diff --git a/.github/SECURITY.md b/.github/SECURITY.md index 1b16d94b575..a4e9730d0a1 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -8,12 +8,12 @@ updates: - The most recent release, and the release prior to that. - Active LTS releases. -At this time, with the latest release of v3.3, the supported +At this time, with the latest release of v3.5, the supported versions are: - v2.7: Current LTS - - v3.2: Prior release - - v3.3: Current release + - v3.4: Prior release + - v3.5: Current release ## Reporting process diff --git a/.github/workflows/blackbox_tests.yml b/.github/workflows/blackbox_tests.yml deleted file mode 100644 index ef84ac12de6..00000000000 --- a/.github/workflows/blackbox_tests.yml +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright (c) 2023 Intel Corporation. -# SPDX-License-Identifier: Apache-2.0 - -name: Twister BlackBox TestSuite - -on: - push: - branches: - - main - paths: - - 'scripts/pylib/twister/**' - - 'scripts/twister' - - 'scripts/tests/twister_blackbox/**' - - '.github/workflows/blackbox_tests.yml' - pull_request: - branches: - - main - paths: - - 'scripts/pylib/twister/**' - - 'scripts/twister' - - 'scripts/tests/twister_blackbox/**' - - '.github/workflows/blackbox_tests.yml' - -jobs: - twister-tests: - name: Twister Black Box Tests - runs-on: ${{ matrix.os }} - strategy: - matrix: - python-version: [3.8, 3.9, '3.10'] - os: [ubuntu-22.04] - container: - image: ghcr.io/zephyrproject-rtos/ci:v0.26.4 - env: - ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.16.1 - - steps: - - name: Apply Container Owner Mismatch Workaround - run: | - # FIXME: The owner UID of the GITHUB_WORKSPACE directory may not - # match the container user UID because of the way GitHub - # Actions runner is implemented. Remove this workaround when - # GitHub comes up with a fundamental fix for this problem. - git config --global --add safe.directory ${GITHUB_WORKSPACE} - - - name: Checkout - uses: actions/checkout@v3 - - - name: Set Up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - - name: Go Into Venv - shell: bash - run: | - python3 -m pip install --user virtualenv - python3 -m venv env - source env/bin/activate - echo "$(which python)" - - - name: Install Packages - run: | - python3 -m pip install -U -r scripts/requirements-base.txt -r scripts/requirements-build-test.txt -r scripts/requirements-run-test.txt - - - name: Run Pytest For Twister Black Box Tests - shell: bash - env: - ZEPHYR_BASE: ./ - ZEPHYR_TOOLCHAIN_VARIANT: zephyr - run: | - echo "Run twister tests" - source zephyr-env.sh - PYTHONPATH="./scripts/tests" pytest ./scripts/tests/twister_blackbox - - - name: Upload Unit Test Results - if: success() || failure() - uses: actions/upload-artifact@v2 - with: - name: Black Box Test Results (Python ${{ matrix.python-version }}) - path: | - twister-out*/twister.log - twister-out*/twister.json - twister-out*/testplan.log - retention-days: 14 - - - name: Clear Workspace - if: success() || failure() - run: | - rm -rf twister-out*/ diff --git a/.github/workflows/bsim-tests.yaml b/.github/workflows/bsim-tests.yaml index 435d61c3085..f52a0439d20 100644 --- a/.github/workflows/bsim-tests.yaml +++ b/.github/workflows/bsim-tests.yaml @@ -30,18 +30,20 @@ jobs: if: github.repository_owner == 'zephyrproject-rtos' runs-on: zephyr-runner-linux-x64-4xlarge container: - image: ghcr.io/zephyrproject-rtos/ci:v0.26.4 + image: ghcr.io/zephyrproject-rtos/ci:v0.26.5 options: '--entrypoint /bin/bash' volumes: - /repo-cache/zephyrproject:/github/cache/zephyrproject env: ZEPHYR_TOOLCHAIN_VARIANT: zephyr - ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.16.1 + ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.16.3 BSIM_OUT_PATH: /opt/bsim/ BSIM_COMPONENTS_PATH: /opt/bsim/components EDTT_PATH: ../tools/edtt - bsim_bluetooth_test_results_file: ./bsim_bluetooth/bsim_results.xml - bsim_networking_test_results_file: ./bsim_net/bsim_results.xml + bsim_bt_52_test_results_file: ./bsim_bt/52_bsim_results.xml + bsim_bt_53_test_results_file: ./bsim_bt/53_bsim_results.xml + bsim_bt_53split_test_results_file: ./bsim_bt/53_bsim_split_results.xml + bsim_net_52_test_results_file: ./bsim_net/52_bsim_results.xml steps: - name: Apply container owner mismatch workaround run: | @@ -133,16 +135,32 @@ jobs: if: steps.check-bluetooth-files.outputs.any_changed == 'true' || steps.check-common-files.outputs.any_changed == 'true' run: | export ZEPHYR_BASE=${PWD} - WORK_DIR=${ZEPHYR_BASE}/bsim_bluetooth nice tests/bsim/bluetooth/compile.sh - RESULTS_FILE=${ZEPHYR_BASE}/${bsim_bluetooth_test_results_file} \ - SEARCH_PATH=tests/bsim/bluetooth/ tests/bsim/run_parallel.sh + export WORK_DIR=${ZEPHYR_BASE}/bsim_bt + # Build and run the BT tests for nrf52_bsim: + nice tests/bsim/bluetooth/compile.sh + RESULTS_FILE=${ZEPHYR_BASE}/${bsim_bt_52_test_results_file} \ + TESTS_FILE=tests/bsim/bluetooth/tests.nrf52bsim.txt tests/bsim/run_parallel.sh + # Build and run the BT controller tests also for the nrf5340bsim_nrf5340_cpunet + BOARD=nrf5340bsim_nrf5340_cpunet \ + nice tests/bsim/bluetooth/compile.nrf5340bsim_nrf5340_cpunet.sh + BOARD=nrf5340bsim_nrf5340_cpunet \ + RESULTS_FILE=${ZEPHYR_BASE}/${bsim_bt_53_test_results_file} \ + TESTS_FILE=tests/bsim/bluetooth/tests.nrf5340bsim_nrf5340_cpunet.txt \ + tests/bsim/run_parallel.sh + # Build and run the nrf5340 split stack tests set + BOARD=nrf5340bsim_nrf5340_cpuapp \ + nice tests/bsim/bluetooth/compile.nrf5340bsim_nrf5340_cpuapp.sh + BOARD=nrf5340bsim_nrf5340_cpuapp \ + RESULTS_FILE=${ZEPHYR_BASE}/${bsim_bt_53split_test_results_file} \ + TESTS_FILE=tests/bsim/bluetooth/tests.nrf5340bsim_nrf5340_cpuapp.txt \ + tests/bsim/run_parallel.sh - name: Run Networking Tests with BSIM if: steps.check-networking-files.outputs.any_changed == 'true' || steps.check-common-files.outputs.any_changed == 'true' run: | export ZEPHYR_BASE=${PWD} WORK_DIR=${ZEPHYR_BASE}/bsim_net nice tests/bsim/net/compile.sh - RESULTS_FILE=${ZEPHYR_BASE}/${bsim_networking_test_results_file} \ + RESULTS_FILE=${ZEPHYR_BASE}/${bsim_net_52_test_results_file} \ SEARCH_PATH=tests/bsim/net/ tests/bsim/run_parallel.sh - name: Upload Test Results @@ -151,8 +169,10 @@ jobs: with: name: bsim-test-results path: | - ./bsim_bluetooth/bsim_results.xml - ./bsim_net/bsim_results.xml + ./bsim_bt/52_bsim_results.xml + ./bsim_bt/53_bsim_results.xml + ./bsim_bt/53_bsim_split_results.xml + ./bsim_net/52_bsim_results.xml ${{ github.event_path }} if-no-files-found: warn diff --git a/.github/workflows/clang.yaml b/.github/workflows/clang.yaml index 402cbae9f95..34b4b8595a9 100644 --- a/.github/workflows/clang.yaml +++ b/.github/workflows/clang.yaml @@ -10,7 +10,7 @@ jobs: clang-build: runs-on: ubuntu-latest container: - image: ghcr.io/zephyrproject-rtos/ci:v0.26.4 + image: ghcr.io/zephyrproject-rtos/ci:v0.26.5 options: '--entrypoint /bin/bash' volumes: - /repo-cache/zephyrproject:/github/cache/zephyrproject @@ -20,7 +20,7 @@ jobs: platform: ["native_posix"] subset: [1, 2, 3, 4, 5] env: - ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.16.1 + ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.16.3 LLVM_TOOLCHAIN_PATH: /usr/lib/llvm-16 COMMIT_RANGE: ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }} BASE_REF: ${{ github.base_ref }} @@ -59,6 +59,7 @@ jobs: git log --pretty=oneline | head -n 10 west init -l . || true west config --global update.narrow true + west config manifest.group-filter -- +ci,+optional # In some cases modules are left in a state where they can't be # updated (i.e. when we cancel a job and the builder is killed), # So first retry to update, if that does not work, remove all modules diff --git a/.github/workflows/codecov.yaml b/.github/workflows/codecov.yaml index 0bf6f3ccfd2..92cf90b8299 100644 --- a/.github/workflows/codecov.yaml +++ b/.github/workflows/codecov.yaml @@ -13,7 +13,7 @@ jobs: if: github.repository == 'zephyrproject-rtos/zephyr' runs-on: zephyr-runner-linux-x64-4xlarge container: - image: ghcr.io/zephyrproject-rtos/ci:v0.26.4 + image: ghcr.io/zephyrproject-rtos/ci:v0.26.5 options: '--entrypoint /bin/bash' volumes: - /repo-cache/zephyrproject:/github/cache/zephyrproject @@ -22,7 +22,7 @@ jobs: matrix: platform: ["native_posix", "qemu_x86", "unit_testing"] env: - ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.16.1 + ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.16.3 steps: - name: Apply container owner mismatch workaround run: | diff --git a/.github/workflows/coding_guidelines.yml b/.github/workflows/coding_guidelines.yml index ea632b7f0b2..c810a22415e 100644 --- a/.github/workflows/coding_guidelines.yml +++ b/.github/workflows/coding_guidelines.yml @@ -17,7 +17,7 @@ jobs: uses: actions/cache@v3 with: path: ~/.cache/pip - key: ${{ runner.os }}-doc-pip + key: ${{ runner.os }}-pip-${{ hashFiles('.github/workflows/coding_guidelines.yml') }} - name: Install python dependencies run: | diff --git a/.github/workflows/compliance.yml b/.github/workflows/compliance.yml index f17780c38e3..d70990ff2c1 100644 --- a/.github/workflows/compliance.yml +++ b/.github/workflows/compliance.yml @@ -21,7 +21,7 @@ jobs: uses: actions/cache@v3 with: path: ~/.cache/pip - key: ${{ runner.os }}-doc-pip + key: ${{ runner.os }}-pip-${{ hashFiles('.github/workflows/compliance.yml') }} - name: Install python dependencies run: | @@ -44,7 +44,8 @@ jobs: # debug git log --pretty=oneline | head -n 10 west init -l . || true - west update 2>&1 1> west.update.log || west update 2>&1 1> west.update2.log + west config manifest.group-filter -- +ci,+optional + west update -o=--depth=1 -n 2>&1 1> west.update.log || west update -o=--depth=1 -n 2>&1 1> west.update2.log - name: Run Compliance Tests continue-on-error: true diff --git a/.github/workflows/devicetree_checks.yml b/.github/workflows/devicetree_checks.yml index 465a8673149..b2d73453b28 100644 --- a/.github/workflows/devicetree_checks.yml +++ b/.github/workflows/devicetree_checks.yml @@ -26,7 +26,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.8, 3.9, '3.10'] + python-version: [3.8, 3.9, '3.10', '3.11', '3.12'] os: [ubuntu-22.04, macos-11, windows-2022] exclude: - os: macos-11 diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index a18507e028d..fa83fe252c7 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -26,7 +26,7 @@ on: env: # NOTE: west docstrings will be extracted from the version listed here - WEST_VERSION: 1.0.0 + WEST_VERSION: 1.2.0 # The latest CMake available directly with apt is 3.18, but we need >=3.20 # so we fetch that through pip. CMAKE_VERSION: 3.20.5 @@ -35,7 +35,8 @@ env: jobs: doc-build-html: name: "Documentation Build (HTML)" - runs-on: ubuntu-22.04 + if: github.repository_owner == 'zephyrproject-rtos' + runs-on: zephyr-runner-linux-x64-4xlarge timeout-minutes: 45 concurrency: group: doc-build-html-${{ github.ref }} @@ -44,11 +45,26 @@ jobs: steps: - name: checkout uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + + - name: Rebase + if: github.event_name == 'pull_request' + continue-on-error: true + env: + BASE_REF: ${{ github.base_ref }} + PR_HEAD: ${{ github.event.pull_request.head.sha }} + run: | + git config --global user.email "actions@zephyrproject.org" + git config --global user.name "Github Actions" + git rebase origin/${BASE_REF} + git log --graph --oneline HEAD...${PR_HEAD} - name: install-pkgs run: | sudo apt-get update - sudo apt-get install -y ninja-build graphviz + sudo apt-get install -y ninja-build graphviz lcov wget --no-verbose "https://github.com/doxygen/doxygen/releases/download/Release_${DOXYGEN_VERSION//./_}/doxygen-${DOXYGEN_VERSION}.linux.bin.tar.gz" tar xf doxygen-${DOXYGEN_VERSION}.linux.bin.tar.gz echo "${PWD}/doxygen-${DOXYGEN_VERSION}/bin" >> $GITHUB_PATH @@ -65,6 +81,7 @@ jobs: pip3 install -r doc/requirements.txt pip3 install west==${WEST_VERSION} pip3 install cmake==${CMAKE_VERSION} + pip3 install coverxygen - name: west setup run: | @@ -84,12 +101,19 @@ jobs: else DOC_TARGET="html" fi - DOC_TAG=${DOC_TAG} SPHINXOPTS_EXTRA="-q -t publish" make -C doc ${DOC_TARGET} + # API documentation coverage + python3 -m coverxygen --xml-dir doc/_build/html/doxygen/xml/ --src-dir include/ --output doc-coverage.info + # deprecated page causing issues + lcov --remove doc-coverage.info \*/deprecated > new.info + genhtml --no-function-coverage --no-branch-coverage new.info -o coverage-report + - name: compress-docs run: | tar cfJ html-output.tar.xz --directory=doc/_build html + tar cfJ api-output.tar.xz --directory=doc/_build html/doxygen/html + tar cfJ api-coverage.tar.xz coverage-report - name: upload-build uses: actions/upload-artifact@v3 @@ -97,15 +121,25 @@ jobs: name: html-output path: html-output.tar.xz + - name: upload-api-coverage + uses: actions/upload-artifact@v3 + with: + name: api-coverage + path: api-coverage.tar.xz + - name: process-pr if: github.event_name == 'pull_request' run: | REPO_NAME="${{ github.event.repository.name }}" PR_NUM="${{ github.event.pull_request.number }}" DOC_URL="https://builds.zephyrproject.io/${REPO_NAME}/pr/${PR_NUM}/docs/" + API_DOC_URL="https://builds.zephyrproject.io/${REPO_NAME}/pr/${PR_NUM}/docs/doxygen/html/" + API_COVERAGE_URL="https://builds.zephyrproject.io/${REPO_NAME}/pr/${PR_NUM}/api-coverage/" echo "${PR_NUM}" > pr_num echo "Documentation will be available shortly at: ${DOC_URL}" >> $GITHUB_STEP_SUMMARY + echo "API Documentation will be available shortly at: ${API_DOC_URL}" >> $GITHUB_STEP_SUMMARY + echo "API Coverage Report will be available shortly at: ${API_COVERAGE_URL}" >> $GITHUB_STEP_SUMMARY - name: upload-pr-number uses: actions/upload-artifact@v3 @@ -116,7 +150,9 @@ jobs: doc-build-pdf: name: "Documentation Build (PDF)" - if: github.event_name != 'pull_request' + if: | + github.event_name != 'pull_request' && + github.repository_owner == 'zephyrproject-rtos' runs-on: zephyr-runner-linux-x64-4xlarge container: texlive/texlive:latest timeout-minutes: 60 @@ -125,6 +161,10 @@ jobs: cancel-in-progress: true steps: + - name: Apply container owner mismatch workaround + run: | + git config --global --add safe.directory ${GITHUB_WORKSPACE} + - name: checkout uses: actions/checkout@v3 diff --git a/.github/workflows/doc-publish-pr.yml b/.github/workflows/doc-publish-pr.yml index 6db566d4e1f..07ee0c10604 100644 --- a/.github/workflows/doc-publish-pr.yml +++ b/.github/workflows/doc-publish-pr.yml @@ -46,6 +46,7 @@ jobs: - name: Uncompress HTML docs run: | tar xf html-output/html-output.tar.xz -C html-output + tar xf api-coverage/api-coverage.tar.xz -C api-coverage - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v2 @@ -61,3 +62,6 @@ jobs: aws s3 sync --quiet html-output/html \ s3://builds.zephyrproject.org/${{ github.event.repository.name }}/pr/${PR_NUM}/docs \ --delete + aws s3 sync --quiet api-coverage/coverage-report/ \ + s3://builds.zephyrproject.org/${{ github.event.repository.name }}/pr/${PR_NUM}/api-coverage \ + --delete diff --git a/.github/workflows/doc-publish.yml b/.github/workflows/doc-publish.yml index 5262d9db67e..c15313bb087 100644 --- a/.github/workflows/doc-publish.yml +++ b/.github/workflows/doc-publish.yml @@ -32,6 +32,7 @@ jobs: - name: Uncompress HTML docs run: | tar xf html-output/html-output.tar.xz -C html-output + tar xf api-coverage/api-coverage.tar.xz -C api-coverage - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v2 @@ -52,4 +53,5 @@ jobs: aws s3 sync --quiet html-output/html s3://docs.zephyrproject.org/${VERSION} --delete aws s3 sync --quiet html-output/html/doxygen/html s3://docs.zephyrproject.org/apidoc/${VERSION} --delete + aws s3 sync --quiet api-coverage/coverage-report/ s3://docs.zephyrproject.org/api-coverage/${VERSION} --delete aws s3 cp --quiet pdf-output/zephyr.pdf s3://docs.zephyrproject.org/${VERSION}/zephyr.pdf diff --git a/.github/workflows/errno.yml b/.github/workflows/errno.yml index 6f76d43a312..537470f0a22 100644 --- a/.github/workflows/errno.yml +++ b/.github/workflows/errno.yml @@ -10,9 +10,9 @@ jobs: check-errno: runs-on: ubuntu-22.04 container: - image: ghcr.io/zephyrproject-rtos/ci:v0.26.4 + image: ghcr.io/zephyrproject-rtos/ci:v0.26.5 env: - ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.16.1 + ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.16.3 steps: - name: Apply container owner mismatch workaround diff --git a/.github/workflows/footprint-tracking.yml b/.github/workflows/footprint-tracking.yml index 5640f7ac7cf..fee3a00449f 100644 --- a/.github/workflows/footprint-tracking.yml +++ b/.github/workflows/footprint-tracking.yml @@ -22,15 +22,15 @@ concurrency: jobs: footprint-tracking: - runs-on: ubuntu-22.04 + runs-on: zephyr-runner-linux-x64-4xlarge if: github.repository_owner == 'zephyrproject-rtos' container: - image: ghcr.io/zephyrproject-rtos/ci:v0.26.4 + image: ghcr.io/zephyrproject-rtos/ci:v0.26.5 options: '--entrypoint /bin/bash' strategy: fail-fast: false env: - ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.16.1 + ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.16.3 ZEPHYR_TOOLCHAIN_VARIANT: zephyr steps: - name: Apply container owner mismatch workaround diff --git a/.github/workflows/footprint.yml b/.github/workflows/footprint.yml index 253823b33b0..685c5644b0c 100644 --- a/.github/workflows/footprint.yml +++ b/.github/workflows/footprint.yml @@ -8,15 +8,15 @@ concurrency: jobs: footprint-delta: - runs-on: ubuntu-22.04 + runs-on: zephyr-runner-linux-x64-4xlarge if: github.repository == 'zephyrproject-rtos/zephyr' container: - image: ghcr.io/zephyrproject-rtos/ci:v0.26.4 + image: ghcr.io/zephyrproject-rtos/ci:v0.26.5 options: '--entrypoint /bin/bash' strategy: fail-fast: false env: - ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.16.1 + ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.16.3 ZEPHYR_TOOLCHAIN_VARIANT: zephyr steps: - name: Apply container owner mismatch workaround diff --git a/.github/workflows/greet_first_time_contributor.yml b/.github/workflows/greet_first_time_contributor.yml index 0c078026692..5984b29fe1f 100644 --- a/.github/workflows/greet_first_time_contributor.yml +++ b/.github/workflows/greet_first_time_contributor.yml @@ -9,9 +9,11 @@ on: jobs: check_for_first_interaction: runs-on: ubuntu-22.04 + if: github.repository == 'zephyrproject-rtos/zephyr' + steps: - uses: actions/checkout@v3 - - uses: zephyrproject-rtos/action-first-interaction@v1.1.1-zephyr-3 + - uses: zephyrproject-rtos/action-first-interaction@v1.1.1-zephyr-4 with: repo-token: ${{ secrets.GITHUB_TOKEN }} @@ -27,12 +29,18 @@ jobs: Hello @${{ github.event.pull_request.user.login }}, and thank you very much for your first pull request to the Zephyr project! - - A project maintainer just triggered our CI pipeline to run it against your PR and - ensure it's compliant and doesn't cause any issues. You might want to take this - opportunity to review the project's [Contributor + Our Continuous Integration pipeline will execute a series of checks on your Pull Request + commit messages and code, and you are expected to address any failures by updating the PR. + Please take a look at [our commit message guidelines](https://docs.zephyrproject.org/latest/contribute/guidelines.html#commit-message-guidelines) + to find out how to format your commit messages, and at [our contribution workflow](https://docs.zephyrproject.org/latest/contribute/guidelines.html#contribution-workflow) + to understand how to update your Pull Request. + If you haven't already, please make sure to review the project's [Contributor Expectations](https://docs.zephyrproject.org/latest/contribute/contributor_expectations.html) - and make any updates to your pull request if necessary. 😊 + and update (by amending and force-pushing the commits) your pull request if necessary. + + If you are stuck or need help please join us on [Discord](https://chat.zephyrproject.org/) + and ask your question there. Additionally, you can [escalate the review](https://docs.zephyrproject.org/latest/contribute/contributor_expectations.html#pr-review-escalation) + when applicable. 😊 pr-merged-message: > Hi @${{ github.event.pull_request.user.login }}! diff --git a/.github/workflows/license_check.yml b/.github/workflows/license_check.yml index dd4e1928a2d..0efedb13489 100644 --- a/.github/workflows/license_check.yml +++ b/.github/workflows/license_check.yml @@ -9,6 +9,8 @@ jobs: steps: - name: Checkout the code uses: actions/checkout@v3 + with: + fetch-depth: 0 - name: Scan the code id: scancode uses: zephyrproject-rtos/action_scancode@v4 diff --git a/.github/workflows/manifest.yml b/.github/workflows/manifest.yml index 1ea0031fb56..fcae7973996 100644 --- a/.github/workflows/manifest.yml +++ b/.github/workflows/manifest.yml @@ -15,12 +15,23 @@ jobs: fetch-depth: 0 persist-credentials: false + - name: west setup + env: + BASE_REF: ${{ github.base_ref }} + working-directory: zephyrproject/zephyr + run: | + pip3 install west + git config --global user.email "you@example.com" + git config --global user.name "Your Name" + west init -l . || true + - name: Manifest - uses: zephyrproject-rtos/action-manifest@a6d0c6e52bbbb7d6df23ceb42842edcb4582b8dc + uses: zephyrproject-rtos/action-manifest@v1.2.2 with: github-token: ${{ secrets.ZB_GITHUB_TOKEN }} manifest-path: 'west.yml' checkout-path: 'zephyrproject/zephyr' + use-tree-checkout: 'true' label-prefix: 'manifest-' verbosity-level: '1' labels: 'manifest' diff --git a/.github/workflows/pylib_tests.yml b/.github/workflows/pylib_tests.yml new file mode 100644 index 00000000000..4368a66d04f --- /dev/null +++ b/.github/workflows/pylib_tests.yml @@ -0,0 +1,54 @@ +# Copyright (c) 2023 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +name: Misc. Pylib Scripts TestSuite + +on: + push: + branches: + - main + - v*-branch + paths: + - 'scripts/pylib/build_helpers/**' + - '.github/workflows/pylib_tests.yml' + pull_request: + branches: + - main + - v*-branch + paths: + - 'scripts/pylib/build_helpers/**' + - '.github/workflows/pylib_tests.yml' + +jobs: + pylib-tests: + name: Misc. Pylib Unit Tests + runs-on: ${{ matrix.os }} + strategy: + matrix: + python-version: [3.8, 3.9, '3.10', '3.11', '3.12'] + os: [ubuntu-22.04] + steps: + - name: checkout + uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: cache-pip-linux + if: startsWith(runner.os, 'Linux') + uses: actions/cache@v3 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ matrix.python-version }} + restore-keys: | + ${{ runner.os }}-pip-${{ matrix.python-version }} + - name: install-packages + run: | + pip3 install -r scripts/requirements-base.txt -r scripts/requirements-build-test.txt + - name: Run pytest for build_helpers + env: + ZEPHYR_BASE: ./ + ZEPHYR_TOOLCHAIN_VARIANT: zephyr + run: | + echo "Run build_helpers tests" + PYTHONPATH=./scripts/tests pytest ./scripts/tests/build_helpers diff --git a/.github/workflows/scripts_tests.yml b/.github/workflows/scripts_tests.yml index 132d8f357c8..7c1a2887ae6 100644 --- a/.github/workflows/scripts_tests.yml +++ b/.github/workflows/scripts_tests.yml @@ -25,7 +25,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.8, 3.9, '3.10'] + python-version: [3.8, 3.9, '3.10', '3.11', '3.12'] os: [ubuntu-20.04] steps: - name: checkout diff --git a/.github/workflows/stale_issue.yml b/.github/workflows/stale_issue.yml index d93aa1f381d..8dc31370125 100644 --- a/.github/workflows/stale_issue.yml +++ b/.github/workflows/stale_issue.yml @@ -24,5 +24,5 @@ jobs: stale-issue-label: 'Stale' stale-pr-label: 'Stale' exempt-pr-labels: 'Blocked,In progress' - exempt-issue-labels: 'In progress,Enhancement,Feature,Feature Request,RFC,Meta,Process' + exempt-issue-labels: 'In progress,Enhancement,Feature,Feature Request,RFC,Meta,Process,Coverity' operations-per-run: 400 diff --git a/.github/workflows/twister.yaml b/.github/workflows/twister.yaml index 4b414a7c9b4..23174d7ab7c 100644 --- a/.github/workflows/twister.yaml +++ b/.github/workflows/twister.yaml @@ -5,10 +5,12 @@ on: branches: - main - v*-branch + - collab-* pull_request_target: branches: - main - v*-branch + - collab-* schedule: # Run at 03:00 UTC on every Sunday - cron: '0 3 * * 0' @@ -22,7 +24,7 @@ jobs: if: github.repository_owner == 'zephyrproject-rtos' runs-on: zephyr-runner-linux-x64-4xlarge container: - image: ghcr.io/zephyrproject-rtos/ci:v0.26.4 + image: ghcr.io/zephyrproject-rtos/ci:v0.26.5 options: '--entrypoint /bin/bash' volumes: - /repo-cache/zephyrproject:/github/cache/zephyrproject @@ -34,7 +36,7 @@ jobs: MATRIX_SIZE: 10 PUSH_MATRIX_SIZE: 15 DAILY_MATRIX_SIZE: 80 - ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.16.1 + ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.16.3 BSIM_OUT_PATH: /opt/bsim/ BSIM_COMPONENTS_PATH: /opt/bsim/components TESTS_PER_BUILDER: 700 @@ -73,7 +75,7 @@ jobs: git rebase origin/${BASE_REF} git log --pretty=oneline | head -n 10 west init -l . || true - west config manifest.group-filter -- +ci + west config manifest.group-filter -- +ci,+optional west config --global update.narrow true west update --path-cache /github/cache/zephyrproject 2>&1 1> west.update.log || west update --path-cache /github/cache/zephyrproject 2>&1 1> west.update.log || ( rm -rf ../modules ../bootloader ../tools && west update --path-cache /github/cache/zephyrproject) west forall -c 'git reset --hard HEAD' @@ -120,7 +122,7 @@ jobs: needs: twister-build-prep if: needs.twister-build-prep.outputs.size != 0 container: - image: ghcr.io/zephyrproject-rtos/ci:v0.26.4 + image: ghcr.io/zephyrproject-rtos/ci:v0.26.5 options: '--entrypoint /bin/bash' volumes: - /repo-cache/zephyrproject:/github/cache/zephyrproject @@ -129,7 +131,7 @@ jobs: matrix: subset: ${{fromJSON(needs.twister-build-prep.outputs.subset)}} env: - ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.16.1 + ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.16.3 BSIM_OUT_PATH: /opt/bsim/ BSIM_COMPONENTS_PATH: /opt/bsim/components TWISTER_COMMON: ' --force-color --inline-logs -v -N -M --retry-failed 3 ' @@ -172,6 +174,7 @@ jobs: echo "$HOME/.local/bin" >> $GITHUB_PATH west init -l . || true + west config manifest.group-filter -- +ci,+optional west config --global update.narrow true west update --path-cache /github/cache/zephyrproject 2>&1 1> west.update.log || west update --path-cache /github/cache/zephyrproject 2>&1 1> west.update.log || ( rm -rf ../modules ../bootloader ../tools && west update --path-cache /github/cache/zephyrproject) west forall -c 'git reset --hard HEAD' diff --git a/.github/workflows/twister_tests.yml b/.github/workflows/twister_tests.yml index 05ea87dfd42..606c49dfdf9 100644 --- a/.github/workflows/twister_tests.yml +++ b/.github/workflows/twister_tests.yml @@ -29,7 +29,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.8, 3.9, '3.10'] + python-version: [3.8, 3.9, '3.10', '3.11', '3.12'] os: [ubuntu-22.04] steps: - name: checkout @@ -48,7 +48,7 @@ jobs: ${{ runner.os }}-pip-${{ matrix.python-version }} - name: install-packages run: | - pip3 install -r scripts/requirements-base.txt -r scripts/requirements-build-test.txt + pip3 install -r scripts/requirements-base.txt -r scripts/requirements-build-test.txt -r scripts/requirements-run-test.txt - name: Run pytest for twisterlib env: ZEPHYR_BASE: ./ diff --git a/.github/workflows/twister_tests_blackbox.yml b/.github/workflows/twister_tests_blackbox.yml new file mode 100644 index 00000000000..a18f79ae455 --- /dev/null +++ b/.github/workflows/twister_tests_blackbox.yml @@ -0,0 +1,91 @@ +# Copyright (c) 2023 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +name: Twister BlackBox TestSuite + +on: + pull_request: + branches: + - main + paths: + - 'scripts/pylib/twister/**' + - 'scripts/twister' + - 'scripts/tests/twister_blackbox/**' + - '.github/workflows/twister_tests_blackbox.yml' + +jobs: + twister-tests: + name: Twister Black Box Tests + runs-on: ${{ matrix.os }} + strategy: + matrix: + python-version: [3.8, 3.9, '3.10', '3.11', '3.12'] + os: [ubuntu-22.04] + container: + image: ghcr.io/zephyrproject-rtos/ci:v0.26.5 + env: + ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.16.3 + + steps: + - name: Apply Container Owner Mismatch Workaround + run: | + # FIXME: The owner UID of the GITHUB_WORKSPACE directory may not + # match the container user UID because of the way GitHub + # Actions runner is implemented. Remove this workaround when + # GitHub comes up with a fundamental fix for this problem. + git config --global --add safe.directory ${GITHUB_WORKSPACE} + + - name: Checkout + uses: actions/checkout@v3 + + - name: Environment Setup + run: | + echo "$HOME/.local/bin" >> $GITHUB_PATH + + west init -l . || true + west config --global update.narrow true + west update --path-cache /github/cache/zephyrproject 2>&1 1> west.update.log || west update --path-cache /github/cache/zephyrproject 2>&1 1> west.update.log || ( rm -rf ../modules ../bootloader ../tools && west update --path-cache /github/cache/zephyrproject) + west forall -c 'git reset --hard HEAD' + + - name: Set Up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: Go Into Venv + shell: bash + run: | + python3 -m pip install --user virtualenv + python3 -m venv env + source env/bin/activate + echo "$(which python)" + + - name: Install Packages + run: | + python3 -m pip install -U -r scripts/requirements-base.txt -r scripts/requirements-build-test.txt -r scripts/requirements-run-test.txt + + - name: Run Pytest For Twister Black Box Tests + shell: bash + env: + ZEPHYR_BASE: ./ + ZEPHYR_TOOLCHAIN_VARIANT: zephyr + run: | + echo "Run twister tests" + source zephyr-env.sh + PYTHONPATH="./scripts/tests" pytest ./scripts/tests/twister_blackbox + + - name: Upload Unit Test Results + if: success() || failure() + uses: actions/upload-artifact@v2 + with: + name: Black Box Test Results (Python ${{ matrix.python-version }}) + path: | + twister-out*/twister.log + twister-out*/twister.json + twister-out*/testplan.log + retention-days: 14 + + - name: Clear Workspace + if: success() || failure() + run: | + rm -rf twister-out*/ diff --git a/.github/workflows/west_cmds.yml b/.github/workflows/west_cmds.yml index 0d30209831d..4a3c1964643 100644 --- a/.github/workflows/west_cmds.yml +++ b/.github/workflows/west_cmds.yml @@ -27,7 +27,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.8, 3.9, '3.10'] + python-version: [3.8, 3.9, '3.10', '3.11', '3.12'] os: [ubuntu-22.04, macos-11, windows-2022] exclude: - os: macos-11 diff --git a/.gitignore b/.gitignore index 16e54c46628..13c99731c52 100644 --- a/.gitignore +++ b/.gitignore @@ -76,7 +76,9 @@ ImageSize.txt Kconfig.txt KconfigBasic.txt KconfigBasicNoModules.txt +KeepSorted.txt MaintainersFormat.txt +ModulesMaintainers.txt Nits.txt Pylint.txt YAMLLint.txt diff --git a/.gitlint b/.gitlint index 8a33f140b2a..de5285527ce 100644 --- a/.gitlint +++ b/.gitlint @@ -1,4 +1,5 @@ # All these sections are optional, edit this file as you like. +# Zephyr-specific defaults are located in scripts/gitlint/zephyr_commit_rules.py [general] ignore=title-trailing-punctuation, T3, title-max-length, T1, body-hard-tab, B3, B1 # verbosity should be a value between 1 and 3, the commandline -v flags take precedence over this @@ -16,13 +17,13 @@ debug = false extra-path=scripts/gitlint [title-max-length-no-revert] -line-length=120 +# line-length=75 [body-min-line-count] -min-line-count=1 +# min-line-count=1 [body-max-line-count] -max-line-count=200 +# max-line-count=200 [title-starts-with-subsystem] regex = ^(?!subsys:)(([^:]+):)(\s([^:]+):)*\s(.+)$ @@ -42,7 +43,7 @@ words=wip [max-line-length-with-exceptions] # B1 = body-max-line-length -line-length=120 +# line-length=75 [body-min-length] min-length=3 diff --git a/CMakeLists.txt b/CMakeLists.txt index e23650f262f..97bcd98d0d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -118,19 +118,7 @@ zephyr_include_directories( include(${ZEPHYR_BASE}/cmake/linker_script/${ARCH}/linker.cmake OPTIONAL) -# Don't add non-existing include directories, it creates noise and -# warnings in some tooling -foreach(optional_include_dir - ${SOC_DIR}/${ARCH}/${SOC_PATH} - ${SOC_DIR}/${ARCH}/${SOC_PATH}/include - ${SOC_DIR}/${ARCH}/${SOC_PATH}/include/${SOC_NAME} - ${SOC_DIR}/${ARCH}/${SOC_FAMILY}/include - ${SOC_DIR}/${ARCH}/${SOC_FAMILY}/common/include - ) - if(EXISTS ${optional_include_dir}) - zephyr_include_directories(${optional_include_dir}) - endif() -endforeach() +zephyr_include_directories(${SOC_DIR}/${ARCH}/${SOC_PATH}) # Don't inherit compiler flags from the environment foreach(var AFLAGS CFLAGS CXXFLAGS CPPFLAGS LDFLAGS) @@ -484,38 +472,12 @@ if(CONFIG_USERSPACE) set(KOBJECT_LINKER_DEP kobject_linker) endif() -get_property(TOPT GLOBAL PROPERTY TOPT) -get_property(COMPILER_TOPT TARGET compiler PROPERTY linker_script) -set_ifndef( TOPT "${COMPILER_TOPT}") -set_ifndef( TOPT -Wl,-T) # Use this if the compiler driver doesn't set a value - -if(CONFIG_HAVE_CUSTOM_LINKER_SCRIPT) - set(LINKER_SCRIPT ${APPLICATION_SOURCE_DIR}/${CONFIG_CUSTOM_LINKER_SCRIPT}) - if(NOT EXISTS ${LINKER_SCRIPT}) - set(LINKER_SCRIPT ${CONFIG_CUSTOM_LINKER_SCRIPT}) - assert_exists(CONFIG_CUSTOM_LINKER_SCRIPT) - endif() -else() - # Try a board specific linker file - set(LINKER_SCRIPT ${BOARD_DIR}/linker.ld) - if(NOT EXISTS ${LINKER_SCRIPT}) - # If not available, try an SoC specific linker file - set(LINKER_SCRIPT ${SOC_DIR}/${ARCH}/${SOC_PATH}/linker.ld) - endif() -endif() - -if(NOT EXISTS ${LINKER_SCRIPT}) - message(FATAL_ERROR "Could not find linker script: '${LINKER_SCRIPT}'. Corrupted configuration?") -endif() - if(DEFINED BUILD_VERSION) set(build_version_argument "-DBUILD_VERSION=${BUILD_VERSION}") elseif(NOT ZEPHYR_GIT_INDEX) - set(ZEPHYR_GIT_INDEX ZEPHYR_GIT_INDEX-NOTFOUND CACHE PATH - "Path to Zephyr git repository index file") if(EXISTS ${ZEPHYR_BASE}/.git/index) - set(ZEPHYR_GIT_DIR ${ZEPHYR_BASE}/.git/index CACHE PATH - "Path to Zephyr git repository index file" FORCE) + set(ZEPHYR_GIT_INDEX ${ZEPHYR_BASE}/.git/index CACHE PATH + "Path to Zephyr git repository index file") elseif(EXISTS ${ZEPHYR_BASE}/.git) # Likely a git-submodule. Let's ask git where the real database is located. find_package(Git QUIET) @@ -535,7 +497,7 @@ elseif(NOT ZEPHYR_GIT_INDEX) message(WARNING "BUILD_VERSION: git rev-parse warned: ${stderr}") endif() set(ZEPHYR_GIT_INDEX ${zephyr_git_dir}/index CACHE PATH - "Path to Zephyr git repository index file" FORCE) + "Path to Zephyr git repository index file") endif() else() message(WARNING "Could not find git installation, " @@ -551,9 +513,33 @@ if(ZEPHYR_GIT_INDEX) set(git_dependency ${ZEPHYR_GIT_INDEX}) endif() +add_custom_command( + OUTPUT ${PROJECT_BINARY_DIR}/include/generated/version.h + COMMAND ${CMAKE_COMMAND} -DZEPHYR_BASE=${ZEPHYR_BASE} + -DOUT_FILE=${PROJECT_BINARY_DIR}/include/generated/version.h + -DVERSION_TYPE=KERNEL + -DVERSION_FILE=${ZEPHYR_BASE}/VERSION + -DKERNEL_VERSION_CUSTOMIZATION="$" + ${build_version_argument} + -P ${ZEPHYR_BASE}/cmake/gen_version_h.cmake + DEPENDS ${ZEPHYR_BASE}/VERSION ${git_dependency} + COMMAND_EXPAND_LISTS +) add_custom_target(version_h DEPENDS ${PROJECT_BINARY_DIR}/include/generated/version.h) if(EXISTS ${APPLICATION_SOURCE_DIR}/VERSION) + add_custom_command( + OUTPUT ${PROJECT_BINARY_DIR}/include/generated/app_version.h + COMMAND ${CMAKE_COMMAND} -DZEPHYR_BASE=${ZEPHYR_BASE} + -DOUT_FILE=${PROJECT_BINARY_DIR}/include/generated/app_version.h + -DVERSION_TYPE=APP + -DVERSION_FILE=${APPLICATION_SOURCE_DIR}/VERSION + -DAPP_VERSION_CUSTOMIZATION="$" + ${build_version_argument} + -P ${ZEPHYR_BASE}/cmake/gen_version_h.cmake + DEPENDS ${APPLICATION_SOURCE_DIR}/VERSION ${git_dependency} + COMMAND_EXPAND_LISTS + ) add_custom_target(app_version_h DEPENDS ${PROJECT_BINARY_DIR}/include/generated/app_version.h) add_dependencies(zephyr_interface app_version_h) endif() @@ -604,32 +590,6 @@ endforeach() set(ZEPHYR_CURRENT_MODULE_DIR) set(ZEPHYR_CURRENT_CMAKE_DIR) -add_custom_command( - OUTPUT ${PROJECT_BINARY_DIR}/include/generated/version.h - COMMAND ${CMAKE_COMMAND} -DZEPHYR_BASE=${ZEPHYR_BASE} - -DOUT_FILE=${PROJECT_BINARY_DIR}/include/generated/version.h - -DVERSION_TYPE=KERNEL - -DVERSION_FILE=${ZEPHYR_BASE}/VERSION - -DKERNEL_VERSION_CUSTOMIZATION="${KERNEL_VERSION_CUSTOMIZATION}" - ${build_version_argument} - -P ${ZEPHYR_BASE}/cmake/gen_version_h.cmake - DEPENDS ${ZEPHYR_BASE}/VERSION ${git_dependency} -) - -if(EXISTS ${APPLICATION_SOURCE_DIR}/VERSION) - add_custom_command( - OUTPUT ${PROJECT_BINARY_DIR}/include/generated/app_version.h - COMMAND ${CMAKE_COMMAND} -DZEPHYR_BASE=${ZEPHYR_BASE} - -DOUT_FILE=${PROJECT_BINARY_DIR}/include/generated/app_version.h - -DVERSION_TYPE=APP - -DVERSION_FILE=${APPLICATION_SOURCE_DIR}/VERSION - -DAPP_VERSION_CUSTOMIZATION="${APP_VERSION_CUSTOMIZATION}" - ${build_version_argument} - -P ${ZEPHYR_BASE}/cmake/gen_version_h.cmake - DEPENDS ${APPLICATION_SOURCE_DIR}/VERSION ${git_dependency} - ) -endif() - get_property(LIBC_LINK_LIBRARIES TARGET zephyr_interface PROPERTY LIBC_LINK_LIBRARIES) zephyr_link_libraries(${LIBC_LINK_LIBRARIES}) @@ -980,6 +940,29 @@ set(CMAKE_C_COMPILE_FEATURES ${compile_features_${CSTD}} PARENT_SCOPE) # @Intent: Configure linker scripts, i.e. generate linker scripts with variables substituted toolchain_ld_configure_files() +get_property(TOPT GLOBAL PROPERTY TOPT) +get_property(COMPILER_TOPT TARGET compiler PROPERTY linker_script) +set_ifndef( TOPT "${COMPILER_TOPT}") +set_ifndef( TOPT -Wl,-T) # Use this if the compiler driver doesn't set a value + +if(CONFIG_HAVE_CUSTOM_LINKER_SCRIPT) + set(LINKER_SCRIPT ${APPLICATION_SOURCE_DIR}/${CONFIG_CUSTOM_LINKER_SCRIPT}) + if(NOT EXISTS ${LINKER_SCRIPT}) + set(LINKER_SCRIPT ${CONFIG_CUSTOM_LINKER_SCRIPT}) + assert_exists(CONFIG_CUSTOM_LINKER_SCRIPT) + endif() +elseif(DEFINED BOARD_LINKER_SCRIPT) + set(LINKER_SCRIPT ${BOARD_LINKER_SCRIPT}) +elseif(DEFINED SOC_LINKER_SCRIPT) + set(LINKER_SCRIPT ${SOC_LINKER_SCRIPT}) +else() + find_package(Deprecated COMPONENTS SEARCHED_LINKER_SCRIPT) +endif() + +if(NOT EXISTS ${LINKER_SCRIPT}) + message(FATAL_ERROR "Could not find linker script: '${LINKER_SCRIPT}'. Corrupted configuration?") +endif() + if(CONFIG_USERSPACE) set(APP_SMEM_ALIGNED_LD "${PROJECT_BINARY_DIR}/include/generated/app_smem_aligned.ld") set(APP_SMEM_UNALIGNED_LD "${PROJECT_BINARY_DIR}/include/generated/app_smem_unaligned.ld") @@ -1129,7 +1112,7 @@ if(CONFIG_USERSPACE) ${PROCESS_GPERF} -i ${KOBJECT_PREBUILT_HASH_OUTPUT_SRC_PRE} -o ${KOBJECT_PREBUILT_HASH_OUTPUT_SRC} - -p "struct z_object" + -p "struct k_object" $<$:--verbose> DEPENDS kobj_prebuilt_hash_output_src_pre ${KOBJECT_PREBUILT_HASH_OUTPUT_SRC_PRE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} @@ -1243,20 +1226,13 @@ if(CONFIG_GEN_ISR_TABLES) # isr_tables.c is generated from ${ZEPHYR_LINK_STAGE_EXECUTABLE} by # gen_isr_tables.py add_custom_command( - OUTPUT isr_tables.c isrList.bin - COMMAND $ - $ - $${OUTPUT_FORMAT} - $binary - $.intList - $$ - $isrList.bin - $ + OUTPUT isr_tables.c COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/build/gen_isr_tables.py --output-source isr_tables.c --kernel $ - --intlist isrList.bin + --intlist-section .intList + --intlist-section intList $<$:--big-endian> $<$:--debug> ${GEN_ISR_TABLE_EXTRA_ARG} @@ -1328,7 +1304,7 @@ if(CONFIG_USERSPACE) ${PROCESS_GPERF} -i ${KOBJECT_HASH_OUTPUT_SRC_PRE} -o ${KOBJECT_HASH_OUTPUT_SRC} - -p "struct z_object" + -p "struct k_object" $<$:--verbose> DEPENDS kobj_hash_output_src_pre ${CMAKE_CURRENT_BINARY_DIR}/${KOBJECT_HASH_OUTPUT_SRC_PRE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} @@ -1786,7 +1762,7 @@ if(CONFIG_BUILD_OUTPUT_EXE) COMMENT "Building native simulator runner, and linking final executable" COMMAND ${MAKE} -f ${ZEPHYR_BASE}/scripts/native_simulator/Makefile all --warn-undefined-variables - -r NSI_CONFIG_FILE=${CMAKE_BINARY_DIR}/zephyr/NSI/nsi_config + -r NSI_CONFIG_FILE=${APPLICATION_BINARY_DIR}/zephyr/NSI/nsi_config # nsi_config is created by the board cmake file DEPENDS ${logical_target_for_zephyr_elf} BYPRODUCTS ${KERNEL_EXE_NAME} @@ -1809,18 +1785,24 @@ if(CONFIG_BUILD_OUTPUT_INFO_HEADER) endif() if(CONFIG_CHECK_INIT_PRIORITIES) - if(CONFIG_CHECK_INIT_PRIORITIES_FAIL_ON_WARNING) - set(fail_on_warning "--fail-on-warning") - endif() list(APPEND post_build_commands COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/build/check_init_priorities.py - --build-dir ${PROJECT_BINARY_DIR}/.. - --edt-pickle ${EDT_PICKLE} - ${fail_on_warning} + --elf-file=${ZEPHYR_BINARY_DIR}/${KERNEL_ELF_NAME} ) endif() +if(NOT CMAKE_C_COMPILER_ID STREQUAL "ARMClang") + add_custom_target( + initlevels + COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/build/check_init_priorities.py + --elf-file=${ZEPHYR_BINARY_DIR}/${KERNEL_ELF_NAME} + --initlevels + DEPENDS ${logical_target_for_zephyr_elf} + USES_TERMINAL + ) +endif() + # Generate and use MCUboot related artifacts as needed. if(CONFIG_BOOTLOADER_MCUBOOT) get_target_property(signing_script zephyr_property_target SIGNING_SCRIPT) diff --git a/CODEOWNERS b/CODEOWNERS index a670048c779..2c8b9db3961 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -11,26 +11,14 @@ # add others as needed. # Do not use wildcard on all source yet -# * @galak @nashif +# +# +++++++++++ NOTE ++++++++++++++++ +# +# Please use the MAINTAINERS file to add yourself in an area or to add a new +# component or code. This file is going to be deprecated and currently only had +# entries that are not covered by the MAINTAINERS file. -/.github/ @nashif @stephanosio /.github/test-spec.yml @nrfconnect/ncs-test-leads -/.github/workflows/ @galak @nashif -/MAINTAINERS.yml @MaureenHelm -/arch/arc/ @abrodkin @ruuddw @evgeniy-paltsev -/arch/arm/ @MaureenHelm @galak @ioannisg -/arch/arm/core/aarch32/cortex_m/cmse/ @ioannisg -/arch/arm/include/aarch32/cortex_m/cmse.h @ioannisg -/arch/arm/core/aarch32/cortex_a_r/ @MaureenHelm @galak @ioannisg @bbolen @stephanosio -/arch/arm64/ @carlocaione -/arch/arm64/core/cortex_r/ @povergoing -/arch/arm64/core/xen/ @lorc @firscity -/arch/common/ @ioannisg @andyross -/arch/mips/ @frantony -/soc/arc/snps_*/ @abrodkin @ruuddw @evgeniy-paltsev -/soc/nios2/ @nashif -/soc/arm/ @MaureenHelm @galak @ioannisg -/soc/arm/arm/mps2/ @fvincenzo /soc/arm/aspeed/ @aspeeddylan /soc/arm/atmel_sam/common/*_sam4l_*.c @nandojve /soc/arm/atmel_sam/sam3x/ @ioannisg @@ -39,18 +27,9 @@ /soc/arm/atmel_sam/sam4s/ @fallrisk /soc/arm/atmel_sam/same70/ @nandojve /soc/arm/atmel_sam/samv71/ @nandojve -/soc/arm/cypress/ @ifyall @npal-cy /soc/arm/bcm*/ @sbranden -/soc/arm/gigadevice/ @nandojve /soc/arm/infineon_cat1/ @ifyall @npal-cy /soc/arm/infineon_xmc/ @parthitce -/soc/arm/nxp*/ @mmahadevan108 @dleach02 -/soc/arm/nxp_s32/ @manuargue -/soc/arm/nordic_nrf/ @anangl -/soc/arm/nuvoton_npcx/ @MulinChao @ChiHuaL -/soc/arm/nuvoton_numicro/ @ssekar15 -/soc/arm/quicklogic_eos_s3/ @fkokosinski @kgugala -/soc/arm/rpi_pico/ @yonsch /soc/arm/silabs_exx32/efm32pg1b/ @rdmeneze /soc/arm/silabs_exx32/efr32mg21/ @l-alfred /soc/arm/st_stm32/ @erwango @@ -64,37 +43,11 @@ /soc/arm/xilinx_zynq7000/ @ibirnbaum /soc/arm/xilinx_zynqmp/ @stephanosio /soc/arm/renesas_rcar/ @aaillet -/soc/arm64/ @carlocaione -/soc/arm64/qemu_cortex_a53/ @carlocaione -/soc/arm64/bcm_vk/ @abhishek-brcm -/soc/arm64/nxp_layerscape/ @JiafeiPan -/soc/arm64/xenvm/ @lorc @firscity -/soc/arm64/nxp_imx/ @MrVan @JiafeiPan -/soc/arm64/arm/ @povergoing -/soc/arm64/arm/fvp_aemv8a/ @carlocaione -/soc/arm64/intel_socfpga/* @siclim -/soc/arm64/renesas_rcar/ @lorc @xakep-amatop -/soc/Kconfig @tejlmand @galak @nashif @nordicjm -/submanifests/* @mbolivar-ampere -/arch/x86/ @jhedberg @nashif -/arch/nios2/ @nashif -/arch/posix/ @aescolar @daor-oti -/arch/riscv/ @kgugala @pgielda -/soc/mips/ @frantony -/soc/posix/ @aescolar @daor-oti -/soc/riscv/ @kgugala @pgielda /soc/riscv/openisa*/ @dleach02 /soc/riscv/riscv-privileged/andes_v5/ @cwshu @kevinwang821020 @jimmyzhe /soc/riscv/riscv-privileged/neorv32/ @henrikbrixandersen /soc/riscv/riscv-privileged/gd32vf103/ @soburi /soc/riscv/riscv-privileged/niosv/ @sweeaun -/soc/x86/ @dcpleung @nashif -/arch/xtensa/ @dcpleung @andyross @nashif -/soc/xtensa/ @dcpleung @andyross @nashif -/arch/sparc/ @julius-barendt -/soc/sparc/ @julius-barendt -/boards/arc/ @abrodkin @ruuddw @evgeniy-paltsev -/boards/arm/ @MaureenHelm @galak /boards/arm/96b_argonkey/ @avisconti /boards/arm/96b_avenger96/ @Mani-Sadhasivam /boards/arm/96b_carbon/ @idlethread @@ -103,7 +56,6 @@ /boards/arm/96b_neonkey/ @Mani-Sadhasivam /boards/arm/96b_stm32_sensor_mez/ @Mani-Sadhasivam /boards/arm/96b_wistrio/ @Mani-Sadhasivam -/boards/arm/arduino_due/ @ioannisg /boards/arm/acn52832/ @sven-hm /boards/arm/arduino_mkrzero/ @soburi /boards/arm/bbc_microbit_v2/ @LingaoM @@ -169,15 +121,7 @@ /boards/arm/rcar_*/ @aaillet /boards/arm/ubx_bmd345eval_nrf52840/ @Navin-Sankar @brec-u-blox /boards/arm/nrf5340_audio_dk_nrf5340 @koffes @alexsven @erikrobstad @rick1082 @gWacey -/boards/common/ @mbolivar-ampere -/boards/deprecated.cmake @tejlmand -/boards/mips/ @frantony -/boards/nios2/ @nashif -/boards/nios2/altera_max10/ @nashif /boards/arm/stm32_min_dev/ @sidcha -/boards/posix/ @aescolar @daor-oti -/boards/posix/nrf52_bsim/ @aescolar @wopu-ot -/boards/riscv/ @kgugala @pgielda /boards/riscv/rv32m1_vega/ @dleach02 /boards/riscv/adp_xc7k_ae350/ @cwshu @kevinwang821020 @jimmyzhe /boards/riscv/longan_nano/ @soburi @@ -185,16 +129,11 @@ /boards/riscv/niosv*/ @sweeaun /boards/riscv/sparkfun_red_v_things_plus/ @soburi /boards/riscv/stamp_c3/ @soburi -/boards/shields/ @erwango /boards/shields/atmel_rf2xx/ @nandojve /boards/shields/esp_8266/ @nandojve /boards/shields/inventek_eswifi/ @nandojve -/boards/x86/ @dcpleung @nashif -/boards/x86/acrn/ @enjiamai -/boards/xtensa/ @nashif @dcpleung /boards/xtensa/odroid_go/ @ydamigos /boards/xtensa/nxp_adsp_imx8/ @iuliana-prodan @dbaluta -/boards/sparc/ @julius-barendt /boards/arm64/qemu_cortex_a53/ @carlocaione /boards/arm64/bcm958402m2_a72/ @abhishek-brcm /boards/arm64/mimx8mm_evk/ @MrVan @JiafeiPan @@ -206,26 +145,15 @@ /boards/arm64/fvp_baser_aemv8r/ @povergoing /boards/arm64/fvp_base_revc_2xaemv8a/ @carlocaione /boards/arm64/intel_socfpga_agilex_socdk/ @siclim @ngboonkhai -/boards/arm64/intel_socfpga_agilex5_socdk/ @chongteikheng +/boards/arm64/intel_socfpga_agilex5_socdk/ @teikheng @gdengi /boards/arm64/rcar_*/ @lorc @xakep-amatop -/boards/Kconfig @tejlmand @galak @nashif @nordicjm # All cmake related files -/cmake/ @tejlmand @nashif -/cmake/*/arcmwdt/ @abrodkin @evgeniy-paltsev @tejlmand -/CMakeLists.txt @tejlmand @nashif -/doc/ @carlescufi /doc/develop/tools/coccinelle.rst @himanshujha199640 @JuliaLawall /doc/services/device_mgmt/smp_protocol.rst @de-nordic @nordicjm /doc/services/device_mgmt/smp_groups/ @de-nordic @nordicjm /doc/services/sensing/ @lixuzha @ghu0510 @qianruh /doc/CMakeLists.txt @carlescufi /doc/_scripts/ @carlescufi -/doc/connectivity/bluetooth/ @alwa-nordic @jhedberg @Vudentz -/doc/build/dts/ @galak @mbolivar-ampere -/doc/build/sysbuild/ @tejlmand @nordicjm -/doc/hardware/peripherals/canbus/ @alexanderwachter @henrikbrixandersen -/doc/security/ @ceolin @d3zd3z -/drivers/debug/ @nashif /drivers/*/*sam4l* @nandojve /drivers/*/*cc13xx_cc26xx* @bwitherspoon /drivers/*/*gd32* @nandojve @@ -239,27 +167,24 @@ /drivers/*/*ifx_cat1* @ifyall @npal-cy /drivers/*/*neorv32* @henrikbrixandersen /drivers/*/*_s32* @manuargue -/drivers/adc/ @anangl /drivers/adc/adc_ads1x1x.c @XenuIsWatching /drivers/adc/adc_stm32.c @cybertale /drivers/adc/adc_rpi_pico.c @soburi /drivers/adc/*ads114s0x* @benediktibk +/drivers/adc/*max11102_17* @benediktibk +/drivers/adc/adc_ad5592.c @bbilas /drivers/audio/*nrfx* @anangl /drivers/auxdisplay/*pt6314* @xingrz /drivers/auxdisplay/* @thedjnK /drivers/bbram/* @yperess @sjg20 @jackrosenthal /drivers/bluetooth/ @alwa-nordic @jhedberg @Vudentz /drivers/bluetooth/hci/hci_esp32.c @sylvioalves -/drivers/cache/ @carlocaione -/drivers/syscon/ @carlocaione @yperess -/drivers/can/ @alexanderwachter @henrikbrixandersen /drivers/can/*mcp2515* @karstenkoenig /drivers/can/*rcar* @aaillet /drivers/clock_control/*agilex* @siclim @gdengi /drivers/clock_control/*nrf* @nordic-krch /drivers/clock_control/*esp32* @extremegtx @sylvioalves /drivers/clock_control/*cpg_mssr* @aaillet -/drivers/counter/ @nordic-krch /drivers/console/ipm_console.c @finikorg /drivers/console/semihost_console.c @luozhongyao /drivers/console/jailhouse_debug_console.c @MrVan @@ -271,7 +196,8 @@ /drivers/crypto/*nrf_ecb* @maciekfabia @anangl /drivers/display/*rm68200* @mmahadevan108 /drivers/display/display_ili9342c.* @extremegtx -/drivers/dac/ @martinjaeger +/drivers/dac/*ad56xx* @benediktibk +/drivers/dac/dac_ad5592.c @bbilas /drivers/dai/ @kv2019i @marcinszkudlinski @abonislawski /drivers/dai/intel/ @kv2019i @marcinszkudlinski @abonislawski /drivers/dai/intel/ssp/ @kv2019i @marcinszkudlinski @abonislawski @@ -286,34 +212,28 @@ /drivers/dma/*intel_adsp* @teburd @abonislawski /drivers/dma/*rpi_pico* @soburi /drivers/dma/*xmc4xxx* @talih0 -/drivers/edac/ @finikorg -/drivers/eeprom/ @henrikbrixandersen /drivers/eeprom/eeprom_stm32.c @KwonTae-young /drivers/entropy/*b91* @andy-liu-telink /drivers/entropy/*bt_hci* @JordanYates /drivers/entropy/*rv32m1* @dleach02 /drivers/entropy/*litex* @mateusz-holenko @kgugala @pgielda -/drivers/espi/ @albertofloyd @franciscomunoz @sjvasanth1 -/drivers/ethernet/ @tbursztyka @jukkar /drivers/ethernet/*dwmac* @npitre /drivers/ethernet/*stm32* @Nukersson @lochej /drivers/ethernet/*w5500* @parthitce /drivers/ethernet/*xlnx_gem* @ibirnbaum /drivers/ethernet/*smsc91x* @sgrrzhf /drivers/ethernet/*adin2111* @GeorgeCGV +/drivers/ethernet/*oa_tc6* @lmajewski +/drivers/ethernet/*lan865x* @lmajewski /drivers/ethernet/phy/ @rlubos @tbursztyka @arvinf @jukkar /drivers/ethernet/phy/*adin2111* @GeorgeCGV -/drivers/mdio/ @rlubos @tbursztyka @arvinf /drivers/mdio/*adin2111* @GeorgeCGV -/drivers/flash/ @nashif @de-nordic /drivers/flash/*stm32_qspi* @lmajewski /drivers/flash/*b91* @andy-liu-telink /drivers/flash/*cadence* @ngboonkhai /drivers/flash/*cc13xx_cc26xx* @pepe2k /drivers/flash/*nrf* @de-nordic /drivers/flash/*esp32* @sylvioalves -/drivers/fpga/ @tgorochowik @kgugala -/drivers/gpio/ @mnkp /drivers/gpio/*b91* @andy-liu-telink /drivers/gpio/*lmp90xxx* @henrikbrixandersen /drivers/gpio/*nct38xx* @MulinChao @ChiHuaL @@ -326,7 +246,8 @@ /drivers/gpio/*ads114s0x* @benediktibk /drivers/gpio/*bd8lb600fs* @benediktibk /drivers/gpio/*pcal64xxa* @benediktibk -/drivers/hwinfo/ @alexanderwachter +/drivers/gpio/gpio_altera_pio.c @shilinte +/drivers/gpio/gpio_ad5592.c @bbilas /drivers/i2c/i2c_common.c @sjg20 /drivers/i2c/i2c_emul.c @sjg20 /drivers/i2c/i2c_ite_enhance.c @GTLin08 @@ -341,7 +262,6 @@ /drivers/i2s/*litex* @mateusz-holenko @kgugala @pgielda /drivers/i2s/i2s_ll_stm32* @avisconti /drivers/i2s/*nrfx* @anangl -/drivers/i3c/ @dcpleung /drivers/i3c/i3c_cdns.c @XenuIsWatching /drivers/ieee802154/ @rlubos @tbursztyka @jukkar @fgrandel /drivers/ieee802154/*b91* @andy-liu-telink @@ -362,31 +282,22 @@ /drivers/ipm/ipm_stm32_hsem.c @cameled /drivers/ipm/ipm_esp32.c @uLipe /drivers/ipm/ipm_ivshmem.c @uLipe -/drivers/kscan/ @VenkatKotakonda @franciscomunoz @sjvasanth1 /drivers/kscan/*xec* @franciscomunoz @sjvasanth1 /drivers/kscan/*ft5336* @MaureenHelm /drivers/kscan/*ht16k33* @henrikbrixandersen -/drivers/led/ @Mani-Sadhasivam /drivers/led_strip/ @mbolivar-ampere -/drivers/lora/ @Mani-Sadhasivam -/drivers/mbox/ @carlocaione -/drivers/misc/ @tejlmand +/drivers/mfd/mfd_ad5592.c @bbilas +/drivers/mfd/mfd_max20335.c @bbilas /drivers/misc/ft8xx/ @hubertmis -/drivers/mm/ @dcpleung /drivers/modem/hl7800.c @rerickson1 /drivers/modem/simcom-sim7080.c @lgehreke /drivers/modem/simcom-sim7080.h @lgehreke /drivers/modem/Kconfig.hl7800 @rerickson1 /drivers/modem/Kconfig.simcom-sim7080 @lgehreke -/drivers/pcie/ @dcpleung @nashif @jhedberg -/drivers/peci/ @albertofloyd @franciscomunoz @sjvasanth1 -/drivers/pinctrl/ @gmarull /drivers/pinctrl/*esp32* @sylvioalves /drivers/pinctrl/*it8xxx2* @ite -/drivers/pm_cpu_ops/ @carlocaione @gdengi /drivers/pm_cpu_ops/psci_shell.c @nbalabak @gdengi /drivers/power_domain/ @ceolin -/drivers/ps2/ @franciscomunoz @sjvasanth1 /drivers/ps2/*xec* @franciscomunoz @sjvasanth1 /drivers/ps2/*npcx* @MulinChao @ChiHuaL /drivers/pwm/*b91* @andy-liu-telink @@ -404,13 +315,12 @@ /drivers/pwm/*rcar* @aaillet /drivers/pwm/*max31790* @benediktibk /drivers/regulator/* @gmarull +/drivers/regulator/regulator_max20335.c @bbilas /drivers/regulator/regulator_pca9420.c @danieldegrasse /drivers/regulator/regulator_rpi_pico.c @soburi /drivers/regulator/regulator_shell.c @danieldegrasse -/drivers/reset/ @andrei-edward-popa /drivers/reset/reset_intel_socfpga.c @nbalabak /drivers/reset/Kconfig.intel_socfpga @nbalabak -/drivers/sensor/ @MaureenHelm /drivers/sensor/ams_iAQcore/ @alexanderwachter /drivers/sensor/ens210/ @alexanderwachter /drivers/sensor/grow_r502a/ @DineshDK03 @@ -441,28 +351,19 @@ /drivers/serial/*numicro* @ssekar15 /drivers/serial/*apbuart* @julius-barendt /drivers/serial/*rcar* @aaillet -/drivers/serial/Kconfig.test @str4t0m -/drivers/serial/serial_test.c @str4t0m /drivers/serial/Kconfig.xen @lorc @firscity /drivers/serial/uart_hvc_xen.c @lorc @firscity /drivers/serial/uart_hvc_xen_consoleio.c @lorc @firscity /drivers/serial/Kconfig.it8xxx2 @GTLin08 /drivers/serial/uart_ite_it8xxx2.c @GTLin08 -/drivers/smbus/ @finikorg -/drivers/sip_svc/ @maheshraotm -/drivers/disk/ @jfischer-no +/drivers/serial/*intel_lw* @shilinte /drivers/disk/sdmmc_sdhc.h @JunYangNXP /drivers/disk/sdmmc_stm32.c @anthonybrandon -/drivers/net/ @rlubos @tbursztyka @jukkar /drivers/ptp_clock/ @tbursztyka @jukkar -/drivers/spi/ @tbursztyka /drivers/spi/*b91* @andy-liu-telink /drivers/spi/spi_rv32m1_lpspi* @karstenkoenig /drivers/spi/*esp32* @sylvioalves /drivers/spi/*pl022* @soburi -/drivers/sdhc/ @danieldegrasse -/drivers/timer/*apic* @dcpleung @nashif -/drivers/timer/apic_tsc.c @andyross /drivers/timer/*arm_arch* @carlocaione /drivers/timer/*cortex_m_systick* @anangl /drivers/timer/*altera_avalon* @nashif @@ -482,10 +383,7 @@ /drivers/timer/*rv32m1_lptmr* @mbolivar /drivers/timer/*nrf_rtc* @anangl /drivers/timer/*hpet* @dcpleung -/drivers/usb/ @jfischer-no /drivers/usb/device/usb_dc_stm32.c @ydamigos @loicpoulain -/drivers/usb_c/ @sambhurst -/drivers/video/ @loicpoulain /drivers/i2c/*b91* @andy-liu-telink /drivers/i2c/i2c_ll_stm32* @ydamigos /drivers/i2c/i2c_rv32m1_lpi2c* @henrikbrixandersen @@ -493,7 +391,6 @@ /drivers/i2c/i2c_dw* @dcpleung /drivers/i2c/*tca954x* @kurddt /drivers/*/*xec* @franciscomunoz @albertofloyd @sjvasanth1 -/drivers/w1/ @str4t0m /drivers/watchdog/*gecko* @oanerer /drivers/watchdog/*sifive* @katsuster /drivers/watchdog/wdt_handlers.c @dcpleung @nashif @@ -504,12 +401,10 @@ /drivers/watchdog/*rpi_pico* @thedjnK /drivers/watchdog/*dw* @softwarecki /drivers/watchdog/*ifx* @sreeramIfx -/drivers/wifi/ @rlubos @tbursztyka @jukkar /drivers/wifi/esp_at/ @mniestroj /drivers/wifi/eswifi/ @loicpoulain @nandojve /drivers/wifi/winc1500/ @kludentwo /drivers/virtualization/ @tbursztyka -/drivers/xen/ @lorc @firscity /dts/arc/ @abrodkin @ruuddw @iriszzw @evgeniy-paltsev /dts/arm/acsip/ @NorthernDean /dts/arm/aspeed/ @aspeeddylan @@ -525,7 +420,6 @@ /dts/arm/gigadevice/ @nandojve /dts/arm/infineon/xmc4* @parthitce @ifyall @npal-cy /dts/arm/infineon/psoc6/ @ifyall @npal-cy -/dts/arm64/ @carlocaione /dts/arm64/armv8-r.dtsi @povergoing /dts/arm64/intel/*intel_socfpga* @siclim /dts/arm64/nxp/ @JiafeiPan @@ -552,7 +446,6 @@ /dts/arm/silabs/efm32pg1b* @rdmeneze /dts/arm/silabs/efr32mg21* @l-alfred /dts/arm/silabs/efr32fg13* @yonsch -/dts/riscv/ @kgugala @pgielda /dts/riscv/ite/ @ite /dts/riscv/microchip/microchip-miv.dtsi @galak /dts/riscv/openisa/rv32m1* @dleach02 @@ -565,17 +458,15 @@ /dts/arm/armv7-r.dtsi @bbolen @stephanosio /dts/arm/xilinx/ @bbolen @stephanosio /dts/arm/renesas/rcar/ @aaillet -/dts/x86/ @jhedberg /dts/xtensa/xtensa.dtsi @ydamigos /dts/xtensa/intel/ @dcpleung /dts/xtensa/espressif/ @sylvioalves /dts/xtensa/nxp/ @iuliana-prodan @dbaluta -/dts/sparc/ @julius-barendt -/dts/bindings/ @galak /dts/bindings/can/ @alexanderwachter @henrikbrixandersen /dts/bindings/i2c/zephyr*i2c-emul*.yaml @sjg20 /dts/bindings/adc/st*stm32-adc.yaml @cybertale /dts/bindings/adc/*ads114s08.yaml @benediktibk +/dts/bindings/adc/*max111* @benediktibk /dts/bindings/modem/*hl7800.yaml @rerickson1 /dts/bindings/serial/ns16550.yaml @dcpleung @nashif /dts/bindings/counter/snps,dw-timers.yaml @pbalsundar @@ -602,7 +493,6 @@ /dts/bindings/ethernet/*gem.yaml @ibirnbaum /dts/bindings/auxdisplay/*pt6314.yaml @xingrz /dts/bindings/auxdisplay/* @thedjnK -/dts/posix/ @aescolar @daor-oti /dts/bindings/sensor/*bme680* @BoschSensortec /dts/bindings/sensor/*ina23* @bbilas /dts/bindings/sensor/st* @avisconti @@ -616,337 +506,4 @@ /dts/bindings/gpio/*bd8lb600fs* @benediktibk /dts/bindings/gpio/*ads114s0x* @benediktibk /dts/bindings/pwm/*max31790* @benediktibk -/dts/common/ @galak -/include/ @nashif @carlescufi @galak @MaureenHelm -/include/zephyr/drivers/*/*litex* @mateusz-holenko @kgugala @pgielda -/include/zephyr/drivers/adc.h @anangl -/include/zephyr/drivers/adc/ads114s0x.h @benediktibk -/include/zephyr/drivers/auxdisplay.h @thedjnK -/include/zephyr/drivers/can.h @alexanderwachter @henrikbrixandersen -/include/zephyr/drivers/can/ @alexanderwachter @henrikbrixandersen -/include/zephyr/drivers/counter.h @nordic-krch -/include/zephyr/drivers/dac.h @martinjaeger -/include/zephyr/drivers/espi.h @albertofloyd @franciscomunoz @sjvasanth1 -/include/zephyr/drivers/bluetooth/ @alwa-nordic @jhedberg @Vudentz -/include/zephyr/drivers/flash.h @nashif @carlescufi @galak @MaureenHelm @de-nordic -/include/zephyr/drivers/i2c_emul.h @sjg20 -/include/zephyr/drivers/i3c.h @dcpleung -/include/zephyr/drivers/i3c/ @dcpleung -/include/zephyr/drivers/led/ht16k33.h @henrikbrixandersen -/include/zephyr/drivers/interrupt_controller/ @dcpleung @nashif -/include/zephyr/drivers/interrupt_controller/gic.h @stephanosio -/include/zephyr/drivers/modem/hl7800.h @rerickson1 -/include/zephyr/drivers/pcie/ @dcpleung -/include/zephyr/drivers/hwinfo.h @alexanderwachter -/include/zephyr/drivers/led.h @Mani-Sadhasivam -/include/zephyr/drivers/led_strip.h @mbolivar-ampere -/include/zephyr/drivers/sensor.h @MaureenHelm -/include/zephyr/drivers/smbus.h @finikorg -/include/zephyr/drivers/spi.h @tbursztyka -/include/zephyr/drivers/sip_svc/ @maheshraotm -/include/zephyr/drivers/lora.h @Mani-Sadhasivam -/include/zephyr/drivers/peci.h @albertofloyd @franciscomunoz @sjvasanth1 -/include/zephyr/drivers/pm_cpu_ops.h @carlocaione -/include/zephyr/drivers/pm_cpu_ops/ @carlocaione -/include/zephyr/drivers/w1.h @str4t0m -/include/zephyr/drivers/pwm/max31790.h @benediktibk -/include/zephyr/app_memory/ @dcpleung -/include/zephyr/arch/arc/ @abrodkin @ruuddw @evgeniy-paltsev -/include/zephyr/arch/arc/arch.h @abrodkin @ruuddw @evgeniy-paltsev -/include/zephyr/arch/arc/v2/irq.h @abrodkin @ruuddw @evgeniy-paltsev -/include/zephyr/arch/arm/aarch32/ @MaureenHelm @galak @ioannisg -/include/zephyr/arch/arm/aarch32/cortex_a_r/ @stephanosio -/include/zephyr/arch/arm64/ @carlocaione -/include/zephyr/arch/arm64/cortex_r/ @povergoing -/include/zephyr/arch/arm/aarch32/irq.h @carlocaione -/include/zephyr/arch/mips/ @frantony -/include/zephyr/arch/nios2/ @nashif -/include/zephyr/arch/nios2/arch.h @nashif -/include/zephyr/arch/posix/ @aescolar @daor-oti -/include/zephyr/arch/riscv/ @kgugala @pgielda -/include/zephyr/arch/x86/ @jhedberg @dcpleung -/include/zephyr/arch/common/ @andyross @nashif -/include/zephyr/arch/xtensa/ @andyross @dcpleung -/include/zephyr/arch/sparc/ @julius-barendt -/include/zephyr/sys/atomic.h @andyross -/include/zephyr/bluetooth/ @alwa-nordic @jhedberg @Vudentz @sjanc -/include/zephyr/bluetooth/audio/ @jhedberg @Vudentz @Thalley -/include/zephyr/cache.h @carlocaione @andyross -/include/zephyr/canbus/ @alexanderwachter @henrikbrixandersen -/include/zephyr/tracing/ @nashif -/include/zephyr/debug/ @nashif -/include/zephyr/debug/coredump.h @dcpleung -/include/zephyr/debug/gdbstub.h @ceolin -/include/zephyr/device.h @tbursztyka @nashif -/include/zephyr/devicetree.h @galak -/include/zephyr/devicetree/can.h @henrikbrixandersen -/include/zephyr/dt-bindings/clock/kinetis_mcg.h @henrikbrixandersen -/include/zephyr/dt-bindings/clock/kinetis_scg.h @henrikbrixandersen -/include/zephyr/dt-bindings/ethernet/xlnx_gem.h @ibirnbaum -/include/zephyr/dt-bindings/pcie/ @dcpleung -/include/zephyr/dt-bindings/pinctrl/esp* @sylvioalves -/include/zephyr/dt-bindings/pwm/*it8xxx2* @RuibinChang -/include/zephyr/dt-bindings/usb/usb.h @galak -/include/zephyr/dt-bindings/adc/ads114s0x_adc.h @benediktibk -/include/zephyr/drivers/emul.h @sjg20 -/include/zephyr/fs/ @nashif @de-nordic -/include/zephyr/init.h @nashif @andyross -/include/zephyr/irq.h @dcpleung @nashif @andyross -/include/zephyr/irq_offload.h @dcpleung @nashif @andyross -/include/zephyr/kernel.h @dcpleung @nashif @andyross -/include/zephyr/kernel_version.h @dcpleung @nashif @andyross -/include/zephyr/linker/app_smem*.ld @dcpleung @nashif -/include/zephyr/linker/ @dcpleung @nashif @andyross -/include/zephyr/logging/ @nordic-krch -/include/zephyr/lorawan/lorawan.h @Mani-Sadhasivam -/include/zephyr/mgmt/osdp.h @sidcha -/include/zephyr/mgmt/mcumgr/ @nordicjm -/include/zephyr/net/ @rlubos @tbursztyka @jukkar -/include/zephyr/net/buf.h @jhedberg @tbursztyka @rlubos @jukkar -/include/zephyr/net/coap*.h @rlubos -/include/zephyr/net/conn_mgr*.h @rlubos @glarsennordic @jukkar -/include/zephyr/net/gptp.h @rlubos @jukkar @fgrandel -/include/zephyr/net/ieee802154*.h @rlubos @tbursztyka @jukkar @fgrandel -/include/zephyr/net/lwm2m*.h @rlubos -/include/zephyr/net/mqtt.h @rlubos -/include/zephyr/net/mqtt_sn.h @rlubos @BeckmaR -/include/zephyr/net/net_pkt_filter.h @npitre -/include/zephyr/posix/ @cfreidt -/include/zephyr/pm/pm.h @nashif @ceolin -/include/zephyr/drivers/ptp_clock.h @tbursztyka @jukkar -/include/zephyr/rtio/ @teburd -/include/zephyr/sensing/ @lixuzha @ghu0510 @qianruh -/include/zephyr/shared_irq.h @dcpleung @nashif @andyross -/include/zephyr/shell/ @jakub-uC @nordic-krch -/include/zephyr/shell/shell_mqtt.h @ycsin -/include/zephyr/sw_isr_table.h @dcpleung @nashif @andyross -/include/zephyr/sd/ @danieldegrasse -/include/zephyr/sip_svc/ @maheshraotm -/include/zephyr/sys_clock.h @dcpleung @nashif @andyross -/include/zephyr/sys/sys_io.h @dcpleung @nashif @andyross -/include/zephyr/sys/kobject.h @dcpleung @nashif -/include/zephyr/toolchain.h @dcpleung @andyross @nashif -/include/zephyr/toolchain/ @dcpleung @nashif @andyross -/include/zephyr/zephyr.h @dcpleung @nashif @andyross -/kernel/ @dcpleung @nashif @andyross -/lib/cpp/ @stephanosio -/lib/smf/ @sambhurst -/lib/util/ @carlescufi @jakub-uC -/lib/util/fnmatch/ @carlescufi @jakub-uC -/lib/open-amp/ @arnopo -/lib/os/ @dcpleung @nashif @andyross -/lib/os/cbprintf_packaged.c @npitre -/lib/posix/ @cfriedt -/lib/posix/getopt/ @jakub-uC -/subsys/portability/ @nashif -/subsys/sensing/ @lixuzha @ghu0510 @qianruh -/lib/libc/ @nashif -/lib/libc/arcmwdt/ @abrodkin @ruuddw @evgeniy-paltsev -/misc/ @tejlmand -/modules/ @nashif -/modules/canopennode/ @henrikbrixandersen -/modules/mbedtls/ @ceolin @d3zd3z -/modules/hal_gigadevice/ @nandojve -/modules/hal_nordic/nrf_802154/ @jciupis -/modules/trusted-firmware-m/ @microbuilder -/kernel/device.c @andyross @nashif -/kernel/idle.c @andyross @nashif -/samples/ @nashif -/samples/application_development/sysbuild/ @tejlmand @nordicjm -/samples/basic/minimal/ @carlescufi -/samples/basic/servo_motor/boards/*microbit* @jhe -/samples/bluetooth/ @jhedberg @Vudentz @alwa-nordic @sjanc -/samples/compression/ @Navin-Sankar -/samples/drivers/can/ @alexanderwachter @henrikbrixandersen -/samples/drivers/clock_control_litex/ @mateusz-holenko @kgugala @pgielda -/samples/drivers/eeprom/ @henrikbrixandersen -/samples/drivers/ht16k33/ @henrikbrixandersen -/samples/drivers/lora/ @Mani-Sadhasivam -/samples/drivers/smbus/ @finikorg -/samples/subsys/lorawan/ @Mani-Sadhasivam -/samples/modules/canopennode/ @henrikbrixandersen -/samples/net/ @rlubos @tbursztyka @jukkar -/samples/net/cloud/tagoio_http_post/ @nandojve -/samples/net/dns_resolve/ @rlubos @tbursztyka @jukkar -/samples/net/gptp/ @rlubos @jukkar @fgrandel -/samples/net/lwm2m_client/ @rlubos -/samples/net/mqtt_publisher/ @rlubos -/samples/net/mqtt_sn_publisher/ @rlubos @BeckmaR -/samples/net/sockets/coap_*/ @rlubos -/samples/net/sockets/ @rlubos @tbursztyka @jukkar -/samples/sensor/ @MaureenHelm -/samples/shields/ @avisconti -/samples/subsys/ipc/ipc_service/icmsg @emob-nordic -/samples/subsys/logging/ @nordic-krch @jakub-uC -/samples/subsys/logging/syst/ @dcpleung -/samples/subsys/shell/ @jakub-uC @nordic-krch @gdengi -/samples/subsys/sip_svc/ @maheshraotm -/samples/subsys/mgmt/mcumgr/ @de-nordic @nordicjm -/samples/subsys/mgmt/updatehub/ @nandojve @otavio -/samples/subsys/mgmt/osdp/ @sidcha -/samples/subsys/usb/ @jfischer-no -/samples/subsys/usb_c/ @sambhurst -/samples/subsys/pm/ @nashif @ceolin -/samples/subsys/sensing/ @lixuzha @ghu0510 @qianruh -/samples/tfm_integration/ @microbuilder -/samples/userspace/ @dcpleung @nashif -/scripts/release/bug_bash.py @cfriedt -/scripts/coccicheck @himanshujha199640 @JuliaLawall -/scripts/coccinelle/ @himanshujha199640 @JuliaLawall -/scripts/coredump/ @dcpleung -/scripts/footprint/ @nashif -/scripts/kconfig/ @ulfalizer -/scripts/logging/dictionary/ @dcpleung -/scripts/native_simulator/ @aescolar -/scripts/pylib/twister/expr_parser.py @nashif -/scripts/schemas/twister/ @nashif -/scripts/build/gen_app_partitions.py @dcpleung @nashif -scripts/build/gen_image_info.py @tejlmand -/scripts/get_maintainer.py @nashif -/scripts/dts/ @mbolivar-ampere @galak -/scripts/release/ @nashif -/scripts/ci/ @nashif -/scripts/ci/check_compliance.py @nashif @carlescufi -/arch/x86/gen_gdt.py @dcpleung @nashif -/arch/x86/gen_idt.py @dcpleung @nashif -/scripts/build/gen_kobject_list.py @dcpleung @nashif -/scripts/build/gen_kobject_placeholders.py @dcpleung -/scripts/build/gen_syscalls.py @dcpleung @nashif -/scripts/list_boards.py @mbolivar-ampere -/scripts/build/process_gperf.py @dcpleung @nashif -/scripts/build/gen_relocate_app.py @dcpleung -/scripts/generate_usb_vif/ @madhurimaparuchuri -/scripts/requirements*.txt @mbolivar-ampere @galak @nashif -/scripts/tests/build/test_subfolder_list.py @rmstoi -/scripts/tracing/ @nashif -/scripts/pylib/twister/ @nashif -/scripts/twister @nashif -/scripts/series-push-hook.sh @erwango -/scripts/utils/pinctrl_nrf_migrate.py @gmarull -/scripts/utils/migrate_mcumgr_kconfigs.py @de-nordic -/scripts/west_commands/ @mbolivar-ampere -/scripts/west_commands/blobs.py @carlescufi -/scripts/west_commands/fetchers/ @carlescufi -/scripts/west_commands/runners/gd32isp.py @mbolivar-ampere @nandojve -/scripts/west_commands/tests/test_gd32isp.py @mbolivar-ampere @nandojve -/scripts/west-commands.yml @mbolivar-ampere -/scripts/zephyr_module.py @tejlmand -/scripts/build/uf2conv.py @petejohanson -/scripts/build/user_wordsize.py @cfriedt -/scripts/valgrind.supp @aescolar @daor-oti -/share/sysbuild/ @tejlmand @nordicjm -/share/zephyr-package/ @tejlmand -/share/zephyrunittest-package/ @tejlmand -/subsys/bluetooth/ @alwa-nordic @jhedberg @Vudentz -/subsys/bluetooth/audio/ @jhedberg @Vudentz @Thalley @sjanc -/subsys/bluetooth/controller/ @carlescufi @cvinayak @thoh-ot @kruithofa -/subsys/bluetooth/host/ @alwa-nordic @jhedberg @Vudentz @sjanc -/subsys/bluetooth/mesh/ @jhedberg @PavelVPV @Vudentz @LingaoM -/subsys/canbus/ @alexanderwachter @henrikbrixandersen -/subsys/debug/ @nashif -/subsys/debug/coredump/ @dcpleung -/subsys/debug/gdbstub/ @ceolin -/subsys/debug/gdbstub.c @ceolin -/subsys/dfu/ @de-nordic @nordicjm -/subsys/disk/ @jfischer-no -/subsys/dsp/ @yperess -/subsys/tracing/ @nashif -/subsys/debug/asan_hacks.c @aescolar @daor-oti -/subsys/demand_paging/ @dcpleung @nashif -/subsys/emul/ @sjg20 -/subsys/fb/ @jfischer-no -/subsys/fs/ @nashif -/subsys/fs/nvs/ @Laczen -/subsys/ipc/ @carlocaione -/subsys/ipc/ipc_service/*/*icmsg* @emob-nordic -/subsys/logging/ @nordic-krch -/subsys/logging/backends/log_backend_net.c @nordic-krch @rlubos @jukkar -/subsys/lorawan/ @Mani-Sadhasivam -/subsys/mgmt/ec_host_cmd/ @jettr -/subsys/mgmt/mcumgr/ @carlescufi @de-nordic @nordicjm -/subsys/mgmt/hawkbit/ @Navin-Sankar -/subsys/mgmt/updatehub/ @nandojve @otavio -/subsys/mgmt/osdp/ @sidcha -/subsys/modbus/ @jfischer-no -/subsys/net/buf.c @jhedberg @tbursztyka @rlubos @jukkar -/subsys/net/conn_mgr/ @rlubos @glarsennordic @jukkar -/subsys/net/ip/ @rlubos @tbursztyka @jukkar -/subsys/net/lib/ @rlubos @tbursztyka @jukkar -/subsys/net/lib/dns/ @rlubos @tbursztyka @cfriedt @jukkar -/subsys/net/lib/lwm2m/ @rlubos -/subsys/net/lib/config/ @rlubos @tbursztyka @jukkar -/subsys/net/lib/mqtt/ @rlubos -/subsys/net/lib/mqtt_sn/ @rlubos @BeckmaR -/subsys/net/lib/coap/ @rlubos -/subsys/net/lib/sockets/socketpair.c @cfriedt -/subsys/net/lib/sockets/ @rlubos @tbursztyka @jukkar -/subsys/net/lib/tls_credentials/ @rlubos -/subsys/net/l2/ @rlubos @tbursztyka @jukkar -/subsys/net/l2/ethernet/gptp/ @rlubos @jukkar @fgrandel -/subsys/net/l2/ieee802154/ @rlubos @tbursztyka @jukkar @fgrandel -/subsys/net/l2/canbus/ @alexanderwachter -/subsys/net/pkt_filter/ @npitre -/subsys/net/*/openthread/ @rlubos -/subsys/pm/ @nashif @ceolin -/subsys/random/ @dleach02 -/subsys/shell/ @jakub-uC @nordic-krch -/subsys/shell/backends/shell_mqtt.c @ycsin -/subsys/sd/ @danieldegrasse -/subsys/sip_svc/ @maheshraotm -/subsys/task_wdt/ @martinjaeger -/subsys/testsuite/ @nashif -/subsys/testsuite/ztest/*/ztress* @nordic-krch -/subsys/timing/ @nashif @dcpleung -/subsys/usb/ @jfischer-no -/subsys/usb/usb_c/ @sambhurst -/tests/ @nashif -/tests/arch/arm/ @ioannisg @stephanosio -/tests/benchmarks/cmsis_dsp/ @stephanosio -/tests/boards/native_posix/ @aescolar @daor-oti -/tests/bluetooth/ @alwa-nordic @jhedberg @Vudentz @sjanc -/tests/bluetooth/controller/ @cvinayak @thoh-ot @kruithofa @erbr-ot @sjanc @ppryga -/tests/bsim/bluetooth/ @alwa-nordic @jhedberg @Vudentz @wopu-ot -/tests/bsim/bluetooth/audio/ @jhedberg @Vudentz @wopu-ot @Thalley -/tests/bsim/bluetooth/mesh/ @jhedberg @Vudentz @wopu-ot @PavelVPV -/tests/bluetooth/mesh_shell/ @jhedberg @Vudentz @sjanc @PavelVPV -/tests/bluetooth/tester/ @alwa-nordic @jhedberg @Vudentz @sjanc -/tests/posix/ @cfriedt -/tests/crypto/ @ceolin -/tests/crypto/mbedtls/ @nashif @ceolin @d3zd3z -/tests/drivers/can/ @alexanderwachter @henrikbrixandersen -/tests/drivers/counter/ @nordic-krch -/tests/drivers/eeprom/ @henrikbrixandersen @sjg20 -/tests/drivers/flash_simulator/ @de-nordic -/tests/drivers/gpio/ @mnkp -/tests/drivers/hwinfo/ @alexanderwachter -/tests/drivers/smbus/ @finikorg -/tests/drivers/spi/ @tbursztyka -/tests/drivers/uart/uart_async_api/ @anangl -/tests/drivers/w1/ @str4t0m -/tests/kernel/ @dcpleung @andyross @nashif -/tests/lib/ @nashif -/tests/lib/cmsis_dsp/ @stephanosio -/tests/net/ @rlubos @tbursztyka @jukkar -/tests/net/buf/ @jhedberg @tbursztyka @jukkar -/tests/net/conn_mgr_monitor/ @rlubos @glarsennordic @jukkar -/tests/net/conn_mgr_conn/ @rlubos @glarsennordic @jukkar -/tests/net/ieee802154/l2/ @rlubos @tbursztyka @jukkar @fgrandel -/tests/net/lib/ @rlubos @tbursztyka @jukkar -/tests/net/lib/http_header_fields/ @rlubos @tbursztyka @jukkar -/tests/net/lib/mqtt_packet/ @rlubos -/tests/net/lib/mqtt_sn_packet/ @rlubos @BeckmaR -/tests/net/lib/mqtt_sn_client/ @rlubos @BeckmaR -/tests/net/lib/coap/ @rlubos -/tests/net/npf/ @npitre -/tests/net/socket/socketpair/ @cfriedt -/tests/net/socket/ @rlubos @tbursztyka @jukkar -/tests/subsys/debug/coredump/ @dcpleung -/tests/subsys/fs/ @nashif @de-nordic -/tests/subsys/mgmt/mcumgr/ @de-nordic @nordicjm -/tests/subsys/sd/ @danieldegrasse -/tests/subsys/rtio/ @teburd -/tests/subsys/shell/ @jakub-uC @nordic-krch -# Get all docs reviewed -*.rst @nashif -/doc/kernel/ @andyross @nashif -*posix*.rst @aescolar @daor-oti +/dts/bindings/dac/*ad56* @benediktibk diff --git a/Kconfig.zephyr b/Kconfig.zephyr index d01cc55eea7..c484898206b 100644 --- a/Kconfig.zephyr +++ b/Kconfig.zephyr @@ -306,6 +306,24 @@ config LINKER_USE_RELAX endmenu # "Linker Sections" +config LINKER_DEVNULL_SUPPORT + bool + default y if CPU_CORTEX_M || (RISCV && !64BIT) + +config LINKER_DEVNULL_MEMORY + bool "Devnull region" + depends on LINKER_DEVNULL_SUPPORT + help + Devnull region is created. It is stripped from final binary but remains + in byproduct elf file. + +config LINKER_DEVNULL_MEMORY_SIZE + int "Devnull region size" + depends on LINKER_DEVNULL_MEMORY + default 262144 + help + Size can be adjusted so it fits all data placed in that region. + endmenu menu "Compiler Options" @@ -316,10 +334,22 @@ config CODING_GUIDELINE_CHECK Use available compiler flags to check coding guideline rules during the build. -config NATIVE_BUILD +config NATIVE_LIBC bool select FULL_LIBC_SUPPORTED - select FULL_LIBCPP_SUPPORTED if CPP + help + Zephyr will use the host system C library. + +config NATIVE_LIBCPP + bool + select FULL_LIBCPP_SUPPORTED + help + Zephyr will use the host system C++ library + +config NATIVE_BUILD + bool + select NATIVE_LIBC if EXTERNAL_LIBC + select NATIVE_LIBCPP if EXTERNAL_LIBCPP help Zephyr will be built targeting the host system for debug and development purposes. @@ -747,22 +777,15 @@ config BUILD_OUTPUT_STRIP_PATHS config CHECK_INIT_PRIORITIES bool "Build time initialization priorities check" default y + depends on !NATIVE_LIBRARY + depends on "$(ZEPHYR_TOOLCHAIN_VARIANT)" != "armclang" help Check the build for initialization priority issues by comparing the initialization priority in the build with the device dependency derived from the devicetree definition. Fails the build on priority errors (dependent devices, inverted - priority), see CHECK_INIT_PRIORITIES_FAIL_ON_WARNING to fail on - warnings (dependent devices, same priority) as well. - -config CHECK_INIT_PRIORITIES_FAIL_ON_WARNING - bool "Fail the build on priority check warnings" - depends on CHECK_INIT_PRIORITIES - help - Fail the build if the dependency check script identifies any pair of - devices depending on each other but initialized with the same - priority. + priority). config EMIT_ALL_SYSCALLS bool "Emit all possible syscalls in the tree" @@ -898,14 +921,3 @@ config BOOTLOADER_BOSSA_ADAFRUIT_UF2 endchoice endmenu - -menu "Compatibility" - -config COMPAT_INCLUDES - bool "Suppress warnings when using header shims" - default y - help - Suppress any warnings from the pre-processor when including - deprecated header files. - -endmenu diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 08ad5c8d61b..a36838cd65d 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -111,6 +111,21 @@ # Areas are sorted by name +ACPI: + status: maintained + maintainers: + - jhedberg + - najumon1980 + collaborators: + - finikorg + - tbursztyka + files: + - lib/acpi/ + - include/zephyr/acpi/ + - tests/lib/acpi/ + labels: + - "area: ACPI" + ARC arch: status: maintained maintainers: @@ -124,6 +139,7 @@ ARC arch: - include/zephyr/arch/arc/ - tests/arch/arc/ - dts/arc/synopsys/ + - doc/hardware/arch/arc-support-status.rst labels: - "area: ARC" @@ -138,10 +154,10 @@ ARM arch: - stephanosio - bbolen - povergoing + - ithinuel files: - arch/arm/ - arch/arm/core/offsets/ - - include/zephyr/arch/arm/aarch32/ - include/zephyr/arch/arm/ - tests/arch/arm/ - doc/hardware/arch/arm_cortex_m.rst @@ -168,6 +184,26 @@ ARM64 arch: labels: - "area: ARM64" +ARM Platforms: + status: odd fixes + files: + - boards/arm/mps*/ + - soc/arm/arm/ + - boards/arm/v2m_*/ + labels: + - "platform: ARM" + +ARM SiP SVC: + status: odd fixes + files: + - subsys/sip_svc/ + - tests/subsys/sip_svc/ + - include/zephyr/sip_svc/ + - include/zephyr/drivers/sip_svc/ + - drivers/sip_svc/ + labels: + - "area: ARM SiP SVC" + MIPS arch: status: odd fixes files: @@ -194,6 +230,31 @@ Ambiq Platforms: labels: - "platform: Ambiq" +Benchmarks: + status: maintained + maintainers: + - peter-mitsis + collaborators: + - nashif + - dcpleung + files: + - tests/benchmarks/ + labels: + - "area: Benchmarks" + +Binary Descriptors: + status: maintained + maintainers: + - yonsch + files: + - subsys/bindesc/ + - include/zephyr/bindesc.h + - samples/subsys/bindesc/ + - scripts/west_commands/bindesc.py + - tests/subsys/bindesc/ + labels: + - "area: Binary Descriptors" + Bluetooth: status: maintained maintainers: @@ -228,6 +289,7 @@ Bluetooth: - tests/bluetooth/host*/ - tests/bluetooth/mesh_*/ - tests/bluetooth/mesh/ + - tests/bluetooth/audio/ - tests/bsim/bluetooth/mesh/ - tests/bluetooth/shell/audio* labels: @@ -315,6 +377,7 @@ Bluetooth Audio: files: - subsys/bluetooth/audio/ - include/zephyr/bluetooth/audio/ + - tests/bluetooth/audio/ - tests/bsim/bluetooth/audio/ - tests/bluetooth/shell/audio* labels: @@ -371,6 +434,20 @@ Board/SoC configuration: labels: - "area: C++" +Cache: + status: maintained + maintainers: + - carlocaione + collaborators: + - nashif + files: + - include/zephyr/drivers/cache.h + - include/zephyr/cache.h + - doc/hardware/cache/index.rst + - drivers/cache/ + labels: + - "area: Cache" + C library: status: maintained maintainers: @@ -391,7 +468,7 @@ CMSIS API layer: collaborators: - nashif files: - - subsys/portability/cmsis_rtos_v*/ + - subsys/portability/ - include/zephyr/portability/cmsis* - samples/subsys/portability/cmsis_rtos_v*/ - tests/subsys/portability/cmsis_rtos_v*/ @@ -421,8 +498,9 @@ CMSIS-DSP integration: - stephanosio collaborators: - galak + - XenuIsWatching files: - - modules/cmsis/Kconfig.cmsis_dsp + - modules/cmsis-dsp/ - tests/benchmarks/cmsis_dsp/ - tests/lib/cmsis_dsp/ labels: @@ -434,8 +512,9 @@ CMSIS-NN integration: - JordanYates collaborators: - stephanosio + - XenuIsWatching files: - - modules/cmsis/Kconfig.cmsis_nn + - modules/cmsis-nn/ - tests/lib/cmsis_nn/ labels: - "area: CMSIS-NN" @@ -475,8 +554,11 @@ Common Architecture Interface: - dcpleung - nashif files: + - include/zephyr/arch/ - arch/common/ - include/zephyr/arch/common/ + - tests/arch/common/ + - doc/hardware/porting/arch.rst labels: - "area: Architectures" @@ -505,6 +587,17 @@ Debug: labels: - "area: Debugging" +Demand Paging: + status: maintained + maintainers: + - dcpleung + collaborators: + - ceolin + - peter-mitsis + - nashif + files: + - subsys/demand_paging/ + Device Driver Model: status: maintained maintainers: @@ -556,6 +649,7 @@ Devicetree Bindings: - galak files: - dts/bindings/ + - include/zephyr/dt-bindings/ labels: - "area: Devicetree Binding" @@ -574,6 +668,7 @@ Disk: - subsys/sd/ - tests/subsys/sd/ - tests/drivers/disk/ + - include/zephyr/sd/ labels: - "area: Disk Access" @@ -589,6 +684,7 @@ Display drivers: - include/zephyr/drivers/display.h - subsys/fb/ - samples/subsys/display/ + - doc/hardware/peripherals/display/ labels: - "area: Display" @@ -615,6 +711,7 @@ Documentation: - doc/templates/sample.tmpl - doc/templates/board.tmpl files-exclude: + - doc/releases/migration-guide-* - doc/releases/release-notes-* labels: - "area: Documentation" @@ -639,9 +736,12 @@ Documentation Infrastructure: Release Notes: status: maintained maintainers: - - jhedberg - - fabiobaltieri + - MaureenHelm + - henrikbrixandersen + collaborators: + - kartben files: + - doc/releases/migration-guide-* - doc/releases/release-notes-* labels: - "Release Notes" @@ -672,6 +772,7 @@ Release Notes: files: - drivers/audio/ - include/zephyr/audio/ + - doc/hardware/peripherals/audio/ labels: - "area: Audio" @@ -683,6 +784,7 @@ Release Notes: - tests/drivers/bbram/ - drivers/bbram/ - include/zephyr/drivers/bbram.h + - doc/hardware/peripherals/bbram.rst labels: - "area: Battery Backed RAM (bbram)" @@ -696,6 +798,7 @@ Release Notes: - include/zephyr/drivers/auxdisplay.h - drivers/auxdisplay/* - dts/bindings/auxdisplay/* + - doc/hardware/peripherals/auxdisplay.rst labels: - "area: Aux display" @@ -710,7 +813,9 @@ Release Notes: - str4t0m files: - boards/shields/mcp2515/ - - doc/hardware/peripherals/canbus/ + - boards/shields/tcan4550evm/ + - doc/connectivity/canbus/ + - doc/hardware/peripherals/can/ - drivers/can/ - drivers/net/canbus.c - dts/bindings/can/ @@ -734,6 +839,20 @@ Release Notes: labels: - "area: CAN" +"Drivers: Charger": + status: maintained + maintainers: + - aaronemassey + - rriveramcrus + files: + - drivers/charger/ + - dts/bindings/charger/ + - include/zephyr/drivers/charger.h + - tests/drivers/charger/ + - doc/hardware/peripherals/charger.rst + labels: + - "area: Charger" + "Drivers: Clock control": status: maintained maintainers: @@ -865,6 +984,7 @@ Release Notes: - include/zephyr/drivers/eeprom.h - samples/drivers/eeprom/ - tests/drivers/eeprom/ + - doc/hardware/peripherals/eeprom.rst labels: - "area: EEPROM" @@ -876,6 +996,7 @@ Release Notes: - drivers/entropy/ - include/zephyr/drivers/entropy.h - tests/drivers/entropy/ + - doc/hardware/peripherals/entropy.rst labels: - "area: Crypto / RNG" @@ -904,6 +1025,7 @@ Release Notes: - include/zephyr/dt-bindings/ethernet/ - tests/drivers/build_all/ethernet/ - dts/bindings/ethernet/ + - tests/drivers/ethernet/ labels: - "area: Ethernet" @@ -969,6 +1091,18 @@ Release Notes: labels: - "area: GPIO" +"Drivers: GNSS": + status: maintained + maintainers: + - bjarki-trackunit + files: + - doc/hardware/peripherals/gnss.rst + - drivers/gnss/ + - include/zephyr/drivers/gnss.h + - tests/drivers/gnss/ + labels: + - "area: GNSS" + "Drivers: HW Info": status: maintained maintainers: @@ -1063,6 +1197,7 @@ Release Notes: - dts/bindings/ipm/ - tests/drivers/ipm/ - doc/hardware/peripherals/ipm.rst + - include/zephyr/drivers/ipm.h description: >- Inter-processor mailboxes labels: @@ -1079,7 +1214,6 @@ Release Notes: - include/zephyr/drivers/kscan.h - samples/drivers/espi/ - samples/drivers/kscan/ - - samples/drivers/kscan_touch/ - tests/drivers/kscan/ - tests/drivers/espi/ - dts/bindings/kscan/ @@ -1117,23 +1251,18 @@ Release Notes: labels: - "area: LED" -"Drivers: lora": - status: maintained - maintainers: - - Mani-Sadhasivam +"Drivers: MFD": + status: odd fixes collaborators: - - mniestroj - - JordanYates + - gmarull + - aasinclair files: - - drivers/lora/ - - include/zephyr/drivers/lora.h - - samples/drivers/lora/ - - include/zephyr/lorawan/ - - subsys/lorawan/ - - samples/subsys/lorawan/ - - doc/connectivity/lora_lorawan/index.rst + - drivers/mfd/ + - include/zephyr/drivers/mfd/ + - dts/bindings/mfd/ + - tests/drivers/build_all/mfd/ labels: - - "area: LoRa" + - "area: MFD" "Drivers: Modem": status: maintained @@ -1145,24 +1274,15 @@ Release Notes: - dts/bindings/modem/ - include/zephyr/drivers/modem/ labels: - - "area: Modem" - -"Drivers: Neural Networks": - status: odd fixes - collaborators: - - nashif - files: - - drivers/neural_net/ - labels: - - "area: Neural Networks" + - "area: Modem Drivers" "Drivers: Regulators": status: maintained maintainers: - - gmarull + - aasinclair collaborators: - danieldegrasse - - aasinclair + - gmarull files: - drivers/regulator/ - include/zephyr/drivers/regulator/ @@ -1183,6 +1303,7 @@ Release Notes: - dts/bindings/retained_mem/ - include/zephyr/drivers/retained_mem.h - tests/drivers/retained_mem/ + - doc/hardware/peripherals/retained_mem.rst labels: - "area: Retained Memory" @@ -1192,6 +1313,7 @@ Release Notes: - bjarki-trackunit files: - drivers/rtc/ + - include/zephyr/drivers/rtc/ - tests/drivers/rtc/ - doc/hardware/peripherals/rtc.rst - include/zephyr/drivers/rtc.h @@ -1209,6 +1331,7 @@ Release Notes: files: - drivers/pcie/ - include/zephyr/drivers/pcie/ + - doc/hardware/peripherals/pcie.rst labels: - "area: PCI" @@ -1324,6 +1447,7 @@ Release Notes: files: - drivers/sensor/ - include/zephyr/drivers/sensor.h + - include/zephyr/drivers/sensor_data_types.h - samples/sensor/ - tests/drivers/sensor/ - dts/bindings/sensor/ @@ -1382,6 +1506,7 @@ Release Notes: - drivers/video/ - include/zephyr/drivers/video.h - include/zephyr/drivers/video-controls.h + - doc/hardware/peripherals/video.rst labels: - "area: Video" @@ -1390,7 +1515,7 @@ Release Notes: maintainers: - str4t0m collaborators: - - dp7hgh7 + - casparfriedrich files: - doc/hardware/peripherals/w1.rst - drivers/w1/ @@ -1581,6 +1706,7 @@ Input: - subsys/input/ - tests/drivers/build_all/input/ - tests/subsys/input/ + - tests/drivers/input/ description: >- Input subsystem and drivers labels: @@ -1602,7 +1728,9 @@ IPC: - "area: IPC" JSON Web Token: - status: odd fixes + status: maintained + maintainers: + - d3zd3z collaborators: - mrfuchs - sir-branch @@ -1611,6 +1739,7 @@ JSON Web Token: - include/zephyr/data/ - lib/os/json.c - tests/subsys/jwt/ + - tests/lib/json/ labels: - "area: JSON" @@ -1623,6 +1752,8 @@ Kconfig: - scripts/kconfig/ - doc/build/kconfig/ - Kconfig.zephyr + - tests/kconfig/configdefault/ + - tests/misc/kconfigoptions/ labels: - "area: Kconfig" description: >- @@ -1633,12 +1764,13 @@ Kernel: status: maintained maintainers: - andyross + - peter-mitsis collaborators: - nashif - ceolin - dcpleung - - peter-mitsis - cfriedt + - npitre files: - doc/kernel/ - include/zephyr/kernel*.h @@ -1657,9 +1789,10 @@ Base OS: status: maintained maintainers: - andyross + - nashif collaborators: - dcpleung - - nashif + - peter-mitsis files: - include/zephyr/sys/ - lib/os/ @@ -1669,6 +1802,10 @@ Base OS: - tests/lib/cbprintf_*/ - lib/os/cbprintf* - lib/os/Kconfig.cbprintf + - include/zephyr/sys/mem_manage.h + - include/zephyr/sys/mpsc_pbuf.h + - include/zephyr/sys/mpsc_packet.h + - lib/os/mpsc_pbuf.c labels: - "area: Base OS" @@ -1707,14 +1844,39 @@ Logging: - dcpleung files: - include/zephyr/logging/ + - include/zephyr/sys/mpsc_pbuf.h + - include/zephyr/sys/mpsc_packet.h + - lib/os/mpsc_pbuf.c + - doc/kernel/data_structures/mpsc_pbuf.rst + - tests/lib/mpsc_pbuf/ - samples/subsys/logging/ - subsys/logging/ - tests/subsys/logging/ - scripts/logging/ - doc/services/logging/ + - tests/lib/spsc_pbuf/ labels: - "area: Logging" +LoRa and LoRaWAN: + status: maintained + maintainers: + - JordanYates + collaborators: + - Mani-Sadhasivam + - martinjaeger + - mniestroj + files: + - drivers/lora/ + - include/zephyr/drivers/lora.h + - samples/drivers/lora/ + - include/zephyr/lorawan/ + - subsys/lorawan/ + - samples/subsys/lorawan/ + - doc/connectivity/lora_lorawan/index.rst + labels: + - "area: LoRa" + MAINTAINERS file: status: maintained maintainers: @@ -1779,6 +1941,10 @@ Modem Modules: - subsys/modem/ - include/zephyr/modem/ - tests/subsys/modem/ + - doc/services/modem/ + - samples/net/cellular_modem/ + labels: + - "area: Modem" OSDP: status: maintained @@ -1823,6 +1989,7 @@ Native POSIX/Sim and POSIX arch: - aescolar files: - arch/posix/ + - boards/posix/common/ - boards/posix/native_*/ - boards/posix/doc/ - boards/posix/*.rst @@ -1863,10 +2030,12 @@ Networking: - include/zephyr/net/gptp.h - include/zephyr/net/ieee802154*.h - include/zephyr/net/wifi*.h + - include/zephyr/net/buf.h - samples/net/gptp/ - samples/net/sockets/coap_*/ - samples/net/lwm2m_client/ - samples/net/wifi/ + - subsys/net/buf*.c - subsys/net/l2/ethernet/gptp/ - subsys/net/l2/ieee802154/ - subsys/net/l2/wifi/ @@ -1901,10 +2070,10 @@ Networking: - jukkar files: - include/zephyr/net/buf.h - - subsys/net/buf.c + - subsys/net/buf*.c - tests/net/buf/ labels: - - "area: Networking" + - "area: Networking Buffers" "Networking: Connection Manager": status: maintained @@ -1918,6 +2087,7 @@ Networking: - subsys/net/conn_mgr/ - tests/net/conn_mgr_monitor/ - tests/net/conn_mgr_conn/ + - doc/connectivity/networking/conn_mgr/ labels: - "area: Networking" @@ -1991,10 +2161,9 @@ Networking: "Networking: Native IEEE 802.15.4": status: maintained maintainers: - - tbursztyka + - fgrandel collaborators: - rlubos - - fgrandel - jukkar files: - doc/connectivity/networking/api/ieee802154.rst @@ -2013,6 +2182,7 @@ Networking: - pdgendt - canisLupus1313 - mariuszpos + - edmont files: - subsys/net/l2/openthread/ - samples/net/openthread/ @@ -2044,6 +2214,8 @@ NIOS-2 arch: - nashif files: - arch/nios2/ + - boards/common/nios2.board.cmake + - boards/nios2/ - soc/nios2/ - include/zephyr/arch/nios2/ - tests/boards/altera_max10/ @@ -2051,18 +2223,18 @@ NIOS-2 arch: labels: - "area: NIOS2" -nRF52 BSIM: +nRF BSIM: status: maintained maintainers: - aescolar files: - - boards/posix/nrf52_bsim/ + - boards/posix/nrf_bsim/ - tests/boards/nrf52_bsim/ - tests/bsim/ files-exclude: - tests/bsim/*/ labels: - - "platform: nRF52 BSIM" + - "platform: nRF BSIM" POSIX API layer: status: maintained @@ -2083,7 +2255,6 @@ Power management: - ceolin collaborators: - nashif - - gmarull - teburd - tmleman - JordanYates @@ -2108,14 +2279,17 @@ RISCV arch: - katsuster - edersondisouza - carlocaione + - npitre files: - arch/riscv/ - boards/riscv/ - dts/bindings/riscv/ + - dts/riscv/ - include/zephyr/arch/riscv/ - soc/riscv/ - tests/arch/riscv/ - doc/hardware/arch/risc-v.rst + - drivers/interrupt_controller/intc_plic.c labels: - "area: RISCV" @@ -2127,9 +2301,21 @@ Retention: - dts/bindings/retention/ - include/zephyr/retention/ - subsys/retention/ + - doc/services/retention/ labels: - "area: Retention" +Samples: + status: maintained + maintainers: + - kartben + collaborators: + - nashif + files: + - samples/ + labels: + - "area: Samples" + Sensor Subsystem: status: maintained maintainers: @@ -2148,6 +2334,14 @@ Sensor Subsystem: labels: - "area: Sensor Subsystem" +Stats: + status: odd fixes + files: + - subsys/stats/ + - include/zephyr/stats/stats.h + labels: + - "area: Stats" + Twister: status: maintained maintainers: @@ -2161,12 +2355,14 @@ Twister: - gchwier files: - scripts/twister + - scripts/schemas/twister/ - scripts/pylib/twister/ - scripts/tests/twister/ - scripts/tests/twister_blackbox/ - doc/develop/test/twister.rst - scripts/pylib/pytest-twister-harness/ - doc/develop/test/pytest.rst + - tests/test_config.yaml labels: - "area: Twister" @@ -2320,18 +2516,24 @@ Nuvoton NPCX Platforms: labels: - "platform: Nuvoton NPCX" -Nuvoton Numicro Platforms: - status: odd fixes +Nuvoton Numicro Numaker Platforms: + status: maintained + maintainers: + - cyliangtw collaborators: - ssekar15 files: - soc/arm/nuvoton_numicro/ + - soc/arm/nuvoton_numaker/ - boards/arm/nuvoton_pfm*/ + - boards/arm/numaker_*/ - dts/arm/nuvoton/ - dts/bindings/*/*numicro* + - dts/bindings/*/*numaker* - drivers/*/*_numicro* + - drivers/*/*_numaker* labels: - - "platform: Nuvoton Numicro" + - "platform: Nuvoton Numicro Numaker" Raspberry Pi Pico Platforms: status: maintained @@ -2406,6 +2608,7 @@ Intel Platforms (Xtensa): - tests/boards/intel_adsp/ - samples/boards/intel_adsp/ - dts/bindings/*/intel,adsp* + - scripts/west_commands/runners/intel_adsp.py labels: - "platform: Intel ADSP" @@ -2431,7 +2634,7 @@ Intel Platforms (Agilex): - gdengi collaborators: - nbalabak - - chongteikheng + - teikheng files: - boards/arm64/intel_*/ - soc/arm64/intel_*/ @@ -2457,6 +2660,7 @@ NXP Platforms: - bperseghetti - dbaluta - iuliana-prodan + - Dat-NguyenDuy files: - boards/arm/mimx*/ - boards/arm/frdm_k*/ @@ -2469,10 +2673,13 @@ NXP Platforms: - drivers/*/*imx* - drivers/*/*lpc*.c - drivers/*/*mcux*.c + - drivers/*/*.mcux + - drivers/*/*.nxp - drivers/*/*nxp* - dts/arm/nxp/ - dts/bindings/*/nxp* - soc/xtensa/nxp_adsp/ + - boards/xtensa/nxp_adsp_*/ - samples/boards/nxp*/ - include/zephyr/dt-bindings/*/nxp* - include/zephyr/drivers/*/*nxp* @@ -2583,6 +2790,7 @@ STM32 Platforms: - Desvauxm-st - GeorgeCGV files: + - boards/arm/b_*/ - boards/arm/nucleo_*/ - boards/arm/stm32*_disco/ - boards/arm/stm32*_dk*/ @@ -2591,6 +2799,7 @@ STM32 Platforms: - drivers/*/*stm32*.c - drivers/*/*stm32*.h - drivers/*/*/*stm32* + - drivers/*/*stm32 - dts/arm/st/ - dts/bindings/*/*stm32* - soc/arm/st_stm32/ @@ -2663,7 +2872,7 @@ TI SimpleLink Platforms: - drivers/*/*cc32* - dts/arm/ti/ - dts/bindings/*/ti,* - - soc/arm/ti*/ + - soc/arm/ti_simplelink/ - dts/bindings/*/ti,* labels: - "platform: TI SimpleLink" @@ -2772,6 +2981,18 @@ Task Watchdog: labels: - "area: Task Watchdog" +"Drivers: Time Aware GPIO": + status: maintained + maintainers: + - akanisetti + files: + - doc/hardware/peripherals/tgpio.rst + - drivers/misc/timeaware_gpio/ + - include/zephyr/drivers/misc/timeaware_gpio/ + - samples/drivers/misc/timeaware_gpio/ + labels: + - "area: Time Aware GPIO" + TF-M Integration: status: maintained maintainers: @@ -2785,7 +3006,8 @@ TF-M Integration: labels: - "area: TF-M" -Toolchain Integration: + +"Toolchain Integration": status: maintained maintainers: - tejlmand @@ -2796,6 +3018,42 @@ Toolchain Integration: - cmake/compiler/ - cmake/linker/ - cmake/toolchain/ + - include/zephyr/toolchain/ + - include/zephyr/toolchain.h + labels: + - "area: Toolchains" + +"Toolchain ARC MWDT": + status: maintained + maintainers: + - evgeniy-paltsev + - abrodkin + files: + - cmake/*/arcmwdt/ + - include/zephyr/toolchain/mwdt.h + - lib/libc/arcmwdt/* + labels: + - "area: Toolchains" + +"Toolchain arm compiler 6": + status: maintained + maintainers: + - tejlmand + files: + - cmake/*/armclang/ + - cmake/linker/armlink/ + - include/zephyr/toolchain/armclang.h + - lib/libc/armstdc/* + labels: + - "area: Toolchains" + +"Toolchain oneApi": + status: maintained + maintainers: + - nashif + files: + - cmake/*/oneApi/ + - cmake/compiler/icx/ labels: - "area: Toolchains" @@ -2807,6 +3065,7 @@ Tracing: - teburd files: - subsys/tracing/ + - scripts/tracing/ - include/zephyr/tracing/ - subsys/timing/ - samples/subsys/tracing/ @@ -2831,6 +3090,7 @@ USB: - tests/subsys/usb/ - tests/drivers/udc/ - doc/connectivity/usb/ + - scripts/generate_usb_vif/ labels: - "area: USB" @@ -2848,6 +3108,7 @@ USB-C: - samples/subsys/usb_c/ - subsys/usb/usb_c/ - doc/connectivity/usb/pd/ + - doc/hardware/peripherals/usbc_vbus.rst labels: - "area: USB-C" @@ -2858,6 +3119,7 @@ Userspace: collaborators: - ceolin files: + - include/zephyr/internal/syscall_handler.h - doc/kernel/usermode/kernelobjects.rst - include/zephyr/app_memory/ - include/zephyr/linker/app_smem*.ld @@ -2871,6 +3133,10 @@ Userspace: - scripts/build/process_gperf.py - scripts/build/gen_relocate_app.py - include/zephyr/sys/kobject.h + - include/zephyr/sys/mem_manage.h + - include/zephyr/kernel/mm.h + - include/zephyr/kernel/internal/mm.h + - include/zephyr/kernel/mm/demand_paging.h labels: - "area: Userspace" @@ -2898,9 +3164,22 @@ West: - scripts/west-commands.yml - scripts/west_commands/ - doc/develop/west/ + - scripts/pylib/build_helpers/domains.py labels: - "area: West" +"West project: acpica": + status: maintained + maintainers: + - najumon1980 + - jhedberg + collaborators: + - tbursztyka + files: + - modules/acpica/ + labels: + - "area: ACPI" + "West project: canopennode": status: maintained maintainers: @@ -2916,6 +3195,7 @@ West: - yperess files: - samples/modules/chre/ + - modules/Kconfig.chre labels: - "area: CHRE" @@ -2927,9 +3207,29 @@ West: - microbuilder - povergoing files: - - modules/cmsis/Kconfig - - modules/cmsis/Kconfig.cmsis_dsp - - modules/cmsis/Kconfig.cmsis_nn + - modules/cmsis/ + labels: + - "area: ARM" + +"West project: cmsis-dsp": + status: maintained + maintainers: + - XenuIsWatching + collaborators: + - stephanosio + files: + - modules/cmsis-dsp/ + labels: + - "area: ARM" + +"West project: cmsis-nn": + status: maintained + maintainers: + - XenuIsWatching + collaborators: + - stephanosio + files: + - modules/cmsis-nn/ labels: - "area: ARM" @@ -2969,7 +3269,8 @@ West: collaborators: - tgorochowik - msobkowski - files: [] + files: + - modules/hal_ambiq/ labels: - "platform: Ambiq" @@ -3000,14 +3301,24 @@ West: status: maintained maintainers: - sylvioalves - - glaubermaroto - - uLipe collaborators: - LucasTambor - files: [] + - marekmatej + files: + - modules/Kconfig.esp32 labels: - "platform: ESP32" +"West project: hal_ethos_u": + status: maintained + maintainers: + - kristofer-jonsson-arm + files: + - drivers/misc/ethos_u/ + - modules/hal_ethos_u/ + labels: + - "area: ARM" + "West project: hal_gigadevice": status: maintained maintainers: @@ -3304,12 +3615,13 @@ West: - "area: Tracing" "West project: nanopb": - status: odd fixes - collaborators: + status: maintained + maintainers: - pdgendt files: - modules/nanopb/ - samples/modules/nanopb/ + - tests/modules/nanopb/ labels: - "area: Serialization" @@ -3351,18 +3663,30 @@ West: - pdgendt - canisLupus1313 - mariuszpos + - edmont files: - modules/openthread/ labels: - "area: OpenThread" +"West project: percepio": + status: maintained + maintainers: + - eriktamlin + - aronlander-pe + files: + - modules/percepio/ + labels: + - "area: Tracing" + "West project: picolibc": status: maintained maintainers: - keith-packard collaborators: - stephanosio - files: [] + files: + - modules/Kconfig.picolibc labels: - "area: C Library" - "area: picolibc" @@ -3420,15 +3744,6 @@ West: labels: - "area: Crypto / RNG" -"West project: TraceRecorderSource": - status: maintained - maintainers: - - eriktamlin - files: - - modules/TraceRecorder/ - labels: - - "area: Tracing" - "West project: trusted-firmware-m": status: maintained maintainers: @@ -3482,6 +3797,7 @@ West: - StefanHri files: - modules/uoscore-uedhoc/ + - tests/modules/uoscore/ labels: - "area: Networking" - "area: Crypto / RNG" @@ -3503,6 +3819,16 @@ West: labels: - "area: Sensors" +"West project: hostap": + status: maintained + maintainers: + - krish2718 + - jukkar + files: + - modules/hostap/ + labels: + - "area: Wi-Fi" + Xtensa arch: status: maintained maintainers: @@ -3510,12 +3836,15 @@ Xtensa arch: collaborators: - andyross - nashif + - ceolin files: - arch/xtensa/ - include/zephyr/arch/xtensa/ - dts/xtensa/ - boards/xtensa/qemu_xtensa/ - boards/xtensa/xt-sim/ + - soc/xtensa/dc233c/ + - soc/xtensa/sample_controller/ labels: - "area: Xtensa" @@ -3552,6 +3881,7 @@ Continuous Integration: - scripts/ci/ - .checkpatch.conf - scripts/gitlint/ + - scripts/set_assignees.py labels: - "area: Continuous Integration" @@ -3568,6 +3898,7 @@ ZTest: - subsys/testsuite/ - tests/ztest/ - tests/unit/util/ + - tests/subsys/testsuite/ - samples/subsys/testsuite/ - doc/develop/test/ztest.rst labels: @@ -3595,8 +3926,8 @@ Emulation: - "area: HW Emulation" Random: - status: odd fixes - collaborators: + status: maintained + maintainers: - ceolin files: - subsys/random/ @@ -3629,3 +3960,18 @@ zbus: - doc/services/zbus/ labels: - "area: zbus" + +"Linkable Loadable Extensions": + status: maintained + maintainers: + - teburd + collaborators: + - lyakh + files: + - samples/subsys/llext/ + - include/zephyr/llext/ + - tests/subsys/llext/ + - subsys/llext/ + - doc/services/llext/ + labels: + - "area: Linkable Loadable Extensions" diff --git a/README.rst b/README.rst index 9770417087d..45a3998194d 100644 --- a/README.rst +++ b/README.rst @@ -54,39 +54,59 @@ Resources Here's a quick summary of resources to help you find your way around: -* **Help**: `Asking for Help Tips`_ -* **Documentation**: http://docs.zephyrproject.org (`Getting Started Guide`_) -* **Source Code**: https://github.com/zephyrproject-rtos/zephyr is the main - repository; https://elixir.bootlin.com/zephyr/latest/source contains a - searchable index -* **Releases**: https://github.com/zephyrproject-rtos/zephyr/releases -* **Samples and example code**: see `Sample and Demo Code Examples`_ -* **Mailing Lists**: users@lists.zephyrproject.org and - devel@lists.zephyrproject.org are the main user and developer mailing lists, - respectively. You can join the developer's list and search its archives at - `Zephyr Development mailing list`_. The other `Zephyr mailing list - subgroups`_ have their own archives and sign-up pages. -* **Nightly CI Build Status**: https://lists.zephyrproject.org/g/builds - The builds@lists.zephyrproject.org mailing list archives the CI nightly build results. -* **Chat**: Real-time chat happens in Zephyr's Discord Server. Use - this `Discord Invite`_ to register. -* **Contributing**: see the `Contribution Guide`_ -* **Wiki**: `Zephyr GitHub wiki`_ -* **Issues**: https://github.com/zephyrproject-rtos/zephyr/issues -* **Security Issues**: Email vulnerabilities@zephyrproject.org to report - security issues; also see our `Security`_ documentation. Security issues are - tracked separately at https://zephyrprojectsec.atlassian.net. -* **Zephyr Project Website**: https://zephyrproject.org - -.. _Discord Invite: https://chat.zephyrproject.org -.. _supported boards: http://docs.zephyrproject.org/latest/boards/index.html -.. _Zephyr Documentation: http://docs.zephyrproject.org -.. _Introduction to Zephyr: http://docs.zephyrproject.org/latest/introduction/index.html -.. _Getting Started Guide: http://docs.zephyrproject.org/latest/develop/getting_started/index.html -.. _Contribution Guide: http://docs.zephyrproject.org/latest/contribute/index.html -.. _Zephyr GitHub wiki: https://github.com/zephyrproject-rtos/zephyr/wiki -.. _Zephyr Development mailing list: https://lists.zephyrproject.org/g/devel -.. _Zephyr mailing list subgroups: https://lists.zephyrproject.org/g/main/subgroups -.. _Sample and Demo Code Examples: http://docs.zephyrproject.org/latest/samples/index.html -.. _Security: http://docs.zephyrproject.org/latest/security/index.html -.. _Asking for Help Tips: https://docs.zephyrproject.org/latest/develop/getting_started/index.html#asking-for-help +Getting Started +--------------- + + | 📖 `Zephyr Documentation`_ + | 🚀 `Getting Started Guide`_ + | 🙋🏽 `Tips when asking for help`_ + | 💻 `Code samples`_ + +Code and Development +-------------------- + + | 🌐 `Source Code Repository`_ + | 📦 `Releases`_ + | 🤝 `Contribution Guide`_ + +Community and Support +--------------------- + + | 💬 `Discord Server`_ for real-time community discussions + | 📧 `User mailing list (users@lists.zephyrproject.org)`_ + | 📧 `Developer mailing list (devel@lists.zephyrproject.org)`_ + | 📬 `Other project mailing lists`_ + | 📚 `Project Wiki`_ + +Issue Tracking and Security +--------------------------- + + | 🐛 `GitHub Issues`_ + | 🔒 `Security documentation`_ + | 🛡️ `Security Advisories Repository`_ + | ⚠️ Report security vulnerabilities at vulnerabilities@zephyrproject.org + +Additional Resources +-------------------- + | 🌐 `Zephyr Project Website`_ + | 📺 `Zephyr Tech Talks`_ + +.. _Zephyr Project Website: https://www.zephyrproject.org +.. _Discord Server: https://chat.zephyrproject.org +.. _supported boards: https://docs.zephyrproject.org/latest/boards/index.html +.. _Zephyr Documentation: https://docs.zephyrproject.org +.. _Introduction to Zephyr: https://docs.zephyrproject.org/latest/introduction/index.html +.. _Getting Started Guide: https://docs.zephyrproject.org/latest/develop/getting_started/index.html +.. _Contribution Guide: https://docs.zephyrproject.org/latest/contribute/index.html +.. _Source Code Repository: https://github.com/zephyrproject-rtos/zephyr +.. _GitHub Issues: https://github.com/zephyrproject-rtos/zephyr/issues +.. _Releases: https://github.com/zephyrproject-rtos/zephyr/releases +.. _Project Wiki: https://github.com/zephyrproject-rtos/zephyr/wiki +.. _User mailing list (users@lists.zephyrproject.org): https://lists.zephyrproject.org/g/users +.. _Developer mailing list (devel@lists.zephyrproject.org): https://lists.zephyrproject.org/g/devel +.. _Other project mailing lists: https://lists.zephyrproject.org/g/main/subgroups +.. _Code samples: https://docs.zephyrproject.org/latest/samples/index.html +.. _Security documentation: https://docs.zephyrproject.org/latest/security/index.html +.. _Security Advisories Repository: https://github.com/zephyrproject-rtos/zephyr/security +.. _Tips when asking for help: https://docs.zephyrproject.org/latest/develop/getting_started/index.html#asking-for-help +.. _Zephyr Tech Talks: https://www.zephyrproject.org/tech-talks diff --git a/VERSION b/VERSION index 2d7dfb83b49..a2cbf5c1335 100644 --- a/VERSION +++ b/VERSION @@ -1,5 +1,5 @@ VERSION_MAJOR = 3 -VERSION_MINOR = 4 +VERSION_MINOR = 5 PATCHLEVEL = 99 VERSION_TWEAK = 0 EXTRAVERSION = diff --git a/arch/Kconfig b/arch/Kconfig index 332bb49455f..5e3b96f414d 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -19,9 +19,9 @@ source "$(ARCH_DIR)/$(ARCH)/Kconfig" config ARC bool select ARCH_IS_SET - select HAS_DTS imply XIP select ARCH_HAS_THREAD_LOCAL_STORAGE + select ARCH_SUPPORTS_ROM_START help ARC architecture @@ -29,7 +29,6 @@ config ARM bool select ARCH_IS_SET select ARCH_SUPPORTS_COREDUMP if CPU_CORTEX_M - select HAS_DTS # FIXME: current state of the code for all ARM requires this, but # is really only necessary for Cortex-M with ARM MPU! select GEN_PRIV_STACKS @@ -42,7 +41,6 @@ config ARM64 bool select ARCH_IS_SET select 64BIT - select HAS_DTS select ARCH_SUPPORTS_COREDUMP select HAS_ARM_SMCCC select ARCH_HAS_THREAD_LOCAL_STORAGE @@ -57,14 +55,12 @@ config MIPS bool select ARCH_IS_SET select ATOMIC_OPERATIONS_C - select HAS_DTS help MIPS architecture config SPARC bool select ARCH_IS_SET - select HAS_DTS select USE_SWITCH select USE_SWITCH_SUPPORTED select BIG_ENDIAN @@ -79,8 +75,8 @@ config X86 bool select ARCH_IS_SET select ATOMIC_OPERATIONS_BUILTIN - select HAS_DTS select ARCH_SUPPORTS_COREDUMP + select ARCH_SUPPORTS_ROM_START if !X86_64 select CPU_HAS_MMU select ARCH_MEM_DOMAIN_DATA if USERSPACE && !X86_COMMON_PAGE_TABLE select ARCH_MEM_DOMAIN_SYNCHRONOUS_API if USERSPACE @@ -100,7 +96,6 @@ config NIOS2 bool select ARCH_IS_SET select ATOMIC_OPERATIONS_C - select HAS_DTS imply XIP select ARCH_HAS_TIMING_FUNCTIONS help @@ -109,8 +104,8 @@ config NIOS2 config RISCV bool select ARCH_IS_SET - select HAS_DTS select ARCH_SUPPORTS_COREDUMP + select ARCH_SUPPORTS_ROM_START if !SOC_SERIES_ESP32C3 select ARCH_HAS_CODE_DATA_RELOCATION select ARCH_HAS_THREAD_LOCAL_STORAGE select IRQ_OFFLOAD_NESTED if IRQ_OFFLOAD @@ -125,7 +120,6 @@ config RISCV config XTENSA bool select ARCH_IS_SET - select HAS_DTS select USE_SWITCH select USE_SWITCH_SUPPORTED select IRQ_OFFLOAD_NESTED if IRQ_OFFLOAD @@ -138,7 +132,6 @@ config XTENSA config ARCH_POSIX bool select ARCH_IS_SET - select HAS_DTS select ATOMIC_OPERATIONS_BUILTIN select ARCH_HAS_CUSTOM_SWAP_TO_MAIN select ARCH_HAS_CUSTOM_BUSY_WAIT @@ -146,6 +139,8 @@ config ARCH_POSIX select NATIVE_BUILD select HAS_COVERAGE_SUPPORT select BARRIER_OPERATIONS_BUILTIN + # native_posix gets its memory cleared on entry by the host OS + select SKIP_BSS_CLEAR help POSIX (native) architecture @@ -403,6 +398,23 @@ config DYNAMIC_INTERRUPTS interrupt-related data structures to RAM instead of ROM, and on some architectures increase code size. +config SHARED_INTERRUPTS + bool "Set this to enable support for shared interrupts" + depends on GEN_SW_ISR_TABLE + select EXPERIMENTAL + help + Set this to enable support for shared interrupts. Use this with + caution as enabling this will increase the image size by a + non-negligible amount. + +config SHARED_IRQ_MAX_NUM_CLIENTS + int "Maximum number of clients allowed per shared interrupt" + default 2 + depends on SHARED_INTERRUPTS + help + This option controls the maximum number of clients allowed + per shared interrupt. Set this according to your needs. + config GEN_ISR_TABLES bool "Use generated IRQ tables" help @@ -580,6 +592,9 @@ config ARCH_SUPPORTS_COREDUMP config ARCH_SUPPORTS_ARCH_HW_INIT bool +config ARCH_SUPPORTS_ROM_START + bool + config ARCH_HAS_EXTRA_EXCEPTION_INFO bool @@ -963,3 +978,10 @@ config TOOLCHAIN_HAS_BUILTIN_FFS default y if !(64BIT && RISCV) help Hidden option to signal that toolchain has __builtin_ffs*(). + +config ARCH_CPU_IDLE_CUSTOM + bool "Custom arch_cpu_idle implementation" + default n + help + This options allows applications to override the default arch idle implementation with + a custom one. diff --git a/arch/arc/core/thread.c b/arch/arc/core/thread.c index 960889661aa..eeb12d45f6a 100644 --- a/arch/arc/core/thread.c +++ b/arch/arc/core/thread.c @@ -14,7 +14,6 @@ #include #include #include -#include #ifdef CONFIG_USERSPACE #include diff --git a/arch/arm/CMakeLists.txt b/arch/arm/CMakeLists.txt index 14c831b9120..5aa25f20396 100644 --- a/arch/arm/CMakeLists.txt +++ b/arch/arm/CMakeLists.txt @@ -2,4 +2,4 @@ set_property(GLOBAL PROPERTY PROPERTY_OUTPUT_FORMAT elf32-littlearm) -add_subdirectory(core/aarch32) +add_subdirectory(core) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index ef9a20d0cc9..8b0d53ec3cf 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -16,23 +16,23 @@ config CPU_CORTEX config ARM_CUSTOM_INTERRUPT_CONTROLLER bool - depends on !CPU_CORTEX_M help This option indicates that the ARM CPU is connected to a custom (i.e. - non-GIC) interrupt controller. + non-GIC or NVIC) interrupt controller. A number of Cortex-A and Cortex-R cores (Cortex-A5, Cortex-R4/5, ...) allow interfacing to a custom external interrupt controller and this option must be selected when such cores are connected to an interrupt - controller that is not the ARM Generic Interrupt Controller (GIC). + controller that is not the ARM Generic Interrupt Controller (GIC) or + the Cortex-M ARM Nested Vectored Interrupt Controller (NVIC). When this option is selected, the architecture interrupt control functions are mapped to the SoC interrupt control interface, which is implemented at the SoC level. - N.B. This option is only applicable to the Cortex-A and Cortex-R - family cores. The Cortex-M family cores are always equipped with - the ARM Nested Vectored Interrupt Controller (NVIC). + N.B. Since all Cortex-M cores have a NVIC, if this option is selected it + is assumed that the custom interrupt control interface implementation + assumes responsibility for handling the NVIC. config CODE_DATA_RELOCATION_SRAM bool "Relocate code/data sections to SRAM" @@ -79,7 +79,7 @@ config ARM_ON_EXIT_CPU_IDLE observed on some SoCs caused by a memory access following WFI/WFE instructions. -rsource "core/aarch32/Kconfig" -rsource "core/aarch32/Kconfig.vfp" +rsource "core/Kconfig" +rsource "core/Kconfig.vfp" endmenu diff --git a/arch/arm/core/CMakeLists.txt b/arch/arm/core/CMakeLists.txt new file mode 100644 index 00000000000..1b4fa58eae5 --- /dev/null +++ b/arch/arm/core/CMakeLists.txt @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources( + fatal.c + nmi.c + nmi_on_reset.S +) + +zephyr_library_sources_ifdef(CONFIG_CPP __aeabi_atexit.c) +zephyr_library_sources_ifdef(CONFIG_IRQ_OFFLOAD irq_offload.c) +zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE tls.c) +zephyr_library_sources_ifdef(CONFIG_USERSPACE userspace.S) +zephyr_library_sources_ifdef(CONFIG_ARM_ZIMAGE_HEADER header.S) +zephyr_library_sources_ifdef(CONFIG_LLEXT elf.c) + +add_subdirectory_ifdef(CONFIG_CPU_CORTEX_M cortex_m) +add_subdirectory_ifdef(CONFIG_CPU_CORTEX_M_HAS_CMSE cortex_m/cmse) +add_subdirectory_ifdef(CONFIG_ARM_SECURE_FIRMWARE cortex_m/tz) +add_subdirectory_ifdef(CONFIG_ARM_NONSECURE_FIRMWARE cortex_m/tz) + +add_subdirectory_ifdef(CONFIG_ARM_MPU mpu) +add_subdirectory_ifdef(CONFIG_ARM_AARCH32_MMU mmu) + +add_subdirectory_ifdef(CONFIG_CPU_AARCH32_CORTEX_R cortex_a_r) +add_subdirectory_ifdef(CONFIG_CPU_AARCH32_CORTEX_A cortex_a_r) + +if (CONFIG_ARM_ZIMAGE_HEADER) +zephyr_linker_sources(ROM_START SORT_KEY 0x0vectors zimage_header.ld) +zephyr_linker_sources(ROM_START SORT_KEY 0x1vectors vector_table.ld) +zephyr_linker_sources(ROM_START SORT_KEY 0x2vectors cortex_m/vector_table_pad.ld) +else() +zephyr_linker_sources(ROM_START SORT_KEY 0x0vectors vector_table.ld) +zephyr_linker_sources(ROM_START SORT_KEY 0x1vectors cortex_m/vector_table_pad.ld) +endif() diff --git a/arch/arm/core/Kconfig b/arch/arm/core/Kconfig new file mode 100644 index 00000000000..4afe6c06ab5 --- /dev/null +++ b/arch/arm/core/Kconfig @@ -0,0 +1,323 @@ +# ARM core configuration options + +# Copyright (c) 2015 Wind River Systems, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config CPU_CORTEX_M + bool + select CPU_CORTEX + select ARCH_HAS_CUSTOM_SWAP_TO_MAIN + select HAS_CMSIS_CORE + select HAS_FLASH_LOAD_OFFSET + select ARCH_HAS_SINGLE_THREAD_SUPPORT + select ARCH_HAS_THREAD_ABORT + select ARCH_HAS_TRUSTED_EXECUTION if ARM_TRUSTZONE_M + select ARCH_HAS_STACK_PROTECTION if (ARM_MPU && !ARMV6_M_ARMV8_M_BASELINE) || CPU_CORTEX_M_HAS_SPLIM + select ARCH_HAS_USERSPACE if ARM_MPU + select ARCH_HAS_NOCACHE_MEMORY_SUPPORT if ARM_MPU && CPU_HAS_ARM_MPU && CPU_HAS_DCACHE + select ARCH_HAS_RAMFUNC_SUPPORT + select ARCH_HAS_NESTED_EXCEPTION_DETECTION + select SWAP_NONATOMIC + select ARCH_HAS_EXTRA_EXCEPTION_INFO + select ARCH_HAS_TIMING_FUNCTIONS if CPU_CORTEX_M_HAS_DWT + select ARCH_SUPPORTS_ARCH_HW_INIT + select ARCH_HAS_SUSPEND_TO_RAM + select ARCH_HAS_CODE_DATA_RELOCATION + select ARCH_SUPPORTS_ROM_START + imply XIP + help + This option signifies the use of a CPU of the Cortex-M family. + +config CPU_AARCH32_CORTEX_R + bool + select CPU_CORTEX + select HAS_CMSIS_CORE + select ARCH_HAS_NESTED_EXCEPTION_DETECTION + select HAS_FLASH_LOAD_OFFSET + select ARCH_HAS_USERSPACE if ARM_MPU && !USE_SWITCH + select ARCH_HAS_EXTRA_EXCEPTION_INFO if !USE_SWITCH + select ARCH_HAS_CODE_DATA_RELOCATION + select ARCH_HAS_NOCACHE_MEMORY_SUPPORT if ARM_MPU && CPU_HAS_ARM_MPU && CPU_HAS_DCACHE + select ARCH_SUPPORTS_ROM_START + select USE_SWITCH_SUPPORTED + help + This option signifies the use of a CPU of the Cortex-R family. + +config ARM_ZIMAGE_HEADER + bool "zImage Header" + depends on CPU_AARCH32_CORTEX_R || CPU_AARCH32_CORTEX_A || CPU_CORTEX_M_HAS_VTOR + help + This option adds a zImage Header. + +config CPU_AARCH32_CORTEX_A + bool + select CPU_CORTEX + select CPU_HAS_MMU + select HAS_CMSIS_CORE + select HAS_FLASH_LOAD_OFFSET + select ARCH_HAS_EXTRA_EXCEPTION_INFO if !USE_SWITCH + select ARCH_HAS_NOCACHE_MEMORY_SUPPORT + select USE_SWITCH_SUPPORTED + help + This option signifies the use of a CPU of the Cortex-A family. + +config ISA_THUMB2 + bool + help + From: http://www.arm.com/products/processors/technologies/instruction-set-architectures.php + + Thumb-2 technology is the instruction set underlying the ARM Cortex + architecture which provides enhanced levels of performance, energy + efficiency, and code density for a wide range of embedded + applications. + + Thumb-2 technology builds on the success of Thumb, the innovative + high code density instruction set for ARM microprocessor cores, to + increase the power of the ARM microprocessor core available to + developers of low cost, high performance systems. + + The technology is backwards compatible with existing ARM and Thumb + solutions, while significantly extending the features available to + the Thumb instructions set. This allows more of the application to + benefit from the best in class code density of Thumb. + + For performance optimized code Thumb-2 technology uses 31 percent + less memory to reduce system cost, while providing up to 38 percent + higher performance than existing high density code, which can be used + to prolong battery-life or to enrich the product feature set. Thumb-2 + technology is featured in the processor, and in all ARMv7 + architecture-based processors. + +config ISA_ARM + bool + help + From: https://developer.arm.com/products/architecture/instruction-sets/a32-and-t32-instruction-sets + + A32 instructions, known as Arm instructions in pre-Armv8 architectures, + are 32 bits wide, and are aligned on 4-byte boundaries. A32 instructions + are supported by both A-profile and R-profile architectures. + + A32 was traditionally used in applications requiring the highest + performance, or for handling hardware exceptions such as interrupts and + processor start-up. Much of its functionality was subsumed into T32 with + the introduction of Thumb-2 technology. + +config ASSEMBLER_ISA_THUMB2 + bool + default y if ISA_THUMB2 && !ISA_ARM + depends on !ISA_ARM + help + This helper symbol specifies the default target instruction set for + the assembler. + + When only the Thumb-2 ISA is supported (i.e. on Cortex-M cores), the + assembler must use the Thumb-2 instruction set. + + When both the Thumb-2 and ARM ISAs are supported (i.e. on Cortex-A + and Cortex-R cores), the assembler must use the ARM instruction set + because the architecture assembly code makes use of the ARM + instructions. + +config COMPILER_ISA_THUMB2 + bool "Compile C/C++ functions using Thumb-2 instruction set" + depends on ISA_THUMB2 + default y + help + This option configures the compiler to compile all C/C++ functions + using the Thumb-2 instruction set. + + N.B. The scope of this symbol is not necessarily limited to the C and + C++ languages; in fact, this symbol refers to all forms of + "compiled" code. + + When an additional natively-compiled language support is added + in the future, this symbol shall also specify the Thumb-2 + instruction set for that language. + +config NUM_IRQS + int + +config STACK_ALIGN_DOUBLE_WORD + bool "Align stacks on double-words (8 octets)" + default y + help + This is needed to conform to AAPCS, the procedure call standard for + the ARM. It wastes stack space. The option also enforces alignment + of stack upon exception entry on Cortex-M3 and Cortex-M4 (ARMv7-M). + Note that for ARMv6-M, ARMv8-M, and Cortex-M7 MCUs stack alignment + on exception entry is enabled by default and it is not configurable. + +config RUNTIME_NMI + bool "Attach an NMI handler at runtime" + select REBOOT + help + The kernel provides a simple NMI handler that simply hangs in a tight + loop if triggered. This fills the requirement that there must be an + NMI handler installed when the CPU boots. If a custom handler is + needed, enable this option and attach it via z_arm_nmi_set_handler(). + +config PLATFORM_SPECIFIC_INIT + bool "Platform (SOC) specific startup hook" + help + The platform specific initialization code (z_arm_platform_init) is + executed at the beginning of the startup code (__start). + +config FAULT_DUMP + int "Fault dump level" + default 2 + range 0 2 + help + Different levels for display information when a fault occurs. + + 2: The default. Display specific and verbose information. Consumes + the most memory (long strings). + + 1: Display general and short information. Consumes less memory + (short strings). + + 0: Off. + +config BUILTIN_STACK_GUARD + bool "Thread Stack Guards based on built-in ARM stack limit checking" + depends on CPU_CORTEX_M_HAS_SPLIM + select THREAD_STACK_INFO + help + Enable Thread/Interrupt Stack Guards via built-in Stack Pointer + limit checking. The functionality must be supported by HW. + +config ARM_STACK_PROTECTION + bool + default y if HW_STACK_PROTECTION + imply BUILTIN_STACK_GUARD if CPU_CORTEX_M_HAS_SPLIM + select MPU_STACK_GUARD if (!BUILTIN_STACK_GUARD && ARM_MPU) + help + This option enables either: + - The built-in Stack Pointer limit checking, or + - the MPU-based stack guard + to cause a system fatal error + if the bounds of the current process stack are overflowed. + The two stack guard options are mutually exclusive. The + selection of the built-in Stack Pointer limit checking is + prioritized over the MPU-based stack guard. The developer + still has the option to manually select the MPU-based + stack guard, if this is desired. + +config ARM_SECURE_FIRMWARE + bool + depends on ARMV8_M_SE + default y if TRUSTED_EXECUTION_SECURE + help + This option indicates that we are building a Zephyr image that + is intended to execute in Secure state. The option is only + applicable to ARMv8-M MCUs that implement the Security Extension. + + This option enables Zephyr to include code that executes in + Secure state, as well as to exclude code that is designed to + execute only in Non-secure state. + + Code executing in Secure state has access to both the Secure + and Non-Secure resources of the Cortex-M MCU. + + Code executing in Non-Secure state may trigger Secure Faults, + if Secure MCU resources are accessed from the Non-Secure state. + Secure Faults may only be handled by code executing in Secure + state. + +config ARM_NONSECURE_FIRMWARE + bool + depends on !ARM_SECURE_FIRMWARE + depends on ARMV8_M_SE + default y if TRUSTED_EXECUTION_NONSECURE + help + This option indicates that we are building a Zephyr image that + is intended to execute in Non-Secure state. Execution of this + image is triggered by Secure firmware that executes in Secure + state. The option is only applicable to ARMv8-M MCUs that + implement the Security Extension. + + This option enables Zephyr to include code that executes in + Non-Secure state only, as well as to exclude code that is + designed to execute only in Secure state. + + Code executing in Non-Secure state has no access to Secure + resources of the Cortex-M MCU, and, therefore, it shall avoid + accessing them. + +config ARM_NONSECURE_PREEMPTIBLE_SECURE_CALLS + bool "Allow secure function calls to be preempted" + depends on ARM_NONSECURE_FIRMWARE + help + When enabled, this option indicates that preemptible Zephyr + threads performing secure function calls, are allowed to be + preempted. When disabled, the option indicates that such + threads many not be context-switched-out while doing a Secure + function call. + +config ARM_STORE_EXC_RETURN + bool + default y if CPU_CORTEX_M && (FPU_SHARING || ARM_NONSECURE_PREEMPTIBLE_SECURE_CALLS) + help + Store the EXC_RETURN value when switching threads. + This is needed when switching between threads that differ in either + FPU usage or security domain. + +choice + prompt "Floating point ABI" + default FP_HARDABI + depends on FPU + +config FP_HARDABI + bool "Floating point Hard ABI" + help + This option selects the Floating point ABI in which hardware floating + point instructions are generated and uses FPU-specific calling + conventions. + + Note: When building with TF-M enabled only the IPC mode is supported. + +config FP_SOFTABI + bool "Floating point Soft ABI" + help + This option selects the Floating point ABI in which hardware floating + point instructions are generated but soft-float calling conventions. + +endchoice + +config FP16 + bool "Half-precision floating point support" + default y + help + This option enables the half-precision (16-bit) floating point support + via the `__fp16` (both IEEE and ARM alternative formats) and the + `_Float16` (defined by ISO/IEC TS 18661-3:2015) types. + +choice + prompt "FP16 format" + default FP16_IEEE + depends on FP16 + +config FP16_IEEE + bool "FP16 IEEE format" + help + This option selects the IEEE 754-2008 format for FP16. This format can + represent normalized values in the range of 2^(-14) to 65504. There are + 11 bits of significand precision, approximately 3 decimal digits. + +config FP16_ALT + bool "FP16 ARM alternative format" + help + This option selects the ARM alternative format for FP16. This + representation is similar to the IEEE 754-2008 format, but does not + support infinites or NaNs. Instead, the range of exponents is extended, + so that this format can represent normalized values in the range of + 2^(-14) to 131008. + + Please note that Clang doesn't support the ARM alternative format. + +endchoice + +rsource "cortex_m/Kconfig" +rsource "cortex_a_r/Kconfig" + +rsource "mpu/Kconfig" +rsource "mmu/Kconfig" diff --git a/arch/arm/core/aarch32/Kconfig.vfp b/arch/arm/core/Kconfig.vfp similarity index 100% rename from arch/arm/core/aarch32/Kconfig.vfp rename to arch/arm/core/Kconfig.vfp diff --git a/arch/arm/core/aarch32/__aeabi_atexit.c b/arch/arm/core/__aeabi_atexit.c similarity index 100% rename from arch/arm/core/aarch32/__aeabi_atexit.c rename to arch/arm/core/__aeabi_atexit.c diff --git a/arch/arm/core/aarch32/CMakeLists.txt b/arch/arm/core/aarch32/CMakeLists.txt deleted file mode 100644 index 00bc7693cda..00000000000 --- a/arch/arm/core/aarch32/CMakeLists.txt +++ /dev/null @@ -1,43 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library() - -zephyr_library_sources( - cpu_idle.S - fatal.c - irq_manage.c - nmi.c - nmi_on_reset.S - prep_c.c - swap.c - swap_helper.S - thread.c -) - -zephyr_library_sources_ifdef(CONFIG_GEN_SW_ISR_TABLE isr_wrapper.S) -zephyr_library_sources_ifdef(CONFIG_CPP __aeabi_atexit.c) -zephyr_library_sources_ifdef(CONFIG_IRQ_OFFLOAD irq_offload.c) -zephyr_library_sources_ifdef(CONFIG_SW_VECTOR_RELAY irq_relay.S) -zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE ../common/tls.c) -zephyr_library_sources_ifdef(CONFIG_USERSPACE userspace.S) -zephyr_library_sources_ifdef(CONFIG_ARM_ZIMAGE_HEADER header.S) - -add_subdirectory_ifdef(CONFIG_CPU_CORTEX_M cortex_m) -add_subdirectory_ifdef(CONFIG_CPU_CORTEX_M_HAS_CMSE cortex_m/cmse) -add_subdirectory_ifdef(CONFIG_ARM_SECURE_FIRMWARE cortex_m/tz) -add_subdirectory_ifdef(CONFIG_ARM_NONSECURE_FIRMWARE cortex_m/tz) - -add_subdirectory_ifdef(CONFIG_ARM_MPU mpu) -add_subdirectory_ifdef(CONFIG_ARM_AARCH32_MMU mmu) - -add_subdirectory_ifdef(CONFIG_CPU_AARCH32_CORTEX_R cortex_a_r) -add_subdirectory_ifdef(CONFIG_CPU_AARCH32_CORTEX_A cortex_a_r) - -if (CONFIG_ARM_ZIMAGE_HEADER) -zephyr_linker_sources(ROM_START SORT_KEY 0x0vectors zimage_header.ld) -zephyr_linker_sources(ROM_START SORT_KEY 0x1vectors vector_table.ld) -zephyr_linker_sources(ROM_START SORT_KEY 0x2vectors cortex_m/vector_table_pad.ld) -else() -zephyr_linker_sources(ROM_START SORT_KEY 0x0vectors vector_table.ld) -zephyr_linker_sources(ROM_START SORT_KEY 0x1vectors cortex_m/vector_table_pad.ld) -endif() diff --git a/arch/arm/core/aarch32/Kconfig b/arch/arm/core/aarch32/Kconfig deleted file mode 100644 index c8a48cb7f11..00000000000 --- a/arch/arm/core/aarch32/Kconfig +++ /dev/null @@ -1,317 +0,0 @@ -# ARM core configuration options - -# Copyright (c) 2015 Wind River Systems, Inc. -# SPDX-License-Identifier: Apache-2.0 - -config CPU_CORTEX_M - bool - select CPU_CORTEX - select ARCH_HAS_CUSTOM_SWAP_TO_MAIN - select HAS_CMSIS_CORE - select HAS_FLASH_LOAD_OFFSET - select ARCH_HAS_SINGLE_THREAD_SUPPORT - select ARCH_HAS_THREAD_ABORT - select ARCH_HAS_TRUSTED_EXECUTION if ARM_TRUSTZONE_M - select ARCH_HAS_STACK_PROTECTION if (ARM_MPU && !ARMV6_M_ARMV8_M_BASELINE) || CPU_CORTEX_M_HAS_SPLIM - select ARCH_HAS_USERSPACE if ARM_MPU - select ARCH_HAS_NOCACHE_MEMORY_SUPPORT if ARM_MPU && CPU_HAS_ARM_MPU && CPU_HAS_DCACHE - select ARCH_HAS_RAMFUNC_SUPPORT - select ARCH_HAS_NESTED_EXCEPTION_DETECTION - select SWAP_NONATOMIC - select ARCH_HAS_EXTRA_EXCEPTION_INFO - select ARCH_HAS_TIMING_FUNCTIONS if CPU_CORTEX_M_HAS_DWT - select ARCH_SUPPORTS_ARCH_HW_INIT - select ARCH_HAS_SUSPEND_TO_RAM - select ARCH_HAS_CODE_DATA_RELOCATION - imply XIP - help - This option signifies the use of a CPU of the Cortex-M family. - -config CPU_AARCH32_CORTEX_R - bool - select CPU_CORTEX - select HAS_CMSIS_CORE - select ARCH_HAS_NESTED_EXCEPTION_DETECTION - select HAS_FLASH_LOAD_OFFSET - select ARCH_HAS_USERSPACE if ARM_MPU - select ARCH_HAS_EXTRA_EXCEPTION_INFO - select ARCH_HAS_CODE_DATA_RELOCATION - select ARCH_HAS_NOCACHE_MEMORY_SUPPORT if ARM_MPU && CPU_HAS_ARM_MPU && CPU_HAS_DCACHE - help - This option signifies the use of a CPU of the Cortex-R family. - -config ARM_ZIMAGE_HEADER - bool "zImage Header" - depends on CPU_AARCH32_CORTEX_R || CPU_AARCH32_CORTEX_A || CPU_CORTEX_M_HAS_VTOR - help - This option adds a zImage Header. - -config CPU_AARCH32_CORTEX_A - bool - select CPU_CORTEX - select CPU_HAS_MMU - select HAS_CMSIS_CORE - select HAS_FLASH_LOAD_OFFSET - select ARCH_HAS_EXTRA_EXCEPTION_INFO - select ARCH_HAS_NOCACHE_MEMORY_SUPPORT - help - This option signifies the use of a CPU of the Cortex-A family. - -config ISA_THUMB2 - bool - help - From: http://www.arm.com/products/processors/technologies/instruction-set-architectures.php - - Thumb-2 technology is the instruction set underlying the ARM Cortex - architecture which provides enhanced levels of performance, energy - efficiency, and code density for a wide range of embedded - applications. - - Thumb-2 technology builds on the success of Thumb, the innovative - high code density instruction set for ARM microprocessor cores, to - increase the power of the ARM microprocessor core available to - developers of low cost, high performance systems. - - The technology is backwards compatible with existing ARM and Thumb - solutions, while significantly extending the features available to - the Thumb instructions set. This allows more of the application to - benefit from the best in class code density of Thumb. - - For performance optimized code Thumb-2 technology uses 31 percent - less memory to reduce system cost, while providing up to 38 percent - higher performance than existing high density code, which can be used - to prolong battery-life or to enrich the product feature set. Thumb-2 - technology is featured in the processor, and in all ARMv7 - architecture-based processors. - -config ISA_ARM - bool - help - From: https://developer.arm.com/products/architecture/instruction-sets/a32-and-t32-instruction-sets - - A32 instructions, known as Arm instructions in pre-Armv8 architectures, - are 32 bits wide, and are aligned on 4-byte boundaries. A32 instructions - are supported by both A-profile and R-profile architectures. - - A32 was traditionally used in applications requiring the highest - performance, or for handling hardware exceptions such as interrupts and - processor start-up. Much of its functionality was subsumed into T32 with - the introduction of Thumb-2 technology. - -config ASSEMBLER_ISA_THUMB2 - bool - default y if ISA_THUMB2 && !ISA_ARM - depends on !ISA_ARM - help - This helper symbol specifies the default target instruction set for - the assembler. - - When only the Thumb-2 ISA is supported (i.e. on Cortex-M cores), the - assembler must use the Thumb-2 instruction set. - - When both the Thumb-2 and ARM ISAs are supported (i.e. on Cortex-A - and Cortex-R cores), the assembler must use the ARM instruction set - because the architecture assembly code makes use of the ARM - instructions. - -config COMPILER_ISA_THUMB2 - bool "Compile C/C++ functions using Thumb-2 instruction set" - depends on ISA_THUMB2 - default y - help - This option configures the compiler to compile all C/C++ functions - using the Thumb-2 instruction set. - - N.B. The scope of this symbol is not necessarily limited to the C and - C++ languages; in fact, this symbol refers to all forms of - "compiled" code. - - When an additional natively-compiled language support is added - in the future, this symbol shall also specify the Thumb-2 - instruction set for that language. - -config NUM_IRQS - int - -config STACK_ALIGN_DOUBLE_WORD - bool "Align stacks on double-words (8 octets)" - default y - help - This is needed to conform to AAPCS, the procedure call standard for - the ARM. It wastes stack space. The option also enforces alignment - of stack upon exception entry on Cortex-M3 and Cortex-M4 (ARMv7-M). - Note that for ARMv6-M, ARMv8-M, and Cortex-M7 MCUs stack alignment - on exception entry is enabled by default and it is not configurable. - -config RUNTIME_NMI - bool "Attach an NMI handler at runtime" - select REBOOT - help - The kernel provides a simple NMI handler that simply hangs in a tight - loop if triggered. This fills the requirement that there must be an - NMI handler installed when the CPU boots. If a custom handler is - needed, enable this option and attach it via z_arm_nmi_set_handler(). - -config PLATFORM_SPECIFIC_INIT - bool "Platform (SOC) specific startup hook" - help - The platform specific initialization code (z_arm_platform_init) is - executed at the beginning of the startup code (__start). - -config FAULT_DUMP - int "Fault dump level" - default 2 - range 0 2 - help - Different levels for display information when a fault occurs. - - 2: The default. Display specific and verbose information. Consumes - the most memory (long strings). - - 1: Display general and short information. Consumes less memory - (short strings). - - 0: Off. - -config BUILTIN_STACK_GUARD - bool "Thread Stack Guards based on built-in ARM stack limit checking" - depends on CPU_CORTEX_M_HAS_SPLIM - select THREAD_STACK_INFO - help - Enable Thread/Interrupt Stack Guards via built-in Stack Pointer - limit checking. The functionality must be supported by HW. - -config ARM_STACK_PROTECTION - bool - default y if HW_STACK_PROTECTION - imply BUILTIN_STACK_GUARD if CPU_CORTEX_M_HAS_SPLIM - select MPU_STACK_GUARD if (!BUILTIN_STACK_GUARD && ARM_MPU) - help - This option enables either: - - The built-in Stack Pointer limit checking, or - - the MPU-based stack guard - to cause a system fatal error - if the bounds of the current process stack are overflowed. - The two stack guard options are mutually exclusive. The - selection of the built-in Stack Pointer limit checking is - prioritized over the MPU-based stack guard. The developer - still has the option to manually select the MPU-based - stack guard, if this is desired. - -config ARM_SECURE_FIRMWARE - bool - depends on ARMV8_M_SE - default y if TRUSTED_EXECUTION_SECURE - help - This option indicates that we are building a Zephyr image that - is intended to execute in Secure state. The option is only - applicable to ARMv8-M MCUs that implement the Security Extension. - - This option enables Zephyr to include code that executes in - Secure state, as well as to exclude code that is designed to - execute only in Non-secure state. - - Code executing in Secure state has access to both the Secure - and Non-Secure resources of the Cortex-M MCU. - - Code executing in Non-Secure state may trigger Secure Faults, - if Secure MCU resources are accessed from the Non-Secure state. - Secure Faults may only be handled by code executing in Secure - state. - -config ARM_NONSECURE_FIRMWARE - bool - depends on !ARM_SECURE_FIRMWARE - depends on ARMV8_M_SE - default y if TRUSTED_EXECUTION_NONSECURE - help - This option indicates that we are building a Zephyr image that - is intended to execute in Non-Secure state. Execution of this - image is triggered by Secure firmware that executes in Secure - state. The option is only applicable to ARMv8-M MCUs that - implement the Security Extension. - - This option enables Zephyr to include code that executes in - Non-Secure state only, as well as to exclude code that is - designed to execute only in Secure state. - - Code executing in Non-Secure state has no access to Secure - resources of the Cortex-M MCU, and, therefore, it shall avoid - accessing them. - -config ARM_NONSECURE_PREEMPTIBLE_SECURE_CALLS - bool "Allow secure function calls to be preempted" - depends on ARM_NONSECURE_FIRMWARE - help - When enabled, this option indicates that preemptible Zephyr - threads performing secure function calls, are allowed to be - preempted. When disabled, the option indicates that such - threads many not be context-switched-out while doing a Secure - function call. - -config ARM_STORE_EXC_RETURN - bool - default y if CPU_CORTEX_M && (FPU_SHARING || ARM_NONSECURE_PREEMPTIBLE_SECURE_CALLS) - help - Store the EXC_RETURN value when switching threads. - This is needed when switching between threads that differ in either - FPU usage or security domain. - -choice - prompt "Floating point ABI" - default FP_HARDABI - depends on FPU - -config FP_HARDABI - bool "Floating point Hard ABI" - help - This option selects the Floating point ABI in which hardware floating - point instructions are generated and uses FPU-specific calling - conventions. - -config FP_SOFTABI - bool "Floating point Soft ABI" - help - This option selects the Floating point ABI in which hardware floating - point instructions are generated but soft-float calling conventions. - -endchoice - -config FP16 - bool "Half-precision floating point support" - default y - help - This option enables the half-precision (16-bit) floating point support - via the `__fp16` (both IEEE and ARM alternative formats) and the - `_Float16` (defined by ISO/IEC TS 18661-3:2015) types. - -choice - prompt "FP16 format" - default FP16_IEEE - depends on FP16 - -config FP16_IEEE - bool "FP16 IEEE format" - help - This option selects the IEEE 754-2008 format for FP16. This format can - represent normalized values in the range of 2^(-14) to 65504. There are - 11 bits of significand precision, approximately 3 decimal digits. - -config FP16_ALT - bool "FP16 ARM alternative format" - help - This option selects the ARM alternative format for FP16. This - representation is similar to the IEEE 754-2008 format, but does not - support infinites or NaNs. Instead, the range of exponents is extended, - so that this format can represent normalized values in the range of - 2^(-14) to 131008. - - Please note that Clang doesn't support the ARM alternative format. - -endchoice - -rsource "cortex_m/Kconfig" -rsource "cortex_a_r/Kconfig" - -rsource "mpu/Kconfig" -rsource "mmu/Kconfig" diff --git a/arch/arm/core/aarch32/cortex_a_r/CMakeLists.txt b/arch/arm/core/aarch32/cortex_a_r/CMakeLists.txt deleted file mode 100644 index c1cdc7e9c67..00000000000 --- a/arch/arm/core/aarch32/cortex_a_r/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library() - -zephyr_library_sources( - exc.S - exc_exit.S - fault.c - irq_init.c - reboot.c - reset.S - stacks.c - tcm.c - vector_table.S - ) - -zephyr_library_sources_ifdef(CONFIG_USERSPACE thread.c) -zephyr_library_sources_ifdef(CONFIG_SEMIHOST semihost.c) -zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE __aeabi_read_tp.S) -zephyr_library_sources_ifdef(CONFIG_ARCH_CACHE cache.c) diff --git a/arch/arm/core/aarch32/cortex_a_r/Kconfig b/arch/arm/core/aarch32/cortex_a_r/Kconfig deleted file mode 100644 index 10bf721a870..00000000000 --- a/arch/arm/core/aarch32/cortex_a_r/Kconfig +++ /dev/null @@ -1,190 +0,0 @@ -# ARM Cortex-A and Cortex-R platform configuration options - -# Copyright (c) 2018 Marvell -# Copyright (c) 2018 Lexmark International, Inc. -# Copyright (c) 2021 Weidmueller Interface GmbH & Co. KG -# -# SPDX-License-Identifier: Apache-2.0 - -# NOTE: We have the specific core implementations first and outside of the -# if CPU_AARCH32_CORTEX_A / if CPU_AARCH32_CORTEX_R block so that SoCs can -# select which core they are using without having to select all the options -# related to that core. Everything else is captured inside the if -# CPU_AARCH32_CORTEX_A / if CPU_AARCH32_CORTEX_R blocks so they are not -# exposed if one selects a different ARM Cortex Family (Cortex-M). - -config CPU_CORTEX_A9 - bool - select CPU_AARCH32_CORTEX_A - select ARMV7_A - help - This option signifies the use of a Cortex-A9 CPU. - -if CPU_AARCH32_CORTEX_A - -config ARMV7_A - bool - select ATOMIC_OPERATIONS_BUILTIN - select ISA_ARM - -config ARMV7_EXCEPTION_STACK_SIZE - int "Undefined Instruction and Abort stack size (in bytes)" - default 256 - help - This option specifies the size of the stack used by the undefined - instruction and data abort exception handlers. - -config ARMV7_FIQ_STACK_SIZE - int "FIQ stack size (in bytes)" - default 256 - help - This option specifies the size of the stack used by the FIQ handler. - -config ARMV7_SVC_STACK_SIZE - int "SVC stack size (in bytes)" - default 512 - help - This option specifies the size of the stack used by the SVC handler. - -config ARMV7_SYS_STACK_SIZE - int "SYS stack size (in bytes)" - default 1024 - help - This option specifies the size of the stack used by the system mode. - -config RUNTIME_NMI - default y - -config GEN_ISR_TABLES - default y - -config GEN_IRQ_VECTOR_TABLE - default n - -config DCACHE_LINE_SIZE - default 32 - -config ICACHE_LINE_SIZE - default 32 - -endif # CPU_AARCH32_CORTEX_A - -config CPU_CORTEX_R4 - bool - select CPU_AARCH32_CORTEX_R - select ARMV7_R - select ARMV7_R_FP if CPU_HAS_FPU - help - This option signifies the use of a Cortex-R4 CPU - -config CPU_CORTEX_R5 - bool - select CPU_AARCH32_CORTEX_R - select ARMV7_R - select ARMV7_R_FP if CPU_HAS_FPU - help - This option signifies the use of a Cortex-R5 CPU - -config CPU_CORTEX_R7 - bool - select CPU_AARCH32_CORTEX_R - select ARMV7_R - select ARMV7_R_FP if CPU_HAS_FPU - help - This option signifies the use of a Cortex-R7 CPU - -config CPU_CORTEX_R52 - bool - select CPU_AARCH32_CORTEX_R - select AARCH32_ARMV8_R - select CPU_HAS_ICACHE - select CPU_HAS_DCACHE - select VFP_SP_D16 - help - This option signifies the use of a Cortex-R52 CPU - -if CPU_AARCH32_CORTEX_R - -config ARMV7_R - bool - select ATOMIC_OPERATIONS_BUILTIN - select ISA_ARM - select ISA_THUMB2 - help - This option signifies the use of an ARMv7-R processor - implementation. - - From https://developer.arm.com/products/architecture/cpu-architecture/r-profile: - The Armv7-R architecture implements a traditional Arm architecture with - multiple modes and supports a Protected Memory System Architecture - (PMSA) based on a Memory Protection Unit (MPU). It supports the Arm (32) - and Thumb (T32) instruction sets. - -config ARMV7_R_FP - bool - depends on ARMV7_R - help - This option signifies the use of an ARMv7-R processor - implementation supporting the Floating-Point Extension. - -config AARCH32_ARMV8_R - bool - select ATOMIC_OPERATIONS_BUILTIN - help - This option signifies the use of an ARMv8-R AArch32 processor - implementation. - - From https://developer.arm.com/products/architecture/cpu-architecture/r-profile: - The Armv8-R architecture targets at the Real-time profile. It introduces - virtualization at the highest security level while retaining the - Protected Memory System Architecture (PMSA) based on a Memory Protection - Unit (MPU). It supports the A32 and T32 instruction sets. - -config ARMV7_EXCEPTION_STACK_SIZE - int "Undefined Instruction and Abort stack size (in bytes)" - default 256 - help - This option specifies the size of the stack used by the undefined - instruction and data abort exception handlers. - -config ARMV7_FIQ_STACK_SIZE - int "FIQ stack size (in bytes)" - default 256 - help - This option specifies the size of the stack used by the FIQ handler. - -config ARMV7_SVC_STACK_SIZE - int "SVC stack size (in bytes)" - default 512 - help - This option specifies the size of the stack used by the SVC handler. - -config ARMV7_SYS_STACK_SIZE - int "SYS stack size (in bytes)" - default 1024 - help - This option specifies the size of the stack used by the system mode. - -config RUNTIME_NMI - default y - -config GEN_ISR_TABLES - default y - -config GEN_IRQ_VECTOR_TABLE - default n - -config DISABLE_TCM_ECC - bool "Disable ECC on TCM" - help - This option disables ECC checks on Tightly Coupled Memory. - -config DCACHE_LINE_SIZE - default 64 if CPU_CORTEX_R52 - default 32 - -config ICACHE_LINE_SIZE - default 64 if CPU_CORTEX_R52 - default 32 - -endif # CPU_AARCH32_CORTEX_R diff --git a/arch/arm/core/aarch32/cortex_a_r/__aeabi_read_tp.S b/arch/arm/core/aarch32/cortex_a_r/__aeabi_read_tp.S deleted file mode 100644 index 25e240b39d3..00000000000 --- a/arch/arm/core/aarch32/cortex_a_r/__aeabi_read_tp.S +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2020 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -_ASM_FILE_PROLOGUE - -GTEXT(__aeabi_read_tp) - -SECTION_FUNC(text, __aeabi_read_tp) - mrc 15, 0, r0, c13, c0, 3 - bx lr diff --git a/arch/arm/core/aarch32/cortex_a_r/stacks.c b/arch/arm/core/aarch32/cortex_a_r/stacks.c deleted file mode 100644 index 7f98deec9cb..00000000000 --- a/arch/arm/core/aarch32/cortex_a_r/stacks.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2018 Lexmark International, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include - -K_KERNEL_STACK_DEFINE(z_arm_fiq_stack, CONFIG_ARMV7_FIQ_STACK_SIZE); -K_KERNEL_STACK_DEFINE(z_arm_abort_stack, CONFIG_ARMV7_EXCEPTION_STACK_SIZE); -K_KERNEL_STACK_DEFINE(z_arm_undef_stack, CONFIG_ARMV7_EXCEPTION_STACK_SIZE); -K_KERNEL_STACK_DEFINE(z_arm_svc_stack, CONFIG_ARMV7_SVC_STACK_SIZE); -K_KERNEL_STACK_DEFINE(z_arm_sys_stack, CONFIG_ARMV7_SYS_STACK_SIZE); - -#if defined(CONFIG_INIT_STACKS) -void z_arm_init_stacks(void) -{ - memset(z_arm_fiq_stack, 0xAA, CONFIG_ARMV7_FIQ_STACK_SIZE); - memset(z_arm_svc_stack, 0xAA, CONFIG_ARMV7_SVC_STACK_SIZE); - memset(z_arm_abort_stack, 0xAA, CONFIG_ARMV7_EXCEPTION_STACK_SIZE); - memset(z_arm_undef_stack, 0xAA, CONFIG_ARMV7_EXCEPTION_STACK_SIZE); - memset(Z_KERNEL_STACK_BUFFER(z_interrupt_stacks[0]), 0xAA, - K_KERNEL_STACK_SIZEOF(z_interrupt_stacks[0])); -} -#endif diff --git a/arch/arm/core/aarch32/cortex_a_r/thread.c b/arch/arm/core/aarch32/cortex_a_r/thread.c deleted file mode 100644 index 736797f4011..00000000000 --- a/arch/arm/core/aarch32/cortex_a_r/thread.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2021 Lexmark International, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -bool z_arm_thread_is_in_user_mode(void) -{ - uint32_t value; - - /* - * For Cortex-R, the mode (lower 5) bits will be 0x10 for user mode. - */ - value = __get_CPSR(); - return ((value & CPSR_M_Msk) == CPSR_M_USR); -} diff --git a/arch/arm/core/aarch32/cortex_a_r/vector_table.S b/arch/arm/core/aarch32/cortex_a_r/vector_table.S deleted file mode 100644 index 971f90240c8..00000000000 --- a/arch/arm/core/aarch32/cortex_a_r/vector_table.S +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2018 Marvell - * Copyright (c) 2018 Lexmark International, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Populated vector table in ROM - */ - -#include -#include -#include "vector_table.h" - -_ASM_FILE_PROLOGUE - -SECTION_SUBSEC_FUNC(exc_vector_table,_vector_table_section,_vector_table) - ldr pc, =z_arm_reset /* offset 0 */ - ldr pc, =z_arm_undef_instruction /* undef instruction offset 4 */ - ldr pc, =z_arm_svc /* svc offset 8 */ - ldr pc, =z_arm_prefetch_abort /* prefetch abort offset 0xc */ - ldr pc, =z_arm_data_abort /* data abort offset 0x10 */ - nop /* offset 0x14 */ -#ifdef CONFIG_GEN_SW_ISR_TABLE - ldr pc, =_isr_wrapper /* IRQ offset 0x18 */ -#else - ldr pc, =z_irq_spurious -#endif - ldr pc, =z_arm_nmi /* FIQ offset 0x1c */ diff --git a/arch/arm/core/aarch32/cortex_m/CMakeLists.txt b/arch/arm/core/aarch32/cortex_m/CMakeLists.txt deleted file mode 100644 index 8d12299e965..00000000000 --- a/arch/arm/core/aarch32/cortex_m/CMakeLists.txt +++ /dev/null @@ -1,57 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library() - -zephyr_library_sources( - exc_exit.S - fault.c - fault_s.S - fpu.c - irq_init.c - reset.S - scb.c - thread_abort.c - vector_table.S - ) - -zephyr_library_sources_ifdef(CONFIG_USERSPACE thread.c) -zephyr_library_sources_ifdef(CONFIG_DEBUG_COREDUMP coredump.c) -zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE __aeabi_read_tp.S) -zephyr_library_sources_ifdef(CONFIG_SEMIHOST semihost.c) -zephyr_library_sources_ifdef(CONFIG_PM_S2RAM pm_s2ram.c pm_s2ram.S) -zephyr_library_sources_ifdef(CONFIG_ARCH_CACHE cache.c) - -if(CONFIG_NULL_POINTER_EXCEPTION_DETECTION_DWT) - zephyr_library_sources(debug.c) -endif() - -if(CONFIG_CORTEX_M_DWT) - if (CONFIG_TIMING_FUNCTIONS) - zephyr_library_sources(timing.c) - endif() -endif() - -if (CONFIG_SW_VECTOR_RELAY) -if (CONFIG_CPU_CORTEX_M_HAS_VTOR) - set(relay_vector_table_sort_key relay_vectors) -else() -# Using 0x0 prefix will result in placing the relay vector table section -# at the beginning of ROM_START (i.e before other sections in ROM_START); -# required for CPUs without VTOR, which need to have the exception vector -# table starting at a fixed address at the beginning of ROM. - set(relay_vector_table_sort_key 0x0relay_vectors) -endif() - -zephyr_linker_sources( - ROM_START - SORT_KEY ${relay_vector_table_sort_key} - relay_vector_table.ld - ) -endif() - -if (CONFIG_SW_VECTOR_RELAY OR CONFIG_SW_VECTOR_RELAY_CLIENT) -zephyr_linker_sources( - RAM_SECTIONS - vt_pointer_section.ld - ) -endif() diff --git a/arch/arm/core/aarch32/cortex_m/Kconfig b/arch/arm/core/aarch32/cortex_m/Kconfig deleted file mode 100644 index 169d5bc838d..00000000000 --- a/arch/arm/core/aarch32/cortex_m/Kconfig +++ /dev/null @@ -1,472 +0,0 @@ -# ARM Cortex-M platform configuration options - -# Copyright (c) 2014-2015 Wind River Systems, Inc. -# SPDX-License-Identifier: Apache-2.0 - -# NOTE: We have the specific core implementations first and outside of the -# if CPU_CORTEX_M block so that SoCs can select which core they are using -# without having to select all the options related to that core. Everything -# else is captured inside the if CPU_CORTEX_M block so they are not exposed -# if one select a different ARM Cortex Family (Cortex-A or Cortex-R) - -config CPU_CORTEX_M0 - bool - select CPU_CORTEX_M - select ARMV6_M_ARMV8_M_BASELINE - help - This option signifies the use of a Cortex-M0 CPU - -config CPU_CORTEX_M0PLUS - bool - select CPU_CORTEX_M - select ARMV6_M_ARMV8_M_BASELINE - help - This option signifies the use of a Cortex-M0+ CPU - -config CPU_CORTEX_M1 - bool - select CPU_CORTEX_M - select ARMV6_M_ARMV8_M_BASELINE - help - This option signifies the use of a Cortex-M1 CPU - -config CPU_CORTEX_M3 - bool - select CPU_CORTEX_M - select ARMV7_M_ARMV8_M_MAINLINE - help - This option signifies the use of a Cortex-M3 CPU - -config CPU_CORTEX_M4 - bool - select CPU_CORTEX_M - select ARMV7_M_ARMV8_M_MAINLINE - select ARMV7_M_ARMV8_M_FP if CPU_HAS_FPU - help - This option signifies the use of a Cortex-M4 CPU - -config CPU_CORTEX_M23 - bool - select CPU_CORTEX_M - select ARMV8_M_BASELINE - select ARMV8_M_SE if CPU_HAS_TEE - help - This option signifies the use of a Cortex-M23 CPU - -config CPU_CORTEX_M33 - bool - select CPU_CORTEX_M - select ARMV8_M_MAINLINE - select ARMV8_M_SE if CPU_HAS_TEE - select ARMV7_M_ARMV8_M_FP if CPU_HAS_FPU - help - This option signifies the use of a Cortex-M33 CPU - -config CPU_CORTEX_M55 - bool - select CPU_CORTEX_M - select ARMV8_1_M_MAINLINE - select ARMV8_M_SE if CPU_HAS_TEE - select ARMV7_M_ARMV8_M_FP if CPU_HAS_FPU - select CPU_HAS_DCACHE - select CPU_HAS_ICACHE - help - This option signifies the use of a Cortex-M55 CPU - -config CPU_CORTEX_M7 - bool - select CPU_CORTEX_M - select ARMV7_M_ARMV8_M_MAINLINE - select ARMV7_M_ARMV8_M_FP if CPU_HAS_FPU - select CPU_HAS_DCACHE - select CPU_HAS_ICACHE - help - This option signifies the use of a Cortex-M7 CPU - -if CPU_CORTEX_M - -config CPU_CORTEX_M_HAS_SYSTICK - bool - help - This option is enabled when the CPU implements the SysTick timer. - -config DCACHE_LINE_SIZE - default 32 - -config ICACHE_LINE_SIZE - default 32 - -config CPU_CORTEX_M_HAS_DWT - bool - depends on !CPU_CORTEX_M0 && !CPU_CORTEX_M0PLUS && !CPU_CORTEX_M1 - help - This option signifies that the CPU implements the Data Watchpoint and - Trace (DWT) unit specified by the ARMv7-M and above. - - While ARMv6-M does define a "DWT" unit, this is significantly different - from the DWT specified by the ARMv7-M and above in terms of both feature - set and register mappings. - -config CPU_CORTEX_M_HAS_BASEPRI - bool - depends on ARMV7_M_ARMV8_M_MAINLINE - help - This option signifies the CPU has the BASEPRI register. - - The BASEPRI register defines the minimum priority for - exception processing. When BASEPRI is set to a nonzero - value, it prevents the activation of all exceptions with - the same or lower priority level as the BASEPRI value. - Always present in CPUs that implement the ARMv7-M or - ARM8-M Mainline architectures. - -config CPU_CORTEX_M_HAS_VTOR - bool - depends on !CPU_CORTEX_M0 && !CPU_CORTEX_M1 - help - This option signifies the CPU has the VTOR register. - The VTOR indicates the offset of the vector table base - address from memory address 0x00000000. Always present - in CPUs implementing the ARMv7-M or ARMv8-M architectures. - Optional in CPUs implementing ARMv6-M, ARMv8-M Baseline - architectures (except for Cortex-M0/M1, where it is never - implemented). - -config CPU_CORTEX_M_HAS_SPLIM - bool - depends on ARMV8_M_MAINLINE || (ARMV8_M_SE && !ARM_NONSECURE_FIRMWARE) - help - This option signifies the CPU has the MSPLIM, PSPLIM registers. - - The stack pointer limit registers, MSPLIM, PSPLIM, limit the - extend to which the Main and Process Stack Pointers, respectively, - can descend. MSPLIM, PSPLIM are always present in ARMv8-M - MCUs that implement the ARMv8-M Main Extension (Mainline). - - In an ARMv8-M Mainline implementation with the Security Extension - the MSPLIM, PSPLIM registers have additional Secure instances. - In an ARMv8-M Baseline implementation with the Security Extension - the MSPLIM, PSPLIM registers have only Secure instances. - -config CPU_CORTEX_M_HAS_PROGRAMMABLE_FAULT_PRIOS - bool - depends on ARMV7_M_ARMV8_M_MAINLINE - help - This option signifies the CPU may trigger system faults - (other than HardFault) with configurable priority, and, - therefore, it needs to reserve a priority level for them. - -config CPU_CORTEX_M0_HAS_VECTOR_TABLE_REMAP - bool - depends on ARMV6_M_ARMV8_M_BASELINE - help - This option signifies the Cortex-M0 has some mechanisms that can map - the vector table to SRAM - -config CPU_CORTEX_M_HAS_CMSE - bool - depends on ARMV8_M_BASELINE || ARMV8_M_MAINLINE - help - This option signifies the Cortex-M CPU has the CMSE intrinsics. - -config ARMV6_M_ARMV8_M_BASELINE - bool - select ATOMIC_OPERATIONS_C - select ISA_THUMB2 - help - This option signifies the use of an ARMv6-M processor - implementation, or the use of an ARMv8-M processor - supporting the Baseline implementation. - - Notes: - - A Processing Element (PE) without the Main Extension - is also referred to as a Baseline Implementation. A - Baseline implementation has a subset of the instructions, - registers, and features, of a Mainline implementation. - - ARMv6-M compatibility is provided by all ARMv8-M - implementations. - -config ARMV8_M_BASELINE - bool - select ARMV6_M_ARMV8_M_BASELINE - select CPU_CORTEX_M_HAS_CMSE - help - This option signifies the use of an ARMv8-M processor - implementation. - - ARMv8-M Baseline includes additional features - not present in the ARMv6-M architecture. - -config ARMV7_M_ARMV8_M_MAINLINE - bool - select ATOMIC_OPERATIONS_BUILTIN - select ISA_THUMB2 - select CPU_CORTEX_M_HAS_BASEPRI - select CPU_CORTEX_M_HAS_VTOR - select CPU_CORTEX_M_HAS_PROGRAMMABLE_FAULT_PRIOS - select CPU_CORTEX_M_HAS_SYSTICK - help - This option signifies the use of an ARMv7-M processor - implementation, or the use of a backwards-compatible - ARMv8-M processor implementation supporting the Main - Extension. - - Notes: - - A Processing Element (PE) with the Main Extension is also - referred to as a Mainline Implementation. - - ARMv7-M compatibility requires the Main Extension. - - From https://developer.arm.com/products/architecture/m-profile: - The Main Extension provides backwards compatibility - with ARMv7-M. - -config ARMV8_M_MAINLINE - bool - select ARMV7_M_ARMV8_M_MAINLINE - select CPU_CORTEX_M_HAS_SPLIM - select CPU_CORTEX_M_HAS_CMSE - help - This option signifies the use of an ARMv8-M processor - implementation, supporting the Main Extension. - - ARMv8-M Main Extension includes additional features - not present in the ARMv7-M architecture. - -config ARMV8_1_M_MAINLINE - bool - select ARMV8_M_MAINLINE - help - This option signifies the use of an ARMv8.1-M processor - implementation, supporting the Main Extension. - - ARMv8.1-M Main Extension includes additional features - not present in the ARMv8-M architecture. - -config ARMV8_M_SE - bool - depends on ARMV8_M_BASELINE || ARMV8_M_MAINLINE - select CPU_CORTEX_M_HAS_SPLIM if !ARM_NONSECURE_FIRMWARE - help - This option signifies the use of an ARMv8-M processor - implementation (Baseline or Mainline) supporting the - Security Extensions. - -config ARMV7_M_ARMV8_M_FP - bool - depends on ARMV7_M_ARMV8_M_MAINLINE && !CPU_CORTEX_M3 - imply FPU_SHARING - help - This option signifies the use of an ARMv7-M processor - implementation, or the use of an ARMv8-M processor - implementation supporting the Floating-Point Extension. - -config ARMV8_M_DSP - bool - depends on ARMV8_M_MAINLINE - help - This option signifies the use of an ARMv8-M processor - implementation supporting the DSP Extension. - -config ARMV8_1_M_MVEI - bool - depends on ARMV8_1_M_MAINLINE - depends on ARMV8_M_DSP - help - This option signifies the use of an ARMv8.1-M processor implementation - supporting the M-Profile Vector Extension (MVE) integer instruction set. - -config ARMV8_1_M_MVEF - bool - depends on ARMV8_1_M_MVEI - help - This option signifies the use of an ARMv8.1-M processor implementation - supporting the M-Profile Vector Extension (MVE) floating-point - instruction set. - -menu "ARM Cortex-M0/M0+/M1/M3/M4/M7/M23/M33 options" - depends on ARMV6_M_ARMV8_M_BASELINE || ARMV7_M_ARMV8_M_MAINLINE - -config GEN_ISR_TABLES - default y - -config ZERO_LATENCY_IRQS - bool "Zero-latency interrupts" - depends on CPU_CORTEX_M_HAS_BASEPRI - help - The kernel may reserve some of the highest interrupts priorities in - the system for its own use. These interrupts will not be masked - by interrupt locking. - When connecting interrupts the kernel will offset all interrupts - to lower priority than those reserved by the kernel. - Zero-latency interrupt can be used to set up an interrupt at the - highest interrupt priority which will not be blocked by interrupt - locking. - Since Zero-latency ISRs will run in the same priority or possibly at - higher priority than the rest of the kernel they cannot use any - kernel functionality. - -config ZERO_LATENCY_LEVELS - int "Number of interrupt priority levels reserved for zero latency" - depends on ZERO_LATENCY_IRQS - range 1 255 - help - The amount of interrupt priority levels reserved for zero latency - interrupts. Increase this value to reserve more than one priority - level for zero latency interrupts. - -config DYNAMIC_DIRECT_INTERRUPTS - bool "Support for dynamic direct interrupts" - depends on DYNAMIC_INTERRUPTS - help - Direct interrupts are designed for performance-critical interrupt - handling and do not go through all of the common interrupt handling - code. This option enables the installation of interrupt service - routines for direct interrupts at runtime. - Note: this requires enabling support for dynamic interrupts in the - kernel. - -config SW_VECTOR_RELAY - bool "Software Vector Relay" - help - When building a bootloader firmware this option adds a - vector table relay handler and a vector relay table, to - relay interrupts based on a vector table pointer. - This is only required but not limited to Cortex-M Baseline CPUs - with no hardware vector table relocation mechanisms (e.g. VTOR). - -config SW_VECTOR_RELAY_CLIENT - bool "Software Vector Relay (client)" - default y if BOOTLOADER_MCUBOOT && !CPU_CORTEX_M0_HAS_VECTOR_TABLE_REMAP - depends on !CPU_CORTEX_M_HAS_VTOR - help - Another image has enabled SW_VECTOR_RELAY, and will be forwarding - exceptions and HW interrupts to this image. Enable this option to make - sure the vector table pointer in RAM is set properly by the image upon - initialization. - -config CORTEX_M_DWT - bool "Data Watchpoint and Trace (DWT)" - depends on CPU_CORTEX_M_HAS_DWT - default y if TIMING_FUNCTIONS - help - Enable and use the Data Watchpoint and Trace (DWT) unit for - timing functions. - -config CORTEX_M_DEBUG_MONITOR_HOOK - bool "Debug monitor interrupt for debugging" - depends on !ARMV6_M_ARMV8_M_BASELINE - help - Enable this option to configure debug monitor exception to low priority - for debugging purposes. - -# enabled, which may increase ESF stacking requirements for -# threads. -config TEST_EXTRA_STACK_SIZE - default 512 if TEST_ARM_CORTEX_M && FPU_SHARING - -config TRAP_UNALIGNED_ACCESS - bool "Unaligned access trap" - depends on !ARMV6_M_ARMV8_M_BASELINE - help - If enabled, the CPU generates a UsageFault exception when executing a - halfword or word access. - -endmenu - -# Implement the null pointer detection using either the Data Watchpoint and -# Trace Unit and the Debug Monitor Exception, or the Memory Protection Unit. - -choice NULL_POINTER_EXCEPTION_DETECTION - bool "Null-pointer exception" - # Disable this until https://github.com/zephyrproject-rtos/zephyr/issues/32984 is fixed - # default NULL_POINTER_EXCEPTION_DETECTION_DWT if TEST_ARM_CORTEX_M && !ARM_NONSECURE_FIRMWARE && CPU_CORTEX_M_HAS_DWT - default NULL_POINTER_EXCEPTION_DETECTION_MPU if TEST_ARM_CORTEX_M && !ARM_NONSECURE_FIRMWARE && ARM_MPU && !CPU_CORTEX_M_HAS_DWT - default NULL_POINTER_EXCEPTION_DETECTION_NONE - help - There are 2 implementations available, one based - on DWT and the other based on MPU. Use this choice - symbol to select one of the options. By default the - feature is disabled. In the test suite the feature - is enabled and the DWT-based solution is preferred. - -config NULL_POINTER_EXCEPTION_DETECTION_NONE - bool "No null pointer exception detection" - help - Null pointer exception detection feature is not - enabled. - -config NULL_POINTER_EXCEPTION_DETECTION_DWT - bool "Use DWT for null pointer exception detection" - depends on CPU_CORTEX_M_HAS_DWT - depends on !TRUSTED_EXECUTION_NONSECURE - select CORTEX_M_DWT - select CORTEX_M_NULL_POINTER_EXCEPTION - help - Null pointer dereference detection implemented - using the DWT unit functionality. - Notes: - - Not enabled for Non-Secure FW images, where - null-pointer dereferencing is likely caught as - a SecureFault. - - Requires DWT functionality in the Cortex-M SoC - implementation (1 comparator for ARMv7-M, 2 comparators - for ARMv8-M). - - Requires the Cortex-M core be in normal mode. - -config NULL_POINTER_EXCEPTION_DETECTION_MPU - bool "Use MPU for null pointer exception detection" - depends on !TRUSTED_EXECUTION_NONSECURE - depends on ARM_MPU - select CORTEX_M_NULL_POINTER_EXCEPTION - help - Null pointer dereference detection implemented - using MPU functionality. - Notes: - - Mutually exclusive to the DWT-based solution - - Not enabled for Non-Secure FW images, where - null-pointer dereferencing is likely caught as - a SecureFault. - - Requires MPU functionality to be present and - enabled. The implementation consumes 1 MPU region. - - In ARMv8-M, explicit null-pointer dereference - detection with MPU requires, additionally, that - the area: [0x0, - CORTEX_M_NULL_POINTER_EXCEPTION_PAGE_SIZE) - is not unmapped (covered by an MPU region already). - If it is unmapped null-pointer dereferencing may - still be indirectly detected (e.g. via a precise - Bus access fault), but this is not guaranteed. A - build-time message warns the user of this scenario. - -endchoice - -config CORTEX_M_NULL_POINTER_EXCEPTION - bool - help - Enable and use the null pointer exception option. - This is a debug feature in Cortex-M, allowing for - detecting null pointer dereferencing (raising a - CPU fault). Supporting the feature results in an - increased code footprint, determined by option - CORTEX_M_NULL_POINTER_EXCEPTION_PAGE_SIZE. - - Note: this hidden option is selected by the choice - symbols corresponding to the DWT-based or to the - MPU-based solution. - -if CORTEX_M_NULL_POINTER_EXCEPTION - -config CORTEX_M_NULL_POINTER_EXCEPTION_PAGE_SIZE - hex "Size of paged unmapped to implement null pointer detection" - default 0x400 - help - Size of the page reserved for detecting null pointer - dereferencing. Must be a power of two. A large value - offers enhanced detection performance to the cost of - wasting a large flash area that code may not use. - -endif # CORTEX_M_NULL_POINTER_EXCEPTION - -rsource "tz/Kconfig" - -endif # CPU_CORTEX_M diff --git a/arch/arm/core/aarch32/cortex_m/thread.c b/arch/arm/core/aarch32/cortex_m/thread.c deleted file mode 100644 index 6ada938f6e1..00000000000 --- a/arch/arm/core/aarch32/cortex_m/thread.c +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2021 Lexmark International, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -bool z_arm_thread_is_in_user_mode(void) -{ - uint32_t value; - - /* return mode information */ - value = __get_CONTROL(); - return (value & CONTROL_nPRIV_Msk) != 0; -} diff --git a/arch/arm/core/aarch32/cpu_idle.S b/arch/arm/core/aarch32/cpu_idle.S deleted file mode 100644 index 95e37917180..00000000000 --- a/arch/arm/core/aarch32/cpu_idle.S +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (c) 2013-2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief ARM Cortex-A, Cortex-M and Cortex-R power management - * - */ - -#include -#include - -#if defined(CONFIG_ARM_ON_EXIT_CPU_IDLE) -#include -#endif - -_ASM_FILE_PROLOGUE - -GTEXT(z_arm_cpu_idle_init) -GTEXT(arch_cpu_idle) -GTEXT(arch_cpu_atomic_idle) - -#if defined(CONFIG_CPU_CORTEX_M) -#define _SCB_SCR 0xE000ED10 - -#define _SCB_SCR_SEVONPEND (1 << 4) -#define _SCB_SCR_SLEEPDEEP (1 << 2) -#define _SCB_SCR_SLEEPONEXIT (1 << 1) -#define _SCR_INIT_BITS _SCB_SCR_SEVONPEND -#endif - -/** - * - * @brief Initialization of CPU idle - * - * Only called by arch_kernel_init(). Sets SEVONPEND bit once for the system's - * duration. - * - * C function prototype: - * - * void z_arm_cpu_idle_init(void); - */ - -SECTION_FUNC(TEXT, z_arm_cpu_idle_init) -#if defined(CONFIG_CPU_CORTEX_M) - ldr r1, =_SCB_SCR - movs.n r2, #_SCR_INIT_BITS - str r2, [r1] -#endif - bx lr - -.macro _sleep_if_allowed wait_instruction -#if defined(CONFIG_ARM_ON_ENTER_CPU_IDLE_HOOK) - push {r0, lr} - bl z_arm_on_enter_cpu_idle - /* Skip the wait instruction if on_enter_cpu_idle() returns false. */ - cmp r0, #0 - beq _skip_\@ -#endif /* CONFIG_ARM_ON_ENTER_CPU_IDLE_HOOK */ - - /* - * Wait for all memory transactions to complete before entering low - * power state. - */ - dsb - \wait_instruction - -#if defined(CONFIG_ARM_ON_EXIT_CPU_IDLE) - /* Inline the macro provided by SoC-specific code */ - SOC_ON_EXIT_CPU_IDLE -#endif /* CONFIG_ARM_ON_EXIT_CPU_IDLE */ - -#if defined(CONFIG_ARM_ON_ENTER_CPU_IDLE_HOOK) -_skip_\@: -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) - pop {r0, r1} - mov lr, r1 -#else - pop {r0, lr} -#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ -#endif /* CONFIG_ARM_ON_ENTER_CPU_IDLE_HOOK */ -.endm - -SECTION_FUNC(TEXT, arch_cpu_idle) -#if defined(CONFIG_TRACING) || \ - defined(CONFIG_ARM_ON_ENTER_CPU_IDLE_PREPARE_HOOK) - push {r0, lr} - -#ifdef CONFIG_TRACING - bl sys_trace_idle -#endif -#ifdef CONFIG_ARM_ON_ENTER_CPU_IDLE_PREPARE_HOOK - bl z_arm_on_enter_cpu_idle_prepare -#endif - -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) - pop {r0, r1} - mov lr, r1 -#else - pop {r0, lr} -#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ -#endif - -#if defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - /* - * PRIMASK is always cleared on ARMv7-M and ARMv8-M Mainline (not used - * for interrupt locking), and configuring BASEPRI to the lowest - * priority to ensure wake-up will cause interrupts to be serviced - * before entering low power state. - * - * Set PRIMASK before configuring BASEPRI to prevent interruption - * before wake-up. - */ - cpsid i - - /* - * Set wake-up interrupt priority to the lowest and synchronise to - * ensure that this is visible to the WFI instruction. - */ - eors.n r0, r0 - msr BASEPRI, r0 - isb -#else - /* - * For all the other ARM architectures that do not implement BASEPRI, - * PRIMASK is used as the interrupt locking mechanism, and it is not - * necessary to set PRIMASK here, as PRIMASK would have already been - * set by the caller as part of interrupt locking if necessary - * (i.e. if the caller sets _kernel.idle). - */ -#endif /* CONFIG_ARMV7_M_ARMV8_M_MAINLINE */ - - /* Enter low power state */ - _sleep_if_allowed wfi - - /* - * Clear PRIMASK and flush instruction buffer to immediately service - * the wake-up interrupt. - */ - cpsie i - isb - - bx lr - -SECTION_FUNC(TEXT, arch_cpu_atomic_idle) -#if defined(CONFIG_TRACING) || \ - defined(CONFIG_ARM_ON_ENTER_CPU_IDLE_PREPARE_HOOK) - push {r0, lr} - -#ifdef CONFIG_TRACING - bl sys_trace_idle -#endif -#ifdef CONFIG_ARM_ON_ENTER_CPU_IDLE_PREPARE_HOOK - bl z_arm_on_enter_cpu_idle_prepare -#endif - -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) - pop {r0, r1} - mov lr, r1 -#else - pop {r0, lr} -#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ -#endif - /* - * Lock PRIMASK while sleeping: wfe will still get interrupted by - * incoming interrupts but the CPU will not service them right away. - */ - cpsid i - - /* - * No need to set SEVONPEND, it's set once in z_arm_cpu_idle_init() - * and never touched again. - */ - - /* r0: interrupt mask from caller */ - -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) \ - || defined(CONFIG_ARMV7_R) \ - || defined(CONFIG_AARCH32_ARMV8_R) \ - || defined(CONFIG_ARMV7_A) - /* No BASEPRI, call wfe directly - * (SEVONPEND is set in z_arm_cpu_idle_init()) - */ - _sleep_if_allowed wfe - - cmp r0, #0 - bne _irq_disabled - cpsie i -_irq_disabled: - -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - /* r1: zero, for setting BASEPRI (needs a register) */ - eors.n r1, r1 - - /* unlock BASEPRI so wfe gets interrupted by incoming interrupts */ - msr BASEPRI, r1 - - _sleep_if_allowed wfe - - msr BASEPRI, r0 - cpsie i -#else -#error Unknown ARM architecture -#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ - bx lr diff --git a/arch/arm/core/aarch32/irq_manage.c b/arch/arm/core/aarch32/irq_manage.c deleted file mode 100644 index 6ad5adf7cda..00000000000 --- a/arch/arm/core/aarch32/irq_manage.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright (c) 2013-2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief ARM Cortex-A, Cortex-M and Cortex-R interrupt management - * - * - * Interrupt management: enabling/disabling and dynamic ISR - * connecting/replacing. SW_ISR_TABLE_DYNAMIC has to be enabled for - * connecting ISRs at runtime. - */ - -#include -#include -#if defined(CONFIG_CPU_CORTEX_M) -#include -#elif defined(CONFIG_CPU_AARCH32_CORTEX_A) \ - || defined(CONFIG_CPU_AARCH32_CORTEX_R) -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include - -extern void z_arm_reserved(void); - -#if defined(CONFIG_CPU_CORTEX_M) -#define NUM_IRQS_PER_REG 32 -#define REG_FROM_IRQ(irq) (irq / NUM_IRQS_PER_REG) -#define BIT_FROM_IRQ(irq) (irq % NUM_IRQS_PER_REG) - -void arch_irq_enable(unsigned int irq) -{ - NVIC_EnableIRQ((IRQn_Type)irq); -} - -void arch_irq_disable(unsigned int irq) -{ - NVIC_DisableIRQ((IRQn_Type)irq); -} - -int arch_irq_is_enabled(unsigned int irq) -{ - return NVIC->ISER[REG_FROM_IRQ(irq)] & BIT(BIT_FROM_IRQ(irq)); -} - -/** - * @internal - * - * @brief Set an interrupt's priority - * - * The priority is verified if ASSERT_ON is enabled. The maximum number - * of priority levels is a little complex, as there are some hardware - * priority levels which are reserved. - */ -void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags) -{ - /* The kernel may reserve some of the highest priority levels. - * So we offset the requested priority level with the number - * of priority levels reserved by the kernel. - */ - - /* If we have zero latency interrupts, those interrupts will - * run at a priority level which is not masked by irq_lock(). - * Our policy is to express priority levels with special properties - * via flags - */ - if (IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) && (flags & IRQ_ZERO_LATENCY)) { - if (ZERO_LATENCY_LEVELS == 1) { - prio = _EXC_ZERO_LATENCY_IRQS_PRIO; - } else { - /* Use caller supplied prio level as-is */ - } - } else { - prio += _IRQ_PRIO_OFFSET; - } - - /* The last priority level is also used by PendSV exception, but - * allow other interrupts to use the same level, even if it ends up - * affecting performance (can still be useful on systems with a - * reduced set of priorities, like Cortex-M0/M0+). - */ - __ASSERT(prio <= (BIT(NUM_IRQ_PRIO_BITS) - 1), - "invalid priority %d for %d irq! values must be less than %lu\n", - prio - _IRQ_PRIO_OFFSET, irq, - BIT(NUM_IRQ_PRIO_BITS) - (_IRQ_PRIO_OFFSET)); - NVIC_SetPriority((IRQn_Type)irq, prio); -} - -#elif defined(CONFIG_CPU_AARCH32_CORTEX_A) \ - || defined(CONFIG_CPU_AARCH32_CORTEX_R) -/* - * For Cortex-A and Cortex-R cores, the default interrupt controller is the ARM - * Generic Interrupt Controller (GIC) and therefore the architecture interrupt - * control functions are mapped to the GIC driver interface. - * - * When a custom interrupt controller is used (i.e. - * CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER is enabled), the architecture - * interrupt control functions are mapped to the SoC layer in - * `include/arch/arm/aarch32/irq.h`. - */ - -#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) -void arch_irq_enable(unsigned int irq) -{ - arm_gic_irq_enable(irq); -} - -void arch_irq_disable(unsigned int irq) -{ - arm_gic_irq_disable(irq); -} - -int arch_irq_is_enabled(unsigned int irq) -{ - return arm_gic_irq_is_enabled(irq); -} - -/** - * @internal - * - * @brief Set an interrupt's priority - * - * The priority is verified if ASSERT_ON is enabled. The maximum number - * of priority levels is a little complex, as there are some hardware - * priority levels which are reserved: three for various types of exceptions, - * and possibly one additional to support zero latency interrupts. - */ -void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags) -{ - arm_gic_irq_set_priority(irq, prio, flags); -} -#endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ - -#endif /* CONFIG_CPU_CORTEX_M */ - -void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf); - -/** - * - * @brief Spurious interrupt handler - * - * Installed in all _sw_isr_table slots at boot time. Throws an error if - * called. - * - */ -void z_irq_spurious(const void *unused) -{ - ARG_UNUSED(unused); - - z_arm_fatal_error(K_ERR_SPURIOUS_IRQ, NULL); -} - -#ifdef CONFIG_PM -void _arch_isr_direct_pm(void) -{ -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) \ - || defined(CONFIG_ARMV7_R) \ - || defined(CONFIG_AARCH32_ARMV8_R) \ - || defined(CONFIG_ARMV7_A) - unsigned int key; - - /* irq_lock() does what we want for this CPU */ - key = irq_lock(); -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - /* Lock all interrupts. irq_lock() will on this CPU only disable those - * lower than BASEPRI, which is not what we want. See comments in - * arch/arm/core/aarch32/isr_wrapper.S - */ - __asm__ volatile("cpsid i" : : : "memory"); -#else -#error Unknown ARM architecture -#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ - - if (_kernel.idle) { - _kernel.idle = 0; - z_pm_save_idle_exit(); - } - -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) \ - || defined(CONFIG_ARMV7_R) \ - || defined(CONFIG_AARCH32_ARMV8_R) \ - || defined(CONFIG_ARMV7_A) - irq_unlock(key); -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - __asm__ volatile("cpsie i" : : : "memory"); -#else -#error Unknown ARM architecture -#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ - -} -#endif - -#if defined(CONFIG_ARM_SECURE_FIRMWARE) -/** - * - * @brief Set the target security state for the given IRQ - * - * Function sets the security state (Secure or Non-Secure) targeted - * by the given irq. It requires ARMv8-M MCU. - * It is only compiled if ARM_SECURE_FIRMWARE is defined. - * It should only be called while in Secure state, otherwise, a write attempt - * to NVIC.ITNS register is write-ignored(WI), as the ITNS register is not - * banked between security states and, therefore, has no Non-Secure instance. - * - * It shall return the resulting target state of the given IRQ, indicating - * whether the operation has been performed successfully. - * - * @param irq IRQ line - * @param irq_target_state the desired IRQ target state - * - * @return The resulting target state of the given IRQ - */ -irq_target_state_t irq_target_state_set(unsigned int irq, - irq_target_state_t irq_target_state) -{ - uint32_t result; - - if (irq_target_state == IRQ_TARGET_STATE_SECURE) { - /* Set target to Secure */ - result = NVIC_ClearTargetState(irq); - } else { - /* Set target to Non-Secure */ - result = NVIC_SetTargetState(irq); - } - - if (result) { - return IRQ_TARGET_STATE_NON_SECURE; - } else { - return IRQ_TARGET_STATE_SECURE; - } -} - -/** - * - * @brief Determine whether the given IRQ targets the Secure state - * - * Function determines whether the given irq targets the Secure state - * or not (i.e. targets the Non-Secure state). It requires ARMv8-M MCU. - * It is only compiled if ARM_SECURE_FIRMWARE is defined. - * It should only be called while in Secure state, otherwise, a read attempt - * to NVIC.ITNS register is read-as-zero(RAZ), as the ITNS register is not - * banked between security states and, therefore, has no Non-Secure instance. - * - * @param irq IRQ line - * - * @return 1 if target state is Secure, 0 otherwise. - */ -int irq_target_state_is_secure(unsigned int irq) -{ - return NVIC_GetTargetState(irq) == 0; -} - -/** - * - * @brief Disable and set all interrupt lines to target Non-Secure state. - * - * The function is used to set all HW NVIC interrupt lines to target the - * Non-Secure state. The function shall only be called fron Secure state. - * - * Notes: - * - All NVIC interrupts are disabled before being routed to Non-Secure. - * - Bits corresponding to un-implemented interrupts are RES0, so writes - * will be ignored. - * -*/ -void irq_target_state_set_all_non_secure(void) -{ - int i; - - /* Disable (Clear) all NVIC interrupt lines. */ - for (i = 0; i < sizeof(NVIC->ICER) / sizeof(NVIC->ICER[0]); i++) { - NVIC->ICER[i] = 0xFFFFFFFF; - } - - barrier_dsync_fence_full(); - barrier_isync_fence_full(); - - /* Set all NVIC interrupt lines to target Non-Secure */ - for (i = 0; i < sizeof(NVIC->ITNS) / sizeof(NVIC->ITNS[0]); i++) { - NVIC->ITNS[i] = 0xFFFFFFFF; - } -} - -#endif /* CONFIG_ARM_SECURE_FIRMWARE */ - -#ifdef CONFIG_DYNAMIC_INTERRUPTS -#ifdef CONFIG_GEN_ISR_TABLES -int arch_irq_connect_dynamic(unsigned int irq, unsigned int priority, - void (*routine)(const void *parameter), - const void *parameter, uint32_t flags) -{ - z_isr_install(irq, routine, parameter); - z_arm_irq_priority_set(irq, priority, flags); - return irq; -} -#endif /* CONFIG_GEN_ISR_TABLES */ - -#ifdef CONFIG_DYNAMIC_DIRECT_INTERRUPTS -static inline void z_arm_irq_dynamic_direct_isr_dispatch(void) -{ - uint32_t irq = __get_IPSR() - 16; - - if (irq < IRQ_TABLE_SIZE) { - struct _isr_table_entry *isr_entry = &_sw_isr_table[irq]; - - isr_entry->isr(isr_entry->arg); - } -} - -ISR_DIRECT_DECLARE(z_arm_irq_direct_dynamic_dispatch_reschedule) -{ - z_arm_irq_dynamic_direct_isr_dispatch(); - - return 1; -} - -ISR_DIRECT_DECLARE(z_arm_irq_direct_dynamic_dispatch_no_reschedule) -{ - z_arm_irq_dynamic_direct_isr_dispatch(); - - return 0; -} - -#endif /* CONFIG_DYNAMIC_DIRECT_INTERRUPTS */ - -#endif /* CONFIG_DYNAMIC_INTERRUPTS */ diff --git a/arch/arm/core/aarch32/isr_wrapper.S b/arch/arm/core/aarch32/isr_wrapper.S deleted file mode 100644 index 205420c5dcc..00000000000 --- a/arch/arm/core/aarch32/isr_wrapper.S +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (c) 2013-2014 Wind River Systems, Inc. - * Copyright (c) 2020 Stephanos Ioannidis - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief ARM Cortex-A, Cortex-M and Cortex-R wrapper for ISRs with parameter - * - * Wrapper installed in vector table for handling dynamic interrupts that accept - * a parameter. - */ -/* - * Tell armclang that stack alignment are ensured. - */ -.eabi_attribute Tag_ABI_align_preserved, 1 - -#include -#include -#include -#include -#include - - -_ASM_FILE_PROLOGUE - -GDATA(_sw_isr_table) - -GTEXT(_isr_wrapper) -GTEXT(z_arm_int_exit) - -/** - * - * @brief Wrapper around ISRs when inserted in software ISR table - * - * When inserted in the vector table, _isr_wrapper() demuxes the ISR table - * using the running interrupt number as the index, and invokes the registered - * ISR with its corresponding argument. When returning from the ISR, it - * determines if a context switch needs to happen (see documentation for - * z_arm_pendsv()) and pends the PendSV exception if so: the latter will - * perform the context switch itself. - * - */ -SECTION_FUNC(TEXT, _isr_wrapper) - -#if defined(CONFIG_CPU_CORTEX_M) - push {r0,lr} /* r0, lr are now the first items on the stack */ -#elif defined(CONFIG_CPU_AARCH32_CORTEX_R) || defined(CONFIG_CPU_AARCH32_CORTEX_A) - -#if defined(CONFIG_USERSPACE) - /* See comment below about svc stack usage */ - cps #MODE_SVC - push {r0} - - /* Determine if interrupted thread was in user context */ - cps #MODE_IRQ - mrs r0, spsr - and r0, #MODE_MASK - cmp r0, #MODE_USR - bne isr_system_thread - - ldr r0, =_kernel - ldr r0, [r0, #_kernel_offset_to_current] - - /* Save away user stack pointer */ - cps #MODE_SYS - str sp, [r0, #_thread_offset_to_sp_usr] /* sp_usr */ - - /* Switch to privileged stack */ - ldr sp, [r0, #_thread_offset_to_priv_stack_end] /* priv stack end */ - -isr_system_thread: - cps #MODE_SVC - pop {r0} - cps #MODE_IRQ -#endif - - /* - * Save away r0-r3, r12 and lr_irq for the previous context to the - * process stack since they are clobbered here. Also, save away lr - * and spsr_irq since we may swap processes and return to a different - * thread. - */ - sub lr, lr, #4 - srsdb #MODE_SYS! - cps #MODE_SYS - push {r0-r3, r12, lr} - -#if defined(CONFIG_FPU_SHARING) - sub sp, sp, #___fpu_t_SIZEOF - - /* - * Note that this handler was entered with the VFP unit enabled. - * The undefined instruction handler uses this to know that it - * needs to save the current floating context. - */ - vmrs r0, fpexc - str r0, [sp, #___fpu_t_SIZEOF - 4] - tst r0, #FPEXC_EN - beq _vfp_not_enabled - vmrs r0, fpscr - str r0, [sp, #___fpu_t_SIZEOF - 8] - - /* Disable VFP */ - mov r0, #0 - vmsr fpexc, r0 - -_vfp_not_enabled: - /* - * Mark where to store the floating context for the undefined - * instruction handler - */ - ldr r2, =_kernel - ldr r0, [r2, #_kernel_offset_to_fp_ctx] - cmp r0, #0 - streq sp, [r2, #_kernel_offset_to_fp_ctx] -#endif /* CONFIG_FPU_SHARING */ - - /* - * Use SVC mode stack for predictable interrupt behaviour; running ISRs - * in the SYS/USR mode stack (i.e. interrupted thread stack) leaves the - * ISR stack usage at the mercy of the interrupted thread and this can - * be prone to stack overflows if any of the ISRs and/or preemptible - * threads have high stack usage. - * - * When userspace is enabled, this also prevents leaking privileged - * information to the user mode. - */ - cps #MODE_SVC - - /* - * Preserve lr_svc which may contain the branch return address of the - * interrupted context in case of a nested interrupt. This value will - * be restored prior to exiting the interrupt in z_arm_int_exit. - */ - push {lr} - - /* Align stack at double-word boundary */ - and r3, sp, #4 - sub sp, sp, r3 - push {r2, r3} - - /* Increment interrupt nesting count */ - ldr r2, =_kernel - ldr r0, [r2, #_kernel_offset_to_nested] - add r0, r0, #1 - str r0, [r2, #_kernel_offset_to_nested] -#endif /* CONFIG_CPU_CORTEX_M */ - -#ifdef CONFIG_TRACING_ISR - bl sys_trace_isr_enter -#endif - -#ifdef CONFIG_PM - /* - * All interrupts are disabled when handling idle wakeup. For tickless - * idle, this ensures that the calculation and programming of the - * device for the next timer deadline is not interrupted. For - * non-tickless idle, this ensures that the clearing of the kernel idle - * state is not interrupted. In each case, z_pm_save_idle_exit - * is called with interrupts disabled. - */ - -#if defined(CONFIG_CPU_CORTEX_M) - /* - * Disable interrupts to prevent nesting while exiting idle state. This - * is only necessary for the Cortex-M because it is the only ARM - * architecture variant that automatically enables interrupts when - * entering an ISR. - */ - cpsid i /* PRIMASK = 1 */ -#endif - - /* is this a wakeup from idle ? */ - ldr r2, =_kernel - /* requested idle duration, in ticks */ - ldr r0, [r2, #_kernel_offset_to_idle] - cmp r0, #0 - -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) - beq _idle_state_cleared - movs.n r1, #0 - /* clear kernel idle state */ - str r1, [r2, #_kernel_offset_to_idle] - bl z_pm_save_idle_exit -_idle_state_cleared: - -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - ittt ne - movne r1, #0 - /* clear kernel idle state */ - strne r1, [r2, #_kernel_offset_to_idle] - blne z_pm_save_idle_exit -#elif defined(CONFIG_ARMV7_R) || defined(CONFIG_AARCH32_ARMV8_R) \ - || defined(CONFIG_ARMV7_A) - beq _idle_state_cleared - movs r1, #0 - /* clear kernel idle state */ - str r1, [r2, #_kernel_offset_to_idle] - bl z_pm_save_idle_exit -_idle_state_cleared: -#else -#error Unknown ARM architecture -#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ - -#if defined(CONFIG_CPU_CORTEX_M) - cpsie i /* re-enable interrupts (PRIMASK = 0) */ -#endif - -#endif /* CONFIG_PM */ - -#if defined(CONFIG_CPU_CORTEX_M) - mrs r0, IPSR /* get exception number */ -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) - ldr r1, =16 - subs r0, r1 /* get IRQ number */ - lsls r0, #3 /* table is 8-byte wide */ -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - sub r0, r0, #16 /* get IRQ number */ - lsl r0, r0, #3 /* table is 8-byte wide */ -#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ -#elif defined(CONFIG_CPU_AARCH32_CORTEX_R) || defined(CONFIG_CPU_AARCH32_CORTEX_A) - /* Get active IRQ number from the interrupt controller */ -#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) - bl arm_gic_get_active -#else - bl z_soc_irq_get_active -#endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ - push {r0, r1} - lsl r0, r0, #3 /* table is 8-byte wide */ -#else -#error Unknown ARM architecture -#endif /* CONFIG_CPU_CORTEX_M */ - -#if !defined(CONFIG_CPU_CORTEX_M) - /* - * Enable interrupts to allow nesting. - * - * Note that interrupts are disabled up to this point on the ARM - * architecture variants other than the Cortex-M. It is also important - * to note that that most interrupt controllers require that the nested - * interrupts are handled after the active interrupt is acknowledged; - * this is be done through the `get_active` interrupt controller - * interface function. - */ - cpsie i - - /* - * Skip calling the isr if it is a spurious interrupt. - */ - mov r1, #CONFIG_NUM_IRQS - lsl r1, r1, #3 - cmp r0, r1 - bge spurious_continue -#endif /* !CONFIG_CPU_CORTEX_M */ - - ldr r1, =_sw_isr_table - add r1, r1, r0 /* table entry: ISRs must have their MSB set to stay - * in thumb mode */ - - ldm r1!,{r0,r3} /* arg in r0, ISR in r3 */ - blx r3 /* call ISR */ - -#if defined(CONFIG_CPU_AARCH32_CORTEX_R) || defined(CONFIG_CPU_AARCH32_CORTEX_A) -spurious_continue: - /* Signal end-of-interrupt */ - pop {r0, r1} -#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) - bl arm_gic_eoi -#else - bl z_soc_irq_eoi -#endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ -#endif /* CONFIG_CPU_AARCH32_CORTEX_R || CONFIG_CPU_AARCH32_CORTEX_A */ - -#ifdef CONFIG_TRACING_ISR - bl sys_trace_isr_exit -#endif - -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) - pop {r0, r3} - mov lr, r3 -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - pop {r0, lr} -#elif defined(CONFIG_ARMV7_R) || defined(CONFIG_AARCH32_ARMV8_R) \ - || defined(CONFIG_ARMV7_A) - /* - * r0 and lr_irq were saved on the process stack since a swap could - * happen. exc_exit will handle getting those values back - * from the process stack to return to the correct location - * so there is no need to do anything here. - */ -#else -#error Unknown ARM architecture -#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ - - /* Use 'bx' instead of 'b' because 'bx' can jump further, and use - * 'bx' instead of 'blx' because exception return is done in - * z_arm_int_exit() */ - ldr r1, =z_arm_int_exit - bx r1 diff --git a/arch/arm/core/aarch32/mpu/CMakeLists.txt b/arch/arm/core/aarch32/mpu/CMakeLists.txt deleted file mode 100644 index 8344f4db6df..00000000000 --- a/arch/arm/core/aarch32/mpu/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library() - -zephyr_library_sources( arm_core_mpu.c) -zephyr_library_sources_ifdef(CONFIG_CPU_HAS_ARM_MPU arm_mpu.c) -zephyr_library_sources_ifdef(CONFIG_CPU_HAS_NXP_MPU nxp_mpu.c) - -if (CONFIG_CPU_AARCH32_CORTEX_R) -zephyr_library_include_directories(cortex_a_r) -elseif (CONFIG_CPU_CORTEX_M) -zephyr_library_include_directories(cortex_m) -else () -message(FATAL_ERROR "CPU is not Cortex-A/R/M") -endif () diff --git a/arch/arm/core/aarch32/prep_c.c b/arch/arm/core/aarch32/prep_c.c deleted file mode 100644 index 80765dd7f4f..00000000000 --- a/arch/arm/core/aarch32/prep_c.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright (c) 2013-2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Full C support initialization - * - * - * Initialization of full C support: zero the .bss, copy the .data if XIP, - * call z_cstart(). - * - * Stack is available in this module, but not the global data/bss until their - * initialization is performed. - */ - -#include -#include -#include -#include - -#if !defined(CONFIG_CPU_CORTEX_M) -#include -#endif - -#if defined(CONFIG_ARMV7_R) || defined(CONFIG_ARMV7_A) -#include -#endif - -#if defined(__GNUC__) -/* - * GCC can detect if memcpy is passed a NULL argument, however one of - * the cases of relocate_vector_table() it is valid to pass NULL, so we - * suppress the warning for this case. We need to do this before - * string.h is included to get the declaration of memcpy. - */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wnonnull" -#endif - -#include - -#if defined(CONFIG_SW_VECTOR_RELAY) || defined(CONFIG_SW_VECTOR_RELAY_CLIENT) -Z_GENERIC_SECTION(.vt_pointer_section) __attribute__((used)) -void *_vector_table_pointer; -#endif - -#ifdef CONFIG_CPU_CORTEX_M_HAS_VTOR - -#define VECTOR_ADDRESS ((uintptr_t)_vector_start) - -static inline void relocate_vector_table(void) -{ - SCB->VTOR = VECTOR_ADDRESS & SCB_VTOR_TBLOFF_Msk; - barrier_dsync_fence_full(); - barrier_isync_fence_full(); -} - -#elif defined(CONFIG_AARCH32_ARMV8_R) - -#define VECTOR_ADDRESS ((uintptr_t)_vector_start) - -static inline void relocate_vector_table(void) -{ - write_sctlr(read_sctlr() & ~HIVECS); - write_vbar(VECTOR_ADDRESS & VBAR_MASK); - barrier_isync_fence_full(); -} - -#else -#define VECTOR_ADDRESS 0 - -void __weak relocate_vector_table(void) -{ -#if defined(CONFIG_XIP) && (CONFIG_FLASH_BASE_ADDRESS != 0) || \ - !defined(CONFIG_XIP) && (CONFIG_SRAM_BASE_ADDRESS != 0) -#if !defined(CONFIG_CPU_CORTEX_M) - write_sctlr(read_sctlr() & ~HIVECS); -#endif - size_t vector_size = (size_t)_vector_end - (size_t)_vector_start; - (void)memcpy(VECTOR_ADDRESS, _vector_start, vector_size); -#elif defined(CONFIG_SW_VECTOR_RELAY) || defined(CONFIG_SW_VECTOR_RELAY_CLIENT) - _vector_table_pointer = _vector_start; -#endif -} - -#if defined(__GNUC__) -#pragma GCC diagnostic pop -#endif - -#endif /* CONFIG_CPU_CORTEX_M_HAS_VTOR */ - -#if defined(CONFIG_CPU_HAS_FPU) -#if defined(CONFIG_CPU_CORTEX_M) -static inline void z_arm_floating_point_init(void) -{ - /* - * Upon reset, the Co-Processor Access Control Register is, normally, - * 0x00000000. However, it might be left un-cleared by firmware running - * before Zephyr boot. - */ - SCB->CPACR &= (~(CPACR_CP10_Msk | CPACR_CP11_Msk)); - -#if defined(CONFIG_FPU) - /* - * Enable CP10 and CP11 Co-Processors to enable access to floating - * point registers. - */ -#if defined(CONFIG_USERSPACE) - /* Full access */ - SCB->CPACR |= CPACR_CP10_FULL_ACCESS | CPACR_CP11_FULL_ACCESS; -#else - /* Privileged access only */ - SCB->CPACR |= CPACR_CP10_PRIV_ACCESS | CPACR_CP11_PRIV_ACCESS; -#endif /* CONFIG_USERSPACE */ - /* - * Upon reset, the FPU Context Control Register is 0xC0000000 - * (both Automatic and Lazy state preservation is enabled). - */ -#if defined(CONFIG_MULTITHREADING) && !defined(CONFIG_FPU_SHARING) - /* Unshared FP registers (multithreading) mode. We disable the - * automatic stacking of FP registers (automatic setting of - * FPCA bit in the CONTROL register), upon exception entries, - * as the FP registers are to be used by a single context (and - * the use of FP registers in ISRs is not supported). This - * configuration improves interrupt latency and decreases the - * stack memory requirement for the (single) thread that makes - * use of the FP co-processor. - */ - FPU->FPCCR &= (~(FPU_FPCCR_ASPEN_Msk | FPU_FPCCR_LSPEN_Msk)); -#else - /* - * FP register sharing (multithreading) mode or single-threading mode. - * - * Enable both automatic and lazy state preservation of the FP context. - * The FPCA bit of the CONTROL register will be automatically set, if - * the thread uses the floating point registers. Because of lazy state - * preservation the volatile FP registers will not be stacked upon - * exception entry, however, the required area in the stack frame will - * be reserved for them. This configuration improves interrupt latency. - * The registers will eventually be stacked when the thread is swapped - * out during context-switch or if an ISR attempts to execute floating - * point instructions. - */ - FPU->FPCCR = FPU_FPCCR_ASPEN_Msk | FPU_FPCCR_LSPEN_Msk; -#endif /* CONFIG_FPU_SHARING */ - - /* Make the side-effects of modifying the FPCCR be realized - * immediately. - */ - barrier_dsync_fence_full(); - barrier_isync_fence_full(); - - /* Initialize the Floating Point Status and Control Register. */ -#if defined(CONFIG_ARMV8_1_M_MAINLINE) - /* - * For ARMv8.1-M with FPU, the FPSCR[18:16] LTPSIZE field must be set - * to 0b100 for "Tail predication not applied" as it's reset value - */ - __set_FPSCR(4 << FPU_FPDSCR_LTPSIZE_Pos); -#else - __set_FPSCR(0); -#endif - - /* - * Note: - * The use of the FP register bank is enabled, however the FP context - * will be activated (FPCA bit on the CONTROL register) in the presence - * of floating point instructions. - */ - -#endif /* CONFIG_FPU */ - - /* - * Upon reset, the CONTROL.FPCA bit is, normally, cleared. However, - * it might be left un-cleared by firmware running before Zephyr boot. - * We must clear this bit to prevent errors in exception unstacking. - * - * Note: - * In Sharing FP Registers mode CONTROL.FPCA is cleared before switching - * to main, so it may be skipped here (saving few boot cycles). - * - * If CONFIG_INIT_ARCH_HW_AT_BOOT is set, CONTROL is cleared at reset. - */ -#if (!defined(CONFIG_FPU) || !defined(CONFIG_FPU_SHARING)) && \ - (!defined(CONFIG_INIT_ARCH_HW_AT_BOOT)) - - __set_CONTROL(__get_CONTROL() & (~(CONTROL_FPCA_Msk))); -#endif -} - -#else - -static inline void z_arm_floating_point_init(void) -{ -#if defined(CONFIG_FPU) - uint32_t reg_val = 0; - - /* - * CPACR : Coprocessor Access Control Register -> CP15 1/0/2 - * comp. ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition, - * chap. B4.1.40 - * - * Must be accessed in >= PL1! - * [23..22] = CP11 access control bits, - * [21..20] = CP10 access control bits. - * 11b = Full access as defined for the respective CP, - * 10b = UNDEFINED, - * 01b = Access at PL1 only, - * 00b = No access. - */ - reg_val = __get_CPACR(); - /* Enable PL1 access to CP10, CP11 */ - reg_val |= (CPACR_CP10(CPACR_FA) | CPACR_CP11(CPACR_FA)); - __set_CPACR(reg_val); - barrier_isync_fence_full(); - -#if !defined(CONFIG_FPU_SHARING) - /* - * FPEXC: Floating-Point Exception Control register - * comp. ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition, - * chap. B6.1.38 - * - * Must be accessed in >= PL1! - * [31] EX bit = determines which registers comprise the current state - * of the FPU. The effects of setting this bit to 1 are - * subarchitecture defined. If EX=0, the following - * registers contain the complete current state - * information of the FPU and must therefore be saved - * during a context switch: - * * D0-D15 - * * D16-D31 if implemented - * * FPSCR - * * FPEXC. - * [30] EN bit = Advanced SIMD/Floating Point Extensions enable bit. - * [29..00] = Subarchitecture defined -> not relevant here. - */ - __set_FPEXC(FPEXC_EN); -#endif -#endif -} - -#endif /* CONFIG_CPU_CORTEX_M */ -#endif /* CONFIG_CPU_HAS_FPU */ - -extern FUNC_NORETURN void z_cstart(void); - -/** - * - * @brief Prepare to and run C code - * - * This routine prepares for the execution of and runs C code. - * - */ -void z_arm_prep_c(void) -{ - relocate_vector_table(); -#if defined(CONFIG_CPU_HAS_FPU) - z_arm_floating_point_init(); -#endif - z_bss_zero(); - z_data_copy(); -#if ((defined(CONFIG_ARMV7_R) || defined(CONFIG_ARMV7_A)) && defined(CONFIG_INIT_STACKS)) - z_arm_init_stacks(); -#endif - z_arm_interrupt_init(); - z_cstart(); - CODE_UNREACHABLE; -} diff --git a/arch/arm/core/aarch32/swap.c b/arch/arm/core/aarch32/swap.c deleted file mode 100644 index 525dc53671e..00000000000 --- a/arch/arm/core/aarch32/swap.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2018 Linaro, Limited - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -extern const int _k_neg_eagain; - -/* The 'key' actually represents the BASEPRI register - * prior to disabling interrupts via the BASEPRI mechanism. - * - * arch_swap() itself does not do much. - * - * It simply stores the intlock key (the BASEPRI value) parameter into - * current->basepri, and then triggers a PendSV exception, which does - * the heavy lifting of context switching. - - * This is the only place we have to save BASEPRI since the other paths to - * z_arm_pendsv all come from handling an interrupt, which means we know the - * interrupts were not locked: in that case the BASEPRI value is 0. - * - * Given that arch_swap() is called to effect a cooperative context switch, - * only the caller-saved integer registers need to be saved in the thread of the - * outgoing thread. This is all performed by the hardware, which stores it in - * its exception stack frame, created when handling the z_arm_pendsv exception. - * - * On ARMv6-M, the intlock key is represented by the PRIMASK register, - * as BASEPRI is not available. - */ -int arch_swap(unsigned int key) -{ - /* store off key and return value */ - _current->arch.basepri = key; - _current->arch.swap_return_value = _k_neg_eagain; - -#if defined(CONFIG_CPU_CORTEX_M) - /* set pending bit to make sure we will take a PendSV exception */ - SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; - - /* clear mask or enable all irqs to take a pendsv */ - irq_unlock(0); -#elif defined(CONFIG_CPU_AARCH32_CORTEX_R) || defined(CONFIG_CPU_AARCH32_CORTEX_A) - z_arm_cortex_r_svc(); - irq_unlock(key); -#endif - - /* Context switch is performed here. Returning implies the - * thread has been context-switched-in again. - */ - return _current->arch.swap_return_value; -} diff --git a/arch/arm/core/aarch32/swap_helper.S b/arch/arm/core/aarch32/swap_helper.S deleted file mode 100644 index d125e0d740c..00000000000 --- a/arch/arm/core/aarch32/swap_helper.S +++ /dev/null @@ -1,929 +0,0 @@ -/* - * Copyright (c) 2013-2014 Wind River Systems, Inc. - * Copyright (c) 2017-2019 Nordic Semiconductor ASA. - * Copyright (c) 2020 Stephanos Ioannidis - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Thread context switching for ARM Cortex-M and Cortex-R - * - * This module implements the routines necessary for thread context switching - * on ARM Cortex-A, Cortex-M and Cortex-R CPUs. - */ - -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_CPU_CORTEX_M) -#include -#endif -_ASM_FILE_PROLOGUE - -GTEXT(z_arm_svc) -GTEXT(z_arm_pendsv) -GTEXT(z_do_kernel_oops) -#if defined(CONFIG_USERSPACE) -GTEXT(z_arm_do_syscall) -#endif - -GDATA(_kernel) - -#if defined(CONFIG_THREAD_LOCAL_STORAGE) && defined(CONFIG_CPU_CORTEX_M) -GDATA(z_arm_tls_ptr) -#endif - -/** - * - * @brief PendSV exception handler, handling context switches - * - * The PendSV exception is the only execution context in the system that can - * perform context switching. When an execution context finds out it has to - * switch contexts, it pends the PendSV exception. - * - * When PendSV is pended, the decision that a context switch must happen has - * already been taken. In other words, when z_arm_pendsv() runs, we *know* we - * have to swap *something*. - * - * For Cortex-M, z_arm_pendsv() is invoked with no arguments. - * - * For Cortex-R, PendSV exception is not supported by the architecture and this - * function is directly called either by z_arm_{exc,int}_exit in case of - * preemption, or z_arm_svc in case of cooperative switching. - */ - -SECTION_FUNC(TEXT, z_arm_pendsv) - -#ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING - /* Register the context switch */ - push {r0, lr} - bl z_thread_mark_switched_out -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) - pop {r0, r1} - mov lr, r1 -#else - pop {r0, lr} -#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ -#endif /* CONFIG_INSTRUMENT_THREAD_SWITCHING */ - - /* load _kernel into r1 and current k_thread into r2 */ - ldr r1, =_kernel - ldr r2, [r1, #_kernel_offset_to_current] - -#if defined(CONFIG_ARM_STORE_EXC_RETURN) - /* Store LSB of LR (EXC_RETURN) to the thread's 'mode' word. */ - strb lr, [r2, #_thread_offset_to_mode_exc_return] -#endif - - /* addr of callee-saved regs in thread in r0 */ - ldr r0, =_thread_offset_to_callee_saved - add r0, r2 - - /* save callee-saved + psp in thread */ -#if defined(CONFIG_CPU_CORTEX_M) - mrs ip, PSP -#endif - -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) - /* Store current r4-r7 */ - stmea r0!, {r4-r7} - /* copy r8-r12 into r3-r7 */ - mov r3, r8 - mov r4, r9 - mov r5, r10 - mov r6, r11 - mov r7, ip - /* store r8-12 */ - stmea r0!, {r3-r7} -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - stmia r0, {v1-v8, ip} -#ifdef CONFIG_FPU_SHARING - /* Assess whether switched-out thread had been using the FP registers. */ - tst lr, #_EXC_RETURN_FTYPE_Msk - bne out_fp_endif - - /* FP context active: set FP state and store callee-saved registers. - * Note: if Lazy FP stacking is enabled, storing the callee-saved - * registers will automatically trigger FP state preservation in - * the thread's stack. This will also clear the FPCCR.LSPACT flag. - */ - add r0, r2, #_thread_offset_to_preempt_float - vstmia r0, {s16-s31} - -out_fp_endif: - /* At this point FPCCR.LSPACT is guaranteed to be cleared, - * regardless of whether the thread has an active FP context. - */ -#endif /* CONFIG_FPU_SHARING */ -#elif defined(CONFIG_ARMV7_R) || defined(CONFIG_AARCH32_ARMV8_R) \ - || defined(CONFIG_ARMV7_A) - /* Store rest of process context */ - cps #MODE_SYS - stm r0, {r4-r11, sp} - cps #MODE_SVC - -#if defined(CONFIG_FPU_SHARING) - ldrb r0, [r2, #_thread_offset_to_user_options] - tst r0, #K_FP_REGS /* _current->base.user_options & K_FP_REGS */ - beq out_fp_inactive - - mov ip, #FPEXC_EN - vmsr fpexc, ip - - /* - * If the float context pointer is not null, then the VFP has not been - * used since this thread has used it. Consequently, the caller-saved - * float registers have not been saved away, so write them to the - * exception stack frame. - */ - ldr r0, [r1, #_kernel_offset_to_fp_ctx] - cmp r0, #0 - beq out_store_thread_context - - vstmia r0!, {s0-s15} -#ifdef CONFIG_VFP_FEATURE_REGS_S64_D32 - vstmia r0!, {d16-d31} -#endif - vmrs r3, fpscr - stm r0, {r3, ip} - -out_store_thread_context: - /* Store s16-s31 to thread context */ - add r0, r2, #_thread_offset_to_preempt_float - vstmia r0, {s16-s31} - - mov ip, #0 - vmsr fpexc, ip - -out_fp_inactive: - /* - * The floating context has now been saved to the exception stack - * frame, so zero out the global pointer to note this. - */ - mov r0, #0 - str r0, [r1, #_kernel_offset_to_fp_ctx] -#endif /* CONFIG_FPU_SHARING */ -#else -#error Unknown ARM architecture -#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ - - /* Protect the kernel state while we play with the thread lists */ -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) - cpsid i -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - movs.n r0, #_EXC_IRQ_DEFAULT_PRIO - msr BASEPRI_MAX, r0 - isb /* Make the effect of disabling interrupts be realized immediately */ -#elif defined(CONFIG_ARMV7_R) || defined(CONFIG_AARCH32_ARMV8_R) \ - || defined(CONFIG_ARMV7_A) - /* - * Interrupts are still disabled from arch_swap so empty clause - * here to avoid the preprocessor error below - */ -#else -#error Unknown ARM architecture -#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ - - /* - * Prepare to clear PendSV with interrupts unlocked, but - * don't clear it yet. PendSV must not be cleared until - * the new thread is context-switched in since all decisions - * to pend PendSV have been taken with the current kernel - * state and this is what we're handling currently. - */ -#if defined(CONFIG_CPU_CORTEX_M) - ldr v4, =_SCS_ICSR - ldr v3, =_SCS_ICSR_UNPENDSV -#endif - - /* _kernel is still in r1 */ - - /* fetch the thread to run from the ready queue cache */ - ldr r2, [r1, #_kernel_offset_to_ready_q_cache] - - str r2, [r1, #_kernel_offset_to_current] - - /* - * Clear PendSV so that if another interrupt comes in and - * decides, with the new kernel state based on the new thread - * being context-switched in, that it needs to reschedule, it - * will take, but that previously pended PendSVs do not take, - * since they were based on the previous kernel state and this - * has been handled. - */ - - /* _SCS_ICSR is still in v4 and _SCS_ICSR_UNPENDSV in v3 */ -#if defined(CONFIG_CPU_CORTEX_M) - str v3, [v4, #0] -#endif - -#if defined(CONFIG_THREAD_LOCAL_STORAGE) - /* Grab the TLS pointer */ - ldr r4, =_thread_offset_to_tls - adds r4, r2, r4 - ldr r0, [r4] - -#if defined(CONFIG_CPU_AARCH32_CORTEX_R) || defined(CONFIG_CPU_AARCH32_CORTEX_A) - /* Store TLS pointer in the "Process ID" register. - * This register is used as a base pointer to all - * thread variables with offsets added by toolchain. - */ - mcr 15, 0, r0, cr13, cr0, 3 -#endif - -#if defined(CONFIG_CPU_CORTEX_M) - /* For Cortex-M, store TLS pointer in a global variable, - * as it lacks the process ID or thread ID register - * to be used by toolchain to access thread data. - */ - ldr r4, =z_arm_tls_ptr - str r0, [r4] -#endif - -#endif - -#if defined(CONFIG_ARM_STORE_EXC_RETURN) - /* Restore EXC_RETURN value. */ - ldrsb lr, [r2, #_thread_offset_to_mode_exc_return] -#endif - - /* Restore previous interrupt disable state (irq_lock key) - * (We clear the arch.basepri field after restoring state) - */ -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) && (_thread_offset_to_basepri > 124) - /* Doing it this way since the offset to thread->arch.basepri can in - * some configurations be larger than the maximum of 124 for ldr/str - * immediate offsets. - */ - ldr r4, =_thread_offset_to_basepri - adds r4, r2, r4 - - ldr r0, [r4] - movs.n r3, #0 - str r3, [r4] -#else - ldr r0, [r2, #_thread_offset_to_basepri] - movs r3, #0 - str r3, [r2, #_thread_offset_to_basepri] -#endif - -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) - /* BASEPRI not available, previous interrupt disable state - * maps to PRIMASK. - * - * Only enable interrupts if value is 0, meaning interrupts - * were enabled before irq_lock was called. - */ - cmp r0, #0 - bne _thread_irq_disabled - cpsie i -_thread_irq_disabled: - -#if defined(CONFIG_MPU_STACK_GUARD) || defined(CONFIG_USERSPACE) - /* Re-program dynamic memory map */ - push {r2,lr} - mov r0, r2 - bl z_arm_configure_dynamic_mpu_regions - pop {r2,r3} - mov lr, r3 -#endif - -#ifdef CONFIG_USERSPACE - /* restore mode */ - ldr r3, =_thread_offset_to_mode - adds r3, r2, r3 - ldr r0, [r3] - mrs r3, CONTROL - movs.n r1, #1 - bics r3, r1 - orrs r3, r0 - msr CONTROL, r3 - - /* ISB is not strictly necessary here (stack pointer is not being - * touched), but it's recommended to avoid executing pre-fetched - * instructions with the previous privilege. - */ - isb - -#endif - - ldr r4, =_thread_offset_to_callee_saved - adds r0, r2, r4 - - /* restore r4-r12 for new thread */ - /* first restore r8-r12 located after r4-r7 (4*4bytes) */ - adds r0, #16 - ldmia r0!, {r3-r7} - /* move to correct registers */ - mov r8, r3 - mov r9, r4 - mov r10, r5 - mov r11, r6 - mov ip, r7 - /* restore r4-r7, go back 9*4 bytes to the start of the stored block */ - subs r0, #36 - ldmia r0!, {r4-r7} -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - /* restore BASEPRI for the incoming thread */ - msr BASEPRI, r0 - -#ifdef CONFIG_FPU_SHARING - /* Assess whether switched-in thread had been using the FP registers. */ - tst lr, #_EXC_RETURN_FTYPE_Msk - beq in_fp_active - /* FP context inactive for swapped-in thread: - * - reset FPSCR to 0 - * - set EXC_RETURN.F_Type (prevents FP frame un-stacking when returning - * from pendSV) - */ - movs.n r3, #0 - vmsr fpscr, r3 - b in_fp_endif - -in_fp_active: - /* FP context active: - * - clear EXC_RETURN.F_Type - * - FPSCR and caller-saved registers will be restored automatically - * - restore callee-saved FP registers - */ - add r0, r2, #_thread_offset_to_preempt_float - vldmia r0, {s16-s31} -in_fp_endif: - /* Clear CONTROL.FPCA that may have been set by FP instructions */ - mrs r3, CONTROL - bic r3, #_CONTROL_FPCA_Msk - msr CONTROL, r3 - isb -#endif - -#if defined(CONFIG_MPU_STACK_GUARD) || defined(CONFIG_USERSPACE) - /* Re-program dynamic memory map */ - push {r2,lr} - mov r0, r2 /* _current thread */ - bl z_arm_configure_dynamic_mpu_regions - pop {r2,lr} -#endif - -#ifdef CONFIG_USERSPACE - /* restore mode */ - ldr r0, [r2, #_thread_offset_to_mode] - mrs r3, CONTROL - bic r3, #1 - orr r3, r0 - msr CONTROL, r3 - - /* ISB is not strictly necessary here (stack pointer is not being - * touched), but it's recommended to avoid executing pre-fetched - * instructions with the previous privilege. - */ - isb - -#endif - - /* load callee-saved + psp from thread */ - add r0, r2, #_thread_offset_to_callee_saved - ldmia r0, {v1-v8, ip} -#elif defined(CONFIG_ARMV7_R) || defined(CONFIG_AARCH32_ARMV8_R) \ - || defined(CONFIG_ARMV7_A) -_thread_irq_disabled: - /* load _kernel into r1 and current k_thread into r2 */ - ldr r1, =_kernel - ldr r2, [r1, #_kernel_offset_to_current] - - /* addr of callee-saved regs in thread in r0 */ - ldr r0, =_thread_offset_to_callee_saved - add r0, r2 - - /* restore r4-r11 and sp for incoming thread */ - cps #MODE_SYS - ldm r0, {r4-r11, sp} - cps #MODE_SVC - -#if defined(CONFIG_FPU_SHARING) - ldrb r0, [r2, #_thread_offset_to_user_options] - tst r0, #K_FP_REGS /* _current->base.user_options & K_FP_REGS */ - beq in_fp_inactive - - mov r3, #FPEXC_EN - vmsr fpexc, r3 - - /* Restore s16-s31 from thread context */ - add r0, r2, #_thread_offset_to_preempt_float - vldmia r0, {s16-s31} - - mov r3, #0 - vmsr fpexc, r3 - -in_fp_inactive: -#endif /* CONFIG_FPU_SHARING */ - -#if defined (CONFIG_ARM_MPU) - /* r2 contains k_thread */ - mov r0, r2 - /* Re-program dynamic memory map */ - push {r2, lr} - bl z_arm_configure_dynamic_mpu_regions - pop {r2, lr} -#endif -#else -#error Unknown ARM architecture -#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ - -#if defined(CONFIG_CPU_CORTEX_M) - msr PSP, ip -#endif - -#ifdef CONFIG_BUILTIN_STACK_GUARD - /* r2 contains k_thread */ - add r0, r2, #0 - push {r2, lr} - bl configure_builtin_stack_guard - pop {r2, lr} -#endif /* CONFIG_BUILTIN_STACK_GUARD */ - -#ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING - /* Register the context switch */ - push {r0, lr} - bl z_thread_mark_switched_in -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) - pop {r0, r1} - mov lr, r1 -#else - pop {r0, lr} -#endif -#endif /* CONFIG_INSTRUMENT_THREAD_SWITCHING */ - - /* - * Cortex-M: return from PendSV exception - * Cortex-R: return to the caller (z_arm_{exc,int}_exit, or z_arm_svc) - */ - bx lr - -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) || \ - defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - -/** - * - * @brief Service call handler - * - * The service call (svc) is used in the following occasions: - * - IRQ offloading - * - Kernel run-time exceptions - * - System Calls (User mode) - * - */ -SECTION_FUNC(TEXT, z_arm_svc) - /* Use EXC_RETURN state to find out if stack frame is on the - * MSP or PSP - */ -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) - movs r0, #_EXC_RETURN_SPSEL_Msk - mov r1, lr - tst r1, r0 - beq _stack_frame_msp - mrs r0, PSP - bne _stack_frame_endif -_stack_frame_msp: - mrs r0, MSP -_stack_frame_endif: -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - tst lr, #_EXC_RETURN_SPSEL_Msk /* did we come from thread mode ? */ - ite eq /* if zero (equal), came from handler mode */ - mrseq r0, MSP /* handler mode, stack frame is on MSP */ - mrsne r0, PSP /* thread mode, stack frame is on PSP */ -#endif - - - /* Figure out what SVC call number was invoked */ - - ldr r1, [r0, #24] /* grab address of PC from stack frame */ - /* SVC is a two-byte instruction, point to it and read the - * SVC number (lower byte of SCV instruction) - */ -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) - subs r1, r1, #2 - ldrb r1, [r1] -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - ldrb r1, [r1, #-2] -#endif - - /* - * grab service call number: - * 0: Unused - * 1: irq_offload (if configured) - * 2: kernel panic or oops (software generated fatal exception) - * 3: System call (if user mode supported) - */ -#if defined(CONFIG_USERSPACE) - mrs r2, CONTROL - - cmp r1, #3 - beq _do_syscall - - /* - * check that we are privileged before invoking other SVCs - * oops if we are unprivileged - */ -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) - movs r3, #0x1 - tst r2, r3 -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - tst r2, #0x1 -#endif - bne _oops - -#endif /* CONFIG_USERSPACE */ - - cmp r1, #2 - beq _oops - -#if defined(CONFIG_IRQ_OFFLOAD) - push {r0, lr} - bl z_irq_do_offload /* call C routine which executes the offload */ -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) - pop {r0, r3} - mov lr, r3 -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - pop {r0, lr} -#endif - - /* exception return is done in z_arm_int_exit() */ - b z_arm_int_exit -#endif - -_oops: - push {r0, lr} -#if defined(CONFIG_EXTRA_EXCEPTION_INFO) -#if defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - /* Build _callee_saved_t. To match the struct - * definition we push the psp & then r11-r4 - */ - mrs r1, PSP - push {r1, r2} - push {r4-r11} - mov r1, sp /* pointer to _callee_saved_t */ -#endif /* CONFIG_ARMV7_M_ARMV8_M_MAINLINE */ -#endif /* CONFIG_EXTRA_EXCEPTION_INFO */ - bl z_do_kernel_oops - /* return from SVC exception is done here */ -#if defined(CONFIG_EXTRA_EXCEPTION_INFO) -#if defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - /* We do not need to restore any register state here - * because we did not use any callee-saved registers - * in this routine. Therefore, we can just reset - * the MSP to its value prior to entering the function - */ - add sp, #40 -#endif /* CONFIG_ARMV7_M_ARMV8_M_MAINLINE */ -#endif /* CONFIG_EXTRA_EXCEPTION_INFO */ - pop {r0, pc} - -#if defined(CONFIG_USERSPACE) - /* - * System call will setup a jump to the z_arm_do_syscall() function - * when the SVC returns via the bx lr. - * - * There is some trickery involved here because we have to preserve - * the original PC value so that we can return back to the caller of - * the SVC. - * - * On SVC exeption, the stack looks like the following: - * r0 - r1 - r2 - r3 - r12 - LR - PC - PSR - * - * Registers look like: - * r0 - arg1 - * r1 - arg2 - * r2 - arg3 - * r3 - arg4 - * r4 - arg5 - * r5 - arg6 - * r6 - call_id - * r8 - saved link register - */ -_do_syscall: -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) - movs r3, #24 - ldr r1, [r0, r3] /* grab address of PC from stack frame */ - mov r8, r1 -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - ldr r8, [r0, #24] /* grab address of PC from stack frame */ -#endif - ldr r1, =z_arm_do_syscall -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) - str r1, [r0, r3] /* overwrite the PC to point to z_arm_do_syscall */ -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - str r1, [r0, #24] /* overwrite the PC to point to z_arm_do_syscall */ -#endif - -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) - ldr r3, =K_SYSCALL_LIMIT - cmp r6, r3 -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - /* validate syscall limit */ - ldr ip, =K_SYSCALL_LIMIT - cmp r6, ip -#endif - /* The supplied syscall_id must be lower than the limit - * (Requires unsigned integer comparison) - */ - blo valid_syscall_id - - /* bad syscall id. Set arg1 to bad id and set call_id to SYSCALL_BAD */ - str r6, [r0] - ldr r6, =K_SYSCALL_BAD - - /* Bad syscalls treated as valid syscalls with ID K_SYSCALL_BAD. */ - -valid_syscall_id: - ldr r0, =_kernel - ldr r0, [r0, #_kernel_offset_to_current] -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) - mov ip, r2 - ldr r1, =_thread_offset_to_mode - ldr r3, [r0, r1] - movs r2, #1 - bics r3, r2 - /* Store (privileged) mode in thread's mode state variable */ - str r3, [r0, r1] - mov r2, ip - dsb - /* set mode to privileged, r2 still contains value from CONTROL */ - movs r3, #1 - bics r2, r3 -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - ldr r1, [r0, #_thread_offset_to_mode] - bic r1, #1 - /* Store (privileged) mode in thread's mode state variable */ - str r1, [r0, #_thread_offset_to_mode] - dsb - /* set mode to privileged, r2 still contains value from CONTROL */ - bic r2, #1 -#endif - msr CONTROL, r2 - - /* ISB is not strictly necessary here (stack pointer is not being - * touched), but it's recommended to avoid executing pre-fetched - * instructions with the previous privilege. - */ - isb - -#if defined(CONFIG_BUILTIN_STACK_GUARD) - /* Thread is now in privileged mode; after returning from SCVall it - * will use the default (user) stack before switching to the privileged - * stack to execute the system call. We need to protect the user stack - * against stack overflows until this stack transition. - */ - ldr r1, [r0, #_thread_offset_to_stack_info_start] /* stack_info.start */ - msr PSPLIM, r1 -#endif /* CONFIG_BUILTIN_STACK_GUARD */ - - /* return from SVC to the modified LR - z_arm_do_syscall */ - bx lr -#endif /* CONFIG_USERSPACE */ - -#elif defined(CONFIG_ARMV7_R) || defined(CONFIG_AARCH32_ARMV8_R) \ - || defined(CONFIG_ARMV7_A) - -#if defined(CONFIG_FPU_SHARING) -#define FPU_SF_SIZE ___fpu_t_SIZEOF -#else -#define FPU_SF_SIZE 0 -#endif - -/** - * - * @brief Service call handler - * - * The service call (svc) is used in the following occasions: - * - Cooperative context switching - * - IRQ offloading - * - Kernel run-time exceptions - * - */ -SECTION_FUNC(TEXT, z_arm_svc) -#if defined(CONFIG_USERSPACE) - /* Determine if incoming thread was in user context */ - push {r0} - mrs r0, spsr - and r0, #MODE_MASK - cmp r0, #MODE_USR - bne svc_system_thread - - ldr r0, =_kernel - ldr r0, [r0, #_kernel_offset_to_current] - - /* Save away user stack pointer */ - cps #MODE_SYS - str sp, [r0, #_thread_offset_to_sp_usr] /* sp_usr */ - - /* Switch to privileged stack */ - ldr sp, [r0, #_thread_offset_to_priv_stack_end] /* priv stack end */ - cps #MODE_SVC - -svc_system_thread: - pop {r0} -#endif - - /* - * Switch to system mode to store r0-r3 to the process stack pointer. - * Save r12 and the lr as we could be swapping in another process and - * returning to a different location. - */ - srsdb #MODE_SYS! - cps #MODE_SYS - push {r0-r3, r12, lr} - -#if defined(CONFIG_FPU_SHARING) - sub sp, sp, #___fpu_t_SIZEOF - - /* - * Note that this handler was entered with the VFP unit enabled. - * The undefined instruction handler uses this to know that it - * needs to save the current floating context. - */ - vmrs r0, fpexc - str r0, [sp, #___fpu_t_SIZEOF - 4] - tst r0, #FPEXC_EN - beq _vfp_not_enabled - vmrs r0, fpscr - str r0, [sp, #___fpu_t_SIZEOF - 8] - - /* Disable VFP */ - mov r0, #0 - vmsr fpexc, r0 - -_vfp_not_enabled: - /* - * Mark where to store the floating context for the undefined - * instruction handler - */ - ldr r2, =_kernel - ldr r0, [r2, #_kernel_offset_to_fp_ctx] - cmp r0, #0 - streq sp, [r2, #_kernel_offset_to_fp_ctx] -#endif /* CONFIG_FPU_SHARING */ - - mov ip, sp - - cps #MODE_SVC - - /* - * Store lr_svc to the SVC mode stack. This value will be restored prior to - * exiting the SVC call in z_arm_int_exit. - */ - push {lr} - - /* Align stack at double-word boundary */ - and r3, sp, #4 - sub sp, sp, r3 - push {r2, r3} - - /* Increment interrupt nesting count */ - ldr r2, =_kernel - ldr r0, [r2, #_kernel_offset_to_nested] - add r0, r0, #1 - str r0, [r2, #_kernel_offset_to_nested] - - /* Get SVC number */ - mrs r0, spsr - tst r0, #0x20 - - ldreq r1, [lr, #-4] - biceq r1, #0xff000000 - beq demux - - ldr r1, [lr, #-2] - and r1, #0xff - - /* - * grab service call number: - * 0: context switch - * 1: irq_offload (if configured) - * 2: kernel panic or oops (software generated fatal exception) - * 3: system calls for memory protection - */ -demux: - -#if defined(CONFIG_USERSPACE) - cmp r1, #_SVC_CALL_SYSTEM_CALL - beq _do_syscall -#endif - - cmp r1, #_SVC_CALL_CONTEXT_SWITCH - beq _context_switch - - cmp r1, #_SVC_CALL_RUNTIME_EXCEPT - beq _oops - -#if CONFIG_IRQ_OFFLOAD - blx z_irq_do_offload /* call C routine which executes the offload */ - - /* exception return is done in z_arm_int_exit() */ - b z_arm_int_exit -#endif - -_context_switch: - /* handler mode exit, to PendSV */ - bl z_arm_pendsv - - b z_arm_int_exit - -_oops: - /* - * Pass the exception frame to z_do_kernel_oops. r0 contains the - * exception reason. - */ - cps #MODE_SYS - mov r0, sp - cps #MODE_SVC - bl z_do_kernel_oops - b z_arm_int_exit - -#if defined(CONFIG_USERSPACE) - /* - * System call will setup a jump to the _do_arm_syscall function - * running in system mode when returning from the exception. - * - * There is some trickery involved here because we have to preserve - * the original PC value so that we can return back to the caller of - * the SVC. - * - * On SVC exception, the USER/SYSTEM stack looks like the following: - * { possible FPU space } - r0 - r1 - r2 - r3 - r12 - LR - PC - SPSR - * - * Registers look like: - * r0 - arg1 - * r1 - arg2 - * r2 - arg3 - * r3 - arg4 - * r4 - arg5 - * r5 - arg6 - * r6 - call_id - * r8 - saved link register - */ -_do_syscall: - /* grab address of LR from stack frame */ - ldr r8, [ip, #(FPU_SF_SIZE + ___basic_sf_t_pc_OFFSET)] - - /* Make the exception return to system state */ - ldr r1, [ip, #(FPU_SF_SIZE + ___basic_sf_t_xpsr_OFFSET)] - - /* If leaving thumb mode, set the return address to thumb mode */ - tst r1, #T_BIT - orrne r8, #1 - - bic r1, #(MODE_MASK | T_BIT) - orr r1, r1, #MODE_SYS - str r1, [ip, #(FPU_SF_SIZE + ___basic_sf_t_xpsr_OFFSET)] - - /* - * Store the address of z_arm_do_syscall for the exit so the exception - * return goes there in system state. - */ - ldr r1, =z_arm_do_syscall - str r1, [ip, #(FPU_SF_SIZE + ___basic_sf_t_pc_OFFSET)] - - /* validate syscall limit, only set priv mode if valid */ - ldr ip, =K_SYSCALL_LIMIT - cmp r6, ip - blo valid_syscall_id - - /* bad syscall id. Set arg0 to bad id and set call_id to SYSCALL_BAD */ - cps #MODE_SYS - str r6, [sp] - cps #MODE_SVC - ldr r6, =K_SYSCALL_BAD - -valid_syscall_id: - ldr r0, =_kernel - ldr r0, [r0, #_kernel_offset_to_current] - ldr r1, [r0, #_thread_offset_to_mode] - bic r1, #1 - /* Store (privileged) mode in thread's mode state variable */ - str r1, [r0, #_thread_offset_to_mode] - dsb - - /* ISB is not strictly necessary here (stack pointer is not being - * touched), but it's recommended to avoid executing pre-fetched - * instructions with the previous privilege. - */ - isb - - /* Return to _arm_do_syscall in system state. */ - b z_arm_int_exit -#endif - -GTEXT(z_arm_cortex_r_svc) -SECTION_FUNC(TEXT, z_arm_cortex_r_svc) - svc #_SVC_CALL_CONTEXT_SWITCH - bx lr - -#else -#error Unknown ARM architecture -#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ diff --git a/arch/arm/core/aarch32/thread.c b/arch/arm/core/aarch32/thread.c deleted file mode 100644 index 275d085e6f6..00000000000 --- a/arch/arm/core/aarch32/thread.c +++ /dev/null @@ -1,668 +0,0 @@ -/* - * Copyright (c) 2013-2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief New thread creation for ARM Cortex-A, Cortex-M and Cortex-R - * - * Core thread related primitives for the ARM Cortex-A, Cortex-M and - * Cortex-R processor architecture. - */ - -#include -#include -#include -#include - -#if (MPU_GUARD_ALIGN_AND_SIZE_FLOAT > MPU_GUARD_ALIGN_AND_SIZE) -#define FP_GUARD_EXTRA_SIZE (MPU_GUARD_ALIGN_AND_SIZE_FLOAT - \ - MPU_GUARD_ALIGN_AND_SIZE) -#else -#define FP_GUARD_EXTRA_SIZE 0 -#endif - -#ifndef EXC_RETURN_FTYPE -/* bit [4] allocate stack for floating-point context: 0=done 1=skipped */ -#define EXC_RETURN_FTYPE (0x00000010UL) -#endif - -/* Default last octet of EXC_RETURN, for threads that have not run yet. - * The full EXC_RETURN value will be e.g. 0xFFFFFFBC. - */ -#if defined(CONFIG_ARM_NONSECURE_FIRMWARE) -#define DEFAULT_EXC_RETURN 0xBC; -#else -#define DEFAULT_EXC_RETURN 0xFD; -#endif - -#if !defined(CONFIG_MULTITHREADING) && defined(CONFIG_CPU_CORTEX_M) -K_THREAD_STACK_DECLARE(z_main_stack, CONFIG_MAIN_STACK_SIZE); -#endif - -/* An initial context, to be "restored" by z_arm_pendsv(), is put at the other - * end of the stack, and thus reusable by the stack when not needed anymore. - * - * The initial context is an exception stack frame (ESF) since exiting the - * PendSV exception will want to pop an ESF. Interestingly, even if the lsb of - * an instruction address to jump to must always be set since the CPU always - * runs in thumb mode, the ESF expects the real address of the instruction, - * with the lsb *not* set (instructions are always aligned on 16 bit - * halfwords). Since the compiler automatically sets the lsb of function - * addresses, we have to unset it manually before storing it in the 'pc' field - * of the ESF. - */ -void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, - char *stack_ptr, k_thread_entry_t entry, - void *p1, void *p2, void *p3) -{ - struct __basic_sf *iframe; - -#ifdef CONFIG_MPU_STACK_GUARD -#if defined(CONFIG_USERSPACE) - if (z_stack_is_user_capable(stack)) { - /* Guard area is carved-out of the buffer instead of reserved - * for stacks that can host user threads - */ - thread->stack_info.start += MPU_GUARD_ALIGN_AND_SIZE; - thread->stack_info.size -= MPU_GUARD_ALIGN_AND_SIZE; - } -#endif /* CONFIG_USERSPACE */ -#if FP_GUARD_EXTRA_SIZE > 0 - if ((thread->base.user_options & K_FP_REGS) != 0) { - /* Larger guard needed due to lazy stacking of FP regs may - * overshoot the guard area without writing anything. We - * carve it out of the stack buffer as-needed instead of - * unconditionally reserving it. - */ - thread->stack_info.start += FP_GUARD_EXTRA_SIZE; - thread->stack_info.size -= FP_GUARD_EXTRA_SIZE; - } -#endif /* FP_GUARD_EXTRA_SIZE */ -#endif /* CONFIG_MPU_STACK_GUARD */ - - iframe = Z_STACK_PTR_TO_FRAME(struct __basic_sf, stack_ptr); -#if defined(CONFIG_USERSPACE) - if ((thread->base.user_options & K_USER) != 0) { - iframe->pc = (uint32_t)arch_user_mode_enter; - } else { - iframe->pc = (uint32_t)z_thread_entry; - } -#else - iframe->pc = (uint32_t)z_thread_entry; -#endif - -#if defined(CONFIG_CPU_CORTEX_M) - /* force ARM mode by clearing LSB of address */ - iframe->pc &= 0xfffffffe; -#endif - iframe->a1 = (uint32_t)entry; - iframe->a2 = (uint32_t)p1; - iframe->a3 = (uint32_t)p2; - iframe->a4 = (uint32_t)p3; - -#if defined(CONFIG_CPU_CORTEX_M) - iframe->xpsr = - 0x01000000UL; /* clear all, thumb bit is 1, even if RO */ -#else - iframe->xpsr = A_BIT | MODE_SYS; -#if defined(CONFIG_COMPILER_ISA_THUMB2) - iframe->xpsr |= T_BIT; -#endif /* CONFIG_COMPILER_ISA_THUMB2 */ -#endif /* CONFIG_CPU_CORTEX_M */ - -#if !defined(CONFIG_CPU_CORTEX_M) \ - && defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) - iframe = (struct __basic_sf *) - ((uintptr_t)iframe - sizeof(struct __fpu_sf)); - memset(iframe, 0, sizeof(struct __fpu_sf)); -#endif - - thread->callee_saved.psp = (uint32_t)iframe; - thread->arch.basepri = 0; - -#if defined(CONFIG_ARM_STORE_EXC_RETURN) || defined(CONFIG_USERSPACE) - thread->arch.mode = 0; -#if defined(CONFIG_ARM_STORE_EXC_RETURN) - thread->arch.mode_exc_return = DEFAULT_EXC_RETURN; -#endif -#if FP_GUARD_EXTRA_SIZE > 0 - if ((thread->base.user_options & K_FP_REGS) != 0) { - thread->arch.mode |= Z_ARM_MODE_MPU_GUARD_FLOAT_Msk; - } -#endif -#if defined(CONFIG_USERSPACE) - thread->arch.priv_stack_start = 0; -#endif -#endif - /* - * initial values in all other registers/thread entries are - * irrelevant. - */ -} - -#if defined(CONFIG_MPU_STACK_GUARD) && defined(CONFIG_FPU) \ - && defined(CONFIG_FPU_SHARING) - -static inline void z_arm_thread_stack_info_adjust(struct k_thread *thread, - bool use_large_guard) -{ - if (use_large_guard) { - /* Switch to use a large MPU guard if not already. */ - if ((thread->arch.mode & - Z_ARM_MODE_MPU_GUARD_FLOAT_Msk) == 0) { - /* Default guard size is used. Update required. */ - thread->arch.mode |= Z_ARM_MODE_MPU_GUARD_FLOAT_Msk; -#if defined(CONFIG_USERSPACE) - if (thread->arch.priv_stack_start) { - /* User thread */ - thread->arch.priv_stack_start += - FP_GUARD_EXTRA_SIZE; - } else -#endif /* CONFIG_USERSPACE */ - { - /* Privileged thread */ - thread->stack_info.start += - FP_GUARD_EXTRA_SIZE; - thread->stack_info.size -= - FP_GUARD_EXTRA_SIZE; - } - } - } else { - /* Switch to use the default MPU guard size if not already. */ - if ((thread->arch.mode & - Z_ARM_MODE_MPU_GUARD_FLOAT_Msk) != 0) { - /* Large guard size is used. Update required. */ - thread->arch.mode &= ~Z_ARM_MODE_MPU_GUARD_FLOAT_Msk; -#if defined(CONFIG_USERSPACE) - if (thread->arch.priv_stack_start) { - /* User thread */ - thread->arch.priv_stack_start -= - FP_GUARD_EXTRA_SIZE; - } else -#endif /* CONFIG_USERSPACE */ - { - /* Privileged thread */ - thread->stack_info.start -= - FP_GUARD_EXTRA_SIZE; - thread->stack_info.size += - FP_GUARD_EXTRA_SIZE; - } - } - } -} - -/* - * Adjust the MPU stack guard size together with the FPU - * policy and the stack_info values for the thread that is - * being switched in. - */ -uint32_t z_arm_mpu_stack_guard_and_fpu_adjust(struct k_thread *thread) -{ - if (((thread->base.user_options & K_FP_REGS) != 0) || - ((thread->arch.mode_exc_return & EXC_RETURN_FTYPE) == 0)) { - /* The thread has been pre-tagged (at creation or later) with - * K_FP_REGS, i.e. it is expected to be using the FPU registers - * (if not already). Activate lazy stacking and program a large - * MPU guard to safely detect privilege thread stack overflows. - * - * OR - * The thread is not pre-tagged with K_FP_REGS, but it has - * generated an FP context. Activate lazy stacking and - * program a large MPU guard to detect privilege thread - * stack overflows. - */ - FPU->FPCCR |= FPU_FPCCR_LSPEN_Msk; - - z_arm_thread_stack_info_adjust(thread, true); - - /* Tag the thread with K_FP_REGS */ - thread->base.user_options |= K_FP_REGS; - - return MPU_GUARD_ALIGN_AND_SIZE_FLOAT; - } - - /* Thread is not pre-tagged with K_FP_REGS, and it has - * not been using the FPU. Since there is no active FPU - * context, de-activate lazy stacking and program the - * default MPU guard size. - */ - FPU->FPCCR &= (~FPU_FPCCR_LSPEN_Msk); - - z_arm_thread_stack_info_adjust(thread, false); - - return MPU_GUARD_ALIGN_AND_SIZE; -} -#endif - -#ifdef CONFIG_USERSPACE -FUNC_NORETURN void arch_user_mode_enter(k_thread_entry_t user_entry, - void *p1, void *p2, void *p3) -{ - - /* Set up privileged stack before entering user mode */ - _current->arch.priv_stack_start = - (uint32_t)z_priv_stack_find(_current->stack_obj); -#if defined(CONFIG_MPU_STACK_GUARD) -#if defined(CONFIG_THREAD_STACK_INFO) - /* We're dropping to user mode which means the guard area is no - * longer used here, it instead is moved to the privilege stack - * to catch stack overflows there. Un-do the calculations done - * which accounted for memory borrowed from the thread stack. - */ -#if FP_GUARD_EXTRA_SIZE > 0 - if ((_current->arch.mode & Z_ARM_MODE_MPU_GUARD_FLOAT_Msk) != 0) { - _current->stack_info.start -= FP_GUARD_EXTRA_SIZE; - _current->stack_info.size += FP_GUARD_EXTRA_SIZE; - } -#endif /* FP_GUARD_EXTRA_SIZE */ - _current->stack_info.start -= MPU_GUARD_ALIGN_AND_SIZE; - _current->stack_info.size += MPU_GUARD_ALIGN_AND_SIZE; -#endif /* CONFIG_THREAD_STACK_INFO */ - - /* Stack guard area reserved at the bottom of the thread's - * privileged stack. Adjust the available (writable) stack - * buffer area accordingly. - */ -#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) - _current->arch.priv_stack_start += - ((_current->arch.mode & Z_ARM_MODE_MPU_GUARD_FLOAT_Msk) != 0) ? - MPU_GUARD_ALIGN_AND_SIZE_FLOAT : MPU_GUARD_ALIGN_AND_SIZE; -#else - _current->arch.priv_stack_start += MPU_GUARD_ALIGN_AND_SIZE; -#endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ -#endif /* CONFIG_MPU_STACK_GUARD */ - -#if defined(CONFIG_CPU_AARCH32_CORTEX_R) - _current->arch.priv_stack_end = - _current->arch.priv_stack_start + CONFIG_PRIVILEGED_STACK_SIZE; -#endif - - z_arm_userspace_enter(user_entry, p1, p2, p3, - (uint32_t)_current->stack_info.start, - _current->stack_info.size - - _current->stack_info.delta); - CODE_UNREACHABLE; -} - -#endif - -#if defined(CONFIG_BUILTIN_STACK_GUARD) -/* - * @brief Configure ARM built-in stack guard - * - * This function configures per thread stack guards by reprogramming - * the built-in Process Stack Pointer Limit Register (PSPLIM). - * The functionality is meant to be used during context switch. - * - * @param thread thread info data structure. - */ -void configure_builtin_stack_guard(struct k_thread *thread) -{ -#if defined(CONFIG_USERSPACE) - if ((thread->arch.mode & CONTROL_nPRIV_Msk) != 0) { - /* Only configure stack limit for threads in privileged mode - * (i.e supervisor threads or user threads doing system call). - * User threads executing in user mode do not require a stack - * limit protection. - */ - __set_PSPLIM(0); - return; - } - /* Only configure PSPLIM to guard the privileged stack area, if - * the thread is currently using it, otherwise guard the default - * thread stack. Note that the conditional check relies on the - * thread privileged stack being allocated in higher memory area - * than the default thread stack (ensured by design). - */ - uint32_t guard_start = - ((thread->arch.priv_stack_start) && - (__get_PSP() >= thread->arch.priv_stack_start)) ? - (uint32_t)thread->arch.priv_stack_start : - (uint32_t)thread->stack_obj; - - __ASSERT(thread->stack_info.start == ((uint32_t)thread->stack_obj), - "stack_info.start does not point to the start of the" - "thread allocated area."); -#else - uint32_t guard_start = thread->stack_info.start; -#endif -#if defined(CONFIG_CPU_CORTEX_M_HAS_SPLIM) - __set_PSPLIM(guard_start); -#else -#error "Built-in PSP limit checks not supported by HW" -#endif -} -#endif /* CONFIG_BUILTIN_STACK_GUARD */ - -#if defined(CONFIG_MPU_STACK_GUARD) || defined(CONFIG_USERSPACE) - -#define IS_MPU_GUARD_VIOLATION(guard_start, guard_len, fault_addr, stack_ptr) \ - ((fault_addr != -EINVAL) ? \ - ((fault_addr >= guard_start) && \ - (fault_addr < (guard_start + guard_len)) && \ - (stack_ptr < (guard_start + guard_len))) \ - : \ - (stack_ptr < (guard_start + guard_len))) - -/** - * @brief Assess occurrence of current thread's stack corruption - * - * This function performs an assessment whether a memory fault (on a - * given memory address) is the result of stack memory corruption of - * the current thread. - * - * Thread stack corruption for supervisor threads or user threads in - * privilege mode (when User Space is supported) is reported upon an - * attempt to access the stack guard area (if MPU Stack Guard feature - * is supported). Additionally the current PSP (process stack pointer) - * must be pointing inside or below the guard area. - * - * Thread stack corruption for user threads in user mode is reported, - * if the current PSP is pointing below the start of the current - * thread's stack. - * - * Notes: - * - we assume a fully descending stack, - * - we assume a stacking error has occurred, - * - the function shall be called when handling MemManage and Bus fault, - * and only if a Stacking error has been reported. - * - * If stack corruption is detected, the function returns the lowest - * allowed address where the Stack Pointer can safely point to, to - * prevent from errors when un-stacking the corrupted stack frame - * upon exception return. - * - * @param fault_addr memory address on which memory access violation - * has been reported. It can be invalid (-EINVAL), - * if only Stacking error has been reported. - * @param psp current address the PSP points to - * - * @return The lowest allowed stack frame pointer, if error is a - * thread stack corruption, otherwise return 0. - */ -uint32_t z_check_thread_stack_fail(const uint32_t fault_addr, const uint32_t psp) -{ -#if defined(CONFIG_MULTITHREADING) - const struct k_thread *thread = _current; - - if (thread == NULL) { - return 0; - } -#endif - -#if (defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)) && \ - defined(CONFIG_MPU_STACK_GUARD) - uint32_t guard_len = - ((_current->arch.mode & Z_ARM_MODE_MPU_GUARD_FLOAT_Msk) != 0) ? - MPU_GUARD_ALIGN_AND_SIZE_FLOAT : MPU_GUARD_ALIGN_AND_SIZE; -#else - /* If MPU_STACK_GUARD is not enabled, the guard length is - * effectively zero. Stack overflows may be detected only - * for user threads in nPRIV mode. - */ - uint32_t guard_len = MPU_GUARD_ALIGN_AND_SIZE; -#endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ - -#if defined(CONFIG_USERSPACE) - if (thread->arch.priv_stack_start) { - /* User thread */ - if (z_arm_thread_is_in_user_mode() == false) { - /* User thread in privilege mode */ - if (IS_MPU_GUARD_VIOLATION( - thread->arch.priv_stack_start - guard_len, - guard_len, - fault_addr, psp)) { - /* Thread's privilege stack corruption */ - return thread->arch.priv_stack_start; - } - } else { - if (psp < (uint32_t)thread->stack_obj) { - /* Thread's user stack corruption */ - return (uint32_t)thread->stack_obj; - } - } - } else { - /* Supervisor thread */ - if (IS_MPU_GUARD_VIOLATION(thread->stack_info.start - - guard_len, - guard_len, - fault_addr, psp)) { - /* Supervisor thread stack corruption */ - return thread->stack_info.start; - } - } -#else /* CONFIG_USERSPACE */ -#if defined(CONFIG_MULTITHREADING) - if (IS_MPU_GUARD_VIOLATION(thread->stack_info.start - guard_len, - guard_len, - fault_addr, psp)) { - /* Thread stack corruption */ - return thread->stack_info.start; - } -#else - if (IS_MPU_GUARD_VIOLATION((uint32_t)z_main_stack, - guard_len, - fault_addr, psp)) { - /* Thread stack corruption */ - return (uint32_t)Z_THREAD_STACK_BUFFER(z_main_stack); - } -#endif -#endif /* CONFIG_USERSPACE */ - - return 0; -} -#endif /* CONFIG_MPU_STACK_GUARD || CONFIG_USERSPACE */ - -#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) -int arch_float_disable(struct k_thread *thread) -{ - if (thread != _current) { - return -EINVAL; - } - - if (arch_is_in_isr()) { - return -EINVAL; - } - - /* Disable all floating point capabilities for the thread */ - - /* K_FP_REG flag is used in SWAP and stack check fail. Locking - * interrupts here prevents a possible context-switch or MPU - * fault to take an outdated thread user_options flag into - * account. - */ - int key = arch_irq_lock(); - - thread->base.user_options &= ~K_FP_REGS; - -#if defined(CONFIG_CPU_CORTEX_M) - __set_CONTROL(__get_CONTROL() & (~CONTROL_FPCA_Msk)); -#else - __set_FPEXC(0); -#endif - - /* No need to add an ISB barrier after setting the CONTROL - * register; arch_irq_unlock() already adds one. - */ - - arch_irq_unlock(key); - - return 0; -} - -int arch_float_enable(struct k_thread *thread, unsigned int options) -{ - /* This is not supported in Cortex-M */ - return -ENOTSUP; -} -#endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ - -/* Internal function for Cortex-M initialization, - * applicable to either case of running Zephyr - * with or without multi-threading support. - */ -static void z_arm_prepare_switch_to_main(void) -{ -#if defined(CONFIG_FPU) - /* Initialize the Floating Point Status and Control Register when in - * Unshared FP Registers mode (In Shared FP Registers mode, FPSCR is - * initialized at thread creation for threads that make use of the FP). - */ -#if defined(CONFIG_ARMV8_1_M_MAINLINE) - /* - * For ARMv8.1-M with FPU, the FPSCR[18:16] LTPSIZE field must be set - * to 0b100 for "Tail predication not applied" as it's reset value - */ - __set_FPSCR(4 << FPU_FPDSCR_LTPSIZE_Pos); -#else - __set_FPSCR(0); -#endif -#if defined(CONFIG_CPU_CORTEX_M) && defined(CONFIG_FPU_SHARING) - /* In Sharing mode clearing FPSCR may set the CONTROL.FPCA flag. */ - __set_CONTROL(__get_CONTROL() & (~(CONTROL_FPCA_Msk))); - barrier_isync_fence_full(); -#endif /* CONFIG_FPU_SHARING */ -#endif /* CONFIG_FPU */ -} - -void arch_switch_to_main_thread(struct k_thread *main_thread, char *stack_ptr, - k_thread_entry_t _main) -{ - z_arm_prepare_switch_to_main(); - - _current = main_thread; - -#if defined(CONFIG_THREAD_LOCAL_STORAGE) && defined(CONFIG_CPU_CORTEX_M) - /* On Cortex-M, TLS uses a global variable as pointer to - * the thread local storage area. So this needs to point - * to the main thread's TLS area before switching to any - * thread for the first time, as the pointer is only set - * during context switching. - */ - extern uintptr_t z_arm_tls_ptr; - - z_arm_tls_ptr = main_thread->tls; -#endif - -#ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING - z_thread_mark_switched_in(); -#endif - - /* the ready queue cache already contains the main thread */ - -#if defined(CONFIG_MPU_STACK_GUARD) || defined(CONFIG_USERSPACE) - /* - * If stack protection is enabled, make sure to set it - * before jumping to thread entry function - */ - z_arm_configure_dynamic_mpu_regions(main_thread); -#endif - -#if defined(CONFIG_BUILTIN_STACK_GUARD) - /* Set PSPLIM register for built-in stack guarding of main thread. */ -#if defined(CONFIG_CPU_CORTEX_M_HAS_SPLIM) - __set_PSPLIM(main_thread->stack_info.start); -#else -#error "Built-in PSP limit checks not supported by HW" -#endif -#endif /* CONFIG_BUILTIN_STACK_GUARD */ - - /* - * Set PSP to the highest address of the main stack - * before enabling interrupts and jumping to main. - */ - __asm__ volatile ( - "mov r0, %0\n\t" /* Store _main in R0 */ -#if defined(CONFIG_CPU_CORTEX_M) - "msr PSP, %1\n\t" /* __set_PSP(stack_ptr) */ -#endif - - "movs r1, #0\n\t" -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) \ - || defined(CONFIG_ARMV7_R) \ - || defined(CONFIG_AARCH32_ARMV8_R) \ - || defined(CONFIG_ARMV7_A) - "cpsie i\n\t" /* __enable_irq() */ -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - "cpsie if\n\t" /* __enable_irq(); __enable_fault_irq() */ - "msr BASEPRI, r1\n\t" /* __set_BASEPRI(0) */ -#else -#error Unknown ARM architecture -#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ - "isb\n\t" - "movs r2, #0\n\t" - "movs r3, #0\n\t" - "bl z_thread_entry\n\t" /* z_thread_entry(_main, 0, 0, 0); */ - : - : "r" (_main), "r" (stack_ptr) - : "r0" /* not to be overwritten by msr PSP, %1 */ - ); - - CODE_UNREACHABLE; -} - -#if !defined(CONFIG_MULTITHREADING) && defined(CONFIG_CPU_CORTEX_M) - -FUNC_NORETURN void z_arm_switch_to_main_no_multithreading( - k_thread_entry_t main_entry, void *p1, void *p2, void *p3) -{ - z_arm_prepare_switch_to_main(); - - /* Set PSP to the highest address of the main stack. */ - char *psp = Z_THREAD_STACK_BUFFER(z_main_stack) + - K_THREAD_STACK_SIZEOF(z_main_stack); - -#if defined(CONFIG_BUILTIN_STACK_GUARD) - char *psplim = (Z_THREAD_STACK_BUFFER(z_main_stack)); - /* Clear PSPLIM before setting it to guard the main stack area. */ - __set_PSPLIM(0); -#endif - - /* Store all required input in registers, to be accessible - * after stack pointer change. The function is not going - * to return, so callee-saved registers do not need to be - * stacked. - */ - register void *p1_inreg __asm__("r0") = p1; - register void *p2_inreg __asm__("r1") = p2; - register void *p3_inreg __asm__("r2") = p3; - - __asm__ volatile ( -#ifdef CONFIG_BUILTIN_STACK_GUARD - "msr PSPLIM, %[_psplim]\n\t" -#endif - "msr PSP, %[_psp]\n\t" /* __set_PSP(psp) */ -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) - "cpsie i\n\t" /* enable_irq() */ -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - "cpsie if\n\t" /* __enable_irq(); __enable_fault_irq() */ - "mov r3, #0\n\t" - "msr BASEPRI, r3\n\t" /* __set_BASEPRI(0) */ -#endif - "isb\n\t" - "blx %[_main_entry]\n\t" /* main_entry(p1, p2, p3) */ -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) - "cpsid i\n\t" /* disable_irq() */ -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - "msr BASEPRI, %[basepri]\n\t"/* __set_BASEPRI(_EXC_IRQ_DEFAULT_PRIO) */ - "isb\n\t" -#endif - "loop: b loop\n\t" /* while (true); */ - : - : "r" (p1_inreg), "r" (p2_inreg), "r" (p3_inreg), - [_psp]"r" (psp), [_main_entry]"r" (main_entry) -#if defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - , [basepri] "r" (_EXC_IRQ_DEFAULT_PRIO) -#endif -#ifdef CONFIG_BUILTIN_STACK_GUARD - , [_psplim]"r" (psplim) -#endif - : - ); - - CODE_UNREACHABLE; /* LCOV_EXCL_LINE */ -} -#endif /* !CONFIG_MULTITHREADING && CONFIG_CPU_CORTEX_M */ diff --git a/arch/arm/core/cortex_a_r/CMakeLists.txt b/arch/arm/core/cortex_a_r/CMakeLists.txt new file mode 100644 index 00000000000..d4e18a614f0 --- /dev/null +++ b/arch/arm/core/cortex_a_r/CMakeLists.txt @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources( + exc.S + fault.c + irq_init.c + reboot.c + reset.S + stacks.c + tcm.c + vector_table.S + irq_manage.c + prep_c.c + thread.c + cpu_idle.S + smp.c + ) + +zephyr_library_sources_ifdef(CONFIG_GEN_SW_ISR_TABLE isr_wrapper.S) +zephyr_library_sources_ifdef(CONFIG_USERSPACE thread.c) +zephyr_library_sources_ifdef(CONFIG_SEMIHOST semihost.c) +zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE __aeabi_read_tp.S) +zephyr_library_sources_ifdef(CONFIG_ARCH_CACHE cache.c) +zephyr_library_sources_ifdef(CONFIG_USE_SWITCH switch.S) +zephyr_library_sources_ifndef(CONFIG_USE_SWITCH swap.c swap_helper.S exc_exit.S) diff --git a/arch/arm/core/cortex_a_r/Kconfig b/arch/arm/core/cortex_a_r/Kconfig new file mode 100644 index 00000000000..3ec57cc408e --- /dev/null +++ b/arch/arm/core/cortex_a_r/Kconfig @@ -0,0 +1,194 @@ +# ARM Cortex-A and Cortex-R platform configuration options + +# Copyright (c) 2018 Marvell +# Copyright (c) 2018 Lexmark International, Inc. +# Copyright (c) 2021 Weidmueller Interface GmbH & Co. KG +# +# SPDX-License-Identifier: Apache-2.0 + +# NOTE: We have the specific core implementations first and outside of the +# if CPU_AARCH32_CORTEX_A / if CPU_AARCH32_CORTEX_R block so that SoCs can +# select which core they are using without having to select all the options +# related to that core. Everything else is captured inside the if +# CPU_AARCH32_CORTEX_A / if CPU_AARCH32_CORTEX_R blocks so they are not +# exposed if one selects a different ARM Cortex Family (Cortex-M). + +config CPU_CORTEX_A9 + bool + select CPU_AARCH32_CORTEX_A + select ARMV7_A + help + This option signifies the use of a Cortex-A9 CPU. + +if CPU_AARCH32_CORTEX_A + +config ARMV7_A + bool + select ATOMIC_OPERATIONS_BUILTIN + select ISA_ARM + +config ARMV7_EXCEPTION_STACK_SIZE + int "Undefined Instruction and Abort stack size (in bytes)" + default 256 + help + This option specifies the size of the stack used by the undefined + instruction and data abort exception handlers. + +config ARMV7_FIQ_STACK_SIZE + int "FIQ stack size (in bytes)" + default 256 + help + This option specifies the size of the stack used by the FIQ handler. + +config ARMV7_SVC_STACK_SIZE + int "SVC stack size (in bytes)" + default 512 + help + This option specifies the size of the stack used by the SVC handler. + +config ARMV7_SYS_STACK_SIZE + int "SYS stack size (in bytes)" + default 1024 + help + This option specifies the size of the stack used by the system mode. + +config RUNTIME_NMI + default y + +config GEN_ISR_TABLES + default y + +config GEN_IRQ_VECTOR_TABLE + default n + +config DCACHE_LINE_SIZE + default 32 + +config ICACHE_LINE_SIZE + default 32 + +endif # CPU_AARCH32_CORTEX_A + +config CPU_CORTEX_R4 + bool + select CPU_AARCH32_CORTEX_R + select ARMV7_R + select ARMV7_R_FP if CPU_HAS_FPU + help + This option signifies the use of a Cortex-R4 CPU + +config CPU_CORTEX_R5 + bool + select CPU_AARCH32_CORTEX_R + select ARMV7_R + select ARMV7_R_FP if CPU_HAS_FPU + help + This option signifies the use of a Cortex-R5 CPU + +config CPU_CORTEX_R7 + bool + select CPU_AARCH32_CORTEX_R + select ARMV7_R + select ARMV7_R_FP if CPU_HAS_FPU + help + This option signifies the use of a Cortex-R7 CPU + +config CPU_CORTEX_R52 + bool + select CPU_AARCH32_CORTEX_R + select AARCH32_ARMV8_R + select CPU_HAS_ICACHE + select CPU_HAS_DCACHE + select VFP_SP_D16 if !USE_SWITCH + help + This option signifies the use of a Cortex-R52 CPU + +if CPU_AARCH32_CORTEX_R + +config ARMV7_R + bool + select ATOMIC_OPERATIONS_BUILTIN + select ISA_ARM + select ISA_THUMB2 + help + This option signifies the use of an ARMv7-R processor + implementation. + + From https://developer.arm.com/products/architecture/cpu-architecture/r-profile: + The Armv7-R architecture implements a traditional Arm architecture with + multiple modes and supports a Protected Memory System Architecture + (PMSA) based on a Memory Protection Unit (MPU). It supports the Arm (32) + and Thumb (T32) instruction sets. + +config ARMV7_R_FP + bool + depends on ARMV7_R + help + This option signifies the use of an ARMv7-R processor + implementation supporting the Floating-Point Extension. + +config AARCH32_ARMV8_R + bool + select ATOMIC_OPERATIONS_BUILTIN + select SCHED_IPI_SUPPORTED if SMP + help + This option signifies the use of an ARMv8-R AArch32 processor + implementation. + + From https://developer.arm.com/products/architecture/cpu-architecture/r-profile: + The Armv8-R architecture targets at the Real-time profile. It introduces + virtualization at the highest security level while retaining the + Protected Memory System Architecture (PMSA) based on a Memory Protection + Unit (MPU). It supports the A32 and T32 instruction sets. + +config ARMV7_EXCEPTION_STACK_SIZE + int "Undefined Instruction and Abort stack size (in bytes)" + default 256 + help + This option specifies the size of the stack used by the undefined + instruction and data abort exception handlers. + +config ARMV7_FIQ_STACK_SIZE + int "FIQ stack size (in bytes)" + default 256 + help + This option specifies the size of the stack used by the FIQ handler. + +config ARMV7_SVC_STACK_SIZE + int "SVC stack size (in bytes)" + default 512 + help + This option specifies the size of the stack used by the SVC handler. + +config ARMV7_SYS_STACK_SIZE + int "SYS stack size (in bytes)" + default 1024 + help + This option specifies the size of the stack used by the system mode. + +config RUNTIME_NMI + default y + +config GEN_ISR_TABLES + default y + +config GEN_IRQ_VECTOR_TABLE + default n + +config DISABLE_TCM_ECC + bool "Disable ECC on TCM" + help + This option disables ECC checks on Tightly Coupled Memory. + +config DCACHE_LINE_SIZE + default 64 if CPU_CORTEX_R52 + default 32 + +config ICACHE_LINE_SIZE + default 64 if CPU_CORTEX_R52 + default 32 + +endif # CPU_AARCH32_CORTEX_R + +config TEST_EXTRA_STACK_SIZE + default 1024 if SMP diff --git a/arch/arm/core/cortex_a_r/__aeabi_read_tp.S b/arch/arm/core/cortex_a_r/__aeabi_read_tp.S new file mode 100644 index 00000000000..40874c4a1fa --- /dev/null +++ b/arch/arm/core/cortex_a_r/__aeabi_read_tp.S @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +_ASM_FILE_PROLOGUE + +GTEXT(__aeabi_read_tp) + +SECTION_FUNC(text, __aeabi_read_tp) + /* + * TPIDRURW will be used as a base pointer point to TLS aera. + */ + mrc 15, 0, r0, c13, c0, 2 + bx lr diff --git a/arch/arm/core/cortex_a_r/boot.h b/arch/arm/core/cortex_a_r/boot.h new file mode 100644 index 00000000000..7eeba8b6ada --- /dev/null +++ b/arch/arm/core/cortex_a_r/boot.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Arm Limited (or its affiliates). All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Definitions for boot code + */ + +#ifndef _BOOT_H_ +#define _BOOT_H_ + +#ifndef _ASMLANGUAGE + +extern void *_vector_table[]; +extern void __start(void); + +#endif /* _ASMLANGUAGE */ + +/* Offsets into the boot_params structure */ +#define BOOT_PARAM_MPID_OFFSET 0 +#define BOOT_PARAM_IRQ_SP_OFFSET 4 +#define BOOT_PARAM_FIQ_SP_OFFSET 8 +#define BOOT_PARAM_ABT_SP_OFFSET 12 +#define BOOT_PARAM_UDF_SP_OFFSET 16 +#define BOOT_PARAM_SVC_SP_OFFSET 20 +#define BOOT_PARAM_SYS_SP_OFFSET 24 + +#endif /* _BOOT_H_ */ diff --git a/arch/arm/core/aarch32/cortex_a_r/cache.c b/arch/arm/core/cortex_a_r/cache.c similarity index 100% rename from arch/arm/core/aarch32/cortex_a_r/cache.c rename to arch/arm/core/cortex_a_r/cache.c diff --git a/arch/arm/core/cortex_a_r/cpu_idle.S b/arch/arm/core/cortex_a_r/cpu_idle.S new file mode 100644 index 00000000000..5c6ef3f12ed --- /dev/null +++ b/arch/arm/core/cortex_a_r/cpu_idle.S @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief ARM Cortex-A and Cortex-R power management + * + */ + +#include +#include + +#if defined(CONFIG_ARM_ON_EXIT_CPU_IDLE) +#include +#endif + +_ASM_FILE_PROLOGUE + +GTEXT(arch_cpu_idle) +GTEXT(arch_cpu_atomic_idle) + +.macro _sleep_if_allowed wait_instruction +#if defined(CONFIG_ARM_ON_ENTER_CPU_IDLE_HOOK) + push {r0, lr} + bl z_arm_on_enter_cpu_idle + /* Skip the wait instruction if on_enter_cpu_idle() returns false. */ + cmp r0, #0 + beq _skip_\@ +#endif /* CONFIG_ARM_ON_ENTER_CPU_IDLE_HOOK */ + + /* + * Wait for all memory transactions to complete before entering low + * power state. + */ + dsb + \wait_instruction + +#if defined(CONFIG_ARM_ON_EXIT_CPU_IDLE) + /* Inline the macro provided by SoC-specific code */ + SOC_ON_EXIT_CPU_IDLE +#endif /* CONFIG_ARM_ON_EXIT_CPU_IDLE */ + +#if defined(CONFIG_ARM_ON_ENTER_CPU_IDLE_HOOK) +_skip_\@: + pop {r0, lr} +#endif /* CONFIG_ARM_ON_ENTER_CPU_IDLE_HOOK */ +.endm + +SECTION_FUNC(TEXT, arch_cpu_idle) +#ifdef CONFIG_TRACING + push {r0, lr} + bl sys_trace_idle + pop {r0, lr} +#endif /* CONFIG_TRACING */ + + /* Enter low power state */ + _sleep_if_allowed wfi + + /* + * Clear PRIMASK and flush instruction buffer to immediately service + * the wake-up interrupt. + */ + cpsie i + isb + + bx lr + +SECTION_FUNC(TEXT, arch_cpu_atomic_idle) +#ifdef CONFIG_TRACING + push {r0, lr} + bl sys_trace_idle + pop {r0, lr} +#endif /* CONFIG_TRACING */ + + /* + * Lock PRIMASK while sleeping: wfe will still get interrupted by + * incoming interrupts but the CPU will not service them right away. + */ + cpsid i + + /* r0: interrupt mask from caller */ + + /* No BASEPRI, call wfe directly + */ + _sleep_if_allowed wfe + + cmp r0, #0 + bne _irq_disabled + cpsie i +_irq_disabled: + + bx lr diff --git a/arch/arm/core/aarch32/cortex_a_r/exc.S b/arch/arm/core/cortex_a_r/exc.S similarity index 75% rename from arch/arm/core/aarch32/cortex_a_r/exc.S rename to arch/arm/core/cortex_a_r/exc.S index 87742b39808..78414fcd0a1 100644 --- a/arch/arm/core/aarch32/cortex_a_r/exc.S +++ b/arch/arm/core/cortex_a_r/exc.S @@ -27,6 +27,7 @@ #include #include #include +#include "macro_priv.inc" _ASM_FILE_PROLOGUE @@ -41,6 +42,8 @@ GTEXT(z_arm_undef_instruction) GTEXT(z_arm_prefetch_abort) GTEXT(z_arm_data_abort) +#ifndef CONFIG_USE_SWITCH + .macro exception_entry mode /* * Store r0-r3, r12, lr, lr_und and spsr_und into the stack to @@ -86,10 +89,10 @@ GTEXT(z_arm_data_abort) #endif /* Increment exception nesting count */ - ldr r2, =_kernel - ldr r1, [r2, #_kernel_offset_to_nested] + get_cpu r2 + ldr r1, [r2, #___cpu_t_nested_OFFSET] add r1, r1, #1 - str r1, [r2, #_kernel_offset_to_nested] + str r1, [r2, #___cpu_t_nested_OFFSET] .endm .macro exception_exit @@ -128,10 +131,10 @@ SECTION_SUBSEC_FUNC(TEXT, __exc, z_arm_undef_instruction) sub sp, #24 /* Increment exception nesting count */ - ldr r2, =_kernel - ldr r1, [r2, #_kernel_offset_to_nested] + get_cpu r2 + ldr r1, [r2, #___cpu_t_nested_OFFSET] add r1, r1, #1 - str r1, [r2, #_kernel_offset_to_nested] + str r1, [r2, #___cpu_t_nested_OFFSET] #if defined(CONFIG_FPU_SHARING) sub sp, #___fpu_t_SIZEOF @@ -232,3 +235,59 @@ SECTION_SUBSEC_FUNC(TEXT, __exc, z_arm_data_abort) streq r1, [sp, #24 + FPU_SF_SIZE] b z_arm_exc_exit + +#else +/** + * @brief Undefined instruction exception handler + * + * An undefined instruction (UNDEF) exception is generated when an undefined + * instruction, or a VFP instruction when the VFP is not enabled, is + * encountered. + */ +SECTION_SUBSEC_FUNC(TEXT, __exc, z_arm_undef_instruction) + /* + * The undefined instruction address is offset by 2 if the previous + * mode is Thumb; otherwise, it is offset by 4. + */ + push {r0} + mrs r0, spsr + tst r0, #T_BIT + subeq lr, #4 /* ARM (!T_BIT) */ + subne lr, #2 /* Thumb (T_BIT) */ + pop {r0} + + z_arm_cortex_ar_enter_exc + bl z_arm_fault_undef_instruction + b z_arm_cortex_ar_exit_exc + +/** + * @brief Prefetch abort exception handler + * + * A prefetch abort (PABT) exception is generated when the processor marks the + * prefetched instruction as invalid and the instruction is executed. + */ +SECTION_SUBSEC_FUNC(TEXT, __exc, z_arm_prefetch_abort) + /* + * The faulting instruction address is always offset by 4 for the + * prefetch abort exceptions. + */ + sub lr, #4 + z_arm_cortex_ar_enter_exc + bl z_arm_fault_prefetch + b z_arm_cortex_ar_exit_exc + +/** + * @brief Data abort exception handler + * + * A data abort (DABT) exception is generated when an error occurs on a data + * memory access. This exception can be either synchronous or asynchronous, + * depending on the type of fault that caused it. + */ +SECTION_SUBSEC_FUNC(TEXT, __exc, z_arm_data_abort) + sub lr, #8 + + z_arm_cortex_ar_enter_exc + bl z_arm_fault_data + b z_arm_cortex_ar_exit_exc + +#endif diff --git a/arch/arm/core/aarch32/cortex_a_r/exc_exit.S b/arch/arm/core/cortex_a_r/exc_exit.S similarity index 89% rename from arch/arm/core/aarch32/cortex_a_r/exc_exit.S rename to arch/arm/core/cortex_a_r/exc_exit.S index 5706a390500..499fa17d30a 100644 --- a/arch/arm/core/aarch32/cortex_a_r/exc_exit.S +++ b/arch/arm/core/cortex_a_r/exc_exit.S @@ -18,12 +18,13 @@ #include #include #include +#include "macro_priv.inc" _ASM_FILE_PROLOGUE GTEXT(z_arm_exc_exit) GTEXT(z_arm_int_exit) -GTEXT(z_arm_pendsv) +GTEXT(z_arm_do_swap) GDATA(_kernel) .macro userspace_exc_exit @@ -52,8 +53,8 @@ GDATA(_kernel) bne system_thread_exit\@ /* Restore user stack pointer */ - ldr r0, =_kernel - ldr r0, [r0, #_kernel_offset_to_current] + get_cpu r0 + ldr r0, [r0, #___cpu_t_current_OFFSET] cps #MODE_SYS ldr sp, [r0, #_thread_offset_to_sp_usr] /* sp_usr */ cps #MODE_SVC @@ -68,8 +69,8 @@ system_thread_exit\@: * If the floating point context pointer is null, then a context was * saved so restore the float context from the exception stack frame. */ - ldr r2, =_kernel - ldr r1, [r2, #_kernel_offset_to_fp_ctx] + get_cpu r2 + ldr r1, [r2, #___cpu_t_fp_ctx_OFFSET] cmp r1, #0 beq vfp_restore\@ @@ -79,7 +80,7 @@ system_thread_exit\@: */ cmp r0, #0 moveq r1, #0 - streq r1, [r2, #_kernel_offset_to_fp_ctx] + streq r1, [r2, #___cpu_t_fp_ctx_OFFSET] b vfp_exit\@ vfp_restore\@: @@ -140,23 +141,24 @@ SECTION_SUBSEC_FUNC(TEXT, _HandlerModeExit, z_arm_int_exit) #ifdef CONFIG_PREEMPT_ENABLED /* Do not context switch if exiting a nested interrupt */ - ldr r3, =_kernel - ldr r0, [r3, #_kernel_offset_to_nested] + get_cpu r3 + ldr r0, [r3, #___cpu_t_nested_OFFSET] cmp r0, #1 bhi __EXIT_INT - ldr r1, [r3, #_kernel_offset_to_current] - ldr r0, [r3, #_kernel_offset_to_ready_q_cache] + ldr r1, [r3, #___cpu_t_current_OFFSET] + ldr r2, =_kernel + ldr r0, [r2, #_kernel_offset_to_ready_q_cache] cmp r0, r1 - blne z_arm_pendsv + blne z_arm_do_swap __EXIT_INT: #endif /* CONFIG_PREEMPT_ENABLED */ /* Decrement interrupt nesting count */ - ldr r2, =_kernel - ldr r0, [r2, #_kernel_offset_to_nested] + get_cpu r2 + ldr r0, [r2, #___cpu_t_nested_OFFSET] sub r0, r0, #1 - str r0, [r2, #_kernel_offset_to_nested] + str r0, [r2, #___cpu_t_nested_OFFSET] /* Restore previous stack pointer */ pop {r2, r3} @@ -207,8 +209,8 @@ __EXIT_INT: */ SECTION_SUBSEC_FUNC(TEXT, _HandlerModeExit, z_arm_exc_exit) /* Do not context switch if exiting a nested exception */ - ldr r3, =_kernel - ldr r1, [r3, #_kernel_offset_to_nested] + get_cpu r3 + ldr r1, [r3, #___cpu_t_nested_OFFSET] cmp r1, #1 bhi __EXIT_EXC @@ -231,18 +233,18 @@ SECTION_SUBSEC_FUNC(TEXT, _HandlerModeExit, z_arm_exc_exit) /* * Switch in the next scheduled thread. * - * Note that z_arm_pendsv must be called in the SVC mode because it + * Note that z_arm_do_swap must be called in the SVC mode because it * switches to the SVC mode during context switch and returns to the * caller using lr_svc. */ cps #MODE_SVC - bl z_arm_pendsv + bl z_arm_do_swap /* Decrement exception nesting count */ - ldr r3, =_kernel - ldr r0, [r3, #_kernel_offset_to_nested] + get_cpu r3 + ldr r0, [r3, #___cpu_t_nested_OFFSET] sub r0, r0, #1 - str r0, [r3, #_kernel_offset_to_nested] + str r0, [r3, #___cpu_t_nested_OFFSET] /* Return to the switched thread */ cps #MODE_SYS @@ -255,9 +257,9 @@ SECTION_SUBSEC_FUNC(TEXT, _HandlerModeExit, z_arm_exc_exit) __EXIT_EXC: /* Decrement exception nesting count */ - ldr r0, [r3, #_kernel_offset_to_nested] + ldr r0, [r3, #___cpu_t_nested_OFFSET] sub r0, r0, #1 - str r0, [r3, #_kernel_offset_to_nested] + str r0, [r3, #___cpu_t_nested_OFFSET] #if defined(CONFIG_FPU_SHARING) add sp, sp, #___fpu_t_SIZEOF diff --git a/arch/arm/core/aarch32/cortex_a_r/fault.c b/arch/arm/core/cortex_a_r/fault.c similarity index 97% rename from arch/arm/core/aarch32/cortex_a_r/fault.c rename to arch/arm/core/cortex_a_r/fault.c index 752fe5a95f0..4b1624cd54b 100644 --- a/arch/arm/core/aarch32/cortex_a_r/fault.c +++ b/arch/arm/core/cortex_a_r/fault.c @@ -147,7 +147,7 @@ bool z_arm_fault_undef_instruction_fp(void) __set_FPEXC(FPEXC_EN); - if (_kernel.cpus[0].nested > 1) { + if (_current_cpu->nested > 1) { /* * If the nested count is greater than 1, the undefined * instruction exception came from an irq/svc context. (The @@ -155,12 +155,12 @@ bool z_arm_fault_undef_instruction_fp(void) * the undef exception would increment it to 2). */ struct __fpu_sf *spill_esf = - (struct __fpu_sf *)_kernel.cpus[0].fp_ctx; + (struct __fpu_sf *)_current_cpu->fp_ctx; if (spill_esf == NULL) return false; - _kernel.cpus[0].fp_ctx = NULL; + _current_cpu->fp_ctx = NULL; /* * If the nested count is 2 and the current thread has used the @@ -170,9 +170,9 @@ bool z_arm_fault_undef_instruction_fp(void) * saved exception stack frame, then save the floating point * context because it is about to be overwritten. */ - if (((_kernel.cpus[0].nested == 2) + if (((_current_cpu->nested == 2) && (_current->base.user_options & K_FP_REGS)) - || ((_kernel.cpus[0].nested > 2) + || ((_current_cpu->nested > 2) && (spill_esf->undefined & FPEXC_EN))) { /* * Spill VFP registers to specified exception stack diff --git a/arch/arm/core/aarch32/cortex_a_r/irq_init.c b/arch/arm/core/cortex_a_r/irq_init.c similarity index 100% rename from arch/arm/core/aarch32/cortex_a_r/irq_init.c rename to arch/arm/core/cortex_a_r/irq_init.c diff --git a/arch/arm/core/cortex_a_r/irq_manage.c b/arch/arm/core/cortex_a_r/irq_manage.c new file mode 100644 index 00000000000..a381fad2a48 --- /dev/null +++ b/arch/arm/core/cortex_a_r/irq_manage.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief ARM Cortex-A and Cortex-R interrupt management + * + * + * Interrupt management: enabling/disabling and dynamic ISR + * connecting/replacing. SW_ISR_TABLE_DYNAMIC has to be enabled for + * connecting ISRs at runtime. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void z_arm_reserved(void); + +/* + * For Cortex-A and Cortex-R cores, the default interrupt controller is the ARM + * Generic Interrupt Controller (GIC) and therefore the architecture interrupt + * control functions are mapped to the GIC driver interface. + * + * When a custom interrupt controller is used (i.e. + * CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER is enabled), the architecture + * interrupt control functions are mapped to the SoC layer in + * `include/arch/arm/irq.h`. + */ + +#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) +void arch_irq_enable(unsigned int irq) +{ + arm_gic_irq_enable(irq); +} + +void arch_irq_disable(unsigned int irq) +{ + arm_gic_irq_disable(irq); +} + +int arch_irq_is_enabled(unsigned int irq) +{ + return arm_gic_irq_is_enabled(irq); +} + +/** + * @internal + * + * @brief Set an interrupt's priority + * + * The priority is verified if ASSERT_ON is enabled. The maximum number + * of priority levels is a little complex, as there are some hardware + * priority levels which are reserved: three for various types of exceptions, + * and possibly one additional to support zero latency interrupts. + */ +void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags) +{ + arm_gic_irq_set_priority(irq, prio, flags); +} +#endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ + +void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf); + +/** + * + * @brief Spurious interrupt handler + * + * Installed in all _sw_isr_table slots at boot time. Throws an error if + * called. + * + */ +void z_irq_spurious(const void *unused) +{ + ARG_UNUSED(unused); + + z_arm_fatal_error(K_ERR_SPURIOUS_IRQ, NULL); +} + +#ifdef CONFIG_PM +void _arch_isr_direct_pm(void) +{ + unsigned int key; + + /* irq_lock() does what we want for this CPU */ + key = irq_lock(); + + if (_kernel.idle) { + _kernel.idle = 0; + z_pm_save_idle_exit(); + } + + irq_unlock(key); +} +#endif + +#ifdef CONFIG_DYNAMIC_INTERRUPTS +#ifdef CONFIG_GEN_ISR_TABLES +int arch_irq_connect_dynamic(unsigned int irq, unsigned int priority, + void (*routine)(const void *parameter), + const void *parameter, uint32_t flags) +{ + z_isr_install(irq, routine, parameter); + z_arm_irq_priority_set(irq, priority, flags); + return irq; +} +#endif /* CONFIG_GEN_ISR_TABLES */ + +#ifdef CONFIG_DYNAMIC_DIRECT_INTERRUPTS +static inline void z_arm_irq_dynamic_direct_isr_dispatch(void) +{ + uint32_t irq = __get_IPSR() - 16; + + if (irq < IRQ_TABLE_SIZE) { + struct _isr_table_entry *isr_entry = &_sw_isr_table[irq]; + + isr_entry->isr(isr_entry->arg); + } +} + +ISR_DIRECT_DECLARE(z_arm_irq_direct_dynamic_dispatch_reschedule) +{ + z_arm_irq_dynamic_direct_isr_dispatch(); + + return 1; +} + +ISR_DIRECT_DECLARE(z_arm_irq_direct_dynamic_dispatch_no_reschedule) +{ + z_arm_irq_dynamic_direct_isr_dispatch(); + + return 0; +} + +#endif /* CONFIG_DYNAMIC_DIRECT_INTERRUPTS */ + +#endif /* CONFIG_DYNAMIC_INTERRUPTS */ diff --git a/arch/arm/core/cortex_a_r/isr_wrapper.S b/arch/arm/core/cortex_a_r/isr_wrapper.S new file mode 100644 index 00000000000..0cd30e0a343 --- /dev/null +++ b/arch/arm/core/cortex_a_r/isr_wrapper.S @@ -0,0 +1,373 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * Copyright (c) 2020 Stephanos Ioannidis + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief ARM Cortex-A and Cortex-R wrapper for ISRs with parameter + * + * Wrapper installed in vector table for handling dynamic interrupts that accept + * a parameter. + */ +/* + * Tell armclang that stack alignment are ensured. + */ +.eabi_attribute Tag_ABI_align_preserved, 1 + +#include +#include +#include +#include +#include +#include "macro_priv.inc" + + +_ASM_FILE_PROLOGUE + +GDATA(_sw_isr_table) + +GTEXT(_isr_wrapper) +GTEXT(z_arm_int_exit) + +#ifndef CONFIG_USE_SWITCH +/** + * + * @brief Wrapper around ISRs when inserted in software ISR table + * + * When inserted in the vector table, _isr_wrapper() demuxes the ISR table + * using the running interrupt number as the index, and invokes the registered + * ISR with its corresponding argument. When returning from the ISR, it + * determines if a context switch needs to happen (see documentation for + * z_arm_pendsv()) and pends the PendSV exception if so: the latter will + * perform the context switch itself. + * + */ +SECTION_FUNC(TEXT, _isr_wrapper) + +#if defined(CONFIG_USERSPACE) + /* See comment below about svc stack usage */ + cps #MODE_SVC + push {r0} + + /* Determine if interrupted thread was in user context */ + cps #MODE_IRQ + mrs r0, spsr + and r0, #MODE_MASK + cmp r0, #MODE_USR + bne isr_system_thread + + get_cpu r0 + ldr r0, [r0, #___cpu_t_current_OFFSET] + + /* Save away user stack pointer */ + cps #MODE_SYS + str sp, [r0, #_thread_offset_to_sp_usr] /* sp_usr */ + + /* Switch to privileged stack */ + ldr sp, [r0, #_thread_offset_to_priv_stack_end] /* priv stack end */ + +isr_system_thread: + cps #MODE_SVC + pop {r0} + cps #MODE_IRQ +#endif + + /* + * Save away r0-r3, r12 and lr_irq for the previous context to the + * process stack since they are clobbered here. Also, save away lr + * and spsr_irq since we may swap processes and return to a different + * thread. + */ + sub lr, lr, #4 + srsdb #MODE_SYS! + cps #MODE_SYS + push {r0-r3, r12, lr} + +#if defined(CONFIG_FPU_SHARING) + sub sp, sp, #___fpu_t_SIZEOF + + /* + * Note that this handler was entered with the VFP unit enabled. + * The undefined instruction handler uses this to know that it + * needs to save the current floating context. + */ + vmrs r0, fpexc + str r0, [sp, #___fpu_t_SIZEOF - 4] + tst r0, #FPEXC_EN + beq _vfp_not_enabled + vmrs r0, fpscr + str r0, [sp, #___fpu_t_SIZEOF - 8] + + /* Disable VFP */ + mov r0, #0 + vmsr fpexc, r0 + +_vfp_not_enabled: + /* + * Mark where to store the floating context for the undefined + * instruction handler + */ + get_cpu r2 + ldr r0, [r2, #___cpu_t_fp_ctx_OFFSET] + cmp r0, #0 + streq sp, [r2, #___cpu_t_fp_ctx_OFFSET] +#endif /* CONFIG_FPU_SHARING */ + + /* + * Use SVC mode stack for predictable interrupt behaviour; running ISRs + * in the SYS/USR mode stack (i.e. interrupted thread stack) leaves the + * ISR stack usage at the mercy of the interrupted thread and this can + * be prone to stack overflows if any of the ISRs and/or preemptible + * threads have high stack usage. + * + * When userspace is enabled, this also prevents leaking privileged + * information to the user mode. + */ + cps #MODE_SVC + + /* + * Preserve lr_svc which may contain the branch return address of the + * interrupted context in case of a nested interrupt. This value will + * be restored prior to exiting the interrupt in z_arm_int_exit. + */ + push {lr} + + /* Align stack at double-word boundary */ + and r3, sp, #4 + sub sp, sp, r3 + push {r2, r3} + + /* Increment interrupt nesting count */ + get_cpu r2 + ldr r0, [r2, #___cpu_t_nested_OFFSET] + add r0, r0, #1 + str r0, [r2, #___cpu_t_nested_OFFSET] + +#ifdef CONFIG_TRACING_ISR + bl sys_trace_isr_enter +#endif + +#ifdef CONFIG_PM + /* + * All interrupts are disabled when handling idle wakeup. For tickless + * idle, this ensures that the calculation and programming of the + * device for the next timer deadline is not interrupted. For + * non-tickless idle, this ensures that the clearing of the kernel idle + * state is not interrupted. In each case, z_pm_save_idle_exit + * is called with interrupts disabled. + */ + + /* is this a wakeup from idle ? */ + ldr r2, =_kernel + /* requested idle duration, in ticks */ + ldr r0, [r2, #_kernel_offset_to_idle] + cmp r0, #0 + + beq _idle_state_cleared + movs r1, #0 + /* clear kernel idle state */ + str r1, [r2, #_kernel_offset_to_idle] + bl z_pm_save_idle_exit +_idle_state_cleared: + +#endif /* CONFIG_PM */ + + /* Get active IRQ number from the interrupt controller */ +#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) + bl arm_gic_get_active +#else + bl z_soc_irq_get_active +#endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ + push {r0, r1} + lsl r0, r0, #3 /* table is 8-byte wide */ + + /* + * Enable interrupts to allow nesting. + * + * Note that interrupts are disabled up to this point on the ARM + * architecture variants other than the Cortex-M. It is also important + * to note that that most interrupt controllers require that the nested + * interrupts are handled after the active interrupt is acknowledged; + * this is be done through the `get_active` interrupt controller + * interface function. + */ + cpsie i + + /* + * Skip calling the isr if it is a spurious interrupt. + */ + mov r1, #CONFIG_NUM_IRQS + lsl r1, r1, #3 + cmp r0, r1 + bge spurious_continue + + ldr r1, =_sw_isr_table + add r1, r1, r0 /* table entry: ISRs must have their MSB set to stay + * in thumb mode */ + + ldm r1!,{r0,r3} /* arg in r0, ISR in r3 */ + blx r3 /* call ISR */ + +spurious_continue: + /* Signal end-of-interrupt */ + pop {r0, r1} +#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) + bl arm_gic_eoi +#else + bl z_soc_irq_eoi +#endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ + +#ifdef CONFIG_TRACING_ISR + bl sys_trace_isr_exit +#endif + + /* Use 'bx' instead of 'b' because 'bx' can jump further, and use + * 'bx' instead of 'blx' because exception return is done in + * z_arm_int_exit() */ + ldr r1, =z_arm_int_exit + bx r1 + +#else +/** + * + * @brief Wrapper around ISRs when inserted in software ISR table + * + * When inserted in the vector table, _isr_wrapper() demuxes the ISR table + * using the running interrupt number as the index, and invokes the registered + * ISR with its corresponding argument. When returning from the ISR, it + * determines if a context switch needs to happen and invoke the arch_switch + * function if so. + * + */ +SECTION_FUNC(TEXT, _isr_wrapper) + sub lr, #4 + z_arm_cortex_ar_enter_exc + + /* Increment interrupt nesting count */ + get_cpu r2 + ldr r0, [r2, #___cpu_t_nested_OFFSET] + add r0, #1 + str r0, [r2, #___cpu_t_nested_OFFSET] + + /* If not nested: switch to IRQ stack and save current sp on it. */ + cmp r0, #1 + bhi 1f + mov r0, sp + cps #MODE_IRQ + push {r0} +1: +#ifdef CONFIG_TRACING_ISR + bl sys_trace_isr_enter +#endif /* CONFIG_TRACING_ISR */ + +#ifdef CONFIG_PM + /* + * All interrupts are disabled when handling idle wakeup. For tickless + * idle, this ensures that the calculation and programming of the + * device for the next timer deadline is not interrupted. For + * non-tickless idle, this ensures that the clearing of the kernel idle + * state is not interrupted. In each case, z_pm_save_idle_exit + * is called with interrupts disabled. + */ + + /* is this a wakeup from idle ? */ + ldr r2, =_kernel + /* requested idle duration, in ticks */ + ldr r0, [r2, #_kernel_offset_to_idle] + cmp r0, #0 + + beq _idle_state_cleared + movs r1, #0 + /* clear kernel idle state */ + str r1, [r2, #_kernel_offset_to_idle] + bl z_pm_save_idle_exit +_idle_state_cleared: +#endif /* CONFIG_PM */ + + /* Get active IRQ number from the interrupt controller */ +#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) + bl arm_gic_get_active +#else + bl z_soc_irq_get_active +#endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ + + push {r0, r1} + lsl r0, r0, #3 /* table is 8-byte wide */ + + /* + * Skip calling the isr if it is a spurious interrupt. + */ + mov r1, #CONFIG_NUM_IRQS + lsl r1, r1, #3 + cmp r0, r1 + bge spurious_continue + + ldr r1, =_sw_isr_table + add r1, r1, r0 /* table entry: ISRs must have their MSB set to stay + * in thumb mode */ + ldm r1!,{r0,r3} /* arg in r0, ISR in r3 */ + + /* + * Enable and disable interrupts again to allow nested in exception handlers. + */ + cpsie i + blx r3 /* call ISR */ + cpsid i + +spurious_continue: + /* Signal end-of-interrupt */ + pop {r0, r1} +#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) + bl arm_gic_eoi +#else + bl z_soc_irq_eoi +#endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ + +#ifdef CONFIG_TRACING_ISR + bl sys_trace_isr_exit +#endif + +GTEXT(z_arm_cortex_ar_irq_done) +z_arm_cortex_ar_irq_done: + /* Decrement interrupt nesting count */ + get_cpu r2 + ldr r0, [r2, #___cpu_t_nested_OFFSET] + sub r0, r0, #1 + str r0, [r2, #___cpu_t_nested_OFFSET] + /* Do not context switch if exiting a nested interrupt */ + cmp r0, #0 + bhi __EXIT_INT + + /* retrieve pointer to the current thread */ + pop {r0} + cps #MODE_SYS + mov sp, r0 + + ldr r1, [r2, #___cpu_t_current_OFFSET] + push {r1} + mov r0, #0 + bl z_get_next_switch_handle + + pop {r1} + cmp r0, #0 + beq __EXIT_INT + + /* + * Switch thread + * r0: new thread + * r1: old thread + */ + bl z_arm_context_switch + +__EXIT_INT: + +#ifdef CONFIG_STACK_SENTINEL + bl z_check_stack_sentinel +#endif /* CONFIG_STACK_SENTINEL */ + + b z_arm_cortex_ar_exit_exc + +#endif diff --git a/arch/arm/core/cortex_a_r/macro_priv.inc b/arch/arm/core/cortex_a_r/macro_priv.inc new file mode 100644 index 00000000000..e02433692f9 --- /dev/null +++ b/arch/arm/core/cortex_a_r/macro_priv.inc @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2023 Arm Limited (or its affiliates). All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _MACRO_PRIV_INC_ +#define _MACRO_PRIV_INC_ + +#include + +/* + * Get CPU id + */ + +.macro get_cpu_id rreg0 + /* Read MPIDR register */ + mrc p15, 0, \rreg0, c0, c0, 5 + ubfx \rreg0, \rreg0, #0, #24 +.endm + +.macro get_cpu rreg0 + /* + * Get CPU pointer. + */ + mrc p15, 0, \rreg0, c13, c0, 3 + and \rreg0, #TPIDRURO_CURR_CPU +.endm + +.macro z_arm_cortex_ar_enter_exc + /* + * Store r0-r3, r12, lr into the stack to construct an exception + * stack frame. + */ + srsdb sp!, #MODE_SYS + cps #MODE_SYS + stmdb sp, {r0-r3, r12, lr}^ + sub sp, #24 + + /* TODO: EXTRA_EXCEPTION_INFO */ + mov r0, sp + + /* increment exception depth */ + get_cpu r2 + ldrb r1, [r2, #_cpu_offset_to_exc_depth] + add r1, r1, #1 + strb r1, [r2, #_cpu_offset_to_exc_depth] +.endm + +#endif /* _MACRO_PRIV_INC_ */ diff --git a/arch/arm/core/cortex_a_r/prep_c.c b/arch/arm/core/cortex_a_r/prep_c.c new file mode 100644 index 00000000000..95dbb49cf1e --- /dev/null +++ b/arch/arm/core/cortex_a_r/prep_c.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Full C support initialization + * + * + * Initialization of full C support: zero the .bss, copy the .data if XIP, + * call z_cstart(). + * + * Stack is available in this module, but not the global data/bss until their + * initialization is performed. + */ + +#include +#include +#include +#include +#include + +#if defined(CONFIG_ARMV7_R) || defined(CONFIG_ARMV7_A) +#include +#endif + +#if defined(__GNUC__) +/* + * GCC can detect if memcpy is passed a NULL argument, however one of + * the cases of relocate_vector_table() it is valid to pass NULL, so we + * suppress the warning for this case. We need to do this before + * string.h is included to get the declaration of memcpy. + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnonnull" +#endif + +#include + +#if defined(CONFIG_SW_VECTOR_RELAY) || defined(CONFIG_SW_VECTOR_RELAY_CLIENT) +Z_GENERIC_SECTION(.vt_pointer_section) __attribute__((used)) +void *_vector_table_pointer; +#endif + +#ifdef CONFIG_ARM_MPU +extern void z_arm_mpu_init(void); +extern void z_arm_configure_static_mpu_regions(void); +#elif defined(CONFIG_ARM_AARCH32_MMU) +extern int z_arm_mmu_init(void); +#endif + +#if defined(CONFIG_AARCH32_ARMV8_R) + +#define VECTOR_ADDRESS ((uintptr_t)_vector_start) + +static inline void relocate_vector_table(void) +{ + write_sctlr(read_sctlr() & ~HIVECS); + write_vbar(VECTOR_ADDRESS & VBAR_MASK); + barrier_isync_fence_full(); +} + +#else +#define VECTOR_ADDRESS 0 + +void __weak relocate_vector_table(void) +{ +#if defined(CONFIG_XIP) && (CONFIG_FLASH_BASE_ADDRESS != 0) || \ + !defined(CONFIG_XIP) && (CONFIG_SRAM_BASE_ADDRESS != 0) + write_sctlr(read_sctlr() & ~HIVECS); + size_t vector_size = (size_t)_vector_end - (size_t)_vector_start; + (void)memcpy(VECTOR_ADDRESS, _vector_start, vector_size); +#elif defined(CONFIG_SW_VECTOR_RELAY) || defined(CONFIG_SW_VECTOR_RELAY_CLIENT) + _vector_table_pointer = _vector_start; +#endif +} + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + +#endif /* CONFIG_AARCH32_ARMV8_R */ + +#if defined(CONFIG_CPU_HAS_FPU) + +static inline void z_arm_floating_point_init(void) +{ +#if defined(CONFIG_FPU) + uint32_t reg_val = 0; + + /* + * CPACR : Coprocessor Access Control Register -> CP15 1/0/2 + * comp. ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition, + * chap. B4.1.40 + * + * Must be accessed in >= PL1! + * [23..22] = CP11 access control bits, + * [21..20] = CP10 access control bits. + * 11b = Full access as defined for the respective CP, + * 10b = UNDEFINED, + * 01b = Access at PL1 only, + * 00b = No access. + */ + reg_val = __get_CPACR(); + /* Enable PL1 access to CP10, CP11 */ + reg_val |= (CPACR_CP10(CPACR_FA) | CPACR_CP11(CPACR_FA)); + __set_CPACR(reg_val); + barrier_isync_fence_full(); + +#if !defined(CONFIG_FPU_SHARING) + /* + * FPEXC: Floating-Point Exception Control register + * comp. ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition, + * chap. B6.1.38 + * + * Must be accessed in >= PL1! + * [31] EX bit = determines which registers comprise the current state + * of the FPU. The effects of setting this bit to 1 are + * subarchitecture defined. If EX=0, the following + * registers contain the complete current state + * information of the FPU and must therefore be saved + * during a context switch: + * * D0-D15 + * * D16-D31 if implemented + * * FPSCR + * * FPEXC. + * [30] EN bit = Advanced SIMD/Floating Point Extensions enable bit. + * [29..00] = Subarchitecture defined -> not relevant here. + */ + __set_FPEXC(FPEXC_EN); +#endif +#endif +} + +#endif /* CONFIG_CPU_HAS_FPU */ + +extern FUNC_NORETURN void z_cstart(void); + +/** + * + * @brief Prepare to and run C code + * + * This routine prepares for the execution of and runs C code. + * + */ +void z_arm_prep_c(void) +{ + /* Initialize tpidruro with our struct _cpu instance address */ + write_tpidruro((uintptr_t)&_kernel.cpus[0]); + + relocate_vector_table(); +#if defined(CONFIG_CPU_HAS_FPU) + z_arm_floating_point_init(); +#endif + z_bss_zero(); + z_data_copy(); +#if ((defined(CONFIG_ARMV7_R) || defined(CONFIG_ARMV7_A)) && defined(CONFIG_INIT_STACKS)) + z_arm_init_stacks(); +#endif + z_arm_interrupt_init(); +#ifdef CONFIG_ARM_MPU + z_arm_mpu_init(); + z_arm_configure_static_mpu_regions(); +#elif defined(CONFIG_ARM_AARCH32_MMU) + z_arm_mmu_init(); +#endif + z_cstart(); + CODE_UNREACHABLE; +} diff --git a/arch/arm/core/aarch32/cortex_a_r/reboot.c b/arch/arm/core/cortex_a_r/reboot.c similarity index 100% rename from arch/arm/core/aarch32/cortex_a_r/reboot.c rename to arch/arm/core/cortex_a_r/reboot.c diff --git a/arch/arm/core/aarch32/cortex_a_r/reset.S b/arch/arm/core/cortex_a_r/reset.S similarity index 81% rename from arch/arm/core/aarch32/cortex_a_r/reset.S rename to arch/arm/core/cortex_a_r/reset.S index 32d1dc468df..ff3c35e0f18 100644 --- a/arch/arm/core/aarch32/cortex_a_r/reset.S +++ b/arch/arm/core/cortex_a_r/reset.S @@ -16,8 +16,10 @@ #include #include #include -#include +#include #include "vector_table.h" +#include "boot.h" +#include "macro_priv.inc" _ASM_FILE_PROLOGUE @@ -76,6 +78,7 @@ SECTION_SUBSEC_FUNC(TEXT, _reset_section, __start) EL1_Reset_Handler: #endif + #if defined(CONFIG_DCLS) /* * Initialise CPU registers to a defined state if the processor is @@ -196,33 +199,72 @@ EL1_Reset_Handler: #endif /* CONFIG_DCLS */ + ldr r0, =arm_cpu_boot_params +#if CONFIG_MP_MAX_NUM_CPUS > 1 + get_cpu_id r1 + + ldrex r2, [r0, #BOOT_PARAM_MPID_OFFSET] + cmp r2, #-1 + bne 1f + strex r3, r1, [r0, #BOOT_PARAM_MPID_OFFSET] + cmp r3, #0 + beq _primary_core + +1: + dmb ld + ldr r2, [r0, #BOOT_PARAM_MPID_OFFSET] + cmp r1, r2 + bne 1b + + /* we can now move on */ + ldr r4, =z_arm_secondary_start + ldr r5, [r0, #BOOT_PARAM_FIQ_SP_OFFSET] + ldr r6, [r0, #BOOT_PARAM_IRQ_SP_OFFSET] + ldr r7, [r0, #BOOT_PARAM_ABT_SP_OFFSET] + ldr r8, [r0, #BOOT_PARAM_UDF_SP_OFFSET] + ldr r9, [r0, #BOOT_PARAM_SVC_SP_OFFSET] + ldr r10, [r0, #BOOT_PARAM_SYS_SP_OFFSET] + b 2f + +_primary_core: +#endif + + ldr r4, =z_arm_prep_c + ldr r5, =(z_arm_fiq_stack + CONFIG_ARMV7_FIQ_STACK_SIZE) + ldr r6, =(z_interrupt_stacks + CONFIG_ISR_STACK_SIZE) + ldr r7, =(z_arm_abort_stack + CONFIG_ARMV7_EXCEPTION_STACK_SIZE) + ldr r8, =(z_arm_undef_stack + CONFIG_ARMV7_EXCEPTION_STACK_SIZE) + ldr r9, =(z_arm_svc_stack + CONFIG_ARMV7_SVC_STACK_SIZE) + ldr r10, =(z_arm_sys_stack + CONFIG_ARMV7_SYS_STACK_SIZE) + +2: /* * Configure stack. */ /* FIQ mode stack */ msr CPSR_c, #(MODE_FIQ | I_BIT | F_BIT) - ldr sp, =(z_arm_fiq_stack + CONFIG_ARMV7_FIQ_STACK_SIZE) + mov sp, r5 /* IRQ mode stack */ msr CPSR_c, #(MODE_IRQ | I_BIT | F_BIT) - ldr sp, =(z_interrupt_stacks + CONFIG_ISR_STACK_SIZE) + mov sp, r6 /* ABT mode stack */ msr CPSR_c, #(MODE_ABT | I_BIT | F_BIT) - ldr sp, =(z_arm_abort_stack + CONFIG_ARMV7_EXCEPTION_STACK_SIZE) + mov sp, r7 /* UND mode stack */ msr CPSR_c, #(MODE_UND | I_BIT | F_BIT) - ldr sp, =(z_arm_undef_stack + CONFIG_ARMV7_EXCEPTION_STACK_SIZE) + mov sp, r8 /* SVC mode stack */ msr CPSR_c, #(MODE_SVC | I_BIT | F_BIT) - ldr sp, =(z_arm_svc_stack + CONFIG_ARMV7_SVC_STACK_SIZE) + mov sp, r9 /* SYS mode stack */ msr CPSR_c, #(MODE_SYS | I_BIT | F_BIT) - ldr sp, =(z_arm_sys_stack + CONFIG_ARMV7_SYS_STACK_SIZE) + mov sp, r10 #if defined(CONFIG_PLATFORM_SPECIFIC_INIT) /* Execute platform-specific initialisation if applicable */ @@ -238,4 +280,4 @@ EL1_Reset_Handler: bl z_arm_tcm_disable_ecc #endif - b z_arm_prep_c + bx r4 diff --git a/arch/arm/core/aarch32/cortex_a_r/semihost.c b/arch/arm/core/cortex_a_r/semihost.c similarity index 100% rename from arch/arm/core/aarch32/cortex_a_r/semihost.c rename to arch/arm/core/cortex_a_r/semihost.c diff --git a/arch/arm/core/cortex_a_r/smp.c b/arch/arm/core/cortex_a_r/smp.c new file mode 100644 index 00000000000..2aeb36c1735 --- /dev/null +++ b/arch/arm/core/cortex_a_r/smp.c @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2023 Arm Limited (or its affiliates). All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "boot.h" +#include "zephyr/cache.h" +#include "zephyr/kernel/thread_stack.h" +#include "zephyr/toolchain/gcc.h" + +#define INV_MPID UINT32_MAX + +#define SGI_SCHED_IPI 0 +#define SGI_MMCFG_IPI 1 +#define SGI_FPU_IPI 2 + +K_KERNEL_PINNED_STACK_ARRAY_DECLARE(z_interrupt_stacks, + CONFIG_MP_MAX_NUM_CPUS, + CONFIG_ISR_STACK_SIZE); + +K_KERNEL_STACK_ARRAY_DECLARE(z_arm_fiq_stack, + CONFIG_MP_MAX_NUM_CPUS, + CONFIG_ARMV7_FIQ_STACK_SIZE); + +K_KERNEL_STACK_ARRAY_DECLARE(z_arm_abort_stack, + CONFIG_MP_MAX_NUM_CPUS, + CONFIG_ARMV7_EXCEPTION_STACK_SIZE); + +K_KERNEL_STACK_ARRAY_DECLARE(z_arm_undef_stack, + CONFIG_MP_MAX_NUM_CPUS, + CONFIG_ARMV7_EXCEPTION_STACK_SIZE); + +K_KERNEL_STACK_ARRAY_DECLARE(z_arm_svc_stack, + CONFIG_MP_MAX_NUM_CPUS, + CONFIG_ARMV7_SVC_STACK_SIZE); + +K_KERNEL_STACK_ARRAY_DECLARE(z_arm_sys_stack, + CONFIG_MP_MAX_NUM_CPUS, + CONFIG_ARMV7_SVC_STACK_SIZE); + +struct boot_params { + uint32_t mpid; + char *irq_sp; + char *fiq_sp; + char *abt_sp; + char *udf_sp; + char *svc_sp; + char *sys_sp; + arch_cpustart_t fn; + void *arg; + int cpu_num; +}; + +/* Offsets used in reset.S */ +BUILD_ASSERT(offsetof(struct boot_params, mpid) == BOOT_PARAM_MPID_OFFSET); +BUILD_ASSERT(offsetof(struct boot_params, irq_sp) == BOOT_PARAM_IRQ_SP_OFFSET); +BUILD_ASSERT(offsetof(struct boot_params, fiq_sp) == BOOT_PARAM_FIQ_SP_OFFSET); +BUILD_ASSERT(offsetof(struct boot_params, abt_sp) == BOOT_PARAM_ABT_SP_OFFSET); +BUILD_ASSERT(offsetof(struct boot_params, udf_sp) == BOOT_PARAM_UDF_SP_OFFSET); +BUILD_ASSERT(offsetof(struct boot_params, svc_sp) == BOOT_PARAM_SVC_SP_OFFSET); +BUILD_ASSERT(offsetof(struct boot_params, sys_sp) == BOOT_PARAM_SYS_SP_OFFSET); + +volatile struct boot_params arm_cpu_boot_params = { + .mpid = -1, + .irq_sp = (char *)(z_interrupt_stacks + CONFIG_ISR_STACK_SIZE), + .fiq_sp = (char *)(z_arm_fiq_stack + CONFIG_ARMV7_FIQ_STACK_SIZE), + .abt_sp = (char *)(z_arm_abort_stack + CONFIG_ARMV7_EXCEPTION_STACK_SIZE), + .udf_sp = (char *)(z_arm_undef_stack + CONFIG_ARMV7_EXCEPTION_STACK_SIZE), + .svc_sp = (char *)(z_arm_svc_stack + CONFIG_ARMV7_SVC_STACK_SIZE), + .sys_sp = (char *)(z_arm_sys_stack + CONFIG_ARMV7_SYS_STACK_SIZE), +}; + +static const uint32_t cpu_node_list[] = { + DT_FOREACH_CHILD_STATUS_OKAY_SEP(DT_PATH(cpus), DT_REG_ADDR, (,))}; + +/* cpu_map saves the maping of core id and mpid */ +static uint32_t cpu_map[CONFIG_MP_MAX_NUM_CPUS] = { + [0 ... (CONFIG_MP_MAX_NUM_CPUS - 1)] = INV_MPID +}; + +#ifdef CONFIG_ARM_MPU +extern void z_arm_mpu_init(void); +extern void z_arm_configure_static_mpu_regions(void); +#elif defined(CONFIG_ARM_AARCH32_MMU) +extern int z_arm_mmu_init(void); +#endif + +/* Called from Zephyr initialization */ +void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz, arch_cpustart_t fn, void *arg) +{ + int cpu_count, i, j; + uint32_t cpu_mpid = 0; + uint32_t master_core_mpid; + + /* Now it is on master core */ + __ASSERT(arch_curr_cpu()->id == 0, ""); + master_core_mpid = MPIDR_TO_CORE(GET_MPIDR()); + + cpu_count = ARRAY_SIZE(cpu_node_list); + __ASSERT(cpu_count == CONFIG_MP_MAX_NUM_CPUS, + "The count of CPU Cores nodes in dts is not equal to CONFIG_MP_MAX_NUM_CPUS\n"); + + for (i = 0, j = 0; i < cpu_count; i++) { + if (cpu_node_list[i] == master_core_mpid) { + continue; + } + if (j == cpu_num - 1) { + cpu_mpid = cpu_node_list[i]; + break; + } + j++; + } + if (i == cpu_count) { + printk("Can't find CPU Core %d from dts and failed to boot it\n", cpu_num); + return; + } + + /* Pass stack address to secondary core */ + arm_cpu_boot_params.irq_sp = Z_KERNEL_STACK_BUFFER(stack) + sz; + arm_cpu_boot_params.fiq_sp = Z_KERNEL_STACK_BUFFER(z_arm_fiq_stack[cpu_num]) + + CONFIG_ARMV7_FIQ_STACK_SIZE; + arm_cpu_boot_params.abt_sp = Z_KERNEL_STACK_BUFFER(z_arm_abort_stack[cpu_num]) + + CONFIG_ARMV7_EXCEPTION_STACK_SIZE; + arm_cpu_boot_params.udf_sp = Z_KERNEL_STACK_BUFFER(z_arm_undef_stack[cpu_num]) + + CONFIG_ARMV7_EXCEPTION_STACK_SIZE; + arm_cpu_boot_params.svc_sp = Z_KERNEL_STACK_BUFFER(z_arm_svc_stack[cpu_num]) + + CONFIG_ARMV7_SVC_STACK_SIZE; + arm_cpu_boot_params.sys_sp = Z_KERNEL_STACK_BUFFER(z_arm_sys_stack[cpu_num]) + + CONFIG_ARMV7_SYS_STACK_SIZE; + + arm_cpu_boot_params.fn = fn; + arm_cpu_boot_params.arg = arg; + arm_cpu_boot_params.cpu_num = cpu_num; + + /* store mpid last as this is our synchronization point */ + arm_cpu_boot_params.mpid = cpu_mpid; + + barrier_dsync_fence_full(); + sys_cache_data_invd_range( + (void *)&arm_cpu_boot_params, + sizeof(arm_cpu_boot_params)); + + /*! TODO: Support PSCI + * \todo Support PSCI + */ + + /* Wait secondary cores up, see z_arm64_secondary_start */ + while (arm_cpu_boot_params.fn) { + wfe(); + } + + cpu_map[cpu_num] = cpu_mpid; + + printk("Secondary CPU core %d (MPID:%#x) is up\n", cpu_num, cpu_mpid); +} + +/* the C entry of secondary cores */ +void z_arm_secondary_start(void) +{ + int cpu_num = arm_cpu_boot_params.cpu_num; + arch_cpustart_t fn; + void *arg; + + __ASSERT(arm_cpu_boot_params.mpid == MPIDR_TO_CORE(GET_MPIDR()), ""); + + /* Initialize tpidrro_el0 with our struct _cpu instance address */ + write_tpidruro((uintptr_t)&_kernel.cpus[cpu_num]); + +#ifdef CONFIG_ARM_MPU + + /*! TODO: Unify mpu and mmu initialization function + * \todo Unify mpu and mmu initialization function + */ + z_arm_mpu_init(); + z_arm_configure_static_mpu_regions(); +#elif defined(CONFIG_ARM_AARCH32_MMU) + z_arm_mmu_init(); +#endif + +#ifdef CONFIG_SMP + arm_gic_secondary_init(); + + irq_enable(SGI_SCHED_IPI); + + /*! TODO: FPU irq + * \todo FPU irq + */ +#endif + + fn = arm_cpu_boot_params.fn; + arg = arm_cpu_boot_params.arg; + barrier_dsync_fence_full(); + + /* + * Secondary core clears .fn to announce its presence. + * Primary core is polling for this. We no longer own + * arm_cpu_boot_params afterwards. + */ + arm_cpu_boot_params.fn = NULL; + barrier_dsync_fence_full(); + + sev(); + + fn(arg); +} + +#ifdef CONFIG_SMP + +static void broadcast_ipi(unsigned int ipi) +{ + uint32_t mpidr = MPIDR_TO_CORE(GET_MPIDR()); + + /* + * Send SGI to all cores except itself + */ + unsigned int num_cpus = arch_num_cpus(); + + for (int i = 0; i < num_cpus; i++) { + uint32_t target_mpidr = cpu_map[i]; + uint8_t aff0; + + if (mpidr == target_mpidr || mpidr == INV_MPID) { + continue; + } + + aff0 = MPIDR_AFFLVL(target_mpidr, 0); + gic_raise_sgi(ipi, (uint64_t)target_mpidr, 1 << aff0); + } +} + +void sched_ipi_handler(const void *unused) +{ + ARG_UNUSED(unused); + + z_sched_ipi(); +} + +/* arch implementation of sched_ipi */ +void arch_sched_ipi(void) +{ + broadcast_ipi(SGI_SCHED_IPI); +} + +static int arm_smp_init(void) +{ + cpu_map[0] = MPIDR_TO_CORE(GET_MPIDR()); + + /* + * SGI0 is use for sched ipi, this might be changed to use Kconfig + * option + */ + IRQ_CONNECT(SGI_SCHED_IPI, IRQ_DEFAULT_PRIORITY, sched_ipi_handler, NULL, 0); + irq_enable(SGI_SCHED_IPI); + + return 0; +} + +SYS_INIT(arm_smp_init, PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); + +#endif diff --git a/arch/arm/core/cortex_a_r/stacks.c b/arch/arm/core/cortex_a_r/stacks.c new file mode 100644 index 00000000000..0691595c359 --- /dev/null +++ b/arch/arm/core/cortex_a_r/stacks.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018 Lexmark International, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "zephyr/kernel/thread_stack.h" +#include +#include +#include +#include + +K_KERNEL_STACK_ARRAY_DEFINE(z_arm_fiq_stack, CONFIG_MP_MAX_NUM_CPUS, + CONFIG_ARMV7_FIQ_STACK_SIZE); +K_KERNEL_STACK_ARRAY_DEFINE(z_arm_abort_stack, CONFIG_MP_MAX_NUM_CPUS, + CONFIG_ARMV7_EXCEPTION_STACK_SIZE); +K_KERNEL_STACK_ARRAY_DEFINE(z_arm_undef_stack, CONFIG_MP_MAX_NUM_CPUS, + CONFIG_ARMV7_EXCEPTION_STACK_SIZE); +K_KERNEL_STACK_ARRAY_DEFINE(z_arm_svc_stack, CONFIG_MP_MAX_NUM_CPUS, + CONFIG_ARMV7_SVC_STACK_SIZE); +K_KERNEL_STACK_ARRAY_DEFINE(z_arm_sys_stack, CONFIG_MP_MAX_NUM_CPUS, + CONFIG_ARMV7_SYS_STACK_SIZE); + +#if defined(CONFIG_INIT_STACKS) +void z_arm_init_stacks(void) +{ + memset(z_arm_fiq_stack, 0xAA, CONFIG_ARMV7_FIQ_STACK_SIZE); + memset(z_arm_svc_stack, 0xAA, CONFIG_ARMV7_SVC_STACK_SIZE); + memset(z_arm_abort_stack, 0xAA, CONFIG_ARMV7_EXCEPTION_STACK_SIZE); + memset(z_arm_undef_stack, 0xAA, CONFIG_ARMV7_EXCEPTION_STACK_SIZE); + memset(Z_KERNEL_STACK_BUFFER(z_interrupt_stacks[0]), 0xAA, + K_KERNEL_STACK_SIZEOF(z_interrupt_stacks[0])); +} +#endif diff --git a/arch/arm/core/cortex_a_r/swap.c b/arch/arm/core/cortex_a_r/swap.c new file mode 100644 index 00000000000..2f7faba741a --- /dev/null +++ b/arch/arm/core/cortex_a_r/swap.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018 Linaro, Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +/* The 'key' actually represents the BASEPRI register + * prior to disabling interrupts via the BASEPRI mechanism. + * + * arch_swap() itself does not do much. + */ +int arch_swap(unsigned int key) +{ + /* store off key and return value */ + _current->arch.basepri = key; + _current->arch.swap_return_value = -EAGAIN; + + z_arm_cortex_r_svc(); + irq_unlock(key); + + /* Context switch is performed here. Returning implies the + * thread has been context-switched-in again. + */ + return _current->arch.swap_return_value; +} diff --git a/arch/arm/core/cortex_a_r/swap_helper.S b/arch/arm/core/cortex_a_r/swap_helper.S new file mode 100644 index 00000000000..548bb446aa3 --- /dev/null +++ b/arch/arm/core/cortex_a_r/swap_helper.S @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * Copyright (c) 2017-2019 Nordic Semiconductor ASA. + * Copyright (c) 2020 Stephanos Ioannidis + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Thread context switching for ARM Cortex-A and Cortex-R + * + * This module implements the routines necessary for thread context switching + * on ARM Cortex-A and Cortex-R CPUs. + */ + +#include +#include +#include +#include +#include +#include +#include "macro_priv.inc" + +_ASM_FILE_PROLOGUE + +GTEXT(z_arm_svc) +GTEXT(z_arm_do_swap) +GTEXT(z_do_kernel_oops) +#if defined(CONFIG_USERSPACE) +GTEXT(z_arm_do_syscall) +#endif + +GDATA(_kernel) + +/** + * + * @brief Routine to handle context switches + * + * For Cortex-R, this function is directly called either by z_arm_{exc,int}_exit + * in case of preemption, or z_arm_svc in case of cooperative switching. + */ + +SECTION_FUNC(TEXT, z_arm_do_swap) + +#ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING + /* Register the context switch */ + push {r0, lr} + bl z_thread_mark_switched_out + pop {r0, lr} +#endif /* CONFIG_INSTRUMENT_THREAD_SWITCHING */ + + /* load current _cpu into r1 and current k_thread into r2 */ + get_cpu r1 + ldr r2, [r1, #___cpu_t_current_OFFSET] + +#if defined(CONFIG_ARM_STORE_EXC_RETURN) + /* Store LSB of LR (EXC_RETURN) to the thread's 'mode' word. */ + strb lr, [r2, #_thread_offset_to_mode_exc_return] +#endif + + /* addr of callee-saved regs in thread in r0 */ + ldr r0, =_thread_offset_to_callee_saved + add r0, r2 + + /* Store rest of process context */ + cps #MODE_SYS + stm r0, {r4-r11, sp} + cps #MODE_SVC + +#if defined(CONFIG_FPU_SHARING) + ldrb r0, [r2, #_thread_offset_to_user_options] + tst r0, #K_FP_REGS /* _current->base.user_options & K_FP_REGS */ + beq out_fp_inactive + + mov ip, #FPEXC_EN + vmsr fpexc, ip + + /* + * If the float context pointer is not null, then the VFP has not been + * used since this thread has used it. Consequently, the caller-saved + * float registers have not been saved away, so write them to the + * exception stack frame. + */ + ldr r0, [r1, #___cpu_t_fp_ctx_OFFSET] + cmp r0, #0 + beq out_store_thread_context + + vstmia r0!, {s0-s15} +#ifdef CONFIG_VFP_FEATURE_REGS_S64_D32 + vstmia r0!, {d16-d31} +#endif + vmrs r3, fpscr + stm r0, {r3, ip} + +out_store_thread_context: + /* Store s16-s31 to thread context */ + add r0, r2, #_thread_offset_to_preempt_float + vstmia r0, {s16-s31} + + mov ip, #0 + vmsr fpexc, ip + +out_fp_inactive: + /* + * The floating context has now been saved to the exception stack + * frame, so zero out the global pointer to note this. + */ + mov r0, #0 + str r0, [r1, #___cpu_t_fp_ctx_OFFSET] +#endif /* CONFIG_FPU_SHARING */ + + /* fetch the thread to run from the ready queue cache */ + ldr r3, =_kernel + ldr r2, [r3, #_kernel_offset_to_ready_q_cache] + + str r2, [r1, #___cpu_t_current_OFFSET] + +#if defined(CONFIG_THREAD_LOCAL_STORAGE) + /* Grab the TLS pointer */ + ldr r4, =_thread_offset_to_tls + adds r4, r2, r4 + ldr r0, [r4] + + /* Store TLS pointer in the "Process ID" register. + * TPIDRURW is used as a base pointer to all + * thread variables with offsets added by toolchain. + */ + mcr 15, 0, r0, c13, c0, 2 +#endif + +#if defined(CONFIG_ARM_STORE_EXC_RETURN) + /* Restore EXC_RETURN value. */ + ldrsb lr, [r2, #_thread_offset_to_mode_exc_return] +#endif + + /* Restore previous interrupt disable state (irq_lock key) + * (We clear the arch.basepri field after restoring state) + */ + ldr r0, [r2, #_thread_offset_to_basepri] + movs r3, #0 + str r3, [r2, #_thread_offset_to_basepri] + + /* addr of callee-saved regs in thread in r0 */ + ldr r0, =_thread_offset_to_callee_saved + add r0, r2 + + /* restore r4-r11 and sp for incoming thread */ + cps #MODE_SYS + ldm r0, {r4-r11, sp} + cps #MODE_SVC + +#if defined(CONFIG_FPU_SHARING) + ldrb r0, [r2, #_thread_offset_to_user_options] + tst r0, #K_FP_REGS /* _current->base.user_options & K_FP_REGS */ + beq in_fp_inactive + + mov r3, #FPEXC_EN + vmsr fpexc, r3 + + /* Restore s16-s31 from thread context */ + add r0, r2, #_thread_offset_to_preempt_float + vldmia r0, {s16-s31} + + mov r3, #0 + vmsr fpexc, r3 + +in_fp_inactive: +#endif /* CONFIG_FPU_SHARING */ + +#if defined (CONFIG_ARM_MPU) + /* r2 contains k_thread */ + mov r0, r2 + /* Re-program dynamic memory map */ + push {r0, lr} + bl z_arm_configure_dynamic_mpu_regions + pop {r0, lr} +#endif + +#ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING + /* Register the context switch */ + push {r0, lr} + bl z_thread_mark_switched_in + pop {r0, lr} +#endif /* CONFIG_INSTRUMENT_THREAD_SWITCHING */ + + /* + * Cortex-R: return to the caller (z_arm_{exc,int}_exit, or z_arm_svc) + */ + bx lr + +#if defined(CONFIG_FPU_SHARING) +#define FPU_SF_SIZE ___fpu_t_SIZEOF +#else +#define FPU_SF_SIZE 0 +#endif + +/** + * + * @brief Service call handler + * + * The service call (svc) is used in the following occasions: + * - Cooperative context switching + * - IRQ offloading + * - Kernel run-time exceptions + * + */ +SECTION_FUNC(TEXT, z_arm_svc) +#if defined(CONFIG_USERSPACE) + /* Determine if incoming thread was in user context */ + push {r0} + mrs r0, spsr + and r0, #MODE_MASK + cmp r0, #MODE_USR + bne svc_system_thread + + get_cpu r0 + ldr r0, [r0, #___cpu_t_current_OFFSET] + + /* Save away user stack pointer */ + cps #MODE_SYS + str sp, [r0, #_thread_offset_to_sp_usr] /* sp_usr */ + + /* Switch to privileged stack */ + ldr sp, [r0, #_thread_offset_to_priv_stack_end] /* priv stack end */ + cps #MODE_SVC + +svc_system_thread: + pop {r0} +#endif + + /* + * Switch to system mode to store r0-r3 to the process stack pointer. + * Save r12 and the lr as we could be swapping in another process and + * returning to a different location. + */ + srsdb #MODE_SYS! + cps #MODE_SYS + push {r0-r3, r12, lr} + +#if defined(CONFIG_FPU_SHARING) + sub sp, sp, #___fpu_t_SIZEOF + + /* + * Note that this handler was entered with the VFP unit enabled. + * The undefined instruction handler uses this to know that it + * needs to save the current floating context. + */ + vmrs r0, fpexc + str r0, [sp, #___fpu_t_SIZEOF - 4] + tst r0, #FPEXC_EN + beq _vfp_not_enabled + vmrs r0, fpscr + str r0, [sp, #___fpu_t_SIZEOF - 8] + + /* Disable VFP */ + mov r0, #0 + vmsr fpexc, r0 + +_vfp_not_enabled: + /* + * Mark where to store the floating context for the undefined + * instruction handler + */ + get_cpu r2 + ldr r0, [r2, #___cpu_t_fp_ctx_OFFSET] + cmp r0, #0 + streq sp, [r2, #___cpu_t_fp_ctx_OFFSET] +#endif /* CONFIG_FPU_SHARING */ + + mov ip, sp + + cps #MODE_SVC + + /* + * Store lr_svc to the SVC mode stack. This value will be restored prior to + * exiting the SVC call in z_arm_int_exit. + */ + push {lr} + + /* Align stack at double-word boundary */ + /* TODO: Question, why push {r2, r3} here */ + and r3, sp, #4 + sub sp, sp, r3 + push {r2, r3} + + /* Increment interrupt nesting count */ + get_cpu r2 + ldr r0, [r2, #___cpu_t_nested_OFFSET] + add r0, r0, #1 + str r0, [r2, #___cpu_t_nested_OFFSET] + + /* Get SVC number */ + mrs r0, spsr + tst r0, #0x20 + + ldreq r1, [lr, #-4] + biceq r1, #0xff000000 + beq demux + + ldr r1, [lr, #-2] + and r1, #0xff + + /* + * grab service call number: + * 0: context switch + * 1: irq_offload (if configured) + * 2: kernel panic or oops (software generated fatal exception) + * 3: system calls for memory protection + */ +demux: + +#if defined(CONFIG_USERSPACE) + cmp r1, #_SVC_CALL_SYSTEM_CALL + beq _do_syscall +#endif + + cmp r1, #_SVC_CALL_CONTEXT_SWITCH + beq _context_switch + + cmp r1, #_SVC_CALL_RUNTIME_EXCEPT + beq _oops + +#if CONFIG_IRQ_OFFLOAD + blx z_irq_do_offload /* call C routine which executes the offload */ + + /* exception return is done in z_arm_int_exit() */ + b z_arm_int_exit +#endif + +_context_switch: + /* handler mode exit, to PendSV */ + bl z_arm_do_swap + + b z_arm_int_exit + +_oops: + /* + * Pass the exception frame to z_do_kernel_oops. r0 contains the + * exception reason. + */ + cps #MODE_SYS + mov r0, sp + cps #MODE_SVC + bl z_do_kernel_oops + b z_arm_int_exit + +#if defined(CONFIG_USERSPACE) + /* + * System call will setup a jump to the _do_arm_syscall function + * running in system mode when returning from the exception. + * + * There is some trickery involved here because we have to preserve + * the original PC value so that we can return back to the caller of + * the SVC. + * + * On SVC exception, the USER/SYSTEM stack looks like the following: + * { possible FPU space } - r0 - r1 - r2 - r3 - r12 - LR - PC - SPSR + * + * Registers look like: + * r0 - arg1 + * r1 - arg2 + * r2 - arg3 + * r3 - arg4 + * r4 - arg5 + * r5 - arg6 + * r6 - call_id + * r8 - saved link register + */ +_do_syscall: + /* grab address of LR from stack frame */ + ldr r8, [ip, #(FPU_SF_SIZE + ___basic_sf_t_pc_OFFSET)] + + /* Make the exception return to system state */ + ldr r1, [ip, #(FPU_SF_SIZE + ___basic_sf_t_xpsr_OFFSET)] + + /* If leaving thumb mode, set the return address to thumb mode */ + tst r1, #T_BIT + orrne r8, #1 + + bic r1, #(MODE_MASK | T_BIT) + orr r1, r1, #MODE_SYS + str r1, [ip, #(FPU_SF_SIZE + ___basic_sf_t_xpsr_OFFSET)] + + /* + * Store the address of z_arm_do_syscall for the exit so the exception + * return goes there in system state. + */ + ldr r1, =z_arm_do_syscall + str r1, [ip, #(FPU_SF_SIZE + ___basic_sf_t_pc_OFFSET)] + + /* validate syscall limit, only set priv mode if valid */ + ldr ip, =K_SYSCALL_LIMIT + cmp r6, ip + blo valid_syscall_id + + /* bad syscall id. Set arg0 to bad id and set call_id to SYSCALL_BAD */ + cps #MODE_SYS + str r6, [sp] + cps #MODE_SVC + ldr r6, =K_SYSCALL_BAD + +valid_syscall_id: + get_cpu r0 + ldr r0, [r0, #___cpu_t_current_OFFSET] + ldr r1, [r0, #_thread_offset_to_mode] + bic r1, #1 + /* Store (privileged) mode in thread's mode state variable */ + str r1, [r0, #_thread_offset_to_mode] + dsb + + /* ISB is not strictly necessary here (stack pointer is not being + * touched), but it's recommended to avoid executing pre-fetched + * instructions with the previous privilege. + */ + isb + + /* Return to _arm_do_syscall in system state. */ + b z_arm_int_exit +#endif + +GTEXT(z_arm_cortex_r_svc) +SECTION_FUNC(TEXT, z_arm_cortex_r_svc) + svc #_SVC_CALL_CONTEXT_SWITCH + bx lr diff --git a/arch/arm/core/cortex_a_r/switch.S b/arch/arm/core/cortex_a_r/switch.S new file mode 100644 index 00000000000..800d46bbf94 --- /dev/null +++ b/arch/arm/core/cortex_a_r/switch.S @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2023 Arm Limited (or its affiliates). All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Thread context switching for ARM Cortex-A and Cortex-R (AArch32) + * + * This module implements the routines necessary for thread context switching + * on ARM Cortex-A and Cortex-R CPUs. + */ + +#include +#include +#include +#include +#include +#include "macro_priv.inc" + +_ASM_FILE_PROLOGUE + +GTEXT(z_arm_svc) +GTEXT(z_arm_context_switch) +GTEXT(z_do_kernel_oops) +GTEXT(z_arm_do_syscall) + +/* + * Routine to handle context switches + * + * This function is directly called either by _isr_wrapper() in case of + * preemption, or arch_switch() in case of cooperative switching. + * + * void z_arm_context_switch(struct k_thread *new, struct k_thread *old); + */ +SECTION_FUNC(TEXT, z_arm_context_switch) + + ldr r2, =_thread_offset_to_callee_saved + add r2, r1, r2 + + stm r2, {r4-r11, sp, lr} + + /* save current thread's exception depth */ + get_cpu r2 + ldrb r3, [r2, #_cpu_offset_to_exc_depth] + strb r3, [r1, #_thread_offset_to_exception_depth] + + /* retrieve next thread's exception depth */ + ldrb r3, [r0, #_thread_offset_to_exception_depth] + strb r3, [r2, #_cpu_offset_to_exc_depth] + + /* save old thread into switch handle which is required by + * z_sched_switch_spin(). + * + * Note that this step must be done after all relevant state is + * saved. + */ + dsb + str r1, [r1, #___thread_t_switch_handle_OFFSET] + +#if defined(CONFIG_THREAD_LOCAL_STORAGE) + /* Grab the TLS pointer */ + ldr r3, [r0, #_thread_offset_to_tls] + + /* Store TLS pointer in the "Process ID" register. + * This register is used as a base pointer to all + * thread variables with offsets added by toolchain. + */ + mcr 15, 0, r3, c13, c0, 2 +#endif + + ldr r2, =_thread_offset_to_callee_saved + add r2, r0, r2 + ldm r2, {r4-r11, sp, lr} + +#if defined (CONFIG_ARM_MPU) + /* Re-program dynamic memory map */ + push {r0, lr} + bl z_arm_configure_dynamic_mpu_regions + pop {r0, lr} +#endif + +#ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING + push {lr} + bl z_thread_mark_switched_in + pop {lr} +#endif + + bx lr + +/** + * + * @brief Service call handler + * + * The service call (svc) is used in the following occasions: + * - Cooperative context switching + * - IRQ offloading + * - Kernel run-time exceptions + * + */ +SECTION_FUNC(TEXT, z_arm_svc) + z_arm_cortex_ar_enter_exc + + /* Get SVC number */ + cps #MODE_SVC + mrs r0, spsr + tst r0, #0x20 + ldreq r1, [lr, #-4] + biceq r1, #0xff000000 + beq demux + + ldr r1, [lr, #-2] + and r1, #0xff + + /* + * grab service call number: + * TODO 0: context switch + * 1: irq_offload (if configured) + * 2: kernel panic or oops (software generated fatal exception) + * TODO 3: system calls for memory protection + */ +demux: + cps #MODE_SYS + + cmp r1, #_SVC_CALL_RUNTIME_EXCEPT + beq _oops + +#ifdef CONFIG_IRQ_OFFLOAD + cmp r1, #_SVC_CALL_IRQ_OFFLOAD + beq offload + b inv +offload: + get_cpu r2 + ldr r3, [r2, #___cpu_t_nested_OFFSET] + add r3, r3, #1 + str r3, [r2, #___cpu_t_nested_OFFSET] + + /* If not nested: switch to IRQ stack and save current sp on it. */ + cmp r3, #1 + bhi 1f + mov r0, sp + cps #MODE_IRQ + push {r0} + +1: + blx z_irq_do_offload + b z_arm_cortex_ar_irq_done +#endif + b inv + +_oops: + /* + * Pass the exception frame to z_do_kernel_oops. r0 contains the + * exception reason. + */ + mov r0, sp + bl z_do_kernel_oops + +inv: + mov r0, #0 /* K_ERR_CPU_EXCEPTION */ + mov r1, sp + bl z_arm_fatal_error + + /* Return here only in case of recoverable error */ + b z_arm_cortex_ar_exit_exc diff --git a/arch/arm/core/aarch32/cortex_a_r/tcm.c b/arch/arm/core/cortex_a_r/tcm.c similarity index 100% rename from arch/arm/core/aarch32/cortex_a_r/tcm.c rename to arch/arm/core/cortex_a_r/tcm.c diff --git a/arch/arm/core/cortex_a_r/thread.c b/arch/arm/core/cortex_a_r/thread.c new file mode 100644 index 00000000000..9d57563f6bd --- /dev/null +++ b/arch/arm/core/cortex_a_r/thread.c @@ -0,0 +1,410 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * Copyright (c) 2021 Lexmark International, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief New thread creation for ARM Cortex-A and Cortex-R + * + * Core thread related primitives for the ARM Cortex-A and + * Cortex-R processor architecture. + */ + +#include +#include +#include +#include +#include + +#if (MPU_GUARD_ALIGN_AND_SIZE_FLOAT > MPU_GUARD_ALIGN_AND_SIZE) +#define FP_GUARD_EXTRA_SIZE (MPU_GUARD_ALIGN_AND_SIZE_FLOAT - \ + MPU_GUARD_ALIGN_AND_SIZE) +#else +#define FP_GUARD_EXTRA_SIZE 0 +#endif + +#ifndef EXC_RETURN_FTYPE +/* bit [4] allocate stack for floating-point context: 0=done 1=skipped */ +#define EXC_RETURN_FTYPE (0x00000010UL) +#endif + +/* Default last octet of EXC_RETURN, for threads that have not run yet. + * The full EXC_RETURN value will be e.g. 0xFFFFFFBC. + */ +#define DEFAULT_EXC_RETURN 0xFD; + +/* An initial context, to be "restored" by z_arm_pendsv(), is put at the other + * end of the stack, and thus reusable by the stack when not needed anymore. + * + * The initial context is an exception stack frame (ESF) since exiting the + * PendSV exception will want to pop an ESF. Interestingly, even if the lsb of + * an instruction address to jump to must always be set since the CPU always + * runs in thumb mode, the ESF expects the real address of the instruction, + * with the lsb *not* set (instructions are always aligned on 16 bit + * halfwords). Since the compiler automatically sets the lsb of function + * addresses, we have to unset it manually before storing it in the 'pc' field + * of the ESF. + */ +void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, + char *stack_ptr, k_thread_entry_t entry, + void *p1, void *p2, void *p3) +{ + struct __basic_sf *iframe; + +#ifdef CONFIG_MPU_STACK_GUARD +#if defined(CONFIG_USERSPACE) + if (z_stack_is_user_capable(stack)) { + /* Guard area is carved-out of the buffer instead of reserved + * for stacks that can host user threads + */ + thread->stack_info.start += MPU_GUARD_ALIGN_AND_SIZE; + thread->stack_info.size -= MPU_GUARD_ALIGN_AND_SIZE; + } +#endif /* CONFIG_USERSPACE */ +#if FP_GUARD_EXTRA_SIZE > 0 + if ((thread->base.user_options & K_FP_REGS) != 0) { + /* Larger guard needed due to lazy stacking of FP regs may + * overshoot the guard area without writing anything. We + * carve it out of the stack buffer as-needed instead of + * unconditionally reserving it. + */ + thread->stack_info.start += FP_GUARD_EXTRA_SIZE; + thread->stack_info.size -= FP_GUARD_EXTRA_SIZE; + } +#endif /* FP_GUARD_EXTRA_SIZE */ +#endif /* CONFIG_MPU_STACK_GUARD */ + + iframe = Z_STACK_PTR_TO_FRAME(struct __basic_sf, stack_ptr); +#if defined(CONFIG_USERSPACE) + if ((thread->base.user_options & K_USER) != 0) { + iframe->pc = (uint32_t)arch_user_mode_enter; + } else { + iframe->pc = (uint32_t)z_thread_entry; + } +#else + iframe->pc = (uint32_t)z_thread_entry; +#endif + + iframe->a1 = (uint32_t)entry; + iframe->a2 = (uint32_t)p1; + iframe->a3 = (uint32_t)p2; + iframe->a4 = (uint32_t)p3; + + iframe->xpsr = A_BIT | MODE_SYS; +#if defined(CONFIG_COMPILER_ISA_THUMB2) + iframe->xpsr |= T_BIT; +#endif /* CONFIG_COMPILER_ISA_THUMB2 */ + +#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) + iframe = (struct __basic_sf *) + ((uintptr_t)iframe - sizeof(struct __fpu_sf)); + memset(iframe, 0, sizeof(struct __fpu_sf)); +#endif + + thread->callee_saved.psp = (uint32_t)iframe; + thread->arch.basepri = 0; + +#if defined(CONFIG_ARM_STORE_EXC_RETURN) || defined(CONFIG_USERSPACE) + thread->arch.mode = 0; +#if defined(CONFIG_ARM_STORE_EXC_RETURN) + thread->arch.mode_exc_return = DEFAULT_EXC_RETURN; +#endif +#if FP_GUARD_EXTRA_SIZE > 0 + if ((thread->base.user_options & K_FP_REGS) != 0) { + thread->arch.mode |= Z_ARM_MODE_MPU_GUARD_FLOAT_Msk; + } +#endif +#if defined(CONFIG_USERSPACE) + thread->arch.priv_stack_start = 0; +#endif +#endif + /* + * initial values in all other registers/thread entries are + * irrelevant. + */ +#if defined(CONFIG_USE_SWITCH) + extern void z_arm_cortex_ar_exit_exc(void); + thread->switch_handle = thread; + /* thread birth happens through the exception return path */ + thread->arch.exception_depth = 1; + thread->callee_saved.lr = (uint32_t)z_arm_cortex_ar_exit_exc; +#endif +} + +#if defined(CONFIG_MPU_STACK_GUARD) && defined(CONFIG_FPU) \ + && defined(CONFIG_FPU_SHARING) + +static inline void z_arm_thread_stack_info_adjust(struct k_thread *thread, + bool use_large_guard) +{ + if (use_large_guard) { + /* Switch to use a large MPU guard if not already. */ + if ((thread->arch.mode & + Z_ARM_MODE_MPU_GUARD_FLOAT_Msk) == 0) { + /* Default guard size is used. Update required. */ + thread->arch.mode |= Z_ARM_MODE_MPU_GUARD_FLOAT_Msk; +#if defined(CONFIG_USERSPACE) + if (thread->arch.priv_stack_start) { + /* User thread */ + thread->arch.priv_stack_start += + FP_GUARD_EXTRA_SIZE; + } else +#endif /* CONFIG_USERSPACE */ + { + /* Privileged thread */ + thread->stack_info.start += + FP_GUARD_EXTRA_SIZE; + thread->stack_info.size -= + FP_GUARD_EXTRA_SIZE; + } + } + } else { + /* Switch to use the default MPU guard size if not already. */ + if ((thread->arch.mode & + Z_ARM_MODE_MPU_GUARD_FLOAT_Msk) != 0) { + /* Large guard size is used. Update required. */ + thread->arch.mode &= ~Z_ARM_MODE_MPU_GUARD_FLOAT_Msk; +#if defined(CONFIG_USERSPACE) + if (thread->arch.priv_stack_start) { + /* User thread */ + thread->arch.priv_stack_start -= + FP_GUARD_EXTRA_SIZE; + } else +#endif /* CONFIG_USERSPACE */ + { + /* Privileged thread */ + thread->stack_info.start -= + FP_GUARD_EXTRA_SIZE; + thread->stack_info.size += + FP_GUARD_EXTRA_SIZE; + } + } + } +} + +#endif + +#ifdef CONFIG_USERSPACE +FUNC_NORETURN void arch_user_mode_enter(k_thread_entry_t user_entry, + void *p1, void *p2, void *p3) +{ + + /* Set up privileged stack before entering user mode */ + _current->arch.priv_stack_start = + (uint32_t)z_priv_stack_find(_current->stack_obj); +#if defined(CONFIG_MPU_STACK_GUARD) +#if defined(CONFIG_THREAD_STACK_INFO) + /* We're dropping to user mode which means the guard area is no + * longer used here, it instead is moved to the privilege stack + * to catch stack overflows there. Un-do the calculations done + * which accounted for memory borrowed from the thread stack. + */ +#if FP_GUARD_EXTRA_SIZE > 0 + if ((_current->arch.mode & Z_ARM_MODE_MPU_GUARD_FLOAT_Msk) != 0) { + _current->stack_info.start -= FP_GUARD_EXTRA_SIZE; + _current->stack_info.size += FP_GUARD_EXTRA_SIZE; + } +#endif /* FP_GUARD_EXTRA_SIZE */ + _current->stack_info.start -= MPU_GUARD_ALIGN_AND_SIZE; + _current->stack_info.size += MPU_GUARD_ALIGN_AND_SIZE; +#endif /* CONFIG_THREAD_STACK_INFO */ + + /* Stack guard area reserved at the bottom of the thread's + * privileged stack. Adjust the available (writable) stack + * buffer area accordingly. + */ +#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) + _current->arch.priv_stack_start += + ((_current->arch.mode & Z_ARM_MODE_MPU_GUARD_FLOAT_Msk) != 0) ? + MPU_GUARD_ALIGN_AND_SIZE_FLOAT : MPU_GUARD_ALIGN_AND_SIZE; +#else + _current->arch.priv_stack_start += MPU_GUARD_ALIGN_AND_SIZE; +#endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ +#endif /* CONFIG_MPU_STACK_GUARD */ + +#if defined(CONFIG_CPU_AARCH32_CORTEX_R) + _current->arch.priv_stack_end = + _current->arch.priv_stack_start + CONFIG_PRIVILEGED_STACK_SIZE; +#endif + + z_arm_userspace_enter(user_entry, p1, p2, p3, + (uint32_t)_current->stack_info.start, + _current->stack_info.size - + _current->stack_info.delta); + CODE_UNREACHABLE; +} + +bool z_arm_thread_is_in_user_mode(void) +{ + uint32_t value; + + /* + * For Cortex-R, the mode (lower 5) bits will be 0x10 for user mode. + */ + value = __get_CPSR(); + return ((value & CPSR_M_Msk) == CPSR_M_USR); +} + +#endif + +#if defined(CONFIG_MPU_STACK_GUARD) || defined(CONFIG_USERSPACE) + +#define IS_MPU_GUARD_VIOLATION(guard_start, guard_len, fault_addr, stack_ptr) \ + ((fault_addr != -EINVAL) ? \ + ((fault_addr >= guard_start) && \ + (fault_addr < (guard_start + guard_len)) && \ + (stack_ptr < (guard_start + guard_len))) \ + : \ + (stack_ptr < (guard_start + guard_len))) + +/** + * @brief Assess occurrence of current thread's stack corruption + * + * This function performs an assessment whether a memory fault (on a + * given memory address) is the result of stack memory corruption of + * the current thread. + * + * Thread stack corruption for supervisor threads or user threads in + * privilege mode (when User Space is supported) is reported upon an + * attempt to access the stack guard area (if MPU Stack Guard feature + * is supported). Additionally the current PSP (process stack pointer) + * must be pointing inside or below the guard area. + * + * Thread stack corruption for user threads in user mode is reported, + * if the current PSP is pointing below the start of the current + * thread's stack. + * + * Notes: + * - we assume a fully descending stack, + * - we assume a stacking error has occurred, + * - the function shall be called when handling MemManage and Bus fault, + * and only if a Stacking error has been reported. + * + * If stack corruption is detected, the function returns the lowest + * allowed address where the Stack Pointer can safely point to, to + * prevent from errors when un-stacking the corrupted stack frame + * upon exception return. + * + * @param fault_addr memory address on which memory access violation + * has been reported. It can be invalid (-EINVAL), + * if only Stacking error has been reported. + * @param psp current address the PSP points to + * + * @return The lowest allowed stack frame pointer, if error is a + * thread stack corruption, otherwise return 0. + */ +uint32_t z_check_thread_stack_fail(const uint32_t fault_addr, const uint32_t psp) +{ +#if defined(CONFIG_MULTITHREADING) + const struct k_thread *thread = _current; + + if (thread == NULL) { + return 0; + } +#endif + +#if (defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)) && \ + defined(CONFIG_MPU_STACK_GUARD) + uint32_t guard_len = + ((_current->arch.mode & Z_ARM_MODE_MPU_GUARD_FLOAT_Msk) != 0) ? + MPU_GUARD_ALIGN_AND_SIZE_FLOAT : MPU_GUARD_ALIGN_AND_SIZE; +#else + /* If MPU_STACK_GUARD is not enabled, the guard length is + * effectively zero. Stack overflows may be detected only + * for user threads in nPRIV mode. + */ + uint32_t guard_len = MPU_GUARD_ALIGN_AND_SIZE; +#endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ + +#if defined(CONFIG_USERSPACE) + if (thread->arch.priv_stack_start) { + /* User thread */ + if (z_arm_thread_is_in_user_mode() == false) { + /* User thread in privilege mode */ + if (IS_MPU_GUARD_VIOLATION( + thread->arch.priv_stack_start - guard_len, + guard_len, + fault_addr, psp)) { + /* Thread's privilege stack corruption */ + return thread->arch.priv_stack_start; + } + } else { + if (psp < (uint32_t)thread->stack_obj) { + /* Thread's user stack corruption */ + return (uint32_t)thread->stack_obj; + } + } + } else { + /* Supervisor thread */ + if (IS_MPU_GUARD_VIOLATION(thread->stack_info.start - + guard_len, + guard_len, + fault_addr, psp)) { + /* Supervisor thread stack corruption */ + return thread->stack_info.start; + } + } +#else /* CONFIG_USERSPACE */ +#if defined(CONFIG_MULTITHREADING) + if (IS_MPU_GUARD_VIOLATION(thread->stack_info.start - guard_len, + guard_len, + fault_addr, psp)) { + /* Thread stack corruption */ + return thread->stack_info.start; + } +#else + if (IS_MPU_GUARD_VIOLATION((uint32_t)z_main_stack, + guard_len, + fault_addr, psp)) { + /* Thread stack corruption */ + return (uint32_t)Z_THREAD_STACK_BUFFER(z_main_stack); + } +#endif +#endif /* CONFIG_USERSPACE */ + + return 0; +} +#endif /* CONFIG_MPU_STACK_GUARD || CONFIG_USERSPACE */ + +#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) +int arch_float_disable(struct k_thread *thread) +{ + if (thread != _current) { + return -EINVAL; + } + + if (arch_is_in_isr()) { + return -EINVAL; + } + + /* Disable all floating point capabilities for the thread */ + + /* K_FP_REG flag is used in SWAP and stack check fail. Locking + * interrupts here prevents a possible context-switch or MPU + * fault to take an outdated thread user_options flag into + * account. + */ + int key = arch_irq_lock(); + + thread->base.user_options &= ~K_FP_REGS; + + __set_FPEXC(0); + + /* No need to add an ISB barrier after setting the CONTROL + * register; arch_irq_unlock() already adds one. + */ + + arch_irq_unlock(key); + + return 0; +} + +int arch_float_enable(struct k_thread *thread, unsigned int options) +{ + /* This is not supported in Cortex-A and Cortex-R */ + return -ENOTSUP; +} +#endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ diff --git a/arch/arm/core/cortex_a_r/vector_table.S b/arch/arm/core/cortex_a_r/vector_table.S new file mode 100644 index 00000000000..8c1060e6122 --- /dev/null +++ b/arch/arm/core/cortex_a_r/vector_table.S @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018 Marvell + * Copyright (c) 2018 Lexmark International, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Populated vector table in ROM + */ + +#include +#include +#include "vector_table.h" +#include "offsets_short.h" +#include "macro_priv.inc" + +_ASM_FILE_PROLOGUE + +SECTION_SUBSEC_FUNC(exc_vector_table,_vector_table_section,_vector_table) + ldr pc, =z_arm_reset /* offset 0 */ + ldr pc, =z_arm_undef_instruction /* undef instruction offset 4 */ + ldr pc, =z_arm_svc /* svc offset 8 */ + ldr pc, =z_arm_prefetch_abort /* prefetch abort offset 0xc */ + ldr pc, =z_arm_data_abort /* data abort offset 0x10 */ + nop /* offset 0x14 */ +#ifdef CONFIG_GEN_SW_ISR_TABLE + ldr pc, =_isr_wrapper /* IRQ offset 0x18 */ +#else + ldr pc, =z_irq_spurious +#endif +#ifndef CONFIG_USE_SWITCH + ldr pc, =z_arm_nmi /* FIQ offset 0x1c */ +#else + ldr pc,=z_irq_spurious +#endif + + +#ifdef CONFIG_USE_SWITCH +GTEXT(z_arm_cortex_ar_exit_exc) +SECTION_SUBSEC_FUNC(TEXT, _HandlerModeExit, z_arm_cortex_ar_exit_exc) + + /* decrement exception depth */ + get_cpu r2 + ldrb r1, [r2, #_cpu_offset_to_exc_depth] + sub r1, r1, #1 + strb r1, [r2, #_cpu_offset_to_exc_depth] + + /* + * Restore r0-r3, r12, lr, lr_und and spsr_und from the exception stack + * and return to the current thread. + */ + ldmia sp, {r0-r3, r12, lr}^ + add sp, #24 + rfeia sp! +#endif diff --git a/arch/arm/core/aarch32/cortex_a_r/vector_table.h b/arch/arm/core/cortex_a_r/vector_table.h similarity index 100% rename from arch/arm/core/aarch32/cortex_a_r/vector_table.h rename to arch/arm/core/cortex_a_r/vector_table.h diff --git a/arch/arm/core/cortex_m/CMakeLists.txt b/arch/arm/core/cortex_m/CMakeLists.txt new file mode 100644 index 00000000000..225d7111bdc --- /dev/null +++ b/arch/arm/core/cortex_m/CMakeLists.txt @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources( + exc_exit.S + fault.c + fault_s.S + fpu.c + reset.S + scb.c + thread_abort.c + vector_table.S + swap.c + swap_helper.S + irq_manage.c + prep_c.c + thread.c + cpu_idle.S + ) + +zephyr_library_sources_ifndef(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER irq_init.c) +zephyr_library_sources_ifdef(CONFIG_GEN_SW_ISR_TABLE isr_wrapper.S) +zephyr_library_sources_ifdef(CONFIG_DEBUG_COREDUMP coredump.c) +zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE __aeabi_read_tp.S) +zephyr_library_sources_ifdef(CONFIG_SEMIHOST semihost.c) +zephyr_library_sources_ifdef(CONFIG_PM_S2RAM pm_s2ram.c pm_s2ram.S) +zephyr_library_sources_ifdef(CONFIG_ARCH_CACHE cache.c) +zephyr_library_sources_ifdef(CONFIG_SW_VECTOR_RELAY irq_relay.S) + +if(CONFIG_NULL_POINTER_EXCEPTION_DETECTION_DWT) + zephyr_library_sources(debug.c) +endif() + +if(CONFIG_CORTEX_M_DWT) + if (CONFIG_TIMING_FUNCTIONS) + zephyr_library_sources(timing.c) + endif() +endif() + +if (CONFIG_SW_VECTOR_RELAY) +if (CONFIG_CPU_CORTEX_M_HAS_VTOR) + set(relay_vector_table_sort_key relay_vectors) +else() +# Using 0x0 prefix will result in placing the relay vector table section +# at the beginning of ROM_START (i.e before other sections in ROM_START); +# required for CPUs without VTOR, which need to have the exception vector +# table starting at a fixed address at the beginning of ROM. + set(relay_vector_table_sort_key 0x0relay_vectors) +endif() + +zephyr_linker_sources( + ROM_START + SORT_KEY ${relay_vector_table_sort_key} + relay_vector_table.ld + ) +endif() + +if (CONFIG_SW_VECTOR_RELAY OR CONFIG_SW_VECTOR_RELAY_CLIENT) +zephyr_linker_sources( + RAM_SECTIONS + vt_pointer_section.ld + ) +endif() diff --git a/arch/arm/core/cortex_m/Kconfig b/arch/arm/core/cortex_m/Kconfig new file mode 100644 index 00000000000..95e05604783 --- /dev/null +++ b/arch/arm/core/cortex_m/Kconfig @@ -0,0 +1,472 @@ +# ARM Cortex-M platform configuration options + +# Copyright (c) 2014-2015 Wind River Systems, Inc. +# SPDX-License-Identifier: Apache-2.0 + +# NOTE: We have the specific core implementations first and outside of the +# if CPU_CORTEX_M block so that SoCs can select which core they are using +# without having to select all the options related to that core. Everything +# else is captured inside the if CPU_CORTEX_M block so they are not exposed +# if one select a different ARM Cortex Family (Cortex-A or Cortex-R) + +config CPU_CORTEX_M0 + bool + select CPU_CORTEX_M + select ARMV6_M_ARMV8_M_BASELINE + help + This option signifies the use of a Cortex-M0 CPU + +config CPU_CORTEX_M0PLUS + bool + select CPU_CORTEX_M + select ARMV6_M_ARMV8_M_BASELINE + help + This option signifies the use of a Cortex-M0+ CPU + +config CPU_CORTEX_M1 + bool + select CPU_CORTEX_M + select ARMV6_M_ARMV8_M_BASELINE + help + This option signifies the use of a Cortex-M1 CPU + +config CPU_CORTEX_M3 + bool + select CPU_CORTEX_M + select ARMV7_M_ARMV8_M_MAINLINE + help + This option signifies the use of a Cortex-M3 CPU + +config CPU_CORTEX_M4 + bool + select CPU_CORTEX_M + select ARMV7_M_ARMV8_M_MAINLINE + select ARMV7_M_ARMV8_M_FP if CPU_HAS_FPU + help + This option signifies the use of a Cortex-M4 CPU + +config CPU_CORTEX_M23 + bool + select CPU_CORTEX_M + select ARMV8_M_BASELINE + select ARMV8_M_SE if CPU_HAS_TEE + help + This option signifies the use of a Cortex-M23 CPU + +config CPU_CORTEX_M33 + bool + select CPU_CORTEX_M + select ARMV8_M_MAINLINE + select ARMV8_M_SE if CPU_HAS_TEE + select ARMV7_M_ARMV8_M_FP if CPU_HAS_FPU + help + This option signifies the use of a Cortex-M33 CPU + +config CPU_CORTEX_M55 + bool + select CPU_CORTEX_M + select ARMV8_1_M_MAINLINE + select ARMV8_M_SE if CPU_HAS_TEE + select ARMV7_M_ARMV8_M_FP if CPU_HAS_FPU + select CPU_HAS_DCACHE + select CPU_HAS_ICACHE + help + This option signifies the use of a Cortex-M55 CPU + +config CPU_CORTEX_M7 + bool + select CPU_CORTEX_M + select ARMV7_M_ARMV8_M_MAINLINE + select ARMV7_M_ARMV8_M_FP if CPU_HAS_FPU + select CPU_HAS_DCACHE + select CPU_HAS_ICACHE + help + This option signifies the use of a Cortex-M7 CPU + +if CPU_CORTEX_M + +config CPU_CORTEX_M_HAS_SYSTICK + bool + help + This option is enabled when the CPU implements the SysTick timer. + +config DCACHE_LINE_SIZE + default 32 + +config ICACHE_LINE_SIZE + default 32 + +config CPU_CORTEX_M_HAS_DWT + bool + depends on !CPU_CORTEX_M0 && !CPU_CORTEX_M0PLUS && !CPU_CORTEX_M1 + help + This option signifies that the CPU implements the Data Watchpoint and + Trace (DWT) unit specified by the ARMv7-M and above. + + While ARMv6-M does define a "DWT" unit, this is significantly different + from the DWT specified by the ARMv7-M and above in terms of both feature + set and register mappings. + +config CPU_CORTEX_M_HAS_BASEPRI + bool + depends on ARMV7_M_ARMV8_M_MAINLINE + help + This option signifies the CPU has the BASEPRI register. + + The BASEPRI register defines the minimum priority for + exception processing. When BASEPRI is set to a nonzero + value, it prevents the activation of all exceptions with + the same or lower priority level as the BASEPRI value. + Always present in CPUs that implement the ARMv7-M or + ARM8-M Mainline architectures. + +config CPU_CORTEX_M_HAS_VTOR + bool + depends on !CPU_CORTEX_M0 && !CPU_CORTEX_M1 + help + This option signifies the CPU has the VTOR register. + The VTOR indicates the offset of the vector table base + address from memory address 0x00000000. Always present + in CPUs implementing the ARMv7-M or ARMv8-M architectures. + Optional in CPUs implementing ARMv6-M, ARMv8-M Baseline + architectures (except for Cortex-M0/M1, where it is never + implemented). + +config CPU_CORTEX_M_HAS_SPLIM + bool + depends on ARMV8_M_MAINLINE || (ARMV8_M_SE && !ARM_NONSECURE_FIRMWARE) + help + This option signifies the CPU has the MSPLIM, PSPLIM registers. + + The stack pointer limit registers, MSPLIM, PSPLIM, limit the + extend to which the Main and Process Stack Pointers, respectively, + can descend. MSPLIM, PSPLIM are always present in ARMv8-M + MCUs that implement the ARMv8-M Main Extension (Mainline). + + In an ARMv8-M Mainline implementation with the Security Extension + the MSPLIM, PSPLIM registers have additional Secure instances. + In an ARMv8-M Baseline implementation with the Security Extension + the MSPLIM, PSPLIM registers have only Secure instances. + +config CPU_CORTEX_M_HAS_PROGRAMMABLE_FAULT_PRIOS + bool + depends on ARMV7_M_ARMV8_M_MAINLINE + help + This option signifies the CPU may trigger system faults + (other than HardFault) with configurable priority, and, + therefore, it needs to reserve a priority level for them. + +config CPU_CORTEX_M0_HAS_VECTOR_TABLE_REMAP + bool + depends on ARMV6_M_ARMV8_M_BASELINE + help + This option signifies the Cortex-M0 has some mechanisms that can map + the vector table to SRAM + +config CPU_CORTEX_M_HAS_CMSE + bool + depends on ARMV8_M_BASELINE || ARMV8_M_MAINLINE + help + This option signifies the Cortex-M CPU has the CMSE intrinsics. + +config ARMV6_M_ARMV8_M_BASELINE + bool + select ATOMIC_OPERATIONS_C if !ARMV8_M_BASELINE + select ISA_THUMB2 + help + This option signifies the use of an ARMv6-M processor + implementation, or the use of an ARMv8-M processor + supporting the Baseline implementation. + + Notes: + - A Processing Element (PE) without the Main Extension + is also referred to as a Baseline Implementation. A + Baseline implementation has a subset of the instructions, + registers, and features, of a Mainline implementation. + - ARMv6-M compatibility is provided by all ARMv8-M + implementations. + +config ARMV8_M_BASELINE + bool + select ARMV6_M_ARMV8_M_BASELINE + select CPU_CORTEX_M_HAS_CMSE + help + This option signifies the use of an ARMv8-M processor + implementation. + + ARMv8-M Baseline includes additional features + not present in the ARMv6-M architecture. + +config ARMV7_M_ARMV8_M_MAINLINE + bool + select ATOMIC_OPERATIONS_BUILTIN + select ISA_THUMB2 + select CPU_CORTEX_M_HAS_BASEPRI + select CPU_CORTEX_M_HAS_VTOR + select CPU_CORTEX_M_HAS_PROGRAMMABLE_FAULT_PRIOS + select CPU_CORTEX_M_HAS_SYSTICK + help + This option signifies the use of an ARMv7-M processor + implementation, or the use of a backwards-compatible + ARMv8-M processor implementation supporting the Main + Extension. + + Notes: + - A Processing Element (PE) with the Main Extension is also + referred to as a Mainline Implementation. + - ARMv7-M compatibility requires the Main Extension. + + From https://developer.arm.com/products/architecture/m-profile: + The Main Extension provides backwards compatibility + with ARMv7-M. + +config ARMV8_M_MAINLINE + bool + select ARMV7_M_ARMV8_M_MAINLINE + select CPU_CORTEX_M_HAS_SPLIM + select CPU_CORTEX_M_HAS_CMSE + help + This option signifies the use of an ARMv8-M processor + implementation, supporting the Main Extension. + + ARMv8-M Main Extension includes additional features + not present in the ARMv7-M architecture. + +config ARMV8_1_M_MAINLINE + bool + select ARMV8_M_MAINLINE + help + This option signifies the use of an ARMv8.1-M processor + implementation, supporting the Main Extension. + + ARMv8.1-M Main Extension includes additional features + not present in the ARMv8-M architecture. + +config ARMV8_M_SE + bool + depends on ARMV8_M_BASELINE || ARMV8_M_MAINLINE + select CPU_CORTEX_M_HAS_SPLIM if !ARM_NONSECURE_FIRMWARE + help + This option signifies the use of an ARMv8-M processor + implementation (Baseline or Mainline) supporting the + Security Extensions. + +config ARMV7_M_ARMV8_M_FP + bool + depends on ARMV7_M_ARMV8_M_MAINLINE && !CPU_CORTEX_M3 + imply FPU_SHARING + help + This option signifies the use of an ARMv7-M processor + implementation, or the use of an ARMv8-M processor + implementation supporting the Floating-Point Extension. + +config ARMV8_M_DSP + bool + depends on ARMV8_M_MAINLINE + help + This option signifies the use of an ARMv8-M processor + implementation supporting the DSP Extension. + +config ARMV8_1_M_MVEI + bool + depends on ARMV8_1_M_MAINLINE + depends on ARMV8_M_DSP + help + This option signifies the use of an ARMv8.1-M processor implementation + supporting the M-Profile Vector Extension (MVE) integer instruction set. + +config ARMV8_1_M_MVEF + bool + depends on ARMV8_1_M_MVEI + help + This option signifies the use of an ARMv8.1-M processor implementation + supporting the M-Profile Vector Extension (MVE) floating-point + instruction set. + +menu "ARM Cortex-M0/M0+/M1/M3/M4/M7/M23/M33 options" + depends on ARMV6_M_ARMV8_M_BASELINE || ARMV7_M_ARMV8_M_MAINLINE + +config GEN_ISR_TABLES + default y + +config ZERO_LATENCY_IRQS + bool "Zero-latency interrupts" + depends on CPU_CORTEX_M_HAS_BASEPRI + help + The kernel may reserve some of the highest interrupts priorities in + the system for its own use. These interrupts will not be masked + by interrupt locking. + When connecting interrupts the kernel will offset all interrupts + to lower priority than those reserved by the kernel. + Zero-latency interrupt can be used to set up an interrupt at the + highest interrupt priority which will not be blocked by interrupt + locking. + Since Zero-latency ISRs will run in the same priority or possibly at + higher priority than the rest of the kernel they cannot use any + kernel functionality. + +config ZERO_LATENCY_LEVELS + int "Number of interrupt priority levels reserved for zero latency" + depends on ZERO_LATENCY_IRQS + range 1 255 + help + The amount of interrupt priority levels reserved for zero latency + interrupts. Increase this value to reserve more than one priority + level for zero latency interrupts. + +config DYNAMIC_DIRECT_INTERRUPTS + bool "Support for dynamic direct interrupts" + depends on DYNAMIC_INTERRUPTS + help + Direct interrupts are designed for performance-critical interrupt + handling and do not go through all of the common interrupt handling + code. This option enables the installation of interrupt service + routines for direct interrupts at runtime. + Note: this requires enabling support for dynamic interrupts in the + kernel. + +config SW_VECTOR_RELAY + bool "Software Vector Relay" + help + When building a bootloader firmware this option adds a + vector table relay handler and a vector relay table, to + relay interrupts based on a vector table pointer. + This is only required but not limited to Cortex-M Baseline CPUs + with no hardware vector table relocation mechanisms (e.g. VTOR). + +config SW_VECTOR_RELAY_CLIENT + bool "Software Vector Relay (client)" + default y if BOOTLOADER_MCUBOOT && !CPU_CORTEX_M0_HAS_VECTOR_TABLE_REMAP + depends on !CPU_CORTEX_M_HAS_VTOR + help + Another image has enabled SW_VECTOR_RELAY, and will be forwarding + exceptions and HW interrupts to this image. Enable this option to make + sure the vector table pointer in RAM is set properly by the image upon + initialization. + +config CORTEX_M_DWT + bool "Data Watchpoint and Trace (DWT)" + depends on CPU_CORTEX_M_HAS_DWT + default y if TIMING_FUNCTIONS + help + Enable and use the Data Watchpoint and Trace (DWT) unit for + timing functions. + +config CORTEX_M_DEBUG_MONITOR_HOOK + bool "Debug monitor interrupt for debugging" + depends on !ARMV6_M_ARMV8_M_BASELINE + help + Enable this option to configure debug monitor exception to low priority + for debugging purposes. + +# enabled, which may increase ESF stacking requirements for +# threads. +config TEST_EXTRA_STACK_SIZE + default 512 if TEST_ARM_CORTEX_M && FPU_SHARING + +config TRAP_UNALIGNED_ACCESS + bool "Unaligned access trap" + depends on !ARMV6_M_ARMV8_M_BASELINE + help + If enabled, the CPU generates a UsageFault exception when executing a + halfword or word access. + +endmenu + +# Implement the null pointer detection using either the Data Watchpoint and +# Trace Unit and the Debug Monitor Exception, or the Memory Protection Unit. + +choice NULL_POINTER_EXCEPTION_DETECTION + bool "Null-pointer exception" + # Disable this until https://github.com/zephyrproject-rtos/zephyr/issues/32984 is fixed + # default NULL_POINTER_EXCEPTION_DETECTION_DWT if TEST_ARM_CORTEX_M && !ARM_NONSECURE_FIRMWARE && CPU_CORTEX_M_HAS_DWT + default NULL_POINTER_EXCEPTION_DETECTION_MPU if TEST_ARM_CORTEX_M && !ARM_NONSECURE_FIRMWARE && ARM_MPU && !CPU_CORTEX_M_HAS_DWT + default NULL_POINTER_EXCEPTION_DETECTION_NONE + help + There are 2 implementations available, one based + on DWT and the other based on MPU. Use this choice + symbol to select one of the options. By default the + feature is disabled. In the test suite the feature + is enabled and the DWT-based solution is preferred. + +config NULL_POINTER_EXCEPTION_DETECTION_NONE + bool "No null pointer exception detection" + help + Null pointer exception detection feature is not + enabled. + +config NULL_POINTER_EXCEPTION_DETECTION_DWT + bool "Use DWT for null pointer exception detection" + depends on CPU_CORTEX_M_HAS_DWT + depends on !TRUSTED_EXECUTION_NONSECURE + select CORTEX_M_DWT + select CORTEX_M_NULL_POINTER_EXCEPTION + help + Null pointer dereference detection implemented + using the DWT unit functionality. + Notes: + - Not enabled for Non-Secure FW images, where + null-pointer dereferencing is likely caught as + a SecureFault. + - Requires DWT functionality in the Cortex-M SoC + implementation (1 comparator for ARMv7-M, 2 comparators + for ARMv8-M). + - Requires the Cortex-M core be in normal mode. + +config NULL_POINTER_EXCEPTION_DETECTION_MPU + bool "Use MPU for null pointer exception detection" + depends on !TRUSTED_EXECUTION_NONSECURE + depends on ARM_MPU + select CORTEX_M_NULL_POINTER_EXCEPTION + help + Null pointer dereference detection implemented + using MPU functionality. + Notes: + - Mutually exclusive to the DWT-based solution + - Not enabled for Non-Secure FW images, where + null-pointer dereferencing is likely caught as + a SecureFault. + - Requires MPU functionality to be present and + enabled. The implementation consumes 1 MPU region. + - In ARMv8-M, explicit null-pointer dereference + detection with MPU requires, additionally, that + the area: [0x0, + CORTEX_M_NULL_POINTER_EXCEPTION_PAGE_SIZE) + is not unmapped (covered by an MPU region already). + If it is unmapped null-pointer dereferencing may + still be indirectly detected (e.g. via a precise + Bus access fault), but this is not guaranteed. A + build-time message warns the user of this scenario. + +endchoice + +config CORTEX_M_NULL_POINTER_EXCEPTION + bool + help + Enable and use the null pointer exception option. + This is a debug feature in Cortex-M, allowing for + detecting null pointer dereferencing (raising a + CPU fault). Supporting the feature results in an + increased code footprint, determined by option + CORTEX_M_NULL_POINTER_EXCEPTION_PAGE_SIZE. + + Note: this hidden option is selected by the choice + symbols corresponding to the DWT-based or to the + MPU-based solution. + +if CORTEX_M_NULL_POINTER_EXCEPTION + +config CORTEX_M_NULL_POINTER_EXCEPTION_PAGE_SIZE + hex "Size of paged unmapped to implement null pointer detection" + default 0x400 + help + Size of the page reserved for detecting null pointer + dereferencing. Must be a power of two. A large value + offers enhanced detection performance to the cost of + wasting a large flash area that code may not use. + +endif # CORTEX_M_NULL_POINTER_EXCEPTION + +rsource "tz/Kconfig" + +endif # CPU_CORTEX_M diff --git a/arch/arm/core/aarch32/cortex_m/__aeabi_read_tp.S b/arch/arm/core/cortex_m/__aeabi_read_tp.S similarity index 100% rename from arch/arm/core/aarch32/cortex_m/__aeabi_read_tp.S rename to arch/arm/core/cortex_m/__aeabi_read_tp.S diff --git a/arch/arm/core/aarch32/cortex_m/cache.c b/arch/arm/core/cortex_m/cache.c similarity index 100% rename from arch/arm/core/aarch32/cortex_m/cache.c rename to arch/arm/core/cortex_m/cache.c diff --git a/arch/arm/core/aarch32/cortex_m/cmse/CMakeLists.txt b/arch/arm/core/cortex_m/cmse/CMakeLists.txt similarity index 100% rename from arch/arm/core/aarch32/cortex_m/cmse/CMakeLists.txt rename to arch/arm/core/cortex_m/cmse/CMakeLists.txt diff --git a/arch/arm/core/aarch32/cortex_m/cmse/arm_core_cmse.c b/arch/arm/core/cortex_m/cmse/arm_core_cmse.c similarity index 99% rename from arch/arm/core/aarch32/cortex_m/cmse/arm_core_cmse.c rename to arch/arm/core/cortex_m/cmse/arm_core_cmse.c index 7ddab21d547..aac96472ecf 100644 --- a/arch/arm/core/aarch32/cortex_m/cmse/arm_core_cmse.c +++ b/arch/arm/core/cortex_m/cmse/arm_core_cmse.c @@ -5,7 +5,7 @@ */ #include -#include +#include int arm_cmse_mpu_region_get(uint32_t addr) { diff --git a/arch/arm/core/aarch32/cortex_m/coredump.c b/arch/arm/core/cortex_m/coredump.c similarity index 100% rename from arch/arm/core/aarch32/cortex_m/coredump.c rename to arch/arm/core/cortex_m/coredump.c diff --git a/arch/arm/core/cortex_m/cpu_idle.S b/arch/arm/core/cortex_m/cpu_idle.S new file mode 100644 index 00000000000..8acae5ddb13 --- /dev/null +++ b/arch/arm/core/cortex_m/cpu_idle.S @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief ARM Cortex-M power management + * + */ + +#include +#include + +#if defined(CONFIG_ARM_ON_EXIT_CPU_IDLE) +#include +#endif + +_ASM_FILE_PROLOGUE + +GTEXT(z_arm_cpu_idle_init) +GTEXT(arch_cpu_idle) +GTEXT(arch_cpu_atomic_idle) + +#define _SCB_SCR 0xE000ED10 + +#define _SCB_SCR_SEVONPEND (1 << 4) +#define _SCB_SCR_SLEEPDEEP (1 << 2) +#define _SCB_SCR_SLEEPONEXIT (1 << 1) +#define _SCR_INIT_BITS _SCB_SCR_SEVONPEND + +.macro _sleep_if_allowed wait_instruction +#if defined(CONFIG_ARM_ON_ENTER_CPU_IDLE_HOOK) + push {r0, lr} + bl z_arm_on_enter_cpu_idle + /* Skip the wait instruction if on_enter_cpu_idle() returns false. */ + cmp r0, #0 + beq _skip_\@ +#endif /* CONFIG_ARM_ON_ENTER_CPU_IDLE_HOOK */ + + /* + * Wait for all memory transactions to complete before entering low + * power state. + */ + dsb + \wait_instruction + +#if defined(CONFIG_ARM_ON_EXIT_CPU_IDLE) + /* Inline the macro provided by SoC-specific code */ + SOC_ON_EXIT_CPU_IDLE +#endif /* CONFIG_ARM_ON_EXIT_CPU_IDLE */ + +#if defined(CONFIG_ARM_ON_ENTER_CPU_IDLE_HOOK) +_skip_\@: +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + pop {r0, r1} + mov lr, r1 +#else + pop {r0, lr} +#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ +#endif /* CONFIG_ARM_ON_ENTER_CPU_IDLE_HOOK */ +.endm + +/** + * + * @brief Initialization of CPU idle + * + * Only called by arch_kernel_init(). Sets SEVONPEND bit once for the system's + * duration. + * + * C function prototype: + * + * void z_arm_cpu_idle_init(void); + */ + +SECTION_FUNC(TEXT, z_arm_cpu_idle_init) + ldr r1, =_SCB_SCR + movs.n r2, #_SCR_INIT_BITS + str r2, [r1] + bx lr + +SECTION_FUNC(TEXT, arch_cpu_idle) +#if defined(CONFIG_TRACING) || \ + defined(CONFIG_ARM_ON_ENTER_CPU_IDLE_PREPARE_HOOK) + push {r0, lr} + +#ifdef CONFIG_TRACING + bl sys_trace_idle +#endif +#ifdef CONFIG_ARM_ON_ENTER_CPU_IDLE_PREPARE_HOOK + bl z_arm_on_enter_cpu_idle_prepare +#endif + +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + pop {r0, r1} + mov lr, r1 +#else + pop {r0, lr} +#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ +#endif + +#if defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + /* + * PRIMASK is always cleared on ARMv7-M and ARMv8-M Mainline (not used + * for interrupt locking), and configuring BASEPRI to the lowest + * priority to ensure wake-up will cause interrupts to be serviced + * before entering low power state. + * + * Set PRIMASK before configuring BASEPRI to prevent interruption + * before wake-up. + */ + cpsid i + + /* + * Set wake-up interrupt priority to the lowest and synchronise to + * ensure that this is visible to the WFI instruction. + */ + eors.n r0, r0 + msr BASEPRI, r0 + isb +#else + /* + * For all the other ARM architectures that do not implement BASEPRI, + * PRIMASK is used as the interrupt locking mechanism, and it is not + * necessary to set PRIMASK here, as PRIMASK would have already been + * set by the caller as part of interrupt locking if necessary + * (i.e. if the caller sets _kernel.idle). + */ +#endif /* CONFIG_ARMV7_M_ARMV8_M_MAINLINE */ + + /* Enter low power state */ + _sleep_if_allowed wfi + + /* + * Clear PRIMASK and flush instruction buffer to immediately service + * the wake-up interrupt. + */ + cpsie i + isb + + bx lr + +SECTION_FUNC(TEXT, arch_cpu_atomic_idle) +#if defined(CONFIG_TRACING) || \ + defined(CONFIG_ARM_ON_ENTER_CPU_IDLE_PREPARE_HOOK) + push {r0, lr} + +#ifdef CONFIG_TRACING + bl sys_trace_idle +#endif +#ifdef CONFIG_ARM_ON_ENTER_CPU_IDLE_PREPARE_HOOK + bl z_arm_on_enter_cpu_idle_prepare +#endif + +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + pop {r0, r1} + mov lr, r1 +#else + pop {r0, lr} +#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ +#endif + /* + * Lock PRIMASK while sleeping: wfe will still get interrupted by + * incoming interrupts but the CPU will not service them right away. + */ + cpsid i + + /* + * No need to set SEVONPEND, it's set once in z_arm_cpu_idle_init() + * and never touched again. + */ + + /* r0: interrupt mask from caller */ + +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + /* No BASEPRI, call wfe directly + * (SEVONPEND is set in z_arm_cpu_idle_init()) + */ + _sleep_if_allowed wfe + + cmp r0, #0 + bne _irq_disabled + cpsie i +_irq_disabled: + +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + /* r1: zero, for setting BASEPRI (needs a register) */ + eors.n r1, r1 + + /* unlock BASEPRI so wfe gets interrupted by incoming interrupts */ + msr BASEPRI, r1 + + _sleep_if_allowed wfe + + msr BASEPRI, r0 + cpsie i +#else +#error Unknown ARM architecture +#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ + bx lr diff --git a/arch/arm/core/aarch32/cortex_m/debug.c b/arch/arm/core/cortex_m/debug.c similarity index 99% rename from arch/arm/core/aarch32/cortex_m/debug.c rename to arch/arm/core/cortex_m/debug.c index 70394b2d361..8d83cd07f2f 100644 --- a/arch/arm/core/aarch32/cortex_m/debug.c +++ b/arch/arm/core/cortex_m/debug.c @@ -12,7 +12,7 @@ #include #include -#include +#include /** * @brief Assess whether a debug monitor event should be treated as an error diff --git a/arch/arm/core/aarch32/cortex_m/exc_exit.S b/arch/arm/core/cortex_m/exc_exit.S similarity index 100% rename from arch/arm/core/aarch32/cortex_m/exc_exit.S rename to arch/arm/core/cortex_m/exc_exit.S diff --git a/arch/arm/core/aarch32/cortex_m/fault.c b/arch/arm/core/cortex_m/fault.c similarity index 100% rename from arch/arm/core/aarch32/cortex_m/fault.c rename to arch/arm/core/cortex_m/fault.c diff --git a/arch/arm/core/aarch32/cortex_m/fault_s.S b/arch/arm/core/cortex_m/fault_s.S similarity index 100% rename from arch/arm/core/aarch32/cortex_m/fault_s.S rename to arch/arm/core/cortex_m/fault_s.S diff --git a/arch/arm/core/aarch32/cortex_m/fpu.c b/arch/arm/core/cortex_m/fpu.c similarity index 96% rename from arch/arm/core/aarch32/cortex_m/fpu.c rename to arch/arm/core/cortex_m/fpu.c index 0e6084470e9..a9c964d14d1 100644 --- a/arch/arm/core/aarch32/cortex_m/fpu.c +++ b/arch/arm/core/cortex_m/fpu.c @@ -7,7 +7,7 @@ #include #include -#include +#include /** * @file @brief Helper functions for saving and restoring the FP context. diff --git a/arch/arm/core/aarch32/cortex_m/irq_init.c b/arch/arm/core/cortex_m/irq_init.c similarity index 100% rename from arch/arm/core/aarch32/cortex_m/irq_init.c rename to arch/arm/core/cortex_m/irq_init.c diff --git a/arch/arm/core/cortex_m/irq_manage.c b/arch/arm/core/cortex_m/irq_manage.c new file mode 100644 index 00000000000..3940d5246d4 --- /dev/null +++ b/arch/arm/core/cortex_m/irq_manage.c @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief ARM Cortex-M interrupt management + * + * + * Interrupt management: enabling/disabling and dynamic ISR + * connecting/replacing. SW_ISR_TABLE_DYNAMIC has to be enabled for + * connecting ISRs at runtime. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void z_arm_reserved(void); + +#define NUM_IRQS_PER_REG 32 +#define REG_FROM_IRQ(irq) (irq / NUM_IRQS_PER_REG) +#define BIT_FROM_IRQ(irq) (irq % NUM_IRQS_PER_REG) + +#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) + +void arch_irq_enable(unsigned int irq) +{ + NVIC_EnableIRQ((IRQn_Type)irq); +} + +void arch_irq_disable(unsigned int irq) +{ + NVIC_DisableIRQ((IRQn_Type)irq); +} + +int arch_irq_is_enabled(unsigned int irq) +{ + return NVIC->ISER[REG_FROM_IRQ(irq)] & BIT(BIT_FROM_IRQ(irq)); +} + +/** + * @internal + * + * @brief Set an interrupt's priority + * + * The priority is verified if ASSERT_ON is enabled. The maximum number + * of priority levels is a little complex, as there are some hardware + * priority levels which are reserved. + */ +void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags) +{ + /* The kernel may reserve some of the highest priority levels. + * So we offset the requested priority level with the number + * of priority levels reserved by the kernel. + */ + + /* If we have zero latency interrupts, those interrupts will + * run at a priority level which is not masked by irq_lock(). + * Our policy is to express priority levels with special properties + * via flags + */ + if (IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) && (flags & IRQ_ZERO_LATENCY)) { + if (ZERO_LATENCY_LEVELS == 1) { + prio = _EXC_ZERO_LATENCY_IRQS_PRIO; + } else { + /* Use caller supplied prio level as-is */ + } + } else { + prio += _IRQ_PRIO_OFFSET; + } + + /* The last priority level is also used by PendSV exception, but + * allow other interrupts to use the same level, even if it ends up + * affecting performance (can still be useful on systems with a + * reduced set of priorities, like Cortex-M0/M0+). + */ + __ASSERT(prio <= (BIT(NUM_IRQ_PRIO_BITS) - 1), + "invalid priority %d for %d irq! values must be less than %lu\n", + prio - _IRQ_PRIO_OFFSET, irq, + BIT(NUM_IRQ_PRIO_BITS) - (_IRQ_PRIO_OFFSET)); + NVIC_SetPriority((IRQn_Type)irq, prio); +} + +#endif /* !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) */ + +void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf); + +/** + * + * @brief Spurious interrupt handler + * + * Installed in all _sw_isr_table slots at boot time. Throws an error if + * called. + * + */ +void z_irq_spurious(const void *unused) +{ + ARG_UNUSED(unused); + + z_arm_fatal_error(K_ERR_SPURIOUS_IRQ, NULL); +} + +#ifdef CONFIG_PM +void _arch_isr_direct_pm(void) +{ +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + unsigned int key; + + /* irq_lock() does what we want for this CPU */ + key = irq_lock(); +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + /* Lock all interrupts. irq_lock() will on this CPU only disable those + * lower than BASEPRI, which is not what we want. See comments in + * arch/arm/core/isr_wrapper.S + */ + __asm__ volatile("cpsid i" : : : "memory"); +#else +#error Unknown ARM architecture +#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ + + if (_kernel.idle) { + _kernel.idle = 0; + z_pm_save_idle_exit(); + } + +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + irq_unlock(key); +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + __asm__ volatile("cpsie i" : : : "memory"); +#else +#error Unknown ARM architecture +#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ + +} +#endif + +#if defined(CONFIG_ARM_SECURE_FIRMWARE) +/** + * + * @brief Set the target security state for the given IRQ + * + * Function sets the security state (Secure or Non-Secure) targeted + * by the given irq. It requires ARMv8-M MCU. + * It is only compiled if ARM_SECURE_FIRMWARE is defined. + * It should only be called while in Secure state, otherwise, a write attempt + * to NVIC.ITNS register is write-ignored(WI), as the ITNS register is not + * banked between security states and, therefore, has no Non-Secure instance. + * + * It shall return the resulting target state of the given IRQ, indicating + * whether the operation has been performed successfully. + * + * @param irq IRQ line + * @param irq_target_state the desired IRQ target state + * + * @return The resulting target state of the given IRQ + */ +irq_target_state_t irq_target_state_set(unsigned int irq, + irq_target_state_t irq_target_state) +{ + uint32_t result; + + if (irq_target_state == IRQ_TARGET_STATE_SECURE) { + /* Set target to Secure */ + result = NVIC_ClearTargetState(irq); + } else { + /* Set target to Non-Secure */ + result = NVIC_SetTargetState(irq); + } + + if (result) { + return IRQ_TARGET_STATE_NON_SECURE; + } else { + return IRQ_TARGET_STATE_SECURE; + } +} + +/** + * + * @brief Determine whether the given IRQ targets the Secure state + * + * Function determines whether the given irq targets the Secure state + * or not (i.e. targets the Non-Secure state). It requires ARMv8-M MCU. + * It is only compiled if ARM_SECURE_FIRMWARE is defined. + * It should only be called while in Secure state, otherwise, a read attempt + * to NVIC.ITNS register is read-as-zero(RAZ), as the ITNS register is not + * banked between security states and, therefore, has no Non-Secure instance. + * + * @param irq IRQ line + * + * @return 1 if target state is Secure, 0 otherwise. + */ +int irq_target_state_is_secure(unsigned int irq) +{ + return NVIC_GetTargetState(irq) == 0; +} + +/** + * + * @brief Disable and set all interrupt lines to target Non-Secure state. + * + * The function is used to set all HW NVIC interrupt lines to target the + * Non-Secure state. The function shall only be called fron Secure state. + * + * Notes: + * - All NVIC interrupts are disabled before being routed to Non-Secure. + * - Bits corresponding to un-implemented interrupts are RES0, so writes + * will be ignored. + * +*/ +void irq_target_state_set_all_non_secure(void) +{ + int i; + + /* Disable (Clear) all NVIC interrupt lines. */ + for (i = 0; i < sizeof(NVIC->ICER) / sizeof(NVIC->ICER[0]); i++) { + NVIC->ICER[i] = 0xFFFFFFFF; + } + + barrier_dsync_fence_full(); + barrier_isync_fence_full(); + + /* Set all NVIC interrupt lines to target Non-Secure */ + for (i = 0; i < sizeof(NVIC->ITNS) / sizeof(NVIC->ITNS[0]); i++) { + NVIC->ITNS[i] = 0xFFFFFFFF; + } +} + +#endif /* CONFIG_ARM_SECURE_FIRMWARE */ + +#ifdef CONFIG_DYNAMIC_INTERRUPTS +#ifdef CONFIG_GEN_ISR_TABLES +int arch_irq_connect_dynamic(unsigned int irq, unsigned int priority, + void (*routine)(const void *parameter), + const void *parameter, uint32_t flags) +{ + z_isr_install(irq, routine, parameter); + z_arm_irq_priority_set(irq, priority, flags); + return irq; +} +#endif /* CONFIG_GEN_ISR_TABLES */ + +#ifdef CONFIG_DYNAMIC_DIRECT_INTERRUPTS +static inline void z_arm_irq_dynamic_direct_isr_dispatch(void) +{ + uint32_t irq = __get_IPSR() - 16; + + if (irq < IRQ_TABLE_SIZE) { + struct _isr_table_entry *isr_entry = &_sw_isr_table[irq]; + + isr_entry->isr(isr_entry->arg); + } +} + +ISR_DIRECT_DECLARE(z_arm_irq_direct_dynamic_dispatch_reschedule) +{ + z_arm_irq_dynamic_direct_isr_dispatch(); + + return 1; +} + +ISR_DIRECT_DECLARE(z_arm_irq_direct_dynamic_dispatch_no_reschedule) +{ + z_arm_irq_dynamic_direct_isr_dispatch(); + + return 0; +} + +#endif /* CONFIG_DYNAMIC_DIRECT_INTERRUPTS */ + +#endif /* CONFIG_DYNAMIC_INTERRUPTS */ diff --git a/arch/arm/core/aarch32/irq_relay.S b/arch/arm/core/cortex_m/irq_relay.S similarity index 100% rename from arch/arm/core/aarch32/irq_relay.S rename to arch/arm/core/cortex_m/irq_relay.S diff --git a/arch/arm/core/cortex_m/isr_wrapper.S b/arch/arm/core/cortex_m/isr_wrapper.S new file mode 100644 index 00000000000..f81b577804f --- /dev/null +++ b/arch/arm/core/cortex_m/isr_wrapper.S @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * Copyright (c) 2020 Stephanos Ioannidis + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief ARM Cortex-M wrapper for ISRs with parameter + * + * Wrapper installed in vector table for handling dynamic interrupts that accept + * a parameter. + */ +/* + * Tell armclang that stack alignment are ensured. + */ +.eabi_attribute Tag_ABI_align_preserved, 1 + +#include +#include +#include +#include +#include + + +_ASM_FILE_PROLOGUE + +GDATA(_sw_isr_table) + +GTEXT(_isr_wrapper) +GTEXT(z_arm_int_exit) + +/** + * + * @brief Wrapper around ISRs when inserted in software ISR table + * + * When inserted in the vector table, _isr_wrapper() demuxes the ISR table + * using the running interrupt number as the index, and invokes the registered + * ISR with its corresponding argument. When returning from the ISR, it + * determines if a context switch needs to happen (see documentation for + * z_arm_pendsv()) and pends the PendSV exception if so: the latter will + * perform the context switch itself. + * + */ +SECTION_FUNC(TEXT, _isr_wrapper) + + push {r0,lr} /* r0, lr are now the first items on the stack */ + +#ifdef CONFIG_TRACING_ISR + bl sys_trace_isr_enter +#endif + +#ifdef CONFIG_PM + /* + * All interrupts are disabled when handling idle wakeup. For tickless + * idle, this ensures that the calculation and programming of the + * device for the next timer deadline is not interrupted. For + * non-tickless idle, this ensures that the clearing of the kernel idle + * state is not interrupted. In each case, z_pm_save_idle_exit + * is called with interrupts disabled. + */ + + /* + * Disable interrupts to prevent nesting while exiting idle state. This + * is only necessary for the Cortex-M because it is the only ARM + * architecture variant that automatically enables interrupts when + * entering an ISR. + */ + cpsid i /* PRIMASK = 1 */ + + /* is this a wakeup from idle ? */ + ldr r2, =_kernel + /* requested idle duration, in ticks */ + ldr r0, [r2, #_kernel_offset_to_idle] + cmp r0, #0 + +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + beq _idle_state_cleared + movs.n r1, #0 + /* clear kernel idle state */ + str r1, [r2, #_kernel_offset_to_idle] + bl z_pm_save_idle_exit +_idle_state_cleared: + +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + ittt ne + movne r1, #0 + /* clear kernel idle state */ + strne r1, [r2, #_kernel_offset_to_idle] + blne z_pm_save_idle_exit +#else +#error Unknown ARM architecture +#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ + + cpsie i /* re-enable interrupts (PRIMASK = 0) */ + +#endif /* CONFIG_PM */ + +#if defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) + bl z_soc_irq_get_active +#else + mrs r0, IPSR /* get exception number */ +#endif /* CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ + +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + ldr r1, =16 + subs r0, r1 /* get IRQ number */ +#if defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) + push {r0} +#endif /* CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ + lsls r0, #3 /* table is 8-byte wide */ +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + sub r0, r0, #16 /* get IRQ number */ +#if defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) + push {r0} +#endif /* CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ + lsl r0, r0, #3 /* table is 8-byte wide */ +#else +#error Unknown ARM architecture +#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ + + ldr r1, =_sw_isr_table + add r1, r1, r0 /* table entry: ISRs must have their MSB set to stay + * in thumb mode */ + + ldm r1!,{r0,r3} /* arg in r0, ISR in r3 */ + blx r3 /* call ISR */ + +#if defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) + pop {r0} + bl z_soc_irq_eoi +#endif /* CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ + +#ifdef CONFIG_TRACING_ISR + bl sys_trace_isr_exit +#endif + +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + pop {r0, r3} + mov lr, r3 +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + pop {r0, lr} +#else +#error Unknown ARM architecture +#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ + + /* Use 'bx' instead of 'b' because 'bx' can jump further, and use + * 'bx' instead of 'blx' because exception return is done in + * z_arm_int_exit() */ + ldr r1, =z_arm_int_exit + bx r1 diff --git a/arch/arm/core/aarch32/cortex_m/pm_s2ram.S b/arch/arm/core/cortex_m/pm_s2ram.S similarity index 100% rename from arch/arm/core/aarch32/cortex_m/pm_s2ram.S rename to arch/arm/core/cortex_m/pm_s2ram.S diff --git a/arch/arm/core/aarch32/cortex_m/pm_s2ram.c b/arch/arm/core/cortex_m/pm_s2ram.c similarity index 100% rename from arch/arm/core/aarch32/cortex_m/pm_s2ram.c rename to arch/arm/core/cortex_m/pm_s2ram.c diff --git a/arch/arm/core/cortex_m/prep_c.c b/arch/arm/core/cortex_m/prep_c.c new file mode 100644 index 00000000000..329f7f8987d --- /dev/null +++ b/arch/arm/core/cortex_m/prep_c.c @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Full C support initialization + * + * + * Initialization of full C support: zero the .bss, copy the .data if XIP, + * call z_cstart(). + * + * Stack is available in this module, but not the global data/bss until their + * initialization is performed. + */ + +#include +#include +#include +#include + +#if defined(__GNUC__) +/* + * GCC can detect if memcpy is passed a NULL argument, however one of + * the cases of relocate_vector_table() it is valid to pass NULL, so we + * suppress the warning for this case. We need to do this before + * string.h is included to get the declaration of memcpy. + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnonnull" +#endif + +#include + +#if defined(CONFIG_SW_VECTOR_RELAY) || defined(CONFIG_SW_VECTOR_RELAY_CLIENT) +Z_GENERIC_SECTION(.vt_pointer_section) __attribute__((used)) +void *_vector_table_pointer; +#endif + +#ifdef CONFIG_CPU_CORTEX_M_HAS_VTOR + +#define VECTOR_ADDRESS ((uintptr_t)_vector_start) + +static inline void relocate_vector_table(void) +{ + SCB->VTOR = VECTOR_ADDRESS & SCB_VTOR_TBLOFF_Msk; + barrier_dsync_fence_full(); + barrier_isync_fence_full(); +} + +#else +#define VECTOR_ADDRESS 0 + +void __weak relocate_vector_table(void) +{ +#if defined(CONFIG_XIP) && (CONFIG_FLASH_BASE_ADDRESS != 0) || \ + !defined(CONFIG_XIP) && (CONFIG_SRAM_BASE_ADDRESS != 0) + size_t vector_size = (size_t)_vector_end - (size_t)_vector_start; + (void)memcpy(VECTOR_ADDRESS, _vector_start, vector_size); +#elif defined(CONFIG_SW_VECTOR_RELAY) || defined(CONFIG_SW_VECTOR_RELAY_CLIENT) + _vector_table_pointer = _vector_start; +#endif +} + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + +#endif /* CONFIG_CPU_CORTEX_M_HAS_VTOR */ + +#if defined(CONFIG_CPU_HAS_FPU) +static inline void z_arm_floating_point_init(void) +{ + /* + * Upon reset, the Co-Processor Access Control Register is, normally, + * 0x00000000. However, it might be left un-cleared by firmware running + * before Zephyr boot. + */ + SCB->CPACR &= (~(CPACR_CP10_Msk | CPACR_CP11_Msk)); + +#if defined(CONFIG_FPU) + /* + * Enable CP10 and CP11 Co-Processors to enable access to floating + * point registers. + */ +#if defined(CONFIG_USERSPACE) + /* Full access */ + SCB->CPACR |= CPACR_CP10_FULL_ACCESS | CPACR_CP11_FULL_ACCESS; +#else + /* Privileged access only */ + SCB->CPACR |= CPACR_CP10_PRIV_ACCESS | CPACR_CP11_PRIV_ACCESS; +#endif /* CONFIG_USERSPACE */ + /* + * Upon reset, the FPU Context Control Register is 0xC0000000 + * (both Automatic and Lazy state preservation is enabled). + */ +#if defined(CONFIG_MULTITHREADING) && !defined(CONFIG_FPU_SHARING) + /* Unshared FP registers (multithreading) mode. We disable the + * automatic stacking of FP registers (automatic setting of + * FPCA bit in the CONTROL register), upon exception entries, + * as the FP registers are to be used by a single context (and + * the use of FP registers in ISRs is not supported). This + * configuration improves interrupt latency and decreases the + * stack memory requirement for the (single) thread that makes + * use of the FP co-processor. + */ + FPU->FPCCR &= (~(FPU_FPCCR_ASPEN_Msk | FPU_FPCCR_LSPEN_Msk)); +#else + /* + * FP register sharing (multithreading) mode or single-threading mode. + * + * Enable both automatic and lazy state preservation of the FP context. + * The FPCA bit of the CONTROL register will be automatically set, if + * the thread uses the floating point registers. Because of lazy state + * preservation the volatile FP registers will not be stacked upon + * exception entry, however, the required area in the stack frame will + * be reserved for them. This configuration improves interrupt latency. + * The registers will eventually be stacked when the thread is swapped + * out during context-switch or if an ISR attempts to execute floating + * point instructions. + */ + FPU->FPCCR = FPU_FPCCR_ASPEN_Msk | FPU_FPCCR_LSPEN_Msk; +#endif /* CONFIG_FPU_SHARING */ + + /* Make the side-effects of modifying the FPCCR be realized + * immediately. + */ + barrier_dsync_fence_full(); + barrier_isync_fence_full(); + + /* Initialize the Floating Point Status and Control Register. */ +#if defined(CONFIG_ARMV8_1_M_MAINLINE) + /* + * For ARMv8.1-M with FPU, the FPSCR[18:16] LTPSIZE field must be set + * to 0b100 for "Tail predication not applied" as it's reset value + */ + __set_FPSCR(4 << FPU_FPDSCR_LTPSIZE_Pos); +#else + __set_FPSCR(0); +#endif + + /* + * Note: + * The use of the FP register bank is enabled, however the FP context + * will be activated (FPCA bit on the CONTROL register) in the presence + * of floating point instructions. + */ + +#endif /* CONFIG_FPU */ + + /* + * Upon reset, the CONTROL.FPCA bit is, normally, cleared. However, + * it might be left un-cleared by firmware running before Zephyr boot. + * We must clear this bit to prevent errors in exception unstacking. + * + * Note: + * In Sharing FP Registers mode CONTROL.FPCA is cleared before switching + * to main, so it may be skipped here (saving few boot cycles). + * + * If CONFIG_INIT_ARCH_HW_AT_BOOT is set, CONTROL is cleared at reset. + */ +#if (!defined(CONFIG_FPU) || !defined(CONFIG_FPU_SHARING)) && \ + (!defined(CONFIG_INIT_ARCH_HW_AT_BOOT)) + + __set_CONTROL(__get_CONTROL() & (~(CONTROL_FPCA_Msk))); +#endif +} + +#endif /* CONFIG_CPU_HAS_FPU */ + +extern FUNC_NORETURN void z_cstart(void); + +/** + * + * @brief Prepare to and run C code + * + * This routine prepares for the execution of and runs C code. + * + */ +void z_arm_prep_c(void) +{ + relocate_vector_table(); +#if defined(CONFIG_CPU_HAS_FPU) + z_arm_floating_point_init(); +#endif + z_bss_zero(); + z_data_copy(); +#if defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) + /* Invoke SoC-specific interrupt controller initialization */ + z_soc_irq_init(); +#else + z_arm_interrupt_init(); +#endif /* CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ + z_cstart(); + CODE_UNREACHABLE; +} diff --git a/arch/arm/core/aarch32/cortex_m/relay_vector_table.ld b/arch/arm/core/cortex_m/relay_vector_table.ld similarity index 100% rename from arch/arm/core/aarch32/cortex_m/relay_vector_table.ld rename to arch/arm/core/cortex_m/relay_vector_table.ld diff --git a/arch/arm/core/aarch32/cortex_m/reset.S b/arch/arm/core/cortex_m/reset.S similarity index 100% rename from arch/arm/core/aarch32/cortex_m/reset.S rename to arch/arm/core/cortex_m/reset.S diff --git a/arch/arm/core/aarch32/cortex_m/scb.c b/arch/arm/core/cortex_m/scb.c similarity index 100% rename from arch/arm/core/aarch32/cortex_m/scb.c rename to arch/arm/core/cortex_m/scb.c diff --git a/arch/arm/core/aarch32/cortex_m/semihost.c b/arch/arm/core/cortex_m/semihost.c similarity index 100% rename from arch/arm/core/aarch32/cortex_m/semihost.c rename to arch/arm/core/cortex_m/semihost.c diff --git a/arch/arm/core/cortex_m/swap.c b/arch/arm/core/cortex_m/swap.c new file mode 100644 index 00000000000..9a597ef219d --- /dev/null +++ b/arch/arm/core/cortex_m/swap.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018 Linaro, Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +/* The 'key' actually represents the BASEPRI register + * prior to disabling interrupts via the BASEPRI mechanism. + * + * arch_swap() itself does not do much. + * + * It simply stores the intlock key (the BASEPRI value) parameter into + * current->basepri, and then triggers a PendSV exception, which does + * the heavy lifting of context switching. + + * This is the only place we have to save BASEPRI since the other paths to + * z_arm_pendsv all come from handling an interrupt, which means we know the + * interrupts were not locked: in that case the BASEPRI value is 0. + * + * Given that arch_swap() is called to effect a cooperative context switch, + * only the caller-saved integer registers need to be saved in the thread of the + * outgoing thread. This is all performed by the hardware, which stores it in + * its exception stack frame, created when handling the z_arm_pendsv exception. + * + * On ARMv6-M, the intlock key is represented by the PRIMASK register, + * as BASEPRI is not available. + */ +int arch_swap(unsigned int key) +{ + /* store off key and return value */ + _current->arch.basepri = key; + _current->arch.swap_return_value = -EAGAIN; + + /* set pending bit to make sure we will take a PendSV exception */ + SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; + + /* clear mask or enable all irqs to take a pendsv */ + irq_unlock(0); + + /* Context switch is performed here. Returning implies the + * thread has been context-switched-in again. + */ + return _current->arch.swap_return_value; +} diff --git a/arch/arm/core/cortex_m/swap_helper.S b/arch/arm/core/cortex_m/swap_helper.S new file mode 100644 index 00000000000..af1d0d791dd --- /dev/null +++ b/arch/arm/core/cortex_m/swap_helper.S @@ -0,0 +1,563 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * Copyright (c) 2017-2019 Nordic Semiconductor ASA. + * Copyright (c) 2020 Stephanos Ioannidis + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Thread context switching for ARM Cortex-M + * + * This module implements the routines necessary for thread context switching + * on ARM Cortex-M CPUs. + */ + +#include +#include +#include +#include +#include +#include + +#include +_ASM_FILE_PROLOGUE + +GTEXT(z_arm_svc) +GTEXT(z_arm_pendsv) +GTEXT(z_do_kernel_oops) +#if defined(CONFIG_USERSPACE) +GTEXT(z_arm_do_syscall) +#endif + +GDATA(_kernel) + +#if defined(CONFIG_THREAD_LOCAL_STORAGE) +GDATA(z_arm_tls_ptr) +#endif + +/** + * + * @brief PendSV exception handler, handling context switches + * + * The PendSV exception is the only execution context in the system that can + * perform context switching. When an execution context finds out it has to + * switch contexts, it pends the PendSV exception. + * + * When PendSV is pended, the decision that a context switch must happen has + * already been taken. In other words, when z_arm_pendsv() runs, we *know* we + * have to swap *something*. + * + * For Cortex-M, z_arm_pendsv() is invoked with no arguments. + */ + +SECTION_FUNC(TEXT, z_arm_pendsv) + +#ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING + /* Register the context switch */ + push {r0, lr} + bl z_thread_mark_switched_out +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + pop {r0, r1} + mov lr, r1 +#else + pop {r0, lr} +#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ +#endif /* CONFIG_INSTRUMENT_THREAD_SWITCHING */ + + /* load _kernel into r1 and current k_thread into r2 */ + ldr r1, =_kernel + ldr r2, [r1, #_kernel_offset_to_current] + +#if defined(CONFIG_ARM_STORE_EXC_RETURN) + /* Store LSB of LR (EXC_RETURN) to the thread's 'mode' word. */ + strb lr, [r2, #_thread_offset_to_mode_exc_return] +#endif + + /* addr of callee-saved regs in thread in r0 */ + ldr r0, =_thread_offset_to_callee_saved + add r0, r2 + + /* save callee-saved + psp in thread */ + mrs ip, PSP + +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + /* Store current r4-r7 */ + stmea r0!, {r4-r7} + /* copy r8-r12 into r3-r7 */ + mov r3, r8 + mov r4, r9 + mov r5, r10 + mov r6, r11 + mov r7, ip + /* store r8-12 */ + stmea r0!, {r3-r7} +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + stmia r0, {v1-v8, ip} +#ifdef CONFIG_FPU_SHARING + /* Assess whether switched-out thread had been using the FP registers. */ + tst lr, #_EXC_RETURN_FTYPE_Msk + bne out_fp_endif + + /* FP context active: set FP state and store callee-saved registers. + * Note: if Lazy FP stacking is enabled, storing the callee-saved + * registers will automatically trigger FP state preservation in + * the thread's stack. This will also clear the FPCCR.LSPACT flag. + */ + add r0, r2, #_thread_offset_to_preempt_float + vstmia r0, {s16-s31} + +out_fp_endif: + /* At this point FPCCR.LSPACT is guaranteed to be cleared, + * regardless of whether the thread has an active FP context. + */ +#endif /* CONFIG_FPU_SHARING */ +#else +#error Unknown ARM architecture +#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ + + /* Protect the kernel state while we play with the thread lists */ +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + cpsid i +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + movs.n r0, #_EXC_IRQ_DEFAULT_PRIO + msr BASEPRI_MAX, r0 + isb /* Make the effect of disabling interrupts be realized immediately */ +#else +#error Unknown ARM architecture +#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ + + /* + * Prepare to clear PendSV with interrupts unlocked, but + * don't clear it yet. PendSV must not be cleared until + * the new thread is context-switched in since all decisions + * to pend PendSV have been taken with the current kernel + * state and this is what we're handling currently. + */ + ldr v4, =_SCS_ICSR + ldr v3, =_SCS_ICSR_UNPENDSV + + /* _kernel is still in r1 */ + + /* fetch the thread to run from the ready queue cache */ + ldr r2, [r1, #_kernel_offset_to_ready_q_cache] + + str r2, [r1, #_kernel_offset_to_current] + + /* + * Clear PendSV so that if another interrupt comes in and + * decides, with the new kernel state based on the new thread + * being context-switched in, that it needs to reschedule, it + * will take, but that previously pended PendSVs do not take, + * since they were based on the previous kernel state and this + * has been handled. + */ + + /* _SCS_ICSR is still in v4 and _SCS_ICSR_UNPENDSV in v3 */ + str v3, [v4, #0] + +#if defined(CONFIG_THREAD_LOCAL_STORAGE) + /* Grab the TLS pointer */ + ldr r4, =_thread_offset_to_tls + adds r4, r2, r4 + ldr r0, [r4] + + /* For Cortex-M, store TLS pointer in a global variable, + * as it lacks the process ID or thread ID register + * to be used by toolchain to access thread data. + */ + ldr r4, =z_arm_tls_ptr + str r0, [r4] +#endif + +#if defined(CONFIG_ARM_STORE_EXC_RETURN) + /* Restore EXC_RETURN value. */ + ldrsb lr, [r2, #_thread_offset_to_mode_exc_return] +#endif + + /* Restore previous interrupt disable state (irq_lock key) + * (We clear the arch.basepri field after restoring state) + */ +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) && (_thread_offset_to_basepri > 124) + /* Doing it this way since the offset to thread->arch.basepri can in + * some configurations be larger than the maximum of 124 for ldr/str + * immediate offsets. + */ + ldr r4, =_thread_offset_to_basepri + adds r4, r2, r4 + + ldr r0, [r4] + movs.n r3, #0 + str r3, [r4] +#else + ldr r0, [r2, #_thread_offset_to_basepri] + movs r3, #0 + str r3, [r2, #_thread_offset_to_basepri] +#endif + +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + /* BASEPRI not available, previous interrupt disable state + * maps to PRIMASK. + * + * Only enable interrupts if value is 0, meaning interrupts + * were enabled before irq_lock was called. + */ + cmp r0, #0 + bne _thread_irq_disabled + cpsie i +_thread_irq_disabled: + +#if defined(CONFIG_MPU_STACK_GUARD) || defined(CONFIG_USERSPACE) + /* Re-program dynamic memory map */ + push {r2,lr} + mov r0, r2 + bl z_arm_configure_dynamic_mpu_regions + pop {r2,r3} + mov lr, r3 +#endif + +#ifdef CONFIG_USERSPACE + /* restore mode */ + ldr r3, =_thread_offset_to_mode + adds r3, r2, r3 + ldr r0, [r3] + mrs r3, CONTROL + movs.n r1, #1 + bics r3, r1 + orrs r3, r0 + msr CONTROL, r3 + + /* ISB is not strictly necessary here (stack pointer is not being + * touched), but it's recommended to avoid executing pre-fetched + * instructions with the previous privilege. + */ + isb + +#endif + + ldr r4, =_thread_offset_to_callee_saved + adds r0, r2, r4 + + /* restore r4-r12 for new thread */ + /* first restore r8-r12 located after r4-r7 (4*4bytes) */ + adds r0, #16 + ldmia r0!, {r3-r7} + /* move to correct registers */ + mov r8, r3 + mov r9, r4 + mov r10, r5 + mov r11, r6 + mov ip, r7 + /* restore r4-r7, go back 9*4 bytes to the start of the stored block */ + subs r0, #36 + ldmia r0!, {r4-r7} +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + /* restore BASEPRI for the incoming thread */ + msr BASEPRI, r0 + +#ifdef CONFIG_FPU_SHARING + /* Assess whether switched-in thread had been using the FP registers. */ + tst lr, #_EXC_RETURN_FTYPE_Msk + beq in_fp_active + /* FP context inactive for swapped-in thread: + * - reset FPSCR to 0 + * - set EXC_RETURN.F_Type (prevents FP frame un-stacking when returning + * from pendSV) + */ + movs.n r3, #0 + vmsr fpscr, r3 + b in_fp_endif + +in_fp_active: + /* FP context active: + * - clear EXC_RETURN.F_Type + * - FPSCR and caller-saved registers will be restored automatically + * - restore callee-saved FP registers + */ + add r0, r2, #_thread_offset_to_preempt_float + vldmia r0, {s16-s31} +in_fp_endif: + /* Clear CONTROL.FPCA that may have been set by FP instructions */ + mrs r3, CONTROL + bic r3, #_CONTROL_FPCA_Msk + msr CONTROL, r3 + isb +#endif + +#if defined(CONFIG_MPU_STACK_GUARD) || defined(CONFIG_USERSPACE) + /* Re-program dynamic memory map */ + push {r2,lr} + mov r0, r2 /* _current thread */ + bl z_arm_configure_dynamic_mpu_regions + pop {r2,lr} +#endif + +#ifdef CONFIG_USERSPACE + /* restore mode */ + ldr r0, [r2, #_thread_offset_to_mode] + mrs r3, CONTROL + bic r3, #1 + orr r3, r0 + msr CONTROL, r3 + + /* ISB is not strictly necessary here (stack pointer is not being + * touched), but it's recommended to avoid executing pre-fetched + * instructions with the previous privilege. + */ + isb + +#endif + + /* load callee-saved + psp from thread */ + add r0, r2, #_thread_offset_to_callee_saved + ldmia r0, {v1-v8, ip} +#else +#error Unknown ARM architecture +#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ + + msr PSP, ip + +#ifdef CONFIG_BUILTIN_STACK_GUARD + /* r2 contains k_thread */ + add r0, r2, #0 + push {r2, lr} + bl configure_builtin_stack_guard + pop {r2, lr} +#endif /* CONFIG_BUILTIN_STACK_GUARD */ + +#ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING + /* Register the context switch */ + push {r0, lr} + bl z_thread_mark_switched_in +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + pop {r0, r1} + mov lr, r1 +#else + pop {r0, lr} +#endif +#endif /* CONFIG_INSTRUMENT_THREAD_SWITCHING */ + + /* + * Cortex-M: return from PendSV exception + */ + bx lr + +/** + * + * @brief Service call handler + * + * The service call (svc) is used in the following occasions: + * - IRQ offloading + * - Kernel run-time exceptions + * - System Calls (User mode) + * + */ +SECTION_FUNC(TEXT, z_arm_svc) + /* Use EXC_RETURN state to find out if stack frame is on the + * MSP or PSP + */ +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + movs r0, #_EXC_RETURN_SPSEL_Msk + mov r1, lr + tst r1, r0 + beq _stack_frame_msp + mrs r0, PSP + bne _stack_frame_endif +_stack_frame_msp: + mrs r0, MSP +_stack_frame_endif: +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + tst lr, #_EXC_RETURN_SPSEL_Msk /* did we come from thread mode ? */ + ite eq /* if zero (equal), came from handler mode */ + mrseq r0, MSP /* handler mode, stack frame is on MSP */ + mrsne r0, PSP /* thread mode, stack frame is on PSP */ +#endif + + + /* Figure out what SVC call number was invoked */ + + ldr r1, [r0, #24] /* grab address of PC from stack frame */ + /* SVC is a two-byte instruction, point to it and read the + * SVC number (lower byte of SCV instruction) + */ +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + subs r1, r1, #2 + ldrb r1, [r1] +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + ldrb r1, [r1, #-2] +#endif + + /* + * grab service call number: + * 0: Unused + * 1: irq_offload (if configured) + * 2: kernel panic or oops (software generated fatal exception) + * 3: System call (if user mode supported) + */ +#if defined(CONFIG_USERSPACE) + mrs r2, CONTROL + + cmp r1, #3 + beq _do_syscall + + /* + * check that we are privileged before invoking other SVCs + * oops if we are unprivileged + */ +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + movs r3, #0x1 + tst r2, r3 +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + tst r2, #0x1 +#endif + bne _oops + +#endif /* CONFIG_USERSPACE */ + + cmp r1, #2 + beq _oops + +#if defined(CONFIG_IRQ_OFFLOAD) + push {r0, lr} + bl z_irq_do_offload /* call C routine which executes the offload */ +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + pop {r0, r3} + mov lr, r3 +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + pop {r0, lr} +#endif + + /* exception return is done in z_arm_int_exit() */ + b z_arm_int_exit +#endif + +_oops: + push {r0, lr} +#if defined(CONFIG_EXTRA_EXCEPTION_INFO) +#if defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + /* Build _callee_saved_t. To match the struct + * definition we push the psp & then r11-r4 + */ + mrs r1, PSP + push {r1, r2} + push {r4-r11} + mov r1, sp /* pointer to _callee_saved_t */ +#endif /* CONFIG_ARMV7_M_ARMV8_M_MAINLINE */ +#endif /* CONFIG_EXTRA_EXCEPTION_INFO */ + bl z_do_kernel_oops + /* return from SVC exception is done here */ +#if defined(CONFIG_EXTRA_EXCEPTION_INFO) +#if defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + /* We do not need to restore any register state here + * because we did not use any callee-saved registers + * in this routine. Therefore, we can just reset + * the MSP to its value prior to entering the function + */ + add sp, #40 +#endif /* CONFIG_ARMV7_M_ARMV8_M_MAINLINE */ +#endif /* CONFIG_EXTRA_EXCEPTION_INFO */ + pop {r0, pc} + +#if defined(CONFIG_USERSPACE) + /* + * System call will setup a jump to the z_arm_do_syscall() function + * when the SVC returns via the bx lr. + * + * There is some trickery involved here because we have to preserve + * the original PC value so that we can return back to the caller of + * the SVC. + * + * On SVC exeption, the stack looks like the following: + * r0 - r1 - r2 - r3 - r12 - LR - PC - PSR + * + * Registers look like: + * r0 - arg1 + * r1 - arg2 + * r2 - arg3 + * r3 - arg4 + * r4 - arg5 + * r5 - arg6 + * r6 - call_id + * r8 - saved link register + */ +_do_syscall: +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + movs r3, #24 + ldr r1, [r0, r3] /* grab address of PC from stack frame */ + mov r8, r1 +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + ldr r8, [r0, #24] /* grab address of PC from stack frame */ +#endif + ldr r1, =z_arm_do_syscall +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + str r1, [r0, r3] /* overwrite the PC to point to z_arm_do_syscall */ +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + str r1, [r0, #24] /* overwrite the PC to point to z_arm_do_syscall */ +#endif + +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + ldr r3, =K_SYSCALL_LIMIT + cmp r6, r3 +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + /* validate syscall limit */ + ldr ip, =K_SYSCALL_LIMIT + cmp r6, ip +#endif + /* The supplied syscall_id must be lower than the limit + * (Requires unsigned integer comparison) + */ + blo valid_syscall_id + + /* bad syscall id. Set arg1 to bad id and set call_id to SYSCALL_BAD */ + str r6, [r0] + ldr r6, =K_SYSCALL_BAD + + /* Bad syscalls treated as valid syscalls with ID K_SYSCALL_BAD. */ + +valid_syscall_id: + ldr r0, =_kernel + ldr r0, [r0, #_kernel_offset_to_current] +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + mov ip, r2 + ldr r1, =_thread_offset_to_mode + ldr r3, [r0, r1] + movs r2, #1 + bics r3, r2 + /* Store (privileged) mode in thread's mode state variable */ + str r3, [r0, r1] + mov r2, ip + dsb + /* set mode to privileged, r2 still contains value from CONTROL */ + movs r3, #1 + bics r2, r3 +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + ldr r1, [r0, #_thread_offset_to_mode] + bic r1, #1 + /* Store (privileged) mode in thread's mode state variable */ + str r1, [r0, #_thread_offset_to_mode] + dsb + /* set mode to privileged, r2 still contains value from CONTROL */ + bic r2, #1 +#endif + msr CONTROL, r2 + + /* ISB is not strictly necessary here (stack pointer is not being + * touched), but it's recommended to avoid executing pre-fetched + * instructions with the previous privilege. + */ + isb + +#if defined(CONFIG_BUILTIN_STACK_GUARD) + /* Thread is now in privileged mode; after returning from SCVall it + * will use the default (user) stack before switching to the privileged + * stack to execute the system call. We need to protect the user stack + * against stack overflows until this stack transition. + */ + ldr r1, [r0, #_thread_offset_to_stack_info_start] /* stack_info.start */ + msr PSPLIM, r1 +#endif /* CONFIG_BUILTIN_STACK_GUARD */ + + /* return from SVC to the modified LR - z_arm_do_syscall */ + bx lr +#endif /* CONFIG_USERSPACE */ diff --git a/arch/arm/core/cortex_m/thread.c b/arch/arm/core/cortex_m/thread.c new file mode 100644 index 00000000000..0ada94e8b27 --- /dev/null +++ b/arch/arm/core/cortex_m/thread.c @@ -0,0 +1,649 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * Copyright (c) 2021 Lexmark International, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief New thread creation for ARM Cortex-M + * + * Core thread related primitives for the ARM Cortex-M + * processor architecture. + */ + +#include +#include +#include +#include +#include + +#if (MPU_GUARD_ALIGN_AND_SIZE_FLOAT > MPU_GUARD_ALIGN_AND_SIZE) +#define FP_GUARD_EXTRA_SIZE (MPU_GUARD_ALIGN_AND_SIZE_FLOAT - \ + MPU_GUARD_ALIGN_AND_SIZE) +#else +#define FP_GUARD_EXTRA_SIZE 0 +#endif + +#ifndef EXC_RETURN_FTYPE +/* bit [4] allocate stack for floating-point context: 0=done 1=skipped */ +#define EXC_RETURN_FTYPE (0x00000010UL) +#endif + +/* Default last octet of EXC_RETURN, for threads that have not run yet. + * The full EXC_RETURN value will be e.g. 0xFFFFFFBC. + */ +#if defined(CONFIG_ARM_NONSECURE_FIRMWARE) +#define DEFAULT_EXC_RETURN 0xBC; +#else +#define DEFAULT_EXC_RETURN 0xFD; +#endif + +#if !defined(CONFIG_MULTITHREADING) +K_THREAD_STACK_DECLARE(z_main_stack, CONFIG_MAIN_STACK_SIZE); +#endif + +/* An initial context, to be "restored" by z_arm_pendsv(), is put at the other + * end of the stack, and thus reusable by the stack when not needed anymore. + * + * The initial context is an exception stack frame (ESF) since exiting the + * PendSV exception will want to pop an ESF. Interestingly, even if the lsb of + * an instruction address to jump to must always be set since the CPU always + * runs in thumb mode, the ESF expects the real address of the instruction, + * with the lsb *not* set (instructions are always aligned on 16 bit + * halfwords). Since the compiler automatically sets the lsb of function + * addresses, we have to unset it manually before storing it in the 'pc' field + * of the ESF. + */ +void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, + char *stack_ptr, k_thread_entry_t entry, + void *p1, void *p2, void *p3) +{ + struct __basic_sf *iframe; + +#ifdef CONFIG_MPU_STACK_GUARD +#if defined(CONFIG_USERSPACE) + if (z_stack_is_user_capable(stack)) { + /* Guard area is carved-out of the buffer instead of reserved + * for stacks that can host user threads + */ + thread->stack_info.start += MPU_GUARD_ALIGN_AND_SIZE; + thread->stack_info.size -= MPU_GUARD_ALIGN_AND_SIZE; + } +#endif /* CONFIG_USERSPACE */ +#if FP_GUARD_EXTRA_SIZE > 0 + if ((thread->base.user_options & K_FP_REGS) != 0) { + /* Larger guard needed due to lazy stacking of FP regs may + * overshoot the guard area without writing anything. We + * carve it out of the stack buffer as-needed instead of + * unconditionally reserving it. + */ + thread->stack_info.start += FP_GUARD_EXTRA_SIZE; + thread->stack_info.size -= FP_GUARD_EXTRA_SIZE; + } +#endif /* FP_GUARD_EXTRA_SIZE */ +#endif /* CONFIG_MPU_STACK_GUARD */ + + iframe = Z_STACK_PTR_TO_FRAME(struct __basic_sf, stack_ptr); +#if defined(CONFIG_USERSPACE) + if ((thread->base.user_options & K_USER) != 0) { + iframe->pc = (uint32_t)arch_user_mode_enter; + } else { + iframe->pc = (uint32_t)z_thread_entry; + } +#else + iframe->pc = (uint32_t)z_thread_entry; +#endif + + /* force ARM mode by clearing LSB of address */ + iframe->pc &= 0xfffffffe; + iframe->a1 = (uint32_t)entry; + iframe->a2 = (uint32_t)p1; + iframe->a3 = (uint32_t)p2; + iframe->a4 = (uint32_t)p3; + + iframe->xpsr = + 0x01000000UL; /* clear all, thumb bit is 1, even if RO */ + + thread->callee_saved.psp = (uint32_t)iframe; + thread->arch.basepri = 0; + +#if defined(CONFIG_ARM_STORE_EXC_RETURN) || defined(CONFIG_USERSPACE) + thread->arch.mode = 0; +#if defined(CONFIG_ARM_STORE_EXC_RETURN) + thread->arch.mode_exc_return = DEFAULT_EXC_RETURN; +#endif +#if FP_GUARD_EXTRA_SIZE > 0 + if ((thread->base.user_options & K_FP_REGS) != 0) { + thread->arch.mode |= Z_ARM_MODE_MPU_GUARD_FLOAT_Msk; + } +#endif +#if defined(CONFIG_USERSPACE) + thread->arch.priv_stack_start = 0; +#endif +#endif + /* + * initial values in all other registers/thread entries are + * irrelevant. + */ +} + +#if defined(CONFIG_MPU_STACK_GUARD) && defined(CONFIG_FPU) \ + && defined(CONFIG_FPU_SHARING) + +static inline void z_arm_thread_stack_info_adjust(struct k_thread *thread, + bool use_large_guard) +{ + if (use_large_guard) { + /* Switch to use a large MPU guard if not already. */ + if ((thread->arch.mode & + Z_ARM_MODE_MPU_GUARD_FLOAT_Msk) == 0) { + /* Default guard size is used. Update required. */ + thread->arch.mode |= Z_ARM_MODE_MPU_GUARD_FLOAT_Msk; +#if defined(CONFIG_USERSPACE) + if (thread->arch.priv_stack_start) { + /* User thread */ + thread->arch.priv_stack_start += + FP_GUARD_EXTRA_SIZE; + } else +#endif /* CONFIG_USERSPACE */ + { + /* Privileged thread */ + thread->stack_info.start += + FP_GUARD_EXTRA_SIZE; + thread->stack_info.size -= + FP_GUARD_EXTRA_SIZE; + } + } + } else { + /* Switch to use the default MPU guard size if not already. */ + if ((thread->arch.mode & + Z_ARM_MODE_MPU_GUARD_FLOAT_Msk) != 0) { + /* Large guard size is used. Update required. */ + thread->arch.mode &= ~Z_ARM_MODE_MPU_GUARD_FLOAT_Msk; +#if defined(CONFIG_USERSPACE) + if (thread->arch.priv_stack_start) { + /* User thread */ + thread->arch.priv_stack_start -= + FP_GUARD_EXTRA_SIZE; + } else +#endif /* CONFIG_USERSPACE */ + { + /* Privileged thread */ + thread->stack_info.start -= + FP_GUARD_EXTRA_SIZE; + thread->stack_info.size += + FP_GUARD_EXTRA_SIZE; + } + } + } +} + +/* + * Adjust the MPU stack guard size together with the FPU + * policy and the stack_info values for the thread that is + * being switched in. + */ +uint32_t z_arm_mpu_stack_guard_and_fpu_adjust(struct k_thread *thread) +{ + if (((thread->base.user_options & K_FP_REGS) != 0) || + ((thread->arch.mode_exc_return & EXC_RETURN_FTYPE) == 0)) { + /* The thread has been pre-tagged (at creation or later) with + * K_FP_REGS, i.e. it is expected to be using the FPU registers + * (if not already). Activate lazy stacking and program a large + * MPU guard to safely detect privilege thread stack overflows. + * + * OR + * The thread is not pre-tagged with K_FP_REGS, but it has + * generated an FP context. Activate lazy stacking and + * program a large MPU guard to detect privilege thread + * stack overflows. + */ + FPU->FPCCR |= FPU_FPCCR_LSPEN_Msk; + + z_arm_thread_stack_info_adjust(thread, true); + + /* Tag the thread with K_FP_REGS */ + thread->base.user_options |= K_FP_REGS; + + return MPU_GUARD_ALIGN_AND_SIZE_FLOAT; + } + + /* Thread is not pre-tagged with K_FP_REGS, and it has + * not been using the FPU. Since there is no active FPU + * context, de-activate lazy stacking and program the + * default MPU guard size. + */ + FPU->FPCCR &= (~FPU_FPCCR_LSPEN_Msk); + + z_arm_thread_stack_info_adjust(thread, false); + + return MPU_GUARD_ALIGN_AND_SIZE; +} +#endif + +#ifdef CONFIG_USERSPACE +FUNC_NORETURN void arch_user_mode_enter(k_thread_entry_t user_entry, + void *p1, void *p2, void *p3) +{ + + /* Set up privileged stack before entering user mode */ + _current->arch.priv_stack_start = + (uint32_t)z_priv_stack_find(_current->stack_obj); +#if defined(CONFIG_MPU_STACK_GUARD) +#if defined(CONFIG_THREAD_STACK_INFO) + /* We're dropping to user mode which means the guard area is no + * longer used here, it instead is moved to the privilege stack + * to catch stack overflows there. Un-do the calculations done + * which accounted for memory borrowed from the thread stack. + */ +#if FP_GUARD_EXTRA_SIZE > 0 + if ((_current->arch.mode & Z_ARM_MODE_MPU_GUARD_FLOAT_Msk) != 0) { + _current->stack_info.start -= FP_GUARD_EXTRA_SIZE; + _current->stack_info.size += FP_GUARD_EXTRA_SIZE; + } +#endif /* FP_GUARD_EXTRA_SIZE */ + _current->stack_info.start -= MPU_GUARD_ALIGN_AND_SIZE; + _current->stack_info.size += MPU_GUARD_ALIGN_AND_SIZE; +#endif /* CONFIG_THREAD_STACK_INFO */ + + /* Stack guard area reserved at the bottom of the thread's + * privileged stack. Adjust the available (writable) stack + * buffer area accordingly. + */ +#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) + _current->arch.priv_stack_start += + ((_current->arch.mode & Z_ARM_MODE_MPU_GUARD_FLOAT_Msk) != 0) ? + MPU_GUARD_ALIGN_AND_SIZE_FLOAT : MPU_GUARD_ALIGN_AND_SIZE; +#else + _current->arch.priv_stack_start += MPU_GUARD_ALIGN_AND_SIZE; +#endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ +#endif /* CONFIG_MPU_STACK_GUARD */ + + z_arm_userspace_enter(user_entry, p1, p2, p3, + (uint32_t)_current->stack_info.start, + _current->stack_info.size - + _current->stack_info.delta); + CODE_UNREACHABLE; +} + + +bool z_arm_thread_is_in_user_mode(void) +{ + uint32_t value; + + /* return mode information */ + value = __get_CONTROL(); + return (value & CONTROL_nPRIV_Msk) != 0; +} +#endif + +#if defined(CONFIG_BUILTIN_STACK_GUARD) +/* + * @brief Configure ARM built-in stack guard + * + * This function configures per thread stack guards by reprogramming + * the built-in Process Stack Pointer Limit Register (PSPLIM). + * The functionality is meant to be used during context switch. + * + * @param thread thread info data structure. + */ +void configure_builtin_stack_guard(struct k_thread *thread) +{ +#if defined(CONFIG_USERSPACE) + if ((thread->arch.mode & CONTROL_nPRIV_Msk) != 0) { + /* Only configure stack limit for threads in privileged mode + * (i.e supervisor threads or user threads doing system call). + * User threads executing in user mode do not require a stack + * limit protection. + */ + __set_PSPLIM(0); + return; + } + /* Only configure PSPLIM to guard the privileged stack area, if + * the thread is currently using it, otherwise guard the default + * thread stack. Note that the conditional check relies on the + * thread privileged stack being allocated in higher memory area + * than the default thread stack (ensured by design). + */ + uint32_t guard_start = + ((thread->arch.priv_stack_start) && + (__get_PSP() >= thread->arch.priv_stack_start)) ? + (uint32_t)thread->arch.priv_stack_start : + (uint32_t)thread->stack_obj; + + __ASSERT(thread->stack_info.start == ((uint32_t)thread->stack_obj), + "stack_info.start does not point to the start of the" + "thread allocated area."); +#else + uint32_t guard_start = thread->stack_info.start; +#endif +#if defined(CONFIG_CPU_CORTEX_M_HAS_SPLIM) + __set_PSPLIM(guard_start); +#else +#error "Built-in PSP limit checks not supported by HW" +#endif +} +#endif /* CONFIG_BUILTIN_STACK_GUARD */ + +#if defined(CONFIG_MPU_STACK_GUARD) || defined(CONFIG_USERSPACE) + +#define IS_MPU_GUARD_VIOLATION(guard_start, guard_len, fault_addr, stack_ptr) \ + ((fault_addr != -EINVAL) ? \ + ((fault_addr >= guard_start) && \ + (fault_addr < (guard_start + guard_len)) && \ + (stack_ptr < (guard_start + guard_len))) \ + : \ + (stack_ptr < (guard_start + guard_len))) + +/** + * @brief Assess occurrence of current thread's stack corruption + * + * This function performs an assessment whether a memory fault (on a + * given memory address) is the result of stack memory corruption of + * the current thread. + * + * Thread stack corruption for supervisor threads or user threads in + * privilege mode (when User Space is supported) is reported upon an + * attempt to access the stack guard area (if MPU Stack Guard feature + * is supported). Additionally the current PSP (process stack pointer) + * must be pointing inside or below the guard area. + * + * Thread stack corruption for user threads in user mode is reported, + * if the current PSP is pointing below the start of the current + * thread's stack. + * + * Notes: + * - we assume a fully descending stack, + * - we assume a stacking error has occurred, + * - the function shall be called when handling MemManage and Bus fault, + * and only if a Stacking error has been reported. + * + * If stack corruption is detected, the function returns the lowest + * allowed address where the Stack Pointer can safely point to, to + * prevent from errors when un-stacking the corrupted stack frame + * upon exception return. + * + * @param fault_addr memory address on which memory access violation + * has been reported. It can be invalid (-EINVAL), + * if only Stacking error has been reported. + * @param psp current address the PSP points to + * + * @return The lowest allowed stack frame pointer, if error is a + * thread stack corruption, otherwise return 0. + */ +uint32_t z_check_thread_stack_fail(const uint32_t fault_addr, const uint32_t psp) +{ +#if defined(CONFIG_MULTITHREADING) + const struct k_thread *thread = _current; + + if (thread == NULL) { + return 0; + } +#endif + +#if (defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)) && \ + defined(CONFIG_MPU_STACK_GUARD) + uint32_t guard_len = + ((_current->arch.mode & Z_ARM_MODE_MPU_GUARD_FLOAT_Msk) != 0) ? + MPU_GUARD_ALIGN_AND_SIZE_FLOAT : MPU_GUARD_ALIGN_AND_SIZE; +#else + /* If MPU_STACK_GUARD is not enabled, the guard length is + * effectively zero. Stack overflows may be detected only + * for user threads in nPRIV mode. + */ + uint32_t guard_len = MPU_GUARD_ALIGN_AND_SIZE; +#endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ + +#if defined(CONFIG_USERSPACE) + if (thread->arch.priv_stack_start) { + /* User thread */ + if (z_arm_thread_is_in_user_mode() == false) { + /* User thread in privilege mode */ + if (IS_MPU_GUARD_VIOLATION( + thread->arch.priv_stack_start - guard_len, + guard_len, + fault_addr, psp)) { + /* Thread's privilege stack corruption */ + return thread->arch.priv_stack_start; + } + } else { + if (psp < (uint32_t)thread->stack_obj) { + /* Thread's user stack corruption */ + return (uint32_t)thread->stack_obj; + } + } + } else { + /* Supervisor thread */ + if (IS_MPU_GUARD_VIOLATION(thread->stack_info.start - + guard_len, + guard_len, + fault_addr, psp)) { + /* Supervisor thread stack corruption */ + return thread->stack_info.start; + } + } +#else /* CONFIG_USERSPACE */ +#if defined(CONFIG_MULTITHREADING) + if (IS_MPU_GUARD_VIOLATION(thread->stack_info.start - guard_len, + guard_len, + fault_addr, psp)) { + /* Thread stack corruption */ + return thread->stack_info.start; + } +#else + if (IS_MPU_GUARD_VIOLATION((uint32_t)z_main_stack, + guard_len, + fault_addr, psp)) { + /* Thread stack corruption */ + return (uint32_t)Z_THREAD_STACK_BUFFER(z_main_stack); + } +#endif +#endif /* CONFIG_USERSPACE */ + + return 0; +} +#endif /* CONFIG_MPU_STACK_GUARD || CONFIG_USERSPACE */ + +#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) +int arch_float_disable(struct k_thread *thread) +{ + if (thread != _current) { + return -EINVAL; + } + + if (arch_is_in_isr()) { + return -EINVAL; + } + + /* Disable all floating point capabilities for the thread */ + + /* K_FP_REG flag is used in SWAP and stack check fail. Locking + * interrupts here prevents a possible context-switch or MPU + * fault to take an outdated thread user_options flag into + * account. + */ + int key = arch_irq_lock(); + + thread->base.user_options &= ~K_FP_REGS; + + __set_CONTROL(__get_CONTROL() & (~CONTROL_FPCA_Msk)); + + /* No need to add an ISB barrier after setting the CONTROL + * register; arch_irq_unlock() already adds one. + */ + + arch_irq_unlock(key); + + return 0; +} + +int arch_float_enable(struct k_thread *thread, unsigned int options) +{ + /* This is not supported in Cortex-M */ + return -ENOTSUP; +} +#endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ + +/* Internal function for Cortex-M initialization, + * applicable to either case of running Zephyr + * with or without multi-threading support. + */ +static void z_arm_prepare_switch_to_main(void) +{ +#if defined(CONFIG_FPU) + /* Initialize the Floating Point Status and Control Register when in + * Unshared FP Registers mode (In Shared FP Registers mode, FPSCR is + * initialized at thread creation for threads that make use of the FP). + */ +#if defined(CONFIG_ARMV8_1_M_MAINLINE) + /* + * For ARMv8.1-M with FPU, the FPSCR[18:16] LTPSIZE field must be set + * to 0b100 for "Tail predication not applied" as it's reset value + */ + __set_FPSCR(4 << FPU_FPDSCR_LTPSIZE_Pos); +#else + __set_FPSCR(0); +#endif +#if defined(CONFIG_FPU_SHARING) + /* In Sharing mode clearing FPSCR may set the CONTROL.FPCA flag. */ + __set_CONTROL(__get_CONTROL() & (~(CONTROL_FPCA_Msk))); + barrier_isync_fence_full(); +#endif /* CONFIG_FPU_SHARING */ +#endif /* CONFIG_FPU */ +} + +void arch_switch_to_main_thread(struct k_thread *main_thread, char *stack_ptr, + k_thread_entry_t _main) +{ + z_arm_prepare_switch_to_main(); + + _current = main_thread; + +#if defined(CONFIG_THREAD_LOCAL_STORAGE) + /* On Cortex-M, TLS uses a global variable as pointer to + * the thread local storage area. So this needs to point + * to the main thread's TLS area before switching to any + * thread for the first time, as the pointer is only set + * during context switching. + */ + extern uintptr_t z_arm_tls_ptr; + + z_arm_tls_ptr = main_thread->tls; +#endif + +#ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING + z_thread_mark_switched_in(); +#endif + + /* the ready queue cache already contains the main thread */ + +#if defined(CONFIG_MPU_STACK_GUARD) || defined(CONFIG_USERSPACE) + /* + * If stack protection is enabled, make sure to set it + * before jumping to thread entry function + */ + z_arm_configure_dynamic_mpu_regions(main_thread); +#endif + +#if defined(CONFIG_BUILTIN_STACK_GUARD) + /* Set PSPLIM register for built-in stack guarding of main thread. */ +#if defined(CONFIG_CPU_CORTEX_M_HAS_SPLIM) + __set_PSPLIM(main_thread->stack_info.start); +#else +#error "Built-in PSP limit checks not supported by HW" +#endif +#endif /* CONFIG_BUILTIN_STACK_GUARD */ + + /* + * Set PSP to the highest address of the main stack + * before enabling interrupts and jumping to main. + */ + __asm__ volatile ( + "mov r0, %0\n\t" /* Store _main in R0 */ + "msr PSP, %1\n\t" /* __set_PSP(stack_ptr) */ + + "movs r1, #0\n\t" +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + "cpsie i\n\t" /* __enable_irq() */ +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + "cpsie if\n\t" /* __enable_irq(); __enable_fault_irq() */ + "msr BASEPRI, r1\n\t" /* __set_BASEPRI(0) */ +#else +#error Unknown ARM architecture +#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ + "isb\n\t" + "movs r2, #0\n\t" + "movs r3, #0\n\t" + "bl z_thread_entry\n\t" /* z_thread_entry(_main, 0, 0, 0); */ + : + : "r" (_main), "r" (stack_ptr) + : "r0" /* not to be overwritten by msr PSP, %1 */ + ); + + CODE_UNREACHABLE; +} + +#if !defined(CONFIG_MULTITHREADING) + +FUNC_NORETURN void z_arm_switch_to_main_no_multithreading( + k_thread_entry_t main_entry, void *p1, void *p2, void *p3) +{ + z_arm_prepare_switch_to_main(); + + /* Set PSP to the highest address of the main stack. */ + char *psp = Z_THREAD_STACK_BUFFER(z_main_stack) + + K_THREAD_STACK_SIZEOF(z_main_stack); + +#if defined(CONFIG_BUILTIN_STACK_GUARD) + char *psplim = (Z_THREAD_STACK_BUFFER(z_main_stack)); + /* Clear PSPLIM before setting it to guard the main stack area. */ + __set_PSPLIM(0); +#endif + + /* Store all required input in registers, to be accessible + * after stack pointer change. The function is not going + * to return, so callee-saved registers do not need to be + * stacked. + */ + register void *p1_inreg __asm__("r0") = p1; + register void *p2_inreg __asm__("r1") = p2; + register void *p3_inreg __asm__("r2") = p3; + + __asm__ volatile ( +#ifdef CONFIG_BUILTIN_STACK_GUARD + "msr PSPLIM, %[_psplim]\n\t" +#endif + "msr PSP, %[_psp]\n\t" /* __set_PSP(psp) */ +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + "cpsie i\n\t" /* enable_irq() */ +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + "cpsie if\n\t" /* __enable_irq(); __enable_fault_irq() */ + "mov r3, #0\n\t" + "msr BASEPRI, r3\n\t" /* __set_BASEPRI(0) */ +#endif + "isb\n\t" + "blx %[_main_entry]\n\t" /* main_entry(p1, p2, p3) */ +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + "cpsid i\n\t" /* disable_irq() */ +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + "msr BASEPRI, %[basepri]\n\t"/* __set_BASEPRI(_EXC_IRQ_DEFAULT_PRIO) */ + "isb\n\t" +#endif + "loop: b loop\n\t" /* while (true); */ + : + : "r" (p1_inreg), "r" (p2_inreg), "r" (p3_inreg), + [_psp]"r" (psp), [_main_entry]"r" (main_entry) +#if defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + , [basepri] "r" (_EXC_IRQ_DEFAULT_PRIO) +#endif +#ifdef CONFIG_BUILTIN_STACK_GUARD + , [_psplim]"r" (psplim) +#endif + : + ); + + CODE_UNREACHABLE; /* LCOV_EXCL_LINE */ +} +#endif /* !CONFIG_MULTITHREADING */ diff --git a/arch/arm/core/aarch32/cortex_m/thread_abort.c b/arch/arm/core/cortex_m/thread_abort.c similarity index 98% rename from arch/arm/core/aarch32/cortex_m/thread_abort.c rename to arch/arm/core/cortex_m/thread_abort.c index b28a9bcf6fa..1ea84200cb8 100644 --- a/arch/arm/core/aarch32/cortex_m/thread_abort.c +++ b/arch/arm/core/cortex_m/thread_abort.c @@ -21,7 +21,6 @@ #include #include #include -#include #include void z_impl_k_thread_abort(k_tid_t thread) diff --git a/arch/arm/core/aarch32/cortex_m/timing.c b/arch/arm/core/cortex_m/timing.c similarity index 98% rename from arch/arm/core/aarch32/cortex_m/timing.c rename to arch/arm/core/cortex_m/timing.c index 2e2912487f8..861f1a9995a 100644 --- a/arch/arm/core/aarch32/cortex_m/timing.c +++ b/arch/arm/core/cortex_m/timing.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/arm/core/aarch32/cortex_m/tz/CMakeLists.txt b/arch/arm/core/cortex_m/tz/CMakeLists.txt similarity index 100% rename from arch/arm/core/aarch32/cortex_m/tz/CMakeLists.txt rename to arch/arm/core/cortex_m/tz/CMakeLists.txt diff --git a/arch/arm/core/aarch32/cortex_m/tz/Kconfig b/arch/arm/core/cortex_m/tz/Kconfig similarity index 100% rename from arch/arm/core/aarch32/cortex_m/tz/Kconfig rename to arch/arm/core/cortex_m/tz/Kconfig diff --git a/arch/arm/core/aarch32/cortex_m/tz/arm_core_tz.c b/arch/arm/core/cortex_m/tz/arm_core_tz.c similarity index 98% rename from arch/arm/core/aarch32/cortex_m/tz/arm_core_tz.c rename to arch/arm/core/cortex_m/tz/arm_core_tz.c index 1a316be7265..8371a08bfef 100644 --- a/arch/arm/core/aarch32/cortex_m/tz/arm_core_tz.c +++ b/arch/arm/core/cortex_m/tz/arm_core_tz.c @@ -5,8 +5,8 @@ */ #include -#include -#include +#include +#include static void configure_nonsecure_vtor_offset(uint32_t vtor_ns) { diff --git a/arch/arm/core/aarch32/cortex_m/tz/secure_entry_functions.ld b/arch/arm/core/cortex_m/tz/secure_entry_functions.ld similarity index 100% rename from arch/arm/core/aarch32/cortex_m/tz/secure_entry_functions.ld rename to arch/arm/core/cortex_m/tz/secure_entry_functions.ld diff --git a/arch/arm/core/aarch32/cortex_m/vector_table.S b/arch/arm/core/cortex_m/vector_table.S similarity index 100% rename from arch/arm/core/aarch32/cortex_m/vector_table.S rename to arch/arm/core/cortex_m/vector_table.S diff --git a/arch/arm/core/aarch32/cortex_m/vector_table.h b/arch/arm/core/cortex_m/vector_table.h similarity index 100% rename from arch/arm/core/aarch32/cortex_m/vector_table.h rename to arch/arm/core/cortex_m/vector_table.h diff --git a/arch/arm/core/aarch32/cortex_m/vector_table_pad.ld b/arch/arm/core/cortex_m/vector_table_pad.ld similarity index 100% rename from arch/arm/core/aarch32/cortex_m/vector_table_pad.ld rename to arch/arm/core/cortex_m/vector_table_pad.ld diff --git a/arch/arm/core/aarch32/cortex_m/vt_pointer_section.ld b/arch/arm/core/cortex_m/vt_pointer_section.ld similarity index 100% rename from arch/arm/core/aarch32/cortex_m/vt_pointer_section.ld rename to arch/arm/core/cortex_m/vt_pointer_section.ld diff --git a/arch/arm/core/elf.c b/arch/arm/core/elf.c new file mode 100644 index 00000000000..e16af6199e6 --- /dev/null +++ b/arch/arm/core/elf.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +LOG_MODULE_REGISTER(elf, CONFIG_LLEXT_LOG_LEVEL); + +/** + * @brief Architecture specific function for relocating partially linked (static) elf + * + * Elf files contain a series of relocations described in a section. These relocation + * instructions are architecture specific and each architecture supporting extensions + * must implement this. + * + * The relocation codes for arm are well documented + * https://github.com/ARM-software/abi-aa/blob/main/aaelf32/aaelf32.rst#relocation + */ +void arch_elf_relocate(elf_rela_t *rel, uintptr_t opaddr, uintptr_t opval) +{ + elf_word reloc_type = ELF32_R_TYPE(rel->r_info); + + switch (reloc_type) { + case R_ARM_ABS32: + /* Update the absolute address of a load/store instruction */ + *((uint32_t *)opaddr) = (uint32_t)opval; + break; + default: + LOG_DBG("Unsupported ARM elf relocation type %d at address %lx", + reloc_type, opaddr); + break; + } +} diff --git a/arch/arm/core/aarch32/fatal.c b/arch/arm/core/fatal.c similarity index 100% rename from arch/arm/core/aarch32/fatal.c rename to arch/arm/core/fatal.c diff --git a/arch/arm/core/aarch32/header.S b/arch/arm/core/header.S similarity index 100% rename from arch/arm/core/aarch32/header.S rename to arch/arm/core/header.S diff --git a/arch/arm/core/aarch32/irq_offload.c b/arch/arm/core/irq_offload.c similarity index 100% rename from arch/arm/core/aarch32/irq_offload.c rename to arch/arm/core/irq_offload.c diff --git a/arch/arm/core/aarch32/mmu/CMakeLists.txt b/arch/arm/core/mmu/CMakeLists.txt similarity index 100% rename from arch/arm/core/aarch32/mmu/CMakeLists.txt rename to arch/arm/core/mmu/CMakeLists.txt diff --git a/arch/arm/core/aarch32/mmu/Kconfig b/arch/arm/core/mmu/Kconfig similarity index 100% rename from arch/arm/core/aarch32/mmu/Kconfig rename to arch/arm/core/mmu/Kconfig diff --git a/arch/arm/core/aarch32/mmu/arm_mmu.c b/arch/arm/core/mmu/arm_mmu.c similarity index 99% rename from arch/arm/core/aarch32/mmu/arm_mmu.c rename to arch/arm/core/mmu/arm_mmu.c index 3658b2df639..77c79fdfc3d 100644 --- a/arch/arm/core/aarch32/mmu/arm_mmu.c +++ b/arch/arm/core/mmu/arm_mmu.c @@ -26,12 +26,12 @@ #include #include #include -#include +#include #include #include -#include +#include #include "arm_mmu_priv.h" LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); @@ -861,7 +861,7 @@ int z_arm_mmu_init(void) * @param phys 32-bit physical address. * @param size Size (in bytes) of the memory area to map. * @param flags Memory attributes & permissions. Comp. K_MEM_... - * flags in sys/mem_manage.h. + * flags in kernel/mm.h. * @retval 0 on success, -EINVAL if an invalid parameter is detected. */ static int __arch_mem_map(void *virt, uintptr_t phys, size_t size, uint32_t flags) @@ -939,7 +939,7 @@ static int __arch_mem_map(void *virt, uintptr_t phys, size_t size, uint32_t flag * @param phys 32-bit physical address. * @param size Size (in bytes) of the memory area to map. * @param flags Memory attributes & permissions. Comp. K_MEM_... - * flags in sys/mem_manage.h. + * flags in kernel/mm.h. */ void arch_mem_map(void *virt, uintptr_t phys, size_t size, uint32_t flags) { diff --git a/arch/arm/core/aarch32/mmu/arm_mmu_priv.h b/arch/arm/core/mmu/arm_mmu_priv.h similarity index 100% rename from arch/arm/core/aarch32/mmu/arm_mmu_priv.h rename to arch/arm/core/mmu/arm_mmu_priv.h diff --git a/arch/arm/core/mpu/CMakeLists.txt b/arch/arm/core/mpu/CMakeLists.txt new file mode 100644 index 00000000000..1df6561ee52 --- /dev/null +++ b/arch/arm/core/mpu/CMakeLists.txt @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources( arm_core_mpu.c) +zephyr_library_sources_ifdef(CONFIG_CPU_HAS_ARM_MPU arm_mpu.c) +zephyr_library_sources_ifdef(CONFIG_CPU_HAS_NXP_MPU nxp_mpu.c) + +if(CONFIG_CPU_CORTEX_M AND NOT CONFIG_CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS) + zephyr_library_sources_ifdef(CONFIG_CPU_HAS_ARM_MPU arm_mpu_regions.c) + zephyr_library_sources_ifdef(CONFIG_CPU_HAS_NXP_MPU nxp_mpu_regions.c) +endif() + +if (CONFIG_CPU_AARCH32_CORTEX_R) +zephyr_library_include_directories(cortex_a_r) +elseif (CONFIG_CPU_CORTEX_M) +zephyr_library_include_directories(cortex_m) +else () +message(FATAL_ERROR "CPU is not Cortex-A/R/M") +endif () diff --git a/arch/arm/core/aarch32/mpu/Kconfig b/arch/arm/core/mpu/Kconfig similarity index 100% rename from arch/arm/core/aarch32/mpu/Kconfig rename to arch/arm/core/mpu/Kconfig diff --git a/arch/arm/core/aarch32/mpu/arm_core_mpu.c b/arch/arm/core/mpu/arm_core_mpu.c similarity index 100% rename from arch/arm/core/aarch32/mpu/arm_core_mpu.c rename to arch/arm/core/mpu/arm_core_mpu.c diff --git a/arch/arm/core/aarch32/mpu/arm_core_mpu_dev.h b/arch/arm/core/mpu/arm_core_mpu_dev.h similarity index 100% rename from arch/arm/core/aarch32/mpu/arm_core_mpu_dev.h rename to arch/arm/core/mpu/arm_core_mpu_dev.h diff --git a/arch/arm/core/aarch32/mpu/arm_mpu.c b/arch/arm/core/mpu/arm_mpu.c similarity index 82% rename from arch/arm/core/aarch32/mpu/arm_mpu.c rename to arch/arm/core/mpu/arm_mpu.c index ac28ab6b609..9b2feffe5ee 100644 --- a/arch/arm/core/aarch32/mpu/arm_mpu.c +++ b/arch/arm/core/mpu/arm_mpu.c @@ -11,6 +11,8 @@ #include "arm_core_mpu_dev.h" #include #include +#include +#include #define LOG_LEVEL CONFIG_MPU_LOG_LEVEL #include @@ -32,6 +34,13 @@ LOG_MODULE_DECLARE(mpu); #define NUM_MPU_REGIONS DT_PROP(MPU_NODEID, arm_num_mpu_regions) #endif +#define NODE_HAS_PROP_AND_OR(node_id, prop) \ + DT_NODE_HAS_PROP(node_id, prop) || + +BUILD_ASSERT((DT_FOREACH_STATUS_OKAY_NODE_VARGS( + NODE_HAS_PROP_AND_OR, zephyr_memory_region_mpu) false) == false, + "`zephyr,memory-region-mpu` was deprecated in favor of `zephyr,memory-attr`"); + /* * Global status variable holding the number of HW MPU region indices, which * have been reserved by the MPU driver to program the static (fixed) memory @@ -74,6 +83,79 @@ static int region_allocate_and_init(const uint8_t index, return index; } +#define _BUILD_REGION_CONF(reg, _ATTR) \ + (struct arm_mpu_region) ARM_MPU_REGION_INIT((reg).dt_name, \ + (reg).dt_addr, \ + (reg).dt_size, \ + _ATTR) + +/* This internal function programs the MPU regions defined in the DT when using + * the `zephyr,memory-attr = <( DT_MEM_ARM(...) )>` property. + */ +static int mpu_configure_regions_from_dt(uint8_t *reg_index) +{ + const struct mem_attr_region_t *region; + size_t num_regions; + + num_regions = mem_attr_get_regions(®ion); + + for (size_t idx = 0; idx < num_regions; idx++) { + struct arm_mpu_region region_conf; + + switch (DT_MEM_ARM_GET(region[idx].dt_attr)) { + case DT_MEM_ARM_MPU_RAM: + region_conf = _BUILD_REGION_CONF(region[idx], REGION_RAM_ATTR); + break; +#ifdef REGION_RAM_NOCACHE_ATTR + case DT_MEM_ARM_MPU_RAM_NOCACHE: + region_conf = _BUILD_REGION_CONF(region[idx], REGION_RAM_NOCACHE_ATTR); + __ASSERT(!(region[idx].dt_attr & DT_MEM_CACHEABLE), + "RAM_NOCACHE with DT_MEM_CACHEABLE attribute\n"); + break; +#endif +#ifdef REGION_FLASH_ATTR + case DT_MEM_ARM_MPU_FLASH: + region_conf = _BUILD_REGION_CONF(region[idx], REGION_FLASH_ATTR); + break; +#endif +#ifdef REGION_PPB_ATTR + case DT_MEM_ARM_MPU_PPB: + region_conf = _BUILD_REGION_CONF(region[idx], REGION_PPB_ATTR); + break; +#endif +#ifdef REGION_IO_ATTR + case DT_MEM_ARM_MPU_IO: + region_conf = _BUILD_REGION_CONF(region[idx], REGION_IO_ATTR); + break; +#endif +#ifdef REGION_EXTMEM_ATTR + case DT_MEM_ARM_MPU_EXTMEM: + region_conf = _BUILD_REGION_CONF(region[idx], REGION_EXTMEM_ATTR); + break; +#endif + default: + /* Either the specified `ATTR_MPU_*` attribute does not + * exists or the `REGION_*_ATTR` macro is not defined + * for that attribute. + */ + LOG_ERR("Invalid attribute for the region\n"); + return -EINVAL; + } +#if defined(CONFIG_ARMV7_R) + region_conf.size = size_to_mpu_rasr_size(region[idx].dt_size); +#endif + + if (region_allocate_and_init((*reg_index), + (const struct arm_mpu_region *) ®ion_conf) < 0) { + return -EINVAL; + } + + (*reg_index)++; + } + + return 0; +} + /* This internal function programs an MPU region * of a given configuration at a given MPU index. */ @@ -375,6 +457,11 @@ int z_arm_mpu_init(void) /* Update the number of programmed MPU regions. */ static_regions_num = mpu_config.num_regions; + /* DT-defined MPU regions. */ + if (mpu_configure_regions_from_dt(&static_regions_num) == -EINVAL) { + __ASSERT(0, "Failed to allocate MPU regions from DT\n"); + return -EINVAL; + } arm_core_mpu_enable(); diff --git a/soc/arm/common/cortex_m/arm_mpu_regions.c b/arch/arm/core/mpu/arm_mpu_regions.c similarity index 84% rename from soc/arm/common/cortex_m/arm_mpu_regions.c rename to arch/arm/core/mpu/arm_mpu_regions.c index a7df11a19e1..cfe1230c907 100644 --- a/soc/arm/common/cortex_m/arm_mpu_regions.c +++ b/arch/arm/core/mpu/arm_mpu_regions.c @@ -5,10 +5,9 @@ */ #include -#include -#include +#include -#include +#include #if USE_PARTITION_MANAGER #include #endif @@ -42,9 +41,6 @@ static const struct arm_mpu_region mpu_regions[] = { #endif #endif /* USE_PARTITION_MANAGER */ - - /* DT-defined regions */ - DT_MEMORY_ATTR_APPLY(ARM_MPU_REGION_INIT) }; const struct arm_mpu_config mpu_config = { diff --git a/arch/arm/core/aarch32/mpu/arm_mpu_v7_internal.h b/arch/arm/core/mpu/arm_mpu_v7_internal.h similarity index 100% rename from arch/arm/core/aarch32/mpu/arm_mpu_v7_internal.h rename to arch/arm/core/mpu/arm_mpu_v7_internal.h diff --git a/arch/arm/core/aarch32/mpu/arm_mpu_v8_internal.h b/arch/arm/core/mpu/arm_mpu_v8_internal.h similarity index 99% rename from arch/arm/core/aarch32/mpu/arm_mpu_v8_internal.h rename to arch/arm/core/mpu/arm_mpu_v8_internal.h index dd5e7f94bfb..1f7cb04839e 100644 --- a/arch/arm/core/aarch32/mpu/arm_mpu_v8_internal.h +++ b/arch/arm/core/mpu/arm_mpu_v8_internal.h @@ -8,7 +8,7 @@ #ifndef ZEPHYR_ARCH_ARM_CORE_AARCH32_MPU_ARM_MPU_V8_INTERNAL_H_ #define ZEPHYR_ARCH_ARM_CORE_AARCH32_MPU_ARM_MPU_V8_INTERNAL_H_ -#include +#include #define LOG_LEVEL CONFIG_MPU_LOG_LEVEL #include #include diff --git a/arch/arm/core/aarch32/mpu/cortex_a_r/arm_mpu_internal.h b/arch/arm/core/mpu/cortex_a_r/arm_mpu_internal.h similarity index 100% rename from arch/arm/core/aarch32/mpu/cortex_a_r/arm_mpu_internal.h rename to arch/arm/core/mpu/cortex_a_r/arm_mpu_internal.h diff --git a/arch/arm/core/aarch32/mpu/cortex_m/arm_mpu_internal.h b/arch/arm/core/mpu/cortex_m/arm_mpu_internal.h similarity index 100% rename from arch/arm/core/aarch32/mpu/cortex_m/arm_mpu_internal.h rename to arch/arm/core/mpu/cortex_m/arm_mpu_internal.h diff --git a/arch/arm/core/aarch32/mpu/nxp_mpu.c b/arch/arm/core/mpu/nxp_mpu.c similarity index 89% rename from arch/arm/core/aarch32/mpu/nxp_mpu.c rename to arch/arm/core/mpu/nxp_mpu.c index eeed6383d83..39d7cde6f8f 100644 --- a/arch/arm/core/aarch32/mpu/nxp_mpu.c +++ b/arch/arm/core/mpu/nxp_mpu.c @@ -13,11 +13,20 @@ #include #include #include +#include +#include #define LOG_LEVEL CONFIG_MPU_LOG_LEVEL #include LOG_MODULE_DECLARE(mpu); +#define NODE_HAS_PROP_AND_OR(node_id, prop) \ + DT_NODE_HAS_PROP(node_id, prop) || + +BUILD_ASSERT((DT_FOREACH_STATUS_OKAY_NODE_VARGS( + NODE_HAS_PROP_AND_OR, zephyr_memory_region_mpu) false) == false, + "`zephyr,memory-region-mpu` was deprecated in favor of `zephyr,memory-attr`"); + /* * Global status variable holding the number of HW MPU region indices, which * have been reserved by the MPU driver to program the static (fixed) memory @@ -28,8 +37,10 @@ static uint8_t static_regions_num; /* Global MPU configuration at system initialization. */ static void mpu_init(void) { +#if defined(CONFIG_SOC_FAMILY_KINETIS) /* Enable clock for the Memory Protection Unit (MPU). */ CLOCK_EnableClock(kCLOCK_Sysmpu0); +#endif } /** @@ -134,6 +145,60 @@ static int region_allocate_and_init(const uint8_t index, return index; } +#define _BUILD_REGION_CONF(reg, _ATTR) \ + (struct nxp_mpu_region) { .name = (reg).dt_name, \ + .base = (reg).dt_addr, \ + .end = (reg).dt_addr + (reg).dt_size, \ + .attr = _ATTR, \ + } + +/* This internal function programs the MPU regions defined in the DT when using + * the `zephyr,memory-attr = <( DT_MEM_ARM(...) )>` property. + */ +static int mpu_configure_regions_from_dt(uint8_t *reg_index) +{ + const struct mem_attr_region_t *region; + size_t num_regions; + + num_regions = mem_attr_get_regions(®ion); + + for (size_t idx = 0; idx < num_regions; idx++) { + struct nxp_mpu_region region_conf; + + switch (DT_MEM_ARM_GET(region[idx].dt_attr)) { + case DT_MEM_ARM_MPU_RAM: + region_conf = _BUILD_REGION_CONF(region[idx], REGION_RAM_ATTR); + break; +#ifdef REGION_FLASH_ATTR + case DT_MEM_ARM_MPU_FLASH: + region_conf = _BUILD_REGION_CONF(region[idx], REGION_FLASH_ATTR); + break; +#endif +#ifdef REGION_IO_ATTR + case DT_MEM_ARM_MPU_IO: + region_conf = _BUILD_REGION_CONF(region[idx], REGION_IO_ATTR); + break; +#endif + default: + /* Either the specified `ATTR_MPU_*` attribute does not + * exists or the `REGION_*_ATTR` macro is not defined + * for that attribute. + */ + LOG_ERR("Invalid attribute for the region\n"); + return -EINVAL; + } + + if (region_allocate_and_init((*reg_index), + (const struct nxp_mpu_region *) ®ion_conf) < 0) { + return -EINVAL; + } + + (*reg_index)++; + } + + return 0; +} + /** * This internal function is utilized by the MPU driver to combine a given * region attribute configuration and size and fill-in a driver-specific @@ -636,6 +701,11 @@ int z_arm_mpu_init(void) /* Update the number of programmed MPU regions. */ static_regions_num = mpu_config.num_regions; + /* DT-defined MPU regions. */ + if (mpu_configure_regions_from_dt(&static_regions_num) == -EINVAL) { + __ASSERT(0, "Failed to allocate MPU regions from DT\n"); + return -EINVAL; + } arm_core_mpu_enable(); diff --git a/arch/arm/core/aarch32/nmi.c b/arch/arm/core/nmi.c similarity index 100% rename from arch/arm/core/aarch32/nmi.c rename to arch/arm/core/nmi.c diff --git a/arch/arm/core/aarch32/nmi_on_reset.S b/arch/arm/core/nmi_on_reset.S similarity index 100% rename from arch/arm/core/aarch32/nmi_on_reset.S rename to arch/arm/core/nmi_on_reset.S diff --git a/arch/arm/core/offsets/offsets_aarch32.c b/arch/arm/core/offsets/offsets_aarch32.c index 1eb63bec54f..4399377134d 100644 --- a/arch/arm/core/offsets/offsets_aarch32.c +++ b/arch/arm/core/offsets/offsets_aarch32.c @@ -32,6 +32,11 @@ GEN_OFFSET_SYM(_thread_arch_t, basepri); GEN_OFFSET_SYM(_thread_arch_t, swap_return_value); +#if defined(CONFIG_CPU_AARCH32_CORTEX_A) || defined(CONFIG_CPU_AARCH32_CORTEX_R) +GEN_OFFSET_SYM(_thread_arch_t, exception_depth); +GEN_OFFSET_SYM(_cpu_arch_t, exc_depth); +#endif + #if defined(CONFIG_ARM_STORE_EXC_RETURN) || defined(CONFIG_USERSPACE) GEN_OFFSET_SYM(_thread_arch_t, mode); #endif diff --git a/arch/arm/core/common/tls.c b/arch/arm/core/tls.c similarity index 100% rename from arch/arm/core/common/tls.c rename to arch/arm/core/tls.c diff --git a/arch/arm/core/aarch32/userspace.S b/arch/arm/core/userspace.S similarity index 99% rename from arch/arm/core/aarch32/userspace.S rename to arch/arm/core/userspace.S index 58553a8c915..bf89c7d663d 100644 --- a/arch/arm/core/aarch32/userspace.S +++ b/arch/arm/core/userspace.S @@ -12,7 +12,7 @@ #include #include -#include +#include #if defined(CONFIG_CPU_AARCH32_CORTEX_R) #include diff --git a/arch/arm/core/aarch32/vector_table.ld b/arch/arm/core/vector_table.ld similarity index 100% rename from arch/arm/core/aarch32/vector_table.ld rename to arch/arm/core/vector_table.ld diff --git a/arch/arm/core/aarch32/zimage_header.ld b/arch/arm/core/zimage_header.ld similarity index 100% rename from arch/arm/core/aarch32/zimage_header.ld rename to arch/arm/core/zimage_header.ld diff --git a/arch/arm/include/aarch32/cortex_a_r/exc.h b/arch/arm/include/aarch32/cortex_a_r/exc.h deleted file mode 100644 index 8f4c7d17c44..00000000000 --- a/arch/arm/include/aarch32/cortex_a_r/exc.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2018 Lexmark International, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Exception/interrupt context helpers for Cortex-A and Cortex-R CPUs - * - * Exception/interrupt context helpers. - */ - -#ifndef ZEPHYR_ARCH_ARM_INCLUDE_AARCH32_CORTEX_A_R_EXC_H_ -#define ZEPHYR_ARCH_ARM_INCLUDE_AARCH32_CORTEX_A_R_EXC_H_ - -#include - -#ifdef _ASMLANGUAGE - -/* nothing */ - -#else - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef CONFIG_IRQ_OFFLOAD -extern volatile irq_offload_routine_t offload_routine; -#endif - -/* Check the CPSR mode bits to see if we are in IRQ or FIQ mode */ -static ALWAYS_INLINE bool arch_is_in_isr(void) -{ - return (_kernel.cpus[0].nested != 0U); -} - -static ALWAYS_INLINE bool arch_is_in_nested_exception(const z_arch_esf_t *esf) -{ - return (_kernel.cpus[0].nested > 1U) ? (true) : (false); -} - -#if defined(CONFIG_USERSPACE) -/* - * This function is used by privileged code to determine if the thread - * associated with the stack frame is in user mode. - */ -static ALWAYS_INLINE bool z_arm_preempted_thread_in_user_mode(const z_arch_esf_t *esf) -{ - return ((esf->basic.xpsr & CPSR_M_Msk) == CPSR_M_USR); -} -#endif - -/** - * @brief Setup system exceptions - * - * Enable fault exceptions. - * - */ -static ALWAYS_INLINE void z_arm_exc_setup(void) -{ -} - -/** - * @brief Clear Fault exceptions - * - * Clear out exceptions for Mem, Bus, Usage and Hard Faults - * - */ -static ALWAYS_INLINE void z_arm_clear_faults(void) -{ -} - -extern void z_arm_cortex_r_svc(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _ASMLANGUAGE */ - -#endif /* ZEPHYR_ARCH_ARM_INCLUDE_AARCH32_CORTEX_A_R_EXC_H_ */ diff --git a/arch/arm/include/aarch32/cortex_m/exc.h b/arch/arm/include/aarch32/cortex_m/exc.h deleted file mode 100644 index 13fc08f178d..00000000000 --- a/arch/arm/include/aarch32/cortex_m/exc.h +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (c) 2013-2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Exception/interrupt context helpers for Cortex-M CPUs - * - * Exception/interrupt context helpers. - */ - -#ifndef ZEPHYR_ARCH_ARM_INCLUDE_AARCH32_CORTEX_M_EXC_H_ -#define ZEPHYR_ARCH_ARM_INCLUDE_AARCH32_CORTEX_M_EXC_H_ - -#include - -#ifdef _ASMLANGUAGE - -/* nothing */ - -#else - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef CONFIG_IRQ_OFFLOAD -extern volatile irq_offload_routine_t offload_routine; -#endif - -/* Writes to the AIRCR must be accompanied by a write of the value 0x05FA - * to the Vector Key field, otherwise the writes are ignored. - */ -#define AIRCR_VECT_KEY_PERMIT_WRITE 0x05FAUL - -/* - * The current executing vector is found in the IPSR register. All - * IRQs and system exceptions are considered as interrupt context. - */ -static ALWAYS_INLINE bool arch_is_in_isr(void) -{ - return (__get_IPSR()) ? (true) : (false); -} - -/** - * @brief Find out if we were in ISR context - * before the current exception occurred. - * - * A function that determines, based on inspecting the current - * ESF, whether the processor was in handler mode before entering - * the current exception state (i.e. nested exception) or not. - * - * Notes: - * - The function shall only be called from ISR context. - * - We do not use ARM processor state flags to determine - * whether we are in a nested exception; we rely on the - * RETPSR value stacked on the ESF. Hence, the function - * assumes that the ESF stack frame has a valid RETPSR - * value. - * - * @param esf the exception stack frame (cannot be NULL) - * @return true if execution state was in handler mode, before - * the current exception occurred, otherwise false. - */ -static ALWAYS_INLINE bool arch_is_in_nested_exception(const z_arch_esf_t *esf) -{ - return (esf->basic.xpsr & IPSR_ISR_Msk) ? (true) : (false); -} - -#if defined(CONFIG_USERSPACE) -/** - * @brief Is the thread in unprivileged mode - * - * @param esf the exception stack frame (unused) - * @return true if the current thread was in unprivileged mode - */ -static ALWAYS_INLINE bool z_arm_preempted_thread_in_user_mode(const z_arch_esf_t *esf) -{ - return z_arm_thread_is_in_user_mode(); -} -#endif - -/** - * @brief Setup system exceptions - * - * Set exception priorities to conform with the BASEPRI locking mechanism. - * Set PendSV priority to lowest possible. - * - * Enable fault exceptions. - */ -static ALWAYS_INLINE void z_arm_exc_setup(void) -{ - /* PendSV is set to lowest priority, regardless of it being used. - * This is done as the IRQ is always enabled. - */ - NVIC_SetPriority(PendSV_IRQn, _EXC_PENDSV_PRIO); - -#ifdef CONFIG_CPU_CORTEX_M_HAS_BASEPRI - /* Note: SVCall IRQ priority level is left to default (0) - * for Cortex-M variants without BASEPRI (e.g. ARMv6-M). - */ - NVIC_SetPriority(SVCall_IRQn, _EXC_SVC_PRIO); -#endif - -#ifdef CONFIG_CPU_CORTEX_M_HAS_PROGRAMMABLE_FAULT_PRIOS - NVIC_SetPriority(MemoryManagement_IRQn, _EXC_FAULT_PRIO); - NVIC_SetPriority(BusFault_IRQn, _EXC_FAULT_PRIO); - NVIC_SetPriority(UsageFault_IRQn, _EXC_FAULT_PRIO); -#if defined(CONFIG_CORTEX_M_DEBUG_MONITOR_HOOK) - NVIC_SetPriority(DebugMonitor_IRQn, IRQ_PRIO_LOWEST); -#elif defined(CONFIG_CPU_CORTEX_M_HAS_DWT) - NVIC_SetPriority(DebugMonitor_IRQn, _EXC_FAULT_PRIO); -#endif -#if defined(CONFIG_ARM_SECURE_FIRMWARE) - NVIC_SetPriority(SecureFault_IRQn, _EXC_FAULT_PRIO); -#endif /* CONFIG_ARM_SECURE_FIRMWARE */ - - /* Enable Usage, Mem, & Bus Faults */ - SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_MEMFAULTENA_Msk | - SCB_SHCSR_BUSFAULTENA_Msk; -#if defined(CONFIG_ARM_SECURE_FIRMWARE) - /* Enable Secure Fault */ - SCB->SHCSR |= SCB_SHCSR_SECUREFAULTENA_Msk; - /* Clear BFAR before setting BusFaults to target Non-Secure state. */ - SCB->BFAR = 0; -#endif /* CONFIG_ARM_SECURE_FIRMWARE */ -#endif /* CONFIG_CPU_CORTEX_M_HAS_PROGRAMMABLE_FAULT_PRIOS */ - -#if defined(CONFIG_ARM_SECURE_FIRMWARE) && \ - !defined(CONFIG_ARM_SECURE_BUSFAULT_HARDFAULT_NMI) - /* Set NMI, Hard, and Bus Faults as Non-Secure. - * NMI and Bus Faults targeting the Secure state will - * escalate to a SecureFault or SecureHardFault. - */ - SCB->AIRCR = - (SCB->AIRCR & (~(SCB_AIRCR_VECTKEY_Msk))) - | SCB_AIRCR_BFHFNMINS_Msk - | ((AIRCR_VECT_KEY_PERMIT_WRITE << SCB_AIRCR_VECTKEY_Pos) & - SCB_AIRCR_VECTKEY_Msk); - /* Note: Fault conditions that would generate a SecureFault - * in a PE with the Main Extension instead generate a - * SecureHardFault in a PE without the Main Extension. - */ -#endif /* ARM_SECURE_FIRMWARE && !ARM_SECURE_BUSFAULT_HARDFAULT_NMI */ - -#if defined(CONFIG_CPU_CORTEX_M_HAS_SYSTICK) && \ - !defined(CONFIG_CORTEX_M_SYSTICK) - /* SoC implements SysTick, but the system does not use it - * as driver for system timing. However, the SysTick IRQ is - * always enabled, so we must ensure the interrupt priority - * is set to a level lower than the kernel interrupts (for - * the assert mechanism to work properly) in case the SysTick - * interrupt is accidentally raised. - */ - NVIC_SetPriority(SysTick_IRQn, _EXC_IRQ_DEFAULT_PRIO); -#endif /* CPU_CORTEX_M_HAS_SYSTICK && ! CORTEX_M_SYSTICK */ - -} - -/** - * @brief Clear Fault exceptions - * - * Clear out exceptions for Mem, Bus, Usage and Hard Faults - */ -static ALWAYS_INLINE void z_arm_clear_faults(void) -{ -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - /* Reset all faults */ - SCB->CFSR = SCB_CFSR_USGFAULTSR_Msk | - SCB_CFSR_MEMFAULTSR_Msk | - SCB_CFSR_BUSFAULTSR_Msk; - - /* Clear all Hard Faults - HFSR is write-one-to-clear */ - SCB->HFSR = 0xffffffff; -#else -#error Unknown ARM architecture -#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ -} - -/** - * @brief Assess whether a debug monitor event should be treated as an error - * - * This routine checks the status of a debug_monitor() exception, and - * evaluates whether this needs to be considered as a processor error. - * - * @return true if the DM exception is a processor error, otherwise false - */ -bool z_arm_debug_monitor_event_error_check(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _ASMLANGUAGE */ - -#endif /* ZEPHYR_ARCH_ARM_INCLUDE_AARCH32_CORTEX_M_EXC_H_ */ diff --git a/arch/arm/include/aarch32/kernel_arch_func.h b/arch/arm/include/aarch32/kernel_arch_func.h deleted file mode 100644 index 08f4a6d92b5..00000000000 --- a/arch/arm/include/aarch32/kernel_arch_func.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2013-2016 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Private kernel definitions (ARM) - * - * This file contains private kernel function definitions and various - * other definitions for the 32-bit ARM Cortex-A/R/M processor architecture - * family. - * - * This file is also included by assembly language files which must #define - * _ASMLANGUAGE before including this header file. Note that kernel - * assembly source files obtains structure offset values via "absolute symbols" - * in the offsets.o module. - */ - -#ifndef ZEPHYR_ARCH_ARM_INCLUDE_AARCH32_KERNEL_ARCH_FUNC_H_ -#define ZEPHYR_ARCH_ARM_INCLUDE_AARCH32_KERNEL_ARCH_FUNC_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _ASMLANGUAGE -extern void z_arm_fault_init(void); -extern void z_arm_cpu_idle_init(void); -#ifdef CONFIG_ARM_MPU -extern void z_arm_configure_static_mpu_regions(void); -extern void z_arm_configure_dynamic_mpu_regions(struct k_thread *thread); -extern int z_arm_mpu_init(void); -#endif /* CONFIG_ARM_MPU */ -#ifdef CONFIG_ARM_AARCH32_MMU -extern int z_arm_mmu_init(void); -#endif /* CONFIG_ARM_AARCH32_MMU */ - -static ALWAYS_INLINE void arch_kernel_init(void) -{ - z_arm_interrupt_stack_setup(); - z_arm_exc_setup(); - z_arm_fault_init(); - z_arm_cpu_idle_init(); - z_arm_clear_faults(); -#if defined(CONFIG_ARM_MPU) - z_arm_mpu_init(); - /* Configure static memory map. This will program MPU regions, - * to set up access permissions for fixed memory sections, such - * as Application Memory or No-Cacheable SRAM area. - * - * This function is invoked once, upon system initialization. - */ - z_arm_configure_static_mpu_regions(); -#endif /* CONFIG_ARM_MPU */ -#if defined(CONFIG_ARM_AARCH32_MMU) - z_arm_mmu_init(); -#endif /* CONFIG_ARM_AARCH32_MMU */ -} - -static ALWAYS_INLINE void -arch_thread_return_value_set(struct k_thread *thread, unsigned int value) -{ - thread->arch.swap_return_value = value; -} - -#if !defined(CONFIG_MULTITHREADING) && defined(CONFIG_CPU_CORTEX_M) -extern FUNC_NORETURN void z_arm_switch_to_main_no_multithreading( - k_thread_entry_t main_func, - void *p1, void *p2, void *p3); - -#define ARCH_SWITCH_TO_MAIN_NO_MULTITHREADING \ - z_arm_switch_to_main_no_multithreading - -#endif /* !CONFIG_MULTITHREADING && CONFIG_CPU_CORTEX_M */ - -extern FUNC_NORETURN void z_arm_userspace_enter(k_thread_entry_t user_entry, - void *p1, void *p2, void *p3, - uint32_t stack_end, - uint32_t stack_start); - -extern void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf); - -#endif /* _ASMLANGUAGE */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZEPHYR_ARCH_ARM_INCLUDE_AARCH32_KERNEL_ARCH_FUNC_H_ */ diff --git a/arch/arm/include/aarch32/offsets_short_arch.h b/arch/arm/include/aarch32/offsets_short_arch.h deleted file mode 100644 index 5f41a7fe195..00000000000 --- a/arch/arm/include/aarch32/offsets_short_arch.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2016 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_ARCH_ARM_INCLUDE_AARCH32_OFFSETS_SHORT_ARCH_H_ -#define ZEPHYR_ARCH_ARM_INCLUDE_AARCH32_OFFSETS_SHORT_ARCH_H_ - -#include - -/* kernel */ - -/* nothing for now */ - -/* end - kernel */ - -/* threads */ - -#define _thread_offset_to_basepri \ - (___thread_t_arch_OFFSET + ___thread_arch_t_basepri_OFFSET) - -#define _thread_offset_to_preempt_float \ - (___thread_t_arch_OFFSET + ___thread_arch_t_preempt_float_OFFSET) - -#if defined(CONFIG_USERSPACE) || defined(CONFIG_FPU_SHARING) -#define _thread_offset_to_mode \ - (___thread_t_arch_OFFSET + ___thread_arch_t_mode_OFFSET) -#endif - -#if defined(CONFIG_ARM_STORE_EXC_RETURN) -#define _thread_offset_to_mode_exc_return \ - (___thread_t_arch_OFFSET + ___thread_arch_t_mode_exc_return_OFFSET) -#endif - -#ifdef CONFIG_USERSPACE -#define _thread_offset_to_priv_stack_start \ - (___thread_t_arch_OFFSET + ___thread_arch_t_priv_stack_start_OFFSET) - -#if defined(CONFIG_CPU_AARCH32_CORTEX_R) -#define _thread_offset_to_priv_stack_end \ - (___thread_t_arch_OFFSET + ___thread_arch_t_priv_stack_end_OFFSET) - -#define _thread_offset_to_sp_usr \ - (___thread_t_arch_OFFSET + ___thread_arch_t_sp_usr_OFFSET) -#endif -#endif - -#if defined(CONFIG_THREAD_STACK_INFO) -#define _thread_offset_to_stack_info_start \ - (___thread_stack_info_t_start_OFFSET + ___thread_t_stack_info_OFFSET) -#endif - - -/* end - threads */ - -#endif /* ZEPHYR_ARCH_ARM_INCLUDE_AARCH32_OFFSETS_SHORT_ARCH_H_ */ diff --git a/arch/arm/include/cortex_a_r/exc.h b/arch/arm/include/cortex_a_r/exc.h new file mode 100644 index 00000000000..6cddaa1c72c --- /dev/null +++ b/arch/arm/include/cortex_a_r/exc.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018 Lexmark International, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Exception/interrupt context helpers for Cortex-A and Cortex-R CPUs + * + * Exception/interrupt context helpers. + */ + +#ifndef ZEPHYR_ARCH_ARM_INCLUDE_AARCH32_CORTEX_A_R_EXC_H_ +#define ZEPHYR_ARCH_ARM_INCLUDE_AARCH32_CORTEX_A_R_EXC_H_ + +#include + +#ifdef _ASMLANGUAGE + +/* nothing */ + +#else + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CONFIG_IRQ_OFFLOAD +extern volatile irq_offload_routine_t offload_routine; +#endif + +/* Check the CPSR mode bits to see if we are in IRQ or FIQ mode */ +static ALWAYS_INLINE bool arch_is_in_isr(void) +{ + return (arch_curr_cpu()->nested != 0U); +} + +static ALWAYS_INLINE bool arch_is_in_nested_exception(const z_arch_esf_t *esf) +{ + return (arch_curr_cpu()->arch.exc_depth > 1U) ? (true) : (false); +} + +#if defined(CONFIG_USERSPACE) +/* + * This function is used by privileged code to determine if the thread + * associated with the stack frame is in user mode. + */ +static ALWAYS_INLINE bool z_arm_preempted_thread_in_user_mode(const z_arch_esf_t *esf) +{ + return ((esf->basic.xpsr & CPSR_M_Msk) == CPSR_M_USR); +} +#endif + +#ifndef CONFIG_USE_SWITCH +extern void z_arm_cortex_r_svc(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_ARCH_ARM_INCLUDE_AARCH32_CORTEX_A_R_EXC_H_ */ diff --git a/arch/arm/include/cortex_a_r/kernel_arch_func.h b/arch/arm/include/cortex_a_r/kernel_arch_func.h new file mode 100644 index 00000000000..88f631ff4b4 --- /dev/null +++ b/arch/arm/include/cortex_a_r/kernel_arch_func.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2019 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @file + * @brief Private kernel definitions (ARM) + * + * This file contains private kernel function definitions and various + * other definitions for the 32-bit ARM Cortex-A/R processor architecture + * family. + * + * This file is also included by assembly language files which must #define + * _ASMLANGUAGE before including this header file. Note that kernel + * assembly source files obtains structure offset values via "absolute symbols" + * in the offsets.o module. + */ + +#ifndef ZEPHYR_ARCH_ARM_INCLUDE_CORTEX_A_R_KERNEL_ARCH_FUNC_H_ +#define ZEPHYR_ARCH_ARM_INCLUDE_CORTEX_A_R_KERNEL_ARCH_FUNC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ASMLANGUAGE + +static ALWAYS_INLINE void arch_kernel_init(void) +{ +} + +#ifndef CONFIG_USE_SWITCH + +static ALWAYS_INLINE void +arch_thread_return_value_set(struct k_thread *thread, unsigned int value) +{ + thread->arch.swap_return_value = value; +} + +#else + +static ALWAYS_INLINE void arch_switch(void *switch_to, void **switched_from) +{ + extern void z_arm_context_switch(struct k_thread *new, + struct k_thread *old); + + struct k_thread *new = switch_to; + struct k_thread *old = CONTAINER_OF(switched_from, struct k_thread, + switch_handle); + + z_arm_context_switch(new, old); +} + +#endif + +extern FUNC_NORETURN void z_arm_userspace_enter(k_thread_entry_t user_entry, + void *p1, void *p2, void *p3, + uint32_t stack_end, + uint32_t stack_start); + +extern void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf); + +#endif /* _ASMLANGUAGE */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_ARCH_ARM_INCLUDE_CORTEX_A_R_KERNEL_ARCH_FUNC_H_ */ diff --git a/arch/arm/include/aarch32/cortex_a_r/stack.h b/arch/arm/include/cortex_a_r/stack.h similarity index 75% rename from arch/arm/include/aarch32/cortex_a_r/stack.h rename to arch/arm/include/cortex_a_r/stack.h index e6648f1914e..5638c49ee23 100644 --- a/arch/arm/include/aarch32/cortex_a_r/stack.h +++ b/arch/arm/include/cortex_a_r/stack.h @@ -26,17 +26,6 @@ extern "C" { extern void z_arm_init_stacks(void); -/** - * - * @brief Setup interrupt stack - * - * On Cortex-A and Cortex-R, the interrupt stack is set up by reset.S - * - */ -static ALWAYS_INLINE void z_arm_interrupt_stack_setup(void) -{ -} - #endif /* _ASMLANGUAGE */ #ifdef __cplusplus diff --git a/arch/arm/include/aarch32/cortex_a_r/tcm.h b/arch/arm/include/cortex_a_r/tcm.h similarity index 100% rename from arch/arm/include/aarch32/cortex_a_r/tcm.h rename to arch/arm/include/cortex_a_r/tcm.h diff --git a/arch/arm/include/aarch32/cortex_m/cmse.h b/arch/arm/include/cortex_m/cmse.h similarity index 100% rename from arch/arm/include/aarch32/cortex_m/cmse.h rename to arch/arm/include/cortex_m/cmse.h diff --git a/arch/arm/include/aarch32/cortex_m/dwt.h b/arch/arm/include/cortex_m/dwt.h similarity index 100% rename from arch/arm/include/aarch32/cortex_m/dwt.h rename to arch/arm/include/cortex_m/dwt.h diff --git a/arch/arm/include/cortex_m/exc.h b/arch/arm/include/cortex_m/exc.h new file mode 100644 index 00000000000..b46e74341a9 --- /dev/null +++ b/arch/arm/include/cortex_m/exc.h @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Exception/interrupt context helpers for Cortex-M CPUs + * + * Exception/interrupt context helpers. + */ + +#ifndef ZEPHYR_ARCH_ARM_INCLUDE_AARCH32_CORTEX_M_EXC_H_ +#define ZEPHYR_ARCH_ARM_INCLUDE_AARCH32_CORTEX_M_EXC_H_ + +#include + +#ifdef _ASMLANGUAGE + +/* nothing */ + +#else + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CONFIG_IRQ_OFFLOAD +extern volatile irq_offload_routine_t offload_routine; +#endif + +/* Writes to the AIRCR must be accompanied by a write of the value 0x05FA + * to the Vector Key field, otherwise the writes are ignored. + */ +#define AIRCR_VECT_KEY_PERMIT_WRITE 0x05FAUL + +/* + * The current executing vector is found in the IPSR register. All + * IRQs and system exceptions are considered as interrupt context. + */ +static ALWAYS_INLINE bool arch_is_in_isr(void) +{ + return (__get_IPSR()) ? (true) : (false); +} + +/** + * @brief Find out if we were in ISR context + * before the current exception occurred. + * + * A function that determines, based on inspecting the current + * ESF, whether the processor was in handler mode before entering + * the current exception state (i.e. nested exception) or not. + * + * Notes: + * - The function shall only be called from ISR context. + * - We do not use ARM processor state flags to determine + * whether we are in a nested exception; we rely on the + * RETPSR value stacked on the ESF. Hence, the function + * assumes that the ESF stack frame has a valid RETPSR + * value. + * + * @param esf the exception stack frame (cannot be NULL) + * @return true if execution state was in handler mode, before + * the current exception occurred, otherwise false. + */ +static ALWAYS_INLINE bool arch_is_in_nested_exception(const z_arch_esf_t *esf) +{ + return (esf->basic.xpsr & IPSR_ISR_Msk) ? (true) : (false); +} + +#if defined(CONFIG_USERSPACE) +/** + * @brief Is the thread in unprivileged mode + * + * @param esf the exception stack frame (unused) + * @return true if the current thread was in unprivileged mode + */ +static ALWAYS_INLINE bool z_arm_preempted_thread_in_user_mode(const z_arch_esf_t *esf) +{ + return z_arm_thread_is_in_user_mode(); +} +#endif + +/** + * @brief Setup system exceptions + * + * Set exception priorities to conform with the BASEPRI locking mechanism. + * Set PendSV priority to lowest possible. + * + * Enable fault exceptions. + */ +static ALWAYS_INLINE void z_arm_exc_setup(void) +{ + /* PendSV is set to lowest priority, regardless of it being used. + * This is done as the IRQ is always enabled. + */ + NVIC_SetPriority(PendSV_IRQn, _EXC_PENDSV_PRIO); + +#ifdef CONFIG_CPU_CORTEX_M_HAS_BASEPRI + /* Note: SVCall IRQ priority level is left to default (0) + * for Cortex-M variants without BASEPRI (e.g. ARMv6-M). + */ + NVIC_SetPriority(SVCall_IRQn, _EXC_SVC_PRIO); +#endif + +#ifdef CONFIG_CPU_CORTEX_M_HAS_PROGRAMMABLE_FAULT_PRIOS + NVIC_SetPriority(MemoryManagement_IRQn, _EXC_FAULT_PRIO); + NVIC_SetPriority(BusFault_IRQn, _EXC_FAULT_PRIO); + NVIC_SetPriority(UsageFault_IRQn, _EXC_FAULT_PRIO); +#if defined(CONFIG_CORTEX_M_DEBUG_MONITOR_HOOK) + NVIC_SetPriority(DebugMonitor_IRQn, IRQ_PRIO_LOWEST); +#elif defined(CONFIG_CPU_CORTEX_M_HAS_DWT) + NVIC_SetPriority(DebugMonitor_IRQn, _EXC_FAULT_PRIO); +#endif +#if defined(CONFIG_ARM_SECURE_FIRMWARE) + NVIC_SetPriority(SecureFault_IRQn, _EXC_FAULT_PRIO); +#endif /* CONFIG_ARM_SECURE_FIRMWARE */ + + /* Enable Usage, Mem, & Bus Faults */ + SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_MEMFAULTENA_Msk | + SCB_SHCSR_BUSFAULTENA_Msk; +#if defined(CONFIG_ARM_SECURE_FIRMWARE) + /* Enable Secure Fault */ + SCB->SHCSR |= SCB_SHCSR_SECUREFAULTENA_Msk; + /* Clear BFAR before setting BusFaults to target Non-Secure state. */ + SCB->BFAR = 0; +#endif /* CONFIG_ARM_SECURE_FIRMWARE */ +#endif /* CONFIG_CPU_CORTEX_M_HAS_PROGRAMMABLE_FAULT_PRIOS */ + +#if defined(CONFIG_ARM_SECURE_FIRMWARE) && \ + !defined(CONFIG_ARM_SECURE_BUSFAULT_HARDFAULT_NMI) + /* Set NMI, Hard, and Bus Faults as Non-Secure. + * NMI and Bus Faults targeting the Secure state will + * escalate to a SecureFault or SecureHardFault. + */ + SCB->AIRCR = + (SCB->AIRCR & (~(SCB_AIRCR_VECTKEY_Msk))) + | SCB_AIRCR_BFHFNMINS_Msk + | ((AIRCR_VECT_KEY_PERMIT_WRITE << SCB_AIRCR_VECTKEY_Pos) & + SCB_AIRCR_VECTKEY_Msk); + /* Note: Fault conditions that would generate a SecureFault + * in a PE with the Main Extension instead generate a + * SecureHardFault in a PE without the Main Extension. + */ +#endif /* ARM_SECURE_FIRMWARE && !ARM_SECURE_BUSFAULT_HARDFAULT_NMI */ + +#if defined(CONFIG_CPU_CORTEX_M_HAS_SYSTICK) && \ + !defined(CONFIG_CORTEX_M_SYSTICK) + /* SoC implements SysTick, but the system does not use it + * as driver for system timing. However, the SysTick IRQ is + * always enabled, so we must ensure the interrupt priority + * is set to a level lower than the kernel interrupts (for + * the assert mechanism to work properly) in case the SysTick + * interrupt is accidentally raised. + */ + NVIC_SetPriority(SysTick_IRQn, _EXC_IRQ_DEFAULT_PRIO); +#endif /* CPU_CORTEX_M_HAS_SYSTICK && ! CORTEX_M_SYSTICK */ + +} + +/** + * @brief Clear Fault exceptions + * + * Clear out exceptions for Mem, Bus, Usage and Hard Faults + */ +static ALWAYS_INLINE void z_arm_clear_faults(void) +{ +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + /* Reset all faults */ + SCB->CFSR = SCB_CFSR_USGFAULTSR_Msk | + SCB_CFSR_MEMFAULTSR_Msk | + SCB_CFSR_BUSFAULTSR_Msk; + + /* Clear all Hard Faults - HFSR is write-one-to-clear */ + SCB->HFSR = 0xffffffff; +#else +#error Unknown ARM architecture +#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ +} + +/** + * @brief Assess whether a debug monitor event should be treated as an error + * + * This routine checks the status of a debug_monitor() exception, and + * evaluates whether this needs to be considered as a processor error. + * + * @return true if the DM exception is a processor error, otherwise false + */ +bool z_arm_debug_monitor_event_error_check(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_ARCH_ARM_INCLUDE_AARCH32_CORTEX_M_EXC_H_ */ diff --git a/arch/arm/include/cortex_m/kernel_arch_func.h b/arch/arm/include/cortex_m/kernel_arch_func.h new file mode 100644 index 00000000000..77619c9d6c4 --- /dev/null +++ b/arch/arm/include/cortex_m/kernel_arch_func.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2019 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @file + * @brief Private kernel definitions (ARM) + * + * This file contains private kernel function definitions and various + * other definitions for the 32-bit ARM Cortex-M processor architecture + * family. + * + * This file is also included by assembly language files which must #define + * _ASMLANGUAGE before including this header file. Note that kernel + * assembly source files obtains structure offset values via "absolute symbols" + * in the offsets.o module. + */ + +#ifndef ZEPHYR_ARCH_ARM_INCLUDE_CORTEX_M_KERNEL_ARCH_FUNC_H_ +#define ZEPHYR_ARCH_ARM_INCLUDE_CORTEX_M_KERNEL_ARCH_FUNC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ASMLANGUAGE +extern void z_arm_fault_init(void); +extern void z_arm_cpu_idle_init(void); +#ifdef CONFIG_ARM_MPU +extern void z_arm_configure_static_mpu_regions(void); +extern void z_arm_configure_dynamic_mpu_regions(struct k_thread *thread); +extern int z_arm_mpu_init(void); +#endif /* CONFIG_ARM_MPU */ +#ifdef CONFIG_ARM_AARCH32_MMU +extern int z_arm_mmu_init(void); +#endif /* CONFIG_ARM_AARCH32_MMU */ + +static ALWAYS_INLINE void arch_kernel_init(void) +{ + z_arm_interrupt_stack_setup(); + z_arm_exc_setup(); + z_arm_fault_init(); + z_arm_cpu_idle_init(); + z_arm_clear_faults(); +#if defined(CONFIG_ARM_MPU) + z_arm_mpu_init(); + /* Configure static memory map. This will program MPU regions, + * to set up access permissions for fixed memory sections, such + * as Application Memory or No-Cacheable SRAM area. + * + * This function is invoked once, upon system initialization. + */ + z_arm_configure_static_mpu_regions(); +#endif /* CONFIG_ARM_MPU */ +} + +static ALWAYS_INLINE void +arch_thread_return_value_set(struct k_thread *thread, unsigned int value) +{ + thread->arch.swap_return_value = value; +} + +#if !defined(CONFIG_MULTITHREADING) +extern FUNC_NORETURN void z_arm_switch_to_main_no_multithreading( + k_thread_entry_t main_func, + void *p1, void *p2, void *p3); + +#define ARCH_SWITCH_TO_MAIN_NO_MULTITHREADING \ + z_arm_switch_to_main_no_multithreading + +#endif /* !CONFIG_MULTITHREADING */ + +extern FUNC_NORETURN void z_arm_userspace_enter(k_thread_entry_t user_entry, + void *p1, void *p2, void *p3, + uint32_t stack_end, + uint32_t stack_start); + +extern void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf); + +#endif /* _ASMLANGUAGE */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_ARCH_ARM_INCLUDE_CORTEX_M_KERNEL_ARCH_FUNC_H_ */ diff --git a/arch/arm/include/aarch32/cortex_m/stack.h b/arch/arm/include/cortex_m/stack.h similarity index 100% rename from arch/arm/include/aarch32/cortex_m/stack.h rename to arch/arm/include/cortex_m/stack.h diff --git a/arch/arm/include/aarch32/cortex_m/tz.h b/arch/arm/include/cortex_m/tz.h similarity index 100% rename from arch/arm/include/aarch32/cortex_m/tz.h rename to arch/arm/include/cortex_m/tz.h diff --git a/arch/arm/include/aarch32/cortex_m/tz_ns.h b/arch/arm/include/cortex_m/tz_ns.h similarity index 100% rename from arch/arm/include/aarch32/cortex_m/tz_ns.h rename to arch/arm/include/cortex_m/tz_ns.h diff --git a/arch/arm/include/kernel_arch_data.h b/arch/arm/include/kernel_arch_data.h index 832e4b1042c..6ae5f643341 100644 --- a/arch/arm/include/kernel_arch_data.h +++ b/arch/arm/include/kernel_arch_data.h @@ -25,11 +25,11 @@ #include #if defined(CONFIG_CPU_CORTEX_M) -#include -#include +#include +#include #elif defined(CONFIG_CPU_AARCH32_CORTEX_R) || defined(CONFIG_CPU_AARCH32_CORTEX_A) -#include -#include +#include +#include #endif #ifndef _ASMLANGUAGE diff --git a/arch/arm/include/kernel_arch_func.h b/arch/arm/include/kernel_arch_func.h index b680da356f8..b8d67137b52 100644 --- a/arch/arm/include/kernel_arch_func.h +++ b/arch/arm/include/kernel_arch_func.h @@ -3,10 +3,29 @@ * * SPDX-License-Identifier: Apache-2.0 */ +/** + * @file + * @brief Private kernel definitions (ARM) + * + * This file contains private kernel function definitions and various + * other definitions for the 32-bit ARM Cortex-A/R/M processor architecture + * family. + * + * This file is also included by assembly language files which must #define + * _ASMLANGUAGE before including this header file. Note that kernel + * assembly source files obtains structure offset values via "absolute symbols" + * in the offsets.o module. + */ #ifndef ZEPHYR_ARCH_ARM_INCLUDE_KERNEL_ARCH_FUNC_H_ #define ZEPHYR_ARCH_ARM_INCLUDE_KERNEL_ARCH_FUNC_H_ -#include +#include + +#if defined(CONFIG_CPU_CORTEX_M) +#include +#else +#include +#endif #endif /* ZEPHYR_ARCH_ARM_INCLUDE_KERNEL_ARCH_FUNC_H_ */ diff --git a/arch/arm/include/offsets_short_arch.h b/arch/arm/include/offsets_short_arch.h index f09f24a72f6..4ceb1fc3f7a 100644 --- a/arch/arm/include/offsets_short_arch.h +++ b/arch/arm/include/offsets_short_arch.h @@ -7,6 +7,59 @@ #ifndef ZEPHYR_ARCH_ARM_INCLUDE_OFFSETS_SHORT_ARCH_H_ #define ZEPHYR_ARCH_ARM_INCLUDE_OFFSETS_SHORT_ARCH_H_ -#include +#include + +/* kernel */ + +/* nothing for now */ + +/* end - kernel */ + +/* threads */ + +#define _thread_offset_to_basepri \ + (___thread_t_arch_OFFSET + ___thread_arch_t_basepri_OFFSET) + +#define _thread_offset_to_preempt_float \ + (___thread_t_arch_OFFSET + ___thread_arch_t_preempt_float_OFFSET) + +#if defined(CONFIG_CPU_AARCH32_CORTEX_A) || defined(CONFIG_CPU_AARCH32_CORTEX_R) +#define _thread_offset_to_exception_depth \ + (___thread_t_arch_OFFSET + ___thread_arch_t_exception_depth_OFFSET) + +#define _cpu_offset_to_exc_depth \ + (___cpu_t_arch_OFFSET + ___cpu_arch_t_exc_depth_OFFSET) +#endif + +#if defined(CONFIG_USERSPACE) || defined(CONFIG_FPU_SHARING) +#define _thread_offset_to_mode \ + (___thread_t_arch_OFFSET + ___thread_arch_t_mode_OFFSET) +#endif + +#if defined(CONFIG_ARM_STORE_EXC_RETURN) +#define _thread_offset_to_mode_exc_return \ + (___thread_t_arch_OFFSET + ___thread_arch_t_mode_exc_return_OFFSET) +#endif + +#ifdef CONFIG_USERSPACE +#define _thread_offset_to_priv_stack_start \ + (___thread_t_arch_OFFSET + ___thread_arch_t_priv_stack_start_OFFSET) + +#if defined(CONFIG_CPU_AARCH32_CORTEX_R) +#define _thread_offset_to_priv_stack_end \ + (___thread_t_arch_OFFSET + ___thread_arch_t_priv_stack_end_OFFSET) + +#define _thread_offset_to_sp_usr \ + (___thread_t_arch_OFFSET + ___thread_arch_t_sp_usr_OFFSET) +#endif +#endif + +#if defined(CONFIG_THREAD_STACK_INFO) +#define _thread_offset_to_stack_info_start \ + (___thread_stack_info_t_start_OFFSET + ___thread_t_stack_info_OFFSET) +#endif + + +/* end - threads */ #endif /* ZEPHYR_ARCH_ARM_INCLUDE_OFFSETS_SHORT_ARCH_H_ */ diff --git a/arch/arm64/core/CMakeLists.txt b/arch/arm64/core/CMakeLists.txt index 56d6413034e..1804556c1a7 100644 --- a/arch/arm64/core/CMakeLists.txt +++ b/arch/arm64/core/CMakeLists.txt @@ -54,4 +54,4 @@ if(CMAKE_C_COMPILER_ID STREQUAL "GNU") zephyr_cc_option(-moverride=tune=no_ldp_stp_qregs) endif() -add_subdirectory_ifdef(CONFIG_SOC_XENVM xen) +add_subdirectory_ifdef(CONFIG_XEN xen) diff --git a/arch/arm64/core/Kconfig b/arch/arm64/core/Kconfig index cd34eb02568..fd74a526416 100644 --- a/arch/arm64/core/Kconfig +++ b/arch/arm64/core/Kconfig @@ -23,6 +23,7 @@ config CPU_AARCH64_CORTEX_R select HAS_FLASH_LOAD_OFFSET select CPU_HAS_DCACHE select CPU_HAS_ICACHE + select ARCH_HAS_STACK_PROTECTION select CPU_HAS_FPU imply FPU imply FPU_SHARING @@ -168,6 +169,17 @@ config ARM64_FALLBACK_ON_RESERVED_CORES then that core will be skipped and the next core in the device tree will be used. +config ARM64_STACK_PROTECTION + bool + default y if HW_STACK_PROTECTION + depends on ARM_MPU + select THREAD_STACK_INFO + select ARM64_SAFE_EXCEPTION_STACK + help + This option leverages the MMU or MPU to cause a system fatal error if + the bounds of the current process stack are overflowed. This is done + by preceding all stack areas with a fixed guard region. + if CPU_CORTEX_A config ARMV8_A_NS @@ -197,6 +209,8 @@ config ARMV8_A so that it can support some features included in the AArch64 state. It supports the T32 and A32 instruction sets. +rsource "xen/Kconfig" + endif # CPU_CORTEX_A if CPU_AARCH64_CORTEX_R diff --git a/arch/arm64/core/boot.h b/arch/arm64/core/boot.h index aa9e4526bba..d3f8e28eca3 100644 --- a/arch/arm64/core/boot.h +++ b/arch/arm64/core/boot.h @@ -20,7 +20,8 @@ extern void __start(void); #endif /* _ASMLANGUAGE */ /* Offsets into the boot_params structure */ -#define BOOT_PARAM_MPID_OFFSET 0 -#define BOOT_PARAM_SP_OFFSET 8 +#define BOOT_PARAM_MPID_OFFSET 0 +#define BOOT_PARAM_SP_OFFSET 8 +#define BOOT_PARAM_VOTING_OFFSET 16 #endif /* _BOOT_H_ */ diff --git a/arch/arm64/core/cortex_r/arm_mpu.c b/arch/arm64/core/cortex_r/arm_mpu.c index 2ecdb525715..e303a7c0379 100644 --- a/arch/arm64/core/cortex_r/arm_mpu.c +++ b/arch/arm64/core/cortex_r/arm_mpu.c @@ -15,14 +15,37 @@ #include #include #include +#include +#include +#include LOG_MODULE_REGISTER(mpu, CONFIG_MPU_LOG_LEVEL); -#define MPU_DYNAMIC_REGION_AREAS_NUM 1 +#define NODE_HAS_PROP_AND_OR(node_id, prop) \ + DT_NODE_HAS_PROP(node_id, prop) || -#ifdef CONFIG_USERSPACE +BUILD_ASSERT((DT_FOREACH_STATUS_OKAY_NODE_VARGS( + NODE_HAS_PROP_AND_OR, zephyr_memory_region_mpu) false) == false, + "`zephyr,memory-region-mpu` was deprecated in favor of `zephyr,memory-attr`"); + +#define MPU_DYNAMIC_REGION_AREAS_NUM 3 + +#if defined(CONFIG_USERSPACE) || defined(CONFIG_ARM64_STACK_PROTECTION) +static struct dynamic_region_info + sys_dyn_regions[CONFIG_MP_MAX_NUM_CPUS][MPU_DYNAMIC_REGION_AREAS_NUM]; +static int sys_dyn_regions_num[CONFIG_MP_MAX_NUM_CPUS]; + +static void dynamic_regions_init(void); static int dynamic_areas_init(uintptr_t start, size_t size); +static int flush_dynamic_regions_to_mpu(struct dynamic_region_info *dyn_regions, + uint8_t region_num); + +#if defined(CONFIG_USERSPACE) #define MPU_DYNAMIC_REGIONS_AREA_START ((uintptr_t)&_app_smem_start) +#else +#define MPU_DYNAMIC_REGIONS_AREA_START ((uintptr_t)&__kernel_ram_start) +#endif + #define MPU_DYNAMIC_REGIONS_AREA_SIZE ((size_t)((uintptr_t)&__kernel_ram_end - \ MPU_DYNAMIC_REGIONS_AREA_START)) #endif @@ -49,7 +72,7 @@ static int dynamic_areas_init(uintptr_t start, size_t size); static uint8_t static_regions_num; /* Get the number of supported MPU regions. */ -static inline uint8_t get_num_regions(void) +static ALWAYS_INLINE uint8_t get_num_regions(void) { uint64_t type; @@ -131,7 +154,7 @@ static ALWAYS_INLINE void mpu_set_region(uint32_t rnr, uint64_t rbar, barrier_isync_fence_full(); } -static inline void mpu_clr_region(uint32_t rnr) +static ALWAYS_INLINE void mpu_clr_region(uint32_t rnr) { write_prselr_el1(rnr); barrier_dsync_fence_full(); @@ -167,6 +190,64 @@ static ALWAYS_INLINE void region_init(const uint32_t index, mpu_set_region(index, rbar, rlar); } +#define _BUILD_REGION_CONF(reg, _ATTR) \ + (struct arm_mpu_region) { .name = (reg).dt_name, \ + .base = (reg).dt_addr, \ + .limit = (reg).dt_addr + (reg).dt_size, \ + .attr = _ATTR, \ + } + +/* This internal function programs the MPU regions defined in the DT when using + * the `zephyr,memory-attr = <( DT_MEM_ARM(...) )>` property. + */ +static int mpu_configure_regions_from_dt(uint8_t *reg_index) +{ + const struct mem_attr_region_t *region; + size_t num_regions; + + num_regions = mem_attr_get_regions(®ion); + + for (size_t idx = 0; idx < num_regions; idx++) { + struct arm_mpu_region region_conf; + + switch (DT_MEM_ARM_GET(region[idx].dt_attr)) { + case DT_MEM_ARM_MPU_RAM: + region_conf = _BUILD_REGION_CONF(region[idx], REGION_RAM_ATTR); + break; +#ifdef REGION_RAM_NOCACHE_ATTR + case DT_MEM_ARM_MPU_RAM_NOCACHE: + region_conf = _BUILD_REGION_CONF(region[idx], REGION_RAM_NOCACHE_ATTR); + __ASSERT(!(region[idx].dt_attr & DT_MEM_CACHEABLE), + "RAM_NOCACHE with DT_MEM_CACHEABLE attribute\n"); + break; +#endif +#ifdef REGION_FLASH_ATTR + case DT_MEM_ARM_MPU_FLASH: + region_conf = _BUILD_REGION_CONF(region[idx], REGION_FLASH_ATTR); + break; +#endif +#ifdef REGION_IO_ATTR + case DT_MEM_ARM_MPU_IO: + region_conf = _BUILD_REGION_CONF(region[idx], REGION_IO_ATTR); + break; +#endif + default: + /* Either the specified `ATTR_MPU_*` attribute does not + * exists or the `REGION_*_ATTR` macro is not defined + * for that attribute. + */ + LOG_ERR("Invalid attribute for the region\n"); + return -EINVAL; + } + + region_init((*reg_index), (const struct arm_mpu_region *) ®ion_conf); + + (*reg_index)++; + } + + return 0; +} + /* * @brief MPU default configuration * @@ -181,6 +262,7 @@ FUNC_NO_STACK_PROTECTOR void z_arm64_mm_init(bool is_primary_core) { uint64_t val; uint32_t r_index; + uint8_t tmp_static_num; /* Current MPU code supports only EL1 */ val = read_currentel(); @@ -220,30 +302,49 @@ FUNC_NO_STACK_PROTECTOR void z_arm64_mm_init(bool is_primary_core) } /* Update the number of programmed MPU regions. */ - static_regions_num = mpu_config.num_regions; + tmp_static_num = mpu_config.num_regions; + + /* DT-defined MPU regions. */ + if (mpu_configure_regions_from_dt(&tmp_static_num) == -EINVAL) { + __ASSERT(0, "Failed to allocate MPU regions from DT\n"); + return; + } arm_core_mpu_enable(); if (!is_primary_core) { - return; + /* + * primary core might reprogram the sys_regions, so secondary cores + * should re-flush the sys regions + */ + goto out; } -#ifdef CONFIG_USERSPACE + /* Only primary core init the static_regions_num */ + static_regions_num = tmp_static_num; + +#if defined(CONFIG_USERSPACE) || defined(CONFIG_ARM64_STACK_PROTECTION) + dynamic_regions_init(); /* Only primary core do the dynamic_areas_init. */ int rc = dynamic_areas_init(MPU_DYNAMIC_REGIONS_AREA_START, MPU_DYNAMIC_REGIONS_AREA_SIZE); - if (rc <= 0) { + if (rc < 0) { __ASSERT(0, "Dynamic areas init fail"); return; } #endif +out: +#if defined(CONFIG_ARM64_STACK_PROTECTION) + (void)flush_dynamic_regions_to_mpu(sys_dyn_regions[arch_curr_cpu()->id], + sys_dyn_regions_num[arch_curr_cpu()->id]); +#endif + return; } -#ifdef CONFIG_USERSPACE - -static struct dynamic_region_info sys_dyn_regions[MPU_DYNAMIC_REGION_AREAS_NUM]; -static int sys_dyn_regions_num; +#if defined(CONFIG_USERSPACE) || defined(CONFIG_ARM64_STACK_PROTECTION) +static int insert_region(struct dynamic_region_info *dyn_regions, uint8_t region_num, + uintptr_t start, size_t size, struct arm_mpu_region_attr *attr); static void arm_core_mpu_background_region_enable(void) { @@ -260,6 +361,8 @@ static void arm_core_mpu_background_region_disable(void) { uint64_t val; + /* Force any outstanding transfers to complete before disabling MPU */ + barrier_dmem_fence_full(); val = read_sctlr_el1(); val &= ~SCTLR_BR_BIT; write_sctlr_el1(val); @@ -267,144 +370,215 @@ static void arm_core_mpu_background_region_disable(void) barrier_isync_fence_full(); } +static void dynamic_regions_init(void) +{ + for (int cpuid = 0; cpuid < arch_num_cpus(); cpuid++) { + for (int i = 0; i < MPU_DYNAMIC_REGION_AREAS_NUM; i++) { + sys_dyn_regions[cpuid][i].index = -1; + } + } +} + static int dynamic_areas_init(uintptr_t start, size_t size) { const struct arm_mpu_region *region; struct dynamic_region_info *tmp_info; + int ret = -ENOENT; uint64_t base = start; uint64_t limit = base + size; - if (sys_dyn_regions_num + 1 > MPU_DYNAMIC_REGION_AREAS_NUM) { - return -1; - } + for (int cpuid = 0; cpuid < arch_num_cpus(); cpuid++) { + /* Check the following searching does not overflow the room */ + if (sys_dyn_regions_num[cpuid] + 1 > MPU_DYNAMIC_REGION_AREAS_NUM) { + return -ENOSPC; + } - for (size_t i = 0; i < mpu_config.num_regions; i++) { - region = &mpu_config.mpu_regions[i]; - tmp_info = &sys_dyn_regions[sys_dyn_regions_num]; - if (base >= region->base && limit <= region->limit) { - tmp_info->index = i; - tmp_info->region_conf = *region; - return ++sys_dyn_regions_num; + ret = -ENOENT; + + for (int i = 0; i < mpu_config.num_regions; i++) { + region = &mpu_config.mpu_regions[i]; + tmp_info = &sys_dyn_regions[cpuid][sys_dyn_regions_num[cpuid]]; + + if (base >= region->base && limit <= region->limit) { + tmp_info->index = i; + tmp_info->region_conf = *region; + sys_dyn_regions_num[cpuid] += 1; + /* find the region, reset ret to no error */ + ret = 0; + break; + } } +#if defined(CONFIG_ARM64_STACK_PROTECTION) + ret = insert_region(sys_dyn_regions[cpuid], + MPU_DYNAMIC_REGION_AREAS_NUM, + (uintptr_t)z_interrupt_stacks[cpuid], + Z_ARM64_STACK_GUARD_SIZE, + NULL /* delete this region */); + if (ret < 0) { + break; + } + /* + * No need to check here if (sys_dyn_regions[cpuid] + ret) overflows, + * because the insert_region has checked it. + */ + sys_dyn_regions_num[cpuid] += ret; +#endif } - return -1; + return ret < 0 ? ret : 0; +} + +static void set_region(struct arm_mpu_region *region, + uint64_t base, uint64_t limit, + struct arm_mpu_region_attr *attr) +{ + region->base = base; + region->limit = limit; + if (attr != NULL) { + region->attr = *attr; + } else { + memset(®ion->attr, 0, sizeof(struct arm_mpu_region_attr)); + } +} + +static void clear_region(struct arm_mpu_region *region) +{ + set_region(region, 0, 0, NULL); } static int dup_dynamic_regions(struct dynamic_region_info *dst, int len) { size_t i; - int ret = sys_dyn_regions_num; + int num = sys_dyn_regions_num[arch_curr_cpu()->id]; - CHECKIF(!(sys_dyn_regions_num < len)) { + if (num >= len) { LOG_ERR("system dynamic region nums too large."); - ret = -EINVAL; - goto out; + return -EINVAL; } - for (i = 0; i < sys_dyn_regions_num; i++) { - dst[i] = sys_dyn_regions[i]; + for (i = 0; i < num; i++) { + dst[i] = sys_dyn_regions[arch_curr_cpu()->id][i]; } for (; i < len; i++) { + clear_region(&dst[i].region_conf); dst[i].index = -1; } -out: - return ret; -} - -static void set_region(struct arm_mpu_region *region, - uint64_t base, uint64_t limit, - struct arm_mpu_region_attr *attr) -{ - region->base = base; - region->limit = limit; - region->attr = *attr; + return num; } -static int get_underlying_region_idx(struct dynamic_region_info *dyn_regions, - uint8_t region_num, uint64_t base, - uint64_t limit) +static struct dynamic_region_info *get_underlying_region(struct dynamic_region_info *dyn_regions, + uint8_t region_num, uint64_t base, + uint64_t limit) { - for (size_t idx = 0; idx < region_num; idx++) { + for (int idx = 0; idx < region_num; idx++) { struct arm_mpu_region *region = &(dyn_regions[idx].region_conf); if (base >= region->base && limit <= region->limit) { - return idx; + return &(dyn_regions[idx]); } } - return -1; + + return NULL; } -static int insert_region(struct dynamic_region_info *dyn_regions, - uint8_t region_idx, uint8_t region_num, - uintptr_t start, size_t size, - struct arm_mpu_region_attr *attr) +static struct dynamic_region_info *find_available_region(struct dynamic_region_info *dyn_regions, + uint8_t region_num) { + return get_underlying_region(dyn_regions, region_num, 0, 0); +} +/* + * return -ENOENT if there is no more available region + * do nothing if attr is NULL + */ +static int _insert_region(struct dynamic_region_info *dyn_regions, uint8_t region_num, + uint64_t base, uint64_t limit, struct arm_mpu_region_attr *attr) +{ + struct dynamic_region_info *tmp_region; + + if (attr == NULL) { + return 0; + } + + tmp_region = find_available_region(dyn_regions, region_num); + + if (tmp_region == NULL) { + return -ENOENT; + } + + set_region(&tmp_region->region_conf, base, limit, attr); + + return 0; +} + +static int insert_region(struct dynamic_region_info *dyn_regions, uint8_t region_num, + uintptr_t start, size_t size, struct arm_mpu_region_attr *attr) +{ + + int ret = 0; /* base: inclusive, limit: exclusive */ uint64_t base = (uint64_t)start; uint64_t limit = base + size; - int u_idx; - struct arm_mpu_region *u_region; + struct dynamic_region_info *u_region; uint64_t u_base; uint64_t u_limit; - struct arm_mpu_region_attr *u_attr; - int ret = 0; + struct arm_mpu_region_attr u_attr; - CHECKIF(!(region_idx < region_num)) { - LOG_ERR("Out-of-bounds error for dynamic region map. " - "region idx: %d, region num: %d", - region_idx, region_num); - ret = -EINVAL; - goto out; - } + int count = 0; - u_idx = get_underlying_region_idx(dyn_regions, region_idx, base, limit); + u_region = get_underlying_region(dyn_regions, region_num, base, limit); - CHECKIF(!(u_idx >= 0)) { - LOG_ERR("Invalid underlying region index"); - ret = -ENOENT; - goto out; + if (u_region == NULL) { + return -ENOENT; } - /* Get underlying region range and attr */ - u_region = &(dyn_regions[u_idx].region_conf); - u_base = u_region->base; - u_limit = u_region->limit; - u_attr = &u_region->attr; + /* restore the underlying region range and attr */ + u_base = u_region->region_conf.base; + u_limit = u_region->region_conf.limit; + u_attr = u_region->region_conf.attr; - /* Temporally holding new region available to be configured */ - struct arm_mpu_region *curr_region = &(dyn_regions[region_idx].region_conf); + clear_region(&u_region->region_conf); + count--; + /* if attr is NULL, meaning we are going to delete a region */ if (base == u_base && limit == u_limit) { /* * The new region overlaps entirely with the * underlying region. Simply update the attr. */ - set_region(u_region, base, limit, attr); + ret += _insert_region(dyn_regions, region_num, base, limit, attr); + count++; } else if (base == u_base) { - set_region(curr_region, base, limit, attr); - set_region(u_region, limit, u_limit, u_attr); - region_idx++; + ret += _insert_region(dyn_regions, region_num, limit, u_limit, &u_attr); + count++; + ret += _insert_region(dyn_regions, region_num, base, limit, attr); + count++; } else if (limit == u_limit) { - set_region(u_region, u_base, base, u_attr); - set_region(curr_region, base, limit, attr); - region_idx++; + ret += _insert_region(dyn_regions, region_num, u_base, base, &u_attr); + count++; + ret += _insert_region(dyn_regions, region_num, base, limit, attr); + count++; } else { - set_region(u_region, u_base, base, u_attr); - set_region(curr_region, base, limit, attr); - region_idx++; - curr_region = &(dyn_regions[region_idx].region_conf); - set_region(curr_region, limit, u_limit, u_attr); - region_idx++; + ret += _insert_region(dyn_regions, region_num, u_base, base, &u_attr); + count++; + ret += _insert_region(dyn_regions, region_num, base, limit, attr); + count++; + ret += _insert_region(dyn_regions, region_num, limit, u_limit, &u_attr); + count++; + } + + if (ret < 0) { + return -ENOENT; } - ret = region_idx; + if (attr == NULL) { + /* meanning we removed a region, so fix the count by decreasing 1 */ + count--; + } -out: - return ret; + return count; } static int flush_dynamic_regions_to_mpu(struct dynamic_region_info *dyn_regions, @@ -413,7 +587,13 @@ static int flush_dynamic_regions_to_mpu(struct dynamic_region_info *dyn_regions, __ASSERT(read_daif() & DAIF_IRQ_BIT, "mpu flushing must be called with IRQs disabled"); int reg_avail_idx = static_regions_num; - int ret = 0; + + if (region_num >= get_num_regions()) { + LOG_ERR("Out-of-bounds error for mpu regions. " + "region num: %d, total mpu regions: %d", + region_num, get_num_regions()); + return -ENOENT; + } arm_core_mpu_background_region_enable(); @@ -445,18 +625,12 @@ static int flush_dynamic_regions_to_mpu(struct dynamic_region_info *dyn_regions, if (region_idx < 0) { region_idx = reg_avail_idx++; } - CHECKIF(!(region_idx < get_num_regions())) { - LOG_ERR("Out-of-bounds error for mpu regions. " - "region idx: %d, total mpu regions: %d", - region_idx, get_num_regions()); - ret = -ENOENT; - } region_init(region_idx, &(dyn_regions[i].region_conf)); } arm_core_mpu_background_region_disable(); - return ret; + return 0; } static int configure_dynamic_mpu_regions(struct k_thread *thread) @@ -465,21 +639,24 @@ static int configure_dynamic_mpu_regions(struct k_thread *thread) struct dynamic_region_info *dyn_regions = thread->arch.regions; const uint8_t max_region_num = ARM64_MPU_MAX_DYNAMIC_REGIONS; - uint8_t region_num; - int ret = 0, ret2; + int region_num; + int ret = 0; /* Busy wait if it is flushing somewhere else */ while (!atomic_cas(&thread->arch.flushing, 0, 1)) { } - ret2 = dup_dynamic_regions(dyn_regions, max_region_num); - CHECKIF(ret2 < 0) { - ret = ret2; + thread->arch.region_num = 0; + + ret = dup_dynamic_regions(dyn_regions, max_region_num); + + if (ret < 0) { goto out; } - region_num = (uint8_t)ret2; + region_num = ret; +#if defined(CONFIG_USERSPACE) struct k_mem_domain *mem_domain = thread->mem_domain_info.mem_domain; if (mem_domain) { @@ -494,41 +671,61 @@ static int configure_dynamic_mpu_regions(struct k_thread *thread) if (partition->size == 0) { continue; } - LOG_DBG("set region 0x%lx 0x%lx", + LOG_DBG("set region 0x%lx 0x%lx\n", partition->start, partition->size); - ret2 = insert_region(dyn_regions, - region_num, - max_region_num, - partition->start, - partition->size, - &partition->attr); - CHECKIF(ret2 < 0) { - ret = ret2; + ret = insert_region(dyn_regions, + max_region_num, + partition->start, + partition->size, + &partition->attr); + + if (ret < 0) { goto out; } - region_num = (uint8_t)ret2; + region_num += ret; } } LOG_DBG("configure user thread %p's context", thread); if ((thread->base.user_options & K_USER) != 0) { /* K_USER thread stack needs a region */ - ret2 = insert_region(dyn_regions, - region_num, - max_region_num, - thread->stack_info.start, - thread->stack_info.size, - &K_MEM_PARTITION_P_RW_U_RW); - CHECKIF(ret2 < 0) { - ret = ret2; + ret = insert_region(dyn_regions, + max_region_num, + thread->stack_info.start, + thread->stack_info.size, + &K_MEM_PARTITION_P_RW_U_RW); + if (ret < 0) { goto out; } - region_num = (uint8_t)ret2; + region_num += ret; } +#endif - thread->arch.region_num = region_num; +#if defined(CONFIG_ARM64_STACK_PROTECTION) + uintptr_t guard_start; + + if (thread->arch.stack_limit != 0) { + guard_start = (uintptr_t)thread->arch.stack_limit - Z_ARM64_STACK_GUARD_SIZE; + ret = insert_region(dyn_regions, + max_region_num, + guard_start, + Z_ARM64_STACK_GUARD_SIZE, + NULL); + if (ret < 0) { + goto out; + } + region_num += ret; + } +#endif + + /* + * There is no need to check if region_num is overflow the uint8_t, + * because the insert_region make sure there is enough room to store a region, + * otherwise the insert_region will return a negtive error number + */ + thread->arch.region_num = (uint8_t)region_num; if (thread == _current) { ret = flush_dynamic_regions_to_mpu(dyn_regions, region_num); @@ -536,9 +733,11 @@ static int configure_dynamic_mpu_regions(struct k_thread *thread) out: atomic_clear(&thread->arch.flushing); - return ret; + return ret < 0 ? ret : 0; } +#endif /* defined(CONFIG_USERSPACE) || defined(CONFIG_HW_STACK_PROTECTION) */ +#if defined(CONFIG_USERSPACE) int arch_mem_domain_max_partitions_get(void) { int remaining_regions = get_num_regions() - static_regions_num + 1; @@ -619,7 +818,9 @@ int arch_mem_domain_thread_remove(struct k_thread *thread) return ret; } +#endif /* CONFIG_USERSPACE */ +#if defined(CONFIG_USERSPACE) || defined(CONFIG_ARM64_STACK_PROTECTION) void z_arm64_thread_mem_domains_init(struct k_thread *thread) { unsigned int key = arch_irq_lock(); @@ -630,18 +831,20 @@ void z_arm64_thread_mem_domains_init(struct k_thread *thread) void z_arm64_swap_mem_domains(struct k_thread *thread) { + int cpuid = arch_curr_cpu()->id; /* Busy wait if it is configuring somewhere else */ while (!atomic_cas(&thread->arch.flushing, 0, 1)) { } if (thread->arch.region_num == 0) { - (void)flush_dynamic_regions_to_mpu(sys_dyn_regions, sys_dyn_regions_num); + (void)flush_dynamic_regions_to_mpu(sys_dyn_regions[cpuid], + sys_dyn_regions_num[cpuid]); } else { - (void)flush_dynamic_regions_to_mpu(thread->arch.regions, thread->arch.region_num); + (void)flush_dynamic_regions_to_mpu(thread->arch.regions, + thread->arch.region_num); } atomic_clear(&thread->arch.flushing); } - -#endif /* CONFIG_USERSPACE */ +#endif diff --git a/arch/arm64/core/fatal.c b/arch/arm64/core/fatal.c index 8a36c50f506..1139a818e1f 100644 --- a/arch/arm64/core/fatal.c +++ b/arch/arm64/core/fatal.c @@ -18,6 +18,7 @@ #include #include #include +#include LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); @@ -233,6 +234,47 @@ static void esf_unwind(const z_arch_esf_t *esf) #endif /* CONFIG_EXCEPTION_DEBUG */ +#ifdef CONFIG_ARM64_STACK_PROTECTION +static bool z_arm64_stack_corruption_check(z_arch_esf_t *esf, uint64_t esr, uint64_t far) +{ + uint64_t sp, sp_limit, guard_start; + /* 0x25 means data abort from current EL */ + if (GET_ESR_EC(esr) == 0x25) { + sp_limit = arch_curr_cpu()->arch.current_stack_limit; + guard_start = sp_limit - Z_ARM64_STACK_GUARD_SIZE; + sp = arch_curr_cpu()->arch.corrupted_sp; + if ((sp != 0 && sp <= sp_limit) || (guard_start <= far && far <= sp_limit)) { +#ifdef CONFIG_FPU_SHARING + /* + * We are in exception stack, and now we are sure the stack does overflow, + * so flush the fpu context to its owner, and then set no fpu trap to avoid + * a new nested exception triggered by FPU accessing (var_args). + */ + z_arm64_flush_local_fpu(); + write_cpacr_el1(read_cpacr_el1() | CPACR_EL1_FPEN_NOTRAP); +#endif + arch_curr_cpu()->arch.corrupted_sp = 0UL; + LOG_ERR("STACK OVERFLOW FROM KERNEL, SP: 0x%llx OR FAR: 0x%llx INVALID," + " SP LIMIT: 0x%llx", sp, far, sp_limit); + return true; + } + } +#ifdef CONFIG_USERSPACE + else if ((_current->base.user_options & K_USER) != 0 && GET_ESR_EC(esr) == 0x24) { + sp_limit = (uint64_t)_current->stack_info.start; + guard_start = sp_limit - Z_ARM64_STACK_GUARD_SIZE; + sp = esf->sp; + if (sp <= sp_limit || (guard_start <= far && far <= sp_limit)) { + LOG_ERR("STACK OVERFLOW FROM USERSPACE, SP: 0x%llx OR FAR: 0x%llx INVALID," + " SP LIMIT: 0x%llx", sp, far, sp_limit); + return true; + } + } +#endif + return false; +} +#endif + static bool is_recoverable(z_arch_esf_t *esf, uint64_t esr, uint64_t far, uint64_t elr) { @@ -278,6 +320,12 @@ void z_arm64_fatal_error(unsigned int reason, z_arch_esf_t *esf) break; } +#ifdef CONFIG_ARM64_STACK_PROTECTION + if (z_arm64_stack_corruption_check(esf, esr, far)) { + reason = K_ERR_STACK_CHK_FAIL; + } +#endif + if (GET_EL(el) != MODE_EL0) { #ifdef CONFIG_EXCEPTION_DEBUG bool dump_far = false; @@ -292,8 +340,10 @@ void z_arm64_fatal_error(unsigned int reason, z_arch_esf_t *esf) LOG_ERR("TPIDRRO: 0x%016llx", read_tpidrro_el0()); #endif /* CONFIG_EXCEPTION_DEBUG */ - if (is_recoverable(esf, esr, far, elr)) + if (is_recoverable(esf, esr, far, elr) && + reason != K_ERR_STACK_CHK_FAIL) { return; + } } } diff --git a/arch/arm64/core/macro_priv.inc b/arch/arm64/core/macro_priv.inc index 616e705f47b..22cefe235fe 100644 --- a/arch/arm64/core/macro_priv.inc +++ b/arch/arm64/core/macro_priv.inc @@ -21,6 +21,27 @@ ubfx \xreg0, \xreg0, #0, #24 .endm +/* + * Get CPU logic id by looking up cpu_node_list + * returns + * xreg0: MPID + * xreg1: logic id (0 ~ CONFIG_MP_MAX_NUM_CPUS - 1) + * clobbers: xreg0, xreg1, xreg2, xreg3 + */ +.macro get_cpu_logic_id xreg0, xreg1, xreg2, xreg3 + get_cpu_id \xreg0 + ldr \xreg3, =cpu_node_list + mov \xreg1, 0 +1: ldr \xreg2, [\xreg3, \xreg1, lsl 3] + cmp \xreg2, \xreg0 + beq 2f + add \xreg1, \xreg1, 1 + cmp \xreg1, #CONFIG_MP_MAX_NUM_CPUS + bne 1b + b . +2: +.endm + /* * Get CPU pointer * Note: keep in sync with `arch_curr_cpu` in include/zephyr/arch/arm64/arch_inlines.h diff --git a/arch/arm64/core/mmu.c b/arch/arm64/core/mmu.c index 7d5670da0f2..2260d22c101 100644 --- a/arch/arm64/core/mmu.c +++ b/arch/arm64/core/mmu.c @@ -731,6 +731,14 @@ static inline void add_arm_mmu_region(struct arm_mmu_ptables *ptables, static inline void inv_dcache_after_map_helper(void *virt, size_t size, uint32_t attrs) { + /* + * DC IVAC instruction requires write access permission to the VA, + * otherwise it can generate a permission fault + */ + if ((attrs & MT_RW) != MT_RW) { + return; + } + if (MT_TYPE(attrs) == MT_NORMAL || MT_TYPE(attrs) == MT_NORMAL_WT) { sys_cache_data_invd_range(virt, size); } @@ -987,6 +995,7 @@ void arch_mem_map(void *virt, uintptr_t phys, size_t size, uint32_t flags) case K_MEM_CACHE_WB: case K_MEM_CACHE_WT: mem_flags = (mem_flags == K_MEM_CACHE_WB) ? MT_NORMAL : MT_NORMAL_WT; + mem_flags |= (flags & K_MEM_PERM_RW) ? MT_RW : 0; inv_dcache_after_map_helper(virt, size, mem_flags); default: break; diff --git a/arch/arm64/core/reset.S b/arch/arm64/core/reset.S index 387e82b341a..81f11e6f2c9 100644 --- a/arch/arm64/core/reset.S +++ b/arch/arm64/core/reset.S @@ -7,6 +7,7 @@ #include #include #include +#include #include "boot.h" #include "macro_priv.inc" @@ -120,38 +121,75 @@ resetwait: #if CONFIG_MP_MAX_NUM_CPUS > 1 + /* + * Deal with multi core booting simultaneously to race for being the primary core. + * Use voting lock[1] with reasonable but minimal requirements on the memory system + * to make sure only one core wins at last. + * + * [1] kernel.org/doc/html/next/arch/arm/vlocks.html + */ ldr x0, =arm64_cpu_boot_params - get_cpu_id x1 /* - * If the cores start up at the same time, we should atomically load and - * store the mpid into arm64_cpu_boot_params. + * Get the "logic" id defined by cpu_node_list statically for voting lock self-identify. + * It is worth noting that this is NOT the final logic id (arch_curr_cpu()->id) */ - ldaxr x2, [x0, #BOOT_PARAM_MPID_OFFSET] - cmp x2, #-1 - bne 1f - /* try to store x1 (mpid) */ - stlxr w3, x1, [x0] - /* If succeed, go to primary_core */ - cbz w3, primary_core + get_cpu_logic_id x1, x2, x3, x4 //x1: MPID, x2: logic id + + add x4, x0, #BOOT_PARAM_VOTING_OFFSET + + /* signal our desire to vote */ + mov w5, #1 + strb w5, [x4, x2] + ldr x3, [x0, #BOOT_PARAM_MPID_OFFSET] + cmn x3, #1 + beq 1f + + /* some core already won, release */ + strb wzr, [x4, x2] + b secondary_core + + /* suggest current core then release */ +1: str x1, [x0, #BOOT_PARAM_MPID_OFFSET] + strb wzr, [x4, x2] + dmb ish + + /* then wait until every core else is done voting */ + mov x5, #0 +2: ldrb w3, [x4, x5] + tst w3, #255 + /* wait */ + bne 2b + add x5, x5, #1 + cmp x5, #CONFIG_MP_MAX_NUM_CPUS + bne 2b + + + /* check if current core won */ + dmb ish + ldr x3, [x0, #BOOT_PARAM_MPID_OFFSET] + cmp x3, x1 + beq primary_core + /* fallthrough secondary */ /* loop until our turn comes */ -1: dmb ld +secondary_core: + dmb ish ldr x2, [x0, #BOOT_PARAM_MPID_OFFSET] cmp x1, x2 - bne 1b + bne secondary_core /* we can now load our stack pointer value and move on */ ldr x24, [x0, #BOOT_PARAM_SP_OFFSET] ldr x25, =z_arm64_secondary_prep_c - b 2f + b boot primary_core: #endif /* load primary stack and entry point */ - ldr x24, =(z_interrupt_stacks + CONFIG_ISR_STACK_SIZE) + ldr x24, =(z_interrupt_stacks + __z_interrupt_stack_SIZEOF) ldr x25, =z_arm64_prep_c -2: +boot: /* Prepare for calling C code */ bl __reset_prep_c diff --git a/arch/arm64/core/reset.c b/arch/arm64/core/reset.c index bd78555de54..f96783318f4 100644 --- a/arch/arm64/core/reset.c +++ b/arch/arm64/core/reset.c @@ -125,6 +125,12 @@ void z_arm64_el2_init(void) write_sctlr_el2(reg); reg = read_hcr_el2(); + /* when EL2 is enable in current security status: + * Clear TGE bit: All exceptions that would not be routed to EL2; + * Clear AMO bit: Physical SError interrupts are not taken to EL2 and EL3. + * Clear IMO bit: Physical IRQ interrupts are not taken to EL2 and EL3. + */ + reg &= ~(HCR_IMO_BIT | HCR_AMO_BIT | HCR_TGE_BIT); reg |= HCR_RW_BIT; /* EL1 Execution state is AArch64 */ write_hcr_el2(reg); diff --git a/arch/arm64/core/smp.c b/arch/arm64/core/smp.c index 3fdb1b333d5..e67032eb2a4 100644 --- a/arch/arm64/core/smp.c +++ b/arch/arm64/core/smp.c @@ -35,6 +35,7 @@ struct boot_params { uint64_t mpid; char *sp; + uint8_t voting[CONFIG_MP_MAX_NUM_CPUS]; arch_cpustart_t fn; void *arg; int cpu_num; @@ -43,12 +44,13 @@ struct boot_params { /* Offsets used in reset.S */ BUILD_ASSERT(offsetof(struct boot_params, mpid) == BOOT_PARAM_MPID_OFFSET); BUILD_ASSERT(offsetof(struct boot_params, sp) == BOOT_PARAM_SP_OFFSET); +BUILD_ASSERT(offsetof(struct boot_params, voting) == BOOT_PARAM_VOTING_OFFSET); volatile struct boot_params __aligned(L1_CACHE_BYTES) arm64_cpu_boot_params = { .mpid = -1, }; -static const uint64_t cpu_node_list[] = { +const uint64_t cpu_node_list[] = { DT_FOREACH_CHILD_STATUS_OKAY_SEP(DT_PATH(cpus), DT_REG_ADDR, (,)) }; @@ -141,12 +143,13 @@ void z_arm64_secondary_start(void) /* Initialize tpidrro_el0 with our struct _cpu instance address */ write_tpidrro_el0((uintptr_t)&_kernel.cpus[cpu_num]); + + z_arm64_mm_init(false); + #ifdef CONFIG_ARM64_SAFE_EXCEPTION_STACK z_arm64_safe_exception_stack_init(); #endif - z_arm64_mm_init(false); - #ifdef CONFIG_SMP arm_gic_secondary_init(); diff --git a/arch/arm64/core/switch.S b/arch/arm64/core/switch.S index 142103dee2f..333b8f0b21e 100644 --- a/arch/arm64/core/switch.S +++ b/arch/arm64/core/switch.S @@ -115,7 +115,7 @@ SECTION_FUNC(TEXT, z_arm64_context_switch) str x2, [x4, #_cpu_offset_to_current_stack_limit] #endif -#ifdef CONFIG_USERSPACE +#if defined(CONFIG_USERSPACE) || defined(CONFIG_ARM64_STACK_PROTECTION) str lr, [sp, #-16]! bl z_arm64_swap_mem_domains ldr lr, [sp], #16 diff --git a/arch/arm64/core/thread.c b/arch/arm64/core/thread.c index 118bee4397a..a0269501c19 100644 --- a/arch/arm64/core/thread.c +++ b/arch/arm64/core/thread.c @@ -13,7 +13,6 @@ #include #include -#include #include /* @@ -29,19 +28,35 @@ * normal execution. When at exception is taken or a syscall is called the * stack pointer switches to SP_EL1 and the execution starts using the * privileged portion of the user stack without touching SP_EL0. This portion - * is marked as not user accessible in the MMU. + * is marked as not user accessible in the MMU/MPU. + * + * - a stack guard region will be added bellow the kernel stack when + * ARM64_STACK_PROTECTION is enabled. In this case, SP_EL0 will always point + * to the safe exception stack in the kernel space. For the kernel thread, + * SP_EL0 will not change always pointing to safe exception stack. For the + * userspace thread, SP_EL0 will switch from the user stack to the safe + * exception stack when entering the EL1 mode, and restore to the user stack + * when backing to userspace (EL0). * * Kernel threads: * + * High memory addresses + * * +---------------+ <- stack_ptr * E | ESF | * L |<<<<<<<<<<<<<<<| <- SP_EL1 * 1 | | - * +---------------+ - + * +---------------+ <- stack limit + * | Stack guard | } Z_ARM64_STACK_GUARD_SIZE (protected by MMU/MPU) + * +---------------+ <- stack_obj + * + * Low Memory addresses + * * * User threads: * + * High memory addresses + * * +---------------+ <- stack_ptr * E | | * L |<<<<<<<<<<<<<<<| <- SP_EL0 @@ -50,7 +65,11 @@ * E | ESF | | Privileged portion of the stack * L +>>>>>>>>>>>>>>>+ <- SP_EL1 |_ used during exceptions and syscalls * 1 | | | of size ARCH_THREAD_STACK_RESERVED - * +---------------+ <- stack_obj..| + * +---------------+ <- stack limit| + * | Stack guard | } Z_ARM64_STACK_GUARD_SIZE (protected by MMU/MPU) + * +---------------+ <- stack_obj + * + * Low Memory addresses * * When a kernel thread switches to user mode the SP_EL0 and SP_EL1 * values are reset accordingly in arch_user_mode_enter(). @@ -70,6 +89,12 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, extern void z_arm64_exit_exc(void); z_arch_esf_t *pInitCtx; + /* + * Clean the thread->arch to avoid unexpected behavior because the + * thread->arch might be dirty + */ + memset(&thread->arch, 0, sizeof(thread->arch)); + /* * The ESF is now hosted at the top of the stack. For user threads this * is also fine because at this stage they are still running in EL1. @@ -101,9 +126,6 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, pInitCtx->elr = (uint64_t)z_thread_entry; } -#if defined(CONFIG_ARM_MPU) - atomic_clear(&thread->arch.flushing); -#endif #else pInitCtx->elr = (uint64_t)z_thread_entry; #endif @@ -123,6 +145,10 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, thread->callee_saved.lr = (uint64_t)z_arm64_exit_exc; thread->switch_handle = thread; +#if defined(CONFIG_ARM64_STACK_PROTECTION) + thread->arch.stack_limit = (uint64_t)stack + Z_ARM64_STACK_GUARD_SIZE; + z_arm64_thread_mem_domains_init(thread); +#endif } #ifdef CONFIG_USERSPACE diff --git a/arch/arm64/core/xen/Kconfig b/arch/arm64/core/xen/Kconfig new file mode 100644 index 00000000000..a4bb0be77e9 --- /dev/null +++ b/arch/arm64/core/xen/Kconfig @@ -0,0 +1,27 @@ +# Xen hypervisor configuration options + +# Copyright (c) 2023 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +config XEN + bool + default y + depends on ARMV8_A + depends on DT_HAS_XEN_XEN_ENABLED + help + Enables support of Xen hypervisor on arm64 platform. Get enabled + when board device tree contains "hypervisor" node with "xen,xen" + compatible enabled. + +config XEN_DOM0 + bool "Zephyr as Xen Domain 0" + depends on XEN + help + Built binary will be used as Xen privileged domain (Domain 0). + +config XEN_DOM0LESS + bool "Zephyr for Xen Dom0less setup" + depends on XEN && !XEN_DOM0 + help + Configures Zephyr as DomU, that can be started on Dom0less + setup. diff --git a/arch/arm64/core/xen/hypercall.S b/arch/arm64/core/xen/hypercall.S index 429b0a42286..063538bae90 100644 --- a/arch/arm64/core/xen/hypercall.S +++ b/arch/arm64/core/xen/hypercall.S @@ -1,7 +1,6 @@ +/* SPDX-License-Identifier: Apache-2.0 */ /* - * Copyright (c) 2021 EPAM Systems - * - * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2021-2023 EPAM Systems */ #include @@ -24,3 +23,7 @@ HYPERCALL(sched_op); HYPERCALL(event_channel_op); HYPERCALL(hvm_op); HYPERCALL(memory_op); + +#ifdef CONFIG_XEN_DOM0 +HYPERCALL(domctl); +#endif diff --git a/arch/common/CMakeLists.txt b/arch/common/CMakeLists.txt index 80102d70331..1a89ba9c13a 100644 --- a/arch/common/CMakeLists.txt +++ b/arch/common/CMakeLists.txt @@ -2,14 +2,28 @@ zephyr_library() +zephyr_library_include_directories(include) + # Library may be empty due to kconfigs zephyr_library_property(ALLOW_EMPTY TRUE) +if(CONFIG_GEN_ISR_TABLES) + zephyr_library_sources( + sw_isr_common.c + ) + zephyr_library_sources_ifdef( + CONFIG_DYNAMIC_INTERRUPTS + dynamic_isr.c + ) +endif() + zephyr_library_sources_ifdef( - CONFIG_GEN_ISR_TABLES - sw_isr_common.c + CONFIG_MULTI_LEVEL_INTERRUPTS + multilevel_irq.c ) +zephyr_library_sources_ifdef(CONFIG_SHARED_INTERRUPTS shared_irq.c) + if(NOT CONFIG_ARCH_HAS_TIMING_FUNCTIONS AND NOT CONFIG_SOC_HAS_TIMING_FUNCTIONS AND NOT CONFIG_BOARD_HAS_TIMING_FUNCTIONS) @@ -56,6 +70,10 @@ if (DEFINED CONFIG_ARM OR DEFINED CONFIG_X86 OR DEFINED CONFIG_ARM64 # Exclamation mark is printable character with lowest number in ASCII table. # We are sure that this file will be included as a first. zephyr_linker_sources(ROM_START SORT_KEY ! rom_start_address.ld) + # Some linkers fill unspecified region with pattern other than 0x00. Include + # fill_with_zeros.ld file which forces the linker to use 0x00 pattern. Please + # note that the pattern will affect empty spaces created after FILL(0x00). + zephyr_linker_sources(ROM_START SORT_KEY $ fill_with_zeros.ld) zephyr_linker_sources(ROM_START SORT_KEY 0x0 rom_start_offset.ld) # Handled in ld.cmake endif() diff --git a/arch/common/dynamic_isr.c b/arch/common/dynamic_isr.c new file mode 100644 index 00000000000..9f56977f259 --- /dev/null +++ b/arch/common/dynamic_isr.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sw_isr_common.h" +#include +#include +#include + +void __weak z_isr_install(unsigned int irq, void (*routine)(const void *), + const void *param) +{ + unsigned int table_idx; + + /* + * Do not assert on the IRQ enable status for ARM GIC since the SGI + * type interrupts are always enabled and attempting to install an ISR + * for them will cause the assertion to fail. + */ +#ifndef CONFIG_GIC + __ASSERT(!irq_is_enabled(irq), "IRQ %d is enabled", irq); +#endif /* !CONFIG_GIC */ + + table_idx = z_get_sw_isr_table_idx(irq); + + /* If dynamic IRQs are enabled, then the _sw_isr_table is in RAM and + * can be modified + */ + _sw_isr_table[table_idx].arg = param; + _sw_isr_table[table_idx].isr = routine; +} + +/* Some architectures don't/can't interpret flags or priority and have + * no more processing to do than this. Provide a generic fallback. + */ +int __weak arch_irq_connect_dynamic(unsigned int irq, + unsigned int priority, + void (*routine)(const void *), + const void *parameter, + uint32_t flags) +{ + ARG_UNUSED(flags); + ARG_UNUSED(priority); + + z_isr_install(irq, routine, parameter); + return irq; +} diff --git a/arch/common/fill_with_zeros.ld b/arch/common/fill_with_zeros.ld new file mode 100644 index 00000000000..b93a5ffead0 --- /dev/null +++ b/arch/common/fill_with_zeros.ld @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2023, Google, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * LLVM LLD fills empty spaces (created using ALIGN() or moving the location + * counter) in executable segments with TrapInstr pattern, e.g. for ARM the + * TrapInstr pattern is 0xd4d4d4d4. GNU LD fills empty spaces with 0x00 + * pattern. + * + * We may want to have some section (e.g. rom_start) filled with 0x00, + * e.g. because MCU can interpret the pattern as a configuration data. + */ +FILL(0x00); diff --git a/arch/common/include/sw_isr_common.h b/arch/common/include/sw_isr_common.h new file mode 100644 index 00000000000..223c9ba2442 --- /dev/null +++ b/arch/common/include/sw_isr_common.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Private header for the software-managed ISR table's functions + */ + +#ifndef ZEPHYR_ARCH_COMMON_INCLUDE_SW_ISR_COMMON_H_ +#define ZEPHYR_ARCH_COMMON_INCLUDE_SW_ISR_COMMON_H_ + +#if !defined(_ASMLANGUAGE) +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Helper function used to compute the index in _sw_isr_table + * based on passed IRQ. + * + * @param irq IRQ number in its zephyr format + * + * @return corresponding index in _sw_isr_table + */ +unsigned int z_get_sw_isr_table_idx(unsigned int irq); + +/** + * @brief Helper function used to get the parent interrupt controller device based on passed IRQ. + * + * @param irq IRQ number in its zephyr format + * + * @return corresponding interrupt controller device in _sw_isr_table + */ +const struct device *z_get_sw_isr_device_from_irq(unsigned int irq); + +/** + * @brief Helper function used to get the IRQN of the passed in parent interrupt + * controller device. + * + * @param dev parent interrupt controller device + * + * @return IRQN of the interrupt controller + */ +unsigned int z_get_sw_isr_irq_from_device(const struct device *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_ARCH_COMMON_INCLUDE_SW_ISR_COMMON_H_ */ diff --git a/arch/common/isr_tables.c b/arch/common/isr_tables.c index a22776f8edb..0311f81f252 100644 --- a/arch/common/isr_tables.c +++ b/arch/common/isr_tables.c @@ -81,3 +81,8 @@ struct _isr_table_entry __sw_isr_table _sw_isr_table[IRQ_TABLE_SIZE] = { (void *)&z_irq_spurious}, }; #endif + +#ifdef CONFIG_SHARED_INTERRUPTS +struct z_shared_isr_table_entry __shared_sw_isr_table z_shared_sw_isr_table[IRQ_TABLE_SIZE] = { +}; +#endif diff --git a/arch/common/multilevel_irq.c b/arch/common/multilevel_irq.c new file mode 100644 index 00000000000..96f3ab0801f --- /dev/null +++ b/arch/common/multilevel_irq.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2018 Intel Corporation. + * Copyright (c) 2023 Meta. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +/* + * Insert code if the node_id is an interrupt controller + */ +#define Z_IF_DT_IS_INTC(node_id, code) \ + IF_ENABLED(DT_NODE_HAS_PROP(node_id, interrupt_controller), (code)) + +/* + * Expands to node_id if its IRQN is equal to `irq`, nothing otherwise + * This only works for `irq` between 0 & 4095, see `IS_EQ` + */ +#define Z_IF_DT_INTC_IRQN_EQ(node_id, irq) IF_ENABLED(IS_EQ(DT_IRQ(node_id, irq), irq), (node_id)) + +/* + * Expands to node_id if it's an interrupt controller & its IRQN is `irq`, or nothing otherwise + */ +#define Z_DT_INTC_GET_IRQN(node_id, irq) \ + Z_IF_DT_IS_INTC(node_id, Z_IF_DT_INTC_IRQN_EQ(node_id, irq)) + +/** + * Loop through child of "/soc" and get root interrupt controllers with `irq` as IRQN, + * this assumes only one device has the IRQN + * @param irq irq number + * @return node_id(s) that has the `irq` number, or empty if none of them has the `irq` + */ +#define INTC_DT_IRQN_GET(irq) \ + DT_FOREACH_CHILD_STATUS_OKAY_VARGS(DT_PATH(soc), Z_DT_INTC_GET_IRQN, irq) + +/* If can't find any matching interrupt controller, fills with `NULL` */ +#define INTC_DEVICE_INIT(node_id) .dev = DEVICE_DT_GET_OR_NULL(node_id), + +#define INIT_IRQ_PARENT_OFFSET(d, i, o) { \ + INTC_DEVICE_INIT(d) \ + .irq = i, \ + .offset = o, \ +} + +#define IRQ_INDEX_TO_OFFSET(i, base) (base + i * CONFIG_MAX_IRQ_PER_AGGREGATOR) + +#define CAT_2ND_LVL_LIST(i, base) \ + INIT_IRQ_PARENT_OFFSET(INTC_DT_IRQN_GET(CONFIG_2ND_LVL_INTR_0##i##_OFFSET), \ + CONFIG_2ND_LVL_INTR_0##i##_OFFSET, IRQ_INDEX_TO_OFFSET(i, base)) +const struct _irq_parent_entry _lvl2_irq_list[CONFIG_NUM_2ND_LEVEL_AGGREGATORS] + = { LISTIFY(CONFIG_NUM_2ND_LEVEL_AGGREGATORS, CAT_2ND_LVL_LIST, (,), + CONFIG_2ND_LVL_ISR_TBL_OFFSET) }; + +#define CAT_3RD_LVL_LIST(i, base) \ + INIT_IRQ_PARENT_OFFSET(INTC_DT_IRQN_GET(CONFIG_3RD_LVL_INTR_0##i##_OFFSET), \ + CONFIG_3RD_LVL_INTR_0##i##_OFFSET, IRQ_INDEX_TO_OFFSET(i, base)) + +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS + +const struct _irq_parent_entry _lvl3_irq_list[CONFIG_NUM_3RD_LEVEL_AGGREGATORS] + = { LISTIFY(CONFIG_NUM_3RD_LEVEL_AGGREGATORS, CAT_3RD_LVL_LIST, (,), + CONFIG_3RD_LVL_ISR_TBL_OFFSET) }; + +#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ + +static const struct _irq_parent_entry *get_parent_entry(unsigned int parent_irq, + const struct _irq_parent_entry list[], + unsigned int length) +{ + unsigned int i; + const struct _irq_parent_entry *entry = NULL; + + for (i = 0U; i < length; ++i) { + if (list[i].irq == parent_irq) { + entry = &list[i]; + break; + } + } + + __ASSERT(i != length, "Invalid argument: %i", parent_irq); + + return entry; +} + +const struct device *z_get_sw_isr_device_from_irq(unsigned int irq) +{ + const struct device *dev = NULL; + unsigned int level, parent_irq; + const struct _irq_parent_entry *entry = NULL; + + level = irq_get_level(irq); + + if (level == 2U) { + parent_irq = irq_parent_level_2(irq); + entry = get_parent_entry(parent_irq, + _lvl2_irq_list, + CONFIG_NUM_2ND_LEVEL_AGGREGATORS); + } +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS + else if (level == 3U) { + parent_irq = irq_parent_level_3(irq); + entry = get_parent_entry(parent_irq, + _lvl3_irq_list, + CONFIG_NUM_3RD_LEVEL_AGGREGATORS); + } +#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ + dev = entry != NULL ? entry->dev : NULL; + + return dev; +} + +unsigned int z_get_sw_isr_irq_from_device(const struct device *dev) +{ + for (size_t i = 0U; i < CONFIG_NUM_2ND_LEVEL_AGGREGATORS; ++i) { + if (_lvl2_irq_list[i].dev == dev) { + return _lvl2_irq_list[i].irq; + } + } + +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS + for (size_t i = 0U; i < CONFIG_NUM_3RD_LEVEL_AGGREGATORS; ++i) { + if (_lvl3_irq_list[i].dev == dev) { + return _lvl3_irq_list[i].irq; + } + } +#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ + + return 0; +} + +unsigned int z_get_sw_isr_table_idx(unsigned int irq) +{ + unsigned int table_idx; + unsigned int level, parent_irq, parent_offset; + const struct _irq_parent_entry *entry = NULL; + + level = irq_get_level(irq); + + if (level == 2U) { + parent_irq = irq_parent_level_2(irq); + entry = get_parent_entry(parent_irq, + _lvl2_irq_list, + CONFIG_NUM_2ND_LEVEL_AGGREGATORS); + parent_offset = entry != NULL ? entry->offset : 0U; + table_idx = parent_offset + irq_from_level_2(irq); + } +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS + else if (level == 3U) { + parent_irq = irq_parent_level_3(irq); + entry = get_parent_entry(parent_irq, + _lvl3_irq_list, + CONFIG_NUM_3RD_LEVEL_AGGREGATORS); + parent_offset = entry != NULL ? entry->offset : 0U; + table_idx = parent_offset + irq_from_level_3(irq); + } +#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ + else { + table_idx = irq; + } + + table_idx -= CONFIG_GEN_IRQ_START_VECTOR; + + return table_idx; +} diff --git a/arch/common/shared_irq.c b/arch/common/shared_irq.c new file mode 100644 index 00000000000..68641cb2bb0 --- /dev/null +++ b/arch/common/shared_irq.c @@ -0,0 +1,211 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sw_isr_common.h" + +#include +#include + +/* an interrupt line can be considered shared only if there's + * at least 2 clients using it. As such, enforce the fact that + * the maximum number of allowed clients should be at least 2. + */ +BUILD_ASSERT(CONFIG_SHARED_IRQ_MAX_NUM_CLIENTS >= 2, + "maximum number of clients should be at least 2"); + +void z_shared_isr(const void *data) +{ + size_t i; + const struct z_shared_isr_table_entry *entry; + const struct z_shared_isr_client *client; + + entry = data; + + for (i = 0; i < entry->client_num; i++) { + client = &entry->clients[i]; + + if (client->isr) { + client->isr(client->arg); + } + } +} + +#ifdef CONFIG_DYNAMIC_INTERRUPTS + +static struct k_spinlock lock; + +void z_isr_install(unsigned int irq, void (*routine)(const void *), + const void *param) +{ + struct z_shared_isr_table_entry *shared_entry; + struct _isr_table_entry *entry; + struct z_shared_isr_client *client; + unsigned int table_idx; + int i; + k_spinlock_key_t key; + + table_idx = z_get_sw_isr_table_idx(irq); + + /* check for out of bounds table index */ + if (table_idx >= CONFIG_NUM_IRQS) { + return; + } + + shared_entry = &z_shared_sw_isr_table[table_idx]; + entry = &_sw_isr_table[table_idx]; + + key = k_spin_lock(&lock); + + /* have we reached the client limit? */ + __ASSERT(shared_entry->client_num < CONFIG_SHARED_IRQ_MAX_NUM_CLIENTS, + "reached maximum number of clients"); + + if (entry->isr == z_irq_spurious) { + /* this is the first time a ISR/arg pair is registered + * for INTID => no need to share it. + */ + entry->isr = routine; + entry->arg = param; + + k_spin_unlock(&lock, key); + + return; + } else if (entry->isr != z_shared_isr) { + /* INTID is being used by another ISR/arg pair. + * Push back the ISR/arg pair registered in _sw_isr_table + * to the list of clients and hijack the pair stored in + * _sw_isr_table with our own z_shared_isr/shared_entry pair. + */ + shared_entry->clients[shared_entry->client_num].isr = entry->isr; + shared_entry->clients[shared_entry->client_num].arg = entry->arg; + + shared_entry->client_num++; + + entry->isr = z_shared_isr; + entry->arg = shared_entry; + } + + /* don't register the same ISR/arg pair multiple times */ + for (i = 0; i < shared_entry->client_num; i++) { + client = &shared_entry->clients[i]; + + __ASSERT(client->isr != routine && client->arg != param, + "trying to register duplicate ISR/arg pair"); + } + + shared_entry->clients[shared_entry->client_num].isr = routine; + shared_entry->clients[shared_entry->client_num].arg = param; + shared_entry->client_num++; + + k_spin_unlock(&lock, key); +} + +static void swap_client_data(struct z_shared_isr_client *a, + struct z_shared_isr_client *b) +{ + struct z_shared_isr_client tmp; + + tmp.arg = a->arg; + tmp.isr = a->isr; + + a->arg = b->arg; + a->isr = b->isr; + + b->arg = tmp.arg; + b->isr = tmp.isr; +} + +static void shared_irq_remove_client(struct z_shared_isr_table_entry *shared_entry, + int client_idx, unsigned int table_idx) +{ + int i; + + shared_entry->clients[client_idx].isr = NULL; + shared_entry->clients[client_idx].arg = NULL; + + /* push back the removed client to the end of the client list */ + for (i = client_idx; i <= (int)shared_entry->client_num - 2; i++) { + swap_client_data(&shared_entry->clients[i], + &shared_entry->clients[i + 1]); + } + + shared_entry->client_num--; + + /* "unshare" interrupt if there will be a single client left */ + if (shared_entry->client_num == 1) { + _sw_isr_table[table_idx].isr = shared_entry->clients[0].isr; + _sw_isr_table[table_idx].arg = shared_entry->clients[0].arg; + + shared_entry->clients[0].isr = NULL; + shared_entry->clients[0].arg = NULL; + + shared_entry->client_num--; + } +} + +int __weak arch_irq_disconnect_dynamic(unsigned int irq, unsigned int priority, + void (*routine)(const void *parameter), + const void *parameter, uint32_t flags) +{ + ARG_UNUSED(priority); + ARG_UNUSED(flags); + + return z_isr_uninstall(irq, routine, parameter); +} + +int z_isr_uninstall(unsigned int irq, + void (*routine)(const void *), + const void *parameter) +{ + struct z_shared_isr_table_entry *shared_entry; + struct _isr_table_entry *entry; + struct z_shared_isr_client *client; + unsigned int table_idx; + size_t i; + k_spinlock_key_t key; + + table_idx = z_get_sw_isr_table_idx(irq); + + /* check for out of bounds table index */ + if (table_idx >= CONFIG_NUM_IRQS) { + return -EINVAL; + } + + shared_entry = &z_shared_sw_isr_table[table_idx]; + entry = &_sw_isr_table[table_idx]; + + key = k_spin_lock(&lock); + + /* note: it's important that we remove the ISR/arg pair even if + * the IRQ line is not being shared because z_isr_install() will + * not overwrite it unless the _sw_isr_table entry for the given + * IRQ line contains the default pair which is z_irq_spurious/NULL. + */ + if (!shared_entry->client_num) { + if (entry->isr == routine && entry->arg == parameter) { + entry->isr = z_irq_spurious; + entry->arg = NULL; + } + + goto out_unlock; + } + + for (i = 0; i < shared_entry->client_num; i++) { + client = &shared_entry->clients[i]; + + if (client->isr == routine && client->arg == parameter) { + /* note: this is the only match we're going to get */ + shared_irq_remove_client(shared_entry, i, table_idx); + goto out_unlock; + } + } + +out_unlock: + k_spin_unlock(&lock, key); + return 0; +} + +#endif /* CONFIG_DYNAMIC_INTERRUPTS */ diff --git a/arch/common/sw_isr_common.c b/arch/common/sw_isr_common.c index 538c03603f2..5efdeb89a67 100644 --- a/arch/common/sw_isr_common.c +++ b/arch/common/sw_isr_common.c @@ -4,140 +4,16 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "sw_isr_common.h" #include -#include #include #include + /* * Common code for arches that use software ISR tables (CONFIG_GEN_ISR_TABLES) */ -#ifdef CONFIG_DYNAMIC_INTERRUPTS - -#ifdef CONFIG_MULTI_LEVEL_INTERRUPTS - -struct irq_parent_offset { - unsigned int irq; - unsigned int offset; -}; - -#define INIT_IRQ_PARENT_OFFSET(i, o) { \ - .irq = i, \ - .offset = o, \ -} - -#define IRQ_INDEX_TO_OFFSET(i, base) (base + i * CONFIG_MAX_IRQ_PER_AGGREGATOR) - -#ifdef CONFIG_2ND_LEVEL_INTERRUPTS - -#define CAT_2ND_LVL_LIST(i, base) \ - INIT_IRQ_PARENT_OFFSET(CONFIG_2ND_LVL_INTR_0##i##_OFFSET, \ - IRQ_INDEX_TO_OFFSET(i, base)) -static struct irq_parent_offset lvl2_irq_list[CONFIG_NUM_2ND_LEVEL_AGGREGATORS] - = { LISTIFY(CONFIG_NUM_2ND_LEVEL_AGGREGATORS, CAT_2ND_LVL_LIST, (,), - CONFIG_2ND_LVL_ISR_TBL_OFFSET) }; - -#endif/* CONFIG_2ND_LEVEL_INTERRUPTS */ - -#ifdef CONFIG_3RD_LEVEL_INTERRUPTS - -#define CAT_3RD_LVL_LIST(i, base) \ - INIT_IRQ_PARENT_OFFSET(CONFIG_3RD_LVL_INTR_0##i##_OFFSET, \ - IRQ_INDEX_TO_OFFSET(i, base)) -static struct irq_parent_offset lvl3_irq_list[CONFIG_NUM_3RD_LEVEL_AGGREGATORS] - = { LISTIFY(CONFIG_NUM_3RD_LEVEL_AGGREGATORS, CAT_3RD_LVL_LIST, (,), - CONFIG_3RD_LVL_ISR_TBL_OFFSET) }; - -#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ - -unsigned int get_parent_offset(unsigned int parent_irq, - struct irq_parent_offset list[], - unsigned int length) -{ - unsigned int i; - unsigned int offset = 0U; - - for (i = 0U; i < length; ++i) { - if (list[i].irq == parent_irq) { - offset = list[i].offset; - break; - } - } - - __ASSERT(i != length, "Invalid argument: %i", parent_irq); - - return offset; -} - -#endif /* CONFIG_MULTI_LEVEL_INTERRUPTS */ - -void z_isr_install(unsigned int irq, void (*routine)(const void *), - const void *param) -{ - unsigned int table_idx; - - /* - * Do not assert on the IRQ enable status for ARM GIC since the SGI - * type interrupts are always enabled and attempting to install an ISR - * for them will cause the assertion to fail. - */ -#ifndef CONFIG_GIC - __ASSERT(!irq_is_enabled(irq), "IRQ %d is enabled", irq); -#endif /* !CONFIG_GIC */ - -#ifdef CONFIG_MULTI_LEVEL_INTERRUPTS - unsigned int level; - unsigned int parent_irq; - unsigned int parent_offset; - - level = irq_get_level(irq); - - if (level == 2U) { - parent_irq = irq_parent_level_2(irq); - parent_offset = get_parent_offset(parent_irq, - lvl2_irq_list, - CONFIG_NUM_2ND_LEVEL_AGGREGATORS); - table_idx = parent_offset + irq_from_level_2(irq); - } -#ifdef CONFIG_3RD_LEVEL_INTERRUPTS - else if (level == 3U) { - parent_irq = irq_parent_level_3(irq); - parent_offset = get_parent_offset(parent_irq, - lvl3_irq_list, - CONFIG_NUM_3RD_LEVEL_AGGREGATORS); - table_idx = parent_offset + irq_from_level_3(irq); - } -#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ - else { - table_idx = irq; - } - - table_idx -= CONFIG_GEN_IRQ_START_VECTOR; -#else - table_idx = irq - CONFIG_GEN_IRQ_START_VECTOR; -#endif /* CONFIG_MULTI_LEVEL_INTERRUPTS */ - - /* If dynamic IRQs are enabled, then the _sw_isr_table is in RAM and - * can be modified - */ - _sw_isr_table[table_idx].arg = param; - _sw_isr_table[table_idx].isr = routine; -} - -/* Some architectures don't/can't interpret flags or priority and have - * no more processing to do than this. Provide a generic fallback. - */ -int __weak arch_irq_connect_dynamic(unsigned int irq, - unsigned int priority, - void (*routine)(const void *), - const void *parameter, - uint32_t flags) +unsigned int __weak z_get_sw_isr_table_idx(unsigned int irq) { - ARG_UNUSED(flags); - ARG_UNUSED(priority); - - z_isr_install(irq, routine, parameter); - return irq; + return irq - CONFIG_GEN_IRQ_START_VECTOR; } - -#endif /* CONFIG_DYNAMIC_INTERRUPTS */ diff --git a/arch/posix/CMakeLists.txt b/arch/posix/CMakeLists.txt index 86cf051ccde..1573ef82ea1 100644 --- a/arch/posix/CMakeLists.txt +++ b/arch/posix/CMakeLists.txt @@ -94,12 +94,12 @@ elseif (CONFIG_NATIVE_LIBRARY) # Do not use the C library from this compiler/host, # but still use the basic compiler headers - # -fno-builtin to avoid the compiler using builtin replacements for std library functions + # no_builtin to avoid the compiler using builtin replacements for std library functions zephyr_compile_options( -nostdinc -isystem ${COMPILER_OWN_INCLUDE_PATH} $ - -fno-builtin + $ ) endif() endif() diff --git a/arch/posix/core/nsi_compat/nsi_compat.c b/arch/posix/core/nsi_compat/nsi_compat.c index eccd2643295..cd338ca1e4f 100644 --- a/arch/posix/core/nsi_compat/nsi_compat.c +++ b/arch/posix/core/nsi_compat/nsi_compat.c @@ -12,7 +12,7 @@ * the migration towards the Native simulator. */ -#include "zephyr/arch/posix/posix_trace.h" +#include void nsi_print_error_and_exit(const char *format, ...) { diff --git a/arch/posix/core/thread.c b/arch/posix/core/thread.c index a1bcecb766d..e1ebc6fbc80 100644 --- a/arch/posix/core/thread.c +++ b/arch/posix/core/thread.c @@ -16,7 +16,6 @@ #include #include #include -#include #include "posix_core.h" #include diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index c008d4184a0..a1cefcbdf43 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -323,6 +323,15 @@ config CMSIS_V2_THREAD_MAX_STACK_SIZE config ARCH_IRQ_VECTOR_TABLE_ALIGN default 256 +config RISCV_TRAP_HANDLER_ALIGNMENT + int "Alignment of RISC-V trap handler in bytes" + default 4 + help + This value configures the alignment of RISC-V trap handling + code. The requirement for a particular alignment arises from + the format of MTVEC register which is RISC-V platform-specific. + The minimum alignment is 4 bytes according to the Spec. + config GEN_IRQ_VECTOR_TABLE select RISCV_VECTORED_MODE if SOC_FAMILY_RISCV_PRIVILEGED diff --git a/arch/riscv/core/irq_manage.c b/arch/riscv/core/irq_manage.c index 88fafd34904..e0ef1374bf1 100644 --- a/arch/riscv/core/irq_manage.c +++ b/arch/riscv/core/irq_manage.c @@ -8,6 +8,7 @@ #include #include #include +#include LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); @@ -24,8 +25,10 @@ FUNC_NORETURN void z_irq_spurious(const void *unused) LOG_ERR("Spurious interrupt detected! IRQ: %ld", mcause); #if defined(CONFIG_RISCV_HAS_PLIC) if (mcause == RISCV_MACHINE_EXT_IRQ) { - LOG_ERR("PLIC interrupt line causing the IRQ: %d", - riscv_plic_get_irq()); + unsigned int save_irq = riscv_plic_get_irq(); + const struct device *save_dev = riscv_plic_get_dev(); + + LOG_ERR("PLIC interrupt line causing the IRQ: %d (%p)", save_irq, save_dev); } #endif z_riscv_fatal_error(K_ERR_SPURIOUS_IRQ, NULL); @@ -42,8 +45,6 @@ int arch_irq_connect_dynamic(unsigned int irq, unsigned int priority, #if defined(CONFIG_RISCV_HAS_PLIC) if (irq_get_level(irq) == 2) { - irq = irq_from_level_2(irq); - riscv_plic_set_priority(irq, priority); } #else diff --git a/arch/riscv/core/isr.S b/arch/riscv/core/isr.S index 75e3ef2e02d..c36679ae6db 100644 --- a/arch/riscv/core/isr.S +++ b/arch/riscv/core/isr.S @@ -103,6 +103,9 @@ GTEXT(_isr_wrapper) */ SECTION_FUNC(exception.entry, _isr_wrapper) +/* Provide requested alignment, which depends e.g. on MTVEC format */ +.balign CONFIG_RISCV_TRAP_HANDLER_ALIGNMENT + #ifdef CONFIG_USERSPACE /* retrieve address of _current_cpu preserving s0 */ csrrw s0, mscratch, s0 @@ -184,10 +187,23 @@ SECTION_FUNC(exception.entry, _isr_wrapper) 1: #endif andi t0, t2, 0x7f /* keep only the opcode bits */ + /* + * Major FP opcodes: + * 0000111 = LOAD-FP + * 0100111 = STORE-FP + * 1000011 = MADD + * 1000111 = MSUB + * 1001011 = NMSUB + * 1001111 = NMADD + * 1010011 = OP-FP + */ xori t1, t0, 0b1010011 /* OP-FP */ beqz t1, is_fp - ori t0, t0, 0b0100000 - xori t1, t0, 0b0100111 /* LOAD-FP / STORE-FP */ + ori t1, t0, 0b0100000 + xori t1, t1, 0b0100111 /* LOAD-FP / STORE-FP */ + beqz t1, is_fp + ori t1, t0, 0b0001100 + xori t1, t1, 0b1001111 /* MADD / MSUB / NMSUB / NMADD */ beqz t1, is_fp /* * The FRCSR, FSCSR, FRRM, FSRM, FSRMI, FRFLAGS, FSFLAGS and FSFLAGSI diff --git a/arch/riscv/core/pmp.c b/arch/riscv/core/pmp.c index 7a3cb02cf52..bfeb1c025cd 100644 --- a/arch/riscv/core/pmp.c +++ b/arch/riscv/core/pmp.c @@ -161,8 +161,8 @@ static bool set_pmp_entry(unsigned int *index_p, uint8_t perm, unsigned int index = *index_p; bool ok = true; - __ASSERT((start & 0x3) == 0, "misaligned start address"); - __ASSERT((size & 0x3) == 0, "misaligned size"); + __ASSERT((start & (CONFIG_PMP_GRANULARITY - 1)) == 0, "misaligned start address"); + __ASSERT((size & (CONFIG_PMP_GRANULARITY - 1)) == 0, "misaligned size"); if (index >= index_limit) { LOG_ERR("out of PMP slots"); diff --git a/arch/riscv/core/reset.S b/arch/riscv/core/reset.S index 094e51b9183..e2faa6fe94d 100644 --- a/arch/riscv/core/reset.S +++ b/arch/riscv/core/reset.S @@ -93,16 +93,24 @@ aa_loop: boot_secondary_core: #if CONFIG_MP_MAX_NUM_CPUS > 1 + la t0, riscv_cpu_wake_flag + li t1, -1 + sr t1, 0(t0) + la t0, riscv_cpu_boot_flag + sr zero, 0(t0) + +wait_secondary_wake_flag: la t0, riscv_cpu_wake_flag lr t0, 0(t0) - bne a0, t0, boot_secondary_core + bne a0, t0, wait_secondary_wake_flag /* Set up stack */ la t0, riscv_cpu_sp lr sp, 0(t0) - la t0, riscv_cpu_wake_flag - sr zero, 0(t0) + la t0, riscv_cpu_boot_flag + li t1, 1 + sr t1, 0(t0) j z_riscv_secondary_cpu_init #else j loop_unconfigured_cores diff --git a/arch/riscv/core/smp.c b/arch/riscv/core/smp.c index 0815920e8e6..6154450e58d 100644 --- a/arch/riscv/core/smp.c +++ b/arch/riscv/core/smp.c @@ -9,15 +9,19 @@ #include #include #include +#include volatile struct { arch_cpustart_t fn; void *arg; } riscv_cpu_init[CONFIG_MP_MAX_NUM_CPUS]; -volatile uintptr_t riscv_cpu_wake_flag; +volatile uintptr_t __noinit riscv_cpu_wake_flag; +volatile uintptr_t riscv_cpu_boot_flag; volatile void *riscv_cpu_sp; +extern void __start(void); + void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz, arch_cpustart_t fn, void *arg) { @@ -25,10 +29,17 @@ void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz, riscv_cpu_init[cpu_num].arg = arg; riscv_cpu_sp = Z_KERNEL_STACK_BUFFER(stack) + sz; - riscv_cpu_wake_flag = _kernel.cpus[cpu_num].arch.hartid; + riscv_cpu_boot_flag = 0U; + +#ifdef CONFIG_PM_CPU_OPS + if (pm_cpu_on(cpu_num, (uintptr_t)&__start)) { + printk("Failed to boot secondary CPU %d\n", cpu_num); + return; + } +#endif - while (riscv_cpu_wake_flag != 0U) { - ; + while (riscv_cpu_boot_flag == 0U) { + riscv_cpu_wake_flag = _kernel.cpus[cpu_num].arch.hartid; } } diff --git a/arch/sparc/core/window_trap.S b/arch/sparc/core/window_trap.S index ea810e1d6dd..5a9edfd37c2 100644 --- a/arch/sparc/core/window_trap.S +++ b/arch/sparc/core/window_trap.S @@ -83,60 +83,85 @@ SECTION_FUNC(TEXT, __sparc_trap_window_underflow) * "By executing a type 3 trap, a process asks the system to flush all its * register windows to the stack." * - * This implementation uses the window overflow trap handler to perform the - * actual window flush. - * * On entry: * %l0: psr * %l1: pc * %l2: npc */ SECTION_FUNC(TEXT, __sparc_trap_flush_windows) - /* push a few registers which are needed later to the stack */ - sub %sp, 0x10, %sp - std %l0, [%sp + 0x40 + 0x00] - st %l2, [%sp + 0x40 + 0x08] - st %g2, [%sp + 0x40 + 0x0c] - - restore - /* In window where we trapped from. This window will not be flushed. */ - - /* Set highest processor interrupt level and enable traps. */ - rd %psr, %g2 - or %g2, PSR_PIL, %g2 - wr %g2, PSR_ET, %psr - nop - nop + /* Save global registers used by the routine */ + mov %g3, %l3 + mov %g4, %l4 + mov %g5, %l5 + mov %g1, %l6 + mov %g2, %l7 - /* Execute "save" NWINDOWS-1 times. */ - set CONFIG_SPARC_NWIN-2, %g2 -1: - save - cmp %g2, %g0 - bne 1b - sub %g2, 1, %g2 + /* Uses g3=psr, g4=1, g2=wim, g1,g5=scratch */ + mov %l0, %g3 + set 1, %g4 + rd %wim, %g2 - /* Execute "restore" NWINDOWS-1 times. */ - set CONFIG_SPARC_NWIN-2, %g2 -2: - restore - cmp %g2, %g0 - bne 2b - sub %g2, 1, %g2 + /* + * We can always restore the previous window. Check if we can restore + * the window after that. + */ + and %l0, PSR_CWP, %g1 + add %g1, 2, %g1 + ba .LcheckNextWindow + restore - save + /* Flush window to stack */ +.LflushWindow: + std %l0, [%sp + 0x00] + std %l2, [%sp + 0x08] + std %l4, [%sp + 0x10] + std %l6, [%sp + 0x18] + std %i0, [%sp + 0x20] + std %i2, [%sp + 0x28] + std %i4, [%sp + 0x30] + std %i6, [%sp + 0x38] - /* pop registers from stack which are used for the trap return */ - ldd [%sp + 0x40 + 0x00], %l0 - ld [%sp + 0x40 + 0x08], %l2 - ld [%sp + 0x40 + 0x0c], %g2 - add %sp, 0x10, %sp + /* + * Check if next window is invalid by comparing + * (1 << ((cwp + 1) % NWIN)) with WIM + */ +.LcheckNextWindow: + set CONFIG_SPARC_NWIN, %g5 + cmp %g1, %g5 + bge,a .Lnowrap + sub %g1, %g5, %g1 +.Lnowrap: + sll %g4, %g1, %g5 + cmp %g5, %g2 + be .LflushWindowDone + inc %g1 - /* Restore %psr as it was on trap entry. */ - wr %l0, %psr - nop - nop - nop + /* We need to flush the next window */ + ba .LflushWindow + restore + /* + * All used windows have been flushed. Set WIM to cause trap for CWP+2. + * When we return from this trap it will be CWP+1 that will trap, that + * is, the next restore or rett. + */ +.LflushWindowDone: + /* We can not restore %psr from %l0 because we may be in any window. */ + wr %g3, %psr + and %g3, PSR_CWP, %g1 + add %g1, 2, %g1 + set CONFIG_SPARC_NWIN, %g5 + /* We are now back in the trap window. */ + cmp %g1, %g5 + bge,a .Lnowrap2 + sub %g1, %g5, %g1 +.Lnowrap2: + sll %g4, %g1, %g1 + wr %g1, %wim + mov %l3, %g3 + mov %l4, %g4 + mov %l5, %g5 + mov %l6, %g1 + mov %l7, %g2 jmp %l2 rett %l2 + 4 diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5f22707aed9..d7ccfca7ecd 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -227,22 +227,16 @@ choice Reboot via the RST_CNT register, going back to BIOS. endchoice -config X86_ACPI - bool "ACPI (Advanced Configuration and Power Interface) support" - depends on X86_PC_COMPATIBLE - help - Allow retrieval of platform configuration at runtime. - config PCIE_MMIO_CFG bool "Use MMIO PCI configuration space access" - select X86_ACPI + select ACPI help Selects the use of the memory-mapped PCI Express Extended Configuration Space instead of the traditional 0xCF8/0xCFC IO Port registers. config KERNEL_VM_SIZE - default 0x40000000 if X86_ACPI + default 0x40000000 if ACPI config X86_PC_COMPATIBLE bool diff --git a/arch/x86/core/CMakeLists.txt b/arch/x86/core/CMakeLists.txt index 4c4bfa98fe9..9268dc4cf4d 100644 --- a/arch/x86/core/CMakeLists.txt +++ b/arch/x86/core/CMakeLists.txt @@ -15,7 +15,7 @@ zephyr_library_sources_ifdef(CONFIG_PCIE pcie.c) zephyr_library_sources_ifdef(CONFIG_REBOOT_RST_CNT reboot_rst_cnt.c) zephyr_library_sources_ifdef(CONFIG_MULTIBOOT_INFO multiboot.c) zephyr_library_sources_ifdef(CONFIG_X86_EFI efi.c) -zephyr_library_sources_ifdef(CONFIG_X86_ACPI acpi.c) +zephyr_library_sources_ifdef(CONFIG_ACPI legacy_bios.c) zephyr_library_sources_ifdef(CONFIG_X86_MMU x86_mmu.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE userspace.c) zephyr_library_sources_ifdef(CONFIG_ARCH_CACHE cache.c) diff --git a/arch/x86/core/acpi.c b/arch/x86/core/acpi.c deleted file mode 100644 index e304a54627f..00000000000 --- a/arch/x86/core/acpi.c +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Copyright (c) 2020 Intel Corporation - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include - -static struct acpi_rsdp *rsdp; -static bool is_rsdp_searched; - -static struct acpi_dmar *dmar; -static bool is_dmar_searched; - -static bool check_sum(struct acpi_sdt *t) -{ - uint8_t sum = 0U, *p = (uint8_t *)t; - - for (int i = 0; i < t->length; i++) { - sum += p[i]; - } - - return sum == 0U; -} - -static void find_rsdp(void) -{ - uint8_t *bda_seg, *zero_page_base; - uint64_t *search; - uintptr_t search_phys, rsdp_phys; - size_t search_length = 0U, rsdp_length; - - if (is_rsdp_searched) { - /* Looking up for RSDP has already been done */ - return; - } - - /* Let's first get it from EFI, if enabled */ - if (IS_ENABLED(CONFIG_X86_EFI)) { - rsdp_phys = (uintptr_t)efi_get_acpi_rsdp(); - if (rsdp_phys != 0UL) { - /* See at found label why this is required */ - search_length = sizeof(struct acpi_rsdp); - z_phys_map((uint8_t **)&search, rsdp_phys, search_length, 0); - rsdp = (struct acpi_rsdp *)search; - - goto found; - } - } - - /* We never identity map the NULL page, so need to map it before - * it can be accessed. - */ - z_phys_map(&zero_page_base, 0, 4096, 0); - - /* Physical (real mode!) address 0000:040e stores a (real - * mode!!) segment descriptor pointing to the 1kb Extended - * BIOS Data Area. - * - * We had to memory map this segment descriptor since it is in - * the NULL page. The remaining structures (EBDA etc) are identity - * mapped somewhere within the minefield of reserved regions in the - * first megabyte and are directly accessible. - */ - bda_seg = 0x040e + zero_page_base; - search_phys = (long)(((int)*(uint16_t *)bda_seg) << 4); - - /* Unmap after use */ - z_phys_unmap(zero_page_base, 4096); - - /* Might be nothing there, check before we inspect. - * Note that EBDA usually is in 0x80000 to 0x100000. - */ - if ((POINTER_TO_UINT(search_phys) >= 0x80000UL) && - (POINTER_TO_UINT(search_phys) < 0x100000UL)) { - search_length = 1024; - z_phys_map((uint8_t **)&search, search_phys, search_length, 0); - - for (int i = 0; i < 1024/8; i++) { - if (search[i] == ACPI_RSDP_SIGNATURE) { - rsdp_phys = search_phys + i * 8; - rsdp = (void *)&search[i]; - goto found; - } - } - - z_phys_unmap((uint8_t *)search, search_length); - } - - /* If it's not there, then look for it in the last 128kb of - * real mode memory. - */ - search_phys = 0xe0000; - search_length = 128 * 1024; - z_phys_map((uint8_t **)&search, search_phys, search_length, 0); - - for (int i = 0; i < 128*1024/8; i++) { - if (search[i] == ACPI_RSDP_SIGNATURE) { - rsdp_phys = search_phys + i * 8; - rsdp = (void *)&search[i]; - goto found; - } - } - - z_phys_unmap((uint8_t *)search, search_length); - - rsdp = NULL; - - is_rsdp_searched = true; - - return; - -found: - /* Determine length of RSDP table. - * ACPI v2 and above uses the length field. - * Otherwise, just the size of struct itself. - */ - if (rsdp->revision < 2) { - rsdp_length = sizeof(*rsdp); - } else { - rsdp_length = rsdp->length; - } - - /* Need to unmap search since it is still mapped */ - if (search_length != 0U) { - z_phys_unmap((uint8_t *)search, search_length); - } - - /* Now map the RSDP */ - z_phys_map((uint8_t **)&rsdp, rsdp_phys, rsdp_length, 0); - - is_rsdp_searched = true; -} - -void *z_acpi_find_table(uint32_t signature) -{ - uint8_t *mapped_tbl; - uint32_t length; - struct acpi_rsdt *rsdt; - struct acpi_xsdt *xsdt; - struct acpi_sdt *t; - uintptr_t t_phys; - bool tbl_found; - - find_rsdp(); - - if (!rsdp) { - return NULL; - } - - if (rsdp->rsdt_ptr != 0U) { - z_phys_map((uint8_t **)&rsdt, rsdp->rsdt_ptr, sizeof(*rsdt), 0); - tbl_found = false; - - if (check_sum(&rsdt->sdt)) { - /* Remap the memory to the indicated length of RSDT */ - length = rsdt->sdt.length; - z_phys_unmap((uint8_t *)rsdt, sizeof(*rsdt)); - z_phys_map((uint8_t **)&rsdt, rsdp->rsdt_ptr, length, 0); - - uint32_t *end = (uint32_t *)((char *)rsdt + rsdt->sdt.length); - - /* Extra indirection required to avoid - * -Waddress-of-packed-member - */ - void *table_ptrs = &rsdt->table_ptrs[0]; - - for (uint32_t *tp = table_ptrs; tp < end; tp++) { - t_phys = (long)*tp; - z_phys_map(&mapped_tbl, t_phys, sizeof(*t), 0); - t = (void *)mapped_tbl; - - if (t->signature == signature && check_sum(t)) { - tbl_found = true; - break; - } - - z_phys_unmap(mapped_tbl, sizeof(*t)); - } - } - - z_phys_unmap((uint8_t *)rsdt, sizeof(*rsdt)); - - if (tbl_found) { - goto found; - } - } - - if (rsdp->revision < 2) { - return NULL; - } - - if (rsdp->xsdt_ptr != 0ULL) { - z_phys_map((uint8_t **)&xsdt, rsdp->xsdt_ptr, sizeof(*xsdt), 0); - - tbl_found = false; - if (check_sum(&xsdt->sdt)) { - /* Remap the memory to the indicated length of RSDT */ - length = xsdt->sdt.length; - z_phys_unmap((uint8_t *)xsdt, sizeof(*xsdt)); - z_phys_map((uint8_t **)&xsdt, rsdp->xsdt_ptr, length, 0); - - uint64_t *end = (uint64_t *)((char *)xsdt + xsdt->sdt.length); - - /* Extra indirection required to avoid - * -Waddress-of-packed-member - */ - void *table_ptrs = &xsdt->table_ptrs[0]; - - for (uint64_t *tp = table_ptrs; tp < end; tp++) { - t_phys = (long)*tp; - z_phys_map(&mapped_tbl, t_phys, sizeof(*t), 0); - t = (void *)mapped_tbl; - - if (t->signature == signature && check_sum(t)) { - tbl_found = true; - break; - } - - z_phys_unmap(mapped_tbl, sizeof(*t)); - } - } - - z_phys_unmap((uint8_t *)xsdt, sizeof(*xsdt)); - - if (tbl_found) { - goto found; - } - } - - return NULL; - -found: - /* Remap to indicated length of the table */ - length = t->length; - z_phys_unmap(mapped_tbl, sizeof(*t)); - z_phys_map(&mapped_tbl, t_phys, length, 0); - t = (void *)mapped_tbl; - - return t; -} - -/* - * Return the 'n'th CPU entry from the ACPI MADT, or NULL if not available. - */ - -struct acpi_cpu *z_acpi_get_cpu(int n) -{ - struct acpi_madt *madt = z_acpi_find_table(ACPI_MADT_SIGNATURE); - uintptr_t base = POINTER_TO_UINT(madt); - uintptr_t offset; - - if (!madt) { - return NULL; - } - - offset = POINTER_TO_UINT(madt->entries) - base; - - while (offset < madt->sdt.length) { - struct acpi_madt_entry *entry; - - entry = (struct acpi_madt_entry *)(offset + base); - if (entry->type == ACPI_MADT_ENTRY_CPU) { - struct acpi_cpu *cpu = (struct acpi_cpu *)entry; - - if ((cpu->flags & ACPI_CPU_FLAGS_ENABLED) != 0) { - if (n == 0) { - return cpu; - } - - --n; - } - } - - offset += entry->length; - } - - return NULL; -} - -static void find_dmar(void) -{ - if (is_dmar_searched) { - return; - } - - dmar = z_acpi_find_table(ACPI_DMAR_SIGNATURE); - is_dmar_searched = true; -} - -struct acpi_dmar *z_acpi_find_dmar(void) -{ - find_dmar(); - return dmar; -} - -struct acpi_drhd *z_acpi_find_drhds(int *n) -{ - struct acpi_drhd *drhds = NULL; - uintptr_t offset; - uintptr_t base; - - find_dmar(); - - if (dmar == NULL) { - return NULL; - } - - *n = 0; - base = POINTER_TO_UINT(dmar); - - offset = POINTER_TO_UINT(dmar->remap_entries) - base; - while (offset < dmar->sdt.length) { - struct acpi_dmar_entry *entry; - - entry = (struct acpi_dmar_entry *)(offset + base); - if (entry->type == ACPI_DMAR_TYPE_DRHD) { - if (*n == 0) { - drhds = (struct acpi_drhd *)entry; - } - - (*n)++; - } else { - /* DMAR entries are found packed by type so - * if type is not DRHD, we will not encounter one, - * anymore. - */ - break; - } - - offset += entry->length; - } - - return drhds; -} - -struct acpi_dmar_dev_scope *z_acpi_get_drhd_dev_scopes(struct acpi_drhd *drhd, - int *n) -{ - uintptr_t offset; - uintptr_t base; - - if (drhd->entry.length <= ACPI_DRHD_MIN_SIZE) { - return NULL; - } - - *n = 0; - base = POINTER_TO_UINT(drhd); - - offset = POINTER_TO_UINT(drhd->device_scope) - base; - while (offset < drhd->entry.length) { - struct acpi_dmar_dev_scope *dev_scope; - - dev_scope = (struct acpi_dmar_dev_scope *)(offset + base); - - (*n)++; - - offset += dev_scope->length; - } - - return (*n == 0) ? NULL : drhd->device_scope; -} - -struct acpi_dmar_dev_path * -z_acpi_get_dev_scope_paths(struct acpi_dmar_dev_scope *dev_scope, int *n) -{ - switch (dev_scope->type) { - case ACPI_DRHD_DEV_SCOPE_PCI_EPD: - /* Fall through */ - case ACPI_DRHD_DEV_SCOPE_PCI_SUB_H: - /* Fall through */ - case ACPI_DRHD_DEV_SCOPE_IOAPIC: - if (dev_scope->length < (ACPI_DMAR_DEV_SCOPE_MIN_SIZE + - ACPI_DMAR_DEV_PATH_SIZE)) { - return NULL; - } - - break; - case ACPI_DRHD_DEV_SCOPE_MSI_CAP_HPET: - /* Fall through */ - case ACPI_DRHD_DEV_SCOPE_NAMESPACE_DEV: - if (dev_scope->length != (ACPI_DMAR_DEV_SCOPE_MIN_SIZE + - ACPI_DMAR_DEV_PATH_SIZE)) { - return NULL; - } - - break; - default: - return NULL; - } - - *n = (dev_scope->length - ACPI_DMAR_DEV_SCOPE_MIN_SIZE) / - ACPI_DMAR_DEV_PATH_SIZE; - - return dev_scope->path; -} - -uint16_t z_acpi_get_dev_id_from_dmar(uint8_t dev_scope_type) -{ - struct acpi_drhd *drhd; - int n_drhd; - - find_dmar(); - - if (dmar == NULL) { - return USHRT_MAX; - } - - drhd = z_acpi_find_drhds(&n_drhd); - - for (; n_drhd > 0; n_drhd--) { - struct acpi_dmar_dev_scope *dev_scope; - int n_ds; - - dev_scope = z_acpi_get_drhd_dev_scopes(drhd, &n_ds); - for (; n_ds > 0; n_ds--) { - if (dev_scope->type == dev_scope_type) { - struct acpi_dmar_dev_path *path; - int n_path; - - path = z_acpi_get_dev_scope_paths(dev_scope, - &n_path); - if (n_path > 0) { - union acpi_dmar_id id; - - /* Let's over simplify for now: - * we don't look for secondary bus - * and extra paths. We just stop here. - */ - - id.bits.bus = dev_scope->start_bus_num; - id.bits.device = path->device; - id.bits.function = path->function; - - return id.raw; - } - } - - dev_scope = (struct acpi_dmar_dev_scope *)( - POINTER_TO_UINT(dev_scope) + dev_scope->length); - } - - drhd = (struct acpi_drhd *)(POINTER_TO_UINT(drhd) + - drhd->entry.length); - } - - return USHRT_MAX; -} diff --git a/arch/x86/core/early_serial.c b/arch/x86/core/early_serial.c index 0c102300a51..572b71cf5a0 100644 --- a/arch/x86/core/early_serial.c +++ b/arch/x86/core/early_serial.c @@ -11,7 +11,10 @@ #include -#ifdef CONFIG_UART_NS16550_ACCESS_IOPORT +#define UART_IS_IOPORT_ACCESS \ + DT_NODE_HAS_PROP(DT_CHOSEN(zephyr_console), io_mapped) + +#if UART_IS_IOPORT_ACCESS /* Legacy I/O Port Access to a NS16550 UART */ #define IN(reg) sys_in8(reg + DT_REG_ADDR(DT_CHOSEN(zephyr_console))) #define OUT(reg, val) sys_out8(val, reg + DT_REG_ADDR(DT_CHOSEN(zephyr_console))) @@ -86,7 +89,7 @@ int arch_printk_char_out(int c) void z_x86_early_serial_init(void) { -#if defined(DEVICE_MMIO_IS_IN_RAM) && !defined(CONFIG_UART_NS16550_ACCESS_IOPORT) +#if defined(DEVICE_MMIO_IS_IN_RAM) && !UART_IS_IOPORT_ACCESS #ifdef X86_SOC_EARLY_SERIAL_PCIDEV struct pcie_bar mbar; pcie_get_mbar(X86_SOC_EARLY_SERIAL_PCIDEV, 0, &mbar); diff --git a/arch/x86/core/efi.c b/arch/x86/core/efi.c index 00bcff8d47c..425b0dcde86 100644 --- a/arch/x86/core/efi.c +++ b/arch/x86/core/efi.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include "../zefi/efi.h" /* ZEFI not on include path */ #include #include diff --git a/arch/x86/core/ia32/crt0.S b/arch/x86/core/ia32/crt0.S index d42a99d5f56..75a5402a4b2 100644 --- a/arch/x86/core/ia32/crt0.S +++ b/arch/x86/core/ia32/crt0.S @@ -21,7 +21,7 @@ #include #include #include -#include +#include /* exports (private APIs) */ diff --git a/arch/x86/core/ia32/fatal.c b/arch/x86/core/ia32/fatal.c index 9c9ab5f3a63..38cf180e0bc 100644 --- a/arch/x86/core/ia32/fatal.c +++ b/arch/x86/core/ia32/fatal.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); diff --git a/arch/x86/core/ia32/userspace.S b/arch/x86/core/ia32/userspace.S index adba32c78b2..bf21a0cc1a2 100644 --- a/arch/x86/core/ia32/userspace.S +++ b/arch/x86/core/ia32/userspace.S @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include /* Exports */ diff --git a/arch/x86/core/intel64/cpu.c b/arch/x86/core/intel64/cpu.c index 80e9e65b90d..204264cbdf9 100644 --- a/arch/x86/core/intel64/cpu.c +++ b/arch/x86/core/intel64/cpu.c @@ -11,7 +11,9 @@ #include #include #include -#include +#ifdef CONFIG_ACPI +#include +#endif BUILD_ASSERT(CONFIG_MP_MAX_NUM_CPUS <= 4, "Only supports max 4 CPUs"); @@ -139,18 +141,18 @@ struct x86_cpuboot x86_cpuboot[] = { void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz, arch_cpustart_t fn, void *arg) { +#if CONFIG_MP_MAX_NUM_CPUS > 1 uint8_t vector = ((unsigned long) x86_ap_start) >> 12; uint8_t apic_id; - if (IS_ENABLED(CONFIG_X86_ACPI)) { - struct acpi_cpu *cpu; + IF_ENABLED(CONFIG_ACPI, ({ + ACPI_MADT_LOCAL_APIC *lapic = acpi_local_apic_get(cpu_num); - cpu = z_acpi_get_cpu(cpu_num); - if (cpu != NULL) { - /* We update the apic_id, x86_ap_start will need it. */ - x86_cpu_loapics[cpu_num] = cpu->apic_id; + if (lapic != NULL) { + /* We update the apic_id, __start will need it. */ + x86_cpu_loapics[cpu_num] = lapic->Id; } - } + })); apic_id = x86_cpu_loapics[cpu_num]; @@ -165,6 +167,13 @@ void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz, while (x86_cpuboot[cpu_num].ready == 0) { } +#else + ARG_UNUSED(cpu_num); + ARG_UNUSED(stack); + ARG_UNUSED(sz); + ARG_UNUSED(fn); + ARG_UNUSED(arg); +#endif } /* Per-CPU initialization, C domain. On the first CPU, z_x86_prep_c is the diff --git a/arch/x86/core/intel64/locore.S b/arch/x86/core/intel64/locore.S index f69545cc64a..dd541921742 100644 --- a/arch/x86/core/intel64/locore.S +++ b/arch/x86/core/intel64/locore.S @@ -13,7 +13,7 @@ #include #include #include -#include +#include /* * Definitions/macros for enabling paging diff --git a/arch/x86/core/intel64/userspace.S b/arch/x86/core/intel64/userspace.S index 747c6183c3c..ab09381c7af 100644 --- a/arch/x86/core/intel64/userspace.S +++ b/arch/x86/core/intel64/userspace.S @@ -8,7 +8,7 @@ #include #include #include -#include +#include #ifdef CONFIG_X86_KPTI /* Copy interrupt return stack context to the trampoline stack, switch back diff --git a/arch/x86/core/legacy_bios.c b/arch/x86/core/legacy_bios.c new file mode 100644 index 00000000000..6a7159a9b1c --- /dev/null +++ b/arch/x86/core/legacy_bios.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#define DATA_SIZE_K(n) (n * 1024u) +#define RSDP_SIGNATURE ((uint64_t)0x2052545020445352) +#define EBDA_ADD (0x040e) +#define BIOS_RODATA_ADD (0xe0000) +#define BIOS_EXT_DATA_LOW (0x80000UL) +#define BIOS_EXT_DATA_HIGH (0x100000UL) + +static uintptr_t bios_search_rsdp_buff(uintptr_t search_phy_add, uint32_t search_length) +{ + uint64_t *search_buff; + + z_phys_map((uint8_t **)&search_buff, search_phy_add, search_length, 0); + if (!search_buff) { + return 0; + } + + for (int i = 0; i < search_length / 8u; i++) { + if (search_buff[i] == RSDP_SIGNATURE) { + z_phys_unmap((uint8_t *)search_buff, search_length); + return (search_phy_add + (i * 8u)); + } + } + z_phys_unmap((uint8_t *)search_buff, search_length); + + return 0; +} + +void *bios_acpi_rsdp_get(void) +{ + uint8_t *bios_ext_data, *zero_page_base; + uintptr_t search_phy_add, rsdp_phy_add; + + z_phys_map(&zero_page_base, 0, DATA_SIZE_K(4u), 0); + bios_ext_data = EBDA_ADD + zero_page_base; + search_phy_add = (uintptr_t)((*(uint16_t *)bios_ext_data) << 4u); + z_phys_unmap(zero_page_base, DATA_SIZE_K(4u)); + + if ((search_phy_add >= BIOS_EXT_DATA_LOW) && (search_phy_add < BIOS_EXT_DATA_HIGH)) { + rsdp_phy_add = bios_search_rsdp_buff(search_phy_add, DATA_SIZE_K(1u)); + if (rsdp_phy_add) { + return (void *)rsdp_phy_add; + } + } + return (void *)bios_search_rsdp_buff(BIOS_RODATA_ADD, DATA_SIZE_K(128u)); +} diff --git a/arch/x86/core/pcie.c b/arch/x86/core/pcie.c index 47b78f990c1..5c1e83725bb 100644 --- a/arch/x86/core/pcie.c +++ b/arch/x86/core/pcie.c @@ -8,8 +8,8 @@ #include #include -#ifdef CONFIG_X86_ACPI -#include +#ifdef CONFIG_ACPI +#include #endif #ifdef CONFIG_PCIE_MSI @@ -35,26 +35,26 @@ static bool do_pcie_mmio_cfg; static void pcie_mm_init(void) { -#ifdef CONFIG_X86_ACPI - struct acpi_mcfg *m = z_acpi_find_table(ACPI_MCFG_SIGNATURE); +#ifdef CONFIG_ACPI + struct acpi_mcfg *m = acpi_table_get("MCFG", 0); if (m != NULL) { - int n = (m->sdt.length - sizeof(*m)) / sizeof(m->pci_segs[0]); + int n = (m->header.Length - sizeof(*m)) / sizeof(m->pci_segs[0]); for (int i = 0; i < n && i < MAX_PCI_BUS_SEGMENTS; i++) { size_t size; uintptr_t phys_addr; - bus_segs[i].start_bus = m->pci_segs[i].start_bus; - bus_segs[i].n_buses = 1 + m->pci_segs[i].end_bus - - m->pci_segs[i].start_bus; + bus_segs[i].start_bus = m->pci_segs[i].StartBusNumber; + bus_segs[i].n_buses = + 1 + m->pci_segs[i].EndBusNumber - m->pci_segs[i].StartBusNumber; - phys_addr = m->pci_segs[i].base_addr; + phys_addr = m->pci_segs[i].Address; /* 32 devices & 8 functions per bus, 4k per device */ size = bus_segs[i].n_buses * (32 * 8 * 4096); - device_map((mm_reg_t *)&bus_segs[i].mmio, phys_addr, - size, K_MEM_CACHE_NONE); + device_map((mm_reg_t *)&bus_segs[i].mmio, phys_addr, size, + K_MEM_CACHE_NONE); } do_pcie_mmio_cfg = true; diff --git a/arch/x86/core/prep_c.c b/arch/x86/core/prep_c.c index 70c3e844756..ee095efe33d 100644 --- a/arch/x86/core/prep_c.c +++ b/arch/x86/core/prep_c.c @@ -6,7 +6,6 @@ #include #include -#include #include #include #include diff --git a/arch/x86/core/userspace.c b/arch/x86/core/userspace.c index d0876749575..2b058206232 100644 --- a/arch/x86/core/userspace.c +++ b/arch/x86/core/userspace.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include #include diff --git a/arch/x86/core/x86_mmu.c b/arch/x86/core/x86_mmu.c index 119179b72ae..71aafe5cad9 100644 --- a/arch/x86/core/x86_mmu.c +++ b/arch/x86/core/x86_mmu.c @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include #include diff --git a/arch/x86/include/x86_mmu.h b/arch/x86/include/x86_mmu.h index 14c5b053c65..b5b319a64e4 100644 --- a/arch/x86/include/x86_mmu.h +++ b/arch/x86/include/x86_mmu.h @@ -14,7 +14,7 @@ #include #include -#include +#include #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) #define XD_SUPPORTED diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 5d042c1d475..a1517f17ed0 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -46,22 +46,10 @@ config XTENSA_USE_CORE_CRT1 config XTENSA_ENABLE_BACKTRACE bool "Backtrace on panic exception" default y - depends on SOC_SERIES_ESP32 || SOC_FAMILY_INTEL_ADSP + depends on SOC_SERIES_ESP32 || SOC_FAMILY_INTEL_ADSP || SOC_XTENSA_DC233C help Enable this config option to print backtrace on panic exception -config XTENSA_CPU_IDLE_SPIN - bool "Use busy loop for k_cpu_idle" - help - Use a spin loop instead of WAITI for the CPU idle state. - -config XTENSA_WAITI_BUG - bool "Workaround sequence for WAITI bug on LX6" - help - SOF traditionally contains this workaround on its ADSP - platforms which prefixes a WAITI entry with 128 NOP - instructions followed by an ISYNC and EXTW. - config XTENSA_SMALL_VECTOR_TABLE_ENTRY bool "Workaround for small vector table entries" help @@ -126,6 +114,7 @@ config XTENSA_MMU default n select MMU select XTENSA_SMALL_VECTOR_TABLE_ENTRY + select KERNEL_VM_USE_CUSTOM_MEM_RANGE_CHECK if XTENSA_RPO_CACHE help Enable support for Xtensa Memory Management Unit. diff --git a/arch/xtensa/core/CMakeLists.txt b/arch/xtensa/core/CMakeLists.txt index 3bf29e88b64..c6fffd4f5e1 100644 --- a/arch/xtensa/core/CMakeLists.txt +++ b/arch/xtensa/core/CMakeLists.txt @@ -23,6 +23,11 @@ zephyr_library_sources_ifdef(CONFIG_TIMING_FUNCTIONS timing.c) zephyr_library_sources_ifdef(CONFIG_GDBSTUB gdbstub.c) zephyr_library_sources_ifdef(CONFIG_XTENSA_MMU xtensa_mmu.c) +zephyr_library_sources_ifdef( + CONFIG_KERNEL_VM_USE_CUSTOM_MEM_RANGE_CHECK + mem_manage.c +) + if("${ZEPHYR_TOOLCHAIN_VARIANT}" STREQUAL "xcc") zephyr_library_sources(xcc_stubs.c) endif() diff --git a/arch/xtensa/core/coredump.c b/arch/xtensa/core/coredump.c index 8f15ca39c58..26060dea8c3 100644 --- a/arch/xtensa/core/coredump.c +++ b/arch/xtensa/core/coredump.c @@ -19,6 +19,7 @@ enum xtensa_soc_code { XTENSA_SOC_INTEL_ADSP, XTENSA_SOC_ESP32S2, XTENSA_SOC_ESP32S3, + XTENSA_SOC_DC233C, }; struct xtensa_arch_block { @@ -117,6 +118,8 @@ void arch_coredump_info_dump(const z_arch_esf_t *esf) arch_blk.soc = XTENSA_SOC_ESP32S2; #elif CONFIG_SOC_SERIES_ESP32S3 arch_blk.soc = XTENSA_SOC_ESP32S3; + #elif CONFIG_SOC_XTENSA_DC233C + arch_blk.soc = XTENSA_SOC_DC233C; #else arch_blk.soc = XTENSA_SOC_UNKNOWN; #endif diff --git a/arch/xtensa/core/cpu_idle.c b/arch/xtensa/core/cpu_idle.c index fa9384d8445..dae79f023ff 100644 --- a/arch/xtensa/core/cpu_idle.c +++ b/arch/xtensa/core/cpu_idle.c @@ -6,48 +6,13 @@ #include #include -/* xt-clang removes any NOPs more than 8. So we need to set - * no optimization to avoid those NOPs from being removed. - * - * This function is simply enough and full of hand written - * assembly that optimization is not really meaningful - * anyway. So we can skip optimization unconditionally. - * Re-evalulate its use and add #ifdef if this assumption - * is no longer valid. - */ -__no_optimization +#ifndef CONFIG_ARCH_CPU_IDLE_CUSTOM void arch_cpu_idle(void) { sys_trace_idle(); - - /* Just spin forever with interrupts unmasked, for platforms - * where WAITI can't be used or where its behavior is - * complicated (Intel DSPs will power gate on idle entry under - * some circumstances) - */ - if (IS_ENABLED(CONFIG_XTENSA_CPU_IDLE_SPIN)) { - __asm__ volatile("rsil a0, 0"); - __asm__ volatile("loop_forever: j loop_forever"); - return; - } - - /* Cribbed from SOF: workaround for a bug in some versions of - * the LX6 IP. Preprocessor ugliness avoids the need to - * figure out how to get the compiler to unroll a loop. - */ - if (IS_ENABLED(CONFIG_XTENSA_WAITI_BUG)) { -#define NOP4 __asm__ volatile("nop; nop; nop; nop"); -#define NOP32 NOP4 NOP4 NOP4 NOP4 NOP4 NOP4 NOP4 NOP4 -#define NOP128() NOP32 NOP32 NOP32 NOP32 - NOP128(); -#undef NOP128 -#undef NOP32 -#undef NOP4 - __asm__ volatile("isync; extw"); - } - __asm__ volatile ("waiti 0"); } +#endif void arch_cpu_atomic_idle(unsigned int key) { diff --git a/arch/xtensa/core/crt1.S b/arch/xtensa/core/crt1.S index 1f9cc148ab5..0fa3ad23099 100644 --- a/arch/xtensa/core/crt1.S +++ b/arch/xtensa/core/crt1.S @@ -23,7 +23,6 @@ .global __start .type z_cstart, @function -.type z_mp_entry, @function #ifdef CONFIG_XTENSA_MMU .type z_xtensa_mmu_init, @function diff --git a/arch/xtensa/core/mem_manage.c b/arch/xtensa/core/mem_manage.c new file mode 100644 index 00000000000..e43bf4b75d6 --- /dev/null +++ b/arch/xtensa/core/mem_manage.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +__weak bool sys_mm_is_phys_addr_in_range(uintptr_t phys) +{ + bool valid; + uintptr_t cached = (uintptr_t)arch_xtensa_cached_ptr((void *)phys); + + valid = ((phys >= CONFIG_SRAM_BASE_ADDRESS) && + (phys < (CONFIG_SRAM_BASE_ADDRESS + (CONFIG_SRAM_SIZE * 1024UL)))); + + valid |= ((cached >= CONFIG_SRAM_BASE_ADDRESS) && + (cached < (CONFIG_SRAM_BASE_ADDRESS + (CONFIG_SRAM_SIZE * 1024UL)))); + + return valid; +} + +__weak bool sys_mm_is_virt_addr_in_range(void *virt) +{ + bool valid; + uintptr_t addr = (uintptr_t)virt; + + uintptr_t cached = (uintptr_t)arch_xtensa_cached_ptr(virt); + + valid = ((addr >= CONFIG_KERNEL_VM_BASE) && + (addr < (CONFIG_KERNEL_VM_BASE + CONFIG_KERNEL_VM_SIZE))); + + valid |= ((cached >= CONFIG_KERNEL_VM_BASE) && + (cached < (CONFIG_KERNEL_VM_BASE + CONFIG_KERNEL_VM_SIZE))); + + return valid; +} diff --git a/arch/xtensa/core/xtensa-asm2.c b/arch/xtensa/core/xtensa-asm2.c index cf032c3e98f..c2371ac8f55 100644 --- a/arch/xtensa/core/xtensa-asm2.c +++ b/arch/xtensa/core/xtensa-asm2.c @@ -122,7 +122,7 @@ void z_xtensa_dump_stack(const z_arch_esf_t *stack) LOG_ERR(" ** A0 %p SP %p A2 %p A3 %p", (void *)bsa->a0, - ((char *)bsa + sizeof(*bsa)), + (void *)((char *)bsa + sizeof(*bsa)), (void *)bsa->a2, (void *)bsa->a3); if (reg_blks_remaining > 0) { diff --git a/arch/xtensa/core/xtensa_backtrace.c b/arch/xtensa/core/xtensa_backtrace.c index 4f767f69042..e0abe09049b 100644 --- a/arch/xtensa/core/xtensa_backtrace.c +++ b/arch/xtensa/core/xtensa_backtrace.c @@ -11,6 +11,8 @@ #include "soc/soc_memory_layout.h" #elif defined(CONFIG_SOC_FAMILY_INTEL_ADSP) #include "debug_helpers.h" +#elif defined(CONFIG_SOC_XTENSA_DC233C) +#include "backtrace_helpers.h" #endif static int mask, cause; @@ -38,6 +40,8 @@ static inline bool z_xtensa_stack_ptr_is_sane(uint32_t sp) return esp_stack_ptr_is_sane(sp); #elif defined(CONFIG_SOC_FAMILY_INTEL_ADSP) return intel_adsp_ptr_is_sane(sp); +#elif defined(CONFIG_SOC_XTENSA_DC233C) + return xtensa_dc233c_stack_ptr_is_sane(sp); #else #warning "z_xtensa_stack_ptr_is_sane is not defined for this platform" #endif @@ -49,6 +53,8 @@ static inline bool z_xtensa_ptr_executable(const void *p) return esp_ptr_executable(p); #elif defined(CONFIG_SOC_FAMILY_INTEL_ADSP) return intel_adsp_ptr_executable(p); +#elif defined(CONFIG_SOC_XTENSA_DC233C) + return xtensa_dc233c_ptr_executable(p); #else #warning "z_xtensa_ptr_executable is not defined for this platform" #endif diff --git a/arch/xtensa/core/xtensa_mmu.c b/arch/xtensa/core/xtensa_mmu.c index c84d01b8337..e50c51a3848 100644 --- a/arch/xtensa/core/xtensa_mmu.c +++ b/arch/xtensa/core/xtensa_mmu.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/xtensa/include/kernel_arch_func.h b/arch/xtensa/include/kernel_arch_func.h index 44811a5b2a8..6427b306e62 100644 --- a/arch/xtensa/include/kernel_arch_func.h +++ b/arch/xtensa/include/kernel_arch_func.h @@ -70,7 +70,7 @@ static ALWAYS_INLINE void arch_kernel_init(void) void xtensa_switch(void *switch_to, void **switched_from); -static inline void arch_switch(void *switch_to, void **switched_from) +static ALWAYS_INLINE void arch_switch(void *switch_to, void **switched_from) { return xtensa_switch(switch_to, switched_from); } diff --git a/boards/Kconfig b/boards/Kconfig index fbab1e97d98..f56c2cab04e 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -111,6 +111,15 @@ config QEMU_GDBSERVER_LISTEN_DEV as the `QEMU_EXTRA_FLAGS` environment variable. Refer to application development doc and/or QEMU invocation doc for more info. +config QEMU_EXTRA_FLAGS + string "QEMU extra flags" + depends on QEMU_TARGET + default "" + help + This option is to pass onto QEMU an extra list of parameters + to setup devices, for example to allocate interface for Zephyr + GDBstub over serial with `-serial tcp:127.0.0.1:5678,server` + # There might not be any board options, hence the optional source osource "$(BOARD_DIR)/Kconfig" endmenu diff --git a/boards/arc/em_starterkit/em_starterkit.yaml b/boards/arc/em_starterkit/em_starterkit.yaml index f2590fcac76..f489b0a28ac 100644 --- a/boards/arc/em_starterkit/em_starterkit.yaml +++ b/boards/arc/em_starterkit/em_starterkit.yaml @@ -14,3 +14,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/em_starterkit/em_starterkit_em11d.yaml b/boards/arc/em_starterkit/em_starterkit_em11d.yaml index 7d8b863f4bb..f06dccbc8e7 100644 --- a/boards/arc/em_starterkit/em_starterkit_em11d.yaml +++ b/boards/arc/em_starterkit/em_starterkit_em11d.yaml @@ -14,3 +14,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/em_starterkit/em_starterkit_em7d.yaml b/boards/arc/em_starterkit/em_starterkit_em7d.yaml index 9d3e6d6cf7f..d4ab57393b4 100644 --- a/boards/arc/em_starterkit/em_starterkit_em7d.yaml +++ b/boards/arc/em_starterkit/em_starterkit_em7d.yaml @@ -14,3 +14,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/em_starterkit/em_starterkit_em7d_v22.yaml b/boards/arc/em_starterkit/em_starterkit_em7d_v22.yaml index 0b7d9de3127..b7eb883286f 100644 --- a/boards/arc/em_starterkit/em_starterkit_em7d_v22.yaml +++ b/boards/arc/em_starterkit/em_starterkit_em7d_v22.yaml @@ -14,3 +14,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/emsdp/emsdp.yaml b/boards/arc/emsdp/emsdp.yaml index 44de46e8a7a..b6fa38fb515 100644 --- a/boards/arc/emsdp/emsdp.yaml +++ b/boards/arc/emsdp/emsdp.yaml @@ -13,3 +13,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/emsdp/emsdp_em4.yaml b/boards/arc/emsdp/emsdp_em4.yaml index bd3757519d5..a146eb72bff 100644 --- a/boards/arc/emsdp/emsdp_em4.yaml +++ b/boards/arc/emsdp/emsdp_em4.yaml @@ -11,3 +11,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/emsdp/emsdp_em5d.yaml b/boards/arc/emsdp/emsdp_em5d.yaml index 5ab93b86d47..d0117790975 100644 --- a/boards/arc/emsdp/emsdp_em5d.yaml +++ b/boards/arc/emsdp/emsdp_em5d.yaml @@ -11,3 +11,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/emsdp/emsdp_em6.yaml b/boards/arc/emsdp/emsdp_em6.yaml index 804cdb91186..2584fb8a953 100644 --- a/boards/arc/emsdp/emsdp_em6.yaml +++ b/boards/arc/emsdp/emsdp_em6.yaml @@ -13,3 +13,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/emsdp/emsdp_em7d.yaml b/boards/arc/emsdp/emsdp_em7d.yaml index 3bf708259fc..57f78c3c7e7 100644 --- a/boards/arc/emsdp/emsdp_em7d.yaml +++ b/boards/arc/emsdp/emsdp_em7d.yaml @@ -11,3 +11,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/emsdp/emsdp_em7d_esp.yaml b/boards/arc/emsdp/emsdp_em7d_esp.yaml index cdf45ea786f..e3387d64798 100644 --- a/boards/arc/emsdp/emsdp_em7d_esp.yaml +++ b/boards/arc/emsdp/emsdp_em7d_esp.yaml @@ -13,3 +13,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/emsdp/emsdp_em9d.yaml b/boards/arc/emsdp/emsdp_em9d.yaml index d495ec11eb3..7bdf0340232 100644 --- a/boards/arc/emsdp/emsdp_em9d.yaml +++ b/boards/arc/emsdp/emsdp_em9d.yaml @@ -13,3 +13,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/hsdk/hsdk.yaml b/boards/arc/hsdk/hsdk.yaml index fba768d57d4..3547f1a313b 100644 --- a/boards/arc/hsdk/hsdk.yaml +++ b/boards/arc/hsdk/hsdk.yaml @@ -13,3 +13,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/hsdk/hsdk_2cores.yaml b/boards/arc/hsdk/hsdk_2cores.yaml index ea811866a28..d21fa765887 100644 --- a/boards/arc/hsdk/hsdk_2cores.yaml +++ b/boards/arc/hsdk/hsdk_2cores.yaml @@ -13,3 +13,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/hsdk4xd/hsdk4xd.yaml b/boards/arc/hsdk4xd/hsdk4xd.yaml index 053de272808..798d7be5f2b 100644 --- a/boards/arc/hsdk4xd/hsdk4xd.yaml +++ b/boards/arc/hsdk4xd/hsdk4xd.yaml @@ -13,3 +13,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/iotdk/iotdk.yaml b/boards/arc/iotdk/iotdk.yaml index 0f64c574bc4..5ec9fdc8d15 100644 --- a/boards/arc/iotdk/iotdk.yaml +++ b/boards/arc/iotdk/iotdk.yaml @@ -11,3 +11,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/nsim/doc/index.rst b/boards/arc/nsim/doc/index.rst index a95a2341aea..4e7054fc43b 100644 --- a/boards/arc/nsim/doc/index.rst +++ b/boards/arc/nsim/doc/index.rst @@ -33,6 +33,8 @@ available configurations are listed below: * ``nsim_vpx5`` - ARCv2 VPX5 core, close to vpx5_integer_full template * ``nsim_hs5x`` - 32-bit ARCv3 HS core with rich set of options * ``nsim_hs6x`` - 64-bit ARCv3 HS core with rich set of options +* ``nsim_hs5x_smp_12cores`` - SMP 12 cores 32-bit ARCv3 HS platform +* ``nsim_hs6x_smp_12cores`` - SMP 12 cores 64-bit ARCv3 HS platform .. _board_arc_nsim_prop_args_files: @@ -107,7 +109,7 @@ The supported toolchains are listed in ``toolchain:`` array in ``.yaml`` file, w particular toolchain. Use this configuration to run basic Zephyr applications and kernel tests in -nSIM, for example, with the :ref:`synchronization_sample`: +nSIM, for example, with the :zephyr:code-sample:`synchronization` sample: .. zephyr-app-commands:: :zephyr-app: samples/synchronization diff --git a/boards/arc/nsim/nsim_em.yaml b/boards/arc/nsim/nsim_em.yaml index 7df93725121..9eb0c88ad50 100644 --- a/boards/arc/nsim/nsim_em.yaml +++ b/boards/arc/nsim/nsim_em.yaml @@ -12,3 +12,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/nsim/nsim_em11d.yaml b/boards/arc/nsim/nsim_em11d.yaml index f88f0dbdc64..a37c9c3888d 100644 --- a/boards/arc/nsim/nsim_em11d.yaml +++ b/boards/arc/nsim/nsim_em11d.yaml @@ -12,3 +12,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/nsim/nsim_em7d_v22.yaml b/boards/arc/nsim/nsim_em7d_v22.yaml index 34ec2889029..036e9b37bae 100644 --- a/boards/arc/nsim/nsim_em7d_v22.yaml +++ b/boards/arc/nsim/nsim_em7d_v22.yaml @@ -11,3 +11,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/nsim/nsim_hs.yaml b/boards/arc/nsim/nsim_hs.yaml index 757fffa95e3..18f2a71039a 100644 --- a/boards/arc/nsim/nsim_hs.yaml +++ b/boards/arc/nsim/nsim_hs.yaml @@ -12,3 +12,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/nsim/nsim_hs3x_hostlink.yaml b/boards/arc/nsim/nsim_hs3x_hostlink.yaml index 4c7d60f42f5..f23cdc18501 100644 --- a/boards/arc/nsim/nsim_hs3x_hostlink.yaml +++ b/boards/arc/nsim/nsim_hs3x_hostlink.yaml @@ -12,3 +12,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/nsim/nsim_hs5x.yaml b/boards/arc/nsim/nsim_hs5x.yaml index 7572a51a294..14d6cf03f8e 100644 --- a/boards/arc/nsim/nsim_hs5x.yaml +++ b/boards/arc/nsim/nsim_hs5x.yaml @@ -12,3 +12,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/nsim/nsim_hs5x_smp.yaml b/boards/arc/nsim/nsim_hs5x_smp.yaml index 70bb7cdb84e..21015ecee69 100644 --- a/boards/arc/nsim/nsim_hs5x_smp.yaml +++ b/boards/arc/nsim/nsim_hs5x_smp.yaml @@ -15,3 +15,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/nsim/nsim_hs5x_smp_12cores.dts b/boards/arc/nsim/nsim_hs5x_smp_12cores.dts new file mode 100644 index 00000000000..b37b6de6fbf --- /dev/null +++ b/boards/arc/nsim/nsim_hs5x_smp_12cores.dts @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2023, Synopsys, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include "nsim-smp.dtsi" +#include "nsim-flat-mem.dtsi" + +/ { + model = "snps,nsim_hs"; + compatible = "snps,nsim_hs"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <0>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <1>; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <2>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <3>; + }; + + cpu@4 { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <4>; + }; + + cpu@5 { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <5>; + }; + + cpu@6 { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <6>; + }; + + cpu@7 { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <7>; + }; + + cpu@8 { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <8>; + }; + + cpu@9 { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <9>; + }; + + cpu@a { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <10>; + }; + + cpu@b { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <11>; + }; + }; +}; diff --git a/boards/arc/nsim/nsim_hs5x_smp_12cores.yaml b/boards/arc/nsim/nsim_hs5x_smp_12cores.yaml new file mode 100644 index 00000000000..416dcd2133d --- /dev/null +++ b/boards/arc/nsim/nsim_hs5x_smp_12cores.yaml @@ -0,0 +1,17 @@ +identifier: nsim_hs5x_smp_12cores +name: Multi-core HS5x nSIM simulator +type: sim +simulation: mdb-nsim +simulation_exec: mdb +arch: arc +toolchain: + - zephyr + - arcmwdt + - cross-compile +supported: + - smp +testing: + timeout_multiplier: 4 + ignore_tags: + - net + - bluetooth diff --git a/boards/arc/nsim/nsim_hs5x_smp_12cores_defconfig b/boards/arc/nsim/nsim_hs5x_smp_12cores_defconfig new file mode 100644 index 00000000000..1d146abff7f --- /dev/null +++ b/boards/arc/nsim/nsim_hs5x_smp_12cores_defconfig @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_ISA_ARCV3=y +CONFIG_SOC_NSIM=y +CONFIG_SOC_NSIM_HS5X_SMP=y +CONFIG_BOARD_NSIM=y +CONFIG_SYS_CLOCK_TICKS_PER_SEC=100 +CONFIG_XIP=n +CONFIG_BUILD_OUTPUT_BIN=n +CONFIG_ARCV2_INTERRUPT_UNIT=y +CONFIG_ARCV2_TIMER=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_ARC_EXCEPTION_DEBUG=y +CONFIG_SMP=y +CONFIG_MP_MAX_NUM_CPUS=12 +CONFIG_TICKET_SPINLOCKS=y diff --git a/boards/arc/nsim/nsim_hs5x_smp_defconfig b/boards/arc/nsim/nsim_hs5x_smp_defconfig index f4b6288b106..c801fe9430e 100644 --- a/boards/arc/nsim/nsim_hs5x_smp_defconfig +++ b/boards/arc/nsim/nsim_hs5x_smp_defconfig @@ -15,3 +15,4 @@ CONFIG_SERIAL=y CONFIG_ARC_EXCEPTION_DEBUG=y CONFIG_SMP=y CONFIG_MP_MAX_NUM_CPUS=2 +CONFIG_TICKET_SPINLOCKS=y diff --git a/boards/arc/nsim/nsim_hs6x.yaml b/boards/arc/nsim/nsim_hs6x.yaml index d2ed2ec1741..08b881eb743 100644 --- a/boards/arc/nsim/nsim_hs6x.yaml +++ b/boards/arc/nsim/nsim_hs6x.yaml @@ -12,3 +12,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/nsim/nsim_hs6x_smp.yaml b/boards/arc/nsim/nsim_hs6x_smp.yaml index 1b40e67483d..d05faa51b29 100644 --- a/boards/arc/nsim/nsim_hs6x_smp.yaml +++ b/boards/arc/nsim/nsim_hs6x_smp.yaml @@ -15,3 +15,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/nsim/nsim_hs6x_smp_12cores.dts b/boards/arc/nsim/nsim_hs6x_smp_12cores.dts new file mode 100644 index 00000000000..b37b6de6fbf --- /dev/null +++ b/boards/arc/nsim/nsim_hs6x_smp_12cores.dts @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2023, Synopsys, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include "nsim-smp.dtsi" +#include "nsim-flat-mem.dtsi" + +/ { + model = "snps,nsim_hs"; + compatible = "snps,nsim_hs"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <0>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <1>; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <2>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <3>; + }; + + cpu@4 { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <4>; + }; + + cpu@5 { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <5>; + }; + + cpu@6 { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <6>; + }; + + cpu@7 { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <7>; + }; + + cpu@8 { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <8>; + }; + + cpu@9 { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <9>; + }; + + cpu@a { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <10>; + }; + + cpu@b { + device_type = "cpu"; + compatible = "snps,arcv3-hs"; + reg = <11>; + }; + }; +}; diff --git a/boards/arc/nsim/nsim_hs6x_smp_12cores.yaml b/boards/arc/nsim/nsim_hs6x_smp_12cores.yaml new file mode 100644 index 00000000000..3113b84e8d6 --- /dev/null +++ b/boards/arc/nsim/nsim_hs6x_smp_12cores.yaml @@ -0,0 +1,17 @@ +identifier: nsim_hs6x_smp_12cores +name: Multi-core HS6x nSIM simulator +type: sim +simulation: mdb-nsim +simulation_exec: mdb +arch: arc +toolchain: + - cross-compile + - zephyr + - arcmwdt +supported: + - smp +testing: + timeout_multiplier: 4 + ignore_tags: + - net + - bluetooth diff --git a/boards/arc/nsim/nsim_hs6x_smp_12cores_defconfig b/boards/arc/nsim/nsim_hs6x_smp_12cores_defconfig new file mode 100644 index 00000000000..86793a594c7 --- /dev/null +++ b/boards/arc/nsim/nsim_hs6x_smp_12cores_defconfig @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_ISA_ARCV3=y +CONFIG_SOC_NSIM=y +CONFIG_SOC_NSIM_HS6X_SMP=y +CONFIG_BOARD_NSIM=y +CONFIG_SYS_CLOCK_TICKS_PER_SEC=100 +CONFIG_XIP=n +CONFIG_BUILD_OUTPUT_BIN=n +CONFIG_ARCV2_INTERRUPT_UNIT=y +CONFIG_ARCV2_TIMER=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_ARC_EXCEPTION_DEBUG=y +CONFIG_SMP=y +CONFIG_MP_MAX_NUM_CPUS=12 +CONFIG_TICKET_SPINLOCKS=y diff --git a/boards/arc/nsim/nsim_hs6x_smp_defconfig b/boards/arc/nsim/nsim_hs6x_smp_defconfig index 6cb2b160e1d..43085894396 100644 --- a/boards/arc/nsim/nsim_hs6x_smp_defconfig +++ b/boards/arc/nsim/nsim_hs6x_smp_defconfig @@ -15,3 +15,4 @@ CONFIG_SERIAL=y CONFIG_ARC_EXCEPTION_DEBUG=y CONFIG_SMP=y CONFIG_MP_MAX_NUM_CPUS=2 +CONFIG_TICKET_SPINLOCKS=y diff --git a/boards/arc/nsim/nsim_hs_flash_xip.yaml b/boards/arc/nsim/nsim_hs_flash_xip.yaml index 8ee16f6bdfd..02da85f5864 100644 --- a/boards/arc/nsim/nsim_hs_flash_xip.yaml +++ b/boards/arc/nsim/nsim_hs_flash_xip.yaml @@ -12,3 +12,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/nsim/nsim_hs_mpuv6.yaml b/boards/arc/nsim/nsim_hs_mpuv6.yaml index 2f25b48f9b9..cf1fdba06a7 100644 --- a/boards/arc/nsim/nsim_hs_mpuv6.yaml +++ b/boards/arc/nsim/nsim_hs_mpuv6.yaml @@ -13,3 +13,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/nsim/nsim_hs_smp.yaml b/boards/arc/nsim/nsim_hs_smp.yaml index e4d7a3c8397..ccc1fab694d 100644 --- a/boards/arc/nsim/nsim_hs_smp.yaml +++ b/boards/arc/nsim/nsim_hs_smp.yaml @@ -16,3 +16,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/nsim/nsim_hs_smp_defconfig b/boards/arc/nsim/nsim_hs_smp_defconfig index 24b1914760b..b07bc87ed41 100644 --- a/boards/arc/nsim/nsim_hs_smp_defconfig +++ b/boards/arc/nsim/nsim_hs_smp_defconfig @@ -14,3 +14,4 @@ CONFIG_SERIAL=y CONFIG_ARC_EXCEPTION_DEBUG=y CONFIG_SMP=y CONFIG_MP_MAX_NUM_CPUS=2 +CONFIG_TICKET_SPINLOCKS=y diff --git a/boards/arc/nsim/nsim_hs_sram.yaml b/boards/arc/nsim/nsim_hs_sram.yaml index 0d17dd55ff3..7a99a91ceff 100644 --- a/boards/arc/nsim/nsim_hs_sram.yaml +++ b/boards/arc/nsim/nsim_hs_sram.yaml @@ -12,3 +12,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/nsim/nsim_sem.yaml b/boards/arc/nsim/nsim_sem.yaml index 3f33ce0392b..13afb56ca69 100644 --- a/boards/arc/nsim/nsim_sem.yaml +++ b/boards/arc/nsim/nsim_sem.yaml @@ -13,3 +13,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/nsim/nsim_sem_mpu_stack_guard.yaml b/boards/arc/nsim/nsim_sem_mpu_stack_guard.yaml index 58baff5e916..45949212a00 100644 --- a/boards/arc/nsim/nsim_sem_mpu_stack_guard.yaml +++ b/boards/arc/nsim/nsim_sem_mpu_stack_guard.yaml @@ -12,3 +12,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/nsim/nsim_vpx5.yaml b/boards/arc/nsim/nsim_vpx5.yaml index 585a107c3b0..4d5a3c8e96e 100644 --- a/boards/arc/nsim/nsim_vpx5.yaml +++ b/boards/arc/nsim/nsim_vpx5.yaml @@ -10,3 +10,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/nsim/support/mdb_hs5x_smp_12cores.args b/boards/arc/nsim/support/mdb_hs5x_smp_12cores.args new file mode 100644 index 00000000000..f1eb7cdcc9b --- /dev/null +++ b/boards/arc/nsim/support/mdb_hs5x_smp_12cores.args @@ -0,0 +1,65 @@ +-arcv3hs +-core0 +-Xdual_issue +-uarch_rev=0:0 +-rgf_num_banks=1 +-rgf_num_wr_ports=2 +-lpc_width=0 +-Xatomic=2 +-Xll64 +-Xunaligned +-Xdiv_rem=radix4 +-Xmpy_option=qmpyh +-Xtimer0 +-Xtimer0_level=0 +-Xtimer1 +-Xtimer1_level=0 +-Xrtc +-action_points=8 +-ap_feature=1 +-Xstack_check +-bpu_bc_entries=2048 +-bpu_pt_entries=16384 +-bpu_rs_entries=4 +-bpu_bc_full_tag=1 +-bpu_tosq_entries=5 +-bpu_fb_entries=2 +-bpu_debug +-smart_version=4 +-smart_stack_entries=8 +-mmuv16 +-mmu_dtlb_entries=16 +-mmu_itlb_entries=16 +-mmu_l2tlb_entries=2048 +-mmu_pgsz=4K +-mmu_address_space=32 +-interrupts=32 +-interrupt_priorities=2 +-ext_interrupts=27 +-interrupt_base=0x0 +-dcache=32768,64,2,a +-dcache_version=5 +-dcache_feature=2 +-dcache_mem_cycles=1 +-dcache_hw_prefetch +-icache=32768,64,4,a +-icache_version=6 +-icache_feature=2 +-Xpct_counters=8 +-Xpct_interrupt +-cluster_version=32 +-arconnect +-connect_ics=1 +-connect_ics_num_semas=16 +-connect_icm=1 +-connect_icm_sram_size=512 +-connect_icm_sram_prot=none +-connect_pmu=1 +-connect_idu=2 +-connect_idu_cirqnum=64 +-connect_gfrc=3 +-connect_icd=2 +-connect_ici=2 +-noprofile +-prop=nsim_mem-dev=uart0,kind=dwuart,base=0xf0000000,irq=24 +-instrs_per_pass=512 diff --git a/boards/arc/nsim/support/mdb_hs6x_smp_12cores.args b/boards/arc/nsim/support/mdb_hs6x_smp_12cores.args new file mode 100644 index 00000000000..56722052471 --- /dev/null +++ b/boards/arc/nsim/support/mdb_hs6x_smp_12cores.args @@ -0,0 +1,64 @@ + -arc64 + -core0 + -Xdual_issue + -uarch_rev=0:0 + -rgf_num_banks=1 + -rgf_num_wr_ports=2 + -Xm128 + -Xatomic=2 + -Xunaligned + -Xmpy_cycles=3 + -Xtimer0 + -Xtimer0_level=0 + -Xtimer1 + -Xtimer1_level=0 + -Xrtc + -action_points=8 + -ap_feature=1 + -Xstack_check + -bpu_bc_entries=2048 + -bpu_pt_entries=16384 + -bpu_rs_entries=4 + -bpu_bc_full_tag=1 + -bpu_tosq_entries=5 + -bpu_fb_entries=2 + -bpu_debug + -smart_version=5 + -smart_stack_entries=8 + -mmuv16 + -mmu_dtlb_entries=16 + -mmu_itlb_entries=16 + -mmu_l2tlb_entries=2048 + -mmu_pgsz=4K + -mmu_address_space=48 + -interrupts=32 + -interrupt_priorities=2 + -ext_interrupts=27 + -interrupt_base=0x0 + -dcache=32768,64,2,a + -dcache_version=5 + -dcache_feature=2 + -dcache_mem_cycles=1 + -dcache_hw_prefetch + -icache=32768,64,4,a + -icache_version=6 + -icache_feature=2 + -Xpct_counters=8 + -Xpct_interrupt + -cluster_version=32 + -arconnect + -connect_ics=1 + -connect_ics_num_semas=16 + -connect_icm=1 + -connect_icm_sram_size=512 + -connect_icm_sram_prot=none + -connect_pmu=1 + -connect_idu=2 + -connect_idu_cirqnum=64 + -connect_gfrc=3 + -connect_icd=2 + -connect_ici=2 + -nogoifmain + -noprofile + -prop=nsim_mem-dev=uart0,kind=dwuart,base=0xf0000000,irq=24 + -instrs_per_pass=512 diff --git a/boards/arc/qemu_arc/doc/index.rst b/boards/arc/qemu_arc/doc/index.rst index e2174fc2c27..5a0857edc41 100644 --- a/boards/arc/qemu_arc/doc/index.rst +++ b/boards/arc/qemu_arc/doc/index.rst @@ -67,7 +67,7 @@ Programming and Debugging ************************* Use this configuration to run basic Zephyr applications and kernel tests in the QEMU -emulated environment, for example, with the :ref:`synchronization_sample` +emulated environment, for example, with the :zephyr:code-sample:`synchronization` sample (note you may use ``qemu_arc_em``, ``qemu_arc_hs``, ``qemu_arc_hs5x`` or ``qemu_arc_hs6x`` depending on target CPU): diff --git a/boards/arc/qemu_arc/qemu_arc_em.dts b/boards/arc/qemu_arc/qemu_arc_em.dts index 290f7eb7308..53ec3c2c38f 100644 --- a/boards/arc/qemu_arc/qemu_arc_em.dts +++ b/boards/arc/qemu_arc/qemu_arc_em.dts @@ -10,7 +10,7 @@ / { model = "QEMU ARC EM"; - compatible = "qemu,arcem"; + compatible = "snps,qemu-arcem"; cpus { #address-cells = <1>; diff --git a/boards/arc/qemu_arc/qemu_arc_em.yaml b/boards/arc/qemu_arc/qemu_arc_em.yaml index d9bcc21f2e5..2c1db9ed374 100644 --- a/boards/arc/qemu_arc/qemu_arc_em.yaml +++ b/boards/arc/qemu_arc/qemu_arc_em.yaml @@ -11,3 +11,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/qemu_arc/qemu_arc_hs.dts b/boards/arc/qemu_arc/qemu_arc_hs.dts index 751e42ea1ad..0148a83b983 100644 --- a/boards/arc/qemu_arc/qemu_arc_hs.dts +++ b/boards/arc/qemu_arc/qemu_arc_hs.dts @@ -10,7 +10,7 @@ / { model = "QEMU ARC HS"; - compatible = "qemu,archs"; + compatible = "snps,qemu-archs"; cpus { #address-cells = <1>; diff --git a/boards/arc/qemu_arc/qemu_arc_hs.yaml b/boards/arc/qemu_arc/qemu_arc_hs.yaml index 05b4428710f..468b3a05215 100644 --- a/boards/arc/qemu_arc/qemu_arc_hs.yaml +++ b/boards/arc/qemu_arc/qemu_arc_hs.yaml @@ -12,3 +12,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/qemu_arc/qemu_arc_hs5x.dts b/boards/arc/qemu_arc/qemu_arc_hs5x.dts index 3ed53dc2769..dad6f805bc6 100644 --- a/boards/arc/qemu_arc/qemu_arc_hs5x.dts +++ b/boards/arc/qemu_arc/qemu_arc_hs5x.dts @@ -10,7 +10,7 @@ / { model = "QEMU ARC HS"; - compatible = "qemu,archs"; + compatible = "snps,qemu-archs"; cpus { #address-cells = <1>; diff --git a/boards/arc/qemu_arc/qemu_arc_hs5x.yaml b/boards/arc/qemu_arc/qemu_arc_hs5x.yaml index 29e57d185fd..0abe51e0472 100644 --- a/boards/arc/qemu_arc/qemu_arc_hs5x.yaml +++ b/boards/arc/qemu_arc/qemu_arc_hs5x.yaml @@ -11,3 +11,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/qemu_arc/qemu_arc_hs6x.dts b/boards/arc/qemu_arc/qemu_arc_hs6x.dts index 751e42ea1ad..0148a83b983 100644 --- a/boards/arc/qemu_arc/qemu_arc_hs6x.dts +++ b/boards/arc/qemu_arc/qemu_arc_hs6x.dts @@ -10,7 +10,7 @@ / { model = "QEMU ARC HS"; - compatible = "qemu,archs"; + compatible = "snps,qemu-archs"; cpus { #address-cells = <1>; diff --git a/boards/arc/qemu_arc/qemu_arc_hs6x.yaml b/boards/arc/qemu_arc/qemu_arc_hs6x.yaml index 6c8d0c1102f..5346dbc1251 100644 --- a/boards/arc/qemu_arc/qemu_arc_hs6x.yaml +++ b/boards/arc/qemu_arc/qemu_arc_hs6x.yaml @@ -11,3 +11,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arc/qemu_arc/qemu_arc_hs_xip.dts b/boards/arc/qemu_arc/qemu_arc_hs_xip.dts index 3ed53dc2769..dad6f805bc6 100644 --- a/boards/arc/qemu_arc/qemu_arc_hs_xip.dts +++ b/boards/arc/qemu_arc/qemu_arc_hs_xip.dts @@ -10,7 +10,7 @@ / { model = "QEMU ARC HS"; - compatible = "qemu,archs"; + compatible = "snps,qemu-archs"; cpus { #address-cells = <1>; diff --git a/boards/arc/qemu_arc/qemu_arc_hs_xip.yaml b/boards/arc/qemu_arc/qemu_arc_hs_xip.yaml index 65203386eed..829045078d2 100644 --- a/boards/arc/qemu_arc/qemu_arc_hs_xip.yaml +++ b/boards/arc/qemu_arc/qemu_arc_hs_xip.yaml @@ -11,3 +11,4 @@ testing: ignore_tags: - net - bluetooth +vendor: snps diff --git a/boards/arm/96b_aerocore2/96b_aerocore2.yaml b/boards/arm/96b_aerocore2/96b_aerocore2.yaml index d2ea3962b12..b066c364322 100644 --- a/boards/arm/96b_aerocore2/96b_aerocore2.yaml +++ b/boards/arm/96b_aerocore2/96b_aerocore2.yaml @@ -19,3 +19,4 @@ supported: - adc ram: 256 flash: 2048 +vendor: gumstix diff --git a/boards/arm/96b_aerocore2/doc/index.rst b/boards/arm/96b_aerocore2/doc/index.rst index fbfee1f0081..6d56911c2f1 100644 --- a/boards/arm/96b_aerocore2/doc/index.rst +++ b/boards/arm/96b_aerocore2/doc/index.rst @@ -330,7 +330,7 @@ Replace :code:`` with the port where the board 96Boards Aerocore2 can be found. For example, under Linux, :code:`/dev/ttyUSB0`. The ``-b`` option sets baud rate ignoring the value from config. -Press the Reset button and you should see the the following message in your +Press the Reset button and you should see the following message in your terminal: .. code-block:: console @@ -347,4 +347,4 @@ terminal: http://dfu-util.sourceforge.net/build.html .. _AN2606: - http://www.st.com/content/ccc/resource/technical/document/application_note/b9/9b/16/3a/12/1e/40/0c/CD00167594.pdf/files/CD00167594.pdf/jcr:content/translations/en.CD00167594.pdf + https://www.st.com/content/ccc/resource/technical/document/application_note/b9/9b/16/3a/12/1e/40/0c/CD00167594.pdf/files/CD00167594.pdf/jcr:content/translations/en.CD00167594.pdf diff --git a/boards/arm/96b_argonkey/doc/index.rst b/boards/arm/96b_argonkey/doc/index.rst index 0cbed592156..6221adee72c 100644 --- a/boards/arm/96b_argonkey/doc/index.rst +++ b/boards/arm/96b_argonkey/doc/index.rst @@ -234,7 +234,7 @@ References https://sourceforge.net/p/stm32flash/wiki/Home/ .. _ST-LINK/V2: - http://www.st.com/en/development-tools/st-link-v2.html + https://www.st.com/en/development-tools/st-link-v2.html .. _TTL-232RG: http://www.ftdichip.com/Support/Documents/DataSheets/Cables/DS_TTL-232RG_CABLES.pdf diff --git a/boards/arm/96b_avenger96/96b_avenger96.yaml b/boards/arm/96b_avenger96/96b_avenger96.yaml index 2b1c86243ef..e1e21e4d4c7 100644 --- a/boards/arm/96b_avenger96/96b_avenger96.yaml +++ b/boards/arm/96b_avenger96/96b_avenger96.yaml @@ -22,3 +22,4 @@ testing: - nfc ram: 256 flash: 64 +vendor: arrow diff --git a/boards/arm/96b_carbon/96b_carbon.yaml b/boards/arm/96b_carbon/96b_carbon.yaml index 53bb4aa953f..3b465d9e676 100644 --- a/boards/arm/96b_carbon/96b_carbon.yaml +++ b/boards/arm/96b_carbon/96b_carbon.yaml @@ -15,3 +15,4 @@ supported: - usb_device ram: 96 flash: 512 +vendor: seeed diff --git a/boards/arm/96b_carbon/doc/index.rst b/boards/arm/96b_carbon/doc/index.rst index 608e77e2b42..7b63bb20de9 100644 --- a/boards/arm/96b_carbon/doc/index.rst +++ b/boards/arm/96b_carbon/doc/index.rst @@ -318,7 +318,7 @@ Replace :code:`` with the port where the board 96Boards Carbon can be found. For example, under Linux, :code:`/dev/ttyUSB0`. The ``-b`` option sets baud rate ignoring the value from config. -Press the Reset button and you should see the the following message in your +Press the Reset button and you should see the following message in your terminal: .. code-block:: console @@ -369,16 +369,16 @@ STM32F401RET using an SWD scan. http://dfu-util.sourceforge.net/build.html .. _AN2606: - http://www.st.com/content/ccc/resource/technical/document/application_note/b9/9b/16/3a/12/1e/40/0c/CD00167594.pdf/files/CD00167594.pdf/jcr:content/translations/en.CD00167594.pdf + https://www.st.com/content/ccc/resource/technical/document/application_note/b9/9b/16/3a/12/1e/40/0c/CD00167594.pdf/files/CD00167594.pdf/jcr:content/translations/en.CD00167594.pdf .. _96Boards website: http://www.96boards.org/documentation .. _STM32F401RE on www.st.com: - http://www.st.com/en/microcontrollers/stm32f401re.html + https://www.st.com/en/microcontrollers/stm32f401re.html .. _STM32F401 reference manual: - http://www.st.com/resource/en/reference_manual/dm00096844.pdf + https://www.st.com/resource/en/reference_manual/dm00096844.pdf .. _96Boards IE Specification: https://linaro.co/ie-specification diff --git a/boards/arm/96b_carbon_nrf51/96b_carbon_nrf51.yaml b/boards/arm/96b_carbon_nrf51/96b_carbon_nrf51.yaml index e83f8cdf140..5ae43e121c7 100644 --- a/boards/arm/96b_carbon_nrf51/96b_carbon_nrf51.yaml +++ b/boards/arm/96b_carbon_nrf51/96b_carbon_nrf51.yaml @@ -10,3 +10,4 @@ toolchain: - xtools supported: - ble +vendor: seeed diff --git a/boards/arm/96b_carbon_nrf51/96b_carbon_nrf51_defconfig b/boards/arm/96b_carbon_nrf51/96b_carbon_nrf51_defconfig index 91a90e7986a..e53e9565e4a 100644 --- a/boards/arm/96b_carbon_nrf51/96b_carbon_nrf51_defconfig +++ b/boards/arm/96b_carbon_nrf51/96b_carbon_nrf51_defconfig @@ -12,5 +12,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/96b_meerkat96/96b_meerkat96.yaml b/boards/arm/96b_meerkat96/96b_meerkat96.yaml index fe13eb1fe22..b06b2ef5268 100644 --- a/boards/arm/96b_meerkat96/96b_meerkat96.yaml +++ b/boards/arm/96b_meerkat96/96b_meerkat96.yaml @@ -21,3 +21,4 @@ testing: ignore_tags: - net - bluetooth +vendor: novtech diff --git a/boards/arm/96b_nitrogen/96b_nitrogen.yaml b/boards/arm/96b_nitrogen/96b_nitrogen.yaml index c3ad4157aed..12b1f6c73e1 100644 --- a/boards/arm/96b_nitrogen/96b_nitrogen.yaml +++ b/boards/arm/96b_nitrogen/96b_nitrogen.yaml @@ -13,3 +13,4 @@ supported: - spi ram: 64 flash: 512 +vendor: seeed diff --git a/boards/arm/96b_nitrogen/96b_nitrogen_defconfig b/boards/arm/96b_nitrogen/96b_nitrogen_defconfig index e804b43da5c..b8565973eb1 100644 --- a/boards/arm/96b_nitrogen/96b_nitrogen_defconfig +++ b/boards/arm/96b_nitrogen/96b_nitrogen_defconfig @@ -15,5 +15,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/96b_nitrogen/doc/index.rst b/boards/arm/96b_nitrogen/doc/index.rst index 86e08e96ccf..ea971f093a8 100644 --- a/boards/arm/96b_nitrogen/doc/index.rst +++ b/boards/arm/96b_nitrogen/doc/index.rst @@ -292,7 +292,7 @@ Replace :code:`` with the port where the board 96Boards Nitrogen can be found. For example, under Linux, :code:`/dev/ttyACM0`. The ``-b`` option sets baud rate ignoring the value from config. -Press the Reset button and you should see the the following message in your +Press the Reset button and you should see the following message in your terminal: .. code-block:: console diff --git a/boards/arm/96b_stm32_sensor_mez/96b_stm32_sensor_mez.yaml b/boards/arm/96b_stm32_sensor_mez/96b_stm32_sensor_mez.yaml index e0fc7bd2db4..160bb802380 100644 --- a/boards/arm/96b_stm32_sensor_mez/96b_stm32_sensor_mez.yaml +++ b/boards/arm/96b_stm32_sensor_mez/96b_stm32_sensor_mez.yaml @@ -12,3 +12,4 @@ supported: - i2c - spi - counter +vendor: st diff --git a/boards/arm/96b_stm32_sensor_mez/doc/index.rst b/boards/arm/96b_stm32_sensor_mez/doc/index.rst index 1160777bb0f..95d11d2bacc 100644 --- a/boards/arm/96b_stm32_sensor_mez/doc/index.rst +++ b/boards/arm/96b_stm32_sensor_mez/doc/index.rst @@ -242,7 +242,7 @@ References https://www.96boards.org/documentation/mezzanine/stm32/ .. _STM32F446VE on www.st.com: - http://www.st.com/en/microcontrollers/stm32f446ve.html + https://www.st.com/en/microcontrollers/stm32f446ve.html .. _STM32F446 reference manual: - http://www.st.com/resource/en/reference_manual/dm00135183.pdf + https://www.st.com/resource/en/reference_manual/dm00135183.pdf diff --git a/boards/arm/acn52832/acn52832_defconfig b/boards/arm/acn52832/acn52832_defconfig index 2bb13882f8c..d35096cdd6e 100644 --- a/boards/arm/acn52832/acn52832_defconfig +++ b/boards/arm/acn52832/acn52832_defconfig @@ -16,5 +16,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/actinius_icarus/actinius_icarus.yaml b/boards/arm/actinius_icarus/actinius_icarus.yaml index 960c1c9704e..d547560af6f 100644 --- a/boards/arm/actinius_icarus/actinius_icarus.yaml +++ b/boards/arm/actinius_icarus/actinius_icarus.yaml @@ -20,3 +20,4 @@ supported: - feather_spi - arduino_i2c - arduino_spi +vendor: actinius diff --git a/boards/arm/actinius_icarus/actinius_icarus_defconfig b/boards/arm/actinius_icarus/actinius_icarus_defconfig index 6e00f057830..58d15739a95 100644 --- a/boards/arm/actinius_icarus/actinius_icarus_defconfig +++ b/boards/arm/actinius_icarus/actinius_icarus_defconfig @@ -22,5 +22,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/actinius_icarus/actinius_icarus_ns.yaml b/boards/arm/actinius_icarus/actinius_icarus_ns.yaml index 57eef9a4849..7fe1ea2ef47 100644 --- a/boards/arm/actinius_icarus/actinius_icarus_ns.yaml +++ b/boards/arm/actinius_icarus/actinius_icarus_ns.yaml @@ -20,3 +20,4 @@ supported: - feather_spi - arduino_i2c - arduino_spi +vendor: actinius diff --git a/boards/arm/actinius_icarus/actinius_icarus_ns_defconfig b/boards/arm/actinius_icarus/actinius_icarus_ns_defconfig index 2eafce1cfb6..e2e6e11584b 100644 --- a/boards/arm/actinius_icarus/actinius_icarus_ns_defconfig +++ b/boards/arm/actinius_icarus/actinius_icarus_ns_defconfig @@ -25,5 +25,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/actinius_icarus_bee/actinius_icarus_bee.yaml b/boards/arm/actinius_icarus_bee/actinius_icarus_bee.yaml index be2865ea3ac..87052c0a149 100644 --- a/boards/arm/actinius_icarus_bee/actinius_icarus_bee.yaml +++ b/boards/arm/actinius_icarus_bee/actinius_icarus_bee.yaml @@ -15,3 +15,4 @@ supported: - spi - watchdog - counter +vendor: actinius diff --git a/boards/arm/actinius_icarus_bee/actinius_icarus_bee_defconfig b/boards/arm/actinius_icarus_bee/actinius_icarus_bee_defconfig index 504bbcadae5..64de49c899b 100644 --- a/boards/arm/actinius_icarus_bee/actinius_icarus_bee_defconfig +++ b/boards/arm/actinius_icarus_bee/actinius_icarus_bee_defconfig @@ -22,5 +22,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/actinius_icarus_bee/actinius_icarus_bee_ns.yaml b/boards/arm/actinius_icarus_bee/actinius_icarus_bee_ns.yaml index d4f50773719..6255c80c010 100644 --- a/boards/arm/actinius_icarus_bee/actinius_icarus_bee_ns.yaml +++ b/boards/arm/actinius_icarus_bee/actinius_icarus_bee_ns.yaml @@ -15,3 +15,4 @@ supported: - spi - watchdog - counter +vendor: actinius diff --git a/boards/arm/actinius_icarus_bee/actinius_icarus_bee_ns_defconfig b/boards/arm/actinius_icarus_bee/actinius_icarus_bee_ns_defconfig index 73e3c4a84ce..7e0d1c6e2df 100644 --- a/boards/arm/actinius_icarus_bee/actinius_icarus_bee_ns_defconfig +++ b/boards/arm/actinius_icarus_bee/actinius_icarus_bee_ns_defconfig @@ -25,5 +25,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/actinius_icarus_som/actinius_icarus_som.yaml b/boards/arm/actinius_icarus_som/actinius_icarus_som.yaml index e2d4a2b1903..db7c14011b5 100644 --- a/boards/arm/actinius_icarus_som/actinius_icarus_som.yaml +++ b/boards/arm/actinius_icarus_som/actinius_icarus_som.yaml @@ -14,3 +14,4 @@ supported: - pwm - watchdog - counter +vendor: actinius diff --git a/boards/arm/actinius_icarus_som/actinius_icarus_som_defconfig b/boards/arm/actinius_icarus_som/actinius_icarus_som_defconfig index e51d63709b9..b2bbfdba52d 100644 --- a/boards/arm/actinius_icarus_som/actinius_icarus_som_defconfig +++ b/boards/arm/actinius_icarus_som/actinius_icarus_som_defconfig @@ -22,5 +22,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/actinius_icarus_som/actinius_icarus_som_ns.yaml b/boards/arm/actinius_icarus_som/actinius_icarus_som_ns.yaml index 84e46877826..6f4d731867d 100644 --- a/boards/arm/actinius_icarus_som/actinius_icarus_som_ns.yaml +++ b/boards/arm/actinius_icarus_som/actinius_icarus_som_ns.yaml @@ -14,3 +14,4 @@ supported: - pwm - watchdog - counter +vendor: actinius diff --git a/boards/arm/actinius_icarus_som/actinius_icarus_som_ns_defconfig b/boards/arm/actinius_icarus_som/actinius_icarus_som_ns_defconfig index 6ebb20a5994..81712f3aa1f 100644 --- a/boards/arm/actinius_icarus_som/actinius_icarus_som_ns_defconfig +++ b/boards/arm/actinius_icarus_som/actinius_icarus_som_ns_defconfig @@ -25,5 +25,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/actinius_icarus_som_dk/actinius_icarus_som_dk.yaml b/boards/arm/actinius_icarus_som_dk/actinius_icarus_som_dk.yaml index f0448ccdb30..aea5ef27753 100644 --- a/boards/arm/actinius_icarus_som_dk/actinius_icarus_som_dk.yaml +++ b/boards/arm/actinius_icarus_som_dk/actinius_icarus_som_dk.yaml @@ -19,3 +19,4 @@ supported: - arduino_i2c - arduino_serial - arduino_spi +vendor: actinius diff --git a/boards/arm/actinius_icarus_som_dk/actinius_icarus_som_dk_defconfig b/boards/arm/actinius_icarus_som_dk/actinius_icarus_som_dk_defconfig index b62a72cf708..2542dbb901e 100644 --- a/boards/arm/actinius_icarus_som_dk/actinius_icarus_som_dk_defconfig +++ b/boards/arm/actinius_icarus_som_dk/actinius_icarus_som_dk_defconfig @@ -22,5 +22,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/actinius_icarus_som_dk/actinius_icarus_som_dk_ns.yaml b/boards/arm/actinius_icarus_som_dk/actinius_icarus_som_dk_ns.yaml index 1d966832c87..2ecf72e7a57 100644 --- a/boards/arm/actinius_icarus_som_dk/actinius_icarus_som_dk_ns.yaml +++ b/boards/arm/actinius_icarus_som_dk/actinius_icarus_som_dk_ns.yaml @@ -19,3 +19,4 @@ supported: - arduino_i2c - arduino_serial - arduino_spi +vendor: actinius diff --git a/boards/arm/actinius_icarus_som_dk/actinius_icarus_som_dk_ns_defconfig b/boards/arm/actinius_icarus_som_dk/actinius_icarus_som_dk_ns_defconfig index 77d7eac9e7e..212dd785cd2 100644 --- a/boards/arm/actinius_icarus_som_dk/actinius_icarus_som_dk_ns_defconfig +++ b/boards/arm/actinius_icarus_som_dk/actinius_icarus_som_dk_ns_defconfig @@ -25,5 +25,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/adafruit_feather_m0_basic_proto/adafruit_feather_m0_basic_proto.dts b/boards/arm/adafruit_feather_m0_basic_proto/adafruit_feather_m0_basic_proto.dts index df83c6d6ddd..8d98095e703 100644 --- a/boards/arm/adafruit_feather_m0_basic_proto/adafruit_feather_m0_basic_proto.dts +++ b/boards/arm/adafruit_feather_m0_basic_proto/adafruit_feather_m0_basic_proto.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include #include "adafruit_feather_m0_basic_proto-pinctrl.dtsi" #include "feather_connector.dtsi" diff --git a/boards/arm/adafruit_feather_m0_basic_proto/adafruit_feather_m0_basic_proto.yaml b/boards/arm/adafruit_feather_m0_basic_proto/adafruit_feather_m0_basic_proto.yaml index cd413794323..859ae9feb17 100644 --- a/boards/arm/adafruit_feather_m0_basic_proto/adafruit_feather_m0_basic_proto.yaml +++ b/boards/arm/adafruit_feather_m0_basic_proto/adafruit_feather_m0_basic_proto.yaml @@ -8,3 +8,4 @@ toolchain: - zephyr - gnuarmemb - xtools +vendor: adafruit diff --git a/boards/arm/adafruit_feather_m0_basic_proto/doc/index.rst b/boards/arm/adafruit_feather_m0_basic_proto/doc/index.rst index 0e1943db6ff..4b1af3d8d49 100644 --- a/boards/arm/adafruit_feather_m0_basic_proto/doc/index.rst +++ b/boards/arm/adafruit_feather_m0_basic_proto/doc/index.rst @@ -97,7 +97,7 @@ USB Device Port The SAMD21 MCU has a USB device port that can be used to communicate with a host PC. See the :ref:`usb-samples` sample applications for -more, such as the :ref:`usb_cdc-acm` sample which sets up a virtual +more, such as the :zephyr:code-sample:`usb-cdc-acm` sample which sets up a virtual serial port that echos characters back to the host PC. Programming and Debugging diff --git a/boards/arm/adafruit_feather_m0_lora/adafruit_feather_m0_lora.dts b/boards/arm/adafruit_feather_m0_lora/adafruit_feather_m0_lora.dts index ac62ebca4f4..c69f547622c 100644 --- a/boards/arm/adafruit_feather_m0_lora/adafruit_feather_m0_lora.dts +++ b/boards/arm/adafruit_feather_m0_lora/adafruit_feather_m0_lora.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include #include "adafruit_feather_m0_lora-pinctrl.dtsi" #include "feather_connector.dtsi" diff --git a/boards/arm/adafruit_feather_m0_lora/adafruit_feather_m0_lora.yaml b/boards/arm/adafruit_feather_m0_lora/adafruit_feather_m0_lora.yaml index c3f13456776..de9b44f8820 100644 --- a/boards/arm/adafruit_feather_m0_lora/adafruit_feather_m0_lora.yaml +++ b/boards/arm/adafruit_feather_m0_lora/adafruit_feather_m0_lora.yaml @@ -8,3 +8,4 @@ toolchain: - zephyr - gnuarmemb - xtools +vendor: adafruit diff --git a/boards/arm/adafruit_feather_m0_lora/doc/index.rst b/boards/arm/adafruit_feather_m0_lora/doc/index.rst index 5aa85132689..154feb14539 100644 --- a/boards/arm/adafruit_feather_m0_lora/doc/index.rst +++ b/boards/arm/adafruit_feather_m0_lora/doc/index.rst @@ -100,7 +100,7 @@ USB Device Port The SAMD21 MCU has a USB device port that can be used to communicate with a host PC. See the :ref:`usb-samples` sample applications for -more, such as the :ref:`usb_cdc-acm` sample which sets up a virtual +more, such as the :zephyr:code-sample:`usb-cdc-acm` sample which sets up a virtual serial port that echos characters back to the host PC. LoRa Radio diff --git a/boards/arm/adafruit_feather_nrf52840/adafruit_feather_nrf52840.dts b/boards/arm/adafruit_feather_nrf52840/adafruit_feather_nrf52840.dts index 284a4d24542..2333e5becbe 100644 --- a/boards/arm/adafruit_feather_nrf52840/adafruit_feather_nrf52840.dts +++ b/boards/arm/adafruit_feather_nrf52840/adafruit_feather_nrf52840.dts @@ -47,6 +47,13 @@ }; }; + vbatt { + compatible = "voltage-divider"; + io-channels = <&adc 5>; + output-ohms = <100000>; + full-ohms = <(100000 + 100000)>; + }; + /* These aliases are provided for compatibility with samples */ aliases { led0 = &led0; diff --git a/boards/arm/adafruit_feather_nrf52840/adafruit_feather_nrf52840.yaml b/boards/arm/adafruit_feather_nrf52840/adafruit_feather_nrf52840.yaml index fde385eea8c..f626fd46a4a 100644 --- a/boards/arm/adafruit_feather_nrf52840/adafruit_feather_nrf52840.yaml +++ b/boards/arm/adafruit_feather_nrf52840/adafruit_feather_nrf52840.yaml @@ -16,3 +16,4 @@ supported: - feather_serial - feather_i2c - feather_spi +vendor: adafruit diff --git a/boards/arm/adafruit_feather_nrf52840/adafruit_feather_nrf52840_defconfig b/boards/arm/adafruit_feather_nrf52840/adafruit_feather_nrf52840_defconfig index 1f42d1a0aa4..74b11931eb8 100644 --- a/boards/arm/adafruit_feather_nrf52840/adafruit_feather_nrf52840_defconfig +++ b/boards/arm/adafruit_feather_nrf52840/adafruit_feather_nrf52840_defconfig @@ -16,5 +16,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/adafruit_feather_nrf52840/doc/index.rst b/boards/arm/adafruit_feather_nrf52840/doc/index.rst index d198ec9e337..6d4af8ca296 100644 --- a/boards/arm/adafruit_feather_nrf52840/doc/index.rst +++ b/boards/arm/adafruit_feather_nrf52840/doc/index.rst @@ -113,7 +113,7 @@ Flashing Flashing Zephyr onto the ``adafruit_feather_nrf52480`` board requires an external programmer. The programmer is attached to the SWD header. -Build the Zephyr kernel and the :ref:`blinky-sample` sample application. +Build the Zephyr kernel and the :zephyr:code-sample:`blinky` sample application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -129,7 +129,7 @@ Flash the image. :goals: flash :compact: -You should see the the red LED blink. +You should see the red LED blink. References ********** diff --git a/boards/arm/adafruit_feather_stm32f405/adafruit_feather_stm32f405.yaml b/boards/arm/adafruit_feather_stm32f405/adafruit_feather_stm32f405.yaml index 43cd2e57739..f71d8d7cab3 100644 --- a/boards/arm/adafruit_feather_stm32f405/adafruit_feather_stm32f405.yaml +++ b/boards/arm/adafruit_feather_stm32f405/adafruit_feather_stm32f405.yaml @@ -15,3 +15,4 @@ supported: - feather_serial - feather_i2c - feather_spi +vendor: adafruit diff --git a/boards/arm/adafruit_feather_stm32f405/doc/index.rst b/boards/arm/adafruit_feather_stm32f405/doc/index.rst index 1e80ba70b49..47d70537e69 100644 --- a/boards/arm/adafruit_feather_stm32f405/doc/index.rst +++ b/boards/arm/adafruit_feather_stm32f405/doc/index.rst @@ -100,7 +100,7 @@ of the built in DFU-Util bootloader is possible by following the Flashing ======== -#. Build the Zephyr kernel and the :ref:`blinky-sample` sample application: +#. Build the Zephyr kernel and the :zephyr:code-sample:`blinky` sample application: .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/adafruit_itsybitsy_m4_express/adafruit_itsybitsy_m4_express.yaml b/boards/arm/adafruit_itsybitsy_m4_express/adafruit_itsybitsy_m4_express.yaml index 8a239a1d5a1..7de6fd7a3f2 100644 --- a/boards/arm/adafruit_itsybitsy_m4_express/adafruit_itsybitsy_m4_express.yaml +++ b/boards/arm/adafruit_itsybitsy_m4_express/adafruit_itsybitsy_m4_express.yaml @@ -17,3 +17,4 @@ supported: - uart - usb_device - watchdog +vendor: adafruit diff --git a/boards/arm/adafruit_itsybitsy_m4_express/doc/index.rst b/boards/arm/adafruit_itsybitsy_m4_express/doc/index.rst index 54cfa87d90a..401e28d6669 100644 --- a/boards/arm/adafruit_itsybitsy_m4_express/doc/index.rst +++ b/boards/arm/adafruit_itsybitsy_m4_express/doc/index.rst @@ -107,7 +107,7 @@ USB Device Port The SAMD51 MCU has a USB device port that can be used to communicate with a host PC. See the :ref:`usb-samples` sample applications for -more, such as the :ref:`usb_cdc-acm` sample which sets up a virtual +more, such as the :zephyr:code-sample:`usb-cdc-acm` sample which sets up a virtual serial port that echos characters back to the host PC. Programming and Debugging @@ -179,7 +179,8 @@ debugged using a SWD probe such as the Segger J-Link. .. zephyr-app-commands:: :zephyr-app: samples/hello_world :board: adafruit_itsybitsy_m4_express - :goals: flash -r openocd + :goals: flash + :flash-args: -r openocd :compact: #. Start debugging: diff --git a/boards/arm/adafruit_itsybitsy_nrf52840/adafruit_itsybitsy_nrf52840.yaml b/boards/arm/adafruit_itsybitsy_nrf52840/adafruit_itsybitsy_nrf52840.yaml index eba07de2022..a95f91e9b12 100644 --- a/boards/arm/adafruit_itsybitsy_nrf52840/adafruit_itsybitsy_nrf52840.yaml +++ b/boards/arm/adafruit_itsybitsy_nrf52840/adafruit_itsybitsy_nrf52840.yaml @@ -19,3 +19,4 @@ supported: - usb_cdc - usb_device - watchdog +vendor: adafruit diff --git a/boards/arm/adafruit_itsybitsy_nrf52840/adafruit_itsybitsy_nrf52840_defconfig b/boards/arm/adafruit_itsybitsy_nrf52840/adafruit_itsybitsy_nrf52840_defconfig index e5a88c27fb3..a88657578f3 100644 --- a/boards/arm/adafruit_itsybitsy_nrf52840/adafruit_itsybitsy_nrf52840_defconfig +++ b/boards/arm/adafruit_itsybitsy_nrf52840/adafruit_itsybitsy_nrf52840_defconfig @@ -17,8 +17,6 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -CONFIG_PINCTRL=y - # Flashing CONFIG_USE_DT_CODE_PARTITION=y CONFIG_BUILD_OUTPUT_UF2=y diff --git a/boards/arm/adafruit_itsybitsy_nrf52840/doc/index.rst b/boards/arm/adafruit_itsybitsy_nrf52840/doc/index.rst index 699e2151194..aa28cb501c3 100644 --- a/boards/arm/adafruit_itsybitsy_nrf52840/doc/index.rst +++ b/boards/arm/adafruit_itsybitsy_nrf52840/doc/index.rst @@ -114,16 +114,16 @@ Push buttons Logging ------- -Logging is done using the USB-CDC port. See the :ref:`logger_sample` -or the :ref:`cdc-acm-console` sample applications to see how this works. +Logging is done using the USB-CDC port. See the :zephyr:code-sample:`logging` sample +or the :zephyr:code-sample:`usb-cdc-acm-console` sample applications to see how this works. Testing LEDs and buttons on the Adafruit ItsyBitsy nRF52840 Express ******************************************************************* -The :ref:`button-sample` sample lets you test the buttons (switches) and the red LED. -The :ref:`blinky-sample` sample lets you test the red LED. +The :zephyr:code-sample:`button` sample lets you test the buttons (switches) and the red LED. +The :zephyr:code-sample:`blinky` sample lets you test the red LED. The DotStar LED has been implemented as a SPI device and can be tested -with the :ref:`led_apa102_sample` sample application. +with the :zephyr:code-sample:`led-apa102` sample application. You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in @@ -151,7 +151,7 @@ Flashing Flashing is done by dragging and dropping the built Zephyr UF2-file into the :code:`ITSY840BOOT` drive. -#. Build the Zephyr kernel and the :ref:`blinky-sample` +#. Build the Zephyr kernel and the :zephyr:code-sample:`blinky` sample application: .. zephyr-app-commands:: diff --git a/boards/arm/adafruit_kb2040/adafruit_kb2040.yaml b/boards/arm/adafruit_kb2040/adafruit_kb2040.yaml index e7a9e0c9bb7..51dd75d58d9 100644 --- a/boards/arm/adafruit_kb2040/adafruit_kb2040.yaml +++ b/boards/arm/adafruit_kb2040/adafruit_kb2040.yaml @@ -17,3 +17,5 @@ supported: - hwinfo - watchdog - pwm + - flash + - dma diff --git a/boards/arm/adafruit_kb2040/doc/index.rst b/boards/arm/adafruit_kb2040/doc/index.rst index bc891b82fe2..98c2bacf9e3 100644 --- a/boards/arm/adafruit_kb2040/doc/index.rst +++ b/boards/arm/adafruit_kb2040/doc/index.rst @@ -76,6 +76,12 @@ hardware features: * - PWM - :kconfig:option:`CONFIG_PWM` - :dtcompatible:`raspberrypi,pico-pwm` + * - Flash + - :kconfig:option:`CONFIG_FLASH` + - :dtcompatible:`raspberrypi,pico-flash` + * - UART (PIO) + - :kconfig:option:`CONFIG_SERIAL` + - :dtcompatible:`raspberrypi,pico-uart-pio` Pin Mapping =========== diff --git a/boards/arm/adafruit_trinket_m0/adafruit_trinket_m0.dts b/boards/arm/adafruit_trinket_m0/adafruit_trinket_m0.dts index ce128b6807b..dd227354dc0 100644 --- a/boards/arm/adafruit_trinket_m0/adafruit_trinket_m0.dts +++ b/boards/arm/adafruit_trinket_m0/adafruit_trinket_m0.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include #include "adafruit_trinket_m0-pinctrl.dtsi" / { diff --git a/boards/arm/adafruit_trinket_m0/adafruit_trinket_m0.yaml b/boards/arm/adafruit_trinket_m0/adafruit_trinket_m0.yaml index 9fd5a490df6..f1d21a5c63d 100644 --- a/boards/arm/adafruit_trinket_m0/adafruit_trinket_m0.yaml +++ b/boards/arm/adafruit_trinket_m0/adafruit_trinket_m0.yaml @@ -19,3 +19,4 @@ supported: - uart - usb_device - watchdog +vendor: adafruit diff --git a/boards/arm/adafruit_trinket_m0/doc/index.rst b/boards/arm/adafruit_trinket_m0/doc/index.rst index 5934589f93d..2512df3fd56 100644 --- a/boards/arm/adafruit_trinket_m0/doc/index.rst +++ b/boards/arm/adafruit_trinket_m0/doc/index.rst @@ -99,7 +99,7 @@ USB Device Port The SAMD21 MCU has a USB device port that can be used to communicate with a host PC. See the :ref:`usb-samples` sample applications for -more, such as the :ref:`usb_cdc-acm` sample which sets up a virtual +more, such as the :zephyr:code-sample:`usb-cdc-acm` sample which sets up a virtual serial port that echos characters back to the host PC. Programming and Debugging diff --git a/boards/arm/am62x_m4/am62x_m4_phyboard_lyra.dts b/boards/arm/am62x_m4/am62x_m4_phyboard_lyra.dts index 3fac130ee90..ba370240340 100644 --- a/boards/arm/am62x_m4/am62x_m4_phyboard_lyra.dts +++ b/boards/arm/am62x_m4/am62x_m4_phyboard_lyra.dts @@ -20,6 +20,10 @@ zephyr,sram1 = &ddr0; }; + aliases { + led0 = &heartbeat_led; + }; + cpus { cpu@0 { status = "okay"; @@ -32,6 +36,14 @@ reg = <0x9CC00000 DT_SIZE_K(4)>; zephyr,memory-region = "DDR"; }; + + leds: leds { + compatible = "gpio-leds"; + heartbeat_led: led_0 { + gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>; + label = "Heartbeat LED"; + }; + }; }; &pinctrl { @@ -41,6 +53,9 @@ mcu_uart0_tx_default: mcu_uart0_tx_default { pinmux = ; }; + mcu_gpio0_led_default: mcu_gpio0_led_default { + pinmux = ; + }; }; &uart0 { @@ -49,3 +64,9 @@ pinctrl-names = "default"; status = "okay"; }; + +&gpio0 { + pinctrl-0 = <&mcu_gpio0_led_default>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/boards/arm/am62x_m4/am62x_m4_phyboard_lyra.yaml b/boards/arm/am62x_m4/am62x_m4_phyboard_lyra.yaml index cff2ea9ee3b..b77fb449347 100644 --- a/boards/arm/am62x_m4/am62x_m4_phyboard_lyra.yaml +++ b/boards/arm/am62x_m4/am62x_m4_phyboard_lyra.yaml @@ -5,3 +5,4 @@ arch: arm toolchain: - zephyr ram: 192 +vendor: phytec diff --git a/boards/arm/am62x_m4/am62x_m4_phyboard_lyra_defconfig b/boards/arm/am62x_m4/am62x_m4_phyboard_lyra_defconfig index 15d2b0f5b28..822222a8900 100644 --- a/boards/arm/am62x_m4/am62x_m4_phyboard_lyra_defconfig +++ b/boards/arm/am62x_m4/am62x_m4_phyboard_lyra_defconfig @@ -20,6 +20,9 @@ CONFIG_PINCTRL=y # Serial Driver CONFIG_SERIAL=y +# GPIO Driver +CONFIG_GPIO=y + # Enable Console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y diff --git a/boards/arm/am62x_m4/am62x_m4_sk.yaml b/boards/arm/am62x_m4/am62x_m4_sk.yaml index 8d9443f184a..ef07d5a99d9 100644 --- a/boards/arm/am62x_m4/am62x_m4_sk.yaml +++ b/boards/arm/am62x_m4/am62x_m4_sk.yaml @@ -5,3 +5,4 @@ arch: arm toolchain: - zephyr ram: 192 +vendor: ti diff --git a/boards/arm/apollo4p_blue_kxr_evb/Kconfig.board b/boards/arm/apollo4p_blue_kxr_evb/Kconfig.board new file mode 100644 index 00000000000..0ae2283f97d --- /dev/null +++ b/boards/arm/apollo4p_blue_kxr_evb/Kconfig.board @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2023 Ambiq Micro Inc. + +config BOARD_APOLLO4P_BLUE_KXR_EVB + bool "Ambiq Apollo4 Blue Plus KXR Evaluation Board" + depends on SOC_APOLLO4P_BLUE diff --git a/boards/arm/apollo4p_blue_kxr_evb/Kconfig.defconfig b/boards/arm/apollo4p_blue_kxr_evb/Kconfig.defconfig new file mode 100644 index 00000000000..f14c801d3b3 --- /dev/null +++ b/boards/arm/apollo4p_blue_kxr_evb/Kconfig.defconfig @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2023 Ambiq Micro Inc. + +config BOARD + default "apollo4p_blue_kxr_evb" + depends on BOARD_APOLLO4P_BLUE_KXR_EVB diff --git a/boards/arm/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb-pinctrl.dtsi b/boards/arm/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb-pinctrl.dtsi new file mode 100644 index 00000000000..0622157b2d0 --- /dev/null +++ b/boards/arm/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb-pinctrl.dtsi @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2023 Ambiq Micro Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + uart0_default: uart0_default { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + i2c0_default: i2c0_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c1_default: i2c1_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c2_default: i2c2_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c3_default: i2c3_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c5_default: i2c5_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c6_default: i2c6_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c7_default: i2c7_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + + spi0_default: spi0_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-nce-module = <0>; + }; + }; + spi1_default: spi1_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-nce-module = <4>; + }; + }; + spi2_default: spi2_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-nce-module = <8>; + }; + }; + spi3_default: spi3_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-nce-module = <12>; + }; + }; + spi4_default: spi4_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-nce-module = <16>; + }; + }; + spi5_default: spi5_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-nce-module = <20>; + }; + }; + spi6_default: spi6_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-nce-module = <24>; + }; + }; + spi7_default: spi7_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-nce-module = <28>; + }; + }; + mspi0_default: mspi0_default{ + group1 { + pinmux = , + , + ; + }; + group2 { + pinmux = ; + drive-push-pull; + drive-strength = "0.5"; + ambiq,iom-nce-module = <32>; + }; + }; + mspi1_default: mspi1_default{ + group1 { + pinmux = , + , + ; + }; + group2 { + pinmux = ; + drive-push-pull; + drive-strength = "0.5"; + ambiq,iom-nce-module = <34>; + }; + }; + mspi2_default: mspi2_default{ + group1 { + pinmux = , + , + ; + }; + group2 { + pinmux = ; + drive-push-pull; + drive-strength = "0.5"; + ambiq,iom-nce-module = <36>; + }; + }; + + xo32m_default: xo32m_default { + group1 { + pinmux = ; + drive-strength = "0.1"; + }; + }; + xo32k_default: xo32k_default { + group1 { + pinmux = ; + drive-strength = "0.1"; + }; + }; +}; diff --git a/boards/arm/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb.dts b/boards/arm/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb.dts new file mode 100644 index 00000000000..68e0195056c --- /dev/null +++ b/boards/arm/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb.dts @@ -0,0 +1,88 @@ +/dts-v1/; +#include + +#include "apollo4p_blue_kxr_evb-pinctrl.dtsi" + +/ { + model = "Ambiq Apollo4 Blue Plus KXR evaluation board"; + compatible = "ambiq,apollo4p_blue_kxr_evb"; + chosen { + zephyr,itcm = &tcm; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,uart-pipe = &uart0; + zephyr,flash-controller = &flash; + }; + aliases { + watchdog0 = &wdt0; + }; + +}; + +&uart0 { + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&counter0 { + status = "okay"; +}; + +&wdt0 { + status = "okay"; +}; + +&iom0 { + compatible = "ambiq,i2c"; + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; + clock-frequency = ; + status = "okay"; +}; + +&iom1 { + compatible = "ambiq,spi"; + pinctrl-0 = <&spi1_default>; + pinctrl-names = "default"; + clock-frequency = <1000000>; + status = "okay"; +}; + +&mspi0 { + pinctrl-0 = <&mspi0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&flash0 { + erase-block-size = <2048>; + write-block-size = <16>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Set 16KB of storage at the end of the 1952KB of flash */ + storage_partition: partition@1e4000 { + label = "storage"; + reg = <0x001e4000 0x4000>; + }; + }; +}; + +&xo32m { + pinctrl-0 = <&xo32m_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&xo32k { + pinctrl-0 = <&xo32k_default>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/boards/arm/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb.yaml b/boards/arm/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb.yaml new file mode 100644 index 00000000000..bbdf0477a36 --- /dev/null +++ b/boards/arm/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb.yaml @@ -0,0 +1,14 @@ +identifier: apollo4p_blue_kxr_evb +name: Apollo4 Blue Plus KXR EVB +type: mcu +arch: arm +ram: 2816 +flash: 1952 +toolchain: + - zephyr + - gnuarmemb +supported: + - uart +testing: + ignore_tags: + - net diff --git a/boards/arm/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb_defconfig b/boards/arm/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb_defconfig new file mode 100644 index 00000000000..4c940d417fd --- /dev/null +++ b/boards/arm/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb_defconfig @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2023 Ambiq Micro Inc. + +CONFIG_SOC_SERIES_APOLLO4X=y +CONFIG_SOC_APOLLO4P_BLUE=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/boards/arm/apollo4p_blue_kxr_evb/board.cmake b/boards/arm/apollo4p_blue_kxr_evb/board.cmake new file mode 100644 index 00000000000..f19b79f968f --- /dev/null +++ b/boards/arm/apollo4p_blue_kxr_evb/board.cmake @@ -0,0 +1,6 @@ +# Copyright (c) 2023 Ambiq Micro Inc. +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(jlink "--device=AMAP42KK-KBR" "--iface=swd" "--speed=1000") + +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/arm/apollo4p_blue_kxr_evb/doc/apollo4-blue-plus-kxr-soc-eval-board.jpg b/boards/arm/apollo4p_blue_kxr_evb/doc/apollo4-blue-plus-kxr-soc-eval-board.jpg new file mode 100644 index 00000000000..c1825eb4c06 Binary files /dev/null and b/boards/arm/apollo4p_blue_kxr_evb/doc/apollo4-blue-plus-kxr-soc-eval-board.jpg differ diff --git a/boards/arm/apollo4p_blue_kxr_evb/doc/index.rst b/boards/arm/apollo4p_blue_kxr_evb/doc/index.rst new file mode 100644 index 00000000000..35592c0b911 --- /dev/null +++ b/boards/arm/apollo4p_blue_kxr_evb/doc/index.rst @@ -0,0 +1,104 @@ +.. _apollo4p_blue_kxr_evb: + +Ambiq Apollo4 Blue Plus KXR EVB +############################### + +Apollo4 Blue Plus KXR EVB is a board by Ambiq featuring their ultra-low power Apollo4 Blue Plus SoC. + +.. image:: ./apollo4-blue-plus-kxr-soc-eval-board.jpg + :align: center + :alt: Apollo4 Blue Plus KXR EVB + +Hardware +******** + +- Apollo4 Blue Plus SoC with upto 192 MHz operating frequency +- ARM® Cortex® M4F core +- 64 kB 2-way Associative/Direct-Mapped Cache per core +- Up to 2 MB of non-volatile memory (NVM) for code/data +- Up to 2.75 MB of low leakage / low power RAM for code/data +- 384 kB Tightly Coupled RAM +- 384 kB Extended RAM +- Bluetooth 5.1 Low Energy + +For more information about the Apollo4 Blue Plus SoC and Apollo4 Blue Plus KXR EVB board: + +- `Apollo4 Blue Plus Website`_ +- `Apollo4 Blue Plus Datasheet`_ +- `Apollo4 Blue Plus KXR EVB Website`_ + +Supported Features +================== + +The Apollo4 Blue Plus KXR EVB board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| MPU | on-chip | memory protection unit | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| STIMER | on-chip | stimer | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial | ++-----------+------------+-------------------------------------+ +| WDT | on-chip | watchdog | ++-----------+------------+-------------------------------------+ +| RADIO | on-chip | bluetooth | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in the defconfig file: +``boards/arm/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb_defconfig``. + +Programming and Debugging +========================= + +Flashing an application +----------------------- + +Connect your device to your host computer using the JLINK USB port. +The sample application :ref:`hello_world` is used for this example. +Build the Zephyr kernel and application, then flash it to the device: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: apollo4p_blue_kxr_evb + :goals: flash + +.. note:: + `west flash` requires `SEGGER J-Link software`_ and `pylink`_ Python module + to be installed on you host computer. + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you should be able to see on the corresponding Serial Port +the following message: + +.. code-block:: console + + Hello World! apollo4p_blue_kxr_evb + +.. _Apollo4 Blue Plus Website: + https://ambiq.com/apollo4-blue-plus/ + +.. _Apollo4 Blue Plus Datasheet: + https://contentportal.ambiq.com/documents/20123/388410/Apollo4-Blue-Plus-SoC-Datasheet.pdf + +.. _Apollo4 Blue Plus KXR EVB Website: + https://www.ambiq.top/en/apollo4-blue-plus-kxr-soc-eval-board + +.. _SEGGER J-Link software: + https://www.segger.com/downloads/jlink + +.. _pylink: + https://github.com/Square/pylink diff --git a/boards/arm/apollo4p_evb/apollo4p_evb-pinctrl.dtsi b/boards/arm/apollo4p_evb/apollo4p_evb-pinctrl.dtsi index 47e74b21c74..abc9f9c9c54 100644 --- a/boards/arm/apollo4p_evb/apollo4p_evb-pinctrl.dtsi +++ b/boards/arm/apollo4p_evb/apollo4p_evb-pinctrl.dtsi @@ -161,4 +161,43 @@ ambiq,iom-nce-module = <28>; }; }; + mspi0_default: mspi0_default{ + group1 { + pinmux = , + , + ; + }; + group2 { + pinmux = ; + drive-push-pull; + drive-strength = "0.5"; + ambiq,iom-nce-module = <32>; + }; + }; + mspi1_default: mspi1_default{ + group1 { + pinmux = , + , + ; + }; + group2 { + pinmux = ; + drive-push-pull; + drive-strength = "0.5"; + ambiq,iom-nce-module = <34>; + }; + }; + mspi2_default: mspi2_default{ + group1 { + pinmux = , + , + ; + }; + group2 { + pinmux = ; + drive-push-pull; + drive-strength = "0.5"; + ambiq,iom-nce-module = <36>; + }; + }; }; diff --git a/boards/arm/apollo4p_evb/apollo4p_evb.dts b/boards/arm/apollo4p_evb/apollo4p_evb.dts index aae84876cb1..059b880388d 100644 --- a/boards/arm/apollo4p_evb/apollo4p_evb.dts +++ b/boards/arm/apollo4p_evb/apollo4p_evb.dts @@ -49,3 +49,9 @@ clock-frequency = <1000000>; status = "okay"; }; + +&mspi0 { + pinctrl-0 = <&mspi0_default>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/boards/arm/apollo4p_evb/apollo4p_evb.yaml b/boards/arm/apollo4p_evb/apollo4p_evb.yaml index 38cfcd2514b..b2c0ecd954b 100644 --- a/boards/arm/apollo4p_evb/apollo4p_evb.yaml +++ b/boards/arm/apollo4p_evb/apollo4p_evb.yaml @@ -13,3 +13,4 @@ testing: ignore_tags: - net - bluetooth +vendor: ambiq diff --git a/boards/arm/arduino_due/arduino_due.yaml b/boards/arm/arduino_due/arduino_due.yaml index 3532f3a66e8..779271c0e12 100644 --- a/boards/arm/arduino_due/arduino_due.yaml +++ b/boards/arm/arduino_due/arduino_due.yaml @@ -12,3 +12,4 @@ supported: - watchdog - gpio - arduino_i2c +vendor: arduino diff --git a/boards/arm/arduino_giga_r1/Kconfig.defconfig b/boards/arm/arduino_giga_r1/Kconfig.defconfig index 5880f88f7e0..e72fb499055 100644 --- a/boards/arm/arduino_giga_r1/Kconfig.defconfig +++ b/boards/arm/arduino_giga_r1/Kconfig.defconfig @@ -9,7 +9,7 @@ config BOARD if BT -choice CYW43XXX_PART +choice AIROC_PART default CYW4343W endchoice diff --git a/boards/arm/arduino_giga_r1/arduino_giga_r1_m4.yaml b/boards/arm/arduino_giga_r1/arduino_giga_r1_m4.yaml index cd071eb7a73..58b71369e12 100644 --- a/boards/arm/arduino_giga_r1/arduino_giga_r1_m4.yaml +++ b/boards/arm/arduino_giga_r1/arduino_giga_r1_m4.yaml @@ -16,3 +16,4 @@ testing: - mpu - nfc - net +vendor: arduino diff --git a/boards/arm/arduino_giga_r1/arduino_giga_r1_m7.dts b/boards/arm/arduino_giga_r1/arduino_giga_r1_m7.dts index 24e26e68fbe..ef3544ef958 100644 --- a/boards/arm/arduino_giga_r1/arduino_giga_r1_m7.dts +++ b/boards/arm/arduino_giga_r1/arduino_giga_r1_m7.dts @@ -7,6 +7,7 @@ /dts-v1/; #include #include +#include #include "arduino_giga_r1.dtsi" / { @@ -29,7 +30,7 @@ device_type = "memory"; reg = <0xc0000000 DT_SIZE_M(8)>; zephyr,memory-region = "SDRAM1"; - zephyr,memory-attr = "RAM"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; aliases { diff --git a/boards/arm/arduino_giga_r1/arduino_giga_r1_m7.yaml b/boards/arm/arduino_giga_r1/arduino_giga_r1_m7.yaml index 53370f743d2..2e844a14804 100644 --- a/boards/arm/arduino_giga_r1/arduino_giga_r1_m7.yaml +++ b/boards/arm/arduino_giga_r1/arduino_giga_r1_m7.yaml @@ -16,3 +16,4 @@ supported: - memc - usb_cdc - usb_device +vendor: arduino diff --git a/boards/arm/arduino_giga_r1/doc/index.rst b/boards/arm/arduino_giga_r1/doc/index.rst index f12df182a86..2e2b03917cc 100644 --- a/boards/arm/arduino_giga_r1/doc/index.rst +++ b/boards/arm/arduino_giga_r1/doc/index.rst @@ -82,7 +82,7 @@ that run the command: west blobs fetch hal_infineon -.. note: Only Bluetooth functionality is currently supported. +.. note:: Only Bluetooth functionality is currently supported. Resources sharing ================= @@ -151,7 +151,7 @@ You should see the following message on the console: Similarly, you can build and flash samples on the M4 target. -Here is an example for the :ref:`blinky-sample` application on M4 core. +Here is an example for the :zephyr:code-sample:`blinky` application on M4 core. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -177,7 +177,7 @@ as "JTAG". For example:: https://www.st.com/content/st_com/en/products/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus/stm32-high-performance-mcus/stm32h7-series/stm32h747-757/stm32h747xi.html .. _STM32H747xx reference manual: - http://www.st.com/resource/en/reference_manual/dm00176879.pdf + https://www.st.com/resource/en/reference_manual/dm00176879.pdf .. _STM32H747xx datasheet: https://www.st.com/resource/en/datasheet/stm32h747xi.pdf diff --git a/boards/arm/arduino_mkrzero/arduino_mkrzero.dts b/boards/arm/arduino_mkrzero/arduino_mkrzero.dts index 657aca978a1..b682e84aec8 100644 --- a/boards/arm/arduino_mkrzero/arduino_mkrzero.dts +++ b/boards/arm/arduino_mkrzero/arduino_mkrzero.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include #include "arduino_mkrzero-pinctrl.dtsi" #include "arduino_mkr_connector.dtsi" diff --git a/boards/arm/arduino_mkrzero/arduino_mkrzero.yaml b/boards/arm/arduino_mkrzero/arduino_mkrzero.yaml index ca3a108932f..9b695e86097 100644 --- a/boards/arm/arduino_mkrzero/arduino_mkrzero.yaml +++ b/boards/arm/arduino_mkrzero/arduino_mkrzero.yaml @@ -20,3 +20,4 @@ supported: - uart - usb_device - watchdog +vendor: arduino diff --git a/boards/arm/arduino_mkrzero/doc/index.rst b/boards/arm/arduino_mkrzero/doc/index.rst index 3df9ea49d19..a64a9248bd0 100644 --- a/boards/arm/arduino_mkrzero/doc/index.rst +++ b/boards/arm/arduino_mkrzero/doc/index.rst @@ -112,7 +112,7 @@ USB Device Port The SAMD21 MCU has a USB device port that can be used to communicate with a host PC. See the :ref:`usb-samples` sample applications for -more, such as the :ref:`usb_cdc-acm` sample which sets up a virtual +more, such as the :zephyr:code-sample:`usb-cdc-acm` sample which sets up a virtual serial port that echos characters back to the host PC. DAC diff --git a/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble.yaml b/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble.yaml index ad9a58b286e..733309555cb 100644 --- a/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble.yaml +++ b/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble.yaml @@ -17,3 +17,4 @@ supported: - usb_cdc - usb_device - watchdog +vendor: arduino diff --git a/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble_defconfig b/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble_defconfig index dcdc0c8a836..49b2009f744 100644 --- a/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble_defconfig +++ b/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble_defconfig @@ -19,5 +19,3 @@ CONFIG_UART_CONSOLE=y # enable sam-ba bootloader on legacy mode CONFIG_BOOTLOADER_BOSSA=y CONFIG_BOOTLOADER_BOSSA_LEGACY=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble_sense.yaml b/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble_sense.yaml index 7c3a4bb5326..cdd9ead370c 100644 --- a/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble_sense.yaml +++ b/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble_sense.yaml @@ -17,3 +17,4 @@ supported: - usb_cdc - usb_device - watchdog +vendor: arduino diff --git a/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble_sense_defconfig b/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble_sense_defconfig index 4604c6bf386..024c659ad37 100644 --- a/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble_sense_defconfig +++ b/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble_sense_defconfig @@ -19,5 +19,3 @@ CONFIG_UART_CONSOLE=y # enable sam-ba bootloader on legacy mode CONFIG_BOOTLOADER_BOSSA=y CONFIG_BOOTLOADER_BOSSA_LEGACY=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/arduino_nano_33_ble/doc/index.rst b/boards/arm/arduino_nano_33_ble/doc/index.rst index ede09b85979..05c0605b464 100644 --- a/boards/arm/arduino_nano_33_ble/doc/index.rst +++ b/boards/arm/arduino_nano_33_ble/doc/index.rst @@ -126,7 +126,7 @@ and there should be a pulsing orange LED near the USB port. Then, you can flash the image using the above script. -You should see the the red LED blink. +You should see the red LED blink. Debugging ========= diff --git a/boards/arm/arduino_nano_33_iot/arduino_nano_33_iot.dts b/boards/arm/arduino_nano_33_iot/arduino_nano_33_iot.dts index 732084dab3e..6cce683f0a9 100644 --- a/boards/arm/arduino_nano_33_iot/arduino_nano_33_iot.dts +++ b/boards/arm/arduino_nano_33_iot/arduino_nano_33_iot.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include #include "arduino_nano_33_iot-pinctrl.dtsi" #include "arduino_nano_r3_connector.dtsi" diff --git a/boards/arm/arduino_nano_33_iot/arduino_nano_33_iot.yaml b/boards/arm/arduino_nano_33_iot/arduino_nano_33_iot.yaml index 6a698d32894..f7ded1f5239 100644 --- a/boards/arm/arduino_nano_33_iot/arduino_nano_33_iot.yaml +++ b/boards/arm/arduino_nano_33_iot/arduino_nano_33_iot.yaml @@ -19,3 +19,4 @@ supported: - uart - usb_device - watchdog +vendor: arduino diff --git a/boards/arm/arduino_nano_33_iot/doc/index.rst b/boards/arm/arduino_nano_33_iot/doc/index.rst index 64e89e717f5..62353ecbe1e 100644 --- a/boards/arm/arduino_nano_33_iot/doc/index.rst +++ b/boards/arm/arduino_nano_33_iot/doc/index.rst @@ -6,7 +6,7 @@ Arduino Nano 33 IOT Overview ******** -The Arduino Nano 33 IOT is a a small form factor development board with USB, +The Arduino Nano 33 IOT is a small form factor development board with USB, Wifi, Bluetooth, a 6 axis IMU, and secure element. .. image:: img/nano_33_iot.jpg @@ -103,7 +103,7 @@ USB Device Port The SAMD21 MCU has a USB device port that can be used to communicate with a host PC. See the :ref:`usb-samples` sample applications for -more, such as the :ref:`usb_cdc-acm` sample which sets up a virtual +more, such as the :zephyr:code-sample:`usb-cdc-acm` sample which sets up a virtual serial port that echos characters back to the host PC. Programming and Debugging diff --git a/boards/arm/arduino_nicla_sense_me/arduino_nicla_sense_me.yaml b/boards/arm/arduino_nicla_sense_me/arduino_nicla_sense_me.yaml index d7d3ef72756..74e8cab3c6b 100644 --- a/boards/arm/arduino_nicla_sense_me/arduino_nicla_sense_me.yaml +++ b/boards/arm/arduino_nicla_sense_me/arduino_nicla_sense_me.yaml @@ -17,3 +17,4 @@ supported: - nvs - pwm - watchdog +vendor: arduino diff --git a/boards/arm/arduino_portenta_h7/arduino_portenta_h7_m4.yaml b/boards/arm/arduino_portenta_h7/arduino_portenta_h7_m4.yaml index f544786e63c..b84e35835c6 100644 --- a/boards/arm/arduino_portenta_h7/arduino_portenta_h7_m4.yaml +++ b/boards/arm/arduino_portenta_h7/arduino_portenta_h7_m4.yaml @@ -14,3 +14,4 @@ testing: ignore_tags: - mpu - nfc +vendor: arduino diff --git a/boards/arm/arduino_portenta_h7/arduino_portenta_h7_m7.yaml b/boards/arm/arduino_portenta_h7/arduino_portenta_h7_m7.yaml index 4751a7d8ad9..af23aee83d4 100644 --- a/boards/arm/arduino_portenta_h7/arduino_portenta_h7_m7.yaml +++ b/boards/arm/arduino_portenta_h7/arduino_portenta_h7_m7.yaml @@ -10,3 +10,4 @@ ram: 512 flash: 1024 supported: - gpio +vendor: arduino diff --git a/boards/arm/arduino_portenta_h7/doc/index.rst b/boards/arm/arduino_portenta_h7/doc/index.rst index 305fde248aa..999a659f773 100644 --- a/boards/arm/arduino_portenta_h7/doc/index.rst +++ b/boards/arm/arduino_portenta_h7/doc/index.rst @@ -121,7 +121,7 @@ You should see the following message on the console: Similarly, you can build and flash samples on the M4 target. For this, please take care of the resource sharing (UART port used for console for instance). -Here is an example for the :ref:`blinky-sample` application on M4 core. +Here is an example for the :zephyr:code-sample:`blinky` application on M4 core. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -135,7 +135,7 @@ Here is an example for the :ref:`blinky-sample` application on M4 core. https://www.st.com/content/st_com/en/products/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus/stm32-high-performance-mcus/stm32h7-series/stm32h747-757/stm32h747xi.html .. _STM32H747xx reference manual: - http://www.st.com/resource/en/reference_manual/dm00176879.pdf + https://www.st.com/resource/en/reference_manual/dm00176879.pdf .. _STM32H747xx datasheet: https://www.st.com/resource/en/datasheet/stm32h747xi.pdf diff --git a/boards/arm/arduino_uno_r4/Kconfig.board b/boards/arm/arduino_uno_r4/Kconfig.board new file mode 100644 index 00000000000..d56eff75387 --- /dev/null +++ b/boards/arm/arduino_uno_r4/Kconfig.board @@ -0,0 +1,6 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_ARDUINO_UNO_R4_MINIMA + bool "Arduino Uno R4 Minima board" + depends on SOC_R7FA4M1AB3CFM diff --git a/boards/arm/arduino_uno_r4/Kconfig.defconfig b/boards/arm/arduino_uno_r4/Kconfig.defconfig new file mode 100644 index 00000000000..2d483f3bb38 --- /dev/null +++ b/boards/arm/arduino_uno_r4/Kconfig.defconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_ARDUINO_UNO_R4_MINIMA + +config BOARD + default "arduino_uno_r4_minima" if BOARD_ARDUINO_UNO_R4_MINIMA + +endif # BOARD_ARDUINO_UNO_R4_MINIMA diff --git a/boards/arm/arduino_uno_r4/arduino_uno_r4_common.dtsi b/boards/arm/arduino_uno_r4/arduino_uno_r4_common.dtsi new file mode 100644 index 00000000000..472e1092f5f --- /dev/null +++ b/boards/arm/arduino_uno_r4/arduino_uno_r4_common.dtsi @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include + +/ { + model = "Arduino Uno R4 Board"; + compatible = "renesas,r7fa4m1aB3cfm"; +}; diff --git a/boards/arm/arduino_uno_r4/arduino_uno_r4_minima-pinctrl.dtsi b/boards/arm/arduino_uno_r4/arduino_uno_r4_minima-pinctrl.dtsi new file mode 100644 index 00000000000..c9538829a48 --- /dev/null +++ b/boards/arm/arduino_uno_r4/arduino_uno_r4_minima-pinctrl.dtsi @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + sci2_default: sci2_default { + group1 { + pinmux = , ; + }; + }; +}; diff --git a/boards/arm/arduino_uno_r4/arduino_uno_r4_minima.dts b/boards/arm/arduino_uno_r4/arduino_uno_r4_minima.dts new file mode 100644 index 00000000000..18b1aea120c --- /dev/null +++ b/boards/arm/arduino_uno_r4/arduino_uno_r4_minima.dts @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include + +#include "arduino_uno_r4_common.dtsi" +#include "arduino_uno_r4_minima-pinctrl.dtsi" + +/ { + model = "Arduino Uno R4 Minima"; + + chosen { + zephyr,console = &uart2; + zephyr,shell-uart = &uart2; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &code_partition; + }; + + leds { + compatible = "gpio-leds"; + led: led { + gpios = <&ioport1 11 GPIO_ACTIVE_HIGH>; + }; + }; + + aliases { + led0 = &led; + }; +}; + +&sci2 { + status = "okay"; + pinctrl-0 = <&sci2_default>; + pinctrl-names = "default"; + uart2: uart { + current-speed = <115200>; + status = "okay"; + }; +}; + +&ioport1 { + status = "okay"; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "bootloader"; + reg = <0x00000000 0x4000>; + read-only; + }; + + code_partition: partition@4000 { + label = "code"; + reg = <0x4000 0x3C000>; + read-only; + }; + }; +}; + +&fcu { + status = "okay"; +}; + +&hoco { + status = "okay"; + clock-frequency = <48000000>; +}; + +&cgc { + clock-source = <&hoco>; + iclk-div = <1>; + pclka-div = <1>; + pclkb-div = <2>; + pclkc-div = <1>; + pclkd-div = <1>; + fclk-div = <2>; +}; diff --git a/boards/arm/arduino_uno_r4/arduino_uno_r4_minima.yaml b/boards/arm/arduino_uno_r4/arduino_uno_r4_minima.yaml new file mode 100644 index 00000000000..81f3a94866a --- /dev/null +++ b/boards/arm/arduino_uno_r4/arduino_uno_r4_minima.yaml @@ -0,0 +1,12 @@ +identifier: arduino_uno_r4_minima +name: Arduino Uno R4 Minima +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +ram: 32 +supported: + - gpio + - uart diff --git a/boards/arm/arduino_uno_r4/arduino_uno_r4_minima_defconfig b/boards/arm/arduino_uno_r4/arduino_uno_r4_minima_defconfig new file mode 100644 index 00000000000..8d44c120b3e --- /dev/null +++ b/boards/arm/arduino_uno_r4/arduino_uno_r4_minima_defconfig @@ -0,0 +1,25 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_RA4M1=y +CONFIG_SOC_R7FA4M1AB3CFM=y + +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=48000000 + +CONFIG_BUILD_OUTPUT_HEX=y + +# enable uart driver +CONFIG_SERIAL=y + +# enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# enable GPIO +CONFIG_GPIO=y + +CONFIG_PINCTRL=y + +CONFIG_CLOCK_CONTROL=y + +CONFIG_USE_DT_CODE_PARTITION=y diff --git a/boards/arm/arduino_uno_r4/board.cmake b/boards/arm/arduino_uno_r4/board.cmake new file mode 100644 index 00000000000..a034dd9dcdf --- /dev/null +++ b/boards/arm/arduino_uno_r4/board.cmake @@ -0,0 +1,6 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(pyocd "--target=r7fa4m1ab") + +include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) diff --git a/boards/arm/arduino_uno_r4/doc/index.rst b/boards/arm/arduino_uno_r4/doc/index.rst new file mode 100644 index 00000000000..e94c4c78902 --- /dev/null +++ b/boards/arm/arduino_uno_r4/doc/index.rst @@ -0,0 +1,64 @@ +.. _arduino_uno_r4: + +Arduino UNO R4 Minima +##################### + +Overview +******** + +The Arduino UNO R4 Minima is a development board featuring the Renesas RA4M1 SoC +in the Arduino form factor and is compatible with traditional Arduino. + +Programming and debugging +************************* + +Building & Flashing +=================== + +You can build and flash an application in the usual way (See +:ref:`build_an_application` and +:ref:`application_run` for more details). + +Here is an example for building and flashing the :zephyr:code-sample:`blinky` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: arduino_uno_r4_minima + :goals: build flash + +Debugging +========= + +Debugging also can be done in the usual way. +The following command is debugging the :zephyr:code-sample:`blinky` application. +Also, see the instructions specific to the debug server that you use. + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: arduino_uno_r4_minima + :maybe-skip-config: + :goals: debug + + +Using pyOCD +----------- + +Various debug adapters, including cmsis-dap probes, can debug the Arduino UNO R4 with pyOCD. +The default configuration uses the pyOCD for debugging. +You must install CMSIS-Pack when flashing or debugging Arduino UNO R4 Minima with pyOCD. +If not installed yet, execute the following command to install CMSIS-Pack for Arduino UNO R4. + +.. code-block:: console + + pyocd pack install r7fa4m1ab + + +Restoring Arduino Bootloader +============================ + +If you corrupt the Arduino bootloader, you can restore it with the following command. + +.. code-block:: console + + wget https://raw.githubusercontent.com/arduino/ArduinoCore-renesas/main/bootloaders/UNO_R4/dfu_minima.hex + pyocd flash -e sector -a 0x0 -t r7fa4m1ab dfu_minima.hex diff --git a/boards/arm/arduino_zero/arduino_zero.dts b/boards/arm/arduino_zero/arduino_zero.dts index 4eff1db0e85..841e7ab7620 100644 --- a/boards/arm/arduino_zero/arduino_zero.dts +++ b/boards/arm/arduino_zero/arduino_zero.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include #include "arduino_zero-pinctrl.dtsi" / { diff --git a/boards/arm/arduino_zero/arduino_zero.yaml b/boards/arm/arduino_zero/arduino_zero.yaml index caf279614b4..771199f1e8f 100644 --- a/boards/arm/arduino_zero/arduino_zero.yaml +++ b/boards/arm/arduino_zero/arduino_zero.yaml @@ -20,3 +20,4 @@ supported: - uart - usb_device - watchdog +vendor: arduino diff --git a/boards/arm/arduino_zero/doc/index.rst b/boards/arm/arduino_zero/doc/index.rst index f466a173e5f..4c686daff5e 100644 --- a/boards/arm/arduino_zero/doc/index.rst +++ b/boards/arm/arduino_zero/doc/index.rst @@ -99,7 +99,7 @@ USB Device Port The SAMD21 MCU has a USB device port that can be used to communicate with a host PC. See the :ref:`usb-samples` sample applications for -more, such as the :ref:`usb_cdc-acm` sample which sets up a virtual +more, such as the :zephyr:code-sample:`usb-cdc-acm` sample which sets up a virtual serial port that echos characters back to the host PC. DAC diff --git a/boards/arm/ast1030_evb/ast1030_evb.yaml b/boards/arm/ast1030_evb/ast1030_evb.yaml index 39f271716e6..e5c5678336b 100644 --- a/boards/arm/ast1030_evb/ast1030_evb.yaml +++ b/boards/arm/ast1030_evb/ast1030_evb.yaml @@ -10,3 +10,4 @@ ram: 768 flash: 1024 supported: - serial +vendor: aspeed diff --git a/boards/arm/atsamc21n_xpro/atsamc21n_xpro.dts b/boards/arm/atsamc21n_xpro/atsamc21n_xpro.dts index e1d64e9124d..da657b5788b 100644 --- a/boards/arm/atsamc21n_xpro/atsamc21n_xpro.dts +++ b/boards/arm/atsamc21n_xpro/atsamc21n_xpro.dts @@ -6,7 +6,8 @@ /dts-v1/; -#include +#include +#include #include "atsamc21n_xpro-pinctrl.dtsi" #include diff --git a/boards/arm/atsamc21n_xpro/atsamc21n_xpro.yaml b/boards/arm/atsamc21n_xpro/atsamc21n_xpro.yaml index bd449a7aff0..16420223b24 100644 --- a/boards/arm/atsamc21n_xpro/atsamc21n_xpro.yaml +++ b/boards/arm/atsamc21n_xpro/atsamc21n_xpro.yaml @@ -19,3 +19,4 @@ supported: - pwm - spi - uart +vendor: atmel diff --git a/boards/arm/atsamd20_xpro/atsamd20_xpro.dts b/boards/arm/atsamd20_xpro/atsamd20_xpro.dts index ade715cd77c..778d76b6017 100644 --- a/boards/arm/atsamd20_xpro/atsamd20_xpro.dts +++ b/boards/arm/atsamd20_xpro/atsamd20_xpro.dts @@ -7,6 +7,7 @@ /dts-v1/; #include #include +#include #include "atsamd20_xpro-pinctrl.dtsi" #include diff --git a/boards/arm/atsamd20_xpro/atsamd20_xpro.yaml b/boards/arm/atsamd20_xpro/atsamd20_xpro.yaml index 71aa6be7fd1..4138e137100 100644 --- a/boards/arm/atsamd20_xpro/atsamd20_xpro.yaml +++ b/boards/arm/atsamd20_xpro/atsamd20_xpro.yaml @@ -10,8 +10,10 @@ toolchain: - xtools supported: - adc + - flash - gpio - i2c - spi - uart - watchdog +vendor: atmel diff --git a/boards/arm/atsamd20_xpro/doc/index.rst b/boards/arm/atsamd20_xpro/doc/index.rst index fb4c3f90acc..b5b6d96eb03 100644 --- a/boards/arm/atsamd20_xpro/doc/index.rst +++ b/boards/arm/atsamd20_xpro/doc/index.rst @@ -36,27 +36,39 @@ Supported Features The atsamd20_xpro board configuration supports the following hardware features: -+-----------+------------+------------------------------------------+ -| Interface | Controller | Driver/Component | -+===========+============+==========================================+ -| NVIC | on-chip | nested vector interrupt controller | -+-----------+------------+------------------------------------------+ -| Flash | on-chip | Can be used with LittleFS to store files | -+-----------+------------+------------------------------------------+ -| SYSTICK | on-chip | systick | -+-----------+------------+------------------------------------------+ -| WDT | on-chip | Watchdog | -+-----------+------------+------------------------------------------+ -| ADC | on-chip | Analog to Digital Converter | -+-----------+------------+------------------------------------------+ -| GPIO | on-chip | I/O ports | -+-----------+------------+------------------------------------------+ -| USART | on-chip | Serial ports | -+-----------+------------+------------------------------------------+ -| I2C | on-chip | I2C ports | -+-----------+------------+------------------------------------------+ -| SPI | on-chip | Serial Peripheral Interface ports | -+-----------+------------+------------------------------------------+ +.. list-table:: + :header-rows: 1 + + * - Interface + - Controller + - Driver / Component + * - NVIC + - on-chip + - nested vector interrupt controller + * - Flash + - on-chip + - Can be used with LittleFS to store files + * - SYSTICK + - on-chip + - systick + * - WDT + - on-chip + - Watchdog + * - ADC + - on-chip + - Analog to Digital Converter + * - GPIO + - on-chip + - I/O ports + * - USART + - on-chip + - Serial ports + * - I2C + - on-chip + - I2C ports + * - SPI + - on-chip + - Serial Peripheral Interface ports Other hardware features are not currently supported by Zephyr. diff --git a/boards/arm/atsamd21_xpro/atsamd21_xpro.dts b/boards/arm/atsamd21_xpro/atsamd21_xpro.dts index b51712589e4..e48e5afd467 100644 --- a/boards/arm/atsamd21_xpro/atsamd21_xpro.dts +++ b/boards/arm/atsamd21_xpro/atsamd21_xpro.dts @@ -7,6 +7,7 @@ /dts-v1/; #include #include +#include #include "atsamd21_xpro-pinctrl.dtsi" #include diff --git a/boards/arm/atsamd21_xpro/atsamd21_xpro.yaml b/boards/arm/atsamd21_xpro/atsamd21_xpro.yaml index a055c521be2..5eebbdfe813 100644 --- a/boards/arm/atsamd21_xpro/atsamd21_xpro.yaml +++ b/boards/arm/atsamd21_xpro/atsamd21_xpro.yaml @@ -22,3 +22,4 @@ supported: - usb_cdc - usb_device - watchdog +vendor: atmel diff --git a/boards/arm/atsamd21_xpro/doc/index.rst b/boards/arm/atsamd21_xpro/doc/index.rst index 97d9f037696..9732c84d6fb 100644 --- a/boards/arm/atsamd21_xpro/doc/index.rst +++ b/boards/arm/atsamd21_xpro/doc/index.rst @@ -36,31 +36,45 @@ Supported Features The atsamd21_xpro board configuration supports the following hardware features: -+-----------+------------+------------------------------------------+ -| Interface | Controller | Driver/Component | -+===========+============+==========================================+ -| NVIC | on-chip | nested vector interrupt controller | -+-----------+------------+------------------------------------------+ -| Flash | on-chip | Can be used with LittleFS to store files | -+-----------+------------+------------------------------------------+ -| SYSTICK | on-chip | systick | -+-----------+------------+------------------------------------------+ -| WDT | on-chip | Watchdog | -+-----------+------------+------------------------------------------+ -| ADC | on-chip | Analog to Digital Converter | -+-----------+------------+------------------------------------------+ -| GPIO | on-chip | I/O ports | -+-----------+------------+------------------------------------------+ -| PWM | on-chip | Pulse Width Modulation | -+-----------+------------+------------------------------------------+ -| USART | on-chip | Serial ports | -+-----------+------------+------------------------------------------+ -| I2C | on-chip | I2C ports | -+-----------+------------+------------------------------------------+ -| SPI | on-chip | Serial Peripheral Interface ports | -+-----------+------------+------------------------------------------+ -| USB | on-chip | Universal Serial Bus device ports | -+-----------+------------+------------------------------------------+ +.. list-table:: + :header-rows: 1 + + * - Interface + - Controller + - Driver / Component + * - NVIC + - on-chip + - nested vector interrupt controller + * - Flash + - on-chip + - Can be used with LittleFS to store files + * - SYSTICK + - on-chip + - systick + * - WDT + - on-chip + - Watchdog + * - ADC + - on-chip + - Analog to Digital Converter + * - GPIO + - on-chip + - I/O ports + * - PWM + - on-chip + - Pulse Width Modulation + * - USART + - on-chip + - Serial ports + * - I2C + - on-chip + - I2C ports + * - SPI + - on-chip + - Serial Peripheral Interface ports + * - USB + - on-chip + - Universal Serial Bus device ports Other hardware features are not currently supported by Zephyr. diff --git a/boards/arm/atsame54_xpro/atsame54_xpro.dts b/boards/arm/atsame54_xpro/atsame54_xpro.dts index 135a53a6c09..a9bc92ad8a7 100644 --- a/boards/arm/atsame54_xpro/atsame54_xpro.dts +++ b/boards/arm/atsame54_xpro/atsame54_xpro.dts @@ -132,9 +132,27 @@ zephyr_udc0: &usb0 { pinctrl-0 = <&mdio_default>; pinctrl-names = "default"; - phy: phy { + phy: ethernet-phy@0 { compatible = "ethernet-phy"; status = "okay"; - address = <0>; + reg = <0>; + }; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* + * The final 16 KiB is reserved for the application. + * Storage partition will be used by FCB/LittleFS/NVS + * if enabled. + */ + storage_partition: partition@fc000 { + label = "storage"; + reg = <0x000fc000 0x00004000>; + }; }; }; diff --git a/boards/arm/atsame54_xpro/atsame54_xpro.yaml b/boards/arm/atsame54_xpro/atsame54_xpro.yaml index 95b78f016d2..f23ef379363 100644 --- a/boards/arm/atsame54_xpro/atsame54_xpro.yaml +++ b/boards/arm/atsame54_xpro/atsame54_xpro.yaml @@ -12,6 +12,7 @@ toolchain: - xtools supported: - adc + - flash - gpio - pwm - spi @@ -19,3 +20,4 @@ supported: - uart - usb_device - netif:eth +vendor: atmel diff --git a/boards/arm/atsaml21_xpro/atsaml21_xpro.yaml b/boards/arm/atsaml21_xpro/atsaml21_xpro.yaml index b659c2a7ab5..03c5c226209 100644 --- a/boards/arm/atsaml21_xpro/atsaml21_xpro.yaml +++ b/boards/arm/atsaml21_xpro/atsaml21_xpro.yaml @@ -22,3 +22,4 @@ supported: - usb_cdc - usb_device - watchdog +vendor: atmel diff --git a/boards/arm/atsamr21_xpro/atsamr21_xpro.dts b/boards/arm/atsamr21_xpro/atsamr21_xpro.dts index a94621730eb..86981d86cfe 100644 --- a/boards/arm/atsamr21_xpro/atsamr21_xpro.dts +++ b/boards/arm/atsamr21_xpro/atsamr21_xpro.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include #include "atsamr21_xpro-pinctrl.dtsi" #include @@ -206,3 +207,21 @@ ext2_spi: &sercom5 { ext2_i2c: &sercom1 { }; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* + * The final 16 KiB is reserved for the application. + * Storage partition will be used by FCB/LittleFS/NVS + * if enabled. + */ + storage_partition: partition@3c000 { + label = "storage"; + reg = <0x0003c000 0x00004000>; + }; + }; +}; diff --git a/boards/arm/atsamr21_xpro/atsamr21_xpro.yaml b/boards/arm/atsamr21_xpro/atsamr21_xpro.yaml index 613cbcc96b3..04608ed2afb 100644 --- a/boards/arm/atsamr21_xpro/atsamr21_xpro.yaml +++ b/boards/arm/atsamr21_xpro/atsamr21_xpro.yaml @@ -13,6 +13,7 @@ toolchain: - xtools supported: - adc + - flash - gpio - i2c - netif @@ -24,3 +25,4 @@ supported: - xpro_i2c - xpro_serial - xpro_spi +vendor: atmel diff --git a/boards/arm/atsamr21_xpro/doc/index.rst b/boards/arm/atsamr21_xpro/doc/index.rst index b362648d652..da9cb14a437 100644 --- a/boards/arm/atsamr21_xpro/doc/index.rst +++ b/boards/arm/atsamr21_xpro/doc/index.rst @@ -159,10 +159,10 @@ externally connected SPI devices. +-------------+------------------------------------------------------------------------------------------+ Zephyr provide several samples that can use this technology. You can check -:ref:`wpanusb-sample` and :ref:`wpan_serial-sample` examples as starting +:zephyr:code-sample:`wpan-usb` and :zephyr:code-sample:`wpan-serial` examples as starting points. Another good test can be done with IPv6 by using the server/client -echo demo. More information at :ref:`sockets-echo-server-sample` and -:ref:`sockets-echo-client-sample`. +echo demo. More information at :zephyr:code-sample:`sockets-echo-server` and +:zephyr:code-sample:`sockets-echo-client`. Programming and Debugging ************************* diff --git a/boards/arm/atsamr34_xpro/atsamr34_xpro.dts b/boards/arm/atsamr34_xpro/atsamr34_xpro.dts index 3e3abee6b2e..aba04a1b3e6 100644 --- a/boards/arm/atsamr34_xpro/atsamr34_xpro.dts +++ b/boards/arm/atsamr34_xpro/atsamr34_xpro.dts @@ -11,7 +11,7 @@ / { model = "SAM R34 Xplained Pro"; - compatible = "atsamr34,xpro", "atmel,samr34j18b", "atmel,samr34"; + compatible = "atmel,atsamr34xpro", "atmel,samr34j18b", "atmel,samr34"; chosen { zephyr,console = &sercom0; diff --git a/boards/arm/atsamr34_xpro/atsamr34_xpro.yaml b/boards/arm/atsamr34_xpro/atsamr34_xpro.yaml index 932fec34bf2..fb5c574b321 100644 --- a/boards/arm/atsamr34_xpro/atsamr34_xpro.yaml +++ b/boards/arm/atsamr34_xpro/atsamr34_xpro.yaml @@ -22,3 +22,4 @@ supported: - usb_cdc - usb_device - watchdog +vendor: atmel diff --git a/boards/arm/az3166_iotdevkit/Kconfig.defconfig b/boards/arm/az3166_iotdevkit/Kconfig.defconfig index d7858ac5d9b..af040b8a58d 100644 --- a/boards/arm/az3166_iotdevkit/Kconfig.defconfig +++ b/boards/arm/az3166_iotdevkit/Kconfig.defconfig @@ -12,7 +12,4 @@ choice HTS221_TRIGGER_MODE default HTS221_TRIGGER_NONE endchoice -config SSD1306_REVERSE_MODE - default y - endif # BOARD_AZ3166_DEVKIT diff --git a/boards/arm/az3166_iotdevkit/az3166_iotdevkit.dts b/boards/arm/az3166_iotdevkit/az3166_iotdevkit.dts index 1f1e8f2c7b6..13b641719ee 100644 --- a/boards/arm/az3166_iotdevkit/az3166_iotdevkit.dts +++ b/boards/arm/az3166_iotdevkit/az3166_iotdevkit.dts @@ -172,6 +172,7 @@ segment-remap; com-invdir; prechargep = <0x22>; + inversion-on; reset-gpios = <&gpioa 8 GPIO_ACTIVE_HIGH>; }; diff --git a/boards/arm/b_g474e_dpow1/b_g474e_dpow1.yaml b/boards/arm/b_g474e_dpow1/b_g474e_dpow1.yaml index 3009e5fb02c..04dc5fb08d6 100644 --- a/boards/arm/b_g474e_dpow1/b_g474e_dpow1.yaml +++ b/boards/arm/b_g474e_dpow1/b_g474e_dpow1.yaml @@ -14,3 +14,4 @@ supported: - watchdog - tcpc - usb +vendor: st diff --git a/boards/arm/b_g474e_dpow1/doc/index.rst b/boards/arm/b_g474e_dpow1/doc/index.rst index 30aa1719dd2..1959ab6ad68 100644 --- a/boards/arm/b_g474e_dpow1/doc/index.rst +++ b/boards/arm/b_g474e_dpow1/doc/index.rst @@ -120,7 +120,7 @@ The B-G474E-DPOW1 Discovery board includes an ST-LINK/V3E embedded debug tool in Flashing an application to the B_G474E_DPOW1 -------------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/b_l072z_lrwan1/b_l072z_lrwan1.yaml b/boards/arm/b_l072z_lrwan1/b_l072z_lrwan1.yaml index ea82e670ada..895fab02c5a 100644 --- a/boards/arm/b_l072z_lrwan1/b_l072z_lrwan1.yaml +++ b/boards/arm/b_l072z_lrwan1/b_l072z_lrwan1.yaml @@ -20,3 +20,4 @@ supported: - eeprom - nvs - lora +vendor: st diff --git a/boards/arm/b_l072z_lrwan1/doc/index.rst b/boards/arm/b_l072z_lrwan1/doc/index.rst index 9a28af18e39..a45ead85652 100644 --- a/boards/arm/b_l072z_lrwan1/doc/index.rst +++ b/boards/arm/b_l072z_lrwan1/doc/index.rst @@ -244,7 +244,7 @@ You can debug an application in the usual way. Here is an example for the https://www.st.com/en/evaluation-tools/b-l072z-lrwan1.html .. _STM32L072CZ on www.st.com: - http://www.st.com/en/microcontrollers/stm32l072cz.html + https://www.st.com/en/microcontrollers/stm32l072cz.html .. _STM32L0x2 reference manual: - http://www.st.com/resource/en/reference_manual/DM00108281.pdf + https://www.st.com/resource/en/reference_manual/DM00108281.pdf diff --git a/boards/arm/b_l4s5i_iot01a/b_l4s5i_iot01a.dts b/boards/arm/b_l4s5i_iot01a/b_l4s5i_iot01a.dts index da66cb53ada..9f8900921f6 100644 --- a/boards/arm/b_l4s5i_iot01a/b_l4s5i_iot01a.dts +++ b/boards/arm/b_l4s5i_iot01a/b_l4s5i_iot01a.dts @@ -157,6 +157,8 @@ reset-gpios = <&gpioa 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; irq-gpios = <&gpioe 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; spi-max-frequency = <2000000>; + controller-data-delay-us = <0>; /* No need for extra delay for BlueNRG-MS */ + spi-hold-cs; }; wifi0: ism43362@1 { diff --git a/boards/arm/b_l4s5i_iot01a/b_l4s5i_iot01a.yaml b/boards/arm/b_l4s5i_iot01a/b_l4s5i_iot01a.yaml index 01c99a43640..63b445b8038 100644 --- a/boards/arm/b_l4s5i_iot01a/b_l4s5i_iot01a.yaml +++ b/boards/arm/b_l4s5i_iot01a/b_l4s5i_iot01a.yaml @@ -21,3 +21,4 @@ supported: - spi - vl53l0x - watchdog +vendor: st diff --git a/boards/arm/b_u585i_iot02a/Kconfig.defconfig b/boards/arm/b_u585i_iot02a/Kconfig.defconfig index 84e7bdb320a..6b3b72554ff 100644 --- a/boards/arm/b_u585i_iot02a/Kconfig.defconfig +++ b/boards/arm/b_u585i_iot02a/Kconfig.defconfig @@ -16,10 +16,6 @@ config SPI_STM32_INTERRUPT config USE_DT_CODE_PARTITION default y if TRUSTED_EXECUTION_NONSECURE -# LPTIM clocked by LSE, force tick freq to 4096 for tick accuracy -config SYS_CLOCK_TICKS_PER_SEC - default 4096 if STM32_LPTIM_TIMER - if BUILD_WITH_TFM # Initial Attestation key provisioned by the BL1 bootloader diff --git a/boards/arm/b_u585i_iot02a/b_u585i_iot02a.yaml b/boards/arm/b_u585i_iot02a/b_u585i_iot02a.yaml index 45cf413fa60..27ba601cae5 100644 --- a/boards/arm/b_u585i_iot02a/b_u585i_iot02a.yaml +++ b/boards/arm/b_u585i_iot02a/b_u585i_iot02a.yaml @@ -22,3 +22,5 @@ supported: - backup_sram - pwm - counter + - i2c +vendor: st diff --git a/boards/arm/b_u585i_iot02a/b_u585i_iot02a_defconfig b/boards/arm/b_u585i_iot02a/b_u585i_iot02a_defconfig index c034f717771..d84deca3fe0 100644 --- a/boards/arm/b_u585i_iot02a/b_u585i_iot02a_defconfig +++ b/boards/arm/b_u585i_iot02a/b_u585i_iot02a_defconfig @@ -18,3 +18,6 @@ CONFIG_UART_CONSOLE=y # enable pin controller CONFIG_PINCTRL=y + +# LSE defined as LPTIM clock source by the DTS +CONFIG_STM32_LPTIM_CLOCK_LSE=y diff --git a/boards/arm/b_u585i_iot02a/b_u585i_iot02a_ns.yaml b/boards/arm/b_u585i_iot02a/b_u585i_iot02a_ns.yaml index 29e69d99b76..0867becc701 100644 --- a/boards/arm/b_u585i_iot02a/b_u585i_iot02a_ns.yaml +++ b/boards/arm/b_u585i_iot02a/b_u585i_iot02a_ns.yaml @@ -8,3 +8,4 @@ toolchain: - xtools ram: 786 flash: 512 +vendor: st diff --git a/boards/arm/b_u585i_iot02a/b_u585i_iot02a_ns_defconfig b/boards/arm/b_u585i_iot02a/b_u585i_iot02a_ns_defconfig index 4b6f6ba7f5c..473e6e2fbb0 100644 --- a/boards/arm/b_u585i_iot02a/b_u585i_iot02a_ns_defconfig +++ b/boards/arm/b_u585i_iot02a/b_u585i_iot02a_ns_defconfig @@ -22,3 +22,6 @@ CONFIG_PINCTRL=y CONFIG_ARM_TRUSTZONE_M=y CONFIG_RUNTIME_NMI=y CONFIG_TRUSTED_EXECUTION_NONSECURE=y + +# LSE defined as LPTIM clock source by the DTS +CONFIG_STM32_LPTIM_CLOCK_LSE=y diff --git a/boards/arm/b_u585i_iot02a/doc/index.rst b/boards/arm/b_u585i_iot02a/doc/index.rst index 5d5be82d592..3c794b4de79 100644 --- a/boards/arm/b_u585i_iot02a/doc/index.rst +++ b/boards/arm/b_u585i_iot02a/doc/index.rst @@ -327,7 +327,7 @@ Debugging ========= Default flasher for this board is openocd. It could be used in the usual way. -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/bbc_microbit/bbc_microbit_defconfig b/boards/arm/bbc_microbit/bbc_microbit_defconfig index ba34da254e7..8396a17b16f 100644 --- a/boards/arm/bbc_microbit/bbc_microbit_defconfig +++ b/boards/arm/bbc_microbit/bbc_microbit_defconfig @@ -17,5 +17,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/bbc_microbit_v2/bbc_microbit_v2_defconfig b/boards/arm/bbc_microbit_v2/bbc_microbit_v2_defconfig index 970aabdd1fb..f4d34eb3599 100644 --- a/boards/arm/bbc_microbit_v2/bbc_microbit_v2_defconfig +++ b/boards/arm/bbc_microbit_v2/bbc_microbit_v2_defconfig @@ -17,5 +17,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/bcm958401m2/bcm958401m2.yaml b/boards/arm/bcm958401m2/bcm958401m2.yaml index 2c61d67d10d..2dd64839807 100644 --- a/boards/arm/bcm958401m2/bcm958401m2.yaml +++ b/boards/arm/bcm958401m2/bcm958401m2.yaml @@ -5,3 +5,4 @@ arch: arm toolchain: - zephyr - gnuarmemb +vendor: brcm diff --git a/boards/arm/bcm958402m2_m7/bcm958402m2_m7.yaml b/boards/arm/bcm958402m2_m7/bcm958402m2_m7.yaml index 004a84124c4..21c94f61721 100644 --- a/boards/arm/bcm958402m2_m7/bcm958402m2_m7.yaml +++ b/boards/arm/bcm958402m2_m7/bcm958402m2_m7.yaml @@ -5,3 +5,4 @@ arch: arm toolchain: - zephyr - gnuarmemb +vendor: brcm diff --git a/boards/arm/beagle_bcf/beagleconnect_freedom.dts b/boards/arm/beagle_bcf/beagleconnect_freedom.dts index 3f6fcafaa21..7fd8341e89b 100644 --- a/boards/arm/beagle_bcf/beagleconnect_freedom.dts +++ b/boards/arm/beagle_bcf/beagleconnect_freedom.dts @@ -59,23 +59,11 @@ sens_i2c: sensor-switch { status = "okay"; - compatible = "ti,ts5a2066"; + compatible = "gpio-i2c-switch"; #address-cells = <1>; #size-cells = <0>; controller = <&i2c0>; gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; - - light: opt3001-light@44 { - status = "okay"; - compatible = "ti,opt3001"; - reg = <0x44>; - }; - - humidity: hdc2010-humidity@41 { - status = "okay"; - compatible = "ti,hdc2010"; - reg = <0x41>; - }; }; }; @@ -138,6 +126,18 @@ compatible = "beagle,usbbridge"; reg = <0x4>; }; + + light: opt3001-light@44 { + status = "okay"; + compatible = "ti,opt3001"; + reg = <0x44>; + }; + + humidity: hdc2010-humidity@41 { + status = "okay"; + compatible = "ti,hdc2010"; + reg = <0x41>; + }; }; &spi0 { diff --git a/boards/arm/beagle_bcf/beagleconnect_freedom.yaml b/boards/arm/beagle_bcf/beagleconnect_freedom.yaml index d85ea8bd355..46cfaf5de3f 100644 --- a/boards/arm/beagle_bcf/beagleconnect_freedom.yaml +++ b/boards/arm/beagle_bcf/beagleconnect_freedom.yaml @@ -13,3 +13,5 @@ supported: - i2c - spi - uart + - hwinfo +vendor: beagle diff --git a/boards/arm/beagle_bcf/beagleconnect_freedom_defconfig b/boards/arm/beagle_bcf/beagleconnect_freedom_defconfig index af58105267c..a2c05f40f32 100644 --- a/boards/arm/beagle_bcf/beagleconnect_freedom_defconfig +++ b/boards/arm/beagle_bcf/beagleconnect_freedom_defconfig @@ -20,3 +20,11 @@ CONFIG_CC13X2_CC26X2_BOOTLOADER_BACKDOOR_PIN=15 # Enable MPU and hardware stack protection CONFIG_ARM_MPU=y CONFIG_HW_STACK_PROTECTION=y + +# Enable default uart console +CONFIG_SERIAL=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Adjust for oscillator capacitors +CONFIG_CC13X2_CC26X2_XOSC_CAPARRAY_DELTA=0x02 diff --git a/boards/arm/beagle_bcf/doc/index.rst b/boards/arm/beagle_bcf/doc/index.rst index 311e99449c2..c208d41e431 100644 --- a/boards/arm/beagle_bcf/doc/index.rst +++ b/boards/arm/beagle_bcf/doc/index.rst @@ -54,6 +54,8 @@ The board configuration supports the following hardware features: +-----------+------------+----------------------+ | SPI | on-chip | spi | +-----------+------------+----------------------+ +| HWINFO | on-chip | hwinfo | ++-----------+------------+----------------------+ | I2C | off-chip | OPT3001 | +-----------+------------+----------------------+ | I2C | off-chip | HDC2010 | diff --git a/boards/arm/bl5340_dvk/Kconfig b/boards/arm/bl5340_dvk/Kconfig index 4be3f3971b0..365da6269e1 100644 --- a/boards/arm/bl5340_dvk/Kconfig +++ b/boards/arm/bl5340_dvk/Kconfig @@ -44,7 +44,7 @@ config DOMAIN_CPUNET_BOARD help The board which will be used for CPUNET domain when creating a multi image application where one or more images should be located on - another board. For example hci_rpmsg on the bl5340_dvk_cpunet for + another board. For example hci_ipc on the bl5340_dvk_cpunet for Bluetooth applications. endif # BOARD_BL5340_DVK_CPUAPP || BOARD_BL5340_DVK_CPUAPP_NS diff --git a/boards/arm/bl5340_dvk/Kconfig.defconfig b/boards/arm/bl5340_dvk/Kconfig.defconfig index e033f718dba..798f331efc3 100644 --- a/boards/arm/bl5340_dvk/Kconfig.defconfig +++ b/boards/arm/bl5340_dvk/Kconfig.defconfig @@ -75,11 +75,11 @@ config MBOX_NRFX_IPC if BOARD_BL5340_DVK_CPUAPP || BOARD_BL5340_DVK_CPUAPP_NS choice BT_HCI_BUS_TYPE - default BT_RPMSG if BT + default BT_HCI_IPC if BT endchoice config HEAP_MEM_POOL_SIZE - default 4096 if BT_RPMSG + default 4096 if BT_HCI_IPC config BT_HCI_VS default y if BT diff --git a/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp.dts b/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp.dts index 12528e19bb7..6052502552e 100644 --- a/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp.dts +++ b/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp.dts @@ -10,7 +10,7 @@ / { model = "Laird Connectivity BL5340 (nRF5340) Application"; - compatible = "lairdconnectivity,bl5340-dvk-cpuapp"; + compatible = "lairdconnect,bl5340-dvk-cpuapp"; chosen { zephyr,sram = &sram0_image; diff --git a/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp.yaml b/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp.yaml index b5ed7165345..10ade88c8b1 100644 --- a/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp.yaml +++ b/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp.yaml @@ -19,3 +19,4 @@ supported: - usb_cdc - usb_device - watchdog +vendor: lairdconnect diff --git a/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp_common.dtsi b/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp_common.dtsi index 4fd2c351013..78d1f2debf7 100644 --- a/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp_common.dtsi +++ b/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp_common.dtsi @@ -15,7 +15,7 @@ zephyr,bt-mon-uart = &uart0; zephyr,bt-c2h-uart = &uart0; zephyr,display = &ili9340; - zephyr,bt-hci-rpmsg-ipc = &ipc0; + zephyr,bt-hci-ipc = &ipc0; }; /* Main LEDs and buttons are on an I2C TCA9538 GPIO port expander */ diff --git a/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp_defconfig b/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp_defconfig index 23bb9d57b10..6c21af3695a 100644 --- a/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp_defconfig +++ b/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp_defconfig @@ -28,5 +28,3 @@ CONFIG_CLOCK_CONTROL_NRF_K32SRC_250PPM=y CONFIG_SOC_LFXO_CAP_INT_7PF=y CONFIG_SOC_HFXO_CAP_INTERNAL=y CONFIG_SOC_HFXO_CAP_INT_VALUE_X2=27 - -CONFIG_PINCTRL=y diff --git a/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp_ns.dts b/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp_ns.dts index cfa5b763241..b943c5bdfbf 100644 --- a/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp_ns.dts +++ b/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp_ns.dts @@ -10,7 +10,7 @@ / { model = "Laird Connectivity BL5340 (nRF5340) Application"; - compatible = "lairdconnectivity,bl5340-dvk-cpuapp"; + compatible = "lairdconnect,bl5340-dvk-cpuapp"; chosen { zephyr,sram = &sram0_ns; diff --git a/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp_ns.yaml b/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp_ns.yaml index c754614833f..5d94e8e7629 100644 --- a/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp_ns.yaml +++ b/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp_ns.yaml @@ -18,3 +18,4 @@ supported: - usb_cdc - usb_device - watchdog +vendor: lairdconnect diff --git a/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp_ns_defconfig b/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp_ns_defconfig index 47fcea1c3a4..27af7678a34 100644 --- a/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp_ns_defconfig +++ b/boards/arm/bl5340_dvk/bl5340_dvk_cpuapp_ns_defconfig @@ -25,5 +25,3 @@ CONFIG_SERIAL=y # Enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/bl5340_dvk/bl5340_dvk_cpunet.dts b/boards/arm/bl5340_dvk/bl5340_dvk_cpunet.dts index 0cacac7cd62..2b3eb053283 100644 --- a/boards/arm/bl5340_dvk/bl5340_dvk_cpunet.dts +++ b/boards/arm/bl5340_dvk/bl5340_dvk_cpunet.dts @@ -11,7 +11,7 @@ / { model = "Laird Connectivity BL5340 (nRF5340) Network"; - compatible = "lairdconnectivity,bl5340-dvk-cpunet"; + compatible = "lairdconnect,bl5340-dvk-cpunet"; chosen { zephyr,console = &uart0; @@ -22,7 +22,7 @@ zephyr,sram = &sram1; zephyr,flash = &flash1; zephyr,code-partition = &slot0_partition; - zephyr,bt-hci-rpmsg-ipc = &ipc0; + zephyr,bt-hci-ipc = &ipc0; }; aliases { diff --git a/boards/arm/bl5340_dvk/bl5340_dvk_cpunet.yaml b/boards/arm/bl5340_dvk/bl5340_dvk_cpunet.yaml index af81eeac4fc..d8a17394be7 100644 --- a/boards/arm/bl5340_dvk/bl5340_dvk_cpunet.yaml +++ b/boards/arm/bl5340_dvk/bl5340_dvk_cpunet.yaml @@ -15,3 +15,4 @@ supported: - spi - uart - watchdog +vendor: lairdconnect diff --git a/boards/arm/bl5340_dvk/bl5340_dvk_cpunet_defconfig b/boards/arm/bl5340_dvk/bl5340_dvk_cpunet_defconfig index 83098b18827..c68fdfc9312 100644 --- a/boards/arm/bl5340_dvk/bl5340_dvk_cpunet_defconfig +++ b/boards/arm/bl5340_dvk/bl5340_dvk_cpunet_defconfig @@ -19,5 +19,3 @@ CONFIG_SERIAL=y # Enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/bl5340_dvk/doc/index.rst b/boards/arm/bl5340_dvk/doc/index.rst index 4a9fe7b1207..544250baa84 100644 --- a/boards/arm/bl5340_dvk/doc/index.rst +++ b/boards/arm/bl5340_dvk/doc/index.rst @@ -290,7 +290,7 @@ described below. .. note:: - By default the the Secure image for BL5340's application core is + By default the Secure image for BL5340's application core is built using TF-M. Building the Secure firmware with TF-M diff --git a/boards/arm/bl652_dvk/bl652_dvk.yaml b/boards/arm/bl652_dvk/bl652_dvk.yaml index 0eb83f54489..a2fd4370d7f 100644 --- a/boards/arm/bl652_dvk/bl652_dvk.yaml +++ b/boards/arm/bl652_dvk/bl652_dvk.yaml @@ -15,3 +15,4 @@ supported: - pwm - spi - watchdog +vendor: lairdconnect diff --git a/boards/arm/bl652_dvk/bl652_dvk_defconfig b/boards/arm/bl652_dvk/bl652_dvk_defconfig index 5302fa8d53f..def931d42fc 100644 --- a/boards/arm/bl652_dvk/bl652_dvk_defconfig +++ b/boards/arm/bl652_dvk/bl652_dvk_defconfig @@ -24,5 +24,3 @@ CONFIG_RTT_CONSOLE=y # 32kHz clock source CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_500PPM=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/bl652_dvk/doc/bl652_dvk.rst b/boards/arm/bl652_dvk/doc/bl652_dvk.rst index 3fafbf1c34b..9d14b847fb9 100644 --- a/boards/arm/bl652_dvk/doc/bl652_dvk.rst +++ b/boards/arm/bl652_dvk/doc/bl652_dvk.rst @@ -255,8 +255,8 @@ Testing the LEDs and buttons in the BL652 DVK There are 2 samples that allow you to test that the buttons (switches) and LEDs on the board are working properly with Zephyr: -* :ref:`blinky-sample` -* :ref:`button-sample` +* :zephyr:code-sample:`blinky` +* :zephyr:code-sample:`button` You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in diff --git a/boards/arm/bl653_dvk/bl653_dvk.dts b/boards/arm/bl653_dvk/bl653_dvk.dts index ba8fa3658d2..4c536eb4512 100644 --- a/boards/arm/bl653_dvk/bl653_dvk.dts +++ b/boards/arm/bl653_dvk/bl653_dvk.dts @@ -148,7 +148,7 @@ &spi1 { compatible = "nordic,nrf-spi"; status = "okay"; - cs-gpios = <&gpio1 23 0>; + cs-gpios = <&gpio0 23 GPIO_ACTIVE_LOW>; pinctrl-0 = <&spi1_default>; pinctrl-1 = <&spi1_sleep>; pinctrl-names = "default", "sleep"; diff --git a/boards/arm/bl653_dvk/bl653_dvk.yaml b/boards/arm/bl653_dvk/bl653_dvk.yaml index ffbde56b11d..6a2792ea521 100644 --- a/boards/arm/bl653_dvk/bl653_dvk.yaml +++ b/boards/arm/bl653_dvk/bl653_dvk.yaml @@ -16,3 +16,4 @@ supported: - counter - spi - i2c +vendor: lairdconnect diff --git a/boards/arm/bl653_dvk/bl653_dvk_defconfig b/boards/arm/bl653_dvk/bl653_dvk_defconfig index 83b73ef4435..b1abe06089c 100644 --- a/boards/arm/bl653_dvk/bl653_dvk_defconfig +++ b/boards/arm/bl653_dvk/bl653_dvk_defconfig @@ -23,5 +23,3 @@ CONFIG_UART_CONSOLE=y # 32kHz clock source CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_500PPM=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/bl653_dvk/doc/bl653_dvk.rst b/boards/arm/bl653_dvk/doc/bl653_dvk.rst index 98c6bbf23aa..ee5996e81ae 100644 --- a/boards/arm/bl653_dvk/doc/bl653_dvk.rst +++ b/boards/arm/bl653_dvk/doc/bl653_dvk.rst @@ -162,8 +162,8 @@ Testing the LEDs and buttons on the BL653 DVK There are 2 samples that allow you to test that the buttons (switches) and LEDs on the board are working properly with Zephyr: -* :ref:`blinky-sample` -* :ref:`button-sample` +* :zephyr:code-sample:`blinky` +* :zephyr:code-sample:`button` You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in diff --git a/boards/arm/bl654_dvk/bl654_dvk.yaml b/boards/arm/bl654_dvk/bl654_dvk.yaml index c15f0d5b0af..27eec7dcaeb 100644 --- a/boards/arm/bl654_dvk/bl654_dvk.yaml +++ b/boards/arm/bl654_dvk/bl654_dvk.yaml @@ -12,3 +12,4 @@ supported: - ble - pwm - watchdog +vendor: lairdconnect diff --git a/boards/arm/bl654_dvk/bl654_dvk_defconfig b/boards/arm/bl654_dvk/bl654_dvk_defconfig index 976495f7e88..7d5b17577b2 100644 --- a/boards/arm/bl654_dvk/bl654_dvk_defconfig +++ b/boards/arm/bl654_dvk/bl654_dvk_defconfig @@ -24,5 +24,3 @@ CONFIG_RTT_CONSOLE=y # 32kHz clock source CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_500PPM=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/bl654_dvk/doc/bl654_dvk.rst b/boards/arm/bl654_dvk/doc/bl654_dvk.rst index 4ae9f496d6f..c70afb78729 100644 --- a/boards/arm/bl654_dvk/doc/bl654_dvk.rst +++ b/boards/arm/bl654_dvk/doc/bl654_dvk.rst @@ -168,8 +168,8 @@ Testing the LEDs and buttons on the BL654 DVK There are 2 samples that allow you to test that the buttons (switches) and LEDs on the board are working properly with Zephyr: -* :ref:`blinky-sample` -* :ref:`button-sample` +* :zephyr:code-sample:`blinky` +* :zephyr:code-sample:`button` You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in diff --git a/boards/arm/bl654_sensor_board/bl654_sensor_board.yaml b/boards/arm/bl654_sensor_board/bl654_sensor_board.yaml index 24110c9d88b..856805fbd16 100644 --- a/boards/arm/bl654_sensor_board/bl654_sensor_board.yaml +++ b/boards/arm/bl654_sensor_board/bl654_sensor_board.yaml @@ -17,3 +17,4 @@ supported: - pwm - watchdog - netif:openthread +vendor: lairdconnect diff --git a/boards/arm/bl654_sensor_board/bl654_sensor_board_defconfig b/boards/arm/bl654_sensor_board/bl654_sensor_board_defconfig index e92c2c4005f..f8352265d3f 100644 --- a/boards/arm/bl654_sensor_board/bl654_sensor_board_defconfig +++ b/boards/arm/bl654_sensor_board/bl654_sensor_board_defconfig @@ -20,5 +20,3 @@ CONFIG_UART_CONSOLE=y # 32KHz clock source CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_150PPM=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/bl654_sensor_board/doc/bl654_sensor_board.rst b/boards/arm/bl654_sensor_board/doc/bl654_sensor_board.rst index 7a1c79f4804..673eed4eefb 100644 --- a/boards/arm/bl654_sensor_board/doc/bl654_sensor_board.rst +++ b/boards/arm/bl654_sensor_board/doc/bl654_sensor_board.rst @@ -233,8 +233,8 @@ Testing the LED and button on the BL654 Sensor Board There are 2 samples that allow you to test that the button (switch) and LED on the board are working properly with Zephyr: -* :ref:`blinky-sample` -* :ref:`button-sample` +* :zephyr:code-sample:`blinky` +* :zephyr:code-sample:`button` You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in diff --git a/boards/arm/bl654_usb/bl654_usb.yaml b/boards/arm/bl654_usb/bl654_usb.yaml index 0187d8e5b27..620275a516d 100644 --- a/boards/arm/bl654_usb/bl654_usb.yaml +++ b/boards/arm/bl654_usb/bl654_usb.yaml @@ -13,3 +13,4 @@ supported: - pwm - watchdog - counter +vendor: lairdconnect diff --git a/boards/arm/bl654_usb/bl654_usb_defconfig b/boards/arm/bl654_usb/bl654_usb_defconfig index 983150c35d9..b51d0c1d99e 100644 --- a/boards/arm/bl654_usb/bl654_usb_defconfig +++ b/boards/arm/bl654_usb/bl654_usb_defconfig @@ -22,5 +22,3 @@ CONFIG_USB_DEVICE_STACK=y # 32KHz clock source CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_150PPM=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/bl654_usb/doc/bl654_usb.rst b/boards/arm/bl654_usb/doc/bl654_usb.rst index 887a2c82685..5d4fdc774de 100644 --- a/boards/arm/bl654_usb/doc/bl654_usb.rst +++ b/boards/arm/bl654_usb/doc/bl654_usb.rst @@ -130,7 +130,7 @@ before proceeding. These instructions were tested with version 6.1.0. The blue LED should start a fade pattern, signalling the bootloader is running. -#. Compile a Zephyr application; we'll use :ref:`blinky `. +#. Compile a Zephyr application; we'll use :zephyr:code-sample:`blinky`. .. zephyr-app-commands:: :app: zephyr/samples/basic/blinky @@ -171,7 +171,7 @@ Testing the LED on the BL654 USB There is a sample that allows you to test that the LED on the board is working properly with Zephyr: -* :ref:`blinky-sample` +* :zephyr:code-sample:`blinky` You can build and flash the example to make sure Zephyr is running correctly on your board. The LED definitions can be found in diff --git a/boards/arm/black_f407ve/doc/index.rst b/boards/arm/black_f407ve/doc/index.rst index 52a8210df6e..4862514d480 100644 --- a/boards/arm/black_f407ve/doc/index.rst +++ b/boards/arm/black_f407ve/doc/index.rst @@ -202,7 +202,7 @@ This interface is supported by the openocd version included in Zephyr SDK. Flashing an application to BLACK_F407VE --------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. Run a serial host program to connect with your board: @@ -235,7 +235,7 @@ You can debug an application in the usual way. Here is an example for the https://stm32-base.org/boards/STM32F407VET6-STM32-F4VE-V2.0.html .. _STM32F407VE on www.st.com: - http://www.st.com/en/microcontrollers/stm32f407ve.html + https://www.st.com/en/microcontrollers/stm32f407ve.html .. _STM32F407VET6 black board: https://os.mbed.com/users/hudakz/code/STM32F407VET6_Hello/ diff --git a/boards/arm/black_f407zg_pro/doc/index.rst b/boards/arm/black_f407zg_pro/doc/index.rst index 18b44f3adf4..4646149a71e 100644 --- a/boards/arm/black_f407zg_pro/doc/index.rst +++ b/boards/arm/black_f407zg_pro/doc/index.rst @@ -184,7 +184,7 @@ This interface is supported by the openocd version included in Zephyr SDK. Flashing an application to BLACK_F407ZG_PRO ------------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. Run a serial host program to connect with your board: diff --git a/boards/arm/blackpill_f401cc/blackpill_f401cc.yaml b/boards/arm/blackpill_f401cc/blackpill_f401cc.yaml index 536fc752d38..2601e64546b 100644 --- a/boards/arm/blackpill_f401cc/blackpill_f401cc.yaml +++ b/boards/arm/blackpill_f401cc/blackpill_f401cc.yaml @@ -14,3 +14,4 @@ supported: - uart - pwm - adc +vendor: weact diff --git a/boards/arm/blackpill_f401cc/doc/index.rst b/boards/arm/blackpill_f401cc/doc/index.rst index 348f0f6f7cb..8c662a11fda 100644 --- a/boards/arm/blackpill_f401cc/doc/index.rst +++ b/boards/arm/blackpill_f401cc/doc/index.rst @@ -168,7 +168,7 @@ References http://dfu-util.sourceforge.net/build.html .. _STM32F401CC website: - http://www.st.com/en/microcontrollers/stm32f401cc.html + https://www.st.com/en/microcontrollers/stm32f401cc.html .. _STM32F401x reference manual: - http://www.st.com/resource/en/reference_manual/dm00096844.pdf + https://www.st.com/resource/en/reference_manual/dm00096844.pdf diff --git a/boards/arm/blackpill_f401ce/blackpill_f401ce.yaml b/boards/arm/blackpill_f401ce/blackpill_f401ce.yaml index 5b835b9be07..813781644f2 100644 --- a/boards/arm/blackpill_f401ce/blackpill_f401ce.yaml +++ b/boards/arm/blackpill_f401ce/blackpill_f401ce.yaml @@ -14,3 +14,4 @@ supported: - uart - pwm - adc +vendor: weact diff --git a/boards/arm/blackpill_f401ce/doc/index.rst b/boards/arm/blackpill_f401ce/doc/index.rst index dc3a43fdf24..265d0fd038e 100644 --- a/boards/arm/blackpill_f401ce/doc/index.rst +++ b/boards/arm/blackpill_f401ce/doc/index.rst @@ -173,7 +173,7 @@ References http://dfu-util.sourceforge.net/build.html .. _STM32F401CE website: - http://www.st.com/en/microcontrollers/stm32f401ce.html + https://www.st.com/en/microcontrollers/stm32f401ce.html .. _STM32F401x reference manual: - http://www.st.com/resource/en/reference_manual/dm00096844.pdf + https://www.st.com/resource/en/reference_manual/dm00096844.pdf diff --git a/boards/arm/blackpill_f411ce/blackpill_f411ce.yaml b/boards/arm/blackpill_f411ce/blackpill_f411ce.yaml index b6729fa9bc5..d0b145fc1e4 100644 --- a/boards/arm/blackpill_f411ce/blackpill_f411ce.yaml +++ b/boards/arm/blackpill_f411ce/blackpill_f411ce.yaml @@ -14,3 +14,4 @@ supported: - uart - pwm - adc +vendor: weact diff --git a/boards/arm/blackpill_f411ce/doc/index.rst b/boards/arm/blackpill_f411ce/doc/index.rst index 5dd7e68fa35..4d3023b462c 100644 --- a/boards/arm/blackpill_f411ce/doc/index.rst +++ b/boards/arm/blackpill_f411ce/doc/index.rst @@ -173,7 +173,7 @@ References http://dfu-util.sourceforge.net/build.html .. _STM32F411CE website: - http://www.st.com/en/microcontrollers/stm32f411ce.html + https://www.st.com/en/microcontrollers/stm32f411ce.html .. _STM32F411x reference manual: - http://www.st.com/resource/en/reference_manual/dm00119316.pdf + https://www.st.com/resource/en/reference_manual/dm00119316.pdf diff --git a/boards/arm/blueclover_plt_demo_v2_nrf52832/blueclover_plt_demo_v2_nrf52832.yaml b/boards/arm/blueclover_plt_demo_v2_nrf52832/blueclover_plt_demo_v2_nrf52832.yaml index 8b8544dedeb..f031e5105ef 100644 --- a/boards/arm/blueclover_plt_demo_v2_nrf52832/blueclover_plt_demo_v2_nrf52832.yaml +++ b/boards/arm/blueclover_plt_demo_v2_nrf52832/blueclover_plt_demo_v2_nrf52832.yaml @@ -17,3 +17,4 @@ supported: - pwm - spi - watchdog +vendor: blueclover diff --git a/boards/arm/blueclover_plt_demo_v2_nrf52832/blueclover_plt_demo_v2_nrf52832_defconfig b/boards/arm/blueclover_plt_demo_v2_nrf52832/blueclover_plt_demo_v2_nrf52832_defconfig index 301a23af362..d9999ba9516 100644 --- a/boards/arm/blueclover_plt_demo_v2_nrf52832/blueclover_plt_demo_v2_nrf52832_defconfig +++ b/boards/arm/blueclover_plt_demo_v2_nrf52832/blueclover_plt_demo_v2_nrf52832_defconfig @@ -23,5 +23,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/blueclover_plt_demo_v2_nrf52832/doc/index.rst b/boards/arm/blueclover_plt_demo_v2_nrf52832/doc/index.rst index 517572c3d96..7a41d95e647 100644 --- a/boards/arm/blueclover_plt_demo_v2_nrf52832/doc/index.rst +++ b/boards/arm/blueclover_plt_demo_v2_nrf52832/doc/index.rst @@ -122,7 +122,7 @@ Flashing Flashing Zephyr onto the ``blueclover_plt_demo_v2_nrf52832`` board requires an external programmer. The programmer is attached to the SWD header. -Build the Zephyr kernel and the :ref:`led_apa102_sample` sample application. +Build the Zephyr kernel and the :zephyr:code-sample:`led-apa102` sample application. .. zephyr-app-commands:: :zephyr-app: samples/drivers/led_apa102 diff --git a/boards/arm/bt510/bt510.yaml b/boards/arm/bt510/bt510.yaml index 4852a82632e..c9b6823d188 100644 --- a/boards/arm/bt510/bt510.yaml +++ b/boards/arm/bt510/bt510.yaml @@ -13,3 +13,4 @@ supported: - watchdog - i2c - sm351lt +vendor: lairdconnect diff --git a/boards/arm/bt510/bt510_defconfig b/boards/arm/bt510/bt510_defconfig index eb769cc9465..cd897918fe1 100644 --- a/boards/arm/bt510/bt510_defconfig +++ b/boards/arm/bt510/bt510_defconfig @@ -20,5 +20,3 @@ CONFIG_UART_CONSOLE=y # 32KHz clock source CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_150PPM=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/bt510/doc/bt510.rst b/boards/arm/bt510/doc/bt510.rst index 3514f90b9f0..841c27b85d6 100644 --- a/boards/arm/bt510/doc/bt510.rst +++ b/boards/arm/bt510/doc/bt510.rst @@ -239,8 +239,8 @@ Testing the LEDs and buttons on the BT510 There are 2 samples that allow you to test that the buttons (switches) and LEDs on the board are working properly with Zephyr: -* :ref:`blinky-sample` -* :ref:`button-sample` +* :zephyr:code-sample:`blinky` +* :zephyr:code-sample:`button` You can build and flash the examples to make sure Zephyr is running correctly on your board. The button, LED and sensor device definitions can be found in diff --git a/boards/arm/bt610/bt610.yaml b/boards/arm/bt610/bt610.yaml index fded74157a3..80cbe9975da 100644 --- a/boards/arm/bt610/bt610.yaml +++ b/boards/arm/bt610/bt610.yaml @@ -19,3 +19,4 @@ supported: - counter - sm351lt - qspi +vendor: lairdconnect diff --git a/boards/arm/bt610/bt610_defconfig b/boards/arm/bt610/bt610_defconfig index d1d7226fade..531ba015b1e 100644 --- a/boards/arm/bt610/bt610_defconfig +++ b/boards/arm/bt610/bt610_defconfig @@ -23,5 +23,3 @@ CONFIG_HW_STACK_PROTECTION=y # 32KHz clock source CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_150PPM=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/bt610/doc/bt610.rst b/boards/arm/bt610/doc/bt610.rst index e792f91ec57..2fe7d7ad931 100644 --- a/boards/arm/bt610/doc/bt610.rst +++ b/boards/arm/bt610/doc/bt610.rst @@ -593,8 +593,8 @@ Testing the LEDs and buttons on the BT610 There are 2 samples that allow you to test that the buttons (switches) and LEDs on the board are working properly with Zephyr: -* :ref:`blinky-sample` -* :ref:`button-sample` +* :zephyr:code-sample:`blinky` +* :zephyr:code-sample:`button` You can build and flash the examples to make sure Zephyr is running correctly on your board. The button, LED and sensor device definitions can be found in diff --git a/boards/arm/cc1352p1_launchxl/cc1352p1_launchxl.dts b/boards/arm/cc1352p1_launchxl/cc1352p1_launchxl.dts index 2e6b6193e66..9fcc6da57da 100644 --- a/boards/arm/cc1352p1_launchxl/cc1352p1_launchxl.dts +++ b/boards/arm/cc1352p1_launchxl/cc1352p1_launchxl.dts @@ -21,6 +21,8 @@ sw0 = &btn0; sw1 = &btn1; watchdog0 = &wdt0; + mcuboot-led0 = &led1; + mcuboot-button0 = &btn1; }; chosen { @@ -29,6 +31,7 @@ zephyr,console = &uart0; zephyr,shell-uart = &uart0; zephyr,ieee802154 = &ieee802154; + zephyr,code-partition = &slot0_partition; }; /** @@ -84,6 +87,37 @@ }; }; +&flash0 { + partitions { + /* 40 KiB (0xa000) for MCUboot */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x0000a000>; + }; + + /* 136 KiB (0x22000) per slot for application */ + slot0_partition: partition@a000 { + label = "image-0"; + reg = <0x0000a000 0x00022000>; + }; + + slot1_partition: partition@2c000 { + label = "image-1"; + reg = <0x0002c000 0x00022000>; + }; + + /* 32 KiB (0x8000) for storage */ + storage_partition: partition@4e000 { + label = "storage"; + reg = <0x0004e000 0x00008000>; + }; + + /* CCFG (customer configuration area) is located in uppermost + * flash sector (0x2000/8 KiB @ 0x56000), keep it unused. + */ + }; +}; + &cpu0 { clock-frequency = <48000000>; }; diff --git a/boards/arm/cc1352p1_launchxl/cc1352p1_launchxl.yaml b/boards/arm/cc1352p1_launchxl/cc1352p1_launchxl.yaml index 90b2cdabf5a..57e62c2ddec 100644 --- a/boards/arm/cc1352p1_launchxl/cc1352p1_launchxl.yaml +++ b/boards/arm/cc1352p1_launchxl/cc1352p1_launchxl.yaml @@ -13,3 +13,5 @@ supported: - i2c - spi - watchdog + - hwinfo +vendor: ti diff --git a/boards/arm/cc1352p1_launchxl/doc/index.rst b/boards/arm/cc1352p1_launchxl/doc/index.rst index 7c934fd0cc6..a5f88cc19ff 100644 --- a/boards/arm/cc1352p1_launchxl/doc/index.rst +++ b/boards/arm/cc1352p1_launchxl/doc/index.rst @@ -58,6 +58,8 @@ features: +-----------+------------+----------------------+ | WDT | on-chip | watchdog | +-----------+------------+----------------------+ +| HWINFO | on-chip | hwinfo | ++-----------+------------+----------------------+ Other hardware features have not been enabled yet for this board. @@ -131,7 +133,7 @@ Programming and Debugging ************************* Before flashing or debugging ensure the RESET, TMS, TCK, TDO, and TDI jumpers -are in place. Also place jumpers on the the TXD and RXD signals for a serial +are in place. Also place jumpers on the TXD and RXD signals for a serial console using the XDS110 application serial port. Prerequisites: diff --git a/boards/arm/cc1352r1_launchxl/cc1352r1_launchxl.dts b/boards/arm/cc1352r1_launchxl/cc1352r1_launchxl.dts index dd48944cc0f..53e5a08a365 100644 --- a/boards/arm/cc1352r1_launchxl/cc1352r1_launchxl.dts +++ b/boards/arm/cc1352r1_launchxl/cc1352r1_launchxl.dts @@ -23,6 +23,8 @@ sw0 = &btn0; sw1 = &btn1; watchdog0 = &wdt0; + mcuboot-led0 = &led1; + mcuboot-button0 = &btn1; }; chosen { @@ -31,6 +33,7 @@ zephyr,console = &uart0; zephyr,shell-uart = &uart0; zephyr,ieee802154 = &ieee802154; + zephyr,code-partition = &slot0_partition; }; leds { @@ -60,6 +63,37 @@ }; }; +&flash0 { + partitions { + /* 40 KiB (0xa000) for MCUboot */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x0000a000>; + }; + + /* 136 KiB (0x22000) per slot for application */ + slot0_partition: partition@a000 { + label = "image-0"; + reg = <0x0000a000 0x00022000>; + }; + + slot1_partition: partition@2c000 { + label = "image-1"; + reg = <0x0002c000 0x00022000>; + }; + + /* 32 KiB (0x8000) for storage */ + storage_partition: partition@4e000 { + label = "storage"; + reg = <0x0004e000 0x00008000>; + }; + + /* CCFG (customer configuration area) is located in uppermost + * flash sector (0x2000/8 KiB @ 0x56000), keep it unused. + */ + }; +}; + &cpu0 { clock-frequency = <48000000>; }; diff --git a/boards/arm/cc1352r1_launchxl/cc1352r1_launchxl.yaml b/boards/arm/cc1352r1_launchxl/cc1352r1_launchxl.yaml index 2491ca0c0a7..7c37a902893 100644 --- a/boards/arm/cc1352r1_launchxl/cc1352r1_launchxl.yaml +++ b/boards/arm/cc1352r1_launchxl/cc1352r1_launchxl.yaml @@ -14,3 +14,5 @@ supported: - spi - watchdog - adc + - hwinfo +vendor: ti diff --git a/boards/arm/cc1352r1_launchxl/doc/index.rst b/boards/arm/cc1352r1_launchxl/doc/index.rst index adece79d1b4..0002b1e1c6f 100644 --- a/boards/arm/cc1352r1_launchxl/doc/index.rst +++ b/boards/arm/cc1352r1_launchxl/doc/index.rst @@ -57,6 +57,8 @@ features: +-----------+------------+----------------------+ | AUX_ADC | on-chip | adc | +-----------+------------+----------------------+ +| HWINFO | on-chip | hwinfo | ++-----------+------------+----------------------+ Other hardware features have not been enabled yet for this board. @@ -130,7 +132,7 @@ Programming and Debugging ************************* Before flashing or debugging ensure the RESET, TMS, TCK, TDO, and TDI jumpers -are in place. Also place jumpers on the the TXD and RXD signals for a serial +are in place. Also place jumpers on the TXD and RXD signals for a serial console using the XDS110 application serial port. Prerequisites: diff --git a/boards/arm/cc1352r_sensortag/cc1352r_sensortag.dts b/boards/arm/cc1352r_sensortag/cc1352r_sensortag.dts index 179efb3c096..b79e4854f73 100644 --- a/boards/arm/cc1352r_sensortag/cc1352r_sensortag.dts +++ b/boards/arm/cc1352r_sensortag/cc1352r_sensortag.dts @@ -29,6 +29,8 @@ sensor2 = &sensor2; accel0 = &sensor1; watchdog0 = &wdt0; + mcuboot-led0 = &led1; + mcuboot-button0 = &btn1; }; chosen { @@ -37,6 +39,7 @@ zephyr,console = &uart0; zephyr,shell-uart = &uart0; zephyr,ieee802154 = &ieee802154; + zephyr,code-partition = &slot0_partition; }; leds { @@ -70,6 +73,37 @@ }; }; +&flash0 { + partitions { + /* 40 KiB (0xa000) for MCUboot */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x0000a000>; + }; + + /* 136 KiB (0x22000) per slot for application */ + slot0_partition: partition@a000 { + label = "image-0"; + reg = <0x0000a000 0x00022000>; + }; + + slot1_partition: partition@2c000 { + label = "image-1"; + reg = <0x0002c000 0x00022000>; + }; + + /* 32 KiB (0x8000) for storage */ + storage_partition: partition@4e000 { + label = "storage"; + reg = <0x0004e000 0x00008000>; + }; + + /* CCFG (customer configuration area) is located in uppermost + * flash sector (0x2000/8 KiB @ 0x56000), keep it unused. + */ + }; +}; + &cpu0 { clock-frequency = <48000000>; }; diff --git a/boards/arm/cc1352r_sensortag/cc1352r_sensortag.yaml b/boards/arm/cc1352r_sensortag/cc1352r_sensortag.yaml index 835d928942a..ab974002e38 100644 --- a/boards/arm/cc1352r_sensortag/cc1352r_sensortag.yaml +++ b/boards/arm/cc1352r_sensortag/cc1352r_sensortag.yaml @@ -14,3 +14,5 @@ supported: - spi - watchdog - adc + - hwinfo +vendor: ti diff --git a/boards/arm/cc1352r_sensortag/doc/index.rst b/boards/arm/cc1352r_sensortag/doc/index.rst index f3843c9505f..c270e85fd57 100644 --- a/boards/arm/cc1352r_sensortag/doc/index.rst +++ b/boards/arm/cc1352r_sensortag/doc/index.rst @@ -65,6 +65,8 @@ features: +-----------+------------+------------------+ | WDT | on-chip | watchdog | +-----------+------------+------------------+ +| HWINFO | on-chip | hwinfo | ++-----------+------------+------------------+ Other hardware features have not been enabled yet for this board. diff --git a/boards/arm/cc26x2r1_launchxl/cc26x2r1_launchxl.dts b/boards/arm/cc26x2r1_launchxl/cc26x2r1_launchxl.dts index 0245c43f622..00b5c7d0507 100644 --- a/boards/arm/cc26x2r1_launchxl/cc26x2r1_launchxl.dts +++ b/boards/arm/cc26x2r1_launchxl/cc26x2r1_launchxl.dts @@ -23,6 +23,8 @@ sw0 = &btn0; sw1 = &btn1; watchdog0 = &wdt0; + mcuboot-led0 = &led1; + mcuboot-button0 = &btn1; }; chosen { @@ -30,6 +32,7 @@ zephyr,flash = &flash0; zephyr,console = &uart0; zephyr,shell-uart = &uart0; + zephyr,code-partition = &slot0_partition; }; leds { @@ -59,6 +62,37 @@ }; }; +&flash0 { + partitions { + /* 40 KiB (0xa000) for MCUboot */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x0000a000>; + }; + + /* 136 KiB (0x22000) per slot for application */ + slot0_partition: partition@a000 { + label = "image-0"; + reg = <0x0000a000 0x00022000>; + }; + + slot1_partition: partition@2c000 { + label = "image-1"; + reg = <0x0002c000 0x00022000>; + }; + + /* 32 KiB (0x8000) for storage */ + storage_partition: partition@4e000 { + label = "storage"; + reg = <0x0004e000 0x00008000>; + }; + + /* CCFG (customer configuration area) is located in uppermost + * flash sector (0x2000/8 KiB @ 0x56000), keep it unused. + */ + }; +}; + &cpu0 { clock-frequency = <48000000>; }; diff --git a/boards/arm/cc26x2r1_launchxl/cc26x2r1_launchxl.yaml b/boards/arm/cc26x2r1_launchxl/cc26x2r1_launchxl.yaml index 6972c004f22..1c2bd9d8876 100644 --- a/boards/arm/cc26x2r1_launchxl/cc26x2r1_launchxl.yaml +++ b/boards/arm/cc26x2r1_launchxl/cc26x2r1_launchxl.yaml @@ -14,3 +14,5 @@ supported: - spi - watchdog - adc + - hwinfo +vendor: ti diff --git a/boards/arm/cc26x2r1_launchxl/doc/index.rst b/boards/arm/cc26x2r1_launchxl/doc/index.rst index 8f2004be90f..8177df13ae3 100644 --- a/boards/arm/cc26x2r1_launchxl/doc/index.rst +++ b/boards/arm/cc26x2r1_launchxl/doc/index.rst @@ -57,6 +57,8 @@ features: +-----------+------------+----------------------+ | AUX_ADC | on-chip | adc | +-----------+------------+----------------------+ +| HWINFO | on-chip | hwinfo | ++-----------+------------+----------------------+ Other hardware features have not been enabled yet for this board. @@ -136,7 +138,7 @@ Programming and Debugging ************************* Before flashing or debugging ensure the RESET, TMS, TCK, TDO, and TDI jumpers -are in place. Also place jumpers on the the TXD and RXD signals for a serial +are in place. Also place jumpers on the TXD and RXD signals for a serial console using the XDS110 application serial port. Prerequisites: diff --git a/boards/arm/cc3220sf_launchxl/cc3220sf_launchxl.yaml b/boards/arm/cc3220sf_launchxl/cc3220sf_launchxl.yaml index 9ef17d92176..2158d5ec453 100644 --- a/boards/arm/cc3220sf_launchxl/cc3220sf_launchxl.yaml +++ b/boards/arm/cc3220sf_launchxl/cc3220sf_launchxl.yaml @@ -12,3 +12,4 @@ supported: - gpio - adc - watchdog +vendor: ti diff --git a/boards/arm/cc3220sf_launchxl/doc/index.rst b/boards/arm/cc3220sf_launchxl/doc/index.rst index 00dad2e5a96..4e941cef91e 100644 --- a/boards/arm/cc3220sf_launchxl/doc/index.rst +++ b/boards/arm/cc3220sf_launchxl/doc/index.rst @@ -172,7 +172,7 @@ Prerequisites: to the paths of the OpenOCD binary and its scripts, before including the common openocd.board.cmake file: - .. code-block:: none + .. code-block:: cmake set(OPENOCD "/usr/local/bin/openocd" CACHE FILEPATH "" FORCE) set(OPENOCD_DEFAULT_PATH /usr/local/share/openocd/scripts) @@ -261,7 +261,7 @@ re-specify the SSID and password. To connect to an AP, first run the Zephyr Wi-Fi shell sample application, and connect to a known AP with SSID and password. -See :ref:`wifi_sample` +See :zephyr:code-sample:`wifi-shell` Once the connection succeeds, the network co-processor keeps the AP identity in its persistent memory. Newly loaded Wi-Fi applications then need not explicitly @@ -284,7 +284,7 @@ and enabled by: keys to the secure flash filesystem, and enabling the TI Trusted Root-Certificate Catalog. -See :ref:`sockets-http-get` and +See :zephyr:code-sample:`sockets-http-get` and :zephyr_file:`samples/net/sockets/http_get/boards/cc3220sf_launchxl.conf` for an example. diff --git a/boards/arm/cc3235sf_launchxl/cc3235sf_launchxl.yaml b/boards/arm/cc3235sf_launchxl/cc3235sf_launchxl.yaml index b40e926d24c..4761555359a 100644 --- a/boards/arm/cc3235sf_launchxl/cc3235sf_launchxl.yaml +++ b/boards/arm/cc3235sf_launchxl/cc3235sf_launchxl.yaml @@ -12,3 +12,4 @@ supported: - gpio - adc - watchdog +vendor: ti diff --git a/boards/arm/cc3235sf_launchxl/doc/index.rst b/boards/arm/cc3235sf_launchxl/doc/index.rst index cb0c5f7858f..80a4fb3c0e9 100644 --- a/boards/arm/cc3235sf_launchxl/doc/index.rst +++ b/boards/arm/cc3235sf_launchxl/doc/index.rst @@ -172,7 +172,7 @@ Prerequisites: to the paths of the OpenOCD binary and its scripts, before including the common openocd.board.cmake file: - .. code-block:: none + .. code-block:: cmake set(OPENOCD "/usr/local/bin/openocd" CACHE FILEPATH "" FORCE) set(OPENOCD_DEFAULT_PATH /usr/local/share/openocd/scripts) @@ -261,7 +261,7 @@ re-specify the SSID and password. To connect to an AP, first run the Zephyr Wi-Fi shell sample application, and connect to a known AP with SSID and password. -See :ref:`wifi_sample` +See :zephyr:code-sample:`wifi-shell` Once the connection succeeds, the network co-processor keeps the AP identity in its persistent memory. Newly loaded Wi-Fi applications then need not explicitly @@ -284,7 +284,7 @@ and enabled by: keys to the secure flash filesystem, and enabling the TI Trusted Root-Certificate Catalog. -See :ref:`sockets-http-get` and +See :zephyr:code-sample:`sockets-http-get` and :zephyr_file:`samples/net/sockets/http_get/boards/cc3235sf_launchxl.conf` for an example. diff --git a/boards/arm/circuitdojo_feather_nrf9160/circuitdojo_feather_nrf9160_defconfig b/boards/arm/circuitdojo_feather_nrf9160/circuitdojo_feather_nrf9160_defconfig index 8d077a6c0ff..f3dc6d6155c 100644 --- a/boards/arm/circuitdojo_feather_nrf9160/circuitdojo_feather_nrf9160_defconfig +++ b/boards/arm/circuitdojo_feather_nrf9160/circuitdojo_feather_nrf9160_defconfig @@ -25,5 +25,3 @@ CONFIG_UART_CONSOLE=y # required to enable 3V3 power rail CONFIG_REGULATOR=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/circuitdojo_feather_nrf9160/circuitdojo_feather_nrf9160_ns_defconfig b/boards/arm/circuitdojo_feather_nrf9160/circuitdojo_feather_nrf9160_ns_defconfig index d38a8dc66ad..9f25a5dda67 100644 --- a/boards/arm/circuitdojo_feather_nrf9160/circuitdojo_feather_nrf9160_ns_defconfig +++ b/boards/arm/circuitdojo_feather_nrf9160/circuitdojo_feather_nrf9160_ns_defconfig @@ -28,5 +28,3 @@ CONFIG_UART_CONSOLE=y # required to enable 3V3 power rail CONFIG_REGULATOR=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/circuitdojo_feather_nrf9160/doc/index.rst b/boards/arm/circuitdojo_feather_nrf9160/doc/index.rst index f6fcb2a5225..f089c468e0d 100644 --- a/boards/arm/circuitdojo_feather_nrf9160/doc/index.rst +++ b/boards/arm/circuitdojo_feather_nrf9160/doc/index.rst @@ -142,8 +142,8 @@ Testing the LEDs and buttons on the nRF9160 Feather There are 2 samples that allow you to test that the buttons (switches) and LEDs on the board are working properly with Zephyr: -* :ref:`blinky-sample` -* :ref:`button-sample` +* :zephyr:code-sample:`blinky` +* :zephyr:code-sample:`button` You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in diff --git a/boards/arm/colibri_imx7d_m4/colibri_imx7d_m4.yaml b/boards/arm/colibri_imx7d_m4/colibri_imx7d_m4.yaml index 4d7dc764e3e..ce87d91e4cd 100644 --- a/boards/arm/colibri_imx7d_m4/colibri_imx7d_m4.yaml +++ b/boards/arm/colibri_imx7d_m4/colibri_imx7d_m4.yaml @@ -20,3 +20,4 @@ testing: - bluetooth supported: - pwm +vendor: nxp diff --git a/boards/arm/contextualelectronics_abc/contextualelectronics_abc.yaml b/boards/arm/contextualelectronics_abc/contextualelectronics_abc.yaml index f6ac7c3fd31..f96fa8c29bf 100644 --- a/boards/arm/contextualelectronics_abc/contextualelectronics_abc.yaml +++ b/boards/arm/contextualelectronics_abc/contextualelectronics_abc.yaml @@ -15,3 +15,4 @@ supported: - i2c - spi - netif:openthread +vendor: contextualelectronics diff --git a/boards/arm/contextualelectronics_abc/contextualelectronics_abc_defconfig b/boards/arm/contextualelectronics_abc/contextualelectronics_abc_defconfig index 7a3055b9c82..fce13936984 100644 --- a/boards/arm/contextualelectronics_abc/contextualelectronics_abc_defconfig +++ b/boards/arm/contextualelectronics_abc/contextualelectronics_abc_defconfig @@ -19,5 +19,3 @@ CONFIG_SERIAL=y # Enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/cy8ckit_062_ble/cy8ckit_062_ble_m0.yaml b/boards/arm/cy8ckit_062_ble/cy8ckit_062_ble_m0.yaml index e67d1d069ab..ee63e4356a5 100644 --- a/boards/arm/cy8ckit_062_ble/cy8ckit_062_ble_m0.yaml +++ b/boards/arm/cy8ckit_062_ble/cy8ckit_062_ble_m0.yaml @@ -20,3 +20,4 @@ supported: - arduino_spi - gpio - spi +vendor: cypress diff --git a/boards/arm/cy8ckit_062_ble/cy8ckit_062_ble_m4.yaml b/boards/arm/cy8ckit_062_ble/cy8ckit_062_ble_m4.yaml index 5349458cbd0..b490c8f3fbe 100644 --- a/boards/arm/cy8ckit_062_ble/cy8ckit_062_ble_m4.yaml +++ b/boards/arm/cy8ckit_062_ble/cy8ckit_062_ble_m4.yaml @@ -18,3 +18,4 @@ toolchain: supported: - arduino_gpio - gpio +vendor: cypress diff --git a/boards/arm/cy8ckit_062_ble/doc/index.rst b/boards/arm/cy8ckit_062_ble/doc/index.rst index af7d2a932f8..7bf45437ca7 100644 --- a/boards/arm/cy8ckit_062_ble/doc/index.rst +++ b/boards/arm/cy8ckit_062_ble/doc/index.rst @@ -190,7 +190,7 @@ Cy_WDT_Disable(). Running on Dual Core ******************** -#. Build the Zephyr kernel and the :ref:`button-sample` sample application: +#. Build the Zephyr kernel and the :zephyr:code-sample:`button` sample application: .. zephyr-app-commands:: :zephyr-app: samples/basic/button diff --git a/boards/arm/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_m0.dts b/boards/arm/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_m0.dts index 6496dcca734..fff6d89ea5d 100644 --- a/boards/arm/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_m0.dts +++ b/boards/arm/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_m0.dts @@ -12,7 +12,7 @@ / { model = "cy8ckit_062_wifi_bt_m0 with a Cypress PSoC6 SoC"; - compatible = "cy8ckit_062_wifi_bt_m0", "PSoC6"; + compatible = "cypress,cy8ckit_062_wifi_bt_m0", "cypress,PSoC6"; aliases { sw0 = &user_bt; diff --git a/boards/arm/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_m0.yaml b/boards/arm/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_m0.yaml index 026450be3fd..a639fc9b700 100644 --- a/boards/arm/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_m0.yaml +++ b/boards/arm/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_m0.yaml @@ -16,3 +16,4 @@ toolchain: - xtools supported: - gpio +vendor: cypress diff --git a/boards/arm/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_m4.dts b/boards/arm/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_m4.dts index 1dfb48fcbeb..e192f94580d 100644 --- a/boards/arm/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_m4.dts +++ b/boards/arm/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_m4.dts @@ -10,7 +10,7 @@ / { model = "cy8ckit_062_wifi_bt_m4 with a Cypress PSoC6 SoC"; - compatible = "cy8ckit_062_wifi_bt_m4", "PSoC6"; + compatible = "cypress,cy8ckit_062_wifi_bt_m4", "cypress,PSoC6"; aliases { uart-5 = &uart5; diff --git a/boards/arm/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_m4.yaml b/boards/arm/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_m4.yaml index b212d41be3e..70c6db96740 100644 --- a/boards/arm/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_m4.yaml +++ b/boards/arm/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_m4.yaml @@ -16,3 +16,4 @@ toolchain: - xtools supported: - gpio +vendor: cypress diff --git a/boards/arm/cy8ckit_062_wifi_bt/doc/index.rst b/boards/arm/cy8ckit_062_wifi_bt/doc/index.rst index 87cb1283246..e1d6d16ef0a 100644 --- a/boards/arm/cy8ckit_062_wifi_bt/doc/index.rst +++ b/boards/arm/cy8ckit_062_wifi_bt/doc/index.rst @@ -187,22 +187,22 @@ References ********** .. _PSoC 62 MCU SoC Website: - http://www.cypress.com/products/32-bit-arm-cortex-m4-psoc-6 + https://www.cypress.com/products/32-bit-arm-cortex-m4-psoc-6 .. _PSoC 62 MCU Datasheet: - http://www.cypress.com/documentation/datasheets/psoc-6-mcu-psoc-62-datasheet-programmable-system-chip-psoc-preliminary + https://www.cypress.com/documentation/datasheets/psoc-6-mcu-psoc-62-datasheet-programmable-system-chip-psoc-preliminary .. _PSoC 62 MCU Architecture Reference Manual: - http://www.cypress.com/documentation/technical-reference-manuals/psoc-6-mcu-psoc-62-architecture-technical-reference-manual + https://www.cypress.com/documentation/technical-reference-manuals/psoc-6-mcu-psoc-62-architecture-technical-reference-manual .. _PSoC 62 MCU Register Reference Manual: - http://www.cypress.com/documentation/technical-reference-manuals/psoc-6-mcu-psoc-62-register-technical-reference-manual-trm + https://www.cypress.com/documentation/technical-reference-manuals/psoc-6-mcu-psoc-62-register-technical-reference-manual-trm .. _CY8CKIT-062-WiFi-BT Website: - http://www.cypress.com/documentation/development-kitsboards/psoc-6-wifi-bt-pioneer-kit + https://www.cypress.com/documentation/development-kitsboards/psoc-6-wifi-bt-pioneer-kit .. _CY8CKIT-062-WiFi-BT User Guide: - http://www.cypress.com/file/407731/download + https://www.cypress.com/file/407731/download .. _CY8CKIT-062-WiFi-BT Schematics: - http://www.cypress.com/file/420846/download + https://www.cypress.com/file/420846/download diff --git a/boards/arm/cy8ckit_062s4/cy8ckit_062s4_m4.yaml b/boards/arm/cy8ckit_062s4/cy8ckit_062s4_m4.yaml index 4cf64830fcf..19391fa39c4 100644 --- a/boards/arm/cy8ckit_062s4/cy8ckit_062s4_m4.yaml +++ b/boards/arm/cy8ckit_062s4/cy8ckit_062s4_m4.yaml @@ -12,3 +12,4 @@ toolchain: - gnuarmemb supported: - gpio +vendor: cypress diff --git a/boards/arm/cy8cproto_062_4343w/Kconfig.defconfig b/boards/arm/cy8cproto_062_4343w/Kconfig.defconfig index 14c47a06e58..ba117ace665 100644 --- a/boards/arm/cy8cproto_062_4343w/Kconfig.defconfig +++ b/boards/arm/cy8cproto_062_4343w/Kconfig.defconfig @@ -10,8 +10,8 @@ config BOARD if WIFI || BT -# Select CYW43XXX part and module -choice CYW43XXX_PART +# Select AIROC part and module +choice AIROC_PART default CYW4343W endchoice @@ -21,6 +21,16 @@ endchoice endif # WIFI || BT +if WIFI + +config WIFI_AIROC + default y + +# Enable L2 Ethernet +config NET_L2_ETHERNET + default y + +endif # WIFI if BT @@ -38,4 +48,9 @@ endchoice endif # BT +# Heap Pool Size +config HEAP_MEM_POOL_SIZE + default 15000 if WIFI + default 4096 + endif # BOARD_CY8CPROTO_062_4343W diff --git a/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w-common.dtsi b/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w-common.dtsi index 3676cdbb471..75012f88ffc 100644 --- a/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w-common.dtsi +++ b/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w-common.dtsi @@ -34,6 +34,10 @@ status = "okay"; }; +&gpio_prt2 { + status = "okay"; +}; + &gpio_prt3 { status = "okay"; }; diff --git a/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w-pinctrl.dtsi b/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w-pinctrl.dtsi index d86f9b67bfa..fcf6655e5d6 100644 --- a/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w-pinctrl.dtsi +++ b/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w-pinctrl.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Rtone. + * Copyright (c) 2023 Cypress Semiconductor Corporation. * SPDX-License-Identifier: Apache-2.0 */ @@ -28,3 +28,53 @@ &p5_0_scb5_uart_rx { input-enable; }; + +/* Configure pin control bias mode for i2c3 pins */ +&p6_0_scb3_i2c_scl { + drive-open-drain; + input-enable; +}; + +&p6_1_scb3_i2c_sda { + drive-open-drain; + input-enable; +}; + +&pinctrl { + /* Configure pin control bias mode for SDIO */ + p2_5_sdio_clk: p2_5_sdio_clk { + pinmux = ; + drive-push-pull; + input-enable; + }; + + p2_4_sdio_cmd: p2_4_sdio_cmd { + pinmux = ; + drive-push-pull; + input-enable; + }; + + p2_0_sdio_data0: p2_0_sdio_data0 { + pinmux = ; + drive-push-pull; + input-enable; + }; + + p2_1_sdio_data1: p2_1_sdio_data1 { + pinmux = ; + drive-push-pull; + input-enable; + }; + + p2_2_sdio_data2: p2_2_sdio_data2 { + pinmux = ; + drive-push-pull; + input-enable; + }; + + p2_3_sdio_data3: p2_3_sdio_data3 { + pinmux = ; + drive-push-pull; + input-enable; + }; +}; diff --git a/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w.dts b/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w.dts index 5ad82d742a6..cc793184b14 100644 --- a/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w.dts +++ b/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w.dts @@ -11,12 +11,13 @@ / { model = "cy8cproto_062_4343w with an Cypress PSoC™ 6 SoC"; - compatible = "cy8cproto_062_4343w", "PSoC6"; + compatible = "cypress,cy8cproto_062_4343w", "cypress,PSoC6"; aliases { uart-5 = &uart5; i2c-0 = &i2c3; watchdog0 = &watchdog0; + sdhc0 = &sdhc0; }; chosen { @@ -50,7 +51,7 @@ uart2: &scb2 { current-speed = <115200>; - /* HCI-UART pins*/ + /* HCI-UART pins */ pinctrl-0 = <&p3_1_scb2_uart_tx &p3_0_scb2_uart_rx &p3_2_scb2_uart_rts &p3_3_scb2_uart_cts>; pinctrl-names = "default"; @@ -68,6 +69,25 @@ uart2: &scb2 { }; }; +&sdhc0 { + status = "okay"; + + /* SDIO pins */ + pinctrl-0 = <&p2_4_sdio_cmd &p2_5_sdio_clk &p2_0_sdio_data0 + &p2_1_sdio_data1 &p2_2_sdio_data2 &p2_3_sdio_data3>; + pinctrl-names = "default"; + + /* Wi-Fi configuration */ + airoc-wifi { + status = "okay"; + compatible = "infineon,airoc-wifi"; + + /* Wi-Fi control gpios */ + wifi-reg-on-gpios = <&gpio_prt2 6 GPIO_ACTIVE_HIGH>; + wifi-host-wake-gpios = <&gpio_prt0 4 GPIO_ACTIVE_HIGH>; + }; +}; + /* System clock configuration */ &fll0 { status = "okay"; diff --git a/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w.yaml b/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w.yaml index 0989469474e..b6d56577209 100644 --- a/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w.yaml +++ b/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w.yaml @@ -14,7 +14,12 @@ toolchain: - gnuarmemb supported: - adc + - bluetooth + - wifi + - airoc + - cyw4343w - counter - gpio - uart - i2c +vendor: cypress diff --git a/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w_defconfig b/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w_defconfig index c36ce13e1a8..3dd8e0eac78 100644 --- a/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w_defconfig +++ b/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w_defconfig @@ -29,3 +29,6 @@ CONFIG_GPIO=y # Enable clock controller CONFIG_CLOCK_CONTROL=y + +# Main Stack Size +CONFIG_MAIN_STACK_SIZE=2048 diff --git a/boards/arm/cy8cproto_062_4343w/doc/index.rst b/boards/arm/cy8cproto_062_4343w/doc/index.rst index b3d0aeeddbf..9cf9c942591 100644 --- a/boards/arm/cy8cproto_062_4343w/doc/index.rst +++ b/boards/arm/cy8cproto_062_4343w/doc/index.rst @@ -101,7 +101,7 @@ To fetch Binary Blobs: Build blinking led sample ************************* -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. code-block:: console @@ -160,16 +160,16 @@ Errata +------------------------------------------------+----------------------------------------+ .. _PSoC 62 MCU SoC Website: - http://www.cypress.com/products/32-bit-arm-cortex-m4-psoc-6 + https://www.cypress.com/products/32-bit-arm-cortex-m4-psoc-6 .. _PSoC 62 MCU Datasheet: - http://www.cypress.com/documentation/datasheets/psoc-6-mcu-psoc-62-datasheet-programmable-system-chip-psoc-preliminary + https://www.cypress.com/documentation/datasheets/psoc-6-mcu-psoc-62-datasheet-programmable-system-chip-psoc-preliminary .. _PSoC 62 MCU Architecture Reference Manual: - http://www.cypress.com/documentation/technical-reference-manuals/psoc-6-mcu-psoc-62-architecture-technical-reference-manual + https://www.cypress.com/documentation/technical-reference-manuals/psoc-6-mcu-psoc-62-architecture-technical-reference-manual .. _PSoC 62 MCU Register Reference Manual: - http://www.cypress.com/documentation/technical-reference-manuals/psoc-6-mcu-psoc-62-register-technical-reference-manual-trm + https://www.cypress.com/documentation/technical-reference-manuals/psoc-6-mcu-psoc-62-register-technical-reference-manual-trm .. _CY8CPROTO-062-4343W PSoC 6 Wi-Fi BT Website: https://www.infineon.com/cms/en/product/evaluation-boards/cy8cproto-062-4343w/ diff --git a/boards/arm/cy8cproto_063_ble/board.cmake b/boards/arm/cy8cproto_063_ble/board.cmake index 79511e34a42..9600fd724ce 100644 --- a/boards/arm/cy8cproto_063_ble/board.cmake +++ b/boards/arm/cy8cproto_063_ble/board.cmake @@ -5,3 +5,6 @@ #*************************************************************************** include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) + +board_runner_args(pyocd "--target=cy8c6xx7_nosmif") +include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) diff --git a/boards/arm/cy8cproto_063_ble/cy8cproto_063_ble.dts b/boards/arm/cy8cproto_063_ble/cy8cproto_063_ble.dts index 228fdeae613..e918f547bd2 100644 --- a/boards/arm/cy8cproto_063_ble/cy8cproto_063_ble.dts +++ b/boards/arm/cy8cproto_063_ble/cy8cproto_063_ble.dts @@ -13,7 +13,7 @@ / { model = "CY8CPROTO-063-BLE PSoC™ 6 BLE Prototyping Kit"; - compatible = "cy8cproto_063_ble", "PSoC6"; + compatible = "cypress,cy8cproto_063_ble", "cypress,PSoC6"; aliases { uart-5 = &uart5; diff --git a/boards/arm/cy8cproto_063_ble/cy8cproto_063_ble.yaml b/boards/arm/cy8cproto_063_ble/cy8cproto_063_ble.yaml index ba6ceaa0f06..1aaef3040d3 100644 --- a/boards/arm/cy8cproto_063_ble/cy8cproto_063_ble.yaml +++ b/boards/arm/cy8cproto_063_ble/cy8cproto_063_ble.yaml @@ -18,3 +18,5 @@ supported: - uart - i2c - watchdog + - spi +vendor: cypress diff --git a/boards/arm/cy8cproto_063_ble/cy8cproto_063_ble_defconfig b/boards/arm/cy8cproto_063_ble/cy8cproto_063_ble_defconfig index bc356fad3b4..a3d7e7beab3 100644 --- a/boards/arm/cy8cproto_063_ble/cy8cproto_063_ble_defconfig +++ b/boards/arm/cy8cproto_063_ble/cy8cproto_063_ble_defconfig @@ -25,6 +25,9 @@ CONFIG_SERIAL=y # Enable pin controller CONFIG_PINCTRL=y +# Enable GPIO +CONFIG_GPIO=y + # Enable clock controller CONFIG_CLOCK_CONTROL=y diff --git a/boards/arm/cy8cproto_063_ble/doc/index.rst b/boards/arm/cy8cproto_063_ble/doc/index.rst index 9757a2d7cc4..58ac2a98183 100644 --- a/boards/arm/cy8cproto_063_ble/doc/index.rst +++ b/boards/arm/cy8cproto_063_ble/doc/index.rst @@ -121,7 +121,7 @@ References ********** .. _PSoC 63 BLE MCU SoC Website: - http://www.cypress.com/products/32-bit-arm-cortex-m4-psoc-6 + https://www.cypress.com/products/32-bit-arm-cortex-m4-psoc-6 .. _PSoC 63 BLE MCU Datasheet: https://www.infineon.com/dgdl/Infineon-PSoC_6_MCU_PSoC_63_with_BLE_Datasheet_Programmable_System-on-Chip_(PSoC)-DataSheet-v16_00-EN.pdf?fileId=8ac78c8c7d0d8da4017d0ee4efe46c37&utm_source=cypress&utm_medium=referral&utm_campaign=202110_globe_en_all_integration-files diff --git a/boards/arm/cyclonev_socdk/cyclonev_socdk.yaml b/boards/arm/cyclonev_socdk/cyclonev_socdk.yaml index 89214e6455e..52f9635c760 100644 --- a/boards/arm/cyclonev_socdk/cyclonev_socdk.yaml +++ b/boards/arm/cyclonev_socdk/cyclonev_socdk.yaml @@ -5,3 +5,4 @@ arch: arm toolchain: - zephyr - gnuarmemb +vendor: altr diff --git a/boards/arm/da14695_dk_usb/Kconfig b/boards/arm/da14695_dk_usb/Kconfig new file mode 100644 index 00000000000..38ccd826507 --- /dev/null +++ b/boards/arm/da14695_dk_usb/Kconfig @@ -0,0 +1,4 @@ +# DA14695 Development Kit USB board configuration + +# Copyright (c) 2023 Renesas Electronics Corporation and/or its affiliates +# SPDX-License-Identifier: Apache-2.0 diff --git a/boards/arm/da14695_dk_usb/Kconfig.board b/boards/arm/da14695_dk_usb/Kconfig.board new file mode 100644 index 00000000000..67dbe731ffa --- /dev/null +++ b/boards/arm/da14695_dk_usb/Kconfig.board @@ -0,0 +1,8 @@ +# DA14695 Development Kit USB board configuration + +# Copyright (c) 2023 Renesas Electronics Corporation and/or its affiliates +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_DA14695_DK_USB + bool "DA14695 Development Kit USB board" + depends on SOC_SERIES_DA1469X diff --git a/boards/arm/da14695_dk_usb/Kconfig.defconfig b/boards/arm/da14695_dk_usb/Kconfig.defconfig new file mode 100644 index 00000000000..8208a705bd8 --- /dev/null +++ b/boards/arm/da14695_dk_usb/Kconfig.defconfig @@ -0,0 +1,11 @@ +# DA14695 Development Kit USB board configuration + +# Copyright (c) 2023 Renesas Electronics Corporation and/or its affiliates +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_DA14695_DK_USB + +config BOARD + default "da14695_dk_usb" + +endif # BOARD_DA14695_DK_USB diff --git a/boards/arm/da14695_dk_usb/board.cmake b/boards/arm/da14695_dk_usb/board.cmake new file mode 100644 index 00000000000..fc5981bb391 --- /dev/null +++ b/boards/arm/da14695_dk_usb/board.cmake @@ -0,0 +1,10 @@ +# +# Copyright (c) 2023 Renesas Electronics Corporation and/or its affiliates +# +# SPDX-License-Identifier: Apache-2.0 +# + +board_runner_args(ezflashcli) +board_runner_args(jlink --device=DA14695) +include(${ZEPHYR_BASE}/boards/common/ezflashcli.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/arm/da14695_dk_usb/da14695_dk_usb-pinctrl.dtsi b/boards/arm/da14695_dk_usb/da14695_dk_usb-pinctrl.dtsi new file mode 100644 index 00000000000..d16ad945fa8 --- /dev/null +++ b/boards/arm/da14695_dk_usb/da14695_dk_usb-pinctrl.dtsi @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023 Renesas Electronics Corporation and/or its affiliates + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + uart_default: uart_default { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + bias-pull-up; + }; + }; + + uart2_default: uart2_default { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + bias-pull-up; + }; + }; + + uart3_default: uart3_default { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + bias-pull-up; + }; + }; + + i2c_default: i2c_default { + group1 { + pinmux = , + ; + bias-pull-up; + }; + }; + + i2c2_default: i2c2_default { + group1 { + pinmux = , + ; + bias-pull-up; + }; + }; + + spi_controller: spi_controller { + group1 { + pinmux = < SMARTBOND_PINMUX(SPI_CLK, 0, 21) >, + ; + output-enable; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + + spi2_controller: spi2_controller { + group1 { + pinmux = < SMARTBOND_PINMUX(SPI2_CLK, 1, 3) >, + ; + output-enable; + }; + group2 { + pinmux = ; + input-enable; + }; + }; +}; diff --git a/boards/arm/da14695_dk_usb/da14695_dk_usb.dts b/boards/arm/da14695_dk_usb/da14695_dk_usb.dts new file mode 100644 index 00000000000..eff5299dcff --- /dev/null +++ b/boards/arm/da14695_dk_usb/da14695_dk_usb.dts @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2023 Renesas Electronics Corporation and/or its affiliates + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "da14695_dk_usb-pinctrl.dtsi" +#include + +/ { + model = "DA14695 series Development Kit USB"; + compatible = "renesas,da14695_dk_usb"; + #address-cells = <1>; + #size-cells = <1>; + + chosen { + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,console = &uart; + zephyr,shell-uart = &uart; + zephyr,code-partition = &slot0_partition; + }; + + leds { + compatible = "gpio-leds"; + red_led: led_0 { + gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + gpios = <&gpio0 6 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; + label = "Push button switch K1"; + zephyr,code = ; + }; + }; + + mikrobus_header{ + mikrobus-connector-1 { + compatible = "mikro-bus"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpio0 25 0>, /* AN */ + /* Not a GPIO*/ /* RST */ + <2 0 &gpio1 2 0>, /* CS */ + <3 0 &gpio1 3 0>, /* SCK */ + <4 0 &gpio1 4 0>, /* MISO */ + <5 0 &gpio1 5 0>, /* MOSI */ + /* +3.3V */ + /* GND */ + <6 0 &gpio1 6 0>, /* PWM */ + <7 0 &gpio1 7 0>, /* INT */ + <8 0 &gpio1 8 0>, /* RX */ + <9 0 &gpio0 17 0>, /* TX */ + <10 0 &gpio0 18 0>, /* SCL */ + <11 0 &gpio0 19 0>; /* SDA */ + /* +5V */ + /* GND */ + }; + mikrobus-connector-2 { + compatible = "mikro-bus"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpio1 9 0>, /* AN */ + /* Not a GPIO*/ /* RST */ + <2 0 &gpio0 20 0>, /* CS */ + <3 0 &gpio0 21 0>, /* SCK */ + <4 0 &gpio0 24 0>, /* MISO */ + <5 0 &gpio0 26 0>, /* MOSI */ + /* +3.3V */ + /* GND */ + <6 0 &gpio1 1 0>, /* PWM */ + <7 0 &gpio0 27 0>, /* INT */ + <8 0 &gpio0 28 0>, /* RX */ + <9 0 &gpio0 29 0>, /* TX */ + <10 0 &gpio0 30 0>, /* SCL */ + <11 0 &gpio0 31 0>; /* SDA */ + /* +5V */ + /* GND */ + }; + }; + + aliases { + led0 = &red_led; + watchdog0 = &wdog; + }; + + sysclk: system-clock { + compatible = "fixed-clock"; + clock-frequency = <32000000>; + #clock-cells = <0>; + }; +}; + +&flash0 { + reg = <0x16000000 DT_SIZE_M(1)>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* + * Flash area from 0x0000 to 0x2400 is reserved + * for product header added by flasher. + */ + + boot_partition: partition@2400 { + label = "mcuboot"; + reg = <0x000002400 0x00009c00>; + }; + slot0_partition: partition@c000 { + label = "image-0"; + reg = <0x0000c000 0x00076000>; + }; + slot1_partition: partition@80000 { + label = "image-1"; + reg = <0x00082000 0x00076000>; + }; + storage_partition: partition@f8000 { + label = "storage"; + reg = <0x000f8000 0x00008000>; + }; + }; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&uart { + current-speed = <115200>; + status = "okay"; + pinctrl-0 = <&uart_default>; + pinctrl-names = "default"; +}; + +&uart2 { + current-speed = <115200>; + status = "okay"; + pinctrl-0 = <&uart2_default>; + pinctrl-names = "default"; +}; + +&uart3 { + current-speed = <115200>; + status = "okay"; + pinctrl-0 = <&uart3_default>; + pinctrl-names = "default"; +}; + +zephyr_udc0: &usbd { + compatible = "renesas,smartbond-usbd"; + status = "okay"; +}; + +&rc32m { + status = "disabled"; +}; + +&xtal32m { + status = "okay"; +}; + +&xtal32k { + status = "okay"; +}; + +&lp_clk { + clock-src = <&xtal32k>; +}; + +&sys_clk { + clock-src = <&xtal32m>; +}; + +&pll { + status = "okay"; +}; +&i2c { + status = "okay"; + pinctrl-0 = <&i2c_default>; + pinctrl-names = "default"; +}; + +&i2c2 { + status = "okay"; + pinctrl-0 = <&i2c2_default>; + pinctrl-names = "default"; +}; + +&spi { + status = "okay"; + pinctrl-0 = <&spi_controller>; + pinctrl-names = "default"; +}; + +&spi2 { + status = "okay"; + pinctrl-0 = <&spi2_controller>; + pinctrl-names = "default"; +}; + +mikrobus_1_i2c: &i2c {}; + +mikrobus_1_spi: &spi {}; + +mikrobus_1_uart: &uart2 {}; + +mikrobus_2_i2c: &i2c2 {}; + +mikrobus_2_spi: &spi2 {}; + +mikrobus_2_uart: &uart3 {}; diff --git a/boards/arm/da14695_dk_usb/da14695_dk_usb.yaml b/boards/arm/da14695_dk_usb/da14695_dk_usb.yaml new file mode 100644 index 00000000000..1bb6100e339 --- /dev/null +++ b/boards/arm/da14695_dk_usb/da14695_dk_usb.yaml @@ -0,0 +1,16 @@ +identifier: da14695_dk_usb +name: DA14695_DK_USB +type: mcu +arch: arm +ram: 512 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - arduino_gpio + - gpio + - watchdog + - i2c + - spi + - usb_device diff --git a/boards/arm/da14695_dk_usb/da14695_dk_usb_defconfig b/boards/arm/da14695_dk_usb/da14695_dk_usb_defconfig new file mode 100644 index 00000000000..d0a67243034 --- /dev/null +++ b/boards/arm/da14695_dk_usb/da14695_dk_usb_defconfig @@ -0,0 +1,22 @@ +# +# Copyright (c) 2023 Renesas Electronics Corporation and/or its affiliates +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_SOC_SERIES_DA1469X=y +CONFIG_SOC_DA14695=y +CONFIG_BOARD_DA14695_DK_USB=y + +CONFIG_HW_STACK_PROTECTION=y + +CONFIG_GPIO=y + +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y + +CONFIG_BUILD_OUTPUT_HEX=n + +CONFIG_I2C=y +CONFIG_I2C_CALLBACK=y diff --git a/boards/arm/da14695_dk_usb/doc/da14695-00hqdevkt-u-usb-board.jpg b/boards/arm/da14695_dk_usb/doc/da14695-00hqdevkt-u-usb-board.jpg new file mode 100644 index 00000000000..1f0c6021e76 Binary files /dev/null and b/boards/arm/da14695_dk_usb/doc/da14695-00hqdevkt-u-usb-board.jpg differ diff --git a/boards/arm/da14695_dk_usb/doc/index.rst b/boards/arm/da14695_dk_usb/doc/index.rst new file mode 100644 index 00000000000..84f5c772d8a --- /dev/null +++ b/boards/arm/da14695_dk_usb/doc/index.rst @@ -0,0 +1,116 @@ +.. _da14695_dk_usb: + +DA14695 Development Kit USB +########################### + +Overview +******** + +The DA14695 Development Kit USB is a low cost development board for DA14695. +The development kit comes with an integrated debugger and an USB hub +to have both the on-chip USB and the J-Link connected via a single port. + +.. figure:: da14695-00hqdevkt-u-usb-board.jpg + :width: 442px + :align: center + :alt: DA14695 Development Kit USB + + DA14695 Development Kit USB (Credit: Renesas Electronics Corporation) + +Hardware +******** + +DA14695 Development Kit USB has two external oscillators. The frequency of +the sleep clock is 32768 Hz. The frequency of the system clock is 32 MHz. + +Supported Features +================== + +The _da14695_dk_usb board configuration supports the following +hardware features: + ++-----------+------------+----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+======================+ +| FLASH | on-chip | flash | ++-----------+------------+----------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+----------------------+ +| MPU | on-chip | arch/arm | ++-----------+------------+----------------------+ +| NVIC | on-chip | arch/arm | ++-----------+------------+----------------------+ +| RTT | Segger | console | ++-----------+------------+----------------------+ +| UART | on-chip | serial | ++-----------+------------+----------------------+ +| SPI | on-chip | spi | ++-----------+------------+----------------------+ + +Other hardware features, including the Configurable MAC (CMAC) controller, +are currently not supported by the port. + +For more information about the DA14695 Development Kit see: + +- `DA14695 DK USB website`_ + +System Clock +============ + +The DA14695 Development Kit USB is configured to use the 32 MHz external oscillator +on the board. + +Connections and IOs +=================== + +The DA14695 Development Kit USB has one LED and one push button which can be used +by applications. The UART is connected to on-board serial converter and accessible +via USB1 port on motherboard. + +The pin connections are as follows: + +* LED (red), = P1.01 +* BUTTON, labeled k1 = P0.06 +* UART RX, connected to J-Link serial = P0.08 +* UART TX, connected to J-Link serial = P0.09 + +Programming and Debugging +************************* + +Applications for the ``da14695_dk_usb`` board configuration can be +built, flashed, and debugged in the usual way. See +:ref:`build_an_application` and :ref:`application_run` for more details on +building and running. + +Flashing +======== + +The DA14695 boots from an external flash connected to QSPI interface. The image +written to flash has to have proper header prepended. The process is simplified +by using dedicated `eZFlashCLI`_ tool that takes care of writing header and can +handle different types of flash chips connected to DA1469x MCU. Follow instructions +on `ezFlashCLI`_ to install the tool. Once installed, flashing can be done in the +usual way. + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: da14695_dk_usb + :goals: build flash + +Debugging +========= + +The DA14695 Development Kit USB includes a `J-Link`_ adaptor built-in +which provides both debugging interface and serial port. +Application can be debugged in the usual way once DA14695 Development Kit USB +is connected to PC via USB. + +References +********** + +.. target-notes:: + +.. _DA14695 DK USB website: https://www.renesas.com/us/en/products/wireless-connectivity/bluetooth-low-energy/da14695-00hqdevkt-u-smartbond-da14695-bluetooth-low-energy-52-usb-development-kit +.. _DA1469x Datasheet: https://www.renesas.com/eu/en/document/dst/da1469x-datasheet +.. _J-Link: https://www.segger.com/jlink-debug-probes.html +.. _ezFlashCLI: https://github.com/ezflash/ezFlashCLI/ diff --git a/boards/arm/da1469x_dk_pro/da1469x_dk_pro.yaml b/boards/arm/da1469x_dk_pro/da1469x_dk_pro.yaml index 4cf50541c1e..e31a2749002 100644 --- a/boards/arm/da1469x_dk_pro/da1469x_dk_pro.yaml +++ b/boards/arm/da1469x_dk_pro/da1469x_dk_pro.yaml @@ -15,3 +15,7 @@ supported: - i2c - spi - usb_device + - rtc + - crypto + - dma +vendor: renesas diff --git a/boards/arm/decawave_dwm1001_dev/decawave_dwm1001_dev.yaml b/boards/arm/decawave_dwm1001_dev/decawave_dwm1001_dev.yaml index 3b9bb82c967..6503c5a3aae 100644 --- a/boards/arm/decawave_dwm1001_dev/decawave_dwm1001_dev.yaml +++ b/boards/arm/decawave_dwm1001_dev/decawave_dwm1001_dev.yaml @@ -11,3 +11,4 @@ flash: 512 supported: - spi - i2c +vendor: decawave diff --git a/boards/arm/decawave_dwm1001_dev/decawave_dwm1001_dev_defconfig b/boards/arm/decawave_dwm1001_dev/decawave_dwm1001_dev_defconfig index 4cb6022e7ae..b77b8937a77 100644 --- a/boards/arm/decawave_dwm1001_dev/decawave_dwm1001_dev_defconfig +++ b/boards/arm/decawave_dwm1001_dev/decawave_dwm1001_dev_defconfig @@ -20,5 +20,3 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_RTT_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/degu_evk/degu_evk.yaml b/boards/arm/degu_evk/degu_evk.yaml index f58303f0b1a..3fd220f4df2 100644 --- a/boards/arm/degu_evk/degu_evk.yaml +++ b/boards/arm/degu_evk/degu_evk.yaml @@ -8,3 +8,4 @@ supported: - i2c - adc - usb_device +vendor: atmarktechno diff --git a/boards/arm/degu_evk/degu_evk_defconfig b/boards/arm/degu_evk/degu_evk_defconfig index e003438c3dc..6123f6c756e 100644 --- a/boards/arm/degu_evk/degu_evk_defconfig +++ b/boards/arm/degu_evk/degu_evk_defconfig @@ -20,5 +20,3 @@ CONFIG_GPIO=y # required to enable 3V3 power rail and Vin1 monitor CONFIG_REGULATOR=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/disco_l475_iot1/Kconfig.defconfig b/boards/arm/disco_l475_iot1/Kconfig.defconfig index 8bf75fa6f7c..847c9ec0878 100644 --- a/boards/arm/disco_l475_iot1/Kconfig.defconfig +++ b/boards/arm/disco_l475_iot1/Kconfig.defconfig @@ -8,10 +8,6 @@ if BOARD_DISCO_L475_IOT1 config BOARD default "disco_l475_iot1" -# LPTIM clocked by LSE, force tick freq to 4096 for tick accuracy -config SYS_CLOCK_TICKS_PER_SEC - default 4096 if STM32_LPTIM_TIMER - config SPI_STM32_INTERRUPT default y depends on SPI diff --git a/boards/arm/disco_l475_iot1/board.cmake b/boards/arm/disco_l475_iot1/board.cmake index e38b92214d9..7e6faf6c383 100644 --- a/boards/arm/disco_l475_iot1/board.cmake +++ b/boards/arm/disco_l475_iot1/board.cmake @@ -1,6 +1,8 @@ # SPDX-License-Identifier: Apache-2.0 +board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") board_runner_args(jlink "--device=STM32L475VG" "--speed=4000") include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) diff --git a/boards/arm/disco_l475_iot1/disco_l475_iot1.dts b/boards/arm/disco_l475_iot1/disco_l475_iot1.dts index fb6b138b931..a37b801b3e4 100644 --- a/boards/arm/disco_l475_iot1/disco_l475_iot1.dts +++ b/boards/arm/disco_l475_iot1/disco_l475_iot1.dts @@ -196,6 +196,8 @@ reset-gpios = <&gpioa 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; irq-gpios = <&gpioe 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; spi-max-frequency = <2000000>; + controller-data-delay-us = <0>; /* No need for extra delay for BlueNRG-MS */ + spi-hold-cs; }; wifi0: ism43362@1 { @@ -288,9 +290,8 @@ zephyr_udc0: &usbotg_fs { }; &adc1 { - pinctrl-0 = <&adc1_in5_pa0 &adc1_in3_pc2 - &adc1_in4_pc3 &adc1_in13_pc4 - &adc1_in14_pc5>; + pinctrl-0 = <&adc1_in3_pc2 &adc1_in4_pc3 + &adc1_in13_pc4 &adc1_in14_pc5>; pinctrl-names = "default"; st,adc-clock-source = ; st,adc-prescaler = <4>; diff --git a/boards/arm/disco_l475_iot1/disco_l475_iot1.yaml b/boards/arm/disco_l475_iot1/disco_l475_iot1.yaml index 4bbb0cfe33f..ca90da9607a 100644 --- a/boards/arm/disco_l475_iot1/disco_l475_iot1.yaml +++ b/boards/arm/disco_l475_iot1/disco_l475_iot1.yaml @@ -27,3 +27,4 @@ supported: - dma ram: 96 flash: 1024 +vendor: st diff --git a/boards/arm/disco_l475_iot1/disco_l475_iot1_defconfig b/boards/arm/disco_l475_iot1/disco_l475_iot1_defconfig index a25b1eff645..072929abda8 100644 --- a/boards/arm/disco_l475_iot1/disco_l475_iot1_defconfig +++ b/boards/arm/disco_l475_iot1/disco_l475_iot1_defconfig @@ -26,3 +26,6 @@ CONFIG_HW_STACK_PROTECTION=y # enable pin controller CONFIG_PINCTRL=y + +# LSE defined as LPTIM clock source by the DTS +CONFIG_STM32_LPTIM_CLOCK_LSE=y diff --git a/boards/arm/disco_l475_iot1/doc/index.rst b/boards/arm/disco_l475_iot1/doc/index.rst index e62bae9b5af..906729fcf8e 100644 --- a/boards/arm/disco_l475_iot1/doc/index.rst +++ b/boards/arm/disco_l475_iot1/doc/index.rst @@ -236,13 +236,13 @@ You can debug an application in the usual way. Here is an example for the :goals: debug .. _Disco L475 IoT1 website: - http://www.st.com/content/st_com/en/products/evaluation-tools/product-evaluation-tools/mcu-eval-tools/stm32-mcu-eval-tools/stm32-mcu-discovery-kits/b-l475e-iot01a.html + https://www.st.com/content/st_com/en/products/evaluation-tools/product-evaluation-tools/mcu-eval-tools/stm32-mcu-eval-tools/stm32-mcu-discovery-kits/b-l475e-iot01a.html .. _STM32 Disco L475 IoT1 board User Manual: - http://www.st.com/resource/en/user_manual/dm00347848.pdf + https://www.st.com/resource/en/user_manual/dm00347848.pdf .. _STM32L475VG on www.st.com: https://www.st.com/en/microcontrollers-microprocessors/stm32l475vg.html .. _STM32L475 reference manual: - http://www.st.com/resource/en/reference_manual/dm00083560.pdf + https://www.st.com/resource/en/reference_manual/dm00083560.pdf diff --git a/boards/arm/dragino_lsn50/doc/index.rst b/boards/arm/dragino_lsn50/doc/index.rst index 68c7732cf69..732e0ec1394 100644 --- a/boards/arm/dragino_lsn50/doc/index.rst +++ b/boards/arm/dragino_lsn50/doc/index.rst @@ -85,7 +85,7 @@ More information about STM32L072CZ can be found here: Supported Features ================== -The Zephyr Dragino LSN50 Board board configuration supports the following hardware features: +The Zephyr Dragino LSN50 board configuration supports the following hardware features: +-----------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | @@ -188,7 +188,7 @@ You can debug an application in the usual way. Here is an example for the https://www.dragino.com/products/lora-lorawan-end-node/item/128-lsn50.html .. _STM32L072CZ on www.st.com: - http://www.st.com/en/microcontrollers/stm32l072cz.html + https://www.st.com/en/microcontrollers/stm32l072cz.html .. _STM32L0x2 reference manual: - http://www.st.com/resource/en/reference_manual/DM00108281.pdf + https://www.st.com/resource/en/reference_manual/DM00108281.pdf diff --git a/boards/arm/dragino_nbsn95/doc/index.rst b/boards/arm/dragino_nbsn95/doc/index.rst index 762125afb3d..ca0b3d8cc1d 100644 --- a/boards/arm/dragino_nbsn95/doc/index.rst +++ b/boards/arm/dragino_nbsn95/doc/index.rst @@ -84,7 +84,7 @@ More information about STM32L072CZ can be found here: Supported Features ================== -The Zephyr Dragino NBSN95 Board board configuration supports the following hardware features: +The Zephyr Dragino NBSN95 board configuration supports the following hardware features: +-----------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | @@ -187,7 +187,7 @@ You can debug an application in the usual way. Here is an example for the https://www.dragino.com/products/nb-iot/item/163-nbsn95.html .. _STM32L072CZ on www.st.com: - http://www.st.com/en/microcontrollers/stm32l072cz.html + https://www.st.com/en/microcontrollers/stm32l072cz.html .. _STM32L0x2 reference manual: - http://www.st.com/resource/en/reference_manual/DM00108281.pdf + https://www.st.com/resource/en/reference_manual/DM00108281.pdf diff --git a/boards/arm/ebyte_e73_tbb_nrf52832/doc/index.rst b/boards/arm/ebyte_e73_tbb_nrf52832/doc/index.rst index 8fd7dde6967..5b0f88f88a6 100644 --- a/boards/arm/ebyte_e73_tbb_nrf52832/doc/index.rst +++ b/boards/arm/ebyte_e73_tbb_nrf52832/doc/index.rst @@ -206,8 +206,8 @@ the board are working properly with Zephyr: .. code-block:: console - :ref:`blinky-sample` - :ref:`button-sample` + :zephyr:code-sample:`blinky` + :zephyr:code-sample:`button` You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in diff --git a/boards/arm/ebyte_e73_tbb_nrf52832/ebyte_e73_tbb_nrf52832_defconfig b/boards/arm/ebyte_e73_tbb_nrf52832/ebyte_e73_tbb_nrf52832_defconfig index 05acf2ca945..8b9a09a8e8d 100644 --- a/boards/arm/ebyte_e73_tbb_nrf52832/ebyte_e73_tbb_nrf52832_defconfig +++ b/boards/arm/ebyte_e73_tbb_nrf52832/ebyte_e73_tbb_nrf52832_defconfig @@ -22,5 +22,3 @@ CONFIG_SERIAL=y # Enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/efm32gg_sltb009a/efm32gg_sltb009a.yaml b/boards/arm/efm32gg_sltb009a/efm32gg_sltb009a.yaml index 44370cc391d..ddea24692fa 100644 --- a/boards/arm/efm32gg_sltb009a/efm32gg_sltb009a.yaml +++ b/boards/arm/efm32gg_sltb009a/efm32gg_sltb009a.yaml @@ -13,3 +13,4 @@ supported: testing: ignore_tags: - bluetooth +vendor: silabs diff --git a/boards/arm/efm32gg_slwstk6121a/efm32gg_slwstk6121a-pinctrl.dtsi b/boards/arm/efm32gg_slwstk6121a/efm32gg_slwstk6121a-pinctrl.dtsi new file mode 100644 index 00000000000..ade31fddfd8 --- /dev/null +++ b/boards/arm/efm32gg_slwstk6121a/efm32gg_slwstk6121a-pinctrl.dtsi @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + /* configuration for usart0 device, default state - operating as UART */ + usart0_default: usart0_default { + group1 { + psels = , + , + , + ; + }; + }; +}; diff --git a/boards/arm/efm32gg_slwstk6121a/efm32gg_slwstk6121a.dts b/boards/arm/efm32gg_slwstk6121a/efm32gg_slwstk6121a.dts index a45d13f7183..10912535b2d 100644 --- a/boards/arm/efm32gg_slwstk6121a/efm32gg_slwstk6121a.dts +++ b/boards/arm/efm32gg_slwstk6121a/efm32gg_slwstk6121a.dts @@ -9,6 +9,7 @@ /dts-v1/; #include #include +#include "efm32gg_slwstk6121a-pinctrl.dtsi" / { model = "Silicon Labs EFM32GG SLWSTK6121A board"; @@ -62,8 +63,8 @@ /* Connected to the WSTK VCOM */ &usart0 { current-speed = <115200>; - location-rx = ; - location-tx = ; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; status = "okay"; }; diff --git a/boards/arm/efm32gg_slwstk6121a/efm32gg_slwstk6121a.yaml b/boards/arm/efm32gg_slwstk6121a/efm32gg_slwstk6121a.yaml index 057e565b9a4..9e976e5ccaa 100644 --- a/boards/arm/efm32gg_slwstk6121a/efm32gg_slwstk6121a.yaml +++ b/boards/arm/efm32gg_slwstk6121a/efm32gg_slwstk6121a.yaml @@ -18,3 +18,4 @@ supported: testing: ignore_tags: - bluetooth +vendor: silabs diff --git a/boards/arm/efm32gg_stk3701a/efm32gg_stk3701a-pinctrl.dtsi b/boards/arm/efm32gg_stk3701a/efm32gg_stk3701a-pinctrl.dtsi new file mode 100644 index 00000000000..8bb7025f4b2 --- /dev/null +++ b/boards/arm/efm32gg_stk3701a/efm32gg_stk3701a-pinctrl.dtsi @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + /* configuration for usart0 device, default state - operating as UART */ + usart0_default: usart0_default { + group1 { + psels = , + , + , + ; + }; + }; + + usart4_default: usart4_default { + group1 { + psels = , + , + , + ; + }; + }; +}; diff --git a/boards/arm/efm32gg_stk3701a/efm32gg_stk3701a.dts b/boards/arm/efm32gg_stk3701a/efm32gg_stk3701a.dts index 970cbafa1a2..1c457890f91 100644 --- a/boards/arm/efm32gg_stk3701a/efm32gg_stk3701a.dts +++ b/boards/arm/efm32gg_stk3701a/efm32gg_stk3701a.dts @@ -8,6 +8,7 @@ /dts-v1/; #include #include +#include "efm32gg_stk3701a-pinctrl.dtsi" / { model = "Silicon Labs EFM32GG STK3701A board"; @@ -60,15 +61,15 @@ &usart0 { current-speed = <115200>; - location-rx = ; - location-tx = ; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; status = "okay"; }; &usart4 { current-speed = <115200>; - location-rx = ; - location-tx = ; + pinctrl-0 = <&usart4_default>; + pinctrl-names = "default"; status = "okay"; }; diff --git a/boards/arm/efm32gg_stk3701a/efm32gg_stk3701a.yaml b/boards/arm/efm32gg_stk3701a/efm32gg_stk3701a.yaml index c2cad793872..426328eae97 100644 --- a/boards/arm/efm32gg_stk3701a/efm32gg_stk3701a.yaml +++ b/boards/arm/efm32gg_stk3701a/efm32gg_stk3701a.yaml @@ -16,3 +16,4 @@ supported: testing: ignore_tags: - bluetooth +vendor: silabs diff --git a/boards/arm/efm32hg_slstk3400a/efm32hg_slstk3400a.yaml b/boards/arm/efm32hg_slstk3400a/efm32hg_slstk3400a.yaml index 5ca83c3d259..d14ffbbd10a 100644 --- a/boards/arm/efm32hg_slstk3400a/efm32hg_slstk3400a.yaml +++ b/boards/arm/efm32hg_slstk3400a/efm32hg_slstk3400a.yaml @@ -15,3 +15,4 @@ testing: ignore_tags: - net - bluetooth +vendor: silabs diff --git a/boards/arm/efm32pg_stk3401a/efm32pg_stk3401a.yaml b/boards/arm/efm32pg_stk3401a/efm32pg_stk3401a.yaml index 0c77d371c51..ee707a08caa 100644 --- a/boards/arm/efm32pg_stk3401a/efm32pg_stk3401a.yaml +++ b/boards/arm/efm32pg_stk3401a/efm32pg_stk3401a.yaml @@ -17,3 +17,4 @@ testing: ignore_tags: - net - bluetooth +vendor: silabs diff --git a/boards/arm/efm32pg_stk3402a/efm32pg_stk3402a.yaml b/boards/arm/efm32pg_stk3402a/efm32pg_stk3402a.yaml index 707e1b02169..ebfe95c91ba 100644 --- a/boards/arm/efm32pg_stk3402a/efm32pg_stk3402a.yaml +++ b/boards/arm/efm32pg_stk3402a/efm32pg_stk3402a.yaml @@ -17,3 +17,4 @@ testing: ignore_tags: - net - bluetooth +vendor: silabs diff --git a/boards/arm/efm32pg_stk3402a/efm32pg_stk3402a_jg.yaml b/boards/arm/efm32pg_stk3402a/efm32pg_stk3402a_jg.yaml index 66e272e8cef..8d7e590e393 100644 --- a/boards/arm/efm32pg_stk3402a/efm32pg_stk3402a_jg.yaml +++ b/boards/arm/efm32pg_stk3402a/efm32pg_stk3402a_jg.yaml @@ -16,3 +16,4 @@ testing: ignore_tags: - net - bluetooth +vendor: silabs diff --git a/boards/arm/efm32wg_stk3800/efm32wg_stk3800.yaml b/boards/arm/efm32wg_stk3800/efm32wg_stk3800.yaml index 449ea45eb83..acd28a6623d 100644 --- a/boards/arm/efm32wg_stk3800/efm32wg_stk3800.yaml +++ b/boards/arm/efm32wg_stk3800/efm32wg_stk3800.yaml @@ -15,3 +15,4 @@ testing: ignore_tags: - net - bluetooth +vendor: silabs diff --git a/boards/arm/efr32_radio/CMakeLists.txt b/boards/arm/efr32_radio/CMakeLists.txt deleted file mode 100644 index 77a7880c491..00000000000 --- a/boards/arm/efr32_radio/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 -zephyr_include_directories(.) diff --git a/boards/arm/efr32_radio/Kconfig.board b/boards/arm/efr32_radio/Kconfig.board index 6a9175aa9c3..6104a3884f0 100644 --- a/boards/arm/efr32_radio/Kconfig.board +++ b/boards/arm/efr32_radio/Kconfig.board @@ -11,6 +11,12 @@ config BOARD_EFR32_RADIO_BRD4104A select BOARD_EFR32_RADIO select SOC_PART_NUMBER_EFR32BG13P632F512GM48 +config BOARD_EFR32_RADIO_BRD4170A + bool "Silicon Labs BRD4170A (Mighty Gecko Radio Board)" + depends on SOC_SERIES_EFR32MG12P + select BOARD_EFR32_RADIO + select SOC_PART_NUMBER_EFR32MG12P433F1024GM68 + config BOARD_EFR32_RADIO_BRD4250B bool "Silicon Labs BRD4250B (Flex Gecko Radio Board)" depends on SOC_SERIES_EFR32FG1P diff --git a/boards/arm/efr32_radio/Kconfig.defconfig b/boards/arm/efr32_radio/Kconfig.defconfig index cf4be7c9dde..39c4b9ff695 100644 --- a/boards/arm/efr32_radio/Kconfig.defconfig +++ b/boards/arm/efr32_radio/Kconfig.defconfig @@ -8,6 +8,7 @@ if BOARD_EFR32_RADIO config BOARD default "efr32_radio_brd4104a" if BOARD_EFR32_RADIO_BRD4104A + default "efr32_radio_brd4170a" if BOARD_EFR32_RADIO_BRD4170A default "efr32_radio_brd4250b" if BOARD_EFR32_RADIO_BRD4250B default "efr32_radio_brd4180a" if BOARD_EFR32_RADIO_BRD4180A default "efr32_radio_brd4187c" if BOARD_EFR32_RADIO_BRD4187C @@ -32,6 +33,7 @@ config LOG_BACKEND_SWO_FREQ_HZ if SOC_GECKO_USE_RAIL config FPU + default n if SOC_GECKO_SERIES1 default y endif # SOC_GECKO_USE_RAIL diff --git a/boards/arm/efr32_radio/board.cmake b/boards/arm/efr32_radio/board.cmake index c43175d6b01..95eaa403fcb 100644 --- a/boards/arm/efr32_radio/board.cmake +++ b/boards/arm/efr32_radio/board.cmake @@ -6,6 +6,8 @@ if(CONFIG_BOARD_EFR32_RADIO_BRD4104A) board_runner_args(jlink "--device=EFR32BG13PxxxF512") elseif(CONFIG_BOARD_EFR32_RADIO_BRD4250B) board_runner_args(jlink "--device=EFR32FG1PxxxF256") +elseif(CONFIG_BOARD_EFR32_RADIO_BRD4170A) +board_runner_args(jlink "--device=EFR32MG12PxxxF1024") elseif(CONFIG_BOARD_EFR32_RADIO_BRD4180A) board_runner_args(jlink "--device=EFR32MG21AxxxF1024") elseif(CONFIG_BOARD_EFR32_RADIO_BRD4187C) diff --git a/boards/arm/efr32_radio/doc/brd4170a.rst b/boards/arm/efr32_radio/doc/brd4170a.rst new file mode 100644 index 00000000000..9924c2b1d1a --- /dev/null +++ b/boards/arm/efr32_radio/doc/brd4170a.rst @@ -0,0 +1,109 @@ +.. _efr32_radio_brd4170a: + +EFR32 BRD4170A (SLWRB4170A) +########################### + +Overview +******** + +The EFR32MG12 Mighty Gecko Radio Board contains a Wireless System-On-Chip +from the EFR32MG12 family built on an ARM Cortex®-M4F processor with excellent +low power capabilities. + +.. figure:: efr32mg12-slwrb4170a.jpg + :align: center + :alt: SLWRB4170A Mighty Gecko Radio Board + + SLWRB4170A (image courtesy of Silicon Labs) + +The BRD4170A a.k.a. SLWRB4170A radio board plugs into the Wireless Starter Kit +Mainboard BRD4001A and is supported as one of :ref:`efr32_radio`. + +Hardware +******** + +- EFR32MG12P433F1024GM68 Mighty Gecko SoC +- CPU core: ARM Cortex®-M4 with FPU +- Flash memory: 1024 kB +- RAM: 256 kB +- Transmit power: up to +19 dBm +- Operation frequency: 2.4 GHz and Sub-Ghz +- Crystals for LFXO (32.768 kHz) and HFXO (38.4 MHz). + +For more information about the EFR32MG12 SoC and BRD4170A board, refer to these +documents: + +- `EFR32MG12 Website`_ +- `EFR32MG12 Datasheet`_ +- `EFR32xG12 Reference Manual`_ +- `BRD4170A User Guide`_ + +Supported Features +================== + +Please refer to +:ref:`EFR32 Radio Board Supported Features ` +for details of the configuration and common features supported by the +efr32_radio_brd4170a board. + +The default configuration can be found in the defconfig file: + + ``boards/arm/efr32_radio/efr32_radio_brd4170a_defconfig`` + +System Clock +============ + +The EFR32MG12P SoC is configured to use the 38.4 MHz external oscillator on the +board. + +Serial Port +=========== + +The EFR32MG12P SoC has four USARTs and one Low Energy UARTs (LEUART). +USART0 is connected to the board controller and is used for the console. + +Programming and Debugging +************************* + +Please refer to +:ref:`Programming and Debugging EFR32 Radio Board ` +for details on the supported debug interfaces. + +Flashing +======== + +Connect the BRD4001A board with a mounted BRD4170A radio module to your host +computer using the USB port. + +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: efr32_radio_brd4170a + :goals: flash + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you should see the following message in the terminal: + +.. code-block:: console + + Hello World! efr32_radio_brd4170a + + +.. _EFR32MG12 Website: + https://www.silabs.com/wireless/zigbee/efr32mg12-series-1-socs + +.. _EFR32MG12 Datasheet: + https://www.silabs.com/documents/public/data-sheets/efr32mg12-datasheet.pdf + +.. _EFR32xG12 Reference Manual: + https://www.silabs.com/documents/public/reference-manuals/efr32xg12-rm.pdf + +.. _BRD4170A User Guide: + https://www.silabs.com/documents/public/user-guides/ug342-brd4170a-user-guide.pdf diff --git a/boards/arm/efr32_radio/doc/efr32mg12-slwrb4170a.jpg b/boards/arm/efr32_radio/doc/efr32mg12-slwrb4170a.jpg new file mode 100644 index 00000000000..516438918cb Binary files /dev/null and b/boards/arm/efr32_radio/doc/efr32mg12-slwrb4170a.jpg differ diff --git a/boards/arm/efr32_radio/doc/index.rst b/boards/arm/efr32_radio/doc/index.rst index 43990cac492..31f79df34e0 100644 --- a/boards/arm/efr32_radio/doc/index.rst +++ b/boards/arm/efr32_radio/doc/index.rst @@ -7,6 +7,7 @@ EFR32 Radio Boards :maxdepth: 1 brd4104a.rst + brd4170a.rst brd4250b.rst brd4180a.rst brd4255a.rst diff --git a/boards/arm/efr32_radio/efr32_radio-pinctrl.dtsi b/boards/arm/efr32_radio/efr32_radio-pinctrl.dtsi new file mode 100644 index 00000000000..ade31fddfd8 --- /dev/null +++ b/boards/arm/efr32_radio/efr32_radio-pinctrl.dtsi @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + /* configuration for usart0 device, default state - operating as UART */ + usart0_default: usart0_default { + group1 { + psels = , + , + , + ; + }; + }; +}; diff --git a/boards/arm/efr32_radio/efr32_radio.dtsi b/boards/arm/efr32_radio/efr32_radio.dtsi index a82081de469..361b66b72df 100644 --- a/boards/arm/efr32_radio/efr32_radio.dtsi +++ b/boards/arm/efr32_radio/efr32_radio.dtsi @@ -5,6 +5,7 @@ */ #include +#include "efr32_radio-pinctrl.dtsi" / { chosen { @@ -57,8 +58,8 @@ &usart0 { current-speed = <115200>; - location-rx = ; - location-tx = ; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; status = "okay"; }; diff --git a/boards/arm/efr32_radio/efr32_radio_brd4104a.yaml b/boards/arm/efr32_radio/efr32_radio_brd4104a.yaml index 163de36c884..62e253011c7 100644 --- a/boards/arm/efr32_radio/efr32_radio_brd4104a.yaml +++ b/boards/arm/efr32_radio/efr32_radio_brd4104a.yaml @@ -19,3 +19,4 @@ testing: ignore_tags: - net - bluetooth +vendor: silabs diff --git a/boards/arm/efr32_radio/efr32_radio_brd4170a.dts b/boards/arm/efr32_radio/efr32_radio_brd4170a.dts new file mode 100644 index 00000000000..ed7e2f992a1 --- /dev/null +++ b/boards/arm/efr32_radio/efr32_radio_brd4170a.dts @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2020 Piotr Mienkowski + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include "efr32_radio.dtsi" + +/ { + model = "Silicon Labs BRD4170A (Mighty Gecko Radio Board)"; + compatible = "silabs,efr32_radio_brd4170a", "silabs,efr32mg12p"; + + aliases { + spi-flash0 = &mx25r80; + }; +}; + +&cpu0 { + clock-frequency = <38400000>; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserve 32 kB for the bootloader */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x0 0x00008000>; + read-only; + }; + + /* Reserve 220 kB for the application in slot 0 */ + slot0_partition: partition@8000 { + label = "image-0"; + reg = <0x00008000 0x00037000>; + }; + + /* Reserve 220 kB for the application in slot 1 */ + slot1_partition: partition@3f000 { + label = "image-1"; + reg = <0x0003f000 0x00037000>; + }; + + /* Reserve 32 kB for the scratch partition */ + scratch_partition: partition@76000 { + label = "image-scratch"; + reg = <0x00076000 0x00008000>; + }; + + /* Set 8Kb of storage at the end of the 512KB of flash */ + storage_partition: partition@7e000 { + label = "storage"; + reg = <0x0007e000 0x00002000>; + }; + + }; +}; + +&usart0 { + current-speed = <115200>; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/boards/arm/efr32_radio/efr32_radio_brd4170a.yaml b/boards/arm/efr32_radio/efr32_radio_brd4170a.yaml new file mode 100644 index 00000000000..88ed4089379 --- /dev/null +++ b/boards/arm/efr32_radio/efr32_radio_brd4170a.yaml @@ -0,0 +1,21 @@ +identifier: efr32_radio_brd4170a +name: BRD4170A +type: mcu +arch: arm +ram: 256 +flash: 1024 +toolchain: + - zephyr + - gnuarmemb +supported: + - counter + - gpio + - nvs + - spi + - uart + - watchdog +testing: + ignore_tags: + - net + - bluetooth +vendor: silabs diff --git a/boards/arm/efr32_radio/efr32_radio_brd4170a_defconfig b/boards/arm/efr32_radio/efr32_radio_brd4170a_defconfig new file mode 100644 index 00000000000..32222b89b31 --- /dev/null +++ b/boards/arm/efr32_radio/efr32_radio_brd4170a_defconfig @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_ARM_MPU=y +CONFIG_SOC_SERIES_EFR32MG12P=y +CONFIG_BOARD_EFR32_RADIO_BRD4170A=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_GPIO=y +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=38400000 +CONFIG_CMU_HFCLK_HFXO=y +CONFIG_SOC_GECKO_EMU_DCDC=y +CONFIG_SOC_GECKO_EMU_DCDC_MODE_ON=y diff --git a/boards/arm/efr32_radio/efr32_radio_brd4180a.yaml b/boards/arm/efr32_radio/efr32_radio_brd4180a.yaml index 93681703fde..ea286ce3c65 100644 --- a/boards/arm/efr32_radio/efr32_radio_brd4180a.yaml +++ b/boards/arm/efr32_radio/efr32_radio_brd4180a.yaml @@ -18,3 +18,4 @@ testing: ignore_tags: - net - bluetooth +vendor: silabs diff --git a/boards/arm/efr32_radio/efr32_radio_brd4180a_defconfig b/boards/arm/efr32_radio/efr32_radio_brd4180a_defconfig index 79da19d5462..0db69e5d9e1 100644 --- a/boards/arm/efr32_radio/efr32_radio_brd4180a_defconfig +++ b/boards/arm/efr32_radio/efr32_radio_brd4180a_defconfig @@ -9,3 +9,4 @@ CONFIG_SERIAL=y CONFIG_GPIO=y CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=38400000 CONFIG_CMU_HFCLK_HFXO=y +CONFIG_PINCTRL=y diff --git a/boards/arm/efr32_radio/efr32_radio_brd4187c.yaml b/boards/arm/efr32_radio/efr32_radio_brd4187c.yaml index 3e9b730855c..a5602114a36 100644 --- a/boards/arm/efr32_radio/efr32_radio_brd4187c.yaml +++ b/boards/arm/efr32_radio/efr32_radio_brd4187c.yaml @@ -18,3 +18,4 @@ testing: - bluetooth - pm - hwinfo +vendor: silabs diff --git a/boards/arm/efr32_radio/efr32_radio_brd4187c_defconfig b/boards/arm/efr32_radio/efr32_radio_brd4187c_defconfig index ce32a6638c3..046f8acfaed 100644 --- a/boards/arm/efr32_radio/efr32_radio_brd4187c_defconfig +++ b/boards/arm/efr32_radio/efr32_radio_brd4187c_defconfig @@ -10,6 +10,7 @@ CONFIG_GPIO=y CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=78000000 CONFIG_SOC_GECKO_EMU_DCDC=y CONFIG_SOC_GECKO_EMU_DCDC_MODE_ON=y +CONFIG_PINCTRL=y # Use BURTC as system clock source CONFIG_GECKO_BURTC_TIMER=y diff --git a/boards/arm/efr32_radio/efr32_radio_brd4250b.dts b/boards/arm/efr32_radio/efr32_radio_brd4250b.dts index 531f3bf1094..2167b1b69b7 100644 --- a/boards/arm/efr32_radio/efr32_radio_brd4250b.dts +++ b/boards/arm/efr32_radio/efr32_radio_brd4250b.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include #include "efr32_radio.dtsi" / { @@ -79,3 +80,10 @@ }; }; + +&usart0 { + current-speed = <115200>; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/boards/arm/efr32_radio/efr32_radio_brd4250b.yaml b/boards/arm/efr32_radio/efr32_radio_brd4250b.yaml index 9a3b3996733..0d45527eced 100644 --- a/boards/arm/efr32_radio/efr32_radio_brd4250b.yaml +++ b/boards/arm/efr32_radio/efr32_radio_brd4250b.yaml @@ -19,3 +19,4 @@ testing: ignore_tags: - net - bluetooth +vendor: silabs diff --git a/boards/arm/efr32_radio/efr32_radio_brd4255a.dts b/boards/arm/efr32_radio/efr32_radio_brd4255a.dts index de019e6d1e8..cf146428322 100644 --- a/boards/arm/efr32_radio/efr32_radio_brd4255a.dts +++ b/boards/arm/efr32_radio/efr32_radio_brd4255a.dts @@ -7,6 +7,7 @@ /dts-v1/; #include +#include #include "efr32_radio.dtsi" / { @@ -57,3 +58,10 @@ }; }; + +&usart0 { + current-speed = <115200>; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/boards/arm/efr32_radio/efr32_radio_brd4255a.yaml b/boards/arm/efr32_radio/efr32_radio_brd4255a.yaml index 34923d504c5..a5b7fc7cb90 100644 --- a/boards/arm/efr32_radio/efr32_radio_brd4255a.yaml +++ b/boards/arm/efr32_radio/efr32_radio_brd4255a.yaml @@ -19,3 +19,4 @@ testing: ignore_tags: - net - bluetooth +vendor: silabs diff --git a/boards/arm/efr32_radio/sl_device_init_hfxo_config.h b/boards/arm/efr32_radio/sl_device_init_hfxo_config.h deleted file mode 100644 index c410e7c4093..00000000000 --- a/boards/arm/efr32_radio/sl_device_init_hfxo_config.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2023 Antmicro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef SL_DEVICE_INIT_HFXO_CONFIG_H -#define SL_DEVICE_INIT_HFXO_CONFIG_H - -#ifdef CONFIG_BOARD_EFR32_RADIO_BRD4187C - -#define SL_DEVICE_INIT_HFXO_MODE cmuHfxoOscMode_Crystal -#define SL_DEVICE_INIT_HFXO_FREQ 39000000 -#define SL_DEVICE_INIT_HFXO_CTUNE 140 - -#endif /* CONFIG_BOARD_EFR32_RADIO_BRD4187C */ - -#endif /* SL_DEVICE_INIT_HFXO_CONFIG_H */ diff --git a/boards/arm/efr32_thunderboard/CMakeLists.txt b/boards/arm/efr32_thunderboard/CMakeLists.txt index 17faf560add..ca93e65ac91 100644 --- a/boards/arm/efr32_thunderboard/CMakeLists.txt +++ b/boards/arm/efr32_thunderboard/CMakeLists.txt @@ -5,5 +5,3 @@ if(CONFIG_UART_GECKO) zephyr_library() zephyr_library_sources(board.c) endif() - -zephyr_include_directories(.) diff --git a/boards/arm/efr32_thunderboard/efr32bg22_brd4184a.yaml b/boards/arm/efr32_thunderboard/efr32bg22_brd4184a.yaml index 560ce77335f..37bc5bed239 100644 --- a/boards/arm/efr32_thunderboard/efr32bg22_brd4184a.yaml +++ b/boards/arm/efr32_thunderboard/efr32bg22_brd4184a.yaml @@ -18,3 +18,4 @@ testing: ignore_tags: - net - bluetooth +vendor: silabs diff --git a/boards/arm/efr32_thunderboard/efr32bg22_brd4184b.yaml b/boards/arm/efr32_thunderboard/efr32bg22_brd4184b.yaml index 86e8e01dae3..40c6377a277 100644 --- a/boards/arm/efr32_thunderboard/efr32bg22_brd4184b.yaml +++ b/boards/arm/efr32_thunderboard/efr32bg22_brd4184b.yaml @@ -18,3 +18,4 @@ testing: ignore_tags: - net - bluetooth +vendor: silabs diff --git a/boards/arm/efr32_thunderboard/efr32bg27_brd2602a.yaml b/boards/arm/efr32_thunderboard/efr32bg27_brd2602a.yaml index 819e07ed65e..844a48854d5 100644 --- a/boards/arm/efr32_thunderboard/efr32bg27_brd2602a.yaml +++ b/boards/arm/efr32_thunderboard/efr32bg27_brd2602a.yaml @@ -16,3 +16,4 @@ testing: ignore_tags: - net - bluetooth +vendor: silabs diff --git a/boards/arm/efr32_thunderboard/sl_device_init_hfxo_config.h b/boards/arm/efr32_thunderboard/sl_device_init_hfxo_config.h deleted file mode 100644 index 1b803c74f3d..00000000000 --- a/boards/arm/efr32_thunderboard/sl_device_init_hfxo_config.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2022 Antmicro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef SL_DEVICE_INIT_HFXO_CONFIG_H -#define SL_DEVICE_INIT_HFXO_CONFIG_H - -#define SL_DEVICE_INIT_HFXO_MODE cmuHfxoOscMode_Crystal -#define SL_DEVICE_INIT_HFXO_FREQ 38400000 -#define SL_DEVICE_INIT_HFXO_CTUNE 120 - -#endif /* SL_DEVICE_INIT_HFXO_CONFIG_H */ diff --git a/boards/arm/efr32_thunderboard/thunderboard.dtsi b/boards/arm/efr32_thunderboard/thunderboard.dtsi index 31387b87609..be2401138ad 100644 --- a/boards/arm/efr32_thunderboard/thunderboard.dtsi +++ b/boards/arm/efr32_thunderboard/thunderboard.dtsi @@ -5,6 +5,7 @@ */ #include +#include / { chosen { diff --git a/boards/arm/efr32mg_sltb004a/efr32mg_sltb004a.dts b/boards/arm/efr32mg_sltb004a/efr32mg_sltb004a.dts index 1a746d53e61..6bdc5be574f 100644 --- a/boards/arm/efr32mg_sltb004a/efr32mg_sltb004a.dts +++ b/boards/arm/efr32mg_sltb004a/efr32mg_sltb004a.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include #include / { @@ -74,8 +75,8 @@ &usart0 { current-speed = <115200>; - location-rx = ; - location-tx = ; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; status = "okay"; }; diff --git a/boards/arm/efr32mg_sltb004a/efr32mg_sltb004a.yaml b/boards/arm/efr32mg_sltb004a/efr32mg_sltb004a.yaml index 7565e1288c5..3c8cbd773d0 100644 --- a/boards/arm/efr32mg_sltb004a/efr32mg_sltb004a.yaml +++ b/boards/arm/efr32mg_sltb004a/efr32mg_sltb004a.yaml @@ -18,3 +18,4 @@ testing: ignore_tags: - net - bluetooth +vendor: silabs diff --git a/boards/arm/efr32xg24_dk2601b/CMakeLists.txt b/boards/arm/efr32xg24_dk2601b/CMakeLists.txt deleted file mode 100644 index 7997d692379..00000000000 --- a/boards/arm/efr32xg24_dk2601b/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) 2021 Sateesh Kotapati -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library() -zephyr_library_sources(board.c) diff --git a/boards/arm/efr32xg24_dk2601b/efr32xg24_dk2601b.yaml b/boards/arm/efr32xg24_dk2601b/efr32xg24_dk2601b.yaml index 48743de3b97..2b803cca1ab 100644 --- a/boards/arm/efr32xg24_dk2601b/efr32xg24_dk2601b.yaml +++ b/boards/arm/efr32xg24_dk2601b/efr32xg24_dk2601b.yaml @@ -16,3 +16,4 @@ testing: - bluetooth - pm - hwinfo +vendor: silabs diff --git a/boards/arm/efr32xg24_dk2601b/sl_device_init_hfxo_config.h b/boards/arm/efr32xg24_dk2601b/sl_device_init_hfxo_config.h deleted file mode 100644 index 7f9e211748e..00000000000 --- a/boards/arm/efr32xg24_dk2601b/sl_device_init_hfxo_config.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2023 Antmicro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef SL_DEVICE_INIT_HFXO_CONFIG_H -#define SL_DEVICE_INIT_HFXO_CONFIG_H - -#define SL_DEVICE_INIT_HFXO_MODE cmuHfxoOscMode_Crystal -#define SL_DEVICE_INIT_HFXO_FREQ 39000000 -#define SL_DEVICE_INIT_HFXO_CTUNE 140 - -#endif /* SL_DEVICE_INIT_HFXO_CONFIG_H */ diff --git a/boards/arm/ev11l78a/doc/index.rst b/boards/arm/ev11l78a/doc/index.rst index 894cda97197..cfa4f075eee 100644 --- a/boards/arm/ev11l78a/doc/index.rst +++ b/boards/arm/ev11l78a/doc/index.rst @@ -33,27 +33,40 @@ Supported Features The ev11l78a board configuration supports the following hardware features: -+-----------+------------+------------------------------------------+ -| Interface | Controller | Driver/Component | -+===========+============+==========================================+ -| NVIC | on-chip | nested vector interrupt controller | -+-----------+------------+------------------------------------------+ -| Flash | on-chip | Can be used with LittleFS to store files | -+-----------+------------+------------------------------------------+ -| SYSTICK | on-chip | systick | -+-----------+------------+------------------------------------------+ -| WDT | on-chip | Watchdog | -+-----------+------------+------------------------------------------+ -| GPIO | on-chip | I/O ports | -+-----------+------------+------------------------------------------+ -| USART | on-chip | Serial ports | -+-----------+------------+------------------------------------------+ -| SPI | on-chip | Serial Peripheral Interface ports | -+-----------+------------+------------------------------------------+ -| I2C | on-chip | I²C ports | -+-----------+------------+------------------------------------------+ -| ADC | on-chip | Analog-to-Digital Converter | -+-----------+------------+------------------------------------------+ + +.. list-table:: + :header-rows: 1 + + * - Interface + - Controller + - Driver / Component + * - NVIC + - on-chip + - nested vector interrupt controller + * - Flash + - on-chip + - Can be used with LittleFS to store files + * - SYSTICK + - on-chip + - systick + * - WDT + - on-chip + - Watchdog + * - ADC + - on-chip + - Analog to Digital Converter + * - GPIO + - on-chip + - I/O ports + * - USART + - on-chip + - Serial ports + * - I2C + - on-chip + - I2C ports + * - SPI + - on-chip + - Serial Peripheral Interface ports Other hardware features are not currently supported by Zephyr. diff --git a/boards/arm/ev11l78a/ev11l78a.dts b/boards/arm/ev11l78a/ev11l78a.dts index 0096fe9651d..02fa9f35915 100644 --- a/boards/arm/ev11l78a/ev11l78a.dts +++ b/boards/arm/ev11l78a/ev11l78a.dts @@ -6,7 +6,9 @@ /dts-v1/; #include +#include #include +#include #include "ev11l78a-pinctrl.dtsi" / { @@ -94,9 +96,9 @@ * Storage partition will be used by FCB/LittleFS/NVS * if enabled. */ - storage_partition: partition@3c000 { + storage_partition: partition@c000 { label = "storage"; - reg = <0x0003c000 0x00004000>; + reg = ; }; }; }; diff --git a/boards/arm/ev11l78a/ev11l78a.yaml b/boards/arm/ev11l78a/ev11l78a.yaml index c181bd12f0d..f9b2a1a53a2 100644 --- a/boards/arm/ev11l78a/ev11l78a.yaml +++ b/boards/arm/ev11l78a/ev11l78a.yaml @@ -14,3 +14,4 @@ supported: - i2c - spi - uart +vendor: atmel diff --git a/boards/arm/faze/doc/index.rst b/boards/arm/faze/doc/index.rst index ed432753fd7..1d61d997cd0 100644 --- a/boards/arm/faze/doc/index.rst +++ b/boards/arm/faze/doc/index.rst @@ -31,7 +31,7 @@ Hardware - External devices connected to the NXP LPC11U67 MCU: - ASMedia ASM2364 USB-to-PCIe bridge (I2C master on port O). - - 6 RGB LEDs connected connected to a TI LP5030 LED controller (I2C device on + - 6 RGB LEDs connected to a TI LP5030 LED controller (I2C device on port 1). - 1 white LED (SSD activity blinking). diff --git a/boards/arm/faze/faze.yaml b/boards/arm/faze/faze.yaml index 0801354ec53..92deff91f49 100644 --- a/boards/arm/faze/faze.yaml +++ b/boards/arm/faze/faze.yaml @@ -18,3 +18,4 @@ supported: - gpio - i2c - serial +vendor: seagate diff --git a/boards/arm/frdm_k22f/frdm_k22f.yaml b/boards/arm/frdm_k22f/frdm_k22f.yaml index 9d8f553af53..caad4fe8519 100644 --- a/boards/arm/frdm_k22f/frdm_k22f.yaml +++ b/boards/arm/frdm_k22f/frdm_k22f.yaml @@ -19,3 +19,4 @@ supported: - spi - usb_device - watchdog +vendor: nxp diff --git a/boards/arm/frdm_k64f/frdm_k64f.dts b/boards/arm/frdm_k64f/frdm_k64f.dts index ec6a0fdf84e..5b0e26fb039 100644 --- a/boards/arm/frdm_k64f/frdm_k64f.dts +++ b/boards/arm/frdm_k64f/frdm_k64f.dts @@ -28,6 +28,7 @@ zephyr,shell-uart = &uart0; zephyr,uart-pipe = &uart0; zephyr,canbus = &flexcan0; + zephyr,uart-mcumgr = &uart0; }; leds { diff --git a/boards/arm/frdm_k64f/frdm_k64f.yaml b/boards/arm/frdm_k64f/frdm_k64f.yaml index 5b03ef23623..a9e99911776 100644 --- a/boards/arm/frdm_k64f/frdm_k64f.yaml +++ b/boards/arm/frdm_k64f/frdm_k64f.yaml @@ -26,3 +26,4 @@ supported: - spi - usb_device - watchdog +vendor: nxp diff --git a/boards/arm/frdm_k82f/frdm_k82f.yaml b/boards/arm/frdm_k82f/frdm_k82f.yaml index 755ad72d5db..49480e2404b 100644 --- a/boards/arm/frdm_k82f/frdm_k82f.yaml +++ b/boards/arm/frdm_k82f/frdm_k82f.yaml @@ -22,3 +22,4 @@ supported: - spi - usb_device - watchdog +vendor: nxp diff --git a/boards/arm/frdm_kl25z/frdm_kl25z.yaml b/boards/arm/frdm_kl25z/frdm_kl25z.yaml index 1fc6c948d0c..d930aed2127 100644 --- a/boards/arm/frdm_kl25z/frdm_kl25z.yaml +++ b/boards/arm/frdm_kl25z/frdm_kl25z.yaml @@ -18,3 +18,4 @@ supported: - gpio - i2c - usb_device +vendor: nxp diff --git a/boards/arm/frdm_kw41z/frdm_kw41z.yaml b/boards/arm/frdm_kw41z/frdm_kw41z.yaml index 42c84fd6d9b..72c7cb4abf3 100644 --- a/boards/arm/frdm_kw41z/frdm_kw41z.yaml +++ b/boards/arm/frdm_kw41z/frdm_kw41z.yaml @@ -19,3 +19,4 @@ supported: testing: ignore_tags: - bluetooth +vendor: nxp diff --git a/boards/arm/fvp_baser_aemv8r_aarch32/doc/index.rst b/boards/arm/fvp_baser_aemv8r_aarch32/doc/index.rst index c65940d8191..d1911002020 100644 --- a/boards/arm/fvp_baser_aemv8r_aarch32/doc/index.rst +++ b/boards/arm/fvp_baser_aemv8r_aarch32/doc/index.rst @@ -77,7 +77,7 @@ Programming =========== Use this configuration to build basic Zephyr applications and kernel tests in the -Arm FVP emulated environment, for example, with the :ref:`synchronization_sample`: +Arm FVP emulated environment, for example, with the :zephyr:code-sample:`synchronization` sample: .. zephyr-app-commands:: :zephyr-app: samples/synchronization diff --git a/boards/arm/fvp_baser_aemv8r_aarch32/fvp_baser_aemv8r_aarch32_smp.dts b/boards/arm/fvp_baser_aemv8r_aarch32/fvp_baser_aemv8r_aarch32_smp.dts new file mode 100644 index 00000000000..cdc0a933ba3 --- /dev/null +++ b/boards/arm/fvp_baser_aemv8r_aarch32/fvp_baser_aemv8r_aarch32_smp.dts @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2023 Arm Limited (or its affiliates). All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include "fvp_baser_aemv8r_aarch32.dts" diff --git a/boards/arm/fvp_baser_aemv8r_aarch32/fvp_baser_aemv8r_aarch32_smp.yaml b/boards/arm/fvp_baser_aemv8r_aarch32/fvp_baser_aemv8r_aarch32_smp.yaml new file mode 100644 index 00000000000..08d01e51ec4 --- /dev/null +++ b/boards/arm/fvp_baser_aemv8r_aarch32/fvp_baser_aemv8r_aarch32_smp.yaml @@ -0,0 +1,14 @@ +# Copyright (c) 2023 Arm Limited (or its affiliates). All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +identifier: fvp_baser_aemv8r_aarch32_smp +name: FVP Emulation FVP_BaseR_AEMv8R AArch32 +arch: arm +type: sim +toolchain: + - zephyr + - cross-compile +ram: 2048 +flash: 64 +testing: + timeout_multiplier: 25 diff --git a/boards/arm/fvp_baser_aemv8r_aarch32/fvp_baser_aemv8r_aarch32_smp_defconfig b/boards/arm/fvp_baser_aemv8r_aarch32/fvp_baser_aemv8r_aarch32_smp_defconfig new file mode 100644 index 00000000000..3f7f981b46e --- /dev/null +++ b/boards/arm/fvp_baser_aemv8r_aarch32/fvp_baser_aemv8r_aarch32_smp_defconfig @@ -0,0 +1,32 @@ +# Copyright (c) 2023 Arm Limited (or its affiliates). All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_FVP_AEMV8R_AARCH32=y +CONFIG_SOC_FVP_AEMV8R_AARCH32=y +CONFIG_BOARD_FVP_BASER_AEMV8R_AARCH32=y +CONFIG_ARM_MPU=y + +CONFIG_ISR_STACK_SIZE=1024 +CONFIG_THREAD_STACK_INFO=y + +# Enable Timer and Sys clock +CONFIG_SYS_CLOCK_TICKS_PER_SEC=100 +CONFIG_ARM_ARCH_TIMER=y + +# Enable UART driver +CONFIG_SERIAL=y + +# Enable serial port +CONFIG_UART_INTERRUPT_DRIVEN=y + +# Enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +CONFIG_CACHE_MANAGEMENT=y + +CONFIG_USE_SWITCH=y +CONFIG_SMP=y +CONFIG_MP_MAX_NUM_CPUS=4 + +CONFIG_DCACHE=n diff --git a/boards/arm/gd32a503v_eval/doc/index.rst b/boards/arm/gd32a503v_eval/doc/index.rst index 1039faf515f..b926a265bb4 100644 --- a/boards/arm/gd32a503v_eval/doc/index.rst +++ b/boards/arm/gd32a503v_eval/doc/index.rst @@ -34,7 +34,7 @@ Hardware - CMSIS-DAP swd debug interface over USB HID. -- 2 CAN port(support CAN-FD) +- 2 CAN FD ports For more information about the GD32A503 SoC and GD32A503V-EVAL board: diff --git a/boards/arm/gd32a503v_eval/gd32a503v_eval.yaml b/boards/arm/gd32a503v_eval/gd32a503v_eval.yaml index ea5a264f5b4..396e68d24b6 100644 --- a/boards/arm/gd32a503v_eval/gd32a503v_eval.yaml +++ b/boards/arm/gd32a503v_eval/gd32a503v_eval.yaml @@ -21,3 +21,4 @@ supported: - spi - uart - watchdog +vendor: gd diff --git a/boards/arm/gd32e103v_eval/doc/index.rst b/boards/arm/gd32e103v_eval/doc/index.rst index ccf1e9b1e3e..3d9058793fe 100644 --- a/boards/arm/gd32e103v_eval/doc/index.rst +++ b/boards/arm/gd32e103v_eval/doc/index.rst @@ -36,7 +36,7 @@ Hardware - CMSIS-DAP swd debug interface over USB HID. -- 2 CAN port(support CAN-FD) +- 2 CAN FD ports - This function is not available in this board due to hardware issues, please check ``GD32C103`` . diff --git a/boards/arm/gd32e103v_eval/gd32e103v_eval.yaml b/boards/arm/gd32e103v_eval/gd32e103v_eval.yaml index 3e3a89759b8..a5dd9ba759b 100644 --- a/boards/arm/gd32e103v_eval/gd32e103v_eval.yaml +++ b/boards/arm/gd32e103v_eval/gd32e103v_eval.yaml @@ -16,3 +16,4 @@ supported: - counter - watchdog - dma +vendor: gd diff --git a/boards/arm/gd32e507v_start/gd32e507v_start.yaml b/boards/arm/gd32e507v_start/gd32e507v_start.yaml index 8801a73c6c6..8a1b4e4b89b 100644 --- a/boards/arm/gd32e507v_start/gd32e507v_start.yaml +++ b/boards/arm/gd32e507v_start/gd32e507v_start.yaml @@ -17,3 +17,4 @@ supported: - watchdog - counter - dma +vendor: gd diff --git a/boards/arm/gd32e507z_eval/gd32e507z_eval.yaml b/boards/arm/gd32e507z_eval/gd32e507z_eval.yaml index 74beaeaf6f1..594df3a5f8d 100644 --- a/boards/arm/gd32e507z_eval/gd32e507z_eval.yaml +++ b/boards/arm/gd32e507z_eval/gd32e507z_eval.yaml @@ -15,3 +15,4 @@ supported: - pwm - gpio - counter +vendor: gd diff --git a/boards/arm/gd32f350r_eval/gd32f350r_eval.yaml b/boards/arm/gd32f350r_eval/gd32f350r_eval.yaml index b8c508f98ae..17834719ff1 100644 --- a/boards/arm/gd32f350r_eval/gd32f350r_eval.yaml +++ b/boards/arm/gd32f350r_eval/gd32f350r_eval.yaml @@ -14,3 +14,4 @@ toolchain: supported: - watchdog - dma +vendor: gd diff --git a/boards/arm/gd32f403z_eval/gd32f403z_eval.yaml b/boards/arm/gd32f403z_eval/gd32f403z_eval.yaml index cd086bd14a4..1bec175723a 100644 --- a/boards/arm/gd32f403z_eval/gd32f403z_eval.yaml +++ b/boards/arm/gd32f403z_eval/gd32f403z_eval.yaml @@ -17,3 +17,4 @@ supported: - watchdog - dma - spi +vendor: gd diff --git a/boards/arm/gd32f407v_start/gd32f407v_start.yaml b/boards/arm/gd32f407v_start/gd32f407v_start.yaml index 6076e41b265..e79982ef6e8 100644 --- a/boards/arm/gd32f407v_start/gd32f407v_start.yaml +++ b/boards/arm/gd32f407v_start/gd32f407v_start.yaml @@ -17,3 +17,4 @@ supported: - counter - dma - spi +vendor: gd diff --git a/boards/arm/gd32f450i_eval/gd32f450i_eval.yaml b/boards/arm/gd32f450i_eval/gd32f450i_eval.yaml index a54cc4d59d8..88ac1c0f558 100644 --- a/boards/arm/gd32f450i_eval/gd32f450i_eval.yaml +++ b/boards/arm/gd32f450i_eval/gd32f450i_eval.yaml @@ -18,3 +18,4 @@ supported: - counter - dma - spi +vendor: gd diff --git a/boards/arm/gd32f450v_start/gd32f450v_start.yaml b/boards/arm/gd32f450v_start/gd32f450v_start.yaml index d3261355724..62cf201bcd2 100644 --- a/boards/arm/gd32f450v_start/gd32f450v_start.yaml +++ b/boards/arm/gd32f450v_start/gd32f450v_start.yaml @@ -17,3 +17,4 @@ supported: - counter - dma - spi +vendor: gd diff --git a/boards/arm/gd32f450z_eval/gd32f450z_eval.yaml b/boards/arm/gd32f450z_eval/gd32f450z_eval.yaml index f8091bd1b33..3cc5f359495 100644 --- a/boards/arm/gd32f450z_eval/gd32f450z_eval.yaml +++ b/boards/arm/gd32f450z_eval/gd32f450z_eval.yaml @@ -21,3 +21,4 @@ supported: - uart - watchdog - dma +vendor: gd diff --git a/boards/arm/gd32f470i_eval/gd32f470i_eval.yaml b/boards/arm/gd32f470i_eval/gd32f470i_eval.yaml index e0d4b21017a..868e4907f3f 100644 --- a/boards/arm/gd32f470i_eval/gd32f470i_eval.yaml +++ b/boards/arm/gd32f470i_eval/gd32f470i_eval.yaml @@ -22,3 +22,4 @@ supported: - watchdog - dma - spi +vendor: gd diff --git a/boards/arm/gd32l233r_eval/gd32l233r_eval.yaml b/boards/arm/gd32l233r_eval/gd32l233r_eval.yaml index a69a61f14b0..04e38f9e46c 100644 --- a/boards/arm/gd32l233r_eval/gd32l233r_eval.yaml +++ b/boards/arm/gd32l233r_eval/gd32l233r_eval.yaml @@ -11,3 +11,4 @@ toolchain: - zephyr - gnuarmemb - xtools +vendor: gd diff --git a/boards/arm/google_dragonclaw/google_dragonclaw.yaml b/boards/arm/google_dragonclaw/google_dragonclaw.yaml index 5a99a50928b..ddb4f3a7713 100644 --- a/boards/arm/google_dragonclaw/google_dragonclaw.yaml +++ b/boards/arm/google_dragonclaw/google_dragonclaw.yaml @@ -8,3 +8,4 @@ toolchain: - xtools ram: 256 flash: 1024 +vendor: google diff --git a/boards/arm/google_kukui/google_kukui.yaml b/boards/arm/google_kukui/google_kukui.yaml index f0c170231d7..ad95d286cb2 100644 --- a/boards/arm/google_kukui/google_kukui.yaml +++ b/boards/arm/google_kukui/google_kukui.yaml @@ -12,3 +12,4 @@ testing: ignore_tags: - net - bluetooth +vendor: google diff --git a/boards/arm/google_twinkie_v2/google_twinkie_v2.yaml b/boards/arm/google_twinkie_v2/google_twinkie_v2.yaml index 77f018d136d..bc9028b4e9a 100644 --- a/boards/arm/google_twinkie_v2/google_twinkie_v2.yaml +++ b/boards/arm/google_twinkie_v2/google_twinkie_v2.yaml @@ -12,3 +12,4 @@ testing: ignore_tags: - net - bluetooth +vendor: google diff --git a/boards/arm/hexiwear_k64/hexiwear_k64.yaml b/boards/arm/hexiwear_k64/hexiwear_k64.yaml index ae8c77edecf..c14e75c35da 100644 --- a/boards/arm/hexiwear_k64/hexiwear_k64.yaml +++ b/boards/arm/hexiwear_k64/hexiwear_k64.yaml @@ -13,3 +13,4 @@ supported: - i2c - pwm - watchdog +vendor: nxp diff --git a/boards/arm/hexiwear_kw40z/hexiwear_kw40z.yaml b/boards/arm/hexiwear_kw40z/hexiwear_kw40z.yaml index 33732674fd5..0e5b4935673 100644 --- a/boards/arm/hexiwear_kw40z/hexiwear_kw40z.yaml +++ b/boards/arm/hexiwear_kw40z/hexiwear_kw40z.yaml @@ -11,3 +11,4 @@ toolchain: testing: ignore_tags: - net +vendor: nxp diff --git a/boards/arm/holyiot_yj16019/doc/index.rst b/boards/arm/holyiot_yj16019/doc/index.rst index 639b04a5470..57990be93a1 100644 --- a/boards/arm/holyiot_yj16019/doc/index.rst +++ b/boards/arm/holyiot_yj16019/doc/index.rst @@ -109,7 +109,7 @@ found in :ref:`nordic_segger_flashing`. Then build and flash applications as usual (see :ref:`build_an_application` and :ref:`application_run` for more details). -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/holyiot_yj16019/holyiot_yj16019_defconfig b/boards/arm/holyiot_yj16019/holyiot_yj16019_defconfig index 8cd91b6b694..7a5c82fbdc8 100644 --- a/boards/arm/holyiot_yj16019/holyiot_yj16019_defconfig +++ b/boards/arm/holyiot_yj16019/holyiot_yj16019_defconfig @@ -13,5 +13,3 @@ CONFIG_USE_SEGGER_RTT=y # Enable GPIO CONFIG_GPIO=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/ip_k66f/CMakeLists.txt b/boards/arm/ip_k66f/CMakeLists.txt index 9881313609a..2fab2b7dc86 100644 --- a/boards/arm/ip_k66f/CMakeLists.txt +++ b/boards/arm/ip_k66f/CMakeLists.txt @@ -1 +1,3 @@ # SPDX-License-Identifier: Apache-2.0 + +set(BOARD_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "Board linker script, ${BOARD}") diff --git a/boards/arm/ip_k66f/doc/index.rst b/boards/arm/ip_k66f/doc/index.rst index d9b5cf10351..eb8ee3b3e99 100644 --- a/boards/arm/ip_k66f/doc/index.rst +++ b/boards/arm/ip_k66f/doc/index.rst @@ -118,7 +118,7 @@ The default flasher is ``jlink`` using the built-in SEGGER Jlink interface. Flashing ======== -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -130,7 +130,7 @@ Red LED0 should blink at 1 second delay. Debugging ========= -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/ip_k66f/ip_k66f.yaml b/boards/arm/ip_k66f/ip_k66f.yaml index 0126d463648..ef2de5f4467 100644 --- a/boards/arm/ip_k66f/ip_k66f.yaml +++ b/boards/arm/ip_k66f/ip_k66f.yaml @@ -15,3 +15,4 @@ supported: - netif:eth ram: 256 flash: 2048 +vendor: nxp diff --git a/boards/arm/ip_k66f/linker.ld b/boards/arm/ip_k66f/linker.ld index e1005cd32b7..21e9d0e4c1f 100644 --- a/boards/arm/ip_k66f/linker.ld +++ b/boards/arm/ip_k66f/linker.ld @@ -44,4 +44,4 @@ ITERABLE_SECTION_RAM(net_if_dev, 4) \ ITERABLE_SECTION_RAM(net_l2, 4) \ ITERABLE_SECTION_RAM(eth_bridge, 4) -#include +#include diff --git a/boards/arm/kv260_r5/kv260_r5.yaml b/boards/arm/kv260_r5/kv260_r5.yaml index 32cb6211866..9cc92025e91 100644 --- a/boards/arm/kv260_r5/kv260_r5.yaml +++ b/boards/arm/kv260_r5/kv260_r5.yaml @@ -9,3 +9,4 @@ testing: ignore_tags: - net - bluetooth +vendor: xlnx diff --git a/boards/arm/legend/doc/index.rst b/boards/arm/legend/doc/index.rst index c744281d651..1156a792317 100644 --- a/boards/arm/legend/doc/index.rst +++ b/boards/arm/legend/doc/index.rst @@ -136,4 +136,4 @@ References - `STM32F070 reference manual`_ .. _STM32F070 reference manual: - http://www.st.com/resource/en/reference_manual/dm00031936.pdf + https://www.st.com/resource/en/reference_manual/dm00031936.pdf diff --git a/boards/arm/legend/legend.yaml b/boards/arm/legend/legend.yaml index b8c8d7d7628..1762e786318 100644 --- a/boards/arm/legend/legend.yaml +++ b/boards/arm/legend/legend.yaml @@ -17,3 +17,4 @@ testing: ignore_tags: - net - bluetooth +vendor: seagate diff --git a/boards/arm/lora_e5_dev_board/doc/lora_e5_dev_board.rst b/boards/arm/lora_e5_dev_board/doc/lora_e5_dev_board.rst index a24920002d9..c3c91fc8f74 100644 --- a/boards/arm/lora_e5_dev_board/doc/lora_e5_dev_board.rst +++ b/boards/arm/lora_e5_dev_board/doc/lora_e5_dev_board.rst @@ -263,7 +263,7 @@ Debugging ========= You can debug an application in the usual way. Here is an example for the -:ref:`blinky-sample` application. +:zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/lora_e5_dev_board/lora_e5_dev_board.yaml b/boards/arm/lora_e5_dev_board/lora_e5_dev_board.yaml index 26d3365a6cc..446bc1934cb 100644 --- a/boards/arm/lora_e5_dev_board/lora_e5_dev_board.yaml +++ b/boards/arm/lora_e5_dev_board/lora_e5_dev_board.yaml @@ -17,3 +17,4 @@ supported: - uart - watchdog - lora +vendor: seeed diff --git a/boards/arm/lpcxpresso11u68/doc/index.rst b/boards/arm/lpcxpresso11u68/doc/index.rst index 75a4b7f15a5..23198a359ea 100644 --- a/boards/arm/lpcxpresso11u68/doc/index.rst +++ b/boards/arm/lpcxpresso11u68/doc/index.rst @@ -107,7 +107,7 @@ Flashing The LPCXpresso11U68 board can be flashed by using the on-board LPC-Link2 debug probe (based on a NXP LPC43xx MCU). This MCU provides either a CMSIS-DAP or a J-Link interface. It depends on the embedded firmware image. The default -OpenOCD configuration supports the the CMSIS-DAP interface. If you want to +OpenOCD configuration supports the CMSIS-DAP interface. If you want to switch to J-Link, then you need to edit the ``boards/arm/lpcxpresso11u68/support/openocd.cfg`` file and to replace:: diff --git a/boards/arm/lpcxpresso11u68/lpcxpresso11u68.dts b/boards/arm/lpcxpresso11u68/lpcxpresso11u68.dts index 680b662e0c4..22e2e9f97f5 100644 --- a/boards/arm/lpcxpresso11u68/lpcxpresso11u68.dts +++ b/boards/arm/lpcxpresso11u68/lpcxpresso11u68.dts @@ -13,7 +13,7 @@ / { model = "NXP LPCXPRESSO11U68 board"; - compatible = "lpcxpresso11u68", "nxp,lpc"; + compatible = "nxp,lpcxpresso11u68", "nxp,lpc"; chosen { zephyr,sram = &sram0; zephyr,flash = &flash0; diff --git a/boards/arm/lpcxpresso11u68/lpcxpresso11u68.yaml b/boards/arm/lpcxpresso11u68/lpcxpresso11u68.yaml index 35c3257948d..e59360c084b 100644 --- a/boards/arm/lpcxpresso11u68/lpcxpresso11u68.yaml +++ b/boards/arm/lpcxpresso11u68/lpcxpresso11u68.yaml @@ -11,3 +11,4 @@ supported: - i2c - serial - eeprom +vendor: nxp diff --git a/boards/arm/lpcxpresso51u68/lpcxpresso51u68.yaml b/boards/arm/lpcxpresso51u68/lpcxpresso51u68.yaml index f2ccc4c612b..1c7a0644a10 100644 --- a/boards/arm/lpcxpresso51u68/lpcxpresso51u68.yaml +++ b/boards/arm/lpcxpresso51u68/lpcxpresso51u68.yaml @@ -19,3 +19,4 @@ supported: - gpio - i2c - spi +vendor: nxp diff --git a/boards/arm/lpcxpresso54114/lpcxpresso54114_m0.yaml b/boards/arm/lpcxpresso54114/lpcxpresso54114_m0.yaml index 78aaf27c87f..4fea41d5526 100644 --- a/boards/arm/lpcxpresso54114/lpcxpresso54114_m0.yaml +++ b/boards/arm/lpcxpresso54114/lpcxpresso54114_m0.yaml @@ -17,3 +17,4 @@ toolchain: - xtools - zephyr - gnuarmemb +vendor: nxp diff --git a/boards/arm/lpcxpresso54114/lpcxpresso54114_m4.yaml b/boards/arm/lpcxpresso54114/lpcxpresso54114_m4.yaml index 5451d22000d..d8410a51893 100644 --- a/boards/arm/lpcxpresso54114/lpcxpresso54114_m4.yaml +++ b/boards/arm/lpcxpresso54114/lpcxpresso54114_m4.yaml @@ -20,3 +20,4 @@ supported: - gpio - i2c - spi +vendor: nxp diff --git a/boards/arm/lpcxpresso55s06/board.cmake b/boards/arm/lpcxpresso55s06/board.cmake index 32f7be75b33..305ed963f21 100644 --- a/boards/arm/lpcxpresso55s06/board.cmake +++ b/boards/arm/lpcxpresso55s06/board.cmake @@ -1,9 +1,12 @@ # # Copyright (c) 2022 metraTec +# Copyright 2023 NXP # # SPDX-License-Identifier: Apache-2.0 # +board_runner_args(linkserver "--device=LPC55S06:LPCXpresso55S06") board_runner_args(jlink "--device=LPC55S06" "--reset-after-load") +include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/arm/lpcxpresso55s06/lpcxpresso55s06.yaml b/boards/arm/lpcxpresso55s06/lpcxpresso55s06.yaml index 43497c89c5b..fcf89bfe0ad 100644 --- a/boards/arm/lpcxpresso55s06/lpcxpresso55s06.yaml +++ b/boards/arm/lpcxpresso55s06/lpcxpresso55s06.yaml @@ -16,3 +16,4 @@ toolchain: supported: - gpio - can +vendor: nxp diff --git a/boards/arm/lpcxpresso55s06/lpcxpresso55s06_common.dtsi b/boards/arm/lpcxpresso55s06/lpcxpresso55s06_common.dtsi index 03633b468dc..aa2373b829c 100644 --- a/boards/arm/lpcxpresso55s06/lpcxpresso55s06_common.dtsi +++ b/boards/arm/lpcxpresso55s06/lpcxpresso55s06_common.dtsi @@ -1,6 +1,6 @@ /* * Copyright (c) 2022 metraTec - * Copyright 2022 NXP + * Copyright 2022-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,12 +12,11 @@ chosen { zephyr,sram = &sram0; zephyr,flash = &flash0; - zephyr,code-partition = &sramx; + zephyr,code-partition = &slot0_partition; zephyr,console = &flexcomm0; zephyr,shell-uart = &flexcomm0; zephyr,entropy = &rng; zephyr,flash-controller = &iap; - zephyr,code-partition = &slot0_partition; zephyr,canbus = &can0; }; @@ -118,23 +117,27 @@ }; &flash0 { - /* - * LPC flash controller requires minimum 512 byte - * write to flash, so MCUBoot is not supported. Just - * provide storage and code partition. - */ partitions { compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - slot0_partition: partition@0 { + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x0 DT_SIZE_K(32)>; + }; + slot0_partition: partition@8000 { label = "image-0"; - reg = <0x00000000 DT_SIZE_K(196)>; + reg = <0x00008000 DT_SIZE_K(96)>; + }; + slot1_partition: partition@20000 { + label = "image-1"; + reg = <0x00020000 DT_SIZE_K(96)>; }; - storage_partition: partition@30000 { + storage_partition: partition@38000 { label = "storage"; - reg = <0x00030000 DT_SIZE_K(64)>; + reg = <0x00038000 DT_SIZE_K(20)>; }; + /* The last 12KB are reserved for PFR on the 256KB flash. */ }; }; diff --git a/boards/arm/lpcxpresso55s06/lpcxpresso55s06_defconfig b/boards/arm/lpcxpresso55s06/lpcxpresso55s06_defconfig index b239a73b8c0..a743b67e2fd 100644 --- a/boards/arm/lpcxpresso55s06/lpcxpresso55s06_defconfig +++ b/boards/arm/lpcxpresso55s06/lpcxpresso55s06_defconfig @@ -13,7 +13,6 @@ CONFIG_SERIAL=y CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_GPIO=y CONFIG_PINCTRL=y -CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=96000000 CONFIG_ARM_MPU=y CONFIG_RUNTIME_NMI=y diff --git a/boards/arm/lpcxpresso55s16/board.cmake b/boards/arm/lpcxpresso55s16/board.cmake index 7daaf7d25c1..45ca5dcfe1c 100644 --- a/boards/arm/lpcxpresso55s16/board.cmake +++ b/boards/arm/lpcxpresso55s16/board.cmake @@ -1,9 +1,14 @@ # # Copyright (c) 2020 Henrik Brix Andersen +# Copyright 2023 NXP # # SPDX-License-Identifier: Apache-2.0 # +board_runner_args(linkserver "--device=LPC55S16:LPCXpresso55S16") board_runner_args(jlink "--device=LPC55S16" "--reset-after-load") +board_runner_args(pyocd "--target=lpc55s16") +include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) +include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) diff --git a/boards/arm/lpcxpresso55s16/doc/index.rst b/boards/arm/lpcxpresso55s16/doc/index.rst index fa6971c988a..9c25ac8898e 100644 --- a/boards/arm/lpcxpresso55s16/doc/index.rst +++ b/boards/arm/lpcxpresso55s16/doc/index.rst @@ -138,9 +138,11 @@ the functionality of a pin. System Clock ============ -The LPC55S16 SoC is configured to use the internal FRO at 96MHz as a -source for the system clock. Other sources for the system clock are -provided in the SOC, depending on your system requirements. +The LPC55S16 SoC is configured to use PLL1 clocked from the external 24MHz +crystal, running at 144MHz as a source for the system clock. When the flash +controller is enabled, the core clock will be reduced to 96MHz. The application +may reconfigure clocks after initialization, provided that the core clock is +always set to 96MHz when flash programming operations are performed. Serial Port =========== diff --git a/boards/arm/lpcxpresso55s16/lpcxpresso55s16.yaml b/boards/arm/lpcxpresso55s16/lpcxpresso55s16.yaml index 8f3d0e47acc..e08460382fd 100644 --- a/boards/arm/lpcxpresso55s16/lpcxpresso55s16.yaml +++ b/boards/arm/lpcxpresso55s16/lpcxpresso55s16.yaml @@ -23,3 +23,4 @@ supported: - i2c - spi - usb_device +vendor: nxp diff --git a/boards/arm/lpcxpresso55s16/lpcxpresso55s16_common.dtsi b/boards/arm/lpcxpresso55s16/lpcxpresso55s16_common.dtsi index b1e152e74c9..1b68d976f3e 100644 --- a/boards/arm/lpcxpresso55s16/lpcxpresso55s16_common.dtsi +++ b/boards/arm/lpcxpresso55s16/lpcxpresso55s16_common.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2020 Henrik Brix Andersen + * Copyright 2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,11 +12,12 @@ chosen { zephyr,sram = &sram0; zephyr,flash = &flash0; - zephyr,code-partition = &sramx; + zephyr,code-partition = &slot0_partition; zephyr,console = &flexcomm0; zephyr,shell-uart = &flexcomm0; zephyr,entropy = &rng; zephyr,canbus = &can0; + zephyr,flash-controller = &iap; }; aliases{ @@ -162,23 +164,27 @@ }; &flash0 { - /* - * LPC flash controller requires minimum 512 byte - * write to flash, so MCUBoot is not supported. Just - * provide storage and code partition. - */ partitions { compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - slot0_partition: partition@0 { + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x0 DT_SIZE_K(32)>; + }; + slot0_partition: partition@8000 { label = "image-0"; - reg = <0x00000000 DT_SIZE_K(196)>; + reg = <0x00008000 DT_SIZE_K(96)>; + }; + slot1_partition: partition@20000 { + label = "image-1"; + reg = <0x00020000 DT_SIZE_K(96)>; }; - storage_partition: partition@30000 { + storage_partition: partition@38000 { label = "storage"; - reg = <0x00030000 DT_SIZE_K(64)>; + reg = <0x00038000 DT_SIZE_K(20)>; }; + /* The last 12KB are reserved for PFR on the 256KB flash. */ }; }; diff --git a/boards/arm/lpcxpresso55s16/lpcxpresso55s16_defconfig b/boards/arm/lpcxpresso55s16/lpcxpresso55s16_defconfig index 1c7617436ce..44af7c468e1 100644 --- a/boards/arm/lpcxpresso55s16/lpcxpresso55s16_defconfig +++ b/boards/arm/lpcxpresso55s16/lpcxpresso55s16_defconfig @@ -13,7 +13,6 @@ CONFIG_SERIAL=y CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_GPIO=y CONFIG_PINCTRL=y -CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=96000000 CONFIG_ARM_MPU=y CONFIG_RUNTIME_NMI=y diff --git a/boards/arm/lpcxpresso55s28/doc/index.rst b/boards/arm/lpcxpresso55s28/doc/index.rst index b55bddb6291..7750254d423 100644 --- a/boards/arm/lpcxpresso55s28/doc/index.rst +++ b/boards/arm/lpcxpresso55s28/doc/index.rst @@ -125,9 +125,11 @@ the functionality of a pin. System Clock ============ -The LPC55S28 SoC is configured to use the internal FRO at 96MHz as a -source for the system clock. Other sources for the system clock are -provided in the SOC, depending on your system requirements. +The LPC55S28 SoC is configured to use PLL1 clocked from the external 24MHz +crystal, running at 144MHz as a source for the system clock. When the flash +controller is enabled, the core clock will be reduced to 96MHz. The application +may reconfigure clocks after initialization, provided that the core clock is +always set to 96MHz when flash programming operations are performed. Serial Port =========== diff --git a/boards/arm/lpcxpresso55s28/lpcxpresso55s28.yaml b/boards/arm/lpcxpresso55s28/lpcxpresso55s28.yaml index 2ffd6657175..77bdb93e90f 100644 --- a/boards/arm/lpcxpresso55s28/lpcxpresso55s28.yaml +++ b/boards/arm/lpcxpresso55s28/lpcxpresso55s28.yaml @@ -23,3 +23,4 @@ supported: - spi - usb_device - watchdog +vendor: nxp diff --git a/boards/arm/lpcxpresso55s28/lpcxpresso55s28_defconfig b/boards/arm/lpcxpresso55s28/lpcxpresso55s28_defconfig index d99a3d01c55..8ce8f718d7e 100644 --- a/boards/arm/lpcxpresso55s28/lpcxpresso55s28_defconfig +++ b/boards/arm/lpcxpresso55s28/lpcxpresso55s28_defconfig @@ -13,7 +13,6 @@ CONFIG_SERIAL=y CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_GPIO=y CONFIG_PINCTRL=y -CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=96000000 CONFIG_ARM_MPU=y CONFIG_HW_STACK_PROTECTION=y diff --git a/boards/arm/lpcxpresso55s36/board.cmake b/boards/arm/lpcxpresso55s36/board.cmake index 2aceb6ca675..b1e16906bd5 100644 --- a/boards/arm/lpcxpresso55s36/board.cmake +++ b/boards/arm/lpcxpresso55s36/board.cmake @@ -1,11 +1,13 @@ # -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # # SPDX-License-Identifier: Apache-2.0 # +board_runner_args(linkserver "--device=LPC55S36:LPCXpresso55S36") board_runner_args(jlink "--device=LPC55S36" "--reset-after-load") board_runner_args(pyocd "--target=lpc55s36") +include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) diff --git a/boards/arm/lpcxpresso55s36/doc/index.rst b/boards/arm/lpcxpresso55s36/doc/index.rst index d25bf7776c3..a8914f20154 100644 --- a/boards/arm/lpcxpresso55s36/doc/index.rst +++ b/boards/arm/lpcxpresso55s36/doc/index.rst @@ -81,6 +81,8 @@ already supported, which can also be re-used on this lpcxpresso55s36 board: +-----------+------------+-------------------------------------+ | USB FS | on-chip | USB Full Speed device | +-----------+------------+-------------------------------------+ +| DAC | on-chip | dac | ++-----------+------------+-------------------------------------+ Other hardware features are not currently enabled. @@ -145,8 +147,9 @@ the functionality of a pin. System Clock ============ -The LPC55S36 SoC is configured to use the internal FRO at 96MHz as a -source for the system clock. Other sources for the system clock are +The LPC55S36 SoC is configured to use PLL1 clocked from the external 24MHz +crystal, running at 144MHz as a source for the system clock. When the flash +controller is enabled, the core clock will be reduced to 96MHz. Other sources for the system clock are provided in the SOC, depending on your system requirements. Serial Port diff --git a/boards/arm/lpcxpresso55s36/lpcxpresso55s36-pinctrl.dtsi b/boards/arm/lpcxpresso55s36/lpcxpresso55s36-pinctrl.dtsi index 2d68da1d13f..8ca6f659f2e 100644 --- a/boards/arm/lpcxpresso55s36/lpcxpresso55s36-pinctrl.dtsi +++ b/boards/arm/lpcxpresso55s36/lpcxpresso55s36-pinctrl.dtsi @@ -2,7 +2,7 @@ * NOTE: File generated by lpc_cfg_utils.py * from LPC55S36.mex * - * Copyright 2022 NXP + * Copyright 2022-2023 NXP * SPDX-License-Identifier: Apache-2.0 */ @@ -119,4 +119,12 @@ slew-rate = "standard"; }; }; + + pinmux_dac0: pinmux_dac0 { + group0 { + pinmux = ; + slew-rate = "standard"; + nxp,analog-mode; + }; + }; }; diff --git a/boards/arm/lpcxpresso55s36/lpcxpresso55s36.dts b/boards/arm/lpcxpresso55s36/lpcxpresso55s36.dts index 98713617fdb..be2b16c27f7 100644 --- a/boards/arm/lpcxpresso55s36/lpcxpresso55s36.dts +++ b/boards/arm/lpcxpresso55s36/lpcxpresso55s36.dts @@ -17,7 +17,7 @@ chosen { zephyr,sram = &sram0; zephyr,flash = &flash0; - zephyr,code-partition = &sramx; + zephyr,code-partition = &slot0_partition; zephyr,console = &flexcomm0; zephyr,shell-uart = &flexcomm0; zephyr,canbus = &can0; @@ -143,20 +143,33 @@ pinctrl-names = "default"; }; +/* Flash is divided into 32 kB sub-regions. + * Each sub-region can be assigned individual + * security tier in secure AHB controller. + */ &flash0 { partitions { compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - slot0_partition: partition@0 { - label = "executable"; - reg = <0x00000000 DT_SIZE_K(182)>; - }; - - storage_partition: partition@88000 { + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x0 DT_SIZE_K(32)>; + }; + slot0_partition: partition@8000 { + label = "image-0"; + reg = <0x00008000 DT_SIZE_K(96)>; + }; + slot1_partition: partition@20000 { + label = "image-1"; + reg = <0x00020000 DT_SIZE_K(96)>; + }; + storage_partition: partition@38000 { label = "storage"; - reg = <0x0002d800 DT_SIZE_K(64)>; + reg = <0x00038000 DT_SIZE_K(20)>; }; + /* The last 12KB are reserved for PFR on the 256KB flash. + */ }; }; @@ -175,3 +188,13 @@ zephyr_udc0: &usbfs { &dma0 { status = "okay"; }; + +&vref0 { + status = "okay"; +}; + +&dac0 { + status = "okay"; + pinctrl-0 = <&pinmux_dac0>; + pinctrl-names = "default"; +}; diff --git a/boards/arm/lpcxpresso55s36/lpcxpresso55s36.yaml b/boards/arm/lpcxpresso55s36/lpcxpresso55s36.yaml index 823e4d3aeab..5a28b2149c5 100644 --- a/boards/arm/lpcxpresso55s36/lpcxpresso55s36.yaml +++ b/boards/arm/lpcxpresso55s36/lpcxpresso55s36.yaml @@ -18,3 +18,5 @@ supported: - can - gpio - pwm + - dac +vendor: nxp diff --git a/boards/arm/lpcxpresso55s36/lpcxpresso55s36_defconfig b/boards/arm/lpcxpresso55s36/lpcxpresso55s36_defconfig index 40c1b5fec75..4bf154138af 100644 --- a/boards/arm/lpcxpresso55s36/lpcxpresso55s36_defconfig +++ b/boards/arm/lpcxpresso55s36/lpcxpresso55s36_defconfig @@ -13,7 +13,6 @@ CONFIG_SERIAL=y CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_GPIO=y CONFIG_PINCTRL=y -CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=96000000 CONFIG_ARM_MPU=y CONFIG_RUNTIME_NMI=y diff --git a/boards/arm/lpcxpresso55s69/doc/index.rst b/boards/arm/lpcxpresso55s69/doc/index.rst index 1bd0ccfbae5..408cd18aa91 100644 --- a/boards/arm/lpcxpresso55s69/doc/index.rst +++ b/boards/arm/lpcxpresso55s69/doc/index.rst @@ -191,21 +191,21 @@ Memory mappings There are multiple memory configurations, they all start from the MCUboot partitioning which looks like the table below -+---------+------------------+---------------------------------+ -| Name | Address[Size] | Comment | -+=========+==================+=================================+ -| boot | 0x00000000[32K] | Bootloader | -+---------+------------------+---------------------------------+ -| slot0 | 0x00008000[160k] | Image that runs after boot | -+---------+------------------+---------------------------------+ -| slot1 | 0x00030000[96k] | Second image, core 1 or NS | -+---------+------------------+---------------------------------+ -| slot2 | 0x00048000[160k] | Updates slot0 image | -+---------+------------------+---------------------------------+ -| slot3 | 0x00070000[96k] | Updates slot1 image | -+---------+------------------+---------------------------------+ -| storage | 0x00088000[50k] | File system, persistent storage | -+---------+------------------+---------------------------------+ ++----------+------------------+---------------------------------+ +| Name | Address[Size] | Comment | ++==========+==================+=================================+ +| boot | 0x00000000[32K] | Bootloader | ++----------+------------------+---------------------------------+ +| slot0 | 0x00008000[160k] | Image that runs after boot | ++----------+------------------+---------------------------------+ +| slot0_ns | 0x00030000[96k] | Second image, core 1 or NS | ++----------+------------------+---------------------------------+ +| slot1 | 0x00048000[160k] | Updates slot0 image | ++----------+------------------+---------------------------------+ +| slot1_ns | 0x00070000[96k] | Updates slot0_ns image | ++----------+------------------+---------------------------------+ +| storage | 0x00088000[50k] | File system, persistent storage | ++----------+------------------+---------------------------------+ See below examples of how this partitioning is used @@ -256,9 +256,11 @@ Dual Core samples System Clock ============ -The LPC55S69 SoC is configured to use the internal FRO at 96MHz as a source for -the system clock. Other sources for the system clock are provided in the SOC, -depending on your system requirements. +The LPC55S69 SoC is configured to use PLL1 clocked from the external 24MHz +crystal, running at 144MHz as a source for the system clock. When the flash +controller is enabled, the core clock will be reduced to 96MHz. The application +may reconfigure clocks after initialization, provided that the core clock is +always set to 96MHz when flash programming operations are performed. Serial Port =========== diff --git a/boards/arm/lpcxpresso55s69/lpcxpresso55s69.dtsi b/boards/arm/lpcxpresso55s69/lpcxpresso55s69.dtsi index 11b3263c3aa..e3d5b08fa19 100644 --- a/boards/arm/lpcxpresso55s69/lpcxpresso55s69.dtsi +++ b/boards/arm/lpcxpresso55s69/lpcxpresso55s69.dtsi @@ -117,28 +117,27 @@ compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - /* Please enable mcuboot's swap move, no scratch */ boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 0x00008000>; + reg = <0x00000000 DT_SIZE_K(32)>; read-only; }; slot0_partition: partition@8000 { label = "image-0"; - reg = <0x00008000 0x00028000>; + reg = <0x00008000 DT_SIZE_K(160)>; }; - slot1_partition: partition@30000 { - label = "image-1"; - reg = <0x00030000 0x00018000>; + slot0_ns_partition: partition@30000 { + label = "image-0-nonsecure"; + reg = <0x00030000 DT_SIZE_K(96)>; }; - slot2_partition: partition@48000 { - label = "image-2"; - reg = <0x00048000 0x00028000>; + slot1_partition: partition@48000 { + label = "image-1"; + reg = <0x00048000 DT_SIZE_K(160)>; }; - slot3_partition: partition@70000 { - label = "image-3"; - reg = <0x00070000 0x00018000>; + slot1_ns_partition: partition@70000 { + label = "image-1-nonsecure"; + reg = <0x00070000 DT_SIZE_K(96)>; }; /* * The flash starting at 0x88000 and ending at @@ -146,7 +145,7 @@ */ storage_partition: partition@88000 { label = "storage"; - reg = <0x00088000 0x0000ca00>; + reg = <0x00088000 DT_SIZE_K(50)>; }; }; }; diff --git a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0.dts b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0.dts index 050d625013f..14ba04fa448 100644 --- a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0.dts +++ b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0.dts @@ -37,7 +37,7 @@ zephyr,sram = &sram0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; - zephyr,code-cpu1-partition = &slot1_partition; + zephyr,code-cpu1-partition = &slot0_ns_partition; zephyr,sram-cpu1-partition = &sram3; zephyr,console = &flexcomm0; zephyr,shell-uart = &flexcomm0; @@ -204,3 +204,7 @@ i2s1: &flexcomm7 { &dma1 { status = "okay"; }; + +&mrt_channel0 { + status = "okay"; +}; diff --git a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0.yaml b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0.yaml index 9feb083ea1f..d0bafc9cd4b 100644 --- a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0.yaml +++ b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0.yaml @@ -27,3 +27,4 @@ supported: - sdhc - usb_device - watchdog +vendor: nxp diff --git a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0_defconfig b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0_defconfig index f6bfb945eec..ece94dd0b6f 100644 --- a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0_defconfig +++ b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0_defconfig @@ -12,7 +12,6 @@ CONFIG_UART_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_GPIO=y -CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=96000000 CONFIG_ARM_MPU=y CONFIG_HW_STACK_PROTECTION=y CONFIG_PINCTRL=y diff --git a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu1.dts b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu1.dts index 1c3f11882a0..9ade525bc37 100644 --- a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu1.dts +++ b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu1.dts @@ -20,7 +20,7 @@ chosen { zephyr,sram = &sram3; zephyr,flash = &flash0; - zephyr,code-partition = &slot1_partition; + zephyr,code-partition = &slot0_ns_partition; zephyr,entropy = &rng; }; }; diff --git a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu1.yaml b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu1.yaml index 928c884506d..818d29535fa 100644 --- a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu1.yaml +++ b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu1.yaml @@ -16,3 +16,4 @@ toolchain: - xtools supported: - gpio +vendor: nxp diff --git a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu1_defconfig b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu1_defconfig index 63d74806221..d93ccd89329 100644 --- a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu1_defconfig +++ b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu1_defconfig @@ -8,7 +8,6 @@ CONFIG_SOC_SERIES_LPC55XXX=y CONFIG_SOC_LPC55S69_CPU1=y CONFIG_BOARD_LPCXPRESSO55S69_CPU1=y CONFIG_GPIO=y -CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=96000000 CONFIG_PINCTRL=y CONFIG_RUNTIME_NMI=y diff --git a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_ns.dts b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_ns.dts index 0491958f9e0..cc2e41e0815 100644 --- a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_ns.dts +++ b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_ns.dts @@ -29,7 +29,7 @@ chosen { zephyr,sram = &non_secure_ram; zephyr,flash = &flash0; - zephyr,code-partition = &slot1_partition; + zephyr,code-partition = &slot0_ns_partition; zephyr,console = &flexcomm0; zephyr,shell-uart = &flexcomm0; zephyr,entropy = &rng; diff --git a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_ns.yaml b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_ns.yaml index 2a2544bcfdf..d7333e026d7 100644 --- a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_ns.yaml +++ b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_ns.yaml @@ -22,3 +22,4 @@ supported: - gpio - spi - watchdog +vendor: nxp diff --git a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_ns_defconfig b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_ns_defconfig index a82f0241fed..451a92a74a6 100644 --- a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_ns_defconfig +++ b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_ns_defconfig @@ -12,7 +12,6 @@ CONFIG_UART_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_GPIO=y -CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=96000000 CONFIG_PINCTRL=y # TFM sets up MPU_NS, can't correctly change this configuration yet diff --git a/boards/arm/mec1501modular_assy6885/mec1501modular_assy6885.dts b/boards/arm/mec1501modular_assy6885/mec1501modular_assy6885.dts index 852602386a9..d59ff04a62f 100644 --- a/boards/arm/mec1501modular_assy6885/mec1501modular_assy6885.dts +++ b/boards/arm/mec1501modular_assy6885/mec1501modular_assy6885.dts @@ -103,31 +103,21 @@ &kscan0 { status = "okay"; - pinctrl-0 = < &kso00_gpio040 - &kso01_gpio045 - &kso02_gpio046 - &kso12_gpio125 - &kso13_gpio126 - &kso03_gpio047 - &kso04_gpio107 - &kso05_gpio112 - &kso06_gpio113 - &kso14_gpio152 - &kso15_gpio151 - &kso07_gpio120 - &kso08_gpio121 - &kso09_gpio122 - &kso10_gpio123 - &kso11_gpio124 - &ksi0_gpio017 - &ksi1_gpio020 - &ksi2_gpio021 - &ksi3_gpio026 - &ksi4_gpio027 - &ksi5_gpio030 - &ksi6_gpio031 - &ksi7_gpio032 >; - pinctrl-names = "default"; + pinctrl-0 = < &kso00_gpio040 &kso01_gpio045 &kso02_gpio046 &kso12_gpio125 + &kso13_gpio126 &kso03_gpio047 &kso04_gpio107 &kso05_gpio112 + &kso06_gpio113 &kso14_gpio152 &kso15_gpio151 &kso07_gpio120 + &kso08_gpio121 &kso09_gpio122 &kso10_gpio123 &kso11_gpio124 + &ksi0_gpio017 &ksi1_gpio020 &ksi2_gpio021 &ksi3_gpio026 + &ksi4_gpio027 &ksi5_gpio030 &ksi6_gpio031 &ksi7_gpio032 >; + pinctrl-1 = < &kso00_gpio040_sleep &kso01_gpio045_sleep &kso02_gpio046_sleep + &kso12_gpio125_sleep &kso13_gpio126_sleep &kso03_gpio047_sleep + &kso04_gpio107_sleep &kso05_gpio112_sleep &kso06_gpio113_sleep + &kso14_gpio152_sleep &kso15_gpio151_sleep &kso07_gpio120_sleep + &kso08_gpio121_sleep &kso09_gpio122_sleep &kso10_gpio123_sleep + &kso11_gpio124_sleep &ksi0_gpio017_sleep &ksi1_gpio020_sleep + &ksi2_gpio021_sleep &ksi3_gpio026_sleep &ksi4_gpio027_sleep + &ksi5_gpio030_sleep &ksi6_gpio031_sleep &ksi7_gpio032_sleep >; + pinctrl-names = "default", "sleep"; }; &peci0 { diff --git a/boards/arm/mec1501modular_assy6885/mec1501modular_assy6885.yaml b/boards/arm/mec1501modular_assy6885/mec1501modular_assy6885.yaml index b1c69db9514..d78477f825f 100644 --- a/boards/arm/mec1501modular_assy6885/mec1501modular_assy6885.yaml +++ b/boards/arm/mec1501modular_assy6885/mec1501modular_assy6885.yaml @@ -23,3 +23,4 @@ supported: - watchdog - kscan - tach +vendor: microchip diff --git a/boards/arm/mec15xxevb_assy6853/mec15xxevb_assy6853.dts b/boards/arm/mec15xxevb_assy6853/mec15xxevb_assy6853.dts index a8bb074a8ff..fa577a53b7e 100644 --- a/boards/arm/mec15xxevb_assy6853/mec15xxevb_assy6853.dts +++ b/boards/arm/mec15xxevb_assy6853/mec15xxevb_assy6853.dts @@ -160,31 +160,21 @@ &kscan0 { status = "okay"; - pinctrl-0 = < &kso00_gpio040 - &kso01_gpio045 - &kso02_gpio046 - &kso12_gpio125 - &kso13_gpio126 - &kso03_gpio047 - &kso04_gpio107 - &kso05_gpio112 - &kso06_gpio113 - &kso14_gpio152 - &kso15_gpio151 - &kso07_gpio120 - &kso08_gpio121 - &kso09_gpio122 - &kso10_gpio123 - &kso11_gpio124 - &ksi0_gpio017 - &ksi1_gpio020 - &ksi2_gpio021 - &ksi3_gpio026 - &ksi4_gpio027 - &ksi5_gpio030 - &ksi6_gpio031 - &ksi7_gpio032 >; - pinctrl-names = "default"; + pinctrl-0 = < &kso00_gpio040 &kso01_gpio045 &kso02_gpio046 &kso12_gpio125 + &kso13_gpio126 &kso03_gpio047 &kso04_gpio107 &kso05_gpio112 + &kso06_gpio113 &kso14_gpio152 &kso15_gpio151 &kso07_gpio120 + &kso08_gpio121 &kso09_gpio122 &kso10_gpio123 &kso11_gpio124 + &ksi0_gpio017 &ksi1_gpio020 &ksi2_gpio021 &ksi3_gpio026 + &ksi4_gpio027 &ksi5_gpio030 &ksi6_gpio031 &ksi7_gpio032 >; + pinctrl-1 = < &kso00_gpio040_sleep &kso01_gpio045_sleep &kso02_gpio046_sleep + &kso12_gpio125_sleep &kso13_gpio126_sleep &kso03_gpio047_sleep + &kso04_gpio107_sleep &kso05_gpio112_sleep &kso06_gpio113_sleep + &kso14_gpio152_sleep &kso15_gpio151_sleep &kso07_gpio120_sleep + &kso08_gpio121_sleep &kso09_gpio122_sleep &kso10_gpio123_sleep + &kso11_gpio124_sleep &ksi0_gpio017_sleep &ksi1_gpio020_sleep + &ksi2_gpio021_sleep &ksi3_gpio026_sleep &ksi4_gpio027_sleep + &ksi5_gpio030_sleep &ksi6_gpio031_sleep &ksi7_gpio032_sleep >; + pinctrl-names = "default", "sleep"; }; &peci0 { diff --git a/boards/arm/mec15xxevb_assy6853/mec15xxevb_assy6853.yaml b/boards/arm/mec15xxevb_assy6853/mec15xxevb_assy6853.yaml index b197fb8562f..8b8190d20d8 100644 --- a/boards/arm/mec15xxevb_assy6853/mec15xxevb_assy6853.yaml +++ b/boards/arm/mec15xxevb_assy6853/mec15xxevb_assy6853.yaml @@ -22,3 +22,4 @@ supported: - pwm - watchdog - kscan +vendor: microchip diff --git a/boards/arm/mec172xevb_assy6906/mec172xevb_assy6906.dts b/boards/arm/mec172xevb_assy6906/mec172xevb_assy6906.dts index 2ecd3d413f2..35966d882e0 100644 --- a/boards/arm/mec172xevb_assy6906/mec172xevb_assy6906.dts +++ b/boards/arm/mec172xevb_assy6906/mec172xevb_assy6906.dts @@ -216,29 +216,21 @@ &kscan0 { status = "okay"; - pinctrl-0 = < &ksi0_gpio017 - &ksi1_gpio020 - &ksi2_gpio021 - &ksi3_gpio026 - &ksi4_gpio027 - &ksi5_gpio030 - &ksi6_gpio031 - &ksi7_gpio032 - &kso00_gpio040 - &kso01_gpio045 - &kso02_gpio046 - &kso03_gpio047 - &kso04_gpio107 - &kso05_gpio112 - &kso06_gpio113 - &kso07_gpio120 - &kso08_gpio121 - &kso09_gpio122 - &kso10_gpio123 - &kso11_gpio124 - &kso12_gpio125 - &kso13_gpio126 >; - pinctrl-names = "default"; + pinctrl-0 = < &ksi0_gpio017 &ksi1_gpio020 &ksi2_gpio021 &ksi3_gpio026 + &ksi4_gpio027 &ksi5_gpio030 &ksi6_gpio031 &ksi7_gpio032 + &kso00_gpio040 &kso01_gpio045 &kso02_gpio046 &kso03_gpio047 + &kso04_gpio107 &kso05_gpio112 &kso06_gpio113 &kso07_gpio120 + &kso08_gpio121 &kso09_gpio122 &kso10_gpio123 &kso11_gpio124 + &kso12_gpio125 &kso13_gpio126 >; + pinctrl-1 = < &ksi0_gpio017_sleep &ksi1_gpio020_sleep &ksi2_gpio021_sleep + &ksi3_gpio026_sleep &ksi4_gpio027_sleep &ksi5_gpio030_sleep + &ksi6_gpio031_sleep &ksi7_gpio032_sleep &kso00_gpio040_sleep + &kso01_gpio045_sleep &kso02_gpio046_sleep &kso03_gpio047_sleep + &kso04_gpio107_sleep &kso05_gpio112_sleep &kso06_gpio113_sleep + &kso07_gpio120_sleep &kso08_gpio121_sleep &kso09_gpio122_sleep + &kso10_gpio123_sleep &kso11_gpio124_sleep &kso12_gpio125_sleep + &kso13_gpio126_sleep >; + pinctrl-names = "default", "sleep"; }; &ksi0_gpio017 { diff --git a/boards/arm/mec172xevb_assy6906/mec172xevb_assy6906.yaml b/boards/arm/mec172xevb_assy6906/mec172xevb_assy6906.yaml index ad15ecfaf80..d7a96791cd6 100644 --- a/boards/arm/mec172xevb_assy6906/mec172xevb_assy6906.yaml +++ b/boards/arm/mec172xevb_assy6906/mec172xevb_assy6906.yaml @@ -19,9 +19,11 @@ supported: - adc - pwm - counter + - spi testing: binaries: - spi_image.bin ignore_tags: - bluetooth - net +vendor: microchip diff --git a/boards/arm/mec172xmodular_assy6930/mec172xmodular_assy6930.dts b/boards/arm/mec172xmodular_assy6930/mec172xmodular_assy6930.dts index 631f7ca15b1..d355f19afc3 100644 --- a/boards/arm/mec172xmodular_assy6930/mec172xmodular_assy6930.dts +++ b/boards/arm/mec172xmodular_assy6930/mec172xmodular_assy6930.dts @@ -194,29 +194,21 @@ &kscan0 { status = "okay"; - pinctrl-0 = < &ksi0_gpio017 - &ksi1_gpio020 - &ksi2_gpio021 - &ksi3_gpio026 - &ksi4_gpio027 - &ksi5_gpio030 - &ksi6_gpio031 - &ksi7_gpio032 - &kso00_gpio040 - &kso01_gpio045 - &kso02_gpio046 - &kso03_gpio047 - &kso04_gpio107 - &kso05_gpio112 - &kso06_gpio113 - &kso07_gpio120 - &kso08_gpio121 - &kso09_gpio122 - &kso10_gpio123 - &kso11_gpio124 - &kso12_gpio125 - &kso13_gpio126 >; - pinctrl-names = "default"; + pinctrl-0 = < &ksi0_gpio017 &ksi1_gpio020 &ksi2_gpio021 &ksi3_gpio026 + &ksi4_gpio027 &ksi5_gpio030 &ksi6_gpio031 &ksi7_gpio032 + &kso00_gpio040 &kso01_gpio045 &kso02_gpio046 &kso03_gpio047 + &kso04_gpio107 &kso05_gpio112 &kso06_gpio113 &kso07_gpio120 + &kso08_gpio121 &kso09_gpio122 &kso10_gpio123 &kso11_gpio124 + &kso12_gpio125 &kso13_gpio126 >; + pinctrl-1 = < &ksi0_gpio017_sleep &ksi1_gpio020_sleep &ksi2_gpio021_sleep + &ksi3_gpio026_sleep &ksi4_gpio027_sleep &ksi5_gpio030_sleep + &ksi6_gpio031_sleep &ksi7_gpio032_sleep &kso00_gpio040_sleep + &kso01_gpio045_sleep &kso02_gpio046_sleep &kso03_gpio047_sleep + &kso04_gpio107_sleep &kso05_gpio112_sleep &kso06_gpio113_sleep + &kso07_gpio120_sleep &kso08_gpio121_sleep &kso09_gpio122_sleep + &kso10_gpio123_sleep &kso11_gpio124_sleep &kso12_gpio125_sleep + &kso13_gpio126_sleep >; + pinctrl-names = "default", "sleep"; }; &ksi0_gpio017 { diff --git a/boards/arm/mec172xmodular_assy6930/mec172xmodular_assy6930.yaml b/boards/arm/mec172xmodular_assy6930/mec172xmodular_assy6930.yaml index 58bf4384d9c..26778c083c6 100644 --- a/boards/arm/mec172xmodular_assy6930/mec172xmodular_assy6930.yaml +++ b/boards/arm/mec172xmodular_assy6930/mec172xmodular_assy6930.yaml @@ -17,3 +17,4 @@ supported: - gpio - pinmux - i2c +vendor: microchip diff --git a/boards/arm/mercury_xu/mercury_xu.yaml b/boards/arm/mercury_xu/mercury_xu.yaml index ce965defd4a..df01c2b112a 100644 --- a/boards/arm/mercury_xu/mercury_xu.yaml +++ b/boards/arm/mercury_xu/mercury_xu.yaml @@ -6,3 +6,4 @@ arch: arm toolchain: - zephyr - gnuarmemb +vendor: xlnx diff --git a/boards/arm/mg100/Kconfig.defconfig b/boards/arm/mg100/Kconfig.defconfig index 74160f93bf5..46091ee3b47 100644 --- a/boards/arm/mg100/Kconfig.defconfig +++ b/boards/arm/mg100/Kconfig.defconfig @@ -18,6 +18,9 @@ config NORDIC_QSPI_NOR config NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE default 4096 if NORDIC_QSPI_NOR +config REGULATOR + default DISK_DRIVER_SDMMC + config BT_CTLR default BT diff --git a/boards/arm/mg100/mg100.dts b/boards/arm/mg100/mg100.dts index 0d33fd32151..1bbaa146dd6 100644 --- a/boards/arm/mg100/mg100.dts +++ b/boards/arm/mg100/mg100.dts @@ -49,6 +49,13 @@ }; }; + en-sd-switch { + compatible = "regulator-fixed"; + regulator-name = "en_sd_switch"; + enable-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>; + regulator-boot-on; + }; + /* These aliases are provided for compatibility with samples */ aliases { led0 = &led1; diff --git a/boards/arm/mg100/mg100.yaml b/boards/arm/mg100/mg100.yaml index adeb9e91121..917eb7f0d86 100644 --- a/boards/arm/mg100/mg100.yaml +++ b/boards/arm/mg100/mg100.yaml @@ -18,3 +18,4 @@ supported: - spi - watchdog - netif:modem +vendor: lairdconnect diff --git a/boards/arm/mg100/mg100_defconfig b/boards/arm/mg100/mg100_defconfig index bb7d09dabf2..e2af3973938 100644 --- a/boards/arm/mg100/mg100_defconfig +++ b/boards/arm/mg100/mg100_defconfig @@ -21,5 +21,3 @@ CONFIG_UART_CONSOLE=y # 32KHz clock source CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_150PPM=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/mikroe_clicker_2/mikroe_clicker_2.yaml b/boards/arm/mikroe_clicker_2/mikroe_clicker_2.yaml index 695407a13ea..b69a800360b 100644 --- a/boards/arm/mikroe_clicker_2/mikroe_clicker_2.yaml +++ b/boards/arm/mikroe_clicker_2/mikroe_clicker_2.yaml @@ -12,3 +12,4 @@ supported: - spi - i2c - adc +vendor: mikroe diff --git a/boards/arm/mikroe_clicker_2/mikroe_clicker_2_defconfig b/boards/arm/mikroe_clicker_2/mikroe_clicker_2_defconfig index 0d46fd7c84e..15ade5bcf58 100644 --- a/boards/arm/mikroe_clicker_2/mikroe_clicker_2_defconfig +++ b/boards/arm/mikroe_clicker_2/mikroe_clicker_2_defconfig @@ -9,6 +9,7 @@ CONFIG_SERIAL=y # console CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y # enable GPIO CONFIG_GPIO=y diff --git a/boards/arm/mikroe_mini_m4_for_stm32/mikroe_mini_m4_for_stm32.yaml b/boards/arm/mikroe_mini_m4_for_stm32/mikroe_mini_m4_for_stm32.yaml index 097c18249e2..479eb6e4887 100644 --- a/boards/arm/mikroe_mini_m4_for_stm32/mikroe_mini_m4_for_stm32.yaml +++ b/boards/arm/mikroe_mini_m4_for_stm32/mikroe_mini_m4_for_stm32.yaml @@ -15,3 +15,4 @@ supported: - spi - pwm - usb +vendor: mikroe diff --git a/boards/arm/mimx8mm_evk/mimx8mm_evk.yaml b/boards/arm/mimx8mm_evk/mimx8mm_evk.yaml index 1bec3704872..8854d16ac55 100644 --- a/boards/arm/mimx8mm_evk/mimx8mm_evk.yaml +++ b/boards/arm/mimx8mm_evk/mimx8mm_evk.yaml @@ -18,3 +18,4 @@ testing: ignore_tags: - net - bluetooth +vendor: nxp diff --git a/boards/arm/mimx8mm_phyboard_polis/mimx8mm_phyboard_polis.yaml b/boards/arm/mimx8mm_phyboard_polis/mimx8mm_phyboard_polis.yaml index 02118d9bda4..ee0fd50bf5f 100644 --- a/boards/arm/mimx8mm_phyboard_polis/mimx8mm_phyboard_polis.yaml +++ b/boards/arm/mimx8mm_phyboard_polis/mimx8mm_phyboard_polis.yaml @@ -18,3 +18,4 @@ testing: ignore_tags: - net - bluetooth +vendor: nxp diff --git a/boards/arm/mimx8mp_evk/mimx8mp_evk_ddr.yaml b/boards/arm/mimx8mp_evk/mimx8mp_evk_ddr.yaml index fc897e4b1e0..7e4b407380b 100644 --- a/boards/arm/mimx8mp_evk/mimx8mp_evk_ddr.yaml +++ b/boards/arm/mimx8mp_evk/mimx8mp_evk_ddr.yaml @@ -20,3 +20,4 @@ testing: - bluetooth supported: - uart +vendor: nxp diff --git a/boards/arm/mimx8mp_evk/mimx8mp_evk_itcm.yaml b/boards/arm/mimx8mp_evk/mimx8mp_evk_itcm.yaml index ed059c18aed..66c3c9b553d 100644 --- a/boards/arm/mimx8mp_evk/mimx8mp_evk_itcm.yaml +++ b/boards/arm/mimx8mp_evk/mimx8mp_evk_itcm.yaml @@ -20,3 +20,4 @@ testing: - bluetooth supported: - uart +vendor: nxp diff --git a/boards/arm/mimx8mp_phyboard_pollux/mimx8mp_phyboard_pollux.yaml b/boards/arm/mimx8mp_phyboard_pollux/mimx8mp_phyboard_pollux.yaml index 27dd7d5ec22..c696532393d 100644 --- a/boards/arm/mimx8mp_phyboard_pollux/mimx8mp_phyboard_pollux.yaml +++ b/boards/arm/mimx8mp_phyboard_pollux/mimx8mp_phyboard_pollux.yaml @@ -21,3 +21,4 @@ testing: supported: - uart - gpio +vendor: nxp diff --git a/boards/arm/mimx8mq_evk/doc/index.rst b/boards/arm/mimx8mq_evk/doc/index.rst index 892c6c6422c..486bf298fec 100644 --- a/boards/arm/mimx8mq_evk/doc/index.rst +++ b/boards/arm/mimx8mq_evk/doc/index.rst @@ -138,17 +138,50 @@ The available configurations are: - &ocram_sys - &ocram_s_sys -Load and run Zephyr on M4 from A53 using u-boot by copying the compiled -``zephyr.bin`` to the first FAT partition of the SD card and plug the SD -card into the board. Power it up and stop the u-boot execution at prompt. +Load and run Zephyr on M4 from A53 using u-boot. -Load the M4 binary onto the desired memory and start its execution using: +.. tabs:: -.. code-block:: console + .. group-tab:: From an SD card + Copy the compiled ``zephyr.bin`` to the first FAT partition of the + SD card and plug the SD card into the board. Power it up and stop the u-boot + execution at prompt. + + Load the M4 binary onto the desired memory and start its execution using: + + .. code-block:: console + + fatload mmc 0:1 0x40480000 zephyr.bin + cp.b 0x40480000 0x7e0000 0x8000 + bootaux 0x7e0000 + + .. group-tab:: From serial + This procedure requires ``screen`` and ``lrzsz`` to be installed. + + Start ``screen``, power up the board, and stop the u-boot execution at prompt: + + .. code-block:: console + + screen 115200 + + Start ``loadx`` with offset ``7e0000``: + + .. code-block:: console + + loadx 7e0000 115200 + + Send the compiled ``zephyr.bin`` with ``sx`` by pressing :kbd:`Ctrl-a` followed by :kbd:`:` + and write: + + .. code-block:: console + + exec !! sx + + Start execution: + + .. code-block:: console - fatload mmc 0:1 0x40480000 zephyr.bin - cp.b 0x40480000 0x7e0000 0x8000 - bootaux 0x7e0000 + bootaux 0x7e0000 Debugging ========= diff --git a/boards/arm/mimx8mq_evk/mimx8mq_evk_cm4.yaml b/boards/arm/mimx8mq_evk/mimx8mq_evk_cm4.yaml index d2462daff35..580b8cef0f3 100644 --- a/boards/arm/mimx8mq_evk/mimx8mq_evk_cm4.yaml +++ b/boards/arm/mimx8mq_evk/mimx8mq_evk_cm4.yaml @@ -18,3 +18,4 @@ testing: ignore_tags: - net - bluetooth +vendor: nxp diff --git a/boards/arm/mimxrt1010_evk/mimxrt1010_evk.yaml b/boards/arm/mimxrt1010_evk/mimxrt1010_evk.yaml index 73cd21480fc..302b3c64d80 100644 --- a/boards/arm/mimxrt1010_evk/mimxrt1010_evk.yaml +++ b/boards/arm/mimxrt1010_evk/mimxrt1010_evk.yaml @@ -26,3 +26,4 @@ supported: - usb_device - spi - adc +vendor: nxp diff --git a/boards/arm/mimxrt1015_evk/mimxrt1015_evk.yaml b/boards/arm/mimxrt1015_evk/mimxrt1015_evk.yaml index 7cddda02d16..b3c0b6d4d9c 100644 --- a/boards/arm/mimxrt1015_evk/mimxrt1015_evk.yaml +++ b/boards/arm/mimxrt1015_evk/mimxrt1015_evk.yaml @@ -24,3 +24,4 @@ supported: - usb_device - spi - adc +vendor: nxp diff --git a/boards/arm/mimxrt1020_evk/mimxrt1020_evk.yaml b/boards/arm/mimxrt1020_evk/mimxrt1020_evk.yaml index d8b3d824b1c..eebbc18ba84 100644 --- a/boards/arm/mimxrt1020_evk/mimxrt1020_evk.yaml +++ b/boards/arm/mimxrt1020_evk/mimxrt1020_evk.yaml @@ -26,3 +26,4 @@ supported: - usb_device - adc - sdhc +vendor: nxp diff --git a/boards/arm/mimxrt1024_evk/mimxrt1024_evk.yaml b/boards/arm/mimxrt1024_evk/mimxrt1024_evk.yaml index 0305793dd0d..4a0350c9cd4 100644 --- a/boards/arm/mimxrt1024_evk/mimxrt1024_evk.yaml +++ b/boards/arm/mimxrt1024_evk/mimxrt1024_evk.yaml @@ -25,3 +25,4 @@ supported: - adc - usb_device - pwm +vendor: nxp diff --git a/boards/arm/mimxrt1040_evk/mimxrt1040_evk.yaml b/boards/arm/mimxrt1040_evk/mimxrt1040_evk.yaml index 71b431a0a70..415ca704d60 100644 --- a/boards/arm/mimxrt1040_evk/mimxrt1040_evk.yaml +++ b/boards/arm/mimxrt1040_evk/mimxrt1040_evk.yaml @@ -21,3 +21,4 @@ supported: - adc - spi - i2c +vendor: nxp diff --git a/boards/arm/mimxrt1050_evk/doc/index.rst b/boards/arm/mimxrt1050_evk/doc/index.rst index 3081e162138..5d48e823f79 100644 --- a/boards/arm/mimxrt1050_evk/doc/index.rst +++ b/boards/arm/mimxrt1050_evk/doc/index.rst @@ -436,9 +436,9 @@ Board Revisions *************** The original MIMXRT1050-EVK (rev A0) board was updated with a newer -MIMXRT1050-EVKB (rev A1) board, with these major hardware differences:: +MIMXRT1050-EVKB (rev A1) board, with these major hardware differences: -- SoC changed from MIMXRT1052DVL6**A** to MIMXRT1052DVL6**B** +- SoC changed from MIMXRT1052DVL6\ **A** to MIMXRT1052DVL6\ **B** - Hardware bug fixes for: power, interfaces, and memory - Arduino headers included diff --git a/boards/arm/mimxrt1050_evk/mimxrt1050_evk.yaml b/boards/arm/mimxrt1050_evk/mimxrt1050_evk.yaml index 5fe02de586b..a19f9f10dba 100644 --- a/boards/arm/mimxrt1050_evk/mimxrt1050_evk.yaml +++ b/boards/arm/mimxrt1050_evk/mimxrt1050_evk.yaml @@ -28,3 +28,4 @@ supported: - usb_device - watchdog - adc +vendor: nxp diff --git a/boards/arm/mimxrt1050_evk/mimxrt1050_evk_qspi.yaml b/boards/arm/mimxrt1050_evk/mimxrt1050_evk_qspi.yaml index 8789741b15f..baadda8c061 100644 --- a/boards/arm/mimxrt1050_evk/mimxrt1050_evk_qspi.yaml +++ b/boards/arm/mimxrt1050_evk/mimxrt1050_evk_qspi.yaml @@ -28,3 +28,4 @@ supported: - usb_device - watchdog - adc +vendor: nxp diff --git a/boards/arm/mimxrt1060_evk/doc/index.rst b/boards/arm/mimxrt1060_evk/doc/index.rst index 838deeb477d..45d10009570 100644 --- a/boards/arm/mimxrt1060_evk/doc/index.rst +++ b/boards/arm/mimxrt1060_evk/doc/index.rst @@ -11,7 +11,7 @@ processor series and expands the i.MX RT series to three scalable families. The i.MX RT1060 doubles the On-Chip SRAM to 1MB while keeping pin-to-pin compatibility with i.MX RT1050. This series introduces additional features -ideal for real-time applications such as High-Speed GPIO, CAN-FD, and +ideal for real-time applications such as High-Speed GPIO, CAN FD, and synchronous parallel NAND/NOR/PSRAM controller. The i.MX RT1060 runs on the Arm® Cortex-M7® core up to 600 MHz. diff --git a/boards/arm/mimxrt1060_evk/mimxrt1060_evk-pinctrl.dtsi b/boards/arm/mimxrt1060_evk/mimxrt1060_evk-pinctrl.dtsi index 38eb539577b..7d2ff7a43e4 100644 --- a/boards/arm/mimxrt1060_evk/mimxrt1060_evk-pinctrl.dtsi +++ b/boards/arm/mimxrt1060_evk/mimxrt1060_evk-pinctrl.dtsi @@ -98,7 +98,7 @@ }; /* flexpwm output for board LED */ - pinmux_flexpwm2: pinmux_flexpwm2 { + pinmux_flexpwm2_3: pinmux_flexpwm2_3 { group0 { pinmux = <&iomuxc_gpio_ad_b0_09_flexpwm2_pwma3>; drive-strength = "r0-4"; @@ -109,6 +109,29 @@ }; }; + /* Conflicts with SD and SPI pins. Requires R281/R356 be populated */ + pinmux_flexpwm1_0: pinmux_flexpwm1_0 { + group0 { + pinmux = <&iomuxc_gpio_sd_b0_01_flexpwm1_pwmb0>; + drive-strength = "r0-4"; + bias-pull-up; + bias-pull-up-value = "47k"; + slew-rate = "slow"; + nxp,speed = "100-mhz"; + }; + }; + + pinmux_flexpwm1: pinmux_flexpwm1 { + group0 { + pinmux = <&iomuxc_gpio_ad_b0_10_flexpwm1_pwma3>; + drive-strength = "r0-4"; + bias-pull-up; + bias-pull-up-value = "47k"; + slew-rate = "slow"; + nxp,speed = "100-mhz"; + }; + }; + pinmux_flexspi1: pinmux_flexspi1 { group0 { pinmux = <&iomuxc_gpio_sd_b1_05_flexspi_a_dqs>; diff --git a/boards/arm/mimxrt1060_evk/mimxrt1060_evk.dts b/boards/arm/mimxrt1060_evk/mimxrt1060_evk.dts index 2b2f352d1c3..998e942e5a2 100644 --- a/boards/arm/mimxrt1060_evk/mimxrt1060_evk.dts +++ b/boards/arm/mimxrt1060_evk/mimxrt1060_evk.dts @@ -238,7 +238,17 @@ zephyr_udc0: &usb1 { &flexpwm2_pwm3 { status = "okay"; - pinctrl-0 = <&pinmux_flexpwm2>; + pinctrl-0 = <&pinmux_flexpwm2_3>; + pinctrl-names = "default"; +}; + +&flexpwm1_pwm0 { + pinctrl-0 = <&pinmux_flexpwm1_0>; + pinctrl-names = "default"; +}; + +&flexpwm1_pwm3 { + pinctrl-0 = <&pinmux_flexpwm1>; pinctrl-names = "default"; }; diff --git a/boards/arm/mimxrt1060_evk/mimxrt1060_evk.yaml b/boards/arm/mimxrt1060_evk/mimxrt1060_evk.yaml index 7daace5558e..82e15486159 100644 --- a/boards/arm/mimxrt1060_evk/mimxrt1060_evk.yaml +++ b/boards/arm/mimxrt1060_evk/mimxrt1060_evk.yaml @@ -32,3 +32,4 @@ supported: - can - watchdog - adc +vendor: nxp diff --git a/boards/arm/mimxrt1060_evk/mimxrt1060_evk_hyperflash.yaml b/boards/arm/mimxrt1060_evk/mimxrt1060_evk_hyperflash.yaml index 2107790685a..fa29bdfaa14 100644 --- a/boards/arm/mimxrt1060_evk/mimxrt1060_evk_hyperflash.yaml +++ b/boards/arm/mimxrt1060_evk/mimxrt1060_evk_hyperflash.yaml @@ -29,3 +29,4 @@ supported: - spi - usb_device - watchdog +vendor: nxp diff --git a/boards/arm/mimxrt1060_evk/mimxrt1060_evkb.yaml b/boards/arm/mimxrt1060_evk/mimxrt1060_evkb.yaml index 1e14219497a..3f9306c1e03 100644 --- a/boards/arm/mimxrt1060_evk/mimxrt1060_evkb.yaml +++ b/boards/arm/mimxrt1060_evk/mimxrt1060_evkb.yaml @@ -31,3 +31,4 @@ supported: - can - watchdog - adc +vendor: nxp diff --git a/boards/arm/mimxrt1062_fmurt6/doc/index.rst b/boards/arm/mimxrt1062_fmurt6/doc/index.rst index e1b7f284cc0..2c801c454af 100644 --- a/boards/arm/mimxrt1062_fmurt6/doc/index.rst +++ b/boards/arm/mimxrt1062_fmurt6/doc/index.rst @@ -11,7 +11,7 @@ processor series and expands the i.MX RT series to three scalable families. The i.MX RT1062 doubles the On-Chip SRAM to 1MB while keeping pin-to-pin compatibility with i.MX RT1050. This series introduces additional features -ideal for real-time applications such as High-Speed GPIO, CAN-FD, and +ideal for real-time applications such as High-Speed GPIO, CAN FD, and synchronous parallel NAND/NOR/PSRAM controller. The i.MX RT1062 runs on the Arm® Cortex-M7® core up to 600 MHz. diff --git a/boards/arm/mimxrt1062_fmurt6/mimxrt1062_fmurt6-pinctrl.dtsi b/boards/arm/mimxrt1062_fmurt6/mimxrt1062_fmurt6-pinctrl.dtsi index 9c22377dfe2..03b2c29c0d1 100644 --- a/boards/arm/mimxrt1062_fmurt6/mimxrt1062_fmurt6-pinctrl.dtsi +++ b/boards/arm/mimxrt1062_fmurt6/mimxrt1062_fmurt6-pinctrl.dtsi @@ -59,20 +59,6 @@ }; }; - pinmux_sensor: pinmux_sensor { - group0 { - pinmux = <&iomuxc_gpio_emc_13_gpio4_io13>, - <&iomuxc_gpio_emc_09_gpio4_io09>, - <&iomuxc_gpio_emc_06_gpio4_io06>, - <&iomuxc_gpio_emc_41_gpio3_io27>, - <&iomuxc_gpio_ad_b0_00_gpio1_io00>, - <&iomuxc_snvs_pmic_on_req_gpio5_io01>; - drive-strength = "r0-7"; - bias-pull-up; - slew-rate = "fast"; - }; - }; - pinmux_flexcan1: pinmux_flexcan1 { group0 { pinmux = <&iomuxc_gpio_ad_b1_08_flexcan1_tx>, diff --git a/boards/arm/mimxrt1062_fmurt6/mimxrt1062_fmurt6.dts b/boards/arm/mimxrt1062_fmurt6/mimxrt1062_fmurt6.dts index 17caea7f2b1..c3af13f1f0d 100644 --- a/boards/arm/mimxrt1062_fmurt6/mimxrt1062_fmurt6.dts +++ b/boards/arm/mimxrt1062_fmurt6/mimxrt1062_fmurt6.dts @@ -51,8 +51,6 @@ /* This regulator controls VDD_3V3_SD_CARD onboard supply */ reg-3v3-sdcard { - pinctrl-0 = <&pinmux_sensor>; - pinctrl-names = "default"; compatible = "regulator-fixed"; regulator-name = "reg-3v3-sdcard"; enable-gpios = <&gpio4 13 GPIO_ACTIVE_HIGH>; @@ -62,8 +60,6 @@ /* This regulator controls VDD_5V_PERIPH onboard supply */ reg-5v-periph { - pinctrl-0 = <&pinmux_sensor>; - pinctrl-names = "default"; compatible = "regulator-fixed"; regulator-name = "reg-5v-periph"; enable-gpios = <&gpio4 9 GPIO_ACTIVE_LOW>; @@ -73,8 +69,6 @@ /* This regulator controls VDD_5V_HIPOWER onboard supply */ reg-5v-hipower { - pinctrl-0 = <&pinmux_sensor>; - pinctrl-names = "default"; compatible = "regulator-fixed"; regulator-name = "reg-5v-hipower"; enable-gpios = <&gpio4 6 GPIO_ACTIVE_LOW>; @@ -84,8 +78,6 @@ /* This regulator controls the 3V3_S line, which powers sensors on-board. */ reg-3v3-sensor { - pinctrl-0 = <&pinmux_sensor>; - pinctrl-names = "default"; compatible = "regulator-fixed"; regulator-name = "reg-3v3-sensor"; enable-gpios = <&gpio3 27 GPIO_ACTIVE_HIGH>; @@ -96,8 +88,6 @@ /* This regulator controls VDD_3V3_SPEKTRUM onboard supply */ reg-3v3-spektrum { - pinctrl-0 = <&pinmux_sensor>; - pinctrl-names = "default"; compatible = "regulator-fixed"; regulator-name = "reg-3v3-spektrum"; enable-gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>; @@ -107,8 +97,6 @@ /* This regulator controls ETH_VDD_3V3 supply to power up the TJA1103 PHY */ reg-eth-power { - pinctrl-0 = <&pinmux_sensor>; - pinctrl-names = "default"; compatible = "regulator-fixed"; regulator-name = "reg-eth-power"; enable-gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>; diff --git a/boards/arm/mimxrt1062_fmurt6/mimxrt1062_fmurt6.yaml b/boards/arm/mimxrt1062_fmurt6/mimxrt1062_fmurt6.yaml index 35732dd66b4..01824d0b3bc 100644 --- a/boards/arm/mimxrt1062_fmurt6/mimxrt1062_fmurt6.yaml +++ b/boards/arm/mimxrt1062_fmurt6/mimxrt1062_fmurt6.yaml @@ -28,3 +28,4 @@ supported: - watchdog - adc - pwm +vendor: nxp diff --git a/boards/arm/mimxrt1064_evk/doc/index.rst b/boards/arm/mimxrt1064_evk/doc/index.rst index 462fe7629b3..24abf5ca76f 100644 --- a/boards/arm/mimxrt1064_evk/doc/index.rst +++ b/boards/arm/mimxrt1064_evk/doc/index.rst @@ -10,7 +10,7 @@ The i.MX RT1064 adds to the industry's first crossover processor series and expands the i.MX RT series to three scalable families. The i.MX RT1064 doubles the On-Chip SRAM to 1MB while keeping pin-to-pin compatibility with i.MX RT1050. This series introduces additional features -ideal for real-time applications such as High-Speed GPIO, CAN-FD, and +ideal for real-time applications such as High-Speed GPIO, CAN FD, and synchronous parallel NAND/NOR/PSRAM controller. The i.MX RT1064 runs on the Arm® Cortex-M7® core up to 600 MHz. diff --git a/boards/arm/mimxrt1064_evk/mimxrt1064_evk.yaml b/boards/arm/mimxrt1064_evk/mimxrt1064_evk.yaml index 1c5a3cbfde1..a9d454a5083 100644 --- a/boards/arm/mimxrt1064_evk/mimxrt1064_evk.yaml +++ b/boards/arm/mimxrt1064_evk/mimxrt1064_evk.yaml @@ -32,3 +32,4 @@ supported: - can - watchdog - adc +vendor: nxp diff --git a/boards/arm/mimxrt1160_evk/mimxrt1160_evk_cm4.yaml b/boards/arm/mimxrt1160_evk/mimxrt1160_evk_cm4.yaml index 08bfd467151..8d0d041c14f 100644 --- a/boards/arm/mimxrt1160_evk/mimxrt1160_evk_cm4.yaml +++ b/boards/arm/mimxrt1160_evk/mimxrt1160_evk_cm4.yaml @@ -20,3 +20,4 @@ supported: - gpio - pwm - uart +vendor: nxp diff --git a/boards/arm/mimxrt1160_evk/mimxrt1160_evk_cm7.yaml b/boards/arm/mimxrt1160_evk/mimxrt1160_evk_cm7.yaml index b5b91c00591..48e4f372355 100644 --- a/boards/arm/mimxrt1160_evk/mimxrt1160_evk_cm7.yaml +++ b/boards/arm/mimxrt1160_evk/mimxrt1160_evk_cm7.yaml @@ -26,3 +26,4 @@ supported: - spi - usb_device - watchdog +vendor: nxp diff --git a/boards/arm/mimxrt1170_evk/board.cmake b/boards/arm/mimxrt1170_evk/board.cmake index e743455b20d..d543dce8821 100644 --- a/boards/arm/mimxrt1170_evk/board.cmake +++ b/boards/arm/mimxrt1170_evk/board.cmake @@ -5,13 +5,28 @@ # if(CONFIG_SOC_MIMXRT1176_CM7 OR CONFIG_SECOND_CORE_MCUX) -board_runner_args(pyocd "--target=mimxrt1170_cm7") -board_runner_args(jlink "--device=MIMXRT1176xxxA_M7" "--reset-after-load") + board_runner_args(pyocd "--target=mimxrt1170_cm7") + board_runner_args(jlink "--device=MIMXRT1176xxxA_M7" "--reset-after-load") + + if(CONFIG_BOARD_MIMXRT1170_EVK_CM7) + board_runner_args(linkserver "--device=MIMXRT1176xxxxx:MIMXRT1170-EVK") + elseif(CONFIG_BOARD_MIMXRT1170_EVKB_CM7) + board_runner_args(linkserver "--device=MIMXRT1176xxxxx:MIMXRT1170-EVKB") + endif() + + board_runner_args(linkserver "--core=cm7") elseif(CONFIG_SOC_MIMXRT1176_CM4) -board_runner_args(pyocd "--target=mimxrt1170_cm4") -# Note: Please use JLINK above V7.50 (Only support run cm4 image when debugging due to default boot core on board is cm7 core) -board_runner_args(jlink "--device=MIMXRT1176xxxA_M4") + board_runner_args(pyocd "--target=mimxrt1170_cm4") + # Note: Please use JLINK above V7.50 (Only support run cm4 image when debugging due to default boot core on board is cm7 core) + board_runner_args(jlink "--device=MIMXRT1176xxxA_M4") + if(CONFIG_BOARD_MIMXRT1170_EVK_CM4) + board_runner_args(linkserver "--device=MIMXRT1176xxxxx:MIMXRT1170-EVK") + elseif(CONFIG_BOARD_MIMXRT1170_EVKB_CM4) + board_runner_args(linkserver "--device=MIMXRT1176xxxxx:MIMXRT1170-EVKB") + endif() + board_runner_args(linkserver "--core=cm4") endif() include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) diff --git a/boards/arm/mimxrt1170_evk/doc/index.rst b/boards/arm/mimxrt1170_evk/doc/index.rst index 1582861ffc9..15a66875d31 100644 --- a/boards/arm/mimxrt1170_evk/doc/index.rst +++ b/boards/arm/mimxrt1170_evk/doc/index.rst @@ -349,6 +349,11 @@ Use the ``-r linkserver`` option with West to use the LinkServer runner. west flash -r linkserver +Alternatively, pyOCD can be used to flash and debug the board by using the +``-r pyocd`` option with West. pyOCD is installed when you complete the +:ref:`gs_python_deps` step in the Getting Started Guide. The runners supported +by NXP are LinkServer and JLink. pyOCD is another potential option, but NXP +does not test or support the pyOCD runner. Configuring a Console ===================== diff --git a/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm4.yaml b/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm4.yaml index ea1382d4233..69232196b62 100644 --- a/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm4.yaml +++ b/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm4.yaml @@ -19,3 +19,4 @@ supported: - gpio - i2c - pwm +vendor: nxp diff --git a/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm7.dts b/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm7.dts index 1bf1ef1597f..48564a03b4d 100644 --- a/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm7.dts +++ b/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm7.dts @@ -82,6 +82,8 @@ zephyr_mipi_dsi: &mipi_dsi { }; &lpspi1 { + dmas = <&edma0 0 36>, <&edma0 1 37>; + dma-names = "rx", "tx"; status = "okay"; }; diff --git a/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm7.yaml b/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm7.yaml index db9980a083e..ba3ae1b201b 100644 --- a/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm7.yaml +++ b/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm7.yaml @@ -28,3 +28,4 @@ supported: - spi - usb_device - watchdog +vendor: nxp diff --git a/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm4.dts b/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm4.dts index 727ada86cd3..5700b77837c 100644 --- a/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm4.dts +++ b/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm4.dts @@ -71,6 +71,8 @@ }; &lpspi1 { + dmas = <&edma_lpsr0 0 36>, <&edma_lpsr0 1 37>; + dma-names = "rx", "tx"; status = "okay"; }; diff --git a/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm4.yaml b/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm4.yaml index e9519f594cd..77a684f23ed 100644 --- a/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm4.yaml +++ b/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm4.yaml @@ -20,3 +20,4 @@ supported: - i2c - spi - pwm +vendor: nxp diff --git a/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm7.yaml b/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm7.yaml index 9bb5b1d809f..03376fd15c3 100644 --- a/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm7.yaml +++ b/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm7.yaml @@ -26,3 +26,4 @@ supported: - spi - usb_device - watchdog +vendor: nxp diff --git a/boards/arm/mimxrt595_evk/board.c b/boards/arm/mimxrt595_evk/board.c index 99aed3a7642..fce50f4c23d 100644 --- a/boards/arm/mimxrt595_evk/board.c +++ b/boards/arm/mimxrt595_evk/board.c @@ -19,6 +19,22 @@ static const struct device *sw2 = DEVICE_DT_GET(NODE_SW2); static const struct device *ldo1 = DEVICE_DT_GET(NODE_LDO1); static const struct device *ldo2 = DEVICE_DT_GET(NODE_LDO2); +#define MEGA (1000000U) + +/* Core frequency levels number. */ +#define POWER_FREQ_LEVELS_NUM (5U) + +/* Invalid voltage level. */ +#define POWER_INVALID_VOLT_LEVEL (0xFFFFFFFFU) + +static const uint32_t power_freq_level[POWER_FREQ_LEVELS_NUM] = { + 275U * MEGA, + 230U * MEGA, + 192U * MEGA, + 100U * MEGA, + 60U * MEGA +}; + /* System clock frequency. */ extern uint32_t SystemCoreClock; @@ -30,7 +46,7 @@ static int32_t board_calc_volt_level(void) uint32_t volt; for (i = 0U; i < POWER_FREQ_LEVELS_NUM; i++) { - if (SystemCoreClock > powerFreqLevel[i]) { + if (SystemCoreClock > power_freq_level[i]) { break; } } diff --git a/boards/arm/mimxrt595_evk/doc/index.rst b/boards/arm/mimxrt595_evk/doc/index.rst index 61ed427858a..a82735ba278 100644 --- a/boards/arm/mimxrt595_evk/doc/index.rst +++ b/boards/arm/mimxrt595_evk/doc/index.rst @@ -174,6 +174,20 @@ Serial Port The MIMXRT595 SoC has 13 FLEXCOMM interfaces for serial communication. One is configured as USART for the console and the remaining are not used. +Fusion F1 DSP Core +================== + +You can build a Zephyr application for the RT500 DSP core using nxp_adsp_rt595 +board. Xtensa toolchain supporting RT500 DSP core is included in Zephyr SDK. +To build the hello_world sample for the RT500 DSP core: + +.. code-block:: shell + + $ west build -b nxp_adsp_rt595 samples/hello_world + +For detailed instructions on how to debug DSP firmware, please refer to +this document: `Getting Started with Xplorer for EVK-MIMXRT595`_ + Programming and Debugging ************************* @@ -313,3 +327,6 @@ steps: .. _i.MX RT595 Reference Manual: https://www.nxp.com/webapp/Download?colCode=IMXRT500RM + +.. _Getting Started with Xplorer for EVK-MIMXRT595: + https://www.nxp.com/docs/en/supporting-information/GSXEVKMIMXRT595.pdf diff --git a/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.dts b/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.dts index e65106d87d6..b91a45f5008 100644 --- a/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.dts +++ b/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.dts @@ -459,7 +459,26 @@ zephyr_udc0: &usbhs { status = "okay"; }; +&mbox { + status = "okay"; +}; + /* Disable this node if not using USB and need another MPU region */ &sram1 { status = "okay"; }; + +/* Enable smartDMA controller */ +&smartdma { + status = "okay"; +}; + +/* Add smartDMA to mipi DSI */ +&mipi_dsi { + dmas = <&smartdma>; + dma-names = "smartdma"; +}; + +&mrt_channel0 { + status = "okay"; +}; diff --git a/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.yaml b/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.yaml index eebf9db3991..6e35595c078 100644 --- a/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.yaml +++ b/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.yaml @@ -28,3 +28,4 @@ supported: - sdhc - pwm - i2s +vendor: nxp diff --git a/boards/arm/mimxrt685_evk/mimxrt685_evk_cm33.yaml b/boards/arm/mimxrt685_evk/mimxrt685_evk_cm33.yaml index 21aaa88535b..d940cbe35f8 100644 --- a/boards/arm/mimxrt685_evk/mimxrt685_evk_cm33.yaml +++ b/boards/arm/mimxrt685_evk/mimxrt685_evk_cm33.yaml @@ -31,3 +31,4 @@ supported: - spi - watchdog - usb_device +vendor: nxp diff --git a/boards/arm/mm_feather/mm_feather.yaml b/boards/arm/mm_feather/mm_feather.yaml index 2645f42f5bc..a8af021d856 100644 --- a/boards/arm/mm_feather/mm_feather.yaml +++ b/boards/arm/mm_feather/mm_feather.yaml @@ -23,3 +23,4 @@ supported: - uart - pwm - spi +vendor: nxp diff --git a/boards/arm/mm_swiftio/mm_swiftio.yaml b/boards/arm/mm_swiftio/mm_swiftio.yaml index 943268dece1..cc27cbe2540 100644 --- a/boards/arm/mm_swiftio/mm_swiftio.yaml +++ b/boards/arm/mm_swiftio/mm_swiftio.yaml @@ -17,3 +17,4 @@ flash: 8192 supported: - counter - sdhc +vendor: nxp diff --git a/boards/arm/mps2_an385/mps2_an385.yaml b/boards/arm/mps2_an385/mps2_an385.yaml index c008aa63697..fec9dfc0fa8 100644 --- a/boards/arm/mps2_an385/mps2_an385.yaml +++ b/boards/arm/mps2_an385/mps2_an385.yaml @@ -13,3 +13,6 @@ supported: - gpio testing: default: true + ignore_tags: + - net +vendor: arm diff --git a/boards/arm/mps2_an521/mps2_an521.yaml b/boards/arm/mps2_an521/mps2_an521.yaml index 964258a32d9..acc2d95127b 100644 --- a/boards/arm/mps2_an521/mps2_an521.yaml +++ b/boards/arm/mps2_an521/mps2_an521.yaml @@ -18,3 +18,4 @@ testing: - bluetooth - net - timer +vendor: arm diff --git a/boards/arm/mps2_an521/mps2_an521_ns.yaml b/boards/arm/mps2_an521/mps2_an521_ns.yaml index 08388be71f2..bf8d5edc243 100644 --- a/boards/arm/mps2_an521/mps2_an521_ns.yaml +++ b/boards/arm/mps2_an521/mps2_an521_ns.yaml @@ -16,3 +16,4 @@ testing: - kernel - tfm - userspace + - trusted-firmware-m diff --git a/boards/arm/mps3_an547/mps3_an547.yaml b/boards/arm/mps3_an547/mps3_an547.yaml index e8f2b551404..3ade98161c8 100644 --- a/boards/arm/mps3_an547/mps3_an547.yaml +++ b/boards/arm/mps3_an547/mps3_an547.yaml @@ -23,3 +23,4 @@ testing: - bluetooth - net - timer +vendor: arm diff --git a/boards/arm/mr_canhubk3/Kconfig.board b/boards/arm/mr_canhubk3/Kconfig.board index 3cea453a2a2..af9a09391cd 100644 --- a/boards/arm/mr_canhubk3/Kconfig.board +++ b/boards/arm/mr_canhubk3/Kconfig.board @@ -3,5 +3,5 @@ config BOARD_MR_CANHUBK3 bool "mr_canhubk3" - depends on SOC_SERIES_S32K3_M7 - select SOC_PART_NUMBER_S32K344 + depends on SOC_SERIES_S32K3XX + select SOC_PART_NUMBER_PS32K344EHVPBS diff --git a/boards/arm/mr_canhubk3/Kconfig.defconfig b/boards/arm/mr_canhubk3/Kconfig.defconfig index c2a2501ebe3..6cf6f085492 100644 --- a/boards/arm/mr_canhubk3/Kconfig.defconfig +++ b/boards/arm/mr_canhubk3/Kconfig.defconfig @@ -23,7 +23,7 @@ endif # CAN if NETWORKING config NET_L2_ETHERNET - default y + default y if !NET_LOOPBACK && !NET_TEST endif # NETWORKING diff --git a/boards/arm/mr_canhubk3/doc/index.rst b/boards/arm/mr_canhubk3/doc/index.rst index bc7add3c112..63dbb36666b 100644 --- a/boards/arm/mr_canhubk3/doc/index.rst +++ b/boards/arm/mr_canhubk3/doc/index.rst @@ -48,6 +48,7 @@ Interface Controller Driver/Component SIUL2 on-chip | pinctrl | gpio | external interrupt controller +WKPU on-chip interrupt controller LPUART on-chip serial QSPI on-chip flash FLEXCAN on-chip can @@ -56,6 +57,8 @@ ADC SAR on-chip adc LPSPI on-chip spi WDT FS26 SBC watchdog EMAC on-chip ethernet +eMIOS on-chip pwm +EDMA on-chip dma ============ ========== ================================ The default configuration can be found in the Kconfig file @@ -68,6 +71,21 @@ Each GPIO port is divided into two banks: low bank, from pin 0 to 15, and high bank, from pin 16 to 31. For example, ``PTA2`` is the pin 2 of ``gpioa_l`` (low bank), and ``PTA20`` is the pin 4 of ``gpioa_h`` (high bank). +The GPIO controller provides the option to route external input pad interrupts +to either the SIUL2 EIRQ or WKPU interrupt controllers, as supported by the SoC. +By default, GPIO interrupts are routed to SIUL2 EIRQ interrupt controller, +unless they are explicity configured to be directed to the WKPU interrupt +controller, as outlined in :zephyr_file:`dts/bindings/gpio/nxp,s32-gpio.yaml`. + +To find information about which GPIOs are compatible with each interrupt +controller, refer to the device reference manual. + +.. note:: + + It is important to highlight that the current board configuration lacks + support for wake-up events and power-management features. WKPU functionality + is restricted solely to serving as an interrupt controller. + LEDs ---- diff --git a/boards/arm/mr_canhubk3/mr_canhubk3-pinctrl.dtsi b/boards/arm/mr_canhubk3/mr_canhubk3-pinctrl.dtsi index 459215510cc..1c3ff008508 100644 --- a/boards/arm/mr_canhubk3/mr_canhubk3-pinctrl.dtsi +++ b/boards/arm/mr_canhubk3/mr_canhubk3-pinctrl.dtsi @@ -9,7 +9,7 @@ &pinctrl { eirq0_default: eirq0_default { group1 { - pinmux = , ; + pinmux = , , ; input-enable; }; }; @@ -267,6 +267,24 @@ pinmux = , , ; + }; + }; + + emios0_default: emios0_default { + group1 { + pinmux = , , + , , + , , + , , + ; + output-enable; + }; + }; + + emios1_default: emios1_default { + group1 { + pinmux = , + ; output-enable; }; }; diff --git a/boards/arm/mr_canhubk3/mr_canhubk3.dts b/boards/arm/mr_canhubk3/mr_canhubk3.dts index f472eb0fe1c..ec5eb1ece43 100644 --- a/boards/arm/mr_canhubk3/mr_canhubk3.dts +++ b/boards/arm/mr_canhubk3/mr_canhubk3.dts @@ -9,6 +9,7 @@ #include #include #include +#include #include "mr_canhubk3-pinctrl.dtsi" / { @@ -28,12 +29,19 @@ }; aliases { + dma0 = &edma0; led0 = &user_led1_red; led1 = &user_led1_green; led2 = &user_led1_blue; sw0 = &user_button_1; sw1 = &user_button_2; watchdog0 = &fs26_wdt; + /* For pwm test suites */ + pwm-0 = &emios0_pwm; + red-pwm-led = &user_led1_red_pwm; + green-pwm-led = &user_led1_green_pwm; + blue-pwm-led = &user_led1_blue_pwm; + pwm-led0 = &user_led1_blue_pwm; }; leds { @@ -52,6 +60,23 @@ }; }; + /* gpio-leds and pwm-leds are the same RGB LED and cannot be used at the same time. */ + pwmleds { + compatible = "pwm-leds"; + + user_led1_blue_pwm: user_led1_blue { + pwms = <&emios1_pwm 5 PWM_MSEC(20) PWM_POLARITY_INVERTED>; + }; + + user_led1_green_pwm: user_led1_green { + pwms = <&emios1_pwm 10 PWM_MSEC(20) PWM_POLARITY_INVERTED>; + }; + + user_led1_red_pwm: user_led1_red { + pwms = <&emios0_pwm 19 PWM_MSEC(20) PWM_POLARITY_INVERTED>; + }; + }; + gpio_keys { compatible = "gpio-keys"; user_button_1: button_0 { @@ -172,38 +197,62 @@ &lpuart0 { pinctrl-0 = <&lpuart0_default>; pinctrl-names = "default"; + dmas = <&edma0 0 37>, <&edma0 1 38>; + dma-names = "tx", "rx"; }; &lpuart1 { pinctrl-0 = <&lpuart1_default>; pinctrl-names = "default"; + dmas = <&edma0 2 39>, <&edma0 3 40>; + dma-names = "tx", "rx"; }; &lpuart2 { pinctrl-0 = <&lpuart2_default>; pinctrl-names = "default"; current-speed = <115200>; + dmas = <&edma0 16 38>, <&edma0 17 39>; + dma-names = "tx", "rx"; status = "okay"; }; &lpuart9 { pinctrl-0 = <&lpuart9_default>; pinctrl-names = "default"; + /* + * LPUART 1 and 9 share the same DMA source for TX + * and RX, using UART async API for both instances + * should be careful. + */ + dmas = <&edma0 4 39>, <&edma0 5 40>; + dma-names = "tx", "rx"; }; &lpuart10 { pinctrl-0 = <&lpuart10_default>; pinctrl-names = "default"; + /* + * LPUART 2 and 10 share the same DMA source for TX + * and RX, using UART async API for both instances + * should be careful. + */ + dmas = <&edma0 18 38>, <&edma0 19 39>; + dma-names = "tx", "rx"; }; &lpuart13 { pinctrl-0 = <&lpuart13_default>; pinctrl-names = "default"; + dmas = <&edma0 20 44>, <&edma0 21 45>; + dma-names = "tx", "rx"; }; &lpuart14 { pinctrl-0 = <&lpuart14_default>; pinctrl-names = "default"; + dmas = <&edma0 22 46>, <&edma0 23 47>; + dma-names = "tx", "rx"; }; &qspi0 { @@ -247,10 +296,8 @@ phys = <&can_phy0>; bus-speed = <125000>; sample-point = <875>; - sjw = <1>; bus-speed-data = <1000000>; sample-point-data = <875>; - sjw-data = <1>; status = "okay"; }; @@ -260,10 +307,8 @@ phys = <&can_phy1>; bus-speed = <125000>; sample-point = <875>; - sjw = <1>; bus-speed-data = <1000000>; sample-point-data = <875>; - sjw-data = <1>; }; &flexcan2 { @@ -272,10 +317,8 @@ phys = <&can_phy2>; bus-speed = <125000>; sample-point = <875>; - sjw = <1>; bus-speed-data = <1000000>; sample-point-data = <875>; - sjw-data = <1>; }; &flexcan3 { @@ -284,10 +327,8 @@ phys = <&can_phy3>; bus-speed = <125000>; sample-point = <875>; - sjw = <1>; bus-speed-data = <1000000>; sample-point-data = <875>; - sjw-data = <1>; }; &flexcan4 { @@ -296,10 +337,8 @@ phys = <&can_phy4>; bus-speed = <125000>; sample-point = <875>; - sjw = <1>; bus-speed-data = <1000000>; sample-point-data = <875>; - sjw-data = <1>; }; &flexcan5 { @@ -308,10 +347,8 @@ phys = <&can_phy5>; bus-speed = <125000>; sample-point = <875>; - sjw = <1>; bus-speed-data = <1000000>; sample-point-data = <875>; - sjw-data = <1>; }; &lpi2c0 { @@ -378,3 +415,159 @@ full-duplex; }; }; + +&emios0 { + clock-divider = <200>; + status = "okay"; + + master_bus { + /* + * Timebase for PWM led, setting clock 50KHz for internal counter, + * default period is 1000 cycles <-> 20ms. + */ + emios0_bus_a { + mode = "MCB_UP_COUNTER"; + prescaler = <16>; + period = <1000>; + status = "okay"; + }; + }; + + emios0_pwm: pwm { + pinctrl-0 = <&emios0_default>; + pinctrl-names = "default"; + status = "okay"; + + /* Default clock for internal counter for PWM channel 0-7 is 100Khz */ + pwm_0 { + channel = <0>; + pwm-mode = "OPWFMB"; + period = <65535>; + duty-cycle = <0>; + prescaler = <8>; + polarity = "ACTIVE_HIGH"; + }; + + pwm_1 { + channel = <1>; + pwm-mode = "OPWFMB"; + period = <65535>; + duty-cycle = <0>; + prescaler = <8>; + polarity = "ACTIVE_HIGH"; + }; + + pwm_2 { + channel = <2>; + pwm-mode = "OPWFMB"; + period = <65535>; + duty-cycle = <0>; + prescaler = <8>; + polarity = "ACTIVE_HIGH"; + }; + + pwm_3 { + channel = <3>; + pwm-mode = "OPWFMB"; + period = <65535>; + duty-cycle = <0>; + prescaler = <8>; + polarity = "ACTIVE_HIGH"; + }; + + pwm_4 { + channel = <4>; + pwm-mode = "OPWFMB"; + period = <65535>; + duty-cycle = <0>; + prescaler = <8>; + polarity = "ACTIVE_HIGH"; + }; + + pwm_5 { + channel = <5>; + pwm-mode = "OPWFMB"; + period = <65535>; + duty-cycle = <0>; + prescaler = <8>; + polarity = "ACTIVE_HIGH"; + }; + + pwm_6 { + channel = <6>; + pwm-mode = "OPWFMB"; + period = <65535>; + duty-cycle = <0>; + prescaler = <8>; + polarity = "ACTIVE_HIGH"; + }; + + pwm_7 { + channel = <7>; + pwm-mode = "OPWFMB"; + period = <65535>; + duty-cycle = <0>; + prescaler = <8>; + polarity = "ACTIVE_HIGH"; + }; + + rgb_red { + channel = <19>; + master-bus = <&emios0_bus_a>; + duty-cycle = <0>; + pwm-mode = "OPWMB"; + polarity = "ACTIVE_LOW"; + }; + }; +}; + +&emios1 { + clock-divider = <200>; + status = "okay"; + + master_bus { + /* + * Timebase for PWM led, setting clock 50KHz for internal counter, + * default period is 1000 cycles <-> 20ms. + */ + emios1_bus_a { + prescaler = <16>; + mode = "MCB_UP_COUNTER"; + period = <1000>; + status = "okay"; + }; + + emios1_bus_f { + prescaler = <16>; + mode = "MCB_UP_COUNTER"; + period = <1000>; + status = "okay"; + }; + }; + + emios1_pwm: pwm { + pinctrl-0 = <&emios1_default>; + pinctrl-names = "default"; + status = "okay"; + + rgb_green { + channel = <10>; + master-bus = <&emios1_bus_a>; + duty-cycle = <0>; + pwm-mode = "OPWMB"; + polarity = "ACTIVE_LOW"; + }; + + rgb_blue { + channel = <5>; + master-bus = <&emios1_bus_f>; + duty-cycle = <0>; + pwm-mode = "OPWMB"; + polarity = "ACTIVE_LOW"; + }; + }; +}; + +&edma0 { + status = "okay"; +}; diff --git a/boards/arm/mr_canhubk3/mr_canhubk3.yaml b/boards/arm/mr_canhubk3/mr_canhubk3.yaml index d60d59838cc..227498e16a7 100644 --- a/boards/arm/mr_canhubk3/mr_canhubk3.yaml +++ b/boards/arm/mr_canhubk3/mr_canhubk3.yaml @@ -18,3 +18,6 @@ supported: - spi - watchdog - netif:eth + - pwm + - dma +vendor: nxp diff --git a/boards/arm/mr_canhubk3/mr_canhubk3_defconfig b/boards/arm/mr_canhubk3/mr_canhubk3_defconfig index 68613d22f11..d8182ce8327 100644 --- a/boards/arm/mr_canhubk3/mr_canhubk3_defconfig +++ b/boards/arm/mr_canhubk3/mr_canhubk3_defconfig @@ -2,8 +2,8 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_BOARD_MR_CANHUBK3=y -CONFIG_SOC_S32K344_M7=y -CONFIG_SOC_SERIES_S32K3_M7=y +CONFIG_SOC_S32K344=y +CONFIG_SOC_SERIES_S32K3XX=y CONFIG_BUILD_OUTPUT_HEX=y # Use Systick as system clock diff --git a/boards/arm/msp_exp432p401r_launchxl/board.cmake b/boards/arm/msp_exp432p401r_launchxl/board.cmake new file mode 100644 index 00000000000..cbeaea2e456 --- /dev/null +++ b/boards/arm/msp_exp432p401r_launchxl/board.cmake @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/arm/msp_exp432p401r_launchxl/doc/index.rst b/boards/arm/msp_exp432p401r_launchxl/doc/index.rst index 709adee2f08..d2a2e12153a 100644 --- a/boards/arm/msp_exp432p401r_launchxl/doc/index.rst +++ b/boards/arm/msp_exp432p401r_launchxl/doc/index.rst @@ -55,47 +55,80 @@ Other hardware features are not currently supported by the Zephyr kernel. Building and Flashing ********************* -Building +Prerequisites: +============== + +#. Ensure the XDS-110 emulation firmware is updated. + + Download and install the latest `XDS-110 emulation package`_. + + Follow these `xds110 firmware update directions + `_ + + Note that the emulation package install may place the xdsdfu utility + in ``/ccs_base/common/uscif/xds110/``. + +#. Install OpenOCD + + You can obtain OpenOCD by following these + :ref:`installing the latest Zephyr SDK instructions `. + + After the installation, add the directory containing the OpenOCD executable + to your environment's PATH variable. For example, use this command in Linux: + + .. code-block:: console + + export PATH=$ZEPHYR_SDK_INSTALL_DIR/sysroots/x86_64-pokysdk-linux/usr/bin/openocd:$PATH + + If you had previously installed TI OpenOCD, you can simply switch to use + the one in the Zephyr SDK. If for some reason you wish to continue to use + your TI OpenOCD installation, you can set the OPENOCD and + OPENOCD_DEFAULT_PATH variables in + :zephyr_file:`boards/arm/msp_exp432p401r_launchxl/board.cmake` to point the build + to the paths of the OpenOCD binary and its scripts, before + including the common openocd.board.cmake file: + + .. code-block:: cmake + + set(OPENOCD "/usr/local/bin/openocd" CACHE FILEPATH "" FORCE) + set(OPENOCD_DEFAULT_PATH /usr/local/share/openocd/scripts) + include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) + +Flashing ======== Follow the :ref:`getting_started` instructions for Zephyr application development. -For example, to build the :ref:`hello_world` application for the +For example, to build and flash the :ref:`hello_world` application for the MSP-EXP432P401R LaunchXL: .. zephyr-app-commands:: :zephyr-app: samples/hello_world :board: msp_exp432p401r_launchxl - :goals: build - -The resulting ``zephyr.elf`` binary in the build directory can be flashed onto -MSP-EXP432P401R LaunchXL using the command line utility mentioned below. - -Flashing -======== + :goals: flash -For Linux: ----------- +This will load the image into flash. -`UniFlash`_ command line utility is used to program the flash memory. Only -elf loading is currently supported. - -The following command will flash the ``zephyr.elf`` binary to the MSP-EXP432P401R LaunchXL board: +To see program output from UART0, connect a separate terminal window: .. code-block:: console - $ ./dslite.sh --config=MSP432P401R.ccxml zephyr.elf + % screen /dev/ttyACM0 115200 8N1 -.. note:: The ccxml configuration file is included in boards/arm/msp_exp432p401r_launchxl/support. +Then press the reset button (S3) on the board to run the program. Debugging ========= -MSP-EXP432P401R LaunchXL board supports debugging primarily using `CCS IDE`_. More information -on debugging using CCS can be found in CCS Debug Handbook. +To debug a previously flashed image, after resetting the board, use the 'debug' +build target: -Launchpad also supports debugging using GDB. See section 3.3 of GCC ARM Toolchain Guide. +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: msp_exp432p401r_launchxl + :maybe-skip-config: + :goals: debug References ********** @@ -114,3 +147,6 @@ TI MSP432 SDK: .. _CCS IDE: http://www.ti.com/tool/ccstudio + +.. _XDS-110 emulation package: + http://processors.wiki.ti.com/index.php/XDS_Emulation_Software_Package#XDS_Emulation_Software_.28emupack.29_Download diff --git a/boards/arm/msp_exp432p401r_launchxl/msp_exp432p401r_launchxl.yaml b/boards/arm/msp_exp432p401r_launchxl/msp_exp432p401r_launchxl.yaml index e1b1478370e..c60f1b65de8 100644 --- a/boards/arm/msp_exp432p401r_launchxl/msp_exp432p401r_launchxl.yaml +++ b/boards/arm/msp_exp432p401r_launchxl/msp_exp432p401r_launchxl.yaml @@ -8,3 +8,4 @@ toolchain: - xtools ram: 64 flash: 256 +vendor: ti diff --git a/boards/arm/msp_exp432p401r_launchxl/msp_exp432p401r_launchxl_defconfig b/boards/arm/msp_exp432p401r_launchxl/msp_exp432p401r_launchxl_defconfig index a71dce228eb..01559c8be94 100644 --- a/boards/arm/msp_exp432p401r_launchxl/msp_exp432p401r_launchxl_defconfig +++ b/boards/arm/msp_exp432p401r_launchxl/msp_exp432p401r_launchxl_defconfig @@ -3,6 +3,7 @@ CONFIG_BOARD_MSP_EXP432P401R_LAUNCHXL=y CONFIG_SOC_SERIES_MSP432P4XX=y CONFIG_SOC_MSP432P401R=y +CONFIG_BUILD_OUTPUT_HEX=y # Floating point options CONFIG_FPU=y diff --git a/boards/arm/msp_exp432p401r_launchxl/support/MSP432P401R.ccxml b/boards/arm/msp_exp432p401r_launchxl/support/MSP432P401R.ccxml deleted file mode 100644 index 331f741ae83..00000000000 --- a/boards/arm/msp_exp432p401r_launchxl/support/MSP432P401R.ccxml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/boards/arm/msp_exp432p401r_launchxl/support/openocd.cfg b/boards/arm/msp_exp432p401r_launchxl/support/openocd.cfg new file mode 100644 index 00000000000..d28491faa51 --- /dev/null +++ b/boards/arm/msp_exp432p401r_launchxl/support/openocd.cfg @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +source [find board/ti_msp432_launchpad.cfg] diff --git a/boards/arm/npcx4m8f_evb/Kconfig.board b/boards/arm/npcx4m8f_evb/Kconfig.board new file mode 100644 index 00000000000..093faa1cade --- /dev/null +++ b/boards/arm/npcx4m8f_evb/Kconfig.board @@ -0,0 +1,6 @@ +# Copyright (c) 2023 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_NPCX4M8F_EVB + bool "Nuvoton NPCX4M8F EVB Development board" + depends on SOC_NPCX4M8F diff --git a/boards/arm/npcx4m8f_evb/Kconfig.defconfig b/boards/arm/npcx4m8f_evb/Kconfig.defconfig new file mode 100644 index 00000000000..ae6ce213595 --- /dev/null +++ b/boards/arm/npcx4m8f_evb/Kconfig.defconfig @@ -0,0 +1,15 @@ +# Copyright (c) 2023 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_NPCX4M8F_EVB + +config BOARD + default "npcx4m8f_evb" + +endif # BOARD_NPCX4M8F_EVB + +config SYS_CLOCK_TICKS_PER_SEC + default 1000 + +config INPUT + default y if KSCAN diff --git a/boards/arm/npcx4m8f_evb/board.cmake b/boards/arm/npcx4m8f_evb/board.cmake new file mode 100644 index 00000000000..51e7fd4c66f --- /dev/null +++ b/boards/arm/npcx4m8f_evb/board.cmake @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd --cmd-load "npcx_write_image") +board_runner_args(openocd --cmd-verify "npcx_verify_image") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/arm/npcx4m8f_evb/doc/index.rst b/boards/arm/npcx4m8f_evb/doc/index.rst new file mode 100644 index 00000000000..a73d65d33da --- /dev/null +++ b/boards/arm/npcx4m8f_evb/doc/index.rst @@ -0,0 +1,131 @@ +.. _npcx4m8f_evb: + +Nuvoton NPCX4M8F_EVB +#################### + +Overview +******** + +The NPCX4M8F_EVB kit is a development platform to evaluate the +Nuvoton NPCX4 series microcontrollers. This board needs to be mated with +part number NPCX498F. + +.. image:: npcx4m8f_evb.jpg + :align: center + :alt: NPCX4M8F Evaluation Board + +Hardware +******** + +- ARM Cortex-M4F Processor +- 512 KB RAM and 64 KB boot ROM +- ADC & GPIO headers +- UART0 and UART1 +- FAN PWM interface +- Jtag interface +- Intel Modular Embedded Controller Card (MECC) headers + +Supported Features +================== + +The following features are supported: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| ADC | on-chip | adc controller | ++-----------+------------+-------------------------------------+ +| CLOCK | on-chip | reset and clock control | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c port/controller | ++-----------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++-----------+------------+-------------------------------------+ +| PM | on-chip | power management | ++-----------+------------+-------------------------------------+ +| PSL | on-chip | power switch logic | ++-----------+------------+-------------------------------------+ +| PWM | on-chip | pulse width modulator | ++-----------+------------+-------------------------------------+ +| TACH | on-chip | tachometer sensor | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ +| WDT | on-chip | watchdog | ++-----------+------------+-------------------------------------+ + +Other hardware features are not currently supported by Zephyr (at the moment) + +The default configuration can be found in the defconfig file: +``boards/arm/npcx4m8f_evb/npcx4m8f_evb_defconfig`` + + +Connections and IOs +=================== + +Nuvoton to provide the schematic for this board. + +System Clock +============ + +The NPCX4M8F MCU is configured to use the 120Mhz internal oscillator with the +on-chip PLL to generate a resulting EC clock rate of 15 MHz. See Processor clock +control register (chapter 4 in user manual) + +Serial Port +=========== + +UART1 is configured for serial logs. + +Programming and Debugging +************************* + +This board comes with a Cortex ETM port which facilitates tracing and debugging +using a single physical connection. In addition, it comes with sockets for +JTAG-only sessions. + +Flashing +======== + +If the correct headers are installed, this board supports both J-TAG and also +the ChromiumOS servo. + +To flash using Servo V2, μServo, or Servo V4 (CCD), see the +`Chromium EC Flashing Documentation`_ for more information. + +To flash with J-TAG, install the drivers for your programmer, for example: +SEGGER J-link's drivers are at https://www.segger.com/downloads/jlink/ + +The openocd from Zephyr SDK 0.16.1 doesn't include npcx4 support, so build openocd from source.:: + + sudo apt-get install libftdi-dev libusb-1.0.0-dev + git clone https://git.code.sf.net/p/openocd/code ~/openocd + cd ~/openocd + ./bootstrap + ./configure --enable-jlink --enable-ftdi + make clean + make + sudo make install + +Build and flash the blinky sample.:: + + west build -t clean && \ + west build -c -p auto -b npcx4m8f_evb samples/basic/blinky && \ + west flash --openocd /usr/local/bin/openocd + +Debugging +========= + +Use JTAG/SWD with a J-Link + +References +********** +.. target-notes:: + +.. _Chromium EC Flashing Documentation: + https://chromium.googlesource.com/chromiumos/platform/ec#Flashing-via-the-servo-debug-board diff --git a/boards/arm/npcx4m8f_evb/doc/npcx4m8f_evb.jpg b/boards/arm/npcx4m8f_evb/doc/npcx4m8f_evb.jpg new file mode 100644 index 00000000000..369dd8b0150 Binary files /dev/null and b/boards/arm/npcx4m8f_evb/doc/npcx4m8f_evb.jpg differ diff --git a/boards/arm/npcx4m8f_evb/npcx4m8f_evb-pinctrl.dtsi b/boards/arm/npcx4m8f_evb/npcx4m8f_evb-pinctrl.dtsi new file mode 100644 index 00000000000..ab9df9c474a --- /dev/null +++ b/boards/arm/npcx4m8f_evb/npcx4m8f_evb-pinctrl.dtsi @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2023 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&i2c0_0_sda_scl_gpb4_b5 { + bias-pull-up; /* Enable internal pull-up for i2c0_0 */ + pinmux-locked; /* Lock pinmuxing */ +}; + +&pwm6_gpc0 { + drive-open-drain; +}; diff --git a/boards/arm/npcx4m8f_evb/npcx4m8f_evb.dts b/boards/arm/npcx4m8f_evb/npcx4m8f_evb.dts new file mode 100644 index 00000000000..a34002e8bc8 --- /dev/null +++ b/boards/arm/npcx4m8f_evb/npcx4m8f_evb.dts @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2023 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include "npcx4m8f_evb-pinctrl.dtsi" + +/ { + model = "Nuvoton NPCX4M8F evaluation board"; + + chosen { + zephyr,sram = &sram0; + zephyr,console = &uart1; + zephyr,flash = &flash0; + zephyr,keyboard-scan = &kscan_input; + }; + + aliases { + pwm-led0 = &pwm_led0_green; + led0 = &gpio_led_red; + pwm-0 = &pwm6; + i2c-0 = &i2c0_0; + watchdog0 = &twd0; + peci-0 = &peci0; + spi-flash0 = &int_flash; + kscan0 = &kscan_input; + }; + + leds-pwm { + compatible = "pwm-leds"; + pwm_led0_green: pwm_led_0 { + pwms = <&pwm6 0 PWM_MSEC(20) PWM_POLARITY_INVERTED>; + label = "User D7 green"; + }; + }; + + leds-gpio { + compatible = "gpio-leds"; + gpio_led_red: led_0 { + gpios = <&gpio6 0 GPIO_ACTIVE_LOW>; + label = "User D8 red"; + }; + }; +}; + +/* Overwrite default device properties with overlays in board dt file here. */ +&uart1 { + status = "okay"; + current-speed = <115200>; + /* Use UART1_SL2 ie. PIN64.65 */ + pinctrl-0 = <&uart1_2_sin_gp64 &uart1_2_sout_gp65>; + pinctrl-names = "default"; +}; + +&pwm6 { + status = "okay"; + pinctrl-0 = <&pwm6_gpc0>; + pinctrl-names = "default"; +}; + +&adc0 { + status = "okay"; + /* Use adc0 channel 0 and 2 for 'adc_api' driver tests */ + pinctrl-0 = <&adc0_chan0_gp45 &adc0_chan2_gp43>; + pinctrl-names = "default"; +}; + +&espi0 { + status = "okay"; + pinctrl-0 = <&espi_lpc_gp46_47_51_52_53_54_55_57>; + pinctrl-names = "default"; +}; + +&i2c0_0 { + status = "okay"; + pinctrl-0 = <&i2c0_0_sda_scl_gpb4_b5>; + pinctrl-names = "default"; + clock-frequency = ; +}; + +&i2c_ctrl0 { + status = "okay"; +}; + +&tach1 { + status = "okay"; + pinctrl-0 = <&ta1_1_in_gp40>; + pinctrl-names = "default"; + port = ; + sample-clk = ; + pulses-per-round = <1>; +}; + +&peci0 { + status = "okay"; + pinctrl-0 = <&peci_dat_gp81>; + pinctrl-names = "default"; +}; + +&kbd { + /* Demonstrate a 13 x 8 keyboard matrix on evb */ + pinctrl-0 = <&ksi0_gp31 &ksi1_gp30 &ksi2_gp27 &ksi3_gp26 + &ksi4_gp25 &ksi5_gp24 &ksi6_gp23 &ksi7_gp22 + &kso00_gp21 &kso01_gp20 &kso02_gp17 &kso03_gp16 + &kso04_gp15 &kso05_gp14 &kso06_gp13 &kso07_gp12 + &kso08_gp11 &kso09_gp10 &kso10_gp07 &kso11_gp06 + &kso12_gp05>; + pinctrl-names = "default"; + row-size = <8>; + col-size = <13>; + status = "okay"; + + kscan_input: kscan-input { + compatible = "zephyr,kscan-input"; + }; +}; diff --git a/boards/arm/npcx4m8f_evb/npcx4m8f_evb.yaml b/boards/arm/npcx4m8f_evb/npcx4m8f_evb.yaml new file mode 100644 index 00000000000..9e225f6163c --- /dev/null +++ b/boards/arm/npcx4m8f_evb/npcx4m8f_evb.yaml @@ -0,0 +1,26 @@ +# +# Copyright (c) 2023 Nuvoton Technology Corporation. +# +# SPDX-License-Identifier: Apache-2.0 +# + +identifier: npcx4m8f_evb +name: Nuvoton NPCX4M8F EVB +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb +ram: 114 +flash: 384 +supported: + - adc + - clock + - gpio + - i2c + - pm + - pwm + - psl + - tach + - uart + - watchdog diff --git a/boards/arm/npcx4m8f_evb/npcx4m8f_evb_defconfig b/boards/arm/npcx4m8f_evb/npcx4m8f_evb_defconfig new file mode 100644 index 00000000000..4ec779de482 --- /dev/null +++ b/boards/arm/npcx4m8f_evb/npcx4m8f_evb_defconfig @@ -0,0 +1,38 @@ +# +# Copyright (c) 2023 Nuvoton Technology Corporation. +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_SOC_NPCX4M8F=y +CONFIG_SOC_SERIES_NPCX4=y +CONFIG_BOARD_NPCX4M8F_EVB=y + +# Enable NPCX firmware header +CONFIG_NPCX_HEADER=y +CONFIG_NPCX_IMAGE_OUTPUT_HEX=y +CONFIG_NPCX_HEADER_SPI_MAX_CLOCK_50=y +CONFIG_NPCX_HEADER_SPI_READ_MODE_DUAL=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Clock configuration +CONFIG_CLOCK_CONTROL=y + +# General Kernel Options +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=15000000 + +# UART Driver +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y + +# GPIO Driver +CONFIG_GPIO=y + +# Pin Controller Driver +CONFIG_PINCTRL=y + +# Console Driver +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y diff --git a/boards/arm/npcx4m8f_evb/support/openocd.cfg b/boards/arm/npcx4m8f_evb/support/openocd.cfg new file mode 100644 index 00000000000..924de78080f --- /dev/null +++ b/boards/arm/npcx4m8f_evb/support/openocd.cfg @@ -0,0 +1,15 @@ +# script for Nuvoton NPCX Cortex-M4 Series + +source [find interface/jlink.cfg] +transport select swd + +set FIUNAME npcx_v2.fiu +source [find target/npcx.cfg] + +proc npcx_write_image {target_image} { + flash write_image erase $target_image 0x64000000 ihex +} + +proc npcx_verify_image {target_image} { + verify_image $target_image 0x64000000 ihex +} diff --git a/boards/arm/npcx7m6fb_evb/doc/index.rst b/boards/arm/npcx7m6fb_evb/doc/index.rst index e3e855254d6..7222aac1ebb 100644 --- a/boards/arm/npcx7m6fb_evb/doc/index.rst +++ b/boards/arm/npcx7m6fb_evb/doc/index.rst @@ -79,10 +79,20 @@ JTAG only sessions. Flashing ======== -Build application as usual for the ``npcx7m6fb_evb`` board, and flash -using Servo V2, μServo, or Servo V4 (CCD). See the +If the correct IDC headers are installed, this board supports both J-TAG and +also the ChromiumOS servo. + +To flash using Servo V2, μServo, or Servo V4 (CCD), see the `Chromium EC Flashing Documentation`_ for more information. +To flash with J-TAG, install the drivers for your programmer, for example: +SEGGER J-link's drivers are at https://www.segger.com/downloads/jlink/ + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: npcx7m6fb_evb + :maybe-skip-config: + :goals: build flash Debugging ========= diff --git a/boards/arm/npcx9m6f_evb/doc/index.rst b/boards/arm/npcx9m6f_evb/doc/index.rst index e74685c965e..898f3051220 100644 --- a/boards/arm/npcx9m6f_evb/doc/index.rst +++ b/boards/arm/npcx9m6f_evb/doc/index.rst @@ -93,8 +93,8 @@ JTAG-only sessions. Flashing ======== -If the correct headers are installed, this board supports both J-TAG and also -the ChromiumOS servo. +If the correct IDC headers are installed, this board supports both J-TAG and +also the ChromiumOS servo. To flash using Servo V2, μServo, or Servo V4 (CCD), see the `Chromium EC Flashing Documentation`_ for more information. @@ -102,22 +102,11 @@ To flash using Servo V2, μServo, or Servo V4 (CCD), see the To flash with J-TAG, install the drivers for your programmer, for example: SEGGER J-link's drivers are at https://www.segger.com/downloads/jlink/ -The openocd from Zephyr SDK 0.14.2 doesn't include npcx support, so build openocd from source.:: - - sudo apt-get install libftdi-dev libusb-1.0.0-dev - git clone https://git.code.sf.net/p/openocd/code ~/openocd - cd ~/openocd - ./bootstrap - ./configure --enable-jlink --enable-ftdi - make clean - make - sudo make install - -Build and flash the blinky sample.:: - - west build -t clean && \ - west build -c -p auto -b npcx9m6f_evb samples/basic/blinky && \ - west flash --openocd /usr/local/bin/openocd +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: npcx9m6f_evb + :maybe-skip-config: + :goals: build flash Debugging ========= diff --git a/boards/arm/nrf21540dk_nrf52840/nrf21540dk_nrf52840.yaml b/boards/arm/nrf21540dk_nrf52840/nrf21540dk_nrf52840.yaml index a93e1ccb62a..985dba241e1 100644 --- a/boards/arm/nrf21540dk_nrf52840/nrf21540dk_nrf52840.yaml +++ b/boards/arm/nrf21540dk_nrf52840/nrf21540dk_nrf52840.yaml @@ -22,3 +22,4 @@ supported: - usb_device - watchdog - netif:openthread +vendor: nordic diff --git a/boards/arm/nrf21540dk_nrf52840/nrf21540dk_nrf52840_defconfig b/boards/arm/nrf21540dk_nrf52840/nrf21540dk_nrf52840_defconfig index af230adb18a..fecb5052471 100644 --- a/boards/arm/nrf21540dk_nrf52840/nrf21540dk_nrf52840_defconfig +++ b/boards/arm/nrf21540dk_nrf52840/nrf21540dk_nrf52840_defconfig @@ -22,5 +22,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf51_ble400/doc/index.rst b/boards/arm/nrf51_ble400/doc/index.rst index cfe3d8a547d..d746806faa1 100644 --- a/boards/arm/nrf51_ble400/doc/index.rst +++ b/boards/arm/nrf51_ble400/doc/index.rst @@ -199,10 +199,10 @@ Testing the LEDs and buttons in the nRF51 DK There are samples below that allow you to test that the buttons (switches) and LEDs on the board are working properly with Zephyr: -- :ref:`blinky-sample` -- :ref:`button-sample` -- :ref:`fade-led-sample` -- :ref:`96b_carbon_multi_thread_blinky` +- :zephyr:code-sample:`blinky` +- :zephyr:code-sample:`button` +- :zephyr:code-sample:`fade-led` +- :zephyr:code-sample:`multi-thread-blinky` You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in diff --git a/boards/arm/nrf51_ble400/nrf51_ble400.yaml b/boards/arm/nrf51_ble400/nrf51_ble400.yaml index 622c7d7d74a..93c73fcd84f 100644 --- a/boards/arm/nrf51_ble400/nrf51_ble400.yaml +++ b/boards/arm/nrf51_ble400/nrf51_ble400.yaml @@ -14,3 +14,4 @@ supported: testing: ignore_tags: - net +vendor: waveshare diff --git a/boards/arm/nrf51_ble400/nrf51_ble400_defconfig b/boards/arm/nrf51_ble400/nrf51_ble400_defconfig index 57332970318..34fd08c47d5 100644 --- a/boards/arm/nrf51_ble400/nrf51_ble400_defconfig +++ b/boards/arm/nrf51_ble400/nrf51_ble400_defconfig @@ -13,5 +13,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf51_blenano/nrf51_blenano_defconfig b/boards/arm/nrf51_blenano/nrf51_blenano_defconfig index e4a5441877a..7bd3f7c6736 100644 --- a/boards/arm/nrf51_blenano/nrf51_blenano_defconfig +++ b/boards/arm/nrf51_blenano/nrf51_blenano_defconfig @@ -13,5 +13,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf51_vbluno51/doc/index.rst b/boards/arm/nrf51_vbluno51/doc/index.rst index 4aa8a9532c2..e4f6b58a68a 100644 --- a/boards/arm/nrf51_vbluno51/doc/index.rst +++ b/boards/arm/nrf51_vbluno51/doc/index.rst @@ -106,7 +106,7 @@ The VBLUno51 board has on-board DAPLink (CMSIS-DAP) interface for flashing and d You do not need any other programming device. You only need to install pyOCD tool (https://pypi.python.org/pypi/pyOCD) -This tutorial uses the blinky application :ref:`blinky-sample`. +This tutorial uses the blinky application :zephyr:code-sample:`blinky`. See the :ref:`getting_started` for general information on setting up your development environment. Then build and flash the application in @@ -121,7 +121,7 @@ Debugging ========= You can debug an application in the usual way. Here is an example for the -:ref:`blinky-sample` application. +:zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -136,8 +136,8 @@ Testing the VBLUno51 with Zephyr: buttons, LEDs, UART, BLE components on the VBLUno51 board: * :ref:`hello_world` - * :ref:`blinky-sample` - * :ref:`button-sample` + * :zephyr:code-sample:`blinky` + * :zephyr:code-sample:`button` * :ref:`bluetooth-beacon-sample` * :ref:`peripheral_hr` diff --git a/boards/arm/nrf51_vbluno51/nrf51_vbluno51_defconfig b/boards/arm/nrf51_vbluno51/nrf51_vbluno51_defconfig index 9cdf638b99c..09836ecc779 100644 --- a/boards/arm/nrf51_vbluno51/nrf51_vbluno51_defconfig +++ b/boards/arm/nrf51_vbluno51/nrf51_vbluno51_defconfig @@ -13,5 +13,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf51dk_nrf51422/nrf51dk_nrf51422.yaml b/boards/arm/nrf51dk_nrf51422/nrf51dk_nrf51422.yaml index 1ccd377906f..8b521b57d90 100644 --- a/boards/arm/nrf51dk_nrf51422/nrf51dk_nrf51422.yaml +++ b/boards/arm/nrf51dk_nrf51422/nrf51dk_nrf51422.yaml @@ -21,3 +21,4 @@ supported: testing: ignore_tags: - net +vendor: nordic diff --git a/boards/arm/nrf51dk_nrf51422/nrf51dk_nrf51422_defconfig b/boards/arm/nrf51dk_nrf51422/nrf51dk_nrf51422_defconfig index 0aba32cb596..7cd29568889 100644 --- a/boards/arm/nrf51dk_nrf51422/nrf51dk_nrf51422_defconfig +++ b/boards/arm/nrf51dk_nrf51422/nrf51dk_nrf51422_defconfig @@ -13,5 +13,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf51dongle_nrf51422/doc/index.rst b/boards/arm/nrf51dongle_nrf51422/doc/index.rst index ba846747efd..1f73d1f9e08 100644 --- a/boards/arm/nrf51dongle_nrf51422/doc/index.rst +++ b/boards/arm/nrf51dongle_nrf51422/doc/index.rst @@ -132,7 +132,7 @@ Segger IC. Testing the LEDs on the nRF51 Dongle ************************************ -Build and flash the :ref:`blinky-sample` sample to test that the onboard LED +Build and flash the :zephyr:code-sample:`blinky` sample to test that the onboard LED is working properly with Zephyr. References diff --git a/boards/arm/nrf51dongle_nrf51422/nrf51dongle_nrf51422.yaml b/boards/arm/nrf51dongle_nrf51422/nrf51dongle_nrf51422.yaml index d0e29a7e3b5..906fce5febf 100644 --- a/boards/arm/nrf51dongle_nrf51422/nrf51dongle_nrf51422.yaml +++ b/boards/arm/nrf51dongle_nrf51422/nrf51dongle_nrf51422.yaml @@ -11,3 +11,4 @@ flash: 256 supported: - ble - nvs +vendor: nordic diff --git a/boards/arm/nrf51dongle_nrf51422/nrf51dongle_nrf51422_defconfig b/boards/arm/nrf51dongle_nrf51422/nrf51dongle_nrf51422_defconfig index dbe03eef66d..c937ab159c8 100644 --- a/boards/arm/nrf51dongle_nrf51422/nrf51dongle_nrf51422_defconfig +++ b/boards/arm/nrf51dongle_nrf51422/nrf51dongle_nrf51422_defconfig @@ -13,5 +13,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52832_mdk/nrf52832_mdk_defconfig b/boards/arm/nrf52832_mdk/nrf52832_mdk_defconfig index 8993b59f938..732b02a3610 100644 --- a/boards/arm/nrf52832_mdk/nrf52832_mdk_defconfig +++ b/boards/arm/nrf52832_mdk/nrf52832_mdk_defconfig @@ -16,5 +16,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52833dk_nrf52820/nrf52833dk_nrf52820.yaml b/boards/arm/nrf52833dk_nrf52820/nrf52833dk_nrf52820.yaml index 1c129df76c7..1e31da83439 100644 --- a/boards/arm/nrf52833dk_nrf52820/nrf52833dk_nrf52820.yaml +++ b/boards/arm/nrf52833dk_nrf52820/nrf52833dk_nrf52820.yaml @@ -15,3 +15,4 @@ supported: - watchdog - counter - netif:openthread +vendor: nordic diff --git a/boards/arm/nrf52833dk_nrf52820/nrf52833dk_nrf52820_defconfig b/boards/arm/nrf52833dk_nrf52820/nrf52833dk_nrf52820_defconfig index 9ef66860ab3..f953cca65f1 100644 --- a/boards/arm/nrf52833dk_nrf52820/nrf52833dk_nrf52820_defconfig +++ b/boards/arm/nrf52833dk_nrf52820/nrf52833dk_nrf52820_defconfig @@ -22,5 +22,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52833dk_nrf52833/doc/index.rst b/boards/arm/nrf52833dk_nrf52833/doc/index.rst index cb6b6fa4a51..126b1266d52 100644 --- a/boards/arm/nrf52833dk_nrf52833/doc/index.rst +++ b/boards/arm/nrf52833dk_nrf52833/doc/index.rst @@ -150,8 +150,8 @@ Testing the LEDs and buttons in the nRF52833 DK There are 2 samples that allow you to test that the buttons (switches) and LEDs on the board are working properly with Zephyr: -* :ref:`blinky-sample` -* :ref:`button-sample` +* :zephyr:code-sample:`blinky` +* :zephyr:code-sample:`button` You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in diff --git a/boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833.yaml b/boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833.yaml index 109024f1070..24cacd6ffa3 100644 --- a/boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833.yaml +++ b/boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833.yaml @@ -20,3 +20,4 @@ supported: - watchdog - counter - netif:openthread +vendor: nordic diff --git a/boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833_defconfig b/boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833_defconfig index 9cbee72b2e7..d4d96e6e395 100644 --- a/boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833_defconfig +++ b/boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833_defconfig @@ -22,5 +22,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52840_blip/doc/index.rst b/boards/arm/nrf52840_blip/doc/index.rst index d85fa3cf04c..e9dc8ad939b 100644 --- a/boards/arm/nrf52840_blip/doc/index.rst +++ b/boards/arm/nrf52840_blip/doc/index.rst @@ -175,8 +175,8 @@ Testing the LEDs and buttons in the nRF52840 PDK There are 2 samples that allow you to test that the buttons (switches) and LEDs on the board are working properly with Zephyr: -* :ref:`blinky-sample` -* :ref:`button-sample` +* :zephyr:code-sample:`blinky` +* :zephyr:code-sample:`button` You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in diff --git a/boards/arm/nrf52840_blip/nrf52840_blip.yaml b/boards/arm/nrf52840_blip/nrf52840_blip.yaml index 9c375172b54..694c2c251b8 100644 --- a/boards/arm/nrf52840_blip/nrf52840_blip.yaml +++ b/boards/arm/nrf52840_blip/nrf52840_blip.yaml @@ -11,3 +11,4 @@ supported: - i2c - usb_device - ble +vendor: electronutlabs diff --git a/boards/arm/nrf52840_blip/nrf52840_blip_defconfig b/boards/arm/nrf52840_blip/nrf52840_blip_defconfig index 811a88de939..526283ef3d4 100644 --- a/boards/arm/nrf52840_blip/nrf52840_blip_defconfig +++ b/boards/arm/nrf52840_blip/nrf52840_blip_defconfig @@ -16,5 +16,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52840_mdk/nrf52840_mdk.yaml b/boards/arm/nrf52840_mdk/nrf52840_mdk.yaml index 9a8e27235d6..c3be56dacaa 100644 --- a/boards/arm/nrf52840_mdk/nrf52840_mdk.yaml +++ b/boards/arm/nrf52840_mdk/nrf52840_mdk.yaml @@ -10,3 +10,4 @@ supported: - usb_device - ble - pwm +vendor: makerdiary diff --git a/boards/arm/nrf52840_mdk/nrf52840_mdk_defconfig b/boards/arm/nrf52840_mdk/nrf52840_mdk_defconfig index e4c79a2bf88..76c73a15a04 100644 --- a/boards/arm/nrf52840_mdk/nrf52840_mdk_defconfig +++ b/boards/arm/nrf52840_mdk/nrf52840_mdk_defconfig @@ -16,5 +16,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle_defconfig b/boards/arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle_defconfig index 8701863e99a..63decf69707 100644 --- a/boards/arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle_defconfig +++ b/boards/arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle_defconfig @@ -7,10 +7,13 @@ CONFIG_BOARD_NRF52840_MDK_USB_DONGLE=y # Enable MPU CONFIG_ARM_MPU=y +# Console +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y + # Enable hardware stack protection CONFIG_HW_STACK_PROTECTION=y # enable GPIO CONFIG_GPIO=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52840_papyr/nrf52840_papyr.yaml b/boards/arm/nrf52840_papyr/nrf52840_papyr.yaml index c5c4d62cccc..446c5205f96 100644 --- a/boards/arm/nrf52840_papyr/nrf52840_papyr.yaml +++ b/boards/arm/nrf52840_papyr/nrf52840_papyr.yaml @@ -12,3 +12,4 @@ supported: - ble - pwm - watchdog +vendor: electronutlabs diff --git a/boards/arm/nrf52840_papyr/nrf52840_papyr_defconfig b/boards/arm/nrf52840_papyr/nrf52840_papyr_defconfig index 4a5e737cd14..9d0226eed01 100644 --- a/boards/arm/nrf52840_papyr/nrf52840_papyr_defconfig +++ b/boards/arm/nrf52840_papyr/nrf52840_papyr_defconfig @@ -16,5 +16,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52840dk_nrf52811/nrf52840dk_nrf52811.yaml b/boards/arm/nrf52840dk_nrf52811/nrf52840dk_nrf52811.yaml index 9c1ac768c68..40d927db116 100644 --- a/boards/arm/nrf52840dk_nrf52811/nrf52840dk_nrf52811.yaml +++ b/boards/arm/nrf52840dk_nrf52811/nrf52840dk_nrf52811.yaml @@ -13,3 +13,4 @@ supported: - pwm - netif:openthread - gpio +vendor: nordic diff --git a/boards/arm/nrf52840dk_nrf52811/nrf52840dk_nrf52811_defconfig b/boards/arm/nrf52840dk_nrf52811/nrf52840dk_nrf52811_defconfig index 2c6b7f2fc82..97eaa9232e5 100644 --- a/boards/arm/nrf52840dk_nrf52811/nrf52840dk_nrf52811_defconfig +++ b/boards/arm/nrf52840dk_nrf52811/nrf52840dk_nrf52811_defconfig @@ -25,5 +25,3 @@ CONFIG_GPIO=y # Bluetooth not enabled by default on nRF52811 due to RAM limitations when # running the default set of kernel tests. # Enable this on your prj.conf to include Bluetooth support - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840.dts b/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840.dts index 96006ec4722..60c3ecf55a1 100644 --- a/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840.dts +++ b/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840.dts @@ -149,10 +149,18 @@ &gpio0 { status = "okay"; + gpio-reserved-ranges = <0 2>, <6 1>, <8 3>, <17 7>; + gpio-line-names = "XL1", "XL2", "AREF", "A0", "A1", "RTS", "TXD", + "CTS", "RXD", "NFC1", "NFC2", "BUTTON1", "BUTTON2", "LED1", + "LED2", "LED3", "LED4", "QSPI CS", "RESET", "QSPI CLK", + "QSPI DIO0", "QSPI DIO1", "QSPI DIO2", "QSPI DIO3","BUTTON3", + "BUTTON4", "SDA", "SCL", "A2", "A3", "A4", "A5"; }; &gpio1 { status = "okay"; + gpio-line-names = "", "D0", "D1", "D2", "D3", "D4", "D5", "D6", + "D7", "", "D8", "D9", "D10", "D11", "D12", "D13"; }; &uart0 { diff --git a/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840.yaml b/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840.yaml index fd739bf001a..00ee8701a97 100644 --- a/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840.yaml +++ b/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840.yaml @@ -25,3 +25,4 @@ supported: - usb_device - watchdog - netif:openthread +vendor: nordic diff --git a/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840_defconfig b/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840_defconfig index 9f1232a8f0a..107f9e00d59 100644 --- a/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840_defconfig +++ b/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840_defconfig @@ -22,5 +22,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52840dongle_nrf52840/Kconfig.defconfig b/boards/arm/nrf52840dongle_nrf52840/Kconfig.defconfig index 75a76b33293..76c7559be8d 100644 --- a/boards/arm/nrf52840dongle_nrf52840/Kconfig.defconfig +++ b/boards/arm/nrf52840dongle_nrf52840/Kconfig.defconfig @@ -33,6 +33,9 @@ config USB_DEVICE_STACK config USB_CDC_ACM default SERIAL +config CONSOLE + default y + config UART_CONSOLE default CONSOLE diff --git a/boards/arm/nrf52840dongle_nrf52840/doc/index.rst b/boards/arm/nrf52840dongle_nrf52840/doc/index.rst index 6a28927b188..6cfe7329d2c 100644 --- a/boards/arm/nrf52840dongle_nrf52840/doc/index.rst +++ b/boards/arm/nrf52840dongle_nrf52840/doc/index.rst @@ -140,7 +140,7 @@ device. Make sure ``nrfutil`` is installed before proceeding. The red LED should start a fade pattern, signalling the bootloader is running. -#. Compile a Zephyr application; we'll use :ref:`blinky `. +#. Compile a Zephyr application; we'll use :zephyr:code-sample:`blinky`. .. zephyr-app-commands:: :app: zephyr/samples/basic/blinky @@ -210,7 +210,7 @@ to the zephyr repository on your computer. nrfutil dfu usb-serial -pkg mcuboot.zip -p /dev/ttyACM0 You can now flash a Zephyr application to the board using MCUboot's serial -recovery mode. We'll use the :ref:`smp_svr_sample` since it's ready to be +recovery mode. We'll use the :zephyr:code-sample:`smp-svr` sample since it's ready to be compiled for chain-loading by MCUboot (and itself supports firmware updates over Bluetooth). @@ -298,7 +298,7 @@ flashed with an offset. Then build and flash applications as usual (see :ref:`build_an_application` and :ref:`application_run` for more details). -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -321,7 +321,7 @@ Testing the LEDs and buttons on the nRF52840 Dongle There are 2 samples that allow you to test that the buttons (switches) and LEDs on the board are working properly with Zephyr: -* :ref:`blinky-sample` +* :zephyr:code-sample:`blinky` You can build and program the examples to make sure Zephyr is running correctly on your board. diff --git a/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840.yaml b/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840.yaml index 1328f9be256..f0fb4cdafbf 100644 --- a/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840.yaml +++ b/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840.yaml @@ -19,3 +19,4 @@ supported: - counter - netif:openthread - gpio +vendor: nordic diff --git a/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840_defconfig b/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840_defconfig index c367a90d5ef..36998fc79a1 100644 --- a/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840_defconfig +++ b/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840_defconfig @@ -13,8 +13,6 @@ CONFIG_HW_STACK_PROTECTION=y # enable GPIO CONFIG_GPIO=y -CONFIG_PINCTRL=y - # Board Kconfig.defconfig enables USB CDC ACM and should disable USB remote # wakeup by default. It needs to be disabled here, because the USB nrfx # driver always overwrites option from Kconfig mentioned above with the diff --git a/boards/arm/nrf52_adafruit_feather/doc/index.rst b/boards/arm/nrf52_adafruit_feather/doc/index.rst index 38e6fd50f22..3555803b449 100644 --- a/boards/arm/nrf52_adafruit_feather/doc/index.rst +++ b/boards/arm/nrf52_adafruit_feather/doc/index.rst @@ -166,11 +166,11 @@ Testing the LEDs and buttons on the nRF52 Adafruit Feather There are several samples that allow you to test that the buttons (switches) and LEDs on the board are working properly with Zephyr: -- :ref:`blinky-sample` -- :ref:`button-sample` -- :ref:`fade-led-sample` -- :ref:`blink-led-sample` -- :ref:`96b_carbon_multi_thread_blinky` +- :zephyr:code-sample:`blinky` +- :zephyr:code-sample:`button` +- :zephyr:code-sample:`fade-led` +- :zephyr:code-sample:`pwm-blinky` +- :zephyr:code-sample:`multi-thread-blinky` You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in diff --git a/boards/arm/nrf52_adafruit_feather/nrf52_adafruit_feather.yaml b/boards/arm/nrf52_adafruit_feather/nrf52_adafruit_feather.yaml index 30a4788644a..0bfa59a6c1b 100644 --- a/boards/arm/nrf52_adafruit_feather/nrf52_adafruit_feather.yaml +++ b/boards/arm/nrf52_adafruit_feather/nrf52_adafruit_feather.yaml @@ -11,3 +11,4 @@ flash: 512 supported: - feather_serial - feather_i2c +vendor: adafruit diff --git a/boards/arm/nrf52_adafruit_feather/nrf52_adafruit_feather_defconfig b/boards/arm/nrf52_adafruit_feather/nrf52_adafruit_feather_defconfig index 19aaa3825d1..b434b22401d 100644 --- a/boards/arm/nrf52_adafruit_feather/nrf52_adafruit_feather_defconfig +++ b/boards/arm/nrf52_adafruit_feather/nrf52_adafruit_feather_defconfig @@ -16,5 +16,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52_blenano2/nrf52_blenano2_defconfig b/boards/arm/nrf52_blenano2/nrf52_blenano2_defconfig index 5c51849c0d9..318b8de6922 100644 --- a/boards/arm/nrf52_blenano2/nrf52_blenano2_defconfig +++ b/boards/arm/nrf52_blenano2/nrf52_blenano2_defconfig @@ -16,5 +16,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52_sparkfun/nrf52_sparkfun.yaml b/boards/arm/nrf52_sparkfun/nrf52_sparkfun.yaml index 81482c334ea..a377d060073 100644 --- a/boards/arm/nrf52_sparkfun/nrf52_sparkfun.yaml +++ b/boards/arm/nrf52_sparkfun/nrf52_sparkfun.yaml @@ -8,3 +8,4 @@ toolchain: - xtools ram: 64 flash: 512 +vendor: sparkfun diff --git a/boards/arm/nrf52_sparkfun/nrf52_sparkfun_defconfig b/boards/arm/nrf52_sparkfun/nrf52_sparkfun_defconfig index 2a21dc07192..3c893c08bc7 100644 --- a/boards/arm/nrf52_sparkfun/nrf52_sparkfun_defconfig +++ b/boards/arm/nrf52_sparkfun/nrf52_sparkfun_defconfig @@ -16,5 +16,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52_vbluno52/doc/index.rst b/boards/arm/nrf52_vbluno52/doc/index.rst index 38292648581..5342fdf81c4 100644 --- a/boards/arm/nrf52_vbluno52/doc/index.rst +++ b/boards/arm/nrf52_vbluno52/doc/index.rst @@ -101,7 +101,7 @@ Here are some sample applications that you can use to test different components on the VBLUno52 board: * :ref:`hello_world` -* :ref:`blinky-sample` -* :ref:`button-sample` +* :zephyr:code-sample:`blinky` +* :zephyr:code-sample:`button` * :ref:`bluetooth-beacon-sample` * :ref:`peripheral_hr` diff --git a/boards/arm/nrf52_vbluno52/nrf52_vbluno52_defconfig b/boards/arm/nrf52_vbluno52/nrf52_vbluno52_defconfig index fac5419e6f6..074355f29a1 100644 --- a/boards/arm/nrf52_vbluno52/nrf52_vbluno52_defconfig +++ b/boards/arm/nrf52_vbluno52/nrf52_vbluno52_defconfig @@ -16,5 +16,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52dk_nrf52805/nrf52dk_nrf52805.yaml b/boards/arm/nrf52dk_nrf52805/nrf52dk_nrf52805.yaml index c720c3da41b..3ebff8db1a4 100644 --- a/boards/arm/nrf52dk_nrf52805/nrf52dk_nrf52805.yaml +++ b/boards/arm/nrf52dk_nrf52805/nrf52dk_nrf52805.yaml @@ -11,3 +11,4 @@ supported: - gpio ram: 24 flash: 192 +vendor: nordic diff --git a/boards/arm/nrf52dk_nrf52805/nrf52dk_nrf52805_defconfig b/boards/arm/nrf52dk_nrf52805/nrf52dk_nrf52805_defconfig index 6e275e63f35..d1c9da8186c 100644 --- a/boards/arm/nrf52dk_nrf52805/nrf52dk_nrf52805_defconfig +++ b/boards/arm/nrf52dk_nrf52805/nrf52dk_nrf52805_defconfig @@ -22,5 +22,3 @@ CONFIG_UART_CONSOLE=y # Bluetooth not enabled by default on nRF52805 due to RAM limitations when # running the default set of kernel tests. - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52dk_nrf52810/nrf52dk_nrf52810.yaml b/boards/arm/nrf52dk_nrf52810/nrf52dk_nrf52810.yaml index 7ce6d3d6582..05e07eeba2a 100644 --- a/boards/arm/nrf52dk_nrf52810/nrf52dk_nrf52810.yaml +++ b/boards/arm/nrf52dk_nrf52810/nrf52dk_nrf52810.yaml @@ -11,3 +11,4 @@ supported: - gpio ram: 24 flash: 192 +vendor: nordic diff --git a/boards/arm/nrf52dk_nrf52810/nrf52dk_nrf52810_defconfig b/boards/arm/nrf52dk_nrf52810/nrf52dk_nrf52810_defconfig index 93706e89d0a..a90ea346ba0 100644 --- a/boards/arm/nrf52dk_nrf52810/nrf52dk_nrf52810_defconfig +++ b/boards/arm/nrf52dk_nrf52810/nrf52dk_nrf52810_defconfig @@ -23,5 +23,3 @@ CONFIG_UART_CONSOLE=y # Bluetooth not enabled by default on nRF52810 due to RAM limitations when # running the default set of kernel tests. # Enable this on your prj.conf to include Bluetooth support - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52dk_nrf52832/nrf52dk_nrf52832.yaml b/boards/arm/nrf52dk_nrf52832/nrf52dk_nrf52832.yaml index 5a5337412c6..209069df379 100644 --- a/boards/arm/nrf52dk_nrf52832/nrf52dk_nrf52832.yaml +++ b/boards/arm/nrf52dk_nrf52832/nrf52dk_nrf52832.yaml @@ -20,3 +20,4 @@ supported: - pwm - spi - watchdog +vendor: nordic diff --git a/boards/arm/nrf52dk_nrf52832/nrf52dk_nrf52832_defconfig b/boards/arm/nrf52dk_nrf52832/nrf52dk_nrf52832_defconfig index 23e1f4c249a..1f1eccdbec2 100644 --- a/boards/arm/nrf52dk_nrf52832/nrf52dk_nrf52832_defconfig +++ b/boards/arm/nrf52dk_nrf52832/nrf52dk_nrf52832_defconfig @@ -22,5 +22,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf5340_audio_dk_nrf5340/Kconfig b/boards/arm/nrf5340_audio_dk_nrf5340/Kconfig index fc237786896..00e48c60542 100644 --- a/boards/arm/nrf5340_audio_dk_nrf5340/Kconfig +++ b/boards/arm/nrf5340_audio_dk_nrf5340/Kconfig @@ -43,7 +43,7 @@ config DOMAIN_CPUNET_BOARD help The board which will be used for CPUNET domain when creating a multi image application where one or more images should be located on - another board. For example hci_rpmsg on the nRF5340_cpunet for + another board. For example hci_ipc on the nRF5340_cpunet for Bluetooth applications. endif # BOARD_NRF5340_AUDIO_DK_NRF5340_CPUAPP || BOARD_NRF5340_AUDIO_DK_NRF5340_CPUAPP_NS diff --git a/boards/arm/nrf5340_audio_dk_nrf5340/Kconfig.defconfig b/boards/arm/nrf5340_audio_dk_nrf5340/Kconfig.defconfig index 87a9a2175a8..eaa56252095 100644 --- a/boards/arm/nrf5340_audio_dk_nrf5340/Kconfig.defconfig +++ b/boards/arm/nrf5340_audio_dk_nrf5340/Kconfig.defconfig @@ -70,11 +70,11 @@ config MBOX_NRFX_IPC if BOARD_NRF5340_AUDIO_DK_NRF5340_CPUAPP || BOARD_NRF5340_AUDIO_DK_NRF5340_CPUAPP_NS choice BT_HCI_BUS_TYPE - default BT_RPMSG if BT + default BT_HCI_IPC if BT endchoice config HEAP_MEM_POOL_SIZE - default 4096 if BT_RPMSG + default 4096 if BT_HCI_IPC endif # BOARD_NRF5340_AUDIO_DK_NRF5340_CPUAPP || BOARD_NRF5340_AUDIO_DK_NRF5340_CPUAPP_NS diff --git a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp.yaml b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp.yaml index 5d752b69566..d5598ed9efc 100644 --- a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp.yaml +++ b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp.yaml @@ -17,3 +17,4 @@ supported: - watchdog - usb_cdc - usb_device +vendor: nordic diff --git a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi index df028fb75a2..132687888b2 100644 --- a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi +++ b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi @@ -13,7 +13,7 @@ zephyr,uart-mcumgr = &uart0; zephyr,bt-mon-uart = &uart0; zephyr,bt-c2h-uart = &uart0; - zephyr,bt-hci-rpmsg-ipc = &ipc0; + zephyr,bt-hci-ipc = &ipc0; watchdog0 = &wdt0; }; diff --git a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_defconfig b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_defconfig index d1b5f551c9b..2e7ac0ea3cc 100644 --- a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_defconfig +++ b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_defconfig @@ -18,6 +18,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -CONFIG_PINCTRL=y - CONFIG_REGULATOR=y diff --git a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_ns.yaml b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_ns.yaml index a094083158b..7b670992a87 100644 --- a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_ns.yaml +++ b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_ns.yaml @@ -16,3 +16,4 @@ supported: - watchdog - usb_cdc - usb_device +vendor: nordic diff --git a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_ns_defconfig b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_ns_defconfig index f0d723ad450..425ae718426 100644 --- a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_ns_defconfig +++ b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_ns_defconfig @@ -19,6 +19,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -CONFIG_PINCTRL=y - CONFIG_REGULATOR=y diff --git a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpunet.dts b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpunet.dts index 11244f82c5c..16aa4179fa9 100644 --- a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpunet.dts +++ b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpunet.dts @@ -18,7 +18,7 @@ zephyr,uart-mcumgr = &uart0; zephyr,bt-mon-uart = &uart0; zephyr,bt-c2h-uart = &uart0; - zephyr,bt-hci-rpmsg-ipc = &ipc0; + zephyr,bt-hci-ipc = &ipc0; zephyr,sram = &sram1; zephyr,flash = &flash1; zephyr,code-partition = &slot0_partition; diff --git a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpunet.yaml b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpunet.yaml index 7a28066f0a1..28ecb10a8b5 100644 --- a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpunet.yaml +++ b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpunet.yaml @@ -10,3 +10,4 @@ ram: 64 flash: 256 supported: - watchdog +vendor: nordic diff --git a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpunet_defconfig b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpunet_defconfig index 0450bb97797..d0844088568 100644 --- a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpunet_defconfig +++ b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpunet_defconfig @@ -10,9 +10,6 @@ CONFIG_ARM_MPU=y # Enable hardware stack protection CONFIG_HW_STACK_PROTECTION=y -# Enable PINCTRL -CONFIG_PINCTRL=y - # enable GPIO CONFIG_GPIO=y diff --git a/boards/arm/nrf5340dk_nrf5340/Kconfig b/boards/arm/nrf5340dk_nrf5340/Kconfig index 85190d7c890..518328e57e8 100644 --- a/boards/arm/nrf5340dk_nrf5340/Kconfig +++ b/boards/arm/nrf5340dk_nrf5340/Kconfig @@ -43,7 +43,7 @@ config DOMAIN_CPUNET_BOARD help The board which will be used for CPUNET domain when creating a multi image application where one or more images should be located on - another board. For example hci_rpmsg on the nRF5340_cpunet for + another board. For example hci_ipc on the nRF5340_cpunet for Bluetooth applications. endif # BOARD_NRF5340DK_NRF5340_CPUAPP || BOARD_NRF5340DK_NRF5340_CPUAPP_NS diff --git a/boards/arm/nrf5340dk_nrf5340/Kconfig.defconfig b/boards/arm/nrf5340dk_nrf5340/Kconfig.defconfig index 09ebfbf50ba..9006846dccb 100644 --- a/boards/arm/nrf5340dk_nrf5340/Kconfig.defconfig +++ b/boards/arm/nrf5340dk_nrf5340/Kconfig.defconfig @@ -67,11 +67,11 @@ config MBOX_NRFX_IPC if BOARD_NRF5340DK_NRF5340_CPUAPP || BOARD_NRF5340DK_NRF5340_CPUAPP_NS choice BT_HCI_BUS_TYPE - default BT_RPMSG if BT + default BT_HCI_IPC if BT endchoice config HEAP_MEM_POOL_SIZE - default 4096 if BT_RPMSG + default 4096 if BT_HCI_IPC endif # BOARD_NRF5340DK_NRF5340_CPUAPP || BOARD_NRF5340DK_NRF5340_CPUAPP_NS diff --git a/boards/arm/nrf5340dk_nrf5340/doc/index.rst b/boards/arm/nrf5340dk_nrf5340/doc/index.rst index 196759af686..984090f3879 100644 --- a/boards/arm/nrf5340dk_nrf5340/doc/index.rst +++ b/boards/arm/nrf5340dk_nrf5340/doc/index.rst @@ -310,8 +310,8 @@ Testing the LEDs and buttons in the nRF5340 DK There are 2 samples that allow you to test that the buttons (switches) and LEDs on the board are working properly with Zephyr: -* :ref:`blinky-sample` -* :ref:`button-sample` +* :zephyr:code-sample:`blinky` +* :zephyr:code-sample:`button` You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in diff --git a/boards/arm/nrf5340dk_nrf5340/nrf5340_cpuapp_common.dtsi b/boards/arm/nrf5340dk_nrf5340/nrf5340_cpuapp_common.dtsi index e3029b45df3..70ba3252450 100644 --- a/boards/arm/nrf5340dk_nrf5340/nrf5340_cpuapp_common.dtsi +++ b/boards/arm/nrf5340dk_nrf5340/nrf5340_cpuapp_common.dtsi @@ -14,7 +14,7 @@ zephyr,uart-mcumgr = &uart0; zephyr,bt-mon-uart = &uart0; zephyr,bt-c2h-uart = &uart0; - zephyr,bt-hci-rpmsg-ipc = &ipc0; + zephyr,bt-hci-ipc = &ipc0; nordic,802154-spinel-ipc = &ipc0; zephyr,ieee802154 = &ieee802154; }; diff --git a/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpuapp.yaml b/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpuapp.yaml index d4f9717fe97..545a41e9cd6 100644 --- a/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpuapp.yaml +++ b/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpuapp.yaml @@ -18,3 +18,4 @@ supported: - usb_device - netif:openthread - gpio +vendor: nordic diff --git a/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpuapp_defconfig b/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpuapp_defconfig index 419a8001670..22e8f52ff31 100644 --- a/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpuapp_defconfig +++ b/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpuapp_defconfig @@ -22,5 +22,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpuapp_ns.yaml b/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpuapp_ns.yaml index 71a8270225e..9519f50f3e9 100644 --- a/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpuapp_ns.yaml +++ b/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpuapp_ns.yaml @@ -16,3 +16,4 @@ supported: - usb_device - netif:openthread - gpio +vendor: nordic diff --git a/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpuapp_ns_defconfig b/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpuapp_ns_defconfig index 95172e7b2bf..0fe351e2780 100644 --- a/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpuapp_ns_defconfig +++ b/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpuapp_ns_defconfig @@ -25,5 +25,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpunet.dts b/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpunet.dts index f142744debd..80c3d183cd2 100644 --- a/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpunet.dts +++ b/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpunet.dts @@ -19,7 +19,7 @@ zephyr,uart-mcumgr = &uart0; zephyr,bt-mon-uart = &uart0; zephyr,bt-c2h-uart = &uart0; - zephyr,bt-hci-rpmsg-ipc = &ipc0; + zephyr,bt-hci-ipc = &ipc0; nordic,802154-spinel-ipc = &ipc0; zephyr,sram = &sram1; zephyr,flash = &flash1; diff --git a/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpunet.yaml b/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpunet.yaml index d6435438e82..2f92bb86440 100644 --- a/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpunet.yaml +++ b/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpunet.yaml @@ -11,3 +11,4 @@ flash: 256 supported: - watchdog - gpio +vendor: nordic diff --git a/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpunet_defconfig b/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpunet_defconfig index 2edb56e45ab..47f7b157d06 100644 --- a/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpunet_defconfig +++ b/boards/arm/nrf5340dk_nrf5340/nrf5340dk_nrf5340_cpunet_defconfig @@ -19,5 +19,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf9131ek_nrf9131/doc/index.rst b/boards/arm/nrf9131ek_nrf9131/doc/index.rst index ffb066d860d..a72cd1526e3 100644 --- a/boards/arm/nrf9131ek_nrf9131/doc/index.rst +++ b/boards/arm/nrf9131ek_nrf9131/doc/index.rst @@ -210,8 +210,8 @@ Testing the LEDs and buttons in the nRF9131 EK There are 2 samples that allow you to test that the button and LED on the board are working properly with Zephyr: -* :ref:`blinky-sample` -* :ref:`button-sample` +* :zephyr:code-sample:`blinky` +* :zephyr:code-sample:`button` You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in diff --git a/boards/arm/nrf9160_innblue21/doc/index.rst b/boards/arm/nrf9160_innblue21/doc/index.rst index 9ded085dc6f..c0f9e33cd75 100644 --- a/boards/arm/nrf9160_innblue21/doc/index.rst +++ b/boards/arm/nrf9160_innblue21/doc/index.rst @@ -95,7 +95,7 @@ Building Secure/Non-Secure Zephyr applications The process requires the following steps: 1. Build the Secure Zephyr application using ``-DBOARD=nrf9160_innblue21`` and - ``CONFIG_TRUSTED_EXECUTION_SECURE=y`` in the the application project configuration file. + ``CONFIG_TRUSTED_EXECUTION_SECURE=y`` in the application project configuration file. 2. Build the Non-Secure Zephyr application using ``-DBOARD=nrf9160_innblue21_ns``. 3. Merge the two binaries together. diff --git a/boards/arm/nrf9160_innblue21/nrf9160_innblue21_defconfig b/boards/arm/nrf9160_innblue21/nrf9160_innblue21_defconfig index 450db1d4d21..7c0e84c1abd 100644 --- a/boards/arm/nrf9160_innblue21/nrf9160_innblue21_defconfig +++ b/boards/arm/nrf9160_innblue21/nrf9160_innblue21_defconfig @@ -21,5 +21,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf9160_innblue21/nrf9160_innblue21_ns_defconfig b/boards/arm/nrf9160_innblue21/nrf9160_innblue21_ns_defconfig index ff57f4b7cdb..4f5410848bc 100644 --- a/boards/arm/nrf9160_innblue21/nrf9160_innblue21_ns_defconfig +++ b/boards/arm/nrf9160_innblue21/nrf9160_innblue21_ns_defconfig @@ -24,5 +24,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf9160_innblue22/doc/index.rst b/boards/arm/nrf9160_innblue22/doc/index.rst index 06f6b6326f8..0f2f83bcfe1 100644 --- a/boards/arm/nrf9160_innblue22/doc/index.rst +++ b/boards/arm/nrf9160_innblue22/doc/index.rst @@ -95,7 +95,7 @@ Building Secure/Non-Secure Zephyr applications The process requires the following steps: 1. Build the Secure Zephyr application using ``-DBOARD=nrf9160_innblue22`` and - ``CONFIG_TRUSTED_EXECUTION_SECURE=y`` in the the application project configuration file. + ``CONFIG_TRUSTED_EXECUTION_SECURE=y`` in the application project configuration file. 2. Build the Non-Secure Zephyr application using ``-DBOARD=nrf9160_innblue22_ns``. 3. Merge the two binaries together. diff --git a/boards/arm/nrf9160_innblue22/nrf9160_innblue22_defconfig b/boards/arm/nrf9160_innblue22/nrf9160_innblue22_defconfig index 73d88346580..ae9e2e2413e 100644 --- a/boards/arm/nrf9160_innblue22/nrf9160_innblue22_defconfig +++ b/boards/arm/nrf9160_innblue22/nrf9160_innblue22_defconfig @@ -21,5 +21,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf9160_innblue22/nrf9160_innblue22_ns_defconfig b/boards/arm/nrf9160_innblue22/nrf9160_innblue22_ns_defconfig index f75f894b1dd..e956d4d8b75 100644 --- a/boards/arm/nrf9160_innblue22/nrf9160_innblue22_ns_defconfig +++ b/boards/arm/nrf9160_innblue22/nrf9160_innblue22_ns_defconfig @@ -24,5 +24,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf9160dk_nrf52840/board.c b/boards/arm/nrf9160dk_nrf52840/board.c index cdf00f8f3dd..adf137df196 100644 --- a/boards/arm/nrf9160dk_nrf52840/board.c +++ b/boards/arm/nrf9160dk_nrf52840/board.c @@ -9,6 +9,7 @@ #include #include #include +#include #include LOG_MODULE_REGISTER(board_control, CONFIG_BOARD_NRF9160DK_LOG_LEVEL); diff --git a/boards/arm/nrf9160dk_nrf52840/doc/index.rst b/boards/arm/nrf9160dk_nrf52840/doc/index.rst index 752eee4c6fa..e16d6bc30e4 100644 --- a/boards/arm/nrf9160dk_nrf52840/doc/index.rst +++ b/boards/arm/nrf9160dk_nrf52840/doc/index.rst @@ -228,7 +228,7 @@ P0.17, P0.18, and P0.19 so that they are routed to nRF52840 pins P0.17, P0.20, and P0.15, respectively, add the following in the devicetree overlay in your application: -.. code-block:: none +.. code-block:: devicetree &nrf_interface_pins_0_2_routing { status = "okay"; @@ -237,7 +237,7 @@ application: And if you want to, for example, disable routing for the VCOM2 pins, add the following: -.. code-block:: none +.. code-block:: devicetree &vcom2_pins_routing { status = "disabled"; @@ -252,7 +252,7 @@ configure the signal routing between nRF9160 and nRF52840 on the nRF9160 DK. For example, to use ``uart1`` on both these chips for communication between them, add the following line in the overlays for applications on both sides: -.. code-block:: none +.. code-block:: devicetree #include diff --git a/boards/arm/nrf9160dk_nrf52840/nrf9160dk_nrf52840.yaml b/boards/arm/nrf9160dk_nrf52840/nrf9160dk_nrf52840.yaml index 4f411fb3782..4b9ffc34035 100644 --- a/boards/arm/nrf9160dk_nrf52840/nrf9160dk_nrf52840.yaml +++ b/boards/arm/nrf9160dk_nrf52840/nrf9160dk_nrf52840.yaml @@ -11,3 +11,4 @@ supported: - ble - netif:openthread - gpio +vendor: nordic diff --git a/boards/arm/nrf9160dk_nrf52840/nrf9160dk_nrf52840_defconfig b/boards/arm/nrf9160dk_nrf52840/nrf9160dk_nrf52840_defconfig index 073409dbba1..58f290ba271 100644 --- a/boards/arm/nrf9160dk_nrf52840/nrf9160dk_nrf52840_defconfig +++ b/boards/arm/nrf9160dk_nrf52840/nrf9160dk_nrf52840_defconfig @@ -16,5 +16,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf9160dk_nrf9160/doc/index.rst b/boards/arm/nrf9160dk_nrf9160/doc/index.rst index 7a8dbc42788..8deb4848255 100644 --- a/boards/arm/nrf9160dk_nrf9160/doc/index.rst +++ b/boards/arm/nrf9160dk_nrf9160/doc/index.rst @@ -245,8 +245,8 @@ Testing the LEDs and buttons in the nRF9160 DK There are 2 samples that allow you to test that the buttons (switches) and LEDs on the board are working properly with Zephyr: -* :ref:`blinky-sample` -* :ref:`button-sample` +* :zephyr:code-sample:`blinky` +* :zephyr:code-sample:`button` You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in diff --git a/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160.yaml b/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160.yaml index 92ef46bc05d..7a6d3362b23 100644 --- a/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160.yaml +++ b/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160.yaml @@ -19,3 +19,4 @@ supported: - spi - watchdog - counter +vendor: nordic diff --git a/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160_defconfig b/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160_defconfig index 7eadd01a2ab..aa61cc4ca35 100644 --- a/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160_defconfig +++ b/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160_defconfig @@ -22,5 +22,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160_ns.yaml b/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160_ns.yaml index 9eac3a41b30..c2a98dcad05 100644 --- a/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160_ns.yaml +++ b/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160_ns.yaml @@ -18,3 +18,4 @@ supported: - watchdog - netif:modem - gpio +vendor: nordic diff --git a/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160_ns_defconfig b/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160_ns_defconfig index 67f4522c30e..93343cc0264 100644 --- a/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160_ns_defconfig +++ b/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160_ns_defconfig @@ -25,5 +25,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf9161dk_nrf9161/doc/index.rst b/boards/arm/nrf9161dk_nrf9161/doc/index.rst index 835ba29c1de..559288b06aa 100644 --- a/boards/arm/nrf9161dk_nrf9161/doc/index.rst +++ b/boards/arm/nrf9161dk_nrf9161/doc/index.rst @@ -184,8 +184,8 @@ Testing the LEDs and buttons in the nRF9161 DK There are 2 samples that allow you to test that the buttons (switches) and LEDs on the board are working properly with Zephyr: -* :ref:`blinky-sample` -* :ref:`button-sample` +* :zephyr:code-sample:`blinky` +* :zephyr:code-sample:`button` You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in diff --git a/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161.yaml b/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161.yaml index efca7888f56..af076428810 100644 --- a/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161.yaml +++ b/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161.yaml @@ -19,3 +19,4 @@ supported: - spi - watchdog - counter +vendor: nordic diff --git a/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_common.dtsi b/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_common.dtsi index a6aeccf34b9..8168a8317e4 100644 --- a/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_common.dtsi +++ b/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_common.dtsi @@ -230,16 +230,12 @@ arduino_spi: &spi3 { slot0_ns_partition: partition@50000 { label = "image-0-nonsecure"; }; - slot1_partition: partition@80000 { + slot1_partition: partition@85000 { label = "image-1"; }; - slot1_ns_partition: partition@c0000 { + slot1_ns_partition: partition@c5000 { label = "image-1-nonsecure"; }; - scratch_partition: partition@f0000 { - label = "image-scratch"; - reg = <0x000f0000 0xa000>; - }; storage_partition: partition@fa000 { label = "storage"; reg = <0x000fa000 0x00006000>; diff --git a/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_defconfig b/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_defconfig index d4db57f62b4..1e04a544d95 100644 --- a/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_defconfig +++ b/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_defconfig @@ -22,5 +22,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_ns.yaml b/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_ns.yaml index b0b16fc403a..2d2da2026f4 100644 --- a/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_ns.yaml +++ b/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_ns.yaml @@ -17,3 +17,4 @@ supported: - pwm - watchdog - netif:modem +vendor: nordic diff --git a/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_ns_defconfig b/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_ns_defconfig index f2d7f04470c..97649b3d4d8 100644 --- a/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_ns_defconfig +++ b/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_ns_defconfig @@ -25,5 +25,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_partition_conf.dtsi b/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_partition_conf.dtsi index 80b4c5f6b3a..9e378cb94e0 100644 --- a/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_partition_conf.dtsi +++ b/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_partition_conf.dtsi @@ -26,15 +26,15 @@ }; &slot0_ns_partition { - reg = <0x00050000 0x30000>; + reg = <0x00050000 0x35000>; }; &slot1_partition { - reg = <0x00080000 0x40000>; + reg = <0x00085000 0x40000>; }; &slot1_ns_partition { - reg = <0x000c0000 0x30000>; + reg = <0x000c5000 0x35000>; }; /* Default SRAM planning when building for nRF9161 with diff --git a/boards/arm/nucleo_c031c6/doc/index.rst b/boards/arm/nucleo_c031c6/doc/index.rst index 292f7defcbf..fcf134f497e 100644 --- a/boards/arm/nucleo_c031c6/doc/index.rst +++ b/boards/arm/nucleo_c031c6/doc/index.rst @@ -127,7 +127,7 @@ Nucleo C031C6 board includes an ST-LINK/V2-1 embedded debug tool interface. Flashing an application to Nucleo C031C6 ---------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -142,7 +142,7 @@ References .. target-notes:: .. _Nucleo C031C6 website: - http://www.st.com/en/evaluation-tools/nucleo-c031c6.html + https://www.st.com/en/evaluation-tools/nucleo-c031c6.html .. _STM32C0x1 reference manual: https://www.st.com/resource/en/reference_manual/rm0490-stm32c0x1-advanced-armbased-64bit-mcus-stmicroelectronics.pdf diff --git a/boards/arm/nucleo_c031c6/nucleo_c031c6.yaml b/boards/arm/nucleo_c031c6/nucleo_c031c6.yaml index d7fff9f984e..c4766287cc5 100644 --- a/boards/arm/nucleo_c031c6/nucleo_c031c6.yaml +++ b/boards/arm/nucleo_c031c6/nucleo_c031c6.yaml @@ -16,3 +16,4 @@ supported: - dma ram: 12 flash: 32 +vendor: st diff --git a/boards/arm/nucleo_f030r8/doc/index.rst b/boards/arm/nucleo_f030r8/doc/index.rst index c1f6eb023ce..821470b20c0 100644 --- a/boards/arm/nucleo_f030r8/doc/index.rst +++ b/boards/arm/nucleo_f030r8/doc/index.rst @@ -149,7 +149,7 @@ This interface is supported by the openocd version included in the Zephyr SDK. Flashing an application to Nucleo F030R8 ---------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -169,7 +169,7 @@ Debugging ========= You can debug an application in the usual way. Here is an example for the -:ref:`blinky-sample` application. +:zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/nucleo_f030r8/nucleo_f030r8.yaml b/boards/arm/nucleo_f030r8/nucleo_f030r8.yaml index 2d348327740..814f2a7fc1b 100644 --- a/boards/arm/nucleo_f030r8/nucleo_f030r8.yaml +++ b/boards/arm/nucleo_f030r8/nucleo_f030r8.yaml @@ -21,3 +21,4 @@ testing: ignore_tags: - net - bluetooth +vendor: st diff --git a/boards/arm/nucleo_f031k6/doc/index.rst b/boards/arm/nucleo_f031k6/doc/index.rst index baff6aadc42..b7adddf6509 100644 --- a/boards/arm/nucleo_f031k6/doc/index.rst +++ b/boards/arm/nucleo_f031k6/doc/index.rst @@ -116,7 +116,7 @@ This interface is supported by the openocd version included in the Zephyr SDK. Flashing an application to Nucleo F030R8 ---------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -129,7 +129,7 @@ Debugging ========= You can debug an application in the usual way. Here is an example for the -:ref:`blinky-sample` application. +:zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/nucleo_f042k6/doc/index.rst b/boards/arm/nucleo_f042k6/doc/index.rst index bbae06bde44..a9676350eb4 100644 --- a/boards/arm/nucleo_f042k6/doc/index.rst +++ b/boards/arm/nucleo_f042k6/doc/index.rst @@ -116,7 +116,7 @@ This interface is supported by the openocd version included in the Zephyr SDK. Flashing an application to Nucleo F042K6 ---------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -129,7 +129,7 @@ Debugging ========= You can debug an application in the usual way. Here is an example for the -:ref:`blinky-sample` application. +:zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/nucleo_f070rb/doc/index.rst b/boards/arm/nucleo_f070rb/doc/index.rst index d609c743919..5d7e214bd1b 100644 --- a/boards/arm/nucleo_f070rb/doc/index.rst +++ b/boards/arm/nucleo_f070rb/doc/index.rst @@ -144,7 +144,7 @@ This interface is supported by the openocd version included in the Zephyr SDK. Flashing an application to Nucleo F070RB ---------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -171,10 +171,10 @@ References .. target-notes:: .. _Nucleo F070RB website: - http://www.st.com/en/evaluation-tools/nucleo-f070rb.html + https://www.st.com/en/evaluation-tools/nucleo-f070rb.html .. _STM32F070 reference manual: - http://www.st.com/resource/en/reference_manual/dm00031936.pdf + https://www.st.com/resource/en/reference_manual/dm00031936.pdf .. _STM32 Nucleo-64 board User Manual: - http://www.st.com/resource/en/user_manual/dm00105823.pdf + https://www.st.com/resource/en/user_manual/dm00105823.pdf diff --git a/boards/arm/nucleo_f070rb/nucleo_f070rb.yaml b/boards/arm/nucleo_f070rb/nucleo_f070rb.yaml index 366bef569cc..60af06296a9 100644 --- a/boards/arm/nucleo_f070rb/nucleo_f070rb.yaml +++ b/boards/arm/nucleo_f070rb/nucleo_f070rb.yaml @@ -22,3 +22,4 @@ testing: ignore_tags: - net - bluetooth +vendor: st diff --git a/boards/arm/nucleo_f091rc/doc/index.rst b/boards/arm/nucleo_f091rc/doc/index.rst index 136b935790f..f1f0df58e10 100644 --- a/boards/arm/nucleo_f091rc/doc/index.rst +++ b/boards/arm/nucleo_f091rc/doc/index.rst @@ -98,6 +98,8 @@ The Zephyr nucleo_f091rc board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | SPI | on-chip | SPI controller | +-----------+------------+-------------------------------------+ +| CAN | on-chip | CAN controller | ++-----------+------------+-------------------------------------+ | ADC | on-chip | ADC controller | +-----------+------------+-------------------------------------+ | DAC | on-chip | DAC controller | @@ -132,7 +134,8 @@ Default Zephyr Peripheral Mapping: - UART_1 TX/RX : PB6/PB7 - UART_2 TX/RX : PA2/PA3 (ST-Link Virtual COM Port) - I2C1 SCL/SDA : PB8/PB9 (Arduino I2C) -- I2C2 SCL/SDA : PA11/PA12 +- I2C2 SCL/SDA : PA11/PA12 (disabled by default, uses same pins as CAN) +- CAN RX/TX : PA11/PA12 - SPI1 SCK/MISO/MOSI : PA5/PA6/PA7 (Arduino SPI) - SPI2 SCK/MISO/MOSI : PB13/PB14/PB15 - USER_PB : PC13 @@ -158,7 +161,7 @@ This interface is supported by the openocd version included in the Zephyr SDK. Flashing an application to Nucleo F091RC ---------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -185,10 +188,10 @@ References .. target-notes:: .. _Nucleo F091RC website: - http://www.st.com/en/evaluation-tools/nucleo-f091rc.html + https://www.st.com/en/evaluation-tools/nucleo-f091rc.html .. _STM32F091 reference manual: - http://www.st.com/resource/en/reference_manual/dm00031936.pdf + https://www.st.com/resource/en/reference_manual/dm00031936.pdf .. _STM32 Nucleo-64 board User Manual: - http://www.st.com/resource/en/user_manual/dm00105823.pdf + https://www.st.com/resource/en/user_manual/dm00105823.pdf diff --git a/boards/arm/nucleo_f091rc/nucleo_f091rc.dts b/boards/arm/nucleo_f091rc/nucleo_f091rc.dts index b496e041c9a..b7a94b29e9e 100644 --- a/boards/arm/nucleo_f091rc/nucleo_f091rc.dts +++ b/boards/arm/nucleo_f091rc/nucleo_f091rc.dts @@ -20,6 +20,7 @@ zephyr,shell-uart = &usart2; zephyr,sram = &sram0; zephyr,flash = &flash0; + zephyr,canbus = &can1; }; leds: leds { @@ -105,12 +106,20 @@ }; &i2c2 { + /* Pin conflict with can1. Enable only with can1 disabled. */ pinctrl-0 = <&i2c2_scl_pa11 &i2c2_sda_pa12>; pinctrl-names = "default"; - status = "okay"; + status = "disabled"; clock-frequency = ; }; +&can1 { + pinctrl-0 = <&can_rx_pa11 &can_tx_pa12>; + pinctrl-names = "default"; + bus-speed = <125000>; + status = "okay"; +}; + &spi1 { pinctrl-0 = <&spi1_sck_pa5 &spi1_miso_pa6 &spi1_mosi_pa7>; pinctrl-names = "default"; diff --git a/boards/arm/nucleo_f091rc/nucleo_f091rc.yaml b/boards/arm/nucleo_f091rc/nucleo_f091rc.yaml index f749400b29c..c19aa47d955 100644 --- a/boards/arm/nucleo_f091rc/nucleo_f091rc.yaml +++ b/boards/arm/nucleo_f091rc/nucleo_f091rc.yaml @@ -22,7 +22,9 @@ supported: - dac - dma - pwm + - can testing: ignore_tags: - net - bluetooth +vendor: st diff --git a/boards/arm/nucleo_f103rb/doc/index.rst b/boards/arm/nucleo_f103rb/doc/index.rst index f704a4c0e49..b717c75b58a 100644 --- a/boards/arm/nucleo_f103rb/doc/index.rst +++ b/boards/arm/nucleo_f103rb/doc/index.rst @@ -151,7 +151,7 @@ This interface is supported by the openocd version included in the Zephyr SDK. Flashing an application to Nucleo F103RB ---------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -164,7 +164,7 @@ Debugging ========= You can debug an application in the usual way. Here is an example for the -:ref:`blinky-sample` application. +:zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -178,13 +178,13 @@ References .. target-notes:: .. _Nucleo F103RB website: - http://www.st.com/en/evaluation-tools/nucleo-f103rb.html + https://www.st.com/en/evaluation-tools/nucleo-f103rb.html .. _STM32F103 reference manual: - http://www.st.com/resource/en/reference_manual/cd00171190.pdf + https://www.st.com/resource/en/reference_manual/cd00171190.pdf .. _STM32F103 data sheet: - http://www.st.com/resource/en/datasheet/stm32f103rb.pdf + https://www.st.com/resource/en/datasheet/stm32f103rb.pdf .. _STM32 Nucleo-64 board User Manual: - http://www.st.com/resource/en/user_manual/dm00105823.pdf + https://www.st.com/resource/en/user_manual/dm00105823.pdf diff --git a/boards/arm/nucleo_f103rb/nucleo_f103rb.yaml b/boards/arm/nucleo_f103rb/nucleo_f103rb.yaml index a36b1373bcc..e231aa5e1d2 100644 --- a/boards/arm/nucleo_f103rb/nucleo_f103rb.yaml +++ b/boards/arm/nucleo_f103rb/nucleo_f103rb.yaml @@ -20,3 +20,4 @@ supported: - dma - nvs - counter +vendor: st diff --git a/boards/arm/nucleo_f207zg/doc/index.rst b/boards/arm/nucleo_f207zg/doc/index.rst index d4ae50dd7f6..e9696365b1c 100644 --- a/boards/arm/nucleo_f207zg/doc/index.rst +++ b/boards/arm/nucleo_f207zg/doc/index.rst @@ -194,13 +194,13 @@ This interface is supported by the openocd version included in Zephyr SDK. .. _Nucleo F207ZG website: - http://www.st.com/en/evaluation-tools/nucleo-f207zg.html + https://www.st.com/en/evaluation-tools/nucleo-f207zg.html .. _STM32 Nucleo-144 board User Manual: - http://www.st.com/resource/en/user_manual/dm00244518.pdf + https://www.st.com/resource/en/user_manual/dm00244518.pdf .. _STM32F207ZG on www.st.com: - http://www.st.com/en/microcontrollers/stm32f207zg.html + https://www.st.com/en/microcontrollers/stm32f207zg.html .. _STM32F207 reference manual: - http://www.st.com/resource/en/reference_manual/cd00225773.pdf + https://www.st.com/resource/en/reference_manual/cd00225773.pdf diff --git a/boards/arm/nucleo_f207zg/nucleo_f207zg.yaml b/boards/arm/nucleo_f207zg/nucleo_f207zg.yaml index 0856304d880..f89510912be 100644 --- a/boards/arm/nucleo_f207zg/nucleo_f207zg.yaml +++ b/boards/arm/nucleo_f207zg/nucleo_f207zg.yaml @@ -24,3 +24,4 @@ supported: - pwm - rng - dma +vendor: st diff --git a/boards/arm/nucleo_f302r8/doc/index.rst b/boards/arm/nucleo_f302r8/doc/index.rst index e774c8282c9..e554549a6fe 100644 --- a/boards/arm/nucleo_f302r8/doc/index.rst +++ b/boards/arm/nucleo_f302r8/doc/index.rst @@ -153,16 +153,16 @@ This interface is supported by the openocd version included in Zephyr SDK. .. _Nucleo F302R8 website: - http://www.st.com/en/evaluation-tools/nucleo-f302r8.html + https://www.st.com/en/evaluation-tools/nucleo-f302r8.html .. _STM32 Nucleo-64 board User Manual: - http://www.st.com/resource/en/user_manual/dm00105823.pdf + https://www.st.com/resource/en/user_manual/dm00105823.pdf .. _STM32F302R8 on www.st.com: - http://www.st.com/en/microcontrollers/stm32f302r8.html + https://www.st.com/en/microcontrollers/stm32f302r8.html .. _STM32F302R8 reference manual: - http://www.st.com/resource/en/reference_manual/dm00094349.pdf + https://www.st.com/resource/en/reference_manual/dm00094349.pdf .. _STM32F302R8 datasheet: - http://www.st.com/resource/en/datasheet/stm32f302r8.pdf + https://www.st.com/resource/en/datasheet/stm32f302r8.pdf diff --git a/boards/arm/nucleo_f302r8/nucleo_f302r8.yaml b/boards/arm/nucleo_f302r8/nucleo_f302r8.yaml index 85abfd6acd9..a5e3758b6a6 100644 --- a/boards/arm/nucleo_f302r8/nucleo_f302r8.yaml +++ b/boards/arm/nucleo_f302r8/nucleo_f302r8.yaml @@ -18,3 +18,4 @@ supported: - pwm - counter - adc +vendor: st diff --git a/boards/arm/nucleo_f303k8/doc/index.rst b/boards/arm/nucleo_f303k8/doc/index.rst index 78cf267a1be..5aab3540663 100644 --- a/boards/arm/nucleo_f303k8/doc/index.rst +++ b/boards/arm/nucleo_f303k8/doc/index.rst @@ -144,13 +144,13 @@ This interface is supported by the openocd version included in Zephyr SDK. .. _Nucleo F303K8 website: - http://www.st.com/en/evaluation-tools/nucleo-F303K8.html + https://www.st.com/en/evaluation-tools/nucleo-F303K8.html .. _STM32 Nucleo-32 board User Manual: https://www.st.com/resource/en/user_manual/dm00231744-stm32-nucleo32-boards-mb1180-stmicroelectronics.pdf .. _STM32F303K8 on www.st.com: - http://www.st.com/en/microcontrollers/stm32F303K8.html + https://www.st.com/en/microcontrollers/stm32F303K8.html .. _STM32F303K8 reference manual: https://www.st.com/resource/en/reference_manual/dm00043574-stm32f303xbcde-stm32f303x68-stm32f328x8-stm32f358xc-stm32f398xe-advanced-armbased-mcus-stmicroelectronics.pdf diff --git a/boards/arm/nucleo_f303k8/nucleo_f303k8.yaml b/boards/arm/nucleo_f303k8/nucleo_f303k8.yaml index 1466d0bafc3..3442ef50d0d 100644 --- a/boards/arm/nucleo_f303k8/nucleo_f303k8.yaml +++ b/boards/arm/nucleo_f303k8/nucleo_f303k8.yaml @@ -15,3 +15,4 @@ supported: - gpio - pwm - counter +vendor: st diff --git a/boards/arm/nucleo_f303re/doc/index.rst b/boards/arm/nucleo_f303re/doc/index.rst index 4fc6c911a7d..387a2bc28d2 100644 --- a/boards/arm/nucleo_f303re/doc/index.rst +++ b/boards/arm/nucleo_f303re/doc/index.rst @@ -147,16 +147,16 @@ This interface is supported by the openocd version included in Zephyr SDK. .. _Nucleo F303RE website: - http://www.st.com/en/evaluation-tools/nucleo-f303re.html + https://www.st.com/en/evaluation-tools/nucleo-f303re.html .. _STM32 Nucleo-64 board User Manual: - http://www.st.com/resource/en/user_manual/dm00105823.pdf + https://www.st.com/resource/en/user_manual/dm00105823.pdf .. _STM32F303RE on www.st.com: - http://www.st.com/en/microcontrollers/stm32f303re.html + https://www.st.com/en/microcontrollers/stm32f303re.html .. _STM32F303RE reference manual: https://www.st.com/resource/en/reference_manual/dm00043574.pdf .. _STM32F303RE datasheet: - http://www.st.com/resource/en/datasheet/stm32f303re.pdf + https://www.st.com/resource/en/datasheet/stm32f303re.pdf diff --git a/boards/arm/nucleo_f303re/nucleo_f303re.yaml b/boards/arm/nucleo_f303re/nucleo_f303re.yaml index f1aa776b762..525a83f252a 100644 --- a/boards/arm/nucleo_f303re/nucleo_f303re.yaml +++ b/boards/arm/nucleo_f303re/nucleo_f303re.yaml @@ -15,3 +15,4 @@ supported: - can - i2c - spi +vendor: st diff --git a/boards/arm/nucleo_f334r8/doc/index.rst b/boards/arm/nucleo_f334r8/doc/index.rst index 422f9f86ba1..d44ee9e51d7 100644 --- a/boards/arm/nucleo_f334r8/doc/index.rst +++ b/boards/arm/nucleo_f334r8/doc/index.rst @@ -143,7 +143,7 @@ Flashing an application to Nucleo F334R8 Connect the Nucleo F334R8 to your host computer using the USB port, then build and flash an application. Here is an example for the -:ref:`blinky-sample` application. +:zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -156,7 +156,7 @@ Debugging ========= You can debug an application in the usual way. Here is an example for -the :ref:`blinky-sample` application. +the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -170,10 +170,10 @@ References .. target-notes:: .. _Nucleo F334R8 website: - http://www.st.com/en/evaluation-tools/nucleo-f334r8.html + https://www.st.com/en/evaluation-tools/nucleo-f334r8.html .. _STM32F334 reference manual: - http://www.st.com/resource/en/reference_manual/dm00093941.pdf + https://www.st.com/resource/en/reference_manual/dm00093941.pdf .. _STM32 Nucleo-64 board User Manual: - http://www.st.com/resource/en/user_manual/dm00105823.pdf + https://www.st.com/resource/en/user_manual/dm00105823.pdf diff --git a/boards/arm/nucleo_f334r8/nucleo_f334r8.yaml b/boards/arm/nucleo_f334r8/nucleo_f334r8.yaml index 2c72db14686..a4533b015a0 100644 --- a/boards/arm/nucleo_f334r8/nucleo_f334r8.yaml +++ b/boards/arm/nucleo_f334r8/nucleo_f334r8.yaml @@ -23,3 +23,4 @@ supported: - watchdog - counter - nvs +vendor: st diff --git a/boards/arm/nucleo_f401re/doc/index.rst b/boards/arm/nucleo_f401re/doc/index.rst index c4aaff7c73f..c844ef9ab9c 100644 --- a/boards/arm/nucleo_f401re/doc/index.rst +++ b/boards/arm/nucleo_f401re/doc/index.rst @@ -194,13 +194,13 @@ You can debug an application in the usual way. Here is an example for the :goals: debug .. _Nucleo F401RE website: - http://www.st.com/en/evaluation-tools/nucleo-f401re.html + https://www.st.com/en/evaluation-tools/nucleo-f401re.html .. _STM32 Nucleo-64 board User Manual: - http://www.st.com/resource/en/user_manual/dm00105823.pdf + https://www.st.com/resource/en/user_manual/dm00105823.pdf .. _STM32F401RE on www.st.com: - http://www.st.com/en/microcontrollers/stm32f401re.html + https://www.st.com/en/microcontrollers/stm32f401re.html .. _STM32F401 reference manual: - http://www.st.com/resource/en/reference_manual/dm00096844.pdf + https://www.st.com/resource/en/reference_manual/dm00096844.pdf diff --git a/boards/arm/nucleo_f401re/nucleo_f401re.yaml b/boards/arm/nucleo_f401re/nucleo_f401re.yaml index 3d6336f7d37..ea1d89798c0 100644 --- a/boards/arm/nucleo_f401re/nucleo_f401re.yaml +++ b/boards/arm/nucleo_f401re/nucleo_f401re.yaml @@ -19,3 +19,4 @@ supported: - watchdog ram: 96 flash: 512 +vendor: st diff --git a/boards/arm/nucleo_f410rb/doc/index.rst b/boards/arm/nucleo_f410rb/doc/index.rst index d629044fc11..c5702552ca8 100644 --- a/boards/arm/nucleo_f410rb/doc/index.rst +++ b/boards/arm/nucleo_f410rb/doc/index.rst @@ -200,13 +200,13 @@ You can debug an application in the usual way. Here is an example for the :goals: debug .. _Nucleo F410RB website: - http://www.st.com/en/evaluation-tools/nucleo-F410RB.html + https://www.st.com/en/evaluation-tools/nucleo-F410RB.html .. _STM32 Nucleo-64 board User Manual: - http://www.st.com/resource/en/user_manual/dm00105823.pdf + https://www.st.com/resource/en/user_manual/dm00105823.pdf .. _STM32F410RB on www.st.com: - http://www.st.com/en/microcontrollers/stm32f410rb.html + https://www.st.com/en/microcontrollers/stm32f410rb.html .. _STM32F410 reference manual: https://www.st.com/resource/en/reference_manual/dm00180366.pdf diff --git a/boards/arm/nucleo_f410rb/nucleo_f410rb.yaml b/boards/arm/nucleo_f410rb/nucleo_f410rb.yaml index a1ce4005e07..81eef793cdd 100644 --- a/boards/arm/nucleo_f410rb/nucleo_f410rb.yaml +++ b/boards/arm/nucleo_f410rb/nucleo_f410rb.yaml @@ -16,3 +16,4 @@ supported: - i2c ram: 32 flash: 128 +vendor: st diff --git a/boards/arm/nucleo_f411re/doc/index.rst b/boards/arm/nucleo_f411re/doc/index.rst index 48e4813eb77..ee7d652d1c5 100644 --- a/boards/arm/nucleo_f411re/doc/index.rst +++ b/boards/arm/nucleo_f411re/doc/index.rst @@ -188,13 +188,13 @@ You can debug an application in the usual way. Here is an example for the :goals: debug .. _Nucleo F411RE website: - http://www.st.com/en/evaluation-tools/nucleo-f411re.html + https://www.st.com/en/evaluation-tools/nucleo-f411re.html .. _STM32 Nucleo-64 board User Manual: - http://www.st.com/resource/en/user_manual/dm00105823.pdf + https://www.st.com/resource/en/user_manual/dm00105823.pdf .. _STM32F411RE on www.st.com: - http://www.st.com/en/microcontrollers/stm32f411re.html + https://www.st.com/en/microcontrollers/stm32f411re.html .. _STM32F411 reference manual: - http://www.st.com/resource/en/reference_manual/dm00119316.pdf + https://www.st.com/resource/en/reference_manual/dm00119316.pdf diff --git a/boards/arm/nucleo_f411re/nucleo_f411re.yaml b/boards/arm/nucleo_f411re/nucleo_f411re.yaml index 1a7a9fafa51..90a57f93720 100644 --- a/boards/arm/nucleo_f411re/nucleo_f411re.yaml +++ b/boards/arm/nucleo_f411re/nucleo_f411re.yaml @@ -17,3 +17,4 @@ supported: - i2c ram: 96 flash: 512 +vendor: st diff --git a/boards/arm/nucleo_f412zg/doc/index.rst b/boards/arm/nucleo_f412zg/doc/index.rst index 024382af888..678971ecf1e 100644 --- a/boards/arm/nucleo_f412zg/doc/index.rst +++ b/boards/arm/nucleo_f412zg/doc/index.rst @@ -160,13 +160,13 @@ This interface is supported by the openocd version included in Zephyr SDK. .. _Nucleo F412ZG website: - http://www.st.com/en/evaluation-tools/nucleo-f412zg.html + https://www.st.com/en/evaluation-tools/nucleo-f412zg.html .. _STM32 Nucleo-144 board User Manual: - http://www.st.com/resource/en/user_manual/dm00244518.pdf + https://www.st.com/resource/en/user_manual/dm00244518.pdf .. _STM32F412ZG on www.st.com: - http://www.st.com/en/microcontrollers/stm32f412zg.html + https://www.st.com/en/microcontrollers/stm32f412zg.html .. _STM32F412 reference manual: - http://www.st.com/resource/en/reference_manual/dm00180369.pdf + https://www.st.com/resource/en/reference_manual/dm00180369.pdf diff --git a/boards/arm/nucleo_f412zg/nucleo_f412zg.yaml b/boards/arm/nucleo_f412zg/nucleo_f412zg.yaml index 1742dc95f1d..10fd21fc705 100644 --- a/boards/arm/nucleo_f412zg/nucleo_f412zg.yaml +++ b/boards/arm/nucleo_f412zg/nucleo_f412zg.yaml @@ -18,3 +18,4 @@ supported: - gpio - usb_device - counter +vendor: st diff --git a/boards/arm/nucleo_f413zh/doc/index.rst b/boards/arm/nucleo_f413zh/doc/index.rst index ca6bfd52a15..b00213ced7e 100644 --- a/boards/arm/nucleo_f413zh/doc/index.rst +++ b/boards/arm/nucleo_f413zh/doc/index.rst @@ -162,13 +162,13 @@ This interface is supported by the openocd version included in Zephyr SDK. .. _Nucleo F413ZH website: - http://www.st.com/en/evaluation-tools/nucleo-f413zh.html + https://www.st.com/en/evaluation-tools/nucleo-f413zh.html .. _STM32 Nucleo-144 board User Manual: - http://www.st.com/resource/en/user_manual/dm00244518.pdf + https://www.st.com/resource/en/user_manual/dm00244518.pdf .. _STM32F413ZH on www.st.com: - http://www.st.com/en/microcontrollers/stm32f413zh.html + https://www.st.com/en/microcontrollers/stm32f413zh.html .. _STM32F413/423 reference manual: - http://www.st.com/resource/en/reference_manual/dm00305666.pdf + https://www.st.com/resource/en/reference_manual/dm00305666.pdf diff --git a/boards/arm/nucleo_f413zh/nucleo_f413zh.yaml b/boards/arm/nucleo_f413zh/nucleo_f413zh.yaml index d81b743115d..415b1d08f56 100644 --- a/boards/arm/nucleo_f413zh/nucleo_f413zh.yaml +++ b/boards/arm/nucleo_f413zh/nucleo_f413zh.yaml @@ -18,3 +18,4 @@ supported: - gpio - usb_device - counter +vendor: st diff --git a/boards/arm/nucleo_f429zi/doc/index.rst b/boards/arm/nucleo_f429zi/doc/index.rst index 8bb1d0fee85..3b20f6a7a0c 100644 --- a/boards/arm/nucleo_f429zi/doc/index.rst +++ b/boards/arm/nucleo_f429zi/doc/index.rst @@ -199,19 +199,19 @@ A specific application can adjust each partition size based on its needs. .. _Nucleo F429ZI website: - http://www.st.com/en/evaluation-tools/nucleo-f429zi.html + https://www.st.com/en/evaluation-tools/nucleo-f429zi.html .. _STM32 Nucleo-144 board User Manual: - http://www.st.com/resource/en/user_manual/dm00244518.pdf + https://www.st.com/resource/en/user_manual/dm00244518.pdf .. _STM32F429ZI on www.st.com: - http://www.st.com/en/microcontrollers/stm32f429zi.html + https://www.st.com/en/microcontrollers/stm32f429zi.html .. _STM32F429 reference manual: - http://www.st.com/resource/en/reference_manual/dm00031020.pdf + https://www.st.com/resource/en/reference_manual/dm00031020.pdf .. _STM32F429 datasheet: - http://www.st.com/resource/en/datasheet/DM00071990.pdf + https://www.st.com/resource/en/datasheet/DM00071990.pdf .. _MCUBoot: https://github.com/JuulLabs-OSS/mcuboot/blob/master/README.md diff --git a/boards/arm/nucleo_f429zi/nucleo_f429zi.yaml b/boards/arm/nucleo_f429zi/nucleo_f429zi.yaml index e4afaa797fa..762ede6fb2c 100644 --- a/boards/arm/nucleo_f429zi/nucleo_f429zi.yaml +++ b/boards/arm/nucleo_f429zi/nucleo_f429zi.yaml @@ -24,3 +24,4 @@ supported: - dac - dma - nvs +vendor: st diff --git a/boards/arm/nucleo_f446re/doc/index.rst b/boards/arm/nucleo_f446re/doc/index.rst index 07005c58cda..a835d963d2b 100644 --- a/boards/arm/nucleo_f446re/doc/index.rst +++ b/boards/arm/nucleo_f446re/doc/index.rst @@ -211,16 +211,16 @@ You can debug an application in the usual way. Here is an example for the :goals: debug .. _Nucleo F446RE website: - http://www.st.com/en/evaluation-tools/nucleo-f446re.html + https://www.st.com/en/evaluation-tools/nucleo-f446re.html .. _STM32 Nucleo-64 board User Manual: - http://www.st.com/resource/en/user_manual/dm00105823.pdf + https://www.st.com/resource/en/user_manual/dm00105823.pdf .. _STM32F446RE on www.st.com: - http://www.st.com/en/microcontrollers/stm32f446re.html + https://www.st.com/en/microcontrollers/stm32f446re.html .. _STM32F446 reference manual: - http://www.st.com/resource/en/reference_manual/dm00135183.pdf + https://www.st.com/resource/en/reference_manual/dm00135183.pdf .. _RS485 CAN Shield: https://www.waveshare.com/wiki/RS485_CAN_Shield diff --git a/boards/arm/nucleo_f446re/nucleo_f446re.yaml b/boards/arm/nucleo_f446re/nucleo_f446re.yaml index 38cf4a4b5a7..9d45982d995 100644 --- a/boards/arm/nucleo_f446re/nucleo_f446re.yaml +++ b/boards/arm/nucleo_f446re/nucleo_f446re.yaml @@ -18,3 +18,4 @@ supported: - backup_sram ram: 96 flash: 512 +vendor: st diff --git a/boards/arm/nucleo_f446ze/doc/index.rst b/boards/arm/nucleo_f446ze/doc/index.rst index 0c7b4fcb874..b0a8f431462 100644 --- a/boards/arm/nucleo_f446ze/doc/index.rst +++ b/boards/arm/nucleo_f446ze/doc/index.rst @@ -236,13 +236,13 @@ You can debug an application in the usual way. Here is an example for the :goals: debug .. _Nucleo F446ZE website: - http://www.st.com/en/evaluation-tools/nucleo-f446ze.html + https://www.st.com/en/evaluation-tools/nucleo-f446ze.html .. _STM32 Nucleo-144 board User Manual: https://www.st.com/resource/en/user_manual/um1974-stm32-nucleo144-boards-mb1137-stmicroelectronics.pdf .. _STM32F446ZE on www.st.com: - http://www.st.com/en/microcontrollers/stm32f446ze.html + https://www.st.com/en/microcontrollers/stm32f446ze.html .. _STM32F446 reference manual: - http://www.st.com/resource/en/reference_manual/dm00135183.pdf + https://www.st.com/resource/en/reference_manual/dm00135183.pdf diff --git a/boards/arm/nucleo_f446ze/nucleo_f446ze.yaml b/boards/arm/nucleo_f446ze/nucleo_f446ze.yaml index f8a93e59e2a..f363608c3be 100644 --- a/boards/arm/nucleo_f446ze/nucleo_f446ze.yaml +++ b/boards/arm/nucleo_f446ze/nucleo_f446ze.yaml @@ -21,3 +21,4 @@ supported: - quadspi ram: 128 flash: 512 +vendor: st diff --git a/boards/arm/nucleo_f746zg/doc/index.rst b/boards/arm/nucleo_f746zg/doc/index.rst index bc419c612c4..ef9fdf9d20e 100644 --- a/boards/arm/nucleo_f746zg/doc/index.rst +++ b/boards/arm/nucleo_f746zg/doc/index.rst @@ -226,7 +226,7 @@ You can debug an application in the usual way. Here is an example for the https://www.st.com/en/evaluation-tools/nucleo-f746zg.html .. _STM32 Nucleo-144 board User Manual: - http://www.st.com/resource/en/user_manual/dm00244518.pdf + https://www.st.com/resource/en/user_manual/dm00244518.pdf .. _STM32F746ZG on www.st.com: https://www.st.com/content/st_com/en/products/microcontrollers/stm32-32-bit-arm-cortex-mcus/stm32-high-performance-mcus/stm32f7-series/stm32f7x6/stm32f746zg.html diff --git a/boards/arm/nucleo_f746zg/nucleo_f746zg.yaml b/boards/arm/nucleo_f746zg/nucleo_f746zg.yaml index 32b17d86aa6..015b1e3e642 100644 --- a/boards/arm/nucleo_f746zg/nucleo_f746zg.yaml +++ b/boards/arm/nucleo_f746zg/nucleo_f746zg.yaml @@ -26,3 +26,4 @@ supported: - dac - dma - backup_sram +vendor: st diff --git a/boards/arm/nucleo_f756zg/doc/index.rst b/boards/arm/nucleo_f756zg/doc/index.rst index 299eb9e4c7b..2616a3b6dcc 100644 --- a/boards/arm/nucleo_f756zg/doc/index.rst +++ b/boards/arm/nucleo_f756zg/doc/index.rst @@ -209,7 +209,7 @@ You can debug an application in the usual way. Here is an example for the https://www.st.com/en/evaluation-tools/nucleo-f756zg.html .. _STM32 Nucleo-144 board User Manual: - http://www.st.com/resource/en/user_manual/dm00105823.pdf + https://www.st.com/resource/en/user_manual/dm00105823.pdf .. _STM32F756ZG on www.st.com: https://www.st.com/content/st_com/en/products/microcontrollers/stm32-32-bit-arm-cortex-mcus/stm32-high-performance-mcus/stm32f7-series/stm32f7x6/stm32f756zg.html diff --git a/boards/arm/nucleo_f756zg/nucleo_f756zg.yaml b/boards/arm/nucleo_f756zg/nucleo_f756zg.yaml index 01d78747f06..ddcf34064ad 100644 --- a/boards/arm/nucleo_f756zg/nucleo_f756zg.yaml +++ b/boards/arm/nucleo_f756zg/nucleo_f756zg.yaml @@ -19,3 +19,4 @@ supported: - i2c - pwm - spi +vendor: st diff --git a/boards/arm/nucleo_f767zi/doc/index.rst b/boards/arm/nucleo_f767zi/doc/index.rst index bf6f1c68b92..bed503e2609 100644 --- a/boards/arm/nucleo_f767zi/doc/index.rst +++ b/boards/arm/nucleo_f767zi/doc/index.rst @@ -227,7 +227,7 @@ You can debug an application in the usual way. Here is an example for the https://www.st.com/en/evaluation-tools/nucleo-f767zi.html .. _STM32 Nucleo-144 board User Manual: - http://www.st.com/resource/en/user_manual/dm00244518.pdf + https://www.st.com/resource/en/user_manual/dm00244518.pdf .. _STM32f767zi on www.st.com: https://www.st.com/content/st_com/en/products/microcontrollers/stm32-32-bit-arm-cortex-mcus/stm32-high-performance-mcus/stm32f7-series/stm32f7x&/stm32f767zi.html diff --git a/boards/arm/nucleo_f767zi/nucleo_f767zi.yaml b/boards/arm/nucleo_f767zi/nucleo_f767zi.yaml index d6b46f15bbc..e3be20e3780 100644 --- a/boards/arm/nucleo_f767zi/nucleo_f767zi.yaml +++ b/boards/arm/nucleo_f767zi/nucleo_f767zi.yaml @@ -25,3 +25,4 @@ supported: - counter - can - dac +vendor: st diff --git a/boards/arm/nucleo_g031k8/doc/index.rst b/boards/arm/nucleo_g031k8/doc/index.rst index 1b32a1fb59e..6f933b08546 100644 --- a/boards/arm/nucleo_g031k8/doc/index.rst +++ b/boards/arm/nucleo_g031k8/doc/index.rst @@ -123,7 +123,7 @@ This interface is supported by the openocd version included in the Zephyr SDK. Flashing an application to Nucleo G031K8 ---------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -159,7 +159,7 @@ References .. target-notes:: .. _Nucleo G031K8 website: - http://www.st.com/en/evaluation-tools/nucleo-g031k8.html + https://www.st.com/en/evaluation-tools/nucleo-g031k8.html .. _STM32G0x1 reference manual: https://www.st.com/resource/en/reference_manual/rm0444-stm32g0x1-advanced-armbased-32bit-mcus-stmicroelectronics.pdf diff --git a/boards/arm/nucleo_g031k8/nucleo_g031k8.yaml b/boards/arm/nucleo_g031k8/nucleo_g031k8.yaml index 9a19f3e6338..34ea35189ab 100644 --- a/boards/arm/nucleo_g031k8/nucleo_g031k8.yaml +++ b/boards/arm/nucleo_g031k8/nucleo_g031k8.yaml @@ -12,3 +12,4 @@ supported: - spi ram: 8 flash: 64 +vendor: st diff --git a/boards/arm/nucleo_g031k8/support/openocd.cfg b/boards/arm/nucleo_g031k8/support/openocd.cfg index 6bb5b17874f..f4b1bc9142c 100644 --- a/boards/arm/nucleo_g031k8/support/openocd.cfg +++ b/boards/arm/nucleo_g031k8/support/openocd.cfg @@ -1,5 +1,5 @@ # This is an ST NUCLEO-G031K8 board with single STM32G031K8 chip. -# http://www.st.com/en/evaluation-tools/nucleo-g031k8.html +# https://www.st.com/en/evaluation-tools/nucleo-g031k8.html source [find interface/stlink-dap.cfg] diff --git a/boards/arm/nucleo_g070rb/doc/index.rst b/boards/arm/nucleo_g070rb/doc/index.rst index acdbdc53d28..056bb298c4f 100644 --- a/boards/arm/nucleo_g070rb/doc/index.rst +++ b/boards/arm/nucleo_g070rb/doc/index.rst @@ -155,7 +155,7 @@ Nucleo G070RB board includes an ST-LINK/V2-1 embedded debug tool interface. Flashing an application to Nucleo G070RB ---------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -182,10 +182,10 @@ References .. target-notes:: .. _Nucleo G070RB website: - http://www.st.com/en/evaluation-tools/nucleo-g070rb.html + https://www.st.com/en/evaluation-tools/nucleo-g070rb.html .. _STM32 Nucleo-64 board User Manual: - http://www.st.com/resource/en/user_manual/dm00452640.pdf + https://www.st.com/resource/en/user_manual/dm00452640.pdf .. _G070RB on www.st.com: - http://www.st.com/en/microcontrollers/stm32g070rb.html + https://www.st.com/en/microcontrollers/stm32g070rb.html diff --git a/boards/arm/nucleo_g070rb/nucleo_g070rb.yaml b/boards/arm/nucleo_g070rb/nucleo_g070rb.yaml index cb12531bebd..6cac29d4db1 100644 --- a/boards/arm/nucleo_g070rb/nucleo_g070rb.yaml +++ b/boards/arm/nucleo_g070rb/nucleo_g070rb.yaml @@ -22,3 +22,4 @@ supported: - pwm - adc - nvs +vendor: st diff --git a/boards/arm/nucleo_g071rb/doc/index.rst b/boards/arm/nucleo_g071rb/doc/index.rst index 81d05439ef8..f6aebe8f12b 100644 --- a/boards/arm/nucleo_g071rb/doc/index.rst +++ b/boards/arm/nucleo_g071rb/doc/index.rst @@ -159,7 +159,7 @@ Nucleo G071RB board includes an ST-LINK/V3 embedded debug tool interface. Flashing an application to Nucleo G071RB ---------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -186,13 +186,13 @@ References .. target-notes:: .. _Nucleo G071RB website: - http://www.st.com/en/evaluation-tools/nucleo-g071rb.html + https://www.st.com/en/evaluation-tools/nucleo-g071rb.html .. _STM32G071 reference manual: - http://www.st.com/resource/en/reference_manual/dm00371828.pdf + https://www.st.com/resource/en/reference_manual/dm00371828.pdf .. _STM32 Nucleo-64 board User Manual: - http://www.st.com/resource/en/user_manual/dm00452640.pdf + https://www.st.com/resource/en/user_manual/dm00452640.pdf .. _G071RB on www.st.com: - http://www.st.com/en/microcontrollers/stm32g071rb.html + https://www.st.com/en/microcontrollers/stm32g071rb.html diff --git a/boards/arm/nucleo_g071rb/nucleo_g071rb.dts b/boards/arm/nucleo_g071rb/nucleo_g071rb.dts index c9f1a2b6575..76b2369280e 100644 --- a/boards/arm/nucleo_g071rb/nucleo_g071rb.dts +++ b/boards/arm/nucleo_g071rb/nucleo_g071rb.dts @@ -140,7 +140,7 @@ &adc1 { pinctrl-0 = <&adc1_in0_pa0 &adc1_in1_pa1>; pinctrl-names = "default"; - st,adc-clock-source = ; + st,adc-clock-source = ; st,adc-prescaler = <4>; status = "okay"; vref-mv = <3300>; diff --git a/boards/arm/nucleo_g071rb/nucleo_g071rb.yaml b/boards/arm/nucleo_g071rb/nucleo_g071rb.yaml index 87921bf7b76..755196fec16 100644 --- a/boards/arm/nucleo_g071rb/nucleo_g071rb.yaml +++ b/boards/arm/nucleo_g071rb/nucleo_g071rb.yaml @@ -25,3 +25,4 @@ supported: - dma - lptim - nvs +vendor: st diff --git a/boards/arm/nucleo_g0b1re/doc/index.rst b/boards/arm/nucleo_g0b1re/doc/index.rst index 1e59c160467..0ad60852627 100644 --- a/boards/arm/nucleo_g0b1re/doc/index.rst +++ b/boards/arm/nucleo_g0b1re/doc/index.rst @@ -56,7 +56,7 @@ Nucleo G0B1RE provides the following hardware components: - HDMI_CEC(1) - USB 2.0 FS device (crystal-less) and host controller(1) - USB Type-C Power Delivery controller -- CAN-FD(2) +- CAN FD(2) - GPIO (up to 94) with external interrupt capability - Tamper Pins(3) - 12-bit ADC with 16 channels @@ -168,7 +168,7 @@ following pyocd command: Flashing an application to Nucleo G0B1RE ---------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -195,13 +195,13 @@ References .. target-notes:: .. _Nucleo G0B1RE website: - http://www.st.com/en/evaluation-tools/nucleo-g0b1re.html + https://www.st.com/en/evaluation-tools/nucleo-g0b1re.html .. _STM32G0B1 reference manual: - http://www.st.com/resource/en/reference_manual/dm00371828.pdf + https://www.st.com/resource/en/reference_manual/dm00371828.pdf .. _STM32 Nucleo-64 board User Manual: - http://www.st.com/resource/en/user_manual/dm00452640.pdf + https://www.st.com/resource/en/user_manual/dm00452640.pdf .. _G0B1RE on www.st.com: - http://www.st.com/en/microcontrollers/stm32g0b1re.html + https://www.st.com/en/microcontrollers/stm32g0b1re.html diff --git a/boards/arm/nucleo_g0b1re/nucleo_g0b1re.dts b/boards/arm/nucleo_g0b1re/nucleo_g0b1re.dts index e74550e497f..17d22e5e9d4 100644 --- a/boards/arm/nucleo_g0b1re/nucleo_g0b1re.dts +++ b/boards/arm/nucleo_g0b1re/nucleo_g0b1re.dts @@ -61,6 +61,7 @@ &clk_hsi48 { status = "okay"; + crs-usb-sof; }; &pll { diff --git a/boards/arm/nucleo_g0b1re/nucleo_g0b1re.yaml b/boards/arm/nucleo_g0b1re/nucleo_g0b1re.yaml index f52eb20db29..bc267274401 100644 --- a/boards/arm/nucleo_g0b1re/nucleo_g0b1re.yaml +++ b/boards/arm/nucleo_g0b1re/nucleo_g0b1re.yaml @@ -13,6 +13,7 @@ supported: - arduino_gpio - arduino_i2c - arduino_spi + - arduino_serial - uart - gpio - i2c @@ -21,3 +22,4 @@ supported: - dma - usb_device - lptim +vendor: st diff --git a/boards/arm/nucleo_g431rb/Kconfig.defconfig b/boards/arm/nucleo_g431rb/Kconfig.defconfig index 993bee2f796..62c8e061965 100644 --- a/boards/arm/nucleo_g431rb/Kconfig.defconfig +++ b/boards/arm/nucleo_g431rb/Kconfig.defconfig @@ -12,8 +12,4 @@ config SPI_STM32_INTERRUPT default y depends on SPI -# LPTIM clocked by LSE, force tick freq to 4096 for tick accuracy -config SYS_CLOCK_TICKS_PER_SEC - default 4096 if STM32_LPTIM_TIMER - endif # BOARD_NUCLEO_G431RB diff --git a/boards/arm/nucleo_g431rb/doc/index.rst b/boards/arm/nucleo_g431rb/doc/index.rst index db18f702cdc..7d60b8c5426 100644 --- a/boards/arm/nucleo_g431rb/doc/index.rst +++ b/boards/arm/nucleo_g431rb/doc/index.rst @@ -119,6 +119,8 @@ The Zephyr nucleo_g431rb board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | SPI | on-chip | spi | +-----------+------------+-------------------------------------+ +| RNG | on-chip | rng | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. @@ -249,13 +251,13 @@ You can debug an application in the usual way. Here is an example for the :goals: debug .. _Nucleo G431RB website: - http://www.st.com/en/evaluation-tools/nucleo-g431rb.html + https://www.st.com/en/evaluation-tools/nucleo-g431rb.html .. _STM32G4 Nucleo-64 board User Manual: https://www.st.com/resource/en/user_manual/dm00556337.pdf .. _STM32G431RB on www.st.com: - http://www.st.com/en/microcontrollers/stm32g431rb.html + https://www.st.com/en/microcontrollers/stm32g431rb.html .. _STM32G4 reference manual: https://www.st.com/resource/en/reference_manual/dm00355726.pdf diff --git a/boards/arm/nucleo_g431rb/nucleo_g431rb.dts b/boards/arm/nucleo_g431rb/nucleo_g431rb.dts index 2ab18ec7360..0bdf2b7d301 100644 --- a/boards/arm/nucleo_g431rb/nucleo_g431rb.dts +++ b/boards/arm/nucleo_g431rb/nucleo_g431rb.dts @@ -63,6 +63,10 @@ status = "okay"; }; +&clk_hsi48 { + status = "okay"; +}; + &clk_hse { clock-frequency = ; status = "okay"; @@ -86,6 +90,12 @@ apb2-prescaler = <1>; }; +&rng { + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x04000000>, + <&rcc STM32_SRC_HSI48 CLK48_SEL(0)>; + status = "okay"; +}; + &usart1 { pinctrl-0 = <&usart1_tx_pc4 &usart1_rx_pc5>; pinctrl-names = "default"; diff --git a/boards/arm/nucleo_g431rb/nucleo_g431rb.yaml b/boards/arm/nucleo_g431rb/nucleo_g431rb.yaml index 6ad1f6f12f9..71ca5707ac5 100644 --- a/boards/arm/nucleo_g431rb/nucleo_g431rb.yaml +++ b/boards/arm/nucleo_g431rb/nucleo_g431rb.yaml @@ -19,5 +19,7 @@ supported: - usb device - counter - spi + - rng - dac - watchdog +vendor: st diff --git a/boards/arm/nucleo_g431rb/nucleo_g431rb_defconfig b/boards/arm/nucleo_g431rb/nucleo_g431rb_defconfig index 92c2363d2d8..25dcaf3dfb7 100644 --- a/boards/arm/nucleo_g431rb/nucleo_g431rb_defconfig +++ b/boards/arm/nucleo_g431rb/nucleo_g431rb_defconfig @@ -24,3 +24,6 @@ CONFIG_HW_STACK_PROTECTION=y # enable pin controller CONFIG_PINCTRL=y + +# LSE defined as LPTIM clock source by the DTS +CONFIG_STM32_LPTIM_CLOCK_LSE=y diff --git a/boards/arm/nucleo_g474re/doc/index.rst b/boards/arm/nucleo_g474re/doc/index.rst index b21265795be..437668ed42e 100644 --- a/boards/arm/nucleo_g474re/doc/index.rst +++ b/boards/arm/nucleo_g474re/doc/index.rst @@ -239,13 +239,13 @@ You can debug an application in the usual way. Here is an example for the :goals: debug .. _Nucleo G474RE website: - http://www.st.com/en/evaluation-tools/nucleo-g474re.html + https://www.st.com/en/evaluation-tools/nucleo-g474re.html .. _STM32G4 Nucleo-64 board User Manual: https://www.st.com/resource/en/user_manual/dm00556337.pdf .. _STM32G474RE on www.st.com: - http://www.st.com/en/microcontrollers/stm32g474re.html + https://www.st.com/en/microcontrollers/stm32g474re.html .. _STM32G4 reference manual: https://www.st.com/resource/en/reference_manual/dm00355726.pdf diff --git a/boards/arm/nucleo_g474re/nucleo_g474re.yaml b/boards/arm/nucleo_g474re/nucleo_g474re.yaml index eee22d085f5..d473be929bf 100644 --- a/boards/arm/nucleo_g474re/nucleo_g474re.yaml +++ b/boards/arm/nucleo_g474re/nucleo_g474re.yaml @@ -24,3 +24,4 @@ supported: - dac - dma - can +vendor: st diff --git a/boards/arm/nucleo_h563zi/doc/index.rst b/boards/arm/nucleo_h563zi/doc/index.rst index 6ed79d8c7b9..9b6f880ac4c 100644 --- a/boards/arm/nucleo_h563zi/doc/index.rst +++ b/boards/arm/nucleo_h563zi/doc/index.rst @@ -294,7 +294,7 @@ Debugging ========= You can debug an application in the usual way. Here is an example for the -:ref:`blinky-sample` application. +:zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -308,7 +308,7 @@ You can debug an application in the usual way. Here is an example for the https://www.st.com/resource/en/user_manual/um3115-stm32h5-nucleo144-board-mb1404-stmicroelectronics.pdf .. _STM32H563ZI on www.st.com: - http://www.st.com/en/microcontrollers/stm32h563zi.html + https://www.st.com/en/microcontrollers/stm32h563zi.html .. _STM32H563 reference manual: https://www.st.com/resource/en/reference_manual/rm0481-stm32h563h573-and-stm32h562-armbased-32bit-mcus-stmicroelectronics.pdf diff --git a/boards/arm/nucleo_h563zi/nucleo_h563zi.yaml b/boards/arm/nucleo_h563zi/nucleo_h563zi.yaml index 0d1b1758a22..9e04cd2b7de 100644 --- a/boards/arm/nucleo_h563zi/nucleo_h563zi.yaml +++ b/boards/arm/nucleo_h563zi/nucleo_h563zi.yaml @@ -22,3 +22,4 @@ supported: - usb_device - usb - rtc +vendor: st diff --git a/boards/arm/nucleo_h723zg/doc/index.rst b/boards/arm/nucleo_h723zg/doc/index.rst index d27c7367aca..09b71835f67 100644 --- a/boards/arm/nucleo_h723zg/doc/index.rst +++ b/boards/arm/nucleo_h723zg/doc/index.rst @@ -71,7 +71,7 @@ Nucleo H723ZG provides the following hardware components: - UART(4) - USB OTG Full Speed and High Speed(1) - USB OTG Full Speed(1) -- CAN-FD(2) +- CAN FD(2) - SAI(2) - SPDIF_Rx(4) - HDMI_CEC(1) diff --git a/boards/arm/nucleo_h723zg/nucleo_h723zg.yaml b/boards/arm/nucleo_h723zg/nucleo_h723zg.yaml index 91c47848192..622c268ecea 100644 --- a/boards/arm/nucleo_h723zg/nucleo_h723zg.yaml +++ b/boards/arm/nucleo_h723zg/nucleo_h723zg.yaml @@ -21,3 +21,4 @@ supported: - netif:eth - backup_sram - usb_device +vendor: st diff --git a/boards/arm/nucleo_h743zi/doc/index.rst b/boards/arm/nucleo_h743zi/doc/index.rst index b2c2b7e6d4f..c401e3ab098 100644 --- a/boards/arm/nucleo_h743zi/doc/index.rst +++ b/boards/arm/nucleo_h743zi/doc/index.rst @@ -73,7 +73,7 @@ Nucleo H743ZI provides the following hardware components: - UART(4) - USB OTG Full Speed and High Speed(1) - USB OTG Full Speed(1) -- CAN-FD(2) +- CAN FD(2) - SAI(2) - SPDIF_Rx(4) - HDMI_CEC(1) @@ -237,7 +237,7 @@ You can debug an application in the usual way. Here is an example for the https://www.st.com/en/evaluation-tools/nucleo-h743zi.html .. _STM32 Nucleo-144 board User Manual: - http://www.st.com/resource/en/user_manual/dm00244518.pdf + https://www.st.com/resource/en/user_manual/dm00244518.pdf .. _STM32H743ZI on www.st.com: https://www.st.com/content/st_com/en/products/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus/stm32-high-performance-mcus/stm32h7-series/stm32h743-753/stm32h743zi.html diff --git a/boards/arm/nucleo_h743zi/nucleo_h743zi.yaml b/boards/arm/nucleo_h743zi/nucleo_h743zi.yaml index a1246f75714..e67e8d0e54e 100644 --- a/boards/arm/nucleo_h743zi/nucleo_h743zi.yaml +++ b/boards/arm/nucleo_h743zi/nucleo_h743zi.yaml @@ -25,3 +25,4 @@ supported: - can - dac - dma +vendor: st diff --git a/boards/arm/nucleo_h745zi_q/doc/index.rst b/boards/arm/nucleo_h745zi_q/doc/index.rst index 99afb70898d..60f86f2ab81 100644 --- a/boards/arm/nucleo_h745zi_q/doc/index.rst +++ b/boards/arm/nucleo_h745zi_q/doc/index.rst @@ -75,7 +75,7 @@ Nucleo H745ZI-Q provides the following hardware components: - UART(4) - USB OTG Full Speed and High Speed(1) - USB OTG Full Speed(1) -- CAN-FD(2) +- CAN FD(2) - SAI(2) - SPDIF_Rx(4) - HDMI_CEC(1) @@ -240,7 +240,7 @@ You should see the following message on the console: Similarly, you can build and flash samples on the M4 target. For this, please take care of the resource sharing (UART port used for console for instance). -Here is an example for the :ref:`blinky-sample` application on M4 core. +Here is an example for the :zephyr:code-sample:`blinky` application on M4 core. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/nucleo_h745zi_q/nucleo_h745zi_q_m4.yaml b/boards/arm/nucleo_h745zi_q/nucleo_h745zi_q_m4.yaml index 4d4ee02380e..3299fb78496 100644 --- a/boards/arm/nucleo_h745zi_q/nucleo_h745zi_q_m4.yaml +++ b/boards/arm/nucleo_h745zi_q/nucleo_h745zi_q_m4.yaml @@ -16,3 +16,4 @@ testing: ignore_tags: - mpu - nfc +vendor: st diff --git a/boards/arm/nucleo_h745zi_q/nucleo_h745zi_q_m7.yaml b/boards/arm/nucleo_h745zi_q/nucleo_h745zi_q_m7.yaml index 656b23bbacf..8c124a0a906 100644 --- a/boards/arm/nucleo_h745zi_q/nucleo_h745zi_q_m7.yaml +++ b/boards/arm/nucleo_h745zi_q/nucleo_h745zi_q_m7.yaml @@ -17,3 +17,4 @@ supported: - i2c - pwm - netif:eth +vendor: st diff --git a/boards/arm/nucleo_h753zi/doc/index.rst b/boards/arm/nucleo_h753zi/doc/index.rst index 8c52f7a4a27..058cbc67c9f 100644 --- a/boards/arm/nucleo_h753zi/doc/index.rst +++ b/boards/arm/nucleo_h753zi/doc/index.rst @@ -73,7 +73,7 @@ Nucleo H753ZI provides the following hardware components: - UART(4) - USB OTG Full Speed and High Speed(1) - USB OTG Full Speed(1) -- CAN-FD(2) +- CAN FD(2) - SAI(2) - SPDIF_Rx(4) - HDMI_CEC(1) @@ -224,7 +224,7 @@ You can debug an application in the usual way. Here is an example for the https://www.st.com/en/evaluation-tools/nucleo-h753zi.html .. _STM32 Nucleo-144 board User Manual: - http://www.st.com/resource/en/user_manual/dm00244518.pdf + https://www.st.com/resource/en/user_manual/dm00244518.pdf .. _STM32H753ZI on www.st.com: https://www.st.com/content/st_com/en/products/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus/stm32-high-performance-mcus/stm32h7-series/stm32h743-753/stm32h753zi.html diff --git a/boards/arm/nucleo_h753zi/nucleo_h753zi.yaml b/boards/arm/nucleo_h753zi/nucleo_h753zi.yaml index d63bd6b2c93..7bca456c26e 100644 --- a/boards/arm/nucleo_h753zi/nucleo_h753zi.yaml +++ b/boards/arm/nucleo_h753zi/nucleo_h753zi.yaml @@ -21,3 +21,4 @@ supported: - spi - usb_device - can +vendor: st diff --git a/boards/arm/nucleo_h7a3zi_q/doc/index.rst b/boards/arm/nucleo_h7a3zi_q/doc/index.rst index 92dfbd98deb..7b107733510 100644 --- a/boards/arm/nucleo_h7a3zi_q/doc/index.rst +++ b/boards/arm/nucleo_h7a3zi_q/doc/index.rst @@ -69,7 +69,7 @@ Nucleo H7A3ZI-Q provides the following hardware components: - USART(5) - UART(5) - USB OTG Full Speed and High Speed(1) -- CAN-FD(2) +- CAN FD(2) - SAI(2) - SPDIF_Rx(4) - HDMI_CEC(1) diff --git a/boards/arm/nucleo_h7a3zi_q/nucleo_h7a3zi_q.yaml b/boards/arm/nucleo_h7a3zi_q/nucleo_h7a3zi_q.yaml index 381d2fdf53b..65cd30b3e0b 100644 --- a/boards/arm/nucleo_h7a3zi_q/nucleo_h7a3zi_q.yaml +++ b/boards/arm/nucleo_h7a3zi_q/nucleo_h7a3zi_q.yaml @@ -15,3 +15,4 @@ supported: - pwm - adc - backup_sram +vendor: st diff --git a/boards/arm/nucleo_l011k4/doc/index.rst b/boards/arm/nucleo_l011k4/doc/index.rst index 6d5831a37b0..9b815ede4de 100644 --- a/boards/arm/nucleo_l011k4/doc/index.rst +++ b/boards/arm/nucleo_l011k4/doc/index.rst @@ -131,7 +131,7 @@ This interface is supported by the openocd version included in the Zephyr SDK. Flashing an application to Nucleo L011K4 ---------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -158,7 +158,7 @@ References .. target-notes:: .. _Nucleo L011K4 website: - http://www.st.com/en/evaluation-tools/nucleo-l011k4.html + https://www.st.com/en/evaluation-tools/nucleo-l011k4.html .. _STM32L0x1 reference manual: https://www.st.com/resource/en/reference_manual/dm00108282-ultralowpower-stm32l0x1-advanced-armbased-32bit-mcus-stmicroelectronics.pdf diff --git a/boards/arm/nucleo_l011k4/support/openocd.cfg b/boards/arm/nucleo_l011k4/support/openocd.cfg index 399b76d1e2f..a6ca36d73b0 100644 --- a/boards/arm/nucleo_l011k4/support/openocd.cfg +++ b/boards/arm/nucleo_l011k4/support/openocd.cfg @@ -1,5 +1,5 @@ # This is an ST NUCLEO-L011K4 board with single STM32L011K4 chip. -# http://www.st.com/en/evaluation-tools/nucleo-l011k4.html +# https://www.st.com/en/evaluation-tools/nucleo-l011k4.html source [find interface/stlink.cfg] transport select hla_swd diff --git a/boards/arm/nucleo_l031k6/doc/index.rst b/boards/arm/nucleo_l031k6/doc/index.rst index cc9803e7857..eb1f6e25387 100644 --- a/boards/arm/nucleo_l031k6/doc/index.rst +++ b/boards/arm/nucleo_l031k6/doc/index.rst @@ -124,7 +124,7 @@ This interface is supported by the openocd version included in the Zephyr SDK. Flashing an application to Nucleo L031K6 ---------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -151,7 +151,7 @@ References .. target-notes:: .. _Nucleo L031K6 website: - http://www.st.com/en/evaluation-tools/nucleo-l031k6.html + https://www.st.com/en/evaluation-tools/nucleo-l031k6.html .. _STM32L0x1 reference manual: https://www.st.com/resource/en/reference_manual/dm00108282-ultralowpower-stm32l0x1-advanced-armbased-32bit-mcus-stmicroelectronics.pdf diff --git a/boards/arm/nucleo_l031k6/nucleo_l031k6.yaml b/boards/arm/nucleo_l031k6/nucleo_l031k6.yaml index 650438636a6..e3ce901c4ee 100644 --- a/boards/arm/nucleo_l031k6/nucleo_l031k6.yaml +++ b/boards/arm/nucleo_l031k6/nucleo_l031k6.yaml @@ -13,3 +13,4 @@ supported: - eeprom ram: 8 flash: 32 +vendor: st diff --git a/boards/arm/nucleo_l031k6/support/openocd.cfg b/boards/arm/nucleo_l031k6/support/openocd.cfg index c9394171884..be154d927e4 100644 --- a/boards/arm/nucleo_l031k6/support/openocd.cfg +++ b/boards/arm/nucleo_l031k6/support/openocd.cfg @@ -1,5 +1,5 @@ # This is an ST NUCLEO-L031K6 board with single STM32L031K6 chip. -# http://www.st.com/en/evaluation-tools/nucleo-l031k6.html +# https://www.st.com/en/evaluation-tools/nucleo-l031k6.html source [find interface/stlink.cfg] transport select hla_swd diff --git a/boards/arm/nucleo_l053r8/doc/index.rst b/boards/arm/nucleo_l053r8/doc/index.rst index 5e55da0fbd2..33f84b14e6c 100644 --- a/boards/arm/nucleo_l053r8/doc/index.rst +++ b/boards/arm/nucleo_l053r8/doc/index.rst @@ -140,7 +140,7 @@ This interface is supported by the openocd version included in the Zephyr SDK. Flashing an application to Nucleo L053R8 ---------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -167,10 +167,10 @@ References .. target-notes:: .. _Nucleo L053R8 website: - http://www.st.com/en/evaluation-tools/nucleo-l053r8.html + https://www.st.com/en/evaluation-tools/nucleo-l053r8.html .. _STM32L0x3 reference manual: - http://www.st.com/resource/en/reference_manual/dm00095744.pdf + https://www.st.com/resource/en/reference_manual/dm00095744.pdf .. _STM32 Nucleo-64 board User Manual: - http://www.st.com/resource/en/user_manual/dm00105823.pdf + https://www.st.com/resource/en/user_manual/dm00105823.pdf diff --git a/boards/arm/nucleo_l053r8/nucleo_l053r8.yaml b/boards/arm/nucleo_l053r8/nucleo_l053r8.yaml index 5605e0ce837..384d5294913 100644 --- a/boards/arm/nucleo_l053r8/nucleo_l053r8.yaml +++ b/boards/arm/nucleo_l053r8/nucleo_l053r8.yaml @@ -16,3 +16,4 @@ supported: - eeprom ram: 8 flash: 64 +vendor: st diff --git a/boards/arm/nucleo_l053r8/support/openocd.cfg b/boards/arm/nucleo_l053r8/support/openocd.cfg index 9eddb05d195..fec9da07d55 100644 --- a/boards/arm/nucleo_l053r8/support/openocd.cfg +++ b/boards/arm/nucleo_l053r8/support/openocd.cfg @@ -1,5 +1,5 @@ # This is an ST NUCLEO-L053R8 board with single STM32L053R8 chip. -# http://www.st.com/en/evaluation-tools/nucleo-l053r8.html +# https://www.st.com/en/evaluation-tools/nucleo-l053r8.html source [find interface/stlink.cfg] transport select hla_swd diff --git a/boards/arm/nucleo_l073rz/Kconfig.defconfig b/boards/arm/nucleo_l073rz/Kconfig.defconfig index 66c2d366181..6a73209134a 100644 --- a/boards/arm/nucleo_l073rz/Kconfig.defconfig +++ b/boards/arm/nucleo_l073rz/Kconfig.defconfig @@ -12,8 +12,4 @@ config SPI_STM32_INTERRUPT default y depends on SPI -# LPTIM clocked by LSI, force tick freq to 4000 for tick accuracy -config SYS_CLOCK_TICKS_PER_SEC - default 4000 if STM32_LPTIM_TIMER - endif # BOARD_NUCLEO_L073RZ diff --git a/boards/arm/nucleo_l073rz/doc/index.rst b/boards/arm/nucleo_l073rz/doc/index.rst index 0950b903853..de662f5b14f 100644 --- a/boards/arm/nucleo_l073rz/doc/index.rst +++ b/boards/arm/nucleo_l073rz/doc/index.rst @@ -154,7 +154,7 @@ This interface is supported by the openocd version included in the Zephyr SDK. Flashing an application to Nucleo L073RZ ---------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -181,10 +181,10 @@ References .. target-notes:: .. _Nucleo L073RZ website: - http://www.st.com/en/evaluation-tools/nucleo-l073rz.html + https://www.st.com/en/evaluation-tools/nucleo-l073rz.html .. _STM32L0x3 reference manual: - http://www.st.com/resource/en/reference_manual/dm00095744.pdf + https://www.st.com/resource/en/reference_manual/dm00095744.pdf .. _STM32 Nucleo-64 board User Manual: - http://www.st.com/resource/en/user_manual/dm00105823.pdf + https://www.st.com/resource/en/user_manual/dm00105823.pdf diff --git a/boards/arm/nucleo_l073rz/nucleo_l073rz.yaml b/boards/arm/nucleo_l073rz/nucleo_l073rz.yaml index dc82c77449c..f97973c4854 100644 --- a/boards/arm/nucleo_l073rz/nucleo_l073rz.yaml +++ b/boards/arm/nucleo_l073rz/nucleo_l073rz.yaml @@ -22,3 +22,4 @@ supported: - counter - rng - eeprom +vendor: st diff --git a/boards/arm/nucleo_l073rz/support/openocd.cfg b/boards/arm/nucleo_l073rz/support/openocd.cfg index 00f68a63ac8..b28dd29e5c1 100644 --- a/boards/arm/nucleo_l073rz/support/openocd.cfg +++ b/boards/arm/nucleo_l073rz/support/openocd.cfg @@ -1,5 +1,5 @@ # This is an ST NUCLEO-L073RZ board with single STM32L073RZ chip. -# http://www.st.com/en/evaluation-tools/nucleo-l073rz.html +# https://www.st.com/en/evaluation-tools/nucleo-l073rz.html source [find interface/stlink.cfg] transport select hla_swd diff --git a/boards/arm/nucleo_l152re/doc/index.rst b/boards/arm/nucleo_l152re/doc/index.rst index 15af9807494..2595144e730 100644 --- a/boards/arm/nucleo_l152re/doc/index.rst +++ b/boards/arm/nucleo_l152re/doc/index.rst @@ -148,7 +148,7 @@ This interface is supported by the openocd version included in the Zephyr SDK. Flashing an application to Nucleo L152RE ---------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/nucleo_l152re/nucleo_l152re.yaml b/boards/arm/nucleo_l152re/nucleo_l152re.yaml index 8cfcaee9c2d..cc550b993c9 100644 --- a/boards/arm/nucleo_l152re/nucleo_l152re.yaml +++ b/boards/arm/nucleo_l152re/nucleo_l152re.yaml @@ -23,3 +23,4 @@ supported: - pwm - dma - nvs +vendor: st diff --git a/boards/arm/nucleo_l412rb_p/nucleo_l412rb_p.yaml b/boards/arm/nucleo_l412rb_p/nucleo_l412rb_p.yaml index c46de0ee7bb..8c663aae012 100644 --- a/boards/arm/nucleo_l412rb_p/nucleo_l412rb_p.yaml +++ b/boards/arm/nucleo_l412rb_p/nucleo_l412rb_p.yaml @@ -18,3 +18,4 @@ supported: - arduino_gpio - arduino_i2c - arduino_spi +vendor: st diff --git a/boards/arm/nucleo_l432kc/doc/index.rst b/boards/arm/nucleo_l432kc/doc/index.rst index fc9bfc51d08..94d6f6f20f0 100644 --- a/boards/arm/nucleo_l432kc/doc/index.rst +++ b/boards/arm/nucleo_l432kc/doc/index.rst @@ -217,13 +217,13 @@ You can debug an application in the usual way. Here is an example for the :goals: debug .. _Nucleo L432KC website: - http://www.st.com/en/evaluation-tools/nucleo-l432kc.html + https://www.st.com/en/evaluation-tools/nucleo-l432kc.html .. _STM32 Nucleo-32 board User Manual: - http://www.st.com/resource/en/user_manual/dm00231744.pdf + https://www.st.com/resource/en/user_manual/dm00231744.pdf .. _STM32L432KC on www.st.com: - http://www.st.com/en/microcontrollers/stm32l432kc.html + https://www.st.com/en/microcontrollers/stm32l432kc.html .. _STM32L432 reference manual: - http://www.st.com/resource/en/reference_manual/dm00151940.pdf + https://www.st.com/resource/en/reference_manual/dm00151940.pdf diff --git a/boards/arm/nucleo_l432kc/nucleo_l432kc.yaml b/boards/arm/nucleo_l432kc/nucleo_l432kc.yaml index 06cead72758..345fcb7e44f 100644 --- a/boards/arm/nucleo_l432kc/nucleo_l432kc.yaml +++ b/boards/arm/nucleo_l432kc/nucleo_l432kc.yaml @@ -14,3 +14,4 @@ supported: - can - counter - spi +vendor: st diff --git a/boards/arm/nucleo_l433rc_p/doc/index.rst b/boards/arm/nucleo_l433rc_p/doc/index.rst index f4903d59b16..da2660417c0 100644 --- a/boards/arm/nucleo_l433rc_p/doc/index.rst +++ b/boards/arm/nucleo_l433rc_p/doc/index.rst @@ -222,7 +222,7 @@ You can debug an application in the usual way. Here is an example for the :goals: debug .. _Nucleo L433RC-P website: - http://www.st.com/en/evaluation-tools/nucleo-l433rc-p.html + https://www.st.com/en/evaluation-tools/nucleo-l433rc-p.html .. _ST Nucleo L433RC-P User Manual: https://www.st.com/resource/en/user_manual/dm00387966.pdf diff --git a/boards/arm/nucleo_l433rc_p/nucleo_l433rc_p.yaml b/boards/arm/nucleo_l433rc_p/nucleo_l433rc_p.yaml index 94ec419e9a4..ee3a41bce02 100644 --- a/boards/arm/nucleo_l433rc_p/nucleo_l433rc_p.yaml +++ b/boards/arm/nucleo_l433rc_p/nucleo_l433rc_p.yaml @@ -17,3 +17,4 @@ supported: - i2c - arduino_i2c - arduino_spi +vendor: st diff --git a/boards/arm/nucleo_l452re/nucleo_l452re.yaml b/boards/arm/nucleo_l452re/nucleo_l452re.yaml index 49e3d93f39f..0b3aa645bf4 100644 --- a/boards/arm/nucleo_l452re/nucleo_l452re.yaml +++ b/boards/arm/nucleo_l452re/nucleo_l452re.yaml @@ -14,3 +14,4 @@ supported: - can - counter - spi +vendor: st diff --git a/boards/arm/nucleo_l452re/nucleo_l452re_p.yaml b/boards/arm/nucleo_l452re/nucleo_l452re_p.yaml index 0f02e07d1a4..7ca93a9c9bc 100644 --- a/boards/arm/nucleo_l452re/nucleo_l452re_p.yaml +++ b/boards/arm/nucleo_l452re/nucleo_l452re_p.yaml @@ -14,3 +14,4 @@ supported: - can - counter - spi +vendor: st diff --git a/boards/arm/nucleo_l476rg/doc/index.rst b/boards/arm/nucleo_l476rg/doc/index.rst index 765657b6a9e..cfbf949df57 100644 --- a/boards/arm/nucleo_l476rg/doc/index.rst +++ b/boards/arm/nucleo_l476rg/doc/index.rst @@ -231,13 +231,13 @@ You can debug an application in the usual way. Here is an example for the :goals: debug .. _Nucleo L476RG website: - http://www.st.com/en/evaluation-tools/nucleo-l476rg.html + https://www.st.com/en/evaluation-tools/nucleo-l476rg.html .. _STM32 Nucleo-64 board User Manual: - http://www.st.com/resource/en/user_manual/dm00105823.pdf + https://www.st.com/resource/en/user_manual/dm00105823.pdf .. _STM32L476RG on www.st.com: - http://www.st.com/en/microcontrollers/stm32l476rg.html + https://www.st.com/en/microcontrollers/stm32l476rg.html .. _STM32L476 reference manual: - http://www.st.com/resource/en/reference_manual/DM00083560.pdf + https://www.st.com/resource/en/reference_manual/DM00083560.pdf diff --git a/boards/arm/nucleo_l476rg/nucleo_l476rg.yaml b/boards/arm/nucleo_l476rg/nucleo_l476rg.yaml index 6c48781032e..d0330751a75 100644 --- a/boards/arm/nucleo_l476rg/nucleo_l476rg.yaml +++ b/boards/arm/nucleo_l476rg/nucleo_l476rg.yaml @@ -19,3 +19,4 @@ supported: - adc ram: 96 flash: 1024 +vendor: st diff --git a/boards/arm/nucleo_l496zg/doc/index.rst b/boards/arm/nucleo_l496zg/doc/index.rst index 9f7c9959717..43f6e1fdb4c 100644 --- a/boards/arm/nucleo_l496zg/doc/index.rst +++ b/boards/arm/nucleo_l496zg/doc/index.rst @@ -232,13 +232,13 @@ You can debug an application in the usual way. Here is an example for the :goals: debug .. _Nucleo L496ZG website: - http://www.st.com/en/evaluation-tools/nucleo-l496zg.html + https://www.st.com/en/evaluation-tools/nucleo-l496zg.html .. _STM32 Nucleo-144 board User Manual: - http://www.st.com/resource/en/user_manual/dm00368330.pdf + https://www.st.com/resource/en/user_manual/dm00368330.pdf .. _STM32L496ZG on www.st.com: - http://www.st.com/en/microcontrollers/stm32l496zg.html + https://www.st.com/en/microcontrollers/stm32l496zg.html .. _STM32L496 reference manual: - http://www.st.com/resource/en/reference_manual/dm00083560.pdf + https://www.st.com/resource/en/reference_manual/dm00083560.pdf diff --git a/boards/arm/nucleo_l496zg/nucleo_l496zg.yaml b/boards/arm/nucleo_l496zg/nucleo_l496zg.yaml index 9f969025a56..39734163f3d 100644 --- a/boards/arm/nucleo_l496zg/nucleo_l496zg.yaml +++ b/boards/arm/nucleo_l496zg/nucleo_l496zg.yaml @@ -21,3 +21,4 @@ testing: ignore_tags: - net - bluetooth +vendor: st diff --git a/boards/arm/nucleo_l4a6zg/doc/index.rst b/boards/arm/nucleo_l4a6zg/doc/index.rst index 895e55ca546..79c7caca7bb 100644 --- a/boards/arm/nucleo_l4a6zg/doc/index.rst +++ b/boards/arm/nucleo_l4a6zg/doc/index.rst @@ -231,13 +231,13 @@ You can debug an application in the usual way. Here is an example for the :goals: debug .. _Nucleo L4A6ZG website: - http://www.st.com/en/evaluation-tools/nucleo-l4a6zg.html + https://www.st.com/en/evaluation-tools/nucleo-l4a6zg.html .. _STM32 Nucleo-144 board User Manual: - http://www.st.com/resource/en/user_manual/dm00368330.pdf + https://www.st.com/resource/en/user_manual/dm00368330.pdf .. _STM32L4A6ZG on www.st.com: - http://www.st.com/en/microcontrollers-microprocessors/stm32l4a6zg.html + https://www.st.com/en/microcontrollers-microprocessors/stm32l4a6zg.html .. _STM32L4A6 reference manual: - http://www.st.com/resource/en/reference_manual/dm00083560.pdf + https://www.st.com/resource/en/reference_manual/dm00083560.pdf diff --git a/boards/arm/nucleo_l4a6zg/nucleo_l4a6zg.yaml b/boards/arm/nucleo_l4a6zg/nucleo_l4a6zg.yaml index fc671d1dfae..bdc87910a4f 100644 --- a/boards/arm/nucleo_l4a6zg/nucleo_l4a6zg.yaml +++ b/boards/arm/nucleo_l4a6zg/nucleo_l4a6zg.yaml @@ -21,3 +21,4 @@ testing: ignore_tags: - net - bluetooth +vendor: st diff --git a/boards/arm/nucleo_l4r5zi/doc/index.rst b/boards/arm/nucleo_l4r5zi/doc/index.rst index f2d27399913..9adb38a2c59 100644 --- a/boards/arm/nucleo_l4r5zi/doc/index.rst +++ b/boards/arm/nucleo_l4r5zi/doc/index.rst @@ -243,16 +243,16 @@ You should see the following message on the console: Hello World! arm .. _Nucleo L4R5ZI website: - http://www.st.com/en/evaluation-tools/nucleo-l4r5zi.html + https://www.st.com/en/evaluation-tools/nucleo-l4r5zi.html .. _STM32 Nucleo-144 board User Manual: - http://www.st.com/resource/en/user_manual/dm00368330.pdf + https://www.st.com/resource/en/user_manual/dm00368330.pdf .. _STM32L4R5ZI on www.st.com: - http://www.st.com/en/microcontrollers/stm32l4r5zi.html + https://www.st.com/en/microcontrollers/stm32l4r5zi.html .. _STM32L4R5 reference manual: - http://www.st.com/resource/en/reference_manual/DM00310109.pdf + https://www.st.com/resource/en/reference_manual/DM00310109.pdf .. _STM32 ST-LINK utility: - http://www.st.com/content/st_com/en/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-programmers/stsw-link004.html + https://www.st.com/content/st_com/en/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-programmers/stsw-link004.html diff --git a/boards/arm/nucleo_l4r5zi/nucleo_l4r5zi.yaml b/boards/arm/nucleo_l4r5zi/nucleo_l4r5zi.yaml index 5c1cb0e1e76..ee4115fc1e6 100644 --- a/boards/arm/nucleo_l4r5zi/nucleo_l4r5zi.yaml +++ b/boards/arm/nucleo_l4r5zi/nucleo_l4r5zi.yaml @@ -20,3 +20,4 @@ supported: - adc ram: 640 flash: 2048 +vendor: st diff --git a/boards/arm/nucleo_l552ze_q/doc/nucleol552ze_q.rst b/boards/arm/nucleo_l552ze_q/doc/nucleol552ze_q.rst index 37dee841eab..51675477af4 100644 --- a/boards/arm/nucleo_l552ze_q/doc/nucleol552ze_q.rst +++ b/boards/arm/nucleo_l552ze_q/doc/nucleol552ze_q.rst @@ -370,16 +370,16 @@ You can debug an application in the usual way. Here is an example for the :goals: debug .. _Nucleo L552ZE Q website: - http://www.st.com/en/evaluation-tools/nucleo-l552ze-q.html + https://www.st.com/en/evaluation-tools/nucleo-l552ze-q.html .. _STM32 Nucleo-144 board User Manual: - http://www.st.com/resource/en/user_manual/dm00615305.pdf + https://www.st.com/resource/en/user_manual/dm00615305.pdf .. _STM32L552ZE on www.st.com: - http://www.st.com/en/microcontrollers/stm32l552ze.html + https://www.st.com/en/microcontrollers/stm32l552ze.html .. _STM32L552 reference manual: - http://www.st.com/resource/en/reference_manual/DM00346336.pdf + https://www.st.com/resource/en/reference_manual/DM00346336.pdf .. _STM32CubeProgrammer: https://www.st.com/en/development-tools/stm32cubeprog.html diff --git a/boards/arm/nucleo_l552ze_q/nucleo_l552ze_q.yaml b/boards/arm/nucleo_l552ze_q/nucleo_l552ze_q.yaml index 43f12c43465..e0a2c89d389 100644 --- a/boards/arm/nucleo_l552ze_q/nucleo_l552ze_q.yaml +++ b/boards/arm/nucleo_l552ze_q/nucleo_l552ze_q.yaml @@ -14,3 +14,4 @@ supported: - spi ram: 192 flash: 512 +vendor: st diff --git a/boards/arm/nucleo_l552ze_q/nucleo_l552ze_q_ns.yaml b/boards/arm/nucleo_l552ze_q/nucleo_l552ze_q_ns.yaml index 5677f5187d6..1eb62f85b96 100644 --- a/boards/arm/nucleo_l552ze_q/nucleo_l552ze_q_ns.yaml +++ b/boards/arm/nucleo_l552ze_q/nucleo_l552ze_q_ns.yaml @@ -10,3 +10,4 @@ supported: - dac ram: 192 flash: 328 +vendor: st diff --git a/boards/arm/nucleo_u575zi_q/doc/index.rst b/boards/arm/nucleo_u575zi_q/doc/index.rst index 9a6df0c6a50..0de2c364ecf 100644 --- a/boards/arm/nucleo_u575zi_q/doc/index.rst +++ b/boards/arm/nucleo_u575zi_q/doc/index.rst @@ -289,7 +289,7 @@ Debugging ========= Default flasher for this board is openocd. It could be used in the usual way. -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -328,10 +328,10 @@ Note: Check the ``build/tfm`` directory to ensure that the commands required by (which is used for initialization) is available in the PATH. .. _STM32 Nucleo-144 board User Manual: - http://www.st.com/resource/en/user_manual/dm00615305.pdf + https://www.st.com/resource/en/user_manual/dm00615305.pdf .. _STM32U575ZI on www.st.com: - http://www.st.com/en/microcontrollers/stm32u575zi.html + https://www.st.com/en/microcontrollers/stm32u575zi.html .. _STM32U575 reference manual: https://www.st.com/resource/en/reference_manual/rm0456-stm32u575585-armbased-32bit-mcus-stmicroelectronics.pdf diff --git a/boards/arm/nucleo_u575zi_q/nucleo_u575zi_q.yaml b/boards/arm/nucleo_u575zi_q/nucleo_u575zi_q.yaml index 4874beb6561..0c65b8361ff 100644 --- a/boards/arm/nucleo_u575zi_q/nucleo_u575zi_q.yaml +++ b/boards/arm/nucleo_u575zi_q/nucleo_u575zi_q.yaml @@ -22,3 +22,4 @@ supported: - dma ram: 786 flash: 2048 +vendor: st diff --git a/boards/arm/nucleo_u5a5zj_q/CMakeLists.txt b/boards/arm/nucleo_u5a5zj_q/CMakeLists.txt new file mode 100644 index 00000000000..c79a4b7b4e7 --- /dev/null +++ b/boards/arm/nucleo_u5a5zj_q/CMakeLists.txt @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: Apache-2.0 + +if(${ZEPHYR_TOOLCHAIN_VARIANT} STREQUAL "zephyr") + set(COMPILER_FULL_PATH ${ZEPHYR_SDK_INSTALL_DIR}/arm-zephyr-eabi/bin/arm-zephyr-eabi-gcc) +elseif(${ZEPHYR_TOOLCHAIN_VARIANT} STREQUAL "gnuarmemb") + set(COMPILER_FULL_PATH ${GNUARMEMB_TOOLCHAIN_PATH}/bin/arm-none-eabi-gcc) +endif() + +if(CONFIG_BUILD_WITH_TFM) + set_property(GLOBAL APPEND PROPERTY extra_post_build_commands + #Execute post build script postbuild.sh + COMMAND $/postbuild.sh ${COMPILER_FULL_PATH} + ) +endif() diff --git a/boards/arm/nucleo_u5a5zj_q/Kconfig.board b/boards/arm/nucleo_u5a5zj_q/Kconfig.board new file mode 100644 index 00000000000..2a1713e0b4f --- /dev/null +++ b/boards/arm/nucleo_u5a5zj_q/Kconfig.board @@ -0,0 +1,8 @@ +# STM32U5A5ZJ Q Nucleo board configuration + +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_NUCLEO_U5A5ZJ_Q + bool "Nucleo U5A5ZJ Q Development Board" + depends on SOC_STM32U5A5XX diff --git a/boards/arm/nucleo_u5a5zj_q/Kconfig.defconfig b/boards/arm/nucleo_u5a5zj_q/Kconfig.defconfig new file mode 100644 index 00000000000..ab566327264 --- /dev/null +++ b/boards/arm/nucleo_u5a5zj_q/Kconfig.defconfig @@ -0,0 +1,11 @@ +# STM32U5A5ZJ Q Nucleo board configuration + +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_NUCLEO_U5A5ZJ_Q + +config BOARD + default "nucleo_u5a5zj_q" + +endif # BOARD_NUCLEO_U5A5ZJ_Q diff --git a/boards/arm/nucleo_u5a5zj_q/arduino_r3_connector.dtsi b/boards/arm/nucleo_u5a5zj_q/arduino_r3_connector.dtsi new file mode 100644 index 00000000000..be1a9c7abcc --- /dev/null +++ b/boards/arm/nucleo_u5a5zj_q/arduino_r3_connector.dtsi @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + arduino_header: connector { + compatible = "arduino-header-r3"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpioa 3 0>, /* A0 */ + <1 0 &gpioa 2 0>, /* A1 */ + <2 0 &gpioc 3 0>, /* A2 */ + <3 0 &gpiob 0 0>, /* A3 */ + <4 0 &gpioc 1 0>, /* A4 */ + <5 0 &gpioc 0 0>, /* A5 */ + <6 0 &gpiog 8 0>, /* D0 */ + <7 0 &gpiog 7 0>, /* D1 */ + <8 0 &gpiof 15 0>, /* D2 */ + <9 0 &gpioe 13 0>, /* D3 */ + <10 0 &gpiof 14 0>, /* D4 */ + <11 0 &gpioe 11 0>, /* D5 */ + <12 0 &gpioe 9 0>, /* D6 */ + <13 0 &gpiof 13 0>, /* D7 */ + <14 0 &gpiof 12 0>, /* D8 */ + <15 0 &gpiod 15 0>, /* D9 */ + <16 0 &gpiod 14 0>, /* D10 */ + <17 0 &gpioa 7 0>, /* D11 */ + <18 0 &gpioa 6 0>, /* D12 */ + <19 0 &gpioa 5 0>, /* D13 */ + <20 0 &gpiob 9 0>, /* D14 */ + <21 0 &gpiob 8 0>; /* D15 */ + }; +}; + +arduino_i2c: &i2c1 {}; +arduino_spi: &spi1 {}; +arduino_serial: &lpuart1 {}; diff --git a/boards/arm/nucleo_u5a5zj_q/board.cmake b/boards/arm/nucleo_u5a5zj_q/board.cmake new file mode 100644 index 00000000000..55861552c8e --- /dev/null +++ b/boards/arm/nucleo_u5a5zj_q/board.cmake @@ -0,0 +1,14 @@ +board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") + +board_runner_args(openocd "--tcl-port=6666") +board_runner_args(openocd --cmd-pre-init "gdb_report_data_abort enable") +board_runner_args(openocd "--no-halt") + +board_runner_args(pyocd "--target=stm32u5a5zjtx") + +board_runner_args(jlink "--device=STM32U5A5ZJ" "--reset-after-load") + +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/arm/nucleo_u5a5zj_q/doc/index.rst b/boards/arm/nucleo_u5a5zj_q/doc/index.rst new file mode 100644 index 00000000000..f877be5c168 --- /dev/null +++ b/boards/arm/nucleo_u5a5zj_q/doc/index.rst @@ -0,0 +1,377 @@ +.. _nucleo_u5a5zj_q_board: + +ST Nucleo U5A5ZJ Q +################## + +Overview +******** + +The Nucleo U5A5ZJ Q board, featuring an ARM Cortex-M33 based STM32U5A5ZJ MCU, +provides an affordable and flexible way for users to try out new concepts and +build prototypes by choosing from the various combinations of performance and +power consumption features. Here are some highlights of the Nucleo U5A5ZJ Q +board: + + +- STM32U5A5ZJ microcontroller in LQFP144 package +- Internal SMPS to generate V core logic supply +- Two types of extension resources: + + - Arduino Uno V3 connectivity + - ST morpho extension pin headers for full access to all STM32 I/Os + +- On-board ST-LINK/V3E debugger/programmer +- Flexible board power supply: + + - USB VBUS or external source(3.3V, 5V, 7 - 12V) + - ST-Link V3E + +- Three users LEDs +- Two push-buttons: USER and RESET +- USB Type-C ™ Sink device FS + +Hardware +******** + +The STM32U5A5xx devices are an ultra-low-power microcontrollers family (STM32U5 +Series) based on the high-performance Arm® Cortex®-M33 32-bit RISC core. +They operate at a frequency of up to 160 MHz. + +- Includes ST state-of-the-art patented technology +- Ultra-low-power with FlexPowerControl: + + - 1.71 V to 3.6 V power supply + - -40 °C to +85/125 °C temperature range + - Low-power background autonomous mode (LPBAM): autonomous peripherals with + DMA, functional down to Stop 2 mode + - VBAT mode: supply for RTC, 32 x 32-bit backup registers and 2-Kbyte backup SRAM + - 150 nA Shutdown mode (24 wake-up pins) + - 195 nA Standby mode (24 wake-up pins) + - 480 nA Standby mode with RTC + - 2 µA Stop 3 mode with 40-Kbyte SRAM + - 8.2 µA Stop 3 mode with 2.5-Mbyte SRAM + - 4.65 µA Stop 2 mode with 40-Kbyte SRAM + - 17.5 µA Stop 2 mode with 2.5-Mbyte SRAM + - 18.5 µA/MHz Run mode at 3.3 V + +- Core: + + - Arm® 32-bit Cortex®-M33 CPU with TrustZone®, MPU, DSP, + and FPU ART Accelerator + - 32-Kbyte ICACHE allowing 0-wait-state execution from flash and external + memories: frequency up to 160 MHz, 240 DMIPS + - 16-Kbyte DCACHE1 for external memories + +- Power management: + + - Embedded regulator (LDO) and SMPSstep-down converter supporting switch + on-the-fly and voltage scaling + +- Benchmarks: + + - 1.5 DMIPS/MHz (Drystone 2.1) + - 655 CoreMark® (4.09 CoreMark®/MHz) + - 369 ULPMark™-CP + - 89 ULPMark™-PP + - 47.2 ULPMark™-CM + - 120000 SecureMark™-TLS + +- Memories: + + - 4-Mbyte flash memory with ECC, 2 banks readwhile-write, including 512 Kbytes + with 100 kcycles + - With SRAM3 ECC off: 2514-Kbyte RAM including 66 Kbytes with ECC + - With SRAM3 ECC on: 2450-Kbyte RAMincluding 322 Kbytes with ECC + - External memory interface supporting SRAM,PSRAM, NOR, NAND, and FRAM memories + - 2 Octo-SPI memory interfaces + - 16-bit HSPI memory interface up to 160 MHz + +- Rich graphic features: + + - Neo-Chrom GPU (GPU2D) accelerating any angle rotation, scaling, and + perspective correct texture mapping + - 16-Kbyte DCACHE2 + - Chrom-ART Accelerator (DMA2D) for smoothmotion and transparency effects + - Chrom-GRC (GFXMMU) allowing up to 20 % of graphic resources optimization + - MIPI® DSI host controller with two DSI lanes running at up to 500 Mbit/s each + - LCD-TFT controller (LTDC) + - Digital camera interface + +- General-purpose input/outputs: + + - Up to 156 fast I/Os with interrupt capability most 5V-tolerant and + up to 14 I/Os with independent supply down to 1.08 V + +- Clock management: + + - 4 to 50 MHz crystal oscillator + - 32 kHz crystal oscillator for RTC (LSE) + - Internal 16 MHz factory-trimmed RC (± 1 %) + - Internal low-power 32 kHz RC (± 5 %) + - 2 internal multispeed 100 kHz to 48 MHz oscillators, including one + autotrimmed by LSE (better than ± 0.25 % accuracy) + - Internal 48 MHz + - 5 PLLs for system clock, USB, audio, ADC, DSI + +- Security and cryptography: + + - SESIP3 and PSA Level 3 Certified Assurance Target + - Arm® TrustZone® and securable I/Os, memories, and peripherals + - Flexible life cycle scheme with RDP andpassword-protected debug + - Root of trust thanks to unique boot entry and secure hide-protection area (HDP) + - Secure firmware installation (SFI) thanks to embedded root secure services (RSS) + - Secure data storage with hardware unique key (HUK) + - Secure firmware upgrade support with TF-M + - 2 AES coprocessors including one with DPA resistance + - Public key accelerator, DPA resistant + - On-the-fly decryption of Octo-SPI external memories + - HASH hardware accelerator + - True random number generator, NIST SP800-90B compliant + - 96-bit unique ID + - 512-byte OTP (one-time programmable) + - Active tampers + +- Up to 17 timers, 2 watchdogs and RTC: + + - 19 timers: 2 16-bit advanced motor-control, 4 32-bit, 3 16-bit general + purpose, 2 16-bit basic, 4 low-power 16-bit (available in Stop mode), + 2 SysTick timers, and 2 watchdogs + - RTC with hardware calendar, alarms, and calibration + +- Up to 25 communication peripherals: + + - 1 USB Type-C®/USB power delivery controller + - 1 USB OTG high-speed with embedded PHY + - 2 SAIs (serial audio interface) + - 6 I2C FM+(1 Mbit/s), SMBus/PMBus™ + - 7 USARTs (ISO 7816, LIN, IrDA, modem) + - 3 SPIs (6x SPIs with OCTOSPI/HSPI) + - 1 CAN FD controller + - 2 SDMMC interfaces + - 1 multifunction digital filter (6 filters) + 1 audio digital filter + with sound-activity detection + - Parallel synchronous slave interface + +- Mathematical coprocessor: + + - CORDIC for trigonometric functions acceleration + - FMAC (filter mathematical accelerator) + +- Rich analog peripherals (independent supply): + + - 2 14-bit ADC 2.5-Msps with hardware oversampling + - 1 12-bit ADC 2.5-Msps, with hardware oversampling, autonomous in Stop 2 mode + - 12-bit DAC (2 channels), low-power sample, and hold, autonomous in Stop 2 mode + - 2 operational amplifiers with built-in PGA + - 2 ultra-low-power comparators + +- ECOPACK2 compliant packages + +More information about STM32U5A5ZJ can be found here: + +- `STM32U5A5ZJ on www.st.com`_ +- `STM32U5A5 reference manual`_ + +Supported Features +================== + +The Zephyr nucleo_u5a5zj_q board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| CAN/CANFD | on-chip | canbus | ++-----------+------------+-------------------------------------+ +| CLOCK | on-chip | reset and clock control | ++-----------+------------+-------------------------------------+ +| DAC | on-chip | DAC Controller | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++-----------+------------+-------------------------------------+ +| SPI | on-chip | spi | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ +| WATCHDOG | on-chip | independent watchdog | ++-----------+------------+-------------------------------------+ +| BKP SRAM | on-chip | Backup SRAM | ++-----------+------------+-------------------------------------+ +| RNG | on-chip | True Random number generator | ++-----------+------------+-------------------------------------+ + + +Other hardware features are not yet supported on this Zephyr port. + +The default configuration can be found in the defconfig file: +``boards/arm/nucleo_u5a5zj_q/nucleo_u5a5zj_q_defconfig`` + + +Connections and IOs +=================== + +Nucleo U5A5ZJ Q Board has 10 GPIO controllers. These controllers are responsible +for pin muxing, input/output, pull-up, etc. + +For mode details please refer to `STM32 Nucleo-144 board User Manual`_. + +Default Zephyr Peripheral Mapping: +---------------------------------- + + +- CAN/CANFD_TX: PD1 +- CAN/CANFD_RX: PD0 +- DAC1_OUT1 : PA4 +- I2C_1_SCL : PB8 +- I2C_1_SDA : PB9 +- I2C_2_SCL : PF1 +- I2C_2_SDA : PF0 +- LD1 : PC7 +- LD2 : PB7 +- LD3 : PG2 +- LPUART_1_TX : PG7 +- LPUART_1_RX : PG8 +- SPI_1_NSS : PA4 +- SPI_1_SCK : PA5 +- SPI_1_MISO : PA6 +- SPI_1_MOSI : PA7 +- UART_1_TX : PA9 +- UART_1_RX : PA10 +- UART_2_TX : PD5 +- UART_2_RX : PD6 +- USER_PB : PC13 + +System Clock +------------ + +Nucleo U5A5ZJ Q System Clock could be driven by internal or external oscillator, +as well as main PLL clock. By default System clock is driven by PLL clock at +160MHz, driven by 4MHz medium speed internal oscillator. + +Serial Port +----------- + +Nucleo U5A5ZJ Q board has 6 U(S)ARTs. The Zephyr console output is assigned to +USART1. Default settings are 115200 8N1. + + +Backup SRAM +----------- + +In order to test backup SRAM you may want to disconnect VBAT from VDD. You can +do it by removing ``SB50`` jumper on the back side of the board. + + +Programming and Debugging +************************* + +Nucleo U5A5ZJ-Q board includes an ST-LINK/V3 embedded debug tool interface. +This probe allows to flash the board using various tools. + +Flashing +======== + +Board is configured to be flashed using west STM32CubeProgrammer runner. +Installation of `STM32CubeProgrammer`_ is then required to flash the board. + +Alternatively, openocd (provided in Zephyr SDK), JLink and pyocd can also be +used to flash and debug the board if west is told to use it as runner, +which can be done by passing either ``-r openocd``, ``-r jlink`` or ``-r pyocd``. + +For pyocd additional target information needs to be installed. +This can be done by executing the following commands. + +.. code-block:: console + + $ pyocd pack --update + $ pyocd pack --install stm32u5 + + +Flashing an application to Nucleo U5A5ZJ Q +------------------------------------------ + +Connect the Nucleo U5A5ZJ Q to your host computer using the USB port. +Then build and flash an application. Here is an example for the +:ref:`hello_world` application. + +Run a serial host program to connect with your Nucleo board: + +.. code-block:: console + + $ minicom -D /dev/ttyACM0 + +Then build and flash the application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: nucleo_u5a5zj_q + :goals: build flash + +You should see the following message on the console: + +.. code-block:: console + + Hello World! arm + +Debugging +========= + +Default flasher for this board is openocd. It could be used in the usual way. +Here is an example for the :zephyr:code-sample:`blinky` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: nucleo_u5a5zj_q + :goals: debug + +Building a secure/non-secure with Arm ® TrustZone ® +=========================================================== + +The TF-M applications can be run on this board, thanks to its Arm ® TrustZone ® +support. +In TF-M configuration, Zephyr is run on the non-secure domain. A non-secure image +can be generated using ``nucleo_u5a5zj_q_ns`` as build target. + +.. code-block:: bash + + $ west build -b nucleo_u5a5zj_q_ns path/to/source/directory + +Note: When building the ``*_ns`` image with TF-M, ``build/tfm/postbuild.sh`` bash script +is run automatically in a post-build step to make some required flash layout changes. + +Once the build is completed, run the following script to initialize the option bytes. + +.. code-block:: bash + + $ build/tfm/regression.sh + +Finally, to flash the board, run: + +.. code-block:: bash + + $ west flash + +Note: Check the ``build/tfm`` directory to ensure that the commands required by these scripts +(``readlink``, etc.) are available on your system. Please also check ``STM32_Programmer_CLI`` +(which is used for initialization) is available in the PATH. + +.. _STM32 Nucleo-144 board User Manual: + https://www.st.com/resource/en/user_manual/um2861-stm32u5-nucleo144-board-mb1549-stmicroelectronics.pdf + +.. _STM32U5A5ZJ on www.st.com: + https://www.st.com/en/microcontrollers/stm32u5a5zj.html + +.. _STM32U5A5 reference manual: + https://www.st.com/resource/en/reference_manual/rm0456-stm32u5-series-armbased-32bit-mcus-stmicroelectronics.pdf + +.. _STM32CubeProgrammer: + https://www.st.com/en/development-tools/stm32cubeprog.html + +.. _STMicroelectronics customized version of OpenOCD: + https://github.com/STMicroelectronics/OpenOCD diff --git a/boards/arm/nucleo_u5a5zj_q/nucleo_u5a5zj_q-common.dtsi b/boards/arm/nucleo_u5a5zj_q/nucleo_u5a5zj_q-common.dtsi new file mode 100644 index 00000000000..d0ba893c873 --- /dev/null +++ b/boards/arm/nucleo_u5a5zj_q/nucleo_u5a5zj_q-common.dtsi @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "arduino_r3_connector.dtsi" +#include + +/ { + leds: leds { + compatible = "gpio-leds"; + green_led_1: led_1 { + gpios = <&gpioc 7 GPIO_ACTIVE_HIGH>; + label = "User LD1"; + }; + blue_led_1: led_2 { + gpios = <&gpiob 7 GPIO_ACTIVE_HIGH>; + label = "User LD2"; + }; + red_led_1: led_3 { + gpios = <&gpiog 2 GPIO_ACTIVE_HIGH>; + label = "User LD3"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button: button { + label = "User"; + gpios = <&gpioc 13 GPIO_ACTIVE_HIGH>; + zephyr,code = ; + }; + }; + + pwmleds: pwmleds { + compatible = "pwm-leds"; + status = "disabled"; + + pwm_led_1: green_led_1 { + pwms = <&pwm3 2 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + label = "green led"; + }; + + pwm_led_2: blue_led_1 { + pwms = <&pwm4 2 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + label = "blue led"; + }; + }; +}; + +&clk_hsi48 { + status = "okay"; +}; + +&clk_lse { + status = "okay"; +}; + +&clk_msis { + status = "okay"; + msi-range = <4>; + msi-pll-mode; +}; + +&pll1 { + div-m = <1>; + mul-n = <80>; + div-q = <2>; + div-r = <2>; + clocks = <&clk_msis>; + status = "okay"; +}; + +&rcc { + clocks = <&pll1>; + clock-frequency = ; + ahb-prescaler = <1>; + apb1-prescaler = <1>; + apb2-prescaler = <1>; + apb3-prescaler = <1>; +}; + +&lpuart1 { + pinctrl-0 = <&lpuart1_tx_pg7 &lpuart1_rx_pg8>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&usart2 { + pinctrl-0 = <&usart2_tx_pd5 &usart2_rx_pd6>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&i2c1 { + pinctrl-0 = <&i2c1_scl_pb8 &i2c1_sda_pb9>; + pinctrl-names = "default"; + status = "okay"; + clock-frequency = ; +}; + +&i2c2 { + pinctrl-0 = <&i2c2_scl_pf1 &i2c2_sda_pf0>; + pinctrl-names = "default"; + status = "okay"; + clock-frequency = ; +}; + +&spi1 { + pinctrl-0 = <&spi1_nss_pe12 &spi1_sck_pa5 + &spi1_miso_pa6 &spi1_mosi_pa7>; + pinctrl-names = "default"; + status = "okay"; +}; + +&dac1 { + pinctrl-0 = <&dac1_out1_pa4>; + pinctrl-names = "default"; + status = "okay"; +}; + +&adc1 { + pinctrl-0 = <&adc1_in1_pc0>; + pinctrl-names = "default"; + st,adc-clock-source = ; + st,adc-prescaler = <4>; + status = "okay"; +}; + +&adc4 { + pinctrl-0 = <&adc4_in18_pb0>; + pinctrl-names = "default"; + st,adc-clock-source = ; + st,adc-prescaler = <4>; + status = "okay"; +}; + +&timers3 { + st,prescaler = <10000>; + status = "okay"; + + pwm3: pwm { + pinctrl-0 = <&tim3_ch2_pc7>; + pinctrl-names = "default"; + status = "okay"; + }; +}; + +&timers4 { + st,prescaler = <10000>; + status = "okay"; + + pwm4: pwm { + pinctrl-0 = <&tim4_ch2_pb7>; + pinctrl-names = "default"; + status = "okay"; + }; +}; + +&iwdg { + status = "okay"; +}; + +&rng { + status = "okay"; +}; + +&fdcan1 { + clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>, + <&rcc STM32_SRC_PLL1_Q FDCAN1_SEL(1)>; + pinctrl-0 = <&fdcan1_rx_pd0 &fdcan1_tx_pd1>; + pinctrl-names = "default"; + bus-speed = <125000>; + bus-speed-data = <1000000>; + status = "okay"; +}; + +&vref1 { + status = "okay"; +}; + +&vbat4 { + status = "okay"; +}; diff --git a/boards/arm/nucleo_u5a5zj_q/nucleo_u5a5zj_q.dts b/boards/arm/nucleo_u5a5zj_q/nucleo_u5a5zj_q.dts new file mode 100644 index 00000000000..c9296ccab97 --- /dev/null +++ b/boards/arm/nucleo_u5a5zj_q/nucleo_u5a5zj_q.dts @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include "nucleo_u5a5zj_q-common.dtsi" + +/ { + model = "STMicroelectronics STM32U5A5ZJ-NUCLEO-Q board"; + compatible = "st,stm32u5a5zj-nucleo-q"; + + #address-cells = <1>; + #size-cells = <1>; + + chosen { + zephyr,console = &usart1; + zephyr,shell-uart = &usart1; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,canbus = &fdcan1; + zephyr,code-partition = &slot0_partition; + }; + + aliases { + led0 = &blue_led_1; + sw0 = &user_button; + pwm-led0 = &pwm_led_1; + pwm-led1 = &pwm_led_2; + watchdog0 = &iwdg; + volt-sensor0 = &vref1; + volt-sensor1 = &vbat4; + }; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* + * Following flash partition is dedicated to the use of nucleo_u5a5zj_q + * with TZEN=0 (so w/o TFM). + */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 DT_SIZE_K(64)>; + }; + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 DT_SIZE_K(1952)>; + }; + slot1_partition: partition@1f8000 { + label = "image-1"; + reg = <0x001f8000 DT_SIZE_K(1960)>; + }; + storage_partition: partition@3e2000 { + label = "storage"; + reg = <0x003f0000 DT_SIZE_K(120)>; + }; + + }; +}; + +&usart1 { + pinctrl-0 = <&usart1_tx_pa9 &usart1_rx_pa10>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&gpdma1 { + status = "okay"; +}; diff --git a/boards/arm/nucleo_u5a5zj_q/nucleo_u5a5zj_q.yaml b/boards/arm/nucleo_u5a5zj_q/nucleo_u5a5zj_q.yaml new file mode 100644 index 00000000000..4d74f6a13b8 --- /dev/null +++ b/boards/arm/nucleo_u5a5zj_q/nucleo_u5a5zj_q.yaml @@ -0,0 +1,24 @@ +identifier: nucleo_u5a5zj_q +name: ST Nucleo U5A5ZJ Q +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb +supported: + - arduino_gpio + - arduino_i2c + - arduino_serial + - arduino_spi + - can + - adc + - dac + - gpio + - i2c + - spi + - usart + - watchdog + - backup_sram + - dma +ram: 2450 +flash: 4096 diff --git a/boards/arm/nucleo_u5a5zj_q/nucleo_u5a5zj_q_defconfig b/boards/arm/nucleo_u5a5zj_q/nucleo_u5a5zj_q_defconfig new file mode 100644 index 00000000000..3134af0b6a7 --- /dev/null +++ b/boards/arm/nucleo_u5a5zj_q/nucleo_u5a5zj_q_defconfig @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_STM32U5X=y +CONFIG_SOC_STM32U5A5XX=y + +# enable uart driver +CONFIG_SERIAL=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable clock +CONFIG_CLOCK_CONTROL=y + +# console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable HW stack protection +CONFIG_HW_STACK_PROTECTION=y + +# enable pin controller +CONFIG_PINCTRL=y diff --git a/boards/arm/nucleo_u5a5zj_q/support/openocd.cfg b/boards/arm/nucleo_u5a5zj_q/support/openocd.cfg new file mode 100644 index 00000000000..ae4ce0a8816 --- /dev/null +++ b/boards/arm/nucleo_u5a5zj_q/support/openocd.cfg @@ -0,0 +1,44 @@ +source [find interface/stlink-dap.cfg] + +set WORKAREASIZE 0x8000 + +transport select "dapdirect_swd" + +set CHIPNAME STM32U5A5ZJTxQ +set BOARDNAME NUCLEO-U5A5ZJ-Q + +# Enable debug when in low power modes +set ENABLE_LOW_POWER 1 + +# Stop Watchdog counters when halt +set STOP_WATCHDOG 1 + +# STlink Debug clock frequency +set CLOCK_FREQ 8000 + +# Reset configuration +# use hardware reset, connect under reset +# connect_assert_srst needed if low power mode application running (WFI...) +reset_config srst_only srst_nogate connect_assert_srst +set CONNECT_UNDER_RESET 1 +set CORE_RESET 0 + +# ACCESS PORT NUMBER +set AP_NUM 0 +# GDB PORT +set GDB_PORT 3333 + +# BCTM CPU variables + +source [find target/stm32u5x.cfg] + +$_TARGETNAME configure -event gdb-attach { + echo "Debugger attaching: halting execution" + reset halt + gdb_breakpoint_override hard +} + +$_TARGETNAME configure -event gdb-detach { + echo "Debugger detaching: resuming execution" + resume +} diff --git a/boards/arm/nucleo_wb55rg/Kconfig.defconfig b/boards/arm/nucleo_wb55rg/Kconfig.defconfig index 1a7ffcff0ef..66c77220d3a 100644 --- a/boards/arm/nucleo_wb55rg/Kconfig.defconfig +++ b/boards/arm/nucleo_wb55rg/Kconfig.defconfig @@ -13,8 +13,4 @@ choice BT_HCI_BUS_TYPE depends on BT endchoice -# LPTIM clocked by LSE, force tick freq to 4096 for tick accuracy -config SYS_CLOCK_TICKS_PER_SEC - default 4096 if STM32_LPTIM_TIMER - endif # BOARD_NUCLEO_WB55RG diff --git a/boards/arm/nucleo_wb55rg/doc/nucleo_wb55rg.rst b/boards/arm/nucleo_wb55rg/doc/nucleo_wb55rg.rst index fe03035e9e8..835b99f227f 100644 --- a/boards/arm/nucleo_wb55rg/doc/nucleo_wb55rg.rst +++ b/boards/arm/nucleo_wb55rg/doc/nucleo_wb55rg.rst @@ -288,7 +288,7 @@ Debugging ========= You can debug an application in the usual way. Here is an example for the -:ref:`blinky-sample` application. +:zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/nucleo_wb55rg/nucleo_wb55rg.dts b/boards/arm/nucleo_wb55rg/nucleo_wb55rg.dts index b92c921df38..eed2cef9368 100644 --- a/boards/arm/nucleo_wb55rg/nucleo_wb55rg.dts +++ b/boards/arm/nucleo_wb55rg/nucleo_wb55rg.dts @@ -202,6 +202,10 @@ zephyr_udc0: &usb { status = "okay"; }; +&aes1 { + status = "okay"; +}; + &flash0 { partitions { compatible = "fixed-partitions"; diff --git a/boards/arm/nucleo_wb55rg/nucleo_wb55rg.yaml b/boards/arm/nucleo_wb55rg/nucleo_wb55rg.yaml index a4a8e181077..f455356048c 100644 --- a/boards/arm/nucleo_wb55rg/nucleo_wb55rg.yaml +++ b/boards/arm/nucleo_wb55rg/nucleo_wb55rg.yaml @@ -22,3 +22,4 @@ supported: - arduino_spi - usb_device - nvs +vendor: st diff --git a/boards/arm/nucleo_wb55rg/nucleo_wb55rg_defconfig b/boards/arm/nucleo_wb55rg/nucleo_wb55rg_defconfig index 9fdd732848e..88f9da2ff18 100644 --- a/boards/arm/nucleo_wb55rg/nucleo_wb55rg_defconfig +++ b/boards/arm/nucleo_wb55rg/nucleo_wb55rg_defconfig @@ -22,3 +22,6 @@ CONFIG_HW_STACK_PROTECTION=y # enable pin controller CONFIG_PINCTRL=y + +# LSE defined as LPTIM clock source by the DTS +CONFIG_STM32_LPTIM_CLOCK_LSE=y diff --git a/boards/arm/nucleo_wba52cg/Kconfig.defconfig b/boards/arm/nucleo_wba52cg/Kconfig.defconfig index 36f0e77818b..dfdac1bba98 100644 --- a/boards/arm/nucleo_wba52cg/Kconfig.defconfig +++ b/boards/arm/nucleo_wba52cg/Kconfig.defconfig @@ -13,8 +13,4 @@ config SPI_STM32_INTERRUPT default y depends on SPI -# LPTIM clocked by LSE, force tick freq to 4096 for tick accuracy -config SYS_CLOCK_TICKS_PER_SEC - default 4096 if STM32_LPTIM_TIMER - endif # BOARD_NUCLEO_WBA52CG diff --git a/boards/arm/nucleo_wba52cg/doc/nucleo_wba52cg.rst b/boards/arm/nucleo_wba52cg/doc/nucleo_wba52cg.rst index 624d1ab1b10..db45d48a7fa 100644 --- a/boards/arm/nucleo_wba52cg/doc/nucleo_wba52cg.rst +++ b/boards/arm/nucleo_wba52cg/doc/nucleo_wba52cg.rst @@ -222,17 +222,37 @@ Default settings are 115200 8N1. Programming and Debugging ************************* +Nucleo WBA52CG board includes an ST-LINK/V3 embedded debug tool interface. +It could be used for flash and debug using either OpenOCD or STM32Cube ecosystem tools. + +OpenOCD Support +=============== + +For now, openocd support is available only on upstream OpenOCD. You can check +`OpenOCD official Github mirror`_. +In order to use it, you should clone and compile it following usual README +guidelines. +Once it is done, you can set the OPENOCD and OPENOCD_DEFAULT_PATH variables in +:zephyr_file:`boards/arm/nucleo_wba52cg/board.cmake` to point the build +to the paths of the OpenOCD binary and its scripts, before +including the common openocd.board.cmake file: + + .. code-block:: none + + set(OPENOCD "/src/openocd" CACHE FILEPATH "" FORCE) + set(OPENOCD_DEFAULT_PATH /tcl) + include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) + Flashing ======== -Nucleo WBA52CG board includes an ST-LINK/V3 embedded debug tool interface. -For now, only STM32CubeProgrammer is available for flashing. It is configured -as flashing tool by default. +STM32CubeProgrammer is configured as flashing tool by default. +If available OpenOCD could be used. Same process applies with both tools. Flashing an application to Nucleo WBA52CG ----------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -244,6 +264,21 @@ You will see the LED blinking every second. Debugging ========= +Debugging using OpenOCD +----------------------- + +You can debug an application in the usual way using OpenOCD. Here is an example for the +:zephyr:code-sample:`blinky` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: nucleo_wba52cg + :maybe-skip-config: + :goals: debug + +Debugging using STM32CubeIDE +---------------------------- + You can debug an application using a STM32WBA compatible version of STM32CubeIDE. For that: - Create an empty STM32WBA project by going to File > New > STM32 project @@ -265,3 +300,6 @@ For that: .. _STM32WBA52CG reference manual: https://www.st.com/resource/en/reference_manual/rm0493-multiprotocol-wireless-bluetooth-lowenergy-armbased-32bit-mcu-stmicroelectronics.pdf + +.. _OpenOCD official Github mirror: + https://github.com/openocd-org/openocd/commit/870769b0ba9f4dae6ada9d8b1a40d75bd83aaa06 diff --git a/boards/arm/nucleo_wba52cg/nucleo_wba52cg.dts b/boards/arm/nucleo_wba52cg/nucleo_wba52cg.dts index 0a6e03c7d6c..df2707f4eeb 100644 --- a/boards/arm/nucleo_wba52cg/nucleo_wba52cg.dts +++ b/boards/arm/nucleo_wba52cg/nucleo_wba52cg.dts @@ -82,6 +82,13 @@ status = "okay"; }; +&rtc { + status = "okay"; + clocks = <&rcc STM32_CLOCK_BUS_APB7 0x00200000>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; + prescaler = <32768>; +}; + &usart1 { pinctrl-0 = <&usart1_tx_pb12 &usart1_rx_pa8>; pinctrl-names = "default"; @@ -89,6 +96,13 @@ status = "okay"; }; +&lpuart1 { + pinctrl-0 = <&lpuart1_tx_pb5 &lpuart1_rx_pa10>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + &spi1 { pinctrl-0 = <&spi1_nss_pa12 &spi1_sck_pb4 &spi1_miso_pb3 &spi1_mosi_pa15>; diff --git a/boards/arm/nucleo_wba52cg/nucleo_wba52cg.yaml b/boards/arm/nucleo_wba52cg/nucleo_wba52cg.yaml index 22e888c7ac3..8e075b44ae1 100644 --- a/boards/arm/nucleo_wba52cg/nucleo_wba52cg.yaml +++ b/boards/arm/nucleo_wba52cg/nucleo_wba52cg.yaml @@ -15,5 +15,7 @@ supported: - arduino_gpio - arduino_i2c - arduino_spi + - counter ram: 128 flash: 1024 +vendor: st diff --git a/boards/arm/nucleo_wba52cg/nucleo_wba52cg_defconfig b/boards/arm/nucleo_wba52cg/nucleo_wba52cg_defconfig index 9b917b0fc69..ffadf13e845 100644 --- a/boards/arm/nucleo_wba52cg/nucleo_wba52cg_defconfig +++ b/boards/arm/nucleo_wba52cg/nucleo_wba52cg_defconfig @@ -24,3 +24,6 @@ CONFIG_HW_STACK_PROTECTION=y # enable pin controller CONFIG_PINCTRL=y + +# LSE defined as LPTIM clock source by the DTS +CONFIG_STM32_LPTIM_CLOCK_LSE=y diff --git a/boards/arm/nucleo_wba52cg/support/openocd.cfg b/boards/arm/nucleo_wba52cg/support/openocd.cfg new file mode 100644 index 00000000000..10647e20ad8 --- /dev/null +++ b/boards/arm/nucleo_wba52cg/support/openocd.cfg @@ -0,0 +1,26 @@ +# Note: Using OpenOCD using nucloe_wba52cg requires using STMicroelectronics +# openocd fork. See board documentation for more information + +source [find interface/stlink-dap.cfg] + +set WORKAREASIZE 0x8000 + +transport select "dapdirect_swd" + +# Enable debug when in low power modes +set ENABLE_LOW_POWER 1 + +# Stop Watchdog counters when halt +set STOP_WATCHDOG 1 + +# STlink Debug clock frequency +set CLOCK_FREQ 8000 + +# Reset configuration +# use hardware reset, connect under reset +# connect_assert_srst needed if low power mode application running (WFI...) +reset_config srst_only srst_nogate + +source [find target/stm32wbax.cfg] + +gdb_memory_map disable diff --git a/boards/arm/nucleo_wl55jc/Kconfig.defconfig b/boards/arm/nucleo_wl55jc/Kconfig.defconfig index 197453cc03e..981e20f0306 100644 --- a/boards/arm/nucleo_wl55jc/Kconfig.defconfig +++ b/boards/arm/nucleo_wl55jc/Kconfig.defconfig @@ -8,7 +8,4 @@ if BOARD_NUCLEO_WL55JC config BOARD default "nucleo_wl55jc" -config SYS_CLOCK_TICKS_PER_SEC - default 4000 if STM32_LPTIM_TIMER - endif # BOARD_NUCLEO_WL55JC diff --git a/boards/arm/nucleo_wl55jc/doc/nucleo_wl55jc.rst b/boards/arm/nucleo_wl55jc/doc/nucleo_wl55jc.rst index 4b0a2937b05..3d569753f15 100644 --- a/boards/arm/nucleo_wl55jc/doc/nucleo_wl55jc.rst +++ b/boards/arm/nucleo_wl55jc/doc/nucleo_wl55jc.rst @@ -307,7 +307,7 @@ Debugging ========= You can debug an application in the usual way. Here is an example for the -:ref:`blinky-sample` application. +:zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/nucleo_wl55jc/nucleo_wl55jc.dts b/boards/arm/nucleo_wl55jc/nucleo_wl55jc.dts index 48822f2fe13..deff3a96cdc 100644 --- a/boards/arm/nucleo_wl55jc/nucleo_wl55jc.dts +++ b/boards/arm/nucleo_wl55jc/nucleo_wl55jc.dts @@ -8,6 +8,7 @@ #include #include #include "arduino_r3_connector.dtsi" +#include "st_morpho_connector.dtsi" #include / { diff --git a/boards/arm/nucleo_wl55jc/nucleo_wl55jc.yaml b/boards/arm/nucleo_wl55jc/nucleo_wl55jc.yaml index 93be2f6ed91..b741d372805 100644 --- a/boards/arm/nucleo_wl55jc/nucleo_wl55jc.yaml +++ b/boards/arm/nucleo_wl55jc/nucleo_wl55jc.yaml @@ -23,3 +23,4 @@ supported: - watchdog - nvs - lora +vendor: st diff --git a/boards/arm/nucleo_wl55jc/st_morpho_connector.dtsi b/boards/arm/nucleo_wl55jc/st_morpho_connector.dtsi new file mode 100644 index 00000000000..c2e2a06bb3e --- /dev/null +++ b/boards/arm/nucleo_wl55jc/st_morpho_connector.dtsi @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023 Marcin Niestroj + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + st_morpho_header: st-morpho-header { + compatible = "st-morpho-header"; + #gpio-cells = <2>; + gpio-map-mask = ; + gpio-map-pass-thru = <0x0 GPIO_DT_FLAGS_MASK>; + gpio-map = , + , /* shared with SWD connected to STLINK */ + , /* shared with SWD connected to STLINK */ + , + , + , + , + , + , + , + , + , + , + + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , /* SB7=ON, SB2=OFF, SB6=OFF */ + , + , /* SB9=ON, SB4=OFF, SB10=OFF */ + ; + }; +}; diff --git a/boards/arm/numaker_pfm_m467/numaker_pfm_m467-pinctrl.dtsi b/boards/arm/numaker_pfm_m467/numaker_pfm_m467-pinctrl.dtsi index 8aff684b1a9..b6b8f3eb508 100644 --- a/boards/arm/numaker_pfm_m467/numaker_pfm_m467-pinctrl.dtsi +++ b/boards/arm/numaker_pfm_m467/numaker_pfm_m467-pinctrl.dtsi @@ -24,4 +24,29 @@ ; }; }; + + /* CAN TX/RX --> PJ10/PJ11 */ + canfd0_default: canfd0_default { + group0 { + pinmux = , + ; + }; + }; + + /* EMAC multi-function pins for MDIO, TX, REFCLK, RX pins */ + emac_default: emac_default { + group0 { + pinmux = , + , + , + , + , + , + , + , + , + , + ; + }; + }; }; diff --git a/boards/arm/numaker_pfm_m467/numaker_pfm_m467.dts b/boards/arm/numaker_pfm_m467/numaker_pfm_m467.dts index 860ca7579f1..da3350d9494 100644 --- a/boards/arm/numaker_pfm_m467/numaker_pfm_m467.dts +++ b/boards/arm/numaker_pfm_m467/numaker_pfm_m467.dts @@ -29,6 +29,7 @@ zephyr,sram = &sram0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,canbus = &canfd0; }; @@ -108,3 +109,17 @@ pinctrl-names = "default"; status = "okay"; }; + +&canfd0 { + bus-speed = <125000>; + bus-speed-data = <1000000>; + pinctrl-0 = <&canfd0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&emac { + pinctrl-0 = <&emac_default>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/boards/arm/numaker_pfm_m467/numaker_pfm_m467.yaml b/boards/arm/numaker_pfm_m467/numaker_pfm_m467.yaml index 41f6d4c88cf..d668f51facb 100644 --- a/boards/arm/numaker_pfm_m467/numaker_pfm_m467.yaml +++ b/boards/arm/numaker_pfm_m467/numaker_pfm_m467.yaml @@ -13,3 +13,4 @@ ram: 512 flash: 1024 supported: - gpio +vendor: nuvoton diff --git a/boards/arm/nuvoton_pfm_m487/nuvoton_pfm_m487.yaml b/boards/arm/nuvoton_pfm_m487/nuvoton_pfm_m487.yaml index 33af96d6bc9..c56fb1fd78e 100644 --- a/boards/arm/nuvoton_pfm_m487/nuvoton_pfm_m487.yaml +++ b/boards/arm/nuvoton_pfm_m487/nuvoton_pfm_m487.yaml @@ -8,3 +8,4 @@ toolchain: - xtools ram: 160 flash: 512 +vendor: nuvoton diff --git a/boards/arm/olimex_lora_stm32wl_devkit/doc/olimex_lora_stm32wl_devkit.rst b/boards/arm/olimex_lora_stm32wl_devkit/doc/olimex_lora_stm32wl_devkit.rst index 8185d7ef445..cd7d3436296 100644 --- a/boards/arm/olimex_lora_stm32wl_devkit/doc/olimex_lora_stm32wl_devkit.rst +++ b/boards/arm/olimex_lora_stm32wl_devkit/doc/olimex_lora_stm32wl_devkit.rst @@ -126,7 +126,7 @@ CON1 pin header. :goals: build flash Run a serial terminal to connect with your board. By default, ``usart1`` is -accessible via the the built-in USB to UART converter. +accessible via the built-in USB to UART converter. .. code-block:: console @@ -136,7 +136,7 @@ Debugging ========= You can debug an application in the usual way. Here is an example for the -:ref:`blinky-sample` application. +:zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/olimex_lora_stm32wl_devkit/olimex_lora_stm32wl_devkit.yaml b/boards/arm/olimex_lora_stm32wl_devkit/olimex_lora_stm32wl_devkit.yaml index a2ac552b4b2..5fdb67ec933 100644 --- a/boards/arm/olimex_lora_stm32wl_devkit/olimex_lora_stm32wl_devkit.yaml +++ b/boards/arm/olimex_lora_stm32wl_devkit/olimex_lora_stm32wl_devkit.yaml @@ -17,3 +17,4 @@ supported: - uart - watchdog - lora +vendor: olimex diff --git a/boards/arm/olimex_stm32_e407/doc/index.rst b/boards/arm/olimex_stm32_e407/doc/index.rst index de5393f4b11..6abdc3b564c 100644 --- a/boards/arm/olimex_stm32_e407/doc/index.rst +++ b/boards/arm/olimex_stm32_e407/doc/index.rst @@ -375,4 +375,4 @@ way. Here is an example for the :ref:`hello_world` application. https://www.olimex.com/Products/ARM/ST/STM32-E407/resources/STM32-E407.pdf .. _ST STM32F407ZG Datasheet: - http://www.st.com/resource/en/reference_manual/dm00031020.pdf + https://www.st.com/resource/en/reference_manual/dm00031020.pdf diff --git a/boards/arm/olimex_stm32_e407/olimex_stm32_e407.yaml b/boards/arm/olimex_stm32_e407/olimex_stm32_e407.yaml index 675ac2631a0..beefd5d2c8a 100644 --- a/boards/arm/olimex_stm32_e407/olimex_stm32_e407.yaml +++ b/boards/arm/olimex_stm32_e407/olimex_stm32_e407.yaml @@ -11,3 +11,4 @@ flash: 1024 supported: - counter - usb_device +vendor: olimex diff --git a/boards/arm/olimex_stm32_h103/doc/index.rst b/boards/arm/olimex_stm32_h103/doc/index.rst index 8ba6e949f8b..3abfb3b8885 100644 --- a/boards/arm/olimex_stm32_h103/doc/index.rst +++ b/boards/arm/olimex_stm32_h103/doc/index.rst @@ -208,7 +208,7 @@ The ``blackmagicprobe`` can also be used to program the device. Flashing ======== -Here is an example for the :ref:`button-sample` application. +Here is an example for the :zephyr:code-sample:`button` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/button diff --git a/boards/arm/olimex_stm32_h103/olimex_stm32_h103.yaml b/boards/arm/olimex_stm32_h103/olimex_stm32_h103.yaml index 392d559fc73..b863460fda4 100644 --- a/boards/arm/olimex_stm32_h103/olimex_stm32_h103.yaml +++ b/boards/arm/olimex_stm32_h103/olimex_stm32_h103.yaml @@ -16,3 +16,4 @@ testing: ignore_tags: - bluetooth - net +vendor: olimex diff --git a/boards/arm/olimex_stm32_h405/olimex_stm32_h405.yaml b/boards/arm/olimex_stm32_h405/olimex_stm32_h405.yaml index 57237445572..9930505236f 100644 --- a/boards/arm/olimex_stm32_h405/olimex_stm32_h405.yaml +++ b/boards/arm/olimex_stm32_h405/olimex_stm32_h405.yaml @@ -10,3 +10,4 @@ ram: 128 flash: 1024 supported: - counter +vendor: olimex diff --git a/boards/arm/olimex_stm32_h407/doc/index.rst b/boards/arm/olimex_stm32_h407/doc/index.rst index 25cd752612e..3555ed52a35 100644 --- a/boards/arm/olimex_stm32_h407/doc/index.rst +++ b/boards/arm/olimex_stm32_h407/doc/index.rst @@ -372,4 +372,4 @@ way. Here is an example for the :ref:`hello_world` application. https://www.olimex.com/Products/ARM/ST/STM32-H407/resources/STM32-H407.pdf .. _ST STM32F407ZG Datasheet: - http://www.st.com/resource/en/reference_manual/dm00031020.pdf + https://www.st.com/resource/en/reference_manual/dm00031020.pdf diff --git a/boards/arm/olimex_stm32_h407/olimex_stm32_h407.yaml b/boards/arm/olimex_stm32_h407/olimex_stm32_h407.yaml index fe6d3237849..fea55c8a3d4 100644 --- a/boards/arm/olimex_stm32_h407/olimex_stm32_h407.yaml +++ b/boards/arm/olimex_stm32_h407/olimex_stm32_h407.yaml @@ -10,3 +10,4 @@ ram: 128 flash: 1024 supported: - counter +vendor: olimex diff --git a/boards/arm/olimex_stm32_p405/doc/index.rst b/boards/arm/olimex_stm32_p405/doc/index.rst index 9aa053e90a0..e68bcb589ca 100644 --- a/boards/arm/olimex_stm32_p405/doc/index.rst +++ b/boards/arm/olimex_stm32_p405/doc/index.rst @@ -260,4 +260,4 @@ You can debug an application in the usual way. Here is an example for the https://www.olimex.com/Products/ARM/ST/STM32-P405/resources/STM32-P405_UM.pdf .. _ST STM32F405RG Datasheet: - http://www.st.com/resource/en/reference_manual/dm00031020.pdf + https://www.st.com/resource/en/reference_manual/dm00031020.pdf diff --git a/boards/arm/olimex_stm32_p405/olimex_stm32_p405.yaml b/boards/arm/olimex_stm32_p405/olimex_stm32_p405.yaml index 6f5c5b9357d..d3c23913f35 100644 --- a/boards/arm/olimex_stm32_p405/olimex_stm32_p405.yaml +++ b/boards/arm/olimex_stm32_p405/olimex_stm32_p405.yaml @@ -11,3 +11,4 @@ flash: 1024 supported: - counter - can +vendor: olimex diff --git a/boards/arm/olimexino_stm32/doc/index.rst b/boards/arm/olimexino_stm32/doc/index.rst index ce5a2407ac9..913b6faa8d6 100644 --- a/boards/arm/olimexino_stm32/doc/index.rst +++ b/boards/arm/olimexino_stm32/doc/index.rst @@ -414,7 +414,7 @@ Flashing an Application to OLIMEXINO-STM32 To upload an application to the OLIMEXINO-STM32 board a TTL(3.3V) serial adapter is required. This tutorial uses the -:ref:`button-sample` sample application. +:zephyr:code-sample:`button` sample application. #. Connect the serial cable to the UEXT lines of the UART interface (pin #3=TX and pin #4=RX). @@ -458,7 +458,7 @@ serial adapter is required. This tutorial uses the https://www.olimex.com/Products/Duino/STM32/OLIMEXINO-STM32/resources/OLIMEXINO-STM32.pdf .. _ST STM32F103xB Datasheet: - http://www.st.com/resource/en/datasheet/stm32f103tb.pdf + https://www.st.com/resource/en/datasheet/stm32f103tb.pdf .. _stm32flash tool: https://sourceforge.net/p/stm32flash/wiki/Home/ diff --git a/boards/arm/olimexino_stm32/olimexino_stm32.yaml b/boards/arm/olimexino_stm32/olimexino_stm32.yaml index b5b2afa8bb2..b4cf8b26bfb 100644 --- a/boards/arm/olimexino_stm32/olimexino_stm32.yaml +++ b/boards/arm/olimexino_stm32/olimexino_stm32.yaml @@ -16,3 +16,4 @@ supported: - usb_device - watchdog - can +vendor: olimex diff --git a/boards/arm/pan1770_evb/pan1770_evb_defconfig b/boards/arm/pan1770_evb/pan1770_evb_defconfig index 1d90cb82c25..7fbc9b87408 100644 --- a/boards/arm/pan1770_evb/pan1770_evb_defconfig +++ b/boards/arm/pan1770_evb/pan1770_evb_defconfig @@ -25,6 +25,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -# using pinctrl -CONFIG_PINCTRL=y diff --git a/boards/arm/pan1780_evb/pan1780_evb_defconfig b/boards/arm/pan1780_evb/pan1780_evb_defconfig index ca1a58c3b74..1bb9d720f52 100644 --- a/boards/arm/pan1780_evb/pan1780_evb_defconfig +++ b/boards/arm/pan1780_evb/pan1780_evb_defconfig @@ -25,6 +25,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -# using pinctrl -CONFIG_PINCTRL=y diff --git a/boards/arm/pan1781_evb/pan1781_evb_defconfig b/boards/arm/pan1781_evb/pan1781_evb_defconfig index dacffd42175..90e88bd4e1c 100644 --- a/boards/arm/pan1781_evb/pan1781_evb_defconfig +++ b/boards/arm/pan1781_evb/pan1781_evb_defconfig @@ -25,6 +25,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -# using pinctrl -CONFIG_PINCTRL=y diff --git a/boards/arm/pan1782_evb/pan1782_evb_defconfig b/boards/arm/pan1782_evb/pan1782_evb_defconfig index e6a6cc1d4a5..98904968416 100644 --- a/boards/arm/pan1782_evb/pan1782_evb_defconfig +++ b/boards/arm/pan1782_evb/pan1782_evb_defconfig @@ -26,8 +26,5 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# using pinctrl -CONFIG_PINCTRL=y - # using rc for slow clock CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y diff --git a/boards/arm/pan1783_evb/CMakeLists.txt b/boards/arm/pan1783_evb/CMakeLists.txt new file mode 100644 index 00000000000..f8bc359b603 --- /dev/null +++ b/boards/arm/pan1783_evb/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright (c) 2023 Panasonic Industrial Devices Europe GmbH +# SPDX-License-Identifier: Apache-2.0 + +if ((CONFIG_BOARD_PAN1783_EVB_CPUAPP) AND (CONFIG_BOARD_ENABLE_CPUNET)) +zephyr_library() +zephyr_library_sources(pan1783_evb_cpunet_reset.c) +endif() diff --git a/boards/arm/pan1783_evb/Kconfig b/boards/arm/pan1783_evb/Kconfig new file mode 100644 index 00000000000..b9c84ba66ff --- /dev/null +++ b/boards/arm/pan1783_evb/Kconfig @@ -0,0 +1,53 @@ +# PAN1783 EVB board configuration + +# Copyright (c) 2023 Panasonic Industrial Devices Europe GmbH +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_PAN1783_EVB_CPUAPP + +config BOARD_ENABLE_DCDC_APP + bool "Application MCU DCDC converter" + select SOC_DCDC_NRF53X_APP + default y + +config BOARD_ENABLE_DCDC_NET + bool "Network MCU DCDC converter" + select SOC_DCDC_NRF53X_NET + default y + +config BOARD_ENABLE_DCDC_HV + bool "High Voltage DCDC converter" + select SOC_DCDC_NRF53X_HV + default y + +config BOARD_ENABLE_CPUNET + bool "NRF53 Network MCU" + select SOC_NRF_GPIO_FORWARDER_FOR_NRF5340 if \ + $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_GPIO_FORWARDER)) + help + This option enables releasing the Network 'force off' signal, which + as a consequence will power up the Network MCU during system boot. + Additionally, the option allocates GPIO pins that will be used by UARTE + of the Network MCU. + default y if (BT || NRF_802154_SER_HOST) + +config DOMAIN_CPUNET_BOARD + string + default "pan1783_evb_cpunet" + depends on BOARD_ENABLE_CPUNET + help + The board which will be used for CPUNET domain when creating a multi + image application where one or more images should be located on + another board. For example hci_ipc on the nRF5340_cpunet for + Bluetooth applications. + +endif # BOARD_PAN1783_EVB_CPUAPP + +config DOMAIN_CPUAPP_BOARD + string + default "pan1783_evb_cpuapp" + depends on BOARD_PAN1783_EVB_CPUNET + help + The board which will be used for CPUAPP domain when creating a multi + image application where one or more images should be located on + another board. diff --git a/boards/arm/pan1783_evb/Kconfig.board b/boards/arm/pan1783_evb/Kconfig.board new file mode 100644 index 00000000000..d66c99aac36 --- /dev/null +++ b/boards/arm/pan1783_evb/Kconfig.board @@ -0,0 +1,12 @@ +# PAN1783 EVB board configuration + +# Copyright (c) 2023 Panasonic Industrial Devices Europe GmbH +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_PAN1783_EVB_CPUAPP + bool "PAN1783 EVB (nRF5340) Application MCU" + depends on SOC_NRF5340_CPUAPP_QKAA + +config BOARD_PAN1783_EVB_CPUNET + bool "PAN1783 EVB (NRF5340) Network MCU" + depends on SOC_NRF5340_CPUNET_QKAA diff --git a/boards/arm/pan1783_evb/Kconfig.defconfig b/boards/arm/pan1783_evb/Kconfig.defconfig new file mode 100644 index 00000000000..b26b4970d84 --- /dev/null +++ b/boards/arm/pan1783_evb/Kconfig.defconfig @@ -0,0 +1,31 @@ +# PAN1783 EVB board configuration + +# Copyright (c) 2023 Panasonic Industrial Devices Europe GmbH +# SPDX-License-Identifier: Apache-2.0 + +config BOARD + default "pan1783_evb_cpuapp" if BOARD_PAN1783_EVB_CPUAPP + +config BOARD + default "pan1783_evb_cpunet" if BOARD_PAN1783_EVB_CPUNET + +config MBOX_NRFX_IPC + default MBOX + +if BOARD_PAN1783_EVB_CPUAPP + +choice BT_HCI_BUS_TYPE + default BT_HCI_IPC if BT +endchoice + +config HEAP_MEM_POOL_SIZE + default 4096 if BT_HCI_IPC + +endif # BOARD_PAN1783_EVB_CPUAPP + +if BOARD_PAN1783_EVB_CPUNET + +config BT_CTLR + default y if BT + +endif # BOARD_PAN1783_EVB_CPUNET diff --git a/boards/arm/pan1783_evb/board.cmake b/boards/arm/pan1783_evb/board.cmake new file mode 100644 index 00000000000..f75151ecb94 --- /dev/null +++ b/boards/arm/pan1783_evb/board.cmake @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_BOARD_PAN1783_EVB_CPUAPP) +board_runner_args(jlink "--device=nrf5340_xxaa_app" "--speed=4000") +endif() + +if(CONFIG_BOARD_PAN1783_EVB_CPUNET) +board_runner_args(jlink "--device=nrf5340_xxaa_net" "--speed=4000") +endif() + +include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/arm/pan1783_evb/doc/img/pan1783_evb.jpg b/boards/arm/pan1783_evb/doc/img/pan1783_evb.jpg new file mode 100644 index 00000000000..273253cfcf9 Binary files /dev/null and b/boards/arm/pan1783_evb/doc/img/pan1783_evb.jpg differ diff --git a/boards/arm/pan1783_evb/doc/index.rst b/boards/arm/pan1783_evb/doc/index.rst new file mode 100644 index 00000000000..39fe7fdff8f --- /dev/null +++ b/boards/arm/pan1783_evb/doc/index.rst @@ -0,0 +1,55 @@ +.. _pan1783_evb: + +PAN1783 Evaluation Board +######################## + +Overview +******** + +The PAN1783 Evaluation Board (pan1783_evb) is a development tool for the +PAN1783 Module which is based on the nRF5340 chipset from Nordic Semiconductor. + +You can find more information about the PAN1783 Module and Evaluation Board +on the `product website`_. + +.. figure:: img/pan1783_evb.jpg + :align: center + :alt: PAN1783 EVB + + PAN1783 EVB (Credit: Panasonic) + +The PAN1783 Evaluation Board is closely linked to these other evaluation +boards: + +* pan1783a_evb +* pan1783a_pa_evb + +Usage +***** + +For detailed information, you can find the `user guide`_ for the PAN1783 +Evaluation Board in the `Panasonic Wireless Connectivity Development Hub`_. + +The User Guide contains (amongst other things) detailed information about + +* pin mapping +* powering options +* breakout pin header interface +* current consumption measurement +* software development + +The schematics for the PAN1783 Evaluation Board are available in the +`download section`_ of the `Panasonic Wireless Connectivity Development Hub`_. + +Programming and Debugging +************************* + +Please use the ``pan1783_evb_cpuapp`` for application core or +``pan1783_evb_cpunet`` board configuration for network core +when :ref:`build_an_application` and :ref:`application_run`. + +.. target-notes:: +.. _product website: https://industry.panasonic.eu/products/devices/wireless-connectivity/bluetooth-low-energy-modules/pan1783-nrf5340 +.. _Panasonic Wireless Connectivity Development Hub: https://pideu.panasonic.de/development-hub/ +.. _user guide: https://pideu.panasonic.de/development-hub/pan1783/evaluation_board/user_guide/ +.. _download section: https://pideu.panasonic.de/development-hub/pan1783/downloads/ diff --git a/boards/arm/pan1783_evb/pan1783_evb_cpuapp.dts b/boards/arm/pan1783_evb/pan1783_evb_cpuapp.dts new file mode 100644 index 00000000000..3adae69badb --- /dev/null +++ b/boards/arm/pan1783_evb/pan1783_evb_cpuapp.dts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 Panasonic Industrial Devices Europe GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "pan1783_evb_cpuapp_common.dtsi" + +/ { + model = "Panasonic PAN1783 EVB (NRF5340) Application"; + compatible = "panasonic,pan1783-evb-cpuapp"; + + chosen { + zephyr,sram = &sram0_image; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + zephyr,sram-secure-partition = &sram0_s; + }; +}; diff --git a/boards/arm/pan1783_evb/pan1783_evb_cpuapp.yaml b/boards/arm/pan1783_evb/pan1783_evb_cpuapp.yaml new file mode 100644 index 00000000000..a0242b83252 --- /dev/null +++ b/boards/arm/pan1783_evb/pan1783_evb_cpuapp.yaml @@ -0,0 +1,21 @@ +identifier: pan1783_evb_cpuapp +name: PAN1783-EVB-application-MCU +type: mcu +arch: arm +toolchain: + - gnuarmemb + - xtools + - zephyr +ram: 448 +flash: 1024 +supported: + - gpio + - i2c + - i2s + - pwm + - watchdog + - usb_cdc + - usb_device + - netif:openthread + - gpio +vendor: panasonic diff --git a/boards/arm/pan1783_evb/pan1783_evb_cpuapp_common-pinctrl.dtsi b/boards/arm/pan1783_evb/pan1783_evb_cpuapp_common-pinctrl.dtsi new file mode 100644 index 00000000000..cdafbaf2cdc --- /dev/null +++ b/boards/arm/pan1783_evb/pan1783_evb_cpuapp_common-pinctrl.dtsi @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2023 Panasonic Industrial Devices Europe GmbH + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + i2c1_default: i2c1_default { + group1 { + psels = , + ; + }; + }; + + i2c1_sleep: i2c1_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + uart0_default: uart0_default { + group1 { + psels = , + ; + }; + group2 { + psels = , + ; + bias-pull-up; + }; + }; + + uart0_sleep: uart0_sleep { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; + + pwm0_default: pwm0_default { + group1 { + psels = ; + }; + }; + + pwm0_sleep: pwm0_sleep { + group1 { + psels = ; + low-power-enable; + }; + }; + + qspi_default: qspi_default { + group1 { + psels = , + , + , + , + , + ; + nordic,drive-mode = ; + }; + }; + + qspi_sleep: qspi_sleep { + group1 { + psels = , + , + , + , + ; + low-power-enable; + }; + group2 { + psels = ; + low-power-enable; + bias-pull-up; + }; + }; + + uart1_default: uart1_default { + group1 { + psels = ; + }; + group2 { + psels = ; + bias-pull-up; + }; + }; + + uart1_sleep: uart1_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + spi4_default: spi4_default { + group1 { + psels = , + , + ; + }; + }; + + spi4_sleep: spi4_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; + +}; diff --git a/boards/arm/pan1783_evb/pan1783_evb_cpuapp_common.dtsi b/boards/arm/pan1783_evb/pan1783_evb_cpuapp_common.dtsi new file mode 100644 index 00000000000..175475f5b0e --- /dev/null +++ b/boards/arm/pan1783_evb/pan1783_evb_cpuapp_common.dtsi @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2023 Panasonic Industrial Devices Europe GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "pan1783_evb_cpuapp_common-pinctrl.dtsi" +#include + +/ { + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,uart-mcumgr = &uart0; + zephyr,bt-mon-uart = &uart0; + zephyr,bt-c2h-uart = &uart0; + zephyr,bt-hci-ipc = &ipc0; + nordic,802154-spinel-ipc = &ipc0; + zephyr,ieee802154 = &ieee802154; + }; + + leds { + compatible = "gpio-leds"; + evb_led1: evb_led_1 { + gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; + label = "LED1 on EVB"; + }; + evb_led2: evb_led_2 { + gpios = <&gpio0 29 GPIO_ACTIVE_LOW>; + label = "LED2 on EVB"; + }; + evb_led3: evb_led_3 { + gpios = <&gpio0 30 GPIO_ACTIVE_LOW>; + label = "LED3 on EVB"; + }; + evb_led4: evb_led_4 { + gpios = <&gpio0 31 GPIO_ACTIVE_LOW>; + label = "LED4 on EVB"; + }; + }; + + pwmleds { + compatible = "pwm-leds"; + pwm_evb_led1: pwm_evb_led_1 { + pwms = <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_INVERTED>; + }; + }; + + buttons { + compatible = "gpio-keys"; + evb_sw1: evb_sw_1 { + gpios = <&gpio0 23 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW1 on EVB"; + zephyr,code = ; + }; + evb_sw2: evb_sw_2 { + gpios = <&gpio0 24 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW2 on EVB"; + zephyr,code = ; + }; + evb_sw3: evb_sw_3 { + gpios = <&gpio0 8 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW3 on EVB"; + zephyr,code = ; + }; + evb_sw4: evb_sw_4 { + gpios = <&gpio0 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW4 on EVB"; + zephyr,code = ; + }; + }; + + mikrobus_header: mikrobus-connector { + compatible = "mikro-bus"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpio0 4 0>, /* AN */ + /* Not a GPIO*/ /* RST */ + <2 0 &gpio1 12 0>, /* CS */ + <3 0 &gpio1 15 0>, /* SCK */ + <4 0 &gpio1 14 0>, /* MISO */ + <5 0 &gpio1 13 0>, /* MOSI */ + /* +3.3V */ + /* GND */ + <6 0 &gpio1 7 0>, /* PWM */ + <7 0 &gpio1 4 0>, /* INT */ + <8 0 &gpio1 0 0>, /* RX */ + <9 0 &gpio1 1 0>, /* TX */ + <10 0 &gpio1 3 0>, /* SCL */ + <11 0 &gpio1 2 0>; /* SDA */ + /* +5V */ + /* GND */ + }; + + arduino_header: connector { + compatible = "arduino-header-r3"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpio0 4 0>, /* A0 */ + <1 0 &gpio0 5 0>, /* A1 */ + <2 0 &gpio0 6 0>, /* A2 */ + <3 0 &gpio0 7 0>, /* A3 */ + <4 0 &gpio0 25 0>, /* A4 */ + <5 0 &gpio0 26 0>, /* A5 */ + <6 0 &gpio1 0 0>, /* D0 */ + <7 0 &gpio1 1 0>, /* D1 */ + <8 0 &gpio1 4 0>, /* D2 */ + <9 0 &gpio1 5 0>, /* D3 */ + <10 0 &gpio1 6 0>, /* D4 */ + <11 0 &gpio1 7 0>, /* D5 */ + <12 0 &gpio1 8 0>, /* D6 */ + <13 0 &gpio1 9 0>, /* D7 */ + <14 0 &gpio1 10 0>, /* D8 */ + <15 0 &gpio1 11 0>, /* D9 */ + <16 0 &gpio1 12 0>, /* D10 */ + <17 0 &gpio1 13 0>, /* D11 */ + <18 0 &gpio1 14 0>, /* D12 */ + <19 0 &gpio1 15 0>, /* D13 */ + <20 0 &gpio1 2 0>, /* D14 */ + <21 0 &gpio1 3 0>; /* D15 */ + }; + + arduino_adc: analog-connector { + compatible = "arduino,uno-adc"; + #io-channel-cells = <1>; + io-channel-map = <0 &adc 0>, /* A0 = P0.4 = AIN0 */ + <1 &adc 1>, /* A1 = P0.5 = AIN1 */ + <2 &adc 2>, /* A2 = P0.6 = AIN2 */ + <3 &adc 3>, /* A3 = P0.7 = AIN3 */ + <4 &adc 4>, /* A4 = P0.25 = AIN4 */ + <5 &adc 5>; /* A5 = P0.26 = AIN5 */ + }; + + gpio_fwd: nrf-gpio-forwarder { + compatible = "nordic,nrf-gpio-forwarder"; + status = "disabled"; + uart { + gpios = <&gpio0 20 0>, <&gpio0 22 0>, <&gpio0 11 0>, <&gpio0 10 0>; + }; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &evb_led1; + led1 = &evb_led2; + led2 = &evb_led3; + led3 = &evb_led4; + pwm-led0 = &pwm_evb_led1; + sw0 = &evb_sw1; + sw1 = &evb_sw2; + sw2 = &evb_sw3; + sw3 = &evb_sw4; + bootloader-led0 = &evb_led1; + mcuboot-button0 = &evb_sw1; + mcuboot-led0 = &evb_led1; + watchdog0 = &wdt0; + spi-flash0 = &mx25r64; + }; +}; + +&adc { + status = "okay"; +}; + +&gpiote { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&i2c1 { + compatible = "nordic,nrf-twim"; + status = "okay"; + pinctrl-0 = <&i2c1_default>; + pinctrl-1 = <&i2c1_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-1 = <&uart0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&pwm0 { + status = "okay"; + pinctrl-0 = <&pwm0_default>; + pinctrl-1 = <&pwm0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&qspi { + status = "okay"; + pinctrl-0 = <&qspi_default>; + pinctrl-1 = <&qspi_sleep>; + pinctrl-names = "default", "sleep"; + mx25r64: mx25r6435f@0 { + compatible = "nordic,qspi-nor"; + reg = <0>; + /* MX25R64 supports only pp and pp4io */ + writeoc = "pp4io"; + /* MX25R64 supports all readoc options */ + readoc = "read4io"; + sck-frequency = <8000000>; + jedec-id = [ c2 28 17 ]; + sfdp-bfp = [ + e5 20 f1 ff ff ff ff 03 44 eb 08 6b 08 3b 04 bb + ee ff ff ff ff ff 00 ff ff ff 00 ff 0c 20 0f 52 + 10 d8 00 ff 23 72 f5 00 82 ed 04 cc 44 83 68 44 + 30 b0 30 b0 f7 c4 d5 5c 00 be 29 ff f0 d0 ff ff + ]; + size = <67108864>; + has-dpd; + t-enter-dpd = <10000>; + t-exit-dpd = <35000>; + }; +}; + +arduino_serial: &uart1 { + compatible = "nordic,nrf-uarte"; + current-speed = <115200>; + pinctrl-0 = <&uart1_default>; + pinctrl-1 = <&uart1_sleep>; + pinctrl-names = "default", "sleep"; +}; + +arduino_i2c: &i2c1 {}; + +arduino_spi: &spi4 { + compatible = "nordic,nrf-spim"; + status = "okay"; + cs-gpios = <&arduino_header 16 GPIO_ACTIVE_LOW>; /* D10 */ + pinctrl-0 = <&spi4_default>; + pinctrl-1 = <&spi4_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&flash0 { + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x00010000>; + }; + slot0_partition: partition@10000 { + label = "image-0"; + }; + slot1_partition: partition@80000 { + label = "image-1"; + }; + /* 0xf0000 to 0xf7fff reserved for TF-M partitions */ + storage_partition: partition@f8000 { + label = "storage"; + reg = <0x000f8000 0x00008000>; + }; + }; +}; + +&ieee802154 { + status = "okay"; +}; + +zephyr_udc0: &usbd { + compatible = "nordic,nrf-usbd"; + status = "okay"; +}; + +/ { + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + sram0_image: image@20000000 { + /* Zephyr image(s) memory */ + }; + + sram0_s: image_s@20000000 { + /* Secure image memory */ + }; + }; +}; + +/* Include partition configuration file */ +#include "pan1783_evb_cpuapp_partition_conf.dtsi" diff --git a/boards/arm/pan1783_evb/pan1783_evb_cpuapp_defconfig b/boards/arm/pan1783_evb/pan1783_evb_cpuapp_defconfig new file mode 100644 index 00000000000..b709d16dc54 --- /dev/null +++ b/boards/arm/pan1783_evb/pan1783_evb_cpuapp_defconfig @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_NRF53X=y +CONFIG_SOC_NRF5340_CPUAPP_QKAA=y +CONFIG_BOARD_PAN1783_EVB_CPUAPP=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable uart driver +CONFIG_SERIAL=y + +# enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# clock config +CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y +CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=n diff --git a/boards/arm/pan1783_evb/pan1783_evb_cpuapp_partition_conf.dtsi b/boards/arm/pan1783_evb/pan1783_evb_cpuapp_partition_conf.dtsi new file mode 100644 index 00000000000..50e32748bec --- /dev/null +++ b/boards/arm/pan1783_evb/pan1783_evb_cpuapp_partition_conf.dtsi @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023 Panasonic Industrial Devices Europe GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Default Flash planning for pan1783_evb CPUAPP (Application MCU). + * + * Secure image will be placed, by default, in flash0 + * (or in slot0, if MCUboot is present). + * Secure image will use sram0 for system memory. + * + */ + +&slot0_partition { + reg = <0x00010000 0x40000>; +}; + +&slot1_partition { + reg = <0x00080000 0x40000>; +}; + +/* Default SRAM planning when building for nRF5340 + * - Lowest 448 kB SRAM allocated to Secure image (sram0_s) + * - Upper 64 kB SRAM allocated as Shared memory (sram0_shared) + * (see pan1783_evb_shared_sram_planning_conf.dts) + */ +&sram0_image { + reg = <0x20000000 DT_SIZE_K(448)>; +}; + +&sram0_s { + reg = <0x20000000 0x70000>; +}; + +/* Include shared RAM configuration file */ +#include "pan1783_evb_shared_sram_planning_conf.dtsi" diff --git a/boards/arm/pan1783_evb/pan1783_evb_cpunet-pinctrl.dtsi b/boards/arm/pan1783_evb/pan1783_evb_cpunet-pinctrl.dtsi new file mode 100644 index 00000000000..8a82e07406e --- /dev/null +++ b/boards/arm/pan1783_evb/pan1783_evb_cpunet-pinctrl.dtsi @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023 Panasonic Industrial Devices Europe GmbH + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + uart0_default: uart0_default { + group1 { + psels = , + ; + }; + group2 { + psels = , + ; + bias-pull-up; + }; + }; + + uart0_sleep: uart0_sleep { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; + + i2c0_default: i2c0_default { + group1 { + psels = , + ; + }; + }; + + i2c0_sleep: i2c0_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + spi0_default: spi0_default { + group1 { + psels = , + , + ; + }; + }; + + spi0_sleep: spi0_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; + +}; diff --git a/boards/arm/pan1783_evb/pan1783_evb_cpunet.dts b/boards/arm/pan1783_evb/pan1783_evb_cpunet.dts new file mode 100644 index 00000000000..6506c46aeed --- /dev/null +++ b/boards/arm/pan1783_evb/pan1783_evb_cpunet.dts @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2023 Panasonic Industrial Devices Europe GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "pan1783_evb_cpunet-pinctrl.dtsi" +#include + +/ { + model = "Panasonic PAN1783 EVB (NRF5340) Network"; + compatible = "panasonic,pan1783-evb-cpunet"; + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,uart-mcumgr = &uart0; + zephyr,bt-mon-uart = &uart0; + zephyr,bt-c2h-uart = &uart0; + zephyr,bt-hci-ipc = &ipc0; + nordic,802154-spinel-ipc = &ipc0; + zephyr,sram = &sram1; + zephyr,flash = &flash1; + zephyr,code-partition = &slot0_partition; + zephyr,ieee802154 = &ieee802154; + }; + + leds { + compatible = "gpio-leds"; + evb_led1: evb_led_1 { + gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; + label = "LED1 on EVB"; + }; + evb_led2: evb_led_2 { + gpios = <&gpio0 29 GPIO_ACTIVE_LOW>; + label = "LED2 on EVB"; + }; + evb_led3: evb_led_3 { + gpios = <&gpio0 30 GPIO_ACTIVE_LOW>; + label = "LED3 on EVB"; + }; + evb_led4: evb_led_4 { + gpios = <&gpio0 31 GPIO_ACTIVE_LOW>; + label = "LED4 on EVB"; + }; + }; + + buttons { + compatible = "gpio-keys"; + evb_sw1: evb_sw_1 { + gpios = <&gpio0 23 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW1 on EVB"; + zephyr,code = ; + }; + evb_sw2: evb_sw_2 { + gpios = <&gpio0 24 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW2 on EVB"; + zephyr,code = ; + }; + evb_sw3: evb_sw_3 { + gpios = <&gpio0 8 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW3 on EVB"; + zephyr,code = ; + }; + evb_sw4: evb_sw_4 { + gpios = <&gpio0 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW4 on EVB"; + zephyr,code = ; + }; + }; + + mikrobus_header: mikrobus-connector { + compatible = "mikro-bus"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpio0 4 0>, /* AN */ + /* Not a GPIO*/ /* RST */ + <2 0 &gpio1 12 0>, /* CS */ + <3 0 &gpio1 15 0>, /* SCK */ + <4 0 &gpio1 14 0>, /* MISO */ + <5 0 &gpio1 13 0>, /* MOSI */ + /* +3.3V */ + /* GND */ + <6 0 &gpio1 7 0>, /* PWM */ + <7 0 &gpio1 4 0>, /* INT */ + <8 0 &gpio1 0 0>, /* RX */ + <9 0 &gpio1 1 0>, /* TX */ + <10 0 &gpio1 3 0>, /* SCL */ + <11 0 &gpio1 2 0>; /* SDA */ + /* +5V */ + /* GND */ + }; + + arduino_header: connector { + compatible = "arduino-header-r3"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpio0 4 0>, /* A0 */ + <1 0 &gpio0 5 0>, /* A1 */ + <2 0 &gpio0 6 0>, /* A2 */ + <3 0 &gpio0 7 0>, /* A3 */ + <4 0 &gpio0 25 0>, /* A4 */ + <5 0 &gpio0 26 0>, /* A5 */ + <6 0 &gpio1 0 0>, /* D0 */ + <7 0 &gpio1 1 0>, /* D1 */ + <8 0 &gpio1 4 0>, /* D2 */ + <9 0 &gpio1 5 0>, /* D3 */ + <10 0 &gpio1 6 0>, /* D4 */ + <11 0 &gpio1 7 0>, /* D5 */ + <12 0 &gpio1 8 0>, /* D6 */ + <13 0 &gpio1 9 0>, /* D7 */ + <14 0 &gpio1 10 0>, /* D8 */ + <15 0 &gpio1 11 0>, /* D9 */ + <16 0 &gpio1 12 0>, /* D10 */ + <17 0 &gpio1 13 0>, /* D11 */ + <18 0 &gpio1 14 0>, /* D12 */ + <19 0 &gpio1 15 0>, /* D13 */ + <20 0 &gpio1 2 0>, /* D14 */ + <21 0 &gpio1 3 0>; /* D15 */ + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &evb_led1; + led1 = &evb_led2; + led2 = &evb_led3; + led3 = &evb_led4; + sw0 = &evb_sw1; + sw1 = &evb_sw2; + sw2 = &evb_sw3; + sw3 = &evb_sw4; + bootloader-led0 = &evb_led1; + mcuboot-button0 = &evb_sw1; + mcuboot-led0 = &evb_led1; + watchdog0 = &wdt0; + }; +}; + +&gpiote { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&uart0 { + status = "disabled"; + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-1 = <&uart0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +arduino_serial: &uart0{}; + +arduino_i2c: &i2c0 { + compatible = "nordic,nrf-twim"; + /* Cannot be used together with uart0. */ + /* status = "okay"; */ + pinctrl-0 = <&i2c0_default>; + pinctrl-1 = <&i2c0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +arduino_spi: &spi0 { + compatible = "nordic,nrf-spim"; + /* Cannot be used together with uart0. */ + /* status = "okay"; */ + cs-gpios = <&arduino_header 16 GPIO_ACTIVE_LOW>; /* D10 */ + pinctrl-0 = <&spi0_default>; + pinctrl-1 = <&spi0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&flash1 { + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0xc000>; + }; + slot0_partition: partition@c000 { + label = "image-0"; + reg = <0x0000C000 0x17000>; + }; + slot1_partition: partition@23000 { + label = "image-1"; + reg = <0x00023000 0x17000>; + }; + storage_partition: partition@3a000 { + label = "storage"; + reg = <0x0003a000 0x6000>; + }; + }; +}; + +&ieee802154 { + status = "okay"; +}; + +/* Include shared RAM configuration file */ +#include "pan1783_evb_shared_sram_planning_conf.dtsi" diff --git a/boards/arm/pan1783_evb/pan1783_evb_cpunet.yaml b/boards/arm/pan1783_evb/pan1783_evb_cpunet.yaml new file mode 100644 index 00000000000..725fae94cc5 --- /dev/null +++ b/boards/arm/pan1783_evb/pan1783_evb_cpunet.yaml @@ -0,0 +1,14 @@ +identifier: pan1783_evb_cpunet +name: PAN1783-EVB-network-MCU +type: mcu +arch: arm +toolchain: + - gnuarmemb + - xtools + - zephyr +ram: 64 +flash: 256 +supported: + - watchdog + - gpio +vendor: panasonic diff --git a/boards/arm/pan1783_evb/pan1783_evb_cpunet_defconfig b/boards/arm/pan1783_evb/pan1783_evb_cpunet_defconfig new file mode 100644 index 00000000000..f83ea000455 --- /dev/null +++ b/boards/arm/pan1783_evb/pan1783_evb_cpunet_defconfig @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_NRF53X=y +CONFIG_SOC_NRF5340_CPUNET_QKAA=y +CONFIG_BOARD_PAN1783_EVB_CPUNET=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# enable GPIO +CONFIG_GPIO=y + +# clock config +CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y +CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=n diff --git a/boards/arm/pan1783_evb/pan1783_evb_cpunet_reset.c b/boards/arm/pan1783_evb/pan1783_evb_cpunet_reset.c new file mode 100644 index 00000000000..5b30492a1f9 --- /dev/null +++ b/boards/arm/pan1783_evb/pan1783_evb_cpunet_reset.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 Panasonic Industrial Devices Europe GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +#include + +LOG_MODULE_REGISTER(pan1783_evb_cpuapp, CONFIG_LOG_DEFAULT_LEVEL); + +#if defined(CONFIG_BT_CTLR_DEBUG_PINS_CPUAPP) +#include <../subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/debug.h> +#else +#define DEBUG_SETUP() +#endif + +static void remoteproc_mgr_config(void) +{ + /* Route Bluetooth Controller Debug Pins */ + DEBUG_SETUP(); + + /* Retain nRF5340 Network MCU */ + NRF_SPU->EXTDOMAIN[0].PERM = 1 << 4; +} + +static int remoteproc_mgr_boot(void) +{ + /* Configure permissions for the Network MCU. */ + remoteproc_mgr_config(); + + /* Release the Network MCU, 'Release force off signal' */ + nrf_reset_network_force_off(NRF_RESET, false); + + LOG_DBG("Network MCU released."); + + return 0; +} + +SYS_INIT(remoteproc_mgr_boot, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); diff --git a/boards/arm/pan1783_evb/pan1783_evb_shared_sram_planning_conf.dtsi b/boards/arm/pan1783_evb/pan1783_evb_shared_sram_planning_conf.dtsi new file mode 100644 index 00000000000..9e2b673f84a --- /dev/null +++ b/boards/arm/pan1783_evb/pan1783_evb_shared_sram_planning_conf.dtsi @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Panasonic Industrial Devices Europe GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Default shared SRAM planning when building for PAN1783 EVB. + * This file is included by both nRF5340 CPUAPP (Application MCU) + * and nRF5340 CPUNET (Network MCU). + * - 64 kB SRAM allocated as Shared memory (sram0_shared) + * - Region defined after the image SRAM of Application MCU + */ + +/ { + chosen { + /* shared memory reserved for the inter-processor communication */ + zephyr,ipc_shm = &sram0_shared; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + sram0_shared: memory@20070000 { + /* SRAM allocated to shared memory */ + reg = <0x20070000 0x10000>; + }; + }; +}; diff --git a/boards/arm/pan1783_evb/pre_dt_board.cmake b/boards/arm/pan1783_evb/pre_dt_board.cmake new file mode 100644 index 00000000000..b84665fcf51 --- /dev/null +++ b/boards/arm/pan1783_evb/pre_dt_board.cmake @@ -0,0 +1,8 @@ +# Copyright (c) 2023 Panasonic Industrial Devices Europe GmbH +# SPDX-License-Identifier: Apache-2.0 + +# Suppress "unique_unit_address_if_enabled" to handle the following overlaps: +# - flash-controller@39000 & kmu@39000 +# - power@5000 & clock@5000 +# - /reserved-memory/image@20000000 & /reserved-memory/image_s@20000000 +list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/boards/arm/pandora_stm32l475/support/openocd.cfg b/boards/arm/pandora_stm32l475/support/openocd.cfg index d9d989eb30e..d4c4da41053 100644 --- a/boards/arm/pandora_stm32l475/support/openocd.cfg +++ b/boards/arm/pandora_stm32l475/support/openocd.cfg @@ -1,5 +1,5 @@ # Explicitly for the STM32L475 Pandora board: -# http://www.st.com/web/en/catalog/tools/PF261635 +# https://www.st.com/web/en/catalog/tools/PF261635 # but perfectly functional for any other STM32L4 board connected via # an stlink-v2-1 interface. # This is for STM32L4 boards that are connected via stlink-v2-1. diff --git a/boards/arm/particle_argon/doc/index.rst b/boards/arm/particle_argon/doc/index.rst index 446b0a349dd..2bbb15a546f 100644 --- a/boards/arm/particle_argon/doc/index.rst +++ b/boards/arm/particle_argon/doc/index.rst @@ -160,8 +160,8 @@ Testing the LEDs and buttons There are 2 samples that allow you to test that the buttons (switches) and LEDs on the board are working properly with Zephyr: -* :ref:`blinky-sample` -* :ref:`button-sample` +* :zephyr:code-sample:`blinky` +* :zephyr:code-sample:`button` You can build and flash the examples to make sure Zephyr is running correctly on your board. diff --git a/boards/arm/particle_argon/particle_argon.yaml b/boards/arm/particle_argon/particle_argon.yaml index 7e3d9e642d6..489b8c9dd1e 100644 --- a/boards/arm/particle_argon/particle_argon.yaml +++ b/boards/arm/particle_argon/particle_argon.yaml @@ -17,3 +17,4 @@ supported: - feather_serial - feather_i2c - feather_spi +vendor: particle diff --git a/boards/arm/particle_argon/particle_argon_defconfig b/boards/arm/particle_argon/particle_argon_defconfig index c29f62babd4..5f3f7a7e2b5 100644 --- a/boards/arm/particle_argon/particle_argon_defconfig +++ b/boards/arm/particle_argon/particle_argon_defconfig @@ -20,5 +20,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/particle_boron/doc/index.rst b/boards/arm/particle_boron/doc/index.rst index 1f26fc09b6c..d5b7ce1f5d0 100644 --- a/boards/arm/particle_boron/doc/index.rst +++ b/boards/arm/particle_boron/doc/index.rst @@ -156,8 +156,8 @@ Testing the LEDs and buttons There are 2 samples that allow you to test that the buttons (switches) and LEDs on the board are working properly with Zephyr: -* :ref:`blinky-sample` -* :ref:`button-sample` +* :zephyr:code-sample:`blinky` +* :zephyr:code-sample:`button` You can build and flash the examples to make sure Zephyr is running correctly on your board. diff --git a/boards/arm/particle_boron/particle_boron.yaml b/boards/arm/particle_boron/particle_boron.yaml index 77ddd5953b5..bec2a0cbb03 100644 --- a/boards/arm/particle_boron/particle_boron.yaml +++ b/boards/arm/particle_boron/particle_boron.yaml @@ -17,3 +17,4 @@ supported: - feather_serial - feather_i2c - feather_spi +vendor: particle diff --git a/boards/arm/particle_boron/particle_boron_defconfig b/boards/arm/particle_boron/particle_boron_defconfig index 622a3169073..453981d2a64 100644 --- a/boards/arm/particle_boron/particle_boron_defconfig +++ b/boards/arm/particle_boron/particle_boron_defconfig @@ -20,8 +20,6 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -CONFIG_PINCTRL=y - # Fix the priority to enable the modem line's serial buffer # before the modem driver starts (gsm_ppp or ublox-sara-r4). CONFIG_REGULATOR=y diff --git a/boards/arm/particle_xenon/doc/index.rst b/boards/arm/particle_xenon/doc/index.rst index 5d011b0de0d..cf18340943a 100644 --- a/boards/arm/particle_xenon/doc/index.rst +++ b/boards/arm/particle_xenon/doc/index.rst @@ -161,8 +161,8 @@ Testing the LEDs and buttons There are 2 samples that allow you to test that the buttons (switches) and LEDs on the board are working properly with Zephyr: -* :ref:`blinky-sample` -* :ref:`button-sample` +* :zephyr:code-sample:`blinky` +* :zephyr:code-sample:`button` You can build and flash the examples to make sure Zephyr is running correctly on your board. diff --git a/boards/arm/particle_xenon/particle_xenon.yaml b/boards/arm/particle_xenon/particle_xenon.yaml index 8129178543f..0aa6a4afa15 100644 --- a/boards/arm/particle_xenon/particle_xenon.yaml +++ b/boards/arm/particle_xenon/particle_xenon.yaml @@ -22,3 +22,4 @@ supported: - feather_serial - feather_i2c - feather_spi +vendor: particle diff --git a/boards/arm/particle_xenon/particle_xenon_defconfig b/boards/arm/particle_xenon/particle_xenon_defconfig index 2495d886b41..8c7246fad1c 100644 --- a/boards/arm/particle_xenon/particle_xenon_defconfig +++ b/boards/arm/particle_xenon/particle_xenon_defconfig @@ -19,5 +19,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/pico_pi_m4/pico_pi_m4.yaml b/boards/arm/pico_pi_m4/pico_pi_m4.yaml index c0225f8fc42..8cc013a4e36 100644 --- a/boards/arm/pico_pi_m4/pico_pi_m4.yaml +++ b/boards/arm/pico_pi_m4/pico_pi_m4.yaml @@ -18,3 +18,4 @@ testing: ignore_tags: - net - bluetooth +vendor: nxp diff --git a/boards/arm/pinetime_devkit0/pinetime_devkit0.yaml b/boards/arm/pinetime_devkit0/pinetime_devkit0.yaml index 245346b1db8..081daced8ab 100644 --- a/boards/arm/pinetime_devkit0/pinetime_devkit0.yaml +++ b/boards/arm/pinetime_devkit0/pinetime_devkit0.yaml @@ -8,3 +8,6 @@ toolchain: - xtools ram: 64 flash: 512 +supported: + - kscan:touch +vendor: pine64 diff --git a/boards/arm/pinetime_devkit0/pinetime_devkit0_defconfig b/boards/arm/pinetime_devkit0/pinetime_devkit0_defconfig index fc8f45eceaa..ce594faf969 100644 --- a/boards/arm/pinetime_devkit0/pinetime_devkit0_defconfig +++ b/boards/arm/pinetime_devkit0/pinetime_devkit0_defconfig @@ -12,5 +12,3 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/pinnacle_100_dvk/pinnacle_100_dvk.yaml b/boards/arm/pinnacle_100_dvk/pinnacle_100_dvk.yaml index c935d100c32..153fb6cab08 100644 --- a/boards/arm/pinnacle_100_dvk/pinnacle_100_dvk.yaml +++ b/boards/arm/pinnacle_100_dvk/pinnacle_100_dvk.yaml @@ -20,3 +20,4 @@ supported: - usb_device - watchdog - netif:modem +vendor: lairdconnect diff --git a/boards/arm/pinnacle_100_dvk/pinnacle_100_dvk_defconfig b/boards/arm/pinnacle_100_dvk/pinnacle_100_dvk_defconfig index 010c72e8c07..0e6c950ae36 100644 --- a/boards/arm/pinnacle_100_dvk/pinnacle_100_dvk_defconfig +++ b/boards/arm/pinnacle_100_dvk/pinnacle_100_dvk_defconfig @@ -25,5 +25,3 @@ CONFIG_UART_CONSOLE=y # 32KHz clock source CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_150PPM=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/qemu_cortex_a9/qemu_cortex_a9.yaml b/boards/arm/qemu_cortex_a9/qemu_cortex_a9.yaml index e896b273b6d..cf8853c3d5f 100644 --- a/boards/arm/qemu_cortex_a9/qemu_cortex_a9.yaml +++ b/boards/arm/qemu_cortex_a9/qemu_cortex_a9.yaml @@ -24,3 +24,4 @@ testing: ignore_tags: - bluetooth - gpio +vendor: xlnx diff --git a/boards/arm/qemu_cortex_m0/doc/index.rst b/boards/arm/qemu_cortex_m0/doc/index.rst index f2fe07dd50a..7035f57b07f 100644 --- a/boards/arm/qemu_cortex_m0/doc/index.rst +++ b/boards/arm/qemu_cortex_m0/doc/index.rst @@ -64,7 +64,7 @@ Programming and Debugging ************************* Use this configuration to run basic Zephyr applications and kernel tests in the QEMU -emulated environment, for example, with the :ref:`synchronization_sample`: +emulated environment, for example, with the :zephyr:code-sample:`synchronization` sample: .. zephyr-app-commands:: :zephyr-app: samples/synchronization diff --git a/boards/arm/qemu_cortex_m0/qemu_cortex_m0_defconfig b/boards/arm/qemu_cortex_m0/qemu_cortex_m0_defconfig index a1b24f00c47..a169a86f8de 100644 --- a/boards/arm/qemu_cortex_m0/qemu_cortex_m0_defconfig +++ b/boards/arm/qemu_cortex_m0/qemu_cortex_m0_defconfig @@ -18,7 +18,5 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -CONFIG_PINCTRL=y - # icount is kinda broken when the NRF timer emulation is used CONFIG_QEMU_ICOUNT=n diff --git a/boards/arm/qemu_cortex_m3/doc/index.rst b/boards/arm/qemu_cortex_m3/doc/index.rst index 9a8d9afd6df..f07f6bf2166 100644 --- a/boards/arm/qemu_cortex_m3/doc/index.rst +++ b/boards/arm/qemu_cortex_m3/doc/index.rst @@ -70,7 +70,7 @@ Programming and Debugging ************************* Use this configuration to run basic Zephyr applications and kernel tests in the QEMU -emulated environment, for example, with the :ref:`synchronization_sample`: +emulated environment, for example, with the :zephyr:code-sample:`synchronization` sample: .. zephyr-app-commands:: :zephyr-app: samples/synchronization diff --git a/boards/arm/qemu_cortex_m3/qemu_cortex_m3.yaml b/boards/arm/qemu_cortex_m3/qemu_cortex_m3.yaml index 51388617d0e..cceafa8942e 100644 --- a/boards/arm/qemu_cortex_m3/qemu_cortex_m3.yaml +++ b/boards/arm/qemu_cortex_m3/qemu_cortex_m3.yaml @@ -15,3 +15,4 @@ flash: 256 testing: ignore_tags: - net +vendor: ti diff --git a/boards/arm/qemu_cortex_r5/doc/index.rst b/boards/arm/qemu_cortex_r5/doc/index.rst index bc86cda64c0..9fd59d117ac 100644 --- a/boards/arm/qemu_cortex_r5/doc/index.rst +++ b/boards/arm/qemu_cortex_r5/doc/index.rst @@ -64,7 +64,7 @@ Programming and Debugging ************************* Use this configuration to run basic Zephyr applications and kernel tests in the -QEMU emulated environment, for example, with the :ref:`synchronization_sample`: +QEMU emulated environment, for example, with the :zephyr:code-sample:`synchronization` sample: .. zephyr-app-commands:: :zephyr-app: samples/synchronization diff --git a/boards/arm/qemu_cortex_r5/qemu_cortex_r5.yaml b/boards/arm/qemu_cortex_r5/qemu_cortex_r5.yaml index 9a7212909df..17fbb1c8d94 100644 --- a/boards/arm/qemu_cortex_r5/qemu_cortex_r5.yaml +++ b/boards/arm/qemu_cortex_r5/qemu_cortex_r5.yaml @@ -14,3 +14,4 @@ testing: ignore_tags: - net - bluetooth +vendor: xlnx diff --git a/boards/arm/qomu/qomu.yaml b/boards/arm/qomu/qomu.yaml index 9ed10212dde..7e47a163ac9 100644 --- a/boards/arm/qomu/qomu.yaml +++ b/boards/arm/qomu/qomu.yaml @@ -10,3 +10,4 @@ testing: ignore_tags: - net - bluetooth +vendor: quicklogic diff --git a/boards/arm/quick_feather/quick_feather.yaml b/boards/arm/quick_feather/quick_feather.yaml index 7f92a190b64..9342b75994e 100644 --- a/boards/arm/quick_feather/quick_feather.yaml +++ b/boards/arm/quick_feather/quick_feather.yaml @@ -10,3 +10,4 @@ testing: ignore_tags: - net - bluetooth +vendor: quicklogic diff --git a/boards/arm/rak4631_nrf52840/rak4631_nrf52840.yaml b/boards/arm/rak4631_nrf52840/rak4631_nrf52840.yaml index 8a1c5a2272c..fb56f5275f6 100644 --- a/boards/arm/rak4631_nrf52840/rak4631_nrf52840.yaml +++ b/boards/arm/rak4631_nrf52840/rak4631_nrf52840.yaml @@ -19,3 +19,4 @@ supported: - usb_device - watchdog - lora +vendor: rak diff --git a/boards/arm/rak4631_nrf52840/rak4631_nrf52840_defconfig b/boards/arm/rak4631_nrf52840/rak4631_nrf52840_defconfig index 4cc2863efab..bfdc1718875 100644 --- a/boards/arm/rak4631_nrf52840/rak4631_nrf52840_defconfig +++ b/boards/arm/rak4631_nrf52840/rak4631_nrf52840_defconfig @@ -21,5 +21,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/rak5010_nrf52840/rak5010_nrf52840.yaml b/boards/arm/rak5010_nrf52840/rak5010_nrf52840.yaml index c32726dccec..1238add9d37 100644 --- a/boards/arm/rak5010_nrf52840/rak5010_nrf52840.yaml +++ b/boards/arm/rak5010_nrf52840/rak5010_nrf52840.yaml @@ -18,3 +18,4 @@ supported: - usb_cdc - usb_device - watchdog +vendor: rak diff --git a/boards/arm/rak5010_nrf52840/rak5010_nrf52840_defconfig b/boards/arm/rak5010_nrf52840/rak5010_nrf52840_defconfig index b908cb5debd..b7e873c3f03 100644 --- a/boards/arm/rak5010_nrf52840/rak5010_nrf52840_defconfig +++ b/boards/arm/rak5010_nrf52840/rak5010_nrf52840_defconfig @@ -21,5 +21,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/raytac_mdbt50q_db_33_nrf52833/raytac_mdbt50q_db_33_nrf52833_defconfig b/boards/arm/raytac_mdbt50q_db_33_nrf52833/raytac_mdbt50q_db_33_nrf52833_defconfig index 1212ba8928f..1176302a56d 100644 --- a/boards/arm/raytac_mdbt50q_db_33_nrf52833/raytac_mdbt50q_db_33_nrf52833_defconfig +++ b/boards/arm/raytac_mdbt50q_db_33_nrf52833/raytac_mdbt50q_db_33_nrf52833_defconfig @@ -25,5 +25,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/raytac_mdbt50q_db_40_nrf52840/raytac_mdbt50q_db_40_nrf52840_defconfig b/boards/arm/raytac_mdbt50q_db_40_nrf52840/raytac_mdbt50q_db_40_nrf52840_defconfig index 438343c6d9b..3651902f740 100644 --- a/boards/arm/raytac_mdbt50q_db_40_nrf52840/raytac_mdbt50q_db_40_nrf52840_defconfig +++ b/boards/arm/raytac_mdbt50q_db_40_nrf52840/raytac_mdbt50q_db_40_nrf52840_defconfig @@ -25,5 +25,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/CMakeLists.txt b/boards/arm/raytac_mdbt53_db_40_nrf5340/CMakeLists.txt new file mode 100644 index 00000000000..6a13dbb534e --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +if ((CONFIG_BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP OR CONFIG_BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP_NS) + AND CONFIG_BOARD_ENABLE_CPUNET) + zephyr_library() + zephyr_library_sources(raytac_mdbt53_db_40_nrf5340_cpunet_reset.c) +endif() diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/Kconfig b/boards/arm/raytac_mdbt53_db_40_nrf5340/Kconfig new file mode 100644 index 00000000000..caf06f347d5 --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/Kconfig @@ -0,0 +1,58 @@ +# Ratac MDBT53-DB-40 nRF5340 board configuration + +# Copyright (c) 2019 - 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP || BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP_NS + +config BOARD_ENABLE_DCDC_APP + bool "Application MCU DCDC converter" + select SOC_DCDC_NRF53X_APP + default y + +config BOARD_ENABLE_DCDC_NET + bool "Network MCU DCDC converter" + select SOC_DCDC_NRF53X_NET + default y + +config BOARD_ENABLE_DCDC_HV + bool "High Voltage DCDC converter" + select SOC_DCDC_NRF53X_HV + default y + +config BOARD_ENABLE_CPUNET + bool "NRF53 Network MCU" + select SOC_NRF_GPIO_FORWARDER_FOR_NRF5340 if \ + $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_GPIO_FORWARDER)) + help + This option enables releasing the Network 'force off' signal, which + as a consequence will power up the Network MCU during system boot. + Additionally, the option allocates GPIO pins that will be used by UARTE + of the Network MCU. + Note: GPIO pin allocation can only be configured by the secure Application + MCU firmware, so when this option is used with the non-secure version of + the board, the application needs to take into consideration, that the + secure firmware image must already have configured GPIO allocation for the + Network MCU. + default y if (BT || NRF_802154_SER_HOST) + +config DOMAIN_CPUNET_BOARD + string + default "raytac_mdbt53_db_40_nrf5340_cpunet" + depends on BOARD_ENABLE_CPUNET + help + The board which will be used for CPUNET domain when creating a multi + image application where one or more images should be located on + another board. For example hci_ipc on the nRF5340_cpunet for + Bluetooth applications. + +endif # BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP || BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP_NS + +config DOMAIN_CPUAPP_BOARD + string + default "raytac_mdbt53_db_40_nrf5340_cpuapp" + depends on BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUNET + help + The board which will be used for CPUAPP domain when creating a multi + image application where one or more images should be located on + another board. diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/Kconfig.board b/boards/arm/raytac_mdbt53_db_40_nrf5340/Kconfig.board new file mode 100644 index 00000000000..ff4b1ac6986 --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/Kconfig.board @@ -0,0 +1,18 @@ +# Raytac MDBT53-DB-40 NRF5340 board configuration + +# Copyright (c) 2019-2020 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if SOC_NRF5340_CPUAPP_QKAA + +config BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP + bool "Raytac MDBT53-DB-40 nRF5340 Application MCU" + +config BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP_NS + bool "Raytac MDBT53-DB-40 nRF5340 Application MCU non-secure" + +endif # SOC_NRF5340_CPUAPP_QKAA + +config BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUNET + bool "Raytac MDBT53-DB-40 NRF5340 Network MCU" + depends on SOC_NRF5340_CPUNET_QKAA diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/Kconfig.defconfig b/boards/arm/raytac_mdbt53_db_40_nrf5340/Kconfig.defconfig new file mode 100644 index 00000000000..f179e667d6b --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/Kconfig.defconfig @@ -0,0 +1,86 @@ +# Raytac MDBT53-DB-40 nRF5340 board configuration + +# Copyright (c) 2019-2020 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP || BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP_NS + +config BOARD + default "raytac_mdbt53_db_40_nrf5340_cpuapp" + +# Code Partition: +# +# For the secure version of the board the firmware is linked at the beginning +# of the flash, or into the code-partition defined in DT if it is intended to +# be loaded by MCUboot. If the secure firmware is to be combined with a non- +# secure image (TRUSTED_EXECUTION_SECURE=y), the secure FW image shall always +# be restricted to the size of its code partition. +# +# For the non-secure version of the board, the firmware +# must be linked into the code-partition (non-secure) defined in DT, regardless. +# Apply this configuration below by setting the Kconfig symbols used by +# the linker according to the information extracted from DT partitions. + +# SRAM Partition: +# +# If the secure firmware is to be combined with a non-secure image +# (TRUSTED_EXECUTION_SECURE=y), the secure FW image SRAM shall always +# be restricted to the secure image SRAM partition (sram-secure-partition). +# Otherwise (if TRUSTED_EXECUTION_SECURE is not set) the whole zephyr,sram +# may be used by the image. +# +# For the non-secure version of the board, the firmware image SRAM is +# always restricted to the allocated non-secure SRAM partition. +# +# Workaround for not being able to have commas in macro arguments +DT_CHOSEN_Z_CODE_PARTITION := zephyr,code-partition +DT_CHOSEN_Z_SRAM_PARTITION := zephyr,sram-secure-partition + +if BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP && TRUSTED_EXECUTION_SECURE + +config FLASH_LOAD_SIZE + default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) + +config SRAM_SIZE + default $(dt_chosen_reg_size_int,$(DT_CHOSEN_Z_SRAM_PARTITION),0,K) + +endif # BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP && TRUSTED_EXECUTION_SECURE + +if BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP_NS + +config FLASH_LOAD_OFFSET + default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) + +config FLASH_LOAD_SIZE + default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) + +endif # BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP_NS + +endif # BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP || BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP_NS + +config BOARD + default "raytac_mdbt53_dv_40_nrf5340_cpunet" if BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUNET + +config IPM_NRFX + default IPM + +config MBOX_NRFX_IPC + default MBOX + +if BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP || BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP_NS + +choice BT_HCI_BUS_TYPE + default BT_HCI_IPC if BT +endchoice + +config HEAP_MEM_POOL_SIZE + default 4096 if BT_HCI_IPC + +endif # BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP || BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP_NS + +if BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUNET + +config BT_CTLR + default y if BT + +endif # BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUNET diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/board.cmake b/boards/arm/raytac_mdbt53_db_40_nrf5340/board.cmake new file mode 100644 index 00000000000..8657aa50f1c --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/board.cmake @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP OR CONFIG_BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP_NS) + board_runner_args(jlink "--device=nrf5340_xxaa_app" "--speed=4000") +endif() + +if(CONFIG_BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUNET) + board_runner_args(jlink "--device=nrf5340_xxaa_net" "--speed=4000") +endif() + +include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake) +include(${ZEPHYR_BASE}/boards/common/nrfutil.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/doc/img/MDBT53-DB-40.jpg b/boards/arm/raytac_mdbt53_db_40_nrf5340/doc/img/MDBT53-DB-40.jpg new file mode 100644 index 00000000000..32525d94b0a Binary files /dev/null and b/boards/arm/raytac_mdbt53_db_40_nrf5340/doc/img/MDBT53-DB-40.jpg differ diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/doc/index.rst b/boards/arm/raytac_mdbt53_db_40_nrf5340/doc/index.rst new file mode 100644 index 00000000000..bcff494f91b --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/doc/index.rst @@ -0,0 +1,271 @@ +.. _raytac_mdbt53_db_40_nrf5340: + +Raytac MDBT53-DB-40 +################### + +Overview +******** + +Raytac MDBT53-DB-40 demo board is a development board based on the Raytac MDBT53-1M module, +using Nordic Semiconductor nRF5340 ARM Cortex-M33 SoC. Its design concept is to connect all +of the module's pins to 2.54mm pin headers. It is convenient for developers to verify whether +the modules are connected to other peripheral devices or sensors as a tool for software development. + +The nRF5340 inside the MDBT53-1M module is a +dual-core SoC based on the Arm® Cortex®-M33 architecture, with: + +* a full-featured Arm Cortex-M33F core with DSP instructions, FPU, and + Armv8-M Security Extension, running at up to 128 MHz, referred to as + the **application core** +* a secondary Arm Cortex-M33 core, with a reduced feature set, running + at a fixed 64 MHz, referred to as the **network core**. + +The raytac_mdbt53_db_40_nrf5340_cpuapp build target provides support for the application +core on the nRF5340 SoC. The raytac_mdbt53_db_40_nrf5340_cpuapp build target provides +support for the network core on the nRF5340 SoC. + +nRF5340 SoC provides support for the following devices: + +* :abbr:`ADC (Analog to Digital Converter)` +* CLOCK +* FLASH +* :abbr:`GPIO (General Purpose Input Output)` +* :abbr:`IDAU (Implementation Defined Attribution Unit)` +* :abbr:`I2C (Inter-Integrated Circuit)` +* :abbr:`MPU (Memory Protection Unit)` +* :abbr:`NVIC (Nested Vectored Interrupt Controller)` +* :abbr:`PWM (Pulse Width Modulation)` +* :abbr:`QSPI (Quad Serial Peripheral Interface)` +* RADIO (Bluetooth Low Energy and 802.15.4) +* :abbr:`RTC (nRF RTC System Clock)` +* Segger RTT (RTT Console) +* :abbr:`SPI (Serial Peripheral Interface)` +* :abbr:`UARTE (Universal asynchronous receiver-transmitter)` +* :abbr:`WDT (Watchdog Timer)` + +.. figure:: img/MDBT53-DB-40.jpg + :width: 442px + :align: center + :alt: MDBT53-DB-40 + + MDBT53-DB-40 (Credit: Raytac Corporation) + +More information about the board can be found at the `MDBT53-DB-40 website`_. +The `MDBT53-DB-40 Specification`_ contains the demo board's datasheet. +The `MDBT53-DB-40 Schematic`_ contains the demo board's schematic. + +Hardware +******** +- Module Demo Board build by MDBT53-1M +- Nordic nRF5340 SoC Solution +- A recommnded 3rd-party module by Nordic Semiconductor. +- Dual-core Arm® Cortex® M33 +- 1MB/256KB Flash Memory; 512kB/ 64kB RAM +- Supports BT5 Long Range Features +- Bluetooth specification v5.2 +- Supports Bluetooth Direction Finding & Mesh +- Supports Bluetooth low energy audio +- Certifications: FCC, IC, CE, Telec (MIC), KC, SRRC, NCC, RCM, WPC +- RoHs & Reach Compiant. +- 48 GPIO +- Chip Antenna +- Interfaces: SPI, UART, I2C, I2S, PWM, ADC, NFC, and USB +- Highly flexible multiprotocol SoC ideally suited for Bluetooth® Low Energy, ANT+, Zigbee, Thread (802.15.4) ultra low-power wireless applications. +- 4 User LEDs +- 4 User buttons +- 1 Mini USB connector for power supply +- SWD connector for FW programing +- J-Link interface for FW programing +- UART interface for UART communication + +Supported Features +================== + +The raytac_mdbt53_db_40_nrf52840_cpuapp board configuration supports the following +hardware features: + ++-----------+------------+----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+======================+ +| ADC | on-chip | adc | ++-----------+------------+----------------------+ +| CLOCK | on-chip | clock_control | ++-----------+------------+----------------------+ +| FLASH | on-chip | flash | ++-----------+------------+----------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+----------------------+ +| I2C(M) | on-chip | i2c | ++-----------+------------+----------------------+ +| MPU | on-chip | arch/arm | ++-----------+------------+----------------------+ +| NVIC | on-chip | arch/arm | ++-----------+------------+----------------------+ +| QSPI(M) | on-chip | nor | ++-----------+------------+----------------------+ +| PWM | on-chip | pwm | ++-----------+------------+----------------------+ +| RTC | on-chip | system clock | ++-----------+------------+----------------------+ +| SPI(M/S) | on-chip | spi | ++-----------+------------+----------------------+ +| SPU | on-chip | system protection | ++-----------+------------+----------------------+ +| UARTE | on-chip | serial | ++-----------+------------+----------------------+ +| WDT | on-chip | watchdog | ++-----------+------------+----------------------+ + +The raytac_mdbt53_db_40_nrf5340_cpunet board configuration supports the following +hardware features: + ++-----------+------------+----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+======================+ +| CLOCK | on-chip | clock_control | ++-----------+------------+----------------------+ +| FLASH | on-chip | flash | ++-----------+------------+----------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+----------------------+ +| I2C(M) | on-chip | i2c | ++-----------+------------+----------------------+ +| MPU | on-chip | arch/arm | ++-----------+------------+----------------------+ +| NVIC | on-chip | arch/arm | ++-----------+------------+----------------------+ +| RADIO | on-chip | Bluetooth, | +| | | ieee802154 | ++-----------+------------+----------------------+ +| RTC | on-chip | system clock | ++-----------+------------+----------------------+ +| SPI(M/S) | on-chip | spi | ++-----------+------------+----------------------+ +| UARTE | on-chip | serial | ++-----------+------------+----------------------+ +| WDT | on-chip | watchdog | ++-----------+------------+----------------------+ + +Other hardware features have not been enabled yet for this board. +See `MDBT53-DB-40 website`_ and `MDBT53-DB-40 Specification`_ +for a complete list of Raytac MDBT53-DB-40 board hardware features. + +Connections and IOs +=================== + +LED +--- + +* LED1 (green) = P0.28 +* LED2 (red) = P0.30 +* LED3 = P0.31 +* LED4 = P0.29 + +Push buttons +------------ + +* BUTTON1 = SW1 = P0.24 +* BUTTON2 = SW2 = P0.08 +* BUTTON3 = SW3 = P0.23 +* BUTTON4 = SW4 = P0.09 + +UART +---- +* RX = P0.22 +* TX = P0.20 +* RTS = P0.19 +* CTS = P0.21 + + +Security components +=================== + +- Implementation Defined Attribution Unit (`IDAU`_) on the application core. + The IDAU is implemented with the System Protection Unit and is used to + define secure and non-secure memory maps. By default, all of the memory + space (Flash, SRAM, and peripheral address space) is defined to be secure + accessible only. +- Secure boot. + +Programming and Debugging +************************* + +nRF5340 application core supports the Armv8-M Security Extension. +Applications built for the raytac_mdbt53_db_40_nrf5340_cpuapp board by +default boot in the Secure state. + +nRF5340 network core does not support the Armv8-M Security Extension. +nRF5340 IDAU may configure bus accesses by the nRF5340 network core +to have Secure attribute set; the latter allows to build and run +Secure only applications on the nRF5340 SoC. + +Applications for the ``raytac_mdbt53_db_40_nrf5340`` board configuration can be +built, flashed, and debugged in the usual way. See :ref:`build_an_application` and +:ref:`application_run` for more details on building and running. + +.. note:: + Flashing and Debugging Zephyr onto the raytac_mdbt53_db_40_nrf5340 board + requires an external J-Link programmer. The programmer is attached to the J1 + or J9 SWD connector. + + +Flashing +======== + +Follow the instructions in the :ref:`nordic_segger` page to install +and configure all the necessary software. Further information can be +found in :ref:`nordic_segger_flashing`. Then build and flash +applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +.. warning:: + + The nRF5340 has a flash read-back protection feature. When flash read-back + protection is active, you will need to recover the chip before reflashing. + If you are flashing with :ref:`west `, run + this command for more details on the related ``--recover`` option: + +Here is an example for the :ref:`hello_world` application. + +Use a USB to TTL converter to connect the computer and raytac_mdbt53_db_40_nrf5340 +J10 connector. Then run your favorite terminal program to listen for output. + +.. code-block:: console + + $ minicom -D -b 115200 + +Replace :code:`` with the port where the USB to TTL converter +can be found. For example, under Linux, :code:`/dev/ttyUSB0`. + +Then build and flash the application in the usual way. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: raytac_mdbt53_db_40_nrf5340 + :goals: build flash + +Debugging +========= + +The ``raytac_mdbt53_db_40_nrf5340`` board does not have an on-board-J-Link debug IC, +however, instructions from the :ref:`nordic_segger` page also apply to this board. +Use the Debug out connector of nRF52x DK to connect to the J1 connector, and use SEGGER +J-Link OB IF to debug. + +Refer to the :ref:`nordic_segger` page to learn about debugging Nordic +boards with a Segger IC. + + +References +********** + +.. _IDAU: + https://developer.arm.com/docs/100690/latest/attribution-units-sau-and-idau +.. _MDBT53-DB-40 website: + https://www.raytac.com/product/ins.php?index_id=139 +.. _MDBT53-DB-40 Specification: + https://www.raytac.com/download/index.php?index_id=60 +.. _MDBT53-DB-40 Schematic: + https://www.raytac.com/upload/catalog_b/8b5e364600a9cc8c53a869733e97f07e.jpg +.. _J-Link Software and documentation pack: + https://www.segger.com/jlink-software.html diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/pre_dt_board.cmake b/boards/arm/raytac_mdbt53_db_40_nrf5340/pre_dt_board.cmake new file mode 100644 index 00000000000..fb045e38545 --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/pre_dt_board.cmake @@ -0,0 +1,8 @@ +# Copyright (c) 2021 Linaro Limited +# SPDX-License-Identifier: Apache-2.0 + +# Suppress "unique_unit_address_if_enabled" to handle the following overlaps: +# - flash-controller@39000 & kmu@39000 +# - power@5000 & clock@5000 +# - /reserved-memory/image@20000000 & /reserved-memory/image_s@20000000 +list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp.dts b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp.dts new file mode 100644 index 00000000000..aed84474a38 --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Raytac Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "raytac_mdbt53_db_40_nrf5340_cpuapp_common.dts" + +/ { + model = "Raytac MDBT53-DB-40 NRF5340 Application"; + compatible = "raytac,raytac-mdbt53-db-40-nrf5340-cpuapp"; + + chosen { + zephyr,sram = &sram0_image; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + zephyr,sram-secure-partition = &sram0_s; + zephyr,sram-non-secure-partition = &sram0_ns; + }; +}; + +zephyr_udc0: &usbd { + compatible = "nordic,nrf-usbd"; + status = "okay"; +}; diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp.yaml b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp.yaml new file mode 100644 index 00000000000..4f70a9e375d --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp.yaml @@ -0,0 +1,22 @@ +identifier: raytac_mdbt53_db_40_nrf5340_cpuapp +name: RAYTAC-MDBT53-DB-40-NRF5340-application-MCU +type: mcu +arch: arm +toolchain: + - gnuarmemb + - xtools + - zephyr +ram: 448 +flash: 1024 +supported: + - gpio + - i2c + - i2s + - pwm + - qspi + - spi + - uart + - watchdog + - usb_cdc + - usb_device + - netif:openthread diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp_common-pinctrl.dtsi b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp_common-pinctrl.dtsi new file mode 100644 index 00000000000..3a3e39f824f --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp_common-pinctrl.dtsi @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2023 Raytac Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + i2c1_default: i2c1_default { + group1 { + psels = , + ; + }; + }; + + i2c1_sleep: i2c1_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + uart0_default: uart0_default { + group1 { + psels = , + , + , + ; + }; + }; + + uart0_sleep: uart0_sleep { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; + + uart1_default: uart1_default { + group1 { + psels = , + , + , + ; + }; + }; + + uart1_sleep: uart1_sleep { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; + + pwm0_default: pwm0_default { + group1 { + psels = ; + }; + }; + + pwm0_sleep: pwm0_sleep { + group1 { + psels = ; + low-power-enable; + }; + }; + + qspi_default: qspi_default { + group1 { + psels = , + , + , + , + , + ; + }; + }; + + qspi_sleep: qspi_sleep { + group1 { + psels = , + , + , + , + , + ; + low-power-enable; + }; + }; + + spi2_default: spi2_default { + group1 { + psels = , + , + ; + }; + }; + + spi2_sleep: spi2_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; + + spi3_default: spi3_default { + group1 { + psels = , + , + ; + }; + }; + + spi3_sleep: spi3_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; + + spi4_default: spi4_default { + group1 { + psels = , + , + ; + }; + }; + + spi4_sleep: spi4_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; + +}; diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp_common.dts b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp_common.dts new file mode 100644 index 00000000000..3af7de1f17e --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp_common.dts @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2023 Raytac Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "raytac_mdbt53_db_40_nrf5340_cpuapp_common-pinctrl.dtsi" +#include + +/ { + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,uart-mcumgr = &uart0; + zephyr,bt-mon-uart = &uart0; + zephyr,bt-c2h-uart = &uart0; + zephyr,bt-hci-ipc = &ipc0; + nordic,802154-spinel-ipc = &ipc0; + zephyr,ieee802154 = &ieee802154; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; + label = "Green LED 0"; + }; + led1: led_1 { + gpios = <&gpio0 30 GPIO_ACTIVE_LOW>; + label = "Red LED 1"; + }; + led2: led_2 { + gpios = <&gpio0 31 GPIO_ACTIVE_LOW>; + label = "LED 2"; + }; + led3: led_3 { + gpios = <&gpio0 29 GPIO_ACTIVE_LOW>; + label = "LED 3"; + }; + }; + + pwmleds { + compatible = "pwm-leds"; + pwm_led0: pwm_led_0 { + pwms = <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_INVERTED>; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + gpios = <&gpio0 24 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "Push button 1 (SW1)"; + zephyr,code = ; + }; + button1: button_1 { + gpios = <&gpio0 8 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "Push button 2 (SW2)"; + zephyr,code = ; + }; + button2: button_2 { + gpios = <&gpio0 23 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "Push button 3 (SW3)"; + zephyr,code = ; + }; + button3: button_3 { + gpios = <&gpio0 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "Push button 4 (SW4)"; + zephyr,code = ; + }; + }; + + gpio_fwd: nrf-gpio-forwarder { + compatible = "nordic,nrf-gpio-forwarder"; + status = "okay"; + uart { + gpios = <&gpio1 1 0>, <&gpio1 0 0>, <&gpio0 11 0>, <&gpio0 10 0>; + }; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led0; + led1 = &led1; + led2 = &led2; + led3 = &led3; + pwm-led0 = &pwm_led0; + sw0 = &button0; + sw1 = &button1; + sw2 = &button2; + sw3 = &button3; + bootloader-led0 = &led0; + mcuboot-button0 = &button0; + mcuboot-led0 = &led0; + watchdog0 = &wdt0; + }; +}; + +&adc { + status = "okay"; +}; + +&gpiote { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&i2c1 { + compatible = "nordic,nrf-twim"; + status = "okay"; + pinctrl-0 = <&i2c1_default>; + pinctrl-1 = <&i2c1_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-1 = <&uart0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&uart1 { + compatible = "nordic,nrf-uarte"; + current-speed = <115200>; + pinctrl-0 = <&uart1_default>; + pinctrl-1 = <&uart1_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&pwm0 { + status = "okay"; + pinctrl-0 = <&pwm0_default>; + pinctrl-1 = <&pwm0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&qspi { + status = "okay"; + pinctrl-0 = <&qspi_default>; + pinctrl-1 = <&qspi_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&spi2 { + compatible = "nordic,nrf-spim"; + status = "okay"; + cs-gpios = <&gpio0 25 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&spi2_default>; + pinctrl-1 = <&spi2_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&spi3 { + compatible = "nordic,nrf-spim"; + status = "okay"; + cs-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&spi3_default>; + pinctrl-1 = <&spi3_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&spi4 { + compatible = "nordic,nrf-spim"; + status = "okay"; + cs-gpios = <&gpio0 11 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&spi4_default>; + pinctrl-1 = <&spi4_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&flash0 { + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x00010000>; + }; + slot0_partition: partition@10000 { + label = "image-0"; + }; + slot0_ns_partition: partition@50000 { + label = "image-0-nonsecure"; + }; + slot1_partition: partition@80000 { + label = "image-1"; + }; + slot1_ns_partition: partition@c0000 { + label = "image-1-nonsecure"; + }; + }; +}; + +&ieee802154 { + status = "okay"; +}; + +zephyr_udc0: &usbd { + compatible = "nordic,nrf-usbd"; + status = "okay"; +}; + +/ { + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + sram0_image: image@20000000 { + /* Zephyr image(s) memory */ + }; + + sram0_s: image_s@20000000 { + /* Secure image memory */ + }; + + sram0_ns: image_ns@20040000 { + /* Non-Secure image memory */ + }; + }; +}; + +/* Include partition configuration file */ +#include "raytac_mdbt53_db_40_nrf5340_cpuapp_partition_conf.dts" diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp_defconfig b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp_defconfig new file mode 100644 index 00000000000..cf048d3d213 --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp_defconfig @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_NRF53X=y +CONFIG_SOC_NRF5340_CPUAPP_QKAA=y +CONFIG_BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# Enable TrustZone-M +CONFIG_ARM_TRUSTZONE_M=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable uart driver +CONFIG_SERIAL=y + +# enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp_ns.dts b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp_ns.dts new file mode 100644 index 00000000000..541de94d8cc --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp_ns.dts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Raytac Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "raytac_mdbt53_db_40_nrf5340_cpuapp_common.dts" + +/ { + model = "Raytac MDBT53-DB-40 NRF5340 Application"; + compatible = "raytac,raytac-mdbt53-db-40-cpuapp"; + + chosen { + zephyr,sram = &sram0_ns; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_ns_partition; + }; +}; diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp_ns.yaml b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp_ns.yaml new file mode 100644 index 00000000000..5c402d46273 --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp_ns.yaml @@ -0,0 +1,21 @@ +identifier: raytac_mdbt53_db_40_nrf5340_cpuapp_ns +name: RAYTAC-MDBT53-DB-40-NRF52840-application-MCU-Non-Secure +type: mcu +arch: arm +toolchain: + - gnuarmemb + - xtools + - zephyr +ram: 192 +flash: 192 +supported: + - counter + - i2c + - pwm + - watchdog + - spi + - uart + - usb_cdc + - usb_device + - netif:openthread + - gpio diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp_ns_defconfig b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp_ns_defconfig new file mode 100644 index 00000000000..e0759063b9a --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp_ns_defconfig @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_NRF53X=y +CONFIG_SOC_NRF5340_CPUAPP_QKAA=y +CONFIG_BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP_NS=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# Enable TrustZone-M +CONFIG_ARM_TRUSTZONE_M=y + +# This Board implies building Non-Secure firmware +CONFIG_TRUSTED_EXECUTION_NONSECURE=y + +# Enable GPIO +CONFIG_GPIO=y + +# Enable UART driver +CONFIG_SERIAL=y + +# Enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp_partition_conf.dts b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp_partition_conf.dts new file mode 100644 index 00000000000..74788769f01 --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpuapp_partition_conf.dts @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 Raytac Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Default Flash planning for raytac_mdbt53_db_40_nrf5340 CPUAPP (Application MCU). + * + * Zephyr build for nRF5340 with ARM TrustZone-M support, + * implies building Secure and Non-Secure Zephyr images. + * + * Secure image will be placed, by default, in flash0 + * (or in slot0, if MCUboot is present). + * Secure image will use sram0 for system memory. + * + * Non-Secure image will be placed in slot0_ns, and use + * sram0_ns for system memory. + * + * Note that the Secure image only requires knowledge of + * the beginning of the Non-Secure image (not its size). + */ + +&slot0_partition { + reg = <0x00010000 0x40000>; +}; + +&slot0_ns_partition { + reg = <0x00050000 0x30000>; +}; + +&slot1_partition { + reg = <0x00080000 0x40000>; +}; + +&slot1_ns_partition { + reg = <0x000c0000 0x30000>; +}; + +/* Default SRAM planning when building for nRF5340 with + * ARM TrustZone-M support + * - Lowest 256 kB SRAM allocated to Secure image (sram0_s) + * - Middle 192 kB allocated to Non-Secure image (sram0_ns) + * - Upper 64 kB SRAM allocated as Shared memory (sram0_shared) + * (see raytac_mdbt53_db_40_nrf5340_shared_sram_planning_conf.dts) + */ +&sram0_image { + reg = <0x20000000 DT_SIZE_K(448)>; +}; + +&sram0_s { + reg = <0x20000000 0x40000>; +}; + +&sram0_ns { + reg = <0x20040000 0x30000>; +}; + +/* Include shared RAM configuration file */ +#include "raytac_mdbt53_db_40_nrf5340_shared_sram_planning_conf.dts" diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpunet-pinctrl.dtsi b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpunet-pinctrl.dtsi new file mode 100644 index 00000000000..33b38bb76db --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpunet-pinctrl.dtsi @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Raytac Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + uart0_default: uart0_default { + group1 { + psels = , + , + , + ; + }; + }; + + uart0_sleep: uart0_sleep { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; + +}; diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpunet.dts b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpunet.dts new file mode 100644 index 00000000000..f9c834ef228 --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpunet.dts @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 Raytac Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "raytac_mdbt53_db_40_nrf5340_cpunet-pinctrl.dtsi" +#include "raytac_mdbt53_db_40_nrf5340_cpunet_common.dts" + +/ { + model = "Raytac MDBT53-DB-40 NRF5340 Network"; + compatible = "raytac,raytac-mdbt53-db-40-nrf5340-cpunet"; + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,uart-mcumgr = &uart0; + zephyr,bt-mon-uart = &uart0; + zephyr,bt-c2h-uart = &uart0; + zephyr,sram = &sram1; + zephyr,flash = &flash1; + zephyr,code-partition = &slot0_partition; + zephyr,bt-hci-ipc = &ipc0; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + watchdog0 = &wdt0; + }; +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-1 = <&uart0_sleep>; + pinctrl-names = "default", "sleep"; +}; diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpunet.yaml b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpunet.yaml new file mode 100644 index 00000000000..bf82a0627c1 --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpunet.yaml @@ -0,0 +1,21 @@ +# Raytac MDBT53_DB_40_NRF5340 board configuration + +# Copyright (c) 2023 Raytac Corporation +# SPDX-License-Identifier: Apache-2.0 +identifier: raytac_mdbt53_db_40_nrf5340_cpunet +name: RAYTAC MDBT53-DB-40-NRF5340-network-MCU +type: mcu +arch: arm +toolchain: + - gnuarmemb + - xtools + - zephyr +ram: 64 +flash: 256 +supported: + - watchdog + - gpio + - i2c + - spi + - uart + - counter diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpunet_common.dts b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpunet_common.dts new file mode 100644 index 00000000000..c04101e11c1 --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpunet_common.dts @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 Raytac Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&gpiote { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&timer0 { + status = "okay"; +}; + +&timer1 { + status = "okay"; +}; + +&timer2 { + status = "okay"; +}; + +&flash1 { + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0xc000>; + }; + slot0_partition: partition@c000 { + label = "image-0"; + reg = <0x0000C000 0x17000>; + }; + slot1_partition: partition@23000 { + label = "image-1"; + reg = <0x00023000 0x17000>; + }; + storage_partition: partition@3a000 { + label = "storage"; + reg = <0x0003a000 0x6000>; + }; + }; +}; + +/* Include shared RAM configuration file */ +#include "raytac_mdbt53_db_40_nrf5340_shared_sram_planning_conf.dts" diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpunet_defconfig b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpunet_defconfig new file mode 100644 index 00000000000..92b16601314 --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpunet_defconfig @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_NRF53X=y +CONFIG_SOC_NRF5340_CPUNET_QKAA=y +CONFIG_BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUNET=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable uart driver +CONFIG_SERIAL=y + +# enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpunet_reset.c b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpunet_reset.c new file mode 100644 index 00000000000..97ae3fc1bd0 --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_cpunet_reset.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2019-2021 Nordic Semiconductor ASA. + * Copyright (c) 2023 Raytac Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(raytac_mdbt53_db_40_nrf5340_cpuapp, CONFIG_LOG_DEFAULT_LEVEL); + +#if defined(CONFIG_BT_CTLR_DEBUG_PINS_CPUAPP) +#include <../subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/debug.h> +#else +#define DEBUG_SETUP() +#endif + +static void remoteproc_mgr_config(void) +{ +#if !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) || defined(CONFIG_BUILD_WITH_TFM) + /* Route Bluetooth Controller Debug Pins */ + DEBUG_SETUP(); +#endif /* !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) || defined(CONFIG_BUILD_WITH_TFM) */ + +#if !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) + /* Retain nRF5340 Network MCU in Secure domain (bus + * accesses by Network MCU will have Secure attribute set). + */ + NRF_SPU->EXTDOMAIN[0].PERM = 1 << 4; +#endif /* !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) */ +} + +static int remoteproc_mgr_boot(const struct device *dev) +{ + + /* Secure domain may configure permissions for the Network MCU. */ + remoteproc_mgr_config(); + +#if !defined(CONFIG_TRUSTED_EXECUTION_SECURE) + /* + * Building Zephyr with CONFIG_TRUSTED_EXECUTION_SECURE=y implies + * building also a Non-Secure image. The Non-Secure image will, in + * this case do the remainder of actions to properly configure and + * boot the Network MCU. + */ + + /* Release the Network MCU, 'Release force off signal' */ + NRF_RESET->NETWORK.FORCEOFF = RESET_NETWORK_FORCEOFF_FORCEOFF_Release; + + LOG_DBG("Network MCU released."); +#endif /* !CONFIG_TRUSTED_EXECUTION_SECURE */ + + return 0; +} + +SYS_INIT(remoteproc_mgr_boot, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); diff --git a/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_shared_sram_planning_conf.dts b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_shared_sram_planning_conf.dts new file mode 100644 index 00000000000..aa162f85a5a --- /dev/null +++ b/boards/arm/raytac_mdbt53_db_40_nrf5340/raytac_mdbt53_db_40_nrf5340_shared_sram_planning_conf.dts @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Raytac Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Default shared SRAM planning when building for nRF5340. + * This file is included by both nRF5340 CPUAPP (Application MCU) + * and nRF5340 CPUNET (Network MCU). + * - 64 kB SRAM allocated as Shared memory (sram0_shared) + * - Region defined after the image SRAM of Application MCU + */ + +/ { + chosen { + /* shared memory reserved for the inter-processor communication */ + zephyr,ipc_shm = &sram0_shared; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + sram0_shared: memory@20070000 { + /* SRAM allocated to shared memory */ + reg = <0x20070000 0x10000>; + }; + }; +}; diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/CMakeLists.txt b/boards/arm/raytac_mdbt53v_db_40_nrf5340/CMakeLists.txt new file mode 100644 index 00000000000..556e084598c --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +if ((CONFIG_BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP OR CONFIG_BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP_NS) + AND CONFIG_BOARD_ENABLE_CPUNET) + zephyr_library() + zephyr_library_sources(raytac_mdbt53v_db_40_nrf5340_cpunet_reset.c) +endif() diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/Kconfig b/boards/arm/raytac_mdbt53v_db_40_nrf5340/Kconfig new file mode 100644 index 00000000000..02b44de6198 --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/Kconfig @@ -0,0 +1,58 @@ +# Ratac MDBT53V-DB-40 nRF5340 board configuration + +# Copyright (c) 2019 - 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP || BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP_NS + +config BOARD_ENABLE_DCDC_APP + bool "Application MCU DCDC converter" + select SOC_DCDC_NRF53X_APP + default y + +config BOARD_ENABLE_DCDC_NET + bool "Network MCU DCDC converter" + select SOC_DCDC_NRF53X_NET + default y + +config BOARD_ENABLE_DCDC_HV + bool "High Voltage DCDC converter" + select SOC_DCDC_NRF53X_HV + default y + +config BOARD_ENABLE_CPUNET + bool "NRF53 Network MCU" + select SOC_NRF_GPIO_FORWARDER_FOR_NRF5340 if \ + $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_GPIO_FORWARDER)) + help + This option enables releasing the Network 'force off' signal, which + as a consequence will power up the Network MCU during system boot. + Additionally, the option allocates GPIO pins that will be used by UARTE + of the Network MCU. + Note: GPIO pin allocation can only be configured by the secure Application + MCU firmware, so when this option is used with the non-secure version of + the board, the application needs to take into consideration, that the + secure firmware image must already have configured GPIO allocation for the + Network MCU. + default y if (BT || NRF_802154_SER_HOST) + +config DOMAIN_CPUNET_BOARD + string + default "raytac_mdbt53v_db_40_nrf5340_cpunet" + depends on BOARD_ENABLE_CPUNET + help + The board which will be used for CPUNET domain when creating a multi + image application where one or more images should be located on + another board. For example hci_ipc on the nRF5340_cpunet for + Bluetooth applications. + +endif # BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP || BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP_NS + +config DOMAIN_CPUAPP_BOARD + string + default "raytac_mdbt53v_db_40_nrf5340_cpuapp" + depends on BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUNET + help + The board which will be used for CPUAPP domain when creating a multi + image application where one or more images should be located on + another board. diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/Kconfig.board b/boards/arm/raytac_mdbt53v_db_40_nrf5340/Kconfig.board new file mode 100644 index 00000000000..69bb4b876ea --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/Kconfig.board @@ -0,0 +1,18 @@ +# Raytac MDBT53-DB-40 NRF5340 board configuration + +# Copyright (c) 2019-2020 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if SOC_NRF5340_CPUAPP_QKAA + +config BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP + bool "Raytac MDBT53V-DB-40 nRF5340 Application MCU" + +config BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP_NS + bool "Raytac MDBT53V-DB-40 nRF5340 Application MCU non-secure" + +endif # SOC_NRF5340_CPUAPP_QKAA + +config BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUNET + bool "Raytac MDBT53V-DB-40 NRF5340 Network MCU" + depends on SOC_NRF5340_CPUNET_QKAA diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/Kconfig.defconfig b/boards/arm/raytac_mdbt53v_db_40_nrf5340/Kconfig.defconfig new file mode 100644 index 00000000000..10f4373b352 --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/Kconfig.defconfig @@ -0,0 +1,86 @@ +# Raytac MDBT53V-DB-40 nRF5340 board configuration + +# Copyright (c) 2019-2020 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP || BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP_NS + +config BOARD + default "raytac_mdbt53v_db_40_nrf5340_cpuapp" if BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP || BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP_NS + +# Code Partition: +# +# For the secure version of the board the firmware is linked at the beginning +# of the flash, or into the code-partition defined in DT if it is intended to +# be loaded by MCUboot. If the secure firmware is to be combined with a non- +# secure image (TRUSTED_EXECUTION_SECURE=y), the secure FW image shall always +# be restricted to the size of its code partition. +# +# For the non-secure version of the board, the firmware +# must be linked into the code-partition (non-secure) defined in DT, regardless. +# Apply this configuration below by setting the Kconfig symbols used by +# the linker according to the information extracted from DT partitions. + +# SRAM Partition: +# +# If the secure firmware is to be combined with a non-secure image +# (TRUSTED_EXECUTION_SECURE=y), the secure FW image SRAM shall always +# be restricted to the secure image SRAM partition (sram-secure-partition). +# Otherwise (if TRUSTED_EXECUTION_SECURE is not set) the whole zephyr,sram +# may be used by the image. +# +# For the non-secure version of the board, the firmware image SRAM is +# always restricted to the allocated non-secure SRAM partition. +# +# Workaround for not being able to have commas in macro arguments +DT_CHOSEN_Z_CODE_PARTITION := zephyr,code-partition +DT_CHOSEN_Z_SRAM_PARTITION := zephyr,sram-secure-partition + +if BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP && TRUSTED_EXECUTION_SECURE + +config FLASH_LOAD_SIZE + default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) + +config SRAM_SIZE + default $(dt_chosen_reg_size_int,$(DT_CHOSEN_Z_SRAM_PARTITION),0,K) + +endif # BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP && TRUSTED_EXECUTION_SECURE + +if BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP_NS + +config FLASH_LOAD_OFFSET + default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) + +config FLASH_LOAD_SIZE + default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) + +endif # BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP_NS + +endif # BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP || BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP_NS + +config BOARD + default "raytac_mdbt53v_dv_40_nrf5340_cpunet" if BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUNET + +config IPM_NRFX + default IPM + +config MBOX_NRFX_IPC + default MBOX + +if BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP || BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP_NS + +choice BT_HCI_BUS_TYPE + default BT_HCI_IPC if BT +endchoice + +config HEAP_MEM_POOL_SIZE + default 4096 if BT_HCI_IPC + +endif # BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP || BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP_NS + +if BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUNET + +config BT_CTLR + default y if BT + +endif # BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUNET diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/board.cmake b/boards/arm/raytac_mdbt53v_db_40_nrf5340/board.cmake new file mode 100644 index 00000000000..8662675aba3 --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/board.cmake @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP OR CONFIG_BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP_NS) + board_runner_args(jlink "--device=nrf5340_xxaa_app" "--speed=4000") +endif() + +if(CONFIG_BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUNET) + board_runner_args(jlink "--device=nrf5340_xxaa_net" "--speed=4000") +endif() + +include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/doc/img/MDBT53V-DB-40.jpg b/boards/arm/raytac_mdbt53v_db_40_nrf5340/doc/img/MDBT53V-DB-40.jpg new file mode 100644 index 00000000000..e53ce080218 Binary files /dev/null and b/boards/arm/raytac_mdbt53v_db_40_nrf5340/doc/img/MDBT53V-DB-40.jpg differ diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/doc/index.rst b/boards/arm/raytac_mdbt53v_db_40_nrf5340/doc/index.rst new file mode 100644 index 00000000000..ca38f03a781 --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/doc/index.rst @@ -0,0 +1,261 @@ +.. _raytac_mdbt53v_db_40_nrf5340: + +Raytac MDBT53V-DB-40 +#################### + +Overview +******** + +Raytac MDBT53V-DB-40 demo board is a development board based on the Raytac MDBT53V-1M module, +using Nordic Semiconductor nRF5340 ARM Cortex-M33 SoC. Its design concept is to connect all +of the module's pins to 2.54mm pin headers. It is convenient for developers to verify whether +the modules are connected to other peripheral devices or sensors as a tool for software development. + +The nRF5340 inside the MDBT53V-1M module is a +dual-core SoC based on the Arm® Cortex®-M33 architecture, with: + +* a full-featured Arm Cortex-M33F core with DSP instructions, FPU, and + Armv8-M Security Extension, running at up to 128 MHz, referred to as + the **application core** +* a secondary Arm Cortex-M33 core, with a reduced feature set, running + at a fixed 64 MHz, referred to as the **network core**. + +The raytac_mdbt53v_db_40_nrf5340_cpuapp build target provides support for the application +core on the nRF5340 SoC. The raytac_mdbt53v_db_40_nrf5340_cpuapp build target provides +support for the network core on the nRF5340 SoC. + +nRF5340 SoC provides support for the following devices: + +* :abbr:`ADC (Analog to Digital Converter)` +* CLOCK +* FLASH +* :abbr:`GPIO (General Purpose Input Output)` +* :abbr:`IDAU (Implementation Defined Attribution Unit)` +* :abbr:`I2C (Inter-Integrated Circuit)` +* :abbr:`MPU (Memory Protection Unit)` +* :abbr:`NVIC (Nested Vectored Interrupt Controller)` +* :abbr:`PWM (Pulse Width Modulation)` +* RADIO (Bluetooth Low Energy and 802.15.4) +* :abbr:`RTC (nRF RTC System Clock)` +* Segger RTT (RTT Console) +* :abbr:`SPI (Serial Peripheral Interface)` +* :abbr:`UARTE (Universal asynchronous receiver-transmitter)` +* :abbr:`WDT (Watchdog Timer)` + +.. figure:: img/MDBT53V-DB-40.jpg + :width: 442px + :align: center + :alt: MDBT53V-DB-40 + + MDBT53V-DB-40 (Credit: Raytac Corporation) + +More information about the board can be found at the `MDBT53V-DB-40 website`_. +The `MDBT53V-DB-40 Specification`_ contains the demo board's datasheet. +The `MDBT53V-DB-40 Schematic`_ contains the demo board's schematic. + +Hardware +******** +- Module Demo Board build by MDBT53V-1M +- Nordic nRF5340 SoC Solution +- A recommnded 3rd-party module by Nordic Semiconductor. +- Dual-core Arm® Cortex® M33 +- 1MB/256KB Flash Memory; 512kB/ 64kB RAM +- Supports BT5 Long Range Features +- Bluetooth specification v5.2 +- Supports BT5 Long Range Features +- Supports Bluetooth Direction Finding & Mesh +- Supports Bluetooth low energy audio +- Cerifications: FCC, IC, CE, Telec(MIC), KC, SRRC, NCC, RCM, WPC +- RoHs & Reach Compiant. +- 25 GPIO +- Chip Antenna +- Interfaces: SPI, UART, I2C, I2S, PWM, ADC, and NFC +- Highly flexible multiprotocol SoC ideally suited for Bluetooth® Low Energy, ANT+, Zigbee, Thread (802.15.4) ultra low-power wireless applications. +- 1 User LEDs +- 3 User buttons +- 1 Mini USB connector for power supply +- SWD connector for FW programing +- J-Link interface for FW programing + +Supported Features +================== + +The raytac_mdbt53v_db_40_nrf5340_cpuapp board configuration supports the following +hardware features: + ++-----------+------------+----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+======================+ +| ADC | on-chip | adc | ++-----------+------------+----------------------+ +| CLOCK | on-chip | clock_control | ++-----------+------------+----------------------+ +| FLASH | on-chip | flash | ++-----------+------------+----------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+----------------------+ +| I2C(M) | on-chip | i2c | ++-----------+------------+----------------------+ +| MPU | on-chip | arch/arm | ++-----------+------------+----------------------+ +| NVIC | on-chip | arch/arm | ++-----------+------------+----------------------+ +| PWM | on-chip | pwm | ++-----------+------------+----------------------+ +| RTC | on-chip | system clock | ++-----------+------------+----------------------+ +| SPI(M/S) | on-chip | spi | ++-----------+------------+----------------------+ +| UARTE | on-chip | serial | ++-----------+------------+----------------------+ +| WDT | on-chip | watchdog | ++-----------+------------+----------------------+ + +The raytac_mdbt53v_db_40_nrf5340_cpunet board configuration supports the following +hardware features: + ++-----------+------------+----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+======================+ +| CLOCK | on-chip | clock_control | ++-----------+------------+----------------------+ +| FLASH | on-chip | flash | ++-----------+------------+----------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+----------------------+ +| I2C(M) | on-chip | i2c | ++-----------+------------+----------------------+ +| MPU | on-chip | arch/arm | ++-----------+------------+----------------------+ +| NVIC | on-chip | arch/arm | ++-----------+------------+----------------------+ +| RADIO | on-chip | Bluetooth, | +| | | ieee802154 | ++-----------+------------+----------------------+ +| RTC | on-chip | system clock | ++-----------+------------+----------------------+ +| SPI(M/S) | on-chip | spi | ++-----------+------------+----------------------+ +| UARTE | on-chip | serial | ++-----------+------------+----------------------+ +| WDT | on-chip | watchdog | ++-----------+------------+----------------------+ + +Other hardware features have not been enabled yet for this board. +See `MDBT53V-DB-40 website`_ and `MDBT53V-DB-40 Specification`_ +for a complete list of Raytac MDBT53V-DB-40 board hardware features. + +Connections and IOs +=================== + +LED +--- + +* LED1 (green) = P0.31 + +Push buttons +------------ + +* BUTTON1 = SW1 = P1.13 +* BUTTON2 = SW2 = P0.25 +* BUTTON3 = SW3 = P0.26 + +HSPI +---- +* MOSI = P0.9 +* MISO = P0.10 +* SCK = P0.8 +* CSN = P0.11 +* DCX = P0.12 + +QSPI +---- +* SCK = P0.17 +* CSN = P0.18 +* DATA0 = P0.13 +* DATA1 = P0.14 +* DATA2 = P0.15 +* DATA3 = P0.16 + +Security components +=================== + +- Implementation Defined Attribution Unit (`IDAU`_) on the application core. + The IDAU is implemented with the System Protection Unit and is used to + define secure and non-secure memory maps. By default, all of the memory + space (Flash, SRAM, and peripheral address space) is defined to be secure + accessible only. +- Secure boot. + +Programming and Debugging +************************* + +nRF5340 application core supports the Armv8-M Security Extension. +Applications built for the raytac_mdbt53v_db_40_nrf5340_cpuapp board by +default boot in the Secure state. + +nRF5340 network core does not support the Armv8-M Security Extension. +nRF5340 IDAU may configure bus accesses by the nRF5340 network core +to have Secure attribute set; the latter allows to build and run +Secure only applications on the nRF5340 SoC. + +Applications for the ``raytac_mdbt53v_db_40_nrf5340`` board configuration can be +built, flashed, and debugged in the usual way. See :ref:`build_an_application` and +:ref:`application_run` for more details on building and running. + +.. note:: + Flashing and Debugging Zephyr onto the raytac_mdbt53v_db_40_nrf5340 board + requires an external J-Link programmer. The programmer is attached to the J1 + or J9 SWD connector. + + +Flashing +======== + +Follow the instructions in the :ref:`nordic_segger` page to install +and configure all the necessary software. Further information can be +found in :ref:`nordic_segger_flashing`. Then build and flash +applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +Here is an example for the :ref:`hello_world` application. + +Use a USB to TTL converter to connect the computer and raytac_mdbt53v_db_40_nrf5340 +J13 connector pin 8(RX), 9(TX) and GND. Then run your favorite terminal program to listen for output. + +.. code-block:: console + + $ minicom -D -b 115200 + +Replace :code:`` with the port where the USB to TTL converter +can be found. For example, under Linux, :code:`/dev/ttyUSB0`. + +Then build and flash the application in the usual way. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: raytac_mdbt53v_db_40_nrf5340 + :goals: build flash + +Debugging +========= + +The ``raytac_mdbt53v_db_40_nrf5340`` board does not have an on-board-J-Link debug IC, +however, instructions from the :ref:`nordic_segger` page also apply to this board. +Use the Debug out connector of nRF52x DK to connect to the J1 connector, and use SEGGER +J-Link OB IF to debug. + + +References +********** + +.. _IDAU: + https://developer.arm.com/docs/100690/latest/attribution-units-sau-and-idau +.. _MDBT53V-DB-40 website: + https://www.raytac.com/product/ins.php?index_id=140 +.. _MDBT53V-DB-40 Specification: + https://www.raytac.com/download/index.php?index_id=62 +.. _MDBT53V-DB-40 Schematic: + https://www.raytac.com/upload/catalog_b/f2c33d52dca8cd6546c95938bc0cb295.jpg +.. _J-Link Software and documentation pack: + https://www.segger.com/jlink-software.html diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/pre_dt_board.cmake b/boards/arm/raytac_mdbt53v_db_40_nrf5340/pre_dt_board.cmake new file mode 100644 index 00000000000..fb045e38545 --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/pre_dt_board.cmake @@ -0,0 +1,8 @@ +# Copyright (c) 2021 Linaro Limited +# SPDX-License-Identifier: Apache-2.0 + +# Suppress "unique_unit_address_if_enabled" to handle the following overlaps: +# - flash-controller@39000 & kmu@39000 +# - power@5000 & clock@5000 +# - /reserved-memory/image@20000000 & /reserved-memory/image_s@20000000 +list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp.dts b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp.dts new file mode 100644 index 00000000000..6b5890d7472 --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 Raytac Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "raytac_mdbt53v_db_40_nrf5340_cpuapp_common.dts" + +/ { + model = "Raytac MDBT53V-DB-40 NRF5340 Application"; + compatible = "raytac,raytac-mdbt53v-db-40-nrf5340-cpuapp"; + + chosen { + zephyr,sram = &sram0_image; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + zephyr,sram-secure-partition = &sram0_s; + zephyr,sram-non-secure-partition = &sram0_ns; + }; +}; diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp.yaml b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp.yaml new file mode 100644 index 00000000000..c9552cb6202 --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp.yaml @@ -0,0 +1,20 @@ +identifier: raytac_mdbt53v_db_40_nrf5340_cpuapp +name: RAYTAC-MDBT53V-DB-40-NRF5340-application-MCU +type: mcu +arch: arm +toolchain: + - gnuarmemb + - xtools + - zephyr +ram: 448 +flash: 1024 +supported: + - counter + - gpio + - i2c + - i2s + - pwm + - qspi + - spi + - watchdog + - netif:openthread diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp_common-pinctrl.dtsi b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp_common-pinctrl.dtsi new file mode 100644 index 00000000000..0574b5b3892 --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp_common-pinctrl.dtsi @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2023 Raytac Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + i2c1_default: i2c1_default { + group1 { + psels = , + ; + }; + }; + + i2c1_sleep: i2c1_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + uart0_default: uart0_default { + group1 { + psels = , + , + , + ; + }; + }; + + uart0_sleep: uart0_sleep { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; + + uart1_default: uart1_default { + group1 { + psels = , + , + , + ; + }; + }; + + uart1_sleep: uart1_sleep { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; + + pwm0_default: pwm0_default { + group1 { + psels = ; + }; + }; + + pwm0_sleep: pwm0_sleep { + group1 { + psels = ; + low-power-enable; + }; + }; + + qspi_default: qspi_default { + group1 { + psels = , + , + , + , + , + ; + }; + }; + + qspi_sleep: qspi_sleep { + group1 { + psels = , + , + , + , + , + ; + low-power-enable; + }; + }; + + spi4_default: spi4_default { + group1 { + psels = , + , + ; + }; + }; + + spi4_sleep: spi4_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; + +}; diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp_common.dts b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp_common.dts new file mode 100644 index 00000000000..c7d7521d08b --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp_common.dts @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2023 Raytac Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "raytac_mdbt53v_db_40_nrf5340_cpuapp_common-pinctrl.dtsi" +#include + +/ { + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,uart-mcumgr = &uart0; + zephyr,bt-mon-uart = &uart0; + zephyr,bt-c2h-uart = &uart0; + zephyr,bt-hci-ipc = &ipc0; + nordic,802154-spinel-ipc = &ipc0; + zephyr,ieee802154 = &ieee802154; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; + label = "Green LED 0"; + }; + }; + + pwmleds { + compatible = "pwm-leds"; + pwm_led0: pwm_led_0 { + pwms = <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_INVERTED>; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + gpios = <&gpio0 24 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "Push button 1"; + zephyr,code = ; + }; + button1: button_1 { + gpios = <&gpio0 8 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "Push button 2"; + zephyr,code = ; + }; + button2: button_2 { + gpios = <&gpio0 23 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "Push button 3"; + zephyr,code = ; + }; + }; + + gpio_fwd: nrf-gpio-forwarder { + compatible = "nordic,nrf-gpio-forwarder"; + status = "okay"; + uart { + gpios = <&gpio1 1 0>, <&gpio1 0 0>, <&gpio0 11 0>, <&gpio0 10 0>; + }; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led0; + pwm-led0 = &pwm_led0; + sw0 = &button0; + sw1 = &button1; + sw2 = &button2; + bootloader-led0 = &led0; + mcuboot-button0 = &button0; + mcuboot-led0 = &led0; + watchdog0 = &wdt0; + }; +}; + +&adc { + status = "okay"; +}; + +&gpiote { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&i2c1 { + compatible = "nordic,nrf-twim"; + status = "okay"; + pinctrl-0 = <&i2c1_default>; + pinctrl-1 = <&i2c1_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-1 = <&uart0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&uart1 { + compatible = "nordic,nrf-uarte"; + current-speed = <115200>; + pinctrl-0 = <&uart1_default>; + pinctrl-1 = <&uart1_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&pwm0 { + status = "okay"; + pinctrl-0 = <&pwm0_default>; + pinctrl-1 = <&pwm0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&qspi { + status = "okay"; + pinctrl-0 = <&qspi_default>; + pinctrl-1 = <&qspi_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&spi4 { + compatible = "nordic,nrf-spim"; + status = "okay"; + cs-gpios = <&gpio0 11 0>; + pinctrl-0 = <&spi4_default>; + pinctrl-1 = <&spi4_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&flash0 { + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x00010000>; + }; + slot0_partition: partition@10000 { + label = "image-0"; + }; + slot0_ns_partition: partition@50000 { + label = "image-0-nonsecure"; + }; + slot1_partition: partition@80000 { + label = "image-1"; + }; + slot1_ns_partition: partition@c0000 { + label = "image-1-nonsecure"; + }; + /* 0xf0000 to 0xf7fff reserved for TF-M partitions */ + storage_partition: partition@f8000 { + label = "storage"; + reg = <0x000f8000 0x00008000>; + }; + }; +}; + +&ieee802154 { + status = "okay"; +}; + +/ { + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + sram0_image: image@20000000 { + /* Zephyr image(s) memory */ + }; + + sram0_s: image_s@20000000 { + /* Secure image memory */ + }; + + sram0_ns: image_ns@20040000 { + /* Non-Secure image memory */ + }; + }; +}; + +/* Include partition configuration file */ +#include "raytac_mdbt53v_db_40_nrf5340_cpuapp_partition_conf.dts" diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp_defconfig b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp_defconfig new file mode 100644 index 00000000000..6966d7d728c --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp_defconfig @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_NRF53X=y +CONFIG_SOC_NRF5340_CPUAPP_QKAA=y +CONFIG_BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# Enable TrustZone-M +CONFIG_ARM_TRUSTZONE_M=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable uart driver +CONFIG_SERIAL=y + +# enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp_ns.dts b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp_ns.dts new file mode 100644 index 00000000000..0713304bc15 --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp_ns.dts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Raytac Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "raytac_mdbt53v_db_40_nrf5340_cpuapp_common.dts" + +/ { + model = "Raytac MDBT53V-DB-40 NRF5340 Application"; + compatible = "raytac,raytac-mdbt53v-db-40-nrf5340-cpuapp"; + + chosen { + zephyr,sram = &sram0_ns; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_ns_partition; + }; +}; diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp_ns.yaml b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp_ns.yaml new file mode 100644 index 00000000000..5251dc8737f --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp_ns.yaml @@ -0,0 +1,16 @@ +identifier: raytac_mdbt53v_db_40_nrf5340_cpuapp_ns +name: RAYTAC-MDBT53V-DB-40-NRF52840-application-MCU-Non-Secure +type: mcu +arch: arm +toolchain: + - gnuarmemb + - xtools + - zephyr +ram: 192 +flash: 192 +supported: + - i2c + - pwm + - watchdog + - netif:openthread + - gpio diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp_ns_defconfig b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp_ns_defconfig new file mode 100644 index 00000000000..44e16cd65ac --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp_ns_defconfig @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_NRF53X=y +CONFIG_SOC_NRF5340_CPUAPP_QKAA=y +CONFIG_BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP_NS=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# Enable TrustZone-M +CONFIG_ARM_TRUSTZONE_M=y + +# This Board implies building Non-Secure firmware +CONFIG_TRUSTED_EXECUTION_NONSECURE=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable uart driver +CONFIG_SERIAL=y + +# enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp_partition_conf.dts b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp_partition_conf.dts new file mode 100644 index 00000000000..207d58f4e75 --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpuapp_partition_conf.dts @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 Raytac Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Default Flash planning for raytac_mdbt53v_db_40_nrf5340 CPUAPP (Application MCU). + * + * Zephyr build for nRF5340 with ARM TrustZone-M support, + * implies building Secure and Non-Secure Zephyr images. + * + * Secure image will be placed, by default, in flash0 + * (or in slot0, if MCUboot is present). + * Secure image will use sram0 for system memory. + * + * Non-Secure image will be placed in slot0_ns, and use + * sram0_ns for system memory. + * + * Note that the Secure image only requires knowledge of + * the beginning of the Non-Secure image (not its size). + */ + +&slot0_partition { + reg = <0x00010000 0x40000>; +}; + +&slot0_ns_partition { + reg = <0x00050000 0x30000>; +}; + +&slot1_partition { + reg = <0x00080000 0x40000>; +}; + +&slot1_ns_partition { + reg = <0x000c0000 0x30000>; +}; + +/* Default SRAM planning when building for nRF5340 with + * ARM TrustZone-M support + * - Lowest 256 kB SRAM allocated to Secure image (sram0_s) + * - Middle 192 kB allocated to Non-Secure image (sram0_ns) + * - Upper 64 kB SRAM allocated as Shared memory (sram0_shared) + * (see raytac_mdbt53v_db_40_nrf5340_shared_sram_planning_conf.dts) + */ +&sram0_image { + reg = <0x20000000 DT_SIZE_K(448)>; +}; + +&sram0_s { + reg = <0x20000000 0x40000>; +}; + +&sram0_ns { + reg = <0x20040000 0x30000>; +}; + +/* Include shared RAM configuration file */ +#include "raytac_mdbt53v_db_40_nrf5340_shared_sram_planning_conf.dts" diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpunet-pinctrl.dtsi b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpunet-pinctrl.dtsi new file mode 100644 index 00000000000..51197c008bb --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpunet-pinctrl.dtsi @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Raytac Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + uart0_default: uart0_default { + group1 { + psels = , + , + , + ; + }; + }; + + uart0_sleep: uart0_sleep { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; + +}; diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpunet.dts b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpunet.dts new file mode 100644 index 00000000000..14f0f114986 --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpunet.dts @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 Raytac Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "raytac_mdbt53v_db_40_nrf5340_cpunet-pinctrl.dtsi" +#include "raytac_mdbt53v_db_40_nrf5340_cpunet_common.dts" +/ { + model = "Raytac MDBT53V-DB-40 NRF5340 Network"; + compatible = "raytac,raytac-mdbt53v-db-40-nrf5340-cpunet"; + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,uart-mcumgr = &uart0; + zephyr,bt-mon-uart = &uart0; + zephyr,bt-c2h-uart = &uart0; + zephyr,sram = &sram1; + zephyr,flash = &flash1; + zephyr,code-partition = &slot0_partition; + zephyr,bt-hci-ipc = &ipc0; + }; + + + /* These aliases are provided for compatibility with samples */ + aliases { + watchdog0 = &wdt0; + }; +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-1 = <&uart0_sleep>; + pinctrl-names = "default", "sleep"; +}; diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpunet.yaml b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpunet.yaml new file mode 100644 index 00000000000..a76a74a6598 --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpunet.yaml @@ -0,0 +1,20 @@ +# Raytac MDBT53V_DB_40_NRF5340 board configuration + +# Copyright (c) 2023 Raytac Corporation +# SPDX-License-Identifier: Apache-2.0 +identifier: raytac_mdbt53v_db_40_nrf5340_cpunet +name: RAYTAC MDBT53V-DB-40-NRF5340-network-MCU +type: mcu +arch: arm +toolchain: + - gnuarmemb + - xtools + - zephyr +ram: 64 +flash: 256 +supported: + - watchdog + - gpio + - i2c + - spi + - uart diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpunet_common.dts b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpunet_common.dts new file mode 100644 index 00000000000..643bebf6e38 --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpunet_common.dts @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 Raytac Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&gpiote { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&timer0 { + status = "okay"; +}; + +&timer1 { + status = "okay"; +}; + +&timer2 { + status = "okay"; +}; + +&flash1 { + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0xc000>; + }; + slot0_partition: partition@c000 { + label = "image-0"; + reg = <0x0000C000 0x17000>; + }; + slot1_partition: partition@23000 { + label = "image-1"; + reg = <0x00023000 0x17000>; + }; + storage_partition: partition@3a000 { + label = "storage"; + reg = <0x0003a000 0x6000>; + }; + }; +}; + +/* Include shared RAM configuration file */ +#include "raytac_mdbt53v_db_40_nrf5340_shared_sram_planning_conf.dts" diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpunet_defconfig b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpunet_defconfig new file mode 100644 index 00000000000..94f21fb4c98 --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpunet_defconfig @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_NRF53X=y +CONFIG_SOC_NRF5340_CPUNET_QKAA=y +CONFIG_BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUNET=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable uart driver +CONFIG_SERIAL=y + +# enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpunet_reset.c b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpunet_reset.c new file mode 100644 index 00000000000..fd48ae16fd6 --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_cpunet_reset.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2019-2021 Nordic Semiconductor ASA. + * Copyright (c) 2023 Raytac Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(raytac_mdbt53v_db_40_nrf5340_cpuapp, CONFIG_LOG_DEFAULT_LEVEL); + +#if defined(CONFIG_BT_CTLR_DEBUG_PINS_CPUAPP) +#include <../subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/debug.h> +#else +#define DEBUG_SETUP() +#endif + +static void remoteproc_mgr_config(void) +{ +#if !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) || defined(CONFIG_BUILD_WITH_TFM) + /* Route Bluetooth Controller Debug Pins */ + DEBUG_SETUP(); +#endif /* !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) || defined(CONFIG_BUILD_WITH_TFM) */ + +#if !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) + /* Retain nRF5340 Network MCU in Secure domain (bus + * accesses by Network MCU will have Secure attribute set). + */ + NRF_SPU->EXTDOMAIN[0].PERM = 1 << 4; +#endif /* !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) */ +} + +static int remoteproc_mgr_boot(const struct device *dev) +{ + + /* Secure domain may configure permissions for the Network MCU. */ + remoteproc_mgr_config(); + +#if !defined(CONFIG_TRUSTED_EXECUTION_SECURE) + /* + * Building Zephyr with CONFIG_TRUSTED_EXECUTION_SECURE=y implies + * building also a Non-Secure image. The Non-Secure image will, in + * this case do the remainder of actions to properly configure and + * boot the Network MCU. + */ + + /* Release the Network MCU, 'Release force off signal' */ + NRF_RESET->NETWORK.FORCEOFF = RESET_NETWORK_FORCEOFF_FORCEOFF_Release; + + LOG_DBG("Network MCU released."); +#endif /* !CONFIG_TRUSTED_EXECUTION_SECURE */ + + return 0; +} + +SYS_INIT(remoteproc_mgr_boot, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); diff --git a/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_shared_sram_planning_conf.dts b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_shared_sram_planning_conf.dts new file mode 100644 index 00000000000..aa162f85a5a --- /dev/null +++ b/boards/arm/raytac_mdbt53v_db_40_nrf5340/raytac_mdbt53v_db_40_nrf5340_shared_sram_planning_conf.dts @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Raytac Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Default shared SRAM planning when building for nRF5340. + * This file is included by both nRF5340 CPUAPP (Application MCU) + * and nRF5340 CPUNET (Network MCU). + * - 64 kB SRAM allocated as Shared memory (sram0_shared) + * - Region defined after the image SRAM of Application MCU + */ + +/ { + chosen { + /* shared memory reserved for the inter-processor communication */ + zephyr,ipc_shm = &sram0_shared; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + sram0_shared: memory@20070000 { + /* SRAM allocated to shared memory */ + reg = <0x20070000 0x10000>; + }; + }; +}; diff --git a/boards/arm/rcar_h3_salvatorx/rcar_h3_salvatorx_cr7.yaml b/boards/arm/rcar_h3_salvatorx/rcar_h3_salvatorx_cr7.yaml index 17a5d80668a..f751adbcc47 100644 --- a/boards/arm/rcar_h3_salvatorx/rcar_h3_salvatorx_cr7.yaml +++ b/boards/arm/rcar_h3_salvatorx/rcar_h3_salvatorx_cr7.yaml @@ -13,3 +13,4 @@ supported: testing: ignore_tags: - isotp +vendor: renesas diff --git a/boards/arm/rcar_h3ulcb/rcar_h3ulcb_cr7.yaml b/boards/arm/rcar_h3ulcb/rcar_h3ulcb_cr7.yaml index 61f8cbc3ac2..09d5ae1c93f 100644 --- a/boards/arm/rcar_h3ulcb/rcar_h3ulcb_cr7.yaml +++ b/boards/arm/rcar_h3ulcb/rcar_h3ulcb_cr7.yaml @@ -14,3 +14,4 @@ supported: testing: ignore_tags: - isotp +vendor: renesas diff --git a/boards/arm/rddrone_fmuk66/rddrone_fmuk66.yaml b/boards/arm/rddrone_fmuk66/rddrone_fmuk66.yaml index ecab5d4c34d..44723b330b3 100644 --- a/boards/arm/rddrone_fmuk66/rddrone_fmuk66.yaml +++ b/boards/arm/rddrone_fmuk66/rddrone_fmuk66.yaml @@ -17,3 +17,4 @@ supported: - spi - usb_device - watchdog +vendor: nxp diff --git a/boards/arm/reel_board/doc/index.rst b/boards/arm/reel_board/doc/index.rst index 2dfe60ffeff..dec81bd88ec 100644 --- a/boards/arm/reel_board/doc/index.rst +++ b/boards/arm/reel_board/doc/index.rst @@ -462,8 +462,7 @@ Meaning of the Power Source Switch positions: X9 or X5. USB - link board BASE is powered from from USB connector - (via DCDC converter). + link board BASE is powered from USB connector (via DCDC converter). RB link board BASE is powered from reel board. The available power is @@ -544,8 +543,8 @@ Testing the LEDs and buttons There are 2 samples that allow you to test that the buttons (switches) and LEDs on the board are working properly with Zephyr: -* :ref:`blinky-sample` -* :ref:`button-sample` +* :zephyr:code-sample:`blinky` +* :zephyr:code-sample:`button` You can build and flash the examples to make sure Zephyr is running correctly on your board. diff --git a/boards/arm/reel_board/reel_board.yaml b/boards/arm/reel_board/reel_board.yaml index d47f29b350d..07b5087b6c6 100644 --- a/boards/arm/reel_board/reel_board.yaml +++ b/boards/arm/reel_board/reel_board.yaml @@ -19,3 +19,4 @@ supported: - arduino_i2c - arduino_spi - arduino_gpio +vendor: phytec diff --git a/boards/arm/reel_board/reel_board_defconfig b/boards/arm/reel_board/reel_board_defconfig index 850506692ba..8e88a3b3231 100644 --- a/boards/arm/reel_board/reel_board_defconfig +++ b/boards/arm/reel_board/reel_board_defconfig @@ -16,5 +16,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/reel_board/reel_board_v2.yaml b/boards/arm/reel_board/reel_board_v2.yaml index 4785e376fa0..2b27622e089 100644 --- a/boards/arm/reel_board/reel_board_v2.yaml +++ b/boards/arm/reel_board/reel_board_v2.yaml @@ -19,3 +19,4 @@ supported: - arduino_i2c - arduino_spi - arduino_gpio +vendor: phytec diff --git a/boards/arm/reel_board/reel_board_v2_defconfig b/boards/arm/reel_board/reel_board_v2_defconfig index 2ac0610f78c..fcec54b6d0c 100644 --- a/boards/arm/reel_board/reel_board_v2_defconfig +++ b/boards/arm/reel_board/reel_board_v2_defconfig @@ -16,5 +16,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/rm1xx_dvk/rm1xx_dvk.yaml b/boards/arm/rm1xx_dvk/rm1xx_dvk.yaml index 00cb5f4c96f..c673fd4d55e 100644 --- a/boards/arm/rm1xx_dvk/rm1xx_dvk.yaml +++ b/boards/arm/rm1xx_dvk/rm1xx_dvk.yaml @@ -14,3 +14,4 @@ supported: testing: ignore_tags: - net +vendor: lairdconnect diff --git a/boards/arm/ronoth_lodev/doc/index.rst b/boards/arm/ronoth_lodev/doc/index.rst index f1c60567a99..58f0756ecb3 100644 --- a/boards/arm/ronoth_lodev/doc/index.rst +++ b/boards/arm/ronoth_lodev/doc/index.rst @@ -8,7 +8,7 @@ Overview ======== The Ronoth_ LoDev_ is a small open source board containing a `AcSIP S76S`_ SiP from AcSIP_. -The `full LoDev design details`_ are available on on GitHub. The LoDev_ board can be purchased +The `full LoDev design details`_ are available on GitHub. The LoDev_ board can be purchased from Ronoth_ or from CrowdSupply_. The S76S contains an STMicro STM32L073RZ MCU, a `Semtech SX1276`_ LoRaWAN transceiver, diff --git a/boards/arm/rpi_pico/doc/index.rst b/boards/arm/rpi_pico/doc/index.rst index 69cb6acd2ce..c94698f14fe 100644 --- a/boards/arm/rpi_pico/doc/index.rst +++ b/boards/arm/rpi_pico/doc/index.rst @@ -140,6 +140,16 @@ Zephyr does not (currently) assemble PIO programs. Rather, they should be manually assembled and embedded in source code. An example of how this is done can be found at `drivers/serial/uart_rpi_pico_pio.c`. +Sample: SPI via PIO +==================== + +The :zephyr_file:`samples/sensor/bme280/README.rst` sample includes a +demonstration of using the PIO SPI driver to communicate with an +environmental sensor. The PIO SPI driver supports using any +combination of GPIO pins for an SPI bus, as well as allowing up to +four independent SPI buses on a single board (using the two SPI +devices as well as both PIO devices). + Programming and Debugging ************************* @@ -152,7 +162,7 @@ Using SEGGER JLink You can Flash the rpi_pico with a SEGGER JLink debug probe as described in :ref:`Building, Flashing and Debugging `. -Here is an example of building and flashing the :ref:`blinky-sample` application. +Here is an example of building and flashing the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -187,7 +197,7 @@ Depending on the interface used (such as JLink), you might need to checkout to a branch that supports this interface, before proceeding. Build and install OpenOCD as described in the README. -Here is an example of building and flashing the :ref:`blinky-sample` application. +Here is an example of building and flashing the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -247,7 +257,7 @@ Using OpenOCD Install OpenOCD as described for flashing the board. -Here is an example for debugging the :ref:`blinky-sample` application. +Here is an example for debugging the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/rpi_pico/rpi_pico-common.dtsi b/boards/arm/rpi_pico/rpi_pico-common.dtsi index 4cc49ce5181..54f12e53843 100644 --- a/boards/arm/rpi_pico/rpi_pico-common.dtsi +++ b/boards/arm/rpi_pico/rpi_pico-common.dtsi @@ -119,6 +119,10 @@ pinctrl-names = "default"; }; +&timer { + status = "okay"; +}; + &wdt0 { status = "okay"; }; diff --git a/boards/arm/rpi_pico/rpi_pico.yaml b/boards/arm/rpi_pico/rpi_pico.yaml index d3baa1f1822..485cfde0db5 100644 --- a/boards/arm/rpi_pico/rpi_pico.yaml +++ b/boards/arm/rpi_pico/rpi_pico.yaml @@ -19,3 +19,4 @@ supported: - pwm - flash - dma + - counter diff --git a/boards/arm/rpi_pico/rpi_pico_w.yaml b/boards/arm/rpi_pico/rpi_pico_w.yaml index adc102da731..32bf9ef078f 100644 --- a/boards/arm/rpi_pico/rpi_pico_w.yaml +++ b/boards/arm/rpi_pico/rpi_pico_w.yaml @@ -19,3 +19,4 @@ supported: - pwm - flash - dma + - pio diff --git a/boards/arm/ruuvi_ruuvitag/doc/index.rst b/boards/arm/ruuvi_ruuvitag/doc/index.rst index 9e827c0941b..5ab0ea9cfc0 100644 --- a/boards/arm/ruuvi_ruuvitag/doc/index.rst +++ b/boards/arm/ruuvi_ruuvitag/doc/index.rst @@ -168,8 +168,8 @@ Testing the LEDs and buttons on the RuuviTag There are 2 samples that allow you to test that the buttons (switches) and LEDs on the board are working properly with Zephyr: -* :ref:`blinky-sample` -* :ref:`button-sample` +* :zephyr:code-sample:`blinky` +* :zephyr:code-sample:`button` You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in :file:`boards/arm/ruuvi_ruuvitag/ruuvi_ruuvitag.dts`. diff --git a/boards/arm/ruuvi_ruuvitag/ruuvi_ruuvitag.yaml b/boards/arm/ruuvi_ruuvitag/ruuvi_ruuvitag.yaml index 43bbfae0fc6..151e614cbfb 100644 --- a/boards/arm/ruuvi_ruuvitag/ruuvi_ruuvitag.yaml +++ b/boards/arm/ruuvi_ruuvitag/ruuvi_ruuvitag.yaml @@ -16,3 +16,4 @@ supported: - counter - nvs - watchdog +vendor: ruuvi diff --git a/boards/arm/ruuvi_ruuvitag/ruuvi_ruuvitag_defconfig b/boards/arm/ruuvi_ruuvitag/ruuvi_ruuvitag_defconfig index 7e28dde8423..08403e5d814 100644 --- a/boards/arm/ruuvi_ruuvitag/ruuvi_ruuvitag_defconfig +++ b/boards/arm/ruuvi_ruuvitag/ruuvi_ruuvitag_defconfig @@ -8,6 +8,11 @@ CONFIG_BOARD_RUUVI_RUUVITAG=y # Enable MPU CONFIG_ARM_MPU=y +# Enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y + # Enable RTT CONFIG_USE_SEGGER_RTT=y diff --git a/boards/arm/rzt2m_starterkit/Kconfig.board b/boards/arm/rzt2m_starterkit/Kconfig.board new file mode 100644 index 00000000000..9fddcf006a4 --- /dev/null +++ b/boards/arm/rzt2m_starterkit/Kconfig.board @@ -0,0 +1,6 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_RZT2M_STARTER_KIT + bool "RZ/T2M Starter Kit Board" + depends on SOC_RENESAS_RZT2M diff --git a/boards/arm/rzt2m_starterkit/Kconfig.defconfig b/boards/arm/rzt2m_starterkit/Kconfig.defconfig new file mode 100644 index 00000000000..9699b23963c --- /dev/null +++ b/boards/arm/rzt2m_starterkit/Kconfig.defconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_RZT2M_STARTER_KIT + +config BOARD + default "rzt2m_starter_kit" + +endif diff --git a/boards/arm/rzt2m_starterkit/board.cmake b/boards/arm/rzt2m_starterkit/board.cmake new file mode 100644 index 00000000000..dd92d0e905a --- /dev/null +++ b/boards/arm/rzt2m_starterkit/board.cmake @@ -0,0 +1,11 @@ +# +# Copyright (c) 2023 Antmicro +# +# SPDX-License-Identifier: Apache-2.0 +# + +board_set_debugger_ifnset(jlink) +board_set_flasher_ifnset(jlink) + +board_runner_args(jlink "--device=R9A07G075M2") +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/arm/rzt2m_starterkit/doc/index.rst b/boards/arm/rzt2m_starterkit/doc/index.rst new file mode 100644 index 00000000000..e965585f6cb --- /dev/null +++ b/boards/arm/rzt2m_starterkit/doc/index.rst @@ -0,0 +1,95 @@ +.. _rzt2m_starterkit: + +Renesas Starter Kit+ for RZ/T2M +=============================== + +Overview +******** + +The Renesas Starter Kit+ for RZ/T2M is an evaluation and development kit for the RZ/T2M MPU. +The board is powered through a 5V input via a DC Power Jack or USB Type-C Connector. + +.. figure:: rzt2m_starterkit.png + :width: 800px + :align: center + :alt: Starter Kit+ for RZ/T2M + + Starter Kit+ for RZ/T2M (Credit: Renesas) + +Hardware +******** + +The board utilizes the SoC of part no. R9A07G075M24GBG, with 2MB of RAM. + +It has several on-board memory components: +* SDRAM (256MBit), +* NOR Flash (256MBit), +* Octa Flash (512MBit), +* HyperRAM (512Mbit), +* QSPI Serial Flash (512Mbit), +* I2C EEPROM (32Kbit). + +The communication interfaces include: +* Debug interfaces (J-Link, MIPI-10, MIPI-20), +* Ethernet, +* CAN, +* USB, +* RS485, +* UART, +* I2C, +* SPI. + +Supported Features +================== + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| PINCTRL | on-chip | pinctrl | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ + +Other hardware features are not currently supported by the port. + +Connections and IOs +=================== + +By default, the board is configured for use with: +* UART0 connected to the USB serial port (pins K18, K19), +* UART3 connected to the PMOD Header (J25, pins H16, G20), +* LEDs defined as `led0`, `led1`, `led2` and `led3`, + +The Zephyr console uses UART0. + +Programming and Debugging +************************* + +Debugging +========= + +Connect to the board using the J-Link On-board USB connector. +Use `west` to start the debug server: + +.. code-block:: console + + west debugserver + +Connect GDB to the server and load an application: + +.. code-block:: + + target remote :2331 + file build/zephyr/zephyr.elf + load + +References +********** + +.. _RZT2M Product page: https://www.renesas.com/us/en/products/microcontrollers-microprocessors/rz-mpus/rzt2m-high-performance-multi-function-mpu-realizing-high-speed-processing-and-high-precision-control diff --git a/boards/arm/rzt2m_starterkit/doc/rzt2m_starterkit.png b/boards/arm/rzt2m_starterkit/doc/rzt2m_starterkit.png new file mode 100644 index 00000000000..960df4fdbb5 Binary files /dev/null and b/boards/arm/rzt2m_starterkit/doc/rzt2m_starterkit.png differ diff --git a/boards/arm/rzt2m_starterkit/rzt2m_starter_kit.dts b/boards/arm/rzt2m_starterkit/rzt2m_starter_kit.dts new file mode 100644 index 00000000000..2568a542b5e --- /dev/null +++ b/boards/arm/rzt2m_starterkit/rzt2m_starter_kit.dts @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include + +/ { + model = "RZT/2M Starter Kit"; + compatible = "renesas,rzt2m_starter_kit"; + + chosen { + zephyr,sram = &cpu0_atcm; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + }; + + aliases { + led0 = &led0; + }; + + leds { + compatible = "gpio-leds"; + led0: led0 { + gpios = <&gpio19 6 0>; + label = "led0"; + }; + led1: led1 { + gpios = <&gpio19 4 0>; + label = "led1"; + }; + led2: led2 { + gpios = <&gpio20 0 0>; + label = "led2"; + }; + led3: led3 { + gpios = <&gpio23 4 0>; + label = "led3"; + }; + }; +}; + + +&pinctrl { + uart0_default: uart0_default { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + uart3_default: uart3_default { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + input-enable; + }; + }; +}; + +&uart0 { + status = "okay"; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; +}; + +&uart3 { + status = "okay"; + pinctrl-0 = <&uart3_default>; + pinctrl-names = "default"; +}; diff --git a/boards/arm/rzt2m_starterkit/rzt2m_starter_kit.yaml b/boards/arm/rzt2m_starterkit/rzt2m_starter_kit.yaml new file mode 100644 index 00000000000..5d091d0fddb --- /dev/null +++ b/boards/arm/rzt2m_starterkit/rzt2m_starter_kit.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +identifier: rzt2m_starter_kit +name: Renesas RZ/T2M Starter Kit+ +type: mcu +arch: arm +ram: 2048 +toolchain: + - zephyr +supported: + - counter + - uart + - gpio +vendor: renesas diff --git a/boards/arm/rzt2m_starterkit/rzt2m_starter_kit_defconfig b/boards/arm/rzt2m_starterkit/rzt2m_starter_kit_defconfig new file mode 100644 index 00000000000..8b994e00082 --- /dev/null +++ b/boards/arm/rzt2m_starterkit/rzt2m_starter_kit_defconfig @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_RENESAS_RZT2M=y +CONFIG_BOARD_RZT2M_STARTER_KIT=y + +CONFIG_SERIAL=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/boards/arm/s32z270dc2_r52/board.cmake b/boards/arm/s32z270dc2_r52/board.cmake index c7da302041a..31a4fe20d42 100644 --- a/boards/arm/s32z270dc2_r52/board.cmake +++ b/boards/arm/s32z270dc2_r52/board.cmake @@ -1,19 +1,24 @@ -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # SPDX-License-Identifier: Apache-2.0 -board_set_flasher_ifnset(trace32) -board_set_debugger_ifnset(trace32) - board_runner_args(trace32 "--startup-args" - "elfFile=${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME}" - "thumb=no" + "elfFile=${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME}" + "rtu=${CONFIG_NXP_S32_RTU_INDEX}" +) + +board_runner_args(nxp_s32dbg + "--soc-family-name" "s32z2e2" + "--soc-name" "S32Z270" ) -if(CONFIG_BOARD_S32Z270DC2_RTU0_R52) -board_runner_args(trace32 "rtu=0") -elseif(CONFIG_BOARD_S32Z270DC2_RTU1_R52) -board_runner_args(trace32 "rtu=1") +if(CONFIG_DCLS) + board_runner_args(trace32 "lockstep=yes") + board_runner_args(nxp_s32dbg "--core-name" "R52_${CONFIG_NXP_S32_RTU_INDEX}_0_LS") +else() + board_runner_args(trace32 "lockstep=no") + board_runner_args(nxp_s32dbg "--core-name" "R52_${CONFIG_NXP_S32_RTU_INDEX}_0") endif() +include(${ZEPHYR_BASE}/boards/common/nxp_s32dbg.board.cmake) include(${ZEPHYR_BASE}/boards/common/trace32.board.cmake) diff --git a/boards/arm/s32z270dc2_r52/doc/index.rst b/boards/arm/s32z270dc2_r52/doc/index.rst index 9ae309a33b4..e940a144f1f 100644 --- a/boards/arm/s32z270dc2_r52/doc/index.rst +++ b/boards/arm/s32z270dc2_r52/doc/index.rst @@ -99,7 +99,7 @@ using GPIO driver or configuring the pinmuxing for the device drivers. +-------------------+-------------+ This board does not include user LED's or switches, which are needed for some -of the samples such as :ref:`blinky-sample` or :ref:`button-sample`. +of the samples such as :zephyr:code-sample:`blinky` or :zephyr:code-sample:`button`. Follow the steps described in the sample description to enable support for this board. @@ -146,26 +146,21 @@ Applications for the ``s32z270dc2_rtu0_r52`` and ``s32z270dc2_rtu1_r52`` boards can be built in the usual way as documented in :ref:`build_an_application`. Currently is only possible to load and execute a Zephyr application binary on -this board from the internal SRAM, using `Lauterbach TRACE32`_ development -tools and debuggers. +this board from the core internal SRAM. -.. note:: - Currently, the start-up scripts executed with ``west flash`` and - ``west debug`` commands perform the same steps to initialize the SoC and - load the application to SRAM. The difference is that ``west flash`` hide the - Lauterbach TRACE32 interface, executes the application and exits. +This board supports West runners for the following debug tools: -Install Lauterbach TRACE32 Software -=================================== +- :ref:`NXP S32 Debug Probe ` (default) +- :ref:`Lauterbach TRACE32 ` -Follow the steps described in :ref:`lauterbach-trace32-debug-host-tools` to -install and set-up Lauterbach TRACE32 software. +Follow the installation steps of the debug tool you plan to use before loading +your firmware. Set-up the Board ================ -Connect the Lauterbach TRACE32 debugger to the board's JTAG connector (``J134``) -and to the host computer. +Connect the external debugger probe to the board's JTAG connector (``J134``) +and to the host computer via USB or Ethernet, as supported by the probe. For visualizing the serial output, connect the board's USB/UART port (``J119``) to the host computer and run your favorite terminal program to listen for output. @@ -178,16 +173,16 @@ For example, using the cross-platform `pySerial miniterm`_ terminal: Replace ```` with the port where the board can be found. For example, under Linux, ``/dev/ttyUSB0``. -Flashing -======== +Debugging +========= -For example, you can build and run the :ref:`hello_world` sample for the board +You can build and debug the :ref:`hello_world` sample for the board ``s32z270dc2_rtu0_r52`` with: .. zephyr-app-commands:: :zephyr-app: samples/hello_world :board: s32z270dc2_rtu0_r52 - :goals: build flash + :goals: build debug In case you are using a newer PCB revision, you have to use an adapted board definition as the default PCB revision is B. For example, if using revision D: @@ -195,30 +190,53 @@ definition as the default PCB revision is B. For example, if using revision D: .. zephyr-app-commands:: :zephyr-app: samples/hello_world :board: s32z270dc2_rtu0_r52@D - :goals: build flash + :goals: build debug + :compact: -You should see the following message in the terminal: +At this point you can do your normal debug session. Set breakpoints and then +:kbd:`c` to continue into the program. You should see the following message in +the terminal: .. code-block:: console Hello World! s32z270dc2_rtu0_r52 -Debugging -========= +To debug with Lauterbach TRACE32 softare run instead: -To enable debugging using Lauterbach TRACE32 software, run instead: +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: s32z270dc2_rtu0_r52 + :goals: build debug -r trace32 + :compact: + +Flashing +======== + +Follow these steps if you just want to download the application to the board +SRAM and run. + +``flash`` command is supported only by the Lauterbach TRACE32 runner: .. zephyr-app-commands:: :zephyr-app: samples/hello_world :board: s32z270dc2_rtu0_r52 - :goals: build debug + :goals: build flash -r trace32 + :compact: -Step through the application in your debugger, and you should see the following -message in the terminal: +.. note:: + Currently, the Lauterbach start-up scripts executed with ``flash`` and + ``debug`` commands perform the same steps to initialize the SoC and + load the application to SRAM. The difference is that ``flash`` hides the + Lauterbach TRACE32 interface, executes the application and exits. -.. code-block:: console +To imitate a similar behavior using NXP S32 Debug Probe runner, you can run the +``debug`` command with GDB in batch mode: - Hello World! s32z270dc2_rtu0_r52 +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: s32z270dc2_rtu0_r52 + :goals: build debug --tool-opt='--batch' + :compact: RTU and Core Configuration ========================== @@ -231,26 +249,29 @@ configuration). To build for split-lock mode, the :kconfig:option:`CONFIG_DCLS` must be disabled from your application Kconfig file. -Additionally, to run in a different core or with a different core -configuration than the default, extra parameters must be provided to the runner -as follows: +By default the board configuration will set the runner arguments according to +the build configuration. To debug for a core different than the default use: -.. code-block:: console +.. tabs:: + + .. group-tab:: lockstep configuration + + .. code-block:: console - west --startup-args elfFile= rtu= \ - core= lockstep= + west debug --core-name='R52___LS' + + .. group-tab:: split-lock configuration + + .. code-block:: console + + west debug --core-name='R52__' Where: -- ```` is ``flash`` or ``debug`` -- ```` is the path to the Zephyr application ELF in the output - directory - ```` is the zero-based RTU index (0 for ``s32z270dc2_rtu0_r52`` and 1 for ``s32z270dc2_rtu1_r52``) - ```` is the zero-based core index relative to the RTU on which to run the Zephyr application (0, 1, 2 or 3) -- ```` can be ``yes`` to run in lock-step, or ``no`` to run in - split-lock. For example, to build the :ref:`hello_world` sample for the board ``s32z270dc2_rtu0_r52`` with split-lock core configuration: @@ -260,13 +281,23 @@ For example, to build the :ref:`hello_world` sample for the board :board: s32z270dc2_rtu0_r52 :goals: build :gen-args: -DCONFIG_DCLS=n + :compact: To execute this sample in the second core of RTU0 in split-lock mode: .. code-block:: console - west flash --startup-args elfFile=build/zephyr/zephyr.elf \ - rtu=0 core=1 lockstep=no + west debug --core-name='R52_0_1' + +If using Lauterbach TRACE32, all runner parameters must be overridden from command +line: + +.. code-block:: console + + west debug --startup-args elfFile= rtu= core= lockstep= + +Where ```` is the path to the Zephyr application ELF in the output +directory. References ********** @@ -276,8 +307,5 @@ References .. _NXP S32Z2 Real-Time Processors website: https://www.nxp.com/products/processors-and-microcontrollers/s32-automotive-platform/s32z-and-s32e-real-time-processors/s32z2-safe-and-secure-high-performance-real-time-processors:S32Z2 -.. _Lauterbach TRACE32: - https://www.lauterbach.com - .. _pySerial miniterm: https://pyserial.readthedocs.io/en/latest/tools.html#module-serial.tools.miniterm diff --git a/boards/arm/s32z270dc2_r52/s32z270dc2_r52.dtsi b/boards/arm/s32z270dc2_r52/s32z270dc2_r52.dtsi index eed395cce8c..884f1d802bb 100644 --- a/boards/arm/s32z270dc2_r52/s32z270dc2_r52.dtsi +++ b/boards/arm/s32z270dc2_r52/s32z270dc2_r52.dtsi @@ -4,95 +4,20 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include "s32z270dc2_r52-pinctrl-common.dtsi" -&spi0 { - clock-frequency = <100000000>; -}; - -&spi1 { - clock-frequency = <100000000>; -}; - -&spi2 { - clock-frequency = <100000000>; -}; - -&spi3 { - clock-frequency = <120000000>; -}; - -&spi4 { - clock-frequency = <120000000>; -}; - -&spi5 { - clock-frequency = <120000000>; -}; - -&spi6 { - clock-frequency = <120000000>; -}; - -&spi7 { - clock-frequency = <100000000>; -}; - -&spi8 { - clock-frequency = <100000000>; -}; - -&spi9 { - clock-frequency = <100000000>; -}; - -&stm0 { - clock-frequency = <133333333>; -}; - -&stm1 { - clock-frequency = <133333333>; -}; - -&stm2 { - clock-frequency = <133333333>; -}; - -&stm3 { - clock-frequency = <133333333>; -}; - &swt0 { - clock-frequency = <48000000>; status = "okay"; }; -&swt1 { - clock-frequency = <48000000>; -}; - -&swt2 { - clock-frequency = <48000000>; -}; - -&swt3 { - clock-frequency = <48000000>; -}; - -&swt4 { - clock-frequency = <48000000>; -}; - &emdio { pinctrl-0 = <&emdio_default>; pinctrl-names = "default"; - protocol = "clause 22"; status = "okay"; - phy0: ethernet-phy { + phy0: ethernet-phy@7 { compatible = "ethernet-phy"; - address = <0x7>; + reg = <0x7>; status = "okay"; }; }; @@ -109,24 +34,18 @@ &can0 { pinctrl-0 = <&can0_default>; pinctrl-names = "default"; - clock-frequency = <80000000>; bus-speed = <125000>; sample-point = <875>; - sjw = <1>; bus-speed-data = <1000000>; sample-point-data = <875>; - sjw-data = <1>; status = "okay"; }; &can1 { pinctrl-0 = <&can1_default>; pinctrl-names = "default"; - clock-frequency = <80000000>; bus-speed = <125000>; sample-point = <875>; - sjw = <1>; bus-speed-data = <1000000>; sample-point-data = <875>; - sjw-data = <1>; }; diff --git a/boards/arm/s32z270dc2_r52/s32z270dc2_rtu0_r52.yaml b/boards/arm/s32z270dc2_r52/s32z270dc2_rtu0_r52.yaml index 9d229e27b98..891f6b3cce5 100644 --- a/boards/arm/s32z270dc2_r52/s32z270dc2_rtu0_r52.yaml +++ b/boards/arm/s32z270dc2_r52/s32z270dc2_rtu0_r52.yaml @@ -1,4 +1,4 @@ -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # SPDX-License-Identifier: Apache-2.0 identifier: s32z270dc2_rtu0_r52 @@ -14,3 +14,6 @@ supported: - watchdog - netif:eth - can + - spi + - counter +vendor: nxp diff --git a/boards/arm/s32z270dc2_r52/s32z270dc2_rtu0_r52_D.yaml b/boards/arm/s32z270dc2_r52/s32z270dc2_rtu0_r52_D.yaml index db8c9e68854..063ea90c351 100644 --- a/boards/arm/s32z270dc2_r52/s32z270dc2_rtu0_r52_D.yaml +++ b/boards/arm/s32z270dc2_r52/s32z270dc2_rtu0_r52_D.yaml @@ -14,3 +14,6 @@ supported: - watchdog - netif:eth - can + - spi + - counter +vendor: nxp diff --git a/boards/arm/s32z270dc2_r52/s32z270dc2_rtu1_r52.yaml b/boards/arm/s32z270dc2_r52/s32z270dc2_rtu1_r52.yaml index 845d7b09291..de48e46091a 100644 --- a/boards/arm/s32z270dc2_r52/s32z270dc2_rtu1_r52.yaml +++ b/boards/arm/s32z270dc2_r52/s32z270dc2_rtu1_r52.yaml @@ -1,4 +1,4 @@ -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # SPDX-License-Identifier: Apache-2.0 identifier: s32z270dc2_rtu1_r52 @@ -14,3 +14,6 @@ supported: - watchdog - netif:eth - can + - spi + - counter +vendor: nxp diff --git a/boards/arm/s32z270dc2_r52/s32z270dc2_rtu1_r52_D.yaml b/boards/arm/s32z270dc2_r52/s32z270dc2_rtu1_r52_D.yaml index aeb1eac2038..70a37261c8e 100644 --- a/boards/arm/s32z270dc2_r52/s32z270dc2_rtu1_r52_D.yaml +++ b/boards/arm/s32z270dc2_r52/s32z270dc2_rtu1_r52_D.yaml @@ -1,4 +1,4 @@ -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # SPDX-License-Identifier: Apache-2.0 identifier: s32z270dc2_rtu1_r52@D @@ -14,3 +14,6 @@ supported: - watchdog - netif:eth - can + - spi + - counter +vendor: nxp diff --git a/boards/arm/sam4e_xpro/sam4e_xpro-pinctrl.dtsi b/boards/arm/sam4e_xpro/sam4e_xpro-pinctrl.dtsi index e83b9eeffe8..fb19be497ca 100644 --- a/boards/arm/sam4e_xpro/sam4e_xpro-pinctrl.dtsi +++ b/boards/arm/sam4e_xpro/sam4e_xpro-pinctrl.dtsi @@ -94,4 +94,16 @@ ; }; }; + + hsmci_default: hsmci_default { + group1 { + pinmux = , + , + , + , + , + ; + }; + }; + }; diff --git a/boards/arm/sam4e_xpro/sam4e_xpro.dts b/boards/arm/sam4e_xpro/sam4e_xpro.dts index 254a4a21100..ddd73d0faef 100644 --- a/boards/arm/sam4e_xpro/sam4e_xpro.dts +++ b/boards/arm/sam4e_xpro/sam4e_xpro.dts @@ -21,6 +21,7 @@ sw0 = &user_button; wdog = &wdt; watchdog0 = &wdt; + sdhc0 = &hsmci; }; chosen { @@ -197,10 +198,10 @@ pinctrl-0 = <&mdio_default>; pinctrl-names = "default"; - phy: phy { + phy: ethernet-phy@0 { compatible = "ethernet-phy"; status = "okay"; - address = <0>; + reg = <0>; }; }; @@ -211,6 +212,17 @@ pinctrl-names = "default"; }; +&hsmci { + status = "okay"; + + pinctrl-0 = <&hsmci_default>; + pinctrl-names = "default"; + mmc { + compatible = "zephyr,sdmmc-disk"; + status = "okay"; + }; +}; + &wdt { status = "okay"; }; diff --git a/boards/arm/sam4e_xpro/sam4e_xpro.yaml b/boards/arm/sam4e_xpro/sam4e_xpro.yaml index b9392fc5089..76ca997b1a0 100644 --- a/boards/arm/sam4e_xpro/sam4e_xpro.yaml +++ b/boards/arm/sam4e_xpro/sam4e_xpro.yaml @@ -10,8 +10,10 @@ supported: - netif:eth - gpio - spi + - sdhc - watchdog - xpro_gpio - xpro_i2c - xpro_serial - xpro_spi +vendor: atmel diff --git a/boards/arm/sam4l_ek/sam4l_ek.yaml b/boards/arm/sam4l_ek/sam4l_ek.yaml index 2a8ecf8c0e1..cdadbee508a 100644 --- a/boards/arm/sam4l_ek/sam4l_ek.yaml +++ b/boards/arm/sam4l_ek/sam4l_ek.yaml @@ -14,3 +14,4 @@ supported: - spi - usart - usb_device +vendor: atmel diff --git a/boards/arm/sam4s_xplained/sam4s_xplained.yaml b/boards/arm/sam4s_xplained/sam4s_xplained.yaml index 3b537a2b56e..20e5949b0fe 100644 --- a/boards/arm/sam4s_xplained/sam4s_xplained.yaml +++ b/boards/arm/sam4s_xplained/sam4s_xplained.yaml @@ -18,3 +18,4 @@ supported: - xplained_serial - xplained_spi - hwinfo +vendor: atmel diff --git a/boards/arm/sam_e70_xplained/sam_e70_xplained-common.dtsi b/boards/arm/sam_e70_xplained/sam_e70_xplained-common.dtsi index 1b50d6494e0..93dc9b1f356 100644 --- a/boards/arm/sam_e70_xplained/sam_e70_xplained-common.dtsi +++ b/boards/arm/sam_e70_xplained/sam_e70_xplained-common.dtsi @@ -136,10 +136,10 @@ zephyr_udc0: &usbhs { pinctrl-0 = <&mdio_default>; pinctrl-names = "default"; - phy: phy { + phy: ethernet-phy@0 { compatible = "ethernet-phy"; status = "okay"; - address = <0>; + reg = <0>; }; }; diff --git a/boards/arm/sam_e70_xplained/sam_e70_xplained.yaml b/boards/arm/sam_e70_xplained/sam_e70_xplained.yaml index ae2fa89bbc7..714795a2104 100644 --- a/boards/arm/sam_e70_xplained/sam_e70_xplained.yaml +++ b/boards/arm/sam_e70_xplained/sam_e70_xplained.yaml @@ -20,3 +20,4 @@ supported: - pwm - can - hwinfo +vendor: atmel diff --git a/boards/arm/sam_e70_xplained/sam_e70b_xplained.yaml b/boards/arm/sam_e70_xplained/sam_e70b_xplained.yaml index 99c53142c18..8cd515dca40 100644 --- a/boards/arm/sam_e70_xplained/sam_e70b_xplained.yaml +++ b/boards/arm/sam_e70_xplained/sam_e70b_xplained.yaml @@ -19,3 +19,4 @@ supported: - pwm - can - hwinfo +vendor: atmel diff --git a/boards/arm/sam_v71_xult/doc/index.rst b/boards/arm/sam_v71_xult/doc/index.rst index 5bed3274d71..a61fe887d6a 100644 --- a/boards/arm/sam_v71_xult/doc/index.rst +++ b/boards/arm/sam_v71_xult/doc/index.rst @@ -70,7 +70,7 @@ features: +-----------+------------+-------------------------------------+ | PWM | on-chip | pwm | +-----------+------------+-------------------------------------+ -| CAN-FD | on-chip | can | +| CAN FD | on-chip | can | +-----------+------------+-------------------------------------+ | HWINFO | on-chip | Unique device serial number | +-----------+------------+-------------------------------------+ diff --git a/boards/arm/sam_v71_xult/sam_v71_xult-common.dtsi b/boards/arm/sam_v71_xult/sam_v71_xult-common.dtsi index 7aefd9cec86..9864c7ae50a 100644 --- a/boards/arm/sam_v71_xult/sam_v71_xult-common.dtsi +++ b/boards/arm/sam_v71_xult/sam_v71_xult-common.dtsi @@ -245,10 +245,10 @@ zephyr_udc0: &usbhs { pinctrl-0 = <&mdio_default>; pinctrl-names = "default"; - phy: phy { + phy: ethernet-phy@0 { compatible = "ethernet-phy"; status = "okay"; - address = <0>; + reg = <0>; }; }; diff --git a/boards/arm/sam_v71_xult/sam_v71_xult.yaml b/boards/arm/sam_v71_xult/sam_v71_xult.yaml index c71bcd3f83d..01055202950 100644 --- a/boards/arm/sam_v71_xult/sam_v71_xult.yaml +++ b/boards/arm/sam_v71_xult/sam_v71_xult.yaml @@ -24,3 +24,4 @@ supported: - xpro_spi - can - hwinfo +vendor: atmel diff --git a/boards/arm/sam_v71_xult/sam_v71b_xult.yaml b/boards/arm/sam_v71_xult/sam_v71b_xult.yaml index 3090a3a155d..9dbb670075f 100644 --- a/boards/arm/sam_v71_xult/sam_v71b_xult.yaml +++ b/boards/arm/sam_v71_xult/sam_v71b_xult.yaml @@ -24,3 +24,4 @@ supported: - xpro_spi - can - hwinfo +vendor: atmel diff --git a/boards/arm/seeeduino_xiao/doc/index.rst b/boards/arm/seeeduino_xiao/doc/index.rst index fb4ff4420a0..22693fed2ab 100644 --- a/boards/arm/seeeduino_xiao/doc/index.rst +++ b/boards/arm/seeeduino_xiao/doc/index.rst @@ -99,7 +99,7 @@ USB Device Port The SAMD21 MCU has a USB device port that can be used to communicate with a host PC. See the :ref:`usb-samples` sample applications for -more, such as the :ref:`usb_cdc-acm` sample which sets up a virtual +more, such as the :zephyr:code-sample:`usb-cdc-acm` sample which sets up a virtual serial port that echos characters back to the host PC. DAC diff --git a/boards/arm/seeeduino_xiao/seeeduino_xiao.dts b/boards/arm/seeeduino_xiao/seeeduino_xiao.dts index a0bc69a4814..0859e87e635 100644 --- a/boards/arm/seeeduino_xiao/seeeduino_xiao.dts +++ b/boards/arm/seeeduino_xiao/seeeduino_xiao.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include #include "seeeduino_xiao-pinctrl.dtsi" #include "seeed_xiao_connector.dtsi" diff --git a/boards/arm/seeeduino_xiao/seeeduino_xiao.yaml b/boards/arm/seeeduino_xiao/seeeduino_xiao.yaml index 657136f693a..73bfc8b114d 100644 --- a/boards/arm/seeeduino_xiao/seeeduino_xiao.yaml +++ b/boards/arm/seeeduino_xiao/seeeduino_xiao.yaml @@ -18,3 +18,4 @@ supported: - uart - usb_device - watchdog +vendor: seeed diff --git a/boards/arm/segger_trb_stm32f407/doc/index.rst b/boards/arm/segger_trb_stm32f407/doc/index.rst index 83fb6924e7a..24c8f8df6d8 100644 --- a/boards/arm/segger_trb_stm32f407/doc/index.rst +++ b/boards/arm/segger_trb_stm32f407/doc/index.rst @@ -109,7 +109,7 @@ Flashing an application to the SEGGER-TRB-STM32F407 Connect the J-Trace/J-Link USB dongle to your host computer and to the JTAG port of the SEGGER-TRB-STM32F407 board. Then build and flash an application. -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -121,7 +121,7 @@ After resetting the board, you should see LED0 blink with a 1 second interval. Debugging ========= -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/segger_trb_stm32f407/segger_trb_stm32f407.yaml b/boards/arm/segger_trb_stm32f407/segger_trb_stm32f407.yaml index 594663d6a39..911c3764802 100644 --- a/boards/arm/segger_trb_stm32f407/segger_trb_stm32f407.yaml +++ b/boards/arm/segger_trb_stm32f407/segger_trb_stm32f407.yaml @@ -17,3 +17,4 @@ testing: - net - shell - console +vendor: segger diff --git a/boards/arm/sensortile_box/doc/index.rst b/boards/arm/sensortile_box/doc/index.rst index a6cabf9b359..db9ba488dc1 100644 --- a/boards/arm/sensortile_box/doc/index.rst +++ b/boards/arm/sensortile_box/doc/index.rst @@ -197,7 +197,7 @@ References https://www.st.com/en/evaluation-tools/steval-mksbox1v1.html .. _AN2606: - http://www.st.com/content/ccc/resource/technical/document/application_note/b9/9b/16/3a/12/1e/40/0c/CD00167594.pdf/files/CD00167594.pdf/jcr:content/translations/en.CD00167594.pdf + https://www.st.com/content/ccc/resource/technical/document/application_note/b9/9b/16/3a/12/1e/40/0c/CD00167594.pdf/files/CD00167594.pdf/jcr:content/translations/en.CD00167594.pdf .. _DFU-UTIL website: http://dfu-util.sourceforge.net/ diff --git a/boards/arm/sensortile_box/sensortile_box.yaml b/boards/arm/sensortile_box/sensortile_box.yaml index f9cbce1bc80..e67e105021b 100644 --- a/boards/arm/sensortile_box/sensortile_box.yaml +++ b/boards/arm/sensortile_box/sensortile_box.yaml @@ -16,3 +16,4 @@ supported: - counter ram: 640 flash: 2048 +vendor: st diff --git a/boards/arm/sensortile_box_pro/CMakeLists.txt b/boards/arm/sensortile_box_pro/CMakeLists.txt new file mode 100644 index 00000000000..4489ff54489 --- /dev/null +++ b/boards/arm/sensortile_box_pro/CMakeLists.txt @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 + +# Define the toolchain to be used (by eg CI) +if(${ZEPHYR_TOOLCHAIN_VARIANT} STREQUAL "zephyr") + set(COMPILER_FULL_PATH ${ZEPHYR_SDK_INSTALL_DIR}/arm-zephyr-eabi/bin/arm-zephyr-eabi-gcc) +elseif(${ZEPHYR_TOOLCHAIN_VARIANT} STREQUAL "gnuarmemb") + set(COMPILER_FULL_PATH ${GNUARMEMB_TOOLCHAIN_PATH}/bin/arm-none-eabi-gcc) +endif() + +zephyr_library_sources(board.c) diff --git a/boards/arm/sensortile_box_pro/Kconfig.board b/boards/arm/sensortile_box_pro/Kconfig.board new file mode 100644 index 00000000000..14429705999 --- /dev/null +++ b/boards/arm/sensortile_box_pro/Kconfig.board @@ -0,0 +1,8 @@ +# SENSORTILE_BOX_PRO board configuration + +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_SENSORTILE_BOX_PRO + bool "SENSORTILE_BOX_PRO Board" + depends on SOC_STM32U585XX diff --git a/boards/arm/sensortile_box_pro/Kconfig.defconfig b/boards/arm/sensortile_box_pro/Kconfig.defconfig new file mode 100644 index 00000000000..e37f5e4f5bf --- /dev/null +++ b/boards/arm/sensortile_box_pro/Kconfig.defconfig @@ -0,0 +1,24 @@ +# SENSORTILE_BOX_PRO board configuration + +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_SENSORTILE_BOX_PRO + +config BOARD + default "sensortile_box_pro" + +config SPI_STM32_INTERRUPT + default y + depends on SPI + +if LOG + +# Logger cannot use itself to log +choice USB_CDC_ACM_LOG_LEVEL_CHOICE + default USB_CDC_ACM_LOG_LEVEL_OFF +endchoice + +endif # LOG + +endif # BOARD_SENSORTILE_BOX_PRO diff --git a/boards/arm/sensortile_box_pro/board.c b/boards/arm/sensortile_box_pro/board.c new file mode 100644 index 00000000000..db3de065f2b --- /dev/null +++ b/boards/arm/sensortile_box_pro/board.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_USB_DEVICE_STACK +/* + * Enable console on USB CDC_ACM + */ +static int sensortile_box_pro_usb_console_init(void) +{ + const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); + + if (!device_is_ready(dev) || usb_enable(NULL)) { + return -1; + } + + return 0; +} + +/* needs to be done at Application */ +SYS_INIT(sensortile_box_pro_usb_console_init, APPLICATION, + CONFIG_KERNEL_INIT_PRIORITY_DEVICE); +#endif diff --git a/boards/arm/sensortile_box_pro/board.cmake b/boards/arm/sensortile_box_pro/board.cmake new file mode 100644 index 00000000000..370c5454429 --- /dev/null +++ b/boards/arm/sensortile_box_pro/board.cmake @@ -0,0 +1,5 @@ +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 +board_runner_args(dfu-util "--pid=0483:df11" "--alt=0" "--dfuse") + +include(${ZEPHYR_BASE}/boards/common/dfu-util.board.cmake) diff --git a/boards/arm/sensortile_box_pro/doc/img/sensortile_box_pro.jpg b/boards/arm/sensortile_box_pro/doc/img/sensortile_box_pro.jpg new file mode 100644 index 00000000000..2865d8c576b Binary files /dev/null and b/boards/arm/sensortile_box_pro/doc/img/sensortile_box_pro.jpg differ diff --git a/boards/arm/sensortile_box_pro/doc/index.rst b/boards/arm/sensortile_box_pro/doc/index.rst new file mode 100644 index 00000000000..bba5a4cb288 --- /dev/null +++ b/boards/arm/sensortile_box_pro/doc/index.rst @@ -0,0 +1,386 @@ +.. _sensortile_box_pro_board: + +ST SensorTile.box PRO +##################### + +Overview +******** + +The STEVAL-MKBOXPRO (SensorTile.box PRO) features an ARM Cortex-M33 based STM32U585AI MCU +and is a ready-to-use box kit for wireless IoT and wearable sensor platforms to help using +and developing apps based on remote motion and environmental sensor data. + +The SensorTile.box PRO board fits into a small plastic box with a long-life rechargeable +battery, and communicates with a standard smartphone through its Bluetooth interface, +providing data coming from the sensors. + +.. image:: img/sensortile_box_pro.jpg + :align: center + :alt: SensorTile.box PRO + +More information about the board can be found at the `SensorTile.box PRO website`_. + +Supported Features +****************** + +The SensorTile.box PRO provides motion, environmental, and audio +sensor data through either the BLE or USB protocols to a host application running +on a smartphone/PC to implement applications such as: + +- Pedometer optimized for belt positioning +- Baby crying detection with Cloud AI learning +- Barometer / environmental monitoring +- Vehicle / goods tracking +- Vibration monitoring +- Compass and inclinometer +- Sensor data logger + +(see `Motion and environmental sensors`_ section for the complete lists of available +sensors on board) + +Hardware +******** + +The STM32U585xx devices are an ultra-low-power microcontrollers family (STM32U5 +Series) based on the high-performance Arm|reg| Cortex|reg|-M33 32-bit RISC core. +They operate at a frequency of up to 160 MHz. + +- Ultra-low-power with FlexPowerControl (down to 300 nA Standby mode and 19.5 uA/MHz run mode) +- Core: ARM |reg| 32-bit Cortex |reg| -M33 CPU with TrustZone |reg| and FPU. +- Performance benchmark: + + - 1.5 DMPIS/MHz (Drystone 2.1) + - 651 CoreMark |reg| (4.07 CoreMark |reg| /MHZ) + +- Security and cryptography + + - Arm |reg| TrustZone |reg| and securable I/Os memories and peripherals + - Flexible life cycle scheme with RDP (readout protection) and password protected debug + - Root of trust thanks to unique boot entry and secure hide protection area (HDP) + - Secure Firmware Installation thanks to embedded Root Secure Services + - Secure data storage with hardware unique key (HUK) + - Secure Firmware Update support with TF-M + - 2 AES coprocessors including one with DPA resistance + - Public key accelerator, DPA resistant + - On-the-fly decryption of Octo-SPI external memories + - HASH hardware accelerator + - Active tampers + - True Random Number Generator NIST SP800-90B compliant + - 96-bit unique ID + - 512-byte One-Time Programmable for user data + - Active tampers + +- Clock management: + + - 4 to 50 MHz crystal oscillator + - 32 kHz crystal oscillator for RTC (LSE) + - Internal 16 MHz factory-trimmed RC ( |plusminus| 1%) + - Internal low-power 32 kHz RC ( |plusminus| 5%) + - 2 internal multispeed 100 kHz to 48 MHz oscillators, including one auto-trimmed by + LSE (better than |plusminus| 0.25 % accuracy) + - 3 PLLs for system clock, USB, audio, ADC + - Internal 48 MHz with clock recovery + +- Power management + + - Embedded regulator (LDO) + - Embedded SMPS step-down converter supporting switch on-the-fly and voltage scaling + +- RTC with HW calendar and calibration +- Up to 136 fast I/Os, most 5 V-tolerant, up to 14 I/Os with independent supply down to 1.08 V +- Up to 24 capacitive sensing channels: support touchkey, linear and rotary touch sensors +- Up to 17 timers and 2 watchdogs + + - 2x 16-bit advanced motor-control + - 2x 32-bit and 5 x 16-bit general purpose + - 4x low-power 16-bit timers (available in Stop mode) + - 2x watchdogs + - 2x SysTick timer + +- ART accelerator + + - 8-Kbyte instruction cache allowing 0-wait-state execution from Flash and + external memories: up to 160 MHz, MPU, 240 DMIPS and DSP + - 4-Kbyte data cache for external memories + +- Memories + + - 2-Mbyte Flash memory with ECC, 2 banks read-while-write, including 512 Kbytes with 100 kcycles + - 786-Kbyte SRAM with ECC OFF or 722-Kbyte SRAM including up to 322-Kbyte SRAM with ECC ON + - External memory interface supporting SRAM, PSRAM, NOR, NAND and FRAM memories + - 2 Octo-SPI memory interfaces + +- Rich analog peripherals (independent supply) + + - 14-bit ADC 2.5-Msps, resolution up to 16 bits with hardware oversampling + - 12-bit ADC 2.5-Msps, with hardware oversampling, autonomous in Stop 2 mode + - 12-bit DAC, low-power sample and hold + - 2 operational amplifiers with built-in PGA + - 2 ultra-low-power comparators + +- Up to 22 communication interfaces + + - USB Type-C / USB power delivery controller + - USB OTG 2.0 full-speed controller + - 2x SAIs (serial audio interface) + - 4x I2C FM+(1 Mbit/s), SMBus/PMBus + - 6x USARTs (ISO 7816, LIN, IrDA, modem) + - 3x SPIs (5x SPIs with dual OCTOSPI in SPI mode) + - 1x FDCAN + - 2x SDMMC interface + - 16- and 4-channel DMA controllers, functional in Stop mode + - 1 multi-function digital filter (6 filters)+ 1 audio digital filter with + sound-activity detection + +- CRC calculation unit +- Development support: serial wire debug (SWD), JTAG, Embedded Trace Macrocell |trade| +- True Random Number Generator (RNG) + +- Graphic features + + - Chrom-ART Accelerator (DMA2D) for enhanced graphic content creation + - 1 digital camera interface + +- Mathematical co-processor + + - CORDIC for trigonometric functions acceleration + - FMAC (filter mathematical accelerator) + + +More information about STM32U585AI can be found here: + +- `STM32U585 on www.st.com`_ +- `STM32U585 reference manual`_ + +Motion and environmental sensors +================================ + + - **LSM6DSV16X** 6-axis inertial measurement unit + (`lsm6dsv16x datasheet`_) + - **LIS2MDL** 3-axis magnetometer + (`lis2mdl datasheet`_) + - **LPS22DF** Altimeter / pressure sensor + (`lps22df datasheet`_) + - **LIS2DU12** 3-axis accelerometer + (`lis2du12 datasheet`_) + - **HTS221** Humidity sensor + (`hts221 datasheet`_) + - **STTS22H** Digital temperature sensor + (`stts22hh datasheet`_) + - **MP23db01HP** Microphone / audio sensor + (`mp23db01hp datasheet`_) + +Connections and IOs +=================== + +- 4x user LEDs + + - **led0** (Green) + - **led1** (Red - shared with BLE) + - **led2** (Yellow) + - **led3** (Blue) + + +- 4x buttons/switch + + - **User BT1** button, available to user application + - **User BT2** / **boot0** button, available to user application + but useful to let the SensorTile.box PRO enter DFU mode + if found pressed after h/w reset (see **rst** button and + `Programming and Debugging`_ section) + - **rst** button, used to reset the board (not available on case) + - **power** switch, used to Power on/off the board + +System Clock +============ + +SensorTile.box PRO System Clock could be driven by internal or external +oscillator, as well as main PLL clock. By default, the System clock is +driven by the PLL clock at 80MHz, driven by the 16MHz external oscillator. +The system clock can be boosted to 120MHz. +The internal AHB/APB1/APB2 AMBA buses are all clocked at 80MHz. + +Serial Port +=========== + +The SensorTile.box PRO has 4 U(S)ARTs. The UART4 is connected to JTAG/SWD connector +and may be used as console. + +USB interface +============= + +SensorTile.box PRO can be connected as a USB device to a PC host through its USB-C connector. +The final application may use it to declare SensorTile.box PRO device as belonging to a +certain standard or vendor class, e.g. a CDC, a mass storage or a composite device with both +functions. + +Console +======= + +There are two possible options for Zephyr console output: + +- through UART4 which is available on SWD connector (JP2). In this case a JTAG adapter + can be used to connect SensorTile.box PRO and have both SWD and console lines available. + + To enable console and shell over UART + + - switch the console lines from cdc_acm to uart4 + (:file:`boards/arm/sensortile_box_pro/sensortile_box_pro.dts`) + + - comment out the USB configuration macros + (:file:`boards/arm/sensortile_box_pro/sensortile_box_pro_defconfig`) + +.. code-block:: dts + :caption: boards/arm/sensortile_box_pro/sensortile_box_pro.dts + + / { + chosen { + zephyr,console = &uart4; + zephyr,shell-uart = &uart4; + //zephyr,console = &cdc_acm_uart0; + //zephyr,shell-uart = &cdc_acm_uart0; + }; + }; + +.. code-block:: Kconfig + :caption: boards/arm/sensortile_box_pro/sensortile_box_pro_defconfig + + # Comment out following USB config lines when + # switching console to UART + #CONFIG_USB_DEVICE_STACK=y + #CONFIG_USB_DEVICE_VID=0x0483 + #CONFIG_USB_DEVICE_PID=0x1235 + #CONFIG_USB_DEVICE_PRODUCT="Zephyr CDC SensorTile.box PRO" + #CONFIG_USB_CDC_ACM_LOG_LEVEL_OFF=y + #CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n + + +- through USB as USB CDC/ACM class. This is the default case present in the board dts file. + +.. code-block:: dts + :caption: boards/arm/sensortile_box_pro/sensortile_box_pro.dts + + / { + chosen { + zephyr,console = &cdc_acm_uart0; + }; + }; + + &zephyr_udc0 { + cdc_acm_uart0: cdc_acm_uart0 { + compatible = "zephyr,cdc-acm-uart"; + }; + }; + + + +Console default settings are 115200 8N1. + +Programming and Debugging +************************* + +There are two alternative methods of flashing ST Sensortile.box Pro board: + +1. Using DFU software tools + + This method requires to enter STM32U585 ROM bootloader DFU mode + by powering up (or reset) the board while keeping the BOOT0 button pressed. + No additional hardware is required except a USB-C cable. This method is fully + supported by :ref:`flash-debug-host-tools`. + You can read more about how to enable and use the ROM bootloader by checking + the application note `AN2606`_ (STM32U585xx section). + +2. Using SWD hardware tools + + This method requires to connect additional hardware, like a ST-LINK/V3 + embedded debug tool, to the board SWD connector. + +DFU flashing +============ + +Install dfu-util +---------------- + +It is recommended to use at least v0.9 of dfu-util. The package available in +Debian and Ubuntu can be quite old, so you might have to build dfu-util from source. +Information about how to get the source code and how to build it can be found +at the `DFU-UTIL website`_ + +Flash an Application to SensorTile.box PRO +------------------------------------------ + +While pressing the BOOT0 button, connect the USB-C cable to the USB OTG SensorTile.box PRO +port and to your computer. The board should be forced to enter DFU mode. + +Check that the board is indeed in DFU mode: + +.. code-block:: console + + $ sudo dfu-util -l + dfu-util 0.9 + + Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. + Copyright 2010-2019 Tormod Volden and Stefan Schmidt + This program is Free Software and has ABSOLUTELY NO WARRANTY + Please report bugs to http://sourceforge.net/p/dfu-util/tickets/ + + Found DFU: [0483:df11] ver=2200, devnum=74, cfg=1, intf=0, path="2-2", alt=2, name="@OTP Memory /0x1FFF7000/01*0001Ke", serial="204A325D574D" + Found DFU: [0483:df11] ver=2200, devnum=74, cfg=1, intf=0, path="2-2", alt=1, name="@Option Bytes /0x1FF00000/01*040 e/0x1FF01000/01*040 e", serial="204A325D574D" + Found DFU: [0483:df11] ver=2200, devnum=74, cfg=1, intf=0, path="2-2", alt=0, name="@Internal Flash /0x08000000/512*0004Kg", serial="204A325D574D" + +You should see following confirmation on your Linux host: + +.. code-block:: console + + $ dmesg + usb 2-2: new full-speed USB device number 74 using xhci_hcd + usb 2-2: New USB device found, idVendor=0483, idProduct=df11 + usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 + usb 2-2: Product: STM32 BOOTLOADER + usb 2-2: Manufacturer: STMicroelectronics + usb 2-2: SerialNumber: 204A325D574D + +You can build and flash the provided sample application +(:ref:`sensortile_box_pro_sample_sensors`) that reads sensors data and outputs +values on the console. + +References +********** + +.. target-notes:: + +.. _SensorTile.box PRO website: + https://www.st.com/en/evaluation-tools/steval-mkboxpro.html + +.. _STM32U585 on www.st.com: + https://www.st.com/en/microcontrollers-microprocessors/stm32u575-585.html + +.. _STM32U585 reference manual: + https://www.st.com/resource/en/reference_manual/rm0456-stm32u575585-armbased-32bit-mcus-stmicroelectronics.pdf + +.. _lsm6dsv16x datasheet: + https://www.st.com/en/mems-and-sensors/lsm6dsv16x.html + +.. _lis2mdl datasheet: + https://www.st.com/en/mems-and-sensors/lis2mdl.html + +.. _lps22df datasheet: + https://www.st.com/en/mems-and-sensors/lps22df.html + +.. _lis2du12 datasheet: + https://www.st.com/en/mems-and-sensors/lis2du12.html + +.. _hts221 datasheet: + https://www.st.com/en/mems-and-sensors/hts221.html + +.. _stts22hh datasheet: + https://www.st.com/en/mems-and-sensors/stts22h.html + +.. _mp23db01hp datasheet: + https://www.st.com/en/mems-and-sensors/mp23db01hp.html + +.. _AN2606: + http://www.st.com/content/ccc/resource/technical/document/application_note/b9/9b/16/3a/12/1e/40/0c/CD00167594.pdf/files/CD00167594.pdf/jcr:content/translations/en.CD00167594.pdf + +.. _DFU-UTIL website: + http://dfu-util.sourceforge.net/ diff --git a/boards/arm/sensortile_box_pro/sensortile_box_pro.dts b/boards/arm/sensortile_box_pro/sensortile_box_pro.dts new file mode 100644 index 00000000000..485ec6b6e7d --- /dev/null +++ b/boards/arm/sensortile_box_pro/sensortile_box_pro.dts @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include + +/ { + model = "STMicroelectronics SENSORTILE-BOX-PRO board"; + compatible = "st,sensortile-box-pro"; + + chosen { + /* + * By default, Zephyr console and shell are assigned to + * USB CDC/ACM. To enable console and shell over UART, + * uncomment following lines and set the correct config + * in sensortile_box_pro_defconfig. + * + * zephyr,console = &uart4; + * zephyr,shell-uart = &uart4; + */ + zephyr,console = &cdc_acm_uart0; + zephyr,shell-uart = &cdc_acm_uart0; + + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + }; + + leds { + compatible = "gpio-leds"; + green_led_1: led_1 { + gpios = <&gpiof 6 GPIO_ACTIVE_HIGH>; + label = "User GREEN led"; + }; + red_led_1: led_2 { + gpios = <&gpioh 11 GPIO_ACTIVE_HIGH>; + label = "User RED led"; + }; + yellow_led_1: led_3 { + gpios = <&gpioh 12 GPIO_ACTIVE_HIGH>; + label = "User YELLOW led"; + }; + blue_led_1: led_4 { + gpios = <&gpiof 9 GPIO_ACTIVE_HIGH>; + label = "User YELLOW led"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + button1: button1 { + label = "User BT1"; + gpios = <&gpioc 13 GPIO_ACTIVE_HIGH>; + zephyr,code = ; + }; + button2: button2 { + label = "User BT2"; + gpios = <&gpioe 0 GPIO_ACTIVE_HIGH>; + zephyr,code = ; + }; + }; + + sd_card: sd-card { + compatible = "st,stile_sd_card"; + en-sd-gpios = <&gpioh 10 (GPIO_ACTIVE_HIGH)>; + sel-sd-gpios = <&gpioh 8 (GPIO_ACTIVE_HIGH)>; + }; + + aliases { + led0 = &green_led_1; + led1 = &red_led_1; + led2 = &yellow_led_1; + led3 = &blue_led_1; + mcuboot-led0 = &blue_led_1; + mcuboot-button0 = &button1; + sw1 = &button1; + sw2 = &button2; + watchdog0 = &iwdg; + die-temp0 = &die_temp; + volt-sensor0 = &vref1; + volt-sensor1 = &vbat4; + }; +}; + +&clk_hsi48 { + status = "okay"; +}; + +&clk_lse { + status = "okay"; +}; + +&clk_msis { + status = "okay"; + msi-range = <4>; + msi-pll-mode; +}; + +&gpioi { + status = "okay"; + + /* switch sensor IMU bus from I2C1 to SPI2 */ + mcu-sel-gpios { + gpio-hog; + gpios = <0 GPIO_ACTIVE_HIGH>; + output-low; + }; +}; + +&pll1 { + div-m = <1>; + mul-n = <80>; + div-q = <2>; + div-r = <2>; + clocks = <&clk_msis>; + status = "okay"; +}; + +&rcc { + clocks = <&pll1>; + clock-frequency = ; + ahb-prescaler = <1>; + apb1-prescaler = <1>; + apb2-prescaler = <1>; + apb3-prescaler = <1>; +}; + +&lptim1 { + clocks = <&rcc STM32_CLOCK_BUS_APB3 0x00000800>, + <&rcc STM32_SRC_LSE LPTIM1_SEL(3)>; + status = "okay"; +}; + +&usart1 { + pinctrl-0 = <&usart1_tx_pa9 &usart1_rx_pa10>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&usart3 { + pinctrl-0 = <&usart3_tx_pd8 &usart3_rx_pd9>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&uart4 { + pinctrl-0 = <&uart4_tx_pa0 &uart4_rx_pa1>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&spi1 { + pinctrl-0 = <&spi1_nss_pe12 &spi1_sck_pe13 + &spi1_miso_pe14 &spi1_mosi_pe15>; + pinctrl-names = "default"; + status = "okay"; +}; + +&spi2 { + pinctrl-0 = <&spi2_sck_pi1 &spi2_miso_pi2 &spi2_mosi_pi3>; + pinctrl-names = "default"; + status = "okay"; + + cs-gpios = <&gpioi 5 GPIO_ACTIVE_LOW>; + + lsm6dsv16x: lsm6dsv16x@0 { + compatible = "st,lsm6dsv16x"; + spi-max-frequency = ; /* 10 MHz */ + reg = <0>; + int1-gpios = <&gpioa 4 GPIO_ACTIVE_HIGH>; + int2-gpios = <&gpiod 11 GPIO_ACTIVE_HIGH>; + + drdy-pin = <2>; + }; +}; + +&timers4 { + status = "okay"; + st,prescaler = <1>; + pwm4: pwm { + status = "okay"; + pinctrl-0 = <&tim4_ch1_pb6>; + pinctrl-names = "default"; + }; +}; + +&timers3 { + status = "okay"; + st,prescaler = <255>; + pwm3: pwm { + status = "okay"; + pinctrl-0 = <&tim3_ch2_pe4>; + pinctrl-names = "default"; + }; +}; + +&i2c1 { + pinctrl-0 = <&i2c1_scl_pb6 &i2c1_sda_pb7>; + pinctrl-names = "default"; + status = "okay"; + clock-frequency = ; + + hts221@5f { + compatible = "st,hts221"; + reg = <0x5f>; + drdy-gpios = <&gpioe 11 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + + lps22df@5d { + compatible = "st,lps22df"; + reg = <0x5d>; + drdy-gpios = <&gpioe 8 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + + lis2mdl@1e { + compatible = "st,lis2mdl"; + reg = <0x1e>; + irq-gpios = <&gpioe 6 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; +}; + +&i2c2 { + pinctrl-0 = <&i2c2_scl_ph4 &i2c2_sda_ph5>; + pinctrl-names = "default"; + status = "okay"; + clock-frequency = ; +}; + +&aes { + status = "okay"; +}; + +&rng { + status = "okay"; +}; + +zephyr_udc0: &usbotg_fs { + pinctrl-0 = <&usb_otg_fs_dm_pa11 &usb_otg_fs_dp_pa12>; + pinctrl-names = "default"; + status = "okay"; + + cdc_acm_uart0: cdc_acm_uart0 { + compatible = "zephyr,cdc-acm-uart"; + }; +}; + +&adc1 { + pinctrl-0 = <&adc1_in15_pb0>; + pinctrl-names = "default"; + st,adc-clock-source = ; + st,adc-prescaler = <4>; + status = "okay"; +}; + +&adc4 { + pinctrl-0 = <&adc4_in19_pb1>; + pinctrl-names = "default"; + st,adc-clock-source = ; + st,adc-prescaler = <4>; + status = "okay"; +}; + +&die_temp { + status = "okay"; +}; + +&dac1 { + pinctrl-0 = <&dac1_out1_pa4>; + pinctrl-names = "default"; + status = "okay"; +}; + +&iwdg { + status = "okay"; +}; + +&vref1 { + status = "okay"; +}; + +&vbat4 { + status = "okay"; +}; + +&sdmmc1 { + status = "okay"; + pinctrl-0 = <&sdmmc1_d0_pc8 &sdmmc1_d1_pc9 + &sdmmc1_d2_pc10 &sdmmc1_d3_pc11 + &sdmmc1_ck_pc12 &sdmmc1_cmd_pd2 + &sdmmc1_d0dir_pc6 &sdmmc1_d123dir_pc7 + &sdmmc1_cdir_pb9 &sdmmc1_ckin_pb8>; + pinctrl-names = "default"; + cd-gpios = <&gpioc 5 GPIO_ACTIVE_LOW>; + pwr-gpios = <&gpioh 10 GPIO_ACTIVE_LOW>; + bus-width = <4>; + clk-div = <4>; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* + * Following flash partition is dedicated to the use of sensortile_box_pro + * with TZEN=0 (so w/o TFM). + * Set the partitions with first MB to make use of the whole Bank1 + */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 DT_SIZE_K(64)>; + }; + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 DT_SIZE_K(416)>; + }; + slot1_partition: partition@78000 { + label = "image-1"; + reg = <0x00078000 DT_SIZE_K(416)>; + }; + scratch_partition: partition@e0000 { + label = "image-scratch"; + reg = <0x000e0000 DT_SIZE_K(64)>; + }; + storage_partition: partition@f0000 { + label = "storage"; + reg = <0x000f0000 DT_SIZE_K(64)>; + }; + + }; +}; + +&gpdma1 { + status = "okay"; +}; diff --git a/boards/arm/sensortile_box_pro/sensortile_box_pro.yaml b/boards/arm/sensortile_box_pro/sensortile_box_pro.yaml new file mode 100644 index 00000000000..da81ee182e1 --- /dev/null +++ b/boards/arm/sensortile_box_pro/sensortile_box_pro.yaml @@ -0,0 +1,19 @@ +identifier: sensortile_box_pro +name: ST SensorTile.box Pro +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - pwm + - spi + - i2c + - gpio + - usb device + - nvs + - counter +ram: 640 +flash: 2048 +vendor: st diff --git a/boards/arm/sensortile_box_pro/sensortile_box_pro_defconfig b/boards/arm/sensortile_box_pro/sensortile_box_pro_defconfig new file mode 100644 index 00000000000..a75aad1dad5 --- /dev/null +++ b/boards/arm/sensortile_box_pro/sensortile_box_pro_defconfig @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_STM32U5X=y +CONFIG_SOC_STM32U585XX=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable Clocks +CONFIG_CLOCK_CONTROL=y + +# config USB and USB console +CONFIG_SERIAL=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_UART_LINE_CTRL=y +CONFIG_UART_INTERRUPT_DRIVEN=y + +# Comment out following USB config lines when +# switching console to UART +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_VID=0x0483 +CONFIG_USB_DEVICE_PID=0x1235 +CONFIG_USB_DEVICE_PRODUCT="Zephyr CDC SensorTile.box PRO" +CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n + +# enable pin controller +CONFIG_PINCTRL=y + +# LSE defined as LPTIM clock source by the DTS +CONFIG_STM32_LPTIM_CLOCK_LSE=y diff --git a/boards/arm/sensortile_box_pro/support/openocd.cfg b/boards/arm/sensortile_box_pro/support/openocd.cfg new file mode 100644 index 00000000000..ee58ed51d43 --- /dev/null +++ b/boards/arm/sensortile_box_pro/support/openocd.cfg @@ -0,0 +1,44 @@ +source [find interface/stlink-dap.cfg] + +set WORKAREASIZE 0x8000 + +transport select "dapdirect_swd" + +set CHIPNAME STM32U575ZITxQ +set BOARDNAME STILE-BOX-PRO + +# Enable debug when in low power modes +set ENABLE_LOW_POWER 1 + +# Stop Watchdog counters when halt +set STOP_WATCHDOG 1 + +# STlink Debug clock frequency +set CLOCK_FREQ 8000 + +# Reset configuration +# use hardware reset, connect under reset +# connect_assert_srst needed if low power mode application running (WFI...) +reset_config srst_only srst_nogate connect_assert_srst +set CONNECT_UNDER_RESET 1 +set CORE_RESET 0 + +# ACCESS PORT NUMBER +set AP_NUM 0 +# GDB PORT +set GDB_PORT 3333 + +# BCTM CPU variables + +source [find target/stm32u5x.cfg] + +$_TARGETNAME configure -event gdb-attach { + echo "Debugger attaching: halting execution" + reset halt + gdb_breakpoint_override hard +} + +$_TARGETNAME configure -event gdb-detach { + echo "Debugger detaching: resuming execution" + resume +} diff --git a/boards/arm/serpente/doc/index.rst b/boards/arm/serpente/doc/index.rst index e2369d0b95e..c446103c712 100644 --- a/boards/arm/serpente/doc/index.rst +++ b/boards/arm/serpente/doc/index.rst @@ -75,7 +75,7 @@ USB Device Port The SAMD21 MCU has a USB device port that can be used to communicate with a host PC. See the :ref:`usb-samples` sample applications for -more, such as the :ref:`usb_cdc-acm` sample which prints "Hello World!" +more, such as the :zephyr:code-sample:`usb-cdc-acm` sample which prints "Hello World!" to the host PC. Programming and Debugging @@ -87,7 +87,7 @@ can be entered by quickly tapping the reset button twice. Flashing ======== -#. Build the Zephyr kernel and the :ref:`blinky-sample` sample application: +#. Build the Zephyr kernel and the :zephyr:code-sample:`blinky` sample application: .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/serpente/serpente.dts b/boards/arm/serpente/serpente.dts index 3237920aa5e..d042cb4a363 100644 --- a/boards/arm/serpente/serpente.dts +++ b/boards/arm/serpente/serpente.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include #include "serpente-pinctrl.dtsi" / { diff --git a/boards/arm/serpente/serpente_defconfig b/boards/arm/serpente/serpente_defconfig index a2c3ac7def2..b670a7b0476 100644 --- a/boards/arm/serpente/serpente_defconfig +++ b/boards/arm/serpente/serpente_defconfig @@ -3,6 +3,8 @@ CONFIG_SOC_SERIES_SAMD21=y CONFIG_SOC_PART_NUMBER_SAMD21E18A=y CONFIG_BOARD_SERPENTE=y +CONFIG_SOC_ATMEL_SAMD_OSC8M=y +CONFIG_SOC_ATMEL_SAMD_OSC8M_AS_MAIN=y CONFIG_CONSOLE=y CONFIG_GPIO=y CONFIG_UART_CONSOLE=y diff --git a/boards/arm/sparkfun_pro_micro_rp2040/doc/index.rst b/boards/arm/sparkfun_pro_micro_rp2040/doc/index.rst index e2de7d69aaf..1999d64def7 100644 --- a/boards/arm/sparkfun_pro_micro_rp2040/doc/index.rst +++ b/boards/arm/sparkfun_pro_micro_rp2040/doc/index.rst @@ -79,6 +79,9 @@ hardware features: * - Flash - :kconfig:option:`CONFIG_FLASH` - :dtcompatible:`raspberrypi,pico-flash` + * - UART (PIO) + - :kconfig:option:`CONFIG_SERIAL` + - :dtcompatible:`raspberrypi,pico-uart-pio` Pin Mapping =========== diff --git a/boards/arm/sparkfun_pro_micro_rp2040/sparkfun_pro_micro_rp2040.yaml b/boards/arm/sparkfun_pro_micro_rp2040/sparkfun_pro_micro_rp2040.yaml index c898e1b5d53..d5993798ff4 100644 --- a/boards/arm/sparkfun_pro_micro_rp2040/sparkfun_pro_micro_rp2040.yaml +++ b/boards/arm/sparkfun_pro_micro_rp2040/sparkfun_pro_micro_rp2040.yaml @@ -18,3 +18,4 @@ supported: - watchdog - pwm - flash + - dma diff --git a/boards/arm/sparkfun_thing_plus_nrf9160/doc/index.rst b/boards/arm/sparkfun_thing_plus_nrf9160/doc/index.rst index aa1a0e6279d..8ee7a38cb33 100644 --- a/boards/arm/sparkfun_thing_plus_nrf9160/doc/index.rst +++ b/boards/arm/sparkfun_thing_plus_nrf9160/doc/index.rst @@ -134,8 +134,8 @@ Testing the LEDs and buttons on the nRF9160 Thing Plus There are 2 samples that allow you to test that the buttons (switches) and LEDs on the board are working properly with Zephyr: -* :ref:`blinky-sample` -* :ref:`button-sample` +* :zephyr:code-sample:`blinky` +* :zephyr:code-sample:`button` You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in diff --git a/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160.yaml b/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160.yaml index 1b00c842f04..8758b385c9d 100644 --- a/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160.yaml +++ b/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160.yaml @@ -13,3 +13,4 @@ supported: - pwm - watchdog - counter +vendor: sparkfun diff --git a/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_defconfig b/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_defconfig index e53eb77c651..8748d5dd83c 100644 --- a/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_defconfig +++ b/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_defconfig @@ -20,6 +20,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -CONFIG_PINCTRL=y - CONFIG_REGULATOR=y diff --git a/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_ns.yaml b/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_ns.yaml index adbef49e2b0..65f9eaad326 100644 --- a/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_ns.yaml +++ b/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_ns.yaml @@ -12,3 +12,4 @@ supported: - i2c - pwm - watchdog +vendor: sparkfun diff --git a/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_ns_defconfig b/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_ns_defconfig index f2e6c1026c7..92818ef157b 100644 --- a/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_ns_defconfig +++ b/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_ns_defconfig @@ -23,6 +23,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -CONFIG_PINCTRL=y - CONFIG_REGULATOR=y diff --git a/boards/arm/steval_fcu001v1/doc/index.rst b/boards/arm/steval_fcu001v1/doc/index.rst index f28685e7fa9..823631dd120 100644 --- a/boards/arm/steval_fcu001v1/doc/index.rst +++ b/boards/arm/steval_fcu001v1/doc/index.rst @@ -155,4 +155,4 @@ You can debug an application in the usual way. Here is an example for the https://www.st.com/en/microcontrollers-microprocessors/stm32f401cc.html .. _STM32F401 reference manual: - http://www.st.com/resource/en/reference_manual/dm00096844.pdf + https://www.st.com/resource/en/reference_manual/dm00096844.pdf diff --git a/boards/arm/steval_fcu001v1/steval_fcu001v1.yaml b/boards/arm/steval_fcu001v1/steval_fcu001v1.yaml index 951cb1b76dc..64ac751a2fc 100644 --- a/boards/arm/steval_fcu001v1/steval_fcu001v1.yaml +++ b/boards/arm/steval_fcu001v1/steval_fcu001v1.yaml @@ -14,3 +14,4 @@ supported: - watchdog ram: 64 flash: 256 +vendor: st diff --git a/boards/arm/stm3210c_eval/doc/index.rst b/boards/arm/stm3210c_eval/doc/index.rst index 6ec151a1cec..9d9278e1614 100644 --- a/boards/arm/stm3210c_eval/doc/index.rst +++ b/boards/arm/stm3210c_eval/doc/index.rst @@ -125,7 +125,7 @@ Flashing an application to STM3210C-EVAL Connect the STM3210C-EVAL to your host computer using the USB port, then build and flash an application in the usual way. -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -159,7 +159,7 @@ References .. target-notes:: .. _STM3210C-EVAL website: - http://www.st.com/en/evaluation-tools/stm3210c-eval.html + https://www.st.com/en/evaluation-tools/stm3210c-eval.html .. _STM32F107VCT reference manual: - http://www.st.com/resource/en/reference_manual/CD00171190.pdf + https://www.st.com/resource/en/reference_manual/CD00171190.pdf diff --git a/boards/arm/stm3210c_eval/stm3210c_eval.yaml b/boards/arm/stm3210c_eval/stm3210c_eval.yaml index ecd46ace145..ae64ea9fe47 100644 --- a/boards/arm/stm3210c_eval/stm3210c_eval.yaml +++ b/boards/arm/stm3210c_eval/stm3210c_eval.yaml @@ -10,3 +10,4 @@ ram: 64 flash: 256 supported: - watchdog +vendor: st diff --git a/boards/arm/stm32373c_eval/doc/index.rst b/boards/arm/stm32373c_eval/doc/index.rst index 2f27c57d0d4..9f6ed1d750b 100644 --- a/boards/arm/stm32373c_eval/doc/index.rst +++ b/boards/arm/stm32373c_eval/doc/index.rst @@ -126,7 +126,7 @@ This interface is supported by the openocd version included in Zephyr SDK. Flashing an application to STM32373C-EVAL ----------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -139,7 +139,7 @@ Debugging ========= You can debug an application in the usual way. Here is an example for the -:ref:`blinky-sample` application. +:zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -153,7 +153,7 @@ References .. target-notes:: .. _STM32373C-EVAL website: - http://www.st.com/en/evaluation-tools/stm32373c-eval.html + https://www.st.com/en/evaluation-tools/stm32373c-eval.html .. _STM32F373VCT6 reference manual: - http://www.st.com/resource/en/reference_manual/dm00041563.pdf + https://www.st.com/resource/en/reference_manual/dm00041563.pdf diff --git a/boards/arm/stm32373c_eval/stm32373c_eval.yaml b/boards/arm/stm32373c_eval/stm32373c_eval.yaml index 6342f2a587c..6d06bffe951 100644 --- a/boards/arm/stm32373c_eval/stm32373c_eval.yaml +++ b/boards/arm/stm32373c_eval/stm32373c_eval.yaml @@ -10,3 +10,4 @@ ram: 32 supported: - watchdog - counter +vendor: st diff --git a/boards/arm/stm32_min_dev/doc/index.rst b/boards/arm/stm32_min_dev/doc/index.rst index 728191c15f0..6d83f0f7ec7 100644 --- a/boards/arm/stm32_min_dev/doc/index.rst +++ b/boards/arm/stm32_min_dev/doc/index.rst @@ -161,7 +161,7 @@ built and flashed in the usual way (see :ref:`build_an_application` and Flashing ======== -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -181,6 +181,6 @@ You can debug an application in the usual way. Here is an example for the :goals: debug .. _STM32F103x8: - http://www.st.com/resource/en/datasheet/stm32f103c8.pdf + https://www.st.com/resource/en/datasheet/stm32f103c8.pdf .. _EmbedJournal: https://embedjournal.com/tag/stm32-min-dev/ diff --git a/boards/arm/stm32_min_dev/stm32_min_dev_black.yaml b/boards/arm/stm32_min_dev/stm32_min_dev_black.yaml index c0062720aef..28739cf2b63 100644 --- a/boards/arm/stm32_min_dev/stm32_min_dev_black.yaml +++ b/boards/arm/stm32_min_dev/stm32_min_dev_black.yaml @@ -13,3 +13,4 @@ supported: - spi - adc - gpio +vendor: st diff --git a/boards/arm/stm32_min_dev/stm32_min_dev_blue.yaml b/boards/arm/stm32_min_dev/stm32_min_dev_blue.yaml index 2d39e25b8b0..ed907a960ce 100644 --- a/boards/arm/stm32_min_dev/stm32_min_dev_blue.yaml +++ b/boards/arm/stm32_min_dev/stm32_min_dev_blue.yaml @@ -12,3 +12,4 @@ supported: - pwm - spi - adc +vendor: st diff --git a/boards/arm/stm32f030_demo/doc/index.rst b/boards/arm/stm32f030_demo/doc/index.rst index 3c57989be0a..a1f3ecd68e2 100644 --- a/boards/arm/stm32f030_demo/doc/index.rst +++ b/boards/arm/stm32f030_demo/doc/index.rst @@ -87,7 +87,7 @@ This interface is supported by the openocd version included in the Zephyr SDK. Flashing an application to STM32F030 DEMO BOARD ----------------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -100,7 +100,7 @@ Debugging ========= You can debug an application in the usual way. Here is an example for the -:ref:`blinky-sample` application. +:zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/stm32f072_eval/doc/index.rst b/boards/arm/stm32f072_eval/doc/index.rst index fad35d0c980..4872f85785b 100644 --- a/boards/arm/stm32f072_eval/doc/index.rst +++ b/boards/arm/stm32f072_eval/doc/index.rst @@ -156,7 +156,7 @@ This interface is supported by the openocd version included in Zephyr SDK. Flashing an application to STM32F072-EVAL ------------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -169,7 +169,7 @@ Debugging ========= You can debug an application in the usual way. Here is an example for the -:ref:`blinky-sample` application. +:zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -179,7 +179,7 @@ You can debug an application in the usual way. Here is an example for the .. _STM32F072VB on www.st.com: - http://www.st.com/en/microcontrollers/stm32f072vb.html + https://www.st.com/en/microcontrollers/stm32f072vb.html .. _STM32F072 reference manual: - http://www.st.com/resource/en/reference_manual/dm00031936.pdf + https://www.st.com/resource/en/reference_manual/dm00031936.pdf diff --git a/boards/arm/stm32f072_eval/stm32f072_eval.yaml b/boards/arm/stm32f072_eval/stm32f072_eval.yaml index ddcdef183e0..b6655a01722 100644 --- a/boards/arm/stm32f072_eval/stm32f072_eval.yaml +++ b/boards/arm/stm32f072_eval/stm32f072_eval.yaml @@ -13,3 +13,4 @@ supported: testing: ignore_tags: - net +vendor: st diff --git a/boards/arm/stm32f072b_disco/doc/index.rst b/boards/arm/stm32f072b_disco/doc/index.rst index e442d035d95..3756926ec4c 100644 --- a/boards/arm/stm32f072b_disco/doc/index.rst +++ b/boards/arm/stm32f072b_disco/doc/index.rst @@ -203,17 +203,17 @@ References .. target-notes:: .. _STM32F072B-DISCO website: - http://www.st.com/en/evaluation-tools/32f072bdiscovery.html + https://www.st.com/en/evaluation-tools/32f072bdiscovery.html .. _STM32F072B-DISCO board User Manual: - http://www.st.com/resource/en/user_manual/dm00099401.pdf + https://www.st.com/resource/en/user_manual/dm00099401.pdf .. _STM32F072RB on www.st.com: - http://www.st.com/en/microcontrollers/stm32f072rb.html + https://www.st.com/en/microcontrollers/stm32f072rb.html .. _STM32F072xB reference manual: - http://www.st.com/resource/en/reference_manual/dm00031936.pdf + https://www.st.com/resource/en/reference_manual/dm00031936.pdf .. _SK Pang CAN breakout board: https://www.skpang.co.uk/products/can-bus-can-fd-breakout-board-5v-supply-and-5v-logic diff --git a/boards/arm/stm32f072b_disco/stm32f072b_disco.yaml b/boards/arm/stm32f072b_disco/stm32f072b_disco.yaml index 5e24b081bd8..186d733ca7d 100644 --- a/boards/arm/stm32f072b_disco/stm32f072b_disco.yaml +++ b/boards/arm/stm32f072b_disco/stm32f072b_disco.yaml @@ -18,3 +18,4 @@ testing: ignore_tags: - net - bluetooth +vendor: st diff --git a/boards/arm/stm32f0_disco/doc/index.rst b/boards/arm/stm32f0_disco/doc/index.rst index b528f22adc9..e2910793d72 100644 --- a/boards/arm/stm32f0_disco/doc/index.rst +++ b/boards/arm/stm32f0_disco/doc/index.rst @@ -107,7 +107,7 @@ This interface is supported by the openocd version included in the Zephyr SDK. Flashing an application to Nucleo F030R8 ---------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -120,7 +120,7 @@ Debugging ========= You can debug an application in the usual way. Here is an example for the -:ref:`blinky-sample` application. +:zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -134,10 +134,10 @@ References .. target-notes:: .. _STM32F0DISCOVERY website: - http://www.st.com/en/evaluation-tools/stm32f0discovery.html + https://www.st.com/en/evaluation-tools/stm32f0discovery.html .. _STM32F0x8 reference manual: - http://www.st.com/resource/en/reference_manual/dm00031936.pdf + https://www.st.com/resource/en/reference_manual/dm00031936.pdf .. _STM32F0DISCOVERY board User Manual: - http://www.st.com/resource/en/user_manual/dm00050135.pdf + https://www.st.com/resource/en/user_manual/dm00050135.pdf diff --git a/boards/arm/stm32f0_disco/stm32f0_disco.yaml b/boards/arm/stm32f0_disco/stm32f0_disco.yaml index 2a5cbec6e7a..53954e2a4ed 100644 --- a/boards/arm/stm32f0_disco/stm32f0_disco.yaml +++ b/boards/arm/stm32f0_disco/stm32f0_disco.yaml @@ -9,3 +9,4 @@ toolchain: ram: 8 supported: - watchdog +vendor: st diff --git a/boards/arm/stm32f103_mini/doc/index.rst b/boards/arm/stm32f103_mini/doc/index.rst index 5ae9621bebc..57e812d0c3a 100644 --- a/boards/arm/stm32f103_mini/doc/index.rst +++ b/boards/arm/stm32f103_mini/doc/index.rst @@ -133,7 +133,7 @@ pattern, which can be triggered by using the BOOT0 pin. Flashing an application to stm32f103 mini ----------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -146,7 +146,7 @@ Debugging ========= You can debug an application in the usual way. Here is an example for the -:ref:`blinky-sample` application. +:zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -160,7 +160,7 @@ References .. target-notes:: .. _STM32F103 reference manual: - http://www.st.com/resource/en/reference_manual/cd00171190.pdf + https://www.st.com/resource/en/reference_manual/cd00171190.pdf .. _STM32F103 data sheet: - http://www.st.com/resource/en/datasheet/stm32f103rc.pdf + https://www.st.com/resource/en/datasheet/stm32f103rc.pdf diff --git a/boards/arm/stm32f103_mini/stm32f103_mini.yaml b/boards/arm/stm32f103_mini/stm32f103_mini.yaml index 7ce2c6ee5bd..ef1427ba5f9 100644 --- a/boards/arm/stm32f103_mini/stm32f103_mini.yaml +++ b/boards/arm/stm32f103_mini/stm32f103_mini.yaml @@ -16,3 +16,4 @@ supported: - watchdog - adc - counter +vendor: st diff --git a/boards/arm/stm32f3_disco/doc/index.rst b/boards/arm/stm32f3_disco/doc/index.rst index f0ccbfd7fca..a94083fa2c7 100644 --- a/boards/arm/stm32f3_disco/doc/index.rst +++ b/boards/arm/stm32f3_disco/doc/index.rst @@ -269,13 +269,13 @@ Again you have to use the adapted command for newer PCB revisions (E and newer): :goals: debug .. _STM32F3DISCOVERY website: - http://www.st.com/en/evaluation-tools/stm32f3discovery.html + https://www.st.com/en/evaluation-tools/stm32f3discovery.html .. _STM32F3DISCOVERY board User Manual: - http://www.st.com/resource/en/user_manual/dm00063382.pdf + https://www.st.com/resource/en/user_manual/dm00063382.pdf .. _STM32F303VC on www.st.com: - http://www.st.com/en/microcontrollers/stm32f303vc.html + https://www.st.com/en/microcontrollers/stm32f303vc.html .. _STM32F303xC reference manual: - http://www.st.com/resource/en/reference_manual/dm00043574.pdf + https://www.st.com/resource/en/reference_manual/dm00043574.pdf diff --git a/boards/arm/stm32f3_disco/stm32f3_disco.yaml b/boards/arm/stm32f3_disco/stm32f3_disco.yaml index ef5b77054cc..0d0aafdc5a2 100644 --- a/boards/arm/stm32f3_disco/stm32f3_disco.yaml +++ b/boards/arm/stm32f3_disco/stm32f3_disco.yaml @@ -21,3 +21,4 @@ supported: - adc - dac - dma +vendor: st diff --git a/boards/arm/stm32f3_seco_d23/doc/index.rst b/boards/arm/stm32f3_seco_d23/doc/index.rst index c551b2f3ca4..9b500e372ff 100644 --- a/boards/arm/stm32f3_seco_d23/doc/index.rst +++ b/boards/arm/stm32f3_seco_d23/doc/index.rst @@ -236,7 +236,7 @@ You should see the following message on the console: https://www.seco.com/Manuals/SBC-D23_Manual.pdf .. _STM32F302VC on www.st.com: - http://www.st.com/en/microcontrollers/stm32f302vc.html + https://www.st.com/en/microcontrollers/stm32f302vc.html .. _STM32F302xC reference manual: https://www.st.com/resource/en/reference_manual/rm0365-stm32f302xbcde-and-stm32f302x68-advanced-armbased-32bit-mcus-stmicroelectronics.pdf diff --git a/boards/arm/stm32f411e_disco/doc/index.rst b/boards/arm/stm32f411e_disco/doc/index.rst index 5c8749012f7..d15dc7728c7 100644 --- a/boards/arm/stm32f411e_disco/doc/index.rst +++ b/boards/arm/stm32f411e_disco/doc/index.rst @@ -141,7 +141,7 @@ Flashing an application to STM32F411E-DISCO Connect the STM32F411E-DISCO Discovery kit to your host computer using the USB port. Then build and flash an application. -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -162,7 +162,7 @@ Debugging ========= You can debug applications in the usual way. Here is an example for -the :ref:`blinky-sample` application. +the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -176,13 +176,13 @@ References .. target-notes:: .. _32F411EDISCOVERY website: - http://www.st.com/en/evaluation-tools/32f411ediscovery.html + https://www.st.com/en/evaluation-tools/32f411ediscovery.html .. _32F411EDISCOVERY board User Manual: - http://www.st.com/resource/en/user_manual/dm00148985.pdf + https://www.st.com/resource/en/user_manual/dm00148985.pdf .. _STM32F411VE website: - http://www.st.com/en/microcontrollers/stm32f411ve.html + https://www.st.com/en/microcontrollers/stm32f411ve.html .. _STM32F411x reference manual: - http://www.st.com/resource/en/reference_manual/dm00119316.pdf + https://www.st.com/resource/en/reference_manual/dm00119316.pdf diff --git a/boards/arm/stm32f411e_disco/stm32f411e_disco.dts b/boards/arm/stm32f411e_disco/stm32f411e_disco.dts index bd4d425c5bc..197df98212d 100644 --- a/boards/arm/stm32f411e_disco/stm32f411e_disco.dts +++ b/boards/arm/stm32f411e_disco/stm32f411e_disco.dts @@ -16,8 +16,10 @@ chosen { zephyr,console = &usart2; zephyr,shell-uart = &usart2; + zephyr,uart-mcumgr = &usart2; zephyr,sram = &sram0; zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; }; leds { @@ -60,7 +62,7 @@ compatible = "gpio-keys"; user_button: button { label = "User"; - gpios = <&gpioa 0 GPIO_ACTIVE_LOW>; + gpios = <&gpioa 0 GPIO_ACTIVE_HIGH>; zephyr,code = ; }; }; @@ -77,6 +79,8 @@ pwm-led3 = &blue_pwm_led; magn0 = &lsm303agr_magn; accel0 = &lsm303agr_accel; + mcuboot-button0 = &user_button; + mcuboot-led0 = &orange_led_3; }; }; @@ -160,3 +164,32 @@ zephyr_udc0: &usbotg_fs { pinctrl-names = "default"; status = "okay"; }; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 DT_SIZE_K(64)>; + read-only; + }; + + slot0_partition: partition@20000 { + label = "image-0"; + reg = <0x00020000 DT_SIZE_K(128)>; + }; + + slot1_partition: partition@40000 { + label = "image-1"; + reg = <0x00040000 DT_SIZE_K(128)>; + }; + + scratch_partition: partition@60000 { + label = "image-scratch"; + reg = <0x00060000 DT_SIZE_K(128)>; + }; + }; +}; diff --git a/boards/arm/stm32f411e_disco/stm32f411e_disco.yaml b/boards/arm/stm32f411e_disco/stm32f411e_disco.yaml index 7ede09caf04..725a9fd46bd 100644 --- a/boards/arm/stm32f411e_disco/stm32f411e_disco.yaml +++ b/boards/arm/stm32f411e_disco/stm32f411e_disco.yaml @@ -8,3 +8,4 @@ toolchain: - xtools supported: - counter +vendor: st diff --git a/boards/arm/stm32f412g_disco/doc/index.rst b/boards/arm/stm32f412g_disco/doc/index.rst index 3849a0d7b9d..b79f9b18a0a 100644 --- a/boards/arm/stm32f412g_disco/doc/index.rst +++ b/boards/arm/stm32f412g_disco/doc/index.rst @@ -190,13 +190,13 @@ You can debug an application in the usual way. Here is an example for the :goals: debug .. _32F412GDISCOVERY website: - http://www.st.com/en/evaluation-tools/32f412gdiscovery.html + https://www.st.com/en/evaluation-tools/32f412gdiscovery.html .. _32F412GDISCOVERY board User Manual: - http://www.st.com/resource/en/user_manual/dm00275919.pdf + https://www.st.com/resource/en/user_manual/dm00275919.pdf .. _STM32F412ZG on www.st.com: - http://www.st.com/en/microcontrollers/stm32f412zg.html + https://www.st.com/en/microcontrollers/stm32f412zg.html .. _STM32F412 reference manual: - http://www.st.com/resource/en/reference_manual/dm00180369.pdf + https://www.st.com/resource/en/reference_manual/dm00180369.pdf diff --git a/boards/arm/stm32f412g_disco/stm32f412g_disco.yaml b/boards/arm/stm32f412g_disco/stm32f412g_disco.yaml index 78f2cb5bd6e..5bf836929ba 100644 --- a/boards/arm/stm32f412g_disco/stm32f412g_disco.yaml +++ b/boards/arm/stm32f412g_disco/stm32f412g_disco.yaml @@ -12,3 +12,4 @@ supported: - arduino_i2c - arduino_spi - counter +vendor: st diff --git a/boards/arm/stm32f429i_disc1/Kconfig.defconfig b/boards/arm/stm32f429i_disc1/Kconfig.defconfig index 37fefc2292a..b6e1113e010 100644 --- a/boards/arm/stm32f429i_disc1/Kconfig.defconfig +++ b/boards/arm/stm32f429i_disc1/Kconfig.defconfig @@ -8,6 +8,9 @@ if BOARD_STM32F429I_DISC1 config BOARD default "stm32f429i_disc1" +config INPUT + default y if DISPLAY + config MEMC default y if DISPLAY diff --git a/boards/arm/stm32f429i_disc1/doc/index.rst b/boards/arm/stm32f429i_disc1/doc/index.rst index d397c414e4f..1a8defe5340 100644 --- a/boards/arm/stm32f429i_disc1/doc/index.rst +++ b/boards/arm/stm32f429i_disc1/doc/index.rst @@ -196,13 +196,13 @@ You can debug an application in the usual way. Here is an example for the :goals: debug .. _STM32F429I-DISC1 website: - http://www.st.com/en/evaluation-tools/32f429idiscovery.html + https://www.st.com/en/evaluation-tools/32f429idiscovery.html .. _STM32F429I-DISC1 board User Manual: - http://www.st.com/web/en/resource/technical/document/user_manual/DM00097320.pdf + https://www.st.com/web/en/resource/technical/document/user_manual/DM00097320.pdf .. _STM32F429ZI on www.st.com: - http://www.st.com/en/microcontrollers/stm32f429-439.html + https://www.st.com/en/microcontrollers/stm32f429-439.html .. _STM32F429 Reference Manual: - http://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf + https://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf diff --git a/boards/arm/stm32f429i_disc1/stm32f429i_disc1.dts b/boards/arm/stm32f429i_disc1/stm32f429i_disc1.dts index 6bd6b450130..60b8c2874f9 100644 --- a/boards/arm/stm32f429i_disc1/stm32f429i_disc1.dts +++ b/boards/arm/stm32f429i_disc1/stm32f429i_disc1.dts @@ -55,6 +55,13 @@ led0 = &green_led_3; sw0 = &user_button; }; + + lvgl_pointer { + compatible = "zephyr,lvgl-pointer-input"; + input = <&stmpe811>; + invert-x; + invert-y; + }; }; &clk_lsi { @@ -115,6 +122,23 @@ pinctrl-names = "default"; status = "okay"; clock-frequency = ; + + stmpe811: stmpe811@41 { + compatible = "st,stmpe811"; + status = "okay"; + reg = <0x41>; + int-gpios = <&gpioa 15 GPIO_ACTIVE_LOW>; + screen-width = <240>; + screen-height = <320>; + raw-x-min = <240>; + raw-y-min = <200>; + raw-x-max = <3680>; + raw-y-max = <3800>; + panel-driver-settling-time-us = <1000>; + touch-detect-delay-us = <5000>; + touch-average-control = <8>; + tracking-index = <127>; + }; }; &spi5 { diff --git a/boards/arm/stm32f429i_disc1/stm32f429i_disc1.yaml b/boards/arm/stm32f429i_disc1/stm32f429i_disc1.yaml index ce8b9d2ae78..5d4b25c8312 100644 --- a/boards/arm/stm32f429i_disc1/stm32f429i_disc1.yaml +++ b/boards/arm/stm32f429i_disc1/stm32f429i_disc1.yaml @@ -13,3 +13,4 @@ supported: - i2c - spi - display +vendor: st diff --git a/boards/arm/stm32f469i_disco/doc/index.rst b/boards/arm/stm32f469i_disco/doc/index.rst index b2c5fd5d3a0..7ba1d7c71e3 100644 --- a/boards/arm/stm32f469i_disco/doc/index.rst +++ b/boards/arm/stm32f469i_disco/doc/index.rst @@ -196,13 +196,13 @@ You can debug an application in the usual way. Here is an example for the .. _32F469IDISCOVERY website: - http://www.st.com/en/evaluation-tools/32f469idiscovery.html + https://www.st.com/en/evaluation-tools/32f469idiscovery.html .. _32F469IDISCOVERY board User Manual: - http://www.st.com/resource/en/user_manual/dm00218846.pdf + https://www.st.com/resource/en/user_manual/dm00218846.pdf .. _STM32F469NI on www.st.com: - http://www.st.com/en/microcontrollers/stm32f469ni.html + https://www.st.com/en/microcontrollers/stm32f469ni.html .. _STM32F469 reference manual: - http://www.st.com/resource/en/reference_manual/dm00127514.pdf + https://www.st.com/resource/en/reference_manual/dm00127514.pdf diff --git a/boards/arm/stm32f469i_disco/stm32f469i_disco.yaml b/boards/arm/stm32f469i_disco/stm32f469i_disco.yaml index fc65586446f..fef17c354b8 100644 --- a/boards/arm/stm32f469i_disco/stm32f469i_disco.yaml +++ b/boards/arm/stm32f469i_disco/stm32f469i_disco.yaml @@ -17,3 +17,4 @@ supported: - gpio - arduino_gpio - usb_device +vendor: st diff --git a/boards/arm/stm32f4_disco/doc/index.rst b/boards/arm/stm32f4_disco/doc/index.rst index 7cd7c26020d..8ea4ef9893c 100644 --- a/boards/arm/stm32f4_disco/doc/index.rst +++ b/boards/arm/stm32f4_disco/doc/index.rst @@ -169,7 +169,7 @@ This interface is supported by the openocd version included in Zephyr SDK. Flashing an application to STM32F4DISCOVERY ------------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. Run a serial host program to connect with your board: @@ -199,16 +199,16 @@ You can debug an application in the usual way. Here is an example for the :goals: debug .. _STM32F4DISCOVERY website: - http://www.st.com/en/evaluation-tools/stm32f4discovery.html + https://www.st.com/en/evaluation-tools/stm32f4discovery.html .. _STM32F4DISCOVERY board User Manual: - http://www.st.com/resource/en/user_manual/dm00039084.pdf + https://www.st.com/resource/en/user_manual/dm00039084.pdf .. _STM32F407VG on www.st.com: - http://www.st.com/en/microcontrollers/stm32f407vg.html + https://www.st.com/en/microcontrollers/stm32f407vg.html .. _STM32F407 reference manual: - http://www.st.com/resource/en/reference_manual/dm00031020.pdf + https://www.st.com/resource/en/reference_manual/dm00031020.pdf .. _SK Pang CAN breakout board: https://www.skpang.co.uk/products/can-bus-can-fd-breakout-board-5v-supply-and-3-3v-logic diff --git a/boards/arm/stm32f4_disco/stm32f4_disco.yaml b/boards/arm/stm32f4_disco/stm32f4_disco.yaml index 525c948ec36..5bdfaca3b7b 100644 --- a/boards/arm/stm32f4_disco/stm32f4_disco.yaml +++ b/boards/arm/stm32f4_disco/stm32f4_disco.yaml @@ -13,3 +13,4 @@ supported: - pwm - counter - usb +vendor: st diff --git a/boards/arm/stm32f723e_disco/doc/index.rst b/boards/arm/stm32f723e_disco/doc/index.rst index 8fe202a75c3..5ebcc65c392 100644 --- a/boards/arm/stm32f723e_disco/doc/index.rst +++ b/boards/arm/stm32f723e_disco/doc/index.rst @@ -180,13 +180,13 @@ You can debug an application in the usual way. Here is an example for the .. _32F723E-DISCO website: - http://www.st.com/en/evaluation-tools/32f723ediscovery.html + https://www.st.com/en/evaluation-tools/32f723ediscovery.html .. _32F723E-DISCO board User Manual: - http://www.st.com/resource/en/user_manual/dm00342318.pdf + https://www.st.com/resource/en/user_manual/dm00342318.pdf .. _STM32F723IEK6 on www.st.com: - http://www.st.com/en/microcontrollers/stm32f723ie.html + https://www.st.com/en/microcontrollers/stm32f723ie.html .. _STM32F72xxx reference manual: - http://www.st.com/resource/en/reference_manual/dm00305990.pdf + https://www.st.com/resource/en/reference_manual/dm00305990.pdf diff --git a/boards/arm/stm32f723e_disco/stm32f723e_disco.yaml b/boards/arm/stm32f723e_disco/stm32f723e_disco.yaml index 95e18e63515..d8f5b1a14a7 100644 --- a/boards/arm/stm32f723e_disco/stm32f723e_disco.yaml +++ b/boards/arm/stm32f723e_disco/stm32f723e_disco.yaml @@ -16,3 +16,4 @@ supported: - spi - arduino_spi - usb_device +vendor: st diff --git a/boards/arm/stm32f746g_disco/doc/index.rst b/boards/arm/stm32f746g_disco/doc/index.rst index 579b19cffc8..c9b77967be9 100644 --- a/boards/arm/stm32f746g_disco/doc/index.rst +++ b/boards/arm/stm32f746g_disco/doc/index.rst @@ -231,13 +231,13 @@ You can debug an application in the usual way. Here is an example for the .. _32F746G-DISCO website: - http://www.st.com/en/evaluation-tools/32f746gdiscovery.html + https://www.st.com/en/evaluation-tools/32f746gdiscovery.html .. _32F746G-DISCO board User Manual: - http://www.st.com/resource/en/user_manual/dm00190424.pdf + https://www.st.com/resource/en/user_manual/dm00190424.pdf .. _STM32F746NGH6 on www.st.com: - http://www.st.com/content/st_com/en/products/microcontrollers/stm32-32-bit-arm-cortex-mcus/stm32-high-performance-mcus/stm32f7-series/stm32f7x6/stm32f746ng.html + https://www.st.com/content/st_com/en/products/microcontrollers/stm32-32-bit-arm-cortex-mcus/stm32-high-performance-mcus/stm32f7-series/stm32f7x6/stm32f746ng.html .. _STM32F74xxx reference manual: - http://www.st.com/resource/en/reference_manual/dm00124865.pdf + https://www.st.com/resource/en/reference_manual/dm00124865.pdf diff --git a/boards/arm/stm32f746g_disco/stm32f746g_disco.dts b/boards/arm/stm32f746g_disco/stm32f746g_disco.dts index f28c5857cbe..e81172d381b 100644 --- a/boards/arm/stm32f746g_disco/stm32f746g_disco.dts +++ b/boards/arm/stm32f746g_disco/stm32f746g_disco.dts @@ -9,6 +9,8 @@ #include #include "arduino_r3_connector.dtsi" #include +#include +#include / { model = "STMicroelectronics STM32F746G DISCOVERY board"; @@ -51,7 +53,7 @@ device_type = "memory"; reg = <0xc0000000 DT_SIZE_M(16)>; zephyr,memory-region = "SDRAM1"; - zephyr,memory-attr = "RAM"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; aliases { diff --git a/boards/arm/stm32f746g_disco/stm32f746g_disco.yaml b/boards/arm/stm32f746g_disco/stm32f746g_disco.yaml index edc6635e0b4..f3ef45a7906 100644 --- a/boards/arm/stm32f746g_disco/stm32f746g_disco.yaml +++ b/boards/arm/stm32f746g_disco/stm32f746g_disco.yaml @@ -20,3 +20,4 @@ supported: - usb_device - display - memc +vendor: st diff --git a/boards/arm/stm32f7508_dk/doc/index.rst b/boards/arm/stm32f7508_dk/doc/index.rst index e20d0ea3236..a3f39f37e5e 100644 --- a/boards/arm/stm32f7508_dk/doc/index.rst +++ b/boards/arm/stm32f7508_dk/doc/index.rst @@ -226,13 +226,13 @@ You can debug an application in the usual way. Here is an example for the .. _32F7508-DK website: - http://www.st.com/en/evaluation-tools/stm32f7508-dk.html + https://www.st.com/en/evaluation-tools/stm32f7508-dk.html .. _32F7508-DK board User Manual: - http://www.st.com/resource/en/user_manual/dm00537062-discovery-kit-for-stm32f7-series-with-stm32f750n8-mcu-stmicroelectronics.pdf + https://www.st.com/resource/en/user_manual/dm00537062-discovery-kit-for-stm32f7-series-with-stm32f750n8-mcu-stmicroelectronics.pdf .. _STM32F750x8 on www.st.com: https://www.st.com/resource/en/datasheet/stm32f750z8.pdf .. _STM32F74xxx reference manual: - http://www.st.com/resource/en/reference_manual/dm00124865.pdf + https://www.st.com/resource/en/reference_manual/dm00124865.pdf diff --git a/boards/arm/stm32f7508_dk/stm32f7508_dk.dts b/boards/arm/stm32f7508_dk/stm32f7508_dk.dts index 3969add4e28..8102e002863 100644 --- a/boards/arm/stm32f7508_dk/stm32f7508_dk.dts +++ b/boards/arm/stm32f7508_dk/stm32f7508_dk.dts @@ -8,6 +8,7 @@ /dts-v1/; #include #include +#include #include "arduino_r3_connector.dtsi" #include @@ -52,7 +53,7 @@ device_type = "memory"; reg = <0xc0000000 DT_SIZE_M(16)>; zephyr,memory-region = "SDRAM1"; - zephyr,memory-attr = "RAM"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; aliases { diff --git a/boards/arm/stm32f7508_dk/stm32f7508_dk.yaml b/boards/arm/stm32f7508_dk/stm32f7508_dk.yaml index fca291ee3d1..b474319510d 100644 --- a/boards/arm/stm32f7508_dk/stm32f7508_dk.yaml +++ b/boards/arm/stm32f7508_dk/stm32f7508_dk.yaml @@ -23,3 +23,4 @@ supported: - usb_device - display - memc +vendor: st diff --git a/boards/arm/stm32f769i_disco/doc/index.rst b/boards/arm/stm32f769i_disco/doc/index.rst index 4346f67fbc1..d2183087b95 100644 --- a/boards/arm/stm32f769i_disco/doc/index.rst +++ b/boards/arm/stm32f769i_disco/doc/index.rst @@ -213,13 +213,13 @@ You can debug an application in the usual way. Here is an example for the .. _32F769I-DISCO website: - http://www.st.com/en/evaluation-tools/32f769idiscovery.html + https://www.st.com/en/evaluation-tools/32f769idiscovery.html .. _32F769I-DISCO board User Manual: - http://www.st.com/resource/en/user_manual/dm00276557.pdf + https://www.st.com/resource/en/user_manual/dm00276557.pdf .. _STM32F769NIH6 on www.st.com: https://www.st.com/content/st_com/en/products/microcontrollers/stm32-32-bit-arm-cortex-mcus/stm32-high-performance-mcus/stm32f7-series/stm32f7x9/stm32f769ni.html .. _STM32F76xxx reference manual: - http://www.st.com/resource/en/reference_manual/dm00224583.pdf + https://www.st.com/resource/en/reference_manual/dm00224583.pdf diff --git a/boards/arm/stm32f769i_disco/stm32f769i_disco.dts b/boards/arm/stm32f769i_disco/stm32f769i_disco.dts index fcd2197aa9d..0548cf06bd8 100644 --- a/boards/arm/stm32f769i_disco/stm32f769i_disco.dts +++ b/boards/arm/stm32f769i_disco/stm32f769i_disco.dts @@ -7,6 +7,7 @@ /dts-v1/; #include #include +#include #include "arduino_r3_connector.dtsi" #include @@ -28,7 +29,7 @@ device_type = "memory"; reg = <0xc0000000 DT_SIZE_M(16)>; zephyr,memory-region = "SDRAM1"; - zephyr,memory-attr = "RAM"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; leds { diff --git a/boards/arm/stm32f769i_disco/stm32f769i_disco.yaml b/boards/arm/stm32f769i_disco/stm32f769i_disco.yaml index 520d6437ef5..69f06949e2a 100644 --- a/boards/arm/stm32f769i_disco/stm32f769i_disco.yaml +++ b/boards/arm/stm32f769i_disco/stm32f769i_disco.yaml @@ -17,3 +17,5 @@ supported: - arduino_gpio - netif:eth - memc + - kscan:touch +vendor: st diff --git a/boards/arm/stm32g0316_disco/doc/index.rst b/boards/arm/stm32g0316_disco/doc/index.rst index 793e3c98aa8..ed68a7b5dd4 100644 --- a/boards/arm/stm32g0316_disco/doc/index.rst +++ b/boards/arm/stm32g0316_disco/doc/index.rst @@ -100,7 +100,7 @@ the following pyocd command: Flashing an application to the STM32G0316-DISCO ----------------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/stm32g0316_disco/stm32g0316_disco.yaml b/boards/arm/stm32g0316_disco/stm32g0316_disco.yaml index 0dc20f26d67..3b6cb215ce4 100644 --- a/boards/arm/stm32g0316_disco/stm32g0316_disco.yaml +++ b/boards/arm/stm32g0316_disco/stm32g0316_disco.yaml @@ -13,3 +13,4 @@ supported: - uart - watchdog - dma +vendor: st diff --git a/boards/arm/stm32g071b_disco/doc/index.rst b/boards/arm/stm32g071b_disco/doc/index.rst index 5f9dd31381c..d7071c3d3d2 100644 --- a/boards/arm/stm32g071b_disco/doc/index.rst +++ b/boards/arm/stm32g071b_disco/doc/index.rst @@ -130,7 +130,7 @@ The STM32G071B Discovery board includes an ST-LINK/V2-1 embedded debug tool inte Flashing an application to the STM32G071B_DISCO ----------------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -160,10 +160,10 @@ References https://www.st.com/en/evaluation-tools/stm32g071b-disco.html .. _STM32G071 reference manual: - http://www.st.com/resource/en/reference_manual/dm00371828.pdf + https://www.st.com/resource/en/reference_manual/dm00371828.pdf .. _STM32G0 Discovery board User Manual: https://www.st.com/resource/en/user_manual/dm00496511.pdf .. _G071RB on www.st.com: - http://www.st.com/en/microcontrollers/stm32g071rb.html + https://www.st.com/en/microcontrollers/stm32g071rb.html diff --git a/boards/arm/stm32g071b_disco/stm32g071b_disco.yaml b/boards/arm/stm32g071b_disco/stm32g071b_disco.yaml index e1830d15f33..817860f27ac 100644 --- a/boards/arm/stm32g071b_disco/stm32g071b_disco.yaml +++ b/boards/arm/stm32g071b_disco/stm32g071b_disco.yaml @@ -14,3 +14,4 @@ supported: - i2c - watchdog - tcpc +vendor: st diff --git a/boards/arm/stm32g081b_eval/doc/index.rst b/boards/arm/stm32g081b_eval/doc/index.rst index 84d9e18c61e..3e2268446c3 100644 --- a/boards/arm/stm32g081b_eval/doc/index.rst +++ b/boards/arm/stm32g081b_eval/doc/index.rst @@ -168,7 +168,7 @@ The STM32G081B Evaluation board includes an ST-LINK/V2-1 embedded debug tool int Flashing an application to the STM32G081B_EVAL ---------------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -204,4 +204,4 @@ References https://www.st.com/resource/en/user_manual/um2403-evaluation-board-with-stm32g081rb-mcu-stmicroelectronics.pdf .. _G081RB on www.st.com: - http://www.st.com/en/microcontrollers/stm32g081rb.html + https://www.st.com/en/microcontrollers/stm32g081rb.html diff --git a/boards/arm/stm32g081b_eval/stm32g081b_eval.yaml b/boards/arm/stm32g081b_eval/stm32g081b_eval.yaml index e22b6e4207c..313faf236a8 100644 --- a/boards/arm/stm32g081b_eval/stm32g081b_eval.yaml +++ b/boards/arm/stm32g081b_eval/stm32g081b_eval.yaml @@ -14,3 +14,4 @@ supported: - gpio - watchdog - tcpc +vendor: st diff --git a/boards/arm/stm32h573i_dk/stm32h573i_dk.yaml b/boards/arm/stm32h573i_dk/stm32h573i_dk.yaml index e7ed5b5d3cb..8eea15d5d02 100644 --- a/boards/arm/stm32h573i_dk/stm32h573i_dk.yaml +++ b/boards/arm/stm32h573i_dk/stm32h573i_dk.yaml @@ -22,3 +22,4 @@ supported: - can - usb_device - usb +vendor: st diff --git a/boards/arm/stm32h735g_disco/Kconfig.defconfig b/boards/arm/stm32h735g_disco/Kconfig.defconfig index 42de4573d83..72308958d7b 100644 --- a/boards/arm/stm32h735g_disco/Kconfig.defconfig +++ b/boards/arm/stm32h735g_disco/Kconfig.defconfig @@ -8,6 +8,13 @@ if BOARD_STM32H735G_DISCO config BOARD default "stm32h735g_disco" +if NETWORKING + +config NET_L2_ETHERNET + default y + +endif # NETWORKING + config SPI_STM32_INTERRUPT default y depends on SPI diff --git a/boards/arm/stm32h735g_disco/stm32h735g_disco.yaml b/boards/arm/stm32h735g_disco/stm32h735g_disco.yaml index 16d056e600d..a679deb18d4 100644 --- a/boards/arm/stm32h735g_disco/stm32h735g_disco.yaml +++ b/boards/arm/stm32h735g_disco/stm32h735g_disco.yaml @@ -15,3 +15,4 @@ supported: - memc - adc - counter +vendor: st diff --git a/boards/arm/stm32h747i_disco/board.cmake b/boards/arm/stm32h747i_disco/board.cmake index b0b8e824858..ac0e473e57d 100644 --- a/boards/arm/stm32h747i_disco/board.cmake +++ b/boards/arm/stm32h747i_disco/board.cmake @@ -1,11 +1,14 @@ # SPDX-License-Identifier: Apache-2.0 if(CONFIG_BOARD_STM32H747I_DISCO_M7) +board_runner_args(jlink "--device=STM32H747ZI_M7") board_runner_args(openocd "--config=${BOARD_DIR}/support/openocd_stm32h747i_disco_m7.cfg") board_runner_args(openocd --target-handle=_CHIPNAME.cpu0) elseif(CONFIG_BOARD_STM32H747I_DISCO_M4) +board_runner_args(jlink "--device=STM32H747ZI_M4") board_runner_args(openocd "--config=${BOARD_DIR}/support/openocd_stm32h747i_disco_m4.cfg") board_runner_args(openocd --target-handle=_CHIPNAME.cpu1) endif() include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/arm/stm32h747i_disco/doc/index.rst b/boards/arm/stm32h747i_disco/doc/index.rst index 2f8d543d446..d020a3ed94e 100644 --- a/boards/arm/stm32h747i_disco/doc/index.rst +++ b/boards/arm/stm32h747i_disco/doc/index.rst @@ -258,7 +258,7 @@ You should see the following message on the console: Similarly, you can build and flash samples on the M4 target. For this, please take care of the resource sharing (UART port used for console for instance). -Here is an example for the :ref:`blinky-sample` application on M4 core. +Here is an example for the :zephyr:code-sample:`blinky` application on M4 core. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -281,13 +281,13 @@ In order to debug a Zephyr application on Cortex M4 side, you can use `STM32CubeIDE`_. .. _STM32H747I-DISCO website: - http://www.st.com/en/evaluation-tools/stm32h747i-disco.html + https://www.st.com/en/evaluation-tools/stm32h747i-disco.html .. _STM32H747XI on www.st.com: https://www.st.com/content/st_com/en/products/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus/stm32-high-performance-mcus/stm32h7-series/stm32h747-757/stm32h747xi.html .. _STM32H747xx reference manual: - http://www.st.com/resource/en/reference_manual/dm00176879.pdf + https://www.st.com/resource/en/reference_manual/dm00176879.pdf .. _STM32H747xx datasheet: https://www.st.com/resource/en/datasheet/stm32h747xi.pdf diff --git a/boards/arm/stm32h747i_disco/stm32h747i_disco_m4.yaml b/boards/arm/stm32h747i_disco/stm32h747i_disco_m4.yaml index 5038a8e5aca..e167c87f64d 100644 --- a/boards/arm/stm32h747i_disco/stm32h747i_disco_m4.yaml +++ b/boards/arm/stm32h747i_disco/stm32h747i_disco_m4.yaml @@ -16,3 +16,4 @@ testing: - mpu - nfc - net +vendor: st diff --git a/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.dts b/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.dts index 918c61b9978..514047c8a55 100644 --- a/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.dts +++ b/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.dts @@ -7,6 +7,7 @@ /dts-v1/; #include #include +#include #include "stm32h747i_disco.dtsi" / { @@ -27,7 +28,7 @@ device_type = "memory"; reg = <0xd0000000 DT_SIZE_M(32)>; zephyr,memory-region = "SDRAM2"; - zephyr,memory-attr = "RAM"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; leds { @@ -77,6 +78,16 @@ status = "okay"; }; +&pll2 { + div-m = <5>; + mul-n = <96>; + div-p = <2>; + div-q = <4>; + div-r = <10>; + clocks = <&clk_hse>; /* Assuming 25MHz HSE */ + status = "okay"; +}; + &rcc { clocks = <&pll>; clock-frequency = ; @@ -201,8 +212,12 @@ zephyr_udc0: &usbotg_hs { &sdmmc1 { status = "okay"; + clocks = <&rcc STM32_CLOCK_BUS_AHB3 0x00010000>, + <&rcc STM32_SRC_PLL2_R SDMMC_SEL(1)>; pinctrl-0 = <&sdmmc1_d0_pc8 &sdmmc1_d1_pc9 &sdmmc1_d2_pc10 &sdmmc1_d3_pc11 + &sdmmc1_d4_pb8 &sdmmc1_d5_pb9 + &sdmmc1_d6_pc6 &sdmmc1_d7_pc7 &sdmmc1_ck_pc12 &sdmmc1_cmd_pd2>; pinctrl-names = "default"; cd-gpios = <&gpioi 8 GPIO_ACTIVE_LOW>; diff --git a/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.yaml b/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.yaml index fb67ae1e398..52e516cda95 100644 --- a/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.yaml +++ b/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.yaml @@ -18,3 +18,4 @@ supported: - memc - usb_cdc - usb_device +vendor: st diff --git a/boards/arm/stm32h7b3i_dk/stm32h7b3i_dk.dts b/boards/arm/stm32h7b3i_dk/stm32h7b3i_dk.dts index 4183c4912bd..35470174123 100644 --- a/boards/arm/stm32h7b3i_dk/stm32h7b3i_dk.dts +++ b/boards/arm/stm32h7b3i_dk/stm32h7b3i_dk.dts @@ -7,6 +7,7 @@ /dts-v1/; #include #include +#include #include "arduino_r3_connector.dtsi" #include @@ -54,7 +55,7 @@ device_type = "memory"; reg = <0xd0000000 DT_SIZE_M(16)>; zephyr,memory-region = "SDRAM2"; - zephyr,memory-attr = "RAM"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; transceiver0: can-phy0 { @@ -258,13 +259,6 @@ spi-bus-width = ; data-rate = ; status = "okay"; - sfdp-bfp = [ - 53 46 44 50 06 01 02 ff - 00 06 01 10 30 00 00 ff - C2 00 01 04 10 01 00 ff - 84 00 01 02 C0 00 00 ff - 00 00 00 00 - ]; partitions { compatible = "fixed-partitions"; diff --git a/boards/arm/stm32h7b3i_dk/stm32h7b3i_dk.yaml b/boards/arm/stm32h7b3i_dk/stm32h7b3i_dk.yaml index d3c2894fb74..3779381d564 100644 --- a/boards/arm/stm32h7b3i_dk/stm32h7b3i_dk.yaml +++ b/boards/arm/stm32h7b3i_dk/stm32h7b3i_dk.yaml @@ -17,3 +17,4 @@ supported: - backup_sram - display - can +vendor: st diff --git a/boards/arm/stm32l1_disco/doc/index.rst b/boards/arm/stm32l1_disco/doc/index.rst index 87064ada200..65bb4bc028f 100644 --- a/boards/arm/stm32l1_disco/doc/index.rst +++ b/boards/arm/stm32l1_disco/doc/index.rst @@ -143,7 +143,7 @@ This interface is supported by the openocd version included in the Zephyr SDK. Flashing an application ----------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -156,7 +156,7 @@ Debugging ========= You can debug an application in the usual way. Here is an example for the -:ref:`blinky-sample` application. +:zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/stm32l1_disco/stm32l1_disco.yaml b/boards/arm/stm32l1_disco/stm32l1_disco.yaml index 6ef79ef4341..75fa0045fa4 100644 --- a/boards/arm/stm32l1_disco/stm32l1_disco.yaml +++ b/boards/arm/stm32l1_disco/stm32l1_disco.yaml @@ -12,3 +12,4 @@ supported: - gpio - i2c - spi +vendor: st diff --git a/boards/arm/stm32l476g_disco/doc/index.rst b/boards/arm/stm32l476g_disco/doc/index.rst index 61f2e5b59a4..bd4b2a5a6d5 100644 --- a/boards/arm/stm32l476g_disco/doc/index.rst +++ b/boards/arm/stm32l476g_disco/doc/index.rst @@ -206,13 +206,13 @@ You can debug an application in the usual way. Here is an example for the :goals: debug .. _STM32L476G Discovery website: - http://www.st.com/en/evaluation-tools/32l476gdiscovery.html + https://www.st.com/en/evaluation-tools/32l476gdiscovery.html .. _STM32L476G Discovery board User Manual: - http://www.st.com/resource/en/user_manual/dm00172179.pdf + https://www.st.com/resource/en/user_manual/dm00172179.pdf .. _STM32L476VG on www.st.com: - http://www.st.com/en/microcontrollers/stm32l476vg.html + https://www.st.com/en/microcontrollers/stm32l476vg.html .. _STM32L476 reference manual: - http://www.st.com/resource/en/reference_manual/DM00083560.pdf + https://www.st.com/resource/en/reference_manual/DM00083560.pdf diff --git a/boards/arm/stm32l476g_disco/stm32l476g_disco.yaml b/boards/arm/stm32l476g_disco/stm32l476g_disco.yaml index 50de851c41a..671e1738519 100644 --- a/boards/arm/stm32l476g_disco/stm32l476g_disco.yaml +++ b/boards/arm/stm32l476g_disco/stm32l476g_disco.yaml @@ -11,3 +11,4 @@ flash: 1024 supported: - gpio - counter +vendor: st diff --git a/boards/arm/stm32l496g_disco/doc/index.rst b/boards/arm/stm32l496g_disco/doc/index.rst index 681969f08af..0bd31e72c38 100644 --- a/boards/arm/stm32l496g_disco/doc/index.rst +++ b/boards/arm/stm32l496g_disco/doc/index.rst @@ -247,13 +247,13 @@ You can debug an application in the usual way. Here is an example for the :goals: debug .. _STM32L496G Discovery website: - http://www.st.com/en/evaluation-tools/32l496gdiscovery.html + https://www.st.com/en/evaluation-tools/32l496gdiscovery.html .. _STM32L496G Discovery board User Manual: - http://www.st.com/resource/en/user_manual/dm00353127.pdf + https://www.st.com/resource/en/user_manual/dm00353127.pdf .. _STM32L496AG on www.st.com: - http://www.st.com/en/microcontrollers/stm32l496ag.html + https://www.st.com/en/microcontrollers/stm32l496ag.html .. _STM32L496 reference manual: - http://www.st.com/resource/en/reference_manual/DM00083560.pdf + https://www.st.com/resource/en/reference_manual/DM00083560.pdf diff --git a/boards/arm/stm32l496g_disco/stm32l496g_disco.yaml b/boards/arm/stm32l496g_disco/stm32l496g_disco.yaml index edf64edc3a4..3544d15980c 100644 --- a/boards/arm/stm32l496g_disco/stm32l496g_disco.yaml +++ b/boards/arm/stm32l496g_disco/stm32l496g_disco.yaml @@ -18,3 +18,4 @@ supported: - sdhc - adc - qspi +vendor: st diff --git a/boards/arm/stm32l4r9i_disco/Kconfig.board b/boards/arm/stm32l4r9i_disco/Kconfig.board new file mode 100644 index 00000000000..57da0f65fdf --- /dev/null +++ b/boards/arm/stm32l4r9i_disco/Kconfig.board @@ -0,0 +1,8 @@ +# STM32L4R9I Discovery board configuration + +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_STM32L4R9I_DISCO + bool "STM32L4R9I Discovery Development Board" + depends on SOC_STM32L4R9XX diff --git a/boards/arm/stm32l4r9i_disco/Kconfig.defconfig b/boards/arm/stm32l4r9i_disco/Kconfig.defconfig new file mode 100644 index 00000000000..82eafa62744 --- /dev/null +++ b/boards/arm/stm32l4r9i_disco/Kconfig.defconfig @@ -0,0 +1,11 @@ +# STM32L4R9I Discovery board configuration + +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_STM32L4R9I_DISCO + +config BOARD + default "stm32l4r9i_disco" + +endif # BOARD_STM32L4R9I_DISCO diff --git a/boards/arm/stm32l4r9i_disco/arduino_r3_connector.dtsi b/boards/arm/stm32l4r9i_disco/arduino_r3_connector.dtsi new file mode 100644 index 00000000000..29b56539b70 --- /dev/null +++ b/boards/arm/stm32l4r9i_disco/arduino_r3_connector.dtsi @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + arduino_header: connector { + compatible = "arduino-header-r3"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpioa 7 0>, /* A0 */ + <1 0 &gpioc 4 0>, /* A1 */ + <2 0 &gpioc 3 0>, /* A2 */ + <3 0 &gpiob 0 0>, /* A3 */ + <4 0 &gpioa 0 0>, /* A4 */ + <5 0 &gpioa 5 0>, /* A5 */ + <6 0 &gpioc 0 0>, /* D0 */ + <7 0 &gpioc 1 0>, /* D1 */ + <8 0 &gpiog 11 0>, /* D2 */ + <9 0 &gpiof 10 0>, /* D3 */ + <10 0 &gpiog 6 0>, /* D4 */ + <11 0 &gpioa 1 0>, /* D5 */ + <12 0 &gpiob 4 0>, /* D6 */ + <13 0 &gpioa 4 0>, /* D7 */ + <14 0 &gpioh 15 0>, /* D8 */ + <15 0 &gpioh 13 0>, /* D9 */ + <16 0 &gpioi 0 0>, /* D10 */ + <17 0 &gpiob 15 0>, /* D11 */ + <18 0 &gpiob 14 0>, /* D12 */ + <19 0 &gpiob 13 0>, /* D13 */ + <20 0 &gpiog 8 0>, /* D14 */ + <21 0 &gpiog 7 0>; /* D15 */ + }; +}; + +arduino_i2c: &i2c3 {}; +arduino_spi: &spi2 {}; diff --git a/boards/arm/stm32l4r9i_disco/board.cmake b/boards/arm/stm32l4r9i_disco/board.cmake new file mode 100644 index 00000000000..c88ae7d0783 --- /dev/null +++ b/boards/arm/stm32l4r9i_disco/board.cmake @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(jlink "--device=STM32L4R9AI" "--speed=4000") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/arm/stm32l4r9i_disco/doc/img/stm32l4r9i_disco.jpg b/boards/arm/stm32l4r9i_disco/doc/img/stm32l4r9i_disco.jpg new file mode 100644 index 00000000000..06914737b5b Binary files /dev/null and b/boards/arm/stm32l4r9i_disco/doc/img/stm32l4r9i_disco.jpg differ diff --git a/boards/arm/stm32l4r9i_disco/doc/index.rst b/boards/arm/stm32l4r9i_disco/doc/index.rst new file mode 100644 index 00000000000..a8f7798f840 --- /dev/null +++ b/boards/arm/stm32l4r9i_disco/doc/index.rst @@ -0,0 +1,150 @@ +.. _stm32l4r9i_disco_board: + +ST STM32L4R9I Discovery +####################### + +Overview +******** + +The 32L4R9IDISCOVERY Discovery kit is a complete demonstration and development platform +for STMicroelectronics Arm® Cortex®-M4 core-based STM32L4R9AI microcontroller. + +Leveraging the innovative ultra-low-power oriented features, 640 Kbytes of embedded RAM, +graphics performance (Chrom-ART Accelerator), and DSI controller offered by the STM32L4R9AI, +the 32L4R9IDISCOVERY Discovery kit enables users to easily prototype applications with +state-of-the-art energy efficiency, as well as stunning audio and graphics rendering with direct +support for AMOLED DSI round LCD display. + +For even more user-friendliness, the on-board ST-LINK/V2-1 debugger provides out-of-the-box +programming and debugging capabilities. + +.. image:: img/stm32l4r9i_disco.jpg + :align: center + :alt: STM32L4R9I-DISCO + +More information about the board can be found at the `STM32L4R9I-DISCOVERY website`_. +More information about STM32L4R9 can be found here: + +- `STM32L4R9/S9 on www.st.com`_ +- `STM32L4+ Series reference manual`_ +- `STM32L4R5xx/R7xx/R9xx datasheet`_ + +Supported Features +================== + +The current Zephyr stm32l4r9i_disco board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling | ++-----------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | on-chip flash memory; | +| | | external OctoSPI memory | ++-----------+------------+-------------------------------------+ +| ADC | on-chip | ADC Controller | ++-----------+------------+-------------------------------------+ +| RTC | on-chip | Real Time Clock | ++-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c | ++-----------+------------+-------------------------------------+ +| SPI | on-chip | spi | ++-----------+------------+-------------------------------------+ +| PWM | on-chip | pwm | ++-----------+------------+-------------------------------------+ +| SDMMC | on-chip | sd/mmc | ++-----------+------------+-------------------------------------+ + +Other hardware features are not yet supported on Zephyr porting. + +The default configuration can be found in the defconfig file: + + ``boards/arm/stm32l4r9i_disco/stm32l4r9i_disco_defconfig`` + + +Pin Mapping +=========== + +For mode details, please refer to `STM32L4R9I-DISCOVERY website`_. + +System Clock +============ + +The STM32L4R9AI System Clock can be driven by an internal or external oscillator, +as well as by the main PLL clock. By default, the System clock is driven by +the PLL clock at 120MHz. PLL clock is driven by a 4MHz medium speed internal clock. + +Serial Port +=========== + +The STM32L4R9I Discovery board has up to 6 U(S)ARTs. +The Zephyr console output is assigned to UART2, which is connected to the onboard +ST-LINK Virtual COM port interface. Default communication settings are 115200 8N1. + + +Programming and Debugging +************************* + +Flashing +======== + +The STM32L4R9I Discovery board includes an ST-LINK/V2-1 debug tool. + +Applications for the ``stm32l4r9i_disco`` board configuration can be +built and flashed in the usual way (see :ref:`build_an_application` +and :ref:`application_run` for more details). + + +Flashing an application to STM32L4R9I Discovery +----------------------------------------------- + +Connect the STM32L4R9I Discovery to your host computer using the ST-LINK +USB port, then run a serial host program to connect with the board. For example: + +.. code-block:: console + + $ minicom -b 115200 -D /dev/ttyACM0 + +You can then build and flash applications in the usual way. +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: stm32l4r9i_disco + :goals: build flash + +You should see the following message in the serial host program: + +.. code-block:: console + + $ Hello World! stm32l4r9i_disco + + +Debugging +========= + +You can debug an application in the usual way. Here is an example for the +:ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: stm32l4r9i_disco + :goals: debug + +.. _STM32L4R9I-DISCOVERY website: + https://www.st.com/en/evaluation-tools/32l4r9idiscovery.html + +.. _STM32L4R9/S9 on www.st.com: + https://www.st.com/en/microcontrollers-microprocessors/stm32l4r9-s9.html + +.. _STM32L4+ Series reference manual: + https://www.st.com/resource/en/reference_manual/rm0432-stm32l4-series-advanced-armbased-32bit-mcus-stmicroelectronics.pdf + +.. _STM32L4R5xx/R7xx/R9xx datasheet: + https://www.st.com/resource/en/datasheet/stm32l4r5vi.pdf diff --git a/boards/arm/stm32l4r9i_disco/stm32l4r9i_disco.dts b/boards/arm/stm32l4r9i_disco/stm32l4r9i_disco.dts new file mode 100644 index 00000000000..8a4833e8c97 --- /dev/null +++ b/boards/arm/stm32l4r9i_disco/stm32l4r9i_disco.dts @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +/dts-v1/; +#include +#include +#include +#include "arduino_r3_connector.dtsi" + +/ { + model = "STMicroelectronics STM32L4R9I-DISCO board"; + compatible = "st,stm32l4r9i-disco"; + + chosen { + zephyr,console = &usart2; + zephyr,shell-uart = &usart2; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + leds { + compatible = "gpio-leds"; + /* N.B. LD1 (orange) is not wired to MCU */ + green_led: led_2 { + gpios = <&gpioh 4 GPIO_ACTIVE_LOW>; + label = "User LD2"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + joy_sel: joystick_selection { + label = "joystick selection"; + gpios = <&gpioc 13 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; + zephyr,code = ; + }; + }; + + aliases { + led0 = &green_led; + sw0 = &joy_sel; + die-temp0 = &die_temp; + volt-sensor0 = &vref; + volt-sensor1 = &vbat; + spi-flash0 = &mx25lm51245; + }; +}; + +&clk_lse { + status = "okay"; +}; + +&clk_lsi { + status = "okay"; +}; + +&clk_hsi48 { + status = "okay"; +}; + +&clk_hsi { + status = "okay"; +}; + +&clk_msi { + status = "okay"; + msi-range = <6>; + msi-pll-mode; +}; + +&pll { + status = "okay"; + div-m = <1>; + mul-n = <60>; + /* + * WORKAROUND: stm32l4-pll-clock does not allow arbitrary PLLP dividers. + * Disable PLLP completely since it only feeds SAI, which is not active either. + */ + /* div-p = <5>; */ + div-q = <2>; + div-r = <2>; + clocks = <&clk_msi>; +}; + +&rcc { + clocks = <&pll>; + ahb-prescaler = <1>; + clock-frequency = ; + apb1-prescaler = <1>; + apb2-prescaler = <1>; +}; + +&usart2 { + status = "okay"; + pinctrl-0 = <&usart2_tx_pa2 &usart2_rx_pa3>; + pinctrl-names = "default"; + current-speed = <115200>; +}; + +&lpuart1 { + status = "okay"; + pinctrl-0 = <&lpuart1_tx_pc1 &lpuart1_rx_pc0>; + pinctrl-names = "default"; + current-speed = <115200>; +}; + +&timers3 { + status = "okay"; + + pwm3: pwm { + status = "okay"; + /* + * N.B.: Datasheet indicates that ARD_D11 (wired to PB15) is connected to TIM3_CH2. + * However, this is incorrect as PB15 cannot be muxed to TIM3 (see DS12023). + * Moved ARD_D11 to TIM15_CH2 instead. + */ + pinctrl-0 = <&tim3_ch1_pb4>; + pinctrl-names = "default"; + }; +}; + +&timers5 { + status = "okay"; + + pwm5: pwm { + status = "okay"; + pinctrl-0 = <&tim5_ch2_pa1 &tim5_ch4_pi0>; + pinctrl-names = "default"; + }; +}; + +&timers8 { + status = "okay"; + + pwm8: pwm { + status = "okay"; + pinctrl-0 = <&tim8_ch1n_ph13>; + pinctrl-names = "default"; + }; +}; + +&timers15 { + status = "okay"; + + pwm15: pwm { + status = "okay"; + pinctrl-0 = <&tim15_ch2_pf10 &tim15_ch2_pb15>; + pinctrl-names = "default"; + }; +}; + +&i2c1 { + status = "okay"; + pinctrl-0 = <&i2c1_scl_pb6 &i2c1_sda_pg13>; + pinctrl-names = "default"; + clock-frequency = ; +}; + +&i2c3 { + status = "okay"; + pinctrl-0 = <&i2c3_scl_pg7 &i2c3_sda_pg8>; + pinctrl-names = "default"; + clock-frequency = ; +}; + +&spi2 { + status = "okay"; + pinctrl-0 = <&spi2_sck_pb13 &spi2_miso_pb14 &spi2_mosi_pb15>; + pinctrl-names = "default"; + cs-gpios = <&gpioi 0 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; +}; + +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; + status = "okay"; +}; + +&sdmmc1 { + status = "okay"; + pinctrl-0 = <&sdmmc1_d0_pc8 &sdmmc1_d1_pc9 + &sdmmc1_d2_pc10 &sdmmc1_d3_pc11 + &sdmmc1_ck_pc12 &sdmmc1_cmd_pd2>; + pinctrl-names = "default"; +}; + +&adc1 { + status = "okay"; + pinctrl-0 = <&adc1_in5_pa0 &adc1_in12_pa7 &adc1_in15_pb0 + &adc1_in4_pc3 &adc1_in13_pc4>; + pinctrl-names = "default"; + st,adc-clock-source = ; + st,adc-prescaler = <1>; +}; + +zephyr_udc0: &usbotg_fs { + status = "okay"; + pinctrl-0 = <&usb_otg_fs_dm_pa11 &usb_otg_fs_dp_pa12 + &usb_otg_fs_id_pa10>; + pinctrl-names = "default"; +}; + +&die_temp { + status = "okay"; +}; + +&vref { + status = "okay"; +}; + +&vbat { + status = "okay"; +}; + +&octospi2 { + status = "okay"; + pinctrl-0 = <&octospim_p2_clk_pi6 &octospim_p2_ncs_pg12 + &octospim_p2_io0_pi11 &octospim_p2_io1_pi10 + &octospim_p2_io2_pi9 &octospim_p2_io3_ph8 + &octospim_p2_io4_ph9 &octospim_p2_io5_ph10 + &octospim_p2_io6_pg9 &octospim_p2_io7_pg10 + &octospim_p2_dqs_pg15>; + pinctrl-names = "default"; + + mx25lm51245: ospi-nor-flash@0 { + status = "okay"; + compatible = "st,stm32-ospi-nor"; + reg = <0>; + ospi-max-frequency = ; + size = ; /* 512 Mbits = 64 MBytes */ + spi-bus-width = ; + data-rate = ; + four-byte-opcodes; + sfdp-bfp = [ + 53 46 44 50 06 01 02 ff + 00 06 01 10 30 00 00 ff + c2 00 01 04 10 01 00 ff + 84 00 01 02 c0 00 00 ff + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + e5 20 fb ff ff ff ff 1f + 44 eb 08 6b 08 3b 04 bb + fe ff ff ff ff ff 00 ff + ff ff 44 eb 0c 20 0f 52 + 10 d8 00 ff d6 49 c5 00 + 81 df 04 e3 44 03 67 38 + 30 b0 30 b0 f7 bd d5 5c + 4a 9e 29 ff f0 50 f9 85 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 7f ef ff ff 21 5c dc ff + ]; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x00000000 DT_SIZE_M(64)>; + }; + }; + }; +}; diff --git a/boards/arm/stm32l4r9i_disco/stm32l4r9i_disco.yaml b/boards/arm/stm32l4r9i_disco/stm32l4r9i_disco.yaml new file mode 100644 index 00000000000..89ab98c92b1 --- /dev/null +++ b/boards/arm/stm32l4r9i_disco/stm32l4r9i_disco.yaml @@ -0,0 +1,25 @@ +identifier: stm32l4r9i_disco +name: ST STM32L4R9I Discovery +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +ram: 640 +flash: 2048 +vendor: st +supported: + - adc + - arduino_gpio + - arduino_i2c + - arduino_spi + - gpio + - i2c + - pwm + - rtc + - sdhc + - spi + - uart + - usb + - usb_device diff --git a/boards/arm/stm32l4r9i_disco/stm32l4r9i_disco_defconfig b/boards/arm/stm32l4r9i_disco/stm32l4r9i_disco_defconfig new file mode 100644 index 00000000000..546bd3379a8 --- /dev/null +++ b/boards/arm/stm32l4r9i_disco/stm32l4r9i_disco_defconfig @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_STM32L4X=y +CONFIG_SOC_STM32L4R9XX=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable HW stack protection +CONFIG_HW_STACK_PROTECTION=y + +# Enable UART +CONFIG_SERIAL=y + +# Enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable GPIO +CONFIG_GPIO=y + +# Enable clocks +CONFIG_CLOCK_CONTROL=y + +# Enable pin controller +CONFIG_PINCTRL=y diff --git a/boards/arm/stm32l4r9i_disco/support/openocd.cfg b/boards/arm/stm32l4r9i_disco/support/openocd.cfg new file mode 100644 index 00000000000..295299f2fbe --- /dev/null +++ b/boards/arm/stm32l4r9i_disco/support/openocd.cfg @@ -0,0 +1,12 @@ +source [find board/stm32l4discovery.cfg] + +$_TARGETNAME configure -event gdb-attach { + echo "Debugger attaching: halting execution" + reset halt + gdb_breakpoint_override hard +} + +$_TARGETNAME configure -event gdb-detach { + echo "Debugger detaching: resuming execution" + resume +} diff --git a/boards/arm/stm32l562e_dk/Kconfig.defconfig b/boards/arm/stm32l562e_dk/Kconfig.defconfig index 1fe37f3e0a4..bec20b338f5 100644 --- a/boards/arm/stm32l562e_dk/Kconfig.defconfig +++ b/boards/arm/stm32l562e_dk/Kconfig.defconfig @@ -8,10 +8,6 @@ if BOARD_STM32L562E_DK config BOARD default "stm32l562e_dk" -# LPTIM clocked by LSE, force tick freq to 4096 for tick accuracy -config SYS_CLOCK_TICKS_PER_SEC - default 4096 if STM32_LPTIM_TIMER - if BT config SPI diff --git a/boards/arm/stm32l562e_dk/doc/index.rst b/boards/arm/stm32l562e_dk/doc/index.rst index e26887732ac..5a4f5845617 100644 --- a/boards/arm/stm32l562e_dk/doc/index.rst +++ b/boards/arm/stm32l562e_dk/doc/index.rst @@ -381,7 +381,7 @@ You can debug an application in the usual way. Here is an example for the https://www.st.com/en/microcontrollers/stm32l562qe.html .. _STM32L562 reference manual: - http://www.st.com/resource/en/reference_manual/DM00346336.pdf + https://www.st.com/resource/en/reference_manual/DM00346336.pdf .. _STM32CubeProgrammer: https://www.st.com/en/development-tools/stm32cubeprog.html diff --git a/boards/arm/stm32l562e_dk/stm32l562e_dk.yaml b/boards/arm/stm32l562e_dk/stm32l562e_dk.yaml index a6759c10c25..dcbe7539d64 100644 --- a/boards/arm/stm32l562e_dk/stm32l562e_dk.yaml +++ b/boards/arm/stm32l562e_dk/stm32l562e_dk.yaml @@ -15,6 +15,7 @@ supported: - dac - adc - spi + - ble - dma - usart - arduino_spi @@ -24,3 +25,4 @@ supported: - nvs ram: 192 flash: 512 +vendor: st diff --git a/boards/arm/stm32l562e_dk/stm32l562e_dk_common.dtsi b/boards/arm/stm32l562e_dk/stm32l562e_dk_common.dtsi index 14f11ece9a9..5bb8c567ee6 100644 --- a/boards/arm/stm32l562e_dk/stm32l562e_dk_common.dtsi +++ b/boards/arm/stm32l562e_dk/stm32l562e_dk_common.dtsi @@ -111,7 +111,7 @@ &spi1 { pinctrl-0 = <&spi1_sck_pg2 &spi1_miso_pg3 &spi1_mosi_pg4>; pinctrl-names = "default"; - cs-gpios = <&gpiog 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; + cs-gpios = <&gpiog 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; status = "okay"; spbtle-rf@0 { @@ -120,6 +120,8 @@ irq-gpios = <&gpiog 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; reset-gpios = <&gpiog 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; spi-max-frequency = <2000000>; + controller-data-delay-us = <0>; /* No need for extra delay for BlueNRG-MS */ + spi-hold-cs; }; }; diff --git a/boards/arm/stm32l562e_dk/stm32l562e_dk_defconfig b/boards/arm/stm32l562e_dk/stm32l562e_dk_defconfig index 6646832e7ef..c5537972912 100644 --- a/boards/arm/stm32l562e_dk/stm32l562e_dk_defconfig +++ b/boards/arm/stm32l562e_dk/stm32l562e_dk_defconfig @@ -24,3 +24,6 @@ CONFIG_HW_STACK_PROTECTION=y # enable pin controller CONFIG_PINCTRL=y + +# LSE defined as LPTIM clock source by the DTS +CONFIG_STM32_LPTIM_CLOCK_LSE=y diff --git a/boards/arm/stm32l562e_dk/stm32l562e_dk_ns.yaml b/boards/arm/stm32l562e_dk/stm32l562e_dk_ns.yaml index 43038b862b0..8d743536e74 100644 --- a/boards/arm/stm32l562e_dk/stm32l562e_dk_ns.yaml +++ b/boards/arm/stm32l562e_dk/stm32l562e_dk_ns.yaml @@ -18,3 +18,4 @@ supported: - usb_device ram: 192 flash: 512 +vendor: st diff --git a/boards/arm/stm32l562e_dk/stm32l562e_dk_ns_defconfig b/boards/arm/stm32l562e_dk/stm32l562e_dk_ns_defconfig index c28424d306a..289f8d82131 100644 --- a/boards/arm/stm32l562e_dk/stm32l562e_dk_ns_defconfig +++ b/boards/arm/stm32l562e_dk/stm32l562e_dk_ns_defconfig @@ -25,3 +25,6 @@ CONFIG_TRUSTED_EXECUTION_NONSECURE=y # enable pin controller CONFIG_PINCTRL=y + +# LSE defined as LPTIM clock source by the DTS +CONFIG_STM32_LPTIM_CLOCK_LSE=y diff --git a/boards/arm/stm32mp157c_dk2/stm32mp157c_dk2.yaml b/boards/arm/stm32mp157c_dk2/stm32mp157c_dk2.yaml index a78e1d2fb9f..d552a6d6aa0 100644 --- a/boards/arm/stm32mp157c_dk2/stm32mp157c_dk2.yaml +++ b/boards/arm/stm32mp157c_dk2/stm32mp157c_dk2.yaml @@ -26,3 +26,4 @@ testing: - nfc ram: 256 flash: 64 +vendor: st diff --git a/boards/arm/stm32u5a9j_dk/Kconfig.board b/boards/arm/stm32u5a9j_dk/Kconfig.board new file mode 100644 index 00000000000..8482aa58f04 --- /dev/null +++ b/boards/arm/stm32u5a9j_dk/Kconfig.board @@ -0,0 +1,8 @@ +# STM32U5A9J Discovery Kit board configuration + +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_STM32U5A9J_DK + bool "STM32U5A9J Discovery Kit Development Board" + depends on SOC_STM32U5A9XX diff --git a/boards/arm/stm32u5a9j_dk/Kconfig.defconfig b/boards/arm/stm32u5a9j_dk/Kconfig.defconfig new file mode 100644 index 00000000000..8124e022740 --- /dev/null +++ b/boards/arm/stm32u5a9j_dk/Kconfig.defconfig @@ -0,0 +1,11 @@ +# STM32U5A9J DISCOVERY KIT board configuration + +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_STM32U5A9J_DK + +config BOARD + default "stm32u5a9j_dk" + +endif # BOARD_STM32U5A9J_DK diff --git a/boards/arm/stm32u5a9j_dk/board.cmake b/boards/arm/stm32u5a9j_dk/board.cmake new file mode 100644 index 00000000000..dadc06c643e --- /dev/null +++ b/boards/arm/stm32u5a9j_dk/board.cmake @@ -0,0 +1,11 @@ +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(stm32cubeprogrammer "--erase" "--port=swd" "--reset-mode=hw") + +board_runner_args(openocd "--tcl-port=6666") +board_runner_args(openocd --cmd-pre-init "gdb_report_data_abort enable") +board_runner_args(openocd "--no-halt") + +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/arm/stm32u5a9j_dk/doc/img/bottom_view.jpg b/boards/arm/stm32u5a9j_dk/doc/img/bottom_view.jpg new file mode 100644 index 00000000000..4d1c1dca173 Binary files /dev/null and b/boards/arm/stm32u5a9j_dk/doc/img/bottom_view.jpg differ diff --git a/boards/arm/stm32u5a9j_dk/doc/img/top_view.jpg b/boards/arm/stm32u5a9j_dk/doc/img/top_view.jpg new file mode 100644 index 00000000000..5d3c4035061 Binary files /dev/null and b/boards/arm/stm32u5a9j_dk/doc/img/top_view.jpg differ diff --git a/boards/arm/stm32u5a9j_dk/doc/index.rst b/boards/arm/stm32u5a9j_dk/doc/index.rst new file mode 100644 index 00000000000..6e3e44c5942 --- /dev/null +++ b/boards/arm/stm32u5a9j_dk/doc/index.rst @@ -0,0 +1,198 @@ +.. _stm32u5a9j_dk_board: + +ST STM32U5A9J Discovery Kit +########################### + +Overview +******** + +The STM32U5A9J-DK Discovery kit is a complete demonstration and development +platform for the STM32U5A9NJH6Q microcontroller, featuring an Arm® Cortex®-M33 +core with Arm® TrustZone®. + +Leveraging the innovative ultra-low-power oriented features, 2.5 Mbytes of +embedded SRAM, 4 Mbytes of embedded flash memory, and rich graphics features, +the STM32U5A9J-DK Discovery kit enables users to easily prototype applications +with state-of-the-art energy efficiency, as well as providing stunning and +optimized graphics rendering with the support of the 2.5D NeoChrom Accelerator, +Chrom-ART Accelerator, and Chrom-GRC™ MMU. + +The full range of hardware features available on the board helps users to +enhance their application development by an evaluation of all the peripherals +such as a 2.47-inch RGB 480x480 pixels TFT round LCD module with MIPI DSI® +interface and capacitive touch panel, USB Type-C® HS, Octo-SPI flash memory +device, Hexadeca-SPI PSRAM memory device, eMMC flash memory device, +Time-of-Flight and gesture detection sensor, temperature sensor, and two 2.54 mm +pitch double-row flexible expansion connectors for easy prototyping with +daughterboards for specific applications (USART, LPUART, two SPIs, SAI, three +I2C, SDMMC, ADCs, timers, and GPIOs). + +The STM32U5A9J-DK Discovery kit integrates an STLINK-V3E embedded in-circuit +debugger and programmer for the STM32 microcontroller with a USB Virtual COM +port bridge and comes with the STM32CubeU5 MCU Package, which provides an STM32 +comprehensive software HAL library as well as various software examples. + +.. image:: img/top_view.jpg + :align: center + :alt: STM32U5A9J-DK Top View + +.. image:: img/bottom_view.jpg + :align: center + :alt: STM32U5A9J-DK Bottom View + +More information about the board can be found at the `STM32U5A9J-DK website`_. +More information about STM32U5A9NJH6Q can be found here: + +- `STM32U5A9NJ on www.st.com`_ +- `STM32U5 Series reference manual`_ +- `STM32U5Axxx datasheet`_ + +Supported Features +================== + +The current Zephyr stm32u5a9j_dk board configuration supports the following +hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ +| LPUART | on-chip | low power uart | ++-----------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| RNG | on-chip | True Random number generator | ++-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c | ++-----------+------------+-------------------------------------+ +| SPI | on-chip | spi | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| ADC | on-chip | adc | ++-----------+------------+-------------------------------------+ +| SDMMC | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| WATCHDOG | on-chip | independent watchdog | ++-----------+------------+-------------------------------------+ +| PWM | on-chip | pwm | ++-----------+------------+-------------------------------------+ + +Other hardware features have not been enabled yet for this board. + +The default configuration per core can be found in the defconfig file: +``boards/arm/stm32u5a9j_dk/stm32u5a9j_dk_defconfig`` + +Pin Mapping +=========== + +For mode details please refer to `STM32U5A9J-DK board User Manual`_. + +Default Zephyr Peripheral Mapping: +---------------------------------- + +- USART_1 TX/RX : PA9/PA10 (ST-Link Virtual Port Com) +- LD3 : PE0 +- LD4 : PE1 +- User Button: PC13 +- USART_3 TX/RX : PB10/PB11 +- LPUART_1 TX/RX : PG7/PG8 +- I2C1 SCL/SDA : PG14/PG13 +- I2C2 SCL/SDA : PF1/PF0 +- I2C6 SCL/SDA : PD1/PD0 +- SPI2 SCK/MISO/MOSI/CS : PB13/PD3/PD4/PB12 +- SPI3 SCK/MISO/MOSI/CS : PG9/PG10/PG11/PG15 +- ADC1 : channel5 PA0, channel14 PC5 +- ADC2 : channel9 PA4 +- ADC4 : channel5 PF14 + +System Clock +============ + +The STM32U5A9J-DK Discovery kit relies on an HSE oscillator (16 MHz crystal) +and an LSE oscillator (32.768 kHz crystal) as clock references. +Using the HSE (instead of HSI) is mandatory to manage the DSI interface for +the LCD module and the USB high‑speed interface. + +Serial Port +=========== + +The STM32U5A9J Discovery kit has up to 4 USARTs, 2 UARTs, and 1 LPUART. +The Zephyr console output is assigned to USART1 which connected to the onboard +ST-LINK/V3.0. Virtual COM port interface. Default communication settings are +115200 8N1. + + +Programming and Debugging +************************* + +STM32U5A9J Discovery kit includes an ST-LINK/V3 embedded debug tool interface. +This probe allows to flash and debug the board using various tools. + +Flashing +======== + +Board is configured to be flashed using west STM32CubeProgrammer runner. +Installation of `STM32CubeProgrammer`_ is then required to flash the board., + +Connect the STM32U5A9J Discovery board to your host computer using the USB +port, then run a serial host program to connect with your Discovery +board. For example: + +.. code-block:: console + + $ minicom -D /dev/ttyACM0 -b 115200 + +Then, build and flash in the usual way. Here is an example for the +:ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: stm32u5a9j_dk + :goals: build flash + +You should see the following message on the console: + +.. code-block:: console + + Hello World! stm32u5a9j_dk + +Debugging +========= + +Default debugger for this board is openocd. It could be used in the usual way +with "west debug" command. +Here is an example for the :zephyr:code-sample:`blinky` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: stm32u5a9j_dk + :goals: debug + + +.. _STM32U5A9J-DK website: + https://www.st.com/en/evaluation-tools/stm32u5a9j-dk.html + +.. _STM32U5A9J-DK board User Manual: + https://www.st.com/resource/en/user_manual/um2967-discovery-kit-with-stm32u5a9nj-mcu-stmicroelectronics.pdf + +.. _STM32U5A9NJ on www.st.com: + https://www.st.com/en/microcontrollers-microprocessors/stm32u5a9nj.html + +.. _STM32U5 Series reference manual: + https://www.st.com/resource/en/reference_manual/rm0456-stm32u5-series-armbased-32bit-mcus-stmicroelectronics.pdf + +.. _STM32U5Axxx datasheet: + https://www.st.com/resource/en/datasheet/stm32u5a9nj.pdf + +.. _STM32CubeProgrammer: + https://www.st.com/en/development-tools/stm32cubeprog.html + +.. _STM32U5A9J_DK board schematics: + https://www.st.com/resource/en/schematic_pack/mb1829-u5a9njq-b01-schematic.pdf diff --git a/boards/arm/stm32u5a9j_dk/stm32u5a9j_dk.dts b/boards/arm/stm32u5a9j_dk/stm32u5a9j_dk.dts new file mode 100644 index 00000000000..f236354c6f2 --- /dev/null +++ b/boards/arm/stm32u5a9j_dk/stm32u5a9j_dk.dts @@ -0,0 +1,299 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include + +/ { + model = "STMicroelectronics STM32U5A9J DISCOVERY KIT board"; + compatible = "st,stm32u5a9j-dk"; + + chosen { + zephyr,console = &usart1; + zephyr,shell-uart = &usart1; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + }; + + leds { + compatible = "gpio-leds"; + green_led_0: led_3 { + gpios = <&gpioe 0 GPIO_ACTIVE_HIGH>; + label = "User LD3"; + }; + red_led_0: led_4 { + gpios = <&gpioe 1 GPIO_ACTIVE_HIGH>; + label = "User LD4"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button: button_0 { + label = "User"; + gpios = <&gpioc 13 GPIO_ACTIVE_LOW>; + zephyr,code = ; + }; + }; + + dsi_lcd_qsh_030: connector_dsi_lcd { + compatible = "st,dsi-lcd-qsh-030"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <4 0 &gpioe 8 0>, /* TOUCH_INT */ + <22 0 &gpiod 8 0>, /* SPI chip SEL */ + <24 0 &gpiob 13 0>, /* SPI CLK */ + <26 0 &gpiod 4 0>, /* SPI MOSI */ + <28 0 &gpiod 11 0>, /* SPI DCX */ + <35 0 &gpioe 5 0>, /* SCLK/MCLK */ + <37 0 &gpioe 4 0>, /* LRCLK */ + <40 0 &gpioh 4 0>, /* I2C5_SDA */ + <43 0 &gpioi 7 0>, /* SWIRE */ + <44 0 &gpioh 5 0>, /* I2C5_SCL */ + <49 0 &gpiof 11 0>, /* DSI_TE */ + <53 0 &gpioi 6 0>, /* LCD_BL_CTRL */ + <57 0 &gpiod 5 0>; /* DSI_RESET */ + }; + + aliases { + led0 = &green_led_0; + led1 = &red_led_0; + sw0 = &user_button; + sdhc0 = &sdmmc1; + watchdog0 = &iwdg; + die-temp0 = &die_temp; + volt-sensor0 = &vref1; + volt-sensor1 = &vbat4; + }; +}; + +&clk_hsi48 { + status = "okay"; +}; + +&clk_hse { + clock-frequency = ; + status = "okay"; +}; + +&clk_msis { + status = "okay"; + msi-range = <4>; /* 4MHz (reset value) */ + msi-pll-mode; +}; + +&pll1 { + div-m = <1>; + mul-n = <80>; + div-p = <2>; + div-q = <2>; + div-r = <2>; + clocks = <&clk_msis>; + status = "okay"; +}; + +&rcc { + clocks = <&pll1>; + clock-frequency = ; + ahb-prescaler = <1>; + apb1-prescaler = <1>; + apb2-prescaler = <1>; + apb3-prescaler = <1>; +}; + +&usart1 { + pinctrl-0 = <&usart1_tx_pa9 &usart1_rx_pa10>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +uart0: &usart3 { + pinctrl-0 = <&usart3_tx_pb10 &usart3_rx_pb11>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&lpuart1 { + pinctrl-0 = <&lpuart1_tx_pg7 &lpuart1_rx_pg8>; + pinctrl-names = "default"; + current-speed = <9600>; + status = "okay"; +}; + +&i2c1 { + pinctrl-0 = <&i2c1_scl_pg14 &i2c1_sda_pg13>; + pinctrl-names = "default"; + status = "okay"; + clock-frequency = ; +}; + +&i2c2 { + pinctrl-0 = <&i2c2_scl_pf1 &i2c2_sda_pf0>; + pinctrl-names = "default"; + status = "okay"; + clock-frequency = ; +}; + +&i2c6 { + pinctrl-0 = <&i2c6_scl_pd1 &i2c6_sda_pd0>; + pinctrl-names = "default"; + status = "okay"; + clock-frequency = ; +}; + +&spi2 { + pinctrl-0 = <&spi2_sck_pb13 &spi2_miso_pd3 &spi2_mosi_pd4>; + pinctrl-names = "default"; + cs-gpios = <&gpiob 12 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + status = "okay"; +}; + +&spi3 { + pinctrl-0 = <&spi3_sck_pg9 &spi3_miso_pg10 &spi3_mosi_pg11>; + pinctrl-names = "default"; + cs-gpios = <&gpiog 15 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + status = "okay"; +}; + +&timers1 { + st,prescaler = <1>; + status = "okay"; + + pwm1: pwm { + status = "okay"; + pinctrl-0 = <&tim1_ch2_pe11>; + pinctrl-names = "default"; + }; +}; + +&timers2 { + st,prescaler = <1>; + status = "okay"; + + pwm2: pwm { + status = "okay"; + pinctrl-0 = <&tim2_ch4_pa3>; + pinctrl-names = "default"; + }; +}; + +&sdmmc1 { + pinctrl-0 = <&sdmmc1_d0_pc8 &sdmmc1_d1_pc9 + &sdmmc1_d2_pc10 &sdmmc1_d3_pc11 + &sdmmc1_d4_pb8 &sdmmc1_d5_pb9 + &sdmmc1_d6_pc6 &sdmmc1_d7_pc7 + &sdmmc1_ck_pc12 &sdmmc1_cmd_pd2>; + pinctrl-names = "default"; + status = "okay"; +}; + +&sdmmc2 { + pinctrl-0 = <&sdmmc2_d0_pb14 &sdmmc2_d1_pb15 + &sdmmc2_d2_pb3 &sdmmc2_d3_pb4 + &sdmmc2_ck_pd6 &sdmmc2_cmd_pd7>; + pinctrl-names = "default"; + status = "okay"; +}; + +&adc1 { + pinctrl-0 = <&adc1_in5_pa0 &adc1_in14_pc5>; + pinctrl-names = "default"; + st,adc-clock-source = ; + st,adc-prescaler = <1>; + status = "okay"; + + #address-cells = <1>; + #size-cells = <0>; + + channel@5 { + reg = <0x5>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <14>; + }; + + channel@e { + reg = <0xe>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <14>; + }; +}; + +&adc4 { + pinctrl-0 = <&adc4_in5_pf14>; + pinctrl-names = "default"; + st,adc-clock-source = ; + st,adc-prescaler = <1>; + status = "okay"; + + #address-cells = <1>; + #size-cells = <0>; + + channel@5 { + reg = <0x5>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* + * Following flash partition is dedicated to the use of bootloader + */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 DT_SIZE_K(64)>; + }; + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 DT_SIZE_K(1952)>; + }; + slot1_partition: partition@1f8000 { + label = "image-1"; + reg = <0x001f8000 DT_SIZE_K(1960)>; + }; + storage_partition: partition@3e2000 { + label = "storage"; + reg = <0x003e2000 DT_SIZE_K(120)>; + }; + }; +}; + +&iwdg { + status = "okay"; +}; + +&rng { + status = "okay"; +}; + +&die_temp { + status = "okay"; +}; + +&vref1 { + status = "okay"; +}; + +&vbat4 { + status = "okay"; +}; diff --git a/boards/arm/stm32u5a9j_dk/stm32u5a9j_dk.yaml b/boards/arm/stm32u5a9j_dk/stm32u5a9j_dk.yaml new file mode 100644 index 00000000000..82ada8651e9 --- /dev/null +++ b/boards/arm/stm32u5a9j_dk/stm32u5a9j_dk.yaml @@ -0,0 +1,23 @@ +identifier: stm32u5a9j_dk +name: ST STM32U5A9J-DK Discovery Kit +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb +supported: + - gpio + - led + - button + - adc + - uart + - usart + - lpuart + - watchdog + - spi + - i2c + - flash + - sdmmc +ram: 2496 +flash: 4096 +vendor: st diff --git a/boards/arm/stm32u5a9j_dk/stm32u5a9j_dk_defconfig b/boards/arm/stm32u5a9j_dk/stm32u5a9j_dk_defconfig new file mode 100644 index 00000000000..71e92cf0450 --- /dev/null +++ b/boards/arm/stm32u5a9j_dk/stm32u5a9j_dk_defconfig @@ -0,0 +1,28 @@ +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +# Set SoC present on the board +CONFIG_SOC_SERIES_STM32U5X=y +CONFIG_SOC_STM32U5A9XX=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable HW stack protection +CONFIG_HW_STACK_PROTECTION=y + +# Enable serial +CONFIG_SERIAL=y + +# Enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable GPIO +CONFIG_GPIO=y + +# Enable clocks +CONFIG_CLOCK_CONTROL=y + +# Enable pinctrl +CONFIG_PINCTRL=y diff --git a/boards/arm/stm32u5a9j_dk/support/openocd.cfg b/boards/arm/stm32u5a9j_dk/support/openocd.cfg new file mode 100644 index 00000000000..23e2409440f --- /dev/null +++ b/boards/arm/stm32u5a9j_dk/support/openocd.cfg @@ -0,0 +1,46 @@ +source [find interface/stlink-dap.cfg] + +set WORKAREASIZE 0x8000 + +transport select "dapdirect_swd" + +set CHIPNAME STM32U5A9NJHxQ +set BOARDNAME STM32U5A9J_DK + +# Enable debug when in low power modes +set ENABLE_LOW_POWER 1 + +# Stop Watchdog counters when halt +set STOP_WATCHDOG 1 + +# STlink Debug clock frequency +set CLOCK_FREQ 8000 + +# Reset configuration +# use hardware reset, connect under reset +# connect_assert_srst needed if low power mode application running (WFI...) +reset_config srst_only srst_nogate connect_assert_srst +set CONNECT_UNDER_RESET 1 +set CORE_RESET 0 + +# ACCESS PORT NUMBER +set AP_NUM 0 +# GDB PORT +set GDB_PORT 3333 + +# BCTM CPU variables + +source [find target/stm32u5x.cfg] + +$_TARGETNAME configure -event gdb-attach { + echo "Debugger attaching: halting execution" + reset halt + gdb_breakpoint_override hard +} + +$_TARGETNAME configure -event gdb-detach { + echo "Debugger detaching: resuming execution" + resume +} + +gdb_memory_map disable diff --git a/boards/arm/stm32vl_disco/doc/index.rst b/boards/arm/stm32vl_disco/doc/index.rst index e7a20a3b3e4..006c8854bb4 100644 --- a/boards/arm/stm32vl_disco/doc/index.rst +++ b/boards/arm/stm32vl_disco/doc/index.rst @@ -137,7 +137,7 @@ This interface is supported by the openocd version included in the Zephyr SDK. Flashing an application ----------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -150,7 +150,7 @@ Debugging ========= You can debug an application in the usual way. Here is an example for the -:ref:`blinky-sample` application. +:zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/stm32vl_disco/stm32vl_disco.yaml b/boards/arm/stm32vl_disco/stm32vl_disco.yaml index 2c73413ed49..5e37731dfcc 100644 --- a/boards/arm/stm32vl_disco/stm32vl_disco.yaml +++ b/boards/arm/stm32vl_disco/stm32vl_disco.yaml @@ -12,3 +12,4 @@ supported: - gpio - i2c - spi +vendor: st diff --git a/boards/arm/swan_r5/swan_r5.yaml b/boards/arm/swan_r5/swan_r5.yaml index 9f52d6b5cb3..5e0efea6540 100644 --- a/boards/arm/swan_r5/swan_r5.yaml +++ b/boards/arm/swan_r5/swan_r5.yaml @@ -17,3 +17,4 @@ supported: - adc ram: 640 flash: 2048 +vendor: blues diff --git a/boards/arm/tdk_robokit1/tdk_robokit1-common.dtsi b/boards/arm/tdk_robokit1/tdk_robokit1-common.dtsi index 4d7003fadd9..5fc1bf4cb9f 100644 --- a/boards/arm/tdk_robokit1/tdk_robokit1-common.dtsi +++ b/boards/arm/tdk_robokit1/tdk_robokit1-common.dtsi @@ -46,7 +46,6 @@ temp_sensor: ambient_temp_sensor { compatible = "epcos,b57861s0103a039"; io-channels = <&spi_adc 0>; - r25-ohm = <10000>; pullup-uv = <3300000>; pullup-ohm = <0>; pulldown-ohm = <10000>; diff --git a/boards/arm/tdk_robokit1/tdk_robokit1.yaml b/boards/arm/tdk_robokit1/tdk_robokit1.yaml index 33ec11e6014..4c4d8b19e13 100644 --- a/boards/arm/tdk_robokit1/tdk_robokit1.yaml +++ b/boards/arm/tdk_robokit1/tdk_robokit1.yaml @@ -18,3 +18,4 @@ supported: - pwm - can - hwinfo +vendor: tdk diff --git a/boards/arm/teensy4/teensy40.yaml b/boards/arm/teensy4/teensy40.yaml index 36ea176ed4b..11a7f0b284d 100644 --- a/boards/arm/teensy4/teensy40.yaml +++ b/boards/arm/teensy4/teensy40.yaml @@ -22,3 +22,4 @@ testing: ignore_tags: - net - posix +vendor: nxp diff --git a/boards/arm/teensy4/teensy41.yaml b/boards/arm/teensy4/teensy41.yaml index 45c40b7fdc8..b2ad1e303ca 100644 --- a/boards/arm/teensy4/teensy41.yaml +++ b/boards/arm/teensy4/teensy41.yaml @@ -23,3 +23,4 @@ testing: ignore_tags: - net - posix +vendor: nxp diff --git a/boards/arm/thingy52_nrf52832/doc/index.rst b/boards/arm/thingy52_nrf52832/doc/index.rst index 96044ee9df4..f90d38a399a 100644 --- a/boards/arm/thingy52_nrf52832/doc/index.rst +++ b/boards/arm/thingy52_nrf52832/doc/index.rst @@ -362,7 +362,7 @@ debugger. A development board with a Debug out connector such as the Testing board features ********************** -The green lightwell LED can be tested with the :ref:`blinky-sample` example. +The green lightwell LED can be tested with the :zephyr:code-sample:`blinky` example. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/arm/thingy52_nrf52832/thingy52_nrf52832.yaml b/boards/arm/thingy52_nrf52832/thingy52_nrf52832.yaml index 22882bc081b..c4aa66f67ce 100644 --- a/boards/arm/thingy52_nrf52832/thingy52_nrf52832.yaml +++ b/boards/arm/thingy52_nrf52832/thingy52_nrf52832.yaml @@ -12,3 +12,4 @@ supported: - gpio - i2c - hts221 +vendor: nordic diff --git a/boards/arm/thingy52_nrf52832/thingy52_nrf52832_defconfig b/boards/arm/thingy52_nrf52832/thingy52_nrf52832_defconfig index 6cdebdd6ff1..2bdadf855de 100644 --- a/boards/arm/thingy52_nrf52832/thingy52_nrf52832_defconfig +++ b/boards/arm/thingy52_nrf52832/thingy52_nrf52832_defconfig @@ -30,5 +30,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/thingy53_nrf5340/Kconfig b/boards/arm/thingy53_nrf5340/Kconfig index a907b074688..116fd1c8edb 100644 --- a/boards/arm/thingy53_nrf5340/Kconfig +++ b/boards/arm/thingy53_nrf5340/Kconfig @@ -56,7 +56,7 @@ config DOMAIN_CPUNET_BOARD help The board which will be used for CPUNET domain when creating a multi image application where one or more images should be located on - another board. For example hci_rpmsg on the nRF5340_cpunet for + another board. For example hci_ipc on the nRF5340_cpunet for Bluetooth applications. endif # BOARD_THINGY53_NRF5340_CPUAPP || BOARD_THINGY53_NRF5340_CPUAPP_NS diff --git a/boards/arm/thingy53_nrf5340/Kconfig.defconfig b/boards/arm/thingy53_nrf5340/Kconfig.defconfig index b6080de9a80..45869075487 100644 --- a/boards/arm/thingy53_nrf5340/Kconfig.defconfig +++ b/boards/arm/thingy53_nrf5340/Kconfig.defconfig @@ -65,11 +65,11 @@ endif # BOARD_THINGY53_NRF5340_CPUAPP_NS if !TRUSTED_EXECUTION_SECURE choice BT_HCI_BUS_TYPE - default BT_RPMSG if BT + default BT_HCI_IPC if BT endchoice config HEAP_MEM_POOL_SIZE - default 4096 if BT_RPMSG + default 4096 if BT_HCI_IPC config BT_HAS_HCI_VS default BT diff --git a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_common.dtsi b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_common.dtsi index 515fc3bea7b..54efd588cf7 100644 --- a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_common.dtsi +++ b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_common.dtsi @@ -13,7 +13,7 @@ zephyr,uart-mcumgr = &cdc_acm_uart; zephyr,bt-mon-uart = &cdc_acm_uart; zephyr,bt-c2h-uart = &cdc_acm_uart; - zephyr,bt-hci-rpmsg-ipc = &ipc0; + zephyr,bt-hci-ipc = &ipc0; nordic,802154-spinel-ipc = &ipc0; zephyr,ieee802154 = &ieee802154; nordic,pm-ext-flash = &mx25r64; diff --git a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpuapp.yaml b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpuapp.yaml index 542de24bbcb..b4651427a22 100644 --- a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpuapp.yaml +++ b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpuapp.yaml @@ -16,3 +16,4 @@ supported: - usb_cdc - usb_device - netif:openthread +vendor: nordic diff --git a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpuapp_defconfig b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpuapp_defconfig index 6ca9f643a56..5f3fd735660 100644 --- a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpuapp_defconfig +++ b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpuapp_defconfig @@ -23,8 +23,6 @@ CONFIG_UART_CONSOLE=y # Enable uart driver CONFIG_SERIAL=y -CONFIG_PINCTRL=y - # Board Kconfig.defconfig enables USB CDC ACM and should disable USB remote # wakeup by default. It needs to be disabled here, because the USB nrfx # driver always overwrites option from Kconfig mentioned above with the diff --git a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpuapp_ns.yaml b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpuapp_ns.yaml index 5b180a30ad2..d8db4ae1520 100644 --- a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpuapp_ns.yaml +++ b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpuapp_ns.yaml @@ -16,3 +16,4 @@ supported: - usb_cdc - usb_device - netif:openthread +vendor: nordic diff --git a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpuapp_ns_defconfig b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpuapp_ns_defconfig index b6608ff6a25..23d7e5ff6e0 100644 --- a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpuapp_ns_defconfig +++ b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpuapp_ns_defconfig @@ -26,8 +26,6 @@ CONFIG_UART_CONSOLE=y # Enable uart driver CONFIG_SERIAL=y -CONFIG_PINCTRL=y - # Board Kconfig.defconfig enables USB CDC ACM and should disable USB remote # wakeup by default. It needs to be disabled here, because the USB nrfx # driver always overwrites option from Kconfig mentioned above with the diff --git a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpunet.dts b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpunet.dts index c88a8ab4f6a..895803a8623 100644 --- a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpunet.dts +++ b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpunet.dts @@ -19,7 +19,7 @@ zephyr,uart-mcumgr = &uart0; zephyr,bt-mon-uart = &uart0; zephyr,bt-c2h-uart = &uart0; - zephyr,bt-hci-rpmsg-ipc = &ipc0; + zephyr,bt-hci-ipc = &ipc0; nordic,802154-spinel-ipc = &ipc0; zephyr,sram = &sram1; zephyr,flash = &flash1; diff --git a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpunet.yaml b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpunet.yaml index 6a2e6001e71..a41d496937f 100644 --- a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpunet.yaml +++ b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpunet.yaml @@ -11,3 +11,4 @@ flash: 256 supported: - gpio - watchdog +vendor: nordic diff --git a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpunet_defconfig b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpunet_defconfig index 50a0e59d652..33dc6fbdedd 100644 --- a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpunet_defconfig +++ b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpunet_defconfig @@ -12,5 +12,3 @@ CONFIG_HW_STACK_PROTECTION=y # Enable GPIO CONFIG_GPIO=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/twr_ke18f/doc/index.rst b/boards/arm/twr_ke18f/doc/index.rst index 336099ddca0..04aa94f0dfe 100644 --- a/boards/arm/twr_ke18f/doc/index.rst +++ b/boards/arm/twr_ke18f/doc/index.rst @@ -113,11 +113,11 @@ accelerometer and magnetometer for sensor values (``CONFIG_FXOS8700_TRIGGER_NONE=y``). In order to support FXOS8700 triggers (interrupts) the 0 ohm resistors -``R47`` and and ``R57`` must be mounted on the TWR-KE18F board. The +``R47`` and ``R57`` must be mounted on the TWR-KE18F board. The devicetree must also be modified to describe the FXOS8700 interrupt GPIOs: -.. code-block:: none +.. code-block:: devicetree /dts-v1/; diff --git a/boards/arm/twr_ke18f/twr_ke18f.dts b/boards/arm/twr_ke18f/twr_ke18f.dts index b8ab3e8af4d..92a11d68842 100644 --- a/boards/arm/twr_ke18f/twr_ke18f.dts +++ b/boards/arm/twr_ke18f/twr_ke18f.dts @@ -266,6 +266,8 @@ }; &lpspi0 { + dmas = <&edma 0 14>, <&edma 1 15>; + dma-names = "rx", "tx"; status = "okay"; pinctrl-0 = <&lpspi0_default>; pinctrl-names = "default"; diff --git a/boards/arm/twr_ke18f/twr_ke18f.yaml b/boards/arm/twr_ke18f/twr_ke18f.yaml index 7f55809d69e..ddd4df467f0 100644 --- a/boards/arm/twr_ke18f/twr_ke18f.yaml +++ b/boards/arm/twr_ke18f/twr_ke18f.yaml @@ -18,3 +18,4 @@ supported: - pwm - spi - watchdog +vendor: nxp diff --git a/boards/arm/twr_kv58f220m/twr_kv58f220m.yaml b/boards/arm/twr_kv58f220m/twr_kv58f220m.yaml index 480c61273bf..810d96c2ae6 100644 --- a/boards/arm/twr_kv58f220m/twr_kv58f220m.yaml +++ b/boards/arm/twr_kv58f220m/twr_kv58f220m.yaml @@ -10,3 +10,4 @@ ram: 256 flash: 1024 supported: - i2c +vendor: nxp diff --git a/boards/arm/ubx_bmd300eval_nrf52832/ubx_bmd300eval_nrf52832.yaml b/boards/arm/ubx_bmd300eval_nrf52832/ubx_bmd300eval_nrf52832.yaml index 3afd6fb2d3a..09d6a50ed74 100644 --- a/boards/arm/ubx_bmd300eval_nrf52832/ubx_bmd300eval_nrf52832.yaml +++ b/boards/arm/ubx_bmd300eval_nrf52832/ubx_bmd300eval_nrf52832.yaml @@ -20,3 +20,4 @@ supported: - pwm - spi - watchdog +vendor: u-blox diff --git a/boards/arm/ubx_bmd300eval_nrf52832/ubx_bmd300eval_nrf52832_defconfig b/boards/arm/ubx_bmd300eval_nrf52832/ubx_bmd300eval_nrf52832_defconfig index 801393790fe..0ac55829154 100644 --- a/boards/arm/ubx_bmd300eval_nrf52832/ubx_bmd300eval_nrf52832_defconfig +++ b/boards/arm/ubx_bmd300eval_nrf52832/ubx_bmd300eval_nrf52832_defconfig @@ -22,5 +22,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/ubx_bmd330eval_nrf52810/ubx_bmd330eval_nrf52810.yaml b/boards/arm/ubx_bmd330eval_nrf52810/ubx_bmd330eval_nrf52810.yaml index e09fd51842c..3554db7451f 100644 --- a/boards/arm/ubx_bmd330eval_nrf52810/ubx_bmd330eval_nrf52810.yaml +++ b/boards/arm/ubx_bmd330eval_nrf52810/ubx_bmd330eval_nrf52810.yaml @@ -20,3 +20,4 @@ supported: - pwm - spi - watchdog +vendor: u-blox diff --git a/boards/arm/ubx_bmd330eval_nrf52810/ubx_bmd330eval_nrf52810_defconfig b/boards/arm/ubx_bmd330eval_nrf52810/ubx_bmd330eval_nrf52810_defconfig index 4f8a5c5a8da..edfe56e0a15 100644 --- a/boards/arm/ubx_bmd330eval_nrf52810/ubx_bmd330eval_nrf52810_defconfig +++ b/boards/arm/ubx_bmd330eval_nrf52810/ubx_bmd330eval_nrf52810_defconfig @@ -25,5 +25,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/ubx_bmd340eval_nrf52840/ubx_bmd340eval_nrf52840.yaml b/boards/arm/ubx_bmd340eval_nrf52840/ubx_bmd340eval_nrf52840.yaml index bef9951282c..dbe7c648911 100644 --- a/boards/arm/ubx_bmd340eval_nrf52840/ubx_bmd340eval_nrf52840.yaml +++ b/boards/arm/ubx_bmd340eval_nrf52840/ubx_bmd340eval_nrf52840.yaml @@ -24,3 +24,4 @@ supported: - usb_device - watchdog - netif:openthread +vendor: u-blox diff --git a/boards/arm/ubx_bmd340eval_nrf52840/ubx_bmd340eval_nrf52840_defconfig b/boards/arm/ubx_bmd340eval_nrf52840/ubx_bmd340eval_nrf52840_defconfig index 37271c2ce81..f1fd8825b8c 100644 --- a/boards/arm/ubx_bmd340eval_nrf52840/ubx_bmd340eval_nrf52840_defconfig +++ b/boards/arm/ubx_bmd340eval_nrf52840/ubx_bmd340eval_nrf52840_defconfig @@ -25,5 +25,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/ubx_bmd345eval_nrf52840/ubx_bmd345eval_nrf52840.yaml b/boards/arm/ubx_bmd345eval_nrf52840/ubx_bmd345eval_nrf52840.yaml index 4f109f0ae61..7d8201f2093 100644 --- a/boards/arm/ubx_bmd345eval_nrf52840/ubx_bmd345eval_nrf52840.yaml +++ b/boards/arm/ubx_bmd345eval_nrf52840/ubx_bmd345eval_nrf52840.yaml @@ -23,3 +23,4 @@ supported: - usb_device - watchdog - netif:openthread +vendor: u-blox diff --git a/boards/arm/ubx_bmd345eval_nrf52840/ubx_bmd345eval_nrf52840_defconfig b/boards/arm/ubx_bmd345eval_nrf52840/ubx_bmd345eval_nrf52840_defconfig index 4a35f6e612f..97872745a6d 100644 --- a/boards/arm/ubx_bmd345eval_nrf52840/ubx_bmd345eval_nrf52840_defconfig +++ b/boards/arm/ubx_bmd345eval_nrf52840/ubx_bmd345eval_nrf52840_defconfig @@ -25,5 +25,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/ubx_bmd360eval_nrf52811/ubx_bmd360eval_nrf52811.yaml b/boards/arm/ubx_bmd360eval_nrf52811/ubx_bmd360eval_nrf52811.yaml index 130de31a7ac..3da084eb1ac 100644 --- a/boards/arm/ubx_bmd360eval_nrf52811/ubx_bmd360eval_nrf52811.yaml +++ b/boards/arm/ubx_bmd360eval_nrf52811/ubx_bmd360eval_nrf52811.yaml @@ -20,3 +20,4 @@ supported: - pwm - spi - watchdog +vendor: u-blox diff --git a/boards/arm/ubx_bmd360eval_nrf52811/ubx_bmd360eval_nrf52811_defconfig b/boards/arm/ubx_bmd360eval_nrf52811/ubx_bmd360eval_nrf52811_defconfig index 7a63bc69bf2..6cc16653c74 100644 --- a/boards/arm/ubx_bmd360eval_nrf52811/ubx_bmd360eval_nrf52811_defconfig +++ b/boards/arm/ubx_bmd360eval_nrf52811/ubx_bmd360eval_nrf52811_defconfig @@ -25,5 +25,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/ubx_bmd380eval_nrf52840/ubx_bmd380eval_nrf52840.yaml b/boards/arm/ubx_bmd380eval_nrf52840/ubx_bmd380eval_nrf52840.yaml index 3fac915b953..afd074165c1 100644 --- a/boards/arm/ubx_bmd380eval_nrf52840/ubx_bmd380eval_nrf52840.yaml +++ b/boards/arm/ubx_bmd380eval_nrf52840/ubx_bmd380eval_nrf52840.yaml @@ -21,3 +21,4 @@ supported: - usb_device - watchdog - netif:openthread +vendor: u-blox diff --git a/boards/arm/ubx_bmd380eval_nrf52840/ubx_bmd380eval_nrf52840_defconfig b/boards/arm/ubx_bmd380eval_nrf52840/ubx_bmd380eval_nrf52840_defconfig index c20dc6fe9f3..79826cc9974 100644 --- a/boards/arm/ubx_bmd380eval_nrf52840/ubx_bmd380eval_nrf52840_defconfig +++ b/boards/arm/ubx_bmd380eval_nrf52840/ubx_bmd380eval_nrf52840_defconfig @@ -26,5 +26,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/ubx_evkannab1_nrf52832/ubx_evkannab1_nrf52832.yaml b/boards/arm/ubx_evkannab1_nrf52832/ubx_evkannab1_nrf52832.yaml index fd7c6b02115..39de6903d44 100644 --- a/boards/arm/ubx_evkannab1_nrf52832/ubx_evkannab1_nrf52832.yaml +++ b/boards/arm/ubx_evkannab1_nrf52832/ubx_evkannab1_nrf52832.yaml @@ -20,3 +20,4 @@ supported: - pwm - spi - watchdog +vendor: u-blox diff --git a/boards/arm/ubx_evkannab1_nrf52832/ubx_evkannab1_nrf52832_defconfig b/boards/arm/ubx_evkannab1_nrf52832/ubx_evkannab1_nrf52832_defconfig index 93127beefef..95f9f59739f 100644 --- a/boards/arm/ubx_evkannab1_nrf52832/ubx_evkannab1_nrf52832_defconfig +++ b/boards/arm/ubx_evkannab1_nrf52832/ubx_evkannab1_nrf52832_defconfig @@ -25,5 +25,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/ubx_evkninab1_nrf52832/ubx_evkninab1_nrf52832.yaml b/boards/arm/ubx_evkninab1_nrf52832/ubx_evkninab1_nrf52832.yaml index a5d025a7d1f..125efd94a1c 100644 --- a/boards/arm/ubx_evkninab1_nrf52832/ubx_evkninab1_nrf52832.yaml +++ b/boards/arm/ubx_evkninab1_nrf52832/ubx_evkninab1_nrf52832.yaml @@ -19,3 +19,4 @@ supported: - pwm - spi - watchdog +vendor: u-blox diff --git a/boards/arm/ubx_evkninab1_nrf52832/ubx_evkninab1_nrf52832_defconfig b/boards/arm/ubx_evkninab1_nrf52832/ubx_evkninab1_nrf52832_defconfig index b44e54e3d18..c23f9eb7833 100644 --- a/boards/arm/ubx_evkninab1_nrf52832/ubx_evkninab1_nrf52832_defconfig +++ b/boards/arm/ubx_evkninab1_nrf52832/ubx_evkninab1_nrf52832_defconfig @@ -25,5 +25,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/ubx_evkninab3_nrf52840/ubx_evkninab3_nrf52840.yaml b/boards/arm/ubx_evkninab3_nrf52840/ubx_evkninab3_nrf52840.yaml index 4c34a42d8d3..34590896e55 100644 --- a/boards/arm/ubx_evkninab3_nrf52840/ubx_evkninab3_nrf52840.yaml +++ b/boards/arm/ubx_evkninab3_nrf52840/ubx_evkninab3_nrf52840.yaml @@ -22,3 +22,4 @@ supported: - usb_device - watchdog - netif:openthread +vendor: u-blox diff --git a/boards/arm/ubx_evkninab3_nrf52840/ubx_evkninab3_nrf52840_defconfig b/boards/arm/ubx_evkninab3_nrf52840/ubx_evkninab3_nrf52840_defconfig index f9cabe94b4a..9ccc843efb0 100644 --- a/boards/arm/ubx_evkninab3_nrf52840/ubx_evkninab3_nrf52840_defconfig +++ b/boards/arm/ubx_evkninab3_nrf52840/ubx_evkninab3_nrf52840_defconfig @@ -25,5 +25,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/ubx_evkninab4_nrf52833/ubx_evkninab4_nrf52833.yaml b/boards/arm/ubx_evkninab4_nrf52833/ubx_evkninab4_nrf52833.yaml index 38bfc53d6c7..4134fe918c8 100644 --- a/boards/arm/ubx_evkninab4_nrf52833/ubx_evkninab4_nrf52833.yaml +++ b/boards/arm/ubx_evkninab4_nrf52833/ubx_evkninab4_nrf52833.yaml @@ -17,3 +17,4 @@ supported: - pwm - watchdog - counter +vendor: u-blox diff --git a/boards/arm/ubx_evkninab4_nrf52833/ubx_evkninab4_nrf52833_defconfig b/boards/arm/ubx_evkninab4_nrf52833/ubx_evkninab4_nrf52833_defconfig index c06ad795868..80995445718 100644 --- a/boards/arm/ubx_evkninab4_nrf52833/ubx_evkninab4_nrf52833_defconfig +++ b/boards/arm/ubx_evkninab4_nrf52833/ubx_evkninab4_nrf52833_defconfig @@ -25,5 +25,3 @@ CONFIG_SERIAL=y # enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/udoo_neo_full_m4/udoo_neo_full_m4.yaml b/boards/arm/udoo_neo_full_m4/udoo_neo_full_m4.yaml index 2a1fd2099c5..8e2876ca5ab 100644 --- a/boards/arm/udoo_neo_full_m4/udoo_neo_full_m4.yaml +++ b/boards/arm/udoo_neo_full_m4/udoo_neo_full_m4.yaml @@ -18,3 +18,4 @@ supported: - counter - gpio - uart +vendor: nxp diff --git a/boards/arm/usb_kw24d512/usb_kw24d512.yaml b/boards/arm/usb_kw24d512/usb_kw24d512.yaml index 33e33c7a6c2..5344593b029 100644 --- a/boards/arm/usb_kw24d512/usb_kw24d512.yaml +++ b/boards/arm/usb_kw24d512/usb_kw24d512.yaml @@ -11,3 +11,4 @@ toolchain: supported: - usb_device - watchdog +vendor: nxp diff --git a/boards/arm/v2m_beetle/v2m_beetle.yaml b/boards/arm/v2m_beetle/v2m_beetle.yaml index 5ccd4f60623..ca1e17d2d8d 100644 --- a/boards/arm/v2m_beetle/v2m_beetle.yaml +++ b/boards/arm/v2m_beetle/v2m_beetle.yaml @@ -8,3 +8,4 @@ toolchain: - xtools supported: - counter +vendor: arm diff --git a/boards/arm/v2m_musca_b1/v2m_musca_b1.yaml b/boards/arm/v2m_musca_b1/v2m_musca_b1.yaml index 5893c9f009c..76ddda99468 100644 --- a/boards/arm/v2m_musca_b1/v2m_musca_b1.yaml +++ b/boards/arm/v2m_musca_b1/v2m_musca_b1.yaml @@ -8,3 +8,4 @@ toolchain: - xtools supported: - gpio +vendor: arm diff --git a/boards/arm/v2m_musca_b1/v2m_musca_b1_ns.yaml b/boards/arm/v2m_musca_b1/v2m_musca_b1_ns.yaml index 7a43ef19844..f116e1e52b9 100644 --- a/boards/arm/v2m_musca_b1/v2m_musca_b1_ns.yaml +++ b/boards/arm/v2m_musca_b1/v2m_musca_b1_ns.yaml @@ -8,3 +8,4 @@ toolchain: - xtools ram: 64 flash: 1663 +vendor: arm diff --git a/boards/arm/v2m_musca_s1/v2m_musca_s1.yaml b/boards/arm/v2m_musca_s1/v2m_musca_s1.yaml index 4fda7c2b4e0..194666cba50 100644 --- a/boards/arm/v2m_musca_s1/v2m_musca_s1.yaml +++ b/boards/arm/v2m_musca_s1/v2m_musca_s1.yaml @@ -8,3 +8,4 @@ toolchain: - xtools supported: - gpio +vendor: arm diff --git a/boards/arm/v2m_musca_s1/v2m_musca_s1_ns.yaml b/boards/arm/v2m_musca_s1/v2m_musca_s1_ns.yaml index e70129e968e..7494e2aff38 100644 --- a/boards/arm/v2m_musca_s1/v2m_musca_s1_ns.yaml +++ b/boards/arm/v2m_musca_s1/v2m_musca_s1_ns.yaml @@ -8,3 +8,4 @@ toolchain: - xtools ram: 256 flash: 511 +vendor: arm diff --git a/boards/arm/verdin_imx8mp_m7/Kconfig.board b/boards/arm/verdin_imx8mp_m7/Kconfig.board new file mode 100644 index 00000000000..fb86601179c --- /dev/null +++ b/boards/arm/verdin_imx8mp_m7/Kconfig.board @@ -0,0 +1,9 @@ +# VERDIN_IMX8MP_M7 board + +# Copyright (c) 2023 Toradex +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_VERDIN_IMX8MP_M7 + bool "Toradex iMX8M Plus M7" + depends on SOC_SERIES_IMX8ML_M7 + select SOC_PART_NUMBER_MIMX8ML8DVNLZ diff --git a/boards/arm/verdin_imx8mp_m7/Kconfig.defconfig b/boards/arm/verdin_imx8mp_m7/Kconfig.defconfig new file mode 100644 index 00000000000..3c3ab2db770 --- /dev/null +++ b/boards/arm/verdin_imx8mp_m7/Kconfig.defconfig @@ -0,0 +1,18 @@ +# VERDIN_IMX8MP_M7 board defconfig + +# Copyright (c) 2023 Toradex +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_VERDIN_IMX8MP_M7 + +config BOARD + default "verdin_imx8mp_m7" + +if !XIP +config FLASH_SIZE + default 0 +config FLASH_BASE_ADDRESS + default 0 +endif + +endif # BOARD_VERDIN_IMX8MP_M7 diff --git a/boards/arm/verdin_imx8mp_m7/board.cmake b/boards/arm/verdin_imx8mp_m7/board.cmake new file mode 100644 index 00000000000..546ba82f8a9 --- /dev/null +++ b/boards/arm/verdin_imx8mp_m7/board.cmake @@ -0,0 +1,11 @@ +# +# Copyright (c) 2023, Toradex +# +# SPDX-License-Identifier: Apache-2.0 +# + +board_set_debugger_ifnset(jlink) +board_set_flasher_ifnset(jlink) + +board_runner_args(jlink "--device=MIMX8ML8_M7") +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/arm/verdin_imx8mp_m7/doc/index.rst b/boards/arm/verdin_imx8mp_m7/doc/index.rst new file mode 100644 index 00000000000..455acb8c290 --- /dev/null +++ b/boards/arm/verdin_imx8mp_m7/doc/index.rst @@ -0,0 +1,304 @@ +.. _verdin_imx8mp_m7: + +Toradex Verdin iMX8M Plus SoM +############################# + +Overview +******** + +The Verdin iMX8M Plus is a Computer on Module (CoM) developed by Toradex. It is based on the NXP® +i.MX 8M Plus family of processors (or System on Chips - SoCs). + +The Verdin iMX8M Plus family consists of: + ++-------------------------------------------------+-----------------------+ +| CoM | SoC | ++=================================================+=======================+ +| Verdin iMX8M Plus Quad 8GB Wi-Fi / Bluetooth IT | i.MX 8M Plus Quad | ++-------------------------------------------------+-----------------------+ +| Verdin iMX8M Plus Quad 4GB Wi-Fi / Bluetooth IT | i.MX 8M Plus Quad | ++-------------------------------------------------+-----------------------+ +| Verdin iMX8M Plus Quad 4GB IT | i.MX 8M Plus Quad | ++-------------------------------------------------+-----------------------+ +| Verdin iMX8M Plus Quad 2GB Wi-Fi / Bluetooth IT | i.MX 8M Plus Quad | ++-------------------------------------------------+-----------------------+ +| Verdin iMX8M Plus QuadLite 1GB IT | i.MX 8M Plus QuadLite | ++-------------------------------------------------+-----------------------+ + +Quoting NXP: + + The i.MX 8M Plus family focuses on machine learning and vision, advanced multimedia, and + industrial automation with high reliability. It is built to meet the needs of Smart Home, + Building, City and Industry 4.0 applications. + +The Verdin iMX8M Plus integrates a total of 4 Arm Cortex™-A53 CPUs, operating at 1.6 GHz, alongside +a single Arm Cortex™-M7F microcontroller operating at 800 MHz. + +.. figure:: verdin_imx8mp_front.jpg + :align: center + :alt: Toradex Verdin iMX8M Plus + + Toradex Verdin iMX8M Plus (Credit: Toradex) + +Regarding the Cortex-A53 cluster, it employs the ARMv8-A architecture as a mid-range and +energy-efficient processor. With four cores in this cluster, each core is equipped with its own L1 +memory system. Moreover, the cluster incorporates a unified L2 cache that offers supplementary +functions. This cache is housed within a single APR region. Facilitating debugging processes, the +cores support both real-time trace through the ETM system and static debugging via JTAG. +Furthermore, the platform features support for real-time trace capabilities, achieved through ARM's +CoreSight ETM modules, and also enables cross-triggering by utilizing CTI and CTM modules. + +The Arm® Cortex®-M7 microcontroller is indicated for Real-time control, combining high-performance +with a minimal interrupt latency. It stands out for its compatibility with existing Cortex-M profile +processors. The microcontroller employs an efficient in-order super-scalar pipeline, allowing +dual-issued instructions such as load/load and load/store pairs, thanks to its multiple memory +interfaces. These interfaces encompass Tightly-Coupled Memory (TCM), Harvard caches, and an AXI +master interface. The Arm Cortex-M7 Platform boasts features like a 32 KB L1 Instruction Cache, 32 +KB L1 Data Cache, Floating Point Unit (FPU) with FPv5 architecture support, and an Internal Trace +(TRC) mechanism. Furthermore, the chip supports 160 IRQs, and integrates crucial Arm CoreSight +components including ETM and CTI, dedicated to facilitating debug and trace functions. + +Hardware +******** + +- SoC name: NXP® i.MX 8M Plus +- CPU Type: 4x Arm Cortex™-A53 (1.6 GHz) +- Microcontroller: 1x Arm Cortex™-M7F (800 MHz) + +- Memory: + + - RAM -> A53: 1GB, 2GB, 4GB or 8GB + - RAM -> M7: 3x32KB (TCML, TCMU, OCRAM_S), 1x128KB (OCRAM) and 1x256MB (DDR) + - Flash -> A53: Up to 32GB eMMC + +- Connectivity: + + - USB 3.1: 1x Host / 1x OTG (Gen 1) + - USB 2.0: 1x Host / 1x OTG + - Ethernet Gigabit with TSN (+2nd RGMII) + - Wi-Fi Dual-band 802.11ac 2x2 MU-MIMO + - Bluetooth 5 + - 5x I2C + - 3x SPI + - 1 QSPI + - 4x UART + - Up to 92 GPIO + - 4x Analog Input + - 2x CAN (FlexCAN) + +- Multimedia: + + - Neural Processing Unit (NPU) + - Image Signal Processor (ISP) + - 2D and 3D acceleration + - HDMI, MIPI-DSI and MIPI-CSI interface + +For more information about the Verdin iMX8M Plus and the i.MX 8M Plus SoC refer to these links: + +- `i.MX 8M Plus Applications Processor page`_ +- `Verdin iMX8M Plus homepage`_ +- `Verdin iMX8M Plus developer page`_ +- `Verdin Development Board developer page`_ +- `Verdin iMX8M Plus Datasheet`_ +- `Verdin Development Board Datasheet`_ + +Supported Features +================== + +The Zephyr verdin_imx8mp_m7 board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| CLOCK | on-chip | clock_control | ++-----------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | GPIO output | +| | | GPIO input | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in the defconfig file: + +- :zephyr_file:`boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7_itcm_defconfig`, if you choose to use + the ITCM memory. + +- :zephyr_file:`boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7_ddr_defconfig`, if you choose to use + the DDR memory. + +It is recommended to disable peripherals used by the M7 core on the Linux host. + +Other hardware features are not currently supported by the port. + +Connections and IOs +=================== + +UART +---- + +Zephyr is configured to use the UART4 by default, which is connected to the FTDI USB converter on +most Toradex carrier boards. + +This is also the UART connected to WiFi/BT chip in modules that have the WiFi/BT chip. Therefore, if +UART4 is used, WiFI/BT will not work properly. + +If the WiFi/BT is needed, then another UART should be used for Zephyr (UART1 for example). You can +change the UART by changing the ``zephyr,console`` and ``zephyr,shell-uart`` in the +:zephyr_file:`boards/arm/verdin_imx8mp_m7_itcm.dts` or +:zephyr_file:`boards/arm/verdin_imx8mp_m7_ddr.dts` file. + ++---------------+-----------------+---------------------------+ +| Board Name | SoC Name | Usage | ++===============+=================+===========================+ +| UART_1 | UART1 | General purpose UART | ++---------------+-----------------+---------------------------+ +| UART_4 | UART4 | Cortex-M4 debug UART | ++---------------+-----------------+---------------------------+ + +GPIO +---- + +All the GPIO banks available are enabled in the :zephyr_file:`dts/arm/nxp/nxp_imx8ml_m7.dtsi`. + +System Clock +============ + +The M7 Core is configured to run at a 800 MHz clock speed. + +Serial Port +=========== + +The i.MX8M Plus SoC has four UARTs. UART_4 is configured for the console and the remaining are not +used/tested. + +Programming and Debugging +************************* + +The Verdin iMX8M Plus board doesn't have QSPI flash for the M7, and it needs to be started by the +A53 core. The A53 core is responsible to load the M7 binary application into the RAM, put the M7 in +reset, set the M7 Program Counter and Stack Pointer, and get the M7 out of reset. The A53 can +perform these steps at bootloader level or after the Linux system has booted. + +The M7 can use up to 3 different RAMs (currently, only two configurations are supported: ITCM and +DDR). These are the memory mapping for A53 and M7: + ++------------+-------------------------+------------------------+-----------------------+----------------------+ +| Region | Cortex-A53 | Cortex-M7 (System Bus) | Cortex-M7 (Code Bus) | Size | ++============+=========================+========================+=======================+======================+ +| OCRAM | 0x00900000-0x0098FFFF | 0x20200000-0x2028FFFF | 0x00900000-0x0098FFFF | 576KB | ++------------+-------------------------+------------------------+-----------------------+----------------------+ +| DTCM | 0x00800000-0x0081FFFF | 0x20000000-0x2001FFFF | | 128KB | ++------------+-------------------------+------------------------+-----------------------+----------------------+ +| ITCM | 0x007E0000-0x007FFFFF | | 0x00000000-0x0001FFFF | 128KB | ++------------+-------------------------+------------------------+-----------------------+----------------------+ +| OCRAM_S | 0x00180000-0x00188FFF | 0x20180000-0x20188FFF | 0x00180000-0x00188FFF | 36KB | ++------------+-------------------------+------------------------+-----------------------+----------------------+ +| DDR | 0x80000000-0x803FFFFF | 0x80200000-0x803FFFFF | 0x80000000-0x801FFFFF | 2MB | ++------------+-------------------------+------------------------+-----------------------+----------------------+ + +For more information about memory mapping see the `i.MX 8M Plus Applications Processor Reference +Manual`_ (section 2.1 to 2.3) + +At compilation time you have to choose which RAM will be used. To facilitate this process, there are +two targets available: + +- ``verdin_imx8mp_m7_itcm``, which uses the ITCM configuration. +- ``verdin_imx8mp_m7_ddr``, which uses the DDR configuration. + + +Starting the Cortex-M7 via U-Boot +================================= + +Load and run Zephyr on M7 from A53 using u-boot by copying the compiled ``zephyr.bin`` to the first +FAT partition of the SD card and plug the SD card into the board. Power it up and stop the u-boot +execution at prompt. + +Load the M7 binary onto the desired memory and start its execution using: + +ITCM +==== + +Loading the binary from an EXT4 partition: + +.. code-block:: shell + + ext4load mmc 2:2 ${loadaddr} //zephyr.bin + cp.b ${loadaddr} 0x7e0000 + bootaux 0x7e0000 + +DDR +=== + +Loading the binary from an EXT4 partition: + +.. code-block:: shell + + ext4load mmc 2:2 ${loadaddr} //zephyr.bin + cp.b ${loadaddr} 0x80000000 + bootaux 0x80000000 + +Debugging +========= + +Toradex Verdin iMX8M Plus SoM can be debugged by connecting an external JLink JTAG debugger to the +X56 debug connector and to the PC, or simply connecting a USB-C to X66 on the Verdin Development +Board. Then, the application can be debugged using the usual way. + +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: verdin_imx8mp_m7_ddr + :goals: debug + +Open a serial terminal, step through the application in your debugger, and you +should see the following message in the terminal: + +.. code-block:: console + + *** Booting Zephyr OS build zephyr-v3.4.0-2300-g03905f7e55d2 *** + Hello World! verdin_imx8mp_m7_ddr + +References +========== + +- `How to Load Compiled Binaries into Cortex-M`_ +- `Cortex-M JTAG Debugging`_ +- `NXP website`_ + +.. _NXP website: + https://www.nxp.com/design/development-boards/i-mx-evaluation-and-development-boards/evaluation-kit-for-the-i-mx-8m-plus-applications-processor:8MPLUSLPD4-EVK + +.. _i.MX 8M Plus Applications Processor Reference Manual: + https://www.nxp.com/webapp/Download?colCode=IMX8MPRM + +.. _How to Load Compiled Binaries into Cortex-M: + https://developer.toradex.com/software/real-time/cortex-m/how-to-load-binaries + +.. _Cortex-M JTAG Debugging: + https://developer.toradex.com/software/real-time/cortex-m/cortexm-jtag-debugging/ + +.. _i.MX 8M Plus Applications Processor page: + https://www.nxp.com/products/processors-and-microcontrollers/arm-processors/i-mx-applications-processors/i-mx-8-applications-processors/i-mx-8m-plus-arm-cortex-a53-machine-learning-vision-multimedia-and-industrial-iot:IMX8MPLUS + +.. _Verdin iMX8M Plus homepage: + https://www.toradex.com/computer-on-modules/verdin-arm-family/nxp-imx-8m-plus + +.. _Verdin iMX8M Plus developer page: + https://developer.toradex.com/hardware/verdin-som-family/modules/verdin-imx8m-plus + +.. _Verdin Development Board developer page: + https://developer.toradex.com/hardware/verdin-som-family/carrier-boards/verdin-development-board/ + +.. _Verdin iMX8M Plus Datasheet: + https://docs.toradex.com/110977-verdin_imx8m_plus_v1.1_datasheet.pdf + +.. _Verdin Development Board Datasheet: + https://docs.toradex.com/109463-verdin_development_board_datasheet_v1.1.pdf diff --git a/boards/arm/verdin_imx8mp_m7/doc/verdin_imx8mp_front.jpg b/boards/arm/verdin_imx8mp_m7/doc/verdin_imx8mp_front.jpg new file mode 100644 index 00000000000..e5089eace4b Binary files /dev/null and b/boards/arm/verdin_imx8mp_m7/doc/verdin_imx8mp_front.jpg differ diff --git a/boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7-pinctrl.dtsi b/boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7-pinctrl.dtsi new file mode 100644 index 00000000000..bb195dc66d0 --- /dev/null +++ b/boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7-pinctrl.dtsi @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Toradex + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + uart1_default: uart1_default { + group0 { + drive-strength = "x1"; + pinmux = <&iomuxc_uart1_rxd_uart_rx_uart1_rx>, + <&iomuxc_uart1_txd_uart_tx_uart1_tx>; + slew-rate = "slow"; + }; + }; + + uart4_default: uart4_default { + group0 { + bias-pull-up; + drive-strength = "x1"; + pinmux = <&iomuxc_uart4_rxd_uart_rx_uart4_rx>, + <&iomuxc_uart4_txd_uart_tx_uart4_tx>; + slew-rate = "slow"; + }; + }; +}; diff --git a/boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7_ddr.dts b/boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7_ddr.dts new file mode 100644 index 00000000000..861077246fd --- /dev/null +++ b/boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7_ddr.dts @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 Toradex + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include "verdin_imx8mp_m7-pinctrl.dtsi" +#include + +/ { + model = "Toradex Verdin iMX8M Plus M7"; + compatible = "nxp,mimx8mp_evk"; + + chosen { + /* DDR */ + zephyr,flash = &ddr_code; + zephyr,sram = &ddr_sys; + + zephyr,console = &uart4; + zephyr,shell-uart = &uart4; + }; +}; + +&gpio3 { + status = "okay"; +}; + +&mailbox0 { + status = "okay"; +}; + +&uart1 { + current-speed = <115200>; + pinctrl-0 = <&uart1_default>; + pinctrl-names = "default"; +}; + +&uart4 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart4_default>; + pinctrl-names = "default"; +}; diff --git a/boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7_ddr.yaml b/boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7_ddr.yaml new file mode 100644 index 00000000000..fc64d8c3db8 --- /dev/null +++ b/boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7_ddr.yaml @@ -0,0 +1,18 @@ +# +# Copyright (c) 2023 Toradex +# +# SPDX-License-Identifier: Apache-2.0 +# + +identifier: verdin_imx8mp_m7_ddr +name: Toradex Verdin iMX8M Plus (DDR) +type: mcu +arch: arm +ram: 2048 +flash: 2048 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - uart diff --git a/boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7_ddr_defconfig b/boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7_ddr_defconfig new file mode 100644 index 00000000000..7c0d4073679 --- /dev/null +++ b/boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7_ddr_defconfig @@ -0,0 +1,16 @@ +# +# Copyright (c) 2023 Toradex +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_SOC_SERIES_IMX8ML_M7=y +CONFIG_SOC_MIMX8ML8=y +CONFIG_BOARD_VERDIN_IMX8MP_M7=y +CONFIG_CLOCK_CONTROL=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_CONSOLE=y +CONFIG_XIP=y +CONFIG_CODE_DDR=y +CONFIG_PINCTRL=y diff --git a/boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7_itcm.dts b/boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7_itcm.dts new file mode 100644 index 00000000000..5744928f8a7 --- /dev/null +++ b/boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7_itcm.dts @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 Toradex + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include "verdin_imx8mp_m7-pinctrl.dtsi" +#include + +/ { + model = "Toradex Verdin iMX8M Plus M7"; + compatible = "nxp,mimx8mp_evk"; + + chosen { + /* TCM */ + zephyr,flash = &itcm; + zephyr,sram = &dtcm; + + zephyr,console = &uart4; + zephyr,shell-uart = &uart4; + }; +}; + +&gpio3 { + status = "okay"; +}; + +&mailbox0 { + status = "okay"; +}; + +&uart1 { + current-speed = <115200>; + pinctrl-0 = <&uart1_default>; + pinctrl-names = "default"; +}; + +&uart4 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart4_default>; + pinctrl-names = "default"; +}; diff --git a/boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7_itcm.yaml b/boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7_itcm.yaml new file mode 100644 index 00000000000..8db4c170c5d --- /dev/null +++ b/boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7_itcm.yaml @@ -0,0 +1,18 @@ +# +# Copyright (c) 2023 Toradex +# +# SPDX-License-Identifier: Apache-2.0 +# + +identifier: verdin_imx8mp_m7_itcm +name: Toradex Verdin iMX8M Plus (ITCM) +type: mcu +arch: arm +ram: 128 +flash: 128 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - uart diff --git a/boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7_itcm_defconfig b/boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7_itcm_defconfig new file mode 100644 index 00000000000..52c354abc1f --- /dev/null +++ b/boards/arm/verdin_imx8mp_m7/verdin_imx8mp_m7_itcm_defconfig @@ -0,0 +1,16 @@ +# +# Copyright (c) 2023 Toradex +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_SOC_SERIES_IMX8ML_M7=y +CONFIG_SOC_MIMX8ML8=y +CONFIG_BOARD_VERDIN_IMX8MP_M7=y +CONFIG_CLOCK_CONTROL=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_CONSOLE=y +CONFIG_XIP=y +CONFIG_CODE_ITCM=y +CONFIG_PINCTRL=y diff --git a/boards/arm/vmu_rt1170/vmu_rt1170-pinctrl.dtsi b/boards/arm/vmu_rt1170/vmu_rt1170-pinctrl.dtsi index 4f9cdf77857..3f27e5c3a33 100644 --- a/boards/arm/vmu_rt1170/vmu_rt1170-pinctrl.dtsi +++ b/boards/arm/vmu_rt1170/vmu_rt1170-pinctrl.dtsi @@ -9,24 +9,6 @@ #include &pinctrl { - - - pinmux_regulator: pinmux_regulator { - group0 { - pinmux = <&iomuxc_gpio_emc_b1_34_gpio_mux2_io02>, - <&iomuxc_gpio_emc_b1_37_gpio_mux2_io05>, - <&iomuxc_gpio_emc_b1_33_gpio_mux2_io01>, - <&iomuxc_gpio_emc_b1_22_gpio_mux1_io22>, - <&iomuxc_gpio_emc_b1_14_gpio_mux1_io14>, - <&iomuxc_gpio_emc_b1_36_gpio_mux2_io04>, - <&iomuxc_gpio_emc_b1_38_gpio_mux2_io06>, - <&iomuxc_gpio_emc_b1_01_gpio_mux1_io01>, - <&iomuxc_gpio_disp_b2_08_gpio_mux5_io09>; - bias-pull-up; - slew-rate = "fast"; - }; - }; - pinmux_enet: pinmux_enet { group0 { pinmux = <&iomuxc_gpio_disp_b2_09_gpio_mux5_io10>, diff --git a/boards/arm/vmu_rt1170/vmu_rt1170.dts b/boards/arm/vmu_rt1170/vmu_rt1170.dts index 0b4298b24df..265fedef389 100644 --- a/boards/arm/vmu_rt1170/vmu_rt1170.dts +++ b/boards/arm/vmu_rt1170/vmu_rt1170.dts @@ -36,8 +36,6 @@ /* This regulator controls VDD_3V3_SD_CARD onboard supply */ reg-3v3-sdcard { - pinctrl-0 = <&pinmux_regulator>; - pinctrl-names = "default"; compatible = "regulator-fixed"; regulator-name = "reg-3v3-sdcard"; enable-gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; @@ -47,8 +45,6 @@ /* This regulator controls VDD_5V_PERIPH onboard supply */ reg-5v-periph { - pinctrl-0 = <&pinmux_regulator>; - pinctrl-names = "default"; compatible = "regulator-fixed"; regulator-name = "reg-5v-periph"; enable-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>; @@ -58,8 +54,6 @@ /* This regulator controls VDD_5V_HIPOWER onboard supply */ reg-5v-hipower { - pinctrl-0 = <&pinmux_regulator>; - pinctrl-names = "default"; compatible = "regulator-fixed"; regulator-name = "reg-5v-hipower"; enable-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>; @@ -69,8 +63,6 @@ /* This regulator controls the VDD_3V3_SENSORS1 onboard supply. */ reg-3v3-sensors-1 { - pinctrl-0 = <&pinmux_regulator>; - pinctrl-names = "default"; compatible = "regulator-fixed"; regulator-name = "reg-3v3-sensors-1"; enable-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>; @@ -81,8 +73,6 @@ /* This regulator controls the VDD_3V3_SENSORS2 onboard supply. */ reg-3v3-sensors-2 { - pinctrl-0 = <&pinmux_regulator>; - pinctrl-names = "default"; compatible = "regulator-fixed"; regulator-name = "reg-3v3-sensors-2"; enable-gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>; @@ -93,8 +83,6 @@ /* This regulator controls the VDD_3V3_SENSORS3 onboard supply. */ reg-3v3-sensors-3 { - pinctrl-0 = <&pinmux_regulator>; - pinctrl-names = "default"; compatible = "regulator-fixed"; regulator-name = "reg-3v3-sensors-3"; enable-gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; @@ -105,8 +93,6 @@ /* This regulator controls the VDD_3V3_SENSORS4 onboard supply. */ reg-3v3-sensors-4 { - pinctrl-0 = <&pinmux_regulator>; - pinctrl-names = "default"; compatible = "regulator-fixed"; regulator-name = "reg-3v3-sensors-4"; enable-gpios = <&gpio2 4 GPIO_ACTIVE_HIGH>; @@ -117,8 +103,6 @@ /* This regulator controls VDD_3V3_SPEKTRUM onboard supply */ reg-3v3-spektrum { - pinctrl-0 = <&pinmux_regulator>; - pinctrl-names = "default"; compatible = "regulator-fixed"; regulator-name = "reg-3v3-spektrum"; enable-gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>; @@ -128,8 +112,6 @@ /* This regulator controls ETH_VDD_3V3 supply to power up the TJA1103 PHY */ reg-eth-power { - pinctrl-0 = <&pinmux_regulator>; - pinctrl-names = "default"; compatible = "regulator-fixed"; regulator-name = "reg-eth-power"; enable-gpios = <&gpio5 9 GPIO_ACTIVE_HIGH>; diff --git a/boards/arm/vmu_rt1170/vmu_rt1170.yaml b/boards/arm/vmu_rt1170/vmu_rt1170.yaml index 0b60cd42e75..2eb4ce0e588 100644 --- a/boards/arm/vmu_rt1170/vmu_rt1170.yaml +++ b/boards/arm/vmu_rt1170/vmu_rt1170.yaml @@ -27,3 +27,4 @@ supported: - spi - usb_device - watchdog +vendor: nxp diff --git a/boards/arm/warp7_m4/warp7_m4.yaml b/boards/arm/warp7_m4/warp7_m4.yaml index 108ce07c600..67ed8dc2745 100644 --- a/boards/arm/warp7_m4/warp7_m4.yaml +++ b/boards/arm/warp7_m4/warp7_m4.yaml @@ -21,3 +21,4 @@ testing: supported: - gpio - i2c +vendor: nxp diff --git a/boards/arm/waveshare_open103z/waveshare_open103z.yaml b/boards/arm/waveshare_open103z/waveshare_open103z.yaml index 82fd93e99e4..c4df844c682 100644 --- a/boards/arm/waveshare_open103z/waveshare_open103z.yaml +++ b/boards/arm/waveshare_open103z/waveshare_open103z.yaml @@ -16,3 +16,4 @@ supported: - watchdog - adc - usb_device +vendor: waveshare diff --git a/boards/arm/we_ophelia1ev_nrf52805/we_ophelia1ev_nrf52805.yaml b/boards/arm/we_ophelia1ev_nrf52805/we_ophelia1ev_nrf52805.yaml index 68fb1650d52..b0697278931 100644 --- a/boards/arm/we_ophelia1ev_nrf52805/we_ophelia1ev_nrf52805.yaml +++ b/boards/arm/we_ophelia1ev_nrf52805/we_ophelia1ev_nrf52805.yaml @@ -16,3 +16,4 @@ supported: - i2c - spi - uart +vendor: we diff --git a/boards/arm/we_ophelia1ev_nrf52805/we_ophelia1ev_nrf52805_defconfig b/boards/arm/we_ophelia1ev_nrf52805/we_ophelia1ev_nrf52805_defconfig index 88c4ddb2023..b81a1a35e4e 100644 --- a/boards/arm/we_ophelia1ev_nrf52805/we_ophelia1ev_nrf52805_defconfig +++ b/boards/arm/we_ophelia1ev_nrf52805/we_ophelia1ev_nrf52805_defconfig @@ -23,5 +23,3 @@ CONFIG_UART_CONSOLE=y # Use internal oscillator CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/we_proteus2ev_nrf52832/we_proteus2ev_nrf52832.yaml b/boards/arm/we_proteus2ev_nrf52832/we_proteus2ev_nrf52832.yaml index 1e1e4267143..4cc87992655 100644 --- a/boards/arm/we_proteus2ev_nrf52832/we_proteus2ev_nrf52832.yaml +++ b/boards/arm/we_proteus2ev_nrf52832/we_proteus2ev_nrf52832.yaml @@ -17,3 +17,4 @@ supported: - i2c - pwm - spi +vendor: we diff --git a/boards/arm/we_proteus2ev_nrf52832/we_proteus2ev_nrf52832_defconfig b/boards/arm/we_proteus2ev_nrf52832/we_proteus2ev_nrf52832_defconfig index 249c4a8e394..0b4e298d05a 100644 --- a/boards/arm/we_proteus2ev_nrf52832/we_proteus2ev_nrf52832_defconfig +++ b/boards/arm/we_proteus2ev_nrf52832/we_proteus2ev_nrf52832_defconfig @@ -26,5 +26,3 @@ CONFIG_UART_CONSOLE=y # Use internal oscillator CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/we_proteus3ev_nrf52840/we_proteus3ev_nrf52840.yaml b/boards/arm/we_proteus3ev_nrf52840/we_proteus3ev_nrf52840.yaml index 12fc336500e..544029d3d9c 100644 --- a/boards/arm/we_proteus3ev_nrf52840/we_proteus3ev_nrf52840.yaml +++ b/boards/arm/we_proteus3ev_nrf52840/we_proteus3ev_nrf52840.yaml @@ -17,3 +17,4 @@ supported: - gpio - i2c - spi +vendor: we diff --git a/boards/arm/we_proteus3ev_nrf52840/we_proteus3ev_nrf52840_defconfig b/boards/arm/we_proteus3ev_nrf52840/we_proteus3ev_nrf52840_defconfig index cca27094e6a..a7687b6b541 100644 --- a/boards/arm/we_proteus3ev_nrf52840/we_proteus3ev_nrf52840_defconfig +++ b/boards/arm/we_proteus3ev_nrf52840/we_proteus3ev_nrf52840_defconfig @@ -26,5 +26,3 @@ CONFIG_UART_CONSOLE=y # Use internal oscillator CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/weact_stm32g431_core/Kconfig.board b/boards/arm/weact_stm32g431_core/Kconfig.board new file mode 100644 index 00000000000..9886fd64702 --- /dev/null +++ b/boards/arm/weact_stm32g431_core/Kconfig.board @@ -0,0 +1,9 @@ +# +# Copyright (c) 2023 Andreas Sandberg +# +# SPDX-License-Identifier: Apache-2.0 +# + +config BOARD_WEACT_STM32G431_CORE + bool "WeAct Studio STM32G431 Core Board" + depends on SOC_STM32G431XX diff --git a/boards/arm/weact_stm32g431_core/Kconfig.defconfig b/boards/arm/weact_stm32g431_core/Kconfig.defconfig new file mode 100644 index 00000000000..25d65455013 --- /dev/null +++ b/boards/arm/weact_stm32g431_core/Kconfig.defconfig @@ -0,0 +1,12 @@ +# +# Copyright (c) 2023 Andreas Sandberg +# +# SPDX-License-Identifier: Apache-2.0 +# + +if BOARD_WEACT_STM32G431_CORE + +config BOARD + default "weact_stm32g431_core" + +endif diff --git a/boards/arm/weact_stm32g431_core/board.cmake b/boards/arm/weact_stm32g431_core/board.cmake new file mode 100644 index 00000000000..5ef1ab31d07 --- /dev/null +++ b/boards/arm/weact_stm32g431_core/board.cmake @@ -0,0 +1,11 @@ +# +# Copyright (c) 2023 Andreas Sandberg +# +# SPDX-License-Identifier: Apache-2.0 +# + +board_runner_args(dfu-util "--pid=0483:df11" "--alt=0" "--dfuse") + +include(${ZEPHYR_BASE}/boards/common/dfu-util.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/blackmagicprobe.board.cmake) diff --git a/boards/arm/weact_stm32g431_core/doc/index.rst b/boards/arm/weact_stm32g431_core/doc/index.rst new file mode 100644 index 00000000000..2d367ba2808 --- /dev/null +++ b/boards/arm/weact_stm32g431_core/doc/index.rst @@ -0,0 +1,147 @@ +.. _weact_stm32g431_core: + +WeAct Studio STM32G431 Core Board +################################# + +The WeAct STM32G431 Core Board is a low-cost bare-bones STM32G431-based development +board. See the `STM32G431CB website`_ for more information about the MCU. More information +about the board, including schematics, is available from the `WeAct GitHub`_. + +Modifications USB-C Power Delivery +********************************** + +The board does not support USB-C PD in its standard configuration. To enable USB-C PD, CC1 +and CC2 need to be disconnected from their pull-down resistors and be connected to PB6 and +PB4 respectively. Dead battery support requires PA9 and PA10 to be routed to CC1 and +CC2. VBUS also needs to be connected to the MCU through a voltage divider. + +The pull-downs are disconnected by removing the zero-Ohm resistors on SB8 and SB9 next to +the USB-C connector. SB3, SB5, SB6, and SB7 then need to be closed to connect the CCx +lines to the MCU. The voltage divider is connected to PB2 by closing SB4. + +After these modifications have been made, PA9, PA10, PB2, PB4, and PB6 should be +considered reserved for USB-C and not available for other applications. + +.. warning:: + The internal USB DFU boot loader may not work correctly with machines that respect USB + PD signaling unless dead battery support has been enabled. A USB-C to USB-A adapter or + programming using the SWD port can be used as a workaround. + + +Supported Features +================== + +The Zephyr weact_stm32g431_core board configuration supports the following hardware +features: + ++------------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++============+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++------------+------------+-------------------------------------+ +| UART | on-chip | serial port | ++------------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++------------+------------+-------------------------------------+ +| ADC | on-chip | ADC Controller | ++------------+------------+-------------------------------------+ +| USB | on-chip | USB device | ++------------+------------+-------------------------------------+ +| UCPD | on-chip | ucpd | ++------------+------------+-------------------------------------+ + +The default configuration can be found in the defconfig file: + + ``boards/arm/weact_stm32g431_core/weact_stm32g431_core_defconfig`` + +Pin Mapping +=========== + +Default Zephyr Peripheral Mapping: +---------------------------------- + +- UART_2 TX/RX : PA2/PA3 +- UCPD1 CCx : PB6/PB4 (not connected by default) +- UCPD1 DBCCx : PA9/PA10 (not connected by default) +- BUTTON (User) : PC13 +- BUTTON (BOOT0) : PB8 +- LED0 : PC6 +- ADC (VBUS) : PB2 + +The ADC is disabled by default since the VBUS voltage divider is not connected in the +board's standard configuration. + + +Hardware Configuration +---------------------- ++---------------+---------+-----------------------------------------------+ +| Solder bridge | Default | Description | ++===============+=========+===============================================+ +| SB1/SB2 | Open | Route PC14/PC15 (LSE) to header | ++---------------+---------+-----------------------------------------------+ +| SB6/SB7 | Open | Connect PB4/PB6 (UCPD1_CCx) to USB-C CCx pins | ++---------------+---------+-----------------------------------------------+ +| SB3/SB5 | Open | Connect PA9/PA10 (UCPD1_DBCCx) to to PB6/PB4 | ++---------------+---------+-----------------------------------------------+ +| SB4 | Open | Connect PB2 to VBUS voltage divider | ++---------------+---------+-----------------------------------------------+ +| SB8/SB9 | Closed | Connect USB-CCx to pull-down resistors | ++---------------+---------+-----------------------------------------------+ +| SB10 | Open | VBUS protection diode bypass | ++---------------+---------+-----------------------------------------------+ + + +Clock Sources +------------- + +The board has two external oscillators. The frequency of the slow clock (LSE) is 32.768 +kHz. The frequency of the main clock (HSE) is 8 MHz. + +The default configuration sources the system clock from the PLL, which is derived from +HSE, and is set at 144 MHz. The 48 MHz clock used by the USB interface is derived from the +PLL instead of the internal 48 MHz oscillator. + +Programming and Debugging +************************* + +The MCU is normally programmed using the ROM bootloader or the exposed SWD port. + +Please note that some laptops may not detect the ROM bootloader correctly if the CCx +pull-downs have been disconnected by opening SB8 and SB9 unless dead battery support has +been enabled by closing SB3 and SB5. A USB-C to USB-A adapter can be used as a workaround +if this is a problem. + +Flashing an Application +======================= + +Connect a USB-C cable and the board should power ON. Force the board into DFU mode by +keeping the BOOT0 switch pressed while pressing and releasing the NRST switch. + +The dfu-util runner is supported on this board and so a sample can be built and tested +easily. + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: weact_stm32g431_core + :goals: build flash + +Debugging +========= + +The board can be debugged by installing the included 100 mil (0.1 inch) header, and +attaching an SWD debugger to the 3V3 (3.3V), GND, SCK, and DIO pins on that header. + + +References +********** + +.. target-notes:: + +.. _WeAct GitHub: + https://github.com/WeActStudio/WeActStudio.STM32G431CoreBoard + +.. _STM32G431CB website: + https://www.st.com/en/microcontrollers-microprocessors/stm32g431cb.html + +.. _STM32F401x reference manual: + https://www.st.com/resource/en/reference_manual/rm0440-stm32g4-series-advanced-armbased-32bit-mcus-stmicroelectronics.pdf diff --git a/boards/arm/weact_stm32g431_core/support/openocd.cfg b/boards/arm/weact_stm32g431_core/support/openocd.cfg new file mode 100644 index 00000000000..d936f7d3534 --- /dev/null +++ b/boards/arm/weact_stm32g431_core/support/openocd.cfg @@ -0,0 +1,7 @@ +source [find interface/stlink.cfg] + +transport select hla_swd + +source [find target/stm32g4x.cfg] + +reset_config srst_only diff --git a/boards/arm/weact_stm32g431_core/weact_stm32g431_core.dts b/boards/arm/weact_stm32g431_core/weact_stm32g431_core.dts new file mode 100644 index 00000000000..cdfe959b3fd --- /dev/null +++ b/boards/arm/weact_stm32g431_core/weact_stm32g431_core.dts @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2023 Andreas Sandberg + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include +#include + +/ { + model = "WeAct Studio STM32G431 Core Board"; + compatible = "weact,stm32g431-core"; + + chosen { + zephyr,console = &usart2; + zephyr,shell-uart = &usart2; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + aliases { + led0 = &led_0; + mcuboot-button0 = &button_0; + mcuboot-led0 = &led_0; + sw0 = &button_0; + sw1 = &button_1; + usbc-port0 = &usbc1; + watchdog0 = &iwdg; + }; + + leds { + compatible = "gpio-leds"; + led_0: led0 { + gpios = <&gpioc 6 GPIO_ACTIVE_HIGH>; + label = "Status LED"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + button_0: button0 { + label = "User"; + gpios = <&gpioc 13 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; + zephyr,code = ; + }; + button_1: button1 { + label = "Boot0"; + gpios = <&gpiob 8 GPIO_ACTIVE_HIGH>; + zephyr,code = ; + }; + }; + + vbus1: vbus { + compatible = "zephyr,usb-c-vbus-adc"; + status = "disabled"; + io-channels = <&adc2 12>; + output-ohms = <10000>; + full-ohms = <(100000 + 10000)>; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + usbc1: usbc-port@1 { + compatible = "usb-c-connector"; + status = "disabled"; + reg = <1>; + tcpc = <&ucpd1>; + vbus = <&vbus1>; + data-role = "device"; + power-role = "sink"; + sink-pdos = ; + }; + }; +}; + +&clk_lsi { + status = "okay"; +}; + +&clk_lse { + status = "okay"; +}; + +&clk_hsi { + status = "disabled"; +}; + +&clk_hse { + status = "okay"; + clock-frequency = ; +}; + +&rcc { + clocks = <&pll>; + clock-frequency = ; + ahb-prescaler = <1>; + apb1-prescaler = <1>; + apb2-prescaler = <1>; +}; + +&pll { + status = "okay"; + div-m = <2>; + mul-n = <72>; + div-p = <2>; + div-q = <6>; + div-r = <2>; + clocks = <&clk_hse>; +}; + +&rtc { + status = "okay"; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; +}; + +&lptim1 { + status = "okay"; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x80000000>, + <&rcc STM32_SRC_LSE LPTIM1_SEL(3)>; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* 4KiB of storage at the end of the 128KiB FLASH */ + storage_partition: partition@1f000 { + label = "storage"; + reg = <0x0001f000 DT_SIZE_K(4)>; + }; + }; +}; + +&iwdg { + status = "okay"; +}; + +&usart2 { + status = "okay"; + pinctrl-0 = <&usart2_tx_pa2 &usart2_rx_pa3>; + pinctrl-names = "default"; + + current-speed = <115200>; +}; + +&adc2 { + pinctrl-0 = <&adc2_in12_pb2>; + pinctrl-names = "default"; + st,adc-clock-source = ; + st,adc-prescaler = <4>; + + #address-cells = <1>; + #size-cells = <0>; + + channel@c { + reg = <12>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + zephyr,vref-mv = <3300>; + }; +}; + +&ucpd1 { + psc-ucpdclk = <1>; + hbitclkdiv = <27>; + pinctrl-0 = <&ucpd1_cc1_pb6 &ucpd1_cc2_pb4>; + pinctrl-names = "default"; +}; + +zephyr_udc0: &usb { + pinctrl-0 = <&usb_dm_pa11 &usb_dp_pa12>; + pinctrl-names = "default"; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00800000>, + <&rcc STM32_SRC_PLL_Q CLK48_SEL(2)>; + status = "okay"; +}; diff --git a/boards/arm/weact_stm32g431_core/weact_stm32g431_core.yaml b/boards/arm/weact_stm32g431_core/weact_stm32g431_core.yaml new file mode 100644 index 00000000000..91886ad0ea5 --- /dev/null +++ b/boards/arm/weact_stm32g431_core/weact_stm32g431_core.yaml @@ -0,0 +1,20 @@ +identifier: weact_stm32g431_core +name: WeAct Studio STM32G431 Core Board +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +ram: 32 +flash: 128 +supported: + - counter + - gpio + - nvs + - pinctrl + - tcpc + - uart + - usb_device + - watchdog +vendor: weact diff --git a/boards/arm/weact_stm32g431_core/weact_stm32g431_core_defconfig b/boards/arm/weact_stm32g431_core/weact_stm32g431_core_defconfig new file mode 100644 index 00000000000..aa9e67db821 --- /dev/null +++ b/boards/arm/weact_stm32g431_core/weact_stm32g431_core_defconfig @@ -0,0 +1,24 @@ +# +# Copyright (c) 2023 Andreas Sandberg +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_SOC_SERIES_STM32G4X=y +CONFIG_SOC_STM32G431XX=y + +CONFIG_CLOCK_CONTROL=y +CONFIG_PINCTRL=y + +# LSE defined as LPTIM clock source by the DTS +CONFIG_STM32_LPTIM_CLOCK_LSE=y + +CONFIG_ARM_MPU=y +CONFIG_HW_STACK_PROTECTION=y + +CONFIG_GPIO=y + +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y diff --git a/boards/arm/wio_terminal/Kconfig.defconfig b/boards/arm/wio_terminal/Kconfig.defconfig index a8974dbd566..cca0d78a232 100644 --- a/boards/arm/wio_terminal/Kconfig.defconfig +++ b/boards/arm/wio_terminal/Kconfig.defconfig @@ -6,3 +6,6 @@ config BOARD default "wio_terminal" depends on BOARD_WIO_TERMINAL + +config LV_COLOR_16_SWAP + default y if LVGL diff --git a/boards/arm/wio_terminal/doc/index.rst b/boards/arm/wio_terminal/doc/index.rst index 5ccd90061c2..4b11a461323 100644 --- a/boards/arm/wio_terminal/doc/index.rst +++ b/boards/arm/wio_terminal/doc/index.rst @@ -122,7 +122,7 @@ USB Device Port The SAMD51 MCU has a USB device port that can be used to communicate with a host PC. See the :ref:`usb-samples` sample applications for more, such as the -:ref:`usb_cdc-acm` sample which sets up a virtual serial port that echos +:zephyr:code-sample:`usb-cdc-acm` sample which sets up a virtual serial port that echos characters back to the host PC. Programming and Debugging @@ -180,7 +180,8 @@ debugged using an SWD probe such as the Segger J-Link. .. zephyr-app-commands:: :zephyr-app: samples/basic/button :board: wio_terminal - :goals: flash -r openocd + :goals: flash + :flash-args: -r openocd :compact: #. Start debugging: diff --git a/boards/arm/wio_terminal/wio_terminal.yaml b/boards/arm/wio_terminal/wio_terminal.yaml index 3612a32d33b..e78e041719b 100644 --- a/boards/arm/wio_terminal/wio_terminal.yaml +++ b/boards/arm/wio_terminal/wio_terminal.yaml @@ -19,3 +19,4 @@ supported: - usb_cdc - usb_device - watchdog +vendor: seeed diff --git a/boards/arm/xiao_ble/board.cmake b/boards/arm/xiao_ble/board.cmake index 67f5aee98e4..a6aa2ac40a7 100644 --- a/boards/arm/xiao_ble/board.cmake +++ b/boards/arm/xiao_ble/board.cmake @@ -9,3 +9,4 @@ include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) include(${ZEPHYR_BASE}/boards/common/uf2.board.cmake) +include(${ZEPHYR_BASE}/boards/common/blackmagicprobe.board.cmake) diff --git a/boards/arm/xiao_ble/doc/index.rst b/boards/arm/xiao_ble/doc/index.rst index 9966f913644..d4d4266311b 100644 --- a/boards/arm/xiao_ble/doc/index.rst +++ b/boards/arm/xiao_ble/doc/index.rst @@ -112,8 +112,8 @@ necessary software. Flashing -------- -Follow the instructions in the :ref:`jlink-external-debug-probe` page to install -and configure all the necessary software. Then build and flash applications as +Setup and connect a supported debug probe (JLink, instructions at :ref:`jlink-external-debug-probe` or +BlackMagic Probe). Then build and flash applications as usual (see :ref:`build_an_application` and :ref:`application_run` for more details). @@ -156,6 +156,8 @@ Debugging Refer to the :ref:`jlink-external-debug-probe` page to learn about debugging boards with a Segger IC. +Debugging using a BlackMagic Probe is also supported. + Testing the LEDs in the XIAO BLE (Sense) **************************************** diff --git a/boards/arm/xiao_ble/xiao_ble.yaml b/boards/arm/xiao_ble/xiao_ble.yaml index e1156429c84..f8dfa743a86 100644 --- a/boards/arm/xiao_ble/xiao_ble.yaml +++ b/boards/arm/xiao_ble/xiao_ble.yaml @@ -21,3 +21,4 @@ supported: - usb_device - watchdog - netif:openthread +vendor: seeed diff --git a/boards/arm/xiao_ble/xiao_ble_defconfig b/boards/arm/xiao_ble/xiao_ble_defconfig index 6b6aa3168ec..59471d3d22a 100644 --- a/boards/arm/xiao_ble/xiao_ble_defconfig +++ b/boards/arm/xiao_ble/xiao_ble_defconfig @@ -28,5 +28,3 @@ CONFIG_USB_DEVICE_STACK=y # Build UF2 by default, supported by the Adafruit nRF52 Bootloader CONFIG_BUILD_OUTPUT_UF2=y CONFIG_USE_DT_CODE_PARTITION=y - -CONFIG_PINCTRL=y diff --git a/boards/arm/xiao_ble/xiao_ble_sense.yaml b/boards/arm/xiao_ble/xiao_ble_sense.yaml index a27be3dc1bd..7d11907651a 100644 --- a/boards/arm/xiao_ble/xiao_ble_sense.yaml +++ b/boards/arm/xiao_ble/xiao_ble_sense.yaml @@ -21,3 +21,4 @@ supported: - usb_device - watchdog - netif:openthread +vendor: seeed diff --git a/boards/arm/xiao_ble/xiao_ble_sense_defconfig b/boards/arm/xiao_ble/xiao_ble_sense_defconfig index 269f6f7915b..73878352edd 100644 --- a/boards/arm/xiao_ble/xiao_ble_sense_defconfig +++ b/boards/arm/xiao_ble/xiao_ble_sense_defconfig @@ -29,7 +29,5 @@ CONFIG_USB_DEVICE_STACK=y CONFIG_BUILD_OUTPUT_UF2=y CONFIG_USE_DT_CODE_PARTITION=y -CONFIG_PINCTRL=y - # required to enable LSM6DS3TR-C power CONFIG_REGULATOR=y diff --git a/boards/arm/xmc45_relax_kit/doc/index.rst b/boards/arm/xmc45_relax_kit/doc/index.rst index 17669cedcbe..7a54abfe37a 100644 --- a/boards/arm/xmc45_relax_kit/doc/index.rst +++ b/boards/arm/xmc45_relax_kit/doc/index.rst @@ -55,6 +55,8 @@ The Relax Kit development board configuration supports the following hardware fe +-----------+------------+-----------------------+ | PWM | on-chip | pwm | +-----------+------------+-----------------------+ +| WATCHDOG | on-chip | watchdog | ++-----------+------------+-----------------------+ More details about the supported peripherals are available in `XMC4500 TRM`_ Other hardware features are not currently supported by the Zephyr kernel. diff --git a/boards/arm/xmc45_relax_kit/xmc45_relax_kit.dts b/boards/arm/xmc45_relax_kit/xmc45_relax_kit.dts index a6fe5e5942c..cebeb2deffe 100644 --- a/boards/arm/xmc45_relax_kit/xmc45_relax_kit.dts +++ b/boards/arm/xmc45_relax_kit/xmc45_relax_kit.dts @@ -22,6 +22,7 @@ led0 = &led1; die-temp0 = &die_temp; pwm-led0 = &pwm_led1; + watchdog0 = &wdt0; }; leds { @@ -57,6 +58,16 @@ }; }; +&psram1 { + compatible = "zephyr,memory-region", "mmio-sram"; + zephyr,memory-region = "PSRAM1"; +}; + +&dsram2 { + compatible = "zephyr,memory-region", "mmio-sram"; + zephyr,memory-region = "DSRAM2"; +}; + &flash_controller { status = "okay"; }; diff --git a/boards/arm/xmc45_relax_kit/xmc45_relax_kit.yaml b/boards/arm/xmc45_relax_kit/xmc45_relax_kit.yaml index 035c48e7d62..b84e29973a7 100644 --- a/boards/arm/xmc45_relax_kit/xmc45_relax_kit.yaml +++ b/boards/arm/xmc45_relax_kit/xmc45_relax_kit.yaml @@ -12,5 +12,7 @@ supported: - gpio - spi - uart + - watchdog ram: 160 flash: 1024 +vendor: infineon diff --git a/boards/arm/xmc47_relax_kit/doc/index.rst b/boards/arm/xmc47_relax_kit/doc/index.rst index fea191f4c30..cbf5eb7a5f3 100644 --- a/boards/arm/xmc47_relax_kit/doc/index.rst +++ b/boards/arm/xmc47_relax_kit/doc/index.rst @@ -58,6 +58,8 @@ The Relax Kit development board configuration supports the following hardware fe +-----------+------------+-----------------------+ | PWM | on-chip | pwm | +-----------+------------+-----------------------+ +| WATCHDOG | on-chip | watchdog | ++-----------+------------+-----------------------+ More details about the supported peripherals are available in `XMC4700 TRM`_ Other hardware features are not currently supported by the Zephyr kernel. diff --git a/boards/arm/xmc47_relax_kit/xmc47_relax_kit.dts b/boards/arm/xmc47_relax_kit/xmc47_relax_kit.dts index 71f6ce2d536..7f1b8f68a38 100644 --- a/boards/arm/xmc47_relax_kit/xmc47_relax_kit.dts +++ b/boards/arm/xmc47_relax_kit/xmc47_relax_kit.dts @@ -21,6 +21,7 @@ led0 = &led1; die-temp0 = &die_temp; pwm-led0 = &pwm_led1; + watchdog0 = &wdt0; }; leds { diff --git a/boards/arm/xmc47_relax_kit/xmc47_relax_kit.yaml b/boards/arm/xmc47_relax_kit/xmc47_relax_kit.yaml index d1b96e3635b..d88826ab4ef 100644 --- a/boards/arm/xmc47_relax_kit/xmc47_relax_kit.yaml +++ b/boards/arm/xmc47_relax_kit/xmc47_relax_kit.yaml @@ -14,5 +14,7 @@ supported: - uart - arduino_spi - arduino_serial + - watchdog ram: 352 flash: 2048 +vendor: infineon diff --git a/boards/arm/zybo/zybo.yaml b/boards/arm/zybo/zybo.yaml index 24054386106..573fb74f666 100644 --- a/boards/arm/zybo/zybo.yaml +++ b/boards/arm/zybo/zybo.yaml @@ -12,3 +12,4 @@ toolchain: ram: 524288 supported: - gpio +vendor: digilent diff --git a/boards/arm64/bcm958402m2_a72/bcm958402m2_a72.yaml b/boards/arm64/bcm958402m2_a72/bcm958402m2_a72.yaml index 08d49c3cf59..d59dd34439c 100644 --- a/boards/arm64/bcm958402m2_a72/bcm958402m2_a72.yaml +++ b/boards/arm64/bcm958402m2_a72/bcm958402m2_a72.yaml @@ -5,3 +5,4 @@ arch: arm64 toolchain: - zephyr - cross-compile +vendor: brcm diff --git a/boards/arm64/fvp_base_revc_2xaemv8a/doc/index.rst b/boards/arm64/fvp_base_revc_2xaemv8a/doc/index.rst index 224fbd95960..495b7ad11f4 100644 --- a/boards/arm64/fvp_base_revc_2xaemv8a/doc/index.rst +++ b/boards/arm64/fvp_base_revc_2xaemv8a/doc/index.rst @@ -72,7 +72,7 @@ Programming =========== Use this configuration to build basic Zephyr applications and kernel tests in the -ARM FVP emulated environment, for example, with the :ref:`synchronization_sample`: +ARM FVP emulated environment, for example, with the :zephyr:code-sample:`synchronization` sample: .. zephyr-app-commands:: :zephyr-app: samples/synchronization diff --git a/boards/arm64/fvp_base_revc_2xaemv8a/fvp_base_revc_2xaemv8a.dts b/boards/arm64/fvp_base_revc_2xaemv8a/fvp_base_revc_2xaemv8a.dts index 373c9b88fa2..3a6ff898bf2 100644 --- a/boards/arm64/fvp_base_revc_2xaemv8a/fvp_base_revc_2xaemv8a.dts +++ b/boards/arm64/fvp_base_revc_2xaemv8a/fvp_base_revc_2xaemv8a.dts @@ -146,11 +146,13 @@ mdio: mdio { compatible = "smsc,lan91c111-mdio"; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; - phy: phy { + phy: ethernet-phy@0 { compatible = "ethernet-phy"; status = "disabled"; - address = <0>; + reg = <0>; }; }; }; diff --git a/boards/arm64/fvp_base_revc_2xaemv8a/fvp_base_revc_2xaemv8a.yaml b/boards/arm64/fvp_base_revc_2xaemv8a/fvp_base_revc_2xaemv8a.yaml index c7035277efc..ce4bdb8a5f1 100644 --- a/boards/arm64/fvp_base_revc_2xaemv8a/fvp_base_revc_2xaemv8a.yaml +++ b/boards/arm64/fvp_base_revc_2xaemv8a/fvp_base_revc_2xaemv8a.yaml @@ -10,3 +10,4 @@ toolchain: - cross-compile ram: 2048 flash: 64 +vendor: arm diff --git a/boards/arm64/fvp_base_revc_2xaemv8a/fvp_base_revc_2xaemv8a_smp_ns.yaml b/boards/arm64/fvp_base_revc_2xaemv8a/fvp_base_revc_2xaemv8a_smp_ns.yaml index 00baea468fd..68ef6a664e8 100644 --- a/boards/arm64/fvp_base_revc_2xaemv8a/fvp_base_revc_2xaemv8a_smp_ns.yaml +++ b/boards/arm64/fvp_base_revc_2xaemv8a/fvp_base_revc_2xaemv8a_smp_ns.yaml @@ -10,3 +10,4 @@ toolchain: - cross-compile ram: 2048 flash: 64 +vendor: arm diff --git a/boards/arm64/fvp_baser_aemv8r/doc/index.rst b/boards/arm64/fvp_baser_aemv8r/doc/index.rst index 862e574715b..3c45ce22840 100644 --- a/boards/arm64/fvp_baser_aemv8r/doc/index.rst +++ b/boards/arm64/fvp_baser_aemv8r/doc/index.rst @@ -86,7 +86,7 @@ Programming =========== Use this configuration to build basic Zephyr applications and kernel tests in the -Arm FVP emulated environment, for example, with the :ref:`synchronization_sample`: +Arm FVP emulated environment, for example, with the :zephyr:code-sample:`synchronization` sample: .. zephyr-app-commands:: :zephyr-app: samples/synchronization diff --git a/boards/arm64/fvp_baser_aemv8r/fvp_baser_aemv8r.dts b/boards/arm64/fvp_baser_aemv8r/fvp_baser_aemv8r.dts index eb49a3e3856..727e7b5d7a2 100644 --- a/boards/arm64/fvp_baser_aemv8r/fvp_baser_aemv8r.dts +++ b/boards/arm64/fvp_baser_aemv8r/fvp_baser_aemv8r.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include / { model = "FVP BaseR AEMv8R"; @@ -41,7 +42,7 @@ compatible = "zephyr,memory-region", "mmio-dram"; reg = <0x9a000000 0x66000000>; zephyr,memory-region = "DEVICE_REGION"; - zephyr,memory-attr = "IO"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; }; }; }; diff --git a/boards/arm64/fvp_baser_aemv8r/fvp_baser_aemv8r.yaml b/boards/arm64/fvp_baser_aemv8r/fvp_baser_aemv8r.yaml index b9d67b6a27f..840fa70e5c9 100644 --- a/boards/arm64/fvp_baser_aemv8r/fvp_baser_aemv8r.yaml +++ b/boards/arm64/fvp_baser_aemv8r/fvp_baser_aemv8r.yaml @@ -12,3 +12,4 @@ ram: 2048 flash: 64 testing: timeout_multiplier: 8 +vendor: arm diff --git a/boards/arm64/fvp_baser_aemv8r/fvp_baser_aemv8r_smp.yaml b/boards/arm64/fvp_baser_aemv8r/fvp_baser_aemv8r_smp.yaml index 97d0d6dc8c0..1e0dfa4a9b2 100644 --- a/boards/arm64/fvp_baser_aemv8r/fvp_baser_aemv8r_smp.yaml +++ b/boards/arm64/fvp_baser_aemv8r/fvp_baser_aemv8r_smp.yaml @@ -14,3 +14,4 @@ supported: - smp testing: timeout_multiplier: 20 +vendor: arm diff --git a/boards/arm64/intel_socfpga_agilex5_socdk/intel_socfpga_agilex5_socdk.yaml b/boards/arm64/intel_socfpga_agilex5_socdk/intel_socfpga_agilex5_socdk.yaml index 22f713dea09..1548281bd9b 100644 --- a/boards/arm64/intel_socfpga_agilex5_socdk/intel_socfpga_agilex5_socdk.yaml +++ b/boards/arm64/intel_socfpga_agilex5_socdk/intel_socfpga_agilex5_socdk.yaml @@ -5,3 +5,4 @@ arch: arm64 toolchain: - zephyr - cross-compile +vendor: intel diff --git a/boards/arm64/intel_socfpga_agilex_socdk/intel_socfpga_agilex_socdk.yaml b/boards/arm64/intel_socfpga_agilex_socdk/intel_socfpga_agilex_socdk.yaml index 775ab2774de..b3b01f1b494 100644 --- a/boards/arm64/intel_socfpga_agilex_socdk/intel_socfpga_agilex_socdk.yaml +++ b/boards/arm64/intel_socfpga_agilex_socdk/intel_socfpga_agilex_socdk.yaml @@ -5,3 +5,4 @@ arch: arm64 toolchain: - zephyr - cross-compile +vendor: intel diff --git a/boards/arm64/khadas_edgev/khadas_edgev.yaml b/boards/arm64/khadas_edgev/khadas_edgev.yaml index a8805daa362..6d1fb7a533c 100644 --- a/boards/arm64/khadas_edgev/khadas_edgev.yaml +++ b/boards/arm64/khadas_edgev/khadas_edgev.yaml @@ -6,3 +6,4 @@ toolchain: - zephyr - cross-compile ram: 8192 +vendor: khadas diff --git a/boards/arm64/mimx8mm_evk/doc/index.rst b/boards/arm64/mimx8mm_evk/doc/index.rst index aa82dbdda83..947abd2ba2a 100644 --- a/boards/arm64/mimx8mm_evk/doc/index.rst +++ b/boards/arm64/mimx8mm_evk/doc/index.rst @@ -92,7 +92,7 @@ Or kick SMP zephyr.bin: Use this configuration to run basic Zephyr applications and kernel tests, -for example, with the :ref:`synchronization_sample`: +for example, with the :zephyr:code-sample:`synchronization` sample: .. zephyr-app-commands:: :zephyr-app: samples/synchronization diff --git a/boards/arm64/mimx8mm_evk/mimx8mm_evk_a53.yaml b/boards/arm64/mimx8mm_evk/mimx8mm_evk_a53.yaml index 2e09f841320..72295bdb7eb 100644 --- a/boards/arm64/mimx8mm_evk/mimx8mm_evk_a53.yaml +++ b/boards/arm64/mimx8mm_evk/mimx8mm_evk_a53.yaml @@ -10,3 +10,4 @@ testing: ignore_tags: - net - bluetooth +vendor: fsl diff --git a/boards/arm64/mimx8mm_evk/mimx8mm_evk_a53_smp.yaml b/boards/arm64/mimx8mm_evk/mimx8mm_evk_a53_smp.yaml index 459cadedcea..b6a23c923e0 100644 --- a/boards/arm64/mimx8mm_evk/mimx8mm_evk_a53_smp.yaml +++ b/boards/arm64/mimx8mm_evk/mimx8mm_evk_a53_smp.yaml @@ -12,3 +12,4 @@ testing: ignore_tags: - net - bluetooth +vendor: fsl diff --git a/boards/arm64/mimx8mn_evk/doc/index.rst b/boards/arm64/mimx8mn_evk/doc/index.rst index 4e7497b672e..b9620176b6e 100644 --- a/boards/arm64/mimx8mn_evk/doc/index.rst +++ b/boards/arm64/mimx8mn_evk/doc/index.rst @@ -7,7 +7,7 @@ Overview ******** i.MX8M Nano LPDDR4 EVK board is based on NXP i.MX8M Nano applications -processor, composed of a quad Cortex®-A53 cluster and a single Cortex®-M47 core. +processor, composed of a quad Cortex®-A53 cluster and a single Cortex®-M7 core. Zephyr OS is ported to run on the Cortex®-A53 core. - Board features: @@ -92,7 +92,7 @@ Or kick SMP zephyr.bin: Use this configuration to run basic Zephyr applications and kernel tests, -for example, with the :ref:`synchronization_sample`: +for example, with the :zephyr:code-sample:`synchronization` sample: .. zephyr-app-commands:: :zephyr-app: samples/synchronization diff --git a/boards/arm64/mimx8mn_evk/mimx8mn_evk_a53.yaml b/boards/arm64/mimx8mn_evk/mimx8mn_evk_a53.yaml index 50c2b2edd0b..4b6bd284846 100644 --- a/boards/arm64/mimx8mn_evk/mimx8mn_evk_a53.yaml +++ b/boards/arm64/mimx8mn_evk/mimx8mn_evk_a53.yaml @@ -10,3 +10,4 @@ testing: ignore_tags: - net - bluetooth +vendor: fsl diff --git a/boards/arm64/mimx8mn_evk/mimx8mn_evk_a53_smp.yaml b/boards/arm64/mimx8mn_evk/mimx8mn_evk_a53_smp.yaml index 63c3f629909..487c1bb8d3a 100644 --- a/boards/arm64/mimx8mn_evk/mimx8mn_evk_a53_smp.yaml +++ b/boards/arm64/mimx8mn_evk/mimx8mn_evk_a53_smp.yaml @@ -12,3 +12,4 @@ testing: ignore_tags: - net - bluetooth +vendor: fsl diff --git a/boards/arm64/mimx8mp_evk/doc/index.rst b/boards/arm64/mimx8mp_evk/doc/index.rst index ab63461f2e8..e59f94189a0 100644 --- a/boards/arm64/mimx8mp_evk/doc/index.rst +++ b/boards/arm64/mimx8mp_evk/doc/index.rst @@ -91,7 +91,7 @@ Or kick SMP zephyr.bin: mw 303d0518 f 1; fatload mmc 1:1 0xc0000000 zephyr.bin; dcache flush; icache flush; dcache off; icache off; cpu 2 release 0xc0000000 Use this configuration to run basic Zephyr applications and kernel tests, -for example, with the :ref:`synchronization_sample`: +for example, with the :zephyr:code-sample:`synchronization` sample: .. zephyr-app-commands:: :zephyr-app: samples/synchronization diff --git a/boards/arm64/mimx8mp_evk/mimx8mp_evk_a53.yaml b/boards/arm64/mimx8mp_evk/mimx8mp_evk_a53.yaml index b5c587ec64a..dbee1a28ef2 100644 --- a/boards/arm64/mimx8mp_evk/mimx8mp_evk_a53.yaml +++ b/boards/arm64/mimx8mp_evk/mimx8mp_evk_a53.yaml @@ -10,3 +10,4 @@ testing: ignore_tags: - net - bluetooth +vendor: fsl diff --git a/boards/arm64/mimx8mp_evk/mimx8mp_evk_a53_smp.yaml b/boards/arm64/mimx8mp_evk/mimx8mp_evk_a53_smp.yaml index b7217fceedb..c44defa6a5b 100644 --- a/boards/arm64/mimx8mp_evk/mimx8mp_evk_a53_smp.yaml +++ b/boards/arm64/mimx8mp_evk/mimx8mp_evk_a53_smp.yaml @@ -12,3 +12,4 @@ testing: ignore_tags: - net - bluetooth +vendor: fsl diff --git a/boards/arm64/mimx93_evk/doc/index.rst b/boards/arm64/mimx93_evk/doc/index.rst index 033739f2d91..67997a3fbbe 100644 --- a/boards/arm64/mimx93_evk/doc/index.rst +++ b/boards/arm64/mimx93_evk/doc/index.rst @@ -97,7 +97,7 @@ Or use the following command to kick zephyr.bin to Cortex-A55 Core0: Use this configuration to run basic Zephyr applications and kernel tests, -for example, with the :ref:`synchronization_sample`: +for example, with the :zephyr:code-sample:`synchronization` sample: .. zephyr-app-commands:: :zephyr-app: samples/synchronization @@ -168,7 +168,7 @@ Firstly, we need to explain a few Jailhouse concepts that will be referred to la cell can utilize. * **Root cell**: refers to the cell in which Linux is running. This is the main cell which - will contain all the hardware resources that Linux will utilize and will be used used to assign + will contain all the hardware resources that Linux will utilize and will be used to assign resources to the inmates. The inmates CANNOT use resources such as the CPU that haven't been assigned to the root cell. diff --git a/boards/arm64/mimx93_evk/mimx93_evk-pinctrl.dtsi b/boards/arm64/mimx93_evk/mimx93_evk-pinctrl.dtsi index 50186a49b0a..83070adf93f 100644 --- a/boards/arm64/mimx93_evk/mimx93_evk-pinctrl.dtsi +++ b/boards/arm64/mimx93_evk/mimx93_evk-pinctrl.dtsi @@ -7,10 +7,20 @@ #include &pinctrl { + uart1_default: uart1_default { + group0 { + pinmux = <&iomuxc1_uart1_rxd_lpuart_rx_lpuart1_rx>, + <&iomuxc1_uart1_txd_lpuart_tx_lpuart1_tx>; + bias-pull-up; + slew-rate = "slightly_fast"; + drive-strength = "x5"; + }; + }; + uart2_default: uart2_default { group0 { - pinmux = <&iomuxc_uart2_rxd_uart_rx_uart2_rx>, - <&iomuxc_uart2_txd_uart_tx_uart2_tx>; + pinmux = <&iomuxc1_uart2_rxd_lpuart_rx_lpuart2_rx>, + <&iomuxc1_uart2_txd_lpuart_tx_lpuart2_tx>; bias-pull-up; slew-rate = "slightly_fast"; drive-strength = "x5"; diff --git a/boards/arm64/mimx93_evk/mimx93_evk_a55.dts b/boards/arm64/mimx93_evk/mimx93_evk_a55.dts index 4ace0665671..375bb2f7a0e 100644 --- a/boards/arm64/mimx93_evk/mimx93_evk_a55.dts +++ b/boards/arm64/mimx93_evk/mimx93_evk_a55.dts @@ -30,6 +30,14 @@ }; }; +&lpuart1 { + status = "disabled"; + current-speed = <115200>; + /* clocks = <&ccm IMX_CCM_UART4_CLK 0x6c 24>; */ + pinctrl-0 = <&uart1_default>; + pinctrl-names = "default"; +}; + &lpuart2 { status = "okay"; current-speed = <115200>; diff --git a/boards/arm64/mimx93_evk/mimx93_evk_a55.yaml b/boards/arm64/mimx93_evk/mimx93_evk_a55.yaml index 636e1067925..72e4c677fc0 100644 --- a/boards/arm64/mimx93_evk/mimx93_evk_a55.yaml +++ b/boards/arm64/mimx93_evk/mimx93_evk_a55.yaml @@ -10,3 +10,4 @@ testing: ignore_tags: - net - bluetooth +vendor: fsl diff --git a/boards/arm64/mimx93_evk/mimx93_evk_a55_defconfig b/boards/arm64/mimx93_evk/mimx93_evk_a55_defconfig index 2bcf6198a10..53cb74f825c 100644 --- a/boards/arm64/mimx93_evk/mimx93_evk_a55_defconfig +++ b/boards/arm64/mimx93_evk/mimx93_evk_a55_defconfig @@ -7,6 +7,9 @@ CONFIG_AARCH64_IMAGE_HEADER=y CONFIG_ARMV8_A_NS=y +# MMU Options +CONFIG_MAX_XLAT_TABLES=64 + # Cache Options CONFIG_CACHE_MANAGEMENT=y CONFIG_DCACHE_LINE_SIZE_DETECT=y diff --git a/boards/arm64/mimx93_evk/mimx93_evk_a55_sof.yaml b/boards/arm64/mimx93_evk/mimx93_evk_a55_sof.yaml index 514b102f495..7fffa3f990e 100644 --- a/boards/arm64/mimx93_evk/mimx93_evk_a55_sof.yaml +++ b/boards/arm64/mimx93_evk/mimx93_evk_a55_sof.yaml @@ -10,3 +10,4 @@ testing: ignore_tags: - net - bluetooth +vendor: fsl diff --git a/boards/arm64/nxp_ls1046ardb/doc/index.rst b/boards/arm64/nxp_ls1046ardb/doc/index.rst index 53f23f89ae2..98e52f941bc 100644 --- a/boards/arm64/nxp_ls1046ardb/doc/index.rst +++ b/boards/arm64/nxp_ls1046ardb/doc/index.rst @@ -84,7 +84,7 @@ Programming and Debugging ************************* Use the following configuration to run basic Zephyr applications and -kernel tests on LS1046A RDB board. For example, with the :ref:`synchronization_sample`: +kernel tests on LS1046A RDB board. For example, with the :zephyr:code-sample:`synchronization` sample: 1. Non-SMP mode diff --git a/boards/arm64/nxp_ls1046ardb/nxp_ls1046ardb.yaml b/boards/arm64/nxp_ls1046ardb/nxp_ls1046ardb.yaml index 4fbc8a9a0f8..e00a5475b1b 100644 --- a/boards/arm64/nxp_ls1046ardb/nxp_ls1046ardb.yaml +++ b/boards/arm64/nxp_ls1046ardb/nxp_ls1046ardb.yaml @@ -6,3 +6,4 @@ toolchain: - zephyr - cross-compile ram: 1024 +vendor: nxp diff --git a/boards/arm64/nxp_ls1046ardb/nxp_ls1046ardb_smp_2cores.yaml b/boards/arm64/nxp_ls1046ardb/nxp_ls1046ardb_smp_2cores.yaml index 51ceb492ead..93e56887e22 100644 --- a/boards/arm64/nxp_ls1046ardb/nxp_ls1046ardb_smp_2cores.yaml +++ b/boards/arm64/nxp_ls1046ardb/nxp_ls1046ardb_smp_2cores.yaml @@ -6,3 +6,4 @@ toolchain: - zephyr - cross-compile ram: 1024 +vendor: nxp diff --git a/boards/arm64/nxp_ls1046ardb/nxp_ls1046ardb_smp_4cores.yaml b/boards/arm64/nxp_ls1046ardb/nxp_ls1046ardb_smp_4cores.yaml index bdda428e8fa..c74af99c1be 100644 --- a/boards/arm64/nxp_ls1046ardb/nxp_ls1046ardb_smp_4cores.yaml +++ b/boards/arm64/nxp_ls1046ardb/nxp_ls1046ardb_smp_4cores.yaml @@ -6,3 +6,4 @@ toolchain: - zephyr - cross-compile ram: 1024 +vendor: nxp diff --git a/boards/arm64/phycore_am62x_a53/phycore_am62x_a53.yaml b/boards/arm64/phycore_am62x_a53/phycore_am62x_a53.yaml index f9b8854bc5c..fe65e6b4a36 100644 --- a/boards/arm64/phycore_am62x_a53/phycore_am62x_a53.yaml +++ b/boards/arm64/phycore_am62x_a53/phycore_am62x_a53.yaml @@ -10,3 +10,4 @@ testing: ignore_tags: - net - bluetooth +vendor: ti diff --git a/boards/arm64/qemu_cortex_a53/doc/index.rst b/boards/arm64/qemu_cortex_a53/doc/index.rst index ad0d2d7cb5d..930671bb927 100644 --- a/boards/arm64/qemu_cortex_a53/doc/index.rst +++ b/boards/arm64/qemu_cortex_a53/doc/index.rst @@ -60,7 +60,7 @@ Programming and Debugging ************************* Use this configuration to run basic Zephyr applications and kernel tests in the QEMU -emulated environment, for example, with the :ref:`synchronization_sample`: +emulated environment, for example, with the :zephyr:code-sample:`synchronization` sample: .. zephyr-app-commands:: :zephyr-app: samples/synchronization diff --git a/boards/arm64/qemu_cortex_a53/qemu_cortex_a53.yaml b/boards/arm64/qemu_cortex_a53/qemu_cortex_a53.yaml index ee4b31be15e..b447db17f67 100644 --- a/boards/arm64/qemu_cortex_a53/qemu_cortex_a53.yaml +++ b/boards/arm64/qemu_cortex_a53/qemu_cortex_a53.yaml @@ -12,3 +12,4 @@ testing: ignore_tags: - net - bluetooth +vendor: qemu diff --git a/boards/arm64/qemu_cortex_a53/qemu_cortex_a53_smp.yaml b/boards/arm64/qemu_cortex_a53/qemu_cortex_a53_smp.yaml index 17b451074ce..9a6e87c0a70 100644 --- a/boards/arm64/qemu_cortex_a53/qemu_cortex_a53_smp.yaml +++ b/boards/arm64/qemu_cortex_a53/qemu_cortex_a53_smp.yaml @@ -14,3 +14,4 @@ testing: ignore_tags: - net - bluetooth +vendor: qemu diff --git a/boards/arm64/qemu_cortex_a53/qemu_cortex_a53_xip.yaml b/boards/arm64/qemu_cortex_a53/qemu_cortex_a53_xip.yaml index 04a92840c6d..5654908d3d2 100644 --- a/boards/arm64/qemu_cortex_a53/qemu_cortex_a53_xip.yaml +++ b/boards/arm64/qemu_cortex_a53/qemu_cortex_a53_xip.yaml @@ -11,3 +11,4 @@ testing: default: true only_tags: - xip +vendor: qemu diff --git a/boards/arm64/qemu_kvm_arm64/qemu_kvm_arm64.yaml b/boards/arm64/qemu_kvm_arm64/qemu_kvm_arm64.yaml index 93135232eb6..3dd2e974d0d 100644 --- a/boards/arm64/qemu_kvm_arm64/qemu_kvm_arm64.yaml +++ b/boards/arm64/qemu_kvm_arm64/qemu_kvm_arm64.yaml @@ -10,3 +10,4 @@ testing: ignore_tags: - net - bluetooth +vendor: qemu diff --git a/boards/arm64/rcar_h3ulcb_ca57/rcar_h3ulcb_ca57.yaml b/boards/arm64/rcar_h3ulcb_ca57/rcar_h3ulcb_ca57.yaml index 25616679c3d..e34235c2d43 100644 --- a/boards/arm64/rcar_h3ulcb_ca57/rcar_h3ulcb_ca57.yaml +++ b/boards/arm64/rcar_h3ulcb_ca57/rcar_h3ulcb_ca57.yaml @@ -14,3 +14,4 @@ testing: - net - bluetooth - isotp +vendor: renesas diff --git a/boards/arm64/rcar_salvator_xs_m3/rcar_salvator_xs_m3.yaml b/boards/arm64/rcar_salvator_xs_m3/rcar_salvator_xs_m3.yaml index 413e33258bf..84d4a864a35 100644 --- a/boards/arm64/rcar_salvator_xs_m3/rcar_salvator_xs_m3.yaml +++ b/boards/arm64/rcar_salvator_xs_m3/rcar_salvator_xs_m3.yaml @@ -10,8 +10,8 @@ supported: - clock_control - uart testing: - default: true ignore_tags: - net - bluetooth - isotp +vendor: renesas diff --git a/boards/arm64/roc_rk3568_pc/CMakeLists.txt b/boards/arm64/roc_rk3568_pc/CMakeLists.txt new file mode 100644 index 00000000000..9881313609a --- /dev/null +++ b/boards/arm64/roc_rk3568_pc/CMakeLists.txt @@ -0,0 +1 @@ +# SPDX-License-Identifier: Apache-2.0 diff --git a/boards/arm64/roc_rk3568_pc/Kconfig.board b/boards/arm64/roc_rk3568_pc/Kconfig.board new file mode 100644 index 00000000000..97844de31fd --- /dev/null +++ b/boards/arm64/roc_rk3568_pc/Kconfig.board @@ -0,0 +1,8 @@ +# Copyright 2022 HNU-ESNL +# Copyright 2022 openEuler SIG-Zephyr +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_ROC_RK3568_PC + bool "Rockchip ROC-RK3568-PC" + depends on SOC_SERIES_RK3568 + select ARM64 diff --git a/boards/arm64/roc_rk3568_pc/Kconfig.defconfig b/boards/arm64/roc_rk3568_pc/Kconfig.defconfig new file mode 100644 index 00000000000..9ad4f73bd2b --- /dev/null +++ b/boards/arm64/roc_rk3568_pc/Kconfig.defconfig @@ -0,0 +1,10 @@ +# Copyright 2022 HNU-ESNL +# Copyright 2022 openEuler SIG-Zephyr +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_ROC_RK3568_PC + +config BOARD + default "roc_rk3568_pc" + +endif # BOARD_ROC_RK3568_PC diff --git a/boards/arm64/roc_rk3568_pc/board.cmake b/boards/arm64/roc_rk3568_pc/board.cmake new file mode 100644 index 00000000000..9881313609a --- /dev/null +++ b/boards/arm64/roc_rk3568_pc/board.cmake @@ -0,0 +1 @@ +# SPDX-License-Identifier: Apache-2.0 diff --git a/boards/arm64/roc_rk3568_pc/doc/index.rst b/boards/arm64/roc_rk3568_pc/doc/index.rst new file mode 100644 index 00000000000..ae999409545 --- /dev/null +++ b/boards/arm64/roc_rk3568_pc/doc/index.rst @@ -0,0 +1,142 @@ +.. _roc_rk3568_pc: + +Firefly ROC-RK3568-PC (Quad-core Cortex-A55) +############################################ + +Overview +******** + +The ROC-RK3568-PC is a Quad-Core 64-Bit Mini Computer, which supports 4G large RAM. M.2 +and SATA3.0 interfaces enables expansion with large hard drives. +Providing dual Gigabit Ethernet ports, it supports WiFi 6 wireless transmission. +Control Port can be connected with RS485/RS232 devices. + +RK3568 quad-core 64-bit Cortex-A55 processor, with brand new ARM v8.2-A architecture, +has frequency up to 2.0GHz. Zephyr OS is ported to run on it. + + +- Board features: + + - RAM: 4GB LPDDR4 + - Storage: + + - 32GB eMMC + - M.2 PCIe 3.0 x 1 (Expand with 2242 / 2280 NVMe SSD) + - TF-Card Slot + - Wireless: + + - Supports WiFi 6 (802.11 AX) + - Supports BT5.0 + - USB: + + - One USB 3.0 + - Two USB 2.0 + - One Type-C + - Ethernet + - M.2 PCIe3.0 (Expand with NVMe SSD) + - LEDs: + + - 1x Power status LED + - Debug + + - UART debug ports for board + + +Supported Features +================== + +The Zephyr roc_rk3568_pc board configuration supports the following hardware +features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| GIC-v3 | on-chip | interrupt controller | ++-----------+------------+-------------------------------------+ +| ARM TIMER | on-chip | system clock | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port | ++-----------+------------+-------------------------------------+ + +Devices +======== +System Clock +------------ + +This board configuration uses a system clock frequency of 24 MHz. +Cortex-A55 Core runs up to 2.0 GHz. + +Serial Port +----------- + +This board configuration uses a single serial communication channel with the +CPU's UART2. + +Programming and Debugging +************************* + +Use U-Boot to load the zephyr.bin to the memory and kick it: + +.. code-block:: console + + tftp 0x40000000 zephyr.bin; dcache flush; icache flush; dcache off; icache off; go 0x40000000 + +Use this configuration to run basic Zephyr applications and kernel tests, +for example, with the :zephyr:code-sample:`synchronization` sample: + +.. zephyr-app-commands:: + :zephyr-app: samples/synchronization + :host-os: unix + :board: roc_rk3568_pc + :goals: run + +This will build an image with the synchronization sample app, boot it and +display the following ram console output: + +.. code-block:: console + + *** Booting Zephyr OS build bc695c6df5eb *** + thread_a: Hello World from cpu 0 on roc_rk3568_pc! + thread_b: Hello World from cpu 0 on roc_rk3568_pc! + thread_a: Hello World from cpu 0 on roc_rk3568_pc! + thread_b: Hello World from cpu 0 on roc_rk3568_pc! + + +roc_rk3568_pc_smp support, use this configuration to run Zephyr smp applications and subsys tests, +for example, with the :zephyr:code-sample:`synchronization` sample: + +.. zephyr-app-commands:: + :zephyr-app: samples/synchronization + :host-os: unix + :board: roc_rk3568_pc_smp + :goals: run + +This will build an image with the shell_module sample app, boot it and +display the following ram console output: + +.. code-block:: console + + *** Booting Zephyr OS build bc695c6df5eb *** + I/TC: Secondary CPU 1 initializing + I/TC: Secondary CPU 1 switching to normal world boot + I/TC: Secondary CPU 2 initializing + I/TC: Secondary CPU 2 switching to normal world boot + I/TC: Secondary CPU 3 initializing + I/TC: Secondary CPU 3 switching to normal world boot + Secondary CPU core 1 (MPID:0x100) is up + Secondary CPU core 2 (MPID:0x200) is up + Secondary CPU core 3 (MPID:0x300) is up + + thread_a: Hello World from cpu 0 on roc_rk3568_pc! + thread_b: Hello World from cpu 1 on roc_rk3568_pc! + thread_a: Hello World from cpu 0 on roc_rk3568_pc! + thread_b: Hello World from cpu 1 on roc_rk3568_pc! + +References +========== + +More information can refer to Firefly official website: +`Firefly website`_. + +.. _Firefly website: + https://en.t-firefly.com/product/industry/rocrk3568pc.html?theme=pc diff --git a/boards/arm64/roc_rk3568_pc/roc_rk3568_pc.dts b/boards/arm64/roc_rk3568_pc/roc_rk3568_pc.dts new file mode 100644 index 00000000000..0e2d0137229 --- /dev/null +++ b/boards/arm64/roc_rk3568_pc/roc_rk3568_pc.dts @@ -0,0 +1,33 @@ +/* + * Copyright 2022 HNU-ESNL + * Copyright 2022 openEuler SIG-Zephyr + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include + +/ { + model = "Firefly ROC-RK3568-PC"; + compatible = "rockchip,rk3568"; + + chosen { + zephyr,console = &uart2; + zephyr,shell-uart = &uart2; + zephyr,sram = &sram0; + }; + + sram0: memory@40000000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0x40000000 DT_SIZE_M(1)>; + }; + +}; + +&uart2 { + status = "okay"; + current-speed = <1500000>; +}; diff --git a/boards/arm64/roc_rk3568_pc/roc_rk3568_pc.yaml b/boards/arm64/roc_rk3568_pc/roc_rk3568_pc.yaml new file mode 100644 index 00000000000..82f35f567d5 --- /dev/null +++ b/boards/arm64/roc_rk3568_pc/roc_rk3568_pc.yaml @@ -0,0 +1,12 @@ +identifier: roc_rk3568_pc +name: Rockchip ROC RK3568 PC +type: mcu +arch: arm64 +toolchain: + - zephyr + - cross-compile +ram: 1024 +testing: + ignore_tags: + - net + - bluetooth diff --git a/boards/arm64/roc_rk3568_pc/roc_rk3568_pc_defconfig b/boards/arm64/roc_rk3568_pc/roc_rk3568_pc_defconfig new file mode 100644 index 00000000000..d85c08d24e7 --- /dev/null +++ b/boards/arm64/roc_rk3568_pc/roc_rk3568_pc_defconfig @@ -0,0 +1,26 @@ +# Copyright 2021 HNU-ESNL +# Copyright 2022 openEuler SIG-Zephyr +# SPDX-License-Identifier: Apache-2.0 + +# Platform Configuration +CONFIG_SOC_SERIES_RK3568=y +CONFIG_SOC_RK3568=y +CONFIG_BOARD_ROC_RK3568_PC=y +CONFIG_ARM_ARCH_TIMER=y + +# Serial Drivers +CONFIG_SERIAL=y +CONFIG_UART_NS16550=y +CONFIG_UART_INTERRUPT_DRIVEN=y + +# Enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# ARMv8 NS world with cache management +CONFIG_ARMV8_A_NS=y +CONFIG_CACHE_MANAGEMENT=y + +# Clock support +CONFIG_CLOCK_CONTROL=y +CONFIG_TICKLESS_KERNEL=y diff --git a/boards/arm64/roc_rk3568_pc/roc_rk3568_pc_smp.dts b/boards/arm64/roc_rk3568_pc/roc_rk3568_pc_smp.dts new file mode 100644 index 00000000000..41d10fb4402 --- /dev/null +++ b/boards/arm64/roc_rk3568_pc/roc_rk3568_pc_smp.dts @@ -0,0 +1,8 @@ +/* + * Copyright 2022 HNU-ESNL + * Copyright 2022 openEuler SIG-Zephyr + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "roc_rk3568_pc.dts" diff --git a/boards/arm64/roc_rk3568_pc/roc_rk3568_pc_smp.yaml b/boards/arm64/roc_rk3568_pc/roc_rk3568_pc_smp.yaml new file mode 100644 index 00000000000..07120b871fa --- /dev/null +++ b/boards/arm64/roc_rk3568_pc/roc_rk3568_pc_smp.yaml @@ -0,0 +1,14 @@ +identifier: roc_rk3568_pc_smp +name: Rockchip ROC RK3568 PC SMP +type: mcu +arch: arm64 +toolchain: + - zephyr + - cross-compile +ram: 1024 +supported: + - smp +testing: + ignore_tags: + - net + - bluetooth diff --git a/boards/arm64/roc_rk3568_pc/roc_rk3568_pc_smp_defconfig b/boards/arm64/roc_rk3568_pc/roc_rk3568_pc_smp_defconfig new file mode 100644 index 00000000000..3ffc3f25b41 --- /dev/null +++ b/boards/arm64/roc_rk3568_pc/roc_rk3568_pc_smp_defconfig @@ -0,0 +1,36 @@ +# Copyright 2022 HNU-ESNL +# Copyright 2022 openEuler SIG-Zephyr +# SPDX-License-Identifier: Apache-2.0 + +# Platform Configuration +CONFIG_SOC_SERIES_RK3568=y +CONFIG_SOC_RK3568=y +CONFIG_BOARD_ROC_RK3568_PC=y +CONFIG_ARM_ARCH_TIMER=y + +# Serial Drivers +CONFIG_SERIAL=y +CONFIG_UART_NS16550=y +CONFIG_UART_INTERRUPT_DRIVEN=y + +# Enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# SMP support +CONFIG_SMP=y +CONFIG_MP_MAX_NUM_CPUS=4 +CONFIG_MAX_THREAD_BYTES=4 + +# ARMv8 NS world with cache management +CONFIG_ARMV8_A_NS=y +CONFIG_CACHE_MANAGEMENT=y +CONFIG_DCACHE=y + +# PSCI support +CONFIG_PM_CPU_OPS=y +CONFIG_PM_CPU_OPS_PSCI=y + +# Clock support +CONFIG_CLOCK_CONTROL=y +CONFIG_TICKLESS_KERNEL=y diff --git a/boards/arm64/rpi_4b/CMakeLists.txt b/boards/arm64/rpi_4b/CMakeLists.txt new file mode 100644 index 00000000000..9881313609a --- /dev/null +++ b/boards/arm64/rpi_4b/CMakeLists.txt @@ -0,0 +1 @@ +# SPDX-License-Identifier: Apache-2.0 diff --git a/boards/arm64/rpi_4b/Kconfig.board b/boards/arm64/rpi_4b/Kconfig.board new file mode 100644 index 00000000000..9b0e9c80985 --- /dev/null +++ b/boards/arm64/rpi_4b/Kconfig.board @@ -0,0 +1,6 @@ +# Copyright 2023 honglin leng +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_RPI_4B + bool "Broadcom BCM2711" + depends on SOC_BCM2711 diff --git a/boards/arm64/rpi_4b/Kconfig.defconfig b/boards/arm64/rpi_4b/Kconfig.defconfig new file mode 100644 index 00000000000..c04170c5751 --- /dev/null +++ b/boards/arm64/rpi_4b/Kconfig.defconfig @@ -0,0 +1,6 @@ +# Copyright 2023 honglin leng +# SPDX-License-Identifier: Apache-2.0 + +config BOARD + default "Raspberry Pi 4 Model B" + depends on BOARD_RPI_4B diff --git a/boards/arm64/rpi_4b/board.cmake b/boards/arm64/rpi_4b/board.cmake new file mode 100644 index 00000000000..9881313609a --- /dev/null +++ b/boards/arm64/rpi_4b/board.cmake @@ -0,0 +1 @@ +# SPDX-License-Identifier: Apache-2.0 diff --git a/boards/arm64/rpi_4b/doc/index.rst b/boards/arm64/rpi_4b/doc/index.rst new file mode 100644 index 00000000000..a3222f368b7 --- /dev/null +++ b/boards/arm64/rpi_4b/doc/index.rst @@ -0,0 +1,71 @@ +.. rpi_4b: + +Raspberry Pi 4 Model B (Cortex-A72) +################################### + +Overview +******** +see + +Hardware +******** +see + +Supported Features +================== +The Raspberry Pi 4 Model B board configuration supports the following +hardware features: + +.. list-table:: + :header-rows: 1 + + * - Peripheral + - Kconfig option + - Devicetree compatible + * - GIC-400 + - N/A + - :dtcompatible:`arm,gic-v2` + * - GPIO + - :kconfig:option:`CONFIG_GPIO` + - :dtcompatible:`brcm,bcm2711-gpio` + * - UART (Mini UART) + - :kconfig:option:`CONFIG_SERIAL` + - :dtcompatible:`brcm,bcm2711-aux-uart` + +Other hardware features have not been enabled yet for this board. + +The default configuration can be found in the defconfig file: + + ``boards/arm64/rpi_4b/rpi_4b_defconfig`` + +Programming and Debugging +************************* + +TF Card +======= + +Prepare a TF card with MBR and FAT32. In the root directory of the TF card: + +1. Download and place these firmware files: + + * `bcm2711-rpi-4-b.dtb `_ + * `bootcode.bin `_ + * `start4.elf `_ + +2. Copy ``build/zephyr/zephyr.bin`` +3. Create a ``config.txt``: + + .. code-block:: text + + kernel=zephyr.bin + arm_64bit=1 + enable_uart=1 + uart_2ndstage=1 + +Insert the card and power on the board. You should see the following output on +the serial console (GPIO 14/15): + +.. code-block:: text + + *** Booting Zephyr OS build XXXXXXXXXXXX *** + Hello World! Raspberry Pi 4 Model B! diff --git a/boards/arm64/rpi_4b/rpi_4b.dts b/boards/arm64/rpi_4b/rpi_4b.dts new file mode 100644 index 00000000000..e7e1faad435 --- /dev/null +++ b/boards/arm64/rpi_4b/rpi_4b.dts @@ -0,0 +1,45 @@ +/* + * Copyright 2023 honglin leng + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include + +/ { + model = "Raspberry Pi 4 Model B"; + compatible = "raspberrypi,4-model-b", "brcm,bcm2838"; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + led0 = &led_act; + }; + + chosen { + zephyr,console = &uart1; + zephyr,shell-uart = &uart1; + zephyr,sram = &sram0; + }; + + leds { + compatible = "gpio-leds"; + + led_act: led-act { + gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; /* GPIO 42 */ + label = "ACT"; + }; + }; +}; + +&gpio1 { + status = "okay"; +}; + +&uart1 { + status = "okay"; + current-speed = <115200>; +}; diff --git a/boards/arm64/rpi_4b/rpi_4b.yaml b/boards/arm64/rpi_4b/rpi_4b.yaml new file mode 100644 index 00000000000..475979827c5 --- /dev/null +++ b/boards/arm64/rpi_4b/rpi_4b.yaml @@ -0,0 +1,7 @@ +identifier: rpi_4b +name: Raspberry Pi 4 Model B +type: mcu +arch: arm64 +toolchain: + - zephyr + - cross-compile diff --git a/boards/arm64/rpi_4b/rpi_4b_defconfig b/boards/arm64/rpi_4b/rpi_4b_defconfig new file mode 100644 index 00000000000..fb79c77a1f6 --- /dev/null +++ b/boards/arm64/rpi_4b/rpi_4b_defconfig @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: Apache-2.0 + +# Platform Configuration +CONFIG_SOC_BCM2711=y +CONFIG_BOARD_RPI_4B=y +CONFIG_ARM64_VA_BITS_36=y +CONFIG_ARM64_PA_BITS_36=y + +# Zephyr Kernel Configuration +CONFIG_XIP=n +CONFIG_FLASH_SIZE=0 +CONFIG_FLASH_BASE_ADDRESS=0x0 + +# Serial Drivers +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y + +# Enable Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Timer Drivers +CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y diff --git a/boards/arm64/xenvm/doc/index.rst b/boards/arm64/xenvm/doc/index.rst index f6ab7d121d1..bfeb319aaae 100644 --- a/boards/arm64/xenvm/doc/index.rst +++ b/boards/arm64/xenvm/doc/index.rst @@ -94,7 +94,7 @@ Building and Running ******************** Use this configuration to run basic Zephyr applications and kernel tests as Xen -guest, for example, with the :ref:`synchronization_sample`: +guest, for example, with the :zephyr:code-sample:`synchronization` sample: - if your hardware is based on GICv2: diff --git a/boards/arm64/xenvm/xenvm.dts b/boards/arm64/xenvm/xenvm.dts index fb6daa3656a..bbba268d9a3 100644 --- a/boards/arm64/xenvm/xenvm.dts +++ b/boards/arm64/xenvm/xenvm.dts @@ -18,8 +18,8 @@ #include / { - model = "XENVM-4.15"; - compatible = "xen,xenvm-4.15", "xen,xenvm"; + model = "XENVM"; + compatible = "xen,xenvm"; interrupt-parent = <&gic>; #address-cells = <0x02>; #size-cells = <0x02>; @@ -68,7 +68,7 @@ }; hypervisor: hypervisor@38000000 { - compatible = "xen,xen-4.15", "xen,xen"; + compatible = "xen,xen"; reg = <0x00 0x38000000 0x00 0x1000000>; interrupts = ; interrupt-parent = <&gic>; diff --git a/boards/arm64/xenvm/xenvm.yaml b/boards/arm64/xenvm/xenvm.yaml index 13fcc815424..2cd38e3c399 100644 --- a/boards/arm64/xenvm/xenvm.yaml +++ b/boards/arm64/xenvm/xenvm.yaml @@ -6,3 +6,4 @@ toolchain: - zephyr - cross-compile ram: 16384 +vendor: xen diff --git a/boards/arm64/xenvm/xenvm_defconfig b/boards/arm64/xenvm/xenvm_defconfig index 8905b74a0c9..39e8a20767c 100644 --- a/boards/arm64/xenvm/xenvm_defconfig +++ b/boards/arm64/xenvm/xenvm_defconfig @@ -4,7 +4,7 @@ CONFIG_BOARD_XENVM=y # Enable UART driver CONFIG_SERIAL=y -CONFIG_MAX_XLAT_TABLES=10 +CONFIG_MAX_XLAT_TABLES=24 CONFIG_HEAP_MEM_POOL_SIZE=16384 # Enable console @@ -16,3 +16,5 @@ CONFIG_LOG=y CONFIG_LOG_MODE_MINIMAL=n CONFIG_USERSPACE=n + +CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y diff --git a/boards/arm64/xenvm/xenvm_gicv3.yaml b/boards/arm64/xenvm/xenvm_gicv3.yaml index 8bcd02c03ff..91026d183d2 100644 --- a/boards/arm64/xenvm/xenvm_gicv3.yaml +++ b/boards/arm64/xenvm/xenvm_gicv3.yaml @@ -6,3 +6,4 @@ toolchain: - zephyr - cross-compile ram: 16384 +vendor: xen diff --git a/boards/arm64/xenvm/xenvm_gicv3_defconfig b/boards/arm64/xenvm/xenvm_gicv3_defconfig index 9bff11a2edb..7b6b9afa888 100644 --- a/boards/arm64/xenvm/xenvm_gicv3_defconfig +++ b/boards/arm64/xenvm/xenvm_gicv3_defconfig @@ -4,7 +4,7 @@ CONFIG_BOARD_XENVM=y # Enable UART driver CONFIG_SERIAL=y -CONFIG_MAX_XLAT_TABLES=10 +CONFIG_MAX_XLAT_TABLES=24 # Enable console CONFIG_CONSOLE=y @@ -15,3 +15,5 @@ CONFIG_LOG=y CONFIG_LOG_MODE_MINIMAL=n CONFIG_USERSPACE=n + +CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y diff --git a/boards/common/nxp_s32dbg.board.cmake b/boards/common/nxp_s32dbg.board.cmake new file mode 100644 index 00000000000..edd49ea305f --- /dev/null +++ b/boards/common/nxp_s32dbg.board.cmake @@ -0,0 +1,6 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +board_set_flasher_ifnset(nxp_s32dbg) +board_set_debugger_ifnset(nxp_s32dbg) +board_finalize_runner_args(nxp_s32dbg) diff --git a/boards/common/stub.dts b/boards/common/stub.dts new file mode 100644 index 00000000000..ebb8b852a92 --- /dev/null +++ b/boards/common/stub.dts @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +/* empty stub file provided for systems not using devicetree */ + +/dts-v1/; + +#include + +/ { + +}; diff --git a/boards/index.rst b/boards/index.rst index 068388e28aa..9c843c9e95b 100644 --- a/boards/index.rst +++ b/boards/index.rst @@ -6,8 +6,11 @@ Supported Boards Zephyr project developers are continually adding board-specific support as documented below. -To add support documentation for a new board, please use the template available -under :zephyr_file:`doc/templates/board.tmpl` +If you are looking to add Zephyr support for a new board, please start with the +:ref:`board_porting_guide`. + +When adding support documentation for each board, remember to use the template +available under :zephyr_file:`doc/templates/board.tmpl`. .. toctree:: diff --git a/boards/mips/qemu_malta/doc/index.rst b/boards/mips/qemu_malta/doc/index.rst index 9ce6f383fd2..abca3138061 100644 --- a/boards/mips/qemu_malta/doc/index.rst +++ b/boards/mips/qemu_malta/doc/index.rst @@ -58,7 +58,7 @@ Programming and Debugging ************************* Use this configuration to run basic Zephyr applications and kernel tests in the QEMU -emulated environment, for example, with the :ref:`synchronization_sample`: +emulated environment, for example, with the :zephyr:code-sample:`synchronization` sample: .. zephyr-app-commands:: :zephyr-app: samples/synchronization @@ -90,7 +90,7 @@ Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`. Big-Endian ========== -Use this configuration to run :ref:`synchronization_sample` in big-endian mode: +Use this configuration to run :zephyr:code-sample:`synchronization` sample in big-endian mode: .. zephyr-app-commands:: :zephyr-app: samples/synchronization diff --git a/boards/mips/qemu_malta/qemu_malta.yaml b/boards/mips/qemu_malta/qemu_malta.yaml index adc81837ff2..3749da567ea 100644 --- a/boards/mips/qemu_malta/qemu_malta.yaml +++ b/boards/mips/qemu_malta/qemu_malta.yaml @@ -13,3 +13,4 @@ testing: ignore_tags: - net - bluetooth +vendor: qemu diff --git a/boards/mips/qemu_malta/qemu_malta_be.yaml b/boards/mips/qemu_malta/qemu_malta_be.yaml index 97de3fe1e70..80eab182050 100644 --- a/boards/mips/qemu_malta/qemu_malta_be.yaml +++ b/boards/mips/qemu_malta/qemu_malta_be.yaml @@ -13,3 +13,4 @@ testing: ignore_tags: - net - bluetooth +vendor: qemu diff --git a/boards/nios2/altera_max10/altera_max10.yaml b/boards/nios2/altera_max10/altera_max10.yaml index a59497a4509..eb068f21f47 100644 --- a/boards/nios2/altera_max10/altera_max10.yaml +++ b/boards/nios2/altera_max10/altera_max10.yaml @@ -4,3 +4,4 @@ type: mcu arch: nios2 toolchain: - zephyr +vendor: altr diff --git a/boards/nios2/qemu_nios2/doc/index.rst b/boards/nios2/qemu_nios2/doc/index.rst index cefa66c78fa..9dcef10a451 100644 --- a/boards/nios2/qemu_nios2/doc/index.rst +++ b/boards/nios2/qemu_nios2/doc/index.rst @@ -74,7 +74,7 @@ Programming and Debugging ************************* Use this configuration to run basic Zephyr applications and kernel tests in the QEMU -emulated environment, for example, with the :ref:`synchronization_sample`: +emulated environment, for example, with the :zephyr:code-sample:`synchronization` sample: .. zephyr-app-commands:: :zephyr-app: samples/synchronization diff --git a/boards/nios2/qemu_nios2/qemu_nios2.yaml b/boards/nios2/qemu_nios2/qemu_nios2.yaml index d491aa236ae..6f170873486 100644 --- a/boards/nios2/qemu_nios2/qemu_nios2.yaml +++ b/boards/nios2/qemu_nios2/qemu_nios2.yaml @@ -13,3 +13,4 @@ testing: ignore_tags: - net - bluetooth +vendor: qemu diff --git a/boards/posix/common/irq/board_irq.h b/boards/posix/common/irq/board_irq.h index abe28b82b94..bad19084dd1 100644 --- a/boards/posix/common/irq/board_irq.h +++ b/boards/posix/common/irq/board_irq.h @@ -9,7 +9,7 @@ #define BOARDS_POSIX_COMMON_BOARD_IRQ_H #include -#include "zephyr/types.h" +#include #ifdef __cplusplus extern "C" { diff --git a/boards/posix/common/natsim_config.cmake b/boards/posix/common/natsim_config.cmake index 54f26aef3ef..2ab155af105 100644 --- a/boards/posix/common/natsim_config.cmake +++ b/boards/posix/common/natsim_config.cmake @@ -1,21 +1,26 @@ # Copyright (c) 2023 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 -set(zephyr_build_path ${CMAKE_BINARY_DIR}/zephyr) +set(zephyr_build_path ${APPLICATION_BINARY_DIR}/zephyr) get_property(CCACHE GLOBAL PROPERTY RULE_LAUNCH_COMPILE) +target_link_options(native_simulator INTERFACE + "-T ${ZEPHYR_BASE}/boards/posix/common/natsim_linker_script.ld") + set(nsi_config_content ${nsi_config_content} "NSI_BUILD_OPTIONS:=$,\ >" "NSI_BUILD_PATH:=${zephyr_build_path}/NSI" "NSI_CC:=${CCACHE} ${CMAKE_C_COMPILER}" "NSI_OBJCOPY:=${CMAKE_OBJCOPY}" - "NSI_EMBEDDED_CPU_SW:=${zephyr_build_path}/${KERNEL_ELF_NAME}" + "NSI_EMBEDDED_CPU_SW:=${zephyr_build_path}/${KERNEL_ELF_NAME} ${CONFIG_NATIVE_SIMULATOR_EXTRA_IMAGE_PATHS}" "NSI_EXE:=${zephyr_build_path}/${KERNEL_EXE_NAME}" "NSI_EXTRA_SRCS:=$,\ >" "NSI_LINK_OPTIONS:=$,\ >" "NSI_EXTRA_LIBS:=$,\ >" "NSI_PATH:=${NSI_DIR}/" + "NSI_N_CPUS:=${CONFIG_NATIVE_SIMULATOR_NUMBER_MCUS}" + "NSI_LOCALIZE_OPTIONS:=--localize-symbol=CONFIG_*" ) string(REPLACE ";" "\n" nsi_config_content "${nsi_config_content}") diff --git a/boards/posix/common/natsim_linker_script.ld b/boards/posix/common/natsim_linker_script.ld new file mode 100644 index 00000000000..add80b86c75 --- /dev/null +++ b/boards/posix/common/natsim_linker_script.ld @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Extra linker command/script file for the native simulator runner + */ + +SECTIONS + { + symbol_to_keep : + { + KEEP(*(symbol_to_keep*)); + } + } INSERT AFTER .data; + +/* + * Note this script augments the default native simulator linker script + */ diff --git a/boards/posix/doc/arch_soc.rst b/boards/posix/doc/arch_soc.rst index 3cd72e080e7..f0e469308ab 100644 --- a/boards/posix/doc/arch_soc.rst +++ b/boards/posix/doc/arch_soc.rst @@ -33,9 +33,9 @@ target hardware in the early phases of development. Types of POSIX arch based boards ================================ -Today there are two types of POSIX boards: The :ref:`native_posix` -board and the :ref:`bsim boards`. -While they share the main objectives and principles, the first is intended as +Today there are two types of POSIX boards: The native boards, :ref:`native_posix` +and :ref:`native_sim`, and the :ref:`bsim boards`. +While they share the main objectives and principles, the first are intended as a HW agnostic test platform which in some cases utilizes the host OS peripherals, while the second intend to simulate a particular HW platform, with focus on their radio (e.g. BT LE) and utilize the `BabbleSim`_ physical layer @@ -65,9 +65,9 @@ This port is designed and tested to run in Linux. The 32 bit version of this port does not directly work in Windows Subsystem for Linux (WSL) because WSL does not support native 32-bit binaries. - You may want to consider WSL2, or, if using native_posix, - you can also just use the native_posix_64 - target: Check :ref:`32 and 64bit versions`. + You may want to consider WSL2, or, if using :ref:`native_sim `, + you can also just use the ``native_sim_64`` + target: Check :ref:`32 and 64bit versions`. Otherwise `with some tinkering `_ it should be possible to make it work. @@ -323,7 +323,7 @@ SOC and board layers This description applies to all current POSIX arch based boards on tree, but it is not a requirement for another board to follow what is described here. -When the executable process is started (that is the the board +When the executable process is started (that is the board :c:func:`main`, which is the linux executable C :c:func:`main`), first, early initialization steps are taken care of (command line argument parsing, initialization of the HW models, etc). @@ -391,7 +391,7 @@ Busy waits ========== Busy waits work thanks to provided board functionality. -This does not need to be the same for all boards, but both native_posix and the +This does not need to be the same for all boards, but both native_sim and the nrf52_bsim board work similarly thru the combination of a board specific `arch_busy_wait()` and a special fake HW timer (provided by the board). diff --git a/boards/posix/doc/bsim_boards_design.rst b/boards/posix/doc/bsim_boards_design.rst index 3c12f0e6acb..9b6bcfc0bca 100644 --- a/boards/posix/doc/bsim_boards_design.rst +++ b/boards/posix/doc/bsim_boards_design.rst @@ -3,18 +3,27 @@ Bsim boards ########### -This page covers the design, architecture and rationale, of the -:ref:`nrf52_bsim` board and other similar bsim boards. -Particular details on the nRF52 simulation board, including how to use it, -can be found in that :ref:`board documentation`. -These boards are postfixed with `_bsim` as they use BabbleSim_ -(shortened bsim). +**Available bsim boards** -.. contents:: +* :ref:`Simulated nRF52833 (nrf52_bsim)` +* :ref:`Simulated nRF5340 (nrf5340bsim)` + +.. contents:: Table of contents :depth: 2 :backlinks: entry :local: +This page covers the design, architecture and rationale, of the +nrf5x_bsim boards and other similar bsim boards. +These boards are postfixed with `_bsim` as they use BabbleSim_ +(shortened bsim), to simulate the radio environment. +These boards use the `native simulator`_ and the :ref:`POSIX architecture` to build +and execute the embedded code natively on Linux. + +Particular details on the :ref:`nRF52` and :ref:`nRF5340` +simulation boards, including how to use them, +can be found in their respective documentation. + .. _BabbleSim: https://BabbleSim.github.io @@ -24,10 +33,20 @@ These boards are postfixed with `_bsim` as they use BabbleSim_ .. _Architecture of HW models used for FW development and testing: https://babblesim.github.io/arch_hw_models.html +.. _native simulator: + https://github.com/BabbleSim/native_simulator/blob/main/docs/README.md + +.. _native simulator design documentation: + https://github.com/BabbleSim/native_simulator/blob/main/docs/Design.md + +.. _nRF HW models design documentation: + https://github.com/BabbleSim/ext_nRF_hw_models/blob/main/docs/README_HW_models.md + + Overall objective ***************** -Bsim boards main purpose is to be test-benches for +The main purpose of these bsim boards is to be test-benches for integration testing of embedded code on workstation/simulation. Integration testing in the sense that the code under test will, at the very least, run with the Zephyr RTOS just like for any other @@ -39,9 +58,12 @@ These tests are run in workstation, that is, without using real embedded HW. The intention being to be able to run tests much faster than real time, without the need for real HW, and in a deterministic/reproducible fashion. -Unlike native_posix, bsim boards do not interact directly with any host +Unlike :ref:`native_sim `, bsim boards do not interact directly with any host peripherals, and their execution is independent of the host load, or timing. +These boards are also designed to be used as prototyping and development environments, +which can help developing applications or communication stacks. + .. _bsim_boards_tests: Different types of tests and how the bsim boards relate to them @@ -82,13 +104,13 @@ to these boards. an special driver that handles the EDTT communication (its RPC transport) and an embedded application that handles the RPC calls themselves, while the python test scripts provide the test logic. - - Using Zephyr's native_posix board: It also allows integration testing of + - Using Zephyr's :ref:`native_sim ` board: It also allows integration testing of the embedded code, but without any specific HW. In that way, many embedded components which are dependent on the HW would not be suited for testing in that platform. Just like the bsim boards, this Zephyr target board can be used with or without Zephyr's ztest system and twister. - The native_posix board shares the :ref:`POSIX architecture` - with the bsim boards. + The :ref:`native_sim ` board shares the :ref:`POSIX architecture`, + and native simulator runner with the bsim boards. - Zephyr's ztest infrastructure and Zephyr's twister: Based on dedicated embedded test applications build with the code under test. @@ -107,34 +129,37 @@ Layering: Zephyr's arch, soc and board layers The basic architecture layering of these boards is as follows: +- The `native simulator`_ runner is used to execute the code in your host. - The architecture, SOC and board components of Zephyr are replaced with simulation specific ones. - The architecture (arch) is the Zephyr :ref:`POSIX architecture` layer. - The SOC layer is the soc_inf layer. And the board layer is dependent on + The SOC layer is `inf_clock`. And the board layer is dependent on the specific device we are simulating. - The POSIX architecture provides an adaptation from the Zephyr arch API - (which handles mostly the thread context switching) to the Linux kernel. + (which handles mostly the thread context switching) to the native simulator + CPU thread emulation. See :ref:`POSIX arch architecture` -- The soc_inf layer provides the overall CPU "simulation" and the handling of - control between the "CPU simulation" (Zephyr threads) and the HW models thread - ( See `Threading`_ ) +- The SOC `inf_clock` layer provides an adaptation to the native simulator CPU "simulation" + and the handling of control between the "CPU simulation" (Zephyr threads) and the + HW models thread ( See `Threading`_ ). - The board layer provides all SOC/ IC specific content, including - (or linking to) HW models, IRQ handling, busy wait API - (see :ref:`posix_busy_wait`), and Zephyr's printk backend. + selecting the HW models which are built in the native simulator runner context, IRQ handling, + busy wait API (see :ref:`posix_busy_wait`), and Zephyr's printk backend. Note that in a normal Zephyr target interrupt handling and a custom busy wait would be provided by the SOC layer, but abusing Zephyr's layering, and for the - soc_inf layer to be generic, these were delegated to the board. - The board layer also provides the :c:func:`main` entry point for the linux - program, command line argument handling, the overall time scheduling of - the simulated device, and other test specific functionality like bs_tests - hooks, trace control, etc. - Note that the POSIX arch and soc_inf expect a set of APIs being provided by + `inf_clock` layer to be generic, these were delegated to the board. + The board layer provides other test specific + functionality like bs_tests hooks, trace control, etc, and + by means of the native simulator, provides the :c:func:`main` entry point for the Linux + program, command line argument handling, and the overall time scheduling of + the simulated device. + Note that the POSIX arch and `inf_clock` soc expect a set of APIs being provided by the board. This includes the busy wait API, a basic tracing API, the interrupt controller and interrupt handling APIs, :c:func:`posix_exit`, - and :c:func:`posix_get_hw_cycle` (see posix_board_if.h and posix_soc_if.h ). + and :c:func:`posix_get_hw_cycle` (see :file:`posix_board_if.h` and :file:`posix_soc_if.h`). -.. figure:: layering.svg +.. figure:: layering_natsim.svg :align: center :alt: Zephyr layering in native & bsim builds :figclass: align-center @@ -147,7 +172,7 @@ Important limitations All native and bsim boards share the same set of :ref:`important limitations which` -are inherited from the POSIX arch and soc_inf design. +are inherited from the POSIX arch and `inf_clock` design. .. _Threading: @@ -156,12 +181,15 @@ Threading and overall scheduling of CPU and HW models The threading description, as well as the general SOC and board architecture introduced in -:ref:`POSIX arch architecture` -apply to the bsim boards. +:ref:`POSIX arch architecture` and on the +`native simulator design documentation`_ apply to the bsim boards. Moreover in `Architecture of HW models used for FW development and testing`_ -more details on the HW models and their scheduling are provided. +a general introduction to the babblesim HW models and their scheduling are provided. + +In case of the nRF bsim boards, more information can be found in the +`nRF HW models design documentation`_. Time and the time_machine ========================= @@ -178,7 +206,7 @@ and the simulation results will not be affected in any way by the load of the simulation host or by the process execution being "paused" in a debugger or similar. -The time_machine component provides the overall HW event time loop +The native simulator HW scheduler provides the overall HW event time loop required by the HW models, which consists of a very simple "search for next event", "advance time to next event and execute it" loop, together with an API for components that use it to inform about their events @@ -204,14 +232,14 @@ below represents this communication: Communication between a Zephyr device and other simulated devices Test code may also communicate with other devices' test code using the bsim -backchannels. These provide a direct, reliable pipe between devices' test code +backchannels. These provide a direct, reliable pipe between devices which test code can use to exchange data. About using Zephyr APIs ======================= -Note that even though bsim board code is linked with the Zephyr kernel, +Note that even though part of the bsim board code is linked with the Zephyr kernel, one should in general not call Zephyr APIs from the board code itself. In particular, one should not call Zephyr APIs from the original/HW models thread as the Zephyr code would be called from the wrong context, @@ -225,13 +253,14 @@ which relies on the bs_trace API. Instead, for tracing the bs_trace API should be used directly. The same applies to other Zephyr APIs, including the entropy API, etc. -posix_print backend -=================== +posix_print and nsi_print backends +================================== + +The bsim board provides a backend for the ``posix_print`` API which is expected by the posix +ARCH and `inf_clock` code, and for the ``nsi_print`` API expected by the native simulator. -The bsim board provides a backend for the posix_print API which is expected by the posix ARCH -and soc inf (POSIX) code. -It simply routes the printk strings to the bs_trace bsim API. -Any message printed to the posix_print API, which is also the default printk backend, +These simply route this API calls into the ``bs_trace`` bsim API. +Any message printed to these APIs, and by extension by default to Zephyr's ``printk``, will be printed to the console (stdout) together with all other device messages. .. _bsim_boards_bs_tests: @@ -254,12 +283,12 @@ callbacks are assigned to the respective hooks. There is a set of one time hooks at different levels of initialization of the HW and Zephyr OS, a hook to process possible command line arguments, and, a hook that can be used to sniff or capture interrupts. -bs_tests also provides a hook which will be called from the embedded application +`bs_tests` also provides a hook which will be called from the embedded application :c:func:`main`, but this will only work if the main application supports it, that is, if the main app is a version for simulation which calls :c:func:`bst_main` when running in the bsim board. -Apart from these hooks, the bs_tests system provides facilities to build a +Apart from these hooks, the `bs_tests` system provides facilities to build a dedicated test "task". This will be executed in the HW models thread context, but will have access to all SW variables. This task will be driven with a special timer which can be configured to produce either periodic or one time @@ -269,12 +298,16 @@ at specific points in time. This can be combined with Babblesim's tb_defs macros to build quite complex test tasks which can wait for a given amount of time, for conditions to be fulfilled, etc. -Note: When writing the tests with bs_tests one needs to be aware that other +Note when writing the tests with `bs_tests` one needs to be aware that other bs tests will probably be built with the same application, and that therefore the tests should not be registering initialization or callback functions using NATIVE_TASKS or Zephyr's PRE/POST kernel driver initialization APIs as this will execute even if the test is not selected. -Instead the equivalent bs_tests provided hooks should be used. +Instead the equivalent `bs_tests` provided hooks should be used. + +Note also that, for AMP targets like the :ref:`nrf5340bsim `, each embedded MCU has +its own separate `bs_tests` built with that MCU. You can select if and what test is used +for each MCU separatedly with the command line options. Command line argument parsing ============================= @@ -289,8 +322,8 @@ arguments: - The HW models command line arguments: The HW models will expose which arguments they need to have processed, but the bsim board as actual integrating program ensures they are handled. -- Test (bs_tests) control: To select a test, print which are available, and - pass arguments to the tests themselves. +- Test (bs_tests) control: To select a test for each embedded CPU, + print which are available, and pass arguments to the tests themselves. Command line argument parsing is handled by using the bs_cmd_line component from Babblesim's base/libUtilv1 library. And basic arguments definitions that diff --git a/boards/posix/doc/layering.svg b/boards/posix/doc/layering.svg index af432d2894e..c85357d0132 100644 --- a/boards/posix/doc/layering.svg +++ b/boards/posix/doc/layering.svg @@ -129,11 +129,11 @@ x="42.81" dy="1.2em" class="st4">layering Sheet.14 - Native_posix & _bsim boards Zephyr layering + native_posix/sim & _bsim boards Zephyr layering - Native_posix native_posix/sim & _bsim boards Zephyr layering diff --git a/boards/posix/doc/layering_natsim.svg b/boards/posix/doc/layering_natsim.svg new file mode 100644 index 00000000000..535ad934e5e --- /dev/null +++ b/boards/posix/doc/layering_natsim.svg @@ -0,0 +1,582 @@ + + + + + + + + + + + + + Sheet.1 + CPU/SOC + + + + CPU/SOC + Sheet.2 + HW peripherals + + + + HW peripherals + Sheet.3 + Drivers + + + + Drivers + Sheet.4 + Architecture/SOC dependent layer + + + + Architecture/SOC dependent layer + Sheet.5 + Zephyr Kernel + + + + ZephyrKernel + Sheet.6 + Application + + + + Application + Sheet.7 + Host OS Kernel (i.e. Linux) + + + + Host OS Kernel (i.e. Linux) Sheet.7Host OS Kernel (i.e. Linux)Overall scheduler & entry pointCPUemulationSheet.8HW models / host HW API adaptationPOSIX archand SOC + Sheet.9 + Drivers + + + + Drivers + Sheet.11 + Zephyr Kernel + + + + ZephyrKernel + Sheet.12 + Application + + + + Application + Sheet.13 + Normal Zephyr layering + + + + Normal Zephyr layering native simulator runner contextEmbedded CPU SW (Zephyr) context +native_sim & _bsimboards Zephyr layeringHW models /Host APIadaptation diff --git a/boards/posix/native_posix/cmdline.c b/boards/posix/native_posix/cmdline.c index fd77f8abf94..aa0ef1e6974 100644 --- a/boards/posix/native_posix/cmdline.c +++ b/boards/posix/native_posix/cmdline.c @@ -8,7 +8,7 @@ #include #include #include "cmdline_common.h" -#include "zephyr/types.h" +#include #include "hw_models_top.h" #include "timer_model.h" #include "cmdline.h" diff --git a/boards/posix/native_posix/cmdline_common.c b/boards/posix/native_posix/cmdline_common.c index 40367033e11..8723505658a 100644 --- a/boards/posix/native_posix/cmdline_common.c +++ b/boards/posix/native_posix/cmdline_common.c @@ -12,7 +12,7 @@ #include #include #include "posix_board_if.h" -#include "zephyr/types.h" +#include #include "cmdline_common.h" /** diff --git a/boards/posix/native_posix/doc/index.rst b/boards/posix/native_posix/doc/index.rst index a9306b7451b..61e6c164327 100644 --- a/boards/posix/native_posix/doc/index.rst +++ b/boards/posix/native_posix/doc/index.rst @@ -11,14 +11,28 @@ Native POSIX execution (native_posix) Overview ******** -This is a :ref:`POSIX architecture` based board. -With it, a Zephyr application can be compiled together with -the Zephyr kernel, creating a normal Linux executable. +``native_posix`` is the predecessor of :ref:`native_sim`. +Just like with :ref:`native_sim` you can build your Zephyr application +with the Zephyr kernel, creating a normal Linux executable with your host tooling, +and can debug and instrument it like any other Linux program. + +But unlike with :ref:`native_sim` you are limited to only using the host C library. +:ref:`native_sim` supports all ``native_posix`` use cases. + +.. note:: + + | If you are a new user, you are encouraged to use :ref:`native_sim` directly. + | If you have been using native_posix you are recommended to start using + :ref:`native_sim` instead. + | If needed, :ref:`native_sim` includes a compatibility mode + :kconfig:option:`CONFIG_NATIVE_SIM_NATIVE_POSIX_COMPAT`, + which will set its configuration to mimic a native_posix's like configuration. This board does not intend to simulate any particular HW, but it provides a few peripherals such as an Ethernet driver, display, UART, etc., to enable developing and testing application code which would require them. -See `Peripherals`_ for more information. +This board supports the same :ref:`peripherals` +:ref:`and backends as native_sim`. .. _native_posix_deps: @@ -36,15 +50,16 @@ Important limitations This board inherits :ref:`the limitations of its architecture` +Moreover, being limited to build only with the host C library, it is not possible to build +applications with the :ref:`Zephyr POSIX OS abstraction`, as there would be symbol +collisions between the host OS and this abstraction layer. + .. _native_posix_how_to_use: How to use it ************* -Compiling -========= - -Specify the native_posix board target to build a native POSIX application: +To build, simply specify the ``native_posix`` board as target: .. zephyr-app-commands:: :zephyr-app: samples/hello_world @@ -53,92 +68,20 @@ Specify the native_posix board target to build a native POSIX application: :goals: build :compact: -Running -======= - -The result of the compilation is an executable (zephyr.exe) placed in the -zephyr/ subdirectory of the build folder. -Run the zephyr.exe executable as you would any other Linux console application. - -.. code-block:: console - - $ ./build/zephyr/zephyr.exe - # Press Ctrl+C to exit - -This executable accepts several command line options depending on the -compilation configuration. -You can run it with the ``--help`` command line switch to get a list of -available options:: - - $ ./build/zephyr/zephyr.exe --help - -Note that the Zephyr kernel does not actually exit once the application is -finished. It simply goes into the idle loop forever. -Therefore you must stop the application manually (Ctrl+C in Linux). - -Application tests using the ``ztest`` framework will exit after all -tests have completed. - -If you want your application to gracefully finish when it reaches some point, -you may add a conditionally compiled (:kconfig:option:`CONFIG_ARCH_POSIX`) call to -``posix_exit(int status)`` at that point. - -.. _native_posix_debug: - -Debugging -========= - -Since the Zephyr executable is a native application, it can be debugged and -instrumented as any other native program. The program is compiled with debug -information, so it can be run directly in, for example, ``gdb`` or instrumented -with ``valgrind``. - -Because the execution of your Zephyr application is normally deterministic -(there are no asynchronous or random components), you can execute the -code multiple times and get the exact same result. Instrumenting the -code does not affect its execution. - -To ease debugging you may want to compile your code without optimizations -(e.g., -O0) by setting :kconfig:option:`CONFIG_NO_OPTIMIZATIONS`. - -.. _native_posix_asan: - -Address Sanitizer (ASan) -======================== - -You can also build Zephyr with the `Address Sanitizer`_. To do this, set -:kconfig:option:`CONFIG_ASAN`, for example, in the application project file, or in the -``west build`` or ``cmake`` command line invocation. - -Note that you will need the ASan library installed in your system. -In Debian/Ubuntu this is ``libasan1``. - -.. _Address Sanitizer: - https://github.com/google/sanitizers/wiki/AddressSanitizer - -Undefined Behavior Sanitizer (UBSan) -==================================== - -You can also build Zephyr with the `Undefined Behavior Sanitizer`_. To do this, set -:kconfig:option:`CONFIG_UBSAN`, for example, in the application project file, or in the -``west build`` or ``cmake`` command line invocation. - -.. _Undefined Behavior Sanitizer: - https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html - -Coverage reports -================ - -See -:ref:`coverage reports using the POSIX architecture`. +Now you have a Linux executable, ``./build/zephyr/zephyr.exe``, you can use just like any +other Linux program. +You can run, debug, build it with sanitizers or with coverage just like with +:ref:`native_sim`. +Please check :ref:`native_sim's how to` for more info. .. _native_posix32_64: 32 and 64bit versions ********************* -native_posix comes with two targets: A 32 bit and 64 bit version. +Just like :ref:`native_sim`, ``native_posix`` comes with two targets: +A 32 bit and 64 bit version. The 32 bit version, ``native_posix``, is the default target, which will compile your code for the ILP32 ABI (i386 in a x86 or x86_64 system) where pointers and longs are 32 bits. @@ -151,388 +94,3 @@ one with a 32bit userspace. The 64 bit version, ``native_posix_64``, compiles your code targeting the LP64 ABI (x86-64 in x86 systems), where pointers and longs are 64 bits. You can use this target if you cannot compile or run 32 bit binaries. - -If you are using another 32 bit POSIX arch target you may also override its ABI -target and pointer bit width by setting :kconfig:option:`CONFIG_64BIT`. - - -Rationale for this port and comparison with other options -********************************************************* - -The native_posix board shares the overall -:ref:`intent of the POSIX architecture`, -while being a HW agnostic test platform which in some cases utilizes the host -OS peripherals. -It does not intend to model any particular HW, and as such can only be used -to develop and test application code which is far decoupled from the HW. - -For developing and testing SW which requires specific HW, while retaining the -benefits of the POSIX architecture other solutions like the -:ref:`bsim boards` -should be considered. - -Check the :ref:`POSIX architecture comparison ` -with other development and test options for more insights. - -.. _native_posix_architecture: - -Architecture -************ - -This board is based on the POSIX architecture port of Zephyr and shares -:ref:`its basic architecture` regarding threading -and CPU/HW scheduling. - -This board does not try to emulate any particular embedded CPU or SOC. -The code is compiled natively for the host system (typically x86). - -About time in native_posix -========================== - -Normally simulated time runs fully decoupled from the real host time -and as fast as the host compute power would allow. -This is desirable when running in a debugger or testing in batch, but not if -interacting with external interfaces based on the real host time. - -The Zephyr kernel is only aware of the simulated time as provided by the -HW models. Therefore any normal Zephyr thread will also know only about -simulated time. - -The only link between the simulated time and the real/host time, if any, -is created by the clock and timer model. - -This model can be configured to slow down the execution of native_posix to -real time. -You can do this with the ``--rt`` and ``--no-rt`` options from the command line. -The default behavior is set with -:kconfig:option:`CONFIG_NATIVE_POSIX_SLOWDOWN_TO_REAL_TIME`. -Note that all this model does is wait before raising the -next system tick interrupt until the corresponding real/host time. -If, for some reason, native_posix runs slower than real time, all this -model can do is "catch up" as soon as possible by not delaying the -following ticks. -So if the host load is too high, or you are running in a debugger, you will -see simulated time lagging behind the real host time. -This solution ensures that normal runs are still deterministic while -providing an illusion of real timeness to the observer. - -When locked to real time, simulated time can also be set to run faster or -slower than real time. -This can be controlled with the ``--rt-ratio=`` and ``-rt-drift=`` -command line options. Note that both of these options control the same -underlying mechanism, and that ``drift`` is by definition equal to -``ratio - 1``. -It is also possible to adjust this clock speed on the fly with -:c:func:`native_rtc_adjust_clock()`. - -In this way if, for example, ``--rt-ratio=2`` is given, the simulated time -will advance at twice the real time speed. -Similarly if ``--rt-drift=-100e-6`` is given, the simulated time will progress -100ppm slower than real time. -Note that these 2 options have no meaning when running in non real-time -mode. - -How simulated time and real time relate to each other ------------------------------------------------------ - -Simulated time (``st``) can be calculated from real time (``rt``) as - -``st = (rt - last_rt) * ratio + last_st`` - -And vice-versa: - -``rt = (st - last_st) / ratio + last_rt`` - -Where ``last_rt`` and ``last_st`` are respectively the real time and the -simulated time when the last clock ratio adjustment took place. - -All times are kept in microseconds. - -.. _native_posix_peripherals: - -Peripherals -*********** - -The following peripherals are currently provided with this board: - -**Interrupt controller**: - A simple yet generic interrupt controller is provided. It can nest interrupts - and provides interrupt priorities. Interrupts can be individually masked or - unmasked. SW interrupts are also supported. - -**Clock, timer and system tick model** - This model provides the system tick timer. By default - :kconfig:option:`CONFIG_SYS_CLOCK_TICKS_PER_SEC` configures it to tick every 10ms. - - This peripheral driver also provides the needed functionality for this - architecture-specific :c:func:`k_busy_wait`. - - Please refer to the section `About time in native_posix`_ for more - information. - -**UART/Serial** - Two optional native UART drivers are available: - - **PTTY driver (UART_NATIVE_POSIX)** - With this driver, one or two Zephyr UART devices can be created. These - can be connected to the Linux process stdin/stdout or a newly created - pseudo-tty. For more information refer to the section `PTTY UART`_. - - **TTY driver (UART_NATIVE_TTY)** - An UART driver for interacting with host-attached serial port devices - (eg. USB to UART dongles). For more information refer to the section - `TTY UART`_. - -**Real time clock** - The real time clock model provides a model of a constantly powered clock. - By default this is initialized to the host time at boot. - - This RTC can also be set to start from time 0 with the ``--rtc-reset`` command - line option. - - It is possible to offset the RTC clock value at boot with the - ``--rtc-offset=`` option, - or to adjust it dynamically with the function :c:func:`native_rtc_offset`. - - After start, this RTC advances with the simulated time, and is therefore - affected by the simulated time speed ratio. - See `About time in native_posix`_ for more information. - - The time can be queried with the functions :c:func:`native_rtc_gettime_us` - and :c:func:`native_rtc_gettime`. Both accept as parameter the clock source: - - - ``RTC_CLOCK_BOOT``: It counts the simulated time passed since boot. - It is not subject to offset adjustments - - ``RTC_CLOCK_REALTIME``: RTC persistent time. It is affected by - offset adjustments. - - ``RTC_CLOCK_PSEUDOHOSTREALTIME``: A version of the real host time, - as if the host was also affected by the clock speed ratio and offset - adjustments performed to the simulated clock and this RTC. Normally - this value will be a couple of hundredths of microseconds ahead of the - simulated time, depending on the host execution speed. - This clock source should be used with care, as depending on the actual - execution speed of native_posix and the host load, - it may return a value considerably ahead of the simulated time. - -**Entropy device**: - An entropy device based on the host :c:func:`random` API. - This device will generate the same sequence of random numbers if initialized - with the same random seed. - You can change this random seed value by using the command line option: - ``--seed=`` where the value specified is a 32-bit integer - such as 97229 (decimal), 0x17BCD (hex), or 0275715 (octal). - -**Ethernet driver**: - A simple TAP based ethernet driver is provided. The driver will create - a **zeth** network interface to the host system. One can communicate with - Zephyr via this network interface. Multiple TAP based network interfaces can - be created if needed. The IP address configuration can be specified for each - network interface instance. - See :kconfig:option:`CONFIG_ETH_NATIVE_POSIX_SETUP_SCRIPT` option for more details. - The :ref:`eth-native-posix-sample` sample app provides - some use examples and more information about this driver configuration. - - Note that this device can only be used with Linux hosts, and that the user - needs elevated permissions. - -**Bluetooth controller**: - It's possible to use the host's Bluetooth adapter as a Bluetooth - controller for Zephyr. To do this the HCI device needs to be passed as - a command line option to ``zephyr.exe``. For example, to use ``hci0``, - use ``sudo zephyr.exe --bt-dev=hci0``. Using the device requires root - privileges (or the CAP_NET_ADMIN POSIX capability, to be exact) so - ``zephyr.exe`` needs to be run through ``sudo``. The chosen HCI device - must be powered down and support Bluetooth Low Energy (i.e. support the - Bluetooth specification version 4.0 or greater). - - Another possibility is to use a HCI TCP server which acts as a - :ref:`virtual Bluetooth controller` over TCP. - To connect to a HCI TCP server its IP address and port number must - be specified. For example, to connect to a HCI TCP server with IP - address 127.0.0.0 and port number 1020 use ``zephyr.exe --bt-dev=127.0.0.1:1020``. - This alternative option is mainly aimed for testing Bluetooth connectivity over - a virtual Bluetooth controller that does not depend on the Linux Bluetooth - stack and its HCI interface. - -**USB controller**: - It's possible to use the Virtual USB controller working over USB/IP - protocol. More information can be found in - :ref:`Testing USB over USP/IP in native_posix `. - -**Display driver**: - A display driver is provided that creates a window on the host machine to - render display content. - - This driver requires a 32-bit version of the `SDL2`_ library on the host - machine and ``pkg-config`` settings to correctly pickup the SDL2 install path - and compiler flags. - - On a Ubuntu 18.04 host system, for example, install the ``pkg-config`` and - ``libsdl2-dev:i386`` packages, and configure the pkg-config search path with - these commands:: - - $ sudo apt-get install pkg-config libsdl2-dev:i386 - $ export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig - -.. _SDL2: - https://www.libsdl.org/download-2.0.php - -**Flash driver**: - A flash driver is provided that accesses all flash data through a binary file - on the host file system. The behavior of the flash device can be configured - through the native POSIX board devicetree or Kconfig settings under - :kconfig:option:`CONFIG_FLASH_SIMULATOR`. - - By default the binary data is located in the file *flash.bin* in the current - working directory. The location of this file can be changed through the - command line parameter *--flash*. The flash data will be stored in raw format - and the file will be truncated to match the size specified in the devicetree - configuration. In case the file does not exists the driver will take care of - creating the file, else the existing file is used. - - The flash content can be accessed from the host system, as explained in the - `Host based flash access`_ section. - -PTTY UART -********* - -This driver can be configured with :kconfig:option:`CONFIG_UART_NATIVE_POSIX` -to instantiate up to two UARTs. By default only one UART is enabled. -With :kconfig:option:`CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE` -you can enable the second one. - -For the first UART, it can link it to a new -pseudoterminal (i.e. ``/dev/pts``), or map the UART input and -output to the executable's ``stdin`` and ``stdout``. -This is chosen by selecting either -:kconfig:option:`CONFIG_NATIVE_UART_0_ON_OWN_PTY` or -:kconfig:option:`CONFIG_NATIVE_UART_0_ON_STDINOUT` -For interactive use with the :ref:`shell_api`, choose the first (OWN_PTY) option. -The second (STDINOUT) option can be used with the shell for automated -testing, such as when piping other processes' output to control it. -This is because the shell subsystem expects access to a raw terminal, -which (by default) a normal Linux terminal is not. - -When :kconfig:option:`CONFIG_NATIVE_UART_0_ON_OWN_PTY` is chosen, the name of the -newly created UART pseudo-terminal will be displayed in the console. -If you want to interact with it manually, you should attach a terminal emulator -to it. This can be done, for example with the command:: - - $ xterm -e screen /dev/ & - -where ``/dev/`` should be replaced with the actual TTY device. - -You may also chose to automatically attach a terminal emulator to the first UART -by passing the command line option ``-attach_uart`` to the executable. -The command used for attaching to the new shell can be set with the command line -option ``-attach_uart_cmd=<"cmd">``. Where the default command is given by -:kconfig:option:`CONFIG_NATIVE_UART_AUTOATTACH_DEFAULT_CMD`. -Note that the default command assumes both ``xterm`` and ``screen`` are -installed in the system. - -.. _native_tty_uart: - -TTY UART -******** - -With this driver an application can use the polling UART API (``uart_poll_out``, -``uart_poll_in``) to write and read characters to and from a connected serial -port device. - -This driver is automatically enabled when a devicetree contains a node -with ``"zephyr,native-tty-uart"`` compatible property and ``okay`` status, such -as one below:: - - uart { - status = "okay"; - compatible = "zephyr,native-tty-uart"; - serial-port = "/dev/ttyUSB0"; - current-speed = <115200>; - }; - -Interaction with serial ports can be configured in several different ways: - -* The default serial port and baud rate can be set via the device tree - properties ``serial-port`` and ``current-speed`` respectively. The - ``serial-port`` property is optional. -* Serial port and baud rate can also be set via command line options ``X_port`` - and ``X_baud`` respectively, where ``X`` is a name of a node. Command line - options override values from the devicetree. -* The rest of the configuration options such as number of data and stop bits, - parity, as well as baud rate can be set at runtime with ``uart_configure``. - -Multiple instances of such uart drivers are supported. - -The :ref:`sample-uart-native-tty` sample app provides a working example of the -driver. - -Subsystems backends -******************* - -Apart from its own peripherals, the native_posix board also has some dedicated -backends for some of Zephyr's subsystems. These backends are designed to ease -development by integrating more seamlessly with the host operating system: - -**Console backend**: - A console backend which by default is configured to - redirect any :c:func:`printk` write to the native host application's - ``stdout``. - - This driver is selected by default if the `PTTY UART`_ is not compiled in. - Otherwise :kconfig:option:`CONFIG_UART_CONSOLE` will be set to select the UART as - console backend. - -**Logger backend**: - A backend which prints all logger output to the process ``stdout``. - It supports timestamping, which can be enabled with - :kconfig:option:`CONFIG_LOG_BACKEND_FORMAT_TIMESTAMP`; and colored output which can - be enabled with :kconfig:option:`CONFIG_LOG_BACKEND_SHOW_COLOR` and controlled - with the command line options ``--color``, ``--no-color`` and - ``--force-color``. - - In native_posix, by default, the logger is configured with - :kconfig:option:`CONFIG_LOG_MODE_IMMEDIATE`. - - This backend can be selected with :kconfig:option:`CONFIG_LOG_BACKEND_NATIVE_POSIX` - and is enabled by default unless the native_posix UART is compiled in. - In this later case, by default, the logger is set to output to the - `PTTY UART`_. - -**Tracing**: - A backend/"bottom" for Zephyr's CTF tracing subsystem which writes the tracing - data to a file in the host filesystem. - More information can be found in :ref:`Common Tracing Format ` - -Host based flash access -*********************** - -If a flash device is present, the file system partitions on the flash -device can be exposed through the host file system by enabling -:kconfig:option:`CONFIG_FUSE_FS_ACCESS`. This option enables a FUSE -(File system in User space) layer that maps the Zephyr file system calls to -the required UNIX file system calls, and provides access to the flash file -system partitions with normal operating system commands such as ``cd``, -``ls`` and ``mkdir``. - -By default the partitions are exposed through the directory *flash* in the -current working directory. This directory can be changed via the command line -option *--flash-mount*. As this directory operates as a mount point for FUSE -you have to ensure that it exists before starting the native POSIX board. - -On exit, the native POSIX board application will take care of unmounting the -directory. In the unfortunate case that the native POSIX board application -crashes, you can cleanup the stale mount point by using the program -``fusermount``:: - - $ fusermount -u flash - -Note that this feature requires a 32-bit version of the FUSE library, with a -minimal version of 2.6, on the host system and ``pkg-config`` settings to -correctly pickup the FUSE install path and compiler flags. - -On a Ubuntu 18.04 host system, for example, install the ``pkg-config`` and -``libfuse-dev:i386`` packages, and configure the pkg-config search path with -these commands:: - - $ sudo apt-get install pkg-config libfuse-dev:i386 - $ export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig diff --git a/boards/posix/native_posix/hw_counter.c b/boards/posix/native_posix/hw_counter.c index 77218a7ada4..eb02fd00807 100644 --- a/boards/posix/native_posix/hw_counter.c +++ b/boards/posix/native_posix/hw_counter.c @@ -17,6 +17,7 @@ static bool counter_running; static uint64_t counter_value; static uint64_t counter_target; static uint64_t counter_period; +static uint64_t counter_wrap; /** * Initialize the counter with prescaler of HW @@ -28,6 +29,7 @@ void hw_counter_init(void) counter_value = 0; counter_running = false; counter_period = NEVER; + counter_wrap = NEVER; } void hw_counter_triggered(void) @@ -38,7 +40,7 @@ void hw_counter_triggered(void) } hw_counter_timer = hwm_get_time() + counter_period; - counter_value = counter_value + 1; + counter_value = (counter_value + 1) % counter_wrap; if (counter_value == counter_target) { hw_irq_ctrl_set_irq(COUNTER_EVENT_IRQ); @@ -54,6 +56,16 @@ void hw_counter_set_period(uint64_t period) counter_period = period; } +/* + * Set the count value at which the counter will wrap + * The counter will count up to (counter_wrap-1), i.e.: + * 0, 1, 2,.., (counter_wrap - 1), 0 + */ +void hw_counter_set_wrap_value(uint64_t wrap_value) +{ + counter_wrap = wrap_value; +} + /** * Starts the counter. It must be previously configured with * hw_counter_set_period() and hw_counter_set_target(). @@ -82,6 +94,11 @@ void hw_counter_stop(void) hwm_find_next_timer(); } +bool hw_counter_is_started(void) +{ + return counter_running; +} + /** * Returns the current counter value. */ @@ -90,6 +107,14 @@ uint64_t hw_counter_get_value(void) return counter_value; } +/** + * Resets the counter value. + */ +void hw_counter_reset(void) +{ + counter_value = 0; +} + /** * Configures the counter to generate an interrupt * when its count value reaches target. diff --git a/boards/posix/native_posix/hw_counter.h b/boards/posix/native_posix/hw_counter.h index 5cd6dd2e577..efbb7e39e29 100644 --- a/boards/posix/native_posix/hw_counter.h +++ b/boards/posix/native_posix/hw_counter.h @@ -18,9 +18,12 @@ void hw_counter_triggered(void); void hw_counter_set_period(uint64_t period); void hw_counter_set_target(uint64_t counter_target); +void hw_counter_set_wrap_value(uint64_t wrap_value); void hw_counter_start(void); void hw_counter_stop(void); +bool hw_counter_is_started(void); uint64_t hw_counter_get_value(void); +void hw_counter_reset(void); #ifdef __cplusplus } diff --git a/boards/posix/native_posix/hw_models_top.h b/boards/posix/native_posix/hw_models_top.h index fe35f1b0455..47d3333277e 100644 --- a/boards/posix/native_posix/hw_models_top.h +++ b/boards/posix/native_posix/hw_models_top.h @@ -7,7 +7,7 @@ #ifndef _NATIVE_POSIX_HW_MODELS_H #define _NATIVE_POSIX_HW_MODELS_H -#include "zephyr/types.h" +#include #include #ifdef __cplusplus diff --git a/boards/posix/native_posix/irq_ctrl.c b/boards/posix/native_posix/irq_ctrl.c index 245f3f2eece..6524e5123a4 100644 --- a/boards/posix/native_posix/irq_ctrl.c +++ b/boards/posix/native_posix/irq_ctrl.c @@ -14,7 +14,7 @@ #include /* for find_lsb_set() */ #include "board_soc.h" #include "posix_soc.h" -#include "zephyr/types.h" +#include uint64_t irq_ctrl_timer = NEVER; diff --git a/boards/posix/native_posix/native_posix.dts b/boards/posix/native_posix/native_posix.dts index 124cc188967..75af8bdb1fd 100644 --- a/boards/posix/native_posix/native_posix.dts +++ b/boards/posix/native_posix/native_posix.dts @@ -189,7 +189,6 @@ can_loopback0: can_loopback0 { status = "okay"; compatible = "zephyr,can-loopback"; - sjw = <1>; sample-point = <875>; bus-speed = <125000>; }; @@ -201,7 +200,6 @@ * name, e.g.: sudo ip link property add dev vcan0 altname zcan0 */ host-interface = "zcan0"; - sjw = <1>; sample-point = <875>; bus-speed = <125000>; }; diff --git a/boards/posix/native_posix/native_posix.yaml b/boards/posix/native_posix/native_posix.yaml index b74534f1eca..a1fb897eb75 100644 --- a/boards/posix/native_posix/native_posix.yaml +++ b/boards/posix/native_posix/native_posix.yaml @@ -10,6 +10,7 @@ toolchain: - llvm supported: - can + - counter - eeprom - netif:eth - usb_device @@ -20,3 +21,4 @@ supported: - rtc testing: default: true +vendor: zephyr diff --git a/boards/posix/native_posix/native_posix_64.yaml b/boards/posix/native_posix/native_posix_64.yaml index b503ff2241b..56ad340f176 100644 --- a/boards/posix/native_posix/native_posix_64.yaml +++ b/boards/posix/native_posix/native_posix_64.yaml @@ -10,9 +10,11 @@ toolchain: - llvm supported: - can + - counter - eeprom - netif:eth - usb_device - adc - gpio - rtc +vendor: zephyr diff --git a/boards/posix/native_posix/native_rtc.h b/boards/posix/native_posix/native_rtc.h index aaff5ae9d92..09fc1663882 100644 --- a/boards/posix/native_posix/native_rtc.h +++ b/boards/posix/native_posix/native_rtc.h @@ -15,7 +15,7 @@ #include "hw_models_top.h" #include -#include "zephyr/types.h" +#include #ifdef __cplusplus extern "C" { diff --git a/boards/posix/native_posix/timer_model.c b/boards/posix/native_posix/timer_model.c index cfa1c10ef06..4927d1028c4 100644 --- a/boards/posix/native_posix/timer_model.c +++ b/boards/posix/native_posix/timer_model.c @@ -25,7 +25,7 @@ #include "hw_models_top.h" #include "irq_ctrl.h" #include "board_soc.h" -#include "zephyr/types.h" +#include #include #include #include "cmdline.h" diff --git a/boards/posix/native_sim/board.cmake b/boards/posix/native_sim/board.cmake index 0ec9fc6a83a..d9d444c1be9 100644 --- a/boards/posix/native_sim/board.cmake +++ b/boards/posix/native_sim/board.cmake @@ -1,3 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 set(SUPPORTED_EMU_PLATFORMS native) + +board_set_debugger_ifnset(native_gdb) +board_finalize_runner_args(native_gdb) diff --git a/boards/posix/native_sim/doc/index.rst b/boards/posix/native_sim/doc/index.rst index 22d3b6b8c31..5d4ab7b8b8c 100644 --- a/boards/posix/native_sim/doc/index.rst +++ b/boards/posix/native_sim/doc/index.rst @@ -3,18 +3,33 @@ Native simulator - native_sim ############################# +.. contents:: + :depth: 1 + :backlinks: entry + :local: + Overview ******** -The native_sim board is an evolution of :ref:`native_posix`. -Just like with :ref:`native_posix` you can build your Zephyr application -with the Zephyr kernel, creating a normal Linux executable with your host tooling, -and can debug and instrument it like any other Linux program. +The ``native_sim`` board is a :ref:`POSIX architecture` based board. +With it, a Zephyr application can be compiled together with +the Zephyr kernel, and libraries, creating a normal Linux executable. -native_sim is based on the +``native_sim`` is based on the `native simulator `_ and the :ref:`POSIX architecture`. +This board does not intend to simulate any particular HW, but it provides +a few peripherals such as an Ethernet driver, display, UART, etc., to enable +developing and testing application code which would require them. +See `Peripherals`_ for more information. + +.. note:: + + | ``native_sim`` is an evolution of the older :ref:`native_posix`. + | Some components, code, options names, and documentation will still use the old native_posix + names. But all components which worked with native_posix will work with native_sim. + Host system dependencies ************************ @@ -26,13 +41,18 @@ Please check the Important limitations ********************* -Native_sim is based on the :ref:`POSIX architecture`, and therefore +``native_sim`` is based on the :ref:`POSIX architecture`, and therefore :ref:`its limitations ` and considerations apply to it. +.. _native_sim_how_to_use: + How to use it ************* -To build, simply specify the native_sim board as target: +Compiling +========= + +To build, simply specify the ``native_sim`` board as target: .. zephyr-app-commands:: :zephyr-app: samples/hello_world @@ -41,17 +61,96 @@ To build, simply specify the native_sim board as target: :goals: build :compact: -Now you have a Linux executable, ``./build/zephyr/zephyr.exe``, you can use just like any -other Linux program. +Running +======= + +The result of the compilation is an executable (``zephyr.exe``) placed in the +``zephyr/`` subdirectory of the ``build`` folder. +Run the ``zephyr.exe`` executable as you would any other Linux console application. + +.. code-block:: console + + $ ./build/zephyr/zephyr.exe + # Press Ctrl+C to exit + +This executable accepts several command line options depending on the +compilation configuration. +You can run it with the ``--help`` command line switch to get a list of +available options. + +.. code-block:: console + + $ ./build/zephyr/zephyr.exe --help + +Note that the Zephyr kernel does not actually exit once the application is +finished. It simply goes into the idle loop forever. +Therefore you must stop the application manually (Ctrl+C in Linux). + +Application tests using the :ref:`ztest framework` will exit after all +tests have completed. + +If you want your application to gracefully finish when it reaches some point, +you may add a conditionally compiled (:kconfig:option:`CONFIG_ARCH_POSIX`) call to +``nsi_exit(int status)`` at that point. + +.. _native_sim_debug: + +Debugging +========= + +Since the Zephyr executable is a native application, it can be debugged and +instrumented as any other native program. The program is compiled with debug +information, so it can be run directly in, for example, ``gdb`` or instrumented +with ``valgrind``. + +Because the execution of your Zephyr application is normally deterministic +(there are no asynchronous or random components), you can execute the +code multiple times and get the exact same result. Instrumenting the +code does not affect its execution. + +To ease debugging you may want to compile your code without optimizations +(e.g., ``-O0``) by setting :kconfig:option:`CONFIG_NO_OPTIMIZATIONS`. + +For ease of debugging consider using an IDE as GUI for your debugger. + +.. _native_sim_asan: + +Address Sanitizer (ASan) +======================== + +You can also build Zephyr with the `Address Sanitizer`_. To do this, set +:kconfig:option:`CONFIG_ASAN`, for example, in the application project file, or in the +``west build`` or ``cmake`` command line invocation. + +Note that you will need the ASan library installed in your system. +In Debian/Ubuntu this is ``libasan1``. + +.. _Address Sanitizer: + https://github.com/google/sanitizers/wiki/AddressSanitizer + +Undefined Behavior Sanitizer (UBSan) +==================================== + +You can also build Zephyr with the `Undefined Behavior Sanitizer`_. To do this, set +:kconfig:option:`CONFIG_UBSAN`, for example, in the application project file, or in the +``west build`` or ``cmake`` command line invocation. + +.. _Undefined Behavior Sanitizer: + https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html + +Coverage reports +================ + +See +:ref:`coverage reports using the POSIX architecture`. + -You can run, debug, build it with sanitizers or with coverage just like with -:ref:`native_posix `. -Please check :ref:`native_posix's how to` for more info. +.. _native_sim32_64: 32 and 64bit versions -********************* +===================== -Just like native_posix, native_sim comes with two targets: A 32 bit and 64 bit version. +native_sim comes with two targets: A 32 bit and 64 bit version. The 32 bit version, ``native_sim``, is the default target, which will compile your code for the ILP32 ABI (i386 in a x86 or x86_64 system) where pointers and longs are 32 bits. @@ -65,41 +164,441 @@ The 64 bit version, ``native_sim_64``, compiles your code targeting the LP64 ABI (x86-64 in x86 systems), where pointers and longs are 64 bits. You can use this target if you cannot compile or run 32 bit binaries. +.. _native_sim_Clib_choice: + C library choice **************** -Unlike native_posix, native_sim may be compiled with a choice of C libraries. +native_sim may be compiled with a choice of C libraries. By default it will be compiled with the host C library (:kconfig:option:`CONFIG_EXTERNAL_LIBC`), but you can also select to build it with :kconfig:option:`CONFIG_MINIMAL_LIBC` or with :kconfig:option:`CONFIG_PICOLIBC`. +If you select some feature which are not compatible with the host C library, +:ref:`Picolibc ` will be selected by default instead. -When building with either :ref:`MINIMAL` or :ref:`PICO` libC +When building with either :ref:`minimal ` or :ref:`Picolibc` you will build your code in a more similar way as when building for the embedded target, you will be able to test your code interacting with that C library, and there will be no conflicts with the :ref:`POSIX OS abstraction` shim, but, accessing the host for test purposes from your embedded code will be more difficult, and you will have a limited choice of -:ref:`drivers and backends to chose from`. +:ref:`drivers and backends to chose from`. + +Rationale for this port and comparison with other options +********************************************************* + +The native_sim board shares the overall +:ref:`intent of the POSIX architecture`, +while being a HW agnostic test platform which in some cases utilizes the host +OS peripherals. +It does not intend to model any particular HW, and as such can only be used +to develop and test application code which is far decoupled from the HW. + +For developing and testing SW which requires specific HW, while retaining the +benefits of the POSIX architecture other solutions like the +:ref:`bsim boards` +should be considered. + +Check the :ref:`POSIX architecture comparison ` +with other development and test options for more insights. + +.. _native_sim_architecture: Architecture ************ -:ref:`native_posix's architecture description` as well as the -:ref:`POSIX architecture description` are directly -applicable to native_sim. +This board is based on the POSIX architecture port of Zephyr and shares +:ref:`its basic architecture` regarding threading +and CPU/HW scheduling. -If you are interested on the inner workigns of the native simulator itself, you can check +If you are interested on the inner workings of the native simulator itself, you can check `its documentation `_. +This board does not try to emulate any particular embedded CPU or SOC. +The code is compiled natively for the host system (typically x86). + +About time in native_sim +======================== + +Normally simulated time runs fully decoupled from the real host time +and as fast as the host compute power would allow. +This is desirable when running in a debugger or testing in batch, but not if +interacting with external interfaces based on the real host time. + +The Zephyr kernel is only aware of the simulated time as provided by the +HW models. Therefore any normal Zephyr thread will also know only about +simulated time. + +The only link between the simulated time and the real/host time, if any, +is created by the clock and timer model. + +This model can be configured to slow down the execution of native_sim to +real time. +You can do this with the ``--rt`` and ``--no-rt`` options from the command line. +The default behavior is set with +:kconfig:option:`CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME`. + +Note that all this model does is wait before raising the +next system tick interrupt until the corresponding real/host time. +If, for some reason, native_sim runs slower than real time, all this +model can do is "catch up" as soon as possible by not delaying the +following ticks. +So if the host load is too high, or you are running in a debugger, you will +see simulated time lagging behind the real host time. +This solution ensures that normal runs are still deterministic while +providing an illusion of real timeness to the observer. + +When locked to real time, simulated time can also be set to run faster or +slower than real time. +This can be controlled with the ``--rt-ratio=`` and ``-rt-drift=`` +command line options. Note that both of these options control the same +underlying mechanism, and that ``drift`` is by definition equal to +``ratio - 1``. +It is also possible to adjust this clock speed on the fly with +:c:func:`native_rtc_adjust_clock()`. + +In this way if, for example, ``--rt-ratio=2`` is given, the simulated time +will advance at twice the real time speed. +Similarly if ``--rt-drift=-100e-6`` is given, the simulated time will progress +100ppm slower than real time. +Note that these 2 options have no meaning when running in non real-time +mode. + +How simulated time and real time relate to each other +----------------------------------------------------- + +Simulated time (``st``) can be calculated from real time (``rt``) as + +.. math:: + st = (rt - last\_rt) \times ratio + last\_st + +And vice-versa: + +.. math:: + rt = (st - last\_st) / ratio + last\_rt + +Where ``last_rt`` and ``last_st`` are respectively the real time and the +simulated time when the last clock ratio adjustment took place. + +All times are kept in microseconds. + .. _native_sim_peripherals: -Peripherals, subsystems backends and host based flash access -************************************************************ +Peripherals +*********** + +The following peripherals are currently provided with this board: + +**Interrupt controller** + A simple yet generic interrupt controller is provided. It can nest interrupts + and provides interrupt priorities. Interrupts can be individually masked or + unmasked. SW interrupts are also supported. + +**Clock, timer and system tick model** + This model provides the system tick timer. By default + :kconfig:option:`CONFIG_SYS_CLOCK_TICKS_PER_SEC` configures it to tick every 10ms. + + Please refer to the section `About time in native_sim`_ for more + information. + +**UART/Serial** + Two optional native UART drivers are available: + + **PTTY driver (UART_NATIVE_POSIX)** + With this driver, one or two Zephyr UART devices can be created. These + can be connected to the Linux process stdin/stdout or a newly created + pseudo-tty. For more information refer to the section `PTTY UART`_. + + **TTY driver (UART_NATIVE_TTY)** + An UART driver for interacting with host-attached serial port devices + (eg. USB to UART dongles). For more information refer to the section + `TTY UART`_. + +**Real time clock** + The real time clock model provides a model of a constantly powered clock. + By default this is initialized to the host time at boot. + + This RTC can also be set to start from time 0 with the ``--rtc-reset`` command + line option. + + It is possible to offset the RTC clock value at boot with the + ``--rtc-offset=`` option, + or to adjust it dynamically with the function :c:func:`native_rtc_offset`. + + After start, this RTC advances with the simulated time, and is therefore + affected by the simulated time speed ratio. + See `About time in native_sim`_ for more information. + + The time can be queried with the functions :c:func:`native_rtc_gettime_us` + and :c:func:`native_rtc_gettime`. Both accept as parameter the clock source: + + - ``RTC_CLOCK_BOOT``: It counts the simulated time passed since boot. + It is not subject to offset adjustments + - ``RTC_CLOCK_REALTIME``: RTC persistent time. It is affected by + offset adjustments. + - ``RTC_CLOCK_PSEUDOHOSTREALTIME``: A version of the real host time, + as if the host was also affected by the clock speed ratio and offset + adjustments performed to the simulated clock and this RTC. Normally + this value will be a couple of hundredths of microseconds ahead of the + simulated time, depending on the host execution speed. + This clock source should be used with care, as depending on the actual + execution speed of native_sim and the host load, + it may return a value considerably ahead of the simulated time. + +**Entropy device** + An entropy device based on the host :c:func:`random` API. + This device will generate the same sequence of random numbers if initialized + with the same random seed. + You can change this random seed value by using the command line option: + :samp:`--seed={}` where the value specified is a 32-bit integer + such as 97229 (decimal), 0x17BCD (hex), or 0275715 (octal). + +**Ethernet driver** + A simple TAP based ethernet driver is provided. The driver expects that the + **zeth** network interface already exists in the host system. The **zeth** + network interface can be created by the ``net-setup.sh`` script found in + the `net-tools`_ zephyr project repository. User can communicate with the + Zephyr instance via the **zeth** network interface. Multiple TAP based + network interfaces can be created if needed. The IP address configuration + can be specified for each network interface instance. + + Note that this device can only be used with Linux hosts. + +.. _net-tools: + https://github.com/zephyrproject-rtos/net-tools + + +**Bluetooth controller** + It's possible to use the host's Bluetooth adapter as a Bluetooth + controller for Zephyr. To do this the HCI device needs to be passed as + a command line option to ``zephyr.exe``. For example, to use ``hci0``, + use ``sudo zephyr.exe --bt-dev=hci0``. Using the device requires root + privileges (or the CAP_NET_ADMIN POSIX capability, to be exact) so + ``zephyr.exe`` needs to be run through ``sudo``. The chosen HCI device + must be powered down and support Bluetooth Low Energy (i.e. support the + Bluetooth specification version 4.0 or greater). + + Another possibility is to use a HCI TCP server which acts as a + :ref:`virtual Bluetooth controller` over TCP. + To connect to a HCI TCP server its IP address and port number must + be specified. For example, to connect to a HCI TCP server with IP + address 127.0.0.0 and port number 1020 use ``zephyr.exe --bt-dev=127.0.0.1:1020``. + This alternative option is mainly aimed for testing Bluetooth connectivity over + a virtual Bluetooth controller that does not depend on the Linux Bluetooth + stack and its HCI interface. + +**USB controller** + It's possible to use the Virtual USB controller working over USB/IP + protocol. More information can be found in + :ref:`Testing USB over USP/IP in native_sim `. + +**Display driver** + A display driver is provided that creates a window on the host machine to + render display content. + + This driver requires a 32-bit version of the `SDL2`_ library on the host + machine and ``pkg-config`` settings to correctly pickup the SDL2 install path + and compiler flags. + + On a Ubuntu 22.04 host system, for example, install the ``pkg-config`` and + ``libsdl2-dev:i386`` packages, and configure the pkg-config search path with + these commands: + + .. code-block:: console + + $ sudo apt-get install pkg-config libsdl2-dev:i386 + $ export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig + +.. _SDL2: + https://www.libsdl.org/download-2.0.php + +**Flash driver** + A flash driver is provided that accesses all flash data through a binary file + on the host file system. The behavior of the flash device can be configured + through the native_sim board devicetree or Kconfig settings under + :kconfig:option:`CONFIG_FLASH_SIMULATOR`. + + By default the binary data is located in the file :file:`flash.bin` in the current + working directory. The location of this file can be changed through the + command line parameter ``--flash``. The flash data will be stored in raw format + and the file will be truncated to match the size specified in the devicetree + configuration. In case the file does not exists the driver will take care of + creating the file, else the existing file is used. + + The flash content can be accessed from the host system, as explained in the + `Host based flash access`_ section. + +.. _native_ptty_uart: + +PTTY UART +========= + +This driver can be configured with :kconfig:option:`CONFIG_UART_NATIVE_POSIX` +to instantiate up to two UARTs. By default only one UART is enabled. +With :kconfig:option:`CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE` +you can enable the second one. + +For the first UART, it can link it to a new +pseudoterminal (i.e. :file:`/dev/pts{}`), or map the UART input and +output to the executable's ``stdin`` and ``stdout``. +This is chosen by selecting either +:kconfig:option:`CONFIG_NATIVE_UART_0_ON_OWN_PTY` or +:kconfig:option:`CONFIG_NATIVE_UART_0_ON_STDINOUT` +For interactive use with the :ref:`shell_api`, choose the first (OWN_PTY) option. +The second (STDINOUT) option can be used with the shell for automated +testing, such as when piping other processes' output to control it. +This is because the shell subsystem expects access to a raw terminal, +which (by default) a normal Linux terminal is not. + +When :kconfig:option:`CONFIG_NATIVE_UART_0_ON_OWN_PTY` is chosen, the name of the +newly created UART pseudo-terminal will be displayed in the console. +If you want to interact with it manually, you should attach a terminal emulator +to it. This can be done, for example with the command: + +.. code-block:: console + + $ xterm -e screen /dev/ & + +where :file:`/dev/tty{}` should be replaced with the actual TTY device. + +You may also chose to automatically attach a terminal emulator to the first UART +by passing the command line option ``-attach_uart`` to the executable. +The command used for attaching to the new shell can be set with the command line +option ``-attach_uart_cmd=<"cmd">``. Where the default command is given by +:kconfig:option:`CONFIG_NATIVE_UART_AUTOATTACH_DEFAULT_CMD`. +Note that the default command assumes both ``xterm`` and ``screen`` are +installed in the system. + +This driver only supports poll mode. Interrupt and async mode are not supported. +Neither runtime configuration or line control are supported. + +.. _native_tty_uart: + +TTY UART +======== + +With this driver an application can use the polling UART API (``uart_poll_out``, +``uart_poll_in``) to write and read characters to and from a connected serial +port device. + +This driver is automatically enabled when a devicetree contains a node +with ``"zephyr,native-tty-uart"`` compatible property and ``okay`` status, such +as one below. + +.. code-block:: dts + + uart { + status = "okay"; + compatible = "zephyr,native-tty-uart"; + serial-port = "/dev/ttyUSB0"; + current-speed = <115200>; + }; + +Interaction with serial ports can be configured in several different ways: + +* The default serial port and baud rate can be set via the device tree + properties ``serial-port`` and ``current-speed`` respectively. The + ``serial-port`` property is optional. +* Serial port and baud rate can also be set via command line options ``X_port`` + and ``X_baud`` respectively, where ``X`` is a name of a node. Command line + options override values from the devicetree. +* The rest of the configuration options such as number of data and stop bits, + parity, as well as baud rate can be set at runtime with ``uart_configure``. + +Multiple instances of such uart drivers are supported. + +The :zephyr:code-sample:`uart-native-tty` sample app provides a working example of the +driver. + +This driver only supports poll mode. Interrupt and async mode are not supported. +It has runtime configuration support, but no line control support. + +.. _native_sim_backends: + +Subsystems backends +******************* + +Apart from its own peripherals, the native_sim board also has some dedicated +backends for some of Zephyr's subsystems. These backends are designed to ease +development by integrating more seamlessly with the host operating system: + +**Console backend**: + A console backend which by default is configured to + redirect any :c:func:`printk` write to the native host application's + ``stdout``. + + This driver is selected by default if the `PTTY UART`_ is not compiled in. + Otherwise :kconfig:option:`CONFIG_UART_CONSOLE` will be set to select the UART as + console backend. + +**Logger backend**: + A backend which prints all logger output to the process ``stdout``. + It supports timestamping, which can be enabled with + :kconfig:option:`CONFIG_LOG_BACKEND_FORMAT_TIMESTAMP`; and colored output which can + be enabled with :kconfig:option:`CONFIG_LOG_BACKEND_SHOW_COLOR` and controlled + with the command line options ``--color``, ``--no-color`` and + ``--force-color``. + + In native_sim, by default, the logger is configured with + :kconfig:option:`CONFIG_LOG_MODE_IMMEDIATE`. + + This backend can be selected with :kconfig:option:`CONFIG_LOG_BACKEND_NATIVE_POSIX` + and is enabled by default unless the PTTY UART is compiled in. + In this later case, by default, the logger is set to output to the + `PTTY UART`_. + +**Tracing**: + A backend/"bottom" for Zephyr's CTF tracing subsystem which writes the tracing + data to a file in the host filesystem. + More information can be found in :ref:`Common Tracing Format ` + +.. _native_fuse_flash: + +Host based flash access +*********************** + +If a flash device is present, the file system partitions on the flash +device can be exposed through the host file system by enabling +:kconfig:option:`CONFIG_FUSE_FS_ACCESS`. This option enables a FUSE +(File system in User space) layer that maps the Zephyr file system calls to +the required UNIX file system calls, and provides access to the flash file +system partitions with normal operating system commands such as ``cd``, +``ls`` and ``mkdir``. + +By default the partitions are exposed through the directory :file:`flash/` in the +current working directory. This directory can be changed via the command line +option ``--flash-mount``. As this directory operates as a mount point for FUSE +you have to ensure that it exists before starting the native_sim board. + +On exit, the native_sim board application will take care of unmounting the +directory. In the unfortunate case that the native_sim board application +crashes, you can cleanup the stale mount point by using the program +``fusermount``: + +.. code-block:: console + + $ fusermount -u flash + +Note that this feature requires a 32-bit version of the FUSE library, with a +minimal version of 2.6, on the host system and ``pkg-config`` settings to +correctly pickup the FUSE install path and compiler flags. + +On a Ubuntu 22.04 host system, for example, install the ``pkg-config`` and +``libfuse-dev:i386`` packages, and configure the pkg-config search path with +these commands: + +.. code-block:: console + + $ sudo apt-get install pkg-config libfuse-dev:i386 + $ export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig + +.. _native_sim_peripherals_c_compat: + +Peripherals and backends C library compatibility +************************************************ -Today, native_sim supports the exact same -:ref:`peripherals and backends as native_posix`, -with the only caveat that some of these are, so far, only available when compiling with the -host libC (:kconfig:option:`CONFIG_EXTERNAL_LIBC`). +Today, some native_sim peripherals and backends are, so far, only available when compiling with the +host libC (:kconfig:option:`CONFIG_EXTERNAL_LIBC`): .. csv-table:: Drivers/backends vs libC choice :header: Driver class, driver name, driver kconfig, libC choices @@ -111,7 +610,7 @@ host libC (:kconfig:option:`CONFIG_EXTERNAL_LIBC`). display, display SDL, :kconfig:option:`CONFIG_SDL_DISPLAY`, all entropy, native posix entropy, :kconfig:option:`CONFIG_FAKE_ENTROPY_NATIVE_POSIX`, all eprom, eprom emulator, :kconfig:option:`CONFIG_EEPROM_EMULATOR`, host libC - ethernet, eth native_posix, :kconfig:option:`CONFIG_ETH_NATIVE_POSIX`, host libC + ethernet, eth native_posix, :kconfig:option:`CONFIG_ETH_NATIVE_POSIX`, all flash, flash simulator, :kconfig:option:`CONFIG_FLASH_SIMULATOR`, all flash, host based flash access, :kconfig:option:`CONFIG_FUSE_FS_ACCESS`, host libC gpio, GPIO emulator, :kconfig:option:`CONFIG_GPIO_EMUL`, all @@ -121,7 +620,7 @@ host libC (:kconfig:option:`CONFIG_EXTERNAL_LIBC`). log backend, native backend, :kconfig:option:`CONFIG_LOG_BACKEND_NATIVE_POSIX`, all rtc, RTC emul, :kconfig:option:`CONFIG_RTC_EMUL`, all serial, uart native posix/PTTY, :kconfig:option:`CONFIG_UART_NATIVE_POSIX`, all - serial, uart native TTY, :kconfig:option:`CONFIG_UART_NATIVE_TTY`, host libC + serial, uart native TTY, :kconfig:option:`CONFIG_UART_NATIVE_TTY`, all spi, SPI emul, :kconfig:option:`CONFIG_SPI_EMUL`, all system tick, native_posix timer, :kconfig:option:`CONFIG_NATIVE_POSIX_TIMER`, all tracing, Posix tracing backend, :kconfig:option:`CONFIG_TRACING_BACKEND_POSIX`, all diff --git a/boards/posix/native_sim/native_sim.yaml b/boards/posix/native_sim/native_sim.yaml index 327cf2f6049..e2defe1ce40 100644 --- a/boards/posix/native_sim/native_sim.yaml +++ b/boards/posix/native_sim/native_sim.yaml @@ -10,6 +10,7 @@ toolchain: - llvm supported: - can + - counter - eeprom - netif:eth - usb_device @@ -18,3 +19,4 @@ supported: - spi - gpio - rtc +vendor: zephyr diff --git a/boards/posix/native_sim/native_sim_64.yaml b/boards/posix/native_sim/native_sim_64.yaml index c2c8b3ac530..52841d23b2b 100644 --- a/boards/posix/native_sim/native_sim_64.yaml +++ b/boards/posix/native_sim/native_sim_64.yaml @@ -10,9 +10,11 @@ toolchain: - llvm supported: - can + - counter - eeprom - netif:eth - usb_device - adc - gpio - rtc +vendor: zephyr diff --git a/boards/posix/nrf52_bsim/CMakeLists.txt b/boards/posix/nrf52_bsim/CMakeLists.txt deleted file mode 100644 index 9e70b603178..00000000000 --- a/boards/posix/nrf52_bsim/CMakeLists.txt +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright (c) 2023 Nordic Semiconductor ASA -# Copyright (c) 2018 Oticon A/S -# SPDX-License-Identifier: Apache-2.0 - -find_package(BabbleSim) - -zephyr_library() - -# Due to the BLE controller assumption about enum size -zephyr_compile_options( - -fshort-enums -) -# Structures layouts needs to match in the interface between the runner and the embedded SW -# The nrfx HAL uses enums in its definitions,so they need to have the same size in both, -# as both the HW models and embedded SW use them. -target_compile_options(native_simulator INTERFACE -fshort-enums) - -zephyr_library_sources( - irq_handler.c - cpu_wait.c - argparse.c - nsi_if.c - soc/nrfx_coredep.c - common/bstests_entry.c - common/cmsis/cmsis.c -) - -target_sources(native_simulator INTERFACE - common/bsim_args_runner.c - common/phy_sync_ctrl.c - common/runner_hooks.c - common/posix_arch_if.c - common/trace_hook.c -) - -zephyr_include_directories( - soc - common - common/cmsis - ${NSI_DIR}/common/src/include -) - -zephyr_library_include_directories( - ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ - ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ - ${BSIM_COMPONENTS_PATH}/libRandv2/src/ - ${ZEPHYR_BASE}/kernel/include - ${ZEPHYR_BASE}/arch/posix/include - common/ -) - -set(libpath ${BSIM_OUT_PATH}/lib) -set_property(TARGET native_simulator APPEND PROPERTY RUNNER_LINK_LIBRARIES - ${libpath}/libUtilv1.32.a - ${libpath}/libPhyComv1.32.a - ${libpath}/lib2G4PhyComv1.32.a - ${libpath}/libRandv2.32.a -) - -include(../common/natsim_config.cmake) diff --git a/boards/posix/nrf52_bsim/Kconfig b/boards/posix/nrf52_bsim/Kconfig deleted file mode 100644 index 566520fafa0..00000000000 --- a/boards/posix/nrf52_bsim/Kconfig +++ /dev/null @@ -1,34 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_NRF52_BSIM - -# The following file is normally parsed only for the ARM architecture, which is -# used by Nordic SoCs, so to make the symbols defined in this file available for -# the simulated nrf52_bsim board, which uses the POSIX architecture, the file -# must be read also from here. -source "soc/arm/nordic_nrf/Kconfig.peripherals" - -endif # BOARD_NRF52_BSIM - - -# This would eventually be shared by a possible family of simulated NRF boards -# which use BabbleSim. When that happens, we can move this to a common -# Kconfig file - -config SOC_SERIES_BSIM_NRFXX - bool - depends on SOC_POSIX - help - Any NRF simulated SOC with BabbleSim, based on the POSIX arch - -config SOC_SERIES_BSIM_NRF52X - bool - depends on SOC_SERIES_BSIM_NRFXX - help - Any NRF52 simulated SOC with BabbleSim, based on the POSIX arch - -config SOC_SERIES_BSIM_NRF53X - bool - depends on SOC_SERIES_BSIM_NRFXX - help - Any NRF53 simulated SOC with BabbleSim, based on the POSIX arch diff --git a/boards/posix/nrf52_bsim/Kconfig.board b/boards/posix/nrf52_bsim/Kconfig.board deleted file mode 100644 index 8d0254b8fec..00000000000 --- a/boards/posix/nrf52_bsim/Kconfig.board +++ /dev/null @@ -1,17 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -config BOARD_NRF52_BSIM - bool "NRF52 simulation model" - select SOC_SERIES_BSIM_NRFXX - select SOC_SERIES_BSIM_NRF52X - select SOC_COMPATIBLE_NRF - select SOC_COMPATIBLE_NRF52X - select SOC_COMPATIBLE_NRF52833 - select NRF_RTC_TIMER - select CLOCK_CONTROL - select HAS_NRFX - select HAS_NORDIC_DRIVERS - select NATIVE_LIBRARY - help - Will produce a console Linux process which can be executed natively. - It needs the BabbleSim simulator both in compile time and to execute diff --git a/boards/posix/nrf52_bsim/Kconfig.defconfig b/boards/posix/nrf52_bsim/Kconfig.defconfig deleted file mode 100644 index 8fae1e9126e..00000000000 --- a/boards/posix/nrf52_bsim/Kconfig.defconfig +++ /dev/null @@ -1,57 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_NRF52_BSIM - -config BUILD_OUTPUT_BIN - default n - -config BUILD_OUTPUT_EXE - default y - -config OUTPUT_PRINT_MEMORY_USAGE - default n - -config BOARD - default "nrf52_bsim" - -config NATIVE_SIMULATOR_CPU_N - default 0 - -config SYS_CLOCK_HW_CYCLES_PER_SEC - default 32768 - -config SYS_CLOCK_TICKS_PER_SEC - default 128 if !TICKLESS_KERNEL - default 32768 - -config BT_CTLR - default y - depends on BT - -# The 15.4 driver Tx encryption is currently not functional with this -# simulated board => we disable it by default. With this Openthread will normally -# default to encrypt packets on its own. -config NRF_802154_ENCRYPTION - default n - -if LOG - -# For this board we can log synchronously without any problem -# Doing so will be nicer for debugging -choice LOG_MODE - default LOG_MODE_IMMEDIATE -endchoice - -endif # LOG - -if CONSOLE - -config POSIX_ARCH_CONSOLE - default y if !SERIAL - -config UART_CONSOLE - default y if SERIAL - -endif # CONSOLE - -endif # BOARD_NRF52_BSIM diff --git a/boards/posix/nrf52_bsim/argparse.c b/boards/posix/nrf52_bsim/argparse.c deleted file mode 100644 index df1a222fffb..00000000000 --- a/boards/posix/nrf52_bsim/argparse.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2017 Oticon A/S - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include "bs_tracing.h" -#include "bstests.h" -#include "bs_cmd_line.h" -#include "bs_dynargs.h" -#include "posix_native_task.h" -#include "nsi_tracing.h" -#include "nsi_main.h" - -static const char exe_name[] = "nrf52_bsim options:"; - -static char *testid; - -static void cmd_testid_found(char *argv, int offset) -{ - bst_set_testapp_mode(testid); -} - -static void cmd_testlist_found(char *argv, int offset) -{ - bst_print_testslist(); - nsi_exit(0); -} - -static void nrfbsim_register_args(void) -{ - static bs_args_struct_t args_struct_toadd[] = { - { - .option = "testid", - .name = "testid", - .type = 's', - .dest = (void *)&testid, - .call_when_found = cmd_testid_found, - .descript = "Which of the bs tests shall be run. Run -testslist for more info" - }, - { - .is_switch = true, - .option = "testslist", - .type = 'b', - .call_when_found = cmd_testlist_found, - .descript = "Print information about the available bs application tests" - }, - ARG_TABLE_ENDMARKER - }; - - bs_add_extra_dynargs(args_struct_toadd); - bs_args_override_exe_name((char *)exe_name); -} - -NATIVE_TASK(nrfbsim_register_args, PRE_BOOT_1, 100); diff --git a/boards/posix/nrf52_bsim/board.cmake b/boards/posix/nrf52_bsim/board.cmake deleted file mode 100644 index 0ec9fc6a83a..00000000000 --- a/boards/posix/nrf52_bsim/board.cmake +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -set(SUPPORTED_EMU_PLATFORMS native) diff --git a/boards/posix/nrf52_bsim/board_soc.h b/boards/posix/nrf52_bsim/board_soc.h deleted file mode 100644 index 7665d49993e..00000000000 --- a/boards/posix/nrf52_bsim/board_soc.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2017 Oticon A/S - * - * SPDX-License-Identifier: Apache-2.0 - */ -/** - * @file Extra definitions provided by the board to soc.h - * - * Background: - * The POSIX ARCH/SOC/board layering is different than in normal archs - * The "SOC" does not provide almost any of the typical SOC functionality - * but that is left for the "board" to define it - * Device code may rely on the soc.h defining some things (like the interrupts - * numbers) - * Therefore this file is included from the inf_clock soc.h to allow a board - * to define that kind of SOC related snippets - */ - -#ifndef _POSIX_NRF52_BOARD_SOC_H -#define _POSIX_NRF52_BOARD_SOC_H - -#include -#include - -#include -#include -#include -#include -#include -#include -#include "cmsis.h" - -#define OFFLOAD_SW_IRQ SWI0_EGU0_IRQn - -#define FLASH_PAGE_ERASE_MAX_TIME_US 89700UL -#define FLASH_PAGE_MAX_CNT 256UL - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _POSIX_NRF52_BOARD_SOC_H */ diff --git a/boards/posix/nrf52_bsim/common/cmsis/cmsis.c b/boards/posix/nrf52_bsim/common/cmsis/cmsis.c deleted file mode 100644 index c9deab58ee2..00000000000 --- a/boards/posix/nrf52_bsim/common/cmsis/cmsis.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * Copyright (c) 2020 Oticon A/S - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include "irq_ctrl.h" -#include "posix_core.h" -#include "posix_board_if.h" -#include "board_soc.h" -#include "bs_tracing.h" - -/* - * Replacement for ARMs NVIC functions() - */ -void NVIC_SetPendingIRQ(IRQn_Type IRQn) -{ - hw_irq_ctrl_raise_im_from_sw(CONFIG_NATIVE_SIMULATOR_CPU_N, IRQn); -} - -void NVIC_ClearPendingIRQ(IRQn_Type IRQn) -{ - hw_irq_ctrl_clear_irq(CONFIG_NATIVE_SIMULATOR_CPU_N, IRQn); -} - -void NVIC_DisableIRQ(IRQn_Type IRQn) -{ - hw_irq_ctrl_disable_irq(CONFIG_NATIVE_SIMULATOR_CPU_N, IRQn); -} - -void NVIC_EnableIRQ(IRQn_Type IRQn) -{ - hw_irq_ctrl_enable_irq(CONFIG_NATIVE_SIMULATOR_CPU_N, IRQn); -} - -void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) -{ - hw_irq_ctrl_prio_set(CONFIG_NATIVE_SIMULATOR_CPU_N, IRQn, priority); -} - -uint32_t NVIC_GetPriority(IRQn_Type IRQn) -{ - return hw_irq_ctrl_get_prio(CONFIG_NATIVE_SIMULATOR_CPU_N, IRQn); -} - -void NVIC_SystemReset(void) -{ - bs_trace_error_time_line("%s called. Exiting\n", __func__); -} - -/* - * Replacements for some other CMSIS functions - */ -void __enable_irq(void) -{ - hw_irq_ctrl_change_lock(CONFIG_NATIVE_SIMULATOR_CPU_N, false); -} - -void __disable_irq(void) -{ - hw_irq_ctrl_change_lock(CONFIG_NATIVE_SIMULATOR_CPU_N, true); -} - -uint32_t __get_PRIMASK(void) -{ - return hw_irq_ctrl_get_current_lock(CONFIG_NATIVE_SIMULATOR_CPU_N); -} - -void __set_PRIMASK(uint32_t primask) -{ - hw_irq_ctrl_change_lock(CONFIG_NATIVE_SIMULATOR_CPU_N, primask != 0); -} - -void __WFE(void) -{ - nrfbsim_WFE_model(); -} - -void __WFI(void) -{ - __WFE(); -} - -void __SEV(void) -{ - nrfbsim_SEV_model(); -} diff --git a/boards/posix/nrf52_bsim/common/trace_hook.c b/boards/posix/nrf52_bsim/common/trace_hook.c deleted file mode 100644 index 123eb4a22cc..00000000000 --- a/boards/posix/nrf52_bsim/common/trace_hook.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2017 Oticon A/S - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include "bs_tracing.h" - -/* - * Provide the posix_print_* functions required from all POSIX arch boards - * (This functions provide a lower level, more direct, print mechanism than - * Zephyr's printk or logger and therefore can be relied on even if the kernel - * is down. - */ - -void posix_vprint_error_and_exit(const char *format, va_list vargs) -{ - bs_trace_vprint(BS_TRACE_ERROR, NULL, 0, 0, BS_TRACE_AUTOTIME, 0, - format, vargs); -} - -void posix_vprint_warning(const char *format, va_list vargs) -{ - bs_trace_vprint(BS_TRACE_WARNING, NULL, 0, 0, BS_TRACE_AUTOTIME, 0, - format, vargs); -} - -void posix_vprint_trace(const char *format, va_list vargs) -{ - bs_trace_vprint(BS_TRACE_RAW, NULL, 0, 2, BS_TRACE_AUTOTIME, 0, - format, vargs); -} - -void posix_print_error_and_exit(const char *format, ...) -{ - va_list variable_argsp; - - va_start(variable_argsp, format); - posix_vprint_error_and_exit(format, variable_argsp); - va_end(variable_argsp); -} - -void posix_print_warning(const char *format, ...) -{ - va_list variable_argsp; - - va_start(variable_argsp, format); - bs_trace_vprint(BS_TRACE_WARNING, NULL, 0, 0, BS_TRACE_AUTOTIME, 0, - format, variable_argsp); - va_end(variable_argsp); -} - -void posix_print_trace(const char *format, ...) -{ - va_list variable_argsp; - - va_start(variable_argsp, format); - bs_trace_vprint(BS_TRACE_RAW, NULL, 0, 2, BS_TRACE_AUTOTIME, 0, - format, variable_argsp); - va_end(variable_argsp); -} - -int posix_trace_over_tty(int file_number) -{ - return bs_trace_is_tty(file_number); -} - -void nsi_vprint_error_and_exit(const char *format, va_list vargs) -{ - bs_trace_vprint(BS_TRACE_ERROR, NULL, 0, 0, BS_TRACE_AUTOTIME, 0, - format, vargs); -} - -void nsi_vprint_warning(const char *format, va_list vargs) -{ - bs_trace_vprint(BS_TRACE_WARNING, NULL, 0, 0, BS_TRACE_AUTOTIME, 0, - format, vargs); -} - -void nsi_vprint_trace(const char *format, va_list vargs) -{ - bs_trace_vprint(BS_TRACE_RAW, NULL, 0, 2, BS_TRACE_AUTOTIME, 0, - format, vargs); -} diff --git a/boards/posix/nrf52_bsim/doc/index.rst b/boards/posix/nrf52_bsim/doc/index.rst deleted file mode 100644 index a954217e21a..00000000000 --- a/boards/posix/nrf52_bsim/doc/index.rst +++ /dev/null @@ -1,195 +0,0 @@ -.. _nrf52_bsim: - -NRF52 simulated board (BabbleSim) -################################# - -.. contents:: - :depth: 1 - :backlinks: entry - :local: - - -Overview -******** - -This is a :ref:`POSIX architecture` -based simulated NRF52 board which uses `BabbleSim`_ to simulate the radio -activity. -This board models some of the NRF52 SOC peripherals: - -* Radio -* Timers -* RTC (Real Time Counter) -* RNG (Random Number Generator) -* AES CCM & AES ECB encryption HW -* AAR (Accelerated Address Resolver) -* CLOCK (Clock control) -* PPI (Programmable Peripheral Interconnect) -* EGU (Event Generator Unit) -* GPIO & GPIOTE -* TEMP (Temperature sensor) -* UICR (User Information Configuration Registers) -* FICR (Factory Information Configuration Registers) -* NVMC (Non-Volatile Memory Controller) - -The nrf52_bsim board definition uses the POSIX architecture and the native simulator to -run applications natively on the development system, this has the benefit of -providing native code execution performance and easy debugging using -native tools, but inherits :ref:`its limitations `. - -.. _BabbleSim: - https://BabbleSim.github.io - -.. _nrf52bsim_build_and_run: - -Building and running -********************** - -This board requires the host 32 bit C library. See -:ref:`POSIX Arch dependencies`. - -To target this board you also need to have `BabbleSim`_ compiled in your system. -If you do not have it yet, the easiest way to get it, is to enable the babblesim group -in your local west configuration, running west update, and building the simulator: - -.. code-block:: console - - west config manifest.group-filter -- +babblesim - west update - cd ${ZEPHYR_BASE}/../tools/bsim - make everything -j 8 - -.. note:: - - If you need more BabbleSim components, or more up to date versions, - you can check the `BabbleSim web page `_ - for instructions on how to - `fetch `_ and - `build `_ it. - -You will now need to define two environment variables to point to your BabbleSim -installation, ``BSIM_OUT_PATH`` and ``BSIM_COMPONENTS_PATH``. -If you followed the previous steps, you can just do: - -.. code-block:: console - - export BSIM_OUT_PATH=${ZEPHYR_BASE}/../tools/bsim - export BSIM_COMPONENTS_PATH=${BSIM_OUT_PATH}/components/ - -.. note:: - - You can add these two lines to your ``~/.zephyrrc`` file, or to your shell - initialization script (``~/.bashrc``), so you won't need to rerun them - manually for each new shell. - -You're now ready to build applications targeting this board, for example: - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :host-os: unix - :board: nrf52_bsim - :goals: build - :compact: - -Then you can execute your application using: - -.. code-block:: console - - $ ./build/zephyr/zephyr.exe -nosim - # Press Ctrl+C to exit - -Note that the executable is a BabbleSim executable. The ``-nosim`` command line -option indicates you want to run it detached from a BabbleSim simulation. This -is possible only while there is no radio activity. But is perfectly fine for -most Zephyr samples and tests. - -When you want to run a simulation with radio activity you need to run also the -BableSim 2G4 (2.4GHz) physical layer simulation (phy). - -For example, if you would like to run a simple case with 1 BLE ``central_hr`` -sample application connecting to a BLE ``peripheral`` sample application: -Build the ``central_hr`` application targeting this board and copy the resulting -executable to the simulator bin folder with a sensible name: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/central_hr - :host-os: unix - :board: nrf52_bsim - :goals: build - :compact: - -.. code-block:: console - - $ cp build/zephyr/zephyr.exe \ - ${BSIM_OUT_PATH}/bin/bs_nrf52_bsim_samples_bluetooth_central_hr - -Do the same for the ``peripheral`` sample app: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/peripheral - :host-os: unix - :board: nrf52_bsim - :goals: build - :compact: - -.. code-block:: console - - $ cp build/zephyr/zephyr.exe \ - ${BSIM_OUT_PATH}/bin/bs_nrf52_bsim_samples_bluetooth_peripheral - -And then run them together with BabbleSim's 2G4 physical layer simulation: - -.. code-block:: console - - cd ${BSIM_OUT_PATH}/bin/ - ./bs_nrf52_bsim_samples_bluetooth_peripheral -s=trial_sim -d=0 & - ./bs_nrf52_bsim_samples_bluetooth_central_hr -s=trial_sim -d=1 & - ./bs_2G4_phy_v1 -s=trial_sim -D=2 -sim_length=10e6 & - -Where the ``-s`` command line option provides a string which uniquely identifies -this simulation; the ``-D`` option tells the Phy how many devices will be run -in this simulation; the ``-d`` option tells each device which is its device -number in the simulation; and the ``-sim_length`` option specifies the length -of the simulation in microseconds. -BabbleSim devices and Phy support many command line switches. -Run them with ``-help`` for more information. - -You can find more information about how to run BabbleSim simulations in -`this BabbleSim example `_. - -Debugging, coverage and address sanitizer -***************************************** - -Just like with :ref:`native_posix`, the resulting -executables are Linux native applications. -Therefore they can be debugged or instrumented with the same tools as any other -native application, like for example ``gdb`` or ``valgrind``. - -The same -:ref:`code coverage analysis means from the POSIX arch` -are inherited in this board. -Similarly, the -:ref:`address and undefined behavior sanitizers can be used as in native_posix`. - - -Note that BabbleSim will run fine if one or several of its components are -being run in a debugger or instrumented. For example, pausing a device in a -breakpoint will pause the whole simulation. - -BabbleSim is fully deterministic by design and the results are not affected by -the host computing speed. All randomness is controlled by random seeds which can -be provided as command line options. - - -About time in BabbleSim -************************ - -Note that time in BabbleSim is simulated and decoupled from real time. Normally -simulated time will pass several orders of magnitude faster than real time, -only limited by your workstation compute power. -If for some reason you want to limit the speed of the simulation to real -time or a ratio of it, you can do so by connecting the `handbrake device`_ -to the BabbleSim Phy. - -.. _handbrake device: - https://github.com/BabbleSim/base/tree/master/device_handbrake diff --git a/boards/posix/nrf52_bsim/nsi_if.c b/boards/posix/nrf52_bsim/nsi_if.c deleted file mode 100644 index bb916c97466..00000000000 --- a/boards/posix/nrf52_bsim/nsi_if.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include "bstests.h" -#include "bs_tracing.h" -#include "phy_sync_ctrl.h" - -NATIVE_SIMULATOR_IF void nsif_cpu0_pre_cmdline_hooks(void) -{ - run_native_tasks(_NATIVE_PRE_BOOT_1_LEVEL); -} - -#define TESTCASAE_ARGV_ALLOCSIZE 128 - -static struct { - char **test_case_argv; - int test_case_argc; - int allocated_size; -} test_args; - -NATIVE_SIMULATOR_IF void nsif_cpu0_save_test_arg(char *argv) -{ - if (test_args.test_case_argc >= test_args.allocated_size) { - test_args.allocated_size += TESTCASAE_ARGV_ALLOCSIZE; - test_args.test_case_argv = realloc(test_args.test_case_argv, - test_args.allocated_size * sizeof(char *)); - if (test_args.test_case_argv == NULL) { /* LCOV_EXCL_BR_LINE */ - bs_trace_error_line("Can't allocate memory\n"); /* LCOV_EXCL_LINE */ - } - } - - bs_trace_raw(9, "cmdarg: adding '%s' to testcase args[%i]\n", - argv, test_args.test_case_argc); - test_args.test_case_argv[test_args.test_case_argc++] = argv; -} - -static void test_args_free(void) -{ - if (test_args.test_case_argv) { - free(test_args.test_case_argv); - test_args.test_case_argv = NULL; - } -} - -NATIVE_TASK(test_args_free, ON_EXIT_PRE, 100); - -NATIVE_SIMULATOR_IF void nsif_cpu0_pre_hw_init_hooks(void) -{ - run_native_tasks(_NATIVE_PRE_BOOT_2_LEVEL); - phy_sync_ctrl_connect_to_2G4_phy(); - - /* We pass to a possible testcase its command line arguments */ - bst_pass_args(test_args.test_case_argc, test_args.test_case_argv); - phy_sync_ctrl_pre_boot2(); -} - -NATIVE_SIMULATOR_IF void nsif_cpu0_boot(void) -{ - run_native_tasks(_NATIVE_PRE_BOOT_3_LEVEL); - bst_pre_init(); - phy_sync_ctrl_pre_boot3(); - posix_boot_cpu(); - run_native_tasks(_NATIVE_FIRST_SLEEP_LEVEL); - bst_post_init(); -} - -NATIVE_SIMULATOR_IF int nsif_cpu0_cleanup(void) -{ - /* - * Note posix_soc_clean_up() may not return, but in that case, - * nsif_cpu0_cleanup() will be called again - */ - posix_soc_clean_up(); - - uint8_t bst_result = bst_delete(); - return bst_result; -} - -NATIVE_SIMULATOR_IF void nsif_cpu0_irq_raised(void) -{ - posix_interrupt_raised(); -} - -NATIVE_SIMULATOR_IF void nsif_cpu0_bst_tick(uint64_t time) -{ - bst_tick(time); -} - -NATIVE_SIMULATOR_IF void nsif_cpu0_irq_raised_from_sw(void) -{ - void posix_irq_handler_im_from_sw(void); - posix_irq_handler_im_from_sw(); -} diff --git a/boards/posix/nrf_bsim/CMakeLists.txt b/boards/posix/nrf_bsim/CMakeLists.txt new file mode 100644 index 00000000000..dfa6248f7dc --- /dev/null +++ b/boards/posix/nrf_bsim/CMakeLists.txt @@ -0,0 +1,76 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# Copyright (c) 2018 Oticon A/S +# SPDX-License-Identifier: Apache-2.0 + +find_package(BabbleSim) + +zephyr_library() + +# Due to the BLE controller assumption about enum size +zephyr_compile_options( + -fshort-enums +) +# Structures layouts needs to match in the interface between the runner and the embedded SW +# The nrfx HAL uses enums in its definitions,so they need to have the same size in both, +# as both the HW models and embedded SW use them. +target_compile_options(native_simulator INTERFACE -fshort-enums) + +zephyr_library_sources( + irq_handler.c + cpu_wait.c + argparse.c + nsi_if.c + soc/nrfx_coredep.c + common/bstests_entry.c + common/cmsis/cmsis.c + common/trace_hook.c +) + +# Include sync_rtc from real SOC code if enabled +zephyr_library_sources_ifdef(CONFIG_NRF53_SYNC_RTC + ${ZEPHYR_BASE}/soc/arm/nordic_nrf/nrf53/sync_rtc.c + ) + +target_sources(native_simulator INTERFACE + common/bsim_args_runner.c + common/bsim_extra_cpu_if_stubs.c + common/phy_sync_ctrl.c + common/runner_hooks.c + common/posix_arch_if.c + common/trace_hook.c +) + +if (CONFIG_IPC_SERVICE AND CONFIG_BOARD_NRF5340BSIM_NRF5340_CPUAPP) + zephyr_library_sources( + ipc_backend.c + ) +endif() + +zephyr_include_directories( + soc + common + common/cmsis + ${NSI_DIR}/common/src/include +) + +zephyr_library_include_directories( + ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ + ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ + ${BSIM_COMPONENTS_PATH}/libRandv2/src/ + ${ZEPHYR_BASE}/kernel/include + ${ZEPHYR_BASE}/arch/posix/include + common/ +) + +set(libpath ${BSIM_OUT_PATH}/lib) +set_property(TARGET native_simulator APPEND PROPERTY RUNNER_LINK_LIBRARIES + ${libpath}/libUtilv1.32.a + ${libpath}/libPhyComv1.32.a + ${libpath}/lib2G4PhyComv1.32.a + ${libpath}/libRandv2.32.a +) + +target_compile_options(native_simulator INTERFACE + "-DNSI_PRIMARY_MCU_N=${CONFIG_NATIVE_SIMULATOR_PRIMARY_MCU_INDEX}") + +include(../common/natsim_config.cmake) diff --git a/boards/posix/nrf_bsim/Kconfig b/boards/posix/nrf_bsim/Kconfig new file mode 100644 index 00000000000..7d67c44d284 --- /dev/null +++ b/boards/posix/nrf_bsim/Kconfig @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_BSIM_NRFXX + +# The following file is normally parsed only for the ARM architecture, which is +# used by Nordic SoCs, so to make the symbols defined in this file available for +# the simulated nrf5x_bsim boards, which use the POSIX architecture, the file +# must be read also from here. +source "soc/arm/nordic_nrf/Kconfig.peripherals" + +endif # SOC_SERIES_BSIM_NRFXX + + +# This would eventually be shared by a possible family of simulated NRF boards +# which use BabbleSim. When that happens, we can move this to a common +# Kconfig file + +config SOC_SERIES_BSIM_NRFXX + bool + depends on SOC_POSIX + help + Any NRF simulated SOC with BabbleSim, based on the POSIX arch + +config SOC_SERIES_BSIM_NRF52X + bool + depends on SOC_SERIES_BSIM_NRFXX + help + Any NRF52 simulated SOC with BabbleSim, based on the POSIX arch + +config SOC_SERIES_BSIM_NRF53X + bool + depends on SOC_SERIES_BSIM_NRFXX + help + Any NRF53 simulated SOC with BabbleSim, based on the POSIX arch + +if BOARD_NRF5340BSIM_NRF5340_CPUAPP + +# Replica of the option provided by the BOARD_NRF5340DK_NRF5340_CPUAPP board so samples can be +# reused as is +config BOARD_ENABLE_CPUNET + bool "NRF53 Network MCU" + +endif # BOARD_NRF5340BSIM_NRF5340_CPUNET + +if SOC_SERIES_BSIM_NRF53X + +# Let's reuse the RTC sync options so applications which use it can be reused as is +source "soc/arm/nordic_nrf/nrf53/Kconfig.sync_rtc" + +endif # SOC_SERIES_BSIM_NRF53X diff --git a/boards/posix/nrf_bsim/Kconfig.board b/boards/posix/nrf_bsim/Kconfig.board new file mode 100644 index 00000000000..4a701c9acdc --- /dev/null +++ b/boards/posix/nrf_bsim/Kconfig.board @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_NRF52_BSIM + bool "NRF52 simulation model" + select SOC_SERIES_BSIM_NRFXX + select SOC_SERIES_BSIM_NRF52X + select SOC_COMPATIBLE_NRF + select SOC_COMPATIBLE_NRF52X + select SOC_COMPATIBLE_NRF52833 + select NRF_RTC_TIMER + select CLOCK_CONTROL + select HAS_NRFX + select HAS_NORDIC_DRIVERS + select NATIVE_LIBRARY + help + Will produce a console Linux process which can be executed natively. + It needs the BabbleSim simulator both in compile time and to execute + +config BOARD_NRF5340BSIM_NRF5340_CPUNET + bool "Simulated NRF53 Network core" + select SOC_SERIES_BSIM_NRFXX + select SOC_SERIES_BSIM_NRF53X + select SOC_COMPATIBLE_NRF + select SOC_COMPATIBLE_NRF53X + select SOC_COMPATIBLE_NRF5340_CPUNET + select NRF_RTC_TIMER + select CLOCK_CONTROL + select HAS_NRFX + select HAS_NORDIC_DRIVERS + select NATIVE_LIBRARY + help + Will produce a console Linux process which can be executed natively. + It needs the BabbleSim simulator both in compile time and to execute + +config BOARD_NRF5340BSIM_NRF5340_CPUAPP + bool "Simulated NRF53 Application core" + select SOC_SERIES_BSIM_NRFXX + select SOC_SERIES_BSIM_NRF53X + select SOC_COMPATIBLE_NRF + select SOC_COMPATIBLE_NRF53X + select SOC_COMPATIBLE_NRF5340_CPUAPP + select NRF_RTC_TIMER + select CLOCK_CONTROL + select HAS_NRFX + select HAS_NORDIC_DRIVERS + select NATIVE_LIBRARY + help + Will produce a console Linux process which can be executed natively. + It needs the BabbleSim simulator both in compile time and to execute diff --git a/boards/posix/nrf_bsim/Kconfig.defconfig b/boards/posix/nrf_bsim/Kconfig.defconfig new file mode 100644 index 00000000000..6993048248c --- /dev/null +++ b/boards/posix/nrf_bsim/Kconfig.defconfig @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_BSIM_NRFXX + +config BUILD_OUTPUT_BIN + default n + +config BUILD_OUTPUT_EXE + # When the IPC service is used, the net core image requires the application core image, as it needs + # access to its IPC buffer. Without it, the executable cannot be built. + default y if !(BOARD_NRF5340BSIM_NRF5340_CPUNET && IPC_SERVICE && (NATIVE_SIMULATOR_EXTRA_IMAGE_PATHS = "")) + +config OUTPUT_PRINT_MEMORY_USAGE + default n + +config BOARD + default "nrf52_bsim" if BOARD_NRF52_BSIM + default "nrf5340bsim_nrf5340_cpunet" if BOARD_NRF5340BSIM_NRF5340_CPUNET + default "nrf5340bsim_nrf5340_cpuapp" if BOARD_NRF5340BSIM_NRF5340_CPUAPP + +config NATIVE_SIMULATOR_NUMBER_MCUS + default 2 if BOARD_NRF5340BSIM_NRF5340_CPUNET || BOARD_NRF5340BSIM_NRF5340_CPUAPP + default 1 + +config NATIVE_SIMULATOR_MCU_N + default 1 if BOARD_NRF5340BSIM_NRF5340_CPUNET + default 0 + +config NATIVE_SIMULATOR_AUTOSTART_MCU + default y if BOARD_NRF5340BSIM_NRF5340_CPUNET + +config NATIVE_SIMULATOR_PRIMARY_MCU_INDEX + default 1 if SOC_SERIES_BSIM_NRF53X + default 0 + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 32768 + +config SYS_CLOCK_TICKS_PER_SEC + default 128 if !TICKLESS_KERNEL + default 32768 + +config BT_CTLR + default y if BOARD_NRF52_BSIM || BOARD_NRF5340BSIM_NRF5340_CPUNET + depends on BT + +config HEAP_MEM_POOL_SIZE + default 4096 if BT_HCI_IPC + default 4096 if NRF_802154_SER_HOST && BOARD_NRF5340BSIM_NRF5340_CPUAPP + default 4096 if NRF_802154_SER_RADIO && BOARD_NRF5340BSIM_NRF5340_CPUNET + +if BOARD_NRF5340BSIM_NRF5340_CPUAPP || BOARD_NRF5340BSIM_NRF5340_CPUNET + +config MBOX_NRFX_IPC + default MBOX + +endif # BOARD_NRF5340BSIM_NRF5340_CPUAPP || BOARD_NRF5340BSIM_NRF5340_CPUNET + +if BOARD_NRF5340BSIM_NRF5340_CPUAPP + +config IPC_SERVICE_BACKEND_RPMSG_SHMEM_RESET + default y if IPC_SERVICE_BACKEND_RPMSG + +choice BT_HCI_BUS_TYPE + default BT_HCI_IPC +endchoice + +endif # BOARD_NRF5340BSIM_NRF5340_CPUAPP + +# The 15.4 driver Tx encryption is currently not functional with this +# simulated board => we disable it by default. With this Openthread will normally +# default to encrypt packets on its own. +config NRF_802154_ENCRYPTION + default n + +if LOG + +# For this board we can log synchronously without any problem +# Doing so will be nicer for debugging +choice LOG_MODE + default LOG_MODE_IMMEDIATE +endchoice + +endif # LOG + +if CONSOLE + +config POSIX_ARCH_CONSOLE + default y if !SERIAL + +config UART_CONSOLE + default y if SERIAL + +endif # CONSOLE + +endif # SOC_SERIES_BSIM_NRFXX diff --git a/boards/posix/nrf_bsim/argparse.c b/boards/posix/nrf_bsim/argparse.c new file mode 100644 index 00000000000..69214ef5d7d --- /dev/null +++ b/boards/posix/nrf_bsim/argparse.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2017 Oticon A/S + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "bs_tracing.h" +#include "bstests.h" +#include "bs_cmd_line.h" +#include "bs_dynargs.h" +#include "posix_native_task.h" +#include "nsi_tracing.h" +#include "nsi_main.h" +#include "nsi_cpu_ctrl.h" + +static const char exe_name[] = "nrf_bsim options:"; + +static char *testid; +static bool cpu_autostart; + +static void cmd_testid_found(char *argv, int offset) +{ + bst_set_testapp_mode(testid); +} + +static void cmd_testlist_found(char *argv, int offset) +{ + bst_print_testslist(); + nsi_exit(0); +} + +static void cmd_autostart_found(char *argv, int offset) +{ + nsi_cpu_set_auto_start(CONFIG_NATIVE_SIMULATOR_MCU_N, cpu_autostart); +} + +static void nrfbsim_register_args(void) +{ + static bs_args_struct_t args_struct_toadd[] = { + { + .option = "cpu" STRINGIFY(CONFIG_NATIVE_SIMULATOR_MCU_N) "_testid", + .name = "testid", + .type = 's', + .dest = (void *)&testid, + .call_when_found = cmd_testid_found, + .descript = "Which of the bs tests shall be run. Run -testslist for more info" + }, + { + .is_switch = true, + .option = "cpu" STRINGIFY(CONFIG_NATIVE_SIMULATOR_MCU_N) "_testslist", + .type = 'b', + .call_when_found = cmd_testlist_found, + .descript = "Print information about the available bs application tests" + }, +#if (CONFIG_NATIVE_SIMULATOR_MCU_N == CONFIG_NATIVE_SIMULATOR_PRIMARY_MCU_INDEX) + { + .option = "testid", + .name = "testid", + .type = 's', + .dest = (void *)&testid, + .call_when_found = cmd_testid_found, + .descript = "Alias of cpu" STRINGIFY(CONFIG_NATIVE_SIMULATOR_MCU_N) "_testid" + }, + { + .is_switch = true, + .option = "testslist", + .type = 'b', + .call_when_found = cmd_testlist_found, + .descript = "Alias of cpu" STRINGIFY(CONFIG_NATIVE_SIMULATOR_MCU_N) "_testslist" + }, +#endif + { + .option = "cpu" STRINGIFY(CONFIG_NATIVE_SIMULATOR_MCU_N) "_autostart", + .name = "autostart", + .type = 'b', + .dest = (void *)&cpu_autostart, + .call_when_found = cmd_autostart_found, + .descript = "Automatically start CPU" STRINGIFY(CONFIG_NATIVE_SIMULATOR_MCU_N) + }, + ARG_TABLE_ENDMARKER + }; + + bs_add_extra_dynargs(args_struct_toadd); + bs_args_override_exe_name((char *)exe_name); +} + +NATIVE_TASK(nrfbsim_register_args, PRE_BOOT_1, 100); diff --git a/boards/posix/nrf52_bsim/argparse.h b/boards/posix/nrf_bsim/argparse.h similarity index 100% rename from boards/posix/nrf52_bsim/argparse.h rename to boards/posix/nrf_bsim/argparse.h diff --git a/boards/posix/nrf_bsim/board.cmake b/boards/posix/nrf_bsim/board.cmake new file mode 100644 index 00000000000..d9d444c1be9 --- /dev/null +++ b/boards/posix/nrf_bsim/board.cmake @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 + +set(SUPPORTED_EMU_PLATFORMS native) + +board_set_debugger_ifnset(native_gdb) +board_finalize_runner_args(native_gdb) diff --git a/boards/posix/nrf52_bsim/board_irq.h b/boards/posix/nrf_bsim/board_irq.h similarity index 94% rename from boards/posix/nrf52_bsim/board_irq.h rename to boards/posix/nrf_bsim/board_irq.h index bc41162c223..e1a385194fb 100644 --- a/boards/posix/nrf52_bsim/board_irq.h +++ b/boards/posix/nrf_bsim/board_irq.h @@ -7,7 +7,7 @@ #ifndef BOARDS_POSIX_NRF52_BSIM_BOARD_IRQ_H #define BOARDS_POSIX_NRF52_BSIM_BOARD_IRQ_H -#include "zephyr/types.h" +#include #include "../common/irq/board_irq.h" #ifdef __cplusplus diff --git a/boards/posix/nrf_bsim/board_soc.h b/boards/posix/nrf_bsim/board_soc.h new file mode 100644 index 00000000000..1b7e7a85c0c --- /dev/null +++ b/boards/posix/nrf_bsim/board_soc.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017 Oticon A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @file Extra definitions provided by the board to soc.h + * + * Background: + * The POSIX ARCH/SOC/board layering is different than in normal archs + * The "SOC" does not provide almost any of the typical SOC functionality + * but that is left for the "board" to define it + * Device code may rely on the soc.h defining some things (like the interrupts + * numbers) + * Therefore this file is included from the inf_clock soc.h to allow a board + * to define that kind of SOC related snippets + */ + +#ifndef BOARDS_POSIX_NRF_BSIM_BOARD_SOC_H +#define BOARDS_POSIX_NRF_BSIM_BOARD_SOC_H + +#include +#include + +#include +#include +#include +#include +#include +#include +#include "cmsis.h" + +#if defined(CONFIG_BOARD_NRF52_BSIM) +#define OFFLOAD_SW_IRQ SWI0_EGU0_IRQn +#elif defined(CONFIG_BOARD_NRF5340BSIM_NRF5340_CPUAPP) +#define OFFLOAD_SW_IRQ EGU0_IRQn +#elif defined(CONFIG_BOARD_NRF5340BSIM_NRF5340_CPUNET) +#define OFFLOAD_SW_IRQ SWI0_IRQn +#endif + +#define FLASH_PAGE_ERASE_MAX_TIME_US 89700UL +#define FLASH_PAGE_MAX_CNT 256UL + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* BOARDS_POSIX_NRF_BSIM_BOARD_SOC_H */ diff --git a/boards/posix/nrf52_bsim/common/README.txt b/boards/posix/nrf_bsim/common/README.txt similarity index 100% rename from boards/posix/nrf52_bsim/common/README.txt rename to boards/posix/nrf_bsim/common/README.txt diff --git a/boards/posix/nrf52_bsim/common/bsim_args_runner.c b/boards/posix/nrf_bsim/common/bsim_args_runner.c similarity index 80% rename from boards/posix/nrf52_bsim/common/bsim_args_runner.c rename to boards/posix/nrf_bsim/common/bsim_args_runner.c index 6aed191793c..29e0d15dd2e 100644 --- a/boards/posix/nrf52_bsim/common/bsim_args_runner.c +++ b/boards/posix/nrf_bsim/common/bsim_args_runner.c @@ -21,9 +21,12 @@ #include "bs_tracing.h" #include "bs_dump_files.h" #include "bs_rand_main.h" +#include "nsi_cpu_if.h" #include "nsi_tasks.h" #include "nsi_main.h" +#include "nsi_cpu_ctrl.h" #include "NRF_HWLowL.h" +#include "NHW_misc.h" static bs_args_struct_t *args_struct; /* Direct use of this global is deprecated, use bsim_args_get_global_device_nbr() instead */ @@ -58,6 +61,18 @@ static void print_no_sim_warning(void) "and nosim\n"); } +static void print_mcus_info(char *argv, int offset) +{ + (void) argv; + (void) offset; + bs_trace_raw(0, "CPU #, Name , Autostart\n"); + bs_trace_raw(0, "-------------------------------\n"); + for (int i = 0; i < NSI_N_CPUS; i++) { + bs_trace_raw(0, "CPU %2i, %12s, %i\n", + i, nhw_get_core_name(i), nsi_cpu_get_auto_start(i)); + } +} + static void bsim_register_basic_args(void) { #define args (&global_args) @@ -86,8 +101,17 @@ static void bsim_register_basic_args(void) .name = "arg", .type = 'l', .descript = "The arguments that follow will be passed straight to the testcase " - "init function. (Note: If more than 1 MCU is present, argtest corresponds " - "to argtestmcu0)" + "init function (Note: If more than 1 MCU is present, argtest corresponds " + "to argstests" NSI_STRINGIFY(NSI_PRIMARY_MCU_N) " )" + }, + { + .manual = true, + .option = "argstest", + .name = "arg", + .type = 'l', + .descript = "The arguments that follow will be passed straight to cpu's " + "testcase init function), where 0 <= n < " NSI_STRINGIFY(NSI_N_CPUS) + " is the cpu number" }, { .manual = true, @@ -96,6 +120,13 @@ static void bsim_register_basic_args(void) .type = 'l', .descript = "The arguments that follow will be passed to main (default)" }, + { + .is_switch = true, + .option = "cpu_print_info", + .call_when_found = print_mcus_info, + .type = 'b', + .descript = "Print information about each MCUs", + }, ARG_TABLE_ENDMARKER }; #undef args @@ -117,6 +148,17 @@ void bs_add_extra_dynargs(bs_args_struct_t *args_struct_toadd) bs_add_dynargs(&args_struct, args_struct_toadd); } +static void nsif_cpun_save_test_arg(int n, char *c) +{ + F_TRAMP_LIST(NATIVE_SIMULATOR_IF void nsif_cpu, _save_test_arg(char *argv)) + + void(*fptrs[])(char *) = { + F_TRAMP_TABLE(nsif_cpu, _save_test_arg) + }; + + fptrs[n](c); +} + /** * Check the arguments provided in the command line: set args based on it or * defaults, and check they are correct @@ -132,9 +174,14 @@ void nsi_handle_cmd_line(int argc, char *argv[]) static const char default_phy[] = "2G4"; enum {Main = 0, Test = 1} parsing = Main; + uint test_cpu_n; for (int i = 1; i < argc; i++) { if (bs_is_option(argv[i], "argstest", 0)) { + parsing = Test; + test_cpu_n = NSI_PRIMARY_MCU_N; + continue; + } else if (bs_is_multi_opt(argv[i], "argstest", &test_cpu_n, 0)) { parsing = Test; continue; } else if (bs_is_option(argv[i], "argsmain", 0)) { @@ -149,8 +196,7 @@ void nsi_handle_cmd_line(int argc, char *argv[]) argv[i]); } } else if (parsing == Test) { - void nsif_cpu0_save_test_arg(char *argv); - nsif_cpu0_save_test_arg(argv[i]); + nsif_cpun_save_test_arg(test_cpu_n, argv[i]); } else { bs_trace_error_line("Bad error\n"); } diff --git a/boards/posix/nrf52_bsim/common/bsim_args_runner.h b/boards/posix/nrf_bsim/common/bsim_args_runner.h similarity index 100% rename from boards/posix/nrf52_bsim/common/bsim_args_runner.h rename to boards/posix/nrf_bsim/common/bsim_args_runner.h diff --git a/boards/posix/nrf_bsim/common/bsim_extra_cpu_if_stubs.c b/boards/posix/nrf_bsim/common/bsim_extra_cpu_if_stubs.c new file mode 100644 index 00000000000..bec831e3943 --- /dev/null +++ b/boards/posix/nrf_bsim/common/bsim_extra_cpu_if_stubs.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_tracing.h" +#include "nsi_cpu_if.h" + +/* + * Default (weak) implementation for nsif_cpu_save_test_arg() expected by the argument + * parsing defined in bsim_args_runner. + * Note that the real implementation is provided by the board code. + * This exists in case the total device image is assembled lacking some of the embedded MCU images + * or the user tries to target a non-existent MCU + */ + +static void save_test_arg_warn(const char *func, char *argv) +{ + bs_trace_warning("%s not defined. You may be passing a test argument to a CPU without" + " image or a non-existent CPU. Argument \"%s\" will be ignored\n", + func, argv); +} + +/* Define N instances of void nsif_cpu_save_test_arg */ +F_TRAMP_BODY_LIST(NATIVE_SIMULATOR_IF __attribute__((weak)) void nsif_cpu, + _save_test_arg(char *argv) { save_test_arg_warn(__func__, argv); }) diff --git a/boards/posix/nrf52_bsim/common/bstests.h b/boards/posix/nrf_bsim/common/bstests.h similarity index 100% rename from boards/posix/nrf52_bsim/common/bstests.h rename to boards/posix/nrf_bsim/common/bstests.h diff --git a/boards/posix/nrf52_bsim/common/bstests_entry.c b/boards/posix/nrf_bsim/common/bstests_entry.c similarity index 86% rename from boards/posix/nrf52_bsim/common/bstests_entry.c rename to boards/posix/nrf_bsim/common/bstests_entry.c index ee61811ee3d..c1f08deb9cd 100644 --- a/boards/posix/nrf52_bsim/common/bstests_entry.c +++ b/boards/posix/nrf_bsim/common/bstests_entry.c @@ -9,6 +9,8 @@ #include "bs_types.h" #include "bs_tracing.h" #include "bstests.h" +#include "bs_oswrap.h" +#include "nsi_host_trampolines.h" /* * Result of the testcase execution. @@ -38,7 +40,7 @@ struct bst_test_list *bst_add_tests(struct bst_test_list *tests, } } else { if (test_def[idx].test_id != NULL) { - head = malloc(sizeof(struct bst_test_list)); + head = bs_malloc(sizeof(struct bst_test_list)); head->next = NULL; head->test_instance = (struct bst_test_instance *) &test_def[idx++]; @@ -47,7 +49,7 @@ struct bst_test_list *bst_add_tests(struct bst_test_list *tests, } while (test_def[idx].test_id != NULL) { - tail->next = malloc(sizeof(struct bst_test_list)); + tail->next = bs_malloc(sizeof(struct bst_test_list)); tail = tail->next; tail->test_instance = (struct bst_test_instance *) &test_def[idx++]; @@ -229,7 +231,7 @@ uint8_t bst_delete(void) while (test_list_top) { struct bst_test_list *tmp = test_list_top->next; - free(test_list_top); + nsi_host_free(test_list_top); test_list_top = tmp; } @@ -243,3 +245,28 @@ uint8_t bst_delete(void) return bst_result; } + +#if defined(CONFIG_NATIVE_SIMULATOR_MCU_N) +#include "bstest_ticker.h" + +void bst_ticker_set_period(bs_time_t tick_period) +{ + bst_ticker_amp_set_period(CONFIG_NATIVE_SIMULATOR_MCU_N, tick_period); +} + +void bst_ticker_set_next_tick_absolute(bs_time_t time) +{ + bst_ticker_amp_set_next_tick_absolutelute(CONFIG_NATIVE_SIMULATOR_MCU_N, time); +} + +void bst_ticker_set_next_tick_delta(bs_time_t time) +{ + bst_ticker_amp_set_next_tick_delta(CONFIG_NATIVE_SIMULATOR_MCU_N, time); +} + +void bst_awake_cpu_asap(void) +{ + bst_ticker_amp_awake_cpu_asap(CONFIG_NATIVE_SIMULATOR_MCU_N); +} + +#endif /* defined(CONFIG_NATIVE_SIMULATOR_MCU_N) */ diff --git a/boards/posix/nrf52_bsim/common/cmdline.h b/boards/posix/nrf_bsim/common/cmdline.h similarity index 100% rename from boards/posix/nrf52_bsim/common/cmdline.h rename to boards/posix/nrf_bsim/common/cmdline.h diff --git a/boards/posix/nrf_bsim/common/cmsis/cmsis.c b/boards/posix/nrf_bsim/common/cmsis/cmsis.c new file mode 100644 index 00000000000..1694bc1da34 --- /dev/null +++ b/boards/posix/nrf_bsim/common/cmsis/cmsis.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * Copyright (c) 2020 Oticon A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "irq_ctrl.h" +#include "posix_core.h" +#include "posix_board_if.h" +#include "board_soc.h" +#include "bs_tracing.h" + +/* + * Replacement for ARMs NVIC functions() + */ +void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + hw_irq_ctrl_raise_im_from_sw(CONFIG_NATIVE_SIMULATOR_MCU_N, IRQn); +} + +void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + hw_irq_ctrl_clear_irq(CONFIG_NATIVE_SIMULATOR_MCU_N, IRQn); +} + +void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + hw_irq_ctrl_disable_irq(CONFIG_NATIVE_SIMULATOR_MCU_N, IRQn); +} + +void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + hw_irq_ctrl_enable_irq(CONFIG_NATIVE_SIMULATOR_MCU_N, IRQn); +} + +void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + hw_irq_ctrl_prio_set(CONFIG_NATIVE_SIMULATOR_MCU_N, IRQn, priority); +} + +uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + return hw_irq_ctrl_get_prio(CONFIG_NATIVE_SIMULATOR_MCU_N, IRQn); +} + +void NVIC_SystemReset(void) +{ + bs_trace_error_time_line("%s called. Exiting\n", __func__); +} + +/* + * Replacements for some other CMSIS functions + */ +void __enable_irq(void) +{ + hw_irq_ctrl_change_lock(CONFIG_NATIVE_SIMULATOR_MCU_N, false); +} + +void __disable_irq(void) +{ + hw_irq_ctrl_change_lock(CONFIG_NATIVE_SIMULATOR_MCU_N, true); +} + +uint32_t __get_PRIMASK(void) +{ + return hw_irq_ctrl_get_current_lock(CONFIG_NATIVE_SIMULATOR_MCU_N); +} + +void __set_PRIMASK(uint32_t primask) +{ + hw_irq_ctrl_change_lock(CONFIG_NATIVE_SIMULATOR_MCU_N, primask != 0); +} + +void __WFE(void) +{ + nrfbsim_WFE_model(); +} + +void __WFI(void) +{ + __WFE(); +} + +void __SEV(void) +{ + nrfbsim_SEV_model(); +} diff --git a/boards/posix/nrf52_bsim/common/cmsis/cmsis.h b/boards/posix/nrf_bsim/common/cmsis/cmsis.h similarity index 94% rename from boards/posix/nrf52_bsim/common/cmsis/cmsis.h rename to boards/posix/nrf_bsim/common/cmsis/cmsis.h index f40ae49a9b7..ff9030ca547 100644 --- a/boards/posix/nrf52_bsim/common/cmsis/cmsis.h +++ b/boards/posix/nrf_bsim/common/cmsis/cmsis.h @@ -14,7 +14,9 @@ #include #include "cmsis_instr.h" +#if defined(CONFIG_SOC_COMPATIBLE_NRF52833) #include "nrf52833.h" +#endif #ifdef __cplusplus extern "C" { diff --git a/boards/posix/nrf52_bsim/common/cmsis/cmsis_compiler.h b/boards/posix/nrf_bsim/common/cmsis/cmsis_compiler.h similarity index 100% rename from boards/posix/nrf52_bsim/common/cmsis/cmsis_compiler.h rename to boards/posix/nrf_bsim/common/cmsis/cmsis_compiler.h diff --git a/boards/posix/nrf52_bsim/common/cmsis/cmsis_instr.h b/boards/posix/nrf_bsim/common/cmsis/cmsis_instr.h similarity index 100% rename from boards/posix/nrf52_bsim/common/cmsis/cmsis_instr.h rename to boards/posix/nrf_bsim/common/cmsis/cmsis_instr.h diff --git a/boards/posix/nrf52_bsim/common/phy_sync_ctrl.c b/boards/posix/nrf_bsim/common/phy_sync_ctrl.c similarity index 96% rename from boards/posix/nrf52_bsim/common/phy_sync_ctrl.c rename to boards/posix/nrf_bsim/common/phy_sync_ctrl.c index 8a03fd797ae..b7b6c507d4f 100644 --- a/boards/posix/nrf52_bsim/common/phy_sync_ctrl.c +++ b/boards/posix/nrf_bsim/common/phy_sync_ctrl.c @@ -23,7 +23,7 @@ static struct { double start_offset; - double max_resync_offset; + bs_time_t max_resync_offset; bool delay_init; bool sync_preinit; bool sync_preboot; @@ -214,6 +214,13 @@ NSI_TASK(phy_sync_ctrl_register_args, PRE_BOOT_1, 10); void phy_sync_ctrl_connect_to_2G4_phy(void) { + static bool ever_run; + + if (ever_run) { + return; + } + ever_run = true; + bs_trace_raw(9, "%s: Connecting to phy...\n", __func__); hwll_connect_to_phy(bsim_args_get_2G4_device_nbr(), bsim_args_get_simid(), @@ -223,6 +230,13 @@ void phy_sync_ctrl_connect_to_2G4_phy(void) void phy_sync_ctrl_pre_boot2(void) { + static bool ever_run; + + if (ever_run) { + return; + } + ever_run = true; + if (((sync_args.start_offset > 0) && (sync_args.delay_init)) || sync_args.sync_preinit) { /* Delay the next steps until the simulation time has @@ -235,6 +249,13 @@ void phy_sync_ctrl_pre_boot2(void) void phy_sync_ctrl_pre_boot3(void) { + static bool ever_run; + + if (ever_run) { + return; + } + ever_run = true; + /* * If sync_preboot was set, we sync with the phy * right before booting the CPU diff --git a/boards/posix/nrf52_bsim/common/phy_sync_ctrl.h b/boards/posix/nrf_bsim/common/phy_sync_ctrl.h similarity index 100% rename from boards/posix/nrf52_bsim/common/phy_sync_ctrl.h rename to boards/posix/nrf_bsim/common/phy_sync_ctrl.h diff --git a/boards/posix/nrf52_bsim/common/posix_arch_if.c b/boards/posix/nrf_bsim/common/posix_arch_if.c similarity index 100% rename from boards/posix/nrf52_bsim/common/posix_arch_if.c rename to boards/posix/nrf_bsim/common/posix_arch_if.c diff --git a/boards/posix/nrf52_bsim/common/runner_hooks.c b/boards/posix/nrf_bsim/common/runner_hooks.c similarity index 100% rename from boards/posix/nrf52_bsim/common/runner_hooks.c rename to boards/posix/nrf_bsim/common/runner_hooks.c diff --git a/boards/posix/nrf_bsim/common/trace_hook.c b/boards/posix/nrf_bsim/common/trace_hook.c new file mode 100644 index 00000000000..55f491a2094 --- /dev/null +++ b/boards/posix/nrf_bsim/common/trace_hook.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2017 Oticon A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "bs_tracing.h" + +/* + * Provide the posix_print_* functions required from all POSIX arch boards + * (This functions provide a lower level, more direct, print mechanism than + * Zephyr's printk or logger and therefore can be relied on even if the kernel + * is down. + */ + +#if (CONFIG_NATIVE_SIMULATOR_NUMBER_MCUS > 1) +static const char *cpu_prefix = "CPU"; +static const unsigned int cpu_number = CONFIG_NATIVE_SIMULATOR_MCU_N; +#else +static const char *cpu_prefix; +static const unsigned int cpu_number; +#endif /* (CONFIG_NATIVE_SIMULATOR_NUMBER_MCUS > 1) */ + +void posix_vprint_error_and_exit(const char *format, va_list vargs) +{ + bs_trace_vprint(BS_TRACE_ERROR, cpu_prefix, cpu_number, 0, BS_TRACE_AUTOTIME, 0, + format, vargs); +} + +void posix_vprint_warning(const char *format, va_list vargs) +{ + bs_trace_vprint(BS_TRACE_WARNING, cpu_prefix, cpu_number, 0, BS_TRACE_AUTOTIME, 0, + format, vargs); +} + +void posix_vprint_trace(const char *format, va_list vargs) +{ + bs_trace_vprint(BS_TRACE_RAW, cpu_prefix, cpu_number, 2, BS_TRACE_AUTOTIME, 0, + format, vargs); +} + +void posix_print_error_and_exit(const char *format, ...) +{ + va_list variable_argsp; + + va_start(variable_argsp, format); + posix_vprint_error_and_exit(format, variable_argsp); + va_end(variable_argsp); +} + +void posix_print_warning(const char *format, ...) +{ + va_list variable_argsp; + + va_start(variable_argsp, format); + bs_trace_vprint(BS_TRACE_WARNING, cpu_prefix, cpu_number, 0, BS_TRACE_AUTOTIME, 0, + format, variable_argsp); + va_end(variable_argsp); +} + +void posix_print_trace(const char *format, ...) +{ + va_list variable_argsp; + + va_start(variable_argsp, format); + bs_trace_vprint(BS_TRACE_RAW, cpu_prefix, cpu_number, 2, BS_TRACE_AUTOTIME, 0, + format, variable_argsp); + va_end(variable_argsp); +} + +int posix_trace_over_tty(int file_number) +{ + return bs_trace_is_tty(file_number); +} + +void nsi_vprint_error_and_exit(const char *format, va_list vargs) +{ + bs_trace_vprint(BS_TRACE_ERROR, cpu_prefix, cpu_number, 0, BS_TRACE_AUTOTIME, 0, + format, vargs); +} + +void nsi_vprint_warning(const char *format, va_list vargs) +{ + bs_trace_vprint(BS_TRACE_WARNING, cpu_prefix, cpu_number, 0, BS_TRACE_AUTOTIME, 0, + format, vargs); +} + +void nsi_vprint_trace(const char *format, va_list vargs) +{ + bs_trace_vprint(BS_TRACE_RAW, cpu_prefix, cpu_number, 2, BS_TRACE_AUTOTIME, 0, + format, vargs); +} diff --git a/boards/posix/nrf52_bsim/cpu_wait.c b/boards/posix/nrf_bsim/cpu_wait.c similarity index 92% rename from boards/posix/nrf52_bsim/cpu_wait.c rename to boards/posix/nrf_bsim/cpu_wait.c index dd443cfb362..cedc71228a8 100644 --- a/boards/posix/nrf52_bsim/cpu_wait.c +++ b/boards/posix/nrf_bsim/cpu_wait.c @@ -32,7 +32,7 @@ void arch_busy_wait(uint32_t usec_to_wait) * There may be wakes due to other interrupts or nested calls to * k_busy_wait in interrupt handlers */ - fake_timer_wake_in_time(time_end); + nhw_fake_timer_wake_in_time(CONFIG_NATIVE_SIMULATOR_MCU_N, time_end); posix_halt_cpu(); } } @@ -58,7 +58,7 @@ void posix_cpu_hold(uint32_t usec_to_waste) * cpu_hold in interrupt handlers */ time_start = nsi_hws_get_time(); - fake_timer_wake_in_time(time_start + to_wait); + nhw_fake_timer_wake_in_time(CONFIG_NATIVE_SIMULATOR_MCU_N, time_start + to_wait); posix_change_cpu_state_and_wait(true); to_wait -= nsi_hws_get_time() - time_start; diff --git a/boards/posix/nrf_bsim/doc/nrf52_bsim.rst b/boards/posix/nrf_bsim/doc/nrf52_bsim.rst new file mode 100644 index 00000000000..da1212e3367 --- /dev/null +++ b/boards/posix/nrf_bsim/doc/nrf52_bsim.rst @@ -0,0 +1,217 @@ +.. _nrf52_bsim: + +NRF52 simulated board (BabbleSim) +################################# + +.. contents:: + :depth: 1 + :backlinks: entry + :local: + + +Overview +******** + +To allow simulating a nRF52833 SOC a Zephyr target boards is provided: the +nrf52_bsim. + +This uses `BabbleSim`_ to simulate the radio activity, and the +:ref:`POSIX architecture` and the `native simulator`_ to +run applications natively on the development system. This has the benefit of +providing native code execution performance and easy debugging using +native tools, but inherits :ref:`its limitations `. + +This board includes models of some of the nRF52 SOC peripherals: + +* Radio +* Timers +* AAR (Accelerated Address Resolver) +* AES CCM & AES ECB encryption HW +* CLOCK (Clock control) +* EGU (Event Generator Unit) +* FICR (Factory Information Configuration Registers) +* GPIO & GPIOTE +* NVMC (Non-Volatile Memory Controller / Flash) +* PPI (Programmable Peripheral Interconnect) +* RNG (Random Number Generator) +* RTC (Real Time Counter) +* TEMP (Temperature sensor) +* UICR (User Information Configuration Registers) + +and will use the same drivers as the nrf52 dk targets for these. +For more information on what is modelled to which level of detail, +check the `HW models implementation status`_. + +Note that unlike a real nrf52 device, the nrf52_bsim has unlimited RAM and flash for code. + +.. _BabbleSim: + https://BabbleSim.github.io + +.. _native simulator: + https://github.com/BabbleSim/native_simulator/blob/main/docs/README.md + +.. _HW models implementation status: + https://github.com/BabbleSim/ext_nRF_hw_models/blob/main/docs/README_impl_status.md + +.. _nrf52bsim_build_and_run: + +Building and running +******************** + +This board requires the host 32 bit C library. See +:ref:`POSIX Arch dependencies`. + +To target this board you also need to have `BabbleSim`_ compiled in your system. +If you do not have it yet, the easiest way to get it, is to enable the babblesim group +in your local west configuration, running west update, and building the simulator: + +.. code-block:: console + + west config manifest.group-filter -- +babblesim + west update + cd ${ZEPHYR_BASE}/../tools/bsim + make everything -j 8 + +.. note:: + + If you need more BabbleSim components, or more up to date versions, + you can check the `BabbleSim web page `_ + for instructions on how to + `fetch `_ and + `build `_ it. + +You will now need to define two environment variables to point to your BabbleSim +installation, ``BSIM_OUT_PATH`` and ``BSIM_COMPONENTS_PATH``. +If you followed the previous steps, you can just do: + +.. code-block:: console + + export BSIM_OUT_PATH=${ZEPHYR_BASE}/../tools/bsim + export BSIM_COMPONENTS_PATH=${BSIM_OUT_PATH}/components/ + +.. note:: + + You can add these two lines to your ``~/.zephyrrc`` file, or to your shell + initialization script (``~/.bashrc``), so you won't need to rerun them + manually for each new shell. + +You're now ready to build applications targeting this board, for example: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :host-os: unix + :board: nrf52_bsim + :goals: build + :compact: + +Then you can execute your application using: + +.. code-block:: console + + $ ./build/zephyr/zephyr.exe -nosim + # Press Ctrl+C to exit + +Note that the executable is a BabbleSim executable. The ``-nosim`` command line +option indicates you want to run it detached from a BabbleSim simulation. This +is possible only while there is no radio activity. But is perfectly fine for +most Zephyr samples and tests. + +When you want to run a simulation with radio activity you need to run also the +BableSim 2G4 (2.4GHz) physical layer simulation (phy). + +For example, if you would like to run a simple case with 1 BLE ``central_hr`` +sample application connecting to a BLE ``peripheral`` sample application: +Build the ``central_hr`` application targeting this board and copy the resulting +executable to the simulator bin folder with a sensible name: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/central_hr + :host-os: unix + :board: nrf52_bsim + :goals: build + :compact: + +.. code-block:: console + + $ cp build/zephyr/zephyr.exe \ + ${BSIM_OUT_PATH}/bin/bs_nrf52_bsim_samples_bluetooth_central_hr + +Do the same for the ``peripheral`` sample app: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/peripheral + :host-os: unix + :board: nrf52_bsim + :goals: build + :compact: + +.. code-block:: console + + $ cp build/zephyr/zephyr.exe \ + ${BSIM_OUT_PATH}/bin/bs_nrf52_bsim_samples_bluetooth_peripheral + +And then run them together with BabbleSim's 2G4 physical layer simulation: + +.. code-block:: console + + cd ${BSIM_OUT_PATH}/bin/ + ./bs_nrf52_bsim_samples_bluetooth_peripheral -s=trial_sim -d=0 & + ./bs_nrf52_bsim_samples_bluetooth_central_hr -s=trial_sim -d=1 & + ./bs_2G4_phy_v1 -s=trial_sim -D=2 -sim_length=10e6 & + +Where the ``-s`` command line option provides a string which uniquely identifies +this simulation; the ``-D`` option tells the Phy how many devices will be run +in this simulation; the ``-d`` option tells each device which is its device +number in the simulation; and the ``-sim_length`` option specifies the length +of the simulation in microseconds. +BabbleSim devices and Phy support many command line switches. +Run them with ``-help`` for more information. + +You can find more information about how to run BabbleSim simulations in +`this BabbleSim example `_. + + +C library choice +**************** + +These nRF bsim boards use the `native simulator`_ at their core, so you can chose with which +C library you want to build your embedded code. +Check the :ref:`native simulator C library choice section` for more info. + + +Debugging, coverage and address sanitizer +***************************************** + +Just like with :ref:`native_sim`, the resulting +executables are Linux native applications. +Therefore they can be debugged or instrumented with the same tools as any other +native application, like for example ``gdb`` or ``valgrind``. + +The same +:ref:`code coverage analysis means from the POSIX arch` +are inherited in this board. +Similarly, the +:ref:`address and undefined behavior sanitizers can be used as in native_sim`. + + +Note that BabbleSim will run fine if one or several of its components are +being run in a debugger or instrumented. For example, pausing a device in a +breakpoint will pause the whole simulation. + +BabbleSim is fully deterministic by design and the results are not affected by +the host computing speed. All randomness is controlled by random seeds which can +be provided as command line options. + + +About time in BabbleSim +************************ + +Note that time in BabbleSim is simulated and decoupled from real time. Normally +simulated time will pass several orders of magnitude faster than real time, +only limited by your workstation compute power. +If for some reason you want to limit the speed of the simulation to real +time or a ratio of it, you can do so by connecting the `handbrake device`_ +to the BabbleSim Phy. + +.. _handbrake device: + https://github.com/BabbleSim/base/tree/master/device_handbrake diff --git a/boards/posix/nrf_bsim/doc/nrf5340bsim.rst b/boards/posix/nrf_bsim/doc/nrf5340bsim.rst new file mode 100644 index 00000000000..f2ece408e08 --- /dev/null +++ b/boards/posix/nrf_bsim/doc/nrf5340bsim.rst @@ -0,0 +1,122 @@ +.. _nrf5340bsim: + +NRF5340 simulated boards (BabbleSim) +#################################### + +.. contents:: + :depth: 1 + :backlinks: entry + :local: + + +Overview +******** + +To allow simulating nrf5340 SOCs two Zephyr target boards are provided: the +``nrf5340bsim_nrf5340_cpuapp`` and ``nrf5340bsim_nrf5340_cpunet``. + +These use `BabbleSim`_ to simulate the radio activity, and the +:ref:`POSIX architecture` and the `native simulator`_ to +run applications natively on the development system. This has the benefit of +providing native code execution performance and easy debugging using +native tools, but inherits :ref:`its limitations `. + +Just like for the nrf5340dk targets, +the nrf5340bsim_nrf5340_cpuapp build target provides support for the application core, +and the nrf5340bsim_nrf5340_cpunet build target provides support for the network +core on the simulated nRF5340 SOC. + +These boards include models of some of the nRF5340 SOC peripherals: + +* AAR (Accelerated Address Resolver) +* AES CCM & AES ECB encryption HW +* CLOCK (Clock control) +* DPPI (Distributed Programmable Peripheral Interconnect) +* EGU (Event Generator Unit) +* FICR (Factory Information Configuration Registers) +* IPC (Interprocessor communication) +* MUTEX (Mutual exclusive peripheral) +* NVMC (Non-Volatile Memory Controller / Flash) +* RADIO +* RNG (Random Number Generator) +* RTC (Real Time Counter) +* TEMP (Temperature sensor) +* TIMER +* UICR (User Information Configuration Registers) + +and will use the same drivers as the nrf5340dk targets for these. +For more information on what is modelled to which level of detail, +check the `HW models implementation status`_. + +Note that unlike a real nrf5340 device, the nrf5340bsim boards have unlimited RAM and flash for +code. + +.. _BabbleSim: + https://BabbleSim.github.io + +.. _native simulator: + https://github.com/BabbleSim/native_simulator/blob/main/docs/README.md + +.. _HW models implementation status: + https://github.com/BabbleSim/ext_nRF_hw_models/blob/main/docs/README_impl_status.md + + +Building for, and using these boards +************************************ + +If you are interested in developing on only one of the MCUs in this SOC, you +can use the corresponding simulated target, nrf5340bsim_nrf5340_cpuapp or nrf5340bsim_nrf5340_cpunet +following the instructions from the :ref:`nrf52_bsim board `. +Simply change the board/target appropriately when building. + + +.. note:: + + Unlike in real HW, the net core MCU is set-up to automatically boot at start, to facilitate + developing without an image in the application core. You can control + this with either :kconfig:option:`CONFIG_NATIVE_SIMULATOR_AUTOSTART_MCU`, or the command line + option ``--cpu1_autostart``. + + If an MCU is booted without any image, it will automatically set itself to sleep. + + +Assembling both MCUs images into a single executable +**************************************************** + +By default, when you build targeting either nrf5340bsim_nrf5340_cpuapp or +nrf5340bsim_nrf5340_cpunet you will end up with a library (``zephyr/zephyr.elf``) that corresponds +to that MCU code image, and an executable (``zephyr/zephyr.exe``) that includes the native simulator +runner, SOC HW models, that image, and an empty image for the other MCU. + +If you want to assemble an executable including a previously built image for the other MCU, +built with either Zephyr's build system or another native simulator compatible build system, +you can provide that image to the Zephyr build of the second image using +:kconfig:option:`CONFIG_NATIVE_SIMULATOR_EXTRA_IMAGE_PATHS`. + +You can also use :ref:`System build (sysbuild) ` to build your dual MCU executable. +The best way to understand how, may be to look into how this is done in one of the examples +in the tree. For example, for :ref:`the nrf53_sync_rtc sample `, +:zephyr_file:`samples/boards/nrf/nrf53_sync_rtc/sysbuild.cmake`. + + +.. note:: + + These libraries/images are **not** embedded images. You cannot use them for embedded devices, + and cannot use an embedded image to assemble a native executable. + +TrustZone, TF-M and other security considerations +************************************************* + +ARM's TrustZone is not modelled in these boards. This means that: + +* There is no differentiation between secure and non secure execution states or bus accesses. +* All RAM, flash and peripherals are in principle accessible from all SW. Peripherals with their + own interconnect master ports can, in principle, access any other peripheral or RAM area. +* There is no nrf5340bsim_nrf5340_cpuapp_ns board/build target, or posibility of mixing secure + and non-secure images. +* Currently there is no model of the SPU, and therefore neither flash, RAM areas or peripherals + can be labelled as restricted for secure or non secure access. +* TF-M cannot be used. + +Note that the ARM cryptocell-312 peripheral is not modelled. The mbedTLS library can still be used +but with a SW crypto backend instead of the cryptocell HW acceleration. diff --git a/boards/posix/nrf_bsim/ipc_backend.c b/boards/posix/nrf_bsim/ipc_backend.c new file mode 100644 index 00000000000..4f14924a44a --- /dev/null +++ b/boards/posix/nrf_bsim/ipc_backend.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Here we define the shared memory buffers for the RPMSG IPC back-end in simulation. + * In real HW, these are booked in RAM thru device tree configuration. + * In this simulated target, we just define them at build time to have the size defined + * in device tree. + * + * Note that this file is only compiled as part of the application core image, and therefore + * when the network core is built with the IPC service, we cannot produce an executable + * with the network core image alone, as we would lack this buffer during linking. + */ + +#include "nsi_cpu_if.h" +#include + +#define DT_DRV_COMPAT zephyr_ipc_openamp_static_vrings + +#define DEFINE_BACKEND_BUFFER(i) \ + NATIVE_SIMULATOR_IF \ + char IPC##i##_shm_buffer[DT_REG_SIZE(DT_INST_PHANDLE(i, memory_region))]; + +DT_INST_FOREACH_STATUS_OKAY(DEFINE_BACKEND_BUFFER) diff --git a/boards/posix/nrf52_bsim/irq_handler.c b/boards/posix/nrf_bsim/irq_handler.c similarity index 91% rename from boards/posix/nrf52_bsim/irq_handler.c rename to boards/posix/nrf_bsim/irq_handler.c index 0ba65fc4985..24c00a4f79c 100644 --- a/boards/posix/nrf52_bsim/irq_handler.c +++ b/boards/posix/nrf_bsim/irq_handler.c @@ -43,7 +43,7 @@ static inline void vector_to_irq(int irq_nbr, int *may_swap) } bs_trace_raw_time(6, "Vectoring to irq %i (%s)\n", irq_nbr, - hw_irq_ctrl_get_name(CONFIG_NATIVE_SIMULATOR_CPU_N, irq_nbr)); + hw_irq_ctrl_get_name(CONFIG_NATIVE_SIMULATOR_MCU_N, irq_nbr)); sys_trace_isr_enter(); @@ -70,7 +70,7 @@ static inline void vector_to_irq(int irq_nbr, int *may_swap) sys_trace_isr_exit(); bs_trace_raw_time(7, "Irq %i (%s) ended\n", irq_nbr, - hw_irq_ctrl_get_name(CONFIG_NATIVE_SIMULATOR_CPU_N, irq_nbr)); + hw_irq_ctrl_get_name(CONFIG_NATIVE_SIMULATOR_MCU_N, irq_nbr)); } /** @@ -86,7 +86,7 @@ void posix_irq_handler(void) uint64_t irq_lock; int irq_nbr; static int may_swap; - const int cpu_n = CONFIG_NATIVE_SIMULATOR_CPU_N; + const int cpu_n = CONFIG_NATIVE_SIMULATOR_MCU_N; irq_lock = hw_irq_ctrl_get_current_lock(cpu_n); @@ -146,7 +146,7 @@ void posix_irq_handler_im_from_sw(void) * pending we go immediately into irq_handler() to vector into its * handler */ - if (hw_irq_ctrl_get_highest_prio_irq(CONFIG_NATIVE_SIMULATOR_CPU_N) != -1) { + if (hw_irq_ctrl_get_highest_prio_irq(CONFIG_NATIVE_SIMULATOR_MCU_N) != -1) { if (!posix_is_cpu_running()) { /* LCOV_EXCL_BR_LINE */ /* LCOV_EXCL_START */ posix_print_error_and_exit("programming error: %s " @@ -191,7 +191,7 @@ void posix_irq_handler_im_from_sw(void) */ unsigned int posix_irq_lock(void) { - return hw_irq_ctrl_change_lock(CONFIG_NATIVE_SIMULATOR_CPU_N, true); + return hw_irq_ctrl_change_lock(CONFIG_NATIVE_SIMULATOR_MCU_N, true); } /** @@ -205,27 +205,27 @@ unsigned int posix_irq_lock(void) */ void posix_irq_unlock(unsigned int key) { - hw_irq_ctrl_change_lock(CONFIG_NATIVE_SIMULATOR_CPU_N, key); + hw_irq_ctrl_change_lock(CONFIG_NATIVE_SIMULATOR_MCU_N, key); } void posix_irq_full_unlock(void) { - hw_irq_ctrl_change_lock(CONFIG_NATIVE_SIMULATOR_CPU_N, false); + hw_irq_ctrl_change_lock(CONFIG_NATIVE_SIMULATOR_MCU_N, false); } void posix_irq_enable(unsigned int irq) { - hw_irq_ctrl_enable_irq(CONFIG_NATIVE_SIMULATOR_CPU_N, irq); + hw_irq_ctrl_enable_irq(CONFIG_NATIVE_SIMULATOR_MCU_N, irq); } void posix_irq_disable(unsigned int irq) { - hw_irq_ctrl_disable_irq(CONFIG_NATIVE_SIMULATOR_CPU_N, irq); + hw_irq_ctrl_disable_irq(CONFIG_NATIVE_SIMULATOR_MCU_N, irq); } int posix_irq_is_enabled(unsigned int irq) { - return hw_irq_ctrl_is_irq_enabled(CONFIG_NATIVE_SIMULATOR_CPU_N, irq); + return hw_irq_ctrl_is_irq_enabled(CONFIG_NATIVE_SIMULATOR_MCU_N, irq); } int posix_get_current_irq(void) @@ -266,7 +266,7 @@ void posix_isr_declare(unsigned int irq_p, int flags, void isr_p(const void *), */ void posix_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags) { - hw_irq_ctrl_prio_set(CONFIG_NATIVE_SIMULATOR_CPU_N, irq, prio); + hw_irq_ctrl_prio_set(CONFIG_NATIVE_SIMULATOR_MCU_N, irq, prio); } /** @@ -279,7 +279,7 @@ void posix_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags) */ void posix_sw_set_pending_IRQ(unsigned int IRQn) { - hw_irq_ctrl_raise_im_from_sw(CONFIG_NATIVE_SIMULATOR_CPU_N, IRQn); + hw_irq_ctrl_raise_im_from_sw(CONFIG_NATIVE_SIMULATOR_MCU_N, IRQn); } /** @@ -288,7 +288,7 @@ void posix_sw_set_pending_IRQ(unsigned int IRQn) */ void posix_sw_clear_pending_IRQ(unsigned int IRQn) { - hw_irq_ctrl_clear_irq(CONFIG_NATIVE_SIMULATOR_CPU_N, IRQn); + hw_irq_ctrl_clear_irq(CONFIG_NATIVE_SIMULATOR_MCU_N, IRQn); } #ifdef CONFIG_IRQ_OFFLOAD diff --git a/boards/posix/nrf52_bsim/nrf52_bsim.dts b/boards/posix/nrf_bsim/nrf52_bsim.dts similarity index 98% rename from boards/posix/nrf52_bsim/nrf52_bsim.dts rename to boards/posix/nrf_bsim/nrf52_bsim.dts index 9c01240540e..a408ceb0eee 100644 --- a/boards/posix/nrf52_bsim/nrf52_bsim.dts +++ b/boards/posix/nrf_bsim/nrf52_bsim.dts @@ -54,6 +54,7 @@ /delete-node/ spi@40004000; /delete-node/ spi@40023000; /delete-node/ spi@4002f000; + /delete-node/ nfct@40005000; /delete-node/ watchdog@40010000; /delete-node/ acl@4001e000; /delete-node/ usbd@40027000; diff --git a/boards/posix/nrf52_bsim/nrf52_bsim.yaml b/boards/posix/nrf_bsim/nrf52_bsim.yaml similarity index 100% rename from boards/posix/nrf52_bsim/nrf52_bsim.yaml rename to boards/posix/nrf_bsim/nrf52_bsim.yaml diff --git a/boards/posix/nrf52_bsim/nrf52_bsim_defconfig b/boards/posix/nrf_bsim/nrf52_bsim_defconfig similarity index 100% rename from boards/posix/nrf52_bsim/nrf52_bsim_defconfig rename to boards/posix/nrf_bsim/nrf52_bsim_defconfig diff --git a/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpuapp.dts b/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpuapp.dts new file mode 100644 index 00000000000..36cbf9691b3 --- /dev/null +++ b/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpuapp.dts @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include + +/ { + model = "Nordic NRF5340 BSIM NRF5340 Application"; + compatible = "bsim,nrf5340-bsim-nrf5340-cpuapp","bsim,nrf53"; + + /* We need to remove aliases to nodes we delete */ + aliases { + /delete-property/ sram-0; + /delete-property/ i2c-0; + /delete-property/ spi-0; + /delete-property/ uart-0; + /delete-property/ i2c-1; + /delete-property/ spi-1; + /delete-property/ uart-1; + /delete-property/ spi-4; + /delete-property/ i2c-2; + /delete-property/ spi-2; + /delete-property/ uart-2; + /delete-property/ i2c-3; + /delete-property/ spi-3; + /delete-property/ uart-3; + /delete-property/ wdt-0; + /delete-property/ wdt-1; + /delete-property/ pwm-0; + /delete-property/ pwm-1; + /delete-property/ pwm-2; + /delete-property/ pwm-3; + /delete-property/ pdm-0; + /delete-property/ i2s-0; + /delete-property/ qdec-0; + /delete-property/ qdec-1; + /delete-property/ gpio-0; + /delete-property/ gpio-1; + /delete-property/ gpiote-0; + }; + + chosen { + zephyr,flash = &flash0; + zephyr,bt-hci-ipc = &ipc0; + nordic,802154-spinel-ipc = &ipc0; + }; + + soc { + /delete-node/ memory@20000000; + peripheral@50000000 { + /delete-node/ dcnf@0; + /delete-node/ oscillator@4000; + /delete-node/ regulator@4000; + /delete-node/ ctrlap@6000; + /delete-node/ i2c@8000; + /delete-node/ spi@8000; + /delete-node/ uart@8000; + /delete-node/ i2c@9000; + /delete-node/ spi@9000; + /delete-node/ uart@9000; + /delete-node/ spi@a000; + /delete-node/ i2c@b000; + /delete-node/ spi@b000; + /delete-node/ uart@b000; + /delete-node/ i2c@c000; + /delete-node/ spi@c000; + /delete-node/ uart@c000; + /delete-node/ adc@e000; + /delete-node/ watchdog@18000; + /delete-node/ watchdog@19000; + /delete-node/ comparator@1a000; + /delete-node/ pwm@21000; + /delete-node/ pwm@22000; + /delete-node/ pwm@23000; + /delete-node/ pwm@24000; + /delete-node/ pdm@26000; + /delete-node/ i2s@28000; + /delete-node/ qspi@2b000; + /delete-node/ nfct@2d000; + /delete-node/ qdec@33000; + /delete-node/ qdec@34000; + /delete-node/ usbd@36000; + /delete-node/ regulator@37000; + /delete-node/ kmu@39000; + /delete-node/ vmc@81000; + /delete-node/ gpio@842500; + /delete-node/ gpio@842800; + }; + /delete-node/ spu@50003000; + /delete-node/ gpiote@5000d000; + /delete-node/ crypto@50844000; + }; + + /delete-node/ cpus; + /delete-node/ sw-pwm; +}; + +&ieee802154 { + status = "okay"; +}; + +&flash0 { + reg = <0x00000000 DT_SIZE_K(1024)>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + storage_partition: partition@0 { + label = "storage"; + reg = <0x00000000 DT_SIZE_K(1024)>; + }; + }; +}; + +/* We re-use the IPC shared buffer definition from the real HW. But note the start address of the + * buffer won't be used. + */ +#include <../boards/arm/nrf5340dk_nrf5340/nrf5340_shared_sram_planning_conf.dtsi> diff --git a/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpuapp.yaml b/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpuapp.yaml new file mode 100644 index 00000000000..822368df0d3 --- /dev/null +++ b/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpuapp.yaml @@ -0,0 +1,14 @@ +identifier: nrf5340bsim_nrf5340_cpuapp +name: NRF53 BabbleSim - Application Core target +type: native +arch: posix +simulation: native +env: + - BSIM_OUT_PATH +toolchain: + - zephyr +testing: + ignore_tags: + - gpio + - modem + - uart diff --git a/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpuapp_defconfig b/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpuapp_defconfig new file mode 100644 index 00000000000..fcf14c5b33a --- /dev/null +++ b/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpuapp_defconfig @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_POSIX=y +CONFIG_BOARD_NRF5340BSIM_NRF5340_CPUAPP=y +CONFIG_CONSOLE=y +CONFIG_NO_OPTIMIZATIONS=y diff --git a/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpunet.dts b/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpunet.dts new file mode 100644 index 00000000000..d9d7b02fc67 --- /dev/null +++ b/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpunet.dts @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include + +/ { + model = "Nordic NRF5340 BSIM NRF5340 Network"; + compatible = "bsim,nrf5340-bsim-nrf5340-cpunet","bsim,nrf53"; + + /* We need to remove aliases to nodes we delete */ + aliases { + /delete-property/ sram-0; + /delete-property/ sram-1; + /delete-property/ gpiote-0; + /delete-property/ wdt-0; + /delete-property/ i2c-0; + /delete-property/ spi-0; + /delete-property/ uart-0; + /delete-property/ gpio-0; + /delete-property/ gpio-1; + }; + + chosen { + zephyr,bt-hci-ipc = &ipc0; + nordic,802154-spinel-ipc = &ipc0; + zephyr,ieee802154 = &ieee802154; + /delete-property/ zephyr,flash-controller; + zephyr,flash = &flash1; + }; + + soc { + /delete-node/ memory@20000000; + /delete-node/ memory@21000000; + /delete-node/ gpiote@4100a000; + /delete-node/ watchdog@4100b000; + /delete-node/ i2c@41013000; + /delete-node/ spi@41013000; + /delete-node/ uart@41013000; + /delete-node/ acl@41080000; + /delete-node/ vmc@41081000; + /delete-node/ gpio@418c0500; + /delete-node/ gpio@418c0800; + }; + + /delete-node/ cpus; + /delete-node/ sw-pwm; +}; + +&radio { + /* These features are not yet supported by the RADIO model */ + /delete-property/ dfe-supported; + /delete-property/ ble-coded-phy-supported; +}; + +&ieee802154 { + status = "okay"; +}; + +&flash1 { + reg = <0x01000000 DT_SIZE_K(256)>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + storage_partition: partition@0 { + label = "storage"; + reg = <0x00000000 DT_SIZE_K(256)>; + }; + }; +}; + +/* We re-use the IPC shared buffer definition from the real HW. But note the start address of the + * buffer won't be used. + */ +#include <../boards/arm/nrf5340dk_nrf5340/nrf5340_shared_sram_planning_conf.dtsi> diff --git a/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpunet.yaml b/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpunet.yaml new file mode 100644 index 00000000000..4e305c095d3 --- /dev/null +++ b/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpunet.yaml @@ -0,0 +1,14 @@ +identifier: nrf5340bsim_nrf5340_cpunet +name: NRF53 Net Core BabbleSim board +type: native +arch: posix +simulation: native +env: + - BSIM_OUT_PATH +toolchain: + - zephyr +testing: + ignore_tags: + - gpio + - modem + - uart diff --git a/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpunet_defconfig b/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpunet_defconfig new file mode 100644 index 00000000000..5da7b71af05 --- /dev/null +++ b/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpunet_defconfig @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_POSIX=y +CONFIG_BOARD_NRF5340BSIM_NRF5340_CPUNET=y +CONFIG_CONSOLE=y +CONFIG_NO_OPTIMIZATIONS=y diff --git a/boards/posix/nrf_bsim/nsi_if.c b/boards/posix/nrf_bsim/nsi_if.c new file mode 100644 index 00000000000..d0f45597fa3 --- /dev/null +++ b/boards/posix/nrf_bsim/nsi_if.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include "bstests.h" +#include "bs_tracing.h" +#include "phy_sync_ctrl.h" +#include "nsi_hw_scheduler.h" +#include "nsi_cpu_ctrl.h" + +/* + * These hooks are to be named nsif_cpu_, for example nsif_cpu0_boot + */ +#define nsif_cpun_pre_cmdline_hooks _CONCAT(_CONCAT(nsif_cpu, CONFIG_NATIVE_SIMULATOR_MCU_N),\ + _pre_cmdline_hooks) +#define nsif_cpun_save_test_arg _CONCAT(_CONCAT(nsif_cpu, CONFIG_NATIVE_SIMULATOR_MCU_N),\ + _save_test_arg) +#define nsif_cpun_pre_hw_init_hooks _CONCAT(_CONCAT(nsif_cpu, CONFIG_NATIVE_SIMULATOR_MCU_N),\ + _pre_hw_init_hooks) +#define nsif_cpun_boot _CONCAT(_CONCAT(nsif_cpu, CONFIG_NATIVE_SIMULATOR_MCU_N),\ + _boot) +#define nsif_cpun_cleanup _CONCAT(_CONCAT(nsif_cpu, CONFIG_NATIVE_SIMULATOR_MCU_N),\ + _cleanup) +#define nsif_cpun_irq_raised _CONCAT(_CONCAT(nsif_cpu, CONFIG_NATIVE_SIMULATOR_MCU_N),\ + _irq_raised) +#define nsif_cpun_test_hook _CONCAT(_CONCAT(nsif_cpu, CONFIG_NATIVE_SIMULATOR_MCU_N),\ + _test_hook) +#define nsif_cpun_irq_raised_from_sw _CONCAT(_CONCAT(nsif_cpu, CONFIG_NATIVE_SIMULATOR_MCU_N),\ + _irq_raised_from_sw) + +NATIVE_SIMULATOR_IF void nsif_cpun_pre_cmdline_hooks(void) +{ + run_native_tasks(_NATIVE_PRE_BOOT_1_LEVEL); +#if defined(CONFIG_NATIVE_SIMULATOR_AUTOSTART_MCU) + nsi_cpu_set_auto_start(CONFIG_NATIVE_SIMULATOR_MCU_N, true); +#endif +} + +#define TESTCASAE_ARGV_ALLOCSIZE 128 + +static struct { + char **test_case_argv; + int test_case_argc; + int allocated_size; +} test_args; + +NATIVE_SIMULATOR_IF void nsif_cpun_save_test_arg(char *argv) +{ + if (test_args.test_case_argc >= test_args.allocated_size) { + test_args.allocated_size += TESTCASAE_ARGV_ALLOCSIZE; + test_args.test_case_argv = realloc(test_args.test_case_argv, + test_args.allocated_size * sizeof(char *)); + if (test_args.test_case_argv == NULL) { /* LCOV_EXCL_BR_LINE */ + bs_trace_error_line("Can't allocate memory\n"); /* LCOV_EXCL_LINE */ + } + } + + bs_trace_raw(9, "cmdarg: adding '%s' to testcase args[%i]\n", + argv, test_args.test_case_argc); + test_args.test_case_argv[test_args.test_case_argc++] = argv; +} + +static void test_args_free(void) +{ + if (test_args.test_case_argv) { + free(test_args.test_case_argv); + test_args.test_case_argv = NULL; + } +} + +NATIVE_TASK(test_args_free, ON_EXIT_PRE, 100); + +NATIVE_SIMULATOR_IF void nsif_cpun_pre_hw_init_hooks(void) +{ + run_native_tasks(_NATIVE_PRE_BOOT_2_LEVEL); + phy_sync_ctrl_connect_to_2G4_phy(); + + /* We pass to a possible testcase its command line arguments */ + bst_pass_args(test_args.test_case_argc, test_args.test_case_argv); + phy_sync_ctrl_pre_boot2(); +} + +NATIVE_SIMULATOR_IF void nsif_cpun_boot(void) +{ + run_native_tasks(_NATIVE_PRE_BOOT_3_LEVEL); + bst_pre_init(); + phy_sync_ctrl_pre_boot3(); + posix_boot_cpu(); + run_native_tasks(_NATIVE_FIRST_SLEEP_LEVEL); + bst_post_init(); +} + +NATIVE_SIMULATOR_IF int nsif_cpun_cleanup(void) +{ + /* + * Note posix_soc_clean_up() may not return, but in that case, + * nsif_cpun_cleanup() will be called again + */ + posix_soc_clean_up(); + + uint8_t bst_result = bst_delete(); + return bst_result; +} + +NATIVE_SIMULATOR_IF void nsif_cpun_irq_raised(void) +{ + posix_interrupt_raised(); +} + +NATIVE_SIMULATOR_IF int nsif_cpun_test_hook(void *p) +{ + (void) p; + bst_tick(nsi_hws_get_time()); + return 0; +} + +NATIVE_SIMULATOR_IF void nsif_cpun_irq_raised_from_sw(void) +{ + void posix_irq_handler_im_from_sw(void); + posix_irq_handler_im_from_sw(); +} diff --git a/boards/posix/nrf52_bsim/pre_dt_board.cmake b/boards/posix/nrf_bsim/pre_dt_board.cmake similarity index 100% rename from boards/posix/nrf52_bsim/pre_dt_board.cmake rename to boards/posix/nrf_bsim/pre_dt_board.cmake diff --git a/boards/posix/nrf52_bsim/soc/nrfx_coredep.c b/boards/posix/nrf_bsim/soc/nrfx_coredep.c similarity index 100% rename from boards/posix/nrf52_bsim/soc/nrfx_coredep.c rename to boards/posix/nrf_bsim/soc/nrfx_coredep.c diff --git a/boards/posix/nrf52_bsim/soc/soc_secure.h b/boards/posix/nrf_bsim/soc/soc_secure.h similarity index 100% rename from boards/posix/nrf52_bsim/soc/soc_secure.h rename to boards/posix/nrf_bsim/soc/soc_secure.h diff --git a/boards/posix/nrf52_bsim/time_machine.h b/boards/posix/nrf_bsim/time_machine.h similarity index 93% rename from boards/posix/nrf52_bsim/time_machine.h rename to boards/posix/nrf_bsim/time_machine.h index de973cf4c8f..2e8a70dfeed 100644 --- a/boards/posix/nrf52_bsim/time_machine.h +++ b/boards/posix/nrf_bsim/time_machine.h @@ -8,7 +8,7 @@ #include "bs_types.h" #include "time_machine_if.h" -#include "zephyr/toolchain.h" +#include #ifdef __cplusplus extern "C" { diff --git a/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350.dts b/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350.dts index bc39000962b..58c91613057 100644 --- a/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350.dts +++ b/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350.dts @@ -211,3 +211,7 @@ &wdt { status = "okay"; }; + +&dma0 { + status = "okay"; +}; diff --git a/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350.yaml b/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350.yaml index b7e792cac8a..5716d7e6e13 100644 --- a/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350.yaml +++ b/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350.yaml @@ -15,6 +15,8 @@ supported: - watchdog - mbox - flash + - dma testing: ignore_tags: - bluetooth +vendor: andestech diff --git a/boards/riscv/adp_xc7k_ae350/doc/index.rst b/boards/riscv/adp_xc7k_ae350/doc/index.rst index 8c6d7fc14f8..c12c04cabc4 100644 --- a/boards/riscv/adp_xc7k_ae350/doc/index.rst +++ b/boards/riscv/adp_xc7k_ae350/doc/index.rst @@ -66,6 +66,24 @@ The ``adp_xc7k_ae350`` board configuration supports the following hardware featu +----------------+------------+----------------------+ | UART | on-chip | serial | +----------------+------------+----------------------+ +| COUNTER | on-chip | counter | ++----------------+------------+----------------------+ +| SPI | on-chip | spi | ++----------------+------------+----------------------+ +| I2C | on-chip | i2c | ++----------------+------------+----------------------+ +| EEPROM | on-chip | eeprom | ++----------------+------------+----------------------+ +| FLASH | on-chip | flash | ++----------------+------------+----------------------+ +| HWINFO | on-chip | syscon | ++----------------+------------+----------------------+ +| MAILBOX | on-chip | mbox | ++----------------+------------+----------------------+ +| DMA | on-chip | dma | ++----------------+------------+----------------------+ +| WATCHDOG | on-chip | wdt | ++----------------+------------+----------------------+ Other hardware features are not supported yet. @@ -211,6 +229,7 @@ You can build applications in the usual way. Here is an example for the :ref:`hello_world` application. .. zephyr-app-commands:: + :zephyr-app: samples/hello_world :board: adp_xc7k_ae350 :goals: build @@ -246,7 +265,7 @@ and execute it. # Check the ICEman server is running # Load the program into RAM and execute it - riscv64-zephyr-elf-gdb zephyr/zephyr.elf + riscv64-zephyr-elf-gdb build/zephyr/zephyr.elf (gdb) target remote :1111 (gdb) monitor reset halt (gdb) load @@ -260,7 +279,7 @@ and execute it. # Check the ICEman server is running # Burn the program into flash and execute it /bin/target_burn_frontend \ - -P 4444 --unlock --verify --image=zephyr/zephyr.bin \ + -P 4444 --unlock --verify --image=build/zephyr/zephyr.bin \ --algorithm-bin=/target_bin/target_SPI_v5_[32|64].bin # Note: @@ -289,7 +308,7 @@ Debugging # Check the ICEman server is running # Load and debug program - ./riscv64-zephyr-elf-gdb zephyr/zephyr.elf + ./riscv64-zephyr-elf-gdb build/zephyr/zephyr.elf (gdb) target remote :1111 (gdb) monitor reset halt (gdb) load diff --git a/boards/riscv/esp32c3_devkitm/doc/index.rst b/boards/riscv/esp32c3_devkitm/doc/index.rst index 95b14e8a39b..6d21b2918c3 100644 --- a/boards/riscv/esp32c3_devkitm/doc/index.rst +++ b/boards/riscv/esp32c3_devkitm/doc/index.rst @@ -122,7 +122,7 @@ Sysbuild ======== The sysbuild makes possible to build and flash all necessary images needed to -bootstrap the board with the EPS32 SoC. +bootstrap the board with the ESP32 SoC. To build the sample application using sysbuild use the command: diff --git a/boards/riscv/esp32c3_devkitm/esp32c3_devkitm.yaml b/boards/riscv/esp32c3_devkitm/esp32c3_devkitm.yaml index 552255dee0a..d52d2bd30eb 100644 --- a/boards/riscv/esp32c3_devkitm/esp32c3_devkitm.yaml +++ b/boards/riscv/esp32c3_devkitm/esp32c3_devkitm.yaml @@ -19,3 +19,4 @@ testing: ignore_tags: - net - bluetooth +vendor: espressif diff --git a/boards/riscv/esp32c3_luatos_core/Kconfig.board b/boards/riscv/esp32c3_luatos_core/Kconfig.board new file mode 100644 index 00000000000..ac7b48a7a36 --- /dev/null +++ b/boards/riscv/esp32c3_luatos_core/Kconfig.board @@ -0,0 +1,14 @@ +# Copyright (c) 2023 YuLong Yao +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_ESP32C3_LUATOS_CORE + bool "luatos ESP32C3-CORE Board" + depends on SOC_SERIES_ESP32C3 + +config BOARD_ESP32C3_LUATOS_CORE_USB + bool "luatos ESP32C3-CORE Board without UART chip" + depends on SOC_SERIES_ESP32C3 + +choice SOC_PART_NUMBER + default SOC_ESP32C3_MINI_N4 +endchoice diff --git a/boards/riscv/esp32c3_luatos_core/Kconfig.defconfig b/boards/riscv/esp32c3_luatos_core/Kconfig.defconfig new file mode 100644 index 00000000000..1a1ee456a3d --- /dev/null +++ b/boards/riscv/esp32c3_luatos_core/Kconfig.defconfig @@ -0,0 +1,17 @@ +# ESP32C3 core board configuration + +# Copyright (c) 2023 YuLong Yao +# SPDX-License-Identifier: Apache-2.0 + +config BOARD + default "esp32c3_luatos_core" + depends on BOARD_ESP32C3_LUATOS_CORE || BOARD_ESP32C3_LUATOS_CORE_USB + +config HEAP_MEM_POOL_SIZE + default 98304 if WIFI + default 40960 if BT + default 4096 + +choice BT_HCI_BUS_TYPE + default BT_ESP32 if BT +endchoice diff --git a/boards/riscv/esp32c3_luatos_core/Kconfig.sysbuild b/boards/riscv/esp32c3_luatos_core/Kconfig.sysbuild new file mode 100644 index 00000000000..3a2d17ac5cf --- /dev/null +++ b/boards/riscv/esp32c3_luatos_core/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/boards/riscv/esp32c3_luatos_core/board.cmake b/boards/riscv/esp32c3_luatos_core/board.cmake new file mode 100644 index 00000000000..d8eee88156c --- /dev/null +++ b/boards/riscv/esp32c3_luatos_core/board.cmake @@ -0,0 +1,10 @@ +# Copyright (c) 2023 YuLong Yao +# SPDX-License-Identifier: Apache-2.0 + +if(NOT "${OPENOCD}" MATCHES "^${ESPRESSIF_TOOLCHAIN_PATH}/.*") + set(OPENOCD OPENOCD-NOTFOUND) +endif() +find_program(OPENOCD openocd PATHS ${ESPRESSIF_TOOLCHAIN_PATH}/openocd-esp32/bin NO_DEFAULT_PATH) + +include(${ZEPHYR_BASE}/boards/common/esp32.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/riscv/esp32c3_luatos_core/doc/img/esp32c3_luatos_core.jpg b/boards/riscv/esp32c3_luatos_core/doc/img/esp32c3_luatos_core.jpg new file mode 100644 index 00000000000..df25a96c292 Binary files /dev/null and b/boards/riscv/esp32c3_luatos_core/doc/img/esp32c3_luatos_core.jpg differ diff --git a/boards/riscv/esp32c3_luatos_core/doc/img/esp32c3_luatos_core_pinfunc.jpg b/boards/riscv/esp32c3_luatos_core/doc/img/esp32c3_luatos_core_pinfunc.jpg new file mode 100644 index 00000000000..3e1968c8f6e Binary files /dev/null and b/boards/riscv/esp32c3_luatos_core/doc/img/esp32c3_luatos_core_pinfunc.jpg differ diff --git a/boards/riscv/esp32c3_luatos_core/doc/img/esp32c3_luatos_core_usb.jpg b/boards/riscv/esp32c3_luatos_core/doc/img/esp32c3_luatos_core_usb.jpg new file mode 100644 index 00000000000..10ccc8d0cf1 Binary files /dev/null and b/boards/riscv/esp32c3_luatos_core/doc/img/esp32c3_luatos_core_usb.jpg differ diff --git a/boards/riscv/esp32c3_luatos_core/doc/index.rst b/boards/riscv/esp32c3_luatos_core/doc/index.rst new file mode 100644 index 00000000000..c943931a9e6 --- /dev/null +++ b/boards/riscv/esp32c3_luatos_core/doc/index.rst @@ -0,0 +1,259 @@ +.. _esp32c3_luatos_core: + +ESP32C3_LUATOS_CORE +################### + +Overview +******** + +ESP32-C3 is a single-core Wi-Fi and Bluetooth 5 (LE) microcontroller SoC, +based on the open-source RISC-V architecture. It strikes the right balance of power, +I/O capabilities and security, thus offering the optimal cost-effective +solution for connected devices. +The availability of Wi-Fi and Bluetooth 5 (LE) connectivity not only makes the device configuration easy, +but it also facilitates a variety of use-cases based on dual connectivity. [1]_ + +The features include the following: + +- 32-bit core RISC-V microcontroller with a maximum clock speed of 160 MHz +- 400 KB of internal RAM +- 802.11b/g/n/e/i +- A Bluetooth LE subsystem that supports features of Bluetooth 5 and Bluetooth mesh +- Various peripherals: + + - 12-bit ADC with up to 6 channels + - TWAI compatible with CAN bus 2.0 + - Temperature sensor + - 3x SPI + - 1x I2S + - 1x I2C + - 2x UART + - LED PWM with up to 6 channels + +- Cryptographic hardware acceleration (RNG, ECC, RSA, SHA-2, AES) + +There are two version hardware of this board. The difference between them is the ch343 chip. + +1. USB-C connect to UART over CH343 chip(esp32c3_luatos_core) + +.. image:: img/esp32c3_luatos_core.jpg + :align: center + :alt: esp32c3_luatos_core + +2. USB-C connect to esp32 chip directly(esp32c3_luatos_core_usb) + +.. image:: img/esp32c3_luatos_core_usb.jpg + :align: center + :alt: esp32c3_luatos_core_usb + +Supported Features +================== + +Current Zephyr's ESP32C3_LUATOS_CORE board supports the following features: + ++------------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++============+============+=====================================+ ++------------+------------+-------------------------------------+ +| UART | on-chip | serial port | ++------------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++------------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++------------+------------+-------------------------------------+ +| USB-JTAG | on-chip | hardware interface | ++------------+------------+-------------------------------------+ +| SPI Master | on-chip | spi | ++------------+------------+-------------------------------------+ +| Timers | on-chip | counter | ++------------+------------+-------------------------------------+ +| Watchdog | on-chip | watchdog | ++------------+------------+-------------------------------------+ +| TRNG | on-chip | entropy | ++------------+------------+-------------------------------------+ +| LEDC | on-chip | pwm | ++------------+------------+-------------------------------------+ +| SPI DMA | on-chip | spi | ++------------+------------+-------------------------------------+ +| TWAI | on-chip | can | ++------------+------------+-------------------------------------+ +| USB-CDC | on-chip | serial | ++------------+------------+-------------------------------------+ +| ADC | on-chip | adc | ++------------+------------+-------------------------------------+ +| Wi-Fi | on-chip | | ++------------+------------+-------------------------------------+ +| Bluetooth | on-chip | | ++------------+------------+-------------------------------------+ + +.. image:: img/esp32c3_luatos_core_pinfunc.jpg + :align: center + :alt: esp32c3_luatos_core_pinfunc + +System requirements +******************* + +Prerequisites +============= + +Espressif HAL requires WiFi and Bluetooth binary blobs in order work. Run the command +below to retrieve those files. + +.. code-block:: console + + west blobs fetch hal_espressif + +.. note:: + + It is recommended running the command above after :file:`west update`. + +Building & Flashing +******************* + +ESP-IDF bootloader +================== + +The board is using the ESP-IDF bootloader as the default 2nd stage bootloader. +It is build as a subproject at each application build. No further attention +is expected from the user. + +MCUboot bootloader +================== + +User may choose to use MCUboot bootloader instead. In that case the bootloader +must be build (and flash) at least once. + +There are two options to be used when building an application: + +1. Sysbuild +2. Manual build + +.. note:: + + User can select the MCUboot bootloader by adding the following line + to the board default configuration file. + ``` + CONFIG_BOOTLOADER_MCUBOOT=y + ``` + +Sysbuild +======== + +The sysbuild makes possible to build and flash all necessary images needed to +bootstrap the board with the ESP32 SoC. + +To build the sample application using sysbuild use the command: + +.. zephyr-app-commands:: + :tool: west + :app: samples/hello_world + :board: esp32c3_luatos_core + :goals: build + :west-args: --sysbuild + :compact: + +By default, the ESP32 sysbuild creates bootloader (MCUboot) and application +images. But it can be configured to create other kind of images. + +Build directory structure created by sysbuild is different from traditional +Zephyr build. Output is structured by the domain subdirectories: + +.. code-block:: + + build/ + ├── hello_world + │   └── zephyr + │   ├── zephyr.elf + │   └── zephyr.bin + ├── mcuboot + │ └── zephyr + │ ├── zephyr.elf + │ └── zephyr.bin + └── domains.yaml + +.. note:: + + With ``--sysbuild`` option the bootloader will be re-build and re-flash + every time the pristine build is used. + +For more information about the system build please read the :ref:`sysbuild` documentation. + +Manual build +============ + +During the development cycle, it is intended to build & flash as quickly possible. +For that reason, images can be build one at a time using traditional build. + +The instructions following are relevant for both manual build and sysbuild. +The only difference is the structure of the build directory. + +.. note:: + + Remember that bootloader (MCUboot) needs to be flash at least once. + +Build and flash applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32c3_luatos_core + :goals: build + +The usual ``flash`` target will work with the ``esp32c3_luatos_core`` board +configuration. Here is an example for the :ref:`hello_world` +application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32c3_luatos_core + :goals: flash + +Open the serial monitor using the following command: + +.. code-block:: shell + + west espressif monitor + +After the board has automatically reset and booted, you should see the following +message in the monitor: + +.. code-block:: console + + ***** Booting Zephyr OS vx.x.x-xxx-gxxxxxxxxxxxx ***** + Hello World! esp32c3_luatos_core + +Debugging +********* + +As with much custom hardware, the ESP32-C3 modules require patches to +OpenOCD that are not upstreamed yet. Espressif maintains their own fork of +the project. The custom OpenOCD can be obtained at `OpenOCD ESP32`_ + +The Zephyr SDK uses a bundled version of OpenOCD by default. You can overwrite that behavior by adding the +``-DOPENOCD= -DOPENOCD_DEFAULT_PATH=`` +parameter when building. + +Here is an example for building the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32c3_luatos_core + :goals: build flash + :gen-args: -DOPENOCD= -DOPENOCD_DEFAULT_PATH= + +You can debug an application in the usual way. Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32c3_luatos_core + :goals: debug + +.. _`OpenOCD ESP32`: https://github.com/espressif/openocd-esp32/releases + +References +********** + +.. [1] https://www.espressif.com/en/products/socs/esp32-c3 +.. _ESP32C3 Core Website: https://wiki.luatos.com/chips/esp32c3/board.html +.. _ESP32C3 Technical Reference Manual: https://espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf +.. _ESP32C3 Datasheet: https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf diff --git a/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core-pinctrl.dtsi b/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core-pinctrl.dtsi new file mode 100644 index 00000000000..c775009d8d5 --- /dev/null +++ b/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core-pinctrl.dtsi @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 YuLong Yao + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +&pinctrl { + uart0_default: uart0_default { + group1 { + pinmux = ; + output-high; + }; + group2 { + pinmux = ; + bias-pull-up; + }; + }; + + spim2_default: spim2_default { + group1 { + pinmux = , + , + ; + }; + group2 { + pinmux = ; + output-low; + }; + }; + + i2c0_default: i2c0_default { + group1 { + pinmux = , + ; + bias-pull-up; + drive-open-drain; + output-high; + }; + }; + + twai_default: twai_default { + group1 { + pinmux = , + ; + }; + }; +}; diff --git a/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core.dts b/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core.dts new file mode 100644 index 00000000000..5a74be9984e --- /dev/null +++ b/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core.dts @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 YuLong Yao + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include "esp32c3_luatos_core.dtsi" + +/ { + chosen { + zephyr,sram = &sram0; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,flash = &flash0; + }; +}; diff --git a/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core.dtsi b/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core.dtsi new file mode 100644 index 00000000000..2a1a74996c5 --- /dev/null +++ b/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core.dtsi @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2023 YuLong Yao + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp32c3_luatos_core-pinctrl.dtsi" +#include + +/ { + model = "esp32c3_luatos_core"; + compatible = "espressif,esp32c3"; + + aliases { + sw0 = &user_button1; + i2c-0 = &i2c0; + watchdog0 = &wdt0; + led0 = &led_d4; + led1 = &led_d5; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button1: button_1 { + label = "User SW1"; + gpios = <&gpio0 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + zephyr,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_d4: led_1 { + label = "D4"; + gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; + }; + led_d5: led_2 { + label = "D5"; + gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&cpu0 { + clock-frequency = ; +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; +}; + +&i2c0 { + status = "okay"; + clock-frequency = ; + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; +}; + +&trng0 { + status = "okay"; +}; + +&spi2 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + pinctrl-0 = <&spim2_default>; + pinctrl-names = "default"; +}; + +&gpio0 { + status = "okay"; +}; + +&wdt0 { + status = "okay"; +}; + +&timer0 { + status = "disabled"; +}; + +&timer1 { + status = "disabled"; +}; + +&twai { + /* requires external CAN transceiver or jumper on RX and TX pins for loopback testing */ + status = "disabled"; + pinctrl-0 = <&twai_default>; + pinctrl-names = "default"; + bus-speed = <125000>; +}; + +&flash0 { + status = "okay"; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserve 60kB for the bootloader */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x0000F000>; + read-only; + }; + + /* Reserve 1024kB for the application in slot 0 */ + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 0x00100000>; + }; + + /* Reserve 1024kB for the application in slot 1 */ + slot1_partition: partition@110000 { + label = "image-1"; + reg = <0x00110000 0x00100000>; + }; + + /* Reserve 256kB for the scratch partition */ + scratch_partition: partition@210000 { + label = "image-scratch"; + reg = <0x00210000 0x00040000>; + }; + + storage_partition: partition@250000 { + label = "storage"; + reg = <0x00250000 0x00006000>; + }; + }; +}; diff --git a/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core.yaml b/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core.yaml new file mode 100644 index 00000000000..6b5641273e2 --- /dev/null +++ b/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core.yaml @@ -0,0 +1,22 @@ +identifier: esp32c3_luatos_core +name: ESP32C3 LuatOS Core +type: mcu +arch: riscv32 +toolchain: + - zephyr +supported: + - adc + - gpio + - i2c + - watchdog + - uart + - dma + - pwm + - spi + - counter + - entropy +testing: + ignore_tags: + - net + - bluetooth +vendor: espressif diff --git a/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core_defconfig b/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core_defconfig new file mode 100644 index 00000000000..d3f8458a2ef --- /dev/null +++ b/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core_defconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_BOARD_ESP32C3_LUATOS_CORE=y +CONFIG_SOC_SERIES_ESP32C3=y + +CONFIG_MAIN_STACK_SIZE=2048 + +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y +CONFIG_GPIO=y diff --git a/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core_usb.dts b/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core_usb.dts new file mode 100644 index 00000000000..f7e99f9b776 --- /dev/null +++ b/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core_usb.dts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 YuLong Yao + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include "esp32c3_luatos_core.dtsi" + +/ { + chosen { + zephyr,sram = &sram0; + zephyr,console = &usb_serial; + zephyr,shell-uart = &usb_serial; + zephyr,flash = &flash0; + }; +}; + +&uart0 { + status = "disabled"; +}; + +&usb_serial { + status = "okay"; +}; diff --git a/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core_usb.yaml b/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core_usb.yaml new file mode 100644 index 00000000000..81acd4d0bb3 --- /dev/null +++ b/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core_usb.yaml @@ -0,0 +1,22 @@ +identifier: esp32c3_luatos_core_usb +name: ESP32C3 LuatOS Core USB +type: mcu +arch: riscv32 +toolchain: + - zephyr +supported: + - adc + - gpio + - i2c + - watchdog + - uart + - dma + - pwm + - spi + - counter + - entropy +testing: + ignore_tags: + - net + - bluetooth +vendor: espressif diff --git a/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core_usb_defconfig b/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core_usb_defconfig new file mode 100644 index 00000000000..0a441dde0bb --- /dev/null +++ b/boards/riscv/esp32c3_luatos_core/esp32c3_luatos_core_usb_defconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_BOARD_ESP32C3_LUATOS_CORE_USB=y +CONFIG_SOC_SERIES_ESP32C3=y + +CONFIG_MAIN_STACK_SIZE=2048 + +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y +CONFIG_GPIO=y diff --git a/boards/riscv/esp32c3_luatos_core/support/openocd.cfg b/boards/riscv/esp32c3_luatos_core/support/openocd.cfg new file mode 100644 index 00000000000..b93b20ba46e --- /dev/null +++ b/boards/riscv/esp32c3_luatos_core/support/openocd.cfg @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 +set ESP_RTOS none + +# ESP32C3 has built-in JTAG interface over USB port in pins GPIO18/GPIO19 (D-/D+). +# Uncomment the line below to enable USB debugging. +source [find interface/esp_usb_jtag.cfg] + +# Otherwise, use external JTAG programmer as ESP-Prog +# source [find interface/ftdi/esp32_devkitj_v1.cfg] + +source [find target/esp32c3.cfg] +adapter_khz 5000 diff --git a/boards/riscv/gd32vf103c_starter/gd32vf103c_starter.yaml b/boards/riscv/gd32vf103c_starter/gd32vf103c_starter.yaml index 67027110d15..546e54d2cd1 100644 --- a/boards/riscv/gd32vf103c_starter/gd32vf103c_starter.yaml +++ b/boards/riscv/gd32vf103c_starter/gd32vf103c_starter.yaml @@ -16,3 +16,4 @@ supported: - watchdog - dma - spi +vendor: gd diff --git a/boards/riscv/gd32vf103v_eval/gd32vf103v_eval.yaml b/boards/riscv/gd32vf103v_eval/gd32vf103v_eval.yaml index 27696651e4d..306d3e11498 100644 --- a/boards/riscv/gd32vf103v_eval/gd32vf103v_eval.yaml +++ b/boards/riscv/gd32vf103v_eval/gd32vf103v_eval.yaml @@ -16,3 +16,4 @@ supported: - watchdog - dma - spi +vendor: gd diff --git a/boards/riscv/hifive1/hifive1.yaml b/boards/riscv/hifive1/hifive1.yaml index 1e716ed5de9..d2a8280bc2d 100644 --- a/boards/riscv/hifive1/hifive1.yaml +++ b/boards/riscv/hifive1/hifive1.yaml @@ -19,3 +19,4 @@ testing: - bluetooth - flash - newlib +vendor: sifive diff --git a/boards/riscv/hifive1_revb/hifive1_revb.yaml b/boards/riscv/hifive1_revb/hifive1_revb.yaml index 1de32bb61fd..8b3576b1fc7 100644 --- a/boards/riscv/hifive1_revb/hifive1_revb.yaml +++ b/boards/riscv/hifive1_revb/hifive1_revb.yaml @@ -14,3 +14,4 @@ supported: - arduino_i2c - gpio - i2c +vendor: sifive diff --git a/boards/riscv/hifive_unleashed/hifive_unleashed.yaml b/boards/riscv/hifive_unleashed/hifive_unleashed.yaml index 072677cc45e..9600aa0218d 100644 --- a/boards/riscv/hifive_unleashed/hifive_unleashed.yaml +++ b/boards/riscv/hifive_unleashed/hifive_unleashed.yaml @@ -17,3 +17,4 @@ testing: supported: - gpio - spi +vendor: sifive diff --git a/boards/riscv/hifive_unmatched/hifive_unmatched.yaml b/boards/riscv/hifive_unmatched/hifive_unmatched.yaml index e054abf43c6..8b62698b61b 100644 --- a/boards/riscv/hifive_unmatched/hifive_unmatched.yaml +++ b/boards/riscv/hifive_unmatched/hifive_unmatched.yaml @@ -12,3 +12,4 @@ testing: supported: - spi - memc +vendor: sifive diff --git a/boards/riscv/icev_wireless/doc/index.rst b/boards/riscv/icev_wireless/doc/index.rst index f6358fbfbcc..a3ae804c668 100644 --- a/boards/riscv/icev_wireless/doc/index.rst +++ b/boards/riscv/icev_wireless/doc/index.rst @@ -128,7 +128,7 @@ Sysbuild ======== The sysbuild makes possible to build and flash all necessary images needed to -bootstrap the board with the EPS32 SoC. +bootstrap the board with the ESP32 SoC. To build the sample application using sysbuild use the command: diff --git a/boards/riscv/icev_wireless/icev_wireless.yaml b/boards/riscv/icev_wireless/icev_wireless.yaml index 9321db80125..cf87f3f1165 100644 --- a/boards/riscv/icev_wireless/icev_wireless.yaml +++ b/boards/riscv/icev_wireless/icev_wireless.yaml @@ -8,3 +8,4 @@ testing: ignore_tags: - net - bluetooth +vendor: espressif diff --git a/boards/riscv/it82xx2_evb/Kconfig.defconfig b/boards/riscv/it82xx2_evb/Kconfig.defconfig index eb57ed18431..37d6dc601c9 100644 --- a/boards/riscv/it82xx2_evb/Kconfig.defconfig +++ b/boards/riscv/it82xx2_evb/Kconfig.defconfig @@ -5,4 +5,8 @@ if BOARD_IT82XX2_EVB config BOARD default "it82xx2_evb" + +config INPUT + default y if KSCAN + endif diff --git a/boards/riscv/it82xx2_evb/it82xx2_evb.dts b/boards/riscv/it82xx2_evb/it82xx2_evb.dts index 2938fb7ebd5..1d1bb23eeb6 100644 --- a/boards/riscv/it82xx2_evb/it82xx2_evb.dts +++ b/boards/riscv/it82xx2_evb/it82xx2_evb.dts @@ -17,7 +17,7 @@ i2c-0 = &i2c0; peci-0 = &peci0; led0 = &led0; - kscan0 = &kscan0; + kscan0 = &kscan_input; watchdog0 = &twd0; pwm-0 = &pwm0; }; @@ -30,7 +30,7 @@ zephyr,flash = &flash0; zephyr,flash-controller = &flashctrl; zephyr,code-partition = &slot0_partition; - zephyr,keyboard-scan = &kscan0; + zephyr,keyboard-scan = &kscan_input; }; leds { @@ -108,13 +108,13 @@ &uart1 { status = "okay"; current-speed = <115200>; - clock-frequency = <1804800>; + clock-frequency = <1843200>; }; &uart2 { status = "okay"; current-speed = <460800>; - clock-frequency = <1804800>; + clock-frequency = <1843200>; }; &ite_uart1_wrapper { @@ -162,7 +162,7 @@ pinctrl-names = "default"; }; -&kscan0 { +&kbd { status = "okay"; pinctrl-0 = <&ksi0_default &ksi1_default @@ -189,6 +189,12 @@ &kso14_default &kso15_default>; pinctrl-names = "default"; + row-size = <8>; + col-size = <16>; + + kscan_input: kscan-input { + compatible = "zephyr,kscan-input"; + }; }; &peci0 { diff --git a/boards/riscv/it82xx2_evb/it82xx2_evb.yaml b/boards/riscv/it82xx2_evb/it82xx2_evb.yaml index 45eb44557a4..b38957ccf4d 100644 --- a/boards/riscv/it82xx2_evb/it82xx2_evb.yaml +++ b/boards/riscv/it82xx2_evb/it82xx2_evb.yaml @@ -21,3 +21,4 @@ supported: - tach - uart - watchdog +vendor: ite diff --git a/boards/riscv/it8xxx2_evb/Kconfig.defconfig b/boards/riscv/it8xxx2_evb/Kconfig.defconfig index a207bafd0cc..8c198316bed 100644 --- a/boards/riscv/it8xxx2_evb/Kconfig.defconfig +++ b/boards/riscv/it8xxx2_evb/Kconfig.defconfig @@ -5,4 +5,17 @@ if BOARD_IT8XXX2_EVB config BOARD default "it8xxx2_evb" -endif + +if PM +config PM_DEVICE + default y + +choice PM_POLICY + default PM_POLICY_CUSTOM +endchoice +endif # PM + +config INPUT + default y if KSCAN + +endif # BOARD_IT8XXX2_EVB diff --git a/boards/riscv/it8xxx2_evb/it8xxx2_evb.dts b/boards/riscv/it8xxx2_evb/it8xxx2_evb.dts index 1b127e4bc0e..c111e9092aa 100644 --- a/boards/riscv/it8xxx2_evb/it8xxx2_evb.dts +++ b/boards/riscv/it8xxx2_evb/it8xxx2_evb.dts @@ -17,7 +17,7 @@ i2c-0 = &i2c0; peci-0 = &peci0; led0 = &led0; - kscan0 = &kscan0; + kscan0 = &kscan_input; watchdog0 = &twd0; pwm-0 = &pwm0; }; @@ -30,7 +30,7 @@ zephyr,flash = &flash0; zephyr,flash-controller = &flashctrl; zephyr,code-partition = &slot0_partition; - zephyr,keyboard-scan = &kscan0; + zephyr,keyboard-scan = &kscan_input; }; leds { @@ -99,12 +99,12 @@ &uart1 { status = "okay"; current-speed = <115200>; - clock-frequency = <1804800>; + clock-frequency = <1843200>; }; &uart2 { status = "okay"; current-speed = <460800>; - clock-frequency = <1804800>; + clock-frequency = <1843200>; }; &ite_uart1_wrapper { status = "okay"; @@ -146,7 +146,7 @@ pinctrl-0 = <&tach0a_gpd6_default>; pinctrl-names = "default"; }; -&kscan0 { +&kbd { status = "okay"; pinctrl-0 = <&ksi0_default &ksi1_default @@ -173,6 +173,12 @@ &kso14_default &kso15_default>; pinctrl-names = "default"; + row-size = <8>; + col-size = <16>; + + kscan_input: kscan-input { + compatible = "zephyr,kscan-input"; + }; }; &peci0 { status = "okay"; diff --git a/boards/riscv/it8xxx2_evb/it8xxx2_evb.yaml b/boards/riscv/it8xxx2_evb/it8xxx2_evb.yaml index 79824947db1..3374ea96c32 100644 --- a/boards/riscv/it8xxx2_evb/it8xxx2_evb.yaml +++ b/boards/riscv/it8xxx2_evb/it8xxx2_evb.yaml @@ -16,3 +16,4 @@ supported: - kscan - pwm - watchdog +vendor: ite diff --git a/boards/riscv/it8xxx2_evb/it8xxx2_evb_defconfig b/boards/riscv/it8xxx2_evb/it8xxx2_evb_defconfig index 9aa7deef842..21967527f8e 100644 --- a/boards/riscv/it8xxx2_evb/it8xxx2_evb_defconfig +++ b/boards/riscv/it8xxx2_evb/it8xxx2_evb_defconfig @@ -19,7 +19,3 @@ CONFIG_INIT_STACKS=y CONFIG_LINKER_ORPHAN_SECTION_PLACE=y CONFIG_COMPILER_OPT="-mcmodel=medlow" CONFIG_GPIO=y -# Power Management -CONFIG_PM=y -CONFIG_PM_DEVICE=y -CONFIG_PM_POLICY_CUSTOM=y diff --git a/boards/riscv/litex_vexriscv/litex_vexriscv.yaml b/boards/riscv/litex_vexriscv/litex_vexriscv.yaml index d3dbcec17d8..1c4a6ef664e 100644 --- a/boards/riscv/litex_vexriscv/litex_vexriscv.yaml +++ b/boards/riscv/litex_vexriscv/litex_vexriscv.yaml @@ -18,3 +18,4 @@ testing: ignore_tags: - bluetooth - xip +vendor: litex diff --git a/boards/riscv/longan_nano/doc/index.rst b/boards/riscv/longan_nano/doc/index.rst index dc4a204a9e7..b62d91c3130 100644 --- a/boards/riscv/longan_nano/doc/index.rst +++ b/boards/riscv/longan_nano/doc/index.rst @@ -71,6 +71,9 @@ The board configuration supports the following hardware features: * - DAC - :kconfig:option:`CONFIG_DAC` - :dtcompatible:`gd,gd32-dac` + * - ADC + - :kconfig:option:`CONFIG_ADC` + - :dtcompatible:`gd,gd32-adc` Serial Port =========== @@ -84,7 +87,7 @@ Programming and debugging Building & Flashing =================== -Here is an example for building the :ref:`blinky-sample` application. +Here is an example for building the :zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky @@ -105,7 +108,7 @@ Debugging ========= You can debug an application in the usual way. Here is an example for the -:ref:`blinky-sample` application. +:zephyr:code-sample:`blinky` application. .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky diff --git a/boards/riscv/longan_nano/longan_nano-common.dtsi b/boards/riscv/longan_nano/longan_nano-common.dtsi index 71f787b2df6..6d272ddd53d 100644 --- a/boards/riscv/longan_nano/longan_nano-common.dtsi +++ b/boards/riscv/longan_nano/longan_nano-common.dtsi @@ -165,6 +165,12 @@ }; }; +&adc0 { + status = "okay"; + pinctrl-0 = <&adc0_default>; + pinctrl-names = "default"; +}; + &fwdgt { status = "okay"; }; diff --git a/boards/riscv/longan_nano/longan_nano-pinctrl.dtsi b/boards/riscv/longan_nano/longan_nano-pinctrl.dtsi index 41dd3538534..93d8abc02bd 100644 --- a/boards/riscv/longan_nano/longan_nano-pinctrl.dtsi +++ b/boards/riscv/longan_nano/longan_nano-pinctrl.dtsi @@ -37,4 +37,11 @@ , ; }; }; + + adc0_default: adc0_default { + group1 { + pinmux = ; + }; + }; + }; diff --git a/boards/riscv/longan_nano/longan_nano.yaml b/boards/riscv/longan_nano/longan_nano.yaml index 3af7c9efa6f..bf89492aabc 100644 --- a/boards/riscv/longan_nano/longan_nano.yaml +++ b/boards/riscv/longan_nano/longan_nano.yaml @@ -11,3 +11,4 @@ supported: - watchdog - dma - spi +vendor: sipeed diff --git a/boards/riscv/longan_nano/longan_nano_lite.yaml b/boards/riscv/longan_nano/longan_nano_lite.yaml index 1ef7ddfb177..71cbb12c3f3 100644 --- a/boards/riscv/longan_nano/longan_nano_lite.yaml +++ b/boards/riscv/longan_nano/longan_nano_lite.yaml @@ -11,3 +11,4 @@ supported: - watchdog - dma - spi +vendor: sipeed diff --git a/boards/riscv/m2gl025_miv/m2gl025_miv.yaml b/boards/riscv/m2gl025_miv/m2gl025_miv.yaml index 283269bb32e..658ede0e9f5 100644 --- a/boards/riscv/m2gl025_miv/m2gl025_miv.yaml +++ b/boards/riscv/m2gl025_miv/m2gl025_miv.yaml @@ -12,3 +12,4 @@ testing: ignore_tags: - net - bluetooth +vendor: microchip diff --git a/boards/riscv/mpfs_icicle/mpfs_icicle.yaml b/boards/riscv/mpfs_icicle/mpfs_icicle.yaml index 0623d31795e..239d10e1ebc 100644 --- a/boards/riscv/mpfs_icicle/mpfs_icicle.yaml +++ b/boards/riscv/mpfs_icicle/mpfs_icicle.yaml @@ -9,3 +9,4 @@ testing: ignore_tags: - net - bluetooth +vendor: microchip diff --git a/boards/riscv/niosv_g/niosv_g.yaml b/boards/riscv/niosv_g/niosv_g.yaml index e88c658cd18..408b83df9eb 100644 --- a/boards/riscv/niosv_g/niosv_g.yaml +++ b/boards/riscv/niosv_g/niosv_g.yaml @@ -5,3 +5,4 @@ arch: riscv32 toolchain: - zephyr ram: 256 +vendor: intel diff --git a/boards/riscv/niosv_m/niosv_m.yaml b/boards/riscv/niosv_m/niosv_m.yaml index c1333752a68..fee0aa30a69 100644 --- a/boards/riscv/niosv_m/niosv_m.yaml +++ b/boards/riscv/niosv_m/niosv_m.yaml @@ -5,3 +5,4 @@ arch: riscv32 toolchain: - zephyr ram: 256 +vendor: intel diff --git a/boards/riscv/opentitan_earlgrey/opentitan_earlgrey.yaml b/boards/riscv/opentitan_earlgrey/opentitan_earlgrey.yaml index 0f01dc5748b..a66cb6d4384 100644 --- a/boards/riscv/opentitan_earlgrey/opentitan_earlgrey.yaml +++ b/boards/riscv/opentitan_earlgrey/opentitan_earlgrey.yaml @@ -11,3 +11,4 @@ testing: - bluetooth supported: - watchdog +vendor: lowrisc diff --git a/boards/riscv/qemu_riscv32/Kconfig.board b/boards/riscv/qemu_riscv32/Kconfig.board index 3277f94129a..989fa13b453 100644 --- a/boards/riscv/qemu_riscv32/Kconfig.board +++ b/boards/riscv/qemu_riscv32/Kconfig.board @@ -4,6 +4,7 @@ config BOARD_QEMU_RISCV32 bool "QEMU RISCV32 target" depends on SOC_RISCV_VIRT select QEMU_TARGET + select HAS_COVERAGE_SUPPORT select CPU_HAS_FPU select RISCV_ISA_RV32I select RISCV_ISA_EXT_ZICSR @@ -13,6 +14,7 @@ config BOARD_QEMU_RISCV32_SMP bool "QEMU RISCV32 SMP target" depends on SOC_RISCV_VIRT select QEMU_TARGET + select HAS_COVERAGE_SUPPORT select CPU_HAS_FPU select RISCV_ISA_RV32I select RISCV_ISA_EXT_ZICSR @@ -22,6 +24,7 @@ config BOARD_QEMU_RISCV32_XIP bool "QEMU RISCV32 XIP target" depends on SOC_RISCV_SIFIVE_FREEDOM select QEMU_TARGET + select HAS_COVERAGE_SUPPORT select CPU_HAS_FPU select RISCV_ISA_RV32I select RISCV_ISA_EXT_ZICSR diff --git a/boards/riscv/qemu_riscv32/doc/index.rst b/boards/riscv/qemu_riscv32/doc/index.rst index f300f8e6068..cf33745e198 100644 --- a/boards/riscv/qemu_riscv32/doc/index.rst +++ b/boards/riscv/qemu_riscv32/doc/index.rst @@ -20,7 +20,7 @@ Flashing While this board is emulated and you can't "flash" it, you can use this configuration to run basic Zephyr applications and kernel tests in the QEMU -emulated environment. For example, with the :ref:`synchronization_sample`: +emulated environment. For example, with the :zephyr:code-sample:`synchronization` sample: .. zephyr-app-commands:: :zephyr-app: samples/synchronization diff --git a/boards/riscv/qemu_riscv32e/Kconfig.board b/boards/riscv/qemu_riscv32e/Kconfig.board index 043be02bfbd..ace6a7322dd 100644 --- a/boards/riscv/qemu_riscv32e/Kconfig.board +++ b/boards/riscv/qemu_riscv32e/Kconfig.board @@ -5,6 +5,7 @@ config BOARD_QEMU_RISCV32E bool "QEMU RISCV32E target" depends on SOC_RISCV_VIRT select QEMU_TARGET + select HAS_COVERAGE_SUPPORT select RISCV_ISA_RV32E select RISCV_ISA_EXT_ZICSR select RISCV_ISA_EXT_ZIFENCEI diff --git a/boards/riscv/qemu_riscv32e/doc/index.rst b/boards/riscv/qemu_riscv32e/doc/index.rst index 465b7428f50..15981f00c8e 100644 --- a/boards/riscv/qemu_riscv32e/doc/index.rst +++ b/boards/riscv/qemu_riscv32e/doc/index.rst @@ -20,7 +20,7 @@ Flashing While this board is emulated and you can't "flash" it, you can use this configuration to run basic Zephyr applications and kernel tests in the QEMU -emulated environment. For example, with the :ref:`synchronization_sample`: +emulated environment. For example, with the :zephyr:code-sample:`synchronization` sample: .. zephyr-app-commands:: :zephyr-app: samples/synchronization diff --git a/boards/riscv/qemu_riscv64/Kconfig.board b/boards/riscv/qemu_riscv64/Kconfig.board index eb92cfef930..f75ba14b7a4 100644 --- a/boards/riscv/qemu_riscv64/Kconfig.board +++ b/boards/riscv/qemu_riscv64/Kconfig.board @@ -6,6 +6,7 @@ config BOARD_QEMU_RISCV64 depends on SOC_RISCV_VIRT select QEMU_TARGET select 64BIT + select HAS_COVERAGE_SUPPORT select CPU_HAS_FPU_DOUBLE_PRECISION select RISCV_ISA_RV64I select RISCV_ISA_EXT_ZICSR @@ -16,6 +17,7 @@ config BOARD_QEMU_RISCV64_SMP depends on SOC_RISCV_VIRT select QEMU_TARGET select 64BIT + select HAS_COVERAGE_SUPPORT select CPU_HAS_FPU_DOUBLE_PRECISION select RISCV_ISA_RV64I select RISCV_ISA_EXT_ZICSR diff --git a/boards/riscv/qemu_riscv64/doc/index.rst b/boards/riscv/qemu_riscv64/doc/index.rst index a0c55fa69a0..e58df91f679 100644 --- a/boards/riscv/qemu_riscv64/doc/index.rst +++ b/boards/riscv/qemu_riscv64/doc/index.rst @@ -29,7 +29,7 @@ Flashing While this board is emulated and you can't "flash" it, you can use this configuration to run basic Zephyr applications and kernel tests in the QEMU -emulated environment. For example, with the :ref:`synchronization_sample`: +emulated environment. For example, with the :zephyr:code-sample:`synchronization` sample: .. zephyr-app-commands:: :zephyr-app: samples/synchronization diff --git a/boards/riscv/qemu_riscv64/qemu_riscv64_smp_defconfig b/boards/riscv/qemu_riscv64/qemu_riscv64_smp_defconfig index df0a497cbfe..78b5b74de9a 100644 --- a/boards/riscv/qemu_riscv64/qemu_riscv64_smp_defconfig +++ b/boards/riscv/qemu_riscv64/qemu_riscv64_smp_defconfig @@ -15,3 +15,4 @@ CONFIG_QEMU_ICOUNT=n CONFIG_IDLE_STACK_SIZE=1024 CONFIG_RISCV_PMP=y +CONFIG_TICKET_SPINLOCKS=y diff --git a/boards/riscv/rv32m1_vega/doc/index.rst b/boards/riscv/rv32m1_vega/doc/index.rst index defd9177435..a2f3d107224 100644 --- a/boards/riscv/rv32m1_vega/doc/index.rst +++ b/boards/riscv/rv32m1_vega/doc/index.rst @@ -126,7 +126,7 @@ BLE Software Link Layer experimental support ================================================== This is an experimental feature supported on the Zephyr's RI5CY configuration, ``rv32m1_vega_ri5cy``. It uses the Software Link Layer -framework by Nordic Semi to enable the the on-SoC radio and transceiver for +framework by Nordic Semi to enable the on-SoC radio and transceiver for implementing a software defined BLE controller. By using both the controller and the host stack available in Zephyr, the following BLE samples can be used with this board: @@ -498,7 +498,7 @@ first make sure you're booting the right core. The output should look like this: - .. code-block:: none + .. code-block:: console $ ~/rv32m1-openocd -f boards/riscv/rv32m1_vega/support/openocd_rv32m1_vega_ri5cy.cfg Open On-Chip Debugger 0.10.0+dev-00431-ge1ec3c7d (2018-10-31-07:29) diff --git a/boards/riscv/rv32m1_vega/doc/ri5cy_boot.jpg b/boards/riscv/rv32m1_vega/doc/ri5cy_boot.jpg index 6483f98642f..f119572c517 100644 Binary files a/boards/riscv/rv32m1_vega/doc/ri5cy_boot.jpg and b/boards/riscv/rv32m1_vega/doc/ri5cy_boot.jpg differ diff --git a/boards/riscv/rv32m1_vega/rv32m1_vega_ri5cy.yaml b/boards/riscv/rv32m1_vega/rv32m1_vega_ri5cy.yaml index f350b82691f..334582e31c3 100644 --- a/boards/riscv/rv32m1_vega/rv32m1_vega_ri5cy.yaml +++ b/boards/riscv/rv32m1_vega/rv32m1_vega_ri5cy.yaml @@ -12,3 +12,4 @@ supported: - i2c - pwm - spi +vendor: openisa diff --git a/boards/riscv/rv32m1_vega/rv32m1_vega_zero_riscy.yaml b/boards/riscv/rv32m1_vega/rv32m1_vega_zero_riscy.yaml index cd64714625f..9afb8da41f6 100644 --- a/boards/riscv/rv32m1_vega/rv32m1_vega_zero_riscy.yaml +++ b/boards/riscv/rv32m1_vega/rv32m1_vega_zero_riscy.yaml @@ -10,3 +10,4 @@ supported: - arduino_i2c - i2c - pwm +vendor: openisa diff --git a/boards/riscv/sparkfun_red_v_things_plus/sparkfun_red_v_things_plus.yaml b/boards/riscv/sparkfun_red_v_things_plus/sparkfun_red_v_things_plus.yaml index 33b56514443..f25cf16f093 100644 --- a/boards/riscv/sparkfun_red_v_things_plus/sparkfun_red_v_things_plus.yaml +++ b/boards/riscv/sparkfun_red_v_things_plus/sparkfun_red_v_things_plus.yaml @@ -16,3 +16,4 @@ supported: - spi - pwm - watchdog +vendor: sparkfun diff --git a/boards/riscv/stamp_c3/doc/index.rst b/boards/riscv/stamp_c3/doc/index.rst index d47ac110fba..8da74e9e1d8 100644 --- a/boards/riscv/stamp_c3/doc/index.rst +++ b/boards/riscv/stamp_c3/doc/index.rst @@ -86,7 +86,7 @@ Sysbuild ======== The sysbuild makes possible to build and flash all necessary images needed to -bootstrap the board with the EPS32 SoC. +bootstrap the board with the ESP32 SoC. To build the sample application using sysbuild use the command: diff --git a/boards/riscv/stamp_c3/stamp_c3.yaml b/boards/riscv/stamp_c3/stamp_c3.yaml index b73d85c982b..9e43f10401d 100644 --- a/boards/riscv/stamp_c3/stamp_c3.yaml +++ b/boards/riscv/stamp_c3/stamp_c3.yaml @@ -14,3 +14,4 @@ testing: ignore_tags: - net - bluetooth +vendor: m5stack diff --git a/boards/riscv/titanium_ti60_f225/titanium_ti60_f225.yaml b/boards/riscv/titanium_ti60_f225/titanium_ti60_f225.yaml index b52f6d8660a..7ed90e8447e 100644 --- a/boards/riscv/titanium_ti60_f225/titanium_ti60_f225.yaml +++ b/boards/riscv/titanium_ti60_f225/titanium_ti60_f225.yaml @@ -8,3 +8,4 @@ ram: 196608 supported: - gpio - uart +vendor: efinix diff --git a/boards/riscv/tlsr9518adk80d/doc/index.rst b/boards/riscv/tlsr9518adk80d/doc/index.rst index 62c6b93cf3a..4bf62efdf78 100644 --- a/boards/riscv/tlsr9518adk80d/doc/index.rst +++ b/boards/riscv/tlsr9518adk80d/doc/index.rst @@ -7,7 +7,7 @@ Overview ******** The TLSR9518A Generic Starter Kit is a hardware platform which -can be used to verify the `Telink TLSR9 series chipset`_ and develop applications +can be used to verify the `Telink TLSR951x series chipset`_ and develop applications for several 2.4 GHz air interface standards including Bluetooth 5.2 (Basic data rate, Enhanced data rate, LE, Indoor positioning and BLE Mesh), Zigbee 3.0, Homekit, 6LoWPAN, Thread and 2.4 Ghz proprietary. @@ -151,7 +151,7 @@ Building .. important:: These instructions assume you've set up a development environment as - described in the `Zephyr Getting Started Guide`_. + described in the :ref:`getting_started`. To build applications using the default RISC-V toolchain from Zephyr SDK, just run the west build command. Here is an example for the "hello_world" application. @@ -259,10 +259,9 @@ References .. target-notes:: -.. _Telink TLSR9 series chipset: http://wiki.telink-semi.cn/wiki/chip-series/TLSR9-Series/ -.. _Telink B91 Generic Starter Kit Hardware Guide: http://wiki.telink-semi.cn/wiki/Hardware/B91_Generic_Starter_Kit_Hardware_Guide/ -.. _Telink RISC-V Linux Toolchain: http://wiki.telink-semi.cn/tools_and_sdk/Tools/IDE/telink_riscv_linux_toolchain.zip -.. _Burning and Debugging Tools for all Series: http://wiki.telink-semi.cn/wiki/IDE-and-Tools/Burning-and-Debugging-Tools-for-all-Series/ -.. _Burning and Debugging Tools for TLSR9 Series: http://wiki.telink-semi.cn/wiki/IDE-and-Tools/Burning-and-Debugging-Tools-for-TLSR9-Series/ -.. _Burning and Debugging Tools for TLSR9 Series in Linux: http://wiki.telink-semi.cn/wiki/IDE-and-Tools/BDT_for_TLSR9_Series_in_Linux/ -.. _Zephyr Getting Started Guide: https://docs.zephyrproject.org/latest/getting_started/index.html +.. _Telink TLSR951x series chipset: https://wiki.telink-semi.cn/wiki/chip-series/TLSR951x-Series/ +.. _Telink B91 Generic Starter Kit Hardware Guide: https://wiki.telink-semi.cn/wiki/Hardware/B91_Generic_Starter_Kit_Hardware_Guide/ +.. _Telink RISC-V Linux Toolchain: https://wiki.telink-semi.cn/tools_and_sdk/Tools/IDE/telink_riscv_linux_toolchain.zip +.. _Burning and Debugging Tools for all Series: https://wiki.telink-semi.cn/wiki/IDE-and-Tools/Burning-and-Debugging-Tools-for-all-Series/ +.. _Burning and Debugging Tools for TLSR9 Series: https://wiki.telink-semi.cn/wiki/IDE-and-Tools/Burning-and-Debugging-Tools-for-TLSR9-Series/ +.. _Burning and Debugging Tools for TLSR9 Series in Linux: https://wiki.telink-semi.cn/wiki/IDE-and-Tools/BDT_for_TLSR9_Series_in_Linux/ diff --git a/boards/riscv/tlsr9518adk80d/tlsr9518adk80d.yaml b/boards/riscv/tlsr9518adk80d/tlsr9518adk80d.yaml index dd2bd76f585..c1879da43e4 100644 --- a/boards/riscv/tlsr9518adk80d/tlsr9518adk80d.yaml +++ b/boards/riscv/tlsr9518adk80d/tlsr9518adk80d.yaml @@ -13,3 +13,4 @@ supported: - pwm - spi - netif:openthread +vendor: telink diff --git a/boards/riscv/xiao_esp32c3/doc/index.rst b/boards/riscv/xiao_esp32c3/doc/index.rst index 4afc3cad4bc..18c56c3ff9b 100644 --- a/boards/riscv/xiao_esp32c3/doc/index.rst +++ b/boards/riscv/xiao_esp32c3/doc/index.rst @@ -110,7 +110,7 @@ Sysbuild ======== The sysbuild makes possible to build and flash all necessary images needed to -bootstrap the board with the EPS32 SoC. +bootstrap the board with the ESP32 SoC. To build the sample application using sysbuild use the command: diff --git a/boards/riscv/xiao_esp32c3/xiao_esp32c3.yaml b/boards/riscv/xiao_esp32c3/xiao_esp32c3.yaml index 6a34ba08bc6..ce2a47ec982 100644 --- a/boards/riscv/xiao_esp32c3/xiao_esp32c3.yaml +++ b/boards/riscv/xiao_esp32c3/xiao_esp32c3.yaml @@ -15,3 +15,4 @@ testing: ignore_tags: - net - bluetooth +vendor: seeed diff --git a/boards/shields/atmel_rf2xx/doc/index.rst b/boards/shields/atmel_rf2xx/doc/index.rst index 31abe4c03f8..e9d2777fafe 100644 --- a/boards/shields/atmel_rf2xx/doc/index.rst +++ b/boards/shields/atmel_rf2xx/doc/index.rst @@ -179,7 +179,7 @@ Pins Assignment of the Arduino Shield Modules MikroBus Shields ================ -MikroBus header is available available without advanced features. It is +MikroBus header is available without advanced features. It is enabled selecting `atmel_rf2xx_mikrobus`_ variant option. Pins Assignment of the MikroBus Shield Modules @@ -283,8 +283,8 @@ and Echo client samples, which provide out-of-the-box configuration for both IEEE 802.15.4 and OpenThread. To enable IEEE 802.15.4 support in the samples, build them with ``overlay-802154.conf`` overlay config file. Same way, to enable OpenThread support, build them with ``overlay-ot.conf`` overlay -config file. See :ref:`sockets-echo-server-sample` and -:ref:`sockets-echo-client-sample` for details. +config file. See :zephyr:code-sample:`sockets-echo-server` and +:zephyr:code-sample:`sockets-echo-client` samples for details. Build and Programming ********************* diff --git a/boards/shields/ftdi_vm800c/doc/index.rst b/boards/shields/ftdi_vm800c/doc/index.rst index 720ffee5aa1..df72ff21111 100644 --- a/boards/shields/ftdi_vm800c/doc/index.rst +++ b/boards/shields/ftdi_vm800c/doc/index.rst @@ -70,7 +70,7 @@ Sample usage You can try use FT800 with the Zephyr FT800 sample, which provides out-of-the-box configuration for FT800 Embedded Video engine. -See :ref:`display-ft800-sample` for details. +See :zephyr:code-sample:`ft800` sample for details. Build and Programming ********************* diff --git a/boards/shields/g1120b0mipi/Kconfig.defconfig b/boards/shields/g1120b0mipi/Kconfig.defconfig index 807183c4742..64b784035e7 100644 --- a/boards/shields/g1120b0mipi/Kconfig.defconfig +++ b/boards/shields/g1120b0mipi/Kconfig.defconfig @@ -11,9 +11,17 @@ config INPUT config INPUT_FT5336_INTERRUPT default y +if MIPI_DSI_MCUX_2L +# Enable color swap in driver + +config MIPI_DSI_MCUX_2L_SWAP16 + default y + +endif # MIPI_DSI_MCUX_2L + # Swap 16 bit color setting for LVGL, to send high byte first config LV_COLOR_16_SWAP - default y + default y if !MIPI_DSI_MCUX_2L_SWAP16 config LV_Z_VDB_SIZE default 16 diff --git a/boards/shields/g1120b0mipi/boards/mimxrt595_evk_cm33.conf b/boards/shields/g1120b0mipi/boards/mimxrt595_evk_cm33.conf new file mode 100644 index 00000000000..ffe50a964ed --- /dev/null +++ b/boards/shields/g1120b0mipi/boards/mimxrt595_evk_cm33.conf @@ -0,0 +1,2 @@ +# Enable DMA, so that DSI MCUX will use SMARTDMA +CONFIG_DMA=y diff --git a/boards/shields/g1120b0mipi/boards/mimxrt595_evk_cm33.overlay b/boards/shields/g1120b0mipi/boards/mimxrt595_evk_cm33.overlay new file mode 100644 index 00000000000..7503627d99d --- /dev/null +++ b/boards/shields/g1120b0mipi/boards/mimxrt595_evk_cm33.overlay @@ -0,0 +1,15 @@ +/* + * Copyright 2023, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Change deep sleep config for suspend mode to keep SMARTDMA ram powered, + * so the SMARTDMA will continue functioning after deep sleep + */ +&suspend { + deep-sleep-config = <0xC800>, + <0x80030004>, + <0xFFFFFFFF>, + <0>; +}; diff --git a/boards/shields/g1120b0mipi/g1120b0mipi.overlay b/boards/shields/g1120b0mipi/g1120b0mipi.overlay index e456a7f31c7..7fec77ee3d7 100644 --- a/boards/shields/g1120b0mipi/g1120b0mipi.overlay +++ b/boards/shields/g1120b0mipi/g1120b0mipi.overlay @@ -33,7 +33,7 @@ compatible = "focaltech,ft5336"; reg = <0x38>; int-gpios = <&nxp_mipi_connector 29 GPIO_ACTIVE_LOW>; - reset-gpios = <&nxp_mipi_connector 28 GPIO_ACTIVE_HIGH>; + reset-gpios = <&nxp_mipi_connector 28 GPIO_ACTIVE_LOW>; }; }; diff --git a/boards/shields/inventek_eswifi/doc/index.rst b/boards/shields/inventek_eswifi/doc/index.rst index 699fd540190..e19713acd3f 100644 --- a/boards/shields/inventek_eswifi/doc/index.rst +++ b/boards/shields/inventek_eswifi/doc/index.rst @@ -140,7 +140,7 @@ Tested Boards Sample usage ************ -The reference sample for WIFI is :ref:`wifi_sample`. It allows you use WIFI +The reference sample for WIFI is :zephyr:code-sample:`wifi-shell`. It allows you to use WIFI shell to scan local Wireless networks. With the password you can pick, connect and send ping. diff --git a/boards/shields/m5stack_core2_ext/Kconfig.shield b/boards/shields/m5stack_core2_ext/Kconfig.shield new file mode 100644 index 00000000000..2710087cd1e --- /dev/null +++ b/boards/shields/m5stack_core2_ext/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright (c) 2023 Martin Kiepfer +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_M5STACK_CORE2_EXT + def_bool $(shields_list_contains,m5stack_core2_ext) diff --git a/boards/shields/m5stack_core2_ext/doc/img/m5stack_core2_ext.webp b/boards/shields/m5stack_core2_ext/doc/img/m5stack_core2_ext.webp new file mode 100644 index 00000000000..f0de7a3d5bf Binary files /dev/null and b/boards/shields/m5stack_core2_ext/doc/img/m5stack_core2_ext.webp differ diff --git a/boards/shields/m5stack_core2_ext/doc/index.rst b/boards/shields/m5stack_core2_ext/doc/index.rst new file mode 100644 index 00000000000..691ad98f4a2 --- /dev/null +++ b/boards/shields/m5stack_core2_ext/doc/index.rst @@ -0,0 +1,56 @@ +.. _m5stack_core2_ext: + +M5Stack-Core2 base shield +#################################### + +Overview +******** + +`M5Stack-Core2`_ comes with a base shield that is connected to the M5Stack +extension connector. It features an MPU6886 6-axis motion tracker (6DOF IMU) +and a SPM1423 microphone. + +.. figure:: img/m5stack_core2_ext.webp + :align: center + :alt: M5Stack-Core2-EXT + :width: 400 px + + M5Stack-Core2-Extension module + +.. note:: + The SPM1423 microphone functionality is not implemented yet. + +Pins Assignments +================ + ++----------------------+--------------+ +| Shield Connector Pin | Function | ++======================+==============+ +| 0 | GND | ++----------------------+--------------+ +| 11 | 3.3V | ++----------------------+--------------+ +| 16 | I2C - intSDA | ++----------------------+--------------+ +| 17 | I2C - intSCL | ++----------------------+--------------+ + +Programming +*********** + +Set ``-DSHIELD=m5stack_core2_ext`` when you invoke ``west build``. +For example: + +.. zephyr-app-commands:: + :zephyr-app: samples/sensor/mpu6050 + :board: m5stack_core2 + :shield: m5stack_core2_ext + :goals: build + +References +********** + +.. target-notes:: + +.. _M5Stack-Core2: + https://docs.m5stack.com/en/core/core2 diff --git a/boards/shields/m5stack_core2_ext/m5stack_core2_ext.overlay b/boards/shields/m5stack_core2_ext/m5stack_core2_ext.overlay new file mode 100644 index 00000000000..8403fd4da9e --- /dev/null +++ b/boards/shields/m5stack_core2_ext/m5stack_core2_ext.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 Martin Kiepfer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + accel0 = &mpu6886_m5stack_core2_ext; + }; +}; + +&m5stack_mbus_i2c0 { + status = "okay"; + + mpu6886_m5stack_core2_ext: mbus_mpu6886@68 { + status = "okay"; + compatible = "invensense,mpu6050"; + reg = <0x68>; + }; +}; diff --git a/boards/shields/mcp2515/adafruit_can_picowbell.overlay b/boards/shields/mcp2515/adafruit_can_picowbell.overlay index 861839de9c3..163d7958318 100644 --- a/boards/shields/mcp2515/adafruit_can_picowbell.overlay +++ b/boards/shields/mcp2515/adafruit_can_picowbell.overlay @@ -16,7 +16,6 @@ reg = <0x0>; osc-freq = <16000000>; bus-speed = <125000>; - sjw = <1>; sample-point = <875>; can-transceiver { diff --git a/boards/shields/mcp2515/dfrobot_can_bus_v2_0.overlay b/boards/shields/mcp2515/dfrobot_can_bus_v2_0.overlay index 04130f29410..397fac2ef70 100644 --- a/boards/shields/mcp2515/dfrobot_can_bus_v2_0.overlay +++ b/boards/shields/mcp2515/dfrobot_can_bus_v2_0.overlay @@ -16,7 +16,6 @@ reg = <0x0>; osc-freq = <16000000>; bus-speed = <125000>; - sjw = <1>; sample-point = <875>; can-transceiver { diff --git a/boards/shields/mcp2515/keyestudio_can_bus_ks0411.overlay b/boards/shields/mcp2515/keyestudio_can_bus_ks0411.overlay index 79d2365ca31..43089f65d84 100644 --- a/boards/shields/mcp2515/keyestudio_can_bus_ks0411.overlay +++ b/boards/shields/mcp2515/keyestudio_can_bus_ks0411.overlay @@ -16,7 +16,6 @@ reg = <0x0>; osc-freq = <16000000>; bus-speed = <125000>; - sjw = <1>; sample-point = <875>; can-transceiver { diff --git a/boards/shields/mikroe_accel13_click/Kconfig.shield b/boards/shields/mikroe_accel13_click/Kconfig.shield new file mode 100644 index 00000000000..335781b3b9b --- /dev/null +++ b/boards/shields/mikroe_accel13_click/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright (c) 2023 Mark Olsson +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_MIKROE_ACCEL13_CLICK + def_bool $(shields_list_contains,mikroe_accel13_click) diff --git a/boards/shields/mikroe_accel13_click/doc/accel-13-click.jpg b/boards/shields/mikroe_accel13_click/doc/accel-13-click.jpg new file mode 100644 index 00000000000..20c2bccb90d Binary files /dev/null and b/boards/shields/mikroe_accel13_click/doc/accel-13-click.jpg differ diff --git a/boards/shields/mikroe_accel13_click/doc/index.rst b/boards/shields/mikroe_accel13_click/doc/index.rst new file mode 100644 index 00000000000..24d6a69443a --- /dev/null +++ b/boards/shields/mikroe_accel13_click/doc/index.rst @@ -0,0 +1,56 @@ +.. _mikroe_accel13_click_shield: + +MikroElektronika ACCEL 13 Click +############################### + +Overview +******** + +The MikroElektronika ACCEL 13 Click carries the `IIS2DLPC`_ ultra-low +power triaxial accelerometer sensor in a `mikroBUS`_ |trade| form factor. + +The `IIS2DLPC`_ sensor supports both SPI and I2C bus protocols. Currently +only I2C is supported for this shield. + +.. figure:: accel-13-click.jpg + :align: center + :alt: MikroElektronika ACCEL 13 Click + + MikroElektronika ACCEL 13 Click (Credit: MikroElektronika) + +Requirements +************ + +This shield can only be used with a development board that provides a +configuration for mikroBUS connectors and defines a node alias for the mikroBUS +I2C interface (see :ref:`shields` for more details). + +For more information about interfacing the IIS2DLPC and the ACCEL 13 Click, +see the following documentation: + +- `IIS2DLPC Datasheet`_ +- `ACCEL 13 Click`_ + +Programming +*********** + +Set ``-DSHIELD=mikro_accel13_click`` when you invoke ``west build``. For +example: + +.. zephyr-app-commands:: + :zephyr-app: test/boards/board_shell + :board: lpcxpresso55s69 + :shield: mikroe_accel13_click + :goals: build + +.. _IIS2DLPC: + https://www.st.com/en/mems-and-sensors/iis2dlpc.html + +.. _mikroBUS: + https://www.mikroe.com/mikrobus + +.. _IIS2DLPC Datasheet: + https://www.st.com/resource/en/datasheet/iis2dlpc.pdf + +.. _ACCEL 13 Click: + https://www.mikroe.com/accel-13-click diff --git a/boards/shields/mikroe_accel13_click/mikroe_accel13_click.overlay b/boards/shields/mikroe_accel13_click/mikroe_accel13_click.overlay new file mode 100644 index 00000000000..e2979b384d3 --- /dev/null +++ b/boards/shields/mikroe_accel13_click/mikroe_accel13_click.overlay @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Mark Olsson + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + accel0 = &iis2dlpc_mikroe_accel13_click; + }; +}; + +&mikrobus_i2c { + status = "okay"; + + iis2dlpc_mikroe_accel13_click: iis2dlpc@18 { + compatible = "st,iis2dlpc"; + reg = <0x18>; + drdy-gpios = <&mikrobus_header 7 GPIO_ACTIVE_HIGH>; + drdy-int = <2>; + status = "okay"; + }; +}; diff --git a/boards/shields/mikroe_mcp2518fd_click/Kconfig.shield b/boards/shields/mikroe_mcp2518fd_click/Kconfig.shield new file mode 100644 index 00000000000..5db87f809c7 --- /dev/null +++ b/boards/shields/mikroe_mcp2518fd_click/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright (c) 2023 Andriy Gelman +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_MIKROE_MCP2518FD_CLICK + def_bool $(shields_list_contains,mikroe_mcp2518fd_click) diff --git a/boards/shields/mikroe_mcp2518fd_click/doc/index.rst b/boards/shields/mikroe_mcp2518fd_click/doc/index.rst new file mode 100644 index 00000000000..79ac2b441c3 --- /dev/null +++ b/boards/shields/mikroe_mcp2518fd_click/doc/index.rst @@ -0,0 +1,41 @@ +.. _mikroe_mcp2518fd_click_shield: + +MikroElektronika MCP2518FD Click shield +####################################### + +Overview +-------- + +MCP2518FD Click shield has a MCP2518FD CAN FD controller via a SPI +interface and a high-speed ATA6563 CAN transceiver. + +More information about the shield can be found at +`Mikroe MCP2518FD click`_. + +Requirements +************ + +The shield uses a mikroBUS interface. The target board must define +a `mikrobus_spi` and `mikrobus_header` node labels +(see :ref:`shields` for more details). The target board must also +support level triggered interrupts. + +Programming +*********** + +Set ``-DSHIELD=mikroe_mcp2518fd_click`` when you invoke ``west build``, +for example: + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/can/counter + :board: lpcxpresso55s28 + :shield: mikroe_mcp2518fd_click + :goals: build flash + +References +********** + +.. target-notes:: + +.. _Mikroe MCP2518FD click: + https://www.mikroe.com/mcp2518fd-click diff --git a/boards/shields/mikroe_mcp2518fd_click/mikroe_mcp2518fd_click.overlay b/boards/shields/mikroe_mcp2518fd_click/mikroe_mcp2518fd_click.overlay new file mode 100644 index 00000000000..afd647b760a --- /dev/null +++ b/boards/shields/mikroe_mcp2518fd_click/mikroe_mcp2518fd_click.overlay @@ -0,0 +1,24 @@ +&mikrobus_spi { + cs-gpios = <&mikrobus_header 2 GPIO_ACTIVE_LOW>; + + mcp2518fd_mikroe_mcp2518fd_click: mcp2518fd@0 { + compatible = "microchip,mcp251xfd"; + status = "okay"; + + spi-max-frequency = <18000000>; + int-gpios = <&mikrobus_header 7 GPIO_ACTIVE_LOW>; + reg = <0x0>; + osc-freq = <40000000>; + + bus-speed = <125000>; + sample-point = <875>; + bus-speed-data = <1000000>; + sample-point-data = <875>; + }; +}; + +/ { + chosen { + zephyr,canbus = &mcp2518fd_mikroe_mcp2518fd_click; + }; +}; diff --git a/boards/shields/rk055hdmipi4m/rk055hdmipi4m.overlay b/boards/shields/rk055hdmipi4m/rk055hdmipi4m.overlay index 079596b60d2..4740ee664f1 100644 --- a/boards/shields/rk055hdmipi4m/rk055hdmipi4m.overlay +++ b/boards/shields/rk055hdmipi4m/rk055hdmipi4m.overlay @@ -30,7 +30,7 @@ compatible = "goodix,gt911"; reg = <0x5d>; irq-gpios = <&nxp_mipi_connector 29 GPIO_ACTIVE_HIGH>; - reset-gpios = <&nxp_mipi_connector 28 GPIO_ACTIVE_HIGH>; + reset-gpios = <&nxp_mipi_connector 28 GPIO_ACTIVE_LOW>; }; }; diff --git a/boards/shields/rk055hdmipi4ma0/rk055hdmipi4ma0.overlay b/boards/shields/rk055hdmipi4ma0/rk055hdmipi4ma0.overlay index 29a90ee0b73..0f4e0c9ce45 100644 --- a/boards/shields/rk055hdmipi4ma0/rk055hdmipi4ma0.overlay +++ b/boards/shields/rk055hdmipi4ma0/rk055hdmipi4ma0.overlay @@ -30,7 +30,7 @@ compatible = "goodix,gt911"; reg = <0x5d>; irq-gpios = <&nxp_mipi_connector 29 GPIO_ACTIVE_HIGH>; - reset-gpios = <&nxp_mipi_connector 28 GPIO_ACTIVE_HIGH>; + reset-gpios = <&nxp_mipi_connector 28 GPIO_ACTIVE_LOW>; }; }; diff --git a/boards/shields/ssd1306/Kconfig.defconfig b/boards/shields/ssd1306/Kconfig.defconfig index 960247d2f1d..3fc5d5a7c05 100644 --- a/boards/shields/ssd1306/Kconfig.defconfig +++ b/boards/shields/ssd1306/Kconfig.defconfig @@ -5,10 +5,6 @@ if SHIELD_SSD1306_128X64 || SHIELD_SSD1306_128X64_SPI || SHIELD_SSD1306_128X32 | if DISPLAY -choice SSD1306_CONTROLLER_TYPE - default SSD1306_SH1106_COMPATIBLE if SHIELD_SH1106_128X64 -endchoice - if LVGL config LV_Z_VDB_SIZE diff --git a/boards/shields/ssd1306/sh1106_128x64.overlay b/boards/shields/ssd1306/sh1106_128x64.overlay index 354b818cbd8..a9e4e0768ad 100644 --- a/boards/shields/ssd1306/sh1106_128x64.overlay +++ b/boards/shields/ssd1306/sh1106_128x64.overlay @@ -14,7 +14,7 @@ status = "okay"; sh1106_sh1106_128x64: ssd1306@3c { - compatible = "solomon,ssd1306fb"; + compatible = "sinowealth,sh1106"; reg = <0x3c>; width = <128>; height = <64>; diff --git a/boards/shields/tcan4550evm/Kconfig.shield b/boards/shields/tcan4550evm/Kconfig.shield new file mode 100644 index 00000000000..f76fffe0bb5 --- /dev/null +++ b/boards/shields/tcan4550evm/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright (c) 2023 Vestas Wind Systems A/S +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_TCAN4550EVM + def_bool $(shields_list_contains,tcan4550evm) diff --git a/boards/shields/tcan4550evm/doc/index.rst b/boards/shields/tcan4550evm/doc/index.rst new file mode 100644 index 00000000000..73e167dcc49 --- /dev/null +++ b/boards/shields/tcan4550evm/doc/index.rst @@ -0,0 +1,68 @@ +.. _tcan4550evm_shield: + +Texas Instruments TCAN4550EVM +############################# + +Overview +******** + +The Texas Instruments `TCAN4550EVM`_ features a `TI TCAN4550-Q1`_ automotive system basis chip (SBC) +with integrated CAN FD controller & transceiver. + +.. figure:: tcan4550evm.jpg + :align: center + :alt: TCAN4550EVM + + TCAN4550EVM (Credit: Texas Instruments) + +Requirements +************ + +This shield can only be used with a board which provides a configuration for Arduino connectors and +defines node aliases for SPI and GPIO interfaces (see :ref:`shields` for more details). + +.. note:: + + This shield configuration limits the maximum SPI clock frequency to 2MHz although the + TCAN4550-Q1 supports up to 18MHz SPI clock frequency. This is done to accommodate the flywires + usually used for connecting the TCAN4550EVM to the board running Zephyr. + +Pin Assignments +=============== + ++-----------------------+---------------------------------------------+ +| Shield Connector Pin | Function | ++=======================+=============================================+ +| D6 | nWKRQ | ++-----------------------+---------------------------------------------+ +| D7 | WAKE_LV | ++-----------------------+---------------------------------------------+ +| D8 | RESET | ++-----------------------+---------------------------------------------+ +| D9 | nINT | ++-----------------------+---------------------------------------------+ +| D10 | nCS | ++-----------------------+---------------------------------------------+ +| D11 | SDI | ++-----------------------+---------------------------------------------+ +| D12 | SDO | ++-----------------------+---------------------------------------------+ +| D13 | SCLK | ++-----------------------+---------------------------------------------+ + +Programming +*********** + +Set ``-DSHIELD=tcan4550evm`` when you invoke ``west build``. For example: + +.. zephyr-app-commands:: + :zephyr-app: tests/drivers/can/api + :board: frdm_k64f + :shield: tcan4550evm + :goals: build + +.. _TCAN4550EVM: + https://www.ti.com/tool/TCAN4550EVM + +.. _TI TCAN4550-Q1: + https://www.ti.com/product/TCAN4550-Q1 diff --git a/boards/shields/tcan4550evm/doc/tcan4550evm.jpg b/boards/shields/tcan4550evm/doc/tcan4550evm.jpg new file mode 100644 index 00000000000..ba24e9c5d74 Binary files /dev/null and b/boards/shields/tcan4550evm/doc/tcan4550evm.jpg differ diff --git a/boards/shields/tcan4550evm/tcan4550evm.overlay b/boards/shields/tcan4550evm/tcan4550evm.overlay new file mode 100644 index 00000000000..61c62ef4c0c --- /dev/null +++ b/boards/shields/tcan4550evm/tcan4550evm.overlay @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 Vestas Wind Systems A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + chosen { + zephyr,canbus = &tcan4x5x_tcan4550evm; + }; +}; + +&arduino_spi { + status = "okay"; + cs-gpios = <&arduino_header 16 GPIO_ACTIVE_LOW>; /* D10 */ + + tcan4x5x_tcan4550evm: can@0 { + compatible = "ti,tcan4x5x"; + reg = <0>; + /* reduced spi-max-frequency to accommodate flywire connections */ + spi-max-frequency = <2000000>; + status = "okay"; + clock-frequency = <40000000>; + device-state-gpios = <&arduino_header 12 GPIO_ACTIVE_HIGH>; /* D6 */ + device-wake-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ + reset-gpios = <&arduino_header 14 GPIO_ACTIVE_HIGH>; /* D8 */ + int-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ + bosch,mram-cfg = <0x0 15 15 7 7 0 10 10>; + sample-point = <875>; + sample-point-data = <875>; + bus-speed = <125000>; + bus-speed-data = <1000000>; + status = "okay"; + + can-transceiver { + max-bitrate = <8000000>; + }; + }; +}; diff --git a/boards/shields/x_nucleo_53l0a1/doc/index.rst b/boards/shields/x_nucleo_53l0a1/doc/index.rst index 60f780ac43d..75f1a76dbcc 100644 --- a/boards/shields/x_nucleo_53l0a1/doc/index.rst +++ b/boards/shields/x_nucleo_53l0a1/doc/index.rst @@ -61,7 +61,7 @@ Samples The sample :ref:`vl53l0x` demonstrates how to use the ranging sensor VL53L0X using the center sensor only. -The sample :ref:`x-nucleo-53l0a1-sample` demonstrates how to use the three +The sample :zephyr:code-sample:`x-nucleo-53l0a1` sample demonstrates how to use the three sensors (soldered + 2 satellites) and the 7 segments display. Programming diff --git a/boards/shields/x_nucleo_eeprma2/doc/index.rst b/boards/shields/x_nucleo_eeprma2/doc/index.rst index ea5a330b514..248260b3657 100644 --- a/boards/shields/x_nucleo_eeprma2/doc/index.rst +++ b/boards/shields/x_nucleo_eeprma2/doc/index.rst @@ -50,7 +50,7 @@ and the X-NUCLEO-EEPRMA2 in particular, see these ST Microelectronics documents: Samples ******* -The :ref:`samples_eeprom` can be used to demonstrate the expansion boards +The :zephyr:code-sample:`eeprom` sample can be used to demonstrate the expansion boards functionality. Per default the shield sets an ``eeprom-0`` alias for the M24C02-FMC6TG EEPROM, which can be overwritten to use the other EEPROM devices instead. diff --git a/boards/shields/x_nucleo_idb05a1/doc/index.rst b/boards/shields/x_nucleo_idb05a1/doc/index.rst index 11ae6a7213a..d2c6f006f77 100644 --- a/boards/shields/x_nucleo_idb05a1/doc/index.rst +++ b/boards/shields/x_nucleo_idb05a1/doc/index.rst @@ -85,7 +85,7 @@ build command: Alternatively, set use of this shield in the project's ``CMakeLists.txt`` file: -.. code-block:: none +.. code-block:: cmake set(SHIELD x_nucleo_idb05a1) @@ -95,7 +95,7 @@ References .. target-notes:: .. _X-NUCLEO-IDB05A1 website: - http://www.st.com/en/ecosystems/x-nucleo-idb05a1.html + https://www.st.com/en/ecosystems/x-nucleo-idb05a1.html .. _X-NUCLEO-IDB05A1 databrief: https://www.st.com/resource/en/data_brief/x-nucleo-idb05a1.pdf diff --git a/boards/shields/x_nucleo_idb05a1/x_nucleo_idb05a1.overlay b/boards/shields/x_nucleo_idb05a1/x_nucleo_idb05a1.overlay index a6a789c53c1..8ccf3d7dbf0 100644 --- a/boards/shields/x_nucleo_idb05a1/x_nucleo_idb05a1.overlay +++ b/boards/shields/x_nucleo_idb05a1/x_nucleo_idb05a1.overlay @@ -14,5 +14,6 @@ irq-gpios = <&arduino_header 0 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; /* A0 */ spi-max-frequency = <2000000>; controller-data-delay-us = <0>; /* No need for extra delay for BlueNRG-MS */ + spi-hold-cs; }; }; diff --git a/boards/shields/x_nucleo_iks01a1/doc/index.rst b/boards/shields/x_nucleo_iks01a1/doc/index.rst index 5674ee69e7a..329471e89f1 100644 --- a/boards/shields/x_nucleo_iks01a1/doc/index.rst +++ b/boards/shields/x_nucleo_iks01a1/doc/index.rst @@ -45,7 +45,7 @@ Programming *********** An example on how to use the ``x-nucleo-iks01a1`` shield is available -in the :ref:`x-nucleo-iks01a1-sample` application documentation +in the :zephyr:code-sample:`x-nucleo-iks01a1` sample application documentation (see :ref:`shields` for more details). References @@ -54,7 +54,7 @@ References .. target-notes:: .. _X-NUCLEO-IKS01A1 website: - http://www.st.com/en/ecosystems/x-nucleo-iks01a1.html + https://www.st.com/en/ecosystems/x-nucleo-iks01a1.html .. _X-NUCLEO-IKS01A1 data sheet: - http://www.st.com/resource/en/datasheet/x-nucleo-iks01a1.pdf + https://www.st.com/resource/en/datasheet/x-nucleo-iks01a1.pdf diff --git a/boards/shields/x_nucleo_iks01a2/doc/index.rst b/boards/shields/x_nucleo_iks01a2/doc/index.rst index 7cd19653b43..9fa9d253520 100644 --- a/boards/shields/x_nucleo_iks01a2/doc/index.rst +++ b/boards/shields/x_nucleo_iks01a2/doc/index.rst @@ -85,9 +85,9 @@ Programming Two samples are provided as examples for ``x-nucleo-iks01a2`` shield: -- :ref:`x-nucleo-iks01a2-std-sample` application, to be used when the shield is configured +- :zephyr:code-sample:`x-nucleo-iks01a2-std` sample application, to be used when the shield is configured in Standard Mode -- :ref:`x-nucleo-iks01a2-shub-sample` application, to be used when the shield is configured +- :zephyr:code-sample:`x-nucleo-iks01a2-shub` sample application, to be used when the shield is configured in SensorHub Mode See also :ref:`shields` for more details. @@ -98,7 +98,7 @@ References .. target-notes:: .. _X-NUCLEO-IKS01A2 website: - http://www.st.com/en/ecosystems/x-nucleo-iks01a2.html + https://www.st.com/en/ecosystems/x-nucleo-iks01a2.html .. _X-NUCLEO-IKS01A2 databrief: - http://www.st.com/resource/en/data_brief/x-nucleo-iks01a2.pdf + https://www.st.com/resource/en/data_brief/x-nucleo-iks01a2.pdf diff --git a/boards/shields/x_nucleo_iks01a3/doc/index.rst b/boards/shields/x_nucleo_iks01a3/doc/index.rst index c18647cfb7f..8da7bec906d 100644 --- a/boards/shields/x_nucleo_iks01a3/doc/index.rst +++ b/boards/shields/x_nucleo_iks01a3/doc/index.rst @@ -82,9 +82,9 @@ Programming Two samples are provided as examples for ``x-nucleo-iks01a3`` shield: -- :ref:`x-nucleo-iks01a3-std-sample` application, to be used when the shield is configured +- :zephyr:code-sample:`x-nucleo-iks01a3-std` sample application, to be used when the shield is configured in Standard Mode -- :ref:`x-nucleo-iks01a3-shub-sample` application, to be used when the shield is configured +- :zephyr:code-sample:`x-nucleo-iks01a3-shub` sample application, to be used when the shield is configured in SensorHub Mode See also :ref:`shields` for more details. @@ -95,7 +95,7 @@ References .. target-notes:: .. _X-NUCLEO-IKS01A3 website: - http://www.st.com/en/ecosystems/x-nucleo-iks01a3.html + https://www.st.com/en/ecosystems/x-nucleo-iks01a3.html .. _X-NUCLEO-IKS01A3 user manual: https://www.st.com/resource/en/user_manual/dm00601501.pdf diff --git a/boards/shields/x_nucleo_iks02a1/doc/index.rst b/boards/shields/x_nucleo_iks02a1/doc/index.rst index 2dab5a453f0..9dd1fc716b0 100644 --- a/boards/shields/x_nucleo_iks02a1/doc/index.rst +++ b/boards/shields/x_nucleo_iks02a1/doc/index.rst @@ -82,11 +82,11 @@ Programming Three samples are provided as examples for ``x-nucleo-iks02a1`` shield: -- :ref:`x-nucleo-iks02a1-std-sample` application, to be used when the shield is configured +- :zephyr:code-sample:`x-nucleo-iks02a1-std` application, to be used when the shield is configured in Standard Mode -- :ref:`x-nucleo-iks02a1-shub-sample` application, to be used when the shield is configured +- :zephyr:code-sample:`x-nucleo-iks02a1-shub` application, to be used when the shield is configured in SensorHub Mode -- :ref:`x-nucleo-iks02a1-mic-sample` application, to be used to acquire data through the +- :zephyr:code-sample:`x-nucleo-iks02a1-mic` application, to be used to acquire data through the on-board PDM microphone See also :ref:`shields` for more details. @@ -97,7 +97,7 @@ References .. target-notes:: .. _X-NUCLEO-IKS02A1 website: - http://www.st.com/en/ecosystems/x-nucleo-iks02a1.html + https://www.st.com/en/ecosystems/x-nucleo-iks02a1.html .. _X-NUCLEO-IKS02A1 user manual: https://www.st.com/resource/en/user_manual/DM00651686.pdf diff --git a/boards/sparc/generic_leon3/generic_leon3.yaml b/boards/sparc/generic_leon3/generic_leon3.yaml index a59d7b93854..3aecda82e0e 100644 --- a/boards/sparc/generic_leon3/generic_leon3.yaml +++ b/boards/sparc/generic_leon3/generic_leon3.yaml @@ -2,7 +2,7 @@ identifier: generic_leon3 name: Generic LEON3 system type: mcu simulation: tsim -simulation_exec: tsim +simulation_exec: tsim-leon3 arch: sparc ram: 4096 flash: 2048 @@ -11,3 +11,8 @@ toolchain: - xtools supported: - netif +testing: + ignore_tags: + - net + - bluetooth +vendor: gaisler diff --git a/boards/sparc/gr716a_mini/gr716a_mini.yaml b/boards/sparc/gr716a_mini/gr716a_mini.yaml index c8ddfc1720e..4107097aab5 100644 --- a/boards/sparc/gr716a_mini/gr716a_mini.yaml +++ b/boards/sparc/gr716a_mini/gr716a_mini.yaml @@ -2,10 +2,15 @@ identifier: gr716a_mini name: GR716-MINI Development Board type: mcu simulation: tsim -simulation_exec: tsim +simulation_exec: tsim-leon3 arch: sparc toolchain: - zephyr - xtools supported: - netif +testing: + ignore_tags: + - net + - bluetooth +vendor: gaisler diff --git a/boards/sparc/qemu_leon3/doc/index.rst b/boards/sparc/qemu_leon3/doc/index.rst index 156829d3728..4e0599697fd 100644 --- a/boards/sparc/qemu_leon3/doc/index.rst +++ b/boards/sparc/qemu_leon3/doc/index.rst @@ -20,7 +20,7 @@ Flashing While this board is emulated and you can't "flash" it, you can use this configuration to run basic Zephyr applications and kernel tests in the QEMU -emulated environment. For example, with the :ref:`synchronization_sample`: +emulated environment. For example, with the :zephyr:code-sample:`synchronization` sample: .. zephyr-app-commands:: :zephyr-app: samples/synchronization diff --git a/boards/x86/acrn/Kconfig.defconfig b/boards/x86/acrn/Kconfig.defconfig index af0a294d422..0216875583c 100644 --- a/boards/x86/acrn/Kconfig.defconfig +++ b/boards/x86/acrn/Kconfig.defconfig @@ -10,4 +10,8 @@ config BOARD config MP_MAX_NUM_CPUS default 2 +config HEAP_MEM_POOL_SIZE + default 32768 if ACPI + depends on KERNEL_MEM_POOL + endif diff --git a/boards/x86/acrn/doc/index.rst b/boards/x86/acrn/doc/index.rst index bd22b8b5e60..2bdaa96a817 100644 --- a/boards/x86/acrn/doc/index.rst +++ b/boards/x86/acrn/doc/index.rst @@ -125,7 +125,7 @@ Configure Zephyr CPUs Now you need to configure the CPU environment ACRN presents to the guest. By default Zephyr builds in SMP mode, but ACRN's default configuration gives it only one CPU. Find the value of -``CONFIG_MP_NUM_CPUS`` in the Zephyr .config file give the guest that +``CONFIG_MP_MAX_NUM_CPUS`` in the Zephyr .config file give the guest that many CPUs in the ```` tag. For example: .. code-block:: xml diff --git a/boards/x86/common/efi_boot.rst b/boards/x86/common/efi_boot.rst index 140de965bf5..54a08386d5d 100644 --- a/boards/x86/common/efi_boot.rst +++ b/boards/x86/common/efi_boot.rst @@ -1,3 +1,7 @@ +:orphan: + +.. start_include_here + Preparing the Boot Device ------------------------- diff --git a/boards/x86/common/net_boot.rst b/boards/x86/common/net_boot.rst index 98543b00037..e00dea8312c 100644 --- a/boards/x86/common/net_boot.rst +++ b/boards/x86/common/net_boot.rst @@ -1,3 +1,7 @@ +:orphan: + +.. start_include_here + Prepare Linux host ------------------ @@ -65,7 +69,7 @@ Booting the board .. note:: Use a baud rate of 115200. -#. Power on the the board. +#. Power on the board. #. Verify that the board got an IP address. Run from the Linux host: diff --git a/boards/x86/index.rst b/boards/x86/index.rst index 07afe762193..f7321566591 100644 --- a/boards/x86/index.rst +++ b/boards/x86/index.rst @@ -7,4 +7,4 @@ x86 Boards :maxdepth: 1 :glob: - **/* + [!common]*/**/* diff --git a/boards/x86/intel_adl/CMakeLists.txt b/boards/x86/intel_adl/CMakeLists.txt index 118b256013a..2dc5afcc323 100644 --- a/boards/x86/intel_adl/CMakeLists.txt +++ b/boards/x86/intel_adl/CMakeLists.txt @@ -1,5 +1,5 @@ # Create an EFI image -if((CONFIG_BOARD_INTEL_ADL_CRB OR CONFIG_BOARD_INTEL_ADL_RVP) AND CONFIG_BUILD_OUTPUT_EFI) +if(CONFIG_BUILD_OUTPUT_EFI) set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/arch/x86/zefi/zefi.py -c ${CMAKE_C_COMPILER} diff --git a/boards/x86/intel_adl/Kconfig.board b/boards/x86/intel_adl/Kconfig.board index 997b5a30504..591da3261f2 100644 --- a/boards/x86/intel_adl/Kconfig.board +++ b/boards/x86/intel_adl/Kconfig.board @@ -12,3 +12,9 @@ config BOARD_INTEL_ADL_RVP depends on SOC_ALDER_LAKE select X86_64 select HAS_COVERAGE_SUPPORT + +config BOARD_UP_SQUARED_PRO_7000 + bool "UP SQUARED PRO 7000 board" + depends on SOC_ALDER_LAKE + select X86_64 + select HAS_COVERAGE_SUPPORT diff --git a/boards/x86/intel_adl/Kconfig.defconfig b/boards/x86/intel_adl/Kconfig.defconfig index 0bc114e4693..cc9e3882ec4 100644 --- a/boards/x86/intel_adl/Kconfig.defconfig +++ b/boards/x86/intel_adl/Kconfig.defconfig @@ -1,11 +1,12 @@ # Copyright (c) 2023 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -if BOARD_INTEL_ADL_CRB || BOARD_INTEL_ADL_RVP +if BOARD_INTEL_ADL_CRB || BOARD_INTEL_ADL_RVP || BOARD_UP_SQUARED_PRO_7000 config BOARD default "intel_adl_crb" if BOARD_INTEL_ADL_CRB default "intel_adl_rvp" if BOARD_INTEL_ADL_RVP + default "up_squared_pro_7000" if BOARD_UP_SQUARED_PRO_7000 config BUILD_OUTPUT_STRIPPED default y @@ -36,6 +37,8 @@ config HEAP_MEM_POOL_SIZE default 64000000 config MAIN_STACK_SIZE default 320000 +config ACPI_PRT_BUS_NAME + default "_SB.PC00" if SHELL config SHELL_STACK_SIZE @@ -43,11 +46,4 @@ config SHELL_STACK_SIZE endif # SHELL endif # ACPI -endif # BOARD_INTEL_ADL_CRB || BOARD_INTEL_ADL_RVP - -if BOARD_INTEL_ADL_RVP - -config UART_NS16550_ACCESS_IOPORT - default y if UART_NS16550 - -endif # BOARD_INTEL_ADL_RVP +endif # BOARD_INTEL_ADL_CRB || BOARD_INTEL_ADL_RVP || BOARD_UP_SQUARED_PRO_7000 diff --git a/boards/x86/intel_adl/doc/index.rst b/boards/x86/intel_adl/doc/index.rst index f009c1c2268..63a518248b8 100644 --- a/boards/x86/intel_adl/doc/index.rst +++ b/boards/x86/intel_adl/doc/index.rst @@ -60,5 +60,6 @@ Booting the Alder Lake N CRB Board using UEFI ============================================= .. include:: ../../common/efi_boot.rst + :start-after: start_include_here .. _INTEL_ADL: https://edc.intel.com/content/www/us/en/design/products/platforms/processor-and-core-i3-n-series-datasheet-volume-1-of-2/ diff --git a/boards/x86/intel_adl/doc/up_squared_pro_7000.rst b/boards/x86/intel_adl/doc/up_squared_pro_7000.rst new file mode 100644 index 00000000000..762340e1049 --- /dev/null +++ b/boards/x86/intel_adl/doc/up_squared_pro_7000.rst @@ -0,0 +1,85 @@ +:orphan: + +.. _up_squared_pro_7000_board: + +UP Squared Pro 7000 +################### + +Overview +******** + +UP Squared Pro 7000 is the 3rd generation of palm-sized developer board of +UP Boards series. UP Squared Pro 7000 is powered by Intel Alder Lake N +(Intel N-series Platform). + +For more information about Intel N-series Platform please refer to +:ref:`intel_adl_n`. + +This board configuration enables kernel support for the UP Squared Pro 7000 boards. + +Hardware +******** + +General information about the board can be found at the `UP Squared Pro 7000`_ website. + +Connections and IOs +=================== + +Refer to the `UP Squared Pro 7000`_ website for more information. + +Programming and Debugging +************************* + +Use the following procedures for booting an image for an UP Squared Pro 7000 board. + +.. contents:: + :depth: 1 + :local: + :backlinks: top + +Build Zephyr application +======================== + +#. Build a Zephyr application; for instance, to build the ``hello_world`` + application for UP Squared Pro 7000 board: + + .. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: up_squared_pro_7000 + :goals: build + + .. note:: + + A Zephyr EFI image file named :file:`zephyr.efi` is automatically + created in the build directory after the application is built. + +Connect Serial Console +====================== + +Current board configuration assumes that serial console is connected to +connector ``CN14 USB 2.0/UART 1x10P Wafer``. Refer to `User Manual`_ for +description of the connector and location on the board. + +Refer to `UP Serial Console`_ for additional information about serial +connection setup. + +Booting the UP Squared Pro 7000 Board using UEFI +================================================ + +.. include:: ../../common/efi_boot.rst + :start-after: start_include_here + +Booting the UP Squared Pro 7000 Board over network +================================================== + +.. include:: ../../common/net_boot.rst + :start-after: start_include_here + +References +********** + +.. target-notes:: + +.. _UP Squared Pro 7000: https://up-board.org/up-squared-pro-7000/ +.. _User Manual: https://downloads.up-community.org/download/up-squared-pro-7000-user-manual/ +.. _UP Serial Console: https://github.com/up-board/up-community/wiki/Serial-Console diff --git a/boards/x86/intel_adl/intel_adl.dts b/boards/x86/intel_adl/intel_adl.dts index 55dace6427c..16dfb20a556 100644 --- a/boards/x86/intel_adl/intel_adl.dts +++ b/boards/x86/intel_adl/intel_adl.dts @@ -13,14 +13,12 @@ #include / { - model = "Alder Lake"; - compatible = "intel,alder_lake"; - chosen { zephyr,sram = &dram0; }; aliases { watchdog0 = &tco_wdt; + sdhc0 = &emmc; }; }; diff --git a/boards/x86/intel_adl/intel_adl_crb.dts b/boards/x86/intel_adl/intel_adl_crb.dts index 65d6b9cef99..7a5f8b9d6e0 100644 --- a/boards/x86/intel_adl/intel_adl_crb.dts +++ b/boards/x86/intel_adl/intel_adl_crb.dts @@ -7,6 +7,9 @@ #include "intel_adl.dts" / { + model = "Intel Alder Lake CRB"; + compatible = "intel,alder-lake-crb"; + chosen { zephyr,console = &uart0; zephyr,shell-uart = &uart0; diff --git a/boards/x86/intel_adl/intel_adl_crb.yaml b/boards/x86/intel_adl/intel_adl_crb.yaml index d567fee4242..b393059d427 100644 --- a/boards/x86/intel_adl/intel_adl_crb.yaml +++ b/boards/x86/intel_adl/intel_adl_crb.yaml @@ -6,14 +6,17 @@ toolchain: - zephyr ram: 2048 supported: + - acpi - watchdog - pwm - gpio - rtc - i2c - spi + - smp testing: timeout_multiplier: 4 ignore_tags: - net - bluetooth +vendor: intel diff --git a/boards/x86/intel_adl/intel_adl_rvp.dts b/boards/x86/intel_adl/intel_adl_rvp.dts index eb74a98a70f..dd946c247c4 100644 --- a/boards/x86/intel_adl/intel_adl_rvp.dts +++ b/boards/x86/intel_adl/intel_adl_rvp.dts @@ -7,6 +7,9 @@ #include "intel_adl.dts" / { + model = "Intel Alder Lake RVP"; + compatible = "intel,alder-lake-rvp"; + chosen { zephyr,console = &uart0_legacy; zephyr,shell-uart = &uart0_legacy; diff --git a/boards/x86/intel_adl/intel_adl_rvp.yaml b/boards/x86/intel_adl/intel_adl_rvp.yaml index 7c5e2c62578..8a09b3fe16e 100644 --- a/boards/x86/intel_adl/intel_adl_rvp.yaml +++ b/boards/x86/intel_adl/intel_adl_rvp.yaml @@ -6,9 +6,12 @@ toolchain: - zephyr ram: 2048 supported: + - acpi + - smp - watchdog testing: timeout_multiplier: 4 ignore_tags: - net - bluetooth +vendor: intel diff --git a/boards/x86/intel_adl/up_squared_pro_7000.dts b/boards/x86/intel_adl/up_squared_pro_7000.dts new file mode 100644 index 00000000000..06d6f8e2330 --- /dev/null +++ b/boards/x86/intel_adl/up_squared_pro_7000.dts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "intel_adl.dts" + +/ { + model = "UP Squared Pro 7000 board"; + compatible = "aaeon,up_squared_pro_7000"; + + chosen { + zephyr,console = &uart1; + zephyr,shell-uart = &uart1; + }; +}; + +&uart1 { + status = "okay"; +}; diff --git a/boards/x86/intel_adl/up_squared_pro_7000.yaml b/boards/x86/intel_adl/up_squared_pro_7000.yaml new file mode 100644 index 00000000000..e1673112309 --- /dev/null +++ b/boards/x86/intel_adl/up_squared_pro_7000.yaml @@ -0,0 +1,17 @@ +identifier: up_squared_pro_7000 +name: UP SQUARED PRO 7000 board +type: mcu +arch: x86 +toolchain: + - zephyr +ram: 2048 +supported: + - acpi + - smp + - watchdog +testing: + timeout_multiplier: 4 + ignore_tags: + - net + - bluetooth +vendor: UP diff --git a/boards/x86/intel_adl/up_squared_pro_7000_defconfig b/boards/x86/intel_adl/up_squared_pro_7000_defconfig new file mode 100644 index 00000000000..211ce9f24e1 --- /dev/null +++ b/boards/x86/intel_adl/up_squared_pro_7000_defconfig @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_ALDER_LAKE=y +CONFIG_BOARD_UP_SQUARED_PRO_7000=y +CONFIG_PIC_DISABLE=y +CONFIG_LOAPIC=y +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_NS16550=y +CONFIG_UART_CONSOLE=y +CONFIG_X2APIC=y +CONFIG_SMP=y +CONFIG_BUILD_OUTPUT_EFI=y +CONFIG_BUILD_NO_GAP_FILL=y +CONFIG_UART_NS16550_PARENT_INIT_LEVEL=y diff --git a/boards/x86/intel_ehl/CMakeLists.txt b/boards/x86/intel_ehl/CMakeLists.txt index 11a5e70608a..2dc5afcc323 100644 --- a/boards/x86/intel_ehl/CMakeLists.txt +++ b/boards/x86/intel_ehl/CMakeLists.txt @@ -1,5 +1,5 @@ # Create an EFI image -if(CONFIG_BOARD_INTEL_EHL_CRB AND CONFIG_BUILD_OUTPUT_EFI) +if(CONFIG_BUILD_OUTPUT_EFI) set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/arch/x86/zefi/zefi.py -c ${CMAKE_C_COMPILER} diff --git a/boards/x86/intel_ehl/Kconfig.defconfig b/boards/x86/intel_ehl/Kconfig.defconfig index d2745ed436e..7d6667a6cec 100644 --- a/boards/x86/intel_ehl/Kconfig.defconfig +++ b/boards/x86/intel_ehl/Kconfig.defconfig @@ -19,6 +19,14 @@ config SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN default n endif +config ACPI_PRT_BUS_NAME + depends on ACPI + default "_SB.PC00" + +config HEAP_MEM_POOL_SIZE + default 2097152 if ACPI + depends on KERNEL_MEM_POOL + # TSC on this board is 1.9 GHz, HPET and APIC are 19.2 MHz config SYS_CLOCK_HW_CYCLES_PER_SEC default 1900000000 if APIC_TSC_DEADLINE_TIMER diff --git a/boards/x86/intel_ehl/doc/index.rst b/boards/x86/intel_ehl/doc/index.rst index 76661961c97..1aa8f530155 100644 --- a/boards/x86/intel_ehl/doc/index.rst +++ b/boards/x86/intel_ehl/doc/index.rst @@ -56,11 +56,13 @@ Booting the Elkhart Lake CRB Board using UEFI ============================================= .. include:: ../../common/efi_boot.rst + :start-after: start_include_here Booting the Elkhart Lake CRB Board over network =============================================== .. include:: ../../common/net_boot.rst + :start-after: start_include_here .. note:: To enable PXE boot for Elkhart Lake CRB board do the following: diff --git a/boards/x86/intel_ehl/intel_ehl_crb.yaml b/boards/x86/intel_ehl/intel_ehl_crb.yaml index 6b1d11e1a52..04cf5e2702e 100644 --- a/boards/x86/intel_ehl/intel_ehl_crb.yaml +++ b/boards/x86/intel_ehl/intel_ehl_crb.yaml @@ -7,11 +7,14 @@ toolchain: - llvm ram: 2048 supported: + - acpi - gpio - smbus + - smp - rtc - watchdog testing: ignore_tags: - net - bluetooth +vendor: intel diff --git a/boards/x86/intel_ehl/intel_ehl_crb_defconfig b/boards/x86/intel_ehl/intel_ehl_crb_defconfig index 7b4bfc6f9b7..e25760a5a05 100644 --- a/boards/x86/intel_ehl/intel_ehl_crb_defconfig +++ b/boards/x86/intel_ehl/intel_ehl_crb_defconfig @@ -11,3 +11,4 @@ CONFIG_X2APIC=y CONFIG_SMP=y CONFIG_BUILD_OUTPUT_EFI=y CONFIG_BUILD_NO_GAP_FILL=y +CONFIG_PCIE_PRT=n diff --git a/boards/x86/intel_ehl/intel_ehl_crb_sbl.yaml b/boards/x86/intel_ehl/intel_ehl_crb_sbl.yaml index 734aac58fe8..52cfa670ae6 100644 --- a/boards/x86/intel_ehl/intel_ehl_crb_sbl.yaml +++ b/boards/x86/intel_ehl/intel_ehl_crb_sbl.yaml @@ -9,3 +9,4 @@ testing: ignore_tags: - net - bluetooth +vendor: intel diff --git a/boards/x86/intel_ehl/intel_ehl_crb_sbl_defconfig b/boards/x86/intel_ehl/intel_ehl_crb_sbl_defconfig index aeac38cda96..1ccff387dc1 100644 --- a/boards/x86/intel_ehl/intel_ehl_crb_sbl_defconfig +++ b/boards/x86/intel_ehl/intel_ehl_crb_sbl_defconfig @@ -9,3 +9,4 @@ CONFIG_SERIAL=y CONFIG_UART_CONSOLE=y CONFIG_X2APIC=y CONFIG_SMP=y +CONFIG_PCIE_PRT=n diff --git a/boards/x86/intel_ish/Kconfig.defconfig b/boards/x86/intel_ish/Kconfig.defconfig index f989dfcd6ed..1f3d6809643 100644 --- a/boards/x86/intel_ish/Kconfig.defconfig +++ b/boards/x86/intel_ish/Kconfig.defconfig @@ -16,9 +16,6 @@ config TEST_EXTRA_STACK_SIZE default 1024 endif # TEST -config HPET_TIMER - default y - config SYS_CLOCK_TICKS_PER_SEC default 2048 if HPET_TIMER # HPET is 32768 HZ diff --git a/boards/x86/intel_ish/intel_ish_5_4_1.yaml b/boards/x86/intel_ish/intel_ish_5_4_1.yaml index a04b3c0e5d0..2894e667001 100644 --- a/boards/x86/intel_ish/intel_ish_5_4_1.yaml +++ b/boards/x86/intel_ish/intel_ish_5_4_1.yaml @@ -11,3 +11,4 @@ testing: ignore_tags: - net - bluetooth +vendor: intel diff --git a/boards/x86/intel_ish/intel_ish_5_6_0.yaml b/boards/x86/intel_ish/intel_ish_5_6_0.yaml index 42044c0d14c..904c09cba45 100644 --- a/boards/x86/intel_ish/intel_ish_5_6_0.yaml +++ b/boards/x86/intel_ish/intel_ish_5_6_0.yaml @@ -11,3 +11,4 @@ testing: ignore_tags: - net - bluetooth +vendor: intel diff --git a/boards/x86/intel_ish/intel_ish_5_8_0.yaml b/boards/x86/intel_ish/intel_ish_5_8_0.yaml index e750d236d06..09dd57f5e30 100644 --- a/boards/x86/intel_ish/intel_ish_5_8_0.yaml +++ b/boards/x86/intel_ish/intel_ish_5_8_0.yaml @@ -11,3 +11,4 @@ testing: ignore_tags: - net - bluetooth +vendor: intel diff --git a/boards/x86/intel_rpl/CMakeLists.txt b/boards/x86/intel_rpl/CMakeLists.txt index 184ac384c2f..2dc5afcc323 100644 --- a/boards/x86/intel_rpl/CMakeLists.txt +++ b/boards/x86/intel_rpl/CMakeLists.txt @@ -1,5 +1,5 @@ # Create an EFI image -if(CONFIG_BOARD_INTEL_RPL_S_CRB AND CONFIG_BUILD_OUTPUT_EFI) +if(CONFIG_BUILD_OUTPUT_EFI) set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/arch/x86/zefi/zefi.py -c ${CMAKE_C_COMPILER} diff --git a/boards/x86/intel_rpl/Kconfig.defconfig b/boards/x86/intel_rpl/Kconfig.defconfig index ee81baa21f3..78c10d200a3 100644 --- a/boards/x86/intel_rpl/Kconfig.defconfig +++ b/boards/x86/intel_rpl/Kconfig.defconfig @@ -12,6 +12,7 @@ config BUILD_OUTPUT_STRIPPED config MP_MAX_NUM_CPUS default 2 +# TSC on this board is 1.9 GHz, HPET and APIC are 19.2 MHz config SYS_CLOCK_HW_CYCLES_PER_SEC default 1900000000 if APIC_TSC_DEADLINE_TIMER default 1900000000 if APIC_TIMER_TSC @@ -29,9 +30,27 @@ endif config ACPI default y +if ACPI +config HEAP_MEM_POOL_SIZE + default 64000000 +config MAIN_STACK_SIZE + default 320000 +config ACPI_PRT_BUS_NAME + default "_SB.PC00" + if SHELL config SHELL_STACK_SIZE default 320000 +endif # SHELL +endif # ACPI + +if DMA +config DMA_64BIT + default y +config DMA_DW_HW_LLI + default n +config DMA_DW_CHANNEL_COUNT + default 2 endif endif # BOARD_INTEL_RPL_S_CRB diff --git a/boards/x86/intel_rpl/doc/index.rst b/boards/x86/intel_rpl/doc/index.rst index c9db4c0fe3f..b9c64ded19e 100644 --- a/boards/x86/intel_rpl/doc/index.rst +++ b/boards/x86/intel_rpl/doc/index.rst @@ -56,5 +56,6 @@ Booting the Raptor Lake S CRB Board using UEFI ============================================== .. include:: ../../common/efi_boot.rst + :start-after: start_include_here .. _RPL: https://www.intel.com/content/www/us/en/newsroom/resources/13th-gen-core.html#gs.glf2fn diff --git a/boards/x86/intel_rpl/intel_rpl_s_crb.yaml b/boards/x86/intel_rpl/intel_rpl_s_crb.yaml index ad4c413cdeb..ef51e444e58 100644 --- a/boards/x86/intel_rpl/intel_rpl_s_crb.yaml +++ b/boards/x86/intel_rpl/intel_rpl_s_crb.yaml @@ -6,6 +6,7 @@ toolchain: - zephyr ram: 2048 supported: + - acpi - smp - smbus - watchdog @@ -15,3 +16,4 @@ testing: ignore_tags: - net - bluetooth +vendor: intel diff --git a/boards/x86/intel_rpl/intel_rpl_s_crb_defconfig b/boards/x86/intel_rpl/intel_rpl_s_crb_defconfig index 1fe227ba4a6..1d8570bdeb7 100644 --- a/boards/x86/intel_rpl/intel_rpl_s_crb_defconfig +++ b/boards/x86/intel_rpl/intel_rpl_s_crb_defconfig @@ -13,5 +13,3 @@ CONFIG_X2APIC=y CONFIG_SMP=y CONFIG_BUILD_OUTPUT_EFI=y CONFIG_BUILD_NO_GAP_FILL=y -CONFIG_HEAP_MEM_POOL_SIZE=64000000 -CONFIG_MAIN_STACK_SIZE=320000 diff --git a/boards/x86/qemu_x86/Kconfig.defconfig b/boards/x86/qemu_x86/Kconfig.defconfig index 0866657a7c3..84f66e32004 100644 --- a/boards/x86/qemu_x86/Kconfig.defconfig +++ b/boards/x86/qemu_x86/Kconfig.defconfig @@ -24,6 +24,10 @@ config FLASH_SIMULATOR config KERNEL_VM_SIZE default 0x10000000 if ACPI +config HEAP_MEM_POOL_SIZE + default 1048576 if ACPI + depends on KERNEL_MEM_POOL + config MULTIBOOT default y @@ -49,6 +53,10 @@ config BOARD config KERNEL_VM_SIZE default 0x10000000 if ACPI +config HEAP_MEM_POOL_SIZE + default 1048576 if ACPI + depends on KERNEL_MEM_POOL + endif # BOARD_QEMU_X86_64 if BOARD_QEMU_X86_LAKEMONT @@ -73,9 +81,6 @@ config QEMU_ICOUNT config QEMU_ICOUNT_SHIFT default 5 -config UART_NS16550_ACCESS_IOPORT - default y if UART_NS16550 - endif # BOARD_QEMU_X86_LAKEMONT if BOARD_QEMU_X86_TINY diff --git a/boards/x86/qemu_x86/board.cmake b/boards/x86/qemu_x86/board.cmake index 214d85ecc87..934b078154e 100644 --- a/boards/x86/qemu_x86/board.cmake +++ b/boards/x86/qemu_x86/board.cmake @@ -66,7 +66,7 @@ set(QEMU_FLAGS_${ARCH} -nographic ) -if(NOT CONFIG_X86_ACPI) +if(NOT CONFIG_ACPI) list(APPEND QEMU_FLAGS_${ARCH} -no-acpi) endif() diff --git a/boards/x86/qemu_x86/doc/index.rst b/boards/x86/qemu_x86/doc/index.rst index 3f06125b6eb..2fdba13bc09 100644 --- a/boards/x86/qemu_x86/doc/index.rst +++ b/boards/x86/qemu_x86/doc/index.rst @@ -79,7 +79,7 @@ Flashing While this board is emulated and you can't "flash" it, you can use this configuration to run basic Zephyr applications and kernel tests in the QEMU -emulated environment. For example, with the :ref:`synchronization_sample`: +emulated environment. For example, with the :zephyr:code-sample:`synchronization` sample: .. zephyr-app-commands:: :zephyr-app: samples/synchronization @@ -111,23 +111,36 @@ to run Zephyr applications and kernel tests, but you need to set up some environment configurations as follows: * Please install uefi-run in your system environment according to this - reference link https://github.com/Richard-W/uefi-run. + reference link https://github.com/Richard-W/uefi-run. Note that uefi-run + from snapstore may not work because of strict snap confinements. + The preferred method is installing with cargo. * Please install OVMF in your system environment according to this reference link https://github.com/tianocore/tianocore.github.io/wiki/OVMF. + The easiest way is to install a special ``ovmf`` package found in many distros. + For example, use the following command in Ubuntu: + + .. code-block:: console + + sudo apt install ovmf * Set system environment variable OVMF_FD_PATH, - for example: export OVMF_FD_PATH=/usr/share/edk2.git/ovmf-x64/OVMF_CODE-pure-efi.fd + for example: -For example, with the test "sample.basic.helloworld.uefi": + .. code-block:: console -.. code-block:: console + export OVMF_FD_PATH=/usr/share/OVMF/OVMF_CODE.fd + +Now you can build application, for example UEFI boot test sample found under +:zephyr_file:`tests/boot/uefi`: - export OVMF_FD_PATH=/usr/share/edk2.git/ovmf-x64/OVMF_CODE-pure-efi.fd - west build -b qemu_x86_64 -p auto samples/hello_world/ -DCONF_FILE=prj_uefi.conf - west build -t run +.. zephyr-app-commands:: + :zephyr-app: tests/boot/uefi + :host-os: unix + :board: qemu_x86_64 + :goals: run -This will build an image with the hello_world sample app, boot it on +This will build an image with the uefi boot test app, boot it on qemu_x86_64 using UEFI, and display the following console output: .. code-block:: console diff --git a/boards/x86/qemu_x86/qemu_x86.dts b/boards/x86/qemu_x86/qemu_x86.dts index 62fc4dff7a7..62dfaf57b05 100644 --- a/boards/x86/qemu_x86/qemu_x86.dts +++ b/boards/x86/qemu_x86/qemu_x86.dts @@ -8,7 +8,7 @@ #define DT_DRAM_BASE 0 #endif #ifndef DT_DRAM_SIZE -#define DT_DRAM_SIZE DT_SIZE_K(4096) +#define DT_DRAM_SIZE DT_SIZE_M(32) #endif #define DT_FLASH_SIZE DT_SIZE_K(4096) @@ -59,7 +59,6 @@ device-id = <0x8406>; interrupts = <11 IRQ_TYPE_LOWEST_LEVEL_LOW 3>; interrupt-parent = <&intc>; - sjw = <1>; bus-speed = <125000>; sample-point = <875>; diff --git a/boards/x86/qemu_x86/qemu_x86.yaml b/boards/x86/qemu_x86/qemu_x86.yaml index bb662c7c93b..ae8bd13f9ca 100644 --- a/boards/x86/qemu_x86/qemu_x86.yaml +++ b/boards/x86/qemu_x86/qemu_x86.yaml @@ -17,3 +17,4 @@ supported: - rtc testing: default: true +vendor: qemu diff --git a/boards/x86/qemu_x86/qemu_x86_64.yaml b/boards/x86/qemu_x86/qemu_x86_64.yaml index d4c8787f2e5..b5c77de4c0e 100644 --- a/boards/x86/qemu_x86/qemu_x86_64.yaml +++ b/boards/x86/qemu_x86/qemu_x86_64.yaml @@ -7,6 +7,7 @@ toolchain: - xtools simulation: qemu supported: + - acpi - can - smp - smbus @@ -16,3 +17,4 @@ testing: ignore_tags: - net - bluetooth +vendor: qemu diff --git a/boards/x86/qemu_x86/qemu_x86_64_nokpti.yaml b/boards/x86/qemu_x86/qemu_x86_64_nokpti.yaml index 7b440601625..531ebd4d3e1 100644 --- a/boards/x86/qemu_x86/qemu_x86_64_nokpti.yaml +++ b/boards/x86/qemu_x86/qemu_x86_64_nokpti.yaml @@ -15,3 +15,4 @@ testing: - userspace ignore_tags: - benchmark +vendor: qemu diff --git a/boards/x86/qemu_x86/qemu_x86_lakemont.dts b/boards/x86/qemu_x86/qemu_x86_lakemont.dts index 9c6a6da82ec..87056f9cf65 100644 --- a/boards/x86/qemu_x86/qemu_x86_lakemont.dts +++ b/boards/x86/qemu_x86/qemu_x86_lakemont.dts @@ -40,6 +40,7 @@ uart0: uart@3f8 { compatible = "ns16550"; reg = <0x000003f8 0x100>; + io-mapped; clock-frequency = <1843200>; interrupts = <4 IRQ_TYPE_LOWEST_EDGE_RISING 3>; interrupt-parent = <&intc>; diff --git a/boards/x86/qemu_x86/qemu_x86_lakemont.yaml b/boards/x86/qemu_x86/qemu_x86_lakemont.yaml index 447b6b86664..1f1d7bb83c9 100644 --- a/boards/x86/qemu_x86/qemu_x86_lakemont.yaml +++ b/boards/x86/qemu_x86/qemu_x86_lakemont.yaml @@ -13,3 +13,4 @@ testing: - kernel ignore_tags: - benchmark +vendor: qemu diff --git a/boards/x86/qemu_x86/qemu_x86_nokpti.yaml b/boards/x86/qemu_x86/qemu_x86_nokpti.yaml index 7e483a9d77b..75ab0d13d5f 100644 --- a/boards/x86/qemu_x86/qemu_x86_nokpti.yaml +++ b/boards/x86/qemu_x86/qemu_x86_nokpti.yaml @@ -13,3 +13,4 @@ testing: - userspace ignore_tags: - benchmark +vendor: qemu diff --git a/boards/x86/qemu_x86/qemu_x86_nommu.yaml b/boards/x86/qemu_x86/qemu_x86_nommu.yaml index a2874f08135..8d7aee97b7e 100644 --- a/boards/x86/qemu_x86/qemu_x86_nommu.yaml +++ b/boards/x86/qemu_x86/qemu_x86_nommu.yaml @@ -11,3 +11,4 @@ testing: only_tags: - kernel - userspace +vendor: qemu diff --git a/boards/x86/qemu_x86/qemu_x86_nopae.yaml b/boards/x86/qemu_x86/qemu_x86_nopae.yaml index a4e3256b245..7dbd449cebc 100644 --- a/boards/x86/qemu_x86/qemu_x86_nopae.yaml +++ b/boards/x86/qemu_x86/qemu_x86_nopae.yaml @@ -13,3 +13,4 @@ testing: - userspace ignore_tags: - benchmark +vendor: qemu diff --git a/boards/x86/qemu_x86/qemu_x86_tiny.ld b/boards/x86/qemu_x86/qemu_x86_tiny.ld index c53e2a7b409..44e8ff85358 100644 --- a/boards/x86/qemu_x86/qemu_x86_tiny.ld +++ b/boards/x86/qemu_x86/qemu_x86_tiny.ld @@ -10,7 +10,7 @@ #include #include #include -#include +#include /* Bounds of physical RAM from DTS */ diff --git a/boards/x86/qemu_x86/qemu_x86_tiny.yaml b/boards/x86/qemu_x86/qemu_x86_tiny.yaml index d8c9606cff7..8807d57d8d0 100644 --- a/boards/x86/qemu_x86/qemu_x86_tiny.yaml +++ b/boards/x86/qemu_x86/qemu_x86_tiny.yaml @@ -13,3 +13,4 @@ testing: - userspace ignore_tags: - benchmark +vendor: qemu diff --git a/boards/x86/qemu_x86/qemu_x86_virt.yaml b/boards/x86/qemu_x86/qemu_x86_virt.yaml index c80052a158c..1f3eb2fb18b 100644 --- a/boards/x86/qemu_x86/qemu_x86_virt.yaml +++ b/boards/x86/qemu_x86/qemu_x86_virt.yaml @@ -13,3 +13,4 @@ testing: - userspace ignore_tags: - benchmark +vendor: qemu diff --git a/boards/x86/qemu_x86/qemu_x86_xip.yaml b/boards/x86/qemu_x86/qemu_x86_xip.yaml index 6b08ba3afe7..c33acd4db16 100644 --- a/boards/x86/qemu_x86/qemu_x86_xip.yaml +++ b/boards/x86/qemu_x86/qemu_x86_xip.yaml @@ -10,3 +10,4 @@ testing: default: true only_tags: - xip +vendor: qemu diff --git a/boards/x86/up_squared/CMakeLists.txt b/boards/x86/up_squared/CMakeLists.txt index 57eef4eabe1..2dc5afcc323 100644 --- a/boards/x86/up_squared/CMakeLists.txt +++ b/boards/x86/up_squared/CMakeLists.txt @@ -1,5 +1,5 @@ # Create an EFI image -if(CONFIG_BOARD_UP_SQUARED AND CONFIG_BUILD_OUTPUT_EFI) +if(CONFIG_BUILD_OUTPUT_EFI) set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/arch/x86/zefi/zefi.py -c ${CMAKE_C_COMPILER} diff --git a/boards/x86/up_squared/Kconfig.defconfig b/boards/x86/up_squared/Kconfig.defconfig index 87d1f169ec5..33cf546edfc 100644 --- a/boards/x86/up_squared/Kconfig.defconfig +++ b/boards/x86/up_squared/Kconfig.defconfig @@ -8,10 +8,11 @@ config BOARD config MP_MAX_NUM_CPUS default 2 if BOARD_UP_SQUARED -config BUILD_OUTPUT_STRIPPED - default y +config HEAP_MEM_POOL_SIZE + default 1048576 if ACPI + depends on KERNEL_MEM_POOL -config APIC_TSC_DEADLINE_TIMER +config BUILD_OUTPUT_STRIPPED default y # TSC on this board is 1.5936 GHz, HPET and APIC are 19.2 MHz diff --git a/boards/x86/up_squared/doc/index.rst b/boards/x86/up_squared/doc/index.rst index 35dc68ac533..bf40fa16ba2 100644 --- a/boards/x86/up_squared/doc/index.rst +++ b/boards/x86/up_squared/doc/index.rst @@ -80,7 +80,7 @@ Booting the UP Squared Board using UEFI ======================================= .. include:: ../../common/efi_boot.rst - + :start-after: start_include_here .. note:: Refer to the `UP Squared Serial Console Wiki page @@ -98,6 +98,7 @@ Booting the UP Squared Board over network ========================================= .. include:: ../../common/net_boot.rst + :start-after: start_include_here .. note:: Refer to the `UP Squared Serial Console Wiki page diff --git a/boards/x86/up_squared/up_squared.dts b/boards/x86/up_squared/up_squared.dts index 987125da950..e4977160db6 100644 --- a/boards/x86/up_squared/up_squared.dts +++ b/boards/x86/up_squared/up_squared.dts @@ -14,7 +14,7 @@ / { model = "up_squared"; - compatible = "up_board,up_squared"; + compatible = "aaeon,up_squared"; aliases { i2c-0 = &i2c0; @@ -36,14 +36,14 @@ cpu@0 { device_type = "cpu"; - compatible = "intel,apollo_lake"; + compatible = "intel,apollo-lake"; d-cache-line-size = <64>; reg = <0>; }; cpu@1 { device_type = "cpu"; - compatible = "intel,apollo_lake"; + compatible = "intel,apollo-lake"; d-cache-line-size = <64>; reg = <1>; }; diff --git a/boards/x86/up_squared/up_squared.yaml b/boards/x86/up_squared/up_squared.yaml index 2b27e7a7b2b..79e4d5e7e92 100644 --- a/boards/x86/up_squared/up_squared.yaml +++ b/boards/x86/up_squared/up_squared.yaml @@ -6,6 +6,7 @@ toolchain: - zephyr ram: 256 supported: + - acpi - smp testing: ignore_tags: diff --git a/boards/xtensa/esp32_devkitc_wroom/esp32_devkitc_wroom.yaml b/boards/xtensa/esp32_devkitc_wroom/esp32_devkitc_wroom.yaml index 4a937b09491..0481a96df00 100644 --- a/boards/xtensa/esp32_devkitc_wroom/esp32_devkitc_wroom.yaml +++ b/boards/xtensa/esp32_devkitc_wroom/esp32_devkitc_wroom.yaml @@ -21,3 +21,4 @@ testing: ignore_tags: - net - bluetooth +vendor: espressif diff --git a/boards/xtensa/esp32_devkitc_wrover/doc/index.rst b/boards/xtensa/esp32_devkitc_wrover/doc/index.rst index e749ac40826..e7615f13335 100644 --- a/boards/xtensa/esp32_devkitc_wrover/doc/index.rst +++ b/boards/xtensa/esp32_devkitc_wrover/doc/index.rst @@ -141,7 +141,7 @@ Sysbuild ======== The sysbuild makes possible to build and flash all necessary images needed to -bootstrap the board with the EPS32 SoC. +bootstrap the board with the ESP32 SoC. To build the sample application using sysbuild use the command: diff --git a/boards/xtensa/esp32_devkitc_wrover/esp32_devkitc_wrover.yaml b/boards/xtensa/esp32_devkitc_wrover/esp32_devkitc_wrover.yaml index 3680afba27a..7ae68f8e9de 100644 --- a/boards/xtensa/esp32_devkitc_wrover/esp32_devkitc_wrover.yaml +++ b/boards/xtensa/esp32_devkitc_wrover/esp32_devkitc_wrover.yaml @@ -21,3 +21,4 @@ testing: ignore_tags: - net - bluetooth +vendor: espressif diff --git a/boards/xtensa/esp32_ethernet_kit/doc/index.rst b/boards/xtensa/esp32_ethernet_kit/doc/index.rst index 18638959af3..7159681dccd 100644 --- a/boards/xtensa/esp32_ethernet_kit/doc/index.rst +++ b/boards/xtensa/esp32_ethernet_kit/doc/index.rst @@ -468,7 +468,7 @@ Sysbuild ======== The sysbuild makes possible to build and flash all necessary images needed to -bootstrap the board with the EPS32 SoC. +bootstrap the board with the ESP32 SoC. To build the sample application using sysbuild use the command: @@ -581,7 +581,9 @@ You can debug an application in the usual way. Here is an example for the :ref:` Enabling Ethernet ***************** -Enable Ethernet MAC, PHY and MDIO; add these to your device tree overlay:: +Enable Ethernet MAC, PHY and MDIO; add these to your device tree overlay: + +.. code-block:: devicetree ð { status = "okay"; @@ -595,7 +597,9 @@ Enable Ethernet MAC, PHY and MDIO; add these to your device tree overlay:: status = "okay"; }; -Enable Ethernet in KConfig:: +Enable Ethernet in KConfig: + +.. code-block:: cfg CONFIG_ETH_ESP32=y CONFIG_NETWORKING=y diff --git a/boards/xtensa/esp32_ethernet_kit/esp32_ethernet_kit.dts b/boards/xtensa/esp32_ethernet_kit/esp32_ethernet_kit.dts index d0dbc4c62d7..3139e8beaa3 100644 --- a/boards/xtensa/esp32_ethernet_kit/esp32_ethernet_kit.dts +++ b/boards/xtensa/esp32_ethernet_kit/esp32_ethernet_kit.dts @@ -119,10 +119,10 @@ pinctrl-0 = <&mdio_default>; pinctrl-names = "default"; - phy: phy { + phy: ethernet-phy@1 { compatible = "ethernet-phy"; status = "disabled"; - address = <1>; + reg = <1>; }; }; diff --git a/boards/xtensa/esp32_ethernet_kit/esp32_ethernet_kit.yaml b/boards/xtensa/esp32_ethernet_kit/esp32_ethernet_kit.yaml index e80b9a07a64..8f1167e1fac 100644 --- a/boards/xtensa/esp32_ethernet_kit/esp32_ethernet_kit.yaml +++ b/boards/xtensa/esp32_ethernet_kit/esp32_ethernet_kit.yaml @@ -14,3 +14,4 @@ testing: ignore_tags: - net - bluetooth +vendor: espressif diff --git a/boards/xtensa/esp32_net/esp32_net.yaml b/boards/xtensa/esp32_net/esp32_net.yaml index 0c4d3aa470f..14739928f62 100644 --- a/boards/xtensa/esp32_net/esp32_net.yaml +++ b/boards/xtensa/esp32_net/esp32_net.yaml @@ -19,3 +19,4 @@ testing: - logging - kernel - pm +vendor: espressif diff --git a/boards/xtensa/esp32s2_franzininho/doc/index.rst b/boards/xtensa/esp32s2_franzininho/doc/index.rst index 63407133c3d..684fbf5dd5c 100644 --- a/boards/xtensa/esp32s2_franzininho/doc/index.rst +++ b/boards/xtensa/esp32s2_franzininho/doc/index.rst @@ -84,7 +84,7 @@ Sysbuild ======== The sysbuild makes possible to build and flash all necessary images needed to -bootstrap the board with the EPS32 SoC. +bootstrap the board with the ESP32 SoC. To build the sample application using sysbuild use the command: diff --git a/boards/xtensa/esp32s2_franzininho/esp32s2_franzininho.yaml b/boards/xtensa/esp32s2_franzininho/esp32s2_franzininho.yaml index 87fb655e204..9cc2a260342 100644 --- a/boards/xtensa/esp32s2_franzininho/esp32s2_franzininho.yaml +++ b/boards/xtensa/esp32s2_franzininho/esp32s2_franzininho.yaml @@ -16,3 +16,4 @@ testing: - heap - net - bluetooth +vendor: espressif diff --git a/boards/xtensa/esp32s2_lolin_mini/Kconfig.board b/boards/xtensa/esp32s2_lolin_mini/Kconfig.board new file mode 100644 index 00000000000..1f567f3f42b --- /dev/null +++ b/boards/xtensa/esp32s2_lolin_mini/Kconfig.board @@ -0,0 +1,12 @@ +# ESP32S2 LOLIN S2 MINI board configuration + +# Copyright (c) 2023 Google, LLC +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_ESP32S2_LOLIN_MINI + bool "ESP32S2 Lolin Mini Board" + depends on SOC_SERIES_ESP32S2 + +choice SOC_PART_NUMBER + default SOC_ESP32S2_FN4R2 +endchoice diff --git a/boards/xtensa/esp32s2_lolin_mini/Kconfig.defconfig b/boards/xtensa/esp32s2_lolin_mini/Kconfig.defconfig new file mode 100644 index 00000000000..7724f8c90a1 --- /dev/null +++ b/boards/xtensa/esp32s2_lolin_mini/Kconfig.defconfig @@ -0,0 +1,15 @@ +# ESP32S2 LOLIN S2 MINI board configuration + +# Copyright (c) 2023 Google, LLC +# SPDX-License-Identifier: Apache-2.0 + +config BOARD + default "esp32s2_lolin_mini" + depends on BOARD_ESP32S2_LOLIN_MINI + +config ENTROPY_GENERATOR + default y + +config HEAP_MEM_POOL_SIZE + default 32768 if WIFI + default 4096 diff --git a/boards/xtensa/esp32s2_lolin_mini/board.cmake b/boards/xtensa/esp32s2_lolin_mini/board.cmake new file mode 100644 index 00000000000..2f04d1fe886 --- /dev/null +++ b/boards/xtensa/esp32s2_lolin_mini/board.cmake @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +if(NOT "${OPENOCD}" MATCHES "^${ESPRESSIF_TOOLCHAIN_PATH}/.*") + set(OPENOCD OPENOCD-NOTFOUND) +endif() +find_program(OPENOCD openocd PATHS ${ESPRESSIF_TOOLCHAIN_PATH}/openocd-esp32/bin NO_DEFAULT_PATH) + +include(${ZEPHYR_BASE}/boards/common/esp32.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/xtensa/esp32s2_lolin_mini/doc/img/esp32_s2_lolin_mini.jpg b/boards/xtensa/esp32s2_lolin_mini/doc/img/esp32_s2_lolin_mini.jpg new file mode 100644 index 00000000000..65ef9d11cae Binary files /dev/null and b/boards/xtensa/esp32s2_lolin_mini/doc/img/esp32_s2_lolin_mini.jpg differ diff --git a/boards/xtensa/esp32s2_lolin_mini/doc/index.rst b/boards/xtensa/esp32s2_lolin_mini/doc/index.rst new file mode 100644 index 00000000000..70682657f8a --- /dev/null +++ b/boards/xtensa/esp32s2_lolin_mini/doc/index.rst @@ -0,0 +1,96 @@ +.. _esp32s2_lolin_mini: + +ESP32-S2 Lolin Mini +################### + +Overview +******** + +ESP32-S2 is a highly integrated, low-power, single-core Wi-Fi Microcontroller SoC, designed to be secure and +cost-effective, with a high performance and a rich set of IO capabilities. [1]_ + +The features include the following: + +- RSA-3072-based secure boot +- AES-XTS-256-based flash encryption +- Protected private key and device secrets from software access +- Cryptographic accelerators for enhanced performance +- Protection against physical fault injection attacks +- Various peripherals: + + - 43x programmable GPIOs + - 14x configurable capacitive touch GPIOs + - USB OTG + - LCD interface + - camera interface + - SPI + - I2S + - UART + - ADC + - DAC + - LED PWM with up to 8 channels + +.. figure:: img/esp32_s2_lolin_mini.jpg + :align: center + :alt: ESP32-S2 LOLIN MINI + +System requirements +******************* + +Prerequisites +------------- + +Espressif HAL requires WiFi and Bluetooth binary blobs in order work. Run the command +below to retrieve those files. + +.. code-block:: console + + west blobs fetch hal_espressif + +.. note:: + + It is recommended running the command above after :file:`west update`. + +Building & Flashing +------------------- + +Build and flash applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32s2_lolin_mini + :goals: build + +The usual ``flash`` target will work with the ``esp32s2_lolin_mini`` board +configuration after putting the board into bootloader mode by holding the '0' +button then pressing 'RST' and releasing the 'RST' button. + +Here is an example for the :ref:`hello_world` +application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32s2_lolin_mini + :goals: flash + +Open a serial port using e.g. screen + +.. code-block:: shell + + screen /dev/ttyUSB0 115200 + +After the board has been manually reset and booted, you should see the following +message in the monitor: + +.. code-block:: console + + ***** Booting Zephyr OS vx.x.x-xxx-gxxxxxxxxxxxx ***** + Hello World! esp32s2_lolin_mini + +References +********** + +.. [1] https://www.espressif.com/en/products/socs/esp32-s2 +.. _`ESP32S2 Technical Reference Manual`: https://espressif.com/sites/default/files/documentation/esp32-s2_technical_reference_manual_en.pdf +.. _`ESP32S2 Datasheet`: https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf diff --git a/boards/xtensa/esp32s2_lolin_mini/esp32s2_lolin_mini-pinctrl.dtsi b/boards/xtensa/esp32s2_lolin_mini/esp32s2_lolin_mini-pinctrl.dtsi new file mode 100644 index 00000000000..c6dbf79e676 --- /dev/null +++ b/boards/xtensa/esp32s2_lolin_mini/esp32s2_lolin_mini-pinctrl.dtsi @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Google, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +&pinctrl { + + uart0_default: uart0_default { + group1 { + pinmux = ; + output-high; + }; + group2 { + pinmux = ; + bias-pull-up; + }; + }; +}; diff --git a/boards/xtensa/esp32s2_lolin_mini/esp32s2_lolin_mini.dts b/boards/xtensa/esp32s2_lolin_mini/esp32s2_lolin_mini.dts new file mode 100644 index 00000000000..9f90447560b --- /dev/null +++ b/boards/xtensa/esp32s2_lolin_mini/esp32s2_lolin_mini.dts @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2023 Google, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include +#include "esp32s2_lolin_mini-pinctrl.dtsi" + +/ { + model = "esp32s2_lolin_mini"; + compatible = "espressif,esp32s2"; + + aliases { + sw0 = &user_button; + led0 = &user_led; + watchdog0 = &wdt0; + }; + + chosen { + zephyr,sram = &sram0; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,flash = &flash0; + }; + + leds { + compatible = "gpio-leds"; + user_led: led { + gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>; + label = "LED1"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button: user_button { + label = "0"; + gpios = <&gpio0 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + zephyr,code = ; + }; + }; +}; + +&cpu0 { + clock-frequency = ; + cpu-power-states = <&deep_sleep &light_sleep>; +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&timer0 { + status = "disabled"; +}; + +&timer1 { + status = "disabled"; +}; + +&timer2 { + status = "disabled"; +}; + +&timer3 { + status = "disabled"; +}; + +&trng0 { + status = "okay"; +}; + +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; + + status = "okay"; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserve 60kB for the bootloader */ + boot_partition: partition@1000 { + label = "mcuboot"; + reg = <0x00001000 0x0000F000>; + read-only; + }; + + /* Reserve 1024kB for the application in slot 0 */ + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 0x00100000>; + }; + + /* Reserve 1024kB for the application in slot 1 */ + slot1_partition: partition@110000 { + label = "image-1"; + reg = <0x00110000 0x00100000>; + }; + + /* Reserve 256kB for the scratch partition */ + scratch_partition: partition@210000 { + label = "image-scratch"; + reg = <0x00210000 0x00040000>; + }; + + storage_partition: partition@250000 { + label = "storage"; + reg = <0x00250000 0x00006000>; + }; + }; +}; + +&wdt0 { + status = "okay"; +}; diff --git a/boards/xtensa/esp32s2_lolin_mini/esp32s2_lolin_mini.yaml b/boards/xtensa/esp32s2_lolin_mini/esp32s2_lolin_mini.yaml new file mode 100644 index 00000000000..3764f5eddd7 --- /dev/null +++ b/boards/xtensa/esp32s2_lolin_mini/esp32s2_lolin_mini.yaml @@ -0,0 +1,14 @@ +identifier: esp32s2_lolin_mini +name: Lolin ESP32-S2 Mini +type: mcu +arch: xtensa +toolchain: + - zephyr +supported: + - gpio + - watchdog + - uart +testing: + ignore_tags: + - net + - bluetooth diff --git a/boards/xtensa/esp32s2_lolin_mini/esp32s2_lolin_mini_defconfig b/boards/xtensa/esp32s2_lolin_mini/esp32s2_lolin_mini_defconfig new file mode 100644 index 00000000000..c8c04460dbe --- /dev/null +++ b/boards/xtensa/esp32s2_lolin_mini/esp32s2_lolin_mini_defconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_BOARD_ESP32S2_LOLIN_MINI=y +CONFIG_SOC_SERIES_ESP32S2=y + +CONFIG_MAIN_STACK_SIZE=2048 + +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y + +CONFIG_GPIO=y diff --git a/boards/xtensa/esp32s2_lolin_mini/support/openocd.cfg b/boards/xtensa/esp32s2_lolin_mini/support/openocd.cfg new file mode 100644 index 00000000000..f75d53b0b34 --- /dev/null +++ b/boards/xtensa/esp32s2_lolin_mini/support/openocd.cfg @@ -0,0 +1,4 @@ +set ESP_RTOS none + +source [find interface/ftdi/esp32s2_kaluga_v1.cfg] +source [find target/esp32s2.cfg] diff --git a/boards/xtensa/esp32s2_saola/doc/index.rst b/boards/xtensa/esp32s2_saola/doc/index.rst index ee5b5c922d3..f52594c6649 100644 --- a/boards/xtensa/esp32s2_saola/doc/index.rst +++ b/boards/xtensa/esp32s2_saola/doc/index.rst @@ -118,7 +118,7 @@ Sysbuild ======== The sysbuild makes possible to build and flash all necessary images needed to -bootstrap the board with the EPS32 SoC. +bootstrap the board with the ESP32 SoC. To build the sample application using sysbuild use the command: diff --git a/boards/xtensa/esp32s2_saola/esp32s2_saola.yaml b/boards/xtensa/esp32s2_saola/esp32s2_saola.yaml index 77ea683f54b..261d7d0eb8f 100644 --- a/boards/xtensa/esp32s2_saola/esp32s2_saola.yaml +++ b/boards/xtensa/esp32s2_saola/esp32s2_saola.yaml @@ -20,3 +20,4 @@ testing: ignore_tags: - net - bluetooth +vendor: espressif diff --git a/boards/xtensa/esp32s3_devkitm/Kconfig.board b/boards/xtensa/esp32s3_devkitm/Kconfig.board index 96de0fb06f7..3f899740c0d 100644 --- a/boards/xtensa/esp32s3_devkitm/Kconfig.board +++ b/boards/xtensa/esp32s3_devkitm/Kconfig.board @@ -6,6 +6,10 @@ config BOARD_ESP32S3_DEVKITM bool "ESP32S3 DevKitM Board" depends on SOC_SERIES_ESP32S3 +config BOARD_ESP32S3_DEVKITM_APPCPU + bool "ESP32S3 Board configuration for APPCPU (core 1)." + depends on SOC_SERIES_ESP32S3 && SOC_ESP32S3_APPCPU + choice SOC_PART_NUMBER default SOC_ESP32S3_MINI_N8 endchoice diff --git a/boards/xtensa/esp32s3_devkitm/Kconfig.defconfig b/boards/xtensa/esp32s3_devkitm/Kconfig.defconfig index e0dc279412f..cb102b4ee64 100644 --- a/boards/xtensa/esp32s3_devkitm/Kconfig.defconfig +++ b/boards/xtensa/esp32s3_devkitm/Kconfig.defconfig @@ -3,12 +3,10 @@ # Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. # SPDX-License-Identifier: Apache-2.0 +if BOARD_ESP32S3_DEVKITM + config BOARD default "esp32s3_devkitm" - depends on BOARD_ESP32S3_DEVKITM - -config ENTROPY_GENERATOR - default y config HEAP_MEM_POOL_SIZE default 98304 if WIFI @@ -18,3 +16,20 @@ config HEAP_MEM_POOL_SIZE choice BT_HCI_BUS_TYPE default BT_ESP32 if BT endchoice + +endif + +if BOARD_ESP32S3_DEVKITM_APPCPU + +config BOARD + default "esp32s3_devkitm_appcpu" + +config HEAP_MEM_POOL_SIZE + default 4096 + +config KERNEL_BIN_NAME + default "esp32_net_firmware" +endif + +config ENTROPY_GENERATOR + default y diff --git a/boards/xtensa/esp32s3_devkitm/doc/index.rst b/boards/xtensa/esp32s3_devkitm/doc/index.rst index 5684ad69118..851246a75d4 100644 --- a/boards/xtensa/esp32s3_devkitm/doc/index.rst +++ b/boards/xtensa/esp32s3_devkitm/doc/index.rst @@ -71,6 +71,13 @@ Security: - 4-Kbit OTP, up to 1792 bits for users - Cryptographic hardware acceleration: (AES-128/256, Hash, RSA, RNG, HMAC, Digital signature) +Asymmetric Multiprocessing (AMP) +******************************** + +ESP32S3-DevKitM allows 2 different applications to be executed in ESP32-S3 SoC. Due to its dual-core +architecture, each core can be enabled to execute customized tasks in stand-alone mode +and/or exchanging data over OpenAMP framework. See :ref:`ipc_samples` folder as code reference. + For more information, check the datasheet at `ESP32-S3 Datasheet`_. Supported Features @@ -160,7 +167,7 @@ Sysbuild ======== The sysbuild makes possible to build and flash all necessary images needed to -bootstrap the board with the EPS32 SoC. +bootstrap the board with the ESP32 SoC. To build the sample application using sysbuild use the command: diff --git a/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm.yaml b/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm.yaml index b44b2ec9357..160e01f4d6e 100644 --- a/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm.yaml +++ b/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm.yaml @@ -19,3 +19,4 @@ testing: ignore_tags: - net - bluetooth +vendor: espressif diff --git a/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm_appcpu.dts b/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm_appcpu.dts new file mode 100644 index 00000000000..ae68f094e14 --- /dev/null +++ b/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm_appcpu.dts @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ +/dts-v1/; + +#include +/ { + model = "esp32s3_appcpu"; + compatible = "espressif,esp32s3_appcpu"; + + chosen { + zephyr,sram = &sram0; + zephyr,ipc_shm = &shm0; + zephyr,ipc = &ipm0; + }; +}; + +&cpu0 { + clock-frequency = ; +}; + +&cpu1 { + clock-frequency = ; +}; + +&trng0 { + status = "okay"; +}; + +&ipm0 { + status = "okay"; +}; diff --git a/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm_appcpu.yaml b/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm_appcpu.yaml new file mode 100644 index 00000000000..b6145d0f965 --- /dev/null +++ b/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm_appcpu.yaml @@ -0,0 +1,26 @@ +identifier: esp32s3_devkitm_appcpu +name: ESP32S3 DEVKITM APPCPU +type: mcu +arch: xtensa +toolchain: + - zephyr +supported: + - uart +testing: + ignore_tags: + - net + - bluetooth + - flash + - cpp + - posix + - watchdog + - logging + - kernel + - pm + - gpio + - crypto + - eeprom + - heap + - cmsis_rtos + - jwt + - zdsp diff --git a/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm_appcpu_defconfig b/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm_appcpu_defconfig new file mode 100644 index 00000000000..e554a951263 --- /dev/null +++ b/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm_appcpu_defconfig @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_ESP32S3=y +CONFIG_SOC_ESP32S3_APPCPU=y +CONFIG_BOARD_ESP32S3_DEVKITM_APPCPU=y + +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_CLOCK_CONTROL=y +CONFIG_MINIMAL_LIBC=y diff --git a/boards/xtensa/esp32s3_luatos_core/doc/index.rst b/boards/xtensa/esp32s3_luatos_core/doc/index.rst index c4883db35d8..9160a20fcf4 100644 --- a/boards/xtensa/esp32s3_luatos_core/doc/index.rst +++ b/boards/xtensa/esp32s3_luatos_core/doc/index.rst @@ -166,7 +166,7 @@ Sysbuild ======== The sysbuild makes possible to build and flash all necessary images needed to -bootstrap the board with the EPS32 SoC. +bootstrap the board with the ESP32 SoC. To build the sample application using sysbuild use the command: diff --git a/boards/xtensa/esp32s3_luatos_core/esp32s3_luatos_core.yaml b/boards/xtensa/esp32s3_luatos_core/esp32s3_luatos_core.yaml index d6548d80c98..eb850a58f95 100644 --- a/boards/xtensa/esp32s3_luatos_core/esp32s3_luatos_core.yaml +++ b/boards/xtensa/esp32s3_luatos_core/esp32s3_luatos_core.yaml @@ -19,3 +19,4 @@ testing: ignore_tags: - net - bluetooth +vendor: espressif diff --git a/boards/xtensa/esp32s3_luatos_core/esp32s3_luatos_core_usb.yaml b/boards/xtensa/esp32s3_luatos_core/esp32s3_luatos_core_usb.yaml index c8346274c09..a8680bb6544 100644 --- a/boards/xtensa/esp32s3_luatos_core/esp32s3_luatos_core_usb.yaml +++ b/boards/xtensa/esp32s3_luatos_core/esp32s3_luatos_core_usb.yaml @@ -19,3 +19,4 @@ testing: ignore_tags: - net - bluetooth +vendor: espressif diff --git a/boards/xtensa/esp_wrover_kit/doc/index.rst b/boards/xtensa/esp_wrover_kit/doc/index.rst index 0e0a9921a0d..0154f2c9ad9 100644 --- a/boards/xtensa/esp_wrover_kit/doc/index.rst +++ b/boards/xtensa/esp_wrover_kit/doc/index.rst @@ -533,7 +533,7 @@ Sysbuild ======== The sysbuild makes possible to build and flash all necessary images needed to -bootstrap the board with the EPS32 SoC. +bootstrap the board with the ESP32 SoC. To build the sample application using sysbuild use the command: diff --git a/boards/xtensa/esp_wrover_kit/esp_wrover_kit.yaml b/boards/xtensa/esp_wrover_kit/esp_wrover_kit.yaml index 0d92719606e..3d1b9921904 100644 --- a/boards/xtensa/esp_wrover_kit/esp_wrover_kit.yaml +++ b/boards/xtensa/esp_wrover_kit/esp_wrover_kit.yaml @@ -20,3 +20,4 @@ testing: ignore_tags: - net - bluetooth +vendor: espressif diff --git a/boards/xtensa/heltec_wifi_lora32_v2/doc/index.rst b/boards/xtensa/heltec_wifi_lora32_v2/doc/index.rst index 658c6083182..1029b21dd60 100644 --- a/boards/xtensa/heltec_wifi_lora32_v2/doc/index.rst +++ b/boards/xtensa/heltec_wifi_lora32_v2/doc/index.rst @@ -72,7 +72,7 @@ Sysbuild ======== The sysbuild makes possible to build and flash all necessary images needed to -bootstrap the board with the EPS32 SoC. +bootstrap the board with the ESP32 SoC. To build the sample application using sysbuild use the command: @@ -188,7 +188,7 @@ Onboard OLED display The onboard OLED display is of type ``ssd1306``, has 128*64 pixels and is connected via I2C. It can therefore be used by enabling the -:ref:`ssd1306_128_shield` as shown in the following for the :ref:`lvgl-sample`: +:ref:`ssd1306_128_shield` as shown in the following for the :zephyr:code-sample:`lvgl` sample: .. zephyr-app-commands:: :zephyr-app: samples/subsys/display/lvgl diff --git a/boards/xtensa/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2.yaml b/boards/xtensa/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2.yaml index 05a5445554d..740755b5e6a 100644 --- a/boards/xtensa/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2.yaml +++ b/boards/xtensa/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2.yaml @@ -14,3 +14,4 @@ testing: ignore_tags: - net - bluetooth +vendor: espressif diff --git a/boards/xtensa/intel_adsp_ace15_mtpm/board.cmake b/boards/xtensa/intel_adsp_ace15_mtpm/board.cmake index 0948dfc49ef..63777239a1d 100644 --- a/boards/xtensa/intel_adsp_ace15_mtpm/board.cmake +++ b/boards/xtensa/intel_adsp_ace15_mtpm/board.cmake @@ -5,3 +5,5 @@ board_set_rimage_target(mtl) set(RIMAGE_SIGN_KEY "otc_private_key_3k.pem" CACHE STRING "default in ace15_mtpm/board.cmake") + +include(${ZEPHYR_BASE}/boards/common/intel_adsp.board.cmake) diff --git a/boards/xtensa/intel_adsp_ace15_mtpm/intel_adsp_ace15_mtpm.dts b/boards/xtensa/intel_adsp_ace15_mtpm/intel_adsp_ace15_mtpm.dts index f4a88d99252..cc0fc9d0803 100644 --- a/boards/xtensa/intel_adsp_ace15_mtpm/intel_adsp_ace15_mtpm.dts +++ b/boards/xtensa/intel_adsp_ace15_mtpm/intel_adsp_ace15_mtpm.dts @@ -10,7 +10,7 @@ / { model = "intel_adsp_ace15_mtpm"; - compatible = "intel"; + compatible = "intel,intel_adsp_ace20_lnl"; aliases { dma0 = &lpgpdma0; diff --git a/boards/xtensa/intel_adsp_ace15_mtpm/intel_adsp_ace15_mtpm.yaml b/boards/xtensa/intel_adsp_ace15_mtpm/intel_adsp_ace15_mtpm.yaml index de626d6a1fe..9493e4c08da 100644 --- a/boards/xtensa/intel_adsp_ace15_mtpm/intel_adsp_ace15_mtpm.yaml +++ b/boards/xtensa/intel_adsp_ace15_mtpm/intel_adsp_ace15_mtpm.yaml @@ -12,3 +12,4 @@ testing: ignore_tags: - net - bluetooth +vendor: intel diff --git a/boards/xtensa/intel_adsp_ace20_lnl/intel_adsp_ace20_lnl.dts b/boards/xtensa/intel_adsp_ace20_lnl/intel_adsp_ace20_lnl.dts index 0a68f186424..6df8089a508 100644 --- a/boards/xtensa/intel_adsp_ace20_lnl/intel_adsp_ace20_lnl.dts +++ b/boards/xtensa/intel_adsp_ace20_lnl/intel_adsp_ace20_lnl.dts @@ -10,7 +10,7 @@ / { model = "intel_adsp_ace20_lnl"; - compatible = "intel"; + compatible = "intel,intel_adsp_ace20_lnl"; chosen { zephyr,sram = &sram0; diff --git a/boards/xtensa/intel_adsp_ace20_lnl/intel_adsp_ace20_lnl.yaml b/boards/xtensa/intel_adsp_ace20_lnl/intel_adsp_ace20_lnl.yaml index 9d9c3277d2c..693f3ad2ce6 100644 --- a/boards/xtensa/intel_adsp_ace20_lnl/intel_adsp_ace20_lnl.yaml +++ b/boards/xtensa/intel_adsp_ace20_lnl/intel_adsp_ace20_lnl.yaml @@ -13,3 +13,4 @@ testing: - net - bluetooth - mcumgr +vendor: intel diff --git a/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25.dts b/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25.dts index 52a0ea3c8c5..ac7a8c058aa 100644 --- a/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25.dts +++ b/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25.dts @@ -10,7 +10,7 @@ / { model = "intel_adsp_cavs25"; - compatible = "intel"; + compatible = "intel,intel_adsp_cavs25"; aliases { dma0 = &lpgpdma0; diff --git a/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25.yaml b/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25.yaml index 590e408a26a..8d175cbc621 100644 --- a/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25.yaml +++ b/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25.yaml @@ -12,3 +12,4 @@ testing: ignore_tags: - net - bluetooth +vendor: intel diff --git a/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25_tgph.dts b/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25_tgph.dts index cadd7de32c1..5b916c9ee3a 100644 --- a/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25_tgph.dts +++ b/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25_tgph.dts @@ -10,7 +10,7 @@ / { model = "intel_adsp_cavs25_tgph"; - compatible = "intel"; + compatible = "intel,intel_adsp_cavs25_tgph"; aliases { dma0 = &lpgpdma0; diff --git a/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25_tgph.yaml b/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25_tgph.yaml index 644e4f497a8..f11256de9bf 100644 --- a/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25_tgph.yaml +++ b/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25_tgph.yaml @@ -11,3 +11,4 @@ testing: ignore_tags: - net - bluetooth +vendor: intel diff --git a/boards/xtensa/m5stack_atoms3/Kconfig.board b/boards/xtensa/m5stack_atoms3/Kconfig.board new file mode 100644 index 00000000000..726e31773e2 --- /dev/null +++ b/boards/xtensa/m5stack_atoms3/Kconfig.board @@ -0,0 +1,12 @@ +# M5Stack AtomS3 board configuration + +# Copyright (c) 2023 Benjamin Cabé +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_M5STACK_ATOMS3 + bool "M5Stack AtomS3 Development Board" + depends on SOC_SERIES_ESP32S3 + +choice SOC_PART_NUMBER + default SOC_ESP32S3_FN8 +endchoice diff --git a/boards/xtensa/m5stack_atoms3/Kconfig.defconfig b/boards/xtensa/m5stack_atoms3/Kconfig.defconfig new file mode 100644 index 00000000000..b9bd2641458 --- /dev/null +++ b/boards/xtensa/m5stack_atoms3/Kconfig.defconfig @@ -0,0 +1,29 @@ +# M5Stack AtomS3 board configuration +# Copyright (c) 2023 Benjamin Cabé +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_M5STACK_ATOMS3 + +config BOARD + default "m5stack_atoms3" + depends on BOARD_M5STACK_ATOMS3 + +config ENTROPY_GENERATOR + default y + +config HEAP_MEM_POOL_SIZE + default 98304 if WIFI + default 65536 if BT + default 4096 + +config KERNEL_MEM_POOL + default y + +choice BT_HCI_BUS_TYPE + default BT_ESP32 if BT +endchoice + +config LV_COLOR_16_SWAP + default y if LVGL + +endif # BOARD_M5STACK_ATOMS3 diff --git a/boards/xtensa/m5stack_atoms3/board.cmake b/boards/xtensa/m5stack_atoms3/board.cmake new file mode 100644 index 00000000000..2f04d1fe886 --- /dev/null +++ b/boards/xtensa/m5stack_atoms3/board.cmake @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +if(NOT "${OPENOCD}" MATCHES "^${ESPRESSIF_TOOLCHAIN_PATH}/.*") + set(OPENOCD OPENOCD-NOTFOUND) +endif() +find_program(OPENOCD openocd PATHS ${ESPRESSIF_TOOLCHAIN_PATH}/openocd-esp32/bin NO_DEFAULT_PATH) + +include(${ZEPHYR_BASE}/boards/common/esp32.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/xtensa/m5stack_atoms3/doc/img/m5stack_atoms3.webp b/boards/xtensa/m5stack_atoms3/doc/img/m5stack_atoms3.webp new file mode 100644 index 00000000000..b4b964069b4 Binary files /dev/null and b/boards/xtensa/m5stack_atoms3/doc/img/m5stack_atoms3.webp differ diff --git a/boards/xtensa/m5stack_atoms3/doc/index.rst b/boards/xtensa/m5stack_atoms3/doc/index.rst new file mode 100644 index 00000000000..2dd229be436 --- /dev/null +++ b/boards/xtensa/m5stack_atoms3/doc/index.rst @@ -0,0 +1,136 @@ +.. _m5stack_atoms3: + +M5Stack AtomS3 +############## + +Overview +******** + +M5Stack AtomS3 is an ESP32-based development board from M5Stack. + +It features the following integrated components: + +- ESP32-S3FN8 chip (240MHz dual core, Wi-Fi/BLE 5.0) +- 512KB of SRAM +- 384KB of ROM +- 8MB of Flash +- LCD IPS TFT 0.85", 128x128 px screen (ST7789 compatible) +- 6-axis IMU MPU6886 +- Infrared emitter + + +.. figure:: img/m5stack_atoms3.webp + :align: center + :alt: M5Stack AtomS3 + + M5Stack AtomS3 + + +Supported Features +================== + +The Zephyr m5stack_atoms3 board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c | ++-----------+------------+-------------------------------------+ +| SPI | on-chip | spi | ++-----------+------------+-------------------------------------+ +| CLOCK | on-chip | reset and clock control | ++-----------+------------+-------------------------------------+ +| COUNTER | on-chip | rtc | ++-----------+------------+-------------------------------------+ +| WATCHDOG | on-chip | independent watchdog | ++-----------+------------+-------------------------------------+ +| PWM | on-chip | pwm | ++-----------+------------+-------------------------------------+ +| ADC | on-chip | adc | ++-----------+------------+-------------------------------------+ +| DAC | on-chip | dac | ++-----------+------------+-------------------------------------+ +| die-temp | on-chip | die temperature sensor | ++-----------+------------+-------------------------------------+ + + +Start Application Development +***************************** + +Before powering up your M5Stack AtomS3, please make sure that the board is in good +condition with no obvious signs of damage. + +System requirements +=================== + +Prerequisites +------------- + +Espressif HAL requires WiFi and Bluetooth binary blobs in order work. Run the command +below to retrieve those files. + +.. code-block:: shell + + west blobs fetch hal_espressif + +.. note:: + + It is recommended running the command above after :file:`west update`. + +Building & Flashing +------------------- + +Build and flash applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: m5stack_atoms3 + :goals: build + +The usual ``flash`` target will work with the ``m5stack_atoms3`` board +configuration. Here is an example for the :ref:`hello_world` +application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: m5stack_atoms3 + :goals: flash + +The baud rate of 921600bps is set by default. If experiencing issues when flashing, +try using different values by using ``--esp-baud-rate `` option during +``west flash`` (e.g. ``west flash --esp-baud-rate 115200``). + +You can also open the serial monitor using the following command: + +.. code-block:: shell + + west espressif monitor + +After the board has automatically reset and booted, you should see the following +message in the monitor: + +.. code-block:: console + + ***** Booting Zephyr OS vx.x.x-xxx-gxxxxxxxxxxxx ***** + Hello World! m5stack_atoms3 + +Debugging +--------- + +M5Stack AtomS3 debugging is not supported due to pinout limitations. + +Related Documents +***************** + +- `M5Stack AtomS3 schematic `_ +- `ESP32S3 Datasheet `_ diff --git a/boards/xtensa/m5stack_atoms3/grove_connectors.dtsi b/boards/xtensa/m5stack_atoms3/grove_connectors.dtsi new file mode 100644 index 00000000000..798c40cf296 --- /dev/null +++ b/boards/xtensa/m5stack_atoms3/grove_connectors.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 Benjamin Cabé + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + grove_header: grove_header { + compatible = "grove-header"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpio0 1 0>, + <1 0 &gpio0 2 0>; + }; +}; + +grove_i2c1: &i2c1 {}; diff --git a/boards/xtensa/m5stack_atoms3/m5stack_atoms3-pinctrl.dtsi b/boards/xtensa/m5stack_atoms3/m5stack_atoms3-pinctrl.dtsi new file mode 100644 index 00000000000..0f59b0bc6a8 --- /dev/null +++ b/boards/xtensa/m5stack_atoms3/m5stack_atoms3-pinctrl.dtsi @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023 Benjamin Cabé + * + * SPDX-License-Identifier: Apache-2.0 + */ + + #include + #include + #include + +&pinctrl { + uart0_default: uart0_default { + group1 { + pinmux = ; + output-high; + }; + group2 { + pinmux = ; + bias-pull-up; + }; + }; + + i2c0_default: i2c0_default { + group1 { + pinmux = , + ; + bias-pull-up; + drive-open-drain; + output-high; + }; + }; + + i2c1_default: i2c1_default { + group1 { + pinmux = , + ; + bias-pull-up; + drive-open-drain; + output-high; + }; + }; + + spim2_default: spim2_default { + group1 { + pinmux = , + ; + }; + group2 { + pinmux = ; + output-low; + }; + + }; +}; diff --git a/boards/xtensa/m5stack_atoms3/m5stack_atoms3.dts b/boards/xtensa/m5stack_atoms3/m5stack_atoms3.dts new file mode 100644 index 00000000000..abbff8bbbfd --- /dev/null +++ b/boards/xtensa/m5stack_atoms3/m5stack_atoms3.dts @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2023 Benjamin Cabé + * + * SPDX-License-Identifier: Apache-2.0 + */ +/dts-v1/; + +#include +#include "m5stack_atoms3-pinctrl.dtsi" +#include "grove_connectors.dtsi" +#include + +/ { + model = "M5Stack AtomS3"; + compatible = "m5stack,atoms3"; + + chosen { + zephyr,sram = &sram0; + zephyr,console = &usb_serial; + zephyr,shell-uart = &usb_serial; + zephyr,flash = &flash0; + zephyr,display = &st7789v; + }; + + aliases { + sw0 = &user_button_0; + watchdog0 = &wdt0; + accel0 = &mpu6886; + }; + + gpio_keys { + compatible = "gpio-keys"; + + /* This is the button that's underneath the LCD display */ + user_button_0: button_0 { + label = "User button 0"; + gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; // G42 + zephyr,code = ; + }; + }; + + /* Regulators */ + lcd_backlight_en { + compatible = "regulator-fixed"; + regulator-name = "lcd_backlight_enable"; + enable-gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>; + regulator-boot-on; + }; + +}; + +&cpu0 { + clock-frequency = ; +}; + +&cpu1 { + clock-frequency = ; +}; + +&usb_serial { + status = "okay"; +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; +}; + +&i2c0 { + status = "okay"; + clock-frequency = ; + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; + + mpu6886: mpu6886@68 { + compatible = "invensense,mpu6050"; + reg = <0x68>; + status = "okay"; + }; +}; + +&i2c1 { + status = "okay"; + clock-frequency = ; + pinctrl-0 = <&i2c1_default>; + pinctrl-names = "default"; +}; + +&trng0 { + status = "okay"; +}; + +&spi2 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + pinctrl-0 = <&spim2_default>; + pinctrl-names = "default"; + + st7789v: st7789v@0 { + compatible = "sitronix,st7789v"; + reg = <0>; + spi-max-frequency = <27000000>; + cmd-data-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>; /* G33 */ + reset-gpios = <&gpio1 2 GPIO_ACTIVE_LOW>; /* G34 */ + + width = <128>; + height = <128>; + x-offset = <2>; + y-offset = <1>; + + vcom = <0x28>; + gctrl = <0x35>; + vrhs = <0x10>; + vdvs = <0x20>; + mdac = <0x00>; + gamma = <0x01>; + colmod = <0x55>; + lcm = <0x0c>; + porch-param = [0c 0c 00 33 33]; + cmd2en-param = [5a 69 02 00]; + pwctrl1-param = [a4 a1]; + pvgam-param = [d0 00 02 07 0a 28 32 44 42 06 0e 12 14 17]; + nvgam-param = [d0 00 02 07 0a 28 31 54 47 0e 1c 17 1b 1e]; + ram-param = [00 E0]; + rgb-param = [40 02 14]; + }; + +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&wdt0 { + status = "okay"; +}; + +&timer0 { + status = "okay"; +}; + +&timer1 { + status = "okay"; +}; + +&flash0 { + status = "okay"; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x0000F000>; + read-only; + }; + + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 0x00100000>; + }; + + slot1_partition: partition@110000 { + label = "image-1"; + reg = <0x00110000 0x00100000>; + }; + + scratch_partition: partition@210000 { + label = "image-scratch"; + reg = <0x00210000 0x00040000>; + }; + + storage_partition: partition@250000 { + label = "storage"; + reg = <0x00250000 0x00006000>; + }; + }; +}; diff --git a/boards/xtensa/m5stack_atoms3/m5stack_atoms3.yaml b/boards/xtensa/m5stack_atoms3/m5stack_atoms3.yaml new file mode 100644 index 00000000000..ed34b2f551d --- /dev/null +++ b/boards/xtensa/m5stack_atoms3/m5stack_atoms3.yaml @@ -0,0 +1,21 @@ +identifier: m5stack_atoms3 +name: M5Stack AtomS3 +type: mcu +arch: xtensa +toolchain: + - zephyr +supported: + - gpio + - i2c + - spi + - watchdog + - regulator + - uart + - pinmux + - nvs + - display +testing: + ignore_tags: + - net + - bluetooth +vendor: m5stack diff --git a/boards/xtensa/m5stack_atoms3/m5stack_atoms3_defconfig b/boards/xtensa/m5stack_atoms3/m5stack_atoms3_defconfig new file mode 100644 index 00000000000..1000271dbe5 --- /dev/null +++ b/boards/xtensa/m5stack_atoms3/m5stack_atoms3_defconfig @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_BOARD_M5STACK_ATOMS3=y +CONFIG_SOC_SERIES_ESP32S3=y + +CONFIG_MAIN_STACK_SIZE=2048 + +CONFIG_GPIO=y +CONFIG_REGULATOR=y # for LCD backlight + +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y diff --git a/boards/xtensa/m5stack_core2/Kconfig.board b/boards/xtensa/m5stack_core2/Kconfig.board new file mode 100644 index 00000000000..9b48a15c24d --- /dev/null +++ b/boards/xtensa/m5stack_core2/Kconfig.board @@ -0,0 +1,12 @@ +# M5Stack Core2 board configuration + +# Copyright (c) 2023 Martin Kiepfer +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_M5STACK_CORE2 + bool "M5Stack Core2 Development Board" + depends on SOC_SERIES_ESP32 + +choice SOC_PART_NUMBER + default SOC_ESP32_D0WD_V3 +endchoice diff --git a/boards/xtensa/m5stack_core2/Kconfig.defconfig b/boards/xtensa/m5stack_core2/Kconfig.defconfig new file mode 100644 index 00000000000..08fc712b0d3 --- /dev/null +++ b/boards/xtensa/m5stack_core2/Kconfig.defconfig @@ -0,0 +1,42 @@ +# M5Stack Core2 board configuration +# Copyright (c) 2022 AVSystem Sławomir Wolf Sp.j. (AVSystem) +# Copyright (c) 2023 Martin Kiepfer +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_M5STACK_CORE2 + +config BOARD + default "m5stack_core2" + depends on BOARD_M5STACK_CORE2 + +config ENTROPY_GENERATOR + default y + +config HEAP_MEM_POOL_SIZE + default 98304 if WIFI + default 65536 if BT + default 4096 + +config KERNEL_MEM_POOL + default y + +choice BT_HCI_BUS_TYPE + default BT_ESP32 if BT +endchoice + +config REGULATOR_AXP192_INIT_PRIORITY + default 81 + +config GPIO_HOGS_INIT_PRIORITY + default 82 + +config INPUT_FT5336_INTERRUPT + default y if INPUT + +config INPUT + default y + +config LV_COLOR_16_SWAP + default y if LVGL + +endif # BOARD_M5STACK_CORE2 diff --git a/boards/xtensa/m5stack_core2/board.cmake b/boards/xtensa/m5stack_core2/board.cmake new file mode 100644 index 00000000000..2f04d1fe886 --- /dev/null +++ b/boards/xtensa/m5stack_core2/board.cmake @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +if(NOT "${OPENOCD}" MATCHES "^${ESPRESSIF_TOOLCHAIN_PATH}/.*") + set(OPENOCD OPENOCD-NOTFOUND) +endif() +find_program(OPENOCD openocd PATHS ${ESPRESSIF_TOOLCHAIN_PATH}/openocd-esp32/bin NO_DEFAULT_PATH) + +include(${ZEPHYR_BASE}/boards/common/esp32.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/xtensa/m5stack_core2/doc/img/m5stack_core2.webp b/boards/xtensa/m5stack_core2/doc/img/m5stack_core2.webp new file mode 100644 index 00000000000..794c8e4c9cb Binary files /dev/null and b/boards/xtensa/m5stack_core2/doc/img/m5stack_core2.webp differ diff --git a/boards/xtensa/m5stack_core2/doc/index.rst b/boards/xtensa/m5stack_core2/doc/index.rst new file mode 100644 index 00000000000..4ca27c546f5 --- /dev/null +++ b/boards/xtensa/m5stack_core2/doc/index.rst @@ -0,0 +1,195 @@ +.. _m5stack_core2: + +M5Stack Core2 +############# + +Overview +******** + +M5Stack Core2 is an ESP32-based development board from M5Stack. It is the successor for the Core module. + +M5Stack Core2 features the following integrated components: + +- ESP32-D0WDQ6-V3 chip (240MHz dual core, 600 DMIPS, 520KB SRAM, Wi-Fi) +- PSRAM 8MB +- Flash 16MB +- LCD IPS TFT 2", 320x240 px screen (ILI9342C) +- Touch screen (FT6336U) +- PMU AXP192 +- Audio NS4168 amplifier (1W-092 speaker) +- Vibration motor +- RTC BM8563 +- USB CP2104 +- SD-Card slot +- IMO 6-axis IMU MPU6886 +- MIC SPM1423 +- Battery 390mAh 3,7V + +.. figure:: img/m5stack_core2.webp + :align: center + :alt: M5Stack-Core2 + :width: 400 px + + M5Stack-Core2 module + +Functional Description +********************** + +The following table below describes the key components, interfaces, and controls +of the M5Stack Core2 board. + +.. _M5Core2 Schematic: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/schematic/Core/CORE2_V1.0_SCH.pdf +.. _MPU-ESP32: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/esp32_datasheet_en_v3.9.pdf +.. _TOUCH-FT6336U: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/Ft6336GU_Firmware%20外部寄存器_20151112-%20EN.xlsx +.. _SND-NS4168: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/NS4168_CN_datasheet.pdf +.. _MPU-6886: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/MPU-6886-000193%2Bv1.1_GHIC_en.pdf +.. _LCD-ILI9342C: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/ILI9342C-ILITEK.pdf +.. _SPM-1423: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/SPM1423HM4H-B_datasheet_en.pdf +.. _RTC-BM8563: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/BM8563_V1.1_cn.pdf +.. _SY7088: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/SY7088-Silergy.pdf +.. _PMU-AXP192: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/AXP192_datasheet_en.pdf +.. _VIB-1072_RFN01: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/1027RFN01-33d.pdf + ++------------------+--------------------------------------------------------------------------+ +| Key Component | Description | ++==================+==========================================================================+ +|| ESP32-D0WDQ6-V2 || This `MPU-ESP32`_ module provides complete Wi-Fi and Bluetooth | +|| module || functionalities and integrates a 16-MB SPI flash. | ++------------------+--------------------------------------------------------------------------+ +|| 32.768 kHz RTC || External precision 32.768 kHz crystal oscillator serves as a clock with | +|| || low-power consumption while the chip is in Deep-sleep mode. | ++------------------+--------------------------------------------------------------------------+ +| Status LED | One user LED connected to the GPIO pin. | ++------------------+--------------------------------------------------------------------------+ +|| USB Port || USB interface. Power supply for the board as well as the | +|| || communication interface between a computer and the board. | +|| || Contains: TypeC x 1, GROVE(I2C+I/O+UART) x 1 | ++------------------+--------------------------------------------------------------------------+ +| Reset button | Reset button | ++------------------+--------------------------------------------------------------------------+ +| Power Switch | Power on/off button. | ++------------------+--------------------------------------------------------------------------+ +|| LCD screen || Built-in LCD TFT display \(`LCD-ILI9342C`_, 2", 320x240 px\) | +|| || controlled via SPI interface | ++------------------+--------------------------------------------------------------------------+ +|| 6-axis IMU || The `MPU-6886`_ is a 6-axis motion tracker (6DOF IMU) device that | +|| MPU6886 || combines a 3-axis gyroscope and a 3-axis accelerometer. | +|| || For details please refer to :ref:`m5stack_core2_ext` | ++------------------+--------------------------------------------------------------------------+ +|| Built-in || The `SPM-1423`_ I2S driven microphone. | +|| microphone || | ++------------------+--------------------------------------------------------------------------+ +| Built-in speaker | 1W speaker for audio output via I2S interface. | ++------------------+--------------------------------------------------------------------------+ + +Supported Features +================== + +The Zephyr m5stack_core2 board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c | ++-----------+------------+-------------------------------------+ +| SPI | on-chip | spi | ++-----------+------------+-------------------------------------+ +| CLOCK | on-chip | reset and clock control | ++-----------+------------+-------------------------------------+ +| COUNTER | on-chip | rtc | ++-----------+------------+-------------------------------------+ +| WATCHDOG | on-chip | independent watchdog | ++-----------+------------+-------------------------------------+ +| PWM | on-chip | pwm | ++-----------+------------+-------------------------------------+ +| ADC | on-chip | adc | ++-----------+------------+-------------------------------------+ +| DAC | on-chip | dac | ++-----------+------------+-------------------------------------+ +| die-temp | on-chip | die temperature sensor | ++-----------+------------+-------------------------------------+ + + +Start Application Development +***************************** + +Before powering up your M5Stack Core2, please make sure that the board is in good +condition with no obvious signs of damage. + +System requirements +=================== + +Prerequisites +------------- + +Espressif HAL requires WiFi and Bluetooth binary blobs in order work. Run the command +below to retrieve those files. + +.. code-block:: console + + west blobs fetch hal_espressif + +.. note:: + + It is recommended running the command above after :file:`west update`. + +Building & Flashing +------------------- + +Build and flash applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: m5stack_core2 + :goals: build + +The usual ``flash`` target will work with the ``m5stack_core2`` board +configuration. Here is an example for the :ref:`hello_world` +application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: m5stack_core2 + :goals: flash + +The baud rate of 921600bps is set by default. If experiencing issues when flashing, +try using different values by using ``--esp-baud-rate `` option during +``west flash`` (e.g. ``west flash --esp-baud-rate 115200``). + +You can also open the serial monitor using the following command: + +.. code-block:: shell + + west espressif monitor + +After the board has automatically reset and booted, you should see the following +message in the monitor: + +.. code-block:: console + + ***** Booting Zephyr OS vx.x.x-xxx-gxxxxxxxxxxxx ***** + Hello World! m5stack_core2 + +Debugging +--------- + +M5Stack Core2 debugging is not supported due to pinout limitations. + +Related Documents +***************** + +- `M5StickC PLUS schematic `_ (WEBP) +- `ESP32-PICO-D4 Datasheet `_ (PDF) +- `M5StickC PLUS docs `_ +- `ESP32 Datasheet `_ (PDF) +- `ESP32 Hardware Reference `_ diff --git a/boards/xtensa/m5stack_core2/grove_connectors.dtsi b/boards/xtensa/m5stack_core2/grove_connectors.dtsi new file mode 100644 index 00000000000..3a49570382d --- /dev/null +++ b/boards/xtensa/m5stack_core2/grove_connectors.dtsi @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Joel Guittet + * Copyright (c) 2023 Martin Kiepfer + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + grove_header: grove_header { + compatible = "grove-header"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpio1 1 0>, /* D0/SCL/RX */ + <1 0 &gpio1 0 0>; /* D1/SDA/TX */ + }; +}; + +grove_i2c: &i2c1 {}; +grove_uart: &uart1 {}; diff --git a/boards/xtensa/m5stack_core2/m5stack_core2-pinctrl.dtsi b/boards/xtensa/m5stack_core2/m5stack_core2-pinctrl.dtsi new file mode 100644 index 00000000000..ac0908ac62a --- /dev/null +++ b/boards/xtensa/m5stack_core2/m5stack_core2-pinctrl.dtsi @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2022 AVSystem Sławomir Wolf Sp.j. (AVSystem) + * Copyright (c) 2023 Martin Kiepfer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +&pinctrl { + + uart0_tx_gpio1: uart0_tx_gpio1 { + pinmux = ; + }; + + uart0_rx_gpio3: uart0_rx_gpio3 { + pinmux = ; + bias-pull-up; + }; + + uart1_rx_gpio33: uart1_rx_gpio33 { + pinmux = ; + }; + + uart2_rx_gpio13: uart2_rx_gpio13 { + pinmux = ; + }; + + uart2_tx_gpio14: uart2_rx_gpio14 { + pinmux = ; + }; + + uart1_tx_gpio32: uart1_tx_gpio32 { + pinmux = ; + }; + + spim3_default: spim3_default { + group1 { + pinmux = , + , + ; + }; + group2 { + pinmux = ; + output-low; + }; + }; + + spim2_default: spim2_default { + group1 { + pinmux = , + , + ; + }; + group2 { + pinmux = ; + output-low; + }; + }; + + i2c0_default: i2c0_default { + group1 { + pinmux = , + ; + drive-open-drain; + output-high; + }; + }; + + i2c1_default: i2c1_default { + group1 { + pinmux = , + ; + drive-open-drain; + output-high; + }; + }; + +}; diff --git a/boards/xtensa/m5stack_core2/m5stack_core2.dts b/boards/xtensa/m5stack_core2/m5stack_core2.dts new file mode 100644 index 00000000000..41ccb5be074 --- /dev/null +++ b/boards/xtensa/m5stack_core2/m5stack_core2.dts @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2023 Martin Kiepfer + * + * SPDX-License-Identifier: Apache-2.0 + */ +/dts-v1/; + +#include +#include "m5stack_core2-pinctrl.dtsi" +#include "grove_connectors.dtsi" +#include "m5stack_mbus_connectors.dtsi" +#include +#include + +/ { + model = "M5Stack Core2"; + compatible = "m5stack,core2"; + + aliases { + pwr-led = &pwr_led; + uart-0 = &uart0; + i2c-0 = &i2c0; + watchdog0 = &wdt0; + rtc = &pfc8563_rtc; + led0 = &led_pwr; + }; + + chosen { + zephyr,sram = &sram0; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,flash = &flash0; + zephyr,display = &ili9342c; + zephyr,code-partition = &slot0_partition; + zephyr,rtc = &pfc8563_rtc; + }; + + leds { + compatible = "gpio-leds"; + led_pwr: led_pwr { + gpios = <&axp192_gpio 1 (GPIO_OPEN_DRAIN | GPIO_ACTIVE_LOW)>; + label = "Power LED"; + }; + }; + + lvgl_pointer { + compatible = "zephyr,lvgl-pointer-input"; + input = <&ft5336_touch>; + }; +}; + +&cpu0 { + clock-frequency = ; +}; + +&cpu1 { + clock-frequency = ; +}; + +&psram0 { + reg = <0x3f800000 DT_SIZE_M(8)>; + status = "disabled"; +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart0_tx_gpio1 &uart0_rx_gpio3>; + pinctrl-names = "default"; +}; + +&uart1 { + status = "disabled"; + current-speed = <115200>; + pinctrl-0 = <&uart1_rx_gpio33 &uart1_tx_gpio32>; + pinctrl-names = "default"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + clock-frequency = ; + sda-gpios = <&gpio0 21 GPIO_OPEN_DRAIN>; + scl-gpios = <&gpio0 22 GPIO_OPEN_DRAIN>; + pinctrl-0 = <&i2c0_default>; + scl-timeout-us = <0>; + pinctrl-names = "default"; + + pfc8563_rtc: pfc8563@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + status = "okay"; + }; + + axp192_pmic: axp192@34 { + compatible = "x-powers,axp192"; + reg = <0x34>; + status = "okay"; + + axp192_regulator: axp192_regulator { + compatible = "x-powers,axp192-regulator"; + status = "okay"; + + vdd_mcu: DCDC1 { + regulator-init-microvolt = <3350000>; + regulator-min-microvolt = <3200000>; + regulator-max-microvolt = <3400000>; + regulator-initial-mode = ; + regulator-boot-on; + regulator-always-on; + }; + + lcd_bg: DCDC3 { + regulator-init-microvolt = <2800000>; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + + v_peri: LDO2 { + regulator-init-microvolt = <3300000>; + regulator-min-microvolt = <3200000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + + vib_motor: LDO3 { + regulator-init-microvolt = <2800000>; + }; + }; + + axp192_gpio: axp192_gpio { + compatible = "x-powers,axp192-gpio"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <5>; + status = "okay"; + + pwr_led: axp192_gpio1 { + gpio-hog; + gpios = <1 (GPIO_OPEN_DRAIN | GPIO_ACTIVE_LOW)>; + output-high; + line-name = "pwr-led"; + }; + + bus_pwr_en: axp192_gpio0 { + gpio-hog; + gpios = <0 0>; + input; + }; + }; + }; + + ft5336_touch: ft5336@38 { + compatible = "focaltech,ft5336"; + reg = <0x38>; + int-gpios = <&gpio1 7 0>; + }; +}; + +&i2c1 { + status = "disabled"; + clock-frequency = ; + sda-gpios = <&gpio1 0 GPIO_OPEN_DRAIN>; + scl-gpios = <&gpio1 1 GPIO_OPEN_DRAIN>; + pinctrl-0 = <&i2c1_default>; + pinctrl-names = "default"; +}; + +&spi3 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + pinctrl-0 = <&spim3_default>; + pinctrl-names = "default"; + dma-enabled; + clock-frequency = <20000000>; + cs-gpios = <&gpio0 5 GPIO_ACTIVE_LOW>; + + ili9342c: ili9342c@0 { + compatible = "ilitek,ili9342c"; + spi-max-frequency = <30000000>; + reg = <0>; + cmd-data-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + vin-supply = <&lcd_bg>; + reset-gpios = <&axp192_gpio 4 (GPIO_OPEN_DRAIN | GPIO_ACTIVE_LOW)>; + pixel-format = ; + display-inversion; + width = <320>; + height = <240>; + rotation = <0>; + }; +}; + + +&timer0 { + status = "okay"; +}; + +&timer1 { + status = "okay"; +}; + +&timer2 { + status = "okay"; +}; + +&timer3 { + status = "okay"; +}; + +&trng0 { + status = "okay"; +}; + +&flash0 { + status = "okay"; + reg = <0 DT_SIZE_M(16)>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserve 60kB for the bootloader */ + boot_partition: partition@1000 { + label = "mcuboot"; + reg = <0x00001000 0x0000F000>; + read-only; + }; + + /* Reserve 1024kB for the application in slot 0 */ + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 0x00100000>; + }; + + /* Reserve 1024kB for the application in slot 1 */ + slot1_partition: partition@110000 { + label = "image-1"; + reg = <0x00110000 0x00100000>; + }; + + /* Reserve 256kB for the scratch partition */ + scratch_partition: partition@210000 { + label = "image-scratch"; + reg = <0x00210000 0x00040000>; + }; + + /* 14MB storage */ + storage_partition: partition@250000 { + label = "storage"; + reg = <0x00250000 0x00db0000>; + }; + }; +}; diff --git a/boards/xtensa/m5stack_core2/m5stack_core2.yaml b/boards/xtensa/m5stack_core2/m5stack_core2.yaml new file mode 100644 index 00000000000..78b361e8834 --- /dev/null +++ b/boards/xtensa/m5stack_core2/m5stack_core2.yaml @@ -0,0 +1,20 @@ +identifier: m5stack_core2 +name: M5Stack Core2 +type: mcu +arch: xtensa +toolchain: + - zephyr +supported: + - gpio + - i2c + - spi + - watchdog + - regulator + - uart + - pinmux + - nvs +testing: + ignore_tags: + - net + - bluetooth +vendor: m5stack diff --git a/boards/xtensa/m5stack_core2/m5stack_core2_defconfig b/boards/xtensa/m5stack_core2/m5stack_core2_defconfig new file mode 100644 index 00000000000..10fde73b477 --- /dev/null +++ b/boards/xtensa/m5stack_core2/m5stack_core2_defconfig @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_BOARD_M5STACK_CORE2=y + +CONFIG_SOC_SERIES_ESP32=y + +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_ESP_HEAP_MEM_POOL_REGION_1_SIZE=0 + +CONFIG_GPIO=y + +CONFIG_REGULATOR=y + +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y + +# for debugging +CONFIG_SHELL=y diff --git a/boards/xtensa/m5stack_core2/m5stack_mbus_connectors.dtsi b/boards/xtensa/m5stack_core2/m5stack_mbus_connectors.dtsi new file mode 100644 index 00000000000..9929b8dc879 --- /dev/null +++ b/boards/xtensa/m5stack_core2/m5stack_mbus_connectors.dtsi @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2023 Martin Kiepfer + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + m5stack_mbus_header: m5stack_mbus_connector { + compatible = "m5stack,mbus-header"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = /* 0 GND */ + <1 0 &gpio1 4 0>, /* ADC0 */ + /* 2 GND */ + <3 0 &gpio1 5 0>, /* ADC1 */ + /* 4 GND */ + /* 5 RESET */ + <6 0 &gpio0 23 0>, /* MOSI */ + <7 0 &gpio0 25 0>, /* DAC0 */ + <8 0 &gpio1 7 0>, /* MISO */ + <9 0 &gpio0 26 0>, /* DAC1 */ + <10 0 &gpio0 18 0>, /* SCK */ + /* 11 3.3V */ + <12 0 &gpio0 3 0>, /* RXD0 */ + <13 0 &gpio0 1 0>, /* TXD0 */ + <14 0 &gpio0 13 0>, /* RXD1 */ + <15 0 &gpio0 14 0>, /* TXD1 */ + <16 0 &gpio0 21 0>, /* intSDA */ + <17 0 &gpio0 22 0>, /* intSCL */ + <18 0 &gpio1 0 0>, /* SDA */ + <19 0 &gpio1 1 0>, /* SCL */ + <20 0 &gpio0 27 0>, /* GPIO */ + <21 0 &gpio0 19 0>, /* GPIO */ + <22 0 &gpio0 2 0>, /* GPIO */ + <23 0 &gpio0 0 0>, /* GPIO */ + /* 24 NC */ + <25 0 &gpio1 3 0>; /* GPIO */ + /* 26 NC */ + /* 27 5V */ + /* 28 NC */ + /* 29 BAT */ + }; +}; + +m5stack_mbus_i2c0: &i2c0 {}; +m5stack_mbus_i2c1: &i2c1 {}; +m5stack_mbus_uart0: &uart1 {}; +m5stack_mbus_uart1: &uart2 {}; +m5stack_mbus_spi: &spi3 {}; diff --git a/boards/xtensa/m5stack_core2/support/openocd.cfg b/boards/xtensa/m5stack_core2/support/openocd.cfg new file mode 100644 index 00000000000..338e6e4e6ea --- /dev/null +++ b/boards/xtensa/m5stack_core2/support/openocd.cfg @@ -0,0 +1,5 @@ +set ESP_RTOS none +set ESP32_ONLYCPU 1 + +source [find interface/ftdi/esp32_devkitj_v1.cfg] +source [find target/esp32.cfg] diff --git a/boards/xtensa/m5stickc_plus/doc/index.rst b/boards/xtensa/m5stickc_plus/doc/index.rst index f015fe3feee..1b042f4f30f 100644 --- a/boards/xtensa/m5stickc_plus/doc/index.rst +++ b/boards/xtensa/m5stickc_plus/doc/index.rst @@ -117,7 +117,7 @@ Sysbuild ======== The sysbuild makes possible to build and flash all necessary images needed to -bootstrap the board with the EPS32 SoC. +bootstrap the board with the ESP32 SoC. To build the sample application using sysbuild use the command: diff --git a/boards/xtensa/m5stickc_plus/m5stickc_plus.dts b/boards/xtensa/m5stickc_plus/m5stickc_plus.dts index 0254d82003d..8cdd4170ba5 100644 --- a/boards/xtensa/m5stickc_plus/m5stickc_plus.dts +++ b/boards/xtensa/m5stickc_plus/m5stickc_plus.dts @@ -10,8 +10,8 @@ #include / { - model = "esp32"; - compatible = "espressif,esp32"; + model = "M5StickC Plus"; + compatible = "m5stack,m5stickc-plus"; aliases { led0 = &red_led; diff --git a/boards/xtensa/m5stickc_plus/m5stickc_plus.yaml b/boards/xtensa/m5stickc_plus/m5stickc_plus.yaml index d648d4119e4..821770c2be4 100644 --- a/boards/xtensa/m5stickc_plus/m5stickc_plus.yaml +++ b/boards/xtensa/m5stickc_plus/m5stickc_plus.yaml @@ -16,3 +16,4 @@ testing: ignore_tags: - net - bluetooth +vendor: m5stack diff --git a/boards/xtensa/nxp_adsp_imx8/Kconfig.board b/boards/xtensa/nxp_adsp_imx8/Kconfig.board index e24c0a45316..4bb4f564040 100644 --- a/boards/xtensa/nxp_adsp_imx8/Kconfig.board +++ b/boards/xtensa/nxp_adsp_imx8/Kconfig.board @@ -5,3 +5,5 @@ config BOARD_NXP_ADSP_IMX8 bool "NXP ADSP i.MX8" + depends on SOC_SERIES_NXP_IMX8 + select SOC_PART_NUMBER_MIMX8QM6AVUFF diff --git a/boards/xtensa/nxp_adsp_imx8/Kconfig.defconfig b/boards/xtensa/nxp_adsp_imx8/Kconfig.defconfig index f72d1a4e11f..04aa0aa6ed3 100644 --- a/boards/xtensa/nxp_adsp_imx8/Kconfig.defconfig +++ b/boards/xtensa/nxp_adsp_imx8/Kconfig.defconfig @@ -7,15 +7,4 @@ if BOARD_NXP_ADSP_IMX8 config BOARD default "nxp_adsp_imx8" -config DUMMY_DMA - bool - default y - depends on DMA - -config IMX_EDMA - bool - default y - depends on DMA - - endif # BOARD_NXP_ADSP_IMX8 diff --git a/boards/xtensa/nxp_adsp_imx8/nxp_adsp_imx8-pinctrl.dtsi b/boards/xtensa/nxp_adsp_imx8/nxp_adsp_imx8-pinctrl.dtsi new file mode 100644 index 00000000000..a6291a5d4b8 --- /dev/null +++ b/boards/xtensa/nxp_adsp_imx8/nxp_adsp_imx8-pinctrl.dtsi @@ -0,0 +1,26 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&iomuxc { + iomuxc_uart2_rx_uart0_rts_b: IOMUXC_UART2_RX_UART0_RTS_B { + pinmux = ; + }; + + iomuxc_uart2_tx_uart0_cts_b: IOMUXC_UART2_TX_UART0_CTS_B { + pinmux = ; + }; +}; + +&pinctrl { + lpuart2_default: lpuart2_default { + group0 { + pinmux = <&iomuxc_uart2_rx_uart0_rts_b>, + <&iomuxc_uart2_tx_uart0_cts_b>; + }; + }; +}; diff --git a/boards/xtensa/nxp_adsp_imx8/nxp_adsp_imx8.dts b/boards/xtensa/nxp_adsp_imx8/nxp_adsp_imx8.dts index 51d3162134a..a17690109ec 100644 --- a/boards/xtensa/nxp_adsp_imx8/nxp_adsp_imx8.dts +++ b/boards/xtensa/nxp_adsp_imx8/nxp_adsp_imx8.dts @@ -7,6 +7,7 @@ /dts-v1/; #include +#include "nxp_adsp_imx8-pinctrl.dtsi" / { model = "nxp_adsp_imx8"; @@ -14,5 +15,14 @@ chosen { zephyr,sram = &sram0; + zephyr,console = &lpuart2; + zephyr,shell-uart = &lpuart2; }; }; + +&lpuart2 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&lpuart2_default>; + pinctrl-names = "default"; +}; diff --git a/boards/xtensa/nxp_adsp_imx8/nxp_adsp_imx8.yaml b/boards/xtensa/nxp_adsp_imx8/nxp_adsp_imx8.yaml index 60aa0482822..b2ab9b227a9 100644 --- a/boards/xtensa/nxp_adsp_imx8/nxp_adsp_imx8.yaml +++ b/boards/xtensa/nxp_adsp_imx8/nxp_adsp_imx8.yaml @@ -8,3 +8,4 @@ testing: only_tags: - kernel - sof +vendor: nxp diff --git a/boards/xtensa/nxp_adsp_imx8/nxp_adsp_imx8_defconfig b/boards/xtensa/nxp_adsp_imx8/nxp_adsp_imx8_defconfig index 3d0c02d5017..a16d8be5e2e 100644 --- a/boards/xtensa/nxp_adsp_imx8/nxp_adsp_imx8_defconfig +++ b/boards/xtensa/nxp_adsp_imx8/nxp_adsp_imx8_defconfig @@ -2,21 +2,21 @@ CONFIG_MAIN_STACK_SIZE=3072 +# board/soc-related configurations CONFIG_SOC_SERIES_NXP_IMX8=y +CONFIG_SOC_MIMX8QM_ADSP=y CONFIG_BOARD_NXP_ADSP_IMX8=y -CONFIG_GEN_ISR_TABLES=y -CONFIG_GEN_IRQ_VECTOR_TABLE=n - -CONFIG_XTENSA_RESET_VECTOR=y - -CONFIG_XTENSA_USE_CORE_CRT1=y - -CONFIG_XTENSA_SMALL_VECTOR_TABLE_ENTRY=y - -CONFIG_MULTI_LEVEL_INTERRUPTS=n -CONFIG_2ND_LEVEL_INTERRUPTS=n +CONFIG_LOG=y +# TODO: maybe move this to SOF? +CONFIG_DYNAMIC_INTERRUPTS=y CONFIG_BUILD_OUTPUT_BIN=n -CONFIG_DCACHE_LINE_SIZE=128 +# clock-related configurations +CONFIG_CLOCK_CONTROL=y + +# serial-related configurations +CONFIG_SERIAL=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y diff --git a/boards/xtensa/nxp_adsp_imx8m/Kconfig.defconfig b/boards/xtensa/nxp_adsp_imx8m/Kconfig.defconfig index 628c8bfd0b4..344449dd744 100644 --- a/boards/xtensa/nxp_adsp_imx8m/Kconfig.defconfig +++ b/boards/xtensa/nxp_adsp_imx8m/Kconfig.defconfig @@ -1,4 +1,4 @@ -# Copyright (c) 2021 NXP +# Copyright 2021, 2023 NXP # # SPDX-License-Identifier: Apache-2.0 @@ -7,14 +7,4 @@ if BOARD_NXP_ADSP_IMX8M config BOARD default "nxp_adsp_imx8m" -config DUMMY_DMA - bool - default y - depends on DMA - -config IMX_SDMA - bool - default y - depends on DMA - endif # BOARD_NXP_ADSP_IMX8M diff --git a/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m.dts b/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m.dts index bc5b663f57d..6a0d7508deb 100644 --- a/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m.dts +++ b/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m.dts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 NXP + * Copyright 2021, 2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,7 +22,7 @@ }; &pinctrl { - /omit-if-no-ref/ uart4_default: uart4_default { + uart4_default: uart4_default { group0 { pinmux = <&iomuxc_uart4_rxd_uart_rx_uart4_rx>, <&iomuxc_uart4_txd_uart_tx_uart4_tx>; diff --git a/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m.yaml b/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m.yaml index 675db668f13..ef0bbdfe0ff 100644 --- a/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m.yaml +++ b/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m.yaml @@ -3,11 +3,14 @@ name: NXP i.MX8M Plus EVK Audio DSP type: mcu arch: xtensa toolchain: + - xcc + - xt-clang - zephyr -testing: - only_tags: - - kernel - - sof - - ipm supported: - uart +testing: + ignore_tags: + - net + - bluetooth + - mcumgr +vendor: nxp diff --git a/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m_defconfig b/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m_defconfig index f3b4ca76cbe..72ccd09f55a 100644 --- a/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m_defconfig +++ b/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m_defconfig @@ -1,27 +1,18 @@ # SPDX-License-Identifier: Apache-2.0 -CONFIG_MAIN_STACK_SIZE=3072 - CONFIG_SOC_SERIES_NXP_IMX8M=y CONFIG_SOC_MIMX8M_ADSP=y CONFIG_BOARD_NXP_ADSP_IMX8M=y -CONFIG_GEN_ISR_TABLES=y -CONFIG_GEN_IRQ_VECTOR_TABLE=n - -CONFIG_XTENSA_RESET_VECTOR=y - -CONFIG_XTENSA_USE_CORE_CRT1=y - -CONFIG_XTENSA_SMALL_VECTOR_TABLE_ENTRY=y +# size of stack for initialization and main thread +CONFIG_MAIN_STACK_SIZE=3072 -CONFIG_MULTI_LEVEL_INTERRUPTS=n -CONFIG_2ND_LEVEL_INTERRUPTS=n +# enable logger +CONFIG_LOG=y +# no need for a "raw" binary zephyr/zephyr.bin in the build directory CONFIG_BUILD_OUTPUT_BIN=n -CONFIG_DCACHE_LINE_SIZE=128 - # enable uart driver CONFIG_SERIAL=y diff --git a/boards/xtensa/nxp_adsp_imx8x/Kconfig.board b/boards/xtensa/nxp_adsp_imx8x/Kconfig.board index 7f4f7e0e3f9..7d5336ce7a7 100644 --- a/boards/xtensa/nxp_adsp_imx8x/Kconfig.board +++ b/boards/xtensa/nxp_adsp_imx8x/Kconfig.board @@ -5,3 +5,5 @@ config BOARD_NXP_ADSP_IMX8X bool "NXP ADSP i.MX8X" + depends on SOC_SERIES_NXP_IMX8 + select SOC_PART_NUMBER_MIMX8QX6AVLFZ diff --git a/boards/xtensa/nxp_adsp_imx8x/Kconfig.defconfig b/boards/xtensa/nxp_adsp_imx8x/Kconfig.defconfig index 31d42395503..a985696286a 100644 --- a/boards/xtensa/nxp_adsp_imx8x/Kconfig.defconfig +++ b/boards/xtensa/nxp_adsp_imx8x/Kconfig.defconfig @@ -7,14 +7,4 @@ if BOARD_NXP_ADSP_IMX8X config BOARD default "nxp_adsp_imx8x" -config DUMMY_DMA - bool - default y - depends on DMA - -config IMX_EDMA - bool - default y - depends on DMA - endif # BOARD_NXP_ADSP_IMX8X diff --git a/boards/xtensa/nxp_adsp_imx8x/nxp_adsp_imx8x-pinctrl.dtsi b/boards/xtensa/nxp_adsp_imx8x/nxp_adsp_imx8x-pinctrl.dtsi new file mode 100644 index 00000000000..18cfb473257 --- /dev/null +++ b/boards/xtensa/nxp_adsp_imx8x/nxp_adsp_imx8x-pinctrl.dtsi @@ -0,0 +1,26 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&iomuxc { + iomuxc_uart2_rx_uart2_rx: IOMUXC_UART2_RX_UART2_RX { + pinmux = ; + }; + + iomuxc_uart2_tx_uart2_tx: IOMUXC_UART2_TX_UART2_TX { + pinmux = ; + }; +}; + +&pinctrl { + lpuart2_default: lpuart2_default { + group0 { + pinmux = <&iomuxc_uart2_rx_uart2_rx>, + <&iomuxc_uart2_tx_uart2_tx>; + }; + }; +}; diff --git a/boards/xtensa/nxp_adsp_imx8x/nxp_adsp_imx8x.dts b/boards/xtensa/nxp_adsp_imx8x/nxp_adsp_imx8x.dts index bee8ccdb1a1..5aa0e59ebdd 100644 --- a/boards/xtensa/nxp_adsp_imx8x/nxp_adsp_imx8x.dts +++ b/boards/xtensa/nxp_adsp_imx8x/nxp_adsp_imx8x.dts @@ -7,6 +7,7 @@ /dts-v1/; #include +#include "nxp_adsp_imx8x-pinctrl.dtsi" / { model = "nxp_adsp_imx8x"; @@ -14,5 +15,14 @@ chosen { zephyr,sram = &sram0; + zephyr,console = &lpuart2; + zephyr,shell-uart = &lpuart2; }; }; + +&lpuart2 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&lpuart2_default>; + pinctrl-names = "default"; +}; diff --git a/boards/xtensa/nxp_adsp_imx8x/nxp_adsp_imx8x.yaml b/boards/xtensa/nxp_adsp_imx8x/nxp_adsp_imx8x.yaml index 3277fffc7d6..a343b8843c8 100644 --- a/boards/xtensa/nxp_adsp_imx8x/nxp_adsp_imx8x.yaml +++ b/boards/xtensa/nxp_adsp_imx8x/nxp_adsp_imx8x.yaml @@ -8,3 +8,4 @@ testing: only_tags: - kernel - sof +vendor: nxp diff --git a/boards/xtensa/nxp_adsp_imx8x/nxp_adsp_imx8x_defconfig b/boards/xtensa/nxp_adsp_imx8x/nxp_adsp_imx8x_defconfig index 92a66362cd0..0635e78adf8 100644 --- a/boards/xtensa/nxp_adsp_imx8x/nxp_adsp_imx8x_defconfig +++ b/boards/xtensa/nxp_adsp_imx8x/nxp_adsp_imx8x_defconfig @@ -2,21 +2,21 @@ CONFIG_MAIN_STACK_SIZE=3072 +# board/soc-related configurations CONFIG_SOC_SERIES_NXP_IMX8=y +CONFIG_SOC_MIMX8QXP_ADSP=y CONFIG_BOARD_NXP_ADSP_IMX8X=y -CONFIG_GEN_ISR_TABLES=y -CONFIG_GEN_IRQ_VECTOR_TABLE=n - -CONFIG_XTENSA_RESET_VECTOR=y - -CONFIG_XTENSA_USE_CORE_CRT1=y - -CONFIG_XTENSA_SMALL_VECTOR_TABLE_ENTRY=y - -CONFIG_MULTI_LEVEL_INTERRUPTS=n -CONFIG_2ND_LEVEL_INTERRUPTS=n +CONFIG_LOG=y +# TODO: maybe move this to SOF? +CONFIG_DYNAMIC_INTERRUPTS=y CONFIG_BUILD_OUTPUT_BIN=n -CONFIG_DCACHE_LINE_SIZE=128 +# clock-related configurations +CONFIG_CLOCK_CONTROL=y + +# serial-related configurations +CONFIG_SERIAL=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y diff --git a/boards/xtensa/nxp_adsp_rt595/Kconfig b/boards/xtensa/nxp_adsp_rt595/Kconfig new file mode 100644 index 00000000000..3c787188a9b --- /dev/null +++ b/boards/xtensa/nxp_adsp_rt595/Kconfig @@ -0,0 +1,41 @@ +# Copyright (c) 2023 Google LLC. +# SPDX-License-Identifier: Apache-2.0 + +DT_ADSP_RESET_MEM := $(dt_nodelabel_path,adsp_reset) +DT_ADSP_DATA_MEM := $(dt_nodelabel_path,adsp_data) +DT_ADSP_TEXT_MEM := $(dt_nodelabel_path,adsp_text) + +if BOARD_NXP_ADSP_RT595 + +config RT595_ADSP_STACK_SIZE + hex "Boot time stack size" + default 0x1000 + help + Stack space is reserved at the end of the RT595_ADSP_DATA_MEM + region, starting at RT595_ADSP_DATA_MEM_ADDR - RT595_ADSP_STACK_SIZE + +config RT595_ADSP_RESET_MEM_ADDR + hex + default $(dt_node_reg_addr_hex,$(DT_ADSP_RESET_MEM)) + +config RT595_ADSP_RESET_MEM_SIZE + hex + default $(dt_node_reg_size_hex,$(DT_ADSP_RESET_MEM)) + +config RT595_ADSP_DATA_MEM_ADDR + hex + default $(dt_node_reg_addr_hex,$(DT_ADSP_DATA_MEM)) + +config RT595_ADSP_DATA_MEM_SIZE + hex + default $(dt_node_reg_size_hex,$(DT_ADSP_DATA_MEM)) + +config RT595_ADSP_TEXT_MEM_ADDR + hex + default $(dt_node_reg_addr_hex,$(DT_ADSP_TEXT_MEM)) + +config RT595_ADSP_TEXT_MEM_SIZE + hex + default $(dt_node_reg_size_hex,$(DT_ADSP_TEXT_MEM)) + +endif # BOARD_NXP_ADSP_RT595 diff --git a/boards/xtensa/nxp_adsp_rt595/Kconfig.board b/boards/xtensa/nxp_adsp_rt595/Kconfig.board new file mode 100644 index 00000000000..a88eb58638f --- /dev/null +++ b/boards/xtensa/nxp_adsp_rt595/Kconfig.board @@ -0,0 +1,6 @@ +# Copyright (c) 2023 Google LLC. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_NXP_ADSP_RT595 + bool "NXP ADSP RT595" + depends on SOC_SERIES_NXP_RT5XX diff --git a/boards/xtensa/nxp_adsp_rt595/Kconfig.defconfig b/boards/xtensa/nxp_adsp_rt595/Kconfig.defconfig new file mode 100644 index 00000000000..7ffe782d28b --- /dev/null +++ b/boards/xtensa/nxp_adsp_rt595/Kconfig.defconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Google LLC. +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_NXP_ADSP_RT595 + +config BOARD + default "nxp_adsp_rt595" + +endif # BOARD_NXP_ADSP_RT595 diff --git a/boards/xtensa/nxp_adsp_rt595/nxp_adsp_rt595.dts b/boards/xtensa/nxp_adsp_rt595/nxp_adsp_rt595.dts new file mode 100644 index 00000000000..dc546c8db24 --- /dev/null +++ b/boards/xtensa/nxp_adsp_rt595/nxp_adsp_rt595.dts @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 Google LLC. + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include + +/ { + model = "nxp_adsp_rt595"; + compatible = "nxp"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "cdns,tensilica-xtensa-lx6"; + reg = <0>; + }; + }; + + sram0: memory@0 { + #address-cells = <1>; + #size-cells = <1>; + device_type = "memory"; + compatible = "mmio-sram"; + /* Reserve first 512kB of shared memory for ADSP. */ + reg = <0x0 DT_SIZE_K(512)>; + /* Reset section must always be at 0 and at least 1kB. */ + adsp_reset: memory@0 { + reg = <0x0 DT_SIZE_K(1)>; + }; + /* Code and data sections can be moved around and resized if needed. */ + adsp_text: memory@400 { + reg = <0x400 DT_SIZE_K(255)>; + }; + /* On RT595 ADSP shared RAM is mapped at offset 0 on the code bus and at + * offset 0x800000 on the data bus. + */ + adsp_data: memory@840000 { + reg = <0x840000 DT_SIZE_K(256)>; + }; + }; + + chosen { + zephyr,sram = &adsp_data; + }; +}; diff --git a/boards/xtensa/nxp_adsp_rt595/nxp_adsp_rt595.yaml b/boards/xtensa/nxp_adsp_rt595/nxp_adsp_rt595.yaml new file mode 100644 index 00000000000..09f61405d94 --- /dev/null +++ b/boards/xtensa/nxp_adsp_rt595/nxp_adsp_rt595.yaml @@ -0,0 +1,10 @@ +identifier: nxp_adsp_rt595 +name: i.MXRT595 DSP +type: mcu +arch: xtensa +toolchain: + - zephyr +testing: + only_tags: + - kernel +vendor: nxp diff --git a/boards/xtensa/nxp_adsp_rt595/nxp_adsp_rt595_defconfig b/boards/xtensa/nxp_adsp_rt595/nxp_adsp_rt595_defconfig new file mode 100644 index 00000000000..0e80f8a41a6 --- /dev/null +++ b/boards/xtensa/nxp_adsp_rt595/nxp_adsp_rt595_defconfig @@ -0,0 +1,7 @@ +CONFIG_SOC_SERIES_NXP_RT5XX=y +CONFIG_SOC_NXP_RT595=y +CONFIG_BOARD_NXP_ADSP_RT595=y + +CONFIG_GEN_ISR_TABLES=y +CONFIG_GEN_IRQ_VECTOR_TABLE=n +CONFIG_XTENSA_SMALL_VECTOR_TABLE_ENTRY=y diff --git a/boards/xtensa/odroid_go/doc/index.rst b/boards/xtensa/odroid_go/doc/index.rst index d53840882ce..933c167f535 100644 --- a/boards/xtensa/odroid_go/doc/index.rst +++ b/boards/xtensa/odroid_go/doc/index.rst @@ -128,7 +128,7 @@ Sysbuild ======== The sysbuild makes possible to build and flash all necessary images needed to -bootstrap the board with the EPS32 SoC. +bootstrap the board with the ESP32 SoC. To build the sample application using sysbuild use the command: diff --git a/boards/xtensa/odroid_go/odroid_go.yaml b/boards/xtensa/odroid_go/odroid_go.yaml index 5cbf1bb0d49..8a487018654 100644 --- a/boards/xtensa/odroid_go/odroid_go.yaml +++ b/boards/xtensa/odroid_go/odroid_go.yaml @@ -15,3 +15,4 @@ testing: ignore_tags: - net - bluetooth +vendor: hardkernel diff --git a/boards/xtensa/olimex_esp32_evb/doc/index.rst b/boards/xtensa/olimex_esp32_evb/doc/index.rst index 9f171498427..3bc02a82295 100644 --- a/boards/xtensa/olimex_esp32_evb/doc/index.rst +++ b/boards/xtensa/olimex_esp32_evb/doc/index.rst @@ -138,7 +138,7 @@ Sysbuild ======== The sysbuild makes possible to build and flash all necessary images needed to -bootstrap the board with the EPS32 SoC. +bootstrap the board with the ESP32 SoC. To build the sample application using sysbuild use the command: diff --git a/boards/xtensa/olimex_esp32_evb/olimex_esp32_evb.yaml b/boards/xtensa/olimex_esp32_evb/olimex_esp32_evb.yaml index 7240bdcf89a..83320db1529 100644 --- a/boards/xtensa/olimex_esp32_evb/olimex_esp32_evb.yaml +++ b/boards/xtensa/olimex_esp32_evb/olimex_esp32_evb.yaml @@ -17,3 +17,4 @@ testing: ignore_tags: - net - bluetooth +vendor: olimex diff --git a/boards/xtensa/qemu_xtensa/Kconfig.board b/boards/xtensa/qemu_xtensa/Kconfig.board index 43a0b1ce76e..34cdf44a15c 100644 --- a/boards/xtensa/qemu_xtensa/Kconfig.board +++ b/boards/xtensa/qemu_xtensa/Kconfig.board @@ -5,10 +5,13 @@ config BOARD_QEMU_XTENSA bool "Xtensa emulation using QEMU" - depends on SOC_XTENSA_SAMPLE_CONTROLLER + depends on SOC_XTENSA_DC233C select QEMU_TARGET + select ARCH_SUPPORTS_COREDUMP -config BOARD_QEMU_XTENSA_DC233C - bool "Xtensa emulation using QEMU (dc233c core)" +config BOARD_QEMU_XTENSA_MMU + bool "Xtensa emulation using QEMU with MMU" depends on SOC_XTENSA_DC233C select QEMU_TARGET + select ARCH_SUPPORTS_COREDUMP + select XTENSA_MMU diff --git a/boards/xtensa/qemu_xtensa/Kconfig.defconfig b/boards/xtensa/qemu_xtensa/Kconfig.defconfig index fdd0daec484..a6beed9151c 100644 --- a/boards/xtensa/qemu_xtensa/Kconfig.defconfig +++ b/boards/xtensa/qemu_xtensa/Kconfig.defconfig @@ -14,13 +14,13 @@ config IPM_CONSOLE_STACK_SIZE endif # BOARD_QEMU_XTENSA -if BOARD_QEMU_XTENSA_DC233C +if BOARD_QEMU_XTENSA_MMU config BUILD_OUTPUT_BIN default n config BOARD - default "qemu_xtensa_dc233c" + default "qemu_xtensa_mmu" config IPM_CONSOLE_STACK_SIZE default 2048 if IPM_CONSOLE_RECEIVER diff --git a/boards/xtensa/qemu_xtensa/board.cmake b/boards/xtensa/qemu_xtensa/board.cmake index 0dc60dfc7f4..56a6c358be4 100644 --- a/boards/xtensa/qemu_xtensa/board.cmake +++ b/boards/xtensa/qemu_xtensa/board.cmake @@ -2,13 +2,7 @@ set(SUPPORTED_EMU_PLATFORMS qemu) -if(CONFIG_BOARD_QEMU_XTENSA) - set(QEMU_CPU_TYPE_${ARCH} sample_controller) - - set(QEMU_FLAGS_${ARCH} - -machine sim -semihosting -nographic -cpu sample_controller - ) -elseif(CONFIG_BOARD_QEMU_XTENSA_DC233C) +if(CONFIG_BOARD_QEMU_XTENSA OR CONFIG_BOARD_QEMU_XTENSA_MMU) set(QEMU_CPU_TYPE_${ARCH} dc233c) set(QEMU_FLAGS_${ARCH} diff --git a/boards/xtensa/qemu_xtensa/doc/index.rst b/boards/xtensa/qemu_xtensa/doc/index.rst index 35f43ac59ae..1bc8b2b2ace 100644 --- a/boards/xtensa/qemu_xtensa/doc/index.rst +++ b/boards/xtensa/qemu_xtensa/doc/index.rst @@ -13,7 +13,7 @@ Programming and Debugging ************************* Use this configuration to run basic Zephyr applications and kernel tests in the QEMU -emulated environment, for example, with the :ref:`synchronization_sample`: +emulated environment, for example, with the :zephyr:code-sample:`synchronization` sample: .. zephyr-app-commands:: :zephyr-app: samples/synchronization diff --git a/boards/xtensa/qemu_xtensa/qemu_xtensa.dts b/boards/xtensa/qemu_xtensa/qemu_xtensa.dts index 4fa67abf2ec..da45a72dbc6 100644 --- a/boards/xtensa/qemu_xtensa/qemu_xtensa.dts +++ b/boards/xtensa/qemu_xtensa/qemu_xtensa.dts @@ -1,16 +1,16 @@ /* - * Copyright (c) 2019 Intel Corporation. + * Copyright (c) 2019, 2023 Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 */ /dts-v1/; -#include "sample_controller.dtsi" +#include "dc233c.dtsi" / { model = "qemu_xtensa"; - compatible = "cdns,xtensa-sample-controller"; + compatible = "cdns,xtensa-dc233c"; chosen { zephyr,sram = &sram0; diff --git a/boards/xtensa/qemu_xtensa/qemu_xtensa.yaml b/boards/xtensa/qemu_xtensa/qemu_xtensa.yaml index 7bd4c605ed6..1190d0d3f8e 100644 --- a/boards/xtensa/qemu_xtensa/qemu_xtensa.yaml +++ b/boards/xtensa/qemu_xtensa/qemu_xtensa.yaml @@ -11,3 +11,4 @@ testing: ignore_tags: - net - bluetooth +vendor: cdns diff --git a/boards/xtensa/qemu_xtensa/qemu_xtensa_dc233c.dts b/boards/xtensa/qemu_xtensa/qemu_xtensa_dc233c.dts deleted file mode 100644 index 1af6545d8bc..00000000000 --- a/boards/xtensa/qemu_xtensa/qemu_xtensa_dc233c.dts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2019, 2023 Intel Corporation. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; - -#include "dc233c.dtsi" - -/ { - model = "qemu_xtensa_dc233c"; - compatible = "cdns,xtensa-dc233c"; - - chosen { - zephyr,sram = &sram0; - }; -}; - -&cpu0 { - clock-frequency = <10000000>; -}; diff --git a/boards/xtensa/qemu_xtensa/qemu_xtensa_dc233c.yaml b/boards/xtensa/qemu_xtensa/qemu_xtensa_dc233c.yaml deleted file mode 100644 index 9a0b11a955e..00000000000 --- a/boards/xtensa/qemu_xtensa/qemu_xtensa_dc233c.yaml +++ /dev/null @@ -1,11 +0,0 @@ -identifier: qemu_xtensa_dc233c -name: QEMU Emulation for Xtensa (dc233c core) -type: qemu -simulation: qemu -arch: xtensa -toolchain: - - xtools -testing: - ignore_tags: - - net - - bluetooth diff --git a/boards/xtensa/qemu_xtensa/qemu_xtensa_dc233c_defconfig b/boards/xtensa/qemu_xtensa/qemu_xtensa_dc233c_defconfig deleted file mode 100644 index 9be7283e74e..00000000000 --- a/boards/xtensa/qemu_xtensa/qemu_xtensa_dc233c_defconfig +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -CONFIG_MAIN_STACK_SIZE=2048 -CONFIG_BOARD_QEMU_XTENSA_DC233C=y -CONFIG_CONSOLE=y -CONFIG_SOC_XTENSA_DC233C=y -CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=10000000 -CONFIG_STACK_SENTINEL=y -CONFIG_GEN_ISR_TABLES=y -CONFIG_GEN_IRQ_VECTOR_TABLE=n -CONFIG_SIMULATOR_XTENSA=y -CONFIG_QEMU_ICOUNT_SHIFT=6 diff --git a/boards/xtensa/qemu_xtensa/qemu_xtensa_defconfig b/boards/xtensa/qemu_xtensa/qemu_xtensa_defconfig index 08e8295cc80..ec51bb17a38 100644 --- a/boards/xtensa/qemu_xtensa/qemu_xtensa_defconfig +++ b/boards/xtensa/qemu_xtensa/qemu_xtensa_defconfig @@ -3,7 +3,7 @@ CONFIG_MAIN_STACK_SIZE=2048 CONFIG_BOARD_QEMU_XTENSA=y CONFIG_CONSOLE=y -CONFIG_SOC_XTENSA_SAMPLE_CONTROLLER=y +CONFIG_SOC_XTENSA_DC233C=y CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=10000000 CONFIG_STACK_SENTINEL=y CONFIG_GEN_ISR_TABLES=y diff --git a/boards/xtensa/qemu_xtensa/qemu_xtensa_mmu.dts b/boards/xtensa/qemu_xtensa/qemu_xtensa_mmu.dts new file mode 100644 index 00000000000..8ed0eb6dbdb --- /dev/null +++ b/boards/xtensa/qemu_xtensa/qemu_xtensa_mmu.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2019, 2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include "dc233c.dtsi" + +/ { + model = "qemu_xtensa_mmu"; + compatible = "cdns,xtensa-dc233c"; + + chosen { + zephyr,sram = &sram0; + }; +}; + +&cpu0 { + clock-frequency = <10000000>; +}; diff --git a/boards/xtensa/qemu_xtensa/qemu_xtensa_mmu.yaml b/boards/xtensa/qemu_xtensa/qemu_xtensa_mmu.yaml new file mode 100644 index 00000000000..aa2ef7692d4 --- /dev/null +++ b/boards/xtensa/qemu_xtensa/qemu_xtensa_mmu.yaml @@ -0,0 +1,13 @@ +identifier: qemu_xtensa_mmu +name: QEMU Emulation for Xtensa with MMU +type: qemu +simulation: qemu +arch: xtensa +toolchain: + - zephyr + - xtools +testing: + default: true + ignore_tags: + - net + - bluetooth diff --git a/boards/xtensa/qemu_xtensa/qemu_xtensa_mmu_defconfig b/boards/xtensa/qemu_xtensa/qemu_xtensa_mmu_defconfig new file mode 100644 index 00000000000..6587737bd88 --- /dev/null +++ b/boards/xtensa/qemu_xtensa/qemu_xtensa_mmu_defconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_BOARD_QEMU_XTENSA_MMU=y +CONFIG_CONSOLE=y +CONFIG_SOC_XTENSA_DC233C=y +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=10000000 +CONFIG_STACK_SENTINEL=y +CONFIG_GEN_ISR_TABLES=y +CONFIG_GEN_IRQ_VECTOR_TABLE=n +CONFIG_SIMULATOR_XTENSA=y +CONFIG_QEMU_ICOUNT_SHIFT=6 diff --git a/boards/xtensa/xiao_esp32s3/doc/index.rst b/boards/xtensa/xiao_esp32s3/doc/index.rst index b0a200f49c2..62a5eb69eba 100644 --- a/boards/xtensa/xiao_esp32s3/doc/index.rst +++ b/boards/xtensa/xiao_esp32s3/doc/index.rst @@ -126,7 +126,7 @@ Sysbuild ======== The sysbuild makes possible to build and flash all necessary images needed to -bootstrap the board with the EPS32 SoC. +bootstrap the board with the ESP32 SoC. To build the sample application using sysbuild use the command: diff --git a/boards/xtensa/xiao_esp32s3/seeed_xiao_connector.dtsi b/boards/xtensa/xiao_esp32s3/seeed_xiao_connector.dtsi index 2251ed92015..73fe66d28dc 100644 --- a/boards/xtensa/xiao_esp32s3/seeed_xiao_connector.dtsi +++ b/boards/xtensa/xiao_esp32s3/seeed_xiao_connector.dtsi @@ -16,8 +16,8 @@ <3 0 &gpio0 4 0>, /* D3 */ <4 0 &gpio0 5 0>, /* D4 */ <5 0 &gpio0 6 0>, /* D5 */ - <6 0 &gpio0 43 0>, /* D6 */ - <7 0 &gpio0 44 0>, /* D7 */ + <6 0 &gpio1 11 0>, /* D6 */ + <7 0 &gpio1 12 0>, /* D7 */ <8 0 &gpio0 7 0>, /* D8 */ <9 0 &gpio0 8 0>, /* D9 */ <10 0 &gpio0 9 0>; /* D10 */ diff --git a/boards/xtensa/xiao_esp32s3/xiao_esp32s3.dts b/boards/xtensa/xiao_esp32s3/xiao_esp32s3.dts index 3090f9ff5af..ecd7814bb6b 100644 --- a/boards/xtensa/xiao_esp32s3/xiao_esp32s3.dts +++ b/boards/xtensa/xiao_esp32s3/xiao_esp32s3.dts @@ -79,6 +79,10 @@ status = "okay"; }; +&gpio1 { + status = "okay"; +}; + &wdt0 { status = "okay"; }; diff --git a/boards/xtensa/xiao_esp32s3/xiao_esp32s3.yaml b/boards/xtensa/xiao_esp32s3/xiao_esp32s3.yaml index c5d8fec4b14..59ddcaec1e1 100644 --- a/boards/xtensa/xiao_esp32s3/xiao_esp32s3.yaml +++ b/boards/xtensa/xiao_esp32s3/xiao_esp32s3.yaml @@ -19,3 +19,4 @@ testing: ignore_tags: - net - bluetooth +vendor: seeed diff --git a/boards/xtensa/yd_esp32/doc/index.rst b/boards/xtensa/yd_esp32/doc/index.rst index 2696c2664b8..c49bdc0cb60 100644 --- a/boards/xtensa/yd_esp32/doc/index.rst +++ b/boards/xtensa/yd_esp32/doc/index.rst @@ -147,7 +147,7 @@ Sysbuild ======== The sysbuild makes possible to build and flash all necessary images needed to -bootstrap the board with the EPS32 SoC. +bootstrap the board with the ESP32 SoC. To build the sample application using sysbuild use the command: @@ -233,7 +233,7 @@ RGB LED ======= The board contains an addressable RGB LED (`XL-5050RGBC-WS2812B`_), driven by GPIO16. -Here is an example of how to test it using the :ref:`led_ws2812_sample` application. +Here is an example of how to test it using the :zephyr:code-sample:`led-ws2812` application. .. zephyr-app-commands:: :zephyr-app: samples/drivers/led_ws2812 diff --git a/boards/xtensa/yd_esp32/yd_esp32.yaml b/boards/xtensa/yd_esp32/yd_esp32.yaml index 99f149df488..2a73436066b 100644 --- a/boards/xtensa/yd_esp32/yd_esp32.yaml +++ b/boards/xtensa/yd_esp32/yd_esp32.yaml @@ -21,3 +21,4 @@ testing: ignore_tags: - net - bluetooth +vendor: espressif diff --git a/cmake/compiler/arcmwdt/compiler_flags.cmake b/cmake/compiler/arcmwdt/compiler_flags.cmake index 8eeaf2fa37a..7ab83ba507d 100644 --- a/cmake/compiler/arcmwdt/compiler_flags.cmake +++ b/cmake/compiler/arcmwdt/compiler_flags.cmake @@ -206,3 +206,6 @@ endif() # Remove after testing that -Wshadow works set_compiler_property(PROPERTY warning_shadow_variables) + +set_compiler_property(PROPERTY no_builtin -fno-builtin) +set_compiler_property(PROPERTY no_builtin_malloc -fno-builtin-malloc) diff --git a/cmake/compiler/clang/generic.cmake b/cmake/compiler/clang/generic.cmake index fa2f5790299..afc8d80766c 100644 --- a/cmake/compiler/clang/generic.cmake +++ b/cmake/compiler/clang/generic.cmake @@ -5,7 +5,6 @@ if(DEFINED TOOLCHAIN_HOME) endif() find_program(CMAKE_C_COMPILER clang ${find_program_clang_args} REQUIRED) -find_program(CMAKE_CXX_COMPILER clang++ ${find_program_clang_args}) find_program(CMAKE_LLVM_COV llvm-cov ${find_program_clang_args}) set(CMAKE_GCOV "${CMAKE_LLVM_COV} gcov") diff --git a/cmake/compiler/clang/target.cmake b/cmake/compiler/clang/target.cmake index 2289856941f..8dd1460280b 100644 --- a/cmake/compiler/clang/target.cmake +++ b/cmake/compiler/clang/target.cmake @@ -20,6 +20,7 @@ find_program(CMAKE_CXX_COMPILER clang++ ${find_program_clang_args}) if(NOT "${ARCH}" STREQUAL "posix") include(${ZEPHYR_BASE}/cmake/gcc-m-cpu.cmake) + include(${ZEPHYR_BASE}/cmake/gcc-m-fpu.cmake) if("${ARCH}" STREQUAL "arm") list(APPEND TOOLCHAIN_C_FLAGS diff --git a/cmake/compiler/compiler_flags_template.cmake b/cmake/compiler/compiler_flags_template.cmake index 1476c45e851..53e37287b9f 100644 --- a/cmake/compiler/compiler_flags_template.cmake +++ b/cmake/compiler/compiler_flags_template.cmake @@ -133,3 +133,7 @@ set_compiler_property(PROPERTY no_global_merge) # Compiler flag for warning about shadow variables set_compiler_property(PROPERTY warning_shadow_variables) + +# Compiler flags to avoid recognizing built-in functions +set_compiler_property(PROPERTY no_builtin) +set_compiler_property(PROPERTY no_builtin_malloc) diff --git a/cmake/compiler/gcc/compiler_flags.cmake b/cmake/compiler/gcc/compiler_flags.cmake index b77dfa4123f..5b1dbde49c6 100644 --- a/cmake/compiler/gcc/compiler_flags.cmake +++ b/cmake/compiler/gcc/compiler_flags.cmake @@ -227,3 +227,6 @@ set_compiler_property(PROPERTY no_position_independent set_compiler_property(PROPERTY no_global_merge "") set_compiler_property(PROPERTY warning_shadow_variables -Wshadow) + +set_compiler_property(PROPERTY no_builtin -fno-builtin) +set_compiler_property(PROPERTY no_builtin_malloc -fno-builtin-malloc) diff --git a/cmake/compiler/gcc/target_arm.cmake b/cmake/compiler/gcc/target_arm.cmake index 0cfaba43da0..a813c2563a3 100644 --- a/cmake/compiler/gcc/target_arm.cmake +++ b/cmake/compiler/gcc/target_arm.cmake @@ -34,5 +34,10 @@ if(CONFIG_FP16) list(APPEND ARM_C_FLAGS -mfp16-format=alternative) endif() endif() + +if(CONFIG_THREAD_LOCAL_STORAGE) + list(APPEND ARM_C_FLAGS -mtp=soft) +endif() + list(APPEND TOOLCHAIN_C_FLAGS ${ARM_C_FLAGS}) list(APPEND TOOLCHAIN_LD_FLAGS NO_SPLIT ${ARM_C_FLAGS}) diff --git a/cmake/emu/native.cmake b/cmake/emu/native.cmake index 12cdd3112b7..3578f47bfc4 100644 --- a/cmake/emu/native.cmake +++ b/cmake/emu/native.cmake @@ -3,7 +3,9 @@ add_custom_target(run_native COMMAND ${APPLICATION_BINARY_DIR}/zephyr/${KERNEL_EXE_NAME} - DEPENDS ${logical_target_for_zephyr_elf} + DEPENDS + ${logical_target_for_zephyr_elf} + $<$:native_runner_executable> WORKING_DIRECTORY ${APPLICATION_BINARY_DIR} USES_TERMINAL ) diff --git a/cmake/emu/qemu.cmake b/cmake/emu/qemu.cmake index a3a8a94515b..6103fc1cefc 100644 --- a/cmake/emu/qemu.cmake +++ b/cmake/emu/qemu.cmake @@ -399,6 +399,13 @@ set(env_qemu $ENV{QEMU_EXTRA_FLAGS}) separate_arguments(env_qemu) list(APPEND QEMU_EXTRA_FLAGS ${env_qemu}) +# Also append QEMU flags from config +if(NOT CONFIG_QEMU_EXTRA_FLAGS STREQUAL "") + set(config_qemu_flags ${CONFIG_QEMU_EXTRA_FLAGS}) + separate_arguments(config_qemu_flags) + list(APPEND QEMU_EXTRA_FLAGS "${config_qemu_flags}") +endif() + list(APPEND MORE_FLAGS_FOR_debugserver_qemu -S) if(NOT CONFIG_QEMU_GDBSERVER_LISTEN_DEV STREQUAL "") diff --git a/cmake/extra_flags.cmake b/cmake/extra_flags.cmake index 2e41720991d..138262afb1f 100644 --- a/cmake/extra_flags.cmake +++ b/cmake/extra_flags.cmake @@ -1,6 +1,8 @@ # SPDX-License-Identifier: Apache-2.0 foreach(extra_flags EXTRA_CPPFLAGS EXTRA_LDFLAGS EXTRA_CFLAGS EXTRA_CXXFLAGS EXTRA_AFLAGS) + # Note: zephyr_get MERGE should not be used until issue #43959 is resolved. + zephyr_get(${extra_flags}) list(LENGTH ${extra_flags} flags_length) if(flags_length LESS_EQUAL 1) # A length of zero means no argument. diff --git a/cmake/flash/CMakeLists.txt b/cmake/flash/CMakeLists.txt index 892cfa081e8..392274891f1 100644 --- a/cmake/flash/CMakeLists.txt +++ b/cmake/flash/CMakeLists.txt @@ -36,6 +36,14 @@ function(runners_yaml_append_config) get_runners_prop(elf_file elf "${KERNEL_ELF_NAME}") runners_yaml_append(" # Build outputs:") runners_yaml_append(" elf_file: ${elf}") + if(CONFIG_BUILD_OUTPUT_EXE) + get_runners_prop(exe_file exe "${KERNEL_EXE_NAME}") + else() + get_runners_prop(exe_file exe "") + endif() + if(exe) + runners_yaml_append(" exe_file: ${exe}") + endif() if(CONFIG_BUILD_OUTPUT_HEX) get_runners_prop(hex_file hex "${KERNEL_HEX_NAME}") else() diff --git a/cmake/linker/armlink/target.cmake b/cmake/linker/armlink/target.cmake index 8f777c7800d..e8511aea244 100644 --- a/cmake/linker/armlink/target.cmake +++ b/cmake/linker/armlink/target.cmake @@ -65,7 +65,7 @@ function(toolchain_ld_link_elf) ) foreach(lib ${ZEPHYR_LIBS_PROPERTY}) - if(NOT ${lib} STREQUAL arch__arm__core__aarch32__cortex_m) + if(NOT ${lib} STREQUAL arch__arm__core__cortex_m) list(APPEND ZEPHYR_LIBS_OBJECTS $) list(APPEND ZEPHYR_LIBS_OBJECTS $) endif() @@ -76,7 +76,7 @@ function(toolchain_ld_link_elf) ${TOOLCHAIN_LD_LINK_ELF_LIBRARIES_PRE_SCRIPT} --scatter=${TOOLCHAIN_LD_LINK_ELF_LINKER_SCRIPT} ${TOOLCHAIN_LD_LINK_ELF_LIBRARIES_POST_SCRIPT} - $ + $ --map --list=${TOOLCHAIN_LD_LINK_ELF_OUTPUT_MAP} ${ZEPHYR_LIBS_OBJECTS} kernel diff --git a/cmake/linker/ld/target.cmake b/cmake/linker/ld/target.cmake index 507188540b7..b57f8902044 100644 --- a/cmake/linker/ld/target.cmake +++ b/cmake/linker/ld/target.cmake @@ -57,6 +57,10 @@ macro(configure_linker_script linker_script_gen linker_pass_define) zephyr_get_include_directories_for_lang(C current_includes) get_property(current_defines GLOBAL PROPERTY PROPERTY_LINKER_SCRIPT_DEFINES) + if(DEFINED SOC_LINKER_SCRIPT) + cmake_path(GET SOC_LINKER_SCRIPT PARENT_PATH soc_linker_script_includes) + set(soc_linker_script_includes -I${soc_linker_script_includes}) + endif() add_custom_command( OUTPUT ${linker_script_gen} @@ -74,6 +78,7 @@ macro(configure_linker_script linker_script_gen linker_pass_define) -D_ASMLANGUAGE -imacros ${AUTOCONF_H} ${current_includes} + ${soc_linker_script_includes} ${current_defines} ${template_script_defines} -E ${LINKER_SCRIPT} diff --git a/cmake/linker/ld/target_cpp.cmake b/cmake/linker/ld/target_cpp.cmake index 057bb02bc6d..a6601347172 100644 --- a/cmake/linker/ld/target_cpp.cmake +++ b/cmake/linker/ld/target_cpp.cmake @@ -4,8 +4,10 @@ macro(toolchain_ld_cpp) - zephyr_link_libraries( - -lstdc++ - ) + if(NOT CONFIG_EXTERNAL_MODULE_LIBCPP) + zephyr_link_libraries( + -lstdc++ + ) + endif() endmacro() diff --git a/cmake/linker/lld/target.cmake b/cmake/linker/lld/target.cmake index 0daf19a7c76..f71a217e5be 100644 --- a/cmake/linker/lld/target.cmake +++ b/cmake/linker/lld/target.cmake @@ -1,7 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 set_property(TARGET linker PROPERTY devices_start_symbol "_device_list_start") -find_package(LlvmLld REQUIRED) +find_package(LlvmLld 14.0.0 REQUIRED) set(CMAKE_LINKER ${LLVMLLD_LINKER}) set_ifndef(LINKERFLAGPREFIX -Wl) @@ -110,6 +110,6 @@ endfunction(toolchain_ld_link_elf) # Load toolchain_ld-family macros include(${ZEPHYR_BASE}/cmake/linker/${LINKER}/target_base.cmake) include(${ZEPHYR_BASE}/cmake/linker/${LINKER}/target_baremetal.cmake) -include(${ZEPHYR_BASE}/cmake/linker/ld/target_cpp.cmake) +include(${ZEPHYR_BASE}/cmake/linker/${LINKER}/target_cpp.cmake) include(${ZEPHYR_BASE}/cmake/linker/ld/target_relocation.cmake) include(${ZEPHYR_BASE}/cmake/linker/ld/target_configure.cmake) diff --git a/cmake/linker/lld/target_cpp.cmake b/cmake/linker/lld/target_cpp.cmake new file mode 100644 index 00000000000..1004c0e6865 --- /dev/null +++ b/cmake/linker/lld/target_cpp.cmake @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 + +# See root CMakeLists.txt for description and expectations of these macros + +macro(toolchain_ld_cpp) + + zephyr_link_libraries( + -lc++ + ) + +endmacro() diff --git a/cmake/linker_script/common/common-ram.cmake b/cmake/linker_script/common/common-ram.cmake index 9c051477d10..a116977ce8c 100644 --- a/cmake/linker_script/common/common-ram.cmake +++ b/cmake/linker_script/common/common-ram.cmake @@ -94,9 +94,6 @@ endif() if(CONFIG_ZTEST) zephyr_iterable_section(NAME ztest_suite_node GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) zephyr_iterable_section(NAME ztest_suite_stats GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) -endif() - -if(CONFIG_ZTEST_NEW_API) zephyr_iterable_section(NAME ztest_unit_test GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) zephyr_iterable_section(NAME ztest_test_rule GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) zephyr_iterable_section(NAME ztest_expected_result_entry GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) diff --git a/cmake/linker_script/common/common-rom.cmake b/cmake/linker_script/common/common-rom.cmake index d81b215facc..d79fa223fc5 100644 --- a/cmake/linker_script/common/common-rom.cmake +++ b/cmake/linker_script/common/common-rom.cmake @@ -67,13 +67,13 @@ if(CONFIG_USERSPACE) # Build-time assignment of permissions to kernel objects to # threads declared with K_THREAD_DEFINE() zephyr_linker_section( - NAME z_object_assignment_area + NAME k_object_assignment_area VMA FLASH NOINPUT SUBALIGN 4 ) zephyr_linker_section_configure( - SECTION z_object_assignment - INPUT ".z_object_assignment.static.*" + SECTION k_object_assignment + INPUT ".k_object_assignment.static.*" KEEP SORT NAME ) endif() @@ -218,3 +218,11 @@ if(CONFIG_ZBUS) zephyr_iterable_section(NAME zbus_channel KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) zephyr_iterable_section(NAME zbus_channel_observation KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) endif() + +if(CONFIG_GNSS) + zephyr_iterable_section(NAME gnss_data_callback KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +endif() + +if(CONFIG_GNSS_SATELLITES) + zephyr_iterable_section(NAME gnss_satellites_callback KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +endif() diff --git a/cmake/modules/FindDeprecated.cmake b/cmake/modules/FindDeprecated.cmake index ae9b292af09..66cac2a5583 100644 --- a/cmake/modules/FindDeprecated.cmake +++ b/cmake/modules/FindDeprecated.cmake @@ -131,5 +131,23 @@ if(NOT "${Deprecated_FIND_COMPONENTS}" STREQUAL "") "${Deprecated_FIND_COMPONENTS}") endif() +if("SEARCHED_LINKER_SCRIPT" IN_LIST Deprecated_FIND_COMPONENTS) + # This code was deprecated after Zephyr v3.5.0 + list(REMOVE_ITEM Deprecated_FIND_COMPONENTS SEARCHED_LINKER_SCRIPT) + + # Try a board specific linker file + set(LINKER_SCRIPT ${BOARD_DIR}/linker.ld) + if(NOT EXISTS ${LINKER_SCRIPT}) + # If not available, try an SoC specific linker file + set(LINKER_SCRIPT ${SOC_DIR}/${ARCH}/${SOC_PATH}/linker.ld) + endif() + message(DEPRECATION + "Pre-defined `linker.ld` script is deprecated. Please set " + "BOARD_LINKER_SCRIPT or SOC_LINKER_SCRIPT to point to ${LINKER_SCRIPT} " + "or one of the Zephyr provided common linker scripts for the ${ARCH} " + "architecture." + ) +endif() + set(Deprecated_FOUND True) set(DEPRECATED_FOUND True) diff --git a/cmake/modules/FindHostTools.cmake b/cmake/modules/FindHostTools.cmake index c8f28f21285..82225b49e56 100644 --- a/cmake/modules/FindHostTools.cmake +++ b/cmake/modules/FindHostTools.cmake @@ -50,7 +50,7 @@ endif() find_package(Deprecated COMPONENTS XCC_USE_CLANG CROSS_COMPILE) -find_package(Zephyr-sdk 0.15) +find_package(Zephyr-sdk 0.16) # gperf is an optional dependency find_program(GPERF gperf) diff --git a/cmake/modules/Findarmclang.cmake b/cmake/modules/Findarmclang.cmake index a84a04f163b..e0f9d6e3c1d 100644 --- a/cmake/modules/Findarmclang.cmake +++ b/cmake/modules/Findarmclang.cmake @@ -16,8 +16,16 @@ include(FindPackageHandleStandardArgs) if(CMAKE_C_COMPILER) # Parse the 'clang --version' output to find the installed version. - execute_process(COMMAND ${CMAKE_C_COMPILER} --target=${triple} --version OUTPUT_VARIABLE ARMCLANG_VERSION) - string(REGEX REPLACE "[^0-9]*([0-9.]+) .*" "\\1" ARMCLANG_VERSION ${ARMCLANG_VERSION}) + execute_process(COMMAND ${CMAKE_C_COMPILER} --target=${triple} --version OUTPUT_VARIABLE ARMCLANG_VERSION ERROR_QUIET) + string(REPLACE "\n" ";" armclang_version_list "${ARMCLANG_VERSION}") + set(ARMCLANG_VERSION ARMCLANG_VERSION-NOTFOUND) + foreach(line ${armclang_version_list}) + # Compiler version is either terminated directly, or followed by space and extra build info. + if(line MATCHES ".*[aA]rm [cC]ompiler[^0-9]*([0-9.]+)($| .*$)") + set(ARMCLANG_VERSION "${CMAKE_MATCH_1}") + break() + endif() + endforeach() endif() find_package_handle_standard_args(armclang diff --git a/cmake/modules/dts.cmake b/cmake/modules/dts.cmake index 8236195ff85..c9ac751a1e5 100644 --- a/cmake/modules/dts.cmake +++ b/cmake/modules/dts.cmake @@ -9,9 +9,6 @@ include(pre_dt) find_package(HostTools) find_package(Dtc 1.4.6) -# Zephyr code is usually configured using devicetree, but this is -# still technically optional (see e.g. CONFIG_HAS_DTS). -# # This module makes information from the devicetree available to # various build stages, as well as to other arbitrary Python scripts: # @@ -125,12 +122,6 @@ set(DTS_CMAKE ${PROJECT_BINARY_DIR}/dts.cmake) # modules. set(VENDOR_PREFIXES dts/bindings/vendor-prefixes.txt) -# -# Halt execution early if there is no devicetree. -# - -# TODO: What to do about non-posix platforms where NOT CONFIG_HAS_DTS (xtensa)? -# Drop support for NOT CONFIG_HAS_DTS perhaps? set_ifndef(DTS_SOURCE ${BOARD_DIR}/${BOARD}.dts) if(EXISTS ${DTS_SOURCE}) # We found a devicetree. Check for a board revision overlay. @@ -138,10 +129,8 @@ if(EXISTS ${DTS_SOURCE}) list(APPEND DTS_SOURCE ${BOARD_DIR}/${BOARD}_${BOARD_REVISION_STRING}.overlay) endif() else() - # If we don't have a devicetree after all, there's not much to do. - set(header_template ${ZEPHYR_BASE}/misc/generated/generated_header.template) - zephyr_file_copy(${header_template} ${DEVICETREE_GENERATED_H} ONLY_IF_DIFFERENT) - return() + # If we don't have a devicetree, provide an empty stub + set(DTS_SOURCE ${ZEPHYR_BASE}/boards/common/stub.dts) endif() # diff --git a/cmake/modules/extensions.cmake b/cmake/modules/extensions.cmake index 1e38ae7ba72..6bdd55433eb 100644 --- a/cmake/modules/extensions.cmake +++ b/cmake/modules/extensions.cmake @@ -528,6 +528,10 @@ function(zephyr_library_cc_option) endforeach() endfunction() +function(zephyr_library_add_dependencies) + add_dependencies(${ZEPHYR_CURRENT_LIBRARY} ${ARGN}) +endfunction() + # Add the existing CMake library 'library' to the global list of # Zephyr CMake libraries. This is done automatically by the # constructor but must be called explicitly on CMake libraries that do @@ -1819,6 +1823,12 @@ function(zephyr_linker_sources_ifdef feature_toggle) endif() endfunction() +function(zephyr_library_add_dependencies_ifdef feature_toggle) + if(${${feature_toggle}}) + zephyr_library_add_dependencies(${ARGN}) + endif() +endfunction() + macro(list_append_ifdef feature_toggle list) if(${${feature_toggle}}) list(APPEND ${list} ${ARGN}) @@ -1965,6 +1975,12 @@ function(zephyr_linker_sources_ifndef feature_toggle) endif() endfunction() +function(zephyr_library_add_dependencies_ifndef feature_toggle) + if(NOT ${feature_toggle}) + zephyr_library_add_dependencies(${ARGN}) + endif() +endfunction() + macro(list_append_ifndef feature_toggle list) if(NOT ${feature_toggle}) list(APPEND ${list} ${ARGN}) @@ -3267,13 +3283,13 @@ function(dt_node_has_status var) return() endif() - dt_prop(${var} PATH ${canonical} PROPERTY status) + dt_prop(status PATH ${canonical} PROPERTY status) - if(NOT DEFINED ${var} OR "${${var}}" STREQUAL ok) - set(${var} okay) + if(NOT DEFINED status OR status STREQUAL "ok") + set(status "okay") endif() - if(${var} STREQUAL ${DT_NODE_STATUS}) + if(status STREQUAL "${DT_NODE_STATUS}") set(${var} TRUE PARENT_SCOPE) else() set(${var} FALSE PARENT_SCOPE) @@ -4049,8 +4065,8 @@ function(zephyr_linker_dts_section) ) endif() - dt_node_exists(exists PATH ${DTS_SECTION_PATH}) - if(NOT ${exists}) + dt_node_has_status(okay PATH ${DTS_SECTION_PATH} STATUS okay) + if(NOT ${okay}) return() endif() @@ -4122,14 +4138,19 @@ function(zephyr_linker_dts_memory) return() endif() - dt_node_exists(exists PATH ${DTS_MEMORY_PATH}) - if(NOT ${exists}) + dt_node_has_status(okay PATH ${DTS_MEMORY_PATH} STATUS okay) + if(NOT ${okay}) return() endif() dt_reg_addr(addr PATH ${DTS_MEMORY_PATH}) dt_reg_size(size PATH ${DTS_MEMORY_PATH}) dt_prop(name PATH ${DTS_MEMORY_PATH} PROPERTY "zephyr,memory-region") + if(NOT DEFINED name) + message(FATAL_ERROR "zephyr_linker_dts_memory(${ARGV0} ...) missing " + "\"zephyr,memory-region\" property" + ) + endif() zephyr_string(SANITIZE name ${name}) zephyr_linker_memory( diff --git a/cmake/modules/kconfig.cmake b/cmake/modules/kconfig.cmake index 7c4a059b570..1a78b3ebd02 100644 --- a/cmake/modules/kconfig.cmake +++ b/cmake/modules/kconfig.cmake @@ -122,6 +122,12 @@ else() set(_local_TOOLCHAIN_HAS_NEWLIB n) endif() +if(TOOLCHAIN_HAS_PICOLIBC) + set(_local_TOOLCHAIN_HAS_PICOLIBC y) +else() + set(_local_TOOLCHAIN_HAS_PICOLIBC n) +endif() + set(COMMON_KCONFIG_ENV_SETTINGS PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} srctree=${ZEPHYR_BASE} @@ -140,6 +146,8 @@ set(COMMON_KCONFIG_ENV_SETTINGS ZEPHYR_TOOLCHAIN_VARIANT=${ZEPHYR_TOOLCHAIN_VARIANT} TOOLCHAIN_KCONFIG_DIR=${TOOLCHAIN_KCONFIG_DIR} TOOLCHAIN_HAS_NEWLIB=${_local_TOOLCHAIN_HAS_NEWLIB} + TOOLCHAIN_HAS_PICOLIBC=${_local_TOOLCHAIN_HAS_PICOLIBC} + HIDE_CHILD_PARENT_CONFIG=${SYSBUILD} EDT_PICKLE=${EDT_PICKLE} # Export all Zephyr modules to Kconfig ${ZEPHYR_KCONFIG_MODULES_DIR} diff --git a/cmake/modules/kernel.cmake b/cmake/modules/kernel.cmake index 28ee922d40b..06e1642f362 100644 --- a/cmake/modules/kernel.cmake +++ b/cmake/modules/kernel.cmake @@ -142,7 +142,8 @@ enable_language(C CXX ASM) # Verify that the toolchain can compile a dummy file, if it is not we # won't be able to test for compatibility with certain C flags. zephyr_check_compiler_flag(C "" toolchain_is_ok) -assert(toolchain_is_ok "The toolchain is unable to build a dummy C file. See CMakeError.log.") +assert(toolchain_is_ok "The toolchain is unable to build a dummy C file.\ + Move ${USER_CACHE_DIR}, re-run and look at CMakeError.log") include(${ZEPHYR_BASE}/cmake/target_toolchain_flags.cmake) diff --git a/cmake/modules/unittest.cmake b/cmake/modules/unittest.cmake index be5fa56741a..8853f5a5b0c 100644 --- a/cmake/modules/unittest.cmake +++ b/cmake/modules/unittest.cmake @@ -6,6 +6,9 @@ include(root) include(boards) include(arch) include(configuration_files) + +include(west) +include(zephyr_module) include(kconfig) find_package(TargetTools) @@ -103,19 +106,12 @@ if(LIBS) message(FATAL_ERROR "This variable is not supported, see SOURCES instead") endif() -if(CONFIG_ZTEST_NEW_API) - target_sources(testbinary PRIVATE - ${ZEPHYR_BASE}/subsys/testsuite/ztest/src/ztest_new.c - ${ZEPHYR_BASE}/subsys/testsuite/ztest/src/ztest_mock.c - ${ZEPHYR_BASE}/subsys/testsuite/ztest/src/ztest_rules.c - ${ZEPHYR_BASE}/subsys/testsuite/ztest/src/ztest_defaults.c - ) -else() - target_sources(testbinary PRIVATE - ${ZEPHYR_BASE}/subsys/testsuite/ztest/src/ztest.c - ${ZEPHYR_BASE}/subsys/testsuite/ztest/src/ztest_mock.c - ) -endif() +target_sources(testbinary PRIVATE + ${ZEPHYR_BASE}/subsys/testsuite/ztest/src/ztest.c + ${ZEPHYR_BASE}/subsys/testsuite/ztest/src/ztest_mock.c + ${ZEPHYR_BASE}/subsys/testsuite/ztest/src/ztest_rules.c + ${ZEPHYR_BASE}/subsys/testsuite/ztest/src/ztest_defaults.c +) target_compile_definitions(test_interface INTERFACE ZTEST_UNITTEST) diff --git a/cmake/package_helper.cmake b/cmake/package_helper.cmake index d33b1cf6ddf..55412b94110 100644 --- a/cmake/package_helper.cmake +++ b/cmake/package_helper.cmake @@ -111,5 +111,16 @@ if(NOT DEFINED MODULES) ) endif() +# Loading Zephyr CMake extension commands, which allows us to overload Zephyr +# scoping rules. +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE} COMPONENTS extensions) + +# Zephyr scoping creates custom targets for handling of properties. +# However, custom targets cannot be used in CMake script mode. +# Therefore disable zephyr_set(... SCOPE ...) in package helper as it is not needed. +function(zephyr_set variable) + # This silence the error: zephyr_set(... SCOPE ) doesn't exists. +endfunction() + string(REPLACE ";" "," MODULES "${MODULES}") find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE} COMPONENTS zephyr_default:${MODULES}) diff --git a/cmake/toolchain/llvm/target.cmake b/cmake/toolchain/llvm/target.cmake index 38097229125..5c06af5f25f 100644 --- a/cmake/toolchain/llvm/target.cmake +++ b/cmake/toolchain/llvm/target.cmake @@ -16,7 +16,7 @@ if("${ARCH}" STREQUAL "arm") elseif(DEFINED CONFIG_ARMV7_M_ARMV8_M_MAINLINE) # ARMV7_M_ARMV8_M_MAINLINE means that ARMv7-M or backward compatible ARMv8-M # processor is used. - set(triple armv7m-cros-eabi) + set(triple armv7m-none-eabi) elseif(DEFINED CONFIG_ARMV6_M_ARMV8_M_BASELINE) # ARMV6_M_ARMV8_M_BASELINE means that ARMv6-M or ARMv8-M supporting the # Baseline implementation processor is used. diff --git a/doc/_doxygen/groups.dox b/doc/_doxygen/groups.dox index cd4efcd6294..65b229a0ce9 100644 --- a/doc/_doxygen/groups.dox +++ b/doc/_doxygen/groups.dox @@ -1,5 +1,11 @@ /** +@defgroup internal_api Internal and System API +@brief Internal and System API +@{ + +@} + @defgroup os_services Operating System Services @brief Operating System Services @{ @@ -36,14 +42,14 @@ @brief Connectivity @defgroup connectivity Connectivity @{ +@} @brief USB @defgroup usb USB +@ingroup connectivity @{ @} -@} - @brief Utilities @defgroup utilities Utilities @{ @@ -60,4 +66,9 @@ @{ @} +@brief Modem APIs +@defgroup modem Modem APIs +@{ +@} + */ diff --git a/doc/_extensions/zephyr/application.py b/doc/_extensions/zephyr/application.py index 9369fb7becf..969e3290a59 100644 --- a/doc/_extensions/zephyr/application.py +++ b/doc/_extensions/zephyr/application.py @@ -92,6 +92,9 @@ class ZephyrAppCommandsDirective(Directive): \:west-args: if set, additional arguments to the west invocation (ignored for CMake) + \:flash-args: + if set, additional arguments to the flash invocation + ''' has_content = False required_arguments = 0 @@ -114,6 +117,7 @@ class ZephyrAppCommandsDirective(Directive): 'maybe-skip-config': directives.flag, 'compact': directives.flag, 'west-args': directives.unchanged, + 'flash-args': directives.unchanged, } TOOLS = ['cmake', 'west', 'all'] @@ -143,6 +147,7 @@ def run(self): skip_config = 'maybe-skip-config' in self.options compact = 'compact' in self.options west_args = self.options.get('west-args', None) + flash_args = self.options.get('flash-args', None) if tool not in self.TOOLS: raise self.error('Unknown tool {}; choose from: {}'.format( @@ -194,7 +199,8 @@ def run(self): 'compact': compact, 'skip_config': skip_config, 'generator': generator, - 'west_args': west_args + 'west_args': west_args, + 'flash_args': flash_args, } if 'west' in tools: @@ -229,7 +235,7 @@ def _lit_block(self, content): # Create the nodes. literal = nodes.literal_block(content, content) self.add_name(literal) - literal['language'] = 'console' + literal['language'] = 'shell' return literal @@ -244,12 +250,14 @@ def _generate_west(self, **kwargs): build_dir = kwargs['build_dir'] compact = kwargs['compact'] west_args = kwargs['west_args'] + flash_args = kwargs['flash_args'] kwargs['board'] = None # west always defaults to ninja gen_arg = ' -G\'Unix Makefiles\'' if generator == 'make' else '' cmake_args = gen_arg + self._cmake_args(**kwargs) cmake_args = ' --{}'.format(cmake_args) if cmake_args != '' else '' west_args = ' {}'.format(west_args) if west_args else '' + flash_args = ' {}'.format(flash_args) if flash_args else '' # ignore zephyr_app since west needs to run within # the installation. Instead rely on relative path. src = ' {}'.format(app) if app and not cd_into else '' @@ -284,7 +292,7 @@ def _generate_west(self, **kwargs): if goal in {'build', 'sign'}: continue elif goal == 'flash': - content.append('west flash{}'.format(dst)) + content.append('west flash{}{}'.format(flash_args, dst)) elif goal == 'debug': content.append('west debug{}'.format(dst)) elif goal == 'debugserver': @@ -407,7 +415,7 @@ def _generate_cmake(self, **kwargs): cmake_args, source_dir)) if not compact: content.extend(['', - '# Now run ninja on the generated build system:']) + '# Now run the build tool on the generated build system:']) if 'build' in goals: content.append('{}{}{}'.format(generator, tool_build_dir, diff --git a/doc/_extensions/zephyr/domain.py b/doc/_extensions/zephyr/domain.py new file mode 100644 index 00000000000..053965e26e3 --- /dev/null +++ b/doc/_extensions/zephyr/domain.py @@ -0,0 +1,339 @@ +""" +Zephyr Extension +################ + +Copyright (c) 2023 The Linux Foundation +SPDX-License-Identifier: Apache-2.0 + +Introduction +============ + +This extension adds a new ``zephyr`` domain for handling the documentation of various entities +specific to the Zephyr RTOS project (ex. code samples). + +Directives +---------- + +- ``zephyr:code-sample::`` - Defines a code sample. + The directive takes an ID as the main argument, and accepts ``:name:`` (human-readable short name + of the sample) and ``:relevant-api:`` (a space separated list of Doxygen group(s) for APIs the + code sample is a good showcase of) as options. + The content of the directive is used as the description of the code sample. + + Example: + + ``` + .. zephyr:code-sample:: blinky + :name: Blinky + :relevant-api: gpio_interface + + Blink an LED forever using the GPIO API. + ``` + +Roles +----- + +- ``:zephyr:code-sample:`` - References a code sample. + The role takes the ID of the code sample as the argument. The role renders as a link to the code + sample, and the link text is the name of the code sample (or a custom text if an explicit name is + provided). + + Example: + + ``` + Check out :zephyr:code-sample:`sample-foo` for an example of how to use the foo API. You may + also be interested in :zephyr:code-sample:`this one `. + ``` + +""" +from typing import Any, Dict, Iterator, List, Tuple + +from breathe.directives.content_block import DoxygenGroupDirective +from docutils import nodes +from docutils.nodes import Node +from docutils.parsers.rst import Directive, directives +from sphinx import addnodes +from sphinx.domains import Domain, ObjType +from sphinx.roles import XRefRole +from sphinx.transforms import SphinxTransform +from sphinx.transforms.post_transforms import SphinxPostTransform +from sphinx.util import logging +from sphinx.util.nodes import NodeMatcher, make_refnode +from zephyr.gh_utils import gh_link_get_url + +import json + +__version__ = "0.1.0" + +logger = logging.getLogger(__name__) + + +class CodeSampleNode(nodes.Element): + pass + + +class RelatedCodeSamplesNode(nodes.Element): + pass + + +class ConvertCodeSampleNode(SphinxTransform): + default_priority = 100 + + def apply(self): + if not self.config.zephyr_domain_apply_transforms: + return + + matcher = NodeMatcher(CodeSampleNode) + for node in self.document.traverse(matcher): + self.convert_node(node) + + def convert_node(self, node): + """ + Transforms a `CodeSampleNode` into a `nodes.section` named after the code sample name. + + Moves all sibling nodes that are after the `CodeSampleNode` in the documement under this new + section. + """ + parent = node.parent + siblings_to_move = [] + if parent is not None: + index = parent.index(node) + siblings_to_move = parent.children[index + 1 :] + + # Create a new section + new_section = nodes.section(ids=[node["id"]]) + new_section += nodes.title(text=node["name"]) + + # Move the sibling nodes under the new section + new_section.extend(siblings_to_move) + + # Replace the custom node with the new section + node.replace_self(new_section) + + # Remove the moved siblings from their original parent + for sibling in siblings_to_move: + parent.remove(sibling) + + # Set sample description as the meta description of the document for improved SEO + meta_description = nodes.meta() + meta_description["name"] = "description" + meta_description["content"] = node.children[0].astext() + node.document += meta_description + + # Similarly, add a node with JSON-LD markup (only renders in HTML output) describing + # the code sample. + json_ld = nodes.raw( + "", + f"""""", + format="html", + ) + node.document += json_ld + + +class ProcessRelatedCodeSamplesNode(SphinxPostTransform): + default_priority = 5 # before ReferencesResolver + + def run(self, **kwargs: Any) -> None: + if not self.config.zephyr_domain_apply_transforms: + return + + matcher = NodeMatcher(RelatedCodeSamplesNode) + for node in self.document.traverse(matcher): + id = node["id"] # the ID of the node is the name of the doxygen group for which we + # want to list related code samples + + code_samples = self.env.domaindata["zephyr"]["code-samples"].values() + # Filter out code samples that don't reference this doxygen group + code_samples = [ + code_sample for code_sample in code_samples if id in code_sample["relevant-api"] + ] + + if len(code_samples) > 0: + admonition = nodes.admonition() + admonition += nodes.title(text="Related code samples") + admonition["classes"].append("related-code-samples") + admonition["classes"].append("dropdown") # used by sphinx-togglebutton extension + admonition["classes"].append("toggle-shown") # show the content by default + + sample_dl = nodes.definition_list() + + for code_sample in sorted(code_samples, key=lambda x: x["name"]): + term = nodes.term() + + sample_xref = addnodes.pending_xref( + "", + refdomain="zephyr", + reftype="code-sample", + reftarget=code_sample["id"], + refwarn=True, + ) + sample_xref += nodes.inline(text=code_sample["name"]) + term += sample_xref + definition = nodes.definition() + definition += nodes.paragraph(text=code_sample["description"].astext()) + sample_dli = nodes.definition_list_item() + sample_dli += term + sample_dli += definition + sample_dl += sample_dli + admonition += sample_dl + + # replace node with the newly created admonition + node.replace_self(admonition) + else: + # remove node if there are no code samples + node.replace_self([]) + + +class CodeSampleDirective(Directive): + """ + A directive for creating a code sample node in the Zephyr documentation. + """ + + required_arguments = 1 # ID + optional_arguments = 0 + option_spec = {"name": directives.unchanged, "relevant-api": directives.unchanged} + has_content = True + + def run(self): + code_sample_id = self.arguments[0] + env = self.state.document.settings.env + code_samples = env.domaindata["zephyr"]["code-samples"] + + if code_sample_id in code_samples: + logger.warning( + f"Code sample {code_sample_id} already exists. " + f"Other instance in {code_samples[code_sample_id]['docname']}", + location=(env.docname, self.lineno), + ) + + name = self.options.get("name", code_sample_id) + relevant_api_list = self.options.get("relevant-api", "").split() + + # Create a node for description and populate it with parsed content + description_node = nodes.container(ids=[f"{code_sample_id}-description"]) + self.state.nested_parse(self.content, self.content_offset, description_node) + + code_sample = { + "id": code_sample_id, + "name": name, + "description": description_node, + "relevant-api": relevant_api_list, + "docname": env.docname, + } + + domain = env.get_domain("zephyr") + domain.add_code_sample(code_sample) + + # Create an instance of the custom node + code_sample_node = CodeSampleNode() + code_sample_node["id"] = code_sample_id + code_sample_node["name"] = name + code_sample_node += description_node + + return [code_sample_node] + + +class ZephyrDomain(Domain): + """Zephyr domain""" + + name = "zephyr" + label = "Zephyr Project" + + roles = { + "code-sample": XRefRole(innernodeclass=nodes.inline, warn_dangling=True), + } + + directives = {"code-sample": CodeSampleDirective} + + object_types: Dict[str, ObjType] = { + "code-sample": ObjType("code-sample", "code-sample"), + } + + initial_data: Dict[str, Any] = {"code-samples": {}} + + def clear_doc(self, docname: str) -> None: + self.data["code-samples"] = { + sample_id: sample_data + for sample_id, sample_data in self.data["code-samples"].items() + if sample_data["docname"] != docname + } + + def merge_domaindata(self, docnames: List[str], otherdata: Dict) -> None: + self.data["code-samples"].update(otherdata["code-samples"]) + + def get_objects(self): + for _, code_sample in self.data["code-samples"].items(): + yield ( + code_sample["id"], + code_sample["name"], + "code-sample", + code_sample["docname"], + code_sample["id"], + 1, + ) + + # used by Sphinx Immaterial theme + def get_object_synopses(self) -> Iterator[Tuple[Tuple[str, str], str]]: + for _, code_sample in self.data["code-samples"].items(): + yield ( + (code_sample["docname"], code_sample["id"]), + code_sample["description"].astext(), + ) + + def resolve_xref(self, env, fromdocname, builder, type, target, node, contnode): + if type == "code-sample": + code_sample_info = self.data["code-samples"].get(target) + if code_sample_info: + if not node.get("refexplicit"): + contnode = [nodes.Text(code_sample_info["name"])] + + return make_refnode( + builder, + fromdocname, + code_sample_info["docname"], + code_sample_info["id"], + contnode, + code_sample_info["description"].astext(), + ) + + def add_code_sample(self, code_sample): + self.data["code-samples"][code_sample["id"]] = code_sample + + +class CustomDoxygenGroupDirective(DoxygenGroupDirective): + """Monkey patch for Breathe's DoxygenGroupDirective.""" + + def run(self) -> List[Node]: + nodes = super().run() + + if self.config.zephyr_domain_apply_transforms: + return [RelatedCodeSamplesNode(id=self.arguments[0]), *nodes] + else: + return nodes + + +def setup(app): + app.add_config_value("zephyr_domain_apply_transforms", False, "env") + + app.add_domain(ZephyrDomain) + + app.add_transform(ConvertCodeSampleNode) + app.add_post_transform(ProcessRelatedCodeSamplesNode) + + # monkey-patching of Breathe's DoxygenGroupDirective + app.add_directive("doxygengroup", CustomDoxygenGroupDirective, override=True) + + return { + "version": __version__, + "parallel_read_safe": True, + "parallel_write_safe": True, + } diff --git a/doc/_extensions/zephyr/gh_utils.py b/doc/_extensions/zephyr/gh_utils.py new file mode 100644 index 00000000000..2c992436c87 --- /dev/null +++ b/doc/_extensions/zephyr/gh_utils.py @@ -0,0 +1,247 @@ +""" +Git/GitHub utilities for Sphinx +############################### + +Copyright (c) 2021 Nordic Semiconductor ASA +Copyright (c) 2023 The Linux Foundation + +SPDX-License-Identifier: Apache-2.0 + +Introduction +============ + +This Sphinx extension can be used to obtain various Git and GitHub related metadata for a page. +This is useful, for example, when adding features like "Open on GitHub" on top +of pages, direct links to open a GitHub issue regarding a page, or date of the most recent commit +to a page. + +The extension installs the following Jinja filter: + +* ``gh_link_get_blob_url``: Returns a URL to the source of a page on GitHub. +* ``gh_link_get_edit_url``: Returns a URL to edit the given page on GitHub. +* ``gh_link_get_open_issue_url``: Returns a URL to open a new issue regarding the given page. +* ``git_info``: Returns the date and SHA1 of the last commit made to a page (if this page is + managed by Git). + +Configuration options +===================== + +- ``gh_link_version``: GitHub version to use in the URL (e.g. "main") +- ``gh_link_base_url``: Base URL used as a prefix for generated URLs. +- ``gh_link_prefixes``: Mapping of pages (regex) <> GitHub prefix. +- ``gh_link_exclude``: List of pages (regex) that will not report a URL. Useful + for, e.g., auto-generated pages not in Git. +""" + +from functools import partial +import os +import re +import subprocess +import sys +from datetime import datetime +from pathlib import Path +from textwrap import dedent +from typing import Final, Optional, Tuple +from urllib.parse import quote + +from sphinx.application import Sphinx +from sphinx.util.i18n import format_date + +ZEPHYR_BASE : Final[str] = Path(__file__).parents[3] +SCRIPTS : Final[str] = ZEPHYR_BASE / "scripts" +sys.path.insert(0, str(SCRIPTS)) + +from get_maintainer import Maintainers + +MAINTAINERS : Final[Maintainers] = Maintainers(filename=f"{ZEPHYR_BASE}/MAINTAINERS.yml") + + +__version__ = "0.1.0" + + +def get_page_prefix(app: Sphinx, pagename: str) -> str: + """Return the prefix that needs to be added to the page path to get its location in the + repository. + + If pagename refers to a page that is automatically generated by Sphinx or if it matches one of + the patterns in ``gh_link_exclude`` configuration option, return None. + + Args: + app: Sphinx instance. + pagename: Page name (path). + + Returns: + Prefix if applicable, None otherwise. + """ + + if not os.path.isfile(app.env.doc2path(pagename)): + return None + + for exclude in app.config.gh_link_exclude: + if re.match(exclude, pagename): + return None + + found_prefix = "" + for pattern, prefix in app.config.gh_link_prefixes.items(): + if re.match(pattern, pagename): + found_prefix = prefix + break + + return found_prefix + + +def gh_link_get_url(app: Sphinx, pagename: str, mode: str = "blob") -> Optional[str]: + """Obtain GitHub URL for the given page. + + Args: + app: Sphinx instance. + mode: Typically "edit", or "blob". + pagename: Page name (path). + + Returns: + GitHub URL if applicable, None otherwise. + """ + + page_prefix = get_page_prefix(app, pagename) + if page_prefix is None: + return None + + return "/".join( + [ + app.config.gh_link_base_url, + mode, + app.config.gh_link_version, + page_prefix, + app.env.doc2path(pagename, False), + ] + ) + + +def gh_link_get_open_issue_url(app: Sphinx, pagename: str, sha1: str) -> Optional[str]: + """Link to open a new Github issue regarding "pagename" with title, body, and + labels already pre-filled with useful information. + + Args: + app: Sphinx instance. + pagename: Page name (path). + + Returns: + URL to open a new issue if applicable, None otherwise. + """ + + page_prefix = get_page_prefix(app, pagename) + if page_prefix is None: + return None + + rel_path = os.path.join( + os.path.relpath(ZEPHYR_BASE), + page_prefix, + app.env.doc2path(pagename, False), + ) + + title = quote(f"doc: Documentation issue in '{pagename}'") + labels = quote("area: Documentation") + areas = MAINTAINERS.path2areas(rel_path) + if areas: + labels += "," + ",".join([label for area in areas for label in area.labels]) + body = quote( + dedent( + f"""\ + **Describe the bug** + + << Please describe the issue here >> + << You may also want to update the automatically generated issue title above. >> + + **Environment** + + * Page: `{pagename}` + * Version: {app.config.gh_link_version} + * SHA-1: {sha1} + """ + ) + ) + + return f"{app.config.gh_link_base_url}/issues/new?title={title}&labels={labels}&body={body}" + + +def git_info_filter(app: Sphinx, pagename) -> Optional[Tuple[str, str]]: + """Return a tuple with the date and SHA1 of the last commit made to a page. + + Arguments: + app {Sphinx} -- Sphinx application object + pagename {str} -- Page name + + Returns: + Optional[Tuple[str, str]] -- Tuple with the date and SHA1 of the last commit made to the + page, or None if the page is not in the repo. + """ + + page_prefix = get_page_prefix(app, pagename) + if page_prefix is None: + return None + + orig_path = os.path.join( + ZEPHYR_BASE, + page_prefix, + app.env.doc2path(pagename, False), + ) + + try: + date_and_sha1 = ( + subprocess.check_output( + [ + "git", + "log", + "-1", + "--format=%ad %H", + "--date=unix", + orig_path, + ], + stderr=subprocess.STDOUT, + ) + .decode("utf-8") + .strip() + ) + date, sha1 = date_and_sha1.split(" ", 1) + date_object = datetime.fromtimestamp(int(date)) + last_update_fmt = app.config.html_last_updated_fmt + if last_update_fmt is not None: + date = format_date(last_update_fmt, date=date_object, language=app.config.language) + + return (date, sha1) + except subprocess.CalledProcessError: + return None + + +def add_jinja_filter(app: Sphinx): + if app.builder.format != "html": + return + + app.builder.templates.environment.filters["gh_link_get_blob_url"] = partial( + gh_link_get_url, app, mode="blob" + ) + + app.builder.templates.environment.filters["gh_link_get_edit_url"] = partial( + gh_link_get_url, app, mode="edit" + ) + + app.builder.templates.environment.filters["gh_link_get_open_issue_url"] = partial( + gh_link_get_open_issue_url, app + ) + + app.builder.templates.environment.filters["git_info"] = partial(git_info_filter, app) + + +def setup(app: Sphinx): + app.add_config_value("gh_link_version", "", "") + app.add_config_value("gh_link_base_url", "", "") + app.add_config_value("gh_link_prefixes", {}, "") + app.add_config_value("gh_link_exclude", [], "") + + app.connect("builder-inited", add_jinja_filter) + + return { + "version": __version__, + "parallel_read_safe": True, + "parallel_write_safe": True, + } diff --git a/doc/_extensions/zephyr/kconfig/__init__.py b/doc/_extensions/zephyr/kconfig/__init__.py index e5992a15dde..c4042e298ad 100644 --- a/doc/_extensions/zephyr/kconfig/__init__.py +++ b/doc/_extensions/zephyr/kconfig/__init__.py @@ -44,7 +44,7 @@ from sphinx.environment import BuildEnvironment from sphinx.errors import ExtensionError from sphinx.roles import XRefRole -from sphinx.util import progress_message +from sphinx.util.display import progress_message from sphinx.util.docutils import SphinxDirective from sphinx.util.nodes import make_refnode diff --git a/doc/_extensions/zephyr/kconfig/static/kconfig.mjs b/doc/_extensions/zephyr/kconfig/static/kconfig.mjs index ae27532ab6a..6c94845a107 100644 --- a/doc/_extensions/zephyr/kconfig/static/kconfig.mjs +++ b/doc/_extensions/zephyr/kconfig/static/kconfig.mjs @@ -491,7 +491,7 @@ function setupKconfigSearch() { doSearchFromURL(); /* install event listeners */ - input.addEventListener('keyup', () => { + input.addEventListener('input', () => { searchOffset = 0; doSearch(); }); diff --git a/doc/_extensions/zephyr/manifest_projects_table.py b/doc/_extensions/zephyr/manifest_projects_table.py new file mode 100644 index 00000000000..0eaa06d45cf --- /dev/null +++ b/doc/_extensions/zephyr/manifest_projects_table.py @@ -0,0 +1,141 @@ +""" +Manifest Revisions Table +======================== + +This extension allows to render a table containing the revisions of the projects +present in a manifest file. + +Usage +***** + +This extension introduces a new directive: ``manifest-projects-table``. It can +be used in the code as:: + + .. manifest-projects-table:: + :filter: active + +where the ``:filter:`` option can have the following values: active, inactive, all. + +Options +******* + +- ``manifest_projects_table_manifest``: Path to the manifest file. + +Copyright (c) Nordic Semiconductor ASA 2022 +Copyright (c) Intel Corp 2023 +SPDX-License-Identifier: Apache-2.0 +""" + +import re +from typing import Any, Dict, List + +from docutils import nodes +from docutils.parsers.rst import directives +from sphinx.application import Sphinx +from sphinx.util.docutils import SphinxDirective +from west.manifest import Manifest + + +__version__ = "0.1.0" + + +class ManifestProjectsTable(SphinxDirective): + """Manifest revisions table.""" + + option_spec = { + "filter": directives.unchanged, + } + + @staticmethod + def rev_url(base_url: str, rev: str) -> str: + """Return URL for a revision. + + Notes: + Revision format is assumed to be a git hash or a tag. URL is + formatted assuming a GitHub base URL. + + Args: + base_url: Base URL of the repository. + rev: Revision. + + Returns: + URL for the revision. + """ + + if re.match(r"^[0-9a-f]{40}$", rev): + return f"{base_url}/commit/{rev}" + + return f"{base_url}/releases/tag/{rev}" + + def run(self) -> List[nodes.Element]: + active_filter = self.options.get("filter", None) + + manifest = Manifest.from_file(self.env.config.manifest_projects_table_manifest) + projects = [] + for project in manifest.projects: + if project.name == "manifest": + continue + if active_filter == 'active' and manifest.is_active(project): + projects.append(project) + elif active_filter == 'inactive' and not manifest.is_active(project): + projects.append(project) + elif active_filter == 'all' or active_filter is None: + projects.append(project) + + # build table + table = nodes.table() + + tgroup = nodes.tgroup(cols=2) + tgroup += nodes.colspec(colwidth=1) + tgroup += nodes.colspec(colwidth=1) + table += tgroup + + thead = nodes.thead() + tgroup += thead + + row = nodes.row() + thead.append(row) + + entry = nodes.entry() + entry += nodes.paragraph(text="Project") + row += entry + entry = nodes.entry() + entry += nodes.paragraph(text="Revision") + row += entry + + rows = [] + for project in projects: + row = nodes.row() + rows.append(row) + + entry = nodes.entry() + entry += nodes.paragraph(text=project.name) + row += entry + entry = nodes.entry() + par = nodes.paragraph() + par += nodes.reference( + project.revision, + project.revision, + internal=False, + refuri=ManifestProjectsTable.rev_url(project.url, project.revision), + ) + entry += par + row += entry + + tbody = nodes.tbody() + tbody.extend(rows) + tgroup += tbody + + return [table] + + +def setup(app: Sphinx) -> Dict[str, Any]: + app.add_config_value("manifest_projects_table_manifest", None, "env") + + directives.register_directive("manifest-projects-table", ManifestProjectsTable) + + return { + "version": __version__, + "parallel_read_safe": True, + "parallel_write_safe": True, + } diff --git a/doc/_extensions/zephyr/vcs_link.py b/doc/_extensions/zephyr/vcs_link.py deleted file mode 100644 index 23aedb5ef33..00000000000 --- a/doc/_extensions/zephyr/vcs_link.py +++ /dev/null @@ -1,89 +0,0 @@ -""" -VCS Link -######## - -Copyright (c) 2021 Nordic Semiconductor ASA -SPDX-License-Identifier: Apache-2.0 - -Introduction -============ - -This Sphinx extension can be used to obtain the VCS URL for a given Sphinx page. -This is useful, for example, when adding features like "Open on GitHub" on top -of pages. The extension installs a Jinja filter which can be used on the -template to obtain VCS page URLs. - -Configuration options -===================== - -- ``vcs_link_base_url``: Base URL used as a prefix for generated URLs. -- ``vcs_link_prefixes``: Mapping of pages (regex) <> VCS prefix. -- ``vcs_link_exclude``: List of pages (regex) that will not report a URL. Useful - for, e.g., auto-generated pages not in VCS. -""" - -from functools import partial -import os -import re -from typing import Optional - -from sphinx.application import Sphinx - - -__version__ = "0.1.0" - - -def vcs_link_get_url(app: Sphinx, pagename: str) -> Optional[str]: - """Obtain VCS URL for the given page. - - Args: - app: Sphinx instance. - pagename: Page name (path). - - Returns: - VCS URL if applicable, None otherwise. - """ - - if not os.path.isfile(app.env.project.doc2path(pagename)): - return None - - for exclude in app.config.vcs_link_exclude: - if re.match(exclude, pagename): - return None - - found_prefix = "" - for pattern, prefix in app.config.vcs_link_prefixes.items(): - if re.match(pattern, pagename): - found_prefix = prefix - break - - return "/".join( - [ - app.config.vcs_link_base_url, - found_prefix, - app.env.project.doc2path(pagename, basedir=False), - ] - ) - - -def add_jinja_filter(app: Sphinx): - if app.builder.name != "html": - return - - app.builder.templates.environment.filters["vcs_link_get_url"] = partial( - vcs_link_get_url, app - ) - - -def setup(app: Sphinx): - app.add_config_value("vcs_link_base_url", "", "") - app.add_config_value("vcs_link_prefixes", {}, "") - app.add_config_value("vcs_link_exclude", [], "") - - app.connect("builder-inited", add_jinja_filter) - - return { - "version": __version__, - "parallel_read_safe": True, - "parallel_write_safe": True, - } diff --git a/doc/_scripts/redirects.py b/doc/_scripts/redirects.py index 6b4825c6c91..0180d1f5373 100644 --- a/doc/_scripts/redirects.py +++ b/doc/_scripts/redirects.py @@ -163,4 +163,6 @@ ('reference/usermode/overview', 'kernel/usermode/overview'), ('reference/usermode/syscalls', 'kernel/usermode/syscalls'), ('reference/util/index', 'kernel/util/index'), + ('samples/drivers/kscan_touch', 'samples/subsys/input/input'), + ('samples/net/cloud/google_iot_mqtt', 'samples/net/cloud'), ] diff --git a/doc/_static/css/custom.css b/doc/_static/css/custom.css index da9f379d41d..72756780b8e 100644 --- a/doc/_static/css/custom.css +++ b/doc/_static/css/custom.css @@ -306,6 +306,12 @@ a.icon-home:visited { white-space: normal; } +/* Allow to control wrapping behavior per table */ +.wy-table-responsive table.wrap-normal td, +.wy-table-responsive table.wrap-normal th { + white-space: normal; +} + /* Make sure not to wrap keyboard shortcuts */ .wy-table-responsive table td kbd { white-space: nowrap; @@ -544,6 +550,22 @@ a.internal:visited code.literal { color: var(--admonition-tip-title-color); } +/* Admonition tweaks - sphinx_togglebutton */ + +.rst-content .admonition.toggle { + overflow: visible; +} + +.rst-content .admonition.toggle button { + display: inline-flex; + color: var(--admonition-note-title-color); +} + +.rst-content .admonition.toggle .tb-icon { + height: 1em; + width: 1em; +} + /* Keyboard shortcuts tweaks */ kbd, .kbd, .rst-content :not(dl.option-list) > :not(dt):not(kbd):not(.kbd) > kbd, @@ -560,6 +582,14 @@ kbd, .kbd, vertical-align: middle; } +/* guilabel and menuselection tweaks */ +.rst-content .guilabel, +.rst-content .menuselection { + color: var(--body-color); + background-color: var(--guiitems-background-color); + border-color: var(--guiitems-border-color); +} + /* Buttons */ .btn-neutral { diff --git a/doc/_static/css/dark.css b/doc/_static/css/dark.css index a577bd69d35..47d555242f6 100644 --- a/doc/_static/css/dark.css +++ b/doc/_static/css/dark.css @@ -87,6 +87,9 @@ --kbd-shadow-color: #1e2023; --kbd-text-color: #e2f2ff; + --guiitems-background-color: #303d4f; + --guiitems-border-color: #7fbbe3; + --btn-neutral-background-color: #404040; --btn-neutral-hover-background-color: #505050; --footer-color: #aaa; diff --git a/doc/_static/css/light.css b/doc/_static/css/light.css index 625516dce31..0389650278c 100644 --- a/doc/_static/css/light.css +++ b/doc/_static/css/light.css @@ -85,6 +85,9 @@ --kbd-shadow-color: #b0b7bf; --kbd-text-color: #444d56; + --guiitems-background-color: #e7f2fa; + --guiitems-border-color: #7fbbe3; + --btn-neutral-background-color: #f3f6f6; --btn-neutral-hover-background-color: #e5ebeb; --footer-color: #808080; diff --git a/doc/_templates/breadcrumbs.html b/doc/_templates/breadcrumbs.html index c0052e0ce53..d1855e491fd 100644 --- a/doc/_templates/breadcrumbs.html +++ b/doc/_templates/breadcrumbs.html @@ -18,10 +18,16 @@
  • - {%- if display_vcs_link %} - {% set vcs_url = pagename | vcs_link_get_url %} - {% if vcs_url %} - {{ _('Open on GitHub') }} + {%- if display_gh_links %} + {% set gh_blob_url = pagename | gh_link_get_blob_url %} + {% if gh_blob_url %} + {{ _('Open on GitHub') }} + {% endif %} + {%- set git_last_updated, sha1 = pagename | git_info | default((None, None), true) %} + {%- if sha1 %} + + {{ _('Report an issue with this page')}} + {% endif %} {% endif %}
  • diff --git a/doc/_templates/footer.html b/doc/_templates/footer.html new file mode 100644 index 00000000000..54ba724acb3 --- /dev/null +++ b/doc/_templates/footer.html @@ -0,0 +1,30 @@ +{% extends "!footer.html" %} +{% block contentinfo %} +

    + {%- if show_copyright %} + © Copyright {{ copyright }}. + {%- endif %} + + {%- if last_updated %} + + Last generated on {{ last_updated }}. + + {%- endif -%} +

    +{%- set git_last_updated, sha1 = pagename | git_info | default((None, None), true) %} +{%- if git_last_updated %} +
    +

    + Help us keep our technical documentation accurate and up-to-date! +

    +

    + The human-authored contents on this page was last updated on {{ git_last_updated }}. +

    +

    + If you find any errors on this page, outdated information, or have any other suggestion for + improving its contents, please consider + opening an issue. +

    +
    +{%- endif %} +{% endblock %} diff --git a/doc/build/cmake/index.rst b/doc/build/cmake/index.rst index 479e044b68e..534c3ff34e1 100644 --- a/doc/build/cmake/index.rst +++ b/doc/build/cmake/index.rst @@ -108,7 +108,7 @@ Devicetree :ref:`dt-guide`. Kconfig - :file:`Kconfig` files define available configuration options for for the + :file:`Kconfig` files define available configuration options for the target architecture, SoC, board, and application, as well as dependencies between options. diff --git a/doc/build/dts/api-usage.rst b/doc/build/dts/api-usage.rst index 97949d86f67..b31c1e9baf3 100644 --- a/doc/build/dts/api-usage.rst +++ b/doc/build/dts/api-usage.rst @@ -47,7 +47,7 @@ By node label By alias Use :c:func:`DT_ALIAS()` to get a node identifier for a property of the special ``/aliases`` node. This is sometimes done by applications (like - :ref:`blinky `, which uses the ``led0`` alias) that need to + :zephyr:code-sample:`blinky`, which uses the ``led0`` alias) that need to refer to *some* device of a particular type ("the board's user LED") but don't care which one is used. diff --git a/doc/build/dts/api/api.rst b/doc/build/dts/api/api.rst index f3a8c2bcb0d..44b87653cc3 100644 --- a/doc/build/dts/api/api.rst +++ b/doc/build/dts/api/api.rst @@ -140,6 +140,7 @@ depends on" relation: - a node directly depends on any nodes its properties refer to by phandle - a node directly depends on its ``interrupt-parent`` if it has an ``interrupts`` property +- a parent node inherits all dependencies from its child nodes A *dependency ordering* of a devicetree is a list of its nodes, where each node ``n`` appears earlier in the list than any nodes that depend on ``n``. A node's @@ -294,15 +295,6 @@ and properties related to them. .. doxygengroup:: devicetree-mbox -.. _devicetree-memory-attr-api: - -Memory attributes -================= - -These conveniences may be used for nodes with a memory attribute property. - -.. doxygengroup:: devicetree-memory-attr - .. _devicetree-pinctrl-api: Pinctrl (pin control) @@ -432,6 +424,9 @@ device. interprocess-communication (IPC) * - zephyr,itcm - Instruction Tightly Coupled Memory node on some Arm SoCs + * - zephyr,log-uart + - Sets the UART device(s) used by the logging subsystem's UART backend. + If defined, the UART log backend would output to the devices listed in this node. * - zephyr,ocm - On-chip memory node on Xilinx Zynq-7000 and ZynqMP SoCs * - zephyr,osdp-uart diff --git a/doc/build/dts/design.rst b/doc/build/dts/design.rst index 82cfe652287..34d26cb7441 100644 --- a/doc/build/dts/design.rst +++ b/doc/build/dts/design.rst @@ -22,7 +22,7 @@ Examples - In-tree sample applications shall use :ref:`aliases ` to determine which of multiple possible generic devices of a given type will be - used in the current build. For example, the :ref:`blinky-sample` uses this to + used in the current build. For example, the :zephyr:code-sample:`blinky` sample uses this to determine the LED to blink. - Boot-time pin muxing and pin control for new SoCs shall be accomplished via a diff --git a/doc/build/dts/howtos.rst b/doc/build/dts/howtos.rst index f1a003f2f94..cb556bb782d 100644 --- a/doc/build/dts/howtos.rst +++ b/doc/build/dts/howtos.rst @@ -149,7 +149,9 @@ that the node has ``status = "okay"``, like this: If you see the ``#error`` output, make sure to enable the node in your devicetree. In some situations your code will compile but it will fail to link -with a message similar to:: +with a message similar to: + +.. code-block:: none ...undefined reference to `__device_dts_ord_N' collect2: error: ld returned 1 exit status @@ -299,6 +301,7 @@ For example, if your BOARD.dts contains this node: These are equivalent ways to override the ``current-speed`` value in an overlay: +.. Disable syntax highlighting as this construct does not seem supported by pygments .. code-block:: none /* Option 1 */ @@ -316,7 +319,7 @@ We'll use the ``&serial0`` style for the rest of these examples. You can add aliases to your devicetree using overlays: an alias is just a property of the ``/aliases`` node. For example: -.. code-block:: none +.. code-block:: devicetree / { aliases { @@ -326,7 +329,7 @@ property of the ``/aliases`` node. For example: Chosen nodes work the same way. For example: -.. code-block:: none +.. code-block:: devicetree / { chosen { @@ -337,7 +340,7 @@ Chosen nodes work the same way. For example: To delete a property (in addition to deleting properties in general, this is how to set a boolean property to false if it's true in BOARD.dts): -.. code-block:: none +.. code-block:: devicetree &serial0 { /delete-property/ some-unwanted-property; @@ -346,7 +349,7 @@ how to set a boolean property to false if it's true in BOARD.dts): You can add subnodes using overlays. For example, to configure a SPI or I2C child device on an existing bus node, do something like this: -.. code-block:: none +.. code-block:: devicetree /* SPI device example */ &spi1 { @@ -630,6 +633,6 @@ Applications that depend on board-specific devices One way to allow application code to run unmodified on multiple boards is by supporting a devicetree alias to specify the hardware specific portions, as is -done in the :ref:`blinky-sample`. The application can then be configured in +done in the :zephyr:code-sample:`blinky` sample. The application can then be configured in :ref:`BOARD.dts ` files or via :ref:`devicetree overlays `. diff --git a/doc/build/dts/intro-input-output.rst b/doc/build/dts/intro-input-output.rst index 7b2c2a1119c..365d9fd3c37 100644 --- a/doc/build/dts/intro-input-output.rst +++ b/doc/build/dts/intro-input-output.rst @@ -23,7 +23,9 @@ There are four types of devicetree input files: - overlays (``.overlay``) - bindings (``.yaml``) -The devicetree files inside the :file:`zephyr` directory look like this:: +The devicetree files inside the :file:`zephyr` directory look like this: + +.. code-block:: none boards///.dts dts/common/skeleton.dtsi diff --git a/doc/build/dts/intro-syntax-structure.rst b/doc/build/dts/intro-syntax-structure.rst index 1a92215a1d9..1fd7eead9f8 100644 --- a/doc/build/dts/intro-syntax-structure.rst +++ b/doc/build/dts/intro-syntax-structure.rst @@ -370,7 +370,7 @@ curious about details, see the devicetree specification. Additional notes on the above: - The values in the ``phandle``, ``phandles``, and ``phandle-array`` types are - are described further in :ref:`dt-phandles` + described further in :ref:`dt-phandles` - Boolean properties are true if present. They should not have a value. A boolean property is only false if it is completely missing in the DTS. @@ -387,9 +387,11 @@ Additional notes on the above: that order. - Parentheses, arithmetic operators, and bitwise operators are allowed. The - ``bar`` property contains a single cell with value 64:: + ``bar`` property contains a single cell with value 64: - bar = <(2 * (1 << 5))>; + .. code-block:: devicetree + + bar = <(2 * (1 << 5))>; Note that the entire expression must be parenthesized. @@ -419,7 +421,7 @@ Additional notes on the above: - Array and similar type property values can be split into several ``<>`` blocks, like this: - .. code-block:: none + .. code-block:: devicetree foo = <1 2>, <3 4>; // Okay for 'type: array' foo = <&label1 &label2>, <&label3 &label4>; // Okay for 'type: phandles' @@ -468,7 +470,7 @@ Using its node label ``uart0``, the same node is set as the value of the chosen Zephyr sample applications sometimes use aliases to allow overriding the particular hardware device used by the application in a generic way. For -example, :ref:`blinky-sample` uses this to abstract the LED to blink via the +example, :zephyr:code-sample:`blinky` uses this to abstract the LED to blink via the ``led0`` alias. The ``/chosen`` node's properties are used to configure system- or diff --git a/doc/build/dts/troubleshooting.rst b/doc/build/dts/troubleshooting.rst index 563ce04aac5..54169b3ab42 100644 --- a/doc/build/dts/troubleshooting.rst +++ b/doc/build/dts/troubleshooting.rst @@ -193,7 +193,7 @@ as you enable the devicetree node. Otherwise, it is sometimes as simple as adding a line like this to your application's :file:`prj.conf` file and then making sure to :ref:`dt-trouble-try-pristine`: -.. code-block:: none +.. code-block:: cfg CONFIG_FOO=y diff --git a/doc/build/kconfig/extensions.rst b/doc/build/kconfig/extensions.rst index c8cb285aeb5..9ee8b33c85f 100644 --- a/doc/build/kconfig/extensions.rst +++ b/doc/build/kconfig/extensions.rst @@ -8,6 +8,42 @@ implementation of `Kconfig `__, which includes some Kconfig extensions: +- Default values can be applied to existing symbols without + :ref:`weakening ` the symbols dependencies + through the use of ``configdefault``. + + .. code-block:: none + + config FOO + bool "FOO" + depends on BAR + + configdefault FOO + default y if FIZZ + + The statement above is equivalent to: + + .. code-block:: none + + config FOO + bool "Foo" + default y if FIZZ + depends on BAR + + ``configdefault`` symbols cannot contain any fields other than ``default``, + however they can be wrapped in ``if`` statements. The two statements below + are equivalent: + + .. code-block:: none + + configdefault FOO + default y if BAR + + if BAR + configdefault FOO + default y + endif # BAR + - Environment variables in ``source`` statements are expanded directly, meaning no "bounce" symbols with ``option env="ENV_VAR"`` need to be defined. @@ -26,7 +62,7 @@ which includes some Kconfig extensions: Consider the following example: - .. code-block:: none + .. code-block:: kconfig source "foo/bar/*/Kconfig" @@ -34,7 +70,7 @@ which includes some Kconfig extensions: :file:`foo/bar/baz/Kconfig` and :file:`foo/bar/qaz/Kconfig`, the statement above is equivalent to the following two ``source`` statements: - .. code-block:: none + .. code-block:: kconfig source "foo/bar/baz/Kconfig" source "foo/bar/qaz/Kconfig" @@ -61,7 +97,7 @@ which includes some Kconfig extensions: :file:`Kconfig` file, and that :file:`foo/bar/Kconfig` has the following statements: - .. code-block:: none + .. code-block:: kconfig source "qaz/Kconfig1" rsource "qaz/Kconfig2" @@ -83,7 +119,7 @@ which includes some Kconfig extensions: For example, the following statement will include :file:`Kconfig1` and :file:`Kconfig2` from the current directory (if they exist): - .. code-block:: none + .. code-block:: kconfig orsource "Kconfig[12]" diff --git a/doc/build/kconfig/preprocessor-functions.rst b/doc/build/kconfig/preprocessor-functions.rst index 295d50af7c4..ae3777444d8 100644 --- a/doc/build/kconfig/preprocessor-functions.rst +++ b/doc/build/kconfig/preprocessor-functions.rst @@ -28,45 +28,43 @@ while the ``*_hex`` version returns a hexadecimal value starting with ``0x``. .. code-block:: none - $(dt_has_compat,) - $(dt_compat_enabled,) - $(dt_compat_on_bus,,) - $(dt_chosen_label,) + $(dt_alias_enabled,) + $(dt_chosen_bool_prop, , ) $(dt_chosen_enabled,) - $(dt_chosen_path,) $(dt_chosen_has_compat,) - $(dt_path_enabled,) - $(dt_alias_enabled,) - $(dt_nodelabel_enabled,) - $(dt_nodelabel_enabled_with_compat,,) - $(dt_chosen_reg_addr_int,[,,]) + $(dt_chosen_label,) + $(dt_chosen_path,) $(dt_chosen_reg_addr_hex,[,,]) - $(dt_chosen_reg_size_int,[,,]) + $(dt_chosen_reg_addr_int,[,,]) $(dt_chosen_reg_size_hex,[,,]) - $(dt_node_reg_addr_int,[,,]) - $(dt_node_reg_addr_hex,[,,]) - $(dt_node_reg_size_int,[,,]) - $(dt_node_reg_size_hex,[,,]) - $(dt_nodelabel_reg_addr_int,[,,]) - $(dt_nodelabel_reg_addr_hex,[,,]) - $(dt_nodelabel_reg_size_int,[,,]) - $(dt_nodelabel_reg_size_hex,[,,]) + $(dt_chosen_reg_size_int,[,,]) $(dt_compat_enabled,) - $(dt_chosen_enabled,) + $(dt_compat_on_bus,,) + $(dt_gpio_hogs_enabled) + $(dt_has_compat,) $(dt_node_bool_prop,,) - $(dt_nodelabel_bool_prop,,) - $(dt_chosen_bool_prop, , ) + $(dt_node_has_compat,,) $(dt_node_has_prop,,) - $(dt_nodelabel_has_prop,,) - $(dt_node_int_prop_int,,[,]) $(dt_node_int_prop_hex,,[,]) + $(dt_node_int_prop_int,,[,]) + $(dt_node_parent,) + $(dt_node_reg_addr_hex,[,,]) + $(dt_node_reg_addr_int,[,,]) + $(dt_node_reg_size_hex,[,,]) + $(dt_node_reg_size_int,[,,]) $(dt_node_str_prop_equals,,,) + $(dt_nodelabel_array_prop_has_val, , , ) + $(dt_nodelabel_bool_prop,,) + $(dt_nodelabel_enabled,) + $(dt_nodelabel_enabled_with_compat,,) $(dt_nodelabel_has_compat,,) - $(dt_node_has_compat,,) + $(dt_nodelabel_has_prop,,) $(dt_nodelabel_path,) - $(dt_node_parent,) - $(dt_nodelabel_array_prop_has_val, , , ) - $(dt_gpio_hogs_enabled) + $(dt_nodelabel_reg_addr_hex,[,,]) + $(dt_nodelabel_reg_addr_int,[,,]) + $(dt_nodelabel_reg_size_hex,[,,]) + $(dt_nodelabel_reg_size_int,[,,]) + $(dt_path_enabled,) $(shields_list_contains,) @@ -75,7 +73,7 @@ Example Usage Assume that the devicetree for some board looks like this: -.. code-block:: none +.. code-block:: devicetree { soc { @@ -94,14 +92,14 @@ The second entry in ``reg`` in ``spi@1001400`` (``<0x20010000 0x3c0900>``) corresponds to ``mem``, and has the address ``0x20010000``. This address can be inserted into Kconfig as follows: -.. code-block:: none +.. code-block:: kconfig config FLASH_BASE_ADDRESS default $(dt_node_reg_addr_hex,/soc/spi@1001400,1) After preprocessor expansion, this turns into the definition below: -.. code-block:: none +.. code-block:: kconfig config FLASH_BASE_ADDRESS default 0x20010000 diff --git a/doc/build/kconfig/setting.rst b/doc/build/kconfig/setting.rst index 5f37e831e9e..cc7658a1664 100644 --- a/doc/build/kconfig/setting.rst +++ b/doc/build/kconfig/setting.rst @@ -27,7 +27,7 @@ between *visible* and *invisible* symbols. Here's an example of a visible symbol: - .. code-block:: none + .. code-block:: kconfig config FPU bool "Support floating point operations" @@ -46,7 +46,7 @@ between *visible* and *invisible* symbols. Here's an example of an invisible symbol: - .. code-block:: none + .. code-block:: kconfig config CPU_HAS_FPU bool @@ -67,7 +67,7 @@ board with application settings, usually from :file:`prj.conf`. See Assignments in configuration files use this syntax: -.. code-block:: none +.. code-block:: cfg CONFIG_= @@ -77,7 +77,7 @@ There should be no spaces around the equals sign. respectively. The ``FPU`` symbol from the example above could be enabled like this: -.. code-block:: none +.. code-block:: cfg CONFIG_FPU=y @@ -86,7 +86,7 @@ this: A boolean symbol can also be set to ``n`` with a comment formatted like this: - .. code-block:: none + .. code-block:: cfg # CONFIG_SOME_OTHER_BOOL is not set @@ -99,14 +99,14 @@ this: Other symbol types are assigned like this: -.. code-block:: none +.. code-block:: cfg CONFIG_SOME_STRING="cool value" CONFIG_SOME_INT=123 Comments use a #: -.. code-block:: none +.. code-block:: cfg # This is a comment @@ -137,7 +137,7 @@ known as a Kconfig fragment, which are then merged to get the final configuration used for a particular build). By default, :file:`prj.conf` is used. -1. If ``CONF_FILE`` is set, the configuration file(s) specified in it are +#. If ``CONF_FILE`` is set, the configuration file(s) specified in it are merged and used as the application configuration. ``CONF_FILE`` can be set in various ways: @@ -147,25 +147,25 @@ used. 3. From the CMake variable cache -2. Otherwise if ``CONF_FILE`` is set, and a single configuration file of the - form :file:`prj_.conf` is used, then if file + Furthermore if ``CONF_FILE`` is set as single configuration file of the + form :file:`prj_.conf` and if file :file:`boards/_.conf` exists in same folder as file :file:`prj_.conf`, the result of merging :file:`prj_.conf` and :file:`boards/_.conf` is used. -3. Otherwise, :file:`prj_.conf` is used if it exists in the application +#. Otherwise, :file:`prj_.conf` is used if it exists in the application configuration directory. -4. Otherwise, if :file:`boards/.conf` exists in the application +#. Otherwise, if :file:`boards/.conf` exists in the application configuration directory, the result of merging it with :file:`prj.conf` is used. -5. Otherwise, if board revisions are used and +#. Otherwise, if board revisions are used and :file:`boards/_.conf` exists in the application configuration directory, the result of merging it with :file:`prj.conf` and :file:`boards/.conf` is used. -6. Otherwise, :file:`prj.conf` is used from the application configuration +#. Otherwise, :file:`prj.conf` is used from the application configuration directory. If it does not exist then a fatal error will be emitted. All configuration files will be taken from the application's configuration @@ -210,7 +210,7 @@ Assigning values in :file:`Kconfig.defconfig` relies on defining a Kconfig symbol in multiple locations. As an example, say we want to set ``FOO_WIDTH`` below to 32: -.. code-block:: none +.. code-block:: kconfig config FOO_WIDTH int @@ -218,7 +218,7 @@ below to 32: To do this, we extend the definition of ``FOO_WIDTH`` as follows, in :file:`Kconfig.defconfig`: -.. code-block:: none +.. code-block:: kconfig if BOARD_MY_BOARD @@ -244,25 +244,51 @@ Note that conditions from surrounding top-level ``if``\ s are propagated to symbol properties, so the above ``default`` is equivalent to ``default 32 if BOARD_MY_BOARD``. -.. warning:: +.. _multiple_symbol_definitions: - When defining a symbol in multiple locations, dependencies are ORed together - rather than ANDed together. It is not possible to make the dependencies of a - symbol more restrictive by defining it in multiple locations. +Multiple symbol definitions +--------------------------- - For example, the direct dependencies of the symbol below becomes - ``DEP1 || DEP2``: +When a symbol is defined in multiple locations, each definition acts as an +independent symbol that happens to share the same name. This means that +properties are not appended to previous definitions. If the conditions +for **ANY** definition result in the symbol resolving to ``y``, the symbol +will be ``y``. It is therefore not possible to make the dependencies of a +symbol more restrictive by defining it in multiple locations. - .. code-block:: none +For example, the dependencies of the symbol ``FOO`` below are satisfied if +either ``DEP1`` **OR** ``DEP2`` are true, it does not require both: + +.. code-block:: none + + config FOO + ... + depends on DEP1 + + config FOO + ... + depends on DEP2 + +.. warning:: + Symbols without explicit dependencies still follow the above rule. A + symbol without any dependencies will result in the symbol always being + assignable. The definition below will result in ``FOO`` always being + enabled by default, regardless of the value of ``DEP1``. + + .. code-block:: kconfig config FOO - ... - depends on DEP1 + bool "FOO" + depends on DEP1 config FOO - ... - depends on DEP2 + default y + This dependency weakening can be avoided with the :ref:`configdefault + ` extension if the desire is only to add a new default + without modifying any other behaviour of the symbol. + +.. note:: When making changes to :file:`Kconfig.defconfig` files, always check the symbol's direct dependencies in one of the :ref:`interactive configuration interfaces ` afterwards. It is often necessary to repeat @@ -310,7 +336,7 @@ There are two ways to configure a Kconfig ``choice``: As an example, assume that a choice has the following base definition (here, the name of the choice is ``FOO``): - .. code-block:: none + .. code-block:: kconfig choice FOO bool "Foo choice" @@ -327,7 +353,7 @@ There are two ways to configure a Kconfig ``choice``: To change the default symbol of ``FOO`` to ``A``, you would add the following definition to :file:`Kconfig.defconfig`: - .. code-block:: none + .. code-block:: kconfig choice FOO default A @@ -345,5 +371,4 @@ The :ref:`kconfig_tips_and_tricks` page has some tips for writing Kconfig files. The :zephyr_file:`kconfiglib.py ` docstring -docstring (at the top of the file) goes over how symbol values are calculated -in detail. +(at the top of the file) goes over how symbol values are calculated in detail. diff --git a/doc/build/kconfig/tips.rst b/doc/build/kconfig/tips.rst index 4deab152660..9bae4d2a1c7 100644 --- a/doc/build/kconfig/tips.rst +++ b/doc/build/kconfig/tips.rst @@ -83,7 +83,7 @@ An application-specific devicetree :ref:`binding ` to identify board specific properties may be appropriate. See :zephyr_file:`tests/drivers/gpio/gpio_basic_api` for an example. -For applications, see :ref:`blinky-sample` for a devicetree-based alternative. +For applications, see :zephyr:code-sample:`blinky` for a devicetree-based alternative. ``select`` statements ********************* @@ -92,7 +92,7 @@ The ``select`` statement is used to force one symbol to ``y`` whenever another symbol is ``y``. For example, the following code forces ``CONSOLE`` to ``y`` whenever ``USB_CONSOLE`` is ``y``: -.. code-block:: none +.. code-block:: kconfig config CONSOLE bool "Console support" @@ -116,7 +116,7 @@ For example, say that a new dependency is added to the ``CONSOLE`` symbol above, by a developer who is unaware of the ``USB_CONSOLE`` symbol (or simply forgot about it): -.. code-block:: none +.. code-block:: kconfig config CONSOLE bool "Console support" @@ -128,7 +128,7 @@ Enabling ``USB_CONSOLE`` now forces ``CONSOLE`` to ``y``, even if To fix the problem, the ``STRING_ROUTINES`` dependency needs to be added to ``USB_CONSOLE`` as well: -.. code-block:: none +.. code-block:: kconfig config USB_CONSOLE bool "USB console support" @@ -146,7 +146,7 @@ statements are common. An alternative attempt to solve the issue might be to turn the ``depends on`` into another ``select``: -.. code-block:: none +.. code-block:: kconfig config CONSOLE bool "Console support" @@ -181,7 +181,7 @@ Alternatives to ``select`` For the example in the previous section, a better solution is usually to turn the ``select`` into a ``depends on``: -.. code-block:: none +.. code-block:: kconfig config CONSOLE bool "Console support" @@ -198,7 +198,7 @@ dependencies only ever have to be updated in a single spot. An objection to using ``depends on`` here might be that configuration files that enable ``USB_CONSOLE`` now also need to enable ``CONSOLE``: -.. code-block:: none +.. code-block:: cfg CONFIG_CONSOLE=y CONFIG_USB_CONSOLE=y @@ -206,7 +206,7 @@ that enable ``USB_CONSOLE`` now also need to enable ``CONSOLE``: This comes down to a trade-off, but if enabling ``CONSOLE`` is the norm, then a mitigation is to make ``CONSOLE`` default to ``y``: -.. code-block:: none +.. code-block:: kconfig config CONSOLE bool "Console support" @@ -214,14 +214,14 @@ mitigation is to make ``CONSOLE`` default to ``y``: This gives just a single assignment in configuration files: -.. code-block:: none +.. code-block:: cfg CONFIG_USB_CONSOLE=y Note that configuration files that do not want ``CONSOLE`` enabled now have to explicitly disable it: -.. code-block:: none +.. code-block:: cfg CONFIG_CONSOLE=n @@ -238,7 +238,7 @@ dependencies. For example, a helper symbol for indicating that a particular CPU/SoC has an FPU could be defined as follows: -.. code-block:: none +.. code-block:: kconfig config CPU_HAS_FPU bool @@ -260,7 +260,7 @@ FPU could be defined as follows: This makes it possible for other symbols to check for FPU support in a generic way, without having to look for particular architectures: -.. code-block:: none +.. code-block:: kconfig config FPU bool "Support floating point operations" @@ -269,7 +269,7 @@ way, without having to look for particular architectures: The alternative would be to have dependencies like the following, possibly duplicated in several spots: -.. code-block:: none +.. code-block:: kconfig config FPU bool "Support floating point operations" @@ -279,7 +279,7 @@ Invisible helper symbols can also be useful without ``select``. For example, the following code defines a helper symbol that has the value ``y`` if the machine has some arbitrarily-defined "large" amount of memory: -.. code-block:: none +.. code-block:: kconfig config LARGE_MEM def_bool MEM_SIZE >= 64 @@ -288,7 +288,7 @@ machine has some arbitrarily-defined "large" amount of memory: This is short for the following: - .. code-block:: none + .. code-block:: kconfig config LARGE_MEM bool @@ -325,7 +325,7 @@ on`` was used. A common misunderstanding related to ``if`` is to think that the following code conditionally includes the file :file:`Kconfig.other`: -.. code-block:: none +.. code-block:: kconfig if DEP source "Kconfig.other" @@ -342,14 +342,14 @@ meaning around a ``source``. Say that :file:`Kconfig.other` above contains this definition: -.. code-block:: none +.. code-block:: kconfig config FOO bool "Support foo" In this case, ``FOO`` will end up with this definition: -.. code-block:: none +.. code-block:: kconfig config FOO bool "Support foo" @@ -371,7 +371,7 @@ twice. There is a common subtle gotcha related to interdependent configuration symbols with prompts. Consider these symbols: -.. code-block:: none +.. code-block:: kconfig config FOO bool "Foo" @@ -396,7 +396,7 @@ To understand what's going on, remember that ``STACK_SIZE`` has a prompt, meaning it is user-configurable, and consider that all Kconfig has to go on from the initial configuration is this: -.. code-block:: none +.. code-block:: cfg CONFIG_STACK_SIZE=0x100 @@ -412,7 +412,7 @@ with suggestions: - If ``STACK_SIZE`` can always be derived automatically and does not need to be user-configurable, then just remove the prompt: - .. code-block:: none + .. code-block:: kconfig config STACK_SIZE hex @@ -425,7 +425,7 @@ with suggestions: 0x200 when ``FOO`` is enabled, then disable its prompt when ``FOO`` is enabled, as described in `optional prompts`_: - .. code-block:: none + .. code-block:: kconfig config STACK_SIZE hex "Stack size" if !FOO @@ -436,7 +436,7 @@ with suggestions: set to a custom value in rare circumstances, then add another option for making ``STACK_SIZE`` user-configurable: - .. code-block:: none + .. code-block:: kconfig config CUSTOM_STACK_SIZE bool "Use a custom stack size" @@ -500,7 +500,7 @@ calculating symbol values. The Kconfig definitions below will hide the ``FOO_DEVICE_FREQUENCY`` symbol and disable any configuration output for it when ``FOO_DEVICE`` is disabled. -.. code-block:: none +.. code-block:: kconfig config FOO_DEVICE bool "Foo device" @@ -530,7 +530,7 @@ children in a separate menu rooted at ``FOO``. ``menuconfig`` can cut down on the number of menus and make the menu structure easier to navigate. For example, say you have the following definitions: -.. code-block:: none +.. code-block:: kconfig menu "Foo subsystem" @@ -557,7 +557,7 @@ easier to navigate. For example, say you have the following definitions: In this case, it's probably better to get rid of the ``menu`` and turn ``FOO_SUBSYSTEM`` into a ``menuconfig`` symbol: -.. code-block:: none +.. code-block:: kconfig menuconfig FOO_SUBSYSTEM bool "Foo subsystem" @@ -599,7 +599,7 @@ Commas in macro arguments Kconfig uses commas to separate macro arguments. This means a construct like this will fail: -.. code-block:: none +.. code-block:: kconfig config FOO bool @@ -608,7 +608,7 @@ This means a construct like this will fail: To solve this problem, create a variable with the text and use this variable as argument, as follows: -.. code-block:: none +.. code-block:: kconfig DT_CHOSEN_ZEPHYR_BAR := zephyr,bar @@ -688,7 +688,7 @@ be factored out with an ``if``. As an example, consider the following code: -.. code-block:: none +.. code-block:: kconfig config FOO bool "Foo" @@ -712,7 +712,7 @@ As an example, consider the following code: Here, the ``DEP`` dependency can be factored out like this: -.. code-block:: none +.. code-block:: kconfig if DEP @@ -742,7 +742,7 @@ Here, the ``DEP`` dependency can be factored out like this: If a sequence of symbols/choices with shared dependencies are all in the same menu, the dependency can be put on the menu itself: -.. code-block:: none +.. code-block:: kconfig menu "Foo features" depends on FOO_SUPPORT @@ -782,7 +782,7 @@ a previously defined ``default y``. That is, FOO will be set to ``n`` in the example below. If the ``default n`` was omitted in the first definition, FOO would have been set to ``y``. - .. code-block:: none + .. code-block:: kconfig config FOO bool "foo" @@ -794,7 +794,7 @@ omitted in the first definition, FOO would have been set to ``y``. In the following example FOO will get the value ``y``. - .. code-block:: none + .. code-block:: kconfig config FOO bool "foo" @@ -814,12 +814,12 @@ Kconfig has two shorthands that deal with prompts and defaults. - `` "prompt"`` is a shorthand for giving a symbol/choice a type and a prompt at the same time. These two definitions are equal: - .. code-block:: none + .. code-block:: kconfig config FOO bool "foo" - .. code-block:: none + .. code-block:: kconfig config FOO bool @@ -830,12 +830,12 @@ Kconfig has two shorthands that deal with prompts and defaults. - ``def_ `` is a shorthand for giving a type and a value at the same time. These two definitions are equal: - .. code-block:: none + .. code-block:: kconfig config FOO def_bool BAR && BAZ - .. code-block:: none + .. code-block:: kconfig config FOO bool @@ -907,7 +907,7 @@ doesn't force a value. For example, the following code could be used to enable USB keyboard support by default on the FOO SoC, while still allowing the user to turn it off: -.. code-block:: none +.. code-block:: kconfig config SOC_FOO bool "FOO SoC" @@ -928,7 +928,7 @@ A condition can be put on a symbol's prompt to make it optionally configurable by the user. For example, a value ``MASK`` that's hardcoded to 0xFF on some boards and configurable on others could be expressed as follows: -.. code-block:: none +.. code-block:: kconfig config MASK hex "Bitmask" if HAS_CONFIGURABLE_MASK @@ -938,7 +938,7 @@ boards and configurable on others could be expressed as follows: This is short for the following: - .. code-block:: none + .. code-block:: kconfig config MASK hex @@ -956,7 +956,7 @@ Optional choices Defining a choice with the ``optional`` keyword allows the whole choice to be toggled off to select none of the symbols: -.. code-block:: none +.. code-block:: kconfig choice prompt "Use legacy protocol" @@ -983,7 +983,7 @@ within it, while still allowing symbol default values to kick in. As a motivating example, consider the following code: -.. code-block:: none +.. code-block:: kconfig menu "Foo subsystem" depends on HAS_CONFIGURABLE_FOO @@ -1002,7 +1002,7 @@ When ``HAS_CONFIGURABLE_FOO`` is ``n``, no configuration output is generated for ``FOO_SETTING_1`` and ``FOO_SETTING_2``, as the code above is logically equivalent to the following code: -.. code-block:: none +.. code-block:: kconfig config FOO_SETTING_1 int "Foo setting 1" @@ -1018,7 +1018,7 @@ If we want the symbols to still get their default values even when ``HAS_CONFIGURABLE_FOO`` is ``n``, but not be configurable by the user, then we can use ``visible if`` instead: -.. code-block:: none +.. code-block:: kconfig menu "Foo subsystem" visible if HAS_CONFIGURABLE_FOO @@ -1035,7 +1035,7 @@ can use ``visible if`` instead: This is logically equivalent to the following: -.. code-block:: none +.. code-block:: kconfig config FOO_SETTING_1 int "Foo setting 1" if HAS_CONFIGURABLE_FOO @@ -1053,7 +1053,7 @@ This is logically equivalent to the following: When ``HAS_CONFIGURABLE`` is ``n``, we now get the following configuration output for the symbols, instead of no output: -.. code-block:: none +.. code-block:: cfg ... CONFIG_FOO_SETTING_1=1 diff --git a/doc/build/sysbuild/index.rst b/doc/build/sysbuild/index.rst index e09ee3e5617..b66ec8938c7 100644 --- a/doc/build/sysbuild/index.rst +++ b/doc/build/sysbuild/index.rst @@ -104,21 +104,27 @@ As mentioned above, you can run sysbuild via ``west build`` or ``cmake``. .. tip:: To configure ``west build`` to use ``--sysbuild`` by default from now on, - run:: + run: - west config build.sysbuild True + .. code-block:: shell + + west config build.sysbuild True Since sysbuild supports both single- and multi-image builds, this lets you use sysbuild all the time, without worrying about what type of build you are running. - To turn this off, run this before generating your build system:: + To turn this off, run this before generating your build system: + + .. code-block:: shell + + west config build.sysbuild False - west config build.sysbuild False + To turn this off for just one ``west build`` command, run: - To turn this off for just one ``west build`` command, run:: + .. code-block:: shell - west build --no-sysbuild ... + west build --no-sysbuild ... .. group-tab:: ``cmake`` @@ -206,15 +212,15 @@ build system to the value ``BAR``, run the following commands: .. group-tab:: ``west build`` - :: + .. code-block:: shell west build --sysbuild ... -- -Dmy_sample_FOO=BAR .. group-tab:: ``cmake`` - :: + .. code-block:: shell - cmake -Dmy_sample_FOO=BAR ... + cmake -Dmy_sample_FOO=BAR ... .. _sysbuild_kconfig_namespacing: @@ -242,13 +248,13 @@ build system to the value ``BAR``, run the following commands: .. group-tab:: ``west build`` - :: + .. code-block:: shell west build --sysbuild ... -- -Dmy_sample_CONFIG_FOO=BAR .. group-tab:: ``cmake`` - :: + .. code-block:: shell cmake -Dmy_sample_CONFIG_FOO=BAR ... @@ -263,13 +269,13 @@ build system to the value ``BAR``, run the following commands: the same syntax for setting Kconfig values at CMake time. For example, the following commands will work in the same way: - :: + .. code-block:: shell - west build -b my_sample -- -DCONFIG_FOO=BAR + west build -b my_sample -- -DCONFIG_FOO=BAR - :: + .. code-block:: shell - west build -b --sysbuild my_sample -- -DCONFIG_FOO=BAR + west build -b --sysbuild my_sample -- -DCONFIG_FOO=BAR Sysbuild flashing using ``west flash`` ************************************** @@ -359,7 +365,7 @@ MCUboot whenever sysbuild is used: └── sysbuild.conf -.. code-block:: none +.. code-block:: cfg SB_CONFIG_BOOTLOADER_MCUBOOT=y @@ -432,7 +438,7 @@ target to execute and it will run. location, the ``rom_report`` build target for ``mcuboot`` can be ran with: - .. code-block:: bash + .. code-block:: shell west build -d build/mcuboot -t rom_report @@ -442,7 +448,7 @@ target to execute and it will run. using ``ninja`` using sysbuild with mcuboot enabled, the ``rom_report`` build target for ``mcuboot`` can be ran with: - .. code-block:: bash + .. code-block:: shell ninja -C mcuboot rom_report @@ -452,7 +458,7 @@ target to execute and it will run. using ``make`` using sysbuild with mcuboot enabled, the ``rom_report`` build target for ``mcuboot`` can be ran with: - .. code-block:: bash + .. code-block:: shell make -C mcuboot rom_report @@ -607,7 +613,7 @@ file or a devicetree overlay :file:`sysbuild/my_sample.overlay`. A Kconfig fragment could look as: -.. code-block:: none +.. code-block:: cfg # sysbuild/my_sample.conf CONFIG_FOO=n diff --git a/doc/build/version/index.rst b/doc/build/version/index.rst index de4e713c6b6..8d169a85bf5 100644 --- a/doc/build/version/index.rst +++ b/doc/build/version/index.rst @@ -26,7 +26,7 @@ which must be placed at the base directory of the application, where the CMakeLi located. This is a simple text file which contains the various version information fields, each on a newline. The basic ``VERSION`` file has the following structure: -.. code-block:: none +.. code-block:: cfg VERSION_MAJOR = VERSION_MINOR = @@ -58,7 +58,7 @@ manually re-ran for changes to this file. For the sections below, examples are provided for the following :file:`VERSION` file: -.. code-block:: none +.. code-block:: cfg VERSION_MAJOR = 1 VERSION_MINOR = 2 diff --git a/doc/build/zephyr_cmake_package.rst b/doc/build/zephyr_cmake_package.rst index fd8eeadd270..499765556bd 100644 --- a/doc/build/zephyr_cmake_package.rst +++ b/doc/build/zephyr_cmake_package.rst @@ -233,15 +233,17 @@ In case no Zephyr is found which satisfies the version required, as example, the find_package(Zephyr 2.z) project(app) -then an error similar to below will be printed:: +then an error similar to below will be printed: - Could not find a configuration file for package "Zephyr" that is compatible - with requested version "2.z". +.. code-block:: none + + Could not find a configuration file for package "Zephyr" that is compatible + with requested version "2.z". - The following configuration files were considered but not accepted: + The following configuration files were considered but not accepted: - /zephyr-workspace-2.a/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake, version: 2.a.0 - /zephyr-workspace-2.b/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake, version: 2.b.0 + /zephyr-workspace-2.a/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake, version: 2.a.0 + /zephyr-workspace-2.b/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake, version: 2.b.0 .. note:: It can also be beneficial to specify a version number for Zephyr repository applications diff --git a/doc/conf.py b/doc/conf.py index 551bb599b0a..4bab42dcc90 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -5,6 +5,7 @@ import os from pathlib import Path import re +import textwrap from sphinx.cmd.build import get_parser import sphinx_rtd_theme @@ -81,10 +82,13 @@ "sphinx_tabs.tabs", "zephyr.warnings_filter", "zephyr.doxyrunner", - "zephyr.vcs_link", + "zephyr.gh_utils", + "zephyr.manifest_projects_table", "notfound.extension", "sphinx_copybutton", + "sphinx_togglebutton", "zephyr.external_content", + "zephyr.domain", ] # Only use SVG converter when it is really needed, e.g. LaTeX. @@ -101,6 +105,7 @@ exclude_patterns.append("**/*west-not-found*") pygments_style = "sphinx" +highlight_language = "none" todo_include_todos = False @@ -160,15 +165,16 @@ "current_version": version, "versions": ( ("latest", "/"), + ("3.5.0", "/3.5.0/"), ("3.4.0", "/3.4.0/"), - ("3.3.0", "/3.3.0/"), ("2.7.5 (LTS)", "/2.7.5/"), ), - "display_vcs_link": True, + "display_gh_links": True, "reference_links": { "API": f"{reference_prefix}/doxygen/html/index.html", "Kconfig Options": f"{reference_prefix}/kconfig.html", "Devicetree Bindings": f"{reference_prefix}/build/dts/api/bindings.html", + "West Projects": f"{reference_prefix}/develop/manifest/index.html", } } @@ -178,7 +184,12 @@ "papersize": "a4paper", "maketitle": open(ZEPHYR_BASE / "doc" / "_static" / "latex" / "title.tex").read(), "preamble": open(ZEPHYR_BASE / "doc" / "_static" / "latex" / "preamble.tex").read(), - "fontpkg": r"\usepackage{charter}", + "makeindex": r"\usepackage[columns=1]{idxlayout}\makeindex", + "fontpkg": textwrap.dedent(r""" + \usepackage{noto} + \usepackage{inconsolata-nerd-font} + \usepackage[T1]{fontenc} + """), "sphinxsetup": ",".join( ( # NOTE: colors match those found in light.css stylesheet @@ -195,12 +206,7 @@ latex_documents = [ ("index-tex", "zephyr.tex", "Zephyr Project Documentation", author, "manual"), ] - -# -- Options for linkcheck ------------------------------------------------ - -linkcheck_ignore = [ - r"https://github.com/zephyrproject-rtos/zephyr/issues/.*" -] +latex_engine = "xelatex" # -- Options for zephyr.doxyrunner plugin --------------------------------- @@ -255,17 +261,17 @@ notfound_urls_prefix = f"/{version}/" if is_release else "/latest/" -# -- Options for zephyr.vcs_link ------------------------------------------ +# -- Options for zephyr.gh_utils ------------------------------------------ -vcs_link_version = f"v{version}" if is_release else "main" -vcs_link_base_url = f"https://github.com/zephyrproject-rtos/zephyr/blob/{vcs_link_version}" -vcs_link_prefixes = { +gh_link_version = f"v{version}" if is_release else "main" +gh_link_base_url = f"https://github.com/zephyrproject-rtos/zephyr" +gh_link_prefixes = { "samples/.*": "", "boards/.*": "", "snippets/.*": "", ".*": "doc", } -vcs_link_exclude = [ +gh_link_exclude = [ "reference/kconfig.*", "build/dts/api/bindings.*", "build/dts/api/compatibles.*", @@ -282,6 +288,7 @@ (ZEPHYR_BASE / "doc", "[!_]*"), (ZEPHYR_BASE, "boards/**/*.rst"), (ZEPHYR_BASE, "boards/**/doc"), + (ZEPHYR_BASE, "samples/**/*.html"), (ZEPHYR_BASE, "samples/**/*.rst"), (ZEPHYR_BASE, "samples/**/doc"), (ZEPHYR_BASE, "snippets/**/*.rst"), @@ -289,11 +296,16 @@ ] external_content_keep = [ "reference/kconfig/*", + "develop/manifest/index.rst", "build/dts/api/bindings.rst", "build/dts/api/bindings/**/*", "build/dts/api/compatibles/**/*", ] +# -- Options for zephyr.domain -------------------------------------------- + +zephyr_domain_apply_transforms = True + # -- Options for sphinx.ext.graphviz -------------------------------------- graphviz_dot = os.environ.get("DOT_EXECUTABLE", "dot") @@ -307,8 +319,17 @@ "-Ecolor=gray60", ] +# -- Options for sphinx_copybutton ---------------------------------------- + +copybutton_prompt_text = r"\$ |uart:~\$ " +copybutton_prompt_is_regexp = True + # -- Linkcheck options ---------------------------------------------------- +linkcheck_ignore = [ + r"https://github.com/zephyrproject-rtos/zephyr/issues/.*" +] + extlinks = { "github": ("https://github.com/zephyrproject-rtos/zephyr/issues/%s", "GitHub #%s"), } diff --git a/doc/connectivity/bluetooth/api/gatt.rst b/doc/connectivity/bluetooth/api/gatt.rst index 3cc1af64387..bb4487f57dd 100644 --- a/doc/connectivity/bluetooth/api/gatt.rst +++ b/doc/connectivity/bluetooth/api/gatt.rst @@ -56,7 +56,7 @@ respective operations. thus it is not recommended to block for long periods of time in them. Attribute value changes can be notified using :c:func:`bt_gatt_notify` API, -alternatively there is :c:func:`bt_gatt_notify_cb` where is is possible to +alternatively there is :c:func:`bt_gatt_notify_cb` where it is possible to pass a callback to be called when it is necessary to know the exact instant when the data has been transmitted over the air. Indications are supported by :c:func:`bt_gatt_indicate` API. diff --git a/doc/connectivity/bluetooth/api/mesh.rst b/doc/connectivity/bluetooth/api/mesh.rst index 1eb691b96c8..457aa5b6895 100644 --- a/doc/connectivity/bluetooth/api/mesh.rst +++ b/doc/connectivity/bluetooth/api/mesh.rst @@ -5,7 +5,10 @@ Bluetooth Mesh Profile The Bluetooth mesh profile adds secure wireless multi-hop communication for Bluetooth Low Energy. This module implements the -`Bluetooth Mesh Profile Specification v1.0.1 `_. +`Bluetooth Mesh Profile Specification v1.0.1 `_. + +Implementation of the `Bluetooth Mesh Protocol Specification v1.1 `_ +is in experimental state. Read more about Bluetooth mesh on the `Bluetooth SIG Website `_. @@ -17,6 +20,7 @@ Read more about Bluetooth mesh on the mesh/access.rst mesh/models.rst mesh/msg.rst + mesh/sar_cfg.rst mesh/provisioning.rst mesh/proxy.rst mesh/heartbeat.rst diff --git a/doc/connectivity/bluetooth/api/mesh/access.rst b/doc/connectivity/bluetooth/api/mesh/access.rst index 37d5d6fddef..2af8e6a03b8 100644 --- a/doc/connectivity/bluetooth/api/mesh/access.rst +++ b/doc/connectivity/bluetooth/api/mesh/access.rst @@ -165,6 +165,63 @@ while model data is being stored. It is recommended to use this option and the :c:func:`bt_mesh_model_data_store_schedule` function when large amount of data needs to be stored. +Composition Data +================ + +.. note:: + + The implementation of the Bluetooth Mesh Protocol Specification version 1.1 + is currently in an experimental state. For Bluetooth Mesh Profile Specification + version 1.0.1, only Composition Data Page 0 is supported. Users that are developing + for Bluetooth Mesh Profile Specification version 1.0.1 may therefore disregard all + parts of the following section mentioning the :ref:`bluetooth_mesh_lcd_srv` + model and Composition Data Pages 1, 2, 128, 129 and 130. + +The Composition Data provides information about a mesh device. +A device's Composition Data holds information about the elements on the +device, the models that it supports, and other features. The Composition +Data is split into different pages, where each page contains specific feature +information about the device. In order to access this information, the user +may use the :ref:`bluetooth_mesh_models_cfg_srv` model or, if supported, +the :ref:`bluetooth_mesh_lcd_srv` model. + +Composition Data Page 0 +----------------------- + +Composition Data Page 0 provides the fundemental information about a device, and +is mandatory for all mesh devices. It contains the element and model composition, +the supported features, and manufacturer information. + +Composition Data Page 1 +----------------------- + +Composition Data Page 1 provides information about the relationships between models, +and is mandatory for all mesh devices. A model may extend and/or correspond to one +or more models. A model can extend another model by calling :c:func:`bt_mesh_model_extend`, +or correspond to another model by calling :c:func:`bt_mesh_model_correspond`. +:kconfig:option:`CONFIG_BT_MESH_MODEL_EXTENSION_LIST_SIZE` specifies how many model +relations can be stored in the composition on a device, and this number should reflect the +number of :c:func:`bt_mesh_model_extend` and :c:func:`bt_mesh_model_correspond` calls. + +Composition Data Page 2 +----------------------- + +Composition Data Page 2 provides information for supported mesh profiles. Mesh profile +specifications define product requirements for devices that want to support a specific +Bluetooth SIG defined profile. Currently supported profiles can be found in section +3.12 in `Bluetooth SIG Assigned Numbers +`_. +Composition Data Page 2 is only mandatory for devices that claim support for one or more +mesh profile(s). + +Composition Data Pages 128, 129 and 130 +--------------------------------------- + +Composition Data Pages 128, 129 and 130 mirror Composition Data Pages 0, 1 and 2 respectively. +They are used to represent the new content of the mirrored pages when the Composition Data will +change after a firmware update. See :ref:`bluetooth_mesh_dfu_srv_comp_data_and_models_metadata` +for details. + API reference ************* diff --git a/doc/connectivity/bluetooth/api/mesh/blob.rst b/doc/connectivity/bluetooth/api/mesh/blob.rst index 069f1ac9c63..31f45289560 100644 --- a/doc/connectivity/bluetooth/api/mesh/blob.rst +++ b/doc/connectivity/bluetooth/api/mesh/blob.rst @@ -3,11 +3,25 @@ BLOB Transfer models #################### -The Binary Large Object (BLOB) Transfer models provide functionality for sending large binary objects from a single source to many Target nodes over the Bluetooth mesh network. It is the underlying transport method for the :ref:`bluetooth_mesh_dfu`, but may be used for other object transfer purposes. - -The BLOB Transfer models support transfers of continuous binary objects of up to 4 GB (2 \ :sup:`32` bytes). The BLOB transfer protocol has built-in recovery procedures for packet losses, and sets up checkpoints to ensure that all targets have received all the data before moving on. Data transfer order is not guaranteed. - -BLOB transfers are constrained by the transfer speed and reliability of the underlying mesh network. Under ideal conditions, the BLOBs can be transferred at a rate of up to 1 kbps, allowing a 100 kB BLOB to be transferred in 10-15 minutes. However, network conditions, transfer capabilities and other limiting factors can easily degrade the data rate by several orders of magnitude. Tuning the parameters of the transfer according to the application and network configuration, as well as scheduling it to periods with low network traffic, will offer significant improvements on the speed and reliability of the protocol. However, achieving transfer rates close to the ideal rate is unlikely in actual deployments. +The Binary Large Object (BLOB) Transfer models implement the Bluetooth Mesh Binary Large Object +Transfer Model specification version 1.0 and provide functionality for sending large binary objects +from a single source to many Target nodes over the Bluetooth mesh network. It is the underlying +transport method for the :ref:`bluetooth_mesh_dfu`, but may be used for other object transfer +purposes. The implementation is in experimental state. + +The BLOB Transfer models support transfers of continuous binary objects of up to 4 GB (2 \ :sup:`32` +bytes). The BLOB transfer protocol has built-in recovery procedures for packet losses, and sets up +checkpoints to ensure that all targets have received all the data before moving on. Data transfer +order is not guaranteed. + +BLOB transfers are constrained by the transfer speed and reliability of the underlying mesh network. +Under ideal conditions, the BLOBs can be transferred at a rate of up to 1 kbps, allowing a 100 kB +BLOB to be transferred in 10-15 minutes. However, network conditions, transfer capabilities and +other limiting factors can easily degrade the data rate by several orders of magnitude. Tuning the +parameters of the transfer according to the application and network configuration, as well as +scheduling it to periods with low network traffic, will offer significant improvements on the speed +and reliability of the protocol. However, achieving transfer rates close to the ideal rate is +unlikely in actual deployments. There are two BLOB Transfer models: @@ -17,7 +31,8 @@ There are two BLOB Transfer models: blob_srv blob_cli -The BLOB Transfer Client is instantiated on the sender node, and the BLOB Transfer Server is instantiated on the receiver nodes. +The BLOB Transfer Client is instantiated on the sender node, and the BLOB Transfer Server is +instantiated on the receiver nodes. Concepts ******** @@ -28,23 +43,44 @@ The BLOB transfer protocol introduces several new concepts to implement the BLOB BLOBs ===== -BLOBs are binary objects up to 4 GB in size, that can contain any data the application would like to transfer through the mesh network. The BLOBs are continuous data objects, divided into blocks and chunks to make the transfers reliable and easy to process. No limitations are put on the contents or structure of the BLOB, and applications are free to define any encoding or compression they'd like on the data itself. +BLOBs are binary objects up to 4 GB in size, that can contain any data the application would like to +transfer through the mesh network. The BLOBs are continuous data objects, divided into blocks and +chunks to make the transfers reliable and easy to process. No limitations are put on the contents or +structure of the BLOB, and applications are free to define any encoding or compression they'd like +on the data itself. -The BLOB transfer protocol does not provide any built-in integrity checks, encryption or authentication of the BLOB data. However, the underlying encryption of the Bluetooth mesh protocol provides data integrity checks and protects the contents of the BLOB from third parties using network and application level encryption. +The BLOB transfer protocol does not provide any built-in integrity checks, encryption or +authentication of the BLOB data. However, the underlying encryption of the Bluetooth mesh protocol +provides data integrity checks and protects the contents of the BLOB from third parties using +network and application level encryption. Blocks ------ -The binary objects are divided into blocks, typically from a few hundred to several thousand bytes in size. Each block is transmitted separately, and the BLOB Transfer Client ensures that all BLOB Transfer Servers have received the full block before moving on to the next. The block size is determined by the transfer's ``block_size_log`` parameter, and is the same for all blocks in the transfer except the last, which may be smaller. For a BLOB stored in flash memory, the block size is typically a multiple of the flash page size of the Target devices. +The binary objects are divided into blocks, typically from a few hundred to several thousand bytes +in size. Each block is transmitted separately, and the BLOB Transfer Client ensures that all BLOB +Transfer Servers have received the full block before moving on to the next. The block size is +determined by the transfer's ``block_size_log`` parameter, and is the same for all blocks in the +transfer except the last, which may be smaller. For a BLOB stored in flash memory, the block size is +typically a multiple of the flash page size of the Target devices. Chunks ------ -Each block is divided into chunks. A chunk is the smallest data unit in the BLOB transfer, and must fit inside a single Bluetooth mesh access message excluding the opcode (379 bytes or less). The mechanism for transferring chunks depends on the transfer mode. +Each block is divided into chunks. A chunk is the smallest data unit in the BLOB transfer, and must +fit inside a single Bluetooth mesh access message excluding the opcode (379 bytes or less). The +mechanism for transferring chunks depends on the transfer mode. -When operating in Push BLOB Transfer Mode, the chunks are sent as unacknowledged packets from the BLOB Transfer Client to all targeted BLOB Transfer Servers. Once all chunks in a block have been sent, the BLOB Transfer Client asks each BLOB Transfer Server if they're missing any chunks, and resends them. This is repeated until all BLOB Transfer Servers have received all chunks, or the BLOB Transfer Client gives up. +When operating in Push BLOB Transfer Mode, the chunks are sent as unacknowledged packets from the +BLOB Transfer Client to all targeted BLOB Transfer Servers. Once all chunks in a block have been +sent, the BLOB Transfer Client asks each BLOB Transfer Server if they're missing any chunks, and +resends them. This is repeated until all BLOB Transfer Servers have received all chunks, or the BLOB +Transfer Client gives up. -When operating in Pull BLOB Transfer Mode, the BLOB Transfer Server will request a small number of chunks from the BLOB Transfer Client at a time, and wait for the BLOB Transfer Client to send them before requesting more chunks. This repeats until all chunks have been transferred, or the BLOB Transfer Server gives up. +When operating in Pull BLOB Transfer Mode, the BLOB Transfer Server will request a small number of +chunks from the BLOB Transfer Client at a time, and wait for the BLOB Transfer Client to send them +before requesting more chunks. This repeats until all chunks have been transferred, or the BLOB +Transfer Server gives up. Read more about the transfer modes in :ref:`bluetooth_mesh_blob_transfer_modes` section. @@ -53,16 +89,31 @@ Read more about the transfer modes in :ref:`bluetooth_mesh_blob_transfer_modes` BLOB streams ============ -In the BLOB Transfer models' APIs, the BLOB data handling is separated from the high-level transfer handling. This split allows reuse of different BLOB storage and transfer strategies for different applications. While the high level transfer is controlled directly by the application, the BLOB data itself is accessed through a *BLOB stream*. +In the BLOB Transfer models' APIs, the BLOB data handling is separated from the high-level transfer +handling. This split allows reuse of different BLOB storage and transfer strategies for different +applications. While the high level transfer is controlled directly by the application, the BLOB data +itself is accessed through a *BLOB stream*. -The BLOB stream is comparable to a standard library file stream. Through opening, closing, reading and writing, the BLOB Transfer model gets full access to the BLOB data, whether it's kept in flash, RAM, or on a peripheral. The BLOB stream is opened with an access mode (read or write) before it's used, and the BLOB Transfer models will move around inside the BLOB's data in blocks and chunks, using the BLOB stream as an interface. +The BLOB stream is comparable to a standard library file stream. Through opening, closing, reading +and writing, the BLOB Transfer model gets full access to the BLOB data, whether it's kept in flash, +RAM, or on a peripheral. The BLOB stream is opened with an access mode (read or write) before it's +used, and the BLOB Transfer models will move around inside the BLOB's data in blocks and chunks, +using the BLOB stream as an interface. Interaction ----------- -Before the BLOB is read or written, the stream is opened by calling its :c:member:`open ` callback. When used with a BLOB Transfer Server, the BLOB stream is always opened in write mode, and when used with a BLOB Transfer Client, it's always opened in read mode. +Before the BLOB is read or written, the stream is opened by calling its +:c:member:`open ` callback. When used with a BLOB Transfer Server, the BLOB +stream is always opened in write mode, and when used with a BLOB Transfer Client, it's always opened +in read mode. -For each block in the BLOB, the BLOB Transfer model starts by calling :c:member:`block_start `. Then, depending on the access mode, the BLOB stream's :c:member:`wr ` or :c:member:`rd ` callback is called repeatedly to move data to or from the BLOB. When the model is done processing the block, it calls :c:member:`block_end `. When the transfer is complete, the BLOB stream is closed by calling :c:member:`close `. +For each block in the BLOB, the BLOB Transfer model starts by calling +:c:member:`block_start `. Then, depending on the access mode, the BLOB +stream's :c:member:`wr ` or :c:member:`rd ` callback is +called repeatedly to move data to or from the BLOB. When the model is done processing the block, it +calls :c:member:`block_end `. When the transfer is complete, the BLOB +stream is closed by calling :c:member:`close `. Implementations --------------- @@ -78,28 +129,41 @@ The application may implement their own BLOB stream, or use the implementations Transfer capabilities ===================== -Each BLOB Transfer Server may have different transfer capabilities. The transfer capabilities of each device are controlled through the following configuration options: +Each BLOB Transfer Server may have different transfer capabilities. The transfer capabilities of +each device are controlled through the following configuration options: * :kconfig:option:`CONFIG_BT_MESH_BLOB_SIZE_MAX` * :kconfig:option:`CONFIG_BT_MESH_BLOB_BLOCK_SIZE_MIN` * :kconfig:option:`CONFIG_BT_MESH_BLOB_BLOCK_SIZE_MAX` * :kconfig:option:`CONFIG_BT_MESH_BLOB_CHUNK_COUNT_MAX` -The :kconfig:option:`CONFIG_BT_MESH_BLOB_CHUNK_COUNT_MAX` option is also used by the BLOB Transfer Client and affects memory consumption by the BLOB Transfer Client model structure. +The :kconfig:option:`CONFIG_BT_MESH_BLOB_CHUNK_COUNT_MAX` option is also used by the BLOB Transfer +Client and affects memory consumption by the BLOB Transfer Client model structure. -To ensure that the transfer can be received by as many servers as possible, the BLOB Transfer Client can retrieve the capabilities of each BLOB Transfer Server before starting the transfer. The client will transfer the BLOB with the highest possible block and chunk size. +To ensure that the transfer can be received by as many servers as possible, the BLOB Transfer Client +can retrieve the capabilities of each BLOB Transfer Server before starting the transfer. The client +will transfer the BLOB with the highest possible block and chunk size. .. _bluetooth_mesh_blob_transfer_modes: Transfer modes ============== -BLOBs can be transferred using two transfer modes, Push BLOB Transfer Mode and Pull BLOB Transfer Mode. -In most cases, the transfer should be conducted in Push BLOB Transfer Mode. +BLOBs can be transferred using two transfer modes, Push BLOB Transfer Mode and Pull BLOB Transfer +Mode. In most cases, the transfer should be conducted in Push BLOB Transfer Mode. -In Push BLOB Transfer Mode, the send rate is controlled by the BLOB Transfer Client, which will push all the chunks of each block without any high level flow control. Push BLOB Transfer Mode supports any number of Target nodes, and should be the default transfer mode. +In Push BLOB Transfer Mode, the send rate is controlled by the BLOB Transfer Client, which will push +all the chunks of each block without any high level flow control. Push BLOB Transfer Mode supports +any number of Target nodes, and should be the default transfer mode. -In Pull BLOB Transfer Mode, the BLOB Transfer Server will "pull" the chunks from the BLOB Transfer Client at its own rate. Pull BLOB Transfer Mode can be conducted with multiple Target nodes, and is intended for transferring BLOBs to Target nodes acting as :ref:`bluetooth_mesh_lpn`. When operating in Pull BLOB Transfer Mode, the BLOB Transfer Server will request chunks from the BLOB Transfer Client in small batches, and wait for them all to arrive before requesting more chunks. This process is repeated until the BLOB Transfer Server has received all chunks in a block. Then, the BLOB Transfer Client starts the next block, and the BLOB Transfer Server requests all chunks of that block. +In Pull BLOB Transfer Mode, the BLOB Transfer Server will "pull" the chunks from the BLOB Transfer +Client at its own rate. Pull BLOB Transfer Mode can be conducted with multiple Target nodes, and is +intended for transferring BLOBs to Target nodes acting as :ref:`bluetooth_mesh_lpn`. When operating +in Pull BLOB Transfer Mode, the BLOB Transfer Server will request chunks from the BLOB Transfer +Client in small batches, and wait for them all to arrive before requesting more chunks. This process +is repeated until the BLOB Transfer Server has received all chunks in a block. Then, the BLOB +Transfer Client starts the next block, and the BLOB Transfer Server requests all chunks of that +block. .. _bluetooth_mesh_blob_timeout: @@ -107,7 +171,8 @@ In Pull BLOB Transfer Mode, the BLOB Transfer Server will "pull" the chunks from Transfer timeout ================ -The timeout of the BLOB transfer is based on a Timeout Base value. Both client and server use the same Timeout Base value, but they calculate timeout differently. +The timeout of the BLOB transfer is based on a Timeout Base value. Both client and server use the +same Timeout Base value, but they calculate timeout differently. The BLOB Transfer Server uses the following formula to calculate the BLOB transfer timeout:: diff --git a/doc/connectivity/bluetooth/api/mesh/blob_cli.rst b/doc/connectivity/bluetooth/api/mesh/blob_cli.rst index 6d926be1b5c..25b90c281c4 100644 --- a/doc/connectivity/bluetooth/api/mesh/blob_cli.rst +++ b/doc/connectivity/bluetooth/api/mesh/blob_cli.rst @@ -3,7 +3,9 @@ BLOB Transfer Client #################### -The Binary Large Object (BLOB) Transfer Client is the sender of the BLOB transfer. It supports sending BLOBs of any size to any number of Target nodes, in both Push BLOB Transfer Mode and Pull BLOB Transfer Mode. +The Binary Large Object (BLOB) Transfer Client is the sender of the BLOB transfer. It supports +sending BLOBs of any size to any number of Target nodes, in both Push BLOB Transfer Mode and Pull +BLOB Transfer Mode. Usage ***** @@ -23,14 +25,17 @@ The BLOB Transfer Client is instantiated on an element with a set of event handl .cb = &blob_cb, }; - static struct bt_mesh_model models[] = { + static const struct bt_mesh_model models[] = { BT_MESH_MODEL_BLOB_CLI(&blob_cli), }; Transfer context ================ -Both the transfer capabilities retrieval procedure and the BLOB transfer uses an instance of a :c:type:`bt_mesh_blob_cli_inputs` to determine how to perform the transfer. The BLOB Transfer Client Inputs structure must at least be initialized with a list of targets, an application key and a time to live (TTL) value before it is used in a procedure: +Both the transfer capabilities retrieval procedure and the BLOB transfer uses an instance of a +:c:type:`bt_mesh_blob_cli_inputs` to determine how to perform the transfer. The BLOB Transfer Client +Inputs structure must at least be initialized with a list of targets, an application key and a time +to live (TTL) value before it is used in a procedure: .. code-block:: c @@ -55,14 +60,28 @@ Note that all BLOB Transfer Servers in the transfer must be bound to the chosen Group address ------------- -The application may additionally specify a group address in the context structure. If the group is not :c:macro:`BT_MESH_ADDR_UNASSIGNED`, the messages in the transfer will be sent to the group address, instead of being sent individually to each Target node. Mesh Manager must ensure that all Target nodes having the BLOB Transfer Server model subscribe to this group address. +The application may additionally specify a group address in the context structure. If the group is +not :c:macro:`BT_MESH_ADDR_UNASSIGNED`, the messages in the transfer will be sent to the group +address, instead of being sent individually to each Target node. Mesh Manager must ensure that all +Target nodes having the BLOB Transfer Server model subscribe to this group address. -Using group addresses for transferring the BLOBs can generally increase the transfer speed, as the BLOB Transfer Client sends each message to all Target nodes at the same time. However, sending large, segmented messages to group addresses in Bluetooth mesh is generally less reliable than sending them to unicast addresses, as there is no transport layer acknowledgment mechanism for groups. This can lead to longer recovery periods at the end of each block, and increases the risk of losing Target nodes. Using group addresses for BLOB transfers will generally only pay off if the list of Target nodes is extensive, and the effectiveness of each addressing strategy will vary heavily between different deployments and the size of the chunks. +Using group addresses for transferring the BLOBs can generally increase the transfer speed, as the +BLOB Transfer Client sends each message to all Target nodes at the same time. However, sending +large, segmented messages to group addresses in Bluetooth mesh is generally less reliable than +sending them to unicast addresses, as there is no transport layer acknowledgment mechanism for +groups. This can lead to longer recovery periods at the end of each block, and increases the risk of +losing Target nodes. Using group addresses for BLOB transfers will generally only pay off if the +list of Target nodes is extensive, and the effectiveness of each addressing strategy will vary +heavily between different deployments and the size of the chunks. Transfer timeout ---------------- -If a Target node fails to respond to an acknowledged message within the BLOB Transfer Client's time limit, the Target node is dropped from the transfer. The application can reduce the chances of this by giving the BLOB Transfer Client extra time through the context structure. The extra time may be set in 10-second increments, up to 182 hours, in addition to the base time of 20 seconds. The wait time scales automatically with the transfer TTL. +If a Target node fails to respond to an acknowledged message within the BLOB Transfer Client's time +limit, the Target node is dropped from the transfer. The application can reduce the chances of this +by giving the BLOB Transfer Client extra time through the context structure. The extra time may be +set in 10-second increments, up to 182 hours, in addition to the base time of 20 seconds. The wait +time scales automatically with the transfer TTL. Note that the BLOB Transfer Client only moves forward with the transfer in following cases: @@ -75,18 +94,33 @@ Increasing the wait time will increase this delay. BLOB transfer capabilities retrieval ==================================== -It is generally recommended to retrieve BLOB transfer capabilities before starting a transfer. The procedure populates the transfer capabilities from all Target nodes with the most liberal set of parameters that allows all Target nodes to participate in the transfer. Any Target nodes that fail to respond, or respond with incompatible transfer parameters, will be dropped. +It is generally recommended to retrieve BLOB transfer capabilities before starting a transfer. The +procedure populates the transfer capabilities from all Target nodes with the most liberal set of +parameters that allows all Target nodes to participate in the transfer. Any Target nodes that fail +to respond, or respond with incompatible transfer parameters, will be dropped. -Target nodes are prioritized according to their order in the list of Target nodes. If a Target node is found to be incompatible with any of the previous Target nodes, for instance by reporting a non-overlapping block size range, it will be dropped. Lost Target nodes will be reported through the :c:member:`lost_target ` callback. +Target nodes are prioritized according to their order in the list of Target nodes. If a Target node +is found to be incompatible with any of the previous Target nodes, for instance by reporting a +non-overlapping block size range, it will be dropped. Lost Target nodes will be reported through the +:c:member:`lost_target ` callback. -The end of the procedure is signalled through the :c:member:`caps ` callback, and the resulting capabilities can be used to determine the block and chunk sizes required for the BLOB transfer. +The end of the procedure is signalled through the :c:member:`caps ` +callback, and the resulting capabilities can be used to determine the block and chunk sizes required +for the BLOB transfer. BLOB transfer ============= -The BLOB transfer is started by calling :c:func:`bt_mesh_blob_cli_send` function, which (in addition to the aforementioned transfer inputs) requires a set of transfer parameters and a BLOB stream instance. The transfer parameters include the 64-bit BLOB ID, the BLOB size, the transfer mode, the block size in logarithmic representation and the chunk size. The BLOB ID is application defined, but must match the BLOB ID the BLOB Transfer Servers have been started with. +The BLOB transfer is started by calling :c:func:`bt_mesh_blob_cli_send` function, which (in addition +to the aforementioned transfer inputs) requires a set of transfer parameters and a BLOB stream +instance. The transfer parameters include the 64-bit BLOB ID, the BLOB size, the transfer mode, the +block size in logarithmic representation and the chunk size. The BLOB ID is application defined, but +must match the BLOB ID the BLOB Transfer Servers have been started with. -The transfer runs until it either completes successfully for at least one Target node, or it is cancelled. The end of the transfer is communicated to the application through the :c:member:`end ` callback. Lost Target nodes will be reported through the :c:member:`lost_target ` callback. +The transfer runs until it either completes successfully for at least one Target node, or it is +cancelled. The end of the transfer is communicated to the application through the :c:member:`end +` callback. Lost Target nodes will be reported through the +:c:member:`lost_target ` callback. API reference ************* diff --git a/doc/connectivity/bluetooth/api/mesh/blob_flash.rst b/doc/connectivity/bluetooth/api/mesh/blob_flash.rst index 0b8f69ab385..5966fe3562b 100644 --- a/doc/connectivity/bluetooth/api/mesh/blob_flash.rst +++ b/doc/connectivity/bluetooth/api/mesh/blob_flash.rst @@ -3,21 +3,30 @@ BLOB Flash ########## -The BLOB Flash Readers and Writers implement BLOB reading to and writing from flash partitions defined in the :ref:`flash map `. +The BLOB Flash Readers and Writers implement BLOB reading to and writing from flash partitions +defined in the :ref:`flash map `. BLOB Flash Reader ***************** -The BLOB Flash Reader interacts with the BLOB Transfer Client to read BLOB data directly from flash. It must be initialized by calling :c:func:`bt_mesh_blob_flash_rd_init` before being passed to the BLOB Transfer Client. Each BLOB Flash Reader only supports one transfer at the time. +The BLOB Flash Reader interacts with the BLOB Transfer Client to read BLOB data directly from flash. +It must be initialized by calling :c:func:`bt_mesh_blob_flash_rd_init` before being passed to the +BLOB Transfer Client. Each BLOB Flash Reader only supports one transfer at the time. BLOB Flash Writer ***************** -The BLOB Flash Writer interacts with the BLOB Transfer Server to write BLOB data directly to flash. It must be initialized by calling :c:func:`bt_mesh_blob_flash_rd_init` before being passed to the BLOB Transfer Server. Each BLOB Flash Writer only supports one transfer at the time, and requires a block size that is a multiple of the flash page size. If a transfer is started with a block size lower than the flash page size, the transfer will be rejected. +The BLOB Flash Writer interacts with the BLOB Transfer Server to write BLOB data directly to flash. +It must be initialized by calling :c:func:`bt_mesh_blob_flash_rd_init` before being passed to the +BLOB Transfer Server. Each BLOB Flash Writer only supports one transfer at the time, and requires a +block size that is a multiple of the flash page size. If a transfer is started with a block size +lower than the flash page size, the transfer will be rejected. -The BLOB Flash Writer copies chunk data into a buffer to accommodate chunks that are unaligned with the flash write block size. The buffer data is padded with ``0xff`` if either the start or length of the chunk is unaligned. +The BLOB Flash Writer copies chunk data into a buffer to accommodate chunks that are unaligned with +the flash write block size. The buffer data is padded with ``0xff`` if either the start or length of +the chunk is unaligned. API Reference ************* diff --git a/doc/connectivity/bluetooth/api/mesh/blob_srv.rst b/doc/connectivity/bluetooth/api/mesh/blob_srv.rst index 22c2540a337..918b9493ff9 100644 --- a/doc/connectivity/bluetooth/api/mesh/blob_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/blob_srv.rst @@ -3,14 +3,22 @@ BLOB Transfer Server #################### -The Binary Large Object (BLOB) Transfer Server model implements reliable receiving of large binary objects. It serves as the backend of the :ref:`bluetooth_mesh_dfu_srv`, but can also be used for receiving other binary images. +The Binary Large Object (BLOB) Transfer Server model implements reliable receiving of large binary +objects. It serves as the backend of the :ref:`bluetooth_mesh_dfu_srv`, but can also be used for +receiving other binary images. BLOBs ***** -As described in :ref:`bluetooth_mesh_blob`, the binary objects transferred by the BLOB Transfer models are divided into blocks, which are divided into chunks. As the transfer is controlled by the BLOB Transfer Client model, the BLOB Transfer Server must allow blocks to come in any order. The chunks within a block may also come in any order, but all chunks in a block must be received before the next block is started. +As described in :ref:`bluetooth_mesh_blob`, the binary objects transferred by the BLOB Transfer +models are divided into blocks, which are divided into chunks. As the transfer is controlled by the +BLOB Transfer Client model, the BLOB Transfer Server must allow blocks to come in any order. The +chunks within a block may also come in any order, but all chunks in a block must be received before +the next block is started. -The BLOB Transfer Server keeps track of the received blocks and chunks, and will process each block and chunk only once. The BLOB Transfer Server also ensures that any missing chunks are resent by the BLOB Transfer Client. +The BLOB Transfer Server keeps track of the received blocks and chunks, and will process each block +and chunk only once. The BLOB Transfer Server also ensures that any missing chunks are resent by the +BLOB Transfer Client. Usage ***** @@ -27,13 +35,20 @@ The BLOB Transfer Server is instantiated on an element with a set of event handl .cb = &blob_cb, }; - static struct bt_mesh_model models[] = { + static const struct bt_mesh_model models[] = { BT_MESH_MODEL_BLOB_SRV(&blob_srv), }; -A BLOB Transfer Server is capable of receiving a single BLOB transfer at a time. Before the BLOB Transfer Server can receive a transfer, it must be prepared by the user. The transfer ID must be passed to the BLOB Transfer Server through the :c:func:`bt_mesh_blob_srv_recv` function before the transfer is started by the BLOB Transfer Client. The ID must be shared between the BLOB Transfer Client and the BLOB Transfer Server through some higher level procedure, like a vendor specific transfer management model. +A BLOB Transfer Server is capable of receiving a single BLOB transfer at a time. Before the BLOB +Transfer Server can receive a transfer, it must be prepared by the user. The transfer ID must be +passed to the BLOB Transfer Server through the :c:func:`bt_mesh_blob_srv_recv` function before the +transfer is started by the BLOB Transfer Client. The ID must be shared between the BLOB Transfer +Client and the BLOB Transfer Server through some higher level procedure, like a vendor specific +transfer management model. -Once the transfer has been set up on the BLOB Transfer Server, it's ready for receiving the BLOB. The application is notified of the transfer progress through the event handler callbacks, and the BLOB data is sent to the BLOB stream. +Once the transfer has been set up on the BLOB Transfer Server, it's ready for receiving the BLOB. +The application is notified of the transfer progress through the event handler callbacks, and the +BLOB data is sent to the BLOB stream. The interaction between the BLOB Transfer Server, BLOB stream and application is shown below: @@ -46,21 +61,36 @@ The interaction between the BLOB Transfer Server, BLOB stream and application is Transfer suspension ******************* -The BLOB Transfer Server keeps a running timer during the transfer, that is reset on every received message. If the BLOB Transfer Client does not send a message before the transfer timer expires, the transfer is suspended by the BLOB Transfer Server. +The BLOB Transfer Server keeps a running timer during the transfer, that is reset on every received +message. If the BLOB Transfer Client does not send a message before the transfer timer expires, the +transfer is suspended by the BLOB Transfer Server. -The BLOB Transfer Server notifies the user of the suspension by calling the :c:member:`suspended ` callback. If the BLOB Transfer Server is in the middle of receiving a block, this block is discarded. +The BLOB Transfer Server notifies the user of the suspension by calling the :c:member:`suspended +` callback. If the BLOB Transfer Server is in the middle of receiving +a block, this block is discarded. -The BLOB Transfer Client may resume a suspended transfer by starting a new block transfer. The BLOB Transfer Server notifies the user by calling the :c:member:`resume ` callback. +The BLOB Transfer Client may resume a suspended transfer by starting a new block transfer. The BLOB +Transfer Server notifies the user by calling the :c:member:`resume ` +callback. Transfer recovery ***************** -The state of the BLOB transfer is stored persistently. If a reboot occurs, the BLOB Transfer Server will attempt to recover the transfer. When the Bluetooth mesh subsystem is started (for instance by calling :c:func:`bt_mesh_init`), the BLOB Transfer Server will check for aborted transfers, and call the :c:member:`recover ` callback if there is any. In the recover callback, the user must provide a BLOB stream to use for the rest of the transfer. If the recover callback doesn't return successfully or does not provide a BLOB stream, the transfer is abandoned. If no recover callback is implemented, transfers are always abandoned after a reboot. +The state of the BLOB transfer is stored persistently. If a reboot occurs, the BLOB Transfer Server +will attempt to recover the transfer. When the Bluetooth mesh subsystem is started (for instance by +calling :c:func:`bt_mesh_init`), the BLOB Transfer Server will check for aborted transfers, and call +the :c:member:`recover ` callback if there is any. In the recover +callback, the user must provide a BLOB stream to use for the rest of the transfer. If the recover +callback doesn't return successfully or does not provide a BLOB stream, the transfer is abandoned. +If no recover callback is implemented, transfers are always abandoned after a reboot. -After a transfer is successfully recovered, the BLOB Transfer Server enters the suspended state. It will stay suspended until the BLOB Transfer Client resumes the transfer, or the user cancels it. +After a transfer is successfully recovered, the BLOB Transfer Server enters the suspended state. It +will stay suspended until the BLOB Transfer Client resumes the transfer, or the user cancels it. .. note:: - The BLOB Transfer Client sending the transfer must support transfer recovery for the transfer to complete. If the BLOB Transfer Client has already given up the transfer, the BLOB Transfer Server will stay suspended until the application calls :c:func:`bt_mesh_blob_srv_cancel`. + The BLOB Transfer Client sending the transfer must support transfer recovery for the transfer to + complete. If the BLOB Transfer Client has already given up the transfer, the BLOB Transfer Server + will stay suspended until the application calls :c:func:`bt_mesh_blob_srv_cancel`. API reference ************* diff --git a/doc/connectivity/bluetooth/api/mesh/cfg_cli.rst b/doc/connectivity/bluetooth/api/mesh/cfg_cli.rst index 1e985970690..bf84edc6b86 100644 --- a/doc/connectivity/bluetooth/api/mesh/cfg_cli.rst +++ b/doc/connectivity/bluetooth/api/mesh/cfg_cli.rst @@ -17,8 +17,8 @@ All configuration functions in the Configuration Client API have ``net_idx`` and ``addr`` as their first parameters. These should be set to the network index and primary unicast address that the target node was provisioned with. -The Configuration Client model is optional, but should be instantiated on the -first element if it is present in the composition data. +The Configuration Client model is optional, and it must only be instantiated on the +primary element if present in the Composition Data. API reference ************* diff --git a/doc/connectivity/bluetooth/api/mesh/cfg_srv.rst b/doc/connectivity/bluetooth/api/mesh/cfg_srv.rst index fe265e243f0..84f174df88b 100644 --- a/doc/connectivity/bluetooth/api/mesh/cfg_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/cfg_srv.rst @@ -8,14 +8,14 @@ specification. The Configuration Server model controls most parameters of the mesh node. It does not have an API of its own, but relies on a :ref:`bluetooth_mesh_models_cfg_cli` to control it. -..note:: +.. note:: The :c:struct:`bt_mesh_cfg_srv` structure has been deprecated. The initial values of the Relay, Beacon, Friend, Network transmit and Relay retransmit should be set through Kconfig, and the Heartbeat feature should be controlled through the :ref:`bluetooth_mesh_heartbeat` API. The Configuration Server model is mandatory on all Bluetooth mesh nodes, and -should be instantiated in the first element. +must only be instantiated on the primary element. API reference ************* diff --git a/doc/connectivity/bluetooth/api/mesh/dfd_srv.rst b/doc/connectivity/bluetooth/api/mesh/dfd_srv.rst index a1912e3acfb..8efc040a56c 100644 --- a/doc/connectivity/bluetooth/api/mesh/dfd_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/dfd_srv.rst @@ -3,20 +3,35 @@ Firmware Distribution Server ############################ -The Firmware Distribution Server model implements the Distributor role for the :ref:`bluetooth_mesh_dfu` subsystem. It extends the :ref:`bluetooth_mesh_blob_srv`, which it uses to receive the firmware image binary from the Initiator node. It also instantiates a :ref:`bluetooth_mesh_dfu_cli`, which it uses to distribute firmware updates throughout the mesh network. +The Firmware Distribution Server model implements the Distributor role for the +:ref:`bluetooth_mesh_dfu` subsystem. It extends the :ref:`bluetooth_mesh_blob_srv`, which it uses to +receive the firmware image binary from the Initiator node. It also instantiates a +:ref:`bluetooth_mesh_dfu_cli`, which it uses to distribute firmware updates throughout the mesh +network. .. note:: - Currently, the Firmware Distribution Server supports out-of-band (OOB) retrieval of firmware images over SMP service only. + Currently, the Firmware Distribution Server supports out-of-band (OOB) retrieval of firmware + images over SMP service only. -The Firmware Distribution Server does not have an API of its own, but relies on a Firmware Distribution Client model on a different device to give it information and trigger image distribution and upload. +The Firmware Distribution Server does not have an API of its own, but relies on a Firmware +Distribution Client model on a different device to give it information and trigger image +distribution and upload. Firmware slots ************** -The Firmware Distribution Server is capable of storing multiple firmware images for distribution. Each slot contains a separate firmware image with metadata, and can be distributed to other mesh nodes in the network in any order. The contents, format and size of the firmware images are vendor specific, and may contain data from other vendors. The application should never attempt to execute or modify them. - -The slots are managed remotely by a Firmware Distribution Client, which can both upload new slots and delete old ones. The application is notified of changes to the slots through the Firmware Distribution Server's callbacks (:cpp:type:`bt_mesh_fd_srv_cb`). While the metadata for each firmware slot is stored internally, the application must provide a :ref:`bluetooth_mesh_blob_stream` for reading and writing the firmware image. +The Firmware Distribution Server is capable of storing multiple firmware images for distribution. +Each slot contains a separate firmware image with metadata, and can be distributed to other mesh +nodes in the network in any order. The contents, format and size of the firmware images are vendor +specific, and may contain data from other vendors. The application should never attempt to execute +or modify them. + +The slots are managed remotely by a Firmware Distribution Client, which can both upload new slots +and delete old ones. The application is notified of changes to the slots through the Firmware +Distribution Server's callbacks (:cpp:type:`bt_mesh_fd_srv_cb`). While the metadata for each +firmware slot is stored internally, the application must provide a :ref:`bluetooth_mesh_blob_stream` +for reading and writing the firmware image. API reference ************* diff --git a/doc/connectivity/bluetooth/api/mesh/dfu.rst b/doc/connectivity/bluetooth/api/mesh/dfu.rst index 685aaf3cbd1..9cf55e244d6 100644 --- a/doc/connectivity/bluetooth/api/mesh/dfu.rst +++ b/doc/connectivity/bluetooth/api/mesh/dfu.rst @@ -3,11 +3,17 @@ Device Firmware Update (DFU) ############################ -Bluetooth mesh supports the distribution of firmware images across a mesh network. The Bluetooth mesh DFU subsystem implements the Firmware update section of the Bluetooth Mesh Model Specification v1.1. +Bluetooth mesh supports the distribution of firmware images across a mesh network. The Bluetooth +mesh DFU subsystem implements the Bluetooth Mesh Device Firmware Update Model specification version +1.0. The implementation is in experimental state. -Bluetooth mesh DFU implements a distribution mechanism for firmware images, and does not put any restrictions on the size, format or usage of the images. The primary design goal of the subsystem is to provide the qualifiable parts of the Bluetooth mesh DFU specification, and leave the usage, firmware validation and deployment to the application. +Bluetooth mesh DFU implements a distribution mechanism for firmware images, and does not put any +restrictions on the size, format or usage of the images. The primary design goal of the subsystem is +to provide the qualifiable parts of the Bluetooth mesh DFU specification, and leave the usage, +firmware validation and deployment to the application. -The DFU specification is implemented in the Zephyr Bluetooth mesh DFU subsystem as three separate models: +The DFU specification is implemented in the Zephyr Bluetooth mesh DFU subsystem as three separate +models: .. toctree:: :maxdepth: 1 @@ -22,29 +28,50 @@ Overview DFU roles ========= -The Bluetooth mesh DFU subsystem defines three different roles the mesh nodes have to assume in the distribution of firmware images: +The Bluetooth mesh DFU subsystem defines three different roles the mesh nodes have to assume in the +distribution of firmware images: Target node - Target node is the receiver and user of the transferred firmware images. All its functionality is implemented by the :ref:`bluetooth_mesh_dfu_srv` model. A transfer may be targeting any number of Target nodes, and they will all be updated concurrently. + Target node is the receiver and user of the transferred firmware images. All its functionality is + implemented by the :ref:`bluetooth_mesh_dfu_srv` model. A transfer may be targeting any number of + Target nodes, and they will all be updated concurrently. Distributor - The Distributor role serves two purposes in the DFU process. First, it's acting as the Target node in the Upload Firmware procedure, then it distributes the uploaded image to other Target nodes as the Distributor. The Distributor does not select the parameters of the transfer, but relies on an Initiator to give it a list of Target nodes and transfer parameters. The Distributor functionality is implemented in two models, :ref:`bluetooth_mesh_dfd_srv` and :ref:`bluetooth_mesh_dfu_cli`. The :ref:`bluetooth_mesh_dfd_srv` is responsible for communicating with the Initiator, and the :ref:`bluetooth_mesh_dfu_cli` is responsible for distributing the image to the Target nodes. + The Distributor role serves two purposes in the DFU process. First, it's acting as the Target + node in the Upload Firmware procedure, then it distributes the uploaded image to other Target + nodes as the Distributor. The Distributor does not select the parameters of the transfer, but + relies on an Initiator to give it a list of Target nodes and transfer parameters. The Distributor + functionality is implemented in two models, :ref:`bluetooth_mesh_dfd_srv` and + :ref:`bluetooth_mesh_dfu_cli`. The :ref:`bluetooth_mesh_dfd_srv` is responsible for communicating + with the Initiator, and the :ref:`bluetooth_mesh_dfu_cli` is responsible for distributing the + image to the Target nodes. Initiator - The Initiator role is typically implemented by the same device that implements the Bluetooth mesh :ref:`Provisioner ` and :ref:`Configurator ` roles. The Initiator needs a full overview of the potential Target nodes and their firmware, and will control (and initiate) all firmware updates. The Initiator role is not implemented in the Zephyr Bluetooth mesh DFU subsystem. + The Initiator role is typically implemented by the same device that implements the Bluetooth mesh + :ref:`Provisioner ` and :ref:`Configurator + ` roles. The Initiator needs a full overview of the potential + Target nodes and their firmware, and will control (and initiate) all firmware updates. The + Initiator role is not implemented in the Zephyr Bluetooth mesh DFU subsystem. .. figure:: images/dfu_roles_mesh.svg :align: center - :alt: Graphic overview of the DFU roles mesh nodes can have during the process of image distribution + :alt: Graphic overview of the DFU roles mesh nodes can have during the process of image + distribution DFU roles and the associated Bluetooth mesh models -Bluetooth mesh applications may combine the DFU roles in any way they'd like, and even take on multiple instances of the same role by instantiating the models on separate elements. For instance, the Distributor and Initiator role can be combined by instantiating the :ref:`bluetooth_mesh_dfu_cli` on the Initiator node and calling its API directly. +Bluetooth mesh applications may combine the DFU roles in any way they'd like, and even take on +multiple instances of the same role by instantiating the models on separate elements. For instance, +the Distributor and Initiator role can be combined by instantiating the +:ref:`bluetooth_mesh_dfu_cli` on the Initiator node and calling its API directly. -It's also possible to combine the Initiator and Distributor devices into a single device, and replace the Firmware Distribution Server model with a proprietary mechanism that will access the Firmware Update Client model directly, e.g. over a serial protocol. +It's also possible to combine the Initiator and Distributor devices into a single device, and +replace the Firmware Distribution Server model with a proprietary mechanism that will access the +Firmware Update Client model directly, e.g. over a serial protocol. .. note:: - All DFU models instantiate one or more :ref:`bluetooth_mesh_blob`, and may need to be spread over multiple elements for certain role combinations. + All DFU models instantiate one or more :ref:`bluetooth_mesh_blob`, and may need to be spread over + multiple elements for certain role combinations. Stages ====== @@ -52,28 +79,63 @@ Stages The Bluetooth mesh DFU process is designed to act in three stages: Upload stage - First, the image is uploaded to a Distributor in a mesh network by an external entity, such as a phone or gateway (the Initiator). During the Upload stage, the Initiator transfers the firmware image and all its metadata to the Distributor node inside the mesh network. The Distributor stores the firmware image and its metadata persistently, and awaits further instructions from the Initiator. The time required to complete the upload process depends on the size of the image. After the upload completes, the Initiator can disconnect from the network during the much more time-consuming Distribution stage. Once the firmware has been uploaded to the Distributor, the Initiator may trigger the Distribution stage at any time. + First, the image is uploaded to a Distributor in a mesh network by an external entity, such as a + phone or gateway (the Initiator). During the Upload stage, the Initiator transfers the firmware + image and all its metadata to the Distributor node inside the mesh network. The Distributor + stores the firmware image and its metadata persistently, and awaits further instructions from the + Initiator. The time required to complete the upload process depends on the size of the image. + After the upload completes, the Initiator can disconnect from the network during the much more + time-consuming Distribution stage. Once the firmware has been uploaded to the Distributor, the + Initiator may trigger the Distribution stage at any time. Firmware Capability Check stage (optional) - Before starting the Distribution stage, the Initiator may optionally check if Target nodes can accept the new firmware. Nodes that do not respond, or respond that they can't receive the new firmware, are excluded from the firmware distribution process. + Before starting the Distribution stage, the Initiator may optionally check if Target nodes can + accept the new firmware. Nodes that do not respond, or respond that they can't receive the new + firmware, are excluded from the firmware distribution process. Distribution stage - Before the firmware image can be distributed, the Initiator transfers the list of Target nodes and their designated firmware image index to the Distributor. Next, it tells the Distributor to start the firmware distributon process, which runs in the background while the Initiator and the mesh network perform other duties. Once the firmware image has been transferred to the Target nodes, the Distributor may ask them to apply the firmware image immediately and report back with their status and new firmware IDs. + Before the firmware image can be distributed, the Initiator transfers the list of Target nodes + and their designated firmware image index to the Distributor. Next, it tells the Distributor to + start the firmware distributon process, which runs in the background while the Initiator and the + mesh network perform other duties. Once the firmware image has been transferred to the Target + nodes, the Distributor may ask them to apply the firmware image immediately and report back with + their status and new firmware IDs. Firmware images =============== -All updatable parts of a mesh node's firmware should be represented as a firmware image. Each Target node holds a list of firmware images, each of which should be independently updatable and identifiable. +All updatable parts of a mesh node's firmware should be represented as a firmware image. Each Target +node holds a list of firmware images, each of which should be independently updatable and +identifiable. -Firmware images are represented as a BLOB (the firmware itself) with the following additional information attached to it: +Firmware images are represented as a BLOB (the firmware itself) with the following additional +information attached to it: Firmware ID - The firmware ID is used to identify a firmware image. The Initiator node may ask the Target nodes for a list of its current firmware IDs to determine whether a newer version of the firmware is available. The format of the firmware ID is vendor specific, but generally, it should include enough information for an Initiator node with knowledge of the format to determine the type of image as well as its version. The firmware ID is optional, and its max length is determined by :kconfig:option:`CONFIG_BT_MESH_DFU_FWID_MAXLEN`. + The firmware ID is used to identify a firmware image. The Initiator node may ask the Target nodes + for a list of its current firmware IDs to determine whether a newer version of the firmware is + available. The format of the firmware ID is vendor specific, but generally, it should include + enough information for an Initiator node with knowledge of the format to determine the type of + image as well as its version. The firmware ID is optional, and its max length is determined by + :kconfig:option:`CONFIG_BT_MESH_DFU_FWID_MAXLEN`. Firmware metadata - The firmware metadata is used by the Target node to determine whether it should accept an incoming firmware update, and what the effect of the update would be. The metadata format is vendor specific, and should contain all information the Target node needs to verify the image, as well as any preparation the Target node has to make before the image is applied. Typical metadata information can be image signatures, changes to the node's Composition Data and the format of the BLOB. The Target node may perform a metadata check before accepting incoming transfers to determine whether the transfer should be started. The firmware metadata can be discarded by the Target node after the metadata check, as other nodes will never request the metadata from the Target node. The firmware metadata is optional, and its maximum length is determined by :kconfig:option:`CONFIG_BT_MESH_DFU_METADATA_MAXLEN`. - - The Bluetooth mesh DFU subsystem in Zephyr provides its own metadata format (:c:struct:`bt_mesh_dfu_metadata`) together with a set of related functions that can be used by an end product. The support for it is enabled using the :kconfig:option:`CONFIG_BT_MESH_DFU_METADATA` option. The format of the metadata is presented in the table below. + The firmware metadata is used by the Target node to determine whether it should accept an + incoming firmware update, and what the effect of the update would be. The metadata format is + vendor specific, and should contain all information the Target node needs to verify the image, as + well as any preparation the Target node has to make before the image is applied. Typical metadata + information can be image signatures, changes to the node's Composition Data and the format of the + BLOB. The Target node may perform a metadata check before accepting incoming transfers to + determine whether the transfer should be started. The firmware metadata can be discarded by the + Target node after the metadata check, as other nodes will never request the metadata from the + Target node. The firmware metadata is optional, and its maximum length is determined by + :kconfig:option:`CONFIG_BT_MESH_DFU_METADATA_MAXLEN`. + + The Bluetooth mesh DFU subsystem in Zephyr provides its own metadata format + (:c:struct:`bt_mesh_dfu_metadata`) together with a set of related functions that can be used by + an end product. The support for it is enabled using the + :kconfig:option:`CONFIG_BT_MESH_DFU_METADATA` option. The format of the metadata is presented in + the table below. +------------------------+--------------+----------------------------------------+ | Field | Size (Bytes) | Description | @@ -109,27 +171,53 @@ Firmware metadata +------------------------+--------------+----------------------------------------+ Firmware URI - The firmware URI gives the Initiator information about where firmware updates for the image can be found. The URI points to an online resource the Initiator can interact with to get new versions of the firmware. This allows Initiators to perform updates for any node in the mesh network by interacting with the web server pointed to in the URI. The URI must point to a resource using the ``http`` or ``https`` schemes, and the targeted web server must behave according to the Firmware Check Over HTTPS procedure defined by the specification. The firmware URI is optional, and its max length is determined by :kconfig:option:`CONFIG_BT_MESH_DFU_URI_MAXLEN`. + The firmware URI gives the Initiator information about where firmware updates for the image can + be found. The URI points to an online resource the Initiator can interact with to get new + versions of the firmware. This allows Initiators to perform updates for any node in the mesh + network by interacting with the web server pointed to in the URI. The URI must point to a + resource using the ``http`` or ``https`` schemes, and the targeted web server must behave + according to the Firmware Check Over HTTPS procedure defined by the specification. The firmware + URI is optional, and its max length is determined by + :kconfig:option:`CONFIG_BT_MESH_DFU_URI_MAXLEN`. .. note:: The out-of-band distribution mechanism is not supported. +.. _bluetooth_mesh_dfu_firmware_effect: + Firmware effect --------------- -A new image may have the Composition Data Page 0 different from the one allocated on a Target node. This may have an effect on the provisioning data of the node and how the Distributor finalizes the DFU. Depending on the availability of the Remote Provisioning Server model on the old and new image, the device may either boot up unprovisioned after applying the new firmware or require to be re-provisioned. The complete list of available options is defined in :c:enum:`bt_mesh_dfu_effect`: +A new image may have the Composition Data Page 0 different from the one allocated on a Target node. +This may have an effect on the provisioning data of the node and how the Distributor finalizes the +DFU. Depending on the availability of the Remote Provisioning Server model on the old and new image, +the device may either boot up unprovisioned after applying the new firmware or require to be +re-provisioned. The complete list of available options is defined in :c:enum:`bt_mesh_dfu_effect`: :c:enum:`BT_MESH_DFU_EFFECT_NONE` - The device stays provisioned after the new firmware is programmed. This effect is chosen if the composition data of the new firmware doesn't change. + The device stays provisioned after the new firmware is programmed. This effect is chosen if the + composition data of the new firmware doesn't change. :c:enum:`BT_MESH_DFU_EFFECT_COMP_CHANGE_NO_RPR` - This effect is chosen when the composition data changes and the device doesn't support the remote provisioning. The new composition data takes place only after re-provisioning. + This effect is chosen when the composition data changes and the device doesn't support the remote + provisioning. The new composition data takes place only after re-provisioning. :c:enum:`BT_MESH_DFU_EFFECT_COMP_CHANGE` - This effect is chosen when the composition data changes and the device supports the remote provisioning. In this case, the device stays provisioned and the new composition data takes place after re-provisioning using the Remote Provisioning models. + This effect is chosen when the composition data changes and the device supports the remote + provisioning. In this case, the device stays provisioned and the new composition data takes place + after re-provisioning using the Remote Provisioning models. :c:enum:`BT_MESH_DFU_EFFECT_UNPROV` - This effect is chosen if the composition data in the new firmware changes, the device doesn't support the remote provisioning, and the new composition data takes effect after applying the firmware. + This effect is chosen if the composition data in the new firmware changes, the device doesn't + support the remote provisioning, and the new composition data takes effect after applying the + firmware. -When the Target node receives the Firmware Update Firmware Metadata Check message, the Firmware Update Server model calls the :c:member:`bt_mesh_dfu_srv_cb.check` callback, the application can then process the metadata and provide the effect value. +When the Target node receives the Firmware Update Firmware Metadata Check message, the Firmware +Update Server model calls the :c:member:`bt_mesh_dfu_srv_cb.check` callback, the application can +then process the metadata and provide the effect value. If the effect is +:c:enum:`BT_MESH_DFU_EFFECT_COMP_CHANGE`, the application must call functions +:c:func:`bt_mesh_comp_change_prepare` and :c:func:`bt_mesh_models_metadata_change_prepare` to +prepare the Composition Data Page and Models Metadata Page contents before applying the new +firmware image. See :ref:`bluetooth_mesh_dfu_srv_comp_data_and_models_metadata` for more +information. DFU procedures @@ -137,9 +225,12 @@ DFU procedures The DFU protocol is implemented as a set of procedures that must be performed in a certain order. -The Initiator controls the Upload stage of the DFU protocol, and all Distributor side handling of the upload subprocedures is implemented in the :ref:`bluetooth_mesh_dfd_srv`. +The Initiator controls the Upload stage of the DFU protocol, and all Distributor side handling of +the upload subprocedures is implemented in the :ref:`bluetooth_mesh_dfd_srv`. -The Distribution stage is controlled by the Distributor, as implemented by the :ref:`bluetooth_mesh_dfu_cli`. The Target node implements all handling of these procedures in the :ref:`bluetooth_mesh_dfu_srv`, and notifies the application through a set of callbacks. +The Distribution stage is controlled by the Distributor, as implemented by the +:ref:`bluetooth_mesh_dfu_cli`. The Target node implements all handling of these procedures in the +:ref:`bluetooth_mesh_dfu_srv`, and notifies the application through a set of callbacks. .. figure:: images/dfu_stages_procedures_mesh.svg :align: center @@ -150,14 +241,23 @@ The Distribution stage is controlled by the Distributor, as implemented by the : Uploading the firmware ====================== -The Upload Firmware procedure uses the :ref:`bluetooth_mesh_blob` to transfer the firmware image from the Initiator to the Distributor. The Upload Firmware procedure works in two steps: +The Upload Firmware procedure uses the :ref:`bluetooth_mesh_blob` to transfer the firmware image +from the Initiator to the Distributor. The Upload Firmware procedure works in two steps: -1. The Initiator generates a BLOB ID, and sends it to the Distributor's Firmware Distribution Server along with the firmware information and other input parameters of the BLOB transfer. The Firmware Distribution Server stores the information, and prepares its BLOB Transfer Server for the incoming transfer before it responds with a status message to the Initiator. -#. The Initiator's BLOB Transfer Client model transfers the firmware image to the Distributor's BLOB Transfer Server, which stores the image in a predetermined flash partition. +1. The Initiator generates a BLOB ID, and sends it to the Distributor's Firmware Distribution Server + along with the firmware information and other input parameters of the BLOB transfer. The Firmware + Distribution Server stores the information, and prepares its BLOB Transfer Server for the + incoming transfer before it responds with a status message to the Initiator. +#. The Initiator's BLOB Transfer Client model transfers the firmware image to the Distributor's BLOB + Transfer Server, which stores the image in a predetermined flash partition. -When the BLOB transfer finishes, the firmware image is ready for distribution. The Initiator may upload several firmware images to the Distributor, and ask it to distribute them in any order or at any time. Additional procedures are available for querying and deleting firmware images from the Distributor. +When the BLOB transfer finishes, the firmware image is ready for distribution. The Initiator may +upload several firmware images to the Distributor, and ask it to distribute them in any order or at +any time. Additional procedures are available for querying and deleting firmware images from the +Distributor. -The following Distributor's capabilities related to firmware images can be configured using the configuration options: +The following Distributor's capabilities related to firmware images can be configured using the +configuration options: * :kconfig:option:`CONFIG_BT_MESH_DFU_SLOT_CNT`: Amount of image slots available on the device. * :kconfig:option:`CONFIG_BT_MESH_DFD_SRV_SLOT_MAX_SIZE`: Maximum allowed size for each image. @@ -166,52 +266,97 @@ The following Distributor's capabilities related to firmware images can be confi Populating the Distributor's receivers list =========================================== -Before the Distributor can start distributing the firmware image, it needs a list of Target nodes to send the image to. The Initiator gets the full list of Target nodes either by querying the potential targets directly, or through some external authority. The Initiator uses this information to populate the Distributor's receivers list with the address and relevant firmware image index of each Target node. The Initiator may send one or more Firmware Distribution Receivers Add messages to build the Distributor's receivers list, and a Firmware Distribution Receivers Delete All message to clear it. +Before the Distributor can start distributing the firmware image, it needs a list of Target nodes to +send the image to. The Initiator gets the full list of Target nodes either by querying the potential +targets directly, or through some external authority. The Initiator uses this information to +populate the Distributor's receivers list with the address and relevant firmware image index of each +Target node. The Initiator may send one or more Firmware Distribution Receivers Add messages to +build the Distributor's receivers list, and a Firmware Distribution Receivers Delete All message to +clear it. -The maximum number of receivers that can be added to the Distributor is configured through the :kconfig:option:`CONFIG_BT_MESH_DFD_SRV_TARGETS_MAX` configuration option. +The maximum number of receivers that can be added to the Distributor is configured through the +:kconfig:option:`CONFIG_BT_MESH_DFD_SRV_TARGETS_MAX` configuration option. Initiating the distribution =========================== -Once the Distributor has stored a firmware image and received a list of Target nodes, the Initiator may initiate the distribution procedure. The BLOB transfer parameters for the distribution are passed to the Distributor along with an update policy. The update policy decides whether the Distributor should request that the firmware is applied on the Target nodes or not. The Distributor stores the transfer parameters and starts distributing the firmware image to its list of Target nodes. +Once the Distributor has stored a firmware image and received a list of Target nodes, the Initiator +may initiate the distribution procedure. The BLOB transfer parameters for the distribution are +passed to the Distributor along with an update policy. The update policy decides whether the +Distributor should request that the firmware is applied on the Target nodes or not. The Distributor +stores the transfer parameters and starts distributing the firmware image to its list of Target +nodes. Firmware distribution --------------------- -The Distributor's Firmware Update Client model uses its BLOB Transfer Client model's broadcast subsystem to communicate with all Target nodes. The firmware distribution is performed with the following steps: +The Distributor's Firmware Update Client model uses its BLOB Transfer Client model's broadcast +subsystem to communicate with all Target nodes. The firmware distribution is performed with the +following steps: -1. The Distributor's Firmware Update Client model generates a BLOB ID and sends it to each Target node's Firmware Update Server model, along with the other BLOB transfer parameters, the Target node firmware image index and the firmware image metadata. Each Target node performs a metadata check and prepares their BLOB Transfer Server model for the transfer, before sending a status response to the Firmware Update Client, indicating if the firmware update will have any effect on the Bluetooth mesh state of the node. +1. The Distributor's Firmware Update Client model generates a BLOB ID and sends it to each Target + node's Firmware Update Server model, along with the other BLOB transfer parameters, the Target + node firmware image index and the firmware image metadata. Each Target node performs a metadata + check and prepares their BLOB Transfer Server model for the transfer, before sending a status + response to the Firmware Update Client, indicating if the firmware update will have any effect on + the Bluetooth mesh state of the node. #. The Distributor's BLOB Transfer Client model transfers the firmware image to all Target nodes. -#. Once the BLOB transfer has been received, the Target nodes' applications verify that the firmware is valid by performing checks such as signature verification or image checksums against the image metadata. -#. The Distributor's Firmware Update Client model queries all Target nodes to ensure that they've all verified the firmware image. +#. Once the BLOB transfer has been received, the Target nodes' applications verify that the firmware + is valid by performing checks such as signature verification or image checksums against the image + metadata. +#. The Distributor's Firmware Update Client model queries all Target nodes to ensure that they've + all verified the firmware image. -If the distribution procedure completed with at least one Target node reporting that the image has been received and verified, the distribution procedure is considered successful. +If the distribution procedure completed with at least one Target node reporting that the image has +been received and verified, the distribution procedure is considered successful. .. note:: - The firmware distribution procedure only fails if *all* Target nodes are lost. It is up to the Initiator to request a list of failed Target nodes from the Distributor and initiate additional attempts to update the lost Target nodes after the current attempt is finished. + The firmware distribution procedure only fails if *all* Target nodes are lost. It is up to the + Initiator to request a list of failed Target nodes from the Distributor and initiate additional + attempts to update the lost Target nodes after the current attempt is finished. Suspending the distribution --------------------------- -The Initiator can also request the Distributor to suspend the firmware distribution. In this case, the Distributor will stop sending any messages to Target nodes. When the firmware distribution is resumed, the Distributor will continue sending the firmware from the last successfully transferred block. +The Initiator can also request the Distributor to suspend the firmware distribution. In this case, +the Distributor will stop sending any messages to Target nodes. When the firmware distribution is +resumed, the Distributor will continue sending the firmware from the last successfully transferred +block. Applying the firmware image =========================== -If the Initiator requested it, the Distributor can initiate the Apply Firmware on Target Node procedure on all Target nodes that successfully received and verified the firmware image. The Apply Firmware on Target Node procedure takes no parameters, and to avoid ambiguity, it should be performed before a new transfer is initiated. The Apply Firmware on Target Node procedure consists of the following steps: - -1. The Distributor's Firmware Update Client model instructs all Target nodes that have verified the firmware image to apply it. The Target nodes' Firmware Update Server models respond with a status message before calling their application's ``apply`` callback. -#. The Target node's application performs any preparations needed before applying the transfer, such as storing a snapshot of the Composition Data or clearing its configuration. -#. The Target node's application swaps the current firmware with the new image and updates its firmware image list with the new firmware ID. -#. The Distributor's Firmware Update Client model requests the full list of firmware images from each Target node, and scans through the list to make sure that the new firmware ID has replaced the old. +If the Initiator requested it, the Distributor can initiate the Apply Firmware on Target Node +procedure on all Target nodes that successfully received and verified the firmware image. The Apply +Firmware on Target Node procedure takes no parameters, and to avoid ambiguity, it should be +performed before a new transfer is initiated. The Apply Firmware on Target Node procedure consists +of the following steps: + +1. The Distributor's Firmware Update Client model instructs all Target nodes that have verified the + firmware image to apply it. The Target nodes' Firmware Update Server models respond with a status + message before calling their application's ``apply`` callback. +#. The Target node's application performs any preparations needed before applying the transfer, such + as storing a snapshot of the Composition Data or clearing its configuration. +#. The Target node's application swaps the current firmware with the new image and updates its + firmware image list with the new firmware ID. +#. The Distributor's Firmware Update Client model requests the full list of firmware images from + each Target node, and scans through the list to make sure that the new firmware ID has replaced + the old. .. note:: - During the metadata check in the distribution procedure, the Target node may have reported that it will become unprovisioned after the firmware image is applied. In this case, the Distributor's Firmware Update Client model will send a request for the full firmware image list, and expect no response. + During the metadata check in the distribution procedure, the Target node may have reported that + it will become unprovisioned after the firmware image is applied. In this case, the Distributor's + Firmware Update Client model will send a request for the full firmware image list, and expect no + response. Cancelling the distribution =========================== -The firmware distribution can be cancelled at any time by the Initiator. In this case, the Distributor starts the cancelling procedure by sending a cancelling message to all Target nodes. The Distributor waits for the response from all Target nodes. Once all Target nodes have replied, or the request has timed out, the distribution procedure is cancelled. After this the distribution procedure can be started again from the ``Firmware distribution`` section. +The firmware distribution can be cancelled at any time by the Initiator. In this case, the +Distributor starts the cancelling procedure by sending a cancelling message to all Target nodes. The +Distributor waits for the response from all Target nodes. Once all Target nodes have replied, or the +request has timed out, the distribution procedure is cancelled. After this the distribution +procedure can be started again from the ``Firmware distribution`` section. API reference @@ -219,6 +364,10 @@ API reference This section lists the types common to the Device Firmware Update mesh models. +.. doxygengroup:: bt_mesh_dfd + :project: Zephyr + :members: + .. doxygengroup:: bt_mesh_dfu :project: Zephyr :members: diff --git a/doc/connectivity/bluetooth/api/mesh/dfu_cli.rst b/doc/connectivity/bluetooth/api/mesh/dfu_cli.rst index c4ea98770d9..71952999caa 100644 --- a/doc/connectivity/bluetooth/api/mesh/dfu_cli.rst +++ b/doc/connectivity/bluetooth/api/mesh/dfu_cli.rst @@ -3,7 +3,9 @@ Firmware Update Client ###################### -The Firmware Update Client is responsible for distributing firmware updates through the mesh network. The Firmware Update Client uses the :ref:`bluetooth_mesh_blob_cli` as a transport for its transfers. +The Firmware Update Client is responsible for distributing firmware updates through the mesh +network. The Firmware Update Client uses the :ref:`bluetooth_mesh_blob_cli` as a transport for its +transfers. API reference diff --git a/doc/connectivity/bluetooth/api/mesh/dfu_srv.rst b/doc/connectivity/bluetooth/api/mesh/dfu_srv.rst index 0b98b1ec067..2642dec8cc9 100644 --- a/doc/connectivity/bluetooth/api/mesh/dfu_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/dfu_srv.rst @@ -3,21 +3,33 @@ Firmware Update Server ###################### -The Firmware Update Server model implements the Target node functionality of the :ref:`bluetooth_mesh_dfu` subsystem. It extends the :ref:`bluetooth_mesh_blob_srv`, which it uses to receive the firmware image binary from the Distributor node. +The Firmware Update Server model implements the Target node functionality of the +:ref:`bluetooth_mesh_dfu` subsystem. It extends the :ref:`bluetooth_mesh_blob_srv`, which it uses to +receive the firmware image binary from the Distributor node. -Together with the extended BLOB Transfer Server model, the Firmware Update Server model implements all the required functionality for receiving firmware updates over the mesh network, but does not provide any functionality for storing, applying or verifying the images. +Together with the extended BLOB Transfer Server model, the Firmware Update Server model implements +all the required functionality for receiving firmware updates over the mesh network, but does not +provide any functionality for storing, applying or verifying the images. Firmware images *************** -The Firmware Update Server holds a list of all the updatable firmware images on the device. The full list shall be passed to the server through the ``_imgs`` parameter in :c:macro:`BT_MESH_DFU_SRV_INIT`, and must be populated before the Bluetooth mesh subsystem is started. Each firmware image in the image list must be independently updatable, and should have its own firmware ID. +The Firmware Update Server holds a list of all the updatable firmware images on the device. The full +list shall be passed to the server through the ``_imgs`` parameter in +:c:macro:`BT_MESH_DFU_SRV_INIT`, and must be populated before the Bluetooth mesh subsystem is +started. Each firmware image in the image list must be independently updatable, and should have its +own firmware ID. -For instance, a device with an upgradable bootloader, an application and a peripheral chip with firmware update capabilities could have three entries in the firmware image list, each with their own separate firmware ID. +For instance, a device with an upgradable bootloader, an application and a peripheral chip with +firmware update capabilities could have three entries in the firmware image list, each with their +own separate firmware ID. Receiving transfers ******************* -The Firmware Update Server model uses a BLOB Transfer Server model on the same element to transfer the binary image. The interaction between the Firmware Update Server, BLOB Transfer Server and application is described below: +The Firmware Update Server model uses a BLOB Transfer Server model on the same element to transfer +the binary image. The interaction between the Firmware Update Server, BLOB Transfer Server and +application is described below: .. figure:: images/dfu_srv.svg :align: center @@ -28,40 +40,89 @@ The Firmware Update Server model uses a BLOB Transfer Server model on the same e Transfer check ============== -The transfer check is an optional pre-transfer check the application can perform on incoming firmware image metadata. The Firmware Update Server performs the transfer check by calling the :c:member:`check ` callback. +The transfer check is an optional pre-transfer check the application can perform on incoming +firmware image metadata. The Firmware Update Server performs the transfer check by calling the +:c:member:`check ` callback. -The result of the transfer check is a pass/fail status return and the expected :c:type:`bt_mesh_dfu_effect`. The DFU effect return parameter will be communicated back to the Distributor, and should indicate what effect the firmware update will have on the mesh state of the device. If the transfer will cause the device to change its Composition Data or become unprovisioned, this should be communicated through the effect parameter of the metadata check. +The result of the transfer check is a pass/fail status return and the expected +:c:type:`bt_mesh_dfu_effect`. The DFU effect return parameter will be communicated back to the +Distributor, and should indicate what effect the firmware update will have on the mesh state of the +device. + +.. _bluetooth_mesh_dfu_srv_comp_data_and_models_metadata: + +Composition Data and Models Metadata +------------------------------------ + +If the transfer will cause the device to change its Composition Data or become +unprovisioned, this should be communicated through the effect parameter of the metadata check. + +When the transfer will cause the Composition Data to change, and the +:ref:`bluetooth_mesh_models_rpr_srv` is supported, the Composition Data of the new firmware image +will be represented by Composition Data Pages 128, 129, and 130. The Models Metadata of the new +firmware image will be represented by Models Metadata Page 128. Composition Data Pages 0, 1 and 2, +and Models Metadata Page 0, will represent the Composition Data and the Models Metadata of the old +firmware image until the device is reprovisioned with Node Provisioning Protocol Interface (NPPI) +procedures using the :ref:`bluetooth_mesh_models_rpr_cli`. + +The application must call functions :c:func:`bt_mesh_comp_change_prepare` and +:c:func:`bt_mesh_models_metadata_change_prepare` to store the existing Composition Data and Models +Metadata pages before booting into the firmware with the updated Composition Data and Models +Metadata. The old Composition Data will then be loaded into Composition Data Pages 0, 1 and 2, +while the Composition Data in the new firmware will be loaded into Composition Data Pages 128, 129 +and 130. The Models Metadata for the old image will be loaded into Models Metadata Page 0, and the +Models Metadata for the new image will be loaded into Models Metadata Page 128. + +Limitation: + +* It is not possible to change the Composition Data of the device and keep the device provisioned + and working with the old firmware after the new firmware image is applied. Start ===== -The Start procedure prepares the application for the incoming transfer. It'll contain information about which image is being updated, as well as the update metadata. +The Start procedure prepares the application for the incoming transfer. It'll contain information +about which image is being updated, as well as the update metadata. -The Firmware Update Server :c:member:`start ` callback must return a pointer to the BLOB Writer the BLOB Transfer Server will send the BLOB to. +The Firmware Update Server :c:member:`start ` callback must return a +pointer to the BLOB Writer the BLOB Transfer Server will send the BLOB to. BLOB transfer ============= -After the setup stage, the Firmware Update Server prepares the BLOB Transfer Server for the incoming transfer. The entire firmware image is transferred to the BLOB Transfer Server, which passes the image to its assigned BLOB Writer. +After the setup stage, the Firmware Update Server prepares the BLOB Transfer Server for the incoming +transfer. The entire firmware image is transferred to the BLOB Transfer Server, which passes the +image to its assigned BLOB Writer. -At the end of the BLOB transfer, the Firmware Update Server calls its :c:member:`end ` callback. +At the end of the BLOB transfer, the Firmware Update Server calls its +:c:member:`end ` callback. Image verification ================== -After the BLOB transfer has finished, the application should verify the image in any way it can to ensure that it is ready for being applied. -Once the image has been verified, the application calls :c:func:`bt_mesh_dfu_srv_verified`. +After the BLOB transfer has finished, the application should verify the image in any way it can to +ensure that it is ready for being applied. Once the image has been verified, the application calls +:c:func:`bt_mesh_dfu_srv_verified`. If the image can't be verified, the application calls :c:func:`bt_mesh_dfu_srv_rejected`. Applying the image ================== -Finally, if the image was verified, the Distributor may instruct the Firmware Update Server to apply the transfer. This is communicated to the application through the :c:member:`apply ` callback. The application should swap the image and start running with the new firmware. The firmware image table should be updated to reflect the new firmware ID of the updated image. +Finally, if the image was verified, the Distributor may instruct the Firmware Update Server to apply +the transfer. This is communicated to the application through the :c:member:`apply +` callback. The application should swap the image and start running with +the new firmware. The firmware image table should be updated to reflect the new firmware ID of the +updated image. -When the transfer applies to the mesh application itself, the device might have to reboot as part of the swap. This restart can be performed from inside the apply callback, or done asynchronously. After booting up with the new firmware, the firmware image table should be updated before the Bluetooth mesh subsystem is started. +When the transfer applies to the mesh application itself, the device might have to reboot as part of +the swap. This restart can be performed from inside the apply callback, or done asynchronously. +After booting up with the new firmware, the firmware image table should be updated before the +Bluetooth mesh subsystem is started. -The Distributor will read out the firmware image table to confirm that the transfer was successfully applied. If the metadata check indicated that the device would become unprovisioned, the Target node is not required to respond to this check. +The Distributor will read out the firmware image table to confirm that the transfer was successfully +applied. If the metadata check indicated that the device would become unprovisioned, the Target node +is not required to respond to this check. API reference ************* diff --git a/doc/connectivity/bluetooth/api/mesh/health_cli.rst b/doc/connectivity/bluetooth/api/mesh/health_cli.rst index da8ba1885bf..44f093dd748 100644 --- a/doc/connectivity/bluetooth/api/mesh/health_cli.rst +++ b/doc/connectivity/bluetooth/api/mesh/health_cli.rst @@ -12,9 +12,9 @@ used in this function call. The second parameter is the ``ctx`` or message context. Message context contains netkey index, appkey index and unicast address that the target node uses. -The Health Client model is optional, and may be instantiated in any element. -However, if a Health Client model is instantiated in an element other than the -first, an instance must also be present in the first element. +The Health Client model is optional, and may be instantiated on any element. +However, if a Health Client model is instantiated on an element other than the +primary, an instance must also be present on the primary element. See :ref:`bluetooth_mesh_health_faults` for a list of specification defined fault values. diff --git a/doc/connectivity/bluetooth/api/mesh/health_srv.rst b/doc/connectivity/bluetooth/api/mesh/health_srv.rst index 22803680290..84c543b4766 100644 --- a/doc/connectivity/bluetooth/api/mesh/health_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/health_srv.rst @@ -7,6 +7,8 @@ The Health Server model provides attention callbacks and node diagnostics for :ref:`bluetooth_mesh_models_health_cli` models. It is primarily used to report faults in the mesh node and map the mesh nodes to their physical location. +If present, the Health Server model must be instantiated on the primary element. + Faults ****** diff --git a/doc/connectivity/bluetooth/api/mesh/lcd_cli.rst b/doc/connectivity/bluetooth/api/mesh/lcd_cli.rst index 27df2e493b2..0eca28f1b2a 100644 --- a/doc/connectivity/bluetooth/api/mesh/lcd_cli.rst +++ b/doc/connectivity/bluetooth/api/mesh/lcd_cli.rst @@ -3,14 +3,20 @@ Large Composition Data Client ############################# -The Large Composition Data Client model is a foundation model defined by the Bluetooth -mesh specification. The model is optional, and is enabled through the :kconfig:option:`CONFIG_BT_MESH_LARGE_COMP_DATA_CLI` option. +The Large Composition Data Client model is a foundation model defined by the Bluetooth mesh +specification. The model is optional, and is enabled through the +:kconfig:option:`CONFIG_BT_MESH_LARGE_COMP_DATA_CLI` option. -The Large Composition Data Client model was introduced in the Bluetooth Mesh Protocol Specification version 1.1, and supports the functionality of reading pages of Composition Data that do not fit in a Config Composition Data Status message and reading the metadata of the model instances on a node that supports the :ref:`bluetooth_mesh_lcd_srv` model. +The Large Composition Data Client model was introduced in the Bluetooth Mesh Protocol Specification +version 1.1, and supports the functionality of reading pages of Composition Data that do not fit in +a Config Composition Data Status message and reading the metadata of the model instances on a node +that supports the :ref:`bluetooth_mesh_lcd_srv` model. -The Large Composition Data Client model communicates with a Large Composition Data Server model using the device key of the node containing the target Large Composition Data Server model instance. +The Large Composition Data Client model communicates with a Large Composition Data Server model +using the device key of the node containing the target Large Composition Data Server model instance. -If present, the Large Composition Data Client model must only be instantiated on the primary element. +If present, the Large Composition Data Client model must only be instantiated on the primary +element. API reference ************* diff --git a/doc/connectivity/bluetooth/api/mesh/lcd_srv.rst b/doc/connectivity/bluetooth/api/mesh/lcd_srv.rst index df724974b86..f96436138b7 100644 --- a/doc/connectivity/bluetooth/api/mesh/lcd_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/lcd_srv.rst @@ -3,24 +3,33 @@ Large Composition Data Server ############################# -The Large Composition Data Server model is a foundation model defined by the Bluetooth -mesh specification. The model is optional, and is enabled through the :kconfig:option:`CONFIG_BT_MESH_LARGE_COMP_DATA_SRV` option. +The Large Composition Data Server model is a foundation model defined by the Bluetooth mesh +specification. The model is optional, and is enabled through the +:kconfig:option:`CONFIG_BT_MESH_LARGE_COMP_DATA_SRV` option. -The Large Composition Data Server model was introduced in the Bluetooth Mesh Protocol Specification version 1.1, and is used to support -the functionality of exposing pages of Composition Data that do not fit in a Config Composition Data Status message and to expose metadata of the model instances. +The Large Composition Data Server model was introduced in the Bluetooth Mesh Protocol Specification +version 1.1, and is used to support the functionality of exposing pages of Composition Data that do +not fit in a Config Composition Data Status message and to expose metadata of the model instances. -The Large Composition Data Server does not have an API of its own and relies on a :ref:`bluetooth_mesh_lcd_cli` to control it. -The model only accepts messages encrypted with the node's device key. +The Large Composition Data Server does not have an API of its own and relies on a +:ref:`bluetooth_mesh_lcd_cli` to control it. The model only accepts messages encrypted with the +node's device key. -If present, the Large Composition Data Server model must only be instantiated on the primary element. +If present, the Large Composition Data Server model must only be instantiated on the primary +element. Models metadata =============== -The Large Composition Data Server model allows each model to have a list of model's specific metadata that can be read by the Large Composition Data Client model. -The metadata list can be associated with the :c:struct:`bt_mesh_model` through the :c:member:`bt_mesh_model.metadata` field. -The metadata list consists of one or more entries defined by the :c:struct:`bt_mesh_models_metadata_entry` structure. Each entry contains the length and ID of the metadata, and a pointer to the raw data. -Entries can be created using the :c:macro:`BT_MESH_MODELS_METADATA_ENTRY` macro. The :c:macro:`BT_MESH_MODELS_METADATA_END` macro marks the end of the metadata list and must always be present. If the model has no metadata, the helper macro :c:macro:`BT_MESH_MODELS_METADATA_NONE` can be used instead. +The Large Composition Data Server model allows each model to have a list of model's specific +metadata that can be read by the Large Composition Data Client model. The metadata list can be +associated with the :c:struct:`bt_mesh_model` through the :c:member:`bt_mesh_model.metadata` field. +The metadata list consists of one or more entries defined by the +:c:struct:`bt_mesh_models_metadata_entry` structure. Each entry contains the length and ID of the +metadata, and a pointer to the raw data. Entries can be created using the +:c:macro:`BT_MESH_MODELS_METADATA_ENTRY` macro. The :c:macro:`BT_MESH_MODELS_METADATA_END` macro +marks the end of the metadata list and must always be present. If the model has no metadata, the +helper macro :c:macro:`BT_MESH_MODELS_METADATA_NONE` can be used instead. API reference ************* diff --git a/doc/connectivity/bluetooth/api/mesh/models.rst b/doc/connectivity/bluetooth/api/mesh/models.rst index df3ba7404ef..3f5f94152ce 100644 --- a/doc/connectivity/bluetooth/api/mesh/models.rst +++ b/doc/connectivity/bluetooth/api/mesh/models.rst @@ -12,20 +12,22 @@ used by network administrators to configure and diagnose mesh nodes. .. toctree:: :maxdepth: 1 - cfg_srv cfg_cli - health_srv + cfg_srv health_cli + health_srv lcd_cli lcd_srv od_cli od_srv op_agg_cli op_agg_srv - priv_beacon_srv priv_beacon_cli + priv_beacon_srv rpr_cli rpr_srv + sar_cfg_cli + sar_cfg_srv srpl_cli srpl_srv diff --git a/doc/connectivity/bluetooth/api/mesh/od_cli.rst b/doc/connectivity/bluetooth/api/mesh/od_cli.rst index bf8ef4fc3f4..5fc841716ce 100644 --- a/doc/connectivity/bluetooth/api/mesh/od_cli.rst +++ b/doc/connectivity/bluetooth/api/mesh/od_cli.rst @@ -3,22 +3,30 @@ On-Demand Private Proxy Client ############################## -The On-Demand Private Proxy Client model is a foundation model defined by the Bluetooth -mesh specification. The model is optional, and is enabled with the :kconfig:option:`CONFIG_BT_MESH_OD_PRIV_PROXY_CLI` option. +The On-Demand Private Proxy Client model is a foundation model defined by the Bluetooth mesh +specification. The model is optional, and is enabled with the +:kconfig:option:`CONFIG_BT_MESH_OD_PRIV_PROXY_CLI` option. -The On-Demand Private Proxy Client model was introduced in the Bluetooth Mesh Protocol -Specification version 1.1, and is used to set and retrieve the On-Demand Private GATT Proxy state. The state defines -how long a node will advertise Mesh Proxy Service with Private Network Identity type after it receives a Solicitation PDU. +The On-Demand Private Proxy Client model was introduced in the Bluetooth Mesh Protocol Specification +version 1.1, and is used to set and retrieve the On-Demand Private GATT Proxy state. The state +defines how long a node will advertise Mesh Proxy Service with Private Network Identity type after +it receives a Solicitation PDU. The On-Demand Private Proxy Client model communicates with an On-Demand Private Proxy Server model -using the device key of the node containing the target On-Demand Private Proxy Server model instance. +using the device key of the node containing the target On-Demand Private Proxy Server model +instance. + +If present, the On-Demand Private Proxy Client model must only be instantiated on the primary +element. Configurations ************** -The On-Demand Private Proxy Client model behavior can be configured with the transmission timeout option :kconfig:option:`CONFIG_BT_MESH_OD_PRIV_PROXY_CLI_TIMEOUT`. -The :kconfig:option:`CONFIG_BT_MESH_OD_PRIV_PROXY_CLI_TIMEOUT` controls how long the Client waits for a state response message to arrive -in milliseconds. This value can be changed at runtime using :c:func:`bt_mesh_od_priv_proxy_cli_timeout_set`. +The On-Demand Private Proxy Client model behavior can be configured with the transmission timeout +option :kconfig:option:`CONFIG_BT_MESH_OD_PRIV_PROXY_CLI_TIMEOUT`. The +:kconfig:option:`CONFIG_BT_MESH_OD_PRIV_PROXY_CLI_TIMEOUT` controls how long the Client waits for a +state response message to arrive in milliseconds. This value can be changed at runtime using +:c:func:`bt_mesh_od_priv_proxy_cli_timeout_set`. API reference diff --git a/doc/connectivity/bluetooth/api/mesh/od_srv.rst b/doc/connectivity/bluetooth/api/mesh/od_srv.rst index 241ce5f155c..700517e4283 100644 --- a/doc/connectivity/bluetooth/api/mesh/od_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/od_srv.rst @@ -3,21 +3,21 @@ On-Demand Private Proxy Server ############################## -The On-Demand Private Proxy Server model is a foundation model defined by the Bluetooth -mesh specification. It is enabled with the :kconfig:option:`CONFIG_BT_MESH_OD_PRIV_PROXY_SRV` option. +The On-Demand Private Proxy Server model is a foundation model defined by the Bluetooth mesh +specification. It is enabled with the :kconfig:option:`CONFIG_BT_MESH_OD_PRIV_PROXY_SRV` option. -The On-Demand Private Proxy Server model was introduced in the Bluetooth Mesh Protocol -Specification version 1.1, and supports the configuration of advertising with Private Network Identity type of a node -that is a recipient of Solicitation PDUs by managing its On-Demand Private GATT Proxy state. +The On-Demand Private Proxy Server model was introduced in the Bluetooth Mesh Protocol Specification +version 1.1, and supports the configuration of advertising with Private Network Identity type of a +node that is a recipient of Solicitation PDUs by managing its On-Demand Private GATT Proxy state. -When enabled, the :ref:`bluetooth_mesh_srpl_srv` is also enabled. The On-Demand Private Proxy Server is dependent on the -:ref:`bluetooth_mesh_models_priv_beacon_srv` to be present on the node. +When enabled, the :ref:`bluetooth_mesh_srpl_srv` is also enabled. The On-Demand Private Proxy Server +is dependent on the :ref:`bluetooth_mesh_models_priv_beacon_srv` to be present on the node. The On-Demand Private Proxy Server does not have an API of its own, and relies on a -:ref:`bluetooth_mesh_od_cli` to control it. The On-Demand Private Proxy Server -model only accepts messages encrypted with the node's device key. +:ref:`bluetooth_mesh_od_cli` to control it. The On-Demand Private Proxy Server model only accepts +messages encrypted with the node's device key. -If present, the On-Demand Private Proxy Server model must be instantiated on the primary +If present, the On-Demand Private Proxy Server model must only be instantiated on the primary element. API reference diff --git a/doc/connectivity/bluetooth/api/mesh/op_agg_cli.rst b/doc/connectivity/bluetooth/api/mesh/op_agg_cli.rst index 23eb608391f..148557a4e81 100644 --- a/doc/connectivity/bluetooth/api/mesh/op_agg_cli.rst +++ b/doc/connectivity/bluetooth/api/mesh/op_agg_cli.rst @@ -3,24 +3,25 @@ Opcodes Aggregator Client ######################### -The Opcodes Aggregator Client model is a foundation model defined by the Bluetooth -mesh specification. It is an optional model, enabled with the :kconfig:option:`CONFIG_BT_MESH_OP_AGG_CLI` option. +The Opcodes Aggregator Client model is a foundation model defined by the Bluetooth mesh +specification. It is an optional model, enabled with the :kconfig:option:`CONFIG_BT_MESH_OP_AGG_CLI` +option. -The Opcodes Aggregator Client model is introduced in the Bluetooth Mesh Profile -Specification version 1.1, and is used to support the functionality of dispatching -a sequence of access layer messages to nodes supporting the :ref:`bluetooth_mesh_models_op_agg_srv` model. +The Opcodes Aggregator Client model is introduced in the Bluetooth Mesh Protocol Specification +version 1.1, and is used to support the functionality of dispatching a sequence of access layer +messages to nodes supporting the :ref:`bluetooth_mesh_models_op_agg_srv` model. -The Opcodes Aggregator Client model communicates with an Opcodes Aggregator Server model -using the device key of the target node or the application keys configured by the Configuration Client. +The Opcodes Aggregator Client model communicates with an Opcodes Aggregator Server model using the +device key of the target node or the application keys configured by the Configuration Client. -The Opcodes Aggregator Client model must only be instantiated on the primary -element, and it is implicitly bound to the device key on initialization. +If present, the Opcodes Aggregator Client model must only be instantiated on the primary element. -The Opcodes Aggregator Client model should be bound to the same application keys that the client models, -used to produce the sequence of messages, are bound to. +The Opcodes Aggregator Client model is implicitly bound to the device key on initialization. It +should be bound to the same application keys as the client models that are used to produce the +sequence of messages. -To be able to aggregate a message from a client model, it should support an asynchronous -API, for example through callbacks. +To be able to aggregate a message from a client model, it should support an asynchronous API, for +example through callbacks. API reference ************* diff --git a/doc/connectivity/bluetooth/api/mesh/op_agg_srv.rst b/doc/connectivity/bluetooth/api/mesh/op_agg_srv.rst index 5d493cb4590..81bd4a90b22 100644 --- a/doc/connectivity/bluetooth/api/mesh/op_agg_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/op_agg_srv.rst @@ -4,17 +4,17 @@ Opcodes Aggregator Server ######################### The Opcodes Aggregator Server model is a foundation model defined by the Bluetooth -mesh specification. It is an optional model, enabled with the :kconfig:option:`CONFIG_BT_MESH_OP_AGG_SRV` option. +mesh specification. It is an optional model, enabled with the +:kconfig:option:`CONFIG_BT_MESH_OP_AGG_SRV` option. -The Opcodes Aggregator Server model is introduced in the Bluetooth Mesh Profile +The Opcodes Aggregator Server model is introduced in the Bluetooth Mesh Protocol Specification version 1.1, and is used to support the functionality of processing a sequence of access layer messages. The Opcodes Aggregator Server model accepts messages encrypted with the node's device key or the application keys. -The Opcodes Aggregator Server model can only be instantiated on the -node's primary element. +If present, the Opcodes Aggregator Server model must only be instantiated on the primary element. The targeted server models should be bound to the same application key that is used to encrypt the sequence of access layer messages sent to the Opcodes Aggregator Server. diff --git a/doc/connectivity/bluetooth/api/mesh/priv_beacon_cli.rst b/doc/connectivity/bluetooth/api/mesh/priv_beacon_cli.rst index 6a6f44b1387..cb531a4c3c8 100644 --- a/doc/connectivity/bluetooth/api/mesh/priv_beacon_cli.rst +++ b/doc/connectivity/bluetooth/api/mesh/priv_beacon_cli.rst @@ -7,7 +7,7 @@ The Private Beacon Client model is a foundation model defined by the Bluetooth mesh specification. It is enabled with the :kconfig:option:`CONFIG_BT_MESH_PRIV_BEACON_CLI` option. -The Private Beacon Client model is introduced in the Bluetooth Mesh Profile +The Private Beacon Client model is introduced in the Bluetooth Mesh Protocol Specification version 1.1, and provides functionality for configuring the :ref:`bluetooth_mesh_models_priv_beacon_srv` models. @@ -25,8 +25,7 @@ All configuration functions in the Private Beacon Client API have ``net_idx`` and ``addr`` as their first parameters. These should be set to the network index and the primary unicast address the target node was provisioned with. -The Private Beacon Client model is optional, and can be instantiated on any -element. +If present, the Private Beacon Client model must only be instantiated on the primary element. API reference ************* diff --git a/doc/connectivity/bluetooth/api/mesh/priv_beacon_srv.rst b/doc/connectivity/bluetooth/api/mesh/priv_beacon_srv.rst index d69fe616e38..3c17cc44675 100644 --- a/doc/connectivity/bluetooth/api/mesh/priv_beacon_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/priv_beacon_srv.rst @@ -7,7 +7,7 @@ The Private Beacon Server model is a foundation model defined by the Bluetooth mesh specification. It is enabled with :kconfig:option:`CONFIG_BT_MESH_PRIV_BEACON_SRV` option. -The Private Beacon Server model is introduced in the Bluetooth Mesh Profile +The Private Beacon Server model is introduced in the Bluetooth Mesh Protocol Specification version 1.1, and controls the mesh node's Private Beacon state, Private GATT Proxy state and Private Node Identity state. @@ -28,8 +28,7 @@ Server model through the :c:struct:`bt_mesh_priv_beacon_srv` instance passed to changes to this configuration in the settings subsystem, the initial values may be overwritten upon loading. -The Private Beacon Server model is optional, and can only be instantiated in the -node's primary element. +If present, the Private Beacon Server model must only be instantiated on the primary element. API reference ************* diff --git a/doc/connectivity/bluetooth/api/mesh/provisioning.rst b/doc/connectivity/bluetooth/api/mesh/provisioning.rst index 7c564e17f4a..36fa38927a3 100644 --- a/doc/connectivity/bluetooth/api/mesh/provisioning.rst +++ b/doc/connectivity/bluetooth/api/mesh/provisioning.rst @@ -53,7 +53,7 @@ The Uniform Resource Identifier shall follow the format specified in the Bluetooth Core Specification Supplement. The URI must start with a URI scheme, encoded as a single utf-8 data point, or the special ``none`` scheme, encoded as ``0x01``. The available schemes are listed on the `Bluetooth website -`_. +`_. Examples of encoded URIs: @@ -180,7 +180,7 @@ a set of vulnerabilities in the Bluetooth mesh provisioning protocol that showca how the low entropy provided by the Blink, Vibrate, Push, Twist and Input/Output numeric OOB methods could be exploited in impersonation and MITM attacks. In response, the Bluetooth SIG has reclassified these OOB methods as -insecure in the Mesh Profile specification `erratum 16350 `_, +insecure in the Bluetooth Mesh Profile Specification v1.0.1 `erratum 16350 `_, as AuthValue may be brute forced in real time. To ensure secure provisioning, applications should use a static OOB value and OOB public key transfer. diff --git a/doc/connectivity/bluetooth/api/mesh/proxy.rst b/doc/connectivity/bluetooth/api/mesh/proxy.rst index 87ee3b07f1d..823401c9571 100644 --- a/doc/connectivity/bluetooth/api/mesh/proxy.rst +++ b/doc/connectivity/bluetooth/api/mesh/proxy.rst @@ -3,11 +3,10 @@ Proxy ##### -The Proxy feature allows legacy devices like phones to access the Bluetooth -mesh network through GATT. The Proxy feature is only compiled in if the -:kconfig:option:`CONFIG_BT_MESH_GATT_PROXY` option is set. The Proxy feature state is -controlled by the :ref:`bluetooth_mesh_models_cfg_srv`, and the initial value -can be set with :c:member:`bt_mesh_cfg_srv.gatt_proxy`. +The Proxy feature allows legacy devices like phones to access the Bluetooth mesh network through +GATT. The Proxy feature is only compiled in if the :kconfig:option:`CONFIG_BT_MESH_GATT_PROXY` +option is set. The Proxy feature state is controlled by the :ref:`bluetooth_mesh_models_cfg_srv`, +and the initial value can be set with :c:member:`bt_mesh_cfg_srv.gatt_proxy`. Nodes with the Proxy feature enabled can advertise with Network Identity and Node Identity, which is controlled by the :ref:`bluetooth_mesh_models_cfg_cli`. @@ -17,8 +16,8 @@ The GATT Proxy state indicates if the Proxy feature is supported. Private Proxy ************* -A node supporting the Proxy feature and the :ref:`bluetooth_mesh_models_priv_beacon_srv` model can advertise with -Private Network Identity and Private Node Identity types, which is controlled by the +A node supporting the Proxy feature and the :ref:`bluetooth_mesh_models_priv_beacon_srv` model can +advertise with Private Network Identity and Private Node Identity types, which is controlled by the :ref:`bluetooth_mesh_models_priv_beacon_cli`. By advertising with this set of identification types, the node allows the legacy device to connect to the network over GATT while maintaining the privacy of the network. @@ -28,28 +27,32 @@ The Private GATT Proxy state indicates whether the Private Proxy functionality i Proxy Solicitation ****************** -In the case where both GATT Proxy and Private GATT Proxy states are disabled on a node, a legacy device cannot -connect to it. A node supporting the :ref:`bluetooth_mesh_od_srv` may however be +In the case where both GATT Proxy and Private GATT Proxy states are disabled on a node, a legacy +device cannot connect to it. A node supporting the :ref:`bluetooth_mesh_od_srv` may however be solicited to advertise connectable advertising events without enabling the Private GATT Proxy state. -To solicit the node, the legacy device can send a Solicitation PDU by calling the :func:`bt_mesh_proxy_solicit` function. -To enable this feature, the client must to be compiled with the :kconfig:option:`CONFIG_BT_MESH_PROXY_SOLICITATION` -option set. +To solicit the node, the legacy device can send a Solicitation PDU by calling the +:func:`bt_mesh_proxy_solicit` function. To enable this feature, the device must to be compiled with +the :kconfig:option:`CONFIG_BT_MESH_PROXY_SOLICITATION` option set. -Solicitation PDUs are non-mesh, non-connectable, undirected advertising messages -containing Proxy Solicitation UUID, encrypted with the network key of the subnet that the legacy device -wants to connect to. The PDU contains the source address of the legacy device and a sequence number. The -sequence number is maintained by the legacy device and is incremented for every new Solicitation PDU sent. +Solicitation PDUs are non-mesh, non-connectable, undirected advertising messages containing Proxy +Solicitation UUID, encrypted with the network key of the subnet that the legacy device wants to +connect to. The PDU contains the source address of the legacy device and a sequence number. The +sequence number is maintained by the legacy device and is incremented for every new Solicitation PDU +sent. -Each node supporting the Solicitation PDU reception holds its own Solicitation Replay Protection List (SRPL). -The SRPL protects the solicitation mechanism from replay attacks by storing solicitation sequence number (SSEQ) -and solicitation source (SSRC) pairs of valid Solicitation PDUs processed by the node. The delay between updating the -SRPL and storing the change to the persistent storage is defined by :kconfig:option:`CONFIG_BT_MESH_RPL_STORE_TIMEOUT`. +Each node supporting the Solicitation PDU reception holds its own Solicitation Replay Protection +List (SRPL). The SRPL protects the solicitation mechanism from replay attacks by storing +solicitation sequence number (SSEQ) and solicitation source (SSRC) pairs of valid Solicitation PDUs +processed by the node. The delay between updating the SRPL and storing the change to the persistent +storage is defined by :kconfig:option:`CONFIG_BT_MESH_RPL_STORE_TIMEOUT`. The Solicitation PDU RPL Configuration models, :ref:`bluetooth_mesh_srpl_cli` and -:ref:`bluetooth_mesh_srpl_srv`, provide the functionality of saving and clearing SRPL entries. -A node that supports the Solicitation PDU RPL Configuration Client model can clear a section of the SRPL on the target by calling the :func:`bt_mesh_sol_pdu_rpl_clear` function. -Communication between the Solicitation PDU RPL Configuration Client and Server is encrypted using the application key, therefore, -the Solicitation PDU RPL Configuration Client can be instantiated on any device in the network. +:ref:`bluetooth_mesh_srpl_srv`, provide the functionality of saving and clearing SRPL entries. A +node that supports the Solicitation PDU RPL Configuration Client model can clear a section of the +SRPL on the target by calling the :func:`bt_mesh_sol_pdu_rpl_clear` function. Communication between +the Solicitation PDU RPL Configuration Client and Server is encrypted using the application key, +therefore, the Solicitation PDU RPL Configuration Client can be instantiated on any device in the +network. When the node receives the Solicitation PDU and successfully authenticates it, it will start advertising connectable advertisements with the Private Network Identity type. The duration of the diff --git a/doc/connectivity/bluetooth/api/mesh/rpr_cli.rst b/doc/connectivity/bluetooth/api/mesh/rpr_cli.rst index 38cb8849f9e..8a87939541a 100644 --- a/doc/connectivity/bluetooth/api/mesh/rpr_cli.rst +++ b/doc/connectivity/bluetooth/api/mesh/rpr_cli.rst @@ -9,7 +9,9 @@ mesh specification. It is enabled with the The Remote Provisioning Client model is introduced in the Bluetooth Mesh Protocol Specification version 1.1. -This model provides functionality to remotely provision devices into a mesh network, and perform Node Provisioning Protocol Interface procedures by interacting with mesh nodes that support the :ref:`bluetooth_mesh_models_rpr_srv` model. +This model provides functionality to remotely provision devices into a mesh network, and perform +Node Provisioning Protocol Interface procedures by interacting with mesh nodes that support the +:ref:`bluetooth_mesh_models_rpr_srv` model. The Remote Provisioning Client model communicates with a Remote Provisioning Server model using the device key of the node containing the target Remote Provisioning Server model instance. @@ -20,7 +22,9 @@ element. Scanning ******** -The scanning procedure is used to scan for unprovisioned devices located nearby the Remote Provisioning Server. The Remote Provisioning Client starts a scan procedure by using the :c:func:`bt_mesh_rpr_scan_start` call: +The scanning procedure is used to scan for unprovisioned devices located nearby the Remote +Provisioning Server. The Remote Provisioning Client starts a scan procedure by using the +:c:func:`bt_mesh_rpr_scan_start` call: .. code-block:: C @@ -49,21 +53,24 @@ The scanning procedure is used to scan for unprovisioned devices located nearby bt_mesh_rpr_scan_start(&rpr_cli, &srv, uuid, timeout, max_devs, &status); -The above example shows pseudo code for starting a scan procedure on the target Remote Provisioning Server node. This -procedure will start a ten-second, multiple-device scanning where the generated scan report will contain -a maximum of three unprovisioned devices. If the UUID argument was specified, the same procedure would -only scan for the device with the corresponding UUID. After the procedure completes, the -server sends the scan report that will be handled in the client's :c:member:`bt_mesh_rpr_cli.scan_report` callback. +The above example shows pseudo code for starting a scan procedure on the target Remote Provisioning +Server node. This procedure will start a ten-second, multiple-device scanning where the generated +scan report will contain a maximum of three unprovisioned devices. If the UUID argument was +specified, the same procedure would only scan for the device with the corresponding UUID. After the +procedure completes, the server sends the scan report that will be handled in the client's +:c:member:`bt_mesh_rpr_cli.scan_report` callback. Additionally, the Remote Provisioning Client model also supports extended scanning with the -:c:func:`bt_mesh_rpr_scan_start_ext` call. Extended scanning supplements regular scanning by allowing the -Remote Provisioning Server to report additional data for a specific device. The Remote Provisioning Server will use active scanning to request -a scan response from the unprovisioned device if it is supported by the unprovisioned device. +:c:func:`bt_mesh_rpr_scan_start_ext` call. Extended scanning supplements regular scanning by +allowing the Remote Provisioning Server to report additional data for a specific device. The Remote +Provisioning Server will use active scanning to request a scan response from the unprovisioned +device if it is supported by the unprovisioned device. Provisioning ************ -The Remote Provisioning Client starts a provisioning procedure by using the :c:func:`bt_mesh_provision_remote` call: +The Remote Provisioning Client starts a provisioning procedure by using the +:c:func:`bt_mesh_provision_remote` call: .. code-block:: C @@ -81,25 +88,27 @@ The Remote Provisioning Client starts a provisioning procedure by using the :c:f bt_mesh_provision_remote(&rpr_cli, &srv, uuid, net_idx, addr); -The above example shows pseudo code for remotely provisioning a device through a Remote Provisioning Server node. This -procedure will attempt to provision the device with the corresponding UUID, and assign the address 0x0006 -to its primary element using the network key located at index zero. +The above example shows pseudo code for remotely provisioning a device through a Remote Provisioning +Server node. This procedure will attempt to provision the device with the corresponding UUID, and +assign the address 0x0006 to its primary element using the network key located at index zero. .. note:: - During the remote provisioning, the same :c:struct:`bt_mesh_prov` callbacks are triggered as for ordinary - provisioning. See section :ref:`bluetooth_mesh_provisioning` for further details. + During the remote provisioning, the same :c:struct:`bt_mesh_prov` callbacks are triggered as for + ordinary provisioning. See section :ref:`bluetooth_mesh_provisioning` for further details. Re-provisioning *************** -In addition to scanning and provisioning functionality, the Remote Provisioning Client also provides means to -reconfigure node addresses, device keys and Composition Data on devices that support the -:ref:`bluetooth_mesh_models_rpr_srv` model. This is provided through the Node Provisioning Protocol Interface -(NPPI) which supports the following three procedures: +In addition to scanning and provisioning functionality, the Remote Provisioning Client also provides +means to reconfigure node addresses, device keys and Composition Data on devices that support the +:ref:`bluetooth_mesh_models_rpr_srv` model. This is provided through the Node Provisioning Protocol +Interface (NPPI) which supports the following three procedures: -* Device Key Refresh procedure: Used to change the device key of the Target node without a need to reconfigure the node. +* Device Key Refresh procedure: Used to change the device key of the Target node without a need to + reconfigure the node. * Node Address Refresh procedure: Used to change the node’s device key and unicast address. -* Node Composition Refresh procedure: Used to change the device key of the node, and to add or delete models or features of the node. +* Node Composition Refresh procedure: Used to change the device key of the node, and to add or + delete models or features of the node. The three NPPI procedures can be initiated with the :c:func:`bt_mesh_reprovision_remote` call: @@ -117,12 +126,13 @@ The three NPPI procedures can be initiated with the :c:func:`bt_mesh_reprovision bt_mesh_reprovision_remote(&rpr_cli, &srv, new_addr, composition_changed); -The above example shows pseudo code for triggering a Node Address Refresh procedure on the Target node. -The specific procedure is not chosen directly, but rather through the other parameters that are inputted. -In the example we can see that the current unicast address of the Target is 0x0006, while the new address is -set to 0x0009. If the two addresses were the same, and the ``composition_changed`` flag was set to true, this code -would instead trigger a Node Composition Refresh procedure. If the two addresses were the same, and -the ``composition_changed`` flag was set to false, this code would trigger a Device Key Refresh procedure. +The above example shows pseudo code for triggering a Node Address Refresh procedure on the Target +node. The specific procedure is not chosen directly, but rather through the other parameters that +are inputted. In the example we can see that the current unicast address of the Target is 0x0006, +while the new address is set to 0x0009. If the two addresses were the same, and the +``composition_changed`` flag was set to true, this code would instead trigger a Node Composition +Refresh procedure. If the two addresses were the same, and the ``composition_changed`` flag was set +to false, this code would trigger a Device Key Refresh procedure. API reference ************* diff --git a/doc/connectivity/bluetooth/api/mesh/rpr_srv.rst b/doc/connectivity/bluetooth/api/mesh/rpr_srv.rst index f958ef31bd9..e51d3c8fac9 100644 --- a/doc/connectivity/bluetooth/api/mesh/rpr_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/rpr_srv.rst @@ -15,12 +15,20 @@ The Remote Provisioning Server does not have an API of its own, but relies on a :ref:`bluetooth_mesh_models_rpr_cli` to control it. The Remote Provisioning Server model only accepts messages encrypted with the node's device key. -If present, the Remote Provisioning Server model must be instantiated on the primary -element. +If present, the Remote Provisioning Server model must be instantiated on the primary element. + +Note that after refreshing the device key, node address or Composition Data through a Node +Provisioning Protocol Interface (NPPI) procedure, the :c:member:`bt_mesh_prov.reprovisioned` +callback is triggered. See section :ref:`bluetooth_mesh_models_rpr_cli` for further details. + +Limitations +----------- + +The following limitations apply to Remote Provisioning Server model: + +* Provisioning of unprovisioned device using PB-GATT is not supported. +* All Node Provisioning Protocol Interface (NPPI) procedures are supported. However, if the composition data of a device gets changed after device firmware update (see :ref:`firmware effect `), it is not possible for the device to remain provisioned. The device should be unprovisioned if its composition data is expected to change. -Note that after refreshing the device key, node address or Composition Data through a Node Provisioning Protocol -Interface (NPPI) procedure, the :c:member:`bt_mesh_prov.reprovisioned` callback is triggered. See section -:ref:`bluetooth_mesh_models_rpr_cli` for further details. API reference ************* diff --git a/doc/connectivity/bluetooth/api/mesh/sar_cfg.rst b/doc/connectivity/bluetooth/api/mesh/sar_cfg.rst new file mode 100644 index 00000000000..a0aa2b46a3e --- /dev/null +++ b/doc/connectivity/bluetooth/api/mesh/sar_cfg.rst @@ -0,0 +1,314 @@ +.. _bluetooth_mesh_sar_cfg: + +Segmentation and reassembly (SAR) +################################# + +Segmentation and reassembly (SAR) provides a way of handling larger upper transport layer messages +in a mesh network, with a purpose of enhancing the Bluetooth mesh throughput. The segmentation and +reassembly mechanism is used by the lower transport layer. + +The lower transport layer defines how the upper transport layer PDUs are segmented and reassembled +into multiple Lower Transport PDUs, and sends them to the lower transport layer on a peer device. +If the Upper Transport PDU fits, it is sent in a single Lower Transport PDU. For longer packets, +which do not fit into a single Lower Transport PDU, the lower transport layer performs segmentation, +splitting the Upper Transport +PDU into multiple segments. + +The lower transport layer on the receiving device reassembles the segments into a single Upper +Transport PDU before passing it up the stack. Delivery of a segmented message is acknowledged by the +lower transport layer of the receiving node, while an unsegmented message delivery is not +acknowledged. However, an Upper Transport PDU that fits into one Lower Transport PDU can also be +sent as a single-segment segmented message when acknowledgment by the lower transport layer is +required. Set the ``send rel`` flag (see :c:struct:`bt_mesh_msg_ctx`) to use the reliable message +transmission and acknowledge single-segment segmented messages. + +The transport layer is able to transport up to 32 segments with its SAR mechanism, with a maximum +message (PDU) size of 384 octets. To configure message size for the Bluetooth mesh stack, use the +following Kconfig options: + +* :kconfig:option:`CONFIG_BT_MESH_RX_SEG_MAX` to set the maximum number of segments in an incoming message. +* :kconfig:option:`CONFIG_BT_MESH_TX_SEG_MAX` to set the maximum number of segments in an outgoing message. + +The Kconfig options :kconfig:option:`CONFIG_BT_MESH_TX_SEG_MSG_COUNT` and +:kconfig:option:`CONFIG_BT_MESH_RX_SEG_MSG_COUNT` define how many outgoing and incoming segmented +messages can be processed simultaneously. When more than one segmented message is sent to the same +destination, the messages are queued and sent one at a time. + +Incoming and outgoing segmented messages share the same pool for allocation of their segments. This +pool size is configured through the :kconfig:option:`CONFIG_BT_MESH_SEG_BUFS` Kconfig option. +Both incoming and outgoing messages allocate segments at the start of the transaction. The outgoing +segmented message releases its segments one by one as soon as they are acknowledged by the receiver, +while the incoming message releases the segments first after the message is fully received. +Keep this in mind when defining the size of the buffers. + +SAR does not impose extra overhead on the access layer payload per segment. + +Intervals, timers and retransmission counters +********************************************* + +The current stable stack implementation allows you to configure the following SAR behavior. + +When sending a segmented message to a unicast address, the unacknowledged segments are repeated +the :kconfig:option:`CONFIG_BT_MESH_TX_SEG_RETRANS_COUNT` number of times before the transmission +is considered as failed. The same option configures a number of retransmissions to a group or +virtual address, but the transmission always succeedes after retransmitting all segments the +configured number of times. + +The timeout between each retransmission to a unicast address is configured by the Kconfig option +:kconfig:option:`CONFIG_BT_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST`. The timeout between each +retransmission to a group or a virtual address is configured by the Kconfig option +:kconfig:option:`CONFIG_BT_MESH_TX_SEG_RETRANS_TIMEOUT_GROUP`. + +The time before sending a Segment Acknowledgment message is controlled by the Kconfig options +:kconfig:option:`CONFIG_BT_MESH_SEG_ACK_BASE_TIMEOUT`, +:kconfig:option:`CONFIG_BT_MESH_SEG_ACK_PER_HOP_TIMEOUT` and +:kconfig:option:`CONFIG_BT_MESH_SEG_ACK_PER_SEGMENT_TIMEOUT`, and is defined as: + +.. math:: + \begin{aligned} + \max(&\mathtt{CONFIG\_BT\_MESH\_SEG\_ACK\_BASE\_TIMEOUT} \\ + &+ \text{TTL} \times \mathtt{CONFIG\_BT\_MESH\_SEG\_ACK\_PER\_HOP\_TIMEOUT} \\ + &+ \text{number of un-acked segments} \times \mathtt{CONFIG\_BT\_MESH\_SEG\_ACK\_PER\_SEGMENT\_TIMEOUT} , 400) + \end{aligned} + +Segmentation and reassembly (SAR) Configuration models +====================================================== + +With Bluetooth Mesh Protocol Specification version 1.1, it became possible to configure SAR +behavior, such as intervals, timers and retransmission counters, over a mesh network using SAR +Configuration models: + +* :ref:`bluetooth_mesh_sar_cfg_cli` +* :ref:`bluetooth_mesh_sar_cfg_srv` + +The following SAR behavior applies regardless of the presence of a SAR Configuration Server on a +node. + +Transmission of segments is separated by a segment transmission interval (see the +`SAR Segment Interval Step`_ state). Other configurable time intervals and delays available for the +segmentation and reassembly are: + +* Interval between unicast retransmissions (see the states `SAR Unicast Retransmissions Interval Step`_ and `SAR Unicast Retransmissions Interval Increment`_). +* Interval between multicast retransmissions (see the `SAR Multicast Retransmissions Interval Step`_ state). +* Segment reception interval (see the `SAR Receiver Segment Interval Step`_ state). +* Acknowledgment delay increment (see the `SAR Acknowledgment Delay Increment`_ state). + +When the last segment marked as unacknowledged is transmitted, the lower transport layer starts a +retransmissions timer. The initial value of the SAR Unicast Retransmissions timer depends on the +value of the TTL field of the message. If the TTL field value is greater than ``0``, the initial +value for the timer is set according to the following formula: + +.. math:: + + unicast~retransmissions~interval~step + unicast~retransmissions~interval~increment \times (TTL - 1) + + +If the TTL field value is ``0``, the initial value of the timer is set to the unicast +retransmissions interval step. + +The initial value of the SAR Multicast Retransmissions timer is set to the multicast retransmissions +interval. + +When the lower transport layer receives a message segment, it starts a SAR Discard timer. The +discard timer tells how long the lower transport layer waits before discarding the segmented message +the segment belongs to. The initial value of the SAR Discard timer is the discard timeout value +indicated by the `SAR Discard Timeout`_ state. + +SAR Acknowledgment timer holds the time before a Segment Acknowledgment message is sent for a +received segment. The initial value of the SAR Acknowledgment timer is calculated using the +following formula: + +.. math:: + + min(SegN + 0.5 , acknowledgment~delay~increment) \times segment~reception~interval + + +The ``SegN`` field value identifies the total number of segments the Upper Transport PDU is +segmented into. + +Four counters are related to SAR behavior: + +* Two unicast retransmissions counts (see `SAR Unicast Retransmissions Count`_ state and `SAR Unicast Retransmissions Without Progress Count`_ state) +* Multicast retransmissions count (see `SAR Multicast Retransmissions Count`_ state) +* Acknowledgment retransmissions count (see `SAR Acknowledgment Retransmissions Count`_ state) + +If the number of segments in the transmission is higher than the value of the +`SAR Segments Threshold`_ state, Segment Acknowledgment messages are retransmitted using the value +of the `SAR Acknowledgment Retransmissions Count`_ state. + +.. _bt_mesh_sar_cfg_states: + +SAR states +========== + +There are two states defined related to segmentation and reassembly: + +* SAR Transmitter state +* SAR Receiver state + +The SAR Transmitter state is a composite state that controls the number and timing of transmissions +of segmented messages. It includes the following states: + +* SAR Segment Interval Step +* SAR Unicast Retransmissions Count +* SAR Unicast Retransmissions Without Progress Count +* SAR Unicast Retransmissions Interval Step +* SAR Unicast Retransmissions Interval Increment +* SAR Multicast Retransmissions Count +* SAR Multicast Retransmissions Interval Step + +The SAR Receiver state is a composite state that controls the number and timing of Segment +Acknowledgment transmissions and the discarding of reassembly of a segmented message. It includes +the following states: + +* SAR Segments Threshold +* SAR Discard Timeout +* SAR Acknowledgment Delay Increment +* SAR Acknowledgment Retransmissions Count +* SAR Receiver Segment Interval Step + +SAR Segment Interval Step +------------------------- + +SAR Segment Interval Step state holds a value that controls the interval between transmissions of +segments of a segmented message. The interval is measured in milliseconds. + +Use the :kconfig:option:`CONFIG_BT_MESH_SAR_TX_SEG_INT_STEP` Kconfig option to set the default +value. Segment transmission interval is then calculated using the following formula: + +.. math:: + + (\mathtt{CONFIG\_BT\_MESH\_SAR\_TX\_SEG\_INT\_STEP} + 1) \times 10~\text{ms} + + +SAR Unicast Retransmissions Count +--------------------------------- + +SAR Unicast Retransmissions Count holds a value that defines the maximum number of retransmissions +of a segmented message to a unicast destination. Use the +:kconfig:option:`CONFIG_BT_MESH_SAR_TX_UNICAST_RETRANS_COUNT` Kconfig option to set the default +value for this state. + +SAR Unicast Retransmissions Without Progress Count +-------------------------------------------------- + +This state holds a value that defines the maximum number of retransmissions of a segmented message +to a unicast address that will be sent if no acknowledgment was received during the timeout, or if +an acknowledgment with already confirmed segments was received. Use the Kconfig option +:kconfig:option:`CONFIG_BT_MESH_SAR_TX_UNICAST_RETRANS_WITHOUT_PROG_COUNT` to set the maximum number +of retransmissions. + +SAR Unicast Retransmissions Interval Step +----------------------------------------- + +The value of this state controls the interval step used for delaying the retransmissions of +unacknowledged segments of a segmented message to a unicast address. The interval step is measured +in milliseconds. + +Use the :kconfig:option:`CONFIG_BT_MESH_SAR_TX_UNICAST_RETRANS_INT_STEP` Kconfig option to set the +default value. This value is then used to calculate the interval step using the following formula: + +.. math:: + + (\mathtt{CONFIG\_BT\_MESH\_SAR\_TX\_UNICAST\_RETRANS\_INT\_STEP} + 1) \times 25~\text{ms} + + +SAR Unicast Retransmissions Interval Increment +---------------------------------------------- + +SAR Unicast Retransmissions Interval Increment holds a value that controls the interval increment +used for delaying the retransmissions of unacknowledged segments of a segmented message to a unicast +address. The increment is measured in milliseconds. + +Use the Kconfig option :kconfig:option:`CONFIG_BT_MESH_SAR_TX_UNICAST_RETRANS_INT_INC` to set the +default value. The Kconfig option value is used to calculate the increment using the following +formula: + +.. math:: + + (\mathtt{CONFIG\_BT\_MESH\_SAR\_TX\_UNICAST\_RETRANS\_INT\_INC} + 1) \times 25~\text{ms} + + +SAR Multicast Retransmissions Count +----------------------------------- + +The state holds a value that controls the total number of retransmissions of a segmented message to +a multicast address. Use the Kconfig option +:kconfig:option:`CONFIG_BT_MESH_SAR_TX_MULTICAST_RETRANS_COUNT` to set the total number of +retransmissions. + +SAR Multicast Retransmissions Interval Step +------------------------------------------- + +This state holds a value that controls the interval between retransmissions of all segments in a +segmented message to a multicast address. The interval is measured in milliseconds. + +Use the Kconfig option :kconfig:option:`CONFIG_BT_MESH_SAR_TX_MULTICAST_RETRANS_INT` to set the +default value that is used to calculate the interval using the following formula: + +.. math:: + + (\mathtt{CONFIG\_BT\_MESH\_SAR\_TX\_MULTICAST\_RETRANS\_INT} + 1) \times 25~\text{ms} + + +SAR Discard Timeout +------------------- + +The value of this state defines the time in seconds that the lower transport layer waits after +receiving segments of a segmented message before discarding that segmented message. Use the Kconfig +option :kconfig:option:`CONFIG_BT_MESH_SAR_RX_DISCARD_TIMEOUT` to set the default value. The discard +timeout will be calculated using the following formula: + +.. math:: + + (\mathtt{CONFIG\_BT\_MESH\_SAR\_RX\_DISCARD\_TIMEOUT} + 1) \times 5~\text{seconds} + + +SAR Acknowledgment Delay Increment +---------------------------------- + +This state holds a value that controls the delay increment of an interval used for delaying the +transmission of an acknowledgment message after receiving a new segment. The increment is measured +in segments. + +Use the Kconfig option :kconfig:option:`CONFIG_BT_MESH_SAR_RX_ACK_DELAY_INC` to set the default +value. The increment value is calculated to be +:math:`\verb|CONFIG_BT_MESH_SAR_RX_ACK_DELAY_INC| + 1.5`. + +SAR Segments Threshold +---------------------- + +SAR Segments Threshold state holds a value that defines a threshold in number of segments of a +segmented message for acknowledgment retransmissions. Use the Kconfig option +:kconfig:option:`CONFIG_BT_MESH_SAR_RX_SEG_THRESHOLD` to set the threshold. + +When the number of segments of a segmented message is above this threshold, the stack will +additionally retransmit every acknowledgment message the number of times given by the value of +:kconfig:option:`CONFIG_BT_MESH_SAR_RX_ACK_RETRANS_COUNT`. + +SAR Acknowledgment Retransmissions Count +---------------------------------------- + +The SAR Acknowledgment Retransmissions Count state controls the number of retransmissions of Segment +Acknowledgment messages sent by the lower transport layer. It gives the total number of +retranmissions of an acknowledgment message that the stack will additionally send when the size of +segments in a segmented message is above the :kconfig:option:`CONFIG_BT_MESH_SAR_RX_SEG_THRESHOLD` +value. + +Use the Kconfig option :kconfig:option:`CONFIG_BT_MESH_SAR_RX_ACK_RETRANS_COUNT` to set the default +value for this state. The maximum number of transmissions of a Segment Acknowledgment message is +:math:`\verb|CONFIG_BT_MESH_SAR_RX_ACK_RETRANS_COUNT| + 1`. + +SAR Receiver Segment Interval Step +---------------------------------- + +The SAR Receiver Segment Interval Step defines the segments reception interval step used for +delaying the transmission of an acknowledgment message after receiving a new segment. The interval +is measured in milliseconds. + +Use the Kconfig option :kconfig:option:`CONFIG_BT_MESH_SAR_RX_SEG_INT_STEP` to set the default value +and calculate the interval using the following formula: + +.. math:: + + (\mathtt{CONFIG\_BT\_MESH\_SAR\_RX\_SEG\_INT\_STEP} + 1) \times 10~\text{ms} diff --git a/doc/connectivity/bluetooth/api/mesh/sar_cfg_cli.rst b/doc/connectivity/bluetooth/api/mesh/sar_cfg_cli.rst new file mode 100644 index 00000000000..b017b53a01a --- /dev/null +++ b/doc/connectivity/bluetooth/api/mesh/sar_cfg_cli.rst @@ -0,0 +1,41 @@ +.. _bluetooth_mesh_sar_cfg_cli: + +SAR Configuration Client +######################## + +The SAR Configuration Client model is a foundation model defined by the Bluetooth mesh +specification. It is an optional model, enabled with the +:kconfig:option:`CONFIG_BT_MESH_SAR_CFG_CLI` configuration option. + +The SAR Configuration Client model is introduced in the Bluetooth Mesh Protocol Specification +version 1.1, and it supports the configuration of the lower transport layer behavior of a node that +supports the :ref:`bluetooth_mesh_sar_cfg_srv` model. + +The model can send messages to query or change the states supported by the SAR Configuration Server +(SAR Transmitter and SAR Receiver) using SAR Configuration messages. + +The SAR Transmitter procedure is used to determine and configure the SAR Transmitter state of a SAR +Configuration Server. Function calls :c:func:`bt_mesh_sar_cfg_cli_transmitter_get` and +:c:func:`bt_mesh_sar_cfg_cli_transmitter_set` are used to get and set the SAR Transmitter state +of the Target node respectively. + +The SAR Receiver procedure is used to determine and configure the SAR Receiver state of a SAR +Configuration Server. Function calls :c:func:`bt_mesh_sar_cfg_cli_receiver_get` and +:c:func:`bt_mesh_sar_cfg_cli_receiver_set` are used to get and set the SAR Receiver state of the +Target node respectively. + +For more information about the two states, see :ref:`bt_mesh_sar_cfg_states`. + +An element can send any SAR Configuration Client message at any time to query or change the states +supported by the SAR Configuration Server model of a peer node. The SAR Configuration Client model +only accepts messages encrypted with the device key of the node supporting the SAR Configuration +Server model. + +If present, the SAR Configuration Client model must only be instantiated on the primary element. + +API reference +************* + +.. doxygengroup:: bt_mesh_sar_cfg_cli + :project: Zephyr + :members: diff --git a/doc/connectivity/bluetooth/api/mesh/sar_cfg_srv.rst b/doc/connectivity/bluetooth/api/mesh/sar_cfg_srv.rst new file mode 100644 index 00000000000..2ea1446c9ea --- /dev/null +++ b/doc/connectivity/bluetooth/api/mesh/sar_cfg_srv.rst @@ -0,0 +1,31 @@ +.. _bluetooth_mesh_sar_cfg_srv: + +SAR Configuration Server +######################## + +The SAR Configuration Server model is a foundation model defined by the Bluetooth mesh +specification. It is an optional model, enabled with the +:kconfig:option:`CONFIG_BT_MESH_SAR_CFG_SRV` configuration option. + +The SAR Configuration Server model is introduced in the Bluetooth Mesh Protocol Specification +version 1.1, and it supports the configuration of the +:ref:`segmentation and reassembly (SAR) ` behavior of a Bluetooth mesh node. +The model defines a set of states and messages for the SAR configuration. + +The SAR Configuration Server model defines two states, SAR Transmitter state and SAR Receiver state. +For more information about the two states, see :ref:`bt_mesh_sar_cfg_states`. + +The model also supports the SAR Transmitter and SAR Receiver get and set messages. + +The SAR Configuration Server model does not have an API of its own, but relies on a +:ref:`bluetooth_mesh_sar_cfg_cli` to control it. The SAR Configuration Server model only accepts +messages encrypted with the node’s device key. + +If present, the SAR Configuration Server model must only be instantiated on the primary element. + +API reference +************* + +.. doxygengroup:: bt_mesh_sar_cfg_srv + :project: Zephyr + :members: diff --git a/doc/connectivity/bluetooth/api/mesh/shell.rst b/doc/connectivity/bluetooth/api/mesh/shell.rst index 6f102b5490f..66bfcdf6168 100644 --- a/doc/connectivity/bluetooth/api/mesh/shell.rst +++ b/doc/connectivity/bluetooth/api/mesh/shell.rst @@ -3,26 +3,32 @@ Bluetooth Mesh Shell #################### -The Bluetooth mesh shell subsystem provides a set of Bluetooth mesh shell commands for the :ref:`shell_api` module. -It allows for testing and exploring the Bluetooth mesh API through an interactive interface, without having to write an application. +The Bluetooth mesh shell subsystem provides a set of Bluetooth mesh shell commands for the +:ref:`shell_api` module. It allows for testing and exploring the Bluetooth mesh API through an +interactive interface, without having to write an application. -The Bluetooth mesh shell interface provides access to most Bluetooth mesh features, including provisioning, configuration, and message sending. +The Bluetooth mesh shell interface provides access to most Bluetooth mesh features, including +provisioning, configuration, and message sending. Prerequisites ************* -The Bluetooth mesh shell subsystem depends on the application to create the composition data and do the mesh initialization. +The Bluetooth mesh shell subsystem depends on the application to create the composition data and do +the mesh initialization. Application *********** -The Bluetooth mesh shell subsystem is most easily used through the Bluetooth mesh shell application under ``tests/bluetooth/mesh_shell``. -See :ref:`shell_api` for information on how to connect and interact with the Bluetooth mesh shell application. +The Bluetooth mesh shell subsystem is most easily used through the Bluetooth mesh shell application +under ``tests/bluetooth/mesh_shell``. See :ref:`shell_api` for information on how to connect and +interact with the Bluetooth mesh shell application. Basic usage *********** -The Bluetooth mesh shell subsystem adds a single ``mesh`` command, which holds a set of sub-commands. Every time the device boots up, make sure to call ``mesh init`` before any of the other Bluetooth mesh shell commands can be called:: +The Bluetooth mesh shell subsystem adds a single ``mesh`` command, which holds a set of +sub-commands. Every time the device boots up, make sure to call ``mesh init`` before any of the +other Bluetooth mesh shell commands can be called:: uart:~$ mesh init @@ -31,26 +37,36 @@ This is done to ensure that all available log will be printed to the shell outpu Provisioning ============ -The mesh node must be provisioned to become part of the network. This is only necessary the first time the device boots up, as the device will remember its provisioning data between reboots. +The mesh node must be provisioned to become part of the network. This is only necessary the first +time the device boots up, as the device will remember its provisioning data between reboots. -The simplest way to provision the device is through self-provisioning. To do this the user must provision the device with the default network key and address ``0x0001``, execute:: +The simplest way to provision the device is through self-provisioning. To do this the user must +provision the device with the default network key and address ``0x0001``, execute:: uart:~$ mesh prov local 0 0x0001 -Since all mesh nodes use the same values for the default network key, this can be done on multiple devices, as long as they're assigned non-overlapping unicast addresses. Alternatively, to provision the device into an existing network, the unprovisioned beacon can be enabled with ``mesh prov pb-adv on`` or ``mesh prov pb-gatt on``. The beacons can be picked up by an external provisioner, which can provision the node into its network. +Since all mesh nodes use the same values for the default network key, this can be done on multiple +devices, as long as they're assigned non-overlapping unicast addresses. Alternatively, to provision +the device into an existing network, the unprovisioned beacon can be enabled with +``mesh prov pb-adv on`` or ``mesh prov pb-gatt on``. The beacons can be picked up by an external +provisioner, which can provision the node into its network. -Once the mesh node is part of a network, its transmission parameters can be controlled by the general configuration commands: +Once the mesh node is part of a network, its transmission parameters can be controlled by the +general configuration commands: * To set the destination address, call ``mesh target dst ``. * To set the network key index, call ``mesh target net ``. * To set the application key index, call ``mesh target app ``. -By default, the transmission parameters are set to send messages to the provisioned address and network key. +By default, the transmission parameters are set to send messages to the provisioned address and +network key. Configuration ============= -By setting the destination address to the local unicast address (``0x0001`` in the ``mesh prov local`` command above), we can perform self-configuration through any of the :ref:`bluetooth_mesh_shell_cfg_cli` commands. +By setting the destination address to the local unicast address (``0x0001`` in the +``mesh prov local`` command above), we can perform self-configuration through any of the +:ref:`bluetooth_mesh_shell_cfg_cli` commands. A good first step is to read out the node's own composition data:: @@ -65,7 +81,8 @@ Next, since the device has no application keys by default, it's a good idea to a Message sending =============== -With an application key added (see above), the mesh node's transition parameters are all valid, and the Bluetooth mesh shell can send raw mesh messages through the network. +With an application key added (see above), the mesh node's transition parameters are all valid, and +the Bluetooth mesh shell can send raw mesh messages through the network. For example, to send a Generic OnOff Set message, call:: @@ -74,16 +91,26 @@ For example, to send a Generic OnOff Set message, call:: .. note:: All multibyte fields model messages are in little endian, except the opcode. -The message will be sent to the current destination address, using the current network and application key indexes. As the destination address points to the local unicast address by default, the device will only send packets to itself. To change the destination address to the All Nodes broadcast address, call:: +The message will be sent to the current destination address, using the current network and +application key indexes. As the destination address points to the local unicast address by default, +the device will only send packets to itself. To change the destination address to the All Nodes +broadcast address, call:: uart:~$ mesh target dst 0xffff -With the destination address set to ``0xffff``, any other mesh nodes in the network with the configured network and application keys will receive and process the messages we send. +With the destination address set to ``0xffff``, any other mesh nodes in the network with the +configured network and application keys will receive and process the messages we send. .. note:: - To change the configuration of the device, the destination address must be set back to the local unicast address before issuing any configuration commands. + To change the configuration of the device, the destination address must be set back to the + local unicast address before issuing any configuration commands. -Sending raw mesh packets is a good way to test model message handler implementations during development, as it can be done without having to implement the sending model. By default, only the reception of the model messages can be tested this way, as the Bluetooth mesh shell only includes the foundation models. To receive a packet in the mesh node, you have to add a model with a valid opcode handler list to the composition data in ``subsys/bluetooth/mesh/shell.c``, and print the incoming message to the shell in the handler callback. +Sending raw mesh packets is a good way to test model message handler implementations during +development, as it can be done without having to implement the sending model. By default, only the +reception of the model messages can be tested this way, as the Bluetooth mesh shell only includes +the foundation models. To receive a packet in the mesh node, you have to add a model with a valid +opcode handler list to the composition data in ``subsys/bluetooth/mesh/shell.c``, and print the +incoming message to the shell in the handler callback. Parameter formats ***************** @@ -98,10 +125,12 @@ The Bluetooth mesh shell commands are parsed with a variety of formats: - Description - Example * - Integers - - The default format unless something else is specified. Can be either decimal or hexadecimal. + - The default format unless something else is specified. Can be either decimal or + hexadecimal. - ``1234``, ``0xabcd01234`` * - Hexstrings - - For raw byte arrays, like UUIDs, key values and message payloads, the parameters should be formatted as an unbroken string of hexadecimal values without any prefix. + - For raw byte arrays, like UUIDs, key values and message payloads, the parameters should + be formatted as an unbroken string of hexadecimal values without any prefix. - ``deadbeef01234`` * - Booleans - Boolean values are denoted in the API documentation as ````. @@ -110,7 +139,10 @@ The Bluetooth mesh shell commands are parsed with a variety of formats: Commands ******** -The Bluetooth mesh shell implements a large set of commands. Some of the commands accept parameters, which are mentioned in brackets after the command name. For example, ``mesh lpn set ``. Mandatory parameters are marked with angle brackets (e.g. ````), and optional parameters are marked with square brackets (e.g. ``[DstAddr]``). +The Bluetooth mesh shell implements a large set of commands. Some of the commands accept parameters, +which are mentioned in brackets after the command name. For example, +``mesh lpn set ``. Mandatory parameters are marked with angle brackets (e.g. +````), and optional parameters are marked with square brackets (e.g. ``[DstAddr]``). The Bluetooth mesh shell commands are divided into the following groups: @@ -119,7 +151,9 @@ The Bluetooth mesh shell commands are divided into the following groups: :local: .. note:: - Some commands depend on specific features being enabled in the compile time configuration of the application. Not all features are enabled by default. The list of available Bluetooth mesh shell commands can be shown in the shell by calling ``mesh`` without any arguments. + Some commands depend on specific features being enabled in the compile time configuration of + the application. Not all features are enabled by default. The list of available Bluetooth + mesh shell commands can be shown in the shell by calling ``mesh`` without any arguments. General configuration ===================== @@ -132,17 +166,21 @@ General configuration ``mesh reset-local`` -------------------- - Reset the local mesh node to its initial unprovisioned state. This command will also clear the Configuration Database (CDB) if present. + Reset the local mesh node to its initial unprovisioned state. This command will also clear + the Configuration Database (CDB) if present. Target ====== -The target commands enables the user to monitor and set the target destination address, network index and application index for the shell. These parameters are used by several commands, like provisioning, Configuration Client, etc. +The target commands enables the user to monitor and set the target destination address, network +index and application index for the shell. These parameters are used by several commands, like +provisioning, Configuration Client, etc. ``mesh target dst [DstAddr]`` ----------------------------- - Get or set the message destination address. The destination address determines where mesh packets are sent with the shell, but has no effect on modules outside the shell's control. + Get or set the message destination address. The destination address determines where mesh + packets are sent with the shell, but has no effect on modules outside the shell's control. * ``DstAddr``: If present, sets the new 16-bit mesh destination address. If omitted, the current destination address is printed. @@ -150,7 +188,10 @@ The target commands enables the user to monitor and set the target destination a ``mesh target net [NetKeyIdx]`` ------------------------------- - Get or set the message network index. The network index determines which network key is used to encrypt mesh packets that are sent with the shell, but has no effect on modules outside the shell's control. The network key must already be added to the device, either through provisioning or by a Configuration Client. + Get or set the message network index. The network index determines which network key is used + to encrypt mesh packets that are sent with the shell, but has no effect on modules outside + the shell's control. The network key must already be added to the device, either through + provisioning or by a Configuration Client. * ``NetKeyIdx``: If present, sets the new network index. If omitted, the current network index is printed. @@ -158,24 +199,30 @@ The target commands enables the user to monitor and set the target destination a ``mesh target app [AppKeyIdx]`` ------------------------------- - Get or set the message application index. The application index determines which application key is used to encrypt mesh packets that are sent with the shell, but has no effect on modules outside the shell's control. The application key must already be added to the device by a Configuration Client, and must be bound to the current network index. + Get or set the message application index. The application index determines which application + key is used to encrypt mesh packets that are sent with the shell, but has no effect on + modules outside the shell's control. The application key must already be added to the device + by a Configuration Client, and must be bound to the current network index. * ``AppKeyIdx``: If present, sets the new application index. If omitted, the current application index is printed. + Low Power Node ============== ``mesh lpn set `` ------------------------------- - Enable or disable Low Power operation. Once enabled, the device will turn off its radio and start polling for friend nodes. + Enable or disable Low Power operation. Once enabled, the device will turn off its radio and + start polling for friend nodes. * ``Val``: Sets whether Low Power operation is enabled. ``mesh lpn poll`` ----------------- - Perform a poll to the friend node, to receive any pending messages. Only available when LPN is enabled. + Perform a poll to the friend node, to receive any pending messages. Only available when LPN + is enabled. Testing ======= @@ -183,7 +230,8 @@ Testing ``mesh test net-send `` ----------------------------------- - Send a raw mesh message with the current destination address, network and application index. The message opcode must be encoded manually. + Send a raw mesh message with the current destination address, network and application index. + The message opcode must be encoded manually. * ``HexString`` Raw hexadecimal representation of the message to send. @@ -208,7 +256,9 @@ Testing .. warning:: - Clearing the replay protection list breaks the security mechanisms of the mesh node, making it susceptible to message replay attacks. This should never be performed in a real deployment. + Clearing the replay protection list breaks the security mechanisms of the mesh node, making + it susceptible to message replay attacks. This should never be performed in a real + deployment. Health Server Test ------------------ @@ -231,42 +281,58 @@ Health Server Test Provisioning ============ -To allow a device to broadcast connectable unprovisioned beacons, the :kconfig:option:`CONFIG_BT_MESH_PROV_DEVICE` configuration option must be enabled, along with the :kconfig:option:`CONFIG_BT_MESH_PB_GATT` option. +To allow a device to broadcast connectable unprovisioned beacons, the +:kconfig:option:`CONFIG_BT_MESH_PROV_DEVICE` configuration option must be enabled, along with the +:kconfig:option:`CONFIG_BT_MESH_PB_GATT` option. ``mesh prov pb-gatt `` ------------------------------------ - Start or stop advertising a connectable unprovisioned beacon. The connectable unprovisioned beacon allows the mesh node to be discovered by nearby GATT based provisioners, and provisioned through the GATT bearer. + Start or stop advertising a connectable unprovisioned beacon. The connectable unprovisioned + beacon allows the mesh node to be discovered by nearby GATT based provisioners, and + provisioned through the GATT bearer. * ``Val``: Enable or disable provisioning with GATT -To allow a device to broadcast unprovisioned beacons, the :kconfig:option:`CONFIG_BT_MESH_PROV_DEVICE` configuration option must be enabled, along with the :kconfig:option:`CONFIG_BT_MESH_PB_ADV` option. +To allow a device to broadcast unprovisioned beacons, the +:kconfig:option:`CONFIG_BT_MESH_PROV_DEVICE` configuration option must be enabled, along with the +:kconfig:option:`CONFIG_BT_MESH_PB_ADV` option. ``mesh prov pb-adv `` ----------------------------------- - Start or stop advertising the unprovisioned beacon. The unprovisioned beacon allows the mesh node to be discovered by nearby advertising-based provisioners, and provisioned through the advertising bearer. + Start or stop advertising the unprovisioned beacon. The unprovisioned beacon allows the mesh + node to be discovered by nearby advertising-based provisioners, and provisioned through the + advertising bearer. * ``Val``: Enable or disable provisioning with advertiser -To allow a device to provision devices, the :kconfig:option:`CONFIG_BT_MESH_PROVISIONER` and :kconfig:option:`CONFIG_BT_MESH_PB_ADV` configuration options must be enabled. +To allow a device to provision devices, the :kconfig:option:`CONFIG_BT_MESH_PROVISIONER` and +:kconfig:option:`CONFIG_BT_MESH_PB_ADV` configuration options must be enabled. ``mesh prov remote-adv `` ----------------------------------------------------------------------------------- - Provision a nearby device into the mesh. The mesh node starts scanning for unprovisioned beacons with the given UUID. Once found, the unprovisioned device will be added to the mesh network with the given unicast address, and given the network key indicated by ``NetKeyIdx``. + Provision a nearby device into the mesh. The mesh node starts scanning for unprovisioned + beacons with the given UUID. Once found, the unprovisioned device will be added to the mesh + network with the given unicast address, and given the network key indicated by + ``NetKeyIdx``. * ``UUID``: UUID of the unprovisioned device. Providing a hex-string shorter than 16 bytes will populate the N most significant bytes of the array and zero-pad the rest. * ``NetKeyIdx``: Index of the network key to pass to the device. * ``Addr``: First unicast address to assign to the unprovisioned device. The device will occupy as many addresses as it has elements, and all must be available. * ``AttDur``: The duration in seconds the unprovisioned device will identify itself for, if supported. See :ref:`bluetooth_mesh_models_health_srv_attention` for details. -To allow a device to provision devices over GATT, the :kconfig:option:`CONFIG_BT_MESH_PROVISIONER` and :kconfig:option:`CONFIG_BT_MESH_PB_GATT_CLIENT` configuration options must be enabled. +To allow a device to provision devices over GATT, the :kconfig:option:`CONFIG_BT_MESH_PROVISIONER` +and :kconfig:option:`CONFIG_BT_MESH_PB_GATT_CLIENT` configuration options must be enabled. ``mesh prov remote-gatt `` ------------------------------------------------------------------------- - Provision a nearby device into the mesh. The mesh node starts scanning for connectable advertising for PB-GATT with the given UUID. Once found, the unprovisioned device will be added to the mesh network with the given unicast address, and given the network key indicated by ``NetKeyIdx``. + Provision a nearby device into the mesh. The mesh node starts scanning for connectable + advertising for PB-GATT with the given UUID. Once found, the unprovisioned device will be + added to the mesh network with the given unicast address, and given the network key + indicated by ``NetKeyIdx``. * ``UUID``: UUID of the unprovisioned device. Providing a hex-string shorter than 16 bytes will populate the N most significant bytes of the array and zero-pad the rest. * ``NetKeyIdx``: Index of the network key to pass to the device. @@ -278,13 +344,15 @@ To allow a device to provision devices over GATT, the :kconfig:option:`CONFIG_BT Get or set the mesh node's UUID, used in the unprovisioned beacons. - * ``UUID``: If present, new 128-bit UUID value. Providing a hex-string shorter than 16 bytes will populate the N most significant bytes of the array and zero-pad the rest. If omitted, the current UUID will be printed. To enable this command, the :kconfig:option:`BT_MESH_SHELL_PROV_CTX_INSTANCE` option must be enabled. + * ``UUID``: If present, new 128-bit UUID value. Providing a hex-string shorter than 16 bytes will populate the N most significant bytes of the array and zero-pad the rest. If omitted, the current UUID will be printed. To enable this command, the :kconfig:option:`CONFIG_BT_MESH_SHELL_PROV_CTX_INSTANCE` option must be enabled. ``mesh prov input-num `` -------------------------------- - Input a numeric OOB authentication value. Only valid when prompted by the shell during provisioning. The input number must match the number presented by the other participant in the provisioning. + Input a numeric OOB authentication value. Only valid when prompted by the shell during + provisioning. The input number must match the number presented by the other participant in + the provisioning. * ``Number``: Decimal authentication number. @@ -292,7 +360,9 @@ To allow a device to provision devices over GATT, the :kconfig:option:`CONFIG_BT ``mesh prov input-str `` -------------------------------- - Input an alphanumeric OOB authentication value. Only valid when prompted by the shell during provisioning. The input string must match the string presented by the other participant in the provisioning. + Input an alphanumeric OOB authentication value. Only valid when prompted by the shell during + provisioning. The input string must match the string presented by the other participant in + the provisioning. * ``String``: Unquoted alphanumeric authentication string. @@ -300,7 +370,10 @@ To allow a device to provision devices over GATT, the :kconfig:option:`CONFIG_BT ``mesh prov static-oob [Val(1-32 hex)]`` ---------------------------------------- - Set or clear the static OOB authentication value. The static OOB authentication value must be set before provisioning starts to have any effect. The static OOB value must be same on both participants in the provisioning. To enable this command, the :kconfig:option:`BT_MESH_SHELL_PROV_CTX_INSTANCE` option must be enabled. + Set or clear the static OOB authentication value. The static OOB authentication value must + be set before provisioning starts to have any effect. The static OOB value must be same on + both participants in the provisioning. To enable this command, the + :kconfig:option:`CONFIG_BT_MESH_SHELL_PROV_CTX_INSTANCE` option must be enabled. * ``Val``: If present, indicates the new hexadecimal value of the static OOB. Providing a hex-string shorter than 16 bytes will populate the N most significant bytes of the array and zero-pad the rest. If omitted, the static OOB value is cleared. @@ -308,7 +381,8 @@ To allow a device to provision devices over GATT, the :kconfig:option:`CONFIG_BT ``mesh prov local [IVI]`` -------------------------------------------- - Provision the mesh node itself. If the Configuration database is enabled, the network key must be created. Otherwise, the default key value is used. + Provision the mesh node itself. If the Configuration database is enabled, the network key + must be created. Otherwise, the default key value is used. * ``NetKeyIdx``: Index of the network key to provision. * ``Addr``: First unicast address to assign to the device. The device will occupy as many addresses as it has elements, and all must be available. @@ -318,7 +392,9 @@ To allow a device to provision devices over GATT, the :kconfig:option:`CONFIG_BT ``mesh prov beacon-listen `` ------------------------------------------ - Enable or disable printing of incoming unprovisioned beacons. Allows a provisioner device to detect nearby unprovisioned devices and provision them. To enable this command, the :kconfig:option:`BT_MESH_SHELL_PROV_CTX_INSTANCE` option must be enabled. + Enable or disable printing of incoming unprovisioned beacons. Allows a provisioner device to + detect nearby unprovisioned devices and provision them. To enable this command, the + :kconfig:option:`CONFIG_BT_MESH_SHELL_PROV_CTX_INSTANCE` option must be enabled. * ``Val``: Whether to enable the unprovisioned beacon printing. @@ -330,7 +406,8 @@ To allow a device to provision devices over GATT, the :kconfig:option:`CONFIG_BT ``mesh prov auth-method input `` ----------------------------------------------- - From the provisioner device, instruct the unprovisioned device to use the specified Input OOB authentication action. + From the provisioner device, instruct the unprovisioned device to use the specified Input + OOB authentication action. * ``Action`` - Input action. Allowed values: @@ -343,7 +420,8 @@ To allow a device to provision devices over GATT, the :kconfig:option:`CONFIG_BT ``mesh prov auth-method output `` ------------------------------------------------ - From the provisioner device, instruct the unprovisioned device to use the specified Output OOB authentication action. + From the provisioner device, instruct the unprovisioned device to use the specified Output + OOB authentication action. * ``Action`` - Output action. Allowed values: @@ -356,25 +434,30 @@ To allow a device to provision devices over GATT, the :kconfig:option:`CONFIG_BT ``mesh prov auth-method static `` ------------------------------------------------ - From the provisioner device, instruct the unprovisioned device to use static OOB authentication, and use the given static authentication value when provisioning. + From the provisioner device, instruct the unprovisioned device to use static OOB + authentication, and use the given static authentication value when provisioning. * ``Val`` - Static OOB value. Providing a hex-string shorter than 32 bytes will populate the N most significant bytes of the array and zero-pad the rest. ``mesh prov auth-method none`` ------------------------------ - From the provisioner device, don't use any authentication when provisioning new devices. This is the default behavior. + From the provisioner device, don't use any authentication when provisioning new devices. + This is the default behavior. Proxy ===== -The Proxy Server module is an optional mesh subsystem that can be enabled through the :kconfig:option:`CONFIG_BT_MESH_GATT_PROXY` configuration option. +The Proxy Server module is an optional mesh subsystem that can be enabled through the +:kconfig:option:`CONFIG_BT_MESH_GATT_PROXY` configuration option. ``mesh proxy identity-enable`` ------------------------------ - Enable the Proxy Node Identity beacon, allowing Proxy devices to connect explicitly to this device. The beacon will run for 60 seconds before the node returns to normal Proxy beacons. + Enable the Proxy Node Identity beacon, allowing Proxy devices to connect explicitly to this + device. The beacon will run for 60 seconds before the node returns to normal Proxy beacons. -The Proxy Client module is an optional mesh subsystem that can be enabled through the :kconfig:option:`CONFIG_BT_MESH_PROXY_CLIENT` configuration option. +The Proxy Client module is an optional mesh subsystem that can be enabled through the +:kconfig:option:`CONFIG_BT_MESH_PROXY_CLIENT` configuration option. ``mesh proxy connect `` ---------------------------------- @@ -395,7 +478,8 @@ The Proxy Client module is an optional mesh subsystem that can be enabled throug ``mesh proxy solicit `` ---------------------------------- - Begin Proxy Solicitation of a subnet. Support of this feature can be enabled through the :kconfig:option:`CONFIG_BT_MESH_PROXY_SOLICITATION` configuration option. + Begin Proxy Solicitation of a subnet. Support of this feature can be enabled through the + :kconfig:option:`CONFIG_BT_MESH_PROXY_SOLICITATION` configuration option. * ``NetKeyIdx``: Index of the network key to send Solicitation PDUs to. @@ -407,9 +491,24 @@ Models Configuration Client -------------------- -The Configuration Client model is an optional mesh subsystem that can be enabled through the :kconfig:option:`CONFIG_BT_MESH_CFG_CLI` configuration option. This is implemented as a separate module (``mesh models cfg``) inside the ``mesh models`` subcommand list. This module will work on any instance of the Configuration Client model if the mentioned shell configuration options is enabled, and as long as the Configuration Client model is present in the model composition of the application. This shell module can be used for configuring itself and other nodes in the mesh network. - -The Configuration Client uses general message parameters set by ``mesh target dst`` and ``mesh target net`` to target specific nodes. When the Bluetooth mesh shell node is provisioned, given that the :kconfig:option:`BT_MESH_SHELL_PROV_CTX_INSTANCE` option is enabled with the shell provisioning context initialized, the Configuration Client model targets itself by default. Similarly, when another node has been provisioned by the Bluetooth mesh shell, the Configuration Client model targets the new node. In most common use-cases, the Configuration Client is depending on the provisioning features and the Configuration database to be fully functional. The Configuration Client always sends messages using the Device key bound to the destination address, so it will only be able to configure itself and the mesh nodes it provisioned. The following steps are an example of how you can set up a device to start using the Configuration Client commands: +The Configuration Client model is an optional mesh subsystem that can be enabled through the +:kconfig:option:`CONFIG_BT_MESH_CFG_CLI` configuration option. This is implemented as a separate +module (``mesh models cfg``) inside the ``mesh models`` subcommand list. This module will work on +any instance of the Configuration Client model if the mentioned shell configuration options is +enabled, and as long as the Configuration Client model is present in the model composition of the +application. This shell module can be used for configuring itself and other nodes in the mesh +network. + +The Configuration Client uses general message parameters set by ``mesh target dst`` and ``mesh +target net`` to target specific nodes. When the Bluetooth mesh shell node is provisioned, given that +the :kconfig:option:`CONFIG_BT_MESH_SHELL_PROV_CTX_INSTANCE` option is enabled with the shell +provisioning context initialized, the Configuration Client model targets itself by default. +Similarly, when another node has been provisioned by the Bluetooth mesh shell, the Configuration +Client model targets the new node. In most common use-cases, the Configuration Client is depending +on the provisioning features and the Configuration database to be fully functional. The +Configuration Client always sends messages using the Device key bound to the destination address, so +it will only be able to configure itself and the mesh nodes it provisioned. The following steps are +an example of how you can set up a device to start using the Configuration Client commands: * Initialize the client node (``mesh init``). * Create the CDB (``mesh cdb create``). @@ -417,7 +516,8 @@ The Configuration Client uses general message parameters set by ``mesh target ds * The shell module should now target itself. * Monitor the composition data of the local node (``mesh models cfg get-comp``). * Configure the local node as desired with the Configuration Client commands. -* Provision other devices (``mesh prov beacon-listen``) (``mesh prov remote-adv``) (``mesh prov remote-gatt``). +* Provision other devices (``mesh prov beacon-listen``) (``mesh prov remote-adv``) + (``mesh prov remote-gatt``). * The shell module should now target the newly added node. * Monitor the newly provisioned nodes and their addresses (``mesh cdb show``). * Monitor the composition data of the target device (``mesh models cfg get-comp``). @@ -449,7 +549,8 @@ The Configuration Client uses general message parameters set by ``mesh target ds ``mesh models cfg get-comp [Page]`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Read a composition data page. The full composition data page will be printed. If the target does not have the given page, it will return the last page before it. + Read a composition data page. The full composition data page will be printed. If the target + does not have the given page, it will return the last page before it. * ``Page``: The composition data page to request. Defaults to 0 if omitted. @@ -506,7 +607,7 @@ The Configuration Client uses general message parameters set by ``mesh target ds * ``0x02``: The feature is not supported. * ``Count``: Sets the new relay retransmit count if ``val`` is ``on``. Ignored if ``val`` is ``off``. Legal retransmit count is 0-7. Defaults to ``2`` if omitted. - * ``Int``: Sets the new relay retransmit interval in milliseconds if ``val`` is ``on``. Legal interval range is 10-320 milliseconds. Ignored if ``val`` is ``off``. Defaults to ``20`` if omitted. + * ``Int``: Sets the new relay retransmit interval in milliseconds if ``val`` is ``on``. Legal interval range is 10-320 milliseconds. Ignored if ``val`` is ``off``. Defaults to ``20`` if omitted. ``mesh models cfg node-id [Identity]`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -566,7 +667,8 @@ The Configuration Client uses general message parameters set by ``mesh target ds ``mesh models cfg appkey add [Key(1-16 hex)]`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Add an application key to the target node. Adds the key to the Configuration Database if enabled. + Add an application key to the target node. Adds the key to the Configuration Database if + enabled. * ``NetKeyIdx``: The network key index the application key is bound to. * ``AppKeyIdx``: The application key index to add. @@ -601,7 +703,8 @@ The Configuration Client uses general message parameters set by ``mesh target ds ``mesh models cfg model app-bind [CID]`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Bind an application key to a model. Models can only encrypt and decrypt messages sent with application keys they are bound to. + Bind an application key to a model. Models can only encrypt and decrypt messages sent with + application keys they are bound to. * ``Addr``: Address of the element the model is on. * ``AppKeyIdx``: The application key to bind to the model. @@ -633,8 +736,9 @@ The Configuration Client uses general message parameters set by ``mesh target ds ``mesh models cfg model pub [CID] [ ]`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Get or set the publication parameters of a model. If all publication parameters are included, they become the new publication parameters of the model. - If all publication parameters are omitted, print the current publication parameters of the model. + Get or set the publication parameters of a model. If all publication parameters are + included, they become the new publication parameters of the model. If all publication + parameters are omitted, print the current publication parameters of the model. * ``Addr``: Address of the element the model is on. * ``MID``: The model ID of the model to get the bound keys of. @@ -685,7 +789,9 @@ The Configuration Client uses general message parameters set by ``mesh target ds ``mesh models cfg model sub-add [CID]`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Subscription the model to a group address. Models only receive messages sent to their unicast address or a group or virtual address they subscribe to. Models may subscribe to multiple group and virtual addresses. + Subscription the model to a group address. Models only receive messages sent to their + unicast address or a group or virtual address they subscribe to. Models may subscribe to + multiple group and virtual addresses. * ``ElemAddr``: Address of the element the model is on. * ``SubAddr``: 16-bit group address the model should subscribe to (``0xc000`` to ``0xFEFF``). @@ -707,7 +813,9 @@ The Configuration Client uses general message parameters set by ``mesh target ds ``mesh models cfg model sub-add-va [CID]`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Subscribe the model to a virtual address. Models only receive messages sent to their unicast address or a group or virtual address they subscribe to. Models may subscribe to multiple group and virtual addresses. + Subscribe the model to a virtual address. Models only receive messages sent to their unicast + address or a group or virtual address they subscribe to. Models may subscribe to multiple + group and virtual addresses. * ``ElemAddr``: Address of the element the model is on. * ``LabelUUID``: 128-bit label UUID of the virtual address to subscribe to. Providing a hex-string shorter than 16 bytes will populate the N most significant bytes of the array and zero-pad the rest. @@ -721,7 +829,7 @@ The Configuration Client uses general message parameters set by ``mesh target ds Unsubscribe a model from a virtual address. * ``ElemAddr``: Address of the element the model is on. - * ``LabelUUID``: 128-bit label UUID of the virtual address to remove the subscription of. Providing a hex-string shorter than 16 bytes will populate the N most significant bytes of the array and zero-pad the rest. + * ``LabelUUID``: 128-bit label UUID of the virtual address to remove the subscription of. Providing a hex-string shorter than 16 bytes will populate the N most significant bytes of the array and zero-pad the rest. * ``MID``: The model ID of the model to add the subscription to. * ``CID``: If present, determines the Company ID of the model. If omitted, the model is a Bluetooth SIG defined model. @@ -738,7 +846,9 @@ The Configuration Client uses general message parameters set by ``mesh target ds ``mesh models cfg model sub-ow-va [CID]`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Overwrite all model subscriptions with a single new virtual address. Models only receive messages sent to their unicast address or a group or virtual address they subscribe to. Models may subscribe to multiple group and virtual addresses. + Overwrite all model subscriptions with a single new virtual address. Models only receive + messages sent to their unicast address or a group or virtual address they subscribe to. + Models may subscribe to multiple group and virtual addresses. * ``ElemAddr``: Address of the element the model is on. * ``LabelUUID``: 128-bit label UUID of the virtual address as the new Address to be added to the subscription list. Providing a hex-string shorter than 16 bytes will populate the N most significant bytes of the array and zero-pad the rest. @@ -779,7 +889,10 @@ The Configuration Client uses general message parameters set by ``mesh target ds ``mesh models cfg hb-sub [ ]`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Get or set the Heartbeat subscription parameters. A node only receives Heartbeat messages matching the Heartbeat subscription parameters. Sets the Heartbeat subscription parameters if present, or prints the current Heartbeat subscription parameters if called with no parameters. + Get or set the Heartbeat subscription parameters. A node only receives Heartbeat messages + matching the Heartbeat subscription parameters. Sets the Heartbeat subscription parameters + if present, or prints the current Heartbeat subscription parameters if called with no + parameters. * ``Src``: Unicast source address to receive Heartbeat messages from. * ``Dst``: Destination address to receive Heartbeat messages on. @@ -792,7 +905,9 @@ The Configuration Client uses general message parameters set by ``mesh target ds ``mesh models cfg hb-pub [ ]`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Get or set the Heartbeat publication parameters. Sets the Heartbeat publication parameters if present, or prints the current Heartbeat publication parameters if called with no parameters. + Get or set the Heartbeat publication parameters. Sets the Heartbeat publication parameters + if present, or prints the current Heartbeat publication parameters if called with no + parameters. * ``Dst``: Destination address to publish Heartbeat messages to. * ``Count``: Logarithmic representation of the number of Heartbeat messages to publish periodically: @@ -820,11 +935,22 @@ The Configuration Client uses general message parameters set by ``mesh target ds Health Client ------------- -The Health Client model is an optional mesh subsystem that can be enabled through the :kconfig:option:`CONFIG_BT_MESH_HEALTH_CLI` configuration option. This is implemented as a separate module (``mesh models health``) inside the ``mesh models`` subcommand list. This module will work on any instance of the Health Client model if the mentioned shell configuration options is enabled, and as long as one or more Health Client model(s) is present in the model composition of the application. This shell module can be used to trigger interaction between Health Clients and Servers on devices in a Mesh network. +The Health Client model is an optional mesh subsystem that can be enabled through the +:kconfig:option:`CONFIG_BT_MESH_HEALTH_CLI` configuration option. This is implemented as a separate +module (``mesh models health``) inside the ``mesh models`` subcommand list. This module will work on +any instance of the Health Client model if the mentioned shell configuration options is enabled, and +as long as one or more Health Client model(s) is present in the model composition of the +application. This shell module can be used to trigger interaction between Health Clients and Servers +on devices in a Mesh network. -By default, the module will choose the first Health Client instance in the model composition when using the Health Client commands. To choose a spesific Health Client instance the user can utilize the commands ``mesh models health instance set`` and ``mesh models health instance get-all``. +By default, the module will choose the first Health Client instance in the model composition when +using the Health Client commands. To choose a spesific Health Client instance the user can utilize +the commands ``mesh models health instance set`` and ``mesh models health instance get-all``. -The Health Client may use the general messages parameters set by ``mesh target dst``, ``mesh target net`` and ``mesh target app`` to target specific nodes. If the shell target destination address is set to zero, the targeted Health Client will attempt to publish messages using its configured publication parameters. +The Health Client may use the general messages parameters set by ``mesh target dst``, +``mesh target net`` and ``mesh target app`` to target specific nodes. If the shell target +destination address is set to zero, the targeted Health Client will attempt to publish messages +using its configured publication parameters. ``mesh models health instance set `` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -889,7 +1015,10 @@ The Health Client may use the general messages parameters set by ``mesh target d ``mesh models health period-set `` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Set the current Health Server publish period divisor. When a fault is detected, the Health Server will start publishing is fault status with a reduced interval. The reduced interval is determined by the Health Server publish period divisor: Fault publish period = Publish period / 2\ :sup:`divisor`. + Set the current Health Server publish period divisor. When a fault is detected, the Health + Server will start publishing is fault status with a reduced interval. The reduced interval + is determined by the Health Server publish period divisor: Fault publish period = Publish + period / 2\ :sup:`divisor`. * ``Divisor``: The new Health Server publish period divisor. @@ -897,7 +1026,10 @@ The Health Client may use the general messages parameters set by ``mesh target d ``mesh models health period-set-unack `` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Set the current Health Server publish period divisor. When a fault is detected, the Health Server will start publishing is fault status with a reduced interval. The reduced interval is determined by the Health Server publish period divisor: Fault publish period = Publish period / 2\ :sup:`divisor`. + Set the current Health Server publish period divisor. When a fault is detected, the Health + Server will start publishing is fault status with a reduced interval. The reduced interval + is determined by the Health Server publish period divisor: Fault publish period = Publish + period / 2\ :sup:`divisor`. * ``Divisor``: The new Health Server publish period divisor. @@ -927,7 +1059,9 @@ The Health Client may use the general messages parameters set by ``mesh target d Binary Large Object (BLOB) Transfer Client model ------------------------------------------------ -The :ref:`bluetooth_mesh_blob_cli` can be added to the mesh shell by enabling the :kconfig:option:`CONFIG_BT_MESH_BLOB_CLI` option, and disabling the :kconfig:option:`CONFIG_BT_MESH_DFU_CLI` option. +The :ref:`bluetooth_mesh_blob_cli` can be added to the mesh shell by enabling the +:kconfig:option:`CONFIG_BT_MESH_BLOB_CLI` option, and disabling the +:kconfig:option:`CONFIG_BT_MESH_DFU_CLI` option. ``mesh models blob cli target `` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -948,11 +1082,14 @@ The :ref:`bluetooth_mesh_blob_cli` can be added to the mesh shell by enabling th ``mesh models blob cli tx [ []]`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Perform a BLOB transfer to Target nodes. The BLOB Transfer Client will send a dummy BLOB to all Target nodes, then post a message when the transfer is completed. Note that all Target nodes must first be configured to receive the transfer using the ``mesh models blob srv rx`` command. + Perform a BLOB transfer to Target nodes. The BLOB Transfer Client will send a dummy BLOB to + all Target nodes, then post a message when the transfer is completed. Note that all Target + nodes must first be configured to receive the transfer using the ``mesh models blob srv rx`` + command. * ``Id``: 64-bit BLOB transfer ID. * ``Size``: Size of the BLOB in bytes. - * ``BlockSizeLog`` Logarithmic representation of the BLOB's block size. The final block size will be ``1 << block size log`` bytes. + * ``BlockSizeLog``: Logarithmic representation of the BLOB's block size. The final block size will be ``1 << block size log`` bytes. * ``ChunkSize``: Chunk size in bytes. * ``Group``: Optional group address to use when communicating with Target nodes. If omitted or set to 0, the BLOB Transfer Client will address each Target node individually. * ``Mode``: BLOB transfer mode to use. Must be either ``push`` (Push BLOB Transfer Mode) or ``pull`` (Pull BLOB Transfer Mode). If omitted, ``push`` will be used by default. @@ -966,7 +1103,8 @@ The :ref:`bluetooth_mesh_blob_cli` can be added to the mesh shell by enabling th ``mesh models blob cli tx-get [Group]`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Determine the progress of a previously running BLOB transfer. Can be used when not performing a BLOB transfer. + Determine the progress of a previously running BLOB transfer. Can be used when not + performing a BLOB transfer. * ``Group``: Optional group address to use when communicating with Target nodes. If omitted or set to 0, the BLOB Transfer Client will address each Target node individually. @@ -985,7 +1123,8 @@ The :ref:`bluetooth_mesh_blob_cli` can be added to the mesh shell by enabling th ``mesh models blob cli instance-set `` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Use the BLOB Transfer Client model instance on the specified element when using the other BLOB Transfer Client model commands. + Use the BLOB Transfer Client model instance on the specified element when using the other + BLOB Transfer Client model commands. * ``ElemIdx``: The element on which to find the BLOB Transfer Client model instance to use. @@ -998,7 +1137,9 @@ The :ref:`bluetooth_mesh_blob_cli` can be added to the mesh shell by enabling th BLOB Transfer Server model -------------------------- -The :ref:`bluetooth_mesh_blob_srv` can be added to the mesh shell by enabling the :kconfig:option:`CONFIG_BT_MESH_BLOB_SRV` option. The BLOB Transfer Server model is capable of receiving any BLOB data, but the implementation in the mesh shell will discard the incoming data. +The :ref:`bluetooth_mesh_blob_srv` can be added to the mesh shell by enabling the +:kconfig:option:`CONFIG_BT_MESH_BLOB_SRV` option. The BLOB Transfer Server model is capable of +receiving any BLOB data, but the implementation in the mesh shell will discard the incoming data. ``mesh models blob srv rx []`` @@ -1018,7 +1159,8 @@ The :ref:`bluetooth_mesh_blob_srv` can be added to the mesh shell by enabling th ``mesh models blob srv instance-set `` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Use the BLOB Transfer Server model instance on the specified element when using the other BLOB Transfer Server model commands. + Use the BLOB Transfer Server model instance on the specified element when using the other + BLOB Transfer Server model commands. * ``ElemIdx``: The element on which to find the BLOB Transfer Server model instance to use. @@ -1031,13 +1173,19 @@ The :ref:`bluetooth_mesh_blob_srv` can be added to the mesh shell by enabling th Firmware Update Client model ---------------------------- -The Firmware Update Client model can be added to the mesh shell by enabling configuration options :kconfig:option:`CONFIG_BT_MESH_BLOB_CLI` and :kconfig:option:`CONFIG_BT_MESH_DFU_CLI`. The Firmware Update Client demonstrates the firmware update Distributor role by transferring a dummy firmware update to a set of Target nodes. +The Firmware Update Client model can be added to the mesh shell by enabling configuration options +:kconfig:option:`CONFIG_BT_MESH_BLOB_CLI` and :kconfig:option:`CONFIG_BT_MESH_DFU_CLI`. The Firmware +Update Client demonstrates the firmware update Distributor role by transferring a dummy firmware +update to a set of Target nodes. ``mesh models dfu slot add []`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Add a virtual DFU image slot that can be transferred as a DFU image. The image slot will be assigned an image slot index, which is printed as a response, and can be used to reference the slot in other commands. To update the image slot, remove it using the ``mesh models dfu slot del`` shell command and then add it again. + Add a virtual DFU image slot that can be transferred as a DFU image. The image slot will be + assigned an image slot index, which is printed as a response, and can be used to reference + the slot in other commands. To update the image slot, remove it using the + ``mesh models dfu slot del`` shell command and then add it again. * ``Size``: DFU image slot size in bytes. * ``FwID``: Firmware ID, formatted as a hexstring. @@ -1086,7 +1234,9 @@ The Firmware Update Client model can be added to the mesh shell by enabling conf ``mesh models dfu cli target-check `` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Check whether the device at the configured destination address will accept a DFU transfer from the given DFU image slot to the Target node's DFU image at the given index, and what the effect would be. + Check whether the device at the configured destination address will accept a DFU transfer + from the given DFU image slot to the Target node's DFU image at the given index, and what + the effect would be. * ``SlotIdx``: Index of the local DFU image slot to check. * ``TargetImgIdx``: Index of the Target node's DFU image to check. @@ -1104,9 +1254,10 @@ The Firmware Update Client model can be added to the mesh shell by enabling conf ``mesh models dfu cli cancel []`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Cancel the DFU procedure at any state on a specific Target node or on all Target nodes. - When a Target node address is provided, the Firmware Update Client model will try to cancel the DFU procedure on the provided Target node. - Otherwise, the Firmware Update Client model will try to cancel the ongoing DFU procedure on all Target nodes. + Cancel the DFU procedure at any state on a specific Target node or on all Target nodes. When + a Target node address is provided, the Firmware Update Client model will try to cancel the + DFU procedure on the provided Target node. Otherwise, the Firmware Update Client model will + try to cancel the ongoing DFU procedure on all Target nodes. * ``Addr``: Optional unicast address of a Target node on which to cancel the DFU procedure. @@ -1114,13 +1265,15 @@ The Firmware Update Client model can be added to the mesh shell by enabling conf ``mesh models dfu cli apply`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Apply the most recent DFU transfer on all Target nodes. Can only be called after a DFU transfer is completed. + Apply the most recent DFU transfer on all Target nodes. Can only be called after a DFU + transfer is completed. ``mesh models dfu cli confirm`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Confirm that the most recent DFU transfer was successfully applied on all Target nodes. Can only be called after a DFU transfer is completed and applied. + Confirm that the most recent DFU transfer was successfully applied on all Target nodes. Can + only be called after a DFU transfer is completed and applied. ``mesh models dfu cli suspend`` @@ -1144,7 +1297,8 @@ The Firmware Update Client model can be added to the mesh shell by enabling conf ``mesh models dfu cli instance-set `` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Use the Firmware Update Client model instance on the specified element when using the other Firmware Update Client model commands. + Use the Firmware Update Client model instance on the specified element when using the other + Firmware Update Client model commands. * ``ElemIdx``: The element on which to find the Firmware Update Client model instance to use. @@ -1157,15 +1311,22 @@ The Firmware Update Client model can be added to the mesh shell by enabling conf Firmware Update Server model ---------------------------- -The Firmware Update Server model can be added to the mesh shell by enabling configuration options :kconfig:option:`CONFIG_BT_MESH_BLOB_SRV` and :kconfig:option:`CONFIG_BT_MESH_DFU_SRV`. The Firmware Update Server demonstrates the firmware update Target role by accepting any firmware update. The mesh shell Firmware Update Server will discard the incoming firmware data, but otherwise behave as a proper firmware update Target node. +The Firmware Update Server model can be added to the mesh shell by enabling configuration options +:kconfig:option:`CONFIG_BT_MESH_BLOB_SRV` and :kconfig:option:`CONFIG_BT_MESH_DFU_SRV`. The Firmware +Update Server demonstrates the firmware update Target role by accepting any firmware update. The +mesh shell Firmware Update Server will discard the incoming firmware data, but otherwise behave as a +proper firmware update Target node. ``mesh models dfu srv applied`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Mark the most recent DFU transfer as applied. Can only be called after a DFU transfer is completed, and the Distributor has requested that the transfer is applied. + Mark the most recent DFU transfer as applied. Can only be called after a DFU transfer is + completed, and the Distributor has requested that the transfer is applied. - As the mesh shell Firmware Update Server doesn't actually apply the incoming firmware image, this command can be used to emulate an applied status, to notify the Distributor that the transfer was successful. + As the mesh shell Firmware Update Server doesn't actually apply the incoming firmware image, + this command can be used to emulate an applied status, to notify the Distributor that the + transfer was successful. ``mesh models dfu srv progress`` @@ -1181,7 +1342,8 @@ The Firmware Update Server model can be added to the mesh shell by enabling conf ``mesh models dfu srv instance-set `` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Use the Firmware Update Server model instance on the specified element when using the other Firmware Update Server model commands. + Use the Firmware Update Server model instance on the specified element when using the other + Firmware Update Server model commands. * ``ElemIdx``: The element on which to find the Firmware Update Server model instance to use. @@ -1196,17 +1358,19 @@ The Firmware Update Server model can be added to the mesh shell by enabling conf Firmware Distribution Server model ---------------------------------- -The Firmware Distribution Server model commands can be added to the mesh shell by enabling the :kconfig:option:`CONFIG_BT_MESH_DFD_SRV` configuration option. -The shell commands for this model mirror the messages sent to the server by a Firmware Distribution Client model. -To use these commands, a Firmware Distribution Server must be instantiated by the application. +The Firmware Distribution Server model commands can be added to the mesh shell by enabling the +:kconfig:option:`CONFIG_BT_MESH_DFD_SRV` configuration option. The shell commands for this model +mirror the messages sent to the server by a Firmware Distribution Client model. To use these +commands, a Firmware Distribution Server must be instantiated by the application. ``mesh models dfd receivers-add ,[;,]...`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Add receivers to the Firmware Distribution Server. - Supply receivers as a list of comma-separated addr,fw_idx pairs, separated by semicolons, for example, ``0x0001,0;0x0002,0;0x0004,1``. - Do not use spaces in the receiver list. - Repeated calls to this command will continue populating the receivers list until ``mesh models dfd receivers-delete-all`` is called. + Add receivers to the Firmware Distribution Server. Supply receivers as a list of + comma-separated addr,fw_idx pairs, separated by semicolons, for example, + ``0x0001,0;0x0002,0;0x0004,1``. Do not use spaces in the receiver list. Repeated calls to + this command will continue populating the receivers list until + ``mesh models dfd receivers-delete-all`` is called. * ``Addr``: Address of the receiving node(s). * ``FwIdx``: Index of the firmware slot to send to ``Addr``. @@ -1291,7 +1455,8 @@ To use these commands, a Firmware Distribution Server must be instantiated by th ``mesh models dfd instance-set `` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Use the Firmware Distribution Server model instance on the specified element when using the other Firmware Distribution Server model commands. + Use the Firmware Distribution Server model instance on the specified element when using the + other Firmware Distribution Server model commands. * ``ElemIdx``: The element on which to find the Firmware Distribution Server model instance to use. @@ -1306,7 +1471,9 @@ To use these commands, a Firmware Distribution Server must be instantiated by th DFU metadata ------------ -The DFU metadata commands allow generating metadata that can be used by a Target node to check the firmware before accepting it. The commands are enabled through the :kconfig:option:`CONFIG_BT_MESH_DFU_METADATA` configuration option. +The DFU metadata commands allow generating metadata that can be used by a Target node to check the +firmware before accepting it. The commands are enabled through the +:kconfig:option:`CONFIG_BT_MESH_DFU_METADATA` configuration option. ``mesh models dfu metadata comp-clear`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1370,7 +1537,10 @@ The DFU metadata commands allow generating metadata that can be used by a Target Segmentation and Reassembly (SAR) Configuration Client ------------------------------------------------------ -The SAR Configuration client is an optional mesh model that can be enabled through the :kconfig:option:`CONFIG_BT_MESH_SAR_CFG_CLI` configuration option. The SAR Configuration Client model is used to support the functionality of configuring the behavior of the lower transport layer of a node that supports the SAR Configuration Server model. +The SAR Configuration client is an optional mesh model that can be enabled through the +:kconfig:option:`CONFIG_BT_MESH_SAR_CFG_CLI` configuration option. The SAR Configuration Client +model is used to support the functionality of configuring the behavior of the lower transport layer +of a node that supports the SAR Configuration Server model. ``mesh models sar tx-get`` @@ -1411,7 +1581,8 @@ The SAR Configuration client is an optional mesh model that can be enabled throu Private Beacon Client --------------------- -The Private Beacon Client model is an optional mesh subsystem that can be enabled through the :kconfig:option:`CONFIG_BT_MESH_PRIV_BEACON_CLI` configuration option. +The Private Beacon Client model is an optional mesh subsystem that can be enabled through the +:kconfig:option:`CONFIG_BT_MESH_PRIV_BEACON_CLI` configuration option. ``mesh models prb priv-beacon-get`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1474,32 +1645,43 @@ The Private Beacon Client model is an optional mesh subsystem that can be enable Opcodes Aggregator Client ------------------------- -The Opcodes Aggregator client is an optional Bluetooth mesh model that can be enabled through the :kconfig:option:`CONFIG_BT_MESH_OP_AGG_CLI` configuration option. The Opcodes Aggregator Client model is used to support the functionality of dispatching a sequence of access layer messages to nodes supporting the Opcodes Aggregator Server model. +The Opcodes Aggregator client is an optional Bluetooth mesh model that can be enabled through the +:kconfig:option:`CONFIG_BT_MESH_OP_AGG_CLI` configuration option. The Opcodes Aggregator Client +model is used to support the functionality of dispatching a sequence of access layer messages to +nodes supporting the Opcodes Aggregator Server model. ``mesh models opagg seq-start `` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Start the Opcodes Aggregator Sequence message. This command initiates the context for aggregating messages and sets the destination address for next shell commands to ``elem_addr``. + Start the Opcodes Aggregator Sequence message. This command initiates the context for + aggregating messages and sets the destination address for next shell commands to + ``elem_addr``. * ``ElemAddr``: Element address that will process the aggregated opcodes. ``mesh models opagg seq-send`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Send the Opcodes Aggregator Sequence message. This command completes the procedure, sends the aggregated sequence message to the target node and clears the context. + Send the Opcodes Aggregator Sequence message. This command completes the procedure, sends + the aggregated sequence message to the target node and clears the context. ``mesh models opagg seq-abort`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Abort the Opcodes Aggregator Sequence message. This command clears the Opcodes Aggregator Client context. + Abort the Opcodes Aggregator Sequence message. This command clears the Opcodes Aggregator + Client context. Remote Provisioning Client -------------------------- -The Remote Provisioning Client is an optional Bluetooth mesh model enabled through the :kconfig:option:`CONFIG_BT_MESH_RPR_CLI` configuration option. The Remote Provisioning Client model provides support for remote provisioning of devices into a mesh network by using the Remote Provisioning Server model. +The Remote Provisioning Client is an optional Bluetooth mesh model enabled through the +:kconfig:option:`CONFIG_BT_MESH_RPR_CLI` configuration option. The Remote Provisioning Client model +provides support for remote provisioning of devices into a mesh network by using the Remote +Provisioning Server model. -This shell module can be used to trigger interaction between Remote Provisioning Clients and Remote Provisioning Servers on devices in a mesh network. +This shell module can be used to trigger interaction between Remote Provisioning Clients and Remote +Provisioning Servers on devices in a mesh network. ``mesh models rpr scan []`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1565,12 +1747,13 @@ This shell module can be used to trigger interaction between Remote Provisioning Reprovision a mesh node using the PB-Remote provisioning bearer. * ``Addr``: Address to assign to remote device. If ``addr`` is 0, the lowest available address will be chosen. - * ``CompChanged``: The Target node has indicated that its Composition Data has changed. Defaults to false. + * ``CompChanged``: The Target node has indicated that its Composition Data has changed. Defaults to false. ``mesh models rpr instance-set `` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Use the Remote Provisioning Client model instance on the specified element when using the other Remote Provisioning Client model commands. + Use the Remote Provisioning Client model instance on the specified element when using the + other Remote Provisioning Client model commands. * ``ElemIdx``: The element on which to find the Remote Provisioning Client model instance to use. @@ -1583,14 +1766,19 @@ This shell module can be used to trigger interaction between Remote Provisioning Configuration database ====================== -The Configuration database is an optional mesh subsystem that can be enabled through the :kconfig:option:`CONFIG_BT_MESH_CDB` configuration option. The Configuration database is only available on provisioner devices, and allows them to store all information about the mesh network. To avoid conflicts, there should only be one mesh node in the network with the Configuration database enabled. This node is the Configurator, and is responsible for adding new nodes to the network and configuring them. +The Configuration database is an optional mesh subsystem that can be enabled through the +:kconfig:option:`CONFIG_BT_MESH_CDB` configuration option. The Configuration database is only +available on provisioner devices, and allows them to store all information about the mesh network. +To avoid conflicts, there should only be one mesh node in the network with the Configuration +database enabled. This node is the Configurator, and is responsible for adding new nodes to the +network and configuring them. ``mesh cdb create [NetKey(1-16 hex)]`` -------------------------------------- Create a Configuration database. - * ``NetKey``: Optional network key value of the primary network key (NetKeyIndex=0). Providing a hex-string shorter than 16 bytes will populate the N most significant bytes of the array and zero-pad the rest. Defaults to the default key value if omitted. + * ``NetKey``: Optional network key value of the primary network key (NetKeyIndex=0). Providing a hex-string shorter than 16 bytes will populate the N most significant bytes of the array and zero-pad the rest. Defaults to the default key value if omitted. ``mesh cdb clear`` @@ -1608,7 +1796,9 @@ The Configuration database is an optional mesh subsystem that can be enabled thr ``mesh cdb node-add [DevKey(1-16 hex)]`` -------------------------------------------------------------------------------------- - Manually add a mesh node to the configuration database. Note that devices provisioned with ``mesh provision`` and ``mesh provision-adv`` will be added automatically if the Configuration Database is enabled and created. + Manually add a mesh node to the configuration database. Note that devices provisioned with + ``mesh provision`` and ``mesh provision-adv`` will be added automatically if the + Configuration Database is enabled and created. * ``UUID``: 128-bit hexadecimal UUID of the node. Providing a hex-string shorter than 16 bytes will populate the N most significant bytes of the array and zero-pad the rest. * ``Addr``: Unicast address of the node, or 0 to automatically choose the lowest available address. @@ -1620,7 +1810,9 @@ The Configuration database is an optional mesh subsystem that can be enabled thr ``mesh cdb node-del `` ---------------------------- - Delete a mesh node from the Configuration database. If possible, the node should be reset with ``mesh reset`` before it is deleted from the Configuration database, to avoid unexpected behavior and uncontrolled access to the network. + Delete a mesh node from the Configuration database. If possible, the node should be reset + with ``mesh reset`` before it is deleted from the Configuration database, to avoid + unexpected behavior and uncontrolled access to the network. * ``Addr`` Address of the node to delete. @@ -1628,7 +1820,9 @@ The Configuration database is an optional mesh subsystem that can be enabled thr ``mesh cdb subnet-add []`` -------------------------------------------------------- - Add a network key to the Configuration database. The network key can later be passed to mesh nodes in the network. Note that adding a key to the Configuration database does not automatically add it to the local node's list of known network keys. + Add a network key to the Configuration database. The network key can later be passed to mesh + nodes in the network. Note that adding a key to the Configuration database does not + automatically add it to the local node's list of known network keys. * ``NetKeyIdx``: Key index of the network key to add. * ``NetKey``: Optional 128-bit network key value. Providing a hex-string shorter than 16 bytes will populate the N most significant bytes of the array and zero-pad the rest. If omitted, a random value will be generated. @@ -1645,7 +1839,9 @@ The Configuration database is an optional mesh subsystem that can be enabled thr ``mesh cdb app-key-add []`` --------------------------------------------------------------------- - Add an application key to the Configuration database. The application key can later be passed to mesh nodes in the network. Note that adding a key to the Configuration database does not automatically add it to the local node's list of known application keys. + Add an application key to the Configuration database. The application key can later be + passed to mesh nodes in the network. Note that adding a key to the Configuration database + does not automatically add it to the local node's list of known application keys. * ``NetKeyIdx``: Network key index the application key is bound to. * ``AppKeyIdx``: Key index of the application key to add. @@ -1663,25 +1859,29 @@ The Configuration database is an optional mesh subsystem that can be enabled thr On-Demand Private GATT Proxy Client ----------------------------------- -The On-Demand Private GATT Proxy Client model is an optional mesh subsystem that can be enabled through the :kconfig:option:`CONFIG_BT_MESH_OD_PRIV_PROXY_CLI` configuration option. +The On-Demand Private GATT Proxy Client model is an optional mesh subsystem that can be enabled +through the :kconfig:option:`CONFIG_BT_MESH_OD_PRIV_PROXY_CLI` configuration option. ``mesh models od_priv_proxy od-priv-gatt-proxy [Dur(s)]`` --------------------------------------------------------- - Set the On-Demand Private GATT Proxy state on active target, or fetch the value of this state from it. + Set the On-Demand Private GATT Proxy state on active target, or fetch the value of this + state from it. - * ``Dur``: If given, set the state of On-Demand Private GATT Proxy to this value in seconds. Fetch this value otherwise. + * ``Dur``: If given, set the state of On-Demand Private GATT Proxy to this value in seconds. Fetch this value otherwise. Solicitation PDU RPL Client --------------------------- -The Solicitation PDU RPL Client model is an optional mesh subsystem that can be enabled through the :kconfig:option:`CONFIG_BT_MESH_SOL_PDU_RPL_CLI` configuration option. +The Solicitation PDU RPL Client model is an optional mesh subsystem that can be enabled through the +:kconfig:option:`CONFIG_BT_MESH_SOL_PDU_RPL_CLI` configuration option. ``mesh models sol_pdu_rpl sol-pdu-rpl-clear [RngLen]`` ------------------------------------------------------------------------ - Clear active target's solicitation replay protection list (SRPL) in given range of solicitation source (SSRC) addresses. + Clear active target's solicitation replay protection list (SRPL) in given range of + solicitation source (SSRC) addresses. * ``RngStart``: Start address of the SSRC range. * ``Ackd``: This argument decides on whether an acknowledged or unacknowledged message will be sent. @@ -1694,7 +1894,8 @@ Frame statistic ``mesh stat get`` ----------------- - Get the frame statistic. The command prints numbers of received frames, as well as numbers of planned and succeeded transmission attempts. + Get the frame statistic. The command prints numbers of received frames, as well as numbers + of planned and succeeded transmission attempts. ``mesh stat clear`` diff --git a/doc/connectivity/bluetooth/api/mesh/srpl_cli.rst b/doc/connectivity/bluetooth/api/mesh/srpl_cli.rst index e940158dd2e..a5a9b7ba47f 100644 --- a/doc/connectivity/bluetooth/api/mesh/srpl_cli.rst +++ b/doc/connectivity/bluetooth/api/mesh/srpl_cli.rst @@ -4,24 +4,28 @@ Solicitation PDU RPL Configuration Client ######################################### The Solicitation PDU RPL Configuration Client model is a foundation model defined by the Bluetooth -mesh specification. The model is optional, and is enabled through the :kconfig:option:`CONFIG_BT_MESH_SOL_PDU_RPL_CLI` option. +mesh specification. The model is optional, and is enabled through the +:kconfig:option:`CONFIG_BT_MESH_SOL_PDU_RPL_CLI` option. The Solicitation PDU RPL Configuration Client model was introduced in the Bluetooth Mesh Protocol -Specification version 1.1, and supports the functionality of removing addresses from the solicitation -replay protection list (SRPL) of a node that supports the :ref:`bluetooth_mesh_srpl_srv` model. +Specification version 1.1, and supports the functionality of removing addresses from the +solicitation replay protection list (SRPL) of a node that supports the +:ref:`bluetooth_mesh_srpl_srv` model. -The Solicitation PDU RPL Configuration Client model communicates with a Solicitation PDU RPL Configuration Server model -using the application keys configured by the Configuration Client. +The Solicitation PDU RPL Configuration Client model communicates with a Solicitation PDU RPL +Configuration Server model using the application keys configured by the Configuration Client. -If present, the Solicitation PDU RPL Configuration Client model must be instantiated on the primary -element. +If present, the Solicitation PDU RPL Configuration Client model must only be instantiated on the +primary element. Configurations ************** -The Solicitation PDU RPL Configuration Client model behavior can be configured with the transmission timeout option :kconfig:option:`CONFIG_BT_MESH_SOL_PDU_RPL_CLI_TIMEOUT`. -The :kconfig:option:`CONFIG_BT_MESH_SOL_PDU_RPL_CLI_TIMEOUT` controls how long the Solicitation PDU RPL Configuration Client waits -for a response message to arrive in milliseconds. This value can be changed at runtime using :c:func:`bt_mesh_sol_pdu_rpl_cli_timeout_set`. +The Solicitation PDU RPL Configuration Client model behavior can be configured with the transmission +timeout option :kconfig:option:`CONFIG_BT_MESH_SOL_PDU_RPL_CLI_TIMEOUT`. The +:kconfig:option:`CONFIG_BT_MESH_SOL_PDU_RPL_CLI_TIMEOUT` controls how long the Solicitation PDU RPL +Configuration Client waits for a response message to arrive in milliseconds. This value can be +changed at runtime using :c:func:`bt_mesh_sol_pdu_rpl_cli_timeout_set`. API reference ************* diff --git a/doc/connectivity/bluetooth/api/mesh/srpl_srv.rst b/doc/connectivity/bluetooth/api/mesh/srpl_srv.rst index a8c5379e305..ad8a26e4c44 100644 --- a/doc/connectivity/bluetooth/api/mesh/srpl_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/srpl_srv.rst @@ -7,20 +7,24 @@ The Solicitation PDU RPL Configuration Server model is a foundation model define mesh specification. The model is enabled if the node has the :ref:`bluetooth_mesh_od_srv` enabled. The Solicitation PDU RPL Configuration Server model was introduced in the Bluetooth Mesh Protocol -Specification version 1.1, and manages the Solicitation Replay Protection List (SRPL) saved on the device. -The SRPL is used to reject Solicitation PDUs that are already processed by a node. When a valid Solicitation PDU message is -successfully processed by a node, the SSRC field and SSEQ field of the message are stored in the node's SRPL. +Specification version 1.1, and manages the Solicitation Replay Protection List (SRPL) saved on the +device. The SRPL is used to reject Solicitation PDUs that are already processed by a node. When a +valid Solicitation PDU message is successfully processed by a node, the SSRC field and SSEQ field +of the message are stored in the node's SRPL. -The Solicitation PDU RPL Configuration Server does not have an API of its own, and relies on a :ref:`bluetooth_mesh_srpl_cli` to control it. -The model only accepts messages encrypted with an application key as configured by the Configuration Client. +The Solicitation PDU RPL Configuration Server does not have an API of its own, and relies on a +:ref:`bluetooth_mesh_srpl_cli` to control it. The model only accepts messages encrypted with an +application key as configured by the Configuration Client. -If present, the Solicitation PDU RPL Configuration Server model must be instantiated on the primary -element. +If present, the Solicitation PDU RPL Configuration Server model must only be instantiated on the +primary element. Configurations ************** -For the Solicitation PDU RPL Configuration Server model, the :kconfig:option:`CONFIG_BT_MESH_PROXY_SRPL_SIZE` option can be configured to set the size of the SRPL. +For the Solicitation PDU RPL Configuration Server model, the +:kconfig:option:`CONFIG_BT_MESH_PROXY_SRPL_SIZE` option can be configured to set the size of the +SRPL. API reference ************* diff --git a/doc/connectivity/bluetooth/api/shell/cap.rst b/doc/connectivity/bluetooth/api/shell/cap.rst index 74bf5bac72f..5ab57a8d320 100644 --- a/doc/connectivity/bluetooth/api/shell/cap.rst +++ b/doc/connectivity/bluetooth/api/shell/cap.rst @@ -14,7 +14,7 @@ Using the CAP Acceptor ====================== When the Bluetooth stack has been initialized (:code:`bt init`), the Acceptor can be registered by -by calling :code:`cap_acceptor init`, which will register the CAS and CSIS services, as well as +calling :code:`cap_acceptor init`, which will register the CAS and CSIS services, as well as register callbacks. .. code-block:: console diff --git a/doc/connectivity/bluetooth/api/shell/csip.rst b/doc/connectivity/bluetooth/api/shell/csip.rst index e2daf744cac..d0fddaa61f3 100644 --- a/doc/connectivity/bluetooth/api/shell/csip.rst +++ b/doc/connectivity/bluetooth/api/shell/csip.rst @@ -14,7 +14,7 @@ or a laptop. The client is able to lock and release members of a coordinated set. While the coordinated set is locked, no other clients may lock the set. To lock a set, the client must connect to each of the set members it wants to -lock. This implementation will always try to to connect to all the members of +lock. This implementation will always try to connect to all the members of the set, and at the same time. Thus if the set size is 3, then :code:`BT_MAX_CONN` shall be at least 3. diff --git a/doc/connectivity/bluetooth/api/shell/mcp.rst b/doc/connectivity/bluetooth/api/shell/mcp.rst index a48ef50685c..e0930852e10 100644 --- a/doc/connectivity/bluetooth/api/shell/mcp.rst +++ b/doc/connectivity/bluetooth/api/shell/mcp.rst @@ -27,8 +27,7 @@ Also note that this documentation does not list all shell commands, it just shows examples of some of them. The set of commands is explorable from the mcc shell and the mpl shell, by typing :code:`mcc` or :code:`mpl` and pressing TAB. A help text for each command can be -found by doing :code:`mcc help` or or :code:`mpl -help`. +found by doing :samp:`mcc {} help` or :samp:`mpl {} help`. Overview ******** diff --git a/doc/connectivity/bluetooth/api/shell/tmap.rst b/doc/connectivity/bluetooth/api/shell/tmap.rst index 416644b3069..8a562a81361 100644 --- a/doc/connectivity/bluetooth/api/shell/tmap.rst +++ b/doc/connectivity/bluetooth/api/shell/tmap.rst @@ -10,7 +10,7 @@ Using the TMAP Shell ******************** When the Bluetooth stack has been initialized (:code:`bt init`), the TMAS can be registered by -by calling :code:`tmap init`. +calling :code:`tmap init`. .. code-block:: console diff --git a/doc/connectivity/bluetooth/autopts/autopts-linux.rst b/doc/connectivity/bluetooth/autopts/autopts-linux.rst index 6388673f025..eac940e9737 100644 --- a/doc/connectivity/bluetooth/autopts/autopts-linux.rst +++ b/doc/connectivity/bluetooth/autopts/autopts-linux.rst @@ -16,11 +16,11 @@ Supported methods to test zephyr bluetooth host: - Testing Zephyr Host Stack on QEMU -- Testing Zephyr Host Stack on native posix +- Testing Zephyr Host Stack on :ref:`native_sim ` - Testing Zephyr combined (controller + host) build on Real hardware (such as nRF52) -For running with QEMU or native posix, see :ref:`bluetooth_qemu_posix`. +For running with QEMU or :ref:`native_sim `, see :ref:`bluetooth_qemu_native`. Setup Linux =========================== @@ -293,14 +293,14 @@ Testing Zephyr Host Stack on QEMU: ~/zephyrproject/build/zephyr/zephyr.elf -i SERVER_IP -l LOCAL_IP -Testing Zephyr Host Stack on native posix: +Testing Zephyr Host Stack on :ref:`native_sim `: .. code-block:: # A Bluetooth controller needs to be mounted. # For running with HCI UART, please visit: https://docs.zephyrproject.org/latest/samples/bluetooth/hci_uart/README.html#bluetooth-hci-uart - west build -b native_posix zephyr/tests/bluetooth/tester/ -DEXTRA_CONF_FILE=overlay-native.conf + west build -b native_sim zephyr/tests/bluetooth/tester/ -DEXTRA_CONF_FILE=overlay-native.conf sudo python ./autoptsclient-zephyr.py "C:\Users\USER_NAME\Documents\Profile Tuning Suite\PTS_PROJECT\PTS_PROJECT.pqw6" \ ~/zephyrproject/build/zephyr/zephyr.exe -i SERVER_IP -l LOCAL_IP --hci 0 diff --git a/doc/connectivity/bluetooth/bluetooth-audio-arch.rst b/doc/connectivity/bluetooth/bluetooth-audio-arch.rst index 49461128270..aa62b426160 100644 --- a/doc/connectivity/bluetooth/bluetooth-audio-arch.rst +++ b/doc/connectivity/bluetooth/bluetooth-audio-arch.rst @@ -43,6 +43,178 @@ GAF has been implemented in Zephyr with the following structure. Zephyr Generic Audio Framework +Bluetooth Audio Stack Status +============================ + +The following table shows the current status and support of the profiles in the +Bluetooth Audio Stack. + +.. table:: Bluetooth Audio Profile status + :widths: auto + + +--------+-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | Module | Role | Version | Added in Release | Status | Remaining | + +========+===============================+=========+==================+=======================+==================================================+ + | VCP | Volume Renderer | 1.0 | 2.6 | - Feature complete | - Sample Application | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Volume Controller | 1.0 | 2.6 | - Feature complete | - Sample Application | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + +--------+-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | MICP | Microphone Device | 1.0 | 2.7 | - Feature complete | - Sample Application | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Microphone Controller | 1.0 | 2.7 | - Feature complete | - Sample Application | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + +--------+-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | CSIP | Set Member | 1.0.1 | 3.0 | - Feature complete | - Sample Application | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Set Coordinator | 1.0.1 | 3.0 | - Feature complete | - Sample Application | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + +--------+-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | CCP | Call Control Server | 1.0 | 3.0 | - Feature complete | - API refactor | + | | | | | - Shell Module | - Sample Application | + | | | | | - BSIM test | | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Call Control Client | 1.0 | 3.0 | - Feature complete | - API refactor | + | | | | | - Shell Module | - Sample Application | + | | | | | - BSIM test | | + +--------+-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | MCP | Media Control Server | 1.0 | 3.0 | - Feature complete | - API refactor | + | | | | | - Shell Module | - Support for multiple instances and connections | + | | | | | - BSIM test | - Sample Application | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Media Control Client | 1.0 | 3.0 | - Feature complete | - API refactor | + | | | | | - Shell Module | - Sample Application | + | | | | | - BSIM test | | + +--------+-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | BAP | Unicast Server | 1.0.1 | 3.0 | - Feature complete | | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + | | | | | - Sample Application | | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Unicast Client | 1.0.1 | 3.0 | - Feature complete | | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + | | | | | - Sample Application | | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Broadcast Source | 1.0.1 | 3.0 | - Feature complete | | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + | | | | | - Sample Application | | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Broadcast Sink | 1.0.1 | 3.0 | - Feature complete | | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + | | | | | - Sample Application | | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Scan Delegator | 1.0.1 | 3.3 | - Feature complete | | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + | | | | | - Sample Application | | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Broadcast Assistant | 1.0.1 | 3.3 | - Feature complete | - Sample Application | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + +--------+-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | CAP | Acceptor | 1.0 | 3.2 | - Feature complete | - Sample Application | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Initiator | 1.0 | 3.3 | - Feature complete | - Sample Application | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Commander | | | - Not Started | | + +--------+-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | HAP | Hearing Aid | 1.0 | 3.1 | - Feature complete | | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + | | | | | - Sample Application | | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Hearing Aid Unicast Client | 1.0 | 3.1 | - Feature complete | | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + | | | | | - Sample Application | | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Hearing Aid Remote Controller | | | - WIP | - Feature complete | + | | | | | | - Shell Module | + | | | | | | - BSIM test | + | | | | | | - Sample Application | + +--------+-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | TMAP | Call Gateway | 1.0 | 3.4 | - Feature complete | | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + | | | | | - Sample Application | | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Call Terminal | 1.0 | 3.4 | - Feature complete | | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + | | | | | - Sample Application | | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Unicast Media Sender | 1.0 | 3.4 | - Feature complete | | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + | | | | | - Sample Application | | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Unicast Media Receiver | 1.0 | 3.4 | - Feature complete | | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + | | | | | - Sample Application | | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Broadcast Media Sender | 1.0 | 3.4 | - Feature complete | | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + | | | | | - Sample Application | | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Broadcast Media Receiver | 1.0 | 3.4 | - Feature complete | | + | | | | | - Shell Module | | + | | | | | - BSIM test | | + | | | | | - Sample Application | | + +--------+-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | PBP | Public Broadcast Source | | | - WIP :github:`60777` | - Feature complete | + | | | | | | - Shell Module | + | | | | | | - BSIM test | + | | | | | | - Sample Application | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Public Broadcast Sink | | | - WIP :github:`60777` | - Feature complete | + | | | | | | - Shell Module | + | | | | | | - BSIM test | + | | | | | | - Sample Application | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Public Broadcast Assistant | | | | - Feature complete | + | | | | | | - Shell Module | + | | | | | | - BSIM test | + | | | | | | - Sample Application | + +--------+-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | GMAP | Unicast Game Gateway | | | - WIP :github:`57032` | - Feature complete | + | | | | | | - Shell Module | + | | | | | | - BSIM test | + | | | | | | - Sample Application | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Unicast Game Terminal | | | - WIP :github:`57032` | - Feature complete | + | | | | | | - Shell Module | + | | | | | | - BSIM test | + | | | | | | - Sample Application | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Broadcast Game Sender | | | - WIP :github:`57032` | - Feature complete | + | | | | | | - Shell Module | + | | | | | | - BSIM test | + | | | | | | - Sample Application | + | +-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + | | Broadcast Game Receiver | | | - WIP :github:`57032` | - Feature complete | + | | | | | | - Shell Module | + | | | | | | - BSIM test | + | | | | | | - Sample Application | + +--------+-------------------------------+---------+------------------+-----------------------+--------------------------------------------------+ + Using the Bluetooth Audio Stack =============================== diff --git a/doc/connectivity/bluetooth/bluetooth-dev.rst b/doc/connectivity/bluetooth/bluetooth-dev.rst index dd3c2058c2c..865eb22d049 100644 --- a/doc/connectivity/bluetooth/bluetooth-dev.rst +++ b/doc/connectivity/bluetooth/bluetooth-dev.rst @@ -33,8 +33,8 @@ There are 4 possible hardware setups to use with Zephyr and Bluetooth: #. Embedded #. QEMU with an external Controller -#. Native POSIX with an external Controller -#. Simulated nRF52 with BabbleSim +#. :ref:`native_sim ` with an external Controller +#. Simulated nRF5x with BabbleSim Embedded ======== @@ -90,7 +90,7 @@ This setup relies on a "dual-chip" :ref:`configuration ` which is comprised of the following devices: #. A :ref:`Host-only ` application running in the - :ref:`QEMU ` emulator or the ``native_posix`` native + :ref:`QEMU ` emulator or the :ref:`native_sim ` native port of Zephyr #. A Controller, which can be one of the following types: @@ -117,52 +117,55 @@ QEMU You can run the Zephyr Host on the :ref:`QEMU emulator` and have it interact with a physical external Bluetooth Controller. -Refer to :ref:`bluetooth_qemu_posix` for full instructions on how to build and +Refer to :ref:`bluetooth_qemu_native` for full instructions on how to build and run an application in this setup. -Native POSIX ------------- +native_sim +---------- .. note:: This is currently only available on GNU/Linux -The :ref:`Native POSIX ` target builds your Zephyr application +The :ref:`native_sim ` target builds your Zephyr application with the Zephyr kernel, and some minimal HW emulation as a native Linux executable. This executable is a normal Linux program, which can be debugged and instrumented like any other, and it communicates with a physical or virtual external Controller. -Refer to :ref:`bluetooth_qemu_posix` for full instructions on how to build and +Refer to :ref:`bluetooth_qemu_native` for full instructions on how to build and run an application with a physical controller. For the virtual controller refer to :ref:`bluetooth_virtual_posix`. -Simulated nRF52 with BabbleSim +Simulated nRF5x with BabbleSim ============================== .. note:: This is currently only available on GNU/Linux -The :ref:`nrf52_bsim board `, is a simulated target board -which emulates the necessary peripherals of a nrf52 SOC to be able to develop +The :ref:`nrf52_bsim ` and :ref:`nrf5340bsim ` boards, +are simulated target boards +which emulate the necessary peripherals of a nRF52/53 SOC to be able to develop and test BLE applications. -This board, uses: +These boards, use: - * `BabbleSim`_ to simulate the nrf52 modem and the radio environment. - * The POSIX arch to emulate the processor. - * `Models of the nrf52 HW `_ + * `BabbleSim`_ to simulate the nRF5x modem and the radio environment. + * The POSIX arch and native simulator to emulate the processor, and run natively on your host. + * `Models of the nrf5x HW `_ -Just like with the ``native_posix`` target, the build result is a normal Linux +Just like with the :ref:`native_sim ` target, the build result is a normal Linux executable. You can find more information on how to run simulations with one or several -devices in -:ref:`this board's documentation ` +devices in either of :ref:`these boards's documentation `. -Currently, only :ref:`Combined builds +With the :ref:`nrf52_bsim `, only :ref:`Combined builds ` are possible, as this board does not yet have any models of a UART, or USB which could be used for an HCI interface towards another real or simulated device. +With the :ref:`nrf5340bsim `, you can build with either, both controller and host +on its network core, or, with the network core running only the controller, the application +core running the host and your application, and the HCI transport over IPC. Initialization ************** diff --git a/doc/connectivity/bluetooth/bluetooth-tools.rst b/doc/connectivity/bluetooth/bluetooth-tools.rst index 35453dd5f67..9da5c5feb1e 100644 --- a/doc/connectivity/bluetooth/bluetooth-tools.rst +++ b/doc/connectivity/bluetooth/bluetooth-tools.rst @@ -74,13 +74,13 @@ Finally, reload and restart the daemon: sudo systemctl daemon-reload sudo systemctl restart bluetooth -.. _bluetooth_qemu_posix: +.. _bluetooth_qemu_native: -Running on QEMU and Native POSIX -******************************** +Running on QEMU or native_sim +***************************** It's possible to run Bluetooth applications using either the :ref:`QEMU -emulator` or :ref:`Native POSIX `. +emulator` or :ref:`native_sim `. In either case, a Bluetooth controller needs to be exported from the host OS (Linux) to the emulator. For this purpose you will need some tools described in the :ref:`bluetooth_bluez` section. @@ -94,14 +94,14 @@ The host OS's Bluetooth controller is connected in the following manner: with the help of the QEMU option :literal:`-serial unix:/tmp/bt-server-bredr`. This option gets passed to QEMU through :makevar:`QEMU_EXTRA_FLAGS` automatically whenever an application has enabled Bluetooth support. -* To a serial port in Native POSIX through the use of a command-line option - passed to the Native POSIX executable: ``--bt-dev=hci0`` +* To a serial port in :ref:`native_sim ` through the use of a command-line option + passed to the native_sim executable: ``--bt-dev=hci0`` On the host side, BlueZ allows you to export its Bluetooth controller -through a so-called user channel for QEMU and Native POSIX to use. +through a so-called user channel for QEMU and :ref:`native_sim ` to use. .. note:: - You only need to run ``btproxy`` when using QEMU. Native POSIX handles + You only need to run ``btproxy`` when using QEMU. native_sim handles the UNIX socket proxying automatically If you are using QEMU, in order to make the Controller available you will need @@ -142,12 +142,12 @@ building and running a sample: the :literal:`bt-server-bredr` UNIX socket, letting the application access the Bluetooth controller. -* To run a Bluetooth application in Native POSIX, first build it: +* To run a Bluetooth application in :ref:`native_sim `, first build it: .. zephyr-app-commands:: :zephyr-app: samples/bluetooth/ :host-os: unix - :board: native_posix + :board: native_sim :goals: build :compact: @@ -180,8 +180,8 @@ In order to see those logs, you can use the built-in ``btmon`` tool from BlueZ: .. _bluetooth_virtual_posix: -Running on a Virtual Controller and Native POSIX -************************************************* +Running on a Virtual Controller and native_sim +********************************************** An alternative to a Bluetooth physical controller is the use of a virtual controller. This controller can be connected over an HCI TCP server. @@ -212,7 +212,7 @@ To connect your application to the Android Emulator follow the next steps: #. Build your Zephyr application and disable the HCI ACL flow control (i.e. ``CONFIG_BT_HCI_ACL_FLOW_CONTROL=n``) as the - the virtual controller from android does not support it at the moment. + virtual controller from android does not support it at the moment. #. Install Android Emulator version >= 33.1.4.0. The easiest way to do this is by installing the latest `Android Studio Preview`_ version. diff --git a/doc/connectivity/canbus/index.rst b/doc/connectivity/canbus/index.rst new file mode 100644 index 00000000000..78271d4181e --- /dev/null +++ b/doc/connectivity/canbus/index.rst @@ -0,0 +1,9 @@ +.. _canbus: + +Controller Area Network (CAN) Bus Protocols +########################################### + +.. toctree:: + :maxdepth: 2 + + isotp.rst diff --git a/doc/hardware/peripherals/canbus/isotp.rst b/doc/connectivity/canbus/isotp.rst similarity index 96% rename from doc/hardware/peripherals/canbus/isotp.rst rename to doc/connectivity/canbus/isotp.rst index 325a45cc036..4fea2c95232 100644 --- a/doc/hardware/peripherals/canbus/isotp.rst +++ b/doc/connectivity/canbus/isotp.rst @@ -18,7 +18,7 @@ over Controller Area Networks. Nevertheless, it's not limited to applications in road vehicles or the automotive domain. This transport protocol extends the limited payload data size for classical -CAN (8 bytes) and CAN-FD (64 bytes) to theoretically four gigabytes. +CAN (8 bytes) and CAN FD (64 bytes) to theoretically four gigabytes. Additionally, it adds a flow control mechanism to influence the sender's behavior. ISO-TP segments packets into small fragments depending on the payload size of the CAN frame. The header of those segments is called Protocol Control diff --git a/doc/hardware/peripherals/canbus/isotp_sequence.svg b/doc/connectivity/canbus/isotp_sequence.svg similarity index 100% rename from doc/hardware/peripherals/canbus/isotp_sequence.svg rename to doc/connectivity/canbus/isotp_sequence.svg diff --git a/doc/connectivity/index.rst b/doc/connectivity/index.rst index c135ed410bb..be81417d0ba 100644 --- a/doc/connectivity/index.rst +++ b/doc/connectivity/index.rst @@ -7,6 +7,7 @@ Connectivity :maxdepth: 1 bluetooth/index.rst + canbus/index.rst networking/index.rst lora_lorawan/index.rst usb/index.rst diff --git a/doc/connectivity/networking/api/capture.rst b/doc/connectivity/networking/api/capture.rst index ba6e347170d..ee7605624c4 100644 --- a/doc/connectivity/networking/api/capture.rst +++ b/doc/connectivity/networking/api/capture.rst @@ -18,7 +18,7 @@ using ``net-shell`` or automatically by using the ``net_capture`` API. Sample usage ************ -See :ref:`Network capture sample application ` and +See :zephyr:code-sample:`net-capture` sample application and :ref:`network_monitoring` for details. diff --git a/doc/connectivity/networking/api/coap.rst b/doc/connectivity/networking/api/coap.rst index 8e5690b3387..ffb794a0c8a 100644 --- a/doc/connectivity/networking/api/coap.rst +++ b/doc/connectivity/networking/api/coap.rst @@ -28,8 +28,6 @@ See :ref:`lwm2m_interface` for more information. Supported RFCs: -Supported RFCs: - - `RFC7252: The Constrained Application Protocol (CoAP) `_ - `RFC6690: Constrained RESTful Environments (CoRE) Link Format `_ - `RFC7959: Block-Wise Transfers in the Constrained Application Protocol (CoAP) `_ @@ -43,6 +41,11 @@ Sample Usage CoAP Server =========== +.. note:: + + A :ref:`coap_server_interface` subsystem is available, the following is for creating a custom + server implementation. + To create a CoAP server, resources for the server need to be defined. The ``.well-known/core`` resource should be added before all other resources that should be included in the responses of the ``.well-known/core`` @@ -97,6 +100,11 @@ with resource path like '/some_resource/+/#'. CoAP Client =========== +.. note:: + + A :ref:`coap_client_interface` subsystem is available, the following is for creating a custom + client implementation. + If the CoAP client knows about resources in the CoAP server, the client can start prepare CoAP requests and wait for responses. If the client doesn't know about resources in the CoAP server, it can request resources through @@ -142,7 +150,7 @@ in Zephyr. See the `net-tools `_ project for more details -The :ref:`coap-server-sample` sample can be built and executed on QEMU as described +The :zephyr:code-sample:`coap-server` sample can be built and executed on QEMU as described in :ref:`networking_with_qemu`. Use this command on the host to run the libcoap implementation of @@ -172,16 +180,16 @@ Install eclipse-titan and set symbolic links for titan tools export TTCN3_DIR=/usr/share/titan - git clone https://github.com/eclipse/titan.misc.git + git clone https://gitlab.eclipse.org/eclipse/titan/titan.misc.git cd titan.misc Follow the instruction to setup CoAP test suite from here: -- https://github.com/eclipse/titan.misc -- https://github.com/eclipse/titan.misc/tree/master/CoAP_Conf +- https://gitlab.eclipse.org/eclipse/titan/titan.misc +- https://gitlab.eclipse.org/eclipse/titan/titan.misc/-/tree/master/CoAP_Conf -After the build is complete, the :ref:`coap-server-sample` sample can be built +After the build is complete, the :zephyr:code-sample:`coap-server` sample can be built and executed on QEMU as described in :ref:`networking_with_qemu`. Change the client (test suite) and server (Zephyr coap-server sample) addresses diff --git a/doc/connectivity/networking/api/coap_server.rst b/doc/connectivity/networking/api/coap_server.rst new file mode 100644 index 00000000000..9a91081f449 --- /dev/null +++ b/doc/connectivity/networking/api/coap_server.rst @@ -0,0 +1,247 @@ +.. _coap_server_interface: + +CoAP server +########### + +.. contents:: + :local: + :depth: 2 + +Overview +******** + +Zephyr comes with a batteries-included CoAP server, which uses services to listen for CoAP +requests. The CoAP services handle communication over sockets and pass requests to registered +CoAP resources. + +Setup +***** + +Some configuration is required to make sure services can be started using the CoAP server. The +:kconfig:option:`CONFIG_COAP_SERVER` option should be enabled in your project: + +.. code-block:: cfg + :caption: ``prj.conf`` + + CONFIG_COAP_SERVER=y + +All services are added to a predefined linker section and all resources for each service also get +their respective linker sections. If you would have a service ``my_service`` it has to be +prefixed wth ``coap_resource_`` and added to a linker file: + +.. code-block:: c + :caption: ``sections-ram.ld`` + + #include + + ITERABLE_SECTION_RAM(coap_resource_my_service, 4) + +Add this linker file to your application using CMake: + +.. code-block:: cmake + :caption: ``CMakeLists.txt`` + + zephyr_linker_sources(DATA_SECTIONS sections-ram.ld) + +You can now define your service as part of the application: + +.. code-block:: c + + #include + + static const uint16_t my_service_port = 5683; + + COAP_SERVICE_DEFINE(my_service, "0.0.0.0", &my_service_port, COAP_SERVICE_AUTOSTART); + +.. note:: + + Services defined with the ``COAP_SERVICE_AUTOSTART`` flag will be started together with the CoAP + server thread. Services can be manually started and stopped with ``coap_service_start`` and + ``coap_service_stop`` respectively. + +Sample Usage +************ + +The following is an example of a CoAP resource registered with our service: + +.. code-block:: c + + #include + + static int my_get(struct coap_resource *resource, struct coap_packet *request, + struct sockaddr *addr, socklen_t addr_len) + { + static const char *msg = "Hello, world!"; + uint8_t data[CONFIG_COAP_SERVER_MESSAGE_SIZE]; + struct coap_packet response; + uint16_t id; + uint8_t token[COAP_TOKEN_MAX_LEN]; + uint8_t tkl, type; + + type = coap_header_get_type(request); + id = coap_header_get_id(request); + tkl = coap_header_get_token(request, token); + + /* Determine response type */ + type = (type == COAP_TYPE_CON) ? COAP_TYPE_ACK : COAP_TYPE_NON_CON; + + coap_packet_init(&response, data, sizeof(data), COAP_VERSION_1, type, tkl, token, + COAP_RESPONSE_CODE_CONTENT, id); + + /* Set content format */ + coap_append_option_int(&response, COAP_OPTION_CONTENT_FORMAT, + COAP_CONTENT_FORMAT_TEXT_PLAIN); + + /* Append payload */ + coap_packet_append_payload_marker(&response); + coap_packet_append_payload(&response, (uint8_t *)msg, sizeof(msg)); + + /* Send to response back to the client */ + return coap_resource_send(resource, &response, addr, addr_len); + } + + static int my_put(struct coap_resource *resource, struct coap_packet *request, + struct sockaddr *addr, socklen_t addr_len) + { + /* ... Handle the incoming request ... */ + + /* Return a CoAP response code as a shortcut for an empty ACK message */ + return COAP_RESPONSE_CODE_CHANGED; + } + + static const char * const my_resource_path[] = { "test", NULL }; + COAP_RESOURCE_DEFINE(my_resource, my_service, { + .path = my_resource_path, + .get = my_get, + .put = my_put, + }); + +.. note:: + + As demonstrated in the example above, a CoAP resource handler can return response codes to let + the server respond with an empty ACK response. + +Observable resources +******************** + +The CoAP server provides logic for parsing observe requests and stores these using the runtime data +of CoAP services. Together with observer events, enabled with +:kconfig:option:`CONFIG_COAP_OBSERVER_EVENTS`, the application can easily keep track of clients +and send state updates. An example using a temperature sensor can look like: + +.. code-block:: c + + #include + #include + #include + + static void notify_observers(struct k_work *work); + K_WORK_DELAYABLE_DEFINE(temp_work, notify_observers); + + static void temp_observer_event(struct coap_resource *resource, struct coap_observer *observer, + enum coap_observer_event event) + { + /* Only track the sensor temperature if an observer is active */ + if (event == COAP_OBSERVER_ADDED) { + k_work_schedule(&temp_work, K_SECONDS(1)); + } + } + + static int send_temperature(struct coap_resource *resource, + const struct sockaddr *addr, socklen_t addr_len, + uint16_t age, uint16_t id, const uint8_t *token, uint8_t tkl, + bool is_response) + { + const struct device *dev = DEVICE_DT_GET(DT_ALIAS(ambient_temp0)); + uint8_t data[CONFIG_COAP_SERVER_MESSAGE_SIZE]; + struct coap_packet response; + char payload[14]; + struct sensor_value value; + double temp; + uint8_t type; + + /* Determine response type */ + type = is_response ? COAP_TYPE_ACK : COAP_TYPE_CON; + + if (!is_response) { + id = coap_next_id(); + } + + coap_packet_init(&response, data, sizeof(data), COAP_VERSION_1, type, tkl, token, + COAP_RESPONSE_CODE_CONTENT, id); + + if (age >= 2U) { + coap_append_option_int(&response, COAP_OPTION_OBSERVE, age); + } + + /* Set content format */ + coap_append_option_int(&response, COAP_OPTION_CONTENT_FORMAT, + COAP_CONTENT_FORMAT_TEXT_PLAIN); + + /* Get the sensor date */ + sensor_sample_fetch_chan(dev, SENSOR_CHAN_AMBIENT_TEMP); + sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &value); + temp = sensor_value_to_double(&value); + + snprintk(payload, sizeof(payload), "%0.2f°C", temp); + + /* Append payload */ + coap_packet_append_payload_marker(&response); + coap_packet_append_payload(&response, (uint8_t *)payload, strlen(payload)); + + return coap_resource_send(resource, &response, addr, addr_len); + } + + static int temp_get(struct coap_resource *resource, struct coap_packet *request, + struct sockaddr *addr, socklen_t addr_len) + { + uint8_t token[COAP_TOKEN_MAX_LEN]; + uint16_t id; + uint8_t tkl; + int r; + + /* Let the CoAP server parse the request and add/remove observers if needed */ + r = coap_resource_parse_observe(resource, request, addr); + + id = coap_header_get_id(request); + tkl = coap_header_get_token(request, token); + + return send_temperature(resource, addr, addr_len, r == 0 ? resource->age : 0, + id, token, tkl, true); + } + + static void temp_notify(struct coap_resource *resource, struct coap_observer *observer) + { + send_temperature(resource, &observer->addr, sizeof(observer->addr), resource->age, 0, + observer->token, observer->tkl, false); + } + + static const char * const temp_resource_path[] = { "sensors", "temp1", NULL }; + COAP_RESOURCE_DEFINE(temp_resource, my_service, { + .path = temp_resource_path, + .get = temp_get, + .notify = temp_notify, + .observer_event_handler = temp_observer_event, + }); + + static void notify_observers(struct k_work *work) + { + if (sys_slist_is_empty(&temp_resource.observers)) { + return; + } + + coap_resource_notify(&temp_resource); + k_work_reschedule(&temp_work, K_SECONDS(1)); + } + +CoRE Link Format +**************** + +The :kconfig:option:`CONFIG_COAP_SERVER_WELL_KNOWN_CORE` option enables handling the +``.well-known/core`` GET requests by the server. This allows clients to get a list of hypermedia +links to other resources hosted in that server. + +API Reference +************* + +.. doxygengroup:: coap_service diff --git a/doc/connectivity/networking/api/dhcpv4.rst b/doc/connectivity/networking/api/dhcpv4.rst index f9588e9dda4..e06bcd9182a 100644 --- a/doc/connectivity/networking/api/dhcpv4.rst +++ b/doc/connectivity/networking/api/dhcpv4.rst @@ -23,7 +23,7 @@ Note that Zephyr only supports DHCP client functionality. Sample usage ************ -See :ref:`dhcpv4-client-sample` for details. +See :zephyr:code-sample:`dhcpv4-client` sample application for details. API Reference ************* diff --git a/doc/connectivity/networking/api/dns_resolve.rst b/doc/connectivity/networking/api/dns_resolve.rst index fc4f0d8613c..d119fc74190 100644 --- a/doc/connectivity/networking/api/dns_resolve.rst +++ b/doc/connectivity/networking/api/dns_resolve.rst @@ -35,7 +35,7 @@ For more information about DNS configuration variables, see: Sample usage ************ -See :ref:`DNS resolve sample application ` for details. +See :zephyr:code-sample:`dns-resolve` sample application for details. API Reference ************* diff --git a/doc/connectivity/networking/api/gptp.rst b/doc/connectivity/networking/api/gptp.rst index e3bba55f50d..58788ee003d 100644 --- a/doc/connectivity/networking/api/gptp.rst +++ b/doc/connectivity/networking/api/gptp.rst @@ -40,7 +40,7 @@ Boards supported: - :ref:`nucleo_h745zi_q_board` - :ref:`nucleo_f767zi_board` - :ref:`sam_e70_xplained` -- :ref:`native_posix` (only usable for simple testing, limited capabilities +- :ref:`native_sim` (only usable for simple testing, limited capabilities due to lack of hardware clock) - :ref:`qemu_x86` (emulated, limited capabilities due to lack of hardware clock) @@ -66,7 +66,7 @@ Testing The stack has been informally tested using the `OpenAVnu gPTP `_ and `Linux ptp4l `_ daemons. -The :ref:`gPTP sample application ` from the Zephyr +The :zephyr:code-sample:`gPTP sample application ` from the Zephyr source distribution can be used for testing. .. _IEEE 802.1AS-2011 standard: diff --git a/doc/connectivity/networking/api/gsm_modem.rst b/doc/connectivity/networking/api/gsm_modem.rst index d44f68b38f1..cf15e429796 100644 --- a/doc/connectivity/networking/api/gsm_modem.rst +++ b/doc/connectivity/networking/api/gsm_modem.rst @@ -12,7 +12,7 @@ The Zephyr uses :ref:`PPP (Point-to-Point Protocol) ` to connect to the GSM modem using UART. Note that some cellular modems have proprietary offloading support using AT commands, but usually those modems also support 3GPP standards and provide PPP connection to them. -See :ref:`GSM modem sample application ` how to setup Zephyr +See :zephyr:code-sample:`GSM modem sample application ` how to setup Zephyr to use the GSM modem. The GSM muxing, that is defined in diff --git a/doc/connectivity/networking/api/http.rst b/doc/connectivity/networking/api/http.rst index a8b81b86357..060a41643d9 100644 --- a/doc/connectivity/networking/api/http.rst +++ b/doc/connectivity/networking/api/http.rst @@ -68,7 +68,7 @@ The following is an example of a very simple response handling function: LOG_INF("Response status %s", rsp->http_status); } -See :ref:`HTTP client sample application ` for +See :zephyr:code-sample:`HTTP client sample application ` for more information about the library usage. API Reference diff --git a/doc/connectivity/networking/api/ieee802154.rst b/doc/connectivity/networking/api/ieee802154.rst index ab838477e1f..ba641b1e4e3 100644 --- a/doc/connectivity/networking/api/ieee802154.rst +++ b/doc/connectivity/networking/api/ieee802154.rst @@ -7,30 +7,91 @@ IEEE 802.15.4 :local: :depth: 2 -Overview -******** +Introduction +************ + IEEE 802.15.4 is a technical standard which defines the operation of low-rate -wireless personal area networks (LR-WPANs). For more detailed overview of this -standard, see this -`IEEE 802.15.4 Wikipedia article `_. -Also, see `IEEE GET Program -`_ -for creating an IEEE account and downloading the specification. - -Zephyr supports IEEE 802.15.4 with Thread and 6LoWPAN. The Thread implementation -is based on `OpenThread `_. -The IPv6 header compression in 6LoWPAN is shared with -the Bluetooth IPSP (IP support profile). +wireless personal area networks (LR-WPANs). For a more detailed overview of this +standard, see the `IEEE 802.15.4 Wikipedia article +`_. + +The most recent version of the standard is accessible through the `IEEE GET +Program +`_. +You need to create a free IEEE account and can then downloading it. + +We're currently following the IEEE 802.15.4-2020 specification. This version is +backwards compatible with IEEE 802.15.4-2015, parts of which are contained in +the Thread protocol stack. The 2020 version also includes prior extensions that +were accepted into the standard, namely IEEE 802.15.4g (SUN FSK) and IEEE +802.15.4e (TSCH) which are of relevance to industrial IoT and automation. For +recent developments in UWB ranging technology, see IEEE 802.15.4z which is not +yet integrated into the standard's mainline. + +Whenever sections from the standard are cited in the documentation, they refer +to IEEE 802.15.4-2020 section, table and figure numbering - unless otherwise +specified. + +Zephyr supports both, native IEEE 802.15.4 and Thread, with 6LoWPAN. Zephyr's +:ref:`thread_protocol_interface` implementation is based on `OpenThread +`_. The IPv6 header compression in 6LoWPAN is shared +among native IEEE 802.15.4 and the Bluetooth IPSP (IP support profile). API Reference ************* -IEEE 802.15.4 -============= +IEEE 802.15.4 API Overview +========================== + +Gives an introduction and overview over the whole IEEE 802.15.4 subsystem and +all of its APIs, configuration and user interfaces for all audiences. .. doxygengroup:: ieee802154 -IEEE 802.15.4 Management -======================== + +.. _ieee802154_mgmt_api: + +IEEE 802.15.4 Management API +============================ + +This is the main subsystem-specific API of interest to IEEE 802.15.4 +**application developers** as it allows to configure the IEEE 802.15.4 subsystem +at runtime. Other relevant interfaces for application developers are the +typical shell, socket, Kconfig and devicetree APIs that can be accessed through +Zephyr's generic subsystem-independent documentation. Look out for +IEEE802154/ieee802154 prefixes there. .. doxygengroup:: ieee802154_mgmt + + +.. _ieee802154_driver_api: + +IEEE 802.15.4 Driver API +======================== + +This is the main API of interest to IEEE 802.15.4 **driver developers**. + +.. doxygengroup:: ieee802154_driver + + +.. _ieee802154_l2_api: + +IEEE 802.15.4 L2 / Native Stack API +=================================== + +This documents the IEEE 802.15.4 L2 native stack, which neither applications nor +drivers will ever access directly. It is called internally by Zephyr's upper +network layers (L3+), its socket and network context abstractions. This API is +therefore of interest to IEEE 802.15.4 **subsystem contributors** only. + +.. doxygengroup:: ieee802154_l2 + +OpenThread L2 Adaptation Layer API +================================== + +Zephyr's OpenThread L2 platform adaptation layer glues the external OpenThread +stack together with Zephyr's IEEE 802.15.4 protocol agnostic driver API. This +API is of interest to OpenThread L2 **subsystem contributors** only. + +The OpenThread API is part of the :ref:`thread_protocol_interface` subsystem and +documented there. diff --git a/doc/connectivity/networking/api/lwm2m.rst b/doc/connectivity/networking/api/lwm2m.rst index d3843e4c3d1..3baa4516c5d 100644 --- a/doc/connectivity/networking/api/lwm2m.rst +++ b/doc/connectivity/networking/api/lwm2m.rst @@ -227,7 +227,7 @@ The full list of registered objects and resource IDs can be found in the Zephyr's LwM2M library lives in the :zephyr_file:`subsys/net/lib/lwm2m`, with a client sample in :zephyr_file:`samples/net/lwm2m_client`. For more information -about the provided sample see: :ref:`lwm2m-client-sample` The sample can be +about the provided sample see: :zephyr:code-sample:`lwm2m-client`. The sample can be configured to use normal unsecure network sockets or sockets secured via DTLS. The Zephyr LwM2M library implements the following items: @@ -404,6 +404,11 @@ NoSec In all modes, Server URI resource (ID 0) must contain the full URI for the target server. When DNS names are used, the DNS resolver must be enabled. +When DTLS is used, following options are recommended to reduce DTLS handshake traffic when connection is re-established: + +* :kconfig:option:`CONFIG_LWM2M_DTLS_CID` enables DTLS Connection Identifier support. When server supports it, this completely removes the handshake when device resumes operation after long idle period. Greatly helps when NAT mappings have timed out. +* :kconfig:option:`CONFIG_LWM2M_TLS_SESSION_CACHING` uses session cache when before falling back to full DTLS handshake. Reduces few packets from handshake, when session is still cached on server side. Most significant effect is to avoid full registration. + LwM2M stack provides callbacks in the :c:struct:`lwm2m_ctx` structure. They are used to feed keys from the LwM2M security object into the TLS credential subsystem. By default, these callbacks can be left as NULL pointers, in which case default callbacks are used. @@ -452,7 +457,7 @@ value of 1 is ok here). client.tls_tag = 1; /* <---- */ lwm2m_rd_client_start(&client, "endpoint-name", 0, rd_client_event); -For a more detailed LwM2M client sample see: :ref:`lwm2m-client-sample`. +For a more detailed LwM2M client sample see: :zephyr:code-sample:`lwm2m-client`. Multi-thread usage ****************** @@ -478,7 +483,7 @@ Support for time series data LwM2M version 1.1 adds support for SenML CBOR and SenML JSON data formats. These data formats add support for time series data. Time series formats can be used for READ, NOTIFY and SEND operations. When data cache is enabled for a resource, each write will create a timestamped entry in a cache, -and its content is then returned as a content in in READ, NOTIFY or SEND operation for a given +and its content is then returned as a content in READ, NOTIFY or SEND operation for a given resource. Data cache is only supported for resources with a fixed data size. @@ -717,7 +722,10 @@ required actions from the server side. -t Write value as time_t create :create PATH - Create object instance + Create object or resource instance + + delete :delete PATH + Delete object or resource instance cache :cache PATH NUM Enable data cache for resource diff --git a/doc/connectivity/networking/api/mqtt.rst b/doc/connectivity/networking/api/mqtt.rst index dcc71e3320b..16ba69e1288 100644 --- a/doc/connectivity/networking/api/mqtt.rst +++ b/doc/connectivity/networking/api/mqtt.rst @@ -129,7 +129,7 @@ be called and an appropriate event notified. The connection can be closed by calling the ``mqtt_disconnect`` function. Zephyr provides sample code utilizing the MQTT client API. See -:ref:`mqtt-publisher-sample` for more information. +:zephyr:code-sample:`mqtt-publisher` for more information. Using MQTT with TLS ******************* @@ -165,7 +165,7 @@ to :ref:`secure sockets documentation `. Finally, ``set_native_tls`` can be optionally set to enable native TLS support instead of offloading TLS operations to the modem. An example of how to use TLS with MQTT is also present in -:ref:`mqtt-publisher-sample`. +:zephyr:code-sample:`mqtt-publisher` sample application. .. _mqtt_api_reference: diff --git a/doc/connectivity/networking/api/mqtt_sn.rst b/doc/connectivity/networking/api/mqtt_sn.rst index 40a1b9d8df8..3da4d903725 100644 --- a/doc/connectivity/networking/api/mqtt_sn.rst +++ b/doc/connectivity/networking/api/mqtt_sn.rst @@ -124,7 +124,7 @@ has no effect on the transport, however. If you want to close the transport (e.g the socket), call ``mqtt_sn_client_deinit``, which will deinit the transport as well. Zephyr provides sample code utilizing the MQTT-SN client API. See -:ref:`mqtt-sn-publisher-sample` for more information. +:zephyr:code-sample:`mqtt-sn-publisher` for more information. Deviations from the standard **************************** diff --git a/doc/connectivity/networking/api/net_if.rst b/doc/connectivity/networking/api/net_if.rst index f2cf7ca521f..590e328df9f 100644 --- a/doc/connectivity/networking/api/net_if.rst +++ b/doc/connectivity/networking/api/net_if.rst @@ -31,6 +31,8 @@ pointer or by a network interface index. The network interface can be resolved from its index by calling ``net_if_get_by_index()`` and from interface pointer by calling ``net_if_get_by_iface()``. +.. _net_if_interface_ip_management: + The IP address for network devices must be set for them to be connectable. In a typical dynamic network environment, IP addresses are set automatically by DHCPv4, for example. If needed though, the application can set a device's @@ -55,6 +57,8 @@ network technology supports promiscuous mode, then it is possible to receive all the network packets that the network device driver is able to receive. See :ref:`promiscuous_interface` API for more details. +.. _net_if_interface_state_management: + Network interface state management ********************************** diff --git a/doc/connectivity/networking/api/net_mgmt.rst b/doc/connectivity/networking/api/net_mgmt.rst index f99089260b6..ed6c512a742 100644 --- a/doc/connectivity/networking/api/net_mgmt.rst +++ b/doc/connectivity/networking/api/net_mgmt.rst @@ -42,6 +42,8 @@ To avoid extra cost, all :c:func:`net_mgmt` calls are direct. Though this may change in a future release, it will not affect the users of this function. +.. _net_mgmt_listening: + Listening to network events *************************** diff --git a/doc/connectivity/networking/api/net_shell.rst b/doc/connectivity/networking/api/net_shell.rst index cf51291d0c9..710b544eb7b 100644 --- a/doc/connectivity/networking/api/net_shell.rst +++ b/doc/connectivity/networking/api/net_shell.rst @@ -38,6 +38,9 @@ The following net-shell commands are implemented: "net ping", "Ping a network host." "net route", "Show IPv6 network routes. Only available if :kconfig:option:`CONFIG_NET_ROUTE` is set." + "net sockets", "Show network socket information and statistics. Only available if + :kconfig:option:`CONFIG_NET_SOCKETS_OBJ_CORE` and :kconfig:option:`CONFIG_OBJ_CORE` + are set." "net stats", "Show network statistics." "net tcp", "Connect/send data/close TCP connection. Only available if :kconfig:option:`CONFIG_NET_TCP` is set." diff --git a/doc/connectivity/networking/api/net_time.rst b/doc/connectivity/networking/api/net_time.rst new file mode 100644 index 00000000000..b736d9f1ed6 --- /dev/null +++ b/doc/connectivity/networking/api/net_time.rst @@ -0,0 +1,9 @@ +.. _net_time_interface: + +Network time representation in the network stack +################################################ + +API Reference +************* + +.. doxygengroup:: net_time diff --git a/doc/connectivity/networking/api/promiscuous.rst b/doc/connectivity/networking/api/promiscuous.rst index c5e18f58fb0..9b60770c00e 100644 --- a/doc/connectivity/networking/api/promiscuous.rst +++ b/doc/connectivity/networking/api/promiscuous.rst @@ -70,7 +70,7 @@ Finally the promiscuous mode can be turned OFF by the application like this: } -See :ref:`net-promiscuous-mode-sample` for a more comprehensive example. +See :zephyr:code-sample:`net-promiscuous-mode` for a more comprehensive example. API Reference diff --git a/doc/connectivity/networking/api/protocols.rst b/doc/connectivity/networking/api/protocols.rst index 6ed46130fa5..aea485b74aa 100644 --- a/doc/connectivity/networking/api/protocols.rst +++ b/doc/connectivity/networking/api/protocols.rst @@ -9,7 +9,9 @@ Protocols coap coap_client + coap_server http lwm2m mqtt mqtt_sn + tftp diff --git a/doc/connectivity/networking/api/sockets.rst b/doc/connectivity/networking/api/sockets.rst index f7a77f68f67..720bebeb820 100644 --- a/doc/connectivity/networking/api/sockets.rst +++ b/doc/connectivity/networking/api/sockets.rst @@ -73,6 +73,8 @@ To enable secure sockets, set the :kconfig:option:`CONFIG_NET_SOCKETS_SOCKOPT_TL option. To enable DTLS support, use :kconfig:option:`CONFIG_NET_SOCKETS_ENABLE_DTLS` option. +.. _sockets_tls_credentials_subsys: + TLS credentials subsystem ========================= @@ -133,8 +135,8 @@ CA certificate and hostname can be set: Once configured, socket can be used just like a regular TCP socket. Several samples in Zephyr use secure sockets for communication. For a sample use -see e.g. :ref:`echo-server sample application ` or -:ref:`HTTP GET sample application `. +see e.g. :zephyr:code-sample:`echo-server sample application ` or +:zephyr:code-sample:`HTTP GET sample application `. Secure Sockets options ====================== diff --git a/doc/connectivity/networking/api/socks5.rst b/doc/connectivity/networking/api/socks5.rst index a935fd9e439..ab72270394a 100644 --- a/doc/connectivity/networking/api/socks5.rst +++ b/doc/connectivity/networking/api/socks5.rst @@ -47,5 +47,5 @@ SOCKS5 Proxy Usage in MQTT ************************** For MQTT client, there is :c:func:`mqtt_client_set_proxy()` API that the -application can call to setup SOCKS5 proxy. See :ref:`mqtt-publisher-sample` -for usage example. +application can call to setup SOCKS5 proxy. See :zephyr:code-sample:`mqtt-publisher` +sample application for usage example. diff --git a/doc/connectivity/networking/api/system_mgmt.rst b/doc/connectivity/networking/api/system_mgmt.rst index 59aab16d3b7..a09ed2b2787 100644 --- a/doc/connectivity/networking/api/system_mgmt.rst +++ b/doc/connectivity/networking/api/system_mgmt.rst @@ -18,3 +18,4 @@ Network System Management traffic-class.rst net_pkt_filter.rst net_shell.rst + tls_credentials_shell.rst diff --git a/doc/connectivity/networking/api/tftp.rst b/doc/connectivity/networking/api/tftp.rst new file mode 100644 index 00000000000..36d9d2cf0bb --- /dev/null +++ b/doc/connectivity/networking/api/tftp.rst @@ -0,0 +1,9 @@ +.. _tftp_interface: + +TFTP +#### + +API Reference +************* + +.. doxygengroup:: tftp_client diff --git a/doc/connectivity/networking/api/thread.rst b/doc/connectivity/networking/api/thread.rst index 6dae56d5c12..155b794d7c1 100644 --- a/doc/connectivity/networking/api/thread.rst +++ b/doc/connectivity/networking/api/thread.rst @@ -38,5 +38,27 @@ Sample usage You can try using OpenThread with the Zephyr Echo server and Echo client samples, which provide out-of-the-box configuration for OpenThread. To enable OpenThread support in these samples, build them with ``overlay-ot.conf`` overlay config file. -See :ref:`sockets-echo-server-sample` and :ref:`sockets-echo-client-sample` for -details. +See :zephyr:code-sample:`sockets-echo-server` and :zephyr:code-sample:`sockets-echo-client` +samples for details. + +Thread related APIs +******************* + +OpenThread Driver API +======================== + +OpenThread L2 uses Zephyr's protocol agnostic IEEE 802.15.4 driver API +internally. This API is of interest to **driver developers** that want to +support OpenThread. + +The driver API is part of the :ref:`ieee802154_driver_api` subsystem and +documented there. + +OpenThread L2 Adaptation Layer API +================================== + +Zephyr's OpenThread L2 platform adaptation layer glues the external OpenThread +stack together with Zephyr's IEEE 802.15.4 protocol agnostic driver API. This +API is of interest to OpenThread L2 **subsystem contributors** only. + +.. doxygengroup:: openthread diff --git a/doc/connectivity/networking/api/tls_credentials_shell.rst b/doc/connectivity/networking/api/tls_credentials_shell.rst new file mode 100644 index 00000000000..69749a8f972 --- /dev/null +++ b/doc/connectivity/networking/api/tls_credentials_shell.rst @@ -0,0 +1,259 @@ +.. _tls_credentials_shell: + +TLS Credentials Shell +##################### + +The TLS Credentials shell provides a command-line interface for managing installed TLS credentials. + +Commands +******** + +.. _tls_credentials_shell_buf_cred: + +Buffer Credential (``buf``) +=========================== + +Buffer data incrementaly into the credential buffer so that it can be added using the :ref:`tls_credentials_shell_add_cred` command. + +Alternatively, clear the credential buffer. + +Usage +----- + +To append ```` to the credential buffer, use: + +.. code-block:: shell + + cred buf + +Use this as many times as needed to load the full credential into the credential buffer, then use the :ref:`tls_credentials_shell_add_cred` command to store it. + +To clear the credential buffer, use: + +.. code-block:: shell + + cred buf clear + +Arguments +--------- + +.. csv-table:: + :header: "Argument", "Description" + :widths: 15 85 + + "````", "Text data to be appended to credential buffer. It can be either text, or base64-encoded binary. See :ref:`tls_credentials_shell_add_cred` and :ref:`tls_credentials_shell_data_formats` for details." + +.. _tls_credentials_shell_add_cred: + +Add Credential (``add``) +========================= + +Add a TLS credential to the TLS Credential store. + +Credential contents can be provided in-line with the call to ``cred add``, or will otherwise be sourced from the credential buffer. + +Usage +----- + +To add a TLS credential using the data from the credential buffer, use: + +.. code-block:: shell + + cred add + +To add a TLS credential using data provided with the same command, use: + +.. code-block:: shell + + cred add + + +Arguments +--------- + +.. csv-table:: + :header: "Argument", "Description" + :widths: 15 85 + + "````", "The sectag to use for the new credential. Can be any non-negative integer." + "````", "The type of credential to add. See :ref:`tls_credentials_shell_cred_types` for valid values." + "````", "Reserved. Must always be ``DEFAULT`` (case-insensitive)." + "````", "Specifies the storage format of the provided credential. See :ref:`tls_credentials_shell_data_formats` for valid values." + "````", "If provided, this argument will be used as the credential data, instead of any data in the credential buffer. Can be either text, or base64-encoded binary." + +.. _tls_credentials_shell_del_cred: + +Delete Credential (``del``) +=========================== + +Delete a specified credential from the credential store. + +Usage +----- + +To delete a credential matching a specified sectag and credential type (if it exists), use: + +.. code-block:: shell + + cred del + +Arguments +--------- + +.. csv-table:: + :header: "Argument", "Description" + :widths: 15 85 + + "````", "The sectag of the credential to delete. Can be any non-negative integer." + "````", "The type of credential to delete. See :ref:`tls_credentials_shell_cred_types` for valid values." + +.. _tls_credentials_shell_get_cred: + +Get Credential Contents (``get``) +================================= + +Retrieve and print the contents of a specified credential. + +Usage +----- + +To retrieve and print a credential matching a specified sectag and credential type (if it exists), use: + +.. code-block:: shell + + cred get + +Arguments +--------- + +.. csv-table:: + :header: "Argument", "Description" + :widths: 15 85 + + "````", "The sectag of the credential to get. Can be any non-negative integer." + "````", "The type of credential to get. See :ref:`tls_credentials_shell_cred_types` for valid values." + "````", "Specifies the retrieval format for the provided credential. See :ref:`tls_credentials_shell_data_formats` for valid values." + +.. _tls_credentials_shell_list_cred: + +List Credentials (``list``) +=========================== + +List TLS credentials in the credential store. + +Usage +----- + +To list all available credentials, use: + +.. code-block:: shell + + cred list + +To list all credentials with a specified sectag, use: + +.. code-block:: shell + + cred list + +To list all credentials with a specified credential type, use: + +.. code-block:: shell + + cred list any + +To list all credentials with a specified credential type and sectag, use: + +.. code-block:: shell + + cred list + + +Arguments +--------- + +.. csv-table:: + :header: "Argument", "Description" + :widths: 15 85 + + "````", "Optional. If provided, only list credentials with this sectag. Pass ``any`` or omit to allow any sectag. Otherwise, can be any non-negative integer." + "````", "Optional. If provided, only list credentials with this credential type. Pass ``any`` or omit to allow any credential type. Otherwise, see :ref:`tls_credentials_shell_cred_types` for valid values." + + +Output +------ + +The command outputs all matching credentials in the following (CSV-compliant) format: + +.. code-block:: shell + + ,,, + +Where: + +.. csv-table:: + :header: "Symbol", "Value" + :widths: 15 85 + + "````", "The sectag of the listed credential. A non-negative integer." + "````", "Credential type short-code (see :ref:`tls_credentials_shell_cred_types` for details) of the listed credential." + "````", "A string digest representing the credential contents. The exact nature of this digest may vary depending on credentials storage backend, but currently for all backends this is a base64 encoded SHA256 hash of the raw credential contents (so different storage formats for essentially identical credentials will have different digests)." + "````", "Status code indicating success or failure with generating a digest of the listed credential. 0 if successful, negative error code specific to the storage backend otherwise. Lines for which status is not zero will be printed with error formatting." + +After the list is printed, a final summary of the found credentials will be printed in the form: + +.. code-block:: shell + + credentials found. + +Where `` is the number of credentials found, and is zero if none are found. + +.. _tls_credentials_shell_cred_types: + +Credential Types +**************** + +The following keywords (case-insensitive) may be used to specify a credential type: + +.. csv-table:: + :header: "Keyword(s)", "Meaning" + :widths: 15 85 + + "``CA_CERT``, ``CA``", "A trusted CA certificate." + "``SERVER_CERT``, ``SELF_CERT``, ``CLIENT_CERT``, ``CLIENT``, ``SELF``, ``SERV``", "Self or server certificate." + "``PRIVATE_KEY``, ``PK``", "A private key." + "``PRE_SHARED_KEY``, ``PSK``", "A pre-shared key." + "``PRE_SHARED_KEY_ID``, ``PSK_ID``", "ID for pre-shared key." + +.. _tls_credentials_shell_data_formats: + +Storage/Retrieval Formats +************************* + +The :ref:`tls_credentials ` module treats stored credentials as arbitrary binary buffers. + +For convenience, the TLS credentials shell offers four formats for providing and later retrieving these buffers using the shell. + +These formats and their (case-insensitive) keywords are as follows: + +.. csv-table:: + :header: "Keyword", "Meaning", "Behavior during storage (``cred add``)", "Behavior during retrieval (``cred get``)" + :widths: 3, 32, 34, 34 + + "``BIN``", "Credential is handled by shell as base64 and stored without NULL termination.", "Data entered into shell will be decoded from base64 into raw binary before storage. No terminator will be appended.", "Stored data will be encoded into base64 before being printed." + "``BINT``", "Credential is handled by shell as base64 and stored with NULL termination.", "Data entered into shell will be decoded from base64 into raw binary and a NULL terminator will be appended before storage.", "NULL terminator will be truncated from stored data before said data is encoded into base64 and then printed." + "``STR``", "Credential is handled by shell as literal string and stored without NULL termination.", "Text data entered into shell will be passed into storage as-written, without a NULL terminator.", "Stored data will be printed as text. Non-printable characters will be printed as ``?``" + "``STRT``", "Credential is handled by shell as literal string and stored with NULL-termination.", "Text data entered into shell will be passed into storage as-written, with a NULL terminator.", "NULL terminator will be truncated from stored data before said data is printed as text. Non-printable characters will be printed as ``?``" + +The ``BIN`` format can be used to install credentials of any type, since base64 can be used to encode any concievable binary buffer. +The remaining three formats are provided for convenience in special use-cases. + +For example: + +- To install printable pre-shared-keys, use ``STR`` to enter the PSK without first encoding it. + This ensures it is stored without a NULL terminator. +- To install DER-formatted X.509 certificates (or other raw-binary credentials, such as non-printable PSKs) base64-encode the binary and use the ``BIN`` format. +- To install PEM-formatted X.509 certificates or certificate chains, base64 encode the full PEM string (including new-lines and ``----BEGIN X ----`` / ``----END X----`` markers), and then use the ``BINT`` format to make sure the stored string is NULL-terminated. + This is required because Zephyr does not support multi-line strings in the shell. + Otherwise, the ``STRT`` format could be used for this purpose without base64 encoding. + It is possible to use ``BIN`` instead if you manually encode a NULL terminator into the base64. diff --git a/doc/connectivity/networking/api/tsn.rst b/doc/connectivity/networking/api/tsn.rst index 50e594c4a71..c9d00cfcc5c 100644 --- a/doc/connectivity/networking/api/tsn.rst +++ b/doc/connectivity/networking/api/tsn.rst @@ -7,4 +7,5 @@ Time Sensitive Networking :maxdepth: 1 gptp.rst + net_time.rst ptp_time.rst diff --git a/doc/connectivity/networking/api/vlan.rst b/doc/connectivity/networking/api/vlan.rst index b0fe35b79a4..efa6d60b8b0 100644 --- a/doc/connectivity/networking/api/vlan.rst +++ b/doc/connectivity/networking/api/vlan.rst @@ -37,7 +37,7 @@ function. The VLAN tagging for a given network interface can be disabled by a :c:func:`net_eth_vlan_disable` function. The application needs to configure the VLAN network interface itself, such as setting the IP address, etc. -See also the :ref:`VLAN sample application ` for API usage +See also the :zephyr:code-sample:`VLAN sample application ` for API usage example. The source code for that sample application can be found at :zephyr_file:`samples/net/vlan`. diff --git a/doc/connectivity/networking/api/zperf.rst b/doc/connectivity/networking/api/zperf.rst index 4f6674679d2..fe09823c057 100644 --- a/doc/connectivity/networking/api/zperf.rst +++ b/doc/connectivity/networking/api/zperf.rst @@ -22,7 +22,7 @@ are missing. LAST PACKET NOT RECEIVED!!! zperf can be enabled in any application, a dedicated sample is also present -in Zephyr. See :ref:`zperf sample application ` for details. +in Zephyr. See :zephyr:code-sample:`zperf sample application ` for details. Sample Usage ************ diff --git a/doc/connectivity/networking/armfvp_user_networking_setup.rst b/doc/connectivity/networking/armfvp_user_networking_setup.rst index c0aeb3a0693..618a33a8242 100644 --- a/doc/connectivity/networking/armfvp_user_networking_setup.rst +++ b/doc/connectivity/networking/armfvp_user_networking_setup.rst @@ -33,7 +33,7 @@ Using Arm FVP User Mode Networking with Zephyr Arm FVP user mode networking can be enabled in any applications and it doesn't need any configurations on the host system. This feature has been enabled in DHCPv4 client sample. -See :ref:`Sample DHCPv4 client application ` +See :zephyr:code-sample:`dhcpv4-client` sample application. Limitations ************* diff --git a/doc/connectivity/networking/conn_mgr/figures/.gitignore b/doc/connectivity/networking/conn_mgr/figures/.gitignore new file mode 100644 index 00000000000..e73bdb62608 --- /dev/null +++ b/doc/connectivity/networking/conn_mgr/figures/.gitignore @@ -0,0 +1,2 @@ +# Ignore drawio backup files +.$* diff --git a/doc/connectivity/networking/conn_mgr/figures/integration_diagram_detailed.drawio b/doc/connectivity/networking/conn_mgr/figures/integration_diagram_detailed.drawio new file mode 100644 index 00000000000..5585c18149a --- /dev/null +++ b/doc/connectivity/networking/conn_mgr/figures/integration_diagram_detailed.drawio @@ -0,0 +1,205 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/connectivity/networking/conn_mgr/figures/integration_diagram_detailed.svg b/doc/connectivity/networking/conn_mgr/figures/integration_diagram_detailed.svg new file mode 100644 index 00000000000..0838db0396d --- /dev/null +++ b/doc/connectivity/networking/conn_mgr/figures/integration_diagram_detailed.svg @@ -0,0 +1,3 @@ + + +
    network
    readiness
    events
    network...
    Application
    Application






    Zephyr ifaces (bound)



    Zephyr ifaces (bound)...
    iface
    iface
    iface
    iface
    iface
    iface
    Zephyr ifaces (unbound)



    Zephyr ifaces (unbound)...
    iface
    iface
    iface
    iface
    iface
    iface
    binding
    binding
    binding
    binding
    binding
    binding
    Connectivity
    Implementation
    (LTE)
    Connectivity...
    Connectivity
    Implementation
    (Wi-Fi)
    Connectivity...
    Connectivity
    Bindings
    Connectivi...
    Zephyr
    ifaces
    Zephy...
    LTE L2
    LTE L2
    network
    commands
    network...
    iface state
    change events
    iface state...
    Wi-Fi L2
    Wi-Fi L2
    iface commands and events,
    binding state updates,
    network commands
    iface commands and events,...
    iface commands
    and events
    iface commands...
    iface commands
    and events
    iface commands...
    Connectivity Control
    Connectivity Control
    Connectivity Monitoring
    Connectivity Monitoring
    network
    commands
    network...
    Connection Manager
    Connection Manager
    Text is not SVG - cannot display
    \ No newline at end of file diff --git a/doc/connectivity/networking/conn_mgr/figures/integration_diagram_simplified.drawio b/doc/connectivity/networking/conn_mgr/figures/integration_diagram_simplified.drawio new file mode 100644 index 00000000000..4796e986b1e --- /dev/null +++ b/doc/connectivity/networking/conn_mgr/figures/integration_diagram_simplified.drawio @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/connectivity/networking/conn_mgr/figures/integration_diagram_simplified.svg b/doc/connectivity/networking/conn_mgr/figures/integration_diagram_simplified.svg new file mode 100644 index 00000000000..1a65c73aedc --- /dev/null +++ b/doc/connectivity/networking/conn_mgr/figures/integration_diagram_simplified.svg @@ -0,0 +1,3 @@ + + +
    network
    readiness
    events
    network...
    Application
    Application
    L2
    L2
    connectivity
    commands
    connectivity...
    iface commands
    and events
    iface commands...
    iface commands
    and events
    iface commands...
    Connectivity Control
    Connectivity Control
    Connectivity Monitoring
    Connectivity Monitoring
    network
    commands
    network...
    Connection Manager
    Connection Manager
    Zephyr ifaces
    Zephyr ifaces
    Connectivity Implementations
    Connectivity Implementat...
    connectivity
    commands
    and events
    connectivity...
    iface events
    iface events
    Text is not SVG - cannot display
    \ No newline at end of file diff --git a/doc/connectivity/networking/conn_mgr/implementation.rst b/doc/connectivity/networking/conn_mgr/implementation.rst new file mode 100644 index 00000000000..932ec7668d2 --- /dev/null +++ b/doc/connectivity/networking/conn_mgr/implementation.rst @@ -0,0 +1,475 @@ +.. _conn_mgr_impl: + +Connectivity Implementations +############################ + +.. _conn_mgr_impl_overview: + +Overview +======== + +Connectivity implementations are technology-specific modules that allow specific Zephyr ifaces to support :ref:`Connectivity Control `. +They are responsible for translating generic :ref:`connectivity control API ` calls into hardware-specific operations. +They are also responsible for implementing standardized :ref:`persistence and timeout ` behaviors. + +See the :ref:`implementation guidelines ` for details on writing conformant connectivity implementations. + +.. _conn_mgr_impl_architecture: + +Architecture +============ + +The :ref:`implementation API ` allows connectivity implementations to be :ref:`defined ` at build time using :c:macro:`CONN_MGR_CONN_DEFINE`. + +This creates a static instance of the :c:struct:`conn_mgr_conn_impl` struct, which then stores a reference to the passed in :c:struct:`conn_mgr_conn_api` struct (which should be populated with implementation callbacks). + +Once defined, you can reference implementations by name and bind them to any unbound iface using :c:macro:`CONN_MGR_BIND_CONN`. +Make sure not to accidentally bind two connectivity implementations to a single iface. + +Once the iface is bound, :ref:`connectivity control API ` functions can be called on the iface, and they will be translated to the corresponding implementation functions in :c:struct:`conn_mgr_conn_api`. + +Binding an iface does not directly modify its :c:struct:`iface struct `. + +Instead, an instance of :c:struct:`conn_mgr_conn_binding` is created and appended an internal :ref:`iterable section `. + +This binding structure will contain a reference to the bound iface, the connectivity implementation it is bound to, as well as a pointer to a per-iface :ref:`context pointer `. + +This iterable section can then be iterated over to find out what (if any) connectivity implementation has been bound to a given iface. +This search process is used by most of the functions in the :ref:`connectivity control API `. +As such, these functions should be called sparingly, due to their relatively high search cost. + +A single connectivity implementation may be bound to multiple ifaces. +See :ref:`conn_mgr_impl_guidelines_no_instancing` for more details. + +.. _conn_mgr_integration_diagram_detailed: + +.. figure:: figures/integration_diagram_detailed.svg + :alt: A detailed view of how Connection Manager integrates with Zephyr and the application. + :figclass: align-center + + A detailed view of how Connection Manager integrates with Zephyr and the application. + + See :ref:`here ` for a simplified version. + +.. _conn_mgr_impl_ctx: + +Context Pointer +=============== + +Since a single connectivity implementation may be shared by several Zephyr ifaces, each binding instantiates a context container (of :ref:`configurable type `) unique to that binding. +Each binding is then instantiated with a reference to that container, which implementations can then use to access per-iface state information. + +See also :ref:`conn_mgr_impl_guidelines_binding_access` and :ref:`conn_mgr_impl_guidelines_no_instancing`. + +.. _conn_mgr_impl_defining: + +Defining an implementation +========================== + +A connectivity implementation may be defined as follows: + +.. code-block:: c + + /* Create the API implementation functions */ + int my_connect_impl(struct conn_mgr_conn_binding *const binding) { + /* Cause your underlying technology to associate */ + } + int my_disconnect_impl(struct conn_mgr_conn_binding *const binding) { + /* Cause your underlying technology to disassociate */ + } + void my_init_impl(struct conn_mgr_conn_binding *const binding) { + /* Perform any required initialization for your underlying technology */ + } + + /* Declare the API struct */ + static struct conn_mgr_conn_api my_impl_api = { + .connect = my_connect_impl, + .disconnect = my_disconnect_impl, + .init = my_init_impl, + /* ... so on */ + }; + + /* Define the implementation (named MY_CONNECTIVITY_IMPL) */ + CONN_MGR_CONN_DEFINE(MY_CONNECTIVITY_IMPL, &my_impl_api); + +.. note:: + This does not work unless you also :ref:`declare the context pointer type `. + +.. _conn_mgr_impl_declaring: + +Declaring an implementation publicly +==================================== + +Once defined, you can make a connectivity implementation available to other compilation units by declaring it (in a header file) as follows: + +.. code-block:: c + :caption: ``my_connectivity_header.h`` + + CONN_MGR_CONN_DECLARE_PUBLIC(MY_CONNECTIVITY_IMPL); + +The header file that contains this declaration must be included in any compilation units that need to reference the implementation. + +.. _conn_mgr_impl_declaring_ctx: + +Declaring a context type +======================== + +For :c:macro:`CONN_MGR_CONN_DEFINE` to work, you must declare a corresponding context pointer type. +This is because all connectivity bindings contain a :ref:`conn_mgr_impl_ctx` of their associated context pointer type. + +If you are using :c:macro:`CONN_MGR_CONN_DECLARE_PUBLIC`, declare this type alongside the declaration: + +.. code-block:: c + :caption: ``my_connectivity_impl.h`` + + #define MY_CONNECTIVITY_IMPL_CTX_TYPE struct my_context_type * + CONN_MGR_CONN_DECLARE_PUBLIC(MY_CONNECTIVITY_IMPL); + +Then, make sure to include the header file before calling :c:macro:`CONN_MGR_CONN_DEFINE`: + +.. code-block:: c + :caption: ``my_connectivity_impl.c`` + + #include "my_connectivity_impl.h" + + CONN_MGR_CONN_DEFINE(MY_CONNECTIVITY_IMPL, &my_impl_api); + +Otherwise, it is sufficient to simply declare the context pointer type immediately before the call to :c:macro:`CONN_MGR_CONN_DEFINE`: + +.. code-block:: c + + #define MY_CONNECTIVITY_IMPL_CTX_TYPE struct my_context_type * + CONN_MGR_CONN_DEFINE(MY_CONNECTIVITY_IMPL, &my_impl_api); + +.. note:: + + Naming is important. + Your context pointer type declaration must use the same name as your implementation declaration, but with ``_CTX_TYPE`` appended. + + In the previous example, the context type is named ``MY_CONNECTIVITY_IMPL_CTX_TYPE``, because ``MY_CONNECTIVITY_IMPL`` was used as the connectivity implementation name. + +If your connectivity implementation does not need a context pointer, simply declare the type as void: + +.. code-block:: c + + #define MY_CONNECTIVITY_IMPL_CTX_TYPE void * + +.. _conn_mgr_impl_binding: + +Binding an iface to an implementation +===================================== + +A defined connectivity implementation may be bound to an iface by calling :c:macro:`CONN_MGR_BIND_CONN` anywhere after the iface's device definition: + +.. code-block:: c + + /* Define an iface */ + NET_DEVICE_INIT(my_iface, + /* ... the specifics here don't matter ... */ + ); + + /* Now bind MY_CONNECTIVITY_IMPL to that iface -- + * the name used should match with the above + */ + CONN_MGR_BIND_CONN(my_iface, MY_CONNECTIVITY_IMPL); + +.. _conn_mgr_impl_guidelines: + +Connectivity implementation guidelines +====================================== + +Rather than implement all features centrally, Connection Manager relies on each connectivity implementation to implement many behaviors and features individually. + +This approach allows Connection Manager to remain lean, and allows each connectivity implementation to choose the most appropriate approach to these behaviors for itself. +However, it relies on trust that all connectivity implementations will faithfully implement the features that have been delegated to them. + +To maintain consistency between all connectivity implementations, observe the following guidelines when writing your own implementation: + +.. _conn_mgr_impl_guidelines_timeout_persistence: + +*Completely implement timeout and persistence* +---------------------------------------------- + +All connectivity implementations must offer complete support for :ref:`timeout and persistence `, such that a user can disable or enable these features, regardless of the inherent behavior of the underlying technology. +In other words, no matter how the underlying technology behaves, your implementation must make it appear to the end user to behave exactly as specified in the :ref:`conn_mgr_control_persistence_timeouts` section. + +See :ref:`conn_mgr_impl_timeout_persistence` for a detailed technical discussion on implementing timeouts and persistence. + +.. _conn_mgr_impl_guidelines_conformity: + +*Conform to API specifications* +------------------------------- + +Each :c:struct:`implementation API function ` you implement should behave as-described in the corresponding connectivity control API function. + +For example, your implementation of :c:member:`conn_mgr_conn_api.connect` should conform to the behavior described for :c:func:`conn_mgr_if_connect`. + +.. _conn_mgr_impl_guidelines_preconfig: + +*Allow connectivity pre-configuration* +-------------------------------------- + +Connectivity implementations should provide means for applications to pre-configure all necessary connection parameters (for example, network SSID, or PSK, if applicable), before the call to :c:func:`conn_mgr_if_connect`. +It should not be necessary to provide this information as part of, or following the :c:func:`conn_mgr_if_connect` call, although implementations :ref:`should await this information if it is not provided `. + +.. _conn_mgr_impl_guidelines_await_config: + +*Await valid connectivity configuration* +---------------------------------------- + +If network association fails because the application pre-configured invalid connection parameters, or did not configure connection parameters at all, this should be treated as a network failure. + +In other words, the connectivity implementation should not give up on the connection attempt, even if valid connection parameters have not been configured. + +Instead, the connectivity implementation should asynchronously wait for valid connection parameters to be configured, either indefinitely, or until the configured :ref:`connectivity timeout ` elapses. + +.. _conn_mgr_impl_guidelines_iface_state_reporting: + +*Implement iface state reporting* +--------------------------------- + +All connectivity implementations must keep bound iface state up to date. + +To be specific: + +* Set the iface to dormant, carrier-down, or both during :c:member:`binding init `. + + * See :ref:`net_if_interface_state_management` for details regarding iface carrier and dormant states. + +* Update dormancy and carrier state so that the iface is non-dormant and carrier-up whenever (and only when) association is complete and connectivity is ready. +* Set the iface either to dormant or to carrier-down as soon as interruption of service is detected. + + * It is acceptable to gate this behind a small timeout (separate from the connection timeout) for network technologies where service is commonly intermittent. + +* If the technology also handles IP assignment, ensure those IP addresses are :ref:`assigned to the iface `. + +.. note:: + + iface state updates do not necessarily need to be performed directly by connectivity implementations. + + For instance: + + * IP assignment is not necessary if :ref:`DHCP ` is used for the iface. + * The connectivity implementation does not need to update iface dormancy if the underlying :ref:`L2 implementation ` already does so. + +.. _conn_mgr_impl_guidelines_iface_state_writeonly: + +*Do not use iface state as implementation state* +------------------------------------------------ + +Zephyr ifaces may be accessed from other threads without respecting the binding mutex. +As such, Zephyr iface state may change unpredictably during connectivity implementation callbacks. + +Therefore, do not base implementation behaviors on iface state. + +Keep iface state updated to reflect network availability, but do not read iface state for any purpose. + +If you need to keep track of dormancy or IP assignment, use a separate state variable stored in the :ref:`context pointer `. + +.. _conn_mgr_impl_guidelines_non_interference: + +*Remain non-interferent* +------------------------ + +Connectivity implementations should not prevent applications from interacting directly with associated technology-specific APIs. + +In other words, it should be possible for an application to directly use your underlying technology without breaking your connectivity implementation. + +If exceptions to this are absolutely necessary, they should be constrained to specific API calls and should be documented. + +.. note:: + + While connectivity implementations must not break, it is acceptable for implementations to have potentially unexpected behavior if applications attempt to directly control the association state. + + For instance, if an application directly instructs an underlying technology to dissassociate, it would be acceptable for the connectivity implementation to interpret this as an unexpected connection loss and immediately attempt to re-associate. + +.. _conn_mgr_impl_guidelines_non_blocking: + +*Remain non-blocking* +--------------------- + +All connectivity implementation callbacks should be non-blocking. + +For instance, calls to :c:member:`conn_mgr_conn_api.connect` should initiate a connection process and return immediately. + +One exception is :c:member:`conn_mgr_conn_api.init`, whose implementations are permitted to block. + +However, bear in mind that blocking during this callback will delay system init, so still consider offloading time-consuming tasks to a background thread. + +.. _conn_mgr_impl_guidelines_immediate_api_readiness: + +*Make API immediately ready* +---------------------------- + +Connectivity implementations must be ready to receive API calls immediately after :c:member:`conn_mgr_conn_api.init`. + +For instance, a call to :c:member:`conn_mgr_conn_api.connect` must eventually lead to an association attempt, even if called immediately after :c:member:`conn_mgr_conn_api.init`. + +If the underlying technology cannot be made ready for connect commands immediately when :c:member:`conn_mgr_conn_api.init` is called, calls to :c:member:`conn_mgr_conn_api.connect` must be queued in a non-blocking fashion, and then executed later when ready. + +.. _conn_mgr_impl_guidelines_context_pointer: + +*Do not store state information outside the context pointer* +------------------------------------------------------------ + +Connection Manager provides a context pointer to each binding. + +Connectivity implementations should store all state information in this context pointer. + +The only exception is connectivity implementations that are meant to be bound to only a single iface. +Such implementations may use statically declared state instead. + +See also :ref:`conn_mgr_impl_guidelines_no_instancing`. + +.. _conn_mgr_impl_guidelines_iface_access: + +*Access ifaces only through binding structs* +-------------------------------------------- + +Do not use statically declared ifaces or externally acquire references to ifaces. + +For example, do not use :c:func:`net_if_get_default` under the assumption that the bound iface will be the default iface. + +Instead, always use the :c:member:`iface pointer ` provided by the relevant :c:struct:`binding struct `. +See also :ref:`conn_mgr_impl_guidelines_binding_access`. + +.. _conn_mgr_impl_guidelines_bindings_optional: + +*Make implementations optional at compile-time* +----------------------------------------------- + +Connectivity implementations should provide a Kconfig option to enable or disable the implementation without affecting bound iface availability. + +In other words, it should be possible to configure builds that include Connectivity Manager, as well as the iface that would have been bound to the implementation, but not the implementation itself, nor its binding. + +.. _conn_mgr_impl_guidelines_no_instancing: + +*Do not instance implementations* +--------------------------------- + +Do not declare a separate connectivity implementation for every iface you are going to bind to. + +Instead, bind one global connectivity implementation to all of your ifaces, and use the context pointer to store state relevant to individual ifaces. + +See also :ref:`conn_mgr_impl_guidelines_binding_access` and :ref:`conn_mgr_impl_guidelines_iface_access`. + +.. _conn_mgr_impl_guidelines_binding_access: + +*Do not access bindings without locking them* +--------------------------------------------- + +Bindings may be accessed and modified at random by multiple threads, so modifying or reading from a binding without first :c:func:`locking it ` may lead to unpredictable behavior. + +This applies to all descendents of the binding, including anything in the :ref:`context container `. + +Make sure to :c:func:`unlock ` the binding when you are done accessing it. + +.. note:: + + A possible exception to this rule is if the resource in question is inherently thread-safe. + + However, be careful taking advantage of this exception. + It may still be possible to create a race condition, for instance when accessing multiple thread-safe resources simultaneously. + + Therefore, it is recommended to simply always lock the binding, whether or not the resource being accessed is inherently thread-safe. + +.. _conn_mgr_impl_guidelines_support_builtins: + +*Do not disable built-in features* +---------------------------------- + +Do not attempt to prevent the use of built-in features (such as :ref:`conn_mgr_control_persistence_timeouts` or :ref:`conn_mgr_control_automations`). + +All connectivity implementations must fully support these features. +Implementations must not attempt to force certain features to be always enabled or always disabled. + +.. _conn_mgr_impl_guidelines_trigger_events: + +*Trigger connectivity control events* +------------------------------------- + +Connectivity control :ref:`network management ` events are not triggered automatically by Connection Manager. + +Connectivity implementations must trigger these events themselves. + +Trigger :c:macro:`NET_EVENT_CONN_CMD_IF_TIMEOUT` when a connection :ref:`timeout ` occurs. +See :ref:`conn_mgr_control_events_timeout` for details. + +Trigger :c:macro:`NET_EVENT_CONN_IF_FATAL_ERROR` when a fatal (non-recoverable) connection error occurs. +See :ref:`conn_mgr_control_events_fatal_error` for details. + +See :ref:`net_mgmt_interface` for details on firing network management events. + +.. _conn_mgr_impl_timeout_persistence: + +Implementing timeouts and persistence +===================================== + +First, see :ref:`conn_mgr_control_persistence_timeouts` for a high-level description of the expected behavior of timeouts and persistence. + +Connectivity implementations must fully conform to that description, regardless of the behavior of the underlying connectivity technology. + +Sometimes this means writing extra logic in the connectivity implementation to fake certain behaviors. +The following sections discuss various common edge-cases and nuances and how to handle them. + +.. _conn_mgr_impl_tp_inherent_persistence: + +*Inherently persistent technologies* +------------------------------------ + +If the underlying technology automatically attempts to reconnect or retry connection after connection loss or failure, the connectivity implementation must manually cancel such attempts when they are in conflict with timeout or persistence settings. + +For example: + + * If the underlying technology automatically attempts to reconnect after losing connection, and persistence is disabled for the iface, the connectivity implementation should immediately cancel this reconnection attempt. + * If a connection attempt times out on an iface whose underlying technology does not have a built-in timeout, the connectivity implementation must simulate a timeout by cancelling the connection attempt manually. + +.. _conn_mgr_impl_tp_inherent_nonpersistence: + +*Technologiess that give up on connection attempts* +--------------------------------------------------- + +If the underlying technology has no mechanism to retry connection attempts, or would give up on them before the user-configured timeout, or would not reconnect after connection loss, the connectivity implementation must manually re-request connection to counteract these deviances. + +* If your underlying technology is not persistent, you must manually trigger reconnect attempts when persistence is enabled. +* If your underlying technology does not support a timeout, you must manually cancel connection attempts if the timeout is enabled. +* If your underlying technology forces a timeout, you must manually trigger a new connection attempts if that timeout is shorter than the Connection Manager timeout. + +.. _conn_mgr_impl_tp_assoc_retry: + +*Technologies with association retry* +------------------------------------- + +Many underlying technologies do not usually associate in a single attempt. + +Instead, these underlying technologies may need to make multiple back-to-back association attempts in a row, usually with a small delay. + +In these situations, the connectivity implementation should treat this series of back-to-back association sub-attempts as a single unified connection attempt. + +For instance, after a sub-attempt failure, persistence being disabled should not prevent further sub-attempts, since they all count as one single overall connection attempt. +See also :ref:`conn_mgr_impl_tp_persistence_during_connect`. + +At which point a series of failed sub-attempts should be considered a failure of the connection attempt as a whole is up to each implementation to decide. + +If the connection attempt crosses this threshold, but the configured timeout has not yet elapsed, or there is no timeout, sub-attempts should continue. + +.. _conn_mgr_impl_tp_persistence_during_connect: + +*Persistence during connection attempts* +---------------------------------------- + +Persistence should not affect any aspect of implementation behavior during a connection attempt. +Persistence should only affect whether or not connection attempts are automatically triggered after a connection loss. + +The configured timeout should fully determine whether connection retry should be performed. + +.. _conn_mgr_impl_api: + +Implementation API +================== + +Include header file :file:`include/zephyr/net/conn_mgr_connectivity_impl.h` to access these. + +Only for use by connectivity implementations. + +.. doxygengroup:: conn_mgr_connectivity_impl diff --git a/doc/connectivity/networking/conn_mgr/index.rst b/doc/connectivity/networking/conn_mgr/index.rst new file mode 100644 index 00000000000..75129877fc9 --- /dev/null +++ b/doc/connectivity/networking/conn_mgr/index.rst @@ -0,0 +1,10 @@ +.. _conn_mgr_docs: + +Connection Manager +################## + +.. toctree:: + :maxdepth: 1 + + main.rst + implementation.rst diff --git a/doc/connectivity/networking/conn_mgr/main.rst b/doc/connectivity/networking/conn_mgr/main.rst new file mode 100644 index 00000000000..675be831418 --- /dev/null +++ b/doc/connectivity/networking/conn_mgr/main.rst @@ -0,0 +1,446 @@ +.. _conn_mgr_overview: + +Overview +######## + +Connection Manager is a collection of optional Zephyr features that aim to allow applications to monitor and control connectivity (access to IP-capable networks) with minimal concern for the specifics of underlying network technologies. + +Using Connection Manager, applications can use a single abstract API to control network association and monitor Internet access, and avoid excessive use of technology-specific boilerplate. + +This allows an application to potentially support several very different connectivity technologies (for example, Wi-Fi and LTE) with a single codebase. + +Applications can also use Connection Manager to generically manage and use multiple connectivity technologies simultaneously. + +Structure +========= + +Connection Manager is split into the following two subsystems: + +* :ref:`Connectivity monitoring ` (header file :file:`include/zephyr/net/conn_mgr_monitoring.h`) monitors all available :ref:`Zephyr network interfaces (ifaces) ` and triggers :ref:`network management ` events indicating when IP connectivity is gained or lost. + +* :ref:`Connectivity control ` (header file :file:`include/zephyr/net/conn_mgr_connectivity.h`) provides an abstract API for controlling iface network association. + +.. _conn_mgr_integration_diagram_simple: + +.. figure:: figures/integration_diagram_simplified.svg + :alt: A simplified view of how Connection Manager integrates with Zephyr and the application. + :figclass: align-center + + A simplified view of how Connection Manager integrates with Zephyr and the application. + + See :ref:`here ` for a more detailed version. + +.. _conn_mgr_monitoring: + +Connectivity monitoring +####################### + +Connectivity monitoring tracks all available ifaces (whether or not they support :ref:`Connectivity control `) as they transition through various :ref:`operational states ` and acquire or lose assigned IP addresses. + +Each available iface is considered ready if it meets the following criteria: + +* The iface is admin-up + + * This means the iface has been instructed to become operational-up (ready for use). This is done by a call to :c:func:`net_if_up`. + +* The iface is oper-up + + * This means the interface is completely ready for use; It is online, and if applicable, has associated with a network. + * See :ref:`net_if_interface_state_management` for details. + +* The iface has at least one assigned IP address + + * Both IPv4 and IPv6 addresses are acceptable. + This condition is met as soon as one or both of these is assigned. + * See :ref:`net_if_interface` for details on iface IP assignment. + +* The iface has not been ignored + + * Ignored ifaces are always treated as unready. + * See :ref:`conn_mgr_monitoring_ignoring_ifaces` for more details. + +.. note:: + + Typically, iface state and IP assignment are updated either by the iface's :ref:`L2 implementation ` or bound :ref:`connectivity implementation `. + + See :ref:`conn_mgr_impl_guidelines_iface_state_reporting` for details. + +A ready iface ceases to be ready the moment any of the above conditions is lost. + +When at least one iface is ready, the :c:macro:`NET_EVENT_L4_CONNECTED` :ref:`network management ` event is triggered, and IP connectivity is said to be ready. + +Afterwards, ifaces can become ready or unready without firing additional events, so long as there always remains at least one ready iface. + +When there are no longer any ready ifaces left, the :c:macro:`NET_EVENT_L4_DISCONNECTED` :ref:`network management ` event is triggered, and IP connectivity is said to be unready. + +.. _conn_mgr_monitoring_usage: + +Usage +===== + +Connectivity monitoring is enabled if the :kconfig:option:`CONFIG_NET_CONNECTION_MANAGER` Kconfig option is enabled. + +To receive connectivity updates, create and register a listener for the :c:macro:`NET_EVENT_L4_CONNECTED` and :c:macro:`NET_EVENT_L4_DISCONNECTED` :ref:`network management ` events: + +.. code-block:: c + + /* Callback struct where the callback will be stored */ + struct net_mgmt_event_callback l4_callback; + + /* Callback handler */ + static void l4_event_handler(struct net_mgmt_event_callback *cb, + uint32_t event, struct net_if *iface) + { + if (event == NET_EVENT_L4_CONNECTED) { + LOG_INF("Network connectivity gained!"); + } else if (event == NET_EVENT_L4_DISCONNECTED) { + LOG_INF("Network connectivity lost!"); + } + + /* Otherwise, it's some other event type we didn't register for. */ + } + + /* Call this before Connection Manager monitoring initializes */ + static void my_application_setup(void) + { + /* Configure the callback struct to respond to (at least) the L4_CONNECTED + * and L4_DISCONNECTED events. + * + * + * Note that the callback may also be triggered for events other than those specified here! + * (See the net_mgmt documentation) + */ + net_mgmt_init_event_callback( + &l4_callback, l4_event_handler, + NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED + ); + + /* Register the callback */ + net_mgmt_add_event_callback(&l4_callback); + } + +See :ref:`net_mgmt_listening` for more details on listening for net_mgmt events. + +.. note:: + To avoid missing initial connectivity events, you should register your listener(s) before Connection Manager monitoring initializes. + See :ref:`conn_mgr_monitoring_missing_notifications` for strategies to ensure this. + +.. _conn_mgr_monitoring_missing_notifications: + +Avoiding missed notifications +============================= + +Connectivity monitoring may trigger events immediately upon initialization. + +If your application registers its event listeners after connectivity monitoring initializes, it is possible to miss this first wave of events, and not be informed the first time network connectivity is gained. + +If this is a concern, your application should :ref:`register its event listeners ` before connectivity monitoring initializes. + +Connectivity monitoring initializes using the :c:macro:`SYS_INIT` ``APPLICATION`` initialization priority specified by the :kconfig:option:`CONFIG_NET_CONNECTION_MANAGER_MONITOR_PRIORITY` Kconfig option. + +You can register your callbacks before this initialization by using :c:macro:`SYS_INIT` with an earlier initialization priority than this value, for instance priority 0: + +.. code-block:: C + + static int my_application_setup(void) + { + /* Register callbacks here */ + return 0; + } + + SYS_INIT(my_application_setup, APPLICATION, 0); + +If this is not feasible, you can instead request that connectivity monitoring resend the latest connectivity events at any time by calling :c:func:`conn_mgr_mon_resend_status`: + +.. code-block:: C + + static void my_late_application_setup(void) + { + /* Register callbacks here */ + + /* Once done, request that events be re-triggered */ + conn_mgr_mon_resend_status(); + } + +.. _conn_mgr_monitoring_ignoring_ifaces: + +Ignoring ifaces +=============== + +Applications can request that ifaces be ignored by Connection Manager by calling :c:func:`conn_mgr_ignore_iface` with the iface to be ignored. + +Alternatively, an entire :ref:`L2 implementation ` can be ignored by calling :c:func:`conn_mgr_ignore_l2`. + +This has the effect of individually ignoring all the ifaces using that :ref:`L2 implementation `. + +While ignored, the iface is treated by Connection Manager as though it were unready for network traffic, no matter its actual state. + +This may be useful, for instance, if your application has configured one or more ifaces that cannot (or for whatever reason should not) be used to contact the wider Internet. + +:ref:`Bulk convenience functions ` optionally skip ignored ifaces. + +See :c:func:`conn_mgr_ignore_iface` and :c:func:`conn_mgr_watch_iface` for more details. + +.. _conn_mgr_monitoring_api: + +Connectivity monitoring API +=========================== + +Include header file :file:`include/zephyr/net/conn_mgr_monitoring.h` to access these. + +.. doxygengroup:: conn_mgr + +.. _conn_mgr_control: + +Connectivity control +#################### + +Many network interfaces require a network association procedure to be completed before being usable. + +For such ifaces, connectivity control can provide a generic API to request network association (:c:func:`conn_mgr_if_connect`) and dissasociation (:c:func:`conn_mgr_if_disconnect`). +Network interfaces implement support for this API by :ref:`binding themselves to a connectivity implementation `. + +Using this API, applications can associate with networks with minimal technology-specific boilerplate. + +Connectivity control also provides the following additional features: + +* Standardized :ref:`persistence and timeout ` behaviors during association. +* :ref:`Bulk functions ` for controlling the admin state and network association of all available ifaces simultaneously. +* Optional :ref:`convenience automations ` for common connectivity actions. + +.. _conn_mgr_control_operation: + +Basic operation +=============== + +The following sections outline the basic operation of Connection Manager's connectivity control. + +.. _conn_mgr_control_operation_binding: + +Binding +------- + +Before an iface can be commanded to associate or dissasociate using Connection Manager, it must first be bound to a :ref:`connectivity implementation `. +Binding is performed by the provider of the iface, not by the application (see :ref:`conn_mgr_impl_binding`), and can be thought of as an extension of the iface declaration. + +Once an iface is bound, all connectivity commands passed to it (such as :c:func:`conn_mgr_if_connect` or :c:func:`conn_mgr_if_disconnect`) will be routed to the corresponding implementation function in the connectivity implementation. + +.. note:: + + To avoid inconsistent behavior, all connectivity implementations must adhere to the :ref:`implementation guidelines `. + +.. _conn_mgr_control_operation_connecting: + +Connecting +---------- + +Once a bound iface is admin-up (see :ref:`net_if_interface_state_management`), :c:func:`conn_mgr_if_connect` can be called to cause it to associate with a network. + +If association succeeds, the connectivity implementation will mark the iface as operational-up (see :ref:`net_if_interface_state_management`). + +If association fails unrecoverably, the :ref:`fatal error event ` will be triggered. + +You can configure an optional :ref:`timeout ` for this process. + +.. note:: + The :c:func:`conn_mgr_if_connect` function is intentionally minimalistic, and does not take any kind of configuration. + Each connectivity implementation should provide a way to pre-configure or automatically configure any required association settings or credentials. + See :ref:`conn_mgr_impl_guidelines_preconfig` for details. + +.. _conn_mgr_control_operation_loss: + +Connection loss +--------------- + +If connectivity is lost due to external factors, the connectivity implementation will mark the iface as operational-down. + +Depending on whether :ref:`persistence ` is set, the iface may then attempt to reconnect. + +.. _conn_mgr_control_operation_disconnection: + +Manual disconnection +-------------------- + +The application can also request that connectivity be intentionally abandoned by calling :c:func:`conn_mgr_if_disconnect`. + +In this case, the connectivity implementation will disassociate the iface from its network and mark the iface as operational-down (see :ref:`net_if_interface_state_management`). +A new connection attempt will not be initiated, regardless of whether persistence is enabled. + +.. _conn_mgr_control_persistence_timeouts: + +Timeouts and Persistence +======================== + +Connection Manager requires that all connectivity implementations support the following standard key features: + +* :ref:`Connection timeouts ` +* :ref:`Connection persistence ` + +These features describe how ifaces should behave during connect and disconnect events. +You can individually set them for each iface. + +.. note:: + It is left to connectivity implementations to successfully and accurately implement these two features as described below. + See :ref:`conn_mgr_impl_timeout_persistence` for more details from the connectivity implementation perspective. + +.. _conn_mgr_control_timeouts: + +Connection Timeouts +------------------- + +When :c:func:`conn_mgr_if_connect` is called on an iface, a connection attempt begins. + +The connection attempt continues indefinitely until it succeeds, unless a timeout has been specified for the iface (using :c:func:`conn_mgr_if_set_timeout`). + +In that case, the connection attempt will be abandoned if the timeout elapses before it succeeds. +If this happens, the :ref:`timeout event` is raised. + +.. _conn_mgr_control_persistence: + +Connection Persistence +---------------------- + +Each iface also has a connection persistence setting that you can enable or disable by setting the :c:enumerator:`~conn_mgr_if_flag.CONN_MGR_IF_PERSISTENT` flag with :c:func:`conn_mgr_binding_set_flag`. + +This setting specifies how the iface should handle unintentional connection loss. + +If persistence is enabled, any unintentional connection loss will initiate a new connection attempt, with a new timeout if applicable. + +Otherwise, the iface will not attempt to reconnect. + +.. note:: + Persistence not does affect connection attempt behavior. + Only the timeout setting affects this. + + For instance, if a connection attempt on an iface times out, the iface will not attempt to reconnect, even if it is persistent. + + Conversely, if there is not a specified timeout, the iface will try to connect forever until it succeeds, even if it is not persistent. + + See :ref:`conn_mgr_impl_tp_persistence_during_connect` for the equivalent implementation guideline. + +.. _conn_mgr_control_events: + +Control events +============== + +Connectivity control triggers :ref:`network management ` events to inform the application of important state changes. + +See :ref:`conn_mgr_impl_guidelines_trigger_events` for the corresponding connectivity implementation guideline. + +.. _conn_mgr_control_events_fatal_error: + +Fatal Error +----------- + +The :c:macro:`NET_EVENT_CONN_IF_FATAL_ERROR` event is raised when an iface encounters an error from which it cannot recover (meaning any subsequent attempts to associate are guaranteed to fail, and all such attempts should be abandoned). + +Handlers of this event will be passed a pointer to the iface for which the fatal error occurred. +Individual connectivity implementations may also pass an application-specific data pointer. + +.. _conn_mgr_control_events_timeout: + +Timeout +------- + +The :c:macro:`NET_EVENT_CONN_IF_TIMEOUT` event is raised when an :ref:`iface association ` attempt :ref:`times out `. + +Handlers of this event will be passed a pointer to the iface that timed out attempting to associate. + +.. _conn_mgr_control_events_listening: + +Listening for control events +---------------------------- + +You can listen for control events as follows: + +.. code-block:: c + + /* Declare a net_mgmt callback struct to store the callback */ + struct net_mgmt_event_callback my_conn_evt_callback; + + /* Declare a handler to receive control events */ + static void my_conn_evt_handler(struct net_mgmt_event_callback *cb, + uint32_t event, struct net_if *iface) + { + if (event == NET_EVENT_CONN_IF_TIMEOUT) { + /* Timeout occurred, handle it */ + } else if (event == NET_EVENT_CONN_IF_FATAL_ERROR) { + /* Fatal error occurred, handle it */ + } + + /* Otherwise, it's some other event type we didn't register for. */ + } + + int main() + { + /* Configure the callback struct to respond to (at least) the CONN_IF_TIMEOUT + * and CONN_IF_FATAL_ERROR events. + * + * Note that the callback may also be triggered for events other than those specified here! + * (See the net_mgmt documentation) + */ + + net_mgmt_init_event_callback( + &conn_mgr_conn_callback, conn_mgr_conn_handler, + NET_EVENT_CONN_IF_TIMEOUT | NET_EVENT_CONN_IF_FATAL_ERROR + ); + + /* Register the callback */ + net_mgmt_add_event_callback(&conn_mgr_conn_callback); + return 0; + } + +See :ref:`net_mgmt_listening` for more details on listening for net_mgmt events. + +.. _conn_mgr_control_automations: + +Automated behaviors +=================== + +There are a few actions related to connectivity that are (by default at least) performed automatically for the user. + +.. _conn_mgr_control_automations_auto_up: + +.. topic:: Automatic admin-up + + In Zephyr, ifaces are automatically taken admin-up (see :ref:`net_if_interface_state_management` for details on iface states) during initialization. + + Applications can disable this behavior by setting the :c:enumerator:`~net_if_flag.NET_IF_NO_AUTO_START` interface flag with :c:func:`net_if_flag_set`. + +.. _conn_mgr_control_automations_auto_connect: + +.. topic:: Automatic connect + + By default, Connection Manager will automatically connect any :ref:`bound ` iface that becomes admin-up. + + Applications can disable this by setting the :c:enumerator:`~conn_mgr_if_flag.CONN_MGR_IF_NO_AUTO_CONNECT` connectivity flag with :c:func:`conn_mgr_if_set_flag`. + +.. _conn_mgr_control_automations_auto_down: + +.. topic:: Automatic admin-down + + By default, Connection Manager will automatically take any bound iface admin-down if it has given up on associating. + + Applications can disable this for all ifaces by disabling the :kconfig:option:`CONFIG_NET_CONNECTION_MANAGER_AUTO_IF_DOWN` Kconfig option, or for individual ifaces by setting the :c:enumerator:`~conn_mgr_if_flag.CONN_MGR_IF_NO_AUTO_DOWN` connectivity flag with :c:func:`conn_mgr_if_set_flag`. + +.. _conn_mgr_control_api: + +Connectivity control API +======================== + +Include header file :file:`include/zephyr/net/conn_mgr_connectivity.h` to access these. + +.. doxygengroup:: conn_mgr_connectivity + +.. _conn_mgr_control_api_bulk: + +Bulk API +-------- + +Connectivity control provides several bulk functions allowing all ifaces to be controlled at once. + +You can restrict these functions to operate only on non-:ref:`ignored ` ifaces if desired. + +Include header file :file:`include/zephyr/net/conn_mgr_connectivity.h` to access these. + +.. doxygengroup:: conn_mgr_connectivity_bulk diff --git a/doc/connectivity/networking/index.rst b/doc/connectivity/networking/index.rst index 8f25a823879..f900bb56330 100644 --- a/doc/connectivity/networking/index.rst +++ b/doc/connectivity/networking/index.rst @@ -16,3 +16,4 @@ operation of the stacks and how they were implemented. networking_with_host.rst network_monitoring.rst api/index.rst + conn_mgr/index.rst diff --git a/doc/connectivity/networking/native_posix_setup.rst b/doc/connectivity/networking/native_posix_setup.rst deleted file mode 100644 index 249cef7f07a..00000000000 --- a/doc/connectivity/networking/native_posix_setup.rst +++ /dev/null @@ -1,91 +0,0 @@ -.. _networking_with_native_posix: - -Networking with native_posix board -################################## - -.. contents:: - :local: - :depth: 2 - -This page describes how to set up a virtual network between a (Linux) host -and a Zephyr application running in a native_posix board. - -In this example, the :ref:`sockets-echo-server-sample` sample application from -the Zephyr source distribution is run in native_posix board. The Zephyr -native_posix board instance is connected to a Linux host using a tuntap device -which is modeled in Linux as an Ethernet network interface. - -Prerequisites -************* - -On the Linux Host, fetch the Zephyr ``net-tools`` project, which is located -in a separate Git repository: - -.. code-block:: console - - git clone https://github.com/zephyrproject-rtos/net-tools - - -Basic Setup -*********** - -For the steps below, you will need three terminal windows: - -* Terminal #1 is terminal window with net-tools being the current - directory (``cd net-tools``) -* Terminal #2 is your usual Zephyr development terminal, - with the Zephyr environment initialized. -* Terminal #3 is the console to the running Zephyr native_posix - instance (optional). - -Step 1 - Create Ethernet interface -================================== - -Before starting native_posix with network emulation, a network interface -should be created. - -In terminal #1, type: - -.. code-block:: console - - ./net-setup.sh - -You can tweak the behavior of the net-setup.sh script. See various options -by running ``net-setup.sh`` like this: - -.. code-block:: console - - ./net-setup.sh --help - - -Step 2 - Start app in native_posix board -======================================== - -Build and start the ``echo_server`` sample application. - -In terminal #2, type: - -.. zephyr-app-commands:: - :zephyr-app: samples/net/sockets/echo_server - :host-os: unix - :board: native_posix - :goals: run - :compact: - - -Step 3 - Connect to console (optional) -====================================== - -The console window should be launched automatically when the Zephyr instance is -started but if it does not show up, you can manually connect to the console. -The native_posix board will print a string like this when it starts: - -.. code-block:: console - - UART connected to pseudotty: /dev/pts/5 - -You can manually connect to it like this: - -.. code-block:: console - - screen /dev/pts/5 diff --git a/doc/connectivity/networking/native_sim_setup.rst b/doc/connectivity/networking/native_sim_setup.rst new file mode 100644 index 00000000000..166ff707c89 --- /dev/null +++ b/doc/connectivity/networking/native_sim_setup.rst @@ -0,0 +1,91 @@ +.. _networking_with_native_sim: + +Networking with native_sim board +################################ + +.. contents:: + :local: + :depth: 2 + +This page describes how to set up a virtual network between a (Linux) host +and a Zephyr application running in a :ref:`native_sim ` board. + +In this example, the :zephyr:code-sample:`sockets-echo-server` sample application from +the Zephyr source distribution is run in native_sim board. The Zephyr +native_sim board instance is connected to a Linux host using a tuntap device +which is modeled in Linux as an Ethernet network interface. + +Prerequisites +************* + +On the Linux Host, fetch the Zephyr ``net-tools`` project, which is located +in a separate Git repository: + +.. code-block:: console + + git clone https://github.com/zephyrproject-rtos/net-tools + + +Basic Setup +*********** + +For the steps below, you will need three terminal windows: + +* Terminal #1 is terminal window with net-tools being the current + directory (``cd net-tools``) +* Terminal #2 is your usual Zephyr development terminal, + with the Zephyr environment initialized. +* Terminal #3 is the console to the running Zephyr native_sim + instance (optional). + +Step 1 - Create Ethernet interface +================================== + +Before starting native_sim with network emulation, a network interface +should be created. + +In terminal #1, type: + +.. code-block:: console + + ./net-setup.sh + +You can tweak the behavior of the net-setup.sh script. See various options +by running ``net-setup.sh`` like this: + +.. code-block:: console + + ./net-setup.sh --help + + +Step 2 - Start app in native_sim board +====================================== + +Build and start the ``echo_server`` sample application. + +In terminal #2, type: + +.. zephyr-app-commands:: + :zephyr-app: samples/net/sockets/echo_server + :host-os: unix + :board: native_sim + :goals: run + :compact: + + +Step 3 - Connect to console (optional) +====================================== + +The console window should be launched automatically when the Zephyr instance is +started but if it does not show up, you can manually connect to the console. +The native_sim board will print a string like this when it starts: + +.. code-block:: console + + UART connected to pseudotty: /dev/pts/5 + +You can manually connect to it like this: + +.. code-block:: console + + screen /dev/pts/5 diff --git a/doc/connectivity/networking/network_monitoring.rst b/doc/connectivity/networking/network_monitoring.rst index 0dbe00fa4fa..a5f2dcfee71 100644 --- a/doc/connectivity/networking/network_monitoring.rst +++ b/doc/connectivity/networking/network_monitoring.rst @@ -13,7 +13,7 @@ Zephyr. This page describes how to set up a way to capture network traffic so that user is able to use Wireshark or similar tool in remote host to see the network packets sent or received by a Zephyr device. -See also the :ref:`net-capture-sample` sample application from the Zephyr +See also the :zephyr:code-sample:`net-capture` sample application from the Zephyr source distribution for configuration options that need to be enabled. Host Configuration @@ -104,7 +104,7 @@ need to terminate the network connection like this. Zephyr Configuration ******************** -In this example, we use ``native_posix`` board. You can also use any other board +In this example, we use the ``native_sim`` board. You can also use any other board that supports networking. In terminal #3, type: @@ -112,7 +112,7 @@ In terminal #3, type: .. zephyr-app-commands:: :zephyr-app: samples/net/capture :host-os: unix - :board: native_posix + :board: native_sim :gen-args: -DCONFIG_NATIVE_UART_AUTOATTACH_DEFAULT_CMD=\""gnome-terminal -- screen %s"\" :goals: build :compact: @@ -189,7 +189,7 @@ Then we need to enable the network packet monitoring like this: net capture enable 2 The ``2`` tells the network interface which traffic we want to capture. In -this example, the ``2`` is the ``native_posix`` board Ethernet interface. +this example, the ``2`` is the ``native_sim`` board Ethernet interface. Note that we send the network traffic to the same interface that we are monitoring in this example. The monitoring system avoids to capture already captured network traffic as that would lead to recursion. diff --git a/doc/connectivity/networking/networking-api-usage.rst b/doc/connectivity/networking/networking-api-usage.rst index d1249d01e6d..0145482fec9 100644 --- a/doc/connectivity/networking/networking-api-usage.rst +++ b/doc/connectivity/networking/networking-api-usage.rst @@ -8,8 +8,8 @@ Applications should use the BSD socket API defined in and close a connection. The same API can be used when working with UDP or TCP data. See :ref:`BSD socket API ` for more details. -See :ref:`sockets-echo-server-sample` and :ref:`sockets-echo-client-sample` -applications how to create a simple server or client BSD socket based +See :zephyr:code-sample:`sockets-echo-server` and :zephyr:code-sample:`sockets-echo-client` +sample applications to learn how to create a simple server or client BSD socket based application. The legacy connectivity API in :zephyr_file:`include/zephyr/net/net_context.h` should not be diff --git a/doc/connectivity/networking/networking_with_host.rst b/doc/connectivity/networking/networking_with_host.rst index 063e065730a..995e7dc0f80 100644 --- a/doc/connectivity/networking/networking_with_host.rst +++ b/doc/connectivity/networking/networking_with_host.rst @@ -7,7 +7,7 @@ Networking with the host system :maxdepth: 1 :hidden: - native_posix_setup.rst + native_sim_setup.rst qemu_eth_setup.rst qemu_setup.rst usbnet_setup.rst @@ -53,14 +53,14 @@ possible: the host on which the model is running. See :ref:`networking_with_armfvp` for details. -* native_posix board. +* native_sim board. * The Zephyr instance can be executed as a user space process in the host system. This is the most convenient way to debug the Zephyr system as one can attach host debugger directly to the running Zephyr instance. This requires that there is an adaptation driver in Zephyr for interfacing with the host system. An Ethernet driver exists in Zephyr for this purpose. - See :ref:`networking_with_native_posix` for details. + See :ref:`networking_with_native_sim` for details. * USB device networking. @@ -70,7 +70,7 @@ possible: * Connecting multiple Zephyr instances together. - * If you have multiple Zephyr instances, either QEMU or native_posix ones, + * If you have multiple Zephyr instances, either QEMU or native_sim ones, and want to create a connection between them, see :ref:`networking_with_multiple_instances` for details. diff --git a/doc/connectivity/networking/networking_with_multiple_instances.rst b/doc/connectivity/networking/networking_with_multiple_instances.rst index 6bd4531c829..6489db45551 100644 --- a/doc/connectivity/networking/networking_with_multiple_instances.rst +++ b/doc/connectivity/networking/networking_with_multiple_instances.rst @@ -9,7 +9,7 @@ Networking with multiple Zephyr instances This page describes how to set up a virtual network between multiple Zephyr instances. The Zephyr instances could be running inside QEMU -or could be native_posix board processes. The Linux host can be used +or could be native_sim board processes. The Linux host can be used to route network traffic between these systems. Prerequisites @@ -34,10 +34,10 @@ For the steps below, you will need five terminal windows: with the Zephyr environment initialized. As there are multiple ways to setup the Zephyr network, the example below uses -``qemu_x86`` board with ``e1000`` Ethernet controller and native_posix board +``qemu_x86`` board with ``e1000`` Ethernet controller and native_sim board to simplify the setup instructions. You can use other QEMU boards and drivers if needed, see :ref:`networking_with_eth_qemu` for details. You can also use -two or more native_posix board Zephyr instances and connect them together. +two or more native_sim board Zephyr instances and connect them together. Step 1 - Create configuration files @@ -122,8 +122,8 @@ In terminal #3, type: Step 4 - Start Zephyr instances =============================== -In this example we start :ref:`sockets-echo-server-sample` and -:ref:`sockets-echo-client-sample` applications. You can use other applications +In this example we start :zephyr:code-sample:`sockets-echo-server` and +:zephyr:code-sample:`sockets-echo-client` sample applications. You can use other applications too as needed. In terminal #4, if you are using QEMU, type this: @@ -141,11 +141,11 @@ In terminal #4, if you are using QEMU, type this: -DCONFIG_ETH_QEMU_IFACE_NAME=\"zeth.1\" \ -DCONFIG_ETH_QEMU_EXTRA_ARGS=\"mac=00:00:5e:00:53:01\" -or if you want to use native_posix board, type this: +or if you want to use native_sim board, type this: .. code-block:: console - west build -d build/server -b native_posix -t run \ + west build -d build/server -b native_sim -t run \ samples/net/sockets/echo_server -- \ -DCONFIG_NET_CONFIG_MY_IPV4_ADDR=\"198.51.100.1\" \ -DCONFIG_NET_CONFIG_PEER_IPV4_ADDR=\"203.0.113.1\" \ @@ -172,11 +172,11 @@ In terminal #5, if you are using QEMU, type this: -DCONFIG_ETH_QEMU_IFACE_NAME=\"zeth.2\" \ -DCONFIG_ETH_QEMU_EXTRA_ARGS=\"mac=00:00:5e:00:53:02\" -or if you want to use native_posix board, type this: +or if you want to use native_sim board, type this: .. code-block:: console - west build -d build/client -b native_posix -t run \ + west build -d build/client -b native_sim -t run \ samples/net/sockets/echo_client -- \ -DCONFIG_NET_CONFIG_MY_IPV4_ADDR=\"203.0.113.1\" \ -DCONFIG_NET_CONFIG_PEER_IPV4_ADDR=\"198.51.100.1\" \ diff --git a/doc/connectivity/networking/overview.rst b/doc/connectivity/networking/overview.rst index c339632fdf1..c1de9a1ab67 100644 --- a/doc/connectivity/networking/overview.rst +++ b/doc/connectivity/networking/overview.rst @@ -56,7 +56,7 @@ can be disabled if not needed. * **TCP** Transmission Control Protocol (`RFC 793 `_) is supported. Both server - and client roles can be used the the application. The amount of TCP sockets + and client roles can be used the application. The amount of TCP sockets that are available to applications can be configured at build time. * **BSD Sockets API** Support for a subset of a @@ -69,12 +69,12 @@ can be disabled if not needed. are provided by mbedTLS library. * **MQTT** Message Queue Telemetry Transport (ISO/IEC PRF 20922) is supported. - A sample :ref:`mqtt-publisher-sample` client application for MQTT v3.1.1 is + A sample :zephyr:code-sample:`mqtt-publisher` client application for MQTT v3.1.1 is implemented. * **CoAP** Constrained Application Protocol (`RFC 7252 `_) is supported. - Both :ref:`coap-client-sample` and :ref:`coap-server-sample` sample + Both :zephyr:code-sample:`coap-client` and :zephyr:code-sample:`coap-server` sample applications are implemented. * **LWM2M** OMA Lightweight Machine-to-Machine Protocol @@ -83,7 +83,7 @@ can be disabled if not needed. Reporting" interfaces. The required core LwM2M objects are implemented as well as several IPSO Smart Objects. (`LwM2M specification 1.1.1`_) is supported in similar manner when enabled with a Kconfig option. - :ref:`lwm2m-client-sample` implements the library as an example. + :zephyr:code-sample:`lwm2m-client` sample implements the library as an example. * **DNS** Domain Name Service (`RFC 1035 `_) client functionality diff --git a/doc/connectivity/networking/qemu_eth_setup.rst b/doc/connectivity/networking/qemu_eth_setup.rst index 5d6aab68962..a0219e6126c 100644 --- a/doc/connectivity/networking/qemu_eth_setup.rst +++ b/doc/connectivity/networking/qemu_eth_setup.rst @@ -10,7 +10,7 @@ Networking with QEMU Ethernet This page describes how to set up a virtual network between a (Linux) host and a Zephyr application running in QEMU. -In this example, the :ref:`sockets-echo-server-sample` sample application from +In this example, the :zephyr:code-sample:`sockets-echo-server` sample application from the Zephyr source distribution is run in QEMU. The Zephyr instance is connected to a Linux host using a tuntap device which is modeled in Linux as an Ethernet network interface. @@ -71,7 +71,7 @@ by running ``net-setup.sh`` like this: Step 2 - Start app in QEMU board ================================ -Build and start the :ref:`sockets-echo-server-sample` sample application. +Build and start the :zephyr:code-sample:`sockets-echo-server` sample application. In this example, the qemu_x86 board is used. In terminal #2, type: diff --git a/doc/connectivity/networking/qemu_setup.rst b/doc/connectivity/networking/qemu_setup.rst index 5740145cd74..f2b979867a8 100644 --- a/doc/connectivity/networking/qemu_setup.rst +++ b/doc/connectivity/networking/qemu_setup.rst @@ -13,7 +13,7 @@ targets such as qemu_x86 and qemu_cortex_m3). Some virtual ARM boards (such as qemu_cortex_a53) only support a single UART, in this case QEMU Ethernet is preferred, see :ref:`networking_with_eth_qemu` for details. -In this example, the :ref:`sockets-echo-server-sample` sample application from +In this example, the :zephyr:code-sample:`sockets-echo-server` sample application from the Zephyr source distribution is run in QEMU. The QEMU instance is connected to a Linux host using a serial port, and SLIP is used to transfer data between the Zephyr application and Linux (over a chain of diff --git a/doc/connectivity/networking/usbnet_setup.rst b/doc/connectivity/networking/usbnet_setup.rst index 5f193770504..a71a48c6771 100644 --- a/doc/connectivity/networking/usbnet_setup.rst +++ b/doc/connectivity/networking/usbnet_setup.rst @@ -12,7 +12,7 @@ and a Zephyr application running on USB supported devices. The board is connected to Linux host using USB cable and provides an Ethernet interface to the host. -The :ref:`sockets-echo-server-sample` application from the Zephyr source +The :zephyr:code-sample:`sockets-echo-server` application from the Zephyr source distribution is run on supported board. The board is connected to a Linux host using a USB cable providing an Ethernet interface to the host. diff --git a/doc/connectivity/usb/device/usb_device.rst b/doc/connectivity/usb/device/usb_device.rst index 6b17e2ec2ca..134ec5972cd 100644 --- a/doc/connectivity/usb/device/usb_device.rst +++ b/doc/connectivity/usb/device/usb_device.rst @@ -39,7 +39,8 @@ Audio There is an experimental implementation of the Audio class. It follows specification version 1.00 (``bcdADC 0x0100``) and supports synchronous synchronisation type only. -See :ref:`usb_audio_headphones_microphone` and :ref:`usb_audio_headset` for reference. +See :zephyr:code-sample:`usb-audio-headphones-microphone` and +:zephyr:code-sample:`usb-audio-headset` samples for reference. Bluetooth HCI USB transport layer ================================= @@ -81,6 +82,9 @@ But there are two important differences in behavior to a real UART controller: initialized and started, until then any data is discarded * If device is connected to the host, it still needs an application on the host side which requests the data +* The CDC ACM poll out implementation follows the API and blocks when the TX + ring buffer is full only if the hw-flow-control property is enabled and + called from a non-ISR context. The devicetree compatible property for CDC ACM UART is :dtcompatible:`zephyr,cdc-acm-uart`. @@ -106,7 +110,7 @@ and looks like this: }; }; -Samples :ref:`usb_cdc-acm` and :ref:`usb_hid-cdc` have similar overlay files. +Samples :zephyr:code-sample:`usb-cdc-acm` and :zephyr:code-sample:`usb-hid-cdc` have similar overlay files. And since no special properties are present, it may seem overkill to use devicetree to describe CDC ACM UART. The motivation behind using devicetree is the easy interchangeability of a real UART controller and CDC ACM UART @@ -117,7 +121,7 @@ Console over CDC ACM UART With the CDC ACM UART node from above and ``zephyr,console`` property of the chosen node, we can describe that CDC ACM UART is to be used with the console. -A similar overlay file is used by :ref:`cdc-acm-console`. +A similar overlay file is used by the :zephyr:code-sample:`usb-cdc-acm-console` sample. .. code-block:: devicetree @@ -166,10 +170,41 @@ CDC ACM UART as backend for a subsystem or application: * ``zephyr,bt-c2h-uart`` used in Bluetooth, for example see :ref:`bluetooth-hci-uart-sample` * ``zephyr,ot-uart`` used in OpenThread, - for example see :ref:`coprocessor-sample` + for example see :zephyr:code-sample:`coprocessor` * ``zephyr,shell-uart`` used by shell for serial backend, for example see :zephyr_file:`samples/subsys/shell/shell_module` -* ``zephyr,uart-mcumgr`` used by :ref:`smp_svr_sample` +* ``zephyr,uart-mcumgr`` used by :zephyr:code-sample:`smp-svr` sample + +POSIX default tty ECHO mitigation +--------------------------------- + +POSIX systems, like Linux, default to enabling ECHO on tty devices. Host side +application can disable ECHO by calling ``open()`` on the tty device and issuing +``ioctl()`` (preferably via ``tcsetattr()``) to disable echo if it is not desired. +Unfortunately, there is an inherent race between the ``open()`` and ``ioctl()`` +where the ECHO is enabled and any characters received (even if host application +does not call ``read()``) will be echoed back. This issue is especially visible +when the CDC ACM port is used without any real UART on the other side because +there is no arbitrary delay due to baud rate. + +To mitigate the issue, Zephyr CDC ACM implementation arms IN endpoint with ZLP +after device is configured. When the host reads the ZLP, which is pretty much +the best indication that host application has opened the tty device, Zephyr will +force :kconfig:option:`CONFIG_CDC_ACM_TX_DELAY_MS` millisecond delay before real +payload is sent. This should allow sufficient time for first, and only first, +application that opens the tty device to disable ECHO if ECHO is not desired. +If ECHO is not desired at all from CDC ACM device it is best to set up udev rule +to disable ECHO as soon as device is connected. + +ECHO is particurarly unwanted when CDC ACM instance is used for Zephyr shell, +because the control characters to set color sent back to shell are interpreted +as (invalid) command and user will see garbage as a result. While minicom does +disable ECHO by default, on exit with reset it will restore the termios settings +to whatever was set on entry. Therefore, if minicom is the first application to +open the tty device, the exit with reset will enable ECHO back and thus set up +a problem for the next application (which cannot be mitigated at Zephyr side). +To prevent the issue it is recommended either to leave minicom without reset or +to disable ECHO before minicom is started. DFU === @@ -177,7 +212,7 @@ DFU USB DFU class implementation is tightly coupled to :ref:`dfu` and :ref:`mcuboot_api`. This means that the target platform must support the :ref:`flash_img_api` API. -See :ref:`usb_dfu` for reference. +See :zephyr:code-sample:`usb-dfu` sample for reference. USB Human Interface Devices (HID) support ========================================= @@ -276,7 +311,7 @@ The disadvantage of this is that Kconfig options such as :kconfig:option:`CONFIG_HID_INTERRUPT_EP_MPS` apply to all instances. This design issue will be fixed in the HID class implementation for the new USB support. -See :ref:`usb_hid` or :ref:`usb_hid-mouse` for reference. +See :zephyr:code-sample:`usb-hid` or :zephyr:code-sample:`usb-hid-mouse` sample for reference. Mass Storage Class ================== @@ -286,10 +321,11 @@ access and expose a RAM disk, emulated block device on a flash partition, or SD Card to the host. Only one disk instance can be exported at a time. The disc to be used by the implementation is set by the -:kconfig:option:`CONFIG_MASS_STORAGE_DISK_NAME` and should be equal to one -of the options used by the disc access driver that the application wants to expose to -the host, :kconfig:option:`CONFIG_DISK_RAM_VOLUME_NAME`, -:kconfig:option:`CONFIG_MMC_VOLUME_NAME`, or :kconfig:option:`CONFIG_SDMMC_VOLUME_NAME`. +:kconfig:option:`CONFIG_MASS_STORAGE_DISK_NAME` and should be the same as the name +used by the disc access driver that the application wants to expose to the host. +SD card disk drivers use options :kconfig:option:`CONFIG_MMC_VOLUME_NAME` or +:kconfig:option:`CONFIG_SDMMC_VOLUME_NAME`, and flash and RAM disk drivers use +node property ``disk-name`` to set the disk name. For the emulated block device on a flash partition, the flash partition and flash disk to be used must be described in the devicetree. If a storage partition @@ -326,7 +362,7 @@ should be the same as ``disk-name`` property. The ``disk-property`` "NAND" may be confusing, but it is simply how some file systems identifies the disc. Therefore, if the application also accesses the file system on the exposed disc, default names should be used, see -:ref:`usb_mass` for reference. +:zephyr:code-sample:`usb-mass` sample for reference. Networking ========== @@ -338,7 +374,7 @@ Ethernet connection between the remote (USB host) and Zephyr network support. * CDC EEM class, enabled with :kconfig:option:`CONFIG_USB_DEVICE_NETWORK_EEM` * RNDIS support, enabled with :kconfig:option:`CONFIG_USB_DEVICE_NETWORK_RNDIS` -See :ref:`zperf-sample` or :ref:`sockets-dumb-http-server-sample` for reference. +See :zephyr:code-sample:`zperf` or :zephyr:code-sample:`socket-dumb-http-server` for reference. Typically, users will need to add a configuration file overlay to the build, such as :zephyr_file:`samples/net/zperf/overlay-netusb.conf`. @@ -354,7 +390,7 @@ The application should register descriptors such as Capability Descriptor using :c:func:`usb_bos_register_cap`. Registered descriptors are added to the root BOS descriptor and handled by the stack. -See :ref:`webusb-sample` for reference. +See :zephyr:code-sample:`webusb` sample for reference. Implementing a non-standard USB class ************************************* @@ -409,14 +445,14 @@ the vendor requests: The class driver waits for the :makevar:`USB_DC_CONFIGURED` device status code before transmitting any data. -.. _testing_USB_native_posix: +.. _testing_USB_native_sim: -Testing over USPIP in native_posix -*********************************** +Testing over USPIP in native_sim +******************************** A virtual USB controller implemented through USBIP might be used to test the USB device stack. Follow the general build procedure to build the USB sample for -the native_posix configuration. +the :ref:`native_sim ` configuration. Run built sample with: @@ -472,35 +508,35 @@ and documented requests. The following Product IDs are currently used: -+-------------------------------------+--------+ -| Sample | PID | -+=====================================+========+ -| :ref:`usb_cdc-acm` | 0x0001 | -+-------------------------------------+--------+ -| :ref:`usb_cdc-acm_composite` | 0x0002 | -+-------------------------------------+--------+ -| :ref:`usb_hid-cdc` | 0x0003 | -+-------------------------------------+--------+ -| :ref:`cdc-acm-console` | 0x0004 | -+-------------------------------------+--------+ -| :ref:`usb_dfu` | 0x0005 | -+-------------------------------------+--------+ -| :ref:`usb_hid` | 0x0006 | -+-------------------------------------+--------+ -| :ref:`usb_hid-mouse` | 0x0007 | -+-------------------------------------+--------+ -| :ref:`usb_mass` | 0x0008 | -+-------------------------------------+--------+ -| :ref:`testusb-app` | 0x0009 | -+-------------------------------------+--------+ -| :ref:`webusb-sample` | 0x000A | -+-------------------------------------+--------+ -| :ref:`bluetooth-hci-usb-sample` | 0x000B | -+-------------------------------------+--------+ -| :ref:`bluetooth-hci-usb-h4-sample` | 0x000C | -+-------------------------------------+--------+ -| :ref:`wpanusb-sample` | 0x000D | -+-------------------------------------+--------+ ++----------------------------------------------------+--------+ +| Sample | PID | ++====================================================+========+ +| :zephyr:code-sample:`usb-cdc-acm` | 0x0001 | ++----------------------------------------------------+--------+ +| :zephyr:code-sample:`usb-cdc-acm-composite` | 0x0002 | ++----------------------------------------------------+--------+ +| :zephyr:code-sample:`usb-hid-cdc` | 0x0003 | ++----------------------------------------------------+--------+ +| :zephyr:code-sample:`usb-cdc-acm-console` | 0x0004 | ++----------------------------------------------------+--------+ +| :zephyr:code-sample:`usb-dfu` | 0x0005 | ++----------------------------------------------------+--------+ +| :zephyr:code-sample:`usb-hid` | 0x0006 | ++----------------------------------------------------+--------+ +| :zephyr:code-sample:`usb-hid-mouse` | 0x0007 | ++----------------------------------------------------+--------+ +| :zephyr:code-sample:`usb-mass` | 0x0008 | ++----------------------------------------------------+--------+ +| :zephyr:code-sample:`testusb-app` | 0x0009 | ++----------------------------------------------------+--------+ +| :zephyr:code-sample:`webusb` | 0x000A | ++----------------------------------------------------+--------+ +| :ref:`bluetooth-hci-usb-sample` | 0x000B | ++----------------------------------------------------+--------+ +| :ref:`bluetooth-hci-usb-h4-sample` | 0x000C | ++----------------------------------------------------+--------+ +| :zephyr:code-sample:`wpan-usb` | 0x000D | ++----------------------------------------------------+--------+ The USB device descriptor field ``bcdDevice`` (Device Release Number) represents the Zephyr kernel major and minor versions as a binary coded decimal value. diff --git a/doc/connectivity/usb/device_next/usb_device.rst b/doc/connectivity/usb/device_next/usb_device.rst index c7755329538..a9009d54e2b 100644 --- a/doc/connectivity/usb/device_next/usb_device.rst +++ b/doc/connectivity/usb/device_next/usb_device.rst @@ -14,7 +14,7 @@ class API that should be used to implement the functions (classes). It will replace :ref:`usb_device_stack`. If you would like to play around with the new device support, or the new USB -support in general, please try :ref:`usb_shell-app`. The sample is mainly to help +support in general, please try :zephyr:code-sample:`usb-shell` sample. The sample is mainly to help test the capabilities of the stack and correct implementation of the USB controller drivers. @@ -33,14 +33,14 @@ CDC ACM CDC ACM implementation has support for multiple instances. Description from :ref:`usb_device_cdc_acm` also applies to the new implementation. -See :ref:`usb_cdc-acm` sample for reference. +See :zephyr:code-sample:`usb-cdc-acm` sample for reference. To build the sample for the new device support, set the configuration ``-DCONF_FILE=usbd_next_prj.conf`` either directly or via ``west``. Mass Storage Class ================== -See :ref:`usb_mass` sample for reference. +See :zephyr:code-sample:`usb-mass` sample for reference. To build the sample for the new device support, set the configuration ``-DCONF_FILE=usbd_next_prj.conf`` either directly or via ``west``. @@ -51,7 +51,7 @@ At the moment only CDC ECM class is implemented and has support for multiple ins It provides a virtual Ethernet connection between the remote (USB host) and Zephyr network support. -See :ref:`zperf-sample` for reference. +See :zephyr:code-sample:`zperf` for reference. To build the sample for the new device support, set the configuration overlay file ``-DDEXTRA_CONF_FILE=overlay-usbd_next_ecm.conf`` and devicetree overlay file ``-DDTC_OVERLAY_FILE="usbd_next_ecm.overlay`` either directly or via ``west``. diff --git a/doc/contribute/contributor_expectations.rst b/doc/contribute/contributor_expectations.rst index dfe6b5ff0e2..aeb90c33d68 100644 --- a/doc/contribute/contributor_expectations.rst +++ b/doc/contribute/contributor_expectations.rst @@ -209,21 +209,47 @@ PR Technical Escalation In cases where a contributor objects to change requests from reviewers, Zephyr defines the following escalation process for resolving technical disagreements. +Before escalation of technical disagreements, follow the steps below: + - Resolve in the PR among assignee, maintainers and reviewer. - Assignee to act as moderator if applicable. -- Optionally resolve in the next `Zephyr Dev Meeting`_ or `Architecture Working - Group`_ meeting with more Maintainers and project stakeholders. +- Optionally resolve in the next `Zephyr Dev Meeting`_ meeting with more + Maintainers and project stakeholders. + + - The involved parties and the Assignee to be present when the issue is + discussed. + +- If no progress is made, the assignee (maintainer) has the right to dismiss + stale, unrelated or irrelevant change requests by reviewers giving the + reviewers a minimum of 1 business day to respond and revisit their initial + change requests or start the escalation process. + + The assignee has the responsibility to document the reasoning for dismissing + any reviews in the PR and should notify the reviewer about their review being + dismissed. - - The involved parties and the Assignee to be present when - the (escalated) issue is discussed. + To give the reviewers time to respond and escalate, the assignee is + expected to block the PR from being merged either by not + approving the PR or by setting the *DNM* label. -- TSC: Assignees can escalate to the TSC voting members and get a binding - resolution in the TSC by adding the `tsc`_ label on the PR. +Escalation can be triggered by any party participating in the review +process (assignee, reviewers or the original author of the change) following +the steps below: -- Assignee to ensure the resolution of the escalation is reflected in the PR - review. +- Escalate to the `Architecture Working Group`_ by adding the `Architecture + Review` label on the PR. Beside the weekly meeting where such escalations are + processed, the `Architecture Working Group`_ shall facilitate an offline + review of the escalation if requested, especially if any of the parties can't + attend the meeting. + +- If all avenues of resolution and escalation have failed, assignees can escalate + to the TSC and get a binding resolution in the TSC by adding the *TSC* label + on the PR. + +- The Assignee is expected to ensure the resolution of the escalation and the + outcome is documented in the related pull request or issues on Github. .. _#pr-help: https://discord.com/channels/720317445772017664/997527108844798012 @@ -235,7 +261,8 @@ defines the following escalation process for resolving technical disagreements. .. _Architecture Working Group: https://github.com/zephyrproject-rtos/zephyr/wiki/Architecture-Working-Group -.. _tsc: https://github.com/zephyrproject-rtos/zephyr/labels/tsc + +.. _reviewer-expectations: Reviewer Expectations ##################### @@ -244,10 +271,11 @@ Reviewer Expectations for more details. - The Zephyr Project recognizes that reviewers and maintainers have limited - bandwidth. Prioritize review requests in the following order: + bandwidth. As a reviewer, prioritize review requests in the following order: - #. PRs related to items in the `Zephyr Release Plan`_. - #. PRs that the reviewer has requested blocking changes. + #. PRs related to items in the `Zephyr Release Plan`_ or those targeting + the next release during the stabilization period (after RC1). + #. PRs where the reviewer has requested blocking changes. #. PRs assigned to the reviewer as the area maintainer. #. All other PRs. @@ -275,6 +303,11 @@ Reviewer Expectations they address all non-blocking comments. PR authors should acknowledge every review comment in some way, even if it's just with an emoticon. +- Reviewers shall be *clear* and *concise* what changes they are requesting when the + "Request Changes" option is used. Requested changes shall be in the scope of + the PR in question and following the contribution and style guidelines of the + project. + .. _Code of Conduct: https://github.com/zephyrproject-rtos/zephyr/blob/main/CODE_OF_CONDUCT.md .. _Zephyr Release Plan: https://github.com/orgs/zephyrproject-rtos/projects/13 diff --git a/doc/contribute/documentation/generation.rst b/doc/contribute/documentation/generation.rst index 3701e860138..87a00357c89 100644 --- a/doc/contribute/documentation/generation.rst +++ b/doc/contribute/documentation/generation.rst @@ -93,6 +93,13 @@ as described below: .. group-tab:: Linux + Common to all Linux installations, install the Python dependencies + required to build the documentation: + + .. code-block:: console + + pip install -r ~/zephyrproject/zephyr/doc/requirements.txt + On Ubuntu Linux: .. code-block:: console @@ -122,6 +129,12 @@ as described below: .. group-tab:: macOS + Install the Python dependencies required to build the documentation: + + .. code-block:: console + + pip install -r ~/zephyrproject/zephyr/doc/requirements.txt + Use ``brew`` and ``tlmgr`` to install the tools: .. code-block:: console @@ -132,6 +145,12 @@ as described below: .. group-tab:: Windows + Install the Python dependencies required to build the documentation: + + .. code-block:: console + + pip install -r %HOMEPATH$\zephyrproject\zephyr\doc\requirements.txt + Open a ``cmd.exe`` window as **Administrator** and run the following command: .. code-block:: console @@ -201,7 +220,7 @@ folder, here are the commands to generate the html content locally: Depending on your development system, it will take up to 15 minutes to collect and generate the HTML content. When done, you can view the HTML output with your browser started at ``doc/_build/html/index.html`` and -if generated, the PDF file is available at ``doc/_build/pdf/zephyr.pdf``. +if generated, the PDF file is available at ``doc/_build/latex/zephyr.pdf``. If you want to build the documentation from scratch just delete the contents of the build folder and run ``cmake`` and then ``ninja`` again. @@ -259,6 +278,25 @@ or invoke make with the following target:: # To generate HTML output without detailed Kconfig make html-fast +Viewing generated documentation locally +*************************************** + +The generated HTML documentation can be hosted locally with python for viewing +with a web browser: + +.. code-block:: console + + $ python3 -m http.server -d _build/html + +.. note:: + + WSL2 users may need to explicitly bind the address to ``127.0.0.1`` in order + to be accessible from the host machine: + + .. code-block:: console + + $ python3 -m http.server -d _build/html --bind 127.0.0.1 + Linking external Doxygen projects against Zephyr ************************************************ diff --git a/doc/contribute/documentation/guidelines.rst b/doc/contribute/documentation/guidelines.rst index fbbc6feb00c..55db8e2e556 100644 --- a/doc/contribute/documentation/guidelines.rst +++ b/doc/contribute/documentation/guidelines.rst @@ -3,6 +3,8 @@ Documentation Guidelines ######################## +.. highlight:: rst + .. note:: For instructions on building the documentation, see :ref:`zephyr_doc`. @@ -11,11 +13,10 @@ Zephyr Project content is written using the `reStructuredText`_ markup language (.rst file extension) with Sphinx extensions, and processed using Sphinx to create a formatted standalone website. Developers can view this content either in its raw form as .rst markup files, or (with -Sphinx installed) they can build the documentation using the Makefile -on Linux systems, or make.bat on Windows, to -generate the HTML content. The HTML content can then be viewed using a -web browser. This same .rst content is also fed into the -`Zephyr documentation`_ website (with a different theme applied). +Sphinx installed) they can :ref:`build the documentation ` locally +to generate the documentation in HTML or PDF format. The HTML content can +then be viewed using a web browser. This same .rst content is served by the +`Zephyr documentation`_ website. You can read details about `reStructuredText`_ and about `Sphinx extensions`_ from their respective websites. @@ -303,9 +304,7 @@ External Cross-Reference Linking With Sphinx's help, we can create link-references to any tagged text within the Zephyr Project documentation. -Target locations in a document are defined with a label directive: - - .. code-block:: rst +Target locations in a document are defined with a label directive:: .. _my label name: @@ -326,10 +325,7 @@ To enable easy cross-page linking within the site, each file should have a reference label before its title so it can be referenced from another file. These reference labels must be unique across the whole site, so generic names such as "samples" should be -avoided. For example the top of this document's .rst file is: - - -.. code-block:: rst +avoided. For example the top of this document's .rst file is:: .. _doc_guidelines: @@ -396,7 +392,7 @@ For example:: .. code-block:: c - struct z_object { + struct k_object { char *name; uint8_t perms[CONFIG_MAX_THREAD_BYTES]; uint8_t type; @@ -412,7 +408,7 @@ This would be rendered as: .. code-block:: c - struct z_object { + struct k_object { char *name; uint8_t perms[CONFIG_MAX_THREAD_BYTES]; uint8_t type; @@ -421,10 +417,93 @@ This would be rendered as: } __packed; -You can specify other languages for the ``code-block`` directive, -including ``c``, ``python``, and ``rst``, and also ``console``, -``bash``, or ``shell``. If you want no syntax highlighting, use the -language ``none``, for example:: +Other languages are of course supported (see `languages supported by Pygments`_), and in particular, +you are encouraged to make use of the following when appropriate: + +.. _`languages supported by Pygments`: http://pygments.org/languages/ + +* ``c`` for C code +* ``cpp`` for C++ code +* ``python`` for Python code +* ``console`` for console output, i.e. interactive shell sessions where commands are prefixed by a + prompt (ex. ``$`` for Linux, or ``uart:~$`` for Zephyr's shell), and where the output is also + shown. The commands will be highlighted, and the output will not. What's more, copying code block + using the "copy" button will automatically copy just the commands, excluding the prompt and the + outputs of the commands. +* ``shell`` or ``bash`` for shell commands. Both languages get highlighted the same but you may use + ``bash`` for conveying that the commands are bash-specific, and ``shell`` for generic shell + commands. + + .. note:: + + Do not use ``bash`` or ``shell`` if your code block includes a prompt, use ``console`` instead. + + Reciprocally, do not use ``console`` if your code block does not include a prompt and is not + showcasing an interactive session with command(s) and their output. + + .. list-table:: When to use ``bash``/``shell`` vs. ``console`` + :class: wrap-normal + :header-rows: 1 + :widths: 20,40,40 + + * - Use case + - ``code-block`` snippet + - Expected output + + * - One or several commands, no output + + - .. code-block:: rst + + .. code-block:: shell + + echo "Hello World!" + + - .. code-block:: shell + + echo "Hello World!" + + * - An interactive shell session with command(s) and their output + + - .. code-block:: rst + + .. code-block:: console + + $ echo "Hello World!" + Hello World! + + - .. code-block:: console + + $ echo "Hello World!" + Hello World! + + * - An interactive Zephyr shell session, with commands and their outputs + + - .. code-block:: rst + + .. code-block:: console + + uart:~$ version + Zephyr version 3.5.99 + uart:~$ kernel uptime + Uptime: 20970 ms + + - .. code-block:: console + + uart:~$ version + Zephyr version 3.5.99 + uart:~$ kernel uptime + Uptime: 20970 ms + +* ``bat`` for Windows batch files +* ``cfg`` for config files with "KEY=value" entries (ex. Kconfig ``.conf`` files) +* ``cmake`` for CMake +* ``devicetree`` for Devicetree +* ``kconfig`` for Kconfig +* ``yaml`` for YAML +* ``rst`` for reStructuredText + +When no language is specified, the language is set to ``none`` and the code block is not +highlighted. You may also use ``none`` explicitly to achieve the same result; for example:: .. code-block:: none @@ -438,11 +517,11 @@ Would display as: This would be a block of text styled with a background and box, but with no syntax highlighting. -There's a shorthand for writing code blocks too: end the introductory -paragraph with a double colon (``::``) and indent the code block content -by three spaces. On output, only one colon will be shown. The -highlighting package makes a best guess at the type of content in the -block and highlighting purposes. +There's a shorthand for writing code blocks too: end the introductory paragraph with a double colon +(``::``) and indent the code block content that follows it by three spaces. On output, only one +colon will be shown. The code block will have no highlighting (i.e. ``none``). You may however use +the ``.. highlight::`` directive to customize the default language used in your document (see for +example how this is done at the beginning of this very document). Images ****** @@ -580,29 +659,3 @@ in the Zephyr setup. Within a tab, you can have most any content *other than a heading* (code-blocks, ordered and unordered lists, pictures, paragraphs, and such). You can read more about sphinx-tabs from the link above. - -Instruction Steps -***************** - -Also introduced in the :ref:`getting_started` is a style that makes it -easy to create tutorial guides with clearly identified steps. Add -the ``.. rst-class:: numbered-step`` directive immediately before a -second-level heading (by project convention, a heading underlined with -asterisks ``******``, and it will be displayed as a numbered step, -sequentially numbered within the document. For example:: - - .. rst-class:: numbered-step - - Put your right hand in - ********************** - -.. rst-class:: numbered-step - -Put your right hand in -********************** - -See the :zephyr_raw:`doc/develop/getting_started/index.rst` source file and -compare with the :ref:`getting_started` to see a full example. As implemented, -only one set of numbered steps is intended per document. - -For instructions on building the documentation, see :ref:`zephyr_doc`. diff --git a/doc/contribute/documentation/index.rst b/doc/contribute/documentation/index.rst deleted file mode 100644 index 0bb801fb36d..00000000000 --- a/doc/contribute/documentation/index.rst +++ /dev/null @@ -1,10 +0,0 @@ -.. _documentation: - -Documentation -############# - -.. toctree:: - :maxdepth: 1 - - guidelines.rst - generation.rst diff --git a/doc/contribute/external.rst b/doc/contribute/external.rst index 2ce1b392edd..e602c94df09 100644 --- a/doc/contribute/external.rst +++ b/doc/contribute/external.rst @@ -103,6 +103,47 @@ With this approach the code is considered as being developed externally, and thus it is not automatically subject to the requirements of the previous section. +Integration in main manifest file (west.yaml) ++++++++++++++++++++++++++++++++++++++++++++++ + +Integrating external code into the main :file:`west.yml` manifest file is +limited to code that is used by a Zephyr subsystem (libraries), by a platform, +drivers (HAL) or tooling needed to test or build Zephyr components. + +The integration of modules in this group is validated by the Zephyr project CI, +and verified to be working with each Zephyr release. + +Integrated modules will not be removed from the tree without a detailed +migration plan. + +Integration as optional modules ++++++++++++++++++++++++++++++++ + +Standalone or loose integration of modules/projects without any incoming +dependencies shall be made optional and shall be kept standalone. Optional +projects that provide value to users directly and through a Zephyr subsystem or +platform shall be added to an optional manifest file that is filtered by +default. (:file:`submanifests/optional.yml`). + +Such optional projects might include samples and tests in their own repositories. + +There shall not be any direct dependency added in the Zephyr code tree (Git +repository) and all sample or test code shall be maintained as part of the module. + +.. note:: + + This is valid for all new optional modules. Existing optional modules with + samples and test code in the Zephyr Git repository will be transitioned out + over time. + +Integration as external modules ++++++++++++++++++++++++++++++++ + +Similar to optional modules, but added to the Zephyr project as an entry in the +documentation using a pre-defined template. This type of modules exists outside the +Zephyr project manifest with documentation instructing users and developers how +to integrate the functionality. + Ongoing maintenance =================== diff --git a/doc/contribute/guidelines.rst b/doc/contribute/guidelines.rst index 82e903580bf..b3dd735dd42 100644 --- a/doc/contribute/guidelines.rst +++ b/doc/contribute/guidelines.rst @@ -316,7 +316,7 @@ Pull Requests and Issues Before starting on a patch, first check in our issues `Zephyr Project Issues`_ system to see what's been reported on the issue you'd like to address. Have a -conversation on the `Zephyr devel mailing list`_ (or the the `Zephyr Discord +conversation on the `Zephyr devel mailing list`_ (or the `Zephyr Discord Server`_) to see what others think of your issue (and proposed solution). You may find others that have encountered the issue you're finding, or that have similar ideas for changes or additions. Send a message to the `Zephyr devel @@ -360,7 +360,7 @@ gitlint When you submit a pull request to the project, a series of checks are performed to verify your commit messages meet the requirements. The same step -done during the CI process can be performed locally using the the ``gitlint`` +done during the CI process can be performed locally using the ``gitlint`` command. Run ``gitlint`` locally in your tree and branch where your patches have been @@ -507,6 +507,7 @@ issues, you can add option --no-verify to the git push command. A more complete alternative to this is using check_compliance.py script from ci-tools repo. +.. _static_analysis: Static Code Analysis ******************** @@ -650,8 +651,8 @@ workflow here: request for the ``main`` branch. The title and message from your commit message should appear as well. -#. GitHub will assign one or more suggested reviewers (based on the - CODEOWNERS file in the repo). If you are a project member, you can +#. A bot will assign one or more suggested reviewers (based on the + MAINTAINERS file in the repo). If you are a project member, you can select additional reviewers now too. #. Click on the submit button and your pull request is sent and awaits @@ -950,10 +951,6 @@ results page where a table with all the different builds will be shown. To see what build or test failed click on the row that contains the failed (i.e. non-green) build. -The `builds@lists.zephyrproject.org mailing list -`_ archives any nightly build results -produced by CI. - Contributions to External Modules ********************************** @@ -1029,3 +1026,18 @@ Some example past treewide changes are: Note that adding a new version of a widely used API while maintaining support for the old one is not a treewide change. Deprecation and removal of such APIs, however, are treewide changes. + +Specialized driver requirements +******************************* + +Drivers for standalone devices should use the Zephyr bus APIs (SPI, I2C...) +whenever possible so that the device can be used with any SoC from any vendor +implementing a compatible bus. + +If it is not technically possible to achieve full performance using the Zephyr +APIs due to specialized accelerators in a particular SoC family, one could +extend the support for an external device by providing a specialized path for +that SoC family. However, the driver must still provide a regular path (via +Zephyr APIs) for all other SoCs. Every exception must be approved by the +Architecture WG in order to be validated and potentially to be learned/improved +from. diff --git a/doc/contribute/index.rst b/doc/contribute/index.rst index d57f5156975..44106539d53 100644 --- a/doc/contribute/index.rst +++ b/doc/contribute/index.rst @@ -3,13 +3,108 @@ Contributing to Zephyr ###################### +Contributions from the community are the backbone of the project. Whether it is by submitting code, +improving documentation, or proposing new features, your efforts are highly appreciated. This page +lists useful resources and guidelines to help you in your contribution journey. + +General Guidelines +================== + .. toctree:: :maxdepth: 1 + :hidden: guidelines.rst - contributor_expectations.rst - proposals_and_rfcs.rst coding_guidelines/index.rst - documentation/index.rst + proposals_and_rfcs.rst + contributor_expectations.rst + +:ref:`contribute_guidelines` + Learn about the overall process and guidelines for contributing to the Zephyr project. + + This page is a mandatory read for first-time contributors as it contains important information on + how to ensure your contribution can be considered for inclusion in the project and potentially + merged. + +:ref:`contributor-expectations` + This document is another mandatory read that describes the expected behavior of `all` + contributors to the project. + +:ref:`coding_guidelines` + Code contributions are expected to follow a set of coding guidelines to ensure consistency and + readability across the code base. + + This page describes these guidelines and introduces important considerations regarding the use of + :ref:`inclusive language `. + +:ref:`rfcs` + Learn when and how to submit RFCs (Request for Comments) for new features and changes to the + project. + +Documentation +============= + +The Zephyr project thrives on good documentation. Whether it is as part of a code contribution or +as a standalone effort, contributing documentation is particularly valuable to the project. + +.. toctree:: + :maxdepth: 1 + :hidden: + + documentation/guidelines.rst + documentation/generation.rst + +:ref:`doc_guidelines` + This page provides some simple guidelines for writing documentation using the reSTructuredText + (reST) markup language and Sphinx documentation generator. + +:ref:`zephyr_doc` + As you write documentation, it can be helpful to see how it will look when rendered. + + This page describes how to build the Zephyr documentation locally. + + +Dealing with external components +================================ + +.. toctree:: + :maxdepth: 1 + :hidden: + external.rst bin_blobs.rst + +:ref:`external-contributions` + Basic functionality or features that would make useful addition to Zephyr might be readily + available in other open source projects, and it is recommended and encouraged to reuse such code. + This page describes in more details when and how to import external source code into Zephyr. + +:ref:`external-tooling` + Similarly, external tooling used during compilation, code analysis, testing or simulation, can be + beneficial and is covered in this section. + +:ref:`bin-blobs` + As some functionality might only be made available with the help of executable code distributed + in binary form, this page describes the process and guidelines for :ref:`contributing binary + blobs ` to the project. + +Zephyr Contributor Badge +======================== + +When your first contribution to the Zephyr project gets merged, you'll become eligible to claim your +Zephyr Contributor Badge. This digital badge can be displayed on your website, blog, social media +profile, etc. It will allow you to showcase your involvement in the Zephyr project and help raise +its awareness. + +You may apply for your Contributor Badge by filling out the `Zephyr Contributor Badge form`_. + +Need help along the way? +======================== + +If you have questions related to the contribution process, the Zephyr community is here to help. +You may join our Discord_ channel or use the `Developer Mailing List`_. + + +.. _Discord: https://chat.zephyrproject.org +.. _Developer Mailing List: https://lists.zephyrproject.org/g/devel +.. _Zephyr Contributor Badge form: https://forms.gle/oCw9iAPLhUsHTapc8 diff --git a/doc/develop/api/overview.rst b/doc/develop/api/overview.rst index c071e286b56..6572ab0f161 100644 --- a/doc/develop/api/overview.rst +++ b/doc/develop/api/overview.rst @@ -37,6 +37,10 @@ between major releases are available in the :ref:`zephyr_release_notes`. - Experimental - 3.4 + * - :ref:`blinfo_api` + - Experimental + - 3.5 + * - :ref:`bluetooth_api` - Stable - 1.0 @@ -49,7 +53,7 @@ between major releases are available in the :ref:`zephyr_release_notes`. - Unstable - 1.10 - * - ``conn_mgr`` + * - :ref:`conn_mgr_docs` - Experimental - 3.4.0 @@ -57,6 +61,14 @@ between major releases are available in the :ref:`zephyr_release_notes`. - Stable - 1.14 + * - :ref:`can_transceiver_api` + - Experimental + - 3.1 + + * - :ref:`charger_api` + - Experimental + - 3.5 + * - :ref:`counter_api` - Unstable - 1.14 @@ -129,9 +141,9 @@ between major releases are available in the :ref:`zephyr_release_notes`. - Stable - 1.11 - * - :ref:`gna_api` + * - :ref:`gnss_api` - Experimental - - 1.14 + - 3.6 * - :ref:`gpio_api` - Stable @@ -161,6 +173,18 @@ between major releases are available in the :ref:`zephyr_release_notes`. - Experimental - 3.2 + * - :ref:`ieee802154_driver_api` + - Unstable + - 1.0 + + * - :ref:`ieee802154_l2_api` + - Unstable + - 1.0 + + * - :ref:`ieee802154_mgmt_api` + - Unstable + - 1.0 + * - :ref:`input` - Experimental - 3.4 @@ -185,6 +209,10 @@ between major releases are available in the :ref:`zephyr_release_notes`. - Unstable - 1.9 + * - :ref:`llext` + - Experimental + - 3.5 + * - :ref:`logging_api` - Stable - 1.13 @@ -205,6 +233,10 @@ between major releases are available in the :ref:`zephyr_release_notes`. - Stable - 1.11 + * - :ref:`modem` + - Experimental + - 3.5 + * - :ref:`mqtt_socket_interface` - Unstable - 1.14 @@ -309,6 +341,10 @@ between major releases are available in the :ref:`zephyr_release_notes`. - Experimental - 3.1 + * - :ref:`tgpio_api` + - Experimental + - 3.5 + * - :ref:`uart_api` - Stable - 1.0 diff --git a/doc/develop/application/index.rst b/doc/develop/application/index.rst index 3fd971ad945..2cd96b3252b 100644 --- a/doc/develop/application/index.rst +++ b/doc/develop/application/index.rst @@ -431,7 +431,7 @@ should know about. * :makevar:`SHIELD`: see :ref:`shields` -* :makevar:`ZEPHYR_MODULES`: A CMake list containing absolute paths of +* :makevar:`ZEPHYR_MODULES`: A `CMake list`_ containing absolute paths of additional directories with source code, Kconfig, etc. that should be used in the application build. See :ref:`modules` for details. If you set this variable, it must be a complete list of all modules to use, as the build @@ -521,6 +521,7 @@ Make sure to follow these steps in order. Structure your :file:`Kconfig` file like this: .. literalinclude:: application-kconfig.include + :language: kconfig .. note:: @@ -700,7 +701,7 @@ be useful for glue code to have access to Zephyr kernel header files. To make it easier to integrate third-party components, the Zephyr build system has defined CMake functions that give application build scripts access to the zephyr compiler options. The functions are -documented and defined in :zephyr_file:`cmake/extensions.cmake` +documented and defined in :zephyr_file:`cmake/modules/extensions.cmake` and follow the naming convention ``zephyr_get__``. The following variables will often need to be exported to the @@ -1053,169 +1054,6 @@ again. target name, for example ``west build -t run_qemu`` or ``ninja run_qemu`` for QEMU. -.. _application_debugging: - -Application Debugging -********************* - -This section is a quick hands-on reference to start debugging your -application with QEMU. Most content in this section is already covered in -`QEMU`_ and `GNU_Debugger`_ reference manuals. - -.. _QEMU: http://wiki.qemu.org/Main_Page - -.. _GNU_Debugger: http://www.gnu.org/software/gdb - -In this quick reference, you'll find shortcuts, specific environmental -variables, and parameters that can help you to quickly set up your debugging -environment. - -The simplest way to debug an application running in QEMU is using the GNU -Debugger and setting a local GDB server in your development system through QEMU. - -You will need an :abbr:`ELF (Executable and Linkable Format)` binary image for -debugging purposes. The build system generates the image in the build -directory. By default, the kernel binary name is :file:`zephyr.elf`. The name -can be changed using :kconfig:option:`CONFIG_KERNEL_BIN_NAME`. - -GDB server -========== - -We will use the standard 1234 TCP port to open a :abbr:`GDB (GNU Debugger)` -server instance. This port number can be changed for a port that best suits the -development environment. There are multiple ways to do this. Each way starts a -QEMU instance with the processor halted at startup and with a GDB server -instance listening for a connection. - -Running QEMU directly -~~~~~~~~~~~~~~~~~~~~~ - -You can run QEMU to listen for a "gdb connection" before it starts executing any -code to debug it. - -.. code-block:: bash - - qemu -s -S - -will setup Qemu to listen on port 1234 and wait for a GDB connection to it. - -The options used above have the following meaning: - -* ``-S`` Do not start CPU at startup; rather, you must type 'c' in the - monitor. -* ``-s`` Shorthand for :literal:`-gdb tcp::1234`: open a GDB server on - TCP port 1234. - - -Running QEMU via :command:`ninja` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Run the following inside the build directory of an application: - -.. code-block:: console - - ninja debugserver - -QEMU will write the console output to the path specified in -:makevar:`${QEMU_PIPE}` via CMake, typically :file:`qemu-fifo` within the build -directory. You may monitor this file during the run with :command:`tail -f -qemu-fifo`. - -Running QEMU via :command:`west` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Run the following from your project root: - -.. code-block:: console - - west build -t debugserver_qemu - -QEMU will write the console output to the terminal from which you invoked -:command:`west`. - -Configuring the :command:`gdbserver` listening device -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The Kconfig option :kconfig:option:`CONFIG_QEMU_GDBSERVER_LISTEN_DEV` controls -the listening device, which can be a TCP port number or a path to a character -device. GDB releases 9.0 and newer also support Unix domain sockets. - -If the option is unset, then the QEMU invocation will lack a ``-s`` or a -``-gdb`` parameter. You can then use the :envvar:`QEMU_EXTRA_FLAGS` shell -environment variable to pass in your own listen device configuration. - -GDB client -========== - -Connect to the server by running :command:`gdb` and giving these commands: - -.. code-block:: bash - - $ path/to/gdb path/to/zephyr.elf - (gdb) target remote localhost:1234 - (gdb) dir ZEPHYR_BASE - -.. note:: - - Substitute the correct :ref:`ZEPHYR_BASE ` for your - system. - -You can use a local GDB configuration :file:`.gdbinit` to initialize your GDB -instance on every run. Your home directory is a typical location for -:file:`.gdbinit`, but you can configure GDB to load from other locations, -including the directory from which you invoked :command:`gdb`. This example -file performs the same configuration as above: - -.. code-block:: none - - target remote localhost:1234 - dir ZEPHYR_BASE - -Alternate interfaces -~~~~~~~~~~~~~~~~~~~~ - -GDB provides a curses-based interface that runs in the terminal. Pass the ``--tui`` -option when invoking :command:`gdb` or give the ``tui enable`` command within -:command:`gdb`. - -.. note:: - - The GDB version on your development system might not support the ``--tui`` - option. Please make sure you use the GDB binary from the SDK which - corresponds to the toolchain that has been used to build the binary. - -Finally, the command below connects to the GDB server using the :abbr:`DDD -(Data Display Debugger)`, a graphical frontend for GDB. The following command -loads the symbol table from the ELF binary file, in this instance, -:file:`zephyr.elf`. - -.. code-block:: bash - - ddd --gdb --debugger "gdb zephyr.elf" - -Both commands execute :command:`gdb`. The command name might -change depending on the toolchain you are using and your cross-development -tools. - -:command:`ddd` may not be installed in your -development system by default. Follow your system instructions to install -it. For example, use :command:`sudo apt-get install ddd` on an Ubuntu system. - -Debugging -========= - -As configured above, when you connect the GDB client, the application will be -stopped at system startup. You may set breakpoints, step through code, etc. as -when running the application directly within :command:`gdb`. - -.. note:: - - :command:`gdb` will not print the system console output as the application runs, - unlike when you run a native application in GDB directly. If you just - :command:`continue` after connecting the client, the application will run, - but nothing will appear to happen. Check the console output as described - above. - .. _custom_board_definition: Custom Board, Devicetree and SOC Definitions @@ -1448,136 +1286,7 @@ Cache variable: :goals: build :compact: - - -Debug with Eclipse -****************** - -Overview -======== - -CMake supports generating a project description file that can be imported into -the Eclipse Integrated Development Environment (IDE) and used for graphical -debugging. - -The `GNU MCU Eclipse plug-ins`_ provide a mechanism to debug ARM projects in -Eclipse with pyOCD, Segger J-Link, and OpenOCD debugging tools. - -The following tutorial demonstrates how to debug a Zephyr application in -Eclipse with pyOCD in Windows. It assumes you have already installed the GCC -ARM Embedded toolchain and pyOCD. - -Set Up the Eclipse Development Environment -========================================== - -#. Download and install `Eclipse IDE for C/C++ Developers`_. - -#. In Eclipse, install the GNU MCU Eclipse plug-ins by opening the menu - ``Window->Eclipse Marketplace...``, searching for ``GNU MCU Eclipse``, and - clicking ``Install`` on the matching result. - -#. Configure the path to the pyOCD GDB server by opening the menu - ``Window->Preferences``, navigating to ``MCU``, and setting the ``Global - pyOCD Path``. - -Generate and Import an Eclipse Project -====================================== - -#. Set up a GNU Arm Embedded toolchain as described in - :ref:`toolchain_gnuarmemb`. - -#. Navigate to a folder outside of the Zephyr tree to build your application. - - .. code-block:: console - - # On Windows - cd %userprofile% - - .. note:: - If the build directory is a subdirectory of the source directory, as is - usually done in Zephyr, CMake will warn: - - "The build directory is a subdirectory of the source directory. - - This is not supported well by Eclipse. It is strongly recommended to use - a build directory which is a sibling of the source directory." - -#. Configure your application with CMake and build it with ninja. Note the - different CMake generator specified by the ``-G"Eclipse CDT4 - Ninja"`` - argument. This will generate an Eclipse project description file, - :file:`.project`, in addition to the usual ninja build files. - - .. zephyr-app-commands:: - :tool: all - :app: %ZEPHYR_BASE%\samples\synchronization - :host-os: win - :board: frdm_k64f - :gen-args: -G"Eclipse CDT4 - Ninja" - :goals: build - :compact: - -#. In Eclipse, import your generated project by opening the menu - ``File->Import...`` and selecting the option ``Existing Projects into - Workspace``. Browse to your application build directory in the choice, - ``Select root directory:``. Check the box for your project in the list of - projects found and click the ``Finish`` button. - -Create a Debugger Configuration -=============================== - -#. Open the menu ``Run->Debug Configurations...``. - -#. Select ``GDB PyOCD Debugging``, click the ``New`` button, and configure the - following options: - - - In the Main tab: - - - Project: ``my_zephyr_app@build`` - - C/C++ Application: :file:`zephyr/zephyr.elf` - - - In the Debugger tab: - - - pyOCD Setup - - - Executable path: :file:`${pyocd_path}\\${pyocd_executable}` - - Uncheck "Allocate console for semihosting" - - - Board Setup - - - Bus speed: 8000000 Hz - - Uncheck "Enable semihosting" - - - GDB Client Setup - - - Executable path example (use your ``GNUARMEMB_TOOLCHAIN_PATH``): - :file:`C:\\gcc-arm-none-eabi-6_2017-q2-update\\bin\\arm-none-eabi-gdb.exe` - - - In the SVD Path tab: - - - File path: :file:`\\modules\\hal\\nxp\\mcux\\devices\\MK64F12\\MK64F12.xml` - - .. note:: - This is optional. It provides the SoC's memory-mapped register - addresses and bitfields to the debugger. - -#. Click the ``Debug`` button to start debugging. - -RTOS Awareness -============== - -Support for Zephyr RTOS awareness is implemented in `pyOCD v0.11.0`_ and later. -It is compatible with GDB PyOCD Debugging in Eclipse, but you must enable -CONFIG_DEBUG_THREAD_INFO=y in your application. - - - .. _CMake: https://www.cmake.org .. _CMake introduction: https://cmake.org/cmake/help/latest/manual/cmake.1.html#description -.. _Eclipse IDE for C/C++ Developers: https://www.eclipse.org/downloads/packages/eclipse-ide-cc-developers/oxygen2 -.. _GNU MCU Eclipse plug-ins: https://gnu-mcu-eclipse.github.io/plugins/install/ -.. _pyOCD v0.11.0: https://github.com/mbedmicro/pyOCD/releases/tag/v0.11.0 .. _CMake list: https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#lists -.. _add_subdirectory(): https://cmake.org/cmake/help/latest/command/add_subdirectory.html -.. _using Chocolatey: https://chocolatey.org/packages/RapidEE .. _example-application: https://github.com/zephyrproject-rtos/example-application diff --git a/doc/develop/beyond-GSG.rst b/doc/develop/beyond-GSG.rst index 13ea085ada0..1b9aab82644 100644 --- a/doc/develop/beyond-GSG.rst +++ b/doc/develop/beyond-GSG.rst @@ -177,14 +177,15 @@ Build and Run an Application You can build, flash, and run Zephyr applications on real hardware using a supported host system. Depending on your operating system, -you can also run it in emulation with QEMU, or as a native POSIX application. +you can also run it in emulation with QEMU, or as a native application with +:ref:`native_sim `. Additional information about building applications can be found in the :ref:`build_an_application` section. Build Blinky ============ -Let's build the :ref:`blinky-sample` sample application. +Let's build the :zephyr:code-sample:`blinky` sample application. Zephyr applications are built to run on specific hardware, called a "board"\ [#board_misnomer]_. We'll use the Phytec :ref:`reel_board @@ -291,22 +292,21 @@ To exit QEMU, type :kbd:`Ctrl-a`, then :kbd:`x`. Use ``qemu_cortex_m3`` to target an emulated Arm Cortex-M3 sample. -.. _gs_posix: +.. _gs_native: -Run a Sample Application natively (POSIX OS) -============================================ +Run a Sample Application natively (Linux) +========================================= -You can compile some samples to run as host processes -on a POSIX OS. This is currently only tested on Linux hosts. See -:ref:`native_posix` for more information. On 64-bit host operating systems, you -need to install a 32-bit C library; see :ref:`native_posix_deps` for details. +You can compile some samples to run as host programs +on Linux. See :ref:`native_sim` for more information. On 64-bit host operating systems, you +need to install a 32-bit C library, or build targeting :ref:`native_sim_64 `. -First, build Hello World for ``native_posix``. +First, build Hello World for ``native_sim``. .. zephyr-app-commands:: :zephyr-app: samples/hello_world :host-os: unix - :board: native_posix + :board: native_sim :goals: build Next, run the application. diff --git a/doc/develop/debug/index.rst b/doc/develop/debug/index.rst new file mode 100644 index 00000000000..a7afdab8c31 --- /dev/null +++ b/doc/develop/debug/index.rst @@ -0,0 +1,366 @@ +.. _develop_debug: + +Debugging +######### + +.. _application_debugging: + +Application Debugging +********************* + +This section is a quick hands-on reference to start debugging your +application with QEMU. Most content in this section is already covered in +`QEMU`_ and `GNU_Debugger`_ reference manuals. + +.. _QEMU: http://wiki.qemu.org/Main_Page + +.. _GNU_Debugger: http://www.gnu.org/software/gdb + +In this quick reference, you'll find shortcuts, specific environmental +variables, and parameters that can help you to quickly set up your debugging +environment. + +The simplest way to debug an application running in QEMU is using the GNU +Debugger and setting a local GDB server in your development system through QEMU. + +You will need an :abbr:`ELF (Executable and Linkable Format)` binary image for +debugging purposes. The build system generates the image in the build +directory. By default, the kernel binary name is :file:`zephyr.elf`. The name +can be changed using :kconfig:option:`CONFIG_KERNEL_BIN_NAME`. + +GDB server +========== + +We will use the standard 1234 TCP port to open a :abbr:`GDB (GNU Debugger)` +server instance. This port number can be changed for a port that best suits the +development environment. There are multiple ways to do this. Each way starts a +QEMU instance with the processor halted at startup and with a GDB server +instance listening for a connection. + +Running QEMU directly +~~~~~~~~~~~~~~~~~~~~~ + +You can run QEMU to listen for a "gdb connection" before it starts executing any +code to debug it. + +.. code-block:: bash + + qemu -s -S + +will setup Qemu to listen on port 1234 and wait for a GDB connection to it. + +The options used above have the following meaning: + +* ``-S`` Do not start CPU at startup; rather, you must type 'c' in the + monitor. +* ``-s`` Shorthand for :literal:`-gdb tcp::1234`: open a GDB server on + TCP port 1234. + + +Running QEMU via :command:`ninja` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Run the following inside the build directory of an application: + +.. code-block:: console + + ninja debugserver + +QEMU will write the console output to the path specified in +:makevar:`${QEMU_PIPE}` via CMake, typically :file:`qemu-fifo` within the build +directory. You may monitor this file during the run with :command:`tail -f +qemu-fifo`. + +Running QEMU via :command:`west` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Run the following from your project root: + +.. code-block:: console + + west build -t debugserver_qemu + +QEMU will write the console output to the terminal from which you invoked +:command:`west`. + +Configuring the :command:`gdbserver` listening device +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Kconfig option :kconfig:option:`CONFIG_QEMU_GDBSERVER_LISTEN_DEV` controls +the listening device, which can be a TCP port number or a path to a character +device. GDB releases 9.0 and newer also support Unix domain sockets. + +If the option is unset, then the QEMU invocation will lack a ``-s`` or a +``-gdb`` parameter. You can then use the :envvar:`QEMU_EXTRA_FLAGS` shell +environment variable to pass in your own listen device configuration. + +GDB client +========== + +Connect to the server by running :command:`gdb` and giving these commands: + +.. code-block:: bash + + $ path/to/gdb path/to/zephyr.elf + (gdb) target remote localhost:1234 + (gdb) dir ZEPHYR_BASE + +.. note:: + + Substitute the correct :ref:`ZEPHYR_BASE ` for your + system. + +You can use a local GDB configuration :file:`.gdbinit` to initialize your GDB +instance on every run. Your home directory is a typical location for +:file:`.gdbinit`, but you can configure GDB to load from other locations, +including the directory from which you invoked :command:`gdb`. This example +file performs the same configuration as above: + +.. code-block:: none + + target remote localhost:1234 + dir ZEPHYR_BASE + +Alternate interfaces +~~~~~~~~~~~~~~~~~~~~ + +GDB provides a curses-based interface that runs in the terminal. Pass the ``--tui`` +option when invoking :command:`gdb` or give the ``tui enable`` command within +:command:`gdb`. + +.. note:: + + The GDB version on your development system might not support the ``--tui`` + option. Please make sure you use the GDB binary from the SDK which + corresponds to the toolchain that has been used to build the binary. + +Finally, the command below connects to the GDB server using the :abbr:`DDD +(Data Display Debugger)`, a graphical frontend for GDB. The following command +loads the symbol table from the ELF binary file, in this instance, +:file:`zephyr.elf`. + +.. code-block:: bash + + ddd --gdb --debugger "gdb zephyr.elf" + +Both commands execute :command:`gdb`. The command name might +change depending on the toolchain you are using and your cross-development +tools. + +:command:`ddd` may not be installed in your +development system by default. Follow your system instructions to install +it. For example, use :command:`sudo apt-get install ddd` on an Ubuntu system. + +Debugging +========= + +As configured above, when you connect the GDB client, the application will be +stopped at system startup. You may set breakpoints, step through code, etc. as +when running the application directly within :command:`gdb`. + +.. note:: + + :command:`gdb` will not print the system console output as the application runs, + unlike when you run a native application in GDB directly. If you just + :command:`continue` after connecting the client, the application will run, + but nothing will appear to happen. Check the console output as described + above. + +Debug with Eclipse +****************** + +Overview +======== + +CMake supports generating a project description file that can be imported into +the Eclipse Integrated Development Environment (IDE) and used for graphical +debugging. + +The `GNU MCU Eclipse plug-ins`_ provide a mechanism to debug ARM projects in +Eclipse with pyOCD, Segger J-Link, and OpenOCD debugging tools. + +The following tutorial demonstrates how to debug a Zephyr application in +Eclipse with pyOCD in Windows. It assumes you have already installed the GCC +ARM Embedded toolchain and pyOCD. + +Set Up the Eclipse Development Environment +========================================== + +#. Download and install `Eclipse IDE for C/C++ Developers`_. + +#. In Eclipse, install the `GNU MCU Eclipse plug-ins`_ by opening the menu + ``Window->Eclipse Marketplace...``, searching for ``GNU MCU Eclipse``, and + clicking ``Install`` on the matching result. + +#. Configure the path to the pyOCD GDB server by opening the menu + ``Window->Preferences``, navigating to ``MCU``, and setting the ``Global + pyOCD Path``. + +Generate and Import an Eclipse Project +====================================== + +#. Set up a GNU Arm Embedded toolchain as described in + :ref:`toolchain_gnuarmemb`. + +#. Navigate to a folder outside of the Zephyr tree to build your application. + + .. code-block:: console + + # On Windows + cd %userprofile% + + .. note:: + If the build directory is a subdirectory of the source directory, as is + usually done in Zephyr, CMake will warn: + + "The build directory is a subdirectory of the source directory. + + This is not supported well by Eclipse. It is strongly recommended to use + a build directory which is a sibling of the source directory." + +#. Configure your application with CMake and build it with ninja. Note the + different CMake generator specified by the ``-G"Eclipse CDT4 - Ninja"`` + argument. This will generate an Eclipse project description file, + :file:`.project`, in addition to the usual ninja build files. + + .. zephyr-app-commands:: + :tool: all + :app: %ZEPHYR_BASE%\samples\synchronization + :host-os: win + :board: frdm_k64f + :gen-args: -G"Eclipse CDT4 - Ninja" + :goals: build + :compact: + +#. In Eclipse, import your generated project by opening the menu + ``File->Import...`` and selecting the option ``Existing Projects into + Workspace``. Browse to your application build directory in the choice, + ``Select root directory:``. Check the box for your project in the list of + projects found and click the ``Finish`` button. + +Create a Debugger Configuration +=============================== + +#. Open the menu ``Run->Debug Configurations...``. + +#. Select ``GDB PyOCD Debugging``, click the ``New`` button, and configure the + following options: + + - In the Main tab: + + - Project: ``my_zephyr_app@build`` + - C/C++ Application: :file:`zephyr/zephyr.elf` + + - In the Debugger tab: + + - pyOCD Setup + + - Executable path: :file:`${pyocd_path}\\${pyocd_executable}` + - Uncheck "Allocate console for semihosting" + + - Board Setup + + - Bus speed: 8000000 Hz + - Uncheck "Enable semihosting" + + - GDB Client Setup + + - Executable path example (use your ``GNUARMEMB_TOOLCHAIN_PATH``): + :file:`C:\\gcc-arm-none-eabi-6_2017-q2-update\\bin\\arm-none-eabi-gdb.exe` + + - In the SVD Path tab: + + - File path: :file:`\\modules\\hal\\nxp\\mcux\\devices\\MK64F12\\MK64F12.xml` + + .. note:: + This is optional. It provides the SoC's memory-mapped register + addresses and bitfields to the debugger. + +#. Click the ``Debug`` button to start debugging. + +RTOS Awareness +============== + +Support for Zephyr RTOS awareness is implemented in `pyOCD v0.11.0`_ and later. +It is compatible with GDB PyOCD Debugging in Eclipse, but you must enable +CONFIG_DEBUG_THREAD_INFO=y in your application. + +Debugging I2C communication +*************************** + +There is a possibility to log all or some of the I2C transactions done by the application. +This feature is enabled by the Kconfig option :kconfig:option:`CONFIG_I2C_DUMP_MESSAGES`, but it +uses the ``LOG_DBG`` function to print the contents so the +:kconfig:option:`CONFIG_I2C_LOG_LEVEL_DBG` option must also be enabled. + +The sample output of the dump looks like this:: + + D: I2C msg: io_i2c_ctrl7_port0, addr=50 + D: W len=01: 00 + D: R Sr P len=08: + D: contents: + D: 43 42 41 00 00 00 00 00 |CBA..... + +The first line indicates the I2C controller and the target address of the transaction. +In above example, the I2C controller is named ``io_i2c_ctrl7_port0`` and the target device address +is ``0x50`` + +.. note:: + + the address, length and contents values are in hexadecimal, but lack the ``0x`` prefix + +Next lines contain messages, both sent and received. The contents of write messages is +always shown, while the content of read messages is controlled by a parameter to the +function ``i2c_dump_msgs_rw``. This function is available for use by user, but is also +called internally by ``i2c_transfer`` API function with read content dump enabled. +Before the length parameter, the header of the message is printed using abbreviations: + + - W - write message + - R - read message + - Sr - restart bit + - P - stop bit + +The above example shows one write message with byte ``0x00`` representing the address of register to +read from the I2C target. After that the log shows the length of received message and following +that, the bytes read from the target ``43 42 41 00 00 00 00 00``. +The content dump consist of both the hex and ASCII representation. + +Filtering the I2C communication dump +==================================== + +By default, all I2C communication is logged between all I2C controllers and I2C targets. +It may litter the log with unrelated devices and make it difficult to effectively debug the +communication with a device of interest. + +Enable the Kconfig option :kconfig:option:`CONFIG_I2C_DUMP_MESSAGES_ALLOWLIST` to create an +allowlist of I2C targets to log. +The allowlist of devices is configured using the devicetree, for example:: + + / { + i2c { + display0: some-display@a { + ... + }; + sensor3: some-sensor@b { + ... + }; + }; + + i2c-dump-allowlist { + compatible = "zephyr,i2c-dump-allowlist"; + devices = < &display0 >, < &sensor3 >; + }; + }; + +The filters nodes are identified by the compatible string with ``zephyr,i2c-dump-allowlist`` value. +The devices are selected using the ``devices`` property with phandles to the devices on the I2C bus. + +In the above example, the communication with device ``display0`` and ``sensor3`` will be displayed +in the log. + + + +.. _Eclipse IDE for C/C++ Developers: https://www.eclipse.org/downloads/packages/eclipse-ide-cc-developers/oxygen2 +.. _GNU MCU Eclipse plug-ins: https://gnu-mcu-eclipse.github.io/plugins/install/ +.. _pyOCD v0.11.0: https://github.com/mbedmicro/pyOCD/releases/tag/v0.11.0 diff --git a/doc/develop/env_vars.rst b/doc/develop/env_vars.rst index 459c62b580a..fba31b7735e 100644 --- a/doc/develop/env_vars.rst +++ b/doc/develop/env_vars.rst @@ -72,7 +72,7 @@ Option 2: In all Terminals You can then run ``rapidee`` from your terminal to launch the program and set environment variables. Make sure to use the "User" environment variables area -- otherwise, you have to run RapidEE as administrator. Also make sure to save - your changes by clicking the Save button at top left before exiting.Settings + your changes by clicking the Save button at top left before exiting. Settings you make in RapidEE will be available whenever you open a new terminal window. .. _env_vars_zephyrrc: diff --git a/doc/develop/flash_debug/host-tools.rst b/doc/develop/flash_debug/host-tools.rst index 981c89ce686..cf349d5d29d 100644 --- a/doc/develop/flash_debug/host-tools.rst +++ b/doc/develop/flash_debug/host-tools.rst @@ -377,6 +377,68 @@ Zephyr RTOS Awareness To enable Zephyr RTOS awareness follow the steps described in `Lauterbach TRACE32 Zephyr OS Awareness Manual`_. +.. _nxp-s32-debug-host-tools: + +NXP S32 Debug Probe Host Tools +****************************** + +:ref:`nxp-s32-debug-probe` is designed to work in conjunction with +`NXP S32 Design Studio for S32 Platform`_. + +Download (registration required) NXP S32 Design Studio for S32 Platform and +follow the `S32 Design Studio for S32 Platform Installation User Guide`_ to get +the necessary debug host tools and associated USB device drivers. + +Note that Zephyr RTOS-awareness support for the NXP S32 GDB server depends on +the target device. Consult the product release notes for more information. + +Supported west commands: + +1. debug +#. debugserver +#. attach + +Basic usage +----------- + +Before starting, add NXP S32 Design Studio installation directory to the system +:ref:`PATH environment variable `. Alternatively, it can be passed to +the runner on each invocation via ``--s32ds-path`` as shown below: + +.. tabs:: + + .. group-tab:: Linux + + .. code-block:: console + + west debug --s32ds-path=/opt/NXP/S32DS.3.5 + + .. group-tab:: Windows + + .. code-block:: console + + west debug --s32ds-path=C:\NXP\S32DS.3.5 + +If multiple S32 debug probes are connected to the host via USB, the runner will +ask the user to select one via command line prompt before continuing. The +connection string for the probe can be also specified when invoking the runner +via ``--dev-id=``. Consult NXP S32 debug probe user manual +for details on how to construct the connection string. For example, if using a +probe with serial ID ``00:04:9f:00:ca:fe``: + +.. code-block:: console + + west debug --dev-id='s32dbg:00:04:9f:00:ca:fe' + +It is possible to pass extra options to the debug host tools via ``--tool-opt``. +When executing ``debug`` or ``attach`` commands, the tool options will be passed +to the GDB client only. When executing ``debugserver``, the tool options will be +passed to the GDB server. For example, to load a Zephyr application to SRAM and +afterwards detach the debug session: + +.. code-block:: console + + west debug --tool-opt='--batch' .. _J-Link Software and Documentation Pack: https://www.segger.com/downloads/jlink/#J-LinkSoftwareAndDocumentationPack @@ -416,3 +478,9 @@ To enable Zephyr RTOS awareness follow the steps described in .. _MCUXpresso Installer: https://www.nxp.com/lgfiles/updates/mcuxpresso/MCUXpressoInstaller.exe + +.. _NXP S32 Design Studio for S32 Platform: + https://www.nxp.com/design/software/development-software/s32-design-studio-ide/s32-design-studio-for-s32-platform:S32DS-S32PLATFORM + +.. _S32 Design Studio for S32 Platform Installation User Guide: + https://www.nxp.com/webapp/Download?colCode=S32DSIG diff --git a/doc/develop/flash_debug/probes.rst b/doc/develop/flash_debug/probes.rst index 83f355aadba..0e237a6fcf6 100644 --- a/doc/develop/flash_debug/probes.rst +++ b/doc/develop/flash_debug/probes.rst @@ -33,21 +33,23 @@ host tools, or with J-Link firmware to communicate with J-Link debug host tools. -+---------------------------------------+---------------------------------------------------------------+ -|| *Debug Probes & Host Tools* | Host Tools | -+| *Compatibility Chart* +--------------------+--------------------+---------------------+ -| | **J-Link Debug** | **OpenOCD** | **pyOCD** | -+----------------+----------------------+--------------------+--------------------+---------------------+ -| | **LPC-Link2 J-Link** | ✓ | | | -| +----------------------+--------------------+--------------------+---------------------+ -| | **OpenSDA DAPLink** | | ✓ | ✓ | -| +----------------------+--------------------+--------------------+---------------------+ -| Debug Probes | **OpenSDA J-Link** | ✓ | | | -| +----------------------+--------------------+--------------------+---------------------+ -| | **J-Link External** | ✓ | ✓ | | -| +----------------------+--------------------+--------------------+---------------------+ -| | **ST-LINK/V2-1** | ✓ | ✓ | *some STM32 boards* | -+----------------+----------------------+--------------------+--------------------+---------------------+ ++------------------------------------------+------------------------------------------------------------------------------------+ +|| *Debug Probes & Host Tools* | Host Tools | ++| *Compatibility Chart* +--------------------+--------------------+---------------------+--------------------+ +| | **J-Link Debug** | **OpenOCD** | **pyOCD** | **NXP S32DS** | ++----------------+-------------------------+--------------------+--------------------+---------------------+--------------------+ +| | **LPC-Link2 J-Link** | ✓ | | | | +| +-------------------------+--------------------+--------------------+---------------------+--------------------+ +| | **OpenSDA DAPLink** | | ✓ | ✓ | | +| +-------------------------+--------------------+--------------------+---------------------+--------------------+ +| Debug Probes | **OpenSDA J-Link** | ✓ | | | | +| +-------------------------+--------------------+--------------------+---------------------+--------------------+ +| | **J-Link External** | ✓ | ✓ | | | +| +-------------------------+--------------------+--------------------+---------------------+--------------------+ +| | **ST-LINK/V2-1** | ✓ | ✓ | *some STM32 boards* | | +| +-------------------------+--------------------+--------------------+---------------------+--------------------+ +| | **NXP S32 Debug Probe** | | | | ✓ | ++----------------+-------------------------+--------------------+--------------------+---------------------+--------------------+ Some supported boards in Zephyr do not include an onboard debug probe and @@ -373,6 +375,20 @@ Where board_uid can be obtained using twister's generate-hardware-map option. For more information about twister and available options, see :ref:`twister_script`. +.. _nxp-s32-debug-probe: + +NXP S32 Debug Probe +******************* + +`NXP S32 Debug Probe`_ enables NXP S32 target system debugging via a standard +debug port while connected to a developer's workstation via USB or remotely via +Ethernet. + +NXP S32 Debug Probe is designed to work in conjunction with NXP S32 Design Studio +(S32DS) and NXP Automotive microcontrollers and processors. Install the debug +host tools as in indicated in :ref:`nxp-s32-debug-host-tools` before you program +the firmware. + .. _LPCScrypt: https://www.nxp.com/lpcscrypt @@ -402,3 +418,6 @@ option. For more information about twister and available options, see .. _MCUXpresso Installer: https://www.nxp.com/lgfiles/updates/mcuxpresso/MCUXpressoInstaller.exe + +.. _NXP S32 Debug Probe: + https://www.nxp.com/design/software/automotive-software-and-tools/s32-debug-probe:S32-DP diff --git a/doc/develop/getting_started/index.rst b/doc/develop/getting_started/index.rst index f7a76a71585..d95651121bf 100644 --- a/doc/develop/getting_started/index.rst +++ b/doc/develop/getting_started/index.rst @@ -13,8 +13,6 @@ Follow this guide to: .. _host_setup: -.. rst-class:: numbered-step - Select and Update OS ******************** @@ -24,7 +22,7 @@ Click the operating system you are using. .. group-tab:: Ubuntu - This guide covers Ubuntu version 18.04 LTS and later. + This guide covers Ubuntu version 20.04 LTS and later. .. code-block:: bash @@ -46,8 +44,6 @@ Click the operating system you are using. .. _install-required-tools: -.. rst-class:: numbered-step - Install dependencies ******************** @@ -98,7 +94,9 @@ The current minimum required version for the main dependencies are: python3-dev python3-pip python3-setuptools python3-tk python3-wheel xz-utils file \ make gcc gcc-multilib g++-multilib libsdl2-dev libmagic1 - #. Verify the versions of the main dependencies installed on your system by entering:: + #. Verify the versions of the main dependencies installed on your system by entering: + + .. code-block:: bash cmake --version python3 --version @@ -134,7 +132,7 @@ The current minimum required version for the main dependencies are: .. code-block:: bash - brew install cmake ninja gperf python3 ccache qemu dtc wget libmagic + brew install cmake ninja gperf python3 ccache qemu dtc libmagic #. Add the Homebrew Python folder to the path, in order to be able to execute ``python`` and ``pip`` as well ``python3`` and ``pip3``. @@ -156,8 +154,9 @@ The current minimum required version for the main dependencies are: Therefore, we don't recommend using WSL when getting started. - These instructions must be run in a ``cmd.exe`` command prompt. The - required commands differ on PowerShell. + These instructions must be run in a ``cmd.exe`` command prompt terminal window. + In modern version of Windows (10 and later) it is recommended to install the Windows Terminal + application from the Microsoft Store. The required commands differ on PowerShell. These instructions rely on `Chocolatey`_. If Chocolatey isn't an option, you can install dependencies from their respective websites and ensure @@ -170,25 +169,30 @@ The current minimum required version for the main dependencies are: #. `Install chocolatey`_. - #. Open a ``cmd.exe`` window as **Administrator**. To do so, press the Windows key, - type "cmd.exe", right-click the result, and choose :guilabel:`Run as - Administrator`. + #. Open a ``cmd.exe`` terminal window as **Administrator**. To do so, press the Windows key, + type ``cmd.exe``, right-click the :guilabel:`Command Prompt`` search result, and choose + :guilabel:`Run as Administrator`. #. Disable global confirmation to avoid having to confirm the installation of individual programs: - .. code-block:: console + .. code-block:: bat choco feature enable -n allowGlobalConfirmation #. Use ``choco`` to install the required dependencies: - .. code-block:: console + .. code-block:: bat choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' - choco install ninja gperf python git dtc-msys2 wget 7zip + choco install ninja gperf python311 git dtc-msys2 wget 7zip + + .. warning:: + + As of November 2023, Python 3.12 is not recommended for Zephyr development on Windows, + as some required Python dependencies may be difficult to install. - #. Close the window and open a new ``cmd.exe`` window **as a regular user** to continue. + #. Close the terminal window. .. _Chocolatey: https://chocolatey.org/ .. _Install chocolatey: https://chocolatey.org/install @@ -198,8 +202,6 @@ The current minimum required version for the main dependencies are: .. _install_py_requirements: .. _gs_python_deps: -.. rst-class:: numbered-step - Get Zephyr and install Python dependencies ****************************************** @@ -272,7 +274,7 @@ additional Python dependencies. automatically load boilerplate code required for building Zephyr applications. - .. code-block:: console + .. code-block:: bash west zephyr-export @@ -306,7 +308,7 @@ additional Python dependencies. automatically load boilerplate code required for building Zephyr applications. - .. code-block:: console + .. code-block:: bash west zephyr-export @@ -362,7 +364,7 @@ additional Python dependencies. automatically load boilerplate code required for building Zephyr applications. - .. code-block:: console + .. code-block:: bash west zephyr-export @@ -393,7 +395,7 @@ additional Python dependencies. automatically load boilerplate code required for building Zephyr applications. - .. code-block:: console + .. code-block:: bash west zephyr-export @@ -410,6 +412,8 @@ additional Python dependencies. .. group-tab:: Install within virtual environment + #. Open a ``cmd.exe`` terminal window **as a regular user** + #. Create a new virtual environment: .. code-block:: bat @@ -421,10 +425,7 @@ additional Python dependencies. .. code-block:: bat - :: cmd.exe zephyrproject\.venv\Scripts\activate.bat - :: PowerShell - zephyrproject\.venv\Scripts\Activate.ps1 Once activated your shell will be prefixed with ``(.venv)``. The virtual environment can be deactivated at any time by running @@ -437,13 +438,13 @@ additional Python dependencies. #. Install west: - .. code-block:: bash + .. code-block:: bat pip install west #. Get the Zephyr source code: - .. code-block:: bash + .. code-block:: bat west init zephyrproject cd zephyrproject @@ -453,19 +454,21 @@ additional Python dependencies. automatically load boilerplate code required for building Zephyr applications. - .. code-block:: console + .. code-block:: bat west zephyr-export #. Zephyr's ``scripts\requirements.txt`` file declares additional Python dependencies. Install them with ``pip``. - .. code-block:: bash + .. code-block:: bat pip install -r %HOMEPATH%\zephyrproject\zephyr\scripts\requirements.txt .. group-tab:: Install globally + #. Open a ``cmd.exe`` terminal window **as a regular user** + #. Install west: .. code-block:: bat @@ -496,11 +499,9 @@ additional Python dependencies. pip3 install -r %HOMEPATH%\zephyrproject\zephyr\scripts\requirements.txt -.. rst-class:: numbered-step - -Install Zephyr SDK -****************** +Install the Zephyr SDK +********************** The :ref:`Zephyr Software Development Kit (SDK) ` contains toolchains for each of Zephyr's supported architectures, which @@ -510,174 +511,25 @@ Zephyr applications. It also contains additional host tools, such as custom QEMU and OpenOCD builds that are used to emulate, flash and debug Zephyr applications. -.. tabs:: - - .. group-tab:: Ubuntu - - .. _ubuntu_zephyr_sdk: - - #. Download and verify the `Zephyr SDK bundle - `_: - - .. code-block:: bash - - cd ~ - wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/zephyr-sdk-0.16.1_linux-x86_64.tar.xz - wget -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/sha256.sum | shasum --check --ignore-missing - - If your host architecture is 64-bit ARM (for example, Raspberry Pi), replace ``x86_64`` - with ``aarch64`` in order to download the 64-bit ARM Linux SDK. - - #. Extract the Zephyr SDK bundle archive: - - .. code-block:: bash - - tar xvf zephyr-sdk-0.16.1_linux-x86_64.tar.xz - - .. note:: - It is recommended to extract the Zephyr SDK bundle at one of the following locations: - - * ``$HOME`` - * ``$HOME/.local`` - * ``$HOME/.local/opt`` - * ``$HOME/bin`` - * ``/opt`` - * ``/usr/local`` - - The Zephyr SDK bundle archive contains the ``zephyr-sdk-0.16.1`` directory and, when - extracted under ``$HOME``, the resulting installation path will be - ``$HOME/zephyr-sdk-0.16.1``. - - #. Run the Zephyr SDK bundle setup script: - - .. code-block:: bash - - cd zephyr-sdk-0.16.1 - ./setup.sh - - .. note:: - You only need to run the setup script once after extracting the Zephyr SDK bundle. - - You must rerun the setup script if you relocate the Zephyr SDK bundle directory after - the initial setup. - - #. Install `udev `_ rules, which - allow you to flash most Zephyr boards as a regular user: - - .. code-block:: bash - - sudo cp ~/zephyr-sdk-0.16.1/sysroots/x86_64-pokysdk-linux/usr/share/openocd/contrib/60-openocd.rules /etc/udev/rules.d - sudo udevadm control --reload - - .. group-tab:: macOS - - .. _macos_zephyr_sdk: - - #. Download and verify the `Zephyr SDK bundle - `_: - - .. code-block:: bash - - cd ~ - wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/zephyr-sdk-0.16.1_macos-x86_64.tar.xz - wget -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/sha256.sum | shasum --check --ignore-missing - - If your host architecture is 64-bit ARM (Apple Silicon, also known as M1), replace - ``x86_64`` with ``aarch64`` in order to download the 64-bit ARM macOS SDK. - - #. Extract the Zephyr SDK bundle archive: - - .. code-block:: bash - - tar xvf zephyr-sdk-0.16.1_macos-x86_64.tar.xz - - .. note:: - It is recommended to extract the Zephyr SDK bundle at one of the following locations: - - * ``$HOME`` - * ``$HOME/.local`` - * ``$HOME/.local/opt`` - * ``$HOME/bin`` - * ``/opt`` - * ``/usr/local`` - - The Zephyr SDK bundle archive contains the ``zephyr-sdk-0.16.1`` directory and, when - extracted under ``$HOME``, the resulting installation path will be - ``$HOME/zephyr-sdk-0.16.1``. - - #. Run the Zephyr SDK bundle setup script: - - .. code-block:: bash - - cd zephyr-sdk-0.16.1 - ./setup.sh - - .. note:: - You only need to run the setup script once after extracting the Zephyr SDK bundle. - - You must rerun the setup script if you relocate the Zephyr SDK bundle directory after - the initial setup. - - .. group-tab:: Windows - - .. _windows_zephyr_sdk: - - #. Open a ``cmd.exe`` window by pressing the Windows key typing "cmd.exe". - - #. Download the `Zephyr SDK bundle - `_: - - .. code-block:: console - - cd %HOMEPATH% - wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/zephyr-sdk-0.16.1_windows-x86_64.7z - - #. Extract the Zephyr SDK bundle archive: - - .. code-block:: console - - 7z x zephyr-sdk-0.16.1_windows-x86_64.7z - - .. note:: - It is recommended to extract the Zephyr SDK bundle at one of the following locations: - - * ``%HOMEPATH%`` - * ``%PROGRAMFILES%`` - - The Zephyr SDK bundle archive contains the ``zephyr-sdk-0.16.1`` directory and, when - extracted under ``%HOMEPATH%``, the resulting installation path will be - ``%HOMEPATH%\zephyr-sdk-0.16.1``. - - #. Run the Zephyr SDK bundle setup script: - - .. code-block:: console - - cd zephyr-sdk-0.16.1 - setup.cmd - - .. note:: - You only need to run the setup script once after extracting the Zephyr SDK bundle. - - You must rerun the setup script if you relocate the Zephyr SDK bundle directory after - the initial setup. +.. include:: ../toolchains/zephyr_sdk.rst + :start-after: toolchain_zephyr_sdk_install_start + :end-before: toolchain_zephyr_sdk_install_end .. _getting_started_run_sample: -.. rst-class:: numbered-step - Build the Blinky Sample *********************** .. note:: - Blinky is compatible with most, but not all, :ref:`boards`. If your board + :zephyr:code-sample:`blinky` is compatible with most, but not all, :ref:`boards`. If your board does not meet Blinky's :ref:`blinky-sample-requirements`, then :ref:`hello_world` is a good alternative. If you are unsure what name west uses for your board, ``west boards`` can be used to obtain a list of all boards Zephyr supports. -Build the :ref:`blinky-sample` with :ref:`west build `, changing +Build the :zephyr:code-sample:`blinky` with :ref:`west build `, changing ```` appropriately for your board: .. tabs:: @@ -708,8 +560,6 @@ users. Users may also use the ``-p auto`` option, which will use heuristics to determine if a pristine build is required, such as when building another sample. -.. rst-class:: numbered-step - Flash the Sample **************** @@ -718,7 +568,7 @@ If in doubt about what to do, check your board's page in :ref:`boards`. Then flash the sample using :ref:`west flash `: -.. code-block:: console +.. code-block:: shell west flash diff --git a/doc/develop/getting_started/installation_linux.rst b/doc/develop/getting_started/installation_linux.rst index acb10471c6e..f507a8d823c 100644 --- a/doc/develop/getting_started/installation_linux.rst +++ b/doc/develop/getting_started/installation_linux.rst @@ -228,14 +228,14 @@ The Zephyr SDK supports the following target architectures: Follow these steps to install the Zephyr SDK: #. Download and verify the `Zephyr SDK bundle - `_: + `_: .. code-block:: bash - wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/zephyr-sdk-0.16.1_linux-x86_64.tar.xz - wget -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/sha256.sum | shasum --check --ignore-missing + wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.3/zephyr-sdk-0.16.3_linux-x86_64.tar.xz + wget -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.3/sha256.sum | shasum --check --ignore-missing - You can change ``0.16.1`` to another version if needed; the `Zephyr SDK + You can change ``0.16.3`` to another version if needed; the `Zephyr SDK Releases`_ page contains all available SDK releases. If your host architecture is 64-bit ARM (for example, Raspberry Pi), replace @@ -246,13 +246,13 @@ Follow these steps to install the Zephyr SDK: .. code-block:: bash cd - tar xvf zephyr-sdk-0.16.1_linux-x86_64.tar.xz + tar xvf zephyr-sdk-0.16.3_linux-x86_64.tar.xz #. Run the Zephyr SDK bundle setup script: .. code-block:: bash - cd zephyr-sdk-0.16.1 + cd zephyr-sdk-0.16.3 ./setup.sh If this fails, make sure Zephyr's dependencies were installed as described @@ -271,9 +271,9 @@ If you relocate the SDK directory, you need to re-run the setup script. * ``/opt`` * ``/usr/local`` - The Zephyr SDK bundle archive contains the ``zephyr-sdk-0.16.1`` directory and, when + The Zephyr SDK bundle archive contains the ``zephyr-sdk-0.16.3`` directory and, when extracted under ``$HOME``, the resulting installation path will be - ``$HOME/zephyr-sdk-0.16.1``. + ``$HOME/zephyr-sdk-0.16.3``. If you install the Zephyr SDK outside any of these locations, you must register the Zephyr SDK in the CMake package registry by running the setup @@ -303,7 +303,7 @@ toolchains for all Zephyr target architectures, and does not require any extra flags when building applications or running tests. In addition to cross-compilers, the Zephyr SDK also provides prebuilt host tools. It is, however, possible to build without the SDK's toolchain by using another -toolchain as as described in the :ref:`toolchains` section. +toolchain as described in the :ref:`toolchains` section. As already noted above, the SDK also includes prebuilt host tools. To use the SDK's prebuilt host tools with a toolchain from another source, you must set the diff --git a/doc/develop/getting_started/installation_mac.rst b/doc/develop/getting_started/installation_mac.rst index de7b3f861b3..a6043d37b4f 100644 --- a/doc/develop/getting_started/installation_mac.rst +++ b/doc/develop/getting_started/installation_mac.rst @@ -19,9 +19,9 @@ get around this issue you can take two different approaches: ``path/to/folder`` is the path to the enclosing folder where the executables you want to run are located. -* Open "System Preferences" -> "Security and Privacy" -> "Privacy" and then - scroll down to "Developer Tools". Then unlock the lock to be able to make - changes and check the checkbox corresponding to your terminal emulator of +* Open :menuselection:`System Preferences --> Security and Privacy --> Privacy` + and then scroll down to "Developer Tools". Then unlock the lock to be able to + make changes and check the checkbox corresponding to your terminal emulator of choice. This will apply to any executable being launched from such terminal program. diff --git a/doc/develop/index.rst b/doc/develop/index.rst index 25efad6cfcb..7067ea5653c 100644 --- a/doc/develop/index.rst +++ b/doc/develop/index.rst @@ -10,6 +10,7 @@ Developing with Zephyr beyond-GSG.rst env_vars.rst application/index.rst + debug/index.rst api/index.rst languages/index.rst optimizations/index diff --git a/doc/develop/languages/c/newlib.rst b/doc/develop/languages/c/newlib.rst index f79d00c01e2..a0daba2b971 100644 --- a/doc/develop/languages/c/newlib.rst +++ b/doc/develop/languages/c/newlib.rst @@ -31,7 +31,7 @@ The Newlib full variant (:file:`libc.a` and :file:`libm.a`) is the most capable variant of the Newlib available in the Zephyr SDK, and supports almost all standard C library features. It is optimized for performance (prefers performance over code size) and its footprint is significantly larger than the -the nano variant. +nano variant. This variant can be enabled by selecting the :kconfig:option:`CONFIG_NEWLIB_LIBC` and de-selecting the diff --git a/doc/develop/languages/c/picolibc.rst b/doc/develop/languages/c/picolibc.rst index 32ab8732c7a..33d2e8f3fd6 100644 --- a/doc/develop/languages/c/picolibc.rst +++ b/doc/develop/languages/c/picolibc.rst @@ -62,6 +62,28 @@ For every release of Zephyr, the toolchain-bundled Picolibc and the sync when using the :ref:`recommended version of Zephyr SDK `. +Building Without Toolchain bundled Picolibc +------------------------------------------- + +For toolchain where there is no bundled Picolibc, it is still +possible to use Picolibc by building it from source. Note that +any restrictions mentioned in :ref:`c_library_picolibc_module` +still apply. + +To build without toolchain bundled Picolibc, the toolchain must +enable :kconfig:option:`CONFIG_PICOLIBC_SUPPORTED`. For example, +this needs to be added to the toolchain Kconfig file: + +.. code-block:: none + + config TOOLCHAIN__PICOLIBC_SUPPORTED + def_bool y + select PICOLIBC_SUPPORTED + +By enabling :kconfig:option:`CONFIG_PICOLIBC_SUPPORTED`, the build +system would automatically build Picolibc from source with its module +when there is no toolchain bundled Picolibc. + Formatted Output **************** diff --git a/doc/develop/manifest/index.rst b/doc/develop/manifest/index.rst new file mode 100644 index 00000000000..4c6d8f99117 --- /dev/null +++ b/doc/develop/manifest/index.rst @@ -0,0 +1,58 @@ +:orphan: + +.. _west_projects_index: + +West Projects index +################### + +See :ref:`external-contributions` for more information about +this contributing and review process for imported components. + +Active Projects/Modules ++++++++++++++++++++++++ + +The projects below are enabled by default and will be downloaded when you +call `west update`. Many of the projects or modules listed below are +essential for building generic Zephyr application and include among others +hardware support for many of the platforms available in Zephyr. + +To disable any of the active modules, for example a specific HAL, use the +following commands:: + + west config manifest.project-filter -- -hal_FOO + west update + +.. manifest-projects-table:: + :filter: active + +Inactive and Optional Projects/Modules +++++++++++++++++++++++++++++++++++++++ + + +The projects below are optional and will not be downloaded when you +call `west update`. You can add any of the projects or modules listed below +and use them to write application code and extend your workspace with the added +functionality. + +To enable any of the modules below, use the following commands:: + + west config manifest.project-filter -- +nanopb + west update + +.. manifest-projects-table:: + :filter: inactive + +External Projects/Modules +++++++++++++++++++++++++++ + + +The projects listed below are external and are not directly imported into the +default manifest. +To use any of the projects below, you will need to define your own manifest +file which includes them. See :ref:`west-manifest-import` for information on +recommended ways to do this while still inheriting the mandatory modules from +Zephyr's :file:`west.yml`. + +.. rst-class:: rst-columns + +- TBD diff --git a/doc/develop/modules.rst b/doc/develop/modules.rst index 5ee6648d329..42d10c32e98 100644 --- a/doc/develop/modules.rst +++ b/doc/develop/modules.rst @@ -276,7 +276,7 @@ The merging of pull requests in the main branch of a module repository must be coupled with the corresponding manifest file update in the zephyr main tree. -**Issue Reporting:** GitHub issues are intentionally disabled in module +**Issue Reporting:** `GitHub issues`_ are intentionally disabled in module repositories, in favor of a centralized policy for issue reporting. Tickets concerning, for example, bugs or enhancements in modules shall be opened in the main @@ -625,7 +625,7 @@ variables. For example: include(${ZEPHYR_CURRENT_MODULE_DIR}/cmake/code.cmake) -It is possible to append values to a Zephyr CMake list variable from the module's first +It is possible to append values to a Zephyr `CMake list`_ variable from the module's first CMakeLists.txt file. To do so, append the value to the list and then set the list in the PARENT_SCOPE of the CMakeLists.txt file. For example, to append ``bar`` to the ``FOO_LIST`` variable in the @@ -671,7 +671,7 @@ example: include(${SYSBUILD_CURRENT_MODULE_DIR}/cmake/code.cmake) -It is possible to append values to a Zephyr CMake list variable from the +It is possible to append values to a Zephyr `CMake list`_ variable from the module's first CMakeLists.txt file. To do so, append the value to the list and then set the list in the PARENT_SCOPE of the CMakeLists.txt file. For example, to append ``bar`` to the @@ -794,7 +794,7 @@ Create a ``MODULE_EXT_ROOT`` with the following structure └── Kconfig and then build your application by specifying ``-DMODULE_EXT_ROOT`` parameter to -the CMake build system. The ``MODULE_EXT_ROOT`` accepts a CMake list of roots as +the CMake build system. The ``MODULE_EXT_ROOT`` accepts a `CMake list`_ of roots as argument. A Zephyr module can automatically be added to the ``MODULE_EXT_ROOT`` @@ -818,7 +818,7 @@ to the path containing the CMake file. To include a module's Kconfig file, set the variable ``ZEPHYR__KCONFIG`` to the path to the Kconfig file. -The following is an example on how to add support the the ``FOO`` module. +The following is an example on how to add support the ``FOO`` module. Create the following structure @@ -1151,5 +1151,4 @@ revision needs to be changed to the commit hash from the module repository. .. _CMake list: https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#lists .. _add_subdirectory(): https://cmake.org/cmake/help/latest/command/add_subdirectory.html - .. _GitHub issues: https://github.com/zephyrproject-rtos/zephyr/issues diff --git a/doc/develop/optimizations/tools.rst b/doc/develop/optimizations/tools.rst index 762891cf8d8..c253d47092e 100644 --- a/doc/develop/optimizations/tools.rst +++ b/doc/develop/optimizations/tools.rst @@ -33,37 +33,48 @@ Use the ``ram_report`` target with your board: which will generate something similar to the output below:: - Path Size % - ============================================================================================================== - ... - ... - SystemCoreClock 4 0.08% - _kernel 48 0.99% - _sw_isr_table 384 7.94% - cli.10544 16 0.33% - gpio_initialized.9765 1 0.02% - on.10543 4 0.08% - poll_out_lock.9764 4 0.08% - z_idle_threads 128 2.65% - z_interrupt_stacks 2048 42.36% - z_main_thread 128 2.65% - arch 1 0.02% - arm 1 0.02% - core 1 0.02% - aarch32 1 0.02% - cortex_m 1 0.02% - mpu 1 0.02% - arm_mpu.c 1 0.02% - static_regions_num 1 0.02% - drivers 536 11.09% - clock_control 100 2.07% - nrf_power_clock.c 100 2.07% - __device_clock_nrf 16 0.33% - data 80 1.65% - hfclk_users 4 0.08% - ... - ... - + Path Size % + ======================================================================================== + Root 4637 100.00% + ├── (hidden) 4 0.09% + ├── (no paths) 2748 59.26% + │ ├── _cpus_active 4 0.09% + │ ├── _kernel 32 0.69% + │ ├── _sw_isr_table 384 8.28% + │ ├── cli.1 16 0.35% + │ ├── on.2 4 0.09% + │ ├── poll_out_lock.0 4 0.09% + │ ├── z_idle_threads 128 2.76% + │ ├── z_interrupt_stacks 2048 44.17% + │ └── z_main_thread 128 2.76% + ├── WORKSPACE 184 3.97% + │ └── modules 184 3.97% + │ └── hal 184 3.97% + │ └── nordic 184 3.97% + │ └── nrfx 184 3.97% + │ └── drivers 184 3.97% + │ └── src 184 3.97% + │ ├── nrfx_clock.c 8 0.17% + │ │ └── m_clock_cb 8 0.17% + │ ├── nrfx_gpiote.c 132 2.85% + │ │ └── m_cb 132 2.85% + │ ├── nrfx_ppi.c 4 0.09% + │ │ └── m_channels_allocated 4 0.09% + │ └── nrfx_twim.c 40 0.86% + │ └── m_cb 40 0.86% + └── ZEPHYR_BASE 1701 36.68% + ├── arch 5 0.11% + │ └── arm 5 0.11% + │ └── core 5 0.11% + │ ├── mpu 1 0.02% + │ │ └── arm_mpu.c 1 0.02% + │ │ └── static_regions_num 1 0.02% + │ └── tls.c 4 0.09% + │ └── z_arm_tls_ptr 4 0.09% + ├── drivers 258 5.56% + │ ├── ... ... ...% + ======================================================================================== + 4637 Build Target: rom_report ======================== @@ -82,47 +93,40 @@ Use the ``rom_report`` to get the ROM report: which will generate something similar to the output below:: - Path Size % - ============================================================================================================== - ... - ... - CSWTCH.5 4 0.02% - SystemCoreClock 4 0.02% - __aeabi_idiv0 2 0.01% - __udivmoddi4 702 3.37% - _sw_isr_table 384 1.85% - delay_machine_code.9114 6 0.03% - levels.8826 20 0.10% - mpu_config 8 0.04% - transitions.10558 12 0.06% - arch 1194 5.74% - arm 1194 5.74% - core 1194 5.74% - aarch32 1194 5.74% - cortex_m 852 4.09% - fault.c 400 1.92% - bus_fault.isra.0 60 0.29% - mem_manage_fault.isra.0 56 0.27% - usage_fault.isra.0 36 0.17% - z_arm_fault 232 1.11% - z_arm_fault_init 16 0.08% - irq_init.c 24 0.12% - z_arm_interrupt_init 24 0.12% - mpu 352 1.69% - arm_core_mpu.c 56 0.27% - z_arm_configure_static_mpu_regions 56 0.27% - arm_mpu.c 296 1.42% - __init_sys_init_arm_mpu_init0 8 0.04% - arm_core_mpu_configure_static_mpu_regions 20 0.10% - arm_core_mpu_disable 16 0.08% - arm_core_mpu_enable 20 0.10% - arm_mpu_init 92 0.44% - mpu_configure_regions 140 0.67% - thread_abort.c 76 0.37% - z_impl_k_thread_abort - 76 0.37% - ... - ... + Path Size % + ======================================================================================== + Root 21652 100.00% + ├── ... ... ...% + └── ZEPHYR_BASE 13378 61.79% + ├── arch 1718 7.93% + │ └── arm 1718 7.93% + │ └── core 1718 7.93% + │ ├── cortex_m 1020 4.71% + │ │ ├── fault.c 620 2.86% + │ │ │ ├── bus_fault.constprop.0 108 0.50% + │ │ │ ├── mem_manage_fault.constprop.0 120 0.55% + │ │ │ ├── usage_fault.constprop.0 84 0.39% + │ │ │ ├── z_arm_fault 292 1.35% + │ │ │ └── z_arm_fault_init 16 0.07% + │ │ ├── ... ... ...% + ├── boards 32 0.15% + │ └── arm 32 0.15% + │ └── reel_board 32 0.15% + │ └── board.c 32 0.15% + │ ├── __init_board_reel_board_init 8 0.04% + │ └── board_reel_board_init 24 0.11% + ├── build 194 0.90% + │ └── zephyr 194 0.90% + │ ├── isr_tables.c 192 0.89% + │ │ └── _irq_vector_table 192 0.89% + │ └── misc 2 0.01% + │ └── generated 2 0.01% + │ └── configs.c 2 0.01% + │ └── _ConfigAbsSyms 2 0.01% + ├── drivers 6162 28.46% + │ ├── ... ... ...% + ======================================================================================== + 21652 Build Target: puncover ====================== diff --git a/doc/develop/test/bsim.rst b/doc/develop/test/bsim.rst index be06fad434f..c785f88c1ee 100644 --- a/doc/develop/test/bsim.rst +++ b/doc/develop/test/bsim.rst @@ -12,7 +12,7 @@ including the BLE stack, 802.15.4, and some of the networking stack. BabbleSim_ is a physical layer simulator, which in combination with the Zephyr :ref:`bsim boards` can be used to simulate a network of BLE and 15.4 devices. -When we build Zephyr targeting an :ref:`nrf52_bsim` board we produce a Linux +When we build Zephyr targeting a :ref:`bsim board` we produce a Linux executable, which includes the application, Zephyr OS, and models of the HW. When there is radio activity, this Linux executable will connect to the BabbleSim Phy simulation @@ -21,8 +21,9 @@ to simulate the radio channel. In the BabbleSim documentation you can find more information on how to `get `_ and `build `_ the simulator. -In the :ref:`nrf52_bsim` board documentation you can find more information about how -to build Zephyr targeting that particular board, and a few examples. +In the :ref:`nrf52_bsim` and :ref:`nrf5340bsim` boards documentation +you can find more information about how to build Zephyr targeting thesee particular boards, +and a few examples. Types of tests ************** @@ -31,8 +32,8 @@ Tests without radio activity: bsim tests with twister ----------------------------------------------------- The :ref:`bsim boards` can be used without radio activity, and in that case, it is not -necessary to connect them to a phyisical layer simulation. Thanks to this, this target boards can -be used just like :ref:`native_posix` with :ref:`twister `, +necessary to connect them to a physical layer simulation. Thanks to this, these target boards can +be used just like :ref:`native_sim` with :ref:`twister `, to run all standard Zephyr twister tests, but with models of a real SOC HW, and their drivers. Tests with radio activity @@ -62,8 +63,8 @@ found in the :ref:`bsim boards tests section`. Test coverage and BabbleSim *************************** -As the :ref:`nrf52_bsim` is based on the POSIX architecture, you can easily collect test -coverage information. +As the :ref:`nrf52_bsim` and :ref:`nrf5340bsim` boards are based on the +POSIX architecture, you can easily collect test coverage information. You can use the script :code:`tests/bsim/generate_coverage_report.sh` to generate an html coverage report from tests. diff --git a/doc/develop/test/coverage.rst b/doc/develop/test/coverage.rst index f911c74287c..84eadad1a21 100644 --- a/doc/develop/test/coverage.rst +++ b/doc/develop/test/coverage.rst @@ -109,7 +109,7 @@ You may postprocess these with your preferred tools. For example: :zephyr-app: samples/hello_world :gen-args: -DCONFIG_COVERAGE=y :host-os: unix - :board: native_posix + :board: native_sim :goals: build :compact: @@ -140,7 +140,7 @@ For example, you may invoke:: or:: - $ twister --coverage -p native_posix -T tests/bluetooth + $ twister --coverage -p native_sim -T tests/bluetooth which will produce ``twister-out/coverage/index.html`` with the report. diff --git a/doc/develop/test/pytest.rst b/doc/develop/test/pytest.rst index 957ff8c773b..f6ba54fa52e 100644 --- a/doc/develop/test/pytest.rst +++ b/doc/develop/test/pytest.rst @@ -79,7 +79,7 @@ Give access to a DeviceAdapter type object, that represents Device Under Test. This fixture is the core of pytest harness plugin. It is required to launch DUT (initialize logging, flash device, connect serial etc). This fixture yields a device prepared according to the requested type -(native posix, qemu, hardware, etc.). All types of devices share the same API. +(``native``, ``qemu``, ``hardware``, etc.). All types of devices share the same API. This allows for writing tests which are device-type-agnostic. Scope of this fixture is determined by the ``pytest_dut_scope`` keyword placed under ``harness_config`` section. diff --git a/doc/develop/test/twister.rst b/doc/develop/test/twister.rst index a61744eec6d..122e9c3871b 100644 --- a/doc/develop/test/twister.rst +++ b/doc/develop/test/twister.rst @@ -19,7 +19,7 @@ tests for different boards and different configurations to help keep the complete code tree buildable. When using (at least) one ``-v`` option, twister's console output -shows for every test how the test is run (qemu, native_posix, etc.) or +shows for every test how the test is run (qemu, native_sim, etc.) or whether the binary was just built. There are a few reasons why twister only builds a test and doesn't run it: @@ -136,7 +136,9 @@ required for best test coverage for this specific board: identifier: A string that matches how the board is defined in the build system. This same string is used when building, for example when calling ``west build`` or - ``cmake``:: + ``cmake``: + + .. code-block:: console # with west west build -b reel_board @@ -153,7 +155,7 @@ arch: Architecture of the board toolchain: The list of supported toolchains that can build this board. This should match - one of the values used for 'ZEPHYR_TOOLCHAIN_VARIANT' when building on the command line + one of the values used for :envvar:`ZEPHYR_TOOLCHAIN_VARIANT` when building on the command line ram: Available RAM on the board (specified in KB). This is used to match testcase requirements. If not specified we default to 128KB. @@ -164,7 +166,7 @@ supported: A list of features this board supports. This can be specified as a single word feature or as a variant of a feature class. For example: - :: + .. code-block:: yaml supported: - pci @@ -172,7 +174,7 @@ supported: This indicates the board does support PCI. You can make a testcase build or run only on such boards, or: - :: + .. code-block:: yaml supported: - netif:eth @@ -195,10 +197,18 @@ testing: only_tags: Only execute tests with this list of tags on a specific platform. + .. _twister_board_timeout_multiplier: + + timeout_multiplier: (default 1) + Multiply each test case timeout by specified ratio. This option allows to tune timeouts only + for required platform. It can be useful in case naturally slow platform I.e.: HW board with + power-efficient but slow CPU or simulation platform which can perform instruction accurate + simulation but does it slowly. + Test Cases ********** -Test cases are detected by the presence of a 'testcase.yaml' or a 'sample.yaml' +Test cases are detected by the presence of a ``testcase.yaml`` or a ``sample.yaml`` files in the application's project directory. This file may contain one or more entries in the test section each identifying a test scenario. @@ -236,7 +246,7 @@ samples. The following is an example test with a few options that are explained in this document. -:: + .. code-block:: yaml tests: bluetooth.gatt: @@ -255,7 +265,7 @@ explained in this document. A sample with tests will have the same structure with additional information related to the sample and what is being demonstrated: -:: + .. code-block:: yaml sample: name: hello world @@ -272,11 +282,7 @@ related to the sample and what is being demonstrated: tags: tests min_ram: 16 -The full canonical name for each test case is: - -:: - - / +The full canonical name for each test case is:``/`` Each test block in the testcase meta data can define the following key/value pairs: @@ -290,7 +296,7 @@ skip: (default False) skip testcase unconditionally. This can be used for broken tests. slow: (default False) - Don't run this test case unless --enable-slow or --enable-slow-only was + Don't run this test case unless ``--enable-slow`` or ``--enable-slow-only`` was passed in on the command line. Intended for time-consuming test cases that are only run under certain circumstances, like daily builds. These test cases are still compiled. @@ -301,7 +307,9 @@ extra_args: extra_configs: Extra configuration options to be merged with a master prj.conf - when building or running the test case. For example:: + when building or running the test case. For example: + + .. code-block:: yaml common: tags: drivers adc @@ -313,7 +321,9 @@ extra_configs: - CONFIG_ADC_ASYNC=y Using namespacing, it is possible to apply a configuration only to some - hardware. Currently both architectures and platforms are supported:: + hardware. Currently both architectures and platforms are supported: + + .. code-block:: yaml common: tags: drivers adc @@ -347,7 +357,7 @@ depends_on: A board or platform can announce what features it supports, this option will enable the test only those platforms that provide this feature. -levels: Test levels this test should be part of. If a level is present, this test will be selectable using the command line option ``--level `` @@ -359,6 +369,8 @@ min_flash: minimum amount of ROM in KB needed for this test to build and run. This is compared with information provided by the board metadata. +.. _twister_test_case_timeout: + timeout: Length of time to run test before automatically killing it. Default to 60 seconds. @@ -377,7 +389,7 @@ platform_allow: integration_platforms: This option limits the scope to the listed platforms when twister is - invoked with the --integration option. Use this instead of + invoked with the ``--integration`` option. Use this instead of platform_allow if the goal is to limit scope due to timing or resource constraints. @@ -393,7 +405,7 @@ sysbuild: (default False) Build the project using sysbuild infrastructure. Only the main project's generated devicetree and Kconfig will be used for filtering tests. on device testing must use the hardware map, or west flash to load - the images onto the target. The --erase option of west flash is + the images onto the target. The ``--erase`` option of west flash is not supported with this option. Usage of unsupported options will result in tests requiring sysbuild support being skipped. @@ -442,7 +454,9 @@ platform_key: that. For example to key on (arch, simulation) to ensure a test is run once - per arch and simulation (as would be most common):: + per arch and simulation (as would be most common): + + .. code-block:: yaml platform_key: - arch @@ -466,7 +480,6 @@ harness_config: record: - regex: (required) Any string that the particular test case prints to record test results. @@ -486,7 +499,7 @@ harness_config: and identify setups that fulfill this dependency. It depends on specific test setup and board selection logic to pick the particular board(s) out of multiple boards that fulfill the dependency in an - automation setup based on "fixture" keyword. Some sample fixture names + automation setup based on ``fixture`` keyword. Some sample fixture names are i2c_hts221, i2c_bme280, i2c_FRAM, ble_fw and gpio_loop. Only one fixture can be defined per testcase and the fixture name has to @@ -511,7 +524,7 @@ harness_config: The following is an example yaml file with a few harness_config options. - :: + .. code-block:: yaml sample: name: HTS221 Temperature and Humidity Monitor @@ -534,7 +547,7 @@ harness_config: default pytest_root name "pytest" will be used if pytest_root not specified. please refer the examples in samples/subsys/testsuite/pytest/. - :: + .. code-block:: yaml common: harness: pytest @@ -553,7 +566,7 @@ harness_config: The following is an example yaml file with robot harness_config options. - :: + .. code-block:: yaml tests: robot.example: @@ -565,7 +578,7 @@ filter: Filter whether the testcase should be run by evaluating an expression against an environment containing the following values: - :: + .. code-block:: none { ARCH : , PLATFORM : , @@ -581,78 +594,118 @@ filter: The grammar for the expression language is as follows: - expression ::= expression "and" expression - | expression "or" expression - | "not" expression - | "(" expression ")" - | symbol "==" constant - | symbol "!=" constant - | symbol "<" number - | symbol ">" number - | symbol ">=" number - | symbol "<=" number - | symbol "in" list - | symbol ":" string - | symbol + .. code-block:: antlr - list ::= "[" list_contents "]" + expression : expression 'and' expression + | expression 'or' expression + | 'not' expression + | '(' expression ')' + | symbol '==' constant + | symbol '!=' constant + | symbol '<' NUMBER + | symbol '>' NUMBER + | symbol '>=' NUMBER + | symbol '<=' NUMBER + | symbol 'in' list + | symbol ':' STRING + | symbol + ; - list_contents ::= constant - | list_contents "," constant + list : '[' list_contents ']'; - constant ::= number - | string + list_contents : constant (',' constant)*; + constant : NUMBER | STRING; - For the case where expression ::= symbol, it evaluates to true + For the case where ``expression ::= symbol``, it evaluates to ``true`` if the symbol is defined to a non-empty string. Operator precedence, starting from lowest to highest: - or (left associative) - and (left associative) - not (right associative) - all comparison operators (non-associative) + * or (left associative) + * and (left associative) + * not (right associative) + * all comparison operators (non-associative) - arch_allow, arch_exclude, platform_allow, platform_exclude - are all syntactic sugar for these expressions. For instance + ``arch_allow``, ``arch_exclude``, ``platform_allow``, ``platform_exclude`` + are all syntactic sugar for these expressions. For instance: + + .. code-block:: none arch_exclude = x86 arc Is the same as: + .. code-block:: none + filter = not ARCH in ["x86", "arc"] - The ':' operator compiles the string argument as a regular expression, + The ``:`` operator compiles the string argument as a regular expression, and then returns a true value only if the symbol's value in the environment - matches. For example, if CONFIG_SOC="stm32f107xc" then + matches. For example, if ``CONFIG_SOC="stm32f107xc"`` then + + .. code-block:: none filter = CONFIG_SOC : "stm.*" Would match it. +required_snippets: + :ref:`Snippets ` are supported in twister for test cases that + require them. As with normal applications, twister supports using the base + zephyr snippet directory and test application directory for finding + snippets. Listed snippets will filter supported tests for boards (snippets + must be compatible with a board for the test to run on them, they are not + optional). + + The following is an example yaml file with 2 required snippets. + + .. code-block:: yaml + + tests: + snippet.example: + required_snippets: + - cdc-acm-console + - user-snippet-example + The set of test cases that actually run depends on directives in the testcase filed and options passed in on the command line. If there is any confusion, -running with -v or examining the discard report +running with ``-v`` or examining the discard report (:file:`twister_discard.csv`) can help show why particular test cases were skipped. Metrics (such as pass/fail state and binary size) for the last code -release are stored in scripts/release/twister_last_release.csv. -To update this, pass the --all --release options. +release are stored in ``scripts/release/twister_last_release.csv``. +To update this, pass the ``--all --release`` options. -To load arguments from a file, write '+' before the file name, e.g., -+file_name. File content must be one or more valid arguments separated by +To load arguments from a file, add ``+`` before the file name, e.g., +``+file_name``. File content must be one or more valid arguments separated by line break instead of white spaces. Most everyday users will run with no arguments. +Managing tests timeouts +*********************** + +There are several parameters which control tests timeouts on various levels: + +* ``timeout`` option in each test case. See :ref:`here ` for more + details. +* ``timeout_multiplier`` option in board configuration. See + :ref:`here ` for more details. +* ``--timeout-multiplier`` twister option which can be used to adjust timeouts in exact twister run. + It can be useful in case of simulation platform as simulation time may depend on the host + speed & load or we may select different simulation method (i.e. cycle accurate but slower + one), etc... + +Overall test case timeout is a multiplication of these three parameters. + Running in Integration Mode *************************** This mode is used in continuous integration (CI) and other automated environments used to give developers fast feedback on changes. The mode can -be activated using the --integration option of twister and narrows down +be activated using the ``--integration`` option of twister and narrows down the scope of builds and tests if applicable to platforms defined under the integration keyword in the testcase definition file (testcase.yaml and sample.yaml). @@ -666,7 +719,7 @@ supports running any out-of-tree custom emulator defined in the board's :file:`b To use this type of simulation, add the following properties to :file:`custom_board/custom_board.yaml`: -:: +.. code-block:: yaml simulation: custom simulation_exec: @@ -676,14 +729,14 @@ make sure this binary exists in the PATH. Then, in :file:`custom_board/board.cmake`, set the supported emulation platforms to ``custom``: -:: +.. code-block:: cmake set(SUPPORTED_EMU_PLATFORMS custom) Finally, implement the ``run_custom`` target in :file:`custom_board/board.cmake`. It should look something like this: -:: +.. code-block:: cmake add_custom_target(run_custom COMMAND @@ -790,40 +843,40 @@ devices, for example: .. group-tab:: Linux - :: - - - connected: true - id: OSHW000032254e4500128002ab98002784d1000097969900 - platform: unknown - product: DAPLink CMSIS-DAP - runner: pyocd - serial: /dev/cu.usbmodem146114202 - - connected: true - id: 000683759358 - platform: unknown - product: J-Link - runner: unknown - serial: /dev/cu.usbmodem0006837593581 + .. code-block:: yaml + + - connected: true + id: OSHW000032254e4500128002ab98002784d1000097969900 + platform: unknown + product: DAPLink CMSIS-DAP + runner: pyocd + serial: /dev/cu.usbmodem146114202 + - connected: true + id: 000683759358 + platform: unknown + product: J-Link + runner: unknown + serial: /dev/cu.usbmodem0006837593581 .. group-tab:: Windows - :: + .. code-block:: yaml - - connected: true - id: OSHW000032254e4500128002ab98002784d1000097969900 - platform: unknown - product: unknown - runner: unknown - serial: COM1 - - connected: true - id: 000683759358 - platform: unknown - product: unknown - runner: unknown - serial: COM2 + - connected: true + id: OSHW000032254e4500128002ab98002784d1000097969900 + platform: unknown + product: unknown + runner: unknown + serial: COM1 + - connected: true + id: 000683759358 + platform: unknown + product: unknown + runner: unknown + serial: COM2 -Any options marked as 'unknown' need to be changed and set with the correct +Any options marked as ``unknown`` need to be changed and set with the correct values, in the above example the platform names, the products and the runners need to be replaced with the correct values corresponding to the connected hardware. In this example we are using a reel_board and an nrf52840dk_nrf52840: @@ -832,41 +885,41 @@ In this example we are using a reel_board and an nrf52840dk_nrf52840: .. group-tab:: Linux - :: - - - connected: true - id: OSHW000032254e4500128002ab98002784d1000097969900 - platform: reel_board - product: DAPLink CMSIS-DAP - runner: pyocd - serial: /dev/cu.usbmodem146114202 - baud: 9600 - - connected: true - id: 000683759358 - platform: nrf52840dk_nrf52840 - product: J-Link - runner: nrfjprog - serial: /dev/cu.usbmodem0006837593581 - baud: 9600 + .. code-block:: yaml + + - connected: true + id: OSHW000032254e4500128002ab98002784d1000097969900 + platform: reel_board + product: DAPLink CMSIS-DAP + runner: pyocd + serial: /dev/cu.usbmodem146114202 + baud: 9600 + - connected: true + id: 000683759358 + platform: nrf52840dk_nrf52840 + product: J-Link + runner: nrfjprog + serial: /dev/cu.usbmodem0006837593581 + baud: 9600 .. group-tab:: Windows - :: - - - connected: true - id: OSHW000032254e4500128002ab98002784d1000097969900 - platform: reel_board - product: DAPLink CMSIS-DAP - runner: pyocd - serial: COM1 - baud: 9600 - - connected: true - id: 000683759358 - platform: nrf52840dk_nrf52840 - product: J-Link - runner: nrfjprog - serial: COM2 - baud: 9600 + .. code-block:: yaml + + - connected: true + id: OSHW000032254e4500128002ab98002784d1000097969900 + platform: reel_board + product: DAPLink CMSIS-DAP + runner: pyocd + serial: COM1 + baud: 9600 + - connected: true + id: 000683759358 + platform: nrf52840dk_nrf52840 + product: J-Link + runner: nrfjprog + serial: COM2 + baud: 9600 The baud entry is only needed if not running at 115200. @@ -905,17 +958,19 @@ command line options as ``flash-timeout`` and ``flash-with-test`` fields respect These hardware map values override command line options for the particular platform. Serial PTY support using ``--device-serial-pty`` can also be used in the -hardware map:: +hardware map: - - connected: true - id: None - platform: intel_adsp_cavs25 - product: None - runner: intel_adsp - serial_pty: path/to/script.py - runner_params: - - --remote-host=remote_host_ip_addr - - --key=/path/to/key.pem +.. code-block:: yaml + + - connected: true + id: None + platform: intel_adsp_cavs25 + product: None + runner: intel_adsp + serial_pty: path/to/script.py + runner_params: + - --remote-host=remote_host_ip_addr + - --key=/path/to/key.pem The runner_params field indicates the parameters you want to pass to the @@ -955,7 +1010,9 @@ specify the fixture it needs which can then be matched with hardware capability of a board and the fixtures it supports via the command line or using the hardware map file. -Fixtures are defined in the hardware map file as a list:: +Fixtures are defined in the hardware map file as a list: + +.. code-block:: yaml - connected: true fixtures: @@ -982,8 +1039,10 @@ Notes +++++ It may be useful to annotate board descriptions in the hardware map file -with additional information. Use the "notes" keyword to do this. For -example:: +with additional information. Use the ``notes`` keyword to do this. For +example: + +.. code-block:: yaml - connected: false fixtures: @@ -991,7 +1050,7 @@ example:: id: 000683290670 notes: An nrf5340dk_nrf5340 is detected as an nrf52840dk_nrf52840 with no serial port, and three serial ports with an unknown platform. The board id of the serial - ports is not the same as the board id of the the development kit. If you regenerate + ports is not the same as the board id of the development kit. If you regenerate this file you will need to update serial to reference the third port, and platform to nrf5340dk_nrf5340_cpuapp or another supported board target. platform: nrf52840dk_nrf52840 @@ -1002,11 +1061,13 @@ example:: Overriding Board Identifier +++++++++++++++++++++++++++ -When (re-)generated the hardware map file will contain an "id" keyword +When (re-)generated the hardware map file will contain an ``id`` keyword that serves as the argument to ``--board-id`` when flashing. In some cases the detected ID is not the correct one to use, for example when -using an external J-Link probe. The "probe_id" keyword overrides the -"id" keyword for this purpose. For example:: +using an external J-Link probe. The ``probe_id`` keyword overrides the +``id`` keyword for this purpose. For example: + +.. code-block:: yaml - connected: false id: 0229000005d9ebc600000000000000000000000097969905 @@ -1033,8 +1094,8 @@ The current status of tests on the quarantine list can also be verified by addin which are not on the given list. A quarantine yaml has to be a sequence of dictionaries. Each dictionary has to have -"scenarios" and "platforms" entries listing combinations of scenarios and platforms -to put under quarantine. In addition, an optional entry "comment" can be used, where +``scenarios`` and ``platforms`` entries listing combinations of scenarios and platforms +to put under quarantine. In addition, an optional entry ``comment`` can be used, where some more details can be given (e.g. link to a reported issue). These comments will also be added to the output reports. @@ -1043,7 +1104,9 @@ when dealing with multiple issues within a subsystem, it is possible to use regular expressions, for example, **kernel.*** would quarantine all kernel tests. -An example of entries in a quarantine yaml:: +An example of entries in a quarantine yaml: + +.. code-block:: yaml - scenarios: - sample.basic.helloworld @@ -1055,9 +1118,11 @@ An example of entries in a quarantine yaml:: - kernel.common.nano64 platforms: - .*_cortex_.* - - native_posix + - native_sim + +To exclude a platform, use the following syntax: -To exclude a platform, use the following syntax:: +.. code-block:: yaml - platforms: - qemu_x86 @@ -1118,7 +1183,9 @@ The following options control platform filtering in twister: can either be used to replace the existing default platforms or can extend it depending on the value of `override_default_platforms`. -And example platforms configuration:: +And example platforms configuration: + +.. code-block:: yaml platforms: override_default_platforms: true @@ -1138,7 +1205,9 @@ In the configuration file you can include complete components using regular expressions and you can specify which test level to import from the same file, making management of levels simple. -And example test level configuration:: +And example test level configuration: + +.. code-block:: yaml levels: - name: my-test-level @@ -1156,7 +1225,9 @@ Combined configuration To mix the Platform and level configuration, you can take an example as below: -And example platforms plus level configuration:: +And example platforms plus level configuration: + +.. code-block:: yaml platforms: override_default_platforms: true @@ -1201,7 +1272,7 @@ Running in Tests in Random Order ******************************** Enable ZTEST framework's :kconfig:option:`CONFIG_ZTEST_SHUFFLE` config option to run your tests in random order. This can be beneficial for identifying -dependencies between test cases. For native_posix platforms, you can provide +dependencies between test cases. For native_sim platforms, you can provide the seed to the random number generator by providing ``-seed=value`` as an argument to twister. See :ref:`Shuffling Test Sequence ` for more details. diff --git a/doc/develop/test/ztest.rst b/doc/develop/test/ztest.rst index 535bab232d0..f9255ecad2a 100644 --- a/doc/develop/test/ztest.rst +++ b/doc/develop/test/ztest.rst @@ -10,10 +10,6 @@ test structure. The framework can be used in two ways, either as a generic framework for integration testing, or for unit testing specific modules. -To enable support for the latest Ztest API, set -:kconfig:option:`CONFIG_ZTEST_NEW_API` to ``y``. There is also a legacy API -that is deprecated and will eventually be removed. - Creating a test suite ********************* @@ -83,7 +79,7 @@ This is achieved via fixtures in the following way: static void *my_suite_setup(void) { /* Allocate the fixture with 256 byte buffer */ - struct my_suite_fixture *fixture = k_malloc(sizeof(struct my_suite_fixture) + 255); + struct my_suite_fixture *fixture = malloc(sizeof(struct my_suite_fixture) + 255); zassume_not_null(fixture, NULL); fixture->max_size = 256; @@ -100,7 +96,7 @@ This is achieved via fixtures in the following way: static void my_suite_teardown(void *f) { - k_free(f); + free(f); } ZTEST_SUITE(my_suite, NULL, my_suite_setup, my_suite_before, NULL, my_suite_teardown); @@ -132,14 +128,14 @@ nature of the code, it's possible to annotate the test as such. For example: ZTEST_SUITE(my_suite, NULL, NULL, NULL, NULL, NULL); - ZTEST_EXPECT_FAIL(my_suite, test_fail) + ZTEST_EXPECT_FAIL(my_suite, test_fail); ZTEST(my_suite, test_fail) { /** This will fail the test */ zassert_true(false, NULL); } - ZTEST_EXPECT_SKIP(my_suite, test_skip) + ZTEST_EXPECT_SKIP(my_suite, test_skip); ZTEST(my_suite, test_skip) { /** This will skip the test */ @@ -344,6 +340,8 @@ it needs to report either a pass or fail. For example: ZTEST_SUITE(common, NULL, NULL, NULL, NULL, NULL); +.. _ztest_unit_testing: + Quick start - Unit testing ************************** @@ -581,7 +579,7 @@ Shuffling Test Sequence By default the tests are sorted and ran in alphanumerical order. Test cases may be dependent on this sequence. Enable :kconfig:option:`CONFIG_ZTEST_SHUFFLE` to randomize the order. The output from the test will display the seed for failed -tests. For native posix builds you can provide the seed as an argument to +tests. For native simulator builds you can provide the seed as an argument to twister with `--seed` Static configuration of ZTEST_SHUFFLE contains: @@ -592,7 +590,7 @@ Static configuration of ZTEST_SHUFFLE contains: Test Selection ************** -For POSIX enabled builds with ZTEST_NEW_API use command line arguments to list +For tests built for native simulator, use command line arguments to list or select tests to run. The test argument expects a comma separated list of ``suite::test`` . You can substitute the test name with an ``*`` to run all tests within a suite. diff --git a/doc/develop/toolchains/zephyr_sdk.rst b/doc/develop/toolchains/zephyr_sdk.rst index 951ddb9b9a8..fc6add9d3eb 100644 --- a/doc/develop/toolchains/zephyr_sdk.rst +++ b/doc/develop/toolchains/zephyr_sdk.rst @@ -67,153 +67,173 @@ the recommended version for the corresponding Zephyr version. For the full list of compatible Zephyr and Zephyr SDK versions, refer to the `Zephyr SDK Version Compatibility Matrix`_. -.. _toolchain_zephyr_sdk_install_linux: +.. _toolchain_zephyr_sdk_install: -Install Zephyr SDK on Linux -*************************** +Zephyr SDK installation +*********************** + +.. toolchain_zephyr_sdk_install_start + +.. note:: You can change ``0.16.3`` to another version in the instructions below + if needed; the `Zephyr SDK Releases`_ page contains all available + SDK releases. + +.. note:: If you want to uninstall the SDK, you may simply remove the directory + where you installed it. + +.. tabs:: -#. Download and verify the `Zephyr SDK bundle`_: + .. group-tab:: Ubuntu - .. code-block:: bash + .. _ubuntu_zephyr_sdk: - wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/zephyr-sdk-0.16.1_linux-x86_64.tar.xz - wget -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/sha256.sum | shasum --check --ignore-missing + #. Download and verify the `Zephyr SDK bundle + `_: - You can change ``0.16.1`` to another version if needed; the `Zephyr SDK - Releases`_ page contains all available SDK releases. + .. code-block:: bash - If your host architecture is 64-bit ARM (for example, Raspberry Pi), replace - ``x86_64`` with ``aarch64`` in order to download the 64-bit ARM Linux SDK. + cd ~ + wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.3/zephyr-sdk-0.16.3_linux-x86_64.tar.xz + wget -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.3/sha256.sum | shasum --check --ignore-missing -#. Extract the Zephyr SDK bundle archive: + If your host architecture is 64-bit ARM (for example, Raspberry Pi), replace ``x86_64`` + with ``aarch64`` in order to download the 64-bit ARM Linux SDK. - .. code-block:: bash + #. Extract the Zephyr SDK bundle archive: - cd - tar xvf zephyr-sdk-0.16.1_linux-x86_64.tar.xz + .. code-block:: bash -#. Run the Zephyr SDK bundle setup script: + tar xvf zephyr-sdk-0.16.3_linux-x86_64.tar.xz - .. code-block:: bash + .. note:: + It is recommended to extract the Zephyr SDK bundle at one of the following locations: - cd zephyr-sdk-0.16.1 - ./setup.sh + * ``$HOME`` + * ``$HOME/.local`` + * ``$HOME/.local/opt`` + * ``$HOME/bin`` + * ``/opt`` + * ``/usr/local`` - If this fails, make sure Zephyr's dependencies were installed as described - in :ref:`Install Requirements and Dependencies `. + The Zephyr SDK bundle archive contains the ``zephyr-sdk-0.16.3`` directory and, when + extracted under ``$HOME``, the resulting installation path will be + ``$HOME/zephyr-sdk-0.16.3``. -If you want to uninstall the SDK, remove the directory where you installed it. -If you relocate the SDK directory, you need to re-run the setup script. + #. Run the Zephyr SDK bundle setup script: -.. note:: - It is recommended to extract the Zephyr SDK bundle at one of the following - default locations: + .. code-block:: bash - * ``$HOME`` - * ``$HOME/.local`` - * ``$HOME/.local/opt`` - * ``$HOME/bin`` - * ``/opt`` - * ``/usr/local`` + cd zephyr-sdk-0.16.3 + ./setup.sh - The Zephyr SDK bundle archive contains the ``zephyr-sdk-0.16.1`` directory and, when - extracted under ``$HOME``, the resulting installation path will be - ``$HOME/zephyr-sdk-0.16.1``. + .. note:: + You only need to run the setup script once after extracting the Zephyr SDK bundle. -.. _toolchain_zephyr_sdk_install_macos: + You must rerun the setup script if you relocate the Zephyr SDK bundle directory after + the initial setup. -Install Zephyr SDK on macOS -*************************** + #. Install `udev `_ rules, which + allow you to flash most Zephyr boards as a regular user: -#. Download and verify the `Zephyr SDK bundle`_: + .. code-block:: bash - .. code-block:: bash + sudo cp ~/zephyr-sdk-0.16.3/sysroots/x86_64-pokysdk-linux/usr/share/openocd/contrib/60-openocd.rules /etc/udev/rules.d + sudo udevadm control --reload - cd ~ - wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/zephyr-sdk-0.16.1_macos-x86_64.tar.xz - wget -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/sha256.sum | shasum --check --ignore-missing + .. group-tab:: macOS - If your host architecture is 64-bit ARM (Apple Silicon, also known as M1), replace - ``x86_64`` with ``aarch64`` in order to download the 64-bit ARM macOS SDK. + .. _macos_zephyr_sdk: -#. Extract the Zephyr SDK bundle archive: + #. Download and verify the `Zephyr SDK bundle + `_: - .. code-block:: bash + .. code-block:: bash - tar xvf zephyr-sdk-0.16.1_macos-x86_64.tar.xz + cd ~ + curl -L -O https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.3/zephyr-sdk-0.16.3_macos-x86_64.tar.xz + curl -L https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.3/sha256.sum | shasum --check --ignore-missing - .. note:: - It is recommended to extract the Zephyr SDK bundle at one of the following - default locations: + If your host architecture is 64-bit ARM (Apple Silicon, also known as M1), replace + ``x86_64`` with ``aarch64`` in order to download the 64-bit ARM macOS SDK. - * ``$HOME`` - * ``$HOME/.local`` - * ``$HOME/.local/opt`` - * ``$HOME/bin`` - * ``/opt`` - * ``/usr/local`` + #. Extract the Zephyr SDK bundle archive: - The Zephyr SDK bundle archive contains the ``zephyr-sdk-0.16.1`` directory and, when - extracted under ``$HOME``, the resulting installation path will be - ``$HOME/zephyr-sdk-0.16.1``. + .. code-block:: bash -#. Run the Zephyr SDK bundle setup script: + tar xvf zephyr-sdk-0.16.3_macos-x86_64.tar.xz - .. code-block:: bash + .. note:: + It is recommended to extract the Zephyr SDK bundle at one of the following locations: - cd zephyr-sdk-0.16.1 - ./setup.sh + * ``$HOME`` + * ``$HOME/.local`` + * ``$HOME/.local/opt`` + * ``$HOME/bin`` + * ``/opt`` + * ``/usr/local`` - .. note:: - You only need to run the setup script once after extracting the Zephyr SDK bundle. + The Zephyr SDK bundle archive contains the ``zephyr-sdk-0.16.3`` directory and, when + extracted under ``$HOME``, the resulting installation path will be + ``$HOME/zephyr-sdk-0.16.3``. - You must rerun the setup script if you relocate the Zephyr SDK bundle directory after - the initial setup. + #. Run the Zephyr SDK bundle setup script: -.. _toolchain_zephyr_sdk_install_windows: + .. code-block:: bash -Install Zephyr SDK on Windows -***************************** + cd zephyr-sdk-0.16.3 + ./setup.sh -#. Open a ``cmd.exe`` window by pressing the Windows key typing "cmd.exe". + .. note:: + You only need to run the setup script once after extracting the Zephyr SDK bundle. -#. Download the `Zephyr SDK bundle`_: + You must rerun the setup script if you relocate the Zephyr SDK bundle directory after + the initial setup. - .. code-block:: console + .. group-tab:: Windows - cd %HOMEPATH% - wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/zephyr-sdk-0.16.1_windows-x86_64.7z + .. _windows_zephyr_sdk: -#. Extract the Zephyr SDK bundle archive: + #. Open a ``cmd.exe`` terminal window **as a regular user** - .. code-block:: console + #. Download the `Zephyr SDK bundle + `_: - 7z x zephyr-sdk-0.16.1_windows-x86_64.7z + .. code-block:: bat - .. note:: - It is recommended to extract the Zephyr SDK bundle at one of the following - default locations: + cd %HOMEPATH% + wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.3/zephyr-sdk-0.16.3_windows-x86_64.7z - * ``%HOMEPATH%`` - * ``%PROGRAMFILES%`` + #. Extract the Zephyr SDK bundle archive: - The Zephyr SDK bundle archive contains the ``zephyr-sdk-0.16.1`` directory and, when - extracted under ``%HOMEPATH%``, the resulting installation path will be - ``%HOMEPATH%\zephyr-sdk-0.16.1``. + .. code-block:: bat -#. Run the Zephyr SDK bundle setup script: + 7z x zephyr-sdk-0.16.3_windows-x86_64.7z - .. code-block:: console + .. note:: + It is recommended to extract the Zephyr SDK bundle at one of the following locations: - cd zephyr-sdk-0.16.1 - setup.cmd + * ``%HOMEPATH%`` + * ``%PROGRAMFILES%`` - .. note:: - You only need to run the setup script once after extracting the Zephyr SDK bundle. + The Zephyr SDK bundle archive contains the ``zephyr-sdk-0.16.3`` directory and, when + extracted under ``%HOMEPATH%``, the resulting installation path will be + ``%HOMEPATH%\zephyr-sdk-0.16.3``. - You must rerun the setup script if you relocate the Zephyr SDK bundle directory after - the initial setup. + #. Run the Zephyr SDK bundle setup script: -.. _Zephyr SDK bundle: https://github.com/zephyrproject-rtos/sdk-ng/releases/tag/v0.16.1 + .. code-block:: bat + + cd zephyr-sdk-0.16.3 + setup.cmd + + .. note:: + You only need to run the setup script once after extracting the Zephyr SDK bundle. + + You must rerun the setup script if you relocate the Zephyr SDK bundle directory after + the initial setup. + +.. _Zephyr SDK bundle: https://github.com/zephyrproject-rtos/sdk-ng/releases/tag/v0.16.3 .. _Zephyr SDK Releases: https://github.com/zephyrproject-rtos/sdk-ng/tags .. _Zephyr SDK Version Compatibility Matrix: https://github.com/zephyrproject-rtos/sdk-ng/wiki/Zephyr-SDK-Version-Compatibility-Matrix + +.. toolchain_zephyr_sdk_install_end diff --git a/doc/develop/west/build-flash-debug.rst b/doc/develop/west/build-flash-debug.rst index b6809094f85..0f9f15ef9d7 100644 --- a/doc/develop/west/build-flash-debug.rst +++ b/doc/develop/west/build-flash-debug.rst @@ -177,8 +177,12 @@ it the value ``always``. For example, these commands are equivalent:: west build -p -b reel_board samples/hello_world west build -p=always -b reel_board samples/hello_world -By default, ``west build`` applies a heuristic to detect if the build directory -needs to be made pristine. This is the same as using ``--pristine=auto``. +By default, ``west build`` makes no attempt to detect if the build directory +needs to be made pristine. This can lead to errors if you do something like +try to re-use a build directory for a different ``--board``. + +Using ``--pristine=auto`` makes ``west build`` detect some of these situations +and make the build directory pristine before trying the build. .. tip:: @@ -739,8 +743,6 @@ debugging. This can of course also be accomplished using the usual targets provided by Zephyr's build system (in fact, that's how these commands do it). -.. rubric:: Footnotes - .. _cmake(1): https://cmake.org/cmake/help/latest/manual/cmake.1.html diff --git a/doc/develop/west/built-in.rst b/doc/develop/west/built-in.rst index 085a37fdc64..b54dbaad54f 100644 --- a/doc/develop/west/built-in.rst +++ b/doc/develop/west/built-in.rst @@ -245,13 +245,14 @@ West has a few more commands for managing the projects in the workspace, which are summarized here. Run ``west -h`` for detailed help. +- ``west compare``: compare the state of the workspace against the manifest +- ``west diff``: run ``git diff`` in local project repositories +- ``west forall``: run an arbitrary command in local project repositories +- ``west grep``: search for patterns in local project repositories - ``west list``: print a line of information about each project in the manifest, according to a format string - ``west manifest``: manage the manifest file. See :ref:`west-manifest-cmd`. -- ``west diff``: run ``git diff`` in local project repositories - ``west status``: run ``git status`` in local project repositories -- ``west forall``: run an arbitrary command in local project repositories -- ``west compare``: compare the state of the workspace against the manifest Other built-in commands *********************** diff --git a/doc/develop/west/config.rst b/doc/develop/west/config.rst index 594b54cbbe7..eae6c7e4b9e 100644 --- a/doc/develop/west/config.rst +++ b/doc/develop/west/config.rst @@ -135,6 +135,24 @@ commands are documented in the pages for those commands. stdout is a terminal. * - ``commands.allow_extensions`` - Boolean, default ``true``, disables :ref:`west-extensions` if ``false`` + * - ``grep.color`` + - String, default empty. Set this to ``never`` to disable ``west grep`` + color output. If set, ``west grep`` passes the value to the grep tool's + ``--color`` option. + * - ``grep.tool`` + - String, one of ``"git-grep"`` (default), ``"ripgrep"``, or ``"grep"``. + The grep tool that ``west grep`` should use. + * - ``grep.-args`` + - String, default empty. The ```` part is a pattern that can be any + ``grep.tool`` value, so ``grep.ripgrep-args`` is an example + configuration option. If set, arguments that ``west grep`` should pass + to the corresponding grep tool. Run ``west help grep`` for details. + * - ``grep.-path`` + - String, default empty. The ```` part is a pattern that can be any + ``grep.tool`` value, so ``grep.ripgrep-path`` is an example + configuration option. The path to the corresponding tool that ``west + grep`` should use instead of searching for the command. Run ``west help + grep`` for details. * - ``manifest.file`` - String, default ``west.yml``. Relative path from the manifest repository root directory to the manifest file used by ``west init`` and other diff --git a/doc/develop/west/index.rst b/doc/develop/west/index.rst index 627267fb250..7b5fd6b2cce 100644 --- a/doc/develop/west/index.rst +++ b/doc/develop/west/index.rst @@ -26,9 +26,6 @@ You can run ``west --help`` (or ``west -h`` for short) to get top-level help for available west commands, and ``west -h`` for detailed help on each command. -The following pages document west's ``v1.0.y`` releases, and provide additional -context about the tool. - .. toctree:: :maxdepth: 1 diff --git a/doc/develop/west/manifest.rst b/doc/develop/west/manifest.rst index 3f2fa74e306..f989cdcae1e 100644 --- a/doc/develop/west/manifest.rst +++ b/doc/develop/west/manifest.rst @@ -174,9 +174,13 @@ Here is an example. We'll assume the ``remotes`` given above. # [... same remotes as above...] projects: - name: proj1 + description: the first example project remote: remote1 path: extra/project-1 - name: proj2 + description: | + A multi-line description of the second example + project. repo-path: my-path remote: remote2 revision: v1.3 @@ -229,6 +233,10 @@ next. reserved values "west" or "manifest". The name must be unique in the manifest file. + * - ``description`` + - Optional, an informational description of the project. Added in + west v1.2.0. + * - ``remote``, ``url`` - Mandatory (one of the two, but not both). @@ -240,7 +248,7 @@ next. remote Git repository. If the project has neither, the ``defaults`` section must specify a - ``remote``, which will be used as the the project's remote. Otherwise, + ``remote``, which will be used as the project's remote. Otherwise, the manifest is invalid. * - ``repo-path`` @@ -331,9 +339,13 @@ so far using ``defaults`` is: projects: - name: proj1 + description: the first example project path: extra/project-1 revision: master - name: proj2 + description: | + A multi-line description of the second example + project. repo-path: my-path remote: remote2 - name: proj3 @@ -487,6 +499,10 @@ about the manifest file features that were introduced in that version. - Identical to ``"0.13"``, but available for use by users that do not wish to use a ``"0.x"`` version field. + * - ``"1.2"`` + - Support for ``description:`` in ``projects:`` + (:ref:`west-manifests-projects`) + .. note:: Versions of west without any new features in the manifest file format do not @@ -1108,7 +1124,7 @@ recursively update the project's Git submodules whenever it updates the project itself. If it's ``false`` or missing, it has no effect. For example, let's say you have a source code repository ``foo``, which has -some submodules, and you want ``west update`` to keep all of them them in sync, +some submodules, and you want ``west update`` to keep all of them in sync, along with another project named ``bar`` in the same workspace. You can do that with this manifest file: @@ -2033,8 +2049,8 @@ The ultimate outcomes of resolving manifest imports are: - a ``projects`` list, which is produced by combining the ``projects`` defined in the top-level file with those defined in imported files -- a set of extension commands, which are drawn from the the ``west-commands`` - keys in in the top-level file and any imported files +- a set of extension commands, which are drawn from the ``west-commands`` + keys in the top-level file and any imported files - a ``group-filter`` list, which is produced by combining the top-level and any imported filters diff --git a/doc/develop/west/release-notes.rst b/doc/develop/west/release-notes.rst index 98d67da96d9..951cc4c3e37 100644 --- a/doc/develop/west/release-notes.rst +++ b/doc/develop/west/release-notes.rst @@ -3,6 +3,81 @@ West Release Notes ################## +v1.2.0 +****** + +Major changes: + +- New ``west grep`` command for running a "grep tool" in your west workspace's + repositories. Currently, ``git grep``, `ripgrep`_, and standard ``grep`` are + supported grep tools. + + To run this command to get ``git grep foo`` results from all cloned, + active repositories, run: + + .. code-block:: console + + west grep foo + + Here are some other examples for running different grep commands + with ``west grep``: + + .. list-table:: + + * - ``git grep --untracked`` + - ``west grep --untracked foo`` + * - ``ripgrep`` + - ``west grep --tool ripgrep foo`` + * - ``grep --recursive`` + - ``west grep --tool grep foo`` + + To switch the default grep tool in your workspace, run the appropriate + command in this table: + + .. list-table:: + + * - ``ripgrep`` + - ``west config grep.tool ripgrep`` + * - ``grep`` + - ``west config grep.tool grep`` + + For more details, run ``west help grep``. + +Other changes: + +- The manifest file format now supports a ``description`` field in each + ``projects:`` element. See :ref:`west-manifests-projects` for examples. + +- ``west list --format`` now accepts ``{description}`` in the format + string, which prints the project's ``description:`` value. + +- ``west compare`` now always prints information about + :ref:`west-manifest-rev`. + +Bug fixes: + +- ``west init`` aborts if the destination directory already exists. + +API changes: + +- ``west.commands.WestCommand`` methods ``check_call()`` and + ``check_output()`` now take any kwargs that can be passed on + to the underlying subprocess function. + +- ``west.commands.WestCommand.run_subprocess()``: new wrapper + around ``subprocess.run()``. This could not be named ``run()`` + because ``WestCommand`` already had a method by this name. + +- ``west.commands.WestCommand`` methods ``dbg()``, ``inf()``, + ``wrn()``, and ``err()`` now all take an ``end`` kwarg, which + is passed on to the call to ``print()``. + +- ``west.manifest.Project`` now has a ``description`` attribute, + which contains the parsed value of the ``description:`` field + in the manifest data. + +.. _ripgrep: https://github.com/BurntSushi/ripgrep#readme + v1.1.0 ****** @@ -594,7 +669,7 @@ The developer-visible changes to the :ref:`west-apis` are: West now requires Python 3.6 or later. Additionally, some features may rely on Python dictionaries being insertion-ordered; this is only an implementation -detail in CPython 3.6, but is is part of the language specification as of +detail in CPython 3.6, but it is part of the language specification as of Python 3.7. v0.6.3 diff --git a/doc/develop/west/sign.rst b/doc/develop/west/sign.rst index 0606da34dc3..8cc55ffeea4 100644 --- a/doc/develop/west/sign.rst +++ b/doc/develop/west/sign.rst @@ -40,9 +40,9 @@ Notes on the above commands: - ``YOUR_BOARD`` should be changed to match your board - The ``CONFIG_MCUBOOT_SIGNATURE_KEY_FILE`` value is the insecure default - provided and used by by MCUboot for development and testing + provided and used by MCUboot for development and testing - You can change the ``hello_world`` application directory to any other - application that can be loaded by MCUboot, such as the :ref:`smp_svr_sample` + application that can be loaded by MCUboot, such as the :zephyr:code-sample:`smp-svr` sample. For more information on these and other related configuration options, see: diff --git a/doc/develop/west/west-apis.rst b/doc/develop/west/west-apis.rst index ec60bc6fe56..306cef813e8 100644 --- a/doc/develop/west/west-apis.rst +++ b/doc/develop/west/west-apis.rst @@ -137,14 +137,39 @@ WestCommand .. automethod:: add_pre_run_hook .. versionadded:: 1.0.0 - .. automethod:: check_call + .. NOTE: the following 'method' (not 'automethod') directives were added for + expediency during the west v1.2 release time frame to work around a build + failure in this zephyr documentation that could not be fixed without + cutting a west point release. (The docstrings in west had some RST syntax + errors). + These should be reverted back to automethod calls at the next release. + + .. method:: check_call(args, **kwargs) + + Runs ``subprocess.check_call(args, **kwargs)`` after + logging the call at Verbosity.DBG_MORE`` level. + + .. versionchanged:: 1.2.0 + The *cwd* keyword argument was replaced with a catch-all ``**kwargs``. .. versionchanged:: 0.11.0 - .. automethod:: check_output + .. method:: check_output(args, **kwargs) + + Runs ``subprocess.check_output(args, **kwargs)`` after + logging the call at Verbosity.DBG_MORE level. + .. versionchanged:: 1.2.0 + The *cwd* keyword argument was replaced with a catch-all ``**kwargs``. .. versionchanged:: 0.11.0 + .. method:: run_subprocess(args, **kwargs) + + Runs ``subprocess.run(args, **kwargs)`` after logging + the call at Verbosity.DBG_MORE level. + + .. versionadded:: 1.2.0 + All subclasses must provide the following abstract methods, which are used to implement the above: @@ -158,15 +183,23 @@ WestCommand "quiet" mode for west commands in a future release: .. automethod:: dbg + .. versionchanged:: 1.2.0 + The *end* argument. .. versionadded:: 1.0.0 .. automethod:: inf + .. versionchanged:: 1.2.0 + The *end* argument. .. versionadded:: 1.0.0 .. automethod:: wrn + .. versionchanged:: 1.2.0 + The *end* argument. .. versionadded:: 1.0.0 .. automethod:: err + .. versionchanged:: 1.2.0 + The *end* argument. .. versionadded:: 1.0.0 .. automethod:: die @@ -396,10 +429,6 @@ Manifest and sub-objects .. (note: attributes are part of the class docstring) - .. versionchanged:: 0.8.0 - The *west_commands* attribute is now always a list. In previous - releases, it could be a string or ``None``. - .. versionchanged:: 0.7.0 The *remote* attribute was removed. Its semantics could no longer be preserved when support for manifest ``import`` keys was added. @@ -407,12 +436,19 @@ Manifest and sub-objects .. versionadded:: 0.7.0 The *remote_name* and *name_and_path* attributes. + .. versionchanged:: 0.8.0 + The *west_commands* attribute is now always a list. In previous + releases, it could be a string or ``None``. + .. versionadded:: 0.9.0 The *group_filter* and *submodules* attributes. .. versionadded:: 0.12.0 The *userdata* attribute. + .. versionadded:: 1.2.0 + The *description* attribute. + Constructor: .. automethod:: __init__ diff --git a/doc/develop/west/zephyr-cmds.rst b/doc/develop/west/zephyr-cmds.rst index d1d96d07ceb..056d22e48eb 100644 --- a/doc/develop/west/zephyr-cmds.rst +++ b/doc/develop/west/zephyr-cmds.rst @@ -185,3 +185,28 @@ Twister can then be invoked via west as follows:: west twister -help west twister -T tests/ztest/base + +.. _west-bindesc: + +Working with binary descriptors: ``west bindesc`` +************************************************* + +The ``bindesc`` command allows users to read :ref:`binary descriptors` +of executable files. It currently supports ``.bin``, ``.hex``, ``.elf`` and ``.uf2`` files +as input. + +You can search for a specific descriptor in an image, for example:: + + west bindesc search KERNEL_VERSION_STRING build/zephyr/zephyr.bin + +You can search for a custom descriptor by type and ID, for example:: + + west bindesc custom_search STR 0x200 build/zephyr/zephyr.bin + +You can dump all of the descriptors in an image using:: + + west bindesc dump build/zephyr/zephyr.bin + +You can list all known standard descriptor names using:: + + west bindesc list diff --git a/doc/glossary.rst b/doc/glossary.rst index 95781c665f6..8571f4b6d49 100644 --- a/doc/glossary.rst +++ b/doc/glossary.rst @@ -51,7 +51,7 @@ Glossary of Terms device runtime power management Device Runtime Power Management (PM) refers the capability of devices to - save energy independently of the the system power state. Devices will keep + save energy independently of the system power state. Devices will keep reference of their usage and will automatically be suspended or resumed. This feature is enabled via the :kconfig:option:`CONFIG_PM_DEVICE_RUNTIME` Kconfig option. @@ -89,7 +89,7 @@ Glossary of Terms system power state System power states describe the power consumption of the system as a - whole. System power states are are represented by :c:enum:`pm_state`. + whole. System power states are represented by :c:enum:`pm_state`. west A multi-repo meta-tool developed for the Zephyr project. See :ref:`west`. diff --git a/doc/hardware/arch/arm_cortex_m.rst b/doc/hardware/arch/arm_cortex_m.rst index 1e70b10cc8c..b037896776f 100644 --- a/doc/hardware/arch/arm_cortex_m.rst +++ b/doc/hardware/arch/arm_cortex_m.rst @@ -169,7 +169,7 @@ PendSV exception return sequence restores the new thread's caller-saved register return address, as part of unstacking the exception stack frame. The implementation of the context-switch mechanism is present in -:file:`arch/arm/core/aarch32/swap_helper.S`. +:file:`arch/arm/core/swap_helper.S`. Stack limit checking (Arm v8-M) ------------------------------- @@ -262,7 +262,7 @@ interrupt. If the ZLI feature is enabled in Mainline Cortex-M builds (see * Regular HW interrupts are assigned priority levels lower than SVC. The priority level configuration in Cortex-M is implemented in -:file:`include/arch/arm/aarch32/exc.h`. +:file:`include/arch/arm/exc.h`. Locking and unlocking IRQs -------------------------- @@ -337,7 +337,7 @@ CPU Idling The Cortex-M architecture port implements both k_cpu_idle() and k_cpu_atomic_idle(). The implementation is present in -:file:`arch/arm/core/aarch32/cpu_idle.S`. +:file:`arch/arm/core/cpu_idle.S`. In both implementations, the processor will attempt to put the core to low power mode. @@ -457,10 +457,6 @@ region will be allocated and programmed during system boot. When used with the :dtcompatible:`zephyr,memory-region` devicetree compatible, it will result in a linker section being generated associated to that MPU region. -The property ``zephyr,memory-attr`` is a string carrying the attributes -for the MPU region. It is converted to a C token for use defining the attributes -of the MPU region. - For example, to define a new non-cacheable memory region in devicetree: .. code-block:: devicetree @@ -469,13 +465,11 @@ For example, to define a new non-cacheable memory region in devicetree: compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x20300000 0x100000>; zephyr,memory-region = "SRAM_NO_CACHE"; - zephyr,memory-attr = "RAM_NOCACHE"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) )>; }; -This will automatically create a new MPU entry in -:zephyr_file:`soc/arm/common/cortex_m/arm_mpu_regions.c` with the correct name, base, -size and attributes gathered directly from the devicetree. See -:zephyr_file:`include/zephyr/linker/devicetree_regions.h` for more details. +This will automatically create a new MPU entry in with the correct name, base, +size and attributes gathered directly from the devicetree. Static MPU regions ------------------ @@ -624,7 +618,7 @@ Linking Cortex-M applications ***************************** Most Cortex-M platforms make use of the default Cortex-M -GCC linker script in :file:`include/arch/arm/aarch32/cortex-m/scripts/linked.ld`, +GCC linker script in :file:`include/arch/arm/cortex-m/scripts/linked.ld`, although it is possible for platforms to use a custom linker script as well. diff --git a/doc/hardware/emulator/index.rst b/doc/hardware/emulator/index.rst index 23ed94a192a..4373480a3e0 100644 --- a/doc/hardware/emulator/index.rst +++ b/doc/hardware/emulator/index.rst @@ -32,7 +32,7 @@ This is the ultimate application we want to run. :alt: Emulator architecture showing tests, emulators and drivers Below that are peripheral drivers, such as the AT24 EEPROM driver. We can test -peripheral drivers using an emulation driver connected via a native_posix I2C +peripheral drivers using an emulation driver connected via a native_sim I2C controller/emulator which passes I2C traffic from the AT24 driver to the AT24 simulator. @@ -41,12 +41,12 @@ tests. These require some sort of device attached to the bus, but with this, we can validate much of the driver functionality. Putting the two together, we can test the application and peripheral code -entirely on native_posix. Since we know that the I2C driver on the real hardware +entirely on native_sim. Since we know that the I2C driver on the real hardware works, we should expect the application and peripheral drivers to work on the real hardware also. Using the above framework we can test an entire application (e.g. Embedded -Controller) on native_posix using emulators for all non-chip drivers: +Controller) on native_sim using emulators for all non-chip drivers: .. figure:: img/app.png :align: center @@ -68,7 +68,7 @@ With this approach we can: All of this can work in the emulated environment or on real hardware. * Write a complex application that ties together all of these pieces and runs on - native_posix. We can develop on a host, use source-level debugging, etc. + native_sim. We can develop on a host, use source-level debugging, etc. * Transfer the application to any board which provides the required features (e.g. I2C, enough GPIOs), by adding Kconfig and devicetree fragments. @@ -110,9 +110,9 @@ device-class. The real code is shown in green, while the emulator code is shown in yellow. -The ``bus_api`` connects the BC1.2 emulators to the ``native_posix`` I2C +The ``bus_api`` connects the BC1.2 emulators to the ``native_sim`` I2C controller. The real BC1.2 drivers are unchanged and operate exactly as if there -was a physical I2C controller present in the system. The ``native_posix`` I2C +was a physical I2C controller present in the system. The ``native_sim`` I2C controller uses the ``bus_api`` to initiate register reads and writes to the emulator. @@ -164,23 +164,24 @@ Here are some examples present in Zephyr: .. zephyr-app-commands:: :app: tests/drivers/sensor/accel/ - :board: native_posix + :board: native_sim :goals: build #. Simple test of the EEPROM emulator: .. zephyr-app-commands:: - :app: tests/drivers/eeprom - :board: native_posix + :app: tests/drivers/eeprom/api + :board: native_sim :goals: build -#. The same test has a second EEPROM which is an Atmel AT24 EEPROM driver +#. The same test can be built with a second EEPROM which is an Atmel AT24 EEPROM driver connected via I2C an emulator: .. zephyr-app-commands:: - :app: tests/drivers/eeprom - :board: native_posix + :app: tests/drivers/eeprom/api + :board: native_sim :goals: build + :gen-args: -DDTC_OVERLAY_FILE=at2x_emul.overlay -DOVERLAY_CONFIG=at2x_emul.conf API Reference ************* diff --git a/doc/hardware/peripherals/auxdisplay.rst b/doc/hardware/peripherals/auxdisplay.rst index b3cb6cbae5b..913b43f2779 100644 --- a/doc/hardware/peripherals/auxdisplay.rst +++ b/doc/hardware/peripherals/auxdisplay.rst @@ -9,7 +9,7 @@ Overview Auxiliary Displays are text-based displays that have simple interfaces for displaying textual, numeric or alphanumeric data, as opposed to the :ref:`display_api`, auxiliary displays do not support custom -graphical output to displays (and and most often monochrome), the most +graphical output to displays (and most often monochrome), the most advanced custom feature supported is generation of custom characters. These inexpensive displays are commonly found with various configurations and sizes, a common display size is 16 characters by 2 lines. diff --git a/doc/hardware/peripherals/bc12.rst b/doc/hardware/peripherals/bc12.rst index 00c9bcdb677..a612a403dbb 100644 --- a/doc/hardware/peripherals/bc12.rst +++ b/doc/hardware/peripherals/bc12.rst @@ -74,7 +74,7 @@ Charging port mode is used by the application when the USB port is configured as a downstream facing port, i.e. a USB host port. For charging port mode, the BC1.2 driver powers up the detection chip and configures the charger type specified by a devicetree property. If the driver supports detection of plug and -and unplug events, the BC1.2 driver notifies the callback registered with +unplug events, the BC1.2 driver notifies the callback registered with ``bc12_set_result_cb()`` to indicate the current connection state of the portable device partner. diff --git a/doc/hardware/peripherals/canbus/controller.rst b/doc/hardware/peripherals/can/controller.rst similarity index 89% rename from doc/hardware/peripherals/canbus/controller.rst rename to doc/hardware/peripherals/can/controller.rst index 85dee4b0f67..6943949d1a4 100644 --- a/doc/hardware/peripherals/canbus/controller.rst +++ b/doc/hardware/peripherals/can/controller.rst @@ -16,22 +16,6 @@ ISO 11898-1:2003 standard. CAN is mostly known for its application in the automotive domain. However, it is also used in home and industrial automation and other products. -A CAN transceiver is an external device that converts the logic level signals -from the CAN controller to the bus-levels. The bus lines are called -CAN High (CAN H) and CAN Low (CAN L). -The transmit wire from the controller to the transceiver is called CAN TX, -and the receive wire is called CAN RX. -These wires use the logic levels whereas the bus-level is interpreted -differentially between CAN H and CAN L. -The bus can be either in the recessive (logical one) or dominant (logical zero) -state. The recessive state is when both lines, CAN H and CAN L, at roughly at -the same voltage level. This state is also the idle state. -To write a dominant bit to the bus, open-drain transistors tie CAN H to Vdd -and CAN L to ground. -The first and last node use a 120-ohm resistor between CAN H and CAN L to -terminate the bus. The dominant state always overrides the recessive state. -This structure is called a wired-AND. - .. warning:: CAN controllers can only initialize when the bus is in the idle (recessive) @@ -39,12 +23,6 @@ This structure is called a wired-AND. CAN RX is high, at least for a short time. This is also necessary for loopback mode. -.. image:: transceiver.svg - :width: 70% - :align: center - :alt: CAN Transceiver - - The bit-timing as defined in ISO 11898-1:2003 looks as following: .. image:: timing.svg @@ -314,7 +292,7 @@ The following example sets the bitrate to 250k baud with the sampling point at LOG_ERR("Failed to start CAN controller"); } -A similar API exists for calculating and setting the timing for the data phase for CAN-FD capable +A similar API exists for calculating and setting the timing for the data phase for CAN FD capable controllers. See :c:func:`can_set_timing_data` and :c:func:`can_calc_timing_data`. SocketCAN @@ -331,18 +309,12 @@ which adds some computation and memory overhead. Samples ******* -We have two ready-to-build samples demonstrating use of the Zephyr CAN API -:ref:`Zephyr CAN counter sample ` and -:ref:`SocketCAN sample `. +We have two ready-to-build samples demonstrating use of the Zephyr CAN API: +:zephyr:code-sample:`Zephyr CAN counter sample ` and +:zephyr:code-sample:`SocketCAN sample `. CAN Controller API Reference **************************** .. doxygengroup:: can_interface - - -CAN Transceiver API Reference -***************************** - -.. doxygengroup:: can_transceiver diff --git a/doc/hardware/peripherals/can/index.rst b/doc/hardware/peripherals/can/index.rst new file mode 100644 index 00000000000..6e96fb15cb2 --- /dev/null +++ b/doc/hardware/peripherals/can/index.rst @@ -0,0 +1,10 @@ +.. _can: + +Controller Area Network (CAN) +############################# + +.. toctree:: + :maxdepth: 2 + + controller.rst + transceiver.rst diff --git a/doc/hardware/peripherals/canbus/timing.svg b/doc/hardware/peripherals/can/timing.svg similarity index 100% rename from doc/hardware/peripherals/canbus/timing.svg rename to doc/hardware/peripherals/can/timing.svg diff --git a/doc/hardware/peripherals/can/transceiver.rst b/doc/hardware/peripherals/can/transceiver.rst new file mode 100644 index 00000000000..26db7856818 --- /dev/null +++ b/doc/hardware/peripherals/can/transceiver.rst @@ -0,0 +1,37 @@ +.. _can_transceiver_api: + +CAN Transceiver +############### + +.. contents:: + :local: + :depth: 2 + +Overview +******** + +A CAN transceiver is an external device that converts the logic level signals +from the CAN controller to the bus-levels. The bus lines are called +CAN High (CAN H) and CAN Low (CAN L). +The transmit wire from the controller to the transceiver is called CAN TX, +and the receive wire is called CAN RX. +These wires use the logic levels whereas the bus-level is interpreted +differentially between CAN H and CAN L. +The bus can be either in the recessive (logical one) or dominant (logical zero) +state. The recessive state is when both lines, CAN H and CAN L, are roughly at +the same voltage level. This state is also the idle state. +To write a dominant bit to the bus, open-drain transistors tie CAN H to Vdd +and CAN L to ground. +The first and last node use a 120-ohm resistor between CAN H and CAN L to +terminate the bus. The dominant state always overrides the recessive state. +This structure is called a wired-AND. + +.. image:: transceiver.svg + :width: 70% + :align: center + :alt: CAN Transceiver + +CAN Transceiver API Reference +***************************** + +.. doxygengroup:: can_transceiver diff --git a/doc/hardware/peripherals/canbus/transceiver.svg b/doc/hardware/peripherals/can/transceiver.svg similarity index 100% rename from doc/hardware/peripherals/canbus/transceiver.svg rename to doc/hardware/peripherals/can/transceiver.svg diff --git a/doc/hardware/peripherals/canbus/index.rst b/doc/hardware/peripherals/canbus/index.rst deleted file mode 100644 index 844ab945ff9..00000000000 --- a/doc/hardware/peripherals/canbus/index.rst +++ /dev/null @@ -1,10 +0,0 @@ -.. _canbus: - -Controller Area Network (CAN) -############################# - -.. toctree:: - :maxdepth: 2 - - controller.rst - isotp.rst diff --git a/doc/hardware/peripherals/charger.rst b/doc/hardware/peripherals/charger.rst new file mode 100644 index 00000000000..b88876058b8 --- /dev/null +++ b/doc/hardware/peripherals/charger.rst @@ -0,0 +1,28 @@ +.. _charger_api: + +Chargers +######## + +The charger subsystem exposes an API to uniformly access battery charger devices. + +Basic Operation +*************** + +Properties +========== + +Fundamentally, a property is a configurable setting, state, or quantity that a charger device can +measure. + +Chargers typically support multiple properties, such as temperature readings of the battery-pack +or present-time current/voltage. + +Properties are fetched by the client one at a time using :c:func:`charger_get_prop`. +Properties are set by the client one at a time using :c:func:`charger_set_prop`. + +.. _charger_api_reference: + +API Reference +************* + +.. doxygengroup:: charger_interface diff --git a/doc/hardware/peripherals/dma.rst b/doc/hardware/peripherals/dma.rst index 198590905d3..53fd18a1aa7 100644 --- a/doc/hardware/peripherals/dma.rst +++ b/doc/hardware/peripherals/dma.rst @@ -6,6 +6,72 @@ Direct Memory Access (DMA) Overview ******** +Direct Memory Access (Controller) is a commonly provided type of co-processor that can typically +offload transferring data to and from peripherals and memory. + +The DMA API is not a portable API and really cannot be as each DMA has unique memory requirements, +peripheral interactions, and features. The API in effect provides a union of all useful DMA +functionality drivers have needed in the tree. It can still be a good abstraction, with care, for +peripheral devices for vendors where the DMA IP might be very similar but have slight variances. + +Driver Implementation Expectations +********************************** + +Synchronization and Ownership ++++++++++++++++++++++++++++++ + +From an API point of view, a DMA channel is a single-owner object, meaning the drivers should not +attempt to wrap a channel with kernel synchronization primitives such as mutexes or semaphores. If +DMA channels require mutating shared registers, those register updates should be wrapped in a spin +lock. + +This enables the entire API to be low-cost and callable from any call context, including ISRs where +it may be very useful to start/stop/suspend/resume/reload a channel transfer. + +Transfer Descriptor Memory Management ++++++++++++++++++++++++++++++++++++++ + +Drivers should not attempt to use heap allocations of any kind. If object pools are needed for +transfer descriptors then those should be setup in a way that does not break the promise of +ISR-allowable calls. Many drivers choose to create a simple static descriptor array per channel with +the size of the descriptor array adjustable using Kconfig. + +Channel State Machine Expectations +++++++++++++++++++++++++++++++++++ + +DMA channels should be viewed as state machines that the DMA API provides transition events for in +the form of API calls. Every driver is expected to maintain its own channel state tracking. The busy +state of the channel should be inspectable at any time with :c:func:`dma_get_status()`. + +A diagram showing those expectated possible state transitions and their API calls is provided here +for reference. + +.. graphviz:: + :caption: DMA state finite state machine + + digraph { + node [style=rounded]; + edge [fontname=Courier]; + init [shape=point]; + + CONFIGURED [label=Configured,shape=box]; + RUNNING [label=Running,shape=box]; + SUSPENDED [label=Suspended,shape=box]; + + init -> CONFIGURED [label=dma_config]; + + CONFIGURED -> RUNNING [label=dma_start]; + CONFIGURED -> CONFIGURED [label=dma_stop]; + + RUNNING -> CONFIGURED [label=dma_stop]; + RUNNING -> RUNNING [label=dma_start]; + RUNNING -> RUNNING [label=dma_resume, headport=w]; + RUNNING -> SUSPENDED [label=dma_suspend]; + + SUSPENDED -> SUSPENDED [label=dma_suspend]; + SUSPENDED -> RUNNING [label=dma_resume]; + SUSPENDED -> CONFIGURED [label=dma_stop]; + } API Reference ************* diff --git a/doc/hardware/peripherals/fuel_gauge.rst b/doc/hardware/peripherals/fuel_gauge.rst index bef7b122796..e7131c440bf 100644 --- a/doc/hardware/peripherals/fuel_gauge.rst +++ b/doc/hardware/peripherals/fuel_gauge.rst @@ -20,8 +20,11 @@ Fundamentally, a property is a quantity that a fuel gauge device can measure. Fuel gauges typically support multiple properties, such as temperature readings of the battery-pack or present-time current/voltage. -Properties are fetched using a client allocated array of :c:struct:`fuel_gauge_get_property`. This -array is then populated by values as according to its `property_type` field. +Properties are fetched by the client one at a time using :c:func:`fuel_gauge_get_prop`, or fetched +in a batch using :c:func:`fuel_gauge_get_props`. + +Properties are set by the client one at a time using :c:func:`fuel_gauge_set_prop`, or set in a +batch using :c:func:`fuel_gauge_set_props`. Battery Cutoff ============== diff --git a/doc/hardware/peripherals/gna.rst b/doc/hardware/peripherals/gna.rst deleted file mode 100644 index 212217bd42d..00000000000 --- a/doc/hardware/peripherals/gna.rst +++ /dev/null @@ -1,22 +0,0 @@ -.. _gna_api: - -Gaussian & Neural Accelerator (GNA) -################################### - -Overview -******** - -The GNA API provides access to Intel's Gaussian Mixture Model and Neural Network -Accelerator (GNA). - -Configuration Options -********************* - -Related configuration options: - -* :kconfig:option:`CONFIG_INTEL_GNA` - -API Reference -************* - -.. doxygengroup:: gna_interface diff --git a/doc/hardware/peripherals/gnss.rst b/doc/hardware/peripherals/gnss.rst new file mode 100644 index 00000000000..fb750358dc3 --- /dev/null +++ b/doc/hardware/peripherals/gnss.rst @@ -0,0 +1,50 @@ +.. _gnss_api: + +GNSS (Global Navigation Satellite System) +######################################### + +Overview +******** + +GNSS is a general term which covers satellite systems used for +navigation, like GPS (Global Positioning System). GNSS services +are usually accessed through GNSS modems which receive and +process GNSS signals to determine their position, or more +specifically, their antennas position. They usually +additionally provide a precise time synchronization mechanism, +commonly named PPS (Pulse-Per-Second). + +Subsystem support +***************** + +The GNSS subsystem is based on the :ref:`modem`. The GNSS +subsystem covers everything from sending and receiving commands +to and from the modem, to parsing, creating and processing +NMEA0183 messages. + +Adding support for additional NMEA0183 based GNSS modems +requires little more than implementing power management +and configuration for the specific GNSS modem. + +Adding support for GNSS modems which use other protocols and/or +busses than the usual NMEA0183 over UART is possible, but will +require a bit more work from the driver developer. + +Configuration Options +********************* + +Related configuration options: + +* :kconfig:option:`CONFIG_GNSS` +* :kconfig:option:`CONFIG_GNSS_SATELLITES` +* :kconfig:option:`CONFIG_GNSS_DUMP_TO_LOG` + +Navigation Reference +******************** + +.. doxygengroup:: navigation + +GNSS API Reference +****************** + +.. doxygengroup:: gnss_interface diff --git a/doc/hardware/peripherals/index.rst b/doc/hardware/peripherals/index.rst index 6e59ca3c44f..19461b6c9f4 100644 --- a/doc/hardware/peripherals/index.rst +++ b/doc/hardware/peripherals/index.rst @@ -16,7 +16,8 @@ Peripherals bbram.rst bc12.rst clock_control.rst - canbus/index.rst + can/index.rst + charger.rst coredump.rst counter.rst dac.rst @@ -28,7 +29,7 @@ Peripherals edac/index.rst flash.rst fuel_gauge.rst - gna.rst + gnss.rst gpio.rst hwinfo.rst i2c_eeprom_target.rst @@ -55,5 +56,6 @@ Peripherals uart.rst usbc_vbus.rst tcpc.rst + tgpio.rst video.rst watchdog.rst diff --git a/doc/hardware/peripherals/retained_mem.rst b/doc/hardware/peripherals/retained_mem.rst index bed5694d451..07fb20bbd88 100644 --- a/doc/hardware/peripherals/retained_mem.rst +++ b/doc/hardware/peripherals/retained_mem.rst @@ -17,6 +17,20 @@ Related configuration options: * :kconfig:option:`CONFIG_RETAINED_MEM` * :kconfig:option:`CONFIG_RETAINED_MEM_INIT_PRIORITY` +* :kconfig:option:`CONFIG_RETAINED_MEM_MUTEX_FORCE_DISABLE` + +Mutex protection +**************** + +Mutex protection of retained memory drivers is enabled by default when +applications are compiled with multithreading support. This means that +different threads can safely call the retained memory functions without +clashing with other concurrent thread function usage, but means that retained +memory functions cannot be used from ISRs. It is possible to disable mutex +protection globally on all retained memory drivers by enabling +:kconfig:option:`CONFIG_RETAINED_MEM_MUTEX_FORCE_DISABLE` - users are then +responsible for ensuring that the function calls do not conflict with each +other. API Reference ************* diff --git a/doc/hardware/peripherals/rtc.rst b/doc/hardware/peripherals/rtc.rst index c279c7c7913..d2552d078ee 100644 --- a/doc/hardware/peripherals/rtc.rst +++ b/doc/hardware/peripherals/rtc.rst @@ -84,9 +84,9 @@ and clock calibration, these must be enabled by selecting :kconfig:option:`CONFIG_RTC_ALARM`, :kconfig:option:`CONFIG_RTC_UPDATE` and :kconfig:option:`CONFIG_RTC_CALIBRATION`. -The following examples build the test suite for the ``native_posix`` +The following examples build the test suite for the ``native_sim`` board. To build the test suite for a different board, replace the -``native_posix`` board with your board. +``native_sim`` board with your board. To build the test application with the default configuration, testing only the mandatory features, the following command can be used for @@ -95,7 +95,7 @@ reference: .. zephyr-app-commands:: :tool: west :host-os: unix - :board: native_posix + :board: native_sim :zephyr-app: tests/drivers/rtc/rtc_api :goals: build @@ -106,7 +106,7 @@ following command can be used for reference: .. zephyr-app-commands:: :tool: west :host-os: unix - :board: native_posix + :board: native_sim :zephyr-app: tests/drivers/rtc/rtc_api :goals: menuconfig @@ -115,7 +115,7 @@ Then build the test application using the following command: .. zephyr-app-commands:: :tool: west :host-os: unix - :board: native_posix + :board: native_sim :zephyr-app: tests/drivers/rtc/rtc_api :maybe-skip-config: :goals: build diff --git a/doc/hardware/peripherals/tgpio.rst b/doc/hardware/peripherals/tgpio.rst new file mode 100644 index 00000000000..460468693c5 --- /dev/null +++ b/doc/hardware/peripherals/tgpio.rst @@ -0,0 +1,20 @@ +.. _tgpio_api: + + +Time-aware General-Purpose Input/Output (TGPIO) +############################################### + +Overview +******** + +Configuration Options +********************* + +Related configuration options: + +* :kconfig:option:`CONFIG_TIMEAWARE_GPIO` + +API Reference +************* + +.. doxygengroup:: tgpio_interface diff --git a/doc/hardware/porting/arch.rst b/doc/hardware/porting/arch.rst index 8b9e96503b2..0e31a62707b 100644 --- a/doc/hardware/porting/arch.rst +++ b/doc/hardware/porting/arch.rst @@ -59,7 +59,7 @@ Common steps for all architectures: * Setup an initial stack. * If running an :abbr:`XIP (eXecute-In-Place)` kernel, copy initialized data -* from ROM to RAM. + from ROM to RAM. * If not using an ELF loader, zero the BSS section. * Jump to :code:`_Cstart()`, the early kernel initialization @@ -160,7 +160,7 @@ we strongly suggest that handlers at least print some debug information. The information helps figuring out what went wrong when hitting an exception that is a fault, like divide-by-zero or invalid memory access, or an interrupt that is not expected (:dfn:`spurious interrupt`). See the ARM implementation in -:zephyr_file:`arch/arm/core/aarch32/cortex_m/fault.c` for an example. +:zephyr_file:`arch/arm/core/cortex_m/fault.c` for an example. Thread Context Switching ************************ @@ -299,7 +299,7 @@ gracefully exits its entry point function. This means implementing an architecture-specific version of :c:func:`k_thread_abort`, and setting the Kconfig option :kconfig:option:`CONFIG_ARCH_HAS_THREAD_ABORT` as needed for the architecture (e.g. see -:zephyr_file:`arch/arm/core/aarch32/cortex_m/Kconfig`). +:zephyr_file:`arch/arm/core/cortex_m/Kconfig`). Thread Local Storage ******************** @@ -535,7 +535,7 @@ The region specified by ``thread.stack_info.start`` and the initial stack pointer from the very end of the stack object, taking into account storage for TLS and ASLR random offsets. -:: +.. code-block:: none +---------------------+ <- thread.stack_obj | Reserved Memory | } K_(THREAD|KERNEL)_STACK_RESERVED @@ -624,7 +624,7 @@ simply leave an non-present virtual page below every stack when it is mapped into the address space. The stack object will still need to be properly aligned and sized to page granularity. -:: +.. code-block:: none +-----------------------------+ <- thread.stack_obj | Guard reserved memory | } K_KERNEL_STACK_RESERVED @@ -683,7 +683,7 @@ On systems without power-of-two region requirements, the reserved memory area for threads stacks defined by :c:macro:`K_THREAD_STACK_RESERVED` may be used to contain the privilege mode stack. The layout could be something like: -:: +.. code-block:: none +------------------------------+ <- thread.stack_obj | Other platform data | @@ -742,7 +742,7 @@ of the privilege stacks can be looked up quickly at runtime based on the thread stack address using :c:func:`z_priv_stack_find()`. These stacks are laid out the same way as other kernel-only stacks. -:: +.. code-block:: none +-----------------------------+ <- z_priv_stack_find(thread.stack_obj) | Reserved memory | } K_KERNEL_STACK_RESERVED diff --git a/doc/hardware/porting/board_porting.rst b/doc/hardware/porting/board_porting.rst index 8482eacc726..5be561aecb2 100644 --- a/doc/hardware/porting/board_porting.rst +++ b/doc/hardware/porting/board_porting.rst @@ -242,37 +242,6 @@ followed by trial and error. If you want to understand details, you will need to read the rest of the devicetree documentation and the devicetree specification. -Board extensions -**************** - -Board extensions are board fragments that can be present in a board root -folder, under ``${BOARD_ROOT}/boards/extensions``. The extension folder must -follow the naming structure of the original board to extend. The board extension -directory may contain Kconfig fragments and/or devicetree overlays. Board -extensions are, by default, automatically loaded and applied on top of board -files, before anything else. There is no guarantee on which order extensions are -applied, in case multiple exist. This feature shall be disabled by passing -``-DBOARD_EXTENSIONS=OFF`` when building. - -Board extensions are designed for downstream users, for example, -``example-application`` or vendor SDKs. In some situations, certain hardware -description or `choices `_ can not be added in the -upstream Zephyr repository, but they can be in a downstream project, where -custom bindings or driver classes can also be created. This feature may also be -useful in development phases, when the board skeleton lives upstream, but other -features are developed in a downstream module. - -Note that board extensions need to follow the -:ref:`same guidelines ` as regular boards. For -example, it is wrong to enable extra peripherals or subsystems in a board -extension. - -.. warning:: - - Board extensions are not allowed in any module referenced in Zephyr's - ``west.yml`` manifest file. Any board changes are required to be submitted to - the main Zephyr repository. - .. _dt_k6x_example: Example: FRDM-K64F and Hexiwear K64 @@ -358,7 +327,7 @@ named ``plank``: This should at least contain a definition for a ``BOARD_PLANK`` option, which looks something like this: - .. code-block:: none + .. code-block:: kconfig config BOARD_PLANK bool "Plank board" @@ -371,7 +340,7 @@ named ``plank``: The entire file should be inside an ``if BOARD_PLANK`` / ``endif`` pair of lines, like this: - .. code-block:: none + .. code-block:: kconfig if BOARD_PLANK @@ -400,10 +369,10 @@ named ``plank``: your system clock, console, etc. The results are architecture-specific, but typically look something like this: - .. code-block:: none + .. code-block:: cfg - CONFIG_SOC_${VENDOR_XYZ3000}=y /* select your SoC */ - CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=120000000 /* set up your clock, etc */ + CONFIG_SOC_${VENDOR_XYZ3000}=y # select your SoC + CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=120000000 # set up your clock, etc CONFIG_SERIAL=y :file:`plank_x_y_z.conf` @@ -810,3 +779,44 @@ There are some extra things you'll need to do: #. Prepare a pull request adding your board which follows the :ref:`contribute_guidelines`. + +Board extensions +**************** + +Boards already supported by Zephyr can be extended by downstream users, such as +``example-application`` or vendor SDKs. In some situations, certain hardware +description or :ref:`choices ` can not be added in the +upstream Zephyr repository, but they can be in a downstream project, where +custom bindings or driver classes can also be created. This feature may also be +useful in development phases, when the board skeleton lives upstream, but other +features are developed in a downstream module. + +Board extensions are board fragments that can be present in an out-of-tree board +root folder, under ``${BOARD_ROOT}/boards/extensions``. Here is an example +structure of an extension for the ``plank`` board and its revisions: + +.. code-block:: none + + boards/extensions/plank + ├── plank.conf # optional + ├── plank_.conf # optional + ├── plank.overlay # optional + └── plank_.overlay # optional + +A board extension directory must follow the naming structure of the original +board it extends. It may contain Kconfig fragments and/or devicetree overlays. +Extensions are, by default, automatically loaded and applied on top of board +files, before anything else. There is no guarantee on which order extensions are +applied, in case multiple exist. This feature can be disabled by passing +``-DBOARD_EXTENSIONS=OFF`` when building. + +Note that board extensions need to follow the +:ref:`same guidelines ` as regular boards. For +example, it is wrong to enable extra peripherals or subsystems in a board +extension. + +.. warning:: + + Board extensions are not allowed in any module referenced in Zephyr's + ``west.yml`` manifest file. Any board changes are required to be submitted to + the main Zephyr repository. diff --git a/doc/hardware/porting/shields.rst b/doc/hardware/porting/shields.rst index 0f6c1a9a7a4..9eca06177b4 100644 --- a/doc/hardware/porting/shields.rst +++ b/doc/hardware/porting/shields.rst @@ -101,7 +101,7 @@ CMake command Alternatively, it could be set by default in a project's CMakeLists.txt: -.. code-block:: none +.. code-block:: cmake set(SHIELD x_nucleo_iks01a1) @@ -153,7 +153,7 @@ node`_ that looks like the following into the board devicetree file: .. _nexus node: https://github.com/devicetree-org/devicetree-specification/blob/4b1dac80eaca45b4babf5299452a951008a5d864/source/devicetree-basics.rst#nexus-nodes-and-specifier-mapping -.. code-block:: none +.. code-block:: devicetree arduino_header: connector { compatible = "arduino-header-r3"; @@ -193,7 +193,7 @@ bits of the flags correspond to features that can be configured in devicetree. In some cases it's necessary to use a non-zero flag value to tell the driver how a particular pin behaves, as with: -.. code-block:: none +.. code-block:: devicetree drdy-gpios = <&arduino_header 11 GPIO_ACTIVE_LOW>; diff --git a/doc/index-tex.rst b/doc/index-tex.rst index 09ef9e9459e..9c0527ae73a 100644 --- a/doc/index-tex.rst +++ b/doc/index-tex.rst @@ -24,3 +24,4 @@ Zephyr Project Documentation project/index.rst security/index.rst safety/index.rst + glossary.rst diff --git a/doc/introduction/index.rst b/doc/introduction/index.rst index 918801fc7d4..85968ca456a 100644 --- a/doc/introduction/index.rst +++ b/doc/introduction/index.rst @@ -9,6 +9,7 @@ sensors and LED wearables to sophisticated embedded controllers, smart watches, and IoT wireless applications. The Zephyr kernel supports multiple architectures, including: + - ARCv2 (EM and HS) and ARCv3 (HS6X) - ARMv6-M, ARMv7-M, and ARMv8-M (Cortex-M) - ARMv7-A and ARMv8-A (Cortex-A, 32- and 64-bit) @@ -143,13 +144,12 @@ Zephyr offers a large and ever growing number of features including: **Native Linux, macOS, and Windows Development** A command-line CMake build environment runs on popular developer OS - systems. A native POSIX port lets you build and run Zephyr as a native - application on Linux and other OSes, aiding development and testing. + systems. A native port (:ref:`native_sim `) lets you build and run Zephyr as a native + application on Linux, aiding development and testing. -**Virtual File System Interface with LittleFS and FATFS Support** - LittleFS and FATFS Support, - FCB (Flash Circular Buffer) for memory constrained applications, and - file system enhancements for logging and configuration. +**Virtual File System Interface with ext2, FatFs, and LittleFS Support** + ext2, LittleFS and FatFS support; FCB (Flash Circular Buffer) for memory constrained + applications. **Powerful multi-backend logging Framework** Support for log filtering, object dumping, panic mode, multiple backends @@ -170,9 +170,9 @@ Zephyr offers a large and ever growing number of features including: NVS allows storage of binary blobs, strings, integers, longs, and any combination of these. -**Native POSIX port** - Supports running Zephyr as a Linux application with support for various - subsystems and networking. +**Native port** + :ref:`Native sim ` allows running Zephyr as a Linux application with support + for various subsystems and networking. .. include:: ../../README.rst diff --git a/doc/kernel/code-relocation.rst b/doc/kernel/code-relocation.rst index ee534ffe3ef..a9da18e98cd 100644 --- a/doc/kernel/code-relocation.rst +++ b/doc/kernel/code-relocation.rst @@ -135,7 +135,7 @@ A test showcasing this feature is provided at This test shows how the code relocation feature is used. This test will place .text, .data, .bss from 3 files to various parts in the SRAM -using a custom linker file derived from ``include/arch/arm/aarch32/cortex_m/scripts/linker.ld`` +using a custom linker file derived from ``include/zephyr/arch/arm/cortex_m/scripts/linker.ld`` A sample showcasing the NOCOPY flag is provided at ``$ZEPHYR_BASE/samples/application_development/code_relocation_nocopy/`` diff --git a/doc/kernel/data_structures/mpsc_pbuf.rst b/doc/kernel/data_structures/mpsc_pbuf.rst index 4ecef5b62e4..73780d6a426 100644 --- a/doc/kernel/data_structures/mpsc_pbuf.rst +++ b/doc/kernel/data_structures/mpsc_pbuf.rst @@ -54,7 +54,7 @@ Header state: +-------+------+----------------------+ Packet buffer space contains free space, valid user packets and internal skip -packets. Internal skip packets indicates padding, e.g. at the of the buffer. +packets. Internal skip packets indicates padding, e.g. at the end of the buffer. Allocation ^^^^^^^^^^ diff --git a/doc/kernel/data_structures/rbtree.rst b/doc/kernel/data_structures/rbtree.rst index 135960200f8..aac446cbad6 100644 --- a/doc/kernel/data_structures/rbtree.rst +++ b/doc/kernel/data_structures/rbtree.rst @@ -27,7 +27,7 @@ the algorithm to work correctly. As with the slist and dlist containers, nodes within an rbtree are represented as a :c:struct:`rbnode` structure which exists in -user-managed memory, typically embedded within the the data structure +user-managed memory, typically embedded within the data structure being tracked in the tree. Unlike the list code, the data within an rbnode is entirely opaque. It is not possible for the user to extract the binary tree topology and "manually" traverse the tree as it is for diff --git a/doc/kernel/data_structures/ring_buffers.rst b/doc/kernel/data_structures/ring_buffers.rst index 63ff3f2b4eb..d077cf1f21f 100644 --- a/doc/kernel/data_structures/ring_buffers.rst +++ b/doc/kernel/data_structures/ring_buffers.rst @@ -44,7 +44,7 @@ A ring buffer has the following key properties: bytes or 32-bit words that have been added to the ring buffer but not yet removed. -* A **data buffer size**, measured in bytes or 32-byte words. This governs +* A **data buffer size**, measured in bytes or 32-bit words. This governs the maximum amount of data (including possible metadata values) the ring buffer can hold. @@ -53,7 +53,7 @@ data buffer to empty. A ``struct ring_buf`` may be placed anywhere in user-accessible memory, and must be initialized with :c:func:`ring_buf_init` or -:c:func:`ring_buf_element_init` before use. This must be provided a region +:c:func:`ring_buf_item_init` before use. This must be provided a region of user-controlled memory for use as the buffer itself. Note carefully that the units of the size of the buffer passed change (either bytes or words) depending on how the ring buffer will be used later. Macros for combining these steps in a diff --git a/doc/kernel/data_structures/slist.rst b/doc/kernel/data_structures/slist.rst index add76e869a6..c1eb062ff83 100644 --- a/doc/kernel/data_structures/slist.rst +++ b/doc/kernel/data_structures/slist.rst @@ -108,7 +108,7 @@ ways identically to the slist API. It adds the ability to associate exactly two bits of user defined "flags" with each list node. These can be accessed and modified with -:c:func:`sys_sfnode_flags_get` and :c:func:`sys_sfnode_flags_get`. +:c:func:`sys_sfnode_flags_get` and :c:func:`sys_sfnode_flags_set`. Internally, the flags are stored unioned with the bottom bits of the next pointer and incur no SRAM storage overhead when compared with the simpler slist code. diff --git a/doc/kernel/drivers/index.rst b/doc/kernel/drivers/index.rst index 33e1027c07e..51b31de006f 100644 --- a/doc/kernel/drivers/index.rst +++ b/doc/kernel/drivers/index.rst @@ -235,11 +235,11 @@ implementation of both the subsystem API and the specific APIs: #ifdef CONFIG_USERSPACE - #include + #include int z_vrfy_specific_from_user(const struct device *dev, int bar) { - Z_OOPS(Z_SYSCALL_SPECIFIC_DRIVER(dev, K_OBJ_DRIVER_GENERIC, &api)); + K_OOPS(K_SYSCALL_SPECIFIC_DRIVER(dev, K_OBJ_DRIVER_GENERIC, &api)); return z_impl_specific_do_that(dev, bar) } @@ -343,13 +343,6 @@ allow the user to specify at what time during the boot sequence the init function will be executed. Any driver will specify one of four initialization levels: -``EARLY`` - Used very early in the boot process, right after entering the C domain - (``z_cstart()``). This can be used in architectures and SoCs that extend - or implement architecture code and use drivers or system services that - have to be initialized before the Kernel calls any architecture specific - initialization code. - ``PRE_KERNEL_1`` Used for devices that have no dependencies, such as those that rely solely on hardware present in the processor/SOC. These devices cannot @@ -368,12 +361,6 @@ initialization levels: Used for devices that require kernel services during configuration. Init functions at this level run in context of the kernel main task. -``APPLICATION`` - Used for application components (i.e. non-kernel components) that need - automatic configuration. These devices can use all services provided by - the kernel during configuration. Init functions at this level run on - the kernel main task. - Within each initialization level you may specify a priority level, relative to other devices in the same initialization level. The priority level is specified as an integer value in the range 0 to 99; lower values indicate earlier @@ -394,6 +381,18 @@ In some cases you may just need to run a function at boot. For such cases, the data structures and there isn't a way to later get a device pointer by name. The same device policies for initialization level and priority apply. +Inspecting the initialization sequence +************************************** + +Device drivers declared with :c:macro:`DEVICE_DEFINE` (or any variations of it) +and :c:macro:`SYS_INIT` are processed at boot time and the corresponding +initialization functions are called sequentially according to their specified +level and priority. + +Sometimes it's useful to inspect the final sequence of initialization function +call as produced by the linker. To do that, use the ``initlevels`` CMake +target, for example ``west build -t initlevels``. + Error handling ************** diff --git a/doc/kernel/index.rst b/doc/kernel/index.rst index b8cf4bd38eb..90f82b5b53c 100644 --- a/doc/kernel/index.rst +++ b/doc/kernel/index.rst @@ -12,6 +12,7 @@ Kernel memory_management/index.rst data_structures/index.rst timing_functions/index.rst + object_cores/index.rst timeutil.rst util/index.rst iterable_sections/index.rst diff --git a/doc/kernel/memory_management/slabs.rst b/doc/kernel/memory_management/slabs.rst index 72d276399cc..7f6945ee386 100644 --- a/doc/kernel/memory_management/slabs.rst +++ b/doc/kernel/memory_management/slabs.rst @@ -71,7 +71,7 @@ A memory slab is defined using a variable of type :c:type:`k_mem_slab`. It must then be initialized by calling :c:func:`k_mem_slab_init`. The following code defines and initializes a memory slab that has 6 blocks -that are 400 bytes long, each of which is aligned to a 4-byte boundary.. +that are 400 bytes long, each of which is aligned to a 4-byte boundary. .. code-block:: c @@ -109,7 +109,7 @@ A warning is printed if a suitable block is not obtained. char *block_ptr; - if (k_mem_slab_alloc(&my_slab, &block_ptr, 100) == 0)) { + if (k_mem_slab_alloc(&my_slab, (void **)&block_ptr, K_MSEC(100)) == 0) { memset(block_ptr, 0, 400); ... } else { @@ -128,9 +128,9 @@ then releases it once it is no longer needed. char *block_ptr; - k_mem_slab_alloc(&my_slab, &block_ptr, K_FOREVER); + k_mem_slab_alloc(&my_slab, (void **)&block_ptr, K_FOREVER); ... /* use memory block pointed at by block_ptr */ - k_mem_slab_free(&my_slab, block_ptr); + k_mem_slab_free(&my_slab, (void *)block_ptr); Suggested Uses ************** diff --git a/doc/kernel/memory_management/sys_mem_blocks.rst b/doc/kernel/memory_management/sys_mem_blocks.rst index abc1edd1a80..da84f7c151c 100644 --- a/doc/kernel/memory_management/sys_mem_blocks.rst +++ b/doc/kernel/memory_management/sys_mem_blocks.rst @@ -112,7 +112,7 @@ to a 4-byte boundary: SYS_MEM_BLOCKS_DEFINE(allocator, 64, 4, 4); -Similarly, you can define a memory slab in private scope: +Similarly, you can define a memory blocks allocator in private scope: .. code-block:: c diff --git a/doc/kernel/object_cores/index.rst b/doc/kernel/object_cores/index.rst new file mode 100644 index 00000000000..3e8a72d68a5 --- /dev/null +++ b/doc/kernel/object_cores/index.rst @@ -0,0 +1,235 @@ +.. _object_cores_api: + +Object Cores +############ + +Object cores are a kernel debugging tool that can be used to both identify and +perform operations on registered objects. + +.. contents:: + :local: + :depth: 2 + +Object Core Concepts +******************** + +Each instance of an object embeds an object core field named `obj_core`. +Objects of the same type are linked together via their respective object +cores to form a singly linked list. Each object core also links to the their +respective object type. Each object type contains a singly linked list +linking together all the object cores of that type. Object types are also +linked together via a singly linked list. Together, this can allow debugging +tools to traverse all the objects in the system. + +Object cores have been integrated into following kernel objects: + * :ref:`Condition Variables ` + * :ref:`Events ` + * :ref:`FIFOs ` and :ref:`LIFOs ` + * :ref:`Mailboxes ` + * :ref:`Memory Slabs ` + * :ref:`Message Queues ` + * :ref:`Mutexes ` + * :ref:`Pipes ` + * :ref:`Semaphores ` + * :ref:`Threads ` + * :ref:`Timers ` + * :ref:`System Memory Blocks ` + +Developers are free to integrate them if desired into other objects within +their projects. + +Object Core Statistics Concepts +******************************* +A variety of kernel objects allow for the gathering and reporting of statistics. +Object cores provide a uniform means to retrieve that information via object +core statistics. When enabled, the object type contains a pointer to a +statistics descriptor that defines the various operations that have been +enabled for interfacing with the object's statistics. Additionally, the object +core contains a pointer to the "raw" statistical information associated with +that object. Raw data is the raw, unmanipulated data associated with the +statistics. Queried data may be "raw", but it may also have been manipulated in +some way by calculation (such as determining an average). + +The following table indicates both what objects have been integrated into the +object core statistics as well as the structures used for both "raw" and +"queried" data. + +===================== ============================== ============================== +Object Raw Data Type Query Data Type +===================== ============================== ============================== +struct mem_slab struct mem_slab_info struct sys_memory_stats +struct sys_mem_blocks struct sys_mem_blocks_info struct sys_memory_stats +struct k_thread struct k_cycle_stats struct k_thread_runtime_stats +struct _cpu struct k_cycle_stats struct k_thread_runtime_stats +struct z_kernel struct k_cycle_stats[num CPUs] struct k_thread_runtime_stats +===================== ============================== ============================== + +Implementation +************** + +Defining a New Object Type +========================== + +An object type is defined using a global variable of type +:c:struct:`k_obj_type`. It must be initialized before any objects of that type +are initialized. The following code shows how a new object type can be +initialized for use with object cores and object core statistics. + +.. code-block:: c + + /* Unique object type ID */ + + #define K_OBJ_TYPE_MY_NEW_TYPE K_OBJ_TYPE_ID_GEN("UNIQ") + struct k_obj_type my_obj_type; + + struct my_obj_type_raw_info { + ... + }; + + struct my_obj_type_query_stats { + ... + }; + + struct my_new_obj { + ... + struct k_obj_core obj_core; + struct my_obj_type_raw_info info; + }; + + struct k_obj_core_stats_desc my_obj_type_stats_desc = { + .raw_size = sizeof(struct my_obj_type_raw_stats), + .query_size = sizeof(struct my_obj_type_query_stats), + .raw = my_obj_type_stats_raw, + .query = my_obj_type_stats_query, + .reset = my_obj_type_stats_reset, + .disable = NULL, /* Stats gathering is always on */ + .enable = NULL, /* Stats gathering is always on */ + }; + + void my_obj_type_init(void) + { + z_obj_type_init(&my_obj_type, K_OBJ_TYPE_MY_NEW_TYPE, + offsetof(struct my_new_obj, obj_core); + k_obj_type_stats_init(&my_obj_type, &my_obj_type_stats_desc); + } + +Initializing a New Object Core +============================== + +Kernel objects that have already been integrated into the object core framework +automatically have their object cores initialized when the object is +initialized. However, developers that wish to add their own objects into the +framework need to both initialize the object core and link it. The following +code builds on the example above and initializes the object core. + +.. code-block:: c + + void my_new_obj_init(struct my_new_obj *new_obj) + { + ... + k_obj_core_init(K_OBJ_CORE(new_obj), &my_obj_type); + k_obj_core_link(K_OBJ_CORE(new_obj)); + k_obj_core_stats_register(K_OBJ_CORE(new_obj), &new_obj->raw_stats, + sizeof(struct my_obj_type_raw_info)); + } + +Walking a List of Object Cores +============================== + +Two routines exist for walking the list of object cores linked to an object +type. These are :c:func:`k_obj_type_walk_locked` and +:c:func:`k_obj_type_walk_unlocked`. The following code builds upon the example +above and prints the addresses of all the objects of that new object type. + +.. code-block:: c + + int walk_op(struct k_obj_core *obj_core, void *data) + { + uint8_t *ptr; + + ptr = obj_core; + ptr -= obj_core->type->obj_core_offset; + + printk("%p\n", ptr); + + return 0; + } + + void print_object_addresses(void) + { + struct k_obj_type *obj_type; + + /* Find the object type */ + + obj_type = k_obj_type_find(K_OBJ_TYPE_MY_NEW_TYPE); + + /* Walk the list of objects */ + + k_obj_type_walk_unlocked(obj_type, walk_op, NULL); + } + +Object Core Statistics Querying +=============================== + +The following code builds on the examples above and shows how an object +integrated into the object core statistics framework can both retrieve queried +data and reset the stats associated with the object. + +.. code-block:: c + + struct my_new_obj my_obj; + + ... + + void my_func(void) + { + struct my_obj_type_query_stats my_stats; + int status; + + my_obj_type_init(&my_obj); + + ... + + status = k_obj_core_stats_query(K_OBJ_CORE(&my_obj), + &my_stats, sizeof(my_stats)); + if (status != 0) { + /* Failed to get stats */ + ... + } else { + k_obj_core_stats_reset(K_OBJ_CORE(&my_obj)); + } + + ... + } + +Configuration Options +********************* + +Related configuration options: + +* :kconfig:option:`CONFIG_OBJ_CORE` +* :kconfig:option:`CONFIG_OBJ_CORE_CONDVAR` +* :kconfig:option:`CONFIG_OBJ_CORE_EVENT` +* :kconfig:option:`CONFIG_OBJ_CORE_FIFO` +* :kconfig:option:`CONFIG_OBJ_CORE_LIFO` +* :kconfig:option:`CONFIG_OBJ_CORE_MAILBOX` +* :kconfig:option:`CONFIG_OBJ_CORE_MEM_SLAB` +* :kconfig:option:`CONFIG_OBJ_CORE_MSGQ` +* :kconfig:option:`CONFIG_OBJ_CORE_MUTEX` +* :kconfig:option:`CONFIG_OBJ_CORE_PIPE` +* :kconfig:option:`CONFIG_OBJ_CORE_SEM` +* :kconfig:option:`CONFIG_OBJ_CORE_STACK` +* :kconfig:option:`CONFIG_OBJ_CORE_THREAD` +* :kconfig:option:`CONFIG_OBJ_CORE_TIMER` +* :kconfig:option:`CONFIG_OBJ_CORE_SYS_MEM_BLOCKS` +* :kconfig:option:`CONFIG_OBJ_CORE_STATS` +* :kconfig:option:`CONFIG_OBJ_CORE_STATS_MEM_SLAB` +* :kconfig:option:`CONFIG_OBJ_CORE_STATS_THREAD` +* :kconfig:option:`CONFIG_OBJ_CORE_STATS_SYSTEM` +* :kconfig:option:`CONFIG_OBJ_CORE_STATS_SYS_MEM_BLOCKS` + +API Reference +************* + +.. doxygengroup:: obj_core_apis +.. doxygengroup:: obj_core_stats_apis diff --git a/doc/kernel/services/data_passing/mailboxes.rst b/doc/kernel/services/data_passing/mailboxes.rst index 41140d8aed4..4561bce7780 100644 --- a/doc/kernel/services/data_passing/mailboxes.rst +++ b/doc/kernel/services/data_passing/mailboxes.rst @@ -248,7 +248,6 @@ portion of the message isn't used. send_msg.info = random_value; send_msg.size = 0; send_msg.tx_data = NULL; - send_msg.tx_block.data = NULL; send_msg.tx_target_thread = K_ANY; /* send message and wait until a consumer receives it */ @@ -284,7 +283,6 @@ the maximum size message buffer that each thread can handle. send_msg.info = buffer_bytes_used; send_msg.size = buffer_bytes_used; send_msg.tx_data = buffer; - send_msg.tx_block.data = NULL; send_msg.tx_target_thread = K_ANY; /* send message and wait until a consumer receives it */ diff --git a/doc/kernel/services/data_passing/message_queues.rst b/doc/kernel/services/data_passing/message_queues.rst index 5e8d43eb4f2..afa33310484 100644 --- a/doc/kernel/services/data_passing/message_queues.rst +++ b/doc/kernel/services/data_passing/message_queues.rst @@ -25,11 +25,6 @@ A message queue has the following key properties: * A **maximum quantity** of data items that can be queued in the ring buffer. -The message queue's ring buffer must be aligned to an N-byte boundary, where -N is a power of 2 (i.e. 1, 2, 4, 8, ...). To ensure that the messages stored in -the ring buffer are similarly aligned to this boundary, the data item size -must also be a multiple of N. - A message queue must be initialized before it can be used. This sets its ring buffer to empty. @@ -64,6 +59,11 @@ the size of the receiving area *must* equal the message queue's data item size. The kernel does allow an ISR to receive an item from a message queue, however the ISR must not attempt to wait if the message queue is empty. +.. note:: + Alignment of the message queue's ring buffer is not necessary. + The underlying implementation uses :c:func:`memcpy` (which is + alignment-agnostic) and does not expose any internal pointers. + Implementation ************** @@ -84,7 +84,7 @@ that is capable of holding 10 items, each of which is 12 bytes long. uint32_t field3; }; - char __aligned(4) my_msgq_buffer[10 * sizeof(struct data_item_type)]; + char my_msgq_buffer[10 * sizeof(struct data_item_type)]; struct k_msgq my_msgq; k_msgq_init(&my_msgq, my_msgq_buffer, sizeof(struct data_item_type), 10); @@ -97,22 +97,7 @@ that the macro defines both the message queue and its buffer. .. code-block:: c - K_MSGQ_DEFINE(my_msgq, sizeof(struct data_item_type), 10, 4); - -The following code demonstrates an alignment implementation for the -structure defined in the previous example code. ``aligned`` means each -:c:struct:`data_item_type` will begin on the specified byte boundary. -``aligned(4)`` means that the structure is aligned to an address that -is divisible by 4. - -.. code-block:: c - - typedef struct { - uint32_t field1; - uint32_t field2; - uint32_t field3; - }__attribute__((aligned(4))) data_item_type; - + K_MSGQ_DEFINE(my_msgq, sizeof(struct data_item_type), 10, 1); Writing to a Message Queue ========================== diff --git a/doc/kernel/services/data_passing/pipes.rst b/doc/kernel/services/data_passing/pipes.rst index 62c4f8f0223..bdeec48f011 100644 --- a/doc/kernel/services/data_passing/pipes.rst +++ b/doc/kernel/services/data_passing/pipes.rst @@ -150,12 +150,12 @@ process data items generated by one or more producing threads. while (1) { rc = k_pipe_get(&my_pipe, buffer, sizeof(buffer), &bytes_read, - sizeof(header), K_MSEC(100)); + sizeof(*header), K_MSEC(100)); - if ((rc < 0) || (bytes_read < sizeof (header))) { + if ((rc < 0) || (bytes_read < sizeof (*header))) { /* Incomplete message header received */ ... - } else if (header->num_data_bytes + sizeof(header) > bytes_read) { + } else if (header->num_data_bytes + sizeof(*header) > bytes_read) { /* Only some data was received */ ... } else { diff --git a/doc/kernel/services/interrupts.rst b/doc/kernel/services/interrupts.rst index 1496dc7fa7a..849e614a562 100644 --- a/doc/kernel/services/interrupts.rst +++ b/doc/kernel/services/interrupts.rst @@ -215,6 +215,38 @@ priority of the thread handling the offload, it is possible that the currently executing cooperative thread or other higher-priority threads may execute before the thread handling the offload is scheduled. +Sharing interrupt lines +======================= + +In the case of some hardware platforms, the same interrupt lines may be used +by different IPs. For example, interrupt 17 may be used by a DMA controller to +signal that a data transfer has been completed or by a DAI controller to signal +that the transfer FIFO has reached its watermark. To make this work, one would +have to either employ some special logic or find a workaround (for example, using +the shared_irq interrupt controller), which doesn't scale very well. + +To solve this problem, one may use shared interrupts, which can be enabled using +:kconfig:option:`CONFIG_SHARED_INTERRUPTS`. Whenever an attempt to register +a second ISR/argument pair on the same interrupt line is made (using +:c:macro:`IRQ_CONNECT` or :c:func:`irq_connect_dynamic`), the interrupt line will +become shared, meaning the two ISR/argument pairs (previous one and the one that +has just been registered) will be invoked each time the interrupt is triggered. +The entities that make use of an interrupt line in the shared interrupt context +are known as clients. The maximum number of allowed clients for an interrupt is +controlled by :kconfig:option:`CONFIG_SHARED_IRQ_MAX_NUM_CLIENTS`. + +Interrupt sharing is transparent to the user. As such, the user may register +interrupts using :c:macro:`IRQ_CONNECT` and :c:func:`irq_connect_dynamic` as +they normally would. The interrupt sharing is taken care of behind the scenes. + +Enabling the shared interrupt support and dynamic interrupt support will +allow users to dynamically disconnect ISRs using :c:func:`irq_disconnect_dynamic`. +After an ISR is disconnected, whenever the interrupt line for which it was +register gets triggered, the ISR will no longer get invoked. + +Please note that enabling :kconfig:option:`CONFIG_SHARED_INTERRUPTS` will +result in a non-negligible increase in the binary size. Use with caution. + Implementation ************** @@ -326,6 +358,98 @@ architecture-specific basis. (The feature is currently implemented in ARM Cortex-M architecture variant. Dynamic direct interrupts feature is exposed to the user via an ARM-only API.) +Sharing an interrupt line +========================= + +The following code defines two ISRs using the same interrupt number. + +.. code-block:: c + + #define MY_DEV_IRQ 24 /* device uses INTID 24 */ + #define MY_DEV_IRQ_PRIO 2 /* device uses interrupt priority 2 */ + /* this argument may be anything */ + #define MY_FST_ISR_ARG INT_TO_POINTER(1) + /* this argument may be anything */ + #define MY_SND_ISR_ARG INT_TO_POINTER(2) + #define MY_IRQ_FLAGS 0 /* IRQ flags */ + + void my_first_isr(void *arg) + { + ... /* some magic happens here */ + } + + void my_second_isr(void *arg) + { + ... /* even more magic happens here */ + } + + void my_isr_installer(void) + { + ... + IRQ_CONNECT(MY_DEV_IRQ, MY_DEV_IRQ_PRIO, my_first_isr, MY_FST_ISR_ARG, MY_IRQ_FLAGS); + IRQ_CONNECT(MY_DEV_IRQ, MY_DEV_IRQ_PRIO, my_second_isr, MY_SND_ISR_ARG, MY_IRQ_FLAGS); + ... + } + +The same restrictions regarding :c:macro:`IRQ_CONNECT` described in `Defining a regular ISR`_ +are applicable here. If :kconfig:option:`CONFIG_SHARED_INTERRUPTS` is disabled, the above +code will generate a build error. Otherwise, the above code will result in the two ISRs +being invoked each time interrupt 24 is triggered. + +If :kconfig:option:`CONFIG_SHARED_IRQ_MAX_NUM_CLIENTS` is set to a value lower than 2 +(current number of clients), a build error will be generated. + +If dynamic interrupts are enabled, c:func:`irq_connect_dynamic` will allow sharing interrupts +during runtime. Exceeding the configured maximum number of allowed clients will result in +a failed assertion. + +Dynamically disconnecting an ISR +================================ + +The following code defines two ISRs using the same interrupt number. The second +ISR is disconnected during runtime. + +.. code-block:: c + + #define MY_DEV_IRQ 24 /* device uses INTID 24 */ + #define MY_DEV_IRQ_PRIO 2 /* device uses interrupt priority 2 */ + /* this argument may be anything */ + #define MY_FST_ISR_ARG INT_TO_POINTER(1) + /* this argument may be anything */ + #define MY_SND_ISR_ARG INT_TO_POINTER(2) + #define MY_IRQ_FLAGS 0 /* IRQ flags */ + + void my_first_isr(void *arg) + { + ... /* some magic happens here */ + } + + void my_second_isr(void *arg) + { + ... /* even more magic happens here */ + } + + void my_isr_installer(void) + { + ... + IRQ_CONNECT(MY_DEV_IRQ, MY_DEV_IRQ_PRIO, my_first_isr, MY_FST_ISR_ARG, MY_IRQ_FLAGS); + IRQ_CONNECT(MY_DEV_IRQ, MY_DEV_IRQ_PRIO, my_second_isr, MY_SND_ISR_ARG, MY_IRQ_FLAGS); + ... + } + + void my_isr_uninstaller(void) + { + ... + irq_disconnect_dynamic(MY_DEV_IRQ, MY_DEV_IRQ_PRIO, my_first_isr, MY_FST_ISR_ARG, MY_IRQ_FLAGS); + ... + } + +The :c:func:`irq_disconnect_dynamic` call will result in interrupt 24 becoming +unshared, meaning the system will act as if the first :c:macro:`IRQ_CONNECT` +call never happened. This behaviour is only allowed if +:kconfig:option:`CONFIG_DYNAMIC_INTERRUPTS` is enabled, otherwise a linker +error will be generated. + Implementation Details ====================== @@ -417,6 +541,32 @@ This is used by the common software IRQ handler to look up the ISR and its argument and execute it. The active IRQ line is looked up in an interrupt controller register and used to index this table. +Shared SW ISR Table +------------------- + +This is an array of struct z_shared_isr_table_entry: + +.. code-block:: c + + struct z_shared_isr_table_entry { + struct z_shared_isr_client clients[CONFIG_SHARED_IRQ_MAX_NUM_CLIENTS]; + size_t client_num; + }; + +This table keeps track of the registered clients for each of the interrupt +lines. Whenever an interrupt line becomes shared, c:func:`z_shared_isr` will +replace the currently registered ISR in _sw_isr_table. This special ISR will +iterate through the list of registered clients and invoke the ISRs. + +The definition for struct z_shared_isr_client is as follows: + +.. code-block:: c + + struct z_shared_isr_client { + void (*isr)(const void *arg); + const void *arg; + }; + x86 Details ----------- diff --git a/doc/kernel/services/smp/smp.rst b/doc/kernel/services/smp/smp.rst index 395d1874f58..0f1e29c9f12 100644 --- a/doc/kernel/services/smp/smp.rst +++ b/doc/kernel/services/smp/smp.rst @@ -18,7 +18,7 @@ variable. This must be set to "y" to enable SMP features, otherwise a uniprocessor kernel will be built. In general the platform default will have enabled this anywhere it's supported. When enabled, the number of physical CPUs available is visible at build time as -:kconfig:option:`CONFIG_MP_NUM_CPUS`. Likewise, the default for this will be the +:kconfig:option:`CONFIG_MP_MAX_NUM_CPUS`. Likewise, the default for this will be the number of available CPUs on the platform and it is not expected that typical apps will change it. But it is legal and supported to set this to a smaller (but obviously not larger) number for special diff --git a/doc/kernel/services/synchronization/events.rst b/doc/kernel/services/synchronization/events.rst index 7182803883a..cbb86894723 100644 --- a/doc/kernel/services/synchronization/events.rst +++ b/doc/kernel/services/synchronization/events.rst @@ -33,10 +33,10 @@ conditions of multiple threads waiting on the event object. All threads whose match conditions have been met are made active at the same time. Threads may wait on one or more events. They may either wait for all of the -the requested events, or for any of them. Furthermore, threads making a wait -request have the option of resetting the current set of events tracked by the -event object prior to waiting. Care must be taken with this option when -multiple threads wait on the same event object. +requested events, or for any of them. Furthermore, threads making a wait request +have the option of resetting the current set of events tracked by the event +object prior to waiting. Care must be taken with this option when multiple +threads wait on the same event object. .. note:: The kernel does allow an ISR to query an event object, however the ISR must diff --git a/doc/kernel/services/synchronization/mutexes.rst b/doc/kernel/services/synchronization/mutexes.rst index b813fec2d68..8fa7d150422 100644 --- a/doc/kernel/services/synchronization/mutexes.rst +++ b/doc/kernel/services/synchronization/mutexes.rst @@ -20,7 +20,7 @@ is referenced by its memory address. A mutex has the following key properties: -* A **lock count** that indicates the number of times the mutex has be locked +* A **lock count** that indicates the number of times the mutex has been locked by the thread that has locked it. A count of zero indicates that the mutex is unlocked. diff --git a/doc/kernel/usermode/kernelobjects.rst b/doc/kernel/usermode/kernelobjects.rst index 1ac62ab8a96..a5a20b6500e 100644 --- a/doc/kernel/usermode/kernelobjects.rst +++ b/doc/kernel/usermode/kernelobjects.rst @@ -210,7 +210,7 @@ Some objects will be implicitly initialized at boot: is run by the kernel early in the boot process. If a kernel object is initialized with a private static initializer, the object -must have :c:func:`z_object_init` called on it at some point by a supervisor +must have :c:func:`k_object_init` called on it at some point by a supervisor thread, otherwise the kernel will consider the object uninitialized if accessed by a user thread. This is very uncommon, typically only for kernel objects that are embedded within some larger struct and initialized statically. @@ -228,7 +228,7 @@ are embedded within some larger struct and initialized statically. }; ... - z_object_init(&my_foo.sem); + k_object_init(&my_foo.sem); ... diff --git a/doc/kernel/usermode/memory_domain.rst b/doc/kernel/usermode/memory_domain.rst index ff5d419ffd8..a1ddcd395e9 100644 --- a/doc/kernel/usermode/memory_domain.rst +++ b/doc/kernel/usermode/memory_domain.rst @@ -419,7 +419,7 @@ dependent. The complete list of available partition attributes for a specific architecture is found in the architecture-specific include file -``include/arch//arch.h``, (for example, ``include/arch/arm/aarch32/arch.h``.) +``include/zephyr/arch//arch.h``, (for example, ``include/zehpyr/arch/arm/arch.h``.) Some examples of partition attributes are: .. code-block:: c diff --git a/doc/kernel/usermode/mpu_stack_objects.rst b/doc/kernel/usermode/mpu_stack_objects.rst index 944be144ada..477a4596757 100644 --- a/doc/kernel/usermode/mpu_stack_objects.rst +++ b/doc/kernel/usermode/mpu_stack_objects.rst @@ -6,8 +6,7 @@ MPU Stack Objects Thread Stack Creation ********************* -Thread stacks are declared statically with :c:macro:`K_THREAD_STACK_DEFINE()` -or embedded within structures using :c:macro:`K_THREAD_STACK_MEMBER()` +Thread stacks are declared statically with :c:macro:`K_THREAD_STACK_DEFINE()`. For architectures which utilize memory protection unit (MPU) hardware, stacks are physically contiguous allocations. This contiguous allocation diff --git a/doc/kernel/usermode/syscalls.rst b/doc/kernel/usermode/syscalls.rst index af16fbd2e4f..f751697d9a3 100644 --- a/doc/kernel/usermode/syscalls.rst +++ b/doc/kernel/usermode/syscalls.rst @@ -271,7 +271,7 @@ passed in. This includes: * Any other arguments that have a limited range of valid values. Verification functions involve a great deal of boilerplate code which has been -made simpler by some macros in :zephyr_file:`include/zephyr/syscall_handler.h`. +made simpler by some macros in :zephyr_file:`include/zephyr/internal/syscall_handler.h`. Verification functions should be declared using these macros. Argument Validation @@ -279,50 +279,50 @@ Argument Validation Several macros exist to validate arguments: -* :c:macro:`Z_SYSCALL_OBJ()` Checks a memory address to assert that it is +* :c:macro:`K_SYSCALL_OBJ()` Checks a memory address to assert that it is a valid kernel object of the expected type, that the calling thread has permissions on it, and that the object is initialized. -* :c:macro:`Z_SYSCALL_OBJ_INIT()` is the same as - :c:macro:`Z_SYSCALL_OBJ()`, except that the provided object may be +* :c:macro:`K_SYSCALL_OBJ_INIT()` is the same as + :c:macro:`K_SYSCALL_OBJ()`, except that the provided object may be uninitialized. This is useful for verifiers of object init functions. -* :c:macro:`Z_SYSCALL_OBJ_NEVER_INIT()` is the same as - :c:macro:`Z_SYSCALL_OBJ()`, except that the provided object must be +* :c:macro:`K_SYSCALL_OBJ_NEVER_INIT()` is the same as + :c:macro:`K_SYSCALL_OBJ()`, except that the provided object must be uninitialized. This is not used very often, currently only for :c:func:`k_thread_create()`. -* :c:macro:`Z_SYSCALL_MEMORY_READ()` validates a memory buffer of a particular +* :c:macro:`K_SYSCALL_MEMORY_READ()` validates a memory buffer of a particular size. The calling thread must have read permissions on the entire buffer. -* :c:macro:`Z_SYSCALL_MEMORY_WRITE()` is the same as - :c:macro:`Z_SYSCALL_MEMORY_READ()` but the calling thread must additionally +* :c:macro:`K_SYSCALL_MEMORY_WRITE()` is the same as + :c:macro:`K_SYSCALL_MEMORY_READ()` but the calling thread must additionally have write permissions. -* :c:macro:`Z_SYSCALL_MEMORY_ARRAY_READ()` validates an array whose total size +* :c:macro:`K_SYSCALL_MEMORY_ARRAY_READ()` validates an array whose total size is expressed as separate arguments for the number of elements and the element size. This macro correctly accounts for multiplication overflow when computing the total size. The calling thread must have read permissions on the total size. -* :c:macro:`Z_SYSCALL_MEMORY_ARRAY_WRITE()` is the same as - :c:macro:`Z_SYSCALL_MEMORY_ARRAY_READ()` but the calling thread must +* :c:macro:`K_SYSCALL_MEMORY_ARRAY_WRITE()` is the same as + :c:macro:`K_SYSCALL_MEMORY_ARRAY_READ()` but the calling thread must additionally have write permissions. -* :c:macro:`Z_SYSCALL_VERIFY_MSG()` does a runtime check of some boolean +* :c:macro:`K_SYSCALL_VERIFY_MSG()` does a runtime check of some boolean expression which must evaluate to true otherwise the check will fail. - A variant :c:macro:`Z_SYSCALL_VERIFY` exists which does not take + A variant :c:macro:`K_SYSCALL_VERIFY` exists which does not take a message parameter, instead printing the expression tested if it fails. The latter should only be used for the most obvious of tests. -* :c:macro:`Z_SYSCALL_DRIVER_OP()` checks at runtime if a driver +* :c:macro:`K_SYSCALL_DRIVER_OP()` checks at runtime if a driver instance is capable of performing a particular operation. While this macro can be used by itself, it's mostly a building block for macros that are automatically generated for every driver subsystem. For instance, to validate the GPIO driver, one could use the - :c:macro:`Z_SYSCALL_DRIVER_GPIO()` macro. + :c:macro:`K_SYSCALL_DRIVER_GPIO()` macro. -* :c:macro:`Z_SYSCALL_SPECIFIC_DRIVER()` is a runtime check to verify that +* :c:macro:`K_SYSCALL_SPECIFIC_DRIVER()` is a runtime check to verify that a provided pointer is a valid instance of a specific device driver, that the calling thread has permissions on it, and that the driver has been initialized. It does this by checking the API structure pointer that @@ -331,7 +331,7 @@ Several macros exist to validate arguments: API structure. If any check fails, the macros will return a nonzero value. The macro -:c:macro:`Z_OOPS()` can be used to induce a kernel oops which will kill the +:c:macro:`K_OOPS()` can be used to induce a kernel oops which will kill the calling thread. This is done instead of returning some error condition to keep the APIs the same when calling from supervisor mode. @@ -357,7 +357,7 @@ For example: static int z_vrfy_k_sem_take(struct k_sem *sem, int32_t timeout) { - Z_OOPS(Z_SYSCALL_OBJ(sem, K_OBJ_SEM)); + K_OOPS(K_SYSCALL_OBJ(sem, K_OBJ_SEM)); return z_impl_k_sem_take(sem, timeout); } #include @@ -377,7 +377,7 @@ The proper procedure to mitigate these attacks is to make a copies in the verification function, and only perform parameter checks on the copies, which user threads will never have access to. The implementation functions get passed the copy and not the original data sent by the user. The -:c:func:`z_user_to_copy()` and :c:func:`z_user_from_copy()` APIs exist for +:c:func:`k_usermode_to_copy()` and :c:func:`k_usermode_from_copy()` APIs exist for this purpose. There is one exception in place, with respect to large data buffers which are @@ -397,12 +397,12 @@ for some integral value: int ret; ret = z_impl_some_syscall(&local_out_param); - Z_OOPS(z_user_to_copy(out_param, &local_out_param, sizeof(*out_param))); + K_OOPS(k_usermode_to_copy(out_param, &local_out_param, sizeof(*out_param))); return ret; } Here we have allocated ``local_out_param`` on the stack, passed its address to -the implementation function, and then used :c:func:`z_user_to_copy()` to fill +the implementation function, and then used :c:func:`k_usermode_to_copy()` to fill in the memory passed in by the caller. It might be tempting to do something more concise: @@ -411,7 +411,7 @@ It might be tempting to do something more concise: int z_vrfy_some_syscall(int *out_param) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(out_param, sizeof(*out_param))); + K_OOPS(K_SYSCALL_MEMORY_WRITE(out_param, sizeof(*out_param))); return z_impl_some_syscall(out_param); } @@ -433,9 +433,9 @@ bytes processed. This too should use a stack copy: size_t size; int ret; - Z_OOPS(z_user_from_copy(&size, size_ptr, sizeof(size)); + K_OOPS(k_usermode_from_copy(&size, size_ptr, sizeof(size)); ret = z_impl_in_out_syscall(&size); - Z_OOPS(z_user_to_copy(size_ptr, &size, sizeof(size))); + K_OOPS(k_usermode_to_copy(size_ptr, &size, sizeof(size))); return ret; } @@ -461,11 +461,11 @@ be copied. Typically this is done by allocating copies on the stack: struct bar bar_right_copy; struct bar bar_left_copy; - Z_OOPS(z_user_from_copy(&foo_copy, foo, sizeof(*foo))); - Z_OOPS(z_user_from_copy(&bar_right_copy, foo_copy.bar_right, + K_OOPS(k_usermode_from_copy(&foo_copy, foo, sizeof(*foo))); + K_OOPS(k_usermode_from_copy(&bar_right_copy, foo_copy.bar_right, sizeof(struct bar))); foo_copy.bar_right = &bar_right_copy; - Z_OOPS(z_user_from_copy(&bar_left_copy, foo_copy.bar_left, + K_OOPS(k_usermode_from_copy(&bar_left_copy, foo_copy.bar_left, sizeof(struct bar))); foo_copy.bar_left = &bar_left_copy; @@ -478,7 +478,7 @@ memory from the caller's resource pool via :c:func:`z_thread_malloc()`. This should always be considered last resort. Functional safety programming guidelines heavily discourage usage of heap and the fact that a resource pool is used must be clearly documented. Any issues with allocation must be -reported, to a caller, with returning the ``-ENOMEM`` . The ``Z_OOPS()`` +reported, to a caller, with returning the ``-ENOMEM`` . The ``K_OOPS()`` should never be used to verify if resource allocation has been successful. .. code-block:: c @@ -500,7 +500,7 @@ should never be used to verify if resource allocation has been successful. size_t bar_list_bytes; /* Safely copy foo into foo_copy */ - Z_OOPS(z_user_from_copy(&foo_copy, foo, sizeof(*foo))); + K_OOPS(k_usermode_from_copy(&foo_copy, foo, sizeof(*foo))); /* Bounds check the count member, in the copy we made */ if (foo_copy.count > 32) { @@ -514,7 +514,7 @@ should never be used to verify if resource allocation has been successful. if (bar_list_copy == NULL) { return -ENOMEM; } - Z_OOPS(z_user_from_copy(bar_list_copy, foo_copy.bar_list, + K_OOPS(k_usermode_from_copy(bar_list_copy, foo_copy.bar_list, bar_list_bytes)); foo_copy.bar_list = bar_list_copy; @@ -528,7 +528,7 @@ should never be used to verify if resource allocation has been successful. Finally, we must consider large data buffers. These represent areas of user memory which either have data copied out of, or copied into. It is permitted to pass these pointers to the implementation function directly. The caller's -access to the buffer still must be validated with ``Z_SYSCALL_MEMORY`` APIs. +access to the buffer still must be validated with ``K_SYSCALL_MEMORY`` APIs. The following constraints need to be met: * If the buffer is used by the implementation function to write data, such @@ -549,7 +549,7 @@ The following constraints need to be met: int z_vrfy_get_data_from_kernel(void *buf, size_t size) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(buf, size)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(buf, size)); return z_impl_get_data_from_kernel(buf, size); } @@ -558,25 +558,25 @@ Verification Return Value Policies When verifying system calls, it's important to note which kinds of verification failures should propagate a return value to the caller, and which should -simply invoke :c:macro:`Z_OOPS()` which kills the calling thread. The current +simply invoke :c:macro:`K_OOPS()` which kills the calling thread. The current conventions are as follows: #. For system calls that are defined but not compiled, invocations of these missing system calls are routed to :c:func:`handler_no_syscall()` which - invokes :c:macro:`Z_OOPS()`. + invokes :c:macro:`K_OOPS()`. -#. Any invalid access to memory found by the set of ``Z_SYSCALL_MEMORY`` APIs, - :c:func:`z_user_from_copy()`, :c:func:`z_user_to_copy()` - should trigger a :c:macro:`Z_OOPS`. This happens when the caller doesn't have +#. Any invalid access to memory found by the set of ``K_SYSCALL_MEMORY`` APIs, + :c:func:`k_usermode_from_copy()`, :c:func:`k_usermode_to_copy()` + should trigger a :c:macro:`K_OOPS`. This happens when the caller doesn't have appropriate permissions on the memory buffer or some size calculation overflowed. #. Most system calls take kernel object pointers as an argument, checked either - with one of the ``Z_SYSCALL_OBJ`` functions, ``Z_SYSCALL_DRIVER_nnnnn``, or - manually using :c:func:`z_object_validate()`. These can fail for a variety + with one of the ``K_SYSCALL_OBJ`` functions, ``K_SYSCALL_DRIVER_nnnnn``, or + manually using :c:func:`k_object_validate()`. These can fail for a variety of reasons: missing driver API, bad kernel object pointer, wrong kernel object type, or improper initialization state. These issues should always - invoke :c:macro:`Z_OOPS()`. + invoke :c:macro:`K_OOPS()`. #. Any error resulting from a failed memory heap allocation, often from invoking :c:func:`z_thread_malloc()`, should propagate ``-ENOMEM`` to the @@ -594,7 +594,7 @@ conventions are as follows: be registered from user mode. APIs which simply install callbacks shall not be exposed as system calls. Some driver subsystem APIs may take optional function callback pointers. User mode verification functions for these APIs - must enforce that these are NULL and should invoke :c:macro:`Z_OOPS()` if + must enforce that these are NULL and should invoke :c:macro:`K_OOPS()` if not. #. Some parameter checks are enforced only from user mode. These should be @@ -608,14 +608,14 @@ There are some known exceptions to these policies currently in Zephyr: initialization bit pulls double-duty to indicate whether a thread is running, cleared upon exit. See #23030. -* :c:func:`k_thread_create()` invokes :c:macro:`Z_OOPS()` for parameter +* :c:func:`k_thread_create()` invokes :c:macro:`K_OOPS()` for parameter checks, due to a great deal of existing code ignoring the return value. This will also be addressed by #23030. -* :c:func:`k_thread_abort()` invokes :c:macro:`Z_OOPS()` if an essential +* :c:func:`k_thread_abort()` invokes :c:macro:`K_OOPS()` if an essential thread is aborted, as the function has no return value. -* Various system calls related to logging invoke :c:macro:`Z_OOPS()` +* Various system calls related to logging invoke :c:macro:`K_OOPS()` when bad parameters are passed in as they do not propagate errors. Configuration Options @@ -630,18 +630,18 @@ APIs **** Helper macros for creating system call verification functions are provided in -:zephyr_file:`include/zephyr/syscall_handler.h`: - -* :c:macro:`Z_SYSCALL_OBJ()` -* :c:macro:`Z_SYSCALL_OBJ_INIT()` -* :c:macro:`Z_SYSCALL_OBJ_NEVER_INIT()` -* :c:macro:`Z_OOPS()` -* :c:macro:`Z_SYSCALL_MEMORY_READ()` -* :c:macro:`Z_SYSCALL_MEMORY_WRITE()` -* :c:macro:`Z_SYSCALL_MEMORY_ARRAY_READ()` -* :c:macro:`Z_SYSCALL_MEMORY_ARRAY_WRITE()` -* :c:macro:`Z_SYSCALL_VERIFY_MSG()` -* :c:macro:`Z_SYSCALL_VERIFY` +:zephyr_file:`include/zephyr/internal/syscall_handler.h`: + +* :c:macro:`K_SYSCALL_OBJ()` +* :c:macro:`K_SYSCALL_OBJ_INIT()` +* :c:macro:`K_SYSCALL_OBJ_NEVER_INIT()` +* :c:macro:`K_OOPS()` +* :c:macro:`K_SYSCALL_MEMORY_READ()` +* :c:macro:`K_SYSCALL_MEMORY_WRITE()` +* :c:macro:`K_SYSCALL_MEMORY_ARRAY_READ()` +* :c:macro:`K_SYSCALL_MEMORY_ARRAY_WRITE()` +* :c:macro:`K_SYSCALL_VERIFY_MSG()` +* :c:macro:`K_SYSCALL_VERIFY` Functions for invoking system calls are defined in :zephyr_file:`include/zephyr/syscall.h`: diff --git a/doc/known-warnings.txt b/doc/known-warnings.txt index abe8e7eca13..35a0ed60b03 100644 --- a/doc/known-warnings.txt +++ b/doc/known-warnings.txt @@ -22,8 +22,3 @@ .*Duplicate C declaration.*\n.*'\.\. c:.*:: .*struct in_addr.*'.* .*Duplicate C declaration.*\n.*'\.\. c:.*:: .*struct in6_addr.*'.* .*Duplicate C declaration.*\n.*'\.\. c:.*:: .*struct net_if.*'.* - -# Clash with field of nested anonymous struct -.*Duplicate C declaration.*\n.*'\.\. c:member:: enum *bt_mesh_dfd_upload_phase bt_mesh_dfd_srv.phase'.* -.*Duplicate C declaration.*\n.*'\.\. c:member:: struct *bt_mesh_blob_xfer bt_mesh_dfu_cli.blob'.* -.*Duplicate C declaration.*\n.*'\.\. c:member:: struct *net_if *\* net_if_mcast_monitor.iface'. diff --git a/doc/project/dev_env_and_tools.rst b/doc/project/dev_env_and_tools.rst index 37356ec3232..8269e891d43 100644 --- a/doc/project/dev_env_and_tools.rst +++ b/doc/project/dev_env_and_tools.rst @@ -20,10 +20,11 @@ and linked to any relevant :ref:`bug or feature tracking issues` The Zephyr project uses GitHub for code reviews and Git tree management. When submitting a change or an enhancement to any Zephyr component, a developer -should use GitHub. GitHub automatically assigns a responsible reviewer on a -component basis, as defined in the :zephyr_file:`CODEOWNERS` file stored with the code -tree in the Zephyr project repository. A limited set of release managers are -allowed to merge a pull request into the main branch once reviews are complete. +should use GitHub. GitHub Actions automatically assigns a responsible reviewer +on a component basis, as defined in the :zephyr_file:`MAINTAINERS.yml` file +stored with the code tree in the Zephyr project repository. A limited set of +release managers are allowed to merge a pull request into the main branch once +reviews are complete. .. _review_time: diff --git a/doc/project/project_roles.rst b/doc/project/project_roles.rst index 95d38da438c..2d1a74b573f 100644 --- a/doc/project/project_roles.rst +++ b/doc/project/project_roles.rst @@ -67,9 +67,9 @@ template ` and the guidelines +of the project or in cases of disagreement, it is the responsibility of the +assignee to advance the review process and resolve any disagreements. + +Collaborator approval of pull requests are counted toward the minimum required +approvals needed to merge a PR. Other criteria for merging may apply. Maintainer ++++++++++ @@ -121,7 +128,8 @@ Contributors or Collaborators are promoted to the Maintainer role by adding the GitHub user name to one or more ``maintainers`` sections of the :ref:`maintainers_file` in the Zephyr repository. -Maintainer votes on pull requests can block or approve the pull request. +Maintainer approval of pull requests are counted toward the minimum +required approvals needed to merge a PR. Other criteria for merging may apply. Role Retirement ############### @@ -149,9 +157,11 @@ Assignees are set either automatically based on the code being changed or set by the other Maintainers, the Release Engineering team can set an assignee when the latter is not possible. -* Right to dismiss stale reviews and seek reviews from additional maintainers, - developers and contributors -* Right to block pull requests from being merged +* Right to dismiss stale and unrelated reviews or reviews not following + :ref:`expectations ` from reviewers and seek reviews + from additional maintainers, developers and contributors +* Right to block pull requests from being merged until issues or changes + requested are addressed * Responsibility to re-assign a pull request if they are the original submitter of the code * Responsibility to drive the pull request to a mergeable state @@ -271,7 +281,7 @@ Generic guidelines for deciding and filling in the Maintainers' list * Pull requests may be re-assigned if this is needed or more appropriate - * Re-assigned by original assignee (see “Assignee” slide) + * Re-assigned by original assignee * In general, updates to the MAINTAINERS file should be in a standalone commit alongside other changes introducing new files and @@ -314,7 +324,40 @@ Release Activity Merge Criteria ++++++++++++++ -* All continuous integration checks have passed +* Minimal of 2 approvals, including an approval by the designated assignee. +* Pull requests should be reviewed by at least a maintainer or collaborator of + each affected area; Unless the changes to a given area are considered trivial + enough, in which case approvals by other affected subsystems + maintainers/collaborators would suffice. +* Four eye principle on the organisation level. We already require at least 2 + approvals (basic four eye principle), however, such reviews and approvals + might be unintentionally biased in the case where the submitter is from the + same organisation as the approvers. To allow for project wide review and + approvals, the merge criteria is extended with the guidelines below: + + * Changes or additions to common and shared code shall have approvals from + different organisations (at least one approval from an + organisation different than the submitters'). + Common and shared code is defined as anything that does not fall under + :file:`soc`, :file:`boards` and :file:`drivers/*/*`. + * Changes or additions to hardware support (driver, SoC, boards) shall at + least have the merger be from a different organisation. This applies only + to implementation of an API supporting vendor specific hardware and not the + APIs. + * Release engineers may make exceptions for areas with contributions primarily + coming from one organisation and where reviews from other organisations are + not possible, however, merges shall be completed by a person from a different + organisation. In such cases, the minimum review period of at least 2 days + shall be strictly followed to allow for additional reviews. + * Release engineers shall not merge code changes originating and reviewed + only by their own organisation. To be able to merge such changes, at least + one review shall be from a different organisation. + +* A minimum review period of 2 business days, 4 hours for trivial changes (see + :ref:`review_time`). +* Hotfixes can be merged at any time after CI has passed and are excluded from + most of the conditions listed above. +* All required checks are passing: * Codeowners * Device Tree @@ -322,7 +365,7 @@ Merge Criteria * Gitlint * Identity/Emails * Kconfig - * License + * License checks * Checkpatch (Coding Style) * Pylint * Integration Tests (Via twister) on emulation/simulation platforms @@ -335,15 +378,3 @@ Merge Criteria * Coding Guidelines * Static Analysis (Coverity) * Documentation coverage (APIs) - -* PR template with checklist - -* Minimal of 2 approvals - - * A collaborator from the same subsystem. - * Alternately another maintainer of another subsystem - * Approval by the assignee - -* A minimum review period of 2 days, 4 hours for trivial changes (see - :ref:`review_time`). Hotfixes can be merged at any time after CI passes. -* All required checks are passing diff --git a/doc/project/release_process.rst b/doc/project/release_process.rst index 5ffb189dbf1..e1e07c417c8 100644 --- a/doc/project/release_process.rst +++ b/doc/project/release_process.rst @@ -45,6 +45,12 @@ The Zephyr release model was loosely based on the Linux kernel model: Release Cycle +.. note:: + + The milestones for the current major version can be found on the + `Official GitHub Wiki `_. + Information on previous releases can be found :ref:`here `. + Development Phase ***************** diff --git a/doc/releases/eol_releases.rst b/doc/releases/eol_releases.rst new file mode 100644 index 00000000000..22900a55e44 --- /dev/null +++ b/doc/releases/eol_releases.rst @@ -0,0 +1,14 @@ +End-of-life releases +==================== + +Release notes for end-of-life releases of Zephyr RTOS are kept here for historical purposes. + +.. toctree:: + :maxdepth: 1 + :glob: + :reversed: + + release-notes-1.? + release-notes-1.* + release-notes-2.[0-6] + release-notes-3.[0-2] diff --git a/doc/releases/index.rst b/doc/releases/index.rst index 48855b65fae..7a3540d227d 100644 --- a/doc/releases/index.rst +++ b/doc/releases/index.rst @@ -3,11 +3,17 @@ Releases ######## -Zephyr project is provided as source code and build scripts for different -target architectures and configurations, and not as a binary image. Updated -versions of the Zephyr project are released approximately every four months. +Zephyr project is provided as source code and build scripts for different target +architectures and configurations, and not as a binary image. Updated versions of +the Zephyr project are released approximately every four months. -All Zephyr project source code is maintained in a `GitHub repository`_. +All Zephyr project source code is maintained in a `GitHub repository`_. In order +to use a released version of the Zephyr project, it is recommended that you use +:ref:`west` to :ref:`get_the_code` of the release you are interested in. + +The technical documentation for current and past releases is available at +https://docs.zephyrproject.org/ (use the version selector to select your release +of interest). Release Life Cycle and Maintenance ********************************** @@ -52,9 +58,9 @@ Supported Releases +=================+================+===============+ | `Zephyr 2.7.5`_ | 2023-06-01 | 2024-08-31 | +-----------------+----------------+---------------+ -| `Zephyr 3.4.0`_ | 2023-06-16 | 2024-02-29 | +| `Zephyr 3.5.0`_ | 2023-10-20 | 2024-07-26 | +-----------------+----------------+---------------+ -| `Zephyr 3.3.0`_ | 2023-02-19 | 2023-10-31 | +| `Zephyr 3.4.0`_ | 2023-06-16 | 2024-02-29 | +-----------------+----------------+---------------+ As of 2022-01-01, LTS1 (1.14.x) is not supported and has reached end of life (EOL). @@ -62,32 +68,14 @@ As of 2022-01-01, LTS1 (1.14.x) is not supported and has reached end of life (EO Release Notes ************* -For Zephyr versions up to 1.13, you can either download source as a tar.gz file -(see the bottom of the `GitHub tagged releases`_ page corresponding to each -release), or clone the GitHub repository. - -With the introduction of the :ref:`west` tool after the release of Zephyr 1.13, -it is no longer recommended to download or clone the source code manually. -Instead we recommend you follow the instructions in :ref:`get_the_code` to do -so with the help of west. - -The project's technical documentation is also tagged to correspond with a -specific release and can be found at https://docs.zephyrproject.org/. - -.. comment We need to split the globbing of release notes to get the - single-digit and double-digit subversions sorted correctly. Specify - names in normal order and use the :reversed: option to reverse it. - This will get us through 10 subversions (0-9) before we need to - update this list for two-digit subversions again. - .. toctree:: :maxdepth: 1 :glob: :reversed: - release-notes-1.? - release-notes-1.* - release-notes-* + eol_releases + release-notes-2.7 + release-notes-3.[3-6] Migration Guides **************** @@ -105,5 +93,5 @@ users transition from the previous release. .. _`GitHub repository`: https://github.com/zephyrproject-rtos/zephyr .. _`GitHub tagged releases`: https://github.com/zephyrproject-rtos/zephyr/tags .. _`Zephyr 2.7.5`: https://docs.zephyrproject.org/2.7.5/ -.. _`Zephyr 3.3.0`: https://docs.zephyrproject.org/3.3.0/ .. _`Zephyr 3.4.0`: https://docs.zephyrproject.org/3.4.0/ +.. _`Zephyr 3.5.0`: https://docs.zephyrproject.org/3.5.0/ diff --git a/doc/releases/migration-guide-3.5.rst b/doc/releases/migration-guide-3.5.rst index 8c059b630c6..cda3602f19f 100644 --- a/doc/releases/migration-guide-3.5.rst +++ b/doc/releases/migration-guide-3.5.rst @@ -2,15 +2,21 @@ .. _migration_3.5: -Migration guide to Zephyr v3.5.0 (Working Draft) -################################################ +Migration guide to Zephyr v3.5.0 +################################ This document describes the changes required or recommended when migrating your application from Zephyr v3.4.0 to Zephyr v3.5.0. +Any other changes (not directly related to migrating applications) can be found in +the :ref:`release notes`. + Required changes **************** +Kernel +====== + * The kernel :c:func:`k_mem_slab_free` function has changed its signature, now taking a ``void *mem`` pointer instead of a ``void **mem`` double-pointer. The new signature will not immediately trigger a compiler error or warning, @@ -19,12 +25,318 @@ Required changes detect if you pass the function memory not belonging to the memory blocks in the slab. +* :c:macro:`CONTAINER_OF` now performs type checking, this was very commonly + misused to obtain user structure from :c:struct:`k_work` pointers without + passing from :c:struct:`k_work_delayable`. This would now result in a build + error and have to be done correctly using + :c:func:`k_work_delayable_from_work`. + +C Library +========= + +* The default C library used on most targets has changed from the built-in + minimal C library to Picolibc. While both provide standard C library + interfaces and shouldn't cause any behavioral regressions for applications, + there are a few side effects to be aware of when migrating to Picolibc. + + * Picolibc enables thread local storage + (:kconfig:option:`CONFIG_THREAD_LOCAL_STORAGE`) where supported. This + changes some internal operations within the kernel that improve + performance using some TLS variables. Zephyr places TLS variables in the + memory reserved for the stack, so stack usage for every thread will + increase by 8-16 bytes. + + * Picolibc uses the same malloc implementation as the minimal C library, but + the default heap size depends on which C library is in use. When using the + minimal C library, the default heap is zero bytes, which means that malloc + will always fail. When using Picolibc, the default is 16kB with + :kconfig:option:`CONFIG_MMU` or :kconfig:option:`ARCH_POSIX`, 2kB with + :kconfig:option:`CONFIG_USERSPACE` and + :kconfig:option:`CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT`. For all + other targets, the default heap uses all remaining memory on the system. + You can change this by adjusting + :kconfig:option:`CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE`. + + * Picolibc can either be built as part of the OS build or pulled from the + toolchain. When building as part of the OS, the build will increase by + approximately 1000 files. + + * When using the standard C++ library with Picolibc, both of those must come + from the toolchain as the standard C++ library depends upon the C library + ABI. + + * Picolibc removes the ``-ffreestanding`` compiler option. This allows + significant compiler optimization improvements, but also means that the + compiler will now warn about declarations of `main` which don't conform to + the Zephyr required type -- ``int main(void)``. + + * Picolibc has four different printf/scanf variants supported in Zephyr, + 'double', 'long long', 'integer', and 'minimal. 'double' offers a + complete printf implementation with exact floating point in decimal and + hexidecimal formats, full integer support including long long, C99 + integer size specifiers (j, z, t) and POSIX positional arguments. 'long + long' mode removes float support, 'integer' removes long long support + while 'minimal' mode also removes support for format modifiers and + positional arguments. Building the library as a module allows finer + control over the feature set provided at each level. + + * Picolibc's default floating point input/output code is larger than the + minimal C library version (this is necessary to conform with the C + language "round trip" requirements for these operations). If you use + :kconfig:option:`CONFIG_CBPRINTF_FP_SUPPORT`, you will see increased + memory usage unless you also disable + :kconfig:option:`CONFIG_PICOLIBC_IO_FLOAT_EXACT`, which switches Picolibc + to a smaller, but inexact conversion algorithm. This requires building + Picolibc as a module. + +Optional Modules +================ + +The following modules have been made optional and are not downloaded with `west update` by default anymore: + +* ``chre`` +* ``lz4`` +* ``nanopb`` +* ``psa-arch-tests`` +* ``sof`` +* ``tf-m-tests`` +* ``tflite-micro`` +* ``thrift`` +* ``zscilib`` + +To enable them again use the ``west config manifest.project-filter -- +`` command, or ``west config manifest.group-filter -- +optional`` to +enable all optional modules, and then run ``west update`` again. + +Device Drivers and Device Tree +============================== + +* ``zephyr,memory-region-mpu`` was renamed ``zephyr,memory-attr`` and its type + moved from 'enum' to 'int'. To have a seamless conversion this is the + required change in the DT: + + .. code-block:: none + + - "RAM" -> <( DT_MEM_ARM(ATTR_MPU_RAM) )> + - "RAM_NOCACHE" -> <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) )> + - "FLASH" -> <( DT_MEM_ARM(ATTR_MPU_FLASH) )> + - "PPB" -> <( DT_MEM_ARM(ATTR_MPU_PPB) )> + - "IO" -> <( DT_MEM_ARM(ATTR_MPU_IO) )> + - "EXTMEM" -> <( DT_MEM_ARM(ATTR_MPU_EXTMEM) )> + +* Device dependencies (incorrectly referred as "device handles" in some areas) + are now an optional feature enabled by :kconfig:option:`CONFIG_DEVICE_DEPS`. + This means that an extra linker stage is no longer necessary if this option is + not enabled. + +* On all STM32 ADC, it is no longer possible to read sensor channels (Vref, + Vbat or temperature) using the ADC driver. The dedicated sensor driver should + be used instead. This change is due to a limitation on STM32F4 where the + channels for temperature and Vbat are identical, and the impossibility of + determining what we want to measure using solely the ADC API. + +* The RAM disk driver has been changed to support multiple instances and instantiation + using devicetree. As a result, Kconfig option :kconfig:option:`CONFIG_DISK_RAM_VOLUME_SIZE` + and Kconfig option :kconfig:option:`CONFIG_DISK_RAM_VOLUME_NAME` are removed, + and the application using the RAM disk must instantiate it using devicetree, + as in the following example: + + .. code-block:: devicetree + + / { + ramdisk0 { + compatible = "zephyr,ram-disk"; + disk-name = "RAM"; + sector-size = <512>; + sector-count = <192>; + }; + }; + +* The :dtcompatible:`goodix,gt911`, :dtcompatible:`xptek,xpt2046` and + :dtcompatible:`hynitron,cst816s` drivers have been converted from Kscan to + Input, they can still be used with Kscan applications by adding a + :dtcompatible:`zephyr,kscan-input` node. + +* The ``zephyr,gpio-keys`` binding has been merged into + :dtcompatible:`gpio-keys` and the callback definition has been renamed from + ``INPUT_LISTENER_CB_DEFINE`` to :c:macro:`INPUT_CALLBACK_DEFINE`. + +* The :dtcompatible:`ti,bq274xx` driver was using incorrect units for capacity + and power channels, these have been fixed and scaled by x1000 factor from the + previous implementation, any application using them has to be changed + accordingly. + +* The configuration options for the SSD1306 display driver can now be provided + via the Devicetree binding :dtcompatible:`solomon,ssd1306fb`. The following + Kconfig options: ``CONFIG_SSD1306_DEFAULT``, + ``CONFIG_SSD1306_SH1106_COMPATIBLE``, and ``CONFIG_SSD1306_REVERSE_MODE`` have + been removed. + + * You can remove ``CONFIG_SSD1306_DEFAULT`` without any other modification. + + * ``CONFIG_SSD1306_SH1106_COMPATIBLE`` was used to assert that the device is + (compatible with) SH1106. This has been replaced by a dedicated dts + compatible declaration. You may update an existing sh1106 node to change the + ``compatible`` designation from :dtcompatible:`solomon,ssd1306fb` to + :dtcompatible:`sinowealth,sh1106`. + + * ``CONFIG_SSD1306_REVERSE_MODE`` is now set using the ``inversion-on`` + property of the devicetree node. + +* GPIO drivers not implementing IRQ related operations must now provide + ``NULL`` to the relevant operations: ``pin_interrupt_configure``, + ``manage_callback``, ``get_pending_int``. The public API will return + ``-ENOSYS`` when these are not available, instead of ``-ENOTSUP``. + +* STM32 Ethernet driver was misusing :c:func:`hwinfo_get_device_id` to generate + last 3 bytes of mac address, resulting in a high risk of collision when using + SoCs from the same lot. This is now fixed to use the whole range of entropy + available from the unique ID (96 bits). Devices using unique ID based mac address + will see last 3 bytes of their MAC address modified by this change. + +* On all STM32 (except F1x and F37x series), two new required properties have been + added to ADC to configure the source clock and the prescaler. + ``st,adc-clock-source`` allows choosing either synchronous or asynchronous clock source. + ``st,adc-prescaler`` allows setting the value of the prescaler for the chosen clock source. + Not all combinations are allowed. Refer to the appropriate RefMan for more information. + When choosing asynchronous clock, the choice of the kernel source clock is made in the + ``clocks`` node as it is done for other peripherals, for example, to select + HSI16 as clock source for STM32G0: + + .. code-block:: devicetree + + &adc { + clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00100000>, + <&rcc STM32_SRC_HSI ADC_SEL(2)>; + }; + +* On NXP boards with LPC DMA, the DMA controller node used to have its ``dma-channels`` property + set in the board DTS as a way to configure the amount of structures the driver will allocate. + This did not match the zephyr dma-controller binding, so this property is now fixed and set + in the SOC devicetree definition. Downstream boards should not override this property and + instead use the new driver Kconfig + :kconfig:option:`CONFIG_DMA_MCUX_LPC_NUMBER_OF_CHANNELS_ALLOCATED`. + +* The LPC55XXX series SOC (except LPC55S06) default main clock has been + updated to PLL1 source from XTAL32K running at 144MHZ. If the new + kconfig option :kconfig:option:`CONFIG_INIT_PLL1` + is disabled then the main clock is muxed to FRO_HR as before. + +* The Kconfig option ``CONFIG_GPIO_NCT38XX_INTERRUPT`` has been renamed to + :kconfig:option:`CONFIG_GPIO_NCT38XX_ALERT`. + +* The CAN controller timing API functions :c:func:`can_set_timing` and :c:func:`can_set_timing_data` + no longer fallback to the (Re-)Synchronization Jump Width (SJW) value set in the devicetree + properties for the given CAN controller upon encountering an SJW value corresponding to + ``CAN_SJW_NO_CHANGE`` (which is no longer available). The caller will therefore need to fill in + the ``sjw`` field in :c:struct:`can_timing`. To aid in this, the :c:func:`can_calc_timing` and + :c:func:`can_calc_timing_data` functions now automatically calculate a suitable SJW. The + calculated SJW can be overwritten by the caller if needed. The CAN controller API functions + :c:func:`can_set_bitrate` and :c:func:`can_set_bitrate_data` now also automatically calculate a + suitable SJW, but their SJW cannot be overwritten by the caller. + +* The CAN ISO-TP message configuration in :c:struct:`isotp_msg_id` is changed to use the following + flags instead of bit fields: + + * :c:macro:`ISOTP_MSG_EXT_ADDR` to enable ISO-TP extended addressing + * :c:macro:`ISOTP_MSG_FIXED_ADDR` to enable ISO-TP fixed addressing + * :c:macro:`ISOTP_MSG_IDE` to use extended (29-bit) CAN IDs + + The two new flags :c:macro:`ISOTP_MSG_FDF` and :c:macro:`ISOTP_MSG_BRS` were added for CAN FD + mode. + +* NXP i.MX RT based boards should now enable + :kconfig:option:`CONFIG_DEVICE_CONFIGURATION_DATA` at the board level when + using a DCD with the RT bootrom, and enable + :kconfig:option:`CONFIG_NXP_IMX_EXTERNAL_SDRAM` when using external SDRAM + via the SEMC + +* NXP i.MX RT11xx series SNVS pin control name identifiers have been updated to + match with the source data for these SOCs. The pin names have had the + suffix ``dig`` added. For example, ``iomuxc_snvs_wakeup_gpio13_io00`` has + been renamed to ``iomuxc_snvs_wakeup_dig_gpio13_io00`` + +Power Management +================ + +* Platforms that implement power management hooks must explicitly select + :kconfig:option:`CONFIG_HAS_PM` in Kconfig. This is now a dependency of + :kconfig:option:`CONFIG_PM`. Before this change all platforms could enable + :kconfig:option:`CONFIG_PM` because empty weak stubs were provided, however, + this is no longer supported. As a result of this change, power management + hooks are no longer defined as weaks. + +* Multiple platforms no longer support powering the system off using + :c:func:`pm_state_force`. The new :c:func:`sys_poweroff` API must be used. + Migrated platforms include Nordic nRF, STM32, ESP32 and TI CC13XX/26XX. The + new API is independent from :kconfig:option:`CONFIG_PM`. It requires + :kconfig:option:`CONFIG_POWEROFF` to be enabled, which depends on + :kconfig:option:`CONFIG_HAS_POWEROFF`, an option selected by platforms + implementing the required new hooks. + +Bootloader +========== + * The :kconfig:option:`CONFIG_BOOTLOADER_SRAM_SIZE` default value is now ``0`` (was ``16``). Bootloaders that use a part of the SRAM should set this value to an appropriate size. :github:`60371` -* The Kconfig option ``CONFIG_GPIO_NCT38XX_INTERRUPT`` has been renamed to - :kconfig:option:`CONFIG_GPIO_NCT38XX_ALERT`. +Bluetooth +========= + +* The ``accept()`` callback's signature in :c:struct:`bt_l2cap_server` has + changed to ``int (*accept)(struct bt_conn *conn, struct bt_l2cap_server + *server, struct bt_l2cap_chan **chan)``, + adding a new ``server`` parameter pointing to the :c:struct:`bt_l2cap_server` + structure instance the callback relates to. :github:`60536` + +Networking +========== + +* A new networking Kconfig option :kconfig:option:`CONFIG_NET_INTERFACE_NAME` + defaults to ``y``. The option allows user to set a name to a network interface. + During system startup a default name is assigned to the network interface like + ``eth0`` to the first Ethernet network interface. The option affects the behavior + of ``SO_BINDTODEVICE`` BSD socket option. If the Kconfig option is set to ``n``, + which is how the system worked earlier, then the name of the device assigned + to the network interface is used by the ``SO_BINDTODEVICE`` socket option. + If the Kconfig option is set to ``y`` (current default), then the network + interface name is used by the ``SO_BINDTODEVICE`` socket option. + +* Ethernet PHY devicetree bindings were updated to use the standard ``reg`` + property for the PHY address instead of a custom ``address`` property. As a + result, MDIO controller nodes now require ``#address-cells`` and + ``#size-cells`` properties. Similarly, Ethernet PHY devicetree nodes and + corresponding driver were updated to consistently use the node name + ``ethernet-phy`` instead of ``phy``. Devicetrees and overlays must be updated + accordingly: + + .. code-block:: devicetree + + mdio { + compatible = "mdio-controller"; + #address-cells = <1>; + #size-cells = <0>; + + ethernet-phy@0 { + compatible = "ethernet-phy"; + reg = <0>; + }; + }; + +Other Subsystems +================ + +* ZBus runtime observers implementation now relies on the HEAP memory instead of a memory slab. + Thus, zbus' configuration (kconfig) related to runtime observers has changed. To keep your runtime + observers code working correctly, you need to: + + - Replace the integer ``CONFIG_ZBUS_RUNTIME_OBSERVERS_POOL_SIZE`` with the boolean + :kconfig:option:`CONFIG_ZBUS_RUNTIME_OBSERVERS`; + - Set the HEAP size with the :kconfig:option:`CONFIG_HEAP_MEM_POOL_SIZE`. + +* The zbus VDED delivery sequence has changed. Check the :ref:`documentation` to verify if it will affect your code. * MCUmgr SMP version 2 error codes entry has changed due to a collision with an existing response in shell_mgmt. Previously, these errors had the entry ``ret`` @@ -34,6 +346,25 @@ Required changes SMP version 2 error code defines for in-tree modules have been updated to replace the ``*_RET_RC_*`` parts with ``*_ERR_*``. +* MCUmgr SMP version 2 error translation (to legacy MCUmgr error code) is now + handled in function handlers by setting the ``mg_translate_error`` function + pointer of :c:struct:`mgmt_group` when registering a group. See + :c:type:`smp_translate_error_fn` for function details. Any SMP version 2 + handlers made for Zephyr 3.4 need to be updated to include these translation + functions when the groups are registered. + +ARM +=== + +* ARM SoC initialization routines no longer need to call `NMI_INIT()`. The + macro call has been removed as it was not doing anything useful. + +RISC V +====== + +* The :kconfig:option:`CONFIG_RISCV_MTVEC_VECTORED_MODE` Kconfig option was renamed to + :kconfig:option:`CONFIG_RISCV_VECTORED_MODE`. + Recommended Changes ******************* @@ -64,3 +395,38 @@ Recommended Changes &uicr { gpio-as-nreset; }; + +* The :kconfig:option:`CONFIG_MODEM_GSM_PPP` modem driver is obsolete. + Instead the new :kconfig:option:`CONFIG_MODEM_CELLULAR` driver should be used. + As part of this :kconfig:option:`CONFIG_GSM_MUX` and :kconfig:option:`CONFIG_UART_MUX` are being + marked as deprecated as well. The new modem subsystem :kconfig:option:`CONFIG_MODEM_CMUX` + and :kconfig:option:`CONFIG_MODEM_PPP` should be used instead. + +* Device drivers should now be restricted to ``PRE_KERNEL_1``, ``PRE_KERNEL_2`` + and ``POST_KERNEL`` initialization levels. Other device initialization levels, + including ``EARLY``, ``APPLICATION``, and ``SMP``, have been deprecated and + will be removed in future releases. Note that these changes do not apply to + initialization levels used in the context of the ``init.h`` API, + e.g. :c:macro:`SYS_INIT`. + +* The following CAN controller devicetree properties are now deprecated in favor specifying the + initial CAN bitrate using the ``bus-speed``, ``sample-point``, ``bus-speed-data``, and + ``sample-point-data`` properties: + + * ``sjw`` + * ``prop-seg`` + * ``phase-seg1`` + * ``phase-seg1`` + * ``sjw-data`` + * ``prop-seg-data`` + * ``phase-seg1-data`` + * ``phase-seg1-data`` + +* ```` and + ```` are now deprecated in favor of + including ```` instead. The new header is part of the CMSIS glue + code in the ``modules`` directory. + +* Random API header ```` is deprecated in favor of + ````. The old header will be removed in future releases + and its usage should be avoided. diff --git a/doc/releases/migration-guide-3.6.rst b/doc/releases/migration-guide-3.6.rst new file mode 100644 index 00000000000..c4b93e5f150 --- /dev/null +++ b/doc/releases/migration-guide-3.6.rst @@ -0,0 +1,159 @@ +:orphan: + +.. _migration_3.6: + +Migration guide to Zephyr v3.6.0 (Working Draft) +################################################ + +This document describes the changes required or recommended when migrating your +application from Zephyr v3.5.0 to Zephyr v3.6.0. + +Any other changes (not directly related to migrating applications) can be found in +the :ref:`release notes`. + +Required changes +**************** + +Kernel +====== + +C Library +========= + +Optional Modules +================ + +The following modules have been made optional and are not downloaded with `west update` by default +anymore: + +* ``canopennode`` (:github:`64139`) + +To enable them again use the ``west config manifest.project-filter -- +`` command, or ``west config manifest.group-filter -- +optional`` to +enable all optional modules, and then run ``west update`` again. + +Device Drivers and Device Tree +============================== + +* The :dtcompatible:`st,lsm6dsv16x` sensor driver has been changed to support + configuration of both int1 and int2 pins. The DT attribute ``irq-gpios`` has been + removed and substituted by two new attributes, ``int1-gpios`` and ``int2-gpios``. + These attributes must be configured in the Device Tree similarly to the following + example: + + .. code-block:: devicetree + + / { + lsm6dsv16x@0 { + compatible = "st,lsm6dsv16x"; + + int1-gpios = <&gpioa 4 GPIO_ACTIVE_HIGH>; + int2-gpios = <&gpiod 11 GPIO_ACTIVE_HIGH>; + drdy-pin = <2>; + }; + }; + + (:github:`62994`) + +Power Management +================ + +Shell +===== + +* The following subsystem and driver shell modules are now disabled by default. Each required shell + module must now be explicitly enabled via Kconfig (:github:`65307`): + + * :kconfig:option:`CONFIG_ACPI_SHELL` + * :kconfig:option:`CONFIG_ADC_SHELL` + * :kconfig:option:`CONFIG_AUDIO_CODEC_SHELL` + * :kconfig:option:`CONFIG_CAN_SHELL` + * :kconfig:option:`CONFIG_CLOCK_CONTROL_NRF_SHELL` + * :kconfig:option:`CONFIG_DAC_SHELL` + * :kconfig:option:`CONFIG_DEBUG_COREDUMP_SHELL` + * :kconfig:option:`CONFIG_EDAC_SHELL` + * :kconfig:option:`CONFIG_EEPROM_SHELL` + * :kconfig:option:`CONFIG_FLASH_SHELL` + * :kconfig:option:`CONFIG_HWINFO_SHELL` + * :kconfig:option:`CONFIG_I2C_SHELL` + * :kconfig:option:`CONFIG_LOG_CMDS` + * :kconfig:option:`CONFIG_LORA_SHELL` + * :kconfig:option:`CONFIG_MCUBOOT_SHELL` + * :kconfig:option:`CONFIG_MDIO_SHELL` + * :kconfig:option:`CONFIG_OPENTHREAD_SHELL` + * :kconfig:option:`CONFIG_PCIE_SHELL` + * :kconfig:option:`CONFIG_PSCI_SHELL` + * :kconfig:option:`CONFIG_PWM_SHELL` + * :kconfig:option:`CONFIG_REGULATOR_SHELL` + * :kconfig:option:`CONFIG_SENSOR_SHELL` + * :kconfig:option:`CONFIG_SMBUS_SHELL` + * :kconfig:option:`CONFIG_STATS_SHELL` + * :kconfig:option:`CONFIG_USBD_SHELL` + * :kconfig:option:`CONFIG_USBH_SHELL` + * :kconfig:option:`CONFIG_W1_SHELL` + * :kconfig:option:`CONFIG_WDT_SHELL` + +Bootloader +========== + +* MCUboot's deprecated ``CONFIG_ZEPHYR_TRY_MASS_ERASE`` Kconfig option has been removed. If an + erase is needed when flashing MCUboot, this should now be provided directly to the ``west`` + command e.g. ``west flash --erase``. (:github:`64703`) + +Bluetooth +========= + +* The HCI implementation for both the Host and the Controller sides has been + renamed for the IPC transport. The ``CONFIG_BT_RPMSG`` Kconfig option is now + :kconfig:option:`CONFIG_BT_HCI_IPC`, and the ``zephyr,bt-hci-rpmsg-ipc`` + Devicetree chosen is now ``zephyr,bt-hci-ipc``. The existing sample has also + been renamed, from ``samples/bluetooth/hci_rpmsg`` to + ``samples/bluetooth/hci_ipc``. (:github:`64391`) +* The BT GATT callback list, appended to by :c:func:`bt_gatt_cb_register`, is no longer + cleared on :c:func:`bt_enable`. Callbacks can now be registered before the initial + call to :c:func:`bt_enable`, and should no longer be re-registered after a :c:func:`bt_disable` + :c:func:`bt_enable` cycle. (:github:`63693`) +* The Bluetooth Mesh ``model`` declaration has been changed to add prefix ``const``. + The ``model->user_data``, ``model->elem_idx`` and ``model->mod_idx`` field has been changed to + the new runtime structure, replaced by ``model->rt->user_data``, ``model->rt->elem_idx`` and + ``model->rt->mod_idx`` separately. (:github:`65152`) +* The Bluetooth Mesh ``element`` declaration has been changed to add prefix ``const``. + The ``elem->addr`` field has been changed to the new runtime structure, replaced by + ``elem->rt->addr``. (:github:`65388`) + +LoRaWAN +======= + +* The API to register a callback to provide battery level information to the LoRaWAN stack has been + renamed from ``lorawan_set_battery_level_callback`` to + :c:func:`lorawan_register_battery_level_callback` and the return type is now ``void``. This + is more consistent with similar functions for downlink and data rate changed callbacks. + (:github:`65103`) + +Networking +========== + +* The CoAP public API has some minor changes to take into account. The + :c:func:`coap_remove_observer` now returns a result if the observer was removed. This + change is used by the newly introduced :ref:`coap_server_interface` subsystem. Also, the + ``request`` argument for :c:func:`coap_well_known_core_get` is made ``const``. + (:github:`64265`) + +Other Subsystems +================ + +* MCUmgr applications that make use of serial transports (shell or UART) must now select + :kconfig:option:`CONFIG_CRC`, this was previously erroneously selected if MCUmgr was enabled, + when for non-serial transports it was not needed. (:github:`64078`) + +* Touchscreen drivers :dtcompatible:`focaltech,ft5336` and + :dtcompatible:`goodix,gt911` were using the incorrect polarity for the + respective ``reset-gpios``. This has been fixed so those signals now have to + be flagged as :c:macro:`GPIO_ACTIVE_LOW` in the devicetree. (:github:`64800`) + +Recommended Changes +******************* + +* New macros available for ST sensor DT properties setting. These macros have a self-explanatory + name that helps in recognizing what the property setting means (e.g. LSM6DSV16X_DT_ODR_AT_60Hz). + (:github:`65410`) diff --git a/doc/releases/release-notes-1.14.rst b/doc/releases/release-notes-1.14.rst index d7d14a8499e..45ed7625890 100644 --- a/doc/releases/release-notes-1.14.rst +++ b/doc/releases/release-notes-1.14.rst @@ -858,11 +858,11 @@ Networking * Added support for SOCKS5 proxy in MQTT client. * Added support for IPSO Timer object in LWM2M. * Added support for receiving gratuitous ARP request. -* Added :ref:`sample application ` for Google IoT Cloud. +* Added sample application for Google IoT Cloud. * :ref:`Network interface ` numbering starts now from 1 for POSIX compatibility. * :ref:`OpenThread ` enhancements. -* :ref:`zperf ` sample application fixes. +* :zephyr:code-sample:`zperf ` sample application fixes. * :ref:`LLDP ` (Link Layer Discovery Protocol) enhancements. * ARP cache update fix. * gPTP link delay calculation fixes. diff --git a/doc/releases/release-notes-3.2.rst b/doc/releases/release-notes-3.2.rst index e9e4bd647db..d902ac4481b 100644 --- a/doc/releases/release-notes-3.2.rst +++ b/doc/releases/release-notes-3.2.rst @@ -335,7 +335,7 @@ Bluetooth payload updates with the Resolvable Private Address (RPA) rotations when the :kconfig:option:`CONFIG_BT_PRIVACY` is enabled. * Added a new :c:func:`bt_le_set_rpa_timeout()` API call to dynamically change - the the Resolvable Private Address (RPA) timeout when the + the Resolvable Private Address (RPA) timeout when the :kconfig:option:`CONFIG_BT_RPA_TIMEOUT_DYNAMIC` is enabled. * Added :c:func:`bt_conn_auth_cb_overlay` to overlay authentication callbacks for a Bluetooth LE connection. diff --git a/doc/releases/release-notes-3.3.rst b/doc/releases/release-notes-3.3.rst index d4b438999e2..312ad1e4754 100644 --- a/doc/releases/release-notes-3.3.rst +++ b/doc/releases/release-notes-3.3.rst @@ -811,7 +811,7 @@ Drivers and Sensors * Added new API :c:func:`pcie_scan` to scan for devices. - * This iterates through the the buses and devices which are expected to + * This iterates through the buses and devices which are expected to exist. The old method was to try all possible combination of buses and devices to determine if there is a device there. :c:func:`pci_init` and :c:func:`pcie_bdf_lookup` have been updated to @@ -2496,13 +2496,13 @@ Libraries / Subsystems * Uses mutex to control channels access. * Added the following samples: - * :ref:`zbus-hello-world-sample` - * :ref:`zbus-work-queue-sample` - * :ref:`zbus-dyn-channel-sample` - * :ref:`zbus-uart-bridge-sample` - * :ref:`zbus-remote-mock-sample` - * :ref:`zbus-runtime-obs-registration-sample` - * :ref:`zbus-benchmark-sample` + * :zephyr:code-sample:`zbus-hello-world` + * :zephyr:code-sample:`zbus-work-queue` + * :zephyr:code-sample:`zbus-dyn-channel` + * :zephyr:code-sample:`zbus-uart-bridge` + * :zephyr:code-sample:`zbus-remote-mock` + * :zephyr:code-sample:`zbus-runtime-obs-registration` + * :zephyr:code-sample:`zbus-benchmark` * Added zbus channels APIs: diff --git a/doc/releases/release-notes-3.4.rst b/doc/releases/release-notes-3.4.rst index 0fb4efbe40f..092fa251c6f 100644 --- a/doc/releases/release-notes-3.4.rst +++ b/doc/releases/release-notes-3.4.rst @@ -1143,7 +1143,7 @@ Networking which allow to disable ND/MLD respectively on an interface. * Reworked network interface mutex protection, to use individual mutex for each interface, instead of a global one. - * Added new :ref:`aws-iot-mqtt-sample`. + * Added new :zephyr:code-sample:`aws-iot-mqtt`. * Added a few missing NULL pointer checks in network interface functions. * OpenThread: diff --git a/doc/releases/release-notes-3.5.rst b/doc/releases/release-notes-3.5.rst index 82d2698849b..d7993bd7804 100644 --- a/doc/releases/release-notes-3.5.rst +++ b/doc/releases/release-notes-3.5.rst @@ -2,48 +2,285 @@ .. _zephyr_3.5: -Zephyr 3.5.0 (Working Draft) -############################ +Zephyr 3.5.0 +############ We are pleased to announce the release of Zephyr version 3.5.0. Major enhancements with this release include: +* Added support for linkable loadable extensions (llext) +* Added native_sim simulator target (successor to native_posix) +* Added new battery charger driver API +* Added new hardware spinlock driver API +* Added new modem subsystem +* Added support for 45+ new boards +* Networking: improvements to CoAP, Connection Manager, DHCP, Ethernet, gPTP, ICMP, + IPv6 and LwM2M +* Bluetooth: improvements to the Controller, Audio, Mesh, as well as the host stack in + general +* Improved LVGL graphics library integration +* Integrated support with the CodeChecker static analyzer +* Picolibc is now the default C standard library + +An overview of the changes required or recommended when migrating your application from Zephyr +v3.4.0 to Zephyr v3.5.0 can be found in the separate :ref:`migration guide`. + The following sections provide detailed lists of changes by component. Security Vulnerability Related ****************************** +The following CVEs are addressed by this release: + +More detailed information can be found in: +https://docs.zephyrproject.org/latest/security/vulnerabilities.html + +* CVE-2023-3725 `Zephyr project bug tracker GHSA-2g3m-p6c7-8rr3 + `_ + +* CVE-2023-4257 `Zephyr project bug tracker GHSA-853q-q69w-gf5j + `_ + +* CVE-2023-4258 `Zephyr project bug tracker GHSA-m34c-cp63-rwh7 + `_ + +* CVE-2023-4259 `Zephyr project bug tracker GHSA-gghm-c696-f4j4 + `_ + +* CVE-2023-4260 `Zephyr project bug tracker GHSA-gj27-862r-55wh + `_ + +* CVE-2023-4263 `Zephyr project bug tracker GHSA-rf6q-rhhp-pqhf + `_ + +* CVE-2023-4264 `Zephyr project bug tracker GHSA-rgx6-3w4j-gf5j + `_ + +* CVE-2023-4424: Under embargo until 2023-11-01 + +* CVE-2023-5055: Under embargo until 2023-11-01 + +* CVE-2023-5139: Under embargo until 2023-10-25 + +* CVE-2023-5184 `Zephyr project bug tracker GHSA-8x3p-q3r5-xh9g + `_ + +* CVE-2023-5563 `Zephyr project bug tracker GHSA-98mc-rj7w-7rpv + `_ + +* CVE-2023-5753 `Zephyr project bug tracker GHSA-hmpr-px56-rvww + `_ Kernel ****** +* Added support for dynamic thread stack allocation via :c:func:`k_thread_stack_alloc` +* Added support for :c:func:`k_spin_trylock` +* Added :c:func:`k_object_is_valid` to check if a kernel object is valid. This replaces + code that has been duplicated throughout the tree. + Architectures ************* -* ARM +* ARC + + * Introduced the scalar port for ARC VPX processors + * Introduced support for ARCv3 HS (both 32 and 64 bit) SMP platforms with up to 12 CPU cores + * Reworked GNU helper tools usage for ARC MWDT toolchain. Now helper tools can be used from + Zephyr SDK (if SDK is installed) + * Fixed dynamic thread stack allocation + * Fixed STR assembly macro offset calculation issue which may cause build error for ARCv3 64bit + * Cleaned-up and made more user friendly handling of the ARC MWDT toolchain path + (ARCMWDT_TOOLCHAIN_PATH) * ARM + * Architectural support for Arm Cortex-M has been separated from Arm + Cortex-A and Cortex-R. This includes separate source modules to handle + tasks like IRQ management, exception handling, thread handling and swap. + For implementation details see :github:`60031`. + * ARM64 * RISC-V + * Added support for detecting null pointer exception using PMP. + * Added the :kconfig:option:`CONFIG_RISCV_RESERVED_IRQ_ISR_TABLES_OFFSET` + option to allow IRQ vector at a specified offset to meet the requirements + set by the Core-Local Interrupt Controller RISC-V specification. + * Added the :kconfig:option:`CONFIG_RISCV_SOC_HAS_CUSTOM_SYS_IO` option to + allow the use of custom system input/output functions. + * Introduced the :kconfig:option:`CONFIG_RISCV_TRAP_HANDLER_ALIGNMENT` option + to set the correct alignment of the trap handling code which is dependent on + the ``MTVEC.BASE`` field size and is platform or application-specific. + * Xtensa + * Added basic MMU v2 Support. + +* x86 + + * Added support for Intel Alder Lake boards + * Added support for Intel Sensor Hub (ISH) + +* POSIX + + * Has been reworked to use the native simulator. + * New boards have been added. + * For the new boards, embedded C libraries can be used, and conflicts with the host symbols + and libraries avoided. + * The :ref:`POSIX OS abstraction` is supported in these new boards. + * AMP targets are now supported. + * Added support for LLVM source profiling/coverage. + Bluetooth ********* * Audio + Improved memory usage of codec configurations and codec capabilities. Fixed several bugs in BAP + and the BAP-related services (ASCS, PACS, BASS), as well as missing features such as proper + notification handling. + + * Added BAP ``bt_bap_stream_get_tx_sync`` + * Added CAP stream send and tx sync + * Added ``bt_audio_codec_cap_get`` helper functions + * Added support for long read/write in CAP + * Fixed ASCS Source ASE link loss state transition + * Fixed ASCS possible ASE leak + * Fixed ASCS to drop ISO PDUs if ASE is not in streaming state + * Fixed BAP ``bt_bap_scan_delegator_find_state`` implementation + * Fixed BAP issue with PA sync and ID in ``broadcast_sink_create`` + * Fixed TMAS characteristic permissions + * Fixed ``tbs_client`` missing discovery complete event + * Fixed audio stack to accept empty CCID list in audio metadata + * Fixed bad size of metadata_backup in ASCS + * Fixed possible ASCS ASE stuck in releasing state + * Refactored ``bt_audio_codec_cap`` to flat arrays + * Refactored ``bt_audio_codec_cfg`` to flat arrays + * Removed ``CONFIG_BT_PACS_{SNK,SRC}_CONTEXT`` + * Removed scanning and PA sync from broadcast sink + * Renamed ``bt_codec`` to ``bt_audio_codec_{cap, conf, data}`` + * Renamed codec qos framing + * Replaced ``BT_AUDIO_CODEC_LC3_ID`` -> ``BT_HCI_CODING_FORMAT_LC3`` + * Replaced ``BT_AUDIO_CODEC_PARSE_ERR_`` values with errno values. + * Reworked PACS notify system + * Updated ASCS ISO QOS based on BAP QOS + * Updated BAP to filter PA data duplicates by default + * Updated CSIP to unlock Non-bonded devices immediately. + * Updated PACS to notify bonded clients on reconnect + * Updated ``bt_cap_stream_ops_register`` to always register BAP callbacks + * Updated the ASCS ACL disconnect behavior + * Updated to split ``bt_audio_codec_meta_get`` to ``cfg`` and ``cap`` + * Direction Finding * Host + * Added SMP bondable flag overlay per connection + * Added USE_NRPA advertising option + * Added ``BT_CONN_PARAM_ANY`` to allow setting any value to connection parameters + * Added advanced broadcast ISO parameters + * Added advanced unicast ISO parameters + * Added new API to manage Bluetooth settings storage + * Fixed HCI ISO Data packets fragmentation + * Fixed HCI ISO SDU length sent to controller + * Fixed OTS ``bt_ots_init`` parameter struct naming + * Fixed OTS memory leak while procedure is not finished + * Fixed a connection reference leak + * Fixed forced pairing request handling + * Fixed host to invalidate the Resolvable Private Address when starting legacy advertising + * Fixed issue with ``bt_iso_cig_reconfigure`` + * Fixed possible buffer overflow in ``bt_conn_le_start_encryption`` + * Fixed some SMP issues + * Fixed to abort pairing if connection disconnected + * Updated L2CAP accept callbacks + * Updated LE L2CAP connected callback to be after connection response + * Updated PAwR implementation to use RPA as responder address if BT_PRIVACY=y + * Mesh + * Added TF-M support. + * Added support to use both tinycrypt and PSA based crypto + * Added full virtual addresses support with the collisions resolution. The + :kconfig:option:`CONFIG_BT_MESH_LABEL_NO_RECOVER` Kconfig option is introduced to restore the + addresses for the subscription list and model publication. + * Added statistic module. + * Fixed an issue where a node acting as a LPN was triggering Friend Poll messages when sending a + segmented message over the loopback interface. + * Fixed an issue where provisioning completes successfully on a node when the identical Public Key + is used by a provisioner. + * Fixed an issue where the :c:func:`settings_load` function called from a cooperative thread other + than the system workqueue caused the GATT Mesh Proxy Service registration to fail. + * Fixed an issue where a node could enter IV Update in Progress state if an old SNB with the + current IV Index and IV Update flag set to 1 was resent. + + * Mesh Protocol v1.1 changes + + * Added storing Private GATT Proxy state persistently. + * Added support for Firmware Distribution Upload OOB Start message in the Firwmware Distribution + Server model. The message support can be enabled with the + :kconfig:option:`CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD` Kconfig option. + * Added extended provisioning protocol timeout when OOB methods are used in the provisioning. + * Added support for Composition Data Pages 2, 129 and 130. + * Added documentation for Composition Data Pages 0, 1, 2, 128, 129 and 130. + * Added documentation for the Segmentation and Reassembly in the Transport layer. + * Added documentation for the SAR Configuration models + * Fixed an issue where the Opcode Aggregator Server model did not compile without the Opcode + Aggregator Client model. + * Fixed an issue where the identity address was used in Private GATT Proxy advertisements + instead of Non-Resolvable Private Addresses. + * Fixed the Proxy Privacy parameter support. + * Fixed an issue where the Composition Data Page 128 was not present on a node that has + instantiated the Remote Provisioning Server model. + * Fixed an issue where the Large Composition Data Server model did not support Composition Data + Pages other then 0. + * Fixed an issue where the Remote Provisioning Client model instanted on a node together with + the Remote Provisioning Server model could not reprovision itself. + * Fixed an issue where the acknowledgment timer in the Segmentation and Reassembly was not + restarted when the incoming Segment Acknowledgment message did not contain at least one + segment newly marked as acknowledged. + * Fixed an issue where the On-Demand Private Proxy Server and Client models had interdependency + that did not allow to compile them separately. + * Controller -* HCI Driver + Improved support for Broadcast and Connected Isochronous channels in the Controller, enabling + LE audio application development. The Controller is experimental, is missing implementations for + interleaved packing in Isochronous channels' lower link layer. + + * Added Checks for minimum sizes of Adv PDUs + * Added Kconfig Option to ignore Tx HCI ISO Data Packet Seq Num + * Added Kconfig for avoiding ISO SDU fragmentation + * Added Kconfig to maximize BIG event length and preempt PTO & CTRL subevents + * Added ``BT_CTLR_EVENT_OVERHEAD_RESERVE_MAX`` Kconfig + * Added memory barrier to ticker transactions + * Added missing nRF53x Tx Power Kconfig + * Added support for Flush Timeout in Connected ISO + * Fixed BIS payload sliding window overrun check + * Fixed CIS Central FT calculation + * Fixed CIS Central error handling + * Fixed CIS assymmetric PHY usage + * Fixed CIS encryption when DF support enabled + * Fixed ISO-AL for quality tests and time stamps + * Fixed PHY value in HCI LE CIS Established Event + * Fixed ULL stuck in semaphore under rare conditions + * Fixed assertion due to late PER CIS active set + * Fixed compiler instruction re-ordering that caused assertions + * Fixed connected ISO dynamic tx power + * Fixed failing advertising conformance tests + * Fixed handling received Auxiliary PDUs when Coded PHY not supported + * Fixed leak in scheduled ticker node when rescheduling ticker nodes + * Fixed missing host feature reset + * Fixed nRF53 SoC back-to-back PDU chaining + * Fixed nRF53 SoC back-to-back Tx Rx implementation + * Fixed regression in Adv PDU overflow calculation + * Fixed regression in observer that caused assertions and scheduling stall + * Fixed use of pre-programmed PPI on nRF SoCs + * Removed HCI ISO data with invalid status in preparation for FT support + * Updated Extended Advertising Report to not be generated when ``AUX_ADV_IND`` not received + * Updated to have ``EVENT_OVERHEAD_START_US`` verbose assertion in each state/role LLL + * Updated to stop following ``aux_ptr`` if ``DATA_LEN_MAX`` is reached during extended scanning Boards & SoC Support ******************** @@ -51,6 +288,11 @@ Boards & SoC Support * Added support for these SoC series: * Nuvoton NuMaker M46x series + * Added support for STM32F072X8 SoC variants + * Added support for STM32L051X6 SoC variants + * Added support for STM32L451XX SoC variants + * Added support for STM32L4Q5XX SoC variants + * Added support for STM32WBA SoC series * Removed support for these SoC series: @@ -61,12 +303,23 @@ Boards & SoC Support and CONFIG_NXP_IMX_EXTERNAL_SDRAM to enabled. * i.MX RT SOCs no longer support CONFIG_OCRAM_NOCACHE, as this functionality can be achieved using devicetree memory regions + * Refactored ESP32 SoC folders. So now these are a proper SoC series. + * RP2040: Changed to reset the I2C device on initializing * Added support for these ARC boards: + * Added support for nsim_vpx5 - simulation (nSIM) platform with ARCv2 VPX5 core, close to + vpx5_integer_full template + * Added support for nsim_hs5x_smp_12cores - simulation (nSIM) platform with 12 cores SMP 32-bit + ARCv3 HS + * Added support for nsim_hs6x_smp_12cores - simulation (nSIM) platform with 12 cores SMP 64-bit + ARCv3 HS + * Added support for these ARM boards: * Nuvoton NuMaker Platform M467 + * ST Nucleo U5A5ZJ Q + * ST Nucleo WBA52CG * Added support for these ARM64 boards: @@ -76,10 +329,38 @@ Boards & SoC Support * Added support for these Xtensa boards: + * Added ``esp32_devkitc_wroom`` and ``esp32_devkitc_wrover``. + + * Added ``esp32s3_luatos_core``. + + * Added ``m5stack_core2``. + + * Added ``qemu_xtensa_mmu`` utilizing Diamond DC233c SoC to support + testing Xtensa MMU. + + * Added ``xiao_esp32s3``. + + * Added ``yd_esp32``. + +* Added support for these POSIX boards: + + * :ref:`native_sim(_64) ` + * nrf5340bsim_nrf5340_cpu(net|app). A simulated nrf5340 SOC, which uses Babblesim for its radio + traffic. + * Made these changes for ARC boards: + * Turned off unsupported stack checking option for hsdk4xd platform + * Changed vendor prefix for ARC QEMU platforms from "qemu" to "snps" + * Made these changes for ARM boards: + * ST morpho connector description was added on ST nucleo boards. + + * rpi_pico: + + * The default adapter when debugging with openocd has been changed to cmsis-dap. + * Made these changes for ARM64 boards: * Made these changes for RISC-V boards: @@ -88,6 +369,19 @@ Boards & SoC Support * Made these changes for Xtensa boards: + * esp32s3_devkitm: + + * Added USB-CDC support. + + * Added CAN support. + +* Made these changes for POSIX boards: + + * nrf52_bsim: + + * Has been reworked to use the native simulator as its runner. + * Multiple HW models improvements and fixes. GPIO & GPIOTE peripherals added. + * Removed support for these ARC boards: * Removed support for these ARM boards: @@ -100,10 +394,20 @@ Boards & SoC Support * Removed support for these Xtensa boards: + * Removed ``esp32``. Use ``esp32_devkitc_*`` instead. + * Made these changes in other boards: * Added support for these following shields: + * Adafruit PiCowbell CAN Bus Shield for Pico + * Arduino UNO click shield + * G1120B0MIPI MIPI Display + * MikroElektronika MCP2518FD Click shield (CAN-FD) + * RK055HDMIPI4M MIPI Display + * RK055HDMIPI4MA0 MIPI Display + * Semtech SX1276MB1MAS LoRa Shield + Build system and infrastructure ******************************* @@ -111,42 +415,125 @@ Build system and infrastructure * Added support for CodeChecker +* Twister now supports ``required_snippets`` in testsuite .yml files, this can + be used to include a snippet when a test is ran (and exclude any boards from + running that the snippet cannot be applied to). + +* Interrupts + + * Added support for shared interrupts + +* Added support for setting MCUboot encryption key in sysbuild which is then + propagated to the bootloader and target images to automatically create + encrypted updates. + +* Build time priority checking: enable build time priority checking by default. + This fails the build if the initialization sequence in the final ELF file + does not match the devicetree hierarchy. It can be turned off by disabling + the :kconfig:option:`COFNIG_CHECK_INIT_PRIORITIES` option. + +* Added a new ``initlevels`` target for printing the final device and + :c:macro:`SYS_INIT` initialization sequence from the final ELF file. + +* Reworked syscall code generations so that not all marshalling functions + will be included in the final binary. Syscalls associated with disabled + subsystems no longer have their marshalling functions generated. + +* Partially enabled compiler warning about shadow variables for subset of + in-tree code. Out-of-tree code needs to be patched before we can fully + enable shadow variable warnings. + Drivers and Sensors ******************* * ADC -* Battery-backed RAM + * Added support for STM32F0 HSI14 clock (dedicated ADC clock) + * Added support for STM32 ADC source clock and prescaler. On STM32F1 and STM32F3 + series, ADC prescaler can be configured using dedicated RCC Clock Controller + option. + * Added support for the ADC sequencer for all STM32 series (except F1) + * Fixed STM32F4 ADC temperature and Vbat measurement. + * Added driver for TI ADS1112. + * Added driver for TI TLA2021. + * Added driver for Gecko ADC. + * Added driver for NXP S32 ADC SAR. + * Added driver for MAX1125x family. + * Added driver for MAX11102-MAX1117. * CAN + * Added support for TI TCAN4x5x CAN-FD controller with integrated transceiver + (:dtcompatible:`ti,tcan4x5x`). + * Added support for Microchip MCP251xFD CAN-FD controller (:dtcompatible:`microchip,mcp251xfd`). + * Added support for CAN statistics to the Bosch M_CAN controller driver backend. + * Switched the NXP S32 CANXL driver to use clock control for the CAN clock instead of hard-coding + a CAN clock frequency in the devicetree. + * Clock control * Added support for Nuvoton NuMaker M46x * Counter -* Crypto + * Added :kconfig:option:`CONFIG_COUNTER_RTC_STM32_SUBSECONDS` to enable subsecond as + the basic time tick on STM32 RTC based counter driver. + + * Added support for Raspberry Pi Pico Timer * DAC -* DFU + * Added support for Analog Devices AD56xx + * Added support for NXP lpcxpresso55s36 (LPDAC) * Disk + * Ramdisk driver is now configured using devicetree, and supports multiple + instances + * Display + * Added support for ST7735S (in ST7735R driver) + * DMA + * Added support for NXP S32K to the eDMA driver + * Added support for NXP SMARTDMA + * Added support for NXP Pixel Pipeline (PXP) for display acceleration + * Added support for DMA get_status() to the SAM XDMAC driver + * Fixes for Intel HDA driver for L1 entry/exit, explicit SCS (sample container) settings + * Fixes for STM32U5 enables error interrupts, fixes block size and data size configuration + * Better Kconfig options for tuning static memory usage in NXP LPC driver + * EEPROM + * Added support for Fujitsu MB85RCxx series I2C FRAM (:dtcompatible:`fujitsu,mb85rcxx`). + * Entropy -* ESPI + * Added a requirement for ``entropy_get_entropy()`` to be thread-safe because + of random subsystem needs. * Ethernet * Added :kconfig:option:`CONFIG_ETH_NATIVE_POSIX_RX_TIMEOUT` to set rx timeout for native posix. + * Added support for adin2111. + * Added support for NXP S32 GMAC. + * Added support for promiscuous mode in eth_smsc91x. + * Added support for STM32H5X SOC series. + * Added support for MDIO Clause 45 APIs. + * Added support for YD-ESP32 board Ethernet. + * Fixed stm32 to generate more unique MAC address by using device id as a base for the MAC. + * Fixed mcux to increase the PTP timestamp accuracy from 20us to 200ns. + * Fixed Ethernet max header size when using VLAN. + * Removed the ``mdio`` DT property. Please use :c:macro:`DT_INST_BUS()` in the driver instead. + * Reworked the device node hierarchy in smsc91x. + * Renamed the phy-dev property with phy-handle to match the Linux ethernet-controller binding + and move it up to ethernet.yaml so that it can be used by other drivers. + * Updated Ethernet PHY to use ``reg`` property in DT bindings. + * Updated driver DT bindings to use ``ethernet-phy`` devicetree node name consistently. + * Updated esp32 and sam-gmac DT so that the phy is pointed by a phandle rather than + a child node, this makes the phy device a child of mdio. * Flash @@ -154,42 +541,96 @@ Drivers and Sensors single Flash Interface Unit (FIU) module and Direct Read Access (DRA) mode for better performance. * Added support for Nuvoton NuMaker M46x embedded flash - -* FPGA - -* Fuel Gauge + * STM32 QSPI driver now supports Jedec SFDP parameter reading. + * STM32 OSPI driver now supports both Low and High ports of IO manager. * GPIO * Added support for Nuvoton NuMaker M46x -* hwinfo - * I2C + * STM32 V1 driver now supports large transactions (more than 256 bytes chunks) + * STM32 V2 driver now supports 10-bit addressing. + * I2C devices can now be used as wakeup source from STOP modes on STM32. + * Fix long ISR execution in Silicon Labs I2C target callback + * Fail gracefully on DMA max size for nRF52 devices in the TWIM driver + * Added support for Intel LPSS DMA usage in the DesignWare driver + * Added filtering of dumped messages for debugging using DeviceTree + * Added target mode to Silicon Labs Gecko driver + * Added Intel SEDI driver + * Added Infineon XMC4 driver + * Added Microchip PolarFire SoC driver + * Added Ambiq driver for Apollo4 SoCs + * I2S + * Fixed handling of the PCM data format in the NXP MCUX driver. + * I3C + * ``i3c_cdns``: + + * Fixed build error when :kconfig:option:`CONFIG_I3C_USE_IBI` is disabled. + + * Fixed transfer issue when controller is busy. Now wait for controller to + idle before proceeding with another transfer. + * IEEE 802.15.4 + * A new mandatory method attr_get() was introduced into ieee802154_radio_api. + Drivers need to implement at least + IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_PAGES and + IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES. + * The hardware capabilities IEEE802154_HW_2_4_GHZ and IEEE802154_HW_SUB_GHZ + were removed as they were not aligned with the standard and some already + existing drivers couldn't properly express their channel page and channel + range (notably SUN FSK and HRP UWB drivers). The capabilities were replaced + by the standard conforming new driver attribute + IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_PAGES that fits all in-tree drivers. + * The method get_subg_channel_count() was removed from ieee802154_radio_api. + This method could not properly express the channel range of existing drivers + (notably SUN FSK drivers that implement channel pages > 0 and may not have + zero-based channel ranges or UWB drivers that could not be represented at + all). The method was replaced by the new driver attribute + IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES that fits all in-tree drivers. + * Interrupt Controller * GIC: Architecture version selection is now based on the device tree -* IPM +* Input -* KSCAN + * New drivers: :dtcompatible:`gpio-qdec`, :dtcompatible:`st,stmpe811`. -* LED + * Drivers converted from Kscan to Input: :dtcompatible:`goodix,gt911` + :dtcompatible:`xptek,xpt2046` :dtcompatible:`hynitron,cst816s` + :dtcompatible:`microchip,cap1203`. -* MBOX + * Added a Kconfig option for dumping all events to the console + :kconfig:option:`CONFIG_INPUT_EVENT_DUMP` and new shell commands + :kconfig:option:`CONFIG_INPUT_SHELL`. -* MEMC + * Merged ``zephyr,gpio-keys`` into :dtcompatible:`gpio-keys` and added + ``zephyr,code`` codes to all in-tree board ``gpio-keys`` nodes. + + * Renamed the callback definition macro from ``INPUT_LISTENER_CB_DEFINE`` to + :c:macro:`INPUT_CALLBACK_DEFINE`. * PCIE -* PECI + * Added support in shell to display PCIe capabilities. + + * Added virtual channel support. + + * Added kconfig :kconfig:option:`CONFIG_PCIE_INIT_PRIORITY` to specify + initialization priority for host controller. + + * Added support to get IRQ from ACPI PCI Routing Table (PRT). + +* ACPI + + * Adopted the ACPICA library as a new module to further enhance ACPI support. * Pin control @@ -197,25 +638,116 @@ Drivers and Sensors * PWM -* Power domain + * Added 4 channels capture on STM32 PWM driver. + * Added driver for Intel Blinky PWM. + * Added driver for MAX31790. + * Added driver for Infineon XMC4XXX CCU4. + * Added driver for Infineon XMC4XXX CCU8. + * Added MCUX CTimer based PWM driver. + * Added PWM driver based on TI CC13xx/CC26xx GPT timer. + * Reworked the pwm_nrf5_sw driver so that it can be used also on nRF53 and + nRF91 Series. Consequently, the driver was renamed to pwm_nrf_sw. + * Added driver for Nuvoton NuMaker family. + * Added PWM driver based on NXP S32 EMIOS peripheral. * Regulators + * Added support for GPIO-controlled voltage regulator + + * Added support for AXP192 PMIC + + * Added support for NXP VREF regulator + + * Fixed regulators can now specify their operating voltage + + * PFM mode is now support for nPM1300 + + * Added new API to configure "ship" mode + + * Regulator shell allows to configure DVS modes + * Reset * Added support for Nuvoton NuMaker M46x +* Retained memory + + * Added support for allowing mutex support to be forcibly disabled with + :kconfig:option:`CONFIG_RETAINED_MEM_MUTEX_FORCE_DISABLE`. + + * Fixed issue with user mode support not working. + +* RTC + + * Added support for STM32 RTC API driver. This driver is not compatible with + the use of RTC based implementation of COUNTER API. + * SDHC + * Added driver for EMMC Host controller present on Alder lake platforms + * Added driver for Atmel HSMCI controller present on SAM4E MCU series + * Sensor + * Reworked the :dtcompatible:`ti,bq274xx` to add ``BQ27427`` support, fixed + units for capacity and power channels. + * Added ADC current sense amplifier and voltage sensor drivers. + * Added ADI LTC2990 voltage, current, and temperature sensor driver. + * Added AMS TSL2540 ambient light sensor driver. + * Added Bosch BMI08x accelerometer/gyroscope driver. + * Added DFRobot A01NYUB distance sensor driver. + * Added Fintek F75303 temperature sensor driver. + * Added Isentek IST8310 magnetometer driver. + * Added Microchip TCN75A temperature sensor driver. + * Added NXP TEMPMON driver. + * Added Seeed HM330X dust sensor driver. + * Added TI TMAG5170 3D Hall sensor driver. + * Added power management support to BMM150, LM75, and Microchip tachometer + drivers. + * Added trigger support to the BMM150 magnetometer driver. + * Added tap trigger support to the LIS2DH accelerometer driver. + * Updated ST sensor drivers to use STMEMSC HAL i/f v2.3 + * Updated the decoder APIs to vertically decode raw sensor data. + * Various fixes and enhancements in the NTC thermistor and INA23x drivers. + * Serial * Added support for Nuvoton NuMaker M46x + * NS16550: Reworked how device initialization macros. + + * ``CONFIG_UART_NS16550_ACCESS_IOPORT`` and ``CONFIG_UART_NS16550_SIMULT_ACCESS`` + are removed. For UART using IO port access, add ``io-mapped`` property to + device tree node. + + * Added async support for ESP32S3. + + * Added support for serial TTY under ``native_posix``. + + * Added support for UART on Efinix Sapphire SoCs. + + * Added Intel SEDI UART driver. + + * Added support for UART on BCM2711. + + * ``uart_stm32``: + + * Added RS485 support. + + * Added wide data support. + + * ``uart_pl011``: added support for Ambiq SoCs. + + * ``serial_test``: added support for interrupt and async APIs. + + * ``uart_emul``: added support for interrupt API. + + * ``uart_rpi_pico``: fixed handling Modbus DE-RE signal + * SPI * Remove npcx spi driver implemented by Flash Interface Unit (FIU) module. + * Added support for Raspberry Pi Pico PIO based SPI. * Timer @@ -227,28 +759,76 @@ Drivers and Sensors * USB -* W1 - -* Watchdog + * Added UDC driver for STM32 based MCU, relying on HAL/PCD. This driver is compatible + with UDC API (experimental). + * Added support for STM32H5 series on USB driver. * WiFi + * Increased esp32 default network (TCP workq, RX and mgmt event) stack sizes to 2048 bytes. + * Reduced the RAM usage for esp32s2_saola in Wi-Fi samples. + * Fixed undefined declarations in winc1500. + * Fixed SPI buffer length in eswifi. + * Fixed esp32 data sending and channel selection in AP mode. + * Fixed esp_at driver init and network interface dormant state setting. + Networking ********** -* Time and timestamps in the network subsystem, PTP and IEEE 802.15.4 - were more precisely specified and all in-tree call sites updated accordingly. - Fields for timed TX and TX/RX timestamps have been consolidated. See - :c:type:`net_time_t`, :c:struct:`net_ptp_time`, :c:struct:`ieee802154_config`, - :c:struct:`ieee802154_radio_api` and :c:struct:`net_pkt` for extensive - documentation. As this is largely an internal API, existing applications will - most probably continue to work unchanged. - * CoAP: + * Optimized CoAP client library to use only a single thread internally. + * Converted CoAP client library to use ``zsock_*`` API internally. + * Fixed a bug in CoAP client library, which resulted in an incorrect + retransmission timeout calculation. * Use 64 bit timer values for calculating transmission timeouts. This fixes potential problems for devices that stay on for more than 49 days when the 32 bit uptime counter might roll over and cause CoAP packets to not timeout at all on this event. + * API documentation improvements. + * Added new API functions: + + * :c:func:`coap_has_descriptive_block_option` + * :c:func:`coap_remove_descriptive_block_option` + * :c:func:`coap_packet_remove_option` + * :c:func:`coap_packet_set_path` + +* Connection Manager: + + * Added support for auto-connect and auto-down behaviors (controlled by + :c:enum:`CONN_MGR_IF_NO_AUTO_CONNECT` and :c:enum:`CONN_MGR_IF_NO_AUTO_DOWN` + flags). + * Split Connection Manager APIs into separate header files. + * Extended Connection Manager documentation to cover new functionalities. + +* DHCP: + + * Added support for DHCPv4 unicast replies processing. + * Added support for DHCPv6 protocol. + +* Ethernet: + + * Fixed ARP queueing so that the queued network packet is sent immediately + instead of queued 2nd time in the core network stack. + +* gPTP: + + * Added support for detecting gPTP packets that use the default multicast destination address. + * Fixed Announce and Follow Up message handling. + +* ICMP: + + * Fixed ICMPv6 error message type check. + * Reworked ICMP callback registration and handling, which allows to register + multiple handlers for the same ICMP message. + * Introduced an API to send ICMP Echo Request (ping). + * Added possibility to register offloaded ICMP ping handlers. + * Added support for setting packet priority for ping. + +* IPv6: + + * Made sure that ongoing DAD procedure is cancelled when IPv6 address is removed. + * Fixed a bug, where Solicited-Node multicast address could be removed while + still in use. * LwM2M: @@ -256,121 +836,1496 @@ Networking so the engine does not constantly wake up the CPU. This can be enabled by :kconfig:option:`CONFIG_LWM2M_TICKLESS`. * Added new :c:macro:`LWM2M_RD_CLIENT_EVENT_DEREGISTER` event. + * Block-wise sending now supports LwM2M read and composite-read operations as well. + When :kconfig:option:`CONFIG_LWM2M_COAP_BLOCK_TRANSFER` is enabled, any content that is larger + than :kconfig:option:`CONFIG_LWM2M_COAP_MAX_MSG_SIZE` is split into a block-wise transfer. + * Block-wise transfers don't require tokens to match anymore as this was not in line + with CoAP specification (CoAP doesn't require tokens re-use). + * Various fixes to bootstrap. Now client ensures that Bootstrap-Finish command is sent, + before closing the DTLS pipe. Also allows Bootstrap server to close the DTLS pipe. + Added timeout when waiting for bootstrap commands. + * Added support for X509 certificates. + * Various fixes to string handling. Allow setting string to zero length. + Ensure string termination when using string operations on opaque resources. + * Added support for Connection Monitoring object version 1.3. + * Added protection for Security object to prevent read/writes by the server. + * Fixed a possible notification stall in case of observation token change. + * Added new shell command, ``lwm2m create``, which allows to create LwM2M object instances. + * Added LwM2M interoperability test-suite against Leshan server. + * API documentation improvements. + * Several other minor fixes and improvements. + +* Misc: + + * Time and timestamps in the network subsystem, PTP and IEEE 802.15.4 + were more precisely specified and all in-tree call sites updated accordingly. + Fields for timed TX and TX/RX timestamps have been consolidated. See + :c:type:`net_time_t`, :c:struct:`net_ptp_time`, :c:struct:`ieee802154_config`, + :c:struct:`ieee802154_radio_api` and :c:struct:`net_pkt` for extensive + documentation. As this is largely an internal API, existing applications will + most probably continue to work unchanged. + * Added support for additional net_pkt filter hooks: + + * :kconfig:option:`CONFIG_NET_PKT_FILTER_IPV4_HOOK` + * :kconfig:option:`CONFIG_NET_PKT_FILTER_IPV6_HOOK` + * :kconfig:option:`CONFIG_NET_PKT_FILTER_LOCAL_IN_HOOK` + + * Reworked several networking components to use timepoint API. + * Added API functions facilitate going through all IPv4/IPv6 registered on an + interface (:c:func:`net_if_ipv4_addr_foreach`, :c:func:`net_if_ipv6_addr_foreach`). + * ``NET_EVENT_IPV6_PREFIX_ADD`` and ``NET_EVENT_IPV6_PREFIX_DEL`` events now provide + more detailed information about the prefix (:c:struct:`net_event_ipv6_prefix`). + * General cleanup of the shadowed variables across the networking subsystem. + * Added ``qemu_cortex_a53`` networking support. + * Introduced new modem subsystem. + * Added new :zephyr:code-sample:`cellular-modem` sample. + * Added support for network interface names (instead of reusing underlying device name). + * Removed support for Google Cloud IoT sample due to service retirement. + * Fixed a bug where packets passed in promiscuous mode could have been modified + by L2 in certain cases. + * Added support for setting syslog server (used for networking log backend) + IP address at runtime. + * Removed no longer used ``queued`` and ``sent`` net_pkt flags. + * Added support for binding zperf TCP/UDP server to a specific IP address. + +* MQTT-SN: + + * Improved thread safety of internal buffers allocation. + * API documentation improvements. + +* OpenThread: + + * Reworked :c:func:`otPlatEntropyGet` to use :c:func:`sys_csrand_get` internally. + * Introduced ``ieee802154_radio_openthread.h`` radio driver extension interface + specific for OpenThread. Added new transmit mode, specific to OpenThread, + :c:enum:`IEEE802154_OPENTHREAD_TX_MODE_TXTIME_MULTIPLE_CCA`. + +* PPP: + + * Fixed PPP L2 usage of the network interface carrier state. + * Made PPP L2 thread priority configurable (:kconfig:option:`CONFIG_NET_L2_PPP_THREAD_PRIO`). + * Moved PPP L2 out of experimental stage. + * Prevent PPP connection reestablish when carrier is down. + +* Sockets: + + * Added support for statically allocated socketpairs (in case no heap is available). + * Made send timeout configurable (:kconfig:option:`CONFIG_NET_SOCKET_MAX_SEND_WAIT`). + * Added support for ``FIONREAD`` and ``FIONBIO`` :c:func:`ioctl` commands. + * Fixed input filtering for connected datagram sockets. + * Fixed :c:func:`getsockname` operation on unconnected sockets. + * Added new secure socket options for DTLS Connection ID support: + + * :c:macro:`TLS_DTLS_CID` + * :c:macro:`TLS_DTLS_CID_VALUE` + * :c:macro:`TLS_DTLS_PEER_CID_VALUE` + * :c:macro:`TLS_DTLS_CID_STATUS` + + * Added support for :c:macro:`SO_REUSEADDR` and :c:macro:`SO_REUSEPORT` socket options. + +* TCP: + + * Fixed potential stall in data retransmission, when data was only partially acknowledged. + * Made TCP work queue priority configurable (:kconfig:option:`CONFIG_NET_TCP_WORKER_PRIO`). + * Added support for TCP new Reno collision avoidance algorithm. + * Fixed source address selection on bound sockets. + * Fixed possible memory leak in case listening socket was closed during active handshake. + * Fixed RST packet handling during handshake. + * Refactored the code responsible for connection teardown to fix found bugs and + simplify future maintenance. + +* TFTP: + + * Added new :zephyr:code-sample:`tftp-client` sample. + * API documentation improvements. + +* WebSocket + + * WebSocket library no longer closes underlying TCP socket automatically on disconnect. + This aligns with the connect behavior, where the WebSocket library expects an already + connected TCP socket. + +* Wi-Fi: -* Wi-Fi * Added Passive scan support. * The Wi-Fi scan API updated with Wi-Fi scan parameter to allow scan mode selection. + * Updated TWT handling. + * Added support for generic network manager API. + * Added support for Wi-Fi mode setting and selection. + * Added user input validation for SSID and PSK in Wi-Fi shell. + * Added scan extension for specifying channels, limiting scan results, filtering SSIDs, + setting active and passive channel dwell times and frequency bands. USB *** +* USB device HID + * Kconfig option USB_HID_PROTOCOL_CODE, deprecated in v2.6, is finally removed. + Devicetree ********** -* ``zephyr,memory-region-mpu`` was renamed ``zephyr,memory-attr`` +API +=== + +New general-purpose macros: -* The following macros were added: - :c:macro:`DT_FOREACH_NODE_VARGS`, - :c:macro:`DT_FOREACH_STATUS_OKAY_NODE_VARGS` - :c:macro:`DT_MEMORY_ATTR_FOREACH_NODE` - :c:macro:`DT_MEMORY_ATTR_APPLY` - :c:macro:`DT_MEM_FROM_FIXED_PARTITION` - :c:macro:`DT_FIXED_PARTITION_ADDR` +- :c:macro:`DT_REG_ADDR_U64` +- :c:macro:`DT_REG_ADDR_BY_NAME_U64` +- :c:macro:`DT_INST_REG_ADDR_BY_NAME_U64` +- :c:macro:`DT_INST_REG_ADDR_U64` +- :c:macro:`DT_FOREACH_STATUS_OKAY_NODE_VARGS` +- :c:macro:`DT_FOREACH_NODE_VARGS` +- :c:macro:`DT_HAS_COMPAT_ON_BUS_STATUS_OKAY` -Libraries / Subsystems -********************** +New special-purpose macros introduced for dependency ordinals: -* Management +- :c:macro:`DT_DEP_ORD_STR_SORTABLE` - * Introduced MCUmgr client support with handlers for img_mgmt and os_mgmt. +New general purpose macros introduced for fixed flash partitions: - * Added response checking to MCUmgr's :c:enumerator:`MGMT_EVT_OP_CMD_RECV` - notification callback to allow applications to reject MCUmgr commands. +- :c:macro:`DT_MEM_FROM_FIXED_PARTITION` +- :c:macro:`DT_FIXED_PARTITION_ADDR` - * MCUmgr SMP version 2 error translation (to legacy MCUmgr error code) is now - supported in function handlers by setting ``mg_translate_error`` of - :c:struct:`mgmt_group` when registering a transport. See - :c:type:`smp_translate_error_fn` for function details. +Bindings +======== - * Fixed an issue with MCUmgr img_mgmt group whereby the size of the upload in - the initial packet was not checked. +* Generic or vendor-independent: - * Fixed an issue with MCUmgr fs_mgmt group whereby some status codes were not - checked properly, this meant that the error returned might not be the - correct error, but would only occur in situations where an error was - already present. + * New bindings: - * Fixed an issue whereby the SMP response function did not check to see if - the initial zcbor map was created successfully. + * :dtcompatible:`current-sense-amplifier` + * :dtcompatible:`current-sense-shunt` + * :dtcompatible:`gpio-qdec` + * :dtcompatible:`regulator-gpio` + * :dtcompatible:`usb-audio-feature-volume` - * Fixes an issue with MCUmgr shell_mgmt group whereby the length of a - received command was not properly checked. + * Modified bindings: - * Added optional mutex locking support to MCUmgr img_mgmt group, which can - be enabled with :kconfig:option:`CONFIG_MCUMGR_GRP_IMG_MUTEX`. + * CAN (Controller Area Network) controller bindings: - * Added MCUmgr settings management group, which allows for manipulation of - zephyr settings from a remote device, see :ref:`mcumgr_smp_group_3` for - details. + * property ``phase-seg1-data`` deprecation status changed from False to True + * property ``phase-seg1`` deprecation status changed from False to True + * property ``phase-seg2-data`` deprecation status changed from False to True + * property ``phase-seg2`` deprecation status changed from False to True + * property ``prop-seg-data`` deprecation status changed from False to True + * property ``prop-seg`` deprecation status changed from False to True + * property ``sjw-data`` default value changed from None to 1 + * property ``sjw-data`` deprecation status changed from False to True + * property ``sjw`` default value changed from None to 1 + * property ``sjw`` deprecation status changed from False to True - * Added :kconfig:option:`CONFIG_MCUMGR_GRP_IMG_ALLOW_CONFIRM_NON_ACTIVE_IMAGE_SECONDARY` - and :kconfig:option:`CONFIG_MCUMGR_GRP_IMG_ALLOW_CONFIRM_NON_ACTIVE_IMAGE_ANY` - that allow to control whether MCUmgr client will be allowed to confirm - non-active images. + * Ethernet controller bindings: new ``phy-handle`` property (in some + bindings, this was renamed from ``phy-dev``), matching the Linux + ethernet-controller binding. - * Added :kconfig:option:`CONFIG_MCUMGR_GRP_IMG_ALLOW_ERASE_PENDING` that allows - to erase slots pending for next boot, that are not revert slots. + * The ``riscv,isa`` property used by RISC-V CPU bindings no longer has an + ``enum`` value. -* File systems + * :dtcompatible:`neorv32-cpu`: - * Added support for ext2 file system. - * Added support of mounting littlefs on the block device from the shell/fs. - * Added alignment parameter to FS_LITTLEFS_DECLARE_CUSTOM_CONFIG macro, it can speed up read/write - operation for SDMMC devices in case when we align buffers on CONFIG_SDHC_BUFFER_ALIGNMENT, - because we can avoid extra copy of data from card bffer to read/prog buffer. + * new property: ``mmu-type`` + * new property: ``riscv,isa`` -HALs -**** + * :dtcompatible:`regulator-fixed`: -* Nuvoton + * new property: ``regulator-min-microvolt`` + * new property: ``regulator-max-microvolt`` + * property ``enable-gpios`` is no longer required - * Added Nuvoton NuMaker M46x + * :dtcompatible:`ethernet-phy`: -MCUboot -******* + * removed property: ``address`` + * removed property: ``mdio`` + * property ``reg`` is now required - * Added :kconfig:option:`CONFIG_MCUBOOT_BOOTLOADER_NO_DOWNGRADE` - that allows to inform application that the on-board MCUboot has been configured - with downgrade prevention enabled. This option is automatically selected for - DirectXIP mode and is available for both swap modes. + * :dtcompatible:`usb-audio-hs` and :dtcompatible:`usb-audio-hp`: - * Added :kconfig:option:`CONFIG_MCUBOOT_BOOTLOADER_MODE_OVERWRITE_ONLY` - that allows to inform application that the on-board MCUboot will overwrite - the primary slot with secondary slot contents, without saving the original - image in primary slot. + * new property: ``volume-max`` + * new property: ``volume-min`` + * new property: ``volume-res`` + * new property: ``status`` + * new property: ``compatible`` + * new property: ``reg`` + * new property: ``reg-names`` + * new property: ``interrupts`` + * new property: ``interrupts-extended`` + * new property: ``interrupt-names`` + * new property: ``interrupt-parent`` + * new property: ``label`` + * new property: ``clocks`` + * new property: ``clock-names`` + * new property: ``#address-cells`` + * new property: ``#size-cells`` + * new property: ``dmas`` + * new property: ``dma-names`` + * new property: ``io-channels`` + * new property: ``io-channel-names`` + * new property: ``mboxes`` + * new property: ``mbox-names`` + * new property: ``wakeup-source`` + * new property: ``power-domain`` + * new property: ``zephyr,pm-device-runtime-auto`` -Storage -******* + * :dtcompatible:`ntc-thermistor-generic`: -Trusted Firmware-M -****************** + * removed property: ``r25-ohm`` -Trusted Firmware-A -****************** + * :dtcompatible:`ns16550`: -* Updated to TF-A 2.9.0. + * new property: ``resets`` + * new property: ``reset-names`` -zcbor -***** + * :dtcompatible:`fixed-clock`: -Documentation -************* + * removed property: ``clocks`` -Tests and Samples -***************** + * All CPU bindings got a new ``enable-method`` property. `pull request + 60210 `_ for + details. -* Created common sample for file systems (`fs_sample`). It originates from sample for FAT - (`fat_fs`) and supports both FAT and ext2 file systems. +* Analog Devices, Inc. (adi): + + * New bindings: + + * :dtcompatible:`adi,ad5628` + * :dtcompatible:`adi,ad5648` + * :dtcompatible:`adi,ad5668` + * :dtcompatible:`adi,ad5672` + * :dtcompatible:`adi,ad5674` + * :dtcompatible:`adi,ad5676` + * :dtcompatible:`adi,ad5679` + * :dtcompatible:`adi,ad5684` + * :dtcompatible:`adi,ad5686` + * :dtcompatible:`adi,ad5687` + * :dtcompatible:`adi,ad5689` + * :dtcompatible:`adi,adin1110` + * :dtcompatible:`adi,adltc2990` + + * Modified bindings: + + * :dtcompatible:`adi,adin2111-mdio` (on adin2111 bus): + + * removed property: ``protocol`` + +* Altera Corp. (altr): + + * New bindings: + + * :dtcompatible:`altr,pio-1.0` + +* Ambiq Micro, Inc. (ambiq): + + * New bindings: + + * :dtcompatible:`ambiq,am1805` + * :dtcompatible:`ambiq,apollo4-pinctrl` + * :dtcompatible:`ambiq,counter` + * :dtcompatible:`ambiq,i2c` + * :dtcompatible:`ambiq,mspi` + * :dtcompatible:`ambiq,pwrctrl` + * :dtcompatible:`ambiq,spi` + * :dtcompatible:`ambiq,stimer` + * :dtcompatible:`ambiq,uart` + * :dtcompatible:`ambiq,watchdog` + +* AMS AG (ams): + + * New bindings: + + * :dtcompatible:`ams,tsl2540` + +* Andes Technology Corporation (andestech): + + * New bindings: + + * :dtcompatible:`andestech,atcwdt200` + * :dtcompatible:`andestech,plic-sw` + * :dtcompatible:`andestech,qspi-nor` + +* ARM Ltd. (arm): + + * New bindings: + + * :dtcompatible:`arm,cortex-a76` + * :dtcompatible:`arm,gic-v1` + * :dtcompatible:`arm,gic-v2` + * :dtcompatible:`arm,gic-v3` + * :dtcompatible:`arm,psci-1.1` + +* ASPEED Technology Inc. (aspeed): + + * Modified bindings: + + * :dtcompatible:`aspeed,ast10x0-reset`: + + * specifier cells for space "reset" are now named: ['id'] (old value: None) + * specifier cells for space "clock" are now named: None (old value: ['reset_id']) + +* Atmel Corporation (atmel): + + * New bindings: + + * :dtcompatible:`atmel,sam-hsmci` + + * Modified bindings: + + * :dtcompatible:`atmel,sam-mdio`: + + * removed property: ``protocol`` + * property ``#address-cells`` const value changed from None to 1 + * property ``#size-cells`` const value changed from None to 0 + * property ``#address-cells`` is now required + * property ``#size-cells`` is now required + +* Bosch Sensortec GmbH (bosch): + + * New bindings: + + * :dtcompatible:`bosch,bmi08x-accel` + * :dtcompatible:`bosch,bmi08x-accel` + * :dtcompatible:`bosch,bmi08x-gyro` + * :dtcompatible:`bosch,bmi08x-gyro` + + * Modified bindings: + + * :dtcompatible:`bosch,bmm150`: + + * new property: ``drdy-gpios`` + + * :dtcompatible:`bosch,bmi270`: + + * new property: ``irq-gpios`` + +* Broadcom Corporation (brcm): + + * New bindings: + + * :dtcompatible:`brcm,bcm2711-aux-uart` + +* Cadence Design Systems Inc. (cdns): + + * New bindings: + + * :dtcompatible:`cdns,tensilica-xtensa-lx3` + +* DFRobot (dfrobot): + + * New bindings: + + * :dtcompatible:`dfrobot,a01nyub` + +* Efinix Inc (efinix): + + * New bindings: + + * :dtcompatible:`efinix,sapphire-gpio` + * :dtcompatible:`efinix,sapphire-timer0` + * :dtcompatible:`efinix,sapphire-uart0` + +* EPCOS AG (epcos): + + * Modified bindings: + + * :dtcompatible:`epcos,b57861s0103a039`: + + * removed property: ``r25-ohm`` + +* Espressif Systems (espressif): + + * Modified bindings: + + * :dtcompatible:`espressif,esp-at` (on uart bus): + + * new property: ``external-reset`` + + * :dtcompatible:`espressif,esp32-mdio`: + + * removed property: ``protocol`` + * property ``#address-cells`` const value changed from None to 1 + * property ``#size-cells`` const value changed from None to 0 + * property ``#address-cells`` is now required + * property ``#size-cells`` is now required + + * :dtcompatible:`espressif,riscv`: + + * new property: ``mmu-type`` + * new property: ``riscv,isa`` + + * :dtcompatible:`espressif,esp32-spi`: + + * new property: ``line-idle-low`` + +* Feature Integration Technology Inc. (fintek): + + * New bindings: + + * :dtcompatible:`fintek,f75303` + +* FocalTech Systems Co.,Ltd (focaltech): + + * Modified bindings: + + * :dtcompatible:`focaltech,ft5336` (on i2c bus): + + * new property: ``reset-gpios`` + +* Fujitsu Ltd. (fujitsu): + + * New bindings: + + * :dtcompatible:`fujitsu,mb85rcxx` + +* Shenzhen Huiding Technology Co., Ltd. (goodix): + + * Modified bindings: + + * :dtcompatible:`goodix,gt911` (on i2c bus): + + * bus list changed from ['kscan'] to [] + * new property: ``alt-addr`` + +* Himax Technologies, Inc. (himax): + + * New bindings: + + * :dtcompatible:`himax,hx8394` + +* Infineon Technologies (infineon): + + * New bindings: + + * :dtcompatible:`infineon,cat1-counter` + * :dtcompatible:`infineon,cat1-spi` + * :dtcompatible:`infineon,xmc4xxx-ccu4-pwm` + * :dtcompatible:`infineon,xmc4xxx-ccu8-pwm` + * :dtcompatible:`infineon,xmc4xxx-i2c` + +* Intel Corporation (intel): + + * New bindings: + + * :dtcompatible:`intel,agilex5-clock` + * :dtcompatible:`intel,alder-lake` + * :dtcompatible:`intel,apollo-lake` + * :dtcompatible:`intel,blinky-pwm` + * :dtcompatible:`intel,elkhart-lake` + * :dtcompatible:`intel,emmc-host` + * :dtcompatible:`intel,ish` + * :dtcompatible:`intel,loapic` + * :dtcompatible:`intel,sedi-gpio` + * :dtcompatible:`intel,sedi-i2c` + * :dtcompatible:`intel,sedi-ipm` + * :dtcompatible:`intel,sedi-uart` + * :dtcompatible:`intel,socfpga-agilex-sip-smc` + * :dtcompatible:`intel,socfpga-reset` + * :dtcompatible:`intel,timeaware-gpio` + + * Removed bindings: + + * ``intel,agilex-socfpga-sip-smc`` + * ``intel,apollo_lake`` + * ``intel,elkhart_lake`` + * ``intel,gna`` + + * Modified bindings: + + * :dtcompatible:`intel,niosv`: + + * new property: ``mmu-type`` + * new property: ``riscv,isa`` + + * :dtcompatible:`intel,adsp-imr`: + + * new property: ``zephyr,memory-attr`` + * property ``zephyr,memory-region-mpu`` enum value changed from ['RAM', 'RAM_NOCACHE', 'FLASH', 'PPB', 'IO', 'EXTMEM'] to None + * property ``zephyr,memory-region-mpu`` deprecation status changed from False to True + + * :dtcompatible:`intel,lpss`: + + * new property: ``dma-parent`` + + * :dtcompatible:`intel,adsp-shim-clkctl`: + + * new property: ``adsp-clkctl-clk-ipll`` + +* Isentek Inc. (isentek): + + * New bindings: + + * :dtcompatible:`isentek,ist8310` + +* Integrated Silicon Solutions Inc. (issi): + + * New bindings: + + * :dtcompatible:`issi,is31fl3216a` + * :dtcompatible:`issi,is31fl3733` + +* ITE Tech. Inc. (ite): + + * New bindings: + + * :dtcompatible:`ite,it8xxx2-sha` + + * Modified bindings: + + * :dtcompatible:`ite,it8xxx2-pinctrl-func`: + + * new property: ``func3-ext`` + * new property: ``func3-ext-mask`` + + * :dtcompatible:`ite,riscv-ite`: + + * new property: ``mmu-type`` + * new property: ``riscv,isa`` + + * :dtcompatible:`ite,enhance-i2c`: + + * new property: ``target-enable`` + * new property: ``target-pio-mode`` + +* Linaro Limited (linaro): + + * New bindings: + + * :dtcompatible:`linaro,ivshmem-ipm` + +* Maxim Integrated Products (maxim): + + * New bindings: + + * :dtcompatible:`maxim,max11102` + * :dtcompatible:`maxim,max11103` + * :dtcompatible:`maxim,max11105` + * :dtcompatible:`maxim,max11106` + * :dtcompatible:`maxim,max11110` + * :dtcompatible:`maxim,max11111` + * :dtcompatible:`maxim,max11115` + * :dtcompatible:`maxim,max11116` + * :dtcompatible:`maxim,max11117` + * :dtcompatible:`maxim,max11253` + * :dtcompatible:`maxim,max11254` + * :dtcompatible:`maxim,max31790` + +* Microchip Technology Inc. (microchip): + + * New bindings: + + * :dtcompatible:`microchip,mcp251xfd` + * :dtcompatible:`microchip,mpfs-i2c` + * :dtcompatible:`microchip,tcn75a` + + * Modified bindings: + + * :dtcompatible:`microchip,xec-pwmbbled`: + + * new property: ``enable-low-power-32k`` + + * :dtcompatible:`microchip,cap1203` (on i2c bus): + + * bus list changed from ['kscan'] to [] + * new property: ``input-codes`` + + * :dtcompatible:`microchip,xec-ps2`: + + * new property: ``wakerx-gpios`` + +* Motorola, Inc. (motorola): + + * Modified bindings: + + * :dtcompatible:`motorola,mc146818`: + + * new property: ``clock-frequency`` + +* Murata Manufacturing Co., Ltd. (murata): + + * New bindings: + + * :dtcompatible:`murata,ncp15wb473` + +* Nordic Semiconductor (nordic): + + * New bindings: + + * :dtcompatible:`nordic,npm1300-led` + * :dtcompatible:`nordic,npm1300-wdt` + + * Removed bindings: + + * ``nordic,nrf-cc310`` + * ``nordic,nrf-cc312`` + + * Modified bindings: + + * :dtcompatible:`nordic,nrf-ccm`: + + * new property: ``headermask-supported`` + + * :dtcompatible:`nordic,nrf-twi`: + + * new property: ``easydma-maxcnt-bits`` + + * :dtcompatible:`nordic,nrf-twim` and :dtcompatible:`nordic,nrf-twis`: + + * new property: ``easydma-maxcnt-bits`` + * new property: ``memory-regions`` + * new property: ``memory-region-names`` + + * :dtcompatible:`nordic,nrf-spi`, :dtcompatible:`nordic,nrf-spis`, and + :dtcompatible:`nordic,nrf-spim`: + + * new property: ``wake-gpios`` + + * :dtcompatible:`nordic,npm1300-charger`: + + * new property: ``thermistor-cold-millidegrees`` + * new property: ``thermistor-cool-millidegrees`` + * new property: ``thermistor-warm-millidegrees`` + * new property: ``thermistor-hot-millidegrees`` + * new property: ``trickle-microvolt`` + * new property: ``term-current-percent`` + * new property: ``vbatlow-charge-enable`` + * new property: ``disable-recharge`` + + * :dtcompatible:`nordic,nrf-uicr`: + + * new property: ``nfct-pins-as-gpios`` + * new property: ``gpio-as-nreset`` + + * :dtcompatible:`nordic,npm1300` (on i2c bus): + + * new property: ``host-int-gpios`` + * new property: ``pmic-int-pin`` + +* Nuclei System Technology (nuclei): + + * Modified bindings: + + * :dtcompatible:`nuclei,bumblebee`: + + * new property: ``mmu-type`` + * new property: ``riscv,isa`` + +* Nuvoton Technology Corporation (nuvoton): + + * New bindings: + + * :dtcompatible:`nuvoton,nct38xx` + * :dtcompatible:`nuvoton,nct38xx-gpio` + * :dtcompatible:`nuvoton,npcx-fiu-nor` + * :dtcompatible:`nuvoton,npcx-fiu-qspi` + * :dtcompatible:`nuvoton,numaker-fmc` + * :dtcompatible:`nuvoton,numaker-gpio` + * :dtcompatible:`nuvoton,numaker-pcc` + * :dtcompatible:`nuvoton,numaker-pinctrl` + * :dtcompatible:`nuvoton,numaker-pwm` + * :dtcompatible:`nuvoton,numaker-rst` + * :dtcompatible:`nuvoton,numaker-scc` + * :dtcompatible:`nuvoton,numaker-spi` + * :dtcompatible:`nuvoton,numaker-uart` + + * Removed bindings: + + * ``nuvoton,nct38xx-gpio`` + * ``nuvoton,npcx-spi-fiu`` + + * Modified bindings: + + * :dtcompatible:`nuvoton,npcx-sha`: + + * new property: ``context-buffer-size`` + + * :dtcompatible:`nuvoton,npcx-adc`: + + * new property: ``vref-mv`` + * removed property: ``threshold-reg-offset`` + + * :dtcompatible:`nuvoton,adc-cmp`: + + * new property: ``thr-sel`` + + * :dtcompatible:`nuvoton,npcx-pcc`: + + * new property: ``pwdwn-ctl-val`` + * property ``clock-frequency`` enum value changed from [100000000, 96000000, 90000000, 80000000, 66000000, 50000000, 48000000, 40000000, 33000000] to [120000000, 100000000, 96000000, 90000000, 80000000, 66000000, 50000000, 48000000] + * property ``ram-pd-depth`` enum value changed from [12, 15] to [8, 12, 15] + +* NXP Semiconductors (nxp): + + * New bindings: + + * :dtcompatible:`nxp,ctimer-pwm` + * :dtcompatible:`nxp,fs26-wdog` + * :dtcompatible:`nxp,imx-flexspi-w956a8mbya` + * :dtcompatible:`nxp,irqsteer-intc` + * :dtcompatible:`nxp,lpdac` + * :dtcompatible:`nxp,mbox-imx-mu` + * :dtcompatible:`nxp,mcux-dcp` + * :dtcompatible:`nxp,mcux-edma-v3` + * :dtcompatible:`nxp,pcf8563` + * :dtcompatible:`nxp,pxp` + * :dtcompatible:`nxp,s32-adc-sar` + * :dtcompatible:`nxp,s32-clock` + * :dtcompatible:`nxp,s32-emios` + * :dtcompatible:`nxp,s32-emios-pwm` + * :dtcompatible:`nxp,s32-gmac` + * :dtcompatible:`nxp,s32-qspi` + * :dtcompatible:`nxp,s32-qspi-device` + * :dtcompatible:`nxp,s32-qspi-nor` + * :dtcompatible:`nxp,s32k3-pinctrl` + * :dtcompatible:`nxp,smartdma` + * :dtcompatible:`nxp,tempmon` + * :dtcompatible:`nxp,vref` + + * Modified bindings: + + * :dtcompatible:`nxp,s32-netc-emdio`: + + * removed property: ``protocol`` + * property ``#address-cells`` const value changed from None to 1 + * property ``#size-cells`` const value changed from None to 0 + * property ``#address-cells`` is now required + * property ``#size-cells`` is now required + + * :dtcompatible:`nxp,mipi-dsi-2l`: + + * property ``nxp,lcdif`` is no longer required + + * :dtcompatible:`nxp,imx-mipi-dsi`: + + * property ``nxp,lcdif`` is no longer required + + * :dtcompatible:`nxp,pca9633` (on i2c bus): + + * new property: ``disable-allcall`` + + * :dtcompatible:`nxp,s32-sys-timer`: + + * removed property: ``clock-frequency`` + * property ``clocks`` is now required + + * :dtcompatible:`nxp,imx-lpspi`: + + * new property: ``data-pin-config`` + + * :dtcompatible:`nxp,s32-spi`: + + * property ``clock-frequency`` is no longer required + * property ``clocks`` is now required + + * :dtcompatible:`nxp,imx-wdog`: + + * pinctrl support + + * :dtcompatible:`nxp,s32-swt`: + + * removed property: ``clock-frequency`` + * property ``clocks`` is now required + + * :dtcompatible:`nxp,lpc-lpadc`: + + * new property: ``nxp,reference-supply`` + + * :dtcompatible:`nxp,kinetis-pit`: + + * new property: ``max-load-value`` + * property ``clocks`` is now required + + * :dtcompatible:`nxp,mcux-edma`: + + * new property: ``dmamux-reg-offset`` + * new property: ``channel-gap`` + * new property: ``irq-shared-offset`` + + * :dtcompatible:`nxp,imx-elcdif`: + + * new property: ``nxp,pxp`` + +* ON Semiconductor Corp. (onnn): + + * New bindings: + + * :dtcompatible:`onnn,ncp5623` + +* Princeton Technology Corp. (ptc): + + * New bindings: + + * :dtcompatible:`ptc,pt6314` + +* Quectel Wireless Solutions Co., Ltd. (quectel): + + * New bindings: + + * :dtcompatible:`quectel,bg95` + +* QuickLogic Corp. (quicklogic): + + * New bindings: + + * :dtcompatible:`quicklogic,eos-s3-pinctrl` + + * Modified bindings: + + * :dtcompatible:`quicklogic,usbserialport-s3b`: + + * pinctrl support + +* Raspberry Pi Foundation (raspberrypi): + + * New bindings: + + * :dtcompatible:`raspberrypi,pico-header` + * :dtcompatible:`raspberrypi,pico-i2c` + * :dtcompatible:`raspberrypi,pico-spi-pio` + * :dtcompatible:`raspberrypi,pico-timer` + +* Raydium Semiconductor Corp. (raydium): + + * New bindings: + + * :dtcompatible:`raydium,rm67162` + +* Renesas Electronics Corporation (renesas): + + * New bindings: + + * :dtcompatible:`renesas,smartbond-lp-osc` + * :dtcompatible:`renesas,smartbond-timer` + + * Modified bindings: + + * :dtcompatible:`renesas,smartbond-flash-controller`: + + * new property: ``read-cs-idle-delay`` + * new property: ``erase-cs-idle-delay`` + +* Smart Battery System (sbs): + + * New bindings: + + * :dtcompatible:`sbs,default-sbs-gauge` + * :dtcompatible:`sbs,sbs-charger` + +* Seeed Technology Co., Ltd (seeed): + + * New bindings: + + * :dtcompatible:`seeed,hm330x` + +* SiFive, Inc. (sifive): + + * Modified bindings: + + * :dtcompatible:`sifive,i2c0`: + + * pinctrl support + +* Silicon Laboratories (silabs): + + * New bindings: + + * :dtcompatible:`silabs,gecko-adc` + +* Sino Wealth Electronic Ltd (sinowealth): + + * New bindings: + + * :dtcompatible:`sinowealth,sh1106` + * :dtcompatible:`sinowealth,sh1106` + +* Sitronix Technology Corporation (sitronix): + + * Modified bindings: + + * :dtcompatible:`sitronix,st7735r` (on spi bus): + + * property ``reset-gpios`` is no longer required + +* Standard Microsystems Corporation (smsc): + + * Modified bindings: + + * :dtcompatible:`smsc,lan91c111-mdio`: + + * removed property: ``protocol`` + * property ``#address-cells`` const value changed from None to 1 + * property ``#size-cells`` const value changed from None to 0 + * property ``#address-cells`` is now required + * property ``#size-cells`` is now required + + * :dtcompatible:`smsc,lan91c111`: + + * new property: ``local-mac-address`` + * new property: ``zephyr,random-mac-address`` + * property ``reg`` is no longer required + +* Synopsys, Inc. (snps): + + * New bindings: + + * :dtcompatible:`snps,dw-timers` + +* Solomon Systech Limited (solomon): + + * Modified bindings: + + * :dtcompatible:`solomon,ssd1306fb` + + * new property: ``inversion-on`` + * new property: ``ready-time-ms`` + +* Sequans Communications (sqn): + + * New bindings: + + * :dtcompatible:`sqn,hwspinlock` + +* STMicroelectronics (st): + + * New bindings: + + * :dtcompatible:`st,stm32-bxcan` + * :dtcompatible:`st,stm32-spi-host-cmd` + * :dtcompatible:`st,stm32f1-rcc` + * :dtcompatible:`st,stm32f3-rcc` + * :dtcompatible:`st,stm32wba-flash-controller` + * :dtcompatible:`st,stm32wba-hse-clock` + * :dtcompatible:`st,stm32wba-pll-clock` + * :dtcompatible:`st,stm32wba-rcc` + * :dtcompatible:`st,stmpe811` + + * Removed bindings: + + * ``st,stm32-can`` + + * Modified bindings: + + * :dtcompatible:`st,stm32-pwm`: + + * new property: ``four-channel-capture-support`` + + * :dtcompatible:`st,stm32f4-adc`: + + * new property: ``st,adc-clock-source`` + * new property: ``st,adc-prescaler`` + * new property: ``st,adc-sequencer`` + * removed property: ``temp-channel`` + * removed property: ``vref-channel`` + * removed property: ``vbat-channel`` + + * :dtcompatible:`st,stm32-adc`: + + * new property: ``st,adc-clock-source`` + * new property: ``st,adc-prescaler`` + * new property: ``st,adc-sequencer`` + * removed property: ``temp-channel`` + * removed property: ``vref-channel`` + * removed property: ``vbat-channel`` + + * :dtcompatible:`st,stm32f1-adc`: + + * new property: ``st,adc-sequencer`` + * removed property: ``temp-channel`` + * removed property: ``vref-channel`` + * removed property: ``vbat-channel`` + + * :dtcompatible:`st,stm32-ospi`: + + * new property: ``io-low-port`` + * new property: ``io-high-port`` + + * :dtcompatible:`st,stm32c0-hsi-clock`: + + * removed property: ``clocks`` + + * :dtcompatible:`st,stm32-hse-clock`: + + * removed property: ``clocks`` + + * :dtcompatible:`st,stm32wl-hse-clock`: + + * removed property: ``clocks`` + + * :dtcompatible:`st,stm32g0-hsi-clock`: + + * removed property: ``clocks`` + + * :dtcompatible:`st,stm32h7-hsi-clock`: + + * removed property: ``clocks`` + + * :dtcompatible:`st,stm32-lse-clock`: + + * removed property: ``clocks`` + + * :dtcompatible:`st,stm32u5-pll-clock`: + + * new property: ``fracn`` + +* Telink Semiconductor (telink): + + * Modified bindings: + + * :dtcompatible:`telink,b91-pwm`: + + * pinctrl support + + * :dtcompatible:`telink,b91`: + + * new property: ``mmu-type`` + * new property: ``riscv,isa`` + + * :dtcompatible:`telink,b91-i2c`: + + * pinctrl support + + * :dtcompatible:`telink,b91-spi`: + + * pinctrl support + + * :dtcompatible:`telink,b91-uart`: + + * pinctrl support + +* Texas Instruments (ti): + + * New bindings: + + * :dtcompatible:`ti,ads1112` + * :dtcompatible:`ti,bq27z746` + * :dtcompatible:`ti,cc13xx-cc26xx-rtc-timer` + * :dtcompatible:`ti,cc13xx-cc26xx-timer` + * :dtcompatible:`ti,cc13xx-cc26xx-timer-pwm` + * :dtcompatible:`ti,cc32xx-pinctrl` + * :dtcompatible:`ti,davinci-gpio` + * :dtcompatible:`ti,davinci-gpio-nexus` + * :dtcompatible:`ti,lp5009` + * :dtcompatible:`ti,lp5012` + * :dtcompatible:`ti,lp5018` + * :dtcompatible:`ti,lp5024` + * :dtcompatible:`ti,lp5030` + * :dtcompatible:`ti,lp5036` + * :dtcompatible:`ti,lp5569` + * :dtcompatible:`ti,tas6422dac` + * :dtcompatible:`ti,tcan4x5x` + * :dtcompatible:`ti,tla2021` + * :dtcompatible:`ti,tmag5170` + * :dtcompatible:`ti,vim` + + * Removed bindings: + + * ``ti,cc13xx-cc26xx-rtc`` + * ``ti,lp503x`` + + * Modified bindings: + + * :dtcompatible:`ti,cc32xx-i2c`: + + * pinctrl support + + * :dtcompatible:`ti,ina230` (on i2c bus): + + * new property: ``alert-config`` + * new property: ``adc-mode`` + * new property: ``vbus-conversion-time-us`` + * new property: ``vshunt-conversion-time-us`` + * new property: ``avg-count`` + * new property: ``rshunt-micro-ohms`` + * removed property: ``rshunt-milliohms`` + * property ``config`` default value changed from None to 0 + * property ``config`` deprecation status changed from False to True + * property ``config`` is no longer required + + * :dtcompatible:`ti,ina237` (on i2c bus): + + * new property: ``adc-mode`` + * new property: ``vbus-conversion-time-us`` + * new property: ``vshunt-conversion-time-us`` + * new property: ``temp-conversion-time-us`` + * new property: ``avg-count`` + * new property: ``high-precision`` + * new property: ``rshunt-micro-ohms`` + * removed property: ``rshunt-milliohms`` + * property ``adc-config`` default value changed from None to 0 + * property ``config`` default value changed from None to 0 + * property ``adc-config`` deprecation status changed from False to True + * property ``config`` deprecation status changed from False to True + * property ``adc-config`` is no longer required + * property ``config`` is no longer required + + * :dtcompatible:`ti,cc32xx-uart`: + + * pinctrl support + +* A stand-in for a real vendor which can be used in examples and tests (vnd): + + * New bindings: + + * :dtcompatible:`vnd,memory-attr` + * :dtcompatible:`vnd,reg-holder-64` + * :dtcompatible:`vnd,reserved-compat` + + * Modified bindings: + + * :dtcompatible:`vnd,serial`: + + * property ``reg`` is no longer required + +* X-Powers (x-powers): + + * New bindings: + + * :dtcompatible:`x-powers,axp192` + * :dtcompatible:`x-powers,axp192-gpio` + * :dtcompatible:`x-powers,axp192-regulator` + +* Xen Hypervisor (xen): + + * New bindings: + + * :dtcompatible:`xen,xen` + + * Removed bindings: + + * ``xen,xen-4.15`` + +* Xilinx (xlnx): + + * New bindings: + + * :dtcompatible:`xlnx,zynqmp-ipi-mailbox` + +* Shenzhen Xptek Technology Co., Ltd (xptek): + + * Modified bindings: + + * :dtcompatible:`xptek,xpt2046` (on spi bus): + + * bus list changed from ['kscan'] to [] + +* Zephyr-specific binding (zephyr): + + * New bindings: + + * :dtcompatible:`zephyr,fake-rtc` + * :dtcompatible:`zephyr,i2c-dump-allowlist` + * :dtcompatible:`zephyr,lvgl-button-input` + * :dtcompatible:`zephyr,lvgl-encoder-input` + * :dtcompatible:`zephyr,lvgl-pointer-input` + * :dtcompatible:`zephyr,mdio-gpio` + * :dtcompatible:`zephyr,native-tty-uart` + * :dtcompatible:`zephyr,ram-disk` + * :dtcompatible:`zephyr,sensing` + * :dtcompatible:`zephyr,sensing-phy-3d-sensor` + + * Removed bindings: + + * ``zephyr,gpio-keys`` + + * Modified bindings: + + * :dtcompatible:`zephyr,mmc-disk` (on sd bus): + + * new property: ``bus-width`` + + * :dtcompatible:`zephyr,bt-hci-spi` (on spi bus): + + * new property: ``controller-data-delay-us`` + + * :dtcompatible:`zephyr,sdhc-spi-slot` (on spi bus): + + * new property: ``pwr-gpios`` + + * :dtcompatible:`zephyr,memory-region`: + + * new property: ``zephyr,memory-attr`` + * property ``zephyr,memory-region-mpu`` enum value changed from ['RAM', 'RAM_NOCACHE', 'FLASH', 'PPB', 'IO', 'EXTMEM'] to None + * property ``zephyr,memory-region-mpu`` deprecation status changed from False to True + * property ``reg`` is now required + +Libraries / Subsystems +********************** + +* Management + + * Introduced MCUmgr client support with handlers for img_mgmt and os_mgmt. + + * Added response checking to MCUmgr's :c:enumerator:`MGMT_EVT_OP_CMD_RECV` + notification callback to allow applications to reject MCUmgr commands. + + * MCUmgr SMP version 2 error translation (to legacy MCUmgr error code) is now + supported in function handlers by setting ``mg_translate_error`` of + :c:struct:`mgmt_group` when registering a group. See + :c:type:`smp_translate_error_fn` for function details. + + * Fixed an issue with MCUmgr img_mgmt group whereby the size of the upload in + the initial packet was not checked. + + * Fixed an issue with MCUmgr fs_mgmt group whereby some status codes were not + checked properly, this meant that the error returned might not be the + correct error, but would only occur in situations where an error was + already present. + + * Fixed an issue whereby the SMP response function did not check to see if + the initial zcbor map was created successfully. + + * Fixes an issue with MCUmgr shell_mgmt group whereby the length of a + received command was not properly checked. + + * Added optional mutex locking support to MCUmgr img_mgmt group, which can + be enabled with :kconfig:option:`CONFIG_MCUMGR_GRP_IMG_MUTEX`. + + * Added MCUmgr settings management group, which allows for manipulation of + zephyr settings from a remote device, see :ref:`mcumgr_smp_group_3` for + details. + + * Added :kconfig:option:`CONFIG_MCUMGR_GRP_IMG_ALLOW_CONFIRM_NON_ACTIVE_IMAGE_SECONDARY` + and :kconfig:option:`CONFIG_MCUMGR_GRP_IMG_ALLOW_CONFIRM_NON_ACTIVE_IMAGE_ANY` + that allow to control whether MCUmgr client will be allowed to confirm + non-active images. + + * Added :kconfig:option:`CONFIG_MCUMGR_GRP_IMG_ALLOW_ERASE_PENDING` that allows + to erase slots pending for next boot, that are not revert slots. + + * Added ``user_data`` as an optional field to :c:struct:`mgmt_handler` when + :kconfig:option:`CONFIG_MCUMGR_MGMT_HANDLER_USER_DATA` is enabled. + + * Added optional ``force`` parameter to os mgmt reset command, this can be checked in the + :c:enum:`MGMT_EVT_OP_OS_MGMT_RESET` notification callback whose data structure is + :c:struct:`os_mgmt_reset_data`. + + * Added configurable number of SMP encoding levels via + :kconfig:option:`CONFIG_MCUMGR_SMP_CBOR_MIN_ENCODING_LEVELS`, which automatically increments + minimum encoding levels for in-tree groups if :kconfig:option:`CONFIG_ZCBOR_CANONICAL` is + enabled. + + * Added STM32 SPI backend for EC Host command protocol. + + * Fixed settings_mgmt returning unknown error instead of invalid key specified error. + + * Fixed fs_mgmt returning parameter too large error instead of file is empty error when + attempting to hash/checksum a file which is empty. + +* File systems + + * Added support for ext2 file system. + * Added support of mounting littlefs on the block device from the shell/fs. + * Added alignment parameter to FS_LITTLEFS_DECLARE_CUSTOM_CONFIG macro, it can speed up read/write + operation for SDMMC devices in case when we align buffers on CONFIG_SDHC_BUFFER_ALIGNMENT, + because we can avoid extra copy of data from card bffer to read/prog buffer. + +* Random + + * ``CONFIG_XOROSHIRO_RANDOM_GENERATOR``, deprecated a long time ago, is finally removed. + +* Retention + + * Added the :ref:`blinfo_api` subsystem. + + * Added support for allowing mutex support to be forcibly disabled with + :kconfig:option:`CONFIG_RETENTION_MUTEX_FORCE_DISABLE`. + +* Binary descriptors + + * Added the :ref:`binary_descriptors` (``bindesc``) subsystem. + +* POSIX API + + * Added dynamic thread stack support for :c:func:`pthread_create` + * Fixed :c:func:`stat` so that it returns file stats instead of filesystem stats + * Implemented :c:func:`pthread_barrierattr_destroy`, :c:func:`pthread_barrierattr_getpshared`, + :c:func:`pthread_barrierattr_init`, :c:func:`pthread_barrierattr_setpshared`, + :c:func:`pthread_condattr_destroy`, :c:func:`pthread_condattr_init`, + :c:func:`pthread_mutexattr_destroy`, :c:func:`pthread_mutexattr_init`, :c:func:`uname`, + :c:func:`sigaddset`, :c:func:`sigdelset`, :c:func:`sigemptyset`, :c:func:`sigfillset`, + :c:func:`sigismember`, :c:func:`strsignal`, :c:func:`pthread_spin_destroy`, + :c:func:`pthread_spin_init`, :c:func:`pthread_spin_lock`, :c:func:`pthread_spin_trylock`, + :c:func:`pthread_spin_unlock`, :c:func:`timer_getoverrun`, :c:func:`pthread_condattr_getclock`, + :c:func:`pthread_condattr_setclock`, :c:func:`clock_nanosleep` + * Added support for querying the number of bytes available to read via the + :c:macro:`FIONREAD` request to :c:func:`ioctl` + * Added :kconfig:option:`CONFIG_FDTABLE` to conditionally compile file descriptor table + * Added logging to POSIX threads, mutexes, and condition variables + * Fixed :c:func:`poll` issue with event file descriptors + +* LoRa/LoRaWAN + + * Updated ``loramac-node`` from v4.6.0 to v4.7.0 + +* CAN ISO-TP + + * Added support for CAN FD. + +* RTIO + + * Added atomic completion counter fixing a race caught by unit tests + * Added a :c:macro:`RTIO_SQE_NO_RESPONSE` flag for submissions when no completion notification + is needed + * Removed unused Kconfig options for different executors + +* ZBus + + * Changed channels' and observers' metadata to comply with the data/config approach. ZBus stores + immutable config in iterable sections in Flash and the mutable portion of data in the RAM. + * The relationship between channels and observers is mapped using a new entity called + observation. The observation enables us to increase the granularity of masking observation. + Developers can mask individual observations, disable the observer, or use runtime observers. + * Added API :c:macro:`ZBUS_CHAN_ADD_OBS` macro for adding post-definition static observers of a + channel. That can replace the runtime observer feature, enabling developers to add static + observers after the channel definition in different files. It increases the composability of + the system using ZBus, making post-definition channel observation rely on the stack instead of + the heap. + * Added a new type of observer called Message Subscriber. ZBus' VDED will send a copy of the + message during the publication/notification process. + * Changed the VDED delivery sequence. Check the ref:`documentation`. + * ZBus runtime observers now rely on the heap instead of a memory pool. + * Added new iterable section iterators APIs (for channels and observers) can now receive a + ``user_data`` pointer to keep context between the function calls. + * Added APIs :c:macro:`ZBUS_LISTENER_DEFINE_WITH_ENABLE` and + :c:macro:`ZBUS_SUBSCRIBER_DEFINE_WITH_ENABLE` that allows developers to define observers' + statuses (enabled/disabled) programmatically. With the API, developers can create observers + initially disabled and enable them in runtime. + +* Power management + + * Added :kconfig:option:`CONFIG_PM_NEED_ALL_DEVICES_IDLE`. When this + option is set the power management will keep the system active + if there is any device busy. + * :c:func:`pm_device_runtime_get` can be called from ISR now. + * Power states can be disabled directly in devicetree doing ``status = "disabled";`` + * Added the helper function, :c:func:`pm_device_driver_init`, for + initializing devices into a specific power state. + +* Modem modules + + * Added the :ref:`modem` subsystem. + +HALs +**** + +* Nordic + + * Updated nrfx to version 3.1.0. + +* Nuvoton + + * Added Nuvoton NuMaker M46x + +MCUboot +******* + + * Added :kconfig:option:`CONFIG_MCUBOOT_BOOTLOADER_NO_DOWNGRADE` + that allows to inform application that the on-board MCUboot has been configured + with downgrade prevention enabled. This option is automatically selected for + DirectXIP mode and is available for both swap modes. + + * Added :kconfig:option:`CONFIG_MCUBOOT_BOOTLOADER_MODE_OVERWRITE_ONLY` + that allows to inform application that the on-board MCUboot will overwrite + the primary slot with secondary slot contents, without saving the original + image in primary slot. + + * Fixed issue with serial recovery not showing image details for decrypted images. + + * Fixed issue with serial recovery in single slot mode wrongly iterating over 2 image slots. + + * Fixed an issue with boot_serial repeats not being processed when output was sent, this would + lead to a divergence of commands whereby later commands being sent would have the previous + command output sent instead. + + * Fixed an issue with the boot_serial zcbor setup encoder function wrongly including the buffer + address in the size which caused serial recovery to fail on some platforms. + + * Fixed wrongly building in optimize for debug mode by default, this saves a significant amount + of flash space. + + * Fixed issue with serial recovery use of MBEDTLS having undefined operations which led to usage + faults when the secondary slot image was encrypted. + + * Fixed issue with bootutil asserting on maximum alignment in non-swap modes. + + * Added error output when flash device fails to open and asserts are disabled, which will now + panic the bootloader. + + * Added currently running slot ID and maximum application size to shared data function + definition. + + * Added P384 and SHA384 support to imgtool. + + * Added optional serial recovery image state and image set state commands. + + * Added ``dumpinfo`` command for signed image parsing in imgtool. + + * Added ``getpubhash`` command to dump the sha256 hash of the public key in imgtool. + + * Added support for ``getpub`` to print the output to a file in imgtool. + + * Added support for dumping the raw versions of the public keys in imgtool. + + * Added support for sharing boot information with application via retention subsystem. + + * Added support for serial recovery to read and handle encrypted seondary slot partitions. + + * Removed ECDSA P224 support. + + * Removed custom image list boot serial extension support. + + * Reworked boot serial extensions so that they can be used by modules or from user repositories + by switching to iterable sections. + + * Reworked image encryption support for Zephyr, static dummy key files are no longer in the code, + a pem file must be supplied to extract the private and public keys. The Kconfig menu has + changed to only show a single option for enabling encryption and selecting the key file. + + * Reworked the ECDSA256 TLV curve agnostic and renamed it to ``ECDSA_SIG``. + + * CDDL auto-generated function code has been replaced with zcbor function calls, this now allows + the parameters to be supplied in any order. + + * The MCUboot version in this release is version ``2.0.0+0-rc1``. + +Nanopb +****** + + * Changed project status to maintained. + + * Added a separate nanopb.cmake file to be included by applications. + + * Added helper cmake function ``zephyr_nanopb_sources`` to simplify ``.proto`` file inclusion. + +LVGL +**** + + * Changed project status to maintained. + + * Library has been updated to release v8.3.7. + + * Added ``zephyr,lvgl-{pointer,button,encoder}-input`` pseudo device bindings. + :kconfig:option:`CONFIG_LV_Z_KSCAN_POINTER` is still supported but touch controllers + need a :dtcompatible:`zephyr,kscan-input` child node to emit input events. + + * LVGL shell allows for monkey testing (requires :kconfig:option:`CONFIG_LV_USE_MONKEY`) + and inspecting memory usage. + +Trusted Firmware-A +****************** + +* Updated to TF-A 2.9.0. + +Documentation +************* + +* Upgraded Sphinx to 6.2 + +Tests and Samples +***************** + +* Created common sample for file systems (`fs_sample`). It originates from sample for FAT + (`fat_fs`) and supports both FAT and ext2 file systems. + +* Created the zbus confirmed channel sample to demonstrate how to implement a delivery-guaranteed + channel using subscribers. -Known Issues -************ +* Created the zbus message subscriber sample to demonstrate how to use message subscribers. diff --git a/doc/releases/release-notes-3.6.rst b/doc/releases/release-notes-3.6.rst new file mode 100644 index 00000000000..676e16fa77c --- /dev/null +++ b/doc/releases/release-notes-3.6.rst @@ -0,0 +1,297 @@ +:orphan: + +.. _zephyr_3.6: + +Zephyr 3.6.0 (Working Draft) +############################ + +We are pleased to announce the release of Zephyr version 3.6.0. + +Major enhancements with this release include: + +An overview of the changes required or recommended when migrating your application from Zephyr +v3.5.0 to Zephyr v3.6.0 can be found in the separate :ref:`migration guide`. + +The following sections provide detailed lists of changes by component. + +Security Vulnerability Related +****************************** +The following CVEs are addressed by this release: + +More detailed information can be found in: +https://docs.zephyrproject.org/latest/security/vulnerabilities.html + +Kernel +****** + +Architectures +************* + +* ARC + +* ARM + +* ARM64 + +* RISC-V + +* Xtensa + +* x86 + +* POSIX + +Bluetooth +********* + +* Audio + +* Direction Finding + +* Host + +* Mesh + +* Controller + +Boards & SoC Support +******************** + +* Added support for these SoC series: + +* Removed support for these SoC series: + +* Made these changes in other SoC series: + +* Added support for these ARC boards: + +* Added support for these ARM boards: + +* Added support for these ARM64 boards: + +* Added support for these RISC-V boards: + +* Added support for these X86 boards: + +* Added support for these Xtensa boards: + +* Added support for these POSIX boards: + +* Made these changes for ARC boards: + +* Made these changes for ARM boards: + +* Made these changes for ARM64 boards: + +* Made these changes for RISC-V boards: + +* Made these changes for X86 boards: + +* Made these changes for Xtensa boards: + +* Made these changes for POSIX boards: + +* Removed support for these ARC boards: + +* Removed support for these ARM boards: + +* Removed support for these ARM64 boards: + +* Removed support for these RISC-V boards: + +* Removed support for these X86 boards: + +* Removed support for these Xtensa boards: + +* Made these changes in other boards: + +* Added support for these following shields: + +Build system and infrastructure +******************************* + +- Dropped the ``COMPAT_INCLUDES`` option, it was unused since 3.0. + +Drivers and Sensors +******************* + +* ADC + +* CAN + +* Clock control + +* Counter + +* DAC + +* Disk + +* Display + +* DMA + +* EEPROM + +* Entropy + +* Ethernet + +* Flash + +* GPIO + +* I2C + +* I2S + +* I3C + +* IEEE 802.15.4 + +* Interrupt Controller + +* Input + +* PCIE + +* ACPI + +* Pin control + +* PWM + +* Regulators + +* Reset + +* Retained memory + +* RTC + +* SDHC + +* Sensor + +* Serial + +* SPI + +* Timer + +* USB + +* WiFi + +Networking +********** + +* CoAP: + +* Connection Manager: + +* DHCP: + +* Ethernet: + +* gPTP: + +* ICMP: + +* IPv6: + +* LwM2M: + +* Misc: + +* MQTT-SN: + +* OpenThread: + +* PPP: + +* Sockets: + +* TCP: + +* TFTP: + +* WebSocket + +* Wi-Fi: + + +USB +*** + +Devicetree +********** + +API +=== + +Bindings +======== + +Libraries / Subsystems +********************** + +* Management + + * Fixed an issue in MCUmgr image management whereby erasing an already erased slot would return + an unknown error, it now returns success. + + * Fixed MCUmgr UDP transport structs being statically initialised, this results in about a + ~5KiB flash saving. + + * Fixed an issue in MCUmgr which would cause a user data buffer overflow if the UDP transport was + enabled on IPv4 only but IPv6 support was enabled in the kernel. + + * Implemented datetime functionality in MCUmgr OS management group, this makes use of the RTC + driver API. + +* File systems + +* Modem modules + +* Power management + +* Random + +* Retention + +* Binary descriptors + +* POSIX API + +* LoRa/LoRaWAN + +* CAN ISO-TP + +* RTIO + +* ZBus + +HALs +**** + +MCUboot +******* + +Nanopb +****** + +LVGL +**** + +Trusted Firmware-A +****************** + +Documentation +************* + +Tests and Samples +***************** + +* Fixed an issue in :zephyr:code-sample:`smp-svr` sample whereby if USB was already initialised, + application would fail to boot properly. diff --git a/doc/requirements.txt b/doc/requirements.txt index 2d90048e16f..45bb461e518 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -8,6 +8,7 @@ sphinxcontrib-svg2pdfconverter pygments>=2.9 sphinx-notfound-page sphinx-copybutton +sphinx-togglebutton # YAML validation. Used by zephyr_module. PyYAML>=5.1 diff --git a/doc/security/reporting.rst b/doc/security/reporting.rst index c3c39677175..376237fe938 100644 --- a/doc/security/reporting.rst +++ b/doc/security/reporting.rst @@ -107,6 +107,8 @@ within the Zephyr project to fix the issues, and 60 days for external parties building products using Zephyr to be able to apply and distribute these fixes. +.. _vulnerability_fix_recommendations: + Fixes to the code shall be made through pull requests PR in the Zephyr project github. Developers shall make an attempt to not reveal the sensitive nature of what is being fixed, and shall not refer to CVE @@ -180,7 +182,12 @@ following releases: The developer of the fix shall be responsible for any necessary backports, and apply them to any of the above listed release branches, unless the fix does not apply (the vulnerability was introduced after -this release was made). +this release was made). All recommendations for +:ref:`vulnerability fixes ` apply +for backport pull requests (and associated issues). Additionally, it is +recommended that the developer privately informs the responsible +release manager that the backport pull request and issue are addressing +a vulnerability. Backports will be tracked on the security advisory. diff --git a/doc/security/secure-coding.rst b/doc/security/secure-coding.rst index a22859d78da..fe712eea82c 100644 --- a/doc/security/secure-coding.rst +++ b/doc/security/secure-coding.rst @@ -207,7 +207,7 @@ scripting, missing authentication, and missing authorization. See the `CWE/SANS top 25`_ or `OWASP Top 10`_ for commonly used lists. .. Turn this into something specific. Can we find examples of - mistakes. Perhaps an example of things Coverity has sent us. + mistakes. Perhaps an example of things static analysis tool has sent us. .. _CWE/SANS top 25: http://cwe.mitre.org/top25/ diff --git a/doc/security/security-overview.rst b/doc/security/security-overview.rst index e02f42b5916..6ed15fa55ba 100644 --- a/doc/security/security-overview.rst +++ b/doc/security/security-overview.rst @@ -105,8 +105,8 @@ The three major security measures currently implemented are: requires all code to be reviewed before being committed to the common repository. Furthermore, the reuse of proven building blocks such as network stacks increases the overall quality level - and guarantees stable APIs. Static code analyses are provided by - Coverity Scan. + and guarantees stable APIs. Static code analyses provide additional + quality checks. - **Execution Protection** including thread separation, stack and memory protection is currently available in the upstream @@ -180,17 +180,15 @@ the experience of the reviewer. Especially for security relevant code, concrete and detailed guidelines need to be developed and aligned with the developers (see: :ref:`secure code`). -Static code analyses are run on the Zephyr code tree on a regular basis -using the open source Coverity Scan tool. Coverity Scan now includes -complexity analysis. +Static code analyses are run on the Zephyr code tree on a regular basis, +see :ref:`static_analysis`. -Bug and issue tracking and management is performed using Jira. The term +Bug and issue tracking and management is performed using Github. The term "survivability" was coined to cover pro-active security tasks such as -security issue categorization and management. Initial effort has been -started on the definition of vulnerability categorization and mitigation -processes within Jira. +security issue categorization and management. A problem identified as +vulnerability is managed within Github security advisories. -Issues determined by Coverity should have more stringent reviews before +Issues determined by static analyses should have more stringent reviews before they are closed as non-issues (at least another person educated in security processes need to agree on non-issue before closing). diff --git a/doc/security/vulnerabilities.rst b/doc/security/vulnerabilities.rst index 92ccc0f3a7d..61d0d25f618 100644 --- a/doc/security/vulnerabilities.rst +++ b/doc/security/vulnerabilities.rst @@ -1157,6 +1157,9 @@ This has been fixed in main for v3.0.0 - `PR 42167 fix for v2.7.0 `_ +CVE-2022 +======== + CVE-2022-0553 ------------- @@ -1264,6 +1267,9 @@ DoS: Invalid Initialization in le_read_buffer_size_complete() - `Zephyr project bug tracker GHSA-w525-fm68-ppq3 `_ +CVE-2023 +======== + CVE-2023-0396 ------------- @@ -1339,6 +1345,144 @@ This has been fixed in main for v3.4.0 - `PR 56709 fix for main `_ +CVE-2023-3725 +------------- + +Potential buffer overflow vulnerability in the Zephyr CANbus subsystem. + +- `Zephyr project bug tracker GHSA-2g3m-p6c7-8rr3 + `_ + +This has been fixed in main for v3.5.0 + +- `PR 61502 fix for main + `_ + +- `PR 61518 fix for 3.4 + `_ + +- `PR 61517 fix for 3.3 + `_ + +- `PR 61516 fix for 2.7 + `_ + +CVE-2023-4257 +------------- + +Unchecked user input length in the Zephyr WiFi shell module can cause +buffer overflows. + +- `Zephyr project bug tracker GHSA-853q-q69w-gf5j + `_ + +This has been fixed in main for v3.5.0 + +- `PR 605377 fix for main + `_ + +- `PR 61383 fix for 3.4 + `_ + +CVE-2023-4258 +------------- + +bt: mesh: vulnerability in provisioning protocol implementation on provisionee side + +- `Zephyr project bug tracker GHSA-m34c-cp63-rwh7 + `_ + +This has been fixed in main for v3.5.0 + +- `PR 59467 fix for main + `_ + +- `PR 60078 fix for 3.4 + `_ + +- `PR 60079 fix for 3.3 + `_ + +CVE-2023-4259 +------------- + +Buffer overflow vulnerabilities in the Zephyr eS-WiFi driver + +- `Zephyr project bug tracker GHSA-gghm-c696-f4j4 + `_ + +This has been fixed in main for v3.5.0 + +- `PR 63074 fix for main + `_ + +- `PR 63750 fix for main + `_ + +CVE-2023-4260 +------------- + +Off-by-one buffer overflow vulnerability in the Zephyr FS subsystem + +- `Zephyr project bug tracker GHSA-gj27-862r-55wh + `_ + +This has been fixed in main for v3.5.0 + +- `PR 63079 fix for main + `_ + +CVE-2023-4262 +------------- + +Potential buffer overflow vulnerabilities in the Zephyr Mgmt subsystem + +- `Zephyr project bug tracker GHSA-56p9-5p3v-hhrc + `_ + +- This issue has not been fixed. + +CVE-2023-4263 +------------- + +Potential buffer overflow vulnerability in the Zephyr IEEE 802.15.4 nRF 15.4 driver. + +- `Zephyr project bug tracker GHSA-rf6q-rhhp-pqhf + `_ + +This has been fixed in main for v3.5.0 + +- `PR 60528 fix for main + `_ + +- `PR 61384 fix for 3.4 + `_ + +- `PR 61216 fix for 2.7 + `_ + +CVE-2023-4264 +------------- + +Potential buffer overflow vulnerabilities in the Zephyr Bluetooth subsystem + +- `Zephyr project bug tracker GHSA-rgx6-3w4j-gf5j + `_ + +This has been fixed in main for v3.5.0 + +- `PR 58834 fix for main + `_ + +- `PR 60465 fix for main + `_ + +- `PR 61845 fix for main + `_ + +- `PR 61385 fix for 3.4 + `_ + CVE-2023-4265 ------------- @@ -1353,3 +1497,75 @@ This has been fixed in main for v3.4.0 `_ - `PR 59018 fix for main `_ + +CVE-2023-4424 +------------- + +Under embargo until 2023/11/01 + +CVE-2023-5055 +------------- + +Under embargo until 2023/11/01 + +CVE-2023-5139 +------------- + +Potential buffer overflow vulnerability in the Zephyr STM32 Crypto driver. + +- `Zephyr project bug tracker GHSA-rhrc-pcxp-4453 + `_ + +This has been fixed in main for v3.5.0 + +- `PR 61839 fix for main + `_ + +CVE-2023-5184 +------------- + +Potential signed to unsigned conversion errors and buffer overflow +vulnerabilities in the Zephyr IPM driver + +- `Zephyr project bug tracker GHSA-8x3p-q3r5-xh9g + `_ + +This has been fixed in main for v3.5.0 + +- `PR 63069 fix for main + `_ + +CVE-2023-5563 +------------- + +The SJA1000 CAN controller driver backend automatically attempts to recover +from a bus-off event when built with CONFIG_CAN_AUTO_BUS_OFF_RECOVERY=y. This +results in calling k_sleep() in IRQ context, causing a fatal exception. + +- `Zephyr project bug tracker GHSA-98mc-rj7w-7rpv + `_ + +This has been fixed in main for v3.5.0 + +- `PR 63713 fix for main + `_ + +- `PR 63718 fix for 3.4 + `_ + +- `PR 63717 fix for 3.3 + `_ + +CVE-2023-5753 +------------- + +Potential buffer overflow vulnerabilities in the Zephyr Bluetooth +subsystem source code when asserts are disabled. + +- `Zephyr project bug tracker GHSA-hmpr-px56-rvww + `_ + +This has been fixed in main for v3.5.0 + +- `PR 63605 fix for main + `_ diff --git a/doc/services/binary_descriptors/index.rst b/doc/services/binary_descriptors/index.rst new file mode 100644 index 00000000000..ef44b8265af --- /dev/null +++ b/doc/services/binary_descriptors/index.rst @@ -0,0 +1,125 @@ +.. _binary_descriptors: + +Binary Descriptors +################## + +Binary Descriptors are constant data objects storing information about the binary executable. +Unlike "regular" constants, binary descriptors are linked to a known offset in the binary, making +them accesible to other programs, such as a different image running on the same device or a host tool. +A few examples of constants that would make useful binary descriptors are: kernel version, app version, +build time, compiler version, environment variables, compiling host name, etc. + +Binary descriptors are created by using the ``DEFINE_BINDESC_*`` macros. For example: + +.. code-block:: c + + #include + + BINDESC_STR_DEFINE(my_string, 2, "Hello world!"); // Unique ID is 2 + +``my_string`` could then be accessed using: + +.. code-block:: c + + printk("my_string: %s\n", BINDESC_GET_STR(my_string)); + +But it could also be retrieved by ``west bindesc``: + +.. code-block:: bash + + $ west bindesc custom_search STR 2 build/zephyr/zephyr.bin + "Hello world!" + +Internals +********* +Binary descriptors are implemented with a TLV (tag, length, value) header linked +to a known offset in the binary image. This offset may vary between architectures, +but generally the descriptors are linked as close to the beginning of the image as +possible. In architectures where the image must begin with a vector table (such as +ARM), the descriptors are linked right after the vector table. The reset vector points +to the beginning of the text section, which is after the descriptors. In architectures +where the image must begin with executable code (e.g. x86), a jump instruction is injected at +the beginning of the image, in order to skip over the binary descriptors, which are right +after the jump instruction. + +Each tag is a 16 bit unsigned integer, where the most significant nibble (4 bits) is the type +(currently uint, string or bytes), and the rest is the ID. The ID is globally unique to each +descriptor. For example, the ID of the app version string is ``0x800``, and a string +is denoted by 0x1, making the app version tag ``0x1800``. The length is a 16 bit +number equal to the length of the data in bytes. The data is the actual descriptor +value. All binary descriptor numbers (magic, tags, uints) are laid out in memory +in the endianness native to the SoC. ``west bindesc`` assumes little endian by default, +so if the image belongs to a big endian SoC, the appropriate flag should be given to the +tool. + +The binary descriptor header starts with the magic number ``0xb9863e5a7ea46046``. It's followed +by the TLVs, and ends with the ``DESCRIPTORS_END`` (``0xffff``) tag. The tags are +always aligned to 32 bits. If the value of the previous descriptor had a non-aligned +length, zero padding will be added to ensure that the current tag is aligned. + +Putting it all together, here is what the example above would look like in memory +(of a little endian SoC): + +.. code-block:: + + 46 60 a4 7e 5a 3e 86 b9 02 10 0d 00 48 65 6c 6c 6f 20 77 6f 72 6c 64 21 00 00 00 00 ff ff + | magic | tag |length| H e l l o w o r l d ! | pad | end | + +Usage +***** +Binary descriptors are always created by the ``BINDESC_*_DEFINE`` macros. As shown in +the example above, a descriptor can be generated from any string or integer, with any +ID. However, it is recommended to comply with the standard tags defined in +``include/zephyr/bindesc.h``, as that would have the following benefits: + + 1. The ``west bindesc`` tool would be able to recognize what the descriptor means and + print a meaningful tag + 2. It would enforce consistency between various apps from various sources + 3. It allows upstream-ability of descriptor generation (see Standard Descriptors) + +To define a descriptor with a standard tag, just use the tags included from ``bindesc.h``: + +.. code-block:: c + + #include + + BINDESC_STR_DEFINE(app_version, BINDESC_ID_APP_VERSION_STRING, "1.2.3"); + +Standard Descriptors +==================== +Some descriptors might be trivial to implement, and could therefore be implemented +in a standard way in upstream Zephyr. These could then be enabled via Kconfig, instead +of requiring every user to reimplement them. These include build times, kernel version, +and host info. For example, to add the build date and time as a string, the following +configs should be enabled: + +.. code-block:: kconfig + + # Enable binary descriptors + CONFIG_BINDESC=y + + # Enable definition of binary descriptors + CONFIG_BINDESC_DEFINE=y + + # Enable default build time binary descriptors + CONFIG_BINDESC_DEFINE_BUILD_TIME=y + CONFIG_BINDESC_BUILD_DATE_TIME_STRING=y + +To avoid collisions with user defined descriptors, the standard descriptors were alloted +the range between ``0x800-0xfff``. This leaves ``0x000-0x7ff`` to users. +For more information read the ``help`` sections of these Kconfig symbols. +By convention, each Kconfig symbol corresponds to a binary descriptor whose +name is the Kconfig name (with ``CONFIG_BINDESC_`` removed) in lower case. For example, +``CONFIG_BINDESC_KERNEL_VERSION_STRING`` creates a descriptor that can be +accessed using ``BINDESC_GET_STR(kernel_version_string)``. + +west bindesc tool +================= +``west`` is able to parse and display binary descriptors from a given executable image. + +For more information refer to ``west bindesc --help`` or the :ref:`documentation`. + +API Reference +************* + +.. doxygengroup:: bindesc_define diff --git a/doc/services/debugging/gdbstub.rst b/doc/services/debugging/gdbstub.rst index 5b702d95698..50b830fb5b8 100644 --- a/doc/services/debugging/gdbstub.rst +++ b/doc/services/debugging/gdbstub.rst @@ -87,8 +87,9 @@ Using Serial Backend Example ******* -This is an example using ``samples/subsys/debug/gdbstub`` to demonstrate -how GDB stub works. +This is an example to demonstrate how GDB stub works. +You can also refer to ``tests/subsys/debug/gdbstub`` +for its implementation as a Twister test. #. Open two terminal windows. diff --git a/doc/services/device_mgmt/mcumgr.rst b/doc/services/device_mgmt/mcumgr.rst index 568525ba5d1..f868aaceb17 100644 --- a/doc/services/device_mgmt/mcumgr.rst +++ b/doc/services/device_mgmt/mcumgr.rst @@ -30,7 +30,7 @@ systems. The management subsystem is located in :zephyr_file:`subsys/mgmt/` inside of the Zephyr tree. -Additionally, there is a :ref:`sample ` that provides +Additionally, there is a :zephyr:code-sample:`sample ` sample that provides management functionality over BLE and serial. .. _mcumgr_cli: diff --git a/doc/services/device_mgmt/ota.rst b/doc/services/device_mgmt/ota.rst index 737b957c082..30a6a5b7cbc 100644 --- a/doc/services/device_mgmt/ota.rst +++ b/doc/services/device_mgmt/ota.rst @@ -44,7 +44,7 @@ REST api to detect firmware updates. When a new update is detected, the binary is downloaded and installed. MCUboot can be used to verify the signature before upgrading the firmware. -There is a :ref:`hawkbit-api-sample` included in the +There is a :zephyr:code-sample:`hawkbit-api` sample included in the Zephyr :ref:`mgmt-samples` section. UpdateHub @@ -55,7 +55,7 @@ be manually triggered or monitored via polling. When a new update is detected, the binary is downloaded and installed. MCUboot can be used to verify the signature before upgrading the firmware. -There is an :ref:`updatehub_fota_sample` included in the Zephyr +There is an :zephyr:code-sample:`updatehub-fota` sample included in the Zephyr :ref:`mgmt-samples` section. SMP Server @@ -66,7 +66,7 @@ Bluetooth Low Energy (BLE) or UDP. :ref:`mcu_mgr` is used to send a signed firmware binary to the remote device where it is verified by MCUboot before the upgrade occurs. -There is an :ref:`smp_svr_sample` included in the Zephyr :ref:`mgmt-samples` +There is an :zephyr:code-sample:`smp-svr` sample included in the Zephyr :ref:`mgmt-samples` section. Lightweight M2M (LWM2M) @@ -74,7 +74,7 @@ Lightweight M2M (LWM2M) The :ref:`lwm2m_interface` protocol includes support for firmware update via :kconfig:option:`CONFIG_LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT`. Devices securely -connect to an LwM2M server using DTLS. An :ref:`lwm2m-client-sample` sample is +connect to an LwM2M server using DTLS. A :zephyr:code-sample:`lwm2m-client` sample is available but it does not demonstrate the firmware update feature. .. _MCUboot bootloader: https://mcuboot.com/ diff --git a/doc/services/device_mgmt/smp_groups/smp_group_0.rst b/doc/services/device_mgmt/smp_groups/smp_group_0.rst index 53907f33bcc..7fb91463e33 100644 --- a/doc/services/device_mgmt/smp_groups/smp_group_0.rst +++ b/doc/services/device_mgmt/smp_groups/smp_group_0.rst @@ -20,7 +20,7 @@ OS management group defines following commands: +-------------------+-----------------------------------------------+ | ``3`` | Memory pool statistics | +-------------------+-----------------------------------------------+ - | ``4`` | Date-time string; unimplemented by Zephyr | + | ``4`` | Date-time string | +-------------------+-----------------------------------------------+ | ``5`` | System reset | +-------------------+-----------------------------------------------+ @@ -64,7 +64,7 @@ where: :align: center +-----------------------+---------------------------------------------------+ - | "d" | string to be replied by echo service | + | "d" | string to be replied by echo service. | +-----------------------+---------------------------------------------------+ Echo response @@ -93,23 +93,44 @@ CBOR data of successful response: In case of error the CBOR data takes the form: -.. code-block:: none +.. tabs:: - { - (str)"rc" : (int) - } + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + } where: .. table:: :align: center - +-----------------------+-----------------------------------------------+ - | "r" | Replying echo string | - +-----------------------+-----------------------------------------------+ - | "rc" | :c:enum:`mcumgr_err_t` | - | | only appears if non-zero (error condition). | - +-----------------------+-----------------------------------------------+ + +------------------+-------------------------------------------------------------------------+ + | "r" | replying echo string. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ Task statistics command *********************** @@ -170,41 +191,62 @@ CBOR data of successful response: In case of error the CBOR data takes the form: -.. code-block:: none +.. tabs:: - { - (str)"rc" : (int) - } + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + } where: .. table:: :align: center - +-----------------------+-----------------------------------------------+ - | | string identifying task | - +-----------------------+-----------------------------------------------+ - | "prio" | task priority | - +-----------------------+-----------------------------------------------+ - | "tid" | numeric task ID | - +-----------------------+-----------------------------------------------+ - | "state" | numeric task state | - +-----------------------+-----------------------------------------------+ - | "stkuse" | task's/thread's stack usage | - +-----------------------+-----------------------------------------------+ - | "stksiz" | task's/thread's stack size | - +-----------------------+-----------------------------------------------+ - | "cswcnt" | task's/thread's context switches | - +-----------------------+-----------------------------------------------+ - | "runtime" | task's/thread's runtime in "ticks" | - +-----------------------+-----------------------------------------------+ - | "last_checkin" | set to 0 by Zephyr | - +-----------------------+-----------------------------------------------+ - | "next_checkin" | set to 0 by Zephyr | - +-----------------------+-----------------------------------------------+ - | "rc" | :c:enum:`mcumgr_err_t` | - | | only appears if non-zero (error condition). | - +-----------------------+-----------------------------------------------+ + +------------------+-------------------------------------------------------------------------+ + | | string identifying task. | + +------------------+-------------------------------------------------------------------------+ + | "prio" | task priority. | + +------------------+-------------------------------------------------------------------------+ + | "tid" | numeric task ID. | + +------------------+-------------------------------------------------------------------------+ + | "state" | numeric task state. | + +------------------+-------------------------------------------------------------------------+ + | "stkuse" | task's/thread's stack usage. | + +------------------+-------------------------------------------------------------------------+ + | "stksiz" | task's/thread's stack size. | + +------------------+-------------------------------------------------------------------------+ + | "cswcnt" | task's/thread's context switches. | + +------------------+-------------------------------------------------------------------------+ + | "runtime" | task's/thread's runtime in "ticks". | + +------------------+-------------------------------------------------------------------------+ + | "last_checkin" | set to 0 by Zephyr. | + +------------------+-------------------------------------------------------------------------+ + | "next_checkin" | set to 0 by Zephyr. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ .. note:: The unit for "stkuse" and "stksiz" is system dependent and in case of Zephyr @@ -262,33 +304,53 @@ CBOR data of successful response: In case of error the CBOR data takes the form: -.. code-block:: none +.. tabs:: - { - (str)"rc" : (int) - } + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + } where: .. table:: :align: center - +-----------------------+--------------------------------------------------+ - | | string representing the pool name, used as a key | - | | for dictionary with pool statistics data | - +-----------------------+--------------------------------------------------+ - | "blksiz" | size of the memory blocks in the pool | - +-----------------------+--------------------------------------------------+ - | "nblks" | number of blocks in the pool | - +-----------------------+--------------------------------------------------+ - | "nfree" | number of free blocks | - +-----------------------+--------------------------------------------------+ - | "min" | lowest number of free blocks the pool reached | - | | during run-time | - +-----------------------+--------------------------------------------------+ - | "rc" | :c:enum:`mcumgr_err_t` | - | | only appears if non-zero (error condition). | - +-----------------------+--------------------------------------------------+ + +------------------+-------------------------------------------------------------------------+ + | | string representing the pool name, used as a key for dictionary with | + | | pool statistics data. | + +------------------+-------------------------------------------------------------------------+ + | "blksiz" | size of the memory block in the pool. | + +------------------+-------------------------------------------------------------------------+ + | "nblks" | number of blocks in the pool. | + +------------------+-------------------------------------------------------------------------+ + | "nfree" | number of free blocks. | + +------------------+-------------------------------------------------------------------------+ + | "min" | lowest number of free blocks the pool reached during run-time. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ Date-time command ***************** @@ -344,24 +406,44 @@ CBOR data of successful response: In case of error the CBOR data takes the form: -.. code-block:: none +.. tabs:: - { - (str)"rc" : (int) - } + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + } where: .. table:: :align: center - +-----------------------+---------------------------------------------+ - | "datetime" | String in format | - | | yyyy-MM-dd'T'HH:mm:ss.SSSSSSZZZZZ | - +-----------------------+---------------------------------------------+ - | "rc" | :c:enum:`mcumgr_err_t`; | - | | only appears if non-zero (error condition). | - +-----------------------+---------------------------------------------+ + +------------------+-------------------------------------------------------------------------+ + | "datetime" | String in format: ``yyyy-MM-dd'T'HH:mm:ss.SSSSSSZZZZZ``. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ Date-time set @@ -396,10 +478,9 @@ where: .. table:: :align: center - +-----------------------+---------------------------------------------------+ - | "datetime" | String in format | - | | yyyy-MM-dd'T'HH:mm:ss.SSSSSSZZZZZ | - +-----------------------+---------------------------------------------------+ + +---------------+----------------------------------------------------------+ + | "datetime" | String in format: ``yyyy-MM-dd'T'HH:mm:ss.SSSSSSZZZZZ``. | + +---------------+----------------------------------------------------------+ Date-time set response ---------------------- @@ -418,21 +499,42 @@ Date-time set response header fields: The command sends an empty CBOR map as data if successful. In case of error the CBOR data takes the form: -.. code-block:: none +.. tabs:: - { - (str)"rc" : (int) - } + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + } where: .. table:: :align: center - +-----------------------+---------------------------------------------+ - | "rc" | :c:enum:`mcumgr_err_t` | - | | only appears if non-zero (error condition). | - +-----------------------+---------------------------------------------+ + +------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ System reset ************ @@ -462,7 +564,7 @@ System reset request header fields: Normally the command sends an empty CBOR map as data, but if a previous reset attempt has responded with "rc" equal to :c:enum:`MGMT_ERR_EBUSY` then the -following map may be send to force a reset: +following map may be sent to force a reset: .. code-block:: none @@ -497,21 +599,42 @@ System reset response header fields The command sends an empty CBOR map as data if successful. In case of error the CBOR data takes the form: -.. code-block:: none +.. tabs:: - { - (str)"rc" : (int) - } + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + } where: .. table:: :align: center - +-----------------------+---------------------------------------------+ - | "rc" | :c:enum:`mcumgr_err_t`; | - | | only appears if non-zero (error condition). | - +-----------------------+---------------------------------------------+ + +------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ MCUmgr Parameters ***************** @@ -559,26 +682,46 @@ CBOR data of successful response: In case of error the CBOR data takes the form: -.. code-block:: none +.. tabs:: - { - (str)"rc" : (int) - } + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + } where: .. table:: :align: center - +-----------------------+--------------------------------------------------+ - | "buf_size" | Single SMP buffer size, this includes SMP header | - | | and CBOR payload | - +-----------------------+--------------------------------------------------+ - | "buf_count" | Number of SMP buffers supported | - +-----------------------+--------------------------------------------------+ - | "rc" | :c:enum:`mcumgr_err_t`; | - | | only appears if non-zero (error condition). | - +-----------------------+--------------------------------------------------+ + +------------------+-------------------------------------------------------------------------+ + | "buf_size" | Single SMP buffer size, this includes SMP header and CBOR payload. | + +------------------+-------------------------------------------------------------------------+ + | "buf_count" | Number of SMP buffers supported. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ .. _mcumgr_os_application_info: @@ -651,15 +794,37 @@ OS/Application info response header fields | ``1`` | ``0`` | ``7`` | +--------+--------------+----------------+ -CBOR data of response: +CBOR data of successful response: .. code-block:: none { (str)"output" : (str) - (opt,str)"rc" : (int) } +In case of error the CBOR data takes the form: + +.. tabs:: + + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + } + where: .. table:: @@ -820,7 +985,7 @@ where: Bootloader Information: MCUboot =============================== -In case when MCUboot is application bootloader empty request will +In case when MCUboot is application bootloader, empty request will be responded with: .. code-block:: none @@ -869,8 +1034,8 @@ where "mode" is one of: | 6 | MCUboot is in RAM loader mode. | +-----+-----------------------------------------------------+ -The "no-downgrade" is a flag, which is always sent when true, indicating that -mode has downgrade prevention enabled; downgrade prevention means that -if uploaded image has lower version than running, it will notbe taken -for exectuion by MCUboot. -MCUmgr may reject image with lower version in that MCUboot configuration. +The ``no-downgrade`` field is a flag, which is always sent when true, indicating that MCUboot has +downgrade prevention enabled; downgrade prevention means that if the uploaded image has a lower +version than the currently running application, it will not be used for an update by MCUboot. + +MCUmgr may reject images with a lower version in this configuration. diff --git a/doc/services/device_mgmt/smp_groups/smp_group_1.rst b/doc/services/device_mgmt/smp_groups/smp_group_1.rst index 7f5ffa171dd..2a1d1f27086 100644 --- a/doc/services/device_mgmt/smp_groups/smp_group_1.rst +++ b/doc/services/device_mgmt/smp_groups/smp_group_1.rst @@ -3,7 +3,7 @@ Application/software image management group ########################################### -Application/software image management management group defines following commands: +Application/software image management group defines following commands: .. table:: :align: center @@ -75,7 +75,7 @@ Get state of images request header fields: | ``0`` | ``1`` | ``0`` | +--------+--------------+----------------+ -The command sends sends empty CBOR map as data. +The command sends an empty CBOR map as data. .. _mcumgr_smp_protocol_op_1_grp_1_cmd_0: @@ -127,73 +127,85 @@ CBOR data of successful response: In case of error the CBOR data takes the form: -.. code-block:: none +.. tabs:: - { - (str)"rc" : (int) - (str,opt)"rsn" : (str) - } + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + (str,opt)"rsn" : (str) + } where: .. table:: :align: center - +-----------------------+---------------------------------------------------+ - | "image" | semi-optional image number; the field is not | - | | required when only one image is supported by | - | | running application | - +-----------------------+---------------------------------------------------+ - | "slot" | slot number within "image"; each image has two | - | | slots : primary (running one) = 0 and secondary | - | | (for DFU dual-bank purposes) = 1 | - +-----------------------+---------------------------------------------------+ - | "version" | string representing image version, as set with | - | | ``imgtool`` | - +-----------------------+---------------------------------------------------+ - | "hash" | SHA256 hash of the image header and body. Note | - | | that this will not be the same as the SHA256 of | - | | the whole file, it is the field in the MCUboot | - | | TLV section that contains a hash of the data | - | | which is used for signature verification | - | | purposes. This field is optional but only | - | | optional when using MCUboot's serial recovery | - | | feature with one pair of image slots, Kconfig | - | | :kconfig:option:`CONFIG_BOOT_SERIAL_IMG_GRP_HASH` | - | | can be disabled to remove support for hashes in | - | | this configuration. MCUmgr in applications must | - | | support sending hashes. | - | | | - | | .. note:: | - | | See ``IMAGE_TLV_SHA256`` in the MCUboot image | - | | format documentation link below. | - +-----------------------+---------------------------------------------------+ - | "bootable" | true if image has bootable flag set; | - | | this field does not have to be present if false | - +-----------------------+---------------------------------------------------+ - | "pending" | true if image is set for next swap | - | | this field does not have to be present if false | - +-----------------------+---------------------------------------------------+ - | "confirmed" | true if image has been confirmed | - | | this field does not have to be present if false | - +-----------------------+---------------------------------------------------+ - | "active" | true if image is currently active application | - | | this field does not have to be present if false | - +-----------------------+---------------------------------------------------+ - | "permanent" | true if image is to stay in primary slot after | - | | next boot | - | | this field does not have to be present if false | - +-----------------------+---------------------------------------------------+ - | "splitStatus" | states whether loader of split image is compatible| - | | with application part; this is unused by Zephyr | - +-----------------------+---------------------------------------------------+ - | "rc" | :c:enum:`mcumgr_err_t` | - | | only appears if non-zero (error condition). | - +-----------------------+---------------------------------------------------+ - | "rsn" | optional string that clarifies reason for an | - | | error; specifically useful for error code ``1``, | - | | unknown error | - +-----------------------+---------------------------------------------------+ + +------------------+-------------------------------------------------------------------------+ + | "image" | semi-optional image number; the field is not required when only one | + | | image is supported by the running application. | + +------------------+-------------------------------------------------------------------------+ + | "slot" | slot number within "image"; each image has two slots : primary (running | + | | one) = 0 and secondary (for DFU dual-bank purposes) = 1. | + +------------------+-------------------------------------------------------------------------+ + | "version" | string representing image version, as set with ``imgtool``. | + +------------------+-------------------------------------------------------------------------+ + | "hash" | SHA256 hash of the image header and body. Note that this will not be | + | | the same as the SHA256 of the whole file, it is the field in the | + | | MCUboot TLV section that contains a hash of the data which is used for | + | | signature verification purposes. This field is optional but only | + | | optional when using MCUboot's serial recovery feature with one pair of | + | | image slots, Kconfig :kconfig:option:`CONFIG_BOOT_SERIAL_IMG_GRP_HASH` | + | | can be disabled to remove support for hashes in this configuration. | + | | MCUmgr in applications must support sending hashes. | + | | | + | | .. note:: | + | | See ``IMAGE_TLV_SHA256`` in the MCUboot image format documentation | + | | link below. | + +------------------+-------------------------------------------------------------------------+ + | "bootable" | true if image has bootable flag set; this field does not have to be | + | | present if false. | + +------------------+-------------------------------------------------------------------------+ + | "pending" | true if image is set for next swap; this field does not have to be | + | | present if false. | + +------------------+-------------------------------------------------------------------------+ + | "confirmed" | true if image has been confirmed; this field does not have to be | + | | present if false. | + +------------------+-------------------------------------------------------------------------+ + | "active" | true if image is currently active application; this field does not have | + | | to be present if false. | + +------------------+-------------------------------------------------------------------------+ + | "permanent" | true if image is to stay in primary slot after the next boot; this | + | | does not have to be present if false. | + +------------------+-------------------------------------------------------------------------+ + | "splitStatus" | states whether loader of split image is compatible with application | + | | part; this is unused by Zephyr. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rsn" | optional string that clarifies reason for an error; specifically useful | + | | when ``rc`` is :c:enum:`MGMT_ERR_EUNKNOWN`. | + +------------------+-------------------------------------------------------------------------+ .. note:: For more information on how does image/slots function, please refer to @@ -351,34 +363,52 @@ CBOR data of successful response: In case of error the CBOR data takes the form: -.. code-block:: none +.. tabs:: - { - (str)"rc" : (int) - (str,opt)"rsn" : (str) - } + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + (str,opt)"rsn" : (str) + } where: .. table:: :align: center - +-----------------------+-----------------------------------------------------+ - | "off" | offset of last successfully written byte of update. | - +-----------------------+-----------------------------------------------------+ - | "match" | indicates if the uploaded data successfully matches | - | | the provided SHA256 hash or not, only sent in the | - | | final packet if | - | | :kconfig:option:`CONFIG_IMG_ENABLE_IMAGE_CHECK` is | - | | enabled. | - +-----------------------+-----------------------------------------------------+ - | "rc" | :c:enum:`mcumgr_err_t` only | - | | appears if non-zero (error condition). | - +-----------------------+-----------------------------------------------------+ - | "rsn" | Optional string that clarifies reason for an error; | - | | specifically useful for error code ``1``, unknown | - | | error. | - +-----------------------+-----------------------------------------------------+ + +------------------+-------------------------------------------------------------------------+ + | "off" | offset of last successfully written byte of update. | + +------------------+-------------------------------------------------------------------------+ + | "match" | indicates if the uploaded data successfully matches the provided SHA256 | + | | hash or not, only sent in the final packet if | + | | :kconfig:option:`CONFIG_IMG_ENABLE_IMAGE_CHECK` is enabled. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rsn" | optional string that clarifies reason for an error; specifically useful | + | | when ``rc`` is :c:enum:`MGMT_ERR_EUNKNOWN`. | + +------------------+-------------------------------------------------------------------------+ The "off" field is only included in responses to successfully processed requests; if "rc" is negative then "off" may not appear. @@ -441,26 +471,46 @@ Image erase response header fields: The command sends an empty CBOR map as data if successful. In case of error the CBOR data takes the form: -.. code-block:: none +.. tabs:: - { - (str)"rc" : (int) - (str,opt)"rsn" : (str) - } + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + (str,opt)"rsn" : (str) + } where: .. table:: :align: center - +-----------------------+--------------------------------------------------+ - | "rc" | :c:enum:`mcumgr_err_t` | - | | only appears if non-zero (error condition). | - +-----------------------+--------------------------------------------------+ - | "rsn" | Optional string that clarifies reason for an | - | | error; specifically useful when rc value is | - | | :c:enum:`MGMT_ERR_EUNKNOWN` | - +-----------------------+--------------------------------------------------+ + +------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rsn" | optional string that clarifies reason for an error; specifically useful | + | | when ``rc`` is :c:enum:`MGMT_ERR_EUNKNOWN`. | + +------------------+-------------------------------------------------------------------------+ .. note:: Response from Zephyr running device may have "rc" value of diff --git a/doc/services/device_mgmt/smp_groups/smp_group_2.rst b/doc/services/device_mgmt/smp_groups/smp_group_2.rst index 7d2c5bd853c..1528a9611fe 100644 --- a/doc/services/device_mgmt/smp_groups/smp_group_2.rst +++ b/doc/services/device_mgmt/smp_groups/smp_group_2.rst @@ -55,7 +55,7 @@ where: :align: center +-----------------------+---------------------------------------------------+ - | "name" | is group name | + | "name" | group name. | +-----------------------+---------------------------------------------------+ Statistics: group data response @@ -86,31 +86,51 @@ CBOR data of successful response: In case of error the CBOR data takes the form: -.. code-block:: none - { - (str)"rc" : (int) - } +.. tabs:: + + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + } where: .. table:: :align: center - +-----------------------+---------------------------------------------------+ - | "name" | this is name of group the response contains data | - | | for | - +-----------------------+---------------------------------------------------+ - | "fields" | this is map of entries within groups that consists| - | | of pairs where entry name is mapped to value it | - | | represents in statistics | - +-----------------------+---------------------------------------------------+ - | | single entry to value mapping; value is hardcoded | - | | to unsigned integer type, in a CBOR meaning | - +-----------------------+---------------------------------------------------+ - | "rc" | :c:enum:`mcumgr_err_t` | - | | only appears if non-zero (error condition). | - +-----------------------+---------------------------------------------------+ + +------------------+-------------------------------------------------------------------------+ + | "name" | this is name of group the response contains data for. | + +------------------+-------------------------------------------------------------------------+ + | "fields" | this is map of entries within groups that consists of pairs where the | + | | entry name is mapped to value it represents in statistics. | + +------------------+-------------------------------------------------------------------------+ + | | single entry to value mapping; value is hardcoded to unsigned integer | + | | type, in a CBOR meaning. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ Statistics: list of groups ************************** @@ -164,21 +184,43 @@ CBOR data of successful response: In case of error the CBOR data takes the form: -.. code-block:: none - { - (str)"rc" : (int) - } +.. tabs:: + + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + } where: .. table:: :align: center - +-----------------------+---------------------------------------------------+ - | "stat_list" | array of strings representing group names; this | - | | array may be empty if there are no groups | - +-----------------------+---------------------------------------------------+ - | "rc" | :c:enum:`mcumgr_err_t` | - | | only appears if non-zero (error condition). | - +-----------------------+---------------------------------------------------+ + +------------------+-------------------------------------------------------------------------+ + | "stat_list" | array of strings representing group names; this array may be empty if | + | | there are no groups. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ diff --git a/doc/services/device_mgmt/smp_groups/smp_group_3.rst b/doc/services/device_mgmt/smp_groups/smp_group_3.rst index a6f1ee73b7a..c70897809e1 100644 --- a/doc/services/device_mgmt/smp_groups/smp_group_3.rst +++ b/doc/services/device_mgmt/smp_groups/smp_group_3.rst @@ -333,7 +333,7 @@ Commit settings request header fields: | ``2`` | ``3`` | ``2`` | +--------+--------------+----------------+ -The command sends sends empty CBOR map as data. +The command sends an empty CBOR map as data. Commit settings response ======================== @@ -409,7 +409,7 @@ Load settings request header fields: | ``0`` | ``3`` | ``3`` | +--------+--------------+----------------+ -The command sends sends empty CBOR map as data. +The command sends an empty CBOR map as data. Load settings response ====================== @@ -479,7 +479,7 @@ Save settings request header fields: | ``2`` | ``3`` | ``3`` | +--------+--------------+----------------+ -The command sends sends empty CBOR map as data. +The command sends an empty CBOR map as data. Save settings response ====================== diff --git a/doc/services/device_mgmt/smp_groups/smp_group_8.rst b/doc/services/device_mgmt/smp_groups/smp_group_8.rst index d86208346f8..502a5757169 100644 --- a/doc/services/device_mgmt/smp_groups/smp_group_8.rst +++ b/doc/services/device_mgmt/smp_groups/smp_group_8.rst @@ -112,32 +112,49 @@ CBOR data of successful response: In case of error the CBOR data takes the form: -.. code-block:: none +.. tabs:: - { - (str)"rc" : (int) - } + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + } where: .. table:: :align: center - +-----------------------+--------------------------------------------------+ - | "off" | offset the response is for | - +-----------------------+--------------------------------------------------+ - | "data" | chunk of data read from file; it is CBOR encoded | - | | stream of bytes with embedded size; | - | | "data" appears only in responses where "rc" is 0 | - +-----------------------+--------------------------------------------------+ - | "len" | length of file, this field is only mandatory | - | | when "off" is 0 | - +-----------------------+--------------------------------------------------+ - | "rc" | :c:enum:`mcumgr_err_t` | - | | only appears if non-zero (error condition). | - +-----------------------+--------------------------------------------------+ - -In case when "rc" is not 0, success, the other fields will not appear. + +------------------+-------------------------------------------------------------------------+ + | "off" | offset the response is for. | + +------------------+-------------------------------------------------------------------------+ + | "data" | chunk of data read from file; it is CBOR encoded stream of bytes with | + | | embedded size; "data" appears only in responses where "rc" is 0. | + +------------------+-------------------------------------------------------------------------+ + | "len" | length of file, this field is only mandatory when "off" is 0. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ File upload *********** @@ -204,15 +221,15 @@ where: :align: center +-----------------------+---------------------------------------------------+ - | "off" | offset to start/continue upload at | + | "off" | offset to start/continue upload at. | +-----------------------+---------------------------------------------------+ | "data" | chunk of data to write to the file; | - | | it is CBOR encoded with length embedded | + | | it is CBOR encoded with length embedded. | +-----------------------+---------------------------------------------------+ - | "name" | absolute path to a file | + | "name" | absolute path to a file. | +-----------------------+---------------------------------------------------+ | "len" | length of file, this field is only mandatory | - | | when "off" is 0 | + | | when "off" is 0. | +-----------------------+---------------------------------------------------+ File upload response @@ -239,23 +256,44 @@ CBOR data of successful response: In case of error the CBOR data takes the form: -.. code-block:: none +.. .. tabs:: - { - (str)"rc" : (int) - } + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + } where: .. table:: :align: center - +-----------------------+---------------------------------------------+ - | "off" | offset of last successfully written data. | - +-----------------------+---------------------------------------------+ - | "rc" | :c:enum:`mcumgr_err_t` | - | | only appears if non-zero (error condition). | - +-----------------------+---------------------------------------------+ + +------------------+-------------------------------------------------------------------------+ + | "off" | offset of last successfully written data. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ File status *********** @@ -291,7 +329,7 @@ where: :align: center +-----------------------+---------------------------------------------------+ - | "name" | absolute path to a file | + | "name" | absolute path to a file. | +-----------------------+---------------------------------------------------+ File status response @@ -318,25 +356,44 @@ CBOR data of successful response: In case of error the CBOR data takes form: -.. code-block:: none +.. tabs:: - { - (str)"rc" : (int) - } + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + } where: .. table:: :align: center - +-----------------------+---------------------------------------------+ - | "len" | length of file (in bytes) | - +-----------------------+---------------------------------------------+ - | "rc" | :c:enum:`mcumgr_err_t` | - | | only appears if non-zero (error condition). | - +-----------------------+---------------------------------------------+ - -In case when "rc" is not 0, success, the other fields will not appear. + +------------------+-------------------------------------------------------------------------+ + | "len" | length of file (in bytes). | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ File hash/checksum ****************** @@ -381,18 +438,18 @@ where: :align: center +-----------------------+---------------------------------------------------+ - | "name" | absolute path to a file | + | "name" | absolute path to a file. | +-----------------------+---------------------------------------------------+ | "type" | type of hash/checksum to perform | | | :ref:`mcumgr_group_8_hash_checksum_types` or omit | - | | to use default | + | | to use default. | +-----------------------+---------------------------------------------------+ | "off" | offset to start hash/checksum calculation at | - | | (optional, 0 if not provided) | + | | (optional, 0 if not provided). | +-----------------------+---------------------------------------------------+ | "len" | maximum length of data to read from file to | | | generate hash/checksum with (optional, full file | - | | size if not provided) | + | | size if not provided). | +-----------------------+---------------------------------------------------+ .. _mcumgr_group_8_hash_checksum_types: @@ -441,34 +498,52 @@ CBOR data of successful response: In case of error the CBOR data takes the form: -.. code-block:: none +.. tabs:: - { - (str)"rc" : (int) - } + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + } where: .. table:: :align: center - +-----------------------+--------------------------------------------------+ - | "rc" | :c:enum:`mcumgr_err_t` | - | | only appears if non-zero (error condition). | - +-----------------------+--------------------------------------------------+ - | "type" | type of hash/checksum that was performed | - | | :ref:`mcumgr_group_8_hash_checksum_types` | - +-----------------------+--------------------------------------------------+ - | "off" | offset that hash/checksum calculation started at | - | | (only present if off is not 0) | - +-----------------------+--------------------------------------------------+ - | "len" | length of input data used for hash/checksum | - | | generation (in bytes) | - +-----------------------+--------------------------------------------------+ - | "output" | output hash/checksum | - +-----------------------+--------------------------------------------------+ - -In case when "rc" is not 0, success, the other fields will not appear. + +------------------+-------------------------------------------------------------------------+ + | "type" | type of hash/checksum that was performed | + | | :ref:`mcumgr_group_8_hash_checksum_types`. | + +------------------+-------------------------------------------------------------------------+ + | "off" | offset that hash/checksum calculation started at (only present if not | + | | 0). | + +------------------+-------------------------------------------------------------------------+ + | "len" | length of input data used for hash/checksum generation (in bytes). | + +------------------+-------------------------------------------------------------------------+ + | "output" | output hash/checksum. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ Supported file hash/checksum types ********************************** @@ -523,28 +598,50 @@ CBOR data of successful response: In case of error the CBOR data takes form: -.. code-block:: none +.. tabs:: - { - (str)"rc" : (int) - } + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + } where: .. table:: :align: center - +-----------------------+---------------------------------------------------+ - | | name of the hash/checksum type | - | | :ref:`mcumgr_group_8_hash_checksum_types` | - +-----------------------+---------------------------------------------------+ - | "format" | format that the hash/checksum returns where 0 is | - | | for numerical and 1 is for byte array. | - +-----------------------+---------------------------------------------------+ - | "size" | size (in bytes) of output hash/checksum response. | - +-----------------------+---------------------------------------------------+ - -In case when "rc" is not 0, success, the other fields will not appear. + +----------------------+-------------------------------------------------------------------------+ + | | name of the hash/checksum type | + | | :ref:`mcumgr_group_8_hash_checksum_types`. | + +----------------------+-------------------------------------------------------------------------+ + | "format" | format that the hash/checksum returns where 0 is for numerical and 1 is | + | | for byte array. | + +----------------------+-------------------------------------------------------------------------+ + | "size" | size (in bytes) of output hash/checksum response. | + +----------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +----------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +----------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +----------------------+-------------------------------------------------------------------------+ File close ********** @@ -585,18 +682,39 @@ File close response header: The command sends an empty CBOR map as data if successful. In case of error the CBOR data takes the form: -.. code-block:: none +.. tabs:: - { - (str)"rc" : (int) - } + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + } where: .. table:: :align: center - +-----------------------+------------------------------------------------+ - | "rc" | :c:enum:`mcumgr_err_t` | - | | only appears if non-zero (error condition). | - +-----------------------+------------------------------------------------+ + +------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ diff --git a/doc/services/device_mgmt/smp_groups/smp_group_9.rst b/doc/services/device_mgmt/smp_groups/smp_group_9.rst index 615a364e812..7e857f70a0d 100644 --- a/doc/services/device_mgmt/smp_groups/smp_group_9.rst +++ b/doc/services/device_mgmt/smp_groups/smp_group_9.rst @@ -56,11 +56,11 @@ where: +-----------------------+---------------------------------------------------+ | "argv" | array consisting of strings representing command | - | | and its arguments | + | | and its arguments. | +-----------------------+---------------------------------------------------+ - | | command to be executed | + | | command to be executed. | +-----------------------+---------------------------------------------------+ - | | optional arguments to command | + | | optional arguments to command. | +-----------------------+---------------------------------------------------+ Shell command line execute response @@ -88,25 +88,46 @@ CBOR data of successful response: In case of error the CBOR data takes the form: -.. code-block:: none +.. tabs:: - { - (str)"rc" : (int) - } + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + } where: .. table:: :align: center - +-----------------------+-----------------------------------------------+ - | "rc" | :c:enum:`mcumgr_err_t` | - | | only appears if non-zero (error condition). | - +-----------------------+-----------------------------------------------+ - | "o" | command output | - +-----------------------+-----------------------------------------------+ - | "ret" | return code from shell command execution | - +-----------------------+-----------------------------------------------+ + +------------------+-------------------------------------------------------------------------+ + | "o" | command output. | + +------------------+-------------------------------------------------------------------------+ + | "ret" | return code from shell command execution. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ .. note:: In older versions of Zephyr, "rc" was used for both the mcumgr status code diff --git a/doc/services/device_mgmt/smp_protocol.rst b/doc/services/device_mgmt/smp_protocol.rst index 4524b830b0a..44c30f32d29 100644 --- a/doc/services/device_mgmt/smp_protocol.rst +++ b/doc/services/device_mgmt/smp_protocol.rst @@ -163,22 +163,50 @@ non-responsive. Minimal response SMP data ========================= -Minimal response is CBOR directory: +Minimal response is: -.. code-block:: none +.. tabs:: - { - (str)"rc" : (int) - } + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + } where: .. table:: :align: center - +-----------------------+--------------------------+ - | "rc" | :c:enum:`mcumgr_err_t` | - +-----------------------+--------------------------+ + +------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + +Note that in the case of a successful command, an empty map will be returned (``rc``/``err`` is +only returned if there is an error condition, therefore if only an empty map is returned or a +response lacks these, the request can be considered as being successful. For SMP version 2, +errors relating to SMP itself that are not group specific will still be returned as ``rc`` +errors, SMP version 2 clients must therefore be able to handle both types of errors. Specifications of management groups supported by Zephyr ******************************************************* diff --git a/doc/services/index.rst b/doc/services/index.rst index 6ba8af68a67..c9055e8081f 100644 --- a/doc/services/index.rst +++ b/doc/services/index.rst @@ -7,6 +7,7 @@ OS Services :maxdepth: 1 + binary_descriptors/index.rst crypto/index debugging/index.rst device_mgmt/index @@ -15,10 +16,13 @@ OS Services formatted_output.rst input/index.rst ipc/index.rst + llext/index.rst logging/index.rst tracing/index.rst resource_management/index.rst + mem_mgmt/index.rst modbus/index.rst + modem/index.rst notify.rst pm/index.rst portability/index.rst diff --git a/doc/services/input/index.rst b/doc/services/input/index.rst index 03851d795c0..b18c57beb30 100644 --- a/doc/services/input/index.rst +++ b/doc/services/input/index.rst @@ -87,3 +87,8 @@ Input Event Definitions *********************** .. doxygengroup:: input_events + +Keyboard Matrix API Reference +***************************** + +.. doxygengroup:: input_kbd_matrix diff --git a/doc/services/ipc/ipc_service/backends/ipc_service_icbmsg.rst b/doc/services/ipc/ipc_service/backends/ipc_service_icbmsg.rst new file mode 100644 index 00000000000..26b9006ae81 --- /dev/null +++ b/doc/services/ipc/ipc_service/backends/ipc_service_icbmsg.rst @@ -0,0 +1,83 @@ +.. _ipc_service_backend_icbmsg: + +ICMsg with dynamically allocated buffers backend +################################################ + +This backend is built on top of the :ref:`ipc_service_backend_icmsg`. +Data transferred over this backend travels in dynamically allocated buffers on shared memory. +The ICMsg just sends references to the buffers. +It also supports multiple endpoints. + +This architecture allows for overcoming some common problems with other backends (mostly related to multithread access and zero-copy). +This backend provides an alternative with no significant limitations. + +Overview +======== + +The shared memory is divided into two parts. +One is reserved for the ICMsg and the other contains equal-sized blocks. +The number of blocks is configured in the devicetree. + +The data sending process is following: + +* The sender allocates one or more blocks. + If there are not enough sequential blocks, it waits using the timeout provided in the parameter that also includes K_FOREVER and K_NO_WAIT. +* The allocated blocks are filled with data. + For the zero-copy case, this is done by the caller, otherwise, it is copied automatically. + During this time other threads are not blocked in any way as long as there are enough free blocks for them. + They can allocate, send data and receive data. +* A message containing the block index is sent over ICMsg to the receiver. + The size of the ICMsg queue is large enough to hold messages for all blocks, so it will never overflow. +* The receiver can hold the data as long as desired. + Again, other threads are not blocked as long as there are enough free blocks for them. +* When data is no longer needed, the backend sends a release message over ICMsg. +* When the backend receives this message, it deallocates all blocks. + It is done internally by the backend and it is invisible to the caller. + +Configuration +============= + +The backend is configured using Kconfig and devicetree. +When configuring the backend, do the following: + +* Define two memory regions and assign them to ``tx-region`` and ``rx-region`` of an instance. + Ensure that the memory regions used for data exchange are unique (not overlapping any other region) and accessible by both domains (or CPUs). +* Define the number of allocable blocks for each region with ``tx-blocks`` and ``rx-blocks``. +* Define MBOX devices for sending a signal that informs the other domain (or CPU) of the written data. + Ensure that the other domain (or CPU) can receive the signal. + +See the following configuration example for one of the instances: + +.. code-block:: devicetree + + reserved-memory { + tx: memory@20070000 { + reg = <0x20070000 0x0800>; + }; + + rx: memory@20078000 { + reg = <0x20078000 0x0800>; + }; + }; + + ipc { + ipc0: ipc0 { + compatible = "zephyr,ipc-icbmsg"; + tx-region = <&tx>; + rx-region = <&rx>; + tx-blocks = <16>; + rx-blocks = <32>; + mboxes = <&mbox 0>, <&mbox 1>; + mbox-names = "tx", "rx"; + status = "okay"; + }; + }; + + +You must provide a similar configuration for the other side of the communication (domain or CPU). +Swap the MBOX channels, memory regions (``tx-region`` and ``rx-region``), and block count (``tx-blocks`` and ``rx-blocks``). + +Samples +======= + +* :ref:`ipc_multi_endpoint_sample` diff --git a/doc/services/ipc/ipc_service/backends/ipc_service_icmsg.rst b/doc/services/ipc/ipc_service/backends/ipc_service_icmsg.rst index 32fb2cbf6aa..2fd67bff195 100644 --- a/doc/services/ipc/ipc_service/backends/ipc_service_icmsg.rst +++ b/doc/services/ipc/ipc_service/backends/ipc_service_icmsg.rst @@ -83,4 +83,4 @@ and the backend informs the application by calling Samples ======= - - :ref:`ipc_icmsg_sample` + - :zephyr:code-sample:`ipc-icmsg` diff --git a/doc/services/ipc/ipc_service/ipc_service.rst b/doc/services/ipc/ipc_service/ipc_service.rst index 35cdfbf1dde..286ded75801 100644 --- a/doc/services/ipc/ipc_service/ipc_service.rst +++ b/doc/services/ipc/ipc_service/ipc_service.rst @@ -185,6 +185,7 @@ backend. :maxdepth: 1 backends/ipc_service_icmsg.rst + backends/ipc_service_icbmsg.rst API Reference ************* diff --git a/doc/services/llext/index.rst b/doc/services/llext/index.rst new file mode 100644 index 00000000000..d742f198530 --- /dev/null +++ b/doc/services/llext/index.rst @@ -0,0 +1,30 @@ +.. _llext: + +Linkable Loadable Extensions (LLEXT) +#################################### + +The llext subsystem provides a toolbox for extending the functionality of an +application at runtime with linkable loadable code. + +Extensions can be loaded from precompiled ELF formatted data which is +verified, loaded, and linked with other extensions. Extensions can be +manipulated and introspected to some degree, as well as unloaded when no longer +needed. + +An extension may be loaded using any implementation of a :c:struct:`llext_loader` +which has a set of function pointers that provide the necessary functionality +to read the ELF data. A loader also provides some minimal context (memory) +needed by the :c:func:`llext_load` function. An implementation over a buffer +containing an ELF in addressable memory in memory is available as +:c:struct:`llext_buf_loader`. + +API Reference +************* + +.. doxygengroup:: llext + +.. doxygengroup:: llext_symbols + +.. doxygengroup:: llext_loader + +.. doxygengroup:: llext_buf_loader diff --git a/doc/services/logging/index.rst b/doc/services/logging/index.rst index c1ee1bf6d9a..2b9fe9a707a 100644 --- a/doc/services/logging/index.rst +++ b/doc/services/logging/index.rst @@ -142,10 +142,16 @@ packet buffer. :kconfig:option:`CONFIG_LOG_FRONTEND_ONLY`: No backends are used when messages goes to frontend. +:kconfig:option:`CONFIG_LOG_FRONTEND_OPT_API`: Optional API optimized for the most common +simple messages. + :kconfig:option:`CONFIG_LOG_CUSTOM_HEADER`: Injects an application provided header into log.h :kconfig:option:`CONFIG_LOG_TIMESTAMP_64BIT`: 64 bit timestamp. +:kconfig:option:`CONFIG_LOG_SIMPLE_MSG_OPTIMIZE`: Optimizes simple log messages for size +and performance. Option available only for 32 bit architectures. + Formatting options: :kconfig:option:`CONFIG_LOG_FUNC_NAME_PREFIX_ERR`: Prepend standard ERROR log messages @@ -734,7 +740,8 @@ hexadecimal characters (e.g. when ``CONFIG_LOG_BACKEND_UART_OUTPUT_DICTIONARY_HEX=y``). This tells the parser to convert the hexadecimal characters to binary before parsing. -Please refer to :ref:`logging_dictionary_sample` on how to use the log parser. +Please refer to the :zephyr:code-sample:`logging-dictionary` sample to learn more on how to use +the log parser. Recommendations diff --git a/doc/services/mem_mgmt/index.rst b/doc/services/mem_mgmt/index.rst new file mode 100644 index 00000000000..eb689c409d1 --- /dev/null +++ b/doc/services/mem_mgmt/index.rst @@ -0,0 +1,90 @@ +.. _mem_mgmt_api: + +Memory Attributes +################# + +It is possible in the devicetree to mark the memory regions with attributes by +using the ``zephyr,memory-attr`` property. This property and the related memory +region can then be retrieved at run-time by leveraging a provided helper +library. + +The set of general attributes that can be specified in the property are defined +and explained in :zephyr_file:`include/zephyr/dt-bindings/memory-attr/memory-attr.h`. + +For example, to mark a memory region in the devicetree as non-volatile, cacheable, +out-of-order: + +.. code-block:: devicetree + + mem: memory@10000000 { + compatible = "mmio-sram"; + reg = <0x10000000 0x1000>; + zephyr,memory-attr = <( DT_MEM_NON_VOLATILE | DT_MEM_CACHEABLE | DT_MEM_OOO )>; + }; + +.. note:: + + The ``zephyr,memory-attr`` usage does not result in any memory region + actually created. When it is needed to create an actual section out of the + devicetree defined memory region, it is possible to use the compatible + :dtcompatible:`zephyr,memory-region` that will result (only when supported + by the architecture) in a new linker section and region. + +The ``zephyr,memory-attr`` property can also be used to set +architecture-specific and software-specific custom attributes that can be +interpreted at run time. This is leveraged, among other things, to create MPU +regions out of devicetree defined memory regions, for example: + +.. code-block:: devicetree + + mem: memory@10000000 { + compatible = "mmio-sram"; + reg = <0x10000000 0x1000>; + zephyr,memory-region = "NOCACHE_REGION"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) )>; + }; + +See :zephyr_file:`include/zephyr/dt-bindings/memory-attr/memory-attr-arm.h` and +:ref:`arm_cortex_m_developer_guide` for more details about MPU usage. + +The conventional and recommended way to deal and manage with memory regions +marked with attributes is by using the provided ``mem-attr`` helper library by +enabling :kconfig:option:`CONFIG_MEM_ATTR`. When this option is enabled the +list of memory regions and their attributes are compiled in a user-accessible +array and a set of functions is made available that can be used to query, probe +and act on regions and attributes (see next section for more details). + +.. note:: + + The ``zephyr,memory-attr`` property is only a descriptive property of the + capabilities of the associated memory region, but it does not result in any + actual setting for the memory to be set. The user, code or subsystem willing + to use this information to do some work (for example creating an MPU region + out of the property) must use either the provided ``mem-attr`` library or + the usual devicetree helpers to perform the required work / setting. + +A test for the ``mem-attr`` library and its usage is provided in +``tests/subsys/mem_mgmt/mem_attr/``. + +Migration guide from `zephyr,memory-region-mpu` +*********************************************** + +When the ``zephyr,memory-attr`` property was introduced, the +``zephyr,memory-region-mpu`` property was removed and deprecated. + +The developers that are still using the deprecated property can move to the new +one by renaming the property and changing its value according to the following list: + +.. code-block:: none + + "RAM" -> <( DT_ARM_MPU(ATTR_MPU_RAM) )> + "RAM_NOCACHE" -> <( DT_ARM_MPU(ATTR_MPU_RAM_NOCACHE) )> + "FLASH" -> <( DT_ARM_MPU(ATTR_MPU_FLASH) )> + "PPB" -> <( DT_ARM_MPU(ATTR_MPU_PPB) )> + "IO" -> <( DT_ARM_MPU(ATTR_MPU_IO) )> + "EXTMEM" -> <( DT_ARM_MPU(ATTR_MPU_EXTMEM) )> + +API Reference +************* + +.. doxygengroup:: memory_attr_interface diff --git a/doc/services/modbus/index.rst b/doc/services/modbus/index.rst index 51b3780d6b1..a263e1eeb7f 100644 --- a/doc/services/modbus/index.rst +++ b/doc/services/modbus/index.rst @@ -25,14 +25,11 @@ More information about Modbus and Modbus RTU can be found on the website Samples ******* -:ref:`modbus-rtu-server-sample` and :ref:`modbus-rtu-client-sample` give -the possibility to try out RTU server and RTU client implementation with -an evaluation board. - -:ref:`modbus-tcp-server-sample` is a simple Modbus TCP server. - -:ref:`modbus-gateway-sample` is an example how to build a TCP to serial line -gateway with Zephyr OS. +* :zephyr:code-sample:`modbus-rtu-server` and :zephyr:code-sample:`modbus-rtu-client` samples give + the possibility to try out RTU server and RTU client implementation with an evaluation board. +* :zephyr:code-sample:`modbus-tcp-server` sample is a simple Modbus TCP server. +* :zephyr:code-sample:`modbus-gateway` sample shows how to build a TCP to serial line + gateway with Zephyr OS. API Reference ************* diff --git a/doc/services/modem/index.rst b/doc/services/modem/index.rst new file mode 100644 index 00000000000..d831d254626 --- /dev/null +++ b/doc/services/modem/index.rst @@ -0,0 +1,53 @@ +.. _modem: + +Modem modules +############# + +This service provides modules necessary to communicate with modems. + +Modems are self-contained devices that implement the hardware and +software necessary to perform RF (Radio-Frequency) communication, +including GNSS, Cellular, WiFi etc. + +The modem modules are inter-connected dynamically using +data-in/data-out pipes making them independently testable and +highly flexible, ensuring stability and scalability. + +Modem pipe +********** + +This module is used to abstract data-in/data-out communication over +a variety of mechanisms, like UART and CMUX DLCI channels, in a +thread-safe manner. + +A modem backend will internally contain an instance of a modem_pipe +structure, alongside any buffers and additional structures required +to abstract away its underlying mechanism. + +The modem backend will return a pointer to its internal modem_pipe +structure when initialized, which will be used to interact with the +backend through the modem pipe API. + +.. doxygengroup:: modem_pipe + +Modem PPP +********* + +This module defines and binds a L2 PPP network interface, described in +:ref:`net_l2_interface`, to a modem backend. The L2 PPP interface sends +and receives network packets. These network packets have to be wrapped +in PPP frames before being transported via a modem backend. This module +performs said wrapping. + +.. doxygengroup:: modem_ppp + +Modem CMUX +********** + +This module is an implementation of CMUX following the 3GPP 27.010 +specification. CMUX is a multiplexing protocol, allowing for multiple +bi-directional streams of data, called DLCI channels. The module +attaches to a single modem backend, exposing multiple modem backends, +each representing a DLCI channel. + +.. doxygengroup:: modem_cmux diff --git a/doc/services/pm/device.rst b/doc/services/pm/device.rst index 490102e78a4..3eb936942ea 100644 --- a/doc/services/pm/device.rst +++ b/doc/services/pm/device.rst @@ -146,7 +146,7 @@ support in a device driver. #define DT_DRV_COMPAT dummy_device static int dummy_driver_pm_action(const struct device *dev, - enum pm_device_action *action) + enum pm_device_action action) { switch (action) { case PM_DEVICE_ACTION_SUSPEND: diff --git a/doc/services/portability/posix.rst b/doc/services/portability/posix.rst index 38be76f9118..392147594c8 100644 --- a/doc/services/portability/posix.rst +++ b/doc/services/portability/posix.rst @@ -85,11 +85,11 @@ Zephyr. :widths: 50,10 _POSIX_BARRIERS,yes - _POSIX_CLOCK_SELECTION, + _POSIX_CLOCK_SELECTION,yes _POSIX_FSYNC, _POSIX_MEMLOCK, _POSIX_MEMLOCK_RANGE, - _POSIX_MONOTONIC_CLOCK, + _POSIX_MONOTONIC_CLOCK,yes _POSIX_NO_TRUNC, _POSIX_REALTIME_SIGNALS, _POSIX_SEMAPHORES,yes @@ -104,7 +104,7 @@ Zephyr. _POSIX_THREAD_PRIORITY_SCHEDULING,yes _POSIX_THREAD_SPORADIC_SERVER, _POSIX_TIMEOUTS, - _POSIX_TIMERS, + _POSIX_TIMERS,yes _POSIX2_C_DEV, _POSIX2_SW_DEV, @@ -453,3 +453,31 @@ POSIX_DEVICE_IO vprintf(),yes vscanf(), write(),yes + +POSIX_TIMERS +++++++++++++ + +.. csv-table:: POSIX_TIMERS + :header: API, Supported + :widths: 50,10 + + clock_getres(), + clock_gettime(),yes + clock_settime(),yes + nanosleep(),yes + timer_create(),yes + timer_delete(),yes + timer_gettime(),yes + timer_getoverrun(),yes + timer_settime(),yes + +POSIX_CLOCK_SELECTION ++++++++++++++++++++++ + +.. csv-table:: POSIX_CLOCK_SELECTION + :header: API, Supported + :widths: 50,10 + + pthread_condattr_getclock(),yes + pthread_condattr_setclock(),yes + clock_nanosleep(),yes diff --git a/doc/services/retention/blinfo.rst b/doc/services/retention/blinfo.rst new file mode 100644 index 00000000000..6f34b0f9a35 --- /dev/null +++ b/doc/services/retention/blinfo.rst @@ -0,0 +1,134 @@ +.. _blinfo_api: + +Bootloader Information +###################### + +The bootloader information (abbreviated to blinfo) subsystem is an extension of +the :ref:`retention_api` which allows for reading shared data from a bootloader +and allowing applications to query it. It has an optional feature of organising +the information retrieved from the bootloader and storing it in the +:ref:`settings_api` with the ``blinfo/`` prefix. + +Devicetree setup +**************** + +To use the bootloader information subsystem, a retention area needs to be +created which has a retained data section as its parent, generally non-init RAM +is used for this purpose. See the following example (examples in this guide are +based on the :ref:`nrf52840dk_nrf52840` board and memory layout): + +.. code-block:: devicetree + + / { + sram@2003F000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x2003F000 DT_SIZE_K(1)>; + zephyr,memory-region = "RetainedMem"; + status = "okay"; + + retainedmem { + compatible = "zephyr,retained-ram"; + status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + + boot_info0: boot_info@0 { + compatible = "zephyr,retention"; + status = "okay"; + reg = <0x0 0x100>; + }; + }; + }; + + chosen { + zephyr,bootloader-info = &boot_info0; + }; + }; + + + /* Reduce SRAM0 usage by 1KB to account for non-init area */ + &sram0 { + reg = <0x20000000 DT_SIZE_K(255)>; + }; + +Note that this configuration needs to be applied on both the bootloader +(MCUboot) and application to be usable. It can be combined with other retention +system APIs such as the :ref:`boot_mode_api` + +MCUboot setup +************* + +Once the above devicetree configuration is applied, MCUboot needs to be +configured to store the shared data in this area, the following Kconfigs need +to be set for this: + +* :kconfig:option:`CONFIG_RETAINED_MEM` - Enables retained memory driver +* :kconfig:option:`CONFIG_RETENTION` - Enables retention system +* :kconfig:option:`CONFIG_BOOT_SHARE_DATA` - Enables shared data +* :kconfig:option:`CONFIG_BOOT_SHARE_DATA_BOOTINFO` - Enables boot information + shared data type +* :kconfig:option:`CONFIG_BOOT_SHARE_BACKEND_RETENTION` - Stores shared data + using retention/blinfo subsystem + +Application setup +***************** + +The application must enable the following base Kconfig options for the +bootloader information subsystem to function: + +* :kconfig:option:`CONFIG_RETAINED_MEM` +* :kconfig:option:`CONFIG_RETENTION` +* :kconfig:option:`CONFIG_RETENTION_BOOTLOADER_INFO` +* :kconfig:option:`CONFIG_RETENTION_BOOTLOADER_INFO_TYPE_MCUBOOT` + +The following include is needed to use the bootloader information subsystem: + +.. code-block:: C + + #include + +By default, only the lookup function is provided: :c:func:`blinfo_lookup`, the +application can call this to query the information from the bootloader. This +function is enabled by default with +:kconfig:option:`CONFIG_RETENTION_BOOTLOADER_INFO_OUTPUT_FUNCTION`, however, +applications can optionally choose to use the settings storage feature instead. +In this mode, the bootloader information can be queries by using settings keys, +the following Kconfig options need to be enabled for this mode: + +* :kconfig:option:`CONFIG_SETTINGS` +* :kconfig:option:`CONFIG_SETTINGS_RUNTIME` +* :kconfig:option:`CONFIG_RETENTION_BOOTLOADER_INFO_OUTPUT_SETTINGS` + +This allows the information to be queried via the +:c:func:`settings_runtime_get` function with the following keys: + +* ``blinfo/mode`` The mode that MCUboot is configured for + (``enum mcuboot_mode`` value) +* ``blinfo/signature_type`` The signature type MCUboot is configured for + (``enum mcuboot_signature_type`` value) +* ``blinfo/recovery`` The recovery type enabled in MCUboot + (``enum mcuboot_recovery_mode`` value) +* ``blinfo/running_slot`` The running slot, useful for direct-XIP mode to know + which slot to use for an update +* ``blinfo/bootloader_version`` Version of the bootloader + (``struct image_version`` object) +* ``blinfo/max_application_size`` Maximum size of an application (in bytes) + that can be loaded + +In addition to the previous include, the following includes are required for +this mode: + +.. code-block:: C + + #include + #include + #include + #include + +API Reference +************* + +Bootloader information API +========================== + +.. doxygengroup:: bootloader_info_interface diff --git a/doc/services/retention/index.rst b/doc/services/retention/index.rst index 0ae60332b0e..1f6de06eae2 100644 --- a/doc/services/retention/index.rst +++ b/doc/services/retention/index.rst @@ -121,6 +121,20 @@ When the write function is called, the magic header and checksum (if enabled) will be set on the area, and it will be marked as valid from that point onwards. +Mutex protection +**************** + +Mutex protection of retention areas is enabled by default when applications are +compiled with multithreading support. This means that different threads can +safely call the retention functions without clashing with other concurrent +thread function usage, but means that retention functions cannot be used from +ISRs. It is possible to disable mutex protection globally on all retention +areas by enabling :kconfig:option:`CONFIG_RETENTION_MUTEX_FORCE_DISABLE` - +users are then responsible for ensuring that the function calls do not conflict +with each other. Note that to use this, retention driver mutex support must +also be disabled by enabling +:kconfig:option:`CONFIG_RETAINED_MEM_MUTEX_FORCE_DISABLE`. + .. _boot_mode_api: Boot mode @@ -184,6 +198,17 @@ which will allow rebooting directly into the serial recovery mode by using: bootmode_set(BOOT_MODE_TYPE_BOOTLOADER); sys_reboot(0); +Retention system modules +************************ + +Modules can expand the functionality of the retention system by using it as a +transport (e.g. between a bootloader and application). + +.. toctree:: + :maxdepth: 1 + + blinfo.rst + API Reference ************* diff --git a/doc/services/rtio/index.rst b/doc/services/rtio/index.rst index b82972d7f68..88c5f29a075 100644 --- a/doc/services/rtio/index.rst +++ b/doc/services/rtio/index.rst @@ -212,214 +212,6 @@ There is a small cost to each RTIO context and iodev. This cost could be weighed against using a thread for each concurrent I/O operation or custom queues and threads per peripheral. RTIO is much lower cost than that. -Examples -******** - -Examples speak loudly about the intended uses and goals of an API. So several key -examples are presented below. Some are entirely plausible today without a -big leap. Others (the sensor example) would require additional work in other -APIs outside of RTIO as a sub system and are theoretical. - -Chained Blocking Requests -========================= - -A common scenario is needing to write the register address to then read from. -This can be accomplished by chaining a write into a read operation. - -The transaction on i2c is implicit for each operation chain. - -.. code-block:: C - - RTIO_I2C_IODEV(i2c_dev, I2C_DT_SPEC_INST(n)); - RTIO_DEFINE(ez_io, 4, 4); - static uint16_t reg_addr; - static uint8_t buf[32]; - - int do_some_io(void) - { - struct rtio_sqe *write_sqe = rtio_spsc_acquire(ez_io.sq); - struct rtio_sqe *read_sqe = rtio_spsc_acquire(ez_io.sq); - - rtio_sqe_prep_write(write_sqe, i2c_dev, RTIO_PRIO_LOW, ®_addr, 2); - write_sqe->flags = RTIO_SQE_CHAINED; /* the next item in the queue will wait on this one */ - - rtio_sqe_prep_read(read_sqe, i2c_dev, RTIO_PRIO_LOW, buf, 32); - - rtio_submit(rtio_inplace_executor, &ez_io, 2); - - struct rtio_cqe *read_cqe = rtio_spsc_consume(ez_io.cq); - struct rtio_cqe *write_cqe = rtio_spsc_consume(ez_io.cq); - - if(read_cqe->result < 0) { - LOG_ERR("read failed!"); - } - - if(write_cqe->result < 0) { - LOG_ERR("write failed!"); - } - - rtio_spsc_release(ez_io.cq); - rtio_spsc_release(ez_io.cq); - } - -Non blocking device to device -============================= - -Imagine wishing to read from one device on an I2C bus and then write the same -buffer to a device on a SPI bus without blocking the thread or setting up -callbacks or other IPC notification mechanisms. - -Perhaps an I2C temperature sensor and a SPI lowrawan module. The following is a -simplified version of that potential operation chain. - -.. code-block:: C - - RTIO_I2C_IODEV(i2c_dev, I2C_DT_SPEC_INST(n)); - RTIO_SPI_IODEV(spi_dev, SPI_DT_SPEC_INST(m)); - - RTIO_DEFINE(ez_io, 4, 4); - static uint8_t buf[32]; - - int do_some_io(void) - { - uint32_t read, write; - struct rtio_sqe *read_sqe = rtio_spsc_acquire(ez_io.sq); - rtio_sqe_prep_read(read_sqe, i2c_dev, RTIO_PRIO_LOW, buf, 32); - read_sqe->flags = RTIO_SQE_CHAINED; /* the next item in the queue will wait on this one */ - - /* Safe to do as the chained operation *ensures* that if one fails all subsequent ops fail */ - struct rtio_sqe *write_sqe = rtio_spsc_acquire(ez_io.sq); - rtio_sqe_prep_write(write_sqe, spi_dev, RTIO_PRIO_LOW, buf, 32); - - /* call will return immediately without blocking if possible */ - rtio_submit(rtio_inplace_executor, &ez_io, 0); - - /* These calls might return NULL if the operations have not yet completed! */ - for (int i = 0; i < 2; i++) { - struct rtio_cqe *cqe = rtio_spsc_consume(ez_io.cq); - while(cqe == NULL) { - cqe = rtio_spsc_consume(ez_io.cq); - k_yield(); - } - if(cqe->userdata == &read && cqe->result < 0) { - LOG_ERR("read from i2c failed!"); - } - if(cqe->userdata == &write && cqe->result < 0) { - LOG_ERR("write to spi failed!"); - } - /* Must release the completion queue event after consume */ - rtio_spsc_release(ez_io.cq); - } - } - -Nested iodevs for Devices on Buses (Sensors), Theoretical -========================================================= - -Consider a device like a sensor or audio codec sitting on a bus. - -Its useful to consider that the sensor driver can use RTIO to do I/O on the SPI -bus, while also being an RTIO device itself. The sensor iodev can set aside a -small portion of the buffer in front or in back to store some metadata describing -the format of the data. This metadata could then be used in creating a sensor -readings iterator which lazily lets you map over each reading, doing -calculations such as FIR/IIR filtering, or perhaps translating the readings into -other numerical formats with useful measurement units such as SI. RTIO is a -common movement API and allows for such uses while not deciding the mechanism. - -This same sort of setup could be done for other data streams such as audio or -video. - -.. code-block:: C - - /* Note that the sensor device itself can use RTIO to get data over I2C/SPI - * potentially with DMA, but we don't need to worry about that here - * All we need to know is the device tree node_id and that it can be an iodev - */ - RTIO_SENSOR_IODEV(sensor_dev, DEVICE_DT_GET(DT_NODE(super6axis)); - - RTIO_DEFINE(ez_io, 4, 4); - - - /* The sensor driver decides the minimum buffer size for us, we decide how - * many bufs. This could be a typical multiple of a fifo packet the sensor - * produces, ICM42688 for example produces a FIFO packet of 20 bytes in - * 20bit mode at 32KHz so perhaps we'd like to get 4 buffers of 4ms of data - * each in this setup to process on. and its already been defined here for us. - */ - #include - static uint8_t bufs[4][ICM42688_RTIO_BUF_SIZE]; - - int do_some_sensors(void) { - /* Obtain a dmac executor from the DMA device */ - struct device *dma = DEVICE_DT_GET(DT_NODE(dma0)); - const struct rtio_executor *rtio_dma_exec = - dma_rtio_executor(dma); - - /* - * Set the executor for our queue context - */ - rtio_set_executor(ez_io, rtio_dma_exec); - - /* Mostly we want to feed the sensor driver enough buffers to fill while - * we wait and process! Small enough to process quickly with low latency, - * big enough to not spend all the time setting transfers up. - * - * It's assumed here that the sensor has been configured already - * and each FIFO watermark interrupt that occurs it attempts - * to pull from the queue, fill the buffer with a small metadata - * offset using its own rtio request to the SPI bus using DMA. - */ - for(int i = 0; i < 4; i++) { - struct rtio_sqe *read_sqe = rtio_spsc_acquire(ez_io.sq); - - rtio_sqe_prep_read(read_sqe, sensor_dev, RTIO_PRIO_HIGH, bufs[i], ICM42688_RTIO_BUF_SIZE); - } - struct device *sensor = DEVICE_DT_GET(DT_NODE(super6axis)); - struct sensor_reader reader; - struct sensor_channels channels[4] = { - SENSOR_TIMESTAMP_CHANNEL, - SENSOR_CHANNEL(int32_t, SENSOR_ACC_X, 0, SENSOR_RAW), - SENSOR_CHANNEL(int32_t SENSOR_ACC_Y, 0, SENSOR_RAW), - SENSOR_CHANNEL(int32_t, SENSOR_ACC_Z, 0, SENSOR_RAW), - }; - while (true) { - /* call will wait for one completion event */ - rtio_submit(ez_io, 1); - struct rtio_cqe *cqe = rtio_spsc_consume(ez_io.cq); - if(cqe->result < 0) { - LOG_ERR("read failed!"); - goto next; - } - - /* Bytes read into the buffer */ - int32_t bytes_read = cqe->result; - - /* Retrieve soon to be reusable buffer pointer from completion */ - uint8_t *buf = cqe->userdata; - - - /* Get an iterator (reader) that obtains sensor readings in integer - * form, 16 bit signed values in the native sensor reading format - */ - res = sensor_reader(sensor, buf, cqe->result, &reader, channels, - sizeof(channels)); - __ASSERT(res == 0); - while(sensor_reader_next(&reader)) { - printf("time(raw): %d, acc (x,y,z): (%d, %d, %d)\n", - channels[0].value.u32, channels[1].value.i32, - channels[2].value.i32, channels[3].value.i32); - } - - next: - /* Release completion queue event */ - rtio_spsc_release(ez_io.cq); - - /* resubmit a read request with the newly freed buffer to the sensor */ - struct rtio_sqe *read_sqe = rtio_spsc_acquire(ez_io.sq); - rtio_sqe_prep_read(read_sqe, sensor_dev, RTIO_PRIO_HIGH, buf, ICM20649_RTIO_BUF_SIZE); - } - } - API Reference ************* diff --git a/doc/services/sensing/index.rst b/doc/services/sensing/index.rst index 99fdc48d6b7..fac113a1772 100644 --- a/doc/services/sensing/index.rst +++ b/doc/services/sensing/index.rst @@ -197,7 +197,7 @@ Sensor Sample Value The ``header`` defines a **base_timestamp**, and each element in the **readings[]** array defines **timestamp_delta**. - The **timestamp_delta** is is in relation to the previous **readings** (or the **base_timestamp**) + The **timestamp_delta** is in relation to the previous **readings** (or the **base_timestamp**) For example: @@ -241,7 +241,7 @@ Device Tree Configuration Sensing subsystem using device tree to configuration all sensor instances and their properties, reporting relationships. -See the example :zephyr_file:`samples/subsys/sensing/simple/boards/native_posix.overlay` +See the example :zephyr_file:`samples/subsys/sensing/simple/boards/native_sim.overlay` API Reference ************* diff --git a/doc/services/settings/index.rst b/doc/services/settings/index.rst index 61f0a2b82a7..fa6d7360052 100644 --- a/doc/services/settings/index.rst +++ b/doc/services/settings/index.rst @@ -19,8 +19,7 @@ element for the package ``id``. Convenience routines are provided for converting a key value to and from a string type. -For an example of the settings subsystem refer to -:ref:`the sample `. +For an example of the settings subsystem refer to :zephyr:code-sample:`settings` sample. .. note:: diff --git a/doc/services/shell/index.rst b/doc/services/shell/index.rst index 6cdb0020bf8..7f8f6f0fd57 100644 --- a/doc/services/shell/index.rst +++ b/doc/services/shell/index.rst @@ -43,6 +43,7 @@ interaction is required. This module is a Unix-like shell with these features: The module can be connected to any transport for command input and output. At this point, the following transport layers are implemented: +* MQTT * Segger RTT * SMP * Telnet @@ -74,6 +75,29 @@ procedure: to the shell. +Telnet Backend +============== + +Enabling :kconfig:option:`CONFIG_SHELL_BACKEND_TELNET` will allow users to use telnet +as a shell backend. Connecting to it can be done using PuTTY or any ``telnet`` client. +For example: + +.. code-block:: none + + telnet + +By default the telnet client won't handle telnet commands and configuration. Although +command support can be enabled with :kconfig:option:`CONFIG_SHELL_TELNET_SUPPORT_COMMAND`. +This will give the telnet client access to a very limited set of supported commands but +still can be turned on if needed. One of the command options it supports is the ``ECHO`` +option. This will allow the client to be in character mode (character at a time), +similar to a UART backend in that regard. This will make the client send a character +as soon as it is typed having the effect of increasing the network traffic +considerably. For that cost, it will enable the line editing, +`tab completion `_, and `history `_ +features of the shell. + + Commands ******** @@ -427,6 +451,7 @@ These commands are activated by :kconfig:option:`CONFIG_SHELL_CMDS` set to ``y`` case of Bluetooth shell to limit the amount of transferred bytes. * :command:`stats` - Shows shell statistics. +.. _tab-feature: Tab Feature *********** @@ -447,12 +472,14 @@ the shell will do one of 3 possible things: :align: center :alt: Tab Feature usage example +.. _history-feature: + History Feature *************** This feature enables commands history in the shell. It is activated by: :kconfig:option:`CONFIG_SHELL_HISTORY` set to ``y``. History can be accessed -using keys: :kbd:`↑` :kbd:`↓` or :kbd:`Ctrl + n` and :kbd:`Ctrl + p` +using keys: :kbd:`↑` :kbd:`↓` or :kbd:`Ctrl+n` and :kbd:`Ctrl+p` if meta keys are active. Number of commands that can be stored depends on size of :kconfig:option:`CONFIG_SHELL_HISTORY_BUFFER` parameter. @@ -486,36 +513,36 @@ The shell module supports the following meta keys: * - Meta keys - Action - * - :kbd:`Ctrl + a` + * - :kbd:`Ctrl+a` - Moves the cursor to the beginning of the line. - * - :kbd:`Ctrl + b` + * - :kbd:`Ctrl+b` - Moves the cursor backward one character. - * - :kbd:`Ctrl + c` + * - :kbd:`Ctrl+c` - Preserves the last command on the screen and starts a new command in a new line. - * - :kbd:`Ctrl + d` + * - :kbd:`Ctrl+d` - Deletes the character under the cursor. - * - :kbd:`Ctrl + e` + * - :kbd:`Ctrl+e` - Moves the cursor to the end of the line. - * - :kbd:`Ctrl + f` + * - :kbd:`Ctrl+f` - Moves the cursor forward one character. - * - :kbd:`Ctrl + k` + * - :kbd:`Ctrl+k` - Deletes from the cursor to the end of the line. - * - :kbd:`Ctrl + l` + * - :kbd:`Ctrl+l` - Clears the screen and leaves the currently typed command at the top of the screen. - * - :kbd:`Ctrl + n` + * - :kbd:`Ctrl+n` - Moves in history to next entry. - * - :kbd:`Ctrl + p` + * - :kbd:`Ctrl+p` - Moves in history to previous entry. - * - :kbd:`Ctrl + u` + * - :kbd:`Ctrl+u` - Clears the currently typed command. - * - :kbd:`Ctrl + w` + * - :kbd:`Ctrl+w` - Removes the word or part of the word to the left of the cursor. Words separated by period instead of space are treated as one word. - * - :kbd:`Alt + b` + * - :kbd:`Alt+b` - Moves the cursor backward one word. - * - :kbd:`Alt + f` + * - :kbd:`Alt+f` - Moves the cursor forward one word. This feature is activated by :kconfig:option:`CONFIG_SHELL_METAKEYS` set to ``y``. @@ -634,21 +661,21 @@ backend and the Log RTT backend does not work by default, because both default to channel ``0``. There are two options: 1. The Shell buffer can use an alternate channel, for example using -:kconfig:option:`SHELL_BACKEND_RTT_BUFFER` set to ``1``. +:kconfig:option:`CONFIG_SHELL_BACKEND_RTT_BUFFER` set to ``1``. This allows monitoring the log using `JLinkRTTViewer `_ while a script interfaces over channel 1. 2. The Log buffer can use an alternate channel, for example using -:kconfig:option:`LOG_BACKEND_RTT_BUFFER` set to ``1``. +:kconfig:option:`CONFIG_LOG_BACKEND_RTT_BUFFER` set to ``1``. This allows interactive use of the shell through JLinkRTTViewer, while the log is written to file. .. warning:: Regardless of the channel selection, the RTT log backend must be explicitly - enabled using :kconfig:option:`LOG_BACKEND_RTT` set to ``y``, because it + enabled using :kconfig:option:`CONFIG_LOG_BACKEND_RTT` set to ``y``, because it defaults to ``n`` when the Shell RTT backend is also enabled using - :kconfig:option:`SHELL_BACKEND_RTT` being set to ``y``. + :kconfig:option:`CONFIG_SHELL_BACKEND_RTT` being set to ``y``. Usage ***** diff --git a/doc/services/smf/index.rst b/doc/services/smf/index.rst index d82de94513a..d5f1f918471 100644 --- a/doc/services/smf/index.rst +++ b/doc/services/smf/index.rst @@ -3,6 +3,8 @@ State Machine Framework ####################### +.. highlight:: c + Overview ======== diff --git a/doc/services/storage/disk/nvme.rst b/doc/services/storage/disk/nvme.rst index 3c6f9713a6a..4f8f94818f2 100644 --- a/doc/services/storage/disk/nvme.rst +++ b/doc/services/storage/disk/nvme.rst @@ -67,3 +67,14 @@ Options Note that NVME requires the target to support PCIe multi-vector MSI-X in order to function. * :kconfig:option:`CONFIG_NVME_MAX_NAMESPACES` + +Important note for users +************************ + +NVMe specifications mandate the data buffer to be placed in a dword (4 bytes) aligned address. +While this is not a problem for advanced OS managing virtual memory and dynamic allocations +below the user processes, this can become an issue in Zephyr as soon as buffer addresses +map directly to physical memory. + +At this stage then, it is up to the user to make sure the buffer address being provided to +:c:func:`disk_access_read` and :c:func:`disk_access_write` are dword aligned. diff --git a/doc/services/tracing/index.rst b/doc/services/tracing/index.rst index 9c06c3d3fc8..eb32d385b31 100644 --- a/doc/services/tracing/index.rst +++ b/doc/services/tracing/index.rst @@ -107,7 +107,7 @@ supported in Zephyr). To enable tracing support with `SEGGER SystemView`_ add the configuration option :kconfig:option:`CONFIG_SEGGER_SYSTEMVIEW` to your project configuration file and set it to *y*. For example, this can be added to the -:ref:`synchronization_sample` to visualize fast switching between threads. +:zephyr:code-sample:`synchronization` sample to visualize fast switching between threads. SystemView can also be used for post-mortem tracing, which can be enabled with `CONFIG_SEGGER_SYSVIEW_POST_MORTEM_MODE`. In this mode, a debugger can be attached after the system has crashed using ``west attach`` after which the @@ -154,23 +154,25 @@ Examples include: not be supported by the other tracing systems The following functions can be defined by the user: -- ``void sys_trace_thread_create_user(struct k_thread *thread)`` -- ``void sys_trace_thread_abort_user(struct k_thread *thread)`` -- ``void sys_trace_thread_suspend_user(struct k_thread *thread)`` -- ``void sys_trace_thread_resume_user(struct k_thread *thread)`` -- ``void sys_trace_thread_name_set_user(struct k_thread *thread)`` -- ``void sys_trace_thread_switched_in_user(struct k_thread *thread)`` -- ``void sys_trace_thread_switched_out_user(struct k_thread *thread)`` -- ``void sys_trace_thread_info_user(struct k_thread *thread)`` -- ``void sys_trace_thread_sched_ready_user(struct k_thread *thread)`` -- ``void sys_trace_thread_pend_user(struct k_thread *thread)`` -- ``void sys_trace_thread_priority_set_user(struct k_thread *thread, int prio)`` -- ``void sys_trace_isr_enter_user(int nested_interrupts)`` -- ``void sys_trace_isr_exit_user(int nested_interrupts)`` -- ``void sys_trace_idle_user()`` -Enable this format with the :kconfig:option:`CONFIG_TRACING_USER` option. +.. code-block:: c + + void sys_trace_thread_create_user(struct k_thread *thread); + void sys_trace_thread_abort_user(struct k_thread *thread); + void sys_trace_thread_suspend_user(struct k_thread *thread); + void sys_trace_thread_resume_user(struct k_thread *thread); + void sys_trace_thread_name_set_user(struct k_thread *thread); + void sys_trace_thread_switched_in_user(struct k_thread *thread); + void sys_trace_thread_switched_out_user(struct k_thread *thread); + void sys_trace_thread_info_user(struct k_thread *thread); + void sys_trace_thread_sched_ready_user(struct k_thread *thread); + void sys_trace_thread_pend_user(struct k_thread *thread); + void sys_trace_thread_priority_set_user(struct k_thread *thread, int prio); + void sys_trace_isr_enter_user(int nested_interrupts); + void sys_trace_isr_exit_user(int nested_interrupts); + void sys_trace_idle_user(); +Enable this format with the :kconfig:option:`CONFIG_TRACING_USER` option. Transport Backends ****************** @@ -179,7 +181,7 @@ The following backends are currently supported: * UART * USB -* File (Using native posix port) +* File (Using the native port with POSIX architecture based targets) * RTT (With SystemView) * RAM (buffer to be retrieved by a debugger) @@ -189,14 +191,14 @@ Using Tracing The sample :zephyr_file:`samples/subsys/tracing` demonstrates tracing with different formats and backends. -To get started, the simplest way is to use the CTF format with the ``native_posix`` +To get started, the simplest way is to use the CTF format with the :ref:`native_sim ` port, build the sample as follows: .. zephyr-app-commands:: :tool: all :app: samples/subsys/tracing - :board: native_posix - :gen-args: -DCONF_FILE=prj_native_posix_ctf.conf + :board: native_sim + :gen-args: -DCONF_FILE=prj_native_ctf.conf :goals: build You can then run the resulting binary with the option ``-trace-file`` to generate @@ -341,14 +343,14 @@ Locking may not be needed if multiple independent channels are available. ``emit(a,thread_id); emit(b,thread_id); emit(c,thread_id);`` - The system has atomic write but one shared channel - E.g. ``native_posix`` or board with DMA. May or may not need locking. + E.g. ``native_sim`` or board with DMA. May or may not need locking. ``emit(a ## b ## c); /* Concat to buffer */`` ``lock(); emit(a); emit(b); emit(c); release(); /* No extra mem */`` - The system has atomic write and many channels - E.g. native_posix or board with multi-channel DMA. Lock-free. + E.g. native_sim or board with multi-channel DMA. Lock-free. ``emit(a ## b ## c, thread_id);`` diff --git a/doc/services/virtualization/ivshmem.rst b/doc/services/virtualization/ivshmem.rst index 673b083794c..4325c261fc0 100644 --- a/doc/services/virtualization/ivshmem.rst +++ b/doc/services/virtualization/ivshmem.rst @@ -46,7 +46,7 @@ Zephyr also supports ivshmem-v2: https://github.com/siemens/jailhouse/blob/master/Documentation/ivshmem-v2-specification.md This is primarily used for IPC in the Jailhouse hypervisor -(e.g. :ref:`eth_ivshmem_sample`). It is also possible to use ivshmem-v2 without +(e.g. :zephyr:code-sample:`eth-ivshmem`). It is also possible to use ivshmem-v2 without Jailhouse by building the Siemens fork of QEMU, and modifying the QEMU launch flags: https://github.com/siemens/qemu/tree/wip/ivshmem2 diff --git a/doc/services/zbus/images/zbus_observation_mask.svg b/doc/services/zbus/images/zbus_observation_mask.svg new file mode 100644 index 00000000000..4405a8f3e4a --- /dev/null +++ b/doc/services/zbus/images/zbus_observation_mask.svg @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/services/zbus/images/zbus_operations.svg b/doc/services/zbus/images/zbus_operations.svg index d0f96881745..6ed8648e9e0 100644 --- a/doc/services/zbus/images/zbus_operations.svg +++ b/doc/services/zbus/images/zbus_operations.svg @@ -1,3 +1,52 @@ - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/services/zbus/images/zbus_publishing_process_example.svg b/doc/services/zbus/images/zbus_publishing_process_example.svg index 0e9ba3dc351..84fbbdd6b1f 100644 --- a/doc/services/zbus/images/zbus_publishing_process_example.svg +++ b/doc/services/zbus/images/zbus_publishing_process_example.svg @@ -1,3 +1,71 @@ - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/services/zbus/images/zbus_publishing_process_example2.svg b/doc/services/zbus/images/zbus_publishing_process_example2.svg new file mode 100644 index 00000000000..f71a3c29ca2 --- /dev/null +++ b/doc/services/zbus/images/zbus_publishing_process_example2.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/services/zbus/images/zbus_publishing_process_example_scenario.svg b/doc/services/zbus/images/zbus_publishing_process_example_scenario.svg index 6d473a45a83..abcb27de217 100644 --- a/doc/services/zbus/images/zbus_publishing_process_example_scenario.svg +++ b/doc/services/zbus/images/zbus_publishing_process_example_scenario.svg @@ -1,3 +1,35 @@ - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/services/zbus/images/zbus_type_of_observers.svg b/doc/services/zbus/images/zbus_type_of_observers.svg new file mode 100644 index 00000000000..34b1be73307 --- /dev/null +++ b/doc/services/zbus/images/zbus_type_of_observers.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/doc/services/zbus/index.rst b/doc/services/zbus/index.rst index 29c2d86eb06..ca8ab6142a8 100644 --- a/doc/services/zbus/index.rst +++ b/doc/services/zbus/index.rst @@ -1,9 +1,16 @@ .. _zbus: -Zephyr message bus (zbus) -######################### +Zephyr bus (zbus) +################# -The :dfn:`Zephyr message bus - Zbus` is a lightweight and flexible message bus enabling a simple way for threads to talk to one another. +.. + Note to documentation authors: the diagrams included in this documentation page were designed + using the following Figma library: + https://www.figma.com/community/file/1292866458780627559/zbus-diagram-assets + + +The :dfn:`Zephyr bus - zbus` is a lightweight and flexible software bus enabling a simple way for +threads to talk to one another in a many-to-many way. .. contents:: :local: @@ -11,8 +18,19 @@ The :dfn:`Zephyr message bus - Zbus` is a lightweight and flexible message bus e Concepts ******** +Threads can send messages to one or more observers using zbus. It makes the many-to-many +communication possible. The bus implements message-passing and publish/subscribe communication +paradigms that enable threads to communicate synchronously or asynchronously through shared memory. -Threads can broadcast messages to all interested observers using zbus. Many-to-many communication is possible. The bus implements message-passing and publish/subscribe communication paradigms that enable threads to communicate synchronously or asynchronously through shared memory. The communication through zbus is channel-based, where threads publish and read to and from using messages. Additionally, threads can observe channels and receive notifications from the bus when the channels are modified. The figure below shows an example of a typical application using zbus in which the application logic (hardware independent) talks to other threads via message bus. Note that the threads are decoupled from each other because they only use zbus' channels and do not need to know each other to talk. +The communication through zbus is channel-based. Threads (or callbacks) use channels to exchange +messages. Additionally, besides other actions, threads can publish and observe channels. When a +thread publishes a message on a channel, the bus will make the message available to all the +published channel's observers. Based on the observer's type, it can access the message directly, +receive a copy of it, or even receive only a reference of the published channel. + +The figure below shows an example of a typical application using zbus in which the application logic +(hardware independent) talks to other threads via software bus. Note that the threads are decoupled +from each other because they only use zbus channels and do not need to know each other to talk. .. figure:: images/zbus_overview.svg @@ -23,36 +41,104 @@ Threads can broadcast messages to all interested observers using zbus. Many-to-m The bus comprises: -* Set of channels that consists of a unique identifier, its control metadata information, and the message itself; -* :dfn:`Virtual distributed event dispatcher` (VDED), the bus logic responsible for sending notifications to the observers. The VDED logic runs inside the publishing action in the same thread context, giving the bus an idea of a distributed execution. When a thread publishes to a channel, it also propagates the notifications to the observers; -* Threads (subscribers) and callbacks (listeners) publishing, reading, and receiving notifications from the bus. +* Set of channels that consists of the control metadata information, and the message itself; +* :dfn:`Virtual Distributed Event Dispatcher` (VDED), the bus logic responsible for sending + notifications/messages to the observers. The VDED logic runs inside the publishing action in the same + thread context, giving the bus an idea of a distributed execution. When a thread publishes to a + channel, it also propagates the notifications to the observers; +* Threads (subscribers and message subscribers) and callbacks (listeners) publishing, reading, and + receiving notifications from the bus. .. figure:: images/zbus_anatomy.svg - :alt: Zbus anatomy + :alt: ZBus anatomy + :width: 70% + + ZBus anatomy. + +The bus makes the publish, read, claim, finish, notify, and subscribe actions available over +channels. Publishing, reading, claiming, and finishing are available in all RTOS thread contexts. +However, it cannot run inside Interrupt Service Routines (ISR) because it uses mutexes to control +channel access, and mutexes cannot work appropriately inside ISRs. The publish and read operations +are simple and fast; the procedure is a mutex locking followed by a memory copy to and from a shared +memory region and then a mutex unlocking. Another essential aspect of zbus is the observers. There +are three types of observers: + +.. figure:: images/zbus_type_of_observers.svg + :alt: ZBus observers type :width: 70% - Zbus anatomy. + ZBus observers. + +* Listeners, a callback that the event dispatcher executes every time an observed channel is + published or notified; +* Subscriber, a thread-based observer that relies internally on a message queue where the event + dispatcher puts a changed channel's reference every time an observed channel is published or + notified. Note this kind of observer does not receive the message itself. It should read the + message from the channel after receiving the notification; +* Message subscribers, a thread-based observer that relies internally on a FIFO where the event + dispatcher puts a copy of the message every time an observed channel is published or notified. + +Channel observation structures define the relationship between a channel and its observers. For +every observation, a pair channel/observer. Developers can statically allocate observation using the +:c:macro:`ZBUS_CHAN_DEFINE` or :c:macro:`ZBUS_CHAN_ADD_OBS`. There are also runtime observers, +enabling developers to create runtime observations. It is possible to disable an observer entirely +or observations individually. The event dispatcher will ignore disabled observers and observations. + +.. figure:: images/zbus_observation_mask.svg + :alt: ZBus observation mask. + :width: 75% -The bus makes the publish, read, and subscribe actions available over channels. Publishing and reading are available in all RTOS thread contexts. However, it cannot run inside Interrupt Service Routines (ISR) because it uses mutexes to control channels access, and mutexes cannot work appropriately inside ISRs. The publish and read operations are simple and fast; the procedure is a mutex locking followed by a memory copy to and from a shared memory region and then a mutex unlocking. Another essential aspect of zbus is the observers, which can be: + ZBus observation mask. -* Static; defined in compile time. It is not possible to remove it at runtime, but it is possible to suppress it by calling the :c:func:`zbus_obs_set_enable`; -* Dynamic; it can be added and removed to and from a channel at runtime. +The above figure illustrates some states, from (a) to (d), for channels from ``C1`` to ``C5``, +``Subscriber 1``, and the observations. The last two are in orange to indicate they are dynamically +allocated (runtime observation). (a) shows that the observer and all observations are enabled. (b) +shows the observer is disabled, so the event dispatcher will ignore it. (c) shows the observer +enabled. However, there is one static observervation disabled. The event dispatcher will only stop +sending notifications from channel ``C3``. In (d), the event dispatcher will stop sending +notifications from channels ``C3`` and ``C5`` to ``Subscriber 1``. -For illustration purposes, suppose a usual sensor-based solution in the figure below. When the timer is triggered, it pushes an action to a work queue that publishes to the ``Start trigger`` channel. As the sensor thread subscribed to the ``Start trigger`` channel, it fetches the sensor data. Notice the VDED executes the blink callback because it also listens to the ``Start trigger`` channel. When the sensor data is ready, the sensor thread publishes it to the ``Sensor data`` channel. The core thread, as a ``Sensor data`` channel subscriber, processes the sensor data and stores it in an internal sample buffer. It repeats until the sample buffer is full; when it happens, the core thread aggregates the sample buffer information, prepares a package, and publishes that to the ``Payload`` channel. The Lora thread receives that because it is a ``Payload`` channel subscriber and sends the payload to the cloud. When it completes the transmission, the Lora thread publishes to the ``Transmission done`` channel. The VDED executes the blink callback again since it listens to the ``Transmission done`` channel. +Suppose a usual sensor-based solution is in the figure below for illustration purposes. When +triggered, the timer pushes an action to a work queue that publishes to the ``Trigger`` channel. As +the sensor thread subscribed to the ``Trigger`` channel, it receives the sensor data. Notice the +VDED executes the ``Blink`` because it also listens to the ``Trigger`` channel. When the sensor data +is ready, the sensor thread publishes it to the ``Sensor data`` channel. The core thread receives +the message as a ``Sensor data`` channel message subscriber, processes the sensor data, and stores +it in an internal sample buffer. It repeats until the sample buffer is full; when it happens, the +core thread aggregates the sample buffer information, prepares a package, and publishes that to the +``Payload`` channel. The Lora thread receives that because it is a ``Payload`` channel message +subscriber and sends the payload to the cloud. When it completes the transmission, the Lora thread +publishes to the ``Transmission done`` channel. The VDED executes the ``Blink`` again since it +listens to the ``Transmission done`` channel. .. figure:: images/zbus_operations.svg - :alt: Zbus sensor-based application - :width: 80% + :alt: ZBus sensor-based application + :width: 85% - Zbus sensor-based application. + ZBus sensor-based application. -This way of implementing the solution makes the application more flexible, enabling us to change things independently. For example, we want to change the trigger from a timer to a button press. We can do that, and the change does not affect other parts of the system. Likewise, we would like to change the communication interface from LoRa to Bluetooth; we only need to change the LoRa thread. No other change is required in order to make that work. Thus, the developer would do that for every block of the image. Based on that, there is a sign zbus promotes decoupling in the system architecture. +This way of implementing the solution makes the application more flexible, enabling us to change +things independently. For example, we want to change the trigger from a timer to a button press. We +can do that, and the change does not affect other parts of the system. Likewise, we would like to +change the communication interface from LoRa to Bluetooth; we only need to change the LoRa thread. +No other change is required in order to make that work. Thus, the developer would do that for every +block of the image. Based on that, there is a sign zbus promotes decoupling in the system +architecture. -Another important aspect of using zbus is the reuse of system modules. If a code portion with well-defined behaviors (we call that module) only uses zbus channels and not hardware interfaces, it can easily be reused in other solutions. The new solution must implement the interfaces (set of channels) the module needs to work. That indicates zbus could improve the module reuse. +Another important aspect of using zbus is the reuse of system modules. If a code portion with +well-defined behaviors (we call that module) only uses zbus channels and not hardware interfaces, it +can easily be reused in other solutions. The new solution must implement the interfaces (set of +channels) the module needs to work. That indicates zbus could improve the module reuse. -The last important note is the zbus solution reach. We can count on many ways of using zbus to enable the developer to be as free as possible to create what they need. For example, messages can be dynamic or static allocated; notifications can be synchronous or asynchronous; the developer can control the channel in so many different ways claiming the channel, developers can add their metadata information to a channel by using the user-data field, the discretionary use of a validator enables the systems to be accurate over message format, and so on. Those characteristics increase the solutions that can be done with zbus and make it a good fit as an open-source community tool. +The last important note is the zbus solution reach. We can count on many ways of using zbus to +enable the developer to be as free as possible to create what they need. For example, messages can +be dynamic or static allocated; notifications can be synchronous or asynchronous; the developer can +control the channel in so many different ways claiming the channel, developers can add their +metadata information to a channel by using the user-data field, the discretionary use of a validator +enables the systems to be accurate over message format, and so on. Those characteristics increase +the solutions that can be done with zbus and make it a good fit as an open-source community tool. .. _Virtual Distributed Event Dispatcher: @@ -60,108 +146,232 @@ The last important note is the zbus solution reach. We can count on many ways of Virtual Distributed Event Dispatcher ==================================== -The VDED execution always happens in the publishing's (thread) context. So it cannot occur inside an Interrupt Service Routine (ISR). Therefore, the IRSs must only access channels indirectly. The basic description of the execution is as follows: +The VDED execution always happens in the publishing's (thread) context. So it cannot occur inside an +Interrupt Service Routine (ISR). Therefore, the IRSs must only access channels indirectly. The basic +description of the execution is as follows: * The channel mutex is acquired; * The channel receives the new message via direct copy (by a raw :c:func:`memcpy`); -* The event dispatcher logic executes the listeners and pushes the channel's reference to the subscribers' notification message queue in the same sequence they appear on the channel observers' list. The listeners can perform non-copy quick access to the constant message reference directly (via the :c:func:`zbus_chan_const_msg` function) since the channel is still locked; +* The event dispatcher logic executes the listeners, sends a copy of the message to the message + subscribers, and pushes the channel's reference to the subscribers' notification message queue in + the same sequence they appear on the channel observers' list. The listeners can perform non-copy + quick access to the constant message reference directly (via the :c:func:`zbus_chan_const_msg` + function) since the channel is still locked; * At last, the publishing function unlocks the channel. -To illustrate the VDED execution, consider the example illustrated below. We have four threads in ascending priority T1, T2, T3, and T4 (the highest priority); two listeners, L1 and L2; and channel A. Supposing L1, L2, T2, T3, and T4 observer channel A. +To illustrate the VDED execution, consider the example illustrated below. We have four threads in +ascending priority ``S1``, ``MS2``, ``MS1``, and ``T1`` (the highest priority); two listeners, +``L1`` and ``L2``; and channel A. Supposing ``L1``, ``L2``, ``MS1``, ``MS2``, and ``S1`` observer +channel A. .. figure:: images/zbus_publishing_process_example_scenario.svg - :alt: Zbus example scenario - :width: 55% + :alt: ZBus example scenario + :width: 45% - Zbus VDED execution example scenario. + ZBus VDED execution example scenario. The following code implements channel A. Note the ``struct a_msg`` is illustrative only. .. code-block:: c - ZBUS_CHAN_DEFINE(a_chan, /* Name */ - struct a_msg, /* Message type */ + ZBUS_CHAN_DEFINE(a_chan, /* Name */ + struct a_msg, /* Message type */ - NULL, /* Validator */ - NULL, /* User Data */ - ZBUS_OBSERVERS(L1, L2, T2, T3, T4), /* observers */ - ZBUS_MSG_INIT(0) /* Initial value {0} */ + NULL, /* Validator */ + NULL, /* User Data */ + ZBUS_OBSERVERS(L1, L2, MS1, MS2, S1), /* observers */ + ZBUS_MSG_INIT(0) /* Initial value {0} */ ); -In the figure below, the letters indicate some action related to the VDED execution. The X-axis represents the time, and the Y-axis represents the priority of threads. Channel A's message, represented by a voice balloon, is only one memory portion (shared memory). It appears several times only as an illustration of the message at that point in time. +In the figure below, the letters indicate some action related to the VDED execution. The X-axis +represents the time, and the Y-axis represents the priority of threads. Channel A's message, +represented by a voice balloon, is only one memory portion (shared memory). It appears several times +only as an illustration of the message at that point in time. .. figure:: images/zbus_publishing_process_example.svg - :alt: Zbus publish processing detail + :alt: ZBus publish processing detail :width: 85% - Zbus VDED execution detail. + ZBus VDED execution detail for priority T1 > MS1 > MS2 > S1. -The figure above illustrates the actions performed during the VDED execution when T1 publishes to channel A. Thus, the figure below describes the actions (represented by a letter) of the VDED execution. +The figure above illustrates the actions performed during the VDED execution when T1 publishes to +channel A. Thus, the table below describes the activities (represented by a letter) of the VDED +execution. The scenario considers the following priorities: T1 > MS1 > MS2 > S1. T1 has the highest +priority. -.. list-table:: VDED execution steps in detail. +.. list-table:: VDED execution steps in detail for priority T1 > MS1 > MS2 > S1. :widths: 5 65 :header-rows: 1 * - Actions - Description * - a - - T1 starts and at some point, publishes to channel A. + - T1 starts and, at some point, publishes to channel A. * - b - The publishing (VDED) process starts. The VDED locks the channel A's mutex. * - c - The VDED copies the T1 message to the channel A message. * - d, e - - The VDED executes L1 and L2 in the respective sequence. Inside the listeners, usually, there is a call to the :c:func:`zbus_chan_const_msg` function, which provides a direct constant reference to channel A's message. It is quick, and no copy is needed here. + - The VDED executes L1 and L2 in the respective sequence. Inside the listeners, usually, there + is a call to the :c:func:`zbus_chan_const_msg` function, which provides a direct constant + reference to channel A's message. It is quick, and no copy is needed here. + + * - f, g + - The VDED copies the message and sends that to MS1 and MS2 sequentially. Notice the threads + get ready to execute right after receiving the notification. However, they go to a pending + state because they have less priority than T1. + * - h + - The VDED pushes the notification message to the queue of S1. Notice the thread gets ready to + execute right after receiving the notification. However, it goes to a pending state because + it cannot access the channel since it is still locked. + + * - i + - VDED finishes the publishing by unlocking channel A. The MS1 leaves the pending state and + starts executing. + + * - j + - MS1 finishes execution. The MS2 leaves the pending state and starts executing. + + * - k + - MS2 finishes execution. The S1 leaves the pending state and starts executing. + + * - l, m, n + - The S1 leaves the pending state since channel A is not locked. It gets in the CPU again and + starts executing. As it did receive a notification from channel A, it performed a channel read + (as simple as lock, memory copy, unlock), continues its execution and goes out of the CPU. - * - f, g, h - - The VDED pushes the notification message to queues of T2, T3, and T4 sequentially. Notice the threads get ready to execute right after receiving the notification. However, they go to a pending state because they cannot access the channel since it is still locked. At that moment, the T1 thread gets its priority elevated (priority inheritance due to the mutex) to the highest pending thread (caused by channel A unavailability). In that case, T4's priority. It ensures the T1 will finish the VDED execution as quickly as possible without preemption from threads with priority below the engaged ones. + * - o + - S1 finishes its workload. + + +The figure below illustrates the actions performed during the VDED execution when T1 publishes to +channel A. The scenario considers the following priorities: T1 < MS1 < MS2 < S1. + +.. figure:: images/zbus_publishing_process_example2.svg + :alt: ZBus publish processing detail + :width: 85% + + ZBus VDED execution detail for priority T1 < MS1 < MS2 < S1. + +Thus, the table below describes the activities (represented by a letter) of the VDED execution. + +.. list-table:: VDED execution steps in detail for priority T1 < MS1 < MS2 < S1. + :widths: 5 65 + :header-rows: 1 + + * - Actions + - Description + * - a + - T1 starts and, at some point, publishes to channel A. + * - b + - The publishing (VDED) process starts. The VDED locks the channel A's mutex. + * - c + - The VDED copies the T1 message to the channel A message. + + * - d, e + - The VDED executes L1 and L2 in the respective sequence. Inside the listeners, usually, there + is a call to the :c:func:`zbus_chan_const_msg` function, which provides a direct constant + reference to channel A's message. It is quick, and no copy is needed here. + + * - f + - The VDED copies the message and sends that to MS1. MS1 preempts T1 and starts working. + After that, the T1 regain MCU. + + * - g + - The VDED copies the message and sends that to MS2. MS2 preempts T1 and starts working. + After that, the T1 regain MCU. + + * - h + - The VDED pushes the notification message to the queue of S1. Notice the thread gets ready to + execute right after receiving the notification. However, it goes to a pending state because + it cannot access the channel since it is still locked. At that moment, the T1 thread gets its + priority elevated (priority inheritance due to the mutex) to the highest pending thread + (caused by channel A unavailability). In that case, S1's priority. It ensures the T1 will + finish the VDED execution as quickly as possible without preemption from threads with + priority below the engaged ones. * - i - VDED finishes the publishing by unlocking channel A. - * - j, k - - The T4 leaves the pending state since channel A is not locked. It gets in the CPU again and starts executing. As it did receive a notification from channel A, it performs a channel read (as simple as lock, memory copy, unlock), continues its execution, and goes out the CPU. - - * - l,m, n - - Now, T3 can access the channel. It repeats the same steps from T4 (j and k). T2 does the same. That is the end of the VDED execution! + * - j, k, l + - The S1 leaves the pending state since channel A is not locked. It gets in the CPU again and + starts executing. As it did receive a notification from channel A, it performs a channel read + (as simple as lock, memory copy, unlock), continues its execution, and goes out the CPU. Limitations =========== -Based on the fact that developers can use zbus to solve many different problems, some challenges arise. Zbus will not solve every problem, so it is necessary to analyze the situation to be sure zbus is applicable. For instance, based on the zbus benchmark, it would not be well suited to a high-speed stream of bytes between threads. The `Pipe` kernel object solves this kind of need. +Based on the fact that developers can use zbus to solve many different problems, some challenges +arise. ZBus will not solve every problem, so it is necessary to analyze the situation to be sure +zbus is applicable. For instance, based on the zbus benchmark, it would not be well suited to a +high-speed stream of bytes between threads. The `Pipe` kernel object solves this kind of need. Delivery guarantees ------------------- -Zbus always delivers the messages to the listeners. However, there are no message delivery guarantees for subscribers because zbus only sends the notification, but the message reading depends on the subscriber's implementation. This is because channels have a mutex protected singleton objects for which message transfer is used. In other words, it can be seen as a single size queue where publishers always overwrite if queue is full. It is possible to increase the delivery rate by following design tips: +ZBus always delivers the messages to the listeners and message subscribers. However, there are no +message delivery guarantees for subscribers because zbus only sends the notification, but the +message reading depends on the subscriber's implementation. It is possible to increase the delivery +rate by following design tips: -* Keep the listeners quick-as-possible (deal with them as ISRs). If some processing is needed, consider submitting a work to a work-queue; +* Keep the listeners quick-as-possible (deal with them as ISRs). If some processing is needed, + consider submitting a work to a work-queue; * Try to give producers a high priority to avoid losses; * Leave spare CPU for observers to consume data produced; * Consider using message queues or pipes for intensive byte transfers. +.. warning:: + ZBus uses :zephyr_file:`include/zephyr/net/buf.h` (network buffers) to exchange data with message + subscribers. So, chose carefully the configurations + :kconfig:option:`CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_SIZE` and + :kconfig:option:`CONFIG_HEAP_MEM_POOL_SIZE`. They are crucial to a proper VDED execution + (delivery garantee) considering message subscribers. + +.. warning:: + Subscribers will receive only the reference of the changing channel. A data loss may be perceived + if the channel is published twice before the subscriber reads it. The second publication + overwrites the value from the first. Thus, the subscriber will receive two notifications, but + only the last data is there. + + + +.. _zbus delivery sequence: Message delivery sequence ------------------------- -The listeners (synchronous observers) will follow the channel definition sequence as the notification and message consumption sequence. However, the subscribers, as they have an asynchronous nature, will all receive the notification as the channel definition sequence but only will consume the data when they execute again. Hence, the delivery respects the order, but the priority assigned to the subscribers will define the reaction sequence. The delivery sequence is first the static observers and then the runtime ones. +The message delivery will follow the precedence: + +#. Observers defined in a channel using the :c:macro:`ZBUS_CHAN_DEFINE` (following the definition + sequence); +#. Observers defined using the :c:macro:`ZBUS_CHAN_ADD_OBS` based on the sequence priority + (parameter of the macro); +#. The latest is the runtime observers in the addition sequence using the + :c:func:`zbus_chan_add_obs`. + +.. note:: + The VDED will ignore all disabled observers or observations. Usage ***** -Zbus operation depends on channels and observers. Therefore, it is necessary to determine its message and observers list during the channel definition. A message is a regular C struct; the observer can be a subscriber (asynchronous) or a listener (synchronous). +ZBus operation depends on channels and observers. Therefore, it is necessary to determine its +message and observers list during the channel definition. A message is a regular C struct; the +observer can be a subscriber (asynchronous), a message subscriber (asynchronous), or a listener +(synchronous). -The following code defines and initializes a regular channel and its dependencies. This channel exchanges accelerometer data, for example. +The following code defines and initializes a regular channel and its dependencies. This channel +exchanges accelerometer data, for example. .. code-block:: c @@ -176,7 +386,8 @@ The following code defines and initializes a regular channel and its dependencie NULL, /* Validator */ NULL, /* User Data */ - ZBUS_OBSERVERS(my_listener, my_subscriber), /* observers */ + ZBUS_OBSERVERS(my_listener, my_subscriber, + my_msg_subscriber), /* observers */ ZBUS_MSG_INIT(.x = 0, .y = 0, .z = 0) /* Initial value */ ); @@ -212,13 +423,44 @@ The following code defines and initializes a regular channel and its dependencie } K_THREAD_DEFINE(subscriber_task_id, 512, subscriber_task, NULL, NULL, NULL, 3, 0, 0); -It is possible to add static observers to a channel using the :c:macro:`ZBUS_CHAN_ADD_OBS`. We call that a post-definition static observer. The command enables us to indicate an initialization priority that affects the observers' initialization order. The priority param only affects the post-definition static observers. There is no possibility to overwrite the execution sequence of the static observers. + ZBUS_MSG_SUBSCRIBER_DEFINE(my_msg_subscriber); + static void msg_subscriber_task(void *sub) + { + const struct zbus_channel *chan; + + struct acc_msg acc = {0}; + + while (!zbus_sub_wait_msg(&my_msg_subscriber, &chan, &acc, K_FOREVER)) { + if (&acc_chan == chan) { + LOG_INF("From msg subscriber -> Acc x=%d, y=%d, z=%d", acc.x, acc.y, acc.z); + } + } + } + K_THREAD_DEFINE(msg_subscriber_task_id, 1024, msg_subscriber_task, NULL, NULL, NULL, 3, 0, 0); + + + +It is possible to add static observers to a channel using the :c:macro:`ZBUS_CHAN_ADD_OBS`. We call +that a post-definition static observer. The command enables us to indicate an initialization +priority that affects the observers' initialization order. The sequence priority param only affects +the post-definition static observers. There is no possibility to overwrite the message delivery +sequence of the static observers. .. note:: - It is unnecessary to claim/lock a channel before accessing the message inside the listener since the event dispatcher calls listeners with the notifying channel already locked. Subscribers, however, must claim/lock that or use regular read operations to access the message after being notified. + It is unnecessary to claim/lock a channel before accessing the message inside the listener since + the event dispatcher calls listeners with the notifying channel already locked. Subscribers, + however, must claim/lock that or use regular read operations to access the message after being + notified. -Channels can have a ``validator function`` that enables a channel to accept only valid messages. Publish attempts invalidated by hard channels will return immediately with an error code. This allows original creators of a channel to exert some authority over other developers/publishers who may want to piggy-back on their channels. The following code defines and initializes a :dfn:`hard channel` and its dependencies. Only valid messages can be published to a :dfn:`hard channel`. It is possible because a ``validator function`` was passed to the channel's definition. In this example, only messages with ``move`` equal to 0, -1, and 1 are valid. Publish function will discard all other values to ``move``. +Channels can have a `validator function` that enables a channel to accept only valid messages. +Publish attempts invalidated by hard channels will return immediately with an error code. This +allows original creators of a channel to exert some authority over other developers/publishers who +may want to piggy-back on their channels. The following code defines and initializes a :dfn:`hard +channel` and its dependencies. Only valid messages can be published to a :dfn:`hard channel`. It is +possible because a `validator function` was passed to the channel's definition. In this example, +only messages with ``move`` equal to 0, -1, and 1 are valid. Publish function will discard all other +values to ``move``. .. code-block:: c @@ -251,7 +493,11 @@ The following sections describe in detail how to use zbus features. Publishing to a channel ======================= -Messages are published to a channel in zbus by calling :c:func:`zbus_chan_pub`. For example, the following code builds on the examples above and publishes to channel ``acc_chan``. The code is trying to publish the message ``acc1`` to channel ``acc_chan``, and it will wait up to one second for the message to be published. Otherwise, the operation fails. As can be inferred from the code sample, it's OK to use stack allocated messages since VDED copies the data internally. +Messages are published to a channel in zbus by calling :c:func:`zbus_chan_pub`. For example, the +following code builds on the examples above and publishes to channel ``acc_chan``. The code is +trying to publish the message ``acc1`` to channel ``acc_chan``, and it will wait up to one second +for the message to be published. Otherwise, the operation fails. As can be inferred from the code +sample, it's OK to use stack allocated messages since VDED copies the data internally. .. code-block:: c @@ -266,7 +512,9 @@ Messages are published to a channel in zbus by calling :c:func:`zbus_chan_pub`. Reading from a channel ====================== -Messages are read from a channel in zbus by calling :c:func:`zbus_chan_read`. So, for example, the following code tries to read the channel ``acc_chan``, which will wait up to 500 milliseconds to read the message. Otherwise, the operation fails. +Messages are read from a channel in zbus by calling :c:func:`zbus_chan_read`. So, for example, the +following code tries to read the channel ``acc_chan``, which will wait up to 500 milliseconds to +read the message. Otherwise, the operation fails. .. code-block:: c @@ -277,12 +525,20 @@ Messages are read from a channel in zbus by calling :c:func:`zbus_chan_read`. So Do not use this function inside an ISR. .. warning:: - Choose the timeout of :c:func:`zbus_chan_read` after receiving a notification from :c:func:`zbus_sub_wait` carefully because the channel will always be unavailable during the VDED execution. Using ``K_NO_WAIT`` for reading is highly likely to return a timeout error if there are more than one subscriber. For example, consider the VDED illustration again and notice how ``T3`` and ``T4's`` read attempts would definitely fail with K_NO_WAIT. For more details, check the `Virtual Distributed Event Dispatcher`_ section. + Choose the timeout of :c:func:`zbus_chan_read` after receiving a notification from + :c:func:`zbus_sub_wait` carefully because the channel will always be unavailable during the VDED + execution. Using ``K_NO_WAIT`` for reading is highly likely to return a timeout error if there + are more than one subscriber. For example, consider the VDED illustration again and notice how + ``S1`` read attempts would definitely fail with K_NO_WAIT. For more details, check + the `Virtual Distributed Event Dispatcher`_ section. -Forcing channel notification -============================ +Notifying a channel +=================== -It is possible to force zbus to notify a channel's observers by calling :c:func:`zbus_chan_notify`. For example, the following code builds on the examples above and forces a notification for the channel ``acc_chan``. Note this can send events with no message, which does not require any data exchange. See the code example under `Claim and finish a channel`_ where this may become useful. +It is possible to force zbus to notify a channel's observers by calling :c:func:`zbus_chan_notify`. +For example, the following code builds on the examples above and forces a notification for the +channel ``acc_chan``. Note this can send events with no message, which does not require any data +exchange. See the code example under `Claim and finish a channel`_ where this may become useful. .. code-block:: c @@ -294,7 +550,13 @@ It is possible to force zbus to notify a channel's observers by calling :c:func: Declaring channels and observers ================================ -For accessing channels or observers from files other than its defining files, it is necessary to declare them by calling :c:macro:`ZBUS_CHAN_DECLARE` and :c:macro:`ZBUS_OBS_DECLARE`. In other words, zbus channel definitions and declarations with the same channel names in different files would point to the same (global) channel. Thus, developers should be careful about existing channels, and naming new channels or linking will fail. It is possible to declare more than one channel or observer on the same call. The following code builds on the examples above and displays the defined channels and observers. +For accessing channels or observers from files other than its defining files, it is necessary to +declare them by calling :c:macro:`ZBUS_CHAN_DECLARE` and :c:macro:`ZBUS_OBS_DECLARE`. In other +words, zbus channel definitions and declarations with the same channel names in different files +would point to the same (global) channel. Thus, developers should be careful about existing +channels, and naming new channels or linking will fail. It is possible to declare more than one +channel or observer on the same call. The following code builds on the examples above and displays +the defined channels and observers. .. code-block:: c @@ -305,7 +567,14 @@ For accessing channels or observers from files other than its defining files, it Iterating over channels and observers ===================================== -Zbus subsystem also implements :ref:`Iterable Sections ` for channels and observers, for which there are supporting APIs like :c:func:`zbus_iterate_over_channels`, :c:func:`zbus_iterate_over_channels_with_user_data`, :c:func:`zbus_iterate_over_observers` and :c:func:`zbus_iterate_over_observers_with_user_data`. This feature enables developers to call a procedure over all declared channels, where the procedure parameter is a :c:struct:`zbus_channel`. The execution sequence is in the alphabetical name order of the channels (see :ref:`Iterable Sections ` documentation for details). Zbus also implements this feature for :c:struct:`zbus_observer`. +ZBus subsystem also implements :ref:`Iterable Sections ` for channels and +observers, for which there are supporting APIs like :c:func:`zbus_iterate_over_channels`, +:c:func:`zbus_iterate_over_channels_with_user_data`, :c:func:`zbus_iterate_over_observers` and +:c:func:`zbus_iterate_over_observers_with_user_data`. This feature enables developers to call a +procedure over all declared channels, where the procedure parameter is a :c:struct:`zbus_channel`. +The execution sequence is in the alphabetical name order of the channels (see :ref:`Iterable +Sections ` documentation for details). ZBus also implements this feature for +:c:struct:`zbus_observer`. .. code-block:: c @@ -389,12 +658,17 @@ The code will log the following output: Advanced channel control ======================== -Zbus was designed to be as flexible and extensible as possible. Thus, there are some features designed to provide some control and extensibility to the bus. +ZBus was designed to be as flexible and extensible as possible. Thus, there are some features +designed to provide some control and extensibility to the bus. Listeners message access ------------------------ -For performance purposes, listeners can access the receiving channel message directly since they already have the mutex lock for it. To access the channel's message, the listener should use the :c:func:`zbus_chan_const_msg` because the channel passed as an argument to the listener function is a constant pointer to the channel. The const pointer return type tells developers not to modify the message. +For performance purposes, listeners can access the receiving channel message directly since they +already have the mutex lock for it. To access the channel's message, the listener should use the +:c:func:`zbus_chan_const_msg` because the channel passed as an argument to the listener function is +a constant pointer to the channel. The const pointer return type tells developers not to modify the +message. .. code-block:: c @@ -412,21 +686,32 @@ For performance purposes, listeners can access the receiving channel message dir User Data --------- -It is possible to pass custom data into the channel's ``user_data`` for various purposes, such as writing channel metadata. That can be achieved by passing a pointer to the channel definition macro's ``user_data`` field, which will then be accessible by others. Note that ``user_data`` is individual for each channel. Also, note that ``user_data`` access is not thread-safe. For thread-safe access to ``user_data``, see the next section. +It is possible to pass custom data into the channel's ``user_data`` for various purposes, such as +writing channel metadata. That can be achieved by passing a pointer to the channel definition +macro's ``user_data`` field, which will then be accessible by others. Note that ``user_data`` is +individual for each channel. Also, note that ``user_data`` access is not thread-safe. For +thread-safe access to ``user_data``, see the next section. Claim and finish a channel -------------------------- -To take more control over channels, two functions were added :c:func:`zbus_chan_claim` and :c:func:`zbus_chan_finish`. With these functions, it is possible to access the channel's metadata safely. When a channel is claimed, no actions are available to that channel. After finishing the channel, all the actions are available again. +To take more control over channels, two functions were added :c:func:`zbus_chan_claim` and +:c:func:`zbus_chan_finish`. With these functions, it is possible to access the channel's metadata +safely. When a channel is claimed, no actions are available to that channel. After finishing the +channel, all the actions are available again. .. warning:: - Never change the fields of the channel struct directly. It may cause zbus behavior inconsistencies and scheduling issues. + Never change the fields of the channel struct directly. It may cause zbus behavior + inconsistencies and scheduling issues. .. warning:: Do not use these functions inside an ISR. -The following code builds on the examples above and claims the ``acc_chan`` to set the ``user_data`` to the channel. Suppose we would like to count how many times the channels exchange messages. We defined the ``user_data`` to have the 32 bits integer. This code could be added to the listener code described above. +The following code builds on the examples above and claims the ``acc_chan`` to set the ``user_data`` +to the channel. Suppose we would like to count how many times the channels exchange messages. We +defined the ``user_data`` to have the 32 bits integer. This code could be added to the listener code +described above. .. code-block:: c @@ -463,7 +748,11 @@ The following code has the exact behavior of the code in :ref:`reading from a ch Runtime observer registration ----------------------------- -It is possible to add observers to channels in runtime. This feature uses the heap to allocate the nodes dynamically. The heap size limits the number of dynamic observers Zbus can create. Therefore, set the :kconfig:option:`CONFIG_ZBUS_RUNTIME_OBSERVERS` to enable the feature. It is possible to adjust the heap size by changing the configuration :kconfig:option:`CONFIG_HEAP_MEM_POOL_SIZE`. The following example illustrates the runtime registration usage. +It is possible to add observers to channels in runtime. This feature uses the heap to allocate the +nodes dynamically. The heap size limits the number of dynamic observers zbus can create. Therefore, +set the :kconfig:option:`CONFIG_ZBUS_RUNTIME_OBSERVERS` to enable the feature. It is possible to +adjust the heap size by changing the configuration :kconfig:option:`CONFIG_HEAP_MEM_POOL_SIZE`. The +following example illustrates the runtime registration usage. @@ -482,23 +771,40 @@ It is possible to add observers to channels in runtime. This feature uses the he Samples ******* -For a complete overview of zbus usage, take a look at the samples. There are the following samples available: - -* :ref:`zbus-hello-world-sample` illustrates the code used above in action; -* :ref:`zbus-work-queue-sample` shows how to define and use different kinds of observers. Note there is an example of using a work queue instead of executing the listener as an execution option; -* :ref:`zbus-dyn-channel-sample` demonstrates how to use dynamically allocated exchanging data in zbus; -* :ref:`zbus-uart-bridge-sample` shows an example of sending the operation of the channel to a host via serial; -* :ref:`zbus-remote-mock-sample` illustrates how to implement an external mock (on the host) to send and receive messages to and from the bus. -* :ref:`zbus-runtime-obs-registration-sample` illustrates a way of using the runtime observer registration feature; -* :ref:`zbus-benchmark-sample` implements a benchmark with different combinations of inputs. +For a complete overview of zbus usage, take a look at the samples. There are the following samples +available: + +* :zephyr:code-sample:`zbus-hello-world` illustrates the code used above in action; +* :zephyr:code-sample:`zbus-work-queue` shows how to define and use different kinds of observers. + Note there is an example of using a work queue instead of executing the listener as an execution + option; +* :zephyr:code-sample:`zbus-msg-subscriber` illustrates how to use message subscribers; +* :zephyr:code-sample:`zbus-dyn-channel` demonstrates how to use dynamically allocated exchanging + data in zbus; +* :zephyr:code-sample:`zbus-uart-bridge` shows an example of sending the operation of the channel to + a host via serial; +* :zephyr:code-sample:`zbus-remote-mock` illustrates how to implement an external mock (on the host) + to send and receive messages to and from the bus; +* :zephyr:code-sample:`zbus-runtime-obs-registration` illustrates a way of using the runtime + observer registration feature; +* :zephyr:code-sample:`zbus-confirmed-channel` implements a way of implement confirmed channel only + with subscribers; +* :zephyr:code-sample:`zbus-benchmark` implements a benchmark with different combinations of inputs. Suggested Uses ************** -Use zbus to transfer data (messages) between threads in one-to-one, one-to-many, and many-to-many synchronously or asynchronously. Choosing the proper observer type is crucial. Use subscribers for scenarios that can tolerate message losses and duplications; when they cannot, use listeners. In addition to the listener, another asynchronous message processing mechanism (like :ref:`message queues `) may be necessary to retain the pending message until it gets processed. +Use zbus to transfer data (messages) between threads in one-to-one, one-to-many, and many-to-many +synchronously or asynchronously. Choosing the proper observer type is crucial. Use subscribers for +scenarios that can tolerate message losses and duplications; when they cannot, use message +subscribers (if you need a thread) or listeners (if you need to be lean and fast). In addition to +the listener, another asynchronous message processing mechanism (like :ref:`message queues +`) may be necessary to retain the pending message until it gets processed. .. note:: - Zbus can be used to transfer streams from the producer to the consumer. However, this can increase zbus' communication latency. So maybe consider a Pipe a good alternative for this communication topology. + ZBus can be used to transfer streams from the producer to the consumer. However, this can + increase zbus' communication latency. So maybe consider a Pipe a good alternative for this + communication topology. Configuration Options ********************* @@ -507,10 +813,22 @@ For enabling zbus, it is necessary to enable the :kconfig:option:`CONFIG_ZBUS` o Related configuration options: -* :kconfig:option:`CONFIG_ZBUS_CHANNEL_NAME` enables the name of channels to be available inside the channels metadata. The log uses this information to show the channels' names; -* :kconfig:option:`CONFIG_ZBUS_OBSERVER_NAME` enables the name of observers to be available inside the channels metadata; +* :kconfig:option:`CONFIG_ZBUS_CHANNELS_SYS_INIT_PRIORITY` determine the :c:macro:`SYS_INIT` + priority used by zbus to organize the channels observations by channel; +* :kconfig:option:`CONFIG_ZBUS_CHANNEL_NAME` enables the name of channels to be available inside the + channels metadata. The log uses this information to show the channels' names; +* :kconfig:option:`CONFIG_ZBUS_OBSERVER_NAME` enables the name of observers to be available inside + the channels metadata; +* :kconfig:option:`CONFIG_ZBUS_MSG_SUBSCRIBER` enables the message subscriber observer type; +* :kconfig:option:`CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_DYNAMIC` uses the heap to allocate message + buffers; +* :kconfig:option:`CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_STATIC` uses the stack to allocate message + buffers; +* :kconfig:option:`CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_SIZE` the available number of message + buffers to be used simultaneously; +* :kconfig:option:`CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_STATIC_DATA_SIZE` the biggest message of zbus + channels to be transported into a message buffer; * :kconfig:option:`CONFIG_ZBUS_RUNTIME_OBSERVERS` enables the runtime observer registration. -* :kconfig:option:`CONFIG_ZBUS_CHANNELS_SYS_INIT_PRIORITY` determine the :c:macro:`SYS_INIT` priority used by Zbus to organize the channels observations by channel. API Reference ************* diff --git a/doc/templates/sample.tmpl b/doc/templates/sample.tmpl index c3b59b89904..e8560b03c46 100644 --- a/doc/templates/sample.tmpl +++ b/doc/templates/sample.tmpl @@ -1,11 +1,13 @@ -.. _descriptive_title_link_name: +.. zephyr:code-sample:: a_unique_id_for_the_sample + :name: A descriptive short name for the sample + :relevant-api: space-separated list of Doxygen groups of APIs this sample is a good showcase of -[A Descriptive Title] -##################### + Short text description of the sample. It is recommended to word this as if you were completing + the sentence "This code sample shows how to ..."). Overview ******** -[A short description about the sample and what it does] +[A longer description about the sample and what it does] Requirements ************ diff --git a/doc/zephyr.doxyfile.in b/doc/zephyr.doxyfile.in index a66110b6d05..1f8a6af46c4 100644 --- a/doc/zephyr.doxyfile.in +++ b/doc/zephyr.doxyfile.in @@ -1368,7 +1368,7 @@ HTML_EXTRA_FILES = @ZEPHYR_BASE@/doc/_doxygen/doxygen-awesome-darkmode-tog # The default value is: AUTO_LIGHT. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_COLORSTYLE = AUTO_LIGHT +HTML_COLORSTYLE = LIGHT # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to @@ -2368,6 +2368,8 @@ PREDEFINED = __DOXYGEN__ \ CONFIG_HEAP_MEM_POOL_SIZE \ CONFIG_MMU \ CONFIG_NET_L2_ETHERNET_MGMT \ + CONFIG_NET_L2_IEEE802154_MGMT \ + CONFIG_NET_L2_IEEE802154_SECURITY \ CONFIG_NET_MGMT_EVENT \ CONFIG_NET_SOCKETS_POSIX_NAMES \ CONFIG_NET_TCP \ @@ -2377,7 +2379,6 @@ PREDEFINED = __DOXYGEN__ \ CONFIG_SCHED_DEADLINE \ CONFIG_SETTINGS_RUNTIME \ CONFIG_SMP \ - CONFIG_SPI_ASYNC \ CONFIG_SYS_CLOCK_EXISTS \ CONFIG_THREAD_CUSTOM_DATA \ CONFIG_THREAD_MONITOR \ @@ -2391,10 +2392,12 @@ PREDEFINED = __DOXYGEN__ \ NET_MGMT_DEFINE_REQUEST_HANDLER(x)= \ DEVICE_DEFINE()= \ BUILD_ASSERT()= \ + XEN_GUEST_HANDLE_64(x)= \ _LINKER \ __deprecated= \ __packed= \ __aligned(x)= \ + __attribute_nonnull(...)= \ "__printf_like(x, y)=" \ __attribute__(x)= \ __syscall= \ diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index 749285d29a3..6310146bb3d 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -5,6 +5,7 @@ add_compile_options($) add_definitions(-D__ZEPHYR_SUPERVISOR__) +# zephyr-keep-sorted-start add_subdirectory(disk) add_subdirectory(interrupt_controller) add_subdirectory(misc) @@ -13,12 +14,14 @@ add_subdirectory(usb) add_subdirectory(usb_c) add_subdirectory_ifdef(CONFIG_ADC adc) +add_subdirectory_ifdef(CONFIG_ARM_SIP_SVC_DRIVER sip_svc) add_subdirectory_ifdef(CONFIG_AUDIO audio) +add_subdirectory_ifdef(CONFIG_AUXDISPLAY auxdisplay) add_subdirectory_ifdef(CONFIG_BBRAM bbram) -add_subdirectory_ifdef(CONFIG_BOARD_XENVM xen) add_subdirectory_ifdef(CONFIG_BT_DRIVERS bluetooth) add_subdirectory_ifdef(CONFIG_CACHE_MANAGEMENT cache) add_subdirectory_ifdef(CONFIG_CAN can) +add_subdirectory_ifdef(CONFIG_CHARGER charger) add_subdirectory_ifdef(CONFIG_CLOCK_CONTROL clock_control) add_subdirectory_ifdef(CONFIG_CONSOLE console) add_subdirectory_ifdef(CONFIG_COREDUMP_DEVICE coredump) @@ -27,7 +30,6 @@ add_subdirectory_ifdef(CONFIG_CRYPTO crypto) add_subdirectory_ifdef(CONFIG_DAC dac) add_subdirectory_ifdef(CONFIG_DAI dai) add_subdirectory_ifdef(CONFIG_DISPLAY display) -add_subdirectory_ifdef(CONFIG_AUXDISPLAY auxdisplay) add_subdirectory_ifdef(CONFIG_DMA dma) add_subdirectory_ifdef(CONFIG_EDAC edac) add_subdirectory_ifdef(CONFIG_EEPROM eeprom) @@ -36,10 +38,11 @@ add_subdirectory_ifdef(CONFIG_ESPI espi) add_subdirectory_ifdef(CONFIG_FLASH flash) add_subdirectory_ifdef(CONFIG_FPGA fpga) add_subdirectory_ifdef(CONFIG_FUEL_GAUGE fuel_gauge) +add_subdirectory_ifdef(CONFIG_GNSS gnss) add_subdirectory_ifdef(CONFIG_GPIO gpio) add_subdirectory_ifdef(CONFIG_HWINFO hwinfo) +add_subdirectory_ifdef(CONFIG_HWSPINLOCK hwspinlock) add_subdirectory_ifdef(CONFIG_I2C i2c) -add_subdirectory_ifdef(CONFIG_SMBUS smbus) add_subdirectory_ifdef(CONFIG_I2S i2s) add_subdirectory_ifdef(CONFIG_I3C i3c) add_subdirectory_ifdef(CONFIG_IEEE802154 ieee802154) @@ -58,7 +61,6 @@ add_subdirectory_ifdef(CONFIG_MM_DRV mm) add_subdirectory_ifdef(CONFIG_MODEM modem) add_subdirectory_ifdef(CONFIG_NET_DRIVERS net) add_subdirectory_ifdef(CONFIG_NET_L2_ETHERNET ethernet) -add_subdirectory_ifdef(CONFIG_NEURAL_NET_ACCEL neural_net) add_subdirectory_ifdef(CONFIG_PECI peci) add_subdirectory_ifdef(CONFIG_PINCTRL pinctrl) add_subdirectory_ifdef(CONFIG_PM_CPU_OPS pm_cpu_ops) @@ -69,9 +71,11 @@ add_subdirectory_ifdef(CONFIG_PWM pwm) add_subdirectory_ifdef(CONFIG_REGULATOR regulator) add_subdirectory_ifdef(CONFIG_RESET reset) add_subdirectory_ifdef(CONFIG_RETAINED_MEM retained_mem) +add_subdirectory_ifdef(CONFIG_RTC rtc) add_subdirectory_ifdef(CONFIG_SDHC sdhc) add_subdirectory_ifdef(CONFIG_SENSOR sensor) add_subdirectory_ifdef(CONFIG_SERIAL serial) +add_subdirectory_ifdef(CONFIG_SMBUS smbus) add_subdirectory_ifdef(CONFIG_SPI spi) add_subdirectory_ifdef(CONFIG_SYSCON syscon) add_subdirectory_ifdef(CONFIG_SYS_CLOCK_EXISTS timer) @@ -80,6 +84,5 @@ add_subdirectory_ifdef(CONFIG_VIRTUALIZATION virtualization) add_subdirectory_ifdef(CONFIG_W1 w1) add_subdirectory_ifdef(CONFIG_WATCHDOG watchdog) add_subdirectory_ifdef(CONFIG_WIFI wifi) -add_subdirectory_ifdef(CONFIG_RTC rtc) -add_subdirectory_ifdef(CONFIG_ARM_SIP_SVC_DRIVER sip_svc) -add_subdirectory_ifdef(CONFIG_HWSPINLOCK hwspinlock) +add_subdirectory_ifdef(CONFIG_XEN xen) +# zephyr-keep-sorted-stop diff --git a/drivers/Kconfig b/drivers/Kconfig index 0a369875f6f..45b03e4829c 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -5,13 +5,15 @@ menu "Device Drivers" +# zephyr-keep-sorted-start source "drivers/adc/Kconfig" -source "drivers/auxdisplay/Kconfig" source "drivers/audio/Kconfig" +source "drivers/auxdisplay/Kconfig" source "drivers/bbram/Kconfig" source "drivers/bluetooth/Kconfig" source "drivers/cache/Kconfig" source "drivers/can/Kconfig" +source "drivers/charger/Kconfig" source "drivers/clock_control/Kconfig" source "drivers/console/Kconfig" source "drivers/coredump/Kconfig" @@ -30,12 +32,13 @@ source "drivers/ethernet/Kconfig" source "drivers/flash/Kconfig" source "drivers/fpga/Kconfig" source "drivers/fuel_gauge/Kconfig" +source "drivers/gnss/Kconfig" source "drivers/gpio/Kconfig" source "drivers/hwinfo/Kconfig" +source "drivers/hwspinlock/Kconfig" source "drivers/i2c/Kconfig" source "drivers/i2s/Kconfig" source "drivers/i3c/Kconfig" -source "drivers/smbus/Kconfig" source "drivers/ieee802154/Kconfig" source "drivers/input/Kconfig" source "drivers/interrupt_controller/Kconfig" @@ -54,7 +57,6 @@ source "drivers/misc/Kconfig" source "drivers/mm/Kconfig" source "drivers/modem/Kconfig" source "drivers/net/Kconfig" -source "drivers/neural_net/Kconfig" source "drivers/pcie/Kconfig" source "drivers/peci/Kconfig" source "drivers/pinctrl/Kconfig" @@ -70,6 +72,8 @@ source "drivers/rtc/Kconfig" source "drivers/sdhc/Kconfig" source "drivers/sensor/Kconfig" source "drivers/serial/Kconfig" +source "drivers/sip_svc/Kconfig" +source "drivers/smbus/Kconfig" source "drivers/spi/Kconfig" source "drivers/syscon/Kconfig" source "drivers/timer/Kconfig" @@ -81,7 +85,6 @@ source "drivers/w1/Kconfig" source "drivers/watchdog/Kconfig" source "drivers/wifi/Kconfig" source "drivers/xen/Kconfig" -source "drivers/sip_svc/Kconfig" -source "drivers/hwspinlock/Kconfig" +# zephyr-keep-sorted-stop endmenu diff --git a/drivers/adc/CMakeLists.txt b/drivers/adc/CMakeLists.txt index ee426090d3f..34536f4c4e0 100644 --- a/drivers/adc/CMakeLists.txt +++ b/drivers/adc/CMakeLists.txt @@ -45,3 +45,6 @@ zephyr_library_sources_ifdef(CONFIG_ADC_SMARTBOND_SDADC adc_smartbond_sdadc.c) zephyr_library_sources_ifdef(CONFIG_ADC_TLA2021 adc_tla2021.c) zephyr_library_sources_ifdef(CONFIG_ADC_NXP_S32_ADC_SAR adc_nxp_s32_adc_sar.c) zephyr_library_sources_ifdef(CONFIG_ADC_MAX1125X adc_max1125x.c) +zephyr_library_sources_ifdef(CONFIG_ADC_MAX11102_17 adc_max11102_17.c) +zephyr_library_sources_ifdef(CONFIG_ADC_AD5592 adc_ad5592.c) +zephyr_library_sources_ifdef(CONFIG_ADC_LTC2451 adc_ltc2451.c) diff --git a/drivers/adc/Kconfig b/drivers/adc/Kconfig index eb9e03041a9..6dd41582bd0 100644 --- a/drivers/adc/Kconfig +++ b/drivers/adc/Kconfig @@ -17,7 +17,6 @@ if ADC config ADC_SHELL bool "ADC Shell" - default y depends on SHELL help Enable ADC Shell for testing. @@ -114,4 +113,10 @@ source "drivers/adc/Kconfig.nxp_s32" source "drivers/adc/Kconfig.max1125x" +source "drivers/adc/Kconfig.max11102_17" + +source "drivers/adc/Kconfig.ad5592" + +source "drivers/adc/Kconfig.ltc2451" + endif # ADC diff --git a/drivers/adc/Kconfig.ad5592 b/drivers/adc/Kconfig.ad5592 new file mode 100644 index 00000000000..92b80f34217 --- /dev/null +++ b/drivers/adc/Kconfig.ad5592 @@ -0,0 +1,25 @@ +# Copyright (c) 2023 Grinn +# SPDX -License-Identifier: Apache-2.0 + +config ADC_AD5592 + bool "AD5592 ADC driver" + default y + depends on DT_HAS_ADI_AD5592_ADC_ENABLED + select MFD + help + Enable the AD5592 ADC driver. + +config ADC_AD5592_ACQUISITION_THREAD_STACK_SIZE + int "Stack size for the ADC data acquisition thread" + depends on ADC_AD5592 + default 384 + help + Size of the stack used for the internal data acquisition + thread. + +config ADC_AD5592_ACQUISITION_THREAD_PRIO + int "Priority for the ADC data acquisition thread" + depends on ADC_AD5592 + default 0 + help + Priority level for the internal ADC data acquisition thread. diff --git a/drivers/adc/Kconfig.ltc2451 b/drivers/adc/Kconfig.ltc2451 new file mode 100644 index 00000000000..8f3cb384cfb --- /dev/null +++ b/drivers/adc/Kconfig.ltc2451 @@ -0,0 +1,8 @@ +# Copyright (c) 2023 Brill Power +# SPDX-License-Identifier: Apache-2.0 + +config ADC_LTC2451 + bool "LTC2451 driver" + default y + depends on DT_HAS_LLTC_LTC2451_ENABLED + select I2C diff --git a/drivers/adc/Kconfig.max11102_17 b/drivers/adc/Kconfig.max11102_17 new file mode 100644 index 00000000000..6fcd8add11e --- /dev/null +++ b/drivers/adc/Kconfig.max11102_17 @@ -0,0 +1,32 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +menuconfig ADC_MAX11102_17 + bool "Maxim Integrated MAX11102-MAX11117" + default y + depends on DT_HAS_MAXIM_MAX11102_ENABLED \ + || DT_HAS_MAXIM_MAX11103_ENABLED \ + || DT_HAS_MAXIM_MAX11105_ENABLED \ + || DT_HAS_MAXIM_MAX11106_ENABLED \ + || DT_HAS_MAXIM_MAX11110_ENABLED \ + || DT_HAS_MAXIM_MAX11111_ENABLED \ + || DT_HAS_MAXIM_MAX11115_ENABLED \ + || DT_HAS_MAXIM_MAX11116_ENABLED \ + || DT_HAS_MAXIM_MAX11117_ENABLED + select SPI + help + Enable the driver implementation for the MAX11102-MAX11117 family + +config ADC_MAX11102_17_ACQUISITION_THREAD_INIT_PRIO + int "ADC data acquisition thread priority" + default 0 + depends on ADC_MAX11102_17 && ADC_ASYNC + +config ADC_MAX11102_17_ACQUISITION_THREAD_STACK_SIZE + int "Stack size for the ADC data acquisition thread" + default 400 + depends on ADC_MAX11102_17 && ADC_ASYNC + help + Size of the stack used for the internal data acquisition + thread. diff --git a/drivers/adc/Kconfig.mcux b/drivers/adc/Kconfig.mcux index c53ffeee468..725ec32c2c8 100644 --- a/drivers/adc/Kconfig.mcux +++ b/drivers/adc/Kconfig.mcux @@ -30,6 +30,7 @@ config ADC_MCUX_LPADC bool "MCUX LPADC driver" default y select ADC_CONFIGURABLE_INPUTS + select REGULATOR depends on DT_HAS_NXP_LPC_LPADC_ENABLED help Enable the MCUX LPADC driver. diff --git a/drivers/adc/Kconfig.npcx b/drivers/adc/Kconfig.npcx index 8f48aefe760..0209fd845d9 100644 --- a/drivers/adc/Kconfig.npcx +++ b/drivers/adc/Kconfig.npcx @@ -11,3 +11,19 @@ config ADC_NPCX This option enables the ADC driver for NPCX family of processors. Say y if you wish to use ADC channels on NPCX MCU. + +if ADC_NPCX + +config ADC_NPCX_CMP_V1 + bool "ADC comparator version 1 support" + default y if SOC_SERIES_NPCX7 || SOC_SERIES_NPCX9 + help + This option enables ADC comparator V1 support. + +config ADC_NPCX_CMP_V2 + bool "ADC comparator version 2 support" + default y if SOC_SERIES_NPCX4 + help + This option enables ADC comparator V2 support. + +endif #ADC_NPCX diff --git a/drivers/adc/adc_ad5592.c b/drivers/adc/adc_ad5592.c new file mode 100644 index 00000000000..422fd549868 --- /dev/null +++ b/drivers/adc/adc_ad5592.c @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2023 Grinn + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT adi_ad5592_adc + +#include +#include +#include + +#include + +#define ADC_CONTEXT_USES_KERNEL_TIMER +#include "adc_context.h" + +#include +LOG_MODULE_REGISTER(adc_ad5592, CONFIG_ADC_LOG_LEVEL); + +#define AD5592_ADC_RESOLUTION 12U +#define AD5592_ADC_MAX_VAL 4096 + +struct adc_ad5592_config { + const struct device *mfd_dev; +}; + +struct adc_ad5592_data { + struct adc_context ctx; + const struct device *dev; + uint8_t adc_conf; + uint16_t *buffer; + uint16_t *repeat_buffer; + uint8_t channels; + struct k_thread thread; + struct k_sem sem; + + K_KERNEL_STACK_MEMBER(stack, CONFIG_ADC_AD5592_ACQUISITION_THREAD_STACK_SIZE); +}; + +static int adc_ad5592_channel_setup(const struct device *dev, + const struct adc_channel_cfg *channel_cfg) +{ + const struct adc_ad5592_config *config = dev->config; + struct adc_ad5592_data *data = dev->data; + + if (channel_cfg->channel_id >= AD5592_PIN_MAX) { + LOG_ERR("invalid channel id %d", channel_cfg->channel_id); + return -EINVAL; + } + + data->adc_conf |= BIT(channel_cfg->channel_id); + + return mfd_ad5592_write_reg(config->mfd_dev, AD5592_REG_ADC_CONFIG, data->adc_conf); +} + +static int adc_ad5592_validate_buffer_size(const struct device *dev, + const struct adc_sequence *sequence) +{ + uint8_t channels; + size_t needed; + + channels = POPCOUNT(sequence->channels); + needed = channels * sizeof(uint16_t); + + if (sequence->buffer_size < needed) { + return -ENOMEM; + } + + return 0; +} + +static int adc_ad5592_start_read(const struct device *dev, const struct adc_sequence *sequence) +{ + struct adc_ad5592_data *data = dev->data; + int ret; + + if (sequence->resolution != AD5592_ADC_RESOLUTION) { + LOG_ERR("invalid resolution %d", sequence->resolution); + return -EINVAL; + } + + if (find_msb_set(sequence->channels) > AD5592_PIN_MAX) { + LOG_ERR("invalid channels in mask: 0x%08x", sequence->channels); + return -EINVAL; + } + + ret = adc_ad5592_validate_buffer_size(dev, sequence); + if (ret < 0) { + LOG_ERR("insufficient buffer size"); + return ret; + } + + data->buffer = sequence->buffer; + adc_context_start_read(&data->ctx, sequence); + + return adc_context_wait_for_completion(&data->ctx); +} + +static int adc_ad5592_read_channel(const struct device *dev, uint8_t channel, uint16_t *result) +{ + const struct adc_ad5592_config *config = dev->config; + uint16_t val; + int ret; + + ret = mfd_ad5592_write_reg(config->mfd_dev, AD5592_REG_SEQ_ADC, BIT(channel)); + if (ret < 0) { + return ret; + } + + /* + * Invalid data: + * See Figure 46. Single-Channel ADC Conversion Sequence. + * The first conversion result always returns invalid data. + */ + (void) mfd_ad5592_read_raw(config->mfd_dev, &val); + + ret = mfd_ad5592_read_raw(config->mfd_dev, &val); + if (ret < 0) { + return ret; + } + + val = sys_be16_to_cpu(val); + if (channel >= 1) { + val -= channel * AD5592_ADC_MAX_VAL; + } + + *result = val; + + return 0; +} + +static void adc_context_start_sampling(struct adc_context *ctx) +{ + struct adc_ad5592_data *data = CONTAINER_OF(ctx, struct adc_ad5592_data, ctx); + + data->channels = ctx->sequence.channels; + data->repeat_buffer = data->buffer; + + k_sem_give(&data->sem); +} + +static void adc_context_update_buffer_pointer(struct adc_context *ctx, + bool repeat_sampling) +{ + struct adc_ad5592_data *data = CONTAINER_OF(ctx, struct adc_ad5592_data, ctx); + + if (repeat_sampling) { + data->buffer = data->repeat_buffer; + } +} + +static void adc_ad5592_acquisition_thread(struct adc_ad5592_data *data) +{ + uint16_t result; + uint8_t channel; + int ret; + + while (true) { + k_sem_take(&data->sem, K_FOREVER); + + while (data->channels != 0) { + channel = find_lsb_set(data->channels) - 1; + + ret = adc_ad5592_read_channel(data->dev, channel, &result); + if (ret < 0) { + LOG_ERR("failed to read channel %d (ret %d)", channel, ret); + adc_context_complete(&data->ctx, ret); + break; + } + + *data->buffer++ = result; + WRITE_BIT(data->channels, channel, 0); + } + + adc_context_on_sampling_done(&data->ctx, data->dev); + } +} + +static int adc_ad5592_read_async(const struct device *dev, + const struct adc_sequence *sequence, + struct k_poll_signal *async) +{ + struct adc_ad5592_data *data = dev->data; + int ret; + + adc_context_lock(&data->ctx, async ? true : false, async); + ret = adc_ad5592_start_read(dev, sequence); + adc_context_release(&data->ctx, ret); + + return ret; +} + +static int adc_ad5592_read(const struct device *dev, + const struct adc_sequence *sequence) +{ + return adc_ad5592_read_async(dev, sequence, NULL); +} + +static int adc_ad5592_init(const struct device *dev) +{ + const struct adc_ad5592_config *config = dev->config; + struct adc_ad5592_data *data = dev->data; + k_tid_t tid; + int ret; + + if (!device_is_ready(config->mfd_dev)) { + return -ENODEV; + } + + ret = mfd_ad5592_write_reg(config->mfd_dev, AD5592_REG_PD_REF_CTRL, AD5592_EN_REF); + if (ret < 0) { + return ret; + } + + data->dev = dev; + + k_sem_init(&data->sem, 0, 1); + adc_context_init(&data->ctx); + + tid = k_thread_create(&data->thread, data->stack, + CONFIG_ADC_AD5592_ACQUISITION_THREAD_STACK_SIZE, + (k_thread_entry_t)adc_ad5592_acquisition_thread, data, NULL, NULL, + CONFIG_ADC_AD5592_ACQUISITION_THREAD_PRIO, 0, K_NO_WAIT); + + ret = k_thread_name_set(tid, "adc_ad5592"); + if (ret < 0) { + return ret; + } + + adc_context_unlock_unconditionally(&data->ctx); + + return 0; +} + +static const struct adc_driver_api adc_ad5592_api = { + .channel_setup = adc_ad5592_channel_setup, + .read = adc_ad5592_read, +#ifdef CONFIG_ADC_ASYNC + .read_async = adc_ad5592_read_async, +#endif +}; + +#define ADC_AD5592_DEFINE(inst) \ + static const struct adc_ad5592_config adc_ad5592_config##inst = { \ + .mfd_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ + }; \ + \ + struct adc_ad5592_data adc_ad5592_data##inst; \ + \ + DEVICE_DT_INST_DEFINE(inst, adc_ad5592_init, NULL, \ + &adc_ad5592_data##inst, &adc_ad5592_config##inst, \ + POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, \ + &adc_ad5592_api); + +DT_INST_FOREACH_STATUS_OKAY(ADC_AD5592_DEFINE) diff --git a/drivers/adc/adc_ads1119.c b/drivers/adc/adc_ads1119.c index 23f71ded75b..1abdcaad720 100644 --- a/drivers/adc/adc_ads1119.c +++ b/drivers/adc/adc_ads1119.c @@ -433,8 +433,12 @@ static int ads1119_read(const struct device *dev, #endif #if CONFIG_ADC_ASYNC -static void ads1119_acquisition_thread(struct device *dev) +static void ads1119_acquisition_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; while (true) { ads1119_adc_perform_read(dev); } @@ -463,10 +467,10 @@ static int ads1119_init(const struct device *dev) } #if CONFIG_ADC_ASYNC - const k_tid_t tid = + k_tid_t tid = k_thread_create(&data->thread, config->stack, CONFIG_ADC_ADS1119_ACQUISITION_THREAD_STACK_SIZE, - (k_thread_entry_t)ads1119_acquisition_thread, + ads1119_acquisition_thread, (void *)dev, NULL, NULL, CONFIG_ADC_ADS1119_ASYNC_THREAD_INIT_PRIO, 0, K_NO_WAIT); diff --git a/drivers/adc/adc_ads114s0x.c b/drivers/adc/adc_ads114s0x.c index 3b050e4e613..e5ab699bcbd 100644 --- a/drivers/adc/adc_ads114s0x.c +++ b/drivers/adc/adc_ads114s0x.c @@ -1063,8 +1063,12 @@ static int ads114s0x_read(const struct device *dev, const struct adc_sequence *s #endif #if CONFIG_ADC_ASYNC -static void ads114s0x_acquisition_thread(struct device *dev) +static void ads114s0x_acquisition_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; while (true) { ads114s0x_adc_perform_read(dev); } @@ -1076,7 +1080,7 @@ static int ads114s0x_gpio_write_config(const struct device *dev) { struct ads114s0x_data *data = dev->data; const struct ads114s0x_config *config = dev->config; - uint8_t register_addresses[2]; + enum ads114s0x_register register_addresses[2]; uint8_t register_values[ARRAY_SIZE(register_addresses)]; uint8_t gpio_dat = 0; uint8_t gpio_con = 0; @@ -1352,9 +1356,9 @@ static int ads114s0x_init(const struct device *dev) } #if CONFIG_ADC_ASYNC - const k_tid_t tid = k_thread_create( + k_tid_t tid = k_thread_create( &data->thread, config->stack, CONFIG_ADC_ADS114S0X_ACQUISITION_THREAD_STACK_SIZE, - (k_thread_entry_t)ads114s0x_acquisition_thread, (void *)dev, NULL, NULL, + ads114s0x_acquisition_thread, (void *)dev, NULL, NULL, CONFIG_ADC_ADS114S0X_ASYNC_THREAD_INIT_PRIO, 0, K_NO_WAIT); k_thread_name_set(tid, "adc_ads114s0x"); #endif diff --git a/drivers/adc/adc_ads1x1x.c b/drivers/adc/adc_ads1x1x.c index 5549c7a83a0..6b2a476f24b 100644 --- a/drivers/adc/adc_ads1x1x.c +++ b/drivers/adc/adc_ads1x1x.c @@ -140,7 +140,7 @@ struct ads1x1x_data { struct k_thread thread; bool differential; - K_THREAD_STACK_MEMBER(stack, CONFIG_ADC_ADS1X1X_ACQUISITION_THREAD_STACK_SIZE); + K_KERNEL_STACK_MEMBER(stack, CONFIG_ADC_ADS1X1X_ACQUISITION_THREAD_STACK_SIZE); }; static int ads1x1x_read_reg(const struct device *dev, enum ads1x1x_reg reg_addr, uint16_t *buf) @@ -537,8 +537,12 @@ static int ads1x1x_read(const struct device *dev, const struct adc_sequence *seq return ads1x1x_adc_read_async(dev, sequence, NULL); } -static void ads1x1x_acquisition_thread(const struct device *dev) +static void ads1x1x_acquisition_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; struct ads1x1x_data *data = dev->data; int rc; @@ -570,9 +574,9 @@ static int ads1x1x_init(const struct device *dev) return -ENODEV; } - const k_tid_t tid = + k_tid_t tid = k_thread_create(&data->thread, data->stack, K_THREAD_STACK_SIZEOF(data->stack), - (k_thread_entry_t)ads1x1x_acquisition_thread, (void *)dev, NULL, + ads1x1x_acquisition_thread, (void *)dev, NULL, NULL, CONFIG_ADC_ADS1X1X_ACQUISITION_THREAD_PRIO, 0, K_NO_WAIT); k_thread_name_set(tid, "adc_ads1x1x"); diff --git a/drivers/adc/adc_ads7052.c b/drivers/adc/adc_ads7052.c index 14b79459505..735c73a1bf0 100644 --- a/drivers/adc/adc_ads7052.c +++ b/drivers/adc/adc_ads7052.c @@ -219,8 +219,12 @@ static int ads7052_read_channel(const struct device *dev, uint8_t channel, uint1 return 0; } -static void ads7052_acquisition_thread(struct ads7052_data *data) +static void ads7052_acquisition_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct ads7052_data *data = p1; uint16_t result = 0; uint8_t channel; int err = 0; @@ -272,7 +276,7 @@ static int adc_ads7052_init(const struct device *dev) k_thread_create(&data->thread, data->stack, CONFIG_ADC_ADS7052_ACQUISITION_THREAD_STACK_SIZE, - (k_thread_entry_t)ads7052_acquisition_thread, data, NULL, NULL, + ads7052_acquisition_thread, data, NULL, NULL, CONFIG_ADC_ADS7052_ACQUISITION_THREAD_PRIO, 0, K_NO_WAIT); adc_context_unlock_unconditionally(&data->ctx); diff --git a/drivers/adc/adc_b91.c b/drivers/adc/adc_b91.c index 6779665c459..30e76c88a76 100644 --- a/drivers/adc/adc_b91.c +++ b/drivers/adc/adc_b91.c @@ -35,7 +35,7 @@ struct b91_adc_data { struct k_sem acq_sem; struct k_thread thread; - K_THREAD_STACK_MEMBER(stack, CONFIG_ADC_B91_ACQUISITION_THREAD_STACK_SIZE); + K_KERNEL_STACK_MEMBER(stack, CONFIG_ADC_B91_ACQUISITION_THREAD_STACK_SIZE); }; struct b91_adc_cfg { @@ -216,8 +216,12 @@ static int adc_b91_adc_start_read(const struct device *dev, const struct adc_seq } /* Main ADC Acquisition thread */ -static void adc_b91_acquisition_thread(const struct device *dev) +static void adc_b91_acquisition_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; int16_t adc_code; struct b91_adc_data *data = dev->data; @@ -260,7 +264,7 @@ static int adc_b91_init(const struct device *dev) k_thread_create(&data->thread, data->stack, CONFIG_ADC_B91_ACQUISITION_THREAD_STACK_SIZE, - (k_thread_entry_t)adc_b91_acquisition_thread, + adc_b91_acquisition_thread, (void *)dev, NULL, NULL, CONFIG_ADC_B91_ACQUISITION_THREAD_PRIO, 0, K_NO_WAIT); diff --git a/drivers/adc/adc_emul.c b/drivers/adc/adc_emul.c index 4ef7a869390..20b9764fd5f 100644 --- a/drivers/adc/adc_emul.c +++ b/drivers/adc/adc_emul.c @@ -470,8 +470,12 @@ static int adc_emul_get_chan_value(struct adc_emul_data *data, * * @return This thread should not end */ -static void adc_emul_acquisition_thread(struct adc_emul_data *data) +static void adc_emul_acquisition_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct adc_emul_data *data = p1; int err; while (true) { @@ -533,7 +537,7 @@ static int adc_emul_init(const struct device *dev) k_thread_create(&data->thread, data->stack, CONFIG_ADC_EMUL_ACQUISITION_THREAD_STACK_SIZE, - (k_thread_entry_t)adc_emul_acquisition_thread, + adc_emul_acquisition_thread, data, NULL, NULL, CONFIG_ADC_EMUL_ACQUISITION_THREAD_PRIO, 0, K_NO_WAIT); diff --git a/drivers/adc/adc_handlers.c b/drivers/adc/adc_handlers.c index cf6319a6264..2b00c2d95a9 100644 --- a/drivers/adc/adc_handlers.c +++ b/drivers/adc/adc_handlers.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include static inline int z_vrfy_adc_channel_setup(const struct device *dev, @@ -13,8 +13,8 @@ static inline int z_vrfy_adc_channel_setup(const struct device *dev, { struct adc_channel_cfg channel_cfg; - Z_OOPS(Z_SYSCALL_DRIVER_ADC(dev, channel_setup)); - Z_OOPS(z_user_from_copy(&channel_cfg, + K_OOPS(K_SYSCALL_DRIVER_ADC(dev, channel_setup)); + K_OOPS(k_usermode_from_copy(&channel_cfg, (struct adc_channel_cfg *)user_channel_cfg, sizeof(struct adc_channel_cfg))); @@ -27,13 +27,13 @@ static bool copy_sequence(struct adc_sequence *dst, struct adc_sequence_options *options, struct adc_sequence *src) { - if (z_user_from_copy(dst, src, sizeof(struct adc_sequence)) != 0) { + if (k_usermode_from_copy(dst, src, sizeof(struct adc_sequence)) != 0) { printk("couldn't copy adc_sequence struct\n"); return false; } if (dst->options) { - if (z_user_from_copy(options, dst->options, + if (k_usermode_from_copy(options, dst->options, sizeof(struct adc_sequence_options)) != 0) { printk("couldn't copy adc_options struct\n"); return false; @@ -41,7 +41,7 @@ static bool copy_sequence(struct adc_sequence *dst, dst->options = options; } - if (Z_SYSCALL_MEMORY_WRITE(dst->buffer, dst->buffer_size) != 0) { + if (K_SYSCALL_MEMORY_WRITE(dst->buffer, dst->buffer_size) != 0) { printk("no access to buffer memory\n"); return false; } @@ -55,12 +55,12 @@ static inline int z_vrfy_adc_read(const struct device *dev, struct adc_sequence sequence; struct adc_sequence_options options; - Z_OOPS(Z_SYSCALL_DRIVER_ADC(dev, read)); - Z_OOPS(Z_SYSCALL_VERIFY_MSG(copy_sequence(&sequence, &options, + K_OOPS(K_SYSCALL_DRIVER_ADC(dev, read)); + K_OOPS(K_SYSCALL_VERIFY_MSG(copy_sequence(&sequence, &options, (struct adc_sequence *)user_sequence), "invalid ADC sequence")); if (sequence.options != NULL) { - Z_OOPS(Z_SYSCALL_VERIFY_MSG(sequence.options->callback == NULL, + K_OOPS(K_SYSCALL_VERIFY_MSG(sequence.options->callback == NULL, "ADC sequence callbacks forbidden from user mode")); } @@ -76,15 +76,15 @@ static inline int z_vrfy_adc_read_async(const struct device *dev, struct adc_sequence sequence; struct adc_sequence_options options; - Z_OOPS(Z_SYSCALL_DRIVER_ADC(dev, read_async)); - Z_OOPS(Z_SYSCALL_VERIFY_MSG(copy_sequence(&sequence, &options, + K_OOPS(K_SYSCALL_DRIVER_ADC(dev, read_async)); + K_OOPS(K_SYSCALL_VERIFY_MSG(copy_sequence(&sequence, &options, (struct adc_sequence *)user_sequence), "invalid ADC sequence")); if (sequence.options != NULL) { - Z_OOPS(Z_SYSCALL_VERIFY_MSG(sequence.options->callback == NULL, + K_OOPS(K_SYSCALL_VERIFY_MSG(sequence.options->callback == NULL, "ADC sequence callbacks forbidden from user mode")); } - Z_OOPS(Z_SYSCALL_OBJ(async, K_OBJ_POLL_SIGNAL)); + K_OOPS(K_SYSCALL_OBJ(async, K_OBJ_POLL_SIGNAL)); return z_impl_adc_read_async((const struct device *)dev, &sequence, (struct k_poll_signal *)async); diff --git a/drivers/adc/adc_lmp90xxx.c b/drivers/adc/adc_lmp90xxx.c index 7ecb2c6cfa6..2dc23a792f3 100644 --- a/drivers/adc/adc_lmp90xxx.c +++ b/drivers/adc/adc_lmp90xxx.c @@ -650,8 +650,12 @@ static int lmp90xxx_adc_read_channel(const struct device *dev, return 0; } -static void lmp90xxx_acquisition_thread(struct lmp90xxx_data *data) +static void lmp90xxx_acquisition_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct lmp90xxx_data *data = p1; uint8_t bgcalcn = LMP90XXX_BGCALN(0x3); /* Default to BgCalMode3 */ int32_t result = 0; uint8_t channel; @@ -1014,7 +1018,7 @@ static int lmp90xxx_init(const struct device *dev) tid = k_thread_create(&data->thread, data->stack, CONFIG_ADC_LMP90XXX_ACQUISITION_THREAD_STACK_SIZE, - (k_thread_entry_t)lmp90xxx_acquisition_thread, + lmp90xxx_acquisition_thread, data, NULL, NULL, CONFIG_ADC_LMP90XXX_ACQUISITION_THREAD_PRIO, 0, K_NO_WAIT); diff --git a/drivers/adc/adc_ltc2451.c b/drivers/adc/adc_ltc2451.c new file mode 100644 index 00000000000..95b86f30d68 --- /dev/null +++ b/drivers/adc/adc_ltc2451.c @@ -0,0 +1,105 @@ +/* LLTC LTC2451 ADC + * + * Copyright (c) 2023 Brill Power Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(ltc2451, CONFIG_ADC_LOG_LEVEL); + +#define DT_DRV_COMPAT lltc_ltc2451 + +struct ltc2451_config { + struct i2c_dt_spec i2c; + uint8_t conversion_speed; +}; + +static int ltc2451_channel_setup(const struct device *dev, + const struct adc_channel_cfg *channel_cfg) +{ + ARG_UNUSED(dev); + + if (channel_cfg->channel_id != 0) { + LOG_ERR("Invalid channel id '%d'", channel_cfg->channel_id); + return -EINVAL; + } + + return 0; +} + +static int ltc2451_set_conversion_speed(const struct device *dev, uint8_t conversion_speed) +{ + const struct ltc2451_config *config = dev->config; + uint8_t wr_buf[1]; + int err; + + if (conversion_speed == 60) { + wr_buf[0] = 0; + } else if (conversion_speed == 30) { + wr_buf[0] = 1; + } else { + LOG_ERR("Invalid conversion speed selected"); + return -EINVAL; + } + + err = i2c_write_dt(&config->i2c, wr_buf, sizeof(wr_buf)); + + if (err != 0) { + LOG_ERR("LTC write failed (err %d)", err); + } + + return err; +} + +static int ltc2451_read_latest_conversion(const struct device *dev, + const struct adc_sequence *sequence) +{ + const struct ltc2451_config *config = dev->config; + uint8_t rd_buf[2]; + uint16_t *value_buf; + int err = i2c_read_dt(&config->i2c, rd_buf, sizeof(rd_buf)); + + if (err == 0) { + value_buf = (uint16_t *)sequence->buffer; + value_buf[0] = sys_get_be16(rd_buf); + } else { + LOG_ERR("LTC read failed (err %d)", err); + } + + return err; +} + +static int ltc2451_init(const struct device *dev) +{ + const struct ltc2451_config *config = dev->config; + + if (!device_is_ready(config->i2c.bus)) { + LOG_ERR("I2C device not ready"); + return -ENODEV; + } + + return ltc2451_set_conversion_speed(dev, config->conversion_speed); +} + +static const struct adc_driver_api ltc2451_api = { + .channel_setup = ltc2451_channel_setup, + .read = ltc2451_read_latest_conversion, +}; + +#define LTC2451_DEFINE(index) \ + static const struct ltc2451_config ltc2451_cfg_##index = { \ + .i2c = I2C_DT_SPEC_INST_GET(index), \ + .conversion_speed = DT_INST_PROP(index, conversion_speed), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(index, <c2451_init, NULL, NULL, \ + <c2451_cfg_##index, POST_KERNEL, CONFIG_ADC_INIT_PRIORITY, \ + <c2451_api); + +DT_INST_FOREACH_STATUS_OKAY(LTC2451_DEFINE) diff --git a/drivers/adc/adc_max11102_17.c b/drivers/adc/adc_max11102_17.c new file mode 100644 index 00000000000..5443de03753 --- /dev/null +++ b/drivers/adc/adc_max11102_17.c @@ -0,0 +1,479 @@ +/* + * Copyright (c) 2023 SILA Embedded Solutions GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ADC_CONTEXT_USES_KERNEL_TIMER 1 +#include "adc_context.h" + +LOG_MODULE_REGISTER(max11102_17, CONFIG_ADC_LOG_LEVEL); + +struct max11102_17_config { + struct spi_dt_spec bus; + const struct gpio_dt_spec gpio_chsel; + uint8_t resolution; + uint8_t channel_count; +}; + +struct max11102_17_data { + struct adc_context ctx; + struct k_sem acquire_signal; + int16_t *buffer; + int16_t *buffer_ptr; + uint8_t current_channel_id; + uint8_t sequence_channel_id; +#if CONFIG_ADC_ASYNC + struct k_thread thread; + + K_KERNEL_STACK_MEMBER(stack, CONFIG_ADC_MAX11102_17_ACQUISITION_THREAD_STACK_SIZE); +#endif /* CONFIG_ADC_ASYNC */ +}; + +static int max11102_17_switch_channel(const struct device *dev) +{ + const struct max11102_17_config *config = dev->config; + struct max11102_17_data *data = dev->data; + int result; + uint8_t buffer_rx[1]; + const struct spi_buf rx_buf[] = {{ + .buf = buffer_rx, + .len = ARRAY_SIZE(buffer_rx), + }}; + const struct spi_buf_set rx = { + .buffers = rx_buf, + .count = ARRAY_SIZE(rx_buf), + }; + struct spi_dt_spec bus; + + memcpy(&bus, &config->bus, sizeof(bus)); + bus.config.operation |= SPI_HOLD_ON_CS; + + result = spi_read_dt(&bus, &rx); + if (result != 0) { + LOG_ERR("read failed with error %i", result); + return result; + } + + gpio_pin_set_dt(&config->gpio_chsel, data->current_channel_id); + + result = spi_read_dt(&config->bus, &rx); + if (result != 0) { + LOG_ERR("read failed with error %i", result); + return result; + } + + return 0; +} + +static int max11102_17_channel_setup(const struct device *dev, + const struct adc_channel_cfg *channel_cfg) +{ + const struct max11102_17_config *config = dev->config; + + LOG_DBG("read from ADC channel %i", channel_cfg->channel_id); + + if (channel_cfg->reference != ADC_REF_EXTERNAL0) { + LOG_ERR("invalid reference %i", channel_cfg->reference); + return -EINVAL; + } + + if (channel_cfg->gain != ADC_GAIN_1) { + LOG_ERR("invalid gain %i", channel_cfg->gain); + return -EINVAL; + } + + if (channel_cfg->acquisition_time != ADC_ACQ_TIME_DEFAULT) { + LOG_ERR("invalid acquisition time %i", channel_cfg->acquisition_time); + return -EINVAL; + } + + if (channel_cfg->differential != 0) { + LOG_ERR("differential inputs are not supported"); + return -EINVAL; + } + + if (channel_cfg->channel_id > config->channel_count) { + LOG_ERR("invalid channel selection %i", channel_cfg->channel_id); + return -EINVAL; + } + + return 0; +} + +static int max11102_17_validate_buffer_size(const struct adc_sequence *sequence) +{ + size_t necessary = sizeof(int16_t); + + if (sequence->options) { + necessary *= (1 + sequence->options->extra_samplings); + } + + if (sequence->buffer_size < necessary) { + return -ENOMEM; + } + + return 0; +} + +static int max11102_17_validate_sequence(const struct device *dev, + const struct adc_sequence *sequence) +{ + const struct max11102_17_config *config = dev->config; + struct max11102_17_data *data = dev->data; + size_t sequence_channel_count = 0; + const size_t channel_maximum = 8*sizeof(sequence->channels); + + if (sequence->resolution != config->resolution) { + LOG_ERR("invalid resolution"); + return -EINVAL; + } + + for (size_t i = 0; i < channel_maximum; ++i) { + if ((BIT(i) & sequence->channels) == 0) { + continue; + } + + if (i > config->channel_count) { + LOG_ERR("invalid channel selection"); + return -EINVAL; + } + + sequence_channel_count++; + data->sequence_channel_id = i; + } + + if (sequence_channel_count == 0) { + LOG_ERR("no channel selected"); + return -EINVAL; + } + + if (sequence_channel_count > 1) { + LOG_ERR("multiple channels selected"); + return -EINVAL; + } + + if (sequence->oversampling) { + LOG_ERR("oversampling is not supported"); + return -EINVAL; + } + + return max11102_17_validate_buffer_size(sequence); +} + +static void adc_context_update_buffer_pointer(struct adc_context *ctx, bool repeat_sampling) +{ + struct max11102_17_data *data = CONTAINER_OF(ctx, struct max11102_17_data, ctx); + + if (repeat_sampling) { + data->buffer = data->buffer_ptr; + } +} + +static void adc_context_start_sampling(struct adc_context *ctx) +{ + struct max11102_17_data *data = CONTAINER_OF(ctx, struct max11102_17_data, ctx); + + data->buffer_ptr = data->buffer; + k_sem_give(&data->acquire_signal); +} + +static int max11102_17_adc_start_read(const struct device *dev, const struct adc_sequence *sequence, + bool wait) +{ + int result; + struct max11102_17_data *data = dev->data; + + result = max11102_17_validate_sequence(dev, sequence); + + if (result != 0) { + LOG_ERR("sequence validation failed"); + return result; + } + + data->buffer = sequence->buffer; + + adc_context_start_read(&data->ctx, sequence); + + if (wait) { + result = adc_context_wait_for_completion(&data->ctx); + } + + return result; +} + +static int max11102_17_read_sample(const struct device *dev, int16_t *sample) +{ + const struct max11102_17_config *config = dev->config; + int result; + size_t trailing_bits = 15 - config->resolution; + uint8_t buffer_rx[2]; + const struct spi_buf rx_buf[] = {{ + .buf = buffer_rx, + .len = ARRAY_SIZE(buffer_rx), + }}; + const struct spi_buf_set rx = { + .buffers = rx_buf, + .count = ARRAY_SIZE(rx_buf), + }; + + result = spi_read_dt(&config->bus, &rx); + + if (result != 0) { + LOG_ERR("read failed with error %i", result); + return result; + } + + *sample = sys_get_be16(buffer_rx); + LOG_DBG("raw sample: 0x%04X", *sample); + + *sample = *sample >> trailing_bits; + *sample = *sample & GENMASK(config->resolution, 0); + LOG_DBG("sample: 0x%04X", *sample); + + return 0; +} + +static int max11102_17_adc_perform_read(const struct device *dev) +{ + int result; + struct max11102_17_data *data = dev->data; + + k_sem_take(&data->acquire_signal, K_FOREVER); + + if (data->sequence_channel_id != data->current_channel_id) { + LOG_DBG("switch channel selection"); + data->current_channel_id = data->sequence_channel_id; + max11102_17_switch_channel(dev); + } + + result = max11102_17_read_sample(dev, data->buffer); + if (result != 0) { + LOG_ERR("reading sample failed"); + adc_context_complete(&data->ctx, result); + return result; + } + + data->buffer++; + + adc_context_on_sampling_done(&data->ctx, dev); + + return result; +} + +#if CONFIG_ADC_ASYNC +static int max11102_17_adc_read_async(const struct device *dev, const struct adc_sequence *sequence, + struct k_poll_signal *async) +{ + int result; + struct max11102_17_data *data = dev->data; + + adc_context_lock(&data->ctx, true, async); + result = max11102_17_adc_start_read(dev, sequence, true); + adc_context_release(&data->ctx, result); + + return result; +} + +static int max11102_17_read(const struct device *dev, const struct adc_sequence *sequence) +{ + int result; + struct max11102_17_data *data = dev->data; + + adc_context_lock(&data->ctx, false, NULL); + result = max11102_17_adc_start_read(dev, sequence, true); + adc_context_release(&data->ctx, result); + + return result; +} + +#else +static int max11102_17_read(const struct device *dev, const struct adc_sequence *sequence) +{ + int result; + struct max11102_17_data *data = dev->data; + + adc_context_lock(&data->ctx, false, NULL); + result = max11102_17_adc_start_read(dev, sequence, false); + + while (result == 0 && k_sem_take(&data->ctx.sync, K_NO_WAIT) != 0) { + result = max11102_17_adc_perform_read(dev); + } + + adc_context_release(&data->ctx, result); + return result; +} +#endif + +#if CONFIG_ADC_ASYNC +static void max11102_17_acquisition_thread(void *p1, void *p2, void *p3) +{ + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; + while (true) { + max11102_17_adc_perform_read(dev); + } +} +#endif + +static int max11102_17_init(const struct device *dev) +{ + int result; + const struct max11102_17_config *config = dev->config; + struct max11102_17_data *data = dev->data; + int16_t sample; + + adc_context_init(&data->ctx); + + k_sem_init(&data->acquire_signal, 0, 1); + + if (!spi_is_ready_dt(&config->bus)) { + LOG_ERR("SPI device is not ready"); + return -ENODEV; + } + + switch (config->channel_count) { + case 1: + if (config->gpio_chsel.port != NULL) { + LOG_ERR("GPIO for chsel set with only one channel"); + return -EINVAL; + } + break; + case 2: + if (config->gpio_chsel.port == NULL) { + LOG_ERR("no GPIO for chsel set with two channels"); + return -EINVAL; + } + + result = gpio_pin_configure_dt(&config->gpio_chsel, GPIO_OUTPUT_INACTIVE); + if (result != 0) { + LOG_ERR("failed to initialize GPIO for chsel"); + return result; + } + break; + default: + LOG_ERR("invalid number of channels (%i)", config->channel_count); + return -EINVAL; + } + + data->current_channel_id = 0; + +#if CONFIG_ADC_ASYNC + k_tid_t tid = k_thread_create( + &data->thread, data->stack, CONFIG_ADC_MAX11102_17_ACQUISITION_THREAD_STACK_SIZE, + max11102_17_acquisition_thread, (void *)dev, NULL, NULL, + CONFIG_ADC_MAX11102_17_ACQUISITION_THREAD_INIT_PRIO, 0, K_NO_WAIT); + k_thread_name_set(tid, "adc_max11102_17"); +#endif + + /* power up time is one conversion cycle */ + result = max11102_17_read_sample(dev, &sample); + if (result != 0) { + LOG_ERR("unable to read dummy sample for power up timing"); + return result; + } + + adc_context_unlock_unconditionally(&data->ctx); + + return result; +} + +static const struct adc_driver_api api = { + .channel_setup = max11102_17_channel_setup, + .read = max11102_17_read, + .ref_internal = 0, +#ifdef CONFIG_ADC_ASYNC + .read_async = max11102_17_adc_read_async, +#endif +}; + +BUILD_ASSERT(CONFIG_ADC_INIT_PRIORITY > CONFIG_SPI_INIT_PRIORITY, + "CONFIG_ADC_INIT_PRIORITY must be higher than CONFIG_SPI_INIT_PRIORITY"); + +#define ADC_MAX11102_17_INST_DEFINE(index, name, res, channels) \ + static const struct max11102_17_config config_##name##_##index = { \ + .bus = SPI_DT_SPEC_INST_GET( \ + index, \ + SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA | SPI_WORD_SET(8), 0), \ + .gpio_chsel = GPIO_DT_SPEC_INST_GET_OR(index, chsel_gpios, {0}), \ + .resolution = res, \ + .channel_count = channels, \ + }; \ + static struct max11102_17_data data_##name##_##index; \ + DEVICE_DT_INST_DEFINE(index, max11102_17_init, NULL, &data_##name##_##index, \ + &config_##name##_##index, POST_KERNEL, CONFIG_ADC_INIT_PRIORITY, \ + &api); + +#define DT_DRV_COMPAT maxim_max11102 +#define ADC_MAX11102_RESOLUTION 12 +#define ADC_MAX11102_CHANNELS 2 +DT_INST_FOREACH_STATUS_OKAY_VARGS(ADC_MAX11102_17_INST_DEFINE, DT_DRV_COMPAT, + ADC_MAX11102_RESOLUTION, ADC_MAX11102_CHANNELS) +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT maxim_max11103 +#define ADC_MAX11103_RESOLUTION 12 +#define ADC_MAX11103_CHANNELS 2 +DT_INST_FOREACH_STATUS_OKAY_VARGS(ADC_MAX11102_17_INST_DEFINE, DT_DRV_COMPAT, + ADC_MAX11103_RESOLUTION, ADC_MAX11103_CHANNELS) +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT maxim_max11105 +#define ADC_MAX11105_RESOLUTION 12 +#define ADC_MAX11105_CHANNELS 1 +DT_INST_FOREACH_STATUS_OKAY_VARGS(ADC_MAX11102_17_INST_DEFINE, DT_DRV_COMPAT, + ADC_MAX11105_RESOLUTION, ADC_MAX11105_CHANNELS) +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT maxim_max11106 +#define ADC_MAX11106_RESOLUTION 10 +#define ADC_MAX11106_CHANNELS 2 +DT_INST_FOREACH_STATUS_OKAY_VARGS(ADC_MAX11102_17_INST_DEFINE, DT_DRV_COMPAT, + ADC_MAX11106_RESOLUTION, ADC_MAX11106_CHANNELS) +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT maxim_max11110 +#define ADC_MAX11110_RESOLUTION 10 +#define ADC_MAX11110_CHANNELS 1 +DT_INST_FOREACH_STATUS_OKAY_VARGS(ADC_MAX11102_17_INST_DEFINE, DT_DRV_COMPAT, + ADC_MAX11110_RESOLUTION, ADC_MAX11110_CHANNELS) +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT maxim_max11111 +#define ADC_MAX11111_RESOLUTION 8 +#define ADC_MAX11111_CHANNELS 2 +DT_INST_FOREACH_STATUS_OKAY_VARGS(ADC_MAX11102_17_INST_DEFINE, DT_DRV_COMPAT, + ADC_MAX11111_RESOLUTION, ADC_MAX11111_CHANNELS) +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT maxim_max11115 +#define ADC_MAX11115_RESOLUTION 8 +#define ADC_MAX11115_CHANNELS 1 +DT_INST_FOREACH_STATUS_OKAY_VARGS(ADC_MAX11102_17_INST_DEFINE, DT_DRV_COMPAT, + ADC_MAX11115_RESOLUTION, ADC_MAX11115_CHANNELS) +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT maxim_max11116 +#define ADC_MAX11116_RESOLUTION 8 +#define ADC_MAX11116_CHANNELS 1 +DT_INST_FOREACH_STATUS_OKAY_VARGS(ADC_MAX11102_17_INST_DEFINE, DT_DRV_COMPAT, + ADC_MAX11116_RESOLUTION, ADC_MAX11116_CHANNELS) +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT maxim_max11117 +#define ADC_MAX11117_RESOLUTION 10 +#define ADC_MAX11117_CHANNELS 1 +DT_INST_FOREACH_STATUS_OKAY_VARGS(ADC_MAX11102_17_INST_DEFINE, DT_DRV_COMPAT, + ADC_MAX11117_RESOLUTION, ADC_MAX11117_CHANNELS) +#undef DT_DRV_COMPAT diff --git a/drivers/adc/adc_max1125x.c b/drivers/adc/adc_max1125x.c index 82a85d2af1c..a6e005defff 100644 --- a/drivers/adc/adc_max1125x.c +++ b/drivers/adc/adc_max1125x.c @@ -226,7 +226,7 @@ struct max1125x_data { struct k_thread thread; bool differential; - K_THREAD_STACK_MEMBER(stack, CONFIG_ADC_MAX1125X_ACQUISITION_THREAD_STACK_SIZE); + K_KERNEL_STACK_MEMBER(stack, CONFIG_ADC_MAX1125X_ACQUISITION_THREAD_STACK_SIZE); }; static void max1125x_data_ready_handler(const struct device *dev, struct gpio_callback *gpio_cb, @@ -690,8 +690,12 @@ static int max1125x_read(const struct device *dev, const struct adc_sequence *se return max1125x_adc_read_async(dev, sequence, NULL); } -static void max1125x_acquisition_thread(const struct device *dev) +static void max1125x_acquisition_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; struct max1125x_data *data = dev->data; int rc; @@ -750,9 +754,9 @@ static int max1125x_init(const struct device *dev) return -EIO; } - const k_tid_t tid = k_thread_create( + k_tid_t tid = k_thread_create( &data->thread, data->stack, K_THREAD_STACK_SIZEOF(data->stack), - (k_thread_entry_t)max1125x_acquisition_thread, (void *)dev, NULL, NULL, + max1125x_acquisition_thread, (void *)dev, NULL, NULL, CONFIG_ADC_MAX1125X_ACQUISITION_THREAD_PRIORITY, 0, K_NO_WAIT); k_thread_name_set(tid, "adc_max1125x"); diff --git a/drivers/adc/adc_mcp320x.c b/drivers/adc/adc_mcp320x.c index b5ff94a105f..dff4e579c5f 100644 --- a/drivers/adc/adc_mcp320x.c +++ b/drivers/adc/adc_mcp320x.c @@ -232,8 +232,12 @@ static int mcp320x_read_channel(const struct device *dev, uint8_t channel, return 0; } -static void mcp320x_acquisition_thread(struct mcp320x_data *data) +static void mcp320x_acquisition_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct mcp320x_data *data = p1; uint16_t result = 0; uint8_t channel; int err; @@ -281,7 +285,7 @@ static int mcp320x_init(const struct device *dev) k_thread_create(&data->thread, data->stack, CONFIG_ADC_MCP320X_ACQUISITION_THREAD_STACK_SIZE, - (k_thread_entry_t)mcp320x_acquisition_thread, + mcp320x_acquisition_thread, data, NULL, NULL, CONFIG_ADC_MCP320X_ACQUISITION_THREAD_PRIO, 0, K_NO_WAIT); diff --git a/drivers/adc/adc_mcux_lpadc.c b/drivers/adc/adc_mcux_lpadc.c index c9ea7197c2b..b15790ccb9d 100644 --- a/drivers/adc/adc_mcux_lpadc.c +++ b/drivers/adc/adc_mcux_lpadc.c @@ -13,7 +13,9 @@ #include #include +#include #include +#include #include @@ -43,6 +45,7 @@ struct mcux_lpadc_config { uint32_t offset_b; void (*irq_config_func)(const struct device *dev); const struct pinctrl_dev_config *pincfg; + const struct device **ref_supplies; }; struct mcux_lpadc_data { @@ -392,6 +395,16 @@ static int mcux_lpadc_init(const struct device *dev) return err; } + /* Enable necessary regulators */ + const struct device **regulator = config->ref_supplies; + + while (*regulator != NULL) { + err = regulator_enable(*(regulator++)); + if (err) { + return err; + } + } + LPADC_GetDefaultConfig(&adc_config); adc_config.enableAnalogPreliminary = true; @@ -455,8 +468,18 @@ static const struct adc_driver_api mcux_lpadc_driver_api = { #endif }; +#define LPADC_REGULATOR_DEPENDENCY(node_id, prop, idx) \ + DEVICE_DT_GET(DT_PHANDLE_BY_IDX(node_id, prop, idx)), + +#define LPADC_REGULATORS_DEFINE(inst) \ + static const struct device *mcux_lpadc_ref_supplies_##inst[] = { \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, nxp_reference_supply), \ + (DT_INST_FOREACH_PROP_ELEM(inst, nxp_reference_supply, \ + LPADC_REGULATOR_DEPENDENCY)), ()) NULL}; #define LPADC_MCUX_INIT(n) \ + LPADC_REGULATORS_DEFINE(n) \ + \ static void mcux_lpadc_config_func_##n(const struct device *dev); \ \ PINCTRL_DT_INST_DEFINE(n); \ @@ -469,8 +492,8 @@ static const struct adc_driver_api mcux_lpadc_driver_api = { .offset_b = DT_INST_PROP(n, offset_value_b), \ .irq_config_func = mcux_lpadc_config_func_##n, \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .ref_supplies = mcux_lpadc_ref_supplies_##n, \ }; \ - \ static struct mcux_lpadc_data mcux_lpadc_data_##n = { \ ADC_CONTEXT_INIT_TIMER(mcux_lpadc_data_##n, ctx), \ ADC_CONTEXT_INIT_LOCK(mcux_lpadc_data_##n, ctx), \ diff --git a/drivers/adc/adc_npcx.c b/drivers/adc/adc_npcx.c index 4bd81c9ef37..ae1cf65ffbb 100644 --- a/drivers/adc/adc_npcx.c +++ b/drivers/adc/adc_npcx.c @@ -28,34 +28,31 @@ LOG_MODULE_REGISTER(adc_npcx, CONFIG_ADC_LOG_LEVEL); #define ADC_REGULAR_GENDLY_VAL 0x0100 #define ADC_REGULAR_MEAST_VAL 0x0001 -/* ADC channel number */ -#define NPCX_ADC_CH_COUNT DT_INST_PROP(0, channel_count) - /* ADC targeted operating frequency (2MHz) */ #define NPCX_ADC_CLK 2000000 -/* ADC internal reference voltage (Unit:mV) */ -#define NPCX_ADC_VREF_VOL 2816 - /* ADC conversion mode */ #define NPCX_ADC_CHN_CONVERSION_MODE 0 #define NPCX_ADC_SCAN_CONVERSION_MODE 1 +/* Max channel number to be converted in ADCCS */ +#define NPCX_ADCCS_MAX_CHANNEL_COUNT 16 + #define ADC_NPCX_THRVAL_RESOLUTION 10 #define ADC_NPCX_THRVAL_MAX BIT_MASK(ADC_NPCX_THRVAL_RESOLUTION) -#define THRCTL(dev, ctl_no) (*((volatile uint16_t *) npcx_thrctl_reg(dev, ctl_no))) - /* Device config */ struct adc_npcx_config { /* adc controller base address */ uintptr_t base; /* clock configuration */ struct npcx_clk_cfg clk_cfg; + /* the number of ADC channels */ + const uint8_t channel_count; /* amount of thresholds supported */ const uint8_t threshold_count; - /* threshold control register offset */ - const uint16_t threshold_reg_offset; + /* routine for configuring ADC's ISR */ + void (*irq_cfg_func)(void); const struct pinctrl_dev_config *pcfg; }; @@ -88,7 +85,7 @@ struct adc_npcx_threshold_data { * channels being used in repetitive mode in order to set ADC registers * back to threshold detection when adc_npcx_read is completed. */ - uint16_t repetitive_channels; + uint32_t repetitive_channels; /* * While threshold interruption is enabled, adc_npcx_read must disable * all active threshold running to avoid race condition, this variable @@ -98,11 +95,6 @@ struct adc_npcx_threshold_data { /* This array holds current configuration for each threshold. */ struct adc_npcx_threshold_control control[DT_INST_PROP(0, threshold_count)]; - /* - * Pointer of work queue thread to be notified when threshold assertion - * occurs. - */ - struct k_work_q *work_q; }; /* Driver data */ @@ -115,7 +107,7 @@ struct adc_npcx_data { * Bit-mask indicating the channels to be included in each sampling * of this sequence. */ - uint16_t channels; + uint32_t channels; /* ADC Device pointer used in api functions */ const struct device *adc_dev; uint16_t *buffer; @@ -129,6 +121,12 @@ struct adc_npcx_data { #endif }; +/* + * Pointer of internal work queue thread to be notified when threshold assertion + * occurs if CONFIG_ADC_CMP_NPCX_WORKQUEUE is enabled. + */ +struct k_work_q *work_q; + /* Driver convenience defines */ #define HAL_INSTANCE(dev) ((struct adc_reg *)((const struct adc_npcx_config *)(dev)->config)->base) @@ -150,12 +148,39 @@ static void adc_npcx_pm_policy_state_lock_put(struct adc_npcx_data *data) } #endif -static inline uint32_t npcx_thrctl_reg(const struct device *dev, - uint32_t ctl_no) +static inline void adc_npcx_config_channels(const struct device *dev, uint32_t channels) +{ + const struct adc_npcx_config *config = dev->config; + struct adc_reg *const inst = HAL_INSTANCE(dev); + + inst->ADCCS = channels & BIT_MASK(NPCX_ADCCS_MAX_CHANNEL_COUNT); + + /* Only npcx4 and later series support over 16 ADC channels */ + if (config->channel_count > NPCX_ADCCS_MAX_CHANNEL_COUNT) { + inst->ADCCS2 = (channels >> NPCX_ADCCS_MAX_CHANNEL_COUNT) & + BIT_MASK(NPCX_ADCCS_MAX_CHANNEL_COUNT); + } +} + +static inline void adc_npcx_enable_threshold_detect(const struct device *dev, uint8_t th_sel, + bool enable) { const struct adc_npcx_config *config = dev->config; - return (config->base + config->threshold_reg_offset) + (ctl_no - 1) * 2; + if (enable) { +#ifdef CONFIG_ADC_NPCX_CMP_V2 + THEN(config->base) |= BIT(th_sel); +#else /* CONFIG_ADC_NPCX_CMP_V1 */ + THRCTL(config->base, th_sel) |= BIT(NPCX_THRCTL_THEN); +#endif + + } else { +#ifdef CONFIG_ADC_NPCX_CMP_V2 + THEN(config->base) &= ~BIT(th_sel); +#else /* CONFIG_ADC_NPCX_CMP_V1 */ + THRCTL(config->base, th_sel) &= ~BIT(NPCX_THRCTL_THEN); +#endif + } } static void adc_npcx_isr(const struct device *dev) @@ -198,12 +223,12 @@ static void adc_npcx_isr(const struct device *dev) if (IS_ENABLED(CONFIG_ADC_CMP_NPCX) && t_data->active_thresholds) { /* Set repetitive channels back */ - inst->ADCCS = t_data->repetitive_channels; + adc_npcx_config_channels(dev, t_data->repetitive_channels); /* Start conversion */ inst->ADCCNF |= BIT(NPCX_ADCCNF_START); } else { /* Disable all channels */ - inst->ADCCS = 0; + adc_npcx_config_channels(dev, 0); /* Turn off ADC */ inst->ADCCNF &= ~(BIT(NPCX_ADCCNF_ADCEN)); @@ -231,9 +256,8 @@ static void adc_npcx_isr(const struct device *dev) inst->THRCTS = thrcts; if (t_data->control[i].work) { /* Notify work thread */ - k_work_submit_to_queue(t_data->work_q ? - t_data->work_q : &k_sys_work_q, - t_data->control[i].work); + k_work_submit_to_queue(work_q ? work_q : &k_sys_work_q, + t_data->control[i].work); } } } @@ -246,11 +270,12 @@ static void adc_npcx_isr(const struct device *dev) static int adc_npcx_validate_buffer_size(const struct device *dev, const struct adc_sequence *sequence) { + const struct adc_npcx_config *config = dev->config; uint8_t channels = 0; uint32_t mask; size_t needed; - for (mask = BIT(NPCX_ADC_CH_COUNT - 1); mask != 0; mask >>= 1) { + for (mask = BIT(config->channel_count - 1); mask != 0; mask >>= 1) { if (mask & sequence->channels) { channels++; } @@ -270,6 +295,7 @@ static int adc_npcx_validate_buffer_size(const struct device *dev, static void adc_npcx_start_scan(const struct device *dev) { + const struct adc_npcx_config *config = dev->config; struct adc_npcx_data *const data = dev->data; struct adc_reg *const inst = HAL_INSTANCE(dev); @@ -286,7 +312,7 @@ static void adc_npcx_start_scan(const struct device *dev) inst->ADCSTS |= BIT(NPCX_ADCSTS_EOCCEV); /* Update selected channels in scan mode by channels mask */ - inst->ADCCS |= data->channels; + adc_npcx_config_channels(dev, data->channels); /* Select 'Scan' Conversion mode. */ SET_FIELD(inst->ADCCNF, NPCX_ADCCNF_ADCMD_FIELD, @@ -298,18 +324,24 @@ static void adc_npcx_start_scan(const struct device *dev) /* Start conversion */ inst->ADCCNF |= BIT(NPCX_ADCCNF_START); - LOG_DBG("Start ADC scan conversion and ADCCNF,ADCCS are (%04X,%04X)\n", + if (config->channel_count > NPCX_ADCCS_MAX_CHANNEL_COUNT) { + LOG_DBG("Start ADC scan conversion and ADCCNF,ADCCS, ADCCS2 are " + "(%04X,%04X,%04X)\n", inst->ADCCNF, inst->ADCCS, inst->ADCCS2); + } else { + LOG_DBG("Start ADC scan conversion and ADCCNF,ADCCS are (%04X,%04X)\n", inst->ADCCNF, inst->ADCCS); + } } static int adc_npcx_start_read(const struct device *dev, const struct adc_sequence *sequence) { + const struct adc_npcx_config *config = dev->config; struct adc_npcx_data *const data = dev->data; int error = 0; if (!sequence->channels || - (sequence->channels & ~BIT_MASK(NPCX_ADC_CH_COUNT))) { + (sequence->channels & ~BIT_MASK(config->channel_count))) { LOG_ERR("Invalid ADC channels"); return -EINVAL; } @@ -364,9 +396,10 @@ static void adc_context_update_buffer_pointer(struct adc_context *ctx, static int adc_npcx_channel_setup(const struct device *dev, const struct adc_channel_cfg *channel_cfg) { + const struct adc_npcx_config *config = dev->config; uint8_t channel_id = channel_cfg->channel_id; - if (channel_id >= NPCX_ADC_CH_COUNT) { + if (channel_id >= config->channel_count) { LOG_ERR("Invalid channel %d", channel_id); return -EINVAL; } @@ -443,18 +476,21 @@ static void adc_npcx_set_repetitive(const struct device *dev, int chnsel, /* Set ADC conversion code to SW conversion mode */ SET_FIELD(inst->ADCCNF, NPCX_ADCCNF_ADCMD_FIELD, NPCX_ADC_SCAN_CONVERSION_MODE); - /* Update number of channel to be converted */ - inst->ADCCS |= BIT(chnsel); + + /* Add selected ADC channel to be converted */ + t_data->repetitive_channels |= BIT(chnsel); + adc_npcx_config_channels(dev, t_data->repetitive_channels); + /* Set conversion type to repetitive (runs continuously) */ inst->ADCCNF |= BIT(NPCX_ADCCNF_ADCRPTC); - t_data->repetitive_channels |= BIT(chnsel); /* Start conversion */ inst->ADCCNF |= BIT(NPCX_ADCCNF_START); } else { - inst->ADCCS &= ~BIT(chnsel); - + /* Remove selected ADC channel to be converted */ t_data->repetitive_channels &= ~BIT(chnsel); + adc_npcx_config_channels(dev, t_data->repetitive_channels); + if (!t_data->repetitive_channels) { /* No thesholdd active left, disable repetitive mode */ inst->ADCCNF &= ~BIT(NPCX_ADCCNF_ADCRPTC); @@ -493,7 +529,7 @@ int adc_npcx_threshold_ctrl_set_param(const struct device *dev, adc_context_lock(&data->ctx, false, NULL); switch (param->type) { case ADC_NPCX_THRESHOLD_PARAM_CHNSEL: - if (param->val >= NPCX_ADC_CH_COUNT) { + if (param->val >= config->channel_count) { ret = -EINVAL; break; } @@ -530,6 +566,7 @@ static int adc_npcx_threshold_ctrl_setup(const struct device *dev, const uint8_t th_sel) { struct adc_npcx_data *const data = dev->data; + struct adc_driver_api *api = (struct adc_driver_api *)dev->api; struct adc_npcx_threshold_data *const t_data = data->threshold_data; const struct adc_npcx_config *config = dev->config; struct adc_npcx_threshold_control *const t_ctrl = @@ -548,24 +585,24 @@ static int adc_npcx_threshold_ctrl_setup(const struct device *dev, return -EBUSY; } - if (t_ctrl->chnsel >= NPCX_ADC_CH_COUNT || - t_ctrl->thrval >= NPCX_ADC_VREF_VOL || + if (t_ctrl->chnsel >= config->channel_count || + t_ctrl->thrval >= api->ref_internal || t_ctrl->thrval == 0 || t_ctrl->work == 0) { adc_context_release(&data->ctx, 0); LOG_ERR("Threshold selected (%d) is not configured!", th_sel); return -EINVAL; } - SET_FIELD(THRCTL(dev, (th_sel + 1)), + SET_FIELD(THRCTL(config->base, th_sel), NPCX_THRCTL_CHNSEL, t_ctrl->chnsel); if (t_ctrl->l_h) { - THRCTL(dev, (th_sel + 1)) |= BIT(NPCX_THRCTL_L_H); + THRCTL(config->base, th_sel) |= BIT(NPCX_THRCTL_L_H); } else { - THRCTL(dev, (th_sel + 1)) &= ~BIT(NPCX_THRCTL_L_H); + THRCTL(config->base, th_sel) &= ~BIT(NPCX_THRCTL_L_H); } /* Set the threshold value. */ - SET_FIELD(THRCTL(dev, (th_sel + 1)), NPCX_THRCTL_THRVAL, + SET_FIELD(THRCTL(config->base, th_sel), NPCX_THRCTL_THRVAL, t_ctrl->thrval); adc_context_release(&data->ctx, 0); @@ -576,6 +613,7 @@ static int adc_npcx_threshold_enable_irq(const struct device *dev, const uint8_t th_sel) { struct adc_reg *const inst = HAL_INSTANCE(dev); + struct adc_driver_api *api = (struct adc_driver_api *)dev->api; struct adc_npcx_data *const data = dev->data; const struct adc_npcx_config *config = dev->config; struct adc_npcx_threshold_data *const t_data = data->threshold_data; @@ -589,8 +627,8 @@ static int adc_npcx_threshold_enable_irq(const struct device *dev, } adc_context_lock(&data->ctx, false, NULL); - if (t_ctrl->chnsel >= NPCX_ADC_CH_COUNT || - t_ctrl->thrval >= NPCX_ADC_VREF_VOL || + if (t_ctrl->chnsel >= config->channel_count || + t_ctrl->thrval >= api->ref_internal || t_ctrl->thrval == 0 || t_ctrl->work == 0) { adc_context_release(&data->ctx, 0); LOG_ERR("Threshold selected (%d) is not configured!", th_sel); @@ -604,7 +642,7 @@ static int adc_npcx_threshold_enable_irq(const struct device *dev, thrcts = inst->THRCTS & ~GENMASK(config->threshold_count - 1, 0); /* Enable threshold detection */ - THRCTL(dev, (th_sel + 1)) |= BIT(NPCX_THRCTL_THEN); + adc_npcx_enable_threshold_detect(dev, th_sel, true); /* clear threshold status */ thrcts |= BIT(th_sel); @@ -652,7 +690,7 @@ int adc_npcx_threshold_disable_irq(const struct device *dev, inst->THRCTS = thrcts; /* Disable threshold detection */ - THRCTL(dev, (th_sel + 1)) &= ~BIT(NPCX_THRCTL_THEN); + adc_npcx_enable_threshold_detect(dev, th_sel, false); /* Update active threshold */ t_data->active_thresholds &= ~BIT(th_sel); @@ -687,53 +725,24 @@ int adc_npcx_threshold_ctrl_enable(const struct device *dev, uint8_t th_sel, return ret; } -int adc_npcx_threshold_mv_to_thrval(uint32_t val_mv, uint32_t *thrval) +int adc_npcx_threshold_mv_to_thrval(const struct device *dev, uint32_t val_mv, + uint32_t *thrval) { + struct adc_driver_api *api = (struct adc_driver_api *)dev->api; + if (!IS_ENABLED(CONFIG_ADC_CMP_NPCX)) { return -EOPNOTSUPP; } - if (val_mv >= NPCX_ADC_VREF_VOL) { + if (val_mv >= api->ref_internal) { return -EINVAL; } *thrval = (val_mv << ADC_NPCX_THRVAL_RESOLUTION) / - NPCX_ADC_VREF_VOL; + api->ref_internal; return 0; } -/* ADC driver registration */ -static const struct adc_driver_api adc_npcx_driver_api = { - .channel_setup = adc_npcx_channel_setup, - .read = adc_npcx_read, -#if defined(CONFIG_ADC_ASYNC) - .read_async = adc_npcx_read_async, -#endif - .ref_internal = NPCX_ADC_VREF_VOL, -}; - -static int adc_npcx_init(const struct device *dev); - -PINCTRL_DT_INST_DEFINE(0); -BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1, - "only one 'nuvoton_npcx_adc' compatible node may be present"); - -static const struct adc_npcx_config adc_npcx_cfg_0 = { - .base = DT_INST_REG_ADDR(0), - .clk_cfg = NPCX_DT_CLK_CFG_ITEM(0), - .threshold_count = DT_INST_PROP(0, threshold_count), - .threshold_reg_offset = DT_INST_PROP(0, threshold_reg_offset), - .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0), -}; - -static struct adc_npcx_threshold_data threshold_data_0; - -static struct adc_npcx_data adc_npcx_data_0 = { - ADC_CONTEXT_INIT_TIMER(adc_npcx_data_0, ctx), - ADC_CONTEXT_INIT_LOCK(adc_npcx_data_0, ctx), - ADC_CONTEXT_INIT_SYNC(adc_npcx_data_0, ctx), -}; - #if defined(CONFIG_ADC_CMP_NPCX_WORKQUEUE) struct k_work_q adc_npcx_work_q; @@ -752,20 +761,13 @@ static int adc_npcx_init_cmp_work_q(void) K_KERNEL_STACK_SIZEOF(adc_npcx_work_q_stack), CONFIG_ADC_CMP_NPCX_WORKQUEUE_PRIORITY, &cfg); - threshold_data_0.work_q = &adc_npcx_work_q; + work_q = &adc_npcx_work_q; return 0; } SYS_INIT(adc_npcx_init_cmp_work_q, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY); #endif -DEVICE_DT_INST_DEFINE(0, - adc_npcx_init, NULL, - &adc_npcx_data_0, &adc_npcx_cfg_0, - PRE_KERNEL_1, - CONFIG_ADC_INIT_PRIORITY, - &adc_npcx_driver_api); - static int adc_npcx_init(const struct device *dev) { const struct adc_npcx_config *const config = dev->config; @@ -814,14 +816,8 @@ static int adc_npcx_init(const struct device *dev) inst->GENDLY = ADC_REGULAR_GENDLY_VAL; inst->MEAST = ADC_REGULAR_MEAST_VAL; - if (IS_ENABLED(CONFIG_ADC_CMP_NPCX)) { - data->threshold_data = &threshold_data_0; - } - /* Configure ADC interrupt and enable it */ - IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), adc_npcx_isr, - DEVICE_DT_INST_GET(0), 0); - irq_enable(DT_INST_IRQN(0)); + config->irq_cfg_func(); /* Initialize mutex of ADC channels */ adc_context_unlock_unconditionally(&data->ctx); @@ -835,3 +831,45 @@ static int adc_npcx_init(const struct device *dev) return 0; } + +#define NPCX_ADC_INIT(n) \ + \ + static void adc_npcx_irq_cfg_func_##n(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \ + adc_npcx_isr, DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + } \ + \ + static const struct adc_driver_api adc_npcx_driver_api_##n = { \ + .channel_setup = adc_npcx_channel_setup, \ + .read = adc_npcx_read, \ + .ref_internal = DT_INST_PROP(n, vref_mv), \ + IF_ENABLED(CONFIG_ADC_ASYNC, \ + (.read_async = adc_npcx_read_async,)) \ + }; \ + \ + PINCTRL_DT_INST_DEFINE(n); \ + \ + static const struct adc_npcx_config adc_npcx_cfg_##n = { \ + .base = DT_INST_REG_ADDR(n), \ + .clk_cfg = NPCX_DT_CLK_CFG_ITEM(n), \ + .channel_count = DT_INST_PROP(n, channel_count), \ + .threshold_count = DT_INST_PROP(n, threshold_count), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .irq_cfg_func = adc_npcx_irq_cfg_func_##n, \ + }; \ + static struct adc_npcx_threshold_data threshold_data_##n; \ + static struct adc_npcx_data adc_npcx_data_##n = { \ + ADC_CONTEXT_INIT_TIMER(adc_npcx_data_##n, ctx), \ + ADC_CONTEXT_INIT_LOCK(adc_npcx_data_##n, ctx), \ + ADC_CONTEXT_INIT_SYNC(adc_npcx_data_##n, ctx), \ + .threshold_data = &threshold_data_##n, \ + }; \ + DEVICE_DT_INST_DEFINE(n, \ + adc_npcx_init, NULL, \ + &adc_npcx_data_##n, &adc_npcx_cfg_##n, \ + PRE_KERNEL_1, CONFIG_ADC_INIT_PRIORITY, \ + &adc_npcx_driver_api_##n); + +DT_INST_FOREACH_STATUS_OKAY(NPCX_ADC_INIT) diff --git a/drivers/adc/adc_rpi_pico.c b/drivers/adc/adc_rpi_pico.c index 0c7f525ec0c..ec13b0d7b6d 100644 --- a/drivers/adc/adc_rpi_pico.c +++ b/drivers/adc/adc_rpi_pico.c @@ -8,6 +8,7 @@ #define DT_DRV_COMPAT raspberrypi_pico_adc #include +#include #include #include @@ -31,6 +32,8 @@ LOG_MODULE_REGISTER(adc_rpi, CONFIG_ADC_LOG_LEVEL); struct adc_rpi_config { /** Number of supported channels */ uint8_t num_channels; + /** pinctrl configs */ + const struct pinctrl_dev_config *pcfg; /** function pointer to irq setup */ void (*irq_configure)(void); }; @@ -289,6 +292,12 @@ static int adc_rpi_init(const struct device *dev) { const struct adc_rpi_config *config = dev->config; struct adc_rpi_data *data = dev->data; + int ret; + + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + return ret; + } config->irq_configure(); @@ -325,6 +334,7 @@ static int adc_rpi_init(const struct device *dev) #define ADC_RPI_INIT(idx) \ IRQ_CONFIGURE_FUNC(idx) \ + PINCTRL_DT_INST_DEFINE(idx); \ static struct adc_driver_api adc_rpi_api_##idx = { \ .channel_setup = adc_rpi_channel_setup, \ .read = adc_rpi_read, \ @@ -333,6 +343,7 @@ static int adc_rpi_init(const struct device *dev) }; \ static const struct adc_rpi_config adc_rpi_config_##idx = { \ .num_channels = ADC_RPI_CHANNEL_NUM, \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx), \ IRQ_CONFIGURE_DEFINE(idx), \ }; \ static struct adc_rpi_data adc_rpi_data_##idx = { \ diff --git a/drivers/adc/adc_shell.c b/drivers/adc/adc_shell.c index c7677b8d45f..81b0d0d3d2f 100644 --- a/drivers/adc/adc_shell.c +++ b/drivers/adc/adc_shell.c @@ -28,6 +28,10 @@ LOG_MODULE_REGISTER(adc_shell); "Configure channel id\n" \ "Usage: id \n" +#define CMD_HELP_DIFF \ + "Configure differential\n" \ + "Usage: differential <0||1>\n" + #define CMD_HELP_CH_NEG \ "Configure channel negative input\n" \ "Usage: negative \n" @@ -91,6 +95,16 @@ static struct adc_hdl { DT_FOREACH_STATUS_OKAY(raspberrypi_pico_adc, ADC_HDL_LIST_ENTRY) DT_FOREACH_STATUS_OKAY(zephyr_adc_emul, ADC_HDL_LIST_ENTRY) DT_FOREACH_STATUS_OKAY(nxp_s32_adc_sar, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(maxim_max11102, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(maxim_max11103, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(maxim_max11105, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(maxim_max11106, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(maxim_max11110, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(maxim_max11111, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(maxim_max11115, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(maxim_max11116, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(maxim_max11117, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(adi_ad5592_adc, ADC_HDL_LIST_ENTRY) }; static struct adc_hdl *get_adc(const char *device_label) @@ -124,7 +138,34 @@ static int cmd_adc_ch_id(const struct shell *sh, size_t argc, char **argv) adc->channel_config.channel_id = (uint8_t)strtol(argv[1], NULL, 10); retval = adc_channel_setup(adc->dev, &adc->channel_config); - LOG_DBG("Channel setup returned %i\n", retval); + LOG_DBG("Channel setup returned %i", retval); + + return retval; +} + +static int cmd_adc_ch_diff(const struct shell *sh, size_t argc, char **argv) +{ + /* -2: index of ADC label name */ + struct adc_hdl *adc = get_adc(argv[-2]); + int retval = 0; + char *endptr; + long diff; + + if (!device_is_ready(adc->dev)) { + shell_error(sh, "ADC device not ready"); + return -ENODEV; + } + + endptr = argv[1]; + diff = strtol(argv[1], &endptr, 10); + if ((endptr == argv[1]) || ((diff != 0) && (diff != 1))) { + shell_error(sh, " must be 0 or 1"); + return -EINVAL; + } + + adc->channel_config.differential = (uint8_t)diff; + retval = adc_channel_setup(adc->dev, &adc->channel_config); + LOG_DBG("Channel setup returned %i", retval); return retval; } @@ -148,7 +189,7 @@ static int cmd_adc_ch_neg(const struct shell *sh, size_t argc, char **argv) adc->channel_config.input_negative = (uint8_t)strtol(argv[1], NULL, 10); retval = adc_channel_setup(adc->dev, &adc->channel_config); - LOG_DBG("Channel setup returned %i\n", retval); + LOG_DBG("Channel setup returned %i", retval); return retval; #else @@ -175,7 +216,7 @@ static int cmd_adc_ch_pos(const struct shell *sh, size_t argc, char **argv) adc->channel_config.input_positive = (uint8_t)strtol(argv[1], NULL, 10); retval = adc_channel_setup(adc->dev, &adc->channel_config); - LOG_DBG("Channel setup returned %i\n", retval); + LOG_DBG("Channel setup returned %i", retval); return retval; #else @@ -202,7 +243,7 @@ static int cmd_adc_gain(const struct shell *sh, size_t argc, char **argv, memcpy(chosen_gain, argv[0], len); chosen_gain[len] = '\0'; retval = adc_channel_setup(adc->dev, &adc->channel_config); - LOG_DBG("Channel setup returned %i\n", retval); + LOG_DBG("Channel setup returned %i", retval); return retval; } @@ -239,7 +280,7 @@ static int cmd_adc_acq(const struct shell *sh, size_t argc, char **argv) ADC_ACQ_TIME_DEFAULT; } retval = adc_channel_setup(adc->dev, &adc->channel_config); - LOG_DBG("Channel setup returned %i\n", retval); + LOG_DBG("Channel setup returned %i", retval); return retval; } @@ -285,7 +326,7 @@ static int cmd_adc_ref(const struct shell *sh, size_t argc, char **argv, adc->channel_config.reference = reference; retval = adc_channel_setup(adc->dev, &adc->channel_config); - LOG_DBG("Channel setup returned %i\n", retval); + LOG_DBG("Channel setup returned %i", retval); return retval; } @@ -296,7 +337,7 @@ static int cmd_adc_read(const struct shell *sh, size_t argc, char **argv) uint8_t adc_channel_id = strtol(argv[1], NULL, 10); /* -1 index of adc label name */ struct adc_hdl *adc = get_adc(argv[-1]); - uint16_t m_sample_buffer[BUFFER_SIZE]; + int16_t m_sample_buffer[BUFFER_SIZE]; int retval; if (!device_is_ready(adc->dev)) { @@ -330,13 +371,23 @@ static int cmd_adc_print(const struct shell *sh, size_t argc, char **argv) "Reference: %s\n" "Acquisition Time: %u\n" "Channel ID: %u\n" + "Differential: %u\n" "Resolution: %u", adc->dev->name, chosen_gain, chosen_reference, adc->channel_config.acquisition_time, adc->channel_config.channel_id, + adc->channel_config.differential, adc->resolution); +#if CONFIG_ADC_CONFIGURABLE_INPUTS + shell_print(sh, "Input positive: %u", + adc->channel_config.input_positive); + if (adc->channel_config.differential != 0) { + shell_print(sh, "Input negative: %u", + adc->channel_config.input_negative); + } +#endif return 0; } @@ -369,6 +420,7 @@ SHELL_SUBCMD_DICT_SET_CREATE(sub_gain_cmds, cmd_adc_gain, SHELL_STATIC_SUBCMD_SET_CREATE(sub_channel_cmds, SHELL_CMD_ARG(id, NULL, CMD_HELP_CH_ID, cmd_adc_ch_id, 2, 0), + SHELL_CMD_ARG(differential, NULL, CMD_HELP_DIFF, cmd_adc_ch_diff, 2, 0), SHELL_COND_CMD_ARG(CONFIG_ADC_CONFIGURABLE_INPUTS, negative, NULL, CMD_HELP_CH_NEG, cmd_adc_ch_neg, 2, 0), SHELL_COND_CMD_ARG(CONFIG_ADC_CONFIGURABLE_INPUTS, diff --git a/drivers/adc/adc_stm32.c b/drivers/adc/adc_stm32.c index 4bff19ce57c..12a38c415fd 100644 --- a/drivers/adc/adc_stm32.c +++ b/drivers/adc/adc_stm32.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #if defined(CONFIG_SOC_SERIES_STM32U5X) #include @@ -27,7 +28,7 @@ #ifdef CONFIG_ADC_STM32_DMA #include #include -#include +#include #include #endif @@ -42,6 +43,17 @@ LOG_MODULE_REGISTER(adc_stm32); #include #include #include +#include + +#ifdef CONFIG_SOC_SERIES_STM32H7X +#include +#endif + +#ifdef CONFIG_NOCACHE_MEMORY +#include +#elif defined(CONFIG_CACHE_MANAGEMENT) +#include +#endif /* CONFIG_NOCACHE_MEMORY */ #if defined(CONFIG_SOC_SERIES_STM32F3X) #if defined(ADC1_V2_5) @@ -66,18 +78,18 @@ LOG_MODULE_REGISTER(adc_stm32); num_sampling_time_common_channels,\ 0, value) 0) +#define ANY_ADC_SEQUENCER_TYPE_IS(value) \ + (DT_INST_FOREACH_STATUS_OKAY_VARGS(IS_EQ_PROP_OR, \ + st_adc_sequencer,\ + 0, value) 0) + #define IS_EQ_PROP_OR(inst, prop, default_value, compare_value) \ IS_EQ(DT_INST_PROP_OR(inst, prop, default_value), compare_value) || /* reference voltage for the ADC */ #define STM32_ADC_VREF_MV DT_INST_PROP(0, vref_mv) -#if !defined(CONFIG_SOC_SERIES_STM32C0X) && \ - !defined(CONFIG_SOC_SERIES_STM32F0X) && \ - !defined(CONFIG_SOC_SERIES_STM32G0X) && \ - !defined(CONFIG_SOC_SERIES_STM32L0X) && \ - !defined(CONFIG_SOC_SERIES_STM32WBAX) && \ - !defined(CONFIG_SOC_SERIES_STM32WLX) +#if ANY_ADC_SEQUENCER_TYPE_IS(FULLY_CONFIGURABLE) #define RANK(n) LL_ADC_REG_RANK_##n static const uint32_t table_rank[] = { RANK(1), @@ -96,6 +108,22 @@ static const uint32_t table_rank[] = { RANK(14), RANK(15), RANK(16), +#if defined(LL_ADC_REG_RANK_17) + RANK(17), + RANK(18), + RANK(19), + RANK(20), + RANK(21), + RANK(22), + RANK(23), + RANK(24), + RANK(25), + RANK(26), + RANK(27), +#if defined(LL_ADC_REG_RANK_28) + RANK(28), +#endif /* LL_ADC_REG_RANK_28 */ +#endif /* LL_ADC_REG_RANK_17 */ }; #define SEQ_LEN(n) LL_ADC_REG_SEQ_SCAN_ENABLE_##n##RANKS @@ -117,11 +145,24 @@ static const uint32_t table_seq_len[] = { SEQ_LEN(14), SEQ_LEN(15), SEQ_LEN(16), +#if defined(LL_ADC_REG_SEQ_SCAN_ENABLE_17RANKS) + SEQ_LEN(17), + SEQ_LEN(18), + SEQ_LEN(19), + SEQ_LEN(20), + SEQ_LEN(21), + SEQ_LEN(22), + SEQ_LEN(23), + SEQ_LEN(24), + SEQ_LEN(25), + SEQ_LEN(26), + SEQ_LEN(27), +#if defined(LL_ADC_REG_SEQ_SCAN_ENABLE_28RANKS) + SEQ_LEN(28), +#endif /* LL_ADC_REG_SEQ_SCAN_ENABLE_28RANKS */ +#endif /* LL_ADC_REG_SEQ_SCAN_ENABLE_17RANKS */ }; -#endif - -/* External channels (maximum). */ -#define STM32_CHANNEL_COUNT 20 +#endif /* ANY_ADC_SEQUENCER_TYPE_IS(FULLY_CONFIGURABLE) */ /* Number of different sampling time values */ #define STM32_NB_SAMPLING_TIME 8 @@ -165,9 +206,7 @@ struct adc_stm32_cfg { const struct pinctrl_dev_config *pcfg; const uint16_t sampling_time_table[STM32_NB_SAMPLING_TIME]; int8_t num_sampling_time_common_channels; - int8_t temp_channel; - int8_t vref_channel; - int8_t vbat_channel; + int8_t sequencer_type; int8_t res_table_size; const uint32_t res_table[]; }; @@ -253,27 +292,25 @@ static int adc_stm32_dma_start(const struct device *dev, * The entire buffer must be in a single region. * An example of how the SRAM region can be defined in the DTS: * &sram4 { - * zephyr,memory-attr = "RAM_NOCACHE"; + * zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) | ... )>; * }; */ -static bool address_in_non_cacheable_sram(const uint16_t *buffer, const uint16_t size) +static bool buf_in_nocache(uintptr_t buf, size_t len_bytes) { - /* Default if no valid SRAM region found or buffer+size not located in a single region */ - bool cachable = false; -#define IS_NON_CACHEABLE_REGION_FN(node_id) \ - COND_CODE_1(DT_NODE_HAS_PROP(node_id, zephyr_memory_attr), ({ \ - const uint32_t region_start = DT_REG_ADDR(node_id); \ - const uint32_t region_end = region_start + DT_REG_SIZE(node_id); \ - if (((uint32_t)buffer >= region_start) && \ - (((uint32_t)buffer + size) < region_end)) { \ - cachable = strcmp(DT_PROP(node_id, zephyr_memory_attr), \ - "RAM_NOCACHE") == 0; \ - } \ - }), \ - (EMPTY)) - DT_FOREACH_STATUS_OKAY(mmio_sram, IS_NON_CACHEABLE_REGION_FN); - - return cachable; + bool buf_within_nocache = false; + +#ifdef CONFIG_NOCACHE_MEMORY + buf_within_nocache = (buf >= ((uintptr_t)_nocache_ram_start)) && + ((buf + len_bytes - 1) <= ((uintptr_t)_nocache_ram_end)); + if (buf_within_nocache) { + return true; + } +#endif /* CONFIG_NOCACHE_MEMORY */ + + buf_within_nocache = mem_attr_check_buf( + (void *)buf, len_bytes, DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE)) == 0; + + return buf_within_nocache; } #endif /* defined(CONFIG_ADC_STM32_DMA) && defined(CONFIG_SOC_SERIES_STM32H7X) */ @@ -296,7 +333,7 @@ static int check_buffer(const struct adc_sequence *sequence, #if defined(CONFIG_ADC_STM32_DMA) && defined(CONFIG_SOC_SERIES_STM32H7X) /* Buffer is forced to be in non-cacheable SRAM region to avoid cache maintenance */ - if (!address_in_non_cacheable_sram(sequence->buffer, needed_buffer_size)) { + if (!buf_in_nocache((uintptr_t)sequence->buffer, needed_buffer_size)) { LOG_ERR("Supplied buffer is not in a non-cacheable region according to DTS."); return -EINVAL; } @@ -305,6 +342,52 @@ static int check_buffer(const struct adc_sequence *sequence, return 0; } +/* + * Enable ADC peripheral, and wait until ready if required by SOC. + */ +static int adc_stm32_enable(ADC_TypeDef *adc) +{ + if (LL_ADC_IsEnabled(adc) == 1UL) { + return 0; + } + +#if !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) && \ + !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_adc) + LL_ADC_ClearFlag_ADRDY(adc); + LL_ADC_Enable(adc); + + /* + * Enabling ADC modules in many series may fail if they are + * still not stabilized, this will wait for a short time (about 1ms) + * to ensure ADC modules are properly enabled. + */ + uint32_t count_timeout = 0; + + while (LL_ADC_IsActiveFlag_ADRDY(adc) == 0) { +#ifdef CONFIG_SOC_SERIES_STM32F0X + /* For F0, continue to write ADEN=1 until ADRDY=1 */ + if (LL_ADC_IsEnabled(adc) == 0UL) { + LL_ADC_Enable(adc); + } +#endif /* CONFIG_SOC_SERIES_STM32F0X */ + count_timeout++; + k_busy_wait(100); + if (count_timeout >= 10) { + return -ETIMEDOUT; + } + } +#else + /* + * On STM32F1, F2, F37x, F4, F7 and L1, do not re-enable the ADC. + * On F1 and F37x if ADON holds 1 (LL_ADC_IsEnabled is true) and 1 is + * written, then conversion starts. That's not what is expected. + */ + LL_ADC_Enable(adc); +#endif + + return 0; +} + static void adc_stm32_start_conversion(const struct device *dev) { const struct adc_stm32_cfg *config = dev->config; @@ -320,6 +403,53 @@ static void adc_stm32_start_conversion(const struct device *dev) #endif } +/* + * Disable ADC peripheral, and wait until it is disabled + */ +static void adc_stm32_disable(ADC_TypeDef *adc) +{ + if (LL_ADC_IsEnabled(adc) != 1UL) { + return; + } + + /* Stop ongoing conversion if any + * Software must poll ADSTART (or JADSTART) until the bit is reset before assuming + * the ADC is completely stopped. + */ + +#if !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) && \ + !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_adc) + if (LL_ADC_REG_IsConversionOngoing(adc)) { + LL_ADC_REG_StopConversion(adc); + while (LL_ADC_REG_IsConversionOngoing(adc)) { + } + } +#endif + +#if !defined(CONFIG_SOC_SERIES_STM32C0X) && \ + !defined(CONFIG_SOC_SERIES_STM32F0X) && \ + !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) && \ + !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_adc) && \ + !defined(CONFIG_SOC_SERIES_STM32G0X) && \ + !defined(CONFIG_SOC_SERIES_STM32L0X) && \ + !defined(CONFIG_SOC_SERIES_STM32WBAX) && \ + !defined(CONFIG_SOC_SERIES_STM32WLX) + if (LL_ADC_INJ_IsConversionOngoing(adc)) { + LL_ADC_INJ_StopConversion(adc); + while (LL_ADC_INJ_IsConversionOngoing(adc)) { + } + } +#endif + + LL_ADC_Disable(adc); + + /* Wait ADC is fully disabled so that we don't leave the driver into intermediate state + * which could prevent enabling the peripheral + */ + while (LL_ADC_IsEnabled(adc) == 1UL) { + } +} + #if !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_adc) #define HAS_CALIBRATION @@ -333,7 +463,7 @@ static void adc_stm32_start_conversion(const struct device *dev) #define ADC_DELAY_CALIB_ADC_CYCLES LL_ADC_DELAY_DISABLE_CALIB_ADC_CYCLES #endif -static void adc_stm32_calib_delay(const struct device *dev) +static void adc_stm32_calibration_delay(const struct device *dev) { /* * Calibration of F1 and F3 (ADC1_V2_5) must start two cycles after ADON @@ -361,7 +491,7 @@ static void adc_stm32_calib_delay(const struct device *dev) } } -static void adc_stm32_calib(const struct device *dev) +static void adc_stm32_calibration_start(const struct device *dev) { const struct adc_stm32_cfg *config = (const struct adc_stm32_cfg *)dev->config; @@ -393,54 +523,60 @@ static void adc_stm32_calib(const struct device *dev) while (LL_ADC_IsCalibrationOnGoing(adc)) { } } -#endif -/* - * Disable ADC peripheral, and wait until it is disabled - */ -static void adc_stm32_disable(ADC_TypeDef *adc) +static int adc_stm32_calibrate(const struct device *dev) { - if (LL_ADC_IsEnabled(adc) != 1UL) { - return; - } - - /* Stop ongoing conversion if any - * Software must poll ADSTART (or JADSTART) until the bit is reset before assuming - * the ADC is completely stopped. - */ + const struct adc_stm32_cfg *config = + (const struct adc_stm32_cfg *)dev->config; + ADC_TypeDef *adc = config->base; + int err; -#if !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) && \ - !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_adc) - if (LL_ADC_REG_IsConversionOngoing(adc)) { - LL_ADC_REG_StopConversion(adc); - while (LL_ADC_REG_IsConversionOngoing(adc)) { - } - } -#endif +#if !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) + adc_stm32_disable(adc); + adc_stm32_calibration_start(dev); + adc_stm32_calibration_delay(dev); +#endif /* !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) */ -#if !defined(CONFIG_SOC_SERIES_STM32C0X) && \ - !defined(CONFIG_SOC_SERIES_STM32F0X) && \ - !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) && \ - !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_adc) && \ - !defined(CONFIG_SOC_SERIES_STM32G0X) && \ - !defined(CONFIG_SOC_SERIES_STM32L0X) && \ - !defined(CONFIG_SOC_SERIES_STM32WBAX) && \ - !defined(CONFIG_SOC_SERIES_STM32WLX) - if (LL_ADC_INJ_IsConversionOngoing(adc)) { - LL_ADC_INJ_StopConversion(adc); - while (LL_ADC_INJ_IsConversionOngoing(adc)) { - } + err = adc_stm32_enable(adc); + if (err < 0) { + return err; } -#endif - LL_ADC_Disable(adc); +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) + adc_stm32_calibration_delay(dev); + adc_stm32_calibration_start(dev); +#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) */ - /* Wait ADC is fully disabled so that we don't leave the driver into intermediate state - * which could prevent enabling the peripheral +#ifdef CONFIG_SOC_SERIES_STM32H7X + /* + * To ensure linearity the factory calibration values + * should be loaded on initialization. */ - while (LL_ADC_IsEnabled(adc) == 1UL) { + uint32_t channel_offset = 0U; + uint32_t linear_calib_buffer = 0U; + + if (adc == ADC1) { + channel_offset = 0UL; + } else if (adc == ADC2) { + channel_offset = 8UL; + } else /*Case ADC3*/ { + channel_offset = 16UL; + } + /* Read factory calibration factors */ + for (uint32_t count = 0UL; count < ADC_LINEAR_CALIB_REG_COUNT; count++) { + linear_calib_buffer = *(uint32_t *)( + ADC_LINEAR_CALIB_REG_1_ADDR + channel_offset + count + ); + LL_ADC_SetCalibrationLinearFactor( + adc, LL_ADC_CALIB_LINEARITY_WORD1 << count, + linear_calib_buffer + ); } +#endif /* CONFIG_SOC_SERIES_STM32H7X */ + + return 0; } +#endif /* !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_adc) */ #if !defined(CONFIG_SOC_SERIES_STM32F0X) && \ !defined(CONFIG_SOC_SERIES_STM32F1X) && \ @@ -573,139 +709,6 @@ static int adc_stm32_oversampling(ADC_TypeDef *adc, uint8_t ratio) } #endif /* CONFIG_SOC_SERIES_STM32xxx */ -/* - * Enable ADC peripheral, and wait until ready if required by SOC. - */ -static int adc_stm32_enable(ADC_TypeDef *adc) -{ - if (LL_ADC_IsEnabled(adc) == 1UL) { - return 0; - } - -#if !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) && \ - !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_adc) - LL_ADC_ClearFlag_ADRDY(adc); - LL_ADC_Enable(adc); - - /* - * Enabling ADC modules in many series may fail if they are - * still not stabilized, this will wait for a short time (about 1ms) - * to ensure ADC modules are properly enabled. - */ - uint32_t count_timeout = 0; - - while (LL_ADC_IsActiveFlag_ADRDY(adc) == 0) { -#ifdef CONFIG_SOC_SERIES_STM32F0X - /* For F0, continue to write ADEN=1 until ADRDY=1 */ - if (LL_ADC_IsEnabled(adc) == 0UL) { - LL_ADC_Enable(adc); - } -#endif /* CONFIG_SOC_SERIES_STM32F0X */ - count_timeout++; - k_busy_wait(100); - if (count_timeout >= 10) { - return -ETIMEDOUT; - } - } -#else - /* - * On STM32F1, F2, F37x, F4, F7 and L1, do not re-enable the ADC. - * On F1 and F37x if ADON holds 1 (LL_ADC_IsEnabled is true) and 1 is - * written, then conversion starts. That's not what is expected. - */ - LL_ADC_Enable(adc); -#endif - - return 0; -} - -/* - * Enable internal channel source - */ -static void adc_stm32_set_common_path(const struct device *dev, uint32_t PathInternal) -{ - const struct adc_stm32_cfg *config = - (const struct adc_stm32_cfg *)dev->config; - ADC_TypeDef *adc = (ADC_TypeDef *)config->base; - - ARG_UNUSED(adc); /* Avoid 'unused variable' warning for some families */ - - /* Do not remove existing paths */ - PathInternal |= LL_ADC_GetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(adc)); - LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(adc), PathInternal); -} - -static void adc_stm32_setup_channel(const struct device *dev, uint8_t channel_id) -{ - const struct adc_stm32_cfg *config = dev->config; - ADC_TypeDef *adc = (ADC_TypeDef *)config->base; - - if (config->temp_channel == channel_id) { - adc_stm32_disable(adc); - adc_stm32_set_common_path(dev, LL_ADC_PATH_INTERNAL_TEMPSENSOR); - k_usleep(LL_ADC_DELAY_TEMPSENSOR_STAB_US); - } - - if (config->vref_channel == channel_id) { - adc_stm32_disable(adc); - adc_stm32_set_common_path(dev, LL_ADC_PATH_INTERNAL_VREFINT); -#ifdef LL_ADC_DELAY_VREFINT_STAB_US - k_usleep(LL_ADC_DELAY_VREFINT_STAB_US); -#endif - } - -#if defined(LL_ADC_CHANNEL_VBAT) - /* Enable the bridge divider only when needed for ADC conversion. */ - if (config->vbat_channel == channel_id) { - adc_stm32_disable(adc); - adc_stm32_set_common_path(dev, LL_ADC_PATH_INTERNAL_VBAT); - } -#endif /* LL_ADC_CHANNEL_VBAT */ -} - -static void adc_stm32_unset_common_path(const struct device *dev, uint32_t PathInternal) -{ - const struct adc_stm32_cfg *config = dev->config; - ADC_TypeDef *adc = (ADC_TypeDef *)config->base; - const uint32_t currentPath = LL_ADC_GetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(adc)); - - ARG_UNUSED(adc); /* Avoid 'unused variable' warning for some families */ - - PathInternal = ~PathInternal & currentPath; - LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(adc), PathInternal); -} - -static void adc_stm32_teardown_channels(const struct device *dev) -{ - const struct adc_stm32_cfg *config = dev->config; - struct adc_stm32_data *data = dev->data; - ADC_TypeDef *adc = (ADC_TypeDef *)config->base; - uint8_t channel_id; - - for (uint32_t channels = data->channels; channels; channels &= ~BIT(channel_id)) { - channel_id = find_lsb_set(channels) - 1; - if (config->temp_channel == channel_id) { - adc_stm32_disable(adc); - adc_stm32_unset_common_path(dev, LL_ADC_PATH_INTERNAL_TEMPSENSOR); - } - - if (config->vref_channel == channel_id) { - adc_stm32_disable(adc); - adc_stm32_unset_common_path(dev, LL_ADC_PATH_INTERNAL_VREFINT); - } - -#if defined(LL_ADC_CHANNEL_VBAT) - /* Enable the bridge divider only when needed for ADC conversion. */ - if (config->vbat_channel == channel_id) { - adc_stm32_disable(adc); - adc_stm32_unset_common_path(dev, LL_ADC_PATH_INTERNAL_VBAT); - } -#endif /* LL_ADC_CHANNEL_VBAT */ - } - - adc_stm32_enable(adc); -} - #ifdef CONFIG_ADC_STM32_DMA static void dma_callback(const struct device *dev, void *user_data, uint32_t channel, int status) @@ -823,6 +826,70 @@ static int set_resolution(const struct device *dev, return 0; } +static int set_sequencer(const struct device *dev) +{ + const struct adc_stm32_cfg *config = dev->config; + struct adc_stm32_data *data = dev->data; + ADC_TypeDef *adc = (ADC_TypeDef *)config->base; + + uint8_t channel_id; + uint8_t channel_index = 0; + uint32_t channels_mask = 0; + + /* Iterate over selected channels in bitmask keeping track of: + * - channel_index: ranging from 0 -> ( data->channel_count - 1 ) + * - channel_id: ordinal position of channel in data->channels bitmask + */ + for (uint32_t channels = data->channels; channels; + channels &= ~BIT(channel_id), channel_index++) { + channel_id = find_lsb_set(channels) - 1; + + uint32_t channel = __LL_ADC_DECIMAL_NB_TO_CHANNEL(channel_id); + + channels_mask |= channel; + +#if ANY_ADC_SEQUENCER_TYPE_IS(FULLY_CONFIGURABLE) + if (config->sequencer_type == FULLY_CONFIGURABLE) { +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32U5X) + /* + * Each channel in the sequence must be previously enabled in PCSEL. + * This register controls the analog switch integrated in the IO level. + */ + LL_ADC_SetChannelPreselection(adc, channel); +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32U5X */ + LL_ADC_REG_SetSequencerRanks(adc, table_rank[channel_index], channel); + LL_ADC_REG_SetSequencerLength(adc, table_seq_len[channel_index]); + } +#endif /* ANY_ADC_SEQUENCER_TYPE_IS(FULLY_CONFIGURABLE) */ + } + +#if ANY_ADC_SEQUENCER_TYPE_IS(NOT_FULLY_CONFIGURABLE) + if (config->sequencer_type == NOT_FULLY_CONFIGURABLE) { + LL_ADC_REG_SetSequencerChannels(adc, channels_mask); + +#if !defined(CONFIG_SOC_SERIES_STM32F0X) && \ + !defined(CONFIG_SOC_SERIES_STM32L0X) && \ + !defined(CONFIG_SOC_SERIES_STM32U5X) && \ + !defined(CONFIG_SOC_SERIES_STM32WBAX) + /* + * After modifying sequencer it is mandatory to wait for the + * assertion of CCRDY flag + */ + while (LL_ADC_IsActiveFlag_CCRDY(adc) == 0) { + } + LL_ADC_ClearFlag_CCRDY(adc); +#endif /* !CONFIG_SOC_SERIES_STM32F0X && !L0X && !U5X && !WBAX */ + } +#endif /* ANY_ADC_SEQUENCER_TYPE_IS(NOT_FULLY_CONFIGURABLE) */ + +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) || \ + DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_adc) + LL_ADC_SetSequencersScanMode(adc, LL_ADC_SEQ_SCAN_ENABLE); +#endif /* st_stm32f1_adc || st_stm32f4_adc */ + + return 0; +} + static int start_read(const struct device *dev, const struct adc_sequence *sequence) { @@ -841,27 +908,20 @@ static int start_read(const struct device *dev, return -EINVAL; } - if (data->channels > BIT(STM32_CHANNEL_COUNT) - 1) { - LOG_ERR("Channels bitmask uses out of range channel"); - return -EINVAL; - } - -#if !defined(CONFIG_SOC_SERIES_STM32C0X) && \ - !defined(CONFIG_SOC_SERIES_STM32F0X) && \ - !defined(CONFIG_SOC_SERIES_STM32G0X) && \ - !defined(CONFIG_SOC_SERIES_STM32L0X) && \ - !defined(CONFIG_SOC_SERIES_STM32WBAX) && \ - !defined(CONFIG_SOC_SERIES_STM32WLX) +#if ANY_ADC_SEQUENCER_TYPE_IS(FULLY_CONFIGURABLE) if (data->channel_count > ARRAY_SIZE(table_seq_len)) { LOG_ERR("Too many channels for sequencer. Max: %d", ARRAY_SIZE(table_seq_len)); return -EINVAL; } -#else +#endif /* ANY_ADC_SEQUENCER_TYPE_IS(FULLY_CONFIGURABLE) */ + +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) && !defined(CONFIG_ADC_STM32_DMA) + /* Multiple samplings is only supported with DMA for F1 */ if (data->channel_count > 1) { - LOG_ERR("This device only supports single channel sampling"); + LOG_ERR("Without DMA, this device only supports single channel sampling"); return -EINVAL; } -#endif +#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) && !CONFIG_ADC_STM32_DMA */ /* Check and set the resolution */ err = set_resolution(dev, sequence); @@ -869,79 +929,10 @@ static int start_read(const struct device *dev, return err; } - uint8_t channel_id; - uint8_t channel_index = 0; - - /* Iterate over selected channels in bitmask keeping track of: - * - channel_index: ranging from 0 -> ( data->channel_count - 1 ) - * - channel_id: ordinal position of channel in data->channels bitmask - */ - for (uint32_t channels = data->channels; channels; - channels &= ~BIT(channel_id), channel_index++) { - channel_id = find_lsb_set(channels) - 1; - - uint32_t channel = __LL_ADC_DECIMAL_NB_TO_CHANNEL(channel_id); - - adc_stm32_setup_channel(dev, channel_id); - -#if defined(CONFIG_SOC_SERIES_STM32H7X) - /* - * Each channel in the sequence must be previously enabled in PCSEL. - * This register controls the analog switch integrated in the IO level. - */ - LL_ADC_SetChannelPreSelection(adc, channel); -#elif defined(CONFIG_SOC_SERIES_STM32U5X) - /* - * Each channel in the sequence must be previously enabled in PCSEL. - * This register controls the analog switch integrated in the IO level. - * Only for ADC1 instance (ADC4 has no Channel preselection capability). - */ - if (adc == ADC1) { - LL_ADC_SetChannelPreselection(adc, channel); - } -#endif - -#if defined(CONFIG_SOC_SERIES_STM32F0X) || \ - defined(CONFIG_SOC_SERIES_STM32L0X) - LL_ADC_REG_SetSequencerChannels(adc, channel); -#elif defined(CONFIG_SOC_SERIES_STM32WLX) - /* Init the the ADC group for REGULAR conversion*/ - LL_ADC_REG_SetSequencerConfigurable(adc, LL_ADC_REG_SEQ_CONFIGURABLE); - LL_ADC_REG_SetTriggerSource(adc, LL_ADC_REG_TRIG_SOFTWARE); - LL_ADC_REG_SetSequencerLength(adc, LL_ADC_REG_SEQ_SCAN_DISABLE); - LL_ADC_REG_SetOverrun(adc, LL_ADC_REG_OVR_DATA_OVERWRITTEN); - LL_ADC_REG_SetSequencerRanks(adc, LL_ADC_REG_RANK_1, channel); - LL_ADC_REG_SetSequencerChannels(adc, channel); - /* Wait for config complete config is ready */ - while (LL_ADC_IsActiveFlag_CCRDY(adc) == 0) { - } - LL_ADC_ClearFlag_CCRDY(adc); -#elif defined(CONFIG_SOC_SERIES_STM32C0X) || defined(CONFIG_SOC_SERIES_STM32G0X) - /* C0 and G0 in "not fully configurable" sequencer mode */ - LL_ADC_REG_SetSequencerChannels(adc, channel); - LL_ADC_REG_SetSequencerConfigurable(adc, LL_ADC_REG_SEQ_FIXED); - while (LL_ADC_IsActiveFlag_CCRDY(adc) == 0) { - } - LL_ADC_ClearFlag_CCRDY(adc); -#elif defined(CONFIG_SOC_SERIES_STM32WBAX) - LL_ADC_REG_StopConversion(adc); - while (LL_ADC_REG_IsStopConversionOngoing(adc) != 0) { - } - LL_ADC_REG_SetSequencerChannels(adc, channel); - LL_ADC_REG_SetSequencerConfigurable(adc, LL_ADC_REG_SEQ_FIXED); -#elif defined(CONFIG_SOC_SERIES_STM32U5X) - if (adc != ADC4) { - LL_ADC_REG_SetSequencerRanks(adc, table_rank[channel_index], channel); - LL_ADC_REG_SetSequencerLength(adc, table_seq_len[channel_index]); - } else { - LL_ADC_REG_SetSequencerConfigurable(adc, LL_ADC_REG_SEQ_FIXED); - LL_ADC_REG_SetSequencerLength(adc, - BIT(__LL_ADC_CHANNEL_TO_DECIMAL_NB(channel))); - } -#else - LL_ADC_REG_SetSequencerRanks(adc, table_rank[channel_index], channel); - LL_ADC_REG_SetSequencerLength(adc, table_seq_len[channel_index]); -#endif + /* Configure the sequencer */ + err = set_sequencer(dev); + if (err < 0) { + return err; } err = check_buffer(sequence, data->channel_count); @@ -962,12 +953,8 @@ static int start_read(const struct device *dev, #endif /* HAS_OVERSAMPLING */ if (sequence->calibrate) { -#if !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) && \ - !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_adc) - - /* we cannot calibrate the ADC while the ADC is enabled */ - adc_stm32_disable(adc); - adc_stm32_calib(dev); +#if defined(HAS_CALIBRATION) + adc_stm32_calibrate(dev); #else LOG_ERR("Calibration not supported"); return -ENOTSUP; @@ -987,6 +974,8 @@ static int start_read(const struct device *dev, #if !defined(CONFIG_ADC_STM32_DMA) #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_adc) + /* Trigger an ISR after each sampling (not just end of sequence) */ + LL_ADC_REG_SetFlagEndOfConversion(adc, LL_ADC_REG_FLAG_EOC_UNITARY_CONV); LL_ADC_EnableIT_EOCS(adc); #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) LL_ADC_EnableIT_EOS(adc); @@ -1040,12 +1029,19 @@ static void adc_stm32_isr(const struct device *dev) (const struct adc_stm32_cfg *)dev->config; ADC_TypeDef *adc = config->base; - *data->buffer++ = LL_ADC_REG_ReadConversionData32(adc); - - /* ISR is triggered after each conversion, and at the end-of-sequence. */ - if (++data->samples_count == data->channel_count) { - data->samples_count = 0; - adc_context_on_sampling_done(&data->ctx, dev); +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) + if (LL_ADC_IsActiveFlag_EOS(adc) == 1) { +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_adc) + if (LL_ADC_IsActiveFlag_EOCS(adc) == 1) { +#else + if (LL_ADC_IsActiveFlag_EOC(adc) == 1) { +#endif + *data->buffer++ = LL_ADC_REG_ReadConversionData32(adc); + /* ISR is triggered after each conversion, and at the end-of-sequence. */ + if (++data->samples_count == data->channel_count) { + data->samples_count = 0; + adc_context_on_sampling_done(&data->ctx, dev); + } } LOG_DBG("%s ISR triggered.", dev->name); @@ -1056,10 +1052,24 @@ static void adc_context_on_complete(struct adc_context *ctx, int status) { struct adc_stm32_data *data = CONTAINER_OF(ctx, struct adc_stm32_data, ctx); + const struct adc_stm32_cfg *config = data->dev->config; + ADC_TypeDef *adc = (ADC_TypeDef *)config->base; ARG_UNUSED(status); - adc_stm32_teardown_channels(data->dev); + adc_stm32_disable(adc); + + /* Reset acquisition time used for the sequence */ + data->acq_time_index = -1; + + /* Reset internal channels */ + LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(adc), + LL_ADC_PATH_INTERNAL_NONE); + +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32U5X) + /* Reset channel preselection register */ + LL_ADC_SetChannelPreselection(adc, 0); +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32U5X */ } static int adc_stm32_read(const struct device *dev, @@ -1168,11 +1178,6 @@ static int adc_stm32_channel_setup(const struct device *dev, struct adc_stm32_data *data = dev->data; int acq_time_index; - if (channel_cfg->channel_id >= STM32_CHANNEL_COUNT) { - LOG_ERR("Channel %d is not valid", channel_cfg->channel_id); - return -EINVAL; - } - acq_time_index = adc_stm32_check_acq_time(dev, channel_cfg->acquisition_time); if (acq_time_index < 0) { @@ -1187,6 +1192,7 @@ static int adc_stm32_channel_setup(const struct device *dev, * identical acquisition time. */ if (acq_time_index != data->acq_time_index) { + LOG_ERR("Multiple sampling times not supported"); return -EINVAL; } } @@ -1280,6 +1286,8 @@ static int adc_stm32_init(const struct device *dev) ADC_TypeDef *adc = (ADC_TypeDef *)config->base; int err; + ARG_UNUSED(adc); /* Necessary to avoid warnings on some series */ + LOG_DBG("Initializing %s", dev->name); if (!device_is_ready(clk)) { @@ -1308,6 +1316,7 @@ static int adc_stm32_init(const struct device *dev) LOG_ERR("ADC pinctrl setup failed (%d)", err); return err; } + #if defined(CONFIG_SOC_SERIES_STM32U5X) /* Enable the independent analog supply */ LL_PWR_EnableVDDA(); @@ -1333,12 +1342,9 @@ static int adc_stm32_init(const struct device *dev) * mode, and restore its calibration parameters if there are some * previously stored calibration parameters. */ - LL_ADC_DisableDeepPowerDown(adc); -#elif defined(CONFIG_SOC_SERIES_STM32WLX) - /* The ADC clock must be disabled by clock gating during CPU1 sleep/stop */ - LL_APB2_GRP1_DisableClockSleep(LL_APB2_GRP1_PERIPH_ADC); #endif + /* * Many ADC modules need some time to be stabilized before performing * any enable or calibration actions. @@ -1350,56 +1356,96 @@ static int adc_stm32_init(const struct device *dev) k_busy_wait(LL_ADC_DELAY_INTERNAL_REGUL_STAB_US); #endif -#if defined(HAS_CALIBRATION) && !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) - adc_stm32_disable(adc); - adc_stm32_calib(dev); - adc_stm32_calib_delay(dev); -#endif /* HAS_CALIBRATION && !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) */ + config->irq_cfg_func(); - err = adc_stm32_enable(adc); - if (err < 0) { - return err; - } +#if defined(HAS_CALIBRATION) + adc_stm32_calibrate(dev); +#endif /* HAS_CALIBRATION */ - config->irq_cfg_func(); + adc_context_unlock_unconditionally(&data->ctx); -#if defined(HAS_CALIBRATION) && DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) - adc_stm32_calib_delay(dev); - adc_stm32_calib(dev); - LL_ADC_REG_SetTriggerSource(adc, LL_ADC_REG_TRIG_SOFTWARE); -#endif /* HAS_CALIBRATION && DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) */ + return 0; +} -#ifdef CONFIG_SOC_SERIES_STM32H7X +#ifdef CONFIG_PM_DEVICE +static int adc_stm32_suspend_setup(const struct device *dev) +{ + const struct adc_stm32_cfg *config = dev->config; + ADC_TypeDef *adc = (ADC_TypeDef *)config->base; + const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); + int err; + + /* Disable ADC */ + adc_stm32_disable(adc); + +#if !defined(CONFIG_SOC_SERIES_STM32F0X) && \ + !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) && \ + !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_adc) + /* Disable ADC internal voltage regulator */ + LL_ADC_DisableInternalRegulator(adc); + while (LL_ADC_IsInternalRegulatorEnabled(adc) == 1U) { + } +#endif + +#if defined(CONFIG_SOC_SERIES_STM32L4X) || \ + defined(CONFIG_SOC_SERIES_STM32L5X) || \ + defined(CONFIG_SOC_SERIES_STM32WBX) || \ + defined(CONFIG_SOC_SERIES_STM32G4X) || \ + defined(CONFIG_SOC_SERIES_STM32H5X) || \ + defined(CONFIG_SOC_SERIES_STM32H7X) || \ + defined(CONFIG_SOC_SERIES_STM32U5X) /* - * To ensure linearity the factory calibration values - * should be loaded on initialization. + * L4, WB, G4, H5, H7 and U5 series STM32 needs to be put into + * deep sleep mode. */ - uint32_t channel_offset = 0U; - uint32_t linear_calib_buffer = 0U; - if (adc == ADC1) { - channel_offset = 0UL; - } else if (adc == ADC2) { - channel_offset = 8UL; - } else /*Case ADC3*/ { - channel_offset = 16UL; + LL_ADC_EnableDeepPowerDown(adc); +#endif + +#if defined(CONFIG_SOC_SERIES_STM32U5X) + /* Disable the independent analog supply */ + LL_PWR_DisableVDDA(); +#endif /* CONFIG_SOC_SERIES_STM32U5X */ + + /* Stop device clock. Note: fixed clocks are not handled yet. */ + err = clock_control_off(clk, (clock_control_subsys_t)&config->pclken[0]); + if (err != 0) { + LOG_ERR("Could not disable ADC clock"); + return err; } - /* Read factory calibration factors */ - for (uint32_t count = 0UL; count < ADC_LINEAR_CALIB_REG_COUNT; count++) { - linear_calib_buffer = *(uint32_t *)( - ADC_LINEAR_CALIB_REG_1_ADDR + channel_offset + count - ); - LL_ADC_SetCalibrationLinearFactor( - adc, LL_ADC_CALIB_LINEARITY_WORD1 << count, - linear_calib_buffer - ); + + /* Move pins to sleep state */ + err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); + if ((err < 0) && (err != -ENOENT)) { + /* + * If returning -ENOENT, no pins where defined for sleep mode : + * Do not output on console (might sleep already) when going to sleep, + * "ADC pinctrl sleep state not available" + * and don't block PM suspend. + * Else return the error. + */ + return err; } -#endif - adc_context_unlock_unconditionally(&data->ctx); return 0; } +static int adc_stm32_pm_action(const struct device *dev, + enum pm_device_action action) +{ + switch (action) { + case PM_DEVICE_ACTION_RESUME: + return adc_stm32_init(dev); + case PM_DEVICE_ACTION_SUSPEND: + return adc_stm32_suspend_setup(dev); + default: + return -ENOTSUP; + } + + return 0; +} +#endif /* CONFIG_PM_DEVICE */ + static const struct adc_driver_api api_stm32_driver_api = { .channel_setup = adc_stm32_channel_setup, .read = adc_stm32_read, @@ -1547,9 +1593,7 @@ static const struct adc_stm32_cfg adc_stm32_cfg_##index = { \ .pclk_len = DT_INST_NUM_CLOCKS(index), \ .clk_prescaler = ADC_STM32_DT_PRESC(index), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(index), \ - .temp_channel = DT_INST_PROP_OR(index, temp_channel, 0xFF), \ - .vref_channel = DT_INST_PROP_OR(index, vref_channel, 0xFF), \ - .vbat_channel = DT_INST_PROP_OR(index, vbat_channel, 0xFF), \ + .sequencer_type = DT_INST_PROP(index, st_adc_sequencer), \ .sampling_time_table = DT_INST_PROP(index, sampling_times), \ .num_sampling_time_common_channels = \ DT_INST_PROP_OR(index, num_sampling_time_common_channels, 0),\ @@ -1564,8 +1608,10 @@ static struct adc_stm32_data adc_stm32_data_##index = { \ ADC_DMA_CHANNEL(index, dmamux, NULL, PERIPHERAL, MEMORY) \ }; \ \ +PM_DEVICE_DT_INST_DEFINE(index, adc_stm32_pm_action); \ + \ DEVICE_DT_INST_DEFINE(index, \ - &adc_stm32_init, NULL, \ + &adc_stm32_init, PM_DEVICE_DT_INST_GET(index), \ &adc_stm32_data_##index, &adc_stm32_cfg_##index, \ POST_KERNEL, CONFIG_ADC_INIT_PRIORITY, \ &api_stm32_driver_api); diff --git a/drivers/audio/CMakeLists.txt b/drivers/audio/CMakeLists.txt index 73cda8192ac..98544d6218c 100644 --- a/drivers/audio/CMakeLists.txt +++ b/drivers/audio/CMakeLists.txt @@ -6,3 +6,5 @@ zephyr_library_sources_ifdef(CONFIG_AUDIO_TLV320DAC tlv320dac310x.c) zephyr_library_sources_ifdef(CONFIG_AUDIO_MPXXDTYY mpxxdtyy.c) zephyr_library_sources_ifdef(CONFIG_AUDIO_MPXXDTYY mpxxdtyy-i2s.c) zephyr_library_sources_ifdef(CONFIG_AUDIO_DMIC_NRFX_PDM dmic_nrfx_pdm.c) +zephyr_library_sources_ifdef(CONFIG_AUDIO_TAS6422DAC tas6422dac.c) +zephyr_library_sources_ifdef(CONFIG_AUDIO_CODEC_SHELL codec_shell.c) diff --git a/drivers/audio/Kconfig b/drivers/audio/Kconfig index 2eb98256aac..a9d11331676 100644 --- a/drivers/audio/Kconfig +++ b/drivers/audio/Kconfig @@ -25,10 +25,17 @@ config AUDIO_CODEC_INIT_PRIORITY help Audio codec device driver initialization priority. +config AUDIO_CODEC_SHELL + bool "Audio Codec shell" + depends on SHELL + help + Enable the Audio Codec shell with Audio Codec related commands. + module = AUDIO_CODEC module-str = audio codec source "subsys/logging/Kconfig.template.log_config" +source "drivers/audio/Kconfig.tas6422dac" source "drivers/audio/Kconfig.tlv320dac" endif # AUDIO_CODEC diff --git a/drivers/audio/Kconfig.dmic_pdm_nrfx b/drivers/audio/Kconfig.dmic_pdm_nrfx index 729c1cfa92e..9f45144effa 100644 --- a/drivers/audio/Kconfig.dmic_pdm_nrfx +++ b/drivers/audio/Kconfig.dmic_pdm_nrfx @@ -6,5 +6,6 @@ config AUDIO_DMIC_NRFX_PDM default y depends on DT_HAS_NORDIC_NRF_PDM_ENABLED select NRFX_PDM + select PINCTRL help Enable support for nrfx PDM driver for nRF MCU series. diff --git a/drivers/audio/Kconfig.tas6422dac b/drivers/audio/Kconfig.tas6422dac new file mode 100644 index 00000000000..1977e7b6331 --- /dev/null +++ b/drivers/audio/Kconfig.tas6422dac @@ -0,0 +1,11 @@ +# Copyright (c) 2023 Centralp +# SPDX-License-Identifier: Apache-2.0 + +config AUDIO_TAS6422DAC + bool "TAS6422 audio amplifier support" + default y + depends on DT_HAS_TI_TAS6422DAC_ENABLED + select I2C + depends on GPIO + help + Enable TAS6422 support on the selected board diff --git a/drivers/audio/codec_shell.c b/drivers/audio/codec_shell.c new file mode 100644 index 00000000000..6fb47d11184 --- /dev/null +++ b/drivers/audio/codec_shell.c @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2023 Centralp + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#define CODEC_START_HELP \ + "Start output audio playback. Syntax:\n" \ + "" + +#define CODEC_STOP_HELP \ + "Stop output audio playback. Syntax:\n" \ + "" + +#define CODEC_SET_PROP_HELP \ + "Set a codec property. Syntax:\n" \ + " " + +#define CODEC_APPLY_PROP_HELP \ + "Apply any cached properties. Syntax:\n" \ + "" + +static const char *const codec_property_name[] = { + [AUDIO_PROPERTY_OUTPUT_VOLUME] = "volume", + [AUDIO_PROPERTY_OUTPUT_MUTE] = "mute", +}; + +static const char *const codec_channel_name[] = { + [AUDIO_CHANNEL_FRONT_LEFT] = "front_left", + [AUDIO_CHANNEL_FRONT_RIGHT] = "front_right", + [AUDIO_CHANNEL_LFE] = "lfe", + [AUDIO_CHANNEL_FRONT_CENTER] = "front_center", + [AUDIO_CHANNEL_REAR_LEFT] = "rear_left", + [AUDIO_CHANNEL_REAR_RIGHT] = "rear_right", + [AUDIO_CHANNEL_REAR_CENTER] = "rear_center", + [AUDIO_CHANNEL_SIDE_LEFT] = "side_left", + [AUDIO_CHANNEL_SIDE_RIGHT] = "side_right", + [AUDIO_CHANNEL_ALL] = "all", +}; + +struct args_index { + uint8_t device; + uint8_t property; + uint8_t channel; + uint8_t value; +}; + +static const struct args_index args_indx = { + .device = 1, + .property = 2, + .channel = 3, + .value = 4, +}; + +static int parse_named_int(const char *name, const char *keystack[], size_t count) +{ + char *endptr; + int i; + + /* Attempt to parse name as a number first */ + i = strtoul(name, &endptr, 0); + if (*endptr == '\0') { + return i; + } + + /* Name is not a number, look it up */ + for (i = 0; i < count; i++) { + if (strcmp(name, keystack[i]) == 0) { + return i; + } + } + + return -ENOTSUP; +} + +static int cmd_start(const struct shell *sh, size_t argc, char *argv[]) +{ + const struct device *dev; + + dev = device_get_binding(argv[args_indx.device]); + if (!dev) { + shell_error(sh, "Audio Codec device not found"); + return -ENODEV; + } + audio_codec_start_output(dev); + + return 0; +} + +static int cmd_stop(const struct shell *sh, size_t argc, char *argv[]) +{ + const struct device *dev; + + dev = device_get_binding(argv[args_indx.device]); + if (!dev) { + shell_error(sh, "Audio Codec device not found"); + return -ENODEV; + } + audio_codec_stop_output(dev); + + return 0; +} + +static int cmd_set_prop(const struct shell *sh, size_t argc, char *argv[]) +{ + const struct device *dev; + int property; + int channel; + long value; + char *endptr; + audio_property_value_t property_value; + + dev = device_get_binding(argv[args_indx.device]); + if (!dev) { + shell_error(sh, "Audio Codec device not found"); + return -ENODEV; + } + + property = parse_named_int(argv[args_indx.property], codec_property_name, + ARRAY_SIZE(codec_property_name)); + if (property < 0) { + shell_error(sh, "Property '%s' unknown", argv[args_indx.property]); + return -EINVAL; + } + + channel = parse_named_int(argv[args_indx.channel], codec_channel_name, + ARRAY_SIZE(codec_channel_name)); + if (channel < 0) { + shell_error(sh, "Channel '%s' unknown", argv[args_indx.channel]); + return -EINVAL; + } + + value = strtol(argv[args_indx.value], &endptr, 0); + if (*endptr != '\0') { + return -EINVAL; + } + if (value > INT32_MAX || value < INT32_MIN) { + return -EINVAL; + } + switch (property) { + case AUDIO_PROPERTY_OUTPUT_VOLUME: + property_value.vol = value; + break; + case AUDIO_PROPERTY_OUTPUT_MUTE: + property_value.mute = value; + break; + default: + return -EINVAL; + } + + return audio_codec_set_property(dev, property, channel, property_value); +} + +static int cmd_apply_prop(const struct shell *sh, size_t argc, char *argv[]) +{ + const struct device *dev; + + dev = device_get_binding(argv[args_indx.device]); + if (!dev) { + shell_error(sh, "Audio Codec device not found"); + return -ENODEV; + } + + return audio_codec_apply_properties(dev); +} + +/* Device name autocompletion support */ +static void device_name_get(size_t idx, struct shell_static_entry *entry) +{ + const struct device *dev = shell_device_lookup(idx, NULL); + + entry->syntax = (dev != NULL) ? dev->name : NULL; + entry->handler = NULL; + entry->help = NULL; + entry->subcmd = NULL; +} + +SHELL_DYNAMIC_CMD_CREATE(dsub_device_name, device_name_get); + +/* clang-format off */ +SHELL_STATIC_SUBCMD_SET_CREATE(sub_codec, + SHELL_CMD_ARG(start, &dsub_device_name, CODEC_START_HELP, cmd_start, + 2, 0), + SHELL_CMD_ARG(stop, &dsub_device_name, CODEC_STOP_HELP, cmd_stop, + 2, 0), + SHELL_CMD_ARG(set_prop, &dsub_device_name, CODEC_SET_PROP_HELP, cmd_set_prop, + 5, 0), + SHELL_CMD_ARG(apply_prop, &dsub_device_name, CODEC_APPLY_PROP_HELP, cmd_apply_prop, + 2, 0), + SHELL_SUBCMD_SET_END +); +/* clang-format on */ + +SHELL_CMD_REGISTER(codec, &sub_codec, "Audio Codec commands", NULL); diff --git a/drivers/audio/tas6422dac.c b/drivers/audio/tas6422dac.c new file mode 100644 index 00000000000..91c36de2897 --- /dev/null +++ b/drivers/audio/tas6422dac.c @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2023 Centralp + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ti_tas6422dac + +#include +#include +#include +#include + +#include "tas6422dac.h" + +#define LOG_LEVEL CONFIG_AUDIO_CODEC_LOG_LEVEL +#include +LOG_MODULE_REGISTER(tas6422dac); + +#define TAS6422DAC_MUTE_GPIO_SUPPORT DT_ANY_INST_HAS_PROP_STATUS_OKAY(mute_gpios) + +#define CODEC_OUTPUT_VOLUME_MAX (24 * 2) +#define CODEC_OUTPUT_VOLUME_MIN (-100 * 2) + +struct codec_driver_config { + struct i2c_dt_spec bus; +#if TAS6422DAC_MUTE_GPIO_SUPPORT + struct gpio_dt_spec mute_gpio; +#endif /* TAS6422DAC_MUTE_GPIO_SUPPORT */ +}; + +struct codec_driver_data { +}; + +enum tas6422dac_channel_t { + TAS6422DAC_CHANNEL_1, + TAS6422DAC_CHANNEL_2, + TAS6422DAC_CHANNEL_ALL, + TAS6422DAC_CHANNEL_UNKNOWN, +}; + +static enum tas6422dac_channel_t audio_to_tas6422dac_channel[] = { + [AUDIO_CHANNEL_FRONT_LEFT] = TAS6422DAC_CHANNEL_1, + [AUDIO_CHANNEL_FRONT_RIGHT] = TAS6422DAC_CHANNEL_2, + [AUDIO_CHANNEL_LFE] = TAS6422DAC_CHANNEL_UNKNOWN, + [AUDIO_CHANNEL_FRONT_CENTER] = TAS6422DAC_CHANNEL_UNKNOWN, + [AUDIO_CHANNEL_REAR_LEFT] = TAS6422DAC_CHANNEL_1, + [AUDIO_CHANNEL_REAR_RIGHT] = TAS6422DAC_CHANNEL_2, + [AUDIO_CHANNEL_REAR_CENTER] = TAS6422DAC_CHANNEL_UNKNOWN, + [AUDIO_CHANNEL_SIDE_LEFT] = TAS6422DAC_CHANNEL_1, + [AUDIO_CHANNEL_SIDE_RIGHT] = TAS6422DAC_CHANNEL_2, + [AUDIO_CHANNEL_ALL] = TAS6422DAC_CHANNEL_ALL, +}; + +static void codec_mute_output(const struct device *dev, enum tas6422dac_channel_t channel); +static void codec_unmute_output(const struct device *dev, enum tas6422dac_channel_t channel); +static void codec_write_reg(const struct device *dev, uint8_t reg, uint8_t val); +static void codec_read_reg(const struct device *dev, uint8_t reg, uint8_t *val); +static void codec_soft_reset(const struct device *dev); +static int codec_configure_dai(const struct device *dev, audio_dai_cfg_t *cfg); +static void codec_configure_output(const struct device *dev); +static int codec_set_output_volume(const struct device *dev, enum tas6422dac_channel_t channel, + int vol); + +#if (LOG_LEVEL >= LOG_LEVEL_DEBUG) +static void codec_read_all_regs(const struct device *dev); +#define CODEC_DUMP_REGS(dev) codec_read_all_regs((dev)) +#else +#define CODEC_DUMP_REGS(dev) +#endif + +static int codec_initialize(const struct device *dev) +{ + const struct codec_driver_config *const dev_cfg = dev->config; + + if (!device_is_ready(dev_cfg->bus.bus)) { + LOG_ERR("I2C device not ready"); + return -ENODEV; + } + +#if TAS6422DAC_MUTE_GPIO_SUPPORT + if (!device_is_ready(dev_cfg->mute_gpio.port)) { + LOG_ERR("GPIO device not ready"); + return -ENODEV; + } +#endif /* TAS6422DAC_MUTE_GPIO_SUPPORT */ + + return 0; +} + +static int codec_configure(const struct device *dev, struct audio_codec_cfg *cfg) +{ + int ret; + + if (cfg->dai_type != AUDIO_DAI_TYPE_I2S) { + LOG_ERR("dai_type must be AUDIO_DAI_TYPE_I2S"); + return -EINVAL; + } + + codec_soft_reset(dev); + ret = codec_configure_dai(dev, &cfg->dai_cfg); + codec_configure_output(dev); + + return ret; +} + +static void codec_start_output(const struct device *dev) +{ + codec_unmute_output(dev, TAS6422DAC_CHANNEL_ALL); + + CODEC_DUMP_REGS(dev); +} + +static void codec_stop_output(const struct device *dev) +{ + codec_mute_output(dev, TAS6422DAC_CHANNEL_ALL); +} + +static void codec_mute_output(const struct device *dev, enum tas6422dac_channel_t channel) +{ + uint8_t val; + +#if TAS6422DAC_MUTE_GPIO_SUPPORT + const struct codec_driver_config *const dev_cfg = dev->config; + + gpio_pin_configure_dt(&dev_cfg->mute_gpio, GPIO_OUTPUT_ACTIVE); +#endif + + codec_read_reg(dev, CH_STATE_CTRL_ADDR, &val); + switch (channel) { + case TAS6422DAC_CHANNEL_1: + val &= ~CH_STATE_CTRL_CH1_STATE_CTRL_MASK; + val |= CH_STATE_CTRL_CH1_STATE_CTRL(CH_STATE_CTRL_MUTE); + break; + case TAS6422DAC_CHANNEL_2: + val &= ~CH_STATE_CTRL_CH2_STATE_CTRL_MASK; + val |= CH_STATE_CTRL_CH2_STATE_CTRL(CH_STATE_CTRL_MUTE); + break; + case TAS6422DAC_CHANNEL_ALL: + val &= ~(CH_STATE_CTRL_CH1_STATE_CTRL_MASK | CH_STATE_CTRL_CH2_STATE_CTRL_MASK); + val |= CH_STATE_CTRL_CH1_STATE_CTRL(CH_STATE_CTRL_MUTE) | + CH_STATE_CTRL_CH2_STATE_CTRL(CH_STATE_CTRL_MUTE); + break; + case TAS6422DAC_CHANNEL_UNKNOWN: + default: + LOG_ERR("Invalid codec channel %u", channel); + return; + } + codec_write_reg(dev, CH_STATE_CTRL_ADDR, val); +} + +static void codec_unmute_output(const struct device *dev, enum tas6422dac_channel_t channel) +{ + uint8_t val; + +#if TAS6422DAC_MUTE_GPIO_SUPPORT + const struct codec_driver_config *const dev_cfg = dev->config; + + gpio_pin_configure_dt(&dev_cfg->mute_gpio, GPIO_OUTPUT_INACTIVE); +#endif + + codec_read_reg(dev, CH_STATE_CTRL_ADDR, &val); + switch (channel) { + case TAS6422DAC_CHANNEL_1: + val &= ~CH_STATE_CTRL_CH1_STATE_CTRL_MASK; + val |= CH_STATE_CTRL_CH1_STATE_CTRL(CH_STATE_CTRL_PLAY); + break; + case TAS6422DAC_CHANNEL_2: + val &= ~CH_STATE_CTRL_CH2_STATE_CTRL_MASK; + val |= CH_STATE_CTRL_CH2_STATE_CTRL(CH_STATE_CTRL_PLAY); + break; + case TAS6422DAC_CHANNEL_ALL: + val &= ~(CH_STATE_CTRL_CH1_STATE_CTRL_MASK | CH_STATE_CTRL_CH2_STATE_CTRL_MASK); + val |= CH_STATE_CTRL_CH1_STATE_CTRL(CH_STATE_CTRL_PLAY) | + CH_STATE_CTRL_CH2_STATE_CTRL(CH_STATE_CTRL_PLAY); + break; + case TAS6422DAC_CHANNEL_UNKNOWN: + default: + LOG_ERR("Invalid codec channel %u", channel); + return; + } + codec_write_reg(dev, CH_STATE_CTRL_ADDR, val); +} + +static int codec_set_property(const struct device *dev, audio_property_t property, + audio_channel_t channel, audio_property_value_t val) +{ + enum tas6422dac_channel_t codec_channel = audio_to_tas6422dac_channel[channel]; + + if (codec_channel == TAS6422DAC_CHANNEL_UNKNOWN) { + LOG_ERR("Invalid channel %u", channel); + return -EINVAL; + } + + switch (property) { + case AUDIO_PROPERTY_OUTPUT_VOLUME: + return codec_set_output_volume(dev, codec_channel, val.vol); + + case AUDIO_PROPERTY_OUTPUT_MUTE: + if (val.mute) { + codec_mute_output(dev, codec_channel); + } else { + codec_unmute_output(dev, codec_channel); + } + return 0; + + default: + break; + } + + return -EINVAL; +} + +static int codec_apply_properties(const struct device *dev) +{ + /* nothing to do because there is nothing cached */ + return 0; +} + +static void codec_write_reg(const struct device *dev, uint8_t reg, uint8_t val) +{ + const struct codec_driver_config *const dev_cfg = dev->config; + + i2c_reg_write_byte_dt(&dev_cfg->bus, reg, val); + LOG_DBG("%s WR REG:0x%02x VAL:0x%02x", dev->name, reg, val); +} + +static void codec_read_reg(const struct device *dev, uint8_t reg, uint8_t *val) +{ + const struct codec_driver_config *const dev_cfg = dev->config; + + i2c_reg_read_byte_dt(&dev_cfg->bus, reg, val); + LOG_DBG("%s RD REG:0x%02x VAL:0x%02x", dev->name, reg, *val); +} + +static void codec_soft_reset(const struct device *dev) +{ + uint8_t val; + + codec_read_reg(dev, MODE_CTRL_ADDR, &val); + val |= MODE_CTRL_RESET; + codec_write_reg(dev, MODE_CTRL_ADDR, val); +} + +static int codec_configure_dai(const struct device *dev, audio_dai_cfg_t *cfg) +{ + uint8_t val; + + codec_read_reg(dev, SAP_CTRL_ADDR, &val); + + /* I2S mode */ + val &= ~SAP_CTRL_INPUT_FORMAT_MASK; + val |= SAP_CTRL_INPUT_FORMAT(SAP_CTRL_INPUT_FORMAT_I2S); + + /* Input sampling rate */ + val &= ~SAP_CTRL_INPUT_SAMPLING_RATE_MASK; + switch (cfg->i2s.frame_clk_freq) { + case AUDIO_PCM_RATE_44P1K: + val |= SAP_CTRL_INPUT_SAMPLING_RATE(SAP_CTRL_INPUT_SAMPLING_RATE_44_1_KHZ); + break; + case AUDIO_PCM_RATE_48K: + val |= SAP_CTRL_INPUT_SAMPLING_RATE(SAP_CTRL_INPUT_SAMPLING_RATE_48_KHZ); + break; + case AUDIO_PCM_RATE_96K: + val |= SAP_CTRL_INPUT_SAMPLING_RATE(SAP_CTRL_INPUT_SAMPLING_RATE_96_KHZ); + break; + default: + LOG_ERR("Invalid sampling rate %zu", cfg->i2s.frame_clk_freq); + return -EINVAL; + } + + codec_write_reg(dev, SAP_CTRL_ADDR, val); + + return 0; +} + +static void codec_configure_output(const struct device *dev) +{ + uint8_t val; + + /* Overcurrent level = 1 */ + codec_read_reg(dev, MISC_CTRL_1_ADDR, &val); + val &= ~MISC_CTRL_1_OC_CONTROL_MASK; + codec_write_reg(dev, MISC_CTRL_1_ADDR, val); + + /* + * PWM frequency = 10 fs + * Reduce PWM frequency to prevent component overtemperature + */ + codec_read_reg(dev, MISC_CTRL_2_ADDR, &val); + val &= ~MISC_CTRL_2_PWM_FREQUENCY_MASK; + val |= MISC_CTRL_2_PWM_FREQUENCY(MISC_CTRL_2_PWM_FREQUENCY_10_FS); + codec_write_reg(dev, MISC_CTRL_2_ADDR, val); +} + +static int codec_set_output_volume(const struct device *dev, enum tas6422dac_channel_t channel, + int vol) +{ + uint8_t vol_val; + + if ((vol > CODEC_OUTPUT_VOLUME_MAX) || (vol < CODEC_OUTPUT_VOLUME_MIN)) { + LOG_ERR("Invalid volume %d.%d dB", vol >> 1, ((uint32_t)vol & 1) ? 5 : 0); + return -EINVAL; + } + + vol_val = vol + 0xcf; + switch (channel) { + case TAS6422DAC_CHANNEL_1: + codec_write_reg(dev, CH1_VOLUME_CTRL_ADDR, CH_VOLUME_CTRL_VOLUME(vol_val)); + break; + case TAS6422DAC_CHANNEL_2: + codec_write_reg(dev, CH2_VOLUME_CTRL_ADDR, CH_VOLUME_CTRL_VOLUME(vol_val)); + break; + case TAS6422DAC_CHANNEL_ALL: + codec_write_reg(dev, CH1_VOLUME_CTRL_ADDR, CH_VOLUME_CTRL_VOLUME(vol_val)); + codec_write_reg(dev, CH2_VOLUME_CTRL_ADDR, CH_VOLUME_CTRL_VOLUME(vol_val)); + break; + case TAS6422DAC_CHANNEL_UNKNOWN: + default: + LOG_ERR("Invalid codec channel %u", channel); + return -EINVAL; + } + + return 0; +} + +#if (LOG_LEVEL >= LOG_LEVEL_DEBUG) +static void codec_read_all_regs(const struct device *dev) +{ + uint8_t val; + + codec_read_reg(dev, MODE_CTRL_ADDR, &val); + codec_read_reg(dev, MISC_CTRL_1_ADDR, &val); + codec_read_reg(dev, MISC_CTRL_2_ADDR, &val); + codec_read_reg(dev, SAP_CTRL_ADDR, &val); + codec_read_reg(dev, CH_STATE_CTRL_ADDR, &val); + codec_read_reg(dev, CH1_VOLUME_CTRL_ADDR, &val); + codec_read_reg(dev, CH2_VOLUME_CTRL_ADDR, &val); + codec_read_reg(dev, DC_LDG_CTRL_1_ADDR, &val); + codec_read_reg(dev, DC_LDG_CTRL_2_ADDR, &val); + codec_read_reg(dev, DC_LDG_REPORT_1_ADDR, &val); + codec_read_reg(dev, DC_LDG_REPORT_3_ADDR, &val); + codec_read_reg(dev, CH_FAULTS_ADDR, &val); + codec_read_reg(dev, GLOBAL_FAULTS_1_ADDR, &val); + codec_read_reg(dev, GLOBAL_FAULTS_2_ADDR, &val); + codec_read_reg(dev, WARNINGS_ADDR, &val); + codec_read_reg(dev, PIN_CTRL_ADDR, &val); + codec_read_reg(dev, MISC_CTRL_3_ADDR, &val); + codec_read_reg(dev, ILIMIT_STATUS_ADDR, &val); + codec_read_reg(dev, MISC_CTRL_4_ADDR, &val); + codec_read_reg(dev, MISC_CTRL_5_ADDR, &val); +} +#endif + +static const struct audio_codec_api codec_driver_api = { + .configure = codec_configure, + .start_output = codec_start_output, + .stop_output = codec_stop_output, + .set_property = codec_set_property, + .apply_properties = codec_apply_properties, +}; + +#if TAS6422DAC_MUTE_GPIO_SUPPORT +#define TAS6422DAC_MUTE_GPIO_INIT(n) .mute_gpio = GPIO_DT_SPEC_INST_GET(n, mute_gpios) +#else +#define TAS6422DAC_MUTE_GPIO_INIT(n) +#endif /* TAS6422DAC_MUTE_GPIO_SUPPORT */ + +#define TAS6422DAC_INIT(n) \ + static struct codec_driver_data codec_device_data_##n; \ + \ + static struct codec_driver_config codec_device_config_##n = { \ + .bus = I2C_DT_SPEC_INST_GET(n), TAS6422DAC_MUTE_GPIO_INIT(n)}; \ + \ + DEVICE_DT_INST_DEFINE(n, codec_initialize, NULL, &codec_device_data_##n, \ + &codec_device_config_##n, POST_KERNEL, \ + CONFIG_AUDIO_CODEC_INIT_PRIORITY, &codec_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(TAS6422DAC_INIT) diff --git a/drivers/audio/tas6422dac.h b/drivers/audio/tas6422dac.h new file mode 100644 index 00000000000..84ec0872636 --- /dev/null +++ b/drivers/audio/tas6422dac.h @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2023 Centralp + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_AUDIO_TAS6422DAC_H_ +#define ZEPHYR_DRIVERS_AUDIO_TAS6422DAC_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Mode Control Register */ +#define MODE_CTRL_ADDR 0x00 +#define MODE_CTRL_RESET BIT(7) +#define MODE_CTRL_RESET_MASK BIT(7) +#define MODE_CTRL_PBTL_CH12 BIT(4) +#define MODE_CTRL_PBTL_CH12_MASK BIT(4) +#define MODE_CTRL_CH1_LO_MODE BIT(3) +#define MODE_CTRL_CH1_LO_MODE_MASK BIT(3) +#define MODE_CTRL_CH2_LO_MODE BIT(2) +#define MODE_CTRL_CH2_LO_MODE_MASK BIT(2) + +/* Miscellaneous Control 1 Register */ +#define MISC_CTRL_1_ADDR 0x01 +#define MISC_CTRL_1_HPF_BYPASS BIT(7) +#define MISC_CTRL_1_HPF_BYPASS_MASK BIT(7) +#define MISC_CTRL_1_OTW_CONTROL_MASK (BIT_MASK(2) << 5) +#define MISC_CTRL_1_OTW_CONTROL(val) (((val) << 5) & MISC_CTRL_1_OTW_CONTROL_MASK) +#define MISC_CTRL_1_OTW_CONTROL_140_DEGREE 0 +#define MISC_CTRL_1_OTW_CONTROL_130_DEGREE 1 +#define MISC_CTRL_1_OTW_CONTROL_120_DEGREE 2 +#define MISC_CTRL_1_OTW_CONTROL_110_DEGREE 3 +#define MISC_CTRL_1_OC_CONTROL BIT(4) +#define MISC_CTRL_1_OC_CONTROL_MASK BIT(4) +#define MISC_CTRL_1_VOLUME_RATE_MASK (BIT_MASK(2) << 2) +#define MISC_CTRL_1_VOLUME_RATE(val) (((val) << 2) & MISC_CTRL_1_VOLUME_RATE_MASK) +#define MISC_CTRL_1_VOLUME_RATE_1_STEP_EVERY_1_FSYNC 0 +#define MISC_CTRL_1_VOLUME_RATE_1_STEP_EVERY_2_FSYNC 1 +#define MISC_CTRL_1_VOLUME_RATE_1_STEP_EVERY_4_FSYNC 2 +#define MISC_CTRL_1_VOLUME_RATE_1_STEP_EVERY_8_FSYNC 3 +#define MISC_CTRL_1_GAIN_MASK BIT_MASK(2) +#define MISC_CTRL_1_GAIN(val) ((val) & MISC_CTRL_1_GAIN_MASK) +#define MISC_CTRL_1_GAIN_7_5_V_PEAK_OUTPUT 0 +#define MISC_CTRL_1_GAIN_15_V_PEAK_OUTPUT 1 +#define MISC_CTRL_1_GAIN_21_V_PEAK_OUTPUT 2 +#define MISC_CTRL_1_GAIN_29_V_PEAK_OUTPUT 3 + +/* Miscellaneous Control 2 Register */ +#define MISC_CTRL_2_ADDR 0x02 +#define MISC_CTRL_2_PWM_FREQUENCY_MASK (BIT_MASK(3) << 4) +#define MISC_CTRL_2_PWM_FREQUENCY(val) (((val) << 4) & MISC_CTRL_2_PWM_FREQUENCY_MASK) +#define MISC_CTRL_2_PWM_FREQUENCY_8_FS 0 +#define MISC_CTRL_2_PWM_FREQUENCY_10_FS 1 +#define MISC_CTRL_2_PWM_FREQUENCY_38_FS 5 +#define MISC_CTRL_2_PWM_FREQUENCY_44_FS 6 +#define MISC_CTRL_2_PWM_FREQUENCY_48_FS 7 +#define MISC_CTRL_2_SDM_OSR BIT(2) +#define MISC_CTRL_2_SDM_OSR_MASK BIT(2) +#define MISC_CTRL_2_OUTPUT_PHASE_MASK BIT_MASK(2) +#define MISC_CTRL_2_OUTPUT_PHASE(val) ((val) & MISC_CTRL_2_OUTPUT_PHASE_MASK) +#define MISC_CTRL_2_OUTPUT_PHASE_210_DEGREES 1 +#define MISC_CTRL_2_OUTPUT_PHASE_225_DEGREES 2 +#define MISC_CTRL_2_OUTPUT_PHASE_240_DEGREES 3 + +/* Serial Audio-Port Control Register */ +#define SAP_CTRL_ADDR 0x03 +#define SAP_CTRL_INPUT_SAMPLING_RATE_MASK (BIT_MASK(2) << 6) +#define SAP_CTRL_INPUT_SAMPLING_RATE(val) (((val) << 6) & SAP_CTRL_INPUT_SAMPLING_RATE_MASK) +#define SAP_CTRL_INPUT_SAMPLING_RATE_44_1_KHZ 0 +#define SAP_CTRL_INPUT_SAMPLING_RATE_48_KHZ 1 +#define SAP_CTRL_INPUT_SAMPLING_RATE_96_KHZ 2 +#define SAP_CTRL_TDM_SLOT_SELECT BIT(5) +#define SAP_CTRL_TDM_SLOT_SELECT_MASK BIT(5) +#define SAP_CTRL_TDM_SLOT_SIZE BIT(4) +#define SAP_CTRL_TDM_SLOT_SIZE_MASK BIT(4) +#define SAP_CTRL_TDM_SLOT_SELECT_2 BIT(3) +#define SAP_CTRL_TDM_SLOT_SELECT_2_MASK BIT(3) +#define SAP_CTRL_INPUT_FORMAT_MASK BIT_MASK(3) +#define SAP_CTRL_INPUT_FORMAT(val) ((val) & SAP_CTRL_INPUT_FORMAT_MASK) +#define SAP_CTRL_INPUT_FORMAT_24_BITS_RIGHT 0 +#define SAP_CTRL_INPUT_FORMAT_20_BITS_RIGHT 1 +#define SAP_CTRL_INPUT_FORMAT_18_BITS_RIGHT 2 +#define SAP_CTRL_INPUT_FORMAT_16_BITS_RIGHT 3 +#define SAP_CTRL_INPUT_FORMAT_I2S 4 +#define SAP_CTRL_INPUT_FORMAT_LEFT 5 +#define SAP_CTRL_INPUT_FORMAT_DSP 6 + +/* Channel State Control Register */ +#define CH_STATE_CTRL_ADDR 0x04 +#define CH_STATE_CTRL_CH1_STATE_CTRL_MASK (BIT_MASK(2) << 6) +#define CH_STATE_CTRL_CH1_STATE_CTRL(val) (((val) << 6) & CH_STATE_CTRL_CH1_STATE_CTRL_MASK) +#define CH_STATE_CTRL_CH2_STATE_CTRL_MASK (BIT_MASK(2) << 4) +#define CH_STATE_CTRL_CH2_STATE_CTRL(val) (((val) << 4) & CH_STATE_CTRL_CH2_STATE_CTRL_MASK) +#define CH_STATE_CTRL_PLAY 0 +#define CH_STATE_CTRL_HIZ 1 +#define CH_STATE_CTRL_MUTE 2 +#define CH_STATE_CTRL_DC_LOAD 3 + +/* Channel 1 and 2 Volume Control Registers */ +#define CH1_VOLUME_CTRL_ADDR 0x05 +#define CH2_VOLUME_CTRL_ADDR 0x06 +#define CH_VOLUME_CTRL_VOLUME_MASK BIT_MASK(8) +#define CH_VOLUME_CTRL_VOLUME(val) ((val) & CH_VOLUME_CTRL_VOLUME_MASK) + +/* DC Load Diagnostic Control 1 Register */ +#define DC_LDG_CTRL_1_ADDR 0x09 +#define DC_LDG_CTRL_1_ABORT BIT(7) +#define DC_LDG_CTRL_1_ABORT_MASK BIT(7) +#define DC_LDG_CTRL_1_DOUBLE_RAMP BIT(6) +#define DC_LDG_CTRL_1_DOUBLE_RAMP_MASK BIT(6) +#define DC_LDG_CTRL_1_DOUBLE_SETTLE BIT(5) +#define DC_LDG_CTRL_1_DOUBLE_SETTLE_MASK BIT(5) +#define DC_LDG_CTRL_1_LO_ENABLE BIT(1) +#define DC_LDG_CTRL_1_LO_ENABLE_MASK BIT(1) +#define DC_LDG_CTRL_1_BYPASS BIT(0) +#define DC_LDG_CTRL_1_BYPASS_MASK BIT(0) + +/* DC Load Diagnostic Control 2 Register */ +#define DC_LDG_CTRL_2_ADDR 0x0A +#define DC_LDG_CTRL_2_CH1_SL_MASK (BIT_MASK(4) << 4) +#define DC_LDG_CTRL_2_CH1_SL(val) (((val) << 4) & DC_LDG_CTRL_2_CH1_SL_MASK) +#define DC_LDG_CTRL_2_CH2_SL_MASK BIT_MASK(4) +#define DC_LDG_CTRL_2_CH2_SL(val) ((val) & DC_LDG_CTRL_2_CH2_SL_MASK) + +/* DC Load Diagnostics Report 1 */ +#define DC_LDG_REPORT_1_ADDR 0x0C +#define DC_LDG_REPORT_1_CH1_S2G BIT(7) +#define DC_LDG_REPORT_1_CH1_S2G_MASK BIT(7) +#define DC_LDG_REPORT_1_CH1_S2P BIT(6) +#define DC_LDG_REPORT_1_CH1_S2P_MASK BIT(6) +#define DC_LDG_REPORT_1_CH1_OL BIT(5) +#define DC_LDG_REPORT_1_CH1_OL_MASK BIT(5) +#define DC_LDG_REPORT_1_CH1_SL BIT(4) +#define DC_LDG_REPORT_1_CH1_SL_MASK BIT(4) +#define DC_LDG_REPORT_1_CH2_S2G BIT(3) +#define DC_LDG_REPORT_1_CH2_S2G_MASK BIT(3) +#define DC_LDG_REPORT_1_CH2_S2P BIT(2) +#define DC_LDG_REPORT_1_CH2_S2P_MASK BIT(2) +#define DC_LDG_REPORT_1_CH2_OL BIT(1) +#define DC_LDG_REPORT_1_CH2_OL_MASK BIT(1) +#define DC_LDG_REPORT_1_CH2_SL BIT(0) +#define DC_LDG_REPORT_1_CH2_SL_MASK BIT(0) + +/* DC Load Diagnostics Report 3 */ +#define DC_LDG_REPORT_3_ADDR 0x0E +#define DC_LDG_REPORT_3_CH1_LO BIT(3) +#define DC_LDG_REPORT_3_CH1_LO_MASK BIT(3) +#define DC_LDG_REPORT_3_CH2_LO BIT(2) +#define DC_LDG_REPORT_3_CH2_LO_MASK BIT(2) + +/* Channel Faults Register */ +#define CH_FAULTS_ADDR 0x10 +#define CH_FAULTS_CH1_OC BIT(7) +#define CH_FAULTS_CH1_OC_MASK BIT(7) +#define CH_FAULTS_CH2_OC BIT(6) +#define CH_FAULTS_CH2_OC_MASK BIT(6) +#define CH_FAULTS_CH1_DC BIT(3) +#define CH_FAULTS_CH1_DC_MASK BIT(3) +#define CH_FAULTS_CH2_DC BIT(2) +#define CH_FAULTS_CH2_DC_MASK BIT(2) + +/* Global Faults 1 Register */ +#define GLOBAL_FAULTS_1_ADDR 0x11 +#define GLOBAL_FAULTS_1_INVALID_CLOCK BIT(4) +#define GLOBAL_FAULTS_1_INVALID_CLOCK_MASK BIT(4) +#define GLOBAL_FAULTS_1_PVDD_OV BIT(3) +#define GLOBAL_FAULTS_1_PVDD_OV_MASK BIT(3) +#define GLOBAL_FAULTS_1_VBAT_OV BIT(2) +#define GLOBAL_FAULTS_1_VBAT_OV_MASK BIT(2) +#define GLOBAL_FAULTS_1_PVDD_UV BIT(1) +#define GLOBAL_FAULTS_1_PVDD_UV_MASK BIT(1) +#define GLOBAL_FAULTS_1_VBAT_UV BIT(0) +#define GLOBAL_FAULTS_1_VBAT_UV_MASK BIT(0) + +/* Global Faults 2 Register */ +#define GLOBAL_FAULTS_2_ADDR 0x12 +#define GLOBAL_FAULTS_2_OTSD BIT(4) +#define GLOBAL_FAULTS_2_OTSD_MASK BIT(4) +#define GLOBAL_FAULTS_2_CH1_OTSD BIT(3) +#define GLOBAL_FAULTS_2_CH1_OTSD_MASK BIT(3) +#define GLOBAL_FAULTS_2_CH2_OTSD BIT(2) +#define GLOBAL_FAULTS_2_CH2_OTSD_MASK BIT(2) + +/* Warnings Register */ +#define WARNINGS_ADDR 0x13 +#define WARNINGS_VDD_POR BIT(5) +#define WARNINGS_VDD_POR_MASK BIT(5) +#define WARNINGS_OTW BIT(4) +#define WARNINGS_OTW_MASK BIT(4) +#define WARNINGS_OTW_CH1 BIT(3) +#define WARNINGS_OTW_CH1_MASK BIT(3) +#define WARNINGS_OTW_CH2 BIT(2) +#define WARNINGS_OTW_CH2_MASK BIT(2) + +/* Pin Control Register */ +#define PIN_CTRL_ADDR 0x14 +#define PIN_CTRL_MASK_OC BIT(7) +#define PIN_CTRL_MASK_OC_MASK BIT(7) +#define PIN_CTRL_MASK_OTSD BIT(6) +#define PIN_CTRL_MASK_OTSD_MASK BIT(6) +#define PIN_CTRL_MASK_UV BIT(5) +#define PIN_CTRL_MASK_UV_MASK BIT(5) +#define PIN_CTRL_MASK_OV BIT(4) +#define PIN_CTRL_MASK_OV_MASK BIT(4) +#define PIN_CTRL_MASK_DC BIT(3) +#define PIN_CTRL_MASK_DC_MASK BIT(3) +#define PIN_CTRL_MASK_ILIMIT BIT(2) +#define PIN_CTRL_MASK_ILIMIT_MASK BIT(2) +#define PIN_CTRL_MASK_CLIP BIT(1) +#define PIN_CTRL_MASK_CLIP_MASK BIT(1) +#define PIN_CTRL_MASK_OTW BIT(0) +#define PIN_CTRL_MASK_OTW_MASK BIT(0) + +/* Miscellaneous Control 3 Register */ +#define MISC_CTRL_3_ADDR 0x21 +#define MISC_CTRL_3_CLEAR_FAULT BIT(7) +#define MISC_CTRL_3_CLEAR_FAULT_MASK BIT(7) +#define MISC_CTRL_3_PBTL_CH_SEL BIT(6) +#define MISC_CTRL_3_PBTL_CH_SEL_MASK BIT(6) +#define MISC_CTRL_3_MASK_ILIMIT BIT(5) +#define MISC_CTRL_3_MASK_ILIMIT_MASK BIT(5) +#define MISC_CTRL_3_OTSD_AUTO_RECOVERY BIT(3) +#define MISC_CTRL_3_OTSD_AUTO_RECOVERY_MASK BIT(3) + +/* ILIMIT Status Register */ +#define ILIMIT_STATUS_ADDR 0x25 +#define ILIMIT_STATUS_CH2_ILIMIT_WARN BIT(1) +#define ILIMIT_STATUS_CH2_ILIMIT_WARN_MASK BIT(1) +#define ILIMIT_STATUS_CH1_ILIMIT_WARN BIT(0) +#define ILIMIT_STATUS_CH1_ILIMIT_WARN_MASK BIT(0) + +/* Miscellaneous Control 4 Register */ +#define MISC_CTRL_4_ADDR 0x26 +#define MISC_CTRL_4_HPF_CORNER_MASK BIT_MASK(3) +#define MISC_CTRL_4_HPF_CORNER(val) ((val) & MISC_CTRL_4_HPF_CORNER_MASK) +#define MISC_CTRL_4_HPF_CORNER_3_7_HZ 0 +#define MISC_CTRL_4_HPF_CORNER_7_4_HZ 1 +#define MISC_CTRL_4_HPF_CORNER_15_HZ 2 +#define MISC_CTRL_4_HPF_CORNER_30_HZ 3 +#define MISC_CTRL_4_HPF_CORNER_59_HZ 4 +#define MISC_CTRL_4_HPF_CORNER_118_HZ 5 +#define MISC_CTRL_4_HPF_CORNER_235_HZ 6 +#define MISC_CTRL_4_HPF_CORNER_463_HZ 7 + +/* Miscellaneous Control 5 Register */ +#define MISC_CTRL_5_ADDR 0x28 +#define MISC_CTRL_5_SS_BW_SEL BIT(7) +#define MISC_CTRL_5_SS_BW_SEL_MASK BIT(7) +#define MISC_CTRL_5_SS_DIV2 BIT(6) +#define MISC_CTRL_5_SS_DIV2_MASK BIT(6) +#define MISC_CTRL_5_PHASE_SEL_MSB BIT(5) +#define MISC_CTRL_5_PHASE_SEL_MSB_MASK BIT(5) + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_DRIVERS_AUDIO_TAS6422DAC_H_ */ diff --git a/drivers/auxdisplay/CMakeLists.txt b/drivers/auxdisplay/CMakeLists.txt index 91a86610526..ce53a06713b 100644 --- a/drivers/auxdisplay/CMakeLists.txt +++ b/drivers/auxdisplay/CMakeLists.txt @@ -8,3 +8,4 @@ zephyr_library_sources_ifdef(CONFIG_AUXDISPLAY_HD44780 auxdisplay_hd44780.c) zephyr_library_sources_ifdef(CONFIG_AUXDISPLAY_ITRON auxdisplay_itron.c) zephyr_library_sources_ifdef(CONFIG_AUXDISPLAY_JHD1313 auxdisplay_jhd1313.c) zephyr_library_sources_ifdef(CONFIG_AUXDISPLAY_PT6314 auxdisplay_pt6314.c) +zephyr_library_sources_ifdef(CONFIG_AUXDISPLAY_SERLCD auxdisplay_serlcd.c) diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig index f28b463a633..908ceab1796 100644 --- a/drivers/auxdisplay/Kconfig +++ b/drivers/auxdisplay/Kconfig @@ -24,5 +24,6 @@ source "drivers/auxdisplay/Kconfig.hd44780" source "drivers/auxdisplay/Kconfig.itron" source "drivers/auxdisplay/Kconfig.jhd1313" source "drivers/auxdisplay/Kconfig.pt6314" +source "drivers/auxdisplay/Kconfig.serlcd" endif # AUXDISPLAY diff --git a/drivers/auxdisplay/Kconfig.serlcd b/drivers/auxdisplay/Kconfig.serlcd new file mode 100644 index 00000000000..d90acfe78d4 --- /dev/null +++ b/drivers/auxdisplay/Kconfig.serlcd @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Jan Henke +# SPDX-License-Identifier: Apache-2.0 + +config AUXDISPLAY_SERLCD + bool "SparkFun SerLCD dot character LCD driver" + default y + select I2C + depends on DT_HAS_SPARKFUN_SERLCD_ENABLED + help + Enable driver for SparkFun SerLCD. diff --git a/drivers/auxdisplay/auxdisplay_handlers.c b/drivers/auxdisplay/auxdisplay_handlers.c index 8944b3da9ff..5c88e7afa09 100644 --- a/drivers/auxdisplay/auxdisplay_handlers.c +++ b/drivers/auxdisplay/auxdisplay_handlers.c @@ -5,25 +5,25 @@ */ #include -#include +#include static inline int z_vrfy_auxdisplay_display_on(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_display_on(dev); } #include static inline int z_vrfy_auxdisplay_display_off(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_display_off(dev); } #include static inline int z_vrfy_auxdisplay_cursor_set_enabled(const struct device *dev, bool enabled) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_cursor_set_enabled(dev, enabled); } #include @@ -31,7 +31,7 @@ static inline int z_vrfy_auxdisplay_cursor_set_enabled(const struct device *dev, static inline int z_vrfy_auxdisplay_position_blinking_set_enabled(const struct device *dev, bool enabled) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_position_blinking_set_enabled(dev, enabled); } #include @@ -39,7 +39,7 @@ static inline int z_vrfy_auxdisplay_position_blinking_set_enabled(const struct d static inline int z_vrfy_auxdisplay_cursor_shift_set(const struct device *dev, uint8_t direction, bool display_shift) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_cursor_shift_set(dev, direction, display_shift); } #include @@ -48,7 +48,7 @@ static inline int z_vrfy_auxdisplay_cursor_position_set(const struct device *dev enum auxdisplay_position type, int16_t x, int16_t y) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_cursor_position_set(dev, type, x, y); } #include @@ -56,7 +56,7 @@ static inline int z_vrfy_auxdisplay_cursor_position_set(const struct device *dev static inline int z_vrfy_auxdisplay_cursor_position_get(const struct device *dev, int16_t *x, int16_t *y) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_cursor_position_get(dev, x, y); } #include @@ -65,7 +65,7 @@ static inline int z_vrfy_auxdisplay_display_position_set(const struct device *de enum auxdisplay_position type, int16_t x, int16_t y) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_display_position_set(dev, type, x, y); } #include @@ -73,7 +73,7 @@ static inline int z_vrfy_auxdisplay_display_position_set(const struct device *de static inline int z_vrfy_auxdisplay_display_position_get(const struct device *dev, int16_t *x, int16_t *y) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_display_position_get(dev, x, y); } #include @@ -81,14 +81,14 @@ static inline int z_vrfy_auxdisplay_display_position_get(const struct device *de static inline int z_vrfy_auxdisplay_capabilities_get(const struct device *dev, struct auxdisplay_capabilities *capabilities) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_capabilities_get(dev, capabilities); } #include static inline int z_vrfy_auxdisplay_clear(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_clear(dev); } #include @@ -96,7 +96,7 @@ static inline int z_vrfy_auxdisplay_clear(const struct device *dev) static inline int z_vrfy_auxdisplay_brightness_get(const struct device *dev, uint8_t *brightness) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_brightness_get(dev, brightness); } #include @@ -104,7 +104,7 @@ static inline int z_vrfy_auxdisplay_brightness_get(const struct device *dev, static inline int z_vrfy_auxdisplay_brightness_set(const struct device *dev, uint8_t brightness) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_brightness_set(dev, brightness); } #include @@ -112,7 +112,7 @@ static inline int z_vrfy_auxdisplay_brightness_set(const struct device *dev, static inline int z_vrfy_auxdisplay_backlight_get(const struct device *dev, uint8_t *backlight) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_backlight_get(dev, backlight); } #include @@ -120,14 +120,14 @@ static inline int z_vrfy_auxdisplay_backlight_get(const struct device *dev, static inline int z_vrfy_auxdisplay_backlight_set(const struct device *dev, uint8_t backlight) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_backlight_set(dev, backlight); } #include static inline int z_vrfy_auxdisplay_is_busy(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_is_busy(dev); } #include @@ -135,7 +135,7 @@ static inline int z_vrfy_auxdisplay_is_busy(const struct device *dev) static inline int z_vrfy_auxdisplay_custom_character_set(const struct device *dev, struct auxdisplay_character *character) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_custom_character_set(dev, character); } #include @@ -143,7 +143,7 @@ static inline int z_vrfy_auxdisplay_custom_character_set(const struct device *de static inline int z_vrfy_auxdisplay_write(const struct device *dev, const uint8_t *data, uint16_t len) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_write(dev, data, len); } #include @@ -151,7 +151,7 @@ static inline int z_vrfy_auxdisplay_write(const struct device *dev, const uint8_ static inline int z_vrfy_auxdisplay_custom_command(const struct device *dev, struct auxdisplay_custom_data *data) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_custom_command(dev, data); } #include diff --git a/drivers/auxdisplay/auxdisplay_serlcd.c b/drivers/auxdisplay/auxdisplay_serlcd.c new file mode 100644 index 00000000000..f3c0e764869 --- /dev/null +++ b/drivers/auxdisplay/auxdisplay_serlcd.c @@ -0,0 +1,436 @@ +/* + * Copyright (c) 2023 Jan Henke + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT sparkfun_serlcd + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(auxdisplay_serlcd, CONFIG_AUXDISPLAY_LOG_LEVEL); + +/* + * | in ASCII, used to begin a display command + */ +#define SERLCD_BEGIN_COMMAND 0x7C + +/* + * special command for the underlying display controller + */ +#define SERLCD_BEGIN_SPECIAL_COMMAND 0xFE + +/* + * delay in milliseconds after a normal command was sent + */ +#define SERLCD_COMMAND_DELAY_MS 10 + +/* + * delay in milliseconds after a special command was sent + */ +#define SERLCD_SPECIAL_COMMAND_DELAY_MS 50 + +/* + * maximum amount of custom chars the display supports + */ +#define SERLCD_CUSTOM_CHAR_MAX_COUNT 8 + +/* + * height of a custom char in bits + */ +#define SERLCD_CUSTOM_CHAR_HEIGHT 8 + +/* + * width of a custom char in bits + */ +#define SERLCD_CUSTOM_CHAR_WIDTH 5 + +/* + * char code for the first custom char + */ +#define SERLCD_CUSTOM_CHAR_INDEX_BASE 0x08 + +/* + * bitmask for custom character detection + */ +#define SERLCD_CUSTOM_CHAR_BITMASK 0xf8 + +/* + * bit to set in the display control special command to indicate the display should be powered on + */ +#define SERLCD_DISPLAY_CONTROL_POWER_BIT BIT(2) + +/* + * bit to set in the display control special command to indicate the cursor should be displayed + */ +#define SERLCD_DISPLAY_CONTROL_CURSOR_BIT BIT(1) + +/* + * bit to set in the display control special command to indicate the cursor should be blinking + */ +#define SERLCD_DISPLAY_CONTROL_BLINKING_BIT BIT(0) + +struct auxdisplay_serlcd_data { + bool power; + bool cursor; + bool blinking; + uint16_t cursor_x; + uint16_t cursor_y; +}; + +struct auxdisplay_serlcd_config { + struct auxdisplay_capabilities capabilities; + struct i2c_dt_spec bus; +}; + +enum auxdisplay_serlcd_command { + SERLCD_COMMAND_SET_CUSTOM_CHAR = 0x1B, + SERLCD_COMMAND_WRITE_CUSTOM_CHAR = 0x23, + SERLCD_COMMAND_CLEAR = 0x2D, +}; + +enum auxdisplay_serlcd_special_command { + SERLCD_SPECIAL_RETURN_HOME = 0x02, + SERLCD_SPECIAL_DISPLAY_CONTROL = 0x08, + SERLCD_SPECIAL_SET_DD_RAM_ADDRESS = 0x80, +}; + +static int auxdisplay_serlcd_send_command(const struct device *dev, + const enum auxdisplay_serlcd_command command) +{ + const struct auxdisplay_serlcd_config *config = dev->config; + const uint8_t buffer[2] = {SERLCD_BEGIN_COMMAND, command}; + + int rc = i2c_write_dt(&config->bus, buffer, sizeof(buffer)); + + k_sleep(K_MSEC(SERLCD_COMMAND_DELAY_MS)); + return rc; +} + +static int +auxdisplay_serlcd_send_special_command(const struct device *dev, + const enum auxdisplay_serlcd_special_command command) +{ + const struct auxdisplay_serlcd_config *config = dev->config; + const uint8_t buffer[2] = {SERLCD_BEGIN_SPECIAL_COMMAND, command}; + + int rc = i2c_write_dt(&config->bus, buffer, sizeof(buffer)); + + k_sleep(K_MSEC(SERLCD_SPECIAL_COMMAND_DELAY_MS)); + return rc; +} + +static int auxdisplay_serlcd_send_display_state(const struct device *dev, + const struct auxdisplay_serlcd_data *data) +{ + uint8_t command = SERLCD_SPECIAL_DISPLAY_CONTROL; + + if (data->power) { + command |= SERLCD_DISPLAY_CONTROL_POWER_BIT; + } + if (data->cursor) { + command |= SERLCD_DISPLAY_CONTROL_CURSOR_BIT; + } + if (data->blinking) { + command |= SERLCD_DISPLAY_CONTROL_BLINKING_BIT; + } + + return auxdisplay_serlcd_send_special_command(dev, command); +} + +static int auxdisplay_serlcd_display_on(const struct device *dev) +{ + struct auxdisplay_serlcd_data *data = dev->data; + + data->power = true; + + return auxdisplay_serlcd_send_display_state(dev, data); +} + +static int auxdisplay_serlcd_display_off(const struct device *dev) +{ + struct auxdisplay_serlcd_data *data = dev->data; + + data->power = false; + + return auxdisplay_serlcd_send_display_state(dev, data); +} + +static int auxdisplay_serlcd_cursor_set_enabled(const struct device *dev, bool enable) +{ + struct auxdisplay_serlcd_data *data = dev->data; + + data->cursor = enable; + + return auxdisplay_serlcd_send_display_state(dev, data); +} + +static int auxdisplay_serlcd_position_blinking_set_enabled(const struct device *dev, bool enable) +{ + struct auxdisplay_serlcd_data *data = dev->data; + + data->blinking = enable; + + return auxdisplay_serlcd_send_display_state(dev, data); +} + +static int auxdisplay_serlcd_cursor_position_set(const struct device *dev, + enum auxdisplay_position type, int16_t x, + int16_t y) +{ + static const uint8_t row_offsets[] = {0x00, 0x40, 0x14, 0x54}; + + const struct auxdisplay_serlcd_config *config = dev->config; + const struct auxdisplay_capabilities capabilities = config->capabilities; + const uint16_t columns = capabilities.columns; + const uint16_t rows = capabilities.rows; + struct auxdisplay_serlcd_data *data = dev->data; + + if (type == AUXDISPLAY_POSITION_ABSOLUTE) { + /* + * shortcut for (0,0) position + */ + if (x == 0 && y == 0) { + data->cursor_x = x; + data->cursor_y = y; + return auxdisplay_serlcd_send_special_command(dev, + SERLCD_SPECIAL_RETURN_HOME); + } + + /* + * bounds checking + */ + if (x < 0 || x >= columns) { + return -EINVAL; + } + if (y < 0 || y >= rows) { + return -EINVAL; + } + + data->cursor_x = x; + data->cursor_y = y; + + const uint8_t cursor_address = x + row_offsets[y]; + + return auxdisplay_serlcd_send_special_command( + dev, SERLCD_SPECIAL_SET_DD_RAM_ADDRESS | cursor_address); + + } else if (type == AUXDISPLAY_POSITION_RELATIVE) { + /* + * clip relative move to display dimensions + */ + const int new_x = (data->cursor_x + x) % columns; + const int new_y = (data->cursor_y + y + x / columns) % rows; + const uint16_t column = new_x < 0 ? new_x + columns : new_x; + const uint16_t row = new_y < 0 ? new_y + rows : new_y; + + data->cursor_x = column; + data->cursor_y = row; + + const uint8_t cursor_address = column + row_offsets[row]; + + return auxdisplay_serlcd_send_special_command( + dev, SERLCD_SPECIAL_SET_DD_RAM_ADDRESS | cursor_address); + } + + /* + * other types of movement are not implemented/supported + */ + return -ENOSYS; +} + +static int auxdisplay_serlcd_cursor_position_get(const struct device *dev, int16_t *x, int16_t *y) +{ + const struct auxdisplay_serlcd_data *data = dev->data; + + *x = (int16_t)data->cursor_x; + *y = (int16_t)data->cursor_y; + + return 0; +} + +static int auxdisplay_serlcd_capabilities_get(const struct device *dev, + struct auxdisplay_capabilities *capabilities) +{ + const struct auxdisplay_serlcd_config *config = dev->config; + + memcpy(capabilities, &config->capabilities, sizeof(struct auxdisplay_capabilities)); + + return 0; +} + +static int auxdisplay_serlcd_clear(const struct device *dev) +{ + int rc = auxdisplay_serlcd_send_command(dev, SERLCD_COMMAND_CLEAR); + + k_sleep(K_MSEC(SERLCD_COMMAND_DELAY_MS)); + return rc; +} + +static int auxdisplay_serlcd_custom_character_set(const struct device *dev, + struct auxdisplay_character *character) +{ + const struct auxdisplay_serlcd_config *config = dev->config; + int rc; + + /* + * only indexes 0..7 are supported + */ + const uint8_t char_index = character->index; + + if (char_index > (SERLCD_CUSTOM_CHAR_MAX_COUNT - 1)) { + return -EINVAL; + } + + /* + * custom characters are accessible via char codes 0x08..0x0f + */ + character->character_code = SERLCD_CUSTOM_CHAR_INDEX_BASE | char_index; + + rc = auxdisplay_serlcd_send_command(dev, SERLCD_COMMAND_SET_CUSTOM_CHAR + char_index); + if (!rc) { + return rc; + } + + /* + * the display expects the custom character as 8 lines of 5 bit each, shades are not + * supported + */ + for (int l = 0; l < SERLCD_CUSTOM_CHAR_HEIGHT; ++l) { + uint8_t buffer = 0; + + for (int i = 0; i < SERLCD_CUSTOM_CHAR_WIDTH; ++i) { + if (character->data[(l * 5) + i]) { + buffer |= BIT(4 - i); + } + } + rc = i2c_write_dt(&config->bus, &buffer, sizeof(buffer)); + if (!rc) { + return rc; + } + } + + return rc; +} + +static void auxdisplay_serlcd_advance_current_position(const struct device *dev) +{ + const struct auxdisplay_serlcd_config *config = dev->config; + struct auxdisplay_serlcd_data *data = dev->data; + + ++(data->cursor_x); + if (data->cursor_x >= config->capabilities.columns) { + data->cursor_x = 0; + ++(data->cursor_y); + } + if (data->cursor_y >= config->capabilities.rows) { + data->cursor_y = 0; + } +} + +static int auxdisplay_serlcd_write(const struct device *dev, const uint8_t *text, uint16_t len) +{ + const struct auxdisplay_serlcd_config *config = dev->config; + + int rc = 0; + + /* + * the display wraps around by itself, just write the text and update the position data + */ + for (int i = 0; i < len; ++i) { + uint8_t character = text[i]; + + /* + * customer characters require a special command, so check for custom char + */ + if ((character & SERLCD_CUSTOM_CHAR_BITMASK) == SERLCD_CUSTOM_CHAR_INDEX_BASE) { + const uint8_t command = SERLCD_COMMAND_WRITE_CUSTOM_CHAR + + (character & ~SERLCD_CUSTOM_CHAR_BITMASK); + + rc = auxdisplay_serlcd_send_command(dev, command); + if (!rc) { + return rc; + } + auxdisplay_serlcd_advance_current_position(dev); + } else if (character == SERLCD_BEGIN_COMMAND || + character == SERLCD_BEGIN_SPECIAL_COMMAND) { + /* + * skip these characters in text, as they have a special meaning, if + * required a custom character can be used as replacement + */ + continue; + } else { + rc = i2c_write_dt(&config->bus, text, len); + if (!rc) { + return rc; + } + auxdisplay_serlcd_advance_current_position(dev); + } + } + + return rc; +} + +static int auxdisplay_serlcd_init(const struct device *dev) +{ + const struct auxdisplay_serlcd_config *config = dev->config; + struct auxdisplay_serlcd_data *data = dev->data; + + /* + * Initialize our data structure + */ + data->power = true; + + if (!device_is_ready(config->bus.bus)) { + return -ENODEV; + } + + auxdisplay_serlcd_clear(dev); + + return 0; +} + +static const struct auxdisplay_driver_api auxdisplay_serlcd_auxdisplay_api = { + .display_on = auxdisplay_serlcd_display_on, + .display_off = auxdisplay_serlcd_display_off, + .cursor_set_enabled = auxdisplay_serlcd_cursor_set_enabled, + .position_blinking_set_enabled = auxdisplay_serlcd_position_blinking_set_enabled, + .cursor_position_set = auxdisplay_serlcd_cursor_position_set, + .cursor_position_get = auxdisplay_serlcd_cursor_position_get, + .capabilities_get = auxdisplay_serlcd_capabilities_get, + .clear = auxdisplay_serlcd_clear, + .custom_character_set = auxdisplay_serlcd_custom_character_set, + .write = auxdisplay_serlcd_write, +}; + +#define AUXDISPLAY_SERLCD_INST(inst) \ + static const struct auxdisplay_serlcd_config auxdisplay_serlcd_config_##inst = { \ + .capabilities = { \ + .columns = DT_INST_PROP(inst, columns), \ + .rows = DT_INST_PROP(inst, rows), \ + .mode = 0, \ + .brightness.minimum = AUXDISPLAY_LIGHT_NOT_SUPPORTED, \ + .brightness.maximum = AUXDISPLAY_LIGHT_NOT_SUPPORTED, \ + .backlight.minimum = AUXDISPLAY_LIGHT_NOT_SUPPORTED, \ + .backlight.maximum = AUXDISPLAY_LIGHT_NOT_SUPPORTED, \ + .custom_characters = SERLCD_CUSTOM_CHAR_MAX_COUNT, \ + .custom_character_width = SERLCD_CUSTOM_CHAR_WIDTH, \ + .custom_character_height = SERLCD_CUSTOM_CHAR_HEIGHT, \ + }, \ + .bus = I2C_DT_SPEC_INST_GET(inst)}; \ + \ + static struct auxdisplay_serlcd_data auxdisplay_serlcd_data_##inst; \ + \ + DEVICE_DT_INST_DEFINE(inst, &auxdisplay_serlcd_init, NULL, &auxdisplay_serlcd_data_##inst, \ + &auxdisplay_serlcd_config_##inst, POST_KERNEL, \ + CONFIG_AUXDISPLAY_INIT_PRIORITY, &auxdisplay_serlcd_auxdisplay_api); + +DT_INST_FOREACH_STATUS_OKAY(AUXDISPLAY_SERLCD_INST) diff --git a/drivers/bbram/Kconfig.stm32 b/drivers/bbram/Kconfig.stm32 index e3cbd3bbd40..ec372cb3ecb 100644 --- a/drivers/bbram/Kconfig.stm32 +++ b/drivers/bbram/Kconfig.stm32 @@ -5,7 +5,7 @@ config BBRAM_STM32 bool "ST STM32 Battery-backed RAM drivers" default y depends on DT_HAS_ST_STM32_BBRAM_ENABLED - depends on COUNTER + depends on COUNTER_RTC_STM32 || RTC_STM32 help This option enables the BBRAM driver for STM32 family of processors. diff --git a/drivers/bbram/bbram_handlers.c b/drivers/bbram/bbram_handlers.c index 1bc20dcd359..14e4abe21b3 100644 --- a/drivers/bbram/bbram_handlers.c +++ b/drivers/bbram/bbram_handlers.c @@ -5,33 +5,33 @@ */ #include -#include +#include static inline int z_vrfy_bbram_check_invalid(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_BBRAM)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_BBRAM)); return z_impl_bbram_check_invalid(dev); } #include static inline int z_vrfy_bbram_check_standby_power(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_BBRAM)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_BBRAM)); return z_impl_bbram_check_standby_power(dev); } #include static inline int z_vrfy_bbram_check_power(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_BBRAM)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_BBRAM)); return z_impl_bbram_check_power(dev); } #include static inline int z_vrfy_bbram_get_size(const struct device *dev, size_t *size) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_BBRAM)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(size, sizeof(size_t))); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_BBRAM)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(size, sizeof(size_t))); return z_impl_bbram_get_size(dev, size); } #include @@ -39,8 +39,8 @@ static inline int z_vrfy_bbram_get_size(const struct device *dev, size_t *size) static inline int z_vrfy_bbram_read(const struct device *dev, size_t offset, size_t size, uint8_t *data) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_BBRAM)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(data, size)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_BBRAM)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(data, size)); return z_impl_bbram_read(dev, offset, size, data); } #include @@ -48,8 +48,8 @@ static inline int z_vrfy_bbram_read(const struct device *dev, size_t offset, static inline int z_vrfy_bbram_write(const struct device *dev, size_t offset, size_t size, const uint8_t *data) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_BBRAM)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(data, size)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_BBRAM)); + K_OOPS(K_SYSCALL_MEMORY_READ(data, size)); return z_impl_bbram_write(dev, offset, size, data); } #include diff --git a/drivers/bbram/bbram_stm32.c b/drivers/bbram/bbram_stm32.c index 30bc2c5edaa..0ba429d66f8 100644 --- a/drivers/bbram/bbram_stm32.c +++ b/drivers/bbram/bbram_stm32.c @@ -14,7 +14,14 @@ LOG_MODULE_REGISTER(bbram, CONFIG_BBRAM_LOG_LEVEL); #define STM32_BKP_REG_BYTES 4 -#define STM32_BKP_REG_OFFSET 0x50 +#ifdef TAMP +/* If a SoC has a TAMP peripherals, then the backup registers are defined there, + * not in the RTC. + */ +#define STM32_BKP_REG_OFFSET (TAMP_BASE + offsetof(TAMP_TypeDef, BKP0R) - RTC_BASE) +#else +#define STM32_BKP_REG_OFFSET offsetof(RTC_TypeDef, BKP0R) +#endif #define STM32_BKP_REG_INDEX(offset) ((offset) >> 2) #define STM32_BKP_REG_BYTE_INDEX(offset) ((offset)&0x3UL) #define STM32_BKP_REG(i) (((volatile uint32_t *)config->base_addr)[(i)]) diff --git a/drivers/bluetooth/hci/CMakeLists.txt b/drivers/bluetooth/hci/CMakeLists.txt index 8aca5f92a7f..6aaf5205b0d 100644 --- a/drivers/bluetooth/hci/CMakeLists.txt +++ b/drivers/bluetooth/hci/CMakeLists.txt @@ -1,13 +1,27 @@ # SPDX-License-Identifier: Apache-2.0 +# Remove after 3.7.0 is released +if(CONFIG_BT_RPMSG) + message(FATAL_ERROR "CONFIG_BT_RPMSG has been renamed to CONFIG_BT_HCI_IPC") +endif() + +# Remove after 3.7.0 is released +if(CONFIG_BT_HCI_IPC) + dt_chosen(chosen_hci_rpmsg PROPERTY "zephyr,bt-hci-rpmsg-ipc") + if(DEFINED chosen_hci_rpmsg) + message(FATAL_ERROR "zephyr,bt-hci-rpmsg-ipc has been renamed to zephyr,bt-hci-ipc") + endif() +endif() + zephyr_library_sources_ifdef(CONFIG_BT_B91 hci_b91.c) -zephyr_library_sources_ifdef(CONFIG_BT_CYW43XXX cyw43xxx.c) +zephyr_library_sources_ifdef(CONFIG_BT_AIROC cyw43xxx.c) zephyr_library_sources_ifdef(CONFIG_BT_ESP32 hci_esp32.c) zephyr_library_sources_ifdef(CONFIG_BT_H4 h4.c) zephyr_library_sources_ifdef(CONFIG_BT_H5 h5.c) -zephyr_library_sources_ifdef(CONFIG_BT_RPMSG rpmsg.c) +zephyr_library_sources_ifdef(CONFIG_BT_HCI_IPC ipc.c) zephyr_library_sources_ifdef(CONFIG_BT_SPI spi.c) zephyr_library_sources_ifdef(CONFIG_BT_STM32_IPM ipm_stm32wb.c) zephyr_library_sources_ifdef(CONFIG_BT_USERCHAN userchan.c) zephyr_library_sources_ifdef(CONFIG_BT_SILABS_HCI slz_hci.c) zephyr_library_sources_ifdef(CONFIG_BT_PSOC6_BLESS hci_psoc6_bless.c) +zephyr_library_sources_ifdef(CONFIG_SOC_NRF5340_CPUAPP nrf53_support.c) diff --git a/drivers/bluetooth/hci/Kconfig b/drivers/bluetooth/hci/Kconfig index 8a50caa92f0..0f792b58b08 100644 --- a/drivers/bluetooth/hci/Kconfig +++ b/drivers/bluetooth/hci/Kconfig @@ -7,41 +7,47 @@ comment "Bluetooth HCI Driver Options" config BT_UART bool + select SERIAL + select UART_INTERRUPT_DRIVEN + choice BT_HCI_BUS_TYPE prompt "Bluetooth HCI driver" config BT_H4 bool "H:4 UART" - select UART_INTERRUPT_DRIVEN select BT_UART - depends on SERIAL help Bluetooth H:4 UART driver. Requires hardware flow control lines to be available. config BT_H5 bool "H:5 UART [EXPERIMENTAL]" - select UART_INTERRUPT_DRIVEN select BT_UART select EXPERIMENTAL - depends on SERIAL help Bluetooth three-wire (H:5) UART driver. Implementation of HCI Three-Wire UART Transport Layer. +# Removed: Here only to give the user a warning about its removal +# Remove after 3.7.0 is released config BT_RPMSG - bool "HCI using RPMsg" + bool "[REMOVED] HCI using RPMsg" + help + Use BT_HCI_IPC instead + +config BT_HCI_IPC + bool "HCI using the IPC subsystem" select BT_HAS_HCI_VS select IPC_SERVICE select MBOX help Bluetooth HCI driver for communication with another CPU - using RPMsg framework. + using the IPC subsystem. config BT_SPI bool "SPI HCI" - depends on SPI + select SPI help Supports Bluetooth ICs using SPI as the communication protocol. HCI packets are sent and received as single Byte transfers, @@ -99,6 +105,7 @@ config BT_PSOC6_BLESS config BT_NO_DRIVER bool "No default HCI driver" + select BT_HAS_HCI_VS help This is intended for unit tests where no internal driver should be selected. @@ -130,10 +137,11 @@ config BT_STM32_IPM_RX_STACK_SIZE depends on BT_STM32_IPM default 512 -menuconfig BT_CYW43XXX - bool "CYW43XXX BT connectivity" +menuconfig BT_AIROC + bool "AIROC BT connectivity" default y select BT_HCI_SETUP + select UART_USE_RUNTIME_CONFIGURE depends on GPIO depends on DT_HAS_INFINEON_CYW43XXX_BT_HCI_ENABLED depends on BT_H4 @@ -146,7 +154,7 @@ source "drivers/bluetooth/hci/Kconfig.infineon" config BT_DRIVER_QUIRK_NO_AUTO_DLE bool "Host auto-initiated Data Length Update quirk" depends on BT_AUTO_DATA_LEN_UPDATE - default y if BT_RPMSG || BT_ESP32 + default y if BT_HCI_IPC || BT_ESP32 help Enable the quirk wherein BT Host stack will auto-initiate Data Length Update procedure for new connections for controllers that do not diff --git a/drivers/bluetooth/hci/Kconfig.infineon b/drivers/bluetooth/hci/Kconfig.infineon index d0e4478ac34..1f4193bd28a 100644 --- a/drivers/bluetooth/hci/Kconfig.infineon +++ b/drivers/bluetooth/hci/Kconfig.infineon @@ -2,10 +2,10 @@ # an affiliate of Cypress Semiconductor Corporation # SPDX-License-Identifier: Apache-2.0 -if BT_CYW43XXX +if BT_AIROC -choice CYW43XXX_PART - prompt "Select CYW43XXX part" +choice AIROC_PART + prompt "Select AIROC part" config CYW4343W bool "CYW4343W" @@ -42,12 +42,12 @@ config CYW43439 More information about CYW43439 device you can find on https://www.infineon.com/cms/en/product/wireless-connectivity/airoc-wi-fi-plus-bluetooth-combos/cyw43439/ -config BT_CYW43XXX_CUSTOM - bool "Custom CYW43xx device/module" +config BT_AIROC_CUSTOM + bool "Custom AIROC device/module" help - Select Custom CYW43xx device/module. For this option, + Select Custom AIROC device/module. For this option, user must to provide path to BT firmware HCD file for - custom or vendor CYW43xx modules in CYW43XX_CUSTOM_FIRMWARE_HCD_BLOB. + custom or vendor AIROC modules in AIROC_CUSTOM_FIRMWARE_HCD_BLOB. endchoice @@ -117,8 +117,8 @@ config CYW43439_MURATA_1YN endchoice -config CYW43XX_CUSTOM_FIRMWARE_HCD_BLOB - depends on BT_CYW43XXX_CUSTOM +config AIROC_CUSTOM_FIRMWARE_HCD_BLOB + depends on BT_AIROC_CUSTOM string "Path to user BT firmware HCD file" help Path to BT firmware HCD file for custom or vendor CYW43xx modules. @@ -134,7 +134,7 @@ config BT_BUF_CMD_TX_SIZE config BT_ATT_ENFORCE_FLOW default n -endif # BT_CYW43XXX +endif # BT_AIROC if BT_PSOC6_BLESS diff --git a/drivers/bluetooth/hci/h5.c b/drivers/bluetooth/hci/h5.c index c9395509248..25a3b3e28f6 100644 --- a/drivers/bluetooth/hci/h5.c +++ b/drivers/bluetooth/hci/h5.c @@ -607,8 +607,12 @@ static int h5_queue(struct net_buf *buf) return 0; } -static void tx_thread(void) +static void tx_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + LOG_DBG(""); /* FIXME: make periodic sending */ @@ -653,8 +657,12 @@ static void h5_set_txwin(uint8_t *conf) conf[2] = h5.tx_win & 0x07; } -static void rx_thread(void) +static void rx_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + LOG_DBG(""); while (true) { @@ -721,7 +729,7 @@ static void h5_init(void) k_fifo_init(&h5.tx_queue); k_thread_create(&tx_thread_data, tx_stack, K_KERNEL_STACK_SIZEOF(tx_stack), - (k_thread_entry_t)tx_thread, NULL, NULL, NULL, + tx_thread, NULL, NULL, NULL, K_PRIO_COOP(CONFIG_BT_HCI_TX_PRIO), 0, K_NO_WAIT); k_thread_name_set(&tx_thread_data, "tx_thread"); @@ -729,7 +737,7 @@ static void h5_init(void) k_fifo_init(&h5.rx_queue); k_thread_create(&rx_thread_data, rx_stack, K_KERNEL_STACK_SIZEOF(rx_stack), - (k_thread_entry_t)rx_thread, NULL, NULL, NULL, + rx_thread, NULL, NULL, NULL, K_PRIO_COOP(CONFIG_BT_RX_PRIO), 0, K_NO_WAIT); k_thread_name_set(&rx_thread_data, "rx_thread"); diff --git a/drivers/bluetooth/hci/hci_psoc6_bless.c b/drivers/bluetooth/hci/hci_psoc6_bless.c index c001264618b..3a5fddb1000 100644 --- a/drivers/bluetooth/hci/hci_psoc6_bless.c +++ b/drivers/bluetooth/hci/hci_psoc6_bless.c @@ -21,7 +21,7 @@ #include #include #include -#include "zephyr/logging/log.h" +#include #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER) #define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL diff --git a/drivers/bluetooth/hci/ipc.c b/drivers/bluetooth/hci/ipc.c new file mode 100644 index 00000000000..56671c702d6 --- /dev/null +++ b/drivers/bluetooth/hci/ipc.c @@ -0,0 +1,410 @@ +/* + * Copyright (c) 2019 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include + +#include +#include + +#define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL +#include +LOG_MODULE_REGISTER(bt_hci_driver); + +#define IPC_CMD 0x01 +#define IPC_ACL 0x02 +#define IPC_SCO 0x03 +#define IPC_EVT 0x04 +#define IPC_ISO 0x05 + +#define IPC_BOUND_TIMEOUT_IN_MS K_MSEC(1000) + +static struct ipc_ept hci_ept; +static K_SEM_DEFINE(ipc_bound_sem, 0, 1); + +static bool is_hci_event_discardable(const uint8_t *evt_data) +{ + uint8_t evt_type = evt_data[0]; + + switch (evt_type) { +#if defined(CONFIG_BT_BREDR) + case BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI: + case BT_HCI_EVT_EXTENDED_INQUIRY_RESULT: + return true; +#endif + case BT_HCI_EVT_LE_META_EVENT: { + uint8_t subevt_type = evt_data[sizeof(struct bt_hci_evt_hdr)]; + + switch (subevt_type) { + case BT_HCI_EVT_LE_ADVERTISING_REPORT: + return true; +#if defined(CONFIG_BT_EXT_ADV) + case BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT: + { + const struct bt_hci_evt_le_ext_advertising_report *ext_adv = + (void *)&evt_data[3]; + + return (ext_adv->num_reports == 1) && + ((ext_adv->adv_info[0].evt_type & + BT_HCI_LE_ADV_EVT_TYPE_LEGACY) != 0); + } +#endif + default: + return false; + } + } + default: + return false; + } +} + +static struct net_buf *bt_ipc_evt_recv(const uint8_t *data, size_t remaining) +{ + bool discardable; + struct bt_hci_evt_hdr hdr; + struct net_buf *buf; + size_t buf_tailroom; + + if (remaining < sizeof(hdr)) { + LOG_ERR("Not enough data for event header"); + return NULL; + } + + discardable = is_hci_event_discardable(data); + + memcpy((void *)&hdr, data, sizeof(hdr)); + data += sizeof(hdr); + remaining -= sizeof(hdr); + + if (remaining != hdr.len) { + LOG_ERR("Event payload length is not correct"); + return NULL; + } + LOG_DBG("len %u", hdr.len); + + do { + buf = bt_buf_get_evt(hdr.evt, discardable, discardable ? K_NO_WAIT : K_SECONDS(10)); + if (!buf) { + if (discardable) { + LOG_DBG("Discardable buffer pool full, ignoring event"); + return buf; + } + LOG_WRN("Couldn't allocate a buffer after waiting 10 seconds."); + } + } while (!buf); + + net_buf_add_mem(buf, &hdr, sizeof(hdr)); + + buf_tailroom = net_buf_tailroom(buf); + if (buf_tailroom < remaining) { + LOG_ERR("Not enough space in buffer %zu/%zu", remaining, buf_tailroom); + net_buf_unref(buf); + return NULL; + } + + net_buf_add_mem(buf, data, remaining); + + return buf; +} + +static struct net_buf *bt_ipc_acl_recv(const uint8_t *data, size_t remaining) +{ + struct bt_hci_acl_hdr hdr; + struct net_buf *buf; + size_t buf_tailroom; + + if (remaining < sizeof(hdr)) { + LOG_ERR("Not enough data for ACL header"); + return NULL; + } + + buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_NO_WAIT); + if (buf) { + memcpy((void *)&hdr, data, sizeof(hdr)); + data += sizeof(hdr); + remaining -= sizeof(hdr); + + net_buf_add_mem(buf, &hdr, sizeof(hdr)); + } else { + LOG_ERR("No available ACL buffers!"); + return NULL; + } + + if (remaining != sys_le16_to_cpu(hdr.len)) { + LOG_ERR("ACL payload length is not correct"); + net_buf_unref(buf); + return NULL; + } + + buf_tailroom = net_buf_tailroom(buf); + if (buf_tailroom < remaining) { + LOG_ERR("Not enough space in buffer %zu/%zu", remaining, buf_tailroom); + net_buf_unref(buf); + return NULL; + } + + LOG_DBG("len %u", remaining); + net_buf_add_mem(buf, data, remaining); + + return buf; +} + +static struct net_buf *bt_ipc_iso_recv(const uint8_t *data, size_t remaining) +{ + struct bt_hci_iso_hdr hdr; + struct net_buf *buf; + size_t buf_tailroom; + + if (remaining < sizeof(hdr)) { + LOG_ERR("Not enough data for ISO header"); + return NULL; + } + + buf = bt_buf_get_rx(BT_BUF_ISO_IN, K_NO_WAIT); + if (buf) { + memcpy((void *)&hdr, data, sizeof(hdr)); + data += sizeof(hdr); + remaining -= sizeof(hdr); + + net_buf_add_mem(buf, &hdr, sizeof(hdr)); + } else { + LOG_ERR("No available ISO buffers!"); + return NULL; + } + + if (remaining != bt_iso_hdr_len(sys_le16_to_cpu(hdr.len))) { + LOG_ERR("ISO payload length is not correct"); + net_buf_unref(buf); + return NULL; + } + + buf_tailroom = net_buf_tailroom(buf); + if (buf_tailroom < remaining) { + LOG_ERR("Not enough space in buffer %zu/%zu", remaining, buf_tailroom); + net_buf_unref(buf); + return NULL; + } + + LOG_DBG("len %zu", remaining); + net_buf_add_mem(buf, data, remaining); + + return buf; +} + +static void bt_ipc_rx(const uint8_t *data, size_t len) +{ + uint8_t pkt_indicator; + struct net_buf *buf = NULL; + size_t remaining = len; + + LOG_HEXDUMP_DBG(data, len, "ipc data:"); + + pkt_indicator = *data++; + remaining -= sizeof(pkt_indicator); + + switch (pkt_indicator) { + case IPC_EVT: + buf = bt_ipc_evt_recv(data, remaining); + break; + + case IPC_ACL: + buf = bt_ipc_acl_recv(data, remaining); + break; + + case IPC_ISO: + buf = bt_ipc_iso_recv(data, remaining); + break; + + default: + LOG_ERR("Unknown HCI type %u", pkt_indicator); + return; + } + + if (buf) { + LOG_DBG("Calling bt_recv(%p)", buf); + + /* The IPC service does not guarantee that the handler thread + * is cooperative. In particular, the OpenAMP implementation is + * preemtible by default. OTOH, the HCI driver interface requires + * that the bt_recv() function is called from a cooperative + * thread. + * + * Calling `k_sched lock()` has the effect of making the current + * thread cooperative. + */ + k_sched_lock(); + bt_recv(buf); + k_sched_unlock(); + + LOG_HEXDUMP_DBG(buf->data, buf->len, "RX buf payload:"); + } +} + +static int bt_ipc_send(struct net_buf *buf) +{ + int err; + uint8_t pkt_indicator; + + LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len); + + switch (bt_buf_get_type(buf)) { + case BT_BUF_ACL_OUT: + pkt_indicator = IPC_ACL; + break; + case BT_BUF_CMD: + pkt_indicator = IPC_CMD; + break; + case BT_BUF_ISO_OUT: + pkt_indicator = IPC_ISO; + break; + default: + LOG_ERR("Unknown type %u", bt_buf_get_type(buf)); + goto done; + } + net_buf_push_u8(buf, pkt_indicator); + + LOG_HEXDUMP_DBG(buf->data, buf->len, "Final HCI buffer:"); + err = ipc_service_send(&hci_ept, buf->data, buf->len); + if (err < 0) { + LOG_ERR("Failed to send (err %d)", err); + } + +done: + net_buf_unref(buf); + return 0; +} + +static void hci_ept_bound(void *priv) +{ + k_sem_give(&ipc_bound_sem); +} + +static void hci_ept_recv(const void *data, size_t len, void *priv) +{ + bt_ipc_rx(data, len); +} + +static struct ipc_ept_cfg hci_ept_cfg = { + .name = "nrf_bt_hci", + .cb = { + .bound = hci_ept_bound, + .received = hci_ept_recv, + }, +}; + +int __weak bt_hci_transport_setup(const struct device *dev) +{ + ARG_UNUSED(dev); + return 0; +} + +int __weak bt_hci_transport_teardown(const struct device *dev) +{ + ARG_UNUSED(dev); + return 0; +} + +static int bt_ipc_open(void) +{ + int err; + + const struct device *hci_ipc_instance = + DEVICE_DT_GET(DT_CHOSEN(zephyr_bt_hci_ipc)); + + err = bt_hci_transport_setup(NULL); + if (err) { + LOG_ERR("HCI transport setup failed with: %d\n", err); + return err; + } + + LOG_DBG(""); + + err = ipc_service_open_instance(hci_ipc_instance); + if (err && (err != -EALREADY)) { + LOG_ERR("IPC service instance initialization failed: %d\n", err); + return err; + } + + err = ipc_service_register_endpoint(hci_ipc_instance, &hci_ept, &hci_ept_cfg); + if (err) { + LOG_ERR("Registering endpoint failed with %d", err); + return err; + } + + err = k_sem_take(&ipc_bound_sem, IPC_BOUND_TIMEOUT_IN_MS); + if (err) { + LOG_ERR("Endpoint binding failed with %d", err); + return err; + } + + return 0; +} + +static int bt_ipc_close(void) +{ + int err; + + if (IS_ENABLED(CONFIG_BT_HCI_HOST)) { + err = bt_hci_cmd_send_sync(BT_HCI_OP_RESET, NULL, NULL); + if (err) { + LOG_ERR("Sending reset command failed with: %d", err); + return err; + } + } + + err = ipc_service_deregister_endpoint(&hci_ept); + if (err) { + LOG_ERR("Deregistering HCI endpoint failed with: %d", err); + return err; + } + + const struct device *hci_ipc_instance = + DEVICE_DT_GET(DT_CHOSEN(zephyr_bt_hci_ipc)); + + err = ipc_service_close_instance(hci_ipc_instance); + if (err) { + LOG_ERR("Closing IPC service failed with: %d", err); + return err; + } + + err = bt_hci_transport_teardown(NULL); + if (err) { + LOG_ERR("HCI transport teardown failed with: %d", err); + return err; + } + + return 0; +} + +static const struct bt_hci_driver drv = { + .name = "IPC", + .open = bt_ipc_open, + .close = bt_ipc_close, + .send = bt_ipc_send, + .bus = BT_HCI_DRIVER_BUS_IPM, +#if defined(CONFIG_BT_DRIVER_QUIRK_NO_AUTO_DLE) + .quirks = BT_QUIRK_NO_AUTO_DLE, +#endif +}; + +static int bt_ipc_init(void) +{ + + int err; + + err = bt_hci_driver_register(&drv); + if (err < 0) { + LOG_ERR("Failed to register BT HIC driver (err %d)", err); + } + + return err; +} + +SYS_INIT(bt_ipc_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); diff --git a/drivers/bluetooth/hci/ipm_stm32wb.c b/drivers/bluetooth/hci/ipm_stm32wb.c index 9ee261ae3d5..59fef02b2c1 100644 --- a/drivers/bluetooth/hci/ipm_stm32wb.c +++ b/drivers/bluetooth/hci/ipm_stm32wb.c @@ -159,8 +159,12 @@ void TM_EvtReceivedCb(TL_EvtPacket_t *hcievt) k_fifo_put(&ipm_rx_events_fifo, hcievt); } -static void bt_ipm_rx_thread(void) +static void bt_ipm_rx_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + while (true) { bool discardable = false; k_timeout_t timeout = K_FOREVER; @@ -554,7 +558,7 @@ static int bt_ipm_open(void) /* Start RX thread */ k_thread_create(&ipm_rx_thread_data, ipm_rx_stack, K_KERNEL_STACK_SIZEOF(ipm_rx_stack), - (k_thread_entry_t)bt_ipm_rx_thread, NULL, NULL, NULL, + bt_ipm_rx_thread, NULL, NULL, NULL, K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO), 0, K_NO_WAIT); diff --git a/drivers/bluetooth/hci/nrf53_support.c b/drivers/bluetooth/hci/nrf53_support.c new file mode 100644 index 00000000000..7fa91f4eb2f --- /dev/null +++ b/drivers/bluetooth/hci/nrf53_support.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 Pawel Osypiuk + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#if defined(CONFIG_BT_CTLR_DEBUG_PINS_CPUAPP) +#include <../subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/debug.h> +#else +#define DEBUG_SETUP() +#endif /* defined(CONFIG_BT_CTLR_DEBUG_PINS_CPUAPP) */ + +#define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL +#include +LOG_MODULE_REGISTER(bt_hci_nrf53_support); + +int bt_hci_transport_teardown(const struct device *dev) +{ + ARG_UNUSED(dev); + /* Put core into reset */ + NRF_RESET->NETWORK.FORCEOFF = RESET_NETWORK_FORCEOFF_FORCEOFF_Hold; + LOG_DBG("Network MCU reseted."); + + return 0; +} + +int bt_hci_transport_setup(const struct device *dev) +{ + ARG_UNUSED(dev); +#if !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) || defined(CONFIG_BUILD_WITH_TFM) + /* Route Bluetooth Controller Debug Pins */ + DEBUG_SETUP(); +#endif /* !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) || defined(CONFIG_BUILD_WITH_TFM) */ + +#if !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) + /* Retain nRF5340 Network MCU in Secure domain (bus + * accesses by Network MCU will have Secure attribute set). + */ + NRF_SPU->EXTDOMAIN[0].PERM = 1 << 4; +#endif /* !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) */ + + NRF_RESET->NETWORK.FORCEOFF = RESET_NETWORK_FORCEOFF_FORCEOFF_Release; + + return 0; +} diff --git a/drivers/bluetooth/hci/rpmsg.c b/drivers/bluetooth/hci/rpmsg.c deleted file mode 100644 index 704508d5f32..00000000000 --- a/drivers/bluetooth/hci/rpmsg.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright (c) 2019 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -#include -#include -#include - -#include -#include - -#define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL -#include -LOG_MODULE_REGISTER(bt_hci_driver); - -#define RPMSG_CMD 0x01 -#define RPMSG_ACL 0x02 -#define RPMSG_SCO 0x03 -#define RPMSG_EVT 0x04 -#define RPMSG_ISO 0x05 - -#define IPC_BOUND_TIMEOUT_IN_MS K_MSEC(1000) - -static struct ipc_ept hci_ept; -static K_SEM_DEFINE(ipc_bound_sem, 0, 1); - -static bool is_hci_event_discardable(const uint8_t *evt_data) -{ - uint8_t evt_type = evt_data[0]; - - switch (evt_type) { -#if defined(CONFIG_BT_BREDR) - case BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI: - case BT_HCI_EVT_EXTENDED_INQUIRY_RESULT: - return true; -#endif - case BT_HCI_EVT_LE_META_EVENT: { - uint8_t subevt_type = evt_data[sizeof(struct bt_hci_evt_hdr)]; - - switch (subevt_type) { - case BT_HCI_EVT_LE_ADVERTISING_REPORT: - return true; -#if defined(CONFIG_BT_EXT_ADV) - case BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT: - { - const struct bt_hci_evt_le_ext_advertising_report *ext_adv = - (void *)&evt_data[3]; - - return (ext_adv->num_reports == 1) && - ((ext_adv->adv_info[0].evt_type & - BT_HCI_LE_ADV_EVT_TYPE_LEGACY) != 0); - } -#endif - default: - return false; - } - } - default: - return false; - } -} - -static struct net_buf *bt_rpmsg_evt_recv(const uint8_t *data, size_t remaining) -{ - bool discardable; - struct bt_hci_evt_hdr hdr; - struct net_buf *buf; - size_t buf_tailroom; - - if (remaining < sizeof(hdr)) { - LOG_ERR("Not enough data for event header"); - return NULL; - } - - discardable = is_hci_event_discardable(data); - - memcpy((void *)&hdr, data, sizeof(hdr)); - data += sizeof(hdr); - remaining -= sizeof(hdr); - - if (remaining != hdr.len) { - LOG_ERR("Event payload length is not correct"); - return NULL; - } - LOG_DBG("len %u", hdr.len); - - do { - buf = bt_buf_get_evt(hdr.evt, discardable, discardable ? K_NO_WAIT : K_SECONDS(10)); - if (!buf) { - if (discardable) { - LOG_DBG("Discardable buffer pool full, ignoring event"); - return buf; - } - LOG_WRN("Couldn't allocate a buffer after waiting 10 seconds."); - } - } while (!buf); - - net_buf_add_mem(buf, &hdr, sizeof(hdr)); - - buf_tailroom = net_buf_tailroom(buf); - if (buf_tailroom < remaining) { - LOG_ERR("Not enough space in buffer %zu/%zu", remaining, buf_tailroom); - net_buf_unref(buf); - return NULL; - } - - net_buf_add_mem(buf, data, remaining); - - return buf; -} - -static struct net_buf *bt_rpmsg_acl_recv(const uint8_t *data, size_t remaining) -{ - struct bt_hci_acl_hdr hdr; - struct net_buf *buf; - size_t buf_tailroom; - - if (remaining < sizeof(hdr)) { - LOG_ERR("Not enough data for ACL header"); - return NULL; - } - - buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_NO_WAIT); - if (buf) { - memcpy((void *)&hdr, data, sizeof(hdr)); - data += sizeof(hdr); - remaining -= sizeof(hdr); - - net_buf_add_mem(buf, &hdr, sizeof(hdr)); - } else { - LOG_ERR("No available ACL buffers!"); - return NULL; - } - - if (remaining != sys_le16_to_cpu(hdr.len)) { - LOG_ERR("ACL payload length is not correct"); - net_buf_unref(buf); - return NULL; - } - - buf_tailroom = net_buf_tailroom(buf); - if (buf_tailroom < remaining) { - LOG_ERR("Not enough space in buffer %zu/%zu", remaining, buf_tailroom); - net_buf_unref(buf); - return NULL; - } - - LOG_DBG("len %u", remaining); - net_buf_add_mem(buf, data, remaining); - - return buf; -} - -static struct net_buf *bt_rpmsg_iso_recv(const uint8_t *data, size_t remaining) -{ - struct bt_hci_iso_hdr hdr; - struct net_buf *buf; - size_t buf_tailroom; - - if (remaining < sizeof(hdr)) { - LOG_ERR("Not enough data for ISO header"); - return NULL; - } - - buf = bt_buf_get_rx(BT_BUF_ISO_IN, K_NO_WAIT); - if (buf) { - memcpy((void *)&hdr, data, sizeof(hdr)); - data += sizeof(hdr); - remaining -= sizeof(hdr); - - net_buf_add_mem(buf, &hdr, sizeof(hdr)); - } else { - LOG_ERR("No available ISO buffers!"); - return NULL; - } - - if (remaining != bt_iso_hdr_len(sys_le16_to_cpu(hdr.len))) { - LOG_ERR("ISO payload length is not correct"); - net_buf_unref(buf); - return NULL; - } - - buf_tailroom = net_buf_tailroom(buf); - if (buf_tailroom < remaining) { - LOG_ERR("Not enough space in buffer %zu/%zu", remaining, buf_tailroom); - net_buf_unref(buf); - return NULL; - } - - LOG_DBG("len %zu", remaining); - net_buf_add_mem(buf, data, remaining); - - return buf; -} - -static void bt_rpmsg_rx(const uint8_t *data, size_t len) -{ - uint8_t pkt_indicator; - struct net_buf *buf = NULL; - size_t remaining = len; - - LOG_HEXDUMP_DBG(data, len, "RPMsg data:"); - - pkt_indicator = *data++; - remaining -= sizeof(pkt_indicator); - - switch (pkt_indicator) { - case RPMSG_EVT: - buf = bt_rpmsg_evt_recv(data, remaining); - break; - - case RPMSG_ACL: - buf = bt_rpmsg_acl_recv(data, remaining); - break; - - case RPMSG_ISO: - buf = bt_rpmsg_iso_recv(data, remaining); - break; - - default: - LOG_ERR("Unknown HCI type %u", pkt_indicator); - return; - } - - if (buf) { - LOG_DBG("Calling bt_recv(%p)", buf); - - bt_recv(buf); - - LOG_HEXDUMP_DBG(buf->data, buf->len, "RX buf payload:"); - } -} - -static int bt_rpmsg_send(struct net_buf *buf) -{ - int err; - uint8_t pkt_indicator; - - LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len); - - switch (bt_buf_get_type(buf)) { - case BT_BUF_ACL_OUT: - pkt_indicator = RPMSG_ACL; - break; - case BT_BUF_CMD: - pkt_indicator = RPMSG_CMD; - break; - case BT_BUF_ISO_OUT: - pkt_indicator = RPMSG_ISO; - break; - default: - LOG_ERR("Unknown type %u", bt_buf_get_type(buf)); - goto done; - } - net_buf_push_u8(buf, pkt_indicator); - - LOG_HEXDUMP_DBG(buf->data, buf->len, "Final HCI buffer:"); - err = ipc_service_send(&hci_ept, buf->data, buf->len); - if (err < 0) { - LOG_ERR("Failed to send (err %d)", err); - } - -done: - net_buf_unref(buf); - return 0; -} - -static void hci_ept_bound(void *priv) -{ - k_sem_give(&ipc_bound_sem); -} - -static void hci_ept_recv(const void *data, size_t len, void *priv) -{ - bt_rpmsg_rx(data, len); -} - -static struct ipc_ept_cfg hci_ept_cfg = { - .name = "nrf_bt_hci", - .cb = { - .bound = hci_ept_bound, - .received = hci_ept_recv, - }, -}; - -static int bt_rpmsg_open(void) -{ - int err; - const struct device *hci_ipc_instance = - DEVICE_DT_GET(DT_CHOSEN(zephyr_bt_hci_rpmsg_ipc)); - - LOG_DBG(""); - - err = ipc_service_open_instance(hci_ipc_instance); - if (err && (err != -EALREADY)) { - LOG_ERR("IPC service instance initialization failed: %d\n", err); - return err; - } - - err = ipc_service_register_endpoint(hci_ipc_instance, &hci_ept, &hci_ept_cfg); - if (err) { - LOG_ERR("Registering endpoint failed with %d", err); - return err; - } - - err = k_sem_take(&ipc_bound_sem, IPC_BOUND_TIMEOUT_IN_MS); - if (err) { - LOG_ERR("Endpoint binding failed with %d", err); - return err; - } - - return 0; -} - -static const struct bt_hci_driver drv = { - .name = "RPMsg", - .open = bt_rpmsg_open, - .send = bt_rpmsg_send, - .bus = BT_HCI_DRIVER_BUS_IPM, -#if defined(CONFIG_BT_DRIVER_QUIRK_NO_AUTO_DLE) - .quirks = BT_QUIRK_NO_AUTO_DLE, -#endif -}; - -static int bt_rpmsg_init(void) -{ - - int err; - - err = bt_hci_driver_register(&drv); - if (err < 0) { - LOG_ERR("Failed to register BT HIC driver (err %d)", err); - } - - return err; -} - -SYS_INIT(bt_rpmsg_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); diff --git a/drivers/bluetooth/hci/slz_hci.c b/drivers/bluetooth/hci/slz_hci.c index 59bd8ba5ff9..0526cb02c40 100644 --- a/drivers/bluetooth/hci/slz_hci.c +++ b/drivers/bluetooth/hci/slz_hci.c @@ -16,11 +16,14 @@ #include LOG_MODULE_REGISTER(bt_hci_driver_slz); -#define SL_BT_CONFIG_ACCEPT_LIST_SIZE 1 -#define SL_BT_CONFIG_MAX_CONNECTIONS 1 -#define SL_BT_CONFIG_USER_ADVERTISERS 1 -#define SL_BT_CONTROLLER_BUFFER_MEMORY CONFIG_BT_SILABS_HCI_BUFFER_MEMORY -#define SL_BT_SILABS_LL_STACK_SIZE 1024 +#define SL_BT_CONFIG_ACCEPT_LIST_SIZE 1 +#define SL_BT_CONFIG_MAX_CONNECTIONS 1 +#define SL_BT_CONFIG_USER_ADVERTISERS 1 +#define SL_BT_CONTROLLER_BUFFER_MEMORY CONFIG_BT_SILABS_HCI_BUFFER_MEMORY +#define SL_BT_CONTROLLER_LE_BUFFER_SIZE_MAX CONFIG_BT_BUF_ACL_TX_COUNT +#define SL_BT_CONTROLLER_COMPLETED_PACKETS_THRESHOLD 1 +#define SL_BT_CONTROLLER_COMPLETED_PACKETS_EVENTS_TIMEOUT 3 +#define SL_BT_SILABS_LL_STACK_SIZE 1024 static K_KERNEL_STACK_DEFINE(slz_ll_stack, SL_BT_SILABS_LL_STACK_SIZE); static struct k_thread slz_ll_thread; @@ -114,6 +117,15 @@ static int slz_bt_send(struct net_buf *buf) return rv; } +static void slz_thread_func(void *p1, void *p2, void *p3) +{ + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + slz_ll_thread_func(); +} + static int slz_bt_open(void) { int ret; @@ -121,7 +133,7 @@ static int slz_bt_open(void) /* Start RX thread */ k_thread_create(&slz_ll_thread, slz_ll_stack, K_KERNEL_STACK_SIZEOF(slz_ll_stack), - (k_thread_entry_t)slz_ll_thread_func, NULL, NULL, NULL, + slz_thread_func, NULL, NULL, NULL, K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO), 0, K_NO_WAIT); @@ -135,6 +147,8 @@ static int slz_bt_open(void) return -ENOMEM; } + sl_btctrl_configure_le_buffer_size(SL_BT_CONTROLLER_LE_BUFFER_SIZE_MAX); + ret = sl_btctrl_init_ll(); if (ret) { LOG_ERR("Bluetooth link layer init failed %d", ret); @@ -155,6 +169,10 @@ static int slz_bt_open(void) goto deinit; } + sl_btctrl_configure_completed_packets_reporting( + SL_BT_CONTROLLER_COMPLETED_PACKETS_THRESHOLD, + SL_BT_CONTROLLER_COMPLETED_PACKETS_EVENTS_TIMEOUT); + sl_bthci_init_upper(); sl_btctrl_hci_parser_init_default(); sl_btctrl_hci_parser_init_conn(); diff --git a/drivers/bluetooth/hci/spi.c b/drivers/bluetooth/hci/spi.c index b86f9ba35fb..32b50ea191f 100644 --- a/drivers/bluetooth/hci/spi.c +++ b/drivers/bluetooth/hci/spi.c @@ -41,6 +41,7 @@ LOG_MODULE_REGISTER(bt_driver); #define EVT_HEADER_TYPE 0 #define EVT_HEADER_EVENT 1 #define EVT_HEADER_SIZE 2 +#define EVT_LE_META_SUBEVENT 3 #define EVT_VENDOR_CODE_LSB 3 #define EVT_VENDOR_CODE_MSB 4 @@ -84,30 +85,6 @@ static K_SEM_DEFINE(sem_busy, 1, 1); static K_KERNEL_STACK_DEFINE(spi_rx_stack, CONFIG_BT_DRV_RX_STACK_SIZE); static struct k_thread spi_rx_thread_data; -#if defined(CONFIG_BT_HCI_DRIVER_LOG_LEVEL_DBG) -#include -static inline void spi_dump_message(const uint8_t *pre, uint8_t *buf, - uint8_t size) -{ - uint8_t i, c; - - printk("%s (%d): ", pre, size); - for (i = 0U; i < size; i++) { - c = buf[i]; - printk("%x ", c); - if (c >= 31U && c <= 126U) { - printk("[%c] ", c); - } else { - printk("[.] "); - } - } - printk("\n"); -} -#else -static inline -void spi_dump_message(const uint8_t *pre, uint8_t *buf, uint8_t size) {} -#endif - #if defined(CONFIG_BT_SPI_BLUENRG) /* Define a limit when reading IRQ high */ /* It can be required to be increased for */ @@ -129,17 +106,8 @@ struct bluenrg_aci_cmd_ll_param { static int bt_spi_send_aci_config_data_controller_mode(void); #endif /* CONFIG_BT_BLUENRG_ACI */ -#if defined(CONFIG_BT_SPI_BLUENRG) -/* In case of BlueNRG-MS, it is necessary to prevent SPI driver to release CS, - * and instead, let current driver manage CS release. see kick_cs()/release_cs() - * So, add SPI_HOLD_ON_CS to operation field. - */ -static const struct spi_dt_spec bus = SPI_DT_SPEC_INST_GET( - 0, SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8) | SPI_HOLD_ON_CS, 0); -#else static const struct spi_dt_spec bus = SPI_DT_SPEC_INST_GET( 0, SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8), 0); -#endif static struct spi_buf spi_tx_buf; static struct spi_buf spi_rx_buf; @@ -208,12 +176,6 @@ static bool bt_spi_handle_vendor_evt(uint8_t *msg) * know the amount of byte to read. * (See section 5.2 of BlueNRG-MS datasheet) */ -static int configure_cs(void) -{ - /* Configure pin as output and set to inactive */ - return gpio_pin_configure_dt(&bus.config.cs.gpio, GPIO_OUTPUT_INACTIVE); -} - static void kick_cs(void) { gpio_pin_set_dt(&bus.config.cs.gpio, 0); @@ -253,7 +215,6 @@ static bool exit_irq_high_loop(void) #else -#define configure_cs(...) 0 #define kick_cs(...) #define release_cs(...) #define irq_pin_high(...) 0 @@ -285,17 +246,76 @@ static int bt_spi_send_aci_config_data_controller_mode(void) } #endif /* CONFIG_BT_BLUENRG_ACI */ -static void bt_spi_rx_thread(void) +static struct net_buf *bt_spi_rx_buf_construct(uint8_t *msg) { bool discardable = false; k_timeout_t timeout = K_FOREVER; + struct bt_hci_acl_hdr acl_hdr; struct net_buf *buf; + int len; + + switch (msg[PACKET_TYPE]) { + case HCI_EVT: + switch (msg[EVT_HEADER_EVENT]) { + case BT_HCI_EVT_VENDOR: + /* Run event through interface handler */ + if (bt_spi_handle_vendor_evt(msg)) { + return NULL; + } + /* Event has not yet been handled */ + __fallthrough; + default: + if (msg[EVT_HEADER_EVENT] == BT_HCI_EVT_LE_META_EVENT && + (msg[EVT_LE_META_SUBEVENT] == BT_HCI_EVT_LE_ADVERTISING_REPORT)) { + discardable = true; + timeout = K_NO_WAIT; + } + buf = bt_buf_get_evt(msg[EVT_HEADER_EVENT], + discardable, timeout); + if (!buf) { + LOG_DBG("Discard adv report due to insufficient buf"); + return NULL; + } + } + + len = sizeof(struct bt_hci_evt_hdr) + msg[EVT_HEADER_SIZE]; + if (len > net_buf_tailroom(buf)) { + LOG_ERR("Event too long: %d", len); + net_buf_unref(buf); + return NULL; + } + net_buf_add_mem(buf, &msg[1], len); + break; + case HCI_ACL: + buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER); + memcpy(&acl_hdr, &msg[1], sizeof(acl_hdr)); + len = sizeof(acl_hdr) + sys_le16_to_cpu(acl_hdr.len); + if (len > net_buf_tailroom(buf)) { + LOG_ERR("ACL too long: %d", len); + net_buf_unref(buf); + return NULL; + } + net_buf_add_mem(buf, &msg[1], len); + break; + default: + LOG_ERR("Unknown BT buf type %d", msg[0]); + return NULL; + } + + return buf; +} + +static void bt_spi_rx_thread(void *p1, void *p2, void *p3) +{ + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + uint8_t header_master[5] = { SPI_READ, 0x00, 0x00, 0x00, 0x00 }; uint8_t header_slave[5]; - struct bt_hci_acl_hdr acl_hdr; + struct net_buf *buf; uint8_t size = 0U; int ret; - int len; (void)memset(&txmsg, 0xFF, SPI_MAX_MSG_LEN); while (true) { @@ -345,60 +365,15 @@ static void bt_spi_rx_thread(void) continue; } - spi_dump_message("RX:ed", rxmsg, size); - - switch (rxmsg[PACKET_TYPE]) { - case HCI_EVT: - switch (rxmsg[EVT_HEADER_EVENT]) { - case BT_HCI_EVT_VENDOR: - /* Run event through interface handler */ - if (bt_spi_handle_vendor_evt(rxmsg)) { - continue; - }; - /* Event has not yet been handled */ - __fallthrough; - default: - if (rxmsg[1] == BT_HCI_EVT_LE_META_EVENT && - (rxmsg[3] == BT_HCI_EVT_LE_ADVERTISING_REPORT)) { - discardable = true; - timeout = K_NO_WAIT; - } - - buf = bt_buf_get_evt(rxmsg[EVT_HEADER_EVENT], - discardable, timeout); - if (!buf) { - LOG_DBG("Discard adv report due to insufficient " - "buf"); - continue; - } - } + LOG_HEXDUMP_DBG(rxmsg, size, "SPI RX"); - len = sizeof(struct bt_hci_evt_hdr) + rxmsg[EVT_HEADER_SIZE]; - if (len > net_buf_tailroom(buf)) { - LOG_ERR("Event too long: %d", len); - net_buf_unref(buf); - continue; - } - net_buf_add_mem(buf, &rxmsg[1], len); - break; - case HCI_ACL: - buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER); - memcpy(&acl_hdr, &rxmsg[1], sizeof(acl_hdr)); - len = sizeof(acl_hdr) + sys_le16_to_cpu(acl_hdr.len); - if (len > net_buf_tailroom(buf)) { - LOG_ERR("ACL too long: %d", len); - net_buf_unref(buf); - continue; - } - net_buf_add_mem(buf, &rxmsg[1], len); - break; - default: - LOG_ERR("Unknown BT buf type %d", rxmsg[0]); - continue; + /* Construct net_buf from SPI data */ + buf = bt_spi_rx_buf_construct(rxmsg); + if (buf) { + /* Handle the received HCI data */ + bt_recv(buf); } - bt_recv(buf); - /* On BlueNRG-MS, host is expected to read */ /* as long as IRQ pin is high */ } while (irq_pin_high()); @@ -407,7 +382,9 @@ static void bt_spi_rx_thread(void) static int bt_spi_send(struct net_buf *buf) { - uint8_t header[5] = { SPI_WRITE, 0x00, 0x00, 0x00, 0x00 }; + uint8_t header_tx[5] = { SPI_WRITE, 0x00, 0x00, 0x00, 0x00 }; + uint8_t header_rx[5]; + uint8_t rx_first[1]; int ret; LOG_DBG(""); @@ -437,22 +414,31 @@ static int bt_spi_send(struct net_buf *buf) /* Poll sanity values until device has woken-up */ do { kick_cs(); - ret = bt_spi_transceive(header, 5, rxmsg, 5); + ret = bt_spi_transceive(header_tx, 5, header_rx, 5); /* - * RX Header (rxmsg) must contain a sanity check Byte and size + * RX Header must contain a sanity check Byte and size * information. If it does not contain BOTH then it is * sleeping or still in the initialisation stage (waking-up). */ - } while ((rxmsg[STATUS_HEADER_READY] != READY_NOW || - (rxmsg[1] | rxmsg[2] | rxmsg[3] | rxmsg[4]) == 0U) && !ret); + } while ((header_rx[STATUS_HEADER_READY] != READY_NOW || + (header_rx[1] | header_rx[2] | header_rx[3] | header_rx[4]) == 0U) && !ret); if (!ret) { + /* Delay here is rounded up to next tick */ + k_sleep(K_USEC(DATA_DELAY_US)); /* Transmit the message */ - do { + while (true) { ret = bt_spi_transceive(buf->data, buf->len, - rxmsg, buf->len); - } while (rxmsg[0] == 0U && !ret); + rx_first, 1); + if (rx_first[0] != 0U || ret) { + break; + } + /* Consider increasing controller-data-delay-us + * if this message is extremely common. + */ + LOG_DBG("Controller not ready for SPI transaction of %d bytes", buf->len); + } } release_cs(); @@ -464,7 +450,7 @@ static int bt_spi_send(struct net_buf *buf) goto out; } - spi_dump_message("TX:ed", buf->data, buf->len); + LOG_HEXDUMP_DBG(buf->data, buf->len, "SPI TX"); #if defined(CONFIG_BT_SPI_BLUENRG) /* @@ -516,7 +502,7 @@ static int bt_spi_open(void) /* Start RX thread */ k_thread_create(&spi_rx_thread_data, spi_rx_stack, K_KERNEL_STACK_SIZEOF(spi_rx_stack), - (k_thread_entry_t)bt_spi_rx_thread, NULL, NULL, NULL, + bt_spi_rx_thread, NULL, NULL, NULL, K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO), 0, K_NO_WAIT); @@ -544,10 +530,6 @@ static int bt_spi_init(void) return -ENODEV; } - if (configure_cs()) { - return -EIO; - } - if (!gpio_is_ready_dt(&irq_gpio)) { LOG_ERR("IRQ GPIO device not ready"); return -ENODEV; diff --git a/drivers/cache/cache_handlers.c b/drivers/cache/cache_handlers.c index 99d7cec501c..2005124136f 100644 --- a/drivers/cache/cache_handlers.c +++ b/drivers/cache/cache_handlers.c @@ -5,11 +5,11 @@ */ #include -#include +#include static inline int z_vrfy_sys_cache_data_flush_range(void *addr, size_t size) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(addr, size)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(addr, size)); return z_impl_sys_cache_data_flush_range(addr, size); } @@ -17,7 +17,7 @@ static inline int z_vrfy_sys_cache_data_flush_range(void *addr, size_t size) static inline int z_vrfy_sys_cache_data_invd_range(void *addr, size_t size) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(addr, size)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(addr, size)); return z_impl_sys_cache_data_invd_range(addr, size); } @@ -25,7 +25,7 @@ static inline int z_vrfy_sys_cache_data_invd_range(void *addr, size_t size) static inline int z_vrfy_sys_cache_data_flush_and_invd_range(void *addr, size_t size) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(addr, size)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(addr, size)); return z_impl_sys_cache_data_flush_and_invd_range(addr, size); } diff --git a/drivers/can/CMakeLists.txt b/drivers/can/CMakeLists.txt index 4c97d22265c..c7d9de93f2e 100644 --- a/drivers/can/CMakeLists.txt +++ b/drivers/can/CMakeLists.txt @@ -10,13 +10,16 @@ zephyr_library_sources_ifdef(CONFIG_CAN_FAKE can_fake.c) zephyr_library_sources_ifdef(CONFIG_CAN_LOOPBACK can_loopback.c) zephyr_library_sources_ifdef(CONFIG_CAN_MCAN can_mcan.c) zephyr_library_sources_ifdef(CONFIG_CAN_MCP2515 can_mcp2515.c) +zephyr_library_sources_ifdef(CONFIG_CAN_MCP251XFD can_mcp251xfd.c) zephyr_library_sources_ifdef(CONFIG_CAN_MCUX_FLEXCAN can_mcux_flexcan.c) zephyr_library_sources_ifdef(CONFIG_CAN_SAM can_sam.c) zephyr_library_sources_ifdef(CONFIG_CAN_SAM0 can_sam0.c) zephyr_library_sources_ifdef(CONFIG_CAN_STM32_BXCAN can_stm32_bxcan.c) zephyr_library_sources_ifdef(CONFIG_CAN_STM32_FDCAN can_stm32_fdcan.c) zephyr_library_sources_ifdef(CONFIG_CAN_STM32H7_FDCAN can_stm32h7_fdcan.c) +zephyr_library_sources_ifdef(CONFIG_CAN_TCAN4X5X can_tcan4x5x.c) zephyr_library_sources_ifdef(CONFIG_CAN_RCAR can_rcar.c) +zephyr_library_sources_ifdef(CONFIG_CAN_NUMAKER can_numaker.c) if(CONFIG_CAN_NATIVE_POSIX_LINUX) if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL Linux) diff --git a/drivers/can/Kconfig b/drivers/can/Kconfig index ab8dcf94fe2..ed0818d3508 100644 --- a/drivers/can/Kconfig +++ b/drivers/can/Kconfig @@ -25,7 +25,6 @@ config CAN_INIT_PRIORITY config CAN_SHELL bool "CAN shell" - default y depends on SHELL select POLL help @@ -56,9 +55,9 @@ config CAN_STATS Enable CAN controller device statistics. config CAN_FD_MODE - bool "CAN-FD" + bool "CAN FD" help - Enable CAN-FD support. Not all CAN controllers support CAN-FD. + Enable CAN FD support. Not all CAN controllers support CAN FD. config CAN_RX_TIMESTAMP bool "Receiving timestamps" @@ -92,6 +91,7 @@ source "drivers/can/Kconfig.mcux" source "drivers/can/Kconfig.mcp2515" source "drivers/can/Kconfig.mcan" source "drivers/can/Kconfig.rcar" +source "drivers/can/Kconfig.numaker" source "drivers/can/Kconfig.loopback" source "drivers/can/Kconfig.native_posix_linux" source "drivers/can/Kconfig.sja1000" @@ -99,6 +99,8 @@ source "drivers/can/Kconfig.esp32" source "drivers/can/Kconfig.kvaser" source "drivers/can/Kconfig.fake" source "drivers/can/Kconfig.nxp_s32" +source "drivers/can/Kconfig.tcan4x5x" +source "drivers/can/Kconfig.mcp251xfd" source "drivers/can/transceiver/Kconfig" diff --git a/drivers/can/Kconfig.mcan b/drivers/can/Kconfig.mcan index 6b25df34567..83cf6ffaba0 100644 --- a/drivers/can/Kconfig.mcan +++ b/drivers/can/Kconfig.mcan @@ -9,7 +9,7 @@ config CAN_MCAN Enable Bosch m_can driver. This driver supports the Bosch m_can IP. This IP is built into the STM32G4, STM32G0, STM32H7, and the Microchip SAM controllers with - CAN-FD. + CAN FD. if CAN_MCAN diff --git a/drivers/can/Kconfig.mcp251xfd b/drivers/can/Kconfig.mcp251xfd new file mode 100644 index 00000000000..128becf8e95 --- /dev/null +++ b/drivers/can/Kconfig.mcp251xfd @@ -0,0 +1,61 @@ +# MCP25XXFD CAN configuration options + +# Copyright (c) 2020 Abram Early +# Copyright (c) 2023 Andriy Gelman +# SPDX-License-Identifier: Apache-2.0 + +config CAN_MCP251XFD + bool "MCP25XXFD CAN Driver" + default y + depends on DT_HAS_MICROCHIP_MCP251XFD_ENABLED + select CRC + select SPI + help + Enable MCP25XXFD CAN Driver + +if CAN_MCP251XFD + +config CAN_MCP251XFD_MAX_TX_QUEUE + int "Maximum number of queued messages" + default 8 + range 1 32 + help + Defines the array size of transmit callback pointers and semaphores, + as well as the number of messages in the TX queue. + +config CAN_MCP251XFD_RX_FIFO_ITEMS + int "Number of CAN messages in the RX fifo" + default 16 + range 1 32 + help + Defines the number of CAN messages in the RX fifo. + +config CAN_MCP251XFD_INT_THREAD_STACK_SIZE + int "Stack size for interrupt handler" + default 768 + help + Size of the stack used for internal thread which is ran for + interrupt handling and incoming packets. + +config CAN_MCP251XFD_INT_THREAD_PRIO + int "Priority for interrupt handler" + default 2 + help + Thread priority of the interrupt handler. A higher number implies a + higher priority. The thread is cooperative and will not be interrupted by + another thread until execution is released. + +config CAN_MCP251XFD_READ_CRC_RETRIES + int "Number of retries during SFR register read" + default 5 + help + Number of retries during SFR register read if CRC fails. + +config CAN_MAX_FILTER + int "Maximum number of concurrent active filters" + default 5 + range 1 32 + help + Maximum number of filters supported by the can_add_rx_callback() API call. + +endif # CAN_MCP251XFD diff --git a/drivers/can/Kconfig.mcux b/drivers/can/Kconfig.mcux index 6ccaad15e45..5983be36c8a 100644 --- a/drivers/can/Kconfig.mcux +++ b/drivers/can/Kconfig.mcux @@ -19,12 +19,19 @@ config CAN_MCUX_FLEXCAN_FD default y depends on DT_HAS_NXP_FLEXCAN_FD_ENABLED && CAN_FD_MODE help - Enable support for CAN-FD capable NXP FlexCAN devices. + Enable support for CAN FD capable NXP FlexCAN devices. + +config CAN_MCUX_FLEXCAN_WAIT_TIMEOUT + int "Maximum number of wait loop iterations" + default 10000 + help + Maximum number of wait loop iterations for the MCUX FlexCAN HAL when entering/leaving + freeze mode. config CAN_MAX_MB int "Maximum number of message buffers for concurrent active instances" default 16 - depends on SOC_SERIES_S32K3_M7 + depends on SOC_SERIES_S32K3XX range 1 96 help Defines maximum number of message buffers for concurrent active instances. @@ -35,7 +42,7 @@ config CAN_MAX_FILTER range 1 15 if SOC_SERIES_KINETIS_KE1XF || SOC_SERIES_KINETIS_K6X range 1 13 if SOC_SERIES_IMX_RT && CAN_MCUX_FLEXCAN_FD range 1 63 if SOC_SERIES_IMX_RT - range 1 96 if SOC_SERIES_S32K3_M7 + range 1 96 if SOC_SERIES_S32K3XX help Defines maximum number of concurrent active RX filters diff --git a/drivers/can/Kconfig.numaker b/drivers/can/Kconfig.numaker new file mode 100644 index 00000000000..23de8ab50ec --- /dev/null +++ b/drivers/can/Kconfig.numaker @@ -0,0 +1,13 @@ +# NuMaker CAN(-FD) driver configuration options + +# Copyright (c) 2023 Nuvoton Technology Corporation +# SPDX-License-Identifier: Apache-2.0 + +config CAN_NUMAKER + bool "Nuvoton NuMaker CAN FD driver" + default y + select CAN_MCAN + depends on DT_HAS_NUVOTON_NUMAKER_CANFD_ENABLED + depends on SOC_SERIES_M46X + help + Enables Nuvoton NuMaker CAN FD driver, using Bosch M_CAN diff --git a/drivers/can/Kconfig.nxp_s32 b/drivers/can/Kconfig.nxp_s32 index a8102d8e958..53c1ffc2b8b 100644 --- a/drivers/can/Kconfig.nxp_s32 +++ b/drivers/can/Kconfig.nxp_s32 @@ -1,10 +1,11 @@ -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # SPDX-License-Identifier: Apache-2.0 config CAN_NXP_S32_CANXL bool "NXP S32 CANXL driver" default y depends on DT_HAS_NXP_S32_CANXL_ENABLED + select CLOCK_CONTROL help Enable support for NXP S32 CANXL driver. diff --git a/drivers/can/Kconfig.tcan4x5x b/drivers/can/Kconfig.tcan4x5x new file mode 100644 index 00000000000..4eeddb35cc0 --- /dev/null +++ b/drivers/can/Kconfig.tcan4x5x @@ -0,0 +1,29 @@ +# TCAN4x5x configuration options + +# Copyright (c) 2023 Vestas Wind Systems A/S +# SPDX-License-Identifier: Apache-2.0 + +config CAN_TCAN4X5X + bool "TI TCAN4x5x" + default y + depends on DT_HAS_TI_TCAN4X5X_ENABLED + select CAN_MCAN + select SPI + help + Enable support for the Texas Instruments TCAN4x5x. + +if CAN_TCAN4X5X + +config CAN_TCAN4X5X_THREAD_STACK_SIZE + int "Stack size for the TCAN4x5x interrupt thread" + default 1024 + help + Size of the stack used for the thread handling interrupts and dispatching callbacks. + +config CAN_TCAN4X5X_THREAD_PRIO + int "Priority for the TCAN4x5x interrupt thread" + default 0 + help + Priority level for the thread handling interrupts and dispatching callbacks. + +endif # CAN_TCAN4X5X diff --git a/drivers/can/can_common.c b/drivers/can/can_common.c index c7902ee9d20..6541c977255 100644 --- a/drivers/can/can_common.c +++ b/drivers/can/can_common.c @@ -170,7 +170,7 @@ static int can_calc_timing_int(uint32_t core_clock, struct can_timing *res, CAN_SYNC_SEG; uint16_t sp_err_min = UINT16_MAX; int sp_err; - struct can_timing tmp_res; + struct can_timing tmp_res = { 0 }; if (bitrate == 0 || sp >= 1000) { return -EINVAL; @@ -209,6 +209,10 @@ static int can_calc_timing_int(uint32_t core_clock, struct can_timing *res, LOG_DBG("SP error: %d 1/1000", sp_err_min); } + /* Calculate default sjw as phase_seg2 / 2 and clamp the result */ + res->sjw = MIN(res->phase_seg1, res->phase_seg2 / 2); + res->sjw = CLAMP(res->sjw, min->sjw, max->sjw); + return sp_err_min == UINT16_MAX ? -ENOTSUP : (int)sp_err_min; } @@ -300,18 +304,18 @@ static int check_timing_in_range(const struct can_timing *timing, const struct can_timing *min, const struct can_timing *max) { - if (timing->sjw != CAN_SJW_NO_CHANGE && - !IN_RANGE(timing->sjw, min->sjw, max->sjw)) { - return -ENOTSUP; - } - - if (!IN_RANGE(timing->prop_seg, min->prop_seg, max->prop_seg) || + if (!IN_RANGE(timing->sjw, min->sjw, max->sjw) || + !IN_RANGE(timing->prop_seg, min->prop_seg, max->prop_seg) || !IN_RANGE(timing->phase_seg1, min->phase_seg1, max->phase_seg1) || !IN_RANGE(timing->phase_seg2, min->phase_seg2, max->phase_seg2) || !IN_RANGE(timing->prescaler, min->prescaler, max->prescaler)) { return -ENOTSUP; } + if ((timing->sjw > timing->phase_seg1) || (timing->sjw > timing->phase_seg2)) { + return -ENOTSUP; + } + return 0; } @@ -333,7 +337,7 @@ int z_impl_can_set_timing(const struct device *dev, int z_impl_can_set_bitrate(const struct device *dev, uint32_t bitrate) { - struct can_timing timing; + struct can_timing timing = { 0 }; uint32_t max_bitrate; uint16_t sample_pnt; int ret; @@ -360,8 +364,6 @@ int z_impl_can_set_bitrate(const struct device *dev, uint32_t bitrate) return -ERANGE; } - timing.sjw = CAN_SJW_NO_CHANGE; - return can_set_timing(dev, &timing); } @@ -388,7 +390,7 @@ int z_impl_can_set_timing_data(const struct device *dev, int z_impl_can_set_bitrate_data(const struct device *dev, uint32_t bitrate_data) { - struct can_timing timing_data; + struct can_timing timing_data = { 0 }; uint32_t max_bitrate; uint16_t sample_pnt; int ret; @@ -415,8 +417,6 @@ int z_impl_can_set_bitrate_data(const struct device *dev, uint32_t bitrate_data) return -ERANGE; } - timing_data.sjw = CAN_SJW_NO_CHANGE; - return can_set_timing_data(dev, &timing_data); } #endif /* CONFIG_CAN_FD_MODE */ diff --git a/drivers/can/can_esp32_twai.c b/drivers/can/can_esp32_twai.c index 794b3bdb8cd..2fd379d0049 100644 --- a/drivers/can/can_esp32_twai.c +++ b/drivers/can/can_esp32_twai.c @@ -118,14 +118,6 @@ static int can_esp32_twai_set_timing(const struct device *dev, const struct can_ struct can_sja1000_data *data = dev->data; uint8_t btr0; uint8_t btr1; - uint8_t sjw; - - __ASSERT_NO_MSG(timing->sjw == CAN_SJW_NO_CHANGE || - (timing->sjw >= 0x1 && timing->sjw <= 0x4)); - __ASSERT_NO_MSG(timing->prop_seg == 0); - __ASSERT_NO_MSG(timing->phase_seg1 >= 0x1 && timing->phase_seg1 <= 0x10); - __ASSERT_NO_MSG(timing->phase_seg2 >= 0x1 && timing->phase_seg2 <= 0x8); - __ASSERT_NO_MSG(timing->prescaler >= 0x1 && timing->prescaler <= 0x2000); if (data->started) { return -EBUSY; @@ -133,15 +125,8 @@ static int can_esp32_twai_set_timing(const struct device *dev, const struct can_ k_mutex_lock(&data->mod_lock, K_FOREVER); - if (timing->sjw == CAN_SJW_NO_CHANGE) { - sjw = data->sjw; - } else { - sjw = timing->sjw; - data->sjw = timing->sjw; - } - btr0 = TWAI_BAUD_PRESC_PREP(timing->prescaler - 1) | - TWAI_SYNC_JUMP_WIDTH_PREP(sjw - 1); + TWAI_SYNC_JUMP_WIDTH_PREP(timing->sjw - 1); btr1 = TWAI_TIME_SEG1_PREP(timing->phase_seg1 - 1) | TWAI_TIME_SEG2_PREP(timing->phase_seg2 - 1); @@ -301,8 +286,8 @@ const struct can_driver_api can_esp32_twai_driver_api = { static struct can_sja1000_data can_sja1000_data_##inst = \ CAN_SJA1000_DATA_INITIALIZER(NULL); \ \ - DEVICE_DT_INST_DEFINE(inst, can_esp32_twai_init, NULL, &can_sja1000_data_##inst, \ - &can_sja1000_config_##inst, POST_KERNEL, \ - CONFIG_CAN_INIT_PRIORITY, &can_esp32_twai_driver_api); + CAN_DEVICE_DT_INST_DEFINE(inst, can_esp32_twai_init, NULL, &can_sja1000_data_##inst, \ + &can_sja1000_config_##inst, POST_KERNEL, \ + CONFIG_CAN_INIT_PRIORITY, &can_esp32_twai_driver_api); DT_INST_FOREACH_STATUS_OKAY(CAN_ESP32_TWAI_INIT) diff --git a/drivers/can/can_fake.c b/drivers/can/can_fake.c index 5fc94319159..88d7780eaad 100644 --- a/drivers/can/can_fake.c +++ b/drivers/can/can_fake.c @@ -9,9 +9,9 @@ #include #include -#ifdef CONFIG_ZTEST_NEW_API +#ifdef CONFIG_ZTEST #include -#endif /* CONFIG_ZTEST_NEW_API */ +#endif /* CONFIG_ZTEST */ #define DT_DRV_COMPAT zephyr_fake_can @@ -46,7 +46,7 @@ DEFINE_FAKE_VOID_FUNC(fake_can_set_state_change_callback, const struct device *, DEFINE_FAKE_VALUE_FUNC(int, fake_can_get_max_filters, const struct device *, bool); -#ifdef CONFIG_ZTEST_NEW_API +#ifdef CONFIG_ZTEST static void fake_can_reset_rule_before(const struct ztest_unit_test *test, void *fixture) { ARG_UNUSED(test); @@ -68,7 +68,7 @@ static void fake_can_reset_rule_before(const struct ztest_unit_test *test, void } ZTEST_RULE(fake_can_reset_rule, fake_can_reset_rule_before, NULL); -#endif /* CONFIG_ZTEST_NEW_API */ +#endif /* CONFIG_ZTEST */ static int fake_can_get_core_clock(const struct device *dev, uint32_t *rate) { @@ -138,9 +138,9 @@ static const struct can_driver_api fake_can_driver_api = { #endif /* CONFIG_CAN_FD_MODE */ }; -#define FAKE_CAN_INIT(inst) \ - DEVICE_DT_INST_DEFINE(inst, NULL, NULL, NULL, NULL, POST_KERNEL,\ - CONFIG_CAN_INIT_PRIORITY, \ - &fake_can_driver_api); +#define FAKE_CAN_INIT(inst) \ + CAN_DEVICE_DT_INST_DEFINE(inst, NULL, NULL, NULL, NULL, POST_KERNEL, \ + CONFIG_CAN_INIT_PRIORITY, \ + &fake_can_driver_api); DT_INST_FOREACH_STATUS_OKAY(FAKE_CAN_INIT) diff --git a/drivers/can/can_handlers.c b/drivers/can/can_handlers.c index e5a8d57b6aa..57201ce6eca 100644 --- a/drivers/can/can_handlers.c +++ b/drivers/can/can_handlers.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include static int z_vrfy_can_calc_timing(const struct device *dev, struct can_timing *res, @@ -13,11 +13,11 @@ static int z_vrfy_can_calc_timing(const struct device *dev, struct can_timing *r struct can_timing res_copy; int err; - Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, get_core_clock)); - Z_OOPS(z_user_from_copy(&res_copy, res, sizeof(res_copy))); + K_OOPS(K_SYSCALL_DRIVER_CAN(dev, get_core_clock)); + K_OOPS(k_usermode_from_copy(&res_copy, res, sizeof(res_copy))); err = z_impl_can_calc_timing(dev, &res_copy, bitrate, sample_pnt); - Z_OOPS(z_user_to_copy(res, &res_copy, sizeof(*res))); + K_OOPS(k_usermode_to_copy(res, &res_copy, sizeof(*res))); return err; } @@ -28,8 +28,8 @@ static inline int z_vrfy_can_set_timing(const struct device *dev, { struct can_timing timing_copy; - Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, set_timing)); - Z_OOPS(z_user_from_copy(&timing_copy, timing, sizeof(timing_copy))); + K_OOPS(K_SYSCALL_DRIVER_CAN(dev, set_timing)); + K_OOPS(k_usermode_from_copy(&timing_copy, timing, sizeof(timing_copy))); return z_impl_can_set_timing(dev, &timing_copy); } @@ -38,8 +38,8 @@ static inline int z_vrfy_can_set_timing(const struct device *dev, static inline int z_vrfy_can_get_core_clock(const struct device *dev, uint32_t *rate) { - Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, get_core_clock)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(rate, sizeof(*rate))); + K_OOPS(K_SYSCALL_DRIVER_CAN(dev, get_core_clock)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(rate, sizeof(*rate))); return z_impl_can_get_core_clock(dev, rate); } @@ -49,8 +49,8 @@ static inline int z_vrfy_can_get_max_bitrate(const struct device *dev, uint32_t *max_bitrate) { /* Optional API function */ - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(max_bitrate, sizeof(*max_bitrate))); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(max_bitrate, sizeof(*max_bitrate))); return z_impl_can_get_max_bitrate(dev, max_bitrate); } @@ -58,7 +58,7 @@ static inline int z_vrfy_can_get_max_bitrate(const struct device *dev, static inline const struct can_timing *z_vrfy_can_get_timing_min(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN)); return z_impl_can_get_timing_min(dev); } @@ -66,7 +66,7 @@ static inline const struct can_timing *z_vrfy_can_get_timing_min(const struct de static inline const struct can_timing *z_vrfy_can_get_timing_max(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN)); return z_impl_can_get_timing_max(dev); } @@ -80,11 +80,11 @@ static int z_vrfy_can_calc_timing_data(const struct device *dev, struct can_timi struct can_timing res_copy; int err; - Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, get_core_clock)); - Z_OOPS(z_user_from_copy(&res_copy, res, sizeof(res_copy))); + K_OOPS(K_SYSCALL_DRIVER_CAN(dev, get_core_clock)); + K_OOPS(k_usermode_from_copy(&res_copy, res, sizeof(res_copy))); err = z_impl_can_calc_timing_data(dev, &res_copy, bitrate, sample_pnt); - Z_OOPS(z_user_to_copy(res, &res_copy, sizeof(*res))); + K_OOPS(k_usermode_to_copy(res, &res_copy, sizeof(*res))); return err; } @@ -92,7 +92,7 @@ static int z_vrfy_can_calc_timing_data(const struct device *dev, struct can_timi static inline const struct can_timing *z_vrfy_can_get_timing_data_min(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN)); return z_impl_can_get_timing_data_min(dev); } @@ -100,7 +100,7 @@ static inline const struct can_timing *z_vrfy_can_get_timing_data_min(const stru static inline const struct can_timing *z_vrfy_can_get_timing_data_max(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN)); return z_impl_can_get_timing_data_max(dev); } @@ -111,8 +111,8 @@ static inline int z_vrfy_can_set_timing_data(const struct device *dev, { struct can_timing timing_data_copy; - Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, set_timing_data)); - Z_OOPS(z_user_from_copy(&timing_data_copy, timing_data, sizeof(timing_data_copy))); + K_OOPS(K_SYSCALL_DRIVER_CAN(dev, set_timing_data)); + K_OOPS(k_usermode_from_copy(&timing_data_copy, timing_data, sizeof(timing_data_copy))); return z_impl_can_set_timing_data(dev, &timing_data_copy); } @@ -121,7 +121,7 @@ static inline int z_vrfy_can_set_timing_data(const struct device *dev, static inline int z_vrfy_can_set_bitrate_data(const struct device *dev, uint32_t bitrate_data) { - Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, set_timing_data)); + K_OOPS(K_SYSCALL_DRIVER_CAN(dev, set_timing_data)); return z_impl_can_set_bitrate_data(dev, bitrate_data); } @@ -132,7 +132,7 @@ static inline int z_vrfy_can_set_bitrate_data(const struct device *dev, static inline int z_vrfy_can_get_max_filters(const struct device *dev, bool ide) { /* Optional API function */ - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN)); return z_impl_can_get_max_filters(dev, ide); } @@ -140,8 +140,8 @@ static inline int z_vrfy_can_get_max_filters(const struct device *dev, bool ide) static inline int z_vrfy_can_get_capabilities(const struct device *dev, can_mode_t *cap) { - Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, get_capabilities)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(cap, sizeof(*cap))); + K_OOPS(K_SYSCALL_DRIVER_CAN(dev, get_capabilities)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(cap, sizeof(*cap))); return z_impl_can_get_capabilities(dev, cap); } @@ -149,7 +149,7 @@ static inline int z_vrfy_can_get_capabilities(const struct device *dev, can_mode static inline int z_vrfy_can_start(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, start)); + K_OOPS(K_SYSCALL_DRIVER_CAN(dev, start)); return z_impl_can_start(dev); } @@ -157,7 +157,7 @@ static inline int z_vrfy_can_start(const struct device *dev) static inline int z_vrfy_can_stop(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, stop)); + K_OOPS(K_SYSCALL_DRIVER_CAN(dev, stop)); return z_impl_can_stop(dev); } @@ -165,7 +165,7 @@ static inline int z_vrfy_can_stop(const struct device *dev) static inline int z_vrfy_can_set_mode(const struct device *dev, can_mode_t mode) { - Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, set_mode)); + K_OOPS(K_SYSCALL_DRIVER_CAN(dev, set_mode)); return z_impl_can_set_mode(dev, mode); } @@ -173,7 +173,7 @@ static inline int z_vrfy_can_set_mode(const struct device *dev, can_mode_t mode) static inline int z_vrfy_can_set_bitrate(const struct device *dev, uint32_t bitrate) { - Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, set_timing)); + K_OOPS(K_SYSCALL_DRIVER_CAN(dev, set_timing)); return z_impl_can_set_bitrate(dev, bitrate); } @@ -187,9 +187,9 @@ static inline int z_vrfy_can_send(const struct device *dev, { struct can_frame frame_copy; - Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, send)); - Z_OOPS(z_user_from_copy(&frame_copy, frame, sizeof(frame_copy))); - Z_OOPS(Z_SYSCALL_VERIFY_MSG(callback == NULL, "callbacks may not be set from user mode")); + K_OOPS(K_SYSCALL_DRIVER_CAN(dev, send)); + K_OOPS(k_usermode_from_copy(&frame_copy, frame, sizeof(frame_copy))); + K_OOPS(K_SYSCALL_VERIFY_MSG(callback == NULL, "callbacks may not be set from user mode")); return z_impl_can_send(dev, &frame_copy, timeout, callback, user_data); } @@ -201,9 +201,9 @@ static inline int z_vrfy_can_add_rx_filter_msgq(const struct device *dev, { struct can_filter filter_copy; - Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, add_rx_filter)); - Z_OOPS(Z_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); - Z_OOPS(z_user_from_copy(&filter_copy, filter, sizeof(filter_copy))); + K_OOPS(K_SYSCALL_DRIVER_CAN(dev, add_rx_filter)); + K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); + K_OOPS(k_usermode_from_copy(&filter_copy, filter, sizeof(filter_copy))); return z_impl_can_add_rx_filter_msgq(dev, msgq, &filter_copy); } @@ -211,7 +211,7 @@ static inline int z_vrfy_can_add_rx_filter_msgq(const struct device *dev, static inline void z_vrfy_can_remove_rx_filter(const struct device *dev, int filter_id) { - Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, remove_rx_filter)); + K_OOPS(K_SYSCALL_DRIVER_CAN(dev, remove_rx_filter)); z_impl_can_remove_rx_filter(dev, filter_id); } @@ -220,14 +220,14 @@ static inline void z_vrfy_can_remove_rx_filter(const struct device *dev, int fil static inline int z_vrfy_can_get_state(const struct device *dev, enum can_state *state, struct can_bus_err_cnt *err_cnt) { - Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, get_state)); + K_OOPS(K_SYSCALL_DRIVER_CAN(dev, get_state)); if (state != NULL) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(state, sizeof(*state))); + K_OOPS(K_SYSCALL_MEMORY_WRITE(state, sizeof(*state))); } if (err_cnt != NULL) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(err_cnt, sizeof(*err_cnt))); + K_OOPS(K_SYSCALL_MEMORY_WRITE(err_cnt, sizeof(*err_cnt))); } return z_impl_can_get_state(dev, state, err_cnt); @@ -237,9 +237,77 @@ static inline int z_vrfy_can_get_state(const struct device *dev, enum can_state #ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY static inline int z_vrfy_can_recover(const struct device *dev, k_timeout_t timeout) { - Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, recover)); + K_OOPS(K_SYSCALL_DRIVER_CAN(dev, recover)); return z_impl_can_recover(dev, timeout); } #include #endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */ + +#ifdef CONFIG_CAN_STATS + +static inline uint32_t z_vrfy_can_stats_get_bit_errors(const struct device *dev) +{ + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN)); + + return z_impl_can_stats_get_bit_errors(dev); +} +#include + +static inline uint32_t z_vrfy_can_stats_get_bit0_errors(const struct device *dev) +{ + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN)); + + return z_impl_can_stats_get_bit0_errors(dev); +} +#include + +static inline uint32_t z_vrfy_can_stats_get_bit1_errors(const struct device *dev) +{ + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN)); + + return z_impl_can_stats_get_bit1_errors(dev); +} +#include + +static inline uint32_t z_vrfy_can_stats_get_stuff_errors(const struct device *dev) +{ + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN)); + + return z_impl_can_stats_get_stuff_errors(dev); +} +#include + +static inline uint32_t z_vrfy_can_stats_get_crc_errors(const struct device *dev) +{ + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN)); + + return z_impl_can_stats_get_crc_errors(dev); +} +#include + +static inline uint32_t z_vrfy_can_stats_get_form_errors(const struct device *dev) +{ + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN)); + + return z_impl_can_stats_get_form_errors(dev); +} +#include + +static inline uint32_t z_vrfy_can_stats_get_ack_errors(const struct device *dev) +{ + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN)); + + return z_impl_can_stats_get_ack_errors(dev); +} +#include + +static inline uint32_t z_vrfy_can_stats_get_rx_overruns(const struct device *dev) +{ + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN)); + + return z_impl_can_stats_get_rx_overruns(dev); +} +#include + +#endif /* CONFIG_CAN_STATS */ diff --git a/drivers/can/can_kvaser_pci.c b/drivers/can/can_kvaser_pci.c index 39ed411cc67..2aa002efd8c 100644 --- a/drivers/can/can_kvaser_pci.c +++ b/drivers/can/can_kvaser_pci.c @@ -176,9 +176,9 @@ const struct can_driver_api can_kvaser_pci_driver_api = { static struct can_sja1000_data can_sja1000_data_##inst = \ CAN_SJA1000_DATA_INITIALIZER(&can_kvaser_pci_data_##inst); \ \ - DEVICE_DT_INST_DEFINE(inst, can_kvaser_pci_init, NULL, &can_sja1000_data_##inst, \ - &can_sja1000_config_##inst, POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ - &can_kvaser_pci_driver_api); \ + CAN_DEVICE_DT_INST_DEFINE(inst, can_kvaser_pci_init, NULL, &can_sja1000_data_##inst, \ + &can_sja1000_config_##inst, POST_KERNEL, \ + CONFIG_CAN_INIT_PRIORITY, &can_kvaser_pci_driver_api); \ \ static void can_kvaser_pci_config_func_##inst(const struct device *dev) \ { \ diff --git a/drivers/can/can_loopback.c b/drivers/can/can_loopback.c index 6eaea400ee0..863bf3a69ac 100644 --- a/drivers/can/can_loopback.c +++ b/drivers/can/can_loopback.c @@ -211,7 +211,7 @@ static void can_loopback_remove_rx_filter(const struct device *dev, int filter_i { struct can_loopback_data *data = dev->data; - if (filter_id >= ARRAY_SIZE(data->filters)) { + if (filter_id < 0 || filter_id >= ARRAY_SIZE(data->filters)) { LOG_ERR("filter ID %d out-of-bounds", filter_id); return; } @@ -460,9 +460,9 @@ static int can_loopback_init(const struct device *dev) #define CAN_LOOPBACK_INIT(inst) \ static struct can_loopback_data can_loopback_dev_data_##inst; \ \ - DEVICE_DT_INST_DEFINE(inst, &can_loopback_init, NULL, \ - &can_loopback_dev_data_##inst, NULL, \ - POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ - &can_loopback_driver_api); + CAN_DEVICE_DT_INST_DEFINE(inst, can_loopback_init, NULL, \ + &can_loopback_dev_data_##inst, NULL, \ + POST_KERNEL, CONFIG_CAN_INIT_PRIORITY,\ + &can_loopback_driver_api); DT_INST_FOREACH_STATUS_OKAY(CAN_LOOPBACK_INIT) diff --git a/drivers/can/can_mcan.c b/drivers/can/can_mcan.c index 0655d3d9e5a..529f2ed7dff 100644 --- a/drivers/can/can_mcan.c +++ b/drivers/can/can_mcan.c @@ -204,27 +204,10 @@ int can_mcan_set_timing(const struct device *dev, const struct can_timing *timin return -EBUSY; } - __ASSERT_NO_MSG(timing->prop_seg == 0U); - __ASSERT_NO_MSG(timing->phase_seg1 <= 0x100 && timing->phase_seg1 > 1U); - __ASSERT_NO_MSG(timing->phase_seg2 <= 0x80 && timing->phase_seg2 > 1U); - __ASSERT_NO_MSG(timing->prescaler <= 0x200 && timing->prescaler > 0U); - __ASSERT_NO_MSG(timing->sjw == CAN_SJW_NO_CHANGE || - (timing->sjw <= 0x80 && timing->sjw > 0U)); - k_mutex_lock(&data->lock, K_FOREVER); - if (timing->sjw == CAN_SJW_NO_CHANGE) { - err = can_mcan_read_reg(dev, CAN_MCAN_NBTP, &nbtp); - if (err != 0) { - goto unlock; - } - - nbtp &= CAN_MCAN_NBTP_NSJW; - } else { - nbtp |= FIELD_PREP(CAN_MCAN_NBTP_NSJW, timing->sjw - 1UL); - } - - nbtp |= FIELD_PREP(CAN_MCAN_NBTP_NTSEG1, timing->phase_seg1 - 1UL) | + nbtp |= FIELD_PREP(CAN_MCAN_NBTP_NSJW, timing->sjw - 1UL) | + FIELD_PREP(CAN_MCAN_NBTP_NTSEG1, timing->phase_seg1 - 1UL) | FIELD_PREP(CAN_MCAN_NBTP_NTSEG2, timing->phase_seg2 - 1UL) | FIELD_PREP(CAN_MCAN_NBTP_NBRP, timing->prescaler - 1UL); @@ -250,27 +233,10 @@ int can_mcan_set_timing_data(const struct device *dev, const struct can_timing * return -EBUSY; } - __ASSERT_NO_MSG(timing_data->prop_seg == 0U); - __ASSERT_NO_MSG(timing_data->phase_seg1 <= 0x20 && timing_data->phase_seg1 > 0U); - __ASSERT_NO_MSG(timing_data->phase_seg2 <= 0x10 && timing_data->phase_seg2 > 0U); - __ASSERT_NO_MSG(timing_data->prescaler <= 0x20 && timing_data->prescaler > 0U); - __ASSERT_NO_MSG(timing_data->sjw == CAN_SJW_NO_CHANGE || - (timing_data->sjw <= 0x10 && timing_data->sjw > 0U)); - k_mutex_lock(&data->lock, K_FOREVER); - if (timing_data->sjw == CAN_SJW_NO_CHANGE) { - err = can_mcan_read_reg(dev, CAN_MCAN_DBTP, &dbtp); - if (err != 0) { - goto unlock; - } - - dbtp &= CAN_MCAN_DBTP_DSJW; - } else { - dbtp |= FIELD_PREP(CAN_MCAN_DBTP_DSJW, timing_data->sjw - 1UL); - } - - dbtp |= FIELD_PREP(CAN_MCAN_DBTP_DTSEG1, timing_data->phase_seg1 - 1UL) | + dbtp |= FIELD_PREP(CAN_MCAN_DBTP_DSJW, timing_data->sjw - 1UL) | + FIELD_PREP(CAN_MCAN_DBTP_DTSEG1, timing_data->phase_seg1 - 1UL) | FIELD_PREP(CAN_MCAN_DBTP_DTSEG2, timing_data->phase_seg2 - 1UL) | FIELD_PREP(CAN_MCAN_DBTP_DBRP, timing_data->prescaler - 1UL); @@ -317,6 +283,9 @@ int can_mcan_start(const struct device *dev) } } + /* Reset statistics */ + CAN_STATS_RESET(dev); + err = can_mcan_leave_init_mode(dev, K_MSEC(CAN_INIT_TIMEOUT_MS)); if (err != 0) { LOG_ERR("failed to leave init mode"); @@ -524,11 +493,67 @@ static void can_mcan_tx_event_handler(const struct device *dev) } } +#ifdef CONFIG_CAN_STATS +static void can_mcan_lec_update_stats(const struct device *dev, enum can_mcan_psr_lec lec) +{ + switch (lec) { + case CAN_MCAN_PSR_LEC_STUFF_ERROR: + CAN_STATS_STUFF_ERROR_INC(dev); + break; + case CAN_MCAN_PSR_LEC_FORM_ERROR: + CAN_STATS_FORM_ERROR_INC(dev); + break; + case CAN_MCAN_PSR_LEC_ACK_ERROR: + CAN_STATS_ACK_ERROR_INC(dev); + break; + case CAN_MCAN_PSR_LEC_BIT1_ERROR: + CAN_STATS_BIT1_ERROR_INC(dev); + break; + case CAN_MCAN_PSR_LEC_BIT0_ERROR: + CAN_STATS_BIT0_ERROR_INC(dev); + break; + case CAN_MCAN_PSR_LEC_CRC_ERROR: + CAN_STATS_CRC_ERROR_INC(dev); + break; + case CAN_MCAN_PSR_LEC_NO_ERROR: + case CAN_MCAN_PSR_LEC_NO_CHANGE: + default: + break; + } +} +#endif /* CONFIG_CAN_STATS */ + +static int can_mcan_read_psr(const struct device *dev, uint32_t *val) +{ + /* Reading the lower byte of the PSR register clears the protocol last + * error codes (LEC). To avoid missing errors, this function should be + * used whenever the PSR register is read. + */ + int err = can_mcan_read_reg(dev, CAN_MCAN_PSR, val); + + if (err != 0) { + return err; + } + +#ifdef CONFIG_CAN_STATS + enum can_mcan_psr_lec lec; + + lec = FIELD_GET(CAN_MCAN_PSR_LEC, *val); + can_mcan_lec_update_stats(dev, lec); +#ifdef CONFIG_CAN_FD_MODE + lec = FIELD_GET(CAN_MCAN_PSR_DLEC, *val); + can_mcan_lec_update_stats(dev, lec); +#endif +#endif /* CONFIG_CAN_STATS */ + + return 0; +} + void can_mcan_line_0_isr(const struct device *dev) { const uint32_t events = CAN_MCAN_IR_BO | CAN_MCAN_IR_EP | CAN_MCAN_IR_EW | CAN_MCAN_IR_TEFN | CAN_MCAN_IR_TEFL | CAN_MCAN_IR_ARA | - CAN_MCAN_IR_MRAF; + CAN_MCAN_IR_MRAF | CAN_MCAN_IR_PEA | CAN_MCAN_IR_PED; struct can_mcan_data *data = dev->data; uint32_t ir; int err; @@ -562,10 +587,18 @@ void can_mcan_line_0_isr(const struct device *dev) LOG_ERR("Access to reserved address"); } - if (ir & CAN_MCAN_IR_MRAF) { + if ((ir & CAN_MCAN_IR_MRAF) != 0U) { LOG_ERR("Message RAM access failure"); } +#ifdef CONFIG_CAN_STATS + if ((ir & (CAN_MCAN_IR_PEA | CAN_MCAN_IR_PED)) != 0U) { + uint32_t reg; + /* This function automatically updates protocol error stats */ + can_mcan_read_psr(dev, ®); + } +#endif + err = can_mcan_read_reg(dev, CAN_MCAN_IR, &ir); if (err != 0) { return; @@ -661,14 +694,16 @@ static void can_mcan_get_message(const struct device *dev, uint16_t fifo_offset, data_length = can_dlc_to_bytes(frame.dlc); if (data_length <= sizeof(frame.data)) { - err = can_mcan_read_mram(dev, fifo_offset + get_idx * - sizeof(struct can_mcan_rx_fifo) + - offsetof(struct can_mcan_rx_fifo, data_32), - &frame.data_32, - ROUND_UP(data_length, sizeof(uint32_t))); - if (err != 0) { - LOG_ERR("failed to read Rx FIFO data (err %d)", err); - return; + if ((frame.flags & CAN_FRAME_RTR) == 0U) { + err = can_mcan_read_mram(dev, fifo_offset + get_idx * + sizeof(struct can_mcan_rx_fifo) + + offsetof(struct can_mcan_rx_fifo, data_32), + &frame.data_32, + ROUND_UP(data_length, sizeof(uint32_t))); + if (err != 0) { + LOG_ERR("failed to read Rx FIFO data (err %d)", err); + return; + } } if ((frame.flags & CAN_FRAME_IDE) != 0) { @@ -739,10 +774,12 @@ void can_mcan_line_1_isr(const struct device *dev) if ((ir & CAN_MCAN_IR_RF0L) != 0U) { LOG_ERR("Message lost on FIFO0"); + CAN_STATS_RX_OVERRUN_INC(dev); } if ((ir & CAN_MCAN_IR_RF1L) != 0U) { LOG_ERR("Message lost on FIFO1"); + CAN_STATS_RX_OVERRUN_INC(dev); } err = can_mcan_read_reg(dev, CAN_MCAN_IR, &ir); @@ -760,7 +797,7 @@ int can_mcan_get_state(const struct device *dev, enum can_state *state, int err; if (state != NULL) { - err = can_mcan_read_reg(dev, CAN_MCAN_PSR, ®); + err = can_mcan_read_psr(dev, ®); if (err != 0) { return err; } @@ -845,7 +882,7 @@ int can_mcan_send(const struct device *dev, const struct can_frame *frame, k_tim } if (!data->fd && ((frame->flags & (CAN_FRAME_FDF | CAN_FRAME_BRS)) != 0U)) { - LOG_ERR("CAN-FD format not supported in non-FD mode"); + LOG_ERR("CAN FD format not supported in non-FD mode"); return -ENOTSUP; } #else /* CONFIG_CAN_FD_MODE */ @@ -863,7 +900,7 @@ int can_mcan_send(const struct device *dev, const struct can_frame *frame, k_tim if ((frame->flags & CAN_FRAME_FDF) != 0U) { if (frame->dlc > CANFD_MAX_DLC) { - LOG_ERR("DLC of %d for CAN-FD format frame", frame->dlc); + LOG_ERR("DLC of %d for CAN FD format frame", frame->dlc); return -EINVAL; } } else { @@ -877,7 +914,7 @@ int can_mcan_send(const struct device *dev, const struct can_frame *frame, k_tim return -ENETDOWN; } - err = can_mcan_read_reg(dev, CAN_MCAN_PSR, ®); + err = can_mcan_read_psr(dev, ®); if (err != 0) { return err; } @@ -918,13 +955,15 @@ int can_mcan_send(const struct device *dev, const struct can_frame *frame, k_tim goto err_unlock; } - err = can_mcan_write_mram(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_TX_BUFFER] + put_idx * - sizeof(struct can_mcan_tx_buffer) + - offsetof(struct can_mcan_tx_buffer, data_32), - &frame->data_32, ROUND_UP(data_length, sizeof(uint32_t))); - if (err != 0) { - LOG_ERR("failed to write Tx Buffer data (err %d)", err); - goto err_unlock; + if ((frame->flags & CAN_FRAME_RTR) == 0U) { + err = can_mcan_write_mram(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_TX_BUFFER] + + put_idx * sizeof(struct can_mcan_tx_buffer) + + offsetof(struct can_mcan_tx_buffer, data_32), + &frame->data_32, ROUND_UP(data_length, sizeof(uint32_t))); + if (err != 0) { + LOG_ERR("failed to write Tx Buffer data (err %d)", err); + goto err_unlock; + } } __ASSERT_NO_MSG(put_idx < cbs->num_tx); @@ -1110,12 +1149,17 @@ void can_mcan_remove_rx_filter(const struct device *dev, int filter_id) struct can_mcan_data *data = dev->data; int err; + if (filter_id < 0) { + LOG_ERR("filter ID %d out of bounds", filter_id); + return; + } + k_mutex_lock(&data->lock, K_FOREVER); if (filter_id >= cbs->num_std) { filter_id -= cbs->num_std; if (filter_id >= cbs->num_ext) { - LOG_ERR("Wrong filter id"); + LOG_ERR("filter ID %d out of bounds", filter_id); k_mutex_unlock(&data->lock); return; } @@ -1288,9 +1332,9 @@ int can_mcan_init(const struct device *dev) const struct can_mcan_config *config = dev->config; const struct can_mcan_callbacks *cbs = config->callbacks; struct can_mcan_data *data = dev->data; - struct can_timing timing; + struct can_timing timing = { 0 }; #ifdef CONFIG_CAN_FD_MODE - struct can_timing timing_data; + struct can_timing timing_data = { 0 }; #endif /* CONFIG_CAN_FD_MODE */ uint32_t reg; int err; @@ -1416,6 +1460,7 @@ int can_mcan_init(const struct device *dev) timing.phase_seg2); LOG_DBG("Sample-point err : %d", err); } else if (config->prop_ts1) { + timing.sjw = config->sjw; timing.prop_seg = 0U; timing.phase_seg1 = config->prop_ts1; timing.phase_seg2 = config->ts2; @@ -1435,6 +1480,7 @@ int can_mcan_init(const struct device *dev) LOG_DBG("Sample-point err data phase: %d", err); } else if (config->prop_ts1_data) { + timing_data.sjw = config->sjw_data; timing_data.prop_seg = 0U; timing_data.phase_seg1 = config->prop_ts1_data; timing_data.phase_seg2 = config->ts2_data; @@ -1445,24 +1491,36 @@ int can_mcan_init(const struct device *dev) } #endif /* CONFIG_CAN_FD_MODE */ - timing.sjw = config->sjw; - can_mcan_set_timing(dev, &timing); + err = can_set_timing(dev, &timing); + if (err != 0) { + LOG_ERR("failed to set timing (err %d)", err); + return -ENODEV; + } #ifdef CONFIG_CAN_FD_MODE - timing_data.sjw = config->sjw_data; - can_mcan_set_timing_data(dev, &timing_data); + err = can_set_timing_data(dev, &timing_data); + if (err != 0) { + LOG_ERR("failed to set data phase timing (err %d)", err); + return -ENODEV; + } #endif /* CONFIG_CAN_FD_MODE */ reg = CAN_MCAN_IE_BOE | CAN_MCAN_IE_EWE | CAN_MCAN_IE_EPE | CAN_MCAN_IE_MRAFE | CAN_MCAN_IE_TEFLE | CAN_MCAN_IE_TEFNE | CAN_MCAN_IE_RF0NE | CAN_MCAN_IE_RF1NE | CAN_MCAN_IE_RF0LE | CAN_MCAN_IE_RF1LE; +#ifdef CONFIG_CAN_STATS + /* These ISRs are only enabled/used for statistics, they are otherwise + * disabled as they may produce a significant amount of frequent ISRs. + */ + reg |= CAN_MCAN_IE_PEAE | CAN_MCAN_IE_PEDE; +#endif err = can_mcan_write_reg(dev, CAN_MCAN_IE, reg); if (err != 0) { return err; } - reg = CAN_MCAN_ILS_RF0NL | CAN_MCAN_ILS_RF1NL; + reg = CAN_MCAN_ILS_RF0NL | CAN_MCAN_ILS_RF1NL | CAN_MCAN_ILS_RF0LL | CAN_MCAN_ILS_RF1LL; err = can_mcan_write_reg(dev, CAN_MCAN_ILS, reg); if (err != 0) { return err; diff --git a/drivers/can/can_mcp2515.c b/drivers/can/can_mcp2515.c index d91a73602d4..0a610fba601 100644 --- a/drivers/can/can_mcp2515.c +++ b/drivers/can/can_mcp2515.c @@ -219,7 +219,7 @@ static void mcp2515_convert_canframe_to_mcp2515frame(const struct can_frame { uint8_t rtr; uint8_t dlc; - uint8_t data_idx = 0U; + uint8_t data_idx; if ((source->flags & CAN_FRAME_IDE) != 0) { target[MCP2515_FRAME_OFFSET_SIDH] = source->id >> 21; @@ -239,16 +239,18 @@ static void mcp2515_convert_canframe_to_mcp2515frame(const struct can_frame target[MCP2515_FRAME_OFFSET_DLC] = rtr | dlc; - for (; data_idx < CAN_MAX_DLC; data_idx++) { - target[MCP2515_FRAME_OFFSET_D0 + data_idx] = - source->data[data_idx]; + if (rtr == 0U) { + for (data_idx = 0U; data_idx < dlc; data_idx++) { + target[MCP2515_FRAME_OFFSET_D0 + data_idx] = + source->data[data_idx]; + } } } static void mcp2515_convert_mcp2515frame_to_canframe(const uint8_t *source, struct can_frame *target) { - uint8_t data_idx = 0U; + uint8_t data_idx; memset(target, 0, sizeof(*target)); @@ -269,11 +271,11 @@ static void mcp2515_convert_mcp2515frame_to_canframe(const uint8_t *source, if ((source[MCP2515_FRAME_OFFSET_DLC] & BIT(6)) != 0) { target->flags |= CAN_FRAME_RTR; - } - - for (; data_idx < CAN_MAX_DLC; data_idx++) { - target->data[data_idx] = source[MCP2515_FRAME_OFFSET_D0 + - data_idx]; + } else { + for (data_idx = 0U; data_idx < target->dlc; data_idx++) { + target->data[data_idx] = source[MCP2515_FRAME_OFFSET_D0 + + data_idx]; + } } } @@ -361,11 +363,8 @@ static int mcp2515_set_timing(const struct device *dev, /* CNF1; SJW<7:6> | BRP<5:0> */ __ASSERT(timing->prescaler > 0, "Prescaler should be bigger than zero"); uint8_t brp = timing->prescaler - 1; - if (timing->sjw != CAN_SJW_NO_CHANGE) { - dev_data->sjw = (timing->sjw - 1) << 6; - } - - uint8_t cnf1 = dev_data->sjw | brp; + uint8_t sjw = (timing->sjw - 1) << 6; + uint8_t cnf1 = sjw | brp; /* CNF2; BTLMODE<7>|SAM<6>|PHSEG1<5:3>|PRSEG<2:0> */ const uint8_t btlmode = 1 << 7; @@ -392,17 +391,6 @@ static int mcp2515_set_timing(const struct device *dev, const uint8_t rx0_ctrl = BIT(6) | BIT(5) | BIT(2); const uint8_t rx1_ctrl = BIT(6) | BIT(5); - __ASSERT(timing->sjw <= 4, "1 <= SJW <= 4"); - __ASSERT((timing->prop_seg >= 1) && (timing->prop_seg <= 8), - "1 <= PROP <= 8"); - __ASSERT((timing->phase_seg1 >= 1) && (timing->phase_seg1 <= 8), - "1 <= BS1 <= 8"); - __ASSERT((timing->phase_seg2 >= 2) && (timing->phase_seg2 <= 8), - "2 <= BS2 <= 8"); - __ASSERT(timing->prop_seg + timing->phase_seg1 >= timing->phase_seg2, - "PROP + BS1 >= BS2"); - __ASSERT(timing->phase_seg2 > timing->sjw, "BS2 > SJW"); - config_buf[0] = cnf3; config_buf[1] = cnf2; config_buf[2] = cnf1; @@ -463,6 +451,8 @@ static int mcp2515_start(const struct device *dev) } } + CAN_STATS_RESET(dev); + k_mutex_lock(&dev_data->mutex, K_FOREVER); ret = mcp2515_set_mode_int(dev, dev_data->mcp2515_mode); @@ -673,6 +663,11 @@ static void mcp2515_remove_rx_filter(const struct device *dev, int filter_id) { struct mcp2515_data *dev_data = dev->data; + if (filter_id < 0 || filter_id >= CONFIG_CAN_MAX_FILTER) { + LOG_ERR("filter ID %d out of bounds", filter_id); + return; + } + k_mutex_lock(&dev_data->mutex, K_FOREVER); dev_data->filter_usage &= ~BIT(filter_id); k_mutex_unlock(&dev_data->mutex); @@ -774,6 +769,20 @@ static int mcp2515_get_state(const struct device *dev, enum can_state *state, err_cnt->rx_err_cnt = err_cnt_buf[1]; } +#ifdef CONFIG_CAN_STATS + if ((eflg & (MCP2515_EFLG_RX0OVR | MCP2515_EFLG_RX1OVR)) != 0U) { + CAN_STATS_RX_OVERRUN_INC(dev); + + ret = mcp2515_cmd_bit_modify(dev, MCP2515_ADDR_EFLG, + eflg & (MCP2515_EFLG_RX0OVR | MCP2515_EFLG_RX1OVR), + 0U); + if (ret < 0) { + LOG_ERR("Failed to clear RX overrun flags [%d]", ret); + return -EIO; + } + } +#endif /* CONFIG_CAN_STATS */ + return 0; } @@ -880,8 +889,12 @@ static void mcp2515_handle_interrupts(const struct device *dev) } } -static void mcp2515_int_thread(const struct device *dev) +static void mcp2515_int_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; struct mcp2515_data *dev_data = dev->data; while (1) { @@ -937,7 +950,7 @@ static int mcp2515_init(const struct device *dev) { const struct mcp2515_config *dev_cfg = dev->config; struct mcp2515_data *dev_data = dev->data; - struct can_timing timing; + struct can_timing timing = { 0 }; k_tid_t tid; int ret; @@ -989,7 +1002,7 @@ static int mcp2515_init(const struct device *dev) tid = k_thread_create(&dev_data->int_thread, dev_data->int_thread_stack, dev_cfg->int_thread_stack_size, - (k_thread_entry_t) mcp2515_int_thread, (void *)dev, + mcp2515_int_thread, (void *)dev, NULL, NULL, K_PRIO_COOP(dev_cfg->int_thread_priority), 0, K_NO_WAIT); (void)k_thread_name_set(tid, "mcp2515"); @@ -998,7 +1011,6 @@ static int mcp2515_init(const struct device *dev) (void)memset(dev_data->filter, 0, sizeof(dev_data->filter)); dev_data->old_state = CAN_STATE_ERROR_ACTIVE; - timing.sjw = dev_cfg->tq_sjw; if (dev_cfg->sample_point && USE_SP_ALGO) { ret = can_calc_timing(dev, &timing, dev_cfg->bus_speed, dev_cfg->sample_point); @@ -1010,6 +1022,7 @@ static int mcp2515_init(const struct device *dev) timing.prescaler, timing.phase_seg1, timing.phase_seg2); LOG_DBG("Sample-point err : %d", ret); } else { + timing.sjw = dev_cfg->tq_sjw; timing.prop_seg = dev_cfg->tq_prop; timing.phase_seg1 = dev_cfg->tq_bs1; timing.phase_seg2 = dev_cfg->tq_bs2; @@ -1057,8 +1070,8 @@ static int mcp2515_init(const struct device *dev) .max_bitrate = DT_INST_CAN_TRANSCEIVER_MAX_BITRATE(inst, 1000000), \ }; \ \ - DEVICE_DT_INST_DEFINE(inst, &mcp2515_init, NULL, &mcp2515_data_##inst, \ - &mcp2515_config_##inst, POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ - &can_api_funcs); + CAN_DEVICE_DT_INST_DEFINE(inst, mcp2515_init, NULL, &mcp2515_data_##inst, \ + &mcp2515_config_##inst, POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ + &can_api_funcs); DT_INST_FOREACH_STATUS_OKAY(MCP2515_INIT) diff --git a/drivers/can/can_mcp2515.h b/drivers/can/can_mcp2515.h index 8d9277b7db8..f8e2921ba63 100644 --- a/drivers/can/can_mcp2515.h +++ b/drivers/can/can_mcp2515.h @@ -46,7 +46,6 @@ struct mcp2515_data { enum can_state old_state; uint8_t mcp2515_mode; bool started; - uint8_t sjw; }; struct mcp2515_config { diff --git a/drivers/can/can_mcp251xfd.c b/drivers/can/can_mcp251xfd.c new file mode 100644 index 00000000000..7b788ec2b6c --- /dev/null +++ b/drivers/can/can_mcp251xfd.c @@ -0,0 +1,1776 @@ +/* + * Copyright (c) 2020 Abram Early + * Copyright (c) 2023 Andriy Gelman + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT microchip_mcp251xfd + +#include "can_mcp251xfd.h" + +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(can_mcp251xfd, CONFIG_CAN_LOG_LEVEL); + +#define SP_IS_SET(inst) DT_INST_NODE_HAS_PROP(inst, sample_point) || + +/* + * Macro to exclude the sample point algorithm from compilation if not used + * Without the macro, the algorithm would always waste ROM + */ +#define USE_SP_ALGO (DT_INST_FOREACH_STATUS_OKAY(SP_IS_SET) 0) + +static void mcp251xfd_canframe_to_txobj(const struct can_frame *src, int mailbox_idx, + struct mcp251xfd_txobj *dst) +{ + memset(dst, 0, sizeof(*dst)); + + if ((src->flags & CAN_FRAME_IDE) != 0) { + dst->id = FIELD_PREP(MCP251XFD_OBJ_ID_SID_MASK, src->id >> 18); + dst->id |= FIELD_PREP(MCP251XFD_OBJ_ID_EID_MASK, src->id); + + dst->flags |= MCP251XFD_OBJ_FLAGS_IDE; + } else { + dst->id = FIELD_PREP(MCP251XFD_OBJ_ID_SID_MASK, src->id); + } + + if ((src->flags & CAN_FRAME_BRS) != 0) { + dst->flags |= MCP251XFD_OBJ_FLAGS_BRS; + } + + dst->flags |= FIELD_PREP(MCP251XFD_OBJ_FLAGS_DLC_MASK, src->dlc); +#if defined(CONFIG_CAN_FD_MODE) + if ((src->flags & CAN_FRAME_FDF) != 0) { + dst->flags |= MCP251XFD_OBJ_FLAGS_FDF; + } +#endif + dst->flags |= FIELD_PREP(MCP251XFD_OBJ_FLAGS_SEQ_MASK, mailbox_idx); + + dst->id = sys_cpu_to_le32(dst->id); + dst->flags = sys_cpu_to_le32(dst->flags); + + if ((src->flags & CAN_FRAME_RTR) != 0) { + dst->flags |= MCP251XFD_OBJ_FLAGS_RTR; + } else { + memcpy(dst->data, src->data, MIN(can_dlc_to_bytes(src->dlc), CAN_MAX_DLEN)); + } +} + +static void *mcp251xfd_read_reg(const struct device *dev, uint16_t addr, int len) +{ + const struct mcp251xfd_config *dev_cfg = dev->config; + struct mcp251xfd_data *dev_data = dev->data; + struct mcp251xfd_spi_data *spi_data = &dev_data->spi_data; + uint16_t spi_cmd; + int ret; + + spi_cmd = sys_cpu_to_be16(MCP251XFD_SPI_INSTRUCTION_READ | addr); + memcpy(&spi_data->header[1], &spi_cmd, sizeof(spi_cmd)); + + struct spi_buf tx_buf = {.buf = &spi_data->header[1], .len = MCP251XFD_SPI_CMD_LEN + len}; + struct spi_buf rx_buf = {.buf = &spi_data->header[1], .len = MCP251XFD_SPI_CMD_LEN + len}; + + const struct spi_buf_set tx = {.buffers = &tx_buf, .count = 1}; + const struct spi_buf_set rx = {.buffers = &rx_buf, .count = 1}; + + ret = spi_transceive_dt(&dev_cfg->bus, &tx, &rx); + if (ret < 0) { + return NULL; + } + + return &spi_data->buf[0]; +} + +static void *mcp251xfd_read_crc(const struct device *dev, uint16_t addr, int len) +{ + const struct mcp251xfd_config *dev_cfg = dev->config; + struct mcp251xfd_data *dev_data = dev->data; + struct mcp251xfd_spi_data *spi_data = &dev_data->spi_data; + int num_retries = CONFIG_CAN_MCP251XFD_READ_CRC_RETRIES + 1; + int ret; + + while (num_retries-- > 0) { + uint16_t crc_in, crc, spi_cmd; + + struct spi_buf tx_buf = {.buf = &spi_data->header[0], + .len = MCP251XFD_SPI_CMD_LEN + + MCP251XFD_SPI_LEN_FIELD_LEN + len + + MCP251XFD_SPI_CRC_LEN}; + + struct spi_buf rx_buf = {.buf = &spi_data->header[0], + .len = MCP251XFD_SPI_CMD_LEN + + MCP251XFD_SPI_LEN_FIELD_LEN + len + + MCP251XFD_SPI_CRC_LEN}; + + const struct spi_buf_set tx = {.buffers = &tx_buf, .count = 1}; + const struct spi_buf_set rx = {.buffers = &rx_buf, .count = 1}; + + spi_cmd = sys_cpu_to_be16(MCP251XFD_SPI_INSTRUCTION_READ_CRC | addr); + memcpy(&spi_data->header[0], &spi_cmd, sizeof(spi_cmd)); + spi_data->header[2] = len; + + /* + * Evaluate initial crc over spi_cmd and length as these value will change after + * spi transaction is finished. + */ + crc_in = crc16(MCP251XFD_CRC_POLY, MCP251XFD_CRC_SEED, + (uint8_t *)(&spi_data->header[0]), + MCP251XFD_SPI_CMD_LEN + MCP251XFD_SPI_LEN_FIELD_LEN); + + ret = spi_transceive_dt(&dev_cfg->bus, &tx, &rx); + if (ret < 0) { + continue; + } + + /* Continue crc calculation over the data field and the crc field */ + crc = crc16(MCP251XFD_CRC_POLY, crc_in, &spi_data->buf[0], + len + MCP251XFD_SPI_CRC_LEN); + if (crc == 0) { + return &spi_data->buf[0]; + } + } + + return NULL; +} + +static inline void *mcp251xfd_get_spi_buf_ptr(const struct device *dev) +{ + struct mcp251xfd_data *dev_data = dev->data; + struct mcp251xfd_spi_data *spi_data = &dev_data->spi_data; + + return &spi_data->buf[0]; +} + +static int mcp251xfd_write(const struct device *dev, uint16_t addr, int len) +{ + const struct mcp251xfd_config *dev_cfg = dev->config; + struct mcp251xfd_data *dev_data = dev->data; + struct mcp251xfd_spi_data *spi_data = &dev_data->spi_data; + uint16_t spi_cmd; + + struct spi_buf tx_buf = {.buf = &spi_data->header[1], .len = MCP251XFD_SPI_CMD_LEN + len}; + const struct spi_buf_set tx = {.buffers = &tx_buf, .count = 1}; + + spi_cmd = sys_cpu_to_be16(MCP251XFD_SPI_INSTRUCTION_WRITE | addr); + memcpy(&spi_data->header[1], &spi_cmd, sizeof(spi_cmd)); + + return spi_write_dt(&dev_cfg->bus, &tx); +} + +static int mcp251xfd_fifo_write(const struct device *dev, int mailbox_idx, + const struct can_frame *msg) +{ + uint32_t *regs; + struct mcp251xfd_txobj *txobj; + uint8_t *reg_byte; + uint16_t address; + int tx_len; + int ret; + + /* read fifosta and ua at the same time */ + regs = mcp251xfd_read_crc(dev, MCP251XFD_REG_TXQSTA, MCP251XFD_REG_SIZE * 2); + if (!regs) { + LOG_ERR("Failed to read 8 bytes from REG_TXQSTA"); + return -EINVAL; + } + + /* check if fifo is full */ + if (!(regs[0] & MCP251XFD_REG_TXQSTA_TXQNIF)) { + return -ENOMEM; + } + + address = MCP251XFD_RAM_START_ADDR + regs[1]; + + txobj = mcp251xfd_get_spi_buf_ptr(dev); + mcp251xfd_canframe_to_txobj(msg, mailbox_idx, txobj); + + tx_len = MCP251XFD_OBJ_HEADER_SIZE; + if ((msg->flags & CAN_FRAME_RTR) == 0) { + tx_len += ROUND_UP(can_dlc_to_bytes(msg->dlc), MCP251XFD_RAM_ALIGNMENT); + } + + ret = mcp251xfd_write(dev, address, tx_len); + if (ret < 0) { + return ret; + } + + reg_byte = mcp251xfd_get_spi_buf_ptr(dev); + *reg_byte = MCP251XFD_UINT32_FLAG_TO_BYTE_MASK(MCP251XFD_REG_TXQCON_UINC | + MCP251XFD_REG_TXQCON_TXREQ); + + return mcp251xfd_write(dev, MCP251XFD_REG_TXQCON + 1, 1); +} + +static void mcp251xfd_rxobj_to_canframe(struct mcp251xfd_rxobj *src, struct can_frame *dst) +{ + memset(dst, 0, sizeof(*dst)); + + src->id = sys_le32_to_cpu(src->id); + src->flags = sys_le32_to_cpu(src->flags); + + if ((src->flags & MCP251XFD_OBJ_FLAGS_IDE) != 0) { + dst->id = FIELD_GET(MCP251XFD_OBJ_ID_EID_MASK, src->id); + dst->id |= FIELD_GET(MCP251XFD_OBJ_ID_SID_MASK, src->id) << 18; + dst->flags |= CAN_FRAME_IDE; + } else { + dst->id = FIELD_GET(MCP251XFD_OBJ_ID_SID_MASK, src->id); + } + + if ((src->flags & MCP251XFD_OBJ_FLAGS_BRS) != 0) { + dst->flags |= CAN_FRAME_BRS; + } + +#if defined(CONFIG_CAN_FD_MODE) + if ((src->flags & MCP251XFD_OBJ_FLAGS_FDF) != 0) { + dst->flags |= CAN_FRAME_FDF; + } +#endif + + dst->dlc = FIELD_GET(MCP251XFD_OBJ_FLAGS_DLC_MASK, src->flags); + +#if defined(CONFIG_CAN_RX_TIMESTAMP) + dst->timestamp = sys_le32_to_cpu(src->timestamp); +#endif + + if ((src->flags & MCP251XFD_OBJ_FLAGS_RTR) != 0) { + dst->flags |= CAN_FRAME_RTR; + } else { + memcpy(dst->data, src->data, MIN(can_dlc_to_bytes(dst->dlc), CAN_MAX_DLEN)); + } +} + +static int mcp251xfd_get_mode_internal(const struct device *dev, uint8_t *mode) +{ + uint8_t *reg_byte; + uint32_t mask = MCP251XFD_UINT32_FLAG_TO_BYTE_MASK(MCP251XFD_REG_CON_OPMOD_MASK); + + reg_byte = mcp251xfd_read_crc(dev, MCP251XFD_REG_CON_B2, 1); + if (!reg_byte) { + return -EINVAL; + } + + *mode = FIELD_GET(mask, *reg_byte); + + return 0; +} + +static int mcp251xfd_reg_check_value_wtimeout(const struct device *dev, uint16_t addr, + uint32_t value, uint32_t mask, + uint32_t timeout_usec, int retries, bool allow_yield) +{ + uint32_t *reg; + uint32_t delay = timeout_usec / retries; + + for (;;) { + reg = mcp251xfd_read_crc(dev, addr, MCP251XFD_REG_SIZE); + if (!reg) { + return -EINVAL; + } + + *reg = sys_le32_to_cpu(*reg); + + if ((*reg & mask) == value) { + return 0; + } + + if (--retries < 0) { + LOG_ERR("Timeout validing 0x%x", addr); + return -EIO; + } + + if (allow_yield) { + k_sleep(K_USEC(delay)); + } else { + k_busy_wait(delay); + } + } + return 0; +} + +static int mcp251xfd_set_tdc(const struct device *dev, bool is_enabled, int tdc_offset) +{ + uint32_t *reg; + + if (is_enabled && + (tdc_offset < MCP251XFD_REG_TDC_TDCO_MIN || tdc_offset > MCP251XFD_REG_TDC_TDCO_MAX)) { + return -EINVAL; + } + + reg = mcp251xfd_get_spi_buf_ptr(dev); + + if (is_enabled) { + *reg = FIELD_PREP(MCP251XFD_REG_TDC_TDCMOD_MASK, MCP251XFD_REG_TDC_TDCMOD_AUTO); + *reg |= FIELD_PREP(MCP251XFD_REG_TDC_TDCO_MASK, tdc_offset); + } else { + *reg = FIELD_PREP(MCP251XFD_REG_TDC_TDCMOD_MASK, MCP251XFD_REG_TDC_TDCMOD_DISABLED); + } + + *reg = sys_cpu_to_le32(*reg); + + return mcp251xfd_write(dev, MCP251XFD_REG_TDC, MCP251XFD_REG_SIZE); +} + +static int mcp251xfd_set_mode_internal(const struct device *dev, uint8_t requested_mode) +{ + struct mcp251xfd_data *dev_data = dev->data; + uint32_t *reg; + uint32_t opmod, reg_con; + int ret = 0; + + k_mutex_lock(&dev_data->mutex, K_FOREVER); + + reg = mcp251xfd_read_crc(dev, MCP251XFD_REG_CON, MCP251XFD_REG_SIZE); + if (!reg) { + ret = -EINVAL; + goto done; + } + + reg_con = sys_le32_to_cpu(*reg); + + opmod = FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK, reg_con); + if (opmod == requested_mode) { + goto done; + } + +#if defined(CONFIG_CAN_FD_MODE) + if (dev_data->current_mcp251xfd_mode == MCP251XFD_REG_CON_MODE_CONFIG) { + if (requested_mode == MCP251XFD_REG_CON_MODE_CAN2_0 || + requested_mode == MCP251XFD_REG_CON_MODE_EXT_LOOPBACK || + requested_mode == MCP251XFD_REG_CON_MODE_INT_LOOPBACK) { + ret = mcp251xfd_set_tdc(dev, false, 0); + } else if (requested_mode == MCP251XFD_REG_CON_MODE_MIXED) { + ret = mcp251xfd_set_tdc(dev, true, dev_data->tdco); + } + + if (ret < 0) { + goto done; + } + } +#endif + + reg_con &= ~MCP251XFD_REG_CON_REQOP_MASK; + reg_con |= FIELD_PREP(MCP251XFD_REG_CON_REQOP_MASK, requested_mode); + + *reg = sys_cpu_to_le32(reg_con); + + ret = mcp251xfd_write(dev, MCP251XFD_REG_CON, MCP251XFD_REG_SIZE); + if (ret < 0) { + LOG_ERR("Failed to write REG_CON register [%d]", MCP251XFD_REG_CON); + goto done; + } + + ret = mcp251xfd_reg_check_value_wtimeout( + dev, MCP251XFD_REG_CON, FIELD_PREP(MCP251XFD_REG_CON_OPMOD_MASK, requested_mode), + MCP251XFD_REG_CON_OPMOD_MASK, MCP251XFD_MODE_CHANGE_TIMEOUT_USEC, + MCP251XFD_MODE_CHANGE_RETRIES, true); +done: + k_mutex_unlock(&dev_data->mutex); + return ret; +} + +static int mcp251xfd_set_mode(const struct device *dev, can_mode_t mode) +{ + struct mcp251xfd_data *dev_data = dev->data; + + if (dev_data->started) { + return -EBUSY; + } + + /* todo: Add CAN_MODE_ONE_SHOT support */ + if ((mode & (CAN_MODE_3_SAMPLES | CAN_MODE_ONE_SHOT)) != 0) { + return -ENOTSUP; + } + + if (mode == CAN_MODE_NORMAL) { + dev_data->next_mcp251xfd_mode = MCP251XFD_REG_CON_MODE_CAN2_0; + } + + if ((mode & CAN_MODE_FD) != 0) { +#if defined(CONFIG_CAN_FD_MODE) + dev_data->next_mcp251xfd_mode = MCP251XFD_REG_CON_MODE_MIXED; +#else + return -ENOTSUP; +#endif + } + + if ((mode & CAN_MODE_LISTENONLY) != 0) { + dev_data->next_mcp251xfd_mode = MCP251XFD_REG_CON_MODE_LISTENONLY; + } + + if ((mode & CAN_MODE_LOOPBACK) != 0) { + dev_data->next_mcp251xfd_mode = MCP251XFD_REG_CON_MODE_EXT_LOOPBACK; + } + + dev_data->mode = mode; + + return 0; +} + +static int mcp251xfd_set_timing(const struct device *dev, const struct can_timing *timing) +{ + struct mcp251xfd_data *dev_data = dev->data; + uint32_t *reg; + int ret; + + if (!timing) { + return -EINVAL; + } + + if (dev_data->started) { + return -EBUSY; + } + + k_mutex_lock(&dev_data->mutex, K_FOREVER); + + reg = mcp251xfd_get_spi_buf_ptr(dev); + *reg = FIELD_PREP(MCP251XFD_REG_NBTCFG_BRP_MASK, timing->prescaler - 1); + *reg |= FIELD_PREP(MCP251XFD_REG_NBTCFG_TSEG1_MASK, + timing->prop_seg + timing->phase_seg1 - 1); + *reg |= FIELD_PREP(MCP251XFD_REG_NBTCFG_TSEG2_MASK, timing->phase_seg2 - 1); + *reg |= FIELD_PREP(MCP251XFD_REG_NBTCFG_SJW_MASK, timing->sjw - 1); + + ret = mcp251xfd_write(dev, MCP251XFD_REG_NBTCFG, MCP251XFD_REG_SIZE); + if (ret < 0) { + LOG_ERR("Failed to write NBTCFG register [%d]", ret); + } + + k_mutex_unlock(&dev_data->mutex); + + return ret; +} + + +#if defined(CONFIG_CAN_FD_MODE) +static int mcp251xfd_set_timing_data(const struct device *dev, const struct can_timing *timing) +{ + struct mcp251xfd_data *dev_data = dev->data; + uint32_t *reg; + int ret; + + if (!timing) { + return -EINVAL; + } + + if (dev_data->started) { + return -EBUSY; + } + + k_mutex_lock(&dev_data->mutex, K_FOREVER); + + reg = mcp251xfd_get_spi_buf_ptr(dev); + + *reg = FIELD_PREP(MCP251XFD_REG_DBTCFG_BRP_MASK, timing->prescaler - 1); + *reg |= FIELD_PREP(MCP251XFD_REG_DBTCFG_TSEG1_MASK, + timing->prop_seg + timing->phase_seg1 - 1); + *reg |= FIELD_PREP(MCP251XFD_REG_DBTCFG_TSEG2_MASK, timing->phase_seg2 - 1); + *reg |= FIELD_PREP(MCP251XFD_REG_DBTCFG_SJW_MASK, timing->sjw - 1); + + *reg = sys_cpu_to_le32(*reg); + + dev_data->tdco = timing->prescaler * (timing->prop_seg + timing->phase_seg1); + + ret = mcp251xfd_write(dev, MCP251XFD_REG_DBTCFG, MCP251XFD_REG_SIZE); + if (ret < 0) { + LOG_ERR("Failed to write DBTCFG register [%d]", ret); + } + + k_mutex_unlock(&dev_data->mutex); + + return ret; +} +#endif + +static int mcp251xfd_send(const struct device *dev, const struct can_frame *msg, + k_timeout_t timeout, can_tx_callback_t callback, void *callback_arg) +{ + struct mcp251xfd_data *dev_data = dev->data; + uint8_t mailbox_idx; + int ret = 0; + + LOG_DBG("Sending %d bytes. Id: 0x%x, ID type: %s %s %s %s", can_dlc_to_bytes(msg->dlc), + msg->id, msg->flags & CAN_FRAME_IDE ? "extended" : "standard", + msg->flags & CAN_FRAME_RTR ? "RTR" : "", + msg->flags & CAN_FRAME_FDF ? "FD frame" : "", + msg->flags & CAN_FRAME_BRS ? "BRS" : ""); + + __ASSERT_NO_MSG(callback != NULL); + + if (!dev_data->started) { + return -ENETDOWN; + } + + if (dev_data->state == CAN_STATE_BUS_OFF) { + return -ENETUNREACH; + } + + if ((msg->flags & CAN_FRAME_FDF) == 0 && msg->dlc > CAN_MAX_DLC) { + LOG_ERR("DLC of %d without fd flag set.", msg->dlc); + return -EINVAL; + } + + if ((msg->flags & CAN_FRAME_FDF) && !(dev_data->mode & CAN_MODE_FD)) { + return -ENOTSUP; + } + + if (k_sem_take(&dev_data->tx_sem, timeout) != 0) { + return -EAGAIN; + } + + k_mutex_lock(&dev_data->mutex, K_FOREVER); + for (mailbox_idx = 0; mailbox_idx < MCP251XFD_TX_QUEUE_ITEMS; mailbox_idx++) { + if ((BIT(mailbox_idx) & dev_data->mailbox_usage) == 0) { + dev_data->mailbox_usage |= BIT(mailbox_idx); + break; + } + } + + if (mailbox_idx >= MCP251XFD_TX_QUEUE_ITEMS) { + k_sem_give(&dev_data->tx_sem); + ret = -EIO; + goto done; + } + + dev_data->mailbox[mailbox_idx].cb = callback; + dev_data->mailbox[mailbox_idx].cb_arg = callback_arg; + + ret = mcp251xfd_fifo_write(dev, mailbox_idx, msg); + + if (ret < 0) { + dev_data->mailbox_usage &= ~BIT(mailbox_idx); + dev_data->mailbox[mailbox_idx].cb = NULL; + k_sem_give(&dev_data->tx_sem); + } + +done: + k_mutex_unlock(&dev_data->mutex); + return ret; +} + +static int mcp251xfd_add_rx_filter(const struct device *dev, can_rx_callback_t rx_cb, void *cb_arg, + const struct can_filter *filter) +{ + struct mcp251xfd_data *dev_data = dev->data; + uint32_t *reg; + uint8_t *reg_byte; + int filter_idx; + int ret; + + __ASSERT(rx_cb != NULL, "rx_cb can not be null"); + k_mutex_lock(&dev_data->mutex, K_FOREVER); + + for (filter_idx = 0; filter_idx < CONFIG_CAN_MAX_FILTER ; filter_idx++) { + if ((BIT(filter_idx) & dev_data->filter_usage) == 0) { + break; + } + } + + if (filter_idx >= CONFIG_CAN_MAX_FILTER) { + filter_idx = -ENOSPC; + goto done; + } + + if ((filter->flags & CAN_FILTER_RTR) != 0) { + filter_idx = -ENOTSUP; + goto done; + } + + reg = mcp251xfd_get_spi_buf_ptr(dev); + + if ((filter->flags & CAN_FILTER_IDE) != 0) { + *reg = FIELD_PREP(MCP251XFD_REG_FLTOBJ_SID_MASK, filter->id >> 18); + *reg |= FIELD_PREP(MCP251XFD_REG_FLTOBJ_EID_MASK, filter->id); + *reg |= MCP251XFD_REG_FLTOBJ_EXIDE; + } else { + *reg = FIELD_PREP(MCP251XFD_REG_FLTOBJ_SID_MASK, filter->id); + } + + *reg = sys_cpu_to_le32(*reg); + ret = mcp251xfd_write(dev, MCP251XFD_REG_FLTOBJ(filter_idx), MCP251XFD_REG_SIZE); + if (ret < 0) { + LOG_ERR("Failed to write FLTOBJ register [%d]", ret); + goto done; + } + + reg = mcp251xfd_get_spi_buf_ptr(dev); + if ((filter->flags & CAN_FILTER_IDE) != 0) { + *reg = FIELD_PREP(MCP251XFD_REG_MASK_MSID_MASK, filter->mask >> 18); + *reg |= FIELD_PREP(MCP251XFD_REG_MASK_MEID_MASK, filter->mask); + } else { + *reg = FIELD_PREP(MCP251XFD_REG_MASK_MSID_MASK, filter->mask); + } + *reg |= MCP251XFD_REG_MASK_MIDE; + + *reg = sys_cpu_to_le32(*reg); + + ret = mcp251xfd_write(dev, MCP251XFD_REG_FLTMASK(filter_idx), MCP251XFD_REG_SIZE); + if (ret < 0) { + LOG_ERR("Failed to write FLTMASK register [%d]", ret); + goto done; + } + + reg_byte = mcp251xfd_get_spi_buf_ptr(dev); + *reg_byte = MCP251XFD_REG_BYTE_FLTCON_FLTEN; + *reg_byte |= FIELD_PREP(MCP251XFD_REG_BYTE_FLTCON_FBP_MASK, MCP251XFD_RX_FIFO_IDX); + + ret = mcp251xfd_write(dev, MCP251XFD_REG_BYTE_FLTCON(filter_idx), 1); + if (ret < 0) { + LOG_ERR("Failed to write FLTCON register [%d]", ret); + goto done; + } + + dev_data->filter_usage |= BIT(filter_idx); + dev_data->filter[filter_idx] = *filter; + dev_data->rx_cb[filter_idx] = rx_cb; + dev_data->cb_arg[filter_idx] = cb_arg; + +done: + k_mutex_unlock(&dev_data->mutex); + + return filter_idx; +} + +static void mcp251xfd_remove_rx_filter(const struct device *dev, int filter_idx) +{ + struct mcp251xfd_data *dev_data = dev->data; + uint8_t *reg_byte; + uint32_t *reg; + int ret; + + if (filter_idx < 0 || filter_idx >= CONFIG_CAN_MAX_FILTER) { + LOG_ERR("Filter ID %d out of bounds", filter_idx); + return; + } + + k_mutex_lock(&dev_data->mutex, K_FOREVER); + + reg_byte = mcp251xfd_get_spi_buf_ptr(dev); + *reg_byte = 0; + + ret = mcp251xfd_write(dev, MCP251XFD_REG_BYTE_FLTCON(filter_idx), 1); + if (ret < 0) { + LOG_ERR("Failed to write FLTCON register [%d]", ret); + goto done; + } + + dev_data->filter_usage &= ~BIT(filter_idx); + + reg = mcp251xfd_get_spi_buf_ptr(dev); + reg[0] = 0; + + ret = mcp251xfd_write(dev, MCP251XFD_REG_FLTCON(filter_idx), MCP251XFD_REG_SIZE); + if (ret < 0) { + LOG_ERR("Failed to write FLTCON register [%d]", ret); + } + +done: + k_mutex_unlock(&dev_data->mutex); +} + +static void mcp251xfd_set_state_change_callback(const struct device *dev, + can_state_change_callback_t cb, void *user_data) +{ + struct mcp251xfd_data *dev_data = dev->data; + + dev_data->state_change_cb = cb; + dev_data->state_change_cb_data = user_data; +} + +static int mcp251xfd_get_state(const struct device *dev, enum can_state *state, + struct can_bus_err_cnt *err_cnt) +{ + struct mcp251xfd_data *dev_data = dev->data; + uint32_t *reg; + int ret = 0; + + k_mutex_lock(&dev_data->mutex, K_FOREVER); + + reg = mcp251xfd_read_crc(dev, MCP251XFD_REG_TREC, MCP251XFD_REG_SIZE); + if (!reg) { + ret = -EINVAL; + goto done; + } + + *reg = sys_le32_to_cpu(*reg); + + if (err_cnt != NULL) { + err_cnt->tx_err_cnt = FIELD_GET(MCP251XFD_REG_TREC_TEC_MASK, *reg); + err_cnt->rx_err_cnt = FIELD_GET(MCP251XFD_REG_TREC_REC_MASK, *reg); + } + + if (state == NULL) { + goto done; + } + + if (!dev_data->started) { + *state = CAN_STATE_STOPPED; + goto done; + } + + if ((*reg & MCP251XFD_REG_TREC_TXBO) != 0) { + *state = CAN_STATE_BUS_OFF; + } else if ((*reg & MCP251XFD_REG_TREC_TXBP) != 0) { + *state = CAN_STATE_ERROR_PASSIVE; + } else if ((*reg & MCP251XFD_REG_TREC_RXBP) != 0) { + *state = CAN_STATE_ERROR_PASSIVE; + } else if ((*reg & MCP251XFD_REG_TREC_TXWARN) != 0) { + *state = CAN_STATE_ERROR_WARNING; + } else if ((*reg & MCP251XFD_REG_TREC_RXWARN) != 0) { + *state = CAN_STATE_ERROR_WARNING; + } else { + *state = CAN_STATE_ERROR_ACTIVE; + } + +done: + k_mutex_unlock(&dev_data->mutex); + return 0; +} + +static int mcp251xfd_get_core_clock(const struct device *dev, uint32_t *rate) +{ + const struct mcp251xfd_config *dev_cfg = dev->config; + + *rate = dev_cfg->osc_freq; + return 0; +} + +static int mcp251xfd_get_max_filters(const struct device *dev, bool ide) +{ + ARG_UNUSED(ide); + + return CONFIG_CAN_MAX_FILTER; +} + +static int mcp251xfd_get_max_bitrate(const struct device *dev, uint32_t *max_bitrate) +{ + const struct mcp251xfd_config *dev_cfg = dev->config; + + *max_bitrate = dev_cfg->max_bitrate; + + return 0; +} + +#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY +static int mcp251xfd_recover(const struct device *dev, k_timeout_t timeout) +{ + struct mcp251xfd_data *dev_data = dev->data; + + ARG_UNUSED(timeout); + + if (!dev_data->started) { + return -ENETDOWN; + } + + return -ENOTSUP; +} +#endif + +static int mcp251xfd_handle_fifo_read(const struct device *dev, const struct mcp251xfd_fifo *fifo, + uint8_t fifo_type) +{ + int ret = 0; + struct mcp251xfd_data *dev_data = dev->data; + uint32_t *regs, fifosta, ua; + uint8_t *reg_byte; + + int len; + int fetch_total = 0; + int ui_inc = 0; + uint32_t fifo_tail_index, fifo_tail_addr; + uint8_t fifo_head_index; + + k_mutex_lock(&dev_data->mutex, K_FOREVER); + + /* read in FIFOSTA and FIFOUA at the same time */ + regs = mcp251xfd_read_crc(dev, MCP251XFD_REG_FIFOCON_TO_STA(fifo->reg_fifocon_addr), + 2 * MCP251XFD_REG_SIZE); + if (!regs) { + ret = -EINVAL; + goto done; + } + fifosta = sys_le32_to_cpu(regs[0]); + ua = sys_le32_to_cpu(regs[1]); + + /* is there any data in the fifo? */ + if (!(fifosta & MCP251XFD_REG_FIFOSTA_TFNRFNIF)) { + goto done; + } + + fifo_tail_addr = ua; + fifo_tail_index = (fifo_tail_addr - fifo->ram_start_addr) / fifo->item_size; + + if (fifo_type == MCP251XFD_FIFO_TYPE_RX) { + /* + * fifo_head_index points where the next message will be written. + * It points to one past the end of the fifo. + */ + fifo_head_index = FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, fifosta); + if (fifo_head_index == 0) { + fifo_head_index = fifo->capacity - 1; + } else { + fifo_head_index -= 1; + } + + if (fifo_tail_index > fifo_head_index) { + /* fetch to the end of the memory and then wrap to the start */ + fetch_total = fifo->capacity - 1 - fifo_tail_index + 1; + fetch_total += fifo_head_index + 1; + } else { + fetch_total = fifo_head_index - fifo_tail_index + 1; + } + } else if (fifo_type == MCP251XFD_FIFO_TYPE_TEF) { + /* FIFOCI doesn't exist for TEF queues, so fetch one message at a time */ + fifo_head_index = fifo_tail_index; + fetch_total = 1; + } else { + ret = -EINVAL; + goto done; + } + + while (fetch_total > 0) { + uint16_t memory_addr; + uint8_t *data; + + if (fifo_tail_index > fifo_head_index) { + len = fifo->capacity - 1 - fifo_tail_index + 1; + } else { + len = fifo_head_index - fifo_tail_index + 1; + } + + memory_addr = MCP251XFD_RAM_START_ADDR + fifo->ram_start_addr + + fifo_tail_index * fifo->item_size; + + data = mcp251xfd_read_reg(dev, memory_addr, len * fifo->item_size); + if (!data) { + LOG_ERR("Error fetching batch message"); + ret = -EINVAL; + goto done; + } + + for (int i = 0; i < len; i++) { + fifo->msg_handler(dev, (void *)(&data[i * fifo->item_size])); + } + + fifo_tail_index = (fifo_tail_index + len) % fifo->capacity; + fetch_total -= len; + ui_inc += len; + } + + reg_byte = mcp251xfd_get_spi_buf_ptr(dev); + *reg_byte = MCP251XFD_UINT32_FLAG_TO_BYTE_MASK(MCP251XFD_REG_FIFOCON_UINC); + + for (int i = 0; i < ui_inc; i++) { + ret = mcp251xfd_write(dev, fifo->reg_fifocon_addr + 1, 1); + if (ret < 0) { + LOG_ERR("Failed to increment pointer"); + goto done; + } + } + +done: + k_mutex_unlock(&dev_data->mutex); + return ret; +} + +static void mcp251xfd_reset_tx_fifos(const struct device *dev, int status) +{ + struct mcp251xfd_data *dev_data = dev->data; + + LOG_INF("All FIFOs Reset"); + k_mutex_lock(&dev_data->mutex, K_FOREVER); + for (int i = 0; i < MCP251XFD_TX_QUEUE_ITEMS; i++) { + can_tx_callback_t callback; + + if (!(dev_data->mailbox_usage & BIT(i))) { + continue; + } + + callback = dev_data->mailbox[i].cb; + if (callback) { + callback(dev, status, dev_data->mailbox[i].cb_arg); + } + + dev_data->mailbox_usage &= ~BIT(i); + dev_data->mailbox[i].cb = NULL; + k_sem_give(&dev_data->tx_sem); + } + k_mutex_unlock(&dev_data->mutex); +} + +/* + * CERRIF will be set each time a threshold in the TEC/REC counter is crossed by the following + * conditions: + * • TEC or REC exceeds the Error Warning state threshold + * • The transmitter or receiver transitions to Error Passive state + * • The transmitter transitions to Bus Off state + * • The transmitter or receiver transitions from Error Passive to Error Active state + * • The module transitions from Bus Off to Error Active state, after the bus off recovery + * sequence + * When the user clears CERRIF, it will remain clear until a new counter crossing occurs. + */ +static int mcp251xfd_handle_cerrif(const struct device *dev) +{ + enum can_state new_state; + struct mcp251xfd_data *dev_data = dev->data; + struct can_bus_err_cnt err_cnt; + int ret = 0; + + k_mutex_lock(&dev_data->mutex, K_FOREVER); + + ret = mcp251xfd_get_state(dev, &new_state, &err_cnt); + if (ret < 0) { + goto done; + } + + if (new_state == dev_data->state) { + goto done; + } + + LOG_INF("State %d -> %d (tx: %d, rx: %d)", dev_data->state, new_state, err_cnt.tx_err_cnt, + err_cnt.rx_err_cnt); + + /* Upon entering bus-off, all the fifos are reset. */ + dev_data->state = new_state; + if (new_state == CAN_STATE_BUS_OFF) { + mcp251xfd_reset_tx_fifos(dev, -ENETDOWN); + } + + if (dev_data->state_change_cb) { + dev_data->state_change_cb(dev, new_state, err_cnt, dev_data->state_change_cb_data); + } + +done: + k_mutex_unlock(&dev_data->mutex); + return ret; +} + +static int mcp251xfd_handle_modif(const struct device *dev) +{ + struct mcp251xfd_data *dev_data = dev->data; + uint8_t mode; + int ret; + + k_mutex_lock(&dev_data->mutex, K_FOREVER); + + ret = mcp251xfd_get_mode_internal(dev, &mode); + if (ret < 0) { + goto finish; + } + + dev_data->current_mcp251xfd_mode = mode; + + LOG_INF("Switched to mode %d", mode); + + if (mode == dev_data->next_mcp251xfd_mode) { + ret = 0; + goto finish; + } + + /* try to transition back into our target mode */ + if (dev_data->started) { + LOG_INF("Switching back into mode %d", dev_data->next_mcp251xfd_mode); + ret = mcp251xfd_set_mode_internal(dev, dev_data->next_mcp251xfd_mode); + } + +finish: + k_mutex_unlock(&dev_data->mutex); + return ret; +} + +static int mcp251xfd_handle_ivmif(const struct device *dev) +{ + uint32_t *reg; + struct mcp251xfd_data *dev_data = dev->data; + int ret; + + k_mutex_lock(&dev_data->mutex, K_FOREVER); + + reg = mcp251xfd_read_crc(dev, MCP251XFD_REG_BDIAG1, MCP251XFD_REG_SIZE); + if (!reg) { + ret = -EINVAL; + goto done; + } + + *reg = sys_le32_to_cpu(*reg); + + if ((*reg & MCP251XFD_REG_BDIAG1_TXBOERR) != 0) { + LOG_INF("ivmif bus-off error"); + mcp251xfd_reset_tx_fifos(dev, -ENETDOWN); + } + + /* Clear the values in diag */ + reg = mcp251xfd_get_spi_buf_ptr(dev); + reg[0] = 0; + ret = mcp251xfd_write(dev, MCP251XFD_REG_BDIAG1, MCP251XFD_REG_SIZE); + +done: + k_mutex_unlock(&dev_data->mutex); + return ret; +} + +static void mcp251xfd_handle_interrupts(const struct device *dev) +{ + const struct mcp251xfd_config *dev_cfg = dev->config; + struct mcp251xfd_data *dev_data = dev->data; + uint16_t *reg_int_hw; + uint32_t reg_int; + int ret; + uint8_t consecutive_calls = 0; + + while (1) { + k_mutex_lock(&dev_data->mutex, K_FOREVER); + reg_int_hw = mcp251xfd_read_crc(dev, MCP251XFD_REG_INT, sizeof(*reg_int_hw)); + + if (!reg_int_hw) { + k_mutex_unlock(&dev_data->mutex); + continue; + } + + *reg_int_hw = sys_le16_to_cpu(*reg_int_hw); + + reg_int = *reg_int_hw; + + /* these interrupt flags need to be explicitly cleared */ + if (*reg_int_hw & MCP251XFD_REG_INT_IF_CLEARABLE_MASK) { + + *reg_int_hw &= ~MCP251XFD_REG_INT_IF_CLEARABLE_MASK; + + *reg_int_hw = sys_cpu_to_le16(*reg_int_hw); + + ret = mcp251xfd_write(dev, MCP251XFD_REG_INT, sizeof(*reg_int_hw)); + if (ret) { + LOG_ERR("Error clearing REG_INT interrupts [%d]", ret); + } + } + + k_mutex_unlock(&dev_data->mutex); + + if ((reg_int & MCP251XFD_REG_INT_RXIF) != 0) { + ret = mcp251xfd_handle_fifo_read(dev, &dev_cfg->rx_fifo, + MCP251XFD_FIFO_TYPE_RX); + if (ret < 0) { + LOG_ERR("Error handling RXIF [%d]", ret); + } + } + + if ((reg_int & MCP251XFD_REG_INT_TEFIF) != 0) { + ret = mcp251xfd_handle_fifo_read(dev, &dev_cfg->tef_fifo, + MCP251XFD_FIFO_TYPE_TEF); + if (ret < 0) { + LOG_ERR("Error handling TEFIF [%d]", ret); + } + } + + if ((reg_int & MCP251XFD_REG_INT_IVMIF) != 0) { + ret = mcp251xfd_handle_ivmif(dev); + if (ret < 0) { + LOG_ERR("Error handling IVMIF [%d]", ret); + } + } + + if ((reg_int & MCP251XFD_REG_INT_MODIF) != 0) { + ret = mcp251xfd_handle_modif(dev); + if (ret < 0) { + LOG_ERR("Error handling MODIF [%d]", ret); + } + } + + /* + * From Linux mcp251xfd driver + * On the MCP2527FD and MCP2518FD, we don't get a CERRIF IRQ on the transition + * TX ERROR_WARNING -> TX ERROR_ACTIVE. + */ + if ((reg_int & MCP251XFD_REG_INT_CERRIF) || + dev_data->state > CAN_STATE_ERROR_ACTIVE) { + ret = mcp251xfd_handle_cerrif(dev); + if (ret < 0) { + LOG_ERR("Error handling CERRIF [%d]", ret); + } + } + + /* Break from loop if INT pin is inactive */ + consecutive_calls++; + ret = gpio_pin_get_dt(&dev_cfg->int_gpio_dt); + if (ret < 0) { + LOG_ERR("Couldn't read INT pin [%d]", ret); + } else if (ret == 0) { + /* All interrupt flags handled */ + break; + } else if (consecutive_calls % MCP251XFD_MAX_INT_HANDLER_CALLS == 0) { + /* If there are clock problems, then MODIF cannot be cleared. */ + /* This is detected if there are too many consecutive calls. */ + /* Sleep this thread if this happens. */ + k_sleep(K_USEC(MCP251XFD_INT_HANDLER_SLEEP_USEC)); + } + } +} + +static void mcp251xfd_int_thread(const struct device *dev) +{ + const struct mcp251xfd_config *dev_cfg = dev->config; + struct mcp251xfd_data *dev_data = dev->data; + + while (1) { + int ret; + + k_sem_take(&dev_data->int_sem, K_FOREVER); + mcp251xfd_handle_interrupts(dev); + + /* Re-enable pin interrupts */ + ret = gpio_pin_interrupt_configure_dt(&dev_cfg->int_gpio_dt, GPIO_INT_LEVEL_ACTIVE); + if (ret < 0) { + LOG_ERR("Couldn't enable pin interrupt [%d]", ret); + k_oops(); + } + } +} + +static void mcp251xfd_int_gpio_callback(const struct device *dev_gpio, struct gpio_callback *cb, + uint32_t pins) +{ + ARG_UNUSED(dev_gpio); + struct mcp251xfd_data *dev_data = CONTAINER_OF(cb, struct mcp251xfd_data, int_gpio_cb); + const struct device *dev = dev_data->dev; + const struct mcp251xfd_config *dev_cfg = dev->config; + int ret; + + /* Disable pin interrupts */ + ret = gpio_pin_interrupt_configure_dt(&dev_cfg->int_gpio_dt, GPIO_INT_DISABLE); + if (ret < 0) { + LOG_ERR("Couldn't disable pin interrupt [%d]", ret); + k_oops(); + } + + k_sem_give(&dev_data->int_sem); +} + +static int mcp251xfd_get_capabilities(const struct device *dev, can_mode_t *cap) +{ + ARG_UNUSED(dev); + + *cap = CAN_MODE_NORMAL | CAN_MODE_LISTENONLY | CAN_MODE_LOOPBACK; + +#if defined(CONFIG_CAN_FD_MODE) + *cap |= CAN_MODE_FD; +#endif + + return 0; +} + +static int mcp251xfd_start(const struct device *dev) +{ + struct mcp251xfd_data *dev_data = dev->data; + const struct mcp251xfd_config *dev_cfg = dev->config; + int ret; + + if (dev_data->started) { + return -EALREADY; + } + + /* in case of a race between mcp251xfd_send() and mcp251xfd_stop() */ + mcp251xfd_reset_tx_fifos(dev, -ENETDOWN); + + if (dev_cfg->phy != NULL) { + ret = can_transceiver_enable(dev_cfg->phy); + if (ret < 0) { + LOG_ERR("Failed to enable CAN transceiver [%d]", ret); + return ret; + } + } + + k_mutex_lock(&dev_data->mutex, K_FOREVER); + + ret = mcp251xfd_set_mode_internal(dev, dev_data->next_mcp251xfd_mode); + if (ret < 0) { + LOG_ERR("Failed to set the mode [%d]", ret); + if (dev_cfg->phy != NULL) { + /* Attempt to disable the CAN transceiver in case of error */ + (void)can_transceiver_disable(dev_cfg->phy); + } + } else { + dev_data->started = true; + } + + k_mutex_unlock(&dev_data->mutex); + + return ret; +} + +static int mcp251xfd_stop(const struct device *dev) +{ + struct mcp251xfd_data *dev_data = dev->data; + const struct mcp251xfd_config *dev_cfg = dev->config; + uint8_t *reg_byte; + int ret; + + if (!dev_data->started) { + return -EALREADY; + } + + k_mutex_lock(&dev_data->mutex, K_FOREVER); + + /* abort all transmissions */ + reg_byte = mcp251xfd_get_spi_buf_ptr(dev); + *reg_byte = MCP251XFD_UINT32_FLAG_TO_BYTE_MASK(MCP251XFD_REG_CON_ABAT); + + ret = mcp251xfd_write(dev, MCP251XFD_REG_CON_B3, 1); + if (ret < 0) { + k_mutex_unlock(&dev_data->mutex); + return ret; + } + + /* wait for all the messages to be aborted */ + while (1) { + reg_byte = mcp251xfd_read_crc(dev, MCP251XFD_REG_CON_B3, 1); + + if (!reg_byte || + (*reg_byte & MCP251XFD_UINT32_FLAG_TO_BYTE_MASK(MCP251XFD_REG_CON_ABAT)) == 0) { + break; + } + } + + mcp251xfd_reset_tx_fifos(dev, -ENETDOWN); + + ret = mcp251xfd_set_mode_internal(dev, MCP251XFD_REG_CON_MODE_CONFIG); + if (ret < 0) { + k_mutex_unlock(&dev_data->mutex); + return ret; + } + + dev_data->started = false; + k_mutex_unlock(&dev_data->mutex); + + if (dev_cfg->phy != NULL) { + ret = can_transceiver_disable(dev_cfg->phy); + if (ret < 0) { + LOG_ERR("Failed to disable CAN transceiver [%d]", ret); + return ret; + } + } + + return 0; +} + +static void mcp251xfd_rx_fifo_handler(const struct device *dev, void *data) +{ + struct can_frame dst; + struct mcp251xfd_data *dev_data = dev->data; + struct mcp251xfd_rxobj *rxobj = data; + uint32_t filhit; + + mcp251xfd_rxobj_to_canframe(rxobj, &dst); + + filhit = FIELD_GET(MCP251XFD_OBJ_FILHIT_MASK, rxobj->flags); + if ((dev_data->filter_usage & BIT(filhit)) != 0) { + LOG_DBG("Received msg CAN id: 0x%x", dst.id); + dev_data->rx_cb[filhit](dev, &dst, dev_data->cb_arg[filhit]); + } +} + +static void mcp251xfd_tef_fifo_handler(const struct device *dev, void *data) +{ + struct mcp251xfd_data *dev_data = dev->data; + can_tx_callback_t callback; + struct mcp251xfd_tefobj *tefobj = data; + uint8_t mailbox_idx; + + mailbox_idx = FIELD_GET(MCP251XFD_OBJ_FLAGS_SEQ_MASK, tefobj->flags); + if (mailbox_idx >= MCP251XFD_TX_QUEUE_ITEMS) { + mcp251xfd_reset_tx_fifos(dev, -EIO); + LOG_ERR("Invalid mailbox index"); + return; + } + + callback = dev_data->mailbox[mailbox_idx].cb; + if (callback != NULL) { + callback(dev, 0, dev_data->mailbox[mailbox_idx].cb_arg); + } + + dev_data->mailbox_usage &= ~BIT(mailbox_idx); + dev_data->mailbox[mailbox_idx].cb = NULL; + k_sem_give(&dev_data->tx_sem); +} + +static int mcp251xfd_init_timing_struct(struct can_timing *timing, + const struct device *dev, + const struct mcp251xfd_timing_params *timing_params, + bool is_nominal) +{ + int ret; + + if (USE_SP_ALGO && timing_params->sample_point > 0) { + if (is_nominal) { + ret = can_calc_timing(dev, timing, timing_params->bus_speed, + timing_params->sample_point); + } else { + ret = can_calc_timing_data(dev, timing, timing_params->bus_speed, + timing_params->sample_point); + } + if (ret < 0) { + return ret; + } + LOG_DBG("Presc: %d, BS1: %d, BS2: %d", timing->prescaler, timing->phase_seg1, + timing->phase_seg2); + LOG_DBG("Sample-point err : %d", ret); + } else { + timing->sjw = timing_params->sjw; + timing->prop_seg = timing_params->prop_seg; + timing->phase_seg1 = timing_params->phase_seg1; + timing->phase_seg2 = timing_params->phase_seg2; + ret = can_calc_prescaler(dev, timing, timing_params->bus_speed); + if (ret > 0) { + LOG_WRN("Bitrate error: %d", ret); + } + } + + return ret; +} + +static inline int mcp251xfd_init_con_reg(const struct device *dev) +{ + uint32_t *reg; + + reg = mcp251xfd_get_spi_buf_ptr(dev); + *reg = MCP251XFD_REG_CON_ISOCRCEN | MCP251XFD_REG_CON_WAKFIL | MCP251XFD_REG_CON_TXQEN | + MCP251XFD_REG_CON_STEF; + *reg |= FIELD_PREP(MCP251XFD_REG_CON_WFT_MASK, MCP251XFD_REG_CON_WFT_T11FILTER) | + FIELD_PREP(MCP251XFD_REG_CON_REQOP_MASK, MCP251XFD_REG_CON_MODE_CONFIG); + + return mcp251xfd_write(dev, MCP251XFD_REG_CON, MCP251XFD_REG_SIZE); +} + +static inline int mcp251xfd_init_osc_reg(const struct device *dev) +{ + int ret; + const struct mcp251xfd_config *dev_cfg = dev->config; + uint32_t *reg = mcp251xfd_get_spi_buf_ptr(dev); + uint32_t reg_value = MCP251XFD_REG_OSC_OSCRDY; + + *reg = FIELD_PREP(MCP251XFD_REG_OSC_CLKODIV_MASK, dev_cfg->clko_div); + if (dev_cfg->pll_enable) { + *reg |= MCP251XFD_REG_OSC_PLLEN; + reg_value |= MCP251XFD_REG_OSC_PLLRDY; + } + + *reg = sys_cpu_to_le32(*reg); + + ret = mcp251xfd_write(dev, MCP251XFD_REG_OSC, MCP251XFD_REG_SIZE); + if (ret < 0) { + return ret; + } + + return mcp251xfd_reg_check_value_wtimeout(dev, MCP251XFD_REG_OSC, reg_value, reg_value, + MCP251XFD_PLLRDY_TIMEOUT_USEC, + MCP251XFD_PLLRDY_RETRIES, false); +} + +static inline int mcp251xfd_init_iocon_reg(const struct device *dev) +{ + const struct mcp251xfd_config *dev_cfg = dev->config; + uint32_t *reg = mcp251xfd_get_spi_buf_ptr(dev); + +/* + * MCP2518FD Errata: DS80000789 + * Writing Byte 2/3 of the IOCON register using single SPI write cleat LAT0 and LAT1. + * This has no effect in the current version since LAT0/1 are set to zero anyway. + * However, it needs to be properly handled if other values are needed. Errata suggests + * to do single byte writes instead. + */ + + *reg = MCP251XFD_REG_IOCON_TRIS0 | MCP251XFD_REG_IOCON_TRIS1 | MCP251XFD_REG_IOCON_PM0 | + MCP251XFD_REG_IOCON_PM1; + + if (dev_cfg->sof_on_clko) { + *reg |= MCP251XFD_REG_IOCON_SOF; + } + + *reg = sys_cpu_to_le32(*reg); + + return mcp251xfd_write(dev, MCP251XFD_REG_IOCON, MCP251XFD_REG_SIZE); +} + +static inline int mcp251xfd_init_int_reg(const struct device *dev) +{ + uint32_t *reg = mcp251xfd_get_spi_buf_ptr(dev); + + *reg = MCP251XFD_REG_INT_RXIE | MCP251XFD_REG_INT_MODIE | MCP251XFD_REG_INT_TEFIE | + MCP251XFD_REG_INT_CERRIE; + + *reg = sys_cpu_to_le32(*reg); + + return mcp251xfd_write(dev, MCP251XFD_REG_INT, MCP251XFD_REG_SIZE); +} + +static inline int mcp251xfd_init_tef_fifo(const struct device *dev) +{ + uint32_t *reg = mcp251xfd_get_spi_buf_ptr(dev); + + *reg = MCP251XFD_REG_TEFCON_TEFNEIE | MCP251XFD_REG_TEFCON_FRESET; + *reg |= FIELD_PREP(MCP251XFD_REG_TEFCON_FSIZE_MASK, MCP251XFD_TX_QUEUE_ITEMS - 1); + + *reg = sys_cpu_to_le32(*reg); + + return mcp251xfd_write(dev, MCP251XFD_REG_TEFCON, MCP251XFD_REG_SIZE); +} + +static inline int mcp251xfd_init_tx_queue(const struct device *dev) +{ + uint32_t *reg = mcp251xfd_get_spi_buf_ptr(dev); + + *reg = MCP251XFD_REG_TXQCON_TXEN | MCP251XFD_REG_TXQCON_FRESET; + *reg |= FIELD_PREP(MCP251XFD_REG_TXQCON_TXAT_MASK, MCP251XFD_REG_TXQCON_TXAT_UNLIMITED); + *reg |= FIELD_PREP(MCP251XFD_REG_TXQCON_FSIZE_MASK, MCP251XFD_TX_QUEUE_ITEMS - 1); + *reg |= FIELD_PREP(MCP251XFD_REG_TXQCON_PLSIZE_MASK, + can_bytes_to_dlc(MCP251XFD_PAYLOAD_SIZE) - 8); + + *reg = sys_cpu_to_le32(*reg); + + return mcp251xfd_write(dev, MCP251XFD_REG_TXQCON, MCP251XFD_REG_SIZE); +} + +static inline int mcp251xfd_init_rx_fifo(const struct device *dev) +{ + uint32_t *reg = mcp251xfd_get_spi_buf_ptr(dev); + + *reg = MCP251XFD_REG_FIFOCON_TFNRFNIE | MCP251XFD_REG_FIFOCON_FRESET; + *reg |= FIELD_PREP(MCP251XFD_REG_FIFOCON_FSIZE_MASK, MCP251XFD_RX_FIFO_ITEMS - 1); + *reg |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK, + can_bytes_to_dlc(MCP251XFD_PAYLOAD_SIZE) - 8); +#if defined(CONFIG_CAN_RX_TIMESTAMP) + *reg |= MCP251XFD_REG_FIFOCON_RXTSEN; +#endif + + *reg = sys_cpu_to_le32(*reg); + + return mcp251xfd_write(dev, MCP251XFD_REG_FIFOCON(MCP251XFD_RX_FIFO_IDX), + MCP251XFD_REG_SIZE); +} + +#if defined(CONFIG_CAN_RX_TIMESTAMP) +static int mcp251xfd_init_tscon(const struct device *dev) +{ + uint32_t *reg = mcp251xfd_get_spi_buf_ptr(dev); + const struct mcp251xfd_config *dev_cfg = dev->config; + + *reg = MCP251XFD_REG_TSCON_TBCEN; + *reg |= FIELD_PREP(MCP251XFD_REG_TSCON_TBCPRE_MASK, + dev_cfg->timestamp_prescaler - 1); + + *reg = sys_cpu_to_le32(*reg); + + return mcp251xfd_write(dev, MCP251XFD_REG_TSCON, MCP251XFD_REG_SIZE); +} +#endif + +static int mcp251xfd_reset(const struct device *dev) +{ + const struct mcp251xfd_config *dev_cfg = dev->config; + uint16_t cmd = sys_cpu_to_be16(MCP251XFD_SPI_INSTRUCTION_RESET); + const struct spi_buf tx_buf = {.buf = &cmd, .len = sizeof(cmd),}; + const struct spi_buf_set tx = {.buffers = &tx_buf, .count = 1}; + int ret; + + /* device can only be reset when in configuration mode */ + ret = mcp251xfd_set_mode_internal(dev, MCP251XFD_REG_CON_MODE_CONFIG); + if (ret < 0) { + return ret; + } + + return spi_write_dt(&dev_cfg->bus, &tx); +} + +static int mcp251xfd_init(const struct device *dev) +{ + const struct mcp251xfd_config *dev_cfg = dev->config; + struct mcp251xfd_data *dev_data = dev->data; + uint32_t *reg; + uint8_t opmod; + int ret; + struct can_timing timing = { 0 }; +#if defined(CONFIG_CAN_FD_MODE) + struct can_timing timing_data = { 0 }; +#endif + + dev_data->dev = dev; + + if (dev_cfg->clk_dev != NULL) { + uint32_t clk_id = dev_cfg->clk_id; + + if (!device_is_ready(dev_cfg->clk_dev)) { + LOG_ERR("Clock controller not ready"); + return -ENODEV; + } + + ret = clock_control_on(dev_cfg->clk_dev, (clock_control_subsys_t)clk_id); + if (ret < 0) { + LOG_ERR("Failed to enable clock [%d]", ret); + return ret; + } + } + + k_sem_init(&dev_data->int_sem, 0, 1); + k_sem_init(&dev_data->tx_sem, MCP251XFD_TX_QUEUE_ITEMS, MCP251XFD_TX_QUEUE_ITEMS); + + k_mutex_init(&dev_data->mutex); + + if (!spi_is_ready_dt(&dev_cfg->bus)) { + LOG_ERR("SPI bus %s not ready", dev_cfg->bus.bus->name); + return -ENODEV; + } + + if (!gpio_is_ready_dt(&dev_cfg->int_gpio_dt)) { + LOG_ERR("GPIO port not ready"); + return -ENODEV; + } + + if (gpio_pin_configure_dt(&dev_cfg->int_gpio_dt, GPIO_INPUT) < 0) { + LOG_ERR("Unable to configure GPIO pin"); + return -EINVAL; + } + + gpio_init_callback(&dev_data->int_gpio_cb, mcp251xfd_int_gpio_callback, + BIT(dev_cfg->int_gpio_dt.pin)); + + if (gpio_add_callback_dt(&dev_cfg->int_gpio_dt, &dev_data->int_gpio_cb) < 0) { + return -EINVAL; + } + + if (gpio_pin_interrupt_configure_dt(&dev_cfg->int_gpio_dt, GPIO_INT_LEVEL_ACTIVE) < 0) { + return -EINVAL; + } + + k_thread_create(&dev_data->int_thread, dev_data->int_thread_stack, + CONFIG_CAN_MCP251XFD_INT_THREAD_STACK_SIZE, + (k_thread_entry_t)mcp251xfd_int_thread, (void *)dev, NULL, NULL, + K_PRIO_COOP(CONFIG_CAN_MCP251XFD_INT_THREAD_PRIO), 0, K_NO_WAIT); + + (void)k_thread_name_set(&dev_data->int_thread, "MCP251XFD interrupt thread"); + + ret = mcp251xfd_reset(dev); + if (ret < 0) { + LOG_ERR("Failed to reset the device [%d]", ret); + goto done; + } + + ret = mcp251xfd_init_timing_struct(&timing, dev, &dev_cfg->timing_params, true); + if (ret < 0) { + LOG_ERR("Can't find timing for given param"); + goto done; + } + +#if defined(CONFIG_CAN_FD_MODE) + ret = mcp251xfd_init_timing_struct(&timing_data, dev, &dev_cfg->timing_params_data, false); + if (ret < 0) { + LOG_ERR("Can't find timing for given param"); + goto done; + } +#endif + + reg = mcp251xfd_read_crc(dev, MCP251XFD_REG_CON, MCP251XFD_REG_SIZE); + if (!reg) { + ret = -EINVAL; + goto done; + } + + *reg = sys_le32_to_cpu(*reg); + + opmod = FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK, *reg); + + if (opmod != MCP251XFD_REG_CON_MODE_CONFIG) { + LOG_ERR("Device did not reset into configuration mode [%d]", opmod); + ret = -EIO; + goto done; + } + + dev_data->current_mcp251xfd_mode = MCP251XFD_REG_CON_MODE_CONFIG; + + ret = mcp251xfd_init_con_reg(dev); + if (ret < 0) { + goto done; + } + + ret = mcp251xfd_init_osc_reg(dev); + if (ret < 0) { + goto done; + } + + ret = mcp251xfd_init_iocon_reg(dev); + if (ret < 0) { + goto done; + } + + ret = mcp251xfd_init_int_reg(dev); + if (ret < 0) { + goto done; + } + + ret = mcp251xfd_set_tdc(dev, false, 0); + if (ret < 0) { + goto done; + } + +#if defined(CONFIG_CAN_RX_TIMESTAMP) + ret = mcp251xfd_init_tscon(dev); + if (ret < 0) { + goto done; + } +#endif + + ret = mcp251xfd_init_tef_fifo(dev); + if (ret < 0) { + goto done; + } + + ret = mcp251xfd_init_tx_queue(dev); + if (ret < 0) { + goto done; + } + + ret = mcp251xfd_init_rx_fifo(dev); + if (ret < 0) { + goto done; + } + + LOG_DBG("%d TX FIFOS: 1 element", MCP251XFD_TX_QUEUE_ITEMS); + LOG_DBG("1 RX FIFO: %d elements", MCP251XFD_RX_FIFO_ITEMS); + LOG_DBG("%db of %db RAM Allocated", + MCP251XFD_TEF_FIFO_SIZE + MCP251XFD_TX_QUEUE_SIZE + MCP251XFD_RX_FIFO_SIZE, + MCP251XFD_RAM_SIZE); + +done: + ret = can_set_timing(dev, &timing); + if (ret < 0) { + return ret; + } + +#if defined(CONFIG_CAN_FD_MODE) + ret = can_set_timing_data(dev, &timing_data); + if (ret < 0) { + return ret; + } +#endif + + return ret; +} + +static const struct can_driver_api mcp251xfd_api_funcs = { + .get_capabilities = mcp251xfd_get_capabilities, + .set_mode = mcp251xfd_set_mode, + .set_timing = mcp251xfd_set_timing, +#if defined(CONFIG_CAN_FD_MODE) + .set_timing_data = mcp251xfd_set_timing_data, +#endif + .start = mcp251xfd_start, + .stop = mcp251xfd_stop, + .send = mcp251xfd_send, + .add_rx_filter = mcp251xfd_add_rx_filter, + .remove_rx_filter = mcp251xfd_remove_rx_filter, +#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY + .recover = mcp251xfd_recover, +#endif + .get_state = mcp251xfd_get_state, + .set_state_change_callback = mcp251xfd_set_state_change_callback, + .get_core_clock = mcp251xfd_get_core_clock, + .get_max_filters = mcp251xfd_get_max_filters, + .get_max_bitrate = mcp251xfd_get_max_bitrate, + .timing_min = { + .sjw = 1, + .prop_seg = 0, + .phase_seg1 = 2, + .phase_seg2 = 1, + .prescaler = 1, + }, + .timing_max = { + .sjw = 128, + .prop_seg = 0, + .phase_seg1 = 256, + .phase_seg2 = 128, + .prescaler = 256, + }, +#if defined(CONFIG_CAN_FD_MODE) + .timing_data_min = { + .sjw = 1, + .prop_seg = 0, + .phase_seg1 = 1, + .phase_seg2 = 1, + .prescaler = 1, + }, + .timing_data_max = { + .sjw = 16, + .prop_seg = 0, + .phase_seg1 = 32, + .phase_seg2 = 16, + .prescaler = 256, + }, +#endif +}; + +#define MCP251XFD_SET_TIMING_MACRO(inst, type) \ + .timing_params##type = { \ + .sjw = DT_INST_PROP(inst, sjw##type), \ + .prop_seg = DT_INST_PROP_OR(inst, prop_seg##type, 0), \ + .phase_seg1 = DT_INST_PROP_OR(inst, phase_seg1##type, 0), \ + .phase_seg2 = DT_INST_PROP_OR(inst, phase_seg2##type, 0), \ + .bus_speed = DT_INST_PROP(inst, bus_speed##type), \ + .sample_point = DT_INST_PROP_OR(inst, sample_point##type, 0), \ + } + +#if defined(CONFIG_CAN_FD_MODE) +#define MCP251XFD_SET_TIMING(inst) \ + MCP251XFD_SET_TIMING_MACRO(inst,), \ + MCP251XFD_SET_TIMING_MACRO(inst, _data) +#else +#define MCP251XFD_SET_TIMING(inst) \ + MCP251XFD_SET_TIMING_MACRO(inst,) +#endif + +#define MCP251XFD_SET_CLOCK(inst) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, clocks), \ + (.clk_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(inst)), \ + .clk_id = DT_INST_CLOCKS_CELL(inst, id)), \ + ()) + +#define MCP251XFD_INIT(inst) \ + static K_KERNEL_STACK_DEFINE(mcp251xfd_int_stack_##inst, \ + CONFIG_CAN_MCP251XFD_INT_THREAD_STACK_SIZE); \ + \ + static struct mcp251xfd_data mcp251xfd_data_##inst = { \ + .int_thread_stack = mcp251xfd_int_stack_##inst, \ + }; \ + static const struct mcp251xfd_config mcp251xfd_config_##inst = { \ + .bus = SPI_DT_SPEC_INST_GET(inst, SPI_WORD_SET(8), 0), \ + .int_gpio_dt = GPIO_DT_SPEC_INST_GET(inst, int_gpios), \ + \ + .sof_on_clko = DT_INST_PROP(inst, sof_on_clko), \ + .clko_div = DT_INST_ENUM_IDX(inst, clko_div), \ + .pll_enable = DT_INST_PROP(inst, pll_enable), \ + .timestamp_prescaler = DT_INST_PROP(inst, timestamp_prescaler), \ + \ + .osc_freq = DT_INST_PROP(inst, osc_freq), \ + MCP251XFD_SET_TIMING(inst), \ + .phy = DEVICE_DT_GET_OR_NULL(DT_INST_PHANDLE(inst, phys)), \ + .max_bitrate = DT_INST_CAN_TRANSCEIVER_MAX_BITRATE(inst, 8000000), \ + .rx_fifo = {.ram_start_addr = MCP251XFD_RX_FIFO_START_ADDR, \ + .reg_fifocon_addr = MCP251XFD_REG_FIFOCON(MCP251XFD_RX_FIFO_IDX), \ + .capacity = MCP251XFD_RX_FIFO_ITEMS, \ + .item_size = MCP251XFD_RX_FIFO_ITEM_SIZE, \ + .msg_handler = mcp251xfd_rx_fifo_handler}, \ + .tef_fifo = {.ram_start_addr = MCP251XFD_TEF_FIFO_START_ADDR, \ + .reg_fifocon_addr = MCP251XFD_REG_TEFCON, \ + .capacity = MCP251XFD_TEF_FIFO_ITEMS, \ + .item_size = MCP251XFD_TEF_FIFO_ITEM_SIZE, \ + .msg_handler = mcp251xfd_tef_fifo_handler}, \ + MCP251XFD_SET_CLOCK(inst) \ + }; \ + \ + CAN_DEVICE_DT_INST_DEFINE(inst, &mcp251xfd_init, NULL, &mcp251xfd_data_##inst, \ + &mcp251xfd_config_##inst, POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ + &mcp251xfd_api_funcs); + +DT_INST_FOREACH_STATUS_OKAY(MCP251XFD_INIT) diff --git a/drivers/can/can_mcp251xfd.h b/drivers/can/can_mcp251xfd.h new file mode 100644 index 00000000000..b87c6ae53dd --- /dev/null +++ b/drivers/can/can_mcp251xfd.h @@ -0,0 +1,557 @@ +/* + * Copyright (c) 2020 Abram Early + * Copyright (c) 2023 Andriy Gelman + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_CAN_MICROCHIP_MCP251XFD_H_ +#define ZEPHYR_DRIVERS_CAN_MICROCHIP_MCP251XFD_H_ + +#include + +#include +#include +#include + +#define MCP251XFD_UINT32_FLAG_TO_BYTE_MASK(flag_u32) \ + ((flag_u32) >> ROUND_DOWN(LOG2((flag_u32)), 8)) + +#define MCP251XFD_RAM_START_ADDR 0x400 +#define MCP251XFD_RAM_SIZE 2048 +#define MCP251XFD_RAM_ALIGNMENT 4 +#define MCP251XFD_PAYLOAD_SIZE CAN_MAX_DLEN + +#define MCP251XFD_FIFO_TYPE_TEF 0 +#define MCP251XFD_FIFO_TYPE_RX 1 + +#define MCP251XFD_TEF_FIFO_ITEM_SIZE 8 +#define MCP251XFD_TX_QUEUE_ITEM_SIZE (8 + MCP251XFD_PAYLOAD_SIZE) + +#if defined(CONFIG_CAN_RX_TIMESTAMP) +#define MCP251XFD_RX_FIFO_ITEM_SIZE (4 + 8 + MCP251XFD_PAYLOAD_SIZE) +#else +#define MCP251XFD_RX_FIFO_ITEM_SIZE (8 + MCP251XFD_PAYLOAD_SIZE) +#endif + +#define MCP251XFD_TEF_FIFO_START_ADDR 0 +#define MCP251XFD_TEF_FIFO_ITEMS CONFIG_CAN_MCP251XFD_MAX_TX_QUEUE +#define MCP251XFD_TEF_FIFO_SIZE (MCP251XFD_TEF_FIFO_ITEMS * MCP251XFD_TEF_FIFO_ITEM_SIZE) + +#define MCP251XFD_TX_QUEUE_START_ADDR MCP251XFD_TEF_FIFO_SIZE +#define MCP251XFD_TX_QUEUE_ITEMS CONFIG_CAN_MCP251XFD_MAX_TX_QUEUE +#define MCP251XFD_TX_QUEUE_SIZE (MCP251XFD_TX_QUEUE_ITEMS * MCP251XFD_TX_QUEUE_ITEM_SIZE) + +#define MCP251XFD_RX_FIFO_START_ADDR (MCP251XFD_TX_QUEUE_START_ADDR + MCP251XFD_TX_QUEUE_SIZE) +#define MCP251XFD_RX_FIFO_SIZE_MAX (MCP251XFD_RAM_SIZE - MCP251XFD_RX_FIFO_START_ADDR) +#define MCP251XFD_RX_FIFO_ITEMS_MAX (MCP251XFD_RX_FIFO_SIZE_MAX / MCP251XFD_RX_FIFO_ITEM_SIZE) + +#define MCP251XFD_RX_FIFO_ITEMS CONFIG_CAN_MCP251XFD_RX_FIFO_ITEMS +#define MCP251XFD_RX_FIFO_SIZE (MCP251XFD_RX_FIFO_ITEMS * MCP251XFD_RX_FIFO_ITEM_SIZE) + +#define MCP251XFD_RX_FIFO_IDX 1 +#define MCP251XFD_REG_SIZE 4 + +#define MCP251XFD_CRC_POLY 0x8005 +#define MCP251XFD_CRC_SEED 0xffff + +BUILD_ASSERT(MCP251XFD_TEF_FIFO_SIZE + MCP251XFD_TX_QUEUE_SIZE + + MCP251XFD_RX_FIFO_SIZE <= MCP251XFD_RAM_SIZE, + "Cannot fit FIFOs into RAM"); + +/* Timeout for changing mode */ +#define MCP251XFD_MODE_CHANGE_TIMEOUT_USEC 200000U +#define MCP251XFD_MODE_CHANGE_RETRIES 100 + +#define MCP251XFD_PLLRDY_TIMEOUT_USEC 100000 +#define MCP251XFD_PLLRDY_RETRIES 100 + +#define MCP251XFD_MAX_INT_HANDLER_CALLS 10 +#define MCP251XFD_INT_HANDLER_SLEEP_USEC 10000 + + +struct mcp251xfd_mailbox { + can_tx_callback_t cb; + void *cb_arg; +}; + +#define MCP251XFD_SPI_CMD_LEN 2 +#define MCP251XFD_SPI_LEN_FIELD_LEN 1 +#define MCP251XFD_SPI_CRC_LEN 2 + +/* MPC251x registers - mostly copied from Linux kernel implementation of driver */ + +/* CAN FD Controller Module SFR */ +#define MCP251XFD_REG_CON 0x00 +#define MCP251XFD_REG_CON_TXBWS_MASK GENMASK(31, 28) +#define MCP251XFD_REG_CON_ABAT BIT(27) +#define MCP251XFD_REG_CON_REQOP_MASK GENMASK(26, 24) +#define MCP251XFD_REG_CON_MODE_MIXED 0 +#define MCP251XFD_REG_CON_MODE_SLEEP 1 +#define MCP251XFD_REG_CON_MODE_INT_LOOPBACK 2 +#define MCP251XFD_REG_CON_MODE_LISTENONLY 3 +#define MCP251XFD_REG_CON_MODE_CONFIG 4 +#define MCP251XFD_REG_CON_MODE_EXT_LOOPBACK 5 +#define MCP251XFD_REG_CON_MODE_CAN2_0 6 +#define MCP251XFD_REG_CON_MODE_RESTRICTED 7 +#define MCP251XFD_REG_CON_OPMOD_MASK GENMASK(23, 21) +#define MCP251XFD_REG_CON_TXQEN BIT(20) +#define MCP251XFD_REG_CON_STEF BIT(19) +#define MCP251XFD_REG_CON_SERR2LOM BIT(18) +#define MCP251XFD_REG_CON_ESIGM BIT(17) +#define MCP251XFD_REG_CON_RTXAT BIT(16) +#define MCP251XFD_REG_CON_BRSDIS BIT(12) +#define MCP251XFD_REG_CON_BUSY BIT(11) +#define MCP251XFD_REG_CON_WFT_MASK GENMASK(10, 9) +#define MCP251XFD_REG_CON_WFT_T00FILTER 0x0 +#define MCP251XFD_REG_CON_WFT_T01FILTER 0x1 +#define MCP251XFD_REG_CON_WFT_T10FILTER 0x2 +#define MCP251XFD_REG_CON_WFT_T11FILTER 0x3 +#define MCP251XFD_REG_CON_WAKFIL BIT(8) +#define MCP251XFD_REG_CON_PXEDIS BIT(6) +#define MCP251XFD_REG_CON_ISOCRCEN BIT(5) +#define MCP251XFD_REG_CON_DNCNT_MASK GENMASK(4, 0) + +#define MCP251XFD_REG_CON_B2 (MCP251XFD_REG_CON + 2) +#define MCP251XFD_REG_CON_B3 (MCP251XFD_REG_CON + 3) + +#define MCP251XFD_REG_NBTCFG 0x04 +#define MCP251XFD_REG_NBTCFG_BRP_MASK GENMASK(31, 24) +#define MCP251XFD_REG_NBTCFG_TSEG1_MASK GENMASK(23, 16) +#define MCP251XFD_REG_NBTCFG_TSEG2_MASK GENMASK(14, 8) +#define MCP251XFD_REG_NBTCFG_SJW_MASK GENMASK(6, 0) + +#define MCP251XFD_REG_DBTCFG 0x08 +#define MCP251XFD_REG_DBTCFG_BRP_MASK GENMASK(31, 24) +#define MCP251XFD_REG_DBTCFG_TSEG1_MASK GENMASK(20, 16) +#define MCP251XFD_REG_DBTCFG_TSEG2_MASK GENMASK(11, 8) +#define MCP251XFD_REG_DBTCFG_SJW_MASK GENMASK(3, 0) + +#define MCP251XFD_REG_TDC 0x0c +#define MCP251XFD_REG_TDC_EDGFLTEN BIT(25) +#define MCP251XFD_REG_TDC_SID11EN BIT(24) +#define MCP251XFD_REG_TDC_TDCMOD_MASK GENMASK(17, 16) +#define MCP251XFD_REG_TDC_TDCMOD_AUTO 2 +#define MCP251XFD_REG_TDC_TDCMOD_MANUAL 1 +#define MCP251XFD_REG_TDC_TDCMOD_DISABLED 0 +#define MCP251XFD_REG_TDC_TDCO_MASK GENMASK(14, 8) +#define MCP251XFD_REG_TDC_TDCV_MASK GENMASK(5, 0) +#define MCP251XFD_REG_TDC_TDCO_MIN -64 +#define MCP251XFD_REG_TDC_TDCO_MAX 63 + +#define MCP251XFD_REG_TBC 0x10 + +#define MCP251XFD_REG_TSCON 0x14 +#define MCP251XFD_REG_TSCON_TSRES BIT(18) +#define MCP251XFD_REG_TSCON_TSEOF BIT(17) +#define MCP251XFD_REG_TSCON_TBCEN BIT(16) +#define MCP251XFD_REG_TSCON_TBCPRE_MASK GENMASK(9, 0) + +#define MCP251XFD_REG_VEC 0x18 +#define MCP251XFD_REG_VEC_RXCODE_MASK GENMASK(30, 24) +#define MCP251XFD_REG_VEC_TXCODE_MASK GENMASK(22, 16) +#define MCP251XFD_REG_VEC_FILHIT_MASK GENMASK(12, 8) +#define MCP251XFD_REG_VEC_ICODE_MASK GENMASK(6, 0) + +#define MCP251XFD_REG_INT 0x1c +#define MCP251XFD_REG_INT_IF_MASK GENMASK(15, 0) +#define MCP251XFD_REG_INT_IE_MASK GENMASK(31, 16) +#define MCP251XFD_REG_INT_IVMIE BIT(31) +#define MCP251XFD_REG_INT_WAKIE BIT(30) +#define MCP251XFD_REG_INT_CERRIE BIT(29) +#define MCP251XFD_REG_INT_SERRIE BIT(28) +#define MCP251XFD_REG_INT_RXOVIE BIT(27) +#define MCP251XFD_REG_INT_TXATIE BIT(26) +#define MCP251XFD_REG_INT_SPICRCIE BIT(25) +#define MCP251XFD_REG_INT_ECCIE BIT(24) +#define MCP251XFD_REG_INT_TEFIE BIT(20) +#define MCP251XFD_REG_INT_MODIE BIT(19) +#define MCP251XFD_REG_INT_TBCIE BIT(18) +#define MCP251XFD_REG_INT_RXIE BIT(17) +#define MCP251XFD_REG_INT_TXIE BIT(16) +#define MCP251XFD_REG_INT_IVMIF BIT(15) +#define MCP251XFD_REG_INT_WAKIF BIT(14) +#define MCP251XFD_REG_INT_CERRIF BIT(13) +#define MCP251XFD_REG_INT_SERRIF BIT(12) +#define MCP251XFD_REG_INT_RXOVIF BIT(11) +#define MCP251XFD_REG_INT_TXATIF BIT(10) +#define MCP251XFD_REG_INT_SPICRCIF BIT(9) +#define MCP251XFD_REG_INT_ECCIF BIT(8) +#define MCP251XFD_REG_INT_TEFIF BIT(4) +#define MCP251XFD_REG_INT_MODIF BIT(3) +#define MCP251XFD_REG_INT_TBCIF BIT(2) +#define MCP251XFD_REG_INT_RXIF BIT(1) +#define MCP251XFD_REG_INT_TXIF BIT(0) + +/* These IRQ flags must be cleared by SW in the CAN_INT register */ +#define MCP251XFD_REG_INT_IF_CLEARABLE_MASK \ + (MCP251XFD_REG_INT_IVMIF | MCP251XFD_REG_INT_WAKIF | MCP251XFD_REG_INT_CERRIF | \ + MCP251XFD_REG_INT_SERRIF | MCP251XFD_REG_INT_MODIF) + +#define MCP251XFD_REG_RXIF 0x20 +#define MCP251XFD_REG_TXIF 0x24 +#define MCP251XFD_REG_RXOVIF 0x28 +#define MCP251XFD_REG_TXATIF 0x2c +#define MCP251XFD_REG_TXREQ 0x30 + +#define MCP251XFD_REG_TREC 0x34 +#define MCP251XFD_REG_TREC_TXBO BIT(21) +#define MCP251XFD_REG_TREC_TXBP BIT(20) +#define MCP251XFD_REG_TREC_RXBP BIT(19) +#define MCP251XFD_REG_TREC_TXWARN BIT(18) +#define MCP251XFD_REG_TREC_RXWARN BIT(17) +#define MCP251XFD_REG_TREC_EWARN BIT(16) +#define MCP251XFD_REG_TREC_TEC_MASK GENMASK(15, 8) +#define MCP251XFD_REG_TREC_REC_MASK GENMASK(7, 0) + +#define MCP251XFD_REG_BDIAG0 0x38 +#define MCP251XFD_REG_BDIAG0_DTERRCNT_MASK GENMASK(31, 24) +#define MCP251XFD_REG_BDIAG0_DRERRCNT_MASK GENMASK(23, 16) +#define MCP251XFD_REG_BDIAG0_NTERRCNT_MASK GENMASK(15, 8) +#define MCP251XFD_REG_BDIAG0_NRERRCNT_MASK GENMASK(7, 0) + +#define MCP251XFD_REG_BDIAG1 0x3c +#define MCP251XFD_REG_BDIAG1_DLCMM BIT(31) +#define MCP251XFD_REG_BDIAG1_ESI BIT(30) +#define MCP251XFD_REG_BDIAG1_DCRCERR BIT(29) +#define MCP251XFD_REG_BDIAG1_DSTUFERR BIT(28) +#define MCP251XFD_REG_BDIAG1_DFORMERR BIT(27) +#define MCP251XFD_REG_BDIAG1_DBIT1ERR BIT(25) +#define MCP251XFD_REG_BDIAG1_DBIT0ERR BIT(24) +#define MCP251XFD_REG_BDIAG1_TXBOERR BIT(23) +#define MCP251XFD_REG_BDIAG1_NCRCERR BIT(21) +#define MCP251XFD_REG_BDIAG1_NSTUFERR BIT(20) +#define MCP251XFD_REG_BDIAG1_NFORMERR BIT(19) +#define MCP251XFD_REG_BDIAG1_NACKERR BIT(18) +#define MCP251XFD_REG_BDIAG1_NBIT1ERR BIT(17) +#define MCP251XFD_REG_BDIAG1_NBIT0ERR BIT(16) +#define MCP251XFD_REG_BDIAG1_BERR_MASK \ + (MCP251XFD_REG_BDIAG1_DLCMM | MCP251XFD_REG_BDIAG1_ESI | MCP251XFD_REG_BDIAG1_DCRCERR | \ + MCP251XFD_REG_BDIAG1_DSTUFERR | MCP251XFD_REG_BDIAG1_DFORMERR | \ + MCP251XFD_REG_BDIAG1_DBIT1ERR | MCP251XFD_REG_BDIAG1_DBIT0ERR | \ + MCP251XFD_REG_BDIAG1_TXBOERR | MCP251XFD_REG_BDIAG1_NCRCERR | \ + MCP251XFD_REG_BDIAG1_NSTUFERR | MCP251XFD_REG_BDIAG1_NFORMERR | \ + MCP251XFD_REG_BDIAG1_NACKERR | MCP251XFD_REG_BDIAG1_NBIT1ERR | \ + MCP251XFD_REG_BDIAG1_NBIT0ERR) +#define MCP251XFD_REG_BDIAG1_EFMSGCNT_MASK GENMASK(15, 0) + +#define MCP251XFD_REG_TEFCON 0x40 +#define MCP251XFD_REG_TEFCON_FSIZE_MASK GENMASK(28, 24) +#define MCP251XFD_REG_TEFCON_FRESET BIT(10) +#define MCP251XFD_REG_TEFCON_UINC BIT(8) +#define MCP251XFD_REG_TEFCON_TEFTSEN BIT(5) +#define MCP251XFD_REG_TEFCON_TEFOVIE BIT(3) +#define MCP251XFD_REG_TEFCON_TEFFIE BIT(2) +#define MCP251XFD_REG_TEFCON_TEFHIE BIT(1) +#define MCP251XFD_REG_TEFCON_TEFNEIE BIT(0) + +#define MCP251XFD_REG_TEFSTA 0x44 +#define MCP251XFD_REG_TEFSTA_TEFOVIF BIT(3) +#define MCP251XFD_REG_TEFSTA_TEFFIF BIT(2) +#define MCP251XFD_REG_TEFSTA_TEFHIF BIT(1) +#define MCP251XFD_REG_TEFSTA_TEFNEIF BIT(0) + +#define MCP251XFD_REG_TEFUA 0x48 + +#define MCP251XFD_REG_TXQCON 0x50 +#define MCP251XFD_REG_TXQCON_PLSIZE_MASK GENMASK(31, 29) +#define MCP251XFD_REG_TXQCON_PLSIZE_8 0 +#define MCP251XFD_REG_TXQCON_PLSIZE_12 1 +#define MCP251XFD_REG_TXQCON_PLSIZE_16 2 +#define MCP251XFD_REG_TXQCON_PLSIZE_20 3 +#define MCP251XFD_REG_TXQCON_PLSIZE_24 4 +#define MCP251XFD_REG_TXQCON_PLSIZE_32 5 +#define MCP251XFD_REG_TXQCON_PLSIZE_48 6 +#define MCP251XFD_REG_TXQCON_PLSIZE_64 7 +#define MCP251XFD_REG_TXQCON_FSIZE_MASK GENMASK(28, 24) +#define MCP251XFD_REG_TXQCON_TXAT_UNLIMITED 3 +#define MCP251XFD_REG_TXQCON_TXAT_THREE_SHOT 1 +#define MCP251XFD_REG_TXQCON_TXAT_ONE_SHOT 0 +#define MCP251XFD_REG_TXQCON_TXAT_MASK GENMASK(22, 21) +#define MCP251XFD_REG_TXQCON_TXPRI_MASK GENMASK(20, 16) +#define MCP251XFD_REG_TXQCON_FRESET BIT(10) +#define MCP251XFD_REG_TXQCON_TXREQ BIT(9) +#define MCP251XFD_REG_TXQCON_UINC BIT(8) +#define MCP251XFD_REG_TXQCON_TXEN BIT(7) +#define MCP251XFD_REG_TXQCON_TXATIE BIT(4) +#define MCP251XFD_REG_TXQCON_TXQEIE BIT(2) +#define MCP251XFD_REG_TXQCON_TXQNIE BIT(0) + +#define MCP251XFD_REG_TXQSTA 0x54 +#define MCP251XFD_REG_TXQSTA_TXQCI_MASK GENMASK(12, 8) +#define MCP251XFD_REG_TXQSTA_TXABT BIT(7) +#define MCP251XFD_REG_TXQSTA_TXLARB BIT(6) +#define MCP251XFD_REG_TXQSTA_TXERR BIT(5) +#define MCP251XFD_REG_TXQSTA_TXATIF BIT(4) +#define MCP251XFD_REG_TXQSTA_TXQEIF BIT(2) +#define MCP251XFD_REG_TXQSTA_TXQNIF BIT(0) + +#define MCP251XFD_REG_TXQUA 0x58 + +#define MCP251XFD_REG_FIFOCON(x) (0x50 + 0xc * (x)) +#define MCP251XFD_REG_FIFOCON_PLSIZE_MASK GENMASK(31, 29) +#define MCP251XFD_REG_FIFOCON_PLSIZE_8 0 +#define MCP251XFD_REG_FIFOCON_PLSIZE_12 1 +#define MCP251XFD_REG_FIFOCON_PLSIZE_16 2 +#define MCP251XFD_REG_FIFOCON_PLSIZE_20 3 +#define MCP251XFD_REG_FIFOCON_PLSIZE_24 4 +#define MCP251XFD_REG_FIFOCON_PLSIZE_32 5 +#define MCP251XFD_REG_FIFOCON_PLSIZE_48 6 +#define MCP251XFD_REG_FIFOCON_PLSIZE_64 7 +#define MCP251XFD_REG_FIFOCON_FSIZE_MASK GENMASK(28, 24) +#define MCP251XFD_REG_FIFOCON_TXAT_MASK GENMASK(22, 21) +#define MCP251XFD_REG_FIFOCON_TXAT_ONE_SHOT 0 +#define MCP251XFD_REG_FIFOCON_TXAT_THREE_SHOT 1 +#define MCP251XFD_REG_FIFOCON_TXAT_UNLIMITED 3 +#define MCP251XFD_REG_FIFOCON_TXPRI_MASK GENMASK(20, 16) +#define MCP251XFD_REG_FIFOCON_FRESET BIT(10) +#define MCP251XFD_REG_FIFOCON_TXREQ BIT(9) +#define MCP251XFD_REG_FIFOCON_UINC BIT(8) +#define MCP251XFD_REG_FIFOCON_TXEN BIT(7) +#define MCP251XFD_REG_FIFOCON_RTREN BIT(6) +#define MCP251XFD_REG_FIFOCON_RXTSEN BIT(5) +#define MCP251XFD_REG_FIFOCON_TXATIE BIT(4) +#define MCP251XFD_REG_FIFOCON_RXOVIE BIT(3) +#define MCP251XFD_REG_FIFOCON_TFERFFIE BIT(2) +#define MCP251XFD_REG_FIFOCON_TFHRFHIE BIT(1) +#define MCP251XFD_REG_FIFOCON_TFNRFNIE BIT(0) + +#define MCP251XFD_REG_FIFOSTA(x) (0x54 + 0xc * (x)) +#define MCP251XFD_REG_FIFOSTA_FIFOCI_MASK GENMASK(12, 8) +#define MCP251XFD_REG_FIFOSTA_TXABT BIT(7) +#define MCP251XFD_REG_FIFOSTA_TXLARB BIT(6) +#define MCP251XFD_REG_FIFOSTA_TXERR BIT(5) +#define MCP251XFD_REG_FIFOSTA_TXATIF BIT(4) +#define MCP251XFD_REG_FIFOSTA_RXOVIF BIT(3) +#define MCP251XFD_REG_FIFOSTA_TFERFFIF BIT(2) +#define MCP251XFD_REG_FIFOSTA_TFHRFHIF BIT(1) +#define MCP251XFD_REG_FIFOSTA_TFNRFNIF BIT(0) + +#define MCP251XFD_REG_FIFOUA(x) (0x58 + 0xc * (x)) + +#define MCP251XFD_REG_BYTE_FLTCON(m) (0x1d0 + m) +#define MCP251XFD_REG_BYTE_FLTCON_FBP_MASK GENMASK(4, 0) +#define MCP251XFD_REG_BYTE_FLTCON_FLTEN BIT(7) + +#define MCP251XFD_REG_FLTOBJ(x) (0x1f0 + 0x8 * (x)) +#define MCP251XFD_REG_FLTOBJ_EXIDE BIT(30) +#define MCP251XFD_REG_FLTOBJ_SID11 BIT(29) +#define MCP251XFD_REG_FLTOBJ_EID_MASK GENMASK(28, 11) +#define MCP251XFD_REG_FLTOBJ_SID_MASK GENMASK(10, 0) + +#define MCP251XFD_REG_FLTMASK(x) (0x1f4 + 0x8 * (x)) +#define MCP251XFD_REG_MASK_MIDE BIT(30) +#define MCP251XFD_REG_MASK_MSID11 BIT(29) +#define MCP251XFD_REG_MASK_MEID_MASK GENMASK(28, 11) +#define MCP251XFD_REG_MASK_MSID_MASK GENMASK(10, 0) + +/* Message Object */ +#define MCP251XFD_OBJ_ID_SID11 BIT(29) +#define MCP251XFD_OBJ_ID_EID_MASK GENMASK(28, 11) +#define MCP251XFD_OBJ_ID_SID_MASK GENMASK(10, 0) +#define MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK GENMASK(31, 9) +#define MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK GENMASK(15, 9) +#define MCP251XFD_OBJ_FLAGS_SEQ_MASK MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK +#define MCP251XFD_OBJ_FLAGS_ESI BIT(8) +#define MCP251XFD_OBJ_FLAGS_FDF BIT(7) +#define MCP251XFD_OBJ_FLAGS_BRS BIT(6) +#define MCP251XFD_OBJ_FLAGS_RTR BIT(5) +#define MCP251XFD_OBJ_FLAGS_IDE BIT(4) +#define MCP251XFD_OBJ_FLAGS_DLC_MASK GENMASK(3, 0) +#define MCP251XFD_OBJ_FILHIT_MASK GENMASK(15, 11) + +#define MCP251XFD_OBJ_DATA_OFFSET 2 /* offset to the data in sizeof(uint32_t) */ +#define MCP251XFD_OBJ_HEADER_SIZE (MCP251XFD_OBJ_DATA_OFFSET * MCP251XFD_REG_SIZE) + +#define MCP251XFD_REG_FRAME_EFF_SID_MASK GENMASK(28, 18) +#define MCP251XFD_REG_FRAME_EFF_EID_MASK GENMASK(17, 0) + +/* MCP2517/18FD SFR */ +#define MCP251XFD_REG_OSC 0xe00 +#define MCP251XFD_REG_OSC_SCLKRDY BIT(12) +#define MCP251XFD_REG_OSC_OSCRDY BIT(10) +#define MCP251XFD_REG_OSC_PLLRDY BIT(8) +#define MCP251XFD_REG_OSC_CLKODIV_10 3 +#define MCP251XFD_REG_OSC_CLKODIV_4 2 +#define MCP251XFD_REG_OSC_CLKODIV_2 1 +#define MCP251XFD_REG_OSC_CLKODIV_1 0 +#define MCP251XFD_REG_OSC_CLKODIV_MASK GENMASK(6, 5) +#define MCP251XFD_REG_OSC_SCLKDIV BIT(4) +#define MCP251XFD_REG_OSC_LPMEN BIT(3) /* MCP2518FD only */ +#define MCP251XFD_REG_OSC_OSCDIS BIT(2) +#define MCP251XFD_REG_OSC_PLLEN BIT(0) + +#define MCP251XFD_REG_IOCON 0xe04 +#define MCP251XFD_REG_IOCON_INTOD BIT(30) +#define MCP251XFD_REG_IOCON_SOF BIT(29) +#define MCP251XFD_REG_IOCON_TXCANOD BIT(28) +#define MCP251XFD_REG_IOCON_PM1 BIT(25) +#define MCP251XFD_REG_IOCON_PM0 BIT(24) +#define MCP251XFD_REG_IOCON_GPIO1 BIT(17) +#define MCP251XFD_REG_IOCON_GPIO0 BIT(16) +#define MCP251XFD_REG_IOCON_LAT1 BIT(9) +#define MCP251XFD_REG_IOCON_LAT0 BIT(8) +#define MCP251XFD_REG_IOCON_XSTBYEN BIT(6) +#define MCP251XFD_REG_IOCON_TRIS1 BIT(1) +#define MCP251XFD_REG_IOCON_TRIS0 BIT(0) + +#define MCP251XFD_REG_CRC 0xe08 +#define MCP251XFD_REG_CRC_FERRIE BIT(25) +#define MCP251XFD_REG_CRC_CRCERRIE BIT(24) +#define MCP251XFD_REG_CRC_FERRIF BIT(17) +#define MCP251XFD_REG_CRC_CRCERRIF BIT(16) +#define MCP251XFD_REG_CRC_IF_MASK GENMASK(17, 16) +#define MCP251XFD_REG_CRC_MASK GENMASK(15, 0) + +#define MCP251XFD_REG_ECCCON 0xe0c +#define MCP251XFD_REG_ECCCON_PARITY_MASK GENMASK(14, 8) +#define MCP251XFD_REG_ECCCON_DEDIE BIT(2) +#define MCP251XFD_REG_ECCCON_SECIE BIT(1) +#define MCP251XFD_REG_ECCCON_ECCEN BIT(0) + +#define MCP251XFD_REG_ECCSTAT 0xe10 +#define MCP251XFD_REG_ECCSTAT_ERRADDR_MASK GENMASK(27, 16) +#define MCP251XFD_REG_ECCSTAT_IF_MASK GENMASK(2, 1) +#define MCP251XFD_REG_ECCSTAT_DEDIF BIT(2) +#define MCP251XFD_REG_ECCSTAT_SECIF BIT(1) + +#define MCP251XFD_REG_DEVID 0xe14 /* MCP2518FD only */ +#define MCP251XFD_REG_DEVID_ID_MASK GENMASK(7, 4) +#define MCP251XFD_REG_DEVID_REV_MASK GENMASK(3, 0) + +/* SPI commands */ +#define MCP251XFD_SPI_INSTRUCTION_RESET 0x0000 +#define MCP251XFD_SPI_INSTRUCTION_WRITE 0x2000 +#define MCP251XFD_SPI_INSTRUCTION_READ 0x3000 +#define MCP251XFD_SPI_INSTRUCTION_WRITE_CRC 0xa000 +#define MCP251XFD_SPI_INSTRUCTION_READ_CRC 0xb000 +#define MCP251XFD_SPI_INSTRUCTION_WRITE_CRC_SAFE 0xc000 +#define MCP251XFD_SPI_ADDRESS_MASK GENMASK(11, 0) + +#define MCP251XFD_REG_FIFOCON_TO_STA(addr) (addr + 0x4) + +#define MCP251XFD_REG_FLTCON(m) (0x1d0 + m) + +struct mcp251xfd_txobj { + uint32_t id; + uint32_t flags; + uint8_t data[CAN_MAX_DLEN]; +} __packed; + +struct mcp251xfd_rxobj { + uint32_t id; + uint32_t flags; +#if defined(CONFIG_CAN_RX_TIMESTAMP) + uint32_t timestamp; +#endif + uint8_t data[CAN_MAX_DLEN]; +} __packed; + +struct mcp251xfd_tefobj { + uint32_t id; + uint32_t flags; +} __packed; + +#define MCP251XFD_MAX_READ_FIFO_BUF_SIZE \ + MAX((MCP251XFD_RX_FIFO_ITEM_SIZE * MCP251XFD_RX_FIFO_ITEMS), \ + (MCP251XFD_TEF_FIFO_ITEM_SIZE * MCP251XFD_TEF_FIFO_ITEMS)) + +#define MCP251XFD_MAX_READ_CRC_BUF_SIZE \ + (MCP251XFD_SPI_CRC_LEN + 2 * MCP251XFD_REG_SIZE) + +#define MCP251XFD_SPI_BUF_SIZE \ + MAX(MCP251XFD_MAX_READ_FIFO_BUF_SIZE, MCP251XFD_MAX_READ_CRC_BUF_SIZE) +#define MCP251XFD_SPI_HEADER_LEN (MCP251XFD_SPI_CMD_LEN + MCP251XFD_SPI_LEN_FIELD_LEN) + +struct mcp251xfd_spi_data { + uint8_t _unused[4 - (MCP251XFD_SPI_HEADER_LEN % 4)]; /* so that buf is 4-byte aligned */ + uint8_t header[MCP251XFD_SPI_HEADER_LEN]; /* contains spi_cmd and length field (if used) */ + uint8_t buf[MCP251XFD_SPI_BUF_SIZE]; +} __packed __aligned(4); + +struct mcp251xfd_fifo { + uint32_t ram_start_addr; + uint16_t reg_fifocon_addr; + uint8_t capacity; + uint8_t item_size; + void (*msg_handler)(const struct device *dev, void *data); +}; + +struct mcp251xfd_data { + /* Interrupt Data */ + struct gpio_callback int_gpio_cb; + struct k_thread int_thread; + k_thread_stack_t *int_thread_stack; + struct k_sem int_sem; + + /* General */ + enum can_state state; + can_state_change_callback_t state_change_cb; + void *state_change_cb_data; + struct k_mutex mutex; + + /* TX Callback */ + struct k_sem tx_sem; + uint32_t mailbox_usage; + struct mcp251xfd_mailbox mailbox[CONFIG_CAN_MCP251XFD_MAX_TX_QUEUE]; + + /* Filter Data */ + uint32_t filter_usage; + struct can_filter filter[CONFIG_CAN_MAX_FILTER]; + can_rx_callback_t rx_cb[CONFIG_CAN_MAX_FILTER]; + void *cb_arg[CONFIG_CAN_MAX_FILTER]; + + const struct device *dev; + + bool started; + uint8_t next_mcp251xfd_mode; + uint8_t current_mcp251xfd_mode; + int tdco; + + can_mode_t mode; + + struct mcp251xfd_spi_data spi_data; + +}; + +struct mcp251xfd_timing_params { + uint8_t sjw; + uint8_t prop_seg; + uint8_t phase_seg1; + uint8_t phase_seg2; + uint32_t bus_speed; + uint16_t sample_point; +}; + +struct mcp251xfd_config { + /* spi configuration */ + struct spi_dt_spec bus; + struct gpio_dt_spec int_gpio_dt; + + uint32_t osc_freq; + + /* IO Config */ + bool sof_on_clko; + bool pll_enable; + uint8_t clko_div; + + uint16_t timestamp_prescaler; + + /* CAN Timing */ + struct mcp251xfd_timing_params timing_params; +#if defined(CONFIG_CAN_FD_MODE) + struct mcp251xfd_timing_params timing_params_data; +#endif + + /* CAN transceiver */ + const struct device *phy; + uint32_t max_bitrate; + + const struct device *clk_dev; + uint8_t clk_id; + + struct mcp251xfd_fifo rx_fifo; + struct mcp251xfd_fifo tef_fifo; +}; + +#endif /* ZEPHYR_DRIVERS_CAN_MICROCHIP_MCP251XFD_H_ */ diff --git a/drivers/can/can_mcux_flexcan.c b/drivers/can/can_mcux_flexcan.c index d212903f34b..4138678911c 100644 --- a/drivers/can/can_mcux_flexcan.c +++ b/drivers/can/can_mcux_flexcan.c @@ -7,7 +7,7 @@ /* Base driver compatible */ #define DT_DRV_COMPAT nxp_flexcan -/* CAN-FD extension compatible */ +/* CAN FD extension compatible */ #define FLEXCAN_FD_DRV_COMPAT nxp_flexcan_fd #include @@ -182,7 +182,6 @@ static int mcux_flexcan_set_timing(const struct device *dev, const struct can_timing *timing) { struct mcux_flexcan_data *data = dev->data; - uint8_t sjw_backup = data->timing.sjw; if (!timing) { return -EINVAL; @@ -193,9 +192,6 @@ static int mcux_flexcan_set_timing(const struct device *dev, } data->timing = *timing; - if (timing->sjw == CAN_SJW_NO_CHANGE) { - data->timing.sjw = sjw_backup; - } return 0; } @@ -205,7 +201,6 @@ static int mcux_flexcan_set_timing_data(const struct device *dev, const struct can_timing *timing_data) { struct mcux_flexcan_data *data = dev->data; - uint8_t sjw_backup = data->timing_data.sjw; if (!timing_data) { return -EINVAL; @@ -216,9 +211,6 @@ static int mcux_flexcan_set_timing_data(const struct device *dev, } data->timing_data = *timing_data; - if (timing_data->sjw == CAN_SJW_NO_CHANGE) { - data->timing_data.sjw = sjw_backup; - } return 0; } @@ -451,7 +443,7 @@ static int mcux_flexcan_set_mode(const struct device *dev, can_mode_t mode) } if ((mode & CAN_MODE_FD) != 0 && (mode & CAN_MODE_3_SAMPLES) != 0) { - LOG_ERR("triple samling is not supported in CAN-FD mode"); + LOG_ERR("triple samling is not supported in CAN FD mode"); return -ENOTSUP; } @@ -487,7 +479,7 @@ static int mcux_flexcan_set_mode(const struct device *dev, can_mode_t mode) #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD if (config->flexcan_fd) { if ((mode & CAN_MODE_FD) != 0) { - /* Enable CAN-FD mode */ + /* Enable CAN FD mode */ mcr |= CAN_MCR_FDEN_MASK; data->fd_mode = true; @@ -498,7 +490,7 @@ static int mcux_flexcan_set_mode(const struct device *dev, can_mode_t mode) config->base->FDCTRL |= CAN_FDCTRL_TDCEN_MASK; } } else { - /* Disable CAN-FD mode */ + /* Disable CAN FD mode */ mcr &= ~(CAN_MCR_FDEN_MASK); data->fd_mode = false; } @@ -528,11 +520,11 @@ static void mcux_flexcan_from_can_frame(const struct can_frame *src, dest->type = kFLEXCAN_FrameTypeRemote; } else { dest->type = kFLEXCAN_FrameTypeData; + dest->dataWord0 = sys_cpu_to_be32(src->data_32[0]); + dest->dataWord1 = sys_cpu_to_be32(src->data_32[1]); } dest->length = src->dlc; - dest->dataWord0 = sys_cpu_to_be32(src->data_32[0]); - dest->dataWord1 = sys_cpu_to_be32(src->data_32[1]); } static void mcux_flexcan_to_can_frame(const flexcan_frame_t *src, @@ -549,11 +541,12 @@ static void mcux_flexcan_to_can_frame(const flexcan_frame_t *src, if (src->type == kFLEXCAN_FrameTypeRemote) { dest->flags |= CAN_FRAME_RTR; + } else { + dest->data_32[0] = sys_be32_to_cpu(src->dataWord0); + dest->data_32[1] = sys_be32_to_cpu(src->dataWord1); } dest->dlc = src->length; - dest->data_32[0] = sys_be32_to_cpu(src->dataWord0); - dest->data_32[1] = sys_be32_to_cpu(src->dataWord1); #ifdef CONFIG_CAN_RX_TIMESTAMP dest->timestamp = src->timestamp; #endif /* CAN_RX_TIMESTAMP */ @@ -579,6 +572,10 @@ static void mcux_flexcan_fd_from_can_frame(const struct can_frame *src, dest->type = kFLEXCAN_FrameTypeRemote; } else { dest->type = kFLEXCAN_FrameTypeData; + + for (i = 0; i < ARRAY_SIZE(dest->dataWord); i++) { + dest->dataWord[i] = sys_cpu_to_be32(src->data_32[i]); + } } if ((src->flags & CAN_FRAME_FDF) != 0) { @@ -590,9 +587,6 @@ static void mcux_flexcan_fd_from_can_frame(const struct can_frame *src, } dest->length = src->dlc; - for (i = 0; i < ARRAY_SIZE(dest->dataWord); i++) { - dest->dataWord[i] = sys_cpu_to_be32(src->data_32[i]); - } } static void mcux_flexcan_fd_to_can_frame(const flexcan_fd_frame_t *src, @@ -611,6 +605,10 @@ static void mcux_flexcan_fd_to_can_frame(const flexcan_fd_frame_t *src, if (src->type == kFLEXCAN_FrameTypeRemote) { dest->flags |= CAN_FRAME_RTR; + } else { + for (i = 0; i < ARRAY_SIZE(dest->data_32); i++) { + dest->data_32[i] = sys_be32_to_cpu(src->dataWord[i]); + } } if (src->edl != 0) { @@ -626,9 +624,7 @@ static void mcux_flexcan_fd_to_can_frame(const flexcan_fd_frame_t *src, } dest->dlc = src->length; - for (i = 0; i < ARRAY_SIZE(dest->data_32); i++) { - dest->data_32[i] = sys_be32_to_cpu(src->dataWord[i]); - } + #ifdef CONFIG_CAN_RX_TIMESTAMP dest->timestamp = src->timestamp; #endif /* CAN_RX_TIMESTAMP */ @@ -853,7 +849,7 @@ static int mcux_flexcan_add_rx_filter(const struct device *dev, } #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD - /* Defer starting FlexCAN-FD MBs unless started */ + /* Defer starting FlexCAN FD MBs unless started */ if (!config->flexcan_fd || data->started) { #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */ status = mcux_flexcan_mb_start(dev, alloc); @@ -926,9 +922,8 @@ static void mcux_flexcan_remove_rx_filter(const struct device *dev, int filter_i { struct mcux_flexcan_data *data = dev->data; - if (filter_id >= MCUX_FLEXCAN_MAX_RX) { - LOG_ERR("Detach: Filter id >= MAX_RX (%d >= %d)", filter_id, - MCUX_FLEXCAN_MAX_RX); + if (filter_id < 0 || filter_id >= MCUX_FLEXCAN_MAX_RX) { + LOG_ERR("filter ID %d out of bounds", filter_id); return; } @@ -938,7 +933,7 @@ static void mcux_flexcan_remove_rx_filter(const struct device *dev, int filter_i #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD const struct mcux_flexcan_config *config = dev->config; - /* Stop FlexCAN-FD MBs unless already in stopped mode */ + /* Stop FlexCAN FD MBs unless already in stopped mode */ if (!config->flexcan_fd || data->started) { #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */ mcux_flexcan_mb_stop(dev, filter_id); @@ -1203,6 +1198,7 @@ static int mcux_flexcan_init(const struct device *dev) data->timing.phase_seg2); LOG_DBG("Sample-point err : %d", err); } else { + data->timing.sjw = config->sjw; data->timing.prop_seg = config->prop_seg; data->timing.phase_seg1 = config->phase_seg1; data->timing.phase_seg2 = config->phase_seg2; @@ -1212,6 +1208,13 @@ static int mcux_flexcan_init(const struct device *dev) } } + /* Validate initial timing parameters */ + err = can_set_timing(dev, &data->timing); + if (err != 0) { + LOG_ERR("failed to set timing (err %d)", err); + return -ENODEV; + } + #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD if (config->flexcan_fd) { data->timing_data.sjw = config->sjw_data; @@ -1227,15 +1230,24 @@ static int mcux_flexcan_init(const struct device *dev) data->timing_data.phase_seg2); LOG_DBG("Sample-point err : %d", err); } else { - data->timing_data.prop_seg = config->prop_seg; - data->timing_data.phase_seg1 = config->phase_seg1; - data->timing_data.phase_seg2 = config->phase_seg2; + data->timing_data.sjw = config->sjw_data; + data->timing_data.prop_seg = config->prop_seg_data; + data->timing_data.phase_seg1 = config->phase_seg1_data; + data->timing_data.phase_seg2 = config->phase_seg2_data; err = can_calc_prescaler(dev, &data->timing_data, config->bitrate_data); if (err) { LOG_WRN("Bitrate error: %d", err); } } } + + /* Validate initial data phase timing parameters */ + err = can_set_timing_data(dev, &data->timing_data); + if (err != 0) { + LOG_ERR("failed to set data phase timing (err %d)", err); + return -ENODEV; + } + #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */ err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); diff --git a/drivers/can/can_mcux_mcan.c b/drivers/can/can_mcux_mcan.c index 73caabb9d9c..eb382c95292 100644 --- a/drivers/can/can_mcux_mcan.c +++ b/drivers/can/can_mcux_mcan.c @@ -208,12 +208,12 @@ static const struct can_mcan_ops mcux_mcan_ops = { static struct can_mcan_data can_mcan_data_##n = \ CAN_MCAN_DATA_INITIALIZER(NULL); \ \ - DEVICE_DT_INST_DEFINE(n, &mcux_mcan_init, NULL, \ - &can_mcan_data_##n, \ - &can_mcan_config_##n, \ - POST_KERNEL, \ - CONFIG_CAN_INIT_PRIORITY, \ - &mcux_mcan_driver_api); \ + CAN_DEVICE_DT_INST_DEFINE(n, mcux_mcan_init, NULL, \ + &can_mcan_data_##n, \ + &can_mcan_config_##n, \ + POST_KERNEL, \ + CONFIG_CAN_INIT_PRIORITY, \ + &mcux_mcan_driver_api); \ \ static void mcux_mcan_irq_config_##n(const struct device *dev) \ { \ diff --git a/drivers/can/can_native_posix_linux.c b/drivers/can/can_native_posix_linux.c index c3a12c9441f..7f8a0ea494f 100644 --- a/drivers/can/can_native_posix_linux.c +++ b/drivers/can/can_native_posix_linux.c @@ -239,6 +239,7 @@ static void can_npl_remove_rx_filter(const struct device *dev, int filter_id) struct can_npl_data *data = dev->data; if (filter_id < 0 || filter_id >= ARRAY_SIZE(data->filters)) { + LOG_ERR("filter ID %d out of bounds"); return; } @@ -488,9 +489,9 @@ static const struct can_npl_config can_npl_cfg_##inst = { \ \ static struct can_npl_data can_npl_data_##inst; \ \ -DEVICE_DT_INST_DEFINE(inst, &can_npl_init, NULL, \ - &can_npl_data_##inst, &can_npl_cfg_##inst, \ - POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ - &can_npl_driver_api); +CAN_DEVICE_DT_INST_DEFINE(inst, can_npl_init, NULL, \ + &can_npl_data_##inst, &can_npl_cfg_##inst, \ + POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ + &can_npl_driver_api); DT_INST_FOREACH_STATUS_OKAY(CAN_NATIVE_POSIX_LINUX_INIT) diff --git a/drivers/can/can_numaker.c b/drivers/can/can_numaker.c new file mode 100644 index 00000000000..0bb47d78a04 --- /dev/null +++ b/drivers/can/can_numaker.c @@ -0,0 +1,299 @@ +/* + * Copyright (c) 2023 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nuvoton_numaker_canfd + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(can_numaker, CONFIG_CAN_LOG_LEVEL); + +/* CANFD Clock Source Selection */ +#define NUMAKER_CANFD_CLKSEL_HXT 0 +#define NUMAKER_CANFD_CLKSEL_PLL_DIV2 1 +#define NUMAKER_CANFD_CLKSEL_HCLK 2 +#define NUMAKER_CANFD_CLKSEL_HIRC 3 + +/* Implementation notes + * 1. Use Bosch M_CAN driver (m_can) as backend + * 2. Need to modify can_numaker_get_core_clock() for new SOC support + */ + +struct can_numaker_config { + mm_reg_t canfd_base; + mem_addr_t mrba; + mem_addr_t mram; + const struct reset_dt_spec reset; + uint32_t clk_modidx; + uint32_t clk_src; + uint32_t clk_div; + const struct device *clk_dev; + void (*irq_config_func)(const struct device *dev); + const struct pinctrl_dev_config *pincfg; +}; + +static int can_numaker_get_core_clock(const struct device *dev, uint32_t *rate) +{ + const struct can_mcan_config *mcan_config = dev->config; + const struct can_numaker_config *config = mcan_config->custom; + uint32_t clksrc_rate_idx; + uint32_t clkdiv_divider; + + /* Module clock source rate */ + clksrc_rate_idx = CLK_GetModuleClockSource(config->clk_modidx); + /* Module clock divider */ + clkdiv_divider = CLK_GetModuleClockDivider(config->clk_modidx) + 1; + + switch (clksrc_rate_idx) { + case NUMAKER_CANFD_CLKSEL_HXT: + *rate = __HXT / clkdiv_divider; + break; + case NUMAKER_CANFD_CLKSEL_PLL_DIV2: + *rate = (CLK_GetPLLClockFreq() / 2) / clkdiv_divider; + break; + case NUMAKER_CANFD_CLKSEL_HCLK: + *rate = CLK_GetHCLKFreq() / clkdiv_divider; + break; + case NUMAKER_CANFD_CLKSEL_HIRC: + *rate = __HIRC / clkdiv_divider; + break; + default: + LOG_ERR("Invalid clock source rate index"); + return -EIO; + } + + LOG_DBG("Clock rate index/divider: %d/%d", clksrc_rate_idx, clkdiv_divider); + + return 0; +} + +static inline int can_numaker_init_unlocked(const struct device *dev) +{ + const struct can_mcan_config *mcan_config = dev->config; + const struct can_numaker_config *config = mcan_config->custom; + struct numaker_scc_subsys scc_subsys; + int rc; + + memset(&scc_subsys, 0x00, sizeof(scc_subsys)); + scc_subsys.subsys_id = NUMAKER_SCC_SUBSYS_ID_PCC; + scc_subsys.pcc.clk_modidx = config->clk_modidx; + scc_subsys.pcc.clk_src = config->clk_src; + scc_subsys.pcc.clk_div = config->clk_div; + + /* To enable clock */ + rc = clock_control_on(config->clk_dev, (clock_control_subsys_t) &scc_subsys); + if (rc < 0) { + return rc; + } + /* To set module clock */ + rc = clock_control_configure(config->clk_dev, (clock_control_subsys_t)&scc_subsys, NULL); + if (rc < 0) { + return rc; + } + + /* Configure pinmux (NuMaker's SYS MFP) */ + rc = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); + if (rc < 0) { + return rc; + } + + /* Reset CAN to default state, same as BSP's SYS_ResetModule(id_rst) */ + reset_line_toggle_dt(&config->reset); + + config->irq_config_func(dev); + + rc = can_mcan_configure_mram(dev, config->mrba, config->mram); + if (rc != 0) { + return rc; + } + + rc = can_mcan_init(dev); + if (rc < 0) { + LOG_ERR("Failed to initialize mcan: %d", rc); + return rc; + } + +#if CONFIG_CAN_LOG_LEVEL >= LOG_LEVEL_DBG + uint32_t rate; + + rc = can_numaker_get_core_clock(dev, &rate); + if (rc < 0) { + return rc; + } + + LOG_DBG("CAN core clock: %d", rate); +#endif + + return rc; +} + +static int can_numaker_init(const struct device *dev) +{ + const struct can_mcan_config *mcan_config = dev->config; + const struct can_numaker_config *config = mcan_config->custom; + int rc; + + if (!device_is_ready(config->reset.dev)) { + LOG_ERR("reset controller not ready"); + return -ENODEV; + } + + if (!device_is_ready(config->clk_dev)) { + LOG_ERR("clock controller not ready"); + return -ENODEV; + } + + SYS_UnlockReg(); + rc = can_numaker_init_unlocked(dev); + SYS_LockReg(); + + return rc; +} + +static const struct can_driver_api can_numaker_driver_api = { + .get_capabilities = can_mcan_get_capabilities, + .start = can_mcan_start, + .stop = can_mcan_stop, + .set_mode = can_mcan_set_mode, + .set_timing = can_mcan_set_timing, + .send = can_mcan_send, + .add_rx_filter = can_mcan_add_rx_filter, + .remove_rx_filter = can_mcan_remove_rx_filter, +#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY + .recover = can_mcan_recover, +#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */ + .get_state = can_mcan_get_state, + .set_state_change_callback = can_mcan_set_state_change_callback, + .get_core_clock = can_numaker_get_core_clock, + .get_max_filters = can_mcan_get_max_filters, + .get_max_bitrate = can_mcan_get_max_bitrate, + .timing_min = CAN_MCAN_TIMING_MIN_INITIALIZER, + .timing_max = CAN_MCAN_TIMING_MAX_INITIALIZER, +#ifdef CONFIG_CAN_FD_MODE + .set_timing_data = can_mcan_set_timing_data, + .timing_data_min = CAN_MCAN_TIMING_DATA_MIN_INITIALIZER, + .timing_data_max = CAN_MCAN_TIMING_DATA_MAX_INITIALIZER, +#endif /* CONFIG_CAN_FD_MODE */ +}; + +static int can_numaker_read_reg(const struct device *dev, uint16_t reg, uint32_t *val) +{ + const struct can_mcan_config *mcan_cfg = dev->config; + const struct can_numaker_config *numaker_cfg = mcan_cfg->custom; + + return can_mcan_sys_read_reg(numaker_cfg->canfd_base, reg, val); +} + +static int can_numaker_write_reg(const struct device *dev, uint16_t reg, uint32_t val) +{ + const struct can_mcan_config *mcan_cfg = dev->config; + const struct can_numaker_config *numaker_cfg = mcan_cfg->custom; + + return can_mcan_sys_write_reg(numaker_cfg->canfd_base, reg, val); +} + +static int can_numaker_read_mram(const struct device *dev, uint16_t offset, void *dst, size_t len) +{ + const struct can_mcan_config *mcan_cfg = dev->config; + const struct can_numaker_config *numaker_cfg = mcan_cfg->custom; + + return can_mcan_sys_read_mram(numaker_cfg->mram, offset, dst, len); +} + +static int can_numaker_write_mram(const struct device *dev, uint16_t offset, const void *src, + size_t len) +{ + const struct can_mcan_config *mcan_cfg = dev->config; + const struct can_numaker_config *numaker_cfg = mcan_cfg->custom; + + return can_mcan_sys_write_mram(numaker_cfg->mram, offset, src, len); +} + +static int can_numaker_clear_mram(const struct device *dev, uint16_t offset, size_t len) +{ + const struct can_mcan_config *mcan_cfg = dev->config; + const struct can_numaker_config *numaker_cfg = mcan_cfg->custom; + + return can_mcan_sys_clear_mram(numaker_cfg->mram, offset, len); +} + +static const struct can_mcan_ops can_numaker_ops = { + .read_reg = can_numaker_read_reg, + .write_reg = can_numaker_write_reg, + .read_mram = can_numaker_read_mram, + .write_mram = can_numaker_write_mram, + .clear_mram = can_numaker_clear_mram, +}; + +#define NUMAKER_CLKCTRL_DEV_INIT(inst) \ + .clk_dev = DEVICE_DT_GET(DT_PARENT(DT_INST_CLOCKS_CTLR(inst))), + +#define NUMAKER_PINCTRL_DEFINE(inst) \ + PINCTRL_DT_INST_DEFINE(inst); +#define NUMAKER_PINCTRL_INIT(inst) \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), + +#define CAN_NUMAKER_INIT(inst) \ + NUMAKER_PINCTRL_DEFINE(inst); \ + CAN_MCAN_DT_INST_CALLBACKS_DEFINE(inst, can_numaker_cbs_##inst); \ + \ + static void can_numaker_irq_config_func_##inst(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(inst, 0, irq), \ + DT_INST_IRQ_BY_IDX(inst, 0, priority), \ + can_mcan_line_0_isr, \ + DEVICE_DT_INST_GET(inst), \ + 0); \ + irq_enable(DT_INST_IRQ_BY_IDX(inst, 0, irq)); \ + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(inst, 1, irq), \ + DT_INST_IRQ_BY_IDX(inst, 1, priority), \ + can_mcan_line_1_isr, \ + DEVICE_DT_INST_GET(inst), \ + 0); \ + irq_enable(DT_INST_IRQ_BY_IDX(inst, 1, irq)); \ + } \ + \ + static const struct can_numaker_config can_numaker_config_##inst = { \ + .canfd_base = CAN_MCAN_DT_INST_MCAN_ADDR(inst), \ + .mrba = CAN_MCAN_DT_INST_MRBA(inst), \ + .mram = CAN_MCAN_DT_INST_MRAM_ADDR(inst), \ + .reset = RESET_DT_SPEC_INST_GET(inst), \ + .clk_modidx = DT_INST_CLOCKS_CELL(inst, clock_module_index), \ + .clk_src = DT_INST_CLOCKS_CELL(inst, clock_source), \ + .clk_div = DT_INST_CLOCKS_CELL(inst, clock_divider), \ + NUMAKER_CLKCTRL_DEV_INIT(inst) \ + .irq_config_func = can_numaker_irq_config_func_##inst, \ + NUMAKER_PINCTRL_INIT(inst) \ + }; \ + \ + static const struct can_mcan_config can_mcan_config_##inst = \ + CAN_MCAN_DT_CONFIG_INST_GET(inst, \ + &can_numaker_config_##inst, \ + &can_numaker_ops, \ + &can_numaker_cbs_##inst); \ + \ + static uint32_t can_numaker_data_##inst; \ + \ + static struct can_mcan_data can_mcan_data_##inst = \ + CAN_MCAN_DATA_INITIALIZER(&can_numaker_data_ ## inst); \ + \ + CAN_DEVICE_DT_INST_DEFINE(inst, \ + &can_numaker_init, \ + NULL, \ + &can_mcan_data_##inst, \ + &can_mcan_config_##inst, \ + POST_KERNEL, \ + CONFIG_CAN_INIT_PRIORITY, \ + &can_numaker_driver_api); \ + +DT_INST_FOREACH_STATUS_OKAY(CAN_NUMAKER_INIT); diff --git a/drivers/can/can_nxp_s32_canxl.c b/drivers/can/can_nxp_s32_canxl.c index b5dd7305c51..211e901055f 100644 --- a/drivers/can/can_nxp_s32_canxl.c +++ b/drivers/can/can_nxp_s32_canxl.c @@ -1,5 +1,5 @@ /* - * Copyright 2022 NXP + * Copyright 2022-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -66,7 +67,8 @@ struct can_nxp_s32_config { CANXL_GRP_CONTROL_Type *base_grp_ctrl; CANXL_DSC_CONTROL_Type *base_dsc_ctrl; uint8 instance; - uint32_t clock_can; + const struct device *clock_dev; + clock_control_subsys_t clock_subsys; uint32_t bitrate; uint32_t sample_point; uint32_t sjw; @@ -286,9 +288,7 @@ static int can_nxp_s32_get_core_clock(const struct device *dev, uint32_t *rate) __ASSERT_NO_MSG(rate != NULL); - *rate = config->clock_can; - - return 0; + return clock_control_get_rate(config->clock_dev, config->clock_subsys, rate); } static int can_nxp_s32_get_max_filters(const struct device *dev, bool ide) @@ -396,7 +396,10 @@ static void can_nxp_s32_remove_rx_filter(const struct device *dev, int filter_id struct can_nxp_s32_data *data = dev->data; int mb_indx = ALLOC_IDX_TO_RXMB_IDX(filter_id); - __ASSERT_NO_MSG(filter_id >= 0 && filter_id < CONFIG_CAN_NXP_S32_MAX_RX); + if (filter_id < 0 || filter_id >= CONFIG_CAN_NXP_S32_MAX_RX) { + LOG_ERR("filter ID %d out of bounds", filter_id); + return; + } k_mutex_lock(&data->rx_mutex, K_FOREVER); @@ -511,13 +514,13 @@ static int can_nxp_s32_send(const struct device *dev, if ((frame->flags & CAN_FRAME_FDF) != 0 && (config->base_sic->BCFG2 & CANXL_SIC_BCFG2_FDEN_MASK) == 0) { - LOG_ERR("CAN-FD format not supported in non-FD mode"); + LOG_ERR("CAN FD format not supported in non-FD mode"); return -ENOTSUP; } if ((frame->flags & CAN_FRAME_BRS) != 0 && ~(config->base_sic->BCFG1 & CANXL_SIC_BCFG1_FDRSDIS_MASK) == 0) { - LOG_ERR("CAN-FD BRS not supported in non-FD mode"); + LOG_ERR("CAN FD BRS not supported in non-FD mode"); return -ENOTSUP; } #else @@ -541,7 +544,7 @@ static int can_nxp_s32_send(const struct device *dev, #ifdef CONFIG_CAN_FD_MODE } else { if (frame->dlc > CANFD_MAX_DLC) { - LOG_ERR("DLC of %d for CAN-FD format frame", frame->dlc); + LOG_ERR("DLC of %d for CAN FD format frame", frame->dlc); return -EINVAL; } #endif @@ -728,14 +731,12 @@ static void can_nxp_s32_err_callback(const struct device *dev, static void nxp_s32_msg_data_to_zcan_frame(Canexcel_RxFdMsg msg_data, struct can_frame *frame) { + memset(frame, 0, sizeof(*frame)); + if (!!(msg_data.Header.Id & CANXL_TX_HEADER_IDE_MASK)) { frame->flags |= CAN_FRAME_IDE; } - if (!!(msg_data.Header.Id & CANXL_TX_HEADER_RTR_MASK)) { - frame->flags |= CAN_FRAME_RTR; - } - if (!!(frame->flags & CAN_FRAME_IDE)) { frame->id = (msg_data.Header.Id & CANXL_IP_ID_EXT_MASK); } else { @@ -754,7 +755,11 @@ static void nxp_s32_msg_data_to_zcan_frame(Canexcel_RxFdMsg msg_data, frame->flags |= CAN_FRAME_BRS; } - memcpy(frame->data, msg_data.data, can_dlc_to_bytes(frame->dlc)); + if (!!(msg_data.Header.Id & CANXL_TX_HEADER_RTR_MASK)) { + frame->flags |= CAN_FRAME_RTR; + } else { + memcpy(frame->data, msg_data.data, can_dlc_to_bytes(frame->dlc)); + } #ifdef CONFIG_CAN_RX_TIMESTAMP frame->timestamp = msg_data.timeStampL; @@ -829,6 +834,17 @@ static int can_nxp_s32_init(const struct device *dev) } } + if (!device_is_ready(config->clock_dev)) { + LOG_ERR("Clock control device not ready"); + return -ENODEV; + } + + err = clock_control_on(config->clock_dev, config->clock_subsys); + if (err) { + LOG_ERR("Failed to enable clock"); + return err; + } + k_mutex_init(&data->rx_mutex); k_mutex_init(&data->tx_mutex); k_sem_init(&data->tx_allocs_sem, CONFIG_CAN_NXP_S32_MAX_TX, CONFIG_CAN_NXP_S32_MAX_TX); @@ -888,7 +904,7 @@ static int can_nxp_s32_init(const struct device *dev) } } - LOG_DBG("Setting CAN-FD bitrate %d:", config->bitrate_data); + LOG_DBG("Setting CAN FD bitrate %d:", config->bitrate_data); nxp_s32_zcan_timing_to_canxl_timing(&data->timing_data, &config->can_cfg->Fd_bitrate); #endif @@ -917,6 +933,20 @@ static int can_nxp_s32_init(const struct device *dev) return 0; } +static void can_nxp_s32_isr_rx_tx(const struct device *dev) +{ + const struct can_nxp_s32_config *config = dev->config; + + Canexcel_Ip_RxTxIRQHandler(config->instance); +} + +static void can_nxp_s32_isr_error(const struct device *dev) +{ + const struct can_nxp_s32_config *config = dev->config; + + Canexcel_Ip_ErrIRQHandler(config->instance); +} + static const struct can_driver_api can_nxp_s32_driver_api = { .get_capabilities = can_nxp_s32_get_capabilities, .start = can_nxp_s32_start, @@ -967,19 +997,13 @@ static const struct can_driver_api can_nxp_s32_driver_api = { #endif }; -#define CAN_NXP_S32_NODE(n) DT_NODELABEL(can##n) - -#define CAN_NXP_S32_IRQ_HANDLER(n, irq_name) DT_CAT5(CANXL, n, _, irq_name, Handler) - -#define _CAN_NXP_S32_IRQ_CONFIG(node_id, prop, idx, n) \ +#define _CAN_NXP_S32_IRQ_CONFIG(node_id, prop, idx) \ do { \ - extern void (CAN_NXP_S32_IRQ_HANDLER(n, \ - DT_STRING_TOKEN_BY_IDX(node_id, prop, idx)))(void); \ IRQ_CONNECT(DT_IRQ_BY_IDX(node_id, idx, irq), \ DT_IRQ_BY_IDX(node_id, idx, priority), \ - CAN_NXP_S32_IRQ_HANDLER(n, \ + UTIL_CAT(can_nxp_s32_isr_, \ DT_STRING_TOKEN_BY_IDX(node_id, prop, idx)), \ - NULL, \ + DEVICE_DT_GET(node_id), \ DT_IRQ_BY_IDX(node_id, idx, flags)); \ irq_enable(DT_IRQ_BY_IDX(node_id, idx, irq)); \ } while (false); @@ -987,15 +1011,14 @@ static const struct can_driver_api can_nxp_s32_driver_api = { #define CAN_NXP_S32_IRQ_CONFIG(n) \ static void can_irq_config_##n(void) \ { \ - DT_FOREACH_PROP_ELEM_VARGS(CAN_NXP_S32_NODE(n), interrupt_names, \ - _CAN_NXP_S32_IRQ_CONFIG, n); \ + DT_INST_FOREACH_PROP_ELEM(n, interrupt_names, _CAN_NXP_S32_IRQ_CONFIG); \ } #define CAN_NXP_S32_ERR_CALLBACK(n) \ void nxp_s32_can_##n##_err_callback(uint8 instance, Canexcel_Ip_EventType eventType,\ uint32 u32SysStatus, const Canexcel_Ip_StateType *canexcelState) \ { \ - const struct device *dev = DEVICE_DT_GET(CAN_NXP_S32_NODE(n)); \ + const struct device *dev = DEVICE_DT_INST_GET(n); \ can_nxp_s32_err_callback(dev, eventType, u32SysStatus, canexcelState); \ } @@ -1003,18 +1026,18 @@ static const struct can_driver_api can_nxp_s32_driver_api = { void nxp_s32_can_##n##_ctrl_callback(uint8 instance, Canexcel_Ip_EventType eventType,\ uint32 buffIdx, const Canexcel_Ip_StateType *canexcelState) \ { \ - const struct device *dev = DEVICE_DT_GET(CAN_NXP_S32_NODE(n)); \ + const struct device *dev = DEVICE_DT_INST_GET(n); \ can_nxp_s32_ctrl_callback(dev, eventType, buffIdx, canexcelState); \ } #if defined(CONFIG_CAN_FD_MODE) #define CAN_NXP_S32_TIMING_DATA_CONFIG(n) \ - .bitrate_data = DT_PROP(CAN_NXP_S32_NODE(n), bus_speed_data), \ - .sjw_data = DT_PROP(CAN_NXP_S32_NODE(n), sjw_data), \ - .prop_seg_data = DT_PROP_OR(CAN_NXP_S32_NODE(n), prop_seg_data, 0), \ - .phase_seg1_data = DT_PROP_OR(CAN_NXP_S32_NODE(n), phase_seg1_data, 0), \ - .phase_seg2_data = DT_PROP_OR(CAN_NXP_S32_NODE(n), phase_seg2_data, 0), \ - .sample_point_data = DT_PROP_OR(CAN_NXP_S32_NODE(n), sample_point_data, 0), + .bitrate_data = DT_INST_PROP(n, bus_speed_data), \ + .sjw_data = DT_INST_PROP(n, sjw_data), \ + .prop_seg_data = DT_INST_PROP_OR(n, prop_seg_data, 0), \ + .phase_seg1_data = DT_INST_PROP_OR(n, phase_seg1_data, 0), \ + .phase_seg2_data = DT_INST_PROP_OR(n, phase_seg2_data, 0), \ + .sample_point_data = DT_INST_PROP_OR(n, sample_point_data, 0), #define CAN_NXP_S32_FD_MODE 1 #define CAN_NXP_S32_BRS 1 #else @@ -1029,11 +1052,17 @@ static const struct can_driver_api can_nxp_s32_driver_api = { #define CAN_NXP_S32_CTRL_OPTIONS 0 #endif +#define CAN_NXP_S32_HW_INSTANCE_CHECK(i, n) \ + ((DT_INST_REG_ADDR(n) == IP_CANXL_##i##__SIC_BASE) ? i : 0) + +#define CAN_NXP_S32_HW_INSTANCE(n) \ + LISTIFY(__DEBRACKET CANXL_SIC_INSTANCE_COUNT, CAN_NXP_S32_HW_INSTANCE_CHECK, (|), n) + #define CAN_NXP_S32_INIT_DEVICE(n) \ CAN_NXP_S32_CTRL_CALLBACK(n) \ CAN_NXP_S32_ERR_CALLBACK(n) \ CAN_NXP_S32_IRQ_CONFIG(n) \ - PINCTRL_DT_DEFINE(CAN_NXP_S32_NODE(n)); \ + PINCTRL_DT_INST_DEFINE(n); \ Canexcel_Ip_ConfigType can_nxp_s32_default_config##n = { \ .rx_mbdesc = (uint8)CONFIG_CAN_NXP_S32_MAX_RX, \ .tx_mbdesc = (uint8)CONFIG_CAN_NXP_S32_MAX_TX, \ @@ -1053,25 +1082,26 @@ static const struct can_driver_api can_nxp_s32_driver_api = { .rx_msg = rx_msg_##n, \ }; \ static struct can_nxp_s32_config can_nxp_s32_config_##n = { \ - .base_sic = (CANXL_SIC_Type *) \ - DT_REG_ADDR_BY_NAME(CAN_NXP_S32_NODE(n), sic), \ + .base_sic = (CANXL_SIC_Type *)DT_INST_REG_ADDR_BY_NAME(n, sic), \ .base_grp_ctrl = (CANXL_GRP_CONTROL_Type *) \ - DT_REG_ADDR_BY_NAME(CAN_NXP_S32_NODE(n), grp_ctrl), \ + DT_INST_REG_ADDR_BY_NAME(n, grp_ctrl), \ .base_dsc_ctrl = (CANXL_DSC_CONTROL_Type *) \ - DT_REG_ADDR_BY_NAME(CAN_NXP_S32_NODE(n), dsc_ctrl), \ - .instance = n, \ - .clock_can = DT_PROP(CAN_NXP_S32_NODE(n), clock_frequency), \ - .bitrate = DT_PROP(CAN_NXP_S32_NODE(n), bus_speed), \ - .sjw = DT_PROP(CAN_NXP_S32_NODE(n), sjw), \ - .prop_seg = DT_PROP_OR(CAN_NXP_S32_NODE(n), prop_seg, 0), \ - .phase_seg1 = DT_PROP_OR(CAN_NXP_S32_NODE(n), phase_seg1, 0), \ - .phase_seg2 = DT_PROP_OR(CAN_NXP_S32_NODE(n), phase_seg2, 0), \ - .sample_point = DT_PROP_OR(CAN_NXP_S32_NODE(n), sample_point, 0), \ + DT_INST_REG_ADDR_BY_NAME(n, dsc_ctrl), \ + .instance = CAN_NXP_S32_HW_INSTANCE(n), \ + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ + .clock_subsys = (clock_control_subsys_t) \ + DT_INST_CLOCKS_CELL(n, name), \ + .bitrate = DT_INST_PROP(n, bus_speed), \ + .sjw = DT_INST_PROP(n, sjw), \ + .prop_seg = DT_INST_PROP_OR(n, prop_seg, 0), \ + .phase_seg1 = DT_INST_PROP_OR(n, phase_seg1, 0), \ + .phase_seg2 = DT_INST_PROP_OR(n, phase_seg2, 0), \ + .sample_point = DT_INST_PROP_OR(n, sample_point, 0), \ CAN_NXP_S32_TIMING_DATA_CONFIG(n) \ - .max_bitrate = DT_CAN_TRANSCEIVER_MAX_BITRATE(CAN_NXP_S32_NODE(n), \ + .max_bitrate = DT_INST_CAN_TRANSCEIVER_MAX_BITRATE(n, \ CAN_NXP_S32_MAX_BITRATE), \ - .phy = DEVICE_DT_GET_OR_NULL(DT_PHANDLE(CAN_NXP_S32_NODE(n), phys)), \ - .pin_cfg = PINCTRL_DT_DEV_CONFIG_GET(CAN_NXP_S32_NODE(n)), \ + .phy = DEVICE_DT_GET_OR_NULL(DT_INST_PHANDLE(n, phys)), \ + .pin_cfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ .can_cfg = (Canexcel_Ip_ConfigType *)&can_nxp_s32_default_config##n, \ .irq_config_func = can_irq_config_##n \ }; \ @@ -1079,19 +1109,13 @@ static const struct can_driver_api can_nxp_s32_driver_api = { { \ return can_nxp_s32_init(dev); \ } \ - DEVICE_DT_DEFINE(CAN_NXP_S32_NODE(n), \ - &can_nxp_s32_##n##_init, \ - NULL, \ - &can_nxp_s32_data_##n, \ - &can_nxp_s32_config_##n, \ - POST_KERNEL, \ - CONFIG_CAN_INIT_PRIORITY, \ - &can_nxp_s32_driver_api); - -#if DT_NODE_HAS_STATUS(CAN_NXP_S32_NODE(0), okay) -CAN_NXP_S32_INIT_DEVICE(0) -#endif - -#if DT_NODE_HAS_STATUS(CAN_NXP_S32_NODE(1), okay) -CAN_NXP_S32_INIT_DEVICE(1) -#endif + CAN_DEVICE_DT_INST_DEFINE(n, \ + can_nxp_s32_##n##_init, \ + NULL, \ + &can_nxp_s32_data_##n, \ + &can_nxp_s32_config_##n, \ + POST_KERNEL, \ + CONFIG_CAN_INIT_PRIORITY, \ + &can_nxp_s32_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(CAN_NXP_S32_INIT_DEVICE) diff --git a/drivers/can/can_rcar.c b/drivers/can/can_rcar.c index 7e108ebd42a..f015407c22f 100644 --- a/drivers/can/can_rcar.c +++ b/drivers/can/can_rcar.c @@ -399,10 +399,6 @@ static void can_rcar_rx_isr(const struct device *dev) frame.id = (val & RCAR_CAN_MB_SID_MASK) >> RCAR_CAN_MB_SID_SHIFT; } - if (val & RCAR_CAN_MB_RTR) { - frame.flags |= CAN_FRAME_RTR; - } - frame.dlc = sys_read16(config->reg_addr + RCAR_CAN_MB_60 + RCAR_CAN_MB_DLC_OFFSET) & 0xF; @@ -413,9 +409,13 @@ static void can_rcar_rx_isr(const struct device *dev) frame.dlc = CAN_MAX_DLC; } - for (i = 0; i < frame.dlc; i++) { - frame.data[i] = sys_read8(config->reg_addr + - RCAR_CAN_MB_60 + RCAR_CAN_MB_DATA_OFFSET + i); + if (val & RCAR_CAN_MB_RTR) { + frame.flags |= CAN_FRAME_RTR; + } else { + for (i = 0; i < frame.dlc; i++) { + frame.data[i] = sys_read8(config->reg_addr + + RCAR_CAN_MB_60 + RCAR_CAN_MB_DATA_OFFSET + i); + } } #if defined(CONFIG_CAN_RX_TIMESTAMP) /* read upper byte */ @@ -914,9 +914,11 @@ static int can_rcar_send(const struct device *dev, const struct can_frame *frame sys_write16(frame->dlc, config->reg_addr + RCAR_CAN_MB_56 + RCAR_CAN_MB_DLC_OFFSET); - for (i = 0; i < frame->dlc; i++) { - sys_write8(frame->data[i], config->reg_addr - + RCAR_CAN_MB_56 + RCAR_CAN_MB_DATA_OFFSET + i); + if ((frame->flags & CAN_FRAME_RTR) == 0) { + for (i = 0; i < frame->dlc; i++) { + sys_write8(frame->data[i], config->reg_addr + + RCAR_CAN_MB_56 + RCAR_CAN_MB_DATA_OFFSET + i); + } } compiler_barrier(); @@ -973,7 +975,8 @@ static void can_rcar_remove_rx_filter(const struct device *dev, int filter_id) { struct can_rcar_data *data = dev->data; - if (filter_id >= CONFIG_CAN_RCAR_MAX_FILTER) { + if (filter_id < 0 || filter_id >= CONFIG_CAN_RCAR_MAX_FILTER) { + LOG_ERR("filter ID %d out of bounds", filter_id); return; } @@ -987,7 +990,7 @@ static int can_rcar_init(const struct device *dev) { const struct can_rcar_cfg *config = dev->config; struct can_rcar_data *data = dev->data; - struct can_timing timing; + struct can_timing timing = { 0 }; int ret; uint16_t ctlr; @@ -1053,7 +1056,6 @@ static int can_rcar_init(const struct device *dev) return ret; } - timing.sjw = config->sjw; if (config->sample_point) { ret = can_calc_timing(dev, &timing, config->bus_speed, config->sample_point); @@ -1065,6 +1067,7 @@ static int can_rcar_init(const struct device *dev) timing.prescaler, timing.phase_seg1, timing.phase_seg2); LOG_DBG("Sample-point err : %d", ret); } else { + timing.sjw = config->sjw; timing.prop_seg = config->prop_seg; timing.phase_seg1 = config->phase_seg1; timing.phase_seg2 = config->phase_seg2; @@ -1074,7 +1077,7 @@ static int can_rcar_init(const struct device *dev) } } - ret = can_rcar_set_timing(dev, &timing); + ret = can_set_timing(dev, &timing); if (ret) { return ret; } diff --git a/drivers/can/can_sam.c b/drivers/can/can_sam.c index 10ff7bc503f..e081e57c794 100644 --- a/drivers/can/can_sam.c +++ b/drivers/can/can_sam.c @@ -186,12 +186,12 @@ static void config_can_##inst##_irq(void) static struct can_mcan_data can_mcan_data_##inst = \ CAN_MCAN_DATA_INITIALIZER(NULL); -#define CAN_SAM_DEVICE_INST(inst) \ - DEVICE_DT_INST_DEFINE(inst, &can_sam_init, NULL, \ - &can_mcan_data_##inst, \ - &can_mcan_cfg_##inst, \ - POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ - &can_sam_driver_api); +#define CAN_SAM_DEVICE_INST(inst) \ + CAN_DEVICE_DT_INST_DEFINE(inst, can_sam_init, NULL, \ + &can_mcan_data_##inst, \ + &can_mcan_cfg_##inst, \ + POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ + &can_sam_driver_api); #define CAN_SAM_INST(inst) \ CAN_MCAN_DT_INST_BUILD_ASSERT_MRAM_CFG(inst); \ diff --git a/drivers/can/can_sam0.c b/drivers/can/can_sam0.c index 786d2cb9a72..ac322fe936e 100644 --- a/drivers/can/can_sam0.c +++ b/drivers/can/can_sam0.c @@ -214,11 +214,11 @@ static void config_can_##inst##_irq(void) \ CAN_MCAN_DATA_INITIALIZER(NULL); #define CAN_SAM0_DEVICE_INST(inst) \ - DEVICE_DT_INST_DEFINE(inst, &can_sam0_init, NULL, \ - &can_mcan_data_##inst, \ - &can_mcan_cfg_##inst, \ - POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ - &can_sam0_driver_api); + CAN_DEVICE_DT_INST_DEFINE(inst, can_sam0_init, NULL, \ + &can_mcan_data_##inst, \ + &can_mcan_cfg_##inst, \ + POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ + &can_sam0_driver_api); #define CAN_SAM0_INST(inst) \ CAN_MCAN_DT_INST_BUILD_ASSERT_MRAM_CFG(inst); \ diff --git a/drivers/can/can_shell.c b/drivers/can/can_shell.c index a6e3e8045af..46dac3fb06a 100644 --- a/drivers/can/can_shell.c +++ b/drivers/can/can_shell.c @@ -362,13 +362,25 @@ static int cmd_can_show(const struct shell *sh, size_t argc, char **argv) timing_min->prescaler, timing_max->prescaler); } +#ifdef CONFIG_CAN_STATS + shell_print(sh, "statistics:"); + shell_print(sh, " bit errors: %u", can_stats_get_bit_errors(dev)); + shell_print(sh, " bit0 errors: %u", can_stats_get_bit0_errors(dev)); + shell_print(sh, " bit1 errors: %u", can_stats_get_bit1_errors(dev)); + shell_print(sh, " stuff errors: %u", can_stats_get_stuff_errors(dev)); + shell_print(sh, " crc errors: %u", can_stats_get_crc_errors(dev)); + shell_print(sh, " form errors: %u", can_stats_get_form_errors(dev)); + shell_print(sh, " ack errors: %u", can_stats_get_ack_errors(dev)); + shell_print(sh, " rx overruns: %u", can_stats_get_rx_overruns(dev)); +#endif /* CONFIG_CAN_STATS */ + return 0; } static int cmd_can_bitrate_set(const struct shell *sh, size_t argc, char **argv) { const struct device *dev = device_get_binding(argv[1]); - struct can_timing timing; + struct can_timing timing = { 0 }; uint16_t sample_pnt; uint32_t bitrate; char *endptr; @@ -392,16 +404,6 @@ static int cmd_can_bitrate_set(const struct shell *sh, size_t argc, char **argv) return -EINVAL; } - if (argc >= 5) { - timing.sjw = (uint16_t)strtoul(argv[4], &endptr, 10); - if (*endptr != '\0') { - shell_error(sh, "failed to parse SJW"); - return -EINVAL; - } - } else { - timing.sjw = CAN_SJW_NO_CHANGE; - } - err = can_calc_timing(dev, &timing, bitrate, sample_pnt); if (err < 0) { shell_error(sh, "failed to calculate timing for " @@ -410,17 +412,20 @@ static int cmd_can_bitrate_set(const struct shell *sh, size_t argc, char **argv) return err; } - if (timing.sjw == CAN_SJW_NO_CHANGE) { - shell_print(sh, "setting bitrate to %d bps, sample point %d.%d%% " - "(+/- %d.%d%%)", - bitrate, sample_pnt / 10, sample_pnt % 10, err / 10, err % 10); - } else { - shell_print(sh, "setting bitrate to %d bps, sample point %d.%d%% " - "(+/- %d.%d%%), sjw %d", - bitrate, sample_pnt / 10, sample_pnt % 10, err / 10, err % 10, - timing.sjw); + if (argc >= 5) { + /* Overwrite calculated default SJW with user-provided value */ + timing.sjw = (uint16_t)strtoul(argv[4], &endptr, 10); + if (*endptr != '\0') { + shell_error(sh, "failed to parse SJW"); + return -EINVAL; + } } + shell_print(sh, "setting bitrate to %d bps, sample point %d.%d%% " + "(+/- %d.%d%%), sjw %d", + bitrate, sample_pnt / 10, sample_pnt % 10, err / 10, err % 10, + timing.sjw); + LOG_DBG("sjw %u, prop_seg %u, phase_seg1 %u, phase_seg2 %u, prescaler %u", timing.sjw, timing.prop_seg, timing.phase_seg1, timing.phase_seg2, timing.prescaler); @@ -446,7 +451,7 @@ static int cmd_can_bitrate_set(const struct shell *sh, size_t argc, char **argv) static int cmd_can_dbitrate_set(const struct shell *sh, size_t argc, char **argv) { const struct device *dev = device_get_binding(argv[1]); - struct can_timing timing; + struct can_timing timing = { 0 }; uint16_t sample_pnt; uint32_t bitrate; char *endptr; @@ -470,16 +475,6 @@ static int cmd_can_dbitrate_set(const struct shell *sh, size_t argc, char **argv return -EINVAL; } - if (argc >= 5) { - timing.sjw = (uint16_t)strtoul(argv[4], &endptr, 10); - if (*endptr != '\0') { - shell_error(sh, "failed to parse SJW"); - return -EINVAL; - } - } else { - timing.sjw = CAN_SJW_NO_CHANGE; - } - err = can_calc_timing_data(dev, &timing, bitrate, sample_pnt); if (err < 0) { shell_error(sh, "failed to calculate timing for " @@ -488,17 +483,20 @@ static int cmd_can_dbitrate_set(const struct shell *sh, size_t argc, char **argv return err; } - if (timing.sjw == CAN_SJW_NO_CHANGE) { - shell_print(sh, "setting data bitrate to %d bps, sample point %d.%d%% " - "(+/- %d.%d%%)", - bitrate, sample_pnt / 10, sample_pnt % 10, err / 10, err % 10); - } else { - shell_print(sh, "setting data bitrate to %d bps, sample point %d.%d%% " - "(+/- %d.%d%%), sjw %d", - bitrate, sample_pnt / 10, sample_pnt % 10, err / 10, err % 10, - timing.sjw); + if (argc >= 5) { + /* Overwrite calculated default SJW with user-provided value */ + timing.sjw = (uint16_t)strtoul(argv[4], &endptr, 10); + if (*endptr != '\0') { + shell_error(sh, "failed to parse SJW"); + return -EINVAL; + } } + shell_print(sh, "setting data bitrate to %d bps, sample point %d.%d%% " + "(+/- %d.%d%%), sjw %d", + bitrate, sample_pnt / 10, sample_pnt % 10, err / 10, err % 10, + timing.sjw); + LOG_DBG("sjw %u, prop_seg %u, phase_seg1 %u, phase_seg2 %u, prescaler %u", timing.sjw, timing.prop_seg, timing.phase_seg1, timing.phase_seg2, timing.prescaler); @@ -521,6 +519,102 @@ static int cmd_can_dbitrate_set(const struct shell *sh, size_t argc, char **argv return 0; } +static int can_shell_parse_timing(const struct shell *sh, size_t argc, char **argv, + struct can_timing *timing) +{ + char *endptr; + + timing->sjw = (uint32_t)strtoul(argv[2], &endptr, 10); + if (*endptr != '\0') { + shell_error(sh, "failed to parse sjw"); + return -EINVAL; + } + + timing->prop_seg = (uint32_t)strtoul(argv[3], &endptr, 10); + if (*endptr != '\0') { + shell_error(sh, "failed to parse prop_seg"); + return -EINVAL; + } + + timing->phase_seg1 = (uint32_t)strtoul(argv[4], &endptr, 10); + if (*endptr != '\0') { + shell_error(sh, "failed to parse phase_seg1"); + return -EINVAL; + } + + timing->phase_seg2 = (uint32_t)strtoul(argv[5], &endptr, 10); + if (*endptr != '\0') { + shell_error(sh, "failed to parse phase_seg2"); + return -EINVAL; + } + + timing->prescaler = (uint32_t)strtoul(argv[6], &endptr, 10); + if (*endptr != '\0') { + shell_error(sh, "failed to parse prescaler"); + return -EINVAL; + } + + return 0; +} + +static int cmd_can_timing_set(const struct shell *sh, size_t argc, char **argv) +{ + const struct device *dev = device_get_binding(argv[1]); + struct can_timing timing = { 0 }; + int err; + + if (!device_is_ready(dev)) { + shell_error(sh, "device %s not ready", argv[1]); + return -ENODEV; + } + + err = can_shell_parse_timing(sh, argc, argv, &timing); + if (err < 0) { + return err; + } + + shell_print(sh, "setting timing to sjw %u, prop_seg %u, phase_seg1 %u, phase_seg2 %u, " + "prescaler %u", timing.sjw, timing.prop_seg, timing.phase_seg1, + timing.phase_seg2, timing.prescaler); + + err = can_set_timing(dev, &timing); + if (err != 0) { + shell_error(sh, "failed to set timing (err %d)", err); + return err; + } + + return 0; +} + +static int cmd_can_dtiming_set(const struct shell *sh, size_t argc, char **argv) +{ + const struct device *dev = device_get_binding(argv[1]); + struct can_timing timing = { 0 }; + int err; + + if (!device_is_ready(dev)) { + shell_error(sh, "device %s not ready", argv[1]); + return -ENODEV; + } + + err = can_shell_parse_timing(sh, argc, argv, &timing); + if (err < 0) { + return err; + } + + shell_print(sh, "setting data phase timing to sjw %u, prop_seg %u, phase_seg1 %u, " + "phase_seg2 %u, prescaler %u", timing.sjw, timing.prop_seg, timing.phase_seg1, + timing.phase_seg2, timing.prescaler); + + err = can_set_timing_data(dev, &timing); + if (err != 0) { + shell_error(sh, "failed to set data phase timing (err %d)", err); + return err; + } + + return 0; +} + static int cmd_can_mode_set(const struct shell *sh, size_t argc, char **argv) { const struct device *dev = device_get_binding(argv[1]); @@ -672,7 +766,7 @@ static int cmd_can_send(const struct shell *sh, size_t argc, char **argv) frame_no = frame_counter++; shell_print(sh, "enqueuing CAN frame #%u with %s (%d-bit) CAN ID 0x%0*x, " - "RTR %d, CAN-FD %d, BRS %d, DLC %d", frame_no, + "RTR %d, CAN FD %d, BRS %d, DLC %d", frame_no, (frame.flags & CAN_FRAME_IDE) != 0 ? "extended" : "standard", (frame.flags & CAN_FRAME_IDE) != 0 ? 29 : 11, (frame.flags & CAN_FRAME_IDE) != 0 ? 8 : 3, frame.id, @@ -784,7 +878,7 @@ static int cmd_can_filter_add(const struct shell *sh, size_t argc, char **argv) } shell_print(sh, "adding filter with %s (%d-bit) CAN ID 0x%0*x, " - "CAN ID mask 0x%0*x, data frames %d, RTR frames %d, CAN-FD frames %d", + "CAN ID mask 0x%0*x, data frames %d, RTR frames %d, CAN FD frames %d", (filter.flags & CAN_FILTER_IDE) != 0 ? "extended" : "standard", (filter.flags & CAN_FILTER_IDE) != 0 ? 29 : 11, (filter.flags & CAN_FILTER_IDE) != 0 ? 8 : 3, filter.id, @@ -911,7 +1005,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_can_filter_cmds, "Add rx filter\n" "Usage: can filter add [-e] [-f] [-r] [-R] [CAN ID mask]\n" "-e use extended (29-bit) CAN ID/CAN ID mask\n" - "-f match CAN-FD format frames\n" + "-f match CAN FD format frames\n" "-r also match Remote Transmission Request (RTR) frames\n" "-R only match Remote Transmission Request (RTR) frames", cmd_can_filter_add, 3, 5), @@ -944,6 +1038,15 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_can_cmds, "Set CAN controller data phase bitrate (sample point and SJW optional)\n" "Usage: can dbitrate [sample point] [sjw]", cmd_can_dbitrate_set, 3, 2), + SHELL_CMD_ARG(timing, &dsub_can_device_name, + "Set CAN controller timing\n" + "Usage: can timing ", + cmd_can_timing_set, 7, 0), + SHELL_COND_CMD_ARG(CONFIG_CAN_FD_MODE, + dtiming, &dsub_can_device_name, + "Set CAN controller data phase timing\n" + "Usage: can dtiming ", + cmd_can_dtiming_set, 7, 0), SHELL_CMD_ARG(mode, &dsub_can_device_name_mode, "Set CAN controller mode\n" "Usage: can mode [mode] [mode] [...]", @@ -953,8 +1056,8 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_can_cmds, "Usage: can send [-e] [-r] [-f] [-b] [data] [...]\n" "-e use extended (29-bit) CAN ID\n" "-r send Remote Transmission Request (RTR) frame\n" - "-f use CAN-FD frame format\n" - "-b use CAN-FD Bit Rate Switching (BRS)", + "-f use CAN FD frame format\n" + "-b use CAN FD Bit Rate Switching (BRS)", cmd_can_send, 3, SHELL_OPT_ARG_CHECK_SKIP), SHELL_CMD(filter, &sub_can_filter_cmds, "CAN rx filter commands\n" diff --git a/drivers/can/can_sja1000.c b/drivers/can/can_sja1000.c index a83cecf4fee..571fc2fb040 100644 --- a/drivers/can/can_sja1000.c +++ b/drivers/can/can_sja1000.c @@ -23,19 +23,14 @@ static inline void can_sja1000_write_reg(const struct device *dev, uint8_t reg, { const struct can_sja1000_config *config = dev->config; - LOG_DBG("write reg %d = 0x%02x", reg, val); return config->write_reg(dev, reg, val); } static inline uint8_t can_sja1000_read_reg(const struct device *dev, uint8_t reg) { const struct can_sja1000_config *config = dev->config; - uint8_t val; - val = config->read_reg(dev, reg); - LOG_DBG("read reg %d = 0x%02x", reg, val); - - return val; + return config->read_reg(dev, reg); } static inline int can_sja1000_enter_reset_mode(const struct device *dev) @@ -58,6 +53,14 @@ static inline int can_sja1000_enter_reset_mode(const struct device *dev) return 0; } +static inline void can_sja1000_leave_reset_mode_nowait(const struct device *dev) +{ + uint8_t mod; + + mod = can_sja1000_read_reg(dev, CAN_SJA1000_MOD); + can_sja1000_write_reg(dev, CAN_SJA1000_MOD, mod & ~(CAN_SJA1000_MOD_RM)); +} + static inline int can_sja1000_leave_reset_mode(const struct device *dev) { int retries = CAN_SJA1000_RESET_MODE_RETRIES; @@ -107,13 +110,6 @@ int can_sja1000_set_timing(const struct device *dev, const struct can_timing *ti struct can_sja1000_data *data = dev->data; uint8_t btr0; uint8_t btr1; - uint8_t sjw; - - __ASSERT_NO_MSG(timing->sjw == CAN_SJW_NO_CHANGE || (timing->sjw >= 1 && timing->sjw <= 4)); - __ASSERT_NO_MSG(timing->prop_seg == 0); - __ASSERT_NO_MSG(timing->phase_seg1 >= 1 && timing->phase_seg1 <= 16); - __ASSERT_NO_MSG(timing->phase_seg2 >= 1 && timing->phase_seg2 <= 8); - __ASSERT_NO_MSG(timing->prescaler >= 1 && timing->prescaler <= 64); if (data->started) { return -EBUSY; @@ -121,15 +117,8 @@ int can_sja1000_set_timing(const struct device *dev, const struct can_timing *ti k_mutex_lock(&data->mod_lock, K_FOREVER); - if (timing->sjw == CAN_SJW_NO_CHANGE) { - sjw = data->sjw; - } else { - sjw = timing->sjw; - data->sjw = timing->sjw; - } - btr0 = CAN_SJA1000_BTR0_BRP_PREP(timing->prescaler - 1) | - CAN_SJA1000_BTR0_SJW_PREP(sjw - 1); + CAN_SJA1000_BTR0_SJW_PREP(timing->sjw - 1); btr1 = CAN_SJA1000_BTR1_TSEG1_PREP(timing->phase_seg1 - 1) | CAN_SJA1000_BTR1_TSEG2_PREP(timing->phase_seg2 - 1); @@ -174,6 +163,7 @@ int can_sja1000_start(const struct device *dev) } can_sja1000_clear_errors(dev); + CAN_STATS_RESET(dev); err = can_sja1000_leave_reset_mode(dev); if (err != 0) { @@ -303,8 +293,11 @@ static void can_sja1000_read_frame(const struct device *dev, struct can_frame *f frame->id |= FIELD_PREP(GENMASK(4, 0), can_sja1000_read_reg(dev, CAN_SJA1000_EFF_ID4) >> 3); - for (i = 0; i < frame->dlc; i++) { - frame->data[i] = can_sja1000_read_reg(dev, CAN_SJA1000_EFF_DATA + i); + if ((frame->flags & CAN_FRAME_RTR) == 0U) { + for (i = 0; i < frame->dlc; i++) { + frame->data[i] = can_sja1000_read_reg(dev, CAN_SJA1000_EFF_DATA + + i); + } } } else { frame->id = FIELD_PREP(GENMASK(10, 3), @@ -312,8 +305,11 @@ static void can_sja1000_read_frame(const struct device *dev, struct can_frame *f frame->id |= FIELD_PREP(GENMASK(2, 0), can_sja1000_read_reg(dev, CAN_SJA1000_XFF_ID2) >> 5); - for (i = 0; i < frame->dlc; i++) { - frame->data[i] = can_sja1000_read_reg(dev, CAN_SJA1000_SFF_DATA + i); + if ((frame->flags & CAN_FRAME_RTR) == 0U) { + for (i = 0; i < frame->dlc; i++) { + frame->data[i] = can_sja1000_read_reg(dev, CAN_SJA1000_SFF_DATA + + i); + } } } } @@ -345,8 +341,11 @@ void can_sja1000_write_frame(const struct device *dev, const struct can_frame *f can_sja1000_write_reg(dev, CAN_SJA1000_EFF_ID4, FIELD_GET(GENMASK(4, 0), frame->id) << 3); - for (i = 0; i < frame->dlc; i++) { - can_sja1000_write_reg(dev, CAN_SJA1000_EFF_DATA + i, frame->data[i]); + if ((frame->flags & CAN_FRAME_RTR) == 0U) { + for (i = 0; i < frame->dlc; i++) { + can_sja1000_write_reg(dev, CAN_SJA1000_EFF_DATA + i, + frame->data[i]); + } } } else { can_sja1000_write_reg(dev, CAN_SJA1000_XFF_ID1, @@ -354,8 +353,11 @@ void can_sja1000_write_frame(const struct device *dev, const struct can_frame *f can_sja1000_write_reg(dev, CAN_SJA1000_XFF_ID2, FIELD_GET(GENMASK(2, 0), frame->id) << 5); - for (i = 0; i < frame->dlc; i++) { - can_sja1000_write_reg(dev, CAN_SJA1000_SFF_DATA + i, frame->data[i]); + if ((frame->flags & CAN_FRAME_RTR) == 0U) { + for (i = 0; i < frame->dlc; i++) { + can_sja1000_write_reg(dev, CAN_SJA1000_SFF_DATA + i, + frame->data[i]); + } } } } @@ -598,6 +600,59 @@ static void can_sja1000_handle_transmit_irq(const struct device *dev) can_sja1000_tx_done(dev, status); } +#ifdef CONFIG_CAN_STATS +static void can_sja1000_handle_data_overrun_irq(const struct device *dev) +{ + /* See NXP SJA1000 Application Note AN97076 (figure 18) for data overrun details */ + + CAN_STATS_RX_OVERRUN_INC(dev); + + can_sja1000_write_reg(dev, CAN_SJA1000_CMR, CAN_SJA1000_CMR_CDO); +} + +static void can_sja1000_handle_bus_error_irq(const struct device *dev) +{ + /* See NXP SJA1000 Application Note AN97076 (tables 6 and 7) for ECC details */ + uint8_t ecc; + + /* Read the Error Code Capture register to re-activate it */ + ecc = can_sja1000_read_reg(dev, CAN_SJA1000_ECC); + + if (ecc == (CAN_SJA1000_ECC_ERRC_OTHER_ERROR | CAN_SJA1000_ECC_DIR_TX | + CAN_SJA1000_ECC_SEG_ACK_SLOT)) { + /* Missing ACK is reported as a TX "other" error in the ACK slot */ + CAN_STATS_ACK_ERROR_INC(dev); + return; + } + + if (ecc == (CAN_SJA1000_ECC_ERRC_FORM_ERROR | CAN_SJA1000_ECC_DIR_RX | + CAN_SJA1000_ECC_SEG_ACK_DELIM)) { + /* CRC error is reported as a RX "form" error in the ACK delimiter */ + CAN_STATS_CRC_ERROR_INC(dev); + return; + } + + switch (ecc & CAN_SJA1000_ECC_ERRC_MASK) { + case CAN_SJA1000_ECC_ERRC_BIT_ERROR: + CAN_STATS_BIT_ERROR_INC(dev); + break; + + case CAN_SJA1000_ECC_ERRC_FORM_ERROR: + CAN_STATS_FORM_ERROR_INC(dev); + break; + case CAN_SJA1000_ECC_ERRC_STUFF_ERROR: + CAN_STATS_STUFF_ERROR_INC(dev); + break; + + case CAN_SJA1000_ECC_ERRC_OTHER_ERROR: + __fallthrough; + default: + /* Other error not currently reported in CAN statistics */ + break; + } +} +#endif /* CONFIG_CAN_STATS */ + static void can_sja1000_handle_error_warning_irq(const struct device *dev) { struct can_sja1000_data *data = dev->data; @@ -609,7 +664,7 @@ static void can_sja1000_handle_error_warning_irq(const struct device *dev) can_sja1000_tx_done(dev, -ENETUNREACH); #ifdef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY if (data->started) { - (void)can_sja1000_leave_reset_mode(dev); + can_sja1000_leave_reset_mode_nowait(dev); } #endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */ } else if ((sr & CAN_SJA1000_SR_ES) != 0) { @@ -649,6 +704,16 @@ void can_sja1000_isr(const struct device *dev) can_sja1000_handle_receive_irq(dev); } +#ifdef CONFIG_CAN_STATS + if ((ir & CAN_SJA1000_IR_DOI) != 0) { + can_sja1000_handle_data_overrun_irq(dev); + } + + if ((ir & CAN_SJA1000_IR_BEI) != 0) { + can_sja1000_handle_bus_error_irq(dev); + } +#endif /* CONFIG_CAN_STATS */ + if ((ir & CAN_SJA1000_IR_EI) != 0) { can_sja1000_handle_error_warning_irq(dev); } @@ -668,7 +733,7 @@ int can_sja1000_init(const struct device *dev) { const struct can_sja1000_config *config = dev->config; struct can_sja1000_data *data = dev->data; - struct can_timing timing; + struct can_timing timing = { 0 }; int err; __ASSERT_NO_MSG(config->read_reg != NULL); @@ -708,10 +773,6 @@ int can_sja1000_init(const struct device *dev) can_sja1000_write_reg(dev, CAN_SJA1000_AMR2, 0xFF); can_sja1000_write_reg(dev, CAN_SJA1000_AMR3, 0xFF); - /* Calculate initial timing parameters */ - data->sjw = config->sjw; - timing.sjw = CAN_SJW_NO_CHANGE; - if (config->sample_point != 0) { err = can_calc_timing(dev, &timing, config->bitrate, config->sample_point); if (err == -EINVAL) { @@ -721,6 +782,7 @@ int can_sja1000_init(const struct device *dev) LOG_DBG("initial sample point error: %d", err); } else { + timing.sjw = config->sjw; timing.prop_seg = 0; timing.phase_seg1 = config->phase_seg1; timing.phase_seg2 = config->phase_seg2; @@ -756,6 +818,9 @@ int can_sja1000_init(const struct device *dev) /* Enable interrupts */ can_sja1000_write_reg(dev, CAN_SJA1000_IER, +#ifdef CONFIG_CAN_STATS + CAN_SJA1000_IER_BEIE | CAN_SJA1000_IER_DOIE | +#endif /* CONFIG_CAN_STATS */ CAN_SJA1000_IER_RIE | CAN_SJA1000_IER_TIE | CAN_SJA1000_IER_EIE | CAN_SJA1000_IER_EPIE); diff --git a/drivers/can/can_sja1000_priv.h b/drivers/can/can_sja1000_priv.h index 03d5dbf0f0d..4a02b734a82 100644 --- a/drivers/can/can_sja1000_priv.h +++ b/drivers/can/can_sja1000_priv.h @@ -108,9 +108,37 @@ /* Error Code Capture register (ECC) bits */ #define CAN_SJA1000_ECC_SEG_MASK GENMASK(4, 0) -#define CAN_SJA1000_ECC_DIR BIT(5) +#define CAN_SJA1000_ECC_DIR_MASK BIT(5) #define CAN_SJA1000_ECC_ERRC_MASK GENMASK(7, 6) +#define CAN_SJA1000_ECC_SEG_SOF FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 3U) +#define CAN_SJA1000_ECC_SEG_ID28_TO_ID21 FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 2U) +#define CAN_SJA1000_ECC_SEG_ID20_TO_ID18 FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 6U) +#define CAN_SJA1000_ECC_SEG_SRTR FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 4U) +#define CAN_SJA1000_ECC_SEG_IDE FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 5U) +#define CAN_SJA1000_ECC_SEG_ID17_TO_ID13 FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 7U) +#define CAN_SJA1000_ECC_SEG_ID12_TO_ID5 FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 15U) +#define CAN_SJA1000_ECC_SEG_ID4_TO_ID0 FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 14U) +#define CAN_SJA1000_ECC_SEG_RTR FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 12U) +#define CAN_SJA1000_ECC_SEG_RES1 FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 13U) +#define CAN_SJA1000_ECC_SEG_RES0 FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 9U) +#define CAN_SJA1000_ECC_SEG_DLC FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 11U) +#define CAN_SJA1000_ECC_SEG_DATA FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 10U) +#define CAN_SJA1000_ECC_SEG_CRC_SEQ FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 8U) +#define CAN_SJA1000_ECC_SEG_CRC_DELIM FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 24U) +#define CAN_SJA1000_ECC_SEG_ACK_SLOT FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 25U) +#define CAN_SJA1000_ECC_SEG_ACK_DELIM FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 27U) +#define CAN_SJA1000_ECC_SEG_EOF FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 26U) +#define CAN_SJA1000_ECC_SEG_INTERMISSION FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 18U) +#define CAN_SJA1000_ECC_SEG_ACTIVE_ERROR_FLAG FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 17U) +#define CAN_SJA1000_ECC_SEG_PASSIVE_ERROR_FLAG FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 22U) +#define CAN_SJA1000_ECC_SEG_TOLERATE_DOM_BITS FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 19U) +#define CAN_SJA1000_ECC_SEG_ERROR_DELIM FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 23U) +#define CAN_SJA1000_ECC_SEG_OVERLOAD_FLAG FIELD_PREP(CAN_SJA1000_ECC_SEG_MASK, 28U) + +#define CAN_SJA1000_ECC_DIR_TX FIELD_PREP(CAN_SJA1000_ECC_DIR_MASK, 0U) +#define CAN_SJA1000_ECC_DIR_RX FIELD_PREP(CAN_SJA1000_ECC_DIR_MASK, 1U) + #define CAN_SJA1000_ECC_ERRC_BIT_ERROR FIELD_PREP(CAN_SJA1000_ECC_ERRC_MASK, 0U) #define CAN_SJA1000_ECC_ERRC_FORM_ERROR FIELD_PREP(CAN_SJA1000_ECC_ERRC_MASK, 1U) #define CAN_SJA1000_ECC_ERRC_STUFF_ERROR FIELD_PREP(CAN_SJA1000_ECC_ERRC_MASK, 2U) diff --git a/drivers/can/can_stm32_bxcan.c b/drivers/can/can_stm32_bxcan.c index cbba04d84ae..58df8f1db5d 100644 --- a/drivers/can/can_stm32_bxcan.c +++ b/drivers/can/can_stm32_bxcan.c @@ -21,7 +21,7 @@ LOG_MODULE_REGISTER(can_stm32, CONFIG_CAN_LOG_LEVEL); -#define CAN_INIT_TIMEOUT (10 * sys_clock_hw_cycles_per_sec() / MSEC_PER_SEC) +#define CAN_INIT_TIMEOUT (10 * (sys_clock_hw_cycles_per_sec() / MSEC_PER_SEC)) #define DT_DRV_COMPAT st_stm32_bxcan @@ -126,11 +126,12 @@ static void can_stm32_rx_fifo_pop(CAN_FIFOMailBox_TypeDef *mbox, struct can_fram if ((mbox->RIR & CAN_RI0R_RTR) != 0) { frame->flags |= CAN_FRAME_RTR; + } else { + frame->data_32[0] = mbox->RDLR; + frame->data_32[1] = mbox->RDHR; } frame->dlc = mbox->RDTR & (CAN_RDT0R_DLC >> CAN_RDT0R_DLC_Pos); - frame->data_32[0] = mbox->RDLR; - frame->data_32[1] = mbox->RDHR; #ifdef CONFIG_CAN_RX_TIMESTAMP frame->timestamp = ((mbox->RDTR & CAN_RDT0R_TIME) >> CAN_RDT0R_TIME_Pos); #endif @@ -555,16 +556,13 @@ static int can_stm32_set_timing(const struct device *dev, return -EBUSY; } - can->BTR = (can->BTR & ~(CAN_BTR_BRP_Msk | CAN_BTR_TS1_Msk | CAN_BTR_TS2_Msk)) | + can->BTR = (can->BTR & ~(CAN_BTR_SJW_Msk | CAN_BTR_BRP_Msk | + CAN_BTR_TS1_Msk | CAN_BTR_TS2_Msk)) | + (((timing->sjw - 1) << CAN_BTR_SJW_Pos) & CAN_BTR_SJW_Msk) | (((timing->phase_seg1 - 1) << CAN_BTR_TS1_Pos) & CAN_BTR_TS1_Msk) | (((timing->phase_seg2 - 1) << CAN_BTR_TS2_Pos) & CAN_BTR_TS2_Msk) | (((timing->prescaler - 1) << CAN_BTR_BRP_Pos) & CAN_BTR_BRP_Msk); - if (timing->sjw != CAN_SJW_NO_CHANGE) { - can->BTR = (can->BTR & ~CAN_BTR_SJW_Msk) | - (((timing->sjw - 1) << CAN_BTR_SJW_Pos) & CAN_BTR_SJW_Msk); - } - k_mutex_unlock(&data->inst_mutex); return 0; @@ -614,7 +612,7 @@ static int can_stm32_init(const struct device *dev) const struct can_stm32_config *cfg = dev->config; struct can_stm32_data *data = dev->data; CAN_TypeDef *can = cfg->can; - struct can_timing timing; + struct can_timing timing = { 0 }; const struct device *clock; uint32_t bank_offset; int ret; @@ -675,7 +673,6 @@ static int can_stm32_init(const struct device *dev) #ifdef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY can->MCR |= CAN_MCR_ABOM; #endif - timing.sjw = cfg->sjw; if (cfg->sample_point && USE_SP_ALGO) { ret = can_calc_timing(dev, &timing, cfg->bus_speed, cfg->sample_point); @@ -687,6 +684,7 @@ static int can_stm32_init(const struct device *dev) timing.prescaler, timing.phase_seg1, timing.phase_seg2); LOG_DBG("Sample-point err : %d", ret); } else { + timing.sjw = cfg->sjw; timing.prop_seg = 0; timing.phase_seg1 = cfg->prop_ts1; timing.phase_seg2 = cfg->ts2; @@ -696,7 +694,7 @@ static int can_stm32_init(const struct device *dev) } } - ret = can_stm32_set_timing(dev, &timing); + ret = can_set_timing(dev, &timing); if (ret) { return ret; } @@ -860,14 +858,14 @@ static int can_stm32_send(const struct device *dev, const struct can_frame *fram if ((frame->flags & CAN_FRAME_RTR) != 0) { mailbox->TIR |= CAN_TI1R_RTR; + } else { + mailbox->TDLR = frame->data_32[0]; + mailbox->TDHR = frame->data_32[1]; } mailbox->TDTR = (mailbox->TDTR & ~CAN_TDT1R_DLC) | ((frame->dlc & 0xF) << CAN_TDT1R_DLC_Pos); - mailbox->TDLR = frame->data_32[0]; - mailbox->TDHR = frame->data_32[1]; - mailbox->TIR |= CAN_TI0R_TXRQ; k_mutex_unlock(&data->inst_mutex); @@ -1037,7 +1035,10 @@ static void can_stm32_remove_rx_filter(const struct device *dev, int filter_id) int bank_num; bool bank_unused; - __ASSERT_NO_MSG(filter_id >= 0 && filter_id < CAN_STM32_MAX_FILTER_ID); + if (filter_id < 0 || filter_id >= CAN_STM32_MAX_FILTER_ID) { + LOG_ERR("filter ID %d out of bounds", filter_id); + return; + } k_mutex_lock(&filter_mutex, K_FOREVER); k_mutex_lock(&data->inst_mutex, K_FOREVER); @@ -1189,10 +1190,10 @@ static const struct can_stm32_config can_stm32_cfg_##inst = { \ static struct can_stm32_data can_stm32_dev_data_##inst; #define CAN_STM32_DEFINE_INST(inst) \ -DEVICE_DT_INST_DEFINE(inst, &can_stm32_init, NULL, \ - &can_stm32_dev_data_##inst, &can_stm32_cfg_##inst, \ - POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ - &can_api_funcs); +CAN_DEVICE_DT_INST_DEFINE(inst, can_stm32_init, NULL, \ + &can_stm32_dev_data_##inst, &can_stm32_cfg_##inst, \ + POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ + &can_api_funcs); #define CAN_STM32_INST(inst) \ CAN_STM32_IRQ_INST(inst) \ diff --git a/drivers/can/can_stm32_fdcan.c b/drivers/can/can_stm32_fdcan.c index 94bc1802c3a..e17fce0e1b9 100644 --- a/drivers/can/can_stm32_fdcan.c +++ b/drivers/can/can_stm32_fdcan.c @@ -673,11 +673,11 @@ static void config_can_##inst##_irq(void) \ static struct can_mcan_data can_mcan_data_##inst = \ CAN_MCAN_DATA_INITIALIZER(NULL); -#define CAN_STM32FD_DEVICE_INST(inst) \ - DEVICE_DT_INST_DEFINE(inst, &can_stm32fd_init, NULL, \ - &can_mcan_data_##inst, &can_mcan_cfg_##inst, \ - POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ - &can_stm32fd_driver_api); +#define CAN_STM32FD_DEVICE_INST(inst) \ + CAN_DEVICE_DT_INST_DEFINE(inst, can_stm32fd_init, NULL, \ + &can_mcan_data_##inst, &can_mcan_cfg_##inst, \ + POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ + &can_stm32fd_driver_api); #define CAN_STM32FD_INST(inst) \ CAN_STM32FD_BUILD_ASSERT_MRAM_CFG(inst) \ diff --git a/drivers/can/can_stm32h7_fdcan.c b/drivers/can/can_stm32h7_fdcan.c index ecffd4ce1cb..291bcfe8091 100644 --- a/drivers/can/can_stm32h7_fdcan.c +++ b/drivers/can/can_stm32h7_fdcan.c @@ -224,11 +224,11 @@ static const struct can_mcan_ops can_stm32h7_ops = { static struct can_mcan_data can_mcan_data_##n = \ CAN_MCAN_DATA_INITIALIZER(NULL); \ \ - DEVICE_DT_INST_DEFINE(n, &can_stm32h7_init, NULL, \ - &can_mcan_data_##n, \ - &can_mcan_cfg_##n, \ - POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ - &can_stm32h7_driver_api); \ + CAN_DEVICE_DT_INST_DEFINE(n, can_stm32h7_init, NULL, \ + &can_mcan_data_##n, \ + &can_mcan_cfg_##n, \ + POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ + &can_stm32h7_driver_api); \ \ static void stm32h7_mcan_irq_config_##n(void) \ { \ diff --git a/drivers/can/can_tcan4x5x.c b/drivers/can/can_tcan4x5x.c new file mode 100644 index 00000000000..d80f8e77526 --- /dev/null +++ b/drivers/can/can_tcan4x5x.c @@ -0,0 +1,800 @@ +/* + * Copyright (c) 2023 Vestas Wind Systems A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(can_tcan4x5x, CONFIG_CAN_LOG_LEVEL); + +#define DT_DRV_COMPAT ti_tcan4x5x + +/* + * The register definitions correspond to those found in the TI TCAN4550-Q1 datasheet, revision D + * June 2022 (SLLSEZ5D). + */ + +/* Device ID1 register */ +#define CAN_TCAN4X5X_DEVICE_ID1 0x0000 + +/* Device ID2 register */ +#define CAN_TCAN4X5X_DEVICE_ID2 0x0004 + +/* Revision register */ +#define CAN_TCAN4X5X_REVISION 0x0008 +#define CAN_TCAN4X5X_REVISION_SPI_2_REVISION GENMASK(31, 24) +#define CAN_TCAN4X5X_REVISION_REV_ID_MAJOR GENMASK(15, 8) +#define CAN_TCAN4X5X_REVISION_REV_ID_MINOR GENMASK(7, 0) + +/* Status register */ +#define CAN_TCAN4X5X_STATUS 0x000c +#define CAN_TCAN4X5X_STATUS_INTERNAL_READ_ERROR BIT(29) +#define CAN_TCAN4X5X_STATUS_INTERNAL_WRITE_ERROR BIT(28) +#define CAN_TCAN4X5X_STATUS_INTERNAL_ERROR_LOG_WRITE BIT(27) +#define CAN_TCAN4X5X_STATUS_READ_FIFO_UNDERFLOW BIT(26) +#define CAN_TCAN4X5X_STATUS_READ_FIFO_EMPTY BIT(25) +#define CAN_TCAN4X5X_STATUS_WRITE_FIFO_OVERFLOW BIT(24) +#define CAN_TCAN4X5X_STATUS_SPI_END_ERROR BIT(21) +#define CAN_TCAN4X5X_STATUS_INVALID_COMMAND BIT(20) +#define CAN_TCAN4X5X_STATUS_WRITE_OVERFLOW BIT(19) +#define CAN_TCAN4X5X_STATUS_WRITE_UNDERFLOW BIT(18) +#define CAN_TCAN4X5X_STATUS_READ_OVERFLOW BIT(17) +#define CAN_TCAN4X5X_STATUS_READ_UNDERFLOW BIT(16) +#define CAN_TCAN4X5X_STATUS_WRITE_FIFO_AVAILABLE BIT(5) +#define CAN_TCAN4X5X_STATUS_READ_FIFO_AVAILABLE BIT(4) +#define CAN_TCAN4X5X_STATUS_INTERNAL_ACCESS_ACTIVE BIT(3) +#define CAN_TCAN4X5X_STATUS_INTERNAL_ERROR_INTERRUPT BIT(2) +#define CAN_TCAN4X5X_STATUS_SPI_ERROR_INTERRUPT BIT(1) +#define CAN_TCAN4X5X_STATUS_INTERRUPT BIT(0) + +/* Mask of clearable status register bits */ +#define CAN_TCAN4X5X_STATUS_CLEAR_ALL \ + (CAN_TCAN4X5X_STATUS_INTERNAL_READ_ERROR | CAN_TCAN4X5X_STATUS_INTERNAL_WRITE_ERROR | \ + CAN_TCAN4X5X_STATUS_INTERNAL_ERROR_LOG_WRITE | CAN_TCAN4X5X_STATUS_READ_FIFO_UNDERFLOW | \ + CAN_TCAN4X5X_STATUS_READ_FIFO_EMPTY | CAN_TCAN4X5X_STATUS_WRITE_FIFO_OVERFLOW | \ + CAN_TCAN4X5X_STATUS_SPI_END_ERROR | CAN_TCAN4X5X_STATUS_INVALID_COMMAND | \ + CAN_TCAN4X5X_STATUS_WRITE_OVERFLOW | CAN_TCAN4X5X_STATUS_WRITE_UNDERFLOW | \ + CAN_TCAN4X5X_STATUS_READ_OVERFLOW | CAN_TCAN4X5X_STATUS_READ_UNDERFLOW) + +/* SPI Error Status Mask register */ +#define CAN_TCAN4X5X_SPI_ERROR_STATUS_MASK 0x0010 +#define CAN_TCAN4X5X_SPI_ERROR_STATUS_MASK_INTERNAL_READ_ERROR BIT(29) +#define CAN_TCAN4X5X_SPI_ERROR_STATUS_MASK_INTERNAL_WRITE_ERROR BIT(28) +#define CAN_TCAN4X5X_SPI_ERROR_STATUS_MASK_INTERNAL_ERROR_LOG_WRITE BIT(27) +#define CAN_TCAN4X5X_SPI_ERROR_STATUS_MASK_READ_FIFO_UNDERFLOW BIT(26) +#define CAN_TCAN4X5X_SPI_ERROR_STATUS_MASK_READ_FIFO_EMPTY BIT(25) +#define CAN_TCAN4X5X_SPI_ERROR_STATUS_MASK_WRITE_FIFO_OVERFLOW BIT(24) +#define CAN_TCAN4X5X_SPI_ERROR_STATUS_MASK_SPI_END_ERROR BIT(21) +#define CAN_TCAN4X5X_SPI_ERROR_STATUS_MASK_INVALID_COMMAND BIT(20) +#define CAN_TCAN4X5X_SPI_ERROR_STATUS_MASK_WRITE_OVERFLOW BIT(19) +#define CAN_TCAN4X5X_SPI_ERROR_STATUS_MASK_WRITE_UNDERFLOW BIT(18) +#define CAN_TCAN4X5X_SPI_ERROR_STATUS_MASK_READ_OVERFLOW BIT(17) +#define CAN_TCAN4X5X_SPI_ERROR_STATUS_MASK_READ_UNDERFLOW BIT(16) + +/* Modes of Operation and Pin Configurations register */ +#define CAN_TCAN4X5X_MODE_CONFIG 0x0800 +#define CAN_TCAN4X5X_MODE_CONFIG_WAKE_CONFIG GENMASK(31, 30) +#define CAN_TCAN4X5X_MODE_CONFIG_WD_TIMER GENMASK(29, 28) +#define CAN_TCAN4X5X_MODE_CONFIG_CLK_REF BIT(27) +#define CAN_TCAN4X5X_MODE_CONFIG_GPO2_CONFIG GENMASK(23, 22) +#define CAN_TCAN4X5X_MODE_CONFIG_TEST_MODE_EN BIT(21) +#define CAN_TCAN4X5X_MODE_CONFIG_NWKRQ_VOLTAGE BIT(19) +#define CAN_TCAN4X5X_MODE_CONFIG_WD_BIT_SET BIT(18) +#define CAN_TCAN4X5X_MODE_CONFIG_WD_ACTION GENMASK(17, 16) +#define CAN_TCAN4X5X_MODE_CONFIG_GPIO1_CONFIG GENMASK(15, 14) +#define CAN_TCAN4X5X_MODE_CONFIG_FAIL_SAFE_EN BIT(13) +#define CAN_TCAN4X5X_MODE_CONFIG_GPIO1_GPO_CONFIG GENMASK(11, 10) +#define CAN_TCAN4X5X_MODE_CONFIG_INH_DIS BIT(9) +#define CAN_TCAN4X5X_MODE_CONFIG_NWKRQ_CONFIG BIT(8) +#define CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL GENMASK(7, 6) +#define CAN_TCAN4X5X_MODE_CONFIG_WD_EN BIT(3) +#define CAN_TCAN4X5X_MODE_CONFIG_DEVICE_RESET BIT(2) +#define CAN_TCAN4X5X_MODE_CONFIG_SWE_DIS BIT(1) +#define CAN_TCAN4X5X_MODE_CONFIG_TEST_MODE_CONFIG BIT(0) + +/* Timestamp Prescaler register */ +#define CAN_TCAN4X5X_TIMESTAMP_PRESCALER 0x0804 +#define CAN_TCAN4X5X_TIMESTAMP_PRESCALER_MASK GENMASK(7, 0) + +/* Test Register and Scratch Pad */ +#define CAN_TCAN4X5X_TEST_SCRATCH_PAD 0x0808 +#define CAN_TCAN4X5X_TEST_SCRATCH_PAD_READ_WRITE GENMASK(31, 16) +#define CAN_TCAN4X5X_TEST_SCRATCH_PAD_SCRATCH_PAD GENMASK(15, 0) + +/* Test register */ +#define CAN_TCAN4X5X_TEST 0x0808 +#define CAN_TCAN4X5X_TEST_ECC_ERR_FORCE_BIT_SEL GENMASK(21, 16) +#define CAN_TCAN4X5X_TEST_ECC_ERR_FORCE BIT(12) +#define CAN_TCAN4X5X_TEST_ECC_ERR_CHECK BIT(11) + +/* Interrupts register */ +#define CAN_TCAN4X5X_IR 0x0820 +#define CAN_TCAN4X5X_IR_CANBUSNOM BIT(31) +#define CAN_TCAN4X5X_IR_SMS BIT(23) +#define CAN_TCAN4X5X_IR_UVSUP BIT(22) +#define CAN_TCAN4X5X_IR_UVIO BIT(21) +#define CAN_TCAN4X5X_IR_PWRON BIT(20) +#define CAN_TCAN4X5X_IR_TSD BIT(19) +#define CAN_TCAN4X5X_IR_WDTO BIT(18) +#define CAN_TCAN4X5X_IR_ECCERR BIT(16) +#define CAN_TCAN4X5X_IR_CANINT BIT(15) +#define CAN_TCAN4X5X_IR_LWU BIT(14) +#define CAN_TCAN4X5X_IR_WKERR BIT(13) +#define CAN_TCAN4X5X_IR_CANSLNT BIT(10) +#define CAN_TCAN4X5X_IR_CANDOM BIT(8) +#define CAN_TCAN4X5X_IR_GLOBALERR BIT(7) +#define CAN_TCAN4X5X_IR_WKRQ BIT(6) +#define CAN_TCAN4X5X_IR_CANERR BIT(5) +#define CAN_TCAN4X5X_IR_SPIERR BIT(3) +#define CAN_TCAN4X5X_IR_M_CAN_INT BIT(1) +#define CAN_TCAN4X5X_IR_VTWD BIT(0) + +/* Mask of clearable interrupts register bits */ +#define CAN_TCAN4X5X_IR_CLEAR_ALL \ + (CAN_TCAN4X5X_IR_SMS | CAN_TCAN4X5X_IR_UVSUP | CAN_TCAN4X5X_IR_UVIO | \ + CAN_TCAN4X5X_IR_PWRON | CAN_TCAN4X5X_IR_TSD | CAN_TCAN4X5X_IR_WDTO | \ + CAN_TCAN4X5X_IR_ECCERR | CAN_TCAN4X5X_IR_CANINT | CAN_TCAN4X5X_IR_LWU | \ + CAN_TCAN4X5X_IR_WKERR | CAN_TCAN4X5X_IR_CANSLNT | CAN_TCAN4X5X_IR_CANDOM) + +/* MCAN Interrupts register */ +#define CAN_TCAN4X5X_MCAN_IR 0x0824 +#define CAN_TCAN4X5X_MCAN_IR_ARA BIT(29) +#define CAN_TCAN4X5X_MCAN_IR_PED BIT(28) +#define CAN_TCAN4X5X_MCAN_IR_PEA BIT(27) +#define CAN_TCAN4X5X_MCAN_IR_WDI BIT(26) +#define CAN_TCAN4X5X_MCAN_IR_BO BIT(25) +#define CAN_TCAN4X5X_MCAN_IR_EW BIT(24) +#define CAN_TCAN4X5X_MCAN_IR_EP BIT(23) +#define CAN_TCAN4X5X_MCAN_IR_ELO BIT(22) +#define CAN_TCAN4X5X_MCAN_IR_BEU BIT(21) +#define CAN_TCAN4X5X_MCAN_IR_BEC BIT(20) +#define CAN_TCAN4X5X_MCAN_IR_DRX BIT(19) +#define CAN_TCAN4X5X_MCAN_IR_TOO BIT(18) +#define CAN_TCAN4X5X_MCAN_IR_MRAF BIT(17) +#define CAN_TCAN4X5X_MCAN_IR_TSW BIT(16) +#define CAN_TCAN4X5X_MCAN_IR_TEFL BIT(15) +#define CAN_TCAN4X5X_MCAN_IR_TEFF BIT(14) +#define CAN_TCAN4X5X_MCAN_IR_TEFW BIT(13) +#define CAN_TCAN4X5X_MCAN_IR_TEFN BIT(12) +#define CAN_TCAN4X5X_MCAN_IR_TFE BIT(11) +#define CAN_TCAN4X5X_MCAN_IR_TCF BIT(10) +#define CAN_TCAN4X5X_MCAN_IR_TC BIT(9) +#define CAN_TCAN4X5X_MCAN_IR_HPM BIT(8) +#define CAN_TCAN4X5X_MCAN_IR_RF1L BIT(7) +#define CAN_TCAN4X5X_MCAN_IR_RF1F BIT(6) +#define CAN_TCAN4X5X_MCAN_IR_RF1W BIT(5) +#define CAN_TCAN4X5X_MCAN_IR_RF1N BIT(4) +#define CAN_TCAN4X5X_MCAN_IR_RF0L BIT(3) +#define CAN_TCAN4X5X_MCAN_IR_RF0F BIT(2) +#define CAN_TCAN4X5X_MCAN_IR_RF0W BIT(1) +#define CAN_TCAN4X5X_MCAN_IR_RF0N BIT(0) + +/* Interrupt Enables register */ +#define CAN_TCAN4X5X_IE 0x0830 +#define CAN_TCAN4X5X_IE_UVSUP BIT(22) +#define CAN_TCAN4X5X_IE_UVIO BIT(21) +#define CAN_TCAN4X5X_IE_TSD BIT(19) +#define CAN_TCAN4X5X_IE_ECCERR BIT(16) +#define CAN_TCAN4X5X_IE_CANINT BIT(15) +#define CAN_TCAN4X5X_IE_LWU BIT(14) +#define CAN_TCAN4X5X_IE_CANSLNT BIT(10) +#define CAN_TCAN4X5X_IE_CANDOM BIT(8) + +/* Bosch M_CAN registers base address */ +#define CAN_TCAN4X5X_MCAN_BASE 0x1000 + +/* Bosch M_CAN Message RAM base address and size */ +#define CAN_TCAN4X5X_MRAM_BASE 0x8000 +#define CAN_TCAN4X5X_MRAM_SIZE 2048 + +/* TCAN4x5x SPI OP codes */ +#define CAN_TCAN4X5X_WRITE_B_FL 0x61 +#define CAN_TCAN4X5X_READ_B_FL 0x41 + +/* TCAN4x5x timing requirements */ +#define CAN_TCAN4X5X_T_MODE_STBY_NOM_US 70 +#define CAN_TCAN4X5X_T_WAKE_US 50 +#define CAN_TCAN4X5X_T_PULSE_WIDTH_US 30 +#define CAN_TCAN4X5X_T_RESET_US 1000 + +/* + * Only compile in support for the optional GPIOs if at least one enabled tcan4x5x device tree node + * has them. Only the INT GPIO is required. + */ +#define TCAN4X5X_RST_GPIO_SUPPORT DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) +#define TCAN4X5X_NWKRQ_GPIO_SUPPORT DT_ANY_INST_HAS_PROP_STATUS_OKAY(device_state_gpios) +#define TCAN4X5X_WAKE_GPIO_SUPPORT DT_ANY_INST_HAS_PROP_STATUS_OKAY(device_wake_gpios) + +struct tcan4x5x_config { + struct spi_dt_spec spi; +#if TCAN4X5X_RST_GPIO_SUPPORT + struct gpio_dt_spec rst_gpio; +#endif /* TCAN4X5X_RST_GPIO_SUPPORT */ +#if TCAN4X5X_NWKRQ_GPIO_SUPPORT + struct gpio_dt_spec nwkrq_gpio; +#endif /* TCAN4X5X_NWKRQ_GPIO_SUPPORT */ +#if TCAN4X5X_WAKE_GPIO_SUPPORT + struct gpio_dt_spec wake_gpio; +#endif /* TCAN4X5X_WAKE_GPIO_SUPPORT */ + struct gpio_dt_spec int_gpio; + uint32_t clk_freq; +}; + +struct tcan4x5x_data { + struct gpio_callback int_gpio_cb; + struct k_thread int_thread; + struct k_sem int_sem; + + K_KERNEL_STACK_MEMBER(int_stack, CONFIG_CAN_TCAN4X5X_THREAD_STACK_SIZE); +}; + +static int tcan4x5x_read(const struct device *dev, uint16_t addr, void *dst, size_t len) +{ + const struct can_mcan_config *mcan_config = dev->config; + const struct tcan4x5x_config *tcan_config = mcan_config->custom; + size_t len32 = len / sizeof(uint32_t); + uint32_t *dst32 = (uint32_t *)dst; + uint8_t cmd[4] = {CAN_TCAN4X5X_READ_B_FL, addr >> 8U & 0xFF, addr & 0xFF, + len32 == 256 ? 0U : len32}; + uint8_t global_status; + const struct spi_buf tx_bufs[] = { + {.buf = &cmd, .len = sizeof(cmd)}, + }; + const struct spi_buf rx_bufs[] = { + {.buf = &global_status, .len = sizeof(global_status)}, + {.buf = NULL, .len = 3}, + {.buf = dst, .len = len}, + }; + const struct spi_buf_set tx = { + .buffers = tx_bufs, + .count = ARRAY_SIZE(tx_bufs), + }; + const struct spi_buf_set rx = { + .buffers = rx_bufs, + .count = ARRAY_SIZE(rx_bufs), + }; + int err; + int i; + + if (len == 0) { + return 0; + } + + /* Maximum transfer size is 256 32-bit words */ + __ASSERT_NO_MSG(len % 4 == 0); + __ASSERT_NO_MSG(len32 <= 256); + + err = spi_transceive_dt(&tcan_config->spi, &tx, &rx); + if (err != 0) { + LOG_ERR("failed to read addr %u, len %d (err %d)", addr, len, err); + return err; + } + + __ASSERT_NO_MSG((global_status & CAN_TCAN4X5X_IR_SPIERR) == 0U); + + for (i = 0; i < len32; i++) { + dst32[i] = sys_be32_to_cpu(dst32[i]); + } + + return 0; +} + +static int tcan4x5x_write(const struct device *dev, uint16_t addr, const void *src, size_t len) +{ + const struct can_mcan_config *mcan_config = dev->config; + const struct tcan4x5x_config *tcan_config = mcan_config->custom; + size_t len32 = len / sizeof(uint32_t); + uint32_t src32[len32]; + uint8_t cmd[4] = {CAN_TCAN4X5X_WRITE_B_FL, addr >> 8U & 0xFF, addr & 0xFF, + len32 == 256 ? 0U : len32}; + uint8_t global_status; + const struct spi_buf tx_bufs[] = { + {.buf = &cmd, .len = sizeof(cmd)}, + {.buf = &src32, .len = len}, + }; + const struct spi_buf rx_bufs[] = { + {.buf = &global_status, .len = sizeof(global_status)}, + }; + const struct spi_buf_set tx = { + .buffers = tx_bufs, + .count = ARRAY_SIZE(tx_bufs), + }; + const struct spi_buf_set rx = { + .buffers = rx_bufs, + .count = ARRAY_SIZE(rx_bufs), + }; + int err; + int i; + + if (len == 0) { + return 0; + } + + /* Maximum transfer size is 256 32-bit words */ + __ASSERT_NO_MSG(len % 4 == 0); + __ASSERT_NO_MSG(len32 <= 256); + + for (i = 0; i < len32; i++) { + src32[i] = sys_cpu_to_be32(((uint32_t *)src)[i]); + } + + err = spi_transceive_dt(&tcan_config->spi, &tx, &rx); + if (err != 0) { + LOG_ERR("failed to write addr %u, len %d (err %d)", addr, len, err); + return err; + } + + __ASSERT_NO_MSG((global_status & CAN_TCAN4X5X_IR_SPIERR) == 0U); + + return 0; +} + +static inline int tcan4x5x_read_tcan_reg(const struct device *dev, uint16_t reg, uint32_t *val) +{ + return tcan4x5x_read(dev, reg, val, sizeof(uint32_t)); +} + +static inline int tcan4x5x_write_tcan_reg(const struct device *dev, uint16_t reg, uint32_t val) +{ + return tcan4x5x_write(dev, reg, &val, sizeof(uint32_t)); +} + +static int tcan4x5x_read_mcan_reg(const struct device *dev, uint16_t reg, uint32_t *val) +{ + return tcan4x5x_read(dev, CAN_TCAN4X5X_MCAN_BASE + reg, val, sizeof(uint32_t)); +} + +static int tcan4x5x_write_mcan_reg(const struct device *dev, uint16_t reg, uint32_t val) +{ + return tcan4x5x_write(dev, CAN_TCAN4X5X_MCAN_BASE + reg, &val, sizeof(uint32_t)); +} + +static int tcan4x5x_read_mcan_mram(const struct device *dev, uint16_t offset, void *dst, size_t len) +{ + return tcan4x5x_read(dev, CAN_TCAN4X5X_MRAM_BASE + offset, dst, len); +} + +static int tcan4x5x_write_mcan_mram(const struct device *dev, uint16_t offset, const void *src, + size_t len) +{ + return tcan4x5x_write(dev, CAN_TCAN4X5X_MRAM_BASE + offset, src, len); +} + +static int tcan4x5x_clear_mcan_mram(const struct device *dev, uint16_t offset, size_t len) +{ + static const uint8_t buf[256] = {0}; + size_t pending; + size_t upto; + int err; + + for (upto = 0; upto < len; upto += pending) { + pending = MIN(len - upto, sizeof(buf)); + + err = tcan4x5x_write_mcan_mram(dev, offset, &buf, pending); + if (err != 0) { + LOG_ERR("failed to clear message RAM (err %d)", err); + return err; + } + + offset += pending; + } + + return 0; +} + +static int tcan4x5x_get_core_clock(const struct device *dev, uint32_t *rate) +{ + const struct can_mcan_config *mcan_config = dev->config; + const struct tcan4x5x_config *tcan_config = mcan_config->custom; + + *rate = tcan_config->clk_freq; + + return 0; +} + +static void tcan4x5x_int_gpio_callback_handler(const struct device *port, struct gpio_callback *cb, + gpio_port_pins_t pins) +{ + struct tcan4x5x_data *tcan_data = CONTAINER_OF(cb, struct tcan4x5x_data, int_gpio_cb); + + k_sem_give(&tcan_data->int_sem); +} + +static void tcan4x5x_int_thread(void *p1, void *p2, void *p3) +{ + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; + struct can_mcan_data *mcan_data = dev->data; + struct tcan4x5x_data *tcan_data = mcan_data->custom; + uint32_t status; + uint32_t ir; + int err; + + while (true) { + k_sem_take(&tcan_data->int_sem, K_FOREVER); + + err = tcan4x5x_read_tcan_reg(dev, CAN_TCAN4X5X_IR, &ir); + if (err != 0) { + LOG_ERR("failed to read interrupt register (err %d)", err); + continue; + } + + while (ir != 0U) { + err = tcan4x5x_write_tcan_reg(dev, CAN_TCAN4X5X_IR, + ir & CAN_TCAN4X5X_IR_CLEAR_ALL); + if (err != 0) { + LOG_ERR("failed to write interrupt register (err %d)", err); + break; + } + + if ((ir & CAN_TCAN4X5X_IR_SPIERR) != 0U) { + err = tcan4x5x_read_tcan_reg(dev, CAN_TCAN4X5X_STATUS, &status); + if (err != 0) { + LOG_ERR("failed to read status register (err %d)", err); + continue; + } + + LOG_ERR("SPIERR, status = 0x%08x", status); + + err = tcan4x5x_write_tcan_reg(dev, CAN_TCAN4X5X_STATUS, status & + CAN_TCAN4X5X_STATUS_CLEAR_ALL); + if (err != 0) { + LOG_ERR("failed to write status register (err %d)", err); + continue; + } + } + + if ((ir & CAN_TCAN4X5X_IR_M_CAN_INT) != 0U) { + can_mcan_line_0_isr(dev); + can_mcan_line_1_isr(dev); + } + + err = tcan4x5x_read_tcan_reg(dev, CAN_TCAN4X5X_IR, &ir); + if (err != 0) { + LOG_ERR("failed to read interrupt register (err %d)", err); + break; + } + } + } +} + +static int tcan4x5x_wake(const struct device *dev) +{ +#if TCAN4X5X_WAKE_GPIO_SUPPORT + const struct can_mcan_config *mcan_config = dev->config; + const struct tcan4x5x_config *tcan_config = mcan_config->custom; + int wake_needed = 1; + int err; + +#if TCAN4X5X_NWKRQ_GPIO_SUPPORT + if (tcan_config->wake_gpio.port != NULL && tcan_config->nwkrq_gpio.port != NULL) { + wake_needed = gpio_pin_get_dt(&tcan_config->nwkrq_gpio); + + if (wake_needed < 0) { + LOG_ERR("failed to get nWKRQ status (err %d)", wake_needed); + return wake_needed; + }; + } +#endif /* TCAN4X5X_NWKRQ_GPIO_SUPPORT */ + if (tcan_config->wake_gpio.port != NULL && wake_needed != 0) { + err = gpio_pin_set_dt(&tcan_config->wake_gpio, 1); + if (err != 0) { + LOG_ERR("failed to assert WAKE GPIO (err %d)", err); + return err; + } + + k_busy_wait(CAN_TCAN4X5X_T_WAKE_US); + + err = gpio_pin_set_dt(&tcan_config->wake_gpio, 0); + if (err != 0) { + LOG_ERR("failed to deassert WAKE GPIO (err %d)", err); + return err; + } + } +#endif /* TCAN4X5X_WAKE_GPIO_SUPPORT*/ + + return 0; +} + +static int tcan4x5x_reset(const struct device *dev) +{ + const struct can_mcan_config *mcan_config = dev->config; + const struct tcan4x5x_config *tcan_config = mcan_config->custom; + int err; + + err = tcan4x5x_wake(dev); + if (err != 0) { + return err; + } + +#if TCAN4X5X_RST_GPIO_SUPPORT + if (tcan_config->rst_gpio.port != NULL) { + err = gpio_pin_set_dt(&tcan_config->rst_gpio, 1); + if (err != 0) { + LOG_ERR("failed to assert RST GPIO (err %d)", err); + return err; + } + + k_busy_wait(CAN_TCAN4X5X_T_PULSE_WIDTH_US); + + err = gpio_pin_set_dt(&tcan_config->rst_gpio, 0); + if (err != 0) { + LOG_ERR("failed to deassert RST GPIO (err %d)", err); + return err; + } + } else { +#endif /* TCAN4X5X_RST_GPIO_SUPPORT */ + err = tcan4x5x_write_tcan_reg(dev, CAN_TCAN4X5X_MODE_CONFIG, + CAN_TCAN4X5X_MODE_CONFIG_DEVICE_RESET); + if (err != 0) { + LOG_ERR("failed to initiate SW reset (err %d)", err); + return err; + } +#if TCAN4X5X_RST_GPIO_SUPPORT + } +#endif /* TCAN4X5X_RST_GPIO_SUPPORT */ + + k_busy_wait(CAN_TCAN4X5X_T_RESET_US); + + return 0; +} + +static int tcan4x5x_init(const struct device *dev) +{ + const struct can_mcan_config *mcan_config = dev->config; + const struct tcan4x5x_config *tcan_config = mcan_config->custom; + struct can_mcan_data *mcan_data = dev->data; + struct tcan4x5x_data *tcan_data = mcan_data->custom; + k_tid_t tid; + uint32_t reg; + int err; + + /* Initialize int_sem to 1 to ensure any pending IRQ is serviced */ + k_sem_init(&tcan_data->int_sem, 1, 1); + + if (!spi_is_ready_dt(&tcan_config->spi)) { + LOG_ERR("SPI bus not ready"); + return -ENODEV; + } + +#if TCAN4X5X_RST_GPIO_SUPPORT + if (tcan_config->rst_gpio.port != NULL) { + if (!gpio_is_ready_dt(&tcan_config->rst_gpio)) { + LOG_ERR("RST GPIO not ready"); + return -ENODEV; + } + + err = gpio_pin_configure_dt(&tcan_config->rst_gpio, GPIO_OUTPUT_INACTIVE); + if (err != 0) { + LOG_ERR("failed to configure RST GPIO (err %d)", err); + return -ENODEV; + } + } +#endif /* TCAN4X5X_RST_GPIO_SUPPORT */ + +#if TCAN4X5X_NWKRQ_GPIO_SUPPORT + if (tcan_config->nwkrq_gpio.port != NULL) { + if (!gpio_is_ready_dt(&tcan_config->nwkrq_gpio)) { + LOG_ERR("nWKRQ GPIO not ready"); + return -ENODEV; + } + + err = gpio_pin_configure_dt(&tcan_config->nwkrq_gpio, GPIO_INPUT); + if (err != 0) { + LOG_ERR("failed to configure nWKRQ GPIO (err %d)", err); + return -ENODEV; + } + } +#endif /* TCAN4X5X_NWKRQ_GPIO_SUPPORT */ + +#if TCAN4X5X_WAKE_GPIO_SUPPORT + if (tcan_config->wake_gpio.port != NULL) { + if (!gpio_is_ready_dt(&tcan_config->wake_gpio)) { + LOG_ERR("WAKE GPIO not ready"); + return -ENODEV; + } + + err = gpio_pin_configure_dt(&tcan_config->wake_gpio, GPIO_OUTPUT_INACTIVE); + if (err != 0) { + LOG_ERR("failed to configure WAKE GPIO (err %d)", err); + return -ENODEV; + } + } +#endif /* TCAN4X5X_WAKE_GPIO_SUPPORT */ + + if (!gpio_is_ready_dt(&tcan_config->int_gpio)) { + LOG_ERR("nINT GPIO not ready"); + return -ENODEV; + } + + err = gpio_pin_configure_dt(&tcan_config->int_gpio, GPIO_INPUT); + if (err != 0) { + LOG_ERR("failed to configure nINT GPIO (err %d)", err); + return -ENODEV; + } + + gpio_init_callback(&tcan_data->int_gpio_cb, tcan4x5x_int_gpio_callback_handler, + BIT(tcan_config->int_gpio.pin)); + + err = gpio_add_callback_dt(&tcan_config->int_gpio, &tcan_data->int_gpio_cb); + if (err != 0) { + LOG_ERR("failed to add nINT GPIO callback (err %d)", err); + return -ENODEV; + } + + /* Initialize nINT GPIO callback and interrupt handler thread to ACK any early SPIERR */ + err = gpio_pin_interrupt_configure_dt(&tcan_config->int_gpio, GPIO_INT_EDGE_TO_ACTIVE); + if (err != 0) { + LOG_ERR("failed to configure nINT GPIO interrupt (err %d)", err); + return -ENODEV; + } + + tid = k_thread_create(&tcan_data->int_thread, tcan_data->int_stack, + K_KERNEL_STACK_SIZEOF(tcan_data->int_stack), + tcan4x5x_int_thread, (void *)dev, NULL, NULL, + CONFIG_CAN_TCAN4X5X_THREAD_PRIO, 0, K_NO_WAIT); + k_thread_name_set(tid, "tcan4x5x"); + + /* Reset TCAN */ + err = tcan4x5x_reset(dev); + if (err != 0) { + return -ENODEV; + } + +#if CONFIG_CAN_LOG_LEVEL >= LOG_LEVEL_DBG + uint32_t info[3]; + + /* Read DEVICE_ID1, DEVICE_ID2, and REVISION registers */ + err = tcan4x5x_read(dev, CAN_TCAN4X5X_DEVICE_ID1, &info, sizeof(info)); + if (err != 0) { + return -EIO; + } + + LOG_DBG("%c%c%c%c%c%c%c%c, SPI 2 rev. %lu, device rev. ID %lu.%lu", + (char)FIELD_GET(GENMASK(7, 0), info[0]), (char)FIELD_GET(GENMASK(15, 8), info[0]), + (char)FIELD_GET(GENMASK(23, 16), info[0]), + (char)FIELD_GET(GENMASK(31, 24), info[0]), (char)FIELD_GET(GENMASK(7, 0), info[1]), + (char)FIELD_GET(GENMASK(15, 8), info[1]), (char)FIELD_GET(GENMASK(23, 16), info[1]), + (char)FIELD_GET(GENMASK(31, 24), info[1]), FIELD_GET(GENMASK(31, 24), info[2]), + FIELD_GET(GENMASK(15, 8), info[2]), FIELD_GET(GENMASK(7, 0), info[2])); +#endif /* CONFIG_CAN_LOG_LEVEL >= LOG_LEVEL_DBG */ + + /* Set TCAN4x5x mode normal */ + err = tcan4x5x_read_tcan_reg(dev, CAN_TCAN4X5X_MODE_CONFIG, ®); + if (err != 0) { + LOG_ERR("failed to read configuration register (err %d)", err); + return -ENODEV; + } + + reg &= ~(CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL); + reg |= FIELD_PREP(CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL, 0x02); + reg |= CAN_TCAN4X5X_MODE_CONFIG_WAKE_CONFIG; + + if (tcan_config->clk_freq == MHZ(20)) { + /* 20 MHz frequency reference */ + reg &= ~(CAN_TCAN4X5X_MODE_CONFIG_CLK_REF); + } else { + /* 40 MHz frequency reference */ + reg |= CAN_TCAN4X5X_MODE_CONFIG_CLK_REF; + } + + err = tcan4x5x_write_tcan_reg(dev, CAN_TCAN4X5X_MODE_CONFIG, reg); + if (err != 0) { + LOG_ERR("failed to write configuration register (err %d)", err); + return -ENODEV; + } + + /* Wait for standby to normal mode switch */ + k_busy_wait(CAN_TCAN4X5X_T_MODE_STBY_NOM_US); + + /* Configure Message RAM */ + err = can_mcan_configure_mram(dev, CAN_TCAN4X5X_MRAM_BASE, CAN_TCAN4X5X_MRAM_BASE); + if (err != 0) { + return -EIO; + } + + /* Initialize M_CAN */ + err = can_mcan_init(dev); + if (err != 0) { + LOG_ERR("failed to initialize mcan (err %d)", err); + return err; + } + + return 0; +} + +static const struct can_driver_api tcan4x5x_driver_api = { + .get_capabilities = can_mcan_get_capabilities, + .start = can_mcan_start, + .stop = can_mcan_stop, + .set_mode = can_mcan_set_mode, + .set_timing = can_mcan_set_timing, + .send = can_mcan_send, + .add_rx_filter = can_mcan_add_rx_filter, + .remove_rx_filter = can_mcan_remove_rx_filter, +#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY + .recover = can_mcan_recover, +#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */ + .get_state = can_mcan_get_state, + .set_state_change_callback = can_mcan_set_state_change_callback, + .get_core_clock = tcan4x5x_get_core_clock, + .get_max_filters = can_mcan_get_max_filters, + .get_max_bitrate = can_mcan_get_max_bitrate, + .timing_min = CAN_MCAN_TIMING_MIN_INITIALIZER, + .timing_max = CAN_MCAN_TIMING_MAX_INITIALIZER, +#ifdef CONFIG_CAN_FD_MODE + .set_timing_data = can_mcan_set_timing_data, + .timing_data_min = CAN_MCAN_TIMING_DATA_MIN_INITIALIZER, + .timing_data_max = CAN_MCAN_TIMING_DATA_MAX_INITIALIZER, +#endif /* CONFIG_CAN_FD_MODE */ +}; + +static const struct can_mcan_ops tcan4x5x_ops = { + .read_reg = tcan4x5x_read_mcan_reg, + .write_reg = tcan4x5x_write_mcan_reg, + .read_mram = tcan4x5x_read_mcan_mram, + .write_mram = tcan4x5x_write_mcan_mram, + .clear_mram = tcan4x5x_clear_mcan_mram, +}; + +#if TCAN4X5X_RST_GPIO_SUPPORT +#define TCAN4X5X_RST_GPIO_INIT(inst) \ + .rst_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, {0}), +#else /* TCAN4X5X_RST_GPIO_SUPPORT */ +#define TCAN4X5X_RST_GPIO_INIT(inst) +#endif /* !TCAN4X5X_RST_GPIO_SUPPORT */ + +#if TCAN4X5X_NWKRQ_GPIO_SUPPORT +#define TCAN4X5X_NWKRQ_GPIO_INIT(inst) \ + .nwkrq_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, device_state_gpios, {0}), +#else /* TCAN4X5X_NWKRQ_GPIO_SUPPORT */ +#define TCAN4X5X_NWKRQ_GPIO_INIT(inst) +#endif /* !TCAN4X5X_NWKRQ_GPIO_SUPPORT */ + +#if TCAN4X5X_WAKE_GPIO_SUPPORT +#define TCAN4X5X_WAKE_GPIO_INIT(inst) \ + .wake_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, device_wake_gpios, {0}), +#else /* TCAN4X5X_WAKE_GPIO_SUPPORT */ +#define TCAN4X5X_WAKE_GPIO_INIT(inst) +#endif /* !TCAN4X5X_WAKE_GPIO_SUPPORT */ + +#define TCAN4X5X_INIT(inst) \ + BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_OFFSET(inst) == 0, "MRAM offset must be 0"); \ + BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_ELEMENTS_SIZE(inst) <= CAN_TCAN4X5X_MRAM_SIZE, \ + "Insufficient Message RAM size to hold elements"); \ + \ + CAN_MCAN_DT_INST_BUILD_ASSERT_MRAM_CFG(inst); \ + CAN_MCAN_DT_INST_CALLBACKS_DEFINE(inst, tcan4x5x_cbs_##inst); \ + \ + static const struct tcan4x5x_config tcan4x5x_config_##inst = { \ + .spi = SPI_DT_SPEC_INST_GET(inst, SPI_WORD_SET(8), 0), \ + .int_gpio = GPIO_DT_SPEC_INST_GET(inst, int_gpios), \ + .clk_freq = DT_INST_PROP(inst, clock_frequency), \ + TCAN4X5X_RST_GPIO_INIT(inst) \ + TCAN4X5X_NWKRQ_GPIO_INIT(inst) \ + TCAN4X5X_WAKE_GPIO_INIT(inst) \ + }; \ + \ + static const struct can_mcan_config can_mcan_config_##inst = CAN_MCAN_DT_CONFIG_INST_GET( \ + inst, &tcan4x5x_config_##inst, &tcan4x5x_ops, &tcan4x5x_cbs_##inst); \ + \ + static struct tcan4x5x_data tcan4x5x_data_##inst; \ + \ + static struct can_mcan_data can_mcan_data_##inst = \ + CAN_MCAN_DATA_INITIALIZER(&tcan4x5x_data_##inst); \ + \ + CAN_DEVICE_DT_INST_DEFINE(inst, tcan4x5x_init, NULL, &can_mcan_data_##inst, \ + &can_mcan_config_##inst, POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ + &tcan4x5x_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(TCAN4X5X_INIT) diff --git a/drivers/charger/CMakeLists.txt b/drivers/charger/CMakeLists.txt new file mode 100644 index 00000000000..ce70f0590c6 --- /dev/null +++ b/drivers/charger/CMakeLists.txt @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/charger.h) + +zephyr_library_sources_ifdef(CONFIG_CHARGER_BQ24190 charger_bq24190.c) +zephyr_library_sources_ifdef(CONFIG_CHARGER_MAX20335 charger_max20335.c) +zephyr_library_sources_ifdef(CONFIG_SBS_CHARGER sbs_charger.c) +zephyr_library_sources_ifdef(CONFIG_USERSPACE charger_handlers.c) +zephyr_library_sources_ifdef(CONFIG_EMUL_SBS_CHARGER emul_sbs_charger.c) diff --git a/drivers/charger/Kconfig b/drivers/charger/Kconfig new file mode 100644 index 00000000000..9c7873168a5 --- /dev/null +++ b/drivers/charger/Kconfig @@ -0,0 +1,26 @@ +# Copyright 2023 Cirrus Logic, Inc. +# +# SPDX-License-Identifier: Apache-2.0 + +menuconfig CHARGER + bool "Battery charger drivers" + help + Enable battery charger driver configuration. + +if CHARGER + +module = CHARGER +module-str = charger +source "subsys/logging/Kconfig.template.log_config" + +config CHARGER_INIT_PRIORITY + int "Battery charger init priority" + default 90 + help + Battery charger initialization priority. + +source "drivers/charger/Kconfig.sbs_charger" +source "drivers/charger/Kconfig.bq24190" +source "drivers/charger/Kconfig.max20335" + +endif # CHARGER diff --git a/drivers/charger/Kconfig.bq24190 b/drivers/charger/Kconfig.bq24190 new file mode 100644 index 00000000000..be3e29727a2 --- /dev/null +++ b/drivers/charger/Kconfig.bq24190 @@ -0,0 +1,10 @@ +# Copyright 2023 Cirrus Logic, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config CHARGER_BQ24190 + bool "BQ24190 Battery Charger" + default y + depends on DT_HAS_TI_BQ24190_ENABLED + select I2C + help + Enable I2C-based driver for the TI BQ24190 Battery Charger. diff --git a/drivers/charger/Kconfig.max20335 b/drivers/charger/Kconfig.max20335 new file mode 100644 index 00000000000..7104e5daab6 --- /dev/null +++ b/drivers/charger/Kconfig.max20335 @@ -0,0 +1,11 @@ +# Copyright 2023 Grinn +# SPDX-License-Identifier: Apache-2.0 + +config CHARGER_MAX20335 + bool "MAX20335 battery charger driver" + default y + depends on DT_HAS_MAXIM_MAX20335_CHARGER_ENABLED + select I2C + select MFD + help + Enable the MAX20335 battery charger driver. diff --git a/drivers/charger/Kconfig.sbs_charger b/drivers/charger/Kconfig.sbs_charger new file mode 100644 index 00000000000..4c59c95a9e5 --- /dev/null +++ b/drivers/charger/Kconfig.sbs_charger @@ -0,0 +1,19 @@ +# Copyright 2023 Cirrus Logic, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config SBS_CHARGER + bool "Smart Battery Charger" + default y + depends on DT_HAS_SBS_SBS_CHARGER_ENABLED + select I2C + help + Enable I2C-based/SMBus-based driver for a Smart Battery Charger. + +config EMUL_SBS_CHARGER + bool "Emulate an SBS 1.1 compliant smart battery charger" + default y + depends on EMUL + depends on SBS_CHARGER + help + It provides reading which follow a simple sequence, thus allowing + test code to check that things are working as expected. diff --git a/drivers/charger/bq24190.h b/drivers/charger/bq24190.h new file mode 100644 index 00000000000..06d5d3ba299 --- /dev/null +++ b/drivers/charger/bq24190.h @@ -0,0 +1,167 @@ +/* + * Copyright 2023 Cirrus Logic, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_CHARGER_BQ24190_H_ +#define ZEPHYR_DRIVERS_CHARGER_BQ24190_H_ + +/* Input Source Control */ +#define BQ24190_REG_ISC 0x00 +#define BQ24190_REG_ISC_EN_HIZ_MASK BIT(7) +#define BQ24190_REG_ISC_EN_HIZ_SHIFT 7 +#define BQ24190_REG_ISC_VINDPM_MASK GENMASK(6, 3) +#define BQ24190_REG_ISC_VINDPM_SHIFT 3 +#define BQ24190_REG_ISC_IINLIM_MASK GENMASK(2, 0) + +/* Power-On Configuration */ +#define BQ24190_REG_POC 0x01 +#define BQ24190_REG_POC_RESET_MASK BIT(7) +#define BQ24190_REG_POC_RESET_SHIFT 7 +#define BQ24190_RESET_MAX_TRIES 100 +#define BQ24190_REG_POC_WDT_RESET_MASK BIT(6) +#define BQ24190_REG_POC_WDT_RESET_SHIFT 6 +#define BQ24190_REG_POC_CHG_CONFIG_MASK GENMASK(5, 4) +#define BQ24190_REG_POC_CHG_CONFIG_SHIFT 4 +#define BQ24190_REG_POC_CHG_CONFIG_DISABLE 0x0 +#define BQ24190_REG_POC_CHG_CONFIG_CHARGE 0x1 +#define BQ24190_REG_POC_CHG_CONFIG_OTG 0x2 +#define BQ24190_REG_POC_CHG_CONFIG_OTG_ALT 0x3 +#define BQ24190_REG_POC_SYS_MIN_MASK GENMASK(3, 1) +#define BQ24190_REG_POC_SYS_MIN_SHIFT 1 +#define BQ24190_REG_POC_SYS_MIN_MIN_UV 3000000 +#define BQ24190_REG_POC_SYS_MIN_MAX_UV 3700000 +#define BQ24190_REG_POC_BOOST_LIM_MASK BIT(0) +#define BQ24190_REG_POC_BOOST_LIM_SHIFT 0 + +/* Charge Current Control */ +#define BQ24190_REG_CCC 0x02 +#define BQ24190_REG_CCC_ICHG_MASK GENMASK(7, 2) +#define BQ24190_REG_CCC_ICHG_SHIFT 2 +#define BQ24190_REG_CCC_ICHG_STEP_UA 64000 +#define BQ24190_REG_CCC_ICHG_OFFSET_UA 512000 +#define BQ24190_REG_CCC_ICHG_MIN_UA BQ24190_REG_CCC_ICHG_OFFSET_UA +#define BQ24190_REG_CCC_ICHG_MAX_UA 4544000 +#define BQ24190_REG_CCC_FORCE_20PCT_MASK BIT(0) +#define BQ24190_REG_CCC_FORCE_20PCT_SHIFT 0 + +/* Pre-charge/Termination Current Cntl */ +#define BQ24190_REG_PCTCC 0x03 +#define BQ24190_REG_PCTCC_IPRECHG_MASK GENMASK(7, 4) +#define BQ24190_REG_PCTCC_IPRECHG_SHIFT 4 +#define BQ24190_REG_PCTCC_IPRECHG_STEP_UA 128000 +#define BQ24190_REG_PCTCC_IPRECHG_OFFSET_UA 128000 +#define BQ24190_REG_PCTCC_IPRECHG_MIN_UA BQ24190_REG_PCTCC_IPRECHG_OFFSET_UA +#define BQ24190_REG_PCTCC_IPRECHG_MAX_UA 2048000 +#define BQ24190_REG_PCTCC_ITERM_MASK GENMASK(3, 0) +#define BQ24190_REG_PCTCC_ITERM_SHIFT 0 +#define BQ24190_REG_PCTCC_ITERM_STEP_UA 128000 +#define BQ24190_REG_PCTCC_ITERM_OFFSET_UA 128000 +#define BQ24190_REG_PCTCC_ITERM_MIN_UA BQ24190_REG_PCTCC_ITERM_OFFSET_UA +#define BQ24190_REG_PCTCC_ITERM_MAX_UA 2048000 + +/* Charge Voltage Control */ +#define BQ24190_REG_CVC 0x04 +#define BQ24190_REG_CVC_VREG_MASK GENMASK(7, 2) +#define BQ24190_REG_CVC_VREG_SHIFT 2 +#define BQ24190_REG_CVC_VREG_STEP_UV 16000 +#define BQ24190_REG_CVC_VREG_OFFSET_UV 3504000 +#define BQ24190_REG_CVC_VREG_MIN_UV BQ24190_REG_CVC_VREG_OFFSET_UV +#define BQ24190_REG_CVC_VREG_MAX_UV 4400000 +#define BQ24190_REG_CVC_BATLOWV_MASK BIT(1) +#define BQ24190_REG_CVC_BATLOWV_SHIFT 1 +#define BQ24190_REG_CVC_VRECHG_MASK BIT(0) +#define BQ24190_REG_CVC_VRECHG_SHIFT 0 + +/* Charge Term/Timer Control */ +#define BQ24190_REG_CTTC 0x05 +#define BQ24190_REG_CTTC_EN_TERM_MASK BIT(7) +#define BQ24190_REG_CTTC_EN_TERM_SHIFT 7 +#define BQ24190_REG_CTTC_TERM_STAT_MASK BIT(6) +#define BQ24190_REG_CTTC_TERM_STAT_SHIFT 6 +#define BQ24190_REG_CTTC_WATCHDOG_MASK GENMASK(5, 4) +#define BQ24190_REG_CTTC_WATCHDOG_SHIFT 4 +#define BQ24190_REG_CTTC_EN_TIMER_MASK BIT(3) +#define BQ24190_REG_CTTC_EN_TIMER_SHIFT 3 +#define BQ24190_REG_CTTC_CHG_TIMER_MASK GENMASK(2, 1) +#define BQ24190_REG_CTTC_CHG_TIMER_SHIFT 1 +#define BQ24190_REG_CTTC_JEITA_ISET_MASK BIT(0) +#define BQ24190_REG_CTTC_JEITA_ISET_SHIFT 0 + +/* IR Comp/Thermal Regulation Control */ +#define BQ24190_REG_ICTRC 0x06 +#define BQ24190_REG_ICTRC_BAT_COMP_MASK GENMASK(7, 5) +#define BQ24190_REG_ICTRC_BAT_COMP_SHIFT 5 +#define BQ24190_REG_ICTRC_VCLAMP_MASK GENMASK(4, 2) +#define BQ24190_REG_ICTRC_VCLAMP_SHIFT 2 +#define BQ24190_REG_ICTRC_TREG_MASK GENMASK(1, 0) +#define BQ24190_REG_ICTRC_TREG_SHIFT 0 + +/* Misc. Operation Control */ +#define BQ24190_REG_MOC 0x07 +#define BQ24190_REG_MOC_DPDM_EN_MASK BIT(7) +#define BQ24190_REG_MOC_DPDM_EN_SHIFT 7 +#define BQ24190_REG_MOC_TMR2X_EN_MASK BIT(6) +#define BQ24190_REG_MOC_TMR2X_EN_SHIFT 6 +#define BQ24190_REG_MOC_BATFET_DISABLE_MASK BIT(5) +#define BQ24190_REG_MOC_BATFET_DISABLE_SHIFT 5 +#define BQ24190_REG_MOC_JEITA_VSET_MASK BIT(4) +#define BQ24190_REG_MOC_JEITA_VSET_SHIFT 4 +#define BQ24190_REG_MOC_INT_MASK_MASK GENMASK(1, 0) +#define BQ24190_REG_MOC_INT_MASK_SHIFT 0 + +/* System Status */ +#define BQ24190_REG_SS 0x08 +#define BQ24190_REG_SS_VBUS_STAT_MASK GENMASK(7, 6) +#define BQ24190_REG_SS_VBUS_STAT_SHIFT 6 +#define BQ24190_REG_SS_CHRG_STAT_MASK GENMASK(5, 4) +#define BQ24190_REG_SS_CHRG_STAT_SHIFT 4 +#define BQ24190_CHRG_STAT_NOT_CHRGING 0x0 +#define BQ24190_CHRG_STAT_PRECHRG 0x1 +#define BQ24190_CHRG_STAT_FAST_CHRG 0x2 +#define BQ24190_CHRG_STAT_CHRG_TERM 0x3 +#define BQ24190_REG_SS_DPM_STAT_MASK BIT(3) +#define BQ24190_REG_SS_DPM_STAT_SHIFT 3 +#define BQ24190_REG_SS_PG_STAT_MASK BIT(2) +#define BQ24190_REG_SS_PG_STAT_SHIFT 2 +#define BQ24190_REG_SS_THERM_STAT_MASK BIT(1) +#define BQ24190_REG_SS_THERM_STAT_SHIFT 1 +#define BQ24190_REG_SS_VSYS_STAT_MASK BIT(0) +#define BQ24190_REG_SS_VSYS_STAT_SHIFT 0 + +/* Fault */ +#define BQ24190_REG_F 0x09 +#define BQ24190_REG_F_WATCHDOG_FAULT_MASK BIT(7) +#define BQ24190_REG_F_WATCHDOG_FAULT_SHIFT 7 +#define BQ24190_REG_F_BOOST_FAULT_MASK BIT(6) +#define BQ24190_REG_F_BOOST_FAULT_SHIFT 6 +#define BQ24190_REG_F_CHRG_FAULT_MASK GENMASK(5, 4) +#define BQ24190_REG_F_CHRG_FAULT_SHIFT 4 +#define BQ24190_CHRG_FAULT_INPUT_FAULT 0x1 +#define BQ24190_CHRG_FAULT_TSHUT 0x2 +#define BQ24190_CHRG_SAFETY_TIMER 0x3 +#define BQ24190_REG_F_BAT_FAULT_MASK BIT(3) +#define BQ24190_REG_F_BAT_FAULT_SHIFT 3 +#define BQ24190_REG_F_NTC_FAULT_MASK GENMASK(2, 0) +#define BQ24190_REG_F_NTC_FAULT_SHIFT 0 +#define BQ24190_NTC_FAULT_TS1_COLD 0x1 +#define BQ24190_NTC_FAULT_TS1_HOT 0x2 +#define BQ24190_NTC_FAULT_TS2_COLD 0x3 +#define BQ24190_NTC_FAULT_TS2_HOT 0x4 +#define BQ24190_NTC_FAULT_TS1_TS2_COLD 0x5 +#define BQ24190_NTC_FAULT_TS1_TS2_HOT 0x6 + +/* Vendor/Part/Revision Status */ +#define BQ24190_REG_VPRS 0x0A +#define BQ24190_REG_VPRS_PN_MASK GENMASK(5, 3) +#define BQ24190_REG_VPRS_PN_SHIFT 3 +#define BQ24190_REG_VPRS_PN_24190 0x4 +#define BQ24190_REG_VPRS_PN_24192 0x5 /* Also 24193, 24196 */ +#define BQ24190_REG_VPRS_PN_24192I 0x3 +#define BQ24190_REG_VPRS_TS_PROFILE_MASK BIT(2) +#define BQ24190_REG_VPRS_TS_PROFILE_SHIFT 2 +#define BQ24190_REG_VPRS_DEV_REG_MASK GENMASK(1, 0) +#define BQ24190_REG_VPRS_DEV_REG_SHIFT 0 + +#endif diff --git a/drivers/charger/charger_bq24190.c b/drivers/charger/charger_bq24190.c new file mode 100644 index 00000000000..0661bd92796 --- /dev/null +++ b/drivers/charger/charger_bq24190.c @@ -0,0 +1,493 @@ +/* + * Copyright 2023 Cirrus Logic, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ti_bq24190 + +#include + +#include "bq24190.h" + +#include "zephyr/device.h" +#include "zephyr/drivers/charger.h" +#include "zephyr/drivers/i2c.h" +#include "zephyr/kernel.h" +#include "zephyr/sys/util.h" +#include "zephyr/logging/log.h" +#include + +LOG_MODULE_REGISTER(ti_bq24190); + +struct bq24190_config { + struct i2c_dt_spec i2c; + struct gpio_dt_spec ce_gpio; +}; + +struct bq24190_data { + uint8_t ss_reg; + unsigned int ichg_ua; + unsigned int vreg_uv; + enum charger_status state; + enum charger_online online; +}; + +static int bq24190_register_reset(const struct device *dev) +{ + const struct bq24190_config *const config = dev->config; + int ret, limit = BQ24190_RESET_MAX_TRIES; + uint8_t val; + + ret = i2c_reg_update_byte_dt(&config->i2c, BQ24190_REG_POC, BQ24190_REG_POC_RESET_MASK, + BQ24190_REG_POC_RESET_MASK); + if (ret) { + return ret; + } + + /* + * No explicit reset timing characteristcs are provided in the datasheet. + * Instead, poll every 100µs for 100 attempts to see if the reset request + * bit has cleared. + */ + do { + ret = i2c_reg_read_byte_dt(&config->i2c, BQ24190_REG_POC, &val); + if (ret) { + return ret; + } + + if (!(val & BQ24190_REG_POC_RESET_MASK)) { + return 0; + } + + k_usleep(100); + } while (--limit); + + return -EIO; +} + +static int bq24190_charger_get_charge_type(const struct device *dev, + enum charger_charge_type *charge_type) +{ + const struct bq24190_config *const config = dev->config; + uint8_t v; + int ret; + + *charge_type = CHARGER_CHARGE_TYPE_UNKNOWN; + + ret = i2c_reg_read_byte_dt(&config->i2c, BQ24190_REG_POC, &v); + if (ret) { + return ret; + } + + v = FIELD_GET(BQ24190_REG_POC_CHG_CONFIG_MASK, v); + + if (!v) { + *charge_type = CHARGER_CHARGE_TYPE_NONE; + } else { + ret = i2c_reg_read_byte_dt(&config->i2c, BQ24190_REG_CCC, &v); + if (ret) { + return ret; + } + + v = FIELD_GET(BQ24190_REG_CCC_FORCE_20PCT_MASK, v); + + if (v) { + *charge_type = CHARGER_CHARGE_TYPE_TRICKLE; + } else { + *charge_type = CHARGER_CHARGE_TYPE_FAST; + } + } + + return 0; +} + +static int bq24190_charger_get_health(const struct device *dev, enum charger_health *health) +{ + const struct bq24190_config *const config = dev->config; + uint8_t v; + int ret; + + ret = i2c_reg_read_byte_dt(&config->i2c, BQ24190_REG_F, &v); + if (ret) { + return ret; + } + + if (v & BQ24190_REG_F_NTC_FAULT_MASK) { + switch (v >> BQ24190_REG_F_NTC_FAULT_SHIFT & 0x7) { + case BQ24190_NTC_FAULT_TS1_COLD: + case BQ24190_NTC_FAULT_TS2_COLD: + case BQ24190_NTC_FAULT_TS1_TS2_COLD: + *health = CHARGER_HEALTH_COLD; + break; + case BQ24190_NTC_FAULT_TS1_HOT: + case BQ24190_NTC_FAULT_TS2_HOT: + case BQ24190_NTC_FAULT_TS1_TS2_HOT: + *health = CHARGER_HEALTH_HOT; + break; + default: + *health = CHARGER_HEALTH_UNKNOWN; + } + } else if (v & BQ24190_REG_F_BAT_FAULT_MASK) { + *health = CHARGER_HEALTH_OVERVOLTAGE; + } else if (v & BQ24190_REG_F_CHRG_FAULT_MASK) { + switch (v >> BQ24190_REG_F_CHRG_FAULT_SHIFT & 0x3) { + case BQ24190_CHRG_FAULT_INPUT_FAULT: + /* + * This could be over-voltage or under-voltage + * and there's no way to tell which. Instead + * of looking foolish and returning 'OVERVOLTAGE' + * when its really under-voltage, just return + * 'UNSPEC_FAILURE'. + */ + *health = CHARGER_HEALTH_UNSPEC_FAILURE; + break; + case BQ24190_CHRG_FAULT_TSHUT: + *health = CHARGER_HEALTH_OVERHEAT; + break; + case BQ24190_CHRG_SAFETY_TIMER: + *health = CHARGER_HEALTH_SAFETY_TIMER_EXPIRE; + break; + default: /* prevent compiler warning */ + *health = CHARGER_HEALTH_UNKNOWN; + } + } else if (v & BQ24190_REG_F_BOOST_FAULT_MASK) { + /* + * This could be over-current or over-voltage but there's + * no way to tell which. Return 'OVERVOLTAGE' since there + * isn't an 'OVERCURRENT' value defined that we can return + * even if it was over-current. + */ + *health = CHARGER_HEALTH_OVERVOLTAGE; + } else { + *health = CHARGER_HEALTH_GOOD; + } + + return 0; +} + +static int bq24190_charger_get_online(const struct device *dev, enum charger_online *online) +{ + const struct bq24190_config *const config = dev->config; + uint8_t pg_stat, batfet_disable; + int ret; + + ret = i2c_reg_read_byte_dt(&config->i2c, BQ24190_REG_SS, &pg_stat); + if (ret) { + return ret; + } + + pg_stat = FIELD_GET(BQ24190_REG_SS_PG_STAT_MASK, pg_stat); + + ret = i2c_reg_read_byte_dt(&config->i2c, BQ24190_REG_MOC, &batfet_disable); + if (ret) { + return ret; + } + + batfet_disable = FIELD_GET(BQ24190_REG_MOC_BATFET_DISABLE_MASK, batfet_disable); + + if (pg_stat && !batfet_disable) { + *online = CHARGER_ONLINE_FIXED; + } else { + *online = CHARGER_ONLINE_OFFLINE; + } + + return 0; +} + +static int bq24190_charger_get_status(const struct device *dev, enum charger_status *status) +{ + const struct bq24190_config *const config = dev->config; + uint8_t ss_reg, chrg_fault; + int ret; + + ret = i2c_reg_read_byte_dt(&config->i2c, BQ24190_REG_F, &chrg_fault); + if (ret) { + return ret; + } + + chrg_fault = FIELD_GET(BQ24190_REG_F_CHRG_FAULT_MASK, chrg_fault); + + ret = i2c_reg_read_byte_dt(&config->i2c, BQ24190_REG_SS, &ss_reg); + if (ret) { + return ret; + } + + /* + * The battery must be discharging when any of these are true: + * - there is no good power source; + * - there is a charge fault. + * Could also be discharging when in "supplement mode" but + * there is no way to tell when its in that mode. + */ + if (!(ss_reg & BQ24190_REG_SS_PG_STAT_MASK) || chrg_fault) { + *status = CHARGER_STATUS_DISCHARGING; + } else { + ss_reg = FIELD_GET(BQ24190_REG_SS_CHRG_STAT_MASK, ss_reg); + + switch (ss_reg) { + case BQ24190_CHRG_STAT_NOT_CHRGING: + *status = CHARGER_STATUS_NOT_CHARGING; + break; + case BQ24190_CHRG_STAT_PRECHRG: + case BQ24190_CHRG_STAT_FAST_CHRG: + *status = CHARGER_STATUS_CHARGING; + break; + case BQ24190_CHRG_STAT_CHRG_TERM: + *status = CHARGER_STATUS_FULL; + break; + default: + return -EIO; + } + } + + return 0; +} + +static int bq24190_charger_get_constant_charge_current(const struct device *dev, + uint32_t *current_ua) +{ + const struct bq24190_config *const config = dev->config; + bool frc_20pct; + uint8_t v; + int ret; + + ret = i2c_reg_read_byte_dt(&config->i2c, BQ24190_REG_CCC, &v); + if (ret) { + return ret; + } + + frc_20pct = v & BQ24190_REG_CCC_FORCE_20PCT_MASK; + + v = FIELD_GET(BQ24190_REG_CCC_ICHG_MASK, v); + + *current_ua = (v * BQ24190_REG_CCC_ICHG_STEP_UA) + BQ24190_REG_CCC_ICHG_OFFSET_UA; + + if (frc_20pct) { + *current_ua /= 5; + } + + return 0; +} + +static int bq24190_charger_get_precharge_current(const struct device *dev, uint32_t *current_ua) +{ + const struct bq24190_config *const config = dev->config; + bool frc_20pct; + uint8_t v; + int ret; + + ret = i2c_reg_read_byte_dt(&config->i2c, BQ24190_REG_CCC, &v); + if (ret) { + return ret; + } + + frc_20pct = v & BQ24190_REG_CCC_FORCE_20PCT_MASK; + + ret = i2c_reg_read_byte_dt(&config->i2c, BQ24190_REG_PCTCC, &v); + if (ret) { + return ret; + } + + v = FIELD_GET(BQ24190_REG_PCTCC_IPRECHG_MASK, v); + + *current_ua = (v * BQ24190_REG_PCTCC_IPRECHG_STEP_UA) + BQ24190_REG_PCTCC_IPRECHG_OFFSET_UA; + + if (frc_20pct) { + *current_ua /= 2; + } + + return 0; +} + +static int bq24190_charger_get_charge_term_current(const struct device *dev, uint32_t *current_ua) +{ + const struct bq24190_config *const config = dev->config; + uint8_t v; + int ret; + + ret = i2c_reg_read_byte_dt(&config->i2c, BQ24190_REG_PCTCC, &v); + if (ret) { + return ret; + } + + v = FIELD_GET(BQ24190_REG_PCTCC_ITERM_MASK, v); + + *current_ua = (v * BQ24190_REG_PCTCC_ITERM_STEP_UA) + BQ24190_REG_PCTCC_ITERM_OFFSET_UA; + + return 0; +} + +static int bq24190_get_constant_charge_voltage(const struct device *dev, uint32_t *voltage_uv) +{ + const struct bq24190_config *const config = dev->config; + uint8_t v; + int ret; + + ret = i2c_reg_read_byte_dt(&config->i2c, BQ24190_REG_CVC, &v); + if (ret < 0) { + return ret; + } + + v = FIELD_GET(BQ24190_REG_CVC_VREG_MASK, v); + + *voltage_uv = (v * BQ24190_REG_CVC_VREG_STEP_UV) + BQ24190_REG_CVC_VREG_OFFSET_UV; + + return 0; +} + +static int bq24190_set_constant_charge_current(const struct device *dev, uint32_t current_ua) +{ + const struct bq24190_config *const config = dev->config; + uint8_t v; + int ret; + + ret = i2c_reg_read_byte_dt(&config->i2c, BQ24190_REG_CCC, &v); + if (ret < 0) { + return ret; + } + + v &= BQ24190_REG_CCC_FORCE_20PCT_MASK; + + if (v) { + current_ua *= 5; + } + + current_ua = CLAMP(current_ua, BQ24190_REG_CCC_ICHG_MIN_UA, BQ24190_REG_CCC_ICHG_MAX_UA); + + v = (current_ua - BQ24190_REG_CCC_ICHG_OFFSET_UA) / BQ24190_REG_CCC_ICHG_STEP_UA; + + v = FIELD_PREP(BQ24190_REG_CCC_ICHG_MASK, v); + + return i2c_reg_update_byte_dt(&config->i2c, BQ24190_REG_CCC, BQ24190_REG_CCC_ICHG_MASK, v); +} + +static int bq24190_set_constant_charge_voltage(const struct device *dev, uint32_t voltage_uv) +{ + const struct bq24190_config *const config = dev->config; + uint8_t v; + + voltage_uv = CLAMP(voltage_uv, BQ24190_REG_CVC_VREG_MIN_UV, BQ24190_REG_CVC_VREG_MAX_UV); + + v = (voltage_uv - BQ24190_REG_CVC_VREG_OFFSET_UV) / BQ24190_REG_CVC_VREG_STEP_UV; + + v = FIELD_PREP(BQ24190_REG_CVC_VREG_MASK, v); + + return i2c_reg_update_byte_dt(&config->i2c, BQ24190_REG_CVC, BQ24190_REG_CVC_VREG_MASK, v); +} + +static int bq24190_set_config(const struct device *dev) +{ + struct bq24190_data *data = dev->data; + union charger_propval val; + int ret; + + val.const_charge_current_ua = data->ichg_ua; + + ret = bq24190_set_constant_charge_current(dev, val.const_charge_current_ua); + if (ret < 0) { + return ret; + } + + val.const_charge_voltage_uv = data->vreg_uv; + + return bq24190_set_constant_charge_voltage(dev, val.const_charge_voltage_uv); +} + +static int bq24190_get_prop(const struct device *dev, charger_prop_t prop, + union charger_propval *val) +{ + switch (prop) { + case CHARGER_PROP_ONLINE: + return bq24190_charger_get_online(dev, &val->online); + case CHARGER_PROP_CHARGE_TYPE: + return bq24190_charger_get_charge_type(dev, &val->charge_type); + case CHARGER_PROP_HEALTH: + return bq24190_charger_get_health(dev, &val->health); + case CHARGER_PROP_STATUS: + return bq24190_charger_get_status(dev, &val->status); + case CHARGER_PROP_CONSTANT_CHARGE_CURRENT_UA: + return bq24190_charger_get_constant_charge_current(dev, + &val->const_charge_current_ua); + case CHARGER_PROP_CONSTANT_CHARGE_VOLTAGE_UV: + return bq24190_get_constant_charge_voltage(dev, &val->const_charge_voltage_uv); + case CHARGER_PROP_PRECHARGE_CURRENT_UA: + return bq24190_charger_get_precharge_current(dev, &val->precharge_current_ua); + case CHARGER_PROP_CHARGE_TERM_CURRENT_UA: + return bq24190_charger_get_charge_term_current(dev, &val->charge_term_current_ua); + default: + return -ENOTSUP; + } +} + +static int bq24190_set_prop(const struct device *dev, charger_prop_t prop, + const union charger_propval *val) +{ + switch (prop) { + case CHARGER_PROP_CONSTANT_CHARGE_CURRENT_UA: + return bq24190_set_constant_charge_current(dev, val->const_charge_current_ua); + case CHARGER_PROP_CONSTANT_CHARGE_VOLTAGE_UV: + return bq24190_set_constant_charge_voltage(dev, val->const_charge_voltage_uv); + default: + return -ENOTSUP; + } +} + +static int bq24190_init(const struct device *dev) +{ + const struct bq24190_config *const config = dev->config; + struct bq24190_data *data = dev->data; + uint8_t val; + int ret; + + ret = i2c_reg_read_byte_dt(&config->i2c, BQ24190_REG_VPRS, &val); + if (ret) { + return ret; + } + + val = FIELD_GET(BQ24190_REG_VPRS_PN_MASK, val); + + switch (val) { + case BQ24190_REG_VPRS_PN_24190: + case BQ24190_REG_VPRS_PN_24192: + case BQ24190_REG_VPRS_PN_24192I: + break; + default: + LOG_ERR("Error unknown model: 0x%02x\n", val); + return -ENODEV; + } + + ret = bq24190_register_reset(dev); + if (ret) { + return ret; + } + + ret = bq24190_set_config(dev); + if (ret) { + return ret; + } + + return i2c_reg_read_byte_dt(&config->i2c, BQ24190_REG_SS, &data->ss_reg); +} + +static const struct charger_driver_api bq24190_driver_api = { + .get_property = &bq24190_get_prop, + .set_property = &bq24190_set_prop, +}; + +#define BQ24190_INIT(inst) \ + \ + static const struct bq24190_config bq24190_config_##inst = { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + }; \ + \ + static struct bq24190_data bq24190_data_##inst = { \ + .ichg_ua = DT_INST_PROP(inst, constant_charge_current_max_microamp), \ + .vreg_uv = DT_INST_PROP(inst, constant_charge_voltage_max_microvolt), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, &bq24190_init, NULL, &bq24190_data_##inst, \ + &bq24190_config_##inst, POST_KERNEL, CONFIG_CHARGER_INIT_PRIORITY, \ + &bq24190_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(BQ24190_INIT) diff --git a/drivers/charger/charger_handlers.c b/drivers/charger/charger_handlers.c new file mode 100644 index 00000000000..417991f9f5f --- /dev/null +++ b/drivers/charger/charger_handlers.c @@ -0,0 +1,38 @@ +/* + * Copyright 2023 Cirrus Logic, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +static inline int z_vrfy_charger_get_prop(const struct device *dev, const charger_prop_t prop, + union charger_propval *val) +{ + union charger_propval k_val; + + K_OOPS(K_SYSCALL_DRIVER_CHARGER(dev, get_property)); + + int ret = z_impl_charger_get_prop(dev, prop, &k_val); + + K_OOPS(k_usermode_to_copy(val, &k_val, sizeof(union charger_propval))); + + return ret; +} + +#include + +static inline int z_vrfy_charger_set_prop(const struct device *dev, const charger_prop_t prop, + const union charger_propval *val) +{ + union charger_propval k_val; + + K_OOPS(K_SYSCALL_DRIVER_CHARGER(dev, set_property)); + + K_OOPS(k_usermode_from_copy(&k_val, val, sizeof(union charger_propval))); + + return z_impl_charger_set_prop(dev, prop, &k_val); +} + +#include diff --git a/drivers/charger/charger_max20335.c b/drivers/charger/charger_max20335.c new file mode 100644 index 00000000000..75eae16f888 --- /dev/null +++ b/drivers/charger/charger_max20335.c @@ -0,0 +1,287 @@ +/* + * Copyright 2023 Grinn + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT maxim_max20335_charger + +#include +#include +#include +#include +#include +#include + +#include "zephyr/logging/log.h" +LOG_MODULE_REGISTER(max20335_charger); + +#define MAX20335_REG_STATUS_A 0x02 +#define MAX20335_REG_ILIMCNTL 0x09 +#define MAX20335_REG_CHG_CNTL_A 0x0A +#define MAX20335_CHGCNTLA_BAT_REG_CFG_MASK GENMASK(4, 1) +#define MAX20335_ILIMCNTL_MASK GENMASK(1, 0) +#define MAX20335_STATUS_A_CHG_STAT_MASK GENMASK(2, 0) +#define MAX20335_CHRG_EN_MASK BIT(0) +#define MAX20335_CHRG_EN BIT(0) +#define MAX20335_REG_CVC_VREG_MIN_UV 4050000U +#define MAX20335_REG_CVC_VREG_STEP_UV 50000U +#define MAX20335_REG_CVC_VREG_MIN_IDX 0x0U +#define MAX20335_REG_CVC_VREG_MAX_IDX 0x0CU + +struct charger_max20335_config { + struct i2c_dt_spec bus; + uint32_t max_ichg_ua; + uint32_t max_vreg_uv; +}; + +enum { + MAX20335_CHARGER_OFF, + MAX20335_CHARGING_SUSPENDED_DUE_TO_TEMPERATURE, + MAX20335_PRE_CHARGE_IN_PROGRESS, + MAX20335_FAST_CHARGE_IN_PROGRESS_1, + MAX20335_FAST_CHARGE_IN_PROGRESS_2, + MAX20335_MAINTAIN_CHARGE_IN_PROGRESS, + MAX20335_MAIN_CHARGER_TIMER_DONE, + MAX20335_CHARGER_FAULT_CONDITION, +}; + +static const struct linear_range charger_uv_range = + LINEAR_RANGE_INIT(MAX20335_REG_CVC_VREG_MIN_UV, + MAX20335_REG_CVC_VREG_STEP_UV, + MAX20335_REG_CVC_VREG_MIN_IDX, + MAX20335_REG_CVC_VREG_MAX_IDX); + +static int max20335_get_status(const struct device *dev, enum charger_status *status) +{ + const struct charger_max20335_config *const config = dev->config; + uint8_t val; + int ret; + + ret = i2c_reg_read_byte_dt(&config->bus, MAX20335_REG_STATUS_A, &val); + if (ret) { + return ret; + } + + val = FIELD_GET(MAX20335_STATUS_A_CHG_STAT_MASK, val); + + switch (val) { + case MAX20335_CHARGER_OFF: + __fallthrough; + case MAX20335_CHARGING_SUSPENDED_DUE_TO_TEMPERATURE: + __fallthrough; + case MAX20335_CHARGER_FAULT_CONDITION: + *status = CHARGER_STATUS_NOT_CHARGING; + break; + case MAX20335_PRE_CHARGE_IN_PROGRESS: + __fallthrough; + case MAX20335_FAST_CHARGE_IN_PROGRESS_1: + __fallthrough; + case MAX20335_FAST_CHARGE_IN_PROGRESS_2: + __fallthrough; + case MAX20335_MAINTAIN_CHARGE_IN_PROGRESS: + *status = CHARGER_STATUS_CHARGING; + break; + case MAX20335_MAIN_CHARGER_TIMER_DONE: + *status = CHARGER_STATUS_FULL; + break; + default: + *status = CHARGER_STATUS_UNKNOWN; + break; + }; + + return 0; +} + +static int max20335_set_constant_charge_voltage(const struct device *dev, + uint32_t voltage_uv) +{ + const struct charger_max20335_config *const config = dev->config; + uint16_t idx; + uint8_t val; + int ret; + + if (voltage_uv > config->max_vreg_uv) { + LOG_WRN("Exceeded max constant charge voltage!"); + return -EINVAL; + } + + ret = linear_range_get_index(&charger_uv_range, voltage_uv, &idx); + if (ret == -EINVAL) { + return ret; + } + + val = FIELD_PREP(MAX20335_CHGCNTLA_BAT_REG_CFG_MASK, idx); + + return i2c_reg_update_byte_dt(&config->bus, + MAX20335_REG_CHG_CNTL_A, + MAX20335_CHGCNTLA_BAT_REG_CFG_MASK, + val); +} + +static int max20335_set_constant_charge_current(const struct device *dev, + uint32_t current_ua) +{ + const struct charger_max20335_config *const config = dev->config; + uint8_t val; + + if (current_ua > config->max_ichg_ua) { + LOG_WRN("Exceeded max constant charge current!"); + return -EINVAL; + } + + switch (current_ua) { + case 0: + val = 0x00; + break; + case 100000: + val = 0x01; + break; + case 500000: + val = 0x02; + break; + case 1000000: + val = 0x03; + break; + default: + return -ENOTSUP; + }; + + val = FIELD_PREP(MAX20335_ILIMCNTL_MASK, val); + + return i2c_reg_update_byte_dt(&config->bus, + MAX20335_REG_ILIMCNTL, + MAX20335_ILIMCNTL_MASK, + val); +} + +static int max20335_get_constant_charge_current(const struct device *dev, + uint32_t *current_ua) +{ + const struct charger_max20335_config *const config = dev->config; + uint8_t val; + int ret; + + ret = i2c_reg_read_byte_dt(&config->bus, MAX20335_REG_ILIMCNTL, &val); + if (ret) { + return ret; + } + + switch (val) { + case 0x00: + *current_ua = 0; + break; + case 0x01: + *current_ua = 100000; + break; + case 0x02: + *current_ua = 500000; + break; + case 0x03: + *current_ua = 1000000; + break; + default: + return -ENOTSUP; + }; + + return 0; +} + +static int max20335_get_constant_charge_voltage(const struct device *dev, + uint32_t *current_uv) +{ + const struct charger_max20335_config *const config = dev->config; + uint8_t val; + int ret; + + ret = i2c_reg_read_byte_dt(&config->bus, MAX20335_REG_CHG_CNTL_A, &val); + if (ret) { + return ret; + } + + val = FIELD_GET(MAX20335_CHGCNTLA_BAT_REG_CFG_MASK, val); + + return linear_range_get_value(&charger_uv_range, val, current_uv); +} + +static int max20335_set_enabled(const struct device *dev, bool enable) +{ + const struct charger_max20335_config *const config = dev->config; + + return i2c_reg_update_byte_dt(&config->bus, + MAX20335_REG_CHG_CNTL_A, + MAX20335_CHRG_EN_MASK, + enable ? MAX20335_CHRG_EN : 0); +} + +static int max20335_get_prop(const struct device *dev, charger_prop_t prop, + union charger_propval *val) +{ + switch (prop) { + case CHARGER_PROP_STATUS: + return max20335_get_status(dev, &val->status); + case CHARGER_PROP_CONSTANT_CHARGE_CURRENT_UA: + return max20335_get_constant_charge_current(dev, + &val->const_charge_current_ua); + case CHARGER_PROP_CONSTANT_CHARGE_VOLTAGE_UV: + return max20335_get_constant_charge_voltage(dev, + &val->const_charge_voltage_uv); + default: + return -ENOTSUP; + } +} + +static int max20335_set_prop(const struct device *dev, charger_prop_t prop, + const union charger_propval *val) +{ + switch (prop) { + case CHARGER_PROP_STATUS: + switch (val->status) { + case CHARGER_STATUS_CHARGING: + return max20335_set_enabled(dev, true); + case CHARGER_STATUS_NOT_CHARGING: + return max20335_set_enabled(dev, false); + default: + return -ENOTSUP; + } + case CHARGER_PROP_CONSTANT_CHARGE_CURRENT_UA: + return max20335_set_constant_charge_current(dev, + val->const_charge_current_ua); + case CHARGER_PROP_CONSTANT_CHARGE_VOLTAGE_UV: + return max20335_set_constant_charge_voltage(dev, + val->const_charge_voltage_uv); + default: + return -ENOTSUP; + } + +} + +static int max20335_init(const struct device *dev) +{ + const struct charger_max20335_config *config = dev->config; + + if (!i2c_is_ready_dt(&config->bus)) { + return -ENODEV; + } + + return 0; +} + +static const struct charger_driver_api max20335_driver_api = { + .get_property = max20335_get_prop, + .set_property = max20335_set_prop, +}; + +#define MAX20335_DEFINE(inst) \ + static const struct charger_max20335_config charger_max20335_config_##inst = { \ + .bus = I2C_DT_SPEC_GET(DT_INST_PARENT(inst)), \ + .max_ichg_ua = DT_INST_PROP(inst, constant_charge_current_max_microamp), \ + .max_vreg_uv = DT_INST_PROP(inst, constant_charge_voltage_max_microvolt), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, &max20335_init, NULL, NULL, \ + &charger_max20335_config_##inst, \ + POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, \ + &max20335_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(MAX20335_DEFINE) diff --git a/drivers/charger/emul_sbs_charger.c b/drivers/charger/emul_sbs_charger.c new file mode 100644 index 00000000000..34d432c8fbb --- /dev/null +++ b/drivers/charger/emul_sbs_charger.c @@ -0,0 +1,141 @@ +/* + * Copyright 2023 Cirrus Logic, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Emulator for SBS 1.1 compliant smart battery charger. + */ + +#define DT_DRV_COMPAT sbs_sbs_charger + +#include +#include +#include +#include +#include +#include + +#include "sbs_charger.h" + +LOG_MODULE_REGISTER(sbs_sbs_charger); + +/** Static configuration for the emulator */ +struct sbs_charger_emul_cfg { + /** I2C address of emulator */ + uint16_t addr; +}; + +static int emul_sbs_charger_reg_write(const struct emul *target, int reg, int val) +{ + LOG_INF("write %x = %x", reg, val); + switch (reg) { + default: + LOG_ERR("Unknown write %x", reg); + return -EIO; + } + + return 0; +} + +static int emul_sbs_charger_reg_read(const struct emul *target, int reg, int *val) +{ + switch (reg) { + case SBS_CHARGER_REG_SPEC_INFO: + case SBS_CHARGER_REG_CHARGER_MODE: + case SBS_CHARGER_REG_STATUS: + case SBS_CHARGER_REG_ALARM_WARNING: + /* Arbitrary stub value. */ + *val = 1; + break; + default: + LOG_ERR("Unknown register 0x%x read", reg); + return -EIO; + } + LOG_INF("read 0x%x = 0x%x", reg, *val); + + return 0; +} + +static int sbs_charger_emul_transfer_i2c(const struct emul *target, struct i2c_msg *msgs, + int num_msgs, int addr) +{ + /* Largely copied from emul_sbs_gauge.c */ + struct sbs_charger_emul_data *data; + unsigned int val; + int reg; + int rc; + + data = target->data; + + i2c_dump_msgs_rw(target->dev, msgs, num_msgs, addr, false); + switch (num_msgs) { + case 2: + if (msgs->flags & I2C_MSG_READ) { + LOG_ERR("Unexpected read"); + return -EIO; + } + if (msgs->len != 1) { + LOG_ERR("Unexpected msg0 length %d", msgs->len); + return -EIO; + } + reg = msgs->buf[0]; + + /* Now process the 'read' part of the message */ + msgs++; + if (msgs->flags & I2C_MSG_READ) { + switch (msgs->len - 1) { + case 1: + rc = emul_sbs_charger_reg_read(target, reg, &val); + if (rc) { + /* Return before writing bad value to message buffer */ + return rc; + } + + /* SBS uses SMBus, which sends data in little-endian format. */ + sys_put_le16(val, msgs->buf); + break; + default: + LOG_ERR("Unexpected msg1 length %d", msgs->len); + return -EIO; + } + } else { + /* We write a word (2 bytes by the SBS spec) */ + if (msgs->len != 2) { + LOG_ERR("Unexpected msg1 length %d", msgs->len); + } + uint16_t value = sys_get_le16(msgs->buf); + + rc = emul_sbs_charger_reg_write(target, reg, value); + } + break; + default: + LOG_ERR("Invalid number of messages: %d", num_msgs); + return -EIO; + } + + return rc; +} + +static const struct i2c_emul_api sbs_charger_emul_api_i2c = { + .transfer = sbs_charger_emul_transfer_i2c, +}; + +static int emul_sbs_sbs_charger_init(const struct emul *target, const struct device *parent) +{ + ARG_UNUSED(target); + ARG_UNUSED(parent); + + return 0; +} + +/* + * Main instantiation macro. SBS Charger Emulator only implemented for I2C + */ +#define SBS_CHARGER_EMUL(n) \ + static const struct sbs_charger_emul_cfg sbs_charger_emul_cfg_##n = { \ + .addr = DT_INST_REG_ADDR(n), \ + }; \ + EMUL_DT_INST_DEFINE(n, emul_sbs_sbs_charger_init, NULL, &sbs_charger_emul_cfg_##n, \ + &sbs_charger_emul_api_i2c, NULL) + +DT_INST_FOREACH_STATUS_OKAY(SBS_CHARGER_EMUL) diff --git a/drivers/charger/sbs_charger.c b/drivers/charger/sbs_charger.c new file mode 100644 index 00000000000..7cdc99b2a73 --- /dev/null +++ b/drivers/charger/sbs_charger.c @@ -0,0 +1,171 @@ +/* + * Copyright 2023 Cirrus Logic, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT sbs_sbs_charger + +#include +#include +#include +#include + +#include "sbs_charger.h" + +struct sbs_charger_config { + struct i2c_dt_spec i2c; +}; + +LOG_MODULE_REGISTER(sbs_charger); + +static int sbs_cmd_reg_read(const struct device *dev, uint8_t reg_addr, uint16_t *val) +{ + const struct sbs_charger_config *cfg; + uint8_t i2c_data[2]; + int status; + + cfg = dev->config; + status = i2c_burst_read_dt(&cfg->i2c, reg_addr, i2c_data, sizeof(i2c_data)); + if (status < 0) { + LOG_ERR("Unable to read register"); + return status; + } + + *val = sys_get_le16(i2c_data); + + return 0; +} + +static int sbs_cmd_reg_write(const struct device *dev, uint8_t reg_addr, uint16_t val) +{ + const struct sbs_charger_config *config = dev->config; + uint8_t buf[2]; + + sys_put_le16(val, buf); + + return i2c_burst_write_dt(&config->i2c, reg_addr, buf, sizeof(buf)); +} + +static int sbs_cmd_reg_update(const struct device *dev, uint8_t reg_addr, uint16_t mask, + uint16_t val) +{ + uint16_t old_val, new_val; + int ret; + + ret = sbs_cmd_reg_read(dev, SBS_CHARGER_REG_STATUS, &old_val); + if (ret < 0) { + return ret; + } + + new_val = (old_val & ~mask) | (val & mask); + if (new_val == old_val) { + return 0; + } + + return sbs_cmd_reg_write(dev, reg_addr, new_val); +} + +static int sbs_charger_get_prop(const struct device *dev, const charger_prop_t prop, + union charger_propval *val) +{ + uint16_t reg_val; + int ret; + + switch (prop) { + case CHARGER_PROP_ONLINE: + ret = sbs_cmd_reg_read(dev, SBS_CHARGER_REG_STATUS, ®_val); + if (ret < 0) { + return ret; + } + + if (reg_val & SBS_CHARGER_STATUS_AC_PRESENT) { + val->online = CHARGER_ONLINE_FIXED; + } else { + val->online = CHARGER_ONLINE_OFFLINE; + } + + return 0; + case CHARGER_PROP_PRESENT: + ret = sbs_cmd_reg_read(dev, SBS_CHARGER_REG_STATUS, ®_val); + if (ret < 0) { + return ret; + } + + if (reg_val & SBS_CHARGER_STATUS_BATTERY_PRESENT) { + val->present = true; + } else { + val->present = false; + } + + return 0; + case CHARGER_PROP_STATUS: + ret = sbs_cmd_reg_read(dev, SBS_CHARGER_REG_STATUS, ®_val); + if (ret < 0) { + return ret; + } + + if (!(reg_val & SBS_CHARGER_STATUS_BATTERY_PRESENT)) { + val->status = CHARGER_STATUS_NOT_CHARGING; + } else if (reg_val & SBS_CHARGER_STATUS_AC_PRESENT && + !(reg_val & SBS_CHARGER_STATUS_CHARGE_INHIBITED)) { + val->status = CHARGER_STATUS_CHARGING; + } else { + val->status = CHARGER_STATUS_DISCHARGING; + } + + return 0; + default: + return -ENOTSUP; + } +} + +static int sbs_charger_set_prop(const struct device *dev, const charger_prop_t prop, + const union charger_propval *val) +{ + uint16_t reg_val = 0; + + switch (prop) { + case CHARGER_PROP_STATUS: + if (val->status != CHARGER_STATUS_CHARGING) { + reg_val = SBS_CHARGER_MODE_INHIBIT_CHARGE; + } + return sbs_cmd_reg_update(dev, SBS_CHARGER_REG_CHARGER_MODE, + SBS_CHARGER_MODE_INHIBIT_CHARGE, reg_val); + default: + return -ENOTSUP; + } +} + +/** + * @brief initialize the charger + * + * @return 0 for success + */ +static int sbs_charger_init(const struct device *dev) +{ + const struct sbs_charger_config *cfg = dev->config; + + if (!i2c_is_ready_dt(&cfg->i2c)) { + LOG_ERR("Bus device is not ready"); + return -ENODEV; + } + + return 0; +} + +static const struct charger_driver_api sbs_charger_driver_api = { + .get_property = &sbs_charger_get_prop, + .set_property = &sbs_charger_set_prop, +}; + +#define SBS_CHARGER_INIT(inst) \ + \ + static const struct sbs_charger_config sbs_charger_config_##inst = { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, &sbs_charger_init, NULL, NULL, &sbs_charger_config_##inst, \ + POST_KERNEL, CONFIG_CHARGER_INIT_PRIORITY, &sbs_charger_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(SBS_CHARGER_INIT) diff --git a/drivers/charger/sbs_charger.h b/drivers/charger/sbs_charger.h new file mode 100644 index 00000000000..abaf08e25fc --- /dev/null +++ b/drivers/charger/sbs_charger.h @@ -0,0 +1,20 @@ +/* + * Copyright 2023 Cirrus Logic, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define SBS_CHARGER_REG_SPEC_INFO 0x11 +#define SBS_CHARGER_REG_CHARGER_MODE 0x12 +#define SBS_CHARGER_REG_STATUS 0x13 +#define SBS_CHARGER_REG_ALARM_WARNING 0x16 + +#define SBS_CHARGER_MODE_INHIBIT_CHARGE BIT(0) + +#define SBS_CHARGER_STATUS_CHARGE_INHIBITED BIT(0) +#define SBS_CHARGER_STATUS_RES_COLD BIT(9) +#define SBS_CHARGER_STATUS_RES_HOT BIT(10) +#define SBS_CHARGER_STATUS_BATTERY_PRESENT BIT(14) +#define SBS_CHARGER_STATUS_AC_PRESENT BIT(15) + +#define SBS_CHARGER_POLL_TIME 500 diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt index 8a8d7fbb61a..a1f553fc134 100644 --- a/drivers/clock_control/CMakeLists.txt +++ b/drivers/clock_control/CMakeLists.txt @@ -26,6 +26,9 @@ zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_SAM clock_cont zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_SMARTBOND clock_control_smartbond.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NUMAKER_SCC clock_control_numaker_scc.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NXP_S32 clock_control_nxp_s32.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_RA clock_control_ra.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_AMBIQ clock_control_ambiq.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_PWM clock_control_pwm.c) if(CONFIG_CLOCK_CONTROL_STM32_CUBE) diff --git a/drivers/clock_control/Kconfig b/drivers/clock_control/Kconfig index f4647930ae3..37cbb2e2895 100644 --- a/drivers/clock_control/Kconfig +++ b/drivers/clock_control/Kconfig @@ -80,4 +80,10 @@ source "drivers/clock_control/Kconfig.nxp_s32" source "drivers/clock_control/Kconfig.agilex5" +source "drivers/clock_control/Kconfig.ra" + +source "drivers/clock_control/Kconfig.ambiq" + +source "drivers/clock_control/Kconfig.pwm" + endif # CLOCK_CONTROL diff --git a/drivers/clock_control/Kconfig.ambiq b/drivers/clock_control/Kconfig.ambiq new file mode 100644 index 00000000000..ca0a4c1bce5 --- /dev/null +++ b/drivers/clock_control/Kconfig.ambiq @@ -0,0 +1,14 @@ +# Ambiq Clock Control Driver configuration options +# +# Copyright (c) 2023 Ambiq Micro Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +config CLOCK_CONTROL_AMBIQ + bool "AMBIQ clock control driver" + default y + depends on DT_HAS_AMBIQ_CLKCTRL_ENABLED + select AMBIQ_HAL + help + Enable driver for Ambiq clock control. diff --git a/drivers/clock_control/Kconfig.npcx b/drivers/clock_control/Kconfig.npcx index b4b91d5f8d3..76e5acf985a 100644 --- a/drivers/clock_control/Kconfig.npcx +++ b/drivers/clock_control/Kconfig.npcx @@ -18,3 +18,15 @@ config CLOCK_CONTROL_NPCX_EXTERNAL_SRC is generated by the on-chip Crystal Oscillator (XTOSC). This includes an on-chip oscillator, to which an external crystal and the related passive components are connected. + +config CLOCK_CONTROL_NPCX_SUPP_APB4 + bool "Indicates that the clock controller supports APB4 bus" + default y if !SOC_SERIES_NPCX7 + help + Selected if NPCX series supports APB4 bus. + +config CLOCK_CONTROL_NPCX_SUPP_FIU1 + bool "Indicates that the clock controller supports FIU1 bus" + default y if SOC_SERIES_NPCX4 + help + Selected if NPCX series supports FIU1 bus. diff --git a/drivers/clock_control/Kconfig.nrf b/drivers/clock_control/Kconfig.nrf index 64e31b1ad16..453aac5b5d0 100644 --- a/drivers/clock_control/Kconfig.nrf +++ b/drivers/clock_control/Kconfig.nrf @@ -25,7 +25,6 @@ if CLOCK_CONTROL_NRF config CLOCK_CONTROL_NRF_SHELL bool "Shell commands" depends on SHELL - default y if SHELL choice CLOCK_CONTROL_NRF_SOURCE prompt "32KHz clock source" diff --git a/drivers/clock_control/Kconfig.pwm b/drivers/clock_control/Kconfig.pwm new file mode 100644 index 00000000000..eed5a91c17b --- /dev/null +++ b/drivers/clock_control/Kconfig.pwm @@ -0,0 +1,18 @@ +# Copyright (c) 2023 Andriy Gelman +# SPDX-License-Identifier: Apache-2.0 + +config CLOCK_CONTROL_PWM + bool "Generic PWM clock" + default y + depends on DT_HAS_PWM_CLOCK_ENABLED + select PWM + help + Enable generic PWM clock. + +config CLOCK_CONTROL_PWM_INIT_PRIORITY + int "Initialization priority of the pwm clock device" + default 51 + depends on CLOCK_CONTROL_PWM + help + Initialization priority of the PWM clock device. Must be + lower priority than PWM. diff --git a/drivers/clock_control/Kconfig.ra b/drivers/clock_control/Kconfig.ra new file mode 100644 index 00000000000..2b4aea0fb81 --- /dev/null +++ b/drivers/clock_control/Kconfig.ra @@ -0,0 +1,9 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +config CLOCK_CONTROL_RA + bool "Renesas RA series clock generation circuit driver" + default y + depends on DT_HAS_RENESAS_RA_CLOCK_GENERATION_CIRCUIT_ENABLED + help + Enable Renesas RA series clock generation circuit driver. diff --git a/drivers/clock_control/clock_control_ambiq.c b/drivers/clock_control/clock_control_ambiq.c new file mode 100644 index 00000000000..a64030c2a2d --- /dev/null +++ b/drivers/clock_control/clock_control_ambiq.c @@ -0,0 +1,138 @@ +/* + * Copyright 2023 Ambiq Micro Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ambiq_clkctrl + +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(clock_control_ambiq, CONFIG_CLOCK_CONTROL_LOG_LEVEL); + +struct ambiq_clock_config { + uint32_t clock_freq; + const struct pinctrl_dev_config *pcfg; +}; + +static int ambiq_clock_on(const struct device *dev, clock_control_subsys_t sub_system) +{ + ARG_UNUSED(dev); + + int ret; + uint32_t clock_name = (uint32_t)sub_system; + am_hal_mcuctrl_control_arg_t arg = { + .b_arg_hfxtal_in_use = true, + .b_arg_apply_ext_source = false, + .b_arg_force_update = false, + }; + + if (clock_name >= CLOCK_CONTROL_AMBIQ_TYPE_MAX) { + return -EINVAL; + } + + switch (clock_name) { + case CLOCK_CONTROL_AMBIQ_TYPE_HFXTAL_BLE: + arg.ui32_arg_hfxtal_user_mask = BIT(AM_HAL_HFXTAL_BLE_CONTROLLER_EN); + arg.b_arg_enable_HfXtalClockout = true; + ret = am_hal_mcuctrl_control(AM_HAL_MCUCTRL_CONTROL_EXTCLK32M_KICK_START, &arg); + break; + case CLOCK_CONTROL_AMBIQ_TYPE_LFXTAL: + ret = am_hal_mcuctrl_control(AM_HAL_MCUCTRL_CONTROL_EXTCLK32K_ENABLE, 0); + default: + ret = -ENOTSUP; + break; + } + + return ret; +} + +static int ambiq_clock_off(const struct device *dev, clock_control_subsys_t sub_system) +{ + ARG_UNUSED(dev); + + int ret; + uint32_t clock_name = (uint32_t)sub_system; + am_hal_mcuctrl_control_arg_t arg = { + .b_arg_hfxtal_in_use = true, + .b_arg_apply_ext_source = false, + .b_arg_force_update = false, + }; + + if (clock_name >= CLOCK_CONTROL_AMBIQ_TYPE_MAX) { + return -EINVAL; + } + + switch (clock_name) { + case CLOCK_CONTROL_AMBIQ_TYPE_HFXTAL_BLE: + arg.ui32_arg_hfxtal_user_mask = BIT(AM_HAL_HFXTAL_BLE_CONTROLLER_EN); + arg.b_arg_enable_HfXtalClockout = true; + ret = am_hal_mcuctrl_control(AM_HAL_MCUCTRL_CONTROL_EXTCLK32M_DISABLE, &arg); + break; + case CLOCK_CONTROL_AMBIQ_TYPE_LFXTAL: + ret = am_hal_mcuctrl_control(AM_HAL_MCUCTRL_CONTROL_EXTCLK32K_DISABLE, 0); + break; + default: + ret = -ENOTSUP; + break; + } + + return ret; +} + +static inline int ambiq_clock_get_rate(const struct device *dev, clock_control_subsys_t sub_system, + uint32_t *rate) +{ + ARG_UNUSED(sub_system); + + const struct ambiq_clock_config *cfg = dev->config; + *rate = cfg->clock_freq; + + return 0; +} + +static inline int ambiq_clock_configure(const struct device *dev, clock_control_subsys_t sub_system, + void *data) +{ + ARG_UNUSED(sub_system); + ARG_UNUSED(data); + + const struct ambiq_clock_config *cfg = dev->config; + int ret; + + ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); + + return ret; +} + +static int ambiq_clock_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + /* Nothing to do.*/ + return 0; +} + +static const struct clock_control_driver_api ambiq_clock_driver_api = { + .on = ambiq_clock_on, + .off = ambiq_clock_off, + .get_rate = ambiq_clock_get_rate, + .configure = ambiq_clock_configure, +}; + +#define AMBIQ_CLOCK_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + static const struct ambiq_clock_config ambiq_clock_config##n = { \ + .clock_freq = DT_INST_PROP(n, clock_frequency), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n)}; \ + DEVICE_DT_INST_DEFINE(n, ambiq_clock_init, NULL, NULL, &ambiq_clock_config##n, \ + POST_KERNEL, CONFIG_CLOCK_CONTROL_INIT_PRIORITY, \ + &ambiq_clock_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(AMBIQ_CLOCK_INIT) diff --git a/drivers/clock_control/clock_control_esp32.c b/drivers/clock_control/clock_control_esp32.c index ea8836d8d75..fba7091b871 100644 --- a/drivers/clock_control/clock_control_esp32.c +++ b/drivers/clock_control/clock_control_esp32.c @@ -328,6 +328,11 @@ static void esp32_clock_perip_init(void) #if defined(CONFIG_SOC_SERIES_ESP32S3) static void esp32_clock_perip_init(void) { +#if defined(CONFIG_SOC_ESP32S3_APPCPU) + /* skip APPCPU configuration */ + return; +#endif + uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0; uint32_t common_perip_clk1 = 0; diff --git a/drivers/clock_control/clock_control_mcux_ccm.c b/drivers/clock_control/clock_control_mcux_ccm.c index d836bb2c260..ab90602d2a4 100644 --- a/drivers/clock_control/clock_control_mcux_ccm.c +++ b/drivers/clock_control/clock_control_mcux_ccm.c @@ -6,11 +6,16 @@ #define DT_DRV_COMPAT nxp_imx_ccm #include +#include #include #include #include #include +#if defined(CONFIG_SOC_MIMX8QM_ADSP) || defined(CONFIG_SOC_MIMX8QXP_ADSP) +#include
    +#endif + #define LOG_LEVEL CONFIG_CLOCK_CONTROL_LOG_LEVEL #include LOG_MODULE_REGISTER(clock_control); @@ -38,18 +43,34 @@ static const clock_ip_name_t uart_clocks[] = { kCLOCK_Uart4, }; #endif -#if defined(CONFIG_UART_MCUX_LPUART) && defined(CONFIG_SOC_MIMX93_A55) -static const clock_root_t lpuart_clk_root[] = { - kCLOCK_Root_Lpuart1, - kCLOCK_Root_Lpuart2, - kCLOCK_Root_Lpuart3, - kCLOCK_Root_Lpuart4, - kCLOCK_Root_Lpuart5, - kCLOCK_Root_Lpuart6, - kCLOCK_Root_Lpuart7, - kCLOCK_Root_Lpuart8, + +#ifdef CONFIG_UART_MCUX_LPUART + +#ifdef CONFIG_SOC_MIMX8QM_ADSP +static const clock_ip_name_t lpuart_clocks[] = { + kCLOCK_DMA_Lpuart0, + kCLOCK_DMA_Lpuart1, + kCLOCK_DMA_Lpuart2, + kCLOCK_DMA_Lpuart3, + kCLOCK_DMA_Lpuart4, }; -#endif + +static const uint32_t lpuart_rate = MHZ(80); +#endif /* CONFIG_SOC_MIMX8QM_ADSP */ + +#ifdef CONFIG_SOC_MIMX8QXP_ADSP +static const clock_ip_name_t lpuart_clocks[] = { + kCLOCK_DMA_Lpuart0, + kCLOCK_DMA_Lpuart1, + kCLOCK_DMA_Lpuart2, + kCLOCK_DMA_Lpuart3, +}; + +static const uint32_t lpuart_rate = MHZ(80); +#endif /* CONFIG_SOC_MIMX8QXP_ADSP */ + +#endif /* CONFIG_UART_MCUX_LPUART */ + static int mcux_ccm_on(const struct device *dev, clock_control_subsys_t sub_system) @@ -66,6 +87,25 @@ static int mcux_ccm_on(const struct device *dev, CLOCK_EnableClock(uart_clocks[instance]); return 0; #endif + +#if defined(CONFIG_UART_MCUX_LPUART) && defined(CONFIG_SOC_MIMX8QM_ADSP) + case IMX_CCM_LPUART1_CLK: + case IMX_CCM_LPUART2_CLK: + case IMX_CCM_LPUART3_CLK: + case IMX_CCM_LPUART4_CLK: + case IMX_CCM_LPUART5_CLK: + CLOCK_EnableClock(lpuart_clocks[instance]); + return 0; +#endif + +#if defined(CONFIG_UART_MCUX_LPUART) && defined(CONFIG_SOC_MIMX8QXP_ADSP) + case IMX_CCM_LPUART1_CLK: + case IMX_CCM_LPUART2_CLK: + case IMX_CCM_LPUART3_CLK: + case IMX_CCM_LPUART4_CLK: + CLOCK_EnableClock(lpuart_clocks[instance]); + return 0; +#endif default: (void)instance; return 0; @@ -127,27 +167,29 @@ static int mcux_ccm_get_subsys_rate(const struct device *dev, #endif #ifdef CONFIG_UART_MCUX_LPUART -#ifdef CONFIG_SOC_MIMX93_A55 + +#if defined(CONFIG_SOC_MIMX8QM_ADSP) case IMX_CCM_LPUART1_CLK: case IMX_CCM_LPUART2_CLK: case IMX_CCM_LPUART3_CLK: case IMX_CCM_LPUART4_CLK: case IMX_CCM_LPUART5_CLK: - case IMX_CCM_LPUART6_CLK: - case IMX_CCM_LPUART7_CLK: - case IMX_CCM_LPUART8_CLK: - { uint32_t instance = clock_name & IMX_CCM_INSTANCE_MASK; - clock_root_t clk_root = lpuart_clk_root[instance]; - uint32_t uart_mux = CLOCK_GetRootClockMux(clk_root); - uint32_t divider = CLOCK_GetRootClockDiv(clk_root); - if (uart_mux == 0) - *rate = MHZ(24) / divider; - else - LOG_ERR("LPUART Clock is not supported\r\n"); + CLOCK_SetIpFreq(lpuart_clocks[instance], lpuart_rate); + *rate = CLOCK_GetIpFreq(lpuart_clocks[instance]); + break; - } break; +#elif defined(CONFIG_SOC_MIMX8QXP_ADSP) + case IMX_CCM_LPUART1_CLK: + case IMX_CCM_LPUART2_CLK: + case IMX_CCM_LPUART3_CLK: + case IMX_CCM_LPUART4_CLK: + uint32_t instance = clock_name & IMX_CCM_INSTANCE_MASK; + + CLOCK_SetIpFreq(lpuart_clocks[instance], lpuart_rate); + *rate = CLOCK_GetIpFreq(lpuart_clocks[instance]); + break; #else case IMX_CCM_LPUART_CLK: @@ -269,6 +311,22 @@ static const struct clock_control_driver_api mcux_ccm_driver_api = { .get_rate = mcux_ccm_get_subsys_rate, }; -DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, NULL, +static int mcux_ccm_init(const struct device *dev) +{ +#if defined(CONFIG_SOC_MIMX8QM_ADSP) || defined(CONFIG_SOC_MIMX8QXP_ADSP) + sc_ipc_t ipc_handle; + int ret; + + ret = sc_ipc_open(&ipc_handle, DT_REG_ADDR(DT_NODELABEL(scu_mu))); + if (ret != SC_ERR_NONE) { + return -ENODEV; + } + + CLOCK_Init(ipc_handle); +#endif + return 0; +} + +DEVICE_DT_INST_DEFINE(0, mcux_ccm_init, NULL, NULL, NULL, PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &mcux_ccm_driver_api); diff --git a/drivers/clock_control/clock_control_mcux_ccm_rev2.c b/drivers/clock_control/clock_control_mcux_ccm_rev2.c index 626402d73df..9a88a36823a 100644 --- a/drivers/clock_control/clock_control_mcux_ccm_rev2.c +++ b/drivers/clock_control/clock_control_mcux_ccm_rev2.c @@ -6,7 +6,6 @@ #define DT_DRV_COMPAT nxp_imx_ccm_rev2 #include -#include #include #include #include @@ -31,7 +30,7 @@ static int mcux_ccm_get_subsys_rate(const struct device *dev, clock_control_subsys_t sub_system, uint32_t *rate) { - uint32_t clock_name = (uint32_t) sub_system; + uint32_t clock_name = (size_t) sub_system; uint32_t clock_root, peripheral, instance; peripheral = (clock_name & IMX_CCM_PERIPHERAL_MASK); @@ -51,6 +50,7 @@ static int mcux_ccm_get_subsys_rate(const struct device *dev, #ifdef CONFIG_UART_MCUX_LPUART case IMX_CCM_LPUART1_CLK: + case IMX_CCM_LPUART2_CLK: clock_root = kCLOCK_Root_Lpuart1 + instance; break; #endif @@ -106,8 +106,11 @@ static int mcux_ccm_get_subsys_rate(const struct device *dev, default: return -EINVAL; } - +#ifdef CONFIG_SOC_MIMX93_A55 + *rate = CLOCK_GetIpFreq(clock_root); +#else *rate = CLOCK_GetRootClockFreq(clock_root); +#endif return 0; } diff --git a/drivers/clock_control/clock_control_mcux_syscon.c b/drivers/clock_control/clock_control_mcux_syscon.c index a8cf4f240fe..3dcc073954c 100644 --- a/drivers/clock_control/clock_control_mcux_syscon.c +++ b/drivers/clock_control/clock_control_mcux_syscon.c @@ -19,12 +19,19 @@ static int mcux_lpc_syscon_clock_control_on(const struct device *dev, clock_control_subsys_t sub_system) { #if defined(CONFIG_CAN_MCUX_MCAN) - uint32_t clock_name = (uint32_t)sub_system; - - if (clock_name == MCUX_MCAN_CLK) { + if ((uint32_t)sub_system == MCUX_MCAN_CLK) { CLOCK_EnableClock(kCLOCK_Mcan); } #endif /* defined(CONFIG_CAN_MCUX_MCAN) */ +#if defined(CONFIG_COUNTER_NXP_MRT) + if ((uint32_t)sub_system == MCUX_MRT_CLK) { +#if defined(CONFIG_SOC_FAMILY_LPC) + CLOCK_EnableClock(kCLOCK_Mrt); +#elif defined(CONFIG_SOC_FAMILY_IMX) + CLOCK_EnableClock(kCLOCK_Mrt0); +#endif + } +#endif /* defined(CONFIG_COUNTER_NXP_MRT) */ return 0; } @@ -145,6 +152,12 @@ static int mcux_lpc_syscon_clock_control_get_subsys_rate( break; #endif +#if defined(CONFIG_COUNTER_NXP_MRT) + case MCUX_MRT_CLK: +#endif +#if defined(CONFIG_PWM_MCUX_SCTIMER) + case MCUX_SCTIMER_CLK: +#endif case MCUX_BUS_CLK: *rate = CLOCK_GetFreq(kCLOCK_BusClk); break; diff --git a/drivers/clock_control/clock_control_pwm.c b/drivers/clock_control/clock_control_pwm.c new file mode 100644 index 00000000000..1936e3ab6cc --- /dev/null +++ b/drivers/clock_control/clock_control_pwm.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2023 Andriy Gelman + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT pwm_clock + +#include + +#include +#include +#include +#include +#include +#include + +#define LOG_LEVEL CONFIG_CLOCK_CONTROL_LOG_LEVEL +#include +LOG_MODULE_REGISTER(clock_control_pwm); + +BUILD_ASSERT(CONFIG_CLOCK_CONTROL_PWM_INIT_PRIORITY > CONFIG_PWM_INIT_PRIORITY, + "PWM must have a higher priority than PWM clock control"); + +#define NUM_PWM_CLOCKS 1 + +struct clock_control_pwm_config { + const struct pwm_dt_spec pwm_dt; + const uint16_t pwm_on_delay; +}; + +struct clock_control_pwm_data { + uint32_t clock_frequency; + bool is_enabled; +}; + +static int clock_control_pwm_on(const struct device *dev, clock_control_subsys_t sys) +{ + struct clock_control_pwm_data *data = dev->data; + const struct clock_control_pwm_config *config = dev->config; + const struct pwm_dt_spec *spec; + int id = (int)sys; + int ret; + + if (id >= NUM_PWM_CLOCKS) { + return -EINVAL; + } + + spec = &config->pwm_dt; + if (data->clock_frequency == 0) { + ret = pwm_set_dt(spec, spec->period, spec->period / 2); + } else { + uint64_t cycles_per_sec; + uint32_t period_cycles; + + ret = pwm_get_cycles_per_sec(spec->dev, spec->channel, &cycles_per_sec); + if (ret) { + return ret; + } + + if (cycles_per_sec % data->clock_frequency > 0) { + LOG_WRN("Target clock frequency cannot be expressed in PWM clock ticks"); + } + + period_cycles = cycles_per_sec / data->clock_frequency; + ret = pwm_set_cycles(spec->dev, spec->channel, period_cycles, period_cycles / 2, + spec->flags); + } + + if (ret) { + return ret; + } + + k_busy_wait(config->pwm_on_delay); + + data->is_enabled = true; + + return 0; +} + +static int clock_control_pwm_get_rate(const struct device *dev, clock_control_subsys_t sys, + uint32_t *rate) +{ + struct clock_control_pwm_data *data = dev->data; + const struct clock_control_pwm_config *config = dev->config; + int id = (int)sys; + + if (id >= NUM_PWM_CLOCKS) { + return -EINVAL; + } + + if (data->clock_frequency > 0) { + *rate = data->clock_frequency; + } else { + *rate = NSEC_PER_SEC / config->pwm_dt.period; + } + + return 0; +} + +static int clock_control_pwm_set_rate(const struct device *dev, clock_control_subsys_rate_t sys, + clock_control_subsys_rate_t rate) +{ + struct clock_control_pwm_data *data = dev->data; + uint32_t rate_hz = (uint32_t)rate; + int id = (int)sys; + + if (id >= NUM_PWM_CLOCKS) { + return -EINVAL; + } + + if (data->clock_frequency == rate_hz && data->is_enabled) { + return -EALREADY; + } + + data->clock_frequency = rate_hz; + + return clock_control_pwm_on(dev, sys); +} + +static int clock_control_pwm_init(const struct device *dev) +{ + const struct clock_control_pwm_config *config = dev->config; + + if (!device_is_ready(config->pwm_dt.dev)) { + return -ENODEV; + } + + return 0; +} + +static struct clock_control_driver_api clock_control_pwm_api = { + .on = clock_control_pwm_on, + .get_rate = clock_control_pwm_get_rate, + .set_rate = clock_control_pwm_set_rate, +}; + +#define PWM_CLOCK_INIT(i) \ + \ + BUILD_ASSERT(DT_INST_PROP_LEN(i, pwms) <= 1, \ + "One PWM per clock control node is supported"); \ + \ + BUILD_ASSERT(DT_INST_PROP(i, pwm_on_delay) <= UINT16_MAX, \ + "Maximum pwm-on-delay is 65535 usec"); \ + \ + static const struct clock_control_pwm_config clock_control_pwm_config_##i = { \ + .pwm_dt = PWM_DT_SPEC_INST_GET(i), \ + .pwm_on_delay = DT_INST_PROP(i, pwm_on_delay), \ + }; \ + \ + static struct clock_control_pwm_data clock_control_pwm_data_##i = { \ + .clock_frequency = DT_INST_PROP_OR(i, clock_frequency, 0), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(i, clock_control_pwm_init, NULL, &clock_control_pwm_data_##i, \ + &clock_control_pwm_config_##i, POST_KERNEL, \ + CONFIG_CLOCK_CONTROL_PWM_INIT_PRIORITY, &clock_control_pwm_api); + +DT_INST_FOREACH_STATUS_OKAY(PWM_CLOCK_INIT) diff --git a/drivers/clock_control/clock_control_ra.c b/drivers/clock_control/clock_control_ra.c new file mode 100644 index 00000000000..b1008e3bf83 --- /dev/null +++ b/drivers/clock_control/clock_control_ra.c @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#define DT_DRV_COMPAT renesas_ra_clock_generation_circuit + +#include +#include +#include +#include + +#if DT_SAME_NODE(DT_INST_PROP(0, clock_source), DT_PATH(clocks, pll)) +#define SYSCLK_SRC pll +#elif DT_SAME_NODE(DT_INST_PROP(0, clock_source), DT_PATH(clocks, mosc)) +#define SYSCLK_SRC moco +#elif DT_SAME_NODE(DT_INST_PROP(0, clock_source), DT_PATH(clocks, sosc)) +#define SYSCLK_SRC soco +#elif DT_SAME_NODE(DT_INST_PROP(0, clock_source), DT_PATH(clocks, hoco)) +#define SYSCLK_SRC hoco +#elif DT_SAME_NODE(DT_INST_PROP(0, clock_source), DT_PATH(clocks, moco)) +#define SYSCLK_SRC moco +#elif DT_SAME_NODE(DT_INST_PROP(0, clock_source), DT_PATH(clocks, loco)) +#define SYSCLK_SRC loco +#else +#error Unknown clock source +#endif + +#define FREQ_iclk (clock_freqs[_CONCAT(SCRSCK_, SYSCLK_SRC)] / DT_INST_PROP(0, iclk_div)) +#define FREQ_pclka (clock_freqs[_CONCAT(SCRSCK_, SYSCLK_SRC)] / DT_INST_PROP(0, pclka_div)) +#define FREQ_pclkb (clock_freqs[_CONCAT(SCRSCK_, SYSCLK_SRC)] / DT_INST_PROP(0, pclkb_div)) +#define FREQ_pclkc (clock_freqs[_CONCAT(SCRSCK_, SYSCLK_SRC)] / DT_INST_PROP(0, pclkc_div)) +#define FREQ_pclkd (clock_freqs[_CONCAT(SCRSCK_, SYSCLK_SRC)] / DT_INST_PROP(0, pclkd_div)) +#define FREQ_fclk (clock_freqs[_CONCAT(SCRSCK_, SYSCLK_SRC)] / DT_INST_PROP(0, fclk_div)) + +#define CLKSRC_FREQ(clk) DT_PROP(DT_PATH(clocks, clk), clock_frequency) + +#define IS_CLKSRC_ENABLED(clk) DT_NODE_HAS_STATUS(DT_PATH(clocks, clk), okay) + +#define SCKSCR_INIT_VALUE _CONCAT(CLKSRC_, SYSCLK_SRC) + +#define SCKDIV_ENABLED(clk) DT_INST_NODE_HAS_PROP(0, clk##_div) +#define SCKDIV_VAL(clk) _CONCAT(SCKDIV_, DT_INST_PROP(0, clk##_div)) +#define SCKDIV_POS(clk) _CONCAT(SCKDIV_POS_, clk) + +#define SCKDIVCR_BITS(clk) \ + COND_CODE_1(SCKDIV_ENABLED(clk), ((SCKDIV_VAL(clk) & 0xFU) << SCKDIV_POS(clk)), (0U)) + +#define SCKDIVCR_INIT_VALUE \ + (SCKDIVCR_BITS(iclk) | SCKDIVCR_BITS(pclka) | SCKDIVCR_BITS(pclkb) | \ + SCKDIVCR_BITS(pclkc) | SCKDIVCR_BITS(pclkd) | SCKDIVCR_BITS(bclk) | SCKDIVCR_BITS(fclk)) + +#define HOCOWTCR_INIT_VALUE (6) + +/* + * Required cycles for sub-clokc stabilizing. + */ +#define SUBCLK_STABILIZE_CYCLES 5 + +extern int z_clock_hw_cycles_per_sec; + +enum { + CLKSRC_hoco = 0, + CLKSRC_moco, + CLKSRC_loco, + CLKSRC_mosc, + CLKSRC_sosc, + CLKSRC_pll, +}; + +enum { + SCKDIV_1 = 0, + SCKDIV_2, + SCKDIV_4, + SCKDIV_8, + SCKDIV_16, + SCKDIV_32, + SCKDIV_64, + SCKDIV_128, + SCKDIV_3, + SCKDIV_6, + SCKDIV_12 +}; + +enum { + SCKDIV_POS_pclkd = 0x0U, + SCKDIV_POS_pclkc = 0x4U, + SCKDIV_POS_pclkb = 0x8U, + SCKDIV_POS_pclka = 0xcU, + SCKDIV_POS_bclk = 0x10U, + SCKDIV_POS_pclke = 0x14U, + SCKDIV_POS_iclk = 0x18U, + SCKDIV_POS_fclk = 0x1cU +}; + +enum { + OSCSF_HOCOSF_POS = 0, + OSCSF_MOSCSF_POS = 3, + OSCSF_PLLSF_POS = 5, +}; + +enum { + OPCCR_OPCMTSF_POS = 4, +}; + +static const uint32_t PRCR_KEY = 0xA500U; +static const uint32_t PRCR_CLOCKS = 0x1U; +static const uint32_t PRCR_LOW_POWER = 0x2U; + +enum { +#if DT_INST_REG_SIZE_BY_NAME(0, mstp) == 16 + MSTPCRA_OFFSET = -0x4, +#else + MSTPCRA_OFFSET = 0x0, +#endif + MSTPCRB_OFFSET = (MSTPCRA_OFFSET + 0x4), + MSTPCRC_OFFSET = (MSTPCRB_OFFSET + 0x4), + MSTPCRD_OFFSET = (MSTPCRC_OFFSET + 0x4), + MSTPCRE_OFFSET = (MSTPCRD_OFFSET + 0x4), +}; + +enum { + SCKDIVCR_OFFSET = 0x021, + SCKSCR_OFFSET = 0x026, + MEMWAIT_OFFSET = 0x031, + MOSCCR_OFFSET = 0x032, + HOCOCR_OFFSET = 0x036, + OSCSF_OFFSET = 0x03C, + CKOCR_OFFSET = 0x03E, + OPCCR_OFFSET = 0x0A0, + HOCOWTCR_OFFSET = 0x0A5, + PRCR_OFFSET = 0x3FE, + SOSCCR_OFFSET = 0x480, +}; + +enum { + SCRSCK_hoco, + SCRSCK_moco, + SCRSCK_loco, + SCRSCK_mosc, + SCRSCK_sosc, + SCRSCK_pll, +}; + +static const int clock_freqs[] = { + COND_CODE_1(IS_CLKSRC_ENABLED(hoco), (CLKSRC_FREQ(hoco)), (0)), + COND_CODE_1(IS_CLKSRC_ENABLED(moco), (CLKSRC_FREQ(moco)), (0)), + COND_CODE_1(IS_CLKSRC_ENABLED(loco), (CLKSRC_FREQ(loco)), (0)), + COND_CODE_1(IS_CLKSRC_ENABLED(mosc), (CLKSRC_FREQ(mosc)), (0)), + COND_CODE_1(IS_CLKSRC_ENABLED(sosc), (CLKSRC_FREQ(sosc)), (0)), + COND_CODE_1(IS_CLKSRC_ENABLED(pll), + (DT_PROP(DT_PHANDLE_BY_IDX(DT_PATH(clocks, pll), clocks, 0), clock_frequency) * + DT_PROP(DT_PATH(clocks, pll), clock_mult) / + DT_PROP(DT_PATH(clocks, pll), clock_div)), + (0)), +}; + +static uint32_t MSTP_read(size_t offset) +{ + return sys_read32(DT_INST_REG_ADDR_BY_NAME(0, mstp) + offset); +} + +static void MSTP_write(size_t offset, uint32_t value) +{ + sys_write32(value, DT_INST_REG_ADDR_BY_NAME(0, mstp) + offset); +} + +static uint8_t SYSTEM_read8(size_t offset) +{ + return sys_read8(DT_INST_REG_ADDR_BY_NAME(0, system) + offset); +} + +static void SYSTEM_write8(size_t offset, uint8_t value) +{ + sys_write8(value, DT_INST_REG_ADDR_BY_NAME(0, system) + offset); +} + +static void SYSTEM_write16(size_t offset, uint16_t value) +{ + sys_write16(value, DT_INST_REG_ADDR_BY_NAME(0, system) + offset); +} + +static void SYSTEM_write32(size_t offset, uint32_t value) +{ + sys_write32(value, DT_INST_REG_ADDR_BY_NAME(0, system) + offset); +} + +static int clock_control_ra_on(const struct device *dev, clock_control_subsys_t subsys) +{ + uint32_t clkid = (uint32_t)subsys; + int lock = irq_lock(); + + MSTP_write(MSTPCRA_OFFSET + RA_CLOCK_GROUP(clkid), + MSTP_read(MSTPCRB_OFFSET) & ~RA_CLOCK_BIT(clkid)); + irq_unlock(lock); + + return 0; +} + +static int clock_control_ra_off(const struct device *dev, clock_control_subsys_t subsys) +{ + uint32_t clkid = (uint32_t)subsys; + int lock = irq_lock(); + + MSTP_write(MSTPCRA_OFFSET + RA_CLOCK_GROUP(clkid), + MSTP_read(MSTPCRB_OFFSET) | RA_CLOCK_BIT(clkid)); + irq_unlock(lock); + + return 0; +} + +static int clock_control_ra_get_rate(const struct device *dev, clock_control_subsys_t subsys, + uint32_t *rate) +{ + uint32_t clkid = (uint32_t)subsys; + + switch (clkid & 0xFFFFFF00) { + case RA_CLOCK_SCI(0): + *rate = FREQ_pclka; + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct clock_control_driver_api ra_clock_control_driver_api = { + .on = clock_control_ra_on, + .off = clock_control_ra_off, + .get_rate = clock_control_ra_get_rate, +}; + +static void crude_busy_loop_impl(uint32_t cycles) +{ + __asm__ volatile(".align 8\n" + "busy_loop:\n" + " sub r0, r0, #1\n" + " cmp r0, #0\n" + " bne.n busy_loop\n"); +} + +static inline void crude_busy_loop(uint32_t wait_us) +{ + static const uint64_t cycles_per_loop = 4; + + crude_busy_loop_impl(sys_clock_hw_cycles_per_sec() * wait_us / USEC_PER_SEC / + cycles_per_loop); +} + +static int clock_control_ra_init(const struct device *dev) +{ + uint8_t sysclk = SYSTEM_read8(SCKSCR_OFFSET); + + z_clock_hw_cycles_per_sec = clock_freqs[sysclk]; + + SYSTEM_write16(PRCR_OFFSET, PRCR_KEY | PRCR_CLOCKS | PRCR_LOW_POWER); + + if (clock_freqs[SCRSCK_hoco] == 64000000) { + SYSTEM_write8(HOCOWTCR_OFFSET, HOCOWTCR_INIT_VALUE); + } + + SYSTEM_write8(SOSCCR_OFFSET, !IS_CLKSRC_ENABLED(sosc)); + SYSTEM_write8(MOSCCR_OFFSET, !IS_CLKSRC_ENABLED(mosc)); + SYSTEM_write8(HOCOCR_OFFSET, !IS_CLKSRC_ENABLED(hoco)); + + if (IS_CLKSRC_ENABLED(sosc)) { + crude_busy_loop(z_clock_hw_cycles_per_sec / clock_freqs[CLKSRC_sosc] * + SUBCLK_STABILIZE_CYCLES); + } + + if (IS_CLKSRC_ENABLED(mosc)) { + while ((SYSTEM_read8(OSCSF_OFFSET) & BIT(OSCSF_MOSCSF_POS)) != + BIT(OSCSF_MOSCSF_POS)) { + ; + } + } + + if (IS_CLKSRC_ENABLED(hoco)) { + while ((SYSTEM_read8(OSCSF_OFFSET) & BIT(OSCSF_HOCOSF_POS)) != + BIT(OSCSF_HOCOSF_POS)) { + ; + } + } + + SYSTEM_write32(SCKDIVCR_OFFSET, SCKDIVCR_INIT_VALUE); + SYSTEM_write8(SCKSCR_OFFSET, SCKSCR_INIT_VALUE); + + z_clock_hw_cycles_per_sec = clock_freqs[sysclk]; + + SYSTEM_write8(OPCCR_OFFSET, 0); + while ((SYSTEM_read8(OPCCR_OFFSET) & BIT(OPCCR_OPCMTSF_POS)) != 0) { + ; + } + + SYSTEM_write8(MEMWAIT_OFFSET, 1); + SYSTEM_write16(PRCR_OFFSET, PRCR_KEY | PRCR_CLOCKS | PRCR_LOW_POWER); + + return 0; +} + +DEVICE_DT_INST_DEFINE(0, &clock_control_ra_init, NULL, NULL, NULL, PRE_KERNEL_1, + CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &ra_clock_control_driver_api); diff --git a/drivers/clock_control/clock_control_renesas_cpg_mssr.h b/drivers/clock_control/clock_control_renesas_cpg_mssr.h index 13d3cbeeb4e..d616567763e 100644 --- a/drivers/clock_control/clock_control_renesas_cpg_mssr.h +++ b/drivers/clock_control/clock_control_renesas_cpg_mssr.h @@ -96,7 +96,7 @@ static const uint16_t srcr[] = { 0x920, 0x924, 0x928, 0x92C, }; -/* CAN-FD Clock Frequency Control Register */ +/* CAN FD Clock Frequency Control Register */ #define CANFDCKCR 0x244 /* Clock stop bit */ diff --git a/drivers/clock_control/clock_stm32_ll_common.c b/drivers/clock_control/clock_stm32_ll_common.c index b596ac08da9..ba5ba2e4673 100644 --- a/drivers/clock_control/clock_stm32_ll_common.c +++ b/drivers/clock_control/clock_stm32_ll_common.c @@ -723,21 +723,6 @@ int stm32_clock_control_init(const struct device *dev) /* Some clocks would be activated by default */ config_enable_default_clocks(); -#if defined(STM32_PLL_ENABLED) && defined(CONFIG_SOC_SERIES_STM32F7X) - /* Assuming we stay on Power Scale default value: Power Scale 1 */ - if (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC > 180000000) { - /* Set Overdrive if needed before configuring the Flash Latency */ - LL_PWR_EnableOverDriveMode(); - while (LL_PWR_IsActiveFlag_OD() != 1) { - /* Wait for OverDrive mode ready */ - } - LL_PWR_EnableOverDriveSwitching(); - while (LL_PWR_IsActiveFlag_ODSW() != 1) { - /* Wait for OverDrive switch ready */ - } - } -#endif /* STM32_PLL_ENABLED && CONFIG_SOC_SERIES_STM32F7X */ - #if defined(FLASH_ACR_LATENCY) uint32_t old_flash_freq; uint32_t new_flash_freq; @@ -748,9 +733,9 @@ int stm32_clock_control_init(const struct device *dev) new_flash_freq = RCC_CALC_FLASH_FREQ(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, STM32_FLASH_PRESCALER); - /* If freq increases, set flash latency before any clock setting */ - if (old_flash_freq < CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC) { - LL_SetFlashLatency(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC); + /* If HCLK increases, set flash latency before any clock setting */ + if (old_flash_freq < new_flash_freq) { + LL_SetFlashLatency(new_flash_freq); } #endif /* FLASH_ACR_LATENCY */ @@ -794,9 +779,9 @@ int stm32_clock_control_init(const struct device *dev) } #if defined(FLASH_ACR_LATENCY) - /* If freq not increased, set flash latency after all clock setting */ - if (old_flash_freq >= CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC) { - LL_SetFlashLatency(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC); + /* If HCLK not increased, set flash latency after all clock setting */ + if (old_flash_freq >= new_flash_freq) { + LL_SetFlashLatency(new_flash_freq); } #endif /* FLASH_ACR_LATENCY */ diff --git a/drivers/clock_control/clock_stm32_ll_h7.c b/drivers/clock_control/clock_stm32_ll_h7.c index c95d8ab1294..dc9127d277d 100644 --- a/drivers/clock_control/clock_stm32_ll_h7.c +++ b/drivers/clock_control/clock_stm32_ll_h7.c @@ -107,6 +107,7 @@ #define AHB_FREQ_MAX 275000000UL #define APBx_FREQ_MAX 137500000UL #elif defined(CONFIG_SOC_STM32H7A3XX) || defined(CONFIG_SOC_STM32H7A3XXQ) ||\ + defined(CONFIG_SOC_STM32H7B0XX) || defined(CONFIG_SOC_STM32H7B0XXQ) ||\ defined(CONFIG_SOC_STM32H7B3XX) || defined(CONFIG_SOC_STM32H7B3XXQ) #define SYSCLK_FREQ_MAX 280000000UL #define AHB_FREQ_MAX 280000000UL @@ -829,6 +830,7 @@ int stm32_clock_control_init(const struct device *dev) /* HW semaphore Clock enable */ #if defined(CONFIG_SOC_STM32H7A3XX) || defined(CONFIG_SOC_STM32H7A3XXQ) || \ + defined(CONFIG_SOC_STM32H7B0XX) || defined(CONFIG_SOC_STM32H7B0XXQ) || \ defined(CONFIG_SOC_STM32H7B3XX) || defined(CONFIG_SOC_STM32H7B3XXQ) LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_HSEM); #else diff --git a/drivers/clock_control/clock_stm32_ll_u5.c b/drivers/clock_control/clock_stm32_ll_u5.c index e7cc8da677b..8fe0608d50c 100644 --- a/drivers/clock_control/clock_stm32_ll_u5.c +++ b/drivers/clock_control/clock_stm32_ll_u5.c @@ -519,6 +519,10 @@ static int set_up_plls(void) LL_RCC_PLL1_SetN(STM32_PLL_N_MULTIPLIER); LL_RCC_PLL1FRACN_Disable(); + if (IS_ENABLED(STM32_PLL_FRACN_ENABLED)) { + LL_RCC_PLL1_SetFRACN(STM32_PLL_FRACN_VALUE); + LL_RCC_PLL1FRACN_Enable(); + } if (IS_ENABLED(STM32_PLL_P_ENABLED)) { LL_RCC_PLL1_SetP(STM32_PLL_P_DIVISOR); @@ -569,6 +573,10 @@ static int set_up_plls(void) LL_RCC_PLL2_SetN(STM32_PLL2_N_MULTIPLIER); LL_RCC_PLL2FRACN_Disable(); + if (IS_ENABLED(STM32_PLL2_FRACN_ENABLED)) { + LL_RCC_PLL2_SetFRACN(STM32_PLL2_FRACN_VALUE); + LL_RCC_PLL2FRACN_Enable(); + } if (IS_ENABLED(STM32_PLL2_P_ENABLED)) { LL_RCC_PLL2_SetP(STM32_PLL2_P_DIVISOR); @@ -617,6 +625,10 @@ static int set_up_plls(void) LL_RCC_PLL3_SetN(STM32_PLL3_N_MULTIPLIER); LL_RCC_PLL3FRACN_Disable(); + if (IS_ENABLED(STM32_PLL3_FRACN_ENABLED)) { + LL_RCC_PLL3_SetFRACN(STM32_PLL3_FRACN_VALUE); + LL_RCC_PLL3FRACN_Enable(); + } if (IS_ENABLED(STM32_PLL3_P_ENABLED)) { LL_RCC_PLL3_SetP(STM32_PLL3_P_DIVISOR); @@ -758,10 +770,25 @@ static void set_up_fixed_clock_sources(void) } if (IS_ENABLED(STM32_LSI_ENABLED)) { + if (!LL_AHB3_GRP1_IsEnabledClock(LL_AHB3_GRP1_PERIPH_PWR)) { + /* Enable the power interface clock */ + LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_PWR); + } + + if (!LL_PWR_IsEnabledBkUpAccess()) { + /* Enable write access to Backup domain */ + LL_PWR_EnableBkUpAccess(); + while (!LL_PWR_IsEnabledBkUpAccess()) { + /* Wait for Backup domain access */ + } + } + /* Enable LSI oscillator */ LL_RCC_LSI_Enable(); while (LL_RCC_LSI_IsReady() != 1) { } + + LL_PWR_DisableBkUpAccess(); } if (IS_ENABLED(STM32_HSI48_ENABLED)) { diff --git a/drivers/clock_control/clock_stm32_ll_wba.c b/drivers/clock_control/clock_stm32_ll_wba.c index 46b834c52e9..8b9da70017a 100644 --- a/drivers/clock_control/clock_stm32_ll_wba.c +++ b/drivers/clock_control/clock_stm32_ll_wba.c @@ -287,7 +287,7 @@ static int get_vco_input_range(uint32_t m_div, uint32_t *range) static void set_regu_voltage(uint32_t hclk_freq) { - if (hclk_freq < MHZ(16)) { + if (hclk_freq <= MHZ(16)) { LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE2); } else { LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); diff --git a/drivers/clock_control/clock_stm32f2_f4_f7.c b/drivers/clock_control/clock_stm32f2_f4_f7.c index e7a28445572..6131fcd4c06 100644 --- a/drivers/clock_control/clock_stm32f2_f4_f7.c +++ b/drivers/clock_control/clock_stm32f2_f4_f7.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -59,6 +60,35 @@ void config_pll_sysclock(void) pllm(STM32_PLL_M_DIVISOR), STM32_PLL_N_MULTIPLIER, pllp(STM32_PLL_P_DIVISOR)); + +#if defined(CONFIG_SOC_SERIES_STM32F7X) + /* Assuming we stay on Power Scale default value: Power Scale 1 */ + if (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC > 180000000) { + /* Enable the PLL (PLLON) before setting overdrive. Skipping the PLL + * locking phase since the system will be stalled during the switch + * (ODSW) but the PLL clock system will be running during the locking + * phase. See reference manual (RM0431) §4.1.4 Voltage regulator + * Sub section: Entering Over-drive mode. + */ + LL_RCC_PLL_Enable(); + + /* Set Overdrive if needed before configuring the Flash Latency */ + LL_PWR_EnableOverDriveMode(); + while (LL_PWR_IsActiveFlag_OD() != 1) { + /* Wait for OverDrive mode ready */ + } + LL_PWR_EnableOverDriveSwitching(); + while (LL_PWR_IsActiveFlag_ODSW() != 1) { + /* Wait for OverDrive switch ready */ + } + + /* The PLL could still not be locked when returning to the caller + * function. But the caller doesn't know we've turned on the PLL + * for the overdrive function. The caller will try to turn on the PLL + * And start waiting for the PLL locking phase to complete. + */ + } +#endif /* CONFIG_SOC_SERIES_STM32F7X */ } #endif /* defined(STM32_PLL_ENABLED) */ diff --git a/drivers/clock_control/clock_stm32g0.c b/drivers/clock_control/clock_stm32g0.c index 50558350141..5f7a3bfb1ad 100644 --- a/drivers/clock_control/clock_stm32g0.c +++ b/drivers/clock_control/clock_stm32g0.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -74,4 +75,18 @@ void config_enable_default_clocks(void) { /* Enable the power interface clock */ LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); + +#if defined(CRS) + if (IS_ENABLED(STM32_HSI48_CRS_USB_SOF)) { + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_CRS); + /* + * After reset the CRS configuration register + * (CRS_CFGR) value corresponds to an USB SOF + * synchronization. FIXME: write it anyway. + */ + LL_CRS_EnableAutoTrimming(); + LL_CRS_EnableFreqErrorCounter(); + } +#endif /* defined(CRS) */ + } diff --git a/drivers/console/Kconfig b/drivers/console/Kconfig index b0dbdf7df7b..606ce1fe6d6 100644 --- a/drivers/console/Kconfig +++ b/drivers/console/Kconfig @@ -256,10 +256,11 @@ source "subsys/logging/Kconfig.template.log_config" source "drivers/console/Kconfig.gsm_mux" config UART_MUX - bool "UART muxing (GSM 07.10) support [EXPERIMENTAL]" + bool "[DEPRECATED] UART muxing (GSM 07.10) support [EXPERIMENTAL]" depends on SERIAL_SUPPORT_INTERRUPT && GSM_MUX select UART_INTERRUPT_DRIVEN select EXPERIMENTAL + select DEPRECATED help Enable this option to create UART muxer that run over a physical UART. The GSM 07.10 muxing protocol is used to separate the data diff --git a/drivers/console/Kconfig.gsm_mux b/drivers/console/Kconfig.gsm_mux index 14ef6b66da6..100b5d54303 100644 --- a/drivers/console/Kconfig.gsm_mux +++ b/drivers/console/Kconfig.gsm_mux @@ -2,8 +2,9 @@ # SPDX-License-Identifier: Apache-2.0 config GSM_MUX - bool "GSM 07.10 muxing protocol" + bool "[DEPRECATED] GSM 07.10 muxing protocol" select CRC + select DEPRECATED help Enable GSM 07.10 muxing protocol defined in https://www.etsi.org/deliver/etsi_ts/101300_101399/101369/07.01.00_60/ts_101369v070100p.pdf diff --git a/drivers/console/uart_console.c b/drivers/console/uart_console.c index 4800180b3f8..21df7fd3455 100644 --- a/drivers/console/uart_console.c +++ b/drivers/console/uart_console.c @@ -446,13 +446,18 @@ static void uart_console_isr(const struct device *unused, void *user_data) ARG_UNUSED(user_data); static uint8_t last_char = '\0'; - while (uart_irq_update(uart_console_dev) && - uart_irq_is_pending(uart_console_dev)) { + while (uart_irq_update(uart_console_dev) > 0 && + uart_irq_is_pending(uart_console_dev) > 0) { static struct console_input *cmd; uint8_t byte; int rx; - if (!uart_irq_rx_ready(uart_console_dev)) { + rx = uart_irq_rx_ready(uart_console_dev); + if (rx < 0) { + return; + } + + if (rx == 0) { continue; } @@ -469,7 +474,7 @@ static void uart_console_isr(const struct device *unused, void *user_data) * The input hook indicates that no further processing * should be done by this handler. */ - return; + continue; } #endif @@ -561,7 +566,7 @@ static void console_input_init(void) uart_irq_callback_set(uart_console_dev, uart_console_isr); /* Drain the fifo */ - while (uart_irq_rx_ready(uart_console_dev)) { + while (uart_irq_rx_ready(uart_console_dev) > 0) { uart_fifo_read(uart_console_dev, &c, 1); } diff --git a/drivers/console/uart_mux.c b/drivers/console/uart_mux.c index ba882b038ee..ca445a1f5b7 100644 --- a/drivers/console/uart_mux.c +++ b/drivers/console/uart_mux.c @@ -10,7 +10,7 @@ LOG_MODULE_REGISTER(uart_mux, CONFIG_UART_MUX_LOG_LEVEL); #include #include #include -#include +#include #include #include #include diff --git a/drivers/console/winstream_console.c b/drivers/console/winstream_console.c index 8d574bbe3a2..abc5344593a 100644 --- a/drivers/console/winstream_console.c +++ b/drivers/console/winstream_console.c @@ -62,4 +62,4 @@ static int winstream_console_init(void) return 0; } -SYS_INIT(winstream_console_init, EARLY, CONFIG_CONSOLE_INIT_PRIORITY); +SYS_INIT(winstream_console_init, PRE_KERNEL_1, CONFIG_CONSOLE_INIT_PRIORITY); diff --git a/drivers/counter/CMakeLists.txt b/drivers/counter/CMakeLists.txt index e250a2851b2..50a1ffad441 100644 --- a/drivers/counter/CMakeLists.txt +++ b/drivers/counter/CMakeLists.txt @@ -44,6 +44,8 @@ zephyr_library_sources_ifdef(CONFIG_COUNTER_INFINEON_CAT1 counter_ifx_cat1 zephyr_library_sources_ifdef(CONFIG_ACE_V1X_ART_COUNTER counter_ace_v1x_art.c) zephyr_library_sources_ifdef(CONFIG_ACE_V1X_RTC_COUNTER counter_ace_v1x_rtc.c) zephyr_library_sources_ifdef(CONFIG_COUNTER_NXP_S32_SYS_TIMER counter_nxp_s32_sys_timer.c) -zephyr_library_sources_ifdef(CONFIG_COUNTER_TIMER_GD32 counter_gd32_timer.c) +zephyr_library_sources_ifdef(CONFIG_COUNTER_TIMER_GD32 counter_gd32_timer.c) zephyr_library_sources_ifdef(CONFIG_COUNTER_SNPS_DW counter_dw_timer.c) zephyr_library_sources_ifdef(CONFIG_COUNTER_SHELL counter_timer_shell.c) +zephyr_library_sources_ifdef(CONFIG_COUNTER_TIMER_RPI_PICO counter_rpi_pico_timer.c) +zephyr_library_sources_ifdef(CONFIG_COUNTER_NXP_MRT counter_nxp_mrt.c) diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig index 793c58dd063..16adaee75b2 100644 --- a/drivers/counter/Kconfig +++ b/drivers/counter/Kconfig @@ -92,4 +92,8 @@ source "drivers/counter/Kconfig.gd32" source "drivers/counter/Kconfig.dw" +source "drivers/counter/Kconfig.rpi_pico" + +source "drivers/counter/Kconfig.nxp_mrt" + endif # COUNTER diff --git a/drivers/counter/Kconfig.native_posix b/drivers/counter/Kconfig.native_posix index 362eb00da1c..a342ed07a30 100644 --- a/drivers/counter/Kconfig.native_posix +++ b/drivers/counter/Kconfig.native_posix @@ -10,3 +10,8 @@ config COUNTER_NATIVE_POSIX_FREQUENCY int "native_posix counter frequency in Hz" default 1000 depends on COUNTER_NATIVE_POSIX + +config COUNTER_NATIVE_POSIX_NBR_CHANNELS + int "native counter, number of channels" + default 4 + depends on COUNTER_NATIVE_POSIX diff --git a/drivers/counter/Kconfig.nxp_mrt b/drivers/counter/Kconfig.nxp_mrt new file mode 100644 index 00000000000..a395ada36b4 --- /dev/null +++ b/drivers/counter/Kconfig.nxp_mrt @@ -0,0 +1,9 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +config COUNTER_NXP_MRT + bool "NXP MRT driver" + default y if DT_HAS_NXP_MRT_CHANNEL_ENABLED && \ + DT_HAS_NXP_MRT_ENABLED + help + Enable driver for the NXP Multirate Timer (MRT). diff --git a/drivers/counter/Kconfig.nxp_s32 b/drivers/counter/Kconfig.nxp_s32 index 72274ee6269..ce4f3574abc 100644 --- a/drivers/counter/Kconfig.nxp_s32 +++ b/drivers/counter/Kconfig.nxp_s32 @@ -1,9 +1,10 @@ -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # SPDX-License-Identifier: Apache-2.0 config COUNTER_NXP_S32_SYS_TIMER bool "NXP S32 System Timer Module driver" default y depends on DT_HAS_NXP_S32_SYS_TIMER_ENABLED + select CLOCK_CONTROL help Enable support for NXP S32 System Timer Module (STM) driver. diff --git a/drivers/counter/Kconfig.rpi_pico b/drivers/counter/Kconfig.rpi_pico new file mode 100644 index 00000000000..53fc748e252 --- /dev/null +++ b/drivers/counter/Kconfig.rpi_pico @@ -0,0 +1,8 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +config COUNTER_TIMER_RPI_PICO + def_bool y + select PICOSDK_USE_TIMER + select PICOSDK_USE_CLAIM + depends on DT_HAS_RASPBERRYPI_PICO_TIMER_ENABLED diff --git a/drivers/counter/Kconfig.stm32_rtc b/drivers/counter/Kconfig.stm32_rtc index 03e72babc60..0e1268557df 100644 --- a/drivers/counter/Kconfig.stm32_rtc +++ b/drivers/counter/Kconfig.stm32_rtc @@ -44,4 +44,13 @@ config COUNTER_RTC_STM32_SAVE_VALUE_BETWEEN_RESETS help Keep the counter value after each reset. +config COUNTER_RTC_STM32_SUBSECONDS + bool "Use the subseconds as a basic tick." + depends on !SOC_SERIES_STM32F1X + help + Use the subseconds as the basic time tick. It increases resolution + of the counter. The frequency of the time is RTC Source Clock divided + by 2. It is the clock after the first asynchronous prescaler. + The config increases power consumption. + endif # COUNTER_RTC_STM32 diff --git a/drivers/counter/counter_handlers.c b/drivers/counter/counter_handlers.c index a493ea0c765..15cd0cb5881 100644 --- a/drivers/counter/counter_handlers.c +++ b/drivers/counter/counter_handlers.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include /* For those APIs that just take one argument which is a counter driver @@ -13,7 +13,7 @@ #define COUNTER_HANDLER(name) \ static inline int z_vrfy_counter_##name(const struct device *dev) \ { \ - Z_OOPS(Z_SYSCALL_DRIVER_COUNTER(dev, name)); \ + K_OOPS(K_SYSCALL_DRIVER_COUNTER(dev, name)); \ return z_impl_counter_ ## name((const struct device *)dev); \ } @@ -27,21 +27,21 @@ COUNTER_HANDLER(start) static inline bool z_vrfy_counter_is_counting_up(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); return z_impl_counter_is_counting_up((const struct device *)dev); } #include static inline uint8_t z_vrfy_counter_get_num_of_channels(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); return z_impl_counter_get_num_of_channels((const struct device *)dev); } #include static inline uint32_t z_vrfy_counter_get_frequency(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); return z_impl_counter_get_frequency((const struct device *)dev); } #include @@ -49,7 +49,7 @@ static inline uint32_t z_vrfy_counter_get_frequency(const struct device *dev) static inline uint32_t z_vrfy_counter_us_to_ticks(const struct device *dev, uint64_t us) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); return z_impl_counter_us_to_ticks((const struct device *)dev, (uint64_t)us); } @@ -58,7 +58,7 @@ static inline uint32_t z_vrfy_counter_us_to_ticks(const struct device *dev, static inline uint64_t z_vrfy_counter_ticks_to_us(const struct device *dev, uint32_t ticks) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); return z_impl_counter_ticks_to_us((const struct device *)dev, (uint32_t)ticks); } @@ -67,16 +67,16 @@ static inline uint64_t z_vrfy_counter_ticks_to_us(const struct device *dev, static inline int z_vrfy_counter_get_value(const struct device *dev, uint32_t *ticks) { - Z_OOPS(Z_SYSCALL_DRIVER_COUNTER(dev, get_value)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(ticks, sizeof(*ticks))); + K_OOPS(K_SYSCALL_DRIVER_COUNTER(dev, get_value)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(ticks, sizeof(*ticks))); return z_impl_counter_get_value((const struct device *)dev, ticks); } static inline int z_vrfy_counter_get_value_64(const struct device *dev, uint64_t *ticks) { - Z_OOPS(Z_SYSCALL_DRIVER_COUNTER(dev, get_value_64)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(ticks, sizeof(*ticks))); + K_OOPS(K_SYSCALL_DRIVER_COUNTER(dev, get_value_64)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(ticks, sizeof(*ticks))); return z_impl_counter_get_value_64((const struct device *)dev, ticks); } @@ -88,9 +88,9 @@ static inline int z_vrfy_counter_set_channel_alarm(const struct device *dev, { struct counter_alarm_cfg cfg_copy; - Z_OOPS(Z_SYSCALL_DRIVER_COUNTER(dev, set_alarm)); - Z_OOPS(z_user_from_copy(&cfg_copy, alarm_cfg, sizeof(cfg_copy))); - Z_OOPS(Z_SYSCALL_VERIFY_MSG(cfg_copy.callback == NULL, + K_OOPS(K_SYSCALL_DRIVER_COUNTER(dev, set_alarm)); + K_OOPS(k_usermode_from_copy(&cfg_copy, alarm_cfg, sizeof(cfg_copy))); + K_OOPS(K_SYSCALL_VERIFY_MSG(cfg_copy.callback == NULL, "callbacks may not be set from user mode")); return z_impl_counter_set_channel_alarm((const struct device *)dev, (uint8_t)chan_id, @@ -102,7 +102,7 @@ static inline int z_vrfy_counter_set_channel_alarm(const struct device *dev, static inline int z_vrfy_counter_cancel_channel_alarm(const struct device *dev, uint8_t chan_id) { - Z_OOPS(Z_SYSCALL_DRIVER_COUNTER(dev, cancel_alarm)); + K_OOPS(K_SYSCALL_DRIVER_COUNTER(dev, cancel_alarm)); return z_impl_counter_cancel_channel_alarm((const struct device *)dev, (uint8_t)chan_id); } @@ -114,9 +114,9 @@ static inline int z_vrfy_counter_set_top_value(const struct device *dev, { struct counter_top_cfg cfg_copy; - Z_OOPS(Z_SYSCALL_DRIVER_COUNTER(dev, set_top_value)); - Z_OOPS(z_user_from_copy(&cfg_copy, cfg, sizeof(cfg_copy))); - Z_OOPS(Z_SYSCALL_VERIFY_MSG(cfg_copy.callback == NULL, + K_OOPS(K_SYSCALL_DRIVER_COUNTER(dev, set_top_value)); + K_OOPS(k_usermode_from_copy(&cfg_copy, cfg, sizeof(cfg_copy))); + K_OOPS(K_SYSCALL_VERIFY_MSG(cfg_copy.callback == NULL, "callbacks may not be set from user mode")); return z_impl_counter_set_top_value((const struct device *)dev, (const struct counter_top_cfg *) @@ -126,14 +126,14 @@ static inline int z_vrfy_counter_set_top_value(const struct device *dev, static inline uint32_t z_vrfy_counter_get_top_value(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_COUNTER(dev, get_top_value)); + K_OOPS(K_SYSCALL_DRIVER_COUNTER(dev, get_top_value)); return z_impl_counter_get_top_value((const struct device *)dev); } #include static inline uint32_t z_vrfy_counter_get_max_top_value(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); return z_impl_counter_get_max_top_value((const struct device *)dev); } #include @@ -141,7 +141,7 @@ static inline uint32_t z_vrfy_counter_get_max_top_value(const struct device *dev static inline uint32_t z_vrfy_counter_get_guard_period(const struct device *dev, uint32_t flags) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); return z_impl_counter_get_guard_period((const struct device *)dev, flags); } @@ -150,7 +150,7 @@ static inline uint32_t z_vrfy_counter_get_guard_period(const struct device *dev, static inline int z_vrfy_counter_set_guard_period(const struct device *dev, uint32_t ticks, uint32_t flags) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); return z_impl_counter_set_guard_period((const struct device *)dev, ticks, flags); diff --git a/drivers/counter/counter_ll_stm32_rtc.c b/drivers/counter/counter_ll_stm32_rtc.c index a7265c635f2..76114cab386 100644 --- a/drivers/counter/counter_ll_stm32_rtc.c +++ b/drivers/counter/counter_ll_stm32_rtc.c @@ -61,6 +61,34 @@ LOG_MODULE_REGISTER(counter_rtc_stm32, CONFIG_COUNTER_LOG_LEVEL); #define COUNTER_NO_DATE #endif +#if DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_LSI +/* LSI */ +#define RTCCLK_FREQ STM32_LSI_FREQ +#else +/* LSE */ +#define RTCCLK_FREQ STM32_LSE_FREQ +#endif /* DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_LSI */ + +#if !defined(CONFIG_SOC_SERIES_STM32F1X) +#ifndef CONFIG_COUNTER_RTC_STM32_SUBSECONDS +#define RTC_ASYNCPRE BIT_MASK(7) +#else /* !CONFIG_COUNTER_RTC_STM32_SUBSECONDS */ +/* Get the highest possible clock for the subsecond register */ +#define RTC_ASYNCPRE 1 +#endif /* CONFIG_COUNTER_RTC_STM32_SUBSECONDS */ +#else /* CONFIG_SOC_SERIES_STM32F1X */ +#define RTC_ASYNCPRE (RTCCLK_FREQ - 1) +#endif /* CONFIG_SOC_SERIES_STM32F1X */ + +/* Adjust the second sync prescaler to get 1Hz on ck_spre */ +#define RTC_SYNCPRE ((RTCCLK_FREQ / (1 + RTC_ASYNCPRE)) - 1) + +#ifndef CONFIG_COUNTER_RTC_STM32_SUBSECONDS +typedef uint32_t tick_t; +#else +typedef uint64_t tick_t; +#endif + struct rtc_stm32_config { struct counter_config_info counter_info; LL_RTC_InitTypeDef ll_rtc_config; @@ -71,6 +99,9 @@ struct rtc_stm32_data { counter_alarm_callback_t callback; uint32_t ticks; void *user_data; +#ifdef CONFIG_COUNTER_RTC_STM32_SUBSECONDS + bool irq_on_late; +#endif /* CONFIG_COUNTER_RTC_STM32_SUBSECONDS */ }; static inline ErrorStatus ll_func_init_alarm(RTC_TypeDef *rtc, uint32_t format, @@ -119,6 +150,17 @@ static inline void ll_func_disable_interrupt_alarm(RTC_TypeDef *rtc) #endif } +#ifdef CONFIG_COUNTER_RTC_STM32_SUBSECONDS +static inline uint32_t ll_func_isenabled_interrupt_alarm(RTC_TypeDef *rtc) +{ +#if defined(CONFIG_SOC_SERIES_STM32F1X) + return LL_RTC_IsEnabledIT_ALR(rtc); +#else + return LL_RTC_IsEnabledIT_ALRA(rtc); +#endif +} +#endif /* CONFIG_COUNTER_RTC_STM32_SUBSECONDS */ + static inline void ll_func_enable_alarm(RTC_TypeDef *rtc) { #if defined(CONFIG_SOC_SERIES_STM32F1X) @@ -142,11 +184,22 @@ static void rtc_stm32_irq_config(const struct device *dev); static int rtc_stm32_start(const struct device *dev) { +#if defined(CONFIG_SOC_SERIES_STM32WBAX) + const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); + const struct rtc_stm32_config *cfg = dev->config; + + /* Enable RTC bus clock */ + if (clock_control_on(clk, (clock_control_subsys_t) &cfg->pclken[0]) != 0) { + LOG_ERR("clock op failed\n"); + return -EIO; + } +#else ARG_UNUSED(dev); z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY); LL_RCC_EnableRTC(); z_stm32_hsem_unlock(CFG_HW_RCC_SEMID); +#endif return 0; } @@ -154,34 +207,55 @@ static int rtc_stm32_start(const struct device *dev) static int rtc_stm32_stop(const struct device *dev) { +#if defined(CONFIG_SOC_SERIES_STM32WBAX) + const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); + const struct rtc_stm32_config *cfg = dev->config; + + /* Enable RTC bus clock */ + if (clock_control_on(clk, (clock_control_subsys_t) &cfg->pclken[0]) != 0) { + LOG_ERR("clock op failed\n"); + return -EIO; + } +#else ARG_UNUSED(dev); z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY); LL_RCC_DisableRTC(); z_stm32_hsem_unlock(CFG_HW_RCC_SEMID); +#endif return 0; } - -static uint32_t rtc_stm32_read(const struct device *dev) -{ #if !defined(COUNTER_NO_DATE) +tick_t rtc_stm32_read(const struct device *dev) +{ struct tm now = { 0 }; time_t ts; - uint32_t rtc_date, rtc_time, ticks; -#else - uint32_t rtc_time, ticks; -#endif + uint32_t rtc_date, rtc_time; + tick_t ticks; +#ifdef CONFIG_COUNTER_RTC_STM32_SUBSECONDS + uint32_t rtc_subseconds; +#endif /* CONFIG_COUNTER_RTC_STM32_SUBSECONDS */ ARG_UNUSED(dev); - /* Read time and date registers */ - rtc_time = LL_RTC_TIME_Get(RTC); -#if !defined(COUNTER_NO_DATE) - rtc_date = LL_RTC_DATE_Get(RTC); + /* Read time and date registers. Make sure value of the previous register + * hasn't been changed while reading the next one. + */ + do { + rtc_date = LL_RTC_DATE_Get(RTC); + +#ifdef CONFIG_COUNTER_RTC_STM32_SUBSECONDS + do { + rtc_time = LL_RTC_TIME_Get(RTC); + rtc_subseconds = LL_RTC_TIME_GetSubSecond(RTC); + } while (rtc_time != LL_RTC_TIME_Get(RTC)); +#else /* CONFIG_COUNTER_RTC_STM32_SUBSECONDS */ + rtc_time = LL_RTC_TIME_Get(RTC); #endif -#if !defined(COUNTER_NO_DATE) + } while (rtc_date != LL_RTC_DATE_Get(RTC)); + /* Convert calendar datetime to UNIX timestamp */ /* RTC start time: 1st, Jan, 2000 */ /* time_t start: 1st, Jan, 1970 */ @@ -201,34 +275,71 @@ static uint32_t rtc_stm32_read(const struct device *dev) ts -= T_TIME_OFFSET; __ASSERT(sizeof(time_t) == 8, "unexpected time_t definition"); - ticks = counter_us_to_ticks(dev, ts * USEC_PER_SEC); -#else + + ticks = ts * counter_get_frequency(dev); +#ifdef CONFIG_COUNTER_RTC_STM32_SUBSECONDS + /* The RTC counts up, except for the subsecond register which counts + * down starting from the sync prescaler value. Add already counted + * ticks. + */ + ticks += RTC_SYNCPRE - rtc_subseconds; +#endif /* CONFIG_COUNTER_RTC_STM32_SUBSECONDS */ + + return ticks; +} +#else /* defined(COUNTER_NO_DATE) */ +tick_t rtc_stm32_read(const struct device *dev) +{ + uint32_t rtc_time, ticks; + + ARG_UNUSED(dev); + + rtc_time = LL_RTC_TIME_Get(RTC); + ticks = rtc_time; -#endif return ticks; } +#endif /* !defined(COUNTER_NO_DATE) */ static int rtc_stm32_get_value(const struct device *dev, uint32_t *ticks) +{ + *ticks = (uint32_t)rtc_stm32_read(dev); + return 0; +} + +#ifdef CONFIG_COUNTER_RTC_STM32_SUBSECONDS +static int rtc_stm32_get_value_64(const struct device *dev, uint64_t *ticks) { *ticks = rtc_stm32_read(dev); return 0; } +#endif /* CONFIG_COUNTER_RTC_STM32_SUBSECONDS */ + +#ifdef CONFIG_COUNTER_RTC_STM32_SUBSECONDS +static void rtc_stm32_set_int_pending(void) +{ + NVIC_SetPendingIRQ(DT_INST_IRQN(0)); +} +#endif /* CONFIG_COUNTER_RTC_STM32_SUBSECONDS */ static int rtc_stm32_set_alarm(const struct device *dev, uint8_t chan_id, const struct counter_alarm_cfg *alarm_cfg) { #if !defined(COUNTER_NO_DATE) struct tm alarm_tm; - time_t alarm_val; + time_t alarm_val_s; +#ifdef CONFIG_COUNTER_RTC_STM32_SUBSECONDS + uint32_t alarm_val_ss; +#endif /* CONFIG_COUNTER_RTC_STM32_SUBSECONDS */ #else uint32_t remain; #endif LL_RTC_AlarmTypeDef rtc_alarm; struct rtc_stm32_data *data = dev->data; - uint32_t now = rtc_stm32_read(dev); - uint32_t ticks = alarm_cfg->ticks; + tick_t now = rtc_stm32_read(dev); + tick_t ticks = alarm_cfg->ticks; if (data->callback != NULL) { LOG_DBG("Alarm busy\n"); @@ -247,11 +358,14 @@ static int rtc_stm32_set_alarm(const struct device *dev, uint8_t chan_id, * that tick+1 event occurs before alarm setting is finished. */ ticks += now + 1; - alarm_val = (time_t)(counter_ticks_to_us(dev, ticks) / USEC_PER_SEC) - + T_TIME_OFFSET; + alarm_val_s = (time_t)(ticks / counter_get_frequency(dev)) + T_TIME_OFFSET; } else { - alarm_val = (time_t)(counter_ticks_to_us(dev, ticks) / USEC_PER_SEC); + alarm_val_s = (time_t)(ticks / counter_get_frequency(dev)); } +#ifdef CONFIG_COUNTER_RTC_STM32_SUBSECONDS + alarm_val_ss = ticks % counter_get_frequency(dev); +#endif /* CONFIG_COUNTER_RTC_STM32_SUBSECONDS */ + #else if ((alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) == 0) { remain = ticks + now + 1; @@ -266,9 +380,13 @@ static int rtc_stm32_set_alarm(const struct device *dev, uint8_t chan_id, #endif #if !defined(COUNTER_NO_DATE) +#ifndef CONFIG_COUNTER_RTC_STM32_SUBSECONDS LOG_DBG("Set Alarm: %d\n", ticks); +#else /* !CONFIG_COUNTER_RTC_STM32_SUBSECONDS */ + LOG_DBG("Set Alarm: %llu\n", ticks); +#endif /* CONFIG_COUNTER_RTC_STM32_SUBSECONDS */ - gmtime_r(&alarm_val, &alarm_tm); + gmtime_r(&alarm_val_s, &alarm_tm); /* Apply ALARM_A */ rtc_alarm.AlarmTime.TimeFormat = LL_RTC_TIME_FORMAT_AM_OR_24; @@ -296,11 +414,34 @@ static int rtc_stm32_set_alarm(const struct device *dev, uint8_t chan_id, } LL_RTC_DisableWriteProtection(RTC); +#ifdef CONFIG_COUNTER_RTC_STM32_SUBSECONDS + /* Care about all bits of the subsecond register */ + LL_RTC_ALMA_SetSubSecondMask(RTC, 0xF); + LL_RTC_ALMA_SetSubSecond(RTC, RTC_SYNCPRE - alarm_val_ss); +#endif /* CONFIG_COUNTER_RTC_STM32_SUBSECONDS */ ll_func_enable_alarm(RTC); ll_func_clear_alarm_flag(RTC); ll_func_enable_interrupt_alarm(RTC); LL_RTC_EnableWriteProtection(RTC); +#ifdef CONFIG_COUNTER_RTC_STM32_SUBSECONDS + /* The reference manual says: + * "Each change of the RTC_CR register is taken into account after + * 1 to 2 RTCCLK clock cycles due to clock synchronization." + * It means we need at least two cycles after programming the CR + * register. It is confirmed experimentally. + * + * It should happen only if one tick alarm is requested and a tick + * occurs while processing the function. Trigger the irq manually in + * this case. + */ + now = rtc_stm32_read(dev); + if ((ticks - now < 2) || (now > ticks)) { + data->irq_on_late = 1; + rtc_stm32_set_int_pending(); + } +#endif /* CONFIG_COUNTER_RTC_STM32_SUBSECONDS */ + return 0; } @@ -357,13 +498,20 @@ void rtc_stm32_isr(const struct device *dev) uint32_t now = rtc_stm32_read(dev); - if (ll_func_is_active_alarm(RTC) != 0) { + if (ll_func_is_active_alarm(RTC) != 0 +#ifdef CONFIG_COUNTER_RTC_STM32_SUBSECONDS + || (data->irq_on_late && ll_func_isenabled_interrupt_alarm(RTC)) +#endif /* CONFIG_COUNTER_RTC_STM32_SUBSECONDS */ + ) { LL_RTC_DisableWriteProtection(RTC); ll_func_clear_alarm_flag(RTC); ll_func_disable_interrupt_alarm(RTC); ll_func_disable_alarm(RTC); LL_RTC_EnableWriteProtection(RTC); +#ifdef CONFIG_COUNTER_RTC_STM32_SUBSECONDS + data->irq_on_late = 0; +#endif /* CONFIG_COUNTER_RTC_STM32_SUBSECONDS */ if (alarm_callback != NULL) { data->callback = NULL; @@ -378,7 +526,7 @@ void rtc_stm32_isr(const struct device *dev) || defined(CONFIG_SOC_SERIES_STM32L5X) \ || defined(CONFIG_SOC_SERIES_STM32H5X) LL_EXTI_ClearRisingFlag_0_31(RTC_EXTI_LINE); -#elif defined(CONFIG_SOC_SERIES_STM32U5X) +#elif defined(CONFIG_SOC_SERIES_STM32U5X) || defined(CONFIG_SOC_SERIES_STM32WBAX) /* in STM32U5 family RTC is not connected to EXTI */ #else LL_EXTI_ClearFlag_0_31(RTC_EXTI_LINE); @@ -420,7 +568,9 @@ static int rtc_stm32_init(const struct device *dev) return -EIO; } +#if !defined(CONFIG_SOC_SERIES_STM32WBAX) LL_RCC_EnableRTC(); +#endif z_stm32_hsem_unlock(CFG_HW_RCC_SEMID); @@ -444,7 +594,7 @@ static int rtc_stm32_init(const struct device *dev) #if defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4) LL_C2_EXTI_EnableIT_0_31(RTC_EXTI_LINE); LL_EXTI_EnableRisingTrig_0_31(RTC_EXTI_LINE); -#elif defined(CONFIG_SOC_SERIES_STM32U5X) +#elif defined(CONFIG_SOC_SERIES_STM32U5X) || defined(CONFIG_SOC_SERIES_STM32WBAX) /* in STM32U5 family RTC is not connected to EXTI */ #else LL_EXTI_EnableIT_0_31(RTC_EXTI_LINE); @@ -477,30 +627,21 @@ static const struct stm32_pclken rtc_clk[] = STM32_DT_INST_CLOCKS(0); static const struct rtc_stm32_config rtc_config = { .counter_info = { .max_top_value = UINT32_MAX, - .freq = 1, +#ifndef CONFIG_COUNTER_RTC_STM32_SUBSECONDS + /* freq = 1Hz for not subsec based driver */ + .freq = RTCCLK_FREQ / ((RTC_ASYNCPRE + 1) * (RTC_SYNCPRE + 1)), +#else /* !CONFIG_COUNTER_RTC_STM32_SUBSECONDS */ + .freq = RTCCLK_FREQ / (RTC_ASYNCPRE + 1), +#endif /* CONFIG_COUNTER_RTC_STM32_SUBSECONDS */ .flags = COUNTER_CONFIG_INFO_COUNT_UP, .channels = 1, }, .ll_rtc_config = { + .AsynchPrescaler = RTC_ASYNCPRE, #if !defined(CONFIG_SOC_SERIES_STM32F1X) .HourFormat = LL_RTC_HOURFORMAT_24HOUR, -#if DT_INST_CLOCKS_CELL(1, bus) == STM32_SRC_LSI - /* prescaler values for LSI @ 32 KHz */ - .AsynchPrescaler = 0x7F, - .SynchPrescaler = 0x00F9, -#else /* DT_INST_CLOCKS_CELL(1, bus) == STM32_SRC_LSE */ - /* prescaler values for LSE @ 32768 Hz */ - .AsynchPrescaler = 0x7F, - .SynchPrescaler = 0x00FF, -#endif + .SynchPrescaler = RTC_SYNCPRE, #else /* CONFIG_SOC_SERIES_STM32F1X */ -#if DT_INST_CLOCKS_CELL(1, bus) == STM32_SRC_LSI - /* prescaler values for LSI @ 40 KHz */ - .AsynchPrescaler = 0x9C3F, -#else /* DT_INST_CLOCKS_CELL(1, bus) == STM32_SRC_LSE */ - /* prescaler values for LSE @ 32768 Hz */ - .AsynchPrescaler = 0x7FFF, -#endif /* DT_INST_CLOCKS_CELL(1, bus) == STM32_SRC_LSE */ .OutPutSource = LL_RTC_CALIB_OUTPUT_NONE, #endif /* CONFIG_SOC_SERIES_STM32F1X */ }, @@ -509,14 +650,17 @@ static const struct rtc_stm32_config rtc_config = { static const struct counter_driver_api rtc_stm32_driver_api = { - .start = rtc_stm32_start, - .stop = rtc_stm32_stop, - .get_value = rtc_stm32_get_value, - .set_alarm = rtc_stm32_set_alarm, - .cancel_alarm = rtc_stm32_cancel_alarm, - .set_top_value = rtc_stm32_set_top_value, - .get_pending_int = rtc_stm32_get_pending_int, - .get_top_value = rtc_stm32_get_top_value, + .start = rtc_stm32_start, + .stop = rtc_stm32_stop, + .get_value = rtc_stm32_get_value, +#ifdef CONFIG_COUNTER_RTC_STM32_SUBSECONDS + .get_value_64 = rtc_stm32_get_value_64, +#endif /* CONFIG_COUNTER_RTC_STM32_SUBSECONDS */ + .set_alarm = rtc_stm32_set_alarm, + .cancel_alarm = rtc_stm32_cancel_alarm, + .set_top_value = rtc_stm32_set_top_value, + .get_pending_int = rtc_stm32_get_pending_int, + .get_top_value = rtc_stm32_get_top_value, }; DEVICE_DT_INST_DEFINE(0, &rtc_stm32_init, NULL, diff --git a/drivers/counter/counter_mcux_lpc_rtc.c b/drivers/counter/counter_mcux_lpc_rtc.c index 18cafe1272d..2bb8d920fea 100644 --- a/drivers/counter/counter_mcux_lpc_rtc.c +++ b/drivers/counter/counter_mcux_lpc_rtc.c @@ -16,9 +16,7 @@ LOG_MODULE_REGISTER(mcux_rtc, CONFIG_COUNTER_LOG_LEVEL); struct mcux_lpc_rtc_data { counter_alarm_callback_t alarm_callback; - counter_top_callback_t top_callback; void *alarm_user_data; - void *top_user_data; }; struct mcux_lpc_rtc_config { @@ -35,7 +33,7 @@ static int mcux_lpc_rtc_start(const struct device *dev) const struct mcux_lpc_rtc_config *config = CONTAINER_OF(info, struct mcux_lpc_rtc_config, info); - RTC_StartTimer(config->base); + RTC_EnableTimer(config->base, true); return 0; } @@ -46,7 +44,7 @@ static int mcux_lpc_rtc_stop(const struct device *dev) const struct mcux_lpc_rtc_config *config = CONTAINER_OF(info, struct mcux_lpc_rtc_config, info); - RTC_StopTimer(config->base); + RTC_EnableTimer(config->base, false); /* clear out any set alarms */ RTC_SetSecondsTimerMatch(config->base, 0); @@ -128,26 +126,7 @@ static int mcux_lpc_rtc_cancel_alarm(const struct device *dev, uint8_t chan_id) static int mcux_lpc_rtc_set_top_value(const struct device *dev, const struct counter_top_cfg *cfg) { - const struct counter_config_info *info = dev->config; - const struct mcux_lpc_rtc_config *config = - CONTAINER_OF(info, struct mcux_lpc_rtc_config, info); - struct mcux_lpc_rtc_data *data = dev->data; - - if (cfg->ticks != info->max_top_value) { - LOG_ERR("Wrap can only be set to 0x%x.", info->max_top_value); - return -ENOTSUP; - } - - if (!(cfg->flags & COUNTER_TOP_CFG_DONT_RESET)) { - RTC_StopTimer(config->base); - RTC_SetSecondsTimerCount(config->base, 0); - RTC_StartTimer(config->base); - } - - data->top_callback = cfg->callback; - data->top_user_data = cfg->user_data; - - return 0; + return -ENOTSUP; } static uint32_t mcux_lpc_rtc_get_pending_int(const struct device *dev) @@ -174,6 +153,7 @@ static void mcux_lpc_rtc_isr(const struct device *dev) struct mcux_lpc_rtc_data *data = dev->data; counter_alarm_callback_t cb; uint32_t current = mcux_lpc_rtc_read(dev); + uint32_t enable = (config->base->CTRL & RTC_CTRL_RTC_EN_MASK); LOG_DBG("Current time is %d ticks", current); @@ -185,21 +165,19 @@ static void mcux_lpc_rtc_isr(const struct device *dev) cb(dev, 0, current, data->alarm_user_data); } - if (data->top_callback) { - data->top_callback(dev, data->top_user_data); - } - /* * Clear any conditions to ack the IRQ * * callback may have already reset the alarm flag if a new * alarm value was programmed to the TAR */ - RTC_StopTimer(config->base); + RTC_EnableTimer(config->base, false); if (RTC_GetStatusFlags(config->base) & RTC_CTRL_ALARM1HZ_MASK) { RTC_ClearStatusFlags(config->base, kRTC_AlarmFlag); } - RTC_StartTimer(config->base); + if (enable) { + RTC_EnableTimer(config->base, true); + } } static int mcux_lpc_rtc_init(const struct device *dev) @@ -210,6 +188,9 @@ static int mcux_lpc_rtc_init(const struct device *dev) RTC_Init(config->base); + /* Issue a software reset to set the registers to init state */ + RTC_Reset(config->base); + config->irq_config_func(dev); if (config->wakeup_source) { diff --git a/drivers/counter/counter_mcux_pit.c b/drivers/counter/counter_mcux_pit.c index 19bfad4e125..94e57bd4325 100644 --- a/drivers/counter/counter_mcux_pit.c +++ b/drivers/counter/counter_mcux_pit.c @@ -1,5 +1,5 @@ /* - * Copyright 2020 NXP + * Copyright 2020,2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,6 +7,7 @@ #define DT_DRV_COMPAT nxp_kinetis_pit #include +#include #include #include @@ -19,13 +20,14 @@ struct mcux_pit_config { PIT_Type *base; bool enableRunInDebug; pit_chnl_t pit_channel; + uint32_t pit_period; void (*irq_config_func)(const struct device *dev); + const struct device *clock_dev; + clock_control_subsys_t clock_subsys; }; struct mcux_pit_data { - counter_alarm_callback_t alarm_callback; counter_top_callback_t top_callback; - void *alarm_user_data; void *top_user_data; }; @@ -115,12 +117,24 @@ static uint32_t mcux_pit_get_pending_int(const struct device *dev) return ((flags & mask) == mask); } +static uint32_t mcux_pit_get_frequency(const struct device *dev) +{ + const struct mcux_pit_config *config = dev->config; + uint32_t clock_rate; + + if (clock_control_get_rate(config->clock_dev, config->clock_subsys, &clock_rate)) { + LOG_ERR("Failed to get clock rate"); + return 0; + } + + return clock_rate; +} + static void mcux_pit_isr(const struct device *dev) { const struct mcux_pit_config *config = dev->config; struct mcux_pit_data *data = dev->data; uint32_t flags; - uint32_t current = 0; LOG_DBG("pit counter isr"); flags = PIT_GetStatusFlags(config->base, config->pit_channel); @@ -128,64 +142,19 @@ static void mcux_pit_isr(const struct device *dev) if (data->top_callback) { data->top_callback(dev, data->top_user_data); } - if (data->alarm_callback) { - PIT_StopTimer(config->base, config->pit_channel); - mcux_pit_get_value(dev, ¤t); - data->alarm_callback(dev, config->pit_channel, current, - data->alarm_user_data); - } } -static int mcux_pit_set_alarm(const struct device *dev, uint8_t chan_id, - const struct counter_alarm_cfg *alarm_cfg) -{ - const struct mcux_pit_config *config = dev->config; - struct mcux_pit_data *data = dev->data; - - uint32_t ticks = alarm_cfg->ticks; - - if (chan_id != DT_INST_PROP(0, pit_channel)) { - LOG_ERR("Invalid channel id"); - return -EINVAL; - } - - if (ticks > mcux_pit_get_top_value(dev)) { - LOG_ERR("Invalid ticks"); - return -EINVAL; - } - - PIT_StopTimer(config->base, chan_id); - PIT_SetTimerPeriod(config->base, chan_id, ticks); - data->alarm_callback = alarm_cfg->callback; - data->alarm_user_data = alarm_cfg->user_data; - LOG_DBG("set alarm to %d", ticks); - PIT_StartTimer(config->base, chan_id); - return 0; -} - -static int mcux_pit_cancel_alarm(const struct device *dev, uint8_t chan_id) +static int mcux_pit_init(const struct device *dev) { const struct mcux_pit_config *config = dev->config; - struct mcux_pit_data *data = dev->data; + pit_config_t pit_config; + uint32_t clock_rate; - if (chan_id != DT_INST_PROP(0, pit_channel)) { - LOG_ERR("Invalid channel id"); - return -EINVAL; + if (!device_is_ready(config->clock_dev)) { + LOG_ERR("Clock control device not ready"); + return -ENODEV; } - PIT_DisableInterrupts(config->base, chan_id, kPIT_TimerInterruptEnable); - PIT_StopTimer(config->base, chan_id); - data->alarm_callback = NULL; - - return 0; -} - -static int mcux_pit_init(const struct device *dev) -{ - const struct mcux_pit_config *config = - (struct mcux_pit_config *)dev->config; - pit_config_t pit_config; - PIT_GetDefaultConfig(&pit_config); pit_config.enableRunInDebug = config->enableRunInDebug; @@ -193,9 +162,9 @@ static int mcux_pit_init(const struct device *dev) config->irq_config_func(dev); + clock_rate = mcux_pit_get_frequency(dev); PIT_SetTimerPeriod(config->base, config->pit_channel, - USEC_TO_COUNT(DT_INST_PROP(0, pit_period), - CLOCK_GetFreq(kCLOCK_BusClk))); + USEC_TO_COUNT(config->pit_period, clock_rate)); return 0; } @@ -205,54 +174,46 @@ static const struct counter_driver_api mcux_pit_driver_api = { .stop = mcux_pit_stop, .get_value = mcux_pit_get_value, .set_top_value = mcux_pit_set_top_value, - .set_alarm = mcux_pit_set_alarm, - .cancel_alarm = mcux_pit_cancel_alarm, .get_pending_int = mcux_pit_get_pending_int, .get_top_value = mcux_pit_get_top_value, + .get_freq = mcux_pit_get_frequency, }; -/* - * This driver is single-instance. If the devicetree contains multiple - * instances, this will fail and the driver needs to be revisited. - */ -BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) <= 1, - "unsupported pit instance"); - -static struct mcux_pit_data mcux_pit_data_0; - -static void mcux_pit_irq_config_0(const struct device *dev); - -static const struct mcux_pit_config mcux_pit_config_0 = { - .info = { - .max_top_value = UINT32_MAX, - .channels = 1, - .freq = DT_INST_PROP(0, clock_frequency), - }, - .base = (PIT_Type *)DT_INST_REG_ADDR(0), - .pit_channel = DT_INST_PROP(0, pit_channel), - .irq_config_func = mcux_pit_irq_config_0, -}; - -DEVICE_DT_INST_DEFINE(0, &mcux_pit_init, NULL, - &mcux_pit_data_0, &mcux_pit_config_0, POST_KERNEL, - CONFIG_COUNTER_INIT_PRIORITY, &mcux_pit_driver_api); +#define COUNTER_MCUX_PIT_IRQ_CONFIG(idx, n) \ + do { \ + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, idx, irq), \ + DT_INST_IRQ_BY_IDX(n, idx, priority), \ + mcux_pit_isr, DEVICE_DT_INST_GET(n), \ + COND_CODE_1(DT_INST_IRQ_HAS_NAME(n, flags), \ + (DT_INST_IRQ_BY_IDX(n, idx, flags)), (0))); \ + irq_enable(DT_INST_IRQ_BY_IDX(n, idx, irq)); \ + } while (0) + +#define COUNTER_MCUX_PIT_DEVICE(n) \ + static void mcux_pit_irq_config_##n(const struct device *dev); \ + static struct mcux_pit_data mcux_pit_data_##n; \ + static const struct mcux_pit_config mcux_pit_config_##n = { \ + .info = { \ + .max_top_value = DT_INST_PROP(n, max_load_value), \ + .channels = 0, \ + }, \ + .base = (PIT_Type *)DT_INST_REG_ADDR(n), \ + .pit_channel = DT_INST_PROP(n, pit_channel), \ + .pit_period = DT_INST_PROP(n, pit_period), \ + .irq_config_func = mcux_pit_irq_config_##n, \ + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ + .clock_subsys = (clock_control_subsys_t) \ + DT_INST_CLOCKS_CELL(n, name), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, &mcux_pit_init, NULL, \ + &mcux_pit_data_##n, &mcux_pit_config_##n, POST_KERNEL, \ + CONFIG_COUNTER_INIT_PRIORITY, &mcux_pit_driver_api); \ + \ + static void mcux_pit_irq_config_##n(const struct device *dev) \ + { \ + LISTIFY(DT_NUM_IRQS(DT_DRV_INST(n)), \ + COUNTER_MCUX_PIT_IRQ_CONFIG, (;), n); \ + } -static void mcux_pit_irq_config_0(const struct device *dev) -{ - IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, 0, irq), - DT_INST_IRQ_BY_IDX(0, 0, priority), mcux_pit_isr, - DEVICE_DT_INST_GET(0), 0); - irq_enable(DT_INST_IRQ_BY_IDX(0, 0, irq)); - IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, 1, irq), - DT_INST_IRQ_BY_IDX(0, 1, priority), mcux_pit_isr, - DEVICE_DT_INST_GET(0), 0); - irq_enable(DT_INST_IRQ_BY_IDX(0, 1, irq)); - IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, 2, irq), - DT_INST_IRQ_BY_IDX(0, 2, priority), mcux_pit_isr, - DEVICE_DT_INST_GET(0), 0); - irq_enable(DT_INST_IRQ_BY_IDX(0, 2, irq)); - IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, 3, irq), - DT_INST_IRQ_BY_IDX(0, 3, priority), mcux_pit_isr, - DEVICE_DT_INST_GET(0), 0); - irq_enable(DT_INST_IRQ_BY_IDX(0, 3, irq)); -} +DT_INST_FOREACH_STATUS_OKAY(COUNTER_MCUX_PIT_DEVICE) diff --git a/drivers/counter/counter_native_posix.c b/drivers/counter/counter_native_posix.c index aa221a11fdc..d03517b1b86 100644 --- a/drivers/counter/counter_native_posix.c +++ b/drivers/counter/counter_native_posix.c @@ -6,6 +6,7 @@ #define DT_DRV_COMPAT zephyr_native_posix_counter +#include #include #include #include @@ -14,38 +15,80 @@ #include #define DRIVER_CONFIG_INFO_FLAGS (COUNTER_CONFIG_INFO_COUNT_UP) -#define DRIVER_CONFIG_INFO_CHANNELS 1 +#define DRIVER_CONFIG_INFO_CHANNELS CONFIG_COUNTER_NATIVE_POSIX_NBR_CHANNELS #define COUNTER_NATIVE_POSIX_IRQ_FLAGS (0) #define COUNTER_NATIVE_POSIX_IRQ_PRIORITY (2) #define COUNTER_PERIOD (USEC_PER_SEC / CONFIG_COUNTER_NATIVE_POSIX_FREQUENCY) #define TOP_VALUE (UINT_MAX) -static struct counter_alarm_cfg pending_alarm; -static bool is_alarm_pending; +static struct counter_alarm_cfg pending_alarm[DRIVER_CONFIG_INFO_CHANNELS]; +static bool is_alarm_pending[DRIVER_CONFIG_INFO_CHANNELS]; +static struct counter_top_cfg top; +static bool is_top_set; static const struct device *device; +static void schedule_next_isr(void) +{ + int64_t current_value = hw_counter_get_value(); + uint32_t next_time = top.ticks; /* top.ticks is TOP_VALUE if is_top_set == false */ + + if (current_value == top.ticks) { + current_value = -1; + } + + for (int i = 0; i < DRIVER_CONFIG_INFO_CHANNELS; i++) { + if (is_alarm_pending[i]) { + if (pending_alarm[i].ticks > current_value) { + /* If the alarm is not after a wrap */ + next_time = MIN(pending_alarm[i].ticks, next_time); + } + } + } + + /* We will at least get an interrupt at top.ticks even if is_top_set == false, + * which is fine. We may use that to set the next alarm if needed + */ + hw_counter_set_target(next_time); +} + static void counter_isr(const void *arg) { ARG_UNUSED(arg); uint32_t current_value = hw_counter_get_value(); - if (is_alarm_pending) { - is_alarm_pending = false; - pending_alarm.callback(device, 0, current_value, - pending_alarm.user_data); + for (int i = 0; i < DRIVER_CONFIG_INFO_CHANNELS; i++) { + if (is_alarm_pending[i] && (current_value == pending_alarm[i].ticks)) { + is_alarm_pending[i] = false; + if (pending_alarm[i].callback) { + pending_alarm[i].callback(device, i, current_value, + pending_alarm[i].user_data); + } + } + } + + if (is_top_set && (current_value == top.ticks)) { + if (top.callback) { + top.callback(device, top.user_data); + } } + + schedule_next_isr(); } static int ctr_init(const struct device *dev) { device = dev; - is_alarm_pending = false; + memset(is_alarm_pending, 0, sizeof(is_alarm_pending)); + is_top_set = false; + top.ticks = TOP_VALUE; IRQ_CONNECT(COUNTER_EVENT_IRQ, COUNTER_NATIVE_POSIX_IRQ_PRIORITY, counter_isr, NULL, COUNTER_NATIVE_POSIX_IRQ_FLAGS); + irq_enable(COUNTER_EVENT_IRQ); hw_counter_set_period(COUNTER_PERIOD); - hw_counter_set_target(TOP_VALUE); + hw_counter_set_wrap_value((uint64_t)top.ticks + 1); + hw_counter_reset(); return 0; } @@ -54,6 +97,7 @@ static int ctr_start(const struct device *dev) { ARG_UNUSED(dev); + schedule_next_isr(); hw_counter_start(); return 0; } @@ -80,19 +124,56 @@ static uint32_t ctr_get_pending_int(const struct device *dev) return 0; } +static bool is_any_alarm_pending(void) +{ + for (int i = 0; i < DRIVER_CONFIG_INFO_CHANNELS; i++) { + if (is_alarm_pending[i]) { + return true; + } + } + return false; +} + static int ctr_set_top_value(const struct device *dev, const struct counter_top_cfg *cfg) { ARG_UNUSED(dev); - ARG_UNUSED(cfg); - posix_print_warning("%s not supported\n", __func__); - return -ENOTSUP; + if (is_any_alarm_pending()) { + posix_print_warning("Can't set top value while alarm is active\n"); + return -EBUSY; + } + + uint32_t current_value = hw_counter_get_value(); + + if (cfg->flags & COUNTER_TOP_CFG_DONT_RESET) { + if (current_value >= cfg->ticks) { + if (cfg->flags & COUNTER_TOP_CFG_RESET_WHEN_LATE) { + hw_counter_reset(); + } + return -ETIME; + } + } else { + hw_counter_reset(); + } + + top = *cfg; + hw_counter_set_wrap_value((uint64_t)top.ticks + 1); + + if ((cfg->ticks == TOP_VALUE) && !cfg->callback) { + is_top_set = false; + } else { + is_top_set = true; + } + + schedule_next_isr(); + + return 0; } static uint32_t ctr_get_top_value(const struct device *dev) { - return TOP_VALUE; + return top.ticks; } static int ctr_set_alarm(const struct device *dev, uint8_t chan_id, @@ -100,21 +181,31 @@ static int ctr_set_alarm(const struct device *dev, uint8_t chan_id, { ARG_UNUSED(dev); - if (chan_id >= DRIVER_CONFIG_INFO_CHANNELS) { - posix_print_warning("channel %u is not supported\n", chan_id); - return -ENOTSUP; - } + if (is_alarm_pending[chan_id]) + return -EBUSY; - pending_alarm = *alarm_cfg; - is_alarm_pending = true; + uint32_t ticks = alarm_cfg->ticks; + + if (ticks > top.ticks) { + posix_print_warning("Alarm ticks %u exceed top ticks %u\n", ticks, + top.ticks); + return -EINVAL; + } if (!(alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE)) { - pending_alarm.ticks = - hw_counter_get_value() + pending_alarm.ticks; + uint32_t current_value = hw_counter_get_value(); + + ticks += current_value; + if (ticks > top.ticks) { /* Handle wrap arounds */ + ticks -= (top.ticks + 1); /* The count period is top.ticks + 1 */ + } } - hw_counter_set_target(pending_alarm.ticks); - irq_enable(COUNTER_EVENT_IRQ); + pending_alarm[chan_id] = *alarm_cfg; + pending_alarm[chan_id].ticks = ticks; + is_alarm_pending[chan_id] = true; + + schedule_next_isr(); return 0; } @@ -123,12 +214,14 @@ static int ctr_cancel_alarm(const struct device *dev, uint8_t chan_id) { ARG_UNUSED(dev); - if (chan_id >= DRIVER_CONFIG_INFO_CHANNELS) { - posix_print_warning("channel %u is not supported\n", chan_id); + if (!hw_counter_is_started()) { + posix_print_warning("Counter not started\n"); return -ENOTSUP; } - is_alarm_pending = false; + is_alarm_pending[chan_id] = false; + + schedule_next_isr(); return 0; } diff --git a/drivers/counter/counter_nrfx_timer.c b/drivers/counter/counter_nrfx_timer.c index df5b6175257..caf2c5852e4 100644 --- a/drivers/counter/counter_nrfx_timer.c +++ b/drivers/counter/counter_nrfx_timer.c @@ -253,6 +253,7 @@ static int set_top_value(const struct device *dev, nrf_timer_int_disable(timer, COUNTER_TOP_INT_MASK); nrf_timer_cc_set(timer, TOP_CH, cfg->ticks); + nrf_timer_event_clear(timer, COUNTER_TOP_EVT); nrf_timer_shorts_enable(timer, COUNTER_OVERFLOW_SHORT); data->top_cb = cfg->callback; diff --git a/drivers/counter/counter_nxp_mrt.c b/drivers/counter/counter_nxp_mrt.c new file mode 100644 index 00000000000..741e7b34d40 --- /dev/null +++ b/drivers/counter/counter_nxp_mrt.c @@ -0,0 +1,341 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * MRT (Multirate timer) is a lightweight timer with multiple independent channels, each capable + * of signalling the shared interrupt with a different period. This driver treats all the channels + * as separate devices adhering to the counter API. The parent device is responsible for the + * initialization, interrupt handling, and any other module-wide tasks. The current implementation + * of this driver prioritizes minimizing image size over speed, because it is not expected for the + * functions to be called very often, and this IP is mostly present on low memory devices. + */ + +#define DT_DRV_COMPAT nxp_mrt + +#include +#include +#include +#include +#include +#include + +#define LOG_MODULE_NAME counter_mrt +#include +LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_COUNTER_LOG_LEVEL); + +/* Device holds a pointer to pointer to data */ +#define MRT_CHANNEL_DATA(dev) \ + (*(struct nxp_mrt_channel_data *const *const)dev->data) + +/* Device config->data is an array of data pointers ordered by channel number, + * dev->data is a pointer to one of these pointers in that array, + * so the value of the dev->data - dev->config->data is the channel index + */ +#define MRT_CHANNEL_ID(dev) \ + (((struct nxp_mrt_channel_data *const *)dev->data) - \ + ((const struct nxp_mrt_config *)dev->config)->data) + +/* Specific for each channel */ +struct nxp_mrt_channel_data { + uint32_t top; + counter_top_callback_t cb; + void *user_data; +}; + +/* Shared between all channels */ +struct nxp_mrt_config { + struct counter_config_info info; + MRT_Type *base; + const struct device *clock_dev; + clock_control_subsys_t clock_subsys; + void (*irq_config_func)(const struct device *dev); + struct nxp_mrt_channel_data *const *data; + const struct device *const *channels; +}; + +static int nxp_mrt_stop(const struct device *dev) +{ + const struct nxp_mrt_config *config = dev->config; + MRT_Type *base = config->base; + int channel_id = MRT_CHANNEL_ID(dev); + + LOG_DBG("MRT@%p channel %d stopped", base, channel_id); + LOG_WRN("MRT channel resets upon stopping"); + + /* LOAD bit and 0 ivalue allows us to forcibly stop the timer */ + base->CHANNEL[channel_id].INTVAL = MRT_CHANNEL_INTVAL_LOAD(1); + + return 0; +} + +static int nxp_mrt_start(const struct device *dev) +{ + const struct nxp_mrt_config *config = dev->config; + MRT_Type *base = config->base; + struct nxp_mrt_channel_data *data = MRT_CHANNEL_DATA(dev); + int channel_id = MRT_CHANNEL_ID(dev); + + if (data->top <= 1) { + /* Zephyr API says default should be max top value */ + LOG_INF("\"Started\" MRT@%p channel %d with default value %d", + base, channel_id, config->info.max_top_value); + data->top = config->info.max_top_value; + } + + /* Start with previously configured top value (if already running this has no effect) */ + base->CHANNEL[channel_id].INTVAL = data->top; + + LOG_DBG("MRT@%p channel %d started with top value %d", base, channel_id, data->top); + + return 0; +} + +static int nxp_mrt_get_value(const struct device *dev, uint32_t *ticks) +{ + const struct nxp_mrt_config *config = dev->config; + MRT_Type *base = config->base; + int channel_id = MRT_CHANNEL_ID(dev); + + *ticks = base->CHANNEL[channel_id].TIMER & MRT_CHANNEL_TIMER_VALUE_MASK; + + return 0; +} + + +static int nxp_mrt_set_top_value(const struct device *dev, const struct counter_top_cfg *cfg) +{ + const struct nxp_mrt_config *config = dev->config; + MRT_Type *base = config->base; + struct nxp_mrt_channel_data *data = MRT_CHANNEL_DATA(dev); + int channel_id = MRT_CHANNEL_ID(dev); + /* By default in Zephyr API, the counter resets on changing top value */ + bool reset = !(cfg->flags & COUNTER_TOP_CFG_DONT_RESET); + bool active = base->CHANNEL[channel_id].STAT & MRT_CHANNEL_STAT_RUN_MASK; + uint32_t current_val = base->CHANNEL[channel_id].TIMER & MRT_CHANNEL_TIMER_VALUE_MASK; + int ret = 0; + + /* Store for use by counter_start */ + data->top = cfg->ticks; + + /* Used by ISR */ + data->cb = cfg->callback; + data->user_data = cfg->user_data; + + + /* If not yet started, wait for counter_start because setting reg value starts timer */ + if (!active) { + LOG_DBG("Set MRT@%p channel %d top value to %d", base, channel_id, data->top); + return ret; + } + + /* Otherwise if currently running, need to check for lateness */ + if (cfg->ticks < current_val) { + LOG_WRN("MRT@%p channel %d received requested top value %d which is " + "smaller than current count %d", + base, channel_id, cfg->ticks, current_val); + /* Zephyr API says return this error in case of lateness + * when COUNTER_TOP_CFG_DONT_RESET is set but can still set period + */ + ret = reset ? 0 : -ETIME; + /* If user said not to reset, they can also clarify exception for lateness */ + reset |= cfg->flags & COUNTER_TOP_CFG_RESET_WHEN_LATE; + } + + /* Sets the top value. If we need to reset, LOAD bit does this */ + base->CHANNEL[channel_id].INTVAL = MRT_CHANNEL_INTVAL_IVALUE(cfg->ticks) | + MRT_CHANNEL_INTVAL_LOAD(reset ? 1 : 0); + + LOG_DBG("Changed MRT@%p channel %d top value while active to %d", + base, channel_id, + base->CHANNEL[channel_id].INTVAL & MRT_CHANNEL_INTVAL_IVALUE_MASK); + + return ret; +} + +static uint32_t nxp_mrt_get_top_value(const struct device *dev) +{ + const struct nxp_mrt_config *config = dev->config; + MRT_Type *base = config->base; + int channel_id = MRT_CHANNEL_ID(dev); + + return base->CHANNEL[channel_id].INTVAL & MRT_CHANNEL_INTVAL_IVALUE_MASK; +} + +static uint32_t nxp_mrt_get_pending_int(const struct device *dev) +{ + const struct nxp_mrt_config *config = dev->config; + MRT_Type *base = config->base; + int channel_id = MRT_CHANNEL_ID(dev); + + return base->CHANNEL[channel_id].STAT & MRT_CHANNEL_STAT_INTFLAG_MASK; +} + +static inline int nxp_mrt_set_alarm(const struct device *dev, + uint8_t chan_id, + const struct counter_alarm_cfg *alarm_cfg) +{ + ARG_UNUSED(dev); + ARG_UNUSED(chan_id); + ARG_UNUSED(alarm_cfg); + + LOG_ERR("MRT does not support alarms"); + return -ENOTSUP; +} + +static inline int nxp_mrt_cancel_alarm(const struct device *dev, uint8_t chan_id) +{ + ARG_UNUSED(dev); + ARG_UNUSED(chan_id); + + LOG_ERR("MRT does not support alarms"); + return -ENOTSUP; +} + +uint32_t nxp_mrt_get_freq(const struct device *dev) +{ + const struct nxp_mrt_config *config = dev->config; + uint32_t freq; + + clock_control_get_rate(config->clock_dev, config->clock_subsys, &freq); + + return freq; +} + +static int nxp_mrt_init(const struct device *dev) +{ + const struct nxp_mrt_config *config = dev->config; + MRT_Type *base = config->base; + uint32_t num_channels = (base->MODCFG & MRT_MODCFG_NOC_MASK) >> MRT_MODCFG_NOC_SHIFT; + + clock_control_on(config->clock_dev, config->clock_subsys); + + config->irq_config_func(dev); + + /* Enable interrupts for all the channels that have devices */ + for (int i = 0; i < num_channels; i++) { + if (config->channels[i]) { + base->CHANNEL[i].CTRL = MRT_CHANNEL_CTRL_INTEN_MASK; + } + } + + return 0; +} + +static void nxp_mrt_isr(const struct device *dev) +{ + const struct nxp_mrt_config *config = dev->config; + MRT_Type *base = config->base; + uint32_t irq_pends = base->IRQ_FLAG; + uint32_t num_channels = (base->MODCFG & MRT_MODCFG_NOC_MASK) >> MRT_MODCFG_NOC_SHIFT; + + for (int i = 0; i < num_channels; i++) { + /* Channel IRQ pending flags lowest order bits in IRQ_FLAG register */ + if (!(irq_pends & (0x1 << i))) { + continue; + } + + LOG_DBG("Handling interrupt for MRT%p channel %d", base, i); + + /* W1C interrupt flag */ + base->CHANNEL[i].STAT |= MRT_CHANNEL_STAT_INTFLAG_MASK; + + /* Channel devs & pointer path to channel cbs is in shared config */ + if (config->data[i]->cb) { + config->data[i]->cb(config->channels[i], config->data[i]->user_data); + } + } +} + +struct counter_driver_api nxp_mrt_api = { + .get_value = nxp_mrt_get_value, + .start = nxp_mrt_start, + .stop = nxp_mrt_stop, + .set_top_value = nxp_mrt_set_top_value, + .get_top_value = nxp_mrt_get_top_value, + .get_pending_int = nxp_mrt_get_pending_int, + .set_alarm = nxp_mrt_set_alarm, + .cancel_alarm = nxp_mrt_cancel_alarm, + .get_freq = nxp_mrt_get_freq, +}; + +/* Creates a device for a channel (needed for counter API) */ +#define NXP_MRT_CHANNEL_DEV_INIT(node, mrt_inst) \ + DEVICE_DT_DEFINE(node, NULL, NULL, \ + (void *) \ + &nxp_mrt_##mrt_inst##_channel_datas[DT_REG_ADDR(node)], \ + &nxp_mrt_##mrt_inst##_config, \ + POST_KERNEL, CONFIG_COUNTER_INIT_PRIORITY, \ + &nxp_mrt_api); \ + +/* Creates a data struct for a channel device */ +#define NXP_MRT_CHANNEL_DATA_INIT(node) \ + static struct nxp_mrt_channel_data \ + nxp_mrt_channel_data_##node; \ + +/* Initializes an element of the channel data pointer array */ +#define NXP_MRT_CHANNEL_DATA_ARRAY_INIT(node) \ + [DT_REG_ADDR(node)] = \ + &nxp_mrt_channel_data_##node, + +/* Initializes an element of the channel device pointer array */ +#define NXP_MRT_CHANNEL_DEV_ARRAY_INIT(node) \ + [DT_REG_ADDR(node)] = DEVICE_DT_GET(node), + +#define NXP_MRT_INIT(n) \ + /* ISR is shared between all channels */ \ + static void nxp_mrt_##n##_irq_config_func(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \ + nxp_mrt_isr, DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + } \ + \ + /* Initialize all the data structs for active channels */ \ + DT_INST_FOREACH_CHILD_STATUS_OKAY(n, NXP_MRT_CHANNEL_DATA_INIT) \ + \ + /* Create an array of const pointers to the data structs */ \ + static struct nxp_mrt_channel_data *const nxp_mrt_##n##_channel_datas \ + [DT_INST_PROP(n, num_channels)] = { \ + DT_INST_FOREACH_CHILD_STATUS_OKAY(n, \ + NXP_MRT_CHANNEL_DATA_ARRAY_INIT) \ + }; \ + \ + /* Forward declaration */ \ + const static struct nxp_mrt_config nxp_mrt_##n##_config; \ + \ + /* Create all the channel/counter devices */ \ + DT_INST_FOREACH_CHILD_STATUS_OKAY_VARGS(n, NXP_MRT_CHANNEL_DEV_INIT, n) \ + \ + /* This channel device array is needed by the module device ISR */ \ + const struct device *const nxp_mrt_##n##_channels \ + [DT_INST_PROP(n, num_channels)] = { \ + DT_INST_FOREACH_CHILD_STATUS_OKAY(n, \ + NXP_MRT_CHANNEL_DEV_ARRAY_INIT) \ + }; \ + \ + /* This config struct is shared by all the channels and parent device */\ + const static struct nxp_mrt_config nxp_mrt_##n##_config = { \ + .info = { \ + .max_top_value = \ + GENMASK(DT_INST_PROP(n, num_bits) - 1, 0), \ + .channels = 0, \ + }, \ + .base = (MRT_Type *)DT_INST_REG_ADDR(n), \ + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ + .clock_subsys = (clock_control_subsys_t) \ + DT_INST_CLOCKS_CELL(n, name), \ + .irq_config_func = nxp_mrt_##n##_irq_config_func, \ + .data = nxp_mrt_##n##_channel_datas, \ + .channels = nxp_mrt_##n##_channels, \ + }; \ + \ + /* Init parent device in order to handle ISR and init. */ \ + DEVICE_DT_INST_DEFINE(n, &nxp_mrt_init, NULL, NULL, \ + &nxp_mrt_##n##_config, \ + POST_KERNEL, \ + CONFIG_COUNTER_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(NXP_MRT_INIT) diff --git a/drivers/counter/counter_nxp_s32_sys_timer.c b/drivers/counter/counter_nxp_s32_sys_timer.c index bdaf62ad7bd..47c1d0e3c3e 100644 --- a/drivers/counter/counter_nxp_s32_sys_timer.c +++ b/drivers/counter/counter_nxp_s32_sys_timer.c @@ -1,10 +1,13 @@ /* - * Copyright 2022 NXP + * Copyright 2022-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ +#define DT_DRV_COMPAT nxp_s32_sys_timer + #include +#include #include #include #include @@ -13,13 +16,8 @@ LOG_MODULE_REGISTER(nxp_s32_sys_timer, CONFIG_COUNTER_LOG_LEVEL); -#define SYS_TIMER_NODE(n) DT_NODELABEL(stm##n) #define SYS_TIMER_MAX_VALUE 0xFFFFFFFFU #define SYS_TIMER_NUM_CHANNELS 4 -#define SYS_TIMER_INSTANCE_ID(n) (n + 3 + CONFIG_NXP_S32_RTU_INDEX * 4) - -#define _SYS_TIMER_ISR(r, n) RTU##r##_STM_##n##_ISR -#define SYS_TIMER_ISR(r, n) _SYS_TIMER_ISR(r, n) struct nxp_s32_sys_timer_chan_data { counter_alarm_callback_t callback; @@ -35,6 +33,8 @@ struct nxp_s32_sys_timer_config { Stm_Ip_InstanceConfigType hw_cfg; Stm_Ip_ChannelConfigType ch_cfg[SYS_TIMER_NUM_CHANNELS]; uint8_t instance; + const struct device *clock_dev; + clock_control_subsys_t clock_subsys; }; static int nxp_s32_sys_timer_start(const struct device *dev) @@ -116,7 +116,7 @@ static uint32_t nxp_s32_sys_timer_get_pending_int(const struct device *dev) uint8_t i; for (i = 0; i < counter_get_num_of_channels(dev); i++) { - flags = Stm_Ip_GetInterruptFlag(config->instance, i); + flags = Stm_Ip_GetInterruptStatusFlag(config->instance, i); if (flags) { break; } @@ -145,8 +145,14 @@ static uint32_t nxp_s32_sys_timer_get_top_value(const struct device *dev) static uint32_t nxp_s32_sys_timer_get_frequency(const struct device *dev) { const struct nxp_s32_sys_timer_config *config = dev->config; + uint32_t clock_rate; - return config->info.freq / (config->hw_cfg.clockPrescaler + 1U); + if (clock_control_get_rate(config->clock_dev, config->clock_subsys, &clock_rate)) { + LOG_ERR("Failed to get clock frequency"); + return 0; + } + + return clock_rate / (config->hw_cfg.clockPrescaler + 1U); } static int nxp_s32_sys_timer_init(const struct device *dev) @@ -155,6 +161,18 @@ static int nxp_s32_sys_timer_init(const struct device *dev) struct nxp_s32_sys_timer_data *data = dev->data; struct nxp_s32_sys_timer_chan_data *ch_data; int i; + int err; + + if (!device_is_ready(config->clock_dev)) { + LOG_ERR("Clock control device not ready"); + return -ENODEV; + } + + err = clock_control_on(config->clock_dev, config->clock_subsys); + if (err) { + LOG_ERR("Failed to enable clock"); + return err; + } Stm_Ip_Init(config->instance, &config->hw_cfg); @@ -188,15 +206,24 @@ static const struct counter_driver_api nxp_s32_sys_timer_driver_api = { .channelMode = STM_IP_CH_MODE_ONESHOT, \ } +#define _SYS_TIMER_ISR(r, n) RTU##r##_STM_##n##_ISR +#define SYS_TIMER_ISR(r, n) _SYS_TIMER_ISR(r, n) + #define SYS_TIMER_ISR_DECLARE(n) \ extern void SYS_TIMER_ISR(CONFIG_NXP_S32_RTU_INDEX, n)(void) +#define SYS_TIMER_HW_INSTANCE_CHECK(i, n) \ + ((DT_INST_REG_ADDR(n) == IP_STM_##i##_BASE) ? i : 0) + +#define SYS_TIMER_HW_INSTANCE(n) \ + LISTIFY(__DEBRACKET STM_INSTANCE_COUNT, SYS_TIMER_HW_INSTANCE_CHECK, (|), n) + #define SYS_TIMER_INIT_DEVICE(n) \ SYS_TIMER_ISR_DECLARE(n); \ \ void nxp_s32_sys_timer_##n##_callback(uint8_t chan_id) \ { \ - const struct device *dev = DEVICE_DT_GET(SYS_TIMER_NODE(n)); \ + const struct device *dev = DEVICE_DT_INST_GET(n); \ const struct nxp_s32_sys_timer_config *config = dev->config; \ struct nxp_s32_sys_timer_data *data = dev->data; \ struct nxp_s32_sys_timer_chan_data *ch_data = &data->ch_data[chan_id]; \ @@ -212,12 +239,10 @@ static const struct counter_driver_api nxp_s32_sys_timer_driver_api = { \ static int nxp_s32_sys_timer_##n##_init(const struct device *dev) \ { \ - IRQ_CONNECT(DT_IRQN(SYS_TIMER_NODE(n)), \ - DT_IRQ(SYS_TIMER_NODE(n), priority), \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \ SYS_TIMER_ISR(CONFIG_NXP_S32_RTU_INDEX, n), \ - DEVICE_DT_GET(SYS_TIMER_NODE(n)), \ - DT_IRQ(SYS_TIMER_NODE(n), flags)); \ - irq_enable(DT_IRQN(SYS_TIMER_NODE(n))); \ + DEVICE_DT_INST_GET(n), DT_INST_IRQ(n, flags)); \ + irq_enable(DT_INST_IRQN(n)); \ \ return nxp_s32_sys_timer_init(dev); \ } \ @@ -227,21 +252,22 @@ static const struct counter_driver_api nxp_s32_sys_timer_driver_api = { static const struct nxp_s32_sys_timer_config nxp_s32_sys_timer_config_##n = { \ .info = { \ .max_top_value = SYS_TIMER_MAX_VALUE, \ - .freq = (DT_PROP(SYS_TIMER_NODE(n), clock_frequency)), \ .channels = SYS_TIMER_NUM_CHANNELS, \ .flags = COUNTER_CONFIG_INFO_COUNT_UP, \ }, \ .hw_cfg = { \ - .stopInDebugMode = DT_PROP(SYS_TIMER_NODE(n), freeze), \ - .clockPrescaler = DT_PROP(SYS_TIMER_NODE(n), prescaler) - 1, \ + .stopInDebugMode = DT_INST_PROP(n, freeze), \ + .clockPrescaler = DT_INST_PROP(n, prescaler) - 1, \ }, \ .ch_cfg = { \ LISTIFY(SYS_TIMER_NUM_CHANNELS, SYS_TIMER_CHANNEL_CFG, (,), n) \ }, \ - .instance = SYS_TIMER_INSTANCE_ID(n), \ + .instance = SYS_TIMER_HW_INSTANCE(n), \ + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ + .clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, name), \ }; \ \ - DEVICE_DT_DEFINE(SYS_TIMER_NODE(n), \ + DEVICE_DT_INST_DEFINE(n, \ nxp_s32_sys_timer_##n##_init, \ NULL, \ &nxp_s32_sys_timer_data_##n, \ @@ -250,18 +276,4 @@ static const struct counter_driver_api nxp_s32_sys_timer_driver_api = { CONFIG_COUNTER_INIT_PRIORITY, \ &nxp_s32_sys_timer_driver_api); -#if DT_NODE_HAS_STATUS(SYS_TIMER_NODE(0), okay) -SYS_TIMER_INIT_DEVICE(0) -#endif - -#if DT_NODE_HAS_STATUS(SYS_TIMER_NODE(1), okay) -SYS_TIMER_INIT_DEVICE(1) -#endif - -#if DT_NODE_HAS_STATUS(SYS_TIMER_NODE(2), okay) -SYS_TIMER_INIT_DEVICE(2) -#endif - -#if DT_NODE_HAS_STATUS(SYS_TIMER_NODE(3), okay) -SYS_TIMER_INIT_DEVICE(3) -#endif +DT_INST_FOREACH_STATUS_OKAY(SYS_TIMER_INIT_DEVICE) diff --git a/drivers/counter/counter_rpi_pico_timer.c b/drivers/counter/counter_rpi_pico_timer.c new file mode 100644 index 00000000000..3e1a1dcbb0b --- /dev/null +++ b/drivers/counter/counter_rpi_pico_timer.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include + +#define LOG_LEVEL CONFIG_COUNTER_LOG_LEVEL +#include + +LOG_MODULE_REGISTER(counter_rpi_pico_timer, LOG_LEVEL); + +#define DT_DRV_COMPAT raspberrypi_pico_timer + +struct counter_rpi_pico_timer_ch_data { + counter_alarm_callback_t callback; + void *user_data; +}; + +struct counter_rpi_pico_timer_data { + struct counter_rpi_pico_timer_ch_data *ch_data; + uint32_t guard_period; +}; + +struct counter_rpi_pico_timer_config { + struct counter_config_info info; + timer_hw_t *timer; + void (*irq_config)(); +}; + +static int counter_rpi_pico_timer_start(const struct device *dev) +{ + const struct counter_rpi_pico_timer_config *config = dev->config; + + config->timer->pause = 0; + + return 0; +} + +static int counter_rpi_pico_timer_stop(const struct device *dev) +{ + const struct counter_rpi_pico_timer_config *config = dev->config; + + config->timer->pause = 1u; + config->timer->timelw = 0; + config->timer->timehw = 0; + + return 0; +} + +static uint32_t counter_rpi_pico_timer_get_top_value(const struct device *dev) +{ + const struct counter_rpi_pico_timer_config *config = dev->config; + + return config->info.max_top_value; +} + +static int counter_rpi_pico_timer_get_value(const struct device *dev, uint32_t *ticks) +{ + *ticks = time_us_32(); + return 0; +} + +static int counter_rpi_pico_timer_set_alarm(const struct device *dev, uint8_t id, + const struct counter_alarm_cfg *alarm_cfg) +{ + const struct counter_rpi_pico_timer_config *config = dev->config; + struct counter_rpi_pico_timer_data *data = dev->data; + struct counter_rpi_pico_timer_ch_data *chdata = &data->ch_data[id]; + uint64_t target = (alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) ? 0 : alarm_cfg->ticks; + absolute_time_t alarm_at; + bool missed; + + update_us_since_boot(&alarm_at, config->timer->timerawl + target); + + if (alarm_cfg->ticks > counter_rpi_pico_timer_get_top_value(dev)) { + return -EINVAL; + } + + if (chdata->callback) { + return -EBUSY; + } + + chdata->callback = alarm_cfg->callback; + chdata->user_data = alarm_cfg->user_data; + + missed = hardware_alarm_set_target(id, alarm_at); + + if (missed) { + if (alarm_cfg->flags & COUNTER_ALARM_CFG_EXPIRE_WHEN_LATE) { + hardware_alarm_force_irq(id); + } + chdata->callback = NULL; + chdata->user_data = NULL; + return -ETIME; + } + + return 0; +} + +static int counter_rpi_pico_timer_cancel_alarm(const struct device *dev, uint8_t id) +{ + hardware_alarm_cancel(id); + + return 0; +} + +static int counter_rpi_pico_timer_set_top_value(const struct device *dev, + const struct counter_top_cfg *cfg) +{ + ARG_UNUSED(dev); + ARG_UNUSED(cfg); + + return -ENOTSUP; +} + +static uint32_t counter_rpi_pico_timer_get_pending_int(const struct device *dev) +{ + return 0; +} + +static uint32_t counter_rpi_pico_timer_get_guard_period(const struct device *dev, uint32_t flags) +{ + struct counter_rpi_pico_timer_data *data = dev->data; + + return data->guard_period; +} + +static int counter_rpi_pico_timer_set_guard_period(const struct device *dev, uint32_t guard, + uint32_t flags) +{ + struct counter_rpi_pico_timer_data *data = dev->data; + + __ASSERT_NO_MSG(guard < counter_rpi_pico_timer_get_top_value(dev)); + + data->guard_period = guard; + + return 0; +} + +static void counter_rpi_pico_irq_handle(uint32_t ch, void *arg) +{ + struct device *dev = arg; + struct counter_rpi_pico_timer_data *data = dev->data; + counter_alarm_callback_t cb = data->ch_data[ch].callback; + void *user_data = data->ch_data[ch].user_data; + + if (cb) { + data->ch_data[ch].callback = NULL; + data->ch_data[ch].user_data = NULL; + cb(dev, ch, time_us_32(), user_data); + } +} + +static int counter_rpi_pico_timer_init(const struct device *dev) +{ + const struct counter_rpi_pico_timer_config *config = dev->config; + + config->irq_config(); + + return 0; +} + +static const struct counter_driver_api counter_rpi_pico_driver_api = { + .start = counter_rpi_pico_timer_start, + .stop = counter_rpi_pico_timer_stop, + .get_value = counter_rpi_pico_timer_get_value, + .set_alarm = counter_rpi_pico_timer_set_alarm, + .cancel_alarm = counter_rpi_pico_timer_cancel_alarm, + .set_top_value = counter_rpi_pico_timer_set_top_value, + .get_pending_int = counter_rpi_pico_timer_get_pending_int, + .get_top_value = counter_rpi_pico_timer_get_top_value, + .get_guard_period = counter_rpi_pico_timer_get_guard_period, + .set_guard_period = counter_rpi_pico_timer_set_guard_period, +}; + +#define RPI_PICO_TIMER_IRQ_ENABLE(node_id, name, idx) \ + do { \ + hardware_alarm_set_callback(idx, counter_rpi_pico_irq_handle); \ + IRQ_CONNECT((DT_IRQ_BY_IDX(node_id, idx, irq)), \ + (DT_IRQ_BY_IDX(node_id, idx, priority)), hardware_alarm_irq_handler, \ + (DEVICE_DT_GET(node_id)), 0); \ + irq_enable((DT_IRQ_BY_IDX(node_id, idx, irq))); \ + } while (false); + +#define COUNTER_RPI_PICO_TIMER(inst) \ + static void counter_irq_config##inst(void) \ + { \ + DT_INST_FOREACH_PROP_ELEM(inst, interrupt_names, RPI_PICO_TIMER_IRQ_ENABLE); \ + } \ + static struct counter_rpi_pico_timer_ch_data \ + ch_data##inst[DT_NUM_IRQS(DT_DRV_INST(inst))]; \ + static struct counter_rpi_pico_timer_data counter_##inst##_data = { \ + .ch_data = ch_data##inst, \ + }; \ + static const struct counter_rpi_pico_timer_config counter_##inst##_config = { \ + .timer = (timer_hw_t *)DT_INST_REG_ADDR(inst), \ + .irq_config = counter_irq_config##inst, \ + .info = \ + { \ + .max_top_value = UINT32_MAX, \ + .freq = 1000000, \ + .flags = COUNTER_CONFIG_INFO_COUNT_UP, \ + .channels = ARRAY_SIZE(ch_data##inst), \ + }, \ + }; \ + DEVICE_DT_INST_DEFINE(inst, counter_rpi_pico_timer_init, NULL, &counter_##inst##_data, \ + &counter_##inst##_config, PRE_KERNEL_1, \ + CONFIG_COUNTER_INIT_PRIORITY, &counter_rpi_pico_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(COUNTER_RPI_PICO_TIMER) diff --git a/drivers/counter/counter_smartbond_timer.c b/drivers/counter/counter_smartbond_timer.c index 5d1468648fd..0173373f107 100644 --- a/drivers/counter/counter_smartbond_timer.c +++ b/drivers/counter/counter_smartbond_timer.c @@ -7,7 +7,7 @@ #define DT_DRV_COMPAT renesas_smartbond_timer #include -#include +#include #include #include @@ -225,7 +225,7 @@ static int counter_smartbond_init_timer(const struct device *dev) TIMER_Type *timer0 = ((TIMER_Type *)cfg->timer) == TIMER ? TIMER : NULL; const struct device *osc_dev; uint32_t osc_freq; - uint32_t osc; + enum smartbond_clock osc; if (cfg->clock_src_divn) { /* Timer clock source is DIVn 32MHz */ @@ -238,17 +238,17 @@ static int counter_smartbond_init_timer(const struct device *dev) switch ((CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) >> CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos) { case LP_CLK_OSC_RC32K: - osc = DT_DEP_ORD(DT_NODELABEL(rc32k)); + osc = SMARTBOND_CLK_RC32K; break; case LP_CLK_OSC_RCX: - osc = DT_DEP_ORD(DT_NODELABEL(rcx)); + osc = SMARTBOND_CLK_RCX; break; default: case LP_CLK_OSC_XTAL32K: - osc = DT_DEP_ORD(DT_NODELABEL(xtal32k)); + osc = SMARTBOND_CLK_XTAL32K; break; } - clock_control_get_rate(osc_dev, (clock_control_subsys_t *)&osc, &osc_freq); + clock_control_get_rate(osc_dev, (clock_control_subsys_t)osc, &osc_freq); data->freq = osc_freq / (cfg->prescaler + 1); } timer->TIMER2_PRESCALER_REG = cfg->prescaler; diff --git a/drivers/counter/maxim_ds3231.c b/drivers/counter/maxim_ds3231.c index 514ddd32b1a..93d20639ecd 100644 --- a/drivers/counter/maxim_ds3231.c +++ b/drivers/counter/maxim_ds3231.c @@ -1300,7 +1300,7 @@ DEVICE_DT_INST_DEFINE(0, ds3231_init, NULL, &ds3231_0_data, #ifdef CONFIG_USERSPACE -#include +#include int z_vrfy_maxim_ds3231_get_syncpoint(const struct device *dev, struct maxim_ds3231_syncpoint *syncpoint) @@ -1308,13 +1308,13 @@ int z_vrfy_maxim_ds3231_get_syncpoint(const struct device *dev, struct maxim_ds3231_syncpoint value; int rv; - Z_OOPS(Z_SYSCALL_SPECIFIC_DRIVER(dev, K_OBJ_DRIVER_COUNTER, &ds3231_api)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(syncpoint, sizeof(*syncpoint))); + K_OOPS(K_SYSCALL_SPECIFIC_DRIVER(dev, K_OBJ_DRIVER_COUNTER, &ds3231_api)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(syncpoint, sizeof(*syncpoint))); rv = z_impl_maxim_ds3231_get_syncpoint(dev, &value); if (rv >= 0) { - Z_OOPS(z_user_to_copy(syncpoint, &value, sizeof(*syncpoint))); + K_OOPS(k_usermode_to_copy(syncpoint, &value, sizeof(*syncpoint))); } return rv; @@ -1325,9 +1325,9 @@ int z_vrfy_maxim_ds3231_get_syncpoint(const struct device *dev, int z_vrfy_maxim_ds3231_req_syncpoint(const struct device *dev, struct k_poll_signal *sig) { - Z_OOPS(Z_SYSCALL_SPECIFIC_DRIVER(dev, K_OBJ_DRIVER_COUNTER, &ds3231_api)); + K_OOPS(K_SYSCALL_SPECIFIC_DRIVER(dev, K_OBJ_DRIVER_COUNTER, &ds3231_api)); if (sig != NULL) { - Z_OOPS(Z_SYSCALL_OBJ(sig, K_OBJ_POLL_SIGNAL)); + K_OOPS(K_SYSCALL_OBJ(sig, K_OBJ_POLL_SIGNAL)); } return z_impl_maxim_ds3231_req_syncpoint(dev, sig); diff --git a/drivers/crypto/CMakeLists.txt b/drivers/crypto/CMakeLists.txt index 07eb8a414ec..68b63aef6ee 100644 --- a/drivers/crypto/CMakeLists.txt +++ b/drivers/crypto/CMakeLists.txt @@ -5,6 +5,7 @@ zephyr_library_sources_ifdef(CONFIG_CRYPTO_TINYCRYPT_SHIM crypto_tc_shim.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_ATAES132A crypto_ataes132a.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_MBEDTLS_SHIM crypto_mtls_shim.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_STM32 crypto_stm32.c) +zephyr_library_sources_ifdef(CONFIG_CRYPTO_SMARTBOND crypto_smartbond.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_NRF_ECB crypto_nrf_ecb.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_INTEL_SHA crypto_intel_sha.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_NPCX_SHA crypto_npcx_sha.c) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index c209ed226f7..5342441038e 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -80,5 +80,6 @@ source "drivers/crypto/Kconfig.npcx" source "drivers/crypto/Kconfig.xec" source "drivers/crypto/Kconfig.it8xxx2" source "drivers/crypto/Kconfig.mcux_dcp" +source "drivers/crypto/Kconfig.smartbond" endif # CRYPTO diff --git a/drivers/crypto/Kconfig.mcux_dcp b/drivers/crypto/Kconfig.mcux_dcp index 38f725b4092..e16517e2815 100644 --- a/drivers/crypto/Kconfig.mcux_dcp +++ b/drivers/crypto/Kconfig.mcux_dcp @@ -6,7 +6,7 @@ config CRYPTO_MCUX_DCP default y depends on HAS_MCUX_CACHE depends on DT_HAS_NXP_MCUX_DCP_ENABLED - select NOCACHE_MEMORY + select NOCACHE_MEMORY if ARCH_HAS_NOCACHE_MEMORY_SUPPORT select CACHE_MANAGEMENT if DCACHE help Enable NXP Data Co-Processor (DCP) driver. diff --git a/drivers/crypto/Kconfig.smartbond b/drivers/crypto/Kconfig.smartbond new file mode 100644 index 00000000000..6c2077c3a42 --- /dev/null +++ b/drivers/crypto/Kconfig.smartbond @@ -0,0 +1,17 @@ +# Smartbond Cryptographic Accelerator configuration options + +# Copyright (c) 2023 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +menuconfig CRYPTO_SMARTBOND + bool "Smartbond Cryptographic Accelerator driver" + depends on DT_HAS_RENESAS_SMARTBOND_CRYPTO_ENABLED + default y + help + Enable Smartbond Cryptographic Accelerator driver. + +config CRYPTO_ASYNC + bool "Support ASYNC crypto operations." + depends on CRYPTO_SMARTBOND + help + Enable ASYNC crypto operations. diff --git a/drivers/crypto/crypto_mchp_xec_symcr.c b/drivers/crypto/crypto_mchp_xec_symcr.c index 626d3f88154..8f47e374d36 100644 --- a/drivers/crypto/crypto_mchp_xec_symcr.c +++ b/drivers/crypto/crypto_mchp_xec_symcr.c @@ -12,7 +12,7 @@ #include #include #include -#include "zephyr/sys/util.h" +#include #include LOG_MODULE_REGISTER(xec_symcr, CONFIG_CRYPTO_LOG_LEVEL); diff --git a/drivers/crypto/crypto_npcx_sha.c b/drivers/crypto/crypto_npcx_sha.c index e2420134cfa..26403599360 100644 --- a/drivers/crypto/crypto_npcx_sha.c +++ b/drivers/crypto/crypto_npcx_sha.c @@ -14,7 +14,7 @@ LOG_MODULE_REGISTER(sha_npcx, CONFIG_CRYPTO_LOG_LEVEL); #define NPCX_HASH_CAPS_SUPPORT (CAP_SEPARATE_IO_BUFS | CAP_SYNC_OPS) -#define NPCX_SHA256_HANDLE_SIZE 212 +#define NPCX_SHA256_HANDLE_SIZE DT_INST_PROP(0, context_buffer_size) #define NPCX_SHA_MAX_SESSION 1 /* The status code returns from Nuvoton Cryptographic Library ROM APIs */ diff --git a/drivers/crypto/crypto_smartbond.c b/drivers/crypto/crypto_smartbond.c new file mode 100644 index 00000000000..5b003875b93 --- /dev/null +++ b/drivers/crypto/crypto_smartbond.c @@ -0,0 +1,956 @@ +/* + * Copyright (c) 2023 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(crypto_smartbond_crypto, CONFIG_CRYPTO_LOG_LEVEL); + +#define DT_DRV_COMPAT renesas_smartbond_crypto + +#define SMARTBOND_IRQN DT_INST_IRQN(0) +#define SMARTBOND_IRQ_PRIO DT_INST_IRQ(0, priority) + +#if defined(CONFIG_CRYPTO_ASYNC) +#define CRYPTO_HW_CAPS (CAP_RAW_KEY | CAP_SEPARATE_IO_BUFS | CAP_ASYNC_OPS | CAP_NO_IV_PREFIX) +#else +#define CRYPTO_HW_CAPS (CAP_RAW_KEY | CAP_SEPARATE_IO_BUFS | CAP_SYNC_OPS | CAP_NO_IV_PREFIX) +#endif + +#define SWAP32(_w) __builtin_bswap32(_w) + +#define CRYPTO_CTRL_REG_SET(_field, _val) \ + AES_HASH->CRYPTO_CTRL_REG = \ + (AES_HASH->CRYPTO_CTRL_REG & ~AES_HASH_CRYPTO_CTRL_REG_ ## _field ## _Msk) | \ + ((_val) << AES_HASH_CRYPTO_CTRL_REG_ ## _field ## _Pos) + +#define CRYPTO_CTRL_REG_GET(_field) \ + ((AES_HASH->CRYPTO_CTRL_REG & AES_HASH_CRYPTO_CTRL_REG_ ## _field ## _Msk) >> \ + AES_HASH_CRYPTO_CTRL_REG_ ## _field ## _Pos) + + +struct crypto_smartbond_data { + /* + * Semaphore to provide mutual exlusion when a crypto session is requested. + */ + struct k_sem session_sem; + + /* + * Semaphore to provide mutual exlusion when a cryptographic task is requested. + * (a session should be requested at this point). + */ + struct k_sem device_sem; +#if defined(CONFIG_CRYPTO_ASYNC) + /* + * User-defined callbacks to be called upon completion of asynchronous + * cryptographic operations. Note that the AES and HASH modes can work + * complementary to each other. + */ + union { + cipher_completion_cb cipher_user_cb; + hash_completion_cb hash_user_cb; + }; + + /* + * Packet context should be stored during a session so that can be rertieved + * from within the crypto engine ISR context. + */ + union { + struct cipher_pkt *cipher_pkt; + struct hash_pkt *hash_pkt; + }; +#else + /* + * Semaphore used to block for as long as a synchronous cryptographic operation + * is in progress. + */ + struct k_sem sync_sem; +#endif +}; + +/* + * Status flag to indicate if the crypto engine resources have been granted. Note that the + * device integrates a single crypto engine instance. + */ +static bool in_use; + +static void crypto_smartbond_set_status(bool enable); + +static void smartbond_crypto_isr(const void *arg) +{ + struct crypto_smartbond_data *data = ((const struct device *)arg)->data; + uint32_t status = AES_HASH->CRYPTO_STATUS_REG; + + if (status & AES_HASH_CRYPTO_STATUS_REG_CRYPTO_IRQ_ST_Msk) { + /* Clear interrupt source. Otherwise the handler will be fire constantly! */ + AES_HASH->CRYPTO_CLRIRQ_REG = 0x1; + +#if defined(CONFIG_CRYPTO_ASYNC) + /* Define the slected crypto mode (AES/HASH). */ + if (AES_HASH->CRYPTO_CTRL_REG & AES_HASH_CRYPTO_CTRL_REG_CRYPTO_HASH_SEL_Msk) { + if (data->hash_user_cb) { + data->hash_user_cb(data->hash_pkt, status); + } + } else { + if (data->cipher_user_cb) { + data->cipher_user_cb(data->cipher_pkt, status); + } + } +#else + /* Designate the requested cryptographic tasks is finished. */ + k_sem_give(&data->sync_sem); +#endif + } +} + +static bool crypto_smartbond_lock_session(const struct device *dev) +{ + bool lock = false; + struct crypto_smartbond_data *data = dev->data; + + k_sem_take(&data->session_sem, K_FOREVER); + + if (!in_use) { + in_use = true; + crypto_smartbond_set_status(true); + lock = true; + } + + k_sem_give(&data->session_sem); + + return lock; +} + +static void crypto_smartbond_unlock_session(const struct device *dev) +{ + struct crypto_smartbond_data *data = dev->data; + + k_sem_take(&data->session_sem, K_FOREVER); + + if (in_use) { + in_use = false; + crypto_smartbond_set_status(false); + } + + k_sem_give(&data->session_sem); +} + +/* + * Input vector should comply with the following restrictions: + * + * mode | CRYPTO_MORE_IN = true | CRYPTO_MORE_IN = false + * ------------| -----------------------| ---------------------- + * ECB | multiple of 16 (bytes) | multiple of 16 (bytes) + * CBC | multiple of 16 | no restrictions + * CTR | multiple of 16 | no restrictions + * MD5 | multiple of 8 | no restrictions + * SHA_1 | multiple of 8 | no restrictions + * SHA_256_224 | multiple of 8 | no restrictions + * SHA_256 | multiple of 8 | no restrictions + * SHA_384 | multiple of 8 | no restrictions + * SHA_512 | multiple of 8 | no restrictions + * SHA_512_224 | multiple of 8 | no restrictions + * SHA_512_256 | multiple of 8 | no restrictions + */ +static int crypto_smartbond_check_in_restrictions(uint16_t in_len) +{ +#define CRYPTO_ALG_MD_ECB_MAGIC_0 0x00 +#define CRYPTO_ALG_MD_ECB_MAGIC_1 0x01 + + bool not_last_in_block = !!(AES_HASH->CRYPTO_CTRL_REG & + AES_HASH_CRYPTO_CTRL_REG_CRYPTO_MORE_IN_Msk); + + /* Define the slected crypto mode (AES/HASH). */ + if (AES_HASH->CRYPTO_CTRL_REG & AES_HASH_CRYPTO_CTRL_REG_CRYPTO_HASH_SEL_Msk) { + if (not_last_in_block && (in_len & 0x7)) { + return -EINVAL; + } + } else { + if (in_len & 0xF) { + if (not_last_in_block) { + return -EINVAL; + } + + uint32_t crypto_mode = CRYPTO_CTRL_REG_GET(CRYPTO_ALG_MD); + + /* Check if AES mode is ECB */ + if (crypto_mode == CRYPTO_ALG_MD_ECB_MAGIC_0 || + crypto_mode == CRYPTO_ALG_MD_ECB_MAGIC_1) { + return -EINVAL; + } + } + } + + return 0; +} + +/* + * The driver model does not define the max. output length. As such, the max supported length + * per mode is applied. + */ +static int crypto_smartbond_hash_set_out_len(void) +{ + uint32_t hash_algo = (AES_HASH->CRYPTO_CTRL_REG & AES_HASH_CRYPTO_CTRL_REG_CRYPTO_ALG_Msk); + + if (AES_HASH->CRYPTO_CTRL_REG & AES_HASH_CRYPTO_CTRL_REG_CRYPTO_ALG_MD_Msk) { + /* 64-bit HASH operations */ + switch (hash_algo) { + case 0x0: + /* SHA-384: 0..47 --> 1..48 bytes */ + CRYPTO_CTRL_REG_SET(CRYPTO_HASH_OUT_LEN, 47); + break; + case 0x1: + /* SHA-512: 0..63 --> 1..64 bytes */ + CRYPTO_CTRL_REG_SET(CRYPTO_HASH_OUT_LEN, 63); + break; + case 0x2: + /* SHA-512/224: 0..27 --> 1..28 bytes */ + CRYPTO_CTRL_REG_SET(CRYPTO_HASH_OUT_LEN, 27); + break; + case 0x3: + /* SHA-512/256: 0..31 --> 1..32 bytes */ + CRYPTO_CTRL_REG_SET(CRYPTO_HASH_OUT_LEN, 31); + break; + default: + break; + } + } else { + /* 32-bit HASH operations */ + switch (hash_algo) { + case 0x0: + /* MD5: 0..15 --> 1..16 bytes */ + CRYPTO_CTRL_REG_SET(CRYPTO_HASH_OUT_LEN, 15); + break; + case 0x1: + /* SHA-1: 0..19 --> 1..20 bytes */ + CRYPTO_CTRL_REG_SET(CRYPTO_HASH_OUT_LEN, 19); + break; + case 0x2: + /* SHA-256/224: 0..27 --> 1..28 bytes */ + CRYPTO_CTRL_REG_SET(CRYPTO_HASH_OUT_LEN, 27); + break; + case 0x3: + /* SHA-256: 0..31 --> 1..32 bytes */ + CRYPTO_CTRL_REG_SET(CRYPTO_HASH_OUT_LEN, 31); + break; + default: + break; + } + } + + /* Return the OUT size applied. */ + return CRYPTO_CTRL_REG_GET(CRYPTO_HASH_OUT_LEN) + 1; +} + +static uint32_t crypto_smartbond_swap_word(uint8_t *data) +{ + /* Check word boundaries of given address and if possible accellerate swapping */ + if ((uint32_t)data & 0x3) { + sys_mem_swap(data, sizeof(uint32_t)); + + return (*(uint32_t *)data); + } else { + return SWAP32(*(uint32_t *)data); + } +} + +static int crypto_smartbond_cipher_key_load(uint8_t *key, uint16_t key_len) +{ + if (key == NULL) { + return -EIO; + } + + AES_HASH->CRYPTO_CTRL_REG &= ~(AES_HASH_CRYPTO_CTRL_REG_CRYPTO_AES_KEY_SZ_Msk); + + if (key_len == 32) { + AES_HASH->CRYPTO_CTRL_REG |= + (0x2 << AES_HASH_CRYPTO_CTRL_REG_CRYPTO_AES_KEY_SZ_Pos); + } else if (key_len == 24) { + AES_HASH->CRYPTO_CTRL_REG |= + (0x1 << AES_HASH_CRYPTO_CTRL_REG_CRYPTO_AES_KEY_SZ_Pos); + } else if (key_len == 16) { + /* Nothing to do */ + } else { + return -EINVAL; + } + + /* Key expansion is performed by the crypto engine */ + AES_HASH->CRYPTO_CTRL_REG |= AES_HASH_CRYPTO_CTRL_REG_CRYPTO_AES_KEXP_Msk; + + /* Check whether the cipher key is located in OTP (user keys segment) */ + if (IS_ADDRESS_USER_DATA_KEYS_SEGMENT((uint32_t)key)) { + + /* User keys segmnet can be accessed if not locked (stick bits are not set) */ + if (CRG_TOP->SECURE_BOOT_REG & CRG_TOP_SECURE_BOOT_REG_PROT_AES_KEY_READ_Msk) { + return -EIO; + } + + uint32_t cell_offset = da1469x_otp_address_to_cell_offset((uint32_t)key); + + da1469x_otp_read(cell_offset, + (void *)&AES_HASH->CRYPTO_KEYS_START, (uint32_t)key_len); + } else { + volatile uint32_t *kmem_ptr = &AES_HASH->CRYPTO_KEYS_START; + + do { + *(kmem_ptr++) = crypto_smartbond_swap_word(key); + key += 4; + key_len -= 4; + } while (key_len); + } + + return 0; +} + +static int crypto_smartbond_cipher_set_mode(enum cipher_mode mode) +{ + /* Select AES mode */ + AES_HASH->CRYPTO_CTRL_REG &= ~(AES_HASH_CRYPTO_CTRL_REG_CRYPTO_ALG_MD_Msk | + AES_HASH_CRYPTO_CTRL_REG_CRYPTO_ALG_Msk | + AES_HASH_CRYPTO_CTRL_REG_CRYPTO_HASH_SEL_Msk); + switch (mode) { + case CRYPTO_CIPHER_MODE_ECB: + /* Already done; CRYPTO_ALG_MD = 0x0 or 0x1 defines ECB. */ + break; + case CRYPTO_CIPHER_MODE_CTR: + AES_HASH->CRYPTO_CTRL_REG |= (0x2 << AES_HASH_CRYPTO_CTRL_REG_CRYPTO_ALG_MD_Pos); + break; + case CRYPTO_CIPHER_MODE_CBC: + AES_HASH->CRYPTO_CTRL_REG |= (0x3 << AES_HASH_CRYPTO_CTRL_REG_CRYPTO_ALG_MD_Pos); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int crypto_smartbond_hash_set_algo(enum hash_algo algo) +{ + /* Select HASH mode and reset to 32-bit mode */ + AES_HASH->CRYPTO_CTRL_REG = + (AES_HASH->CRYPTO_CTRL_REG & ~(AES_HASH_CRYPTO_CTRL_REG_CRYPTO_ALG_Msk | + AES_HASH_CRYPTO_CTRL_REG_CRYPTO_ALG_MD_Msk)) | + AES_HASH_CRYPTO_CTRL_REG_CRYPTO_HASH_SEL_Msk; + + switch (algo) { + case CRYPTO_HASH_ALGO_SHA224: + /* CRYPTO_ALG_MD = 0x0 defines 32-bit operations */ + AES_HASH->CRYPTO_CTRL_REG |= (0x2 << AES_HASH_CRYPTO_CTRL_REG_CRYPTO_ALG_Pos); + break; + case CRYPTO_HASH_ALGO_SHA256: + /* CRYPTO_ALG_MD = 0x0 defines 32-bit operations */ + AES_HASH->CRYPTO_CTRL_REG |= (0x3 << AES_HASH_CRYPTO_CTRL_REG_CRYPTO_ALG_Pos); + break; + case CRYPTO_HASH_ALGO_SHA384: + /* CRYPTO_ALG_MD = 0x1 defines 64-bit operations */ + AES_HASH->CRYPTO_CLRIRQ_REG |= AES_HASH_CRYPTO_CTRL_REG_CRYPTO_ALG_MD_Msk; + break; + case CRYPTO_HASH_ALGO_SHA512: + /* CRYPTO_ALG_MD = 0x1 defines 64-bit operations */ + AES_HASH->CRYPTO_CTRL_REG |= (AES_HASH_CRYPTO_CTRL_REG_CRYPTO_ALG_MD_Msk | + (0x1 << AES_HASH_CRYPTO_CTRL_REG_CRYPTO_ALG_Pos)); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int crypto_smartbond_set_in_out_buf(uint8_t *in_buf, uint8_t *out_buf, int len) +{ + if (in_buf == NULL) { + return -EIO; + } + + /* + * Input data can reside in any address space. Cryto DMA can only access physical addresses + * (not remapped). + */ + uint32_t phy_addr = black_orca_phy_addr((uint32_t)in_buf); + + if (IS_QSPIF_CACHED_ADDRESS(phy_addr)) { + /* + * To achiebe max. perfomance, peripherals should not access the Flash memory + * through the instruction cache controller (avoid cache misses). + */ + phy_addr += (MCU_QSPIF_M_BASE - MCU_QSPIF_M_CACHED_BASE); + } else if (IS_OTP_ADDRESS(phy_addr)) { + /* Peripherals should access the OTP memory through its peripheral address space. */ + phy_addr += (MCU_OTP_M_P_BASE - MCU_OTP_M_BASE); + } + + AES_HASH->CRYPTO_FETCH_ADDR_REG = phy_addr; + + /* + * OUT buffer can be NULL in case of fregmented data processing. CRYPTO_DEST_ADDR and + * CRYPTO_FETCH_ADDR are being updated as calculations prceed and OUT data are written + * into memory. + */ + if (out_buf) { + uint32_t remap_adr0 = CRG_TOP->SYS_CTRL_REG & CRG_TOP_SYS_CTRL_REG_REMAP_ADR0_Msk; + + /* + * OUT data can only be written in SYSRAM, non-cached remapped SYSRAM and + * cached non-remapped SYSRAM. + */ + if (IS_SYSRAM_ADDRESS(out_buf) || + (IS_REMAPPED_ADDRESS(out_buf) && remap_adr0 == 3)) { + AES_HASH->CRYPTO_DEST_ADDR_REG = black_orca_phy_addr((uint32_t)out_buf); + } else { + return -EIO; + } + } + + AES_HASH->CRYPTO_LEN_REG = len; + + return 0; +} + +static inline void crypto_smartbond_cipher_store_dep_data(uint32_t *words, uint32_t len_words) +{ + volatile uint32_t *mreg3 = &AES_HASH->CRYPTO_MREG3_REG; + + for (int i = 0; i < len_words; i++) { + *(mreg3--) = crypto_smartbond_swap_word((uint8_t *)(words++)); + } +} + +static int crypto_smartbond_cipher_set_mreg(uint8_t *mreg, uint32_t len_words) +{ + if (mreg == NULL || len_words == 0 || len_words > 4) { + return -EINVAL; + } + + AES_HASH->CRYPTO_MREG0_REG = 0; + AES_HASH->CRYPTO_MREG1_REG = 0; + AES_HASH->CRYPTO_MREG2_REG = 0; + AES_HASH->CRYPTO_MREG3_REG = 0; + + crypto_smartbond_cipher_store_dep_data((uint32_t *)mreg, len_words); + + return 0; +} + +static void crypto_smartbond_set_status(bool enable) +{ + unsigned int key; + + key = irq_lock(); + + if (enable) { + CRG_TOP->CLK_AMBA_REG |= (CRG_TOP_CLK_AMBA_REG_AES_CLK_ENABLE_Msk); + + AES_HASH->CRYPTO_CLRIRQ_REG = 0x1; + AES_HASH->CRYPTO_CTRL_REG |= (AES_HASH_CRYPTO_CTRL_REG_CRYPTO_IRQ_EN_Msk); + + irq_enable(SMARTBOND_IRQN); + } else { + AES_HASH->CRYPTO_CTRL_REG &= ~(AES_HASH_CRYPTO_CTRL_REG_CRYPTO_IRQ_EN_Msk); + AES_HASH->CRYPTO_CLRIRQ_REG = 0x1; + + irq_disable(SMARTBOND_IRQN); + + CRG_TOP->CLK_AMBA_REG &= ~(CRG_TOP_CLK_AMBA_REG_AES_CLK_ENABLE_Msk); + } + + irq_unlock(key); +} + +static int crypto_smartbond_query_hw_caps(const struct device *dev) +{ + return CRYPTO_HW_CAPS; +} + +static int crypto_smartbond_cipher_ecb_handler(struct cipher_ctx *ctx, struct cipher_pkt *pkt) +{ + int ret; + struct crypto_smartbond_data *data = ctx->device->data; + + if ((AES_HASH->CRYPTO_STATUS_REG & AES_HASH_CRYPTO_STATUS_REG_CRYPTO_INACTIVE_Msk) == 0) { + LOG_ERR("Crypto engine is already employed"); + return -EINVAL; + } + + if (pkt->out_buf_max < pkt->in_len) { + LOG_ERR("OUT buffer cannot be less that IN buffer"); + return -EINVAL; + } + + if (pkt->in_buf == NULL || pkt->out_buf == NULL) { + LOG_ERR("Missing IN or OUT buffer declaration"); + return -EIO; + } + + if (pkt->in_len > 16) { + LOG_ERR("For security reasons, do not operate on more than 16 bytes"); + return -EINVAL; + } + + k_sem_take(&data->device_sem, K_FOREVER); + + ret = crypto_smartbond_check_in_restrictions(pkt->in_len); + if (ret < 0) { + LOG_ERR("Unsupported IN buffer size"); + k_sem_give(&data->device_sem); + return ret; + } + + ret = crypto_smartbond_set_in_out_buf(pkt->in_buf, pkt->out_buf, pkt->in_len); + if (ret < 0) { + LOG_ERR("Unsupported IN or OUT buffer location"); + k_sem_give(&data->device_sem); + return ret; + } + +#if defined(CONFIG_CRYPTO_ASYNC) + data->cipher_pkt = pkt; +#endif + + /* Start crypto processing */ + AES_HASH->CRYPTO_START_REG = 1; + +#if !defined(CONFIG_CRYPTO_ASYNC) + /* Wait for crypto to finish its task */ + k_sem_take(&data->sync_sem, K_FOREVER); +#endif + + /* Report that number of bytes operated upon. */ + pkt->out_len = pkt->in_len; + + k_sem_give(&data->device_sem); + + return 0; +} + +static int +crypto_smartbond_cipher_cbc_handler(struct cipher_ctx *ctx, struct cipher_pkt *pkt, uint8_t *iv) +{ + int ret; + int offset = 0; + struct crypto_smartbond_data *data = ctx->device->data; + bool is_op_encryption = + !!(AES_HASH->CRYPTO_CTRL_REG & AES_HASH_CRYPTO_CTRL_REG_CRYPTO_ENCDEC_Msk); + + if ((AES_HASH->CRYPTO_STATUS_REG & AES_HASH_CRYPTO_STATUS_REG_CRYPTO_INACTIVE_Msk) == 0) { + LOG_ERR("Crypto engine is already employed"); + return -EINVAL; + } + + if ((is_op_encryption && pkt->out_buf_max < (pkt->in_len + 16)) || + pkt->out_buf_max < (pkt->in_len - 16)) { + LOG_ERR("Invalid OUT buffer size"); + return -EINVAL; + } + + if (pkt->in_buf == NULL || pkt->out_buf == NULL) { + LOG_ERR("Missing IN or OUT buffer declaration"); + return -EIO; + } + + if ((ctx->flags & CAP_NO_IV_PREFIX) == 0) { + offset = 16; + if (is_op_encryption) { + /* Prefix IV to ciphertet unless CAP_NO_IV_PREFIX is set. */ + memcpy(pkt->out_buf, iv, offset); + } + } + + k_sem_take(&data->device_sem, K_FOREVER); + + ret = crypto_smartbond_check_in_restrictions(pkt->in_len); + if (ret < 0) { + LOG_ERR("Unsupported IN buffer size"); + k_sem_give(&data->device_sem); + return ret; + } + + ret = crypto_smartbond_cipher_set_mreg(iv, 4); + if (ret < 0) { + LOG_ERR("Missing Initialization Vector (IV)"); + k_sem_give(&data->device_sem); + return ret; + } + + if (is_op_encryption) { + ret = crypto_smartbond_set_in_out_buf(pkt->in_buf, + pkt->out_buf + offset, pkt->in_len); + } else { + ret = crypto_smartbond_set_in_out_buf(pkt->in_buf + offset, + pkt->out_buf, pkt->in_len - offset); + } + + if (ret < 0) { + LOG_ERR("Unsupported IN or OUT buffer location"); + k_sem_give(&data->device_sem); + return ret; + } + +#if defined(CONFIG_CRYPTO_ASYNC) + data->cipher_pkt = pkt; +#endif + + /* Start crypto processing */ + AES_HASH->CRYPTO_START_REG = 1; + +#if !defined(CONFIG_CRYPTO_ASYNC) + /* Wait for crypto to finish its task */ + k_sem_take(&data->sync_sem, K_FOREVER); +#endif + + /* Report that number of bytes operated upon. */ + if (is_op_encryption) { + pkt->out_len = pkt->in_len + offset; + } else { + pkt->out_len = pkt->in_len - offset; + } + + k_sem_give(&data->device_sem); + + return 0; +} + +static int crypto_smartbond_cipher_ctr_handler(struct cipher_ctx *ctx, + struct cipher_pkt *pkt, uint8_t *ic) +{ + int ret; + /* ivlen + ctrlen = keylen, ctrl_len is expressed in bits */ + uint32_t iv_len = ctx->keylen - (ctx->mode_params.ctr_info.ctr_len >> 3); + struct crypto_smartbond_data *data = ctx->device->data; + + if ((AES_HASH->CRYPTO_STATUS_REG & AES_HASH_CRYPTO_STATUS_REG_CRYPTO_INACTIVE_Msk) == 0) { + LOG_ERR("Crypto engine is already employed"); + return -EINVAL; + } + + if (pkt->out_buf_max < pkt->in_len) { + LOG_ERR("OUT buffer cannot be less that IN buffer"); + return -EINVAL; + } + + if (pkt->in_buf == NULL || pkt->out_buf == NULL) { + LOG_ERR("Missing IN or OUT buffer declaration"); + return -EIO; + } + + k_sem_take(&data->device_sem, K_FOREVER); + + ret = crypto_smartbond_check_in_restrictions(pkt->in_len); + if (ret < 0) { + LOG_ERR("Unsupported IN buffer size"); + k_sem_give(&data->device_sem); + return ret; + } + + ret = crypto_smartbond_cipher_set_mreg(ic, iv_len >> 2); + if (ret < 0) { + LOG_ERR("Missing Initialization Counter (IC)"); + k_sem_give(&data->device_sem); + return ret; + } + + ret = crypto_smartbond_set_in_out_buf(pkt->in_buf, pkt->out_buf, pkt->in_len); + if (ret < 0) { + LOG_ERR("Unsupported IN or OUT buffer location"); + k_sem_give(&data->device_sem); + return ret; + } + +#if defined(CONFIG_CRYPTO_ASYNC) + data->cipher_pkt = pkt; +#endif + + /* Start crypto processing */ + AES_HASH->CRYPTO_START_REG = 1; + +#if !defined(CONFIG_CRYPTO_ASYNC) + /* Wait for crypto to finish its task */ + k_sem_take(&data->sync_sem, K_FOREVER); +#endif + + /* Report that number of bytes operated upon. */ + pkt->out_len = pkt->in_len; + + k_sem_give(&data->device_sem); + + return 0; +} + +static int crypto_smartbond_hash_handler(struct hash_ctx *ctx, struct hash_pkt *pkt, bool finish) +{ + int ret; + struct crypto_smartbond_data *data = ctx->device->data; + /* + * In case of framgemented data processing crypto status should be visible as busy for + * as long as the last block is to be processed. + */ + bool is_multipart_started = + (AES_HASH->CRYPTO_STATUS_REG & AES_HASH_CRYPTO_STATUS_REG_CRYPTO_WAIT_FOR_IN_Msk) && + !(AES_HASH->CRYPTO_STATUS_REG & AES_HASH_CRYPTO_STATUS_REG_CRYPTO_INACTIVE_Msk); + + if (pkt->in_buf == NULL || (pkt->out_buf == NULL)) { + LOG_ERR("Missing IN or OUT buffer declaration"); + return -EIO; + } + + k_sem_take(&data->device_sem, K_FOREVER); + + /* Check if this is the last block to process or more blocks will follow */ + if (finish) { + AES_HASH->CRYPTO_CTRL_REG &= ~(AES_HASH_CRYPTO_CTRL_REG_CRYPTO_MORE_IN_Msk); + } else { + AES_HASH->CRYPTO_CTRL_REG |= AES_HASH_CRYPTO_CTRL_REG_CRYPTO_MORE_IN_Msk; + } + + /* CRYPTO_MORE_IN should be updated prior to checking for IN restrictions! */ + ret = crypto_smartbond_check_in_restrictions(pkt->in_len); + if (ret < 0) { + LOG_ERR("Unsupported IN buffer size"); + k_sem_give(&data->device_sem); + return ret; + } + + if (!is_multipart_started) { + ret = crypto_smartbond_hash_set_out_len(); + if (ret < 0) { + LOG_ERR("Invalid OUT buffer size"); + k_sem_give(&data->device_sem); + return ret; + } + } + + if (!is_multipart_started) { + ret = crypto_smartbond_set_in_out_buf(pkt->in_buf, pkt->out_buf, pkt->in_len); + } else { + /* Destination buffer is being updated as fragmented input is being processed. */ + ret = crypto_smartbond_set_in_out_buf(pkt->in_buf, NULL, pkt->in_len); + } + + if (ret < 0) { + LOG_ERR("Unsupported IN or OUT buffer location"); + k_sem_give(&data->device_sem); + return ret; + } + +#if defined(CONFIG_CRYPTO_ASYNC) + data->hash_pkt = pkt; +#endif + + /* Start hash processing */ + AES_HASH->CRYPTO_START_REG = 1; + +#if !defined(CONFIG_CRYPTO_ASYNC) + k_sem_take(&data->sync_sem, K_FOREVER); +#endif + + k_sem_give(&data->device_sem); + + return 0; +} + +static int +crypto_smartbond_cipher_begin_session(const struct device *dev, struct cipher_ctx *ctx, + enum cipher_algo algo, enum cipher_mode mode, enum cipher_op op_type) +{ + int ret; + + if (ctx->flags & ~(CRYPTO_HW_CAPS)) { + LOG_ERR("Unsupported flag"); + return -EINVAL; + } + + if (algo != CRYPTO_CIPHER_ALGO_AES) { + LOG_ERR("Unsupported cipher algo"); + return -EINVAL; + } + + if (!crypto_smartbond_lock_session(dev)) { + LOG_ERR("No free session for now"); + return -ENOSPC; + } + + ret = crypto_smartbond_cipher_key_load(ctx->key.bit_stream, ctx->keylen); + if (ret < 0) { + LOG_ERR("Invalid key length or key cannot be accessed"); + crypto_smartbond_unlock_session(dev); + return ret; + } + + ret = crypto_smartbond_cipher_set_mode(mode); + if (ret < 0) { + LOG_ERR("Unsupported cipher mode"); + crypto_smartbond_unlock_session(dev); + return ret; + } + + if (op_type == CRYPTO_CIPHER_OP_ENCRYPT) { + AES_HASH->CRYPTO_CTRL_REG |= AES_HASH_CRYPTO_CTRL_REG_CRYPTO_ENCDEC_Msk; + } else { + AES_HASH->CRYPTO_CTRL_REG &= ~(AES_HASH_CRYPTO_CTRL_REG_CRYPTO_ENCDEC_Msk); + } + + /* IN buffer fragmentation is not supported by the driver model */ + AES_HASH->CRYPTO_CTRL_REG &= ~(AES_HASH_CRYPTO_CTRL_REG_CRYPTO_MORE_IN_Msk); + + switch (mode) { + case CRYPTO_CIPHER_MODE_ECB: + ctx->ops.block_crypt_hndlr = crypto_smartbond_cipher_ecb_handler; + break; + case CRYPTO_CIPHER_MODE_CBC: + ctx->ops.cbc_crypt_hndlr = crypto_smartbond_cipher_cbc_handler; + break; + case CRYPTO_CIPHER_MODE_CTR: + ctx->ops.ctr_crypt_hndlr = crypto_smartbond_cipher_ctr_handler; + break; + default: + break; + } + + ctx->drv_sessn_state = NULL; + + return 0; +} + +static int crypto_smartbond_cipher_free_session(const struct device *dev, struct cipher_ctx *ctx) +{ + ARG_UNUSED(ctx); + crypto_smartbond_unlock_session(dev); + + return 0; +} + +#if defined(CONFIG_CRYPTO_ASYNC) +static int +crypto_smartbond_cipher_set_async_callback(const struct device *dev, cipher_completion_cb cb) +{ + struct crypto_smartbond_data *data = dev->data; + + data->cipher_user_cb = cb; + + return 0; +} +#endif + +static int +crypto_smartbond_hash_begin_session(const struct device *dev, + struct hash_ctx *ctx, enum hash_algo algo) +{ + int ret; + + if (ctx->flags & ~(CRYPTO_HW_CAPS)) { + LOG_ERR("Unsupported flag"); + return -EINVAL; + } + + if (!crypto_smartbond_lock_session(dev)) { + LOG_ERR("No free session for now"); + return -ENOSPC; + } + + /* + * Crypto should be disabled only if not used in other sessions. In case of failure, + * developer should next free the current session. + */ + crypto_smartbond_set_status(true); + + ret = crypto_smartbond_hash_set_algo(algo); + if (ret < 0) { + LOG_ERR("Unsupported HASH algo"); + crypto_smartbond_unlock_session(dev); + return ret; + } + + ctx->hash_hndlr = crypto_smartbond_hash_handler; + + ctx->drv_sessn_state = NULL; + + return 0; +} + +static int crypto_smartbond_hash_free_session(const struct device *dev, struct hash_ctx *ctx) +{ + ARG_UNUSED(ctx); + crypto_smartbond_unlock_session(dev); + + return 0; +} + +#if defined(CONFIG_CRYPTO_ASYNC) +static int +crypto_smartbond_hash_set_async_callback(const struct device *dev, hash_completion_cb cb) +{ + struct crypto_smartbond_data *data = dev->data; + + data->hash_user_cb = cb; + + return 0; +} +#endif + +static struct crypto_driver_api crypto_smartbond_driver_api = { + .cipher_begin_session = crypto_smartbond_cipher_begin_session, + .cipher_free_session = crypto_smartbond_cipher_free_session, +#if defined(CONFIG_CRYPTO_ASYNC) + .cipher_async_callback_set = crypto_smartbond_cipher_set_async_callback, +#endif + .hash_begin_session = crypto_smartbond_hash_begin_session, + .hash_free_session = crypto_smartbond_hash_free_session, +#if defined(CONFIG_CRYPTO_ASYNC) + .hash_async_callback_set = crypto_smartbond_hash_set_async_callback, +#endif + .query_hw_caps = crypto_smartbond_query_hw_caps +}; + +static int crypto_smartbond_init(const struct device *dev) +{ + struct crypto_smartbond_data *data = dev->data; + + /* Semaphore used during sessions (begin/free) */ + k_sem_init(&data->session_sem, 1, 1); + + /* Semaphore used to employ the crypto device */ + k_sem_init(&data->device_sem, 1, 1); + +#if !defined(CONFIG_CRYPTO_ASYNC) + /* Sempahore used when sync operations are enabled */ + k_sem_init(&data->sync_sem, 0, 1); +#endif + + IRQ_CONNECT(SMARTBOND_IRQN, SMARTBOND_IRQ_PRIO, smartbond_crypto_isr, + DEVICE_DT_INST_GET(0), 0); + + crypto_smartbond_set_status(false); + + return 0; +} + +/* + * There is only one instance integrated on the SoC. Just in case that assumption becomes invalid + * in the future, we use a BUILD_ASSERT(). + */ +#define SMARTBOND_CRYPTO_INIT(inst) \ + BUILD_ASSERT((inst) == 0, \ + "multiple instances are not supported"); \ + \ + static struct crypto_smartbond_data crypto_smartbond_data_##inst; \ + \ + DEVICE_DT_INST_DEFINE(0, \ + crypto_smartbond_init, NULL, \ + &crypto_smartbond_data_##inst, NULL, \ + POST_KERNEL, \ + CONFIG_CRYPTO_INIT_PRIORITY, \ + &crypto_smartbond_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(SMARTBOND_CRYPTO_INIT) diff --git a/drivers/crypto/crypto_stm32.c b/drivers/crypto/crypto_stm32.c index ca80b2afe35..17250a944a9 100644 --- a/drivers/crypto/crypto_stm32.c +++ b/drivers/crypto/crypto_stm32.c @@ -43,8 +43,13 @@ LOG_MODULE_REGISTER(crypto_stm32); #define STM32_RCC_CRYPTO_RELEASE_RESET __HAL_RCC_CRYP_RELEASE_RESET #define STM32_CRYPTO_TYPEDEF CRYP_TypeDef #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_aes) +#if defined(CONFIG_SOC_SERIES_STM32WBX) +#define STM32_RCC_CRYPTO_FORCE_RESET __HAL_RCC_AES1_FORCE_RESET +#define STM32_RCC_CRYPTO_RELEASE_RESET __HAL_RCC_AES1_RELEASE_RESET +#else #define STM32_RCC_CRYPTO_FORCE_RESET __HAL_RCC_AES_FORCE_RESET #define STM32_RCC_CRYPTO_RELEASE_RESET __HAL_RCC_AES_RELEASE_RESET +#endif #define STM32_CRYPTO_TYPEDEF AES_TypeDef #endif diff --git a/drivers/dac/CMakeLists.txt b/drivers/dac/CMakeLists.txt index 5689bea3086..c84b0d9d78e 100644 --- a/drivers/dac/CMakeLists.txt +++ b/drivers/dac/CMakeLists.txt @@ -4,6 +4,7 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/dac.h) zephyr_library() +zephyr_library_sources_ifdef(CONFIG_DAC_MCUX_LPDAC dac_mcux_lpdac.c) zephyr_library_sources_ifdef(CONFIG_DAC_MCUX_DAC dac_mcux_dac.c) zephyr_library_sources_ifdef(CONFIG_DAC_MCUX_DAC32 dac_mcux_dac32.c) zephyr_library_sources_ifdef(CONFIG_DAC_STM32 dac_stm32.c) @@ -17,4 +18,6 @@ zephyr_library_sources_ifdef(CONFIG_DAC_MCP4725 dac_mcp4725.c) zephyr_library_sources_ifdef(CONFIG_DAC_MCP4728 dac_mcp4728.c) zephyr_library_sources_ifdef(CONFIG_DAC_GD32 dac_gd32.c) zephyr_library_sources_ifdef(CONFIG_DAC_ESP32 dac_esp32.c) +zephyr_library_sources_ifdef(CONFIG_DAC_AD5592 dac_ad5592.c) +zephyr_library_sources_ifdef(CONFIG_DAC_AD56XX dac_ad56xx.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE dac_handlers.c) diff --git a/drivers/dac/Kconfig b/drivers/dac/Kconfig index 77b0db902bf..3735a11aa2a 100644 --- a/drivers/dac/Kconfig +++ b/drivers/dac/Kconfig @@ -19,7 +19,6 @@ source "subsys/logging/Kconfig.template.log_config" config DAC_SHELL bool "DAC shell" - default y depends on SHELL help Enable DAC related shell commands. @@ -52,4 +51,8 @@ source "drivers/dac/Kconfig.gd32" source "drivers/dac/Kconfig.esp32" +source "drivers/dac/Kconfig.ad56xx" + +source "drivers/dac/Kconfig.ad5592" + endif # DAC diff --git a/drivers/dac/Kconfig.ad5592 b/drivers/dac/Kconfig.ad5592 new file mode 100644 index 00000000000..1010992fb7f --- /dev/null +++ b/drivers/dac/Kconfig.ad5592 @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Grinn +# SPDX -License-Identifier: Apache-2.0 + +config DAC_AD5592 + bool "AD5592 DAC driver" + default y + depends on DT_HAS_ADI_AD5592_DAC_ENABLED + select MFD + help + Enable the AD5592 DAC driver. diff --git a/drivers/dac/Kconfig.ad56xx b/drivers/dac/Kconfig.ad56xx new file mode 100644 index 00000000000..7ce2be653f6 --- /dev/null +++ b/drivers/dac/Kconfig.ad56xx @@ -0,0 +1,33 @@ +# DAC configuration options + +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +config DAC_AD56XX + bool "Analog Devices AD56xx DAC driver" + default y + select SPI + depends on DT_HAS_ADI_AD5628_ENABLED \ + || DT_HAS_ADI_AD5648_ENABLED \ + || DT_HAS_ADI_AD5668_ENABLED \ + || DT_HAS_ADI_AD5672_ENABLED \ + || DT_HAS_ADI_AD5674_ENABLED \ + || DT_HAS_ADI_AD5676_ENABLED \ + || DT_HAS_ADI_AD5679_ENABLED \ + || DT_HAS_ADI_AD5684_ENABLED \ + || DT_HAS_ADI_AD5686_ENABLED \ + || DT_HAS_ADI_AD5687_ENABLED \ + || DT_HAS_ADI_AD5689_ENABLED + help + Enable the driver for the Analog Devices AD56xx DAC + +if DAC_AD56XX + +config DAC_AD56XX_INIT_PRIORITY + int "Init priority" + default 80 + help + Analog Devices AD56xx DAC device driver initialization priority. + +endif # DAC_AD56XX diff --git a/drivers/dac/Kconfig.mcux b/drivers/dac/Kconfig.mcux index e02d498f505..87869775d03 100644 --- a/drivers/dac/Kconfig.mcux +++ b/drivers/dac/Kconfig.mcux @@ -19,6 +19,13 @@ config DAC_MCUX_DAC32 help Enable the driver for the NXP Kinetis MCUX DAC32. +config DAC_MCUX_LPDAC + bool "NXP MCUX LPDAC driver" + default y + depends on DT_HAS_NXP_LPDAC_ENABLED + help + Enable the driver for the NXP MCUX LPDAC. + config DAC_MCUX_DAC32_TESTOUT bool "DAC test output" depends on DAC_MCUX_DAC32 diff --git a/drivers/dac/dac_ad5592.c b/drivers/dac/dac_ad5592.c new file mode 100644 index 00000000000..653df85dd56 --- /dev/null +++ b/drivers/dac/dac_ad5592.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2023 Grinn + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT adi_ad5592_dac + +#include +#include +#include + +#include + +#include +LOG_MODULE_REGISTER(dac_ad5592, CONFIG_DAC_LOG_LEVEL); + +#define AD5592_DAC_RESOLUTION 12 +#define AD5592_DAC_WR_MSB_BIT BIT(15) +#define AD5592_DAC_CHANNEL_SHIFT_VAL 12 + +struct dac_ad5592_config { + const struct device *mfd_dev; +}; + +struct dac_ad5592_data { + uint8_t dac_conf; +}; + +static int dac_ad5592_channel_setup(const struct device *dev, + const struct dac_channel_cfg *channel_cfg) +{ + const struct dac_ad5592_config *config = dev->config; + struct dac_ad5592_data *data = dev->data; + + if (channel_cfg->channel_id >= AD5592_PIN_MAX) { + LOG_ERR("Invalid channel number %d", channel_cfg->channel_id); + return -EINVAL; + } + + if (channel_cfg->resolution != AD5592_DAC_RESOLUTION) { + LOG_ERR("Invalid resolution %d", channel_cfg->resolution); + return -EINVAL; + } + + data->dac_conf |= BIT(channel_cfg->channel_id); + + return mfd_ad5592_write_reg(config->mfd_dev, AD5592_REG_LDAC_EN, data->dac_conf); +} + +static int dac_ad5592_write_value(const struct device *dev, uint8_t channel, + uint32_t value) +{ + const struct dac_ad5592_config *config = dev->config; + uint16_t msg; + + if (channel >= AD5592_PIN_MAX) { + LOG_ERR("Invalid channel number %d", channel); + return -EINVAL; + } + + if (value >= (1 << AD5592_DAC_RESOLUTION)) { + LOG_ERR("Value %d out of range", value); + return -EINVAL; + } + + msg = sys_cpu_to_be16(AD5592_DAC_WR_MSB_BIT | + channel << AD5592_DAC_CHANNEL_SHIFT_VAL | + value); + + return mfd_ad5592_write_raw(config->mfd_dev, msg); +} + +static const struct dac_driver_api dac_ad5592_api = { + .channel_setup = dac_ad5592_channel_setup, + .write_value = dac_ad5592_write_value, +}; + +static int dac_ad5592_init(const struct device *dev) +{ + const struct dac_ad5592_config *config = dev->config; + int ret; + + if (!device_is_ready(config->mfd_dev)) { + return -ENODEV; + } + + ret = mfd_ad5592_write_reg(config->mfd_dev, AD5592_REG_PD_REF_CTRL, AD5592_EN_REF); + if (ret < 0) { + return ret; + } + + return 0; +} + +#define DAC_AD5592_DEFINE(inst) \ + static const struct dac_ad5592_config dac_ad5592_config##inst = { \ + .mfd_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ + }; \ + \ + struct dac_ad5592_data dac_ad5592_data##inst; \ + \ + DEVICE_DT_INST_DEFINE(inst, dac_ad5592_init, NULL, \ + &dac_ad5592_data##inst, &dac_ad5592_config##inst, \ + POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, \ + &dac_ad5592_api); + +DT_INST_FOREACH_STATUS_OKAY(DAC_AD5592_DEFINE) diff --git a/drivers/dac/dac_ad56xx.c b/drivers/dac/dac_ad56xx.c new file mode 100644 index 00000000000..fe523288294 --- /dev/null +++ b/drivers/dac/dac_ad56xx.c @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2023 SILA Embedded Solutions GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(dac_ad56xx, CONFIG_DAC_LOG_LEVEL); + +/* + * These values are actually all way less than 1us, but we can only + * wait with 1us precision. + * + * This should be checked when new types of this series are added to + * this implementation. + */ +#define DAC_AD56XX_MINIMUM_PULSE_WIDTH_LOW_IN_US 1 +#define DAC_AD56XX_PULSE_ACTIVATION_TIME_IN_US 1 + +enum ad56xx_command { + AD56XX_CMD_WRITE_UPDATE_CHANNEL = 3, + AD56XX_CMD_SOFTWARE_RESET = 6, +}; + +struct ad56xx_config { + struct spi_dt_spec bus; + const struct gpio_dt_spec gpio_reset; + uint8_t resolution; + + const uint8_t *channel_addresses; + size_t channel_count; +}; + +struct ad56xx_data { +}; + +static int ad56xx_write_command(const struct device *dev, enum ad56xx_command command, + uint8_t address, uint16_t value) +{ + const struct ad56xx_config *config = dev->config; + uint8_t buffer_tx[3]; + uint8_t buffer_rx[ARRAY_SIZE(buffer_tx)]; + const struct spi_buf tx_buf[] = {{ + .buf = buffer_tx, + .len = ARRAY_SIZE(buffer_tx), + }}; + const struct spi_buf rx_buf[] = {{ + .buf = buffer_rx, + .len = ARRAY_SIZE(buffer_rx), + }}; + const struct spi_buf_set tx = { + .buffers = tx_buf, + .count = ARRAY_SIZE(tx_buf), + }; + const struct spi_buf_set rx = { + .buffers = rx_buf, + .count = ARRAY_SIZE(rx_buf), + }; + + buffer_tx[0] = (command << 4) | address; + value = value << (16 - config->resolution); + sys_put_be16(value, buffer_tx + 1); + + LOG_DBG("sending to DAC %s command 0x%02X, address 0x%02X and value 0x%04X", dev->name, + command, address, value); + int result = spi_transceive_dt(&config->bus, &tx, &rx); + + if (result != 0) { + LOG_ERR("spi_transceive failed with error %i", result); + return result; + } + + return 0; +} + +static int ad56xx_channel_setup(const struct device *dev, const struct dac_channel_cfg *channel_cfg) +{ + const struct ad56xx_config *config = dev->config; + + if (channel_cfg->channel_id >= config->channel_count) { + LOG_ERR("invalid channel %i", channel_cfg->channel_id); + return -EINVAL; + } + + if (channel_cfg->resolution != config->resolution) { + LOG_ERR("invalid resolution %i", channel_cfg->resolution); + return -EINVAL; + } + + return 0; +} + +static int ad56xx_write_value(const struct device *dev, uint8_t channel, uint32_t value) +{ + const struct ad56xx_config *config = dev->config; + + if (value > BIT(config->resolution) - 1) { + LOG_ERR("invalid value %i", value); + return -EINVAL; + } + + if (channel > config->channel_count) { + LOG_ERR("invalid channel %i", channel); + return -EINVAL; + } + + return ad56xx_write_command(dev, AD56XX_CMD_WRITE_UPDATE_CHANNEL, + config->channel_addresses[channel], value); +} + +static int ad56xx_init(const struct device *dev) +{ + const struct ad56xx_config *config = dev->config; + int result; + + if (!spi_is_ready_dt(&config->bus)) { + LOG_ERR("SPI bus %s not ready", config->bus.bus->name); + return -ENODEV; + } + + if (config->gpio_reset.port != NULL) { + LOG_DBG("reset %s with GPIO", dev->name); + result = gpio_pin_configure_dt(&config->gpio_reset, GPIO_OUTPUT_ACTIVE); + if (result != 0) { + LOG_ERR("failed to initialize GPIO for reset"); + return result; + } + + k_busy_wait(DAC_AD56XX_MINIMUM_PULSE_WIDTH_LOW_IN_US); + gpio_pin_set_dt(&config->gpio_reset, 0); + } else { + LOG_DBG("reset %s with command", dev->name); + result = ad56xx_write_command(dev, AD56XX_CMD_SOFTWARE_RESET, 0, 0); + if (result != 0) { + LOG_ERR("failed to send reset command"); + return result; + } + } + + /* + * The pulse activation time is actually defined to start together + * with the pulse start. To be on the safe side we add the wait time + * on top of the actual pulse. + */ + k_busy_wait(DAC_AD56XX_PULSE_ACTIVATION_TIME_IN_US); + + return 0; +} + +static const struct dac_driver_api ad56xx_driver_api = { + .channel_setup = ad56xx_channel_setup, + .write_value = ad56xx_write_value, +}; + +BUILD_ASSERT(CONFIG_DAC_AD56XX_INIT_PRIORITY > CONFIG_SPI_INIT_PRIORITY, + "CONFIG_DAC_AD56XX_INIT_PRIORITY must be higher than CONFIG_SPI_INIT_PRIORITY"); + +#define DAC_AD56XX_INST_DEFINE(index, name, res, channels, channels_count) \ + static struct ad56xx_data data_##name##_##index; \ + static const struct ad56xx_config config_##name##_##index = { \ + .bus = SPI_DT_SPEC_INST_GET( \ + index, SPI_OP_MODE_MASTER | SPI_MODE_CPHA | SPI_WORD_SET(8), 0), \ + .resolution = res, \ + .gpio_reset = GPIO_DT_SPEC_INST_GET_OR(index, reset_gpios, {0}), \ + .channel_addresses = channels, \ + .channel_count = channels_count, \ + }; \ + DEVICE_DT_INST_DEFINE(index, ad56xx_init, NULL, &data_##name##_##index, \ + &config_##name##_##index, POST_KERNEL, \ + CONFIG_DAC_AD56XX_INIT_PRIORITY, &ad56xx_driver_api); + +#define DT_DRV_COMPAT adi_ad5628 +#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) +static const uint8_t ad5628_channels[] = { + 0, 1, 2, 3, 4, 5, 6, 7, +}; +#define DAC_AD5628_RESOLUTION 12 +#define DAC_AD5628_CHANNELS ad5628_channels +#define DAC_AD5628_CHANNEL_COUNT ARRAY_SIZE(ad5628_channels) +DT_INST_FOREACH_STATUS_OKAY_VARGS(DAC_AD56XX_INST_DEFINE, DT_DRV_COMPAT, DAC_AD5628_RESOLUTION, + DAC_AD5628_CHANNELS, DAC_AD5628_CHANNEL_COUNT) +#endif +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT adi_ad5648 +#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) +static const uint8_t ad5648_channels[] = { + 0, 1, 2, 3, 4, 5, 6, 7, +}; +#define DAC_AD5648_RESOLUTION 14 +#define DAC_AD5648_CHANNELS ad5648_channels +#define DAC_AD5648_CHANNEL_COUNT ARRAY_SIZE(ad5648_channels) +DT_INST_FOREACH_STATUS_OKAY_VARGS(DAC_AD56XX_INST_DEFINE, DT_DRV_COMPAT, DAC_AD5648_RESOLUTION, + DAC_AD5648_CHANNELS, DAC_AD5648_CHANNEL_COUNT) +#endif +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT adi_ad5668 +#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) +static const uint8_t ad5668_channels[] = { + 0, 1, 2, 3, 4, 5, 6, 7, +}; +#define DAC_AD5668_RESOLUTION 16 +#define DAC_AD5668_CHANNELS ad5668_channels +#define DAC_AD5668_CHANNEL_COUNT ARRAY_SIZE(ad5668_channels) +DT_INST_FOREACH_STATUS_OKAY_VARGS(DAC_AD56XX_INST_DEFINE, DT_DRV_COMPAT, DAC_AD5668_RESOLUTION, + DAC_AD5668_CHANNELS, DAC_AD5668_CHANNEL_COUNT) +#endif +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT adi_ad5672 +#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) +static const uint8_t ad5672_channels[] = { + 0, 1, 2, 3, 4, 5, 6, 7, +}; +#define DAC_AD5672_RESOLUTION 12 +#define DAC_AD5672_CHANNELS ad5672_channels +#define DAC_AD5672_CHANNEL_COUNT ARRAY_SIZE(ad5672_channels) +DT_INST_FOREACH_STATUS_OKAY_VARGS(DAC_AD56XX_INST_DEFINE, DT_DRV_COMPAT, DAC_AD5672_RESOLUTION, + DAC_AD5672_CHANNELS, DAC_AD5672_CHANNEL_COUNT) +#endif +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT adi_ad5674 +#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) +static const uint8_t ad5674_channels[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, +}; +#define DAC_AD5674_RESOLUTION 12 +#define DAC_AD5674_CHANNELS ad5674_channels +#define DAC_AD5674_CHANNEL_COUNT ARRAY_SIZE(ad5674_channels) +DT_INST_FOREACH_STATUS_OKAY_VARGS(DAC_AD56XX_INST_DEFINE, DT_DRV_COMPAT, DAC_AD5674_RESOLUTION, + DAC_AD5674_CHANNELS, DAC_AD5674_CHANNEL_COUNT) +#endif +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT adi_ad5676 +#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) +static const uint8_t ad5676_channels[] = { + 0, 1, 2, 3, 4, 5, 6, 7, +}; +#define DAC_AD5676_RESOLUTION 16 +#define DAC_AD5676_CHANNELS ad5676_channels +#define DAC_AD5676_CHANNEL_COUNT ARRAY_SIZE(ad5676_channels) +DT_INST_FOREACH_STATUS_OKAY_VARGS(DAC_AD56XX_INST_DEFINE, DT_DRV_COMPAT, DAC_AD5676_RESOLUTION, + DAC_AD5676_CHANNELS, DAC_AD5676_CHANNEL_COUNT) +#endif +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT adi_ad5679 +#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) +static const uint8_t ad5679_channels[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, +}; +#define DAC_AD5679_RESOLUTION 16 +#define DAC_AD5679_CHANNELS ad5679_channels +#define DAC_AD5679_CHANNEL_COUNT ARRAY_SIZE(ad5679_channels) +DT_INST_FOREACH_STATUS_OKAY_VARGS(DAC_AD56XX_INST_DEFINE, DT_DRV_COMPAT, DAC_AD5679_RESOLUTION, + DAC_AD5679_CHANNELS, DAC_AD5679_CHANNEL_COUNT) +#endif +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT adi_ad5684 +#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) +static const uint8_t ad5684_channels[] = { + 1, + 2, + 4, + 8, +}; +#define DAC_AD5684_RESOLUTION 12 +#define DAC_AD5684_CHANNELS ad5684_channels +#define DAC_AD5684_CHANNEL_COUNT ARRAY_SIZE(ad5684_channels) +DT_INST_FOREACH_STATUS_OKAY_VARGS(DAC_AD56XX_INST_DEFINE, DT_DRV_COMPAT, DAC_AD5684_RESOLUTION, + DAC_AD5684_CHANNELS, DAC_AD5684_CHANNEL_COUNT) +#endif +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT adi_ad5686 +#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) +static const uint8_t ad5686_channels[] = { + 1, + 2, + 4, + 8, +}; +#define DAC_AD5686_RESOLUTION 16 +#define DAC_AD5686_CHANNELS ad5686_channels +#define DAC_AD5686_CHANNEL_COUNT ARRAY_SIZE(ad5686_channels) +DT_INST_FOREACH_STATUS_OKAY_VARGS(DAC_AD56XX_INST_DEFINE, DT_DRV_COMPAT, DAC_AD5686_RESOLUTION, + DAC_AD5686_CHANNELS, DAC_AD5686_CHANNEL_COUNT) +#endif +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT adi_ad5687 +#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) +static const uint8_t ad5687_channels[] = { + 1, + 8, +}; +#define DAC_AD5687_RESOLUTION 12 +#define DAC_AD5687_CHANNELS ad5687_channels +#define DAC_AD5687_CHANNEL_COUNT ARRAY_SIZE(ad5687_channels) +DT_INST_FOREACH_STATUS_OKAY_VARGS(DAC_AD56XX_INST_DEFINE, DT_DRV_COMPAT, DAC_AD5687_RESOLUTION, + DAC_AD5687_CHANNELS, DAC_AD5687_CHANNEL_COUNT) +#endif +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT adi_ad5689 +#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) +static const uint8_t ad5689_channels[] = { + 1, + 8, +}; +#define DAC_AD5689_RESOLUTION 16 +#define DAC_AD5689_CHANNELS ad5689_channels +#define DAC_AD5689_CHANNEL_COUNT ARRAY_SIZE(ad5689_channels) +DT_INST_FOREACH_STATUS_OKAY_VARGS(DAC_AD56XX_INST_DEFINE, DT_DRV_COMPAT, DAC_AD5689_RESOLUTION, + DAC_AD5689_CHANNELS, DAC_AD5689_CHANNEL_COUNT) +#endif +#undef DT_DRV_COMPAT diff --git a/drivers/dac/dac_handlers.c b/drivers/dac/dac_handlers.c index aa6660651e2..bd9ee0bc7e0 100644 --- a/drivers/dac/dac_handlers.c +++ b/drivers/dac/dac_handlers.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include static inline int z_vrfy_dac_channel_setup(const struct device *dev, @@ -13,8 +13,8 @@ static inline int z_vrfy_dac_channel_setup(const struct device *dev, { struct dac_channel_cfg channel_cfg; - Z_OOPS(Z_SYSCALL_DRIVER_DAC(dev, channel_setup)); - Z_OOPS(z_user_from_copy(&channel_cfg, + K_OOPS(K_SYSCALL_DRIVER_DAC(dev, channel_setup)); + K_OOPS(k_usermode_from_copy(&channel_cfg, (struct dac_channel_cfg *)user_channel_cfg, sizeof(struct dac_channel_cfg))); @@ -26,7 +26,7 @@ static inline int z_vrfy_dac_channel_setup(const struct device *dev, static inline int z_vrfy_dac_write_value(const struct device *dev, uint8_t channel, uint32_t value) { - Z_OOPS(Z_SYSCALL_DRIVER_DAC(dev, write_value)); + K_OOPS(K_SYSCALL_DRIVER_DAC(dev, write_value)); return z_impl_dac_write_value((const struct device *)dev, channel, value); diff --git a/drivers/dac/dac_mcux_lpdac.c b/drivers/dac/dac_mcux_lpdac.c new file mode 100644 index 00000000000..d65624940e7 --- /dev/null +++ b/drivers/dac/dac_mcux_lpdac.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2020 Henrik Brix Andersen + * Copyright (c) 2023, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ +#define DT_DRV_COMPAT nxp_lpdac + +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(dac_mcux_lpdac, CONFIG_DAC_LOG_LEVEL); + +struct mcux_lpdac_config { + LPDAC_Type *base; + dac_reference_voltage_source_t ref_voltage; + bool low_power; +}; + +struct mcux_lpdac_data { + bool configured; +}; + +static int mcux_lpdac_channel_setup(const struct device *dev, + const struct dac_channel_cfg *channel_cfg) +{ + const struct mcux_lpdac_config *config = dev->config; + struct mcux_lpdac_data *data = dev->data; + dac_config_t dac_config; + + if (channel_cfg->channel_id != 0) { + LOG_ERR("unsupported channel %d", channel_cfg->channel_id); + return -ENOTSUP; + } + + if (channel_cfg->resolution != 12) { + LOG_ERR("unsupported resolution %d", channel_cfg->resolution); + return -ENOTSUP; + } + + DAC_GetDefaultConfig(&dac_config); + dac_config.referenceVoltageSource = config->ref_voltage; +#if defined(FSL_FEATURE_LPDAC_HAS_GCR_BUF_SPD_CTRL) && FSL_FEATURE_LPDAC_HAS_GCR_BUF_SPD_CTRL + dac_config.enableLowerLowPowerMode = config->low_power; +#else + dac_config.enableLowPowerMode = config->low_power; +#endif + DAC_Init(config->base, &dac_config); + DAC_Enable(config->base, false); + data->configured = true; + + return 0; +} + +static int mcux_lpdac_write_value(const struct device *dev, uint8_t channel, uint32_t value) +{ + const struct mcux_lpdac_config *config = dev->config; + struct mcux_lpdac_data *data = dev->data; + + if (!data->configured) { + LOG_ERR("channel not initialized"); + return -EINVAL; + } + + if (channel != 0) { + LOG_ERR("unsupported channel %d", channel); + return -ENOTSUP; + } + + if (value >= 4096) { + LOG_ERR("unsupported value %d", value); + return -EINVAL; + } + + DAC_Enable(config->base, true); + DAC_SetData(config->base, value); + + return 0; +} + +static int mcux_lpdac_init(const struct device *dev) +{ + return 0; +} + +static const struct dac_driver_api mcux_lpdac_driver_api = { + .channel_setup = mcux_lpdac_channel_setup, + .write_value = mcux_lpdac_write_value, +}; + +#define MCUX_LPDAC_INIT(n) \ + static struct mcux_lpdac_data mcux_lpdac_data_##n; \ + \ + static const struct mcux_lpdac_config mcux_lpdac_config_##n = { \ + .base = (LPDAC_Type *)DT_INST_REG_ADDR(n), \ + .ref_voltage = DT_INST_PROP(n, voltage_reference), \ + .low_power = DT_INST_PROP(n, low_power_mode), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, mcux_lpdac_init, NULL, &mcux_lpdac_data_##n, \ + &mcux_lpdac_config_##n, POST_KERNEL, CONFIG_DAC_INIT_PRIORITY, \ + &mcux_lpdac_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(MCUX_LPDAC_INIT) diff --git a/drivers/dai/intel/alh/Kconfig.alh b/drivers/dai/intel/alh/Kconfig.alh index e2885a29e5d..785074454fb 100644 --- a/drivers/dai/intel/alh/Kconfig.alh +++ b/drivers/dai/intel/alh/Kconfig.alh @@ -16,8 +16,9 @@ config DAI_INTEL_ALH if DAI_INTEL_ALH config DAI_ALH_HAS_OWNERSHIP - bool "Intel ALH driver has ownership" - default y if SOC_SERIES_INTEL_ACE + bool "Intel ALH driver has ownership only on ACE 1.5" + default y + depends on SOC_INTEL_ACE15_MTPM help Select this to enable programming HW ownership diff --git a/drivers/dai/intel/dmic/dmic.c b/drivers/dai/intel/dmic/dmic.c index fcc9b119670..3da5fb8c538 100644 --- a/drivers/dai/intel/dmic/dmic.c +++ b/drivers/dai/intel/dmic/dmic.c @@ -527,11 +527,20 @@ static void dai_dmic_gain_ramp(struct dai_intel_dmic *dmic) FIR_CONTROL_MUTE, 0); } - val = FIELD_PREP(OUT_GAIN, gval); - dai_dmic_write(dmic, dmic_base[i] + FIR_CHANNEL_REGS_SIZE * - dmic->dai_config_params.dai_index + OUT_GAIN_LEFT, val); - dai_dmic_write(dmic, dmic_base[i] + FIR_CHANNEL_REGS_SIZE * - dmic->dai_config_params.dai_index + OUT_GAIN_RIGHT, val); + if (gval != 0) { + val = FIELD_PREP(OUT_GAIN, gval); + dai_dmic_write(dmic, dmic_base[i] + FIR_CHANNEL_REGS_SIZE * + dmic->dai_config_params.dai_index + OUT_GAIN_LEFT, val); + dai_dmic_write(dmic, dmic_base[i] + FIR_CHANNEL_REGS_SIZE * + dmic->dai_config_params.dai_index + OUT_GAIN_RIGHT, val); + } else { + dai_dmic_write(dmic, dmic_base[i] + FIR_CHANNEL_REGS_SIZE * + dmic->dai_config_params.dai_index + OUT_GAIN_LEFT, + dmic->gain_left); + dai_dmic_write(dmic, dmic_base[i] + FIR_CHANNEL_REGS_SIZE * + dmic->dai_config_params.dai_index + OUT_GAIN_RIGHT, + dmic->gain_right); + } } k_spin_unlock(&dmic->lock, key); diff --git a/drivers/dai/intel/dmic/dmic.h b/drivers/dai/intel/dmic/dmic.h index 52399106925..e06ed80daed 100644 --- a/drivers/dai/intel/dmic/dmic.h +++ b/drivers/dai/intel/dmic/dmic.h @@ -179,6 +179,8 @@ struct dai_intel_dmic { #endif int irq; uint32_t flags; + uint32_t gain_left; + uint32_t gain_right; }; static inline int32_t sat_int32(int64_t x) diff --git a/drivers/dai/intel/dmic/dmic_nhlt.c b/drivers/dai/intel/dmic/dmic_nhlt.c index 9e3b08072cd..17a8f385a02 100644 --- a/drivers/dai/intel/dmic/dmic_nhlt.c +++ b/drivers/dai/intel/dmic/dmic_nhlt.c @@ -621,6 +621,9 @@ static void configure_fir(struct dai_intel_dmic *dmic, const uint32_t base, dai_dmic_write(dmic, base + DC_OFFSET_RIGHT, fir_cfg->dc_offset_right); dai_dmic_write(dmic, base + OUT_GAIN_LEFT, fir_cfg->out_gain_left); dai_dmic_write(dmic, base + OUT_GAIN_RIGHT, fir_cfg->out_gain_right); + + dmic->gain_left = fir_cfg->out_gain_left; + dmic->gain_right = fir_cfg->out_gain_right; } int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cfg) diff --git a/drivers/disk/Kconfig.ram b/drivers/disk/Kconfig.ram index b662c41fa3a..f09bd3af45f 100644 --- a/drivers/disk/Kconfig.ram +++ b/drivers/disk/Kconfig.ram @@ -3,6 +3,7 @@ config DISK_DRIVER_RAM bool "RAM Disk" + default y if DT_HAS_ZEPHYR_RAM_DISK_ENABLED help RAM buffer used to emulate storage disk. This option can be used to test the file @@ -10,18 +11,6 @@ config DISK_DRIVER_RAM if DISK_DRIVER_RAM -config DISK_RAM_VOLUME_SIZE - int "RAM Disk size in kilobytes" - default 96 - help - Size of the RAM Disk. - -config DISK_RAM_VOLUME_NAME - string "RAM Disk mount point or drive name" - default "RAM" - help - Disk name as per file system naming guidelines. - module = RAMDISK module-str = ramdisk source "subsys/logging/Kconfig.template.log_config" diff --git a/drivers/disk/mmc_subsys.c b/drivers/disk/mmc_subsys.c index 8af8a01991e..455d56818d3 100644 --- a/drivers/disk/mmc_subsys.c +++ b/drivers/disk/mmc_subsys.c @@ -21,6 +21,7 @@ enum sd_status { struct mmc_config { const struct device *host_controller; + uint8_t bus_width; }; struct mmc_data { @@ -104,8 +105,10 @@ static struct disk_info mmc_disk = { static int disk_mmc_init(const struct device *dev) { struct mmc_data *data = dev->data; + const struct mmc_config *config = dev->config; data->status = SD_UNINIT; + data->card.bus_width = config->bus_width; mmc_disk.dev = dev; mmc_disk.name = data->name; @@ -115,6 +118,7 @@ static int disk_mmc_init(const struct device *dev) #define DISK_ACCESS_MMC_INIT(n) \ static const struct mmc_config mmc_config_##n = { \ .host_controller = DEVICE_DT_GET(DT_INST_PARENT(n)), \ + .bus_width = DT_INST_PROP(n, bus_width), \ }; \ \ static struct mmc_data mmc_data_##n = { \ diff --git a/drivers/disk/nvme/nvme_cmd.c b/drivers/disk/nvme/nvme_cmd.c index f6633b7dec1..fb0bcb2d70c 100644 --- a/drivers/disk/nvme/nvme_cmd.c +++ b/drivers/disk/nvme/nvme_cmd.c @@ -26,6 +26,174 @@ static void request_timeout(struct k_work *work); static K_WORK_DELAYABLE_DEFINE(request_timer, request_timeout); +#ifdef CONFIG_NVME_LOG_LEVEL_DBG +struct nvme_status_string { + uint16_t sc; + const char *str; +}; + +static struct nvme_status_string generic_status[] = { + { NVME_SC_SUCCESS, "SUCCESS" }, + { NVME_SC_INVALID_OPCODE, "INVALID OPCODE" }, + { NVME_SC_INVALID_FIELD, "INVALID_FIELD" }, + { NVME_SC_COMMAND_ID_CONFLICT, "COMMAND ID CONFLICT" }, + { NVME_SC_DATA_TRANSFER_ERROR, "DATA TRANSFER ERROR" }, + { NVME_SC_ABORTED_POWER_LOSS, "ABORTED - POWER LOSS" }, + { NVME_SC_INTERNAL_DEVICE_ERROR, "INTERNAL DEVICE ERROR" }, + { NVME_SC_ABORTED_BY_REQUEST, "ABORTED - BY REQUEST" }, + { NVME_SC_ABORTED_SQ_DELETION, "ABORTED - SQ DELETION" }, + { NVME_SC_ABORTED_FAILED_FUSED, "ABORTED - FAILED FUSED" }, + { NVME_SC_ABORTED_MISSING_FUSED, "ABORTED - MISSING FUSED" }, + { NVME_SC_INVALID_NAMESPACE_OR_FORMAT, "INVALID NAMESPACE OR FORMAT" }, + { NVME_SC_COMMAND_SEQUENCE_ERROR, "COMMAND SEQUENCE ERROR" }, + { NVME_SC_INVALID_SGL_SEGMENT_DESCR, "INVALID SGL SEGMENT DESCRIPTOR" }, + { NVME_SC_INVALID_NUMBER_OF_SGL_DESCR, "INVALID NUMBER OF SGL DESCRIPTORS" }, + { NVME_SC_DATA_SGL_LENGTH_INVALID, "DATA SGL LENGTH INVALID" }, + { NVME_SC_METADATA_SGL_LENGTH_INVALID, "METADATA SGL LENGTH INVALID" }, + { NVME_SC_SGL_DESCRIPTOR_TYPE_INVALID, "SGL DESCRIPTOR TYPE INVALID" }, + { NVME_SC_INVALID_USE_OF_CMB, "INVALID USE OF CONTROLLER MEMORY BUFFER" }, + { NVME_SC_PRP_OFFSET_INVALID, "PRP OFFSET INVALID" }, + { NVME_SC_ATOMIC_WRITE_UNIT_EXCEEDED, "ATOMIC WRITE UNIT EXCEEDED" }, + { NVME_SC_OPERATION_DENIED, "OPERATION DENIED" }, + { NVME_SC_SGL_OFFSET_INVALID, "SGL OFFSET INVALID" }, + { NVME_SC_HOST_ID_INCONSISTENT_FORMAT, "HOST IDENTIFIER INCONSISTENT FORMAT" }, + { NVME_SC_KEEP_ALIVE_TIMEOUT_EXPIRED, "KEEP ALIVE TIMEOUT EXPIRED" }, + { NVME_SC_KEEP_ALIVE_TIMEOUT_INVALID, "KEEP ALIVE TIMEOUT INVALID" }, + { NVME_SC_ABORTED_DUE_TO_PREEMPT, "COMMAND ABORTED DUE TO PREEMPT AND ABORT" }, + { NVME_SC_SANITIZE_FAILED, "SANITIZE FAILED" }, + { NVME_SC_SANITIZE_IN_PROGRESS, "SANITIZE IN PROGRESS" }, + { NVME_SC_SGL_DATA_BLOCK_GRAN_INVALID, "SGL_DATA_BLOCK_GRANULARITY_INVALID" }, + { NVME_SC_NOT_SUPPORTED_IN_CMB, "COMMAND NOT SUPPORTED FOR QUEUE IN CMB" }, + { NVME_SC_NAMESPACE_IS_WRITE_PROTECTED, "NAMESPACE IS WRITE PROTECTED" }, + { NVME_SC_COMMAND_INTERRUPTED, "COMMAND INTERRUPTED" }, + { NVME_SC_TRANSIENT_TRANSPORT_ERROR, "TRANSIENT TRANSPORT ERROR" }, + { NVME_SC_LBA_OUT_OF_RANGE, "LBA OUT OF RANGE" }, + { NVME_SC_CAPACITY_EXCEEDED, "CAPACITY EXCEEDED" }, + { NVME_SC_NAMESPACE_NOT_READY, "NAMESPACE NOT READY" }, + { NVME_SC_RESERVATION_CONFLICT, "RESERVATION CONFLICT" }, + { NVME_SC_FORMAT_IN_PROGRESS, "FORMAT IN PROGRESS" }, + { 0xFFFF, "GENERIC" } +}; + +static struct nvme_status_string command_specific_status[] = { + { NVME_SC_COMPLETION_QUEUE_INVALID, "INVALID COMPLETION QUEUE" }, + { NVME_SC_INVALID_QUEUE_IDENTIFIER, "INVALID QUEUE IDENTIFIER" }, + { NVME_SC_MAXIMUM_QUEUE_SIZE_EXCEEDED, "MAX QUEUE SIZE EXCEEDED" }, + { NVME_SC_ABORT_COMMAND_LIMIT_EXCEEDED, "ABORT CMD LIMIT EXCEEDED" }, + { NVME_SC_ASYNC_EVENT_REQUEST_LIMIT_EXCEEDED, "ASYNC LIMIT EXCEEDED" }, + { NVME_SC_INVALID_FIRMWARE_SLOT, "INVALID FIRMWARE SLOT" }, + { NVME_SC_INVALID_FIRMWARE_IMAGE, "INVALID FIRMWARE IMAGE" }, + { NVME_SC_INVALID_INTERRUPT_VECTOR, "INVALID INTERRUPT VECTOR" }, + { NVME_SC_INVALID_LOG_PAGE, "INVALID LOG PAGE" }, + { NVME_SC_INVALID_FORMAT, "INVALID FORMAT" }, + { NVME_SC_FIRMWARE_REQUIRES_RESET, "FIRMWARE REQUIRES RESET" }, + { NVME_SC_INVALID_QUEUE_DELETION, "INVALID QUEUE DELETION" }, + { NVME_SC_FEATURE_NOT_SAVEABLE, "FEATURE IDENTIFIER NOT SAVEABLE" }, + { NVME_SC_FEATURE_NOT_CHANGEABLE, "FEATURE NOT CHANGEABLE" }, + { NVME_SC_FEATURE_NOT_NS_SPECIFIC, "FEATURE NOT NAMESPACE SPECIFIC" }, + { NVME_SC_FW_ACT_REQUIRES_NVMS_RESET, "FIRMWARE ACTIVATION REQUIRES NVM SUBSYSTEM RESET" }, + { NVME_SC_FW_ACT_REQUIRES_RESET, "FIRMWARE ACTIVATION REQUIRES RESET" }, + { NVME_SC_FW_ACT_REQUIRES_TIME, "FIRMWARE ACTIVATION REQUIRES MAXIMUM TIME VIOLATION" }, + { NVME_SC_FW_ACT_PROHIBITED, "FIRMWARE ACTIVATION PROHIBITED" }, + { NVME_SC_OVERLAPPING_RANGE, "OVERLAPPING RANGE" }, + { NVME_SC_NS_INSUFFICIENT_CAPACITY, "NAMESPACE INSUFFICIENT CAPACITY" }, + { NVME_SC_NS_ID_UNAVAILABLE, "NAMESPACE IDENTIFIER UNAVAILABLE" }, + { NVME_SC_NS_ALREADY_ATTACHED, "NAMESPACE ALREADY ATTACHED" }, + { NVME_SC_NS_IS_PRIVATE, "NAMESPACE IS PRIVATE" }, + { NVME_SC_NS_NOT_ATTACHED, "NS NOT ATTACHED" }, + { NVME_SC_THIN_PROV_NOT_SUPPORTED, "THIN PROVISIONING NOT SUPPORTED" }, + { NVME_SC_CTRLR_LIST_INVALID, "CONTROLLER LIST INVALID" }, + { NVME_SC_SELF_TEST_IN_PROGRESS, "DEVICE SELF-TEST IN PROGRESS" }, + { NVME_SC_BOOT_PART_WRITE_PROHIB, "BOOT PARTITION WRITE PROHIBITED" }, + { NVME_SC_INVALID_CTRLR_ID, "INVALID CONTROLLER IDENTIFIER" }, + { NVME_SC_INVALID_SEC_CTRLR_STATE, "INVALID SECONDARY CONTROLLER STATE" }, + { NVME_SC_INVALID_NUM_OF_CTRLR_RESRC, "INVALID NUMBER OF CONTROLLER RESOURCES" }, + { NVME_SC_INVALID_RESOURCE_ID, "INVALID RESOURCE IDENTIFIER" }, + { NVME_SC_SANITIZE_PROHIBITED_WPMRE, + "SANITIZE PROHIBITED WRITE PERSISTENT MEMORY REGION ENABLED" }, + { NVME_SC_ANA_GROUP_ID_INVALID, "ANA GROUP IDENTIFIED INVALID" }, + { NVME_SC_ANA_ATTACH_FAILED, "ANA ATTACH FAILED" }, + { NVME_SC_CONFLICTING_ATTRIBUTES, "CONFLICTING ATTRIBUTES" }, + { NVME_SC_INVALID_PROTECTION_INFO, "INVALID PROTECTION INFO" }, + { NVME_SC_ATTEMPTED_WRITE_TO_RO_PAGE, "WRITE TO RO PAGE" }, + { 0xFFFF, "COMMAND SPECIFIC" } +}; + +static struct nvme_status_string media_error_status[] = { + { NVME_SC_WRITE_FAULTS, "WRITE FAULTS" }, + { NVME_SC_UNRECOVERED_READ_ERROR, "UNRECOVERED READ ERROR" }, + { NVME_SC_GUARD_CHECK_ERROR, "GUARD CHECK ERROR" }, + { NVME_SC_APPLICATION_TAG_CHECK_ERROR, "APPLICATION TAG CHECK ERROR" }, + { NVME_SC_REFERENCE_TAG_CHECK_ERROR, "REFERENCE TAG CHECK ERROR" }, + { NVME_SC_COMPARE_FAILURE, "COMPARE FAILURE" }, + { NVME_SC_ACCESS_DENIED, "ACCESS DENIED" }, + { NVME_SC_DEALLOCATED_OR_UNWRITTEN, "DEALLOCATED OR UNWRITTEN LOGICAL BLOCK" }, + { 0xFFFF, "MEDIA ERROR" } +}; + +static struct nvme_status_string path_related_status[] = { + { NVME_SC_INTERNAL_PATH_ERROR, "INTERNAL PATH ERROR" }, + { NVME_SC_ASYMMETRIC_ACCESS_PERSISTENT_LOSS, "ASYMMETRIC ACCESS PERSISTENT LOSS" }, + { NVME_SC_ASYMMETRIC_ACCESS_INACCESSIBLE, "ASYMMETRIC ACCESS INACCESSIBLE" }, + { NVME_SC_ASYMMETRIC_ACCESS_TRANSITION, "ASYMMETRIC ACCESS TRANSITION" }, + { NVME_SC_CONTROLLER_PATHING_ERROR, "CONTROLLER PATHING ERROR" }, + { NVME_SC_HOST_PATHING_ERROR, "HOST PATHING ERROR" }, + { NVME_SC_COMMAND_ABORTED_BY_HOST, "COMMAND ABORTED BY HOST" }, + { 0xFFFF, "PATH RELATED" }, +}; + +static const char *get_status_string(uint16_t sct, uint16_t sc) +{ + struct nvme_status_string *entry; + + switch (sct) { + case NVME_SCT_GENERIC: + entry = generic_status; + break; + case NVME_SCT_COMMAND_SPECIFIC: + entry = command_specific_status; + break; + case NVME_SCT_MEDIA_ERROR: + entry = media_error_status; + break; + case NVME_SCT_PATH_RELATED: + entry = path_related_status; + break; + case NVME_SCT_VENDOR_SPECIFIC: + return "VENDOR SPECIFIC"; + default: + return "RESERVED"; + } + + while (entry->sc != 0xFFFF) { + if (entry->sc == sc) { + return entry->str; + } + + entry++; + } + return entry->str; +} + +void nvme_completion_print(const struct nvme_completion *cpl) +{ + uint8_t sct, sc, crd, m, dnr, p; + + sct = NVME_STATUS_GET_SCT(cpl->status); + sc = NVME_STATUS_GET_SC(cpl->status); + crd = NVME_STATUS_GET_CRD(cpl->status); + m = NVME_STATUS_GET_M(cpl->status); + dnr = NVME_STATUS_GET_DNR(cpl->status); + p = NVME_STATUS_GET_P(cpl->status); + + LOG_DBG("%s (%02x/%02x) crd:%x m:%x dnr:%x p:%d " + "sqid:%d cid:%d cdw0:%x\n", + get_status_string(sct, sc), sct, sc, crd, m, dnr, p, + cpl->sqid, cpl->cid, cpl->cdw0); +} + +#endif /* CONFIG_NVME_LOG_LEVEL_DBG */ + void nvme_cmd_init(void) { int idx; @@ -399,6 +567,32 @@ static int nvme_cmd_qpair_fill_prp_list(struct nvme_cmd_qpair *qpair, return 0; } +static int compute_n_prp(uintptr_t addr, uint32_t size) +{ + int n_prp; + + /* See Common Command Format, Data Pointer (DPTR) field */ + + n_prp = size / CONFIG_MMU_PAGE_SIZE; + if (n_prp == 0) { + n_prp = 1; + } + + if (size != CONFIG_MMU_PAGE_SIZE) { + size = size % CONFIG_MMU_PAGE_SIZE; + } + + if (n_prp == 1) { + if ((addr + (uintptr_t)size) > NVME_PRP_NEXT_PAGE(addr)) { + n_prp++; + } + } else if (size > 0) { + n_prp++; + } + + return n_prp; +} + static int nvme_cmd_qpair_fill_dptr(struct nvme_cmd_qpair *qpair, struct nvme_request *request) { @@ -413,19 +607,15 @@ static int nvme_cmd_qpair_fill_dptr(struct nvme_cmd_qpair *qpair, return -EINVAL; } - n_prp = request->payload_size / qpair->ctrlr->page_size; - if ((request->payload_size % qpair->ctrlr->page_size) || - ((uintptr_t)request->payload & NVME_PBAO_MASK)) { - n_prp++; - } - + n_prp = compute_n_prp((uintptr_t)request->payload, + request->payload_size); if (n_prp <= 2) { request->cmd.dptr.prp1 = (uint64_t)sys_cpu_to_le64(request->payload); - if ((uintptr_t)request->payload & NVME_PBAO_MASK) { - request->cmd.dptr.prp2 = + if (n_prp == 2) { + request->cmd.dptr.prp2 = (uint64_t)sys_cpu_to_le64( NVME_PRP_NEXT_PAGE( - (uintptr_t)request->payload); + (uintptr_t)request->payload)); } else { request->cmd.dptr.prp2 = 0; } diff --git a/drivers/disk/nvme/nvme_cmd.h b/drivers/disk/nvme/nvme_cmd.h index 5dc17b8e8c4..24351570f10 100644 --- a/drivers/disk/nvme/nvme_cmd.h +++ b/drivers/disk/nvme/nvme_cmd.h @@ -197,7 +197,7 @@ enum nvme_path_related_status_code { NVME_SC_ASYMMETRIC_ACCESS_TRANSITION = 0x03, NVME_SC_CONTROLLER_PATHING_ERROR = 0x60, NVME_SC_HOST_PATHING_ERROR = 0x70, - NVME_SC_COMMAND_ABOTHED_BY_HOST = 0x71, + NVME_SC_COMMAND_ABORTED_BY_HOST = 0x71, }; /* admin opcodes */ @@ -306,16 +306,14 @@ enum nvme_feature { #define CACHE_LINE_SIZE CONFIG_DCACHE_LINE_SIZE #endif -/* Assuming page size it always 4Kib - * ToDo: define it accorditng to CONFIG_MMU_PAGE_SIZE - */ -#define NVME_PBAO_MASK 0xFFF +#define NVME_PBAO_MASK (CONFIG_MMU_PAGE_SIZE - 1) -#define NVME_PRP_NEXT_PAGE(_addr) ((_addr & (~NVME_PBAO_MASK)) + 0x1000) +#define NVME_PRP_NEXT_PAGE(_addr) \ + ((_addr & ~NVME_PBAO_MASK) + CONFIG_MMU_PAGE_SIZE) struct nvme_prp_list { uintptr_t prp[CONFIG_MMU_PAGE_SIZE / sizeof(uintptr_t)] - __aligned(0x1000); + __aligned(CONFIG_MMU_PAGE_SIZE); sys_dnode_t node; }; @@ -377,6 +375,12 @@ void nvme_cmd_init(void); void nvme_completion_poll_cb(void *arg, const struct nvme_completion *cpl); +#ifdef CONFIG_NVME_LOG_LEVEL_DBG +void nvme_completion_print(const struct nvme_completion *cpl); +#else +#define nvme_completion_print(...) +#endif /* CONFIG_NVME_LOG_LEVEL_DBG */ + void nvme_cmd_request_free(struct nvme_request *request); struct nvme_request *nvme_cmd_request_alloc(void); diff --git a/drivers/disk/nvme/nvme_controller.c b/drivers/disk/nvme/nvme_controller.c index c387da71d20..699df325add 100644 --- a/drivers/disk/nvme/nvme_controller.c +++ b/drivers/disk/nvme/nvme_controller.c @@ -183,6 +183,7 @@ static int nvme_controller_setup_io_queues(const struct device *dev) if (nvme_cpl_status_is_error(&status)) { LOG_ERR("Could not set IO num queues to %u", nvme_ctrlr->num_io_queues); + nvme_completion_print(&status.cpl); return -EIO; } @@ -225,6 +226,7 @@ static int nvme_controller_setup_io_queues(const struct device *dev) nvme_completion_poll(&status); if (nvme_cpl_status_is_error(&status)) { LOG_ERR("IO CQ creation failed"); + nvme_completion_print(&status.cpl); return -EIO; } @@ -240,6 +242,7 @@ static int nvme_controller_setup_io_queues(const struct device *dev) nvme_completion_poll(&status); if (nvme_cpl_status_is_error(&status)) { LOG_ERR("IO CQ creation failed"); + nvme_completion_print(&status.cpl); return -EIO; } } @@ -372,9 +375,9 @@ static int nvme_controller_identify(struct nvme_controller *nvme_ctrlr) nvme_ctrlr_cmd_identify_controller(nvme_ctrlr, nvme_completion_poll_cb, &status); nvme_completion_poll(&status); - if (nvme_cpl_status_is_error(&status)) { LOG_ERR("Could not identify the controller"); + nvme_completion_print(&status.cpl); return -EIO; } diff --git a/drivers/disk/nvme/nvme_disk.c b/drivers/disk/nvme/nvme_disk.c index ff22e3bad41..834a6e2e6c7 100644 --- a/drivers/disk/nvme/nvme_disk.c +++ b/drivers/disk/nvme/nvme_disk.c @@ -34,6 +34,11 @@ static int nvme_disk_read(struct disk_info *disk, uint32_t payload_size; int ret = 0; + if (!NVME_IS_BUFFER_DWORD_ALIGNED(data_buf)) { + LOG_WRN("Data buffer pointer needs to be 4-bytes aligned"); + return -EINVAL; + } + nvme_lock(disk->dev); payload_size = num_sector * nvme_namespace_get_sector_size(ns); @@ -57,6 +62,7 @@ static int nvme_disk_read(struct disk_info *disk, if (nvme_cpl_status_is_error(&status)) { LOG_WRN("Reading at sector %u (count %d) on disk %s failed", start_sector, num_sector, ns->name); + nvme_completion_print(&status.cpl); ret = -EIO; } out: @@ -77,6 +83,11 @@ static int nvme_disk_write(struct disk_info *disk, uint32_t payload_size; int ret = 0; + if (!NVME_IS_BUFFER_DWORD_ALIGNED(data_buf)) { + LOG_WRN("Data buffer pointer needs to be 4-bytes aligned"); + return -EINVAL; + } + nvme_lock(disk->dev); payload_size = num_sector * nvme_namespace_get_sector_size(ns); @@ -100,6 +111,7 @@ static int nvme_disk_write(struct disk_info *disk, if (nvme_cpl_status_is_error(&status)) { LOG_WRN("Writing at sector %u (count %d) on disk %s failed", start_sector, num_sector, ns->name); + nvme_completion_print(&status.cpl); ret = -EIO; } out: @@ -128,6 +140,7 @@ static int nvme_disk_flush(struct nvme_namespace *ns) nvme_completion_poll(&status); if (nvme_cpl_status_is_error(&status)) { LOG_ERR("Flushing disk %s failed", ns->name); + nvme_completion_print(&status.cpl); return -EIO; } diff --git a/drivers/disk/nvme/nvme_helpers.h b/drivers/disk/nvme/nvme_helpers.h index fb8165be519..325c6e9b842 100644 --- a/drivers/disk/nvme/nvme_helpers.h +++ b/drivers/disk/nvme/nvme_helpers.h @@ -514,4 +514,6 @@ enum shst_value { (mm_reg_t)b_a + nvme_mmio_offsetof(reg) + 4); \ } while (0) +#define NVME_IS_BUFFER_DWORD_ALIGNED(_buf_addr) (!((uintptr_t)_buf_addr & 0x3)) + #endif /* ZEPHYR_DRIVERS_DISK_NVME_NHME_HELPERS_H_ */ diff --git a/drivers/disk/ramdisk.c b/drivers/disk/ramdisk.c index 7c9c8789c85..1d1fcc46a0d 100644 --- a/drivers/disk/ramdisk.c +++ b/drivers/disk/ramdisk.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2016 Intel Corporation. - * Copyright (c) 2021, Nordic Semiconductor ASA + * Copyright (c) 2021,2023 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,15 +15,25 @@ LOG_MODULE_REGISTER(ramdisk, CONFIG_RAMDISK_LOG_LEVEL); -#define RAMDISK_SECTOR_SIZE 512 -#define RAMDISK_VOLUME_SIZE (CONFIG_DISK_RAM_VOLUME_SIZE * 1024) -#define RAMDISK_SECTOR_COUNT (RAMDISK_VOLUME_SIZE / RAMDISK_SECTOR_SIZE) +struct ram_disk_data { + struct disk_info info; + const size_t sector_size; + const size_t sector_count; + uint8_t *const buf; +}; -static uint8_t ramdisk_buf[RAMDISK_VOLUME_SIZE]; +struct ram_disk_config { + const size_t sector_size; + const size_t sector_count; + const size_t size; + uint8_t *const buf; +}; -static void *lba_to_address(uint32_t lba) +static void *lba_to_address(const struct device *dev, uint32_t lba) { - return &ramdisk_buf[lba * RAMDISK_SECTOR_SIZE]; + const struct ram_disk_config *config = dev->config; + + return &config->buf[lba * config->sector_size]; } static int disk_ram_access_status(struct disk_info *disk) @@ -39,15 +49,17 @@ static int disk_ram_access_init(struct disk_info *disk) static int disk_ram_access_read(struct disk_info *disk, uint8_t *buff, uint32_t sector, uint32_t count) { + const struct device *dev = disk->dev; + const struct ram_disk_config *config = dev->config; uint32_t last_sector = sector + count; - if (last_sector < sector || last_sector > RAMDISK_SECTOR_COUNT) { - LOG_ERR("Sector %" PRIu32 " is outside the range %u", - last_sector, RAMDISK_SECTOR_COUNT); + if (last_sector < sector || last_sector > config->sector_count) { + LOG_ERR("Sector %" PRIu32 " is outside the range %zu", + last_sector, config->sector_count); return -EIO; } - memcpy(buff, lba_to_address(sector), count * RAMDISK_SECTOR_SIZE); + memcpy(buff, lba_to_address(dev, sector), count * config->sector_size); return 0; } @@ -55,29 +67,33 @@ static int disk_ram_access_read(struct disk_info *disk, uint8_t *buff, static int disk_ram_access_write(struct disk_info *disk, const uint8_t *buff, uint32_t sector, uint32_t count) { + const struct device *dev = disk->dev; + const struct ram_disk_config *config = dev->config; uint32_t last_sector = sector + count; - if (last_sector < sector || last_sector > RAMDISK_SECTOR_COUNT) { - LOG_ERR("Sector %" PRIu32 " is outside the range %u", - last_sector, RAMDISK_SECTOR_COUNT); + if (last_sector < sector || last_sector > config->sector_count) { + LOG_ERR("Sector %" PRIu32 " is outside the range %zu", + last_sector, config->sector_count); return -EIO; } - memcpy(lba_to_address(sector), buff, count * RAMDISK_SECTOR_SIZE); + memcpy(lba_to_address(dev, sector), buff, count * config->sector_size); return 0; } static int disk_ram_access_ioctl(struct disk_info *disk, uint8_t cmd, void *buff) { + const struct ram_disk_config *config = disk->dev->config; + switch (cmd) { case DISK_IOCTL_CTRL_SYNC: break; case DISK_IOCTL_GET_SECTOR_COUNT: - *(uint32_t *)buff = RAMDISK_SECTOR_COUNT; + *(uint32_t *)buff = config->sector_count; break; case DISK_IOCTL_GET_SECTOR_SIZE: - *(uint32_t *)buff = RAMDISK_SECTOR_SIZE; + *(uint32_t *)buff = config->sector_size; break; case DISK_IOCTL_GET_ERASE_BLOCK_SZ: *(uint32_t *)buff = 1U; @@ -89,6 +105,15 @@ static int disk_ram_access_ioctl(struct disk_info *disk, uint8_t cmd, void *buff return 0; } +static int disk_ram_init(const struct device *dev) +{ + struct disk_info *info = dev->data; + + info->dev = dev; + + return disk_access_register(info); +} + static const struct disk_operations ram_disk_ops = { .init = disk_ram_access_init, .status = disk_ram_access_status, @@ -97,15 +122,51 @@ static const struct disk_operations ram_disk_ops = { .ioctl = disk_ram_access_ioctl, }; -static struct disk_info ram_disk = { - .name = CONFIG_DISK_RAM_VOLUME_NAME, - .ops = &ram_disk_ops, -}; - -static int disk_ram_init(void) -{ +#define DT_DRV_COMPAT zephyr_ram_disk + +#define RAMDISK_DEVICE_SIZE(n) \ + (DT_INST_PROP(n, sector_size) * DT_INST_PROP(n, sector_count)) + +#define RAMDISK_DEVICE_CONFIG_DEFINE_MEMREG(n) \ + BUILD_ASSERT(RAMDISK_DEVICE_SIZE(n) <= \ + DT_REG_SIZE(DT_INST_PHANDLE(n, ram_region)), \ + "Disk size is smaller than memory region"); \ + \ + static struct ram_disk_config disk_config_##n = { \ + .sector_size = DT_INST_PROP(n, sector_size), \ + .sector_count = DT_INST_PROP(n, sector_count), \ + .size = RAMDISK_DEVICE_SIZE(n), \ + .buf = UINT_TO_POINTER(DT_REG_ADDR(DT_INST_PHANDLE(n, ram_region))), \ + } - return disk_access_register(&ram_disk); -} +#define RAMDISK_DEVICE_CONFIG_DEFINE_LOCAL(n) \ + static uint8_t disk_buf_##n[DT_INST_PROP(n, sector_size) * \ + DT_INST_PROP(n, sector_count)]; \ + \ + static struct ram_disk_config disk_config_##n = { \ + .sector_size = DT_INST_PROP(n, sector_size), \ + .sector_count = DT_INST_PROP(n, sector_count), \ + .size = RAMDISK_DEVICE_SIZE(n), \ + .buf = disk_buf_##n, \ + } -SYS_INIT(disk_ram_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); +#define RAMDISK_DEVICE_CONFIG_DEFINE(n) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, ram_region), \ + (RAMDISK_DEVICE_CONFIG_DEFINE_MEMREG(n)), \ + (RAMDISK_DEVICE_CONFIG_DEFINE_LOCAL(n))) + +#define RAMDISK_DEVICE_DEFINE(n) \ + \ + static struct disk_info disk_info_##n = { \ + .name = DT_INST_PROP(n, disk_name), \ + .ops = &ram_disk_ops, \ + }; \ + \ + RAMDISK_DEVICE_CONFIG_DEFINE(n); \ + \ + DEVICE_DT_INST_DEFINE(n, disk_ram_init, NULL, \ + &disk_info_##n, &disk_config_##n, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ + &ram_disk_ops); + +DT_INST_FOREACH_STATUS_OKAY(RAMDISK_DEVICE_DEFINE) diff --git a/drivers/display/Kconfig.ssd1306 b/drivers/display/Kconfig.ssd1306 index 443e096ed84..32f8b0e1423 100644 --- a/drivers/display/Kconfig.ssd1306 +++ b/drivers/display/Kconfig.ssd1306 @@ -6,9 +6,11 @@ menuconfig SSD1306 bool "SSD1306 display driver" default y - depends on DT_HAS_SOLOMON_SSD1306FB_ENABLED + depends on DT_HAS_SOLOMON_SSD1306FB_ENABLED || DT_HAS_SINOWEALTH_SH1106_ENABLED select I2C if $(dt_compat_on_bus,$(DT_COMPAT_SOLOMON_SSD1306FB),i2c) select SPI if $(dt_compat_on_bus,$(DT_COMPAT_SOLOMON_SSD1306FB),spi) + select I2C if $(dt_compat_on_bus,$(DT_COMPAT_SINOWEALTH_SH1106),i2c) + select SPI if $(dt_compat_on_bus,$(DT_COMPAT_SINOWEALTH_SH1106),spi) help Enable driver for SSD1306 display driver. @@ -21,23 +23,4 @@ config SSD1306_DEFAULT_CONTRAST help SSD1306 default contrast. -choice SSD1306_CONTROLLER_TYPE - prompt "Display controller type" - default SSD1306_DEFAULT - help - Specify the type of the controller. - -config SSD1306_DEFAULT - bool "Default SSD1306 controller" - -config SSD1306_SH1106_COMPATIBLE - bool "SH1106 compatible mode" - -endchoice - -config SSD1306_REVERSE_MODE - bool "SSD1306 reverse mode" - help - SSD1306 reverse video mode. - endif # SSD1306 diff --git a/drivers/display/Kconfig.st7735r b/drivers/display/Kconfig.st7735r index 383df0aa0d8..94153eca585 100644 --- a/drivers/display/Kconfig.st7735r +++ b/drivers/display/Kconfig.st7735r @@ -4,9 +4,9 @@ # SPDX-License-Identifier: Apache-2.0 config ST7735R - bool "ST7735R display driver" + bool "ST7735R/ST7735S display driver" default y depends on DT_HAS_SITRONIX_ST7735R_ENABLED select SPI help - Enable driver for ST7735R display driver. + Enable driver for ST7735R/ST7735S display driver. diff --git a/drivers/display/display_dummy.c b/drivers/display/display_dummy.c index dd49573f790..630ed57a045 100644 --- a/drivers/display/display_dummy.c +++ b/drivers/display/display_dummy.c @@ -142,7 +142,7 @@ static const struct display_driver_api dummy_display_api = { DEVICE_DT_INST_DEFINE(n, &dummy_display_init, NULL, \ &dd_data_##n, \ &dd_config_##n, \ - APPLICATION, \ + POST_KERNEL, \ CONFIG_DISPLAY_INIT_PRIORITY, \ &dummy_display_api); \ diff --git a/drivers/display/display_hx8394.c b/drivers/display/display_hx8394.c index 9a71197b481..d5fecfb4fe1 100644 --- a/drivers/display/display_hx8394.c +++ b/drivers/display/display_hx8394.c @@ -31,7 +31,7 @@ struct hx8394_config { #define HX8394_MIPI_LP_CD_DIS BIT(5) #define HX8394_MIPI_TA_6TL 0x3 #define HX8394_MIPI_DPHYCMD_LPRX_8NS 0x40 -#define HX8394_MIPI_DPHYCMD_LPRX_66mV 0x10 +#define HX8394_MIPI_DPHYCMD_LPRX_66mV 0x20 #define HX8394_MIPI_DPHYCMD_LPTX_SRLIM 0x8 #define HX8394_MIPI_DPHYCMD_LDO_1_55V 0x60 #define HX8394_MIPI_DPHYCMD_HSRX_7X 0x8 @@ -404,7 +404,7 @@ const uint8_t hx8394_bank0[] = { const uint8_t hx8394_cmd3[] = {0xC6U, 0xEDU}; -const uint8_t tear_config[] = {HX8394_SET_TEAR, HX8394_TEAR_VBLANK | 0x3}; +const uint8_t tear_config[] = {HX8394_SET_TEAR, HX8394_TEAR_VBLANK}; static int hx8394_write(const struct device *dev, const uint16_t x, const uint16_t y, diff --git a/drivers/display/display_rm67162.c b/drivers/display/display_rm67162.c index c23abef6dc0..5516e57789d 100644 --- a/drivers/display/display_rm67162.c +++ b/drivers/display/display_rm67162.c @@ -8,10 +8,12 @@ #include #include +#include #include #include #include #include +#include #include LOG_MODULE_REGISTER(rm67162, CONFIG_DISPLAY_LOG_LEVEL); @@ -181,8 +183,6 @@ static const struct { {.cmd = 0x35, .param = 0x00}, }; -#define DSI_TX_MAX_PAYLOAD_BYTE (64U * 4U) - struct rm67162_config { const struct device *mipi_dsi; uint8_t channel; @@ -345,42 +345,38 @@ static int rm67162_init(const struct device *dev) MIPI_DCS_SET_DISPLAY_ON, NULL, 0); } -/* Helper to write data to rm67162 via MIPI interface. */ -static int rm67162_write_buf(const struct device *dev, bool first_write, +/* Helper to write framebuffer data to rm67162 via MIPI interface. */ +static int rm67162_write_fb(const struct device *dev, bool first_write, const uint8_t *src, uint32_t len) { const struct rm67162_config *config = dev->config; - struct rm67162_data *data = dev->data; - int ret = 0; - uint32_t max_write, wlen; - uint8_t cmd; + uint32_t wlen = 0; + struct mipi_dsi_msg msg = {0}; - /* - * Max write len: one byte is reserved for DSC command, and - * pixels should not be split across transfers + /* Note- we need to set custom flags on the DCS message, + * so we bypass the mipi_dsi_dcs_write API */ - max_write = ((DSI_TX_MAX_PAYLOAD_BYTE - 1) / data->bytes_per_pixel) * - data->bytes_per_pixel; if (first_write) { - cmd = MIPI_DCS_WRITE_MEMORY_START; + msg.cmd = MIPI_DCS_WRITE_MEMORY_START; } else { - cmd = MIPI_DCS_WRITE_MEMORY_CONTINUE; + msg.cmd = MIPI_DCS_WRITE_MEMORY_CONTINUE; } + msg.type = MIPI_DSI_DCS_LONG_WRITE; + msg.flags = MCUX_DSI_2L_FB_DATA; while (len > 0) { - /* Cap each tx to max DSI APB transfer size */ - wlen = MIN(max_write, len); - ret = mipi_dsi_dcs_write(config->mipi_dsi, config->channel, - cmd, src, wlen); - if (ret < 0) { - return ret; + msg.tx_len = len; + msg.tx_buf = src; + wlen = mipi_dsi_transfer(config->mipi_dsi, config->channel, &msg); + if (wlen < 0) { + return wlen; } /* Advance source pointer and decrement remaining */ src += wlen; len -= wlen; /* All future commands should use WRITE_MEMORY_CONTINUE */ - cmd = MIPI_DCS_WRITE_MEMORY_CONTINUE; + msg.cmd = MIPI_DCS_WRITE_MEMORY_CONTINUE; } - return ret; + return wlen; } static int rm67162_write(const struct device *dev, const uint16_t x, @@ -456,12 +452,12 @@ static int rm67162_write(const struct device *dev, const uint16_t x, if (desc->pitch == desc->width) { /* Buffer is contiguous, we can perform entire transfer */ - rm67162_write_buf(dev, first_cmd, src, + rm67162_write_fb(dev, first_cmd, src, desc->height * desc->width * data->bytes_per_pixel); } else { /* Buffer is not contiguous, we must write each line separately */ for (h_idx = 0; h_idx < desc->height; h_idx++) { - rm67162_write_buf(dev, first_cmd, src, + rm67162_write_fb(dev, first_cmd, src, desc->width * data->bytes_per_pixel); first_cmd = false; /* The pitch is not equal to width, account for it here */ @@ -573,6 +569,31 @@ static int rm67162_set_orientation(const struct device *dev, return -ENOTSUP; } +#ifdef CONFIG_PM_DEVICE + +static int rm67162_pm_action(const struct device *dev, + enum pm_device_action action) +{ + const struct rm67162_config *config = dev->config; + struct rm67162_data *data = dev->data; + struct mipi_dsi_device mdev = {0}; + + mdev.data_lanes = config->num_of_lanes; + mdev.pixfmt = data->pixel_format; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + /* Detach from the MIPI DSI controller */ + return mipi_dsi_detach(config->mipi_dsi, config->channel, &mdev); + case PM_DEVICE_ACTION_RESUME: + return mipi_dsi_attach(config->mipi_dsi, config->channel, &mdev); + default: + return -ENOTSUP; + } +} + +#endif /* CONFIG_PM_DEVICE */ + static const struct display_driver_api rm67162_api = { .blanking_on = rm67162_blanking_on, .blanking_off = rm67162_blanking_off, @@ -598,9 +619,10 @@ static const struct display_driver_api rm67162_api = { static struct rm67162_data rm67162_data_##id = { \ .pixel_format = DT_INST_PROP(id, pixel_format), \ }; \ + PM_DEVICE_DT_INST_DEFINE(id, rm67162_pm_action); \ DEVICE_DT_INST_DEFINE(id, \ &rm67162_init, \ - NULL, \ + PM_DEVICE_DT_INST_GET(id), \ &rm67162_data_##id, \ &rm67162_config_##id, \ POST_KERNEL, \ diff --git a/drivers/display/display_sdl.c b/drivers/display/display_sdl.c index f7ada84fbea..2a457249ede 100644 --- a/drivers/display/display_sdl.c +++ b/drivers/display/display_sdl.c @@ -374,7 +374,7 @@ static const struct display_driver_api sdl_display_api = { DEVICE_DT_INST_DEFINE(n, &sdl_display_init, NULL, \ &sdl_data_##n, \ &sdl_config_##n, \ - APPLICATION, \ + POST_KERNEL, \ CONFIG_DISPLAY_INIT_PRIORITY, \ &sdl_display_api); \ \ diff --git a/drivers/display/display_st7735r.c b/drivers/display/display_st7735r.c index 7d0f4aa6ac9..a20242d9703 100644 --- a/drivers/display/display_st7735r.c +++ b/drivers/display/display_st7735r.c @@ -75,8 +75,8 @@ static void st7735r_set_cmd(const struct device *dev, int is_cmd) gpio_pin_set_dt(&config->cmd_data, is_cmd); } -static int st7735r_transmit(const struct device *dev, uint8_t cmd, - const uint8_t *tx_data, size_t tx_count) +static int st7735r_transmit_hold(const struct device *dev, uint8_t cmd, + const uint8_t *tx_data, size_t tx_count) { const struct st7735r_config *config = dev->config; struct spi_buf tx_buf = { .buf = &cmd, .len = 1 }; @@ -102,6 +102,17 @@ static int st7735r_transmit(const struct device *dev, uint8_t cmd, return 0; } +static int st7735r_transmit(const struct device *dev, uint8_t cmd, + const uint8_t *tx_data, size_t tx_count) +{ + const struct st7735r_config *config = dev->config; + int ret; + + ret = st7735r_transmit_hold(dev, cmd, tx_data, tx_count); + spi_release_dt(&config->bus); + return ret; +} + static int st7735r_exit_sleep(const struct device *dev) { int ret; @@ -161,28 +172,36 @@ static int st7735r_set_mem_area(const struct device *dev, const uint16_t x, const uint16_t y, const uint16_t w, const uint16_t h) { + const struct st7735r_config *config = dev->config; struct st7735r_data *data = dev->data; uint16_t spi_data[2]; int ret; + /* ST7735S requires repeating COLMOD for each transfer */ + ret = st7735r_transmit_hold(dev, ST7735R_CMD_COLMOD, &config->colmod, 1); + if (ret < 0) { + return ret; + } + uint16_t ram_x = x + data->x_offset; uint16_t ram_y = y + data->y_offset; spi_data[0] = sys_cpu_to_be16(ram_x); spi_data[1] = sys_cpu_to_be16(ram_x + w - 1); - ret = st7735r_transmit(dev, ST7735R_CMD_CASET, (uint8_t *)&spi_data[0], 4); + ret = st7735r_transmit_hold(dev, ST7735R_CMD_CASET, (uint8_t *)&spi_data[0], 4); if (ret < 0) { return ret; } spi_data[0] = sys_cpu_to_be16(ram_y); spi_data[1] = sys_cpu_to_be16(ram_y + h - 1); - ret = st7735r_transmit(dev, ST7735R_CMD_RASET, (uint8_t *)&spi_data[0], 4); + ret = st7735r_transmit_hold(dev, ST7735R_CMD_RASET, (uint8_t *)&spi_data[0], 4); if (ret < 0) { return ret; } + /* NB: CS still held - data transfer coming next */ return 0; } @@ -209,7 +228,7 @@ static int st7735r_write(const struct device *dev, desc->width, desc->height, x, y); ret = st7735r_set_mem_area(dev, x, y, desc->width, desc->height); if (ret < 0) { - return ret; + goto out; } if (desc->pitch > desc->width) { @@ -220,11 +239,11 @@ static int st7735r_write(const struct device *dev, nbr_of_writes = 1U; } - ret = st7735r_transmit(dev, ST7735R_CMD_RAMWR, - (void *) write_data_start, - desc->width * ST7735R_PIXEL_SIZE * write_h); + ret = st7735r_transmit_hold(dev, ST7735R_CMD_RAMWR, + (void *) write_data_start, + desc->width * ST7735R_PIXEL_SIZE * write_h); if (ret < 0) { - return ret; + goto out; } tx_bufs.buffers = &tx_buf; @@ -236,13 +255,16 @@ static int st7735r_write(const struct device *dev, tx_buf.len = desc->width * ST7735R_PIXEL_SIZE * write_h; ret = spi_write_dt(&config->bus, &tx_bufs); if (ret < 0) { - return ret; + goto out; } write_data_start += (desc->pitch * ST7735R_PIXEL_SIZE); } - return 0; + ret = 0; +out: + spi_release_dt(&config->bus); + return ret; } static void *st7735r_get_framebuffer(const struct device *dev) @@ -539,7 +561,8 @@ static const struct display_driver_api st7735r_api = { #define ST7735R_INIT(inst) \ const static struct st7735r_config st7735r_config_ ## inst = { \ .bus = SPI_DT_SPEC_INST_GET( \ - inst, SPI_OP_MODE_MASTER | SPI_WORD_SET(8), 0), \ + inst, SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | \ + SPI_HOLD_ON_CS | SPI_LOCK_ON, 0), \ .cmd_data = GPIO_DT_SPEC_INST_GET(inst, cmd_data_gpios), \ .reset = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, {}), \ .width = DT_INST_PROP(inst, width), \ diff --git a/drivers/display/display_stm32_ltdc.c b/drivers/display/display_stm32_ltdc.c index 81ca122ed22..99001c3b37b 100644 --- a/drivers/display/display_stm32_ltdc.c +++ b/drivers/display/display_stm32_ltdc.c @@ -336,7 +336,7 @@ static int stm32_ltdc_suspend(const struct device *dev) } /* Turn off backlight (if its GPIO is defined in device tree) */ - if (config->disp_on_gpio.port) { + if (config->bl_ctrl_gpio.port) { err = gpio_pin_set_dt(&config->bl_ctrl_gpio, 0); if (err < 0) { return err; diff --git a/drivers/display/ssd1306.c b/drivers/display/ssd1306.c index 34166a2be9a..0f17293a70f 100644 --- a/drivers/display/ssd1306.c +++ b/drivers/display/ssd1306.c @@ -4,8 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define DT_DRV_COMPAT solomon_ssd1306fb - #include LOG_MODULE_REGISTER(ssd1306, CONFIG_DISPLAY_LOG_LEVEL); @@ -20,25 +18,6 @@ LOG_MODULE_REGISTER(ssd1306, CONFIG_DISPLAY_LOG_LEVEL); #include "ssd1306_regs.h" -#if DT_INST_PROP(0, segment_remap) == 1 -#define SSD1306_PANEL_SEGMENT_REMAP true -#else -#define SSD1306_PANEL_SEGMENT_REMAP false -#endif - -#if DT_INST_PROP(0, com_invdir) == 1 -#define SSD1306_PANEL_COM_INVDIR true -#else -#define SSD1306_PANEL_COM_INVDIR false -#endif - -#if DT_INST_PROP(0, com_sequential) == 1 -#define SSD1306_COM_PINS_HW_CONFIG SSD1306_SET_PADS_HW_SEQUENTIAL -#else -#define SSD1306_COM_PINS_HW_CONFIG SSD1306_SET_PADS_HW_ALTERNATIVE -#endif - -#define SSD1306_PANEL_NUMOF_PAGES (DT_INST_PROP(0, height) / 8) #define SSD1306_CLOCK_DIV_RATIO 0x0 #define SSD1306_CLOCK_FREQUENCY 0x8 #define SSD1306_PANEL_VCOM_DESEL_LEVEL 0x20 @@ -48,14 +27,36 @@ LOG_MODULE_REGISTER(ssd1306, CONFIG_DISPLAY_LOG_LEVEL); #define SSD1306_ADDRESSING_MODE (SSD1306_SET_MEM_ADDRESSING_HORIZONTAL) #endif +union ssd1306_bus { + struct i2c_dt_spec i2c; + struct spi_dt_spec spi; +}; + +typedef bool (*ssd1306_bus_ready_fn)(const struct device *dev); +typedef int (*ssd1306_write_bus_fn)(const struct device *dev, uint8_t *buf, size_t len, + bool command); +typedef const char *(*ssd1306_bus_name_fn)(const struct device *dev); + struct ssd1306_config { -#if DT_INST_ON_BUS(0, i2c) - struct i2c_dt_spec bus; -#elif DT_INST_ON_BUS(0, spi) - struct spi_dt_spec bus; + union ssd1306_bus bus; struct gpio_dt_spec data_cmd; -#endif struct gpio_dt_spec reset; + ssd1306_bus_ready_fn bus_ready; + ssd1306_write_bus_fn write_bus; + ssd1306_bus_name_fn bus_name; + uint16_t height; + uint16_t width; + uint8_t segment_offset; + uint8_t page_offset; + uint8_t display_offset; + uint8_t multiplex_ratio; + uint8_t prechargep; + bool segment_remap; + bool com_invdir; + bool com_sequential; + bool color_inversion; + bool sh1106_compatible; + int ready_time_ms; }; struct ssd1306_data { @@ -63,29 +64,36 @@ struct ssd1306_data { uint8_t scan_mode; }; -#if DT_INST_ON_BUS(0, i2c) - -static inline bool ssd1306_bus_ready(const struct device *dev) +#if (DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(solomon_ssd1306fb, i2c) || \ + DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(sinowealth_sh1106, i2c)) +static bool ssd1306_bus_ready_i2c(const struct device *dev) { const struct ssd1306_config *config = dev->config; - return device_is_ready(config->bus.bus); + return i2c_is_ready_dt(&config->bus.i2c); } -static inline int ssd1306_write_bus(const struct device *dev, - uint8_t *buf, size_t len, bool command) +static int ssd1306_write_bus_i2c(const struct device *dev, uint8_t *buf, size_t len, bool command) { const struct ssd1306_config *config = dev->config; - return i2c_burst_write_dt(&config->bus, + return i2c_burst_write_dt(&config->bus.i2c, command ? SSD1306_CONTROL_ALL_BYTES_CMD : SSD1306_CONTROL_ALL_BYTES_DATA, buf, len); } -#elif DT_INST_ON_BUS(0, spi) +static const char *ssd1306_bus_name_i2c(const struct device *dev) +{ + const struct ssd1306_config *config = dev->config; + + return config->bus.i2c.bus->name; +} +#endif -static inline bool ssd1306_bus_ready(const struct device *dev) +#if (DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(solomon_ssd1306fb, spi) || \ + DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(sinowealth_sh1106, spi)) +static bool ssd1306_bus_ready_spi(const struct device *dev) { const struct ssd1306_config *config = dev->config; @@ -93,11 +101,10 @@ static inline bool ssd1306_bus_ready(const struct device *dev) return false; } - return spi_is_ready_dt(&config->bus); + return spi_is_ready_dt(&config->bus.spi); } -static inline int ssd1306_write_bus(const struct device *dev, - uint8_t *buf, size_t len, bool command) +static int ssd1306_write_bus_spi(const struct device *dev, uint8_t *buf, size_t len, bool command) { const struct ssd1306_config *config = dev->config; int errno; @@ -113,50 +120,70 @@ static inline int ssd1306_write_bus(const struct device *dev, .count = 1 }; - errno = spi_write_dt(&config->bus, &tx_bufs); + errno = spi_write_dt(&config->bus.spi, &tx_bufs); return errno; } + +static const char *ssd1306_bus_name_spi(const struct device *dev) +{ + const struct ssd1306_config *config = dev->config; + + return config->bus.spi.bus->name; +} #endif +static inline bool ssd1306_bus_ready(const struct device *dev) +{ + const struct ssd1306_config *config = dev->config; + + return config->bus_ready(dev); +} + +static inline int ssd1306_write_bus(const struct device *dev, uint8_t *buf, size_t len, + bool command) +{ + const struct ssd1306_config *config = dev->config; + + return config->write_bus(dev, buf, len, command); +} + static inline int ssd1306_set_panel_orientation(const struct device *dev) { - uint8_t cmd_buf[] = { - (SSD1306_PANEL_SEGMENT_REMAP ? - SSD1306_SET_SEGMENT_MAP_REMAPED : - SSD1306_SET_SEGMENT_MAP_NORMAL), - (SSD1306_PANEL_COM_INVDIR ? - SSD1306_SET_COM_OUTPUT_SCAN_FLIPPED : - SSD1306_SET_COM_OUTPUT_SCAN_NORMAL) - }; + const struct ssd1306_config *config = dev->config; + uint8_t cmd_buf[] = {(config->segment_remap ? SSD1306_SET_SEGMENT_MAP_REMAPED + : SSD1306_SET_SEGMENT_MAP_NORMAL), + (config->com_invdir ? SSD1306_SET_COM_OUTPUT_SCAN_FLIPPED + : SSD1306_SET_COM_OUTPUT_SCAN_NORMAL)}; return ssd1306_write_bus(dev, cmd_buf, sizeof(cmd_buf), true); } static inline int ssd1306_set_timing_setting(const struct device *dev) { - uint8_t cmd_buf[] = { - SSD1306_SET_CLOCK_DIV_RATIO, - (SSD1306_CLOCK_FREQUENCY << 4) | SSD1306_CLOCK_DIV_RATIO, - SSD1306_SET_CHARGE_PERIOD, - DT_INST_PROP(0, prechargep), - SSD1306_SET_VCOM_DESELECT_LEVEL, - SSD1306_PANEL_VCOM_DESEL_LEVEL - }; + const struct ssd1306_config *config = dev->config; + uint8_t cmd_buf[] = {SSD1306_SET_CLOCK_DIV_RATIO, + (SSD1306_CLOCK_FREQUENCY << 4) | SSD1306_CLOCK_DIV_RATIO, + SSD1306_SET_CHARGE_PERIOD, + config->prechargep, + SSD1306_SET_VCOM_DESELECT_LEVEL, + SSD1306_PANEL_VCOM_DESEL_LEVEL}; return ssd1306_write_bus(dev, cmd_buf, sizeof(cmd_buf), true); } static inline int ssd1306_set_hardware_config(const struct device *dev) { + const struct ssd1306_config *config = dev->config; uint8_t cmd_buf[] = { SSD1306_SET_START_LINE, SSD1306_SET_DISPLAY_OFFSET, - DT_INST_PROP(0, display_offset), + config->display_offset, SSD1306_SET_PADS_HW_CONFIG, - SSD1306_COM_PINS_HW_CONFIG, + (config->com_sequential ? SSD1306_SET_PADS_HW_SEQUENTIAL + : SSD1306_SET_PADS_HW_ALTERNATIVE), SSD1306_SET_MULTIPLEX_RATIO, - DT_INST_PROP(0, multiplex_ratio) + config->multiplex_ratio, }; return ssd1306_write_bus(dev, cmd_buf, sizeof(cmd_buf), true); @@ -164,15 +191,11 @@ static inline int ssd1306_set_hardware_config(const struct device *dev) static inline int ssd1306_set_charge_pump(const struct device *dev) { + const struct ssd1306_config *config = dev->config; uint8_t cmd_buf[] = { -#if defined(CONFIG_SSD1306_DEFAULT) - SSD1306_SET_CHARGE_PUMP_ON, - SSD1306_SET_CHARGE_PUMP_ON_ENABLED, -#endif -#if defined(CONFIG_SSD1306_SH1106_COMPATIBLE) - SH1106_SET_DCDC_MODE, - SH1106_SET_DCDC_ENABLED, -#endif + (config->sh1106_compatible ? SH1106_SET_DCDC_MODE : SSD1306_SET_CHARGE_PUMP_ON), + (config->sh1106_compatible ? SH1106_SET_DCDC_ENABLED + : SSD1306_SET_CHARGE_PUMP_ON_ENABLED), SSD1306_PANEL_PUMP_VOLTAGE, }; @@ -197,37 +220,10 @@ static int ssd1306_suspend(const struct device *dev) return ssd1306_write_bus(dev, cmd_buf, sizeof(cmd_buf), true); } -static int ssd1306_write(const struct device *dev, const uint16_t x, const uint16_t y, - const struct display_buffer_descriptor *desc, - const void *buf) +static int ssd1306_write_default(const struct device *dev, const uint16_t x, const uint16_t y, + const struct display_buffer_descriptor *desc, const void *buf, + const size_t buf_len) { - size_t buf_len; - - if (desc->pitch < desc->width) { - LOG_ERR("Pitch is smaller then width"); - return -1; - } - - buf_len = MIN(desc->buf_size, desc->height * desc->width / 8); - if (buf == NULL || buf_len == 0U) { - LOG_ERR("Display buffer is not available"); - return -1; - } - - if (desc->pitch > desc->width) { - LOG_ERR("Unsupported mode"); - return -1; - } - - if ((y & 0x7) != 0U) { - LOG_ERR("Unsupported origin"); - return -1; - } - - LOG_DBG("x %u, y %u, pitch %u, width %u, height %u, buf_len %u", - x, y, desc->pitch, desc->width, desc->height, buf_len); - -#if defined(CONFIG_SSD1306_DEFAULT) uint8_t cmd_buf[] = { SSD1306_SET_MEM_ADDRESSING_MODE, SSD1306_ADDRESSING_MODE, @@ -245,9 +241,14 @@ static int ssd1306_write(const struct device *dev, const uint16_t x, const uint1 } return ssd1306_write_bus(dev, (uint8_t *)buf, buf_len, false); +} -#elif defined(CONFIG_SSD1306_SH1106_COMPATIBLE) - uint8_t x_offset = x + DT_INST_PROP(0, segment_offset); +static int ssd1306_write_sh1106(const struct device *dev, const uint16_t x, const uint16_t y, + const struct display_buffer_descriptor *desc, const void *buf, + const size_t buf_len) +{ + const struct ssd1306_config *config = dev->config; + uint8_t x_offset = x + config->segment_offset; uint8_t cmd_buf[] = { SSD1306_SET_LOWER_COL_ADDRESS | (x_offset & SSD1306_SET_LOWER_COL_ADDRESS_MASK), @@ -276,11 +277,47 @@ static int ssd1306_write(const struct device *dev, const uint16_t x, const uint1 return -1; } } -#endif return 0; } +static int ssd1306_write(const struct device *dev, const uint16_t x, const uint16_t y, + const struct display_buffer_descriptor *desc, const void *buf) +{ + const struct ssd1306_config *config = dev->config; + size_t buf_len; + + if (desc->pitch < desc->width) { + LOG_ERR("Pitch is smaller then width"); + return -1; + } + + buf_len = MIN(desc->buf_size, desc->height * desc->width / 8); + if (buf == NULL || buf_len == 0U) { + LOG_ERR("Display buffer is not available"); + return -1; + } + + if (desc->pitch > desc->width) { + LOG_ERR("Unsupported mode"); + return -1; + } + + if ((y & 0x7) != 0U) { + LOG_ERR("Unsupported origin"); + return -1; + } + + LOG_DBG("x %u, y %u, pitch %u, width %u, height %u, buf_len %u", x, y, desc->pitch, + desc->width, desc->height, buf_len); + + if (config->sh1106_compatible) { + return ssd1306_write_sh1106(dev, x, y, desc, buf, buf_len); + } + + return ssd1306_write_default(dev, x, y, desc, buf, buf_len); +} + static int ssd1306_read(const struct device *dev, const uint16_t x, const uint16_t y, const struct display_buffer_descriptor *desc, @@ -316,9 +353,10 @@ static int ssd1306_set_contrast(const struct device *dev, const uint8_t contrast static void ssd1306_get_capabilities(const struct device *dev, struct display_capabilities *caps) { + const struct ssd1306_config *config = dev->config; memset(caps, 0, sizeof(struct display_capabilities)); - caps->x_resolution = DT_INST_PROP(0, width); - caps->y_resolution = DT_INST_PROP(0, height); + caps->x_resolution = config->width; + caps->y_resolution = config->height; caps->supported_pixel_formats = PIXEL_FORMAT_MONO10; caps->current_pixel_format = PIXEL_FORMAT_MONO10; caps->screen_info = SCREEN_INFO_MONO_VTILED; @@ -348,11 +386,8 @@ static int ssd1306_init_device(const struct device *dev) uint8_t cmd_buf[] = { SSD1306_SET_ENTIRE_DISPLAY_OFF, -#ifdef CONFIG_SSD1306_REVERSE_MODE - SSD1306_SET_REVERSE_DISPLAY, -#else - SSD1306_SET_NORMAL_DISPLAY, -#endif + (config->color_inversion ? SSD1306_SET_REVERSE_DISPLAY + : SSD1306_SET_NORMAL_DISPLAY), }; /* Reset if pin connected */ @@ -403,8 +438,10 @@ static int ssd1306_init(const struct device *dev) LOG_DBG(""); + k_sleep(K_TIMEOUT_ABS_MS(config->ready_time_ms)); + if (!ssd1306_bus_ready(dev)) { - LOG_ERR("Bus device %s not ready!", config->bus.bus->name); + LOG_ERR("Bus device %s not ready!", config->bus_name(dev)); return -EINVAL; } @@ -426,19 +463,6 @@ static int ssd1306_init(const struct device *dev) return 0; } -static const struct ssd1306_config ssd1306_config = { -#if DT_INST_ON_BUS(0, i2c) - .bus = I2C_DT_SPEC_INST_GET(0), -#elif DT_INST_ON_BUS(0, spi) - .bus = SPI_DT_SPEC_INST_GET( - 0, SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8), 0), - .data_cmd = GPIO_DT_SPEC_INST_GET(0, data_cmd_gpios), -#endif - .reset = GPIO_DT_SPEC_INST_GET_OR(0, reset_gpios, { 0 }) -}; - -static struct ssd1306_data ssd1306_driver; - static struct display_driver_api ssd1306_driver_api = { .blanking_on = ssd1306_suspend, .blanking_off = ssd1306_resume, @@ -452,7 +476,44 @@ static struct display_driver_api ssd1306_driver_api = { .set_orientation = ssd1306_set_orientation, }; -DEVICE_DT_INST_DEFINE(0, ssd1306_init, NULL, - &ssd1306_driver, &ssd1306_config, - POST_KERNEL, CONFIG_DISPLAY_INIT_PRIORITY, - &ssd1306_driver_api); +#define SSD1306_CONFIG_SPI(node_id) \ + .bus = {.spi = SPI_DT_SPEC_GET( \ + node_id, SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8), 0)}, \ + .bus_ready = ssd1306_bus_ready_spi, \ + .write_bus = ssd1306_write_bus_spi, \ + .bus_name = ssd1306_bus_name_spi, \ + .data_cmd = GPIO_DT_SPEC_GET(node_id, data_cmd_gpios), + +#define SSD1306_CONFIG_I2C(node_id) \ + .bus = {.i2c = I2C_DT_SPEC_GET(node_id)}, \ + .bus_ready = ssd1306_bus_ready_i2c, \ + .write_bus = ssd1306_write_bus_i2c, \ + .bus_name = ssd1306_bus_name_i2c, \ + .data_cmd = {0}, + +#define SSD1306_DEFINE(node_id) \ + static struct ssd1306_data data##node_id; \ + static const struct ssd1306_config config##node_id = { \ + .reset = GPIO_DT_SPEC_GET_OR(node_id, reset_gpios, {0}), \ + .height = DT_PROP(node_id, height), \ + .width = DT_PROP(node_id, width), \ + .segment_offset = DT_PROP(node_id, segment_offset), \ + .page_offset = DT_PROP(node_id, page_offset), \ + .display_offset = DT_PROP(node_id, display_offset), \ + .multiplex_ratio = DT_PROP(node_id, multiplex_ratio), \ + .segment_remap = DT_PROP(node_id, segment_remap), \ + .com_invdir = DT_PROP(node_id, com_invdir), \ + .com_sequential = DT_PROP(node_id, com_sequential), \ + .prechargep = DT_PROP(node_id, prechargep), \ + .color_inversion = DT_PROP(node_id, inversion_on), \ + .sh1106_compatible = DT_NODE_HAS_COMPAT(node_id, sinowealth_sh1106), \ + .ready_time_ms = DT_PROP(node_id, ready_time_ms), \ + COND_CODE_1(DT_ON_BUS(node_id, spi), (SSD1306_CONFIG_SPI(node_id)), \ + (SSD1306_CONFIG_I2C(node_id))) \ + }; \ + \ + DEVICE_DT_DEFINE(node_id, ssd1306_init, NULL, &data##node_id, &config##node_id, \ + POST_KERNEL, CONFIG_DISPLAY_INIT_PRIORITY, &ssd1306_driver_api); + +DT_FOREACH_STATUS_OKAY(solomon_ssd1306fb, SSD1306_DEFINE) +DT_FOREACH_STATUS_OKAY(sinowealth_sh1106, SSD1306_DEFINE) diff --git a/drivers/dma/CMakeLists.txt b/drivers/dma/CMakeLists.txt index 3cb622ae9e8..e65c3726622 100644 --- a/drivers/dma/CMakeLists.txt +++ b/drivers/dma/CMakeLists.txt @@ -15,6 +15,7 @@ zephyr_library_sources_ifdef(CONFIG_DMA_NIOS2_MSGDMA dma_nios2_msgdma.c) zephyr_library_sources_ifdef(CONFIG_DMA_SAM0 dma_sam0.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE dma_handlers.c) zephyr_library_sources_ifdef(CONFIG_DMA_MCUX_EDMA dma_mcux_edma.c) +zephyr_library_sources_ifdef(CONFIG_DMA_MCUX_EDMA_V3 dma_mcux_edma.c) zephyr_library_sources_ifdef(CONFIG_DMA_MCUX_LPC dma_mcux_lpc.c) zephyr_library_sources_ifdef(CONFIG_DMA_PL330 dma_pl330.c) zephyr_library_sources_ifdef(CONFIG_DMA_IPROC_PAX dma_iproc_pax_v1.c) @@ -32,3 +33,8 @@ zephyr_library_sources_ifdef(CONFIG_DMA_MCHP_XEC dma_mchp_xec.c) zephyr_library_sources_ifdef(CONFIG_DMA_XMC4XXX dma_xmc4xxx.c) zephyr_library_sources_ifdef(CONFIG_DMA_RPI_PICO dma_rpi_pico.c) zephyr_library_sources_ifdef(CONFIG_MCUX_PXP dma_mcux_pxp.c) +zephyr_library_sources_ifdef(CONFIG_DMA_MCUX_SMARTDMA dma_mcux_smartdma.c) +zephyr_library_sources_ifdef(CONFIG_DMA_ANDES_ATCDMAC300 dma_andes_atcdmac300.c) +zephyr_library_sources_ifdef(CONFIG_DMA_SEDI dma_sedi.c) +zephyr_library_sources_ifdef(CONFIG_DMA_SMARTBOND dma_smartbond.c) +zephyr_library_sources_ifdef(CONFIG_DMA_NXP_SOF_HOST_DMA dma_nxp_sof_host_dma.c) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 5023d9af9dd..e24386558cd 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -61,4 +61,15 @@ source "drivers/dma/Kconfig.rpi_pico" source "drivers/dma/Kconfig.intel_lpss" source "drivers/dma/Kconfig.mcux_pxp" + +source "drivers/dma/Kconfig.mcux_smartdma" + +source "drivers/dma/Kconfig.andes_atcdmac300" + +source "drivers/dma/Kconfig.sedi" + +source "drivers/dma/Kconfig.smartbond" + +source "drivers/dma/Kconfig.nxp_sof_host_dma" + endif # DMA diff --git a/drivers/dma/Kconfig.andes_atcdmac300 b/drivers/dma/Kconfig.andes_atcdmac300 new file mode 100644 index 00000000000..cb1133cdeb5 --- /dev/null +++ b/drivers/dma/Kconfig.andes_atcdmac300 @@ -0,0 +1,12 @@ +# Andestech ATCDMAC300 configuration options +# Copyright (c) 2023 Andes Technology Corporation. + +# SPDX-License-Identifier: Apache-2.0 + + +config DMA_ANDES_ATCDMAC300 + bool "Using Andes ATCDMAC300 DMA driver" + default y + depends on DT_HAS_ANDESTECH_ATCDMAC300_ENABLED + help + Andes ATCDMAC300 DMA driver. diff --git a/drivers/dma/Kconfig.intel_lpss b/drivers/dma/Kconfig.intel_lpss index d475c742784..3f58618d869 100644 --- a/drivers/dma/Kconfig.intel_lpss +++ b/drivers/dma/Kconfig.intel_lpss @@ -5,8 +5,9 @@ config DMA_INTEL_LPSS bool "INTEL LPSS DMA driver" - default n + default y depends on DT_HAS_INTEL_LPSS_ENABLED + select DEVICE_DEPS help INTEL LPSS DMA driver. diff --git a/drivers/dma/Kconfig.mcux_edma b/drivers/dma/Kconfig.mcux_edma index d4d44cb4cf7..d1e513e3c13 100644 --- a/drivers/dma/Kconfig.mcux_edma +++ b/drivers/dma/Kconfig.mcux_edma @@ -11,7 +11,14 @@ config DMA_MCUX_EDMA help DMA driver for MCUX series SoCs. -if DMA_MCUX_EDMA +config DMA_MCUX_EDMA_V3 + bool "MCUX DMA v3 driver" + default y + depends on DT_HAS_NXP_MCUX_EDMA_V3_ENABLED + help + DMA version 3 driver for MCUX series SoCs. + +if DMA_MCUX_EDMA || DMA_MCUX_EDMA_V3 config DMA_TCD_QUEUE_SIZE int "number of TCD in a queue for SG mode" @@ -21,9 +28,10 @@ config DMA_TCD_QUEUE_SIZE config DMA_MCUX_TEST_SLOT_START int "test slot start num" - depends on (SOC_SERIES_KINETIS_K6X || SOC_SERIES_KINETIS_KE1XF) + depends on (SOC_SERIES_KINETIS_K6X || SOC_SERIES_KINETIS_KE1XF || SOC_SERIES_S32K3XX) default 58 if SOC_SERIES_KINETIS_K6X default 60 if SOC_SERIES_KINETIS_KE1XF + default 62 if SOC_SERIES_S32K3XX help test slot start num @@ -33,4 +41,4 @@ config DMA_MCUX_USE_DTCM_FOR_DMA_DESCRIPTORS When this option is activated, the descriptors for DMA transfer are located in the DTCM (Data Tightly Coupled Memory). -endif # DMA_MCUX_EDMA +endif # DMA_MCUX_EDMA || DMA_MCUX_EDMA_V3 diff --git a/drivers/dma/Kconfig.mcux_pxp b/drivers/dma/Kconfig.mcux_pxp index 054dde52451..b00148304cf 100644 --- a/drivers/dma/Kconfig.mcux_pxp +++ b/drivers/dma/Kconfig.mcux_pxp @@ -5,5 +5,6 @@ config MCUX_PXP bool "MCUX PXP DMA driver" default y depends on DT_HAS_NXP_PXP_ENABLED + depends on DISPLAY help PXP DMA driver for NXP SOCs diff --git a/drivers/dma/Kconfig.mcux_smartdma b/drivers/dma/Kconfig.mcux_smartdma new file mode 100644 index 00000000000..e4258038ee5 --- /dev/null +++ b/drivers/dma/Kconfig.mcux_smartdma @@ -0,0 +1,9 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +config DMA_MCUX_SMARTDMA + bool "MCUX SmartDMA Driver" + default y + depends on DT_HAS_NXP_SMARTDMA_ENABLED + help + MCUX SmartDMA driver. diff --git a/drivers/dma/Kconfig.nxp_sof_host_dma b/drivers/dma/Kconfig.nxp_sof_host_dma new file mode 100644 index 00000000000..f909612f3aa --- /dev/null +++ b/drivers/dma/Kconfig.nxp_sof_host_dma @@ -0,0 +1,34 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +config DMA_NXP_SOF_HOST_DMA + bool "NXP DMA driver used by SOF's host component" + default y + depends on DT_HAS_NXP_SOF_HOST_DMA_ENABLED + help + Enable NXP's DMA driver used by + SOF (Sound Open Firmware) host + component. Specifically, this driver + is used by the SOF host component to + perform transfers between the host + memory and firmware (local) memory, which + can be accessed without an actual + DMA engine. + +if DMA_NXP_SOF_HOST_DMA + +config DMA_NXP_SOF_HOST_DMA_ALIGN + int "Alignment (in bytes) required for memory regions passed to this driver" + default 8 + help + Use this to set the alignment (in bytes) + which shall be used by entities employing + this driver to adjust a memory region's size + and base address. Since this driver doesn't + actually have any hardware to back it up this + configuration doesn't make much sense as there's + no alignment restrictions imposed by memcpy. + Nevertheless, this is needed because this driver + needs to act as if it controls a DMA engine. + +endif # DMA_NXP_SOF_HOST_DMA diff --git a/drivers/dma/Kconfig.sedi b/drivers/dma/Kconfig.sedi new file mode 100644 index 00000000000..9f07bff903a --- /dev/null +++ b/drivers/dma/Kconfig.sedi @@ -0,0 +1,14 @@ +# Intel sedi DMA configuration options + +# Copyright (c) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +config DMA_SEDI + bool "SEDI DMA driver" + select DMA_64BIT + default y + depends on DT_HAS_INTEL_SEDI_DMA_ENABLED + help + This option enables the Intel SEDI DMA driver. + This driver is simply a shim driver built upon the SEDI + bare metal DMA driver in the hal-intel module diff --git a/drivers/dma/Kconfig.smartbond b/drivers/dma/Kconfig.smartbond new file mode 100644 index 00000000000..3234e13020f --- /dev/null +++ b/drivers/dma/Kconfig.smartbond @@ -0,0 +1,11 @@ +# Smartbond DMA Accelerator Configuration Options + +# Copyright (c) 2023 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +config DMA_SMARTBOND + bool "Smartbond DMA Accelerator Driver" + depends on DT_HAS_RENESAS_SMARTBOND_DMA_ENABLED + default y + help + Enable Smartbond DMA Accelerator Driver diff --git a/drivers/dma/dma_andes_atcdmac300.c b/drivers/dma/dma_andes_atcdmac300.c new file mode 100644 index 00000000000..ef90868f943 --- /dev/null +++ b/drivers/dma/dma_andes_atcdmac300.c @@ -0,0 +1,536 @@ +/* + * Copyright (c) 2023 Andes Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include +#include +#include +#include +#include +#include +#include + +#define DT_DRV_COMPAT andestech_atcdmac300 + +#define LOG_LEVEL CONFIG_DMA_LOG_LEVEL +#include +LOG_MODULE_REGISTER(dma_andes_atcdmac300); + +#define ATCDMAC100_MAX_CHAN 8 + +#define DMA_ABORT(dev) (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x24) +#define DMA_INT_STATUS(dev) \ + (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x30) + +#define DMA_CH_OFFSET(ch) (ch * 0x20) +#define DMA_CH_CTRL(dev, ch) \ + (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x40 + DMA_CH_OFFSET(ch)) +#define DMA_CH_TRANSIZE(dev, ch) \ + (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x44 + DMA_CH_OFFSET(ch)) +#define DMA_CH_SRC_ADDR_L(dev, ch) \ + (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x48 + DMA_CH_OFFSET(ch)) +#define DMA_CH_SRC_ADDR_H(dev, ch) \ + (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x4C + DMA_CH_OFFSET(ch)) +#define DMA_CH_DST_ADDR_L(dev, ch) \ + (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x50 + DMA_CH_OFFSET(ch)) +#define DMA_CH_DST_ADDR_H(dev, ch) \ + (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x54 + DMA_CH_OFFSET(ch)) +#define DMA_CH_LL_PTR_L(dev, ch) \ + (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x58 + DMA_CH_OFFSET(ch)) +#define DMA_CH_LL_PTR_H(dev, ch) \ + (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x5C + DMA_CH_OFFSET(ch)) + +/* Source burst size options */ +#define DMA_BSIZE_1 (0) +#define DMA_BSIZE_2 (1) +#define DMA_BSIZE_4 (2) +#define DMA_BSIZE_8 (3) +#define DMA_BSIZE_16 (4) +#define DMA_BSIZE_32 (5) +#define DMA_BSIZE_64 (6) +#define DMA_BSIZE_128 (7) +#define DMA_BSIZE_256 (8) +#define DMA_BSIZE_512 (9) +#define DMA_BSIZE_1024 (10) + +/* Source/Destination transfer width options */ +#define DMA_WIDTH_BYTE (0) +#define DMA_WIDTH_HALFWORD (1) +#define DMA_WIDTH_WORD (2) +#define DMA_WIDTH_DWORD (3) +#define DMA_WIDTH_QWORD (4) +#define DMA_WIDTH_EWORD (5) + +/* Bus interface index */ +#define DMA_INF_IDX0 (0) +#define DMA_INF_IDX1 (1) + +/* DMA Channel Control Register Definition */ +#define DMA_CH_CTRL_SBINF_MASK BIT(31) +#define DMA_CH_CTRL_DBINF_MASK BIT(30) +#define DMA_CH_CTRL_PRIORITY_HIGH BIT(29) +#define DMA_CH_CTRL_SBSIZE_MASK BIT(24) +#define DMA_CH_CTRL_SBSIZE(n) FIELD_PREP(DMA_CH_CTRL_SBSIZE_MASK, (n)) +#define DMA_CH_CTRL_SWIDTH_MASK GENMASK(23, 21) +#define DMA_CH_CTRL_SWIDTH(n) FIELD_PREP(DMA_CH_CTRL_SWIDTH_MASK, (n)) +#define DMA_CH_CTRL_DWIDTH_MASK GENMASK(20, 18) +#define DMA_CH_CTRL_DWIDTH(n) FIELD_PREP(DMA_CH_CTRL_DWIDTH_MASK, (n)) +#define DMA_CH_CTRL_SMODE_HANDSHAKE BIT(17) +#define DMA_CH_CTRL_DMODE_HANDSHAKE BIT(17) +#define DMA_CH_CTRL_SRCADDRCTRL_MASK GENMASK(15, 14) +#define DMA_CH_CTRL_SRCADDR_INC FIELD_PREP(DMA_CH_CTRL_DWIDTH_MASK, (0)) +#define DMA_CH_CTRL_SRCADDR_DEC FIELD_PREP(DMA_CH_CTRL_DWIDTH_MASK, (1)) +#define DMA_CH_CTRL_SRCADDR_FIX FIELD_PREP(DMA_CH_CTRL_DWIDTH_MASK, (2)) +#define DMA_CH_CTRL_DSTADDRCTRL_MASK GENMASK(13, 12) +#define DMA_CH_CTRL_DSTADDR_INC FIELD_PREP(DMA_CH_CTRL_DSTADDRCTRL_MASK, (0)) +#define DMA_CH_CTRL_DSTADDR_DEC FIELD_PREP(DMA_CH_CTRL_DSTADDRCTRL_MASK, (1)) +#define DMA_CH_CTRL_DSTADDR_FIX FIELD_PREP(DMA_CH_CTRL_DSTADDRCTRL_MASK, (2)) +#define DMA_CH_CTRL_SRCREQ_MASK GENMASK(11, 8) +#define DMA_CH_CTRL_SRCREQ(n) FIELD_PREP(DMA_CH_CTRL_SRCREQ_MASK, (n)) +#define DMA_CH_CTRL_DSTREQ_MASK GENMASK(7, 4) +#define DMA_CH_CTRL_DSTREQ(n) FIELD_PREP(DMA_CH_CTRL_DSTREQ_MASK, (n)) +#define DMA_CH_CTRL_INTABT BIT(3) +#define DMA_CH_CTRL_INTERR BIT(2) +#define DMA_CH_CTRL_INTTC BIT(1) +#define DMA_CH_CTRL_ENABLE BIT(0) + +/* DMA Interrupt Status Register Definition */ +#define DMA_INT_STATUS_TC_MASK GENMASK(23, 16) +#define DMA_INT_STATUS_ABORT_MASK GENMASK(15, 8) +#define DMA_INT_STATUS_ERROR_MASK GENMASK(7, 0) +#define DMA_INT_STATUS_TC_VAL(x) FIELD_GET(DMA_INT_STATUS_TC_MASK, (x)) +#define DMA_INT_STATUS_ABORT_VAL(x) FIELD_GET(DMA_INT_STATUS_ABORT_MASK, (x)) +#define DMA_INT_STATUS_ERROR_VAL(x) FIELD_GET(DMA_INT_STATUS_ERROR_MASK, (x)) +#define DMA_INT_STATUS_CH_MSK(ch) (0x111 << ch) + +typedef void (*atcdmac300_cfg_func_t)(void); + +struct chain_block { + uint32_t ctrl; + uint32_t transize; + uint32_t srcaddrl; + uint32_t srcaddrh; + uint32_t dstaddrl; + uint32_t dstaddrh; + uint32_t llpointerl; + uint32_t llpointerh; +#if __riscv_xlen == 32 + uint32_t reserved; +#endif + struct chain_block *next_block; +}; + +/* data for each DMA channel */ +struct dma_chan_data { + void *blkuser_data; + dma_callback_t blkcallback; + struct chain_block *head_block; + struct dma_status status; +}; + +/* Device run time data */ +struct dma_atcdmac300_data { + struct dma_chan_data chan[ATCDMAC100_MAX_CHAN]; + struct k_spinlock lock; +}; + +/* Device constant configuration parameters */ +struct dma_atcdmac300_cfg { + atcdmac300_cfg_func_t irq_config; + uint32_t base; + uint32_t irq_num; +}; + +static struct __aligned(64) + chain_block dma_chain[ATCDMAC100_MAX_CHAN][sizeof(struct chain_block) * 16]; + +static void dma_atcdmac300_isr(const struct device *dev) +{ + uint32_t int_status, int_ch_status, channel; + struct dma_atcdmac300_data *const data = dev->data; + struct dma_chan_data *ch_data; + k_spinlock_key_t key; + + key = k_spin_lock(&data->lock); + int_status = sys_read32(DMA_INT_STATUS(dev)); + /* Clear interrupt*/ + sys_write32(int_status, DMA_INT_STATUS(dev)); + + k_spin_unlock(&data->lock, key); + + /* Handle terminal count status */ + int_ch_status = DMA_INT_STATUS_TC_VAL(int_status); + while (int_ch_status) { + channel = find_msb_set(int_ch_status) - 1; + int_ch_status &= ~(BIT(channel)); + + ch_data = &data->chan[channel]; + if (ch_data->blkcallback) { + ch_data->blkcallback(dev, ch_data->blkuser_data, channel, 0); + } + data->chan[channel].status.busy = false; + } + + /* Handle error status */ + int_ch_status = DMA_INT_STATUS_ERROR_VAL(int_status); + while (int_ch_status) { + channel = find_msb_set(int_ch_status) - 1; + int_ch_status &= ~(BIT(channel)); + + ch_data = &data->chan[channel]; + if (ch_data->blkcallback) { + ch_data->blkcallback(dev, ch_data->blkuser_data, channel, -EIO); + } + } +} + +static int dma_atcdmac300_config(const struct device *dev, uint32_t channel, + struct dma_config *cfg) +{ + struct dma_atcdmac300_data *const data = dev->data; + uint32_t src_width, dst_width, src_burst_size, ch_ctrl, tfr_size; + int32_t ret = 0; + struct dma_block_config *cfg_blocks; + k_spinlock_key_t key; + + if (channel >= ATCDMAC100_MAX_CHAN) { + return -EINVAL; + } + + __ASSERT_NO_MSG(cfg->source_data_size == cfg->dest_data_size); + __ASSERT_NO_MSG(cfg->source_burst_length == cfg->dest_burst_length); + + if (cfg->source_data_size != 1 && cfg->source_data_size != 2 && + cfg->source_data_size != 4) { + LOG_ERR("Invalid 'source_data_size' value"); + ret = -EINVAL; + goto end; + } + + cfg_blocks = cfg->head_block; + if (cfg_blocks == NULL) { + ret = -EINVAL; + goto end; + } + + tfr_size = cfg_blocks->block_size/cfg->source_data_size; + if (tfr_size == 0) { + ret = -EINVAL; + goto end; + } + + ch_ctrl = 0; + + switch (cfg->channel_direction) { + case MEMORY_TO_MEMORY: + break; + case MEMORY_TO_PERIPHERAL: + ch_ctrl |= DMA_CH_CTRL_DSTREQ(cfg->dma_slot); + ch_ctrl |= DMA_CH_CTRL_DMODE_HANDSHAKE; + break; + case PERIPHERAL_TO_MEMORY: + ch_ctrl |= DMA_CH_CTRL_SRCREQ(cfg->dma_slot); + ch_ctrl |= DMA_CH_CTRL_SMODE_HANDSHAKE; + break; + default: + ret = -EINVAL; + goto end; + } + + + switch (cfg_blocks->source_addr_adj) { + case DMA_ADDR_ADJ_INCREMENT: + ch_ctrl |= DMA_CH_CTRL_SRCADDR_INC; + break; + case DMA_ADDR_ADJ_DECREMENT: + ch_ctrl |= DMA_CH_CTRL_SRCADDR_DEC; + break; + case DMA_ADDR_ADJ_NO_CHANGE: + ch_ctrl |= DMA_CH_CTRL_SRCADDR_FIX; + break; + default: + ret = -EINVAL; + goto end; + } + + switch (cfg_blocks->dest_addr_adj) { + case DMA_ADDR_ADJ_INCREMENT: + ch_ctrl |= DMA_CH_CTRL_DSTADDR_INC; + break; + case DMA_ADDR_ADJ_DECREMENT: + ch_ctrl |= DMA_CH_CTRL_DSTADDR_DEC; + break; + case DMA_ADDR_ADJ_NO_CHANGE: + ch_ctrl |= DMA_CH_CTRL_DSTADDR_FIX; + break; + default: + ret = -EINVAL; + goto end; + } + + ch_ctrl |= DMA_CH_CTRL_INTABT; + + /* Disable the error callback */ + if (!cfg->error_callback_en) { + ch_ctrl |= DMA_CH_CTRL_INTERR; + } + + src_width = find_msb_set(cfg->source_data_size) - 1; + dst_width = find_msb_set(cfg->dest_data_size) - 1; + src_burst_size = find_msb_set(cfg->source_burst_length) - 1; + + ch_ctrl |= DMA_CH_CTRL_SWIDTH(src_width) | + DMA_CH_CTRL_DWIDTH(dst_width) | + DMA_CH_CTRL_SBSIZE(src_burst_size); + + + /* Reset DMA channel configuration */ + sys_write32(0, DMA_CH_CTRL(dev, channel)); + + key = k_spin_lock(&data->lock); + /* Clear DMA interrupts status */ + sys_write32(DMA_INT_STATUS_CH_MSK(channel), DMA_INT_STATUS(dev)); + k_spin_unlock(&data->lock, key); + + /* Set transfer size */ + sys_write32(tfr_size, DMA_CH_TRANSIZE(dev, channel)); + + /* Update the status of channel */ + data->chan[channel].status.dir = cfg->channel_direction; + data->chan[channel].status.pending_length = cfg->source_data_size; + + /* Configure a callback appropriately depending on whether the + * interrupt is requested at the end of transaction completion or + * at the end of each block. + */ + data->chan[channel].blkcallback = cfg->dma_callback; + data->chan[channel].blkuser_data = cfg->user_data; + + sys_write32(ch_ctrl, DMA_CH_CTRL(dev, channel)); + + /* Set source and destination address */ + sys_write32(cfg_blocks->source_address, + DMA_CH_SRC_ADDR_L(dev, channel)); + sys_write32(0, DMA_CH_SRC_ADDR_H(dev, channel)); + sys_write32(cfg_blocks->dest_address, + DMA_CH_DST_ADDR_L(dev, channel)); + sys_write32(0, DMA_CH_DST_ADDR_H(dev, channel)); + + if (cfg->dest_chaining_en == 1 && cfg_blocks->next_block) { + uint32_t current_block_idx = 0; + + sys_write32((uint32_t)((long)&dma_chain[channel][current_block_idx]), + DMA_CH_LL_PTR_L(dev, channel)); + sys_write32(0, DMA_CH_LL_PTR_H(dev, channel)); + + for (cfg_blocks = cfg_blocks->next_block; cfg_blocks != NULL; + cfg_blocks = cfg_blocks->next_block) { + + ch_ctrl &= ~(DMA_CH_CTRL_SRCADDRCTRL_MASK | + DMA_CH_CTRL_DSTADDRCTRL_MASK); + + switch (cfg_blocks->source_addr_adj) { + case DMA_ADDR_ADJ_INCREMENT: + ch_ctrl |= DMA_CH_CTRL_SRCADDR_INC; + break; + case DMA_ADDR_ADJ_DECREMENT: + ch_ctrl |= DMA_CH_CTRL_SRCADDR_DEC; + break; + case DMA_ADDR_ADJ_NO_CHANGE: + ch_ctrl |= DMA_CH_CTRL_SRCADDR_FIX; + break; + default: + ret = -EINVAL; + goto end; + } + + switch (cfg_blocks->dest_addr_adj) { + case DMA_ADDR_ADJ_INCREMENT: + ch_ctrl |= DMA_CH_CTRL_DSTADDR_INC; + break; + case DMA_ADDR_ADJ_DECREMENT: + ch_ctrl |= DMA_CH_CTRL_DSTADDR_DEC; + break; + case DMA_ADDR_ADJ_NO_CHANGE: + ch_ctrl |= DMA_CH_CTRL_DSTADDR_FIX; + break; + default: + ret = -EINVAL; + goto end; + } + dma_chain[channel][current_block_idx].ctrl = ch_ctrl; + dma_chain[channel][current_block_idx].transize = + cfg_blocks->block_size/cfg->source_data_size; + + dma_chain[channel][current_block_idx].srcaddrl = + (uint32_t)cfg_blocks->source_address; + dma_chain[channel][current_block_idx].srcaddrh = 0x0; + + dma_chain[channel][current_block_idx].dstaddrl = + (uint32_t)((long)cfg_blocks->dest_address); + dma_chain[channel][current_block_idx].dstaddrh = 0x0; + + if (cfg_blocks->next_block) { + dma_chain[channel][current_block_idx].llpointerl = + (uint32_t)&dma_chain[channel][current_block_idx + 1]; + dma_chain[channel][current_block_idx].llpointerh = 0x0; + + current_block_idx = current_block_idx + 1; + + } else { + dma_chain[channel][current_block_idx].llpointerl = 0x0; + dma_chain[channel][current_block_idx].llpointerh = 0x0; + dma_chain[channel][current_block_idx].next_block = NULL; + } + } + } else { + /* Single transfer is supported, but Chain transfer is still + * not supported. Therefore, set LLPointer to zero + */ + sys_write32(0, DMA_CH_LL_PTR_L(dev, channel)); + sys_write32(0, DMA_CH_LL_PTR_H(dev, channel)); + } + +end: + return ret; +} + +static int dma_atcdmac300_reload(const struct device *dev, uint32_t channel, + uint32_t src, uint32_t dst, size_t size) +{ + uint32_t src_width; + + if (channel >= ATCDMAC100_MAX_CHAN) { + return -EINVAL; + } + + /* Set source and destination address */ + sys_write32(src, DMA_CH_SRC_ADDR_L(dev, channel)); + sys_write32(0, DMA_CH_SRC_ADDR_H(dev, channel)); + sys_write32(dst, DMA_CH_DST_ADDR_L(dev, channel)); + sys_write32(0, DMA_CH_DST_ADDR_H(dev, channel)); + + src_width = FIELD_GET(DMA_CH_CTRL_SWIDTH_MASK, sys_read32(DMA_CH_CTRL(dev, channel))); + src_width = BIT(src_width); + + /* Set transfer size */ + sys_write32(size/src_width, DMA_CH_TRANSIZE(dev, channel)); + + return 0; +} + +static int dma_atcdmac300_transfer_start(const struct device *dev, + uint32_t channel) +{ + struct dma_atcdmac300_data *const data = dev->data; + + if (channel >= ATCDMAC100_MAX_CHAN) { + return -EINVAL; + } + + sys_write32(sys_read32(DMA_CH_CTRL(dev, channel)) | DMA_CH_CTRL_ENABLE, + DMA_CH_CTRL(dev, channel)); + + data->chan[channel].status.busy = true; + + return 0; +} + +static int dma_atcdmac300_transfer_stop(const struct device *dev, + uint32_t channel) +{ + struct dma_atcdmac300_data *const data = dev->data; + k_spinlock_key_t key; + + if (channel >= ATCDMAC100_MAX_CHAN) { + return -EINVAL; + } + + key = k_spin_lock(&data->lock); + + sys_write32(BIT(channel), DMA_ABORT(dev)); + sys_write32(0, DMA_CH_CTRL(dev, channel)); + sys_write32(FIELD_GET(DMA_INT_STATUS_ABORT_MASK, (channel)), DMA_INT_STATUS(dev)); + data->chan[channel].status.busy = false; + + k_spin_unlock(&data->lock, key); + + return 0; +} + +static int dma_atcdmac300_init(const struct device *dev) +{ + const struct dma_atcdmac300_cfg *const config = (struct dma_atcdmac300_cfg *)dev->config; + uint32_t ch_num; + + /* Disable all channels and Channel interrupts */ + for (ch_num = 0; ch_num < ATCDMAC100_MAX_CHAN; ch_num++) { + sys_write32(0, DMA_CH_CTRL(dev, ch_num)); + } + + sys_write32(0xFFFFFF, DMA_INT_STATUS(dev)); + + /* Configure interrupts */ + config->irq_config(); + + irq_enable(config->irq_num); + + return 0; +} + +static int dma_atcdmac300_get_status(const struct device *dev, + uint32_t channel, + struct dma_status *stat) +{ + struct dma_atcdmac300_data *const data = dev->data; + + stat->busy = data->chan[channel].status.busy; + stat->dir = data->chan[channel].status.dir; + stat->pending_length = data->chan[channel].status.pending_length; + + return 0; +} + +static const struct dma_driver_api dma_atcdmac300_api = { + .config = dma_atcdmac300_config, + .reload = dma_atcdmac300_reload, + .start = dma_atcdmac300_transfer_start, + .stop = dma_atcdmac300_transfer_stop, + .get_status = dma_atcdmac300_get_status +}; + +#define ATCDMAC300_INIT(n) \ + \ + static void dma_atcdmac300_irq_config_##n(void); \ + \ + static const struct dma_atcdmac300_cfg dma_config_##n = { \ + .irq_config = dma_atcdmac300_irq_config_##n, \ + .base = DT_INST_REG_ADDR(n), \ + .irq_num = DT_INST_IRQN(n), \ + }; \ + \ + static struct dma_atcdmac300_data dma_data_##n; \ + \ + DEVICE_DT_INST_DEFINE(0, \ + dma_atcdmac300_init, \ + NULL, \ + &dma_data_##n, \ + &dma_config_##n, \ + POST_KERNEL, \ + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ + &dma_atcdmac300_api); \ + \ + static void dma_atcdmac300_irq_config_##n(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), \ + 1, \ + dma_atcdmac300_isr, \ + DEVICE_DT_INST_GET(n), \ + 0); \ + } + + +DT_INST_FOREACH_STATUS_OKAY(ATCDMAC300_INIT) diff --git a/drivers/dma/dma_dw_common.c b/drivers/dma/dma_dw_common.c index e3210658dfc..0a5040980b2 100644 --- a/drivers/dma/dma_dw_common.c +++ b/drivers/dma/dma_dw_common.c @@ -434,7 +434,7 @@ bool dw_dma_is_enabled(const struct device *dev, uint32_t channel) { const struct dw_dma_dev_cfg *const dev_cfg = dev->config; - return dw_read(dev_cfg->base, DW_DMA_CHAN_EN) & DW_CHAN_MASK(channel); + return dw_read(dev_cfg->base, DW_DMA_CHAN_EN) & DW_CHAN(channel); } int dw_dma_start(const struct device *dev, uint32_t channel) @@ -809,7 +809,7 @@ int dw_dma_get_status(const struct device *dev, uint32_t channel, const struct dw_dma_dev_cfg *const dev_cfg = dev->config; struct dw_dma_chan_data *chan_data; - if (channel >= DW_MAX_CHAN) { + if (channel >= DW_CHAN_COUNT) { return -EINVAL; } diff --git a/drivers/dma/dma_handlers.c b/drivers/dma/dma_handlers.c index 058cbbf4623..d84c1510152 100644 --- a/drivers/dma/dma_handlers.c +++ b/drivers/dma/dma_handlers.c @@ -5,7 +5,7 @@ */ #include -#include +#include /* Both of these APIs are assuming that the drive implementations are checking * the validity of the channel ID and returning -errno if it's bogus @@ -13,14 +13,14 @@ static inline int z_vrfy_dma_start(const struct device *dev, uint32_t channel) { - Z_OOPS(Z_SYSCALL_DRIVER_DMA(dev, start)); + K_OOPS(K_SYSCALL_DRIVER_DMA(dev, start)); return z_impl_dma_start((const struct device *)dev, channel); } #include static inline int z_vrfy_dma_stop(const struct device *dev, uint32_t channel) { - Z_OOPS(Z_SYSCALL_DRIVER_DMA(dev, stop)); + K_OOPS(K_SYSCALL_DRIVER_DMA(dev, stop)); return z_impl_dma_stop((const struct device *)dev, channel); } #include diff --git a/drivers/dma/dma_intel_adsp_gpdma.c b/drivers/dma/dma_intel_adsp_gpdma.c index 1601d9af6ac..50e1fdae50e 100644 --- a/drivers/dma/dma_intel_adsp_gpdma.c +++ b/drivers/dma/dma_intel_adsp_gpdma.c @@ -320,6 +320,7 @@ static int intel_adsp_gpdma_enable(const struct device *dev) return 0; } +#ifdef CONFIG_PM_DEVICE static int intel_adsp_gpdma_disable(const struct device *dev) { const struct intel_adsp_gpdma_cfg *const dev_cfg = dev->config; @@ -328,7 +329,8 @@ static int intel_adsp_gpdma_disable(const struct device *dev) sys_write32(sys_read32(reg) & ~SHIM_CLKCTL_LPGPDMA_SPA, reg); return 0; } -#endif +#endif /* CONFIG_PM_DEVICE */ +#endif /* CONFIG_SOC_SERIES_INTEL_ACE */ static int intel_adsp_gpdma_power_on(const struct device *dev) { diff --git a/drivers/dma/dma_intel_adsp_hda.c b/drivers/dma/dma_intel_adsp_hda.c index daf0a4622b8..2dd0bea6ed6 100644 --- a/drivers/dma/dma_intel_adsp_hda.c +++ b/drivers/dma/dma_intel_adsp_hda.c @@ -53,10 +53,8 @@ int intel_adsp_hda_dma_host_in_config(const struct device *dev, *DGMBS(cfg->base, cfg->regblock_size, channel) = blk_cfg->block_size & HDA_ALIGN_MASK; - if (dma_cfg->source_data_size <= 3) { - /* set the sample container set bit to 16bits */ - *DGCS(cfg->base, cfg->regblock_size, channel) |= DGCS_SCS; - } + intel_adsp_hda_set_sample_container_size(cfg->base, cfg->regblock_size, channel, + dma_cfg->source_data_size); } return res; @@ -90,10 +88,8 @@ int intel_adsp_hda_dma_host_out_config(const struct device *dev, *DGMBS(cfg->base, cfg->regblock_size, channel) = blk_cfg->block_size & HDA_ALIGN_MASK; - if (dma_cfg->dest_data_size <= 3) { - /* set the sample container set bit to 16bits */ - *DGCS(cfg->base, cfg->regblock_size, channel) |= DGCS_SCS; - } + intel_adsp_hda_set_sample_container_size(cfg->base, cfg->regblock_size, channel, + dma_cfg->dest_data_size); } return res; @@ -120,10 +116,9 @@ int intel_adsp_hda_dma_link_in_config(const struct device *dev, buf = (uint8_t *)(uintptr_t)(blk_cfg->dest_address); res = intel_adsp_hda_set_buffer(cfg->base, cfg->regblock_size, channel, buf, blk_cfg->block_size); - - if (res == 0 && dma_cfg->dest_data_size <= 3) { - /* set the sample container set bit to 16bits */ - *DGCS(cfg->base, cfg->regblock_size, channel) |= DGCS_SCS; + if (res == 0) { + intel_adsp_hda_set_sample_container_size(cfg->base, cfg->regblock_size, channel, + dma_cfg->dest_data_size); } return res; @@ -152,10 +147,9 @@ int intel_adsp_hda_dma_link_out_config(const struct device *dev, res = intel_adsp_hda_set_buffer(cfg->base, cfg->regblock_size, channel, buf, blk_cfg->block_size); - - if (res == 0 && dma_cfg->source_data_size <= 3) { - /* set the sample container set bit to 16bits */ - *DGCS(cfg->base, cfg->regblock_size, channel) |= DGCS_SCS; + if (res == 0) { + intel_adsp_hda_set_sample_container_size(cfg->base, cfg->regblock_size, channel, + dma_cfg->source_data_size); } return res; diff --git a/drivers/dma/dma_intel_lpss.c b/drivers/dma/dma_intel_lpss.c index c1ae1763e50..7d0fec20045 100644 --- a/drivers/dma/dma_intel_lpss.c +++ b/drivers/dma/dma_intel_lpss.c @@ -27,22 +27,36 @@ struct dma_intel_lpss_cfg { const struct device *parent; }; +int dma_intel_lpss_setup(const struct device *dev) +{ + struct dma_intel_lpss_cfg *dev_cfg = (struct dma_intel_lpss_cfg *)dev->config; + + if (dev_cfg->dw_cfg.base != 0) { + return dw_dma_setup(dev); + } + + return 0; +} + +void dma_intel_lpss_set_base(const struct device *dev, uintptr_t base) +{ + struct dma_intel_lpss_cfg *dev_cfg = (struct dma_intel_lpss_cfg *)dev->config; + + dev_cfg->dw_cfg.base = base; +} + static int dma_intel_lpss_init(const struct device *dev) { struct dma_intel_lpss_cfg *dev_cfg = (struct dma_intel_lpss_cfg *)dev->config; uint32_t base; int ret; - if (!device_is_ready(dev_cfg->parent)) { - LOG_ERR("LPSS DMA parent not ready"); - ret = -ENODEV; - goto out; + if (device_is_ready(dev_cfg->parent)) { + base = DEVICE_MMIO_GET(dev_cfg->parent) + DMA_INTEL_LPSS_OFFSET; + dev_cfg->dw_cfg.base = base; } - base = DEVICE_MMIO_GET(dev_cfg->parent) + DMA_INTEL_LPSS_OFFSET; - dev_cfg->dw_cfg.base = base; - - ret = dw_dma_setup(dev); + ret = dma_intel_lpss_setup(dev); if (ret != 0) { LOG_ERR("failed to initialize LPSS DMA %s", dev->name); @@ -53,6 +67,81 @@ static int dma_intel_lpss_init(const struct device *dev) return ret; } +int dma_intel_lpss_reload(const struct device *dev, uint32_t channel, + uint64_t src, uint64_t dst, size_t size) +{ + struct dw_dma_dev_data *const dev_data = dev->data; + struct dma_intel_lpss_cfg *lpss_dev_cfg = (struct dma_intel_lpss_cfg *)dev->config; + struct dw_dma_dev_cfg *const dev_cfg = &lpss_dev_cfg->dw_cfg; + struct dw_dma_chan_data *chan_data; + uint32_t ctrl_hi = 0; + + if (channel >= DW_MAX_CHAN) { + return -EINVAL; + } + + chan_data = &dev_data->chan[channel]; + + chan_data->lli_current->sar = src; + chan_data->lli_current->dar = dst; + chan_data->ptr_data.current_ptr = dst; + chan_data->ptr_data.buffer_bytes = size; + + ctrl_hi = dw_read(dev_cfg->base, DW_CTRL_HIGH(channel)); + ctrl_hi &= ~(DW_CTLH_DONE(1) | DW_CTLH_BLOCK_TS_MASK); + ctrl_hi |= size & DW_CTLH_BLOCK_TS_MASK; + + chan_data->lli_current->ctrl_hi = ctrl_hi; + chan_data->ptr_data.start_ptr = DW_DMA_LLI_ADDRESS(chan_data->lli_current, + chan_data->direction); + chan_data->ptr_data.end_ptr = chan_data->ptr_data.start_ptr + + chan_data->ptr_data.buffer_bytes; + chan_data->ptr_data.hw_ptr = chan_data->ptr_data.start_ptr; + + chan_data->state = DW_DMA_PREPARED; + + return 0; +} + +int dma_intel_lpss_get_status(const struct device *dev, uint32_t channel, + struct dma_status *stat) +{ + struct dma_intel_lpss_cfg *lpss_dev_cfg = (struct dma_intel_lpss_cfg *)dev->config; + struct dw_dma_dev_cfg *const dev_cfg = &lpss_dev_cfg->dw_cfg; + struct dw_dma_dev_data *const dev_data = dev->data; + struct dw_dma_chan_data *chan_data; + uint32_t ctrl_hi; + size_t current_length; + bool done; + + if (channel >= DW_CHAN_COUNT) { + return -EINVAL; + } + + chan_data = &dev_data->chan[channel]; + ctrl_hi = dw_read(dev_cfg->base, DW_CTRL_HIGH(channel)); + current_length = ctrl_hi & DW_CTLH_BLOCK_TS_MASK; + done = ctrl_hi & DW_CTLH_DONE(1); + + if (!(dw_read(dev_cfg->base, DW_DMA_CHAN_EN) & DW_CHAN(channel))) { + stat->busy = false; + stat->pending_length = chan_data->ptr_data.buffer_bytes; + return 0; + } + stat->busy = true; + + if (done) { + stat->pending_length = 0; + } else if (current_length == chan_data->ptr_data.buffer_bytes) { + stat->pending_length = chan_data->ptr_data.buffer_bytes; + } else { + stat->pending_length = + chan_data->ptr_data.buffer_bytes - current_length; + } + + return 0; +} + void dma_intel_lpss_isr(const struct device *dev) { dw_dma_isr(dev); @@ -61,9 +150,17 @@ void dma_intel_lpss_isr(const struct device *dev) static const struct dma_driver_api dma_intel_lpss_driver_api = { .config = dw_dma_config, .start = dw_dma_start, + .reload = dma_intel_lpss_reload, + .get_status = dma_intel_lpss_get_status, .stop = dw_dma_stop, }; +#define DMA_LPSS_INIT_VAL_0 49 /* When parent device depends on DMA */ +#define DMA_LPSS_INIT_VAL_1 80 /* When DMA device depends on parent */ + +#define DMA_LPSS_INIT_VAL(n)\ + _CONCAT(DMA_LPSS_INIT_VAL_, DT_INST_NODE_HAS_PROP(n, dma_parent)) + #define DMA_INTEL_LPSS_INIT(n) \ \ static struct dw_drv_plat_data dma_intel_lpss##n = { \ @@ -82,7 +179,8 @@ static const struct dma_driver_api dma_intel_lpss_driver_api = { .dw_cfg = { \ .base = 0, \ }, \ - .parent = DEVICE_DT_GET(DT_INST_PARENT(n)), \ + IF_ENABLED(DT_INST_NODE_HAS_PROP(n, dma_parent), \ + (.parent = DEVICE_DT_GET(DT_INST_PHANDLE(n, dma_parent)),))\ }; \ \ static struct dw_dma_dev_data dma_intel_lpss##n##_data = { \ @@ -94,7 +192,7 @@ static const struct dma_driver_api dma_intel_lpss_driver_api = { NULL, \ &dma_intel_lpss##n##_data, \ &dma_intel_lpss##n##_config, POST_KERNEL, \ - DMA_INTEL_LPSS_INIT_PRIORITY, \ + DMA_LPSS_INIT_VAL(n), \ &dma_intel_lpss_driver_api); \ DT_INST_FOREACH_STATUS_OKAY(DMA_INTEL_LPSS_INIT) diff --git a/drivers/dma/dma_mcux_edma.c b/drivers/dma/dma_mcux_edma.c index 9130542ee84..bc40f1c3a9e 100644 --- a/drivers/dma/dma_mcux_edma.c +++ b/drivers/dma/dma_mcux_edma.c @@ -24,14 +24,26 @@ #include #include +#ifdef CONFIG_DMA_MCUX_EDMA #define DT_DRV_COMPAT nxp_mcux_edma +#elif CONFIG_DMA_MCUX_EDMA_V3 +#define DT_DRV_COMPAT nxp_mcux_edma_v3 +#endif LOG_MODULE_REGISTER(dma_mcux_edma, CONFIG_DMA_LOG_LEVEL); +#define HAS_CHANNEL_GAP(n) DT_INST_NODE_HAS_PROP(n, channel_gap) || +#define DMA_MCUX_HAS_CHANNEL_GAP (DT_INST_FOREACH_STATUS_OKAY(HAS_CHANNEL_GAP) 0) + struct dma_mcux_edma_config { DMA_Type *base; - DMAMUX_Type *dmamux_base; + DMAMUX_Type **dmamux_base; + uint8_t channels_per_mux; + uint8_t dmamux_reg_offset; int dma_channels; /* number of channels */ +#if DMA_MCUX_HAS_CHANNEL_GAP + uint32_t channel_gap[2]; +#endif void (*irq_config_func)(const struct device *dev); }; @@ -102,20 +114,59 @@ struct dma_mcux_edma_data { #define DEV_DATA(dev) ((struct dma_mcux_edma_data *)dev->data) #define DEV_BASE(dev) ((DMA_Type *)DEV_CFG(dev)->base) -#define DEV_DMAMUX_BASE(dev) ((DMAMUX_Type *)DEV_CFG(dev)->dmamux_base) - #define DEV_CHANNEL_DATA(dev, ch) \ ((struct call_back *)(&(DEV_DATA(dev)->data_cb[ch]))) #define DEV_EDMA_HANDLE(dev, ch) \ ((edma_handle_t *)(&(DEV_CHANNEL_DATA(dev, ch)->edma_handle))) +#define DEV_DMAMUX_BASE(dev, idx) ((DMAMUX_Type *)DEV_CFG(dev)->dmamux_base[idx]) +#define DEV_DMAMUX_IDX(dev, ch) (ch / DEV_CFG(dev)->channels_per_mux) + +#define DEV_DMAMUX_CHANNEL(dev, ch) \ + (ch % DEV_CFG(dev)->channels_per_mux) ^ (DEV_CFG(dev)->dmamux_reg_offset) + +/* + * The hardware channel (takes the gap into account) is used when access DMA registers. + * For data structures in the shim driver still use the primitive channel. + */ +static ALWAYS_INLINE uint32_t dma_mcux_edma_add_channel_gap(const struct device *dev, + uint32_t channel) +{ +#if DMA_MCUX_HAS_CHANNEL_GAP + const struct dma_mcux_edma_config *config = DEV_CFG(dev); + + return (channel < config->channel_gap[0]) ? channel : + (channel + 1 + config->channel_gap[1] - config->channel_gap[0]); +#else + ARG_UNUSED(dev); + return channel; +#endif +} + +static ALWAYS_INLINE uint32_t dma_mcux_edma_remove_channel_gap(const struct device *dev, + uint32_t channel) +{ +#if DMA_MCUX_HAS_CHANNEL_GAP + const struct dma_mcux_edma_config *config = DEV_CFG(dev); + + return (channel < config->channel_gap[0]) ? channel : + (channel + config->channel_gap[0] - config->channel_gap[1] - 1); +#else + ARG_UNUSED(dev); + return channel; +#endif +} + static bool data_size_valid(const size_t data_size) { return (data_size == 4U || data_size == 2U || data_size == 1U || data_size == 8U || - data_size == 16U || - data_size == 32U); + data_size == 16U || data_size == 32U +#ifdef CONFIG_DMA_MCUX_EDMA_V3 + || data_size == 64U +#endif + ); } static void nxp_edma_callback(edma_handle_t *handle, void *param, bool transferDone, @@ -123,7 +174,8 @@ static void nxp_edma_callback(edma_handle_t *handle, void *param, bool transferD { int ret = -EIO; struct call_back *data = (struct call_back *)param; - uint32_t channel = handle->channel; + + uint32_t channel = dma_mcux_edma_remove_channel_gap(data->dev, handle->channel); if (transferDone) { /* DMA is no longer busy when there are no remaining TCDs to transfer */ @@ -134,46 +186,52 @@ static void nxp_edma_callback(edma_handle_t *handle, void *param, bool transferD data->dma_callback(data->dev, data->user_data, channel, ret); } - -static void dma_mcux_edma_irq_handler(const struct device *dev) +static void dma_mcux_edma_irq_handler(const struct device *dev, uint32_t channel) { - int i = 0; - - LOG_DBG("IRQ CALLED"); - for (i = 0; i < DT_INST_PROP(0, dma_channels); i++) { - uint32_t flag = EDMA_GetChannelStatusFlags(DEV_BASE(dev), i); + uint32_t hw_channel = dma_mcux_edma_add_channel_gap(dev, channel); + uint32_t flag = EDMA_GetChannelStatusFlags(DEV_BASE(dev), hw_channel); + + if (flag & kEDMA_InterruptFlag) { + LOG_DBG("IRQ OCCURRED"); + /* EDMA interrupt flag is cleared here */ + EDMA_HandleIRQ(DEV_EDMA_HANDLE(dev, channel)); + LOG_DBG("IRQ DONE"); + } - if ((flag & (uint32_t)kEDMA_InterruptFlag) != 0U) { - LOG_DBG("IRQ OCCURRED"); - EDMA_HandleIRQ(DEV_EDMA_HANDLE(dev, i)); - LOG_DBG("IRQ DONE"); -#if defined __CORTEX_M && (__CORTEX_M == 4U) - barrier_dsync_fence_full(); -#endif - } +#if DT_INST_PROP(0, no_error_irq) + /* Channel shares the same irq for error and transfer complete */ + else if (flag & kEDMA_ErrorFlag) { + EDMA_ClearChannelStatusFlags(DEV_BASE(dev), channel, 0xFFFFFFFF); + EDMA_AbortTransfer(DEV_EDMA_HANDLE(dev, channel)); + DEV_CHANNEL_DATA(dev, channel)->busy = false; + LOG_INF("channel %d error status is 0x%x", channel, flag); } +#endif } +#if !DT_INST_PROP(0, no_error_irq) static void dma_mcux_edma_error_irq_handler(const struct device *dev) { int i = 0; uint32_t flag = 0; + uint32_t hw_channel; - for (i = 0; i < DT_INST_PROP(0, dma_channels); i++) { + for (i = 0; i < DEV_CFG(dev)->dma_channels; i++) { if (DEV_CHANNEL_DATA(dev, i)->busy) { - flag = EDMA_GetChannelStatusFlags(DEV_BASE(dev), i); - LOG_INF("channel %d error status is 0x%x", i, flag); - EDMA_ClearChannelStatusFlags(DEV_BASE(dev), i, - 0xFFFFFFFF); + hw_channel = dma_mcux_edma_add_channel_gap(dev, i); + flag = EDMA_GetChannelStatusFlags(DEV_BASE(dev), hw_channel); + EDMA_ClearChannelStatusFlags(DEV_BASE(dev), hw_channel, 0xFFFFFFFF); EDMA_AbortTransfer(DEV_EDMA_HANDLE(dev, i)); DEV_CHANNEL_DATA(dev, i)->busy = false; + LOG_INF("channel %d error status is 0x%x", hw_channel, flag); } } -#if defined __CORTEX_M && (__CORTEX_M == 4U) +#if defined(CONFIG_CPU_CORTEX_M4) barrier_dsync_fence_full(); #endif } +#endif /* Configure a channel */ static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel, @@ -188,20 +246,25 @@ static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel, struct call_back *data = DEV_CHANNEL_DATA(dev, channel); struct dma_block_config *block_config = config->head_block; uint32_t slot = config->dma_slot; + uint8_t dmamux_idx, dmamux_channel; + uint32_t hw_channel; edma_transfer_type_t transfer_type; unsigned int key; int ret = 0; - if (slot > DT_INST_PROP(0, dma_requests)) { - LOG_ERR("source number is outof scope %d", slot); + if (slot >= DT_INST_PROP(0, dma_requests)) { + LOG_ERR("source number is out of scope %d", slot); return -ENOTSUP; } - if (channel > DT_INST_PROP(0, dma_channels)) { + if (channel >= DT_INST_PROP(0, dma_channels)) { LOG_ERR("out of DMA channel %d", channel); return -EINVAL; } + hw_channel = dma_mcux_edma_add_channel_gap(dev, channel); + dmamux_idx = DEV_DMAMUX_IDX(dev, channel); + dmamux_channel = DEV_DMAMUX_CHANNEL(dev, channel); data->transfer_settings.valid = false; switch (config->channel_direction) { @@ -256,26 +319,26 @@ static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel, transfer_type == kEDMA_MemoryToMemory) { /*software trigger make the channel always on*/ LOG_DBG("ALWAYS ON"); - DMAMUX_EnableAlwaysOn(DEV_DMAMUX_BASE(dev), channel, true); + DMAMUX_EnableAlwaysOn(DEV_DMAMUX_BASE(dev, dmamux_idx), dmamux_channel, true); } else { - DMAMUX_SetSource(DEV_DMAMUX_BASE(dev), channel, slot); + DMAMUX_SetSource(DEV_DMAMUX_BASE(dev, dmamux_idx), dmamux_channel, slot); } #else - DMAMUX_SetSource(DEV_DMAMUX_BASE(dev), channel, slot); + DMAMUX_SetSource(DEV_DMAMUX_BASE(dev, dmamux_idx), dmamux_channel, slot); #endif /* dam_imx_rt_set_channel_priority(dev, channel, config); */ - DMAMUX_EnableChannel(DEV_DMAMUX_BASE(dev), channel); + DMAMUX_EnableChannel(DEV_DMAMUX_BASE(dev, dmamux_idx), dmamux_channel); if (data->busy) { EDMA_AbortTransfer(p_handle); } - EDMA_ResetChannel(DEV_BASE(dev), channel); - EDMA_CreateHandle(p_handle, DEV_BASE(dev), channel); + EDMA_ResetChannel(DEV_BASE(dev), hw_channel); + EDMA_CreateHandle(p_handle, DEV_BASE(dev), hw_channel); EDMA_SetCallback(p_handle, nxp_edma_callback, (void *)data); - LOG_DBG("channel is %d", p_handle->channel); - EDMA_EnableChannelInterrupts(DEV_BASE(dev), channel, kEDMA_ErrorInterruptEnable); + LOG_DBG("channel is %d", channel); + EDMA_EnableChannelInterrupts(DEV_BASE(dev), hw_channel, kEDMA_ErrorInterruptEnable); if (block_config->source_gather_en || block_config->dest_scatter_en) { EDMA_InstallTCDMemory(p_handle, tcdpool[channel], CONFIG_DMA_TCD_QUEUE_SIZE); @@ -314,8 +377,11 @@ static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel, LOG_ERR("Error submitting EDMA Transfer: 0x%x", submit_status); ret = -EFAULT; } - edma_tcd_t *tcdRegs = (edma_tcd_t *)(uint32_t)&p_handle->base->TCD[channel]; - LOG_DBG("data csr is 0x%x", tcdRegs->CSR); +#ifdef CONFIG_DMA_MCUX_EDMA_V3 + LOG_DBG("DMA TCD_CSR 0x%x", DEV_BASE(dev)->CH[hw_channel].TCD_CSR); +#else + LOG_DBG("data csr is 0x%x", DEV_BASE(dev)->TCD[hw_channel].CSR); +#endif } if (config->dest_chaining_en) { @@ -345,10 +411,15 @@ static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel, static int dma_mcux_edma_start(const struct device *dev, uint32_t channel) { struct call_back *data = DEV_CHANNEL_DATA(dev, channel); + uint8_t dmamux_idx = DEV_DMAMUX_IDX(dev, channel); + uint8_t dmamux_channel = DEV_DMAMUX_CHANNEL(dev, channel); LOG_DBG("START TRANSFER"); - LOG_DBG("DMAMUX CHCFG 0x%x", DEV_DMAMUX_BASE(dev)->CHCFG[channel]); + LOG_DBG("DMAMUX CHCFG 0x%x", DEV_DMAMUX_BASE(dev, dmamux_idx)->CHCFG[dmamux_channel]); + +#ifndef CONFIG_DMA_MCUX_EDMA_V3 LOG_DBG("DMA CR 0x%x", DEV_BASE(dev)->CR); +#endif data->busy = true; EDMA_StartTransfer(DEV_EDMA_HANDLE(dev, channel)); return 0; @@ -357,17 +428,21 @@ static int dma_mcux_edma_start(const struct device *dev, uint32_t channel) static int dma_mcux_edma_stop(const struct device *dev, uint32_t channel) { struct dma_mcux_edma_data *data = DEV_DATA(dev); + uint32_t hw_channel; + + hw_channel = dma_mcux_edma_add_channel_gap(dev, channel); data->data_cb[channel].transfer_settings.valid = false; if (!data->data_cb[channel].busy) { return 0; } + EDMA_AbortTransfer(DEV_EDMA_HANDLE(dev, channel)); - EDMA_ClearChannelStatusFlags(DEV_BASE(dev), channel, + EDMA_ClearChannelStatusFlags(DEV_BASE(dev), hw_channel, kEDMA_DoneFlag | kEDMA_ErrorFlag | kEDMA_InterruptFlag); - EDMA_ResetChannel(DEV_BASE(dev), channel); + EDMA_ResetChannel(DEV_BASE(dev), hw_channel); data->data_cb[channel].busy = false; return 0; } @@ -443,26 +518,39 @@ static int dma_mcux_edma_reload(const struct device *dev, uint32_t channel, static int dma_mcux_edma_get_status(const struct device *dev, uint32_t channel, struct dma_status *status) { - edma_tcd_t *tcdRegs; + uint8_t dmamux_idx = DEV_DMAMUX_IDX(dev, channel); + uint8_t dmamux_channel = DEV_DMAMUX_CHANNEL(dev, channel); + + uint32_t hw_channel = dma_mcux_edma_add_channel_gap(dev, channel); if (DEV_CHANNEL_DATA(dev, channel)->busy) { status->busy = true; status->pending_length = - EDMA_GetRemainingMajorLoopCount(DEV_BASE(dev), channel); + EDMA_GetRemainingMajorLoopCount(DEV_BASE(dev), hw_channel); } else { status->busy = false; status->pending_length = 0; } status->dir = DEV_CHANNEL_DATA(dev, channel)->transfer_settings.direction; - LOG_DBG("DMAMUX CHCFG 0x%x", DEV_DMAMUX_BASE(dev)->CHCFG[channel]); + LOG_DBG("DMAMUX CHCFG 0x%x", DEV_DMAMUX_BASE(dev, dmamux_idx)->CHCFG[dmamux_channel]); + +#ifdef CONFIG_DMA_MCUX_EDMA_V3 + LOG_DBG("DMA MP_CSR 0x%x", DEV_BASE(dev)->MP_CSR); + LOG_DBG("DMA MP_ES 0x%x", DEV_BASE(dev)->MP_ES); + LOG_DBG("DMA CHx_ES 0x%x", DEV_BASE(dev)->CH[hw_channel].CH_ES); + LOG_DBG("DMA CHx_CSR 0x%x", DEV_BASE(dev)->CH[hw_channel].CH_CSR); + LOG_DBG("DMA CHx_ES 0x%x", DEV_BASE(dev)->CH[hw_channel].CH_ES); + LOG_DBG("DMA CHx_INT 0x%x", DEV_BASE(dev)->CH[hw_channel].CH_INT); + LOG_DBG("DMA TCD_CSR 0x%x", DEV_BASE(dev)->CH[hw_channel].TCD_CSR); +#else LOG_DBG("DMA CR 0x%x", DEV_BASE(dev)->CR); LOG_DBG("DMA INT 0x%x", DEV_BASE(dev)->INT); LOG_DBG("DMA ERQ 0x%x", DEV_BASE(dev)->ERQ); LOG_DBG("DMA ES 0x%x", DEV_BASE(dev)->ES); LOG_DBG("DMA ERR 0x%x", DEV_BASE(dev)->ERR); LOG_DBG("DMA HRS 0x%x", DEV_BASE(dev)->HRS); - tcdRegs = (edma_tcd_t *)((uint32_t)&DEV_BASE(dev)->TCD[channel]); - LOG_DBG("data csr is 0x%x", tcdRegs->CSR); + LOG_DBG("data csr is 0x%x", DEV_BASE(dev)->TCD[hw_channel].CSR); +#endif return 0; } @@ -496,11 +584,20 @@ static int dma_mcux_edma_init(const struct device *dev) struct dma_mcux_edma_data *data = dev->data; edma_config_t userConfig = { 0 }; + uint8_t i; LOG_DBG("INIT NXP EDMA"); - DMAMUX_Init(DEV_DMAMUX_BASE(dev)); + + for (i = 0; i < config->dma_channels / config->channels_per_mux; i++) { + DMAMUX_Init(DEV_DMAMUX_BASE(dev, i)); + } + EDMA_GetDefaultConfig(&userConfig); EDMA_Init(DEV_BASE(dev), &userConfig); +#ifdef CONFIG_DMA_MCUX_EDMA_V3 + /* Channel linking available and will be controlled by each channel's link settings */ + EDMA_EnableAllChannelLink(DEV_BASE(dev), true); +#endif config->irq_config_func(dev); memset(dev->data, 0, sizeof(struct dma_mcux_edma_data)); memset(tcdpool, 0, sizeof(tcdpool)); @@ -510,63 +607,92 @@ static int dma_mcux_edma_init(const struct device *dev) return 0; } -#define IRQ_CONFIG(n, idx, fn) \ - IF_ENABLED(DT_INST_IRQ_HAS_IDX(n, idx), ( \ - IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, idx, irq), \ - DT_INST_IRQ_BY_IDX(n, idx, priority), \ - fn, \ - DEVICE_DT_INST_GET(n), 0); \ - irq_enable(DT_INST_IRQ_BY_IDX(n, idx, irq)); \ - )) - -#define DMA_MCUX_EDMA_CONFIG_FUNC(n) \ - static void dma_imx_config_func_##n(const struct device *dev) \ - { \ - ARG_UNUSED(dev); \ - \ - IRQ_CONFIG(n, 0, dma_mcux_edma_irq_handler); \ - IRQ_CONFIG(n, 1, dma_mcux_edma_irq_handler); \ - IRQ_CONFIG(n, 2, dma_mcux_edma_irq_handler); \ - IRQ_CONFIG(n, 3, dma_mcux_edma_irq_handler); \ - IRQ_CONFIG(n, 4, dma_mcux_edma_irq_handler); \ - IRQ_CONFIG(n, 5, dma_mcux_edma_irq_handler); \ - IRQ_CONFIG(n, 6, dma_mcux_edma_irq_handler); \ - IRQ_CONFIG(n, 7, dma_mcux_edma_irq_handler); \ - IRQ_CONFIG(n, 8, dma_mcux_edma_irq_handler); \ - IRQ_CONFIG(n, 9, dma_mcux_edma_irq_handler); \ - IRQ_CONFIG(n, 10, dma_mcux_edma_irq_handler); \ - IRQ_CONFIG(n, 11, dma_mcux_edma_irq_handler); \ - IRQ_CONFIG(n, 12, dma_mcux_edma_irq_handler); \ - IRQ_CONFIG(n, 13, dma_mcux_edma_irq_handler); \ - IRQ_CONFIG(n, 14, dma_mcux_edma_irq_handler); \ - IRQ_CONFIG(n, 15, dma_mcux_edma_irq_handler); \ - \ - IRQ_CONFIG(n, 16, dma_mcux_edma_error_irq_handler); \ - \ - LOG_DBG("install irq done"); \ +/* The shared error interrupt (if have) must be declared as the last element in devicetree */ +#if !DT_INST_PROP(0, no_error_irq) +#define NUM_IRQS_WITHOUT_ERROR_IRQ(n) UTIL_DEC(DT_NUM_IRQS(DT_DRV_INST(n))) +#else +#define NUM_IRQS_WITHOUT_ERROR_IRQ(n) DT_NUM_IRQS(DT_DRV_INST(n)) +#endif + +#define IRQ_CONFIG(n, idx, fn) \ + { \ + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, idx, irq), \ + DT_INST_IRQ_BY_IDX(n, idx, priority), \ + fn, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQ_BY_IDX(n, idx, irq)); \ + } + +#define DMA_MCUX_EDMA_IRQ_DEFINE(idx, n) \ + static void dma_mcux_edma_##n##_irq_##idx(const struct device *dev) \ + { \ + dma_mcux_edma_irq_handler(dev, idx); \ + \ + IF_ENABLED(UTIL_BOOL(DT_INST_PROP(n, irq_shared_offset)), \ + (dma_mcux_edma_irq_handler(dev, \ + idx + DT_INST_PROP(n, irq_shared_offset));)) \ + \ + IF_ENABLED(CONFIG_CPU_CORTEX_M4, (barrier_dsync_fence_full();)) \ } +#define DMA_MCUX_EDMA_IRQ_CONFIG(idx, n) \ + IRQ_CONFIG(n, idx, dma_mcux_edma_##n##_irq_##idx) + +#define DMA_MCUX_EDMA_CONFIG_FUNC(n) \ + LISTIFY(NUM_IRQS_WITHOUT_ERROR_IRQ(n), DMA_MCUX_EDMA_IRQ_DEFINE, (), n) \ + static void dma_imx_config_func_##n(const struct device *dev) \ + { \ + ARG_UNUSED(dev); \ + \ + LISTIFY(NUM_IRQS_WITHOUT_ERROR_IRQ(n), \ + DMA_MCUX_EDMA_IRQ_CONFIG, (;), n) \ + \ + IF_ENABLED(UTIL_NOT(DT_INST_NODE_HAS_PROP(n, no_error_irq)), \ + (IRQ_CONFIG(n, NUM_IRQS_WITHOUT_ERROR_IRQ(n), \ + dma_mcux_edma_error_irq_handler))) \ + \ + LOG_DBG("install irq done"); \ + } + +#define DMA_MCUX_EDMA_MUX(idx, n) \ + (DMAMUX_Type *)DT_INST_REG_ADDR_BY_IDX(n, UTIL_INC(idx)) + +#if DMA_MCUX_HAS_CHANNEL_GAP +#define DMA_MCUX_EDMA_CHANNEL_GAP(n) \ + .channel_gap = DT_INST_PROP_OR(n, channel_gap, \ + {[0 ... 1] = DT_INST_PROP(n, dma_channels)}), +#else +#define DMA_MCUX_EDMA_CHANNEL_GAP(n) +#endif + /* * define the dma */ -#define DMA_INIT(n) \ - static void dma_imx_config_func_##n(const struct device *dev); \ - static const struct dma_mcux_edma_config dma_config_##n = { \ - .base = (DMA_Type *)DT_INST_REG_ADDR(n), \ - .dmamux_base = \ - (DMAMUX_Type *)DT_INST_REG_ADDR_BY_IDX(n, 1), \ - .dma_channels = DT_INST_PROP(n, dma_channels), \ - .irq_config_func = dma_imx_config_func_##n, \ - }; \ - \ - struct dma_mcux_edma_data dma_data_##n; \ - \ - DEVICE_DT_INST_DEFINE(n, \ - &dma_mcux_edma_init, NULL, \ - &dma_data_##n, &dma_config_##n, \ - PRE_KERNEL_1, CONFIG_DMA_INIT_PRIORITY, \ - &dma_mcux_edma_api); \ - \ +#define DMA_INIT(n) \ + static void dma_imx_config_func_##n(const struct device *dev); \ + static DMAMUX_Type *dmamux_base_##n[] = { \ + LISTIFY(UTIL_DEC(DT_NUM_REGS(DT_DRV_INST(n))), \ + DMA_MCUX_EDMA_MUX, (,), n) \ + }; \ + static const struct dma_mcux_edma_config dma_config_##n = { \ + .base = (DMA_Type *)DT_INST_REG_ADDR(n), \ + .dmamux_base = &dmamux_base_##n[0], \ + .dma_channels = DT_INST_PROP(n, dma_channels), \ + .channels_per_mux = DT_INST_PROP(n, dma_channels) / \ + ARRAY_SIZE(dmamux_base_##n), \ + .irq_config_func = dma_imx_config_func_##n, \ + .dmamux_reg_offset = DT_INST_PROP(n, dmamux_reg_offset), \ + DMA_MCUX_EDMA_CHANNEL_GAP(n) \ + }; \ + \ + struct dma_mcux_edma_data dma_data_##n; \ + \ + DEVICE_DT_INST_DEFINE(n, \ + &dma_mcux_edma_init, NULL, \ + &dma_data_##n, &dma_config_##n, \ + PRE_KERNEL_1, CONFIG_DMA_INIT_PRIORITY, \ + &dma_mcux_edma_api); \ + \ DMA_MCUX_EDMA_CONFIG_FUNC(n); DT_INST_FOREACH_STATUS_OKAY(DMA_INIT) diff --git a/drivers/dma/dma_mcux_lpc.c b/drivers/dma/dma_mcux_lpc.c index eb44d4fb5fc..ef0a164d4af 100644 --- a/drivers/dma/dma_mcux_lpc.c +++ b/drivers/dma/dma_mcux_lpc.c @@ -18,6 +18,7 @@ #include #include #include +#include #define DT_DRV_COMPAT nxp_lpc_dma @@ -554,11 +555,35 @@ static int dma_mcux_lpc_configure(const struct device *dev, uint32_t channel, data->descriptors_queued = true; } - if (is_periph) { + if (config->dma_slot) { + uint32_t cfg_reg = 0; + + /* User supplied manual trigger configuration */ + if (config->dma_slot & LPC_DMA_PERIPH_REQ_EN) { + cfg_reg |= DMA_CHANNEL_CFG_PERIPHREQEN_MASK; + } + if (config->dma_slot & LPC_DMA_HWTRIG_EN) { + /* Setup hardware trigger */ + cfg_reg |= DMA_CHANNEL_CFG_HWTRIGEN_MASK; + if (config->dma_slot & LPC_DMA_TRIGTYPE_LEVEL) { + cfg_reg |= DMA_CHANNEL_CFG_TRIGTYPE_MASK; + } + if (config->dma_slot & LPC_DMA_TRIGPOL_HIGH_RISING) { + cfg_reg |= DMA_CHANNEL_CFG_TRIGPOL_MASK; + } + if (config->dma_slot & LPC_DMA_TRIGBURST) { + cfg_reg |= DMA_CHANNEL_CFG_TRIGBURST_MASK; + cfg_reg |= DMA_CHANNEL_CFG_BURSTPOWER( + LPC_DMA_GET_BURSTPOWER(config->dma_slot)); + } + } + p_handle->base->CHANNEL[p_handle->channel].CFG = cfg_reg; + } else if (is_periph) { DMA_EnableChannelPeriphRq(p_handle->base, p_handle->channel); } else { DMA_DisableChannelPeriphRq(p_handle->base, p_handle->channel); } + DMA_SetChannelPriority(p_handle->base, p_handle->channel, config->channel_priority); data->busy = false; if (config->dma_callback) { diff --git a/drivers/dma/dma_mcux_pxp.c b/drivers/dma/dma_mcux_pxp.c index 69ce6a2eeba..ef6f9f90f28 100644 --- a/drivers/dma/dma_mcux_pxp.c +++ b/drivers/dma/dma_mcux_pxp.c @@ -89,7 +89,13 @@ static int dma_mcux_pxp_configure(const struct device *dev, uint32_t channel, bytes_per_pixel = 2; break; case DMA_MCUX_PXP_FMT_RGB888: +#if (!(defined(FSL_FEATURE_PXP_HAS_NO_EXTEND_PIXEL_FORMAT) && \ + FSL_FEATURE_PXP_HAS_NO_EXTEND_PIXEL_FORMAT)) && \ + (!(defined(FSL_FEATURE_PXP_V3) && FSL_FEATURE_PXP_V3)) + ps_buffer_cfg.pixelFormat = kPXP_PsPixelFormatARGB8888; +#else ps_buffer_cfg.pixelFormat = kPXP_PsPixelFormatRGB888; +#endif output_buffer_cfg.pixelFormat = kPXP_OutputPixelFormatRGB888; bytes_per_pixel = 3; break; diff --git a/drivers/dma/dma_mcux_smartdma.c b/drivers/dma/dma_mcux_smartdma.c new file mode 100644 index 00000000000..b1870b3959c --- /dev/null +++ b/drivers/dma/dma_mcux_smartdma.c @@ -0,0 +1,252 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define DT_DRV_COMPAT nxp_smartdma + +LOG_MODULE_REGISTER(dma_mcux_smartdma, CONFIG_DMA_LOG_LEVEL); + +/* SMARTDMA peripheral registers, taken from MCUX driver implementation*/ +struct smartdma_periph { + volatile uint32_t BOOT; + volatile uint32_t CTRL; + volatile uint32_t PC; + volatile uint32_t SP; + volatile uint32_t BREAK_ADDR; + volatile uint32_t BREAK_VECT; + volatile uint32_t EMER_VECT; + volatile uint32_t EMER_SEL; + volatile uint32_t ARM2SMARTDMA; + volatile uint32_t SMARTDMA2ARM; + volatile uint32_t PENDTRAP; +}; + +struct dma_mcux_smartdma_config { + struct smartdma_periph *base; + void (*irq_config_func)(const struct device *dev); + + void (**smartdma_progs)(void); +}; + +struct dma_mcux_smartdma_data { + uint32_t smartdma_stack[32]; /* Stack for SMARTDMA */ + /* Installed DMA callback and user data */ + dma_callback_t callback; + void *user_data; +}; + +/* Seems to be written to smartDMA control register when it is configured */ +#define SMARTDMA_MAGIC 0xC0DE0000U +/* These bits are set when the SMARTDMA boots, cleared to reset it */ +#define SMARTDMA_BOOT 0x11 + +static inline bool dma_mcux_smartdma_prog_is_mipi(uint32_t prog) +{ + return ((prog == kSMARTDMA_MIPI_RGB565_DMA) || + (prog == kSMARTDMA_MIPI_RGB888_DMA) || + (prog == kSMARTDMA_MIPI_RGB565_R180_DMA) || + (prog == kSMARTDMA_MIPI_RGB888_R180_DMA)); +} + +/* Configure a channel */ +static int dma_mcux_smartdma_configure(const struct device *dev, + uint32_t channel, struct dma_config *config) +{ + const struct dma_mcux_smartdma_config *dev_config = dev->config; + struct dma_mcux_smartdma_data *data = dev->data; + uint32_t prog_idx; + bool swap_pixels = false; + + /* SMARTDMA does not have channels */ + ARG_UNUSED(channel); + + data->callback = config->dma_callback; + data->user_data = config->user_data; + + /* Reset smartDMA */ + SMARTDMA_Reset(); + + /* + * The dma_slot parameter is used to determine which SMARTDMA program + * to run. First, convert the Zephyr define to a HAL enum. + */ + switch (config->dma_slot) { + case DMA_SMARTDMA_MIPI_RGB565_DMA: + prog_idx = kSMARTDMA_MIPI_RGB565_DMA; + break; + case DMA_SMARTDMA_MIPI_RGB888_DMA: + prog_idx = kSMARTDMA_MIPI_RGB888_DMA; + break; + case DMA_SMARTDMA_MIPI_RGB565_180: + prog_idx = kSMARTDMA_MIPI_RGB565_R180_DMA; + break; + case DMA_SMARTDMA_MIPI_RGB888_180: + prog_idx = kSMARTDMA_MIPI_RGB888_R180_DMA; + break; + case DMA_SMARTDMA_MIPI_RGB565_DMA_SWAP: + swap_pixels = true; + prog_idx = kSMARTDMA_MIPI_RGB565_DMA; + break; + case DMA_SMARTDMA_MIPI_RGB888_DMA_SWAP: + swap_pixels = true; + prog_idx = kSMARTDMA_MIPI_RGB888_DMA; + break; + case DMA_SMARTDMA_MIPI_RGB565_180_SWAP: + swap_pixels = true; + prog_idx = kSMARTDMA_MIPI_RGB565_R180_DMA; + break; + case DMA_SMARTDMA_MIPI_RGB888_180_SWAP: + swap_pixels = true; + prog_idx = kSMARTDMA_MIPI_RGB888_R180_DMA; + break; + default: + prog_idx = config->dma_slot; + break; + } + + if (dma_mcux_smartdma_prog_is_mipi(prog_idx)) { + smartdma_dsi_param_t param = {.disablePixelByteSwap = (swap_pixels == false)}; + + if (config->block_count != 1) { + return -ENOTSUP; + } + /* Setup SMARTDMA */ + param.p_buffer = (uint8_t *)config->head_block->source_address; + param.buffersize = config->head_block->block_size; + param.smartdma_stack = data->smartdma_stack; + /* Save configuration to SMARTDMA */ + dev_config->base->ARM2SMARTDMA = (uint32_t)(¶m); + } else { + /* For other cases, we simply pass the entire DMA config + * struct to the SMARTDMA. The user's application could either + * populate this structure with data, or choose to write + * different configuration data to the SMARTDMA in their + * application + */ + dev_config->base->ARM2SMARTDMA = ((uint32_t)config); + } + /* Save program */ + dev_config->base->BOOT = (uint32_t)dev_config->smartdma_progs[prog_idx]; + LOG_DBG("Boot address set to 0x%X", dev_config->base->BOOT); + return 0; +} + +static int dma_mcux_smartdma_start(const struct device *dev, uint32_t channel) +{ + const struct dma_mcux_smartdma_config *config = dev->config; + +#ifdef CONFIG_PM + /* Block PM transition until DMA completes */ + pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES); +#endif + /* Kick off SMARTDMA */ + config->base->CTRL = SMARTDMA_MAGIC | SMARTDMA_BOOT; + return 0; +} + + +static int dma_mcux_smartdma_stop(const struct device *dev, uint32_t channel) +{ + ARG_UNUSED(dev); + ARG_UNUSED(channel); + /* Stop DMA */ + SMARTDMA_Reset(); +#ifdef CONFIG_PM + /* Release PM lock */ + pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES); +#endif + return 0; +} + +static int dma_mcux_smartdma_init(const struct device *dev) +{ + const struct dma_mcux_smartdma_config *config = dev->config; + /* + * Initialize the SMARTDMA with firmware. The default firmware + * from MCUX SDK is a display firmware, which has functions + * implemented above in the dma configuration function. The + * user can install another firmware using `dma_smartdma_install_fw` + */ + SMARTDMA_Init((uint32_t)config->smartdma_progs, + s_smartdmaDisplayFirmware, + SMARTDMA_DISPLAY_FIRMWARE_SIZE); + config->irq_config_func(dev); + + return 0; +} + +static void dma_mcux_smartdma_irq(const struct device *dev) +{ + const struct dma_mcux_smartdma_data *data = dev->data; + + if (data->callback) { + data->callback(dev, data->user_data, 0, 0); + } +#ifdef CONFIG_PM + /* Release PM lock */ + pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES); +#endif +} + +/** + * @brief install SMARTDMA firmware + * + * Install a custom firmware for the smartDMA. This function allows the user + * to install a custom firmware into the smartDMA, which implements + * different API functions than the standard MCUX SDK firmware. + * @param dev: smartDMA device + * @param firmware: address of buffer containing smartDMA firmware + * @param len: length of firmware buffer + */ +void dma_smartdma_install_fw(const struct device *dev, uint8_t *firmware, + uint32_t len) +{ + const struct dma_mcux_smartdma_config *config = dev->config; + + SMARTDMA_InstallFirmware((uint32_t)config->smartdma_progs, firmware, len); +} + +static const struct dma_driver_api dma_mcux_smartdma_api = { + .config = dma_mcux_smartdma_configure, + .start = dma_mcux_smartdma_start, + .stop = dma_mcux_smartdma_stop, +}; + + +#define SMARTDMA_INIT(n) \ + static void dma_mcux_smartdma_config_func_##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \ + dma_mcux_smartdma_irq, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + } \ + \ + static const struct dma_mcux_smartdma_config smartdma_##n##_config = { \ + .base = (struct smartdma_periph *)DT_INST_REG_ADDR(n), \ + .smartdma_progs = (void (**)(void))DT_INST_PROP(n, program_mem),\ + .irq_config_func = dma_mcux_smartdma_config_func_##n, \ + }; \ + static struct dma_mcux_smartdma_data smartdma_##n##_data; \ + \ + DEVICE_DT_INST_DEFINE(n, \ + &dma_mcux_smartdma_init, \ + NULL, \ + &smartdma_##n##_data, &smartdma_##n##_config, \ + POST_KERNEL, CONFIG_DMA_INIT_PRIORITY, \ + &dma_mcux_smartdma_api); + +DT_INST_FOREACH_STATUS_OKAY(SMARTDMA_INIT) diff --git a/drivers/dma/dma_nxp_sof_host_dma.c b/drivers/dma/dma_nxp_sof_host_dma.c new file mode 100644 index 00000000000..6c03d84418c --- /dev/null +++ b/drivers/dma/dma_nxp_sof_host_dma.c @@ -0,0 +1,284 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +/* used for driver binding */ +#define DT_DRV_COMPAT nxp_sof_host_dma + +/* macros used to parse DTS properties */ +#define IDENTITY_VARGS(V, ...) IDENTITY(V) + +#define _SOF_HOST_DMA_CHANNEL_INDEX_ARRAY(inst)\ + LISTIFY(DT_INST_PROP_OR(inst, dma_channels, 0), IDENTITY_VARGS, (,)) + +#define _SOF_HOST_DMA_CHANNEL_DECLARE(idx) {} + +#define SOF_HOST_DMA_CHANNELS_DECLARE(inst)\ + FOR_EACH(_SOF_HOST_DMA_CHANNEL_DECLARE,\ + (,), _SOF_HOST_DMA_CHANNEL_INDEX_ARRAY(inst)) + +LOG_MODULE_REGISTER(nxp_sof_host_dma); + +/* note: This driver doesn't attempt to provide + * a generic software-based DMA engine implementation. + * As its name suggests, its only usage is in SOF + * (Sound Open Firmware) for NXP plaforms which are + * able to access the host memory directly from the + * core on which the firmware is running. + */ + +enum channel_state { + CHAN_STATE_INIT = 0, + CHAN_STATE_CONFIGURED, +}; + +struct sof_host_dma_channel { + uint32_t src; + uint32_t dest; + uint32_t size; + uint32_t direction; + enum channel_state state; +}; + +struct sof_host_dma_data { + /* this needs to be first */ + struct dma_context ctx; + atomic_t channel_flags; + struct sof_host_dma_channel *channels; +}; + +static int channel_change_state(struct sof_host_dma_channel *chan, + enum channel_state next) +{ + enum channel_state prev = chan->state; + + /* validate transition */ + switch (prev) { + case CHAN_STATE_INIT: + case CHAN_STATE_CONFIGURED: + if (next != CHAN_STATE_CONFIGURED) { + return -EPERM; + } + break; + default: + LOG_ERR("invalid channel previous state: %d", prev); + return -EINVAL; + } + + chan->state = next; + + return 0; +} + +static int sof_host_dma_reload(const struct device *dev, uint32_t chan_id, + uint32_t src, uint32_t dst, size_t size) +{ + ARG_UNUSED(src); + ARG_UNUSED(dst); + ARG_UNUSED(size); + + struct sof_host_dma_data *data; + struct sof_host_dma_channel *chan; + int ret; + + data = dev->data; + + if (chan_id >= data->ctx.dma_channels) { + LOG_ERR("channel %d is not a valid channel ID", chan_id); + return -EINVAL; + } + + /* fetch channel data */ + chan = &data->channels[chan_id]; + + /* validate state */ + if (chan->state != CHAN_STATE_CONFIGURED) { + LOG_ERR("attempting to reload unconfigured DMA channel %d", chan_id); + return -EINVAL; + } + + if (chan->direction == HOST_TO_MEMORY) { + /* the host may have modified the region we're about to copy + * to local memory. In this case, the data cache holds stale + * data so invalidate it to force a read from the main memory. + */ + ret = sys_cache_data_invd_range(UINT_TO_POINTER(chan->src), + chan->size); + if (ret < 0) { + LOG_ERR("failed to invalidate data cache range"); + return ret; + } + } + + memcpy(UINT_TO_POINTER(chan->dest), UINT_TO_POINTER(chan->src), chan->size); + + if (chan->direction == MEMORY_TO_HOST) { + /* force range to main memory so that host doesn't read any + * stale data. + */ + ret = sys_cache_data_flush_range(UINT_TO_POINTER(chan->dest), + chan->size); + if (ret < 0) { + LOG_ERR("failed to flush data cache range"); + return ret; + } + } + + return 0; +} + + +static int sof_host_dma_config(const struct device *dev, uint32_t chan_id, + struct dma_config *config) +{ + struct sof_host_dma_data *data; + struct sof_host_dma_channel *chan; + int ret; + + data = dev->data; + + if (chan_id >= data->ctx.dma_channels) { + LOG_ERR("channel %d is not a valid channel ID", chan_id); + return -EINVAL; + } + + /* fetch channel data */ + chan = &data->channels[chan_id]; + + /* attempt a state transition */ + ret = channel_change_state(chan, CHAN_STATE_CONFIGURED); + if (ret < 0) { + LOG_ERR("failed to change channel %d's state to CONFIGURED", chan_id); + return ret; + } + + /* SG configurations are not currently supported */ + if (config->block_count != 1) { + LOG_ERR("invalid number of blocks: %d", config->block_count); + return -EINVAL; + } + + if (!config->head_block->source_address) { + LOG_ERR("got NULL source address"); + return -EINVAL; + } + + if (!config->head_block->dest_address) { + LOG_ERR("got NULL destination address"); + return -EINVAL; + } + + if (!config->head_block->block_size) { + LOG_ERR("got 0 bytes to copy"); + return -EINVAL; + } + + /* for now, only H2M and M2H transfers are supported */ + if (config->channel_direction != HOST_TO_MEMORY && + config->channel_direction != MEMORY_TO_HOST) { + LOG_ERR("invalid channel direction: %d", + config->channel_direction); + return -EINVAL; + } + + /* latch onto the passed configuration */ + chan->src = config->head_block->source_address; + chan->dest = config->head_block->dest_address; + chan->size = config->head_block->block_size; + chan->direction = config->channel_direction; + + LOG_DBG("configured channel %d with SRC 0x%x DST 0x%x SIZE 0x%x", + chan_id, chan->src, chan->dest, chan->size); + + return 0; +} + +static int sof_host_dma_start(const struct device *dev, uint32_t chan_id) +{ + /* nothing to be done here */ + return 0; +} + +static int sof_host_dma_stop(const struct device *dev, uint32_t chan_id) +{ + /* nothing to be done here */ + return 0; +} + +static int sof_host_dma_suspend(const struct device *dev, uint32_t chan_id) +{ + /* nothing to be done here */ + return 0; +} + +static int sof_host_dma_resume(const struct device *dev, uint32_t chan_id) +{ + /* nothing to be done here */ + return 0; +} + +static int sof_host_dma_get_status(const struct device *dev, + uint32_t chan_id, struct dma_status *stat) +{ + /* nothing to be done here */ + return 0; +} + +static int sof_host_dma_get_attribute(const struct device *dev, uint32_t type, uint32_t *val) +{ + switch (type) { + case DMA_ATTR_COPY_ALIGNMENT: + case DMA_ATTR_BUFFER_SIZE_ALIGNMENT: + case DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT: + *val = CONFIG_DMA_NXP_SOF_HOST_DMA_ALIGN; + break; + default: + LOG_ERR("invalid attribute type: %d", type); + return -EINVAL; + } + + return 0; +} + +static const struct dma_driver_api sof_host_dma_api = { + .reload = sof_host_dma_reload, + .config = sof_host_dma_config, + .start = sof_host_dma_start, + .stop = sof_host_dma_stop, + .suspend = sof_host_dma_suspend, + .resume = sof_host_dma_resume, + .get_status = sof_host_dma_get_status, + .get_attribute = sof_host_dma_get_attribute, +}; + +static int sof_host_dma_init(const struct device *dev) +{ + struct sof_host_dma_data *data = dev->data; + + data->channel_flags = ATOMIC_INIT(0); + data->ctx.atomic = &data->channel_flags; + + return 0; +} + +static struct sof_host_dma_channel channels[] = { + SOF_HOST_DMA_CHANNELS_DECLARE(0), +}; + +static struct sof_host_dma_data sof_host_dma_data = { + .ctx.magic = DMA_MAGIC, + .ctx.dma_channels = ARRAY_SIZE(channels), + .channels = channels, +}; + +/* assumption: only 1 SOF_HOST_DMA instance */ +DEVICE_DT_INST_DEFINE(0, sof_host_dma_init, NULL, + &sof_host_dma_data, NULL, + PRE_KERNEL_1, CONFIG_DMA_INIT_PRIORITY, + &sof_host_dma_api); diff --git a/drivers/dma/dma_sam_xdmac.c b/drivers/dma/dma_sam_xdmac.c index 954fedddff5..7919c5770d1 100644 --- a/drivers/dma/dma_sam_xdmac.c +++ b/drivers/dma/dma_sam_xdmac.c @@ -375,11 +375,36 @@ static int sam_xdmac_initialize(const struct device *dev) return 0; } +static int sam_xdmac_get_status(const struct device *dev, uint32_t channel, + struct dma_status *status) +{ + const struct sam_xdmac_dev_cfg *const dev_cfg = dev->config; + + Xdmac * const xdmac = dev_cfg->regs; + uint32_t chan_cfg = xdmac->XDMAC_CHID[channel].XDMAC_CC; + uint32_t ublen = xdmac->XDMAC_CHID[channel].XDMAC_CUBC; + + /* we need to check some of the XDMAC_CC registers to determine the DMA direction */ + if ((chan_cfg & XDMAC_CC_TYPE_Msk) == 0) { + status->dir = MEMORY_TO_MEMORY; + } else if ((chan_cfg & XDMAC_CC_DSYNC_Msk) == XDMAC_CC_DSYNC_MEM2PER) { + status->dir = MEMORY_TO_PERIPHERAL; + } else { + status->dir = PERIPHERAL_TO_MEMORY; + } + + status->busy = ((chan_cfg & XDMAC_CC_INITD_Msk) != 0) || (ublen > 0); + status->pending_length = ublen; + + return 0; +} + static const struct dma_driver_api sam_xdmac_driver_api = { .config = sam_xdmac_config, .reload = sam_xdmac_transfer_reload, .start = sam_xdmac_transfer_start, .stop = sam_xdmac_transfer_stop, + .get_status = sam_xdmac_get_status, }; /* DMA0 */ diff --git a/drivers/dma/dma_sedi.c b/drivers/dma/dma_sedi.c new file mode 100644 index 00000000000..7c4ffa72e57 --- /dev/null +++ b/drivers/dma/dma_sedi.c @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT intel_sedi_dma + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sedi_driver_dma.h" +#include "sedi_driver_core.h" + +#include +LOG_MODULE_REGISTER(sedi_dma, CONFIG_DMA_LOG_LEVEL); + +extern void dma_isr(sedi_dma_t dma_device); + +struct dma_sedi_config_info { + sedi_dma_t peripheral_id; /* Controller instance. */ + uint8_t chn_num; + void (*irq_config)(void); +}; + +struct dma_sedi_driver_data { + struct dma_config dma_configs[DMA_CHANNEL_NUM]; +}; + +#define DEV_DATA(dev) ((struct dma_sedi_driver_data *const)(dev)->data) +#define DEV_CFG(dev) \ + ((const struct dma_sedi_config_info *const)(dev)->config) + +/* + * this function will be called when dma transferring is completed + * or error happened + */ +static void dma_handler(sedi_dma_t dma_device, int channel, int event_id, + void *args) +{ + ARG_UNUSED(args); + const struct device *dev = (const struct device *)args; + struct dma_sedi_driver_data *const data = DEV_DATA(dev); + struct dma_config *config = &(data->dma_configs[channel]); + + /* run user-defined callback */ + if (config->dma_callback) { + if ((event_id == SEDI_DMA_EVENT_TRANSFER_DONE) && + (config->complete_callback_en)) { + config->dma_callback(dev, config->user_data, + channel, 0); + } else if (config->error_callback_en) { + config->dma_callback(dev, config->user_data, + channel, event_id); + } + } +} + +/* map width to certain macros*/ +static int width_index(uint32_t num_bytes, uint32_t *index) +{ + switch (num_bytes) { + case 1: + *index = DMA_TRANS_WIDTH_8; + break; + case 2: + *index = DMA_TRANS_WIDTH_16; + break; + case 4: + *index = DMA_TRANS_WIDTH_32; + break; + case 8: + *index = DMA_TRANS_WIDTH_64; + break; + case 16: + *index = DMA_TRANS_WIDTH_128; + break; + case 32: + *index = DMA_TRANS_WIDTH_256; + break; + default: + return -ENOTSUP; + } + + return 0; +} + +/* map burst size to certain macros*/ +static int burst_index(uint32_t num_units, uint32_t *index) +{ + switch (num_units) { + case 1: + *index = DMA_BURST_TRANS_LENGTH_1; + break; + case 4: + *index = DMA_BURST_TRANS_LENGTH_4; + break; + case 8: + *index = DMA_BURST_TRANS_LENGTH_8; + break; + case 16: + *index = DMA_BURST_TRANS_LENGTH_16; + break; + case 32: + *index = DMA_BURST_TRANS_LENGTH_32; + break; + case 64: + *index = DMA_BURST_TRANS_LENGTH_64; + break; + case 128: + *index = DMA_BURST_TRANS_LENGTH_128; + break; + case 256: + *index = DMA_BURST_TRANS_LENGTH_256; + break; + default: + return -ENOTSUP; + } + + return 0; +} + +static void dma_config_convert(struct dma_config *config, + dma_memory_type_t *src_mem, + dma_memory_type_t *dst_mem, + uint8_t *sedi_dma_dir) +{ + + *src_mem = DMA_SRAM_MEM; + *dst_mem = DMA_SRAM_MEM; + *sedi_dma_dir = MEMORY_TO_MEMORY; + switch (config->channel_direction) { + case MEMORY_TO_MEMORY: + case MEMORY_TO_PERIPHERAL: + case PERIPHERAL_TO_MEMORY: + case PERIPHERAL_TO_PERIPHERAL: + *sedi_dma_dir = config->channel_direction; + break; + case MEMORY_TO_HOST: + *dst_mem = DMA_DRAM_MEM; + break; + case HOST_TO_MEMORY: + *src_mem = DMA_DRAM_MEM; + break; +#ifdef MEMORY_TO_IMR + case MEMORY_TO_IMR: + *dst_mem = DMA_UMA_MEM; + break; +#endif +#ifdef IMR_TO_MEMORY + case IMR_TO_MEMORY: + *src_mem = DMA_UMA_MEM; + break; +#endif + } +} + +/* config basic dma */ +static int dma_sedi_apply_common_config(sedi_dma_t dev, uint32_t channel, + struct dma_config *config, uint8_t *dir) +{ + uint8_t direction = MEMORY_TO_MEMORY; + dma_memory_type_t src_mem = DMA_SRAM_MEM, dst_mem = DMA_SRAM_MEM; + + dma_config_convert(config, &src_mem, &dst_mem, &direction); + + if (dir) { + *dir = direction; + } + + /* configure dma transferring direction*/ + sedi_dma_control(dev, channel, SEDI_CONFIG_DMA_DIRECTION, + direction); + + if (direction == MEMORY_TO_MEMORY) { + sedi_dma_control(dev, channel, SEDI_CONFIG_DMA_SR_MEM_TYPE, + src_mem); + sedi_dma_control(dev, channel, SEDI_CONFIG_DMA_DT_MEM_TYPE, + dst_mem); + } else if (direction == MEMORY_TO_PERIPHERAL) { + sedi_dma_control(dev, channel, SEDI_CONFIG_DMA_HS_DEVICE_ID, + config->dma_slot); + sedi_dma_control(dev, channel, SEDI_CONFIG_DMA_HS_POLARITY, + DMA_HS_POLARITY_HIGH); + sedi_dma_control(dev, channel, + SEDI_CONFIG_DMA_HS_DEVICE_ID_PER_DIR, + DMA_HS_PER_TX); + } else if (direction == PERIPHERAL_TO_MEMORY) { + sedi_dma_control(dev, channel, SEDI_CONFIG_DMA_HS_DEVICE_ID, + config->dma_slot); + sedi_dma_control(dev, channel, SEDI_CONFIG_DMA_HS_POLARITY, + DMA_HS_POLARITY_HIGH); + sedi_dma_control(dev, channel, + SEDI_CONFIG_DMA_HS_DEVICE_ID_PER_DIR, + DMA_HS_PER_RX); + } else { + return -1; + } + return 0; +} + +static int dma_sedi_apply_single_config(sedi_dma_t dev, uint32_t channel, + struct dma_config *config) +{ + int ret = 0; + uint32_t temp = 0; + + ret = dma_sedi_apply_common_config(dev, channel, config, NULL); + if (ret != 0) { + goto INVALID_ARGS; + } + /* configurate dma width of source data*/ + ret = width_index(config->source_data_size, &temp); + if (ret != 0) { + goto INVALID_ARGS; + } + sedi_dma_control(dev, channel, SEDI_CONFIG_DMA_SR_TRANS_WIDTH, temp); + + /* configurate dma width of destination data*/ + ret = width_index(config->dest_data_size, &temp); + if (ret != 0) { + goto INVALID_ARGS; + } + sedi_dma_control(dev, channel, SEDI_CONFIG_DMA_DT_TRANS_WIDTH, temp); + + /* configurate dma burst size*/ + ret = burst_index(config->source_burst_length, &temp); + if (ret != 0) { + goto INVALID_ARGS; + } + sedi_dma_control(dev, channel, SEDI_CONFIG_DMA_BURST_LENGTH, temp); + return 0; + +INVALID_ARGS: + return ret; +} + +static int dma_sedi_chan_config(const struct device *dev, uint32_t channel, + struct dma_config *config) +{ + if ((dev == NULL) || (channel >= DEV_CFG(dev)->chn_num) + || (config == NULL) + || (config->block_count != 1)) { + goto INVALID_ARGS; + } + + const struct dma_sedi_config_info *const info = DEV_CFG(dev); + struct dma_sedi_driver_data *const data = DEV_DATA(dev); + + memcpy(&(data->dma_configs[channel]), config, sizeof(struct dma_config)); + + /* initialize the dma controller, following the sedi api*/ + sedi_dma_event_cb_t cb = dma_handler; + + sedi_dma_init(info->peripheral_id, (int)channel, cb, (void *)dev); + + return 0; + +INVALID_ARGS: + return -1; +} + +static int dma_sedi_reload(const struct device *dev, uint32_t channel, + uint64_t src, uint64_t dst, size_t size) +{ + if ((dev == NULL) || (channel >= DEV_CFG(dev)->chn_num)) { + LOG_ERR("dma reload failed for invalid args"); + return -ENOTSUP; + } + + int ret = 0; + struct dma_sedi_driver_data *const data = DEV_DATA(dev); + struct dma_config *config = &(data->dma_configs[channel]); + struct dma_block_config *block_config; + + if ((config == NULL) || (config->head_block == NULL)) { + LOG_ERR("dma reload failed, no config found"); + return -ENOTSUP; + } + block_config = config->head_block; + + if ((config->block_count == 1) || (block_config->next_block == NULL)) { + block_config->source_address = src; + block_config->dest_address = dst; + block_config->block_size = size; + } else { + LOG_ERR("no reload support for multi-linkedlist mode"); + return -ENOTSUP; + } + return ret; +} + +static int dma_sedi_start(const struct device *dev, uint32_t channel) +{ + if ((dev == NULL) || (channel >= DEV_CFG(dev)->chn_num)) { + LOG_ERR("dma transferring failed for invalid args"); + return -ENOTSUP; + } + + int ret = -1; + const struct dma_sedi_config_info *const info = DEV_CFG(dev); + struct dma_sedi_driver_data *const data = DEV_DATA(dev); + struct dma_config *config = &(data->dma_configs[channel]); + struct dma_block_config *block_config = config->head_block; + uint64_t src_addr, dst_addr; + + if (config->block_count == 1) { + /* call sedi start function */ + ret = dma_sedi_apply_single_config(info->peripheral_id, + channel, config); + if (ret) { + goto ERR; + } + src_addr = block_config->source_address; + dst_addr = block_config->dest_address; + + ret = sedi_dma_start_transfer(info->peripheral_id, channel, + src_addr, dst_addr, block_config->block_size); + } else { + LOG_ERR("MULTIPLE_BLOCK CONFIG is not set"); + goto ERR; + } + + if (ret != SEDI_DRIVER_OK) { + goto ERR; + } + + return ret; + +ERR: + LOG_ERR("dma transfer failed"); + return ret; +} + +static int dma_sedi_stop(const struct device *dev, uint32_t channel) +{ + const struct dma_sedi_config_info *const info = DEV_CFG(dev); + + LOG_DBG("stopping dma: %p, %d", dev, channel); + sedi_dma_abort_transfer(info->peripheral_id, channel); + + return 0; +} + +static const struct dma_driver_api dma_funcs = { .config = dma_sedi_chan_config, + .start = dma_sedi_start, + .stop = dma_sedi_stop, + .reload = dma_sedi_reload, + .get_status = NULL +}; + +static int dma_sedi_init(const struct device *dev) +{ + const struct dma_sedi_config_info *const config = DEV_CFG(dev); + + config->irq_config(); + + return 0; +} + +#define DMA_DEVICE_INIT_SEDI(inst) \ + static void dma_sedi_##inst##_irq_config(void); \ + \ + static struct dma_sedi_driver_data dma_sedi_dev_data_##inst; \ + static const struct dma_sedi_config_info dma_sedi_config_data_##inst = { \ + .peripheral_id = DT_INST_PROP(inst, peripheral_id), \ + .chn_num = DT_INST_PROP(inst, dma_channels), \ + .irq_config = dma_sedi_##inst##_irq_config \ + }; \ + DEVICE_DT_DEFINE(DT_INST(inst, DT_DRV_COMPAT), &dma_sedi_init, \ + NULL, &dma_sedi_dev_data_##inst, &dma_sedi_config_data_##inst, PRE_KERNEL_2, \ + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, (void *)&dma_funcs); \ + \ + static void dma_sedi_##inst##_irq_config(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(inst), \ + DT_INST_IRQ(inst, priority), dma_isr, \ + (void *)DT_INST_PROP(inst, peripheral_id), \ + DT_INST_IRQ(inst, sense)); \ + irq_enable(DT_INST_IRQN(inst)); \ + } + +DT_INST_FOREACH_STATUS_OKAY(DMA_DEVICE_INIT_SEDI) diff --git a/drivers/dma/dma_smartbond.c b/drivers/dma/dma_smartbond.c new file mode 100644 index 00000000000..79305c77d6a --- /dev/null +++ b/drivers/dma/dma_smartbond.c @@ -0,0 +1,969 @@ +/* + * Copyright (c) 2023 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(dma_smartbond, CONFIG_DMA_LOG_LEVEL); + +#define DT_DRV_COMPAT renesas_smartbond_dma + +#define SMARTBOND_IRQN DT_INST_IRQN(0) +#define SMARTBOND_IRQ_PRIO DT_INST_IRQ(0, priority) + +#define DMA_CHANNELS_COUNT DT_PROP(DT_NODELABEL(dma), dma_channels) +#define DMA_BLOCK_COUNT DT_PROP(DT_NODELABEL(dma), block_count) +#define DMA_SECURE_CHANNEL 7 + +#define DMA_CTRL_REG_SET_FIELD(_field, _var, _val) \ + (_var) = \ + (((_var) & ~DMA_DMA0_CTRL_REG_ ## _field ## _Msk) | \ + (((_val) << DMA_DMA0_CTRL_REG_ ## _field ## _Pos) & DMA_DMA0_CTRL_REG_ ## _field ## _Msk)) + +#define DMA_CTRL_REG_GET_FIELD(_field, _var) \ + (((_var) & DMA_DMA0_CTRL_REG_ ## _field ## _Msk) >> DMA_DMA0_CTRL_REG_ ## _field ## _Pos) + +#define DMA_CHN2REG(_idx) (&((struct channel_regs *)DMA)[(_idx)]) + +#define DMA_MUX_SHIFT(_idx) (((_idx) >> 1) * 4) + +#define DMA_REQ_MUX_REG_SET(_idx, _val) \ + DMA->DMA_REQ_MUX_REG = \ + (DMA->DMA_REQ_MUX_REG & ~(0xf << DMA_MUX_SHIFT((_idx)))) | \ + (((_val) & 0xf) << DMA_MUX_SHIFT((_idx))) + +#define DMA_REQ_MUX_REG_GET(_idx) \ + ((DMA->DMA_REQ_MUX_REG >> DMA_MUX_SHIFT((_idx))) & 0xf) + +#define CRYPTO_KEYS_BUF_ADDR 0x30040100 +#define CRYPTO_KEYS_BUF_SIZE 0x100 +#define IS_AES_KEYS_BUF_RANGE(_a) ((uint32_t)(_a) >= (uint32_t)(CRYPTO_KEYS_BUF_ADDR)) && \ + ((uint32_t)(_a) < (uint32_t)(CRYPTO_KEYS_BUF_ADDR + CRYPTO_KEYS_BUF_SIZE)) + +/* + * DMA channel priority level. The smaller the value the lower the priority granted to a channel + * when two or more channels request the bus at the same time. For channels of same priority an + * inherent mechanism is applied in which the lower the channel number the higher the priority. + */ +enum dma_smartbond_channel_prio { + DMA_SMARTBOND_CHANNEL_PRIO_0 = 0x0, /* Lowest channel priority */ + DMA_SMARTBOND_CHANNEL_PRIO_1, + DMA_SMARTBOND_CHANNEL_PRIO_2, + DMA_SMARTBOND_CHANNEL_PRIO_3, + DMA_SMARTBOND_CHANNEL_PRIO_4, + DMA_SMARTBOND_CHANNEL_PRIO_5, + DMA_SMARTBOND_CHANNEL_PRIO_6, + DMA_SMARTBOND_CHANNEL_PRIO_7, /* Highest channel priority */ + DMA_SMARTBOND_CHANNEL_PRIO_MAX +}; + +enum dma_smartbond_channel { + DMA_SMARTBOND_CHANNEL_0 = 0x0, + DMA_SMARTBOND_CHANNEL_1, + DMA_SMARTBOND_CHANNEL_2, + DMA_SMARTBOND_CHANNEL_3, + DMA_SMARTBOND_CHANNEL_4, + DMA_SMARTBOND_CHANNEL_5, + DMA_SMARTBOND_CHANNEL_6, + DMA_SMARTBOND_CHANNEL_7, + DMA_SMARTBOND_CHANNEL_MAX +}; + +enum dma_smartbond_burst_len { + DMA_SMARTBOND_BURST_LEN_1B = 0x1, /* Burst mode is disabled */ + DMA_SMARTBOND_BURST_LEN_4B = 0x4, /* Perform bursts of 4 beats (INCR4) */ + DMA_SMARTBOND_BURST_LEN_8B = 0x8 /* Perform bursts of 8 beats (INCR8) */ +}; + +/* + * DMA bus width indicating how many bytes are retrived/written per transfer. + * Note that the bus width is the same for the source and destination. + */ +enum dma_smartbond_bus_width { + DMA_SMARTBOND_BUS_WIDTH_1B = 0x1, + DMA_SMARTBOND_BUS_WIDTH_2B = 0x2, + DMA_SMARTBOND_BUS_WIDTH_4B = 0x4 +}; + +enum dreq_mode { + DREQ_MODE_SW = 0x0, + DREQ_MODE_HW +}; + +enum burst_mode { + BURST_MODE_0B = 0x0, + BURST_MODE_4B = 0x1, + BURST_MODE_8B = 0x2 +}; + +enum bus_width { + BUS_WIDTH_1B = 0x0, + BUS_WIDTH_2B = 0x1, + BUS_WIDTH_4B = 0x2 +}; + +enum addr_adj { + ADDR_ADJ_NO_CHANGE = 0x0, + ADDR_ADJ_INCR +}; + +enum copy_mode { + COPY_MODE_BLOCK = 0x0, + COPY_MODE_INIT +}; + +enum req_sense { + REQ_SENSE_LEVEL = 0x0, + REQ_SENSE_EDGE +}; + +struct channel_regs { + __IO uint32_t DMA_A_START; + __IO uint32_t DMA_B_START; + __IO uint32_t DMA_INT_REG; + __IO uint32_t DMA_LEN_REG; + __IO uint32_t DMA_CTRL_REG; + + __I uint32_t DMA_IDX_REG; + __I uint32_t RESERVED[2]; +}; + +struct dma_channel_data { + dma_callback_t cb; + void *user_data; + enum dma_smartbond_bus_width bus_width; + enum dma_smartbond_burst_len burst_len; + enum dma_channel_direction dir; + bool is_dma_configured; +}; + +struct dma_smartbond_data { + /* Should be the first member of the driver data */ + struct dma_context dma_ctx; + + ATOMIC_DEFINE(channels_atomic, DMA_CHANNELS_COUNT); + + /* User callbacks and data to be stored per channel */ + struct dma_channel_data channel_data[DMA_CHANNELS_COUNT]; +}; + +/* True if there is any DMA activity on any channel, false otheriwise. */ +static bool dma_smartbond_is_dma_active(void) +{ + int idx; + struct channel_regs *regs; + + for (idx = 0; idx < DMA_CHANNELS_COUNT; idx++) { + regs = DMA_CHN2REG(idx); + + if (DMA_CTRL_REG_GET_FIELD(DMA_ON, regs->DMA_CTRL_REG)) { + return true; + } + } + + return false; +} + +static void dma_smartbond_set_channel_status(uint32_t channel, bool status) +{ + unsigned int key; + struct channel_regs *regs = DMA_CHN2REG(channel); + + key = irq_lock(); + + if (status) { + /* Make sure the status register for the requested channel is cleared. */ + DMA->DMA_CLEAR_INT_REG |= BIT(channel); + /* Enable interrupts for the requested channel. */ + DMA->DMA_INT_MASK_REG |= BIT(channel); + + /* Check if this is the first attempt to enable DMA interrupts. */ + if (!irq_is_enabled(SMARTBOND_IRQN)) { + irq_enable(SMARTBOND_IRQN); + } + + DMA_CTRL_REG_SET_FIELD(DMA_ON, regs->DMA_CTRL_REG, 0x1); + } else { + DMA_CTRL_REG_SET_FIELD(DMA_ON, regs->DMA_CTRL_REG, 0x0); + + /* + * It might happen that DMA is already in progress. Make sure the current + * on-going transfer is complete (cannot be interrupted). + */ + while (DMA_CTRL_REG_GET_FIELD(DMA_ON, regs->DMA_CTRL_REG)) { + } + + /* Disable interrupts for the requested channel */ + DMA->DMA_INT_MASK_REG &= ~(BIT(channel)); + /* Clear the status register; the requested channel should be considered obsolete */ + DMA->DMA_CLEAR_INT_REG |= BIT(channel); + + /* DMA interrupts should be disabled only if all channels are disabled. */ + if (!dma_smartbond_is_dma_active()) { + irq_disable(SMARTBOND_IRQN); + } + } + + irq_unlock(key); +} + +static bool dma_channel_dst_addr_check_and_adjust(uint32_t channel, uint32_t *dst) +{ + uint32_t phy_address; + uint32_t secure_boot_reg; + bool is_aes_keys_protected, is_qspic_keys_protected; + + phy_address = black_orca_phy_addr(*dst); + + secure_boot_reg = CRG_TOP->SECURE_BOOT_REG; + is_aes_keys_protected = + (secure_boot_reg & CRG_TOP_SECURE_BOOT_REG_PROT_AES_KEY_READ_Msk); + is_qspic_keys_protected = + (secure_boot_reg & CRG_TOP_SECURE_BOOT_REG_PROT_QSPI_KEY_READ_Msk); + + /* + * If the destination address reflects the AES key buffer area and secure keys are protected + * then only the secure channel #7 can be used to transfer data to AES key buffer. + */ + if ((IS_AES_KEYS_BUF_RANGE(phy_address) && + (is_aes_keys_protected || is_qspic_keys_protected) && + (channel != DMA_SECURE_CHANNEL))) { + LOG_ERR("Keys are protected. Only secure channel #7 can be employed."); + return false; + } + + if (IS_QSPIF_ADDRESS(phy_address) || IS_QSPIF_CACHED_ADDRESS(phy_address) || + IS_OTP_ADDRESS(phy_address) || IS_OTP_P_ADDRESS(phy_address)) { + LOG_ERR("Invalid destination location."); + return false; + } + + *dst = phy_address; + + return true; +} + +static bool dma_channel_src_addr_check_and_adjust(uint32_t channel, uint32_t *src) +{ + uint32_t phy_address; + uint32_t secure_boot_reg; + bool is_aes_keys_protected, is_qspic_keys_protected; + + /* DMA can only access physical addresses, not remapped. */ + phy_address = black_orca_phy_addr(*src); + + if (IS_QSPIF_CACHED_ADDRESS(phy_address)) { + /* + * To achiebe max. perfomance, peripherals should not access the Flash memory + * through the instruction cache controller (avoid cache misses). + */ + phy_address += (MCU_QSPIF_M_BASE - MCU_QSPIF_M_CACHED_BASE); + } else if (IS_OTP_ADDRESS(phy_address)) { + /* Peripherals should access OTP through its peripheral address space. */ + phy_address += (MCU_OTP_M_P_BASE - MCU_OTP_M_BASE); + } + + secure_boot_reg = CRG_TOP->SECURE_BOOT_REG; + is_aes_keys_protected = + (secure_boot_reg & CRG_TOP_SECURE_BOOT_REG_PROT_AES_KEY_READ_Msk); + is_qspic_keys_protected = + (secure_boot_reg & CRG_TOP_SECURE_BOOT_REG_PROT_QSPI_KEY_READ_Msk); + + /* + * If the source address reflects protected area in OTP then only the + * secure channel #7 can be used to fetch secure keys data. + */ + if (((IS_ADDRESS_USER_DATA_KEYS_SEGMENT(phy_address) && is_aes_keys_protected) || + (IS_ADDRESS_QSPI_FW_KEYS_SEGMENT(phy_address) && is_qspic_keys_protected)) && + (channel != DMA_SECURE_CHANNEL)) { + LOG_ERR("Keys are protected. Only secure channel #7 can be employed."); + return false; + } + + *src = phy_address; + + return true; +} + +static bool dma_channel_update_dreq_mode(enum dma_channel_direction direction, + uint32_t *dma_ctrl_reg) +{ + switch (direction) { + case MEMORY_TO_HOST: + case HOST_TO_MEMORY: + case MEMORY_TO_MEMORY: + /* DMA channel starts immediately */ + DMA_CTRL_REG_SET_FIELD(DREQ_MODE, *dma_ctrl_reg, DREQ_MODE_SW); + break; + case PERIPHERAL_TO_MEMORY: + case PERIPHERAL_TO_PERIPHERAL: + /* DMA channels starts by peripheral DMA req */ + DMA_CTRL_REG_SET_FIELD(DREQ_MODE, *dma_ctrl_reg, DREQ_MODE_HW); + break; + default: + return false; + }; + + return true; +} + +static bool dma_channel_update_src_addr_adj(enum dma_addr_adj addr_adj, uint32_t *dma_ctrl_reg) +{ + switch (addr_adj) { + case DMA_ADDR_ADJ_NO_CHANGE: + DMA_CTRL_REG_SET_FIELD(AINC, *dma_ctrl_reg, ADDR_ADJ_NO_CHANGE); + break; + case DMA_ADDR_ADJ_INCREMENT: + DMA_CTRL_REG_SET_FIELD(AINC, *dma_ctrl_reg, ADDR_ADJ_INCR); + break; + default: + return false; + } + + return true; +} + +static bool dma_channel_update_dst_addr_adj(enum dma_addr_adj addr_adj, uint32_t *dma_ctrl_reg) +{ + switch (addr_adj) { + case DMA_ADDR_ADJ_NO_CHANGE: + DMA_CTRL_REG_SET_FIELD(BINC, *dma_ctrl_reg, ADDR_ADJ_NO_CHANGE); + break; + case DMA_ADDR_ADJ_INCREMENT: + DMA_CTRL_REG_SET_FIELD(BINC, *dma_ctrl_reg, ADDR_ADJ_INCR); + break; + default: + return false; + } + + return true; +} + +static bool dma_channel_update_bus_width(uint16_t bw, uint32_t *dma_ctrl_reg) +{ + switch (bw) { + case DMA_SMARTBOND_BUS_WIDTH_1B: + DMA_CTRL_REG_SET_FIELD(BW, *dma_ctrl_reg, BUS_WIDTH_1B); + break; + case DMA_SMARTBOND_BUS_WIDTH_2B: + DMA_CTRL_REG_SET_FIELD(BW, *dma_ctrl_reg, BUS_WIDTH_2B); + break; + case DMA_SMARTBOND_BUS_WIDTH_4B: + DMA_CTRL_REG_SET_FIELD(BW, *dma_ctrl_reg, BUS_WIDTH_4B); + break; + default: + return false; + } + + return true; +} + +static bool dma_channel_update_burst_mode(uint16_t burst, uint32_t *dma_ctrl_reg) +{ + switch (burst) { + case DMA_SMARTBOND_BURST_LEN_1B: + DMA_CTRL_REG_SET_FIELD(BURST_MODE, *dma_ctrl_reg, BURST_MODE_0B); + break; + case DMA_SMARTBOND_BURST_LEN_4B: + DMA_CTRL_REG_SET_FIELD(BURST_MODE, *dma_ctrl_reg, BURST_MODE_4B); + break; + case DMA_SMARTBOND_BURST_LEN_8B: + DMA_CTRL_REG_SET_FIELD(BURST_MODE, *dma_ctrl_reg, BURST_MODE_8B); + break; + default: + return false; + } + + return true; +} + +static void dma_channel_update_req_sense(enum dma_smartbond_trig_mux trig_mux, + uint32_t channel, uint32_t *dma_ctrl_reg) +{ + switch (trig_mux) { + case DMA_SMARTBOND_TRIG_MUX_UART: + case DMA_SMARTBOND_TRIG_MUX_UART2: + case DMA_SMARTBOND_TRIG_MUX_UART3: + case DMA_SMARTBOND_TRIG_MUX_I2C: + case DMA_SMARTBOND_TRIG_MUX_I2C2: + case DMA_SMARTBOND_TRIG_MUX_USB: + /* Odd channel numbers should reflect TX path */ + if (channel & BIT(0)) { + DMA_CTRL_REG_SET_FIELD(REQ_SENSE, *dma_ctrl_reg, REQ_SENSE_EDGE); + break; + } + default: + DMA_CTRL_REG_SET_FIELD(REQ_SENSE, *dma_ctrl_reg, REQ_SENSE_LEVEL); + } +} + +static void dma_set_mux_request(enum dma_smartbond_trig_mux trig_mux, uint32_t channel) +{ + unsigned int key; + + key = irq_lock(); + DMA_REQ_MUX_REG_SET(channel, trig_mux); + + /* + * Having same trigger for different channels can cause unpredictable results. + * The audio triggers (src and pcm) are an exception, as they use 2 pairs each + * for DMA access. + * The lesser significant selector has higher priority and will control + * the DMA acknowledge signal driven to the selected peripheral. Make sure + * the current selector does not match with selectors of + * higher priorities (dma channels of lower indexing). It's OK if a + * channel of higher indexing defines the same peripheral request source + * (should be ignored as it has lower priority). + */ + if (trig_mux != DMA_SMARTBOND_TRIG_MUX_NONE) { + switch (channel) { + case DMA_SMARTBOND_CHANNEL_7: + case DMA_SMARTBOND_CHANNEL_6: + if (DMA_REQ_MUX_REG_GET(DMA_SMARTBOND_CHANNEL_5) == trig_mux) { + DMA_REQ_MUX_REG_SET(DMA_SMARTBOND_CHANNEL_5, + DMA_SMARTBOND_TRIG_MUX_NONE); + } + /* fall-through */ + case DMA_SMARTBOND_CHANNEL_5: + case DMA_SMARTBOND_CHANNEL_4: + if (DMA_REQ_MUX_REG_GET(DMA_SMARTBOND_CHANNEL_3) == trig_mux) { + DMA_REQ_MUX_REG_SET(DMA_SMARTBOND_CHANNEL_3, + DMA_SMARTBOND_TRIG_MUX_NONE); + } + /* fall-through */ + case DMA_SMARTBOND_CHANNEL_3: + case DMA_SMARTBOND_CHANNEL_2: + if (DMA_REQ_MUX_REG_GET(DMA_SMARTBOND_CHANNEL_1) == trig_mux) { + DMA_REQ_MUX_REG_SET(DMA_SMARTBOND_CHANNEL_1, + DMA_SMARTBOND_TRIG_MUX_NONE); + } + case DMA_SMARTBOND_CHANNEL_1: + case DMA_SMARTBOND_CHANNEL_0: + break; + } + } + + irq_unlock(key); +} + +static int dma_smartbond_config(const struct device *dev, uint32_t channel, struct dma_config *cfg) +{ + struct dma_smartbond_data *data = dev->data; + struct channel_regs *regs; + uint32_t dma_ctrl_reg; + uint32_t src_dst_address; + + if (channel >= DMA_CHANNELS_COUNT) { + LOG_ERR("Inavlid DMA channel index"); + return -EINVAL; + } + regs = DMA_CHN2REG(channel); + + dma_ctrl_reg = regs->DMA_CTRL_REG; + + if (DMA_CTRL_REG_GET_FIELD(DMA_ON, dma_ctrl_reg)) { + LOG_ERR("Requested channel is enabled. It should first be disabled"); + return -EIO; + } + + if (cfg == NULL || cfg->head_block == NULL) { + LOG_ERR("Missing configuration structure"); + return -EINVAL; + } + + /* Error handling is not supported; just warn user. */ + if (cfg->error_callback_en) { + LOG_WRN("Error handling is not supported"); + } + + if (!cfg->complete_callback_en) { + data->channel_data[channel].cb = cfg->dma_callback; + data->channel_data[channel].user_data = cfg->user_data; + } else { + LOG_WRN("User callback can only be called at completion only and not per block."); + + /* Nulify pointers to indicate notifications are disabled. */ + data->channel_data[channel].cb = NULL; + data->channel_data[channel].user_data = NULL; + } + + data->channel_data[channel].dir = cfg->channel_direction; + + if (cfg->block_count > DMA_BLOCK_COUNT) { + LOG_WRN("A single block is supported. The rest blocks will be discarded"); + } + + if (cfg->channel_priority >= DMA_SMARTBOND_CHANNEL_PRIO_MAX) { + cfg->channel_priority = DMA_SMARTBOND_CHANNEL_PRIO_7; + LOG_WRN("Channel priority exceeded max. Setting to highest valid level"); + } + + DMA_CTRL_REG_SET_FIELD(DMA_PRIO, dma_ctrl_reg, cfg->channel_priority); + + if (((cfg->source_burst_length != cfg->dest_burst_length) || + !dma_channel_update_burst_mode(cfg->source_burst_length, &dma_ctrl_reg))) { + LOG_ERR("Invalid burst mode or source and destination mode mismatch"); + return -EINVAL; + } + + data->channel_data[channel].burst_len = cfg->source_burst_length; + + if (cfg->source_data_size != cfg->dest_data_size || + !dma_channel_update_bus_width(cfg->source_data_size, &dma_ctrl_reg)) { + LOG_ERR("Invalid bus width or source and destination bus width mismatch"); + return -EINVAL; + } + + data->channel_data[channel].bus_width = cfg->source_data_size; + + if (cfg->source_chaining_en || cfg->dest_chaining_en || + cfg->head_block->source_gather_en || cfg->head_block->dest_scatter_en || + cfg->head_block->source_reload_en || cfg->head_block->dest_reload_en) { + LOG_WRN("Chainning, scattering, gathering or reloading is not supported"); + } + + if (!dma_channel_update_src_addr_adj(cfg->head_block->source_addr_adj, + &dma_ctrl_reg)) { + LOG_ERR("Invalid source address adjustment"); + return -EINVAL; + } + + if (!dma_channel_update_dst_addr_adj(cfg->head_block->dest_addr_adj, &dma_ctrl_reg)) { + LOG_ERR("Invalid destination address adjustment"); + return -EINVAL; + } + + if (!dma_channel_update_dreq_mode(cfg->channel_direction, &dma_ctrl_reg)) { + LOG_ERR("Inavlid channel direction"); + return -EINVAL; + } + + /* Cyclic is valid only when DREQ_MODE is set */ + if (cfg->cyclic && DMA_CTRL_REG_GET_FIELD(DREQ_MODE, dma_ctrl_reg) != DREQ_MODE_HW) { + LOG_ERR("Circular mode is only supported for non memory-memory transfers"); + return -EINVAL; + } + + DMA_CTRL_REG_SET_FIELD(CIRCULAR, dma_ctrl_reg, cfg->cyclic); + + if (DMA_CTRL_REG_GET_FIELD(DREQ_MODE, dma_ctrl_reg) == DREQ_MODE_SW && + DMA_CTRL_REG_GET_FIELD(AINC, dma_ctrl_reg) == ADDR_ADJ_NO_CHANGE && + DMA_CTRL_REG_GET_FIELD(BINC, dma_ctrl_reg) == ADDR_ADJ_INCR) { + /* + * Valid for memory initialization to a specific value. This process + * cannot be interrupted by other DMA channels. + */ + DMA_CTRL_REG_SET_FIELD(DMA_INIT, dma_ctrl_reg, COPY_MODE_INIT); + } else { + DMA_CTRL_REG_SET_FIELD(DMA_INIT, dma_ctrl_reg, COPY_MODE_BLOCK); + } + + dma_channel_update_req_sense(cfg->dma_slot, channel, &dma_ctrl_reg); + + regs->DMA_CTRL_REG = dma_ctrl_reg; + + /* Requested address might be changed */ + src_dst_address = cfg->head_block->source_address; + if (!dma_channel_src_addr_check_and_adjust(channel, &src_dst_address)) { + return -EINVAL; + } + + if (src_dst_address % cfg->source_data_size) { + LOG_ERR("Source address is not bus width aligned"); + return -EINVAL; + } + + regs->DMA_A_START = src_dst_address; + + src_dst_address = cfg->head_block->dest_address; + if (!dma_channel_dst_addr_check_and_adjust(channel, &src_dst_address)) { + return -EINVAL; + } + + if (src_dst_address % cfg->dest_data_size) { + LOG_ERR("Destination address is not bus width aligned"); + return -EINVAL; + } + + regs->DMA_B_START = src_dst_address; + + if (cfg->head_block->block_size % (cfg->source_data_size * cfg->source_burst_length)) { + LOG_ERR("Requested data size is not multiple of bus width"); + return -EINVAL; + } + + regs->DMA_LEN_REG = (cfg->head_block->block_size / cfg->source_data_size) - 1; + + /* Interrupt will be raised once all transfers are complete. */ + regs->DMA_INT_REG = (cfg->head_block->block_size / cfg->source_data_size) - 1; + + if ((cfg->source_handshake != cfg->dest_handshake) || + (cfg->source_handshake != 0)/*HW*/) { + LOG_ERR("Source/destination handshakes mismatch or invalid"); + return -EINVAL; + } + + dma_set_mux_request(cfg->dma_slot, channel); + + /* Designate that channel has been configured */ + data->channel_data[channel].is_dma_configured = true; + + return 0; +} + + +static int dma_smartbond_reload(const struct device *dev, uint32_t channel, uint32_t src, + uint32_t dst, size_t size) +{ + struct dma_smartbond_data *data = dev->data; + struct channel_regs *regs; + + if (channel >= DMA_CHANNELS_COUNT) { + LOG_ERR("Inavlid DMA channel index"); + return -EINVAL; + } + regs = DMA_CHN2REG(channel); + + if (!data->channel_data[channel].is_dma_configured) { + LOG_ERR("Requested DMA channel should first be configured"); + return -EINVAL; + } + + if (size == 0) { + LOG_ERR("Min. transfer size is one"); + return -EINVAL; + } + + if (DMA_CTRL_REG_GET_FIELD(DMA_ON, regs->DMA_CTRL_REG)) { + LOG_ERR("Channel is busy, settings cannot be changed mid-transfer"); + return -EBUSY; + } + + if (src % data->channel_data[channel].bus_width) { + LOG_ERR("Source address is not bus width aligned"); + return -EINVAL; + } + + if (!dma_channel_src_addr_check_and_adjust(channel, &src)) { + return -EINVAL; + } + + regs->DMA_A_START = src; + + if (dst % data->channel_data[channel].bus_width) { + LOG_ERR("Destination address is not bus width aligned"); + return -EINVAL; + } + + if (!dma_channel_dst_addr_check_and_adjust(channel, &dst)) { + return -EINVAL; + } + + regs->DMA_B_START = dst; + + if (size % (data->channel_data[channel].burst_len * + data->channel_data[channel].bus_width)) { + LOG_ERR("Requested data size is not multiple of bus width"); + return -EINVAL; + } + + regs->DMA_LEN_REG = (size / data->channel_data[channel].bus_width) - 1; + + /* Interrupt will be raised once all transfers are complete. */ + regs->DMA_INT_REG = (size / data->channel_data[channel].bus_width) - 1; + + return 0; +} + +static int dma_smartbond_start(const struct device *dev, uint32_t channel) +{ + struct channel_regs *regs; + struct dma_smartbond_data *data = dev->data; + + if (channel >= DMA_CHANNELS_COUNT) { + LOG_ERR("Inavlid DMA channel index"); + return -EINVAL; + } + regs = DMA_CHN2REG(channel); + + if (!data->channel_data[channel].is_dma_configured) { + LOG_ERR("Requested DMA channel should first be configured"); + return -EINVAL; + } + + /* Should return succss if the requested channel is already started. */ + if (DMA_CTRL_REG_GET_FIELD(DMA_ON, regs->DMA_CTRL_REG)) { + return 0; + } + + dma_smartbond_set_channel_status(channel, true); + + return 0; +} + +static int dma_smartbond_stop(const struct device *dev, uint32_t channel) +{ + struct channel_regs *regs; + + if (channel >= DMA_CHANNELS_COUNT) { + LOG_ERR("Inavlid DMA channel index"); + return -EINVAL; + } + regs = DMA_CHN2REG(channel); + + /* + * In normal mode DMA_ON is cleared automatically. However we need to clear + * the corresponding register mask and disable NVIC if there is no other + * channel in use. + */ + dma_smartbond_set_channel_status(channel, false); + + return 0; +} + +static int dma_smartbond_suspend(const struct device *dev, uint32_t channel) +{ + if (channel >= DMA_CHANNELS_COUNT) { + LOG_ERR("Inavlid DMA channel index"); + return -EINVAL; + } + + /* + * Freezing the DMA engine is valid for memory-to-memory operations. + * Valid memory locations are SYSRAM and/or PSRAM. + */ + LOG_WRN("DMA is freezed globally"); + + /* + * Freezing the DMA engine can be done universally and not per channel!. + * An attempt to disable the channel would result in resetting the IDX + * register next time the channel was re-enabled. + */ + GPREG->SET_FREEZE_REG = GPREG_SET_FREEZE_REG_FRZ_DMA_Msk; + + return 0; +} + +static int dma_smartbond_resume(const struct device *dev, uint32_t channel) +{ + if (channel >= DMA_CHANNELS_COUNT) { + LOG_ERR("Inavlid DMA channel index"); + return -EINVAL; + } + + LOG_WRN("DMA is unfreezed globally"); + + /* Unfreezing the DMA engine can be done unviversally and not per channel! */ + GPREG->RESET_FREEZE_REG = GPREG_RESET_FREEZE_REG_FRZ_DMA_Msk; + + return 0; +} + +static int dma_smartbond_get_status(const struct device *dev, uint32_t channel, + struct dma_status *stat) +{ + struct channel_regs *regs; + int key; + struct dma_smartbond_data *data = dev->data; + uint8_t bus_width; + uint32_t dma_ctrl_reg, dma_idx_reg, dma_len_reg; + + if (channel >= DMA_CHANNELS_COUNT) { + LOG_ERR("Inavlid DMA channel index"); + return -EINVAL; + } + + if (stat == NULL) { + LOG_ERR("User should provide a valid pointer to store the status info requested"); + } + + if (!data->channel_data[channel].is_dma_configured) { + LOG_ERR("Requested DMA channel should first be configured"); + return -EINVAL; + } + + regs = DMA_CHN2REG(channel); + + /* + * The DMA is running in parallel with CPU and so it might happen that an on-going transfer + * might be completed the moment user parses the status results. Disable interrupts globally + * so there is no chance for a new transfer to be initiated from within ISR and so changing + * the channel registers values. + */ + key = irq_lock(); + + dma_ctrl_reg = regs->DMA_CTRL_REG; + dma_idx_reg = regs->DMA_IDX_REG; + dma_len_reg = regs->DMA_LEN_REG; + + /* Calculate how many byes each transfer consists of. */ + bus_width = DMA_CTRL_REG_GET_FIELD(BW, dma_ctrl_reg); + if (bus_width == BUS_WIDTH_1B) { + bus_width = 1; + } else { + bus_width <<= 1; + } + + /* Convert transfers to bytes. */ + stat->total_copied = dma_idx_reg * bus_width; + stat->pending_length = ((dma_len_reg + 1) - dma_idx_reg) * bus_width; + stat->busy = DMA_CTRL_REG_GET_FIELD(DMA_ON, dma_ctrl_reg); + stat->dir = data->channel_data[channel].dir; + + /* DMA does not support circular buffer functionality */ + stat->free = 0; + stat->read_position = 0; + stat->write_position = 0; + + irq_unlock(key); + + return 0; +} + +static int dma_smartbond_get_attribute(const struct device *dev, uint32_t type, uint32_t *value) +{ + if (value == NULL) { + LOG_ERR("User should provide a valid pointer to attribute value"); + return -EINVAL; + } + + switch (type) { + /* + * Source and destination addresses should be multiple of a channel's bus width. + * This info could be provided at runtime given that attributes of a specific + * channel could be requested. + */ + case DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT: + case DMA_ATTR_COPY_ALIGNMENT: + /* + * Buffer size should be multiple of a channel's bus width multiplied by burst length. + * This info could be provided at runtime given that attributes of a specific channel + * could be requested. + */ + case DMA_ATTR_BUFFER_SIZE_ALIGNMENT: + return -ENOSYS; + case DMA_ATTR_MAX_BLOCK_COUNT: + *value = DMA_BLOCK_COUNT; + return 0; + default: + return -EINVAL; + } +} + +static bool dma_smartbond_chan_filter(const struct device *dev, int channel, void *filter_param) +{ + uint32_t requested_channel; + + if (channel >= DMA_CHANNELS_COUNT) { + LOG_ERR("Inavlid DMA channel index"); + return -EINVAL; + } + + /* If user does not provide any channel request explicitly, return true. */ + if (filter_param == NULL) { + return true; + } + + requested_channel = *(uint32_t *)filter_param; + + if (channel == requested_channel) { + return true; + } + + return false; +} + +static struct dma_driver_api dma_smartbond_driver_api = { + .config = dma_smartbond_config, + .reload = dma_smartbond_reload, + .start = dma_smartbond_start, + .stop = dma_smartbond_stop, + .suspend = dma_smartbond_suspend, + .resume = dma_smartbond_resume, + .get_status = dma_smartbond_get_status, + .get_attribute = dma_smartbond_get_attribute, + .chan_filter = dma_smartbond_chan_filter +}; + +static void smartbond_dma_isr(const void *arg) +{ + uint16_t dma_int_status_reg; + int i; + struct channel_regs *regs; + struct dma_smartbond_data *data = ((const struct device *)arg)->data; + + /* + * A single interrupt line is generated for all channels and so each channel + * should be parsed separately. + */ + for (i = 0, dma_int_status_reg = DMA->DMA_INT_STATUS_REG; + i < DMA_CHANNELS_COUNT && dma_int_status_reg != 0; ++i, dma_int_status_reg >>= 1) { + /* Check if the selected channel has raised the interrupt line */ + if (dma_int_status_reg & BIT(0)) { + + regs = DMA_CHN2REG(i); + /* + * Should be valid if callbacks are explicitly enabled by users. + * Interrupt should be triggered only when the total size of + * bytes has been transferred. Bus errors cannot raise interrupts. + */ + if (data->channel_data[i].cb) { + data->channel_data[i].cb((const struct device *)arg, + data->channel_data[i].user_data, i, DMA_STATUS_COMPLETE); + } + /* Channel line should be cleared otherwise ISR will keep firing! */ + DMA->DMA_CLEAR_INT_REG = BIT(i); + } + } +} + +static int dma_smartbond_init(const struct device *dev) +{ +#ifdef CONFIG_DMA_64BIT + LOG_ERR("64-bit addressing mode is not supported\n"); + return -ENOSYS; +#endif + + int idx; + struct dma_smartbond_data *data; + + data = dev->data; + data->dma_ctx.magic = DMA_MAGIC; + data->dma_ctx.dma_channels = DMA_CHANNELS_COUNT; + data->dma_ctx.atomic = data->channels_atomic; + + /* Make sure that all channels are disabled. */ + for (idx = 0; idx < DMA_CHANNELS_COUNT; idx++) { + dma_smartbond_set_channel_status(idx, false); + data->channel_data[idx].is_dma_configured = false; + } + + IRQ_CONNECT(SMARTBOND_IRQN, SMARTBOND_IRQ_PRIO, smartbond_dma_isr, + DEVICE_DT_INST_GET(0), 0); + + return 0; +} + +#define SMARTBOND_DMA_INIT(inst) \ + BUILD_ASSERT((inst) == 0, "multiple instances are not supported"); \ + \ + static struct dma_smartbond_data dma_smartbond_data_ ## inst; \ + \ + DEVICE_DT_INST_DEFINE(0, dma_smartbond_init, NULL, \ + &dma_smartbond_data_ ## inst, NULL, \ + POST_KERNEL, \ + CONFIG_DMA_INIT_PRIORITY, \ + &dma_smartbond_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(SMARTBOND_DMA_INIT) diff --git a/drivers/dma/dma_stm32_bdma.c b/drivers/dma/dma_stm32_bdma.c index 797ed9ed794..1df5746facb 100644 --- a/drivers/dma/dma_stm32_bdma.c +++ b/drivers/dma/dma_stm32_bdma.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -813,7 +814,7 @@ static int bdma_stm32_init(const struct device *dev) * }; */ #if DT_NODE_HAS_PROP(DT_NODELABEL(sram4), zephyr_memory_attr) - if (strcmp(DT_PROP(DT_NODELABEL(sram4), zephyr_memory_attr), "RAM_NOCACHE") != 0) { + if ((DT_PROP(DT_NODELABEL(sram4), zephyr_memory_attr) & DT_MEM_ARM_MPU_RAM_NOCACHE) == 0) { LOG_ERR("SRAM4 is not set as non-cachable."); return -EIO; } diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 45e499a749a..e5029ce470f 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -19,7 +19,6 @@ config EDAC_ERROR_INJECT config EDAC_SHELL bool "EDAC Shell" depends on SHELL - default y if SHELL help Enable EDAC shell for debugging EDAC. diff --git a/drivers/eeprom/Kconfig b/drivers/eeprom/Kconfig index 745d274ff1e..29405f4ed65 100644 --- a/drivers/eeprom/Kconfig +++ b/drivers/eeprom/Kconfig @@ -24,7 +24,6 @@ config EEPROM_INIT_PRIORITY config EEPROM_SHELL bool "EEPROM shell" - default y depends on SHELL help Enable the EEPROM shell with EEPROM related commands. diff --git a/drivers/eeprom/eeprom_at2x_emul.c b/drivers/eeprom/eeprom_at2x_emul.c index 25d079dfa6d..91033c02b4a 100644 --- a/drivers/eeprom/eeprom_at2x_emul.c +++ b/drivers/eeprom/eeprom_at2x_emul.c @@ -81,7 +81,7 @@ static int at24_emul_transfer(const struct emul *target, struct i2c_msg *msgs, return -EIO; } - i2c_dump_msgs_rw("emul", msgs, num_msgs, addr, false); + i2c_dump_msgs_rw(target->dev, msgs, num_msgs, addr, false); switch (num_msgs) { case 1: if (msgs->flags & I2C_MSG_READ) { diff --git a/drivers/eeprom/eeprom_emulator.c b/drivers/eeprom/eeprom_emulator.c index 822c9a7e2cf..0672e83f839 100644 --- a/drivers/eeprom/eeprom_emulator.c +++ b/drivers/eeprom/eeprom_emulator.c @@ -642,7 +642,7 @@ static int eeprom_emu_init(const struct device *dev) struct eeprom_emu_data *dev_data = dev->data; off_t offset; uint8_t buf[dev_config->flash_cbs]; - int rc; + int rc = 0; k_mutex_init(&dev_data->lock); if (!device_is_ready(dev_config->flash_dev)) { diff --git a/drivers/eeprom/eeprom_fake.c b/drivers/eeprom/eeprom_fake.c index c7ed9ff5cd4..f925671fba8 100644 --- a/drivers/eeprom/eeprom_fake.c +++ b/drivers/eeprom/eeprom_fake.c @@ -9,9 +9,9 @@ #include #include -#ifdef CONFIG_ZTEST_NEW_API +#ifdef CONFIG_ZTEST #include -#endif /* CONFIG_ZTEST_NEW_API */ +#endif /* CONFIG_ZTEST */ #define DT_DRV_COMPAT zephyr_fake_eeprom @@ -32,7 +32,7 @@ size_t fake_eeprom_size_delegate(const struct device *dev) return config->size; } -#ifdef CONFIG_ZTEST_NEW_API +#ifdef CONFIG_ZTEST static void fake_eeprom_reset_rule_before(const struct ztest_unit_test *test, void *fixture) { ARG_UNUSED(test); @@ -47,7 +47,7 @@ static void fake_eeprom_reset_rule_before(const struct ztest_unit_test *test, vo } ZTEST_RULE(fake_eeprom_reset_rule, fake_eeprom_reset_rule_before, NULL); -#endif /* CONFIG_ZTEST_NEW_API */ +#endif /* CONFIG_ZTEST */ static const struct eeprom_driver_api fake_eeprom_driver_api = { .read = fake_eeprom_read, diff --git a/drivers/eeprom/eeprom_handlers.c b/drivers/eeprom/eeprom_handlers.c index 79e00d3a6fd..9b1406a6004 100644 --- a/drivers/eeprom/eeprom_handlers.c +++ b/drivers/eeprom/eeprom_handlers.c @@ -4,14 +4,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include static inline int z_vrfy_eeprom_read(const struct device *dev, off_t offset, void *data, size_t len) { - Z_OOPS(Z_SYSCALL_DRIVER_EEPROM(dev, read)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(data, len)); + K_OOPS(K_SYSCALL_DRIVER_EEPROM(dev, read)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(data, len)); return z_impl_eeprom_read((const struct device *)dev, offset, (void *)data, len); @@ -21,8 +21,8 @@ static inline int z_vrfy_eeprom_read(const struct device *dev, off_t offset, static inline int z_vrfy_eeprom_write(const struct device *dev, off_t offset, const void *data, size_t len) { - Z_OOPS(Z_SYSCALL_DRIVER_EEPROM(dev, write)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(data, len)); + K_OOPS(K_SYSCALL_DRIVER_EEPROM(dev, write)); + K_OOPS(K_SYSCALL_MEMORY_READ(data, len)); return z_impl_eeprom_write((const struct device *)dev, offset, (const void *)data, len); } @@ -30,7 +30,7 @@ static inline int z_vrfy_eeprom_write(const struct device *dev, off_t offset, static inline size_t z_vrfy_eeprom_get_size(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_EEPROM(dev, size)); + K_OOPS(K_SYSCALL_DRIVER_EEPROM(dev, size)); return z_impl_eeprom_get_size((const struct device *)dev); } #include diff --git a/drivers/entropy/Kconfig.psa_crypto b/drivers/entropy/Kconfig.psa_crypto index 455a2c9b55b..18514a071d1 100644 --- a/drivers/entropy/Kconfig.psa_crypto +++ b/drivers/entropy/Kconfig.psa_crypto @@ -5,7 +5,6 @@ config ENTROPY_PSA_CRYPTO_RNG bool "PSA Crypto Random source Entropy driver" - depends on BUILD_WITH_TFM depends on DT_HAS_ZEPHYR_PSA_CRYPTO_RNG_ENABLED select ENTROPY_HAS_DRIVER select PSA_WANT_GENERATE_RANDOM diff --git a/drivers/entropy/entropy_b91_trng.c b/drivers/entropy/entropy_b91_trng.c index 7d719e01a2d..914b70003b3 100644 --- a/drivers/entropy/entropy_b91_trng.c +++ b/drivers/entropy/entropy_b91_trng.c @@ -55,7 +55,7 @@ static int entropy_b91_trng_get_entropy_isr(const struct device *dev, /* No specific handling in case of running from ISR, just call standard API */ entropy_b91_trng_get_entropy(dev, buffer, length); - return 0; + return length; } /* Entropy driver APIs structure */ diff --git a/drivers/entropy/entropy_gecko_se.c b/drivers/entropy/entropy_gecko_se.c index 2efe1e2307c..133df43e0a3 100644 --- a/drivers/entropy/entropy_gecko_se.c +++ b/drivers/entropy/entropy_gecko_se.c @@ -40,13 +40,6 @@ static int entropy_gecko_se_get_entropy(const struct device *dev, return err; } -static int entropy_gecko_se_get_entropy_isr(const struct device *dev, - uint8_t *buf, - uint16_t len, uint32_t flags) -{ - return -ENOTSUP; -} - static int entropy_gecko_se_init(const struct device *dev) { if (sl_se_init()) { @@ -58,7 +51,6 @@ static int entropy_gecko_se_init(const struct device *dev) static const struct entropy_driver_api entropy_gecko_se_api_funcs = { .get_entropy = entropy_gecko_se_get_entropy, - .get_entropy_isr = entropy_gecko_se_get_entropy_isr }; #define GECKO_SE_INIT(n) \ diff --git a/drivers/entropy/entropy_handlers.c b/drivers/entropy/entropy_handlers.c index 7eb4dcba0c4..76b7df3d0bd 100644 --- a/drivers/entropy/entropy_handlers.c +++ b/drivers/entropy/entropy_handlers.c @@ -5,14 +5,14 @@ */ #include -#include +#include static inline int z_vrfy_entropy_get_entropy(const struct device *dev, uint8_t *buffer, uint16_t len) { - Z_OOPS(Z_SYSCALL_DRIVER_ENTROPY(dev, get_entropy)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(buffer, len)); + K_OOPS(K_SYSCALL_DRIVER_ENTROPY(dev, get_entropy)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(buffer, len)); return z_impl_entropy_get_entropy((const struct device *)dev, (uint8_t *)buffer, len); diff --git a/drivers/entropy/entropy_mcux_caam.c b/drivers/entropy/entropy_mcux_caam.c index 252453d919c..586b2137ff3 100644 --- a/drivers/entropy/entropy_mcux_caam.c +++ b/drivers/entropy/entropy_mcux_caam.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include diff --git a/drivers/entropy/entropy_mcux_css.c b/drivers/entropy/entropy_mcux_css.c index 24f3bce44ab..e0a5853aa25 100644 --- a/drivers/entropy/entropy_mcux_css.c +++ b/drivers/entropy/entropy_mcux_css.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include static int entropy_mcux_css_get_entropy(const struct device *dev, uint8_t *buffer, uint16_t length) { diff --git a/drivers/entropy/entropy_mcux_rng.c b/drivers/entropy/entropy_mcux_rng.c index dc5f0fc1fa3..b205c4fa21b 100644 --- a/drivers/entropy/entropy_mcux_rng.c +++ b/drivers/entropy/entropy_mcux_rng.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include "fsl_rng.h" diff --git a/drivers/entropy/entropy_mcux_rnga.c b/drivers/entropy/entropy_mcux_rnga.c index 5004ec719b4..b82bd22ff0e 100644 --- a/drivers/entropy/entropy_mcux_rnga.c +++ b/drivers/entropy/entropy_mcux_rnga.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include "fsl_rnga.h" diff --git a/drivers/entropy/entropy_mcux_trng.c b/drivers/entropy/entropy_mcux_trng.c index 8718694e59c..c48e3aab25d 100644 --- a/drivers/entropy/entropy_mcux_trng.c +++ b/drivers/entropy/entropy_mcux_trng.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include "fsl_trng.h" diff --git a/drivers/entropy/entropy_neorv32_trng.c b/drivers/entropy/entropy_neorv32_trng.c index 269339adb9d..2163f8c1928 100644 --- a/drivers/entropy/entropy_neorv32_trng.c +++ b/drivers/entropy/entropy_neorv32_trng.c @@ -69,7 +69,7 @@ static int neorv32_trng_get_entropy_isr(const struct device *dev, uint8_t *buffe } /* No entropy available */ - return 0; + return -ENODATA; } err = neorv32_trng_get_entropy(dev, buffer, len); diff --git a/drivers/entropy/entropy_rv32m1_trng.c b/drivers/entropy/entropy_rv32m1_trng.c index 3e12429d105..0e44afb7c18 100644 --- a/drivers/entropy/entropy_rv32m1_trng.c +++ b/drivers/entropy/entropy_rv32m1_trng.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include "fsl_trng.h" diff --git a/drivers/entropy/entropy_sam.c b/drivers/entropy/entropy_sam.c index b01569b899b..57bdb8f8419 100644 --- a/drivers/entropy/entropy_sam.c +++ b/drivers/entropy/entropy_sam.c @@ -39,7 +39,7 @@ static inline uint32_t _data(Trng * const trng) #endif } -static int entropy_sam_wait_ready(Trng * const trng, uint32_t flags) +static int entropy_sam_wait_ready(Trng * const trng) { /* According to the reference manual, the generator provides * one 32-bit random value every 84 peripheral clock cycles. @@ -56,17 +56,6 @@ static int entropy_sam_wait_ready(Trng * const trng, uint32_t flags) if (timeout-- == 0) { return -ETIMEDOUT; } - - if ((flags & ENTROPY_BUSYWAIT) == 0U) { - /* This internal function is used by both get_entropy, - * and get_entropy_isr APIs. The later may call this - * function with the ENTROPY_BUSYWAIT flag set. In - * that case make no assumption that the kernel is - * initialized when the function is called; so, just - * do busy-wait for the random data to be ready. - */ - k_yield(); - } } return 0; @@ -74,7 +63,7 @@ static int entropy_sam_wait_ready(Trng * const trng, uint32_t flags) static int entropy_sam_get_entropy_internal(const struct device *dev, uint8_t *buffer, - uint16_t length, uint32_t flags) + uint16_t length) { const struct trng_sam_dev_cfg *config = dev->config; Trng *const trng = config->regs; @@ -84,7 +73,7 @@ static int entropy_sam_get_entropy_internal(const struct device *dev, uint32_t value; int res; - res = entropy_sam_wait_ready(trng, flags); + res = entropy_sam_wait_ready(trng); if (res < 0) { return res; } @@ -103,7 +92,7 @@ static int entropy_sam_get_entropy_internal(const struct device *dev, static int entropy_sam_get_entropy(const struct device *dev, uint8_t *buffer, uint16_t length) { - return entropy_sam_get_entropy_internal(dev, buffer, length, 0); + return entropy_sam_get_entropy_internal(dev, buffer, length); } static int entropy_sam_get_entropy_isr(const struct device *dev, @@ -144,7 +133,7 @@ static int entropy_sam_get_entropy_isr(const struct device *dev, /* Allowed to busy-wait */ int ret = entropy_sam_get_entropy_internal(dev, - buffer, length, flags); + buffer, length); if (ret == 0) { /* Data retrieved successfully. */ diff --git a/drivers/entropy/entropy_stm32.c b/drivers/entropy/entropy_stm32.c index 7c342a09c23..0abedb1940c 100644 --- a/drivers/entropy/entropy_stm32.c +++ b/drivers/entropy/entropy_stm32.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -234,6 +235,8 @@ static int random_byte_get(void) unsigned int key; RNG_TypeDef *rng = entropy_stm32_rng_data.rng; + key = irq_lock(); + if (IS_ENABLED(CONFIG_ENTROPY_STM32_CLK_CHECK) && !k_is_pre_kernel()) { /* CECS bit signals that a clock configuration issue is detected, * which may lead to generation of non truly random data. @@ -243,8 +246,6 @@ static int random_byte_get(void) "\tSee ref man and update target clock configuration."); } - key = irq_lock(); - if (LL_RNG_IsActiveFlag_SEIS(rng) && (recover_seed_error(rng) < 0)) { retval = -EIO; goto out; @@ -632,13 +633,60 @@ static int entropy_stm32_rng_init(const struct device *dev) return 0; } +#ifdef CONFIG_PM_DEVICE +static int entropy_stm32_rng_pm_action(const struct device *dev, + enum pm_device_action action) +{ + struct entropy_stm32_rng_dev_data *dev_data = dev->data; + const struct entropy_stm32_rng_dev_cfg *dev_cfg = dev->config; + RNG_TypeDef *rng = dev_data->rng; + int res = 0; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + LL_RNG_Disable(rng); + +#ifdef CONFIG_SOC_SERIES_STM32WBAX + uint32_t wait_cycles, rng_rate; + + if (clock_control_get_rate(dev_data->clock, + (clock_control_subsys_t) &dev_cfg->pclken[0], + &rng_rate) < 0) { + return -EIO; + } + + wait_cycles = SystemCoreClock / rng_rate * 2; + + for (int i = wait_cycles; i >= 0; i--) { + } +#endif /* CONFIG_SOC_SERIES_STM32WBAX */ + + res = clock_control_off(dev_data->clock, + (clock_control_subsys_t)&dev_cfg->pclken[0]); + break; + case PM_DEVICE_ACTION_RESUME: + res = clock_control_on(dev_data->clock, + (clock_control_subsys_t)&dev_cfg->pclken[0]); + LL_RNG_Enable(rng); + break; + default: + return -ENOTSUP; + } + + return res; +} +#endif /* CONFIG_PM_DEVICE */ + static const struct entropy_driver_api entropy_stm32_rng_api = { .get_entropy = entropy_stm32_rng_get_entropy, .get_entropy_isr = entropy_stm32_rng_get_entropy_isr }; +PM_DEVICE_DT_INST_DEFINE(0, entropy_stm32_rng_pm_action); + DEVICE_DT_INST_DEFINE(0, - entropy_stm32_rng_init, NULL, + entropy_stm32_rng_init, + PM_DEVICE_DT_INST_GET(0), &entropy_stm32_rng_data, &entropy_stm32_rng_config, PRE_KERNEL_1, CONFIG_ENTROPY_INIT_PRIORITY, &entropy_stm32_rng_api); diff --git a/drivers/entropy/fake_entropy_native_posix.c b/drivers/entropy/fake_entropy_native_posix.c index b39c07bbf30..33658155595 100644 --- a/drivers/entropy/fake_entropy_native_posix.c +++ b/drivers/entropy/fake_entropy_native_posix.c @@ -59,7 +59,9 @@ static int entropy_native_posix_get_entropy_isr(const struct device *dev, * entropy_native_posix_get_entropy() is also safe for ISRs * and always produces data. */ - return entropy_native_posix_get_entropy(dev, buf, len); + entropy_native_posix_get_entropy(dev, buf, len); + + return len; } static int entropy_native_posix_init(const struct device *dev) diff --git a/drivers/espi/Kconfig.npcx b/drivers/espi/Kconfig.npcx index 1da4f661217..d0680565a6d 100644 --- a/drivers/espi/Kconfig.npcx +++ b/drivers/espi/Kconfig.npcx @@ -80,4 +80,10 @@ config ESPI_PERIPHERAL_ACPI_SHM_REGION config ESPI_PERIPHERAL_CUSTOM_OPCODE default y +config ESPI_NPCX_SUPP_VW_GPIO + bool "Indicates that the eSPI hardware supports virtual wire GPIOs" + default y if SOC_SERIES_NPCX9 || SOC_SERIES_NPCX4 + help + Selected if NPCX series supports virtual wire GPIOs in eSPI module. + endif #ESPI_NPCX diff --git a/drivers/espi/espi_handlers.c b/drivers/espi/espi_handlers.c index d6800fe0f6e..c215838fd79 100644 --- a/drivers/espi/espi_handlers.c +++ b/drivers/espi/espi_handlers.c @@ -5,7 +5,7 @@ */ #include -#include +#include static inline int z_vrfy_espi_config(const struct device *dev, @@ -13,8 +13,8 @@ static inline int z_vrfy_espi_config(const struct device *dev, { struct espi_cfg cfg_copy; - Z_OOPS(Z_SYSCALL_DRIVER_ESPI(dev, config)); - Z_OOPS(z_user_from_copy(&cfg_copy, cfg, + K_OOPS(K_SYSCALL_DRIVER_ESPI(dev, config)); + K_OOPS(k_usermode_from_copy(&cfg_copy, cfg, sizeof(struct espi_cfg))); return z_impl_espi_config(dev, &cfg_copy); @@ -24,7 +24,7 @@ static inline int z_vrfy_espi_config(const struct device *dev, static inline bool z_vrfy_espi_get_channel_status(const struct device *dev, enum espi_channel ch) { - Z_OOPS(Z_SYSCALL_DRIVER_ESPI(dev, get_channel_status)); + K_OOPS(K_SYSCALL_DRIVER_ESPI(dev, get_channel_status)); return z_impl_espi_get_channel_status(dev, ch); } @@ -37,10 +37,10 @@ static inline int z_vrfy_espi_read_lpc_request(const struct device *dev, int ret; uint32_t data_copy; - Z_OOPS(Z_SYSCALL_DRIVER_ESPI(dev, read_lpc_request)); + K_OOPS(K_SYSCALL_DRIVER_ESPI(dev, read_lpc_request)); ret = z_impl_espi_read_lpc_request(dev, op, &data_copy); - Z_OOPS(z_user_to_copy(data, &data_copy, sizeof(uint8_t))); + K_OOPS(k_usermode_to_copy(data, &data_copy, sizeof(uint8_t))); return ret; } @@ -52,8 +52,8 @@ static inline int z_vrfy_espi_write_lpc_request(const struct device *dev, { uint32_t data_copy; - Z_OOPS(Z_SYSCALL_DRIVER_ESPI(dev, write_lpc_request)); - Z_OOPS(z_user_from_copy(&data_copy, data, sizeof(*data))); + K_OOPS(K_SYSCALL_DRIVER_ESPI(dev, write_lpc_request)); + K_OOPS(k_usermode_from_copy(&data_copy, data, sizeof(*data))); return z_impl_espi_write_lpc_request(dev, op, &data_copy); } @@ -63,7 +63,7 @@ static inline int z_vrfy_espi_send_vwire(const struct device *dev, enum espi_vwire_signal signal, uint8_t level) { - Z_OOPS(Z_SYSCALL_DRIVER_ESPI(dev, send_vwire)); + K_OOPS(K_SYSCALL_DRIVER_ESPI(dev, send_vwire)); return z_impl_espi_send_vwire(dev, signal, level); } @@ -76,10 +76,10 @@ static inline int z_vrfy_espi_receive_vwire(const struct device *dev, int ret; uint8_t level_copy; - Z_OOPS(Z_SYSCALL_DRIVER_ESPI(dev, receive_vwire)); + K_OOPS(K_SYSCALL_DRIVER_ESPI(dev, receive_vwire)); ret = z_impl_espi_receive_vwire(dev, signal, &level_copy); - Z_OOPS(z_user_to_copy(level, &level_copy, sizeof(uint8_t))); + K_OOPS(k_usermode_to_copy(level, &level_copy, sizeof(uint8_t))); return ret; } @@ -91,14 +91,14 @@ static inline int z_vrfy_espi_read_request(const struct device *dev, int ret; struct espi_request_packet req_copy; - Z_OOPS(Z_SYSCALL_DRIVER_ESPI(dev, read_request)); - Z_OOPS(z_user_from_copy(&req_copy, req, + K_OOPS(K_SYSCALL_DRIVER_ESPI(dev, read_request)); + K_OOPS(k_usermode_from_copy(&req_copy, req, sizeof(struct espi_request_packet))); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(req_copy.data, req_copy.len)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(req_copy.data, req_copy.len)); ret = z_impl_espi_read_request(dev, &req_copy); - Z_OOPS(z_user_to_copy(req, &req_copy, + K_OOPS(k_usermode_to_copy(req, &req_copy, sizeof(struct espi_request_packet))); return ret; @@ -111,9 +111,9 @@ static inline int z_vrfy_espi_write_request(const struct device *dev, int ret; struct espi_request_packet req_copy; - Z_OOPS(Z_SYSCALL_DRIVER_ESPI(dev, write_request)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(req->data, req->len)); - Z_OOPS(z_user_from_copy(&req_copy, req, + K_OOPS(K_SYSCALL_DRIVER_ESPI(dev, write_request)); + K_OOPS(K_SYSCALL_MEMORY_READ(req->data, req->len)); + K_OOPS(k_usermode_from_copy(&req_copy, req, sizeof(struct espi_request_packet))); ret = z_impl_espi_write_request(dev, &req_copy); @@ -128,9 +128,9 @@ static inline int z_vrfy_espi_send_oob(const struct device *dev, int ret; struct espi_oob_packet pckt_copy; - Z_OOPS(Z_SYSCALL_DRIVER_ESPI(dev, send_oob)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(pckt->buf, pckt->len)); - Z_OOPS(z_user_from_copy(&pckt_copy, pckt, + K_OOPS(K_SYSCALL_DRIVER_ESPI(dev, send_oob)); + K_OOPS(K_SYSCALL_MEMORY_READ(pckt->buf, pckt->len)); + K_OOPS(k_usermode_from_copy(&pckt_copy, pckt, sizeof(struct espi_oob_packet))); ret = z_impl_espi_send_oob(dev, &pckt_copy); @@ -145,13 +145,13 @@ static inline int z_vrfy_espi_receive_oob(const struct device *dev, int ret; struct espi_oob_packet pckt_copy; - Z_OOPS(Z_SYSCALL_DRIVER_ESPI(dev, receive_oob)); - Z_OOPS(z_user_from_copy(&pckt_copy, pckt, + K_OOPS(K_SYSCALL_DRIVER_ESPI(dev, receive_oob)); + K_OOPS(k_usermode_from_copy(&pckt_copy, pckt, sizeof(struct espi_oob_packet))); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(pckt->buf, pckt->len)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(pckt->buf, pckt->len)); ret = z_impl_espi_receive_oob(dev, &pckt_copy); - Z_OOPS(z_user_to_copy(pckt, &pckt_copy, + K_OOPS(k_usermode_to_copy(pckt, &pckt_copy, sizeof(struct espi_oob_packet))); return ret; @@ -164,13 +164,13 @@ static inline int z_vrfy_espi_read_flash(const struct device *dev, int ret; struct espi_flash_packet pckt_copy; - Z_OOPS(Z_SYSCALL_DRIVER_ESPI(dev, flash_read)); - Z_OOPS(z_user_from_copy(&pckt_copy, pckt, + K_OOPS(K_SYSCALL_DRIVER_ESPI(dev, flash_read)); + K_OOPS(k_usermode_from_copy(&pckt_copy, pckt, sizeof(struct espi_flash_packet))); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(pckt->buf, pckt->len)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(pckt->buf, pckt->len)); ret = z_impl_espi_read_flash(dev, pckt); - Z_OOPS(z_user_to_copy(pckt, &pckt_copy, + K_OOPS(k_usermode_to_copy(pckt, &pckt_copy, sizeof(struct espi_flash_packet))); return ret; @@ -183,10 +183,10 @@ static inline int z_vrfy_espi_write_flash(const struct device *dev, int ret; struct espi_flash_packet pckt_copy; - Z_OOPS(Z_SYSCALL_DRIVER_ESPI(dev, flash_write)); - Z_OOPS(z_user_from_copy(&pckt_copy, pckt, + K_OOPS(K_SYSCALL_DRIVER_ESPI(dev, flash_write)); + K_OOPS(k_usermode_from_copy(&pckt_copy, pckt, sizeof(struct espi_flash_packet))); - Z_OOPS(Z_SYSCALL_MEMORY_READ(pckt->buf, pckt->len)); + K_OOPS(K_SYSCALL_MEMORY_READ(pckt->buf, pckt->len)); ret = z_impl_espi_write_flash(dev, &pckt_copy); @@ -200,10 +200,10 @@ static inline int z_vrfy_espi_flash_erase(const struct device *dev, int ret; struct espi_flash_packet pckt_copy; - Z_OOPS(Z_SYSCALL_DRIVER_ESPI(dev, flash_write)); - Z_OOPS(z_user_from_copy(&pckt_copy, pckt, + K_OOPS(K_SYSCALL_DRIVER_ESPI(dev, flash_write)); + K_OOPS(k_usermode_from_copy(&pckt_copy, pckt, sizeof(struct espi_flash_packet))); - Z_OOPS(Z_SYSCALL_MEMORY_READ(pckt->buf, pckt->len)); + K_OOPS(K_SYSCALL_MEMORY_READ(pckt->buf, pckt->len)); ret = z_impl_espi_flash_erase(dev, &pckt_copy); diff --git a/drivers/espi/espi_npcx.c b/drivers/espi/espi_npcx.c index 7d2679407a4..d6177dee388 100644 --- a/drivers/espi/espi_npcx.c +++ b/drivers/espi/espi_npcx.c @@ -164,7 +164,7 @@ static const struct npcx_vw_out_config vw_out_tbl[] = { /* Virtual wire GPIOs for platform level usage (High at Reset state) */ static const struct npcx_vw_out_config vw_out_gpio_tbl1[] = { /* Only NPCX9 and later series support this feature */ -#if !defined(CONFIG_SOC_SERIES_NPCX7) +#if defined(CONFIG_ESPI_NPCX_SUPP_VW_GPIO) /* index 50h (Out) */ NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_SLV_GPIO_0, vw_slv_gpio_0), NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_SLV_GPIO_1, vw_slv_gpio_1), diff --git a/drivers/ethernet/CMakeLists.txt b/drivers/ethernet/CMakeLists.txt index 6f963cd68d0..8c8795509fd 100644 --- a/drivers/ethernet/CMakeLists.txt +++ b/drivers/ethernet/CMakeLists.txt @@ -34,6 +34,7 @@ zephyr_library_sources_ifdef(CONFIG_SLIP_TAP eth_slip_tap.c) zephyr_library_sources_ifdef(CONFIG_ETH_SMSC91X eth_smsc91x.c) zephyr_library_sources_ifdef(CONFIG_ETH_IVSHMEM eth_ivshmem.c eth_ivshmem_queue.c) zephyr_library_sources_ifdef(CONFIG_ETH_ADIN2111 eth_adin2111.c) +zephyr_library_sources_ifdef(CONFIG_ETH_LAN865X eth_lan865x.c oa_tc6.c) if(CONFIG_ETH_NXP_S32_NETC) zephyr_library_sources(eth_nxp_s32_netc.c) @@ -42,14 +43,20 @@ if(CONFIG_ETH_NXP_S32_NETC) endif() zephyr_library_sources_ifdef(CONFIG_ETH_NXP_S32_GMAC eth_nxp_s32_gmac.c) +zephyr_library_sources_ifdef(CONFIG_ETH_NUMAKER eth_numaker.c) if(CONFIG_ETH_NATIVE_POSIX) - set(native_posix_source_files eth_native_posix.c eth_native_posix_adapt.c) - set_source_files_properties(${native_posix_source_files} - PROPERTIES COMPILE_DEFINITIONS - "NO_POSIX_CHEATS;_BSD_SOURCE;_DEFAULT_SOURCE" - ) - zephyr_library_sources(${native_posix_source_files}) + if (CONFIG_NATIVE_APPLICATION) + set(native_posix_source_files eth_native_posix.c eth_native_posix_adapt.c) + set_source_files_properties(${native_posix_source_files} + PROPERTIES COMPILE_DEFINITIONS + "NO_POSIX_CHEATS;_BSD_SOURCE;_DEFAULT_SOURCE" + ) + zephyr_library_sources(${native_posix_source_files}) + else() + zephyr_library_sources(eth_native_posix.c) + target_sources(native_simulator INTERFACE eth_native_posix_adapt.c) + endif() endif() add_subdirectory(phy) diff --git a/drivers/ethernet/Kconfig b/drivers/ethernet/Kconfig index 8160fc74358..69b60e09bc2 100644 --- a/drivers/ethernet/Kconfig +++ b/drivers/ethernet/Kconfig @@ -61,6 +61,8 @@ source "drivers/ethernet/Kconfig.nxp_s32_gmac" source "drivers/ethernet/Kconfig.smsc91x" source "drivers/ethernet/Kconfig.ivshmem" source "drivers/ethernet/Kconfig.adin2111" +source "drivers/ethernet/Kconfig.numaker" +source "drivers/ethernet/Kconfig.lan865x" source "drivers/ethernet/phy/Kconfig" diff --git a/drivers/ethernet/Kconfig.adin2111 b/drivers/ethernet/Kconfig.adin2111 index 11914519667..2e1cbd8a0af 100644 --- a/drivers/ethernet/Kconfig.adin2111 +++ b/drivers/ethernet/Kconfig.adin2111 @@ -20,16 +20,6 @@ menuconfig ETH_ADIN2111 if ETH_ADIN2111 -config ETH_ADIN2111_INIT_PRIORITY - int "ADIN2111 driver init priority" - default 72 - help - ADIN2111 device driver initialization priority. - Must be initialized after SPI, but before MDIO - and ports. - - Both ports use ETH_INIT_PRIORITY initialization priority. - config ETH_ADIN2111_IRQ_THREAD_STACK_SIZE int "Stack size for a thread that processes ADIN IRQ" default 2048 diff --git a/drivers/ethernet/Kconfig.dsa b/drivers/ethernet/Kconfig.dsa index 3683a539759..c6b78f0a463 100644 --- a/drivers/ethernet/Kconfig.dsa +++ b/drivers/ethernet/Kconfig.dsa @@ -6,10 +6,10 @@ menuconfig NET_DSA bool "Distributed Switch Architecture support" - depends on ETH_MCUX || ETH_SAM_GMAC + depends on ETH_MCUX || ETH_SAM_GMAC || ETH_STM32_HAL help Enable Distributed Switch Architecture support. For now it - only supports Kinetics ENET driver. + only supports Kinetics and STM32 ENET drivers. if NET_DSA diff --git a/drivers/ethernet/Kconfig.dwmac b/drivers/ethernet/Kconfig.dwmac index 547a8a7a1f1..47acdffd0b1 100644 --- a/drivers/ethernet/Kconfig.dwmac +++ b/drivers/ethernet/Kconfig.dwmac @@ -30,7 +30,7 @@ if ETH_DWMAC config ETH_DWMAC_STM32H7X bool depends on SOC_SERIES_STM32H7X - select NOCACHE_MEMORY + select NOCACHE_MEMORY if ARCH_HAS_NOCACHE_MEMORY_SUPPORT default y config ETH_DWMAC_MMU diff --git a/drivers/ethernet/Kconfig.lan865x b/drivers/ethernet/Kconfig.lan865x new file mode 100644 index 00000000000..c3bdc2f9b73 --- /dev/null +++ b/drivers/ethernet/Kconfig.lan865x @@ -0,0 +1,50 @@ +# Copyright (c) 2023 DENX Software Engineering GmbH +# SPDX-License-Identifier: Apache-2.0 + +menuconfig ETH_LAN865X + bool "LAN865X 10BASE-T1S Controller" + default y + depends on DT_HAS_MICROCHIP_LAN865X_ENABLED + select SPI + help + The LAN865X is a low power, 10BASE-T1S transceiver compliant with + the IEEE® 802.3cg-2019™ Ethernet standard for long reach, 10 + Mbps single pair Ethernet (SPE). + + Featuring an integrated media access control (MAC) and a PHY, + the LAN865X enables direct connectivity with a variety of controllers + via a serial peripheral inter-face (SPI). + +if ETH_LAN865X + +config ETH_LAN865X_INIT_PRIORITY + int "LAN865X driver init priority" + default 72 + help + LAN865X device driver initialization priority. + Must be initialized after SPI. + + +config ETH_LAN865X_IRQ_THREAD_STACK_SIZE + int "Stack size for a thread that processes IRQ" + default 512 + help + Size of the stack used for internal thread which is ran to + process raised INT IRQ. + +config ETH_LAN865X_IRQ_THREAD_PRIO + int "Priority for internal incoming packet handler" + default 2 + help + Priority level for internal thread which is ran for LAN + INT IRQ processing. + +config ETH_LAN865X_TIMEOUT + int "IP buffer timeout" + default 100 + help + Given timeout in milliseconds. Maximum amount of time + that the driver will wait from the IP stack to get + a memory buffer before the Ethernet frame is dropped. + +endif # ETH_LAN865X diff --git a/drivers/ethernet/Kconfig.mcux b/drivers/ethernet/Kconfig.mcux index 1ecf0db8dc9..8996d7239ff 100644 --- a/drivers/ethernet/Kconfig.mcux +++ b/drivers/ethernet/Kconfig.mcux @@ -7,7 +7,7 @@ menuconfig ETH_MCUX bool "MCUX Ethernet driver" default y depends on DT_HAS_NXP_KINETIS_ETHERNET_ENABLED - select NOCACHE_MEMORY if HAS_MCUX_CACHE + select NOCACHE_MEMORY if HAS_MCUX_CACHE && CPU_HAS_DCACHE select ARM_MPU if CPU_CORTEX_M7 select NET_POWER_MANAGEMENT if PM_DEVICE help diff --git a/drivers/ethernet/Kconfig.native_posix b/drivers/ethernet/Kconfig.native_posix index 5fc33450540..8ab1033d477 100644 --- a/drivers/ethernet/Kconfig.native_posix +++ b/drivers/ethernet/Kconfig.native_posix @@ -5,65 +5,12 @@ menuconfig ETH_NATIVE_POSIX bool "Native Posix Ethernet driver" - depends on ARCH_POSIX && EXTERNAL_LIBC + depends on ARCH_POSIX help Enable native posix ethernet driver. Note, this driver is run inside a process in your host system. if ETH_NATIVE_POSIX -config ETH_NATIVE_POSIX_STARTUP_AUTOMATIC - bool "Start network interface automatically" - help - If set, the native_posix ethernet driver will set up the network - interface, requiring ``zephyr.exe`` to be run with root privileges - (needed to create and configure the TAP device). - If not set (the default and recommended way), the network interface - must be set up manually using ``net-setup.sh`` (from the net-tools - project repo). The ``zephyr.exe`` program can then be run as a - non-root user. - -if ETH_NATIVE_POSIX_STARTUP_AUTOMATIC - -config ETH_NATIVE_POSIX_SETUP_SCRIPT - string "Host setup script" - default "${ZEPHYR_BASE}/samples/net/eth_native_posix/net_setup_host" - help - This option sets the name of the script that is run when the host TAP - network interface is created. The script should setup IP addresses - etc. for the host TAP network interface. - The default script accepts following options: - -i|--interface , default is zeth - -f|--file , default is net_setup_host.conf - If needed, you can add these options to this script name option. - Note that the driver will add -i option with the value of - CONFIG_ETH_NATIVE_POSIX_DRV_NAME option to the end of the options - list when calling the host setup script. - -config ETH_NATIVE_POSIX_STARTUP_SCRIPT - string "Host startup script" - default "" - help - This option sets the name of the script that is run when the host TAP - network interface is created and setup script has been run. - The startup script could launch e.g., wireshark to capture - the network traffic for the freshly started network interface. - Note that the network interface name CONFIG_ETH_NATIVE_POSIX_DRV_NAME - is appended at the end of this startup script name. - Example script for starting wireshark is provided in - ${ZEPHYR_BASE}/samples/net/eth_native_posix/net_start_wireshark.sh - file. - -config ETH_NATIVE_POSIX_STARTUP_SCRIPT_USER - string "Username to run the host startup script" - default "" - help - By default the startup script is run as a root user. Set here the - username to run the script if running it as a root user is not - desired. Note that this setting is only for startup script and not - for the setup script. The setup script needs to be run always as - a root user. - -endif # ETH_NATIVE_POSIX_STARTUP_AUTOMATIC config ETH_NATIVE_POSIX_INTERFACE_COUNT int "Number of network interfaces created" diff --git a/drivers/ethernet/Kconfig.numaker b/drivers/ethernet/Kconfig.numaker new file mode 100644 index 00000000000..eb757870d7b --- /dev/null +++ b/drivers/ethernet/Kconfig.numaker @@ -0,0 +1,14 @@ +# NUMAKER Ethernet Driver configuration options + +# Copyright (c) 2023 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +config ETH_NUMAKER + bool "Nuvoton NUMAKER MCU Ethernet driver" + default y + select HAS_NUMAKER_ETH + depends on DT_HAS_NUVOTON_NUMAKER_ETHERNET_ENABLED + help + This option enables the Ethernet driver for Nuvoton NuMaker family of + processors. + Say y if you wish to enable NuMaker ETH. diff --git a/drivers/ethernet/Kconfig.nxp_s32_gmac b/drivers/ethernet/Kconfig.nxp_s32_gmac index 1d78ea5ff99..a1d0f3f7c3d 100644 --- a/drivers/ethernet/Kconfig.nxp_s32_gmac +++ b/drivers/ethernet/Kconfig.nxp_s32_gmac @@ -5,7 +5,7 @@ menuconfig ETH_NXP_S32_GMAC bool "NXP S32 GMAC driver" default y depends on DT_HAS_NXP_S32_GMAC_ENABLED - select NOCACHE_MEMORY + select NOCACHE_MEMORY if ARCH_HAS_NOCACHE_MEMORY_SUPPORT select PINCTRL help Enable GMAC/EMAC Ethernet driver for NXP S32 SoCs. diff --git a/drivers/ethernet/Kconfig.nxp_s32_netc b/drivers/ethernet/Kconfig.nxp_s32_netc index d56c38916ba..6c568ca211e 100644 --- a/drivers/ethernet/Kconfig.nxp_s32_netc +++ b/drivers/ethernet/Kconfig.nxp_s32_netc @@ -1,14 +1,13 @@ -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # SPDX-License-Identifier: Apache-2.0 menuconfig ETH_NXP_S32_NETC bool "NXP S32 Ethernet Switch and Controller (NETC) driver" default y depends on (DT_HAS_NXP_S32_NETC_PSI_ENABLED || DT_HAS_NXP_S32_NETC_VSI_ENABLED) - depends on !NET_TEST select MBOX select MDIO if DT_HAS_NXP_S32_NETC_PSI_ENABLED - select NOCACHE_MEMORY + select NOCACHE_MEMORY if ARCH_HAS_NOCACHE_MEMORY_SUPPORT help Enable Ethernet Switch and Controller (NETC) driver for NXP S32 SoCs. diff --git a/drivers/ethernet/dsa_ksz8xxx.c b/drivers/ethernet/dsa_ksz8xxx.c index 0a6bb0adffe..964cd3505d3 100644 --- a/drivers/ethernet/dsa_ksz8xxx.c +++ b/drivers/ethernet/dsa_ksz8xxx.c @@ -1091,8 +1091,6 @@ static struct dsa_api dsa_api_f = { #if defined(CONFIG_DSA_SPI) #define DSA_SPI_BUS_CONFIGURATION(n) \ .spi = SPI_DT_SPEC_INST_GET(n, \ - COND_CODE_1(DT_INST_PROP(n, spi_cpol), (SPI_MODE_CPOL), ()) | \ - COND_CODE_1(DT_INST_PROP(n, spi_cpha), (SPI_MODE_CPHA), ()) | \ SPI_WORD_SET(8), \ 0U) #else diff --git a/drivers/ethernet/eth.h b/drivers/ethernet/eth.h index 06ba7558466..ebbff29a9d9 100644 --- a/drivers/ethernet/eth.h +++ b/drivers/ethernet/eth.h @@ -8,7 +8,7 @@ #define ZEPHYR_DRIVERS_ETHERNET_ETH_H_ #include -#include +#include /* helper macro to return mac address octet from local_mac_address prop */ #define NODE_MAC_ADDR_OCTET(node, n) DT_PROP_BY_IDX(node, local_mac_address, n) diff --git a/drivers/ethernet/eth_adin2111.c b/drivers/ethernet/eth_adin2111.c index 4d8c7053698..e73beb891d4 100644 --- a/drivers/ethernet/eth_adin2111.c +++ b/drivers/ethernet/eth_adin2111.c @@ -264,8 +264,12 @@ static inline void adin2111_port_on_phyint(const struct device *dev) } } -static void adin2111_offload_thread(const struct device *dev) +static void adin2111_offload_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; struct adin2111_data *ctx = dev->data; const struct adin2111_config *adin_cfg = dev->config; bool is_adin2111 = (adin_cfg->id == ADIN2111_MAC); @@ -669,7 +673,7 @@ static void adin2111_port_iface_init(struct net_if *iface) /* all ifaces are done, start INT processing */ k_thread_create(&ctx->rx_thread, ctx->rx_thread_stack, CONFIG_ETH_ADIN2111_IRQ_THREAD_STACK_SIZE, - (k_thread_entry_t)adin2111_offload_thread, + adin2111_offload_thread, (void *)adin, NULL, NULL, CONFIG_ETH_ADIN2111_IRQ_THREAD_PRIO, K_ESSENTIAL, K_NO_WAIT); @@ -696,19 +700,23 @@ static int adin2111_port_set_config(const struct device *dev, const struct device *adin = cfg->adin; int ret = -ENOTSUP; + (void)eth_adin2111_lock(adin, K_FOREVER); + if (type == ETHERNET_CONFIG_TYPE_MAC_ADDRESS) { - ret = adin2111_filter_unicast(adin, data->mac_addr, cfg->port_idx); + ret = adin2111_filter_unicast(adin, (uint8_t *)&config->mac_address.addr[0], + cfg->port_idx); if (ret < 0) { - return ret; + goto end_unlock; } - memcpy(data->mac_addr, config->mac_address.addr, sizeof(data->mac_addr)); + (void)memcpy(data->mac_addr, config->mac_address.addr, sizeof(data->mac_addr)); - net_if_set_link_addr(data->iface, data->mac_addr, - sizeof(data->mac_addr), - NET_LINK_ETHERNET); + (void)net_if_set_link_addr(data->iface, data->mac_addr, sizeof(data->mac_addr), + NET_LINK_ETHERNET); } +end_unlock: + (void)eth_adin2111_unlock(adin); return ret; } @@ -938,62 +946,62 @@ static const struct ethernet_api adin2111_port_api = { #define ADIN2111_XSTR(x) ADIN2111_STR(x) #define ADIN2111_MDIO_PHY_BY_ADDR(adin_n, phy_addr) \ - DEVICE_DT_GET(DT_CHILD(DT_INST_CHILD(adin_n, mdio), phy_##phy_addr)) + DEVICE_DT_GET(DT_CHILD(DT_INST_CHILD(adin_n, mdio), ethernet_phy_##phy_addr)) #define ADIN2111_PORT_MAC(adin_n, port_n) \ DT_PROP(DT_CHILD(DT_DRV_INST(adin_n), port##port_n), local_mac_address) -#define ADIN2111_PORT_DEVICE_INIT_INSTANCE(parent_n, port_n, phy_n) \ - static struct adin2111_port_data adin2111_port_data_##port_n = { \ +#define ADIN2111_PORT_DEVICE_INIT_INSTANCE(parent_n, port_n, phy_n, name) \ + static struct adin2111_port_data name##_port_data_##port_n = { \ .mac_addr = ADIN2111_PORT_MAC(parent_n, phy_n), \ }; \ - static const struct adin2111_port_config adin2111_port_config_##port_n = { \ + static const struct adin2111_port_config name##_port_config_##port_n = { \ .adin = DEVICE_DT_INST_GET(parent_n), \ .phy = ADIN2111_MDIO_PHY_BY_ADDR(parent_n, phy_n), \ .port_idx = port_n, \ .phy_addr = phy_n, \ }; \ - NET_DEVICE_INIT_INSTANCE(adin2111_port_##port_n, "port_" ADIN2111_XSTR(port_n), port_n, \ - NULL, NULL, &adin2111_port_data_##port_n, \ - &adin2111_port_config_##port_n, CONFIG_ETH_INIT_PRIORITY, \ + NET_DEVICE_INIT_INSTANCE(name##_port_##port_n, "port_" ADIN2111_XSTR(port_n), port_n, \ + NULL, NULL, &name##_port_data_##port_n, \ + &name##_port_config_##port_n, CONFIG_ETH_INIT_PRIORITY, \ &adin2111_port_api, ETHERNET_L2, \ NET_L2_GET_CTX_TYPE(ETHERNET_L2), NET_ETH_MTU); #define ADIN2111_SPI_OPERATION ((uint16_t)(SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8))) -#define ADIN2111_MAC_INITIALIZE(inst, dev_id, ifaces) \ - static uint8_t __aligned(4) adin2111_buffer_##inst[CONFIG_ETH_ADIN2111_BUFFER_SIZE]; \ - static const struct adin2111_config adin2111_config_##inst = { \ +#define ADIN2111_MAC_INITIALIZE(inst, dev_id, ifaces, name) \ + static uint8_t __aligned(4) name##_buffer_##inst[CONFIG_ETH_ADIN2111_BUFFER_SIZE]; \ + static const struct adin2111_config name##_config_##inst = { \ .id = dev_id, \ .spi = SPI_DT_SPEC_INST_GET(inst, ADIN2111_SPI_OPERATION, 1), \ .interrupt = GPIO_DT_SPEC_INST_GET(inst, int_gpios), \ .reset = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, { 0 }), \ }; \ - static struct adin2111_data adin2111_data_##inst = { \ + static struct adin2111_data name##_data_##inst = { \ .ifaces_left_to_init = ifaces, \ .port = {}, \ - .offload_sem = Z_SEM_INITIALIZER(adin2111_data_##inst.offload_sem, 0, 1), \ - .lock = Z_MUTEX_INITIALIZER(adin2111_data_##inst.lock), \ - .buf = adin2111_buffer_##inst, \ + .offload_sem = Z_SEM_INITIALIZER(name##_data_##inst.offload_sem, 0, 1), \ + .lock = Z_MUTEX_INITIALIZER(name##_data_##inst.lock), \ + .buf = name##_buffer_##inst, \ }; \ /* adin */ \ DEVICE_DT_DEFINE(DT_DRV_INST(inst), adin2111_init, NULL, \ - &adin2111_data_##inst, &adin2111_config_##inst, \ - POST_KERNEL, CONFIG_ETH_ADIN2111_INIT_PRIORITY, \ + &name##_data_##inst, &name##_config_##inst, \ + POST_KERNEL, CONFIG_ETH_INIT_PRIORITY, \ NULL); -#define ADIN2111_MAC_INIT(inst) ADIN2111_MAC_INITIALIZE(inst, ADIN2111_MAC, 2) \ +#define ADIN2111_MAC_INIT(inst) ADIN2111_MAC_INITIALIZE(inst, ADIN2111_MAC, 2, adin2111) \ /* ports */ \ - ADIN2111_PORT_DEVICE_INIT_INSTANCE(inst, 0, 1) \ - ADIN2111_PORT_DEVICE_INIT_INSTANCE(inst, 1, 2) + ADIN2111_PORT_DEVICE_INIT_INSTANCE(inst, 0, 1, adin2111) \ + ADIN2111_PORT_DEVICE_INIT_INSTANCE(inst, 1, 2, adin2111) #undef DT_DRV_COMPAT #define DT_DRV_COMPAT adi_adin2111 DT_INST_FOREACH_STATUS_OKAY(ADIN2111_MAC_INIT) -#define ADIN1110_MAC_INIT(inst) ADIN2111_MAC_INITIALIZE(inst, ADIN1110_MAC, 1) \ +#define ADIN1110_MAC_INIT(inst) ADIN2111_MAC_INITIALIZE(inst, ADIN1110_MAC, 1, adin1110) \ /* ports */ \ - ADIN2111_PORT_DEVICE_INIT_INSTANCE(inst, 0, 1) + ADIN2111_PORT_DEVICE_INIT_INSTANCE(inst, 0, 1, adin1110) #undef DT_DRV_COMPAT #define DT_DRV_COMPAT adi_adin1110 diff --git a/drivers/ethernet/eth_dwmac_mmu.c b/drivers/ethernet/eth_dwmac_mmu.c index 38e8a99c435..b78fbbc035d 100644 --- a/drivers/ethernet/eth_dwmac_mmu.c +++ b/drivers/ethernet/eth_dwmac_mmu.c @@ -15,7 +15,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #define DT_DRV_COMPAT snps_designware_ethernet #include -#include +#include #include #include #include diff --git a/drivers/ethernet/eth_enc28j60.c b/drivers/ethernet/eth_enc28j60.c index 35aacd8753a..502d0cc1199 100644 --- a/drivers/ethernet/eth_enc28j60.c +++ b/drivers/ethernet/eth_enc28j60.c @@ -708,8 +708,12 @@ static int eth_enc28j60_rx(const struct device *dev, uint16_t *vlan_tag) return 0; } -static void eth_enc28j60_rx_thread(const struct device *dev) +static void eth_enc28j60_rx_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; struct eth_enc28j60_runtime *context = dev->data; uint16_t vlan_tag = NET_VLAN_TAG_UNSPEC; uint8_t int_stat; @@ -850,7 +854,7 @@ static int eth_enc28j60_init(const struct device *dev) /* Start interruption-poll thread */ k_thread_create(&context->thread, context->thread_stack, CONFIG_ETH_ENC28J60_RX_THREAD_STACK_SIZE, - (k_thread_entry_t)eth_enc28j60_rx_thread, + eth_enc28j60_rx_thread, (void *)dev, NULL, NULL, K_PRIO_COOP(CONFIG_ETH_ENC28J60_RX_THREAD_PRIO), 0, K_NO_WAIT); diff --git a/drivers/ethernet/eth_enc424j600.c b/drivers/ethernet/eth_enc424j600.c index c4ab7440058..b2b645652ce 100644 --- a/drivers/ethernet/eth_enc424j600.c +++ b/drivers/ethernet/eth_enc424j600.c @@ -442,8 +442,12 @@ static int enc424j600_rx(const struct device *dev) return 0; } -static void enc424j600_rx_thread(struct enc424j600_runtime *context) +static void enc424j600_rx_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct enc424j600_runtime *context = p1; uint16_t eir; uint16_t estat; uint8_t counter; @@ -767,7 +771,7 @@ static int enc424j600_init(const struct device *dev) /* Start interruption-poll thread */ k_thread_create(&context->thread, context->thread_stack, CONFIG_ETH_ENC424J600_RX_THREAD_STACK_SIZE, - (k_thread_entry_t)enc424j600_rx_thread, + enc424j600_rx_thread, context, NULL, NULL, K_PRIO_COOP(CONFIG_ETH_ENC424J600_RX_THREAD_PRIO), 0, K_NO_WAIT); diff --git a/drivers/ethernet/eth_lan865x.c b/drivers/ethernet/eth_lan865x.c new file mode 100644 index 00000000000..8107b7d3542 --- /dev/null +++ b/drivers/ethernet/eth_lan865x.c @@ -0,0 +1,585 @@ +/* + * Copyright (c) 2023 DENX Software Engineering GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT microchip_lan865x + +#include +LOG_MODULE_REGISTER(eth_lan865x, CONFIG_ETHERNET_LOG_LEVEL); + +#include +#include + +#include +#include + +#include +#include +#include + +#include "eth_lan865x_priv.h" + +static int lan865x_mac_rxtx_control(const struct device *dev, bool en) +{ + struct lan865x_data *ctx = dev->data; + uint32_t ctl = 0; + + if (en) { + ctl = LAN865x_MAC_NCR_TXEN | LAN865x_MAC_NCR_RXEN; + } + + return oa_tc6_reg_write(ctx->tc6, LAN865x_MAC_NCR, ctl); +} + +static void lan865x_iface_init(struct net_if *iface) +{ + const struct device *dev = net_if_get_device(iface); + struct lan865x_data *ctx = dev->data; + + net_if_set_link_addr(iface, ctx->mac_address, sizeof(ctx->mac_address), + NET_LINK_ETHERNET); + + if (ctx->iface == NULL) { + ctx->iface = iface; + } + + ethernet_init(iface); + + net_eth_carrier_on(iface); + ctx->iface_initialized = true; +} + +static enum ethernet_hw_caps lan865x_port_get_capabilities(const struct device *dev) +{ + ARG_UNUSED(dev); + return ETHERNET_LINK_10BASE_T | ETHERNET_PROMISC_MODE; +} + +static void lan865x_write_macaddress(const struct device *dev); +static int lan865x_set_config(const struct device *dev, enum ethernet_config_type type, + const struct ethernet_config *config) +{ + struct lan865x_data *ctx = dev->data; + int ret = -ENOTSUP; + + if (type == ETHERNET_CONFIG_TYPE_PROMISC_MODE) { + ret = lan865x_mac_rxtx_control(dev, LAN865x_MAC_TXRX_OFF); + if (ret) { + return ret; + } + + ret = oa_tc6_reg_write(ctx->tc6, LAN865x_MAC_NCFGR, + LAN865x_MAC_NCFGR_CAF); + if (ret) { + return ret; + } + + return lan865x_mac_rxtx_control(dev, LAN865x_MAC_TXRX_ON); + } + + if (type == ETHERNET_CONFIG_TYPE_MAC_ADDRESS) { + ret = lan865x_mac_rxtx_control(dev, LAN865x_MAC_TXRX_OFF); + if (ret) { + return ret; + } + + memcpy(ctx->mac_address, config->mac_address.addr, + sizeof(ctx->mac_address)); + + lan865x_write_macaddress(dev); + + net_if_set_link_addr(ctx->iface, ctx->mac_address, + sizeof(ctx->mac_address), + NET_LINK_ETHERNET); + + return lan865x_mac_rxtx_control(dev, LAN865x_MAC_TXRX_ON); + } + + return ret; +} + +static int lan865x_wait_for_reset(const struct device *dev) +{ + struct lan865x_data *ctx = dev->data; + uint8_t i; + + /* Wait for end of LAN865x reset */ + for (i = 0; !ctx->reset && i < LAN865X_RESET_TIMEOUT; i++) { + k_msleep(1); + } + + if (i == LAN865X_RESET_TIMEOUT) { + LOG_ERR("LAN865x reset timeout reached!"); + return -ENODEV; + } + + return 0; +} + +static int lan865x_gpio_reset(const struct device *dev) +{ + const struct lan865x_config *cfg = dev->config; + + /* Perform (GPIO based) HW reset */ + /* assert RESET_N low for 10 µs (5 µs min) */ + gpio_pin_set_dt(&cfg->reset, 1); + k_busy_wait(10U); + /* deassert - end of reset indicated by IRQ_N low */ + gpio_pin_set_dt(&cfg->reset, 0); + + return lan865x_wait_for_reset(dev); +} + +static int lan865x_check_spi(const struct device *dev) +{ + struct lan865x_data *ctx = dev->data; + uint32_t val; + int ret; + + ret = oa_tc6_reg_read(ctx->tc6, LAN865x_DEVID, &val); + if (ret < 0) { + return -ENODEV; + } + + ctx->silicon_rev = val & LAN865X_REV_MASK; + if (ctx->silicon_rev != 1 && ctx->silicon_rev != 2) { + return -ENODEV; + } + + ctx->chip_id = (val >> 4) & 0xFFFF; + if (ctx->chip_id != LAN8650_DEVID && ctx->chip_id != LAN8651_DEVID) { + return -ENODEV; + } + + return ret; +} + +/* Implementation of pseudo code from AN1760 */ +static uint8_t lan865x_read_indirect_reg(const struct device *dev, uint8_t addr, + uint8_t mask) +{ + struct lan865x_data *ctx = dev->data; + uint32_t val; + + oa_tc6_reg_write(ctx->tc6, 0x000400D8, addr); + oa_tc6_reg_write(ctx->tc6, 0x000400DA, 0x02); + + oa_tc6_reg_read(ctx->tc6, 0x000400D9, &val); + + return (uint8_t) val & mask; +} + +static int lan865x_init_chip(const struct device *dev, uint8_t silicon_rev) +{ + struct lan865x_data *ctx = dev->data; + uint8_t value1, value2; + int8_t offset1 = 0, offset2 = 0, ret; + uint16_t value3, value4, value5, value6, value7; + uint16_t cfgparam1, cfgparam2, cfgparam3, cfgparam4, cfgparam5; + uint32_t val; + + ret = lan865x_read_indirect_reg(dev, 0x05, 0x40); + if (ret == 0) { + LOG_ERR("LAN865x error! Please contact microchip support for replacement."); + return -EIO; + } + + value1 = lan865x_read_indirect_reg(dev, 0x04, 0x1F); + if ((value1 & 0x10) != 0) { /* Convert uint8_t to int8_t */ + offset1 = value1 | 0xE0; + if (offset1 < -5) { + LOG_ERR("LAN865x internal error!"); + return -EIO; + } + } else { + offset1 = value1; + } + + value2 = lan865x_read_indirect_reg(dev, 0x08, 0x1F); + if ((value2 & 0x10) != 0) { /* Convert uint8_t to int8_t */ + offset2 = value2 | 0xE0; + } else { + offset2 = value2; + } + + oa_tc6_reg_read(ctx->tc6, 0x00040084, &val); + value3 = (uint16_t)val; + + oa_tc6_reg_read(ctx->tc6, 0x0004008A, &val); + value4 = (uint16_t)val; + + oa_tc6_reg_read(ctx->tc6, 0x000400AD, &val); + value5 = (uint16_t)val; + + oa_tc6_reg_read(ctx->tc6, 0x000400AE, &val); + value6 = (uint8_t)val; + + oa_tc6_reg_read(ctx->tc6, 0x000400AF, &val); + value7 = (uint8_t)val; + + cfgparam1 = (value3 & 0xF) | (((9 + offset1) << 10) | ((14 + offset1) << 4)); + cfgparam2 = (value4 & 0x3FF) | ((40 + offset2) << 10); + cfgparam3 = (value5 & 0xC0C0) | (((5 + offset1) << 8) | (9 + offset1)); + cfgparam4 = (value6 & 0xC0C0) | (((9 + offset1) << 8) | (14 + offset1)); + cfgparam5 = (value7 & 0xC0C0) | (((17 + offset1) << 8) | (22 + offset1)); + + oa_tc6_reg_write(ctx->tc6, 0x00040084, (uint32_t) cfgparam1); + oa_tc6_reg_write(ctx->tc6, 0x0004008A, (uint32_t) cfgparam2); + oa_tc6_reg_write(ctx->tc6, 0x000400AD, (uint32_t) cfgparam3); + oa_tc6_reg_write(ctx->tc6, 0x000400AE, (uint32_t) cfgparam4); + oa_tc6_reg_write(ctx->tc6, 0x000400AF, (uint32_t) cfgparam5); + + return 0; +} +/* Implementation of pseudo code from AN1760 - END */ + +static int lan865x_config_plca(const struct device *dev, uint8_t node_id, + uint8_t node_cnt, uint8_t burst_cnt, uint8_t burst_timer) +{ + struct lan865x_data *ctx = dev->data; + uint32_t val; + + /* Collision Detection */ + oa_tc6_reg_write(ctx->tc6, 0x00040087, 0x0083u); /* COL_DET_CTRL0 */ + + /* T1S Phy Node Id and Max Node Count */ + val = ((uint32_t)node_cnt << 8) | node_id; + oa_tc6_reg_write(ctx->tc6, 0x0004CA02, val); /* PLCA_CONTROL_1_REGISTER */ + + /* PLCA Burst Count and Burst Timer */ + val = ((uint32_t)burst_cnt << 8) | burst_timer; + oa_tc6_reg_write(ctx->tc6, 0x0004CA05, val); /* PLCA_BURST_MODE_REGISTER */ + + /* Enable PLCA */ + oa_tc6_reg_write(ctx->tc6, 0x0004CA01, BIT(15)); /* PLCA_CONTROL_0_REGISTER */ + + return 0; +} + +static void lan865x_write_macaddress(const struct device *dev) +{ + struct lan865x_data *ctx = dev->data; + uint8_t *mac = &ctx->mac_address[0]; + uint32_t val; + + /* SPEC_ADD2_BOTTOM */ + val = (mac[3] << 24) | (mac[2] << 16) | (mac[1] << 8) | mac[0]; + oa_tc6_reg_write(ctx->tc6, LAN865x_MAC_SAB2, val); + + /* SPEC_ADD2_TOP */ + val = (mac[5] << 8) | mac[4]; + oa_tc6_reg_write(ctx->tc6, LAN865x_MAC_SAT2, val); + + /* SPEC_ADD1_BOTTOM */ + val = (mac[5] << 24) | (mac[4] << 16) | (mac[3] << 8) | mac[2]; + oa_tc6_reg_write(ctx->tc6, LAN865x_MAC_SAB1, val); +} + +static int lan865x_default_config(const struct device *dev, uint8_t silicon_rev) +{ + /* Values in the below table are the same for LAN865x rev. B0 and B1 */ + static const oa_mem_map_t lan865x_conf[] = { + { .address = 0x00010000, .value = 0x00000000 }, + { .address = 0x00040091, .value = 0x00009660 }, + { .address = 0x00040081, .value = 0x00000080 }, + { .address = 0x00010077, .value = 0x00000028 }, + { .address = 0x00040043, .value = 0x000000FF }, + { .address = 0x00040044, .value = 0x0000FFFF }, + { .address = 0x00040045, .value = 0x00000000 }, + { .address = 0x00040053, .value = 0x000000FF }, + { .address = 0x00040054, .value = 0x0000FFFF }, + { .address = 0x00040055, .value = 0x00000000 }, + { .address = 0x00040040, .value = 0x00000002 }, + { .address = 0x00040050, .value = 0x00000002 }, + { .address = 0x000400E9, .value = 0x00009E50 }, + { .address = 0x000400F5, .value = 0x00001CF8 }, + { .address = 0x000400F4, .value = 0x0000C020 }, + { .address = 0x000400F8, .value = 0x00009B00 }, + { .address = 0x000400F9, .value = 0x00004E53 }, + { .address = 0x000400B0, .value = 0x00000103 }, + { .address = 0x000400B1, .value = 0x00000910 }, + { .address = 0x000400B2, .value = 0x00001D26 }, + { .address = 0x000400B3, .value = 0x0000002A }, + { .address = 0x000400B4, .value = 0x00000103 }, + { .address = 0x000400B5, .value = 0x0000070D }, + { .address = 0x000400B6, .value = 0x00001720 }, + { .address = 0x000400B7, .value = 0x00000027 }, + { .address = 0x000400B8, .value = 0x00000509 }, + { .address = 0x000400B9, .value = 0x00000E13 }, + { .address = 0x000400BA, .value = 0x00001C25 }, + { .address = 0x000400BB, .value = 0x0000002B }, + { .address = 0x0000000C, .value = 0x00000100 }, + { .address = 0x00040081, .value = 0x000000E0 }, + }; + const struct lan865x_config *cfg = dev->config; + uint8_t i, size = ARRAY_SIZE(lan865x_conf); + struct lan865x_data *ctx = dev->data; + int ret; + + /* Enable protected control RW */ + oa_tc6_set_protected_ctrl(ctx->tc6, true); + + for (i = 0; i < size; i++) { + oa_tc6_reg_write(ctx->tc6, lan865x_conf[i].address, + lan865x_conf[i].value); + } + + if (silicon_rev == 1) { + /* For silicon rev 1 (B0): (bit [3..0] from 0x0A0084 */ + oa_tc6_reg_write(ctx->tc6, 0x000400D0, 0x5F21); + } + + lan865x_write_macaddress(dev); + + ret = lan865x_init_chip(dev, silicon_rev); + if (ret < 0) + return ret; + + if (cfg->plca_enable) { + ret = lan865x_config_plca(dev, cfg->plca_node_id, + cfg->plca_node_count, + cfg->plca_burst_count, + cfg->plca_burst_timer); + if (ret < 0) { + return ret; + } + } + return 0; +} + +static void lan865x_int_callback(const struct device *dev, + struct gpio_callback *cb, + uint32_t pins) +{ + ARG_UNUSED(dev); + ARG_UNUSED(pins); + + struct lan865x_data *ctx = + CONTAINER_OF(cb, struct lan865x_data, gpio_int_callback); + + k_sem_give(&ctx->int_sem); +} + +static void lan865x_read_chunks(const struct device *dev) +{ + const struct lan865x_config *cfg = dev->config; + struct lan865x_data *ctx = dev->data; + struct oa_tc6 *tc6 = ctx->tc6; + struct net_pkt *pkt; + int ret; + + k_sem_take(&ctx->tx_rx_sem, K_FOREVER); + pkt = net_pkt_rx_alloc(K_MSEC(cfg->timeout)); + if (!pkt) { + LOG_ERR("OA RX: Could not allocate packet!"); + k_sem_give(&ctx->tx_rx_sem); + return; + } + + ret = oa_tc6_read_chunks(tc6, pkt); + k_sem_give(&ctx->tx_rx_sem); + if (ret < 0) { + eth_stats_update_errors_rx(ctx->iface); + net_pkt_unref(pkt); + return; + } + + /* Feed buffer frame to IP stack */ + ret = net_recv_data(ctx->iface, pkt); + if (ret < 0) { + LOG_ERR("OA RX: Could not process packet (%d)!", ret); + net_pkt_unref(pkt); + } +} + +static void lan865x_int_thread(const struct device *dev) +{ + struct lan865x_data *ctx = dev->data; + struct oa_tc6 *tc6 = ctx->tc6; + uint32_t sts, val, ftr; + + while (true) { + k_sem_take(&ctx->int_sem, K_FOREVER); + if (!ctx->reset) { + oa_tc6_reg_read(tc6, OA_STATUS0, &sts); + if (sts & OA_STATUS0_RESETC) { + oa_tc6_reg_write(tc6, OA_STATUS0, sts); + lan865x_default_config(dev, ctx->silicon_rev); + oa_tc6_reg_read(tc6, OA_CONFIG0, &val); + oa_tc6_reg_write(tc6, OA_CONFIG0, OA_CONFIG0_SYNC | val); + lan865x_mac_rxtx_control(dev, LAN865x_MAC_TXRX_ON); + + ctx->reset = true; + /* + * According to OA T1S standard - it is mandatory to + * read chunk of data to get the IRQ_N negated (deasserted). + */ + oa_tc6_read_status(tc6, &ftr); + continue; + } + } + + /* + * The IRQ_N is asserted when RCA becomes > 0, so update its value + * before reading chunks. + */ + oa_tc6_update_buf_info(tc6); + + while (tc6->rca > 0) { + lan865x_read_chunks(dev); + } + + if (tc6->exst) { + /* + * Just clear any pending interrupts - data RX will be served + * earlier. + * The RESETC is handled separately as it requires LAN865x device + * configuration. + */ + oa_tc6_reg_read(tc6, OA_STATUS0, &sts); + if (sts != 0) { + oa_tc6_reg_write(tc6, OA_STATUS0, sts); + } + + oa_tc6_reg_read(tc6, OA_STATUS1, &sts); + if (sts != 0) { + oa_tc6_reg_write(tc6, OA_STATUS1, sts); + } + } + } +} + +static int lan865x_init(const struct device *dev) +{ + const struct lan865x_config *cfg = dev->config; + struct lan865x_data *ctx = dev->data; + int ret; + + __ASSERT(cfg->spi.config.frequency <= LAN865X_SPI_MAX_FREQUENCY, + "SPI frequency exceeds supported maximum\n"); + + if (!spi_is_ready_dt(&cfg->spi)) { + LOG_ERR("SPI bus %s not ready", cfg->spi.bus->name); + return -ENODEV; + } + + if (!gpio_is_ready_dt(&cfg->interrupt)) { + LOG_ERR("Interrupt GPIO device %s is not ready", + cfg->interrupt.port->name); + return -ENODEV; + } + + /* Check SPI communication after reset */ + ret = lan865x_check_spi(dev); + if (ret < 0) { + LOG_ERR("SPI communication not working, %d", ret); + return ret; + } + + /* + * Configure interrupt service routine for LAN865x IRQ + */ + ret = gpio_pin_configure_dt(&cfg->interrupt, GPIO_INPUT); + if (ret < 0) { + LOG_ERR("Failed to configure interrupt GPIO, %d", ret); + return ret; + } + + gpio_init_callback(&(ctx->gpio_int_callback), lan865x_int_callback, + BIT(cfg->interrupt.pin)); + + ret = gpio_add_callback(cfg->interrupt.port, &ctx->gpio_int_callback); + if (ret < 0) { + LOG_ERR("Failed to add INT callback, %d", ret); + return ret; + } + + gpio_pin_interrupt_configure_dt(&cfg->interrupt, GPIO_INT_EDGE_TO_ACTIVE); + + /* Start interruption-poll thread */ + ctx->tid_int = + k_thread_create(&ctx->thread, ctx->thread_stack, + CONFIG_ETH_LAN865X_IRQ_THREAD_STACK_SIZE, + (k_thread_entry_t)lan865x_int_thread, + (void *)dev, NULL, NULL, + K_PRIO_COOP(CONFIG_ETH_LAN865X_IRQ_THREAD_PRIO), + 0, K_NO_WAIT); + k_thread_name_set(ctx->tid_int, "lan865x_interrupt"); + + ctx->reset = false; + + /* Perform HW reset - 'rst-gpios' required property set in DT */ + if (!gpio_is_ready_dt(&cfg->reset)) { + LOG_ERR("Reset GPIO device %s is not ready", + cfg->reset.port->name); + return -ENODEV; + } + + ret = gpio_pin_configure_dt(&cfg->reset, GPIO_OUTPUT_INACTIVE); + if (ret < 0) { + LOG_ERR("Failed to configure reset GPIO, %d", ret); + return ret; + } + + return lan865x_gpio_reset(dev); +} + +static int lan865x_port_send(const struct device *dev, struct net_pkt *pkt) +{ + struct lan865x_data *ctx = dev->data; + struct oa_tc6 *tc6 = ctx->tc6; + int ret; + + k_sem_take(&ctx->tx_rx_sem, K_FOREVER); + ret = oa_tc6_send_chunks(tc6, pkt); + k_sem_give(&ctx->tx_rx_sem); + if (ret < 0) { + LOG_ERR("TX transmission error, %d", ret); + eth_stats_update_errors_tx(net_pkt_iface(pkt)); + return ret; + } + + return 0; +} + +static const struct ethernet_api lan865x_api_func = { + .iface_api.init = lan865x_iface_init, + .get_capabilities = lan865x_port_get_capabilities, + .set_config = lan865x_set_config, + .send = lan865x_port_send, +}; + +#define LAN865X_DEFINE(inst) \ + static const struct lan865x_config lan865x_config_##inst = { \ + .spi = SPI_DT_SPEC_INST_GET(inst, SPI_WORD_SET(8), 0), \ + .interrupt = GPIO_DT_SPEC_INST_GET(inst, int_gpios), \ + .reset = GPIO_DT_SPEC_INST_GET(inst, rst_gpios), \ + .timeout = CONFIG_ETH_LAN865X_TIMEOUT, \ + .plca_node_id = DT_INST_PROP(inst, plca_node_id), \ + .plca_node_count = DT_INST_PROP(inst, plca_node_count), \ + .plca_burst_count = DT_INST_PROP(inst, plca_burst_count), \ + .plca_burst_timer = DT_INST_PROP(inst, plca_burst_timer), \ + .plca_to_timer = DT_INST_PROP(inst, plca_to_timer), \ + .plca_enable = DT_INST_PROP(inst, plca_enable), \ + }; \ + \ + struct oa_tc6 oa_tc6_##inst = { \ + .cps = 64, \ + .protected = 0, \ + .spi = &lan865x_config_##inst.spi \ + }; \ + static struct lan865x_data lan865x_data_##inst = { \ + .mac_address = DT_INST_PROP(inst, local_mac_address), \ + .tx_rx_sem = \ + Z_SEM_INITIALIZER((lan865x_data_##inst).tx_rx_sem, 1, UINT_MAX), \ + .int_sem = Z_SEM_INITIALIZER((lan865x_data_##inst).int_sem, 0, UINT_MAX), \ + .tc6 = &oa_tc6_##inst \ + }; \ + \ + ETH_NET_DEVICE_DT_INST_DEFINE(inst, lan865x_init, NULL, &lan865x_data_##inst, \ + &lan865x_config_##inst, CONFIG_ETH_INIT_PRIORITY, \ + &lan865x_api_func, NET_ETH_MTU); + +DT_INST_FOREACH_STATUS_OKAY(LAN865X_DEFINE); diff --git a/drivers/ethernet/eth_lan865x_priv.h b/drivers/ethernet/eth_lan865x_priv.h new file mode 100644 index 00000000000..fa4af1a949a --- /dev/null +++ b/drivers/ethernet/eth_lan865x_priv.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023 DENX Software Engineering GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ETH_LAN865X_PRIV_H__ +#define ETH_LAN865X_PRIV_H__ + +#include +#include +#include +#include +#include +#include +#include +#include "oa_tc6.h" + +#define LAN865X_SPI_MAX_FREQUENCY 25000000U +#define LAN865X_HW_BOOT_DELAY_MS 7 +#define LAN8650_DEVID 0x8650 +#define LAN8651_DEVID 0x8651 +#define LAN865X_REV_MASK GENMASK(3, 0) +#define LAN865X_RESET_TIMEOUT 10 + +/* Memory Map Sector (MMS) 1 (0x1) */ +#define LAN865x_MAC_NCR MMS_REG(0x1, 0x000) +#define LAN865x_MAC_NCR_TXEN BIT(3) +#define LAN865x_MAC_NCR_RXEN BIT(2) +#define LAN865x_MAC_NCFGR MMS_REG(0x1, 0x001) +#define LAN865x_MAC_NCFGR_CAF BIT(4) +#define LAN865x_MAC_SAB1 MMS_REG(0x1, 0x022) +#define LAN865x_MAC_SAB2 MMS_REG(0x1, 0x024) +#define LAN865x_MAC_SAT2 MMS_REG(0x1, 0x025) + +#define LAN865x_MAC_TXRX_ON 1 +#define LAN865x_MAC_TXRX_OFF 0 + +/* Memory Map Sector (MMS) 10 (0xA) */ +#define LAN865x_DEVID MMS_REG(0xA, 0x094) + +struct lan865x_config { + struct spi_dt_spec spi; + struct gpio_dt_spec interrupt; + struct gpio_dt_spec reset; + int32_t timeout; + + /* PLCA */ + bool plca_enable : 1; /* 1 - PLCA enable, 0 - CSMA/CD enable */ + uint8_t plca_node_id /* PLCA node id range: 0 to 254 */; + uint8_t plca_node_count; /* PLCA node count range: 1 to 255 */ + uint8_t plca_burst_count; /* PLCA burst count range: 0x0 to 0xFF */ + uint8_t plca_burst_timer; /* PLCA burst timer */ + uint8_t plca_to_timer; /* PLCA TO value */ + + /* MAC */ + bool tx_cut_through_mode; /* 1 - tx cut through, 0 - Store and forward */ + bool rx_cut_through_mode; /* 1 - rx cut through, 0 - Store and forward */ +}; + +struct lan865x_data { + struct net_if *iface; + struct gpio_callback gpio_int_callback; + struct k_sem tx_rx_sem; + struct k_sem int_sem; + struct oa_tc6 *tc6; + uint16_t chip_id; + uint8_t silicon_rev; + uint8_t mac_address[6]; + bool iface_initialized; + bool reset; + + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_ETH_LAN865X_IRQ_THREAD_STACK_SIZE); + struct k_thread thread; + k_tid_t tid_int; +}; + +#endif /* ETH_LAN865X_PRIV_H__ */ diff --git a/drivers/ethernet/eth_mcux.c b/drivers/ethernet/eth_mcux.c index a03922ccd78..f9ab95db9aa 100644 --- a/drivers/ethernet/eth_mcux.c +++ b/drivers/ethernet/eth_mcux.c @@ -1042,6 +1042,8 @@ static void eth_mcux_init(const struct device *dev) enet_config.interrupt |= kENET_MiiInterrupt; #endif enet_config.miiMode = kENET_RmiiMode; + enet_config.callback = eth_callback; + enet_config.userData = context; if (IS_ENABLED(CONFIG_ETH_MCUX_PROMISCUOUS_MODE)) { enet_config.macSpecialConfig |= kENET_ControlPromiscuousEnable; @@ -1098,7 +1100,6 @@ static void eth_mcux_init(const struct device *dev) /* Enable reclaim of tx descriptors that will have the tx timestamp */ ENET_SetTxReclaim(&context->enet_handle, true, 0); #endif - ENET_SetCallback(&context->enet_handle, eth_callback, context); eth_mcux_phy_start(context); } @@ -1162,7 +1163,6 @@ static int eth_init(const struct device *dev) return 0; } -#if defined(CONFIG_NET_IPV6) static void net_if_mcast_cb(struct net_if *iface, const struct net_addr *addr, bool is_joined) @@ -1171,30 +1171,29 @@ static void net_if_mcast_cb(struct net_if *iface, struct eth_context *context = dev->data; struct net_eth_addr mac_addr; - if (addr->family != AF_INET6) { + if (IS_ENABLED(CONFIG_NET_IPV4) && addr->family == AF_INET) { + net_eth_ipv4_mcast_to_mac_addr(&addr->in_addr, &mac_addr); + } else if (IS_ENABLED(CONFIG_NET_IPV6) && addr->family == AF_INET6) { + net_eth_ipv6_mcast_to_mac_addr(&addr->in6_addr, &mac_addr); + } else { return; } - net_eth_ipv6_mcast_to_mac_addr(&addr->in6_addr, &mac_addr); - if (is_joined) { ENET_AddMulticastGroup(context->base, mac_addr.addr); } else { ENET_LeaveMulticastGroup(context->base, mac_addr.addr); } } -#endif /* CONFIG_NET_IPV6 */ static void eth_iface_init(struct net_if *iface) { const struct device *dev = net_if_get_device(iface); struct eth_context *context = dev->data; -#if defined(CONFIG_NET_IPV6) static struct net_if_mcast_monitor mon; net_if_mcast_mon_register(&mon, iface, net_if_mcast_cb); -#endif /* CONFIG_NET_IPV6 */ net_if_set_link_addr(iface, context->mac_addr, sizeof(context->mac_addr), diff --git a/drivers/ethernet/eth_native_posix.c b/drivers/ethernet/eth_native_posix.c index 874077b61a1..4c0a9b0a7f1 100644 --- a/drivers/ethernet/eth_native_posix.c +++ b/drivers/ethernet/eth_native_posix.c @@ -153,7 +153,7 @@ static void update_gptp(struct net_if *iface, struct net_pkt *pkt, struct gptp_hdr *hdr; int ret; - ret = eth_clock_gettime(×tamp); + ret = eth_clock_gettime(×tamp.second, ×tamp.nanosecond); if (ret < 0) { return; } @@ -364,8 +364,12 @@ static int read_data(struct eth_context *ctx, int fd) return 0; } -static void eth_rx(struct eth_context *ctx) +static void eth_rx(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct eth_context *ctx = p1; LOG_DBG("Starting ZETH RX thread"); while (1) { @@ -391,7 +395,7 @@ static void create_rx_handler(struct eth_context *ctx) k_thread_create(ctx->rx_thread, ctx->rx_stack, ctx->rx_stack_size, - (k_thread_entry_t)eth_rx, + eth_rx, ctx, NULL, NULL, K_PRIO_COOP(14), 0, K_NO_WAIT); @@ -460,7 +464,7 @@ static void eth_iface_init(struct net_if *iface) * change the documentation etc. and break things. */ if (CONFIG_ETH_NATIVE_POSIX_INTERFACE_COUNT == 1) { - ctx->if_name = ETH_NATIVE_POSIX_DRV_NAME; + ctx->if_name = CONFIG_ETH_NATIVE_POSIX_DRV_NAME; } LOG_DBG("Interface %p using \"%s\"", iface, ctx->if_name); @@ -468,16 +472,12 @@ static void eth_iface_init(struct net_if *iface) net_if_set_link_addr(iface, ll_addr->addr, ll_addr->len, NET_LINK_ETHERNET); - ctx->dev_fd = eth_iface_create(ctx->if_name, false); + ctx->dev_fd = eth_iface_create(CONFIG_ETH_NATIVE_POSIX_DEV_NAME, ctx->if_name, false); if (ctx->dev_fd < 0) { LOG_ERR("Cannot create %s (%d)", ctx->if_name, -errno); } else { /* Create a thread that will handle incoming data from host */ create_rx_handler(ctx); - - eth_setup_host(ctx->if_name); - - eth_start_script(ctx->if_name); } } @@ -573,36 +573,11 @@ static int vlan_setup(const struct device *dev, struct net_if *iface, } #endif /* CONFIG_NET_VLAN */ -static int eth_start_device(const struct device *dev) -{ - struct eth_context *context = dev->data; - int ret; - - context->status = true; - - ret = eth_if_up(context->if_name); - - eth_setup_host(context->if_name); - - return ret; -} - -static int eth_stop_device(const struct device *dev) -{ - struct eth_context *context = dev->data; - - context->status = false; - - return eth_if_down(context->if_name); -} - static const struct ethernet_api eth_if_api = { .iface_api.init = eth_iface_init, .get_capabilities = eth_posix_native_get_capabilities, .set_config = set_config, - .start = eth_start_device, - .stop = eth_stop_device, .send = eth_send, #if defined(CONFIG_NET_VLAN) @@ -671,7 +646,7 @@ static int ptp_clock_get_native_posix(const struct device *clk, { ARG_UNUSED(clk); - return eth_clock_gettime(tm); + return eth_clock_gettime(&tm->second, &tm->nanosecond); } static int ptp_clock_adjust_native_posix(const struct device *clk, diff --git a/drivers/ethernet/eth_native_posix_adapt.c b/drivers/ethernet/eth_native_posix_adapt.c index 14f73d6916a..7e3864910dc 100644 --- a/drivers/ethernet/eth_native_posix_adapt.c +++ b/drivers/ethernet/eth_native_posix_adapt.c @@ -25,39 +25,25 @@ #include #include #include -#include +#include +#include #ifdef __linux +#include #include #endif -/* Zephyr include files. Be very careful here and only include minimum - * things needed. - */ -#define LOG_MODULE_NAME eth_posix_adapt -#define LOG_LEVEL CONFIG_ETHERNET_LOG_LEVEL - -#include -LOG_MODULE_REGISTER(LOG_MODULE_NAME); - -#include -#include - -#if defined(CONFIG_NET_GPTP) -#include -#endif - #include "eth_native_posix_priv.h" /* Note that we cannot create the TUN/TAP device from the setup script * as we need to get a file descriptor to communicate with the interface. */ -int eth_iface_create(const char *if_name, bool tun_only) +int eth_iface_create(const char *dev_name, const char *if_name, bool tun_only) { struct ifreq ifr; int fd, ret = -EINVAL; - fd = open(ETH_NATIVE_POSIX_DEV_NAME, O_RDWR); + fd = open(dev_name, O_RDWR); if (fd < 0) { return -errno; } @@ -98,48 +84,13 @@ static int ssystem(const char *fmt, ...) vsnprintf(cmd, sizeof(cmd), fmt, ap); va_end(ap); - posix_print_trace("%s\n", cmd); + nsi_print_trace("%s\n", cmd); ret = system(cmd); return -WEXITSTATUS(ret); } -int eth_setup_host(const char *if_name) -{ - if (!IS_ENABLED(CONFIG_ETH_NATIVE_POSIX_STARTUP_AUTOMATIC)) { - return 0; - } - - /* User might have added -i option to setup script string, so - * check that situation in the script itself so that the -i option - * we add here is ignored in that case. - */ - return ssystem("%s -i %s", ETH_NATIVE_POSIX_SETUP_SCRIPT, - if_name); -} - -int eth_start_script(const char *if_name) -{ - if (!IS_ENABLED(CONFIG_ETH_NATIVE_POSIX_STARTUP_AUTOMATIC)) { - return 0; - } - - if (ETH_NATIVE_POSIX_STARTUP_SCRIPT[0] == '\0') { - return 0; - } - - if (ETH_NATIVE_POSIX_STARTUP_SCRIPT_USER[0] == '\0') { - return ssystem("%s %s", ETH_NATIVE_POSIX_STARTUP_SCRIPT, - if_name); - } else { - return ssystem("sudo -u %s %s %s", - ETH_NATIVE_POSIX_STARTUP_SCRIPT_USER, - ETH_NATIVE_POSIX_STARTUP_SCRIPT, - if_name); - } -} - int eth_wait_data(int fd) { struct timeval timeout; @@ -175,8 +126,7 @@ ssize_t eth_write_data(int fd, void *buf, size_t buf_len) return write(fd, buf, buf_len); } -#if defined(CONFIG_NET_GPTP) -int eth_clock_gettime(struct net_ptp_time *time) +int eth_clock_gettime(uint64_t *second, uint32_t *nanosecond) { struct timespec tp; int ret; @@ -186,44 +136,14 @@ int eth_clock_gettime(struct net_ptp_time *time) return -errno; } - time->second = tp.tv_sec; - time->nanosecond = tp.tv_nsec; + *second = (uint64_t)tp.tv_sec; + *nanosecond = (uint32_t)tp.tv_nsec; return 0; } -#endif /* CONFIG_NET_GPTP */ -#if defined(CONFIG_NET_PROMISCUOUS_MODE) int eth_promisc_mode(const char *if_name, bool enable) { - if (!IS_ENABLED(CONFIG_ETH_NATIVE_POSIX_STARTUP_AUTOMATIC)) { - return 0; - } - return ssystem("ip link set dev %s promisc %s", if_name, enable ? "on" : "off"); } -#endif /* CONFIG_NET_PROMISCUOUS_MODE */ - -/* If we have enabled manual setup, then interface cannot be - * taken up or down by the driver as we normally do not have - * enough permissions. - */ - -int eth_if_up(const char *if_name) -{ - if (!IS_ENABLED(CONFIG_ETH_NATIVE_POSIX_STARTUP_AUTOMATIC)) { - return 0; - } - - return ssystem("ip link set dev %s up", if_name); -} - -int eth_if_down(const char *if_name) -{ - if (!IS_ENABLED(CONFIG_ETH_NATIVE_POSIX_STARTUP_AUTOMATIC)) { - return 0; - } - - return ssystem("ip link set dev %s down", if_name); -} diff --git a/drivers/ethernet/eth_native_posix_priv.h b/drivers/ethernet/eth_native_posix_priv.h index 2d925fd83dc..7ce8c19f67a 100644 --- a/drivers/ethernet/eth_native_posix_priv.h +++ b/drivers/ethernet/eth_native_posix_priv.h @@ -11,44 +11,12 @@ #ifndef ZEPHYR_DRIVERS_ETHERNET_ETH_NATIVE_POSIX_PRIV_H_ #define ZEPHYR_DRIVERS_ETHERNET_ETH_NATIVE_POSIX_PRIV_H_ -#define ETH_NATIVE_POSIX_DRV_NAME CONFIG_ETH_NATIVE_POSIX_DRV_NAME -#define ETH_NATIVE_POSIX_DEV_NAME CONFIG_ETH_NATIVE_POSIX_DEV_NAME - -#if defined(CONFIG_ETH_NATIVE_POSIX_STARTUP_AUTOMATIC) -#define ETH_NATIVE_POSIX_SETUP_SCRIPT CONFIG_ETH_NATIVE_POSIX_SETUP_SCRIPT -#define ETH_NATIVE_POSIX_STARTUP_SCRIPT CONFIG_ETH_NATIVE_POSIX_STARTUP_SCRIPT -#define ETH_NATIVE_POSIX_STARTUP_SCRIPT_USER \ - CONFIG_ETH_NATIVE_POSIX_STARTUP_SCRIPT_USER -#else -#define ETH_NATIVE_POSIX_SETUP_SCRIPT "" -#define ETH_NATIVE_POSIX_STARTUP_SCRIPT "" -#define ETH_NATIVE_POSIX_STARTUP_SCRIPT_USER "" -#endif - -int eth_iface_create(const char *if_name, bool tun_only); +int eth_iface_create(const char *dev_name, const char *if_name, bool tun_only); int eth_iface_remove(int fd); -int eth_setup_host(const char *if_name); -int eth_start_script(const char *if_name); int eth_wait_data(int fd); ssize_t eth_read_data(int fd, void *buf, size_t buf_len); ssize_t eth_write_data(int fd, void *buf, size_t buf_len); -int eth_if_up(const char *if_name); -int eth_if_down(const char *if_name); - -#if defined(CONFIG_NET_GPTP) -int eth_clock_gettime(struct net_ptp_time *time); -#endif - -#if defined(CONFIG_NET_PROMISCUOUS_MODE) +int eth_clock_gettime(uint64_t *second, uint32_t *nanosecond); int eth_promisc_mode(const char *if_name, bool enable); -#else -static inline int eth_promisc_mode(const char *if_name, bool enable) -{ - ARG_UNUSED(if_name); - ARG_UNUSED(enable); - - return -ENOTSUP; -} -#endif #endif /* ZEPHYR_DRIVERS_ETHERNET_ETH_NATIVE_POSIX_PRIV_H_ */ diff --git a/drivers/ethernet/eth_numaker.c b/drivers/ethernet/eth_numaker.c new file mode 100644 index 00000000000..77577943f23 --- /dev/null +++ b/drivers/ethernet/eth_numaker.c @@ -0,0 +1,790 @@ +/* + * Copyright (c) 2023 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nuvoton_numaker_ethernet + +#include +#include +#include +#include +#include +#include +#include +#include "eth_numaker_priv.h" +#include "ethernet/eth_stats.h" +#include +#include +#include + +#ifdef CONFIG_SOC_M467 +#include +#endif + +LOG_MODULE_REGISTER(eth_numaker, CONFIG_ETHERNET_LOG_LEVEL); + +/* Device EMAC Interface port */ +#define NUMAKER_GMAC_INTF 0 +/* 2KB Data Flash at 0xFF800 */ +#define NUMAKER_DATA_FLASH (0xFF800U) +#define NUMAKER_MASK_32 (0xFFFFFFFFU) +#define NUMAKER_MII_CONFIG (ADVERTISE_CSMA | ADVERTISE_10HALF | ADVERTISE_10FULL | \ + ADVERTISE_100HALF | ADVERTISE_100FULL) +#define NUMAKER_MII_LINKED (BMSR_ANEGCOMPLETE | BMSR_LSTATUS) + +extern synopGMACdevice GMACdev[GMAC_CNT]; +extern struct sk_buff tx_buf[GMAC_CNT][TRANSMIT_DESC_SIZE]; +extern struct sk_buff rx_buf[GMAC_CNT][RECEIVE_DESC_SIZE]; + +static uint32_t eth_phy_addr; + +/* Device config */ +struct eth_numaker_config { + uint32_t gmac_base; + const struct reset_dt_spec reset; + uint32_t phy_addr; + uint32_t clk_modidx; + uint32_t clk_src; + uint32_t clk_div; + const struct device *clk_dev; + const struct pinctrl_dev_config *pincfg; +}; + +/* Driver context/data */ +struct eth_numaker_data { + synopGMACdevice *gmacdev; + struct net_if *iface; + uint8_t mac_addr[NU_HWADDR_SIZE]; + struct k_mutex tx_frame_buf_mutex; + struct k_spinlock rx_frame_buf_lock; +}; + +/* Delay execution for given amount of ticks for SDK-HAL */ +void plat_delay(uint32_t delay) +{ + uint32_t us_cnt = k_ticks_to_us_floor32((uint64_t)delay); + + k_busy_wait(us_cnt); +} + +static void mdio_write(synopGMACdevice *gmacdev, uint32_t addr, uint32_t reg, int data) +{ + synopGMAC_write_phy_reg((u32 *)gmacdev->MacBase, addr, reg, data); +} + +static int mdio_read(synopGMACdevice *gmacdev, uint32_t addr, uint32_t reg) +{ + uint16_t data; + + synopGMAC_read_phy_reg((u32 *)gmacdev->MacBase, addr, reg, &data); + return data; +} + +static int numaker_eth_link_ok(synopGMACdevice *gmacdev) +{ + /* first, a dummy read to latch */ + mdio_read(gmacdev, eth_phy_addr, MII_BMSR); + if (mdio_read(gmacdev, eth_phy_addr, MII_BMSR) & BMSR_LSTATUS) { + return 1; + } + return 0; +} + +static int reset_phy(synopGMACdevice *gmacdev) +{ + uint16_t reg; + uint32_t delay_us; + bool ret; + + mdio_write(gmacdev, eth_phy_addr, MII_BMCR, BMCR_RESET); + + delay_us = 200000U; + ret = WAIT_FOR(!(mdio_read(gmacdev, eth_phy_addr, MII_BMCR) & BMCR_RESET), + delay_us, k_msleep(1)); + if (ret == false) { + LOG_DBG("Reset phy failed"); + return -EIO; + } + + LOG_INF("PHY ID 1:0x%x", mdio_read(gmacdev, eth_phy_addr, MII_PHYSID1)); + LOG_INF("PHY ID 2:0x%x", mdio_read(gmacdev, eth_phy_addr, MII_PHYSID2)); + delay_us = 3000000U; + ret = WAIT_FOR(numaker_eth_link_ok(gmacdev), delay_us, k_msleep(1)); + if (ret) { + gmacdev->LinkState = LINKUP; + LOG_DBG("Link Up"); + } else { + gmacdev->LinkState = LINKDOWN; + LOG_DBG("Link Down"); + return -EIO; + } + + mdio_write(gmacdev, eth_phy_addr, MII_ADVERTISE, NUMAKER_MII_CONFIG); + reg = mdio_read(gmacdev, eth_phy_addr, MII_BMCR); + mdio_write(gmacdev, eth_phy_addr, MII_BMCR, reg | BMCR_ANRESTART); + delay_us = 3000000U; + ret = WAIT_FOR((mdio_read(gmacdev, eth_phy_addr, MII_BMSR) & + NUMAKER_MII_LINKED) == NUMAKER_MII_LINKED, + delay_us, k_msleep(1)); + if (ret == false) { + LOG_DBG("AN failed. Set to 100 FULL"); + synopGMAC_set_full_duplex(gmacdev); + synopGMAC_set_mode(NUMAKER_GMAC_INTF, 1); /* Set mode 1: 100Mbps; 2: 10Mbps */ + return -EIO; + } + + reg = mdio_read(gmacdev, eth_phy_addr, MII_LPA); + if (reg & ADVERTISE_100FULL) { + LOG_DBG("100 full"); + gmacdev->DuplexMode = FULLDUPLEX; + gmacdev->Speed = SPEED100; + synopGMAC_set_full_duplex(gmacdev); + synopGMAC_set_mode(NUMAKER_GMAC_INTF, 1); /* Set mode 1: 100Mbps; 2: 10Mbps */ + } else if (reg & ADVERTISE_100HALF) { + LOG_DBG("100 half"); + gmacdev->DuplexMode = HALFDUPLEX; + gmacdev->Speed = SPEED100; + synopGMAC_set_half_duplex(gmacdev); + synopGMAC_set_mode(NUMAKER_GMAC_INTF, 1); /* Set mode 1: 100Mbps; 2: 10Mbps */ + } else if (reg & ADVERTISE_10FULL) { + LOG_DBG("10 full"); + gmacdev->DuplexMode = FULLDUPLEX; + gmacdev->Speed = SPEED10; + synopGMAC_set_full_duplex(gmacdev); + synopGMAC_set_mode(NUMAKER_GMAC_INTF, 2); /* Set mode 1: 100Mbps; 2: 10Mbps */ + } else { + LOG_DBG("10 half"); + gmacdev->DuplexMode = HALFDUPLEX; + gmacdev->Speed = SPEED10; + synopGMAC_set_half_duplex(gmacdev); + synopGMAC_set_mode(NUMAKER_GMAC_INTF, 2); /* Set mode 1: 100Mbps; 2: 10Mbps */ + } + + return 0; +} + +static void m_numaker_read_mac_addr(char *mac) +{ + uint32_t uid1; + /* Fetch word 0 of data flash */ + uint32_t word0 = *(uint32_t *)(NUMAKER_DATA_FLASH + 0x04U); + /* + * Fetch word 1 of data flash + * we only want bottom 16 bits of word1 (MAC bits 32-47) + * and bit 9 forced to 1, bit 8 forced to 0 + * Locally administered MAC, reduced conflicts + * http://en.wikipedia.org/wiki/MAC_address + */ + uint32_t word1 = *(uint32_t *)NUMAKER_DATA_FLASH; + + /* Not burn any mac address at the beginning of data flash */ + if (word0 == NUMAKER_MASK_32) { + /* Generate a semi-unique MAC address from the UUID */ + SYS_UnlockReg(); + /* Enable FMC ISP function */ + FMC_Open(); + uid1 = FMC_ReadUID(1); + word1 = (uid1 & 0x003FFFFF) | ((uid1 & 0x030000) << 6) >> 8; + word0 = ((FMC_ReadUID(0) >> 4) << 20) | ((uid1 & 0xFF) << 12) | + (FMC_ReadUID(2) & 0xFFF); + /* Disable FMC ISP function */ + FMC_Close(); + /* Lock protected registers */ + SYS_LockReg(); + } + + word1 |= 0x00000200; + word1 &= 0x0000FEFF; + + mac[0] = (word1 & 0x0000ff00) >> 8; + mac[1] = (word1 & 0x000000ff); + mac[2] = (word0 & 0xff000000) >> 24; + mac[3] = (word0 & 0x00ff0000) >> 16; + mac[4] = (word0 & 0x0000ff00) >> 8; + mac[5] = (word0 & 0x000000ff); + + LOG_INF("mac address %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], + mac[4], mac[5]); +} + +static void m_numaker_gmacdev_enable(synopGMACdevice *gmacdev) +{ + + synopGMAC_clear_interrupt(gmacdev); + + /* Enable INT & TX/RX */ + synopGMAC_enable_interrupt(gmacdev, DmaIntEnable); + synopGMAC_enable_dma_rx(gmacdev); + synopGMAC_enable_dma_tx(gmacdev); + + synopGMAC_tx_enable(gmacdev); + synopGMAC_rx_enable(gmacdev); +} + +static int m_numaker_gmacdev_init(synopGMACdevice *gmacdev, uint8_t *mac_addr, uint32_t gmac_base) +{ + int status; + int i; + uint32_t offload_needed = 0; + struct sk_buff *skb; + + LOG_DBG(""); + + /*Attach the device to MAC struct This will configure all the required base + * addresses such as Mac base, configuration base, phy base address(out of 32 + * possible phys ) + */ + synopGMAC_attach(gmacdev, gmac_base + MACBASE, gmac_base + DMABASE, DEFAULT_PHY_BASE); + synopGMAC_disable_interrupt_all(gmacdev); + + /* Reset MAC */ + synopGMAC_reset(gmacdev); + gmacdev->Intf = NUMAKER_GMAC_INTF; + synopGMAC_read_version(gmacdev); + + /* Check for Phy initialization */ + synopGMAC_set_mdc_clk_div(gmacdev, GmiiCsrClk5); + gmacdev->ClockDivMdc = synopGMAC_get_mdc_clk_div(gmacdev); + + /* Reset PHY */ + status = reset_phy(gmacdev); + + /* Set up the tx and rx descriptor queue/ring */ + synopGMAC_setup_tx_desc_queue(gmacdev, TRANSMIT_DESC_SIZE, RINGMODE); + synopGMAC_init_tx_desc_base(gmacdev); + + synopGMAC_setup_rx_desc_queue(gmacdev, RECEIVE_DESC_SIZE, RINGMODE); + synopGMAC_init_rx_desc_base(gmacdev); + + /* Initialize the dma interface */ + synopGMAC_dma_bus_mode_init(gmacdev, + DmaBurstLength32 | DmaDescriptorSkip0 | DmaDescriptor8Words); + synopGMAC_dma_control_init(gmacdev, + DmaStoreAndForward | DmaTxSecondFrame | DmaRxThreshCtrl128); + + /* Initialize the mac interface */ + synopGMAC_mac_init(gmacdev); + synopGMAC_promisc_enable(gmacdev); + + /* This enables the pause control in Full duplex mode of operation */ + synopGMAC_pause_control(gmacdev); + +#if defined(NU_USING_HW_CHECKSUM) + /*IPC Checksum offloading is enabled for this driver. Should only be used if + * Full Ip checksumm offload engine is configured in the hardware + */ + offload_needed = 1; + + /* Enable the offload engine in the receive path */ + synopGMAC_enable_rx_chksum_offload(gmacdev); + + /* Default configuration, DMA drops the packets if error in encapsulated ethernet payload */ + synopGMAC_rx_tcpip_chksum_drop_enable(gmacdev); +#endif + + for (i = 0; i < RECEIVE_DESC_SIZE; i++) { + skb = &rx_buf[NUMAKER_GMAC_INTF][i]; + synopGMAC_set_rx_qptr(gmacdev, (u32)((u64)(skb->data) & NUMAKER_MASK_32), + sizeof(skb->data), (u32)((u64)skb & NUMAKER_MASK_32)); + } + + for (i = 0; i < TRANSMIT_DESC_SIZE; i++) { + skb = &tx_buf[NUMAKER_GMAC_INTF][i]; + synopGMAC_set_tx_qptr(gmacdev, (u32)((u64)(skb->data) & NUMAKER_MASK_32), + sizeof(skb->data), (u32)((u64)skb & NUMAKER_MASK_32), + offload_needed, 0); + } + + synopGMAC_set_mac_address(NUMAKER_GMAC_INTF, mac_addr); + synopGMAC_clear_interrupt(gmacdev); + + return status; +} + +static int m_numaker_gmacdev_get_rx_buf(synopGMACdevice *gmacdev, uint16_t *len, uint8_t **buf) +{ + DmaDesc *rxdesc = gmacdev->RxBusyDesc; + + LOG_DBG("start"); + if (synopGMAC_is_desc_owned_by_dma(rxdesc)) { + return -EIO; + } + if (synopGMAC_is_desc_empty(rxdesc)) { + return -EIO; + } + + *len = synop_handle_received_data(NUMAKER_GMAC_INTF, buf); + if (*len <= 0) { + synopGMAC_enable_interrupt(gmacdev, DmaIntEnable); + return -ENOSPC; /* No available RX frame */ + } + + /* length of payload should be <= 1514 */ + if (*len > (NU_ETH_MAX_FLEN - 4)) { + LOG_DBG("unexpected long packet length=%d, buf=0x%x", *len, (uint32_t)*buf); + *len = 0; /* Skip this unexpected long packet */ + } + + LOG_DBG("end"); + return 0; +} + +static void m_numaker_gmacdev_rx_next(synopGMACdevice *gmacdev) +{ + LOG_DBG("RX Next"); + /* Already did in synop_handle_received_data + * No-op at this stage + * DmaDesc * rxdesc = (gmacdev->RxBusyDesc - 1); + * rxdesc->status = DescOwnByDma; + */ +} + +static void m_numaker_gmacdev_trigger_rx(synopGMACdevice *gmacdev) +{ + LOG_DBG("start"); + + /* Enable the interrupt */ + synopGMAC_enable_interrupt(gmacdev, DmaIntEnable); + + /* Trigger RX DMA */ + synopGMAC_enable_dma_rx(gmacdev); + synopGMAC_resume_dma_rx(gmacdev); + LOG_DBG("resume RX DMA"); + LOG_DBG("end"); +} + +static void m_numaker_gmacdev_packet_rx(const struct device *dev) +{ + struct eth_numaker_data *data = dev->data; + synopGMACdevice *gmacdev = data->gmacdev; + uint8_t *buffer; + uint16_t len; + struct net_pkt *pkt; + k_spinlock_key_t key; + int res; + + /* Get exclusive access, use spin-lock instead of mutex in ISR */ + key = k_spin_lock(&data->rx_frame_buf_lock); + + /* Two approach: 1. recv all RX packets in one time. + * 2. recv one RX and set pending interrupt for rx-next. + */ + while (1) { + /* get received frame */ + if (m_numaker_gmacdev_get_rx_buf(gmacdev, &len, &buffer) != 0) { + break; + } + + if (len == 0) { + LOG_WRN("No available RX frame"); + break; + } + /* Allocate a memory buffer chain from buffer pool + * Using root iface. It will be updated in net_recv_data() + */ + pkt = net_pkt_rx_alloc_with_buffer(data->iface, len, AF_UNSPEC, 0, K_NO_WAIT); + if (!pkt) { + LOG_ERR("pkt alloc frame-len=%d failed", len); + goto next; + } + + LOG_DBG("length=%d, pkt=0x%x", len, (uint32_t)pkt); + /* deliver RX packet to upper layer, pack as one net_pkt */ + if (net_pkt_write(pkt, buffer, len)) { + LOG_ERR("Unable to write RX frame into the pkt"); + net_pkt_unref(pkt); + goto error; + } + + if (pkt != NULL) { + res = net_recv_data(data->iface, pkt); + if (res < 0) { + LOG_ERR("net_recv_data: %d", res); + net_pkt_unref(pkt); + goto error; + } + } +next: + m_numaker_gmacdev_rx_next(gmacdev); + } + m_numaker_gmacdev_trigger_rx(gmacdev); + +error: + k_spin_unlock(&data->rx_frame_buf_lock, key); +} + +static uint8_t *m_numaker_gmacdev_get_tx_buf(synopGMACdevice *gmacdev) +{ + DmaDesc *txdesc = gmacdev->TxNextDesc; + + if (!synopGMAC_is_desc_empty(txdesc)) { + return NULL; + } + + if (synopGMAC_is_desc_owned_by_dma(txdesc)) { + return NULL; + } + + return (uint8_t *)(txdesc->buffer1); +} + +static void m_numaker_gmacdev_trigger_tx(synopGMACdevice *gmacdev, uint16_t length) +{ + DmaDesc *txdesc = gmacdev->TxNextDesc; + uint32_t txnext = gmacdev->TxNext; + bool offload_needed = IS_ENABLED(NU_USING_HW_CHECKSUM); + + /* busy tx descriptor is incremented by one as it will be handed over to DMA */ + (gmacdev->BusyTxDesc)++; + + txdesc->length |= ((length << DescSize1Shift) & DescSize1Mask); + txdesc->status |= (DescTxFirst | DescTxLast | DescTxIntEnable); + if (offload_needed) { + /* + * Make sure that the OS you are running supports the IP and TCP checksum + * offloading, before calling any of the functions given below. + */ + synopGMAC_tx_checksum_offload_tcp_pseudo(gmacdev, txdesc); + } else { + synopGMAC_tx_checksum_offload_bypass(gmacdev, txdesc); + } + __DSB(); + txdesc->status |= DescOwnByDma; + + gmacdev->TxNext = synopGMAC_is_last_tx_desc(gmacdev, txdesc) ? 0 : txnext + 1; + gmacdev->TxNextDesc = + synopGMAC_is_last_tx_desc(gmacdev, txdesc) ? gmacdev->TxDesc : (txdesc + 1); + + /* Enable the interrupt */ + synopGMAC_enable_interrupt(gmacdev, DmaIntEnable); + /* Trigger TX DMA */ + synopGMAC_resume_dma_tx(gmacdev); +} + +static int numaker_eth_tx(const struct device *dev, struct net_pkt *pkt) +{ + struct eth_numaker_data *data = dev->data; + synopGMACdevice *gmacdev = data->gmacdev; + uint16_t total_len = net_pkt_get_len(pkt); + uint8_t *buffer; + + /* Get exclusive access */ + k_mutex_lock(&data->tx_frame_buf_mutex, K_FOREVER); + if (total_len > NET_ETH_MAX_FRAME_SIZE) { + /* NuMaker SDK reserve 2048 for tx_buf */ + LOG_ERR("TX packet length [%d] over max [%d]", total_len, NET_ETH_MAX_FRAME_SIZE); + goto error; + } + + buffer = m_numaker_gmacdev_get_tx_buf(gmacdev); + LOG_DBG("buffer=0x%x", (uint32_t)buffer); + if (buffer == NULL) { + goto error; + } + + if (net_pkt_read(pkt, buffer, total_len)) { + goto error; + } + + /* Prepare transmit descriptors to give to DMA */ + m_numaker_gmacdev_trigger_tx(gmacdev, total_len); + + k_mutex_unlock(&data->tx_frame_buf_mutex); + + return 0; + +error: + LOG_ERR("Writing pkt to TX descriptor failed"); + k_mutex_unlock(&data->tx_frame_buf_mutex); + return -EIO; +} + +static void numaker_eth_if_init(struct net_if *iface) +{ + const struct device *dev = net_if_get_device(iface); + struct eth_numaker_data *data = dev->data; + + synopGMACdevice *gmacdev = data->gmacdev; + + LOG_DBG("eth_if_init"); + + /* Read mac address */ + m_numaker_read_mac_addr(data->mac_addr); + + net_if_set_link_addr(iface, data->mac_addr, sizeof(data->mac_addr), NET_LINK_ETHERNET); + data->iface = iface; + ethernet_init(iface); + + /* Enable GMAC device INT & TX/RX */ + m_numaker_gmacdev_enable(gmacdev); +} + +static int numaker_eth_set_config(const struct device *dev, enum ethernet_config_type type, + const struct ethernet_config *config) +{ + struct eth_numaker_data *data = dev->data; + + switch (type) { + case ETHERNET_CONFIG_TYPE_MAC_ADDRESS: + memcpy(data->mac_addr, config->mac_address.addr, sizeof(data->mac_addr)); + synopGMAC_set_mac_address(NUMAKER_GMAC_INTF, data->mac_addr); + net_if_set_link_addr(data->iface, data->mac_addr, sizeof(data->mac_addr), + NET_LINK_ETHERNET); + LOG_DBG("%s MAC set to %02x:%02x:%02x:%02x:%02x:%02x", dev->name, data->mac_addr[0], + data->mac_addr[1], data->mac_addr[2], data->mac_addr[3], data->mac_addr[4], + data->mac_addr[5]); + return 0; + default: + return -ENOTSUP; + } +} + +static enum ethernet_hw_caps numaker_eth_get_cap(const struct device *dev) +{ + ARG_UNUSED(dev); +#if defined(NU_USING_HW_CHECKSUM) + return ETHERNET_LINK_10BASE_T | ETHERNET_LINK_100BASE_T | ETHERNET_HW_RX_CHKSUM_OFFLOAD; +#else + return ETHERNET_LINK_10BASE_T | ETHERNET_LINK_100BASE_T; +#endif +} + +static const struct ethernet_api eth_numaker_driver_api = { + .iface_api.init = numaker_eth_if_init, + .get_capabilities = numaker_eth_get_cap, + .set_config = numaker_eth_set_config, + .send = numaker_eth_tx, +}; + +/* EMAC IRQ Handler */ +static void eth_numaker_isr(const struct device *dev) +{ + struct eth_numaker_data *data = dev->data; + synopGMACdevice *gmacdev = data->gmacdev; + uint32_t interrupt; + uint32_t dma_status_reg; + uint32_t mac_status_reg; + int status; + uint32_t dma_ie = DmaIntEnable; + + uint32_t volatile reg; + + /* Check GMAC interrupt */ + mac_status_reg = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacInterruptStatus); + if (mac_status_reg & GmacTSIntSts) { + gmacdev->synopGMACNetStats.ts_int = 1; + status = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacTSStatus); + if (!(status & BIT(1))) { + LOG_WRN("TS alarm flag not set??"); + } else { + LOG_DBG("TS alarm"); + } + } + + if (mac_status_reg & GmacLPIIntSts) { + LOG_DBG("LPI"); + } + + if (mac_status_reg & GmacRgmiiIntSts) { + reg = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacRgmiiCtrlSts); + } + + synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacInterruptStatus, mac_status_reg); + /* Read the Dma interrupt status to know whether the interrupt got generated by + * our device or not + */ + dma_status_reg = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaStatus); + LOG_DBG("i %08x %08x", mac_status_reg, dma_status_reg); + + if (dma_status_reg == 0) { + return; + } + + synopGMAC_disable_interrupt_all(gmacdev); + LOG_DBG("Dma Status Reg: 0x%08x", dma_status_reg); + if (dma_status_reg & GmacPmtIntr) { + LOG_DBG("Interrupt due to PMT module"); + synopGMAC_powerup_mac(gmacdev); + } + + if (dma_status_reg & GmacLineIntfIntr) { + LOG_DBG("Interrupt due to GMAC LINE module"); + } + + /* Now lets handle the DMA interrupts */ + interrupt = synopGMAC_get_interrupt_type(gmacdev); + LOG_DBG("Interrupts to be handled: 0x%08x", interrupt); + if (interrupt & synopGMACDmaError) { + LOG_DBG("Fatal Bus Error Interrupt Seen"); + synopGMAC_disable_dma_tx(gmacdev); + synopGMAC_disable_dma_rx(gmacdev); + + synopGMAC_take_desc_ownership_tx(gmacdev); + synopGMAC_take_desc_ownership_rx(gmacdev); + + synopGMAC_init_tx_rx_desc_queue(gmacdev); + + synopGMAC_reset(gmacdev); /* reset the DMA engine and the GMAC ip */ + synopGMAC_set_mac_address(NUMAKER_GMAC_INTF, data->mac_addr); + synopGMAC_dma_bus_mode_init(gmacdev, DmaFixedBurstEnable | DmaBurstLength8 | + DmaDescriptorSkip0); + synopGMAC_dma_control_init(gmacdev, DmaStoreAndForward); + synopGMAC_init_rx_desc_base(gmacdev); + synopGMAC_init_tx_desc_base(gmacdev); + synopGMAC_mac_init(gmacdev); + synopGMAC_enable_dma_rx(gmacdev); + synopGMAC_enable_dma_tx(gmacdev); + } + + if (interrupt & synopGMACDmaRxNormal) { + LOG_DBG("Rx Normal"); + /* disable RX interrupt */ + dma_ie &= ~DmaIntRxNormMask; + /* to handle received data */ + m_numaker_gmacdev_packet_rx(dev); + } + + if (interrupt & synopGMACDmaRxAbnormal) { + LOG_ERR("Abnormal Rx Interrupt Seen"); + /* If Mac is not in powerdown */ + if (gmacdev->GMAC_Power_down == 0) { + gmacdev->synopGMACNetStats.rx_over_errors++; + dma_ie &= ~DmaIntRxAbnMask; + /* To handle GBPS with 12 descriptors. */ + synopGMAC_resume_dma_rx(gmacdev); + } + } + + /* Receiver gone in to stopped state */ + if (interrupt & synopGMACDmaRxStopped) { + LOG_ERR("Receiver stopped seeing Rx interrupts"); + if (gmacdev->GMAC_Power_down == 0) { + gmacdev->synopGMACNetStats.rx_over_errors++; + synopGMAC_enable_dma_rx(gmacdev); + } + } + + if (interrupt & synopGMACDmaTxNormal) { + LOG_DBG("Finished Normal Transmission"); + synop_handle_transmit_over(0); + /* No-op at this stage for TX INT */ + } + + if (interrupt & synopGMACDmaTxAbnormal) { + LOG_ERR("Abnormal Tx Interrupt Seen"); + if (gmacdev->GMAC_Power_down == 0) { + synop_handle_transmit_over(0); + /* No-op at this stage for TX INT */ + } + } + + if (interrupt & synopGMACDmaTxStopped) { + LOG_ERR("Transmitter stopped sending the packets"); + if (gmacdev->GMAC_Power_down == 0) { + synopGMAC_disable_dma_tx(gmacdev); + synopGMAC_take_desc_ownership_tx(gmacdev); + synopGMAC_enable_dma_tx(gmacdev); + LOG_ERR("Transmission Resumed"); + } + } + + /* Enable the interrupt before returning from ISR*/ + synopGMAC_enable_interrupt(gmacdev, dma_ie); +} + +/* Declare pin-ctrl __pinctrl_dev_config__device_dts_ord_xx before + * PINCTRL_DT_INST_DEV_CONFIG_GET() + */ +PINCTRL_DT_INST_DEFINE(0); + +static int eth_numaker_init(const struct device *dev) +{ + const struct eth_numaker_config *cfg = dev->config; + struct eth_numaker_data *data = dev->data; + synopGMACdevice *gmacdev; + + /* Init MAC Address based on UUID*/ + uint8_t mac_addr[NU_HWADDR_SIZE]; + int ret = 0; + struct numaker_scc_subsys scc_subsys; + + gmacdev = &GMACdev[NUMAKER_GMAC_INTF]; + data->gmacdev = gmacdev; + + k_mutex_init(&data->tx_frame_buf_mutex); + + eth_phy_addr = cfg->phy_addr; + + /* CLK controller */ + memset(&scc_subsys, 0x00, sizeof(scc_subsys)); + scc_subsys.subsys_id = NUMAKER_SCC_SUBSYS_ID_PCC; + scc_subsys.pcc.clk_modidx = cfg->clk_modidx; + scc_subsys.pcc.clk_src = cfg->clk_src; + scc_subsys.pcc.clk_div = cfg->clk_div; + + /* Equivalent to CLK_EnableModuleClock() */ + ret = clock_control_on(cfg->clk_dev, (clock_control_subsys_t)&scc_subsys); + if (ret != 0) { + goto done; + } + + /* For EMAC, not need CLK_SetModuleClock() + * Validate this module's reset object + */ + if (!device_is_ready(cfg->reset.dev)) { + LOG_ERR("reset controller not ready"); + return -ENODEV; + } + + SYS_UnlockReg(); + + irq_disable(DT_INST_IRQN(0)); + ret = pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_DEFAULT); + if (ret != 0) { + LOG_ERR("Failed to apply pinctrl state"); + goto done; + } + + /* Reset EMAC to default state, same as BSP's SYS_ResetModule(id_rst) */ + reset_line_toggle_dt(&cfg->reset); + + /* Read mac address */ + m_numaker_read_mac_addr(mac_addr); + + /* Configure GMAC device */ + ret = m_numaker_gmacdev_init(gmacdev, mac_addr, cfg->gmac_base); + if (ret != 0) { + LOG_ERR("GMAC failed to initialize"); + goto done; + } + + IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), eth_numaker_isr, + DEVICE_DT_INST_GET(0), 0); + + irq_enable(DT_INST_IRQN(0)); + +done: + SYS_LockReg(); + return ret; +} + +static struct eth_numaker_data eth_numaker_data_inst; + +/* Set config based on DTS */ +static struct eth_numaker_config eth_numaker_cfg_inst = { + .gmac_base = (uint32_t)DT_INST_REG_ADDR(0), + .reset = RESET_DT_SPEC_INST_GET(0), + .phy_addr = DT_INST_PROP(0, phy_addr), + .clk_modidx = DT_INST_CLOCKS_CELL(0, clock_module_index), + .clk_src = DT_INST_CLOCKS_CELL(0, clock_source), + .clk_div = DT_INST_CLOCKS_CELL(0, clock_divider), + .clk_dev = DEVICE_DT_GET(DT_PARENT(DT_INST_CLOCKS_CTLR(0))), + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0), + .reset = RESET_DT_SPEC_INST_GET(0), +}; + +ETH_NET_DEVICE_DT_INST_DEFINE(0, eth_numaker_init, NULL, ð_numaker_data_inst, + ð_numaker_cfg_inst, CONFIG_ETH_INIT_PRIORITY, + ð_numaker_driver_api, NET_ETH_MTU); diff --git a/drivers/ethernet/eth_numaker_priv.h b/drivers/ethernet/eth_numaker_priv.h new file mode 100644 index 00000000000..e3bec804b98 --- /dev/null +++ b/drivers/ethernet/eth_numaker_priv.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_ETHERNET_ETH_NUMAKER_PRIV_H_ +#define ZEPHYR_DRIVERS_ETHERNET_ETH_NUMAKER_PRIV_H_ + +#include + +#define NU_ETH_MAX_FLEN (1518) + +#define NU_HWADDR_SIZE (6) + +#define NU_ETH_MTU_SIZE 1500 + +#endif /* ZEPHYR_DRIVERS_ETHERNET_ETH_NUMAKER_PRIV_H_ */ diff --git a/drivers/ethernet/eth_nxp_s32_gmac.c b/drivers/ethernet/eth_nxp_s32_gmac.c index 423f2b1499e..71e3e94c176 100644 --- a/drivers/ethernet/eth_nxp_s32_gmac.c +++ b/drivers/ethernet/eth_nxp_s32_gmac.c @@ -78,7 +78,7 @@ static inline struct net_if *get_iface(struct eth_nxp_s32_data *ctx, uint16_t vl #endif } -#if defined(CONFIG_SOC_PART_NUMBER_S32K3) +#if defined(CONFIG_SOC_SERIES_S32K3XX) static int select_phy_interface(Gmac_Ip_MiiModeType mode) { uint32_t regval; @@ -105,7 +105,7 @@ static int select_phy_interface(Gmac_Ip_MiiModeType mode) } #else #error "SoC not supported" -#endif /* CONFIG_SOC_PART_NUMBER_S32K3 */ +#endif /* CONFIG_SOC_SERIES_S32K3XX */ static int eth_nxp_s32_init(const struct device *dev) { @@ -564,7 +564,7 @@ BUILD_ASSERT((CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE % FEATURE_GMAC_DATA_BUS_WIDTH_ #define ETH_NXP_S32_MAC_SPEED(n) \ COND_CODE_1(ETH_NXP_S32_IS_FIXED_LINK(n), \ - (CONCAT(CONCAT(GMAC_SPEED_, ETH_NXP_S32_FIXED_LINK_SPEED(n)), M)), \ + (_CONCAT(_CONCAT(GMAC_SPEED_, ETH_NXP_S32_FIXED_LINK_SPEED(n)), M)), \ (GMAC_SPEED_100M)) #define ETH_NXP_S32_MAC_DUPLEX(n) \ @@ -574,7 +574,7 @@ BUILD_ASSERT((CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE % FEATURE_GMAC_DATA_BUS_WIDTH_ (GMAC_FULL_DUPLEX)) #define ETH_NXP_S32_MAC_MII(n) \ - CONCAT(CONCAT(GMAC_, DT_INST_STRING_UPPER_TOKEN(n, phy_connection_type)), _MODE) + _CONCAT(_CONCAT(GMAC_, DT_INST_STRING_UPPER_TOKEN(n, phy_connection_type)), _MODE) #define ETH_NXP_S32_IRQ_INIT(n, name) \ IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, name, irq), \ diff --git a/drivers/ethernet/eth_nxp_s32_netc.c b/drivers/ethernet/eth_nxp_s32_netc.c index c452a4b398f..f5a3994a9c4 100644 --- a/drivers/ethernet/eth_nxp_s32_netc.c +++ b/drivers/ethernet/eth_nxp_s32_netc.c @@ -18,7 +18,7 @@ LOG_MODULE_REGISTER(nxp_s32_eth); #include #include -#include +#include #include #include #include diff --git a/drivers/ethernet/eth_nxp_s32_netc_psi.c b/drivers/ethernet/eth_nxp_s32_netc_psi.c index f35eb73ba28..8a3242be911 100644 --- a/drivers/ethernet/eth_nxp_s32_netc_psi.c +++ b/drivers/ethernet/eth_nxp_s32_netc_psi.c @@ -18,7 +18,7 @@ LOG_MODULE_REGISTER(nxp_s32_eth_psi); #include #include -#include +#include #include #include #include diff --git a/drivers/ethernet/eth_nxp_s32_netc_vsi.c b/drivers/ethernet/eth_nxp_s32_netc_vsi.c index b262250c226..1a159529814 100644 --- a/drivers/ethernet/eth_nxp_s32_netc_vsi.c +++ b/drivers/ethernet/eth_nxp_s32_netc_vsi.c @@ -18,7 +18,7 @@ LOG_MODULE_REGISTER(nxp_s32_eth_vsi); #include #include -#include +#include #include #include #include diff --git a/drivers/ethernet/eth_sam_gmac.c b/drivers/ethernet/eth_sam_gmac.c index 9cd9daa6908..dec6ea6df20 100644 --- a/drivers/ethernet/eth_sam_gmac.c +++ b/drivers/ethernet/eth_sam_gmac.c @@ -1973,7 +1973,9 @@ static void eth0_iface_init(struct net_if *iface) } /* Do not start the interface until PHY link is up */ - net_if_carrier_off(iface); + if (!(dev_data->link_up)) { + net_if_carrier_off(iface); + } init_done = true; } diff --git a/drivers/ethernet/eth_smsc91x.c b/drivers/ethernet/eth_smsc91x.c index 02d11a26838..cac41136217 100644 --- a/drivers/ethernet/eth_smsc91x.c +++ b/drivers/ethernet/eth_smsc91x.c @@ -4,7 +4,7 @@ */ #include -#include "zephyr/net/phy.h" +#include #include #include #include diff --git a/drivers/ethernet/eth_stm32_hal.c b/drivers/ethernet/eth_stm32_hal.c index bdb4771d01f..40760171e9d 100644 --- a/drivers/ethernet/eth_stm32_hal.c +++ b/drivers/ethernet/eth_stm32_hal.c @@ -33,6 +33,10 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #include #include +#if defined(CONFIG_NET_DSA) +#include +#endif + #if defined(CONFIG_PTP_CLOCK_STM32_HAL) #include #endif /* CONFIG_PTP_CLOCK_STM32_HAL */ @@ -489,10 +493,10 @@ static int eth_tx(const struct device *dev, struct net_pkt *pkt) } /* Check for MAC errors */ - if (HAL_ETH_GetDMAError(heth)) { - LOG_ERR("%s: ETH DMA error: macerror:%x", + if (HAL_ETH_GetMACError(heth)) { + LOG_ERR("%s: ETH MAC error: macerror:%x", __func__, - HAL_ETH_GetDMAError(heth)); + HAL_ETH_GetMACError(heth)); /* MAC errors are putting in error state*/ /* TODO recover from this */ } @@ -867,6 +871,7 @@ static void rx_thread(void *arg1, void *unused1, void *unused2) uint16_t vlan_tag = NET_VLAN_TAG_UNSPEC; const struct device *dev; struct eth_stm32_hal_dev_data *dev_data; + struct net_if *iface; struct net_pkt *pkt; int res; uint32_t status; @@ -892,7 +897,11 @@ static void rx_thread(void *arg1, void *unused1, void *unused2) vlan_tag)); } while ((pkt = eth_rx(dev, &vlan_tag)) != NULL) { - res = net_recv_data(net_pkt_iface(pkt), pkt); + iface = net_pkt_iface(pkt); +#if defined(CONFIG_NET_DSA) + iface = dsa_net_recv(iface, &pkt); +#endif + res = net_recv_data(iface, pkt); if (res < 0) { eth_stats_update_errors_rx( net_pkt_iface(pkt)); @@ -1516,6 +1525,10 @@ static void eth_iface_init(struct net_if *iface) sizeof(dev_data->mac_addr), NET_LINK_ETHERNET); +#if defined(CONFIG_NET_DSA) + dsa_register_master_tx(iface, ð_tx); +#endif + ethernet_init(iface); net_if_carrier_off(iface); @@ -1559,6 +1572,9 @@ static enum ethernet_hw_caps eth_stm32_hal_get_capabilities(const struct device #if defined(CONFIG_ETH_STM32_HW_CHECKSUM) | ETHERNET_HW_RX_CHKSUM_OFFLOAD | ETHERNET_HW_TX_CHKSUM_OFFLOAD +#endif +#if defined(CONFIG_NET_DSA) + | ETHERNET_DSA_MASTER_PORT #endif ; } @@ -1638,7 +1654,11 @@ static const struct ethernet_api eth_api = { #endif /* CONFIG_PTP_CLOCK_STM32_HAL */ .get_capabilities = eth_stm32_hal_get_capabilities, .set_config = eth_stm32_hal_set_config, +#if defined(CONFIG_NET_DSA) + .send = dsa_tx, +#else .send = eth_tx, +#endif #if defined(CONFIG_NET_STATISTICS_ETHERNET) .get_stats = eth_stm32_hal_get_stats, #endif /* CONFIG_NET_STATISTICS_ETHERNET */ diff --git a/drivers/ethernet/eth_w5500.c b/drivers/ethernet/eth_w5500.c index 03b5cb752d1..88a2d710b72 100644 --- a/drivers/ethernet/eth_w5500.c +++ b/drivers/ethernet/eth_w5500.c @@ -275,8 +275,12 @@ static void w5500_rx(const struct device *dev) w5500_command(dev, S0_CR_RECV); } -static void w5500_thread(const struct device *dev) +static void w5500_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; uint8_t ir; struct w5500_runtime *ctx = dev->data; const struct w5500_config *config = dev->config; @@ -557,7 +561,7 @@ static int w5500_init(const struct device *dev) k_thread_create(&ctx->thread, ctx->thread_stack, CONFIG_ETH_W5500_RX_THREAD_STACK_SIZE, - (k_thread_entry_t)w5500_thread, + w5500_thread, (void *)dev, NULL, NULL, K_PRIO_COOP(CONFIG_ETH_W5500_RX_THREAD_PRIO), 0, K_NO_WAIT); diff --git a/drivers/ethernet/eth_w5500_priv.h b/drivers/ethernet/eth_w5500_priv.h index aed1fe4adfa..5367300d5ef 100644 --- a/drivers/ethernet/eth_w5500_priv.h +++ b/drivers/ethernet/eth_w5500_priv.h @@ -90,7 +90,7 @@ struct w5500_config { struct w5500_runtime { struct net_if *iface; - K_THREAD_STACK_MEMBER(thread_stack, + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_ETH_W5500_RX_THREAD_STACK_SIZE); struct k_thread thread; uint8_t mac_addr[6]; diff --git a/drivers/ethernet/oa_tc6.c b/drivers/ethernet/oa_tc6.c new file mode 100644 index 00000000000..0fa1f105581 --- /dev/null +++ b/drivers/ethernet/oa_tc6.c @@ -0,0 +1,393 @@ +/* + * Copyright (c) 2023 DENX Software Engineering GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "oa_tc6.h" + +#include +LOG_MODULE_REGISTER(oa_tc6, CONFIG_ETHERNET_LOG_LEVEL); + +int oa_tc6_reg_read(struct oa_tc6 *tc6, const uint32_t reg, uint32_t *val) +{ + uint8_t buf[OA_TC6_HDR_SIZE + 12] = { 0 }; + struct spi_buf tx_buf = { .buf = buf, .len = sizeof(buf) }; + const struct spi_buf_set tx = { .buffers = &tx_buf, .count = 1 }; + struct spi_buf rx_buf = { .buf = buf, .len = sizeof(buf) }; + const struct spi_buf_set rx = { .buffers = &rx_buf, .count = 1 }; + uint32_t rv, rvn, hdr_bkp, *hdr = (uint32_t *) &buf[0]; + int ret = 0; + + /* + * Buffers are allocated for protected (larger) case (by 4 bytes). + * When non-protected case - we need to decrase them + */ + if (!tc6->protected) { + tx_buf.len -= sizeof(rvn); + rx_buf.len -= sizeof(rvn); + } + + *hdr = FIELD_PREP(OA_CTRL_HDR_DNC, 0) | + FIELD_PREP(OA_CTRL_HDR_WNR, 0) | + FIELD_PREP(OA_CTRL_HDR_AID, 0) | + FIELD_PREP(OA_CTRL_HDR_MMS, reg >> 16) | + FIELD_PREP(OA_CTRL_HDR_ADDR, reg) | + FIELD_PREP(OA_CTRL_HDR_LEN, 0); /* To read single register len = 0 */ + *hdr |= FIELD_PREP(OA_CTRL_HDR_P, oa_tc6_get_parity(*hdr)); + hdr_bkp = *hdr; + *hdr = sys_cpu_to_be32(*hdr); + + ret = spi_transceive_dt(tc6->spi, &tx, &rx); + if (ret < 0) { + return ret; + } + + /* Check if echoed control command header is correct */ + rv = sys_be32_to_cpu(*(uint32_t *)&buf[4]); + if (hdr_bkp != rv) { + LOG_ERR("Header transmission error!"); + return -1; + } + + rv = sys_be32_to_cpu(*(uint32_t *)&buf[8]); + + /* In protected mode read data is followed by its compliment value */ + if (tc6->protected) { + rvn = sys_be32_to_cpu(*(uint32_t *)&buf[12]); + if (rv != ~rvn) { + LOG_ERR("Protected mode transmission error!"); + return -1; + } + } + + *val = rv; + + return ret; +} + +int oa_tc6_reg_write(struct oa_tc6 *tc6, const uint32_t reg, uint32_t val) +{ + uint8_t buf_tx[OA_TC6_HDR_SIZE + 12] = { 0 }; + uint8_t buf_rx[OA_TC6_HDR_SIZE + 12] = { 0 }; + struct spi_buf tx_buf = { .buf = buf_tx, .len = sizeof(buf_tx) }; + const struct spi_buf_set tx = { .buffers = &tx_buf, .count = 1 }; + struct spi_buf rx_buf = { .buf = buf_rx, .len = sizeof(buf_rx) }; + const struct spi_buf_set rx = { .buffers = &rx_buf, .count = 1 }; + uint32_t rv, rvn, hdr_bkp, *hdr = (uint32_t *) &buf_tx[0]; + int ret; + + /* + * Buffers are allocated for protected (larger) case (by 4 bytes). + * When non-protected case - we need to decrase them + */ + if (!tc6->protected) { + tx_buf.len -= sizeof(rvn); + rx_buf.len -= sizeof(rvn); + } + + *hdr = FIELD_PREP(OA_CTRL_HDR_DNC, 0) | + FIELD_PREP(OA_CTRL_HDR_WNR, 1) | + FIELD_PREP(OA_CTRL_HDR_AID, 0) | + FIELD_PREP(OA_CTRL_HDR_MMS, reg >> 16) | + FIELD_PREP(OA_CTRL_HDR_ADDR, reg) | + FIELD_PREP(OA_CTRL_HDR_LEN, 0); /* To read single register len = 0 */ + *hdr |= FIELD_PREP(OA_CTRL_HDR_P, oa_tc6_get_parity(*hdr)); + hdr_bkp = *hdr; + *hdr = sys_cpu_to_be32(*hdr); + + *(uint32_t *)&buf_tx[4] = sys_cpu_to_be32(val); + if (tc6->protected) { + *(uint32_t *)&buf_tx[8] = sys_be32_to_cpu(~val); + } + + ret = spi_transceive_dt(tc6->spi, &tx, &rx); + if (ret < 0) { + return ret; + } + + /* Check if echoed control command header is correct */ + rv = sys_be32_to_cpu(*(uint32_t *)&buf_rx[4]); + if (hdr_bkp != rv) { + LOG_ERR("Header transmission error!"); + return -1; + } + + /* Check if echoed value is correct */ + rv = sys_be32_to_cpu(*(uint32_t *)&buf_rx[8]); + if (val != rv) { + LOG_ERR("Header transmission error!"); + return -1; + } + + /* + * In protected mode check if read value is followed by its + * compliment value + */ + if (tc6->protected) { + rvn = sys_be32_to_cpu(*(uint32_t *)&buf_rx[12]); + if (val != ~rvn) { + LOG_ERR("Protected mode transmission error!"); + return -1; + } + } + + return ret; +} + +int oa_tc6_set_protected_ctrl(struct oa_tc6 *tc6, bool prote) +{ + uint32_t val; + int ret; + + ret = oa_tc6_reg_read(tc6, OA_CONFIG0, &val); + if (ret < 0) { + return ret; + } + + if (prote) { + val |= OA_CONFIG0_PROTE; + } else { + val &= ~OA_CONFIG0_PROTE; + } + + ret = oa_tc6_reg_write(tc6, OA_CONFIG0, val); + if (ret < 0) { + return ret; + } + + tc6->protected = prote; + return 0; +} + +int oa_tc6_send_chunks(struct oa_tc6 *tc6, struct net_pkt *pkt) +{ + uint16_t len = net_pkt_get_len(pkt); + uint8_t oa_tx[tc6->cps]; + uint32_t hdr, ftr; + uint8_t chunks, i; + int ret; + + chunks = (len / tc6->cps) + 1; + + /* Check if LAN865x has any free internal buffer space */ + if (chunks > tc6->txc) { + return -EIO; + } + + /* Transform struct net_pkt content into chunks */ + for (i = 1; i <= chunks; i++) { + hdr = FIELD_PREP(OA_DATA_HDR_DNC, 1) | + FIELD_PREP(OA_DATA_HDR_DV, 1) | + FIELD_PREP(OA_DATA_HDR_NORX, 1) | + FIELD_PREP(OA_DATA_HDR_SWO, 0); + + if (i == 1) { + hdr |= FIELD_PREP(OA_DATA_HDR_SV, 1); + } + + if (i == chunks) { + hdr |= FIELD_PREP(OA_DATA_HDR_EBO, len - 1) | + FIELD_PREP(OA_DATA_HDR_EV, 1); + } + + hdr |= FIELD_PREP(OA_DATA_HDR_P, oa_tc6_get_parity(hdr)); + + ret = net_pkt_read(pkt, oa_tx, len > tc6->cps ? tc6->cps : len); + if (ret < 0) { + return ret; + } + + ret = oa_tc6_chunk_spi_transfer(tc6, NULL, oa_tx, hdr, &ftr); + if (ret < 0) { + return ret; + } + + len -= tc6->cps; + } + + return 0; +} + +static void oa_tc6_update_status(struct oa_tc6 *tc6, uint32_t ftr) +{ + tc6->exst = FIELD_GET(OA_DATA_FTR_EXST, ftr); + tc6->sync = FIELD_GET(OA_DATA_FTR_SYNC, ftr); + tc6->rca = FIELD_GET(OA_DATA_FTR_RCA, ftr); + tc6->txc = FIELD_GET(OA_DATA_FTR_TXC, ftr); +} + +int oa_tc6_update_buf_info(struct oa_tc6 *tc6) +{ + uint32_t val; + int ret; + + ret = oa_tc6_reg_read(tc6, OA_BUFSTS, &val); + if (ret < 0) { + return ret; + } + + tc6->rca = FIELD_GET(OA_BUFSTS_RCA, val); + tc6->txc = FIELD_GET(OA_BUFSTS_TXC, val); + + return 0; +} + +int oa_tc6_chunk_spi_transfer(struct oa_tc6 *tc6, uint8_t *buf_rx, uint8_t *buf_tx, + uint32_t hdr, uint32_t *ftr) +{ + struct spi_buf tx_buf[2]; + struct spi_buf rx_buf[2]; + struct spi_buf_set tx; + struct spi_buf_set rx; + int ret; + + hdr = sys_cpu_to_be32(hdr); + tx_buf[0].buf = &hdr; + tx_buf[0].len = sizeof(hdr); + + tx_buf[1].buf = buf_tx; + tx_buf[1].len = tc6->cps; + + tx.buffers = tx_buf; + tx.count = ARRAY_SIZE(tx_buf); + + rx_buf[0].buf = buf_rx; + rx_buf[0].len = tc6->cps; + + rx_buf[1].buf = ftr; + rx_buf[1].len = sizeof(*ftr); + + rx.buffers = rx_buf; + rx.count = ARRAY_SIZE(rx_buf); + + ret = spi_transceive_dt(tc6->spi, &tx, &rx); + if (ret < 0) { + return ret; + } + *ftr = sys_be32_to_cpu(*ftr); + oa_tc6_update_status(tc6, *ftr); + + return 0; +} + +int oa_tc6_read_status(struct oa_tc6 *tc6, uint32_t *ftr) +{ + uint32_t hdr; + + hdr = FIELD_PREP(OA_DATA_HDR_DNC, 1) | + FIELD_PREP(OA_DATA_HDR_DV, 0) | + FIELD_PREP(OA_DATA_HDR_NORX, 1); + hdr |= FIELD_PREP(OA_DATA_HDR_P, oa_tc6_get_parity(hdr)); + + return oa_tc6_chunk_spi_transfer(tc6, NULL, NULL, hdr, ftr); +} + +int oa_tc6_read_chunks(struct oa_tc6 *tc6, struct net_pkt *pkt) +{ + struct net_buf *buf_rx = NULL; + uint8_t chunks, sbo, ebo; + uint32_t hdr, ftr; + int ret; + + /* + * Special case - append already received data (extracted from previous + * chunk) to new packet. + */ + if (tc6->concat_buf) { + net_pkt_append_buffer(pkt, tc6->concat_buf); + tc6->concat_buf = NULL; + } + + for (chunks = tc6->rca; chunks; chunks--) { + buf_rx = net_pkt_get_frag(pkt, tc6->cps, OA_TC6_BUF_ALLOC_TIMEOUT); + if (!buf_rx) { + LOG_ERR("OA RX: Can't allocate RX buffer fordata!"); + return -ENOMEM; + } + + hdr = FIELD_PREP(OA_DATA_HDR_DNC, 1); + hdr |= FIELD_PREP(OA_DATA_HDR_P, oa_tc6_get_parity(hdr)); + + ret = oa_tc6_chunk_spi_transfer(tc6, buf_rx->data, NULL, hdr, &ftr); + if (ret < 0) { + LOG_ERR("OA RX: transmission error: %d!", ret); + goto unref_buf; + } + + ret = -EIO; + if (oa_tc6_get_parity(ftr)) { + LOG_ERR("OA RX: Footer parity error!"); + goto unref_buf; + } + + if (!FIELD_GET(OA_DATA_FTR_SYNC, ftr)) { + LOG_ERR("OA RX: Configuration not SYNC'ed!"); + goto unref_buf; + } + + if (!FIELD_GET(OA_DATA_FTR_DV, ftr)) { + LOG_ERR("OA RX: Data chunk not valid, skip!"); + goto unref_buf; + } + + sbo = FIELD_GET(OA_DATA_FTR_SWO, ftr) * sizeof(uint32_t); + ebo = FIELD_GET(OA_DATA_FTR_EBO, ftr) + 1; + + if (FIELD_GET(OA_DATA_FTR_SV, ftr)) { + /* + * Adjust beginning of the buffer with SWO only when + * we DO NOT have two frames concatenated together + * in one chunk. + */ + if (!(FIELD_GET(OA_DATA_FTR_EV, ftr) && (ebo <= sbo))) { + if (sbo) { + net_buf_pull(buf_rx, sbo); + } + } + } + + net_pkt_append_buffer(pkt, buf_rx); + buf_rx->len = tc6->cps; + + if (FIELD_GET(OA_DATA_FTR_EV, ftr)) { + /* + * Check if received frame shall be dropped - i.e. MAC has + * detected error condition, which shall result in frame drop + * by the SPI host. + */ + if (FIELD_GET(OA_DATA_FTR_FD, ftr)) { + ret = -EIO; + goto unref_buf; + } + + /* + * Concatenation of frames in a single chunk - one frame ends + * and second one starts just afterwards (ebo == sbo). + */ + if (FIELD_GET(OA_DATA_FTR_SV, ftr) && (ebo <= sbo)) { + tc6->concat_buf = net_buf_clone(buf_rx, OA_TC6_BUF_ALLOC_TIMEOUT); + if (!tc6->concat_buf) { + LOG_ERR("OA RX: Can't allocate RX buffer for data!"); + ret = -ENOMEM; + goto unref_buf; + } + net_buf_pull(tc6->concat_buf, sbo); + } + + /* Set final size of the buffer */ + buf_rx->len = ebo; + /* + * Exit when complete packet is read and added to + * struct net_pkt + */ + break; + } + } + + return 0; + + unref_buf: + net_buf_unref(buf_rx); + return ret; +} diff --git a/drivers/ethernet/oa_tc6.h b/drivers/ethernet/oa_tc6.h new file mode 100644 index 00000000000..7a9337e7c5d --- /dev/null +++ b/drivers/ethernet/oa_tc6.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2023 DENX Software Engineering GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef OA_TC6_CFG_H__ +#define OA_TC6_CFG_H__ + +#include +#include +#include +#include +#include +#include + +#define MMS_REG(m, r) ((((m) & GENMASK(3, 0)) << 16) | ((r) & GENMASK(15, 0))) +/* Memory Map Sector (MMS) 0 */ +#define OA_ID MMS_REG(0x0, 0x000) /* expect 0x11 */ +#define OA_PHYID MMS_REG(0x0, 0x001) +#define OA_RESET MMS_REG(0x0, 0x003) +#define OA_RESET_SWRESET BIT(0) +#define OA_CONFIG0 MMS_REG(0x0, 0x004) +#define OA_CONFIG0_SYNC BIT(15) +#define OA_CONFIG0_PROTE BIT(5) +#define OA_STATUS0 MMS_REG(0x0, 0x008) +#define OA_STATUS0_RESETC BIT(6) +#define OA_STATUS1 MMS_REG(0x0, 0x009) +#define OA_BUFSTS MMS_REG(0x0, 0x00B) +#define OA_BUFSTS_TXC GENMASK(15, 8) +#define OA_BUFSTS_RCA GENMASK(7, 0) +#define OA_IMASK0 MMS_REG(0x0, 0x00C) +#define OA_IMASK0_TXPEM BIT(0) +#define OA_IMASK0_TXBOEM BIT(1) +#define OA_IMASK0_TXBUEM BIT(2) +#define OA_IMASK0_RXBOEM BIT(3) +#define OA_IMASK0_LOFEM BIT(4) +#define OA_IMASK0_HDREM BIT(5) +#define OA_IMASK1 MMS_REG(0x0, 0x00D) +#define OA_IMASK0_UV18M BIT(19) + +/* OA Control header */ +#define OA_CTRL_HDR_DNC BIT(31) +#define OA_CTRL_HDR_HDRB BIT(30) +#define OA_CTRL_HDR_WNR BIT(29) +#define OA_CTRL_HDR_AID BIT(28) +#define OA_CTRL_HDR_MMS GENMASK(27, 24) +#define OA_CTRL_HDR_ADDR GENMASK(23, 8) +#define OA_CTRL_HDR_LEN GENMASK(7, 1) +#define OA_CTRL_HDR_P BIT(0) + +/* OA Data header */ +#define OA_DATA_HDR_DNC BIT(31) +#define OA_DATA_HDR_SEQ BIT(30) +#define OA_DATA_HDR_NORX BIT(29) +#define OA_DATA_HDR_DV BIT(21) +#define OA_DATA_HDR_SV BIT(20) +#define OA_DATA_HDR_SWO GENMASK(19, 16) +#define OA_DATA_HDR_EV BIT(14) +#define OA_DATA_HDR_EBO GENMASK(13, 8) +#define OA_DATA_HDR_P BIT(0) + +/* OA Data footer */ +#define OA_DATA_FTR_EXST BIT(31) +#define OA_DATA_FTR_HDRB BIT(30) +#define OA_DATA_FTR_SYNC BIT(29) +#define OA_DATA_FTR_RCA GENMASK(28, 24) +#define OA_DATA_FTR_DV BIT(21) +#define OA_DATA_FTR_SV BIT(20) +#define OA_DATA_FTR_SWO GENMASK(19, 16) +#define OA_DATA_FTR_FD BIT(15) +#define OA_DATA_FTR_EV BIT(14) +#define OA_DATA_FTR_EBO GENMASK(13, 8) +#define OA_DATA_FTR_TXC GENMASK(5, 1) +#define OA_DATA_FTR_P BIT(0) + +#define OA_TC6_HDR_SIZE 4 +#define OA_TC6_FTR_SIZE 4 +#define OA_TC6_BUF_ALLOC_TIMEOUT K_MSEC(10) + +/** + * @brief OA TC6 data. + */ +struct oa_tc6 { + /** Pointer to SPI device */ + const struct spi_dt_spec *spi; + + /** OA data payload (chunk) size */ + uint8_t cps; + + /** + * Number of available chunks buffers in OA TC6 device to store + * data for transmission + */ + uint8_t txc; + + /** Number of available chunks to read from OA TC6 device */ + uint8_t rca; + + /** Indication of pending interrupt in OA TC6 device */ + bool exst; + + /** Indication of OA TC6 device being ready for transmission */ + bool sync; + + /** Indication of protected control transmission mode */ + bool protected; + + /** Pointer to network buffer concatenated from received chunk */ + struct net_buf *concat_buf; +}; + +typedef struct { + uint32_t address; + uint32_t value; +} oa_mem_map_t; + +/** + * @brief Calculate parity bit from data + * + * @param x data to calculate parity + * + * @return 0 if number of ones is odd, 1 otherwise. + */ +static inline bool oa_tc6_get_parity(const uint32_t x) +{ + uint32_t y; + + y = x ^ (x >> 1); + y = y ^ (y >> 2); + y = y ^ (y >> 4); + y = y ^ (y >> 8); + y = y ^ (y >> 16); + + return !(y & 1); +} + +/** + * @brief Read OA TC6 compliant device single register + * + * @param tc6 OA TC6 specific data + * + * @param reg register to read + + * @param val pointer to variable to store read value + * + * @return 0 if read was successful, <0 otherwise. + */ +int oa_tc6_reg_read(struct oa_tc6 *tc6, const uint32_t reg, uint32_t *val); + +/** + * @brief Write to OA TC6 compliant device a single register + * + * @param tc6 OA TC6 specific data + * + * @param reg register to read + + * @param val data to send to device + * + * @return 0 if write was successful, <0 otherwise. + */ +int oa_tc6_reg_write(struct oa_tc6 *tc6, const uint32_t reg, uint32_t val); + +/** + * @brief Enable or disable the protected mode for control transactions + * + * @param tc6 OA TC6 specific data + * + * @param prote enable or disable protected control transactions + * + * @return 0 if operation was successful, <0 otherwise. + */ +int oa_tc6_set_protected_ctrl(struct oa_tc6 *tc6, bool prote); + +/** + * @brief Send OA TC6 data chunks to the device + * + * @param tc6 OA TC6 specific data + * + * @param pkt network packet to be send + * + * @return 0 if data send was successful, <0 otherwise. + */ +int oa_tc6_send_chunks(struct oa_tc6 *tc6, struct net_pkt *pkt); + +/** + * @brief Read data chunks from OA TC6 device + * + * @param tc6 OA TC6 specific data + * + * @param pkt network packet to store received data + * + * @return 0 if read was successful, <0 otherwise. + */ +int oa_tc6_read_chunks(struct oa_tc6 *tc6, struct net_pkt *pkt); + +/** + * @brief Perform SPI transfer of single chunk from/to OA TC6 device + * + * @param tc6 OA TC6 specific data + * + * @param buf_rx buffer to store read data + * + * @param buf_tx buffer with data to send + * + * @param hdr OA TC6 data transmission header value + * + * @param ftr poniter to OA TC6 data received footer + * + * @return 0 if transmission was successful, <0 otherwise. + */ +int oa_tc6_chunk_spi_transfer(struct oa_tc6 *tc6, uint8_t *buf_rx, uint8_t *buf_tx, + uint32_t hdr, uint32_t *ftr); + +/** + * @brief Read status from OA TC6 device + * + * @param tc6 OA TC6 specific data + * + * @param ftr poniter to OA TC6 data received footer + * + * @return 0 if successful, <0 otherwise. + */ +int oa_tc6_read_status(struct oa_tc6 *tc6, uint32_t *ftr); + +/** + * @brief Read from OA TC6 device and update buffer information + * + * @param tc6 OA TC6 specific data + * + * @return 0 if successful, <0 otherwise. + */ +int oa_tc6_update_buf_info(struct oa_tc6 *tc6); +#endif /* OA_TC6_CFG_H__ */ diff --git a/drivers/ethernet/phy/Kconfig b/drivers/ethernet/phy/Kconfig index bd5d9fb48ed..ae1229de1fc 100644 --- a/drivers/ethernet/phy/Kconfig +++ b/drivers/ethernet/phy/Kconfig @@ -23,7 +23,8 @@ config PHY_INIT_PRIORITY config PHY_GENERIC_MII bool "Generic MII PHY Driver" - default y if !ETH_ADIN2111 + default y + depends on DT_HAS_ETHERNET_PHY_ENABLED depends on MDIO help This is a generic MII PHY interface that communicates with the diff --git a/drivers/ethernet/phy/phy_adin2111.c b/drivers/ethernet/phy/phy_adin2111.c index 86f92f6e710..eb90eddd013 100644 --- a/drivers/ethernet/phy/phy_adin2111.c +++ b/drivers/ethernet/phy/phy_adin2111.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2023 PHOENIX CONTACT Electronics GmbH + * Copyright 2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,8 +18,8 @@ LOG_MODULE_REGISTER(phy_adin2111, CONFIG_PHY_LOG_LEVEL); #include #include #include +#include #include -#include /* PHYs out of reset check retry delay */ #define ADIN2111_PHY_AWAIT_DELAY_POLL_US 15U @@ -37,36 +38,10 @@ LOG_MODULE_REGISTER(phy_adin2111, CONFIG_PHY_LOG_LEVEL); #define ADIN2111_PHY_ID 0x0283BCA1U #define ADIN1110_PHY_ID 0x0283BC91U -/* 10BASE-T1L PMA Status Register */ -#define ADIN2111_PHY_PMA_STATUS 0x000108F7U -/* Indicates PHY support of 10BASE-T1L high voltage (2.4V) tx level op mode */ -#define ADIN2111_PHY_PMA_STATUS_B10L_TX_LVL_HI_ABLE BIT(12) - -/* BASE-T1 Autonegotiation Control Register */ -#define ADIN2111_PHY_AN_CONTROL 0x00070200U -/* Autonegotiation Enable */ -#define ADIN2111_PHY_AN_CONTROL_AN_EN BIT(12) -/* Autonegotiation Restart */ -#define ADIN2111_PHY_AN_CONTROL_AN_RESTART BIT(9) - -/* BASE-T1 Autonegotiation Status Register */ -#define ADIN2111_PHY_AN_STATUS 0x00070201U -/* Autonegotiation Complete */ -#define ADIN2111_PHY_AN_STATUS_AN_COMPLETE BIT(5) -/* Link Status */ -#define ADIN2111_PHY_AN_STATUS_AN_LINK_STATUS BIT(2) - -/* 10BASE-T1 Autonegotiation Advertisement Register */ -#define ADIN2111_PHY_AN_ADV_ABILITY_H 0x00070204U -/* Advertise PHY capability of 2.4V tx level op mode */ -#define ADIN2111_PHY_AN_ADV_ABILITY_H_B10L_TX_LVL_HI_ABL BIT(13) -/* Advertise PHY request of 2.4V tx level op mode */ -#define ADIN2111_PHY_AN_ADV_ABILITY_H_B10L_TX_LVL_HI_REQ BIT(12) - /* System Interrupt Mask Register */ -#define ADIN2111_PHY_CRSM_IRQ_MASK 0x001E0020U +#define ADIN2111_PHY_CRSM_IRQ_MASK 0x0020U /* System Interrupt Status Register */ -#define ADIN2111_PHY_CRSM_IRQ_STATUS 0x001E0010U +#define ADIN2111_PHY_CRSM_IRQ_STATUS 0x0010U /** * Mask of reserved interrupts that indicates a fatal error in the system. * @@ -82,21 +57,21 @@ LOG_MODULE_REGISTER(phy_adin2111, CONFIG_PHY_LOG_LEVEL); #define ADIN2111_PHY_CRSM_IRQ_STATUS_FATAL_ERR 0x2BFFU /* PHY Subsystem Interrupt Mask Register */ -#define ADIN2111_PHY_SUBSYS_IRQ_MASK 0x001F0021U +#define ADIN2111_PHY_SUBSYS_IRQ_MASK 0x0021U /* PHY Subsystem Interrupt Status Register */ -#define ADIN2111_PHY_SUBSYS_IRQ_STATUS 0x001F0011U +#define ADIN2111_PHY_SUBSYS_IRQ_STATUS 0x0011U /* Link Status Change */ #define ADIN2111_PHY_SUBSYS_IRQ_STATUS_LINK_STAT_CHNG_LH BIT(1) /* Software Power-down Control Register */ -#define ADIN2111_PHY_CRSM_SFT_PD_CNTRL 0x001E8812U +#define ADIN2111_PHY_CRSM_SFT_PD_CNTRL 0x8812U /* System Status Register */ -#define ADIN2111_PHY_CRSM_STAT 0x001E8818U +#define ADIN2111_PHY_CRSM_STAT 0x8818U /* Software Power-down Status */ #define ADIN2111_CRSM_STAT_CRSM_SFT_PD_RDY BIT(1) /* LED Control Register */ -#define ADIN2111_PHY_LED_CNTRL 0x001E8C82U +#define ADIN2111_PHY_LED_CNTRL 0x8C82U /* LED 1 Enable */ #define ADIN2111_PHY_LED_CNTRL_LED1_EN BIT(15) /* LED 0 Enable */ @@ -131,22 +106,20 @@ static inline int phy_adin2111_c22_write(const struct device *dev, uint16_t reg, return mdio_write(cfg->mdio, cfg->phy_addr, reg, val); } -static inline int phy_adin2111_c45_write(const struct device *dev, uint32_t reg, - uint16_t val) +static inline int phy_adin2111_c45_write(const struct device *dev, uint16_t devad, + uint16_t reg, uint16_t val) { const struct phy_adin2111_config *cfg = dev->config; - return adin2111_mdio_c45_write(cfg->mdio, cfg->phy_addr, ((reg >> 16U) & 0x1FU), - (reg & UINT16_MAX), val); + return mdio_write_c45(cfg->mdio, cfg->phy_addr, devad, reg, val); } -static inline int phy_adin2111_c45_read(const struct device *dev, uint32_t reg, - uint16_t *val) +static inline int phy_adin2111_c45_read(const struct device *dev, uint16_t devad, + uint16_t reg, uint16_t *val) { const struct phy_adin2111_config *cfg = dev->config; - return adin2111_mdio_c45_read(cfg->mdio, cfg->phy_addr, ((reg >> 16U) & 0x1FU), - (reg & 0xFFFFU), val); + return mdio_read_c45(cfg->mdio, cfg->phy_addr, devad, reg, val); } static int phy_adin2111_reg_read(const struct device *dev, uint16_t reg_addr, @@ -192,7 +165,8 @@ static int phy_adin2111_await_phy(const struct device *dev) * it comes out from reset. */ for (count = 0U; count < ADIN2111_PHY_AWAIT_RETRY_COUNT; ++count) { - ret = phy_adin2111_c45_read(dev, ADIN2111_PHY_CRSM_IRQ_MASK, &val); + ret = phy_adin2111_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC1, + ADIN2111_PHY_CRSM_IRQ_MASK, &val); if (ret >= 0) { if (val != 0U) { break; @@ -233,8 +207,9 @@ int phy_adin2111_handle_phy_irq(const struct device *dev, uint16_t subsys_status; int ret; - ret = phy_adin2111_c45_read(dev, ADIN2111_PHY_SUBSYS_IRQ_STATUS, - &subsys_status); + ret = phy_adin2111_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC2, + ADIN2111_PHY_SUBSYS_IRQ_STATUS, + &subsys_status); if (ret < 0) { return ret; } @@ -262,15 +237,16 @@ static int phy_adin2111_sft_pd(const struct device *dev, bool enter) const uint16_t expected = enter ? ADIN2111_CRSM_STAT_CRSM_SFT_PD_RDY : 0U; uint16_t val; - ret = phy_adin2111_c45_write(dev, ADIN2111_PHY_CRSM_SFT_PD_CNTRL, - enter ? 1U : 0U); + ret = phy_adin2111_c45_write(dev, MDIO_MMD_VENDOR_SPECIFIC1, + ADIN2111_PHY_CRSM_SFT_PD_CNTRL, + enter ? 1U : 0U); if (ret < 0) { return ret; } for (count = 0U; count < ADIN2111_PHY_SFT_PD_RETRY_COUNT; ++count) { - ret = phy_adin2111_c45_read(dev, ADIN2111_PHY_CRSM_STAT, - &val); + ret = phy_adin2111_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC1, + ADIN2111_PHY_CRSM_STAT, &val); if (ret >= 0) { if ((val & ADIN2111_CRSM_STAT_CRSM_SFT_PD_RDY) == expected) { break; @@ -368,20 +344,23 @@ static int phy_adin2111_init(const struct device *dev) } /* disable interrupts */ - ret = phy_adin2111_c45_write(dev, ADIN2111_PHY_CRSM_IRQ_MASK, 0U); + ret = phy_adin2111_c45_write(dev, MDIO_MMD_VENDOR_SPECIFIC1, + ADIN2111_PHY_CRSM_IRQ_MASK, 0U); if (ret < 0) { return ret; } /* enable link status change irq */ - ret = phy_adin2111_c45_write(dev, ADIN2111_PHY_SUBSYS_IRQ_MASK, + ret = phy_adin2111_c45_write(dev, MDIO_MMD_VENDOR_SPECIFIC2, + ADIN2111_PHY_SUBSYS_IRQ_MASK, ADIN2111_PHY_SUBSYS_IRQ_STATUS_LINK_STAT_CHNG_LH); if (ret < 0) { return ret; } /* clear PHY IRQ status before enabling ADIN IRQs */ - ret = phy_adin2111_c45_read(dev, ADIN2111_PHY_CRSM_IRQ_STATUS, &val); + ret = phy_adin2111_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC1, + ADIN2111_PHY_CRSM_IRQ_STATUS, &val); if (ret < 0) { return ret; } @@ -391,13 +370,15 @@ static int phy_adin2111_init(const struct device *dev) return -ENODEV; } - ret = phy_adin2111_c45_read(dev, ADIN2111_PHY_SUBSYS_IRQ_STATUS, &val); + ret = phy_adin2111_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC2, + ADIN2111_PHY_SUBSYS_IRQ_STATUS, &val); if (ret < 0) { return ret; } if (!cfg->led0_en || !cfg->led1_en) { - ret = phy_adin2111_c45_read(dev, ADIN2111_PHY_LED_CNTRL, &val); + ret = phy_adin2111_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC1, + ADIN2111_PHY_LED_CNTRL, &val); if (ret < 0) { return ret; } @@ -407,19 +388,20 @@ static int phy_adin2111_init(const struct device *dev) if (!cfg->led1_en) { val &= ~(ADIN2111_PHY_LED_CNTRL_LED1_EN); } - ret = phy_adin2111_c45_write(dev, ADIN2111_PHY_LED_CNTRL, val); + ret = phy_adin2111_c45_write(dev, MDIO_MMD_VENDOR_SPECIFIC1, + ADIN2111_PHY_LED_CNTRL, val); if (ret < 0) { return ret; } } /* check 2.4V support */ - ret = phy_adin2111_c45_read(dev, ADIN2111_PHY_PMA_STATUS, &val); + ret = phy_adin2111_c45_read(dev, MDIO_MMD_PMAPMD, MDIO_PMA_B10L_STAT, &val); if (ret < 0) { return ret; } - tx_24v_supported = !!(val & ADIN2111_PHY_PMA_STATUS_B10L_TX_LVL_HI_ABLE); + tx_24v_supported = !!(val & MDIO_PMA_B10L_STAT_2V4_ABLE); LOG_INF("PHY %u 2.4V mode %s", cfg->phy_addr, tx_24v_supported ? "supported" : "not supported"); @@ -430,16 +412,15 @@ static int phy_adin2111_init(const struct device *dev) } /* config 2.4V auto-negotiation */ - ret = phy_adin2111_c45_read(dev, ADIN2111_PHY_AN_ADV_ABILITY_H, - &val); + ret = phy_adin2111_c45_read(dev, MDIO_MMD_AN, MDIO_AN_T1_ADV_H, &val); if (ret < 0) { return ret; } if (tx_24v_supported) { - val |= ADIN2111_PHY_AN_ADV_ABILITY_H_B10L_TX_LVL_HI_ABL; + val |= MDIO_AN_T1_ADV_H_10L_TX_HI; } else { - val &= ~ADIN2111_PHY_AN_ADV_ABILITY_H_B10L_TX_LVL_HI_ABL; + val &= ~MDIO_AN_T1_ADV_H_10L_TX_HI; } if (cfg->tx_24v) { @@ -449,20 +430,19 @@ static int phy_adin2111_init(const struct device *dev) return -EINVAL; } - val |= ADIN2111_PHY_AN_ADV_ABILITY_H_B10L_TX_LVL_HI_REQ; + val |= MDIO_AN_T1_ADV_H_10L_TX_HI_REQ; } else { - val &= ~ADIN2111_PHY_AN_ADV_ABILITY_H_B10L_TX_LVL_HI_REQ; + val &= ~MDIO_AN_T1_ADV_H_10L_TX_HI_REQ; } - ret = phy_adin2111_c45_write(dev, ADIN2111_PHY_AN_ADV_ABILITY_H, - val); + ret = phy_adin2111_c45_write(dev, MDIO_MMD_AN, MDIO_AN_T1_ADV_H, val); if (ret < 0) { return ret; } /* enable auto-negotiation */ - ret = phy_adin2111_c45_write(dev, ADIN2111_PHY_AN_CONTROL, - ADIN2111_PHY_AN_CONTROL_AN_EN); + ret = phy_adin2111_c45_write(dev, MDIO_MMD_AN, MDIO_AN_T1_CTRL, + MDIO_AN_T1_CTRL_EN); if (ret < 0) { return ret; } diff --git a/drivers/ethernet/phy/phy_mii.c b/drivers/ethernet/phy/phy_mii.c index fa703cc685e..4ad961089e6 100644 --- a/drivers/ethernet/phy/phy_mii.c +++ b/drivers/ethernet/phy/phy_mii.c @@ -477,7 +477,7 @@ static const struct ethphy_driver_api phy_mii_driver_api = { #define PHY_MII_CONFIG(n) \ static const struct phy_mii_dev_config phy_mii_dev_config_##n = { \ - .phy_addr = DT_INST_PROP(n, address), \ + .phy_addr = DT_INST_REG_ADDR(n), \ .fixed = IS_FIXED_LINK(n), \ .fixed_speed = DT_INST_ENUM_IDX_OR(n, fixed_link, 0), \ .mdio = UTIL_AND(UTIL_NOT(IS_FIXED_LINK(n)), \ diff --git a/drivers/flash/CMakeLists.txt b/drivers/flash/CMakeLists.txt index e937d3ee5a9..4a02268a2b4 100644 --- a/drivers/flash/CMakeLists.txt +++ b/drivers/flash/CMakeLists.txt @@ -51,6 +51,7 @@ zephyr_library_sources_ifdef(CONFIG_FLASH_CAD_QSPI_NOR flash_cadence_qspi_nor.c zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_XMC4XXX soc_flash_xmc4xxx.c) zephyr_library_sources_ifdef(CONFIG_FLASH_RPI_PICO flash_rpi_pico.c) zephyr_library_sources_ifdef(CONFIG_FLASH_ANDES_QSPI flash_andes_qspi.c) +zephyr_library_sources_ifdef(CONFIG_FLASH_AMBIQ flash_ambiq.c) if(CONFIG_FLASH_MCUX_FLEXSPI_XIP) dt_chosen(chosen_flash PROPERTY "zephyr,flash") diff --git a/drivers/flash/Kconfig b/drivers/flash/Kconfig index 8660bed13e4..698190e7780 100644 --- a/drivers/flash/Kconfig +++ b/drivers/flash/Kconfig @@ -52,7 +52,7 @@ config FLASH_JESD216_API config FLASH_SHELL bool "Flash shell" depends on SHELL && FLASH_PAGE_LAYOUT - default y + select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enable the flash shell with flash related commands such as test, write, read and erase. @@ -158,4 +158,6 @@ source "drivers/flash/Kconfig.nxp_s32" source "drivers/flash/Kconfig.andes" +source "drivers/flash/Kconfig.ambiq" + endif # FLASH diff --git a/drivers/flash/Kconfig.ambiq b/drivers/flash/Kconfig.ambiq new file mode 100644 index 00000000000..cc84c0faf39 --- /dev/null +++ b/drivers/flash/Kconfig.ambiq @@ -0,0 +1,12 @@ +# Copyright (c) 2023 Ambiq Micro Inc. +# SPDX-License-Identifier: Apache-2.0 + +config FLASH_AMBIQ + bool "Ambiq flash driver on MRAM" + default y + depends on DT_HAS_AMBIQ_FLASH_CONTROLLER_ENABLED + select AMBIQ_HAL + select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_DRIVER_ENABLED + help + Enables Ambiq flash driver on MRAM. diff --git a/drivers/flash/Kconfig.nor b/drivers/flash/Kconfig.nor index 622ded42258..507e681c120 100644 --- a/drivers/flash/Kconfig.nor +++ b/drivers/flash/Kconfig.nor @@ -8,6 +8,7 @@ menuconfig SPI_NOR select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_JESD216 + select FLASH_HAS_EX_OP select SPI if SPI_NOR @@ -19,7 +20,8 @@ choice SPI_NOR_SFDP config SPI_NOR_SFDP_MINIMAL bool "Fixed flash configuration" help - Synthesize a minimal configuration assuming 256 By page size and + Synthesize a minimal configuration assuming 256 By page size (or as + set by the page-size devicetree property) and standard 4 KiBy and 64 KiBy erase instructions. Requires the size and jedec-id properties in the devicetree jedec,spi-nor node. diff --git a/drivers/flash/Kconfig.nordic_qspi_nor b/drivers/flash/Kconfig.nordic_qspi_nor index 7b9fa05eb7f..aac9830835a 100644 --- a/drivers/flash/Kconfig.nordic_qspi_nor +++ b/drivers/flash/Kconfig.nordic_qspi_nor @@ -8,6 +8,7 @@ menuconfig NORDIC_QSPI_NOR select FLASH_HAS_DRIVER_ENABLED select NRFX_QSPI select FLASH_JESD216 + select PINCTRL help Enable support for nrfx QSPI driver with EasyDMA. diff --git a/drivers/flash/Kconfig.npcx_fiu b/drivers/flash/Kconfig.npcx_fiu index d46d7f2e0dc..e4ac74c9d44 100644 --- a/drivers/flash/Kconfig.npcx_fiu +++ b/drivers/flash/Kconfig.npcx_fiu @@ -24,6 +24,8 @@ config FLASH_NPCX_FIU_NOR This option enables the QSPI NOR Flash driver for NPCX family of processors. +if FLASH_NPCX_FIU_QSPI + config FLASH_NPCX_FIU_NOR_INIT bool "QSPI NOR flash feature during driver initialization" default y @@ -32,3 +34,33 @@ config FLASH_NPCX_FIU_NOR_INIT This option enables the QSPI NOR Flash features such as Quad-Enable, 4-byte address support and so on during driver initialization. Disable it if QSPI NOR devices are not ready during driver initialization. + +config FLASH_NPCX_FIU_DRA_V1 + bool "Direct Read Access version 1 support" + default y if SOC_SERIES_NPCX9 + help + This option enables DRA V1 support. + +config FLASH_NPCX_FIU_DRA_V2 + bool "Direct Read Access version 2 support" + default y if SOC_SERIES_NPCX4 + help + This option enables DRA V1 support. + +config FLASH_NPCX_FIU_SUPP_DRA_4B_ADDR + bool "4 byte address support in Direct Read Access mode" + default y if FLASH_NPCX_FIU_DRA_V1 || \ + FLASH_NPCX_FIU_DRA_V2 + help + Selected if NPCX series supports 4 byte address mode in Direct Read + Access mode. + +config FLASH_NPCX_FIU_SUPP_DRA_2_DEV + bool "4 byte address support in Direct Read Access mode" + default y if FLASH_NPCX_FIU_DRA_V1 || \ + FLASH_NPCX_FIU_DRA_V2 + help + Selected if NPCX series supports two external SPI devices in Direct + Read Access (DRA) on QSPI bus. + +endif #FLASH_NPCX_FIU_QSPI diff --git a/drivers/flash/Kconfig.stm32 b/drivers/flash/Kconfig.stm32 index 55aa1c7dcca..5344d818322 100644 --- a/drivers/flash/Kconfig.stm32 +++ b/drivers/flash/Kconfig.stm32 @@ -8,13 +8,11 @@ config SOC_FLASH_STM32 bool "STM32 flash driver" - depends on DT_HAS_ST_STM32_FLASH_CONTROLLER_ENABLED || \ - DT_HAS_ST_STM32H7_FLASH_CONTROLLER_ENABLED + depends on DT_HAS_ST_STM32_FLASH_CONTROLLER_ENABLED select FLASH_HAS_DRIVER_ENABLED default y select FLASH_PAGE_LAYOUT select FLASH_HAS_PAGE_LAYOUT - select FLASH_HAS_EX_OP if SOC_SERIES_STM32F4X select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enable flash driver for STM32 series @@ -24,6 +22,7 @@ if SOC_FLASH_STM32 config FLASH_STM32_WRITE_PROTECT bool "Extended operation for flash write protection control" depends on SOC_SERIES_STM32F4X + select FLASH_HAS_EX_OP default n help Enables flash extended operation for enabling/disabling flash write @@ -39,7 +38,8 @@ config FLASH_STM32_WRITE_PROTECT_DISABLE_PREVENTION config FLASH_STM32_READOUT_PROTECTION bool "Extended operation for flash readout protection control" - depends on SOC_SERIES_STM32F4X + depends on SOC_SERIES_STM32F4X || SOC_SERIES_STM32L4X || SOC_SERIES_STM32G4X + select FLASH_HAS_EX_OP default n help Enables flash extended operation for enabling/disabling flash readout diff --git a/drivers/flash/flash_ambiq.c b/drivers/flash/flash_ambiq.c new file mode 100644 index 00000000000..fdc852c04ca --- /dev/null +++ b/drivers/flash/flash_ambiq.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2023 Ambiq Micro Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ambiq_flash_controller + +#include +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(flash_ambiq, CONFIG_FLASH_LOG_LEVEL); + +#define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash) +#define SOC_NV_FLASH_ADDR DT_REG_ADDR(SOC_NV_FLASH_NODE) +#define SOC_NV_FLASH_SIZE DT_REG_SIZE(SOC_NV_FLASH_NODE) +#define MIN_WRITE_SIZE 16 +#define FLASH_WRITE_BLOCK_SIZE MAX(DT_PROP(SOC_NV_FLASH_NODE, write_block_size), MIN_WRITE_SIZE) +#define FLASH_ERASE_BLOCK_SIZE DT_PROP(SOC_NV_FLASH_NODE, erase_block_size) + +BUILD_ASSERT((FLASH_WRITE_BLOCK_SIZE & (MIN_WRITE_SIZE - 1)) == 0, + "The flash write block size must be a multiple of 16!"); + +#define FLASH_ERASE_BYTE 0xFF +#define FLASH_ERASE_WORD \ + (((uint32_t)(FLASH_ERASE_BYTE << 24)) | ((uint32_t)(FLASH_ERASE_BYTE << 16)) | \ + ((uint32_t)(FLASH_ERASE_BYTE << 8)) | ((uint32_t)FLASH_ERASE_BYTE)) + +#if defined(CONFIG_MULTITHREADING) +static struct k_sem flash_ambiq_sem; +#define FLASH_SEM_INIT() k_sem_init(&flash_ambiq_sem, 1, 1) +#define FLASH_SEM_TAKE() k_sem_take(&flash_ambiq_sem, K_FOREVER) +#define FLASH_SEM_GIVE() k_sem_give(&flash_ambiq_sem) +#else +#define FLASH_SEM_INIT() +#define FLASH_SEM_TAKE() +#define FLASH_SEM_GIVE() +#endif /* CONFIG_MULTITHREADING */ + +static const struct flash_parameters flash_ambiq_parameters = { + .write_block_size = FLASH_WRITE_BLOCK_SIZE, + .erase_value = FLASH_ERASE_BYTE, +}; + +static bool flash_ambiq_valid_range(off_t offset, size_t len) +{ + if ((offset < 0) || offset >= SOC_NV_FLASH_SIZE || (SOC_NV_FLASH_SIZE - offset) < len) { + return false; + } + + return true; +} + +static int flash_ambiq_read(const struct device *dev, off_t offset, void *data, size_t len) +{ + ARG_UNUSED(dev); + + if (!flash_ambiq_valid_range(offset, len)) { + return -EINVAL; + } + + if (len == 0) { + return 0; + } + + memcpy(data, (uint8_t *)(SOC_NV_FLASH_ADDR + offset), len); + + return 0; +} + +static int flash_ambiq_write(const struct device *dev, off_t offset, const void *data, size_t len) +{ + ARG_UNUSED(dev); + + int ret = 0; + uint32_t critical = 0; + uint32_t aligned[FLASH_WRITE_BLOCK_SIZE / sizeof(uint32_t)] = {0}; + uint32_t *src = (uint32_t *)data; + + /* write address must be block size aligned and the write length must be multiple of block + * size. + */ + if (!flash_ambiq_valid_range(offset, len) || + ((uint32_t)offset & (FLASH_WRITE_BLOCK_SIZE - 1)) || + (len & (FLASH_WRITE_BLOCK_SIZE - 1))) { + return -EINVAL; + } + + if (len == 0) { + return 0; + } + + FLASH_SEM_TAKE(); + + critical = am_hal_interrupt_master_disable(); + for (int i = 0; i < len / FLASH_WRITE_BLOCK_SIZE; i++) { + for (int j = 0; j < FLASH_WRITE_BLOCK_SIZE / sizeof(uint32_t); j++) { + /* Make sure the source data is 4-byte aligned. */ + aligned[j] = UNALIGNED_GET((uint32_t *)src); + src++; + } + ret = am_hal_mram_main_program( + AM_HAL_MRAM_PROGRAM_KEY, aligned, + (uint32_t *)(SOC_NV_FLASH_ADDR + offset + i * FLASH_WRITE_BLOCK_SIZE), + FLASH_WRITE_BLOCK_SIZE / sizeof(uint32_t)); + if (ret) { + break; + } + } + am_hal_interrupt_master_set(critical); + + FLASH_SEM_GIVE(); + + return ret; +} + +static int flash_ambiq_erase(const struct device *dev, off_t offset, size_t len) +{ + ARG_UNUSED(dev); + + int ret = 0; + + if (!flash_ambiq_valid_range(offset, len)) { + return -EINVAL; + } + + /* The erase address and length alignment check will be done in HAL.*/ + + if (len == 0) { + return 0; + } + + FLASH_SEM_TAKE(); + + ret = am_hal_mram_main_fill(AM_HAL_MRAM_PROGRAM_KEY, FLASH_ERASE_WORD, + (uint32_t *)(SOC_NV_FLASH_ADDR + offset), + (len / sizeof(uint32_t))); + + FLASH_SEM_GIVE(); + + return ret; +} + +static const struct flash_parameters *flash_ambiq_get_parameters(const struct device *dev) +{ + ARG_UNUSED(dev); + + return &flash_ambiq_parameters; +} + +#if CONFIG_FLASH_PAGE_LAYOUT +static const struct flash_pages_layout pages_layout = { + .pages_count = SOC_NV_FLASH_SIZE / FLASH_ERASE_BLOCK_SIZE, + .pages_size = FLASH_ERASE_BLOCK_SIZE, +}; + +static void flash_ambiq_pages_layout(const struct device *dev, + const struct flash_pages_layout **layout, size_t *layout_size) +{ + ARG_UNUSED(dev); + + *layout = &pages_layout; + *layout_size = 1; +} +#endif /* CONFIG_FLASH_PAGE_LAYOUT */ + +static const struct flash_driver_api flash_ambiq_driver_api = { + .read = flash_ambiq_read, + .write = flash_ambiq_write, + .erase = flash_ambiq_erase, + .get_parameters = flash_ambiq_get_parameters, +#ifdef CONFIG_FLASH_PAGE_LAYOUT + .page_layout = flash_ambiq_pages_layout, +#endif +}; + +static int flash_ambiq_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + FLASH_SEM_INIT(); + + return 0; +} + +DEVICE_DT_INST_DEFINE(0, flash_ambiq_init, NULL, NULL, NULL, POST_KERNEL, + CONFIG_FLASH_INIT_PRIORITY, &flash_ambiq_driver_api); diff --git a/drivers/flash/flash_handlers.c b/drivers/flash/flash_handlers.c index 6d639420294..ac727b109e7 100644 --- a/drivers/flash/flash_handlers.c +++ b/drivers/flash/flash_handlers.c @@ -4,14 +4,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include static inline int z_vrfy_flash_read(const struct device *dev, off_t offset, void *data, size_t len) { - Z_OOPS(Z_SYSCALL_DRIVER_FLASH(dev, read)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(data, len)); + K_OOPS(K_SYSCALL_DRIVER_FLASH(dev, read)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(data, len)); return z_impl_flash_read((const struct device *)dev, offset, (void *)data, len); @@ -21,8 +21,8 @@ static inline int z_vrfy_flash_read(const struct device *dev, off_t offset, static inline int z_vrfy_flash_write(const struct device *dev, off_t offset, const void *data, size_t len) { - Z_OOPS(Z_SYSCALL_DRIVER_FLASH(dev, write)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(data, len)); + K_OOPS(K_SYSCALL_DRIVER_FLASH(dev, write)); + K_OOPS(K_SYSCALL_MEMORY_READ(data, len)); return z_impl_flash_write((const struct device *)dev, offset, (const void *)data, len); } @@ -31,21 +31,21 @@ static inline int z_vrfy_flash_write(const struct device *dev, off_t offset, static inline int z_vrfy_flash_erase(const struct device *dev, off_t offset, size_t size) { - Z_OOPS(Z_SYSCALL_DRIVER_FLASH(dev, erase)); + K_OOPS(K_SYSCALL_DRIVER_FLASH(dev, erase)); return z_impl_flash_erase((const struct device *)dev, offset, size); } #include static inline size_t z_vrfy_flash_get_write_block_size(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_FLASH)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_FLASH)); return z_impl_flash_get_write_block_size(dev); } #include static inline const struct flash_parameters *z_vrfy_flash_get_parameters(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_FLASH(dev, get_parameters)); + K_OOPS(K_SYSCALL_DRIVER_FLASH(dev, get_parameters)); return z_impl_flash_get_parameters(dev); } #include @@ -55,8 +55,8 @@ static inline int z_vrfy_flash_get_page_info_by_offs(const struct device *dev, off_t offs, struct flash_pages_info *info) { - Z_OOPS(Z_SYSCALL_DRIVER_FLASH(dev, page_layout)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(info, sizeof(struct flash_pages_info))); + K_OOPS(K_SYSCALL_DRIVER_FLASH(dev, page_layout)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(info, sizeof(struct flash_pages_info))); return z_impl_flash_get_page_info_by_offs((const struct device *)dev, offs, (struct flash_pages_info *)info); @@ -67,8 +67,8 @@ static inline int z_vrfy_flash_get_page_info_by_idx(const struct device *dev, uint32_t idx, struct flash_pages_info *info) { - Z_OOPS(Z_SYSCALL_DRIVER_FLASH(dev, page_layout)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(info, sizeof(struct flash_pages_info))); + K_OOPS(K_SYSCALL_DRIVER_FLASH(dev, page_layout)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(info, sizeof(struct flash_pages_info))); return z_impl_flash_get_page_info_by_idx((const struct device *)dev, idx, (struct flash_pages_info *)info); @@ -77,7 +77,7 @@ static inline int z_vrfy_flash_get_page_info_by_idx(const struct device *dev, static inline size_t z_vrfy_flash_get_page_count(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_FLASH(dev, page_layout)); + K_OOPS(K_SYSCALL_DRIVER_FLASH(dev, page_layout)); return z_impl_flash_get_page_count((const struct device *)dev); } #include @@ -90,8 +90,8 @@ static inline int z_vrfy_flash_sfdp_read(const struct device *dev, off_t offset, void *data, size_t len) { - Z_OOPS(Z_SYSCALL_DRIVER_FLASH(dev, sfdp_read)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(data, len)); + K_OOPS(K_SYSCALL_DRIVER_FLASH(dev, sfdp_read)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(data, len)); return z_impl_flash_sfdp_read(dev, offset, data, len); } #include @@ -99,8 +99,8 @@ static inline int z_vrfy_flash_sfdp_read(const struct device *dev, static inline int z_vrfy_flash_read_jedec_id(const struct device *dev, uint8_t *id) { - Z_OOPS(Z_SYSCALL_DRIVER_FLASH(dev, read_jedec_id)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(id, 3)); + K_OOPS(K_SYSCALL_DRIVER_FLASH(dev, read_jedec_id)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(id, 3)); return z_impl_flash_read_jedec_id(dev, id); } #include @@ -112,7 +112,7 @@ static inline int z_vrfy_flash_read_jedec_id(const struct device *dev, static inline int z_vrfy_flash_ex_op(const struct device *dev, uint16_t code, const uintptr_t in, void *out) { - Z_OOPS(Z_SYSCALL_DRIVER_FLASH(dev, ex_op)); + K_OOPS(K_SYSCALL_DRIVER_FLASH(dev, ex_op)); /* * If the code is a vendor code, then ex_op function have to perform diff --git a/drivers/flash/flash_mcux_flexspi_hyperflash.c b/drivers/flash/flash_mcux_flexspi_hyperflash.c index d1c6cb1ee06..b0a04ee63ed 100644 --- a/drivers/flash/flash_mcux_flexspi_hyperflash.c +++ b/drivers/flash/flash_mcux_flexspi_hyperflash.c @@ -596,7 +596,6 @@ static int flash_flexspi_hyperflash_init(const struct device *dev) { const struct flash_flexspi_hyperflash_config *config = dev->config; struct flash_flexspi_hyperflash_data *data = dev->data; - uint32_t temp_lut[sizeof(flash_flexspi_hyperflash_lut) / sizeof(uint32_t)]; /* Since the controller variable may be used in critical sections, * copy the device pointer into a variable stored in RAM @@ -610,27 +609,15 @@ static int flash_flexspi_hyperflash_init(const struct device *dev) memc_flexspi_wait_bus_idle(&data->controller); - if (!memc_flexspi_is_running_xip(&data->controller) && - memc_flexspi_set_device_config(&data->controller, &data->config, - data->port)) { - LOG_ERR("Could not set device configuration"); - return -EINVAL; + if (memc_flexspi_is_running_xip(&data->controller)) { + /* Wait for bus idle before configuring */ + memc_flexspi_wait_bus_idle(&data->controller); } - - /* - * Using the LUT stored in the FlexSPI directly when updating - * the FlexSPI can result in an invalid LUT entry being stored, - * as the LUT itself describes how the FlexSPI should access the flash. - * To resolve this, copy the LUT to a array placed in RAM before - * updating the FlexSPI. - */ - memcpy(temp_lut, flash_flexspi_hyperflash_lut, - sizeof(flash_flexspi_hyperflash_lut)); - - if (memc_flexspi_update_lut(&data->controller, 0, - (const uint32_t *) temp_lut, - sizeof(temp_lut) / sizeof(uint32_t))) { - LOG_ERR("Could not update lut"); + if (memc_flexspi_set_device_config(&data->controller, &data->config, + (const uint32_t *)flash_flexspi_hyperflash_lut, + sizeof(flash_flexspi_hyperflash_lut) / MEMC_FLEXSPI_CMD_SIZE, + data->port)) { + LOG_ERR("Could not set device configuration"); return -EINVAL; } diff --git a/drivers/flash/flash_mcux_flexspi_mx25um51345g.c b/drivers/flash/flash_mcux_flexspi_mx25um51345g.c index 0caa535529c..b72da49d154 100644 --- a/drivers/flash/flash_mcux_flexspi_mx25um51345g.c +++ b/drivers/flash/flash_mcux_flexspi_mx25um51345g.c @@ -17,7 +17,6 @@ #include #endif -#define NOR_WRITE_SIZE 1 #define NOR_ERASE_VALUE 0xff #ifdef CONFIG_FLASH_MCUX_FLEXSPI_NOR_WRITE_BUFFER @@ -40,8 +39,11 @@ static uint8_t nor_write_buf[SPI_NOR_PAGE_SIZE]; /* FLASH_ENABLE_OCTAL_CMD: (01 = STR OPI Enable) , (02 = DTR OPI Enable) */ #if CONFIG_FLASH_MCUX_FLEXSPI_MX25UM51345G_OPI_DTR #define NOR_FLASH_ENABLE_OCTAL_CMD 0x2 +/* In OPI DTR mode, all writes must be 2 byte aligned, and multiples of 2 bytes */ +#define NOR_WRITE_SIZE 2 #else #define NOR_FLASH_ENABLE_OCTAL_CMD 0x1 +#define NOR_WRITE_SIZE 1 #endif LOG_MODULE_REGISTER(flash_flexspi_nor, CONFIG_FLASH_LOG_LEVEL); @@ -388,6 +390,12 @@ static int flash_flexspi_nor_write(const struct device *dev, off_t offset, */ key = irq_lock(); } + if (IS_ENABLED(CONFIG_FLASH_MCUX_FLEXSPI_MX25UM51345G_OPI_DTR)) { + /* Check that write size and length are even */ + if ((offset & 0x1) || (len & 0x1)) { + return -EINVAL; + } + } while (len) { /* If the offset isn't a multiple of the NOR page size, we first need @@ -504,34 +512,22 @@ static int flash_flexspi_nor_init(const struct device *dev) { struct flash_flexspi_nor_data *data = dev->data; uint8_t vendor_id; - uint32_t temp_lut[sizeof(flash_flexspi_nor_lut) / sizeof(uint32_t)]; if (!device_is_ready(data->controller)) { LOG_ERR("Controller device not ready"); return -ENODEV; } - if (!memc_flexspi_is_running_xip(data->controller) && - memc_flexspi_set_device_config(data->controller, &data->config, - data->port)) { - LOG_ERR("Could not set device configuration"); - return -EINVAL; + if (memc_flexspi_is_running_xip(data->controller)) { + /* Wait for bus idle before configuring */ + memc_flexspi_wait_bus_idle(data->controller); } - /* - * Using the LUT stored in the FlexSPI directly when updating - * the FlexSPI can result in an invalid LUT entry being stored, - * as the LUT itself describes how the FlexSPI should access the flash. - * To resolve this, copy the LUT to a array placed in RAM before - * updating the FlexSPI. - */ - memcpy(temp_lut, flash_flexspi_nor_lut, - sizeof(flash_flexspi_nor_lut)); - - if (memc_flexspi_update_lut(data->controller, 0, - (const uint32_t *) temp_lut, - sizeof(temp_lut) / sizeof(uint32_t))) { - LOG_ERR("Could not update lut"); + if (memc_flexspi_set_device_config(data->controller, &data->config, + (const uint32_t *)flash_flexspi_nor_lut, + sizeof(flash_flexspi_nor_lut) / MEMC_FLEXSPI_CMD_SIZE, + data->port)) { + LOG_ERR("Could not set device configuration"); return -EINVAL; } diff --git a/drivers/flash/flash_mcux_flexspi_nor.c b/drivers/flash/flash_mcux_flexspi_nor.c index e863bc9b8db..8a9c4f182ad 100644 --- a/drivers/flash/flash_mcux_flexspi_nor.c +++ b/drivers/flash/flash_mcux_flexspi_nor.c @@ -58,9 +58,17 @@ enum { ERASE_CHIP, }; +struct flash_flexspi_nor_config { + /* Note: don't use this controller reference in code. It is + * only used during init to copy the device structure from ROM + * into a RAM structure + */ + const struct device *controller; +}; + /* Device variables used in critical sections should be in this structure */ struct flash_flexspi_nor_data { - const struct device *controller; + struct device controller; flexspi_device_config_t config; flexspi_port_t port; struct flash_pages_layout layout; @@ -154,10 +162,9 @@ static const uint32_t flash_flexspi_nor_lut[][4] = { }, }; -static int flash_flexspi_nor_get_vendor_id(const struct device *dev, +static int flash_flexspi_nor_get_vendor_id(struct flash_flexspi_nor_data *data, uint8_t *vendor_id) { - struct flash_flexspi_nor_data *data = dev->data; uint32_t buffer = 0; int ret; @@ -173,17 +180,15 @@ static int flash_flexspi_nor_get_vendor_id(const struct device *dev, LOG_DBG("Reading id"); - ret = memc_flexspi_transfer(data->controller, &transfer); + ret = memc_flexspi_transfer(&data->controller, &transfer); *vendor_id = buffer; return ret; } -static int flash_flexspi_nor_read_status(const struct device *dev, +static int flash_flexspi_nor_read_status(struct flash_flexspi_nor_data *data, uint32_t *status) { - struct flash_flexspi_nor_data *data = dev->data; - flexspi_transfer_t transfer = { .deviceAddress = 0, .port = data->port, @@ -196,14 +201,12 @@ static int flash_flexspi_nor_read_status(const struct device *dev, LOG_DBG("Reading status register"); - return memc_flexspi_transfer(data->controller, &transfer); + return memc_flexspi_transfer(&data->controller, &transfer); } -static int flash_flexspi_nor_write_status(const struct device *dev, +static int flash_flexspi_nor_write_status(struct flash_flexspi_nor_data *data, uint32_t *status) { - struct flash_flexspi_nor_data *data = dev->data; - flexspi_transfer_t transfer = { .deviceAddress = 0, .port = data->port, @@ -216,13 +219,11 @@ static int flash_flexspi_nor_write_status(const struct device *dev, LOG_DBG("Writing status register"); - return memc_flexspi_transfer(data->controller, &transfer); + return memc_flexspi_transfer(&data->controller, &transfer); } -static int flash_flexspi_nor_write_enable(const struct device *dev) +static int flash_flexspi_nor_write_enable(struct flash_flexspi_nor_data *data) { - struct flash_flexspi_nor_data *data = dev->data; - flexspi_transfer_t transfer = { .deviceAddress = 0, .port = data->port, @@ -235,14 +236,12 @@ static int flash_flexspi_nor_write_enable(const struct device *dev) LOG_DBG("Enabling write"); - return memc_flexspi_transfer(data->controller, &transfer); + return memc_flexspi_transfer(&data->controller, &transfer); } -static int flash_flexspi_nor_erase_sector(const struct device *dev, +static int flash_flexspi_nor_erase_sector(struct flash_flexspi_nor_data *data, off_t offset) { - struct flash_flexspi_nor_data *data = dev->data; - flexspi_transfer_t transfer = { .deviceAddress = offset, .port = data->port, @@ -255,14 +254,12 @@ static int flash_flexspi_nor_erase_sector(const struct device *dev, LOG_DBG("Erasing sector at 0x%08zx", (ssize_t) offset); - return memc_flexspi_transfer(data->controller, &transfer); + return memc_flexspi_transfer(&data->controller, &transfer); } -static int flash_flexspi_nor_erase_block(const struct device *dev, +static int flash_flexspi_nor_erase_block(struct flash_flexspi_nor_data *data, off_t offset) { - struct flash_flexspi_nor_data *data = dev->data; - flexspi_transfer_t transfer = { .deviceAddress = offset, .port = data->port, @@ -275,13 +272,11 @@ static int flash_flexspi_nor_erase_block(const struct device *dev, LOG_DBG("Erasing block at 0x%08zx", (ssize_t) offset); - return memc_flexspi_transfer(data->controller, &transfer); + return memc_flexspi_transfer(&data->controller, &transfer); } -static int flash_flexspi_nor_erase_chip(const struct device *dev) +static int flash_flexspi_nor_erase_chip(struct flash_flexspi_nor_data *data) { - struct flash_flexspi_nor_data *data = dev->data; - flexspi_transfer_t transfer = { .deviceAddress = 0, .port = data->port, @@ -294,14 +289,12 @@ static int flash_flexspi_nor_erase_chip(const struct device *dev) LOG_DBG("Erasing chip"); - return memc_flexspi_transfer(data->controller, &transfer); + return memc_flexspi_transfer(&data->controller, &transfer); } -static int flash_flexspi_nor_page_program(const struct device *dev, +static int flash_flexspi_nor_page_program(struct flash_flexspi_nor_data *data, off_t offset, const void *buffer, size_t len) { - struct flash_flexspi_nor_data *data = dev->data; - flexspi_transfer_t transfer = { .deviceAddress = offset, .port = data->port, @@ -314,16 +307,16 @@ static int flash_flexspi_nor_page_program(const struct device *dev, LOG_DBG("Page programming %d bytes to 0x%08zx", len, (ssize_t) offset); - return memc_flexspi_transfer(data->controller, &transfer); + return memc_flexspi_transfer(&data->controller, &transfer); } -static int flash_flexspi_nor_wait_bus_busy(const struct device *dev) +static int flash_flexspi_nor_wait_bus_busy(struct flash_flexspi_nor_data *data) { uint32_t status = 0; int ret; do { - ret = flash_flexspi_nor_read_status(dev, &status); + ret = flash_flexspi_nor_read_status(data, &status); LOG_DBG("status: 0x%x", status); if (ret) { LOG_ERR("Could not read status"); @@ -334,14 +327,13 @@ static int flash_flexspi_nor_wait_bus_busy(const struct device *dev) return 0; } -static int flash_flexspi_nor_enable_quad_mode(const struct device *dev) +static int flash_flexspi_nor_enable_quad_mode(struct flash_flexspi_nor_data *data) { - struct flash_flexspi_nor_data *data = dev->data; uint32_t status = 0x40; - flash_flexspi_nor_write_status(dev, &status); - flash_flexspi_nor_wait_bus_busy(dev); - memc_flexspi_reset(data->controller); + flash_flexspi_nor_write_status(data, &status); + flash_flexspi_nor_wait_bus_busy(data); + memc_flexspi_reset(&data->controller); return 0; } @@ -350,7 +342,7 @@ static int flash_flexspi_nor_read(const struct device *dev, off_t offset, void *buffer, size_t len) { struct flash_flexspi_nor_data *data = dev->data; - uint8_t *src = memc_flexspi_get_ahb_address(data->controller, + uint8_t *src = memc_flexspi_get_ahb_address(&data->controller, data->port, offset); @@ -368,11 +360,11 @@ static int flash_flexspi_nor_write(const struct device *dev, off_t offset, int i; unsigned int key = 0; - uint8_t *dst = memc_flexspi_get_ahb_address(data->controller, + uint8_t *dst = memc_flexspi_get_ahb_address(&data->controller, data->port, offset); - if (memc_flexspi_is_running_xip(data->controller)) { + if (memc_flexspi_is_running_xip(&data->controller)) { /* * ==== ENTER CRITICAL SECTION ==== * No flash access should be performed in critical section. All @@ -390,20 +382,20 @@ static int flash_flexspi_nor_write(const struct device *dev, off_t offset, #ifdef CONFIG_FLASH_MCUX_FLEXSPI_NOR_WRITE_BUFFER memcpy(nor_write_buf, src, i); #endif - flash_flexspi_nor_write_enable(dev); + flash_flexspi_nor_write_enable(data); #ifdef CONFIG_FLASH_MCUX_FLEXSPI_NOR_WRITE_BUFFER - flash_flexspi_nor_page_program(dev, offset, nor_write_buf, i); + flash_flexspi_nor_page_program(data, offset, nor_write_buf, i); #else - flash_flexspi_nor_page_program(dev, offset, src, i); + flash_flexspi_nor_page_program(data, offset, src, i); #endif - flash_flexspi_nor_wait_bus_busy(dev); - memc_flexspi_reset(data->controller); + flash_flexspi_nor_wait_bus_busy(data); + memc_flexspi_reset(&data->controller); src += i; offset += i; len -= i; } - if (memc_flexspi_is_running_xip(data->controller)) { + if (memc_flexspi_is_running_xip(&data->controller)) { /* ==== EXIT CRITICAL SECTION ==== */ irq_unlock(key); } @@ -425,7 +417,7 @@ static int flash_flexspi_nor_erase(const struct device *dev, off_t offset, int i; unsigned int key = 0; - uint8_t *dst = memc_flexspi_get_ahb_address(data->controller, + uint8_t *dst = memc_flexspi_get_ahb_address(&data->controller, data->port, offset); @@ -439,7 +431,7 @@ static int flash_flexspi_nor_erase(const struct device *dev, off_t offset, return -EINVAL; } - if (memc_flexspi_is_running_xip(data->controller)) { + if (memc_flexspi_is_running_xip(&data->controller)) { /* * ==== ENTER CRITICAL SECTION ==== * No flash access should be performed in critical section. All @@ -449,29 +441,29 @@ static int flash_flexspi_nor_erase(const struct device *dev, off_t offset, } if ((offset == 0) && (size == data->config.flashSize * KB(1))) { - flash_flexspi_nor_write_enable(dev); - flash_flexspi_nor_erase_chip(dev); - flash_flexspi_nor_wait_bus_busy(dev); - memc_flexspi_reset(data->controller); + flash_flexspi_nor_write_enable(data); + flash_flexspi_nor_erase_chip(data); + flash_flexspi_nor_wait_bus_busy(data); + memc_flexspi_reset(&data->controller); } else if ((0 == (offset % SPI_NOR_BLOCK_SIZE)) && (0 == (size % SPI_NOR_BLOCK_SIZE))) { for (i = 0; i < num_blocks; i++) { - flash_flexspi_nor_write_enable(dev); - flash_flexspi_nor_erase_block(dev, offset); - flash_flexspi_nor_wait_bus_busy(dev); - memc_flexspi_reset(data->controller); + flash_flexspi_nor_write_enable(data); + flash_flexspi_nor_erase_block(data, offset); + flash_flexspi_nor_wait_bus_busy(data); + memc_flexspi_reset(&data->controller); offset += SPI_NOR_BLOCK_SIZE; } } else { for (i = 0; i < num_sectors; i++) { - flash_flexspi_nor_write_enable(dev); - flash_flexspi_nor_erase_sector(dev, offset); - flash_flexspi_nor_wait_bus_busy(dev); - memc_flexspi_reset(data->controller); + flash_flexspi_nor_write_enable(data); + flash_flexspi_nor_erase_sector(data, offset); + flash_flexspi_nor_wait_bus_busy(data); + memc_flexspi_reset(&data->controller); offset += SPI_NOR_SECTOR_SIZE; } } - if (memc_flexspi_is_running_xip(data->controller)) { + if (memc_flexspi_is_running_xip(&data->controller)) { /* ==== EXIT CRITICAL SECTION ==== */ irq_unlock(key); } @@ -504,48 +496,42 @@ static void flash_flexspi_nor_pages_layout(const struct device *dev, static int flash_flexspi_nor_init(const struct device *dev) { + const struct flash_flexspi_nor_config *config = dev->config; struct flash_flexspi_nor_data *data = dev->data; uint8_t vendor_id; - uint32_t temp_lut[sizeof(flash_flexspi_nor_lut) / sizeof(uint32_t)]; - if (!device_is_ready(data->controller)) { + /* First step- use ROM pointer to controller device to create + * a copy of the device structure in RAM we can use while in + * critical sections of code. + */ + memcpy(&data->controller, config->controller, sizeof(struct device)); + + if (!device_is_ready(&data->controller)) { LOG_ERR("Controller device is not ready"); return -ENODEV; } - if (!memc_flexspi_is_running_xip(data->controller) && - memc_flexspi_set_device_config(data->controller, &data->config, - data->port)) { - LOG_ERR("Could not set device configuration"); - return -EINVAL; + if (memc_flexspi_is_running_xip(&data->controller)) { + /* Wait for bus idle before configuring */ + memc_flexspi_wait_bus_idle(&data->controller); } - - /* - * Using the LUT stored in the FlexSPI directly when updating - * the FlexSPI can result in an invalid LUT entry being stored, - * as the LUT itself describes how the FlexSPI should access the flash. - * To resolve this, copy the LUT to a array placed in RAM before - * updating the FlexSPI. - */ - memcpy(temp_lut, flash_flexspi_nor_lut, - sizeof(flash_flexspi_nor_lut)); - - if (memc_flexspi_update_lut(data->controller, 0, - (const uint32_t *) temp_lut, - sizeof(temp_lut) / sizeof(uint32_t))) { - LOG_ERR("Could not update lut"); + if (memc_flexspi_set_device_config(&data->controller, &data->config, + (const uint32_t *)flash_flexspi_nor_lut, + sizeof(flash_flexspi_nor_lut) / MEMC_FLEXSPI_CMD_SIZE, + data->port)) { + LOG_ERR("Could not set device configuration"); return -EINVAL; } - memc_flexspi_reset(data->controller); + memc_flexspi_reset(&data->controller); - if (flash_flexspi_nor_get_vendor_id(dev, &vendor_id)) { + if (flash_flexspi_nor_get_vendor_id(data, &vendor_id)) { LOG_ERR("Could not read vendor id"); return -EIO; } LOG_DBG("Vendor id: 0x%0x", vendor_id); - if (flash_flexspi_nor_enable_quad_mode(dev)) { + if (flash_flexspi_nor_enable_quad_mode(data)) { LOG_ERR("Could not enable quad mode"); return -EIO; } @@ -596,9 +582,12 @@ static const struct flash_driver_api flash_flexspi_nor_api = { } \ #define FLASH_FLEXSPI_NOR(n) \ + static const struct flash_flexspi_nor_config \ + flash_flexspi_nor_config_##n = { \ + .controller = DEVICE_DT_GET(DT_INST_BUS(n)), \ + }; \ static struct flash_flexspi_nor_data \ flash_flexspi_nor_data_##n = { \ - .controller = DEVICE_DT_GET(DT_INST_BUS(n)), \ .config = FLASH_FLEXSPI_DEVICE_CONFIG(n), \ .port = DT_INST_REG_ADDR(n), \ .layout = { \ @@ -616,7 +605,7 @@ static const struct flash_driver_api flash_flexspi_nor_api = { flash_flexspi_nor_init, \ NULL, \ &flash_flexspi_nor_data_##n, \ - NULL, \ + &flash_flexspi_nor_config_##n, \ POST_KERNEL, \ CONFIG_FLASH_INIT_PRIORITY, \ &flash_flexspi_nor_api); diff --git a/drivers/flash/flash_npcx_fiu_nor.c b/drivers/flash/flash_npcx_fiu_nor.c index 6b99e832f24..e42aa82f896 100644 --- a/drivers/flash/flash_npcx_fiu_nor.c +++ b/drivers/flash/flash_npcx_fiu_nor.c @@ -14,7 +14,7 @@ #include #ifdef CONFIG_USERSPACE #include -#include +#include #endif #include "flash_npcx_fiu_qspi.h" @@ -453,7 +453,7 @@ static int flash_npcx_nor_ex_op(const struct device *dev, uint16_t code, struct npcx_ex_ops_uma_out out_copy; if (syscall_trap) { - Z_OOPS(z_user_from_copy(&in_copy, op_in, sizeof(in_copy))); + K_OOPS(k_usermode_from_copy(&in_copy, op_in, sizeof(in_copy))); op_in = &in_copy; op_out = &out_copy; } @@ -462,7 +462,7 @@ static int flash_npcx_nor_ex_op(const struct device *dev, uint16_t code, ret = flash_npcx_nor_ex_exec_uma(dev, op_in, op_out); #ifdef CONFIG_USERSPACE if (ret == 0 && syscall_trap) { - Z_OOPS(z_user_to_copy(out, op_out, sizeof(out_copy))); + K_OOPS(k_usermode_to_copy(out, op_out, sizeof(out_copy))); } #endif break; @@ -474,7 +474,7 @@ static int flash_npcx_nor_ex_op(const struct device *dev, uint16_t code, struct npcx_ex_ops_qspi_oper_in in_copy; if (syscall_trap) { - Z_OOPS(z_user_from_copy(&in_copy, op_in, sizeof(in_copy))); + K_OOPS(k_usermode_from_copy(&in_copy, op_in, sizeof(in_copy))); op_in = &in_copy; } #endif @@ -495,7 +495,7 @@ static int flash_npcx_nor_ex_op(const struct device *dev, uint16_t code, ret = flash_npcx_nor_ex_get_spi_spec(dev, op_out); #ifdef CONFIG_USERSPACE if (ret == 0 && syscall_trap) { - Z_OOPS(z_user_to_copy(out, op_out, sizeof(out_copy))); + K_OOPS(k_usermode_to_copy(out, op_out, sizeof(out_copy))); } #endif break; diff --git a/drivers/flash/flash_npcx_fiu_qspi.c b/drivers/flash/flash_npcx_fiu_qspi.c index 3af0d4092a6..39e699bbef9 100644 --- a/drivers/flash/flash_npcx_fiu_qspi.c +++ b/drivers/flash/flash_npcx_fiu_qspi.c @@ -99,10 +99,10 @@ static inline void qspi_npcx_config_uma_mode(const struct device *dev, static inline void qspi_npcx_config_dra_4byte_mode(const struct device *dev, const struct npcx_qspi_cfg *qspi_cfg) { -#if !defined(CONFIG_SOC_SERIES_NPCX7) /* NPCX7 doesn't support this feature */ +#if defined(CONFIG_FLASH_NPCX_FIU_SUPP_DRA_4B_ADDR) struct fiu_reg *const inst = HAL_INSTANCE(dev); -#if defined(CONFIG_SOC_SERIES_NPCX9) +#if defined(CONFIG_FLASH_NPCX_FIU_DRA_V1) if (qspi_cfg->enter_4ba != 0) { if ((qspi_cfg->flags & NPCX_QSPI_SEC_FLASH_SL) != 0) { inst->SPI1_DEV |= BIT(NPCX_SPI1_DEV_FOUR_BADDR_CS11); @@ -113,12 +113,12 @@ static inline void qspi_npcx_config_dra_4byte_mode(const struct device *dev, inst->SPI1_DEV &= ~(BIT(NPCX_SPI1_DEV_FOUR_BADDR_CS11) | BIT(NPCX_SPI1_DEV_FOUR_BADDR_CS10)); } -#elif defined(CONFIG_SOC_SERIES_NPCX4) +#elif defined(CONFIG_FLASH_NPCX_FIU_DRA_V2) if (qspi_cfg->enter_4ba != 0) { SET_FIELD(inst->SPI_DEV, NPCX_SPI_DEV_NADDRB, NPCX_DEV_NUM_ADDR_4BYTE); } #endif -#endif /* CONFIG_SOC_SERIES_NPCX7 */ +#endif /* CONFIG_FLASH_NPCX_FIU_SUPP_DRA_4B_ADDR */ } static inline void qspi_npcx_config_dra_mode(const struct device *dev, @@ -127,7 +127,7 @@ static inline void qspi_npcx_config_dra_mode(const struct device *dev, struct fiu_reg *const inst = HAL_INSTANCE(dev); /* Select SPI device number for DRA mode in npcx4 series */ - if (IS_ENABLED(CONFIG_SOC_SERIES_NPCX4)) { + if (IS_ENABLED(CONFIG_FLASH_NPCX_FIU_DRA_V2)) { int spi_dev_num = (qspi_cfg->flags & NPCX_QSPI_SEC_FLASH_SL) != 0 ? 1 : 0; SET_FIELD(inst->BURST_CFG, NPCX_BURST_CFG_SPI_DEV_SEL, spi_dev_num); @@ -247,7 +247,6 @@ void qspi_npcx_fiu_mutex_unlock(const struct device *dev) static int qspi_npcx_fiu_init(const struct device *dev) { const struct npcx_qspi_fiu_config *const config = dev->config; - struct fiu_reg *const inst = HAL_INSTANCE(dev); struct npcx_qspi_fiu_data *const data = dev->data; const struct device *const clk_dev = DEVICE_DT_GET(NPCX_CLK_CTRL_NODE); int ret; @@ -270,9 +269,11 @@ static int qspi_npcx_fiu_init(const struct device *dev) /* Enable direct access for 2 external SPI devices */ if (config->en_direct_access_2dev) { - if (IS_ENABLED(CONFIG_SOC_SERIES_NPCX9) || IS_ENABLED(CONFIG_SOC_SERIES_NPCX4)) { - inst->FIU_EXT_CFG |= BIT(NPCX_FIU_EXT_CFG_SPI1_2DEV); - } +#if defined(CONFIG_FLASH_NPCX_FIU_SUPP_DRA_2_DEV) + struct fiu_reg *const inst = HAL_INSTANCE(dev); + + inst->FIU_EXT_CFG |= BIT(NPCX_FIU_EXT_CFG_SPI1_2DEV); +#endif } return 0; diff --git a/drivers/flash/flash_sam0.c b/drivers/flash/flash_sam0.c index b5fc5567cb8..eb55c5d36a0 100644 --- a/drivers/flash/flash_sam0.c +++ b/drivers/flash/flash_sam0.c @@ -5,6 +5,7 @@ */ #define DT_DRV_COMPAT atmel_sam0_nvmctrl +#define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash) #define LOG_LEVEL CONFIG_FLASH_LOG_LEVEL #include @@ -17,6 +18,9 @@ LOG_MODULE_REGISTER(flash_sam0); #include #include +#define FLASH_WRITE_BLK_SZ DT_PROP(SOC_NV_FLASH_NODE, write_block_size) +BUILD_ASSERT((FLASH_WRITE_BLK_SZ % sizeof(uint32_t)) == 0, "unsupported write-block-size"); + /* * Zephyr and the SAM0 series use different and conflicting names for * the erasable units and programmable units: @@ -67,7 +71,7 @@ static const struct flash_parameters flash_sam0_parameters = { #if CONFIG_SOC_FLASH_SAM0_EMULATE_BYTE_PAGES .write_block_size = 1, #else - .write_block_size = DT_PROP(DT_INST(0, soc_nv_flash), write_block_size), + .write_block_size = FLASH_WRITE_BLK_SZ, #endif .erase_value = 0xff, }; @@ -147,11 +151,18 @@ static int flash_sam0_check_status(off_t offset) return 0; } +/* + * Data to be written to the NVM block are first written to and stored + * in an internal buffer called the page buffer. The page buffer contains + * the same number of bytes as an NVM page. Writes to the page buffer must + * be 16 or 32 bits. 8-bit writes to the page buffer are not allowed and + * will cause a system exception + */ static int flash_sam0_write_page(const struct device *dev, off_t offset, - const void *data) + const void *data, size_t len) { const uint32_t *src = data; - const uint32_t *end = src + FLASH_PAGE_SIZE / sizeof(*src); + const uint32_t *end = src + (len / sizeof(*src)); uint32_t *dst = FLASH_MEM(offset); int err; @@ -178,7 +189,7 @@ static int flash_sam0_write_page(const struct device *dev, off_t offset, return err; } - if (memcmp(data, FLASH_MEM(offset), FLASH_PAGE_SIZE) != 0) { + if (memcmp(data, FLASH_MEM(offset), len) != 0) { LOG_ERR("verify error at offset 0x%lx", (long)offset); return -EIO; } @@ -213,7 +224,7 @@ static int flash_sam0_commit(const struct device *dev, off_t base) for (page = 0; page < PAGES_PER_ROW; page++) { err = flash_sam0_write_page( dev, base + page * FLASH_PAGE_SIZE, - &ctx->buf[page * FLASH_PAGE_SIZE]); + &ctx->buf[page * FLASH_PAGE_SIZE], ROW_SIZE); if (err != 0) { return err; } @@ -280,19 +291,18 @@ static int flash_sam0_write(const struct device *dev, off_t offset, { const uint8_t *pdata = data; int err; - size_t idx; err = flash_sam0_valid_range(offset, len); if (err != 0) { return err; } - if ((offset % FLASH_PAGE_SIZE) != 0) { + if ((offset % FLASH_WRITE_BLK_SZ) != 0) { LOG_WRN("0x%lx: not on a write block boundary", (long)offset); return -EINVAL; } - if ((len % FLASH_PAGE_SIZE) != 0) { + if ((len % FLASH_WRITE_BLK_SZ) != 0) { LOG_WRN("%zu: not a integer number of write blocks", len); return -EINVAL; } @@ -301,12 +311,20 @@ static int flash_sam0_write(const struct device *dev, off_t offset, err = flash_sam0_write_protection(dev, false); if (err == 0) { - for (idx = 0; idx < len; idx += FLASH_PAGE_SIZE) { - err = flash_sam0_write_page(dev, offset + idx, - &pdata[idx]); + /* Maximum size without crossing a page */ + size_t eop_len = FLASH_PAGE_SIZE - (offset % FLASH_PAGE_SIZE); + size_t write_len = MIN(len, eop_len); + + while (len > 0) { + err = flash_sam0_write_page(dev, offset, pdata, write_len); if (err != 0) { break; } + + offset += write_len; + pdata += write_len; + len -= write_len; + write_len = MIN(len, FLASH_PAGE_SIZE); } } @@ -454,6 +472,9 @@ static int flash_sam0_init(const struct device *dev) #ifdef NVMCTRL_CTRLB_MANW /* Require an explicit write command */ NVMCTRL->CTRLB.bit.MANW = 1; +#elif NVMCTRL_CTRLA_WMODE + /* Set manual write mode */ + NVMCTRL->CTRLA.bit.WMODE = NVMCTRL_CTRLA_WMODE_MAN_Val; #endif return flash_sam0_write_protection(dev, false); diff --git a/drivers/flash/flash_shell.c b/drivers/flash/flash_shell.c index e953b2edd1a..015bbbe9915 100644 --- a/drivers/flash/flash_shell.c +++ b/drivers/flash/flash_shell.c @@ -663,7 +663,7 @@ static int cmd_load(const struct shell *sh, size_t argc, char *argv[]) flash_load_boff = 0; flash_load_chunk = 0; - shell_print(sh, "Loading %d bytes starting at address %x", size, addr); + shell_print(sh, "Send %d bytes to complete flash load command", size); set_bypass(sh, bypass_cb); return 0; diff --git a/drivers/flash/flash_simulator.c b/drivers/flash/flash_simulator.c index 9fe5d230207..ccbc28edfe4 100644 --- a/drivers/flash/flash_simulator.c +++ b/drivers/flash/flash_simulator.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include @@ -481,12 +481,12 @@ void *z_impl_flash_simulator_get_memory(const struct device *dev, #ifdef CONFIG_USERSPACE -#include +#include void *z_vrfy_flash_simulator_get_memory(const struct device *dev, size_t *mock_size) { - Z_OOPS(Z_SYSCALL_SPECIFIC_DRIVER(dev, K_OBJ_DRIVER_FLASH, &flash_sim_api)); + K_OOPS(K_SYSCALL_SPECIFIC_DRIVER(dev, K_OBJ_DRIVER_FLASH, &flash_sim_api)); return z_impl_flash_simulator_get_memory(dev, mock_size); } diff --git a/drivers/flash/flash_stm32.c b/drivers/flash/flash_stm32.c index cba4a76a969..36e3103c56d 100644 --- a/drivers/flash/flash_stm32.c +++ b/drivers/flash/flash_stm32.c @@ -390,7 +390,7 @@ int flash_stm32_option_bytes_lock(const struct device *dev, bool enable) return 0; } -#if defined(CONFIG_FLASH_STM32_BLOCK_REGISTERS) +#if defined(CONFIG_FLASH_EX_OP_ENABLED) && defined(CONFIG_FLASH_STM32_BLOCK_REGISTERS) static int flash_stm32_control_register_disable(const struct device *dev) { FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); diff --git a/drivers/flash/flash_stm32_ex_op.c b/drivers/flash/flash_stm32_ex_op.c index 1e2d801ffa5..623d4e23d6d 100644 --- a/drivers/flash/flash_stm32_ex_op.c +++ b/drivers/flash/flash_stm32_ex_op.c @@ -11,7 +11,7 @@ #ifdef CONFIG_USERSPACE #include -#include +#include #endif #include @@ -36,7 +36,7 @@ int flash_stm32_ex_op_sector_wp(const struct device *dev, const uintptr_t in, struct flash_stm32_ex_op_sector_wp_in in_copy; if (syscall_trap) { - Z_OOPS(z_user_from_copy(&in_copy, request, + K_OOPS(k_usermode_from_copy(&in_copy, request, sizeof(in_copy))); request = &in_copy; } @@ -75,7 +75,7 @@ int flash_stm32_ex_op_sector_wp(const struct device *dev, const uintptr_t in, #ifdef CONFIG_USERSPACE if (syscall_trap) { - Z_OOPS(z_user_to_copy(out, result, sizeof(out_copy))); + K_OOPS(k_usermode_to_copy(out, result, sizeof(out_copy))); } #endif } @@ -102,7 +102,7 @@ int flash_stm32_ex_op_rdp(const struct device *dev, const uintptr_t in, if (request != NULL) { #ifdef CONFIG_USERSPACE if (syscall_trap) { - Z_OOPS(z_user_from_copy(©, request, sizeof(copy))); + K_OOPS(k_usermode_from_copy(©, request, sizeof(copy))); request = © } #endif @@ -132,7 +132,7 @@ int flash_stm32_ex_op_rdp(const struct device *dev, const uintptr_t in, #ifdef CONFIG_USERSPACE if (syscall_trap) { - Z_OOPS(z_user_to_copy(out, result, sizeof(copy))); + K_OOPS(k_usermode_to_copy(out, result, sizeof(copy))); } #endif } diff --git a/drivers/flash/flash_stm32_ospi.c b/drivers/flash/flash_stm32_ospi.c index 6f7cf0cc2a9..eb84564ddea 100644 --- a/drivers/flash/flash_stm32_ospi.c +++ b/drivers/flash/flash_stm32_ospi.c @@ -345,6 +345,17 @@ static OSPI_RegularCmdTypeDef ospi_prepare_cmd(uint8_t transfer_mode, uint8_t tr return cmd_tmp; } +static uint32_t stm32_ospi_hal_address_size(const struct device *dev) +{ + struct flash_stm32_ospi_data *dev_data = dev->data; + + if (dev_data->address_width == 4U) { + return HAL_OSPI_ADDRESS_32_BITS; + } + + return HAL_OSPI_ADDRESS_24_BITS; +} + #if defined(CONFIG_FLASH_JESD216_API) /* * Read the JEDEC ID data from the octoFlash at init or DTS @@ -367,7 +378,8 @@ static int stm32_ospi_read_jedec_id(const struct device *dev) OSPI_RegularCmdTypeDef cmd = ospi_prepare_cmd(OSPI_SPI_MODE, OSPI_STR_TRANSFER); cmd.Instruction = JESD216_CMD_READ_ID; - cmd.AddressSize = HAL_OSPI_ADDRESS_NONE; + cmd.AddressSize = stm32_ospi_hal_address_size(dev); + cmd.AddressMode = HAL_OSPI_ADDRESS_NONE; cmd.NbData = JESD216_READ_ID_LEN; /* 3 bytes in the READ ID */ HAL_StatusTypeDef hal_ret; @@ -815,7 +827,7 @@ static int stm32_ospi_config_mem(const struct device *dev) } /* Wait that the configuration is effective and check that memory is ready */ - k_msleep(STM32_OSPI_WRITE_REG_MAX_TIME); + k_busy_wait(STM32_OSPI_WRITE_REG_MAX_TIME * USEC_PER_MSEC); /* Reconfigure the memory type of the peripheral */ dev_data->hospi.Init.MemoryType = HAL_OSPI_MEMTYPE_MACRONIX; @@ -937,23 +949,12 @@ static int stm32_ospi_mem_reset(const struct device *dev) } #endif - /* After SWreset CMD, wait in case SWReset occurred during erase operation */ - k_msleep(STM32_OSPI_RESET_MAX_TIME); + /* Wait after SWreset CMD, in case SWReset occurred during erase operation */ + k_busy_wait(STM32_OSPI_RESET_MAX_TIME * USEC_PER_MSEC); return 0; } -static uint32_t stm32_ospi_hal_address_size(const struct device *dev) -{ - struct flash_stm32_ospi_data *dev_data = dev->data; - - if (dev_data->address_width == 4U) { - return HAL_OSPI_ADDRESS_32_BITS; - } - - return HAL_OSPI_ADDRESS_24_BITS; -} - /* * Function to erase the flash : chip or sector with possible OSPI/SPI and STR/DTR * to erase the complete chip (using dedicated command) : diff --git a/drivers/flash/flash_stm32_qspi.c b/drivers/flash/flash_stm32_qspi.c index 4090cd41bbb..6a9f8a58557 100644 --- a/drivers/flash/flash_stm32_qspi.c +++ b/drivers/flash/flash_stm32_qspi.c @@ -336,8 +336,13 @@ static int qspi_read_jedec_id(const struct device *dev, uint8_t *id) static int qspi_read_sfdp(const struct device *dev, off_t addr, void *data, size_t size) { + struct flash_stm32_qspi_data *dev_data = dev->data; + HAL_StatusTypeDef hal_ret; + __ASSERT(data != NULL, "null destination"); + LOG_INF("Reading SFDP"); + QSPI_CommandTypeDef cmd = { .Instruction = JESD216_CMD_READ_SFDP, .Address = addr, @@ -346,9 +351,26 @@ static int qspi_read_sfdp(const struct device *dev, off_t addr, void *data, .InstructionMode = QSPI_INSTRUCTION_1_LINE, .AddressMode = QSPI_ADDRESS_1_LINE, .DataMode = QSPI_DATA_1_LINE, + .NbData = size, }; - return qspi_read_access(dev, &cmd, (uint8_t *)data, size); + hal_ret = HAL_QSPI_Command(&dev_data->hqspi, &cmd, + HAL_QSPI_TIMEOUT_DEFAULT_VALUE); + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to send SFDP instruction", hal_ret); + return -EIO; + } + + hal_ret = HAL_QSPI_Receive(&dev_data->hqspi, (uint8_t *)data, + HAL_QSPI_TIMEOUT_DEFAULT_VALUE); + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to read SFDP", hal_ret); + return -EIO; + } + + dev_data->cmd_status = 0; + + return 0; } static bool qspi_address_is_valid(const struct device *dev, off_t addr, @@ -615,6 +637,11 @@ static void qspi_dma_callback(const struct device *dev, void *arg, } #endif +__weak HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma) +{ + return HAL_OK; +} + __weak HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma) { return HAL_OK; diff --git a/drivers/flash/flash_stm32f4x.c b/drivers/flash/flash_stm32f4x.c index f94c1b2e979..4261c26a589 100644 --- a/drivers/flash/flash_stm32f4x.c +++ b/drivers/flash/flash_stm32f4x.c @@ -292,8 +292,7 @@ int flash_stm32_update_rdp(const struct device *dev, bool enable, switch (current_level) { case FLASH_STM32_RDP2: if (!enable || !permanent) { - __ASSERT(false, "RDP level 2 is permanent and can't be " - "changed!"); + LOG_ERR("RDP level 2 is permanent and can't be changed!"); return -ENOTSUP; } break; @@ -304,9 +303,8 @@ int flash_stm32_update_rdp(const struct device *dev, bool enable, #if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW) target_level = FLASH_STM32_RDP2; #else - __ASSERT(false, - "Permanent readout protection (RDP " - "level 0 -> 2) not allowed"); + LOG_ERR("Permanent readout protection (RDP " + "level 0 -> 2) not allowed"); return -ENOTSUP; #endif } @@ -317,8 +315,8 @@ int flash_stm32_update_rdp(const struct device *dev, bool enable, #if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW) target_level = FLASH_STM32_RDP2; #else - __ASSERT(false, "Permanent readout protection (RDP " - "level 1 -> 2) not allowed"); + LOG_ERR("Permanent readout protection (RDP " + "level 1 -> 2) not allowed"); return -ENOTSUP; #endif } @@ -326,8 +324,8 @@ int flash_stm32_update_rdp(const struct device *dev, bool enable, #if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_DISABLE_ALLOW) target_level = FLASH_STM32_RDP0; #else - __ASSERT(false, "Disabling readout protection (RDP " - "level 1 -> 0) not allowed"); + LOG_ERR("Disabling readout protection (RDP " + "level 1 -> 0) not allowed"); return -EACCES; #endif } diff --git a/drivers/flash/flash_stm32g0x.c b/drivers/flash/flash_stm32g0x.c index 07eea9ce32b..41a0e1da3bf 100644 --- a/drivers/flash/flash_stm32g0x.c +++ b/drivers/flash/flash_stm32g0x.c @@ -231,7 +231,7 @@ int flash_stm32_check_configuration(void) { #if defined(STM32G0_DBANK_SUPPORT) && (CONFIG_FLASH_SIZE == 256) /* Single bank mode not supported on dual bank SoCs with 256kiB flash */ - if ((regs->OPTR & FLASH_OPTR_DUAL_BANK) == 0) { + if ((FLASH->OPTR & FLASH_OPTR_DUAL_BANK) == 0) { LOG_ERR("Single bank configuration not supported by the driver"); return -ENOTSUP; } diff --git a/drivers/flash/flash_stm32g4x.c b/drivers/flash/flash_stm32g4x.c index e1f012c254b..8f11e21c20e 100644 --- a/drivers/flash/flash_stm32g4x.c +++ b/drivers/flash/flash_stm32g4x.c @@ -13,6 +13,7 @@ LOG_MODULE_REGISTER(LOG_DOMAIN); #include #include #include +#include #include #include #include @@ -254,6 +255,155 @@ int flash_stm32_write_range(const struct device *dev, unsigned int offset, return rc; } +static __unused int write_optb(const struct device *dev, uint32_t mask, + uint32_t value) +{ + FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); + int rc; + + if (regs->CR & FLASH_CR_OPTLOCK) { + return -EIO; + } + + if ((regs->OPTR & mask) == value) { + return 0; + } + + rc = flash_stm32_wait_flash_idle(dev); + if (rc < 0) { + return rc; + } + + regs->OPTR = (regs->OPTR & ~mask) | value; + regs->CR |= FLASH_CR_OPTSTRT; + + /* Make sure previous write is completed. */ + barrier_dsync_fence_full(); + + rc = flash_stm32_wait_flash_idle(dev); + if (rc < 0) { + return rc; + } + + return 0; +} + +#if defined(CONFIG_FLASH_STM32_WRITE_PROTECT) + +/* + * Remark for future development implementing Write Protection for the L4 parts: + * + * STM32L4 allows for 2 write protected memory areas, c.f. FLASH_WEP1AR, FLASH_WRP1BR + * which are defined by their start and end pages. + * + * Other STM32 parts (i.e. F4 series) uses bitmask to select sectors. + * + * To implement Write Protection for L4 one should thus add a new EX_OP like + * FLASH_STM32_EX_OP_SECTOR_WP_RANGED in stm32_flash_api_extensions.h + */ + +#endif /* CONFIG_FLASH_STM32_WRITE_PROTECT */ + +#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION) +int flash_stm32_update_rdp(const struct device *dev, bool enable, + bool permanent) +{ + FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); + uint8_t current_level, target_level; + + current_level = + (regs->OPTR & FLASH_OPTR_RDP_Msk) >> FLASH_OPTR_RDP_Pos; + target_level = current_level; + + /* + * 0xAA = RDP level 0 (no protection) + * 0xCC = RDP level 2 (permanent protection) + * others = RDP level 1 (protection active) + */ + switch (current_level) { + case FLASH_STM32_RDP2: + if (!enable || !permanent) { + LOG_ERR("RDP level 2 is permanent and can't be changed!"); + return -ENOTSUP; + } + break; + case FLASH_STM32_RDP0: + if (enable) { + target_level = FLASH_STM32_RDP1; + if (permanent) { +#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW) + target_level = FLASH_STM32_RDP2; +#else + LOG_ERR("Permanent readout protection (RDP " + "level 0 -> 2) not allowed"); + return -ENOTSUP; +#endif + } + } + break; + default: /* FLASH_STM32_RDP1 */ + if (enable && permanent) { +#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW) + target_level = FLASH_STM32_RDP2; +#else + LOG_ERR("Permanent readout protection (RDP " + "level 1 -> 2) not allowed"); + return -ENOTSUP; +#endif + } + if (!enable) { +#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_DISABLE_ALLOW) + target_level = FLASH_STM32_RDP0; +#else + LOG_ERR("Disabling readout protection (RDP " + "level 1 -> 0) not allowed"); + return -EACCES; +#endif + } + } + + /* Update RDP level if needed */ + if (current_level != target_level) { + LOG_INF("RDP changed from 0x%02x to 0x%02x", current_level, + target_level); + + write_optb(dev, FLASH_OPTR_RDP_Msk, + (uint32_t)target_level << FLASH_OPTR_RDP_Pos); + } + return 0; +} + +int flash_stm32_get_rdp(const struct device *dev, bool *enabled, + bool *permanent) +{ + FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); + uint8_t current_level; + + current_level = + (regs->OPTR & FLASH_OPTR_RDP_Msk) >> FLASH_OPTR_RDP_Pos; + + /* + * 0xAA = RDP level 0 (no protection) + * 0xCC = RDP level 2 (permanent protection) + * others = RDP level 1 (protection active) + */ + switch (current_level) { + case FLASH_STM32_RDP2: + *enabled = true; + *permanent = true; + break; + case FLASH_STM32_RDP0: + *enabled = false; + *permanent = false; + break; + default: /* FLASH_STM32_RDP1 */ + *enabled = true; + *permanent = false; + } + return 0; +} +#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */ + void flash_stm32_page_layout(const struct device *dev, const struct flash_pages_layout **layout, size_t *layout_size) diff --git a/drivers/flash/flash_stm32l4x.c b/drivers/flash/flash_stm32l4x.c index 24644aba95e..ead57fb3df4 100644 --- a/drivers/flash/flash_stm32l4x.c +++ b/drivers/flash/flash_stm32l4x.c @@ -15,6 +15,7 @@ LOG_MODULE_REGISTER(LOG_DOMAIN); #include #include #include +#include #include #include @@ -244,6 +245,157 @@ int flash_stm32_write_range(const struct device *dev, unsigned int offset, return rc; } +static __unused int write_optb(const struct device *dev, uint32_t mask, + uint32_t value) +{ + FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); + int rc; + + if (regs->CR & FLASH_CR_OPTLOCK) { + return -EIO; + } + + if ((regs->OPTR & mask) == value) { + return 0; + } + + rc = flash_stm32_wait_flash_idle(dev); + if (rc < 0) { + return rc; + } + + regs->OPTR = (regs->OPTR & ~mask) | value; + regs->CR |= FLASH_CR_OPTSTRT; + + /* Make sure previous write is completed. */ + barrier_dsync_fence_full(); + + rc = flash_stm32_wait_flash_idle(dev); + if (rc < 0) { + return rc; + } + + return 0; +} + +#if defined(CONFIG_FLASH_STM32_WRITE_PROTECT) + +/* + * Remark for future development implementing Write Protection for the L4 parts: + * + * STM32L4 allows for 2 write protected memory areas, c.f. FLASH_WEP1AR, FLASH_WRP1BR + * which are defined by their start and end pages. + * + * Other STM32 parts (i.e. F4 series) uses bitmask to select sectors. + * + * To implement Write Protection for L4 one should thus add a new EX_OP like + * FLASH_STM32_EX_OP_SECTOR_WP_RANGED in stm32_flash_api_extensions.h + */ + +#endif /* CONFIG_FLASH_STM32_WRITE_PROTECT */ + +#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION) +int flash_stm32_update_rdp(const struct device *dev, bool enable, + bool permanent) +{ + FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); + uint8_t current_level, target_level; + + current_level = + (regs->OPTR & FLASH_OPTR_RDP_Msk) >> FLASH_OPTR_RDP_Pos; + target_level = current_level; + + /* + * 0xAA = RDP level 0 (no protection) + * 0xCC = RDP level 2 (permanent protection) + * others = RDP level 1 (protection active) + */ + switch (current_level) { + case FLASH_STM32_RDP2: + if (!enable || !permanent) { + LOG_ERR("RDP level 2 is permanent and can't be changed!"); + return -ENOTSUP; + } + break; + case FLASH_STM32_RDP0: + if (enable) { + target_level = FLASH_STM32_RDP1; + if (permanent) { +#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW) + target_level = FLASH_STM32_RDP2; +#else + LOG_ERR("Permanent readout protection (RDP " + "level 0 -> 2) not allowed"); + return -ENOTSUP; +#endif + } + } + break; + default: /* FLASH_STM32_RDP1 */ + if (enable && permanent) { +#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW) + target_level = FLASH_STM32_RDP2; +#else + LOG_ERR("Permanent readout protection (RDP " + "level 1 -> 2) not allowed"); + return -ENOTSUP; +#endif + } + if (!enable) { +#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_DISABLE_ALLOW) + target_level = FLASH_STM32_RDP0; +#else + LOG_ERR("Disabling readout protection (RDP " + "level 1 -> 0) not allowed"); + return -EACCES; +#endif + } + } + + /* Update RDP level if needed */ + if (current_level != target_level) { + LOG_INF("RDP changed from 0x%02x to 0x%02x", current_level, + target_level); + + write_optb(dev, FLASH_OPTR_RDP_Msk, + (uint32_t)target_level << FLASH_OPTR_RDP_Pos); + } + return 0; +} + +int flash_stm32_get_rdp(const struct device *dev, bool *enabled, + bool *permanent) +{ + FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); + uint8_t current_level; + + current_level = + (regs->OPTR & FLASH_OPTR_RDP_Msk) >> FLASH_OPTR_RDP_Pos; + + /* + * 0xAA = RDP level 0 (no protection) + * 0xCC = RDP level 2 (permanent protection) + * others = RDP level 1 (protection active) + */ + switch (current_level) { + case FLASH_STM32_RDP2: + *enabled = true; + *permanent = true; + break; + case FLASH_STM32_RDP0: + *enabled = false; + *permanent = false; + break; + default: /* FLASH_STM32_RDP1 */ + *enabled = true; + *permanent = false; + } + return 0; +} +#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */ + + + void flash_stm32_page_layout(const struct device *dev, const struct flash_pages_layout **layout, size_t *layout_size) diff --git a/drivers/flash/nrf_qspi_nor.c b/drivers/flash/nrf_qspi_nor.c index ac055229710..d6695989857 100644 --- a/drivers/flash/nrf_qspi_nor.c +++ b/drivers/flash/nrf_qspi_nor.c @@ -1331,11 +1331,11 @@ void z_impl_nrf_qspi_nor_xip_enable(const struct device *dev, bool enable) } #ifdef CONFIG_USERSPACE -#include +#include void z_vrfy_nrf_qspi_nor_xip_enable(const struct device *dev, bool enable) { - Z_OOPS(Z_SYSCALL_SPECIFIC_DRIVER(dev, K_OBJ_DRIVER_FLASH, + K_OOPS(K_SYSCALL_SPECIFIC_DRIVER(dev, K_OBJ_DRIVER_FLASH, &qspi_nor_api)); z_impl_nrf_qspi_nor_xip_enable(dev, enable); diff --git a/drivers/flash/soc_flash_mcux.c b/drivers/flash/soc_flash_mcux.c index a8b2d282107..f3f4059da44 100644 --- a/drivers/flash/soc_flash_mcux.c +++ b/drivers/flash/soc_flash_mcux.c @@ -193,9 +193,18 @@ static int flash_mcux_read(const struct device *dev, off_t offset, #ifdef CONFIG_CHECK_BEFORE_READING #ifdef CONFIG_SOC_LPC55S36 + /* Validates the given address range is loaded in the flash hiding region. */ rc = FLASH_IsFlashAreaReadable(&priv->config, addr, len); if (rc != kStatus_FLASH_Success) { rc = -EIO; + } else { + /* Check whether the flash is erased ("len" and "addr" must be word-aligned). */ + rc = FLASH_VerifyErase(&priv->config, ((addr + 0x3) & ~0x3), ((len + 0x3) & ~0x3)); + if (rc == kStatus_FLASH_Success) { + rc = -ENODATA; + } else { + rc = 0; + } } #else rc = is_area_readable(addr, len); diff --git a/drivers/flash/soc_flash_nrf.c b/drivers/flash/soc_flash_nrf.c index ea76ae1e3f8..b5a3fefa1e5 100644 --- a/drivers/flash/soc_flash_nrf.c +++ b/drivers/flash/soc_flash_nrf.c @@ -164,11 +164,6 @@ static int flash_nrf_read(const struct device *dev, off_t addr, return 0; } -#if CONFIG_TRUSTED_EXECUTION_NONSECURE && USE_PARTITION_MANAGER && PM_APP_ADDRESS - if (addr < PM_APP_ADDRESS) { - return soc_secure_mem_read(data, (void *)addr, len); - } -#endif #if CONFIG_SOC_FLASH_NRF_UICR && IS_ENABLED(NRF91_ERRATA_7_ENABLE_WORKAROUND) if (within_uicr) { nrf_buffer_read_91_uicr(data, (uint32_t)addr, len); @@ -176,6 +171,12 @@ static int flash_nrf_read(const struct device *dev, off_t addr, } #endif +#if CONFIG_TRUSTED_EXECUTION_NONSECURE && USE_PARTITION_MANAGER && PM_APP_ADDRESS + if (addr < PM_APP_ADDRESS) { + return soc_secure_mem_read(data, (void *)addr, len); + } +#endif + nrf_nvmc_buffer_read(data, (uint32_t)addr, len); return 0; diff --git a/drivers/flash/spi_nor.c b/drivers/flash/spi_nor.c index c0d67af7250..ea23d11eb95 100644 --- a/drivers/flash/spi_nor.c +++ b/drivers/flash/spi_nor.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2018 Savoir-Faire Linux. * Copyright (c) 2020 Peter Bigot Consulting, LLC + * Copyright (c) 2023 Intercreate, Inc. * * This driver is heavily inspired from the spi_flash_w25qxxdv.c SPI NOR driver. * @@ -63,6 +64,14 @@ LOG_MODULE_REGISTER(spi_nor, CONFIG_FLASH_LOG_LEVEL); #define T_DPDD_MS 0 #endif /* DPD_WAKEUP_SEQUENCE */ +#define _INST_HAS_WP_OR(inst) DT_INST_NODE_HAS_PROP(inst, wp_gpios) || +#define ANY_INST_HAS_WP_GPIOS DT_INST_FOREACH_STATUS_OKAY(_INST_HAS_WP_OR) 0 + +#define _INST_HAS_HOLD_OR(inst) DT_INST_NODE_HAS_PROP(inst, hold_gpios) || +#define ANY_INST_HAS_HOLD_GPIOS DT_INST_FOREACH_STATUS_OKAY(_INST_HAS_HOLD_OR) 0 + +#define DEV_CFG(_dev_) ((const struct spi_nor_config * const) (_dev_)->config) + /* Build-time data associated with the device. */ struct spi_nor_config { /* Devicetree SPI configuration */ @@ -107,6 +116,15 @@ struct spi_nor_config { * This information cannot be derived from SFDP. */ uint8_t has_lock; + +#if ANY_INST_HAS_WP_GPIOS + /* The write-protect GPIO (wp-gpios) */ + const struct gpio_dt_spec *wp; +#endif +#if ANY_INST_HAS_HOLD_GPIOS + /* The hold GPIO (hold-gpios) */ + const struct gpio_dt_spec *hold; +#endif }; /** @@ -208,7 +226,7 @@ static inline uint32_t dev_flash_size(const struct device *dev) static inline uint16_t dev_page_size(const struct device *dev) { #ifdef CONFIG_SPI_NOR_SFDP_MINIMAL - return 256; + return DT_INST_PROP_OR(0, page_size, 256); #else /* CONFIG_SPI_NOR_SFDP_MINIMAL */ const struct spi_nor_data *data = dev->data; @@ -684,6 +702,34 @@ static int spi_nor_read(const struct device *dev, off_t addr, void *dest, return ret; } +#if defined(CONFIG_FLASH_EX_OP_ENABLED) +static int flash_spi_nor_ex_op(const struct device *dev, uint16_t code, + const uintptr_t in, void *out) +{ + int ret; + + ARG_UNUSED(in); + ARG_UNUSED(out); + + acquire_device(dev); + + switch (code) { + case FLASH_EX_OP_RESET: + ret = spi_nor_cmd_write(dev, SPI_NOR_CMD_RESET_EN); + if (ret == 0) { + ret = spi_nor_cmd_write(dev, SPI_NOR_CMD_RESET_MEM); + } + break; + default: + ret = -ENOTSUP; + break; + } + + release_device(dev); + return ret; +} +#endif + static int spi_nor_write(const struct device *dev, off_t addr, const void *src, size_t size) @@ -829,6 +875,12 @@ static int spi_nor_write_protection_set(const struct device *dev, { int ret; +#if ANY_INST_HAS_WP_GPIOS + if (DEV_CFG(dev)->wp && write_protect == false) { + gpio_pin_set_dt(DEV_CFG(dev)->wp, 0); + } +#endif + ret = spi_nor_cmd_write(dev, (write_protect) ? SPI_NOR_CMD_WRDI : SPI_NOR_CMD_WREN); @@ -838,6 +890,12 @@ static int spi_nor_write_protection_set(const struct device *dev, ret = spi_nor_cmd_write(dev, SPI_NOR_CMD_ULBPR); } +#if ANY_INST_HAS_WP_GPIOS + if (DEV_CFG(dev)->wp && write_protect == true) { + gpio_pin_set_dt(DEV_CFG(dev)->wp, 1); + } +#endif + return ret; } @@ -999,10 +1057,10 @@ static int spi_nor_process_sfdp(const struct device *dev) /* We only process BFP so use one parameter block */ uint8_t raw[JESD216_SFDP_SIZE(decl_nph)]; struct jesd216_sfdp_header sfdp; - } u; - const struct jesd216_sfdp_header *hp = &u.sfdp; + } u_header; + const struct jesd216_sfdp_header *hp = &u_header.sfdp; - rc = spi_nor_sfdp_read(dev, 0, u.raw, sizeof(u.raw)); + rc = spi_nor_sfdp_read(dev, 0, u_header.raw, sizeof(u_header.raw)); if (rc != 0) { LOG_ERR("SFDP read failed: %d", rc); return rc; @@ -1032,10 +1090,11 @@ static int spi_nor_process_sfdp(const struct device *dev) union { uint32_t dw[MIN(php->len_dw, 20)]; struct jesd216_bfp bfp; - } u; - const struct jesd216_bfp *bfp = &u.bfp; + } u_param; + const struct jesd216_bfp *bfp = &u_param.bfp; - rc = spi_nor_sfdp_read(dev, jesd216_param_addr(php), u.dw, sizeof(u.dw)); + rc = spi_nor_sfdp_read(dev, jesd216_param_addr(php), + u_param.dw, sizeof(u_param.dw)); if (rc == 0) { rc = spi_nor_process_bfp(dev, php, bfp); } @@ -1326,6 +1385,31 @@ static int spi_nor_init(const struct device *dev) k_sem_init(&driver_data->sem, 1, K_SEM_MAX_LIMIT); } +#if ANY_INST_HAS_WP_GPIOS + if (DEV_CFG(dev)->wp) { + if (!device_is_ready(DEV_CFG(dev)->wp->port)) { + LOG_ERR("Write-protect pin not ready"); + return -ENODEV; + } + if (gpio_pin_configure_dt(DEV_CFG(dev)->wp, GPIO_OUTPUT_ACTIVE)) { + LOG_ERR("Write-protect pin failed to set active"); + return -ENODEV; + } + } +#endif /* ANY_INST_HAS_WP_GPIOS */ +#if ANY_INST_HAS_HOLD_GPIOS + if (DEV_CFG(dev)->hold) { + if (!device_is_ready(DEV_CFG(dev)->hold->port)) { + LOG_ERR("Hold pin not ready"); + return -ENODEV; + } + if (gpio_pin_configure_dt(DEV_CFG(dev)->hold, GPIO_OUTPUT_INACTIVE)) { + LOG_ERR("Hold pin failed to set inactive"); + return -ENODEV; + } + } +#endif /* ANY_INST_HAS_HOLD_GPIOS */ + return spi_nor_configure(dev); } @@ -1371,6 +1455,9 @@ static const struct flash_driver_api spi_nor_api = { .sfdp_read = spi_nor_sfdp_read, .read_jedec_id = spi_nor_read_jedec_id, #endif +#if defined(CONFIG_FLASH_EX_OP_ENABLED) + .ex_op = flash_spi_nor_ex_op, +#endif }; #ifndef CONFIG_SPI_NOR_SFDP_RUNTIME @@ -1422,6 +1509,21 @@ BUILD_ASSERT(DT_INST_PROP(0, has_lock) == (DT_INST_PROP(0, has_lock) & 0xFF), "Need support for lock clear beyond SR1"); #endif +#define INST_HAS_WP_GPIO(idx) DT_INST_NODE_HAS_PROP(idx, wp_gpios) + +#define INST_WP_GPIO_SPEC(idx) \ + IF_ENABLED(INST_HAS_WP_GPIO(idx), (static const struct gpio_dt_spec wp_##idx = \ + GPIO_DT_SPEC_INST_GET(idx, wp_gpios);)) + +#define INST_HAS_HOLD_GPIO(idx) DT_INST_NODE_HAS_PROP(idx, hold_gpios) + +#define INST_HOLD_GPIO_SPEC(idx) \ + IF_ENABLED(INST_HAS_HOLD_GPIO(idx), (static const struct gpio_dt_spec hold_##idx = \ + GPIO_DT_SPEC_INST_GET(idx, hold_gpios);)) + +INST_WP_GPIO_SPEC(0) +INST_HOLD_GPIO_SPEC(0) + static const struct spi_nor_config spi_nor_config_0 = { .spi = SPI_DT_SPEC_INST_GET(0, SPI_WORD_SET(8), CONFIG_SPI_NOR_CS_WAIT_DELAY), @@ -1455,6 +1557,14 @@ static const struct spi_nor_config spi_nor_config_0 = { #endif /* CONFIG_SPI_NOR_SFDP_DEVICETREE */ #endif /* CONFIG_SPI_NOR_SFDP_RUNTIME */ + +#if DT_INST_NODE_HAS_PROP(0, wp_gpios) + .wp = &wp_0, +#endif + +#if DT_INST_NODE_HAS_PROP(0, hold_gpios) + .hold = &hold_0, +#endif }; static struct spi_nor_data spi_nor_data_0; diff --git a/drivers/fpga/fpga_eos_s3.c b/drivers/fpga/fpga_eos_s3.c index a0e21226530..30841dd43bf 100644 --- a/drivers/fpga/fpga_eos_s3.c +++ b/drivers/fpga/fpga_eos_s3.c @@ -148,5 +148,5 @@ static const struct fpga_driver_api eos_s3_api = { .get_info = eos_s3_fpga_get_info }; -DEVICE_DT_DEFINE(DT_NODELABEL(fpga0), &eos_s3_fpga_init, NULL, &fpga_data, NULL, APPLICATION, +DEVICE_DT_DEFINE(DT_NODELABEL(fpga0), &eos_s3_fpga_init, NULL, &fpga_data, NULL, POST_KERNEL, CONFIG_FPGA_INIT_PRIORITY, &eos_s3_api); diff --git a/drivers/fpga/fpga_zynqmp.c b/drivers/fpga/fpga_zynqmp.c index 1be08d59b7d..8da54462fae 100644 --- a/drivers/fpga/fpga_zynqmp.c +++ b/drivers/fpga/fpga_zynqmp.c @@ -323,4 +323,4 @@ static const struct fpga_driver_api zynqmp_api = { }; DEVICE_DT_INST_DEFINE(0, &zynqmp_fpga_init, NULL, &fpga_data, NULL, - APPLICATION, CONFIG_FPGA_INIT_PRIORITY, &zynqmp_api); + POST_KERNEL, CONFIG_FPGA_INIT_PRIORITY, &zynqmp_api); diff --git a/drivers/fuel_gauge/CMakeLists.txt b/drivers/fuel_gauge/CMakeLists.txt index bf7d5e4918e..c48e2ead003 100644 --- a/drivers/fuel_gauge/CMakeLists.txt +++ b/drivers/fuel_gauge/CMakeLists.txt @@ -4,5 +4,11 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/fuel_gauge.h) add_subdirectory_ifdef(CONFIG_SBS_GAUGE_NEW_API sbs_gauge) add_subdirectory_ifdef(CONFIG_MAX17048 max17048) +add_subdirectory_ifdef(CONFIG_BQ27Z746 bq27z746) zephyr_library_sources_ifdef(CONFIG_USERSPACE fuel_gauge_syscall_handlers.c) + +if (CONFIG_EMUL AND CONFIG_USERSPACE) + zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/emul_fuel_gauge.h) + zephyr_library_sources(emul_fuel_gauge_syscall_handlers.c) +endif() diff --git a/drivers/fuel_gauge/Kconfig b/drivers/fuel_gauge/Kconfig index 929dd060490..616ab3885d2 100644 --- a/drivers/fuel_gauge/Kconfig +++ b/drivers/fuel_gauge/Kconfig @@ -20,7 +20,7 @@ config FUEL_GAUGE_INIT_PRIORITY Battery fuel gauge initialization priority. source "drivers/fuel_gauge/max17048/Kconfig" - source "drivers/fuel_gauge/sbs_gauge/Kconfig" +source "drivers/fuel_gauge/bq27z746/Kconfig" endif # FUEL_GAUGE diff --git a/drivers/fuel_gauge/bq27z746/CMakeLists.txt b/drivers/fuel_gauge/bq27z746/CMakeLists.txt new file mode 100644 index 00000000000..ff6a6ff0343 --- /dev/null +++ b/drivers/fuel_gauge/bq27z746/CMakeLists.txt @@ -0,0 +1,6 @@ +zephyr_library() + +zephyr_library_sources(bq27z746.c) + +zephyr_include_directories_ifdef(CONFIG_EMUL_BQ27Z746 .) +zephyr_library_sources_ifdef(CONFIG_EMUL_BQ27Z746 ./emul_bq27z746.c) diff --git a/drivers/fuel_gauge/bq27z746/Kconfig b/drivers/fuel_gauge/bq27z746/Kconfig new file mode 100644 index 00000000000..26f3d2612d8 --- /dev/null +++ b/drivers/fuel_gauge/bq27z746/Kconfig @@ -0,0 +1,21 @@ +# Copyright (c) 2023, ithinx GmbH +# Copyright (c) 2023, Tonies GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +config BQ27Z746 + bool "BQ27Z746 Fuel Gauge" + default y + depends on DT_HAS_TI_BQ27Z746_ENABLED + select I2C + help + Enable I2C-based driver for BQ27Z746 Fuel Gauge. + +config EMUL_BQ27Z746 + bool "Emulate an BQ27Z746 fuel gague" + default y + depends on EMUL + depends on BQ27Z746 + help + It provides readings which follow a simple sequence, thus allowing + test code to check that things are working as expected. diff --git a/drivers/fuel_gauge/bq27z746/bq27z746.c b/drivers/fuel_gauge/bq27z746/bq27z746.c new file mode 100644 index 00000000000..98918faaa76 --- /dev/null +++ b/drivers/fuel_gauge/bq27z746/bq27z746.c @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2023, ithinx GmbH + * Copyright (c) 2023, Tonies GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ti_bq27z746 + +#include "bq27z746.h" + +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(BQ27Z746); + +#define BQ27Z746_MAC_DATA_LEN 32 +#define BQ27Z746_MAC_OVERHEAD_LEN 4 /* 2 cmd bytes, 1 length byte, 1 checksum byte */ +#define BQ27Z746_MAC_COMPLETE_LEN (BQ27Z746_MAC_DATA_LEN + BQ27Z746_MAC_OVERHEAD_LEN) + +static int bq27z746_read16(const struct device *dev, uint8_t reg, uint16_t *value) +{ + uint8_t i2c_data[2]; + const struct bq27z746_config *cfg = dev->config; + const int status = i2c_burst_read_dt(&cfg->i2c, reg, i2c_data, sizeof(i2c_data)); + + if (status < 0) { + LOG_ERR("Unable to read register"); + return status; + } + *value = sys_get_le16(i2c_data); + + return 0; +} + +static int bq27z746_write16(const struct device *dev, uint8_t reg, uint16_t value) +{ + uint8_t buf[3]; + const struct bq27z746_config *cfg = dev->config; + + buf[0] = reg; + sys_put_le16(value, &buf[1]); + + return i2c_write_dt(&cfg->i2c, buf, sizeof(buf)); +} + +static int bq27z746_read_mac(const struct device *dev, uint16_t cmd, uint8_t *data, int len) +{ + if (len > BQ27Z746_MAC_DATA_LEN) { + return -EINVAL; + } + + uint8_t buf[BQ27Z746_MAC_COMPLETE_LEN]; + const struct bq27z746_config *cfg = dev->config; + + /* Instead of MAC, ALTMAC is used as reccommended in the datasheet */ + int ret = bq27z746_write16(dev, BQ27Z746_ALTMANUFACTURERACCESS, cmd); + + if (ret != 0) { + return ret; + } + + /* + * The data read from BQ27Z746_ALTMANUFACTURERACCESS is: + * 0..1: The command (for verification) + * 2..33: The data + * 34: Checksum calculated as (uint8_t)(0xFF - (sum of all command and data bytes)) + * 35: Length including command, checksum and length (e.g. data length + 4) + */ + + ret = i2c_burst_read_dt(&cfg->i2c, BQ27Z746_ALTMANUFACTURERACCESS, buf, + BQ27Z746_MAC_COMPLETE_LEN); + if (ret != 0) { + return ret; + } + + /* The first two bytes read is the command and is used for verification */ + const uint16_t read_cmd = sys_get_le16(buf); + + if (read_cmd != cmd) { + LOG_ERR("Read command 0x%x != written command 0x%x", read_cmd, cmd); + return -EIO; + } + + const uint8_t checksum_actual = buf[34]; + uint8_t sum = 0; /* Intentionally 8 bit wide and overflowing */ + + for (int i = 0; i < BQ27Z746_MAC_COMPLETE_LEN - 2; i++) { + sum += buf[i]; + } + + const uint8_t checksum_expected = 0xFF - sum; + + if (checksum_expected != checksum_actual) { + LOG_ERR("Checksum mismatch"); + return -EIO; + } + + /* First byte of the user buffer is the length */ + data[0] = buf[35] - BQ27Z746_MAC_OVERHEAD_LEN; + + /* Copy only the data to the user buffer (= skipping the first two command bytes) */ + memcpy(&data[1], &buf[2], len); + + return ret; +} + +static int bq27z746_get_prop(const struct device *dev, fuel_gauge_prop_t prop, + union fuel_gauge_prop_val *val) +{ + int rc = 0; + uint16_t tmp_val = 0; + + /* + * Possibly negative values must be cast from uint16 to int16 first to + * then correctly end up in the wider datatypes of `prop`. + */ + + switch (prop) { + case FUEL_GAUGE_AVG_CURRENT: + rc = bq27z746_read16(dev, BQ27Z746_AVERAGECURRENT, &tmp_val); + val->avg_current = (int16_t)tmp_val * 1000; + break; + case FUEL_GAUGE_CYCLE_COUNT: + rc = bq27z746_read16(dev, BQ27Z746_CYCLECOUNT, &tmp_val); + val->cycle_count = tmp_val * 100; + break; + case FUEL_GAUGE_CURRENT: + rc = bq27z746_read16(dev, BQ27Z746_CURRENT, &tmp_val); + val->current = (int16_t)tmp_val * 1000; + break; + case FUEL_GAUGE_FULL_CHARGE_CAPACITY: + rc = bq27z746_read16(dev, BQ27Z746_FULLCHARGECAPACITY, &tmp_val); + val->full_charge_capacity = tmp_val * 1000; + break; + case FUEL_GAUGE_REMAINING_CAPACITY: + rc = bq27z746_read16(dev, BQ27Z746_REMAININGCAPACITY, &tmp_val); + val->remaining_capacity = tmp_val * 1000; + break; + case FUEL_GAUGE_RUNTIME_TO_EMPTY: + rc = bq27z746_read16(dev, BQ27Z746_AVERAGETIMETOEMPTY, &tmp_val); + val->runtime_to_empty = tmp_val; + break; + case FUEL_GAUGE_RUNTIME_TO_FULL: + rc = bq27z746_read16(dev, BQ27Z746_AVERAGETIMETOFULL, &tmp_val); + val->runtime_to_full = tmp_val; + break; + case FUEL_GAUGE_SBS_MFR_ACCESS: + rc = bq27z746_read16(dev, BQ27Z746_MANUFACTURERACCESS, &tmp_val); + val->sbs_mfr_access_word = tmp_val; + break; + case FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE: + rc = bq27z746_read16(dev, BQ27Z746_RELATIVESTATEOFCHARGE, &tmp_val); + val->relative_state_of_charge = tmp_val; + break; + case FUEL_GAUGE_TEMPERATURE: + rc = bq27z746_read16(dev, BQ27Z746_TEMPERATURE, &tmp_val); + val->temperature = tmp_val; + break; + case FUEL_GAUGE_VOLTAGE: + rc = bq27z746_read16(dev, BQ27Z746_VOLTAGE, &tmp_val); + val->voltage = tmp_val * 1000; + break; + case FUEL_GAUGE_SBS_ATRATE: + rc = bq27z746_read16(dev, BQ27Z746_ATRATE, &tmp_val); + val->sbs_at_rate = (int16_t)tmp_val; + break; + case FUEL_GAUGE_SBS_ATRATE_TIME_TO_EMPTY: + rc = bq27z746_read16(dev, BQ27Z746_ATRATETIMETOEMPTY, &tmp_val); + val->sbs_at_rate_time_to_empty = tmp_val; + break; + case FUEL_GAUGE_CHARGE_VOLTAGE: + rc = bq27z746_read16(dev, BQ27Z746_CHARGINGVOLTAGE, &tmp_val); + val->chg_voltage = tmp_val * 1000; + break; + case FUEL_GAUGE_CHARGE_CURRENT: + rc = bq27z746_read16(dev, BQ27Z746_CHARGINGCURRENT, &tmp_val); + val->chg_current = tmp_val * 1000; + break; + case FUEL_GAUGE_STATUS: + rc = bq27z746_read16(dev, BQ27Z746_BATTERYSTATUS, &tmp_val); + val->fg_status = tmp_val; + break; + case FUEL_GAUGE_DESIGN_CAPACITY: + rc = bq27z746_read16(dev, BQ27Z746_DESIGNCAPACITY, &tmp_val); + val->design_cap = tmp_val; + break; + default: + rc = -ENOTSUP; + } + + return rc; +} + +static int bq27z746_get_buffer_prop(const struct device *dev, + fuel_gauge_prop_t property_type, void *dst, + size_t dst_len) +{ + int rc = 0; + + switch (property_type) { + case FUEL_GAUGE_MANUFACTURER_NAME: + if (dst_len == sizeof(struct sbs_gauge_manufacturer_name)) { + rc = bq27z746_read_mac(dev, BQ27Z746_MAC_CMD_MANUFACTURER_NAME, + (uint8_t *)dst, dst_len - 1); + } else { + rc = -EINVAL; + } + break; + case FUEL_GAUGE_DEVICE_NAME: + if (dst_len == sizeof(struct sbs_gauge_device_name)) { + rc = bq27z746_read_mac(dev, BQ27Z746_MAC_CMD_DEVICE_NAME, (uint8_t *)dst, + dst_len - 1); + } else { + rc = -EINVAL; + } + break; + case FUEL_GAUGE_DEVICE_CHEMISTRY: + if (dst_len == sizeof(struct sbs_gauge_device_chemistry)) { + rc = bq27z746_read_mac(dev, BQ27Z746_MAC_CMD_DEVICE_CHEM, (uint8_t *)dst, + dst_len - 1); + } else { + rc = -EINVAL; + } + break; + default: + rc = -ENOTSUP; + } + + return rc; +} + +static int bq27z746_set_prop(const struct device *dev, fuel_gauge_prop_t prop, + union fuel_gauge_prop_val val) +{ + int rc = 0; + uint16_t tmp_val = 0; + + switch (prop) { + case FUEL_GAUGE_SBS_MFR_ACCESS: + rc = bq27z746_write16(dev, BQ27Z746_MANUFACTURERACCESS, val.sbs_mfr_access_word); + val.sbs_mfr_access_word = tmp_val; + break; + case FUEL_GAUGE_SBS_ATRATE: + rc = bq27z746_write16(dev, BQ27Z746_ATRATE, val.sbs_at_rate); + val.sbs_at_rate = tmp_val; + break; + default: + rc = -ENOTSUP; + } + + return rc; +} + +static int bq27z746_init(const struct device *dev) +{ + const struct bq27z746_config *cfg; + + cfg = dev->config; + + if (!device_is_ready(cfg->i2c.bus)) { + LOG_ERR("Bus device is not ready"); + return -ENODEV; + } + + return 0; +} + +static const struct fuel_gauge_driver_api bq27z746_driver_api = { + .get_property = &bq27z746_get_prop, + .set_property = &bq27z746_set_prop, + .get_buffer_property = &bq27z746_get_buffer_prop, +}; + +#define BQ27Z746_INIT(index) \ + \ + static const struct bq27z746_config bq27z746_config_##index = { \ + .i2c = I2C_DT_SPEC_INST_GET(index), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(index, &bq27z746_init, NULL, NULL, &bq27z746_config_##index, \ + POST_KERNEL, CONFIG_FUEL_GAUGE_INIT_PRIORITY, &bq27z746_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(BQ27Z746_INIT) diff --git a/drivers/fuel_gauge/bq27z746/bq27z746.h b/drivers/fuel_gauge/bq27z746/bq27z746.h new file mode 100644 index 00000000000..6d9f821b90d --- /dev/null +++ b/drivers/fuel_gauge/bq27z746/bq27z746.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2023, ithinx GmbH + * Copyright (c) 2023, Tonies GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_FUELGAUGE_BQ27Z746_GAUGE_H_ +#define ZEPHYR_DRIVERS_FUELGAUGE_BQ27Z746_GAUGE_H_ + +#include + +/* Registers */ +#define BQ27Z746_MANUFACTURERACCESS 0x00 /* R/W */ +#define BQ27Z746_ATRATE 0x02 /* R/W, Unit: mA, Range: -32768..32767 */ +#define BQ27Z746_ATRATETIMETOEMPTY 0x04 /* R/O, Unit: minutes, Range: 0..65535 */ +#define BQ27Z746_TEMPERATURE 0x06 /* R/O, Unit: 0.1 K, Range: 0..32767 */ +#define BQ27Z746_VOLTAGE 0x08 /* R/O, Unit: mV, Range: 0..32767 */ +#define BQ27Z746_BATTERYSTATUS 0x0A /* R/O, Unit: status bits */ +#define BQ27Z746_CURRENT 0x0C /* R/O, Unit: mA, Range: -32768..32767 */ +#define BQ27Z746_REMAININGCAPACITY 0x10 /* R/O, Unit: mAh, Range: 0..32767 */ +#define BQ27Z746_FULLCHARGECAPACITY 0x12 /* R/O, Unit: mAh, Range: 0..32767 */ +#define BQ27Z746_AVERAGECURRENT 0x14 /* R/O, Unit: mA, Range: -32768..32767 */ +#define BQ27Z746_AVERAGETIMETOEMPTY 0x16 /* R/O, Unit: minutes, Range: 0..65535 */ +#define BQ27Z746_AVERAGETIMETOFULL 0x18 /* R/O, Unit: minutes, Range: 0..65535 */ +#define BQ27Z746_MAXLOADCURRENT 0x1E /* R/O, Unit: mA, Range: 0..65535 */ +#define BQ27Z746_MAXLOADTIMETOEMPTY 0x20 /* R/O, Unit: minutes, Range: 0..65535 */ +#define BQ27Z746_AVERAGEPOWER 0x22 /* R/O, Unit: mW, Range: -32768..32767 */ +#define BQ27Z746_BTPDISCHARGESET 0x24 /* Datasheet unclear */ +#define BQ27Z746_BTPCHARGESET 0x26 /* Datasheet unclear */ +#define BQ27Z746_INTERNALTEMPERATURE 0x28 /* R/O, Unit: 0.1 K, Range: 0..32767 */ +#define BQ27Z746_CYCLECOUNT 0x2A /* R/O, Unit: none, Range: 0..65535 */ +#define BQ27Z746_RELATIVESTATEOFCHARGE 0x2C /* R/O, Unit: percent, Range: 0..100 */ +#define BQ27Z746_STATEOFHEALTH 0x2E /* R/O, Unit: percent, Range: 0..100 */ +#define BQ27Z746_CHARGINGVOLTAGE 0x30 /* R/O, Unit: mV, Range: 0..32767 */ +#define BQ27Z746_CHARGINGCURRENT 0x32 /* R/O, Unit: mA, Range: 0..32767 */ +#define BQ27Z746_TERMINATEVOLTAGE 0x34 /* R/W, Unit: mC, Range: 0..32767 */ +#define BQ27Z746_TIMESTAMPUPPER 0x36 /* R/O, Unit: seconds, Range: 0..65535 */ +#define BQ27Z746_TIMESTAMPLOWER 0x38 /* R/O, Unit: seconds, Range: 0..65535 */ +#define BQ27Z746_QMAXCYCLES 0x3A /* R/O, Unit: none, Range: 0..65535 */ +#define BQ27Z746_DESIGNCAPACITY \ + 0x3C /* R/O (sealed), R/W (unsealed or factory access), Unit: mAh, Range: 0..32767 */ +#define BQ27Z746_ALTMANUFACTURERACCESS 0x3E /* R/W */ +#define BQ27Z746_MACDATA 0x40 /* R/O, MAC data */ +#define BQ27Z746_MACDATASUM 0x60 /* R/O, Checksum over MAC command and data */ +#define BQ27Z746_MACDATALEN 0x61 /* R/O, Length of the MAC data */ +#define BQ27Z746_VOLTHISETTHRESHOLD 0x62 /* R/W, Unit: mV, Range: 0..5000 */ +#define BQ27Z746_VOLTHICLEARTHRESHOLD 0x64 /* R/W, Unit: mV, Range: 0..5000 */ +#define BQ27Z746_VOLTLOSETTHRESHOLD 0x66 /* R/W, Unit: mV, Range: 0..5000 */ +#define BQ27Z746_VOLTLOCLEARTHRESHOLD 0x68 /* R/W, Unit: mV, Range: 0..5000 */ +#define BQ27Z746_TEMPHISETTHRESHOLD 0x6A /* R/W, Unit: degree celsius, Range: -128..127 */ +#define BQ27Z746_TEMPHICLEARTHRESHOLD 0x6B /* R/W, Unit: degree celsius, Range: -128..127 */ +#define BQ27Z746_TEMPLOSETTHRESHOLD 0x6C /* R/W, Unit: degree celsius, Range: -128..127 */ +#define BQ27Z746_TEMPLOCLEARTHRESHOLD 0x6D /* R/W, Unit: degree celsius, Range: -128..127 */ +#define BQ27Z746_INTERRUPTSTATUS 0x6E /* R/O, Unit: status bits */ +#define BQ27Z746_SOCDELTASETTHRESHOLD 0x6F /* R/W, Unit: percent, Range: 0..100 */ + +/* MAC commands */ +#define BQ27Z746_MAC_CMD_DEVICETYPE 0x0001 +#define BQ27Z746_MAC_CMD_FIRMWAREVERSION 0x0002 +#define BQ27Z746_MAC_CMD_HARDWAREVERSION 0x0003 +#define BQ27Z746_MAC_CMD_IFCHECKSUM 0x0004 +#define BQ27Z746_MAC_CMD_STATICDFSIGNATURE 0x0005 +#define BQ27Z746_MAC_CMD_CHEMID 0x0006 +#define BQ27Z746_MAC_CMD_PREV_MACWRITE 0x0007 +#define BQ27Z746_MAC_CMD_STATICCHEMDFSIGNATURE 0x0008 +#define BQ27Z746_MAC_CMD_ALLDFSIGNATURE 0x0009 +#define BQ27Z746_MAC_CMD_SHELFENABLE 0x000B +#define BQ27Z746_MAC_CMD_SHELFDISABLE 0x000C +#define BQ27Z746_MAC_CMD_SHUTDOWNMODE 0x0010 +#define BQ27Z746_MAC_CMD_RESET1 0x0012 +#define BQ27Z746_MAC_CMD_SHIPMODEENABLE 0x0015 +#define BQ27Z746_MAC_CMD_SHIPMODEDISABLE 0x0016 +#define BQ27Z746_MAC_CMD_QMAX_DAY 0x0017 +#define BQ27Z746_MAC_CMD_CHARGEFETTOGGLE 0x001F +#define BQ27Z746_MAC_CMD_DISCHARGEFETTOGGLE 0x0020 +#define BQ27Z746_MAC_CMD_GAUGING_IT_ENABLE 0x0021 +#define BQ27Z746_MAC_CMD_FET_ENABLE 0x0022 +#define BQ27Z746_MAC_CMD_LIFETIMEDATACOLLECTION 0x0023 +#define BQ27Z746_MAC_CMD_LIFETIMEDATARESET 0x0028 +#define BQ27Z746_MAC_CMD_CALIBRATIONMODE 0x002D +#define BQ27Z746_MAC_CMD_LIFETIMEDATAFLUSH 0x002E +#define BQ27Z746_MAC_CMD_LIFETIMEDATASPEEDUPMODE 0x002F +#define BQ27Z746_MAC_CMD_SEALDEVICE 0x0030 +#define BQ27Z746_MAC_CMD_SECURITYKEYS 0x0035 +#define BQ27Z746_MAC_CMD_RESET2 0x0041 +#define BQ27Z746_MAC_CMD_TAMBIENTSYNC 0x0047 +#define BQ27Z746_MAC_CMD_DEVICE_NAME 0x004A +#define BQ27Z746_MAC_CMD_DEVICE_CHEM 0x004B +#define BQ27Z746_MAC_CMD_MANUFACTURER_NAME 0x004C +#define BQ27Z746_MAC_CMD_MANUFACTURE_DATE 0x004D +#define BQ27Z746_MAC_CMD_SERIAL_NUMBER 0x004E +#define BQ27Z746_MAC_CMD_SAFETYALERT 0x0050 +#define BQ27Z746_MAC_CMD_SAFETYSTATUS 0x0051 +#define BQ27Z746_MAC_CMD_OPERATIONSTATUS 0x0054 +#define BQ27Z746_MAC_CMD_CHARGINGSTATUS 0x0055 +#define BQ27Z746_MAC_CMD_GAUGINGSTATUS 0x0056 +#define BQ27Z746_MAC_CMD_MANUFACTURINGSTATUS 0x0057 +#define BQ27Z746_MAC_CMD_LIFETIMEDATABLOCK1 0x0060 +#define BQ27Z746_MAC_CMD_LIFETIMEDATABLOCK2 0x0061 +#define BQ27Z746_MAC_CMD_LIFETIMEDATABLOCK3 0x0062 +#define BQ27Z746_MAC_CMD_LIFETIMEDATABLOCK4 0x0063 +#define BQ27Z746_MAC_CMD_LIFETIMEDATABLOCK6 0x0065 +#define BQ27Z746_MAC_CMD_LIFETIMEDATABLOCK7 0x0065 +#define BQ27Z746_MAC_CMD_LIFETIMEDATABLOCK8 0x0067 +#define BQ27Z746_MAC_CMD_LIFETIMEDATABLOCK9 0x0068 +#define BQ27Z746_MAC_CMD_LIFETIMEDATABLOCK10 0x0069 +#define BQ27Z746_MAC_CMD_LIFETIMEDATABLOCK11 0x006A +#define BQ27Z746_MAC_CMD_LIFETIMEDATABLOCK12 0x006B +#define BQ27Z746_MAC_CMD_MANUFACTURERINFO 0x0070 +#define BQ27Z746_MAC_CMD_DASTATUS1 0x0071 +#define BQ27Z746_MAC_CMD_DASTATUS2 0x0072 +#define BQ27Z746_MAC_CMD_ITSTATUS1 0x0073 +#define BQ27Z746_MAC_CMD_ITSTATUS2 0x0074 +#define BQ27Z746_MAC_CMD_ITSTATUS3 0x0075 +#define BQ27Z746_MAC_CMD_FCC_SOH 0x0077 +#define BQ27Z746_MAC_CMD_FILTERED_CAPACITY 0x0078 +#define BQ27Z746_MAC_CMD_MANUFACTURERINFOB 0x007A +#define BQ27Z746_MAC_CMD_MANUFACTURERINFOC 0x007B +#define BQ27Z746_MAC_CMD_FET_CONTROL_OVERRIDE 0x0097 +#define BQ27Z746_MAC_CMD_SYSTEM_RESET_ENABLE 0x00A3 +#define BQ27Z746_MAC_CMD_SYSTEM_RESET 0x00A4 +#define BQ27Z746_MAC_CMD_BATTSENSEOUTPUT 0x00B1 +#define BQ27Z746_MAC_CMD_RATABLECELL0 0x00E0 +#define BQ27Z746_MAC_CMD_ROMMODE 0x0F00 +#define BQ27Z746_MAC_CMD_DATAFLASHACCESS 0x4000 +#define BQ27Z746_MAC_CMD_SWITCHTOHDQ 0x7C40 +#define BQ27Z746_MAC_CMD_EXITCALIBRATIONOUTPUT 0xF080 +#define BQ27Z746_MAC_CMD_OUTPUTCCANDADCFORCALIBRATIO 0xF081 +#define BQ27Z746_MAC_CMD_OUTPUTTEMPERATURECAL 0xF083 +#define BQ27Z746_MAC_CMD_PROTECTORCALIBRATION 0xF0A0 +#define BQ27Z746_MAC_CMD_PROTECTORIMAGE1 0xF0A1 +#define BQ27Z746_MAC_CMD_PROTECTORIMAGE2 0xF0A2 +#define BQ27Z746_MAC_CMD_PROTECTORIMAGESAVE 0xF0A3 +#define BQ27Z746_MAC_CMD_PROTECTORIMAGELOCK 0xF0A4 +#define BQ27Z746_MAC_CMD_PROTECTORFACTORYCONFIG 0xF0A5 + +struct bq27z746_config { + struct i2c_dt_spec i2c; +}; + +#endif diff --git a/drivers/fuel_gauge/bq27z746/emul_bq27z746.c b/drivers/fuel_gauge/bq27z746/emul_bq27z746.c new file mode 100644 index 00000000000..b416babd0d5 --- /dev/null +++ b/drivers/fuel_gauge/bq27z746/emul_bq27z746.c @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2023, ithinx GmbH + * Copyright (c) 2023, Tonies GmbH + * + * SPDX-License-Identifier: Apache-2.0 + * + * Emulator for bq27z746 fuel gauge + */ + +#include +#define DT_DRV_COMPAT ti_bq27z746 + +#include +LOG_MODULE_REGISTER(EMUL_BQ27Z746); + +#include +#include +#include +#include +#include + +#include "bq27z746.h" + +#define BQ27Z746_MAC_DATA_LEN 32 +#define BQ27Z746_MAC_OVERHEAD_LEN 4 /* 2 cmd bytes, 1 length byte, 1 checksum byte */ +#define BQ27Z746_MAC_COMPLETE_LEN (BQ27Z746_MAC_DATA_LEN + BQ27Z746_MAC_OVERHEAD_LEN) + +struct bq27z746_emul_data { + uint16_t mac_cmd; +}; + +/** Static configuration for the emulator */ +struct bq27z746_emul_cfg { + /** I2C address of emulator */ + uint16_t addr; +}; + +static int emul_bq27z746_read_altmac(const struct emul *target, uint8_t *buf, size_t len) +{ + const uint8_t manufacturer_name[] = "Texas Instruments"; + const uint8_t device_name[] = "BQ27Z746"; + const uint8_t device_chemistry[] = "LION"; + const struct bq27z746_emul_data *data = target->data; + + if (len < BQ27Z746_MAC_COMPLETE_LEN) { + LOG_ERR("When reading the ALTMAC, one must read the full %u byte", + BQ27Z746_MAC_COMPLETE_LEN); + return -EIO; + } + + memset(buf, 0, len); + + /* + * The data read from BQ27Z746_ALTMANUFACTURERACCESS is: + * 0..1: The command (for verification) + * 2..33: The data + * 34: Checksum calculated as (uint8_t)(0xFF - (sum of all command and data bytes)) + * 35: Length including command, checksum and length (e.g. data length + 4) + */ + + /* Put the command in the first two byte */ + sys_put_le16(data->mac_cmd, buf); + + /* Based on the command, put some data and the length into the buffer. */ + /* In all of the operations, don't consider the zero-terminator. */ + switch (data->mac_cmd) { + case BQ27Z746_MAC_CMD_MANUFACTURER_NAME: + memcpy(&buf[2], manufacturer_name, sizeof(manufacturer_name) - 1); + buf[35] = sizeof(manufacturer_name) - 1 + BQ27Z746_MAC_OVERHEAD_LEN; + break; + case BQ27Z746_MAC_CMD_DEVICE_NAME: + memcpy(&buf[2], device_name, sizeof(device_name) - 1); + buf[35] = sizeof(device_name) - 1 + BQ27Z746_MAC_OVERHEAD_LEN; + break; + case BQ27Z746_MAC_CMD_DEVICE_CHEM: + memcpy(&buf[2], device_chemistry, sizeof(device_chemistry) - 1); + buf[35] = sizeof(device_chemistry) - 1 + BQ27Z746_MAC_OVERHEAD_LEN; + break; + default: + LOG_ERR("ALTMAC command 0x%x is not supported", data->mac_cmd); + return -EIO; + } + + /* Calculate the checksum */ + uint8_t sum = 0; /* Intentionally 8 bit wide and overflowing */ + + for (int i = 0; i < BQ27Z746_MAC_COMPLETE_LEN - 2; i++) { + sum += buf[i]; + } + buf[34] = 0xFF - sum; + + return 0; +} + +static int emul_bq27z746_write(const struct emul *target, uint8_t *buf, size_t len) +{ + struct bq27z746_emul_data *data = target->data; + const uint8_t reg = buf[0]; + + switch (reg) { + case BQ27Z746_ALTMANUFACTURERACCESS: + data->mac_cmd = sys_get_le16(&buf[1]); + return 0; + default: + LOG_ERR("Writing is only supported to ALTMAC currently"); + return -EIO; + } +} + +static int emul_bq27z746_reg_read(const struct emul *target, int reg, int *val) +{ + switch (reg) { + case BQ27Z746_MANUFACTURERACCESS: + *val = 1; + break; + case BQ27Z746_ATRATE: + *val = -2; + break; + case BQ27Z746_ATRATETIMETOEMPTY: + *val = 1; + break; + case BQ27Z746_TEMPERATURE: + *val = 1; + break; + case BQ27Z746_VOLTAGE: + *val = 1; + break; + case BQ27Z746_BATTERYSTATUS: + *val = 1; + break; + case BQ27Z746_CURRENT: + *val = -2; + break; + case BQ27Z746_REMAININGCAPACITY: + *val = 1; + break; + case BQ27Z746_FULLCHARGECAPACITY: + *val = 1; + break; + case BQ27Z746_AVERAGECURRENT: + *val = -2; + break; + case BQ27Z746_AVERAGETIMETOEMPTY: + *val = 1; + break; + case BQ27Z746_AVERAGETIMETOFULL: + *val = 1; + break; + case BQ27Z746_MAXLOADCURRENT: + *val = 1; + break; + case BQ27Z746_MAXLOADTIMETOEMPTY: + *val = 1; + break; + case BQ27Z746_AVERAGEPOWER: + *val = 1; + break; + case BQ27Z746_BTPDISCHARGESET: + *val = 1; + break; + case BQ27Z746_BTPCHARGESET: + *val = 1; + break; + case BQ27Z746_INTERNALTEMPERATURE: + *val = 1; + break; + case BQ27Z746_CYCLECOUNT: + *val = 1; + break; + case BQ27Z746_RELATIVESTATEOFCHARGE: + *val = 1; + break; + case BQ27Z746_STATEOFHEALTH: + *val = 1; + break; + case BQ27Z746_CHARGINGVOLTAGE: + *val = 1; + break; + case BQ27Z746_CHARGINGCURRENT: + *val = 1; + break; + case BQ27Z746_TERMINATEVOLTAGE: + *val = 1; + break; + case BQ27Z746_TIMESTAMPUPPER: + *val = 1; + break; + case BQ27Z746_TIMESTAMPLOWER: + *val = 1; + break; + case BQ27Z746_QMAXCYCLES: + *val = 1; + break; + case BQ27Z746_DESIGNCAPACITY: + *val = 1; + break; + case BQ27Z746_ALTMANUFACTURERACCESS: + *val = 1; + break; + case BQ27Z746_MACDATA: + *val = 1; + break; + case BQ27Z746_MACDATASUM: + *val = 1; + break; + case BQ27Z746_MACDATALEN: + *val = 1; + break; + case BQ27Z746_VOLTHISETTHRESHOLD: + *val = 1; + break; + case BQ27Z746_VOLTHICLEARTHRESHOLD: + *val = 1; + break; + case BQ27Z746_VOLTLOSETTHRESHOLD: + *val = 1; + break; + case BQ27Z746_VOLTLOCLEARTHRESHOLD: + *val = 1; + break; + case BQ27Z746_TEMPHISETTHRESHOLD: + *val = 1; + break; + case BQ27Z746_TEMPHICLEARTHRESHOLD: + *val = 1; + break; + case BQ27Z746_TEMPLOSETTHRESHOLD: + *val = 1; + break; + case BQ27Z746_TEMPLOCLEARTHRESHOLD: + *val = 1; + break; + case BQ27Z746_INTERRUPTSTATUS: + *val = 1; + break; + case BQ27Z746_SOCDELTASETTHRESHOLD: + *val = 1; + break; + default: + LOG_ERR("Unknown register 0x%x read", reg); + return -EIO; + } + LOG_INF("read 0x%x = 0x%x", reg, *val); + + return 0; +} + +static int emul_bq27z746_read(const struct emul *target, int reg, uint8_t *buf, size_t len) +{ + if (len == 2) { + unsigned int val; + int rc = emul_bq27z746_reg_read(target, reg, &val); + + if (rc) { + return rc; + } + + sys_put_le16(val, buf); + } else { + switch (reg) { + case BQ27Z746_ALTMANUFACTURERACCESS: + LOG_DBG("Reading %u byte from ALTMAC", len); + emul_bq27z746_read_altmac(target, buf, len); + break; + default: + LOG_ERR("Reading is only supported from ALTMAC currently"); + return -EIO; + } + } + + return 0; +} + +static int bq27z746_emul_transfer_i2c(const struct emul *target, struct i2c_msg *msgs, int num_msgs, + int addr) +{ + int reg; + int rc; + + __ASSERT_NO_MSG(msgs && num_msgs); + + i2c_dump_msgs_rw(target->dev, msgs, num_msgs, addr, false); + switch (num_msgs) { + case 1: + if (msgs->flags & I2C_MSG_READ) { + LOG_ERR("Unexpected read"); + return -EIO; + } + + return emul_bq27z746_write(target, msgs->buf, msgs->len); + case 2: + if (msgs->flags & I2C_MSG_READ) { + LOG_ERR("Unexpected read"); + return -EIO; + } + if (msgs->len != 1) { + LOG_ERR("Unexpected msg0 length %d", msgs->len); + return -EIO; + } + reg = msgs->buf[0]; + + /* Now process the 'read' part of the message */ + msgs++; + if (msgs->flags & I2C_MSG_READ) { + rc = emul_bq27z746_read(target, reg, msgs->buf, msgs->len); + if (rc) { + return rc; + } + } else { + LOG_ERR("Second message must be an I2C write"); + return -EIO; + } + return rc; + default: + LOG_ERR("Invalid number of messages: %d", num_msgs); + return -EIO; + } + + return 0; +} + +static const struct i2c_emul_api bq27z746_emul_api_i2c = { + .transfer = bq27z746_emul_transfer_i2c, +}; + +/** + * Set up a new emulator (I2C) + * + * @param emul Emulation information + * @param parent Device to emulate + * @return 0 indicating success (always) + */ +static int emul_bq27z746_init(const struct emul *target, const struct device *parent) +{ + ARG_UNUSED(target); + ARG_UNUSED(parent); + + return 0; +} + +/* + * Main instantiation macro. + */ +#define BQ27Z746_EMUL(n) \ + static struct bq27z746_emul_data bq27z746_emul_data_##n; \ + static const struct bq27z746_emul_cfg bq27z746_emul_cfg_##n = { \ + .addr = DT_INST_REG_ADDR(n), \ + }; \ + EMUL_DT_INST_DEFINE(n, emul_bq27z746_init, &bq27z746_emul_data_##n, \ + &bq27z746_emul_cfg_##n, &bq27z746_emul_api_i2c, NULL) + +DT_INST_FOREACH_STATUS_OKAY(BQ27Z746_EMUL) diff --git a/drivers/fuel_gauge/emul_fuel_gauge_syscall_handlers.c b/drivers/fuel_gauge/emul_fuel_gauge_syscall_handlers.c new file mode 100644 index 00000000000..2382fcad77b --- /dev/null +++ b/drivers/fuel_gauge/emul_fuel_gauge_syscall_handlers.c @@ -0,0 +1,25 @@ +/* + * Copyright 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* Emulator syscalls just need to exist as stubs as these are only called by tests. */ + +static inline int z_vrfy_emul_fuel_gauge_is_battery_cutoff(const struct emul *target, bool *cutoff) +{ + return z_impl_emul_fuel_gauge_is_battery_cutoff(target, cutoff); +} + +#include + +static inline int z_vrfy_emul_fuel_gauge_set_battery_charging(const struct emul *target, + uint32_t uV, int uA) +{ + return z_impl_emul_fuel_gauge_set_battery_charging(target, uV, uA); +} + +#include diff --git a/drivers/fuel_gauge/fuel_gauge_syscall_handlers.c b/drivers/fuel_gauge/fuel_gauge_syscall_handlers.c index 4c664b0f551..312564c35a6 100644 --- a/drivers/fuel_gauge/fuel_gauge_syscall_handlers.c +++ b/drivers/fuel_gauge/fuel_gauge_syscall_handlers.c @@ -5,66 +5,89 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include -static inline int z_vrfy_fuel_gauge_get_prop(const struct device *dev, - struct fuel_gauge_get_property *props, - size_t props_len) +static inline int z_vrfy_fuel_gauge_get_prop(const struct device *dev, fuel_gauge_prop_t prop, + union fuel_gauge_prop_val *val) { - struct fuel_gauge_get_property k_props[props_len]; + union fuel_gauge_prop_val k_val; - Z_OOPS(Z_SYSCALL_DRIVER_FUEL_GAUGE(dev, get_property)); + K_OOPS(K_SYSCALL_DRIVER_FUEL_GAUGE(dev, get_property)); - Z_OOPS(z_user_from_copy(k_props, props, - props_len * sizeof(struct fuel_gauge_get_property))); + K_OOPS(k_usermode_from_copy(&k_val, val, sizeof(union fuel_gauge_prop_val))); - int ret = z_impl_fuel_gauge_get_prop(dev, k_props, props_len); + int ret = z_impl_fuel_gauge_get_prop(dev, prop, &k_val); - Z_OOPS(z_user_to_copy(props, k_props, props_len * sizeof(struct fuel_gauge_get_property))); + K_OOPS(k_usermode_to_copy(val, &k_val, sizeof(union fuel_gauge_prop_val))); return ret; } #include -static inline int z_vrfy_fuel_gauge_set_prop(const struct device *dev, - struct fuel_gauge_set_property *props, - size_t props_len) +static inline int z_vrfy_fuel_gauge_get_props(const struct device *dev, fuel_gauge_prop_t *props, + union fuel_gauge_prop_val *vals, size_t len) { - struct fuel_gauge_set_property k_props[props_len]; + union fuel_gauge_prop_val k_vals[len]; + fuel_gauge_prop_t k_props[len]; - Z_OOPS(Z_SYSCALL_DRIVER_FUEL_GAUGE(dev, set_property)); + K_OOPS(K_SYSCALL_DRIVER_FUEL_GAUGE(dev, get_property)); - Z_OOPS(z_user_from_copy(k_props, props, - props_len * sizeof(struct fuel_gauge_set_property))); + K_OOPS(k_usermode_from_copy(k_vals, vals, len * sizeof(union fuel_gauge_prop_val))); + K_OOPS(k_usermode_from_copy(k_props, props, len * sizeof(fuel_gauge_prop_t))); - int ret = z_impl_fuel_gauge_set_prop(dev, k_props, props_len); + int ret = z_impl_fuel_gauge_get_props(dev, k_props, k_vals, len); - Z_OOPS(z_user_to_copy(props, k_props, props_len * sizeof(struct fuel_gauge_set_property))); + K_OOPS(k_usermode_to_copy(vals, k_vals, len * sizeof(union fuel_gauge_prop_val))); + + return ret; +} + +#include + +static inline int z_vrfy_fuel_gauge_set_prop(const struct device *dev, fuel_gauge_prop_t prop, + union fuel_gauge_prop_val val) +{ + K_OOPS(K_SYSCALL_DRIVER_FUEL_GAUGE(dev, set_property)); + + int ret = z_impl_fuel_gauge_set_prop(dev, prop, val); return ret; } #include -static inline int z_vrfy_fuel_gauge_get_buffer_prop(const struct device *dev, - struct fuel_gauge_get_buffer_property *prop, - void *dst, size_t dst_len) +static inline int z_vrfy_fuel_gauge_set_props(const struct device *dev, fuel_gauge_prop_t *props, + union fuel_gauge_prop_val *vals, size_t len) { - struct fuel_gauge_get_buffer_property k_prop; + union fuel_gauge_prop_val k_vals[len]; + fuel_gauge_prop_t k_props[len]; - Z_OOPS(Z_SYSCALL_DRIVER_FUEL_GAUGE(dev, get_buffer_property)); + K_OOPS(K_SYSCALL_DRIVER_FUEL_GAUGE(dev, set_property)); - Z_OOPS(z_user_from_copy(&k_prop, prop, - sizeof(struct fuel_gauge_get_buffer_property))); + K_OOPS(k_usermode_from_copy(k_vals, vals, len * sizeof(union fuel_gauge_prop_val))); + K_OOPS(k_usermode_from_copy(k_props, props, len * sizeof(fuel_gauge_prop_t))); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(dst, dst_len)); + int ret = z_impl_fuel_gauge_set_props(dev, k_props, k_vals, len); + + /* We only copy back vals because props will never be modified */ + K_OOPS(k_usermode_to_copy(vals, k_vals, len * sizeof(union fuel_gauge_prop_val))); + + return ret; +} + +#include + +static inline int z_vrfy_fuel_gauge_get_buffer_prop(const struct device *dev, + fuel_gauge_prop_t prop, void *dst, + size_t dst_len) +{ + K_OOPS(K_SYSCALL_DRIVER_FUEL_GAUGE(dev, get_buffer_property)); - int ret = z_impl_fuel_gauge_get_buffer_prop(dev, &k_prop, dst, dst_len); + K_OOPS(K_SYSCALL_MEMORY_WRITE(dst, dst_len)); - Z_OOPS(z_user_to_copy(prop, &k_prop, - sizeof(struct fuel_gauge_get_buffer_property))); + int ret = z_impl_fuel_gauge_get_buffer_prop(dev, prop, dst, dst_len); return ret; } @@ -73,7 +96,7 @@ static inline int z_vrfy_fuel_gauge_get_buffer_prop(const struct device *dev, static inline int z_vrfy_fuel_gauge_battery_cutoff(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_FUEL_GAUGE(dev, battery_cutoff)); + K_OOPS(K_SYSCALL_DRIVER_FUEL_GAUGE(dev, battery_cutoff)); return z_impl_fuel_gauge_battery_cutoff(dev); } diff --git a/drivers/fuel_gauge/max17048/emul_max17048.c b/drivers/fuel_gauge/max17048/emul_max17048.c index 3ae1565cb47..a3a09f4c03e 100644 --- a/drivers/fuel_gauge/max17048/emul_max17048.c +++ b/drivers/fuel_gauge/max17048/emul_max17048.c @@ -75,7 +75,7 @@ static int max17048_emul_transfer_i2c(const struct emul *target, struct i2c_msg __ASSERT_NO_MSG(msgs && num_msgs); - i2c_dump_msgs_rw("emul", msgs, num_msgs, addr, false); + i2c_dump_msgs_rw(target->dev, msgs, num_msgs, addr, false); switch (num_msgs) { case 2: if (msgs->flags & I2C_MSG_READ) { diff --git a/drivers/fuel_gauge/max17048/max17048.c b/drivers/fuel_gauge/max17048/max17048.c index 3da147e3c29..a54fb331ae5 100644 --- a/drivers/fuel_gauge/max17048/max17048.c +++ b/drivers/fuel_gauge/max17048/max17048.c @@ -90,7 +90,7 @@ int max17048_voltage(const struct device *i2c_dev, uint16_t *response) * milli volts instead of volts. */ - *response = *response * 78125 / 1000000; + *response = (uint16_t)((uint32_t)*response * 78125L / 1000000L); return 0; } @@ -175,43 +175,42 @@ static int max17048_init(const struct device *dev) /** * Get a single property from the fuel gauge */ -static int max17048_get_prop(const struct device *dev, struct fuel_gauge_get_property *prop) +static int max17048_get_single_prop_impl(const struct device *dev, fuel_gauge_prop_t prop, + union fuel_gauge_prop_val *val) { struct max17048_data *data = dev->data; int rc = 0; - switch (prop->property_type) { + switch (prop) { case FUEL_GAUGE_RUNTIME_TO_EMPTY: - prop->value.runtime_to_empty = data->time_to_empty; + val->runtime_to_empty = data->time_to_empty; break; case FUEL_GAUGE_RUNTIME_TO_FULL: - prop->value.runtime_to_full = data->time_to_full; + val->runtime_to_full = data->time_to_full; break; case FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE: - prop->value.relative_state_of_charge = data->charge; + val->relative_state_of_charge = data->charge; break; case FUEL_GAUGE_VOLTAGE: - prop->value.voltage = data->voltage; + val->voltage = data->voltage; break; default: rc = -ENOTSUP; } - prop->status = rc; - return rc; } /** - * Get all possible properties from the fuel gague + * Get properties from the fuel gauge */ -static int max17048_get_props(const struct device *dev, struct fuel_gauge_get_property *props, - size_t len) +static int max17048_get_prop(const struct device *dev, fuel_gauge_prop_t prop, + union fuel_gauge_prop_val *val) { - int err_count = 0; struct max17048_data *data = dev->data; int rc = max17048_percent(dev, &data->charge); int16_t crate; + int ret; if (rc < 0) { LOG_ERR("Error while reading battery percentage"); @@ -242,7 +241,6 @@ static int max17048_get_props(const struct device *dev, struct fuel_gauge_get_pr */ data->charging = crate > 0; - /** * In the following code, we multiply by 1000 the charge to increase the * precision. If we just truncate the division without this multiplier, @@ -266,12 +264,6 @@ static int max17048_get_props(const struct device *dev, struct fuel_gauge_get_pr data->time_to_empty = hours_pending * 60 / 1000; data->time_to_full = 0; } - - for (int i = 0; i < len; i++) { - int ret = max17048_get_prop(dev, props + i); - - err_count += ret ? 1 : 0; - } } else { /** * This case is to avoid a division by 0 when the charge rate is the same @@ -283,13 +275,13 @@ static int max17048_get_props(const struct device *dev, struct fuel_gauge_get_pr data->time_to_empty = 0; } - err_count = (err_count == len) ? -1 : err_count; + ret = max17048_get_single_prop_impl(dev, prop, val); - return err_count; + return ret; } static const struct fuel_gauge_driver_api max17048_driver_api = { - .get_property = &max17048_get_props, + .get_property = &max17048_get_prop, }; #define MAX17048_DEFINE(inst) \ diff --git a/drivers/fuel_gauge/sbs_gauge/emul_sbs_gauge.c b/drivers/fuel_gauge/sbs_gauge/emul_sbs_gauge.c index c84a73e75ff..160552edeff 100644 --- a/drivers/fuel_gauge/sbs_gauge/emul_sbs_gauge.c +++ b/drivers/fuel_gauge/sbs_gauge/emul_sbs_gauge.c @@ -233,7 +233,7 @@ static int sbs_gauge_emul_transfer_i2c(const struct emul *target, struct i2c_msg __ASSERT_NO_MSG(msgs && num_msgs); - i2c_dump_msgs_rw("emul", msgs, num_msgs, addr, false); + i2c_dump_msgs_rw(target->dev, msgs, num_msgs, addr, false); switch (num_msgs) { case 2: if (msgs->flags & I2C_MSG_READ) { @@ -342,9 +342,6 @@ static void emul_sbs_gauge_reset_rule_after(const struct ztest_unit_test *test, DT_INST_FOREACH_STATUS_OKAY(SBS_GAUGE_EMUL_RESET_RULE_BEFORE) } ZTEST_RULE(emul_sbs_gauge_reset, NULL, emul_sbs_gauge_reset_rule_after); -#else /* !CONFIG_ZTEST */ -/* Stub ZTEST_DMEM in case emulator is not used in a testing environment. */ -#define ZTEST_DMEM #endif /* CONFIG_ZTEST */ /** diff --git a/drivers/fuel_gauge/sbs_gauge/sbs_gauge.c b/drivers/fuel_gauge/sbs_gauge/sbs_gauge.c index e136900187d..4c9ba6702aa 100644 --- a/drivers/fuel_gauge/sbs_gauge/sbs_gauge.c +++ b/drivers/fuel_gauge/sbs_gauge/sbs_gauge.c @@ -66,114 +66,113 @@ static int sbs_cmd_buffer_read(const struct device *dev, uint8_t reg_addr, char return 0; } -static int sbs_gauge_get_prop(const struct device *dev, struct fuel_gauge_get_property *prop) +static int sbs_gauge_get_prop(const struct device *dev, fuel_gauge_prop_t prop, + union fuel_gauge_prop_val *val) { int rc = 0; - uint16_t val = 0; + uint16_t tmp_val = 0; - switch (prop->property_type) { + switch (prop) { case FUEL_GAUGE_AVG_CURRENT: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_AVG_CURRENT, &val); - prop->value.avg_current = val * 1000; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_AVG_CURRENT, &tmp_val); + val->avg_current = tmp_val * 1000; break; case FUEL_GAUGE_CYCLE_COUNT: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_CYCLE_COUNT, &val); - prop->value.cycle_count = val; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_CYCLE_COUNT, &tmp_val); + val->cycle_count = tmp_val; break; case FUEL_GAUGE_CURRENT: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_CURRENT, &val); - prop->value.current = val * 1000; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_CURRENT, &tmp_val); + val->current = tmp_val * 1000; break; case FUEL_GAUGE_FULL_CHARGE_CAPACITY: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_FULL_CAPACITY, &val); - prop->value.full_charge_capacity = val * 1000; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_FULL_CAPACITY, &tmp_val); + val->full_charge_capacity = tmp_val * 1000; break; case FUEL_GAUGE_REMAINING_CAPACITY: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_REM_CAPACITY, &val); - prop->value.remaining_capacity = val * 1000; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_REM_CAPACITY, &tmp_val); + val->remaining_capacity = tmp_val * 1000; break; case FUEL_GAUGE_RUNTIME_TO_EMPTY: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_RUNTIME2EMPTY, &val); - prop->value.runtime_to_empty = val; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_RUNTIME2EMPTY, &tmp_val); + val->runtime_to_empty = tmp_val; break; case FUEL_GAUGE_RUNTIME_TO_FULL: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_AVG_TIME2FULL, &val); - prop->value.runtime_to_full = val; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_AVG_TIME2FULL, &tmp_val); + val->runtime_to_full = tmp_val; break; case FUEL_GAUGE_SBS_MFR_ACCESS: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_MANUFACTURER_ACCESS, &val); - prop->value.sbs_mfr_access_word = val; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_MANUFACTURER_ACCESS, &tmp_val); + val->sbs_mfr_access_word = tmp_val; break; case FUEL_GAUGE_ABSOLUTE_STATE_OF_CHARGE: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_ASOC, &val); - prop->value.absolute_state_of_charge = val; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_ASOC, &tmp_val); + val->absolute_state_of_charge = tmp_val; break; case FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_RSOC, &val); - prop->value.relative_state_of_charge = val; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_RSOC, &tmp_val); + val->relative_state_of_charge = tmp_val; break; case FUEL_GAUGE_TEMPERATURE: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_TEMP, &val); - prop->value.temperature = val; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_TEMP, &tmp_val); + val->temperature = tmp_val; break; case FUEL_GAUGE_VOLTAGE: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_VOLTAGE, &val); - prop->value.voltage = val * 1000; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_VOLTAGE, &tmp_val); + val->voltage = tmp_val * 1000; break; case FUEL_GAUGE_SBS_MODE: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_BATTERY_MODE, &val); - prop->value.sbs_mode = val; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_BATTERY_MODE, &tmp_val); + val->sbs_mode = tmp_val; break; case FUEL_GAUGE_CHARGE_CURRENT: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_CHG_CURRENT, &val); - prop->value.chg_current = val; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_CHG_CURRENT, &tmp_val); + val->chg_current = tmp_val * 1000; break; case FUEL_GAUGE_CHARGE_VOLTAGE: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_CHG_VOLTAGE, &val); - prop->value.chg_voltage = val; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_CHG_VOLTAGE, &tmp_val); + val->chg_voltage = tmp_val * 1000; break; case FUEL_GAUGE_STATUS: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_FLAGS, &val); - prop->value.fg_status = val; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_FLAGS, &tmp_val); + val->fg_status = tmp_val; break; case FUEL_GAUGE_DESIGN_CAPACITY: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_NOM_CAPACITY, &val); - prop->value.design_cap = val; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_NOM_CAPACITY, &tmp_val); + val->design_cap = tmp_val; break; case FUEL_GAUGE_DESIGN_VOLTAGE: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_DESIGN_VOLTAGE, &val); - prop->value.design_volt = val; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_DESIGN_VOLTAGE, &tmp_val); + val->design_volt = tmp_val; break; case FUEL_GAUGE_SBS_ATRATE: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_AR, &val); - prop->value.sbs_at_rate = val; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_AR, &tmp_val); + val->sbs_at_rate = tmp_val; break; case FUEL_GAUGE_SBS_ATRATE_TIME_TO_FULL: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_ARTTF, &val); - prop->value.sbs_at_rate_time_to_full = val; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_ARTTF, &tmp_val); + val->sbs_at_rate_time_to_full = tmp_val; break; case FUEL_GAUGE_SBS_ATRATE_TIME_TO_EMPTY: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_ARTTE, &val); - prop->value.sbs_at_rate_time_to_empty = val; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_ARTTE, &tmp_val); + val->sbs_at_rate_time_to_empty = tmp_val; break; case FUEL_GAUGE_SBS_ATRATE_OK: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_AROK, &val); - prop->value.sbs_at_rate_ok = val; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_AROK, &tmp_val); + val->sbs_at_rate_ok = tmp_val; break; case FUEL_GAUGE_SBS_REMAINING_CAPACITY_ALARM: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_REM_CAPACITY_ALARM, &val); - prop->value.sbs_remaining_capacity_alarm = val; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_REM_CAPACITY_ALARM, &tmp_val); + val->sbs_remaining_capacity_alarm = tmp_val; break; case FUEL_GAUGE_SBS_REMAINING_TIME_ALARM: - rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_REM_TIME_ALARM, &val); - prop->value.sbs_remaining_time_alarm = val; + rc = sbs_cmd_reg_read(dev, SBS_GAUGE_CMD_REM_TIME_ALARM, &tmp_val); + val->sbs_remaining_time_alarm = tmp_val; break; default: rc = -ENOTSUP; } - prop->status = rc; - return rc; } @@ -196,52 +195,51 @@ static int sbs_gauge_do_battery_cutoff(const struct device *dev) return rc; } -static int sbs_gauge_set_prop(const struct device *dev, struct fuel_gauge_set_property *prop) +static int sbs_gauge_set_prop(const struct device *dev, fuel_gauge_prop_t prop, + union fuel_gauge_prop_val val) { int rc = 0; - uint16_t val = 0; + uint16_t tmp_val = 0; - switch (prop->property_type) { + switch (prop) { case FUEL_GAUGE_SBS_MFR_ACCESS: rc = sbs_cmd_reg_write(dev, SBS_GAUGE_CMD_MANUFACTURER_ACCESS, - prop->value.sbs_mfr_access_word); - prop->value.sbs_mfr_access_word = val; + val.sbs_mfr_access_word); + val.sbs_mfr_access_word = tmp_val; break; case FUEL_GAUGE_SBS_REMAINING_CAPACITY_ALARM: rc = sbs_cmd_reg_write(dev, SBS_GAUGE_CMD_REM_CAPACITY_ALARM, - prop->value.sbs_remaining_capacity_alarm); - prop->value.sbs_remaining_capacity_alarm = val; + val.sbs_remaining_capacity_alarm); + val.sbs_remaining_capacity_alarm = tmp_val; break; case FUEL_GAUGE_SBS_REMAINING_TIME_ALARM: rc = sbs_cmd_reg_write(dev, SBS_GAUGE_CMD_REM_TIME_ALARM, - prop->value.sbs_remaining_time_alarm); - prop->value.sbs_remaining_time_alarm = val; + val.sbs_remaining_time_alarm); + val.sbs_remaining_time_alarm = tmp_val; break; case FUEL_GAUGE_SBS_MODE: - rc = sbs_cmd_reg_write(dev, SBS_GAUGE_CMD_BATTERY_MODE, prop->value.sbs_mode); - prop->value.sbs_mode = val; + rc = sbs_cmd_reg_write(dev, SBS_GAUGE_CMD_BATTERY_MODE, val.sbs_mode); + val.sbs_mode = tmp_val; break; case FUEL_GAUGE_SBS_ATRATE: - rc = sbs_cmd_reg_write(dev, SBS_GAUGE_CMD_AR, prop->value.sbs_at_rate); - prop->value.sbs_at_rate = val; + rc = sbs_cmd_reg_write(dev, SBS_GAUGE_CMD_AR, val.sbs_at_rate); + val.sbs_at_rate = tmp_val; break; default: rc = -ENOTSUP; } - prop->status = rc; - return rc; } static int sbs_gauge_get_buffer_prop(const struct device *dev, - struct fuel_gauge_get_buffer_property *prop, void *dst, + fuel_gauge_prop_t prop_type, void *dst, size_t dst_len) { int rc = 0; - switch (prop->property_type) { + switch (prop_type) { case FUEL_GAUGE_MANUFACTURER_NAME: if (dst_len == sizeof(struct sbs_gauge_manufacturer_name)) { rc = sbs_cmd_buffer_read(dev, SBS_GAUGE_CMD_MANUFACTURER_NAME, (char *)dst, @@ -270,42 +268,9 @@ static int sbs_gauge_get_buffer_prop(const struct device *dev, rc = -ENOTSUP; } - prop->status = rc; return rc; } -static int sbs_gauge_get_props(const struct device *dev, struct fuel_gauge_get_property *props, - size_t len) -{ - int err_count = 0; - - for (int i = 0; i < len; i++) { - int ret = sbs_gauge_get_prop(dev, props + i); - - err_count += ret ? 1 : 0; - } - - err_count = (err_count == len) ? -1 : err_count; - - return err_count; -} - -static int sbs_gauge_set_props(const struct device *dev, struct fuel_gauge_set_property *props, - size_t len) -{ - int err_count = 0; - - for (int i = 0; i < len; i++) { - int ret = sbs_gauge_set_prop(dev, props + i); - - err_count += ret ? 1 : 0; - } - - err_count = (err_count == len) ? -1 : err_count; - - return err_count; -} - /** * @brief initialize the fuel gauge * @@ -326,8 +291,8 @@ static int sbs_gauge_init(const struct device *dev) } static const struct fuel_gauge_driver_api sbs_gauge_driver_api = { - .get_property = &sbs_gauge_get_props, - .set_property = &sbs_gauge_set_props, + .get_property = &sbs_gauge_get_prop, + .set_property = &sbs_gauge_set_prop, .get_buffer_property = &sbs_gauge_get_buffer_prop, .battery_cutoff = &sbs_gauge_do_battery_cutoff, }; diff --git a/drivers/gnss/CMakeLists.txt b/drivers/gnss/CMakeLists.txt new file mode 100644 index 00000000000..6c24df4903e --- /dev/null +++ b/drivers/gnss/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() +zephyr_library_sources(gnss_publish.c) +zephyr_library_sources_ifdef(CONFIG_GNSS_DUMP gnss_dump.c) +zephyr_library_sources_ifdef(CONFIG_GNSS_PARSE gnss_parse.c) +zephyr_library_sources_ifdef(CONFIG_GNSS_NMEA0183 gnss_nmea0183.c) +zephyr_library_sources_ifdef(CONFIG_GNSS_NMEA0183_MATCH gnss_nmea0183_match.c) +zephyr_library_sources_ifdef(CONFIG_GNSS_QUECTEL_LCX6G gnss_quectel_lcx6g.c) diff --git a/drivers/gnss/Kconfig b/drivers/gnss/Kconfig new file mode 100644 index 00000000000..5bdc0f530d8 --- /dev/null +++ b/drivers/gnss/Kconfig @@ -0,0 +1,69 @@ +# Copyright (c) 2023 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +menuconfig GNSS + bool "GNSS drivers" + select EXPERIMENTAL + help + Enable GNSS drivers and configuration. + +if GNSS + +config GNSS_SATELLITES + bool "GNSS satellites support" + help + Enable GNSS sattelites callback. + +config GNSS_DUMP + bool "GNSS dump support" + depends on LOG + help + Enable GNSS dump library + +config GNSS_DUMP_TO_LOG + bool "Dump GNSS events to log" + select GNSS_DUMP + help + Enable GNSS dump to log. + +if GNSS_DUMP_TO_LOG + +config GNSS_DUMP_TO_LOG_BUF_SIZE + int "GNSS log dump buffer size" + default 128 + help + Size of GNSS log dump buffer + +endif + +config GNSS_PARSE + bool "GNSS parsing utilities" + help + Enable GNSS parsing utilities. + +config GNSS_NMEA0183 + bool "NMEA0183 parsing utilities" + select GNSS_PARSE + help + Enable NMEA0183 parsing utilities. + +config GNSS_NMEA0183_MATCH + bool "GNSS NMEA0183 match utilities" + select GNSS_NMEA0183 + help + Enable NMEA0183 match utilities. + +config GNSS_INIT_PRIORITY + int "GNSS driver initialization priority" + default 80 + range 0 99 + help + Driver initialization priority for GNSS drivers. + +module = GNSS +module-str = gnss +source "subsys/logging/Kconfig.template.log_config" + +rsource "Kconfig.quectel_lcx6g" + +endif diff --git a/drivers/gnss/Kconfig.quectel_lcx6g b/drivers/gnss/Kconfig.quectel_lcx6g new file mode 100644 index 00000000000..6736015aed7 --- /dev/null +++ b/drivers/gnss/Kconfig.quectel_lcx6g @@ -0,0 +1,17 @@ +# Copyright (c) 2023 Trackunit Corporation +# Copyright (c) 2023 Bjarki Arge Andreasen +# SPDX-License-Identifier: Apache-2.0 + +config GNSS_QUECTEL_LCX6G + bool "Quectel LCX6G GNSS modem driver" + default y + depends on GNSS + depends on DT_HAS_QUECTEL_LC26G_ENABLED || DT_HAS_QUECTEL_LC76G_ENABLED || DT_HAS_QUECTEL_LC86G_ENABLED + select MODEM_MODULES + select MODEM_BACKEND_UART + select MODEM_CHAT + select GNSS_PARSE + select GNSS_NMEA0183 + select GNSS_NMEA0183_MATCH + help + Enable quectel LCX6G series GNSS modem driver. diff --git a/drivers/gnss/gnss_dump.c b/drivers/gnss/gnss_dump.c new file mode 100644 index 00000000000..1946d65ea2e --- /dev/null +++ b/drivers/gnss/gnss_dump.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2023 Bjarki Arge Andreasen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "gnss_dump.h" +#include +#include + +#include + +#if CONFIG_GNSS_DUMP_TO_LOG +static char dump_buf[CONFIG_GNSS_DUMP_TO_LOG_BUF_SIZE]; +#endif /* CONFIG_GNSS_DUMP_TO_LOG */ + +static const char *gnss_fix_status_to_str(enum gnss_fix_status fix_status) +{ + switch (fix_status) { + case GNSS_FIX_STATUS_NO_FIX: + return "NO_FIX"; + case GNSS_FIX_STATUS_GNSS_FIX: + return "GNSS_FIX"; + case GNSS_FIX_STATUS_DGNSS_FIX: + return "DGNSS_FIX"; + case GNSS_FIX_STATUS_ESTIMATED_FIX: + return "ESTIMATED_FIX"; + } + + return "unknown"; +} + +static const char *gnss_fix_quality_to_str(enum gnss_fix_quality fix_quality) +{ + switch (fix_quality) { + case GNSS_FIX_QUALITY_INVALID: + return "INVALID"; + case GNSS_FIX_QUALITY_GNSS_SPS: + return "GNSS_SPS"; + case GNSS_FIX_QUALITY_DGNSS: + return "DGNSS"; + case GNSS_FIX_QUALITY_GNSS_PPS: + return "GNSS_PPS"; + case GNSS_FIX_QUALITY_RTK: + return "RTK"; + case GNSS_FIX_QUALITY_FLOAT_RTK: + return "FLOAT_RTK"; + case GNSS_FIX_QUALITY_ESTIMATED: + return "ESTIMATED"; + } + + return "unknown"; +} + +#if CONFIG_GNSS_SATELLITES +static const char *gnss_system_to_str(enum gnss_system system) +{ + switch (system) { + case GNSS_SYSTEM_GPS: + return "GPS"; + case GNSS_SYSTEM_GLONASS: + return "GLONASS"; + case GNSS_SYSTEM_GALILEO: + return "GALILEO"; + case GNSS_SYSTEM_BEIDOU: + return "BEIDOU"; + case GNSS_SYSTEM_QZSS: + return "QZSS"; + case GNSS_SYSTEM_IRNSS: + return "IRNSS"; + case GNSS_SYSTEM_SBAS: + return "SBAS"; + case GNSS_SYSTEM_IMES: + return "IMES"; + } + + return "unknown"; +} +#endif + +int gnss_dump_info(char *str, uint16_t strsize, const struct gnss_info *info) +{ + int ret; + const char *fmt = "gnss_info: {satellites_cnt: %u, hdop: %u.%u, fix_status: %s, " + "fix_quality: %s}"; + + ret = snprintk(str, strsize, fmt, info->satellites_cnt, info->hdop / 1000, + info->hdop % 1000, gnss_fix_status_to_str(info->fix_status), + gnss_fix_quality_to_str(info->fix_quality)); + + return (strsize < ret) ? -ENOMEM : 0; +} + +int gnss_dump_nav_data(char *str, uint16_t strsize, const struct navigation_data *nav_data) +{ + int ret; + int32_t altitude_int; + int32_t altitude_fraction; + const char *fmt = "navigation_data: {latitude: %lli.%lli, longitude : %lli.%lli, " + "bearing %u.%u, speed %u.%u, altitude: %i.%i}"; + + altitude_int = nav_data->altitude / 1000; + altitude_fraction = nav_data->altitude % 1000; + altitude_fraction = (altitude_fraction < 0) ? -altitude_fraction : altitude_fraction; + + ret = snprintk(str, strsize, fmt, nav_data->latitude / 1000000000, + nav_data->latitude % 1000000000, nav_data->longitude / 1000000000, + nav_data->longitude % 1000000000, nav_data->bearing / 1000, + nav_data->bearing % 1000, nav_data->speed / 1000, nav_data->speed % 1000, + altitude_int, altitude_fraction); + + return (strsize < ret) ? -ENOMEM : 0; +} + +int gnss_dump_time(char *str, uint16_t strsize, const struct gnss_time *utc) +{ + int ret; + const char *fmt = "gnss_time: {hour: %u, minute: %u, millisecond %u, month_day %u, " + "month: %u, century_year: %u}"; + + ret = snprintk(str, strsize, fmt, utc->hour, utc->minute, utc->millisecond, + utc->month_day, utc->month, utc->century_year); + + return (strsize < ret) ? -ENOMEM : 0; +} + +#if CONFIG_GNSS_SATELLITES +int gnss_dump_satellite(char *str, uint16_t strsize, const struct gnss_satellite *satellite) +{ + int ret; + const char *fmt = "gnss_satellite: {prn: %u, snr: %u, elevation %u, azimuth %u, " + "system: %s, is_tracked: %u}"; + + ret = snprintk(str, strsize, fmt, satellite->prn, satellite->snr, satellite->elevation, + satellite->azimuth, gnss_system_to_str(satellite->system), + satellite->is_tracked); + + return (strsize < ret) ? -ENOMEM : 0; +} +#endif + +#if CONFIG_GNSS_DUMP_TO_LOG +static void gnss_dump_data_to_log(const struct device *dev, const struct gnss_data *data) +{ + if (gnss_dump_info(dump_buf, sizeof(dump_buf), &data->info) < 0) { + return; + } + + LOG_PRINTK("%s: %s\r\n", dev->name, dump_buf); + + if (gnss_dump_nav_data(dump_buf, sizeof(dump_buf), &data->nav_data) < 0) { + return; + } + + LOG_PRINTK("%s: %s\r\n", dev->name, dump_buf); + + if (gnss_dump_time(dump_buf, sizeof(dump_buf), &data->utc) < 0) { + return; + } + + LOG_PRINTK("%s: %s\r\n", dev->name, dump_buf); +} + +GNSS_DATA_CALLBACK_DEFINE(NULL, gnss_dump_data_to_log); +#endif + +#if defined(CONFIG_GNSS_DUMP_TO_LOG) && defined(CONFIG_GNSS_SATELLITES) +static void gnss_dump_satellites_to_log(const struct device *dev, + const struct gnss_satellite *satellites, uint16_t size) +{ + for (uint16_t i = 0; i < size; i++) { + if (gnss_dump_satellite(dump_buf, sizeof(dump_buf), &satellites[i]) < 0) { + return; + } + + LOG_PRINTK("%s: %s\r\n", dev->name, dump_buf); + } +} + +GNSS_SATELLITES_CALLBACK_DEFINE(NULL, gnss_dump_satellites_to_log); +#endif diff --git a/drivers/gnss/gnss_dump.h b/drivers/gnss/gnss_dump.h new file mode 100644 index 00000000000..ba02b085cd2 --- /dev/null +++ b/drivers/gnss/gnss_dump.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 Bjarki Arge Andreasen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_GNSS_GNSS_DUMP_H_ +#define ZEPHYR_DRIVERS_GNSS_GNSS_DUMP_H_ + +#include + +/** + * @brief Dump struct gnss_info as string + * + * @param str Destination for dumped GNSS info + * @param strsize Size of str + * @param info GNSS info to dump + * + * @retval 0 if GNSS info successfully dumped + * @retval -ENOMEM if strsize too small + */ +int gnss_dump_info(char *str, uint16_t strsize, const struct gnss_info *info); + +/** + * @brief Dump struct navigation_data as string + * + * @param str Destination for dumped navigation data + * @param strsize Size of str + * @param nav_data Navigation data to dump + * + * @retval 0 if navigation data successfully dumped + * @retval -ENOMEM if strsize too small + */ +int gnss_dump_nav_data(char *str, uint16_t strsize, const struct navigation_data *nav_data); + +/** + * @brief Dump struct gnss_time as string + * + * @param str Destination for dumped GNSS time + * @param strsize Size of str + * @param utc GNSS time to dump + * + * @retval 0 if GNSS time successfully dumped + * @retval -ENOMEM if strsize too small + */ +int gnss_dump_time(char *str, uint16_t strsize, const struct gnss_time *utc); + +/** + * @brief Dump struct gnss_satellite as string + * + * @param str Destination for dumped GNSS satellite + * @param strsize Size of str + * @param utc GNSS satellite to dump + * + * @retval 0 if GNSS satellite successfully dumped + * @retval -ENOMEM if strsize too small + */ +int gnss_dump_satellite(char *str, uint16_t strsize, const struct gnss_satellite *satellite); + +#endif /* ZEPHYR_DRIVERS_GNSS_GNSS_DUMP_H_ */ diff --git a/drivers/gnss/gnss_nmea0183.c b/drivers/gnss/gnss_nmea0183.c new file mode 100644 index 00000000000..f69dd347a9f --- /dev/null +++ b/drivers/gnss/gnss_nmea0183.c @@ -0,0 +1,678 @@ +/* + * Copyright (c) 2023 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include + +#include "gnss_nmea0183.h" +#include "gnss_parse.h" + +#define GNSS_NMEA0183_PICO_DEGREES_IN_DEGREE (1000000000000ULL) +#define GNSS_NMEA0183_PICO_DEGREES_IN_MINUTE (GNSS_NMEA0183_PICO_DEGREES_IN_DEGREE / 60ULL) +#define GNSS_NMEA0183_PICO_DEGREES_IN_NANO_DEGREE (1000ULL) +#define GNSS_NMEA0183_NANO_KNOTS_IN_MMS (1943861LL) + +#define GNSS_NMEA0183_MESSAGE_SIZE_MIN (6) +#define GNSS_NMEA0183_MESSAGE_CHECKSUM_SIZE (3) + +#define GNSS_NMEA0183_GSV_HDR_ARG_CNT (4) +#define GNSS_NMEA0183_GSV_SV_ARG_CNT (4) + +#define GNSS_NMEA0183_GSV_PRN_GPS_RANGE (32) +#define GNSS_NMEA0183_GSV_PRN_SBAS_OFFSET (87) +#define GNSS_NMEA0183_GSV_PRN_GLONASS_OFFSET (64) +#define GNSS_NMEA0183_GSV_PRN_BEIDOU_OFFSET (100) + +struct gsv_header_args { + const char *message_id; + const char *number_of_messages; + const char *message_number; + const char *numver_of_svs; +}; + +struct gsv_sv_args { + const char *prn; + const char *elevation; + const char *azimuth; + const char *snr; +}; + +static int gnss_system_from_gsv_header_args(const struct gsv_header_args *args, + enum gnss_system *sv_system) +{ + switch (args->message_id[2]) { + case 'A': + *sv_system = GNSS_SYSTEM_GALILEO; + break; + case 'B': + *sv_system = GNSS_SYSTEM_BEIDOU; + break; + case 'P': + *sv_system = GNSS_SYSTEM_GPS; + break; + case 'L': + *sv_system = GNSS_SYSTEM_GLONASS; + break; + case 'Q': + *sv_system = GNSS_SYSTEM_QZSS; + break; + default: + return -EINVAL; + } + + return 0; +} + +static void align_satellite_with_gnss_system(enum gnss_system sv_system, + struct gnss_satellite *satellite) +{ + switch (sv_system) { + case GNSS_SYSTEM_GPS: + if (satellite->prn > GNSS_NMEA0183_GSV_PRN_GPS_RANGE) { + satellite->system = GNSS_SYSTEM_SBAS; + satellite->prn += GNSS_NMEA0183_GSV_PRN_SBAS_OFFSET; + break; + } + + satellite->system = GNSS_SYSTEM_GPS; + break; + + case GNSS_SYSTEM_GLONASS: + satellite->system = GNSS_SYSTEM_GLONASS; + satellite->prn -= GNSS_NMEA0183_GSV_PRN_GLONASS_OFFSET; + break; + + case GNSS_SYSTEM_GALILEO: + satellite->system = GNSS_SYSTEM_GALILEO; + break; + + case GNSS_SYSTEM_BEIDOU: + satellite->system = GNSS_SYSTEM_BEIDOU; + satellite->prn -= GNSS_NMEA0183_GSV_PRN_BEIDOU_OFFSET; + break; + + case GNSS_SYSTEM_QZSS: + satellite->system = GNSS_SYSTEM_QZSS; + break; + + case GNSS_SYSTEM_IRNSS: + case GNSS_SYSTEM_IMES: + case GNSS_SYSTEM_SBAS: + break; + } +} + +uint8_t gnss_nmea0183_checksum(const char *str) +{ + uint8_t checksum = 0; + size_t end; + + __ASSERT(str != NULL, "str argument must be provided"); + + end = strlen(str); + for (size_t i = 0; i < end; i++) { + checksum = checksum ^ str[i]; + } + + return checksum; +} + +int gnss_nmea0183_snprintk(char *str, size_t size, const char *fmt, ...) +{ + va_list ap; + uint8_t checksum; + int pos; + int len; + + __ASSERT(str != NULL, "str argument must be provided"); + __ASSERT(fmt != NULL, "fmt argument must be provided"); + + if (size < GNSS_NMEA0183_MESSAGE_SIZE_MIN) { + return -ENOMEM; + } + + str[0] = '$'; + + va_start(ap, fmt); + pos = vsnprintk(&str[1], size - 1, fmt, ap) + 1; + va_end(ap); + + if (pos < 0) { + return -EINVAL; + } + + len = pos + GNSS_NMEA0183_MESSAGE_CHECKSUM_SIZE; + + if ((size - 1) < len) { + return -ENOMEM; + } + + checksum = gnss_nmea0183_checksum(&str[1]); + pos = snprintk(&str[pos], size - pos, "*%02X", checksum); + if (pos != 3) { + return -EINVAL; + } + + str[len] = '\0'; + return len; +} + +int gnss_nmea0183_ddmm_mmmm_to_ndeg(const char *ddmm_mmmm, int64_t *ndeg) +{ + uint64_t pico_degrees = 0; + int8_t decimal = -1; + int8_t pos = 0; + uint64_t increment; + + __ASSERT(ddmm_mmmm != NULL, "ddmm_mmmm argument must be provided"); + __ASSERT(ndeg != NULL, "ndeg argument must be provided"); + + /* Find decimal */ + while (ddmm_mmmm[pos] != '\0') { + /* Verify if char is decimal */ + if (ddmm_mmmm[pos] == '.') { + decimal = pos; + break; + } + + /* Advance position */ + pos++; + } + + /* Verify decimal was found and placed correctly */ + if (decimal < 1) { + return -EINVAL; + } + + /* Validate potential degree fraction is within bounds */ + if (decimal > 1 && ddmm_mmmm[decimal - 2] > '5') { + return -EINVAL; + } + + /* Convert minute fraction to pico degrees and add it to pico_degrees */ + pos = decimal + 1; + increment = (GNSS_NMEA0183_PICO_DEGREES_IN_MINUTE / 10); + while (ddmm_mmmm[pos] != '\0') { + /* Verify char is decimal */ + if (ddmm_mmmm[pos] < '0' || ddmm_mmmm[pos] > '9') { + return -EINVAL; + } + + /* Add increment to pico_degrees */ + pico_degrees += (ddmm_mmmm[pos] - '0') * increment; + + /* Update unit */ + increment /= 10; + + /* Increment position */ + pos++; + } + + /* Convert minutes and degrees to pico_degrees */ + pos = decimal - 1; + increment = GNSS_NMEA0183_PICO_DEGREES_IN_MINUTE; + while (pos >= 0) { + /* Check if digit switched from minutes to degrees */ + if ((decimal - pos) == 3) { + /* Reset increment to degrees */ + increment = GNSS_NMEA0183_PICO_DEGREES_IN_DEGREE; + } + + /* Verify char is decimal */ + if (ddmm_mmmm[pos] < '0' || ddmm_mmmm[pos] > '9') { + return -EINVAL; + } + + /* Add increment to pico_degrees */ + pico_degrees += (ddmm_mmmm[pos] - '0') * increment; + + /* Update unit */ + increment *= 10; + + /* Decrement position */ + pos--; + } + + /* Convert to nano degrees */ + *ndeg = (int64_t)(pico_degrees / GNSS_NMEA0183_PICO_DEGREES_IN_NANO_DEGREE); + return 0; +} + +bool gnss_nmea0183_validate_message(char **argv, uint16_t argc) +{ + int32_t tmp = 0; + uint8_t checksum = 0; + size_t len; + + __ASSERT(argv != NULL, "argv argument must be provided"); + + /* Message must contain message id and checksum */ + if (argc < 2) { + return false; + } + + /* First argument should start with '$' which is not covered by checksum */ + if ((argc < 1) || (argv[0][0] != '$')) { + return false; + } + + len = strlen(argv[0]); + for (uint16_t u = 1; u < len; u++) { + checksum ^= argv[0][u]; + } + checksum ^= ','; + + /* Cover all except last argument which contains the checksum*/ + for (uint16_t i = 1; i < (argc - 1); i++) { + len = strlen(argv[i]); + for (uint16_t u = 0; u < len; u++) { + checksum ^= argv[i][u]; + } + checksum ^= ','; + } + + if ((gnss_parse_atoi(argv[argc - 1], 16, &tmp) < 0) || + (tmp > UINT8_MAX) || + (tmp < 0)) { + return false; + } + + return checksum == (uint8_t)tmp; +} + +int gnss_nmea0183_knots_to_mms(const char *str, int64_t *mms) +{ + int ret; + + __ASSERT(str != NULL, "str argument must be provided"); + __ASSERT(mms != NULL, "mms argument must be provided"); + + ret = gnss_parse_dec_to_nano(str, mms); + if (ret < 0) { + return ret; + } + + *mms = (*mms) / GNSS_NMEA0183_NANO_KNOTS_IN_MMS; + return 0; +} + +int gnss_nmea0183_parse_hhmmss(const char *hhmmss, struct gnss_time *utc) +{ + int64_t i64; + int32_t i32; + char part[3] = {0}; + + __ASSERT(hhmmss != NULL, "hhmmss argument must be provided"); + __ASSERT(utc != NULL, "utc argument must be provided"); + + if (strlen(hhmmss) < 6) { + return -EINVAL; + } + + memcpy(part, hhmmss, 2); + if ((gnss_parse_atoi(part, 10, &i32) < 0) || + (i32 < 0) || + (i32 > 23)) { + return -EINVAL; + } + + utc->hour = (uint8_t)i32; + + memcpy(part, &hhmmss[2], 2); + if ((gnss_parse_atoi(part, 10, &i32) < 0) || + (i32 < 0) || + (i32 > 59)) { + return -EINVAL; + } + + utc->minute = (uint8_t)i32; + + if ((gnss_parse_dec_to_milli(&hhmmss[4], &i64) < 0) || + (i64 < 0) || + (i64 > 59999)) { + return -EINVAL; + } + + utc->millisecond = (uint16_t)i64; + return 0; +} + +int gnss_nmea0183_parse_ddmmyy(const char *ddmmyy, struct gnss_time *utc) +{ + int32_t i32; + char part[3] = {0}; + + __ASSERT(ddmmyy != NULL, "ddmmyy argument must be provided"); + __ASSERT(utc != NULL, "utc argument must be provided"); + + if (strlen(ddmmyy) != 6) { + return -EINVAL; + } + + memcpy(part, ddmmyy, 2); + if ((gnss_parse_atoi(part, 10, &i32) < 0) || + (i32 < 1) || + (i32 > 31)) { + return -EINVAL; + } + + utc->month_day = (uint8_t)i32; + + memcpy(part, &ddmmyy[2], 2); + if ((gnss_parse_atoi(part, 10, &i32) < 0) || + (i32 < 1) || + (i32 > 12)) { + return -EINVAL; + } + + utc->month = (uint8_t)i32; + + memcpy(part, &ddmmyy[4], 2); + if ((gnss_parse_atoi(part, 10, &i32) < 0) || + (i32 < 0) || + (i32 > 99)) { + return -EINVAL; + } + + utc->century_year = (uint8_t)i32; + return 0; +} + +int gnss_nmea0183_parse_rmc(const char **argv, uint16_t argc, struct gnss_data *data) +{ + int64_t tmp; + + __ASSERT(argv != NULL, "argv argument must be provided"); + __ASSERT(data != NULL, "data argument must be provided"); + + if (argc < 10) { + return -EINVAL; + } + + /* Validate GNSS has fix */ + if (argv[2][0] == 'V') { + return 0; + } + + if (argv[2][0] != 'A') { + return -EINVAL; + } + + /* Parse UTC time */ + if ((gnss_nmea0183_parse_hhmmss(argv[1], &data->utc) < 0)) { + return -EINVAL; + } + + /* Validate cardinal directions */ + if (((argv[4][0] != 'N') && (argv[4][0] != 'S')) || + ((argv[6][0] != 'E') && (argv[6][0] != 'W'))) { + return -EINVAL; + } + + /* Parse coordinates */ + if ((gnss_nmea0183_ddmm_mmmm_to_ndeg(argv[3], &data->nav_data.latitude) < 0) || + (gnss_nmea0183_ddmm_mmmm_to_ndeg(argv[5], &data->nav_data.longitude) < 0)) { + return -EINVAL; + } + + /* Align sign of coordinates with cardinal directions */ + data->nav_data.latitude = argv[4][0] == 'N' + ? data->nav_data.latitude + : -data->nav_data.latitude; + + data->nav_data.longitude = argv[6][0] == 'E' + ? data->nav_data.longitude + : -data->nav_data.longitude; + + /* Parse speed */ + if ((gnss_nmea0183_knots_to_mms(argv[7], &tmp) < 0) || + (tmp > UINT32_MAX)) { + return -EINVAL; + } + + data->nav_data.speed = (uint32_t)tmp; + + /* Parse bearing */ + if ((gnss_parse_dec_to_milli(argv[8], &tmp) < 0) || + (tmp > 359999) || + (tmp < 0)) { + return -EINVAL; + } + + data->nav_data.bearing = (uint32_t)tmp; + + /* Parse UTC date */ + if ((gnss_nmea0183_parse_ddmmyy(argv[9], &data->utc) < 0)) { + return -EINVAL; + } + + return 0; +} + +static int parse_gga_fix_quality(const char *str, enum gnss_fix_quality *fix_quality) +{ + __ASSERT(str != NULL, "str argument must be provided"); + __ASSERT(fix_quality != NULL, "fix_quality argument must be provided"); + + if ((str[1] != ((char)'\0')) || (str[0] < ((char)'0')) || (((char)'6') < str[0])) { + return -EINVAL; + } + + (*fix_quality) = (enum gnss_fix_quality)(str[0] - ((char)'0')); + return 0; +} + +static enum gnss_fix_status fix_status_from_fix_quality(enum gnss_fix_quality fix_quality) +{ + enum gnss_fix_status fix_status = GNSS_FIX_STATUS_NO_FIX; + + switch (fix_quality) { + case GNSS_FIX_QUALITY_GNSS_SPS: + case GNSS_FIX_QUALITY_GNSS_PPS: + fix_status = GNSS_FIX_STATUS_GNSS_FIX; + break; + + case GNSS_FIX_QUALITY_DGNSS: + case GNSS_FIX_QUALITY_RTK: + case GNSS_FIX_QUALITY_FLOAT_RTK: + fix_status = GNSS_FIX_STATUS_DGNSS_FIX; + break; + + case GNSS_FIX_QUALITY_ESTIMATED: + fix_status = GNSS_FIX_STATUS_ESTIMATED_FIX; + break; + + default: + break; + } + + return fix_status; +} + +int gnss_nmea0183_parse_gga(const char **argv, uint16_t argc, struct gnss_data *data) +{ + int32_t tmp32; + int64_t tmp64; + + __ASSERT(argv != NULL, "argv argument must be provided"); + __ASSERT(data != NULL, "data argument must be provided"); + + if (argc < 12) { + return -EINVAL; + } + + /* Parse fix quality and status */ + if (parse_gga_fix_quality(argv[6], &data->info.fix_quality) < 0) { + return -EINVAL; + } + + data->info.fix_status = fix_status_from_fix_quality(data->info.fix_quality); + + /* Validate GNSS has fix */ + if (data->info.fix_status == GNSS_FIX_STATUS_NO_FIX) { + return 0; + } + + /* Parse number of satellites */ + if ((gnss_parse_atoi(argv[7], 10, &tmp32) < 0) || + (tmp32 > UINT16_MAX) || + (tmp32 < 0)) { + return -EINVAL; + } + + data->info.satellites_cnt = (uint16_t)tmp32; + + /* Parse HDOP */ + if ((gnss_parse_dec_to_milli(argv[8], &tmp64) < 0) || + (tmp64 > UINT16_MAX) || + (tmp64 < 0)) { + return -EINVAL; + } + + data->info.hdop = (uint16_t)tmp64; + + /* Parse altitude */ + if ((gnss_parse_dec_to_milli(argv[11], &tmp64) < 0) || + (tmp64 > INT32_MAX) || + (tmp64 < INT32_MIN)) { + return -EINVAL; + } + + data->nav_data.altitude = (int32_t)tmp64; + return 0; +} + +static int parse_gsv_svs(struct gnss_satellite *satellites, const struct gsv_sv_args *svs, + uint16_t svs_size) +{ + int32_t i32; + + for (uint16_t i = 0; i < svs_size; i++) { + /* Parse PRN */ + if ((gnss_parse_atoi(svs[i].prn, 10, &i32) < 0) || + (i32 < 0) || (i32 > UINT16_MAX)) { + return -EINVAL; + } + + satellites[i].prn = (uint16_t)i32; + + /* Parse elevation */ + if ((gnss_parse_atoi(svs[i].elevation, 10, &i32) < 0) || + (i32 < 0) || (i32 > 90)) { + return -EINVAL; + } + + satellites[i].elevation = (uint8_t)i32; + + /* Parse azimuth */ + if ((gnss_parse_atoi(svs[i].azimuth, 10, &i32) < 0) || + (i32 < 0) || (i32 > 359)) { + return -EINVAL; + } + + satellites[i].azimuth = (uint16_t)i32; + + /* Parse SNR */ + if (strlen(svs[i].snr) == 0) { + satellites[i].snr = 0; + satellites[i].is_tracked = false; + continue; + } + + if ((gnss_parse_atoi(svs[i].snr, 10, &i32) < 0) || + (i32 < 0) || (i32 > 99)) { + return -EINVAL; + } + + satellites[i].snr = (uint16_t)i32; + satellites[i].is_tracked = true; + } + + return 0; +} + +int gnss_nmea0183_parse_gsv_header(const char **argv, uint16_t argc, + struct gnss_nmea0183_gsv_header *header) +{ + const struct gsv_header_args *args = (const struct gsv_header_args *)argv; + int i32; + + __ASSERT(argv != NULL, "argv argument must be provided"); + __ASSERT(header != NULL, "header argument must be provided"); + + if (argc < 4) { + return -EINVAL; + } + + /* Parse GNSS sv_system */ + if (gnss_system_from_gsv_header_args(args, &header->system) < 0) { + return -EINVAL; + } + + /* Parse number of messages */ + if ((gnss_parse_atoi(args->number_of_messages, 10, &i32) < 0) || + (i32 < 0) || (i32 > UINT16_MAX)) { + return -EINVAL; + } + + header->number_of_messages = (uint16_t)i32; + + /* Parse message number */ + if ((gnss_parse_atoi(args->message_number, 10, &i32) < 0) || + (i32 < 0) || (i32 > UINT16_MAX)) { + return -EINVAL; + } + + header->message_number = (uint16_t)i32; + + /* Parse message number */ + if ((gnss_parse_atoi(args->numver_of_svs, 10, &i32) < 0) || + (i32 < 0) || (i32 > UINT16_MAX)) { + return -EINVAL; + } + + header->number_of_svs = (uint16_t)i32; + return 0; +} + +int gnss_nmea0183_parse_gsv_svs(const char **argv, uint16_t argc, + struct gnss_satellite *satellites, uint16_t size) +{ + const struct gsv_header_args *header_args = (const struct gsv_header_args *)argv; + const struct gsv_sv_args *sv_args = (const struct gsv_sv_args *)(argv + 4); + uint16_t sv_args_size; + enum gnss_system sv_system; + + __ASSERT(argv != NULL, "argv argument must be provided"); + __ASSERT(satellites != NULL, "satellites argument must be provided"); + + if (argc < 9) { + return 0; + } + + sv_args_size = (argc - GNSS_NMEA0183_GSV_HDR_ARG_CNT) / GNSS_NMEA0183_GSV_SV_ARG_CNT; + + if (size < sv_args_size) { + return -ENOMEM; + } + + if (parse_gsv_svs(satellites, sv_args, sv_args_size) < 0) { + return -EINVAL; + } + + if (gnss_system_from_gsv_header_args(header_args, &sv_system) < 0) { + return -EINVAL; + } + + for (uint16_t i = 0; i < sv_args_size; i++) { + align_satellite_with_gnss_system(sv_system, &satellites[i]); + } + + return (int)sv_args_size; +} diff --git a/drivers/gnss/gnss_nmea0183.h b/drivers/gnss/gnss_nmea0183.h new file mode 100644 index 00000000000..6a3fa177f44 --- /dev/null +++ b/drivers/gnss/gnss_nmea0183.h @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2023 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_GNSS_GNSS_NMEA0183_H_ +#define ZEPHYR_DRIVERS_GNSS_GNSS_NMEA0183_H_ + +#include + +/** + * @brief Compute NMEA0183 checksum + * + * @example "PAIR002" -> 0x38 + * + * @param str String from which checksum is computed + * + * @retval checksum + */ +uint8_t gnss_nmea0183_checksum(const char *str); + +/** + * @brief Encapsulate str in NMEA0183 message format + * + * @example "PAIR%03u", 2 -> "$PAIR002*38" + * + * @param str Destination for encapsulated string + * @param size Size of destination for encapsulated string + * @param fmt Format of string to encapsulate + * @param ... Arguments + * + * @retval checksum + */ +int gnss_nmea0183_snprintk(char *str, size_t size, const char *fmt, ...); + +/** + * @brief Computes and validates checksum + * + * @param argv Array of arguments split by ',' including message id and checksum + * @param argc Number of arguments in argv + * + * @retval true if message is intact + * @retval false if message is corrupted + */ +bool gnss_nmea0183_validate_message(char **argv, uint16_t argc); + +/** + * @brief Parse a ddmm.mmmm formatted angle to nano degrees + * + * @example "5610.9928" -> 56183214000 + * + * @param ddmm_mmmm String representation of angle in ddmm.mmmm format + * @param ndeg Result in nano degrees + * + * @retval -EINVAL if ddmm_mmmm argument is invalid + * @retval 0 if parsed successfully + */ +int gnss_nmea0183_ddmm_mmmm_to_ndeg(const char *ddmm_mmmm, int64_t *ndeg); + +/** + * @brief Parse knots to millimeters pr second + * + * @example "15.231" -> 7835 + * + * @param str String representation of speed in knots + * @param mms Destination for speed in millimeters pr second + * + * @retval -EINVAL if str could not be parsed or if speed is negative + * @retval 0 if parsed successfully + */ +int gnss_nmea0183_knots_to_mms(const char *str, int64_t *mms); + +/** + * @brief Parse hhmmss.sss to struct gnss_time + * + * @example "133243.012" -> { .hour = 13, .minute = 32, .ms = 43012 } + * @example "133243" -> { .hour = 13, .minute = 32, .ms = 43000 } + * + * @param str String representation of hours, minutes, seconds and subseconds + * @param utc Destination for parsed time + * + * @retval -EINVAL if str could not be parsed + * @retval 0 if parsed successfully + */ +int gnss_nmea0183_parse_hhmmss(const char *hhmmss, struct gnss_time *utc); + +/** + * @brief Parse ddmmyy to unsigned integers + * + * @example "041122" -> { .mday = 4, .month = 11, .year = 22 } + * + * @param str String representation of speed in knots + * @param utc Destination for parsed time + * + * @retval -EINVAL if str could not be parsed + * @retval 0 if parsed successfully + */ +int gnss_nmea0183_parse_ddmmyy(const char *ddmmyy, struct gnss_time *utc); + +/** + * @brief Parses NMEA0183 RMC message + * + * @details Parses the time, date, latitude, longitude, speed, and bearing + * from the NMEA0183 RMC message provided as an array of strings split by ',' + * + * @param argv Array of arguments split by ',' including message id and checksum + * @param argc Number of arguments in argv' + * @param data Destination for data parsed from NMEA0183 RMC message + * + * @retval 0 if successful + * @retval -EINVAL if input is invalid + */ +int gnss_nmea0183_parse_rmc(const char **argv, uint16_t argc, struct gnss_data *data); + +/** + * @brief Parses NMEA0183 GGA message + * + * @details Parses the GNSS fix quality and status, number of satellites used for + * fix, HDOP, and altitude (geoid separation) from the NMEA0183 GGA message provided + * as an array of strings split by ',' + * + * @param argv Array of arguments split by ',' including message id and checksum + * @param argc Number of arguments in argv' + * @param data Destination for data parsed from NMEA0183 GGA message + * + * @retval 0 if successful + * @retval -EINVAL if input is invalid + */ +int gnss_nmea0183_parse_gga(const char **argv, uint16_t argc, struct gnss_data *data); + +/** GSV header structure */ +struct gnss_nmea0183_gsv_header { + /** Indicates the system of the space-vehicles contained in the message */ + enum gnss_system system; + /** Number of GSV messages in total */ + uint16_t number_of_messages; + /** Number of this GSV message */ + uint16_t message_number; + /** Number of visible space-vehicles */ + uint16_t number_of_svs; +}; + +/** + * @brief Parses header of NMEA0183 GSV message + * + * @details The GSV messages are part of a list of messages sent in ascending + * order, split by GNSS system. + * + * @param argv Array of arguments split by ',' including message id and checksum + * @param argc Number of arguments in argv + * @param header Destination for parsed NMEA0183 GGA message header + * + * @retval 0 if successful + * @retval -EINVAL if input is invalid + */ +int gnss_nmea0183_parse_gsv_header(const char **argv, uint16_t argc, + struct gnss_nmea0183_gsv_header *header); + +/** + * @brief Parses space-vehicles in NMEA0183 GSV message + * + * @details The NMEA0183 GSV message contains up to 4 space-vehicles which follow + * the header. + * + * @param argv Array of arguments split by ',' including message id and checksum + * @param argc Number of arguments in argv + * @param satellites Destination for parsed satellites from NMEA0183 GGA message + * @param size Size of destination for parsed satellites from NMEA0183 GGA message + * + * @retval Number of parsed space-vehicles stored at destination if successful + * @retval -ENOMEM if all space-vehicles in message could not be stored at destination + * @retval -EINVAL if input is invalid + */ +int gnss_nmea0183_parse_gsv_svs(const char **argv, uint16_t argc, + struct gnss_satellite *satellites, uint16_t size); + +#endif /* ZEPHYR_DRIVERS_GNSS_GNSS_NMEA0183_H_ */ diff --git a/drivers/gnss/gnss_nmea0183_match.c b/drivers/gnss/gnss_nmea0183_match.c new file mode 100644 index 00000000000..3fe3b159fdb --- /dev/null +++ b/drivers/gnss/gnss_nmea0183_match.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2023 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +#include "gnss_nmea0183.h" +#include "gnss_nmea0183_match.h" +#include "gnss_publish.h" + +static bool gnss_nmea0183_match_timed_out(struct gnss_nmea0183_match_data *data) +{ + int64_t delta; + + delta = k_uptime_delta(&data->timestamp); + data->timestamp = k_uptime_get(); + return ((uint16_t)delta) > data->timeout_ms; +} + +#if CONFIG_GNSS_SATELLITES +static void gnss_nmea0183_match_reset_gsv(struct gnss_nmea0183_match_data *data) +{ + data->satellites_length = 0; + data->gsv_message_number = 1; +} +#endif + +static void gnss_nmea0183_match_reset(struct gnss_nmea0183_match_data *data) +{ + data->gga_received = false; + data->rmc_received = false; +} + +void gnss_nmea0183_match_gga_callback(struct modem_chat *chat, char **argv, uint16_t argc, + void *user_data) +{ + struct gnss_nmea0183_match_data *data = user_data; + + if (gnss_nmea0183_match_timed_out(data)) { + gnss_nmea0183_match_reset(data); + } + + if (gnss_nmea0183_parse_gga((const char **)argv, argc, &data->data) < 0) { + return; + } + + data->gga_received = true; + + if (data->gga_received && data->rmc_received) { + gnss_publish_data(data->gnss, &data->data); + } +} + +void gnss_nmea0183_match_rmc_callback(struct modem_chat *chat, char **argv, uint16_t argc, + void *user_data) +{ + struct gnss_nmea0183_match_data *data = user_data; + + if (gnss_nmea0183_match_timed_out(data)) { + gnss_nmea0183_match_reset(data); + } + + if (gnss_nmea0183_parse_rmc((const char **)argv, argc, &data->data) < 0) { + return; + } + + data->rmc_received = true; + + if (data->gga_received && data->rmc_received) { + gnss_publish_data(data->gnss, &data->data); + } +} + +#if CONFIG_GNSS_SATELLITES +void gnss_nmea0183_match_gsv_callback(struct modem_chat *chat, char **argv, uint16_t argc, + void *user_data) +{ + struct gnss_nmea0183_match_data *data = user_data; + struct gnss_nmea0183_gsv_header header; + int ret; + + if (gnss_nmea0183_match_timed_out(data)) { + gnss_nmea0183_match_reset(data); + } + + if (gnss_nmea0183_parse_gsv_header((const char **)argv, argc, &header) < 0) { + return; + } + + if (header.number_of_svs == 0) { + return; + } + + if (header.message_number != data->gsv_message_number) { + gnss_nmea0183_match_reset_gsv(data); + return; + } + + data->gsv_message_number++; + + ret = gnss_nmea0183_parse_gsv_svs((const char **)argv, argc, + &data->satellites[data->satellites_length], + data->satellites_size - data->satellites_length); + if (ret < 0) { + gnss_nmea0183_match_reset_gsv(data); + return; + } + + data->satellites_length += (uint16_t)ret; + + if (data->satellites_length == header.number_of_svs) { + gnss_publish_satellites(data->gnss, data->satellites, data->satellites_length); + gnss_nmea0183_match_reset_gsv(data); + } +} +#endif + +int gnss_nmea0183_match_init(struct gnss_nmea0183_match_data *data, + const struct gnss_nmea0183_match_config *config) +{ + __ASSERT(data != NULL, "data argument must be provided"); + __ASSERT(config != NULL, "data argument must be provided"); + + memset(data, 0, sizeof(struct gnss_nmea0183_match_data)); + data->gnss = config->gnss; +#if CONFIG_GNSS_SATELLITES + data->satellites = config->satellites; + data->satellites_size = config->satellites_size; +#endif + data->timeout_ms = config->timeout_ms; + return 0; +} diff --git a/drivers/gnss/gnss_nmea0183_match.h b/drivers/gnss/gnss_nmea0183_match.h new file mode 100644 index 00000000000..65104e1dc8a --- /dev/null +++ b/drivers/gnss/gnss_nmea0183_match.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2023 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * The GNSS NMEA0183 match is a set of modem_chat match handlers and a context to be + * passed to said handlers, to parse the NMEA0183 messages received from a NMEA0183 + * based GNSS device. + * + * The context struct gnss_nmea0183_match_data *data is placed as the first member + * of the data structure which is passed to the modem_chat instance through the + * user_data member. + * + * struct my_gnss_nmea0183_driver { + * gnss_nmea0183_match_data match_data; + * ... + * }; + * + * The struct gnss_nmea0183_match_data context must be initialized using + * gnss_nmea0183_match_init(). + * + * When initializing the modem_chat instance, the three match callbacks must be added + * as part of the unsolicited matches. + * + * MODEM_CHAT_MATCHES_DEFINE(unsol_matches, + * MODEM_CHAT_MATCH_WILDCARD("$??GGA,", ",*", gnss_nmea0183_match_gga_callback), + * MODEM_CHAT_MATCH_WILDCARD("$??RMC,", ",*", gnss_nmea0183_match_rmc_callback), + * #if CONFIG_GNSS_SATELLITES + * MODEM_CHAT_MATCH_WILDCARD("$??GSV,", ",*", gnss_nmea0183_match_gsv_callback), + * #endif + * + */ + +#ifndef ZEPHYR_DRIVERS_GNSS_GNSS_NMEA0183_MATCH_H_ +#define ZEPHYR_DRIVERS_GNSS_GNSS_NMEA0183_MATCH_H_ + +#include +#include +#include +#include + +struct gnss_nmea0183_match_data { + const struct device *gnss; + struct gnss_data data; +#if CONFIG_GNSS_SATELLITES + struct gnss_satellite *satellites; + uint16_t satellites_size; + uint16_t satellites_length; +#endif + int64_t timestamp; + uint16_t timeout_ms; + uint8_t gga_received : 1; + uint8_t rmc_received : 1; + uint8_t gsv_message_number : 6; +}; + +/** GNSS NMEA0183 match configuration structure */ +struct gnss_nmea0183_match_config { + /** The GNSS device from which the data is published */ + const struct device *gnss; +#if CONFIG_GNSS_SATELLITES + /** Buffer for parsed satellites */ + struct gnss_satellite *satellites; + /** Number of elements in buffer for parsed satellites */ + uint16_t satellites_size; +#endif + /** The maximum time from the first to the last NMEA0183 message of a fix */ + uint16_t timeout_ms; +}; + +/** + * @brief Match callback for the NMEA GGA NMEA0183 message + * + * @details Should be used as the callback of a modem_chat match which matches "$??GGA," + */ +void gnss_nmea0183_match_gga_callback(struct modem_chat *chat, char **argv, uint16_t argc, + void *user_data); + +/** + * @brief Match callback for the NMEA RMC NMEA0183 message + * + * @details Should be used as the callback of a modem_chat match which matches "$??RMC," + */ +void gnss_nmea0183_match_rmc_callback(struct modem_chat *chat, char **argv, uint16_t argc, + void *user_data); + +/** + * @brief Match callback for the NMEA GSV NMEA0183 message + * + * @details Should be used as the callback of a modem_chat match which matches "$??GSV," + */ +void gnss_nmea0183_match_gsv_callback(struct modem_chat *chat, char **argv, uint16_t argc, + void *user_data); + +/** + * @brief Initialize a GNSS NMEA0183 match instance + * + * @param data GNSS NMEA0183 match instance to initialize + * @param config Configuration to apply to GNSS NMEA0183 match instance + */ +int gnss_nmea0183_match_init(struct gnss_nmea0183_match_data *data, + const struct gnss_nmea0183_match_config *config); + +#endif /* ZEPHYR_DRIVERS_GNSS_GNSS_NMEA0183_MATCH_H_ */ diff --git a/drivers/gnss/gnss_parse.c b/drivers/gnss/gnss_parse.c new file mode 100644 index 00000000000..29808dd74f2 --- /dev/null +++ b/drivers/gnss/gnss_parse.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2023 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include + +#include "gnss_parse.h" + +#define GNSS_PARSE_NANO_KNOTS_IN_MMS (1943840LL) +#define GNSS_PARSE_NANO (1000000000LL) +#define GNSS_PARSE_MICRO (1000000LL) +#define GNSS_PARSE_MILLI (1000LL) + +int gnss_parse_dec_to_nano(const char *str, int64_t *nano) +{ + int64_t sum = 0; + int8_t decimal = -1; + int8_t pos = 0; + int8_t start = 0; + int64_t increment; + + __ASSERT(str != NULL, "str argument must be provided"); + __ASSERT(nano != NULL, "nano argument must be provided"); + + /* Find decimal */ + while (str[pos] != '\0') { + /* Verify if char is decimal */ + if (str[pos] == '.') { + decimal = pos; + break; + } + + /* Advance position */ + pos++; + } + + /* Determine starting position based on decimal location */ + pos = decimal < 0 ? pos - 1 : decimal - 1; + + /* Skip sign if it exists */ + start = str[0] == '-' ? 1 : 0; + + /* Add whole value to sum */ + increment = GNSS_PARSE_NANO; + while (start <= pos) { + /* Verify char is decimal */ + if (str[pos] < '0' || str[pos] > '9') { + return -EINVAL; + } + + /* Add value to sum */ + sum += (str[pos] - '0') * increment; + + /* Update increment */ + increment *= 10; + + /* Degrement position */ + pos--; + } + + /* Check if decimal was found */ + if (decimal < 0) { + /* Set sign of sum */ + sum = start == 1 ? -sum : sum; + + *nano = sum; + return 0; + } + + /* Convert decimal part to nano fractions and add it to sum */ + pos = decimal + 1; + increment = GNSS_PARSE_NANO / 10LL; + while (str[pos] != '\0') { + /* Verify char is decimal */ + if (str[pos] < '0' || str[pos] > '9') { + return -EINVAL; + } + + /* Add value to micro_degrees */ + sum += (str[pos] - '0') * increment; + + /* Update unit */ + increment /= 10; + + /* Increment position */ + pos++; + } + + /* Set sign of sum */ + sum = start == 1 ? -sum : sum; + + *nano = sum; + return 0; +} + +int gnss_parse_dec_to_micro(const char *str, uint64_t *micro) +{ + int ret; + + __ASSERT(str != NULL, "str argument must be provided"); + __ASSERT(micro != NULL, "micro argument must be provided"); + + ret = gnss_parse_dec_to_nano(str, micro); + if (ret < 0) { + return ret; + } + + *micro = (*micro) / GNSS_PARSE_MILLI; + return 0; +} + + +int gnss_parse_dec_to_milli(const char *str, int64_t *milli) +{ + int ret; + + __ASSERT(str != NULL, "str argument must be provided"); + __ASSERT(milli != NULL, "milli argument must be provided"); + + ret = gnss_parse_dec_to_nano(str, milli); + if (ret < 0) { + return ret; + } + + (*milli) = (*milli) / GNSS_PARSE_MICRO; + return 0; +} + +int gnss_parse_atoi(const char *str, uint8_t base, int32_t *integer) +{ + char *end; + + __ASSERT(str != NULL, "str argument must be provided"); + __ASSERT(integer != NULL, "integer argument must be provided"); + + *integer = (int32_t)strtol(str, &end, (int)base); + + if ('\0' != (*end)) { + return -EINVAL; + } + + return 0; +} diff --git a/drivers/gnss/gnss_parse.h b/drivers/gnss/gnss_parse.h new file mode 100644 index 00000000000..443363cfa6e --- /dev/null +++ b/drivers/gnss/gnss_parse.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_GNSS_GNSS_PARSE_H_ +#define ZEPHYR_DRIVERS_GNSS_GNSS_PARSE_H_ + +#include + +/** + * @brief Parse decimal string to nano parts + * + * @example "-1231.3512" -> -1231351200000 + * + * @param str The decimal string to be parsed + * @param nano Destination for parsed decimal + * + * @retval -EINVAL if str could not be parsed + * @retval 0 if str successfully parsed + */ +int gnss_parse_dec_to_nano(const char *str, int64_t *nano); + +/** + * @brief Parse decimal string to micro parts + * + * @example "-1231.3512" -> -1231351200 + * + * @param str The decimal string to be parsed + * @param milli Destination for parsed decimal + * + * @retval -EINVAL if str could not be parsed + * @retval 0 if str successfully parsed + */ +int gnss_parse_dec_to_micro(const char *str, uint64_t *micro); + +/** + * @brief Parse decimal string to milli parts + * + * @example "-1231.3512" -> -1231351 + * + * @param str The decimal string to be parsed + * @param milli Destination for parsed decimal + * + * @retval -EINVAL if str could not be parsed + * @retval 0 if str successfully parsed + */ +int gnss_parse_dec_to_milli(const char *str, int64_t *milli); + +/** + * @brief Parse integer string of configurable base to integer + * + * @example "-1231" -> -1231 + * + * @param str Decimal string to be parsed + * @param base Base of decimal string to be parsed + * @param integer Destination for parsed integer + * + * @retval -EINVAL if str could not be parsed + * @retval 0 if str successfully parsed + */ +int gnss_parse_atoi(const char *str, uint8_t base, int32_t *integer); + +#endif /* ZEPHYR_DRIVERS_GNSS_GNSS_PARSE_H_ */ diff --git a/drivers/gnss/gnss_publish.c b/drivers/gnss/gnss_publish.c new file mode 100644 index 00000000000..98e3a2e5e19 --- /dev/null +++ b/drivers/gnss/gnss_publish.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "gnss_publish.h" +#include +#include + +static struct k_spinlock lock; + +void gnss_publish_data(const struct device *dev, const struct gnss_data *data) +{ + K_SPINLOCK(&lock) { + STRUCT_SECTION_FOREACH(gnss_data_callback, callback) { + if (callback->dev == NULL || callback->dev == dev) { + callback->callback(dev, data); + } + } + } +} + +#if CONFIG_GNSS_SATELLITES +void gnss_publish_satellites(const struct device *dev, const struct gnss_satellite *satellites, + uint16_t size) +{ + K_SPINLOCK(&lock) { + STRUCT_SECTION_FOREACH(gnss_satellites_callback, callback) { + if (callback->dev == NULL || callback->dev == dev) { + callback->callback(dev, satellites, size); + } + } + } +} +#endif diff --git a/drivers/gnss/gnss_publish.h b/drivers/gnss/gnss_publish.h new file mode 100644 index 00000000000..b686c7eaed1 --- /dev/null +++ b/drivers/gnss/gnss_publish.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_GNSS_GNSS_H_ +#define ZEPHYR_DRIVERS_GNSS_GNSS_H_ + +#include + +/** Internal function used by GNSS drivers to publish GNSS data */ +void gnss_publish_data(const struct device *dev, const struct gnss_data *data); + +/** Internal function used by GNSS drivers to publish GNSS satellites */ +void gnss_publish_satellites(const struct device *dev, const struct gnss_satellite *satellites, + uint16_t size); + +#endif /* ZEPHYR_DRIVERS_GNSS_GNSS_H_ */ diff --git a/drivers/gnss/gnss_quectel_lcx6g.c b/drivers/gnss/gnss_quectel_lcx6g.c new file mode 100644 index 00000000000..0ca7f5203ac --- /dev/null +++ b/drivers/gnss/gnss_quectel_lcx6g.c @@ -0,0 +1,784 @@ +/* + * Copyright (c) 2023 Trackunit Corporation + * Copyright (c) 2023 Bjarki Arge Andreasen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gnss_publish.h" +#include "gnss_nmea0183.h" +#include "gnss_nmea0183_match.h" +#include "gnss_parse.h" + +#include +LOG_MODULE_REGISTER(quectel_lcx6g, CONFIG_GNSS_LOG_LEVEL); + +#define QUECTEL_LCX6G_STARTUP_DELAY (K_MSEC(300U)) +#define QUECTEL_LCX6G_STATE_CHANGE_DELAY_MSEC (300LL) +#define QUECTEL_LCX6G_PAIR_TIMEOUT (K_SECONDS(11)) +#define QUECTEL_LCX6G_SCRIPT_TIMEOUT_S (10U) + +#define QUECTEL_LCX6G_PAIR_NAV_MODE_STATIONARY (4) +#define QUECTEL_LCX6G_PAIR_NAV_MODE_FITNESS (1) +#define QUECTEL_LCX6G_PAIR_NAV_MODE_NORMAL (0) +#define QUECTEL_LCX6G_PAIR_NAV_MODE_DRONE (5) + +#define QUECTEL_LCX6G_PAIR_PPS_MODE_DISABLED (0) +#define QUECTEL_LCX6G_PAIR_PPS_MODE_ENABLED (4) +#define QUECTEL_LCX6G_PAIR_PPS_MODE_ENABLED_AFTER_LOCK (1) +#define QUECTEL_LCX6G_PAIR_PPS_MODE_ENABLED_WHILE_LOCKED (2) + +struct quectel_lcx6g_config { + const struct device *uart; + const enum gnss_pps_mode pps_mode; + const uint16_t pps_pulse_width; +}; + +struct quectel_lcx6g_data { + struct gnss_nmea0183_match_data match_data; +#if CONFIG_GNSS_SATELLITES + struct gnss_satellite satellites[24]; +#endif + + /* UART backend */ + struct modem_pipe *uart_pipe; + struct modem_backend_uart uart_backend; + uint8_t uart_backend_receive_buf[128]; + uint8_t uart_backend_transmit_buf[64]; + + /* Modem chat */ + struct modem_chat chat; + uint8_t chat_receive_buf[256]; + uint8_t chat_delimiter[2]; + uint8_t *chat_argv[32]; + + /* Dynamic chat script */ + uint8_t dynamic_match_buf[32]; + uint8_t dynamic_separators_buf[2]; + uint8_t dynamic_request_buf[32]; + struct modem_chat_match dynamic_match; + struct modem_chat_script_chat dynamic_script_chat; + struct modem_chat_script dynamic_script; + + /* Allocation for responses from GNSS modem */ + union { + uint16_t fix_rate_response; + gnss_systems_t enabled_systems_response; + enum gnss_navigation_mode navigation_mode_response; + }; + + struct k_spinlock lock; +}; + +#define MODEM_CHAT_SCRIPT_NO_ABORT_DEFINE(_sym, _script_chats, _callback, _timeout) \ + static struct modem_chat_script _sym = { \ + .name = #_sym, \ + .script_chats = _script_chats, \ + .script_chats_size = ARRAY_SIZE(_script_chats), \ + .abort_matches = NULL, \ + .abort_matches_size = 0, \ + .callback = _callback, \ + .timeout = _timeout, \ + } + +#ifdef CONFIG_PM_DEVICE +MODEM_CHAT_MATCH_DEFINE(pair003_success_match, "$PAIR001,003,0*38", "", NULL); +MODEM_CHAT_SCRIPT_CMDS_DEFINE( + suspend_script_cmds, + MODEM_CHAT_SCRIPT_CMD_RESP("$PAIR003*39", pair003_success_match) +); + +MODEM_CHAT_SCRIPT_NO_ABORT_DEFINE(suspend_script, suspend_script_cmds, + NULL, QUECTEL_LCX6G_SCRIPT_TIMEOUT_S); +#endif /* CONFIG_PM_DEVICE */ + +MODEM_CHAT_MATCH_DEFINE(any_match, "", "", NULL); +MODEM_CHAT_MATCH_DEFINE(pair062_ack_match, "$PAIR001,062,0*3F", "", NULL); +MODEM_CHAT_SCRIPT_CMDS_DEFINE( + resume_script_cmds, + MODEM_CHAT_SCRIPT_CMD_RESP("$PAIR002*38", any_match), + MODEM_CHAT_SCRIPT_CMD_RESP("$PAIR062,0,1*3F", pair062_ack_match), + MODEM_CHAT_SCRIPT_CMD_RESP("$PAIR062,1,0*3F", pair062_ack_match), + MODEM_CHAT_SCRIPT_CMD_RESP("$PAIR062,2,0*3C", pair062_ack_match), +#if CONFIG_GNSS_SATELLITES + MODEM_CHAT_SCRIPT_CMD_RESP("$PAIR062,3,5*38", pair062_ack_match), +#else + MODEM_CHAT_SCRIPT_CMD_RESP("$PAIR062,3,0*3D", pair062_ack_match), +#endif + MODEM_CHAT_SCRIPT_CMD_RESP("$PAIR062,4,1*3B", pair062_ack_match), + MODEM_CHAT_SCRIPT_CMD_RESP("$PAIR062,5,0*3B", pair062_ack_match), +); + +MODEM_CHAT_SCRIPT_NO_ABORT_DEFINE(resume_script, resume_script_cmds, + NULL, QUECTEL_LCX6G_SCRIPT_TIMEOUT_S); + +MODEM_CHAT_MATCHES_DEFINE(unsol_matches, + MODEM_CHAT_MATCH_WILDCARD("$??GGA,", ",*", gnss_nmea0183_match_gga_callback), + MODEM_CHAT_MATCH_WILDCARD("$??RMC,", ",*", gnss_nmea0183_match_rmc_callback), +#if CONFIG_GNSS_SATELLITES + MODEM_CHAT_MATCH_WILDCARD("$??GSV,", ",*", gnss_nmea0183_match_gsv_callback), +#endif +); + +static int quectel_lcx6g_configure_pps(const struct device *dev) +{ + const struct quectel_lcx6g_config *config = dev->config; + struct quectel_lcx6g_data *data = dev->data; + uint8_t pps_mode = 0; + int ret; + + switch (config->pps_mode) { + case GNSS_PPS_MODE_DISABLED: + pps_mode = QUECTEL_LCX6G_PAIR_PPS_MODE_DISABLED; + break; + + case GNSS_PPS_MODE_ENABLED: + pps_mode = QUECTEL_LCX6G_PAIR_PPS_MODE_ENABLED; + break; + + case GNSS_PPS_MODE_ENABLED_AFTER_LOCK: + pps_mode = QUECTEL_LCX6G_PAIR_PPS_MODE_ENABLED_AFTER_LOCK; + break; + + case GNSS_PPS_MODE_ENABLED_WHILE_LOCKED: + pps_mode = QUECTEL_LCX6G_PAIR_PPS_MODE_ENABLED_WHILE_LOCKED; + break; + } + + ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + "PAIR752,%u,%u", pps_mode, config->pps_pulse_width); + if (ret < 0) { + return ret; + } + + data->dynamic_script_chat.request_size = ret; + + ret = gnss_nmea0183_snprintk(data->dynamic_match_buf, sizeof(data->dynamic_match_buf), + "PAIR001,752,0"); + if (ret < 0) { + return ret; + } + + data->dynamic_match.match_size = ret; + + return modem_chat_run_script(&data->chat, &data->dynamic_script); +} + +static int quectel_lcx6g_resume(const struct device *dev) +{ + struct quectel_lcx6g_data *data = dev->data; + int ret; + + ret = modem_pipe_open(data->uart_pipe); + if (ret < 0) { + return ret; + } + + ret = modem_chat_attach(&data->chat, data->uart_pipe); + if (ret < 0) { + modem_pipe_close(data->uart_pipe); + return ret; + } + + ret = modem_chat_run_script(&data->chat, &resume_script); + if (ret < 0) { + modem_pipe_close(data->uart_pipe); + return ret; + } + + k_msleep(1000); + + ret = quectel_lcx6g_configure_pps(dev); + if (ret < 0) { + modem_pipe_close(data->uart_pipe); + } + + return ret; +} + +#ifdef CONFIG_PM_DEVICE +static int quectel_lcx6g_suspend(const struct device *dev) +{ + struct quectel_lcx6g_data *data = dev->data; + int ret; + + ret = modem_chat_run_script_run(&data->chat, &suspend_script); + if (ret < 0) { + modem_pipe_close(data->uart_pipe); + } + + return ret; +} + +static int quectel_lcx6g_turn_off(const struct device *dev) +{ + struct quectel_lcx6g_data *data = dev->data; + + return modem_pipe_close(data->uart_pipe); +} + +static int quectel_lcx6g_pm_action(const struct device *dev, enum pm_device_action action) +{ + struct quectel_lcx6g_data *data = dev->data; + k_spinlock_key_t key; + int ret = -ENOTSUP; + + key = k_spin_lock(&data->lock); + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + ret = quectel_lcx6g_suspend(dev); + break; + + case PM_DEVICE_ACTION_RESUME: + ret = quectel_lcx6g_resume(dev); + break; + + case PM_DEVICE_ACTION_TURN_ON: + ret = 0; + break; + + case PM_DEVICE_ACTION_TURN_OFF: + ret = quectel_lcx6g_turn_off(dev); + break; + + default: + break; + } + + k_spin_unlock(&data->lock, key); + return ret; +} +#endif /* CONFIG_PM_DEVICE */ + +static int quectel_lcx6g_set_fix_rate(const struct device *dev, uint32_t fix_interval_ms) +{ + struct quectel_lcx6g_data *data = dev->data; + k_spinlock_key_t key; + int ret; + + if (fix_interval_ms < 100 || fix_interval_ms > 1000) { + return -EINVAL; + } + + key = k_spin_lock(&data->lock); + + ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + "PAIR050,%u", fix_interval_ms); + if (ret < 0) { + goto unlock_return; + } + + data->dynamic_script_chat.request_size = ret; + + ret = gnss_nmea0183_snprintk(data->dynamic_match_buf, sizeof(data->dynamic_match_buf), + "PAIR001,050,0"); + if (ret < 0) { + goto unlock_return; + } + + data->dynamic_match.match_size = ret; + + ret = modem_chat_run_script(&data->chat, &data->dynamic_script); + if (ret < 0) { + goto unlock_return; + } + +unlock_return: + k_spin_unlock(&data->lock, key); + return ret; +} + +static void quectel_lcx6g_get_fix_rate_callback(struct modem_chat *chat, char **argv, + uint16_t argc, void *user_data) +{ + struct quectel_lcx6g_data *data = user_data; + int32_t tmp; + + if (argc != 3) { + return; + } + + if ((gnss_parse_atoi(argv[1], 10, &tmp) < 0) || (tmp < 0) || (tmp > 1000)) { + return; + } + + data->fix_rate_response = (uint16_t)tmp; +} + +static int quectel_lcx6g_get_fix_rate(const struct device *dev, uint32_t *fix_interval_ms) +{ + struct quectel_lcx6g_data *data = dev->data; + k_spinlock_key_t key; + int ret; + + key = k_spin_lock(&data->lock); + + ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + "PAIR051"); + if (ret < 0) { + goto unlock_return; + } + + data->dynamic_script_chat.request_size = ret; + + strncpy(data->dynamic_match_buf, "$PAIR051,", sizeof(data->dynamic_match_buf)); + data->dynamic_match.match_size = sizeof("$PAIR051,") - 1; + data->dynamic_match.callback = quectel_lcx6g_get_fix_rate_callback; + + ret = modem_chat_run_script(&data->chat, &data->dynamic_script); + data->dynamic_match.callback = NULL; + if (ret < 0) { + goto unlock_return; + } + + *fix_interval_ms = data->fix_rate_response; + +unlock_return: + k_spin_unlock(&data->lock, key); + return 0; +} + +static int quectel_lcx6g_set_navigation_mode(const struct device *dev, + enum gnss_navigation_mode mode) +{ + struct quectel_lcx6g_data *data = dev->data; + k_spinlock_key_t key; + uint8_t navigation_mode = 0; + int ret; + + switch (mode) { + case GNSS_NAVIGATION_MODE_ZERO_DYNAMICS: + navigation_mode = QUECTEL_LCX6G_PAIR_NAV_MODE_STATIONARY; + break; + + case GNSS_NAVIGATION_MODE_LOW_DYNAMICS: + navigation_mode = QUECTEL_LCX6G_PAIR_NAV_MODE_FITNESS; + break; + + case GNSS_NAVIGATION_MODE_BALANCED_DYNAMICS: + navigation_mode = QUECTEL_LCX6G_PAIR_NAV_MODE_NORMAL; + break; + + case GNSS_NAVIGATION_MODE_HIGH_DYNAMICS: + navigation_mode = QUECTEL_LCX6G_PAIR_NAV_MODE_DRONE; + break; + } + + key = k_spin_lock(&data->lock); + + ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + "PAIR080,%u", navigation_mode); + if (ret < 0) { + goto unlock_return; + } + + data->dynamic_script_chat.request_size = ret; + + ret = gnss_nmea0183_snprintk(data->dynamic_match_buf, sizeof(data->dynamic_match_buf), + "PAIR001,080,0"); + if (ret < 0) { + goto unlock_return; + } + + data->dynamic_match.match_size = ret; + + ret = modem_chat_run_script(&data->chat, &data->dynamic_script); + if (ret < 0) { + goto unlock_return; + } + +unlock_return: + k_spin_unlock(&data->lock, key); + return ret; +} + +static void quectel_lcx6g_get_navigation_mode_callback(struct modem_chat *chat, char **argv, + uint16_t argc, void *user_data) +{ + struct quectel_lcx6g_data *data = user_data; + int32_t tmp; + + if (argc != 3) { + return; + } + + if ((gnss_parse_atoi(argv[1], 10, &tmp) < 0) || (tmp < 0) || (tmp > 7)) { + return; + } + + switch (tmp) { + case QUECTEL_LCX6G_PAIR_NAV_MODE_FITNESS: + data->navigation_mode_response = GNSS_NAVIGATION_MODE_LOW_DYNAMICS; + break; + + case QUECTEL_LCX6G_PAIR_NAV_MODE_STATIONARY: + data->navigation_mode_response = GNSS_NAVIGATION_MODE_ZERO_DYNAMICS; + break; + + case QUECTEL_LCX6G_PAIR_NAV_MODE_DRONE: + data->navigation_mode_response = GNSS_NAVIGATION_MODE_HIGH_DYNAMICS; + break; + + default: + data->navigation_mode_response = GNSS_NAVIGATION_MODE_BALANCED_DYNAMICS; + break; + } +} + +static int quectel_lcx6g_get_navigation_mode(const struct device *dev, + enum gnss_navigation_mode *mode) +{ + struct quectel_lcx6g_data *data = dev->data; + k_spinlock_key_t key; + int ret; + + key = k_spin_lock(&data->lock); + + ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + "PAIR081"); + if (ret < 0) { + goto unlock_return; + } + + data->dynamic_script_chat.request_size = ret; + + strncpy(data->dynamic_match_buf, "$PAIR081,", sizeof(data->dynamic_match_buf)); + data->dynamic_match.match_size = sizeof("$PAIR081,") - 1; + data->dynamic_match.callback = quectel_lcx6g_get_navigation_mode_callback; + + ret = modem_chat_run_script(&data->chat, &data->dynamic_script); + data->dynamic_match.callback = NULL; + if (ret < 0) { + goto unlock_return; + } + + *mode = data->navigation_mode_response; + +unlock_return: + k_spin_unlock(&data->lock, key); + return ret; +} + +static int quectel_lcx6g_set_enabled_systems(const struct device *dev, gnss_systems_t systems) +{ + struct quectel_lcx6g_data *data = dev->data; + gnss_systems_t supported_systems; + k_spinlock_key_t key; + int ret; + + supported_systems = (GNSS_SYSTEM_GPS | GNSS_SYSTEM_GLONASS | GNSS_SYSTEM_GALILEO | + GNSS_SYSTEM_BEIDOU | GNSS_SYSTEM_QZSS | GNSS_SYSTEM_SBAS); + + if ((~supported_systems) & systems) { + return -EINVAL; + } + + key = k_spin_lock(&data->lock); + + ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + "PAIR066,%u,%u,%u,%u,%u,0", + (0 < (systems & GNSS_SYSTEM_GPS)), + (0 < (systems & GNSS_SYSTEM_GLONASS)), + (0 < (systems & GNSS_SYSTEM_GALILEO)), + (0 < (systems & GNSS_SYSTEM_BEIDOU)), + (0 < (systems & GNSS_SYSTEM_QZSS))); + if (ret < 0) { + goto unlock_return; + } + + data->dynamic_script_chat.request_size = ret; + + ret = gnss_nmea0183_snprintk(data->dynamic_match_buf, sizeof(data->dynamic_match_buf), + "PAIR001,066,0"); + if (ret < 0) { + goto unlock_return; + } + + data->dynamic_match.match_size = ret; + + ret = modem_chat_run_script(&data->chat, &data->dynamic_script); + if (ret < 0) { + goto unlock_return; + } + + ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + "PAIR410,%u", (0 < (systems & GNSS_SYSTEM_SBAS))); + if (ret < 0) { + goto unlock_return; + } + + data->dynamic_script_chat.request_size = ret; + + ret = gnss_nmea0183_snprintk(data->dynamic_match_buf, sizeof(data->dynamic_match_buf), + "PAIR001,410,0"); + if (ret < 0) { + goto unlock_return; + } + + data->dynamic_match.match_size = ret; + + ret = modem_chat_run_script(&data->chat, &data->dynamic_script); + if (ret < 0) { + goto unlock_return; + } + +unlock_return: + k_spin_unlock(&data->lock, key); + return ret; +} + +static inline bool search_mode_enabled(const char *arg) +{ + return arg[0] == '1'; +} + +static void quectel_lcx6g_get_search_mode_callback(struct modem_chat *chat, char **argv, + uint16_t argc, void *user_data) +{ + struct quectel_lcx6g_data *data = user_data; + + if (argc != 8) { + return; + } + + data->enabled_systems_response = search_mode_enabled(argv[1]) ? GNSS_SYSTEM_GPS : 0; + data->enabled_systems_response |= search_mode_enabled(argv[2]) ? GNSS_SYSTEM_GLONASS : 0; + data->enabled_systems_response |= search_mode_enabled(argv[3]) ? GNSS_SYSTEM_GALILEO : 0; + data->enabled_systems_response |= search_mode_enabled(argv[4]) ? GNSS_SYSTEM_BEIDOU : 0; + data->enabled_systems_response |= search_mode_enabled(argv[5]) ? GNSS_SYSTEM_QZSS : 0; +} + +static void quectel_lcx6g_get_sbas_status_callback(struct modem_chat *chat, char **argv, + uint16_t argc, void *user_data) +{ + struct quectel_lcx6g_data *data = user_data; + + if (argc != 3) { + return; + } + + data->enabled_systems_response |= ('1' == argv[1][0]) ? GNSS_SYSTEM_SBAS : 0; +} + + +static int quectel_lcx6g_get_enabled_systems(const struct device *dev, gnss_systems_t *systems) +{ + struct quectel_lcx6g_data *data = dev->data; + k_spinlock_key_t key; + int ret; + + key = k_spin_lock(&data->lock); + + ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + "PAIR067"); + if (ret < 0) { + goto unlock_return; + } + + data->dynamic_script_chat.request_size = ret; + + strncpy(data->dynamic_match_buf, "$PAIR067,", sizeof(data->dynamic_match_buf)); + data->dynamic_match.match_size = sizeof("$PAIR067,") - 1; + data->dynamic_match.callback = quectel_lcx6g_get_search_mode_callback; + + ret = modem_chat_run_script(&data->chat, &data->dynamic_script); + data->dynamic_match.callback = NULL; + if (ret < 0) { + goto unlock_return; + } + + ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + "PAIR411"); + if (ret < 0) { + goto unlock_return; + } + + data->dynamic_script_chat.request_size = ret; + + strncpy(data->dynamic_match_buf, "$PAIR411,", sizeof(data->dynamic_match_buf)); + data->dynamic_match.match_size = sizeof("$PAIR411,") - 1; + data->dynamic_match.callback = quectel_lcx6g_get_sbas_status_callback; + + ret = modem_chat_run_script(&data->chat, &data->dynamic_script); + data->dynamic_match.callback = NULL; + if (ret < 0) { + goto unlock_return; + } + + *systems = data->enabled_systems_response; + +unlock_return: + k_spin_unlock(&data->lock, key); + return ret; +} + +static int quectel_lcx6g_get_supported_systems(const struct device *dev, gnss_systems_t *systems) +{ + *systems = (GNSS_SYSTEM_GPS | GNSS_SYSTEM_GLONASS | GNSS_SYSTEM_GALILEO | + GNSS_SYSTEM_BEIDOU | GNSS_SYSTEM_QZSS | GNSS_SYSTEM_SBAS); + return 0; +} + +static struct gnss_driver_api gnss_api = { + .set_fix_rate = quectel_lcx6g_set_fix_rate, + .get_fix_rate = quectel_lcx6g_get_fix_rate, + .set_navigation_mode = quectel_lcx6g_set_navigation_mode, + .get_navigation_mode = quectel_lcx6g_get_navigation_mode, + .set_enabled_systems = quectel_lcx6g_set_enabled_systems, + .get_enabled_systems = quectel_lcx6g_get_enabled_systems, + .get_supported_systems = quectel_lcx6g_get_supported_systems, +}; + +static int quectel_lcx6g_init_nmea0183_match(const struct device *dev) +{ + struct quectel_lcx6g_data *data = dev->data; + + const struct gnss_nmea0183_match_config config = { + .gnss = dev, +#if CONFIG_GNSS_SATELLITES + .satellites = data->satellites, + .satellites_size = ARRAY_SIZE(data->satellites), +#endif + .timeout_ms = 50, + }; + + return gnss_nmea0183_match_init(&data->match_data, &config); +} + +static void quectel_lcx6g_init_pipe(const struct device *dev) +{ + const struct quectel_lcx6g_config *config = dev->config; + struct quectel_lcx6g_data *data = dev->data; + + const struct modem_backend_uart_config uart_backend_config = { + .uart = config->uart, + .receive_buf = data->uart_backend_receive_buf, + .receive_buf_size = ARRAY_SIZE(data->uart_backend_receive_buf), + .transmit_buf = data->uart_backend_transmit_buf, + .transmit_buf_size = ARRAY_SIZE(data->uart_backend_transmit_buf), + }; + + data->uart_pipe = modem_backend_uart_init(&data->uart_backend, &uart_backend_config); +} + +static int quectel_lcx6g_init_chat(const struct device *dev) +{ + struct quectel_lcx6g_data *data = dev->data; + + const struct modem_chat_config chat_config = { + .user_data = data, + .receive_buf = data->chat_receive_buf, + .receive_buf_size = ARRAY_SIZE(data->chat_receive_buf), + .delimiter = data->chat_delimiter, + .delimiter_size = ARRAY_SIZE(data->chat_delimiter), + .filter = NULL, + .filter_size = 0, + .argv = data->chat_argv, + .argv_size = ARRAY_SIZE(data->chat_argv), + .unsol_matches = unsol_matches, + .unsol_matches_size = ARRAY_SIZE(unsol_matches), + .process_timeout = K_MSEC(2), + }; + + return modem_chat_init(&data->chat, &chat_config); +} + +static void quectel_lcx6g_init_dynamic_script(const struct device *dev) +{ + struct quectel_lcx6g_data *data = dev->data; + + data->dynamic_match.match = data->dynamic_match_buf; + data->dynamic_match.separators = data->dynamic_separators_buf; + data->dynamic_match.separators_size = sizeof(data->dynamic_separators_buf); + data->dynamic_match.wildcards = false; + data->dynamic_match.partial = false; + + data->dynamic_script_chat.request = data->dynamic_request_buf; + data->dynamic_script_chat.response_matches = &data->dynamic_match; + data->dynamic_script_chat.response_matches_size = 1; + data->dynamic_script_chat.timeout = 0; + + data->dynamic_script.name = "pair"; + data->dynamic_script.script_chats = &data->dynamic_script_chat; + data->dynamic_script.script_chats_size = 1; + data->dynamic_script.abort_matches = NULL; + data->dynamic_script.abort_matches_size = 0; + data->dynamic_script.callback = NULL; + data->dynamic_script.timeout = 10; +} + +static int quectel_lcx6g_init(const struct device *dev) +{ + int ret; + + LOG_INF("Initializing Quectel LCX6G"); + ret = quectel_lcx6g_init_nmea0183_match(dev); + if (ret < 0) { + return ret; + } + + quectel_lcx6g_init_pipe(dev); + + ret = quectel_lcx6g_init_chat(dev); + if (ret < 0) { + return ret; + } + + quectel_lcx6g_init_dynamic_script(dev); + +#ifdef CONFIG_PM_DEVICE_RUNTIME + pm_device_init_suspended(dev); +#else + LOG_INF("Resuming Quectel LCX6G"); + ret = quectel_lcx6g_resume(dev); + if (ret < 0) { + LOG_ERR("Failed to resume Quectel LCX6G"); + return ret; + } +#endif + LOG_INF("Quectel LCX6G initialized"); + return 0; +} + +#define LCX6G_INST_NAME(inst, name) \ + _CONCAT(_CONCAT(_CONCAT(name, _), DT_DRV_COMPAT), inst) + +#define LCX6G_DEVICE(inst) \ + static struct quectel_lcx6g_config LCX6G_INST_NAME(inst, config) = { \ + .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ + .pps_mode = DT_INST_STRING_UPPER_TOKEN(inst, pps_mode), \ + .pps_pulse_width = DT_INST_PROP(inst, pps_pulse_width), \ + }; \ + \ + static struct quectel_lcx6g_data LCX6G_INST_NAME(inst, data) = { \ + .chat_delimiter = {'\r', '\n'}, \ + .dynamic_separators_buf = {',', '*'}, \ + }; \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, quectel_lcx6g_pm_action); \ + \ + DEVICE_DT_INST_DEFINE(inst, quectel_lcx6g_init, PM_DEVICE_DT_INST_GET(inst), \ + &LCX6G_INST_NAME(inst, data), &LCX6G_INST_NAME(inst, config), \ + POST_KERNEL, CONFIG_GNSS_INIT_PRIORITY, &gnss_api); + +#define DT_DRV_COMPAT quectel_lc26g +DT_INST_FOREACH_STATUS_OKAY(LCX6G_DEVICE) +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT quectel_lc76g +DT_INST_FOREACH_STATUS_OKAY(LCX6G_DEVICE) +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT quectel_lc86g +DT_INST_FOREACH_STATUS_OKAY(LCX6G_DEVICE) +#undef DT_DRV_COMPAT diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index 5b1229fd00b..b1cd06978bb 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -4,6 +4,7 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/gpio.h) zephyr_library() +zephyr_library_sources_ifdef(CONFIG_GPIO_AD5592 gpio_ad5592.c) zephyr_library_sources_ifdef(CONFIG_GPIO_AXP192 gpio_axp192.c) zephyr_library_sources_ifdef(CONFIG_GPIO_TELINK_B91 gpio_b91.c) zephyr_library_sources_ifdef(CONFIG_GPIO_INFINEON_CAT1 gpio_ifx_cat1.c) @@ -82,6 +83,12 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_HOGS gpio_hogs.c) zephyr_library_sources_ifdef(CONFIG_GPIO_NUMAKER gpio_numaker.c) zephyr_library_sources_ifdef(CONFIG_GPIO_EFINIX_SAPPHIRE gpio_efinix_sapphire.c) zephyr_library_sources_ifdef(CONFIG_GPIO_DAVINCI gpio_davinci.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_SEDI gpio_sedi.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_TLE9104 gpio_tle9104.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_ALTERA_PIO gpio_altera_pio.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_BCM2711 gpio_bcm2711.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_RA gpio_ra.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_RZT2M gpio_rzt2m.c) if (CONFIG_GPIO_EMUL_SDL) zephyr_library_sources(gpio_emul_sdl.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 7e368a9852e..c49e2aa1167 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -20,6 +20,24 @@ config GPIO_SHELL help Enable GPIO Shell for testing. +config GPIO_SHELL_INFO_CMD + bool "GPIO Shell info command" + default y + depends on GPIO_SHELL + help + Enable GPIO Shell information command. + This command provides a shell user extra information about gpio + controller reserved pins and line names. + +config GPIO_SHELL_BLINK_CMD + bool "GPIO Shell blink command" + default y + depends on GPIO_SHELL + help + Enable GPIO Shell blink command. + This command provides a shell user the ability to 'blink' a pin + at 1Hz. + config GPIO_INIT_PRIORITY int "GPIO init priority" default KERNEL_INIT_PRIORITY_DEFAULT @@ -69,6 +87,8 @@ config GPIO_ENABLE_DISABLE_INTERRUPT pending register, etc. The driver must implement it to work. +source "drivers/gpio/Kconfig.ad5592" + source "drivers/gpio/Kconfig.axp192" source "drivers/gpio/Kconfig.b91" @@ -204,5 +224,16 @@ source "drivers/gpio/Kconfig.numaker" source "drivers/gpio/Kconfig.efinix_sapphire" source "drivers/gpio/Kconfig.davinci" +source "drivers/gpio/Kconfig.sedi" + +source "drivers/gpio/Kconfig.tle9104" + +source "drivers/gpio/Kconfig.altera" + +source "drivers/gpio/Kconfig.bcm2711" + +source "drivers/gpio/Kconfig.ra" + +source "drivers/gpio/Kconfig.rzt2m" endif # GPIO diff --git a/drivers/gpio/Kconfig.ad5592 b/drivers/gpio/Kconfig.ad5592 new file mode 100644 index 00000000000..c2654d1857b --- /dev/null +++ b/drivers/gpio/Kconfig.ad5592 @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Grinn +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_AD5592 + bool "AD5592 GPIO driver" + default y + depends on DT_HAS_ADI_AD5592_GPIO_ENABLED + select MFD + help + Enable the AD5592 GPIO driver. diff --git a/drivers/gpio/Kconfig.altera b/drivers/gpio/Kconfig.altera new file mode 100644 index 00000000000..2bb03287494 --- /dev/null +++ b/drivers/gpio/Kconfig.altera @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_ALTERA_PIO + bool "Altera PIO" + default y + depends on DT_HAS_ALTR_PIO_1_0_ENABLED + help + Enable driver for Altera PIO diff --git a/drivers/gpio/Kconfig.axp192 b/drivers/gpio/Kconfig.axp192 index a9e648309fb..c81c02d895c 100644 --- a/drivers/gpio/Kconfig.axp192 +++ b/drivers/gpio/Kconfig.axp192 @@ -14,7 +14,7 @@ config GPIO_AXP192 config GPIO_AXP192_INIT_PRIORITY int "AXP192 GPIO driver initialization priority" depends on GPIO_AXP192 - default 80 + default 81 help Initialization priority for the AXP192 GPIO driver. It must be greater than the I2C controller init priority and the mfd driver diff --git a/drivers/gpio/Kconfig.bcm2711 b/drivers/gpio/Kconfig.bcm2711 new file mode 100644 index 00000000000..ad7c3c11b13 --- /dev/null +++ b/drivers/gpio/Kconfig.bcm2711 @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Chen Xingyu +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_BCM2711 + bool "BCM2711 GPIO driver" + default y + depends on DT_HAS_BRCM_BCM2711_GPIO_ENABLED + help + Enable BCM2711 GPIO driver. diff --git a/drivers/gpio/Kconfig.nct38xx b/drivers/gpio/Kconfig.nct38xx index 3c4f396063b..dfa5cbf9c38 100644 --- a/drivers/gpio/Kconfig.nct38xx +++ b/drivers/gpio/Kconfig.nct38xx @@ -7,7 +7,8 @@ config GPIO_NCT38XX bool "NCT38XX I2C-based GPIO chip" default y depends on DT_HAS_NUVOTON_NCT38XX_GPIO_PORT_ENABLED - depends on I2C + select I2C + select MFD help Enable driver for NCT38XX I2C-based GPIO chip. @@ -15,17 +16,17 @@ if GPIO_NCT38XX config GPIO_NCT38XX_INIT_PRIORITY int "NCT38XX GPIO init priority" - default 51 + default 82 help - Device driver initialization priority. The priority should be lower - than I2C device. + NCT38xx GPIO driver initialization priority. The priority must be lower + than MFD_INIT_PRIORITY. config GPIO_NCT38XX_PORT_INIT_PRIORITY int "NCT38XX GPIO port init priority" - default 52 + default 84 help - Device driver initialization priority. The priority should be lower - than I2C & GPIO_NCT38XX_INIT_PRIORITY device. + NCT38xx GPIO port device driver initialization priority. The priority + must be lower than GPIO_NCT38XX_INIT_PRIORITY device. config GPIO_NCT38XX_ALERT bool "NCT38XX GPIO interrupt" @@ -36,7 +37,7 @@ config GPIO_NCT38XX_ALERT config GPIO_NCT38XX_ALERT_INIT_PRIORITY int "NCT38XX GPIO alert handler init priority" - default 52 + default 84 depends on GPIO_NCT38XX_ALERT help NCT38XX alert handler initialization priority. This initialization diff --git a/drivers/gpio/Kconfig.npm1300 b/drivers/gpio/Kconfig.npm1300 index c3cbf53d6e2..65cb81a3686 100644 --- a/drivers/gpio/Kconfig.npm1300 +++ b/drivers/gpio/Kconfig.npm1300 @@ -13,7 +13,7 @@ config GPIO_NPM1300 config GPIO_NPM1300_INIT_PRIORITY int "nPM1300 GPIO driver initialization priority" depends on GPIO_NPM1300 - default 70 + default 85 help Initialization priority for the nPM1300 GPIO driver. It must be greater than the I2C controller init priority. diff --git a/drivers/gpio/Kconfig.npm6001 b/drivers/gpio/Kconfig.npm6001 index 81fc4cb4a60..b138b101a72 100644 --- a/drivers/gpio/Kconfig.npm6001 +++ b/drivers/gpio/Kconfig.npm6001 @@ -13,6 +13,6 @@ config GPIO_NPM6001 config GPIO_NPM6001_INIT_PRIORITY int "nPM6001 GPIO driver initialization priority" depends on GPIO_NPM6001 - default 65 + default 85 help Initialization priority for the nPM6001 GPIO driver. diff --git a/drivers/gpio/Kconfig.nxp_s32 b/drivers/gpio/Kconfig.nxp_s32 index 159402b10ea..0c478c324df 100644 --- a/drivers/gpio/Kconfig.nxp_s32 +++ b/drivers/gpio/Kconfig.nxp_s32 @@ -5,6 +5,6 @@ config GPIO_NXP_S32 bool "NXP S32 GPIO driver" default y depends on DT_HAS_NXP_S32_GPIO_ENABLED - select NOCACHE_MEMORY + select NOCACHE_MEMORY if ARCH_HAS_NOCACHE_MEMORY_SUPPORT help Enable the GPIO driver for NXP S32 processors. diff --git a/drivers/gpio/Kconfig.ra b/drivers/gpio/Kconfig.ra new file mode 100644 index 00000000000..391a32f293d --- /dev/null +++ b/drivers/gpio/Kconfig.ra @@ -0,0 +1,10 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_RA + bool "Renesas RA Series GPIO driver" + default y + select GPIO_GET_CONFIG + depends on DT_HAS_RENESAS_RA_GPIO_ENABLED + help + Enable Renesas RA series GPIO driver. diff --git a/drivers/gpio/Kconfig.rzt2m b/drivers/gpio/Kconfig.rzt2m new file mode 100644 index 00000000000..d9cb6b1e867 --- /dev/null +++ b/drivers/gpio/Kconfig.rzt2m @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_RZT2M + bool "Renesas RZT2M GPIO" + default y + depends on DT_HAS_RENESAS_RZT2M_GPIO_ENABLED + help + Enable Renesas RZT2M GPIO driver. diff --git a/drivers/gpio/Kconfig.sedi b/drivers/gpio/Kconfig.sedi new file mode 100644 index 00000000000..3ad11b5893e --- /dev/null +++ b/drivers/gpio/Kconfig.sedi @@ -0,0 +1,14 @@ +# +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +config GPIO_SEDI + bool "SEDI GPIO driver" + default y + depends on DT_HAS_INTEL_SEDI_GPIO_ENABLED + help + This option enables Intel SEDI GPIO driver. + This driver is simply a shim driver built upon the SEDI + bare metal GPIO driver in hal-intel module. diff --git a/drivers/gpio/Kconfig.tle9104 b/drivers/gpio/Kconfig.tle9104 new file mode 100644 index 00000000000..fd12710a5f5 --- /dev/null +++ b/drivers/gpio/Kconfig.tle9104 @@ -0,0 +1,19 @@ +# TLE9104 GPIO configuration options + +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +menuconfig GPIO_TLE9104 + bool "TLE9104 SPI-based powertrain switch" + default y + depends on DT_HAS_INFINEON_TLE9104_ENABLED + depends on SPI + help + Enable driver for TLE9104 SPI-based powertrain switch. + +config GPIO_TLE9104_INIT_PRIORITY + int "Init priority" + default 75 + depends on GPIO_TLE9104 + help + Device driver initialization priority. diff --git a/drivers/gpio/gpio_ad5592.c b/drivers/gpio/gpio_ad5592.c new file mode 100644 index 00000000000..a8b30ddcee4 --- /dev/null +++ b/drivers/gpio/gpio_ad5592.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2023 Grinn + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT adi_ad5592_gpio + +#include +#include +#include +#include + +#include + +struct gpio_ad5592_config { + /* gpio_driver_config needs to be first */ + struct gpio_driver_config common; + const struct device *mfd_dev; +}; + +struct gpio_ad5592_data { + /* gpio_driver_data needs to be first */ + struct gpio_driver_data common; + uint8_t gpio_val; + uint8_t gpio_out; + uint8_t gpio_in; + uint8_t gpio_pull_down; +}; + +static int gpio_ad5592_port_get_raw(const struct device *dev, uint32_t *value) +{ + const struct gpio_ad5592_config *config = dev->config; + struct gpio_ad5592_data *drv_data = dev->data; + uint16_t data; + int ret; + + if (k_is_in_isr()) { + return -EWOULDBLOCK; + } + + ret = mfd_ad5592_read_reg(config->mfd_dev, + AD5592_REG_GPIO_INPUT_EN, drv_data->gpio_in, &data); + if (ret < 0) { + return ret; + } + + *value = (uint32_t)data; + + return 0; +} + +static int gpio_ad5592_port_set_bits_raw(const struct device *dev, + gpio_port_pins_t pins) +{ + struct gpio_ad5592_data *data = dev->data; + const struct gpio_ad5592_config *config = dev->config; + + if (k_is_in_isr()) { + return -EWOULDBLOCK; + } + + data->gpio_val |= (uint8_t)pins; + + return mfd_ad5592_write_reg(config->mfd_dev, AD5592_REG_GPIO_SET, data->gpio_val); +} + +static int gpio_ad5592_port_clear_bits_raw(const struct device *dev, + gpio_port_pins_t pins) +{ + struct gpio_ad5592_data *data = dev->data; + const struct gpio_ad5592_config *config = dev->config; + + if (k_is_in_isr()) { + return -EWOULDBLOCK; + } + + data->gpio_val &= ~(uint8_t)pins; + + return mfd_ad5592_write_reg(config->mfd_dev, AD5592_REG_GPIO_SET, data->gpio_val); +} + +static inline int gpio_ad5592_configure(const struct device *dev, + gpio_pin_t pin, gpio_flags_t flags) +{ + struct gpio_ad5592_data *data = dev->data; + const struct gpio_ad5592_config *config = dev->config; + uint8_t val; + int ret; + + if (k_is_in_isr()) { + return -EWOULDBLOCK; + } + + if (pin >= AD5592_PIN_MAX) { + return -EINVAL; + } + + val = BIT(pin); + if ((flags & GPIO_OUTPUT) != 0U) { + data->gpio_in &= ~val; + data->gpio_out |= val; + + if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) { + ret = gpio_ad5592_port_set_bits_raw( + dev, (gpio_port_pins_t)BIT(pin)); + if (ret < 0) { + return ret; + } + } else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0U) { + ret = gpio_ad5592_port_clear_bits_raw( + dev, (gpio_port_pins_t)BIT(pin)); + if (ret < 0) { + return ret; + } + } + + ret = mfd_ad5592_write_reg(config->mfd_dev, + AD5592_REG_GPIO_OUTPUT_EN, data->gpio_out); + if (ret < 0) { + return ret; + } + + ret = mfd_ad5592_write_reg(config->mfd_dev, + AD5592_REG_GPIO_INPUT_EN, data->gpio_in); + } else if ((flags & GPIO_INPUT) != 0U) { + data->gpio_in |= val; + data->gpio_out &= ~val; + + if ((flags & GPIO_PULL_DOWN) != 0U) { + data->gpio_pull_down |= val; + + ret = mfd_ad5592_write_reg(config->mfd_dev, + AD5592_REG_GPIO_PULLDOWN, + data->gpio_pull_down); + if (ret < 0) { + return ret; + } + } else if ((flags & GPIO_PULL_UP) != 0U) { + return -ENOTSUP; + } + + ret = mfd_ad5592_write_reg(config->mfd_dev, + AD5592_REG_GPIO_OUTPUT_EN, data->gpio_out); + if (ret < 0) { + return ret; + } + + ret = mfd_ad5592_write_reg(config->mfd_dev, + AD5592_REG_GPIO_INPUT_EN, data->gpio_in); + } else { + return -ENOTSUP; + } + + return ret; +} + +static int gpio_ad5592_port_set_masked_raw(const struct device *dev, + gpio_port_pins_t mask, + gpio_port_value_t value) +{ + ARG_UNUSED(dev); + ARG_UNUSED(mask); + ARG_UNUSED(value); + + return -ENOTSUP; +} + +static int gpio_ad5592_port_toggle_bits(const struct device *dev, + gpio_port_pins_t pins) +{ + ARG_UNUSED(dev); + ARG_UNUSED(pins); + + return -ENOTSUP; +} + +static int gpio_ad5592_pin_interrupt_configure(const struct device *dev, + gpio_pin_t pin, + enum gpio_int_mode mode, + enum gpio_int_trig trig) +{ + ARG_UNUSED(dev); + ARG_UNUSED(pin); + ARG_UNUSED(mode); + ARG_UNUSED(trig); + + return -ENOTSUP; +} + +static const struct gpio_driver_api gpio_ad5592_api = { + .pin_configure = gpio_ad5592_configure, + .port_get_raw = gpio_ad5592_port_get_raw, + .port_set_masked_raw = gpio_ad5592_port_set_masked_raw, + .port_set_bits_raw = gpio_ad5592_port_set_bits_raw, + .port_clear_bits_raw = gpio_ad5592_port_clear_bits_raw, + .port_toggle_bits = gpio_ad5592_port_toggle_bits, + .pin_interrupt_configure = gpio_ad5592_pin_interrupt_configure, +}; + +static int gpio_ad5592_init(const struct device *dev) +{ + const struct gpio_ad5592_config *config = dev->config; + + if (!device_is_ready(config->mfd_dev)) { + return -ENODEV; + } + + return 0; +} + +#define GPIO_AD5592_DEFINE(inst) \ + static const struct gpio_ad5592_config gpio_ad5592_config##inst = { \ + .common = { \ + .port_pin_mask = \ + GPIO_PORT_PIN_MASK_FROM_DT_INST(inst), \ + }, \ + .mfd_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ + }; \ + \ + static struct gpio_ad5592_data gpio_ad5592_data##inst; \ + \ + DEVICE_DT_INST_DEFINE(inst, gpio_ad5592_init, NULL, \ + &gpio_ad5592_data##inst, &gpio_ad5592_config##inst, \ + POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, \ + &gpio_ad5592_api); + +DT_INST_FOREACH_STATUS_OKAY(GPIO_AD5592_DEFINE) diff --git a/drivers/gpio/gpio_altera_pio.c b/drivers/gpio/gpio_altera_pio.c new file mode 100644 index 00000000000..d85c63d3245 --- /dev/null +++ b/drivers/gpio/gpio_altera_pio.c @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2023, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT altr_pio_1_0 + +#include +#include +#include +#include + +#define ALTERA_AVALON_PIO_DATA_OFFSET 0x00 +#define ALTERA_AVALON_PIO_DIRECTION_OFFSET 0x04 +#define ALTERA_AVALON_PIO_IRQ_OFFSET 0x08 +#define ALTERA_AVALON_PIO_SET_BITS 0x10 +#define ALTERA_AVALON_PIO_CLEAR_BITS 0x14 + +typedef void (*altera_cfg_func_t)(void); + +struct gpio_altera_config { + struct gpio_driver_config common; + uintptr_t reg_base; + uint32_t irq_num; + uint8_t direction; + uint8_t outset; + uint8_t outclear; + altera_cfg_func_t cfg_func; +}; + +struct gpio_altera_data { + /* gpio_driver_data needs to be first */ + struct gpio_driver_data common; + /* list of callbacks */ + sys_slist_t cb; + struct k_spinlock lock; +}; + +static bool gpio_pin_direction(const struct device *dev, uint32_t pin_mask) +{ + const struct gpio_altera_config *cfg = dev->config; + const int direction = cfg->direction; + uintptr_t reg_base = cfg->reg_base; + uint32_t addr; + uint32_t pin_direction; + + if (pin_mask == 0) { + return -EINVAL; + } + + /* Check if the direction is Bidirectional */ + if (direction != 0) { + return -EINVAL; + } + + addr = reg_base + ALTERA_AVALON_PIO_DIRECTION_OFFSET; + + pin_direction = sys_read32(addr); + + if (!(pin_direction & pin_mask)) { + return false; + } + + return true; +} + +static int gpio_altera_configure(const struct device *dev, + gpio_pin_t pin, gpio_flags_t flags) +{ + const struct gpio_altera_config *cfg = dev->config; + struct gpio_altera_data * const data = dev->data; + const int port_pin_mask = cfg->common.port_pin_mask; + const int direction = cfg->direction; + uintptr_t reg_base = cfg->reg_base; + k_spinlock_key_t key; + uint32_t addr; + + /* Check if pin number is within range */ + if ((port_pin_mask & BIT(pin)) == 0) { + return -EINVAL; + } + + /* Check if the direction is Bidirectional */ + if (direction != 0) { + return -EINVAL; + } + + addr = reg_base + ALTERA_AVALON_PIO_DIRECTION_OFFSET; + + key = k_spin_lock(&data->lock); + + if (flags == GPIO_INPUT) { + sys_clear_bits(addr, BIT(pin)); + } else if (flags == GPIO_OUTPUT) { + sys_set_bits(addr, BIT(pin)); + } else { + return -EINVAL; + } + + k_spin_unlock(&data->lock, key); + + return 0; +} + +static int gpio_altera_port_get_raw(const struct device *dev, uint32_t *value) +{ + const struct gpio_altera_config *cfg = dev->config; + uintptr_t reg_base = cfg->reg_base; + uint32_t addr; + + addr = reg_base + ALTERA_AVALON_PIO_DATA_OFFSET; + + if (value == NULL) { + return -EINVAL; + } + + *value = sys_read32((addr)); + + return 0; +} + +static int gpio_altera_port_set_bits_raw(const struct device *dev, gpio_port_pins_t mask) +{ + const struct gpio_altera_config *cfg = dev->config; + struct gpio_altera_data * const data = dev->data; + const uint8_t outset = cfg->outset; + const int port_pin_mask = cfg->common.port_pin_mask; + uintptr_t reg_base = cfg->reg_base; + uint32_t addr; + k_spinlock_key_t key; + + if ((port_pin_mask & mask) == 0) { + return -EINVAL; + } + + if (!gpio_pin_direction(dev, mask)) { + return -EINVAL; + } + + key = k_spin_lock(&data->lock); + + if (outset) { + addr = reg_base + ALTERA_AVALON_PIO_SET_BITS; + sys_write32(mask, addr); + } else { + addr = reg_base + ALTERA_AVALON_PIO_DATA_OFFSET; + sys_set_bits(addr, mask); + } + + k_spin_unlock(&data->lock, key); + + return 0; +} + +static int gpio_altera_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t mask) +{ + const struct gpio_altera_config *cfg = dev->config; + struct gpio_altera_data * const data = dev->data; + const uint8_t outclear = cfg->outclear; + const int port_pin_mask = cfg->common.port_pin_mask; + uintptr_t reg_base = cfg->reg_base; + uint32_t addr; + k_spinlock_key_t key; + + /* Check if mask range within 32 */ + if ((port_pin_mask & mask) == 0) { + return -EINVAL; + } + + if (!gpio_pin_direction(dev, mask)) { + return -EINVAL; + } + + key = k_spin_lock(&data->lock); + + if (outclear) { + addr = reg_base + ALTERA_AVALON_PIO_CLEAR_BITS; + sys_write32(mask, addr); + } else { + addr = reg_base + ALTERA_AVALON_PIO_DATA_OFFSET; + sys_clear_bits(addr, mask); + } + + k_spin_unlock(&data->lock, key); + + return 0; +} + +static int gpio_init(const struct device *dev) +{ + const struct gpio_altera_config *cfg = dev->config; + + /* Configure GPIO device */ + cfg->cfg_func(); + + return 0; +} + +static int gpio_altera_pin_interrupt_configure(const struct device *dev, + gpio_pin_t pin, + enum gpio_int_mode mode, + enum gpio_int_trig trig) +{ + ARG_UNUSED(trig); + + const struct gpio_altera_config *cfg = dev->config; + struct gpio_altera_data * const data = dev->data; + uintptr_t reg_base = cfg->reg_base; + const int port_pin_mask = cfg->common.port_pin_mask; + uint32_t addr; + k_spinlock_key_t key; + + /* Check if pin number is within range */ + if ((port_pin_mask & BIT(pin)) == 0) { + return -EINVAL; + } + + if (!gpio_pin_direction(dev, BIT(pin))) { + return -EINVAL; + } + + addr = reg_base + ALTERA_AVALON_PIO_IRQ_OFFSET; + + key = k_spin_lock(&data->lock); + + switch (mode) { + case GPIO_INT_MODE_DISABLED: + /* Disable interrupt of pin */ + sys_clear_bits(addr, BIT(pin)); + irq_disable(cfg->irq_num); + break; + case GPIO_INT_MODE_LEVEL: + case GPIO_INT_MODE_EDGE: + /* Enable interrupt of pin */ + sys_set_bits(addr, BIT(pin)); + irq_enable(cfg->irq_num); + break; + default: + return -EINVAL; + } + + k_spin_unlock(&data->lock, key); + + return 0; +} + +static int gpio_altera_manage_callback(const struct device *dev, + struct gpio_callback *callback, + bool set) +{ + + struct gpio_altera_data * const data = dev->data; + + return gpio_manage_callback(&data->cb, callback, set); +} + +static void gpio_altera_irq_handler(const struct device *dev) +{ + const struct gpio_altera_config *cfg = dev->config; + struct gpio_altera_data *data = dev->data; + uintptr_t reg_base = cfg->reg_base; + uint32_t port_value; + uint32_t addr; + k_spinlock_key_t key; + + addr = reg_base + ALTERA_AVALON_PIO_IRQ_OFFSET; + + key = k_spin_lock(&data->lock); + + port_value = sys_read32(addr); + + sys_clear_bits(addr, port_value); + + k_spin_unlock(&data->lock, key); + + /* Call the corresponding callback registered for the pin */ + gpio_fire_callbacks(&data->cb, dev, port_value); +} + +static const struct gpio_driver_api gpio_altera_driver_api = { + .pin_configure = gpio_altera_configure, + .port_get_raw = gpio_altera_port_get_raw, + .port_set_masked_raw = NULL, + .port_set_bits_raw = gpio_altera_port_set_bits_raw, + .port_clear_bits_raw = gpio_altera_port_clear_bits_raw, + .port_toggle_bits = NULL, + .pin_interrupt_configure = gpio_altera_pin_interrupt_configure, + .manage_callback = gpio_altera_manage_callback +}; + +#define GPIO_CFG_IRQ(idx, n) \ + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, idx, irq), \ + COND_CODE_1(DT_INST_IRQ_HAS_CELL(n, priority), \ + DT_INST_IRQ(n, priority), (0)), gpio_altera_irq_handler, \ + DEVICE_DT_INST_GET(n), 0); \ + +#define CREATE_GPIO_DEVICE(n) \ + static void gpio_altera_cfg_func_##n(void); \ + static struct gpio_altera_data gpio_altera_data_##n; \ + static struct gpio_altera_config gpio_config_##n = { \ + .common = { \ + .port_pin_mask = \ + GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \ + }, \ + .reg_base = DT_INST_REG_ADDR(n), \ + .direction = DT_INST_ENUM_IDX(n, direction), \ + .irq_num = COND_CODE_1(DT_INST_IRQ_HAS_IDX(n, 0), (DT_INST_IRQN(n)), (0)),\ + .cfg_func = gpio_altera_cfg_func_##n, \ + .outset = DT_INST_PROP(n, outset), \ + .outclear = DT_INST_PROP(n, outclear), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, \ + gpio_init, \ + NULL, \ + &gpio_altera_data_##n, \ + &gpio_config_##n, \ + POST_KERNEL, \ + CONFIG_GPIO_INIT_PRIORITY, \ + &gpio_altera_driver_api); \ + \ + static void gpio_altera_cfg_func_##n(void) \ + { \ + LISTIFY(DT_NUM_IRQS(DT_DRV_INST(n)), GPIO_CFG_IRQ, (), n)\ + } + +DT_INST_FOREACH_STATUS_OKAY(CREATE_GPIO_DEVICE) diff --git a/drivers/gpio/gpio_axp192.c b/drivers/gpio/gpio_axp192.c index 95625d99dfe..cf594c25aba 100644 --- a/drivers/gpio/gpio_axp192.c +++ b/drivers/gpio/gpio_axp192.c @@ -159,7 +159,18 @@ static int gpio_axp192_port_toggle_bits(const struct device *dev, gpio_port_pins return ret; } -#ifdef CONFIG_GPIO_GET_CONFIG +static int gpio_axp192_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, + enum gpio_int_mode mode, enum gpio_int_trig trig) +{ + ARG_UNUSED(dev); + ARG_UNUSED(pin); + ARG_UNUSED(mode); + ARG_UNUSED(trig); + + return -ENOTSUP; +} + +#if defined(CONFIG_GPIO_GET_CONFIG) || defined(CONFIG_GPIO_GET_DIRECTION) static int gpio_axp192_get_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t *out_flags) { const struct gpio_axp192_config *config = dev->config; @@ -265,6 +276,7 @@ static const struct gpio_driver_api gpio_axp192_api = { .port_set_bits_raw = gpio_axp192_port_set_bits_raw, .port_clear_bits_raw = gpio_axp192_port_clear_bits_raw, .port_toggle_bits = gpio_axp192_port_toggle_bits, + .pin_interrupt_configure = gpio_axp192_pin_interrupt_configure, .manage_callback = gpio_axp192_manage_callback, #ifdef CONFIG_GPIO_GET_DIRECTION .port_get_direction = gpio_axp192_port_get_direction, diff --git a/drivers/gpio/gpio_b91.c b/drivers/gpio/gpio_b91.c index 45a82f71620..bc73f9db9f5 100644 --- a/drivers/gpio/gpio_b91.c +++ b/drivers/gpio/gpio_b91.c @@ -78,7 +78,7 @@ struct gpio_b91_t { struct gpio_b91_config { struct gpio_driver_config common; uint32_t gpio_base; - uint8_t irq_num; + uint32_t irq_num; uint8_t irq_priority; void (*pirq_connect)(void); }; diff --git a/drivers/gpio/gpio_bcm2711.c b/drivers/gpio/gpio_bcm2711.c new file mode 100644 index 00000000000..a4e4a31e7c9 --- /dev/null +++ b/drivers/gpio/gpio_bcm2711.c @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2023 Chen Xingyu + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT brcm_bcm2711_gpio + +#include +#include +#include +#include +#include + +#define GPIO_REG_GROUP(n, cnt) (n / cnt) +#define GPIO_REG_SHIFT(n, cnt, bits) ((n % cnt) * bits) + +#define GPFSEL(base, n) (base + 0x00 + 0x04 * n) +#define GPSET(base, n) (base + 0x1C + 0x04 * n) +#define GPCLR(base, n) (base + 0x28 + 0x04 * n) +#define GPLEV(base, n) (base + 0x34 + 0x04 * n) +#define GPEDS(base, n) (base + 0x40 + 0x04 * n) +#define GPREN(base, n) (base + 0x4C + 0x04 * n) +#define GPFEN(base, n) (base + 0x58 + 0x04 * n) +#define GPHEN(base, n) (base + 0x64 + 0x04 * n) +#define GPLEN(base, n) (base + 0x70 + 0x04 * n) +#define GPAREN(base, n) (base + 0x7C + 0x04 * n) +#define GPAFEN(base, n) (base + 0x88 + 0x04 * n) +#define GPPULL(base, n) (base + 0xE4 + 0x04 * n) + +#define FSEL_GROUPS (10) +#define FSEL_BITS (3) +#define FSEL_OUTPUT (0x1) + +#define IO_GROUPS (32) +#define IO_BITS (1) + +#define PULL_GROUPS (16) +#define PULL_BITS (2) +#define PULL_UP (0x1) +#define PULL_DOWN (0x2) + +#define DEV_CFG(dev) ((const struct gpio_bcm2711_config *const)(dev)->config) +#define DEV_DATA(dev) ((struct gpio_bcm2711_data *const)(dev)->data) + +#define RPI_PIN_NUM(dev, n) (DEV_CFG(dev)->offset + n) + +#define FROM_U64(val, idx) ((uint32_t)((val >> (idx * 32)) & UINT32_MAX)) + +struct gpio_bcm2711_config { + struct gpio_driver_config common; + + DEVICE_MMIO_NAMED_ROM(reg_base); + + void (*irq_config_func)(void); + + uint8_t offset; + uint8_t ngpios; +}; + +struct gpio_bcm2711_data { + struct gpio_driver_data common; + + DEVICE_MMIO_NAMED_RAM(reg_base); + mem_addr_t base; + + sys_slist_t cb; +}; + +static int gpio_bcm2711_pin_configure(const struct device *port, gpio_pin_t pin, gpio_flags_t flags) +{ + struct gpio_bcm2711_data *data = DEV_DATA(port); + uint32_t group; + uint32_t shift; + uint32_t regval; + + if (flags & GPIO_OPEN_DRAIN) { + return -ENOTSUP; + } + + /* Set direction */ + { + group = GPIO_REG_GROUP(RPI_PIN_NUM(port, pin), FSEL_GROUPS); + shift = GPIO_REG_SHIFT(RPI_PIN_NUM(port, pin), FSEL_GROUPS, FSEL_BITS); + + regval = sys_read32(GPFSEL(data->base, group)); + regval &= ~(BIT_MASK(FSEL_BITS) << shift); + if (flags & GPIO_OUTPUT) { + regval |= (FSEL_OUTPUT << shift); + } + sys_write32(regval, GPFSEL(data->base, group)); + } + + /* Set output level */ + if (flags & GPIO_OUTPUT) { + group = GPIO_REG_GROUP(RPI_PIN_NUM(port, pin), IO_GROUPS); + shift = GPIO_REG_SHIFT(RPI_PIN_NUM(port, pin), IO_GROUPS, IO_BITS); + + if (flags & GPIO_OUTPUT_INIT_HIGH) { + regval = sys_read32(GPSET(data->base, group)); + regval |= BIT(shift); + sys_write32(regval, GPSET(data->base, group)); + } else if (flags & GPIO_OUTPUT_INIT_LOW) { + regval = sys_read32(GPCLR(data->base, group)); + regval |= BIT(shift); + sys_write32(regval, GPCLR(data->base, group)); + } + } + + /* Set pull */ + { + group = GPIO_REG_GROUP(RPI_PIN_NUM(port, pin), PULL_GROUPS); + shift = GPIO_REG_SHIFT(RPI_PIN_NUM(port, pin), PULL_GROUPS, PULL_BITS); + + regval = sys_read32(GPPULL(data->base, group)); + regval &= ~(BIT_MASK(PULL_BITS) << shift); + if (flags & GPIO_PULL_UP) { + regval |= (PULL_UP << shift); + } else if (flags & GPIO_PULL_DOWN) { + regval |= (PULL_DOWN << shift); + } + sys_write32(regval, GPPULL(data->base, group)); + } + + return 0; +} + +static int gpio_bcm2711_port_get_raw(const struct device *port, gpio_port_value_t *value) +{ + const struct gpio_bcm2711_config *cfg = DEV_CFG(port); + struct gpio_bcm2711_data *data = DEV_DATA(port); + uint64_t regval; + + regval = ((uint64_t)sys_read32(GPLEV(data->base, 0))) | + ((uint64_t)sys_read32(GPLEV(data->base, 1)) << 32); + + *value = (regval >> cfg->offset) & BIT_MASK(cfg->ngpios); + + return 0; +} + +static int gpio_bcm2711_port_set_masked_raw(const struct device *port, gpio_port_pins_t mask, + gpio_port_value_t value) +{ + const struct gpio_bcm2711_config *cfg = DEV_CFG(port); + struct gpio_bcm2711_data *data = DEV_DATA(port); + uint64_t regval, regmask; + uint64_t set, clr; + + value &= BIT_MASK(cfg->ngpios); + mask &= BIT_MASK(cfg->ngpios); + + regval = (uint64_t)value << cfg->offset; + regmask = (uint64_t)mask << cfg->offset; + + set = regval & regmask; + clr = regval ^ regmask; + + sys_write32(FROM_U64(set, 0), GPSET(data->base, 0)); + sys_write32(FROM_U64(clr, 0), GPCLR(data->base, 0)); + sys_write32(FROM_U64(set, 1), GPSET(data->base, 1)); + sys_write32(FROM_U64(clr, 1), GPCLR(data->base, 1)); + + return 0; +} + +static int gpio_bcm2711_port_set_bits_raw(const struct device *port, gpio_port_pins_t pins) +{ + const struct gpio_bcm2711_config *cfg = DEV_CFG(port); + struct gpio_bcm2711_data *data = DEV_DATA(port); + uint64_t regval; + + regval = ((uint64_t)pins & BIT_MASK(cfg->ngpios)) << cfg->offset; + + sys_write32(FROM_U64(regval, 0), GPSET(data->base, 0)); + sys_write32(FROM_U64(regval, 1), GPSET(data->base, 1)); + + return 0; +} + +static int gpio_bcm2711_port_clear_bits_raw(const struct device *port, gpio_port_pins_t pins) +{ + const struct gpio_bcm2711_config *cfg = DEV_CFG(port); + struct gpio_bcm2711_data *data = DEV_DATA(port); + uint64_t regval; + + regval = ((uint64_t)pins & BIT_MASK(cfg->ngpios)) << cfg->offset; + + sys_write32(FROM_U64(regval, 0), GPCLR(data->base, 0)); + sys_write32(FROM_U64(regval, 1), GPCLR(data->base, 1)); + + return 0; +} + +static int gpio_bcm2711_port_toggle_bits(const struct device *port, gpio_port_pins_t pins) +{ + const struct gpio_bcm2711_config *cfg = DEV_CFG(port); + struct gpio_bcm2711_data *data = DEV_DATA(port); + uint64_t regval, regmask; + uint64_t set, clr; + + regval = ((uint64_t)sys_read32(GPLEV(data->base, 0))) | + ((uint64_t)sys_read32(GPLEV(data->base, 1)) << 32); + + regmask = ((uint64_t)pins & BIT_MASK(cfg->ngpios)) << cfg->offset; + + set = regval ^ regmask; + clr = regval & regmask; + + sys_write32(FROM_U64(set, 0), GPSET(data->base, 0)); + sys_write32(FROM_U64(clr, 0), GPCLR(data->base, 0)); + sys_write32(FROM_U64(set, 1), GPSET(data->base, 1)); + sys_write32(FROM_U64(clr, 1), GPCLR(data->base, 1)); + + return 0; +} + +static int gpio_bcm2711_pin_interrupt_configure(const struct device *port, gpio_pin_t pin, + enum gpio_int_mode mode, enum gpio_int_trig trig) +{ + struct gpio_bcm2711_data *data = DEV_DATA(port); + uint32_t group; + uint32_t shift; + uint32_t regval; + + group = GPIO_REG_GROUP(RPI_PIN_NUM(port, pin), IO_GROUPS); + shift = GPIO_REG_SHIFT(RPI_PIN_NUM(port, pin), IO_GROUPS, IO_BITS); + + /* Clear all detections first */ + + regval = sys_read32(GPREN(data->base, group)); + regval &= ~BIT(shift); + sys_write32(regval, GPREN(data->base, group)); + + regval = sys_read32(GPFEN(data->base, group)); + regval &= ~BIT(shift); + sys_write32(regval, GPFEN(data->base, group)); + + regval = sys_read32(GPHEN(data->base, group)); + regval &= ~BIT(shift); + sys_write32(regval, GPHEN(data->base, group)); + + regval = sys_read32(GPLEN(data->base, group)); + regval &= ~BIT(shift); + sys_write32(regval, GPLEN(data->base, group)); + + regval = sys_read32(GPAREN(data->base, group)); + regval &= ~BIT(shift); + sys_write32(regval, GPAREN(data->base, group)); + + regval = sys_read32(GPAFEN(data->base, group)); + regval &= ~BIT(shift); + sys_write32(regval, GPAFEN(data->base, group)); + + if (mode == GPIO_INT_MODE_LEVEL) { + if (trig & GPIO_INT_LOW_0) { + regval = sys_read32(GPLEN(data->base, group)); + regval |= BIT(shift); + sys_write32(regval, GPLEN(data->base, group)); + } + if (trig & GPIO_INT_HIGH_1) { + regval = sys_read32(GPHEN(data->base, group)); + regval |= BIT(shift); + sys_write32(regval, GPHEN(data->base, group)); + } + } else if (mode == GPIO_INT_MODE_EDGE) { + if (trig & GPIO_INT_LOW_0) { + regval = sys_read32(GPAFEN(data->base, group)); + regval |= BIT(shift); + sys_write32(regval, GPAFEN(data->base, group)); + } + if (trig & GPIO_INT_HIGH_1) { + regval = sys_read32(GPAREN(data->base, group)); + regval |= BIT(shift); + sys_write32(regval, GPAREN(data->base, group)); + } + } + + return 0; +} + +static int gpio_bcm2711_manage_callback(const struct device *port, struct gpio_callback *cb, + bool set) +{ + struct gpio_bcm2711_data *data = DEV_DATA(port); + + return gpio_manage_callback(&data->cb, cb, set); +} + +static void gpio_bcm2711_isr(const struct device *port) +{ + const struct gpio_bcm2711_config *cfg = DEV_CFG(port); + struct gpio_bcm2711_data *data = DEV_DATA(port); + uint64_t regval; + uint32_t pins; + + regval = ((uint64_t)sys_read32(GPEDS(data->base, 0))) | + ((uint64_t)sys_read32(GPEDS(data->base, 1)) << 32); + + regval &= BIT_MASK(cfg->ngpios) << cfg->offset; + + pins = (uint32_t)(regval >> cfg->offset); + gpio_fire_callbacks(&data->cb, port, pins); + + /* Write to clear */ + sys_write32(FROM_U64(regval, 0), GPEDS(data->base, 0)); + sys_write32(FROM_U64(regval, 1), GPEDS(data->base, 1)); +} + +int gpio_bcm2711_init(const struct device *port) +{ + const struct gpio_bcm2711_config *cfg = DEV_CFG(port); + struct gpio_bcm2711_data *data = DEV_DATA(port); + + DEVICE_MMIO_NAMED_MAP(port, reg_base, K_MEM_CACHE_NONE); + data->base = DEVICE_MMIO_NAMED_GET(port, reg_base); + + cfg->irq_config_func(); + + return 0; +} + +static const struct gpio_driver_api gpio_bcm2711_api = { + .pin_configure = gpio_bcm2711_pin_configure, + .port_get_raw = gpio_bcm2711_port_get_raw, + .port_set_masked_raw = gpio_bcm2711_port_set_masked_raw, + .port_set_bits_raw = gpio_bcm2711_port_set_bits_raw, + .port_clear_bits_raw = gpio_bcm2711_port_clear_bits_raw, + .port_toggle_bits = gpio_bcm2711_port_toggle_bits, + .pin_interrupt_configure = gpio_bcm2711_pin_interrupt_configure, + .manage_callback = gpio_bcm2711_manage_callback, +}; + +#define GPIO_BCM2711_INST(n) \ + static struct gpio_bcm2711_data gpio_bcm2711_data_##n; \ + \ + static void gpio_bcm2711_irq_config_func_##n(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), gpio_bcm2711_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + } \ + \ + static const struct gpio_bcm2711_config gpio_bcm2711_cfg_##n = { \ + .common = {.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(0)}, \ + DEVICE_MMIO_NAMED_ROM_INIT(reg_base, DT_INST_PARENT(n)), \ + .irq_config_func = gpio_bcm2711_irq_config_func_##n, \ + .offset = DT_INST_REG_ADDR(n), \ + .ngpios = DT_INST_PROP(n, ngpios), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, gpio_bcm2711_init, NULL, &gpio_bcm2711_data_##n, \ + &gpio_bcm2711_cfg_##n, PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, \ + &gpio_bcm2711_api); + +DT_INST_FOREACH_STATUS_OKAY(GPIO_BCM2711_INST) diff --git a/drivers/gpio/gpio_davinci.c b/drivers/gpio/gpio_davinci.c index 5726ed1bf32..205e0112cde 100644 --- a/drivers/gpio/gpio_davinci.c +++ b/drivers/gpio/gpio_davinci.c @@ -17,10 +17,14 @@ #include #include #include +#include +#include + +LOG_MODULE_REGISTER(gpio_davinci, CONFIG_GPIO_LOG_LEVEL); /* Helper Macros for GPIO */ #define DEV_CFG(dev) \ - ((const struct gpio_davinci_config * const)((dev)->config)) + ((const struct gpio_davinci_config *)((dev)->config)) #define DEV_DATA(dev) ((struct gpio_davinci_data *)(dev)->data) #define DEV_GPIO_CFG_BASE(dev) \ ((struct gpio_davinci_regs *)DEVICE_MMIO_NAMED_GET(dev, port_base)) @@ -55,6 +59,7 @@ struct gpio_davinci_config { DEVICE_MMIO_NAMED_ROM(port_base); uint32_t port_num; + const struct pinctrl_dev_config *pcfg; }; static int gpio_davinci_configure(const struct device *dev, gpio_pin_t pin, @@ -76,11 +81,9 @@ static int gpio_davinci_configure(const struct device *dev, gpio_pin_t pin, } else { regs->clr_data = BIT(pin); } - - regs->dir &= (~(BIT(pin))); - + regs->dir &= ~(BIT(pin)); } else { - regs->dir |= (BIT(pin)); + regs->dir |= BIT(pin); } return 0; @@ -149,6 +152,7 @@ static int gpio_davinci_init(const struct device *dev) { const struct gpio_davinci_config *config = DEV_CFG(dev); volatile struct gpio_davinci_regs *regs = DEV_GPIO_CFG_BASE(dev); + int ret; DEVICE_MMIO_NAMED_MAP(dev, port_base, K_MEM_CACHE_NONE); @@ -156,44 +160,43 @@ static int gpio_davinci_init(const struct device *dev) config->bank_config(dev); + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + LOG_ERR("failed to apply pinctrl"); + return ret; + } return 0; } -#define GPIO_DAVINCI_INIT_FUNC(n) \ - static void gpio_davinci_bank_##n##_config(const struct device *dev) \ - { \ +#define GPIO_DAVINCI_INIT_FUNC(n) \ + static void gpio_davinci_bank_##n##_config(const struct device *dev) \ + { \ volatile struct gpio_davinci_regs *regs = DEV_GPIO_CFG_BASE(dev); \ - ARG_UNUSED(regs); \ + ARG_UNUSED(regs); \ } -#define GPIO_DAVINCI_DEVICE_INIT(n) \ - DEVICE_DT_INST_DEFINE(n, &gpio_davinci_##n##_init, \ - NULL, &gpio_davinci_##n##_data, \ - &gpio_davinci_##n##_config, \ - POST_KERNEL, CONFIG_GPIO_INIT_PRIORITY, \ - &api_funcs) - -#define GPIO_DAVINCI_INIT(n) \ - \ - GPIO_DAVINCI_INIT_FUNC(n) \ - static const struct gpio_davinci_config gpio_davinci_##n##_config = { \ - .bank_config = gpio_davinci_bank_##n##_config, \ - .common = { \ - .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \ - }, \ - DEVICE_MMIO_NAMED_ROM_INIT(port_base, DT_DRV_INST(n)), \ - .port_num = n \ - }; \ - \ - static struct gpio_davinci_data gpio_davinci_##n##_data; \ - \ - DEVICE_DT_INST_DEFINE(n, \ - &gpio_davinci_init, \ - NULL, \ - &gpio_davinci_##n##_data, \ - &gpio_davinci_##n##_config, \ - PRE_KERNEL_2, \ - CONFIG_GPIO_INIT_PRIORITY, \ +#define GPIO_DAVINCI_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + GPIO_DAVINCI_INIT_FUNC(n); \ + static const struct gpio_davinci_config gpio_davinci_##n##_config = { \ + .bank_config = gpio_davinci_bank_##n##_config, \ + .common = { \ + .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \ + }, \ + DEVICE_MMIO_NAMED_ROM_INIT(port_base, DT_DRV_INST(n)), \ + .port_num = n, \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + }; \ + \ + static struct gpio_davinci_data gpio_davinci_##n##_data; \ + \ + DEVICE_DT_INST_DEFINE(n, \ + &gpio_davinci_init, \ + NULL, \ + &gpio_davinci_##n##_data, \ + &gpio_davinci_##n##_config, \ + PRE_KERNEL_2, \ + CONFIG_GPIO_INIT_PRIORITY, \ &gpio_davinci_driver_api); DT_INST_FOREACH_STATUS_OKAY(GPIO_DAVINCI_INIT) diff --git a/drivers/gpio/gpio_handlers.c b/drivers/gpio/gpio_handlers.c index ce64fc87bda..99fbc6f45d9 100644 --- a/drivers/gpio/gpio_handlers.c +++ b/drivers/gpio/gpio_handlers.c @@ -5,13 +5,13 @@ */ #include -#include +#include static inline int z_vrfy_gpio_pin_configure(const struct device *port, gpio_pin_t pin, gpio_flags_t flags) { - Z_OOPS(Z_SYSCALL_DRIVER_GPIO(port, pin_configure)); + K_OOPS(K_SYSCALL_DRIVER_GPIO(port, pin_configure)); return z_impl_gpio_pin_configure((const struct device *)port, pin, flags); @@ -23,8 +23,8 @@ static inline int z_vrfy_gpio_pin_get_config(const struct device *port, gpio_pin_t pin, gpio_flags_t *flags) { - Z_OOPS(Z_SYSCALL_DRIVER_GPIO(port, pin_get_config)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(flags, sizeof(gpio_flags_t))); + K_OOPS(K_SYSCALL_DRIVER_GPIO(port, pin_get_config)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(flags, sizeof(gpio_flags_t))); return z_impl_gpio_pin_get_config(port, pin, flags); } @@ -34,8 +34,8 @@ static inline int z_vrfy_gpio_pin_get_config(const struct device *port, static inline int z_vrfy_gpio_port_get_raw(const struct device *port, gpio_port_value_t *value) { - Z_OOPS(Z_SYSCALL_DRIVER_GPIO(port, port_get_raw)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(value, sizeof(gpio_port_value_t))); + K_OOPS(K_SYSCALL_DRIVER_GPIO(port, port_get_raw)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(value, sizeof(gpio_port_value_t))); return z_impl_gpio_port_get_raw((const struct device *)port, (gpio_port_value_t *)value); } @@ -45,7 +45,7 @@ static inline int z_vrfy_gpio_port_set_masked_raw(const struct device *port, gpio_port_pins_t mask, gpio_port_value_t value) { - Z_OOPS(Z_SYSCALL_DRIVER_GPIO(port, port_set_masked_raw)); + K_OOPS(K_SYSCALL_DRIVER_GPIO(port, port_set_masked_raw)); return z_impl_gpio_port_set_masked_raw((const struct device *)port, mask, value); @@ -55,7 +55,7 @@ static inline int z_vrfy_gpio_port_set_masked_raw(const struct device *port, static inline int z_vrfy_gpio_port_set_bits_raw(const struct device *port, gpio_port_pins_t pins) { - Z_OOPS(Z_SYSCALL_DRIVER_GPIO(port, port_set_bits_raw)); + K_OOPS(K_SYSCALL_DRIVER_GPIO(port, port_set_bits_raw)); return z_impl_gpio_port_set_bits_raw((const struct device *)port, pins); } @@ -64,7 +64,7 @@ static inline int z_vrfy_gpio_port_set_bits_raw(const struct device *port, static inline int z_vrfy_gpio_port_clear_bits_raw(const struct device *port, gpio_port_pins_t pins) { - Z_OOPS(Z_SYSCALL_DRIVER_GPIO(port, port_clear_bits_raw)); + K_OOPS(K_SYSCALL_DRIVER_GPIO(port, port_clear_bits_raw)); return z_impl_gpio_port_clear_bits_raw((const struct device *)port, pins); } @@ -73,7 +73,7 @@ static inline int z_vrfy_gpio_port_clear_bits_raw(const struct device *port, static inline int z_vrfy_gpio_port_toggle_bits(const struct device *port, gpio_port_pins_t pins) { - Z_OOPS(Z_SYSCALL_DRIVER_GPIO(port, port_toggle_bits)); + K_OOPS(K_SYSCALL_DRIVER_GPIO(port, port_toggle_bits)); return z_impl_gpio_port_toggle_bits((const struct device *)port, pins); } #include @@ -82,7 +82,7 @@ static inline int z_vrfy_gpio_pin_interrupt_configure(const struct device *port, gpio_pin_t pin, gpio_flags_t flags) { - Z_OOPS(Z_SYSCALL_DRIVER_GPIO(port, pin_interrupt_configure)); + K_OOPS(K_SYSCALL_DRIVER_GPIO(port, pin_interrupt_configure)); return z_impl_gpio_pin_interrupt_configure((const struct device *)port, pin, flags); @@ -91,7 +91,7 @@ static inline int z_vrfy_gpio_pin_interrupt_configure(const struct device *port, static inline int z_vrfy_gpio_get_pending_int(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_GPIO(dev, get_pending_int)); + K_OOPS(K_SYSCALL_DRIVER_GPIO(dev, get_pending_int)); return z_impl_gpio_get_pending_int((const struct device *)dev); } @@ -102,14 +102,14 @@ static inline int z_vrfy_gpio_port_get_direction(const struct device *dev, gpio_ gpio_port_pins_t *inputs, gpio_port_pins_t *outputs) { - Z_OOPS(Z_SYSCALL_DRIVER_GPIO(dev, port_get_direction)); + K_OOPS(K_SYSCALL_DRIVER_GPIO(dev, port_get_direction)); if (inputs != NULL) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(inputs, sizeof(gpio_port_pins_t))); + K_OOPS(K_SYSCALL_MEMORY_WRITE(inputs, sizeof(gpio_port_pins_t))); } if (outputs != NULL) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(outputs, sizeof(gpio_port_pins_t))); + K_OOPS(K_SYSCALL_MEMORY_WRITE(outputs, sizeof(gpio_port_pins_t))); } return z_impl_gpio_port_get_direction(dev, map, inputs, outputs); diff --git a/drivers/gpio/gpio_mchp_xec.c b/drivers/gpio/gpio_mchp_xec.c index f01aefd6d2d..86d9f2a5d7a 100644 --- a/drivers/gpio/gpio_mchp_xec.c +++ b/drivers/gpio/gpio_mchp_xec.c @@ -66,7 +66,6 @@ static int gpio_xec_configure(const struct device *dev, __IO uint32_t *current_pcr1; uint32_t pcr1 = 0U; uint32_t mask = 0U; - __IO uint32_t *gpio_out_reg = GPIO_OUT_BASE(config); /* Validate pin number range in terms of current port */ if ((valid_ctrl_masks[config->port_num] & BIT(pin)) == 0U) { @@ -88,7 +87,22 @@ static int gpio_xec_configure(const struct device *dev, mask |= MCHP_GPIO_CTRL_DIR_MASK; mask |= MCHP_GPIO_CTRL_INPAD_DIS_MASK; mask |= MCHP_GPIO_CTRL_PWRG_MASK; - pcr1 |= MCHP_GPIO_CTRL_DIR_INPUT; + mask |= MCHP_GPIO_CTRL_AOD_MASK; + + current_pcr1 = config->pcr1_base + pin; + + if (flags == GPIO_DISCONNECTED) { + pcr1 |= MCHP_GPIO_CTRL_PWRG_OFF; + *current_pcr1 = (*current_pcr1 & ~mask) | pcr1; + return 0; + } + + pcr1 = MCHP_GPIO_CTRL_PWRG_VTR_IO; + + /* Always enable input pad */ + if (*current_pcr1 & BIT(MCHP_GPIO_CTRL_INPAD_DIS_POS)) { + *current_pcr1 &= ~BIT(MCHP_GPIO_CTRL_INPAD_DIS_POS); + } /* Figure out the pullup/pulldown configuration and keep it in the * pcr1 variable @@ -114,38 +128,33 @@ static int gpio_xec_configure(const struct device *dev, pcr1 |= MCHP_GPIO_CTRL_BUFT_PUSHPULL; } - /* Use GPIO output register to control pin output, instead of - * using the control register (=> alternate output disable). - */ - mask |= MCHP_GPIO_CTRL_AOD_MASK; - pcr1 |= MCHP_GPIO_CTRL_AOD_DIS; - - /* Make sure disconnected on first control register write */ - if (flags == GPIO_DISCONNECTED) { - pcr1 |= MCHP_GPIO_CTRL_PWRG_OFF; - } - - /* Now write contents of pcr1 variable to the PCR1 register that - * corresponds to the GPIO being configured. - * AOD is 1 and direction is input. HW will allow use to set the - * GPIO parallel output bit for this pin and with the pin direction - * as input no glitch will occur. - */ - current_pcr1 = config->pcr1_base + pin; - *current_pcr1 = (*current_pcr1 & ~mask) | pcr1; - if ((flags & GPIO_OUTPUT) != 0U) { + mask |= MCHP_GPIO_CTRL_OUTV_HI; if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) { - *gpio_out_reg |= BIT(pin); + pcr1 |= BIT(MCHP_GPIO_CTRL_OUTVAL_POS); } else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0U) { - *gpio_out_reg &= ~BIT(pin); + pcr1 &= ~BIT(MCHP_GPIO_CTRL_OUTVAL_POS); + } else { /* Copy current input state to output state */ + if ((*current_pcr1 & MCHP_GPIO_CTRL_PWRG_MASK) == + MCHP_GPIO_CTRL_PWRG_OFF) { + *current_pcr1 = (*current_pcr1 & + ~MCHP_GPIO_CTRL_PWRG_MASK) | + MCHP_GPIO_CTRL_PWRG_VTR_IO; + } + if (*current_pcr1 & BIT(MCHP_GPIO_CTRL_INPAD_VAL_POS)) { + pcr1 |= BIT(MCHP_GPIO_CTRL_OUTVAL_POS); + } else { + pcr1 &= ~BIT(MCHP_GPIO_CTRL_OUTVAL_POS); + } } - mask = MCHP_GPIO_CTRL_DIR_MASK; - pcr1 = MCHP_GPIO_CTRL_DIR_OUTPUT; - *current_pcr1 = (*current_pcr1 & ~mask) | pcr1; + pcr1 |= MCHP_GPIO_CTRL_DIR_OUTPUT; } + *current_pcr1 = (*current_pcr1 & ~mask) | pcr1; + /* Control output bit becomes ready only and parallel output r/w */ + *current_pcr1 = *current_pcr1 | BIT(MCHP_GPIO_CTRL_AOD_POS); + return 0; } diff --git a/drivers/gpio/gpio_mcux_lpc.c b/drivers/gpio/gpio_mcux_lpc.c index ae0ef1bf796..297e83930f2 100644 --- a/drivers/gpio/gpio_mcux_lpc.c +++ b/drivers/gpio/gpio_mcux_lpc.c @@ -119,6 +119,12 @@ static int gpio_mcux_lpc_configure(const struct device *dev, gpio_pin_t pin, } else if ((flags & GPIO_PULL_DOWN) != 0) { *pinconfig |= IOCON_PIO_MODE_PULLDOWN; } +#endif + } else { +#ifdef IOPCTL /* RT600 and RT500 series */ + *pinconfig &= ~IOPCTL_PIO_PUPD_EN; +#else /* LPC SOCs */ + *pinconfig &= ~(IOCON_PIO_MODE_PULLUP|IOCON_PIO_MODE_PULLDOWN); #endif } diff --git a/drivers/gpio/gpio_nct38xx.c b/drivers/gpio/gpio_nct38xx.c index 82c8663fe15..a4949f1f9bb 100644 --- a/drivers/gpio/gpio_nct38xx.c +++ b/drivers/gpio/gpio_nct38xx.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -17,6 +18,27 @@ #include LOG_MODULE_REGISTER(gpio_ntc38xx, CONFIG_GPIO_LOG_LEVEL); +/* Driver config */ +struct gpio_nct38xx_config { + /* Multi-function device, parent to the NCT38xx GPIO controller */ + const struct device *mfd; + /* GPIO ports */ + const struct device **sub_gpio_dev; + uint8_t sub_gpio_port_num; + /* Alert handler */ + const struct device *alert_dev; +}; + +/* Driver data */ +struct gpio_nct38xx_data { + /* NCT38XX device */ + const struct device *dev; + /* lock NCT38xx register access */ + struct k_sem *lock; + /* I2C device for the MFD parent */ + const struct i2c_dt_spec *i2c_dev; +}; + void nct38xx_gpio_alert_handler(const struct device *dev) { const struct gpio_nct38xx_config *const config = dev->config; @@ -29,46 +51,60 @@ void nct38xx_gpio_alert_handler(const struct device *dev) static int nct38xx_init_interrupt(const struct device *dev) { uint16_t alert, alert_mask = 0; + int ret = 0; + struct gpio_nct38xx_data *data = dev->data; + + k_sem_take(data->lock, K_FOREVER); /* Disable all interrupt */ - if (nct38xx_reg_burst_write(dev, NCT38XX_REG_ALERT_MASK, (uint8_t *)&alert_mask, - sizeof(alert_mask))) { - return -EIO; + if (i2c_burst_write_dt(data->i2c_dev, NCT38XX_REG_ALERT_MASK, (uint8_t *)&alert_mask, + sizeof(alert_mask))) { + ret = -EIO; + goto unlock; } /* Enable vendor-defined alert for GPIO. */ alert_mask |= BIT(NCT38XX_REG_ALERT_MASK_VENDOR_DEFINDED_ALERT); /* Clear alert */ - if (nct38xx_reg_burst_read(dev, NCT38XX_REG_ALERT, (uint8_t *)&alert, sizeof(alert))) { - return -EIO; + if (i2c_burst_read_dt(data->i2c_dev, NCT38XX_REG_ALERT, (uint8_t *)&alert, sizeof(alert))) { + ret = -EIO; + goto unlock; } alert &= alert_mask; if (alert) { - if (nct38xx_reg_burst_write(dev, NCT38XX_REG_ALERT, (uint8_t *)&alert, - sizeof(alert))) { - return -EIO; + if (i2c_burst_write_dt(data->i2c_dev, NCT38XX_REG_ALERT, (uint8_t *)&alert, + sizeof(alert))) { + ret = -EIO; + goto unlock; } } - if (nct38xx_reg_burst_write(dev, NCT38XX_REG_ALERT_MASK, (uint8_t *)&alert_mask, - sizeof(alert_mask))) { - return -EIO; + if (i2c_burst_write_dt(data->i2c_dev, NCT38XX_REG_ALERT_MASK, (uint8_t *)&alert_mask, + sizeof(alert_mask))) { + ret = -EIO; + goto unlock; } - return 0; +unlock: + k_sem_give(data->lock); + return ret; } static int nct38xx_gpio_init(const struct device *dev) { const struct gpio_nct38xx_config *const config = dev->config; + struct gpio_nct38xx_data *data = dev->data; - /* Check I2C is ready */ - if (!device_is_ready(config->i2c_dev.bus)) { - LOG_ERR("%s device not ready", config->i2c_dev.bus->name); + /* Verify multi-function parent is ready */ + if (!device_is_ready(config->mfd)) { + LOG_ERR("%s device not ready", config->mfd->name); return -ENODEV; } + data->lock = mfd_nct38xx_get_lock_reference(config->mfd); + data->i2c_dev = mfd_nct38xx_get_i2c_dt_spec(config->mfd); + if (IS_ENABLED(CONFIG_GPIO_NCT38XX_ALERT)) { nct38xx_init_interrupt(dev); } @@ -81,7 +117,7 @@ static int nct38xx_gpio_init(const struct device *dev) DT_INST_FOREACH_CHILD_STATUS_OKAY_SEP(inst, DEVICE_DT_GET, (,)) \ }; \ static const struct gpio_nct38xx_config gpio_nct38xx_cfg_##inst = { \ - .i2c_dev = I2C_DT_SPEC_INST_GET(inst), \ + .mfd = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ .sub_gpio_dev = sub_gpio_dev_##inst, \ .sub_gpio_port_num = ARRAY_SIZE(sub_gpio_dev_##inst), \ }; \ @@ -93,3 +129,6 @@ static int nct38xx_gpio_init(const struct device *dev) CONFIG_GPIO_NCT38XX_INIT_PRIORITY, NULL); DT_INST_FOREACH_STATUS_OKAY(GPIO_NCT38XX_DEVICE_INSTANCE) + +/* The nct38xx MFD parent must be initialized before this driver */ +BUILD_ASSERT(CONFIG_GPIO_NCT38XX_INIT_PRIORITY > CONFIG_MFD_INIT_PRIORITY); diff --git a/drivers/gpio/gpio_nct38xx.h b/drivers/gpio/gpio_nct38xx.h index 78b7466f6bc..38032664566 100644 --- a/drivers/gpio/gpio_nct38xx.h +++ b/drivers/gpio/gpio_nct38xx.h @@ -31,110 +31,6 @@ #define NCT38XX_REG_ALERT_VENDOR_DEFINDED_ALERT 15 #define NCT38XX_REG_ALERT_MASK_VENDOR_DEFINDED_ALERT 15 -/* Driver config */ -struct gpio_nct38xx_config { - /* I2C device */ - const struct i2c_dt_spec i2c_dev; - /* GPIO ports */ - const struct device **sub_gpio_dev; - uint8_t sub_gpio_port_num; - /* Alert handler */ - const struct device *alert_dev; -}; - -/* Driver data */ -struct gpio_nct38xx_data { - /* NCT38XX device */ - const struct device *dev; -}; - -/** - * @brief Read a NCT38XX register - * - * @param dev NCT38XX device - * @param reg_addr Register address - * @param val A pointer to a buffer for the data to return - * - * @return 0 if successful, otherwise failed. - */ -static inline int nct38xx_reg_read_byte(const struct device *dev, uint8_t reg_addr, uint8_t *val) -{ - const struct gpio_nct38xx_config *const config = - (const struct gpio_nct38xx_config *)dev->config; - return i2c_reg_read_byte_dt(&config->i2c_dev, reg_addr, val); -} - -/** - * @brief Read a sequence of NCT38XX registers - * - * @param dev NCT38XX device - * @param start_addr The register start address - * @param buf A pointer to a buffer for the data to return - * @param num_bytes Number of data to read - * - * @return 0 if successful, otherwise failed. - */ -static inline int nct38xx_reg_burst_read(const struct device *dev, uint8_t start_addr, uint8_t *buf, - uint32_t num_bytes) -{ - const struct gpio_nct38xx_config *const config = - (const struct gpio_nct38xx_config *)dev->config; - return i2c_burst_read_dt(&config->i2c_dev, start_addr, buf, num_bytes); -} - -/** - * @brief Write a NCT38XX register - * - * @param dev NCT38XX device - * @param reg_addr Register address - * @param val Data to write - * - * @return 0 if successful, otherwise failed. - */ -static inline int nct38xx_reg_write_byte(const struct device *dev, uint8_t reg_addr, uint8_t val) -{ - const struct gpio_nct38xx_config *const config = - (const struct gpio_nct38xx_config *)dev->config; - return i2c_reg_write_byte_dt(&config->i2c_dev, reg_addr, val); -} - -/** - * @brief Write a sequence of NCT38XX registers - * - * @param dev NCT38XX device - * @param start_addr The register start address - * @param buf A pointer to a buffer for the data to write - * @param num_bytes Number of data to write - * - * @return 0 if successful, otherwise failed. - */ -static inline int nct38xx_reg_burst_write(const struct device *dev, uint8_t start_addr, - uint8_t *buf, uint32_t num_bytes) -{ - const struct gpio_nct38xx_config *const config = - (const struct gpio_nct38xx_config *)dev->config; - return i2c_burst_write_dt(&config->i2c_dev, start_addr, buf, num_bytes); -} - -/** - * @brief Compare data & write a NCT38XX register - * - * @param dev NCT38XX device - * @param reg_addr Register address - * @param reg_val Old register data - * @param new_val New register data - * - * @return 0 if successful, otherwise failed. - */ -static inline int nct38xx_reg_update(const struct device *dev, uint8_t reg_addr, uint8_t reg_val, - uint8_t new_val) -{ - if (reg_val == new_val) - return 0; - - return nct38xx_reg_write_byte(dev, reg_addr, new_val); -} - /** * @brief Dispatch GPIO port ISR * diff --git a/drivers/gpio/gpio_nct38xx_alert.c b/drivers/gpio/gpio_nct38xx_alert.c index 64ece947bd5..eb52339364a 100644 --- a/drivers/gpio/gpio_nct38xx_alert.c +++ b/drivers/gpio/gpio_nct38xx_alert.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -17,6 +18,13 @@ #include LOG_MODULE_DECLARE(gpio_ntc38xx, CONFIG_GPIO_LOG_LEVEL); +struct nct38xx_mfd { + /* Lock for NCT38xx register access */ + struct k_sem *lock; + /* I2C device used for register access */ + const struct i2c_dt_spec *i2c_dev; +}; + /* Driver config */ struct nct38xx_alert_config { /* Alert GPIO pin */ @@ -35,6 +43,8 @@ struct nct38xx_alert_data { struct gpio_callback gpio_cb; /* Alert worker */ struct k_work alert_worker; + /* Lock for NCT38xx register access */ + struct nct38xx_mfd *mfd; }; static void nct38xx_alert_callback(const struct device *dev, struct gpio_callback *cb, @@ -46,39 +56,58 @@ static void nct38xx_alert_callback(const struct device *dev, struct gpio_callbac k_work_submit(&data->alert_worker); } +static bool nct38xx_alert_is_active(struct nct38xx_mfd *mfd) +{ + int ret; + uint16_t alert, mask; + + k_sem_take(mfd->lock, K_FOREVER); + + /* Clear alert */ + ret = i2c_burst_read_dt(mfd->i2c_dev, NCT38XX_REG_ALERT, (uint8_t *)&alert, + sizeof(alert)); + if (ret < 0) { + goto release_lock; + } + ret = i2c_burst_read_dt(mfd->i2c_dev, NCT38XX_REG_ALERT_MASK, + (uint8_t *)&mask, sizeof(mask)); + if (ret < 0) { + goto release_lock; + } + + alert &= mask; + if (alert) { + ret = i2c_burst_write_dt(mfd->i2c_dev, NCT38XX_REG_ALERT, + (uint8_t *)&alert, sizeof(alert)); + } + +release_lock: + k_sem_give(mfd->lock); + + if (ret < 0) { + LOG_ERR("i2c access failed"); + return false; + } + + if (alert & BIT(NCT38XX_REG_ALERT_VENDOR_DEFINDED_ALERT)) { + return true; + } + + return false; +} + static void nct38xx_alert_worker(struct k_work *work) { struct nct38xx_alert_data *const data = CONTAINER_OF(work, struct nct38xx_alert_data, alert_worker); const struct nct38xx_alert_config *const config = data->alert_dev->config; - uint16_t alert, mask; do { /* NCT38XX device handler */ for (int i = 0; i < config->nct38xx_num; i++) { - /* Clear alert */ - if (nct38xx_reg_burst_read(config->nct38xx_dev[i], NCT38XX_REG_ALERT, - (uint8_t *)&alert, sizeof(alert))) { - LOG_ERR("i2c access failed"); - return; - } - if (nct38xx_reg_burst_read(config->nct38xx_dev[i], NCT38XX_REG_ALERT_MASK, - (uint8_t *)&mask, sizeof(mask))) { - LOG_ERR("i2c access failed"); - return; - } + struct nct38xx_mfd *mfd = &data->mfd[i]; - alert &= mask; - if (alert) { - if (nct38xx_reg_burst_write(config->nct38xx_dev[i], - NCT38XX_REG_ALERT, (uint8_t *)&alert, - sizeof(alert))) { - LOG_ERR("i2c access failed"); - return; - } - } - - if (alert & BIT(NCT38XX_REG_ALERT_VENDOR_DEFINDED_ALERT)) { + if (nct38xx_alert_is_active(mfd)) { nct38xx_gpio_alert_handler(config->nct38xx_dev[i]); } } @@ -98,6 +127,9 @@ static int nct38xx_alert_init(const struct device *dev) LOG_ERR("%s device not ready", config->nct38xx_dev[i]->name); return -ENODEV; } + + data->mfd[i].lock = mfd_nct38xx_get_lock_reference(config->nct38xx_dev[i]); + data->mfd[i].i2c_dev = mfd_nct38xx_get_i2c_dt_spec(config->nct38xx_dev[i]); } /* Set the alert pin for handling the interrupt */ @@ -129,8 +161,9 @@ BUILD_ASSERT(CONFIG_GPIO_NCT38XX_ALERT_INIT_PRIORITY > CONFIG_GPIO_NCT38XX_INIT_ DEVICE_DT_GET(DT_PHANDLE_BY_IDX(node_id, prop, idx)), #define NCT38XX_ALERT_DEVICE_INSTANCE(inst) \ - const struct device *nct38xx_dev_##inst[] = { DT_INST_FOREACH_PROP_ELEM( \ - inst, nct38xx_dev, NCT38XX_DEV_AND_COMMA) }; \ + const struct device *nct38xx_dev_##inst[] = { \ + DT_INST_FOREACH_PROP_ELEM(inst, nct38xx_dev, NCT38XX_DEV_AND_COMMA)}; \ + static struct nct38xx_mfd nct38xx_mfd_##inst[DT_INST_PROP_LEN(inst, nct38xx_dev)]; \ static const struct nct38xx_alert_config nct38xx_alert_cfg_##inst = { \ .irq_gpio = GPIO_DT_SPEC_INST_GET(inst, irq_gpios), \ .nct38xx_dev = &nct38xx_dev_##inst[0], \ @@ -138,6 +171,7 @@ BUILD_ASSERT(CONFIG_GPIO_NCT38XX_ALERT_INIT_PRIORITY > CONFIG_GPIO_NCT38XX_INIT_ }; \ static struct nct38xx_alert_data nct38xx_alert_data_##inst = { \ .alert_dev = DEVICE_DT_INST_GET(inst), \ + .mfd = nct38xx_mfd_##inst, \ }; \ DEVICE_DT_INST_DEFINE(inst, nct38xx_alert_init, NULL, &nct38xx_alert_data_##inst, \ &nct38xx_alert_cfg_##inst, POST_KERNEL, \ diff --git a/drivers/gpio/gpio_nct38xx_port.c b/drivers/gpio/gpio_nct38xx_port.c index 561e98842c9..32d70808fcd 100644 --- a/drivers/gpio/gpio_nct38xx_port.c +++ b/drivers/gpio/gpio_nct38xx_port.c @@ -8,8 +8,8 @@ #include "gpio_nct38xx.h" #include - #include +#include #include LOG_MODULE_DECLARE(gpio_ntc38xx, CONFIG_GPIO_LOG_LEVEL); @@ -18,7 +18,7 @@ struct gpio_nct38xx_port_config { /* gpio_driver_config needs to be first */ struct gpio_driver_config common; /* NCT38XX controller dev */ - const struct device *nct38xx_dev; + const struct device *mfd; /* GPIO port index */ uint8_t gpio_port; /* GPIO port 0 pinmux mask */ @@ -31,8 +31,10 @@ struct gpio_nct38xx_port_data { struct gpio_driver_data common; /* GPIO callback list */ sys_slist_t cb_list_gpio; - /* lock GPIO register access */ - struct k_sem lock; + /* lock NCT38xx register access */ + struct k_sem *lock; + /* I2C device for the MFD parent */ + const struct i2c_dt_spec *i2c_dev; }; /* GPIO api functions */ @@ -40,8 +42,8 @@ static int gpio_nct38xx_pin_config(const struct device *dev, gpio_pin_t pin, gpi { const struct gpio_nct38xx_port_config *const config = dev->config; struct gpio_nct38xx_port_data *const data = dev->data; - uint32_t mask = BIT(pin); - uint8_t reg, new_reg; + uint32_t mask; + uint8_t new_reg; int ret; /* Don't support simultaneous in/out mode */ @@ -59,21 +61,18 @@ static int gpio_nct38xx_pin_config(const struct device *dev, gpio_pin_t pin, gpi return -ENOTSUP; } - k_sem_take(&data->lock, K_FOREVER); + k_sem_take(data->lock, K_FOREVER); /* Pin multiplexing */ if (config->gpio_port == 0) { - ret = nct38xx_reg_read_byte(config->nct38xx_dev, NCT38XX_REG_MUX_CONTROL, ®); - if (ret < 0) { - goto done; - } - - new_reg = reg | mask; - /* NCT3807 bit3 must be set to 0 */ - new_reg &= config->pinmux_mask; + /* Set the mux control bit, but ensure the reserved fields + * are cleared. Note that pinmux_mask contains the set + * of non-reserved bits. + */ + new_reg = BIT(pin) & config->pinmux_mask; + mask = BIT(pin) | ~config->pinmux_mask; - ret = nct38xx_reg_update(config->nct38xx_dev, NCT38XX_REG_MUX_CONTROL, reg, - new_reg); + ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_MUX_CONTROL, mask, new_reg); if (ret < 0) { goto done; } @@ -81,68 +80,49 @@ static int gpio_nct38xx_pin_config(const struct device *dev, gpio_pin_t pin, gpi /* Configure pin as input. */ if (flags & GPIO_INPUT) { - ret = nct38xx_reg_read_byte(config->nct38xx_dev, - NCT38XX_REG_GPIO_DIR(config->gpio_port), ®); - if (ret < 0) { - goto done; - } - new_reg = reg & ~mask; - ret = nct38xx_reg_update(config->nct38xx_dev, - NCT38XX_REG_GPIO_DIR(config->gpio_port), reg, new_reg); + /* Clear the direction bit to set as an input */ + new_reg = 0; + mask = BIT(pin); + ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DIR(config->gpio_port), + mask, new_reg); - k_sem_give(&data->lock); - return ret; + goto done; } /* Select open drain 0:push-pull 1:open-drain */ - ret = nct38xx_reg_read_byte(config->nct38xx_dev, NCT38XX_REG_GPIO_OD_SEL(config->gpio_port), - ®); - if (ret < 0) { - goto done; - } + mask = BIT(pin); if (flags & GPIO_OPEN_DRAIN) { - new_reg = reg | mask; + new_reg = mask; } else { - new_reg = reg & ~mask; + new_reg = 0; } - ret = nct38xx_reg_update(config->nct38xx_dev, NCT38XX_REG_GPIO_OD_SEL(config->gpio_port), - reg, new_reg); + ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_OD_SEL(config->gpio_port), + mask, new_reg); if (ret < 0) { goto done; } /* Set level 0:low 1:high */ - ret = nct38xx_reg_read_byte(config->nct38xx_dev, - NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), - ®); - if (ret < 0) { - goto done; - } if (flags & GPIO_OUTPUT_INIT_HIGH) { - new_reg = reg | mask; + new_reg = mask; } else if (flags & GPIO_OUTPUT_INIT_LOW) { - new_reg = reg & ~mask; + new_reg = 0; } - ret = nct38xx_reg_update(config->nct38xx_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), - reg, new_reg); + ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), + mask, new_reg); if (ret < 0) { goto done; } /* Configure pin as output, if requested 0:input 1:output */ if (flags & GPIO_OUTPUT) { - ret = nct38xx_reg_read_byte(config->nct38xx_dev, - NCT38XX_REG_GPIO_DIR(config->gpio_port), ®); - if (ret < 0) { - goto done; - } - new_reg = reg | mask; - ret = nct38xx_reg_update(config->nct38xx_dev, - NCT38XX_REG_GPIO_DIR(config->gpio_port), reg, new_reg); + new_reg = BIT(pin); + ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DIR(config->gpio_port), + mask, new_reg); } done: - k_sem_give(&data->lock); + k_sem_give(data->lock); return ret; } @@ -155,7 +135,7 @@ int gpio_nct38xx_pin_get_config(const struct device *dev, gpio_pin_t pin, gpio_f uint8_t reg; int ret; - k_sem_take(&data->lock, K_FOREVER); + k_sem_take(data->lock, K_FOREVER); if (config->gpio_port == 0) { if (mask & (~config->common.port_pin_mask)) { @@ -163,7 +143,7 @@ int gpio_nct38xx_pin_get_config(const struct device *dev, gpio_pin_t pin, gpio_f goto done; } - ret = nct38xx_reg_read_byte(config->nct38xx_dev, NCT38XX_REG_MUX_CONTROL, ®); + ret = i2c_reg_read_byte_dt(data->i2c_dev, NCT38XX_REG_MUX_CONTROL, ®); if (ret < 0) { goto done; } @@ -174,8 +154,7 @@ int gpio_nct38xx_pin_get_config(const struct device *dev, gpio_pin_t pin, gpio_f } } - ret = nct38xx_reg_read_byte(config->nct38xx_dev, NCT38XX_REG_GPIO_DIR(config->gpio_port), - ®); + ret = i2c_reg_read_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DIR(config->gpio_port), ®); if (ret < 0) { goto done; } @@ -185,8 +164,8 @@ int gpio_nct38xx_pin_get_config(const struct device *dev, gpio_pin_t pin, gpio_f *flags = GPIO_OUTPUT; /* 0 - push-pull, 1 - open-drain */ - ret = nct38xx_reg_read_byte(config->nct38xx_dev, - NCT38XX_REG_GPIO_OD_SEL(config->gpio_port), ®); + ret = i2c_reg_read_byte_dt(data->i2c_dev, + NCT38XX_REG_GPIO_OD_SEL(config->gpio_port), ®); if (ret < 0) { goto done; } @@ -196,8 +175,8 @@ int gpio_nct38xx_pin_get_config(const struct device *dev, gpio_pin_t pin, gpio_f } /* Output value */ - ret = nct38xx_reg_read_byte(config->nct38xx_dev, - NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), ®); + ret = i2c_reg_read_byte_dt(data->i2c_dev, + NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), ®); if (ret < 0) { goto done; } @@ -213,17 +192,24 @@ int gpio_nct38xx_pin_get_config(const struct device *dev, gpio_pin_t pin, gpio_f } done: - k_sem_give(&data->lock); + k_sem_give(data->lock); return ret; } #endif /* CONFIG_GPIO_GET_CONFIG */ static int gpio_nct38xx_port_get_raw(const struct device *dev, gpio_port_value_t *value) { + int ret; const struct gpio_nct38xx_port_config *const config = dev->config; + struct gpio_nct38xx_port_data *const data = dev->data; + + k_sem_take(data->lock, K_FOREVER); - return nct38xx_reg_read_byte(config->nct38xx_dev, - NCT38XX_REG_GPIO_DATA_IN(config->gpio_port), (uint8_t *)value); + ret = i2c_reg_read_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DATA_IN(config->gpio_port), + (uint8_t *)value); + + k_sem_give(data->lock); + return ret; } static int gpio_nct38xx_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask, @@ -231,22 +217,14 @@ static int gpio_nct38xx_port_set_masked_raw(const struct device *dev, gpio_port_ { const struct gpio_nct38xx_port_config *const config = dev->config; struct gpio_nct38xx_port_data *const data = dev->data; - uint8_t reg, new_reg; int ret; - k_sem_take(&data->lock, K_FOREVER); + k_sem_take(data->lock, K_FOREVER); - ret = nct38xx_reg_read_byte(config->nct38xx_dev, - NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), ®); - if (ret < 0) { - goto done; - } - new_reg = ((reg & ~mask) | (value & mask)); - ret = nct38xx_reg_update(config->nct38xx_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), - reg, new_reg); + ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), + mask, value); -done: - k_sem_give(&data->lock); + k_sem_give(data->lock); return ret; } @@ -255,22 +233,14 @@ static int gpio_nct38xx_port_set_bits_raw(const struct device *dev, gpio_port_pi { const struct gpio_nct38xx_port_config *const config = dev->config; struct gpio_nct38xx_port_data *const data = dev->data; - uint8_t reg, new_reg; int ret; - k_sem_take(&data->lock, K_FOREVER); + k_sem_take(data->lock, K_FOREVER); - ret = nct38xx_reg_read_byte(config->nct38xx_dev, - NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), ®); - if (ret < 0) { - goto done; - } - new_reg = reg | mask; - ret = nct38xx_reg_update(config->nct38xx_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), - reg, new_reg); + ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), + mask, mask); -done: - k_sem_give(&data->lock); + k_sem_give(data->lock); return ret; } @@ -279,22 +249,14 @@ static int gpio_nct38xx_port_clear_bits_raw(const struct device *dev, gpio_port_ { const struct gpio_nct38xx_port_config *const config = dev->config; struct gpio_nct38xx_port_data *const data = dev->data; - uint8_t reg, new_reg; int ret; - k_sem_take(&data->lock, K_FOREVER); + k_sem_take(data->lock, K_FOREVER); - ret = nct38xx_reg_read_byte(config->nct38xx_dev, - NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), ®); - if (ret < 0) { - goto done; - } - new_reg = reg & ~mask; - ret = nct38xx_reg_update(config->nct38xx_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), - reg, new_reg); + ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), + mask, 0); -done: - k_sem_give(&data->lock); + k_sem_give(data->lock); return ret; } @@ -306,19 +268,21 @@ static int gpio_nct38xx_port_toggle_bits(const struct device *dev, gpio_port_pin uint8_t reg, new_reg; int ret; - k_sem_take(&data->lock, K_FOREVER); + k_sem_take(data->lock, K_FOREVER); - ret = nct38xx_reg_read_byte(config->nct38xx_dev, - NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), ®); + ret = i2c_reg_read_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), + ®); if (ret < 0) { goto done; } new_reg = reg ^ mask; - ret = nct38xx_reg_update(config->nct38xx_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), - reg, new_reg); + if (new_reg != reg) { + ret = i2c_reg_write_byte_dt(data->i2c_dev, + NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), new_reg); + } done: - k_sem_give(&data->lock); + k_sem_give(data->lock); return ret; } @@ -328,24 +292,16 @@ static int gpio_nct38xx_pin_interrupt_configure(const struct device *dev, gpio_p { const struct gpio_nct38xx_port_config *const config = dev->config; struct gpio_nct38xx_port_data *const data = dev->data; - uint8_t reg, new_reg, rise, new_rise, fall, new_fall; + uint8_t new_reg, new_rise, new_fall; int ret; uint32_t mask = BIT(pin); - k_sem_take(&data->lock, K_FOREVER); + k_sem_take(data->lock, K_FOREVER); /* Disable irq before configuring them */ - ret = nct38xx_reg_read_byte(config->nct38xx_dev, - NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), ®); - if (ret < 0) { - goto done; - } - new_reg = reg & ~mask; - ret = nct38xx_reg_update(config->nct38xx_dev, - NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), reg, new_reg); - if (ret < 0) { - goto done; - } + new_reg = 0; + ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), + mask, new_reg); /* Configure and enable interrupt? */ if (mode == GPIO_INT_MODE_DISABLED) { @@ -353,69 +309,52 @@ static int gpio_nct38xx_pin_interrupt_configure(const struct device *dev, gpio_p } /* set edge register */ - ret = nct38xx_reg_read_byte(config->nct38xx_dev, - NCT38XX_REG_GPIO_ALERT_RISE(config->gpio_port), &rise); - if (ret < 0) { - goto done; - } - ret = nct38xx_reg_read_byte(config->nct38xx_dev, - NCT38XX_REG_GPIO_ALERT_FALL(config->gpio_port), &fall); - if (ret < 0) { - goto done; - } - if (mode == GPIO_INT_MODE_EDGE) { if (trig == GPIO_INT_TRIG_LOW) { - new_rise = rise & ~mask; - new_fall = fall | mask; + new_rise = 0; + new_fall = mask; } else if (trig == GPIO_INT_TRIG_HIGH) { - new_rise = rise | mask; - new_fall = fall & ~mask; + new_rise = mask; + new_fall = 0; } else if (trig == GPIO_INT_TRIG_BOTH) { - new_rise = rise | mask; - new_fall = fall | mask; + new_rise = mask; + new_fall = mask; } else { LOG_ERR("Invalid interrupt trigger type %d", trig); return -EINVAL; } } else { /* level mode */ - new_rise = rise & ~mask; - new_fall = fall & ~mask; + new_rise = 0; + new_fall = 0; } - ret = nct38xx_reg_update(config->nct38xx_dev, - NCT38XX_REG_GPIO_ALERT_RISE(config->gpio_port), rise, new_rise); + ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_ALERT_RISE(config->gpio_port), + mask, new_rise); if (ret < 0) { goto done; } - ret = nct38xx_reg_update(config->nct38xx_dev, - NCT38XX_REG_GPIO_ALERT_FALL(config->gpio_port), fall, new_fall); + ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_ALERT_FALL(config->gpio_port), + mask, new_fall); if (ret < 0) { goto done; } if (mode == GPIO_INT_MODE_LEVEL) { /* set active high/low */ - ret = nct38xx_reg_read_byte(config->nct38xx_dev, - NCT38XX_REG_GPIO_ALERT_LEVEL(config->gpio_port), ®); - if (ret < 0) { - goto done; - } - if (trig == GPIO_INT_TRIG_LOW) { - new_reg = reg & ~mask; + new_reg = 0; } else if (trig == GPIO_INT_TRIG_HIGH) { - new_reg = reg | mask; + new_reg = mask; } else { LOG_ERR("Invalid interrupt trigger type %d", trig); ret = -EINVAL; goto done; } - ret = nct38xx_reg_update(config->nct38xx_dev, - NCT38XX_REG_GPIO_ALERT_LEVEL(config->gpio_port), reg, - new_reg); + ret = i2c_reg_update_byte_dt(data->i2c_dev, + NCT38XX_REG_GPIO_ALERT_LEVEL(config->gpio_port), mask, + new_reg); if (ret < 0) { goto done; @@ -423,24 +362,19 @@ static int gpio_nct38xx_pin_interrupt_configure(const struct device *dev, gpio_p } /* Clear pending bit */ - ret = nct38xx_reg_write_byte(config->nct38xx_dev, - NCT38XX_REG_GPIO_ALERT_STAT(config->gpio_port), mask); + ret = i2c_reg_write_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_ALERT_STAT(config->gpio_port), + mask); if (ret < 0) { goto done; } /* Enable it after configuration is completed */ - ret = nct38xx_reg_read_byte(config->nct38xx_dev, - NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), ®); - if (ret < 0) { - goto done; - } - new_reg = reg | mask; - ret = nct38xx_reg_update(config->nct38xx_dev, - NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), reg, new_reg); + new_reg = mask; + ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), + mask, new_reg); done: - k_sem_give(&data->lock); + k_sem_give(data->lock); return ret; } @@ -462,13 +396,12 @@ static int gpio_nct38xx_port_get_direction(const struct device *dev, gpio_port_p uint8_t dir_reg; int ret; - k_sem_take(&data->lock, K_FOREVER); + k_sem_take(data->lock, K_FOREVER); if (config->gpio_port == 0) { uint8_t enabled_gpios; /* Remove the disabled GPIOs from the mask */ - ret = nct38xx_reg_read_byte(config->nct38xx_dev, NCT38XX_REG_MUX_CONTROL, - &enabled_gpios); + ret = i2c_reg_read_byte_dt(data->i2c_dev, NCT38XX_REG_MUX_CONTROL, &enabled_gpios); mask &= (enabled_gpios & config->common.port_pin_mask); if (ret < 0) { @@ -477,8 +410,8 @@ static int gpio_nct38xx_port_get_direction(const struct device *dev, gpio_port_p } /* Read direction register, 0 - input, 1 - output */ - ret = nct38xx_reg_read_byte(config->nct38xx_dev, NCT38XX_REG_GPIO_DIR(config->gpio_port), - &dir_reg); + ret = i2c_reg_read_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DIR(config->gpio_port), + &dir_reg); if (ret < 0) { goto done; } @@ -492,7 +425,7 @@ static int gpio_nct38xx_port_get_direction(const struct device *dev, gpio_port_p } done: - k_sem_give(&data->lock); + k_sem_give(data->lock); return ret; } #endif /* CONFIG_GPIO_GET_DIRECTION */ @@ -505,32 +438,31 @@ int gpio_nct38xx_dispatch_port_isr(const struct device *dev) int ret; do { - k_sem_take(&data->lock, K_FOREVER); - ret = nct38xx_reg_read_byte(config->nct38xx_dev, - NCT38XX_REG_GPIO_ALERT_STAT(config->gpio_port), - &alert_pins); + k_sem_take(data->lock, K_FOREVER); + ret = i2c_reg_read_byte_dt( + data->i2c_dev, NCT38XX_REG_GPIO_ALERT_STAT(config->gpio_port), &alert_pins); if (ret < 0) { - k_sem_give(&data->lock); + k_sem_give(data->lock); return ret; } - ret = nct38xx_reg_read_byte(config->nct38xx_dev, - NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), &mask); + ret = i2c_reg_read_byte_dt(data->i2c_dev, + NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), &mask); if (ret < 0) { - k_sem_give(&data->lock); + k_sem_give(data->lock); return ret; } alert_pins &= mask; if (alert_pins) { - ret = nct38xx_reg_write_byte(config->nct38xx_dev, - NCT38XX_REG_GPIO_ALERT_STAT(config->gpio_port), - alert_pins); + ret = i2c_reg_write_byte_dt(data->i2c_dev, + NCT38XX_REG_GPIO_ALERT_STAT(config->gpio_port), + alert_pins); if (ret < 0) { - k_sem_give(&data->lock); + k_sem_give(data->lock); return ret; } } - k_sem_give(&data->lock); + k_sem_give(data->lock); gpio_fire_callbacks(&data->cb_list_gpio, dev, alert_pins); @@ -566,12 +498,13 @@ static int gpio_nct38xx_port_init(const struct device *dev) const struct gpio_nct38xx_port_config *const config = dev->config; struct gpio_nct38xx_port_data *const data = dev->data; - if (!device_is_ready(config->nct38xx_dev)) { - LOG_ERR("%s is not ready", config->nct38xx_dev->name); + if (!device_is_ready(config->mfd)) { + LOG_ERR("%s is not ready", config->mfd->name); return -ENODEV; } - k_sem_init(&data->lock, 1, 1); + data->lock = mfd_nct38xx_get_lock_reference(config->mfd); + data->i2c_dev = mfd_nct38xx_get_i2c_dt_spec(config->mfd); return 0; } @@ -583,7 +516,7 @@ BUILD_ASSERT(CONFIG_GPIO_NCT38XX_PORT_INIT_PRIORITY > CONFIG_GPIO_NCT38XX_INIT_P static const struct gpio_nct38xx_port_config gpio_nct38xx_port_cfg_##inst = { \ .common = {.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(inst) & \ DT_INST_PROP(inst, pin_mask)}, \ - .nct38xx_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ + .mfd = DEVICE_DT_GET(DT_INST_GPARENT(inst)), \ .gpio_port = DT_INST_REG_ADDR(inst), \ .pinmux_mask = COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, pinmux_mask), \ (DT_INST_PROP(inst, pinmux_mask)), (0)), \ diff --git a/drivers/gpio/gpio_nxp_s32.c b/drivers/gpio/gpio_nxp_s32.c index de5dbd39dd7..2d272cdea09 100644 --- a/drivers/gpio/gpio_nxp_s32.c +++ b/drivers/gpio/gpio_nxp_s32.c @@ -9,20 +9,33 @@ #include #include #include +#include +#include #include #include +LOG_MODULE_REGISTER(nxp_s32_gpio, CONFIG_GPIO_LOG_LEVEL); + #ifdef CONFIG_NXP_S32_EIRQ #include +#endif +#ifdef CONFIG_NXP_S32_WKPU +#include +#endif + +#if defined(CONFIG_NXP_S32_EIRQ) || defined(CONFIG_NXP_S32_WKPU) +#define NXP_S32_GPIO_LINE_NOT_FOUND 0xff -struct eirq_nxp_s32_info { - const struct device *eirq_dev; - uint8_t num_lines; - struct gpio_pin_line { - uint8_t pin; - uint8_t line; - } gpio_pin_lines[]; +struct gpio_nxp_s32_irq_map { + uint8_t pin; + uint8_t line; +} __packed; + +struct gpio_nxp_s32_irq_config { + const struct device *ctrl; + uint8_t map_cnt; + struct gpio_nxp_s32_irq_map *map; }; #endif @@ -34,7 +47,10 @@ struct gpio_nxp_s32_config { Siul2_Port_Ip_PortType *port_base; #ifdef CONFIG_NXP_S32_EIRQ - struct eirq_nxp_s32_info *eirq_info; + struct gpio_nxp_s32_irq_config *eirq_info; +#endif +#ifdef CONFIG_NXP_S32_WKPU + struct gpio_nxp_s32_irq_config *wkpu_info; #endif }; @@ -42,8 +58,11 @@ struct gpio_nxp_s32_data { /* gpio_driver_data needs to be first */ struct gpio_driver_data common; -#ifdef CONFIG_NXP_S32_EIRQ +#if defined(CONFIG_NXP_S32_EIRQ) || defined(CONFIG_NXP_S32_WKPU) sys_slist_t callbacks; +#if defined(CONFIG_NXP_S32_WKPU) + uint32_t pin_wkpu_mask; +#endif /* defined(CONFIG_NXP_S32_WKPU) */ #endif }; @@ -59,6 +78,16 @@ static int nxp_s32_gpio_configure(const struct device *dev, gpio_pin_t pin, return -ENOTSUP; } +#if defined(CONFIG_NXP_S32_WKPU) + struct gpio_nxp_s32_data *data = dev->data; + + WRITE_BIT(data->pin_wkpu_mask, pin, (flags & NXP_S32_GPIO_INT_WKPU)); +#else + if (flags & NXP_S32_GPIO_INT_WKPU) { + return -ENOTSUP; + } +#endif + switch (flags & GPIO_DIR_MASK) { case GPIO_INPUT: Siul2_Port_Ip_SetPinDirection(port_base, pin, SIUL2_PORT_IN); @@ -153,21 +182,31 @@ static int nxp_s32_gpio_port_toggle_bits(const struct device *port, return 0; } -#ifdef CONFIG_NXP_S32_EIRQ +#if defined(CONFIG_NXP_S32_EIRQ) || defined(CONFIG_NXP_S32_WKPU) -static uint8_t nxp_s32_gpio_pin_to_line(const struct eirq_nxp_s32_info *eirq_info, uint8_t pin) +static uint8_t nxp_s32_gpio_pin_to_line(const struct gpio_nxp_s32_irq_config *irq_cfg, + uint8_t pin) { uint8_t i; - for (i = 0; i < eirq_info->num_lines; i++) { - if (eirq_info->gpio_pin_lines[i].pin == pin) { - return eirq_info->gpio_pin_lines[i].line; + for (i = 0; i < irq_cfg->map_cnt; i++) { + if (irq_cfg->map[i].pin == pin) { + return irq_cfg->map[i].line; } } - return SIUL2_ICU_IP_NUM_OF_CHANNELS; + return NXP_S32_GPIO_LINE_NOT_FOUND; } +static void nxp_s32_gpio_isr(uint8_t pin, void *arg) +{ + const struct device *dev = (struct device *)arg; + struct gpio_nxp_s32_data *data = dev->data; + + gpio_fire_callbacks(&data->callbacks, dev, BIT(pin)); +} + +#if defined(CONFIG_NXP_S32_EIRQ) static int nxp_s32_gpio_eirq_get_trigger(Siul2_Icu_Ip_EdgeType *edge_type, enum gpio_int_mode mode, enum gpio_int_trig trigger) @@ -198,91 +237,153 @@ static int nxp_s32_gpio_eirq_get_trigger(Siul2_Icu_Ip_EdgeType *edge_type, return 0; } -static void nxp_s32_gpio_isr(uint8_t pin, void *arg) +static int nxp_s32_gpio_config_eirq(const struct device *dev, + gpio_pin_t pin, + enum gpio_int_mode mode, + enum gpio_int_trig trig) { - const struct device *dev = (struct device *)arg; - struct gpio_nxp_s32_data *data = dev->data; + const struct gpio_nxp_s32_config *config = dev->config; + const struct gpio_nxp_s32_irq_config *irq_cfg = config->eirq_info; + uint8_t irq_line; + Siul2_Icu_Ip_EdgeType edge_type; - gpio_fire_callbacks(&data->callbacks, dev, BIT(pin)); + if (irq_cfg == NULL) { + LOG_ERR("external interrupt controller not available or enabled"); + return -ENOTSUP; + } + + if (nxp_s32_gpio_eirq_get_trigger(&edge_type, mode, trig)) { + LOG_ERR("trigger or mode not supported"); + return -ENOTSUP; + } + + irq_line = nxp_s32_gpio_pin_to_line(irq_cfg, pin); + if (irq_line == NXP_S32_GPIO_LINE_NOT_FOUND) { + if (edge_type == SIUL2_ICU_DISABLE) { + return 0; + } + LOG_ERR("pin %d cannot be used for external interrupt", pin); + return -ENOTSUP; + } + + if (edge_type == SIUL2_ICU_DISABLE) { + eirq_nxp_s32_disable_interrupt(irq_cfg->ctrl, irq_line); + eirq_nxp_s32_unset_callback(irq_cfg->ctrl, irq_line); + } else { + if (eirq_nxp_s32_set_callback(irq_cfg->ctrl, irq_line, + nxp_s32_gpio_isr, pin, (void *)dev)) { + LOG_ERR("pin %d is already in use", pin); + return -EBUSY; + } + eirq_nxp_s32_enable_interrupt(irq_cfg->ctrl, irq_line, edge_type); + } + + return 0; } +#endif /* CONFIG_NXP_S32_EIRQ */ -static int nxp_s32_gpio_pin_interrupt_configure(const struct device *dev, - gpio_pin_t pin, - enum gpio_int_mode mode, - enum gpio_int_trig trig) +#if defined(CONFIG_NXP_S32_WKPU) +static int nxp_s32_gpio_wkpu_get_trigger(Wkpu_Ip_EdgeType *edge_type, + enum gpio_int_mode mode, + enum gpio_int_trig trigger) { - const struct gpio_nxp_s32_config *config = dev->config; - const struct eirq_nxp_s32_info *eirq_info = config->eirq_info; - - uint8_t eirq_line; + if (mode == GPIO_INT_MODE_DISABLED) { + *edge_type = WKPU_IP_NONE_EDGE; + return 0; + } - Siul2_Icu_Ip_EdgeType edge_type; + if (mode == GPIO_INT_MODE_LEVEL) { + return -ENOTSUP; + } - if (eirq_info == NULL) { - /* - * There is no external interrupt device for - * the GPIO port or exists but is not enabled - */ + switch (trigger) { + case GPIO_INT_TRIG_LOW: + *edge_type = WKPU_IP_FALLING_EDGE; + break; + case GPIO_INT_TRIG_HIGH: + *edge_type = WKPU_IP_RISING_EDGE; + break; + case GPIO_INT_TRIG_BOTH: + *edge_type = WKPU_IP_BOTH_EDGES; + break; + default: return -ENOTSUP; } - eirq_line = nxp_s32_gpio_pin_to_line(eirq_info, pin); + return 0; +} - if (eirq_line == SIUL2_ICU_IP_NUM_OF_CHANNELS) { - /* - * GPIO pin cannot be used for processing - * external interrupt signal - */ +static int nxp_s32_gpio_config_wkpu(const struct device *dev, + gpio_pin_t pin, + enum gpio_int_mode mode, + enum gpio_int_trig trig) +{ + const struct gpio_nxp_s32_config *config = dev->config; + const struct gpio_nxp_s32_irq_config *irq_cfg = config->wkpu_info; + uint8_t irq_line; + Wkpu_Ip_EdgeType edge_type; + + if (irq_cfg == NULL) { + LOG_ERR("WKPU controller not available or enabled"); return -ENOTSUP; } - if (nxp_s32_gpio_eirq_get_trigger(&edge_type, mode, trig)) { + if (nxp_s32_gpio_wkpu_get_trigger(&edge_type, mode, trig)) { + LOG_ERR("trigger or mode not supported"); return -ENOTSUP; } - if (edge_type == SIUL2_ICU_DISABLE) { - eirq_nxp_s32_disable_interrupt(eirq_info->eirq_dev, eirq_line); - eirq_nxp_s32_unset_callback(eirq_info->eirq_dev, eirq_line); + irq_line = nxp_s32_gpio_pin_to_line(irq_cfg, pin); + if (irq_line == NXP_S32_GPIO_LINE_NOT_FOUND) { + if (edge_type == WKPU_IP_NONE_EDGE) { + return 0; + } + LOG_ERR("pin %d cannot be used for external interrupt", pin); + return -ENOTSUP; + } + + if (edge_type == WKPU_IP_NONE_EDGE) { + wkpu_nxp_s32_disable_interrupt(irq_cfg->ctrl, irq_line); + wkpu_nxp_s32_unset_callback(irq_cfg->ctrl, irq_line); } else { - if (eirq_nxp_s32_set_callback(eirq_info->eirq_dev, eirq_line, - nxp_s32_gpio_isr, pin, (void *)dev)) { + if (wkpu_nxp_s32_set_callback(irq_cfg->ctrl, irq_line, + nxp_s32_gpio_isr, pin, (void *)dev)) { + LOG_ERR("pin %d is already in use", pin); return -EBUSY; } - - eirq_nxp_s32_enable_interrupt(eirq_info->eirq_dev, eirq_line, edge_type); + wkpu_nxp_s32_enable_interrupt(irq_cfg->ctrl, irq_line, edge_type); } return 0; } +#endif /* CONFIG_NXP_S32_WKPU */ -static int nxp_s32_gpio_manage_callback(const struct device *dev, - struct gpio_callback *cb, bool set) +static int nxp_s32_gpio_pin_interrupt_configure(const struct device *dev, + gpio_pin_t pin, + enum gpio_int_mode mode, + enum gpio_int_trig trig) { +#if defined(CONFIG_NXP_S32_WKPU) struct gpio_nxp_s32_data *data = dev->data; - return gpio_manage_callback(&data->callbacks, cb, set); + if (data->pin_wkpu_mask & BIT(pin)) { + return nxp_s32_gpio_config_wkpu(dev, pin, mode, trig); + } +#endif + +#if defined(CONFIG_NXP_S32_EIRQ) + return nxp_s32_gpio_config_eirq(dev, pin, mode, trig); +#endif } -static uint32_t nxp_s32_gpio_get_pending_int(const struct device *dev) +static int nxp_s32_gpio_manage_callback(const struct device *dev, + struct gpio_callback *cb, bool set) { - const struct gpio_nxp_s32_config *config = dev->config; - const struct eirq_nxp_s32_info *eirq_info = config->eirq_info; - - if (eirq_info == NULL) { - /* - * There is no external interrupt device for - * the GPIO port or exists but is not enabled - */ - return 0; - } + struct gpio_nxp_s32_data *data = dev->data; - /* - * Return all pending lines of the interrupt controller - * that GPIO port belongs to - */ - return eirq_nxp_s32_get_pending(eirq_info->eirq_dev); + return gpio_manage_callback(&data->callbacks, cb, set); } -#endif /* CONFIG_NXP_S32_EIRQ */ +#endif /* defined(CONFIG_NXP_S32_EIRQ) || defined(CONFIG_NXP_S32_WKPU) */ #ifdef CONFIG_GPIO_GET_CONFIG static int nxp_s32_gpio_pin_get_config(const struct device *dev, @@ -375,10 +476,9 @@ static const struct gpio_driver_api gpio_nxp_s32_driver_api = { .port_set_bits_raw = nxp_s32_gpio_port_set_bits_raw, .port_clear_bits_raw = nxp_s32_gpio_port_clear_bits_raw, .port_toggle_bits = nxp_s32_gpio_port_toggle_bits, -#ifdef CONFIG_NXP_S32_EIRQ +#if defined(CONFIG_NXP_S32_EIRQ) || defined(CONFIG_NXP_S32_WKPU) .pin_interrupt_configure = nxp_s32_gpio_pin_interrupt_configure, .manage_callback = nxp_s32_gpio_manage_callback, - .get_pending_int = nxp_s32_gpio_get_pending_int, #endif #ifdef CONFIG_GPIO_GET_CONFIG .pin_get_config = nxp_s32_gpio_pin_get_config, @@ -424,37 +524,65 @@ static const struct gpio_driver_api gpio_nxp_s32_driver_api = { DT_INST_PHANDLE(n, interrupt_parent) #define GPIO_NXP_S32_EIRQ_PIN_LINE(idx, n) \ - { \ - .pin = DT_INST_IRQ_BY_IDX(n, idx, gpio_pin), \ - .line = DT_INST_IRQ_BY_IDX(n, idx, eirq_line), \ - } + DT_INST_IRQ_BY_IDX(n, idx, gpio_pin), \ + DT_INST_IRQ_BY_IDX(n, idx, eirq_line) \ #define GPIO_NXP_S32_SET_EIRQ_INFO(n) \ BUILD_ASSERT((DT_NODE_HAS_PROP(DT_DRV_INST(n), interrupt_parent) == \ DT_NODE_HAS_PROP(DT_DRV_INST(n), interrupts)), \ - "interrupts and interrupt-parent must be set when" \ - " using external interrupts"); \ - IF_ENABLED(DT_NODE_HAS_STATUS(GPIO_NXP_S32_EIRQ_NODE(n), okay), \ - (static struct eirq_nxp_s32_info eirq_nxp_s32_info_##n = { \ - .eirq_dev = DEVICE_DT_GET(GPIO_NXP_S32_EIRQ_NODE(n)), \ - .gpio_pin_lines = { \ - LISTIFY(DT_NUM_IRQS(DT_DRV_INST(n)), \ - GPIO_NXP_S32_EIRQ_PIN_LINE, (,), n) \ - }, \ - .num_lines = DT_NUM_IRQS(DT_DRV_INST(n)) \ + "interrupts and interrupt-parent must be set when " \ + "using external interrupts"); \ + IF_ENABLED(DT_NODE_HAS_STATUS(GPIO_NXP_S32_EIRQ_NODE(n), okay), ( \ + static uint8_t gpio_nxp_s32_eirq_data_##n[] = { \ + LISTIFY(DT_NUM_IRQS(DT_DRV_INST(n)), \ + GPIO_NXP_S32_EIRQ_PIN_LINE, (,), n) \ }; \ - )) + static struct gpio_nxp_s32_irq_config gpio_nxp_s32_eirq_##n = { \ + .ctrl = DEVICE_DT_GET(GPIO_NXP_S32_EIRQ_NODE(n)), \ + .map_cnt = DT_NUM_IRQS(DT_DRV_INST(n)), \ + .map = (struct gpio_nxp_s32_irq_map *) \ + gpio_nxp_s32_eirq_data_##n, \ + }; \ + )) #define GPIO_NXP_S32_GET_EIRQ_INFO(n) \ .eirq_info = UTIL_AND(DT_NODE_HAS_STATUS(GPIO_NXP_S32_EIRQ_NODE(n), okay),\ - &eirq_nxp_s32_info_##n) + &gpio_nxp_s32_eirq_##n), #else #define GPIO_NXP_S32_SET_EIRQ_INFO(n) #define GPIO_NXP_S32_GET_EIRQ_INFO(n) #endif /* CONFIG_NXP_S32_EIRQ */ +#ifdef CONFIG_NXP_S32_WKPU +#define GPIO_NXP_S32_WKPU_NODE(n) DT_INST_PHANDLE(n, nxp_wkpu) + +#define GPIO_NXP_S32_SET_WKPU_INFO(n) \ + BUILD_ASSERT((DT_INST_NODE_HAS_PROP(n, nxp_wkpu) == \ + DT_INST_NODE_HAS_PROP(n, nxp_wkpu_interrupts)), \ + "nxp,wkpu and nxp,wkpu-interrupts must be provided"); \ + IF_ENABLED(DT_NODE_HAS_STATUS(GPIO_NXP_S32_WKPU_NODE(n), okay), ( \ + static uint8_t gpio_nxp_s32_wkpu_data_##n[] = \ + DT_INST_PROP(n, nxp_wkpu_interrupts); \ + static struct gpio_nxp_s32_irq_config gpio_nxp_s32_wkpu_##n = { \ + .ctrl = DEVICE_DT_GET(GPIO_NXP_S32_WKPU_NODE(n)), \ + .map_cnt = sizeof(gpio_nxp_s32_wkpu_data_##n) / \ + sizeof(struct gpio_nxp_s32_irq_map), \ + .map = (struct gpio_nxp_s32_irq_map *) \ + gpio_nxp_s32_wkpu_data_##n, \ + }; \ + )) + +#define GPIO_NXP_S32_GET_WKPU_INFO(n) \ + .wkpu_info = UTIL_AND(DT_NODE_HAS_STATUS(GPIO_NXP_S32_WKPU_NODE(n), okay),\ + &gpio_nxp_s32_wkpu_##n) +#else +#define GPIO_NXP_S32_SET_WKPU_INFO(n) +#define GPIO_NXP_S32_GET_WKPU_INFO(n) +#endif /* CONFIG_NXP_S32_WKPU */ + #define GPIO_NXP_S32_DEVICE_INIT(n) \ GPIO_NXP_S32_SET_EIRQ_INFO(n) \ + GPIO_NXP_S32_SET_WKPU_INFO(n) \ static const struct gpio_nxp_s32_config gpio_nxp_s32_config_##n = { \ .common = { \ .port_pin_mask = GPIO_NXP_S32_PORT_PIN_MASK(n), \ @@ -462,6 +590,7 @@ static const struct gpio_driver_api gpio_nxp_s32_driver_api = { .gpio_base = GPIO_NXP_S32_REG_ADDR(n), \ .port_base = GPIO_NXP_S32_PORT_REG_ADDR(n), \ GPIO_NXP_S32_GET_EIRQ_INFO(n) \ + GPIO_NXP_S32_GET_WKPU_INFO(n) \ }; \ static struct gpio_nxp_s32_data gpio_nxp_s32_data_##n; \ static int gpio_nxp_s32_init_##n(const struct device *dev) \ diff --git a/drivers/gpio/gpio_ra.c b/drivers/gpio/gpio_ra.c new file mode 100644 index 00000000000..9f4fe59c83b --- /dev/null +++ b/drivers/gpio/gpio_ra.c @@ -0,0 +1,435 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_ra_gpio + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + PCNTR1_OFFSET = 0x0, + PCNTR2_OFFSET = 0x4, + PCNTR3_OFFSET = 0x8, + PCNTR4_OFFSET = 0xc +}; + +enum { + PCNTR1_PDR0_OFFSET = 0, + PCNTR1_PODR0_OFFSET = 16, +}; + +enum { + PCNTR2_PIDR0_OFFSET = 0, + PCNTR2_EIDR0_OFFSET = 16, +}; + +enum { + PCNTR3_POSR0_OFFSET = 0, + PCNTR3_PORR0_OFFSET = 16, +}; + +enum { + PCNTR4_EOSR0_OFFSET = 0, + PCNTR4_EORR0_OFFSET = 16, +}; + +struct gpio_ra_irq_info { + const uint8_t *const pins; + size_t num; + int port_irq; + int irq; + uint32_t priority; + uint32_t flags; + ra_isr_handler isr; +}; + +struct gpio_ra_pin_irq_info { + const struct gpio_ra_irq_info *info; + uint8_t pin; +}; + +struct gpio_ra_config { + struct gpio_driver_config common; + mem_addr_t regs; + struct gpio_ra_irq_info *irq_info; + uint32_t irq_info_size; + uint16_t port; +}; + +struct gpio_ra_data { + struct gpio_driver_data common; + struct gpio_ra_pin_irq_info port_irq_info[16]; + sys_slist_t callbacks; +}; + +static inline uint32_t gpio_ra_irq_info_event(const struct gpio_ra_irq_info *info) +{ + return ((info->flags & RA_ICU_FLAG_EVENT_MASK) >> RA_ICU_FLAG_EVENT_OFFSET); +} + +static void gpio_ra_isr(const struct device *dev, uint32_t port_irq) +{ + struct gpio_ra_data *data = dev->data; + const struct gpio_ra_pin_irq_info *pin_irq = &data->port_irq_info[port_irq]; + const int irq = ra_icu_query_exists_irq(gpio_ra_irq_info_event(pin_irq->info)); + + if (irq >= 0) { + gpio_fire_callbacks(&data->callbacks, dev, BIT(pin_irq->pin)); + ra_icu_clear_int_flag(irq); + } +} + +static const struct gpio_ra_irq_info *query_irq_info(const struct device *dev, uint32_t pin) +{ + const struct gpio_ra_config *config = dev->config; + + for (int i = 0; i < config->irq_info_size; i++) { + const struct gpio_ra_irq_info *info = &config->irq_info[i]; + + for (int j = 0; j < info->num; j++) { + if (info->pins[j] == pin) { + return info; + } + } + } + + return NULL; +} + +static inline uint32_t reg_read(const struct device *dev, size_t offset) +{ + const struct gpio_ra_config *config = dev->config; + + return sys_read32(config->regs + offset); +} + +static inline void reg_write(const struct device *dev, size_t offset, uint32_t value) +{ + const struct gpio_ra_config *config = dev->config; + + sys_write32(value, config->regs + offset); +} + +static inline uint32_t port_read(const struct device *dev) +{ + return reg_read(dev, PCNTR2_OFFSET) & UINT16_MAX; +} + +static int port_write(const struct device *dev, uint16_t value, uint16_t mask) +{ + const uint16_t set = value & mask; + const uint16_t clr = (~value) & mask; + + reg_write(dev, PCNTR3_OFFSET, (clr << PCNTR3_PORR0_OFFSET) | set << PCNTR3_POSR0_OFFSET); + + return 0; +} + +static int gpio_ra_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) +{ + const enum gpio_int_mode mode = + flags & (GPIO_INT_EDGE | GPIO_INT_DISABLE | GPIO_INT_ENABLE); + const enum gpio_int_trig trig = flags & (GPIO_INT_LOW_0 | GPIO_INT_HIGH_1); + const struct gpio_ra_config *config = dev->config; + struct gpio_ra_data *data = dev->data; + struct pinctrl_ra_pin pincfg = {0}; + + if ((flags & GPIO_OUTPUT) && (flags & GPIO_INPUT)) { + /* Pin cannot be configured as input and output */ + return -ENOTSUP; + } else if (!(flags & (GPIO_INPUT | GPIO_OUTPUT))) { + /* Pin has to be configured as input or output */ + return -ENOTSUP; + } + + if (flags & GPIO_OUTPUT) { + pincfg.config |= BIT(PmnPFS_PDR_POS); + } + + if (flags & GPIO_PULL_UP) { + pincfg.config |= BIT(PmnPFS_PCR_POS); + } + + if ((flags & GPIO_SINGLE_ENDED) && (flags & GPIO_LINE_OPEN_DRAIN)) { + pincfg.config |= BIT(PmnPFS_NCODR_POS); + } + + if (flags & GPIO_INT_ENABLE) { + pincfg.config |= BIT(PmnPFS_ISEL_POS); + } + + pincfg.config &= ~BIT(PmnPFS_PMR_POS); + + pincfg.pin = pin; + pincfg.port = config->port; + + if (flags & GPIO_INT_ENABLE) { + const struct gpio_ra_irq_info *irq_info; + uint32_t intcfg; + int irqn; + + if (mode == GPIO_INT_MODE_LEVEL) { + if (trig != GPIO_INT_TRIG_LOW) { + return -ENOTSUP; + } + + intcfg = ICU_LOW_LEVEL; + } else if (mode == GPIO_INT_MODE_EDGE) { + switch (trig) { + case GPIO_INT_TRIG_LOW: + intcfg = ICU_FALLING; + break; + case GPIO_INT_TRIG_HIGH: + intcfg = ICU_RISING; + break; + case GPIO_INT_TRIG_BOTH: + intcfg = ICU_BOTH_EDGE; + break; + default: + return -ENOTSUP; + } + } else { + return -ENOTSUP; + } + + irq_info = query_irq_info(dev, pin); + if (irq_info == NULL) { + return -EINVAL; + } + + irqn = ra_icu_irq_connect_dynamic( + irq_info->irq, irq_info->priority, irq_info->isr, dev, + (intcfg << RA_ICU_FLAG_INTCFG_OFFSET) | irq_info->flags); + if (irqn < 0) { + return irqn; + } + + data->port_irq_info[irq_info->port_irq].pin = pin; + data->port_irq_info[irq_info->port_irq].info = irq_info; + + irq_enable(irqn); + } + + return pinctrl_configure_pins(&pincfg, 1, PINCTRL_REG_NONE); +} + +#ifdef CONFIG_GPIO_GET_CONFIG +static int gpio_ra_pin_get_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t *flags) +{ + const struct gpio_ra_config *config = dev->config; + const struct gpio_ra_irq_info *irq_info; + struct pinctrl_ra_pin pincfg; + ra_isr_handler cb; + const void *cbarg; + uint32_t intcfg; + int irqn; + int err; + + memset(flags, 0, sizeof(gpio_flags_t)); + + err = pinctrl_ra_query_config(config->port, pin, &pincfg); + if (err < 0) { + return err; + } + + if (pincfg.config & BIT(PmnPFS_PDR_POS)) { + *flags |= GPIO_OUTPUT; + } else { + *flags |= GPIO_INPUT; + } + + if (pincfg.config & BIT(PmnPFS_ISEL_POS)) { + *flags |= GPIO_INT_ENABLE; + } + + if (pincfg.config & BIT(PmnPFS_PCR_POS)) { + *flags |= GPIO_PULL_UP; + } + + irq_info = query_irq_info(dev, pin); + if (irq_info == NULL) { + return 0; + } + + irqn = ra_icu_query_exists_irq(gpio_ra_irq_info_event(irq_info)); + if (irqn < 0) { + return 0; + } + + ra_icu_query_irq_config(irqn, &intcfg, &cb, &cbarg); + + if (cbarg != dev) { + return 0; + } + + if (intcfg == ICU_FALLING) { + *flags |= GPIO_INT_TRIG_LOW; + *flags |= GPIO_INT_MODE_EDGE; + } else if (intcfg == ICU_RISING) { + *flags |= GPIO_INT_TRIG_HIGH; + *flags |= GPIO_INT_MODE_EDGE; + } else if (intcfg == ICU_BOTH_EDGE) { + *flags |= GPIO_INT_TRIG_BOTH; + *flags |= GPIO_INT_MODE_EDGE; + } else if (intcfg == ICU_LOW_LEVEL) { + *flags |= GPIO_INT_TRIG_LOW; + *flags |= GPIO_INT_MODE_LEVEL; + } + + return 0; +} +#endif + +static int gpio_ra_port_get_raw(const struct device *dev, gpio_port_value_t *value) +{ + *value = port_read(dev); + + return 0; +} + +static int gpio_ra_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask, + gpio_port_value_t value) +{ + uint16_t port_val; + + port_val = port_read(dev); + port_val = (port_val & ~mask) | (value & mask); + return port_write(dev, port_val, UINT16_MAX); +} + +static int gpio_ra_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + uint16_t port_val; + + port_val = port_read(dev); + port_val |= pins; + return port_write(dev, port_val, UINT16_MAX); +} + +static int gpio_ra_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + uint16_t port_val; + + port_val = port_read(dev); + port_val &= ~pins; + return port_write(dev, port_val, UINT16_MAX); +} + +static int gpio_ra_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins) +{ + uint16_t port_val; + + port_val = port_read(dev); + port_val ^= pins; + return port_write(dev, port_val, UINT16_MAX); +} + +static int gpio_ra_manage_callback(const struct device *dev, struct gpio_callback *callback, + bool set) +{ + struct gpio_ra_data *data = dev->data; + + return gpio_manage_callback(&data->callbacks, callback, set); +} + +static int gpio_ra_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, + enum gpio_int_mode mode, enum gpio_int_trig trig) +{ + gpio_flags_t pincfg; + int err; + + err = gpio_ra_pin_get_config(dev, pin, &pincfg); + if (err < 0) { + return err; + } + + return gpio_ra_pin_configure(dev, pin, pincfg | mode | trig); +} + +static const struct gpio_driver_api gpio_ra_driver_api = { + .pin_configure = gpio_ra_pin_configure, +#ifdef CONFIG_GPIO_GET_CONFIG + .pin_get_config = gpio_ra_pin_get_config, +#endif + .port_get_raw = gpio_ra_port_get_raw, + .port_set_masked_raw = gpio_ra_port_set_masked_raw, + .port_set_bits_raw = gpio_ra_port_set_bits_raw, + .port_clear_bits_raw = gpio_ra_port_clear_bits_raw, + .port_toggle_bits = gpio_ra_port_toggle_bits, + .pin_interrupt_configure = gpio_ra_pin_interrupt_configure, + .manage_callback = gpio_ra_manage_callback, +}; + +#define RA_NUM_PORT_IRQ0 0 +#define RA_NUM_PORT_IRQ1 1 +#define RA_NUM_PORT_IRQ2 2 +#define RA_NUM_PORT_IRQ3 3 +#define RA_NUM_PORT_IRQ4 4 +#define RA_NUM_PORT_IRQ5 5 +#define RA_NUM_PORT_IRQ6 6 +#define RA_NUM_PORT_IRQ7 7 +#define RA_NUM_PORT_IRQ8 8 +#define RA_NUM_PORT_IRQ9 9 +#define RA_NUM_PORT_IRQ10 10 +#define RA_NUM_PORT_IRQ11 11 +#define RA_NUM_PORT_IRQ12 12 +#define RA_NUM_PORT_IRQ13 13 +#define RA_NUM_PORT_IRQ14 14 +#define RA_NUM_PORT_IRQ15 15 + +#define GPIO_RA_DECL_PINS(n, p, i) \ + const uint8_t _CONCAT(n, ___pins##i[]) = {DT_FOREACH_PROP_ELEM_SEP( \ + n, _CONCAT(DT_STRING_TOKEN_BY_IDX(n, p, i), _pins), DT_PROP_BY_IDX, (,))}; + +#define GPIO_RA_IRQ_INFO(n, p, i) \ + { \ + .port_irq = _CONCAT(RA_NUM_, DT_STRING_UPPER_TOKEN_BY_IDX(n, p, i)), \ + .irq = DT_IRQ_BY_IDX(n, i, irq), \ + .flags = DT_IRQ_BY_IDX(n, i, flags), \ + .priority = DT_IRQ_BY_IDX(n, i, priority), \ + .pins = _CONCAT(n, ___pins##i), \ + .num = ARRAY_SIZE(_CONCAT(n, ___pins##i)), \ + .isr = _CONCAT(n, _CONCAT(gpio_ra_isr_, DT_STRING_TOKEN_BY_IDX(n, p, i))), \ + }, + +#define GPIO_RA_ISR_DECL(n, p, i) \ + static void _CONCAT(n, _CONCAT(gpio_ra_isr_, DT_STRING_TOKEN_BY_IDX(n, p, i)))( \ + const void *arg) \ + { \ + gpio_ra_isr((const struct device *)arg, \ + _CONCAT(RA_NUM_, DT_STRING_UPPER_TOKEN_BY_IDX(n, p, i))); \ + } + +#define GPIO_RA_INIT(idx) \ + static struct gpio_ra_data gpio_ra_data_##idx = {}; \ + DT_INST_FOREACH_PROP_ELEM(idx, interrupt_names, GPIO_RA_DECL_PINS); \ + DT_INST_FOREACH_PROP_ELEM(idx, interrupt_names, GPIO_RA_ISR_DECL); \ + struct gpio_ra_irq_info gpio_ra_irq_info_##idx[] = { \ + DT_INST_FOREACH_PROP_ELEM(idx, interrupt_names, GPIO_RA_IRQ_INFO)}; \ + static struct gpio_ra_config gpio_ra_config_##idx = { \ + .common = { \ + .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(idx), \ + }, \ + .regs = DT_INST_REG_ADDR(idx), \ + .port = (DT_INST_REG_ADDR(idx) - DT_REG_ADDR(DT_NODELABEL(ioport0))) / \ + DT_INST_REG_SIZE(idx), \ + .irq_info = gpio_ra_irq_info_##idx, \ + .irq_info_size = ARRAY_SIZE(gpio_ra_irq_info_##idx), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(idx, NULL, NULL, &gpio_ra_data_##idx, &gpio_ra_config_##idx, \ + PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, &gpio_ra_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(GPIO_RA_INIT) diff --git a/drivers/gpio/gpio_rzt2m.c b/drivers/gpio/gpio_rzt2m.c new file mode 100644 index 00000000000..c2bfd1a4acd --- /dev/null +++ b/drivers/gpio/gpio_rzt2m.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_rzt2m_gpio + +#include +#include +#include +#include +#include +#include +#include + +#define PMm_OFFSET 0x200 +#define PINm_OFFSET 0x800 +#define DRCTLm_OFFSET 0xa00 + +#define DRIVE_SHIFT 0 +#define SCHMITT_TRIGGER_SHIFT 4 +#define SLEW_RATE_SHIFT 5 + +#define PULL_SHIFT 2 +#define PULL_NONE (0 << PULL_SHIFT) +#define PULL_UP (1 << PULL_SHIFT) +#define PULL_DOWN (2 << PULL_SHIFT) + +struct rzt2m_gpio_config { + struct gpio_driver_config common; + uint8_t *port_nsr; + uint8_t *ptadr; + uint8_t port; +}; + +struct rzt2m_gpio_data { + struct gpio_driver_data common; +}; + +static void rzt2m_gpio_unlock(void) +{ + rzt2m_unlock_prcrn(PRCRN_PRC1); + rzt2m_unlock_prcrs(PRCRS_GPIO); +} + +static void rzt2m_gpio_lock(void) +{ + rzt2m_lock_prcrn(PRCRN_PRC1); + rzt2m_lock_prcrs(PRCRS_GPIO); +} + +/* Port m output data store */ +static volatile uint8_t *rzt2m_gpio_get_p_reg(const struct device *dev) +{ + const struct rzt2m_gpio_config *config = dev->config; + + return (volatile uint8_t *)(config->port_nsr + config->port); +} + +/* Port m input data store */ +static volatile uint8_t *rzt2m_gpio_get_pin_reg(const struct device *dev) +{ + const struct rzt2m_gpio_config *config = dev->config; + + return (volatile uint8_t *)(config->port_nsr + PINm_OFFSET + config->port); +} + +/* Port m mode register */ +static volatile uint16_t *rzt2m_gpio_get_pm_reg(const struct device *dev) +{ + const struct rzt2m_gpio_config *config = dev->config; + + return (volatile uint16_t *)(config->port_nsr + PMm_OFFSET + 0x2 * config->port); +} + +/* IO Buffer m function switching register */ +static volatile uint64_t *rzt2m_gpio_get_drctl_reg(const struct device *dev) +{ + const struct rzt2m_gpio_config *config = dev->config; + + return (volatile uint64_t *)(config->port_nsr + DRCTLm_OFFSET + 0x8 * config->port); +} + +/* Port m region select register */ +static volatile uint8_t *rzt2m_gpio_get_rselp_reg(const struct device *dev) +{ + const struct rzt2m_gpio_config *config = dev->config; + + return (volatile uint8_t *)(config->ptadr + config->port); +} + +static int rzt2m_gpio_init(const struct device *dev) +{ + rzt2m_gpio_unlock(); + + volatile uint8_t *rselp_reg = rzt2m_gpio_get_rselp_reg(dev); + *rselp_reg = 0xFF; + + rzt2m_gpio_lock(); + + return 0; +} + +static int rzt2m_gpio_get_raw(const struct device *dev, gpio_port_value_t *value) +{ + rzt2m_gpio_unlock(); + + volatile uint8_t *pin_reg = rzt2m_gpio_get_pin_reg(dev); + *value = *pin_reg; + + rzt2m_gpio_lock(); + + return 0; +} + +static int rzt2m_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask, + gpio_port_value_t value) +{ + rzt2m_gpio_unlock(); + + volatile uint8_t *p_reg = rzt2m_gpio_get_p_reg(dev); + *p_reg = (*p_reg & ~mask) | (value & mask); + + rzt2m_gpio_lock(); + + return 0; +} + +static int rzt2m_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + rzt2m_gpio_unlock(); + + volatile uint8_t *p_reg = rzt2m_gpio_get_p_reg(dev); + *p_reg |= pins; + + rzt2m_gpio_lock(); + + return 0; +} + +static int rzt2m_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + rzt2m_gpio_unlock(); + + volatile uint8_t *p_reg = rzt2m_gpio_get_p_reg(dev); + *p_reg &= ~pins; + + rzt2m_gpio_lock(); + + return 0; +} + +static int rzt2m_gpio_toggle(const struct device *dev, gpio_port_pins_t pins) +{ + rzt2m_gpio_unlock(); + + volatile uint8_t *p_reg = rzt2m_gpio_get_p_reg(dev); + *p_reg ^= pins; + + rzt2m_gpio_lock(); + + return 0; +} + +static int rzt2m_gpio_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) +{ + volatile uint16_t *pm_reg = rzt2m_gpio_get_pm_reg(dev); + volatile uint64_t *drctl_reg = rzt2m_gpio_get_drctl_reg(dev); + + rzt2m_gpio_unlock(); + + WRITE_BIT(*pm_reg, pin * 2, flags & GPIO_INPUT); + WRITE_BIT(*pm_reg, pin * 2 + 1, flags & GPIO_OUTPUT); + + if (flags & GPIO_OUTPUT) { + if (flags & GPIO_OUTPUT_INIT_LOW) { + rzt2m_port_clear_bits_raw(dev, 1 << pin); + } else if (flags & GPIO_OUTPUT_INIT_HIGH) { + rzt2m_port_set_bits_raw(dev, 1 << pin); + } + } + + if (flags & GPIO_PULL_UP && flags & GPIO_PULL_DOWN) { + rzt2m_gpio_lock(); + return -EINVAL; + } + + uint8_t drctl_pin_config = 0; + + if (flags & GPIO_PULL_UP) { + drctl_pin_config |= PULL_UP; + } else if (flags & GPIO_PULL_DOWN) { + drctl_pin_config |= PULL_DOWN; + } else { + drctl_pin_config |= PULL_NONE; + } + + drctl_pin_config |= + (flags & RZT2M_GPIO_DRIVE_MASK) >> (RZT2M_GPIO_DRIVE_OFFSET - DRIVE_SHIFT); + drctl_pin_config |= (flags & RZT2M_GPIO_SCHMITT_TRIGGER_MASK) >> + (RZT2M_GPIO_SCHMITT_TRIGGER_OFFSET - SCHMITT_TRIGGER_SHIFT); + drctl_pin_config |= (flags & RZT2M_GPIO_SLEW_RATE_MASK) >> + (RZT2M_GPIO_SLEW_RATE_OFFSET - SLEW_RATE_SHIFT); + + uint64_t drctl_pin_value = *drctl_reg & ~(0xFFULL << (pin * 8)); + *drctl_reg = drctl_pin_value | ((uint64_t)drctl_pin_config << (pin * 8)); + + rzt2m_gpio_lock(); + + return 0; +} + +static const struct gpio_driver_api rzt2m_gpio_driver_api = { + .pin_configure = rzt2m_gpio_configure, + .port_get_raw = rzt2m_gpio_get_raw, + .port_set_masked_raw = rzt2m_port_set_masked_raw, + .port_set_bits_raw = rzt2m_port_set_bits_raw, + .port_clear_bits_raw = rzt2m_port_clear_bits_raw, + .port_toggle_bits = rzt2m_gpio_toggle}; + +#define RZT2M_GPIO_DEFINE(inst) \ + static struct rzt2m_gpio_data rzt2m_gpio_data##inst; \ + static struct rzt2m_gpio_config rzt2m_gpio_config##inst = { \ + .port_nsr = (uint8_t *)DT_REG_ADDR_BY_NAME(DT_INST_PARENT(inst), port_nsr), \ + .ptadr = (uint8_t *)DT_REG_ADDR_BY_NAME(DT_INST_PARENT(inst), ptadr), \ + .port = DT_INST_REG_ADDR(inst), \ + .common = {.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(inst)}}; \ + DEVICE_DT_INST_DEFINE(inst, rzt2m_gpio_init, NULL, &rzt2m_gpio_data##inst, \ + &rzt2m_gpio_config##inst, PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, \ + &rzt2m_gpio_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(RZT2M_GPIO_DEFINE) diff --git a/drivers/gpio/gpio_sedi.c b/drivers/gpio/gpio_sedi.c new file mode 100644 index 00000000000..17dfe79f090 --- /dev/null +++ b/drivers/gpio/gpio_sedi.c @@ -0,0 +1,340 @@ +/* Copyright (c) 2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT intel_sedi_gpio + +#include "sedi_driver_gpio.h" +#include +#include +#include +#include + +struct gpio_sedi_config { + /* gpio_driver_data needs to be first */ + struct gpio_driver_config common; + sedi_gpio_t device; + uint32_t pin_nums; + void (*irq_config)(void); + + DEVICE_MMIO_ROM; +}; + +struct gpio_sedi_data { + /* gpio_driver_data needs to be first */ + struct gpio_driver_config common; + sys_slist_t callbacks; + + DEVICE_MMIO_RAM; +}; + +static int gpio_sedi_init(const struct device *dev); + +#ifdef CONFIG_PM_DEVICE +static int gpio_sedi_suspend_device(const struct device *dev) +{ + const struct gpio_sedi_config *config = dev->config; + sedi_gpio_t gpio_dev = config->device; + int ret; + + if (pm_device_is_busy(dev)) { + return -EBUSY; + } + + ret = sedi_gpio_set_power(gpio_dev, SEDI_POWER_SUSPEND); + + if (ret != SEDI_DRIVER_OK) { + return -EIO; + } + + return 0; +} + +static int gpio_sedi_resume_device_from_suspend(const struct device *dev) +{ + const struct gpio_sedi_config *config = dev->config; + sedi_gpio_t gpio_dev = config->device; + int ret; + + ret = sedi_gpio_set_power(gpio_dev, SEDI_POWER_FULL); + if (ret != SEDI_DRIVER_OK) { + return -EIO; + } + + return 0; +} + +static int gpio_sedi_pm_action(const struct device *dev, + enum pm_device_action action) +{ + int ret = 0; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + ret = gpio_sedi_suspend_device(dev); + break; + case PM_DEVICE_ACTION_RESUME: + ret = gpio_sedi_resume_device_from_suspend(dev); + break; + + default: + ret = -ENOTSUP; + } + + return ret; +} +#endif /* CONFIG_PM_DEVICE */ + +static void gpio_sedi_callback(const uint32_t pin_mask, + const sedi_gpio_port_t port, + void *param) +{ + ARG_UNUSED(port); + struct device *dev = (struct device *)param; + struct gpio_sedi_data *data = + (struct gpio_sedi_data *)(dev->data); + + /* call the callbacks */ + gpio_fire_callbacks(&data->callbacks, dev, pin_mask); +} + +static void gpio_sedi_write_raw(const struct device *dev, + uint32_t pins, + bool is_clear) +{ + uint8_t i; + const struct gpio_sedi_config *config = dev->config; + sedi_gpio_t gpio_dev = config->device; + sedi_gpio_pin_state_t val; + + if (is_clear) { + val = SEDI_GPIO_STATE_LOW; + } else { + val = SEDI_GPIO_STATE_HIGH; + } + + for (i = 0; i < config->pin_nums; i++) { + if (pins & 0x1) { + sedi_gpio_write_pin(gpio_dev, i, val); + } + pins >>= 1; + if (pins == 0) { + break; + } + } +} + +static int gpio_sedi_configure(const struct device *dev, gpio_pin_t pin, + gpio_flags_t flags) +{ + const struct gpio_sedi_config *config = dev->config; + sedi_gpio_t gpio_dev = config->device; + sedi_gpio_pin_config_t pin_config = { 0 }; + + if ((flags & GPIO_OUTPUT) && (flags & GPIO_INPUT)) { + /* Pin cannot be configured as input and output */ + return -ENOTSUP; + } else if (!(flags & (GPIO_INPUT | GPIO_OUTPUT))) { + /* Pin has to be configured as input or output */ + return -ENOTSUP; + } + + pin_config.enable_interrupt = false; + /* Map direction */ + if (flags & GPIO_OUTPUT) { + pin_config.direction = SEDI_GPIO_DIR_MODE_OUTPUT; + sedi_gpio_config_pin(gpio_dev, pin, pin_config); + /* Set start state */ + if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) { + sedi_gpio_write_pin(gpio_dev, pin, 1); + } else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) { + sedi_gpio_write_pin(gpio_dev, pin, 0); + } + } else { + pin_config.direction = SEDI_GPIO_DIR_MODE_INPUT; + sedi_gpio_config_pin(gpio_dev, pin, pin_config); + } + + return 0; +} + +static int gpio_sedi_get_raw(const struct device *dev, uint32_t *value) +{ + const struct gpio_sedi_config *config = dev->config; + sedi_gpio_t gpio_dev = config->device; + + *value = sedi_gpio_read_pin_32bits(gpio_dev, 0); + + return 0; +} + +static int gpio_sedi_set_masked_raw(const struct device *dev, + uint32_t mask, + uint32_t value) +{ + gpio_sedi_write_raw(dev, (mask & value), false); + + return 0; +} + +static int gpio_sedi_set_bits_raw(const struct device *dev, uint32_t pins) +{ + gpio_sedi_write_raw(dev, pins, false); + + return 0; +} + +static int gpio_sedi_clear_bits_raw(const struct device *dev, uint32_t pins) +{ + gpio_sedi_write_raw(dev, pins, true); + + return 0; +} + +static int gpio_sedi_toggle_bits(const struct device *dev, uint32_t pins) +{ + const struct gpio_sedi_config *config = dev->config; + sedi_gpio_t gpio_dev = config->device; + uint8_t i; + + for (i = 0; i < config->pin_nums; i++) { + if (pins & 0x1) { + sedi_gpio_toggle_pin(gpio_dev, i); + } + pins >>= 1; + if (pins == 0) { + break; + } + } + + return 0; +} + +static int gpio_sedi_interrupt_configure(const struct device *dev, + gpio_pin_t pin, + enum gpio_int_mode mode, + enum gpio_int_trig trig) +{ + const struct gpio_sedi_config *config = dev->config; + sedi_gpio_t gpio_dev = config->device; + sedi_gpio_pin_config_t pin_config = { 0 }; + + /* Not support level trigger */ + if (mode == GPIO_INT_MODE_LEVEL) { + return -EINVAL; + } + /* Only input needs interrupt enabled */ + pin_config.direction = SEDI_GPIO_DIR_MODE_INPUT; + pin_config.enable_wakeup = true; + if (mode == GPIO_INT_MODE_DISABLED) { + pin_config.enable_interrupt = false; + } else { + pin_config.enable_interrupt = true; + switch (trig) { + case GPIO_INT_TRIG_LOW: + pin_config.interrupt_mode = + SEDI_GPIO_INT_MODE_FALLING_EDGE; + break; + case GPIO_INT_TRIG_HIGH: + pin_config.interrupt_mode = + SEDI_GPIO_INT_MODE_RISING_EDGE; + break; + case GPIO_INT_TRIG_BOTH: + pin_config.interrupt_mode = + SEDI_GPIO_INT_MODE_BOTH_EDGE; + break; + } + } + /* Configure interrupt mode */ + sedi_gpio_config_pin(gpio_dev, pin, pin_config); + + return 0; +} + +static int gpio_sedi_manage_callback(const struct device *dev, + struct gpio_callback *callback, + bool set) +{ + struct gpio_sedi_data *data = dev->data; + + gpio_manage_callback(&(data->callbacks), callback, set); + + return 0; +} + +static uint32_t gpio_sedi_get_pending(const struct device *dev) +{ + const struct gpio_sedi_config *config = dev->config; + sedi_gpio_t gpio_dev = config->device; + + return sedi_gpio_get_gisr(gpio_dev, 0); +} + +static const struct gpio_driver_api gpio_sedi_driver_api = { + .pin_configure = gpio_sedi_configure, + .port_get_raw = gpio_sedi_get_raw, + .port_set_masked_raw = gpio_sedi_set_masked_raw, + .port_set_bits_raw = gpio_sedi_set_bits_raw, + .port_clear_bits_raw = gpio_sedi_clear_bits_raw, + .port_toggle_bits = gpio_sedi_toggle_bits, + .pin_interrupt_configure = gpio_sedi_interrupt_configure, + .manage_callback = gpio_sedi_manage_callback, + .get_pending_int = gpio_sedi_get_pending +}; + +extern void gpio_isr(IN sedi_gpio_t gpio_device); + +static int gpio_sedi_init(const struct device *dev) +{ + int ret; + const struct gpio_sedi_config *config = dev->config; + sedi_gpio_t gpio_dev = config->device; + + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); + + /* Call sedi gpio init */ + ret = sedi_gpio_init(gpio_dev, gpio_sedi_callback, (void *)dev); + + if (ret != 0) { + return ret; + } + sedi_gpio_set_power(gpio_dev, SEDI_POWER_FULL); + + config->irq_config(); + + return 0; +} + +#define GPIO_SEDI_IRQ_FLAGS_SENSE0(n) 0 +#define GPIO_SEDI_IRQ_FLAGS_SENSE1(n) DT_INST_IRQ(n, sense) +#define GPIO_SEDI_IRQ_FLAGS(n) \ + _CONCAT(GPIO_SEDI_IRQ_FLAGS_SENSE, DT_INST_IRQ_HAS_CELL(n, sense))(n) + +#define GPIO_DEVICE_INIT_SEDI(n) \ + static struct gpio_sedi_data gpio##n##_data; \ + static void gpio_sedi_irq_config_##n(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \ + gpio_isr, n, \ + GPIO_SEDI_IRQ_FLAGS(n)); \ + irq_enable(DT_INST_IRQN(n)); \ + }; \ + static const struct gpio_sedi_config gpio##n##_config = { \ + DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), \ + .common = { 0xFFFFFFFF }, \ + .device = DT_INST_PROP(n, peripheral_id), \ + .pin_nums = DT_INST_PROP(n, ngpios), \ + .irq_config = gpio_sedi_irq_config_##n, \ + }; \ + PM_DEVICE_DEFINE(gpio_##n, gpio_sedi_pm_action); \ + DEVICE_DT_INST_DEFINE(n, \ + &gpio_sedi_init, \ + PM_DEVICE_GET(gpio_##n), \ + &gpio##n##_data, \ + &gpio##n##_config, \ + POST_KERNEL, \ + CONFIG_GPIO_INIT_PRIORITY, \ + &gpio_sedi_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(GPIO_DEVICE_INIT_SEDI) diff --git a/drivers/gpio/gpio_shell.c b/drivers/gpio/gpio_shell.c index b444288953b..48d7e95f7a7 100644 --- a/drivers/gpio/gpio_shell.c +++ b/drivers/gpio/gpio_shell.c @@ -1,187 +1,607 @@ /* * Copyright (c) 2018 Intel Corporation * Copyright (c) 2021 Dennis Ruffer + * Copyright (c) 2023 Nick Ward * * SPDX-License-Identifier: Apache-2.0 - * - * Use "device list" command for GPIO port names */ -#include +#include #include -#include -#include + #include -#include -#include -#include -#include -#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL +#define ARGV_DEV 1 +#define ARGV_PIN 2 +#define ARGV_CONF 3 +#define ARGV_VALUE 3 +#define ARGV_VENDOR_SPECIFIC 4 -LOG_MODULE_REGISTER(gpio_shell); +#define NGPIOS_UNKNOWN -1 +#define PIN_NOT_FOUND UINT8_MAX -struct args_index { - uint8_t port; - uint8_t index; - uint8_t mode; - uint8_t value; -}; +/* Pin syntax maximum length */ +#define PIN_SYNTAX_MAX 32 +#define PIN_NUM_MAX 4 -static const struct args_index args_indx = { - .port = 1, - .index = 2, - .mode = 3, - .value = 3, +struct gpio_ctrl { + const struct device *dev; + int8_t ngpios; + gpio_port_pins_t reserved_mask; + const char **line_names; + uint8_t line_names_len; + const union shell_cmd_entry *subcmd; }; -static int cmd_gpio_conf(const struct shell *sh, size_t argc, char **argv) -{ - uint8_t index = 0U; - int type = GPIO_OUTPUT; +struct sh_gpio { const struct device *dev; + gpio_pin_t pin; +}; +/* + * Find idx-th pin reference from the set of non reserved + * pin numbers and provided line names. + */ +static void port_pin_get(gpio_port_pins_t reserved_mask, const char **line_names, + uint8_t line_names_len, size_t idx, struct shell_static_entry *entry) +{ + static char pin_syntax[PIN_SYNTAX_MAX]; + static char pin_num[PIN_NUM_MAX]; + const char *name; + gpio_pin_t pin; + bool reserved; + + entry->handler = NULL; + + /* Find allowed numeric pin reference */ + for (pin = 0; pin < GPIO_MAX_PINS_PER_PORT; pin++) { + reserved = ((BIT64(pin) & reserved_mask) != 0); + if (!reserved) { + if (idx == 0) { + break; + } + idx--; + } + } - if (isdigit((unsigned char)argv[args_indx.index][0]) != 0 && - isalpha((unsigned char)argv[args_indx.mode][0]) != 0) { - index = (uint8_t)atoi(argv[args_indx.index]); - if (!strcmp(argv[args_indx.mode], "in")) { - type = GPIO_INPUT; - } else if (!strcmp(argv[args_indx.mode], "inu")) { - type = GPIO_INPUT | GPIO_PULL_UP; - } else if (!strcmp(argv[args_indx.mode], "ind")) { - type = GPIO_INPUT | GPIO_PULL_DOWN; - } else if (!strcmp(argv[args_indx.mode], "out")) { - type = GPIO_OUTPUT; + if (pin < GPIO_MAX_PINS_PER_PORT) { + sprintf(pin_num, "%u", pin); + if ((pin < line_names_len) && (strlen(line_names[pin]) > 0)) { + /* pin can be specified by line name */ + name = line_names[pin]; + for (int i = 0; i < (sizeof(pin_syntax) - 1); i++) { + /* + * For line-name tab completion to work replace any + * space characters with '_'. + */ + pin_syntax[i] = (name[i] != ' ') ? name[i] : '_'; + if (name[i] == '\0') { + break; + } + } + pin_syntax[sizeof(pin_syntax) - 1] = '\0'; + entry->syntax = pin_syntax; + entry->help = pin_num; } else { - return 0; + /* fallback to pin specified by pin number */ + entry->syntax = pin_num; + entry->help = NULL; } } else { - shell_error(sh, "Wrong parameters for conf"); - return -ENOTSUP; + /* No more pins */ + entry->syntax = NULL; + entry->help = NULL; } +} - dev = device_get_binding(argv[args_indx.port]); +#define GPIO_DT_RESERVED_RANGES_NGPIOS_SHELL(node_id) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, ngpios), \ + (GPIO_DT_RESERVED_RANGES_NGPIOS(node_id, DT_PROP(node_id, ngpios))), \ + (GPIO_MAX_PINS_PER_PORT)) - if (dev != NULL) { - index = (uint8_t)atoi(argv[args_indx.index]); - shell_print(sh, "Configuring %s pin %d", - argv[args_indx.port], index); - gpio_pin_configure(dev, index, type); +#define GPIO_CTRL_PIN_GET_FN(node_id) \ + static const char *node_id##line_names[] = DT_PROP_OR(node_id, gpio_line_names, {NULL}); \ + \ + static void node_id##cmd_gpio_pin_get(size_t idx, struct shell_static_entry *entry); \ + \ + SHELL_DYNAMIC_CMD_CREATE(node_id##sub_gpio_pin, node_id##cmd_gpio_pin_get); \ + \ + static void node_id##cmd_gpio_pin_get(size_t idx, struct shell_static_entry *entry) \ + { \ + gpio_port_pins_t reserved_mask = GPIO_DT_RESERVED_RANGES_NGPIOS_SHELL(node_id); \ + uint8_t line_names_len = DT_PROP_LEN_OR(node_id, gpio_line_names, 0); \ + \ + port_pin_get(reserved_mask, node_id##line_names, line_names_len, idx, entry); \ + entry->subcmd = NULL; \ } - return 0; +#define IS_GPIO_CTRL_PIN_GET(node_id) \ + COND_CODE_1(DT_PROP(node_id, gpio_controller), (GPIO_CTRL_PIN_GET_FN(node_id)), ()) + +DT_FOREACH_STATUS_OKAY_NODE(IS_GPIO_CTRL_PIN_GET) + +#define GPIO_CTRL_LIST_ENTRY(node_id) \ + { \ + .dev = DEVICE_DT_GET(node_id), \ + .ngpios = DT_PROP_OR(node_id, ngpios, NGPIOS_UNKNOWN), \ + .reserved_mask = GPIO_DT_RESERVED_RANGES_NGPIOS_SHELL(node_id), \ + .line_names = node_id##line_names, \ + .line_names_len = DT_PROP_LEN_OR(node_id, gpio_line_names, 0), \ + .subcmd = &node_id##sub_gpio_pin, \ + }, + +#define IS_GPIO_CTRL_LIST(node_id) \ + COND_CODE_1(DT_PROP(node_id, gpio_controller), (GPIO_CTRL_LIST_ENTRY(node_id)), ()) + +static const struct gpio_ctrl gpio_list[] = {DT_FOREACH_STATUS_OKAY_NODE(IS_GPIO_CTRL_LIST)}; + +static const struct gpio_ctrl *get_gpio_ctrl(char *name) +{ + const struct device *dev = device_get_binding(name); + size_t i; + + for (i = 0; i < ARRAY_SIZE(gpio_list); i++) { + if (gpio_list[i].dev == dev) { + return &gpio_list[i]; + } + } + return NULL; } -static int cmd_gpio_get(const struct shell *sh, - size_t argc, char **argv) +int line_cmp(const char *input, const char *line_name) { - const struct device *dev; - uint8_t index = 0U; - int rc; + int i = 0; - if (isdigit((unsigned char)argv[args_indx.index][0]) != 0) { - index = (uint8_t)atoi(argv[args_indx.index]); - } else { - shell_error(sh, "Wrong parameters for get"); + while (true) { + if ((input[i] == '_') && (line_name[i] == ' ')) { + /* Allow input underscore to match line_name space */ + } else if (input[i] != line_name[i]) { + return (input[i] > line_name[i]) ? 1 : -1; + } else if (line_name[i] == '\0') { + return 0; + } + i++; + } +} + +static int get_gpio_pin(const struct shell *sh, const struct gpio_ctrl *ctrl, char *line_name) +{ + gpio_pin_t pin = PIN_NOT_FOUND; + gpio_pin_t i; + int result; + + for (i = 0; i < ctrl->ngpios; i++) { + result = line_cmp(line_name, ctrl->line_names[i]); + if (result == 0) { + if ((BIT64(i) & ctrl->reserved_mask) != 0) { + shell_error(sh, "Reserved pin"); + return -EACCES; + } else if (pin == PIN_NOT_FOUND) { + pin = i; + } else { + shell_error(sh, "Line name ambiguous"); + return -EFAULT; + } + } + } + + if (pin == PIN_NOT_FOUND) { + shell_error(sh, "Line name not found: '%s'", line_name); + return -ENOENT; + } + + return pin; +} + +static int get_sh_gpio(const struct shell *sh, char **argv, struct sh_gpio *gpio) +{ + const struct gpio_ctrl *ctrl; + int ret = 0; + int pin; + + ctrl = get_gpio_ctrl(argv[ARGV_DEV]); + if (ctrl == NULL) { + shell_error(sh, "unknown gpio controller: %s", argv[ARGV_DEV]); return -EINVAL; } + gpio->dev = ctrl->dev; + pin = shell_strtoul(argv[ARGV_PIN], 0, &ret); + if (ret != 0) { + pin = get_gpio_pin(sh, ctrl, argv[ARGV_PIN]); + if (pin < 0) { + return pin; + } + } else if ((BIT64(pin) & ctrl->reserved_mask) != 0) { + shell_error(sh, "Reserved pin"); + return -EACCES; + } + gpio->pin = pin; + + return 0; +} - dev = device_get_binding(argv[args_indx.port]); +static int cmd_gpio_conf(const struct shell *sh, size_t argc, char **argv, void *data) +{ + gpio_flags_t flags = 0; + gpio_flags_t vendor_specific; + struct sh_gpio gpio; + int ret = 0; + + ret = get_sh_gpio(sh, argv, &gpio); + if (ret != 0) { + shell_help(sh); + return SHELL_CMD_HELP_PRINTED; + } - if (dev != NULL) { - index = (uint8_t)atoi(argv[2]); - shell_print(sh, "Reading %s pin %d", - argv[args_indx.port], index); - rc = gpio_pin_get(dev, index); - if (rc >= 0) { - shell_print(sh, "Value %d", rc); + for (int i = 0; i < strlen(argv[ARGV_CONF]); i++) { + switch (argv[ARGV_CONF][i]) { + case 'i': + flags |= GPIO_INPUT; + break; + case 'o': + flags |= GPIO_OUTPUT; + break; + case 'u': + flags |= GPIO_PULL_UP; + break; + case 'd': + flags |= GPIO_PULL_DOWN; + break; + case 'h': + flags |= GPIO_ACTIVE_HIGH; + break; + case 'l': + flags |= GPIO_ACTIVE_LOW; + break; + case '0': + flags |= GPIO_OUTPUT_INIT_LOGICAL | GPIO_OUTPUT_INIT_LOW; + break; + case '1': + flags |= GPIO_OUTPUT_INIT_LOGICAL | GPIO_OUTPUT_INIT_HIGH; + break; + default: + shell_error(sh, "Unknown: '%c'", argv[ARGV_CONF][i]); + shell_help(sh); + return SHELL_CMD_HELP_PRINTED; + } + } + + if (((flags & GPIO_INPUT) != 0) == ((flags & GPIO_OUTPUT) != 0)) { + shell_error(sh, "must be either input or output"); + shell_help(sh); + return SHELL_CMD_HELP_PRINTED; + } + + if (((flags & GPIO_PULL_UP) != 0) && ((flags & GPIO_PULL_DOWN) != 0)) { + shell_error(sh, "cannot be pull up and pull down"); + shell_help(sh); + return SHELL_CMD_HELP_PRINTED; + } + + if (((flags & GPIO_ACTIVE_LOW) != 0) && ((flags & GPIO_ACTIVE_HIGH) != 0)) { + shell_error(sh, "cannot be active low and active high"); + shell_help(sh); + return SHELL_CMD_HELP_PRINTED; + } + + if ((flags & GPIO_OUTPUT) != 0) { + /* Default to active high if not specified */ + if ((flags & (GPIO_ACTIVE_LOW | GPIO_ACTIVE_HIGH)) == 0) { + flags |= GPIO_ACTIVE_HIGH; + } + /* Default to initialisation to logic 0 if not specified */ + if ((flags & GPIO_OUTPUT_INIT_LOGICAL) == 0) { + flags |= GPIO_OUTPUT_INIT_LOGICAL | GPIO_OUTPUT_INIT_LOW; + } + } + + if (((flags & GPIO_INPUT) != 0) && ((flags & GPIO_OUTPUT_INIT_LOGICAL) != 0)) { + shell_error(sh, "an input cannot be initialised to a logic level"); + shell_help(sh); + return SHELL_CMD_HELP_PRINTED; + } + + if (((flags & GPIO_OUTPUT_INIT_LOW) != 0) && ((flags & GPIO_OUTPUT_INIT_HIGH) != 0)) { + shell_error(sh, "cannot initialise to logic 0 and logic 1"); + shell_help(sh); + return SHELL_CMD_HELP_PRINTED; + } + + if (argc == 5) { + vendor_specific = shell_strtoul(argv[ARGV_VENDOR_SPECIFIC], 0, &ret); + if ((ret == 0) && ((vendor_specific & ~(0xFF00U)) == 0)) { + flags |= vendor_specific; } else { - shell_error(sh, "Error %d reading value", rc); - return -EIO; + /* + * See include/zephyr/dt-bindings/gpio/ for the + * available flags for your vendor. + */ + shell_error(sh, "vendor specific flags must be within " + "the mask 0xFF00"); + shell_help(sh); + return SHELL_CMD_HELP_PRINTED; } } + ret = gpio_pin_configure(gpio.dev, gpio.pin, flags); + if (ret != 0) { + shell_error(sh, "error: %d", ret); + return ret; + } + return 0; } -static int cmd_gpio_set(const struct shell *sh, - size_t argc, char **argv) +static int cmd_gpio_get(const struct shell *sh, size_t argc, char **argv) { - const struct device *dev; - uint8_t index = 0U; - uint8_t value = 0U; + struct sh_gpio gpio; + int value; + int ret; - if (isdigit((unsigned char)argv[args_indx.index][0]) != 0 && - isdigit((unsigned char)argv[args_indx.value][0]) != 0) { - index = (uint8_t)atoi(argv[args_indx.index]); - value = (uint8_t)atoi(argv[args_indx.value]); - } else { - shell_print(sh, "Wrong parameters for set"); - return -EINVAL; + ret = get_sh_gpio(sh, argv, &gpio); + if (ret != 0) { + shell_help(sh); + return SHELL_CMD_HELP_PRINTED; } - dev = device_get_binding(argv[args_indx.port]); - if (dev != NULL) { - index = (uint8_t)atoi(argv[2]); - shell_print(sh, "Writing to %s pin %d", - argv[args_indx.port], index); - gpio_pin_set(dev, index, value); + value = gpio_pin_get(gpio.dev, gpio.pin); + if (value >= 0) { + shell_print(sh, "%u", value); + } else { + shell_error(sh, "error: %d", value); + return value; } return 0; } +static int cmd_gpio_set(const struct shell *sh, size_t argc, char **argv) +{ + struct sh_gpio gpio; + unsigned long value; + int ret = 0; + + ret = get_sh_gpio(sh, argv, &gpio); + if (ret != 0) { + shell_help(sh); + return SHELL_CMD_HELP_PRINTED; + } + + value = shell_strtoul(argv[ARGV_VALUE], 0, &ret); + if (ret != 0) { + shell_help(sh); + return SHELL_CMD_HELP_PRINTED; + } + + ret = gpio_pin_set(gpio.dev, gpio.pin, value != 0); + if (ret != 0) { + shell_error(sh, "error: %d", ret); + return ret; + } + + return 0; +} /* 500 msec = 1/2 sec */ #define SLEEP_TIME_MS 500 -static int cmd_gpio_blink(const struct shell *sh, - size_t argc, char **argv) +static int cmd_gpio_blink(const struct shell *sh, size_t argc, char **argv) { - const struct device *dev; - uint8_t index = 0U; - uint8_t value = 0U; - size_t count = 0; + bool msg_one_shot = true; + struct sh_gpio gpio; + size_t count; char data; + int ret; - if (isdigit((unsigned char)argv[args_indx.index][0]) != 0) { - index = (uint8_t)atoi(argv[args_indx.index]); - } else { - shell_error(sh, "Wrong parameters for blink"); - return -EINVAL; + ret = get_sh_gpio(sh, argv, &gpio); + if (ret != 0) { + shell_help(sh); + return SHELL_CMD_HELP_PRINTED; } - dev = device_get_binding(argv[args_indx.port]); - if (dev != NULL) { - index = (uint8_t)atoi(argv[2]); - shell_fprintf(sh, SHELL_NORMAL, "Blinking port %s index %d.", argv[1], index); - shell_fprintf(sh, SHELL_NORMAL, " Hit any key to exit"); + /* dummy read to clear any pending input */ + (void)sh->iface->api->read(sh->iface, &data, sizeof(data), &count); - /* dummy read to clear any pending input */ + while (true) { (void)sh->iface->api->read(sh->iface, &data, sizeof(data), &count); + if (count != 0) { + break; + } + ret = gpio_pin_toggle(gpio.dev, gpio.pin); + if (ret != 0) { + shell_error(sh, "%d", ret); + break; + } else if (msg_one_shot) { + msg_one_shot = false; + shell_print(sh, "Hit any key to exit"); + } + k_msleep(SLEEP_TIME_MS); + } - while (true) { - (void)sh->iface->api->read(sh->iface, &data, sizeof(data), &count); - if (count != 0) { - break; + return 0; +} + +static void device_name_get(size_t idx, struct shell_static_entry *entry) +{ + if (idx >= ARRAY_SIZE(gpio_list)) { + entry->syntax = NULL; + return; + } + + entry->syntax = gpio_list[idx].dev->name; + entry->handler = NULL; + entry->help = "Device"; + entry->subcmd = gpio_list[idx].subcmd; +} + +SHELL_DYNAMIC_CMD_CREATE(sub_gpio_dev, device_name_get); + +struct pin_info { + const struct device *dev; + bool reserved; + gpio_pin_t pin; + const char *line_name; +}; + +struct pin_order_user_data { + const struct shell *sh; + struct pin_info prev; + struct pin_info next; +}; + +typedef void (*pin_foreach_func_t)(const struct pin_info *info, void *user_data); + +static void print_gpio_ctrl_info(const struct shell *sh, const struct gpio_ctrl *ctrl) +{ + gpio_pin_t pin; + bool reserved; + + shell_print(sh, " ngpios: %u", ctrl->ngpios); + shell_print(sh, " Reserved pin mask: 0x%08X", ctrl->reserved_mask); + + shell_print(sh, ""); + + shell_print(sh, " Reserved Pin Line Name"); + for (pin = 0; pin < GPIO_MAX_PINS_PER_PORT; pin++) { + if ((pin >= ctrl->ngpios) && (pin >= ctrl->line_names_len)) { + /* Out of info */ + break; + } + reserved = (BIT64(pin) & ctrl->reserved_mask) != 0; + shell_print(sh, " %c %2u %s", reserved ? '*' : ' ', + pin, ctrl->line_names[pin]); + } +} + +static void foreach_pin(pin_foreach_func_t func, void *user_data) +{ + gpio_port_pins_t reserved_mask; + struct pin_info info; + gpio_pin_t pin; + size_t i; + + for (i = 0; i < ARRAY_SIZE(gpio_list); i++) { + for (pin = 0; pin < gpio_list[i].ngpios; pin++) { + info.dev = gpio_list[i].dev; + reserved_mask = gpio_list[i].reserved_mask; + info.reserved = (BIT64(pin) & reserved_mask) != 0; + info.pin = pin; + if (pin < gpio_list[i].line_names_len) { + info.line_name = gpio_list[i].line_names[pin]; + } else { + info.line_name = ""; } - gpio_pin_set(dev, index, value); - value = !value; - k_msleep(SLEEP_TIME_MS); + func(&info, user_data); } + } +} + +static int pin_cmp(const struct pin_info *a, const struct pin_info *b) +{ + int result = strcmp(a->line_name, b->line_name); + + if (result != 0) { + return result; + } + result = strcmp(a->dev->name, b->dev->name); + if (result != 0) { + return result; + } + result = (int)a->pin - (int)b->pin; + + return result; +} + +static void pin_get_next(const struct pin_info *info, void *user_data) +{ + struct pin_order_user_data *data = user_data; + int result; - shell_fprintf(sh, SHELL_NORMAL, "\n"); + if (data->prev.line_name != NULL) { + result = pin_cmp(info, &data->prev); + } else { + result = 1; + } + if (result > 0) { + if (data->next.line_name == NULL) { + data->next = *info; + return; + } + result = pin_cmp(info, &data->next); + if (result < 0) { + data->next = *info; + } } +} + +static void pin_ordered(const struct pin_info *info, void *user_data) +{ + struct pin_order_user_data *data = user_data; + + ARG_UNUSED(info); + + foreach_pin(pin_get_next, data); + + shell_print(data->sh, " %-12s %-8c %-16s %2u", + data->next.line_name, + data->next.reserved ? '*' : ' ', + data->next.dev->name, + data->next.pin); + + data->prev = data->next; + data->next.line_name = NULL; +} + +static void print_ordered_info(const struct shell *sh) +{ + struct pin_order_user_data data = {0}; + + data.sh = sh; + + shell_print(sh, " %-12s %-8s %-16s %-3s", + "Line", "Reserved", "Device", "Pin"); + + foreach_pin(pin_ordered, &data); +} + +static int cmd_gpio_info(const struct shell *sh, size_t argc, char **argv) +{ + const struct gpio_ctrl *ctrl = get_gpio_ctrl(argv[ARGV_DEV]); + + if (ctrl == NULL) { + /* No device specified */ + print_ordered_info(sh); + return 0; + } + + print_gpio_ctrl_info(sh, ctrl); return 0; } SHELL_STATIC_SUBCMD_SET_CREATE(sub_gpio, - SHELL_CMD_ARG(conf, NULL, "Configure GPIO", cmd_gpio_conf, 4, 0), - SHELL_CMD_ARG(get, NULL, "Get GPIO value", cmd_gpio_get, 3, 0), - SHELL_CMD_ARG(set, NULL, "Set GPIO", cmd_gpio_set, 4, 0), - SHELL_CMD_ARG(blink, NULL, "Blink GPIO", cmd_gpio_blink, 3, 0), - SHELL_SUBCMD_SET_END /* Array terminated. */ - ); + SHELL_CMD_ARG(conf, &sub_gpio_dev, + "Configure GPIO pin\n" + "Usage: gpio conf [u|d][h|l][0|1]> [vendor specific]\n" + " - input|output\n" + "[u|d] - pull up|pull down, otherwise open\n" + "[h|l] - active high|active low, otherwise defaults to active high\n" + "[0|1] - initialise to logic 0|logic 1, otherwise defaults to logic 0\n" + "[vendor specific] - configuration flags within the mask 0xFF00\n" + " see include/zephyr/dt-bindings/gpio/", + cmd_gpio_conf, 4, 1), + SHELL_CMD_ARG(get, &sub_gpio_dev, + "Get GPIO pin value\n" + "Usage: gpio get ", cmd_gpio_get, 3, 0), + SHELL_CMD_ARG(set, &sub_gpio_dev, + "Set GPIO pin value\n" + "Usage: gpio set ", cmd_gpio_set, 4, 0), + SHELL_COND_CMD_ARG(CONFIG_GPIO_SHELL_BLINK_CMD, blink, &sub_gpio_dev, + "Blink GPIO pin\n" + "Usage: gpio blink ", cmd_gpio_blink, 3, 0), + SHELL_COND_CMD_ARG(CONFIG_GPIO_SHELL_INFO_CMD, info, &sub_gpio_dev, + "GPIO Information\n" + "Usage: gpio info [device]", cmd_gpio_info, 1, 1), + SHELL_SUBCMD_SET_END /* Array terminated. */ +); SHELL_CMD_REGISTER(gpio, &sub_gpio, "GPIO commands", NULL); diff --git a/drivers/gpio/gpio_sifive.c b/drivers/gpio/gpio_sifive.c index a3b5292fe14..77703f25707 100644 --- a/drivers/gpio/gpio_sifive.c +++ b/drivers/gpio/gpio_sifive.c @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -77,7 +78,7 @@ static inline unsigned int gpio_sifive_pin_irq(unsigned int base_irq, int pin) if (level == 1) { pin_irq = base_irq + pin; } else if (level == 2) { - pin_irq = base_irq + (pin << 8); + pin_irq = base_irq + (pin << CONFIG_1ST_LEVEL_INTERRUPT_BITS); } return pin_irq; @@ -104,7 +105,8 @@ static void gpio_sifive_irq_handler(const struct device *dev) const struct gpio_sifive_config *cfg = DEV_GPIO_CFG(dev); /* Calculate pin and mask from base level 2 line */ - uint8_t pin = 1 + (riscv_plic_get_irq() - (uint8_t)(cfg->gpio_irq_base >> 8)); + uint8_t pin = 1 + (riscv_plic_get_irq() - + (uint8_t)(cfg->gpio_irq_base >> CONFIG_1ST_LEVEL_INTERRUPT_BITS)); /* This peripheral tracks each condition separately: a * transition from low to high will mark the pending bit for @@ -375,7 +377,7 @@ DEVICE_DT_INST_DEFINE(0, &gpio_sifive_driver); #define IRQ_INIT(n) \ -IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, n, irq), \ +IRQ_CONNECT(DT_INST_IRQN_BY_IDX(0, n), \ DT_INST_IRQ_BY_IDX(0, n, priority), \ gpio_sifive_irq_handler, \ DEVICE_DT_INST_GET(0), \ diff --git a/drivers/gpio/gpio_smartbond.c b/drivers/gpio/gpio_smartbond.c index 8bfa4f8d9a1..81ce31296f2 100644 --- a/drivers/gpio/gpio_smartbond.c +++ b/drivers/gpio/gpio_smartbond.c @@ -13,6 +13,7 @@ #include #include +#include #define GPIO_MODE_RESET 0x200 @@ -56,6 +57,8 @@ struct gpio_smartbond_wkup_regs { struct gpio_smartbond_data { /* gpio_driver_data needs to be first */ struct gpio_driver_data common; + /* Pins that are configured for both edges (handled by software) */ + gpio_port_pins_t both_edges_pins; sys_slist_t callbacks; }; @@ -66,6 +69,8 @@ struct gpio_smartbond_config { volatile uint32_t *mode_regs; volatile struct gpio_smartbond_latch_regs *latch_regs; volatile struct gpio_smartbond_wkup_regs *wkup_regs; + /* Value of TRIG_SELECT for PDC_CTRLx_REG entry */ + uint8_t wkup_trig_select; }; static void gpio_smartbond_wkup_init(void) @@ -184,34 +189,71 @@ static int gpio_smartbond_port_toggle_bits(const struct device *dev, return 0; } +static void gpio_smartbond_arm_next_edge_interrupt(const struct device *dev, + uint32_t pin_mask) +{ + const struct gpio_smartbond_config *config = dev->config; + uint32_t pin_value; + + do { + pin_value = config->data_regs->data & pin_mask; + if (pin_value) { + config->wkup_regs->pol |= pin_mask; + } else { + config->wkup_regs->pol &= ~pin_mask; + } + } while (pin_value != (config->data_regs->data & pin_mask)); +} + static int gpio_smartbond_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, enum gpio_int_mode mode, enum gpio_int_trig trig) { const struct gpio_smartbond_config *config = dev->config; + struct gpio_smartbond_data *data = dev->data; + uint32_t pin_mask = BIT(pin); +#if CONFIG_PM + int trig_select_id = (config->wkup_trig_select << 5) | pin; + int pdc_ix; +#endif /* Not supported by hardware */ if (mode == GPIO_INT_MODE_LEVEL) { return -ENOTSUP; } +#if CONFIG_PM + pdc_ix = da1469x_pdc_find(trig_select_id, MCU_PDC_MASTER_M33, MCU_PDC_EN_XTAL); +#endif if (mode == GPIO_INT_MODE_DISABLED) { - config->wkup_regs->sel &= ~BIT(pin); - config->wkup_regs->clear = BIT(pin); + config->wkup_regs->sel &= ~pin_mask; + config->wkup_regs->clear = pin_mask; + data->both_edges_pins &= ~pin_mask; +#if CONFIG_PM + da1469x_pdc_del(pdc_ix); +#endif } else { if (trig == GPIO_INT_TRIG_BOTH) { /* Not supported by hardware */ - return -ENOTSUP; - } - - if (trig == GPIO_INT_TRIG_HIGH) { - config->wkup_regs->pol &= ~BIT(pin); + data->both_edges_pins |= pin_mask; + gpio_smartbond_arm_next_edge_interrupt(dev, pin_mask); + } else if (trig == GPIO_INT_TRIG_HIGH) { + config->wkup_regs->pol &= ~pin_mask; } else { - config->wkup_regs->pol |= BIT(pin); + config->wkup_regs->pol |= pin_mask; } - config->wkup_regs->sel |= BIT(pin); + config->wkup_regs->sel |= pin_mask; +#if CONFIG_PM + if (pdc_ix < 0) { + pdc_ix = da1469x_pdc_add(trig_select_id, MCU_PDC_MASTER_M33, + MCU_PDC_EN_XTAL); + } + if (pdc_ix < 0) { + return -ENOMEM; + } +#endif } return 0; @@ -230,10 +272,21 @@ static void gpio_smartbond_isr(const struct device *dev) const struct gpio_smartbond_config *config = dev->config; struct gpio_smartbond_data *data = dev->data; uint32_t stat; + uint32_t two_edge_triggered; WAKEUP->WKUP_RESET_IRQ_REG = WAKEUP_WKUP_RESET_IRQ_REG_WKUP_IRQ_RST_Msk; stat = config->wkup_regs->status; + + two_edge_triggered = stat & data->both_edges_pins; + while (two_edge_triggered) { + int pos = find_lsb_set(two_edge_triggered) - 1; + + two_edge_triggered &= ~BIT(pos); + /* Re-arm for other edge */ + gpio_smartbond_arm_next_edge_interrupt(dev, BIT(pos)); + } + config->wkup_regs->clear = stat; gpio_fire_callbacks(&data->callbacks, dev, stat); @@ -264,6 +317,7 @@ static const struct gpio_driver_api gpio_smartbond_drv_api_funcs = { DT_INST_REG_ADDR_BY_NAME(id, latch), \ .wkup_regs = (volatile struct gpio_smartbond_wkup_regs *) \ DT_INST_REG_ADDR_BY_NAME(id, wkup), \ + .wkup_trig_select = id, \ }; \ \ static struct gpio_smartbond_data gpio_smartbond_p##id##_data; \ @@ -283,7 +337,7 @@ static const struct gpio_driver_api gpio_smartbond_drv_api_funcs = { NULL, \ &gpio_smartbond_p##id##_data, \ &gpio_smartbond_p##id##_config, \ - POST_KERNEL, \ + PRE_KERNEL_1, \ CONFIG_GPIO_INIT_PRIORITY, \ &gpio_smartbond_drv_api_funcs); diff --git a/drivers/gpio/gpio_tle9104.c b/drivers/gpio/gpio_tle9104.c new file mode 100644 index 00000000000..072828dec88 --- /dev/null +++ b/drivers/gpio/gpio_tle9104.c @@ -0,0 +1,535 @@ +/* + * Copyright (c) 2023 SILA Embedded Solutions GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT infineon_tle9104 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(gpio_tle9104, CONFIG_GPIO_LOG_LEVEL); + +/* + * The values for the defines below as well as the register definitions were + * taken from the datasheet, which can be found at: + * https://www.infineon.com/dgdl/Infineon-TLE9104SH-DataSheet-v01_31-EN.pdf?fileId=5546d462766cbe86017676144d76581b + */ +#define TLE9104_RESET_DURATION_TIME_US 10 +#define TLE9104_RESET_DURATION_WAIT_TIME_SAFETY_MARGIN_US 200 +#define TLE9104_RESET_DURATION_WAIT_TIME_US 10 +#define TLE9104_GPIO_COUNT 4 +#define TLE9104_INITIALIZATION_TIMEOUT_MS 1 +#define TLE9104_ICVERSIONID 0xB1 + +#define TLE9104_FRAME_RW_POS 15 +#define TLE9104_FRAME_PARITY_POS 14 +#define TLE9104_FRAME_FAULTCOMMUNICATION_POS 13 +#define TLE9104_FRAME_FAULTGLOBAL_POS 12 +#define TLE9104_FRAME_ADDRESS_POS 8 +#define TLE9104_FRAME_DATA_POS 0 + +#define TLE9104_CFG_CWDTIME_LENGTH 2 +#define TLE9104_CFG_CWDTIME_POS 6 + +#define TLE9104_CTRL_OUT1ONS_BIT BIT(1) +#define TLE9104_CTRL_OUT1ONC_BIT BIT(0) +#define TLE9104_CFG_OUT1DD_BIT BIT(0) +#define TLE9104_GLOBALSTATUS_OUTEN_BIT BIT(7) +#define TLE9104_GLOBALSTATUS_POR_LATCH_BIT BIT(0) +#define TLE9104_SPIFRAME_FAULTCOMMUNICATION_BIT BIT(13) + +enum tle9104_register { + TLE9104REGISTER_CTRL = 0x00, + TLE9104REGISTER_CFG = 0x01, + TLE9104REGISTER_GLOBALSTATUS = 0x07, + TLE9104REGISTER_ICVID = 0x08, +}; + +struct tle9104_config { + /* gpio_driver_config needs to be first */ + struct gpio_driver_config common; + + struct spi_dt_spec bus; + const struct gpio_dt_spec gpio_reset; + const struct gpio_dt_spec gpio_enable; + const struct gpio_dt_spec gpio_control[TLE9104_GPIO_COUNT]; +}; + +struct tle9104_data { + /* gpio_driver_data needs to be first */ + struct gpio_driver_data common; + /* each bit is one output channel, bit 0 = OUT1, ... */ + uint8_t state; + /* same as state, just kept for checking what has to be updated */ + uint8_t previous_state; + /* each bit defines if the output channel is configured, see state */ + uint8_t configured; + struct k_mutex lock; +}; + +static void tle9104_set_cfg_cwdtime(uint8_t *destination, uint8_t value) +{ + uint8_t length = TLE9104_CFG_CWDTIME_LENGTH; + uint8_t pos = TLE9104_CFG_CWDTIME_POS; + + *destination &= ~GENMASK(pos + length - 1, pos); + *destination |= FIELD_PREP(GENMASK(pos + length - 1, pos), value); +} + +static int tle9104_calculate_parity(uint16_t value) +{ + int parity = 1 + POPCOUNT(value); + + if ((value & BIT(TLE9104_FRAME_PARITY_POS)) != 0) { + parity--; + } + + return parity % 2; +} + +static void tle9104_apply_parity(uint16_t *value) +{ + int parity = tle9104_calculate_parity(*value); + + WRITE_BIT(*value, TLE9104_FRAME_PARITY_POS, parity); +} + +static bool tle9104_check_parity(uint16_t value) +{ + int parity = tle9104_calculate_parity(value); + + return ((value & BIT(TLE9104_FRAME_PARITY_POS)) >> TLE9104_FRAME_PARITY_POS) == parity; +} + +static int tle9104_transceive_frame(const struct device *dev, bool write, + enum tle9104_register write_reg, uint8_t write_data, + enum tle9104_register *read_reg, uint8_t *read_data) +{ + const struct tle9104_config *config = dev->config; + uint16_t write_frame; + uint16_t read_frame; + int result; + uint8_t buffer_tx[2]; + uint8_t buffer_rx[ARRAY_SIZE(buffer_tx)]; + const struct spi_buf tx_buf[] = {{ + .buf = buffer_tx, + .len = ARRAY_SIZE(buffer_tx), + }}; + const struct spi_buf rx_buf[] = {{ + .buf = buffer_rx, + .len = ARRAY_SIZE(buffer_rx), + }}; + const struct spi_buf_set tx = { + .buffers = tx_buf, + .count = ARRAY_SIZE(tx_buf), + }; + const struct spi_buf_set rx = { + .buffers = rx_buf, + .count = ARRAY_SIZE(rx_buf), + }; + + write_frame = write_data << TLE9104_FRAME_DATA_POS; + write_frame |= write_reg << TLE9104_FRAME_ADDRESS_POS; + WRITE_BIT(write_frame, TLE9104_FRAME_RW_POS, write); + tle9104_apply_parity(&write_frame); + sys_put_be16(write_frame, buffer_tx); + LOG_DBG("writing in register 0x%02X of TLE9104 value 0x%02X, complete frame 0x%04X", + write_reg, write_data, write_frame); + + result = spi_transceive_dt(&config->bus, &tx, &rx); + if (result != 0) { + LOG_ERR("spi_write failed with error %i", result); + return result; + } + + read_frame = sys_get_be16(buffer_rx); + LOG_DBG("received complete frame 0x%04X", read_frame); + + if (!tle9104_check_parity(read_frame)) { + LOG_ERR("parity check for received frame of TLE9104 failed"); + return -EIO; + } + + if ((TLE9104_SPIFRAME_FAULTCOMMUNICATION_BIT & read_frame) != 0) { + LOG_WRN("communication fault reported by TLE9104"); + } + + *read_reg = FIELD_GET(GENMASK(TLE9104_FRAME_FAULTGLOBAL_POS - 1, TLE9104_FRAME_ADDRESS_POS), + read_frame); + *read_data = FIELD_GET(GENMASK(TLE9104_FRAME_ADDRESS_POS - 1, TLE9104_FRAME_DATA_POS), + read_frame); + + return 0; +} + +static int tle9104_write_register(const struct device *dev, enum tle9104_register reg, + uint8_t value) +{ + enum tle9104_register read_reg; + uint8_t read_data; + + return tle9104_transceive_frame(dev, true, reg, value, &read_reg, &read_data); +} + +static int tle9104_write_state(const struct device *dev) +{ + const struct tle9104_config *config = dev->config; + struct tle9104_data *data = dev->data; + bool spi_update_required = false; + uint8_t register_ctrl = 0x00; + int result; + + LOG_DBG("writing state 0x%02X to TLE9104", data->state); + + for (size_t i = 0; i < TLE9104_GPIO_COUNT; ++i) { + uint8_t mask = GENMASK(i, i); + bool current_value = (data->state & mask) != 0; + bool previous_value = (data->previous_state & mask) != 0; + + /* + * Setting the OUTx_ON bits results in a high impedance output, + * clearing them pulls the output to ground. Therefore the + * meaning here is intentionally inverted, as this will then turn + * out for a low active open drain output to be pulled to ground + * if set to off. + */ + if (current_value == 0) { + register_ctrl |= TLE9104_CTRL_OUT1ONS_BIT << (2 * i); + } else { + register_ctrl |= TLE9104_CTRL_OUT1ONC_BIT << (2 * i); + } + + if (current_value == previous_value) { + continue; + } + + if (config->gpio_control[i].port == NULL) { + spi_update_required = true; + continue; + } + + result = gpio_pin_set_dt(&config->gpio_control[i], current_value); + if (result != 0) { + LOG_ERR("unable to set control GPIO"); + return result; + } + } + + if (spi_update_required) { + result = tle9104_write_register(dev, TLE9104REGISTER_CTRL, register_ctrl); + if (result != 0) { + LOG_ERR("unable to set control register"); + return result; + } + } + + data->previous_state = data->state; + + return 0; +} + +static int tle9104_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) +{ + struct tle9104_data *data = dev->data; + int result; + + /* cannot execute a bus operation in an ISR context */ + if (k_is_in_isr()) { + return -EWOULDBLOCK; + } + + if (pin >= TLE9104_GPIO_COUNT) { + LOG_ERR("invalid pin nummber %i", pin); + return -EINVAL; + } + + if ((flags & GPIO_INPUT) != 0) { + LOG_ERR("cannot configure pin as input"); + return -ENOTSUP; + } + + if ((flags & GPIO_OUTPUT) == 0) { + LOG_ERR("pin must be configured as an output"); + return -ENOTSUP; + } + + if ((flags & GPIO_SINGLE_ENDED) == 0) { + LOG_ERR("pin must be configured as single ended"); + return -ENOTSUP; + } + + if ((flags & GPIO_LINE_OPEN_DRAIN) == 0) { + LOG_ERR("pin must be configured as open drain"); + return -ENOTSUP; + } + + if ((flags & GPIO_PULL_UP) != 0) { + LOG_ERR("pin cannot have a pull up configured"); + return -ENOTSUP; + } + + if ((flags & GPIO_PULL_DOWN) != 0) { + LOG_ERR("pin cannot have a pull down configured"); + return -ENOTSUP; + } + + k_mutex_lock(&data->lock, K_FOREVER); + + if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) { + WRITE_BIT(data->state, pin, 0); + } else if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) { + WRITE_BIT(data->state, pin, 1); + } + + WRITE_BIT(data->configured, pin, 1); + result = tle9104_write_state(dev); + k_mutex_unlock(&data->lock); + + return result; +} + +static int tle9104_port_get_raw(const struct device *dev, uint32_t *value) +{ + ARG_UNUSED(dev); + ARG_UNUSED(value); + + LOG_ERR("input pins are not available"); + return -ENOTSUP; +} + +static int tle9104_port_set_masked_raw(const struct device *dev, uint32_t mask, uint32_t value) +{ + struct tle9104_data *data = dev->data; + int result; + + /* cannot execute a bus operation in an ISR context */ + if (k_is_in_isr()) { + return -EWOULDBLOCK; + } + + k_mutex_lock(&data->lock, K_FOREVER); + data->state = (data->state & ~mask) | (mask & value); + result = tle9104_write_state(dev); + k_mutex_unlock(&data->lock); + + return result; +} + +static int tle9104_port_set_bits_raw(const struct device *dev, uint32_t mask) +{ + return tle9104_port_set_masked_raw(dev, mask, mask); +} + +static int tle9104_port_clear_bits_raw(const struct device *dev, uint32_t mask) +{ + return tle9104_port_set_masked_raw(dev, mask, 0); +} + +static int tle9104_port_toggle_bits(const struct device *dev, uint32_t mask) +{ + struct tle9104_data *data = dev->data; + int result; + + /* cannot execute a bus operation in an ISR context */ + if (k_is_in_isr()) { + return -EWOULDBLOCK; + } + + k_mutex_lock(&data->lock, K_FOREVER); + data->state ^= mask; + result = tle9104_write_state(dev); + k_mutex_unlock(&data->lock); + + return result; +} + +static int tle9104_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, + enum gpio_int_mode mode, enum gpio_int_trig trig) +{ + ARG_UNUSED(dev); + ARG_UNUSED(pin); + ARG_UNUSED(mode); + ARG_UNUSED(trig); + return -ENOTSUP; +} + +static const struct gpio_driver_api api_table = { + .pin_configure = tle9104_pin_configure, + .port_get_raw = tle9104_port_get_raw, + .port_set_masked_raw = tle9104_port_set_masked_raw, + .port_set_bits_raw = tle9104_port_set_bits_raw, + .port_clear_bits_raw = tle9104_port_clear_bits_raw, + .port_toggle_bits = tle9104_port_toggle_bits, + .pin_interrupt_configure = tle9104_pin_interrupt_configure, +}; + +static int tle9104_init(const struct device *dev) +{ + const struct tle9104_config *config = dev->config; + struct tle9104_data *data = dev->data; + uint8_t register_cfg; + uint8_t register_globalstatus; + uint8_t register_icvid; + enum tle9104_register read_reg; + int result; + + LOG_DBG("initialize TLE9104 instance %s", dev->name); + + result = k_mutex_init(&data->lock); + if (result != 0) { + LOG_ERR("unable to initialize mutex"); + return result; + } + + if (!spi_is_ready_dt(&config->bus)) { + LOG_ERR("SPI bus %s is not ready", config->bus.bus->name); + return -ENODEV; + } + + register_cfg = 0x00; + + for (int i = 0; i < TLE9104_GPIO_COUNT; ++i) { + const struct gpio_dt_spec *current = config->gpio_control + i; + + if (current->port == NULL) { + LOG_DBG("got no control port for output %i, will control it via SPI", i); + continue; + } + + register_cfg |= TLE9104_CFG_OUT1DD_BIT << i; + + if (!device_is_ready(current->port)) { + LOG_ERR("control GPIO %s is not ready", current->port->name); + return -ENODEV; + } + + result = gpio_pin_configure_dt(current, GPIO_OUTPUT_INACTIVE); + if (result != 0) { + LOG_ERR("failed to initialize control GPIO %i", i); + return result; + } + } + + if (config->gpio_enable.port != NULL) { + if (!device_is_ready(config->gpio_enable.port)) { + LOG_ERR("enable GPIO %s is not ready", config->gpio_enable.port->name); + return -ENODEV; + } + + result = gpio_pin_configure_dt(&config->gpio_enable, GPIO_OUTPUT_ACTIVE); + if (result != 0) { + LOG_ERR("failed to enable TLE9104"); + return result; + } + } + + result = gpio_pin_configure_dt(&config->gpio_reset, GPIO_OUTPUT_ACTIVE); + if (result != 0) { + LOG_ERR("failed to initialize GPIO for reset"); + return result; + } + + k_busy_wait(TLE9104_RESET_DURATION_TIME_US); + gpio_pin_set_dt(&config->gpio_reset, 0); + k_busy_wait(TLE9104_RESET_DURATION_WAIT_TIME_US + + TLE9104_RESET_DURATION_WAIT_TIME_SAFETY_MARGIN_US); + + /* + * The first read value should be the ICVID, this acts also as the setup of the + * global status register address. + */ + result = tle9104_transceive_frame(dev, false, TLE9104REGISTER_GLOBALSTATUS, 0x00, &read_reg, + ®ister_icvid); + if (result != 0) { + return result; + } + + if (read_reg != TLE9104REGISTER_ICVID) { + LOG_ERR("expected to read register ICVID, got instead 0x%02X", read_reg); + return -EIO; + } + + if (register_icvid != TLE9104_ICVERSIONID) { + LOG_ERR("got unexpected IC version id 0x%02X", register_icvid); + return -EIO; + } + + result = tle9104_transceive_frame(dev, false, TLE9104REGISTER_GLOBALSTATUS, 0x00, &read_reg, + ®ister_globalstatus); + if (result != 0) { + return result; + } + + if (read_reg != TLE9104REGISTER_GLOBALSTATUS) { + LOG_ERR("expected to read register GLOBALSTATUS, got instead 0x%02X", read_reg); + return -EIO; + } + + if ((register_globalstatus & TLE9104_GLOBALSTATUS_POR_LATCH_BIT) == 0) { + LOG_ERR("no power on reset detected"); + return -EIO; + } + + result = tle9104_write_register(dev, TLE9104REGISTER_CFG, register_cfg); + if (result != 0) { + LOG_ERR("unable to write configuration"); + return result; + } + + register_globalstatus = 0x00; + /* disable communication watchdog */ + tle9104_set_cfg_cwdtime(®ister_cfg, 0); + /* enable outputs */ + register_globalstatus |= TLE9104_GLOBALSTATUS_OUTEN_BIT; + + result = tle9104_write_register(dev, TLE9104REGISTER_GLOBALSTATUS, register_globalstatus); + if (result != 0) { + LOG_ERR("unable to write global status"); + return result; + } + + return 0; +} + +BUILD_ASSERT(CONFIG_GPIO_TLE9104_INIT_PRIORITY > CONFIG_SPI_INIT_PRIORITY, + "TLE9104 must be initialized after SPI"); + +#define TLE9104_INIT_GPIO_FIELDS(inst, gpio) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, gpio), \ + (GPIO_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst), gpio, 0)), ({0})) + +#define TLE9104_INIT(inst) \ + static const struct tle9104_config tle9104_##inst##_config = { \ + .common = { \ + .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(inst), \ + }, \ + .bus = SPI_DT_SPEC_INST_GET( \ + inst, SPI_OP_MODE_MASTER | SPI_MODE_CPHA | SPI_WORD_SET(8), 0), \ + .gpio_enable = TLE9104_INIT_GPIO_FIELDS(inst, en_gpios), \ + .gpio_reset = GPIO_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst), resn_gpios, 0), \ + .gpio_control = { \ + TLE9104_INIT_GPIO_FIELDS(inst, in1_gpios), \ + TLE9104_INIT_GPIO_FIELDS(inst, in2_gpios), \ + TLE9104_INIT_GPIO_FIELDS(inst, in3_gpios), \ + TLE9104_INIT_GPIO_FIELDS(inst, in4_gpios), \ + }, \ + }; \ + \ + static struct tle9104_data tle9104_##inst##_drvdata; \ + \ + /* This has to be initialized after the SPI peripheral. */ \ + DEVICE_DT_INST_DEFINE(inst, tle9104_init, NULL, &tle9104_##inst##_drvdata, \ + &tle9104_##inst##_config, POST_KERNEL, \ + CONFIG_GPIO_TLE9104_INIT_PRIORITY, &api_table); + +DT_INST_FOREACH_STATUS_OKAY(TLE9104_INIT) diff --git a/drivers/hwinfo/CMakeLists.txt b/drivers/hwinfo/CMakeLists.txt index 6ff5d1929f6..437fbf969cf 100644 --- a/drivers/hwinfo/CMakeLists.txt +++ b/drivers/hwinfo/CMakeLists.txt @@ -8,6 +8,7 @@ zephyr_library_sources_ifdef(CONFIG_USERSPACE hwinfo_handlers.c) zephyr_library_sources_ifdef(CONFIG_HWINFO hwinfo_weak_impl.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_SHELL hwinfo_shell.c) +zephyr_library_sources_ifdef(CONFIG_HWINFO_CC13XX_CC26XX hwinfo_cc13xx_cc26xx.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_ESP32 hwinfo_esp32.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_GECKO hwinfo_gecko.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_IMXRT hwinfo_imxrt.c) diff --git a/drivers/hwinfo/Kconfig b/drivers/hwinfo/Kconfig index 879f2b3e9d7..7c4cc7f0805 100644 --- a/drivers/hwinfo/Kconfig +++ b/drivers/hwinfo/Kconfig @@ -16,11 +16,46 @@ source "subsys/logging/Kconfig.template.log_config" config HWINFO_SHELL bool "HWINFO Shell" - default y depends on SHELL help Enable hwinfo Shell for testing. +menuconfig HWINFO_CC13XX_CC26XX + bool "TI SimpleLink CC13xx/CC26xx hwinfo driver" + default y + depends on SOC_SERIES_CC13X2_CC26X2 || SOC_SERIES_CC13X2X7_CC26X2X7 + help + Enable TI SimpleLink CC13xx/CC26xx hwinfo driver. + +if HWINFO_CC13XX_CC26XX + +config HWINFO_CC13XX_CC26XX_ALWAYS_USE_FACTORY_DEFAULT + bool "Ignore CCFG and always use factory value" + default y + help + Always return factory pre-programmed values, stored in FCFG and ignore + values provided in CCFG (Customer Configuration). + +choice + prompt "Select MAC address type for device ID" + default HWINFO_CC13XX_CC26XX_USE_IEEE_MAC + help + Specify the MAC address type to be used as device ID by the driver. + +config HWINFO_CC13XX_CC26XX_USE_IEEE_MAC + bool "Use IEEE 802.15.4 extended address" + help + Use 8-bytes length IEEE 802.15.4 extended address as device ID value. + +config HWINFO_CC13XX_CC26XX_USE_BLE_MAC + bool "Use BLE MAC address" + help + Use 6-bytes length BLE MAC address as device ID value. + +endchoice + +endif + config HWINFO_STM32 bool "STM32 hwinfo" default y diff --git a/drivers/hwinfo/hwinfo_cc13xx_cc26xx.c b/drivers/hwinfo/hwinfo_cc13xx_cc26xx.c new file mode 100644 index 00000000000..536ff15a192 --- /dev/null +++ b/drivers/hwinfo/hwinfo_cc13xx_cc26xx.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2023 Piotr Dymacz + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_HWINFO_CC13XX_CC26XX_USE_BLE_MAC +#define CC13XX_CC26XX_DEVID_SIZE 6 +#else +#define CC13XX_CC26XX_DEVID_SIZE 8 +#endif + +ssize_t z_impl_hwinfo_get_device_id(uint8_t *buffer, size_t length) +{ + uint8_t *mac; + + if (IS_ENABLED(CONFIG_HWINFO_CC13XX_CC26XX_USE_BLE_MAC)) { + if (IS_ENABLED(CONFIG_HWINFO_CC13XX_CC26XX_ALWAYS_USE_FACTORY_DEFAULT) || + sys_read32(CCFG_BASE + CCFG_O_IEEE_BLE_0) == 0xFFFFFFFF || + sys_read32(CCFG_BASE + CCFG_O_IEEE_BLE_1) == 0xFFFFFFFF) { + mac = (uint8_t *)(FCFG1_BASE + FCFG1_O_MAC_BLE_0); + } else { + mac = (uint8_t *)(CCFG_BASE + CCFG_O_IEEE_BLE_0); + } + } else if (IS_ENABLED(CONFIG_HWINFO_CC13XX_CC26XX_USE_IEEE_MAC)) { + if (IS_ENABLED(CONFIG_HWINFO_CC13XX_CC26XX_ALWAYS_USE_FACTORY_DEFAULT) || + sys_read32(CCFG_BASE + CCFG_O_IEEE_MAC_0) == 0xFFFFFFFF || + sys_read32(CCFG_BASE + CCFG_O_IEEE_MAC_1) == 0xFFFFFFFF) { + mac = (uint8_t *)(FCFG1_BASE + FCFG1_O_MAC_15_4_0); + } else { + mac = (uint8_t *)(CCFG_BASE + CCFG_O_IEEE_MAC_0); + } + } + + if (length > CC13XX_CC26XX_DEVID_SIZE) { + length = CC13XX_CC26XX_DEVID_SIZE; + } + + /* Provide device ID (MAC) in big endian */ + sys_memcpy_swap(buffer, mac, length); + + return length; +} + +int z_impl_hwinfo_get_reset_cause(uint32_t *cause) +{ + uint32_t reset_src; + + reset_src = SysCtrlResetSourceGet(); + + switch (reset_src) { + case RSTSRC_PWR_ON: + *cause = RESET_POR; + break; + case RSTSRC_PIN_RESET: + *cause = RESET_PIN; + break; + case RSTSRC_VDDS_LOSS: + __fallthrough; + case RSTSRC_VDDR_LOSS: + *cause = RESET_BROWNOUT; + break; + case RSTSRC_CLK_LOSS: + *cause = RESET_CLOCK; + break; + case RSTSRC_SYSRESET: + *cause = RESET_SOFTWARE; + break; + } + + return 0; +} + +int z_impl_hwinfo_clear_reset_cause(void) +{ + return -ENOSYS; +} + +int z_impl_hwinfo_get_supported_reset_cause(uint32_t *supported) +{ + *supported = (RESET_PIN + | RESET_SOFTWARE + | RESET_BROWNOUT + | RESET_POR + | RESET_CLOCK); + + return 0; +} diff --git a/drivers/hwinfo/hwinfo_handlers.c b/drivers/hwinfo/hwinfo_handlers.c index dd411f265d0..02058f9b955 100644 --- a/drivers/hwinfo/hwinfo_handlers.c +++ b/drivers/hwinfo/hwinfo_handlers.c @@ -4,12 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include ssize_t z_vrfy_hwinfo_get_device_id(uint8_t *buffer, size_t length) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(buffer, length)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(buffer, length)); return z_impl_hwinfo_get_device_id((uint8_t *)buffer, (size_t)length); } @@ -21,7 +21,7 @@ int z_vrfy_hwinfo_get_reset_cause(uint32_t *cause) uint32_t cause_copy; ret = z_impl_hwinfo_get_reset_cause(&cause_copy); - Z_OOPS(z_user_to_copy(cause, &cause_copy, sizeof(uint32_t))); + K_OOPS(k_usermode_to_copy(cause, &cause_copy, sizeof(uint32_t))); return ret; } @@ -40,7 +40,7 @@ int z_vrfy_hwinfo_get_supported_reset_cause(uint32_t *supported) uint32_t supported_copy; ret = z_impl_hwinfo_get_supported_reset_cause(&supported_copy); - Z_OOPS(z_user_to_copy(supported, &supported_copy, sizeof(uint32_t))); + K_OOPS(k_usermode_to_copy(supported, &supported_copy, sizeof(uint32_t))); return ret; } diff --git a/drivers/hwspinlock/hwspinlock_handlers.c b/drivers/hwspinlock/hwspinlock_handlers.c index a8e6c2a132e..7064293be4b 100644 --- a/drivers/hwspinlock/hwspinlock_handlers.c +++ b/drivers/hwspinlock/hwspinlock_handlers.c @@ -5,11 +5,11 @@ */ #include -#include +#include static inline int z_vrfy_hwspinlock_trylock(const struct device *dev, uint32_t id) { - Z_OOPS(Z_SYSCALL_DRIVER_HWSPINLOCK(dev, trylock)); + K_OOPS(K_SYSCALL_DRIVER_HWSPINLOCK(dev, trylock)); return z_impl_hwspinlock_trylock(dev, id); } @@ -17,7 +17,7 @@ static inline int z_vrfy_hwspinlock_trylock(const struct device *dev, uint32_t i static inline void z_vrfy_hwspinlock_lock(const struct device *dev, uint32_t id) { - Z_OOPS(Z_SYSCALL_DRIVER_HWSPINLOCK(dev, lock)); + K_OOPS(K_SYSCALL_DRIVER_HWSPINLOCK(dev, lock)); z_impl_hwspinlock_lock(dev, id); } @@ -25,7 +25,7 @@ static inline void z_vrfy_hwspinlock_lock(const struct device *dev, uint32_t id) static inline void z_vrfy_hwspinlock_unlock(const struct device *dev, uint32_t id) { - Z_OOPS(Z_SYSCALL_DRIVER_HWSPINLOCK(dev, unlock)); + K_OOPS(K_SYSCALL_DRIVER_HWSPINLOCK(dev, unlock)); z_impl_hwspinlock_unlock(dev, id); } @@ -33,7 +33,7 @@ static inline void z_vrfy_hwspinlock_unlock(const struct device *dev, uint32_t i static inline uint32_t z_vrfy_hwspinlock_get_max_id(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_HWSPINLOCK(dev, get_max_id)); + K_OOPS(K_SYSCALL_DRIVER_HWSPINLOCK(dev, get_max_id)); return z_impl_hwspinlock_get_max_id(dev); } diff --git a/drivers/i2c/CMakeLists.txt b/drivers/i2c/CMakeLists.txt index 20ea5c0cb1e..f7f363ed8d4 100644 --- a/drivers/i2c/CMakeLists.txt +++ b/drivers/i2c/CMakeLists.txt @@ -54,6 +54,7 @@ zephyr_library_sources_ifdef(CONFIG_I2C_XILINX_AXI i2c_xilinx_axi.c) zephyr_library_sources_ifdef(CONFIG_I2C_MCHP_MSS i2c_mchp_mss.c) zephyr_library_sources_ifdef(CONFIG_I2C_SEDI i2c_sedi.c) zephyr_library_sources_ifdef(CONFIG_I2C_AMBIQ i2c_ambiq.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_I2C_SWITCH gpio_i2c_switch.c) zephyr_library_sources_ifdef(CONFIG_I2C_STM32_V1 i2c_ll_stm32_v1.c diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 655d7f6e0bc..233879167c6 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -15,7 +15,6 @@ if I2C config I2C_SHELL bool "I2C Shell" - default y depends on SHELL help Enable I2C Shell. @@ -30,11 +29,26 @@ config I2C_STATS Enable I2C Stats. config I2C_DUMP_MESSAGES - bool "Log all I2C transactions" + bool "Log I2C transactions" depends on LOG + depends on I2C_LOG_LEVEL_DBG help Dump every I2C transaction to the system log as debug level log messages. +config I2C_DUMP_MESSAGES_ALLOWLIST + bool "Use allowlist for logging of I2C transactions" + depends on I2C_DUMP_MESSAGES + depends on DT_HAS_ZEPHYR_I2C_DUMP_ALLOWLIST_ENABLED + help + Use allowlist to specify which devices transactions should be logged. + The allowlist is defined in the devicetree using the compatible string of + "zephyr,i2c-dump-allowlist" and phandles to the devices that need to be traced. + Example of devicetree node: + i2c-dump-allowlist { + compatible = "zephyr,i2c-dump-allowlist"; + devices = < &display0 >, < &sensor3 >; + }; + config I2C_CALLBACK bool "I2C asynchronous callback API" help @@ -180,4 +194,11 @@ config I2C_RV32M1_LPI2C help Enable the RV32M1 LPI2C driver. +config GPIO_I2C_SWITCH + bool "GPIO controlled I2C bus switch" + default y + depends on DT_HAS_GPIO_I2C_SWITCH_ENABLED + help + Enable GPIO controlled I2C bus switch driver. + endif # I2C diff --git a/drivers/i2c/Kconfig.dw b/drivers/i2c/Kconfig.dw index b6350b269f4..c84215f4571 100644 --- a/drivers/i2c/Kconfig.dw +++ b/drivers/i2c/Kconfig.dw @@ -12,3 +12,12 @@ config I2C_DW_CLOCK_SPEED int "Set the clock speed for I2C" depends on I2C_DW default 32 + +config I2C_DW_LPSS_DMA + bool "Use I2C integrated DMA for asynchronous transfer" + select DMA + select DMA_INTEL_LPSS + help + This option enables I2C DMA feature to be used for asynchrounous + data transfers. All Tx operaton are done using dma channel 0 and + all Rx operations are done using dma channel 1. diff --git a/drivers/i2c/Kconfig.nrfx b/drivers/i2c/Kconfig.nrfx index 1be1ba5aa1a..78967177a3a 100644 --- a/drivers/i2c/Kconfig.nrfx +++ b/drivers/i2c/Kconfig.nrfx @@ -8,6 +8,7 @@ menuconfig I2C_NRFX default y depends on SOC_FAMILY_NRF depends on MULTITHREADING + select PINCTRL help Enable support for nrfx TWI drivers for nRF MCU series. @@ -26,6 +27,19 @@ config I2C_NRFX_TWIM select NRFX_TWIM1 if HAS_HW_NRF_TWIM1 select NRFX_TWIM2 if HAS_HW_NRF_TWIM2 select NRFX_TWIM3 if HAS_HW_NRF_TWIM3 + select NRFX_TWIM20 if HAS_HW_NRF_TWIM20 + select NRFX_TWIM21 if HAS_HW_NRF_TWIM21 + select NRFX_TWIM22 if HAS_HW_NRF_TWIM22 + select NRFX_TWIM30 if HAS_HW_NRF_TWIM30 + select NRFX_TWIM120 if HAS_HW_NRF_TWIM120 + select NRFX_TWIM130 if HAS_HW_NRF_TWIM130 + select NRFX_TWIM131 if HAS_HW_NRF_TWIM131 + select NRFX_TWIM132 if HAS_HW_NRF_TWIM132 + select NRFX_TWIM133 if HAS_HW_NRF_TWIM133 + select NRFX_TWIM134 if HAS_HW_NRF_TWIM134 + select NRFX_TWIM135 if HAS_HW_NRF_TWIM135 + select NRFX_TWIM136 if HAS_HW_NRF_TWIM136 + select NRFX_TWIM137 if HAS_HW_NRF_TWIM137 config I2C_NRFX_TRANSFER_TIMEOUT int "Transfer timeout [ms]" diff --git a/drivers/i2c/Kconfig.sc18im704 b/drivers/i2c/Kconfig.sc18im704 index 15cdbd43d4d..f38c0e67d23 100644 --- a/drivers/i2c/Kconfig.sc18im704 +++ b/drivers/i2c/Kconfig.sc18im704 @@ -5,6 +5,7 @@ config I2C_SC18IM704 bool "NXP SC18IM704 I2C controller driver" default y depends on DT_HAS_NXP_SC18IM704_I2C_ENABLED + select UART_USE_RUNTIME_CONFIGURE help Enables NXP SC18IM704 I2C controller driver diff --git a/drivers/i2c/gpio_i2c_switch.c b/drivers/i2c/gpio_i2c_switch.c new file mode 100644 index 00000000000..07183d82e62 --- /dev/null +++ b/drivers/i2c/gpio_i2c_switch.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2023 Ayush Singh + * Copyright (c) 2021 Jason Kridner, BeagleBoard.org Foundation + * Copyright (c) 2020 Innoseis BV + * + * Based on i2c_tca9656a.c + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT gpio_i2c_switch + +#define GPIO_I2C_TOGGLE_DELAY_US 1 +#define GPIO_I2C_LOCK_TIMEOUT_US (GPIO_I2C_TOGGLE_DELAY_US * 2 + 100) + +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(gpio_i2c_switch, CONFIG_I2C_LOG_LEVEL); + +struct gpio_i2c_switch_config { + const struct device *bus; + const struct gpio_dt_spec gpio; +}; + +struct gpio_i2c_switch_data { + struct k_mutex lock; +}; + +static int gpio_i2c_switch_configure(const struct device *dev, uint32_t dev_config) +{ + const struct gpio_i2c_switch_config *config = dev->config; + + return i2c_configure(config->bus, dev_config); +} + +static int gpio_i2c_switch_transfer(const struct device *dev, struct i2c_msg *msgs, + uint8_t num_msgs, uint16_t addr) +{ + int res; + struct gpio_i2c_switch_data *data = dev->data; + const struct gpio_i2c_switch_config *config = dev->config; + + res = k_mutex_lock(&data->lock, K_USEC(GPIO_I2C_LOCK_TIMEOUT_US)); + if (res != 0) { + return res; + } + + /* enable switch */ + gpio_pin_set_dt(&config->gpio, 1); + k_busy_wait(GPIO_I2C_TOGGLE_DELAY_US); + + res = i2c_transfer(config->bus, msgs, num_msgs, addr); + + /* disable switch */ + gpio_pin_set_dt(&config->gpio, 0); + k_busy_wait(GPIO_I2C_TOGGLE_DELAY_US); + k_mutex_unlock(&data->lock); + + return res; +} + +const struct i2c_driver_api gpio_i2c_switch_api_funcs = { + .configure = gpio_i2c_switch_configure, + .transfer = gpio_i2c_switch_transfer, +}; + +static int gpio_i2c_switch_init(const struct device *dev) +{ + const struct gpio_i2c_switch_config *config = dev->config; + struct gpio_i2c_switch_data *data = dev->data; + + k_mutex_init(&data->lock); + + return gpio_pin_configure_dt(&config->gpio, GPIO_OUTPUT_INACTIVE); +} + +#define DEFINE_GPIO_I2C_SWITCH(inst) \ + \ + static struct gpio_i2c_switch_data gpio_i2c_switch_dev_data_##inst; \ + \ + static const struct gpio_i2c_switch_config gpio_i2c_switch_dev_cfg_##inst = { \ + .bus = DEVICE_DT_GET(DT_PHANDLE(DT_DRV_INST(inst), controller)), \ + .gpio = GPIO_DT_SPEC_GET(DT_DRV_INST(inst), gpios), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, gpio_i2c_switch_init, device_pm_control_nop, \ + &gpio_i2c_switch_dev_data_##inst, &gpio_i2c_switch_dev_cfg_##inst, \ + POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, &gpio_i2c_switch_api_funcs); + +DT_INST_FOREACH_STATUS_OKAY(DEFINE_GPIO_I2C_SWITCH) diff --git a/drivers/i2c/i2c_common.c b/drivers/i2c/i2c_common.c index aaae974add8..93986d6f58d 100644 --- a/drivers/i2c/i2c_common.c +++ b/drivers/i2c/i2c_common.c @@ -25,25 +25,53 @@ void z_i2c_transfer_signal_cb(const struct device *dev, } #endif -void i2c_dump_msgs_rw(const char *name, const struct i2c_msg *msgs, - uint8_t num_msgs, uint16_t addr, bool dump_read) +#ifdef CONFIG_I2C_DUMP_MESSAGES_ALLOWLIST +#define DEF_BUS_WITH_ADDR(node, prop, idx) I2C_DT_SPEC_GET(DT_PHANDLE_BY_IDX(node, prop, idx)), +#define DEF_ALLOWLIST_DEV(node) DT_FOREACH_PROP_ELEM(node, devices, DEF_BUS_WITH_ADDR) + +struct i2c_dt_spec messages_allowlist[] = { + DT_FOREACH_STATUS_OKAY(zephyr_i2c_dump_allowlist, DEF_ALLOWLIST_DEV)}; + +#undef DEF_ALLOWLIST_DEV +#undef DEF_BUS_WITH_ADDR +#endif + +void i2c_dump_msgs_rw(const struct device *dev, const struct i2c_msg *msgs, uint8_t num_msgs, + uint16_t addr, bool dump_read) { - LOG_DBG("I2C msg: %s, addr=%x", name, addr); +#ifdef CONFIG_I2C_DUMP_MESSAGES_ALLOWLIST + bool found_dev = 0; + + for (int a = 0; a < ARRAY_SIZE(messages_allowlist); a++) { + struct i2c_dt_spec *allowed = &messages_allowlist[a]; + + if (dev != allowed->bus || addr != allowed->addr) { + continue; + } else { + found_dev = 1; + break; + } + } + + if (!found_dev) { + return; + } +#endif + + LOG_DBG("I2C msg: %s, addr=%x", dev->name, addr); for (unsigned int i = 0; i < num_msgs; i++) { const struct i2c_msg *msg = &msgs[i]; const bool is_read = msg->flags & I2C_MSG_READ; const bool dump_data = dump_read || !is_read; if (msg->len == 1 && dump_data) { - LOG_DBG(" %c %s%s len=01: %02x", is_read ? 'R' : 'W', - msg->flags & I2C_MSG_RESTART ? "Sr " : "", - msg->flags & I2C_MSG_STOP ? "P" : "", - msg->buf[0]); + LOG_DBG(" %c %2s %1s len=01: %02x", is_read ? 'R' : 'W', + msg->flags & I2C_MSG_RESTART ? "Sr" : "", + msg->flags & I2C_MSG_STOP ? "P" : "", msg->buf[0]); } else { - LOG_DBG(" %c %s%s len=%02x: ", is_read ? 'R' : 'W', - msg->flags & I2C_MSG_RESTART ? "Sr " : "", - msg->flags & I2C_MSG_STOP ? "P" : "", - msg->len); + LOG_DBG(" %c %2s %1s len=%02x: ", is_read ? 'R' : 'W', + msg->flags & I2C_MSG_RESTART ? "Sr" : "", + msg->flags & I2C_MSG_STOP ? "P" : "", msg->len); if (dump_data) { LOG_HEXDUMP_DBG(msg->buf, msg->len, "contents:"); } diff --git a/drivers/i2c/i2c_dw.c b/drivers/i2c/i2c_dw.c index 74cf471783b..ca4485606b7 100644 --- a/drivers/i2c/i2c_dw.c +++ b/drivers/i2c/i2c_dw.c @@ -21,12 +21,20 @@ #if defined(CONFIG_PINCTRL) #include #endif +#if defined(CONFIG_RESET) +#include +#endif #include #include #include +#if defined(CONFIG_I2C_DW_LPSS_DMA) +#include +#include +#endif + #ifdef CONFIG_IOAPIC #include #endif @@ -45,6 +53,147 @@ static inline uint32_t get_regs(const struct device *dev) return (uint32_t)DEVICE_MMIO_GET(dev); } +#ifdef CONFIG_I2C_DW_LPSS_DMA +void i2c_dw_enable_idma(const struct device *dev, bool enable) +{ + uint32_t reg; + uint32_t reg_base = get_regs(dev); + + if (enable) { + write_dma_cr(DW_IC_DMA_ENABLE, reg_base); + reg = sys_read32(reg_base + DW_IC_REG_DMA_CR); + } else { + reg = read_dma_cr(reg_base); + reg &= ~DW_IC_DMA_ENABLE; + write_dma_cr(reg, reg_base); + reg = sys_read32(reg_base + DW_IC_REG_DMA_CR); + } +} + +void cb_i2c_idma_transfer(const struct device *dma, void *user_data, + uint32_t channel, int status) +{ + const struct device *dev = (const struct device *)user_data; + struct i2c_dw_dev_config *const dw = dev->data; + + dma_stop(dw->dma_dev, channel); + i2c_dw_enable_idma(dev, false); + + if (status) { + dw->xfr_status = true; + } else { + dw->xfr_status = false; + } +} + +void i2c_dw_set_fifo_th(const struct device *dev, uint8_t fifo_depth) +{ + uint32_t reg_base = get_regs(dev); + + write_tdlr(fifo_depth, reg_base); + write_rdlr(fifo_depth - 1, reg_base); +} + +inline void *i2c_dw_dr_phy_addr(const struct device *dev) +{ + struct i2c_dw_dev_config *const dw = dev->data; + + return (void *) (dw->phy_addr + DW_IC_REG_DATA_CMD); +} + +int32_t i2c_dw_idma_rx_transfer(const struct device *dev) +{ + struct i2c_dw_dev_config *const dw = dev->data; + + struct dma_config dma_cfg = { 0 }; + struct dma_block_config dma_block_cfg = { 0 }; + + if (!device_is_ready(dw->dma_dev)) { + LOG_DBG("DMA device is not ready"); + return -ENODEV; + } + + dma_cfg.dma_slot = 1U; + dma_cfg.channel_direction = PERIPHERAL_TO_MEMORY; + dma_cfg.source_data_size = 1U; + dma_cfg.dest_data_size = 1U; + dma_cfg.source_burst_length = 1U; + dma_cfg.dest_burst_length = 1U; + dma_cfg.dma_callback = cb_i2c_idma_transfer; + dma_cfg.user_data = (void *)dev; + dma_cfg.complete_callback_en = 0U; + dma_cfg.error_callback_en = 1U; + dma_cfg.block_count = 1U; + dma_cfg.head_block = &dma_block_cfg; + + dma_block_cfg.block_size = dw->xfr_len; + dma_block_cfg.dest_address = (uint64_t)&dw->xfr_buf[0]; + dma_block_cfg.source_address = (uint64_t)i2c_dw_dr_phy_addr(dev); + dw->xfr_status = false; + + if (dma_config(dw->dma_dev, DMA_INTEL_LPSS_RX_CHAN, &dma_cfg)) { + LOG_DBG("Error transfer"); + return -EIO; + } + + if (dma_start(dw->dma_dev, DMA_INTEL_LPSS_RX_CHAN)) { + LOG_DBG("Error transfer"); + return -EIO; + } + + i2c_dw_enable_idma(dev, true); + i2c_dw_set_fifo_th(dev, 1); + + return 0; +} + +int32_t i2c_dw_idma_tx_transfer(const struct device *dev, + uint64_t data) +{ + struct i2c_dw_dev_config *const dw = dev->data; + + struct dma_config dma_cfg = { 0 }; + struct dma_block_config dma_block_cfg = { 0 }; + + if (!device_is_ready(dw->dma_dev)) { + LOG_DBG("DMA device is not ready"); + return -ENODEV; + } + + dma_cfg.dma_slot = 0U; + dma_cfg.channel_direction = MEMORY_TO_PERIPHERAL; + dma_cfg.source_data_size = 1U; + dma_cfg.dest_data_size = 1U; + dma_cfg.source_burst_length = 1U; + dma_cfg.dest_burst_length = 1U; + dma_cfg.dma_callback = cb_i2c_idma_transfer; + dma_cfg.user_data = (void *)dev; + dma_cfg.complete_callback_en = 0U; + dma_cfg.error_callback_en = 1U; + dma_cfg.block_count = 1U; + dma_cfg.head_block = &dma_block_cfg; + + dma_block_cfg.block_size = 1; + dma_block_cfg.source_address = (uint64_t)&data; + dma_block_cfg.dest_address = (uint64_t)i2c_dw_dr_phy_addr(dev); + dw->xfr_status = false; + + if (dma_config(dw->dma_dev, DMA_INTEL_LPSS_TX_CHAN, &dma_cfg)) { + LOG_DBG("Error transfer"); + return -EIO; + } + + if (dma_start(dw->dma_dev, DMA_INTEL_LPSS_TX_CHAN)) { + LOG_DBG("Error trnasfer"); + return -EIO; + } + i2c_dw_enable_idma(dev, true); + i2c_dw_set_fifo_th(dev, 1); + + return 0; +} +#endif + static inline void i2c_dw_data_ask(const struct device *dev) { struct i2c_dw_dev_config * const dw = dev->data; @@ -116,6 +265,13 @@ static void i2c_dw_data_read(const struct device *dev) struct i2c_dw_dev_config * const dw = dev->data; uint32_t reg_base = get_regs(dev); +#ifdef CONFIG_I2C_DW_LPSS_DMA + if (test_bit_status_rfne(reg_base) && (dw->xfr_len > 0)) { + i2c_dw_idma_rx_transfer(dev); + dw->xfr_len = 0; + dw->rx_pending = 0; + } +#else while (test_bit_status_rfne(reg_base) && (dw->xfr_len > 0)) { dw->xfr_buf[0] = (uint8_t)read_cmd_data(reg_base); @@ -127,7 +283,7 @@ static void i2c_dw_data_read(const struct device *dev) break; } } - +#endif /* Nothing to receive anymore */ if (dw->xfr_len == 0U) { dw->state &= ~I2C_DW_CMD_RECV; @@ -166,8 +322,11 @@ static int i2c_dw_data_send(const struct device *dev) data |= IC_DATA_CMD_STOP; } +#ifdef CONFIG_I2C_DW_LPSS_DMA + i2c_dw_idma_tx_transfer(dev, data); +#else write_cmd_data(data, reg_base); - +#endif dw->xfr_len--; dw->xfr_buf++; @@ -227,6 +386,16 @@ static void i2c_dw_isr(const struct device *port) /* Check if we are configured as a master device */ if (test_bit_con_master_mode(reg_base)) { +#ifdef CONFIG_I2C_DW_LPSS_DMA + uint32_t stat = sys_read32(reg_base + IDMA_REG_INTR_STS); + + if (stat & IDMA_TX_RX_CHAN_MASK) { + /* Handle the DMA interrupt */ + dma_intel_lpss_isr(dw->dma_dev); + + } +#endif + /* Bail early if there is any error. */ if ((DW_INTR_STAT_TX_ABRT | DW_INTR_STAT_TX_OVER | DW_INTR_STAT_RX_OVER | DW_INTR_STAT_RX_UNDER) & @@ -847,6 +1016,15 @@ static int i2c_dw_initialize(const struct device *dev) union ic_con_register ic_con; int ret = 0; +#if defined(CONFIG_RESET) + if (rom->reset.dev) { + ret = reset_line_toggle_dt(&rom->reset); + if (ret) { + return ret; + } + } +#endif + #if defined(CONFIG_PINCTRL) ret = pinctrl_apply_state(rom->pcfg, PINCTRL_STATE_DEFAULT); if (ret) { @@ -867,6 +1045,26 @@ static int i2c_dw_initialize(const struct device *dev) device_map(DEVICE_MMIO_RAM_PTR(dev), mbar.phys_addr, mbar.size, K_MEM_CACHE_NONE); + + pcie_set_cmd(rom->pcie->bdf, PCIE_CONF_CMDSTAT_MASTER, true); + +#ifdef CONFIG_I2C_DW_LPSS_DMA + size_t nhdls = 0; + const device_handle_t *hdls; + + hdls = device_supported_handles_get(dev, &nhdls); + dw->dma_dev = device_from_handle(*hdls); + + /* Assign physical & virtual address to dma instance */ + dw->phy_addr = mbar.phys_addr; + dw->base_addr = (uint32_t)(DEVICE_MMIO_GET(dev) + DMA_INTEL_LPSS_OFFSET); + sys_write32((uint32_t)dw->phy_addr, + DEVICE_MMIO_GET(dev) + DMA_INTEL_LPSS_REMAP_LOW); + sys_write32((uint32_t)(dw->phy_addr >> DMA_INTEL_LPSS_ADDR_RIGHT_SHIFT), + DEVICE_MMIO_GET(dev) + DMA_INTEL_LPSS_REMAP_HI); + LOG_DBG("i2c instance physical addr: [0x%lx], virtual addr: [0x%lx]", + dw->phy_addr, dw->base_addr); +#endif } else #endif { @@ -877,6 +1075,7 @@ static int i2c_dw_initialize(const struct device *dev) k_mutex_init(&dw->bus_mutex); uint32_t reg_base = get_regs(dev); + clear_bit_enable_en(reg_base); /* verify that we have a valid DesignWare register first */ @@ -922,6 +1121,14 @@ static int i2c_dw_initialize(const struct device *dev) #define PINCTRL_DW_CONFIG(n) #endif +#if defined(CONFIG_RESET) +#define RESET_DW_CONFIG(n) \ + IF_ENABLED(DT_INST_NODE_HAS_PROP(0, resets), \ + (.reset = RESET_DT_SPEC_INST_GET(n),)) +#else +#define RESET_DW_CONFIG(n) +#endif + #define I2C_DW_INIT_PCIE0(n) #define I2C_DW_INIT_PCIE1(n) DEVICE_PCIE_INST_INIT(n, pcie), #define I2C_DW_INIT_PCIE(n) \ @@ -985,6 +1192,7 @@ static int i2c_dw_initialize(const struct device *dev) I2C_CONFIG_REG_INIT(n) \ .config_func = i2c_config_##n, \ .bitrate = DT_INST_PROP(n, clock_frequency), \ + RESET_DW_CONFIG(n) \ PINCTRL_DW_CONFIG(n) \ I2C_DW_INIT_PCIE(n) \ }; \ diff --git a/drivers/i2c/i2c_dw.h b/drivers/i2c/i2c_dw.h index c9f7381eb89..34427504708 100644 --- a/drivers/i2c/i2c_dw.h +++ b/drivers/i2c/i2c_dw.h @@ -18,6 +18,10 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_PCIE), "DW I2C in DT needs CONFIG_PCIE"); #include #endif +#if defined(CONFIG_RESET) +#include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -93,6 +97,9 @@ struct i2c_dw_rom_config { #if defined(CONFIG_PINCTRL) const struct pinctrl_dev_config *pcfg; #endif +#if defined(CONFIG_RESET) + const struct reset_dt_spec reset; +#endif #if DT_ANY_INST_ON_BUS_STATUS_OKAY(pcie) struct pcie_dev *pcie; @@ -116,6 +123,13 @@ struct i2c_dw_dev_config { uint8_t request_bytes; uint8_t xfr_flags; bool support_hs_mode; +#ifdef CONFIG_I2C_DW_LPSS_DMA + const struct device *dma_dev; + uintptr_t phy_addr; + uintptr_t base_addr; + /* For dma transfer */ + bool xfr_status; +#endif struct i2c_target_config *slave_cfg; }; diff --git a/drivers/i2c/i2c_dw_registers.h b/drivers/i2c/i2c_dw_registers.h index be76cbdaad9..6b2a11dffa4 100644 --- a/drivers/i2c/i2c_dw_registers.h +++ b/drivers/i2c/i2c_dw_registers.h @@ -144,14 +144,25 @@ union ic_comp_param_1_register { #define DW_IC_REG_STATUS (0x70) #define DW_IC_REG_TXFLR (0x74) #define DW_IC_REG_RXFLR (0x78) +#define DW_IC_REG_DMA_CR (0x88) +#define DW_IC_REG_TDLR (0x8C) +#define DW_IC_REG_RDLR (0x90) #define DW_IC_REG_FS_SPKLEN (0xA0) #define DW_IC_REG_HS_SPKLEN (0xA4) #define DW_IC_REG_COMP_PARAM_1 (0xF4) #define DW_IC_REG_COMP_TYPE (0xFC) +#define IDMA_REG_INTR_STS 0xAE8 +#define IDMA_TX_RX_CHAN_MASK 0x3 + /* CON Bit */ #define DW_IC_CON_MASTER_MODE_BIT (0) +/* DMA control bits */ +#define DW_IC_DMA_RX_ENABLE BIT(0) +#define DW_IC_DMA_TX_ENABLE BIT(1) +#define DW_IC_DMA_ENABLE (BIT(0) | BIT(1)) + DEFINE_TEST_BIT_OP(con_master_mode, DW_IC_REG_CON, DW_IC_CON_MASTER_MODE_BIT) DEFINE_MM_REG_WRITE(con, DW_IC_REG_CON, 32) DEFINE_MM_REG_READ(con, DW_IC_REG_CON, 32) @@ -209,6 +220,14 @@ DEFINE_TEST_BIT_OP(status_rfne, DW_IC_REG_STATUS, DW_IC_STATUS_RFNE_BIT) DEFINE_MM_REG_READ(txflr, DW_IC_REG_TXFLR, 32) DEFINE_MM_REG_READ(rxflr, DW_IC_REG_RXFLR, 32) +DEFINE_MM_REG_READ(dma_cr, DW_IC_REG_DMA_CR, 32) +DEFINE_MM_REG_WRITE(dma_cr, DW_IC_REG_DMA_CR, 32) + +DEFINE_MM_REG_READ(tdlr, DW_IC_REG_TDLR, 32) +DEFINE_MM_REG_WRITE(tdlr, DW_IC_REG_TDLR, 32) +DEFINE_MM_REG_READ(rdlr, DW_IC_REG_RDLR, 32) +DEFINE_MM_REG_WRITE(rdlr, DW_IC_REG_RDLR, 32) + DEFINE_MM_REG_READ(fs_spklen, DW_IC_REG_FS_SPKLEN, 32) DEFINE_MM_REG_READ(hs_spklen, DW_IC_REG_HS_SPKLEN, 32) diff --git a/drivers/i2c/i2c_esp32.c b/drivers/i2c/i2c_esp32.c index 18a38b02a28..60af4648949 100644 --- a/drivers/i2c/i2c_esp32.c +++ b/drivers/i2c/i2c_esp32.c @@ -560,12 +560,20 @@ static int IRAM_ATTR i2c_esp32_transfer(const struct device *dev, struct i2c_msg { struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; struct i2c_msg *current, *next; + uint32_t timeout = I2C_TRANSFER_TIMEOUT_MSEC * USEC_PER_MSEC; int ret = 0; if (!num_msgs) { return 0; } + while (i2c_hal_is_bus_busy(&data->hal)) { + k_busy_wait(1); + if (timeout-- == 0) { + return -EBUSY; + } + } + /* Check for validity of all messages before transfer */ current = msgs; diff --git a/drivers/i2c/i2c_gecko.c b/drivers/i2c/i2c_gecko.c index edeef470434..0c537add17a 100644 --- a/drivers/i2c/i2c_gecko.c +++ b/drivers/i2c/i2c_gecko.c @@ -45,7 +45,6 @@ struct i2c_gecko_data { uint32_t dev_config; #if defined(CONFIG_I2C_TARGET) struct i2c_target_config *target_cfg; - volatile bool target_read; #endif }; @@ -81,9 +80,6 @@ static int i2c_gecko_configure(const struct device *dev, uint32_t dev_config_raw struct i2c_gecko_data *data = dev->data; I2C_Init_TypeDef i2cInit = I2C_INIT_DEFAULT; uint32_t baudrate; -#if defined(CONFIG_I2C_TARGET) - const struct i2c_gecko_config *config = dev->config; -#endif if (!(I2C_MODE_CONTROLLER & dev_config_raw)) { return -EINVAL; @@ -108,7 +104,6 @@ static int i2c_gecko_configure(const struct device *dev, uint32_t dev_config_raw #if defined(CONFIG_I2C_TARGET) i2cInit.master = 0; - BUS_RegBitWrite(&(config->base->CTRL), _I2C_CTRL_AUTOACK_SHIFT, 1); #endif I2C_Init(base, &i2cInit); @@ -212,7 +207,8 @@ static int i2c_gecko_target_register(const struct device *dev, struct i2c_target I2C_SlaveAddressMaskSet(config->base, _I2C_SADDRMASK_SADDRMASK_MASK); I2C_IntDisable(config->base, _I2C_IEN_MASK); - I2C_IntEnable(config->base, I2C_IEN_ADDR | I2C_IEN_RXDATAV | I2C_IEN_SSTOP); + I2C_IntEnable(config->base, I2C_IEN_ADDR | I2C_IEN_RXDATAV | I2C_IEN_ACK | I2C_IEN_SSTOP | + I2C_IEN_BUSERR | I2C_IEN_ARBLOST); config->irq_config_func(dev); @@ -242,57 +238,60 @@ static const struct i2c_driver_api i2c_gecko_driver_api = { }; #if defined(CONFIG_I2C_TARGET) -static void i2c_gecko_isr(const struct device *dev) +void i2c_gecko_isr(const struct device *dev) { const struct i2c_gecko_config *config = dev->config; struct i2c_gecko_data *data = dev->data; - uint32_t status; - uint32_t rx_data; - uint8_t tx_byte; - status = config->base->IF; + uint32_t pending; + uint32_t rx_byte; + uint8_t tx_byte; - if (status & I2C_IF_ADDR && status & I2C_IF_RXDATAV) { - /* Address Match */ - rx_data = config->base->RXDATA; - if (rx_data & 0x1) { - data->target_read = true; + pending = config->base->IF; + + /* If some sort of fault, abort transfer. */ + if (pending & (I2C_IF_BUSERR | I2C_IF_ARBLOST)) { + LOG_ERR("I2C Bus Error"); + I2C_IntClear(config->base, I2C_IF_BUSERR); + I2C_IntClear(config->base, I2C_IF_ARBLOST); + } else { + if (pending & I2C_IF_ADDR) { + /* Address Match, indicating that reception is started */ + rx_byte = config->base->RXDATA; + config->base->CMD = I2C_CMD_ACK; + + /* Check if read bit set */ + if (rx_byte & 0x1) { + data->target_cfg->callbacks->read_requested(data->target_cfg, + &tx_byte); + config->base->TXDATA = tx_byte; + } else { + data->target_cfg->callbacks->write_requested(data->target_cfg); + } - data->target_cfg->callbacks->read_requested(data->target_cfg, &tx_byte); - config->base->TXDATA = tx_byte; + I2C_IntClear(config->base, I2C_IF_ADDR | I2C_IF_RXDATAV); + } else if (pending & I2C_IF_RXDATAV) { + rx_byte = config->base->RXDATA; + /* Read new data and write to target address */ + data->target_cfg->callbacks->write_received(data->target_cfg, rx_byte); + config->base->CMD = I2C_CMD_ACK; - I2C_IntEnable(config->base, I2C_IEN_BUSHOLD); - } else { - data->target_read = false; - data->target_cfg->callbacks->write_requested(data->target_cfg); - } - I2C_IntClear(config->base, I2C_IF_ADDR); - I2C_IntClear(config->base, I2C_IF_RXDATAV); - } else if (status & I2C_IF_RXDATAV) { - if (data->target_read == true) { - LOG_ERR("Unexpected Data"); - } else { - rx_data = config->base->RXDATA; - data->target_cfg->callbacks->write_received(data->target_cfg, rx_data); + I2C_IntClear(config->base, I2C_IF_RXDATAV); } - I2C_IntClear(config->base, I2C_IF_RXDATAV); - } else if (data->target_read && status & I2C_IF_BUSHOLD && !(status & I2C_IF_SSTOP)) { - data->target_cfg->callbacks->read_processed(data->target_cfg, &tx_byte); - config->base->TXDATA = tx_byte; - I2C_IntClear(config->base, I2C_IF_BUSHOLD); - } + if (pending & I2C_IF_ACK) { + /* Leader ACK'ed, so requesting more data */ + data->target_cfg->callbacks->read_processed(data->target_cfg, &tx_byte); + config->base->TXDATA = tx_byte; - if (status & I2C_IF_SSTOP) { - if (config->base->STATUS & I2C_STATUS_RXDATAV) { - LOG_ERR("Still valid data"); + I2C_IntClear(config->base, I2C_IF_ACK); } - /* Stop received, reception is ended */ - data->target_cfg->callbacks->stop(data->target_cfg); - I2C_IntClear(config->base, I2C_IF_SSTOP); - I2C_IntClear(config->base, I2C_IF_BUSHOLD); - I2C_IntDisable(config->base, I2C_IEN_BUSHOLD); + if (pending & I2C_IF_SSTOP) { + /* End of transaction */ + data->target_cfg->callbacks->stop(data->target_cfg); + I2C_IntClear(config->base, I2C_IF_SSTOP); + } } } #endif diff --git a/drivers/i2c/i2c_handlers.c b/drivers/i2c/i2c_handlers.c index fca385ee27b..20ec2a6f578 100644 --- a/drivers/i2c/i2c_handlers.c +++ b/drivers/i2c/i2c_handlers.c @@ -6,12 +6,12 @@ #include #include -#include +#include static inline int z_vrfy_i2c_configure(const struct device *dev, uint32_t dev_config) { - Z_OOPS(Z_SYSCALL_DRIVER_I2C(dev, configure)); + K_OOPS(K_SYSCALL_DRIVER_I2C(dev, configure)); return z_impl_i2c_configure((const struct device *)dev, dev_config); } #include @@ -19,8 +19,8 @@ static inline int z_vrfy_i2c_configure(const struct device *dev, static inline int z_vrfy_i2c_get_config(const struct device *dev, uint32_t *dev_config) { - Z_OOPS(Z_SYSCALL_DRIVER_I2C(dev, get_config)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(dev_config, sizeof(uint32_t))); + K_OOPS(K_SYSCALL_DRIVER_I2C(dev, get_config)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(dev_config, sizeof(uint32_t))); return z_impl_i2c_get_config(dev, dev_config); } @@ -41,7 +41,7 @@ static uint32_t copy_msgs_and_transfer(const struct device *dev, * that the target buffer be writable */ for (i = 0U; i < num_msgs; i++) { - Z_OOPS(Z_SYSCALL_MEMORY(copy[i].buf, copy[i].len, + K_OOPS(K_SYSCALL_MEMORY(copy[i].buf, copy[i].len, copy[i].flags & I2C_MSG_READ)); } @@ -52,17 +52,17 @@ static inline int z_vrfy_i2c_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, uint16_t addr) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_I2C)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_I2C)); /* copy_msgs_and_transfer() will allocate a copy on the stack using * VLA, so ensure this won't blow the stack. Most functions defined * in i2c.h use only a handful of messages, so up to 32 messages * should be more than sufficient. */ - Z_OOPS(Z_SYSCALL_VERIFY(num_msgs >= 1 && num_msgs < 32)); + K_OOPS(K_SYSCALL_VERIFY(num_msgs >= 1 && num_msgs < 32)); /* We need to be able to read the overall array of messages */ - Z_OOPS(Z_SYSCALL_MEMORY_ARRAY_READ(msgs, num_msgs, + K_OOPS(K_SYSCALL_MEMORY_ARRAY_READ(msgs, num_msgs, sizeof(struct i2c_msg))); return copy_msgs_and_transfer((const struct device *)dev, @@ -73,21 +73,21 @@ static inline int z_vrfy_i2c_transfer(const struct device *dev, static inline int z_vrfy_i2c_target_driver_register(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_I2C)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_I2C)); return z_impl_i2c_target_driver_register(dev); } #include static inline int z_vrfy_i2c_target_driver_unregister(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_I2C)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_I2C)); return z_impl_i2c_target_driver_unregister(dev); } #include static inline int z_vrfy_i2c_recover_bus(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_I2C)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_I2C)); return z_impl_i2c_recover_bus(dev); } #include diff --git a/drivers/i2c/i2c_ite_enhance.c b/drivers/i2c/i2c_ite_enhance.c index d15b9cb0bf9..1d26ade56c1 100644 --- a/drivers/i2c/i2c_ite_enhance.c +++ b/drivers/i2c/i2c_ite_enhance.c @@ -63,6 +63,7 @@ struct i2c_enhance_config { uint8_t *base; uint8_t i2c_irq_base; uint8_t port; + uint8_t channel_switch_sel; /* SCL GPIO cells */ struct gpio_dt_spec scl_gpios; /* SDA GPIO cells */ @@ -72,6 +73,7 @@ struct i2c_enhance_config { uint8_t prescale_scl_low; uint32_t clock_gate_offset; bool target_enable; + bool target_pio_mode; }; enum i2c_pin_fun { @@ -137,6 +139,7 @@ struct i2c_enhance_data { #ifdef CONFIG_I2C_TARGET struct i2c_target_config *target_cfg; uint32_t buffer_size; + int target_nack; bool target_attached; #endif union { @@ -209,6 +212,7 @@ enum i2c_reset_cause { I2C_RC_TIMEOUT, }; +#ifdef CONFIG_I2C_TARGET enum enhanced_i2c_target_status { /* Time out error */ E_TARGET_TMOE = 0x08, @@ -217,6 +221,7 @@ enum enhanced_i2c_target_status { /* Time out or lost arbitration */ E_TARGET_ANY_ERROR = (E_TARGET_TMOE | E_TARGET_ARB), }; +#endif static int i2c_parsing_return_value(const struct device *dev) { @@ -381,6 +386,8 @@ static int enhanced_i2c_error(const struct device *dev) } else if ((i2c_str & E_HOSTA_BDS_AND_ACK) == E_HOSTA_BDS) { if (IT8XXX2_I2C_CTR(base) & E_ACK) { data->err = E_HOSTA_ACK; + /* STOP */ + IT8XXX2_I2C_CTR(base) = E_FINISH; } } @@ -729,9 +736,11 @@ static int enhanced_i2c_cq_isr(const struct device *dev) uint8_t msgs_idx = data->num_msgs - 1; /* Get data if this is a read transaction. */ - for (int i = 0; i < data->cq_msgs[msgs_idx].len; i++) { - data->cq_msgs[msgs_idx].buf[i] = - host_buffer->i2c_cq_mode_rx_dlm[i]; + if (data->cq_msgs[msgs_idx].flags & I2C_MSG_READ) { + for (int i = 0; i < data->cq_msgs[msgs_idx].len; i++) { + data->cq_msgs[msgs_idx].buf[i] = + host_buffer->i2c_cq_mode_rx_dlm[i]; + } } } else { /* Device 1 error have occurred. eg. nack, timeout... */ @@ -955,10 +964,104 @@ static int i2c_enhance_transfer(const struct device *dev, } #ifdef CONFIG_I2C_TARGET -static void target_i2c_isr(const struct device *dev) +static void target_i2c_isr_dma(const struct device *dev, + uint8_t interrupt_status) { struct i2c_enhance_data *data = dev->data; + const struct i2c_enhance_config *config = dev->config; + const struct i2c_target_callbacks *target_cb = data->target_cfg->callbacks; struct i2c_target_dma_buffer *target_buffer = &data->target_buffer; + uint8_t *base = config->base; + + /* Byte counter enable */ + if (interrupt_status & IT8XXX2_I2C_IDW_CLR) { + IT8XXX2_I2C_BYTE_CNT_L(base) |= + (IT8XXX2_I2C_DMA_ADDR_RELOAD | + IT8XXX2_I2C_BYTE_CNT_ENABLE); + } + /* The number of received data exceeds the byte counter setting */ + if (interrupt_status & IT8XXX2_I2C_CNT_HOLD) { + LOG_ERR("The excess data written starts " + "from the memory address:%p", + target_buffer->in_buffer + + CONFIG_I2C_TARGET_IT8XXX2_MAX_BUF_SIZE); + } + /* Controller to write data */ + if (interrupt_status & IT8XXX2_I2C_SLVDATAFLG) { + /* Number of receive data in target mode */ + data->buffer_size = + ((IT8XXX2_I2C_SLV_NUM_H(base) << 8) | + IT8XXX2_I2C_SLV_NUM_L(base)) + 1; + + /* Write data done callback function */ + target_cb->buf_write_received(data->target_cfg, + target_buffer->in_buffer, data->buffer_size); + } + /* Controller to read data */ + if (interrupt_status & IT8XXX2_I2C_IDR_CLR) { + uint32_t len; + uint8_t *rdata = NULL; + + /* Clear byte counter setting */ + IT8XXX2_I2C_BYTE_CNT_L(base) &= + ~(IT8XXX2_I2C_DMA_ADDR_RELOAD | + IT8XXX2_I2C_BYTE_CNT_ENABLE); + /* Read data callback function */ + target_cb->buf_read_requested(data->target_cfg, + &rdata, &len); + + if (len > CONFIG_I2C_TARGET_IT8XXX2_MAX_BUF_SIZE) { + LOG_ERR("The bufffer size exceeds " + "I2C_TARGET_IT8XXX2_MAX_BUF_SIZE: len=%d", + len); + } else { + memcpy(target_buffer->out_buffer, rdata, len); + } + } +} + +static int target_i2c_isr_pio(const struct device *dev, + uint8_t interrupt_status, + uint8_t target_status) +{ + struct i2c_enhance_data *data = dev->data; + const struct i2c_enhance_config *config = dev->config; + const struct i2c_target_callbacks *target_cb = data->target_cfg->callbacks; + int ret = 0; + uint8_t *base = config->base; + uint8_t val; + + /* Target ID write flag */ + if (interrupt_status & IT8XXX2_I2C_IDW_CLR) { + ret = target_cb->write_requested(data->target_cfg); + } + /* Target ID read flag */ + else if (interrupt_status & IT8XXX2_I2C_IDR_CLR) { + if (!target_cb->read_requested(data->target_cfg, &val)) { + IT8XXX2_I2C_DTR(base) = val; + } + } + /* Byte transfer done */ + else if (target_status & IT8XXX2_I2C_BYTE_DONE) { + /* Read of write */ + if (target_status & IT8XXX2_I2C_RW) { + /* Host receiving, target transmitting */ + if (!target_cb->read_processed(data->target_cfg, &val)) { + IT8XXX2_I2C_DTR(base) = val; + } + } else { + /* Host transmitting, target receiving */ + val = IT8XXX2_I2C_DRR(base); + ret = target_cb->write_received(data->target_cfg, val); + } + } + + return ret; +} + +static void target_i2c_isr(const struct device *dev) +{ + struct i2c_enhance_data *data = dev->data; const struct i2c_enhance_config *config = dev->config; const struct i2c_target_callbacks *target_cb = data->target_cfg->callbacks; uint8_t *base = config->base; @@ -966,69 +1069,41 @@ static void target_i2c_isr(const struct device *dev) /* Any error */ if (target_status & E_TARGET_ANY_ERROR) { - /* Hardware reset */ - IT8XXX2_I2C_CTR(base) |= IT8XXX2_I2C_HALT; + goto end; + } + /* Interrupt pending */ - } else if (target_status & IT8XXX2_I2C_INT_PEND) { + if (target_status & IT8XXX2_I2C_INT_PEND) { uint8_t interrupt_status = IT8XXX2_I2C_IRQ_ST(base); - /* Byte counter enable */ - if (interrupt_status & IT8XXX2_I2C_IDW_CLR) { - IT8XXX2_I2C_BYTE_CNT_L(base) |= - (IT8XXX2_I2C_DMA_ADDR_RELOAD | - IT8XXX2_I2C_BYTE_CNT_ENABLE); - } - /* The number of received data exceeds the byte counter setting */ - if (interrupt_status & IT8XXX2_I2C_CNT_HOLD) { - LOG_ERR("The excess data written starts " - "from the memory address:%p", - target_buffer->in_buffer + - CONFIG_I2C_TARGET_IT8XXX2_MAX_BUF_SIZE); - } - /* Controller to write data */ - if (interrupt_status & IT8XXX2_I2C_SLVDATAFLG) { - /* Number of receive data in target mode */ - data->buffer_size = - ((IT8XXX2_I2C_SLV_NUM_H(base) << 8) | - IT8XXX2_I2C_SLV_NUM_L(base)) + 1; - - /* Write data done callback function */ - target_cb->buf_write_received(data->target_cfg, - target_buffer->in_buffer, data->buffer_size); - } - /* Controller to read data */ - if (interrupt_status & IT8XXX2_I2C_IDR_CLR) { - uint32_t len; - uint8_t *rdata = NULL; - - /* Clear byte counter setting */ - IT8XXX2_I2C_BYTE_CNT_L(base) &= - ~(IT8XXX2_I2C_DMA_ADDR_RELOAD | - IT8XXX2_I2C_BYTE_CNT_ENABLE); - /* Read data callback function */ - target_cb->buf_read_requested(data->target_cfg, - &rdata, &len); - - if (len > CONFIG_I2C_TARGET_IT8XXX2_MAX_BUF_SIZE) { - LOG_ERR("The bufffer size exceeds " - "I2C_TARGET_IT8XXX2_MAX_BUF_SIZE: len=%d", - len); - } else { - memcpy(target_buffer->out_buffer, rdata, len); + /* Determine whether the transaction uses PIO or DMA mode */ + if (config->target_pio_mode) { + if (target_i2c_isr_pio(dev, interrupt_status, target_status) < 0) { + /* NACK */ + IT8XXX2_I2C_CTR(base) &= ~IT8XXX2_I2C_ACK; + IT8XXX2_I2C_CTR(base) |= IT8XXX2_I2C_HALT; + data->target_nack = 1; } + } else { + target_i2c_isr_dma(dev, interrupt_status); } /* Peripheral finish */ if (interrupt_status & IT8XXX2_I2C_P_CLR) { /* Transfer done callback function */ target_cb->stop(data->target_cfg); - /* Hardware reset */ - IT8XXX2_I2C_CTR(base) |= IT8XXX2_I2C_HALT; + + if (data->target_nack) { + /* Set acknowledge */ + IT8XXX2_I2C_CTR(base) |= IT8XXX2_I2C_ACK; + data->target_nack = 0; + } } /* Write clear the peripheral status */ IT8XXX2_I2C_IRQ_ST(base) = interrupt_status; } - /* Write clear the target status */ - IT8XXX2_I2C_STR(base) = target_status; +end: + /* Hardware reset */ + IT8XXX2_I2C_CTR(base) |= IT8XXX2_I2C_HALT; } #endif @@ -1100,6 +1175,27 @@ static int i2c_enhance_init(const struct device *dev) enhanced_i2c_set_cmd_addr_regs(dev); #endif + /* ChannelA-F switch selection of I2C pin */ + if (config->port == SMB_CHANNEL_A) { + IT8XXX2_SMB_SMB01CHS = (IT8XXX2_SMB_SMB01CHS &= ~GENMASK(2, 0)) | + config->channel_switch_sel; + } else if (config->port == SMB_CHANNEL_B) { + IT8XXX2_SMB_SMB01CHS = (config->channel_switch_sel << 4) | + (IT8XXX2_SMB_SMB01CHS &= ~GENMASK(6, 4)); + } else if (config->port == SMB_CHANNEL_C) { + IT8XXX2_SMB_SMB23CHS = (IT8XXX2_SMB_SMB23CHS &= ~GENMASK(2, 0)) | + config->channel_switch_sel; + } else if (config->port == I2C_CHANNEL_D) { + IT8XXX2_SMB_SMB23CHS = (config->channel_switch_sel << 4) | + (IT8XXX2_SMB_SMB23CHS &= ~GENMASK(6, 4)); + } else if (config->port == I2C_CHANNEL_E) { + IT8XXX2_SMB_SMB45CHS = (IT8XXX2_SMB_SMB45CHS &= ~GENMASK(2, 0)) | + config->channel_switch_sel; + } else if (config->port == I2C_CHANNEL_F) { + IT8XXX2_SMB_SMB45CHS = (config->channel_switch_sel << 4) | + (IT8XXX2_SMB_SMB45CHS &= ~GENMASK(6, 4)); + } + /* Set clock frequency for I2C ports */ if (config->bitrate == I2C_BITRATE_STANDARD || config->bitrate == I2C_BITRATE_FAST || @@ -1200,8 +1296,6 @@ static int i2c_enhance_target_register(const struct device *dev, { const struct i2c_enhance_config *config = dev->config; struct i2c_enhance_data *data = dev->data; - struct i2c_target_dma_buffer *target_buffer = &data->target_buffer; - uint32_t in_data_addr, out_data_addr; uint8_t *base = config->base; if (!target_cfg) { @@ -1222,11 +1316,9 @@ static int i2c_enhance_target_register(const struct device *dev, /* Software reset */ IT8XXX2_I2C_DHTR(base) |= IT8XXX2_I2C_SOFT_RST; IT8XXX2_I2C_DHTR(base) &= ~IT8XXX2_I2C_SOFT_RST; - /* - * Set time out register. - * I2C D/E/F clock/data low timeout. - */ - IT8XXX2_I2C_TOR(base) = I2C_CLK_LOW_TIMEOUT; + /* Disable the timeout setting when clock/data are in a low state */ + IT8XXX2_I2C_TO_ARB_ST(base) &= ~(IT8XXX2_I2C_SCL_TIMEOUT_EN | + IT8XXX2_I2C_SDA_TIMEOUT_EN); /* Bit stretching */ IT8XXX2_I2C_TOS(base) |= IT8XXX2_I2C_CLK_STRETCH; /* Peripheral address(8-bit) */ @@ -1237,44 +1329,59 @@ static int i2c_enhance_target_register(const struct device *dev, /* Interrupt status write clear */ IT8XXX2_I2C_IRQ_ST(base) = 0xff; - /* Clear read and write data buffer of DMA */ - memset(target_buffer->in_buffer, 0, CONFIG_I2C_TARGET_IT8XXX2_MAX_BUF_SIZE); - memset(target_buffer->out_buffer, 0, CONFIG_I2C_TARGET_IT8XXX2_MAX_BUF_SIZE); + /* I2C target initial configuration of PIO mode */ + if (config->target_pio_mode) { + /* Block to enter power policy. */ + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); - in_data_addr = (uint32_t)target_buffer->in_buffer & 0xffffff; - out_data_addr = (uint32_t)target_buffer->out_buffer & 0xffffff; - /* - * DMA write target address register - * for high order byte - */ - IT8XXX2_I2C_RAMH2A(base) = in_data_addr >> 16; - IT8XXX2_I2C_RAMHA(base) = in_data_addr >> 8; - IT8XXX2_I2C_RAMLA(base) = in_data_addr; - /* - * DMA read target address register - * for high order byte - */ - IT8XXX2_I2C_CMD_ADDH2(base) = out_data_addr >> 16; - IT8XXX2_I2C_RAMHA2(base) = out_data_addr >> 8; - IT8XXX2_I2C_RAMLA2(base) = out_data_addr; + /* I2C module enable */ + IT8XXX2_I2C_CTR1(base) = IT8XXX2_I2C_MDL_EN; + /* I2C target initial configuration of DMA mode */ + } else { + struct i2c_target_dma_buffer *target_buffer = &data->target_buffer; + uint32_t in_data_addr, out_data_addr; + int buf_size = CONFIG_I2C_TARGET_IT8XXX2_MAX_BUF_SIZE; - /* Byte counter setting */ - /* This register indicates byte count[10:3]. */ - IT8XXX2_I2C_BYTE_CNT_H(base) = CONFIG_I2C_TARGET_IT8XXX2_MAX_BUF_SIZE >> 3; - /* This register indicates byte count[2:0]. */ - IT8XXX2_I2C_BYTE_CNT_L(base) = CONFIG_I2C_TARGET_IT8XXX2_MAX_BUF_SIZE & - GENMASK(2, 0); + /* Clear read and write data buffer of DMA */ + memset(target_buffer->in_buffer, 0, buf_size); + memset(target_buffer->out_buffer, 0, buf_size); - /* - * The EC processor(CPU) cannot be in the k_cpu_idle() and power - * policy during the transactions with the CQ mode(DMA mode). - * Otherwise, the EC processor would be clock gated. - */ - chip_block_idle(); - pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + in_data_addr = (uint32_t)target_buffer->in_buffer & 0xffffff; + out_data_addr = (uint32_t)target_buffer->out_buffer & 0xffffff; + /* + * DMA write target address register + * for high order byte + */ + IT8XXX2_I2C_RAMH2A(base) = in_data_addr >> 16; + IT8XXX2_I2C_RAMHA(base) = in_data_addr >> 8; + IT8XXX2_I2C_RAMLA(base) = in_data_addr; + /* + * DMA read target address register + * for high order byte + */ + IT8XXX2_I2C_CMD_ADDH2(base) = out_data_addr >> 16; + IT8XXX2_I2C_RAMHA2(base) = out_data_addr >> 8; + IT8XXX2_I2C_RAMLA2(base) = out_data_addr; + + /* Byte counter setting */ + /* This register indicates byte count[10:3]. */ + IT8XXX2_I2C_BYTE_CNT_H(base) = + CONFIG_I2C_TARGET_IT8XXX2_MAX_BUF_SIZE >> 3; + /* This register indicates byte count[2:0]. */ + IT8XXX2_I2C_BYTE_CNT_L(base) = + CONFIG_I2C_TARGET_IT8XXX2_MAX_BUF_SIZE & GENMASK(2, 0); - /* I2C module enable and command queue mode */ - IT8XXX2_I2C_CTR1(base) = IT8XXX2_I2C_COMQ_EN | IT8XXX2_I2C_MDL_EN; + /* + * The EC processor(CPU) cannot be in the k_cpu_idle() and power + * policy during the transactions with the CQ mode(DMA mode). + * Otherwise, the EC processor would be clock gated. + */ + chip_block_idle(); + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + + /* I2C module enable and command queue mode */ + IT8XXX2_I2C_CTR1(base) = IT8XXX2_I2C_COMQ_EN | IT8XXX2_I2C_MDL_EN; + } ite_intc_isr_clear(config->i2c_irq_base); irq_enable(config->i2c_irq_base); @@ -1296,10 +1403,13 @@ static int i2c_enhance_target_unregister(const struct device *dev, /* Permit to enter power policy and idle mode. */ pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); - chip_permit_idle(); + if (!config->target_pio_mode) { + chip_permit_idle(); + } data->target_cfg = NULL; data->target_attached = false; + data->target_nack = 0; return 0; } @@ -1339,12 +1449,14 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_I2C_TARGET_BUFFER_MODE), .bitrate = DT_INST_PROP(inst, clock_frequency), \ .i2c_irq_base = DT_INST_IRQN(inst), \ .port = DT_INST_PROP(inst, port_num), \ + .channel_switch_sel = DT_INST_PROP(inst, channel_switch_sel), \ .scl_gpios = GPIO_DT_SPEC_INST_GET(inst, scl_gpios), \ .sda_gpios = GPIO_DT_SPEC_INST_GET(inst, sda_gpios), \ .prescale_scl_low = DT_INST_PROP_OR(inst, prescale_scl_low, 0), \ .clock_gate_offset = DT_INST_PROP(inst, clock_gate_offset), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ .target_enable = DT_INST_PROP(inst, target_enable), \ + .target_pio_mode = DT_INST_PROP(inst, target_pio_mode), \ }; \ \ static struct i2c_enhance_data i2c_enhance_data_##inst; \ diff --git a/drivers/i2c/i2c_ite_it8xxx2.c b/drivers/i2c/i2c_ite_it8xxx2.c index 2a55576ef5b..b931a932030 100644 --- a/drivers/i2c/i2c_ite_it8xxx2.c +++ b/drivers/i2c/i2c_ite_it8xxx2.c @@ -44,6 +44,7 @@ struct i2c_it8xxx2_config { uint8_t *reg_mstfctrl; uint8_t i2c_irq_base; uint8_t port; + uint8_t channel_switch_sel; /* SCL GPIO cells */ struct gpio_dt_spec scl_gpios; /* SDA GPIO cells */ @@ -1134,6 +1135,18 @@ static int i2c_it8xxx2_init(const struct device *dev) } #endif + /* ChannelA-C switch selection of I2C pin */ + if (config->port == SMB_CHANNEL_A) { + IT8XXX2_SMB_SMB01CHS = (IT8XXX2_SMB_SMB01CHS &= ~GENMASK(2, 0)) | + config->channel_switch_sel; + } else if (config->port == SMB_CHANNEL_B) { + IT8XXX2_SMB_SMB01CHS = (config->channel_switch_sel << 4) | + (IT8XXX2_SMB_SMB01CHS &= ~GENMASK(6, 4)); + } else if (config->port == SMB_CHANNEL_C) { + IT8XXX2_SMB_SMB23CHS = (IT8XXX2_SMB_SMB23CHS &= ~GENMASK(2, 0)) | + config->channel_switch_sel; + } + /* Set clock frequency for I2C ports */ if (config->bitrate == I2C_BITRATE_STANDARD || config->bitrate == I2C_BITRATE_FAST || @@ -1242,7 +1255,7 @@ static const struct i2c_driver_api i2c_it8xxx2_driver_api = { * that channel C may encounter wrong register being written due to FIFO2 * byte counter wrong write after channel B's write operation. */ -BUILD_ASSERT((DT_INST_PROP(SMB_CHANNEL_C, fifo_enable) == false), +BUILD_ASSERT((DT_PROP(DT_NODELABEL(i2c2), fifo_enable) == false), "Channel C cannot use FIFO mode."); #endif @@ -1265,6 +1278,7 @@ BUILD_ASSERT((DT_INST_PROP(SMB_CHANNEL_C, fifo_enable) == false), .bitrate = DT_INST_PROP(inst, clock_frequency), \ .i2c_irq_base = DT_INST_IRQN(inst), \ .port = DT_INST_PROP(inst, port_num), \ + .channel_switch_sel = DT_INST_PROP(inst, channel_switch_sel), \ .scl_gpios = GPIO_DT_SPEC_INST_GET(inst, scl_gpios), \ .sda_gpios = GPIO_DT_SPEC_INST_GET(inst, sda_gpios), \ .clock_gate_offset = DT_INST_PROP(inst, clock_gate_offset), \ diff --git a/drivers/i2c/i2c_ll_stm32.c b/drivers/i2c/i2c_ll_stm32.c index 1dffd246412..2fcb1f8e931 100644 --- a/drivers/i2c/i2c_ll_stm32.c +++ b/drivers/i2c/i2c_ll_stm32.c @@ -44,25 +44,39 @@ LOG_MODULE_REGISTER(i2c_ll_stm32); #define STM32_I2C_DOMAIN_CLOCK_SUPPORT 0 #endif +int i2c_stm32_get_config(const struct device *dev, uint32_t *config) +{ + struct i2c_stm32_data *data = dev->data; + + if (!data->is_configured) { + LOG_ERR("I2C controller not configured"); + return -EIO; + } + + *config = data->dev_config; + + return 0; +} + int i2c_stm32_runtime_configure(const struct device *dev, uint32_t config) { const struct i2c_stm32_config *cfg = dev->config; struct i2c_stm32_data *data = dev->data; I2C_TypeDef *i2c = cfg->i2c; - uint32_t clock = 0U; + uint32_t i2c_clock = 0U; int ret; if (IS_ENABLED(STM32_I2C_DOMAIN_CLOCK_SUPPORT) && (cfg->pclk_len > 1)) { if (clock_control_get_rate(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE), (clock_control_subsys_t)&cfg->pclken[1], - &clock) < 0) { + &i2c_clock) < 0) { LOG_ERR("Failed call clock_control_get_rate(pclken[1])"); return -EIO; } } else { if (clock_control_get_rate(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE), (clock_control_subsys_t) &cfg->pclken[0], - &clock) < 0) { + &i2c_clock) < 0) { LOG_ERR("Failed call clock_control_get_rate(pclken[0])"); return -EIO; } @@ -73,19 +87,23 @@ int i2c_stm32_runtime_configure(const struct device *dev, uint32_t config) k_sem_take(&data->bus_mutex, K_FOREVER); #ifdef CONFIG_PM_DEVICE_RUNTIME - (void)pm_device_runtime_get(dev); -#else - pm_device_busy_set(dev); + ret = clock_control_on(clk, (clock_control_subsys_t)&cfg->pclken[0]); + if (ret < 0) { + LOG_ERR("failure Enabling I2C clock"); + return ret; + } #endif LL_I2C_Disable(i2c); LL_I2C_SetMode(i2c, LL_I2C_MODE_I2C); - ret = stm32_i2c_configure_timing(dev, clock); + ret = stm32_i2c_configure_timing(dev, i2c_clock); #ifdef CONFIG_PM_DEVICE_RUNTIME - (void)pm_device_runtime_put(dev); -#else - pm_device_busy_clear(dev); + ret = clock_control_off(clk, (clock_control_subsys_t)&cfg->pclken[0]); + if (ret < 0) { + LOG_ERR("failure disabling I2C clock"); + return ret; + } #endif k_sem_give(&data->bus_mutex); @@ -146,11 +164,6 @@ static int i2c_stm32_transfer(const struct device *dev, struct i2c_msg *msg, return ret; } - ret = pm_device_runtime_get(dev); - if (ret < 0) { - return ret; - } - /* Send out messages */ k_sem_take(&data->bus_mutex, K_FOREVER); @@ -277,6 +290,7 @@ static int i2c_stm32_recover_bus(const struct device *dev) static const struct i2c_driver_api api_funcs = { .configure = i2c_stm32_runtime_configure, .transfer = i2c_stm32_transfer, + .get_config = i2c_stm32_get_config, #if CONFIG_I2C_STM32_BUS_RECOVERY .recover_bus = i2c_stm32_recover_bus, #endif /* CONFIG_I2C_STM32_BUS_RECOVERY */ @@ -351,6 +365,8 @@ static int i2c_stm32_init(const struct device *dev) cfg->irq_config_func(dev); #endif + data->is_configured = false; + /* * initialize mutex used when multiple transfers * are taking place to guarantee that each one is @@ -396,11 +412,11 @@ static int i2c_stm32_init(const struct device *dev) } #ifdef CONFIG_PM_DEVICE_RUNTIME - i2c_stm32_suspend(dev); - pm_device_init_suspended(dev); (void)pm_device_runtime_enable(dev); #endif + data->is_configured = true; + return 0; } diff --git a/drivers/i2c/i2c_ll_stm32.h b/drivers/i2c/i2c_ll_stm32.h index 1db22236043..c77b687038d 100644 --- a/drivers/i2c/i2c_ll_stm32.h +++ b/drivers/i2c/i2c_ll_stm32.h @@ -78,6 +78,7 @@ struct i2c_stm32_data { #endif bool slave_attached; #endif + bool is_configured; }; int32_t stm32_i2c_transaction(const struct device *dev, @@ -85,6 +86,7 @@ int32_t stm32_i2c_transaction(const struct device *dev, uint16_t periph); int32_t stm32_i2c_configure_timing(const struct device *dev, uint32_t clk); int i2c_stm32_runtime_configure(const struct device *dev, uint32_t config); +int i2c_stm32_get_config(const struct device *dev, uint32_t *config); void stm32_i2c_event_isr(void *arg); void stm32_i2c_error_isr(void *arg); diff --git a/drivers/i2c/i2c_ll_stm32_v2.c b/drivers/i2c/i2c_ll_stm32_v2.c index ea2e626f8ec..c75d68e4f19 100644 --- a/drivers/i2c/i2c_ll_stm32_v2.c +++ b/drivers/i2c/i2c_ll_stm32_v2.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include "i2c_ll_stm32.h" #define LOG_LEVEL CONFIG_I2C_LOG_LEVEL @@ -101,6 +103,10 @@ static void stm32_i2c_master_mode_end(const struct device *dev) stm32_i2c_disable_transfer_interrupts(dev); + if (LL_I2C_IsEnabledReloadMode(i2c)) { + LL_I2C_DisableReloadMode(i2c); + } + #if defined(CONFIG_I2C_TARGET) data->master_active = false; if (!data->slave_attached) { @@ -120,18 +126,25 @@ static void stm32_i2c_slave_event(const struct device *dev) I2C_TypeDef *i2c = cfg->i2c; const struct i2c_target_callbacks *slave_cb; struct i2c_target_config *slave_cfg; - uint8_t slave_address; - - /* Choose the right slave from the address match code */ - slave_address = LL_I2C_GetAddressMatchCode(i2c) >> 1; - if (data->slave_cfg != NULL && slave_address == data->slave_cfg->address) { - slave_cfg = data->slave_cfg; - } else if (data->slave2_cfg != NULL && slave_address == data->slave2_cfg->address) { - slave_cfg = data->slave2_cfg; - } else { - __ASSERT_NO_MSG(0); - return; + + if (data->slave_cfg->flags != I2C_TARGET_FLAGS_ADDR_10_BITS) { + uint8_t slave_address; + + /* Choose the right slave from the address match code */ + slave_address = LL_I2C_GetAddressMatchCode(i2c) >> 1; + if (data->slave_cfg != NULL && + slave_address == data->slave_cfg->address) { + slave_cfg = data->slave_cfg; + } else if (data->slave2_cfg != NULL && + slave_address == data->slave2_cfg->address) { + slave_cfg = data->slave2_cfg; + } else { + __ASSERT_NO_MSG(0); + return; + } } + + slave_cfg = data->slave_cfg; slave_cb = slave_cfg->callbacks; if (LL_I2C_IsActiveFlag_TXIS(i2c)) { @@ -220,6 +233,16 @@ int i2c_stm32_target_register(const struct device *dev, return ret; } +#if defined(CONFIG_PM_DEVICE_RUNTIME) + if (pm_device_wakeup_is_capable(dev)) { + /* Mark device as active */ + (void)pm_device_runtime_get(dev); + /* Enable wake-up from stop */ + LOG_DBG("i2c: enabling wakeup from stop"); + LL_I2C_EnableWakeUpFromStop(cfg->i2c); + } +#endif /* defined(CONFIG_PM_DEVICE_RUNTIME) */ + LL_I2C_Enable(i2c); if (!data->slave_cfg) { @@ -299,6 +322,16 @@ int i2c_stm32_target_unregister(const struct device *dev, LL_I2C_Disable(i2c); +#if defined(CONFIG_PM_DEVICE_RUNTIME) + if (pm_device_wakeup_is_capable(dev)) { + /* Disable wake-up from STOP */ + LOG_DBG("i2c: disabling wakeup from stop"); + LL_I2C_DisableWakeUpFromStop(i2c); + /* Release the device */ + (void)pm_device_runtime_put(dev); + } +#endif /* defined(CONFIG_PM_DEVICE_RUNTIME) */ + data->slave_attached = false; return 0; @@ -702,6 +735,8 @@ int stm32_i2c_configure_timing(const struct device *dev, uint32_t clock) i2c_setup_time_min = 500U; break; default: + LOG_ERR("i2c: speed above \"fast\" requires manual timing configuration, " + "see \"timings\" property of st,stm32-i2c-v2 devicetree binding"); return -EINVAL; } diff --git a/drivers/i2c/i2c_nrfx_twi.c b/drivers/i2c/i2c_nrfx_twi.c index bbb070e7e0c..8af5fe4ddee 100644 --- a/drivers/i2c/i2c_nrfx_twi.c +++ b/drivers/i2c/i2c_nrfx_twi.c @@ -126,7 +126,6 @@ static int i2c_nrfx_twi_transfer(const struct device *dev, * to make sure everything has been done to restore the * bus from this error. */ - LOG_ERR("Error on I2C line occurred for message %d", i); nrfx_twi_disable(&config->twi); (void)i2c_nrfx_twi_recover_bus(dev); ret = -EIO; @@ -135,7 +134,6 @@ static int i2c_nrfx_twi_transfer(const struct device *dev, res = data->res; if (res != NRFX_SUCCESS) { - LOG_ERR("Error 0x%08X occurred for message %d", res, i); ret = -EIO; break; } diff --git a/drivers/i2c/i2c_nrfx_twim.c b/drivers/i2c/i2c_nrfx_twim.c index a282a60746f..90e1fcfb109 100644 --- a/drivers/i2c/i2c_nrfx_twim.c +++ b/drivers/i2c/i2c_nrfx_twim.c @@ -38,6 +38,7 @@ struct i2c_nrfx_twim_config { uint16_t msg_buf_size; void (*irq_connect)(void); const struct pinctrl_dev_config *pcfg; + uint16_t max_transfer_size; }; static int i2c_nrfx_twim_recover_bus(const struct device *dev); @@ -124,6 +125,14 @@ static int i2c_nrfx_twim_transfer(const struct device *dev, cur_xfer.type = (msgs[i].flags & I2C_MSG_READ) ? NRFX_TWIM_XFER_RX : NRFX_TWIM_XFER_TX; + if (cur_xfer.primary_length > dev_config->max_transfer_size) { + LOG_ERR("Trying to transfer more than the maximum size " + "for this device: %d > %d", + cur_xfer.primary_length, + dev_config->max_transfer_size); + return -ENOSPC; + } + nrfx_err_t res = nrfx_twim_xfer(&dev_config->twim, &cur_xfer, (msgs[i].flags & I2C_MSG_STOP) ? @@ -157,7 +166,6 @@ static int i2c_nrfx_twim_transfer(const struct device *dev, * to make sure everything has been done to restore the * bus from this error. */ - LOG_ERR("Error on I2C line occurred for message %d", i); (void)i2c_nrfx_twim_recover_bus(dev); ret = -EIO; break; @@ -166,7 +174,6 @@ static int i2c_nrfx_twim_transfer(const struct device *dev, res = dev_data->res; if (res != NRFX_SUCCESS) { - LOG_ERR("Error 0x%08X occurred for message %d", res, i); ret = -EIO; break; } @@ -412,6 +419,8 @@ static int i2c_nrfx_twim_init(const struct device *dev) .msg_buf_size = MSG_BUF_SIZE(idx), \ .irq_connect = irq_connect##idx, \ .pcfg = PINCTRL_DT_DEV_CONFIG_GET(I2C(idx)), \ + .max_transfer_size = BIT_MASK( \ + DT_PROP(I2C(idx), easydma_maxcnt_bits)), \ }; \ PM_DEVICE_DT_DEFINE(I2C(idx), twim_nrfx_pm_action); \ I2C_DEVICE_DT_DEFINE(I2C(idx), \ @@ -444,3 +453,55 @@ I2C_NRFX_TWIM_DEVICE(2); #ifdef CONFIG_HAS_HW_NRF_TWIM3 I2C_NRFX_TWIM_DEVICE(3); #endif + +#ifdef CONFIG_HAS_HW_NRF_TWIM20 +I2C_NRFX_TWIM_DEVICE(20); +#endif + +#ifdef CONFIG_HAS_HW_NRF_TWIM21 +I2C_NRFX_TWIM_DEVICE(21); +#endif + +#ifdef CONFIG_HAS_HW_NRF_TWIM22 +I2C_NRFX_TWIM_DEVICE(22); +#endif + +#ifdef CONFIG_HAS_HW_NRF_TWIM30 +I2C_NRFX_TWIM_DEVICE(30); +#endif + +#ifdef CONFIG_HAS_HW_NRF_TWIM120 +I2C_NRFX_TWIM_DEVICE(120); +#endif + +#ifdef CONFIG_HAS_HW_NRF_TWIM130 +I2C_NRFX_TWIM_DEVICE(130); +#endif + +#ifdef CONFIG_HAS_HW_NRF_TWIM131 +I2C_NRFX_TWIM_DEVICE(131); +#endif + +#ifdef CONFIG_HAS_HW_NRF_TWIM132 +I2C_NRFX_TWIM_DEVICE(132); +#endif + +#ifdef CONFIG_HAS_HW_NRF_TWIM133 +I2C_NRFX_TWIM_DEVICE(133); +#endif + +#ifdef CONFIG_HAS_HW_NRF_TWIM134 +I2C_NRFX_TWIM_DEVICE(134); +#endif + +#ifdef CONFIG_HAS_HW_NRF_TWIM135 +I2C_NRFX_TWIM_DEVICE(135); +#endif + +#ifdef CONFIG_HAS_HW_NRF_TWIM136 +I2C_NRFX_TWIM_DEVICE(136); +#endif + +#ifdef CONFIG_HAS_HW_NRF_TWIM137 +I2C_NRFX_TWIM_DEVICE(137); +#endif diff --git a/drivers/i2c/i2c_rcar.c b/drivers/i2c/i2c_rcar.c index 5eeecc6a64e..d6ac6678853 100644 --- a/drivers/i2c/i2c_rcar.c +++ b/drivers/i2c/i2c_rcar.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/i2c/i2c_rtio.c b/drivers/i2c/i2c_rtio.c index f4a97345e27..7e74329612d 100644 --- a/drivers/i2c/i2c_rtio.c +++ b/drivers/i2c/i2c_rtio.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "zephyr/rtio/rtio.h" +#include #include #include #include diff --git a/drivers/i2c/i2c_sam_twihs_rtio.c b/drivers/i2c/i2c_sam_twihs_rtio.c index 1111a03c4e1..40abfd0c263 100644 --- a/drivers/i2c/i2c_sam_twihs_rtio.c +++ b/drivers/i2c/i2c_sam_twihs_rtio.c @@ -6,7 +6,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "zephyr/spinlock.h" +#include #define DT_DRV_COMPAT atmel_sam_i2c_twihs /** @file diff --git a/drivers/i2s/Kconfig.nrfx b/drivers/i2s/Kconfig.nrfx index 404f78a15bf..b36f3eb9c64 100644 --- a/drivers/i2s/Kconfig.nrfx +++ b/drivers/i2s/Kconfig.nrfx @@ -6,6 +6,8 @@ menuconfig I2S_NRFX default y depends on DT_HAS_NORDIC_NRF_I2S_ENABLED select NRFX_I2S0 if HAS_HW_NRF_I2S0 + select NRFX_I2S20 if HAS_HW_NRF_I2S20 + select PINCTRL help Enable support for nrfx I2S driver for nRF MCU series. diff --git a/drivers/i2s/i2s_handlers.c b/drivers/i2s/i2s_handlers.c index c454f8374b1..0ef1f6e6cd5 100644 --- a/drivers/i2s/i2s_handlers.c +++ b/drivers/i2s/i2s_handlers.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include @@ -16,24 +16,24 @@ static inline int z_vrfy_i2s_configure(const struct device *dev, struct i2s_config config; int ret = -EINVAL; - if (Z_SYSCALL_DRIVER_I2S(dev, configure)) { + if (K_SYSCALL_DRIVER_I2S(dev, configure)) { goto out; } - Z_OOPS(z_user_from_copy(&config, (const void *)cfg_ptr, + K_OOPS(k_usermode_from_copy(&config, (const void *)cfg_ptr, sizeof(struct i2s_config))); /* Check that the k_mem_slab provided is a valid pointer and that * the caller has permission on it */ - if (Z_SYSCALL_OBJ(config.mem_slab, K_OBJ_MEM_SLAB)) { + if (K_SYSCALL_OBJ(config.mem_slab, K_OBJ_MEM_SLAB)) { goto out; } /* Ensure that the k_mem_slab's slabs are large enough for the * specified block size */ - if (config.block_size > config.mem_slab->block_size) { + if (config.block_size > config.mem_slab->info.block_size) { goto out; } @@ -50,7 +50,7 @@ static inline int z_vrfy_i2s_buf_read(const struct device *dev, size_t data_size; int ret; - Z_OOPS(Z_SYSCALL_DRIVER_I2S(dev, read)); + K_OOPS(K_SYSCALL_DRIVER_I2S(dev, read)); ret = i2s_read((const struct device *)dev, &mem_block, &data_size); @@ -63,12 +63,12 @@ static inline int z_vrfy_i2s_buf_read(const struct device *dev, */ rx_cfg = i2s_config_get((const struct device *)dev, I2S_DIR_RX); - copy_success = z_user_to_copy((void *)buf, mem_block, + copy_success = k_usermode_to_copy((void *)buf, mem_block, data_size); k_mem_slab_free(rx_cfg->mem_slab, mem_block); - Z_OOPS(copy_success); - Z_OOPS(z_user_to_copy((void *)size, &data_size, + K_OOPS(copy_success); + K_OOPS(k_usermode_to_copy((void *)size, &data_size, sizeof(data_size))); } @@ -83,7 +83,7 @@ static inline int z_vrfy_i2s_buf_write(const struct device *dev, const struct i2s_config *tx_cfg; void *mem_block; - Z_OOPS(Z_SYSCALL_DRIVER_I2S(dev, write)); + K_OOPS(K_SYSCALL_DRIVER_I2S(dev, write)); tx_cfg = i2s_config_get((const struct device *)dev, I2S_DIR_TX); if (!tx_cfg) { return -EIO; @@ -98,10 +98,10 @@ static inline int z_vrfy_i2s_buf_write(const struct device *dev, return -ENOMEM; } - ret = z_user_from_copy(mem_block, (void *)buf, size); + ret = k_usermode_from_copy(mem_block, (void *)buf, size); if (ret) { k_mem_slab_free(tx_cfg->mem_slab, mem_block); - Z_OOPS(ret); + K_OOPS(ret); } ret = i2s_write((const struct device *)dev, mem_block, size); @@ -117,7 +117,7 @@ static inline int z_vrfy_i2s_trigger(const struct device *dev, enum i2s_dir dir, enum i2s_trigger_cmd cmd) { - Z_OOPS(Z_SYSCALL_DRIVER_I2S(dev, trigger)); + K_OOPS(K_SYSCALL_DRIVER_I2S(dev, trigger)); return z_impl_i2s_trigger((const struct device *)dev, dir, cmd); } diff --git a/drivers/i2s/i2s_mcux_flexcomm.c b/drivers/i2s/i2s_mcux_flexcomm.c index d1dda99a5f2..4155bd24b62 100644 --- a/drivers/i2s/i2s_mcux_flexcomm.c +++ b/drivers/i2s/i2s_mcux_flexcomm.c @@ -901,7 +901,7 @@ static int i2s_mcux_init(const struct device *dev) data->tx.state = I2S_STATE_NOT_READY; data->rx.state = I2S_STATE_NOT_READY; - LOG_INF("Device %s inited", dev->name); + LOG_DBG("Device %s inited", dev->name); return 0; } diff --git a/drivers/i2s/i2s_mcux_sai.c b/drivers/i2s/i2s_mcux_sai.c index ebb9b9f00d5..08bcdbb6343 100644 --- a/drivers/i2s/i2s_mcux_sai.c +++ b/drivers/i2s/i2s_mcux_sai.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 NXP Semiconductor INC. + * Copyright 2021,2023 NXP Semiconductor INC. * All rights reserved. * * SPDX-License-Identifier: Apache-2.0 @@ -577,11 +577,18 @@ static int i2s_mcux_config(const struct device *dev, enum i2s_dir dir, SAI_GetDSPConfig(&config, kSAI_FrameSyncLenOneBitClk, word_size_bits, kSAI_Stereo, dev_cfg->tx_channel); + /* We need to set the data word count manually, since the HAL + * function does not + */ + config.serialData.dataWordNum = num_words; + config.frameSync.frameSyncEarly = true; + config.bitClock.bclkPolarity = kSAI_SampleOnFallingEdge; break; case I2S_FMT_DATA_FORMAT_PCM_LONG: SAI_GetTDMConfig(&config, kSAI_FrameSyncLenPerWordWidth, word_size_bits, num_words, dev_cfg->tx_channel); + config.bitClock.bclkPolarity = kSAI_SampleOnFallingEdge; break; default: LOG_ERR("Unsupported I2S data format"); @@ -629,40 +636,52 @@ static int i2s_mcux_config(const struct device *dev, enum i2s_dir dir, /* clock signal polarity */ switch (i2s_cfg->format & I2S_FMT_CLK_FORMAT_MASK) { case I2S_FMT_CLK_NF_NB: - config.frameSync.frameSyncPolarity = - kSAI_PolarityActiveLow; - config.bitClock.bclkSrcSwap = false; + /* No action required, leave the configuration untouched */ break; case I2S_FMT_CLK_NF_IB: - config.frameSync.frameSyncPolarity = - kSAI_PolarityActiveLow; - config.bitClock.bclkSrcSwap = true; + /* Swap bclk polarity */ + config.bitClock.bclkPolarity = + (config.bitClock.bclkPolarity == kSAI_SampleOnFallingEdge) ? + kSAI_SampleOnRisingEdge : + kSAI_SampleOnFallingEdge; break; case I2S_FMT_CLK_IF_NB: + /* Swap frame sync polarity */ config.frameSync.frameSyncPolarity = - kSAI_PolarityActiveHigh; - config.bitClock.bclkSrcSwap = false; + (config.frameSync.frameSyncPolarity == kSAI_PolarityActiveHigh) ? + kSAI_PolarityActiveLow : + kSAI_PolarityActiveHigh; break; case I2S_FMT_CLK_IF_IB: + /* Swap frame sync and bclk polarity */ config.frameSync.frameSyncPolarity = - kSAI_PolarityActiveHigh; - config.bitClock.bclkSrcSwap = true; + (config.frameSync.frameSyncPolarity == kSAI_PolarityActiveHigh) ? + kSAI_PolarityActiveLow : + kSAI_PolarityActiveHigh; + config.bitClock.bclkPolarity = + (config.bitClock.bclkPolarity == kSAI_SampleOnFallingEdge) ? + kSAI_SampleOnRisingEdge : + kSAI_SampleOnFallingEdge; break; } - config.frameSync.frameSyncWidth = (uint8_t)word_size_bits; + /* PCM short format always requires that WS be one BCLK cycle */ + if ((i2s_cfg->format & I2S_FMT_DATA_FORMAT_MASK) != + I2S_FMT_DATA_FORMAT_PCM_SHORT) { + config.frameSync.frameSyncWidth = (uint8_t)word_size_bits; + } if (dir == I2S_DIR_TX) { memcpy(&dev_data->tx.cfg, i2s_cfg, sizeof(struct i2s_config)); LOG_DBG("tx slab free_list = 0x%x", (uint32_t)i2s_cfg->mem_slab->free_list); LOG_DBG("tx slab num_blocks = %d", - (uint32_t)i2s_cfg->mem_slab->num_blocks); + (uint32_t)i2s_cfg->mem_slab->info.num_blocks); LOG_DBG("tx slab block_size = %d", - (uint32_t)i2s_cfg->mem_slab->block_size); + (uint32_t)i2s_cfg->mem_slab->info.block_size); LOG_DBG("tx slab buffer = 0x%x", (uint32_t)i2s_cfg->mem_slab->buffer); @@ -693,9 +712,9 @@ static int i2s_mcux_config(const struct device *dev, enum i2s_dir dir, LOG_DBG("rx slab free_list = 0x%x", (uint32_t)i2s_cfg->mem_slab->free_list); LOG_DBG("rx slab num_blocks = %d", - (uint32_t)i2s_cfg->mem_slab->num_blocks); + (uint32_t)i2s_cfg->mem_slab->info.num_blocks); LOG_DBG("rx slab block_size = %d", - (uint32_t)i2s_cfg->mem_slab->block_size); + (uint32_t)i2s_cfg->mem_slab->info.block_size); LOG_DBG("rx slab buffer = 0x%x", (uint32_t)i2s_cfg->mem_slab->buffer); @@ -1235,9 +1254,7 @@ static const struct i2s_driver_api i2s_mcux_driver_api = { \ static const struct i2s_mcux_config i2s_##i2s_id##_config = { \ .base = (I2S_Type *)DT_INST_REG_ADDR(i2s_id), \ - .clk_src = \ - DT_CLOCKS_CELL_BY_IDX(DT_DRV_INST(i2s_id), \ - 0, bits), \ + .clk_src = DT_INST_PROP(i2s_id, clock_mux), \ .clk_pre_div = DT_INST_PROP(i2s_id, pre_div), \ .clk_src_div = DT_INST_PROP(i2s_id, podf), \ .pll_src = \ diff --git a/drivers/i2s/i2s_nrfx.c b/drivers/i2s/i2s_nrfx.c index ea1aed635a6..e1b3684c4f7 100644 --- a/drivers/i2s/i2s_nrfx.c +++ b/drivers/i2s/i2s_nrfx.c @@ -583,6 +583,7 @@ static int i2s_nrfx_write(const struct device *dev, void *mem_block, size_t size) { struct i2s_nrfx_drv_data *drv_data = dev->data; + int ret; if (!drv_data->tx_configured) { LOG_ERR("Device is not configured"); @@ -601,26 +602,41 @@ static int i2s_nrfx_write(const struct device *dev, return -EIO; } + ret = k_msgq_put(&drv_data->tx_queue, + &mem_block, + SYS_TIMEOUT_MS(drv_data->tx.cfg.timeout)); + if (ret < 0) { + return ret; + } + + LOG_DBG("Queued TX %p", mem_block); + + /* Check if interrupt wanted to get next TX buffer before current buffer + * was queued. Do not move this check before queuing because doing so + * opens the possibility for a race condition between this function and + * data_handler() that is called in interrupt context. + */ if (drv_data->state == I2S_STATE_RUNNING && drv_data->next_tx_buffer_needed) { - nrfx_i2s_buffers_t next = { .p_tx_buffer = mem_block }; + nrfx_i2s_buffers_t next = { 0 }; + + if (!get_next_tx_buffer(drv_data, &next)) { + /* Log error because this is definitely unexpected. + * Do not return error because the caller is no longer + * responsible for releasing the buffer. + */ + LOG_ERR("Cannot reacquire queued buffer"); + return 0; + } drv_data->next_tx_buffer_needed = false; - LOG_DBG("Next TX %p", mem_block); + LOG_DBG("Next TX %p", next.p_tx_buffer); if (!supply_next_buffers(drv_data, &next)) { return -EIO; } - } else { - int ret = k_msgq_put(&drv_data->tx_queue, - &mem_block, - SYS_TIMEOUT_MS(drv_data->tx.cfg.timeout)); - if (ret < 0) { - return ret; - } - LOG_DBG("Queued TX %p", mem_block); } return 0; @@ -939,5 +955,10 @@ static const struct i2s_driver_api i2s_nrf_drv_api = { POST_KERNEL, CONFIG_I2S_INIT_PRIORITY, \ &i2s_nrf_drv_api); -/* Existing SoCs only have one I2S instance. */ +#ifdef CONFIG_HAS_HW_NRF_I2S0 I2S_NRFX_DEVICE(0); +#endif + +#ifdef CONFIG_HAS_HW_NRF_I2S20 +I2S_NRFX_DEVICE(20); +#endif diff --git a/drivers/i3c/CMakeLists.txt b/drivers/i3c/CMakeLists.txt index 2645dbeabb5..71a7dc6eb27 100644 --- a/drivers/i3c/CMakeLists.txt +++ b/drivers/i3c/CMakeLists.txt @@ -30,3 +30,8 @@ zephyr_library_sources_ifdef( CONFIG_I3C_CADENCE i3c_cdns.c ) + +zephyr_library_sources_ifdef( + CONFIG_I3C_TEST + i3c_test.c +) diff --git a/drivers/i3c/Kconfig b/drivers/i3c/Kconfig index f4a343632ab..2b524c2bf9d 100644 --- a/drivers/i3c/Kconfig +++ b/drivers/i3c/Kconfig @@ -100,5 +100,6 @@ comment "Device Drivers" rsource "Kconfig.nxp" rsource "Kconfig.cdns" +rsource "Kconfig.test" endif # I3C diff --git a/drivers/i3c/Kconfig.test b/drivers/i3c/Kconfig.test new file mode 100644 index 00000000000..3b28d596980 --- /dev/null +++ b/drivers/i3c/Kconfig.test @@ -0,0 +1,11 @@ +# Copyright (c) 2021, Commonwealth Scientific and Industrial Research +# Organisation (CSIRO) ABN 41 687 119 230. +# Copyright (c) 2023 STMicroelectronics +# +# SPDX-License-Identifier: Apache-2.0 + +# Hidden option for turning on the dummy driver for vnd,i3c devices +# used in testing. +config I3C_TEST + def_bool DT_HAS_VND_I3C_ENABLED + depends on DT_HAS_VND_I3C_ENABLED diff --git a/drivers/i3c/i3c_cdns.c b/drivers/i3c/i3c_cdns.c index 6ca92581595..cad71e5cae6 100644 --- a/drivers/i3c/i3c_cdns.c +++ b/drivers/i3c/i3c_cdns.c @@ -371,12 +371,13 @@ #define I3C_CONTROLLER_ADDR 0x08 /* Maximum i3c devices that the IP can be built with */ -#define I3C_MAX_DEVS 11 -#define I3C_MAX_MSGS 10 -#define I3C_SIR_DEFAULT_DA 0x7F -#define I3C_MAX_IDLE_WAIT_RETRIES 50 -#define I3C_PRESCL_REG_SCALE (4) -#define I2C_PRESCL_REG_SCALE (5) +#define I3C_MAX_DEVS 11 +#define I3C_MAX_MSGS 10 +#define I3C_SIR_DEFAULT_DA 0x7F +#define I3C_MAX_IDLE_CANCEL_WAIT_RETRIES 50 +#define I3C_MAX_IDLE_WAIT_RETRIES 5000 +#define I3C_PRESCL_REG_SCALE (4) +#define I2C_PRESCL_REG_SCALE (5) /* Target T_LOW period in open-drain mode. */ #define I3C_BUS_TLOW_OD_MIN_NS 200 @@ -612,30 +613,6 @@ static int cdns_i3c_read_rx_fifo(const struct cdns_i3c_config *config, void *buf return 0; } -static int cdns_i3c_read_ibi_fifo(const struct cdns_i3c_config *config, void *buf, uint32_t len) -{ - uint32_t *ptr = buf; - uint32_t remain, val; - - for (remain = len; remain >= 4; remain -= 4) { - if (cdns_i3c_ibi_fifo_empty(config)) { - return -EIO; - } - val = sys_le32_to_cpu(sys_read32(config->base + IBI_DATA_FIFO)); - *ptr++ = val; - } - - if (remain > 0) { - if (cdns_i3c_ibi_fifo_empty(config)) { - return -EIO; - } - val = sys_le32_to_cpu(sys_read32(config->base + IBI_DATA_FIFO)); - memcpy(ptr, &val, remain); - } - - return 0; -} - static void cdns_i3c_set_prescalers(const struct device *dev) { struct cdns_i3c_data *data = dev->data; @@ -726,7 +703,7 @@ static void cdns_i3c_program_controller_retaining_reg(const struct device *dev) if (!i3c_addr_slots_is_free(&data->common.attached_dev.addr_slots, controller_da)) { controller_da = - i3c_addr_slots_next_free_find(&data->common.attached_dev.addr_slots); + i3c_addr_slots_next_free_find(&data->common.attached_dev.addr_slots, 0); LOG_DBG("%s: 0x%02x DA selected for controller", dev->name, controller_da); } sys_write32(prepare_rr0_dev_address(controller_da), config->base + DEV_ID_RR0(0)); @@ -875,8 +852,9 @@ static void cdns_i3c_cancel_transfer(const struct device *dev) sys_write32(MST_INT_CMDD_EMP, config->base + MST_IDR); /* Ignore if no pending transfer */ - if (data->xfer.num_cmds == 0) + if (data->xfer.num_cmds == 0) { return; + } data->xfer.num_cmds = 0; @@ -888,7 +866,7 @@ static void cdns_i3c_cancel_transfer(const struct device *dev) * actually take any time since we only get here if a transaction didn't * complete in a long time. */ - retry_count = I3C_MAX_IDLE_WAIT_RETRIES; + retry_count = I3C_MAX_IDLE_CANCEL_WAIT_RETRIES; while (retry_count--) { val = sys_read32(config->base + MST_STATUS0); if (val & MST_STATUS0_IDLE) { @@ -1017,6 +995,22 @@ static int cdns_i3c_do_ccc(const struct device *dev, struct i3c_ccc_payload *pay k_mutex_lock(&data->bus_lock, K_FOREVER); + /** + * Spin waiting for device to go idle. It is unlikely that this will + * actually take any time unless if the last transaction came immediately + * after an error condition. + */ + uint32_t retry_count = I3C_MAX_IDLE_WAIT_RETRIES; + + while (!(sys_read32(config->base + MST_STATUS0) & MST_STATUS0_IDLE) && (retry_count > 0)) { + retry_count--; + } + if (retry_count == 0) { + LOG_ERR("%s: Unable to start transfer, device not idle", dev->name); + ret = -EAGAIN; + goto error; + } + dcmd->cmd1 = CMD1_FIFO_CCC(payload->ccc.id); dcmd->cmd0 = CMD0_FIFO_IS_CCC; dcmd->len = 0; @@ -1070,7 +1064,6 @@ static int cdns_i3c_do_ccc(const struct device *dev, struct i3c_ccc_payload *pay data->xfer.num_cmds = num_cmds; cdns_i3c_start_transfer(dev); - if (k_sem_take(&data->xfer.complete, K_MSEC(1000)) != 0) { cdns_i3c_cancel_transfer(dev); } @@ -1080,6 +1073,7 @@ static int cdns_i3c_do_ccc(const struct device *dev, struct i3c_ccc_payload *pay } ret = data->xfer.ret; +error: k_mutex_unlock(&data->bus_lock); return ret; @@ -1302,7 +1296,7 @@ static void cdns_i3c_complete_transfer(const struct device *dev) } for (int i = 0; i < data->xfer.num_cmds; i++) { - switch (data->xfer.cmds->error) { + switch (data->xfer.cmds[i].error) { case CMDR_NO_ERROR: break; @@ -1389,6 +1383,22 @@ static int cdns_i3c_i2c_transfer(const struct device *dev, struct i3c_i2c_device k_mutex_lock(&data->bus_lock, K_FOREVER); + /** + * Spin waiting for device to go idle. It is unlikely that this will + * actually take any time unless if the last transaction came immediately + * after an error condition. + */ + uint32_t retry_count = I3C_MAX_IDLE_WAIT_RETRIES; + + while (!(sys_read32(config->base + MST_STATUS0) & MST_STATUS0_IDLE) && (retry_count > 0)) { + retry_count--; + } + if (retry_count == 0) { + LOG_ERR("%s: Unable to start transfer, device not idle", dev->name); + ret = -EAGAIN; + goto error; + } + for (unsigned int i = 0; i < num_msgs; i++) { struct cdns_i3c_cmd *cmd = &data->xfer.cmds[i]; @@ -1422,6 +1432,7 @@ static int cdns_i3c_i2c_transfer(const struct device *dev, struct i3c_i2c_device } ret = data->xfer.ret; +error: k_mutex_unlock(&data->bus_lock); return ret; @@ -1433,8 +1444,9 @@ static int cdns_i3c_master_get_rr_slot(const struct device *dev, uint8_t dyn_add const struct cdns_i3c_config *config = dev->config; if (dyn_addr == 0) { - if (!data->free_rr_slots) + if (!data->free_rr_slots) { return -ENOSPC; + } return find_lsb_set(data->free_rr_slots) - 1; } @@ -1664,6 +1676,22 @@ static int cdns_i3c_transfer(const struct device *dev, struct i3c_device_desc *t k_mutex_lock(&data->bus_lock, K_FOREVER); + /** + * Spin waiting for device to go idle. It is unlikely that this will + * actually take any time unless if the last transaction came immediately + * after an error condition. + */ + uint32_t retry_count = I3C_MAX_IDLE_WAIT_RETRIES; + + while (!(sys_read32(config->base + MST_STATUS0) & MST_STATUS0_IDLE) && (retry_count > 0)) { + retry_count--; + } + if (retry_count == 0) { + LOG_ERR("%s: Unable to start transfer, device not idle", dev->name); + ret = -EAGAIN; + goto error; + } + /* * Prepare transfer commands. Currently there is only a single transfer * in-flight but it would be possible to keep a queue of transfers. If so, @@ -1716,11 +1744,37 @@ static int cdns_i3c_transfer(const struct device *dev, struct i3c_device_desc *t } ret = data->xfer.ret; +error: k_mutex_unlock(&data->bus_lock); return ret; } +#ifdef CONFIG_I3C_USE_IBI +static int cdns_i3c_read_ibi_fifo(const struct cdns_i3c_config *config, void *buf, uint32_t len) +{ + uint32_t *ptr = buf; + uint32_t remain, val; + + for (remain = len; remain >= 4; remain -= 4) { + if (cdns_i3c_ibi_fifo_empty(config)) { + return -EIO; + } + val = sys_le32_to_cpu(sys_read32(config->base + IBI_DATA_FIFO)); + *ptr++ = val; + } + + if (remain > 0) { + if (cdns_i3c_ibi_fifo_empty(config)) { + return -EIO; + } + val = sys_le32_to_cpu(sys_read32(config->base + IBI_DATA_FIFO)); + memcpy(ptr, &val, remain); + } + + return 0; +} + static void cdns_i3c_handle_ibi(const struct device *dev, uint32_t ibir) { const struct cdns_i3c_config *config = dev->config; @@ -1815,6 +1869,7 @@ static void cdns_i3c_target_ibi_hj_complete(const struct device *dev) k_sem_give(&data->ibi_hj_complete); } +#endif static void cdns_i3c_irq_handler(const struct device *dev) { @@ -1853,7 +1908,12 @@ static void cdns_i3c_irq_handler(const struct device *dev) /* In-band interrupt */ if (int_st & MST_INT_IBIR_THR) { sys_write32(MST_INT_IBIR_THR, config->base + MST_ICR); +#ifdef CONFIG_I3C_USE_IBI cnds_i3c_master_demux_ibis(dev); +#else + LOG_ERR("%s: IBI received - Kconfig for using IBIs is not enabled", + dev->name); +#endif } /* In-band interrupt data */ @@ -1948,7 +2008,9 @@ static void cdns_i3c_irq_handler(const struct device *dev) /* HJ could send a DISEC which would trigger the SLV_INT_EVENT_UP bit, * but it's still expected to eventually send a DAA */ +#ifdef CONFIG_I3C_USE_IBI cdns_i3c_target_ibi_hj_complete(dev); +#endif } /* HJ complete and DA has been assigned */ @@ -2406,8 +2468,10 @@ static int cdns_i3c_bus_init(const struct device *dev) if (!ctrl_config->is_secondary) { /* Perform bus initialization */ ret = i3c_bus_init(dev, &config->common.dev_list); +#ifdef CONFIG_I3C_USE_IBI /* Bus Initialization Complete, allow HJ ACKs */ sys_write32(CTRL_HJ_ACK | sys_read32(config->base + CTRL), config->base + CTRL); +#endif } return 0; diff --git a/drivers/i3c/i3c_common.c b/drivers/i3c/i3c_common.c index 29746f3cf68..6c170edb9e3 100644 --- a/drivers/i3c/i3c_common.c +++ b/drivers/i3c/i3c_common.c @@ -157,13 +157,13 @@ bool i3c_addr_slots_is_free(struct i3c_addr_slots *slots, return (status == I3C_ADDR_SLOT_STATUS_FREE); } -uint8_t i3c_addr_slots_next_free_find(struct i3c_addr_slots *slots) +uint8_t i3c_addr_slots_next_free_find(struct i3c_addr_slots *slots, uint8_t start_addr) { uint8_t addr; enum i3c_addr_slot_status status; /* Addresses 0 to 7 are reserved. So start at 8. */ - for (addr = 8; addr < I3C_MAX_ADDR; addr++) { + for (addr = MAX(start_addr, 8); addr < I3C_MAX_ADDR; addr++) { status = i3c_addr_slots_status(slots, addr); if (status == I3C_ADDR_SLOT_STATUS_FREE) { return addr; @@ -252,7 +252,7 @@ int i3c_determine_default_addr(struct i3c_device_desc *target, uint8_t *addr) } else { /* address is not free, get the next one */ *addr = i3c_addr_slots_next_free_find( - &data->attached_dev.addr_slots); + &data->attached_dev.addr_slots, 0); } } else { /* Use the init dynamic address as it's DA, but the RR will need to @@ -281,7 +281,7 @@ int i3c_determine_default_addr(struct i3c_device_desc *target, uint8_t *addr) } else { /* pick a DA to use */ *addr = i3c_addr_slots_next_free_find( - &data->attached_dev.addr_slots); + &data->attached_dev.addr_slots, 0); } } } else { @@ -488,7 +488,7 @@ int i3c_dev_list_daa_addr_helper(struct i3c_addr_slots *addr_slots, /* * Find the next available address. */ - dyn_addr = i3c_addr_slots_next_free_find(addr_slots); + dyn_addr = i3c_addr_slots_next_free_find(addr_slots, 0); if (dyn_addr == 0U) { /* No free addresses available */ diff --git a/drivers/i3c/i3c_handlers.c b/drivers/i3c/i3c_handlers.c index e5a5289868d..a5d218992a3 100644 --- a/drivers/i3c/i3c_handlers.c +++ b/drivers/i3c/i3c_handlers.c @@ -6,29 +6,29 @@ #include #include -#include +#include static inline int z_vrfy_i3c_do_ccc(const struct device *dev, struct i3c_ccc_payload *payload) { - Z_OOPS(Z_SYSCALL_DRIVER_I3C(dev, do_ccc)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(payload, sizeof(*payload))); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(payload, sizeof(*payload))); + K_OOPS(K_SYSCALL_DRIVER_I3C(dev, do_ccc)); + K_OOPS(K_SYSCALL_MEMORY_READ(payload, sizeof(*payload))); + K_OOPS(K_SYSCALL_MEMORY_WRITE(payload, sizeof(*payload))); if (payload->ccc.data != NULL) { - Z_OOPS(Z_SYSCALL_MEMORY_ARRAY_READ(payload->ccc.data, + K_OOPS(K_SYSCALL_MEMORY_ARRAY_READ(payload->ccc.data, payload->ccc.data_len, sizeof(*payload->ccc.data))); - Z_OOPS(Z_SYSCALL_MEMORY_ARRAY_WRITE(payload->ccc.data, + K_OOPS(K_SYSCALL_MEMORY_ARRAY_WRITE(payload->ccc.data, payload->ccc.data_len, sizeof(*payload->ccc.data))); } if (payload->targets.payloads != NULL) { - Z_OOPS(Z_SYSCALL_MEMORY_ARRAY_READ(payload->targets.payloads, + K_OOPS(K_SYSCALL_MEMORY_ARRAY_READ(payload->targets.payloads, payload->targets.num_targets, sizeof(*payload->targets.payloads))); - Z_OOPS(Z_SYSCALL_MEMORY_ARRAY_WRITE(payload->targets.payloads, + K_OOPS(K_SYSCALL_MEMORY_ARRAY_WRITE(payload->targets.payloads, payload->targets.num_targets, sizeof(*payload->targets.payloads))); } @@ -51,7 +51,7 @@ static uint32_t copy_i3c_msgs_and_transfer(struct i3c_device_desc *target, * that the target buffer be writable */ for (i = 0U; i < num_msgs; i++) { - Z_OOPS(Z_SYSCALL_MEMORY(copy[i].buf, copy[i].len, + K_OOPS(K_SYSCALL_MEMORY(copy[i].buf, copy[i].len, copy[i].flags & I3C_MSG_READ)); } @@ -61,18 +61,18 @@ static uint32_t copy_i3c_msgs_and_transfer(struct i3c_device_desc *target, static inline int z_vrfy_i3c_transfer(struct i3c_device_desc *target, struct i3c_msg *msgs, uint8_t num_msgs) { - Z_OOPS(Z_SYSCALL_MEMORY_READ(target, sizeof(*target))); - Z_OOPS(Z_SYSCALL_OBJ(target->bus, K_OBJ_DRIVER_I3C)); + K_OOPS(K_SYSCALL_MEMORY_READ(target, sizeof(*target))); + K_OOPS(K_SYSCALL_OBJ(target->bus, K_OBJ_DRIVER_I3C)); /* copy_msgs_and_transfer() will allocate a copy on the stack using * VLA, so ensure this won't blow the stack. Most functions defined * in i2c.h use only a handful of messages, so up to 32 messages * should be more than sufficient. */ - Z_OOPS(Z_SYSCALL_VERIFY(num_msgs >= 1 && num_msgs < 32)); + K_OOPS(K_SYSCALL_VERIFY(num_msgs >= 1 && num_msgs < 32)); /* We need to be able to read the overall array of messages */ - Z_OOPS(Z_SYSCALL_MEMORY_ARRAY_READ(msgs, num_msgs, + K_OOPS(K_SYSCALL_MEMORY_ARRAY_READ(msgs, num_msgs, sizeof(struct i3c_msg))); return copy_i3c_msgs_and_transfer((struct i3c_device_desc *)target, diff --git a/drivers/i3c/i3c_mcux.c b/drivers/i3c/i3c_mcux.c index c1ef9d9392e..d996639dab0 100644 --- a/drivers/i3c/i3c_mcux.c +++ b/drivers/i3c/i3c_mcux.c @@ -81,15 +81,15 @@ struct mcux_i3c_config { /** Interrupt configuration function. */ void (*irq_config_func)(const struct device *dev); + + /** Disable open drain high push pull */ + bool disable_open_drain_high_pp; }; struct mcux_i3c_data { /** Common I3C Driver Data */ struct i3c_driver_data common; - /** Configuration parameter to be used with HAL. */ - i3c_master_config_t ctrl_config_hal; - /** Semaphore to serialize access for applications. */ struct k_sem lock; @@ -542,9 +542,6 @@ static inline void mcux_i3c_request_daa(I3C_Type *base) /** * @brief Tell controller to start auto IBI. * - * This also waits for the controller to indicate auto IBI - * has started before returning. - * * @param base Pointer to controller registers. */ static inline void mcux_i3c_request_auto_ibi(I3C_Type *base) @@ -552,8 +549,6 @@ static inline void mcux_i3c_request_auto_ibi(I3C_Type *base) reg32_update(&base->MCTRL, I3C_MCTRL_REQUEST_MASK | I3C_MCTRL_IBIRESP_MASK | I3C_MCTRL_RDTERM_MASK, I3C_MCTRL_REQUEST_AUTO_IBI | I3C_MCTRL_IBIRESP_ACK_AUTO); - - mcux_i3c_status_wait_clear(base, I3C_MSTATUS_MCTRLDONE_MASK); } /** @@ -882,9 +877,7 @@ static int mcux_i3c_recover_bus(const struct device *dev) */ static int mcux_i3c_do_one_xfer_read(I3C_Type *base, uint8_t *buf, uint8_t buf_sz) { - int rx_count; bool completed = false; - bool overflow = false; int ret = 0; int offset = 0; @@ -911,28 +904,19 @@ static int mcux_i3c_do_one_xfer_read(I3C_Type *base, uint8_t *buf, uint8_t buf_s } /* - * Transfer data from FIFO into buffer. + * Transfer data from FIFO into buffer. Read + * in a tight loop to reduce chance of losing + * FIFO data when the i3c speed is high. */ - rx_count = mcux_i3c_fifo_rx_count_get(base); - while (rx_count > 0) { - uint8_t data = (uint8_t)base->MRDATAB; - - if (offset < buf_sz) { - buf[offset] = data; - offset += 1; - } else { - overflow = true; + while (offset < buf_sz) { + if (mcux_i3c_fifo_rx_count_get(base) == 0) { + break; } - - rx_count -= 1; + buf[offset++] = (uint8_t)base->MRDATAB; } } - if (overflow) { - ret = -EINVAL; - } else { - ret = offset; - } + ret = offset; one_xfer_read_out: return ret; @@ -1074,6 +1058,7 @@ static int mcux_i3c_transfer(const struct device *dev, I3C_Type *base = config->base; uint32_t intmask; int ret; + bool send_broadcast = true; if (target->dynamic_addr == 0U) { ret = -EINVAL; @@ -1124,12 +1109,32 @@ static int mcux_i3c_transfer(const struct device *dev, } } + /* + * Send broadcast header on first transfer or after a STOP, + * unless flag is set not to. + */ + if (!(msgs[i].flags & I3C_MSG_NBCH) && (send_broadcast)) { + ret = mcux_i3c_request_emit_start(base, I3C_BROADCAST_ADDR, + false, false, 0); + if (ret < 0) { + LOG_ERR("emit start of broadcast addr failed, error (%d)", + ret); + goto out_xfer_i3c_stop_unlock; + } + send_broadcast = false; + } + ret = mcux_i3c_do_one_xfer(base, dev_data, target->dynamic_addr, false, msgs[i].buf, msgs[i].len, is_read, emit_start, emit_stop, no_ending); if (ret < 0) { goto out_xfer_i3c_stop_unlock; } + + if (emit_stop) { + /* After a STOP, send broadcast header before next msg */ + send_broadcast = true; + } } ret = 0; @@ -1806,7 +1811,7 @@ static int mcux_i3c_configure(const struct device *dev, const struct mcux_i3c_config *dev_cfg = dev->config; struct mcux_i3c_data *dev_data = dev->data; I3C_Type *base = dev_cfg->base; - i3c_master_config_t *ctrl_config_hal = &dev_data->ctrl_config_hal; + i3c_master_config_t master_config; struct i3c_config_controller *ctrl_cfg = config; uint32_t clock_freq; int ret = 0; @@ -1835,11 +1840,24 @@ static int mcux_i3c_configure(const struct device *dev, goto out_configure; } - ctrl_config_hal->baudRate_Hz.i2cBaud = ctrl_cfg->scl.i2c; - ctrl_config_hal->baudRate_Hz.i3cPushPullBaud = ctrl_cfg->scl.i3c; + /* + * Save requested config so next config_get() call returns the + * correct values. + */ + (void)memcpy(&dev_data->common.ctrl_config, ctrl_cfg, sizeof(*ctrl_cfg)); + + I3C_MasterGetDefaultConfig(&master_config); + + master_config.baudRate_Hz.i2cBaud = ctrl_cfg->scl.i2c; + master_config.baudRate_Hz.i3cPushPullBaud = ctrl_cfg->scl.i3c; + master_config.enableOpenDrainHigh = dev_cfg->disable_open_drain_high_pp ? false : true; + + if (dev_data->clocks.i3c_od_scl_hz) { + master_config.baudRate_Hz.i3cOpenDrainBaud = dev_data->clocks.i3c_od_scl_hz; + } /* Initialize hardware */ - I3C_MasterInit(base, ctrl_config_hal, clock_freq); + I3C_MasterInit(base, &master_config, clock_freq); out_configure: return ret; @@ -1912,30 +1930,11 @@ static int mcux_i3c_init(const struct device *dev) k_sem_init(&data->lock, 1, 1); k_sem_init(&data->ibi_lock, 1, 1); - /* - * Default controller configuration to act as the primary - * and active controller. - */ - I3C_MasterGetDefaultConfig(&data->ctrl_config_hal); - - /* Set default SCL clock rate (in Hz) */ - if (ctrl_config->scl.i2c == 0U) { - ctrl_config->scl.i2c = data->ctrl_config_hal.baudRate_Hz.i2cBaud; - } - - if (ctrl_config->scl.i3c == 0U) { - ctrl_config->scl.i3c = data->ctrl_config_hal.baudRate_Hz.i3cPushPullBaud; - } - - if (data->clocks.i3c_od_scl_hz != 0U) { - data->ctrl_config_hal.baudRate_Hz.i3cOpenDrainBaud = data->clocks.i3c_od_scl_hz; - } - /* Currently can only act as primary controller. */ - data->common.ctrl_config.is_secondary = false; + ctrl_config->is_secondary = false; /* HDR mode not supported at the moment. */ - data->common.ctrl_config.supported_hdr = 0U; + ctrl_config->supported_hdr = 0U; ret = mcux_i3c_configure(dev, I3C_CONFIG_CONTROLLER, ctrl_config); if (ret != 0) { @@ -2095,6 +2094,8 @@ static const struct i3c_driver_api mcux_i3c_driver_api = { .common.dev_list.i2c = mcux_i3c_i2c_device_array_##id, \ .common.dev_list.num_i2c = ARRAY_SIZE(mcux_i3c_i2c_device_array_##id), \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(id), \ + .disable_open_drain_high_pp = \ + DT_INST_PROP_OR(id, disable_open_drain_high_pp, false), \ }; \ static struct mcux_i3c_data mcux_i3c_data_##id = { \ .clocks.i3c_od_scl_hz = DT_INST_PROP_OR(id, i3c_od_scl_hz, 0), \ diff --git a/drivers/i3c/i3c_test.c b/drivers/i3c/i3c_test.c new file mode 100644 index 00000000000..165449747d8 --- /dev/null +++ b/drivers/i3c/i3c_test.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * This is not a real I3C driver. It is used to instantiate struct + * devices for the "vnd,i3c" devicetree compatible used in test code. + */ + +#define DT_DRV_COMPAT vnd_i3c + +#include +#include +#include + +static int vnd_i3c_configure(const struct device *dev, + enum i3c_config_type type, void *config) +{ + return -ENOTSUP; +} + +static int vnd_i3c_config_get(const struct device *dev, + enum i3c_config_type type, void *config) +{ + return -ENOTSUP; +} + +static int vnd_i3c_recover_bus(const struct device *dev) +{ + return -ENOTSUP; +} + +static const struct i3c_driver_api vnd_i3c_api = { + .configure = vnd_i3c_configure, + .config_get = vnd_i3c_config_get, + .recover_bus = vnd_i3c_recover_bus, +}; + +#define VND_I3C_INIT(n) \ + DEVICE_DT_INST_DEFINE(n, NULL, NULL, NULL, NULL, \ + POST_KERNEL, \ + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ + &vnd_i3c_api); + +DT_INST_FOREACH_STATUS_OKAY(VND_I3C_INIT) diff --git a/drivers/ieee802154/Kconfig.cc1200 b/drivers/ieee802154/Kconfig.cc1200 index 0e8329ed153..de75ce5530d 100644 --- a/drivers/ieee802154/Kconfig.cc1200 +++ b/drivers/ieee802154/Kconfig.cc1200 @@ -6,7 +6,6 @@ menuconfig IEEE802154_CC1200 bool "TI CC1200 Driver support" default y depends on DT_HAS_TI_CC1200_ENABLED - select NET_L2_IEEE802154_SUB_GHZ if IEEE802154_CC1200 @@ -85,13 +84,22 @@ choice Set the RF preset you want to use. config IEEE802154_CC1200_RF_SET_0 - bool "868MHz - 50Kbps - 2-GFSK - IEEE 802.15.4g compliant - ETSI" + bool "IEEE 802.15.4g SUN MR-FSK, 863MHz band, mode #1 - channel page 9, 34 channels, 50Kbps (ETSI)" + help + This is a legacy IEEE 802.15.4g-2012 SUN MR-FSK PHY that does no + longer exist in recent standards (IEEE 802.15.4-2015+). config IEEE802154_CC1200_RF_SET_1 - bool "920MHz - 50Kbps - 2-GFSK - IEEE 802.15.4g compliant - ARIB" + bool "IEEE 802.15.4g SUN MR-FSK 920MHz band, mode #1 - channel page 9, 39 channels, 50Kbps (ARIB)" + help + This is a legacy IEEE 802.15.4g-2012 SUN MR-FSK PHY that does no + longer exist in recent standards (IEEE 802.15.4-2015+). config IEEE802154_CC1200_RF_SET_2 - bool "434MHz - 50Kbps - 2-GFSK - IEEE 802.15.4g compliant - ETSI" + bool "IEEE 802.15.4 Non-Standard 2-GFSK 433MHz band - channel page 9, 15 channels, 50Kbps (ETSI)" + help + This is a non-standard PHY similar to the IEEE 802.15.4g-2012 SUN + MR-FSK PHY but not in one of the standard bands. endchoice diff --git a/drivers/ieee802154/Kconfig.cc13xx_cc26xx b/drivers/ieee802154/Kconfig.cc13xx_cc26xx index e3ccf944abc..2414b16967f 100644 --- a/drivers/ieee802154/Kconfig.cc13xx_cc26xx +++ b/drivers/ieee802154/Kconfig.cc13xx_cc26xx @@ -59,7 +59,6 @@ menuconfig IEEE802154_CC13XX_CC26XX_SUB_GHZ bool "TI CC13xx / CC26xx IEEE 802.15.4g driver support" default y depends on DT_HAS_TI_CC13XX_CC26XX_IEEE802154_SUBGHZ_ENABLED - select NET_L2_IEEE802154_SUB_GHZ if NET_L2_IEEE802154 if IEEE802154_CC13XX_CC26XX_SUB_GHZ diff --git a/drivers/ieee802154/Kconfig.rf2xx b/drivers/ieee802154/Kconfig.rf2xx index 156cbcdcaea..80eb7f20876 100644 --- a/drivers/ieee802154/Kconfig.rf2xx +++ b/drivers/ieee802154/Kconfig.rf2xx @@ -9,7 +9,6 @@ menuconfig IEEE802154_RF2XX depends on DT_HAS_ATMEL_RF2XX_ENABLED select SPI select GPIO - select NET_L2_IEEE802154_SUB_GHZ if NET_L2_IEEE802154 if IEEE802154_RF2XX diff --git a/drivers/ieee802154/ieee802154_b91.c b/drivers/ieee802154/ieee802154_b91.c index 8361d3e8aa2..0557c533944 100644 --- a/drivers/ieee802154/ieee802154_b91.c +++ b/drivers/ieee802154/ieee802154_b91.c @@ -19,7 +19,7 @@ #include LOG_MODULE_REGISTER(LOG_MODULE_NAME); -#include +#include #include #include #if defined(CONFIG_NET_L2_OPENTHREAD) @@ -30,7 +30,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); /* B91 data structure */ -static struct b91_data data; +static struct b91_data data; /* Set filter PAN ID */ static int b91_set_pan_id(uint16_t pan_id) @@ -173,19 +173,26 @@ static void b91_update_rssi_and_lqi(struct net_pkt *pkt) } /* Prepare TX buffer */ -static void b91_set_tx_payload(uint8_t *payload, uint8_t payload_len) +static int b91_set_tx_payload(uint8_t *payload, uint8_t payload_len) { unsigned char rf_data_len; unsigned int rf_tx_dma_len; + /* See Telink SDK Dev Handbook, AN-21010600, section 21.5.2.2. */ + if (payload_len > (B91_TRX_LENGTH - B91_PAYLOAD_OFFSET - IEEE802154_FCS_LENGTH)) { + return -EINVAL; + } + rf_data_len = payload_len + 1; rf_tx_dma_len = rf_tx_packet_dma_len(rf_data_len); data.tx_buffer[0] = rf_tx_dma_len & 0xff; data.tx_buffer[1] = (rf_tx_dma_len >> 8) & 0xff; data.tx_buffer[2] = (rf_tx_dma_len >> 16) & 0xff; data.tx_buffer[3] = (rf_tx_dma_len >> 24) & 0xff; - data.tx_buffer[4] = payload_len + 2; + data.tx_buffer[4] = payload_len + IEEE802154_FCS_LENGTH; memcpy(data.tx_buffer + B91_PAYLOAD_OFFSET, payload, payload_len); + + return 0; } /* Enable ack handler */ @@ -243,7 +250,10 @@ static void b91_send_ack(uint8_t seq_num) { uint8_t ack_buf[] = { B91_ACK_TYPE, 0, seq_num }; - b91_set_tx_payload(ack_buf, sizeof(ack_buf)); + if (b91_set_tx_payload(ack_buf, sizeof(ack_buf))) { + return; + } + rf_set_txmode(); delay_us(CONFIG_IEEE802154_B91_SET_TXRX_DELAY_US); rf_tx_pkt(data.tx_buffer); @@ -403,7 +413,7 @@ static enum ieee802154_hw_caps b91_get_capabilities(const struct device *dev) { ARG_UNUSED(dev); - return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_FILTER | + return IEEE802154_HW_FCS | IEEE802154_HW_FILTER | IEEE802154_HW_TX_RX_ACK | IEEE802154_HW_RX_TX_ACK; } @@ -428,10 +438,14 @@ static int b91_set_channel(const struct device *dev, uint16_t channel) { ARG_UNUSED(dev); - if (channel < 11 || channel > 26) { + if (channel > 26) { return -EINVAL; } + if (channel < 11) { + return -ENOTSUP; + } + if (data.current_channel != channel) { data.current_channel = channel; rf_set_chn(B91_LOGIC_CHANNEL_TO_PHYSICAL(channel)); @@ -530,7 +544,10 @@ static int b91_tx(const struct device *dev, } /* prepare tx buffer */ - b91_set_tx_payload(frag->data, frag->len); + status = b91_set_tx_payload(frag->data, frag->len); + if (status) { + return status; + } /* reset semaphores */ k_sem_reset(&b91->tx_wait); @@ -585,6 +602,20 @@ static int b91_configure(const struct device *dev, return -ENOTSUP; } +/* driver-allocated attribute memory - constant across all driver instances */ +IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26); + +/* API implementation: attr_get */ +static int b91_attr_get(const struct device *dev, enum ieee802154_attr attr, + struct ieee802154_attr_value *value) +{ + ARG_UNUSED(dev); + + return ieee802154_attr_get_channel_page_and_range( + attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915, + &drv_attr.phy_supported_channels, value); +} + /* IEEE802154 driver APIs structure */ static struct ieee802154_radio_api b91_radio_api = { .iface_api.init = b91_iface_init, @@ -598,6 +629,7 @@ static struct ieee802154_radio_api b91_radio_api = { .tx = b91_tx, .ed_scan = b91_ed_scan, .configure = b91_configure, + .attr_get = b91_attr_get, }; diff --git a/drivers/ieee802154/ieee802154_cc1200.c b/drivers/ieee802154/ieee802154_cc1200.c index a5c4f37c47f..e5f8ea36670 100644 --- a/drivers/ieee802154/ieee802154_cc1200.c +++ b/drivers/ieee802154/ieee802154_cc1200.c @@ -27,7 +27,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #include #include -#include +#include #include #include @@ -446,9 +446,12 @@ static inline bool verify_crc(const struct device *dev, struct net_pkt *pkt) return true; } -static void cc1200_rx(void *arg) +static void cc1200_rx(void *p1, void *p2, void *p3) { - const struct device *dev = arg; + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; struct cc1200_context *cc1200 = dev->data; struct net_pkt *pkt; uint8_t pkt_len; @@ -519,7 +522,7 @@ static void cc1200_rx(void *arg) *******************/ static enum ieee802154_hw_caps cc1200_get_capabilities(const struct device *dev) { - return IEEE802154_HW_FCS | IEEE802154_HW_SUB_GHZ; + return IEEE802154_HW_FCS; } static int cc1200_cca(const struct device *dev) @@ -543,6 +546,15 @@ static int cc1200_cca(const struct device *dev) static int cc1200_set_channel(const struct device *dev, uint16_t channel) { struct cc1200_context *cc1200 = dev->data; + uint32_t freq; + + /* As SUN FSK provides a host of configurations with extremely different + * channel counts it doesn't make sense to validate (aka -EINVAL) a + * global upper limit on the number of supported channels on this page. + */ + if (channel > IEEE802154_CC1200_CHANNEL_LIMIT) { + return -ENOTSUP; + } /* Unlike usual 15.4 chips, cc1200 is closer to a bare metal radio modem * and thus does not provide any means to select a channel directly, but @@ -552,14 +564,16 @@ static int cc1200_set_channel(const struct device *dev, uint16_t channel) * See rf_evaluate_freq_setting() above. */ - if (atomic_get(&cc1200->rx) == 0) { - uint32_t freq = rf_evaluate_freq_setting(dev, channel); + if (atomic_get(&cc1200->rx) != 0) { + return -EIO; + } - if (!write_reg_freq(dev, freq) || - rf_calibrate(dev)) { - LOG_ERR("Could not set channel %u", channel); - return -EIO; - } + freq = rf_evaluate_freq_setting(dev, channel); + + if (!write_reg_freq(dev, freq) || + rf_calibrate(dev)) { + LOG_ERR("Could not set channel %u", channel); + return -EIO; } return 0; @@ -692,11 +706,19 @@ static int cc1200_stop(const struct device *dev) return 0; } -static uint16_t cc1200_get_channel_count(const struct device *dev) +/* driver-allocated attribute memory - constant across all driver instances as + * this driver's channel range is configured via a global KConfig setting. + */ +IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 0, IEEE802154_CC1200_CHANNEL_LIMIT); + +static int cc1200_attr_get(const struct device *dev, enum ieee802154_attr attr, + struct ieee802154_attr_value *value) { - struct cc1200_context *cc1200 = dev->data; + ARG_UNUSED(dev); - return cc1200->rf_settings->channel_limit; + return ieee802154_attr_get_channel_page_and_range( + attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_NINE_SUN_PREDEFINED, + &drv_attr.phy_supported_channels, value); } /****************** @@ -760,7 +782,7 @@ static int cc1200_init(const struct device *dev) k_thread_create(&cc1200->rx_thread, cc1200->rx_stack, CONFIG_IEEE802154_CC1200_RX_STACK_SIZE, - (k_thread_entry_t)cc1200_rx, + cc1200_rx, (void *)dev, NULL, NULL, K_PRIO_COOP(2), 0, K_NO_WAIT); k_thread_name_set(&cc1200->rx_thread, "cc1200_rx"); @@ -801,7 +823,7 @@ static struct ieee802154_radio_api cc1200_radio_api = { .tx = cc1200_tx, .start = cc1200_start, .stop = cc1200_stop, - .get_subg_channel_count = cc1200_get_channel_count, + .attr_get = cc1200_attr_get, }; NET_DEVICE_DT_INST_DEFINE(0, cc1200_init, NULL, &cc1200_context_data, diff --git a/drivers/ieee802154/ieee802154_cc1200_rf.h b/drivers/ieee802154/ieee802154_cc1200_rf.h index 8135fcad3cf..e3788d7d7c2 100644 --- a/drivers/ieee802154/ieee802154_cc1200_rf.h +++ b/drivers/ieee802154/ieee802154_cc1200_rf.h @@ -23,9 +23,10 @@ #if defined(CONFIG_IEEE802154_CC1200_RF_SET_0) +#define IEEE802154_CC1200_CHANNEL_LIMIT 33 + const struct cc1200_rf_registers_set cc1200_rf_settings = { .chan_center_freq0 = 863125, - .channel_limit = 33, .channel_spacing = 2000, /* 200 KHz */ .registers = { 0x6F, /* SYNC3 */ @@ -133,9 +134,10 @@ const struct cc1200_rf_registers_set cc1200_rf_settings = { #elif defined(CONFIG_IEEE802154_CC1200_RF_SET_1) +#define IEEE802154_CC1200_CHANNEL_LIMIT 38 + const struct cc1200_rf_registers_set cc1200_rf_settings = { .chan_center_freq0 = 920600, - .channel_limit = 38, .channel_spacing = 2000, /* 200 KHz */ .registers = { 0x6F, /* SYNC3 */ @@ -243,9 +245,10 @@ const struct cc1200_rf_registers_set cc1200_rf_settings = { #elif defined(CONFIG_IEEE802154_CC1200_RF_SET_2) +#define IEEE802154_CC1200_CHANNEL_LIMIT 14 + const struct cc1200_rf_registers_set cc1200_rf_settings = { .chan_center_freq0 = 433164, - .channel_limit = 14, .channel_spacing = 2000, /* 200 KHz */ .registers = { 0x6F, /* SYNC3 */ diff --git a/drivers/ieee802154/ieee802154_cc13xx_cc26xx.c b/drivers/ieee802154/ieee802154_cc13xx_cc26xx.c index 2068e08a475..5d5a53ed08e 100644 --- a/drivers/ieee802154/ieee802154_cc13xx_cc26xx.c +++ b/drivers/ieee802154/ieee802154_cc13xx_cc26xx.c @@ -17,7 +17,7 @@ LOG_MODULE_REGISTER(ieee802154_cc13xx_cc26xx); #include #include #include -#include +#include #include #include @@ -122,7 +122,7 @@ static void client_event_callback(RF_Handle h, RF_ClientEvent event, void *arg) static enum ieee802154_hw_caps ieee802154_cc13xx_cc26xx_get_capabilities(const struct device *dev) { - return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_FILTER | + return IEEE802154_HW_FCS | IEEE802154_HW_FILTER | IEEE802154_HW_RX_TX_ACK | IEEE802154_HW_TX_RX_ACK | IEEE802154_HW_CSMA | IEEE802154_HW_RETRANSMISSION; } @@ -155,42 +155,36 @@ static inline int ieee802154_cc13xx_cc26xx_channel_to_frequency( __ASSERT_NO_MSG(frequency != NULL); __ASSERT_NO_MSG(fractFreq != NULL); - if (channel >= IEEE802154_2_4_GHZ_CHANNEL_MIN - && channel <= IEEE802154_2_4_GHZ_CHANNEL_MAX) { - *frequency = 2405 + 5 * (channel - IEEE802154_2_4_GHZ_CHANNEL_MIN); + /* See IEEE 802.15.4-2020, section 10.1.3.3. */ + if (channel >= 11 && channel <= 26) { + *frequency = 2405 + 5 * (channel - 11); *fractFreq = 0; + return 0; } else { + /* TODO: Support sub-GHz for CC13xx rather than having separate drivers */ *frequency = 0; *fractFreq = 0; - return -EINVAL; + return channel < 11 ? -ENOTSUP : -EINVAL; } - - return 0; } static int ieee802154_cc13xx_cc26xx_set_channel(const struct device *dev, uint16_t channel) { - int r; + int ret; RF_CmdHandle cmd_handle; RF_EventMask reason; uint16_t freq, fract; struct ieee802154_cc13xx_cc26xx_data *drv_data = dev->data; - /* TODO Support sub-GHz for CC13xx */ - if (channel < 11 || channel > 26) { - return -EINVAL; - } - - r = ieee802154_cc13xx_cc26xx_channel_to_frequency( - channel, &freq, &fract); - if (r < 0) { - return -EINVAL; + ret = ieee802154_cc13xx_cc26xx_channel_to_frequency(channel, &freq, &fract); + if (ret < 0) { + return ret; } /* Abort FG and BG processes */ if (ieee802154_cc13xx_cc26xx_stop(dev) < 0) { - r = -EIO; + ret = -EIO; goto out; } @@ -205,7 +199,7 @@ static int ieee802154_cc13xx_cc26xx_set_channel(const struct device *dev, RF_PriorityNormal, NULL, 0); if (reason != RF_EventLastCmdDone) { LOG_ERR("Failed to set frequency: 0x%" PRIx64, reason); - r = -EIO; + ret = -EIO; goto out; } @@ -217,15 +211,15 @@ static int ieee802154_cc13xx_cc26xx_set_channel(const struct device *dev, cmd_ieee_rx_callback, RF_EventRxEntryDone); if (cmd_handle < 0) { LOG_ERR("Failed to post RX command (%d)", cmd_handle); - r = -EIO; + ret = -EIO; goto out; } - r = 0; + ret = 0; out: k_mutex_unlock(&drv_data->tx_mutex); - return r; + return ret; } /* TODO remove when rf driver bugfix is pulled in */ @@ -514,6 +508,18 @@ ieee802154_cc13xx_cc26xx_configure(const struct device *dev, return -ENOTSUP; } +/* driver-allocated attribute memory - constant across all driver instances */ +IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26); + +static int ieee802154_cc13xx_cc26xx_attr_get(const struct device *dev, enum ieee802154_attr attr, + struct ieee802154_attr_value *value) +{ + ARG_UNUSED(dev); + + return ieee802154_attr_get_channel_page_and_range( + attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915, + &drv_attr.phy_supported_channels, value); +} static void ieee802154_cc13xx_cc26xx_data_init(const struct device *dev) { @@ -576,6 +582,7 @@ static struct ieee802154_radio_api ieee802154_cc13xx_cc26xx_radio_api = { .start = ieee802154_cc13xx_cc26xx_start, .stop = ieee802154_cc13xx_cc26xx_stop_if, .configure = ieee802154_cc13xx_cc26xx_configure, + .attr_get = ieee802154_cc13xx_cc26xx_attr_get, }; /** RF patches to use (note: RF core keeps a pointer to this, so no stack). */ diff --git a/drivers/ieee802154/ieee802154_cc13xx_cc26xx.h b/drivers/ieee802154/ieee802154_cc13xx_cc26xx.h index ac3cc29a630..185e445a175 100644 --- a/drivers/ieee802154/ieee802154_cc13xx_cc26xx.h +++ b/drivers/ieee802154/ieee802154_cc13xx_cc26xx.h @@ -23,7 +23,7 @@ /* For O-QPSK the physical and MAC timing symbol rates are the same, see section 12.3.3. */ #define IEEE802154_2450MHZ_OQPSK_SYMBOLS_PER_SECOND \ - IEEE802154_PHY_SYMBOLS_PER_SECOND(IEEE802154_PHY_OQPSK_2450MHZ_SYMBOL_PERIOD_US) + IEEE802154_PHY_SYMBOLS_PER_SECOND(IEEE802154_PHY_OQPSK_780_TO_2450MHZ_SYMBOL_PERIOD_NS) /* PHY PIB attribute phyCcaMode - CCA Mode 3: Carrier sense with energy above threshold, see * section 11.3, table 11-2 and section 10.2.8 diff --git a/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c b/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c index e06ab05207c..ea626908d16 100644 --- a/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c +++ b/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c @@ -10,16 +10,17 @@ #include LOG_MODULE_REGISTER(ieee802154_cc13xx_cc26xx_subg); -#include #include -#include -#include +#include + +#include #include +#include #include -#include -#include -#include +#include +#include #include +#include #include #include @@ -32,18 +33,8 @@ LOG_MODULE_REGISTER(ieee802154_cc13xx_cc26xx_subg); #include "ieee802154_cc13xx_cc26xx_subg.h" -static void ieee802154_cc13xx_cc26xx_subg_rx_done( - struct ieee802154_cc13xx_cc26xx_subg_data *drv_data); -static void ieee802154_cc13xx_cc26xx_subg_data_init( - struct ieee802154_cc13xx_cc26xx_subg_data *drv_data); -static int ieee802154_cc13xx_cc26xx_subg_stop( - const struct device *dev); -static int ieee802154_cc13xx_cc26xx_subg_stop_if( - const struct device *dev); -static int ieee802154_cc13xx_cc26xx_subg_rx( - const struct device *dev); -static void ieee802154_cc13xx_cc26xx_subg_setup_rx_buffers( - struct ieee802154_cc13xx_cc26xx_subg_data *drv_data); +static int drv_start_rx(const struct device *dev); +static int drv_stop_rx(const struct device *dev); #ifndef CMD_PROP_RADIO_DIV_SETUP_PA /* workaround for older HAL TI SDK (less than 4.40) */ @@ -91,7 +82,7 @@ static uint32_t ieee802154_cc13xx_overrides_sub_ghz[] = { }; /* Radio values for CC13X2P */ -#elif defined(CONFIG_SOC_CC1352P) +#elif defined(CONFIG_SOC_CC1352P) || defined(CONFIG_SOC_CC1352P7) /* CC1352P overrides from SmartRF Studio (200kbps, 50kHz deviation, 2-GFSK, 311.8kHz Rx BW) */ static uint32_t ieee802154_cc13xx_overrides_sub_ghz[] = { /* Tx: Configure PA ramp time, PACTL2.RC=0x3 (in ADI0, set PACTL2[4:3]=0x1) */ @@ -150,7 +141,7 @@ static uint32_t rf_prop_overrides_tx_20[] = { #if defined(CONFIG_SOC_CC1352R) static volatile rfc_CMD_PROP_RADIO_DIV_SETUP_t ieee802154_cc13xx_subg_radio_div_setup = { .commandNo = CMD_PROP_RADIO_DIV_SETUP, -#elif defined(CONFIG_SOC_CC1352P) +#elif defined(CONFIG_SOC_CC1352P) || defined(CONFIG_SOC_CC1352P7) static volatile rfc_CMD_PROP_RADIO_DIV_SETUP_PA_t ieee802154_cc13xx_subg_radio_div_setup = { .commandNo = CMD_PROP_RADIO_DIV_SETUP_PA, #endif /* CONFIG_SOC_CC1352x */ @@ -216,7 +207,7 @@ static const RF_TxPowerTable_Entry ieee802154_cc13xx_subg_power_table[] = { #endif RF_TxPowerTable_TERMINATION_ENTRY }; -#elif defined(CONFIG_SOC_CC1352P) +#elif defined(CONFIG_SOC_CC1352P) || defined(CONFIG_SOC_CC1352P7) /* Sub GHz power table */ static const RF_TxPowerTable_Entry ieee802154_cc13xx_subg_power_table[] = { { -20, RF_TxPowerTable_DEFAULT_PA_ENTRY(0, 3, 0, 2) }, @@ -250,38 +241,39 @@ static const RF_TxPowerTable_Entry ieee802154_cc13xx_subg_power_table[] = { }; #endif /* CONFIG_SOC_CC1352x power table */ +#define LOCK_TIMEOUT (k_is_in_isr() ? K_NO_WAIT : K_FOREVER) + /** RF patches to use (note: RF core keeps a pointer to this, so no stack). */ static RF_Mode rf_mode = { .rfMode = RF_MODE_MULTIPLE, .cpePatchFxn = &rf_patch_cpe_multi_protocol, }; - -static inline int ieee802154_cc13xx_cc26xx_subg_channel_to_frequency( - uint16_t channel, uint16_t *frequency, uint16_t *fractFreq) +static inline int drv_channel_frequency(uint16_t channel, uint16_t *frequency, uint16_t *fractFreq) { __ASSERT_NO_MSG(frequency != NULL); __ASSERT_NO_MSG(fractFreq != NULL); - /* See IEEE 802.15.4, section 10.1.3.3. */ - if (channel == IEEE802154_SUB_GHZ_CHANNEL_MIN) { + /* See IEEE 802.15.4-2020, section 10.1.3.3. */ + if (channel == 0) { *frequency = 868; /* * uint16_t fractional part of 868.3 MHz * equivalent to (0.3 * 1000 * BIT(16)) / 1000, rounded up */ *fractFreq = 0x4ccd; - } else if (channel <= IEEE802154_SUB_GHZ_CHANNEL_MAX) { + } else if (channel <= 10) { *frequency = 906 + 2 * (channel - 1); *fractFreq = 0; } else { *frequency = 0; *fractFreq = 0; - return -EINVAL; + return channel <= 26 ? -ENOTSUP : -EINVAL; } - /* TODO: This incorrectly mixes up legacy O-QPSK SubGHz PHY channel page zero - * frequency calculation with SUN FSK operating mode #3 PHY radio settings. + /* TODO: This incorrectly mixes up legacy BPSK SubGHz PHY channel page + * zero frequency calculation with SUN FSK operating mode #3 PHY radio + * settings. * * The correct channel frequency calculation for this PHY is on channel page 9, * using the formula ChanCenterFreq = ChanCenterFreq0 + channel * ChanSpacing. @@ -299,14 +291,22 @@ static inline int ieee802154_cc13xx_cc26xx_subg_channel_to_frequency( * Making derived MAC/PHY PIB attributes available to L2 requires an additional * attribute getter, see * https://github.com/zephyrproject-rtos/zephyr/issues/50336#issuecomment-1251122582. + * + * We resolve this bug right now by basing all timing on SUN FSK + * parameters while maintaining the channel/channel page assignment of a + * BPSK PHY. */ return 0; } -static inline bool is_subghz(uint16_t channel) +static inline int drv_power_down(const struct device *const dev) { - return (channel <= IEEE802154_SUB_GHZ_CHANNEL_MAX); + struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data; + + (void)RF_yield(drv_data->rf_handle); + + return 0; } static void cmd_prop_tx_adv_callback(RF_Handle h, RF_CmdHandle ch, @@ -316,10 +316,83 @@ static void cmd_prop_tx_adv_callback(RF_Handle h, RF_CmdHandle ch, struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data; RF_Op *op = RF_getCmdOp(h, ch); + /* No need for locking as the RX status is volatile and there's no race. */ LOG_DBG("ch: %u cmd: %04x cs st: %04x tx st: %04x e: 0x%" PRIx64, ch, op->commandNo, op->status, drv_data->cmd_prop_tx_adv.status, e); } +static void drv_rx_done(struct ieee802154_cc13xx_cc26xx_subg_data *drv_data) +{ + int8_t rssi, status; + struct net_pkt *pkt; + uint8_t len; + uint8_t *sdu; + + /* No need for locking as only immutable data is accessed from drv_data. + * The rx queue itself (entries and data) are managed and protected + * internally by TI's RF driver. + */ + + for (int i = 0; i < CC13XX_CC26XX_NUM_RX_BUF; i++) { + if (drv_data->rx_entry[i].status == DATA_ENTRY_FINISHED) { + len = drv_data->rx_data[i][0]; + sdu = drv_data->rx_data[i] + 1; + status = drv_data->rx_data[i][len--]; + rssi = drv_data->rx_data[i][len--]; + + /* TODO: Configure firmware to include CRC in raw mode. */ + if (IS_ENABLED(CONFIG_IEEE802154_RAW_MODE) && len > 0) { + /* append CRC-16/CCITT */ + uint16_t crc = 0; + + crc = crc16_ccitt(0, sdu, len); + sdu[len++] = crc; + sdu[len++] = crc >> 8; + } + + LOG_DBG("Received: len = %u, rssi = %d status = %u", + len, rssi, status); + + pkt = net_pkt_rx_alloc_with_buffer( + drv_data->iface, len, AF_UNSPEC, 0, K_NO_WAIT); + if (!pkt) { + LOG_WRN("Cannot allocate packet"); + continue; + } + + if (net_pkt_write(pkt, sdu, len)) { + LOG_WRN("Cannot write packet"); + net_pkt_unref(pkt); + continue; + } + + drv_data->rx_entry[i].status = DATA_ENTRY_PENDING; + + /* TODO: Determine LQI in PROP mode. */ + net_pkt_set_ieee802154_lqi(pkt, 0xff); + net_pkt_set_ieee802154_rssi_dbm(pkt, + rssi == CC13XX_CC26XX_INVALID_RSSI + ? IEEE802154_MAC_RSSI_DBM_UNDEFINED + : rssi); + + if (ieee802154_handle_ack(drv_data->iface, pkt) == NET_OK) { + net_pkt_unref(pkt); + continue; + } + + if (net_recv_data(drv_data->iface, pkt)) { + LOG_WRN("Packet dropped"); + net_pkt_unref(pkt); + } + + } else if (drv_data->rx_entry[i].status == + DATA_ENTRY_UNFINISHED) { + LOG_WRN("Frame not finished"); + drv_data->rx_entry[i].status = DATA_ENTRY_PENDING; + } + } +} + static void cmd_prop_rx_adv_callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e) { @@ -331,15 +404,21 @@ static void cmd_prop_rx_adv_callback(RF_Handle h, RF_CmdHandle ch, op->commandNo, op->status, e); if (e & RF_EventRxEntryDone) { - ieee802154_cc13xx_cc26xx_subg_rx_done(drv_data); + drv_rx_done(drv_data); } if (op->status == PROP_ERROR_RXBUF || op->status == PROP_ERROR_RXFULL || op->status == PROP_ERROR_RXOVF) { LOG_DBG("RX Error %x", op->status); + /* Restart RX */ - (void)ieee802154_cc13xx_cc26xx_subg_rx(dev); + if (k_sem_take(&drv_data->lock, LOCK_TIMEOUT)) { + return; + } + + (void)drv_start_rx(dev); + k_sem_give(&drv_data->lock); } } @@ -348,7 +427,7 @@ static void client_error_callback(RF_Handle h, RF_CmdHandle ch, { ARG_UNUSED(h); ARG_UNUSED(ch); - LOG_DBG("e: 0x%" PRIx64, e); + LOG_ERR("client error: 0x%" PRIx64, e); } static void client_event_callback(RF_Handle h, RF_ClientEvent event, @@ -362,26 +441,34 @@ static enum ieee802154_hw_caps ieee802154_cc13xx_cc26xx_subg_get_capabilities(const struct device *dev) { /* TODO: enable IEEE802154_HW_FILTER */ - return IEEE802154_HW_FCS | IEEE802154_HW_SUB_GHZ; + return IEEE802154_HW_FCS; } static int ieee802154_cc13xx_cc26xx_subg_cca(const struct device *dev) { struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data; + bool was_rx_on = false; RF_EventMask events; - bool was_rx_on; int ret; + if (k_sem_take(&drv_data->lock, LOCK_TIMEOUT)) { + return -EWOULDBLOCK; + } + + if (!drv_data->is_up) { + ret = -ENETDOWN; + goto out; + } + drv_data->cmd_prop_cs.status = IDLE; - drv_data->cmd_prop_cs.pNextOp = NULL; - drv_data->cmd_prop_cs.condition.rule = COND_NEVER; was_rx_on = drv_data->cmd_prop_rx_adv.status == ACTIVE; - - ret = ieee802154_cc13xx_cc26xx_subg_stop(dev); - if (ret < 0) { - ret = -EIO; - goto out; + if (was_rx_on) { + ret = drv_stop_rx(dev); + if (ret) { + ret = -EIO; + goto out; + } } events = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_prop_cs, RF_PriorityNormal, @@ -398,7 +485,8 @@ static int ieee802154_cc13xx_cc26xx_subg_cca(const struct device *dev) * this usually means we want to TX directly after * and cannot afford any extra latency. */ - return 0; + ret = 0; + break; case PROP_DONE_BUSY: case PROP_DONE_BUSYTIMEOUT: ret = -EBUSY; @@ -414,19 +502,33 @@ static int ieee802154_cc13xx_cc26xx_subg_cca(const struct device *dev) * and want to be able to receive packets in * the meantime. */ - if (was_rx_on) { - ieee802154_cc13xx_cc26xx_subg_rx(dev); + if (ret && was_rx_on) { + drv_start_rx(dev); } + + k_sem_give(&drv_data->lock); return ret; } -static int ieee802154_cc13xx_cc26xx_subg_rx(const struct device *dev) +/* This method must be called with the lock held. */ +static int drv_start_rx(const struct device *dev) { struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data; RF_CmdHandle cmd_handle; - /* Set all RX entries to empty */ - ieee802154_cc13xx_cc26xx_subg_setup_rx_buffers(drv_data); + if (drv_data->cmd_prop_rx_adv.status == ACTIVE) { + return -EALREADY; + } + +#ifdef CONFIG_ASSERT + if (CONFIG_ASSERT_LEVEL > 0) { + /* ensure that all RX buffers are initialized and pending. */ + for (int i = 0; i < CC13XX_CC26XX_NUM_RX_BUF; i++) { + __ASSERT_NO_MSG(drv_data->rx_entry[i].pNextEntry != NULL); + __ASSERT_NO_MSG(drv_data->rx_entry[i].status == DATA_ENTRY_PENDING); + } + } +#endif drv_data->cmd_prop_rx_adv.status = IDLE; cmd_handle = RF_postCmd(drv_data->rf_handle, @@ -437,57 +539,80 @@ static int ieee802154_cc13xx_cc26xx_subg_rx(const struct device *dev) return -EIO; } + drv_data->rx_cmd_handle = cmd_handle; + return 0; } +/* This method must be called with the lock held. */ +static int drv_stop_rx(const struct device *dev) +{ + struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data; + RF_Stat status; + + if (drv_data->cmd_prop_rx_adv.status != ACTIVE) { + return -EALREADY; + } + + /* Stop RX without aborting ongoing reception of packets. */ + status = RF_cancelCmd(drv_data->rf_handle, drv_data->rx_cmd_handle, RF_ABORT_GRACEFULLY); + switch (status) { + case RF_StatSuccess: + case RF_StatCmdEnded: + return 0; + default: + return -EIO; + } +} + static int ieee802154_cc13xx_cc26xx_subg_set_channel( const struct device *dev, uint16_t channel) { struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data; - RF_EventMask events; uint16_t freq, fract; + RF_EventMask events; bool was_rx_on; int ret; - if (!is_subghz(channel)) { - return -EINVAL; + ret = drv_channel_frequency(channel, &freq, &fract); + if (ret < 0) { + return ret; } - ret = ieee802154_cc13xx_cc26xx_subg_channel_to_frequency(channel, &freq, &fract); - if (ret < 0) { - return -EINVAL; + if (k_sem_take(&drv_data->lock, LOCK_TIMEOUT)) { + return -EWOULDBLOCK; } was_rx_on = drv_data->cmd_prop_rx_adv.status == ACTIVE; - - /* Abort FG and BG processes */ - ret = ieee802154_cc13xx_cc26xx_subg_stop(dev); - if (ret) { - ret = -EIO; - goto out; + if (was_rx_on) { + ret = drv_stop_rx(dev); + if (ret) { + ret = -EIO; + goto out; + } } - /* Block TX while changing channel */ - k_mutex_lock(&drv_data->tx_mutex, K_FOREVER); - /* Set the frequency */ drv_data->cmd_fs.status = IDLE; drv_data->cmd_fs.frequency = freq; drv_data->cmd_fs.fractFreq = fract; events = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_fs, RF_PriorityNormal, NULL, 0); - if (events != RF_EventLastCmdDone) { + if (events != RF_EventLastCmdDone || drv_data->cmd_fs.status != DONE_OK) { LOG_DBG("Failed to set frequency: 0x%" PRIx64, events); ret = -EIO; } - k_mutex_unlock(&drv_data->tx_mutex); - out: - /* Re-enable RX if we found it on initially. */ if (was_rx_on) { - ieee802154_cc13xx_cc26xx_subg_rx(dev); + /* Re-enable RX if we found it on initially. */ + (void)drv_start_rx(dev); + } else if (!drv_data->is_up) { + ret = drv_power_down(dev); } + + k_sem_give(&drv_data->lock); + return ret; } @@ -507,23 +632,35 @@ static int ieee802154_cc13xx_cc26xx_subg_set_txpower( const struct device *dev, int16_t dbm) { struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data; + RF_TxPowerTable_Value power_table_value; RF_Stat status; + int ret = 0; - RF_TxPowerTable_Value power_table_value = RF_TxPowerTable_findValue( + power_table_value = RF_TxPowerTable_findValue( (RF_TxPowerTable_Entry *)ieee802154_cc13xx_subg_power_table, dbm); - if (power_table_value.rawValue == RF_TxPowerTable_INVALID_VALUE) { LOG_DBG("RF_TxPowerTable_findValue() failed"); return -EINVAL; } + /* No need for locking: rf_handle is immutable after initialization. */ status = RF_setTxPower(drv_data->rf_handle, power_table_value); if (status != RF_StatSuccess) { LOG_DBG("RF_setTxPower() failed: %d", status); return -EIO; } - return 0; + if (k_sem_take(&drv_data->lock, LOCK_TIMEOUT)) { + return -EWOULDBLOCK; + } + + if (!drv_data->is_up) { + ret = drv_power_down(dev); + } + + k_sem_give(&drv_data->lock); + + return ret; } /* See IEEE 802.15.4 section 6.7.1 and TRM section 25.5.4.3 */ @@ -534,42 +671,45 @@ static int ieee802154_cc13xx_cc26xx_subg_tx(const struct device *dev, { struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data; RF_EventMask events; - int ret; + int ret = 0; + + if (buf->len > (CC13XX_CC26XX_TX_BUF_SIZE - IEEE802154_PHY_SUN_FSK_PHR_LEN)) { + return -EINVAL; + } if (mode != IEEE802154_TX_MODE_DIRECT) { /* For backwards compatibility we only log an error but do not bail. */ NET_ERR("TX mode %d not supported - sending directly instead.", mode); } - k_mutex_lock(&drv_data->tx_mutex, K_FOREVER); + if (k_sem_take(&drv_data->lock, K_FOREVER)) { + return -EIO; + } - /* Prepend data with the SUN FSK PHY header, - * see IEEE 802.15.4, section 19.2.4. - */ + if (!drv_data->is_up) { + ret = -ENETDOWN; + goto out; + } + + if (drv_data->cmd_prop_rx_adv.status == ACTIVE) { + ret = drv_stop_rx(dev); + if (ret) { + ret = -EIO; + goto out; + } + } + + /* Complete the SUN FSK PHY header, see IEEE 802.15.4, section 19.2.4. */ drv_data->tx_data[0] = buf->len + IEEE802154_FCS_LENGTH; - drv_data->tx_data[1] = 0; - drv_data->tx_data[1] |= BIT(3); /* FCS Type: 2-octet FCS */ - drv_data->tx_data[1] |= BIT(4); /* DW: Enable Data Whitening */ - /* TODO: Zero-copy TX, see discussion in #49775. */ - __ASSERT_NO_MSG(buf->len + IEEE802154_PHY_SUN_FSK_PHR_LEN <= CC13XX_CC26XX_TX_BUF_SIZE); + /* Set TX data + * + * TODO: Zero-copy TX, see discussion in #49775. + */ memcpy(&drv_data->tx_data[IEEE802154_PHY_SUN_FSK_PHR_LEN], buf->data, buf->len); - - /* Set TX data */ drv_data->cmd_prop_tx_adv.pktLen = buf->len + IEEE802154_PHY_SUN_FSK_PHR_LEN; - drv_data->cmd_prop_tx_adv.pPkt = drv_data->tx_data; - /* Reset command status */ drv_data->cmd_prop_tx_adv.status = IDLE; - drv_data->cmd_prop_tx_adv.pNextOp = NULL; - - /* Abort FG and BG processes */ - ret = ieee802154_cc13xx_cc26xx_subg_stop(dev); - if (ret < 0) { - ret = -EIO; - goto out; - } - events = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_prop_tx_adv, RF_PriorityNormal, cmd_prop_tx_adv_callback, RF_EventLastCmdDone); if ((events & RF_EventLastCmdDone) == 0) { @@ -581,93 +721,61 @@ static int ieee802154_cc13xx_cc26xx_subg_tx(const struct device *dev, if (drv_data->cmd_prop_tx_adv.status != PROP_DONE_OK) { LOG_DBG("Transmit failed (0x%x)", drv_data->cmd_prop_tx_adv.status); ret = -EIO; - goto out; } out: - (void)ieee802154_cc13xx_cc26xx_subg_rx(dev); - k_mutex_unlock(&drv_data->tx_mutex); + (void)drv_start_rx(dev); + + k_sem_give(&drv_data->lock); return ret; } -static void ieee802154_cc13xx_cc26xx_subg_rx_done( - struct ieee802154_cc13xx_cc26xx_subg_data *drv_data) -{ - struct net_pkt *pkt; - uint8_t len; - int8_t rssi, status; - uint8_t *sdu; - - for (int i = 0; i < CC13XX_CC26XX_NUM_RX_BUF; i++) { - if (drv_data->rx_entry[i].status == DATA_ENTRY_FINISHED) { - len = drv_data->rx_data[i][0]; - sdu = drv_data->rx_data[i] + 1; - status = drv_data->rx_data[i][len--]; - rssi = drv_data->rx_data[i][len--]; - - /* TODO: Configure firmware to include CRC in raw mode. */ - if (IS_ENABLED(CONFIG_IEEE802154_RAW_MODE) && len > 0) { - /* append CRC-16/CCITT */ - uint16_t crc = 0; +/* driver-allocated attribute memory - constant across all driver instances */ +IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 0, 10); - crc = crc16_ccitt(0, sdu, len); - sdu[len++] = crc; - sdu[len++] = crc >> 8; - } - - LOG_DBG("Received: len = %u, rssi = %d status = %u", - len, rssi, status); - - pkt = net_pkt_rx_alloc_with_buffer( - drv_data->iface, len, AF_UNSPEC, 0, K_NO_WAIT); - if (!pkt) { - LOG_WRN("Cannot allocate packet"); - continue; - } - - if (net_pkt_write(pkt, sdu, len)) { - LOG_WRN("Cannot write packet"); - net_pkt_unref(pkt); - continue; - } +static int ieee802154_cc13xx_cc26xx_subg_attr_get(const struct device *dev, + enum ieee802154_attr attr, + struct ieee802154_attr_value *value) +{ + ARG_UNUSED(dev); - drv_data->rx_entry[i].status = DATA_ENTRY_PENDING; + /* We claim channel page nine with channel page zero channel range to + * ensure SUN-FSK timing, see the TODO in + * ieee802154_cc13xx_cc26xx_subg_channel_to_frequency(). + */ + return ieee802154_attr_get_channel_page_and_range( + attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_NINE_SUN_PREDEFINED, + &drv_attr.phy_supported_channels, value); +} - /* TODO: Determine LQI in PROP mode. */ - net_pkt_set_ieee802154_lqi(pkt, 0xff); - net_pkt_set_ieee802154_rssi_dbm(pkt, - rssi == CC13XX_CC26XX_INVALID_RSSI - ? IEEE802154_MAC_RSSI_DBM_UNDEFINED - : rssi); +static int ieee802154_cc13xx_cc26xx_subg_start(const struct device *dev) +{ + struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data; + int ret; - if (ieee802154_handle_ack(drv_data->iface, pkt) == NET_OK) { - net_pkt_unref(pkt); - continue; - } + if (k_sem_take(&drv_data->lock, LOCK_TIMEOUT)) { + return -EIO; + } - if (net_recv_data(drv_data->iface, pkt)) { - LOG_WRN("Packet dropped"); - net_pkt_unref(pkt); - } + if (drv_data->is_up) { + ret = -EALREADY; + goto out; + } - } else if (drv_data->rx_entry[i].status == - DATA_ENTRY_UNFINISHED) { - LOG_WRN("Frame not finished"); - drv_data->rx_entry[i].status = DATA_ENTRY_PENDING; - } + ret = drv_start_rx(dev); + if (ret) { + goto out; } -} -static int ieee802154_cc13xx_cc26xx_subg_start(const struct device *dev) -{ - /* Start RX */ - return ieee802154_cc13xx_cc26xx_subg_rx(dev); + drv_data->is_up = true; + +out: + k_sem_give(&drv_data->lock); + return ret; } -/** - * Flushes / stops all radio commands in RF queue. - */ -static int ieee802154_cc13xx_cc26xx_subg_stop(const struct device *dev) +/* Aborts all radio commands in the RF queue. Requires the lock to be held. */ +static int drv_abort_commands(const struct device *dev) { struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data; RF_Stat status; @@ -693,14 +801,30 @@ static int ieee802154_cc13xx_cc26xx_subg_stop_if(const struct device *dev) struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data; int ret; - ret = ieee802154_cc13xx_cc26xx_subg_stop(dev); - if (ret < 0) { - return ret; + if (k_sem_take(&drv_data->lock, LOCK_TIMEOUT)) { + return -EIO; } - /* power down radio */ - RF_yield(drv_data->rf_handle); - return 0; + if (!drv_data->is_up) { + ret = -EALREADY; + goto out; + } + + ret = drv_abort_commands(dev); + if (ret) { + goto out; + } + + ret = drv_power_down(dev); + if (ret) { + goto out; + } + + drv_data->is_up = false; + + out: + k_sem_give(&drv_data->lock); + return ret; } static int @@ -711,21 +835,13 @@ ieee802154_cc13xx_cc26xx_subg_configure(const struct device *dev, return -ENOTSUP; } -uint16_t ieee802154_cc13xx_cc26xx_subg_get_subg_channel_count( - const struct device *dev) +static void drv_setup_rx_buffers(struct ieee802154_cc13xx_cc26xx_subg_data *drv_data) { - ARG_UNUSED(dev); - - /* IEEE 802.15.4 SubGHz channels range from 0 to 10 for channel page zero. */ - return 11; -} + /* No need to zero buffers as they are zeroed on initialization and no + * need for locking as initialization is done with exclusive access. + */ -static void ieee802154_cc13xx_cc26xx_subg_setup_rx_buffers( - struct ieee802154_cc13xx_cc26xx_subg_data *drv_data) -{ for (size_t i = 0; i < CC13XX_CC26XX_NUM_RX_BUF; ++i) { - memset(&drv_data->rx_entry[i], 0, sizeof(drv_data->rx_entry[i])); - if (i < CC13XX_CC26XX_NUM_RX_BUF - 1) { drv_data->rx_entry[i].pNextEntry = (uint8_t *) &drv_data->rx_entry[i + 1]; @@ -744,8 +860,20 @@ static void ieee802154_cc13xx_cc26xx_subg_setup_rx_buffers( drv_data->rx_queue.pLastEntry = NULL; } -static void ieee802154_cc13xx_cc26xx_subg_data_init( - struct ieee802154_cc13xx_cc26xx_subg_data *drv_data) +static void drv_setup_tx_buffer(struct ieee802154_cc13xx_cc26xx_subg_data *drv_data) +{ + /* No need to zero buffers as they are zeroed on initialization and no + * need for locking as initialization is done with exclusive access. + */ + + /* Part of the SUN FSK PHY header, see IEEE 802.15.4, section 19.2.4. */ + drv_data->tx_data[1] = BIT(3) | /* FCS Type: 2-octet FCS */ + BIT(4); /* DW: Enable Data Whitening */ + + drv_data->cmd_prop_tx_adv.pPkt = drv_data->tx_data; +} + +static void drv_data_init(struct ieee802154_cc13xx_cc26xx_subg_data *drv_data) { uint8_t *mac; @@ -760,9 +888,12 @@ static void ieee802154_cc13xx_cc26xx_subg_data_init( sys_memcpy_swap(&drv_data->mac, mac, sizeof(drv_data->mac)); /* Setup circular RX queue (TRM 25.3.2.7) */ - ieee802154_cc13xx_cc26xx_subg_setup_rx_buffers(drv_data); + drv_setup_rx_buffers(drv_data); + + /* Setup TX buffer (TRM 25.10.2.1.1, table 25-171) */ + drv_setup_tx_buffer(drv_data); - k_mutex_init(&drv_data->tx_mutex); + k_sem_init(&drv_data->lock, 1, 1); } static void ieee802154_cc13xx_cc26xx_subg_iface_init(struct net_if *iface) @@ -791,18 +922,20 @@ static struct ieee802154_radio_api .start = ieee802154_cc13xx_cc26xx_subg_start, .stop = ieee802154_cc13xx_cc26xx_subg_stop_if, .configure = ieee802154_cc13xx_cc26xx_subg_configure, - .get_subg_channel_count = - ieee802154_cc13xx_cc26xx_subg_get_subg_channel_count, + .attr_get = ieee802154_cc13xx_cc26xx_subg_attr_get, }; static int ieee802154_cc13xx_cc26xx_subg_init(const struct device *dev) { + struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data; + uint16_t freq, fract; RF_Params rf_params; RF_EventMask events; - struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data; + + /* No need for locking - initialization is exclusive. */ /* Initialize driver data */ - ieee802154_cc13xx_cc26xx_subg_data_init(drv_data); + drv_data_init(drv_data); /* Setup radio */ RF_Params_init(&rf_params); @@ -817,26 +950,21 @@ static int ieee802154_cc13xx_cc26xx_subg_init(const struct device *dev) return -EIO; } - /* - * Run CMD_FS with frequency 0 to ensure RF_currClient is not NULL. - * RF_currClient is a static variable in the TI RF Driver library. - * If this is not done, then even CMD_ABORT fails. + /* Run CMD_FS for channel 0 to place a valid CMD_FS command in the + * driver's internal state which it requires for proper operation. */ + (void)drv_channel_frequency(0, &freq, &fract); drv_data->cmd_fs.status = IDLE; - drv_data->cmd_fs.pNextOp = NULL; - drv_data->cmd_fs.condition.rule = COND_NEVER; - drv_data->cmd_fs.synthConf.bTxMode = false; - drv_data->cmd_fs.frequency = 0; - drv_data->cmd_fs.fractFreq = 0; - + drv_data->cmd_fs.frequency = freq; + drv_data->cmd_fs.fractFreq = fract; events = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_fs, RF_PriorityNormal, NULL, 0); - if (events != RF_EventLastCmdDone) { + if (events != RF_EventLastCmdDone || drv_data->cmd_fs.status != DONE_OK) { LOG_ERR("Failed to set frequency: 0x%" PRIx64, events); return -EIO; } - return 0; + return drv_power_down(dev); } static struct ieee802154_cc13xx_cc26xx_subg_data ieee802154_cc13xx_cc26xx_subg_data = { @@ -879,12 +1007,13 @@ static struct ieee802154_cc13xx_cc26xx_subg_data ieee802154_cc13xx_cc26xx_subg_d .cmd_prop_rx_adv_output, }, - /* TODO: Support correlation CCA modes, see section 10.2.8. */ .cmd_prop_cs = { .commandNo = CMD_PROP_CS, .condition.rule = COND_NEVER, .csConf = { - /* CCA Mode 1: Energy above threshold, see section 10.2.8. */ + /* CCA Mode 1: Energy above threshold, see section 10.2.8. + * CC13/26xx SubG does not support correlation mode. + */ .bEnaRssi = true, /* Abort as soon as any energy above the ED threshold is detected. */ .busyOp = true, @@ -896,7 +1025,9 @@ static struct ieee802154_cc13xx_cc26xx_subg_data ieee802154_cc13xx_cc26xx_subg_d /* see IEEE 802.15.4, section 11.3, table 11-1 and section 10.2.8 */ .csEndTime = RF_convertUsToRatTicks( IEEE802154_PHY_A_CCA_TIME * - IEEE802154_PHY_SUN_FSK_863MHZ_915MHZ_SYMBOL_PERIOD_US), + (IEEE802154_PHY_SUN_FSK_863MHZ_915MHZ_SYMBOL_PERIOD_NS / + NSEC_PER_USEC) + ), }, .cmd_prop_tx_adv = { @@ -907,7 +1038,8 @@ static struct ieee802154_cc13xx_cc26xx_subg_data ieee802154_cc13xx_cc26xx_subg_d .pktConf.bUseCrc = true, /* PHR field format, see IEEE 802.15.4, section 19.2.4 */ .numHdrBits = 16, - .preTrigger.triggerType = TRIG_REL_START, + .preTrigger.triggerType = + TRIG_REL_START, /* workaround for CC13_RF_ROM_FW_CPE--BUG00016 */ .preTrigger.pastTrig = true, /* Last preamble byte and SFD for uncoded 2-FSK SUN PHY, phySunFskSfd = 0, * see IEEE 802.15.4, section 19.2.3.2, table 19-2. @@ -916,7 +1048,7 @@ static struct ieee802154_cc13xx_cc26xx_subg_data ieee802154_cc13xx_cc26xx_subg_d }, }; -#if defined(CONFIG_NET_L2_IEEE802154_SUB_GHZ) +#if defined(CONFIG_NET_L2_IEEE802154) NET_DEVICE_DT_INST_DEFINE(0, ieee802154_cc13xx_cc26xx_subg_init, NULL, &ieee802154_cc13xx_cc26xx_subg_data, NULL, CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_INIT_PRIO, diff --git a/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.h b/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.h index 2c150b4ebdb..bae259b1983 100644 --- a/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.h +++ b/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.h @@ -32,13 +32,16 @@ #define CC13XX_CC26XX_INVALID_RSSI INT8_MIN struct ieee802154_cc13xx_cc26xx_subg_data { + /* protects writable data and serializes access to the API */ + struct k_sem lock; + RF_Handle rf_handle; RF_Object rf_object; struct net_if *iface; uint8_t mac[8]; /* in big endian */ - struct k_mutex tx_mutex; + bool is_up; dataQueue_t rx_queue; rfc_dataEntryPointer_t rx_entry[CC13XX_CC26XX_NUM_RX_BUF]; @@ -53,6 +56,8 @@ struct ieee802154_cc13xx_cc26xx_subg_data { volatile rfc_CMD_PROP_TX_ADV_t cmd_prop_tx_adv; volatile rfc_propRxOutput_t cmd_prop_rx_adv_output; volatile rfc_CMD_PROP_CS_t cmd_prop_cs; + + RF_CmdHandle rx_cmd_handle; }; #endif /* ZEPHYR_DRIVERS_IEEE802154_IEEE802154_CC13XX_CC26XX_SUBG_H_ */ diff --git a/drivers/ieee802154/ieee802154_cc2520.c b/drivers/ieee802154/ieee802154_cc2520.c index 184b0bf13af..cf7c1091661 100644 --- a/drivers/ieee802154/ieee802154_cc2520.c +++ b/drivers/ieee802154/ieee802154_cc2520.c @@ -27,7 +27,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #include #include -#include +#include #include @@ -591,9 +591,12 @@ static inline bool verify_rxfifo_validity(const struct device *dev, return true; } -static void cc2520_rx(void *arg) +static void cc2520_rx(void *p1, void *p2, void *p3) { - const struct device *dev = arg; + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; struct cc2520_context *cc2520 = dev->data; struct net_pkt *pkt; uint8_t pkt_len; @@ -668,7 +671,7 @@ static void cc2520_rx(void *arg) static enum ieee802154_hw_caps cc2520_get_capabilities(const struct device *dev) { /* TODO: Add support for IEEE802154_HW_PROMISC */ - return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_FILTER | + return IEEE802154_HW_FCS | IEEE802154_HW_FILTER | IEEE802154_HW_RX_TX_ACK; } @@ -686,10 +689,14 @@ static int cc2520_set_channel(const struct device *dev, uint16_t channel) { LOG_DBG("%u", channel); - if (channel < 11 || channel > 26) { + if (channel > 26) { return -EINVAL; } + if (channel < 11) { + return -ENOTSUP; + } + /* See chapter 16 */ channel = 11 + (channel - 11) * 5U; @@ -878,6 +885,19 @@ static int cc2520_stop(const struct device *dev) return 0; } +/* driver-allocated attribute memory - constant across all driver instances */ +IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26); + +static int cc2520_attr_get(const struct device *dev, enum ieee802154_attr attr, + struct ieee802154_attr_value *value) +{ + ARG_UNUSED(dev); + + return ieee802154_attr_get_channel_page_and_range( + attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915, + &drv_attr.phy_supported_channels, value); +} + /****************** * Initialization * *****************/ @@ -1003,7 +1023,7 @@ static int cc2520_init(const struct device *dev) k_thread_create(&cc2520->cc2520_rx_thread, cc2520->cc2520_rx_stack, CONFIG_IEEE802154_CC2520_RX_STACK_SIZE, - (k_thread_entry_t)cc2520_rx, + cc2520_rx, (void *)dev, NULL, NULL, K_PRIO_COOP(2), 0, K_NO_WAIT); k_thread_name_set(&cc2520->cc2520_rx_thread, "cc2520_rx"); @@ -1048,6 +1068,7 @@ static struct ieee802154_radio_api cc2520_radio_api = { .start = cc2520_start, .stop = cc2520_stop, .tx = cc2520_tx, + .attr_get = cc2520_attr_get, }; #if defined(CONFIG_IEEE802154_RAW_MODE) diff --git a/drivers/ieee802154/ieee802154_dw1000.c b/drivers/ieee802154/ieee802154_dw1000.c index 174f97b879e..d20df488966 100644 --- a/drivers/ieee802154/ieee802154_dw1000.c +++ b/drivers/ieee802154/ieee802154_dw1000.c @@ -18,7 +18,7 @@ LOG_MODULE_REGISTER(dw1000, LOG_LEVEL_INF); #include #include -#include +#include #include #include @@ -46,8 +46,8 @@ LOG_MODULE_REGISTER(dw1000, LOG_LEVEL_INF); #define DW1000_RX_ANT_DLY 16450 /* SHR Symbol Duration in ns */ -#define UWB_PHY_TPSYM_PRF64 1017.63 -#define UWB_PHY_TPSYM_PRF16 993.59 +#define UWB_PHY_TPSYM_PRF64 IEEE802154_PHY_HRP_UWB_PRF64_TPSYM_SYMBOL_PERIOD_NS +#define UWB_PHY_TPSYM_PRF16 IEEE802154_PHY_HRP_UWB_PRF16_TPSYM_SYMBOL_PERIOD_NS #define UWB_PHY_NUMOF_SYM_SHR_SFD 8 @@ -452,14 +452,11 @@ static inline void dwt_irq_handle_rx(const struct device *dev, uint32_t sys_stat if (IS_ENABLED(CONFIG_NET_PKT_TIMESTAMP)) { uint8_t ts_buf[sizeof(uint64_t)] = {0}; - struct net_ptp_time timestamp; - uint64_t ts_fsec; + uint64_t ts_nsec; memcpy(ts_buf, rx_inf_reg.rx_time, DWT_RX_TIME_RX_STAMP_LEN); - ts_fsec = sys_get_le64(ts_buf) * DWT_TS_TIME_UNITS_FS; - timestamp.second = (ts_fsec / 1000000) / NSEC_PER_SEC; - timestamp.nanosecond = (ts_fsec / 1000000) % NSEC_PER_SEC; - net_pkt_set_timestamp(pkt, ×tamp); + ts_nsec = (sys_get_le64(ts_buf) * DWT_TS_TIME_UNITS_FS) / 1000000U; + net_pkt_set_timestamp_ns(pkt, ts_nsec); } /* See 4.7.2 Estimating the receive signal power */ @@ -624,9 +621,8 @@ static void dwt_gpio_callback(const struct device *dev, static enum ieee802154_hw_caps dwt_get_capabilities(const struct device *dev) { - /* TODO: Add channel page attribute with channel page four. */ /* TODO: Implement HW-supported AUTOACK + frame pending bit handling. */ - return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_FILTER | + return IEEE802154_HW_FCS | IEEE802154_HW_FILTER | IEEE802154_HW_TXTIME; } @@ -684,6 +680,14 @@ static int dwt_set_channel(const struct device *dev, uint16_t channel) struct dwt_context *ctx = dev->data; struct dwt_phy_config *rf_cfg = &ctx->rf_cfg; + if (channel > 15) { + return -EINVAL; + } + + if (channel == 0 || channel == 6 || channel > 7) { + return -ENOTSUP; + } + rf_cfg->channel = channel; LOG_INF("Set channel %u", channel); @@ -780,7 +784,6 @@ static int dwt_tx(const struct device *dev, enum ieee802154_tx_mode tx_mode, struct dwt_context *ctx = dev->data; size_t len = frag->len; uint32_t tx_time = 0; - struct net_ptp_time *txts; uint64_t tmp_fs; uint32_t tx_fctrl; uint8_t sys_ctrl = DWT_SYS_CTRL_TXSTRT; @@ -801,8 +804,7 @@ static int dwt_tx(const struct device *dev, enum ieee802154_tx_mode tx_mode, * tx_time is the high 32-bit of the 40-bit system * time value at which to send the message. */ - txts = net_pkt_timestamp(pkt); - tmp_fs = txts->second * NSEC_PER_SEC + txts->nanosecond; + tmp_fs = net_pkt_timestamp_ns(pkt); tmp_fs *= 1000U * 1000U; tx_time = (tmp_fs / DWT_TS_TIME_UNITS_FS) >> 8; @@ -859,7 +861,6 @@ static int dwt_tx(const struct device *dev, enum ieee802154_tx_mode tx_mode, if (IS_ENABLED(CONFIG_NET_PKT_TIMESTAMP)) { uint8_t ts_buf[sizeof(uint64_t)] = {0}; - struct net_ptp_time timestamp; k_sem_take(&ctx->dev_lock, K_FOREVER); dwt_register_read(dev, DWT_TX_TIME_ID, @@ -872,9 +873,7 @@ static int dwt_tx(const struct device *dev, enum ieee802154_tx_mode tx_mode, k_sem_give(&ctx->dev_lock); tmp_fs = sys_get_le64(ts_buf) * DWT_TS_TIME_UNITS_FS; - timestamp.second = (tmp_fs / 1000000) / NSEC_PER_SEC; - timestamp.nanosecond = (tmp_fs / 1000000) % NSEC_PER_SEC; - net_pkt_set_timestamp(pkt, ×tamp); + net_pkt_set_timestamp_ns(pkt, tmp_fs / 1000000U); } atomic_clear_bit(&ctx->state, DWT_STATE_TX); @@ -940,6 +939,46 @@ static int dwt_configure(const struct device *dev, return -ENOTSUP; } +/* driver-allocated attribute memory - constant across all driver instances */ +static const struct { + const struct ieee802154_phy_channel_range phy_channel_range[2]; + const struct ieee802154_phy_supported_channels phy_supported_channels; +} drv_attr = { + .phy_channel_range = { + { .from_channel = 1, .to_channel = 5 }, + { .from_channel = 7, .to_channel = 7 }, + }, + .phy_supported_channels = { + .ranges = drv_attr.phy_channel_range, + .num_ranges = 2U, + }, +}; + +static int dwt_attr_get(const struct device *dev, enum ieee802154_attr attr, + struct ieee802154_attr_value *value) +{ + if (ieee802154_attr_get_channel_page_and_range( + attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_FOUR_HRP_UWB, + &drv_attr.phy_supported_channels, value) == 0) { + return 0; + } + + switch (attr) { + case IEEE802154_ATTR_PHY_HRP_UWB_SUPPORTED_PRFS: { + struct dwt_context *ctx = dev->data; + struct dwt_phy_config *rf_cfg = &ctx->rf_cfg; + + value->phy_hrp_uwb_supported_nominal_prfs = + rf_cfg->prf == DWT_PRF_64M ? IEEE802154_PHY_HRP_UWB_NOMINAL_64_M + : IEEE802154_PHY_HRP_UWB_NOMINAL_16_M; + return 0; + } + + default: + return -ENOENT; + } +} + /* * Note, the DW_RESET pin should not be driven high externally. */ @@ -1633,6 +1672,7 @@ static struct ieee802154_radio_api dwt_radio_api = { .configure = dwt_configure, .ed_scan = dwt_ed, .tx = dwt_tx, + .attr_get = dwt_attr_get, }; #define DWT_PSDU_LENGTH (127 - DWT_FCS_LENGTH) diff --git a/drivers/ieee802154/ieee802154_kw41z.c b/drivers/ieee802154/ieee802154_kw41z.c index 3720ec0fd53..aee802ad6ff 100644 --- a/drivers/ieee802154/ieee802154_kw41z.c +++ b/drivers/ieee802154/ieee802154_kw41z.c @@ -22,7 +22,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #include #include #include -#include +#include #include "fsl_xcvr.h" @@ -359,7 +359,7 @@ static void kw41z_tmr3_disable(void) static enum ieee802154_hw_caps kw41z_get_capabilities(const struct device *dev) { - return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_FILTER | + return IEEE802154_HW_FCS | IEEE802154_HW_FILTER | IEEE802154_HW_TX_RX_ACK | IEEE802154_HW_RX_TX_ACK; } @@ -385,7 +385,7 @@ static int kw41z_cca(const struct device *dev) static int kw41z_set_channel(const struct device *dev, uint16_t channel) { if (channel < 11 || channel > 26) { - return -EINVAL; + return channel < 11 ? -ENOTSUP : -EINVAL; } ZLL->CHANNEL_NUM0 = channel; @@ -1078,6 +1078,19 @@ static int kw41z_configure(const struct device *dev, return 0; } +/* driver-allocated attribute memory - constant across all driver instances */ +IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26); + +static int kw41z_attr_get(const struct device *dev, enum ieee802154_attr attr, + struct ieee802154_attr_value *value) +{ + ARG_UNUSED(dev); + + return ieee802154_attr_get_channel_page_and_range( + attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915, + &drv_attr.phy_supported_channels, value); +} + static struct ieee802154_radio_api kw41z_radio_api = { .iface_api.init = kw41z_iface_init, @@ -1090,6 +1103,7 @@ static struct ieee802154_radio_api kw41z_radio_api = { .stop = kw41z_stop, .tx = kw41z_tx, .configure = kw41z_configure, + .attr_get = kw41z_attr_get, }; #if defined(CONFIG_NET_L2_IEEE802154) diff --git a/drivers/ieee802154/ieee802154_mcr20a.c b/drivers/ieee802154/ieee802154_mcr20a.c index 1448e32e5cf..6a1e5a99727 100644 --- a/drivers/ieee802154/ieee802154_mcr20a.c +++ b/drivers/ieee802154/ieee802154_mcr20a.c @@ -27,7 +27,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #include #include -#include +#include #include #include @@ -730,9 +730,12 @@ static inline bool irqsts3_event(const struct device *dev, return retval; } -static void mcr20a_thread_main(void *arg) +static void mcr20a_thread_main(void *p1, void *p2, void *p3) { - const struct device *dev = arg; + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; struct mcr20a_context *mcr20a = dev->data; uint8_t dregs[MCR20A_PHY_CTRL4 + 1]; bool set_new_seq; @@ -854,7 +857,7 @@ static int mcr20a_set_cca_mode(const struct device *dev, uint8_t mode) static enum ieee802154_hw_caps mcr20a_get_capabilities(const struct device *dev) { - return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_TX_RX_ACK | + return IEEE802154_HW_FCS | IEEE802154_HW_TX_RX_ACK | IEEE802154_HW_RX_TX_ACK | IEEE802154_HW_FILTER; } @@ -916,7 +919,7 @@ static int mcr20a_set_channel(const struct device *dev, uint16_t channel) if (channel < 11 || channel > 26) { LOG_ERR("Unsupported channel %u", channel); - return -EINVAL; + return channel < 11 ? -ENOTSUP : -EINVAL; } k_mutex_lock(&mcr20a->phy_mutex, K_FOREVER); @@ -1265,6 +1268,19 @@ static int mcr20a_stop(const struct device *dev) return -EIO; } +/* driver-allocated attribute memory - constant across all driver instances */ +IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26); + +static int mcr20a_attr_get(const struct device *dev, enum ieee802154_attr attr, + struct ieee802154_attr_value *value) +{ + ARG_UNUSED(dev); + + return ieee802154_attr_get_channel_page_and_range( + attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915, + &drv_attr.phy_supported_channels, value); +} + static int mcr20a_update_overwrites(const struct device *dev) { if (!write_reg_overwrite_ver(dev, overwrites_direct[0].data)) { @@ -1406,7 +1422,7 @@ static int mcr20a_init(const struct device *dev) k_thread_create(&mcr20a->mcr20a_rx_thread, mcr20a->mcr20a_rx_stack, CONFIG_IEEE802154_MCR20A_RX_STACK_SIZE, - (k_thread_entry_t)mcr20a_thread_main, + mcr20a_thread_main, (void *)dev, NULL, NULL, K_PRIO_COOP(2), 0, K_NO_WAIT); k_thread_name_set(&mcr20a->mcr20a_rx_thread, "mcr20a_rx"); @@ -1447,6 +1463,7 @@ static struct ieee802154_radio_api mcr20a_radio_api = { .start = mcr20a_start, .stop = mcr20a_stop, .tx = mcr20a_tx, + .attr_get = mcr20a_attr_get, }; #if defined(CONFIG_IEEE802154_RAW_MODE) diff --git a/drivers/ieee802154/ieee802154_nrf5.c b/drivers/ieee802154/ieee802154_nrf5.c index 35dbcaf11c8..df01f530abf 100644 --- a/drivers/ieee802154/ieee802154_nrf5.c +++ b/drivers/ieee802154/ieee802154_nrf5.c @@ -39,7 +39,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #include #include -#include +#include #include #include @@ -61,13 +61,10 @@ static struct nrf5_802154_data nrf5_data; static const struct device *nrf5_dev; #endif -#define ACK_REQUEST_BYTE 1 -#define ACK_REQUEST_BIT (1 << 5) -#define FRAME_PENDING_BYTE 1 -#define FRAME_PENDING_BIT (1 << 4) - #define DRX_SLOT_RX 0 /* Delayed reception window ID */ +#define NSEC_PER_TEN_SYMBOLS (10 * IEEE802154_PHY_OQPSK_780_TO_2450MHZ_SYMBOL_PERIOD_NS) + #if defined(CONFIG_IEEE802154_NRF5_UICR_EUI64_ENABLE) #if defined(CONFIG_SOC_NRF5340_CPUAPP) #if defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) @@ -190,13 +187,11 @@ static void nrf5_rx_thread(void *arg1, void *arg2, void *arg3) net_pkt_set_ieee802154_ack_fpb(pkt, rx_frame->ack_fpb); #if defined(CONFIG_NET_PKT_TIMESTAMP) - struct net_ptp_time timestamp = { - .second = rx_frame->time / USEC_PER_SEC, - .nanosecond = - (rx_frame->time % USEC_PER_SEC) * NSEC_PER_USEC - }; + net_pkt_set_timestamp_ns(pkt, rx_frame->time * NSEC_PER_USEC); +#endif - net_pkt_set_timestamp(pkt, ×tamp); +#if defined(CONFIG_NET_L2_OPENTHREAD) + net_pkt_set_ieee802154_ack_seb(pkt, rx_frame->ack_seb); #endif LOG_DBG("Caught a packet (%u) (LQI: %u)", @@ -235,7 +230,6 @@ static void nrf5_get_capabilities_at_boot(void) IEEE802154_HW_PROMISC | IEEE802154_HW_FILTER | ((caps & NRF_802154_CAPABILITY_CSMA) ? IEEE802154_HW_CSMA : 0UL) | - IEEE802154_HW_2_4_GHZ | IEEE802154_HW_TX_RX_ACK | IEEE802154_HW_RX_TX_ACK | IEEE802154_HW_ENERGY_SCAN | @@ -282,7 +276,7 @@ static int nrf5_set_channel(const struct device *dev, uint16_t channel) LOG_DBG("%u", channel); if (channel < 11 || channel > 26) { - return -EINVAL; + return channel < 11 ? -ENOTSUP : -EINVAL; } nrf_802154_channel_set(channel); @@ -420,12 +414,7 @@ static int handle_ack(struct nrf5_802154_data *nrf5_radio) net_pkt_set_ieee802154_rssi_dbm(ack_pkt, nrf5_radio->ack_frame.rssi); #if defined(CONFIG_NET_PKT_TIMESTAMP) - struct net_ptp_time timestamp = { - .second = nrf5_radio->ack_frame.time / USEC_PER_SEC, - .nanosecond = (nrf5_radio->ack_frame.time % USEC_PER_SEC) * NSEC_PER_USEC - }; - - net_pkt_set_timestamp(ack_pkt, ×tamp); + net_pkt_set_timestamp_ns(ack_pkt, nrf5_radio->ack_frame.time * NSEC_PER_USEC); #endif net_pkt_cursor_init(ack_pkt); @@ -544,7 +533,7 @@ static bool nrf5_tx_at(struct nrf5_802154_data *nrf5_radio, struct net_pkt *pkt, * expects a timestamp pointing to start of SHR. */ uint64_t tx_at = nrf_802154_timestamp_phr_to_shr_convert( - net_ptp_time_to_ns(net_pkt_timestamp(pkt)) / NSEC_PER_USEC); + net_pkt_timestamp_ns(pkt) / NSEC_PER_USEC); return nrf_802154_transmit_raw_at(payload, tx_at, &metadata); } @@ -687,10 +676,11 @@ static int nrf5_stop(const struct device *dev) #if defined(CONFIG_IEEE802154_CSL_ENDPOINT) if (nrf_802154_sleep_if_idle() != NRF_802154_SLEEP_ERROR_NONE) { if (nrf5_data.event_handler) { - nrf5_data.event_handler(dev, IEEE802154_EVENT_SLEEP, NULL); + nrf5_data.event_handler(dev, IEEE802154_EVENT_RX_OFF, NULL); } else { LOG_WRN("Transition to radio sleep cannot be handled."); } + Z_SPIN_DELAY(1); return 0; } #else @@ -892,27 +882,46 @@ static int nrf5_configure(const struct device *dev, #endif /* CONFIG_NRF_802154_ENCRYPTION */ case IEEE802154_CONFIG_ENH_ACK_HEADER_IE: { - uint8_t short_addr_le[SHORT_ADDRESS_SIZE]; uint8_t ext_addr_le[EXTENDED_ADDRESS_SIZE]; + uint8_t short_addr_le[SHORT_ADDRESS_SIZE]; + uint8_t element_id; + + if (config->ack_ie.short_addr == IEEE802154_BROADCAST_ADDRESS || + config->ack_ie.ext_addr == NULL) { + return -ENOTSUP; + } + + element_id = ieee802154_header_ie_get_element_id(config->ack_ie.header_ie); + + if (element_id != IEEE802154_HEADER_IE_ELEMENT_ID_CSL_IE && + (!IS_ENABLED(CONFIG_NET_L2_OPENTHREAD) || + element_id != IEEE802154_HEADER_IE_ELEMENT_ID_VENDOR_SPECIFIC_IE)) { + return -ENOTSUP; + } + +#if defined(CONFIG_NET_L2_OPENTHREAD) + uint8_t vendor_oui_le[IEEE802154_OPENTHREAD_VENDOR_OUI_LEN] = + IEEE802154_OPENTHREAD_THREAD_IE_VENDOR_OUI; + + if (element_id == IEEE802154_HEADER_IE_ELEMENT_ID_VENDOR_SPECIFIC_IE && + memcmp(config->ack_ie.header_ie->content.vendor_specific.vendor_oui, + vendor_oui_le, sizeof(vendor_oui_le))) { + return -ENOTSUP; + } +#endif sys_put_le16(config->ack_ie.short_addr, short_addr_le); - /** - * The extended address field passed to this function starts - * with the most significant octet and ends with the least - * significant octet (i.e. big endian byte order). - * The IEEE 802.15.4 transmission order mandates this order to be - * reversed (i.e. little endian byte order) in a transmitted frame. - * - * The nrf_802154_ack_data_set expects extended address in transmission - * order. - */ sys_memcpy_swap(ext_addr_le, config->ack_ie.ext_addr, EXTENDED_ADDRESS_SIZE); - if (config->ack_ie.data_len > 0) { - nrf_802154_ack_data_set(short_addr_le, false, config->ack_ie.data, - config->ack_ie.data_len, NRF_802154_ACK_DATA_IE); - nrf_802154_ack_data_set(ext_addr_le, true, config->ack_ie.data, - config->ack_ie.data_len, NRF_802154_ACK_DATA_IE); + if (config->ack_ie.header_ie && config->ack_ie.header_ie->length > 0) { + nrf_802154_ack_data_set(short_addr_le, false, config->ack_ie.header_ie, + config->ack_ie.header_ie->length + + IEEE802154_HEADER_IE_HEADER_LENGTH, + NRF_802154_ACK_DATA_IE); + nrf_802154_ack_data_set(ext_addr_le, true, config->ack_ie.header_ie, + config->ack_ie.header_ie->length + + IEEE802154_HEADER_IE_HEADER_LENGTH, + NRF_802154_ACK_DATA_IE); } else { nrf_802154_ack_data_clear(short_addr_le, false, NRF_802154_ACK_DATA_IE); nrf_802154_ack_data_clear(ext_addr_le, true, NRF_802154_ACK_DATA_IE); @@ -920,8 +929,21 @@ static int nrf5_configure(const struct device *dev, } break; #if defined(CONFIG_IEEE802154_CSL_ENDPOINT) - case IEEE802154_CONFIG_CSL_RX_TIME: { - nrf_802154_csl_writer_anchor_time_set(config->csl_rx_time / NSEC_PER_USEC); + case IEEE802154_CONFIG_EXPECTED_RX_TIME: { + +#if defined(CONFIG_NRF_802154_SER_HOST) + net_time_t period_ns = nrf5_data.csl_period * NSEC_PER_TEN_SYMBOLS; + bool changed = (config->expected_rx_time - nrf5_data.csl_rx_time) % period_ns; + + nrf5_data.csl_rx_time = config->expected_rx_time; + + if (changed) +#endif /* CONFIG_NRF_802154_SER_HOST */ + { + nrf_802154_csl_writer_anchor_time_set( + nrf_802154_timestamp_phr_to_mhr_convert(config->expected_rx_time / + NSEC_PER_USEC)); + } } break; case IEEE802154_CONFIG_RX_SLOT: { @@ -937,9 +959,12 @@ static int nrf5_configure(const struct device *dev, config->rx_slot.channel, DRX_SLOT_RX); } break; - case IEEE802154_CONFIG_CSL_PERIOD: + case IEEE802154_CONFIG_CSL_PERIOD: { nrf_802154_csl_writer_period_set(config->csl_period); - break; +#if defined(CONFIG_NRF_802154_SER_HOST) + nrf5_data.csl_period = config->csl_period; +#endif + } break; #endif /* CONFIG_IEEE802154_CSL_ENDPOINT */ #if defined(CONFIG_IEEE802154_NRF5_MULTIPLE_CCA) @@ -957,12 +982,20 @@ static int nrf5_configure(const struct device *dev, return 0; } +/* driver-allocated attribute memory - constant across all driver instances */ +IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26); + static int nrf5_attr_get(const struct device *dev, enum ieee802154_attr attr, struct ieee802154_attr_value *value) { ARG_UNUSED(dev); - ARG_UNUSED(value); + + if (ieee802154_attr_get_channel_page_and_range( + attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915, + &drv_attr.phy_supported_channels, value) == 0) { + return 0; + } switch ((uint32_t)attr) { #if defined(CONFIG_IEEE802154_NRF5_MULTIPLE_CCA) @@ -1001,13 +1034,10 @@ void nrf_802154_received_timestamp_raw(uint8_t *data, int8_t power, uint8_t lqi, nrf_802154_timestamp_end_to_phr_convert(time, data[0]); #endif - if (data[ACK_REQUEST_BYTE] & ACK_REQUEST_BIT) { - nrf5_data.rx_frames[i].ack_fpb = nrf5_data.last_frame_ack_fpb; - } else { - nrf5_data.rx_frames[i].ack_fpb = false; - } - + nrf5_data.rx_frames[i].ack_fpb = nrf5_data.last_frame_ack_fpb; + nrf5_data.rx_frames[i].ack_seb = nrf5_data.last_frame_ack_seb; nrf5_data.last_frame_ack_fpb = false; + nrf5_data.last_frame_ack_seb = false; k_fifo_put(&nrf5_data.rx_fifo, &nrf5_data.rx_frames[i]); @@ -1031,7 +1061,7 @@ void nrf_802154_receive_failed(nrf_802154_rx_error_t error, uint32_t id) * As a side effect, regular failure notifications would be reported with the * incorrect ID. */ - nrf5_data.event_handler(dev, IEEE802154_EVENT_SLEEP, NULL); + nrf5_data.event_handler(dev, IEEE802154_EVENT_RX_OFF, NULL); #endif if (error == NRF_802154_RX_ERROR_DELAYED_TIMEOUT) { return; @@ -1067,6 +1097,8 @@ void nrf_802154_receive_failed(nrf_802154_rx_error_t error, uint32_t id) } nrf5_data.last_frame_ack_fpb = false; + nrf5_data.last_frame_ack_seb = false; + if (nrf5_data.event_handler) { nrf5_data.event_handler(dev, IEEE802154_EVENT_RX_FAILED, (void *)&reason); } @@ -1074,8 +1106,8 @@ void nrf_802154_receive_failed(nrf_802154_rx_error_t error, uint32_t id) void nrf_802154_tx_ack_started(const uint8_t *data) { - nrf5_data.last_frame_ack_fpb = - data[FRAME_PENDING_BYTE] & FRAME_PENDING_BIT; + nrf5_data.last_frame_ack_fpb = data[FRAME_PENDING_OFFSET] & FRAME_PENDING_BIT; + nrf5_data.last_frame_ack_seb = data[SECURITY_ENABLED_OFFSET] & SECURITY_ENABLED_BIT; } void nrf_802154_transmitted_raw(uint8_t *frame, diff --git a/drivers/ieee802154/ieee802154_nrf5.h b/drivers/ieee802154/ieee802154_nrf5.h index 2cb41debbb8..9115fe0bdae 100644 --- a/drivers/ieee802154/ieee802154_nrf5.h +++ b/drivers/ieee802154/ieee802154_nrf5.h @@ -19,6 +19,7 @@ struct nrf5_802154_rx_frame { uint8_t lqi; /* Last received frame LQI value. */ int8_t rssi; /* Last received frame RSSI value. */ bool ack_fpb; /* FPB value in ACK sent for the received frame. */ + bool ack_seb; /* SEB value in ACK sent for the received frame. */ }; struct nrf5_802154_data { @@ -45,6 +46,9 @@ struct nrf5_802154_data { /* Frame pending bit value in ACK sent for the last received frame. */ bool last_frame_ack_fpb; + /* Security Enabled bit value in ACK sent for the last received frame. */ + bool last_frame_ack_seb; + /* CCA complete semaphore. Unlocked when CCA is complete. */ struct k_sem cca_wait; @@ -92,6 +96,14 @@ struct nrf5_802154_data { /* The maximum number of extra CCA attempts to be performed before transmission. */ uint8_t max_extra_cca_attempts; #endif + +#if defined(CONFIG_NRF_802154_SER_HOST) && defined(CONFIG_IEEE802154_CSL_ENDPOINT) + /* The last configured value of CSL period in units of 10 symbols. */ + uint32_t csl_period; + + /* The last configured value of CSL phase time in nanoseconds. */ + net_time_t csl_rx_time; +#endif /* CONFIG_NRF_802154_SER_HOST && CONFIG_IEEE802154_CSL_ENDPOINT */ }; #endif /* ZEPHYR_DRIVERS_IEEE802154_IEEE802154_NRF5_H_ */ diff --git a/drivers/ieee802154/ieee802154_rf2xx.c b/drivers/ieee802154/ieee802154_rf2xx.c index bef2195b252..ac7f13580d0 100644 --- a/drivers/ieee802154/ieee802154_rf2xx.c +++ b/drivers/ieee802154/ieee802154_rf2xx.c @@ -29,7 +29,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #include #include -#include +#include #include #include @@ -141,11 +141,11 @@ static void rf2xx_set_rssi_base(const struct device *dev, uint16_t channel) struct rf2xx_context *ctx = dev->data; int8_t base; - if (ctx->cc_page == RF2XX_TRX_CC_PAGE_0) { + if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915) { base = channel == 0 ? RF2XX_RSSI_BPSK_20 : RF2XX_RSSI_BPSK_40; - } else if (ctx->cc_page == RF2XX_TRX_CC_PAGE_2) { + } else if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_TWO_OQPSK_868_915) { base = channel == 0 ? RF2XX_RSSI_OQPSK_SIN_RC_100 : RF2XX_RSSI_OQPSK_SIN_250; @@ -179,8 +179,8 @@ static void rf2xx_trx_rx(const struct device *dev) pkt_len = rx_buf[RX2XX_FRAME_PHR_INDEX]; } - if (pkt_len < RX2XX_FRAME_MIN_PHR_SIZE) { - LOG_ERR("invalid RX frame length"); + if (!ctx->promiscuous && pkt_len < RX2XX_FRAME_MIN_PHR_SIZE) { + LOG_ERR("Invalid RX frame length"); return; } @@ -189,28 +189,35 @@ static void rf2xx_trx_rx(const struct device *dev) rf2xx_iface_frame_read(dev, rx_buf, frame_len); - trac = rx_buf[pkt_len + RX2XX_FRAME_TRAC_INDEX]; - trac = (trac >> RF2XX_RX_TRAC_STATUS) & RF2XX_RX_TRAC_BIT_MASK; + if (ctx->trx_model != RF2XX_TRX_MODEL_231) { + trac = rx_buf[pkt_len + RX2XX_FRAME_TRAC_INDEX]; + trac = (trac >> RF2XX_RX_TRAC_STATUS) & RF2XX_RX_TRAC_BIT_MASK; - if (trac == RF2XX_TRX_PHY_STATE_TRAC_INVALID) { - LOG_ERR("invalid RX frame"); + ctx->pkt_ed = rx_buf[pkt_len + RX2XX_FRAME_ED_INDEX]; + } else { + trac = (rf2xx_iface_reg_read(dev, RF2XX_TRX_STATE_REG) + >> RF2XX_TRAC_STATUS) & RF2XX_TRAC_BIT_MASK; - return; + ctx->pkt_ed = (rf2xx_iface_reg_read(dev, RF2XX_PHY_RSSI_REG) + >> RF2XX_RSSI) & RF2XX_RSSI_MASK; } - ctx->pkt_lqi = rx_buf[pkt_len + RX2XX_FRAME_LQI_INDEX]; - ctx->pkt_ed = rx_buf[pkt_len + RX2XX_FRAME_ED_INDEX]; + + if (!ctx->promiscuous && trac == RF2XX_TRX_PHY_STATE_TRAC_INVALID) { + LOG_ERR("Invalid RX frame"); + return; + } if (!IS_ENABLED(CONFIG_IEEE802154_RAW_MODE) && - !IS_ENABLED(CONFIG_NET_L2_OPENTHREAD)) { + !IS_ENABLED(CONFIG_NET_L2_OPENTHREAD) && + pkt_len >= RX2XX_FRAME_FCS_LENGTH) { pkt_len -= RX2XX_FRAME_FCS_LENGTH; } pkt = net_pkt_rx_alloc_with_buffer(ctx->iface, pkt_len, AF_UNSPEC, 0, K_NO_WAIT); - if (!pkt) { - LOG_ERR("No buf available"); + LOG_ERR("No RX buffer available"); return; } @@ -224,7 +231,7 @@ static void rf2xx_trx_rx(const struct device *dev) ctx->pkt_ed); if (net_recv_data(ctx->iface, pkt) < 0) { - LOG_DBG("Packet dropped by NET stack"); + LOG_DBG("RX Packet dropped by NET stack"); net_pkt_unref(pkt); return; } @@ -284,9 +291,12 @@ static void rf2xx_process_trx_end(const struct device *dev) } } -static void rf2xx_thread_main(void *arg) +static void rf2xx_thread_main(void *p1, void *p2, void *p3) { - struct rf2xx_context *ctx = arg; + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct rf2xx_context *ctx = p1; uint8_t isr_status; while (true) { @@ -357,8 +367,6 @@ static inline uint8_t *get_mac(const struct device *dev) static enum ieee802154_hw_caps rf2xx_get_capabilities(const struct device *dev) { - struct rf2xx_context *ctx = dev->data; - LOG_DBG("HW Caps"); return IEEE802154_HW_FCS | @@ -367,10 +375,7 @@ static enum ieee802154_hw_caps rf2xx_get_capabilities(const struct device *dev) IEEE802154_HW_CSMA | IEEE802154_HW_RETRANSMISSION | IEEE802154_HW_TX_RX_ACK | - IEEE802154_HW_RX_TX_ACK | - (ctx->trx_model == RF2XX_TRX_MODEL_212 - ? IEEE802154_HW_SUB_GHZ - : IEEE802154_HW_2_4_GHZ); + IEEE802154_HW_RX_TX_ACK; } static int rf2xx_configure_sub_channel(const struct device *dev, uint16_t channel) @@ -379,11 +384,11 @@ static int rf2xx_configure_sub_channel(const struct device *dev, uint16_t channe uint8_t reg; uint8_t cc_mask; - if (ctx->cc_page == RF2XX_TRX_CC_PAGE_0) { + if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915) { cc_mask = channel == 0 ? RF2XX_CC_BPSK_20 : RF2XX_CC_BPSK_40; - } else if (ctx->cc_page == RF2XX_TRX_CC_PAGE_2) { + } else if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_TWO_OQPSK_868_915) { cc_mask = channel == 0 ? RF2XX_CC_OQPSK_SIN_RC_100 : RF2XX_CC_OQPSK_SIN_250; @@ -397,13 +402,14 @@ static int rf2xx_configure_sub_channel(const struct device *dev, uint16_t channe return 0; } + static int rf2xx_configure_trx_path(const struct device *dev) { struct rf2xx_context *ctx = dev->data; uint8_t reg; uint8_t gc_tx_offset; - if (ctx->cc_page == RF2XX_TRX_CC_PAGE_0) { + if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915) { gc_tx_offset = 0x03; } else { gc_tx_offset = 0x02; @@ -433,24 +439,26 @@ static int rf2xx_set_channel(const struct device *dev, uint16_t channel) LOG_DBG("Set Channel %d", channel); if (ctx->trx_model == RF2XX_TRX_MODEL_212) { - if ((ctx->cc_page == RF2XX_TRX_CC_PAGE_0 - || ctx->cc_page == RF2XX_TRX_CC_PAGE_2) + if ((ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915 + || ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_TWO_OQPSK_868_915) && channel > 10) { LOG_ERR("Unsupported channel %u", channel); - return -EINVAL; + return channel > 26 ? -EINVAL : -ENOTSUP; } - if (ctx->cc_page == RF2XX_TRX_CC_PAGE_5 && channel > 3) { + if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_FIVE_OQPSK_780 && + channel > 3) { LOG_ERR("Unsupported channel %u", channel); - return -EINVAL; + return channel > 7 ? -EINVAL : -ENOTSUP; } rf2xx_configure_sub_channel(dev, channel); rf2xx_configure_trx_path(dev); rf2xx_set_rssi_base(dev, channel); } else { + /* 2.4G O-QPSK, channel page zero */ if (channel < 11 || channel > 26) { LOG_ERR("Unsupported channel %u", channel); - return -EINVAL; + return channel < 11 ? -ENOTSUP : -EINVAL; } } @@ -768,8 +776,11 @@ static int rf2xx_pan_coord_set(const struct device *dev, bool pan_coordinator) static int rf2xx_promiscuous_set(const struct device *dev, bool promiscuous) { + struct rf2xx_context *ctx = dev->data; uint8_t reg; + ctx->promiscuous = promiscuous; + if (promiscuous) { reg = rf2xx_iface_reg_read(dev, RF2XX_XAH_CTRL_1_REG); reg |= (1 << RF2XX_AACK_PROM_MODE); @@ -820,11 +831,23 @@ int rf2xx_configure(const struct device *dev, return ret; } -uint16_t rf2xx_get_subgiga_channel_count(const struct device *dev) +static int rf2xx_attr_get(const struct device *dev, enum ieee802154_attr attr, + struct ieee802154_attr_value *value) { struct rf2xx_context *ctx = dev->data; - return ctx->cc_page == RF2XX_TRX_CC_PAGE_5 ? 4 : 11; + switch (attr) { + case IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_PAGES: + value->phy_supported_channel_pages = ctx->cc_page; + return 0; + + case IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES: + value->phy_supported_channels = &ctx->cc_channels; + return 0; + + default: + return -ENOENT; + } } static int power_on_and_setup(const struct device *dev) @@ -896,6 +919,7 @@ static int power_on_and_setup(const struct device *dev) } ctx->tx_mode = IEEE802154_TX_MODE_CSMA_CA; + ctx->promiscuous = false; /* Configure INT behaviour */ config = (1 << RF2XX_RX_START) | @@ -1015,7 +1039,7 @@ static int rf2xx_init(const struct device *dev) k_thread_create(&ctx->trx_thread, ctx->trx_stack, CONFIG_IEEE802154_RF2XX_RX_STACK_SIZE, - (k_thread_entry_t) rf2xx_thread_main, + rf2xx_thread_main, ctx, NULL, NULL, K_PRIO_COOP(2), 0, K_NO_WAIT); @@ -1038,6 +1062,25 @@ static void rf2xx_iface_init(struct net_if *iface) ctx->iface = iface; + if (ctx->trx_model == RF2XX_TRX_MODEL_212) { + if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915 || + ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_TWO_OQPSK_868_915) { + ctx->cc_range.from_channel = 0U; + ctx->cc_range.to_channel = 10U; + } else if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_FIVE_OQPSK_780) { + ctx->cc_range.from_channel = 0U; + ctx->cc_range.to_channel = 3U; + } else { + __ASSERT(false, "Unsupported channel page %u.", ctx->cc_page); + } + } else { + __ASSERT(ctx->cc_page == + IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915, + "Unsupported channel page %u.", ctx->cc_page); + ctx->cc_range.from_channel = 11U; + ctx->cc_range.to_channel = 26U; + } + ieee802154_init(iface); } @@ -1053,7 +1096,7 @@ static struct ieee802154_radio_api rf2xx_radio_api = { .start = rf2xx_start, .stop = rf2xx_stop, .configure = rf2xx_configure, - .get_subg_channel_count = rf2xx_get_subgiga_channel_count, + .attr_get = rf2xx_attr_get, }; #if !defined(CONFIG_IEEE802154_RAW_MODE) @@ -1102,7 +1145,11 @@ static struct ieee802154_radio_api rf2xx_radio_api = { #define IEEE802154_RF2XX_DEVICE_DATA(n) \ static struct rf2xx_context rf2xx_ctx_data_##n = { \ .mac_addr = { DRV_INST_LOCAL_MAC_ADDRESS(n) }, \ - .cc_page = DT_INST_ENUM_IDX_OR(n, channel_page, 0), \ + .cc_page = BIT(DT_INST_ENUM_IDX_OR(n, channel_page, 0)),\ + .cc_channels = { \ + .ranges = &rf2xx_ctx_data_##n.cc_range, \ + .num_ranges = 1U, \ + } \ } #define IEEE802154_RF2XX_RAW_DEVICE_INIT(n) \ diff --git a/drivers/ieee802154/ieee802154_rf2xx.h b/drivers/ieee802154/ieee802154_rf2xx.h index 04d15533c78..9a337214afb 100644 --- a/drivers/ieee802154/ieee802154_rf2xx.h +++ b/drivers/ieee802154/ieee802154_rf2xx.h @@ -74,12 +74,6 @@ enum rf2xx_trx_model_t { RF2XX_TRX_MODEL_233 = 0x0B, }; -enum rf2xx_trx_channel_page_t { - RF2XX_TRX_CC_PAGE_0 = 0x00, - RF2XX_TRX_CC_PAGE_2 = 0x02, - RF2XX_TRX_CC_PAGE_5 = 0x05, -}; - struct rf2xx_config { struct gpio_dt_spec irq_gpio; struct gpio_dt_spec reset_gpio; @@ -112,7 +106,12 @@ struct rf2xx_context { struct k_sem trx_tx_sync; enum rf2xx_trx_model_t trx_model; - enum rf2xx_trx_channel_page_t cc_page; + + /* PHY specific driver attributes */ + enum ieee802154_phy_channel_page cc_page; + struct ieee802154_phy_channel_range cc_range; + struct ieee802154_phy_supported_channels cc_channels; + enum rf2xx_trx_state_trac_t trx_trac; enum ieee802154_tx_mode tx_mode; @@ -122,6 +121,7 @@ struct rf2xx_context { int8_t trx_rssi_base; uint8_t trx_version; uint8_t rx_phr; + bool promiscuous; }; #endif /* ZEPHYR_DRIVERS_IEEE802154_IEEE802154_RF2XX_H_ */ diff --git a/drivers/ieee802154/ieee802154_rf2xx_regs.h b/drivers/ieee802154/ieee802154_rf2xx_regs.h index d780b9a8012..ce9c2b89acc 100644 --- a/drivers/ieee802154/ieee802154_rf2xx_regs.h +++ b/drivers/ieee802154/ieee802154_rf2xx_regs.h @@ -131,6 +131,7 @@ #define RF2XX_RX_CRC_VALID 7 #define RF2XX_RND_VALUE 5 #define RF2XX_RSSI 0 +#define RF2XX_RSSI_MASK 0x1F /* PHY_CC_CCA */ #define RF2XX_CCA_REQUEST 7 diff --git a/drivers/ieee802154/ieee802154_uart_pipe.c b/drivers/ieee802154/ieee802154_uart_pipe.c index 158097e2ad2..cdb420d9747 100644 --- a/drivers/ieee802154/ieee802154_uart_pipe.c +++ b/drivers/ieee802154/ieee802154_uart_pipe.c @@ -21,7 +21,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #include #include #include -#include +#include #include #include @@ -181,9 +181,7 @@ static uint8_t *upipe_rx(uint8_t *buf, size_t *off) static enum ieee802154_hw_caps upipe_get_capabilities(const struct device *dev) { - return IEEE802154_HW_FCS | - IEEE802154_HW_2_4_GHZ | - IEEE802154_HW_FILTER; + return IEEE802154_HW_FCS | IEEE802154_HW_FILTER; } static int upipe_cca(const struct device *dev) @@ -329,6 +327,20 @@ static int upipe_stop(const struct device *dev) return 0; } +/* driver-allocated attribute memory - constant across all driver instances */ +IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26); + +/* API implementation: attr_get */ +static int upipe_attr_get(const struct device *dev, enum ieee802154_attr attr, + struct ieee802154_attr_value *value) +{ + ARG_UNUSED(dev); + + return ieee802154_attr_get_channel_page_and_range( + attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915, + &drv_attr.phy_supported_channels, value); +} + static int upipe_init(const struct device *dev) { struct upipe_context *upipe = dev->data; @@ -391,6 +403,7 @@ static struct ieee802154_radio_api upipe_radio_api = { .tx = upipe_tx, .start = upipe_start, .stop = upipe_stop, + .attr_get = upipe_attr_get, }; NET_DEVICE_DT_INST_DEFINE(0, upipe_init, NULL, &upipe_context_data, NULL, diff --git a/drivers/input/CMakeLists.txt b/drivers/input/CMakeLists.txt index 51b25155911..d63dc2ae797 100644 --- a/drivers/input/CMakeLists.txt +++ b/drivers/input/CMakeLists.txt @@ -3,14 +3,20 @@ zephyr_library() zephyr_library_property(ALLOW_EMPTY TRUE) +# zephyr-keep-sorted-start zephyr_library_sources_ifdef(CONFIG_INPUT_CAP1203 input_cap1203.c) zephyr_library_sources_ifdef(CONFIG_INPUT_CST816S input_cst816s.c) zephyr_library_sources_ifdef(CONFIG_INPUT_FT5336 input_ft5336.c) +zephyr_library_sources_ifdef(CONFIG_INPUT_GPIO_KBD_MATRIX input_gpio_kbd_matrix.c) zephyr_library_sources_ifdef(CONFIG_INPUT_GPIO_KEYS input_gpio_keys.c) zephyr_library_sources_ifdef(CONFIG_INPUT_GPIO_QDEC input_gpio_qdec.c) zephyr_library_sources_ifdef(CONFIG_INPUT_GT911 input_gt911.c) +zephyr_library_sources_ifdef(CONFIG_INPUT_ITE_IT8XXX2_KBD input_ite_it8xxx2_kbd.c) +zephyr_library_sources_ifdef(CONFIG_INPUT_KBD_MATRIX input_kbd_matrix.c) zephyr_library_sources_ifdef(CONFIG_INPUT_NPCX_KBD input_npcx_kbd.c) +zephyr_library_sources_ifdef(CONFIG_INPUT_STMPE811 input_stmpe811.c) zephyr_library_sources_ifdef(CONFIG_INPUT_XPT2046 input_xpt2046.c) +# zephyr-keep-sorted-stop if (CONFIG_INPUT_SDL_TOUCH) zephyr_library_sources(input_sdl_touch.c) diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 3aa5271bf4e..afab00d4259 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -5,15 +5,21 @@ if INPUT menu "Input drivers" +# zephyr-keep-sorted-start source "drivers/input/Kconfig.cap1203" source "drivers/input/Kconfig.cst816s" source "drivers/input/Kconfig.ft5336" +source "drivers/input/Kconfig.gpio_kbd_matrix" source "drivers/input/Kconfig.gpio_keys" source "drivers/input/Kconfig.gpio_qdec" source "drivers/input/Kconfig.gt911" +source "drivers/input/Kconfig.it8xxx2" +source "drivers/input/Kconfig.kbd_matrix" source "drivers/input/Kconfig.npcx" source "drivers/input/Kconfig.sdl" +source "drivers/input/Kconfig.stmpe811" source "drivers/input/Kconfig.xpt2046" +# zephyr-keep-sorted-stop endmenu # Input Drivers diff --git a/drivers/input/Kconfig.gpio_kbd_matrix b/drivers/input/Kconfig.gpio_kbd_matrix new file mode 100644 index 00000000000..1ded27c1258 --- /dev/null +++ b/drivers/input/Kconfig.gpio_kbd_matrix @@ -0,0 +1,10 @@ +# Copyright 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +config INPUT_GPIO_KBD_MATRIX + bool "GPIO based keyboard matrix input driver" + default y + depends on DT_HAS_GPIO_KBD_MATRIX_ENABLED + select INPUT_KBD_MATRIX + help + GPIO keyboard matrix input driver. diff --git a/drivers/input/Kconfig.it8xxx2 b/drivers/input/Kconfig.it8xxx2 new file mode 100644 index 00000000000..6e729b27c3a --- /dev/null +++ b/drivers/input/Kconfig.it8xxx2 @@ -0,0 +1,11 @@ +# Copyright (c) 2021 ITE Corporation. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +config INPUT_ITE_IT8XXX2_KBD + bool "ITE keyboard scanning driver" + default y + depends on DT_HAS_ITE_IT8XXX2_KBD_ENABLED + select INPUT_KBD_MATRIX + select MULTITHREADING + help + This option enables the ITE keyboard scan driver. diff --git a/drivers/input/Kconfig.kbd_matrix b/drivers/input/Kconfig.kbd_matrix new file mode 100644 index 00000000000..5d1328a227f --- /dev/null +++ b/drivers/input/Kconfig.kbd_matrix @@ -0,0 +1,17 @@ +# Copyright 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +config INPUT_KBD_MATRIX + bool + help + Enable library used for keyboard matrix drivers. + +if INPUT_KBD_MATRIX + +config INPUT_KBD_MATRIX_THREAD_STACK_SIZE + int "Stack size for the keyboard matrix thread" + default 1024 + help + Size of the stack used for the keyboard matrix thread. + +endif # INPUT_KBD_MATRIX diff --git a/drivers/input/Kconfig.npcx b/drivers/input/Kconfig.npcx index e6936aeb2ee..ef380b0ca4b 100644 --- a/drivers/input/Kconfig.npcx +++ b/drivers/input/Kconfig.npcx @@ -3,41 +3,20 @@ # Copyright (c) 2022 Nuvoton Technology Corporation. # SPDX-License-Identifier: Apache-2.0 -menuconfig INPUT_NPCX_KBD +config INPUT_NPCX_KBD bool "Nuvoton NPCX embedded controller (EC) keyboard scan driver" default y depends on DT_HAS_NUVOTON_NPCX_KBD_ENABLED + select INPUT_KBD_MATRIX select MULTITHREADING help This option enables the keyboard scan driver for NPCX family of processors. -if INPUT_NPCX_KBD - -config INPUT_NPCX_KBD_POLL_PERIOD_MS - int "Keyscan NPCX Poll Period" - default 5 - help - Defines the poll period in msecs between between matrix scans. - config INPUT_NPCX_KBD_KSO_HIGH_DRIVE bool "Select quasi-bidirectional buffers for KSO pins" default y + depends on INPUT_NPCX_KBD help Select quasi-bidirectional buffers for KSO pins to reduce the low-to-high transition time. - -config INPUT_NPCX_KBD_POLL_COL_OUTPUT_SETTLE_TIME_US - int "keyboard matrix poll column output settle time" - default 50 - help - Delay (us) between setting column output and waiting for it - to settle - -config INPUT_NPCX_KBD_THREAD_STACK_SIZE - int "Stack size for the kscan thread" - default 1024 - help - Size of the stack used for the kscan thread. - -endif # INPUT_NPCX_KBD diff --git a/drivers/input/Kconfig.stmpe811 b/drivers/input/Kconfig.stmpe811 new file mode 100644 index 00000000000..08a4307b9fb --- /dev/null +++ b/drivers/input/Kconfig.stmpe811 @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +config INPUT_STMPE811 + bool "STMPE811 touch driver" + default y + depends on DT_HAS_ST_STMPE811_ENABLED + select I2C + help + Enable driver for STMPE811 touch panel. diff --git a/drivers/input/input_cst816s.c b/drivers/input/input_cst816s.c index 6cebddf3379..9409deb045a 100644 --- a/drivers/input/input_cst816s.c +++ b/drivers/input/input_cst816s.c @@ -173,12 +173,11 @@ static void cst816s_chip_reset(const struct device *dev) int ret; if (gpio_is_ready_dt(&config->rst_gpio)) { - ret = gpio_pin_configure_dt(&config->rst_gpio, GPIO_OUTPUT_INACTIVE); + ret = gpio_pin_configure_dt(&config->rst_gpio, GPIO_OUTPUT_ACTIVE); if (ret < 0) { LOG_ERR("Could not configure reset GPIO pin"); return; } - gpio_pin_set_dt(&config->rst_gpio, 1); k_msleep(CST816S_RESET_DELAY); gpio_pin_set_dt(&config->rst_gpio, 0); k_msleep(CST816S_WAIT_DELAY); diff --git a/drivers/input/input_ft5336.c b/drivers/input/input_ft5336.c index 00649ee4e71..1dd705d80f6 100644 --- a/drivers/input/input_ft5336.c +++ b/drivers/input/input_ft5336.c @@ -153,8 +153,8 @@ static int ft5336_init(const struct device *dev) k_work_init(&data->work, ft5336_work_handler); if (config->reset_gpio.port != NULL) { - /* Enable reset GPIO, and pull down */ - r = gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_INACTIVE); + /* Enable reset GPIO and assert reset */ + r = gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_ACTIVE); if (r < 0) { LOG_ERR("Could not enable reset GPIO"); return r; @@ -166,7 +166,7 @@ static int ft5336_init(const struct device *dev) */ k_sleep(K_MSEC(5)); /* Pull reset pin high to complete reset sequence */ - r = gpio_pin_set_dt(&config->reset_gpio, 1); + r = gpio_pin_set_dt(&config->reset_gpio, 0); if (r < 0) { return r; } diff --git a/drivers/input/input_gpio_kbd_matrix.c b/drivers/input/input_gpio_kbd_matrix.c new file mode 100644 index 00000000000..9d532bfd0af --- /dev/null +++ b/drivers/input/input_gpio_kbd_matrix.c @@ -0,0 +1,198 @@ +/* + * Copyright 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT gpio_kbd_matrix + +#include +#include + +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(input_gpio_kbd_matrix, CONFIG_INPUT_LOG_LEVEL); + +struct gpio_kbd_matrix_config { + struct input_kbd_matrix_common_config common; + const struct gpio_dt_spec *row_gpio; + const struct gpio_dt_spec *col_gpio; + struct gpio_callback *gpio_cb; + gpio_callback_handler_t handler; +}; + +struct gpio_kbd_matrix_data { + struct input_kbd_matrix_common_data common; + uint32_t last_col_state; +}; + +INPUT_KBD_STRUCT_CHECK(struct gpio_kbd_matrix_config, + struct gpio_kbd_matrix_data); + +static void gpio_kbd_matrix_drive_column(const struct device *dev, int col) +{ + const struct gpio_kbd_matrix_config *cfg = dev->config; + const struct input_kbd_matrix_common_config *common = &cfg->common; + struct gpio_kbd_matrix_data *data = dev->data; + int state; + + if (col == INPUT_KBD_MATRIX_COLUMN_DRIVE_NONE) { + state = 0; + } else if (col == INPUT_KBD_MATRIX_COLUMN_DRIVE_ALL) { + state = BIT_MASK(common->col_size); + } else { + state = BIT(col); + } + + for (int i = 0; i < common->col_size; i++) { + const struct gpio_dt_spec *gpio = &cfg->col_gpio[i]; + + if ((data->last_col_state ^ state) & BIT(i)) { + if (state & BIT(i)) { + gpio_pin_configure_dt(gpio, GPIO_OUTPUT_ACTIVE); + } else { + gpio_pin_configure_dt(gpio, GPIO_INPUT); + } + } + } + + data->last_col_state = state; +} + +static int gpio_kbd_matrix_read_row(const struct device *dev) +{ + const struct gpio_kbd_matrix_config *cfg = dev->config; + const struct input_kbd_matrix_common_config *common = &cfg->common; + int val = 0; + + for (int i = 0; i < common->row_size; i++) { + const struct gpio_dt_spec *gpio = &cfg->row_gpio[i]; + + if (gpio_pin_get_dt(gpio)) { + val |= BIT(i); + } + } + + return val; +} + +static void gpio_kbd_matrix_set_detect_mode(const struct device *dev, bool enabled) +{ + const struct gpio_kbd_matrix_config *cfg = dev->config; + const struct input_kbd_matrix_common_config *common = &cfg->common; + unsigned int flags = enabled ? GPIO_INT_EDGE_BOTH : GPIO_INT_DISABLE; + int ret; + + for (int i = 0; i < common->row_size; i++) { + const struct gpio_dt_spec *gpio = &cfg->row_gpio[i]; + + ret = gpio_pin_interrupt_configure_dt(gpio, flags); + if (ret != 0) { + LOG_ERR("Pin %d interrupt configuration failed: %d", i, ret); + return; + } + } +} + +static int gpio_kbd_matrix_init(const struct device *dev) +{ + const struct gpio_kbd_matrix_config *cfg = dev->config; + const struct input_kbd_matrix_common_config *common = &cfg->common; + int ret; + int i; + + for (i = 0; i < common->col_size; i++) { + const struct gpio_dt_spec *gpio = &cfg->col_gpio[i]; + + if (!gpio_is_ready_dt(gpio)) { + LOG_ERR("%s is not ready", gpio->port->name); + return -ENODEV; + } + + ret = gpio_pin_configure_dt(gpio, GPIO_INPUT); + if (ret != 0) { + LOG_ERR("Pin %d configuration failed: %d", i, ret); + return ret; + } + } + + for (i = 0; i < common->row_size; i++) { + const struct gpio_dt_spec *gpio = &cfg->row_gpio[i]; + struct gpio_callback *gpio_cb = &cfg->gpio_cb[i]; + + if (!gpio_is_ready_dt(gpio)) { + LOG_ERR("%s is not ready", gpio->port->name); + return -ENODEV; + } + + ret = gpio_pin_configure_dt(gpio, GPIO_INPUT); + if (ret != 0) { + LOG_ERR("Pin %d configuration failed: %d", i, ret); + return ret; + } + + gpio_init_callback(gpio_cb, cfg->handler, BIT(gpio->pin)); + + ret = gpio_add_callback_dt(gpio, gpio_cb); + if (ret < 0) { + LOG_ERR("Could not set gpio callback"); + return ret; + } + } + + gpio_kbd_matrix_set_detect_mode(dev, true); + + return input_kbd_matrix_common_init(dev); +} + +static const struct input_kbd_matrix_api gpio_kbd_matrix_api = { + .drive_column = gpio_kbd_matrix_drive_column, + .read_row = gpio_kbd_matrix_read_row, + .set_detect_mode = gpio_kbd_matrix_set_detect_mode, +}; + +#define INPUT_GPIO_KBD_MATRIX_INIT(n) \ + BUILD_ASSERT(DT_INST_PROP_LEN(n, col_gpios) <= 32, "invalid col-size"); \ + \ + INPUT_KBD_MATRIX_DT_INST_DEFINE_ROW_COL( \ + n, DT_INST_PROP_LEN(n, row_gpios), DT_INST_PROP_LEN(n, col_gpios)); \ + \ + static void gpio_kbd_matrix_cb_##n(const struct device *gpio_dev, \ + struct gpio_callback *cb, uint32_t pins) \ + { \ + input_kbd_matrix_poll_start(DEVICE_DT_INST_GET(n)); \ + } \ + \ + static const struct gpio_dt_spec gpio_kbd_matrix_row_gpio_##n[DT_INST_PROP_LEN( \ + n, row_gpios)] = { \ + DT_INST_FOREACH_PROP_ELEM_SEP(n, row_gpios, GPIO_DT_SPEC_GET_BY_IDX, (,)) \ + }; \ + static const struct gpio_dt_spec gpio_kbd_matrix_col_gpio_##n[DT_INST_PROP_LEN( \ + n, col_gpios)] = { \ + DT_INST_FOREACH_PROP_ELEM_SEP(n, col_gpios, GPIO_DT_SPEC_GET_BY_IDX, (,)) \ + }; \ + static struct gpio_callback gpio_kbd_matrix_gpio_cb_##n[DT_INST_PROP_LEN(n, row_gpios)];\ + \ + static const struct gpio_kbd_matrix_config gpio_kbd_matrix_cfg_##n = { \ + .common = INPUT_KBD_MATRIX_DT_INST_COMMON_CONFIG_INIT_ROW_COL( \ + n, &gpio_kbd_matrix_api, \ + DT_INST_PROP_LEN(n, row_gpios), DT_INST_PROP_LEN(n, col_gpios)), \ + .row_gpio = gpio_kbd_matrix_row_gpio_##n, \ + .col_gpio = gpio_kbd_matrix_col_gpio_##n, \ + .gpio_cb = gpio_kbd_matrix_gpio_cb_##n, \ + .handler = gpio_kbd_matrix_cb_##n, \ + }; \ + \ + static struct gpio_kbd_matrix_data gpio_kbd_matrix_data_##n; \ + \ + DEVICE_DT_INST_DEFINE(n, gpio_kbd_matrix_init, NULL, \ + &gpio_kbd_matrix_data_##n, &gpio_kbd_matrix_cfg_##n, \ + POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, \ + NULL); + +DT_INST_FOREACH_STATUS_OKAY(INPUT_GPIO_KBD_MATRIX_INIT) diff --git a/drivers/input/input_gt911.c b/drivers/input/input_gt911.c index f62be5f1e0f..c7f2d5c90b3 100644 --- a/drivers/input/input_gt911.c +++ b/drivers/input/input_gt911.c @@ -230,7 +230,7 @@ static int gt911_init(const struct device *dev) return -ENODEV; } - r = gpio_pin_configure_dt(&config->rst_gpio, GPIO_OUTPUT_INACTIVE); + r = gpio_pin_configure_dt(&config->rst_gpio, GPIO_OUTPUT_ACTIVE); if (r < 0) { LOG_ERR("Could not configure reset GPIO pin"); return r; @@ -253,10 +253,10 @@ static int gt911_init(const struct device *dev) /* Delay at least 10 ms after power on before we configure gt911 */ k_sleep(K_MSEC(20)); /* reset the device and confgiure the addr mode0 */ - gpio_pin_set_dt(&config->rst_gpio, 0); + gpio_pin_set_dt(&config->rst_gpio, 1); /* hold down at least 1us, 1ms here */ k_sleep(K_MSEC(1)); - gpio_pin_set_dt(&config->rst_gpio, 1); + gpio_pin_set_dt(&config->rst_gpio, 0); /* hold down at least 5ms. This is the point the INT pin must be low. */ k_sleep(K_MSEC(5)); /* hold down 50ms to make sure the address available */ diff --git a/drivers/input/input_ite_it8xxx2_kbd.c b/drivers/input/input_ite_it8xxx2_kbd.c new file mode 100644 index 00000000000..8d688d42db1 --- /dev/null +++ b/drivers/input/input_ite_it8xxx2_kbd.c @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2021 ITE Corporation. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ite_it8xxx2_kbd + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(input_ite_it8xxx2_kbd); + +#define KEYBOARD_KSI_PIN_COUNT IT8XXX2_DT_INST_WUCCTRL_LEN(0) + +struct it8xxx2_kbd_wuc_map_cfg { + /* WUC control device structure */ + const struct device *wucs; + /* WUC pin mask */ + uint8_t mask; +}; + +struct it8xxx2_kbd_config { + struct input_kbd_matrix_common_config common; + /* Keyboard scan controller base address */ + struct kscan_it8xxx2_regs *base; + /* Keyboard scan input (KSI) wake-up irq */ + int irq; + /* KSI[7:0] wake-up input source configuration list */ + const struct it8xxx2_kbd_wuc_map_cfg *wuc_map_list; + /* KSI[7:0]/KSO[17:0] keyboard scan alternate configuration */ + const struct pinctrl_dev_config *pcfg; + /* KSO16 GPIO cells */ + struct gpio_dt_spec kso16_gpios; + /* KSO17 GPIO cells */ + struct gpio_dt_spec kso17_gpios; +}; + +struct it8xxx2_kbd_data { + struct input_kbd_matrix_common_data common; + /* KSI[7:0] wake-up interrupt status mask */ + uint8_t ksi_pin_mask; +}; + +INPUT_KBD_STRUCT_CHECK(struct it8xxx2_kbd_config, struct it8xxx2_kbd_data); + +static void it8xxx2_kbd_drive_column(const struct device *dev, int col) +{ + const struct it8xxx2_kbd_config *const config = dev->config; + const struct input_kbd_matrix_common_config *common = &config->common; + struct kscan_it8xxx2_regs *const inst = config->base; + int mask; + + /* Tri-state all outputs */ + if (col == INPUT_KBD_MATRIX_COLUMN_DRIVE_NONE) { + mask = 0x3ffff; + /* Assert all outputs */ + } else if (col == INPUT_KBD_MATRIX_COLUMN_DRIVE_ALL) { + mask = 0; + /* Assert a single output */ + } else { + mask = 0x3ffff ^ BIT(col); + } + + /* Set KSO[17:0] output data */ + inst->KBS_KSOL = (uint8_t) (mask & 0xff); + inst->KBS_KSOH1 = (uint8_t) ((mask >> 8) & 0xff); + if (common->col_size > 16) { + inst->KBS_KSOH2 = (uint8_t) ((mask >> 16) & 0xff); + } +} + +static int it8xxx2_kbd_read_row(const struct device *dev) +{ + const struct it8xxx2_kbd_config *const config = dev->config; + struct kscan_it8xxx2_regs *const inst = config->base; + + /* Bits are active-low, so toggle it (return 1 means key pressed) */ + return (inst->KBS_KSI ^ 0xff); +} + +static void it8xxx2_kbd_isr(const struct device *dev) +{ + const struct it8xxx2_kbd_config *const config = dev->config; + struct it8xxx2_kbd_data *data = dev->data; + + /* + * W/C wakeup interrupt status of KSI[7:0] pins + * + * NOTE: We want to clear the status as soon as possible, + * so clear KSI[7:0] pins at a time. + */ + it8xxx2_wuc_clear_status(config->wuc_map_list[0].wucs, + data->ksi_pin_mask); + + /* W/C interrupt status of KSI[7:0] pins */ + ite_intc_isr_clear(config->irq); + + input_kbd_matrix_poll_start(dev); +} + +static void it8xxx2_kbd_set_detect_mode(const struct device *dev, bool enable) +{ + const struct it8xxx2_kbd_config *const config = dev->config; + struct it8xxx2_kbd_data *data = dev->data; + + if (enable) { + /* + * W/C wakeup interrupt status of KSI[7:0] pins + * + * NOTE: We want to clear the status as soon as possible, + * so clear KSI[7:0] pins at a time. + */ + it8xxx2_wuc_clear_status(config->wuc_map_list[0].wucs, + data->ksi_pin_mask); + + /* W/C interrupt status of KSI[7:0] pins */ + ite_intc_isr_clear(config->irq); + + irq_enable(config->irq); + } else { + irq_disable(config->irq); + } +} + +static int it8xxx2_kbd_init(const struct device *dev) +{ + const struct it8xxx2_kbd_config *const config = dev->config; + const struct input_kbd_matrix_common_config *common = &config->common; + struct it8xxx2_kbd_data *data = dev->data; + struct kscan_it8xxx2_regs *const inst = config->base; + int status; + + /* Disable wakeup and interrupt of KSI pins before configuring */ + it8xxx2_kbd_set_detect_mode(dev, false); + + if (common->col_size > 16) { + /* + * For KSO[16] and KSO[17]: + * 1.GPOTRC: + * Bit[x] = 1b: Enable the open-drain mode of KSO pin + * 2.GPCRCx: + * Bit[7:6] = 00b: Select alternate KSO function + * Bit[2] = 1b: Enable the internal pull-up of KSO pin + * + * NOTE: Set input temporarily for gpio_pin_configure(), after + * that pinctrl_apply_state() set to alternate function + * immediately. + */ + gpio_pin_configure_dt(&config->kso16_gpios, GPIO_INPUT); + gpio_pin_configure_dt(&config->kso17_gpios, GPIO_INPUT); + } + /* + * Enable the internal pull-up and kbs mode of the KSI[7:0] pins. + * Enable the internal pull-up and kbs mode of the KSO[15:0] pins. + * Enable the open-drain mode of the KSO[17:0] pins. + */ + status = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (status < 0) { + LOG_ERR("Failed to configure KSI[7:0] and KSO[17:0] pins"); + return status; + } + + /* KSO[17:0] pins output low */ + inst->KBS_KSOL = 0x00; + inst->KBS_KSOH1 = 0x00; + if (common->col_size > 16) { + inst->KBS_KSOH2 = 0x00; + } + + for (int i = 0; i < KEYBOARD_KSI_PIN_COUNT; i++) { + /* Select wakeup interrupt falling-edge triggered of KSI[7:0] pins */ + it8xxx2_wuc_set_polarity(config->wuc_map_list[i].wucs, + config->wuc_map_list[i].mask, + WUC_TYPE_EDGE_FALLING); + /* W/C wakeup interrupt status of KSI[7:0] pins */ + it8xxx2_wuc_clear_status(config->wuc_map_list[i].wucs, + config->wuc_map_list[i].mask); + /* Enable wakeup interrupt of KSI[7:0] pins */ + it8xxx2_wuc_enable(config->wuc_map_list[i].wucs, + config->wuc_map_list[i].mask); + + /* + * We want to clear KSI[7:0] pins status at a time when wakeup + * interrupt fire, so gather the KSI[7:0] pin mask value here. + */ + if (config->wuc_map_list[i].wucs != config->wuc_map_list[0].wucs) { + LOG_ERR("KSI%d pin isn't in the same wuc node!", i); + } + data->ksi_pin_mask |= config->wuc_map_list[i].mask; + } + + /* W/C interrupt status of KSI[7:0] pins */ + ite_intc_isr_clear(config->irq); + + irq_connect_dynamic(DT_INST_IRQN(0), 0, + (void (*)(const void *))it8xxx2_kbd_isr, + (const void *)dev, 0); + + return input_kbd_matrix_common_init(dev); +} + +static const struct it8xxx2_kbd_wuc_map_cfg + it8xxx2_kbd_wuc[IT8XXX2_DT_INST_WUCCTRL_LEN(0)] = IT8XXX2_DT_WUC_ITEMS_LIST(0); + +PINCTRL_DT_INST_DEFINE(0); + +INPUT_KBD_MATRIX_DT_INST_DEFINE(0); + +static const struct input_kbd_matrix_api it8xxx2_kbd_api = { + .drive_column = it8xxx2_kbd_drive_column, + .read_row = it8xxx2_kbd_read_row, + .set_detect_mode = it8xxx2_kbd_set_detect_mode, +}; + +static const struct it8xxx2_kbd_config it8xxx2_kbd_cfg_0 = { + .common = INPUT_KBD_MATRIX_DT_INST_COMMON_CONFIG_INIT(0, &it8xxx2_kbd_api), + .base = (struct kscan_it8xxx2_regs *)DT_INST_REG_ADDR_BY_IDX(0, 0), + .irq = DT_INST_IRQN(0), + .wuc_map_list = it8xxx2_kbd_wuc, + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0), + .kso16_gpios = GPIO_DT_SPEC_INST_GET(0, kso16_gpios), + .kso17_gpios = GPIO_DT_SPEC_INST_GET(0, kso17_gpios), +}; + +static struct it8xxx2_kbd_data it8xxx2_kbd_data_0; + +DEVICE_DT_INST_DEFINE(0, &it8xxx2_kbd_init, NULL, + &it8xxx2_kbd_data_0, &it8xxx2_kbd_cfg_0, + POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, NULL); + +BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1, + "only one ite,it8xxx2-kbd compatible node can be supported"); +BUILD_ASSERT(IN_RANGE(DT_INST_PROP(0, row_size), 1, 8), "invalid row-size"); +BUILD_ASSERT(IN_RANGE(DT_INST_PROP(0, col_size), 16, 18), "invalid col-size"); diff --git a/drivers/input/input_kbd_matrix.c b/drivers/input/input_kbd_matrix.c new file mode 100644 index 00000000000..6005a76b3b3 --- /dev/null +++ b/drivers/input/input_kbd_matrix.c @@ -0,0 +1,292 @@ +/* + * Copyright 2019 Intel Corporation + * Copyright 2022 Nuvoton Technology Corporation. + * Copyright 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(input_kbd_matrix, CONFIG_INPUT_LOG_LEVEL); + +#define INPUT_KBD_MATRIX_ROW_MASK UINT8_MAX + +void input_kbd_matrix_poll_start(const struct device *dev) +{ + struct input_kbd_matrix_common_data *data = dev->data; + + k_sem_give(&data->poll_lock); +} + +static bool input_kbd_matrix_ghosting(const struct device *dev) +{ + const struct input_kbd_matrix_common_config *cfg = dev->config; + const uint8_t *state = cfg->matrix_new_state; + + /* + * Matrix keyboard designs are suceptible to ghosting. + * An extra key appears to be pressed when 3 keys belonging to the same + * block are pressed. For example, in the following block: + * + * . . w . q . + * . . . . . . + * . . . . . . + * . . m . a . + * + * the key m would look as pressed if the user pressed keys w, q and a + * simultaneously. A block can also be formed, with not adjacent + * columns. + */ + for (int c = 0; c < cfg->col_size; c++) { + if (!state[c]) { + continue; + } + + for (int c_next = c + 1; c_next < cfg->col_size; c_next++) { + /* + * We AND the columns to detect a "block". This is an + * indication of ghosting, due to current flowing from + * a key which was never pressed. In our case, current + * flowing is a bit set to 1 as we flipped the bits + * when the matrix was scanned. Now we OR the colums + * using z&(z-1) which is non-zero only if z has more + * than one bit set. + */ + uint8_t common_row_bits = state[c] & state[c_next]; + + if (common_row_bits & (common_row_bits - 1)) { + return true; + } + } + } + + return false; +} + +static bool input_kbd_matrix_scan(const struct device *dev) +{ + const struct input_kbd_matrix_common_config *cfg = dev->config; + const struct input_kbd_matrix_api *api = cfg->api; + int row; + uint8_t key_event = 0U; + + for (int col = 0; col < cfg->col_size; col++) { + api->drive_column(dev, col); + + /* Allow the matrix to stabilize before reading it */ + k_busy_wait(cfg->settle_time_us); + + row = api->read_row(dev) & INPUT_KBD_MATRIX_ROW_MASK; + cfg->matrix_new_state[col] = row; + key_event |= row; + } + + api->drive_column(dev, INPUT_KBD_MATRIX_COLUMN_DRIVE_NONE); + + return key_event != 0U; +} + +static void input_kbd_matrix_update_state(const struct device *dev) +{ + const struct input_kbd_matrix_common_config *cfg = dev->config; + struct input_kbd_matrix_common_data *data = dev->data; + uint8_t *matrix_new_state = cfg->matrix_new_state; + uint32_t cycles_now; + uint8_t row_changed; + uint8_t deb_col; + + cycles_now = k_cycle_get_32(); + + data->scan_clk_cycle[data->scan_cycles_idx] = cycles_now; + + /* + * The intent of this loop is to gather information related to key + * changes. + */ + for (int c = 0; c < cfg->col_size; c++) { + /* Check if there was an update from the previous scan */ + row_changed = matrix_new_state[c] ^ cfg->matrix_previous_state[c]; + + if (!row_changed) { + continue; + } + + for (int r = 0; r < cfg->row_size; r++) { + uint8_t cyc_idx = c * cfg->row_size + r; + + /* + * Index all they keys that changed for each row in + * order to debounce each key in terms of it + */ + if (row_changed & BIT(r)) { + cfg->scan_cycle_idx[cyc_idx] = data->scan_cycles_idx; + } + } + + cfg->matrix_unstable_state[c] |= row_changed; + cfg->matrix_previous_state[c] = matrix_new_state[c]; + } + + for (int c = 0; c < cfg->col_size; c++) { + deb_col = cfg->matrix_unstable_state[c]; + + if (!deb_col) { + continue; + } + + /* Debouncing for each row key occurs here */ + for (int r = 0; r < cfg->row_size; r++) { + uint8_t mask = BIT(r); + uint8_t row_bit = matrix_new_state[c] & mask; + + /* Continue if we already debounce a key */ + if (!(deb_col & mask)) { + continue; + } + + uint8_t cyc_idx = c * cfg->row_size + r; + uint8_t scan_cyc_idx = cfg->scan_cycle_idx[cyc_idx]; + uint8_t scan_clk_cycle = data->scan_clk_cycle[scan_cyc_idx]; + + /* Convert the clock cycle differences to usec */ + uint32_t debt = k_cyc_to_us_floor32(cycles_now - scan_clk_cycle); + + /* Does the key requires more time to be debounced? */ + if (debt < (row_bit ? cfg->debounce_down_ms : cfg->debounce_up_ms)) { + /* Need more time to debounce */ + continue; + } + + cfg->matrix_unstable_state[c] &= ~row_bit; + + /* Check if there was a change in the stable state */ + if ((cfg->matrix_stable_state[c] & mask) == row_bit) { + /* Key state did not change */ + continue; + } + + /* + * The current row has been debounced, therefore update + * the stable state. Then, proceed to notify the + * application about the keys pressed. + */ + cfg->matrix_stable_state[c] ^= mask; + + input_report_abs(dev, INPUT_ABS_X, c, false, K_FOREVER); + input_report_abs(dev, INPUT_ABS_Y, r, false, K_FOREVER); + input_report_key(dev, INPUT_BTN_TOUCH, row_bit, true, K_FOREVER); + } + } + + data->scan_cycles_idx = (data->scan_cycles_idx + 1) % INPUT_KBD_MATRIX_SCAN_OCURRENCES; +} + +static bool input_kbd_matrix_check_key_events(const struct device *dev) +{ + const struct input_kbd_matrix_common_config *cfg = dev->config; + bool key_pressed; + + /* Scan the matrix */ + key_pressed = input_kbd_matrix_scan(dev); + + for (int c = 0; c < cfg->col_size; c++) { + LOG_DBG("c=%2d u=%02x p=%02x n=%02x", + c, + cfg->matrix_unstable_state[c], + cfg->matrix_previous_state[c], + cfg->matrix_new_state[c]); + } + + /* Abort if ghosting is detected */ + if (cfg->ghostkey_check && input_kbd_matrix_ghosting(dev)) { + return key_pressed; + } + + input_kbd_matrix_update_state(dev); + + return key_pressed; +} + +static void input_kbd_matrix_poll(const struct device *dev) +{ + const struct input_kbd_matrix_common_config *cfg = dev->config; + k_timepoint_t poll_time_end; + uint32_t current_cycles; + uint32_t cycles_diff; + uint32_t wait_period_us; + + poll_time_end = sys_timepoint_calc(K_MSEC(cfg->poll_timeout_ms)); + + while (true) { + uint32_t start_period_cycles = k_cycle_get_32(); + + if (input_kbd_matrix_check_key_events(dev)) { + poll_time_end = sys_timepoint_calc(K_MSEC(cfg->poll_timeout_ms)); + } else if (sys_timepoint_expired(poll_time_end)) { + break; + } + + /* + * Subtract the time invested from the sleep period in order to + * compensate for the time invested in debouncing a key + */ + current_cycles = k_cycle_get_32(); + cycles_diff = current_cycles - start_period_cycles; + wait_period_us = cfg->poll_period_us - k_cyc_to_us_floor32(cycles_diff); + + wait_period_us = CLAMP(wait_period_us, + USEC_PER_MSEC, cfg->poll_period_us); + + LOG_DBG("wait_period_us: %d", wait_period_us); + + /* Allow other threads to run while we sleep */ + k_usleep(wait_period_us); + } +} + +static void input_kbd_matrix_polling_thread(void *arg1, void *unused2, void *unused3) +{ + const struct device *dev = arg1; + const struct input_kbd_matrix_common_config *cfg = dev->config; + const struct input_kbd_matrix_api *api = cfg->api; + struct input_kbd_matrix_common_data *data = dev->data; + + ARG_UNUSED(unused2); + ARG_UNUSED(unused3); + + while (true) { + api->drive_column(dev, INPUT_KBD_MATRIX_COLUMN_DRIVE_ALL); + api->set_detect_mode(dev, true); + + k_sem_take(&data->poll_lock, K_FOREVER); + LOG_DBG("scan start"); + + /* Disable interrupt of KSI pins and start polling */ + api->set_detect_mode(dev, false); + + input_kbd_matrix_poll(dev); + } +} + +int input_kbd_matrix_common_init(const struct device *dev) +{ + struct input_kbd_matrix_common_data *data = dev->data; + + k_sem_init(&data->poll_lock, 0, 1); + + k_thread_create(&data->thread, data->thread_stack, + CONFIG_INPUT_KBD_MATRIX_THREAD_STACK_SIZE, + input_kbd_matrix_polling_thread, (void *)dev, NULL, NULL, + K_PRIO_COOP(4), 0, K_NO_WAIT); + + k_thread_name_set(&data->thread, dev->name); + + return 0; +} diff --git a/drivers/input/input_npcx_kbd.c b/drivers/input/input_npcx_kbd.c index ff6f08e1676..64cde93bda9 100644 --- a/drivers/input/input_npcx_kbd.c +++ b/drivers/input/input_npcx_kbd.c @@ -11,27 +11,20 @@ #include #include -#include +#include #include #include +#include +#include #include -#define LOG_LEVEL CONFIG_INPUT_LOG_LEVEL -LOG_MODULE_REGISTER(input_npcx_kbd); +LOG_MODULE_REGISTER(input_npcx_kbd, CONFIG_INPUT_LOG_LEVEL); -#define KEYBOARD_COLUMN_DRIVE_ALL -2 -#define KEYBOARD_COLUMN_DRIVE_NONE -1 - -/* Number of tracked scan times */ -#define SCAN_OCURRENCES 30U - -#define KSCAN_ROW_SIZE DT_INST_PROP(0, row_size) -#define KSCAN_COL_SIZE DT_INST_PROP(0, col_size) - -#define HAS_GHOSTING_ENABLED !DT_INST_PROP(0, no_ghostkey_check) +#define ROW_SIZE DT_INST_PROP(0, row_size) /* Driver config */ -struct input_npcx_kbd_config { +struct npcx_kbd_config { + struct input_kbd_matrix_common_config common; /* Keyboard scan controller base address */ struct kbs_reg *base; /* Clock configuration */ @@ -42,73 +35,54 @@ struct input_npcx_kbd_config { int irq; /* Size of keyboard inputs-wui mapping array */ int wui_size; - uint8_t row_size; - uint8_t col_size; - uint32_t deb_time_press; - uint32_t deb_time_rel; /* Mapping table between keyboard inputs and wui */ struct npcx_wui wui_maps[]; }; -struct input_npcx_kbd_data { - int64_t poll_timeout_us; - uint32_t poll_period_us; - uint8_t matrix_stable_state[KSCAN_COL_SIZE]; - uint8_t matrix_unstable_state[KSCAN_COL_SIZE]; - uint8_t matrix_previous_state[KSCAN_COL_SIZE]; - uint8_t matrix_new_state[KSCAN_COL_SIZE]; - /* Index in to the scan_clock_cycle to indicate start of debouncing */ - uint8_t scan_cycle_idx[KSCAN_COL_SIZE * KSCAN_ROW_SIZE]; - struct miwu_callback ksi_callback[KSCAN_ROW_SIZE]; - /* Track previous "elapsed clock cycles" per matrix scan. This - * is used to calculate the debouncing time for every key - */ - uint8_t scan_clk_cycle[SCAN_OCURRENCES]; - struct k_sem poll_lock; - uint8_t scan_cycles_idx; - struct k_thread thread; - - K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_INPUT_NPCX_KBD_THREAD_STACK_SIZE); +struct npcx_kbd_data { + struct input_kbd_matrix_common_data common; + struct miwu_callback ksi_callback[ROW_SIZE]; }; +INPUT_KBD_STRUCT_CHECK(struct npcx_kbd_config, struct npcx_kbd_data); + /* Keyboard scan local functions */ -static void input_npcx_kbd_ksi_isr(const struct device *dev, struct npcx_wui *wui) +static void npcx_kbd_ksi_isr(const struct device *dev, struct npcx_wui *wui) { ARG_UNUSED(wui); - struct input_npcx_kbd_data *const data = dev->data; - k_sem_give(&data->poll_lock); + input_kbd_matrix_poll_start(dev); } -static int input_npcx_kbd_resume_detection(const struct device *dev, bool resume) +static void npcx_kbd_set_detect_mode(const struct device *dev, bool enabled) { - const struct input_npcx_kbd_config *const config = dev->config; + const struct npcx_kbd_config *const config = dev->config; - if (resume) { + if (enabled) { irq_enable(config->irq); } else { irq_disable(config->irq); } - - return 0; } -static int input_npcx_kbd_drive_column(const struct device *dev, int col) +static void npcx_kbd_drive_column(const struct device *dev, int col) { - const struct input_npcx_kbd_config *config = dev->config; + const struct npcx_kbd_config *config = dev->config; + const struct input_kbd_matrix_common_config *common = &config->common; struct kbs_reg *const inst = config->base; uint32_t mask; - if (col >= config->col_size) { - return -EINVAL; + if (col >= common->col_size) { + LOG_ERR("invalid column: %d", col); + return; } - if (col == KEYBOARD_COLUMN_DRIVE_NONE) { + if (col == INPUT_KBD_MATRIX_COLUMN_DRIVE_NONE) { /* Drive all lines to high: key detection is disabled */ mask = ~0; - } else if (col == KEYBOARD_COLUMN_DRIVE_ALL) { + } else if (col == INPUT_KBD_MATRIX_COLUMN_DRIVE_ALL) { /* Drive all lines to low for detection any key press */ - mask = ~(BIT(config->col_size) - 1); + mask = ~BIT_MASK(common->col_size); } else { /* * Drive one line to low for determining which key's state @@ -121,278 +95,27 @@ static int input_npcx_kbd_drive_column(const struct device *dev, int col) inst->KBSOUT0 = (mask & 0xFFFF); inst->KBSOUT1 = ((mask >> 16) & 0x03); - - return 0; } -static int input_npcx_kbd_read_row(const struct device *dev) +static int npcx_kbd_read_row(const struct device *dev) { - const struct input_npcx_kbd_config *config = dev->config; + const struct npcx_kbd_config *config = dev->config; + const struct input_kbd_matrix_common_config *common = &config->common; struct kbs_reg *const inst = config->base; int val; val = inst->KBSIN; /* 1 means key pressed, otherwise means key released. */ - val = (~val & (BIT(config->row_size) - 1)); + val = ~val & BIT_MASK(common->row_size); return val; } -static bool is_matrix_ghosting(const struct device *dev, const uint8_t *state) -{ - const struct input_npcx_kbd_config *const config = dev->config; - - /* - * Matrix keyboard designs are suceptible to ghosting. - * An extra key appears to be pressed when 3 keys belonging to the same - * block are pressed. For example, in the following block: - * - * . . w . q . - * . . . . . . - * . . . . . . - * . . m . a . - * - * the key m would look as pressed if the user pressed keys w, q and a - * simultaneously. A block can also be formed, with not adjacent - * columns. - */ - for (int c = 0; c < config->col_size; c++) { - if (!state[c]) { - continue; - } - - for (int c_next = c + 1; c_next < config->col_size; c_next++) { - /* - * We AND the columns to detect a "block". This is an - * indication of ghosting, due to current flowing from - * a key which was never pressed. In our case, current - * flowing is a bit set to 1 as we flipped the bits - * when the matrix was scanned. Now we OR the colums - * using z&(z-1) which is non-zero only if z has more - * than one bit set. - */ - uint8_t common_row_bits = state[c] & state[c_next]; - - if (common_row_bits & (common_row_bits - 1)) { - return true; - } - } - } - - return false; -} - -static bool read_keyboard_matrix(const struct device *dev, uint8_t *new_state) -{ - const struct input_npcx_kbd_config *const config = dev->config; - int row; - uint8_t key_event = 0U; - - for (int col = 0; col < config->col_size; col++) { - input_npcx_kbd_drive_column(dev, col); - - /* Allow the matrix to stabilize before reading it */ - k_busy_wait(CONFIG_INPUT_NPCX_KBD_POLL_COL_OUTPUT_SETTLE_TIME_US); - - row = input_npcx_kbd_read_row(dev); - new_state[col] = row & 0xFF; - key_event |= row; - } - - input_npcx_kbd_drive_column(dev, KEYBOARD_COLUMN_DRIVE_NONE); - - return key_event != 0U; -} - -static void update_matrix_state(const struct device *dev, uint8_t *matrix_new_state) -{ - const struct input_npcx_kbd_config *const config = dev->config; - struct input_npcx_kbd_data *const data = dev->data; - uint32_t cycles_now = k_cycle_get_32(); - uint8_t row_changed = 0U; - uint8_t deb_col; - - data->scan_clk_cycle[data->scan_cycles_idx] = cycles_now; - - /* - * The intent of this loop is to gather information related to key - * changes. - */ - for (int c = 0; c < config->col_size; c++) { - /* Check if there was an update from the previous scan */ - row_changed = matrix_new_state[c] ^ data->matrix_previous_state[c]; - - if (!row_changed) { - continue; - } - - for (int r = 0; r < config->row_size; r++) { - uint8_t cyc_idx = c * config->row_size + r; - - /* - * Index all they keys that changed for each row in - * order to debounce each key in terms of it - */ - if (row_changed & BIT(r)) { - data->scan_cycle_idx[cyc_idx] = data->scan_cycles_idx; - } - } - - data->matrix_unstable_state[c] |= row_changed; - data->matrix_previous_state[c] = matrix_new_state[c]; - } - - for (int c = 0; c < config->col_size; c++) { - deb_col = data->matrix_unstable_state[c]; - - if (!deb_col) { - continue; - } - - /* Debouncing for each row key occurs here */ - for (int r = 0; r < config->row_size; r++) { - uint8_t mask = BIT(r); - uint8_t row_bit = matrix_new_state[c] & mask; - - /* Continue if we already debounce a key */ - if (!(deb_col & mask)) { - continue; - } - - uint8_t cyc_idx = c * config->row_size + r; - /* Convert the clock cycle differences to usec */ - uint32_t debt = k_cyc_to_us_floor32( - cycles_now - data->scan_clk_cycle[data->scan_cycle_idx[cyc_idx]]); - - /* Does the key requires more time to be debounced? */ - if (debt < (row_bit ? config->deb_time_press : config->deb_time_rel)) { - /* Need more time to debounce */ - continue; - } - - data->matrix_unstable_state[c] &= ~row_bit; - - /* Check if there was a change in the stable state */ - if ((data->matrix_stable_state[c] & mask) == row_bit) { - /* Key state did not change */ - continue; - } - - /* - * The current row has been debounced, therefore update - * the stable state. Then, proceed to notify the - * application about the keys pressed. - */ - data->matrix_stable_state[c] ^= mask; - - input_report_abs(dev, INPUT_ABS_X, c, false, K_FOREVER); - input_report_abs(dev, INPUT_ABS_Y, r, false, K_FOREVER); - input_report_key(dev, INPUT_BTN_TOUCH, row_bit, true, K_FOREVER); - } - } -} - -static bool check_key_events(const struct device *dev) -{ - const struct input_npcx_kbd_config *const config = dev->config; - struct input_npcx_kbd_data *const data = dev->data; - uint8_t *matrix_new_state = data->matrix_new_state; - bool key_pressed = false; - - if (++data->scan_cycles_idx >= SCAN_OCURRENCES) { - data->scan_cycles_idx = 0U; - } - - /* Scan the matrix */ - key_pressed = read_keyboard_matrix(dev, matrix_new_state); - - for (int c = 0; c < config->col_size; c++) { - LOG_DBG("U%x, P%x, N%x", data->matrix_unstable_state[c], - data->matrix_previous_state[c], matrix_new_state[c]); - } - - /* Abort if ghosting is detected */ - if (HAS_GHOSTING_ENABLED && is_matrix_ghosting(dev, matrix_new_state)) { - return key_pressed; - } - - update_matrix_state(dev, matrix_new_state); - - return key_pressed; -} - -static void kbd_matrix_poll(const struct device *dev) -{ - struct input_npcx_kbd_data *const data = dev->data; - k_timepoint_t poll_time_end = sys_timepoint_calc(K_USEC(data->poll_timeout_us)); - uint32_t current_cycles; - uint32_t cycles_diff; - uint32_t wait_period; - - while (true) { - uint32_t start_period_cycles = k_cycle_get_32(); - - if (check_key_events(dev)) { - poll_time_end = sys_timepoint_calc(K_USEC(data->poll_timeout_us)); - } else if (sys_timepoint_expired(poll_time_end)) { - break; - } - - /* - * Subtract the time invested from the sleep period in order to - * compensate for the time invested in debouncing a key - */ - current_cycles = k_cycle_get_32(); - cycles_diff = current_cycles - start_period_cycles; - wait_period = data->poll_period_us - k_cyc_to_us_floor32(cycles_diff); - - /* Override wait_period in case it is less than 1 ms */ - if (wait_period < USEC_PER_MSEC) { - wait_period = USEC_PER_MSEC; - } - - /* - * Wait period results in a larger number when current cycles - * counter wrap. In this case, the whole poll period is used - */ - if (wait_period > data->poll_period_us) { - LOG_DBG("wait_period: %u", wait_period); - - wait_period = data->poll_period_us; - } - - /* Allow other threads to run while we sleep */ - k_usleep(wait_period); - } -} - -static void kbd_matrix_polling_thread(const struct device *dev, void *dummy2, void *dummy3) -{ - struct input_npcx_kbd_data *const data = dev->data; - - ARG_UNUSED(dummy2); - ARG_UNUSED(dummy3); - - while (true) { - /* Enable interrupt of KSI pins */ - input_npcx_kbd_resume_detection(dev, true); - - input_npcx_kbd_drive_column(dev, KEYBOARD_COLUMN_DRIVE_ALL); - k_sem_take(&data->poll_lock, K_FOREVER); - LOG_DBG("Start KB scan"); - - /* Disable interrupt of KSI pins and start polling */ - input_npcx_kbd_resume_detection(dev, false); - - kbd_matrix_poll(dev); - } -} - -static void input_npcx_kbd_init_ksi_wui_callback(const struct device *dev, - struct miwu_callback *callback, - const struct npcx_wui *wui, - miwu_dev_callback_handler_t handler) +static void npcx_kbd_init_ksi_wui_callback(const struct device *dev, + struct miwu_callback *callback, + const struct npcx_wui *wui, + miwu_dev_callback_handler_t handler) { /* KSI signal which has no wake-up input source */ if (wui->table == NPCX_MIWU_TABLE_NONE) { @@ -408,11 +131,12 @@ static void input_npcx_kbd_init_ksi_wui_callback(const struct device *dev, npcx_miwu_irq_enable(wui); } -static int input_npcx_kbd_init(const struct device *dev) +static int npcx_kbd_init(const struct device *dev) { const struct device *clk_dev = DEVICE_DT_GET(NPCX_CLK_CTRL_NODE); - const struct input_npcx_kbd_config *const config = dev->config; - struct input_npcx_kbd_data *const data = dev->data; + const struct npcx_kbd_config *const config = dev->config; + const struct input_kbd_matrix_common_config *common = &config->common; + struct npcx_kbd_data *const data = dev->data; struct kbs_reg *const inst = config->base; int ret; @@ -425,6 +149,7 @@ static int input_npcx_kbd_init(const struct device *dev) ret = clock_control_on(clk_dev, (clock_control_subsys_t)&config->clk_cfg); if (ret < 0) { LOG_ERR("Turn on KBSCAN clock fail %d", ret); + return -EIO; } /* Pull-up KBSIN0-7 internally */ @@ -450,13 +175,18 @@ static int input_npcx_kbd_init(const struct device *dev) } /* Drive all column lines to low for detection any key press */ - input_npcx_kbd_drive_column(dev, KEYBOARD_COLUMN_DRIVE_NONE); + npcx_kbd_drive_column(dev, INPUT_KBD_MATRIX_COLUMN_DRIVE_NONE); + + if (common->row_size != ROW_SIZE) { + LOG_ERR("Unexpected ROW_SIZE: %d != %d", common->row_size, ROW_SIZE); + return -EINVAL; + } /* Configure wake-up input and callback for keyboard input signal */ - for (int i = 0; i < config->row_size; i++) { - input_npcx_kbd_init_ksi_wui_callback( + for (int i = 0; i < common->row_size; i++) { + npcx_kbd_init_ksi_wui_callback( dev, &data->ksi_callback[i], &config->wui_maps[i], - input_npcx_kbd_ksi_isr); + npcx_kbd_ksi_isr); } /* Configure pin-mux for keyboard scan device */ @@ -466,43 +196,36 @@ static int input_npcx_kbd_init(const struct device *dev) return ret; } - /* Initialize semaphore used by keyboard scan task and driver */ - k_sem_init(&data->poll_lock, 0, 1); - - /* Time figures are transformed from msec to usec */ - data->poll_period_us = (uint32_t)(CONFIG_INPUT_NPCX_KBD_POLL_PERIOD_MS * USEC_PER_MSEC); - data->poll_timeout_us = 100 * USEC_PER_MSEC; - - k_thread_create(&data->thread, data->thread_stack, - CONFIG_INPUT_NPCX_KBD_THREAD_STACK_SIZE, - (k_thread_entry_t)kbd_matrix_polling_thread, (void *)dev, NULL, NULL, - K_PRIO_COOP(4), 0, K_NO_WAIT); - - k_thread_name_set(&data->thread, "npcx-kbd"); - - return 0; + return input_kbd_matrix_common_init(dev); } PINCTRL_DT_INST_DEFINE(0); -static const struct input_npcx_kbd_config npcx_kbd_cfg = { +INPUT_KBD_MATRIX_DT_INST_DEFINE(0); + +static const struct input_kbd_matrix_api npcx_kbd_api = { + .drive_column = npcx_kbd_drive_column, + .read_row = npcx_kbd_read_row, + .set_detect_mode = npcx_kbd_set_detect_mode, +}; + +static const struct npcx_kbd_config npcx_kbd_cfg_0 = { + .common = INPUT_KBD_MATRIX_DT_INST_COMMON_CONFIG_INIT(0, &npcx_kbd_api), .base = (struct kbs_reg *)DT_INST_REG_ADDR(0), .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0), .clk_cfg = NPCX_DT_CLK_CFG_ITEM(0), .irq = DT_INST_IRQN(0), .wui_size = NPCX_DT_WUI_ITEMS_LEN(0), .wui_maps = NPCX_DT_WUI_ITEMS_LIST(0), - .row_size = KSCAN_ROW_SIZE, - .col_size = KSCAN_COL_SIZE, - .deb_time_press = DT_INST_PROP(0, debounce_down_ms), - .deb_time_rel = DT_INST_PROP(0, debounce_up_ms), }; -static struct input_npcx_kbd_data npcx_kbd_data; +static struct npcx_kbd_data npcx_kbd_data_0; -DEVICE_DT_INST_DEFINE(0, input_npcx_kbd_init, NULL, - &npcx_kbd_data, &npcx_kbd_cfg, +DEVICE_DT_INST_DEFINE(0, npcx_kbd_init, NULL, + &npcx_kbd_data_0, &npcx_kbd_cfg_0, POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, NULL); BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1, "only one nuvoton,npcx-kbd compatible node can be supported"); +BUILD_ASSERT(IN_RANGE(DT_INST_PROP(0, row_size), 1, 8), "invalid row-size"); +BUILD_ASSERT(IN_RANGE(DT_INST_PROP(0, col_size), 1, 18), "invalid col-size"); diff --git a/drivers/input/input_stmpe811.c b/drivers/input/input_stmpe811.c new file mode 100644 index 00000000000..38ae921e8d7 --- /dev/null +++ b/drivers/input/input_stmpe811.c @@ -0,0 +1,548 @@ +/** + * Copyright (c) 2023 Antmicro + * SPDX-License-Identifier: Apache-2.0 + */ +#define DT_DRV_COMPAT st_stmpe811 + +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(stmpe811, CONFIG_INPUT_LOG_LEVEL); + +#define CHIP_ID 0x0811U + +/* Touch Screen Pins definition */ +#define STMPE811_GPIO_PIN_4 BIT(4) +#define STMPE811_GPIO_PIN_5 BIT(5) +#define STMPE811_GPIO_PIN_6 BIT(6) +#define STMPE811_GPIO_PIN_7 BIT(7) + +#define STMPE811_TOUCH_YD STMPE811_GPIO_PIN_7 +#define STMPE811_TOUCH_XD STMPE811_GPIO_PIN_6 +#define STMPE811_TOUCH_YU STMPE811_GPIO_PIN_5 +#define STMPE811_TOUCH_XU STMPE811_GPIO_PIN_4 +#define STMPE811_TOUCH_IO_ALL \ + (STMPE811_TOUCH_YD | STMPE811_TOUCH_XD | STMPE811_TOUCH_YU | STMPE811_TOUCH_XU) + +/* Registers */ +#define STMPE811_CHP_ID_LSB_REG 0x00U +#define STMPE811_ADC_CTRL1_REG 0x20U +#define STMPE811_ADC_CTRL2_REG 0x21U +#define STMPE811_SYS_CTRL1_REG 0x03U +#define STMPE811_SYS_CTRL2_REG 0x04U +#define STMPE811_TSC_CFG_REG 0x41U +#define STMPE811_IO_AF_REG 0x17U +#define STMPE811_FIFO_TH_REG 0x4AU +#define STMPE811_FIFO_STA_REG 0x4BU +#define STMPE811_FIFO_SIZE_REG 0x4CU +#define STMPE811_TSC_FRACT_XYZ_REG 0x56U +#define STMPE811_TSC_I_DRIVE_REG 0x58U +#define STMPE811_TSC_CTRL_REG 0x40U +#define STMPE811_INT_STA_REG 0x0BU +#define STMPE811_TSC_DATA_NON_INC_REG 0xD7U +#define STMPE811_INT_CTRL_REG 0x09U +#define STMPE811_INT_EN_REG 0x0AU + +/* Touch detected bit */ +#define STMPE811_TSC_CTRL_BIT_TOUCH_DET BIT(7) + +/* Global interrupt enable bit */ +#define STMPE811_INT_CTRL_BIT_GLOBAL_INT BIT(0) + +/* IO expander functionalities */ +#define STMPE811_SYS_CTRL2_BIT_ADC_FCT BIT(0) +#define STMPE811_SYS_CTRL2_BIT_TS_FCT BIT(1) +#define STMPE811_SYS_CTRL2_BIT_IO_FCT BIT(2) + +/* Global Interrupts definitions */ +#define STMPE811_INT_BIT_FIFO_THRESHOLD BIT(1) /* FIFO above threshold interrupt */ +#define STMPE811_INT_BIT_TOUCH BIT(0) /* Touch/release is detected interrupt */ +#define STMPE811_INT_ALL BIT_MASK(8) /* All interrupts */ + +/* Reset control */ +#define STMPE811_SYS_CTRL1_RESET_ON 0 +#define STMPE811_SYS_CTRL1_RESET_SOFT BIT(1) /* Soft reset */ + +/* Delays to ensure registers erasing */ +#define STMPE811_RESET_DELAY_MS 10 +#define STMPE811_WAIT_DELAY_MS 2 + +/* Configuration */ +#define STMPE811_FIFO_TH_SINGLE_POINT 1 +#define STMPE811_FIFO_STA_CLEAR 1 +#define STMPE811_FIFO_STA_OPERATIONAL 0 +#define STMPE811_TSC_I_DRIVE_LIMIT 1 + +/** + * Touch Screen Control + * + * - bits [1-3] X, Y only acquisition mode + */ +#define STMPE811_TSC_CTRL_CONF 3U + +/** + * Analog-to-digital Converter + * + * - bit [3] selects 12 bit ADC + * - bits [4-6] select ADC conversion time = 80 + */ +#define STMPE811_ADC_CTRL1_CONF 0x48U + +/** + * ADC clock speed: 3.25 MHz + * + * - 00 : 1.625 MHz + * - 01 : 3.25 MHz + * - 10 : 6.5 MHz + * - 11 : 6.5 MHz + */ +#define STMPE811_ADC_CLOCK_SPEED 1 + +/** + * Range and accuracy of the pressure measurement (Z) + * + * - Fractional part : 7 + * - Whole part : 1 + */ +#define STMPE811_TSC_FRACT_XYZ_CONF 1 + +struct stmpe811_config { + struct i2c_dt_spec bus; + struct gpio_dt_spec int_gpio; + uint8_t panel_driver_settling_time_us; + uint8_t touch_detect_delay_us; + uint8_t touch_average_control; + uint8_t tracking_index; + uint16_t screen_width; + uint16_t screen_height; + int raw_x_min; + int raw_y_min; + uint16_t raw_x_max; + uint16_t raw_y_max; +}; + +struct stmpe811_data { + const struct device *dev; + struct k_work processing_work; + struct gpio_callback int_gpio_cb; + uint32_t touch_x; + uint32_t touch_y; +}; + +static int stmpe811_reset(const struct device *dev) +{ + const struct stmpe811_config *config = dev->config; + + /* Power down the stmpe811 */ + int ret = i2c_reg_write_byte_dt(&config->bus, STMPE811_SYS_CTRL1_REG, + STMPE811_SYS_CTRL1_RESET_SOFT); + + if (ret < 0) { + return ret; + } + k_msleep(STMPE811_RESET_DELAY_MS); + + /* Power on the stmpe811 after the power off => all registers are reinitialized */ + ret = i2c_reg_write_byte_dt(&config->bus, STMPE811_SYS_CTRL1_REG, + STMPE811_SYS_CTRL1_RESET_ON); + if (ret < 0) { + return ret; + } + k_msleep(STMPE811_WAIT_DELAY_MS); + + return 0; +} + +static int stmpe811_io_enable_af(const struct device *dev, uint32_t io_pin) +{ + const struct stmpe811_config *config = dev->config; + + /* Apply ~io_pin as a mask to the current register value */ + return i2c_reg_update_byte_dt(&config->bus, STMPE811_IO_AF_REG, io_pin, 0); +} + +static uint8_t stmpe811_tsc_config_bits(const struct device *dev) +{ + const struct stmpe811_config *config = dev->config; + + /** + * Configuration: + * - bits [0-2] : panel driver settling time + * - bits [3-5] : touch detect delay + * - bits [6-7] : touch average control + */ + + return config->panel_driver_settling_time_us | config->touch_detect_delay_us << 3 | + config->touch_average_control << 6; +} + +static uint8_t stmpe811_tsc_control_bits(const struct device *dev) +{ + const struct stmpe811_config *config = dev->config; + + /** + * Touch Screen Control + * + * - bit [0] enables TSC + * - bits [1-3] X, Y only acquisition mode + * - bits [4-6] window tracking index (set from config) + * - bit [7] TSC status (writing has no effect) + */ + + return STMPE811_TSC_CTRL_CONF | config->tracking_index << 4; +} + +static int stmpe811_ts_init(const struct device *dev) +{ + const struct stmpe811_config *config = dev->config; + int err; + + err = stmpe811_reset(dev); + if (err < 0) { + return err; + } + + /* Select TSC pins in TSC alternate mode */ + err = stmpe811_io_enable_af(dev, STMPE811_TOUCH_IO_ALL); + if (err < 0) { + return err; + } + + /** + * Set the functionalities to be enabled + * Bits [0-3] disable functionalities if set to 1 (reset value: 0x0f) + * + * Apply inverted sum of chosen FCT bits as a mask to the currect register value + */ + err = i2c_reg_update_byte_dt(&config->bus, STMPE811_SYS_CTRL2_REG, + STMPE811_SYS_CTRL2_BIT_IO_FCT | STMPE811_SYS_CTRL2_BIT_TS_FCT | + STMPE811_SYS_CTRL2_BIT_ADC_FCT, 0); + if (err < 0) { + return err; + } + + /* Select sample time, bit number and ADC reference */ + err = i2c_reg_write_byte_dt(&config->bus, STMPE811_ADC_CTRL1_REG, STMPE811_ADC_CTRL1_CONF); + if (err < 0) { + return err; + } + + /* Select the ADC clock speed */ + err = i2c_reg_write_byte_dt(&config->bus, STMPE811_ADC_CTRL2_REG, STMPE811_ADC_CLOCK_SPEED); + if (err < 0) { + return err; + } + + /* Touch screen configuration */ + err = i2c_reg_write_byte_dt(&config->bus, STMPE811_TSC_CFG_REG, + stmpe811_tsc_config_bits(dev)); + if (err < 0) { + return err; + } + + /* Configure the touch FIFO threshold */ + err = i2c_reg_write_byte_dt(&config->bus, STMPE811_FIFO_TH_REG, + STMPE811_FIFO_TH_SINGLE_POINT); + if (err < 0) { + return err; + } + + /* Clear the FIFO memory content */ + err = i2c_reg_write_byte_dt(&config->bus, STMPE811_FIFO_STA_REG, STMPE811_FIFO_STA_CLEAR); + if (err < 0) { + return err; + } + + /* Set the range and accuracy of the pressure measurement (Z) */ + err = i2c_reg_write_byte_dt(&config->bus, STMPE811_TSC_FRACT_XYZ_REG, + STMPE811_TSC_FRACT_XYZ_CONF); + if (err < 0) { + return err; + } + + /* Set the driving capability (limit) of the device for TSC pins */ + err = i2c_reg_write_byte_dt(&config->bus, STMPE811_TSC_I_DRIVE_REG, + STMPE811_TSC_I_DRIVE_LIMIT); + if (err < 0) { + return err; + } + + /* Touch screen control configuration */ + err = i2c_reg_write_byte_dt(&config->bus, STMPE811_TSC_CTRL_REG, + stmpe811_tsc_control_bits(dev)); + if (err < 0) { + return err; + } + + /** + * Clear all the status pending bits if any. + * Writing '1' to this register clears the corresponding bits. + * This is an 8-bit register, so writing 0xFF clears all. + */ + err = i2c_reg_write_byte_dt(&config->bus, STMPE811_INT_STA_REG, STMPE811_INT_ALL); + if (err < 0) { + return err; + } + + /* Put the FIFO back into operation mode */ + err = i2c_reg_write_byte_dt(&config->bus, STMPE811_FIFO_STA_REG, + STMPE811_FIFO_STA_OPERATIONAL); + if (err < 0) { + return err; + } + + /* Enable FIFO and touch interrupts */ + err = i2c_reg_write_byte_dt(&config->bus, STMPE811_INT_EN_REG, + STMPE811_INT_BIT_TOUCH | STMPE811_INT_BIT_FIFO_THRESHOLD); + if (err < 0) { + LOG_ERR("Could not enable interrupt types (%d)", err); + return err; + } + + return 0; +} + +static int stmpe811_ts_get_data(const struct device *dev) +{ + const struct stmpe811_config *config = dev->config; + struct stmpe811_data *data = dev->data; + + uint8_t data_xy[3]; + uint32_t uldata_xy; + + int ret = i2c_burst_read_dt(&config->bus, STMPE811_TSC_DATA_NON_INC_REG, data_xy, + sizeof(data_xy)); + if (ret < 0) { + return ret; + } + + /* Calculate positions values */ + uldata_xy = (data_xy[0] << 16) | (data_xy[1] << 8) | data_xy[2]; + data->touch_x = (uldata_xy >> 12U) & BIT_MASK(12); + data->touch_y = uldata_xy & BIT_MASK(12); + + return 0; +} + +static void stmpe811_report_touch(const struct device *dev) +{ + const struct stmpe811_config *config = dev->config; + struct stmpe811_data *data = dev->data; + int x = data->touch_x; + int y = data->touch_y; + + if (config->screen_width > 0 && config->screen_height > 0) { + x = (((int)data->touch_x - config->raw_x_min) * config->screen_width) / + (config->raw_x_max - config->raw_x_min); + y = (((int)data->touch_y - config->raw_y_min) * config->screen_height) / + (config->raw_y_max - config->raw_y_min); + + x = CLAMP(x, 0, config->screen_width); + y = CLAMP(y, 0, config->screen_height); + } + + input_report_abs(dev, INPUT_ABS_X, x, false, K_FOREVER); + input_report_abs(dev, INPUT_ABS_Y, y, false, K_FOREVER); + input_report_key(dev, INPUT_BTN_TOUCH, 1, true, K_FOREVER); +} + +static int stmpe811_process(const struct device *dev) +{ + const struct stmpe811_config *config = dev->config; + + int err; + uint8_t int_sta, fifo_size, tsc_ctrl; + + err = i2c_reg_read_byte_dt(&config->bus, STMPE811_INT_STA_REG, &int_sta); + if (err < 0) { + return err; + } + + /* Clear processed interrupts */ + err = i2c_reg_write_byte_dt(&config->bus, STMPE811_INT_STA_REG, int_sta); + if (err < 0) { + return err; + } + + if (int_sta & STMPE811_INT_BIT_FIFO_THRESHOLD) { + /** + * Report every element in FIFO + * + * This requires a while loop to avoid a race condition + * in which an element is added after reading FIFO_SIZE. + * + * Exiting ISR without handling every element in FIFO + * would prevent FIFO_THRESHOLD interrupt from being triggered again. + */ + while (true) { + err = i2c_reg_read_byte_dt(&config->bus, STMPE811_FIFO_SIZE_REG, + &fifo_size); + if (err < 0) { + return err; + } + + if (fifo_size == 0) { + break; + } + + for (int i = 0; i < fifo_size; i++) { + err = stmpe811_ts_get_data(dev); + if (err < 0) { + return err; + } + + stmpe811_report_touch(dev); + } + } + } + + /* TOUCH interrupt also gets triggered at release */ + if (int_sta & STMPE811_INT_BIT_TOUCH) { + err = i2c_reg_read_byte_dt(&config->bus, STMPE811_TSC_CTRL_REG, &tsc_ctrl); + if (err < 0) { + return err; + } + + /* TOUCH interrupt + no touch detected in TSC_CTRL reg <=> release */ + if (!(tsc_ctrl & STMPE811_TSC_CTRL_BIT_TOUCH_DET)) { + input_report_key(dev, INPUT_BTN_TOUCH, 0, true, K_FOREVER); + } + } + + return 0; +} + +static void stmpe811_work_handler(struct k_work *work) +{ + struct stmpe811_data *data = CONTAINER_OF(work, struct stmpe811_data, processing_work); + const struct stmpe811_config *config = data->dev->config; + + stmpe811_process(data->dev); + /** + * Reschedule ISR if there was an interrupt triggered during handling (race condition). + * IRQ is edge-triggered, so otherwise it would never be triggered again. + */ + if (gpio_pin_get_dt(&config->int_gpio)) { + k_work_submit(&data->processing_work); + } +} + +static void stmpe811_interrupt_handler(const struct device *dev, struct gpio_callback *cb, + uint32_t pins) +{ + struct stmpe811_data *data = CONTAINER_OF(cb, struct stmpe811_data, int_gpio_cb); + + k_work_submit(&data->processing_work); +} + +static int stmpe811_verify_chip_id(const struct device *dev) +{ + const struct stmpe811_config *config = dev->config; + uint8_t buf[2]; + + i2c_burst_read_dt(&config->bus, STMPE811_CHP_ID_LSB_REG, buf, 2); + + if (sys_get_be16(buf) != CHIP_ID) { + return -EINVAL; + } + + return 0; +} + +static int stmpe811_init(const struct device *dev) +{ + const struct stmpe811_config *config = dev->config; + struct stmpe811_data *data = dev->data; + int err; + + if (!i2c_is_ready_dt(&config->bus)) { + LOG_ERR("I2C controller device not ready"); + return -ENODEV; + } + + data->dev = dev; + + k_work_init(&data->processing_work, stmpe811_work_handler); + + /* Verify CHIP_ID */ + err = stmpe811_verify_chip_id(dev); + if (err) { + LOG_ERR("CHIP ID verification failed (%d)", err); + return err; + } + + /* Initialize */ + err = stmpe811_ts_init(dev); + if (err) { + LOG_ERR("Touch screen controller initialization failed (%d)", err); + return err; + } + + /* Initialize GPIO interrupt */ + if (!gpio_is_ready_dt(&config->int_gpio)) { + LOG_ERR("Interrupt GPIO controller device not ready"); + return -ENODEV; + } + + err = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT); + if (err < 0) { + LOG_ERR("Could not configure interrupt GPIO pin (%d)", err); + return err; + } + + err = gpio_pin_interrupt_configure_dt(&config->int_gpio, GPIO_INT_EDGE_TO_ACTIVE); + if (err < 0) { + LOG_ERR("Could not configure GPIO interrupt (%d)", err); + return err; + } + + gpio_init_callback(&data->int_gpio_cb, stmpe811_interrupt_handler, + BIT(config->int_gpio.pin)); + err = gpio_add_callback_dt(&config->int_gpio, &data->int_gpio_cb); + if (err < 0) { + LOG_ERR("Could not set GPIO callback (%d)", err); + return err; + } + + /* Enable global interrupts */ + err = i2c_reg_write_byte_dt(&config->bus, STMPE811_INT_CTRL_REG, + STMPE811_INT_CTRL_BIT_GLOBAL_INT); + if (err < 0) { + LOG_ERR("Could not enable global interrupts (%d)", err); + return err; + } + + return 0; +} + +#define STMPE811_DEFINE(index) \ + BUILD_ASSERT(DT_INST_PROP_OR(index, raw_x_max, 4096) > \ + DT_INST_PROP_OR(index, raw_x_min, 0), \ + "raw-x-max should be larger than raw-x-min"); \ + BUILD_ASSERT(DT_INST_PROP_OR(index, raw_y_max, 4096) > \ + DT_INST_PROP_OR(index, raw_y_min, 0), \ + "raw-y-max should be larger than raw-y-min"); \ + static const struct stmpe811_config stmpe811_config_##index = { \ + .bus = I2C_DT_SPEC_INST_GET(index), \ + .int_gpio = GPIO_DT_SPEC_INST_GET(index, int_gpios), \ + .panel_driver_settling_time_us = \ + DT_INST_ENUM_IDX(index, panel_driver_settling_time_us), \ + .screen_width = DT_INST_PROP(index, screen_width), \ + .screen_height = DT_INST_PROP(index, screen_height), \ + .raw_x_min = DT_INST_PROP_OR(index, raw_x_min, 0), \ + .raw_y_min = DT_INST_PROP_OR(index, raw_y_min, 0), \ + .raw_x_max = DT_INST_PROP_OR(index, raw_x_max, 4096), \ + .raw_y_max = DT_INST_PROP_OR(index, raw_y_max, 4096), \ + .touch_detect_delay_us = DT_INST_ENUM_IDX(index, touch_detect_delay_us), \ + .touch_average_control = DT_INST_ENUM_IDX(index, touch_average_control), \ + .tracking_index = DT_INST_ENUM_IDX(index, tracking_index)}; \ + static struct stmpe811_data stmpe811_data_##index; \ + DEVICE_DT_INST_DEFINE(index, stmpe811_init, NULL, &stmpe811_data_##index, \ + &stmpe811_config_##index, POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, \ + NULL); + +DT_INST_FOREACH_STATUS_OKAY(STMPE811_DEFINE) diff --git a/drivers/interrupt_controller/CMakeLists.txt b/drivers/interrupt_controller/CMakeLists.txt index 90163e7eaa5..5598d038940 100644 --- a/drivers/interrupt_controller/CMakeLists.txt +++ b/drivers/interrupt_controller/CMakeLists.txt @@ -33,9 +33,13 @@ zephyr_library_sources_ifdef(CONFIG_VEXRISCV_LITEX_IRQ intc_vexriscv_litex. zephyr_library_sources_ifdef(CONFIG_VIM intc_vim.c) zephyr_library_sources_ifdef(CONFIG_NUCLEI_ECLIC intc_nuclei_eclic.c) zephyr_library_sources_ifdef(CONFIG_NXP_S32_EIRQ intc_eirq_nxp_s32.c) +zephyr_library_sources_ifdef(CONFIG_NXP_S32_WKPU intc_wkpu_nxp_s32.c) zephyr_library_sources_ifdef(CONFIG_XMC4XXX_INTC intc_xmc4xxx.c) zephyr_library_sources_ifdef(CONFIG_NXP_PINT intc_nxp_pint.c) +zephyr_library_sources_ifdef(CONFIG_RENESAS_RA_ICU intc_ra_icu.c) if(CONFIG_INTEL_VTD_ICTL) zephyr_library_include_directories(${ZEPHYR_BASE}/arch/x86/include) endif() + +zephyr_library_include_directories(${ZEPHYR_BASE}/arch/common/include) diff --git a/drivers/interrupt_controller/Kconfig b/drivers/interrupt_controller/Kconfig index 16ed7d40910..2a79a998c02 100644 --- a/drivers/interrupt_controller/Kconfig +++ b/drivers/interrupt_controller/Kconfig @@ -102,4 +102,6 @@ source "drivers/interrupt_controller/Kconfig.nxp_pint" source "drivers/interrupt_controller/Kconfig.vim" +source "drivers/interrupt_controller/Kconfig.ra" + endmenu diff --git a/drivers/interrupt_controller/Kconfig.nxp_s32 b/drivers/interrupt_controller/Kconfig.nxp_s32 index e9d573ed77d..b4d54ea5f5b 100644 --- a/drivers/interrupt_controller/Kconfig.nxp_s32 +++ b/drivers/interrupt_controller/Kconfig.nxp_s32 @@ -1,12 +1,20 @@ # Configuration for NXP S32 external interrupt controller -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # SPDX-License-Identifier: Apache-2.0 config NXP_S32_EIRQ bool "External interrupt controller driver for NXP S32 MCUs" default y depends on DT_HAS_NXP_S32_SIUL2_EIRQ_ENABLED - select NOCACHE_MEMORY + select NOCACHE_MEMORY if ARCH_HAS_NOCACHE_MEMORY_SUPPORT help External interrupt controller driver for NXP S32 MCUs + +config NXP_S32_WKPU + bool "Wake-up Unit interrupt controller driver for NXP S32 MCUs" + default y + depends on DT_HAS_NXP_S32_WKPU_ENABLED + select NOCACHE_MEMORY + help + Wake-up Unit interrupt controller driver for NXP S32 MCUs diff --git a/drivers/interrupt_controller/Kconfig.plic b/drivers/interrupt_controller/Kconfig.plic index fd5f3b95de4..c1e16c7c1c5 100644 --- a/drivers/interrupt_controller/Kconfig.plic +++ b/drivers/interrupt_controller/Kconfig.plic @@ -10,9 +10,3 @@ config PLIC help Platform Level Interrupt Controller provides support for external interrupt lines defined by the RISC-V SoC. - -config PLIC_SUPPORTS_EDGE_IRQ - bool "The given interrupt controller supports edge interrupts" - help - The given interrupt controller supports edge triggered - interrupts. diff --git a/drivers/interrupt_controller/Kconfig.ra b/drivers/interrupt_controller/Kconfig.ra new file mode 100644 index 00000000000..1105ea428b0 --- /dev/null +++ b/drivers/interrupt_controller/Kconfig.ra @@ -0,0 +1,9 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +config RENESAS_RA_ICU + bool "Renesas RA series interrupt controller unit" + default y + depends on DT_HAS_RENESAS_RA_INTERRUPT_CONTROLLER_UNIT_ENABLED + help + Renesas RA series interrupt controller unit diff --git a/drivers/interrupt_controller/intc_arcv2_irq_unit.c b/drivers/interrupt_controller/intc_arcv2_irq_unit.c index 5c06d936893..8825e1a7345 100644 --- a/drivers/interrupt_controller/intc_arcv2_irq_unit.c +++ b/drivers/interrupt_controller/intc_arcv2_irq_unit.c @@ -19,7 +19,9 @@ #include #include #include -#include +#include + +#define DT_DRV_COMPAT snps_arcv2_intc #ifdef CONFIG_ARC_CONNECT static void arc_shared_intc_init(void) @@ -134,7 +136,7 @@ void arc_core_private_intc_init(void) #endif /* CONFIG_ARC_CONNECT */ } -static int arc_irq_init(void) +static int arc_irq_init(const struct device *dev) { #ifdef CONFIG_ARC_CONNECT arc_shared_intc_init(); @@ -149,4 +151,5 @@ static int arc_irq_init(void) return 0; } -SYS_INIT(arc_irq_init, PRE_KERNEL_1, 0); +DEVICE_DT_INST_DEFINE(0, arc_irq_init, NULL, NULL, NULL, + PRE_KERNEL_1, 0, NULL); diff --git a/drivers/interrupt_controller/intc_eirq_nxp_s32.c b/drivers/interrupt_controller/intc_eirq_nxp_s32.c index 51631e0546c..2526aecad4d 100644 --- a/drivers/interrupt_controller/intc_eirq_nxp_s32.c +++ b/drivers/interrupt_controller/intc_eirq_nxp_s32.c @@ -4,6 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +#define DT_DRV_COMPAT nxp_s32_siul2_eirq + +#include #include #include #include @@ -124,23 +127,17 @@ static int eirq_nxp_s32_init(const struct device *dev) return 0; } -#define EIRQ_NXP_S32_NODE(n) DT_NODELABEL(eirq##n) - #define EIRQ_NXP_S32_CALLBACK(line, n) \ void nxp_s32_icu_##n##_eirq_line_##line##_callback(void) \ { \ - const struct device *dev = DEVICE_DT_GET(EIRQ_NXP_S32_NODE(n)); \ - \ - eirq_nxp_s32_callback(dev, line); \ + eirq_nxp_s32_callback(DEVICE_DT_INST_GET(n), line); \ } #define EIRQ_NXP_S32_CHANNEL_CONFIG(idx, n) \ { \ .hwChannel = idx, \ - .digFilterEn = DT_PROP_OR(DT_CHILD(EIRQ_NXP_S32_NODE(n), line_##idx), \ - filter_enable, 0), \ - .maxFilterCnt = DT_PROP_OR(DT_CHILD(EIRQ_NXP_S32_NODE(n), line_##idx), \ - filter_counter, 0), \ + .digFilterEn = DT_INST_PROP_OR(DT_CHILD(n, line_##idx), filter_enable, 0), \ + .maxFilterCnt = DT_INST_PROP_OR(DT_CHILD(n, line_##idx), filter_counter, 0), \ .intSel = SIUL2_ICU_IRQ, \ .intEdgeSel = SIUL2_ICU_DISABLE, \ .callback = NULL, \ @@ -155,8 +152,7 @@ static int eirq_nxp_s32_init(const struct device *dev) #define EIRQ_NXP_S32_INSTANCE_CONFIG(n) \ static const Siul2_Icu_Ip_InstanceConfigType eirq_##n##_instance_nxp_s32_cfg = { \ - .intFilterClk = DT_PROP_OR(EIRQ_NXP_S32_NODE(n), \ - filter_prescaler, (0)), \ + .intFilterClk = DT_INST_PROP_OR(n, filter_prescaler, 0), \ .altIntFilterClk = 0U, \ } @@ -176,42 +172,45 @@ static int eirq_nxp_s32_init(const struct device *dev) #define _EIRQ_NXP_S32_IRQ_NAME(name) DT_CAT3(SIUL2_EXT_IRQ_, name, _ISR) #define EIRQ_NXP_S32_IRQ_NAME(idx, n) \ - COND_CODE_1(DT_NODE_HAS_PROP(EIRQ_NXP_S32_NODE(n), interrupt_names), \ - (_EIRQ_NXP_S32_IRQ_NAME( \ - DT_STRING_TOKEN_BY_IDX(EIRQ_NXP_S32_NODE(n), interrupt_names, idx))), \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, interrupt_names), \ + (_EIRQ_NXP_S32_IRQ_NAME(DT_INST_STRING_TOKEN_BY_IDX(n, interrupt_names, idx))), \ (DT_CAT3(SIUL2_, n, _ICU_EIRQ_SINGLE_INT_HANDLER))) #define _EIRQ_NXP_S32_IRQ_CONFIG(idx, n) \ do { \ - IRQ_CONNECT(DT_IRQ_BY_IDX(EIRQ_NXP_S32_NODE(n), idx, irq), \ - DT_IRQ_BY_IDX(EIRQ_NXP_S32_NODE(n), idx, priority), \ + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, idx, irq), \ + DT_INST_IRQ_BY_IDX(n, idx, priority), \ EIRQ_NXP_S32_IRQ_NAME(idx, n), \ - DEVICE_DT_GET(EIRQ_NXP_S32_NODE(n)), \ - COND_CODE_1(CONFIG_GIC, \ - (DT_IRQ_BY_IDX(EIRQ_NXP_S32_NODE(n), idx, flags)), \ - (0))); \ - irq_enable(DT_IRQ_BY_IDX(EIRQ_NXP_S32_NODE(n), idx, irq)); \ + DEVICE_DT_INST_GET(n), \ + COND_CODE_1(CONFIG_GIC, (DT_INST_IRQ_BY_IDX(n, idx, flags)), (0))); \ + irq_enable(DT_INST_IRQ_BY_IDX(n, idx, irq)); \ } while (false); #define EIRQ_NXP_S32_IRQ_CONFIG(n) \ - LISTIFY(DT_NUM_IRQS(EIRQ_NXP_S32_NODE(n)), _EIRQ_NXP_S32_IRQ_CONFIG, (), n) + LISTIFY(DT_NUM_IRQS(DT_DRV_INST(n)), _EIRQ_NXP_S32_IRQ_CONFIG, (), n) + +#define EIRQ_NXP_S32_HW_INSTANCE_CHECK(i, n) \ + (((DT_REG_ADDR(DT_INST_PARENT(n))) == IP_SIUL2_##i##_BASE) ? i : 0) + +#define EIRQ_NXP_S32_HW_INSTANCE(n) \ + LISTIFY(__DEBRACKET SIUL2_INSTANCE_COUNT, EIRQ_NXP_S32_HW_INSTANCE_CHECK, (|), n) #define EIRQ_NXP_S32_INIT_DEVICE(n) \ EIRQ_NXP_S32_CONFIG(n) \ - PINCTRL_DT_DEFINE(EIRQ_NXP_S32_NODE(n)); \ + PINCTRL_DT_INST_DEFINE(n); \ static const struct eirq_nxp_s32_config eirq_nxp_s32_conf_##n = { \ - .instance = n, \ - .disr0 = (mem_addr_t)DT_REG_ADDR_BY_NAME(EIRQ_NXP_S32_NODE(n), disr0), \ - .direr0 = (mem_addr_t)DT_REG_ADDR_BY_NAME(EIRQ_NXP_S32_NODE(n), direr0), \ + .instance = EIRQ_NXP_S32_HW_INSTANCE(n), \ + .disr0 = (mem_addr_t)DT_INST_REG_ADDR_BY_NAME(n, disr0), \ + .direr0 = (mem_addr_t)DT_INST_REG_ADDR_BY_NAME(n, direr0), \ .icu_cfg = (Siul2_Icu_Ip_ConfigType *)&eirq_##n##_nxp_s32_cfg, \ - .pincfg = PINCTRL_DT_DEV_CONFIG_GET(EIRQ_NXP_S32_NODE(n)) \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n) \ }; \ static struct eirq_nxp_s32_cb eirq_nxp_s32_cb_##n[NXP_S32_NUM_CHANNELS]; \ static struct eirq_nxp_s32_data eirq_nxp_s32_data_##n = { \ .cb = eirq_nxp_s32_cb_##n, \ }; \ static int eirq_nxp_s32_init##n(const struct device *dev); \ - DEVICE_DT_DEFINE(EIRQ_NXP_S32_NODE(n), \ + DEVICE_DT_INST_DEFINE(n, \ eirq_nxp_s32_init##n, \ NULL, \ &eirq_nxp_s32_data_##n, \ @@ -233,18 +232,4 @@ static int eirq_nxp_s32_init(const struct device *dev) return 0; \ } -#if DT_NODE_HAS_STATUS(EIRQ_NXP_S32_NODE(0), okay) -EIRQ_NXP_S32_INIT_DEVICE(0) -#endif - -#if DT_NODE_HAS_STATUS(EIRQ_NXP_S32_NODE(1), okay) -EIRQ_NXP_S32_INIT_DEVICE(1) -#endif - -#if DT_NODE_HAS_STATUS(EIRQ_NXP_S32_NODE(4), okay) -EIRQ_NXP_S32_INIT_DEVICE(4) -#endif - -#if DT_NODE_HAS_STATUS(EIRQ_NXP_S32_NODE(5), okay) -EIRQ_NXP_S32_INIT_DEVICE(5) -#endif +DT_INST_FOREACH_STATUS_OKAY(EIRQ_NXP_S32_INIT_DEVICE) diff --git a/drivers/interrupt_controller/intc_exti_stm32.c b/drivers/interrupt_controller/intc_exti_stm32.c index 064d23cae20..f5f8bdc7d6e 100644 --- a/drivers/interrupt_controller/intc_exti_stm32.c +++ b/drivers/interrupt_controller/intc_exti_stm32.c @@ -73,8 +73,6 @@ void stm32_exti_enable(int line) void stm32_exti_disable(int line) { - z_stm32_hsem_lock(CFG_HW_EXTI_SEMID, HSEM_LOCK_DEFAULT_RETRY); - if (line < 32) { #if defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4) LL_C2_EXTI_DisableIT_0_31(BIT((uint32_t)line)); @@ -84,7 +82,6 @@ void stm32_exti_disable(int line) } else { __ASSERT_NO_MSG(line); } - z_stm32_hsem_unlock(CFG_HW_EXTI_SEMID); } /** diff --git a/drivers/interrupt_controller/intc_gic.c b/drivers/interrupt_controller/intc_gic.c index d664288df56..82eda22da27 100644 --- a/drivers/interrupt_controller/intc_gic.c +++ b/drivers/interrupt_controller/intc_gic.c @@ -10,7 +10,7 @@ * NOTE: This driver implements the GICv1 and GICv2 interfaces. */ -#include +#include #include #include #include @@ -18,6 +18,14 @@ #include #include +#if defined(CONFIG_GIC_V1) +#define DT_DRV_COMPAT arm_gic_v1 +#elif defined(CONFIG_GIC_V2) +#define DT_DRV_COMPAT arm_gic_v2 +#else +#error "Unknown GIC controller compatible for this configuration" +#endif + static const uint64_t cpu_mpid_list[] = { DT_FOREACH_CHILD_STATUS_OKAY_SEP(DT_PATH(cpus), DT_REG_ADDR, (,)) }; @@ -253,9 +261,8 @@ static void gic_cpu_init(void) /** * @brief Initialize the GIC device driver */ -int arm_gic_init(void) +int arm_gic_init(const struct device *dev) { - /* Init of Distributor interface registers */ gic_dist_init(); @@ -265,7 +272,8 @@ int arm_gic_init(void) return 0; } -SYS_INIT(arm_gic_init, PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY); +DEVICE_DT_INST_DEFINE(0, arm_gic_init, NULL, NULL, NULL, + PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY, NULL); #ifdef CONFIG_SMP void arm_gic_secondary_init(void) diff --git a/drivers/interrupt_controller/intc_gicv3.c b/drivers/interrupt_controller/intc_gicv3.c index 9c7611ad3c6..e3c25c4d8b8 100644 --- a/drivers/interrupt_controller/intc_gicv3.c +++ b/drivers/interrupt_controller/intc_gicv3.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include #include #include @@ -17,6 +17,8 @@ #include +#define DT_DRV_COMPAT arm_gic_v3 + /* Redistributor base addresses for each core */ mem_addr_t gic_rdists[CONFIG_MP_MAX_NUM_CPUS]; @@ -596,16 +598,16 @@ static void __arm_gic_init(void) gicv3_cpuif_init(); } -int arm_gic_init(void) +int arm_gic_init(const struct device *dev) { - gicv3_dist_init(); __arm_gic_init(); return 0; } -SYS_INIT(arm_gic_init, PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY); +DEVICE_DT_INST_DEFINE(0, arm_gic_init, NULL, NULL, NULL, + PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY, NULL); #ifdef CONFIG_SMP void arm_gic_secondary_init(void) diff --git a/drivers/interrupt_controller/intc_ioapic.c b/drivers/interrupt_controller/intc_ioapic.c index f889d0d2295..22e9ecaf374 100644 --- a/drivers/interrupt_controller/intc_ioapic.c +++ b/drivers/interrupt_controller/intc_ioapic.c @@ -89,7 +89,6 @@ DEVICE_MMIO_TOPLEVEL_STATIC(ioapic_regs, DT_DRV_INST(0)); static __pinned_bss uint32_t ioapic_rtes; #ifdef CONFIG_PM_DEVICE -#include #define BITS_PER_IRQ 4 #define IOAPIC_BITFIELD_HI_LO 0 @@ -120,7 +119,7 @@ static void IoApicRedUpdateLo(unsigned int irq, uint32_t value, !defined(CONFIG_INTEL_VTD_ICTL_XAPIC_PASSTHROUGH) #include -#include +#include static const struct device *const vtd = DEVICE_DT_GET_OR_NULL(DT_INST(0, intel_vt_d)); @@ -129,11 +128,19 @@ static uint16_t ioapic_id; static bool get_vtd(void) { + union acpi_dmar_id *dmar_id; + int inst_cnt; + if (vtd != NULL) { return true; } - ioapic_id = z_acpi_get_dev_id_from_dmar(ACPI_DRHD_DEV_SCOPE_IOAPIC); + /* Assume only one PCH in system (say client platform). */ + if (!acpi_drhd_get(ACPI_DMAR_SCOPE_TYPE_IOAPIC, NULL, &dmar_id, &inst_cnt, 1u)) { + return false; + } + + ioapic_id = dmar_id->raw; return vtd == NULL ? false : true; } @@ -535,7 +542,7 @@ static void IoApicRedUpdateLo(unsigned int irq, ioApicRedSetLo(irq, (ioApicRedGetLo(irq) & ~mask) | (value & mask)); } -PM_DEVICE_DEFINE(ioapic, ioapic_pm_action); +PM_DEVICE_DT_INST_DEFINE(0, ioapic_pm_action); -DEVICE_DEFINE(ioapic, "ioapic", ioapic_init, PM_DEVICE_GET(ioapic), NULL, NULL, - PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY, NULL); +DEVICE_DT_INST_DEFINE(0, ioapic_init, PM_DEVICE_DT_INST_GET(0), NULL, NULL, + PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY, NULL); diff --git a/drivers/interrupt_controller/intc_irqmp.c b/drivers/interrupt_controller/intc_irqmp.c index ce2ffc9d6ae..6f023f38dcd 100644 --- a/drivers/interrupt_controller/intc_irqmp.c +++ b/drivers/interrupt_controller/intc_irqmp.c @@ -17,7 +17,7 @@ #define DT_DRV_COMPAT gaisler_irqmp #include -#include +#include /* * Register description for IRQMP and IRQAMP interrupt controllers @@ -108,7 +108,7 @@ int z_sparc_int_get_source(int irl) return source; } -static int irqmp_init(void) +static int irqmp_init(const struct device *dev) { volatile struct irqmp_regs *regs = get_irqmp_regs(); @@ -121,4 +121,5 @@ static int irqmp_init(void) return 0; } -SYS_INIT(irqmp_init, PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY); +DEVICE_DT_INST_DEFINE(0, irqmp_init, NULL, NULL, NULL, + PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY, NULL); diff --git a/drivers/interrupt_controller/intc_loapic.c b/drivers/interrupt_controller/intc_loapic.c index 52722c5de45..c7faaa39cdb 100644 --- a/drivers/interrupt_controller/intc_loapic.c +++ b/drivers/interrupt_controller/intc_loapic.c @@ -65,7 +65,6 @@ #define LOAPIC_SSPND_BITS_PER_IRQ 1 /* Just the one for enable disable*/ #define LOAPIC_SUSPEND_BITS_REQD (ROUND_UP((LOAPIC_IRQ_COUNT * LOAPIC_SSPND_BITS_PER_IRQ), 32)) #ifdef CONFIG_PM_DEVICE -#include __pinned_bss uint32_t loapic_suspend_buf[LOAPIC_SUSPEND_BITS_REQD / 32] = {0}; #endif @@ -413,10 +412,10 @@ static int loapic_pm_action(const struct device *dev, } #endif /* CONFIG_PM_DEVICE */ -PM_DEVICE_DEFINE(loapic, loapic_pm_action); +PM_DEVICE_DT_INST_DEFINE(0, loapic_pm_action); -DEVICE_DEFINE(loapic, "loapic", loapic_init, PM_DEVICE_GET(loapic), NULL, NULL, - PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY, NULL); +DEVICE_DT_INST_DEFINE(0, loapic_init, PM_DEVICE_DT_INST_GET(0), NULL, NULL, + PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY, NULL); #if CONFIG_LOAPIC_SPURIOUS_VECTOR extern void z_loapic_spurious_handler(void); diff --git a/drivers/interrupt_controller/intc_nuclei_eclic.c b/drivers/interrupt_controller/intc_nuclei_eclic.c index 19f1d682f55..7c112c1a63f 100644 --- a/drivers/interrupt_controller/intc_nuclei_eclic.c +++ b/drivers/interrupt_controller/intc_nuclei_eclic.c @@ -11,12 +11,15 @@ #include #include #include -#include +#include +#include #include #include #include +#define DT_DRV_COMPAT nuclei_eclic + union CLICCFG { struct { uint8_t _reserved0 : 1; @@ -159,7 +162,7 @@ void riscv_clic_irq_priority_set(uint32_t irq, uint32_t pri, uint32_t flags) ECLIC_CTRL[irq].INTATTR.b.trg = (uint8_t)(flags & CLIC_INTATTR_TRIG_Msk); } -static int nuclei_eclic_init(void) +static int nuclei_eclic_init(const struct device *dev) { /* check hardware support required interrupt levels */ __ASSERT_NO_MSG(ECLIC_INFO.b.intctlbits >= INTERRUPT_LEVEL); @@ -182,4 +185,5 @@ static int nuclei_eclic_init(void) return 0; } -SYS_INIT(nuclei_eclic_init, PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY); +DEVICE_DT_INST_DEFINE(0, nuclei_eclic_init, NULL, NULL, NULL, + PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY, NULL); diff --git a/drivers/interrupt_controller/intc_nxp_pint.c b/drivers/interrupt_controller/intc_nxp_pint.c index ac497700e64..e05e2d30535 100644 --- a/drivers/interrupt_controller/intc_nxp_pint.c +++ b/drivers/interrupt_controller/intc_nxp_pint.c @@ -6,7 +6,7 @@ /* Based on STM32 EXTI driver, which is (c) 2016 Open-RnD Sp. z o.o. */ -#include +#include #include #include #include @@ -15,9 +15,7 @@ #define DT_DRV_COMPAT nxp_pint -#define PINT_NODE DT_INST(0, DT_DRV_COMPAT) - -static PINT_Type *pint_base = (PINT_Type *)DT_REG_ADDR(PINT_NODE); +static PINT_Type *pint_base = (PINT_Type *)DT_INST_REG_ADDR(0); /* Describes configuration of PINT IRQ slot */ struct pint_irq_slot { @@ -30,9 +28,9 @@ struct pint_irq_slot { #define NO_PINT_ID 0xFF /* Tracks IRQ configuration for each pint interrupt source */ -static struct pint_irq_slot pint_irq_cfg[DT_PROP(PINT_NODE, num_lines)]; +static struct pint_irq_slot pint_irq_cfg[DT_INST_PROP(0, num_lines)]; /* Tracks pint interrupt source selected for each pin */ -static uint8_t pin_pint_id[DT_PROP(PINT_NODE, num_inputs)]; +static uint8_t pin_pint_id[DT_INST_PROP(0, num_inputs)]; #define PIN_TO_INPUT_MUX_CONNECTION(pin) \ ((PINTSEL_PMUX_ID << PMUX_SHIFT) + (pin)) @@ -188,17 +186,17 @@ static void nxp_pint_isr(uint8_t *slot) irq_enable(DT_IRQ_BY_IDX(node_id, idx, irq)); \ } while (false))) -static int intc_nxp_pint_init(void) +static int intc_nxp_pint_init(const struct device *dev) { /* First, connect IRQs for each interrupt. * The IRQ handler will receive the PINT slot as a * parameter. */ - LISTIFY(8, NXP_PINT_IRQ, (;), PINT_NODE); + LISTIFY(8, NXP_PINT_IRQ, (;), DT_INST(0, DT_DRV_COMPAT)); PINT_Init(pint_base); memset(pin_pint_id, NO_PINT_ID, ARRAY_SIZE(pin_pint_id)); return 0; } -SYS_INIT(intc_nxp_pint_init, PRE_KERNEL_1, - CONFIG_INTC_INIT_PRIORITY); +DEVICE_DT_INST_DEFINE(0, intc_nxp_pint_init, NULL, NULL, NULL, + PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY, NULL); diff --git a/drivers/interrupt_controller/intc_plic.c b/drivers/interrupt_controller/intc_plic.c index 67a5313287c..51ce1769396 100644 --- a/drivers/interrupt_controller/intc_plic.c +++ b/drivers/interrupt_controller/intc_plic.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2017 Jean-Paul Etienne + * Copyright (c) 2023 Meta * Contributors: 2018 Antmicro * * SPDX-License-Identifier: Apache-2.0 @@ -12,32 +13,103 @@ * for RISC-V processors */ +#include "sw_isr_common.h" + #include #include -#include +#include #include #include #include #include -#define PLIC_MAX_PRIO DT_INST_PROP(0, riscv_max_priority) -#define PLIC_PRIO DT_INST_REG_ADDR_BY_NAME_U64(0, prio) -#define PLIC_IRQ_EN DT_INST_REG_ADDR_BY_NAME_U64(0, irq_en) -#define PLIC_REG DT_INST_REG_ADDR_BY_NAME_U64(0, reg) +#define PLIC_BASE_ADDR(n) DT_INST_REG_ADDR(n) +/* + * These registers' offset are defined in the RISCV PLIC specs, see: + * https://github.com/riscv/riscv-plic-spec + */ +#define PLIC_REG_PRIO_OFFSET 0x0 +#define PLIC_REG_IRQ_EN_OFFSET 0x2000 +#define PLIC_REG_REGS_OFFSET 0x200000 +#define PLIC_REG_REGS_THRES_PRIORITY_OFFSET 0 +#define PLIC_REG_REGS_CLAIM_COMPLETE_OFFSET sizeof(uint32_t) +/* + * Trigger type is mentioned, but not defined in the RISCV PLIC specs. + * However, it is defined and supported by at least the Andes & Telink datasheet, and supported + * in Linux's SiFive PLIC driver + */ +#define PLIC_REG_TRIG_TYPE_OFFSET 0x1080 + +/* PLIC registers are 32-bit memory-mapped */ +#define PLIC_REG_SIZE 32 +#define PLIC_REG_MASK BIT_MASK(LOG2(PLIC_REG_SIZE)) + +#ifdef CONFIG_TEST_INTC_PLIC +#define INTC_PLIC_STATIC +#else +#define INTC_PLIC_STATIC static inline +#endif + +typedef void (*riscv_plic_irq_config_func_t)(void); +struct plic_config { + mem_addr_t prio; + mem_addr_t irq_en; + mem_addr_t reg; + mem_addr_t trig; + uint32_t max_prio; + uint32_t num_irqs; + riscv_plic_irq_config_func_t irq_config_func; +}; -#define PLIC_IRQS (CONFIG_NUM_IRQS - CONFIG_2ND_LVL_ISR_TBL_OFFSET) -#define PLIC_EN_SIZE ((PLIC_IRQS >> 5) + 1) +static uint32_t save_irq; +static const struct device *save_dev; -#define PLIC_EDGE_TRIG_TYPE (PLIC_MAX_PRIO + DT_INST_PROP(0, riscv_trigger_reg_offset)) -#define PLIC_EDGE_TRIG_SHIFT 5 +INTC_PLIC_STATIC uint32_t local_irq_to_reg_index(uint32_t local_irq) +{ + return local_irq >> LOG2(PLIC_REG_SIZE); +} -struct plic_regs_t { - uint32_t threshold_prio; - uint32_t claim_complete; -}; +INTC_PLIC_STATIC uint32_t local_irq_to_reg_offset(uint32_t local_irq) +{ + return local_irq_to_reg_index(local_irq) * sizeof(uint32_t); +} + +static inline uint32_t get_plic_enabled_size(const struct device *dev) +{ + const struct plic_config *config = dev->config; + + return local_irq_to_reg_index(config->num_irqs) + 1; +} + +static inline mem_addr_t get_claim_complete_addr(const struct device *dev) +{ + const struct plic_config *config = dev->config; + + return config->reg + PLIC_REG_REGS_CLAIM_COMPLETE_OFFSET; +} + +static inline mem_addr_t get_threshold_priority_addr(const struct device *dev) +{ + const struct plic_config *config = dev->config; -static int save_irq; + return config->reg + PLIC_REG_REGS_THRES_PRIORITY_OFFSET; +} + +/** + * @brief Determine the PLIC device from the IRQ + * + * @param irq IRQ number + * + * @return PLIC device of that IRQ + */ +static inline const struct device *get_plic_dev_from_irq(uint32_t irq) +{ + const struct device *dev = COND_CODE_1(IS_ENABLED(CONFIG_DYNAMIC_INTERRUPTS), + (z_get_sw_isr_device_from_irq(irq)), (NULL)); + + return dev == NULL ? DEVICE_DT_INST_GET(0) : dev; +} /** * @brief return edge irq value or zero @@ -46,19 +118,17 @@ static int save_irq; * value of the irq. In the event edge irq is not supported this * routine will return 0 * - * @param irq IRQ number to add to the trigger + * @param dev PLIC-instance device + * @param local_irq PLIC-instance IRQ number to add to the trigger * * @return irq value when enabled 0 otherwise */ -static int riscv_plic_is_edge_irq(uint32_t irq) +static int riscv_plic_is_edge_irq(const struct device *dev, uint32_t local_irq) { - if (IS_ENABLED(CONFIG_PLIC_SUPPORTS_EDGE_IRQ)) { - volatile uint32_t *trig = (volatile uint32_t *)PLIC_EDGE_TRIG_TYPE; + const struct plic_config *config = dev->config; + mem_addr_t trig_addr = config->trig + local_irq_to_reg_offset(local_irq); - trig += (irq >> PLIC_EDGE_TRIG_SHIFT); - return *trig & BIT(irq); - } - return 0; + return sys_read32(trig_addr) & BIT(local_irq); } /** @@ -73,12 +143,17 @@ static int riscv_plic_is_edge_irq(uint32_t irq) */ void riscv_plic_irq_enable(uint32_t irq) { + const struct device *dev = get_plic_dev_from_irq(irq); + const struct plic_config *config = dev->config; + const uint32_t local_irq = irq_from_level_2(irq); + mem_addr_t en_addr = config->irq_en + local_irq_to_reg_offset(local_irq); + uint32_t en_value; uint32_t key; - volatile uint32_t *en = (volatile uint32_t *)PLIC_IRQ_EN; key = irq_lock(); - en += (irq >> 5); - *en |= (1 << (irq & 31)); + en_value = sys_read32(en_addr); + WRITE_BIT(en_value, local_irq & PLIC_REG_MASK, true); + sys_write32(en_value, en_addr); irq_unlock(key); } @@ -94,12 +169,17 @@ void riscv_plic_irq_enable(uint32_t irq) */ void riscv_plic_irq_disable(uint32_t irq) { + const struct device *dev = get_plic_dev_from_irq(irq); + const struct plic_config *config = dev->config; + const uint32_t local_irq = irq_from_level_2(irq); + mem_addr_t en_addr = config->irq_en + local_irq_to_reg_offset(local_irq); + uint32_t en_value; uint32_t key; - volatile uint32_t *en = (volatile uint32_t *)PLIC_IRQ_EN; key = irq_lock(); - en += (irq >> 5); - *en &= ~(1 << (irq & 31)); + en_value = sys_read32(en_addr); + WRITE_BIT(en_value, local_irq & PLIC_REG_MASK, false); + sys_write32(en_value, en_addr); irq_unlock(key); } @@ -113,10 +193,16 @@ void riscv_plic_irq_disable(uint32_t irq) */ int riscv_plic_irq_is_enabled(uint32_t irq) { - volatile uint32_t *en = (volatile uint32_t *)PLIC_IRQ_EN; + const struct device *dev = get_plic_dev_from_irq(irq); + const struct plic_config *config = dev->config; + const uint32_t local_irq = irq_from_level_2(irq); + mem_addr_t en_addr = config->irq_en + local_irq_to_reg_offset(local_irq); + uint32_t en_value; - en += (irq >> 5); - return !!(*en & (1 << (irq & 31))); + en_value = sys_read32(en_addr); + en_value &= BIT(local_irq & PLIC_REG_MASK); + + return !!en_value; } /** @@ -131,13 +217,15 @@ int riscv_plic_irq_is_enabled(uint32_t irq) */ void riscv_plic_set_priority(uint32_t irq, uint32_t priority) { - volatile uint32_t *prio = (volatile uint32_t *)PLIC_PRIO; + const struct device *dev = get_plic_dev_from_irq(irq); + const struct plic_config *config = dev->config; + const uint32_t local_irq = irq_from_level_2(irq); + mem_addr_t prio_addr = config->prio + (local_irq * sizeof(uint32_t)); - if (priority > PLIC_MAX_PRIO) - priority = PLIC_MAX_PRIO; + if (priority > config->max_prio) + priority = config->max_prio; - prio += irq; - *prio = priority; + sys_write32(priority, prio_addr); } /** @@ -146,24 +234,29 @@ void riscv_plic_set_priority(uint32_t irq, uint32_t priority) * This routine returns the RISCV PLIC-specific interrupt line causing an * interrupt. * + * @param dev Optional device pointer to get the interrupt line's controller + * * @return PLIC-specific interrupt line causing an interrupt. */ -int riscv_plic_get_irq(void) +unsigned int riscv_plic_get_irq(void) { return save_irq; } -static void plic_irq_handler(const void *arg) +const struct device *riscv_plic_get_dev(void) { - volatile struct plic_regs_t *regs = - (volatile struct plic_regs_t *) PLIC_REG; + return save_dev; +} - uint32_t irq; +static void plic_irq_handler(const struct device *dev) +{ + const struct plic_config *config = dev->config; + mem_addr_t claim_complete_addr = get_claim_complete_addr(dev); struct _isr_table_entry *ite; int edge_irq; /* Get the IRQ number generating the interrupt */ - irq = regs->claim_complete; + const uint32_t local_irq = sys_read32(claim_complete_addr); /* * Save IRQ in save_irq. To be used, if need be, by @@ -171,16 +264,17 @@ static void plic_irq_handler(const void *arg) * as IRQ number held by the claim_complete register is * cleared upon read. */ - save_irq = irq; + save_irq = local_irq; + save_dev = dev; /* * If the IRQ is out of range, call z_irq_spurious. * A call to z_irq_spurious will not return. */ - if (irq == 0U || irq >= PLIC_IRQS) + if (local_irq == 0U || local_irq >= config->num_irqs) z_irq_spurious(NULL); - edge_irq = riscv_plic_is_edge_irq(irq); + edge_irq = riscv_plic_is_edge_irq(dev, local_irq); /* * For edge triggered interrupts, write to the claim_complete register @@ -188,12 +282,17 @@ static void plic_irq_handler(const void *arg) * for edge triggered interrupts. */ if (edge_irq) - regs->claim_complete = save_irq; + sys_write32(local_irq, claim_complete_addr); - irq += CONFIG_2ND_LVL_ISR_TBL_OFFSET; + const uint32_t parent_irq = COND_CODE_1(IS_ENABLED(CONFIG_DYNAMIC_INTERRUPTS), + (z_get_sw_isr_irq_from_device(dev)), (0U)); + const uint32_t irq = irq_to_level_2(local_irq) | parent_irq; + const unsigned int isr_offset = + COND_CODE_1(IS_ENABLED(CONFIG_DYNAMIC_INTERRUPTS), (z_get_sw_isr_table_idx(irq)), + (irq_from_level_2(irq) + CONFIG_2ND_LVL_ISR_TBL_OFFSET)); /* Call the corresponding IRQ handler in _sw_isr_table */ - ite = (struct _isr_table_entry *)&_sw_isr_table[irq]; + ite = (struct _isr_table_entry *)&_sw_isr_table[isr_offset]; ite->isr(ite->arg); /* @@ -202,49 +301,69 @@ static void plic_irq_handler(const void *arg) * for level triggered interrupts. */ if (!edge_irq) - regs->claim_complete = save_irq; + sys_write32(local_irq, claim_complete_addr); } /** * @brief Initialize the Platform Level Interrupt Controller * + * @param dev PLIC device struct + * * @retval 0 on success. */ -static int plic_init(void) +static int plic_init(const struct device *dev) { - - volatile uint32_t *en = (volatile uint32_t *)PLIC_IRQ_EN; - volatile uint32_t *prio = (volatile uint32_t *)PLIC_PRIO; - volatile struct plic_regs_t *regs = - (volatile struct plic_regs_t *)PLIC_REG; - int i; + const struct plic_config *config = dev->config; + mem_addr_t en_addr = config->irq_en; + mem_addr_t prio_addr = config->prio; + mem_addr_t thres_prio_addr = get_threshold_priority_addr(dev); /* Ensure that all interrupts are disabled initially */ - for (i = 0; i < PLIC_EN_SIZE; i++) { - *en = 0U; - en++; + for (uint32_t i = 0; i < get_plic_enabled_size(dev); i++) { + sys_write32(0U, en_addr + (i * sizeof(uint32_t))); } /* Set priority of each interrupt line to 0 initially */ - for (i = 0; i < PLIC_IRQS; i++) { - *prio = 0U; - prio++; + for (uint32_t i = 0; i < config->num_irqs; i++) { + sys_write32(0U, prio_addr + (i * sizeof(uint32_t))); } /* Set threshold priority to 0 */ - regs->threshold_prio = 0U; - - /* Setup IRQ handler for PLIC driver */ - IRQ_CONNECT(RISCV_MACHINE_EXT_IRQ, - 0, - plic_irq_handler, - NULL, - 0); + sys_write32(0U, thres_prio_addr); - /* Enable IRQ for PLIC driver */ - irq_enable(RISCV_MACHINE_EXT_IRQ); + /* Configure IRQ for PLIC driver */ + config->irq_config_func(); return 0; } -SYS_INIT(plic_init, PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY); +#define PLIC_INTC_IRQ_FUNC_DECLARE(n) static void plic_irq_config_func_##n(void) + +#define PLIC_INTC_IRQ_FUNC_DEFINE(n) \ + static void plic_irq_config_func_##n(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), 0, plic_irq_handler, DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + } + +#define PLIC_INTC_CONFIG_INIT(n) \ + PLIC_INTC_IRQ_FUNC_DECLARE(n); \ + static const struct plic_config plic_config_##n = { \ + .prio = PLIC_BASE_ADDR(n) + PLIC_REG_PRIO_OFFSET, \ + .irq_en = PLIC_BASE_ADDR(n) + PLIC_REG_IRQ_EN_OFFSET, \ + .reg = PLIC_BASE_ADDR(n) + PLIC_REG_REGS_OFFSET, \ + .trig = PLIC_BASE_ADDR(n) + PLIC_REG_TRIG_TYPE_OFFSET, \ + .max_prio = DT_INST_PROP(n, riscv_max_priority), \ + .num_irqs = DT_INST_PROP(n, riscv_ndev), \ + .irq_config_func = plic_irq_config_func_##n, \ + }; \ + PLIC_INTC_IRQ_FUNC_DEFINE(n) + +#define PLIC_INTC_DEVICE_INIT(n) \ + PLIC_INTC_CONFIG_INIT(n) \ + DEVICE_DT_INST_DEFINE(n, &plic_init, NULL, \ + NULL, &plic_config_##n, \ + PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY, \ + NULL); + +DT_INST_FOREACH_STATUS_OKAY(PLIC_INTC_DEVICE_INIT) diff --git a/drivers/interrupt_controller/intc_ra_icu.c b/drivers/interrupt_controller/intc_ra_icu.c new file mode 100644 index 00000000000..167673f187f --- /dev/null +++ b/drivers/interrupt_controller/intc_ra_icu.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2023 TOKITTA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_ra_interrupt_controller_unit + +#include +#include +#include +#include +#include +#include + +#define IELSRn_REG(n) (DT_INST_REG_ADDR(0) + IELSRn_OFFSET + (n * 4)) +#define IRQCRi_REG(i) (DT_INST_REG_ADDR(0) + IRQCRi_OFFSET + (i)) + +#define IRQCRi_IRQMD_POS 0 +#define IRQCRi_IRQMD_MASK BIT_MASK(2) +#define IELSRn_IR_POS 16 +#define IELSRn_IR_MASK BIT_MASK(1) + +enum { + IRQCRi_OFFSET = 0x0, + IELSRn_OFFSET = 0x300, +}; + +int ra_icu_query_exists_irq(uint32_t event) +{ + for (uint32_t i = 0; i < CONFIG_NUM_IRQS; i++) { + uint32_t els = sys_read32(IELSRn_REG(i)) & UINT8_MAX; + + if (event == els) { + return i; + } + } + + return -EINVAL; +} + +int ra_icu_query_available_irq(uint32_t event) +{ + int irq = -EINVAL; + + if (ra_icu_query_exists_irq(event) > 0) { + return -EINVAL; + } + + for (uint32_t i = 0; i < CONFIG_NUM_IRQS; i++) { + if (_sw_isr_table[i].isr == z_irq_spurious) { + irq = i; + break; + } + } + + return irq; +} + +void ra_icu_clear_int_flag(unsigned int irqn) +{ + uint32_t cfg = sys_read32(IELSRn_REG(irqn)); + + sys_write32(cfg & ~BIT(IELSRn_IR_POS), IELSRn_REG(irqn)); +} + +void ra_icu_query_irq_config(unsigned int irq, uint32_t *intcfg, ra_isr_handler *cb, + const void **cbarg) +{ + *intcfg = sys_read32(IELSRn_REG(irq)); + *cb = _sw_isr_table[irq].isr; + *cbarg = (void *)_sw_isr_table[irq].arg; +} + +static void ra_icu_irq_configure(unsigned int irqn, uint32_t intcfg) +{ + uint8_t reg = sys_read8(IRQCRi_REG(irqn)) & ~(IRQCRi_IRQMD_MASK); + + sys_write8(reg | (intcfg & IRQCRi_IRQMD_MASK), IRQCRi_REG(irqn)); +} + +int ra_icu_irq_connect_dynamic(unsigned int irq, unsigned int priority, + void (*routine)(const void *parameter), const void *parameter, + uint32_t flags) +{ + uint32_t event = ((flags & RA_ICU_FLAG_EVENT_MASK) >> RA_ICU_FLAG_EVENT_OFFSET); + uint32_t intcfg = ((flags & RA_ICU_FLAG_INTCFG_MASK) >> RA_ICU_FLAG_INTCFG_OFFSET); + int irqn = irq; + + if (irq == RA_ICU_IRQ_UNSPECIFIED) { + irqn = ra_icu_query_available_irq(event); + if (irqn < 0) { + return irqn; + } + } + + irq_disable(irqn); + sys_write32(event, IELSRn_REG(irqn)); + z_isr_install(irqn, routine, parameter); + z_arm_irq_priority_set(irqn, priority, flags); + ra_icu_irq_configure(event, intcfg); + irq_enable(irqn); + + return irqn; +} + +DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, NULL, PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY, + NULL); diff --git a/drivers/interrupt_controller/intc_swerv_pic.c b/drivers/interrupt_controller/intc_swerv_pic.c index 65266cf8f9f..5c52ab49614 100644 --- a/drivers/interrupt_controller/intc_swerv_pic.c +++ b/drivers/interrupt_controller/intc_swerv_pic.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include @@ -143,7 +143,7 @@ static void swerv_pic_irq_handler(const void *arg) swerv_pic_write(SWERV_PIC_meigwclr(irq), 0); } -static int swerv_pic_init(void) +static int swerv_pic_init(const struct device *dev) { int i; @@ -236,4 +236,5 @@ int arch_irq_is_enabled(unsigned int irq) return !!(mie & (1 << irq)); } -SYS_INIT(swerv_pic_init, PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY); +DEVICE_DT_INST_DEFINE(0, swerv_pic_init, NULL, NULL, NULL, + PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY, NULL); diff --git a/drivers/interrupt_controller/intc_vexriscv_litex.c b/drivers/interrupt_controller/intc_vexriscv_litex.c index 719bd98ec36..efec4d2478e 100644 --- a/drivers/interrupt_controller/intc_vexriscv_litex.c +++ b/drivers/interrupt_controller/intc_vexriscv_litex.c @@ -4,17 +4,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define DT_DRV_COMPAT litex_eth0 +#define DT_DRV_COMPAT vexriscv_intc0 #include #include -#include #include #include #include -#define IRQ_MASK DT_REG_ADDR_BY_NAME(DT_INST(0, vexriscv_intc0), irq_mask) -#define IRQ_PENDING DT_REG_ADDR_BY_NAME(DT_INST(0, vexriscv_intc0), irq_pending) +#define IRQ_MASK DT_INST_REG_ADDR_BY_NAME(0, irq_mask) +#define IRQ_PENDING DT_INST_REG_ADDR_BY_NAME(0, irq_pending) #define TIMER0_IRQ DT_IRQN(DT_INST(0, litex_timer0)) #define UART0_IRQ DT_IRQN(DT_INST(0, litex_uart0)) @@ -120,7 +119,7 @@ int arch_irq_is_enabled(unsigned int irq) return vexriscv_litex_irq_getmask() & (1 << irq); } -static int vexriscv_litex_irq_init(void) +static int vexriscv_litex_irq_init(const struct device *dev) { __asm__ volatile ("csrrs x0, mie, %0" :: "r"(1 << RISCV_MACHINE_EXT_IRQ)); @@ -131,5 +130,5 @@ static int vexriscv_litex_irq_init(void) return 0; } -SYS_INIT(vexriscv_litex_irq_init, PRE_KERNEL_2, - CONFIG_INTC_INIT_PRIORITY); +DEVICE_DT_INST_DEFINE(0, vexriscv_litex_irq_init, NULL, NULL, NULL, + PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY, NULL); diff --git a/drivers/interrupt_controller/intc_vim.c b/drivers/interrupt_controller/intc_vim.c index df4eb4a9605..01d2633413d 100644 --- a/drivers/interrupt_controller/intc_vim.c +++ b/drivers/interrupt_controller/intc_vim.c @@ -8,7 +8,7 @@ #include -#include +#include #include #include #include diff --git a/drivers/interrupt_controller/intc_wkpu_nxp_s32.c b/drivers/interrupt_controller/intc_wkpu_nxp_s32.c new file mode 100644 index 00000000000..5a3a7b5b075 --- /dev/null +++ b/drivers/interrupt_controller/intc_wkpu_nxp_s32.c @@ -0,0 +1,194 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_s32_wkpu + +#include +#include +#include +#include +#include + +#include + +#define NXP_S32_NUM_CHANNELS WKPU_IP_NUM_OF_CHANNELS +#define NXP_S32_NUM_CHANNELS_DEBRACKET __DEBRACKET WKPU_IP_NUM_OF_CHANNELS + +struct wkpu_nxp_s32_config { + uint8_t instance; + + const WKPU_Type *base; + + const Wkpu_Ip_IrqConfigType *wkpu_cfg; +}; + +/* Wrapper callback for each WKPU line, from low level driver callback to GPIO callback */ +struct wkpu_nxp_s32_cb { + wkpu_nxp_s32_callback_t cb; + uint8_t pin; + void *data; +}; + +struct wkpu_nxp_s32_data { + struct wkpu_nxp_s32_cb *cb; +}; + +int wkpu_nxp_s32_set_callback(const struct device *dev, uint8_t line, + wkpu_nxp_s32_callback_t cb, uint8_t pin, void *arg) +{ + struct wkpu_nxp_s32_data *data = dev->data; + + __ASSERT(line < NXP_S32_NUM_CHANNELS, "Interrupt line is out of range"); + + if (data->cb[line].cb) { + return -EBUSY; + } + + data->cb[line].cb = cb; + data->cb[line].pin = pin; + data->cb[line].data = arg; + + return 0; +} + +void wkpu_nxp_s32_unset_callback(const struct device *dev, uint8_t line) +{ + struct wkpu_nxp_s32_data *data = dev->data; + + __ASSERT(line < NXP_S32_NUM_CHANNELS, "Interrupt line is out of range"); + + data->cb[line].cb = NULL; + data->cb[line].pin = 0; + data->cb[line].data = NULL; +} + +void wkpu_nxp_s32_enable_interrupt(const struct device *dev, uint8_t line, + Wkpu_Ip_EdgeType edge_type) +{ + const struct wkpu_nxp_s32_config *config = dev->config; + + __ASSERT(line < NXP_S32_NUM_CHANNELS, "Interrupt line is out of range"); + + Wkpu_Ip_SetActivationCondition(config->instance, line, edge_type); + Wkpu_Ip_EnableNotification(line); + Wkpu_Ip_EnableInterrupt(config->instance, line); +} + +void wkpu_nxp_s32_disable_interrupt(const struct device *dev, uint8_t line) +{ + const struct wkpu_nxp_s32_config *config = dev->config; + + __ASSERT(line < NXP_S32_NUM_CHANNELS, "Interrupt line is out of range"); + + Wkpu_Ip_DisableInterrupt(config->instance, line); + Wkpu_Ip_DisableNotification(line); + Wkpu_Ip_SetActivationCondition(config->instance, line, WKPU_IP_NONE_EDGE); +} + +uint64_t wkpu_nxp_s32_get_pending(const struct device *dev) +{ + const struct wkpu_nxp_s32_config *config = dev->config; + uint64_t flags; + + flags = config->base->WISR & config->base->IRER; +#if defined(WKPU_IP_64_CH_USED) && (WKPU_IP_64_CH_USED == STD_ON) + flags |= ((uint64_t)(config->base->WISR_64 & config->base->IRER_64)) << 32U; +#endif + + return flags; +} + +static void wkpu_nxp_s32_callback(const struct device *dev, uint8 line) +{ + const struct wkpu_nxp_s32_data *data = dev->data; + + if (data->cb[line].cb != NULL) { + data->cb[line].cb(data->cb[line].pin, data->cb[line].data); + } +} + +static int wkpu_nxp_s32_init(const struct device *dev) +{ + const struct wkpu_nxp_s32_config *config = dev->config; + + if (Wkpu_Ip_Init(config->instance, config->wkpu_cfg)) { + return -EINVAL; + } + + return 0; +} + +#define WKPU_NXP_S32_CALLBACK(line, n) \ + void nxp_s32_wkpu_##n##wkpu_line_##line##_callback(void) \ + { \ + const struct device *dev = DEVICE_DT_INST_GET(n); \ + \ + wkpu_nxp_s32_callback(dev, line); \ + } + +#define WKPU_NXP_S32_CHANNEL_CONFIG(idx, n) \ + { \ + .hwChannel = idx, \ + .filterEn = DT_INST_PROP_OR(DT_INST_CHILD(n, line_##idx), filter_enable, 0), \ + .edgeEvent = WKPU_IP_NONE_EDGE, \ + .WkpuChannelNotification = nxp_s32_wkpu_##n##wkpu_line_##idx##_callback, \ + .callback = NULL, \ + .callbackParam = 0U \ + } + +#define WKPU_NXP_S32_CHANNELS_CONFIG(n) \ + static const Wkpu_Ip_ChannelConfigType wkpu_##n##_channel_nxp_s32_cfg[] = { \ + LISTIFY(NXP_S32_NUM_CHANNELS_DEBRACKET, WKPU_NXP_S32_CHANNEL_CONFIG, (,), n) \ + } + +#define WKPU_NXP_S32_INSTANCE_CONFIG(n) \ + static const Wkpu_Ip_IrqConfigType wkpu_##n##_nxp_s32_cfg = { \ + .numChannels = NXP_S32_NUM_CHANNELS, \ + .pChannelsConfig = &wkpu_##n##_channel_nxp_s32_cfg, \ + } + +#define WKPU_NXP_S32_CONFIG(n) \ + LISTIFY(NXP_S32_NUM_CHANNELS_DEBRACKET, WKPU_NXP_S32_CALLBACK, (), n) \ + WKPU_NXP_S32_CHANNELS_CONFIG(n); \ + WKPU_NXP_S32_INSTANCE_CONFIG(n); + +#define WKPU_NXP_S32_INIT_DEVICE(n) \ + WKPU_NXP_S32_CONFIG(n) \ + static const struct wkpu_nxp_s32_config wkpu_nxp_s32_conf_##n = { \ + .instance = n, \ + .base = (WKPU_Type *)DT_INST_REG_ADDR(n), \ + .wkpu_cfg = (Wkpu_Ip_IrqConfigType *)&wkpu_##n##_nxp_s32_cfg, \ + }; \ + static struct wkpu_nxp_s32_cb wkpu_nxp_s32_cb_##n[NXP_S32_NUM_CHANNELS]; \ + static struct wkpu_nxp_s32_data wkpu_nxp_s32_data_##n = { \ + .cb = wkpu_nxp_s32_cb_##n, \ + }; \ + static int wkpu_nxp_s32_init##n(const struct device *dev) \ + { \ + int err; \ + \ + err = wkpu_nxp_s32_init(dev); \ + if (err) { \ + return err; \ + } \ + \ + IRQ_CONNECT(DT_INST_IRQ(n, irq), DT_INST_IRQ(n, priority), \ + WKPU_EXT_IRQ_SINGLE_ISR, NULL, \ + COND_CODE_1(CONFIG_GIC, (DT_INST_IRQ(n, flags)), (0))); \ + irq_enable(DT_INST_IRQ(n, irq)); \ + \ + return 0; \ + } \ + DEVICE_DT_INST_DEFINE(n, \ + wkpu_nxp_s32_init##n, \ + NULL, \ + &wkpu_nxp_s32_data_##n, \ + &wkpu_nxp_s32_conf_##n, \ + PRE_KERNEL_2, \ + CONFIG_INTC_INIT_PRIORITY, \ + NULL); + +DT_INST_FOREACH_STATUS_OKAY(WKPU_NXP_S32_INIT_DEVICE) diff --git a/drivers/ipm/CMakeLists.txt b/drivers/ipm/CMakeLists.txt index f2d37bb67c9..cc79cce4f83 100644 --- a/drivers/ipm/CMakeLists.txt +++ b/drivers/ipm/CMakeLists.txt @@ -6,14 +6,14 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_IPM_MCUX ipm_mcux.c) zephyr_library_sources_ifdef(CONFIG_IPM_IMX ipm_imx.c) -zephyr_library_sources_ifdef(CONFIG_IPM_IMX_REV2 ipm_imx.c) zephyr_library_sources_ifdef(CONFIG_IPM_MHU ipm_mhu.c) zephyr_library_sources_ifdef(CONFIG_IPM_STM32_IPCC ipm_stm32_ipcc.c) zephyr_library_sources_ifdef(CONFIG_IPM_NRFX ipm_nrfx_ipc.c) -zephyr_library_sources_ifdef(CONFIG_IPM_CAVS_IDC ipm_cavs_idc.c) zephyr_library_sources_ifdef(CONFIG_IPM_STM32_HSEM ipm_stm32_hsem.c) zephyr_library_sources_ifdef(CONFIG_IPM_CAVS_HOST ipm_cavs_host.c) +zephyr_library_sources_ifdef(CONFIG_IPM_SEDI ipm_sedi.c) +zephyr_library_sources_ifdef(CONFIG_IPM_IVSHMEM ipm_ivshmem.c) zephyr_library_sources_ifdef(CONFIG_ESP32_SOFT_IPM ipm_esp32.c) zephyr_library_sources_ifdef(CONFIG_XLNX_IPI ipm_xlnx_ipi.c) + zephyr_library_sources_ifdef(CONFIG_USERSPACE ipm_handlers.c) -zephyr_library_sources_ifdef(CONFIG_IPM_IVSHMEM ipm_ivshmem.c) diff --git a/drivers/ipm/Kconfig b/drivers/ipm/Kconfig index 17c92b7e241..81c64202427 100644 --- a/drivers/ipm/Kconfig +++ b/drivers/ipm/Kconfig @@ -60,6 +60,7 @@ source "drivers/ipm/Kconfig.imx" source "drivers/ipm/Kconfig.stm32" source "drivers/ipm/Kconfig.intel_adsp" source "drivers/ipm/Kconfig.ivshmem" +source "drivers/ipm/Kconfig.sedi" module = IPM diff --git a/drivers/ipm/Kconfig.imx b/drivers/ipm/Kconfig.imx index 503d32b708c..67fbc370ac8 100644 --- a/drivers/ipm/Kconfig.imx +++ b/drivers/ipm/Kconfig.imx @@ -15,17 +15,11 @@ config IPM_IMX help Driver for NXP i.MX messaging unit -config IPM_IMX_REV2 - bool "IMX IPM driver (rev 2)" - default y - depends on DT_HAS_NXP_IMX_MU_REV2_ENABLED - help - Rev 2 driver for NXP i.MX messaging unit (MCUX-based) +if IPM_IMX choice prompt "IMX IPM max data size" default IPM_IMX_MAX_DATA_SIZE_16 - depends on IPM_IMX || IPM_IMX_REV2 help Select maximum message size for NXP i.MX messaging unit. @@ -55,7 +49,6 @@ config IPM_IMX_MAX_DATA_SIZE default 4 if IPM_IMX_MAX_DATA_SIZE_4 default 8 if IPM_IMX_MAX_DATA_SIZE_8 default 16 if IPM_IMX_MAX_DATA_SIZE_16 - depends on IPM_IMX || IPM_IMX_REV2 config IPM_IMX_MAX_ID_VAL int @@ -63,4 +56,10 @@ config IPM_IMX_MAX_ID_VAL default 3 if IPM_IMX_MAX_DATA_SIZE_4 default 1 if IPM_IMX_MAX_DATA_SIZE_8 default 0 if IPM_IMX_MAX_DATA_SIZE_16 - depends on IPM_IMX || IPM_IMX_REV2 + +config IPM_IMX_FW_READY_REPLY + bool "Send FW_READY reply message" + help + Send FW_READY reply to check for FW boot completion + +endif # IPM_IMX diff --git a/drivers/ipm/Kconfig.intel_adsp b/drivers/ipm/Kconfig.intel_adsp index 9a8880fc0e4..dbf6cdf91f2 100644 --- a/drivers/ipm/Kconfig.intel_adsp +++ b/drivers/ipm/Kconfig.intel_adsp @@ -1,14 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2022, Intel Corporation -config IPM_CAVS_IDC - bool "CAVS DSP Intra-DSP Communication (IDC) driver" - default y if MP_NUM_CPUS > 1 && SMP - depends on CAVS_ICTL && DT_HAS_INTEL_ADSP_IDC_ENABLED - help - Driver for the Intra-DSP Communication (IDC) channel for - cross SoC communications. - config IPM_CALLBACK_ASYNC bool "Deliver callbacks asynchronously" default y if IPM_CAVS_HOST diff --git a/drivers/ipm/Kconfig.sedi b/drivers/ipm/Kconfig.sedi new file mode 100644 index 00000000000..bbb347dd5f4 --- /dev/null +++ b/drivers/ipm/Kconfig.sedi @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2023 Intel Corporation + +config IPM_SEDI + bool "Intel SEDI IPM Driver" + default y if DT_HAS_INTEL_SEDI_IPM_ENABLED + select IPM_CALLBACK_ASYNC + help + This option enables the Intel SEDI IPM(IPC) driver. + This driver is simply a shim driver built upon the SEDI + bare metal IPC driver in the hal-intel module diff --git a/drivers/ipm/ipm_cavs_host.c b/drivers/ipm/ipm_cavs_host.c index 308acd8a9a2..5877309d48d 100644 --- a/drivers/ipm/ipm_cavs_host.c +++ b/drivers/ipm/ipm_cavs_host.c @@ -56,7 +56,7 @@ static int send(const struct device *dev, int wait, uint32_t id, return -EBUSY; } - if (size > MAX_MSG) { + if ((size < 0) || (size > MAX_MSG)) { return -EMSGSIZE; } diff --git a/drivers/ipm/ipm_cavs_idc.c b/drivers/ipm/ipm_cavs_idc.c deleted file mode 100644 index 5793d2e4b70..00000000000 --- a/drivers/ipm/ipm_cavs_idc.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 2020 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include -#include -#include - -#include -#include -#include "ipm_cavs_idc.h" - -#ifdef CONFIG_SCHED_IPI_SUPPORTED -extern void z_sched_ipi(void); -#endif - -struct cavs_idc_data { - ipm_callback_t cb; - void *user_data; -}; - -static struct cavs_idc_data cavs_idc_device_data; - -static void cavs_idc_isr(const struct device *dev) -{ - struct cavs_idc_data *drv_data = dev->data; - - uint32_t i, id; - void *ext; - uint32_t idctfc; - uint32_t curr_cpu_id = arch_curr_cpu()->id; -#ifdef CONFIG_SCHED_IPI_SUPPORTED - bool do_sched_ipi = false; -#endif - - unsigned int num_cpus = arch_num_cpus(); - - for (i = 0; i < num_cpus; i++) { - if (i == curr_cpu_id) { - /* skip current core */ - continue; - } - - idctfc = idc_read(IPC_IDCTFC(i), curr_cpu_id); - - if ((idctfc & IPC_IDCTFC_BUSY) == 0) { - /* No message from this core */ - continue; - } - - /* Extract the message */ - id = idctfc & IPC_IDCTFC_MSG_MASK; - - switch (id) { -#ifdef CONFIG_SCHED_IPI_SUPPORTED - case IPM_CAVS_IDC_MSG_SCHED_IPI_ID: - do_sched_ipi = true; - break; -#endif - default: - if (drv_data->cb != NULL) { - ext = UINT_TO_POINTER( - idc_read(IPC_IDCTEFC(i), curr_cpu_id) & - IPC_IDCTEFC_MSG_MASK); - drv_data->cb(dev, drv_data->user_data, id, ext); - } - break; - } - - /* Reset busy bit by writing to it */ - idctfc |= IPC_IDCTFC_BUSY; - idc_write(IPC_IDCTFC(i), curr_cpu_id, idctfc); - } -#ifdef CONFIG_SCHED_IPI_SUPPORTED - if (do_sched_ipi) { - z_sched_ipi(); - } -#endif -} - -static int cavs_idc_send(const struct device *dev, int wait, uint32_t id, - const void *data, int size) -{ - uint32_t curr_cpu_id = arch_curr_cpu()->id; - uint32_t ext = POINTER_TO_UINT(data); - uint32_t reg; - bool busy; - int i; - - if ((wait != 0) || (size != 0)) { - return -ENOTSUP; - } - - /* Check if any core is still busy */ - busy = false; - unsigned int num_cpus = arch_num_cpus(); - - for (i = 0; i < num_cpus; i++) { - if (i == curr_cpu_id) { - /* skip current core */ - continue; - } - - reg = idc_read(IPC_IDCITC(i), curr_cpu_id); - if ((reg & IPC_IDCITC_BUSY) != 0) { - busy = true; - break; - } - } - - /* Can't send if busy */ - if (busy) { - return -EBUSY; - } - - id &= IPC_IDCITC_MSG_MASK; - ext &= IPC_IDCIETC_MSG_MASK; - ext |= IPC_IDCIETC_DONE; /* always clear DONE bit */ - - for (i = 0; i < num_cpus; i++) { - if (i == curr_cpu_id) { - /* skip current core */ - continue; - } - - idc_write(IPC_IDCIETC(i), curr_cpu_id, ext); - idc_write(IPC_IDCITC(i), curr_cpu_id, id | IPC_IDCITC_BUSY); - } - - return 0; -} - -static int cavs_idc_max_data_size_get(const struct device *dev) -{ - ARG_UNUSED(dev); - - /* IDC can send an ID (of 31 bits, the header) and - * another data of 30 bits (the extension). It cannot - * send a whole message over. Best we can do is send - * a 4-byte aligned pointer. - * - * So return 0 here for max data size. - */ - - return 0; -} - -static uint32_t cavs_idc_max_id_val_get(const struct device *dev) -{ - ARG_UNUSED(dev); - - return IPM_CAVS_IDC_ID_MASK; -} - -static void cavs_idc_register_callback(const struct device *dev, - ipm_callback_t cb, - void *user_data) -{ - struct cavs_idc_data *drv_data = dev->data; - - drv_data->cb = cb; - drv_data->user_data = user_data; -} - -static int cavs_idc_set_enabled(const struct device *dev, int enable) -{ - int i, j; - uint32_t mask; - -#ifdef CONFIG_SCHED_IPI_SUPPORTED - /* With scheduler IPI, IDC must always be enabled. */ - if (enable == 0) { - return -ENOTSUP; - } -#endif - - unsigned int num_cpus = arch_num_cpus(); - - for (i = 0; i < num_cpus; i++) { - mask = 0; - - if (enable) { - for (j = 0; j < num_cpus; j++) { - if (i == j) { - continue; - } - - mask |= IPC_IDCCTL_IDCTBIE(j); - } - } - - idc_write(IPC_IDCCTL, i, mask); - - /* FIXME: when we have API to enable IRQ on specific core. */ - sys_set_bit(DT_REG_ADDR(DT_NODELABEL(cavs_intc0)) + 0x04 + - CAVS_ICTL_INT_CPU_OFFSET(i), - CAVS_IRQ_NUMBER(DT_INST_IRQN(0))); - } - - return 0; -} - -static int cavs_idc_init(const struct device *dev) -{ - IRQ_CONNECT(DT_INST_IRQN(0), - DT_INST_IRQ(0, priority), - cavs_idc_isr, DEVICE_DT_INST_GET(0), 0); - - irq_enable(DT_INST_IRQN(0)); - - return 0; -} - -static const struct ipm_driver_api cavs_idc_driver_api = { - .send = cavs_idc_send, - .register_callback = cavs_idc_register_callback, - .max_data_size_get = cavs_idc_max_data_size_get, - .max_id_val_get = cavs_idc_max_id_val_get, - .set_enabled = cavs_idc_set_enabled, -}; - -DEVICE_DT_INST_DEFINE(0, &cavs_idc_init, NULL, - &cavs_idc_device_data, NULL, - PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, - &cavs_idc_driver_api); - -#ifdef CONFIG_SCHED_IPI_SUPPORTED -int cavs_idc_smp_init(void) -{ - /* Enable IDC for scheduler IPI */ - cavs_idc_set_enabled(dev, 1); - - return 0; -} - -#ifndef CONFIG_SMP_BOOT_DELAY -SYS_INIT(cavs_idc_smp_init, SMP, 0); -#endif -#endif diff --git a/drivers/ipm/ipm_cavs_idc.h b/drivers/ipm/ipm_cavs_idc.h deleted file mode 100644 index e9ce493d880..00000000000 --- a/drivers/ipm/ipm_cavs_idc.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2020 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_DRIVERS_IPM_IPM_CAVS_IDC_H_ -#define ZEPHYR_DRIVERS_IPM_IPM_CAVS_IDC_H_ - -#define DT_DRV_COMPAT intel_adsp_idc -#include - -/* Redeclaration of the earlier IDC register API for platforms being - * held back on this driver. - */ -# ifndef IPC_DSP_BASE -# define IPC_DSP_BASE(core) (INTEL_ADSP_IDC_REG_ADDRESS + 0x80 * (core)) -# endif -#define IPC_IDCTFC(x) (x * 0x10) -#define IPC_IDCTFC_BUSY BIT(31) -#define IPC_IDCTFC_MSG_MASK 0x7FFFFFFF -#define IPC_IDCTEFC(x) (0x4 + x * 0x10) -#define IPC_IDCTEFC_MSG_MASK 0x3FFFFFFF -#define IPC_IDCITC(x) (0x8 + x * 0x10) -#define IPC_IDCITC_MSG_MASK 0x7FFFFFFF -#define IPC_IDCITC_BUSY BIT(31) -#define IPC_IDCIETC(x) (0xc + x * 0x10) -#define IPC_IDCIETC_MSG_MASK 0x3FFFFFFF -#define IPC_IDCIETC_DONE BIT(30) -#define IPC_IDCCTL 0x50 -#define IPC_IDCCTL_IDCTBIE(x) BIT(x) - -#define IPM_CAVS_IDC_ID_MASK \ - (CAVS_IDC_TYPE(CAVS_IDC_TYPE_MASK) | \ - CAVS_IDC_HEADER(CAVS_IDC_HEADER_MASK)) - -/* IDC message type. */ -#define CAVS_IDC_TYPE_SHIFT 24U -#define CAVS_IDC_TYPE_MASK 0x7FU -#define CAVS_IDC_TYPE(x) \ - (((x) & CAVS_IDC_TYPE_MASK) << CAVS_IDC_TYPE_SHIFT) - -/* IDC message header. */ -#define CAVS_IDC_HEADER_MASK 0xFFFFFFU -#define CAVS_IDC_HEADER(x) ((x) & CAVS_IDC_HEADER_MASK) - -/* IDC message extension. */ -#define CAVS_IDC_EXTENSION_MASK 0x3FFFFFFFU -#define CAVS_IDC_EXTENSION(x) ((x) & CAVS_IDC_EXTENSION_MASK) - -/* Scheduler IPI message (type 0x7F, header 'IPI' in ascii) */ -#define IPM_CAVS_IDC_MSG_SCHED_IPI_DATA 0 -#define IPM_CAVS_IDC_MSG_SCHED_IPI_ID \ - (CAVS_IDC_TYPE(0x7FU) | CAVS_IDC_HEADER(0x495049U)) - -static inline uint32_t idc_read(uint32_t reg, uint32_t core_id) -{ - return *((volatile uint32_t*)(IPC_DSP_BASE(core_id) + reg)); -} - -static inline void idc_write(uint32_t reg, uint32_t core_id, uint32_t val) -{ - *((volatile uint32_t*)(IPC_DSP_BASE(core_id) + reg)) = val; -} - -int cavs_idc_smp_init(const struct device *dev); - -#endif /* ZEPHYR_DRIVERS_IPM_IPM_CAVS_IDC_H_ */ diff --git a/drivers/ipm/ipm_esp32.c b/drivers/ipm/ipm_esp32.c index 9f7e6063519..cbe6e42d90f 100644 --- a/drivers/ipm/ipm_esp32.c +++ b/drivers/ipm/ipm_esp32.c @@ -54,9 +54,17 @@ IRAM_ATTR static void esp32_ipm_isr(const struct device *dev) /* clear interrupt flag */ if (core_id == 0) { +#if defined(CONFIG_SOC_SERIES_ESP32) || defined(CONFIG_SOC_SERIES_ESP32_NET) DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, 0); +#elif defined(CONFIG_SOC_SERIES_ESP32S3) + WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, 0); +#endif } else { +#if defined(CONFIG_SOC_SERIES_ESP32) || defined(CONFIG_SOC_SERIES_ESP32_NET) DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_1_REG, 0); +#elif defined(CONFIG_SOC_SERIES_ESP32S3) + WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_1_REG, 0); +#endif } /* first of all take the own of the shared memory */ @@ -130,12 +138,21 @@ static int esp32_ipm_send(const struct device *dev, int wait, uint32_t id, memcpy(dev_data->shm.app_cpu_shm, data, size); atomic_set(&dev_data->control->lock, ESP32_IPM_LOCK_FREE_VAL); LOG_DBG("Generating interrupt on remote CPU 1 from CPU 0"); +#if defined(CONFIG_SOC_SERIES_ESP32) || defined(CONFIG_SOC_SERIES_ESP32_NET) DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_1_REG, DPORT_CPU_INTR_FROM_CPU_1); +#elif defined(CONFIG_SOC_SERIES_ESP32S3) + WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_1_REG, SYSTEM_CPU_INTR_FROM_CPU_1); +#endif + } else { memcpy(dev_data->shm.pro_cpu_shm, data, size); atomic_set(&dev_data->control->lock, ESP32_IPM_LOCK_FREE_VAL); LOG_DBG("Generating interrupt on remote CPU 0 from CPU 1"); +#if defined(CONFIG_SOC_SERIES_ESP32) || defined(CONFIG_SOC_SERIES_ESP32_NET) DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, DPORT_CPU_INTR_FROM_CPU_0); +#elif defined(CONFIG_SOC_SERIES_ESP32S3) + WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, SYSTEM_CPU_INTR_FROM_CPU_0); +#endif } irq_unlock(key); @@ -217,7 +234,6 @@ static int esp32_ipm_init(const struct device *dev) NULL); LOG_DBG("Waiting CPU0 to sync"); - while (!atomic_cas(&data->control->lock, ESP32_IPM_LOCK_FREE_VAL, data->this_core_id)) ; diff --git a/drivers/ipm/ipm_handlers.c b/drivers/ipm/ipm_handlers.c index 647f87c543f..259644ae8d0 100644 --- a/drivers/ipm/ipm_handlers.c +++ b/drivers/ipm/ipm_handlers.c @@ -4,15 +4,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include static inline int z_vrfy_ipm_send(const struct device *dev, int wait, uint32_t id, const void *data, int size) { - Z_OOPS(Z_SYSCALL_DRIVER_IPM(dev, send)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(data, size)); + K_OOPS(K_SYSCALL_DRIVER_IPM(dev, send)); + K_OOPS(K_SYSCALL_MEMORY_READ(data, size)); return z_impl_ipm_send((const struct device *)dev, wait, id, (const void *)data, size); } @@ -20,21 +20,21 @@ static inline int z_vrfy_ipm_send(const struct device *dev, int wait, static inline int z_vrfy_ipm_max_data_size_get(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_IPM(dev, max_data_size_get)); + K_OOPS(K_SYSCALL_DRIVER_IPM(dev, max_data_size_get)); return z_impl_ipm_max_data_size_get((const struct device *)dev); } #include static inline uint32_t z_vrfy_ipm_max_id_val_get(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_IPM(dev, max_id_val_get)); + K_OOPS(K_SYSCALL_DRIVER_IPM(dev, max_id_val_get)); return z_impl_ipm_max_id_val_get((const struct device *)dev); } #include static inline int z_vrfy_ipm_set_enabled(const struct device *dev, int enable) { - Z_OOPS(Z_SYSCALL_DRIVER_IPM(dev, set_enabled)); + K_OOPS(K_SYSCALL_DRIVER_IPM(dev, set_enabled)); return z_impl_ipm_set_enabled((const struct device *)dev, enable); } #include diff --git a/drivers/ipm/ipm_imx.c b/drivers/ipm/ipm_imx.c index c38117cbde5..7a4b3b1e210 100644 --- a/drivers/ipm/ipm_imx.c +++ b/drivers/ipm/ipm_imx.c @@ -1,9 +1,10 @@ /* - * Copyright (c) 2018, NXP + * Copyright 2018,2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ +#define DT_DRV_COMPAT nxp_imx_mu #include #include @@ -12,11 +13,11 @@ #include #include #include -#if defined(CONFIG_IPM_IMX_REV2) -#define DT_DRV_COMPAT nxp_imx_mu_rev2 + +#ifdef CONFIG_HAS_MCUX +/* MCUX HAL uses a different header file than the i.MX HAL for this IP block */ #include "fsl_mu.h" #else -#define DT_DRV_COMPAT nxp_imx_mu #include #endif @@ -38,7 +39,7 @@ struct imx_mu_data { void *user_data; }; -#if defined(CONFIG_IPM_IMX_REV2) +#if defined(CONFIG_HAS_MCUX) /*! * @brief Check RX full status. * @@ -127,7 +128,7 @@ static void imx_mu_isr(const struct device *dev) } if (all_registers_full) { for (i = 0; i < IMX_IPM_DATA_REGS; i++) { -#if defined(CONFIG_IPM_IMX_REV2) +#if defined(CONFIG_HAS_MCUX) data32[i] = MU_ReceiveMsg(base, (id * IMX_IPM_DATA_REGS) + i); #else @@ -165,8 +166,8 @@ static int imx_mu_ipm_send(const struct device *dev, int wait, uint32_t id, { const struct imx_mu_config *config = dev->config; MU_Type *base = MU(config); - uint32_t data32[IMX_IPM_DATA_REGS]; -#if !IS_ENABLED(CONFIG_IPM_IMX_REV2) + uint32_t data32[IMX_IPM_DATA_REGS] = {0}; +#if !IS_ENABLED(CONFIG_HAS_MCUX) mu_status_t status; #endif int i; @@ -175,14 +176,14 @@ static int imx_mu_ipm_send(const struct device *dev, int wait, uint32_t id, return -EINVAL; } - if (size > CONFIG_IPM_IMX_MAX_DATA_SIZE) { + if ((size < 0) || (size > CONFIG_IPM_IMX_MAX_DATA_SIZE)) { return -EMSGSIZE; } /* Actual message is passing using 32 bits registers */ memcpy(data32, data, size); -#if defined(CONFIG_IPM_IMX_REV2) +#if defined(CONFIG_HAS_MCUX) if (wait) { for (i = 0; i < IMX_IPM_DATA_REGS; i++) { MU_SendMsgNonBlocking(base, id * IMX_IPM_DATA_REGS + i, @@ -249,7 +250,7 @@ static int imx_mu_ipm_set_enabled(const struct device *dev, int enable) { const struct imx_mu_config *config = dev->config; MU_Type *base = MU(config); -#if defined(CONFIG_IPM_IMX_REV2) +#if defined(CONFIG_HAS_MCUX) #if CONFIG_IPM_IMX_MAX_DATA_SIZE_4 if (enable) { MU_EnableInterrupts(base, kMU_Rx0FullInterruptEnable); @@ -321,6 +322,22 @@ static int imx_mu_init(const struct device *dev) MU_Init(MU(config)); config->irq_config_func(dev); +#if defined(CONFIG_IPM_IMX_FW_READY_REPLY) + /* Send FW_READY reply message - this is used on host side, + * for handshake communication. + * + * An example is in Linux, imx_dsp_rproc driver, where + * after starting the remote processor, the host is waiting for a + * FW_READY reply. + */ + MU_Type * base = MU(config); + + MU_TriggerInterrupts(base, kMU_GenInt0InterruptTrigger | + kMU_GenInt1InterruptTrigger | + kMU_GenInt2InterruptTrigger | + kMU_GenInt3InterruptTrigger); +#endif + return 0; } diff --git a/drivers/ipm/ipm_ivshmem.c b/drivers/ipm/ipm_ivshmem.c index deda3f51950..46e009fb634 100644 --- a/drivers/ipm/ipm_ivshmem.c +++ b/drivers/ipm/ipm_ivshmem.c @@ -102,7 +102,7 @@ static int ivshmem_ipm_init(const struct device *dev) k_thread_create(&ivshmem_ev_loop_thread, ivshmem_ev_loop_stack, CONFIG_IPM_IVSHMEM_EVENT_LOOP_STACK_SIZE, - (k_thread_entry_t)ivshmem_ipm_event_loop_thread, + ivshmem_ipm_event_loop_thread, (void *)dev, NULL, NULL, CONFIG_IPM_IVSHMEM_EVENT_LOOP_PRIO, 0, K_NO_WAIT); diff --git a/drivers/ipm/ipm_mcux.c b/drivers/ipm/ipm_mcux.c index 176b858f20a..2365f58aacc 100644 --- a/drivers/ipm/ipm_mcux.c +++ b/drivers/ipm/ipm_mcux.c @@ -81,9 +81,8 @@ static int mcux_mailbox_ipm_send(const struct device *d, int wait, { const struct mcux_mailbox_config *config = d->config; MAILBOX_Type *base = config->base; - uint32_t data32[MCUX_IPM_DATA_REGS]; /* Until we change API - * to uint32_t array - */ + /* Until we change API to uint32_t array */ + uint32_t data32[MCUX_IPM_DATA_REGS] = {0}; unsigned int flags; int i; @@ -93,7 +92,7 @@ static int mcux_mailbox_ipm_send(const struct device *d, int wait, return -EINVAL; } - if (size > MCUX_IPM_DATA_REGS * sizeof(uint32_t)) { + if ((size < 0) || (size > MCUX_IPM_DATA_REGS * sizeof(uint32_t))) { return -EMSGSIZE; } diff --git a/drivers/ipm/ipm_sedi.c b/drivers/ipm/ipm_sedi.c new file mode 100644 index 00000000000..04a48029c6d --- /dev/null +++ b/drivers/ipm/ipm_sedi.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT intel_sedi_ipm + +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(ipm_sedi, CONFIG_IPM_LOG_LEVEL); + +#include "ipm_sedi.h" + +extern void sedi_ipc_isr(IN sedi_ipc_t ipc_device); + +static void set_ipm_dev_busy(const struct device *dev, bool is_write) +{ + struct ipm_sedi_context *ipm = dev->data; + unsigned int key = irq_lock(); + + atomic_set_bit(&ipm->status, is_write ? IPM_WRITE_BUSY_BIT : IPM_READ_BUSY_BIT); + pm_device_busy_set(dev); + irq_unlock(key); +} + +static void clear_ipm_dev_busy(const struct device *dev, bool is_write) +{ + struct ipm_sedi_context *ipm = dev->data; + unsigned int key = irq_lock(); + + atomic_clear_bit(&ipm->status, is_write ? IPM_WRITE_BUSY_BIT : IPM_READ_BUSY_BIT); + if ((!atomic_test_bit(&ipm->status, IPM_WRITE_BUSY_BIT)) + && (!atomic_test_bit(&ipm->status, IPM_READ_BUSY_BIT))) { + pm_device_busy_clear(dev); + } + irq_unlock(key); +} + +static void ipm_event_dispose(IN sedi_ipc_t device, IN uint32_t event, INOUT void *params) +{ + const struct device *dev = (const struct device *)params; + struct ipm_sedi_context *ipm = dev->data; + uint32_t drbl_in = 0, len; + + LOG_DBG("dev: %u, event: %u", device, event); + switch (event) { + case SEDI_IPC_EVENT_MSG_IN: + if (ipm->rx_msg_notify_cb != NULL) { + set_ipm_dev_busy(dev, false); + sedi_ipc_read_dbl(device, &drbl_in); + len = IPC_HEADER_GET_LENGTH(drbl_in); + sedi_ipc_read_msg(device, ipm->incoming_data_buf, len); + ipm->rx_msg_notify_cb(dev, + ipm->rx_msg_notify_cb_data, + drbl_in, ipm->incoming_data_buf); + } else { + LOG_WRN("no handler for ipm new msg"); + } + break; + case SEDI_IPC_EVENT_MSG_PEER_ACKED: + if (atomic_test_bit(&ipm->status, IPM_WRITE_IN_PROC_BIT)) { + k_sem_give(&ipm->device_write_msg_sem); + } else { + LOG_WRN("no sending in progress, got an ack"); + } + break; + default: + return; + } +} + +static int ipm_init(const struct device *dev) +{ + /* allocate resource and context*/ + const struct ipm_sedi_config_t *info = dev->config; + sedi_ipc_t device = info->ipc_device; + struct ipm_sedi_context *ipm = dev->data; + + info->irq_config(); + k_sem_init(&ipm->device_write_msg_sem, 0, 1); + k_mutex_init(&ipm->device_write_lock); + ipm->status = 0; + + sedi_ipc_init(device, ipm_event_dispose, (void *)dev); + atomic_set_bit(&ipm->status, IPM_PEER_READY_BIT); + LOG_DBG("ipm driver initialized on device: %p", dev); + return 0; +} + +static int ipm_send_isr(const struct device *dev, + uint32_t drbl, + const void *msg, + int msg_size) +{ + const struct ipm_sedi_config_t *info = dev->config; + sedi_ipc_t device = info->ipc_device; + uint32_t drbl_acked = 0; + + sedi_ipc_write_msg(device, (uint8_t *)msg, + (uint32_t)msg_size); + sedi_ipc_write_dbl(device, drbl); + do { + sedi_ipc_read_ack_drbl(device, &drbl_acked); + } while ((drbl_acked & BIT(IPC_BUSY_BIT)) == 0); + + return 0; +} + +static int ipm_sedi_send(const struct device *dev, + int wait, + uint32_t drbl, + const void *msg, + int msg_size) +{ + __ASSERT((dev != NULL), "bad params\n"); + const struct ipm_sedi_config_t *info = dev->config; + struct ipm_sedi_context *ipm = dev->data; + sedi_ipc_t device = info->ipc_device; + int ret, sedi_ret; + + /* check params, check status */ + if ((msg_size > IPC_DATA_LEN_MAX) || ((msg_size > 0) && (msg == NULL)) || + ((drbl & BIT(IPC_BUSY_BIT)) == 0)) { + LOG_ERR("bad params when sending ipm msg on device: %p", dev); + return -EINVAL; + } + + if (wait == 0) { + LOG_ERR("not support no wait mode when sending ipm msg"); + return -ENOTSUP; + } + + if (k_is_in_isr()) { + return ipm_send_isr(dev, drbl, msg, msg_size); + } + + k_mutex_lock(&ipm->device_write_lock, K_FOREVER); + set_ipm_dev_busy(dev, true); + + if (!atomic_test_bit(&ipm->status, IPM_PEER_READY_BIT)) { + LOG_WRN("peer is not ready"); + ret = -EBUSY; + goto write_err; + } + + /* write data regs */ + if (msg_size > 0) { + sedi_ret = sedi_ipc_write_msg(device, (uint8_t *)msg, + (uint32_t)msg_size); + if (sedi_ret != SEDI_DRIVER_OK) { + LOG_ERR("ipm write data fail on device: %p", dev); + ret = -EBUSY; + goto write_err; + } + } + + atomic_set_bit(&ipm->status, IPM_WRITE_IN_PROC_BIT); + /* write drbl regs to interrupt peer*/ + sedi_ret = sedi_ipc_write_dbl(device, drbl); + + if (sedi_ret != SEDI_DRIVER_OK) { + LOG_ERR("ipm write doorbell fail on device: %p", dev); + ret = -EBUSY; + goto func_out; + } + + /* wait for busy-bit-consumed interrupt */ + ret = k_sem_take(&ipm->device_write_msg_sem, K_MSEC(IPM_TIMEOUT_MS)); + if (ret) { + LOG_WRN("ipm write timeout on device: %p", dev); + sedi_ipc_write_dbl(device, 0); + } + +func_out: + atomic_clear_bit(&ipm->status, IPM_WRITE_IN_PROC_BIT); + +write_err: + clear_ipm_dev_busy(dev, true); + k_mutex_unlock(&ipm->device_write_lock); + if (ret == 0) { + LOG_DBG("ipm wrote a new message on device: %p, drbl=%08x", + dev, drbl); + } + return ret; +} + +static void ipm_sedi_register_callback(const struct device *dev, ipm_callback_t cb, + void *user_data) +{ + __ASSERT((dev != NULL), "bad params\n"); + + struct ipm_sedi_context *ipm = dev->data; + + if (cb == NULL) { + LOG_ERR("bad params when add ipm callback on device: %p", dev); + return; + } + + if (ipm->rx_msg_notify_cb == NULL) { + ipm->rx_msg_notify_cb = cb; + ipm->rx_msg_notify_cb_data = user_data; + } else { + LOG_ERR("ipm rx callback already exists on device: %p", dev); + } +} + +static void ipm_sedi_complete(const struct device *dev) +{ + int ret; + + __ASSERT((dev != NULL), "bad params\n"); + + const struct ipm_sedi_config_t *info = dev->config; + sedi_ipc_t device = info->ipc_device; + + ret = sedi_ipc_send_ack_drbl(device, 0); + if (ret != SEDI_DRIVER_OK) { + LOG_ERR("ipm send ack drl fail on device: %p", dev); + } + + clear_ipm_dev_busy(dev, false); +} + +static int ipm_sedi_get_max_data_size(const struct device *ipmdev) +{ + ARG_UNUSED(ipmdev); + return IPC_DATA_LEN_MAX; +} + +static uint32_t ipm_sedi_get_max_id(const struct device *ipmdev) +{ + ARG_UNUSED(ipmdev); + return UINT32_MAX; +} + +static int ipm_sedi_set_enable(const struct device *dev, int enable) +{ + __ASSERT((dev != NULL), "bad params\n"); + + const struct ipm_sedi_config_t *info = dev->config; + + if (enable) { + irq_enable(info->irq_num); + } else { + irq_disable(info->irq_num); + } + return 0; +} + +#if defined(CONFIG_PM_DEVICE) +static int ipm_power_ctrl(const struct device *dev, + enum pm_device_action action) +{ + return 0; +} +#endif + +static const struct ipm_driver_api ipm_funcs = { + .send = ipm_sedi_send, + .register_callback = ipm_sedi_register_callback, + .max_data_size_get = ipm_sedi_get_max_data_size, + .max_id_val_get = ipm_sedi_get_max_id, + .complete = ipm_sedi_complete, + .set_enabled = ipm_sedi_set_enable +}; + +#define IPM_SEDI_DEV_DEFINE(n) \ + static struct ipm_sedi_context ipm_data_##n; \ + static void ipm_##n##_irq_config(void); \ + static const struct ipm_sedi_config_t ipm_config_##n = { \ + .ipc_device = DT_INST_PROP(n, peripheral_id), \ + .irq_num = DT_INST_IRQN(n), \ + .irq_config = ipm_##n##_irq_config, \ + }; \ + static void ipm_##n##_irq_config(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), \ + DT_INST_IRQ(n, priority), sedi_ipc_isr, \ + DT_INST_PROP(n, peripheral_id), \ + DT_INST_IRQ(n, sense)); \ + } \ + PM_DEVICE_DT_DEFINE(DT_NODELABEL(ipm##n), ipm_power_ctrl); \ + DEVICE_DT_INST_DEFINE(n, \ + &ipm_init, \ + PM_DEVICE_DT_GET(DT_NODELABEL(ipm##n)), \ + &ipm_data_##n, \ + &ipm_config_##n, \ + POST_KERNEL, \ + 0, \ + &ipm_funcs); + +DT_INST_FOREACH_STATUS_OKAY(IPM_SEDI_DEV_DEFINE) diff --git a/drivers/ipm/ipm_sedi.h b/drivers/ipm/ipm_sedi.h new file mode 100644 index 00000000000..f1524b0beea --- /dev/null +++ b/drivers/ipm/ipm_sedi.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef __DRIVERS_IPM_SEDI_H +#define __DRIVERS_IPM_SEDI_H + +#ifdef __cplusplus +extern "C" { +#endif +#include "sedi_driver_common.h" +#include "sedi_driver_ipc.h" +#include + +/* + * bit 31 indicates whether message is valid, and could generate interrupt + * while set/clear + */ +#define IPC_BUSY_BIT 31 + +#define IPM_WRITE_IN_PROC_BIT 0 +#define IPM_WRITE_BUSY_BIT 1 +#define IPM_READ_BUSY_BIT 2 +#define IPM_PEER_READY_BIT 3 + +#define IPM_TIMEOUT_MS 1000 + +struct ipm_sedi_config_t { + sedi_ipc_t ipc_device; + int32_t irq_num; + void (*irq_config)(void); +}; + +struct ipm_sedi_context { + ipm_callback_t rx_msg_notify_cb; + void *rx_msg_notify_cb_data; + uint8_t incoming_data_buf[IPC_DATA_LEN_MAX]; + struct k_sem device_write_msg_sem; + struct k_mutex device_write_lock; + atomic_t status; + uint32_t power_status; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __DRIVERS_IPM_SEDI_H */ diff --git a/drivers/kscan/CMakeLists.txt b/drivers/kscan/CMakeLists.txt index d650f17f917..005c53ab4b7 100644 --- a/drivers/kscan/CMakeLists.txt +++ b/drivers/kscan/CMakeLists.txt @@ -4,7 +4,6 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/kscan.h) zephyr_library() -zephyr_library_sources_ifdef(CONFIG_KSCAN_ITE_IT8XXX2 kscan_ite_it8xxx2.c) zephyr_library_sources_ifdef(CONFIG_KSCAN_XEC kscan_mchp_xec.c) zephyr_library_sources_ifdef(CONFIG_KSCAN_HT16K33 kscan_ht16k33.c) zephyr_library_sources_ifdef(CONFIG_KSCAN_INPUT kscan_input.c) diff --git a/drivers/kscan/Kconfig b/drivers/kscan/Kconfig index 02ef0987cc6..a2a786c31e3 100644 --- a/drivers/kscan/Kconfig +++ b/drivers/kscan/Kconfig @@ -10,7 +10,6 @@ menuconfig KSCAN if KSCAN -source "drivers/kscan/Kconfig.it8xxx2" source "drivers/kscan/Kconfig.xec" source "drivers/kscan/Kconfig.ht16k33" source "drivers/kscan/Kconfig.input" diff --git a/drivers/kscan/Kconfig.it8xxx2 b/drivers/kscan/Kconfig.it8xxx2 deleted file mode 100644 index da5cead4b78..00000000000 --- a/drivers/kscan/Kconfig.it8xxx2 +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright (c) 2021 ITE Corporation. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0 - -menuconfig KSCAN_ITE_IT8XXX2 - bool "ITE KSCAN driver" - default y - depends on DT_HAS_ITE_IT8XXX2_KSCAN_ENABLED - select MULTITHREADING - help - This option enables the ITE keyboard scan driver. - -if KSCAN_ITE_IT8XXX2 - -config KSCAN_ITE_IT8XXX2_COLUMN_SIZE - int "KSCAN_ITE_IT8XXX2_COLUMN_SIZE" - range 16 18 - default 16 - help - Adjust the value to your keyboard columns. The maximum - column size for the ITE family is 18. - -config KSCAN_ITE_IT8XXX2_ROW_SIZE - int "KSCAN_ITE_IT8XXX2_ROW_SIZE" - default 8 - help - Adjust the value to your keyboard rows. The maximum - row size for the ITE family is 8. - -config KSCAN_ITE_IT8XXX2_DEBOUNCE_DOWN - int "KSCAN_ITE_IT8XXX2_DEBOUNCE_DOWN" - default 9 - help - Determines the time in msecs for debouncing a key press. - -config KSCAN_ITE_IT8XXX2_DEBOUNCE_UP - int "KSCAN_ITE_IT8XXX2_DEBOUNCE_UP" - default 30 - help - Determines the time in msecs for debouncing a key release. - -config KSCAN_ITE_IT8XXX2_POLL_PERIOD - int "KSCAN_ITE_IT8XXX2_POLL_PERIOD" - default 3 - help - Defines the poll period in msecs between matrix scans. - -endif # KSCAN_ITE_IT8XXX2 diff --git a/drivers/kscan/kscan_handlers.c b/drivers/kscan/kscan_handlers.c index b2d36ba3943..98809687430 100644 --- a/drivers/kscan/kscan_handlers.c +++ b/drivers/kscan/kscan_handlers.c @@ -5,13 +5,13 @@ */ #include -#include +#include static inline int z_vrfy_kscan_config(const struct device *dev, kscan_callback_t callback_isr) { - Z_OOPS(Z_SYSCALL_DRIVER_KSCAN(dev, config)); - Z_OOPS(Z_SYSCALL_VERIFY_MSG(callback_isr == 0, + K_OOPS(K_SYSCALL_DRIVER_KSCAN(dev, config)); + K_OOPS(K_SYSCALL_VERIFY_MSG(callback_isr == 0, "callback cannot be set from user mode")); return z_impl_kscan_config((const struct device *)dev, callback_isr); } @@ -19,7 +19,7 @@ static inline int z_vrfy_kscan_config(const struct device *dev, static inline int z_vrfy_kscan_disable_callback(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_KSCAN(dev, disable_callback)); + K_OOPS(K_SYSCALL_DRIVER_KSCAN(dev, disable_callback)); return z_impl_kscan_disable_callback((const struct device *)dev); } @@ -27,7 +27,7 @@ static inline int z_vrfy_kscan_disable_callback(const struct device *dev) static int z_vrfy_kscan_enable_callback(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_KSCAN(dev, enable_callback)); + K_OOPS(K_SYSCALL_DRIVER_KSCAN(dev, enable_callback)); return z_impl_kscan_enable_callback((const struct device *)dev); } diff --git a/drivers/kscan/kscan_ite_it8xxx2.c b/drivers/kscan/kscan_ite_it8xxx2.c deleted file mode 100644 index 85d47d9d230..00000000000 --- a/drivers/kscan/kscan_ite_it8xxx2.c +++ /dev/null @@ -1,589 +0,0 @@ -/* - * Copyright (c) 2021 ITE Corporation. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT ite_it8xxx2_kscan - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#define LOG_LEVEL CONFIG_KSCAN_LOG_LEVEL -LOG_MODULE_REGISTER(kscan_ite_it8xxx2); - -#define KEYBOARD_KSI_PIN_COUNT IT8XXX2_DT_INST_WUCCTRL_LEN(0) -#define KEYBOARD_COLUMN_DRIVE_ALL -2 -#define KEYBOARD_COLUMN_DRIVE_NONE -1 -/* Free run timer counts transform to micro-seconds (clock source is 32768Hz) */ -#define CLOCK_32K_HW_CYCLES_TO_US(X) \ - (uint32_t)((((uint64_t)(X) * 1000000U) / \ - sys_clock_hw_cycles_per_sec())) -/* Milli-second transform to micro-second */ -#define MS_TO_US 1000U -/* Number of tracked scan times */ -#define SCAN_OCURRENCES 30U -/* Thread stack size */ -#define TASK_STACK_SIZE 1024 - -/* Device config */ -enum kscan_pin_func { - KSO16 = 0, - KSO17, -}; - -struct kscan_wuc_map_cfg { - /* WUC control device structure */ - const struct device *wucs; - /* WUC pin mask */ - uint8_t mask; -}; - -struct kscan_it8xxx2_config { - /* Keyboard scan controller base address */ - struct kscan_it8xxx2_regs *base; - /* Keyboard scan input (KSI) wake-up irq */ - int irq; - /* KSI[7:0] wake-up input source configuration list */ - const struct kscan_wuc_map_cfg *wuc_map_list; - /* KSI[7:0]/KSO[17:0] keyboard scan alternate configuration */ - const struct pinctrl_dev_config *pcfg; - /* KSO16 GPIO cells */ - struct gpio_dt_spec kso16_gpios; - /* KSO17 GPIO cells */ - struct gpio_dt_spec kso17_gpios; -}; - -/* Device data */ -struct kscan_it8xxx2_data { - /* Variables in usec units */ - uint32_t deb_time_press; - uint32_t deb_time_rel; - int32_t poll_timeout; - uint32_t poll_period; - uint8_t matrix_stable_state[CONFIG_KSCAN_ITE_IT8XXX2_COLUMN_SIZE]; - uint8_t matrix_unstable_state[CONFIG_KSCAN_ITE_IT8XXX2_COLUMN_SIZE]; - uint8_t matrix_previous_state[CONFIG_KSCAN_ITE_IT8XXX2_COLUMN_SIZE]; - /* Index in to the scan_clock_cycle to indicate start of debouncing */ - uint8_t scan_cycle_idx[CONFIG_KSCAN_ITE_IT8XXX2_COLUMN_SIZE] - [CONFIG_KSCAN_ITE_IT8XXX2_ROW_SIZE]; - /* - * Track previous "elapsed clock cycles" per matrix scan. This - * is used to calculate the debouncing time for every key - */ - uint8_t scan_clk_cycle[SCAN_OCURRENCES]; - struct k_sem poll_lock; - uint8_t scan_cycles_idx; - kscan_callback_t callback; - struct k_thread thread; - atomic_t enable_scan; - /* KSI[7:0] wake-up interrupt status mask */ - uint8_t ksi_pin_mask; - - K_KERNEL_STACK_MEMBER(thread_stack, TASK_STACK_SIZE); -}; - -static void drive_keyboard_column(const struct device *dev, int col) -{ - const struct kscan_it8xxx2_config *const config = dev->config; - struct kscan_it8xxx2_regs *const inst = config->base; - int mask; - - /* Tri-state all outputs */ - if (col == KEYBOARD_COLUMN_DRIVE_NONE) { - mask = 0x3ffff; - /* Assert all outputs */ - } else if (col == KEYBOARD_COLUMN_DRIVE_ALL) { - mask = 0; - /* Assert a single output */ - } else { - mask = 0x3ffff ^ BIT(col); - } - - /* Set KSO[17:0] output data */ - inst->KBS_KSOL = (uint8_t) (mask & 0xff); - inst->KBS_KSOH1 = (uint8_t) ((mask >> 8) & 0xff); -#if (CONFIG_KSCAN_ITE_IT8XXX2_COLUMN_SIZE > 16) - inst->KBS_KSOH2 = (uint8_t) ((mask >> 16) & 0xff); -#endif -} - -static uint8_t read_keyboard_row(const struct device *dev) -{ - const struct kscan_it8xxx2_config *const config = dev->config; - struct kscan_it8xxx2_regs *const inst = config->base; - - /* Bits are active-low, so toggle it (return 1 means key pressed) */ - return (inst->KBS_KSI ^ 0xff); -} - -static bool is_matrix_ghosting(const uint8_t *state) -{ - /* - * Matrix keyboard designs are susceptible to ghosting. - * An extra key appears to be pressed when 3 keys - * belonging to the same block are pressed. - * for example, in the following block - * - * . . w . q . - * . . . . . . - * . . . . . . - * . . m . a . - * - * the key m would look as pressed if the user pressed keys - * w, q and a simultaneously. A block can also be formed, - * with not adjacent columns. - */ - for (int c = 0; c < CONFIG_KSCAN_ITE_IT8XXX2_COLUMN_SIZE; c++) { - if (!state[c]) - continue; - - for (int c_n = c + 1; c_n < CONFIG_KSCAN_ITE_IT8XXX2_COLUMN_SIZE; c_n++) { - /* - * We AND the columns to detect a "block". - * this is an indication of ghosting, due to current - * flowing from a key which was never pressed. in our - * case, current flowing is a bit set to 1 as we - * flipped the bits when the matrix was scanned. - * now we OR the columns using z&(z-1) which is - * non-zero only if z has more than one bit set. - */ - uint8_t common_row_bits = state[c] & state[c_n]; - - if (common_row_bits & (common_row_bits - 1)) - return true; - } - } - - return false; -} - -static bool read_keyboard_matrix(const struct device *dev, uint8_t *new_state) -{ - uint8_t row; - uint8_t key_event = 0U; - - for (int col = 0; col < CONFIG_KSCAN_ITE_IT8XXX2_COLUMN_SIZE; col++) { - /* Drive specific column low and others high */ - drive_keyboard_column(dev, col); - /* Allow the matrix to stabilize before reading it */ - k_busy_wait(50U); - row = read_keyboard_row(dev); - new_state[col] = row; - - key_event |= row; - } - - drive_keyboard_column(dev, KEYBOARD_COLUMN_DRIVE_NONE); - - return key_event != 0U ? true : false; -} - -static void keyboard_raw_interrupt(const struct device *dev) -{ - const struct kscan_it8xxx2_config *const config = dev->config; - struct kscan_it8xxx2_data *data = dev->data; - - /* - * W/C wakeup interrupt status of KSI[7:0] pins - * - * NOTE: We want to clear the status as soon as possible, - * so clear KSI[7:0] pins at a time. - */ - it8xxx2_wuc_clear_status(config->wuc_map_list[0].wucs, - data->ksi_pin_mask); - - /* W/C interrupt status of KSI[7:0] pins */ - ite_intc_isr_clear(config->irq); - - /* Release poll lock semaphore */ - k_sem_give(&data->poll_lock); -} - -void keyboard_raw_enable_interrupt(const struct device *dev, int enable) -{ - const struct kscan_it8xxx2_config *const config = dev->config; - struct kscan_it8xxx2_data *data = dev->data; - - if (enable) { - /* - * W/C wakeup interrupt status of KSI[7:0] pins - * - * NOTE: We want to clear the status as soon as possible, - * so clear KSI[7:0] pins at a time. - */ - it8xxx2_wuc_clear_status(config->wuc_map_list[0].wucs, - data->ksi_pin_mask); - - /* W/C interrupt status of KSI[7:0] pins */ - ite_intc_isr_clear(config->irq); - - irq_enable(config->irq); - } else { - irq_disable(config->irq); - } -} - -static bool check_key_events(const struct device *dev) -{ - struct kscan_it8xxx2_data *data = dev->data; - uint8_t matrix_new_state[CONFIG_KSCAN_ITE_IT8XXX2_COLUMN_SIZE] = {0U}; - bool key_pressed = false; - uint32_t cycles_now = k_cycle_get_32(); - uint8_t row_changed = 0U; - uint8_t deb_col; - - if (++data->scan_cycles_idx >= SCAN_OCURRENCES) { - data->scan_cycles_idx = 0U; - } - - data->scan_clk_cycle[data->scan_cycles_idx] = cycles_now; - - /* Scan the matrix */ - key_pressed = read_keyboard_matrix(dev, matrix_new_state); - - /* Abort if ghosting is detected */ - if (is_matrix_ghosting(matrix_new_state)) { - return false; - } - - /* - * The intent of this loop is to gather information related to key - * changes - */ - for (int c = 0; c < CONFIG_KSCAN_ITE_IT8XXX2_COLUMN_SIZE; c++) { - /* Check if there was an update from the previous scan */ - row_changed = matrix_new_state[c] ^ - data->matrix_previous_state[c]; - - if (!row_changed) - continue; - - for (int r = 0; r < CONFIG_KSCAN_ITE_IT8XXX2_ROW_SIZE; r++) { - /* - * Index all they keys that changed for each row - * in order to debounce each key in terms of it - */ - if (row_changed & BIT(r)) - data->scan_cycle_idx[c][r] = - data->scan_cycles_idx; - } - - data->matrix_unstable_state[c] |= row_changed; - data->matrix_previous_state[c] = matrix_new_state[c]; - } - - for (int c = 0; c < CONFIG_KSCAN_ITE_IT8XXX2_COLUMN_SIZE; c++) { - deb_col = data->matrix_unstable_state[c]; - - if (!deb_col) - continue; - - /* Debouncing for each row key occurs here */ - for (int r = 0; r < CONFIG_KSCAN_ITE_IT8XXX2_ROW_SIZE; r++) { - uint8_t mask = BIT(r); - uint8_t row_bit = matrix_new_state[c] & mask; - - /* Continue if we already debounce a key */ - if (!(deb_col & mask)) - continue; - - /* Convert the clock cycle differences to usec */ - uint32_t debt = CLOCK_32K_HW_CYCLES_TO_US(cycles_now - - data->scan_clk_cycle[data->scan_cycle_idx[c][r]]); - - /* Does the key requires more time to be debounced ? */ - if (debt < (row_bit ? data->deb_time_press : - data->deb_time_rel)) { - /* Need more time to debounce */ - continue; - } - - data->matrix_unstable_state[c] &= ~row_bit; - - /* Check if there was a change in the stable state */ - if ((data->matrix_stable_state[c] & mask) == row_bit) { - /* Key state did not change */ - continue; - } - - /* - * The current row has been debounced, therefore update - * the stable state. Then, proceed to notify the - * application about the keys pressed. - */ - data->matrix_stable_state[c] ^= mask; - if ((atomic_get(&data->enable_scan) == 1U) && - (data->callback != NULL)) { - data->callback(dev, r, c, - row_bit ? true : false); - } - } - } - - return key_pressed; -} - -/** - * @brief Determine if a timer is expired. - * - * @param start_cycles The starting time of HW cycle. - * @param timeout Pointer to the period time. - * - * @retval true If timer is expired; - * false If timer isn't expired. - */ -static bool poll_expired(uint32_t start_cycles, int32_t *timeout) -{ - uint32_t now_cycles; - uint32_t microsecs_spent; - - now_cycles = k_cycle_get_32(); - microsecs_spent = CLOCK_32K_HW_CYCLES_TO_US(now_cycles - start_cycles); - - /* Update the timeout value */ - *timeout -= microsecs_spent; - - return !(*timeout >= 0); -} - -void polling_task(const struct device *dev, void *dummy2, void *dummy3) -{ - struct kscan_it8xxx2_data *data = dev->data; - int32_t local_poll_timeout = data->poll_timeout; - uint32_t current_cycles; - uint32_t cycles_delta; - uint32_t wait_period; - - ARG_UNUSED(dummy2); - ARG_UNUSED(dummy3); - - while (true) { - /* Init all KSO output low */ - drive_keyboard_column(dev, KEYBOARD_COLUMN_DRIVE_ALL); - /* Enable wakeup and interrupt of KSI pins */ - keyboard_raw_enable_interrupt(dev, 1); - /* Wait poll lock semaphore */ - k_sem_take(&data->poll_lock, K_FOREVER); - /* Disable wakeup and interrupt of KSI pins after fired */ - keyboard_raw_enable_interrupt(dev, 0); - - uint32_t start_poll_cycles = k_cycle_get_32(); - - while (atomic_get(&data->enable_scan) == 1U) { - uint32_t start_period_cycles = k_cycle_get_32(); - - if (check_key_events(dev)) { - start_poll_cycles = k_cycle_get_32(); - } else if (poll_expired(start_poll_cycles, - &local_poll_timeout)) { - break; - } - - /* - * Subtract the time invested from the sleep period - * in order to compensate for the time invested - * in debouncing a key - */ - current_cycles = k_cycle_get_32(); - cycles_delta = current_cycles - start_period_cycles; - wait_period = data->poll_period - - CLOCK_32K_HW_CYCLES_TO_US(cycles_delta); - - /* Override wait_period in case it's less than 1000 us */ - if (wait_period < MS_TO_US) { - wait_period = MS_TO_US; - } - - /* - * Wait period results in a larger number when - * current cycles counter wrap. In this case, the - * whole poll period is used - */ - if (wait_period > data->poll_period) { - LOG_DBG("wait_period : %u", wait_period); - wait_period = data->poll_period; - } - - /* Allow other threads to run while we sleep */ - k_usleep(wait_period); - } - } -} - -static int kscan_it8xxx2_init(const struct device *dev) -{ - const struct kscan_it8xxx2_config *const config = dev->config; - struct kscan_it8xxx2_data *data = dev->data; - struct kscan_it8xxx2_regs *const inst = config->base; - int status; - - /* Disable wakeup and interrupt of KSI pins before configuring */ - keyboard_raw_enable_interrupt(dev, 0); - -#if (CONFIG_KSCAN_ITE_IT8XXX2_COLUMN_SIZE > 16) - /* - * For KSO[16] and KSO[17]: - * 1.GPOTRC: - * Bit[x] = 1b: Enable the open-drain mode of KSO pin - * 2.GPCRCx: - * Bit[7:6] = 00b: Select alternate KSO function - * Bit[2] = 1b: Enable the internal pull-up of KSO pin - * - * NOTE: Set input temporarily for gpio_pin_configure(), after that - * pinctrl_apply_state() set to alternate function immediately. - */ - gpio_pin_configure_dt(&config->kso16_gpios, GPIO_INPUT); - gpio_pin_configure_dt(&config->kso17_gpios, GPIO_INPUT); -#endif - /* - * Enable the internal pull-up and kbs mode of the KSI[7:0] pins. - * Enable the internal pull-up and kbs mode of the KSO[15:0] pins. - * Enable the open-drain mode of the KSO[17:0] pins. - */ - status = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); - if (status < 0) { - LOG_ERR("Failed to configure KSI[7:0] and KSO[17:0] pins"); - return status; - } - - /* KSO[17:0] pins output low */ - inst->KBS_KSOL = 0x00; - inst->KBS_KSOH1 = 0x00; -#if (CONFIG_KSCAN_ITE_IT8XXX2_COLUMN_SIZE > 16) - inst->KBS_KSOH2 = 0x00; -#endif - - for (int i = 0; i < KEYBOARD_KSI_PIN_COUNT; i++) { - /* Select wakeup interrupt falling-edge triggered of KSI[7:0] pins */ - it8xxx2_wuc_set_polarity(config->wuc_map_list[i].wucs, - config->wuc_map_list[i].mask, - WUC_TYPE_EDGE_FALLING); - /* W/C wakeup interrupt status of KSI[7:0] pins */ - it8xxx2_wuc_clear_status(config->wuc_map_list[i].wucs, - config->wuc_map_list[i].mask); - /* Enable wakeup interrupt of KSI[7:0] pins */ - it8xxx2_wuc_enable(config->wuc_map_list[i].wucs, - config->wuc_map_list[i].mask); - - /* - * We want to clear KSI[7:0] pins status at a time when wakeup - * interrupt fire, so gather the KSI[7:0] pin mask value here. - */ - if (IS_ENABLED(CONFIG_LOG)) { - if (config->wuc_map_list[i].wucs != config->wuc_map_list[0].wucs) { - LOG_ERR("KSI%d pin isn't in the same wuc node!", i); - } - } - data->ksi_pin_mask |= config->wuc_map_list[i].mask; - } - - /* W/C interrupt status of KSI[7:0] pins */ - ite_intc_isr_clear(config->irq); - - /* Kconfig.it8xxx2 time figures are transformed from msec to usec */ - data->deb_time_press = - (uint32_t) (CONFIG_KSCAN_ITE_IT8XXX2_DEBOUNCE_DOWN * MS_TO_US); - data->deb_time_rel = - (uint32_t) (CONFIG_KSCAN_ITE_IT8XXX2_DEBOUNCE_UP * MS_TO_US); - data->poll_period = - (uint32_t) (CONFIG_KSCAN_ITE_IT8XXX2_POLL_PERIOD * MS_TO_US); - data->poll_timeout = 100 * MS_TO_US; - - /* Init null for callback function */ - data->callback = NULL; - - /* Create poll lock semaphore */ - k_sem_init(&data->poll_lock, 0, 1); - - /* Enable keyboard scan loop */ - atomic_set(&data->enable_scan, 1); - - irq_connect_dynamic(DT_INST_IRQN(0), 0, - (void (*)(const void *))keyboard_raw_interrupt, - (const void *)dev, 0); - - /* Create keyboard scan task */ - k_thread_create(&data->thread, data->thread_stack, - TASK_STACK_SIZE, - (void (*)(void *, void *, void *))polling_task, - (void *)dev, NULL, NULL, - K_PRIO_COOP(4), 0, K_NO_WAIT); - - return 0; -} - -static int kscan_it8xxx2_configure(const struct device *dev, - kscan_callback_t callback) -{ - struct kscan_it8xxx2_data *data = dev->data; - - if (!callback) { - return -EINVAL; - } - - /* Setup callback function */ - data->callback = callback; - - return 0; -} - -static int kscan_it8xxx2_disable_callback(const struct device *dev) -{ - struct kscan_it8xxx2_data *data = dev->data; - - /* Disable keyboard scan loop */ - atomic_set(&data->enable_scan, 0); - - return 0; -} - -static int kscan_it8xxx2_enable_callback(const struct device *dev) -{ - struct kscan_it8xxx2_data *data = dev->data; - - /* Enable keyboard scan loop */ - atomic_set(&data->enable_scan, 1); - - return 0; -} - -static const struct kscan_driver_api kscan_it8xxx2_driver_api = { - .config = kscan_it8xxx2_configure, - .disable_callback = kscan_it8xxx2_disable_callback, - .enable_callback = kscan_it8xxx2_enable_callback, -}; - -static const struct kscan_wuc_map_cfg kscan_wuc_0[IT8XXX2_DT_INST_WUCCTRL_LEN(0)] = - IT8XXX2_DT_WUC_ITEMS_LIST(0); - -PINCTRL_DT_INST_DEFINE(0); - -static const struct kscan_it8xxx2_config kscan_it8xxx2_cfg_0 = { - .base = (struct kscan_it8xxx2_regs *)DT_INST_REG_ADDR_BY_IDX(0, 0), - .irq = DT_INST_IRQN(0), - .wuc_map_list = kscan_wuc_0, - .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0), - .kso16_gpios = GPIO_DT_SPEC_INST_GET(0, kso16_gpios), - .kso17_gpios = GPIO_DT_SPEC_INST_GET(0, kso17_gpios), -}; - -static struct kscan_it8xxx2_data kscan_it8xxx2_kbd_data; - -DEVICE_DT_INST_DEFINE(0, - &kscan_it8xxx2_init, - NULL, - &kscan_it8xxx2_kbd_data, - &kscan_it8xxx2_cfg_0, - POST_KERNEL, - CONFIG_KSCAN_INIT_PRIORITY, - &kscan_it8xxx2_driver_api); diff --git a/drivers/kscan/kscan_mchp_xec.c b/drivers/kscan/kscan_mchp_xec.c index d3a39868c28..e0960b1c946 100644 --- a/drivers/kscan/kscan_mchp_xec.c +++ b/drivers/kscan/kscan_mchp_xec.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #define LOG_LEVEL CONFIG_KSCAN_LOG_LEVEL LOG_MODULE_REGISTER(kscan_mchp_xec); @@ -42,13 +44,14 @@ LOG_MODULE_REGISTER(kscan_mchp_xec); struct kscan_xec_config { struct kscan_regs *regs; + const struct pinctrl_dev_config *pcfg; + uint8_t rsvd[3]; uint8_t girq; uint8_t girq_pos; uint8_t irq_pri; uint8_t pcr_idx; uint8_t pcr_pos; - uint8_t rsvd[3]; - const struct pinctrl_dev_config *pcfg; + bool wakeup_source; }; struct kscan_xec_data { @@ -370,7 +373,9 @@ void polling_task(const struct device *dev, void *dummy2, void *dummy3) drive_keyboard_column(dev, KEYBOARD_COLUMN_DRIVE_ALL); k_sem_take(&data->poll_lock, K_FOREVER); - +#ifdef CONFIG_PM_DEVICE + pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES); +#endif uint32_t start_poll_cycles = k_cycle_get_32(); while (atomic_get(&data->enable_scan) == 1U) { @@ -411,6 +416,9 @@ void polling_task(const struct device *dev, void *dummy2, void *dummy3) /* Allow other threads to run while we sleep */ k_usleep(wait_period); } +#ifdef CONFIG_PM_DEVICE + pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES); +#endif } } @@ -449,6 +457,44 @@ static int kscan_xec_enable_interface(const struct device *dev) return 0; } +#ifdef CONFIG_PM_DEVICE +static int kscan_xec_pm_action(const struct device *dev, enum pm_device_action action) +{ + struct kscan_xec_config const *cfg = dev->config; + struct kscan_regs *regs = cfg->regs; + int ret = 0; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + if (!(cfg->wakeup_source)) { + ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); + if (ret != 0) { + LOG_ERR("XEC KSCAN pinctrl init failed (%d)", ret); + return ret; + } + regs->KSO_SEL &= ~BIT(MCHP_KSCAN_KSO_EN_POS); + /* Clea Status register */ + regs->KSI_STS = MCHP_KSCAN_KSO_SEL_REG_MASK; + regs->KSI_IEN = MCHP_KSCAN_KSI_IEN_REG_MASK; + } + break; + case PM_DEVICE_ACTION_SUSPEND: + if (!(cfg->wakeup_source)) { + regs->KSO_SEL |= BIT(MCHP_KSCAN_KSO_EN_POS); + regs->KSI_IEN = (~MCHP_KSCAN_KSI_IEN_REG_MASK); + ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_SLEEP); + if (ret == -ENOENT) { /* pinctrl-1 does not exist. */ + ret = 0; + } + } + break; + default: + ret = -ENOTSUP; + } + return ret; +} +#endif /* CONFIG_PM_DEVICE */ + static const struct kscan_driver_api kscan_xec_driver_api = { .config = kscan_xec_configure, .disable_callback = kscan_xec_inhibit_interface, @@ -505,6 +551,12 @@ static struct kscan_xec_data kbd_data; PINCTRL_DT_INST_DEFINE(0); +/* To enable wakeup on the KSCAN, the DTS needs to have entries defined + * in the KSCAN node in the DTS specifying it as a wake source; + * Example as below + * + * wakeup-source; + */ static struct kscan_xec_config kscan_xec_cfg_0 = { .regs = (struct kscan_regs *)(DT_INST_REG_ADDR(0)), .girq = (uint8_t)(DT_INST_PROP_BY_IDX(0, girqs, 0)), @@ -512,9 +564,12 @@ static struct kscan_xec_config kscan_xec_cfg_0 = { .pcr_idx = (uint8_t)(DT_INST_PROP_BY_IDX(0, pcrs, 0)), .pcr_pos = (uint8_t)(DT_INST_PROP_BY_IDX(0, pcrs, 1)), .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0), + .wakeup_source = DT_INST_PROP(0, wakeup_source) }; +PM_DEVICE_DT_INST_DEFINE(0, kscan_xec_pm_action); + DEVICE_DT_INST_DEFINE(0, kscan_xec_init, - NULL, &kbd_data, &kscan_xec_cfg_0, + PM_DEVICE_DT_INST_GET(0), &kbd_data, &kscan_xec_cfg_0, POST_KERNEL, CONFIG_KSCAN_INIT_PRIORITY, &kscan_xec_driver_api); diff --git a/drivers/led/ht16k33.c b/drivers/led/ht16k33.c index 0db398e55ff..8df5b7553f6 100644 --- a/drivers/led/ht16k33.c +++ b/drivers/led/ht16k33.c @@ -247,8 +247,12 @@ static bool ht16k33_process_keyscan_data(const struct device *dev) return pressed; } -static void ht16k33_irq_thread(struct ht16k33_data *data) +static void ht16k33_irq_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct ht16k33_data *data = p1; bool pressed; while (true) { @@ -420,7 +424,7 @@ static int ht16k33_init(const struct device *dev) k_thread_create(&data->irq_thread, data->irq_thread_stack, CONFIG_HT16K33_KEYSCAN_IRQ_THREAD_STACK_SIZE, - (k_thread_entry_t)ht16k33_irq_thread, data, NULL, NULL, + ht16k33_irq_thread, data, NULL, NULL, K_PRIO_COOP(CONFIG_HT16K33_KEYSCAN_IRQ_THREAD_PRIO), 0, K_NO_WAIT); #endif /* CONFIG_HT16K33_KEYSCAN */ diff --git a/drivers/led/led_handlers.c b/drivers/led/led_handlers.c index a3a37fb49e1..a089846e695 100644 --- a/drivers/led/led_handlers.c +++ b/drivers/led/led_handlers.c @@ -4,13 +4,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include static inline int z_vrfy_led_blink(const struct device *dev, uint32_t led, uint32_t delay_on, uint32_t delay_off) { - Z_OOPS(Z_SYSCALL_DRIVER_LED(dev, blink)); + K_OOPS(K_SYSCALL_DRIVER_LED(dev, blink)); return z_impl_led_blink((const struct device *)dev, led, delay_on, delay_off); } @@ -19,8 +19,8 @@ static inline int z_vrfy_led_blink(const struct device *dev, uint32_t led, static inline int z_vrfy_led_get_info(const struct device *dev, uint32_t led, const struct led_info **info) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_LED)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(info, sizeof(*info))); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_LED)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(info, sizeof(*info))); return z_impl_led_get_info(dev, led, info); } #include @@ -29,7 +29,7 @@ static inline int z_vrfy_led_set_brightness(const struct device *dev, uint32_t led, uint8_t value) { - Z_OOPS(Z_SYSCALL_DRIVER_LED(dev, set_brightness)); + K_OOPS(K_SYSCALL_DRIVER_LED(dev, set_brightness)); return z_impl_led_set_brightness((const struct device *)dev, led, value); } @@ -39,8 +39,8 @@ static inline int z_vrfy_led_write_channels(const struct device *dev, uint32_t start_channel, uint32_t num_channels, const uint8_t *buf) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_LED)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(buf, num_channels)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_LED)); + K_OOPS(K_SYSCALL_MEMORY_READ(buf, num_channels)); return z_impl_led_write_channels(dev, start_channel, num_channels, buf); } #include @@ -48,7 +48,7 @@ z_vrfy_led_write_channels(const struct device *dev, uint32_t start_channel, static inline int z_vrfy_led_set_channel(const struct device *dev, uint32_t channel, uint8_t value) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_LED)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_LED)); return z_impl_led_set_channel(dev, channel, value); } #include @@ -56,22 +56,22 @@ static inline int z_vrfy_led_set_channel(const struct device *dev, static inline int z_vrfy_led_set_color(const struct device *dev, uint32_t led, uint8_t num_colors, const uint8_t *color) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_LED)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(color, num_colors)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_LED)); + K_OOPS(K_SYSCALL_MEMORY_READ(color, num_colors)); return z_impl_led_set_color(dev, led, num_colors, color); } #include static inline int z_vrfy_led_on(const struct device *dev, uint32_t led) { - Z_OOPS(Z_SYSCALL_DRIVER_LED(dev, on)); + K_OOPS(K_SYSCALL_DRIVER_LED(dev, on)); return z_impl_led_on((const struct device *)dev, led); } #include static inline int z_vrfy_led_off(const struct device *dev, uint32_t led) { - Z_OOPS(Z_SYSCALL_DRIVER_LED(dev, off)); + K_OOPS(K_SYSCALL_DRIVER_LED(dev, off)); return z_impl_led_off((const struct device *)dev, led); } #include diff --git a/drivers/led/led_pwm.c b/drivers/led/led_pwm.c index 72cb616a6e5..7a860ec97b7 100644 --- a/drivers/led/led_pwm.c +++ b/drivers/led/led_pwm.c @@ -116,7 +116,7 @@ static int led_pwm_pm_action(const struct device *dev, err = pm_device_action_run(led->dev, action); if (err && (err != -EALREADY)) { - LOG_ERR("Cannot switch PWM %p power state", led->dev); + LOG_DBG("Cannot switch PWM %p power state (err = %d)", led->dev, err); } } diff --git a/drivers/led/ncp5623.c b/drivers/led/ncp5623.c index 3cb58d4bc48..0fd0f128d37 100644 --- a/drivers/led/ncp5623.c +++ b/drivers/led/ncp5623.c @@ -149,9 +149,10 @@ static int ncp5623_led_init(const struct device *dev) return -ENODEV; } - if (led_info->num_colors != 3 || led_info->num_colors != 1) { - LOG_ERR("%s: invalid number of colors %d (must be %d or 1)", dev->name, - led_info->num_colors, NCP5623_CHANNEL_COUNT); + if (led_info->num_colors != NCP5623_CHANNEL_COUNT) { + LOG_ERR("%s: invalid number of colors %d (must be %d with a single LED)", + dev->name, led_info->num_colors, NCP5623_CHANNEL_COUNT); + return -EINVAL; } } else if (config->num_leds <= 3) { /* three single-channel LEDs */ for (i = 0; i < config->num_leds; i++) { diff --git a/drivers/led/pca9633.c b/drivers/led/pca9633.c index 96a04dc484c..a7f95d61872 100644 --- a/drivers/led/pca9633.c +++ b/drivers/led/pca9633.c @@ -37,6 +37,7 @@ LOG_MODULE_REGISTER(pca9633); #define PCA9633_LEDOUT 0x08 /* PCA9633 mode register 1 */ +#define PCA9633_MODE1_ALLCAL 0x01 /* All Call Address enabled */ #define PCA9633_MODE1_SLEEP 0x10 /* Sleep Mode */ /* PCA9633 mode register 2 */ #define PCA9633_MODE2_DMBLNK 0x20 /* Enable blinking */ @@ -45,6 +46,7 @@ LOG_MODULE_REGISTER(pca9633); struct pca9633_config { struct i2c_dt_spec i2c; + bool disable_allcall; }; struct pca9633_data { @@ -192,11 +194,16 @@ static int pca9633_led_init(const struct device *dev) return -ENODEV; } - /* Take the LED driver out from Sleep mode. */ - if (i2c_reg_update_byte_dt(&config->i2c, - PCA9633_MODE1, - PCA9633_MODE1_SLEEP, - ~PCA9633_MODE1_SLEEP)) { + /* + * Take the LED driver out from Sleep mode and disable All Call Address + * if specified in DT. + */ + if (i2c_reg_update_byte_dt( + &config->i2c, PCA9633_MODE1, + config->disable_allcall ? PCA9633_MODE1_SLEEP | PCA9633_MODE1_ALLCAL + : PCA9633_MODE1_SLEEP, + config->disable_allcall ? ~(PCA9633_MODE1_SLEEP | PCA9633_MODE1_ALLCAL) + : ~PCA9633_MODE1_SLEEP)) { LOG_ERR("LED reg update failed"); return -EIO; } @@ -218,7 +225,8 @@ static const struct led_driver_api pca9633_led_api = { #define PCA9633_DEVICE(id) \ static const struct pca9633_config pca9633_##id##_cfg = { \ - .i2c = I2C_DT_SPEC_INST_GET(id) \ + .i2c = I2C_DT_SPEC_INST_GET(id), \ + .disable_allcall = DT_INST_PROP(id, disable_allcall), \ }; \ static struct pca9633_data pca9633_##id##_data; \ \ diff --git a/drivers/led_strip/ws2812_spi.c b/drivers/led_strip/ws2812_spi.c index c562d5c3dad..44cfecebc9e 100644 --- a/drivers/led_strip/ws2812_spi.c +++ b/drivers/led_strip/ws2812_spi.c @@ -34,8 +34,6 @@ LOG_MODULE_REGISTER(ws2812_spi); * isn't an EEPROM) */ #define SPI_OPER(idx) (SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | \ - COND_CODE_1(DT_INST_PROP(idx, spi_cpol), (SPI_MODE_CPOL), (0)) | \ - COND_CODE_1(DT_INST_PROP(idx, spi_cpha), (SPI_MODE_CPHA), (0)) | \ SPI_WORD_SET(SPI_FRAME_BITS)) struct ws2812_spi_cfg { diff --git a/drivers/lora/Kconfig b/drivers/lora/Kconfig index ddc1e50e625..585f122c3d6 100644 --- a/drivers/lora/Kconfig +++ b/drivers/lora/Kconfig @@ -21,7 +21,6 @@ source "subsys/logging/Kconfig.template.log_config" config LORA_SHELL bool "LoRa Shell" - default y depends on SHELL help Enable LoRa Shell for testing. diff --git a/drivers/mbox/CMakeLists.txt b/drivers/mbox/CMakeLists.txt index aa39b235522..b81a3bb679f 100644 --- a/drivers/mbox/CMakeLists.txt +++ b/drivers/mbox/CMakeLists.txt @@ -7,4 +7,5 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_USERSPACE mbox_handlers.c) zephyr_library_sources_ifdef(CONFIG_MBOX_NRFX_IPC mbox_nrfx_ipc.c) zephyr_library_sources_ifdef(CONFIG_MBOX_NXP_S32_MRU mbox_nxp_s32_mru.c) +zephyr_library_sources_ifdef(CONFIG_MBOX_NXP_IMX_MU mbox_nxp_imx_mu.c) zephyr_library_sources_ifdef(CONFIG_MBOX_ANDES_PLIC_SW mbox_andes_plic_sw.c) diff --git a/drivers/mbox/Kconfig b/drivers/mbox/Kconfig index a88a84472b4..0668c9aab8b 100644 --- a/drivers/mbox/Kconfig +++ b/drivers/mbox/Kconfig @@ -13,6 +13,7 @@ if MBOX # overridden (by defining symbols in multiple locations) source "drivers/mbox/Kconfig.nrfx" source "drivers/mbox/Kconfig.nxp_s32" +source "drivers/mbox/Kconfig.nxp_imx" source "drivers/mbox/Kconfig.andes" config MBOX_INIT_PRIORITY diff --git a/drivers/mbox/Kconfig.nxp_imx b/drivers/mbox/Kconfig.nxp_imx new file mode 100644 index 00000000000..6822e5dd87c --- /dev/null +++ b/drivers/mbox/Kconfig.nxp_imx @@ -0,0 +1,9 @@ +# Copyright 2022 NXP +# SPDX-License-Identifier: Apache-2.0 + +config MBOX_NXP_IMX_MU + bool "NXP i.MX Message Unit (MU) driver" + default y + depends on DT_HAS_NXP_MBOX_IMX_MU_ENABLED + help + Driver for NXP i.MX Message Unit. diff --git a/drivers/mbox/Kconfig.nxp_s32 b/drivers/mbox/Kconfig.nxp_s32 index ca3a81614a3..91c661eaa64 100644 --- a/drivers/mbox/Kconfig.nxp_s32 +++ b/drivers/mbox/Kconfig.nxp_s32 @@ -5,6 +5,6 @@ config MBOX_NXP_S32_MRU bool "NXP S32 Message Receive Unit (MRU) driver" default y depends on DT_HAS_NXP_S32_MRU_ENABLED - select NOCACHE_MEMORY + select NOCACHE_MEMORY if ARCH_HAS_NOCACHE_MEMORY_SUPPORT help Driver for NXP S32 Message Receive Unit (MRU). diff --git a/drivers/mbox/mbox_andes_plic_sw.c b/drivers/mbox/mbox_andes_plic_sw.c index 13254c464af..bc01da73a30 100644 --- a/drivers/mbox/mbox_andes_plic_sw.c +++ b/drivers/mbox/mbox_andes_plic_sw.c @@ -31,7 +31,7 @@ LOG_MODULE_REGISTER(mbox_andes_plic_sw); static struct mbox_andes_data { mbox_callback_t cb[IPI_NUM]; void *user_data[IPI_NUM]; - uint32_t enabled_channel[CONFIG_MP_NUM_CPUS]; + uint32_t enabled_channel[CONFIG_MP_MAX_NUM_CPUS]; #ifdef CONFIG_SCHED_IPI_SUPPORTED uint32_t reg_cb_channel; uint32_t ipi_channel; diff --git a/drivers/mbox/mbox_handlers.c b/drivers/mbox/mbox_handlers.c index 55b2b010c83..c4e43f74fe5 100644 --- a/drivers/mbox/mbox_handlers.c +++ b/drivers/mbox/mbox_handlers.c @@ -4,16 +4,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include static inline int z_vrfy_mbox_send(const struct mbox_channel *channel, const struct mbox_msg *msg) { - Z_OOPS(Z_SYSCALL_MEMORY_READ(channel, sizeof(struct mbox_channel))); - Z_OOPS(Z_SYSCALL_DRIVER_MBOX(channel->dev, send)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(msg, sizeof(struct mbox_msg))); - Z_OOPS(Z_SYSCALL_MEMORY_READ(msg->data, msg->size)); + K_OOPS(K_SYSCALL_MEMORY_READ(channel, sizeof(struct mbox_channel))); + K_OOPS(K_SYSCALL_DRIVER_MBOX(channel->dev, send)); + K_OOPS(K_SYSCALL_MEMORY_READ(msg, sizeof(struct mbox_msg))); + K_OOPS(K_SYSCALL_MEMORY_READ(msg->data, msg->size)); return z_impl_mbox_send(channel, msg); } @@ -21,7 +21,7 @@ static inline int z_vrfy_mbox_send(const struct mbox_channel *channel, static inline int z_vrfy_mbox_mtu_get(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_MBOX(dev, mtu_get)); + K_OOPS(K_SYSCALL_DRIVER_MBOX(dev, mtu_get)); return z_impl_mbox_mtu_get(dev); } @@ -29,7 +29,7 @@ static inline int z_vrfy_mbox_mtu_get(const struct device *dev) static inline uint32_t z_vrfy_mbox_max_channels_get(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_MBOX(dev, max_channels_get)); + K_OOPS(K_SYSCALL_DRIVER_MBOX(dev, max_channels_get)); return z_impl_mbox_max_channels_get(dev); } @@ -37,8 +37,8 @@ static inline uint32_t z_vrfy_mbox_max_channels_get(const struct device *dev) static inline int z_vrfy_mbox_set_enabled(const struct mbox_channel *channel, bool enable) { - Z_OOPS(Z_SYSCALL_MEMORY_READ(channel, sizeof(struct mbox_channel))); - Z_OOPS(Z_SYSCALL_DRIVER_MBOX(channel->dev, set_enabled)); + K_OOPS(K_SYSCALL_MEMORY_READ(channel, sizeof(struct mbox_channel))); + K_OOPS(K_SYSCALL_DRIVER_MBOX(channel->dev, set_enabled)); return z_impl_mbox_set_enabled(channel, enable); } diff --git a/drivers/mbox/mbox_nxp_imx_mu.c b/drivers/mbox/mbox_nxp_imx_mu.c new file mode 100644 index 00000000000..3c708b95eca --- /dev/null +++ b/drivers/mbox/mbox_nxp_imx_mu.c @@ -0,0 +1,179 @@ +/* + * Wrapper of the i.MX Message Unit driver into Zephyr's MBOX model. + */ + +#include +#include +#include +#include + +#define LOG_LEVEL CONFIG_MBOX_LOG_LEVEL +#include +LOG_MODULE_REGISTER(nxp_mbox_imx_mu); + +#define DT_DRV_COMPAT nxp_mbox_imx_mu + +#define MU_MAX_CHANNELS 4 +#define MU_MBOX_SIZE sizeof(uint32_t) + +struct nxp_imx_mu_data { + mbox_callback_t cb[MU_MAX_CHANNELS]; + void *user_data[MU_MAX_CHANNELS]; +}; + +struct nxp_imx_mu_config { + MU_Type *base; +}; + +static int nxp_imx_mu_send(const struct device *dev, uint32_t channel, + const struct mbox_msg *msg) +{ + uint32_t __aligned(4) data32; + const struct nxp_imx_mu_config *cfg = dev->config; + + if (channel >= MU_MAX_CHANNELS) { + return -EINVAL; + } + + /* Signalling mode. */ + if (msg == NULL) { + return MU_TriggerInterrupts( + cfg->base, kMU_GenInt0InterruptTrigger); + } + + /* Data transfer mode. */ + if (msg->size != MU_MBOX_SIZE) { + /* We can only send this many bytes at a time. */ + return -EMSGSIZE; + } + + /* memcpy to avoid issues when msg->data is not word-aligned. */ + memcpy(&data32, msg->data, msg->size); + MU_SendMsg(cfg->base, channel, data32); + return 0; +} + +static int nxp_imx_mu_register_callback(const struct device *dev, uint32_t channel, + mbox_callback_t cb, void *user_data) +{ + struct nxp_imx_mu_data *data = dev->data; + + if (channel >= MU_MAX_CHANNELS) { + return -EINVAL; + } + + data->cb[channel] = cb; + data->user_data[channel] = user_data; + + return 0; +} + +static int nxp_imx_mu_mtu_get(const struct device *dev) +{ + ARG_UNUSED(dev); + return MU_MBOX_SIZE; +} + +static uint32_t nxp_imx_mu_max_channels_get(const struct device *dev) +{ + ARG_UNUSED(dev); + return MU_MAX_CHANNELS; +} + +static int nxp_imx_mu_set_enabled(const struct device *dev, uint32_t channel, + bool enable) +{ + struct nxp_imx_mu_data *data = dev->data; + const struct nxp_imx_mu_config *cfg = dev->config; + + if (channel >= MU_MAX_CHANNELS) { + return -EINVAL; + } + + if (enable) { + if (data->cb[channel] == NULL) { + LOG_WRN("Enabling channel without a registered callback"); + } + MU_EnableInterrupts(cfg->base, + kMU_GenInt0InterruptEnable | kMU_GenInt1InterruptEnable | + kMU_GenInt2InterruptEnable | kMU_GenInt3InterruptEnable | + kMU_Rx0FullInterruptEnable | kMU_Rx1FullInterruptEnable | + kMU_Rx2FullInterruptEnable | kMU_Rx3FullInterruptEnable); + } else { + MU_DisableInterrupts(cfg->base, + kMU_GenInt0InterruptEnable | kMU_GenInt1InterruptEnable | + kMU_GenInt2InterruptEnable | kMU_GenInt3InterruptEnable | + kMU_Rx0FullInterruptEnable | kMU_Rx1FullInterruptEnable | + kMU_Rx2FullInterruptEnable | kMU_Rx3FullInterruptEnable); + } + + return 0; +} + +static const struct mbox_driver_api nxp_imx_mu_driver_api = { + .send = nxp_imx_mu_send, + .register_callback = nxp_imx_mu_register_callback, + .mtu_get = nxp_imx_mu_mtu_get, + .max_channels_get = nxp_imx_mu_max_channels_get, + .set_enabled = nxp_imx_mu_set_enabled, +}; + +#define MU_INSTANCE_DEFINE(idx) \ + static struct nxp_imx_mu_data nxp_imx_mu_##idx##_data; \ + static struct nxp_imx_mu_config nxp_imx_mu_##idx##_config = { \ + .base = (MU_Type *)DT_INST_REG_ADDR(idx), \ + }; \ + \ + void MU_##idx##_IRQHandler(void); \ + static int nxp_imx_mu_##idx##_init(const struct device *dev) \ + { \ + ARG_UNUSED(dev); \ + MU_Init(nxp_imx_mu_##idx##_config.base); \ + IRQ_CONNECT(DT_INST_IRQN(idx), \ + DT_INST_IRQ(idx, priority), \ + MU_##idx##_IRQHandler, \ + NULL, \ + 0); \ + irq_enable(DT_INST_IRQN(idx)); \ + return 0; \ + } \ + DEVICE_DT_INST_DEFINE(idx, nxp_imx_mu_##idx##_init, NULL, \ + &nxp_imx_mu_##idx##_data, &nxp_imx_mu_##idx##_config, \ + POST_KERNEL, CONFIG_MBOX_INIT_PRIORITY, \ + &nxp_imx_mu_driver_api) + +#define MU_IRQ_HANDLER(idx) \ + static uint32_t mu_##idx##_received_data; \ + void MU_##idx##_IRQHandler(void) \ + { \ + const struct device *dev = DEVICE_DT_INST_GET(idx); \ + const struct nxp_imx_mu_data *data = dev->data; \ + const struct nxp_imx_mu_config *config = dev->config; \ + int channel = 0; \ + struct mbox_msg msg; \ + struct mbox_msg *callback_msg_ptr = NULL; \ + uint32_t flag = MU_GetStatusFlags(config->base); \ + \ + if ((flag & kMU_Rx0FullFlag) == kMU_Rx0FullFlag) { \ + mu_##idx##_received_data = \ + MU_ReceiveMsgNonBlocking(config->base, 0); \ + msg.data = (const void *)&mu_##idx##_received_data; \ + msg.size = MU_MBOX_SIZE; \ + callback_msg_ptr = &msg; \ + } else if ((flag & kMU_GenInt0Flag) == kMU_GenInt0Flag) { \ + MU_ClearStatusFlags(config->base, kMU_GenInt0Flag); \ + callback_msg_ptr = NULL; \ + } \ + \ + if (data->cb[channel]) { \ + data->cb[channel](dev, channel, \ + data->user_data[channel], \ + callback_msg_ptr); \ + } \ + } + +#define MU_INST(idx) \ + MU_INSTANCE_DEFINE(idx); \ + MU_IRQ_HANDLER(idx); + +DT_INST_FOREACH_STATUS_OKAY(MU_INST) diff --git a/drivers/mbox/mbox_nxp_s32_mru.c b/drivers/mbox/mbox_nxp_s32_mru.c index 287ba89eff8..2c6246d8dce 100644 --- a/drivers/mbox/mbox_nxp_s32_mru.c +++ b/drivers/mbox/mbox_nxp_s32_mru.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#define DT_DRV_COMPAT nxp_s32_mru + #include #include #include @@ -19,22 +21,11 @@ LOG_MODULE_REGISTER(nxp_s32_mru); #define MRU_MBOX_SIZE 4 #define MRU_CHANNEL_OFFSET 0x1000 -#define MRU_NODE(n) DT_NODELABEL(mru##n) -#define MRU_BASE(n) ((RTU_MRU_Type *)DT_REG_ADDR(MRU_NODE(n))) -#define MRU_RX_CHANNELS(n) DT_PROP_OR(MRU_NODE(n), rx_channels, 0) -#define MRU_MBOX_ADDR(n, ch, mb) \ - (DT_REG_ADDR(MRU_NODE(n)) + ((ch + 1) * MRU_CHANNEL_OFFSET) + (MRU_MBOX_SIZE * mb)) - /* Utility macros to convert from GIC index to interrupt group index */ #define _MRU_IRQ_17 MRU_IP_INT_GROUP_0 #define _MRU_IRQ_18 MRU_IP_INT_GROUP_1 #define MRU_INT_GROUP(irq) _CONCAT(_MRU_IRQ_, irq) -#define _CONCAT7(...) DT_CAT7(__VA_ARGS__) -#define MRU_ISR_FUNC(n) \ - _CONCAT7(Mru_Ip_RTU, CONFIG_NXP_S32_RTU_INDEX, _MRU, n, _Int, \ - MRU_INT_GROUP(DT_IRQN(MRU_NODE(n))), _IRQHandler) - struct nxp_s32_mru_data { mbox_callback_t cb[MRU_MAX_CHANNELS]; void *user_data[MRU_MAX_CHANNELS]; @@ -44,6 +35,7 @@ struct nxp_s32_mru_config { RTU_MRU_Type *base; Mru_Ip_ConfigType hw_cfg; void (*config_irq)(void); + uint8_t irq_group; }; static inline bool is_rx_channel_valid(const struct device *dev, uint32_t ch) @@ -178,6 +170,13 @@ static int nxp_s32_mru_init(const struct device *dev) return 0; } +void nxp_s32_mru_isr(const struct device *dev) +{ + const struct nxp_s32_mru_config *config = dev->config; + + Mru_Ip_IrqHandler(config->hw_cfg.InstanceId, config->irq_group); +} + static const struct mbox_driver_api nxp_s32_mru_driver_api = { .send = nxp_s32_mru_send, .register_callback = nxp_s32_mru_register_callback, @@ -186,18 +185,26 @@ static const struct mbox_driver_api nxp_s32_mru_driver_api = { .set_enabled = nxp_s32_mru_set_enabled, }; -#define MRU_ISR_FUNC_DECLARE(n) extern void MRU_ISR_FUNC(n)(void) +#define MRU_BASE(n) ((RTU_MRU_Type *)DT_INST_REG_ADDR(n)) +#define MRU_RX_CHANNELS(n) DT_INST_PROP_OR(n, rx_channels, 0) +#define MRU_MBOX_ADDR(n, ch, mb) \ + (DT_INST_REG_ADDR(n) + ((ch + 1) * MRU_CHANNEL_OFFSET) + (MRU_MBOX_SIZE * mb)) + +#define MRU_HW_INSTANCE_CHECK(i, n) \ + ((DT_INST_REG_ADDR(n) == IP_MRU_##i##_BASE) ? i : 0) + +#define MRU_HW_INSTANCE(n) \ + LISTIFY(__DEBRACKET RTU_MRU_INSTANCE_COUNT, MRU_HW_INSTANCE_CHECK, (|), n) #define MRU_INIT_IRQ_FUNC(n) \ - MRU_ISR_FUNC_DECLARE(n); \ static void nxp_s32_mru_##n##_init_irq(void) \ { \ - IRQ_CONNECT(DT_IRQN(MRU_NODE(n)), \ - DT_IRQ(MRU_NODE(n), priority), \ - MRU_ISR_FUNC(n), \ - NULL, \ - DT_IRQ(MRU_NODE(n), flags)); \ - irq_enable(DT_IRQN(MRU_NODE(n))); \ + IRQ_CONNECT(DT_INST_IRQN(n), \ + DT_INST_IRQ(n, priority), \ + nxp_s32_mru_isr, \ + DEVICE_DT_INST_GET(n), \ + DT_INST_IRQ(n, flags)); \ + irq_enable(DT_INST_IRQN(n)); \ } #define MRU_CH_RX_CFG(i, n) \ @@ -208,7 +215,6 @@ static const struct mbox_driver_api nxp_s32_mru_driver_api = { static uint32_t nxp_s32_mru_##n##_ch_##i##_buf[MRU_MAX_MBOX_PER_CHAN]; \ static const Mru_Ip_ReceiveChannelType nxp_s32_mru_##n##_ch_##i##_rx_cfg = { \ .ChannelId = i, \ - .InstanceId = n, \ .ChannelIndex = i, \ .NumRxMB = MRU_MAX_MBOX_PER_CHAN, \ .MBAddList = nxp_s32_mru_##n##_ch_##i##_rx_mbox_addr, \ @@ -224,7 +230,7 @@ static const struct mbox_driver_api nxp_s32_mru_driver_api = { #define MRU_CH_RX_LINK_CFG(i, n) \ static const Mru_Ip_MBLinkReceiveChannelType \ nxp_s32_mru_##n##_ch_##i##_rx_link_cfg[MRU_MAX_MBOX_PER_CHAN][MRU_MAX_INT_GROUPS] = {\ - MRU_CH_RX_LINK_CFG_MBOX(0, n, i, MRU_INT_GROUP(DT_IRQN(MRU_NODE(n)))) \ + MRU_CH_RX_LINK_CFG_MBOX(0, n, i, MRU_INT_GROUP(DT_INST_IRQN(n))) \ } #define MRU_CH_CFG(i, n) \ @@ -232,7 +238,7 @@ static const struct mbox_driver_api nxp_s32_mru_driver_api = { .ChCFG0Add = &MRU_BASE(n)->CHXCONFIG[i].CH_CFG0, \ .ChCFG0 = RTU_MRU_CH_CFG0_IE(0) | RTU_MRU_CH_CFG0_MBE0(0), \ .ChCFG1Add = &MRU_BASE(n)->CHXCONFIG[i].CH_CFG1, \ - .ChCFG1 = RTU_MRU_CH_CFG1_MBIC0(MRU_INT_GROUP(DT_IRQN(MRU_NODE(n)))), \ + .ChCFG1 = RTU_MRU_CH_CFG1_MBIC0(MRU_INT_GROUP(DT_INST_IRQN(n))), \ .ChMBSTATAdd = &MRU_BASE(n)->CHXCONFIG[i].CH_MBSTAT, \ .NumMailbox = MRU_MAX_MBOX_PER_CHAN, \ .MBLinkReceiveChCfg = nxp_s32_mru_##n##_ch_##i##_rx_link_cfg \ @@ -242,7 +248,7 @@ static const struct mbox_driver_api nxp_s32_mru_driver_api = { #define MRU_CALLBACK_WRAPPER_FUNC(n) \ void nxp_s32_mru_##n##_cb(uint8_t channel, const uint32_t *buf, uint8_t mbox_count) \ { \ - const struct device *dev = DEVICE_DT_GET(MRU_NODE(n)); \ + const struct device *dev = DEVICE_DT_INST_GET(n); \ struct nxp_s32_mru_data *data = dev->data; \ \ if (is_rx_channel_valid(dev, channel)) { \ @@ -271,53 +277,24 @@ static const struct mbox_driver_api nxp_s32_mru_driver_api = { static struct nxp_s32_mru_config nxp_s32_mru_##n##_config = { \ .base = MRU_BASE(n), \ .hw_cfg = { \ - .InstanceId = n, \ + .InstanceId = MRU_HW_INSTANCE(n), \ .StateIndex = n, \ .NumChannel = MRU_RX_CHANNELS(n), \ .ChannelCfg = COND_CODE_0(MRU_RX_CHANNELS(n), \ (NULL), (nxp_s32_mru_##n##_ch_cfg)), \ .NOTIFYAdd = { \ - &MRU_BASE(n)->NOTIFY0, \ - &MRU_BASE(n)->NOTIFY1 \ + &MRU_BASE(n)->NOTIFY[0], \ + &MRU_BASE(n)->NOTIFY[1] \ }, \ }, \ + .irq_group = MRU_INT_GROUP(DT_INST_IRQN(n)), \ .config_irq = COND_CODE_0(MRU_RX_CHANNELS(n), \ (NULL), (nxp_s32_mru_##n##_init_irq)), \ }; \ \ - DEVICE_DT_DEFINE(MRU_NODE(n), nxp_s32_mru_init, NULL, \ + DEVICE_DT_INST_DEFINE(n, nxp_s32_mru_init, NULL, \ &nxp_s32_mru_##n##_data, &nxp_s32_mru_##n##_config, \ POST_KERNEL, CONFIG_MBOX_INIT_PRIORITY, \ - &nxp_s32_mru_driver_api) - -#if DT_NODE_HAS_STATUS(MRU_NODE(0), okay) -MRU_INSTANCE_DEFINE(0); -#endif - -#if DT_NODE_HAS_STATUS(MRU_NODE(1), okay) -MRU_INSTANCE_DEFINE(1); -#endif - -#if DT_NODE_HAS_STATUS(MRU_NODE(2), okay) -MRU_INSTANCE_DEFINE(2); -#endif - -#if DT_NODE_HAS_STATUS(MRU_NODE(3), okay) -MRU_INSTANCE_DEFINE(3); -#endif - -#if DT_NODE_HAS_STATUS(MRU_NODE(4), okay) -MRU_INSTANCE_DEFINE(4); -#endif - -#if DT_NODE_HAS_STATUS(MRU_NODE(5), okay) -MRU_INSTANCE_DEFINE(5); -#endif - -#if DT_NODE_HAS_STATUS(MRU_NODE(6), okay) -MRU_INSTANCE_DEFINE(6); -#endif + &nxp_s32_mru_driver_api); -#if DT_NODE_HAS_STATUS(MRU_NODE(7), okay) -MRU_INSTANCE_DEFINE(7); -#endif +DT_INST_FOREACH_STATUS_OKAY(MRU_INSTANCE_DEFINE) diff --git a/drivers/mdio/CMakeLists.txt b/drivers/mdio/CMakeLists.txt index 7fc03a8fc8f..4972626cdb5 100644 --- a/drivers/mdio/CMakeLists.txt +++ b/drivers/mdio/CMakeLists.txt @@ -7,3 +7,4 @@ zephyr_library_sources_ifdef(CONFIG_MDIO_ATMEL_SAM mdio_sam.c) zephyr_library_sources_ifdef(CONFIG_MDIO_ESP32 mdio_esp32.c) zephyr_library_sources_ifdef(CONFIG_MDIO_NXP_S32_NETC mdio_nxp_s32_netc.c) zephyr_library_sources_ifdef(CONFIG_MDIO_ADIN2111 mdio_adin2111.c) +zephyr_library_sources_ifdef(CONFIG_MDIO_GPIO mdio_gpio.c) diff --git a/drivers/mdio/Kconfig b/drivers/mdio/Kconfig index 0f2d3b84a84..b3831b2c2d7 100644 --- a/drivers/mdio/Kconfig +++ b/drivers/mdio/Kconfig @@ -15,7 +15,6 @@ if MDIO config MDIO_SHELL bool "MDIO Shell" - default y depends on SHELL help Enable MDIO Shell. @@ -29,6 +28,7 @@ source "drivers/mdio/Kconfig.esp32" source "drivers/mdio/Kconfig.sam" source "drivers/mdio/Kconfig.nxp_s32" source "drivers/mdio/Kconfig.adin2111" +source "drivers/mdio/Kconfig.gpio" config MDIO_INIT_PRIORITY int "Init priority" diff --git a/drivers/mdio/Kconfig.gpio b/drivers/mdio/Kconfig.gpio new file mode 100644 index 00000000000..1ab5dd70dc4 --- /dev/null +++ b/drivers/mdio/Kconfig.gpio @@ -0,0 +1,9 @@ +# Copyright (c) 2023, Aleksandr Senin +# SPDX-License-Identifier: Apache-2.0 + +config MDIO_GPIO + bool "GPIO bitbang MDIO controller driver" + default y + depends on DT_HAS_ZEPHYR_MDIO_GPIO_ENABLED + help + Enable software driven (bit banging) MDIO support using GPIO pins diff --git a/drivers/mdio/Kconfig.nxp_s32 b/drivers/mdio/Kconfig.nxp_s32 index e13b1b5b2ef..61b02d53809 100644 --- a/drivers/mdio/Kconfig.nxp_s32 +++ b/drivers/mdio/Kconfig.nxp_s32 @@ -1,10 +1,11 @@ -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # SPDX-License-Identifier: Apache-2.0 config MDIO_NXP_S32_NETC bool "NXP S32 NETC External MDIO driver" default y depends on DT_HAS_NXP_S32_NETC_EMDIO_ENABLED - select NOCACHE_MEMORY + depends on ETH_NXP_S32_NETC && DT_HAS_NXP_S32_NETC_PSI_ENABLED + select NOCACHE_MEMORY if ARCH_HAS_NOCACHE_MEMORY_SUPPORT help Enable NETC External MDIO Controller driver for NXP S32 SoCs. diff --git a/drivers/mdio/mdio_adin2111.c b/drivers/mdio/mdio_adin2111.c index 39d994c9cc3..ff3cf80e43b 100644 --- a/drivers/mdio/mdio_adin2111.c +++ b/drivers/mdio/mdio_adin2111.c @@ -14,7 +14,6 @@ LOG_MODULE_REGISTER(mdio_adin2111, CONFIG_MDIO_LOG_LEVEL); #include #include #include -#include #include /* MDIO ready check retry delay */ @@ -56,9 +55,9 @@ static int mdio_adin2111_wait_ready(const struct device *dev, uint16_t reg, } -int adin2111_mdio_c45_read(const struct device *dev, uint8_t prtad, - uint8_t devad, uint16_t regad, - uint16_t *data) +static int mdio_adin2111_read_c45(const struct device *dev, uint8_t prtad, + uint8_t devad, uint16_t regad, + uint16_t *data) { const struct mdio_adin2111_config *const cfg = dev->config; uint32_t rdy; @@ -96,9 +95,9 @@ int adin2111_mdio_c45_read(const struct device *dev, uint8_t prtad, return ret; } -int adin2111_mdio_c45_write(const struct device *dev, uint8_t prtad, - uint8_t devad, uint16_t regad, - uint16_t data) +static int mdio_adin2111_write_c45(const struct device *dev, uint8_t prtad, + uint8_t devad, uint16_t regad, + uint16_t data) { const struct mdio_adin2111_config *const cfg = dev->config; @@ -131,7 +130,7 @@ int adin2111_mdio_c45_write(const struct device *dev, uint8_t prtad, } static int mdio_adin2111_read(const struct device *dev, uint8_t prtad, - uint8_t devad, uint16_t *data) + uint8_t regad, uint16_t *data) { const struct mdio_adin2111_config *const cfg = dev->config; uint32_t read; @@ -141,7 +140,7 @@ static int mdio_adin2111_read(const struct device *dev, uint8_t prtad, cmd = BIT(28); cmd |= 0x3U << 26; cmd |= (prtad & 0x1FU) << 21; - cmd |= (devad & 0x1FU) << 16; + cmd |= (regad & 0x1FU) << 16; ret = eth_adin2111_reg_write(cfg->adin, ADIN2111_MDIOACC0, cmd); if (ret >= 0) { @@ -153,7 +152,7 @@ static int mdio_adin2111_read(const struct device *dev, uint8_t prtad, } static int mdio_adin2111_write(const struct device *dev, uint8_t prtad, - uint8_t devad, uint16_t data) + uint8_t regad, uint16_t data) { const struct mdio_adin2111_config *const cfg = dev->config; uint32_t cmd; @@ -163,7 +162,7 @@ static int mdio_adin2111_write(const struct device *dev, uint8_t prtad, cmd = BIT(28); cmd |= BIT(26); cmd |= (prtad & 0x1FU) << 21; - cmd |= (devad & 0x1FU) << 16; + cmd |= (regad & 0x1FU) << 16; cmd |= data; ret = eth_adin2111_reg_write(cfg->adin, ADIN2111_MDIOACC0, cmd); @@ -191,6 +190,8 @@ static void mdio_adin2111_bus_disable(const struct device *dev) static const struct mdio_driver_api mdio_adin2111_api = { .read = mdio_adin2111_read, .write = mdio_adin2111_write, + .read_c45 = mdio_adin2111_read_c45, + .write_c45 = mdio_adin2111_write_c45, .bus_enable = mdio_adin2111_bus_enable, .bus_disable = mdio_adin2111_bus_disable }; diff --git a/drivers/mdio/mdio_esp32.c b/drivers/mdio/mdio_esp32.c index fb243346669..871380c9a0a 100644 --- a/drivers/mdio/mdio_esp32.c +++ b/drivers/mdio/mdio_esp32.c @@ -30,7 +30,7 @@ struct mdio_esp32_dev_config { const struct pinctrl_dev_config *pcfg; }; -static int mdio_transfer(const struct device *dev, uint8_t prtad, uint8_t devad, +static int mdio_transfer(const struct device *dev, uint8_t prtad, uint8_t regad, bool write, uint16_t data_in, uint16_t *data_out) { struct mdio_esp32_dev_data *const dev_data = dev->data; @@ -46,7 +46,7 @@ static int mdio_transfer(const struct device *dev, uint8_t prtad, uint8_t devad, if (write) { emac_ll_set_phy_data(dev_data->hal.mac_regs, data_in); } - emac_hal_set_phy_cmd(&dev_data->hal, prtad, devad, write); + emac_hal_set_phy_cmd(&dev_data->hal, prtad, regad, write); /* Poll until operation complete */ bool success = false; @@ -73,17 +73,17 @@ static int mdio_transfer(const struct device *dev, uint8_t prtad, uint8_t devad, return 0; } -static int mdio_esp32_read(const struct device *dev, uint8_t prtad, uint8_t devad, +static int mdio_esp32_read(const struct device *dev, uint8_t prtad, uint8_t regad, uint16_t *data) { - return mdio_transfer(dev, prtad, devad, false, 0, data); + return mdio_transfer(dev, prtad, regad, false, 0, data); } static int mdio_esp32_write(const struct device *dev, uint8_t prtad, - uint8_t devad, uint16_t data) + uint8_t regad, uint16_t data) { - return mdio_transfer(dev, prtad, devad, true, data, NULL); + return mdio_transfer(dev, prtad, regad, true, data, NULL); } static void mdio_esp32_bus_enable(const struct device *dev) @@ -143,12 +143,7 @@ static const struct mdio_esp32_dev_config mdio_esp32_dev_config_##n = { \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ }; -#define MDIO_ESP32_PROTOCOL_ASSERT(n) \ - BUILD_ASSERT(DT_INST_ENUM_IDX(n, protocol) == CLAUSE_22, \ - "ESP32 MDIO only supports CLAUSE_22 protocol") - #define MDIO_ESP32_DEVICE(n) \ - MDIO_ESP32_PROTOCOL_ASSERT(n); \ PINCTRL_DT_INST_DEFINE(n); \ MDIO_ESP32_CONFIG(n); \ static struct mdio_esp32_dev_data mdio_esp32_dev_data##n; \ diff --git a/drivers/mdio/mdio_gpio.c b/drivers/mdio/mdio_gpio.c new file mode 100644 index 00000000000..25f67cd41b1 --- /dev/null +++ b/drivers/mdio/mdio_gpio.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2023 Aleksandr Senin + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT zephyr_mdio_gpio + +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(mdio_gpio, CONFIG_MDIO_LOG_LEVEL); + +#define MDIO_GPIO_READ_OP 0 +#define MDIO_GPIO_WRITE_OP 1 +#define MDIO_GPIO_MSB 0x80000000 + +struct mdio_gpio_data { + struct k_sem sem; +}; + +struct mdio_gpio_config { + struct gpio_dt_spec mdc_gpio; + struct gpio_dt_spec mdio_gpio; +}; + +static ALWAYS_INLINE void mdio_gpio_clock_the_bit(const struct mdio_gpio_config *dev_cfg) +{ + k_busy_wait(1); + gpio_pin_set_dt(&dev_cfg->mdc_gpio, 1); + k_busy_wait(1); + gpio_pin_set_dt(&dev_cfg->mdc_gpio, 0); +} + +static ALWAYS_INLINE void mdio_gpio_dir(const struct mdio_gpio_config *dev_cfg, uint8_t dir) +{ + gpio_pin_configure_dt(&dev_cfg->mdio_gpio, dir ? GPIO_OUTPUT_ACTIVE : GPIO_INPUT); + if (dir == 0) { + mdio_gpio_clock_the_bit(dev_cfg); + } +} + +static ALWAYS_INLINE void mdio_gpio_read(const struct mdio_gpio_config *dev_cfg, uint16_t *pdata) +{ + uint16_t data = 0; + + for (uint16_t i = 0; i < 16; i++) { + data <<= 1; + mdio_gpio_clock_the_bit(dev_cfg); + if (gpio_pin_get_dt(&dev_cfg->mdio_gpio) == 1) { + data |= 1; + } + } + + *pdata = data; +} + +static ALWAYS_INLINE void mdio_gpio_write(const struct mdio_gpio_config *dev_cfg, + uint32_t data, uint8_t len) +{ + uint32_t v_data = data; + uint32_t v_len = len; + + v_data <<= 32 - v_len; + for (; v_len > 0; v_len--) { + gpio_pin_set_dt(&dev_cfg->mdio_gpio, (v_data & MDIO_GPIO_MSB) ? 1 : 0); + mdio_gpio_clock_the_bit(dev_cfg); + v_data <<= 1; + } +} + +static int mdio_gpio_transfer(const struct device *dev, uint8_t prtad, uint8_t devad, uint8_t rw, + uint16_t data_in, uint16_t *data_out) +{ + const struct mdio_gpio_config *const dev_cfg = dev->config; + struct mdio_gpio_data *const dev_data = dev->data; + + k_sem_take(&dev_data->sem, K_FOREVER); + + /* DIR: output */ + mdio_gpio_dir(dev_cfg, MDIO_GPIO_WRITE_OP); + /* PRE32: 32 bits '1' for sync*/ + mdio_gpio_write(dev_cfg, 0xFFFFFFFF, 32); + /* ST: 2 bits start of frame */ + mdio_gpio_write(dev_cfg, 0x1, 2); + /* OP: 2 bits opcode, read '10' or write '01' */ + mdio_gpio_write(dev_cfg, rw ? 0x1 : 0x2, 2); + /* PA5: 5 bits PHY address */ + mdio_gpio_write(dev_cfg, prtad, 5); + /* RA5: 5 bits register address */ + mdio_gpio_write(dev_cfg, devad, 5); + + if (rw) { /* Write data */ + /* TA: 2 bits turn-around */ + mdio_gpio_write(dev_cfg, 0x2, 2); + mdio_gpio_write(dev_cfg, data_in, 16); + } else { /* Read data */ + /* Release the MDIO line */ + mdio_gpio_dir(dev_cfg, MDIO_GPIO_READ_OP); + mdio_gpio_read(dev_cfg, data_out); + } + + /* DIR: input. Tristate MDIO line */ + mdio_gpio_dir(dev_cfg, MDIO_GPIO_READ_OP); + + k_sem_give(&dev_data->sem); + + return 0; +} + +static int mdio_gpio_read_mmi(const struct device *dev, uint8_t prtad, uint8_t devad, + uint16_t *data) +{ + return mdio_gpio_transfer(dev, prtad, devad, MDIO_GPIO_READ_OP, 0, data); +} + +static int mdio_gpio_write_mmi(const struct device *dev, uint8_t prtad, uint8_t devad, + uint16_t data) +{ + return mdio_gpio_transfer(dev, prtad, devad, MDIO_GPIO_WRITE_OP, data, NULL); +} + +static int mdio_gpio_initialize(const struct device *dev) +{ + const struct mdio_gpio_config *const dev_cfg = dev->config; + struct mdio_gpio_data *const dev_data = dev->data; + int rc; + + k_sem_init(&dev_data->sem, 1, 1); + + if (!device_is_ready(dev_cfg->mdc_gpio.port)) { + LOG_ERR("GPIO port for MDC pin is not ready"); + return -ENODEV; + } + + if (!device_is_ready(dev_cfg->mdio_gpio.port)) { + LOG_ERR("GPIO port for MDIO pin is not ready"); + return -ENODEV; + } + + rc = gpio_pin_configure_dt(&dev_cfg->mdc_gpio, GPIO_OUTPUT_INACTIVE); + if (rc < 0) { + LOG_ERR("Couldn't configure MDC pin; (%d)", rc); + return rc; + } + + rc = gpio_pin_configure_dt(&dev_cfg->mdio_gpio, GPIO_INPUT); + if (rc < 0) { + LOG_ERR("Couldn't configure MDIO pin; (%d)", rc); + return rc; + } + + return 0; +} + +static void mdio_gpio_bus_enable(const struct device *dev) +{ + ARG_UNUSED(dev); +} + +static void mdio_gpio_bus_disable(const struct device *dev) +{ + ARG_UNUSED(dev); +} + +static const struct mdio_driver_api mdio_gpio_driver_api = { + .read = mdio_gpio_read_mmi, + .write = mdio_gpio_write_mmi, + .bus_enable = mdio_gpio_bus_enable, + .bus_disable = mdio_gpio_bus_disable, +}; + +#define MDIO_GPIO_CONFIG(inst) \ + static struct mdio_gpio_config mdio_gpio_dev_config_##inst = { \ + .mdc_gpio = GPIO_DT_SPEC_INST_GET(inst, mdc_gpios), \ + .mdio_gpio = GPIO_DT_SPEC_INST_GET(inst, mdio_gpios), \ + }; + +#define MDIO_GPIO_DEVICE(inst) \ + MDIO_GPIO_CONFIG(inst); \ + static struct mdio_gpio_data mdio_gpio_dev_data_##inst; \ + DEVICE_DT_INST_DEFINE(inst, &mdio_gpio_initialize, NULL, &mdio_gpio_dev_data_##inst, \ + &mdio_gpio_dev_config_##inst, POST_KERNEL, \ + CONFIG_MDIO_INIT_PRIORITY, &mdio_gpio_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(MDIO_GPIO_DEVICE) diff --git a/drivers/mdio/mdio_nxp_s32_netc.c b/drivers/mdio/mdio_nxp_s32_netc.c index 4ce88ac96f7..ff8a561d974 100644 --- a/drivers/mdio/mdio_nxp_s32_netc.c +++ b/drivers/mdio/mdio_nxp_s32_netc.c @@ -1,9 +1,11 @@ /* - * Copyright 2022 NXP + * Copyright 2022-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ +#define DT_DRV_COMPAT nxp_s32_netc_emdio + #include #include #include @@ -12,12 +14,9 @@ LOG_MODULE_REGISTER(nxp_s32_emdio, CONFIG_MDIO_LOG_LEVEL); #include -#define MDIO_NODE DT_NODELABEL(emdio) -#define NETC_SWT_IDX 0 - struct nxp_s32_mdio_config { - int protocol; const struct pinctrl_dev_config *pincfg; + uint8_t instance; }; struct nxp_s32_mdio_data { @@ -25,38 +24,28 @@ struct nxp_s32_mdio_data { }; static int nxp_s32_mdio_read(const struct device *dev, uint8_t prtad, - uint8_t devad, uint16_t *regval) + uint8_t regad, uint16_t *regval) { - const struct nxp_s32_mdio_config *const cfg = dev->config; + const struct nxp_s32_mdio_config *cfg = dev->config; struct nxp_s32_mdio_data *data = dev->data; Std_ReturnType status; - if (cfg->protocol != CLAUSE_22) { - LOG_ERR("Unsupported protocol"); - return -ENOTSUP; - } - k_mutex_lock(&data->rw_mutex, K_FOREVER); - status = Netc_EthSwt_Ip_ReadTrcvRegister(NETC_SWT_IDX, prtad, devad, regval); + status = Netc_EthSwt_Ip_ReadTrcvRegister(cfg->instance, prtad, regad, regval); k_mutex_unlock(&data->rw_mutex); return status == E_OK ? 0 : -EIO; } static int nxp_s32_mdio_write(const struct device *dev, uint8_t prtad, - uint8_t devad, uint16_t regval) + uint8_t regad, uint16_t regval) { - const struct nxp_s32_mdio_config *const cfg = dev->config; + const struct nxp_s32_mdio_config *cfg = dev->config; struct nxp_s32_mdio_data *data = dev->data; Std_ReturnType status; - if (cfg->protocol != CLAUSE_22) { - LOG_ERR("Unsupported protocol"); - return -ENOTSUP; - } - k_mutex_lock(&data->rw_mutex, K_FOREVER); - status = Netc_EthSwt_Ip_WriteTrcvRegister(NETC_SWT_IDX, prtad, devad, regval); + status = Netc_EthSwt_Ip_WriteTrcvRegister(cfg->instance, prtad, regad, regval); k_mutex_unlock(&data->rw_mutex); return status == E_OK ? 0 : -EIO; @@ -91,20 +80,26 @@ static const struct mdio_driver_api nxp_s32_mdio_api = { .bus_disable = nxp_s32_mdio_noop, }; -PINCTRL_DT_DEFINE(MDIO_NODE); - -static struct nxp_s32_mdio_data nxp_s32_mdio0_data; - -static const struct nxp_s32_mdio_config nxp_s32_mdio0_cfg = { - .protocol = DT_ENUM_IDX(MDIO_NODE, protocol), - .pincfg = PINCTRL_DT_DEV_CONFIG_GET(MDIO_NODE), -}; - -DEVICE_DT_DEFINE(MDIO_NODE, - &nxp_s32_mdio_initialize, - NULL, - &nxp_s32_mdio0_data, - &nxp_s32_mdio0_cfg, - POST_KERNEL, - CONFIG_MDIO_INIT_PRIORITY, - &nxp_s32_mdio_api); +#define NXP_S32_MDIO_HW_INSTANCE_CHECK(i, n) \ + ((DT_INST_REG_ADDR(n) == IP_NETC_EMDIO_##n##_BASE) ? i : 0) + +#define NXP_S32_MDIO_HW_INSTANCE(n) \ + LISTIFY(__DEBRACKET NETC_F1_INSTANCE_COUNT, NXP_S32_MDIO_HW_INSTANCE_CHECK, (|), n) + +#define NXP_S32_MDIO_INSTANCE_DEFINE(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + static struct nxp_s32_mdio_data nxp_s32_mdio##n##_data; \ + static const struct nxp_s32_mdio_config nxp_s32_mdio##n##_cfg = { \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .instance = NXP_S32_MDIO_HW_INSTANCE(n), \ + }; \ + DEVICE_DT_INST_DEFINE(n, \ + &nxp_s32_mdio_initialize, \ + NULL, \ + &nxp_s32_mdio##n##_data, \ + &nxp_s32_mdio##n##_cfg, \ + POST_KERNEL, \ + CONFIG_MDIO_INIT_PRIORITY, \ + &nxp_s32_mdio_api); + +DT_INST_FOREACH_STATUS_OKAY(NXP_S32_MDIO_INSTANCE_DEFINE) diff --git a/drivers/mdio/mdio_sam.c b/drivers/mdio/mdio_sam.c index 950dfe7f00f..5665057f7c9 100644 --- a/drivers/mdio/mdio_sam.c +++ b/drivers/mdio/mdio_sam.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 IP-Logix Inc. + * Copyright 2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,8 +12,10 @@ #include #include #include +#include #include #include +#include #include LOG_MODULE_REGISTER(mdio_sam, CONFIG_MDIO_LOG_LEVEL); @@ -31,11 +34,14 @@ struct mdio_sam_dev_data { struct mdio_sam_dev_config { Gmac * const regs; const struct pinctrl_dev_config *pcfg; - int protocol; +#ifdef CONFIG_SOC_FAMILY_SAM + const struct atmel_sam_pmc_config clock_cfg; +#endif }; -static int mdio_transfer(const struct device *dev, uint8_t prtad, uint8_t devad, - uint8_t rw, uint16_t data_in, uint16_t *data_out) +static int mdio_transfer(const struct device *dev, uint8_t prtad, uint8_t regad, + enum mdio_opcode op, bool c45, uint16_t data_in, + uint16_t *data_out) { const struct mdio_sam_dev_config *const cfg = dev->config; struct mdio_sam_dev_data *const data = dev->data; @@ -44,24 +50,12 @@ static int mdio_transfer(const struct device *dev, uint8_t prtad, uint8_t devad, k_sem_take(&data->sem, K_FOREVER); /* Write mdio transaction */ - if (cfg->protocol == CLAUSE_45) { - cfg->regs->GMAC_MAN = (GMAC_MAN_OP(rw ? 0x2 : 0x3)) - | GMAC_MAN_WTN(0x02) - | GMAC_MAN_PHYA(prtad) - | GMAC_MAN_REGA(devad) - | GMAC_MAN_DATA(data_in); - - } else if (cfg->protocol == CLAUSE_22) { - cfg->regs->GMAC_MAN = GMAC_MAN_CLTTO - | (GMAC_MAN_OP(rw ? 0x2 : 0x1)) - | GMAC_MAN_WTN(0x02) - | GMAC_MAN_PHYA(prtad) - | GMAC_MAN_REGA(devad) - | GMAC_MAN_DATA(data_in); - - } else { - LOG_ERR("Unsupported protocol"); - } + cfg->regs->GMAC_MAN = (c45 ? 0U : GMAC_MAN_CLTTO) + | GMAC_MAN_OP(op) + | GMAC_MAN_WTN(0x02) + | GMAC_MAN_PHYA(prtad) + | GMAC_MAN_REGA(regad) + | GMAC_MAN_DATA(data_in); /* Wait until done */ while (!(cfg->regs->GMAC_NSR & GMAC_NSR_IDLE)) { @@ -84,16 +78,48 @@ static int mdio_transfer(const struct device *dev, uint8_t prtad, uint8_t devad, return 0; } -static int mdio_sam_read(const struct device *dev, uint8_t prtad, uint8_t devad, +static int mdio_sam_read(const struct device *dev, uint8_t prtad, uint8_t regad, uint16_t *data) { - return mdio_transfer(dev, prtad, devad, 1, 0, data); + return mdio_transfer(dev, prtad, regad, MDIO_OP_C22_READ, false, + 0, data); } static int mdio_sam_write(const struct device *dev, uint8_t prtad, - uint8_t devad, uint16_t data) + uint8_t regad, uint16_t data) { - return mdio_transfer(dev, prtad, devad, 0, data, NULL); + return mdio_transfer(dev, prtad, regad, MDIO_OP_C22_WRITE, false, + data, NULL); +} + +static int mdio_sam_read_c45(const struct device *dev, uint8_t prtad, + uint8_t devad, uint16_t regad, uint16_t *data) +{ + int err; + + err = mdio_transfer(dev, prtad, devad, MDIO_OP_C45_ADDRESS, true, + regad, NULL); + if (!err) { + err = mdio_transfer(dev, prtad, devad, MDIO_OP_C45_READ, true, + 0, data); + } + + return err; +} + +static int mdio_sam_write_c45(const struct device *dev, uint8_t prtad, + uint8_t devad, uint16_t regad, uint16_t data) +{ + int err; + + err = mdio_transfer(dev, prtad, devad, MDIO_OP_C45_ADDRESS, true, + regad, NULL); + if (!err) { + err = mdio_transfer(dev, prtad, devad, MDIO_OP_C45_WRITE, true, + data, NULL); + } + + return err; } static void mdio_sam_bus_enable(const struct device *dev) @@ -118,6 +144,15 @@ static int mdio_sam_initialize(const struct device *dev) k_sem_init(&data->sem, 1, 1); +#ifdef CONFIG_SOC_FAMILY_SAM + /* Enable GMAC module's clock */ + (void) clock_control_on(SAM_DT_PMC_CONTROLLER, (clock_control_subsys_t) &cfg->clock_cfg); +#else + /* Enable MCLK clock on GMAC */ + MCLK->AHBMASK.reg |= MCLK_AHBMASK_GMAC; + *MCLK_GMAC |= MCLK_GMAC_MASK; +#endif + retval = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); return retval; @@ -126,15 +161,22 @@ static int mdio_sam_initialize(const struct device *dev) static const struct mdio_driver_api mdio_sam_driver_api = { .read = mdio_sam_read, .write = mdio_sam_write, + .read_c45 = mdio_sam_read_c45, + .write_c45 = mdio_sam_write_c45, .bus_enable = mdio_sam_bus_enable, .bus_disable = mdio_sam_bus_disable, }; +#define MDIO_SAM_CLOCK(n) \ + COND_CODE_1(CONFIG_SOC_FAMILY_SAM, \ + (.clock_cfg = SAM_DT_INST_CLOCK_PMC_CFG(n),), () \ + ) + #define MDIO_SAM_CONFIG(n) \ static const struct mdio_sam_dev_config mdio_sam_dev_config_##n = { \ .regs = (Gmac *)DT_INST_REG_ADDR(n), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ - .protocol = DT_INST_ENUM_IDX(n, protocol), \ + MDIO_SAM_CLOCK(n) \ }; #define MDIO_SAM_DEVICE(n) \ diff --git a/drivers/mdio/mdio_shell.c b/drivers/mdio/mdio_shell.c index 090cde16ece..b70ff7bc1a0 100644 --- a/drivers/mdio/mdio_shell.c +++ b/drivers/mdio/mdio_shell.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 IP-Logix Inc. + * Copyright 2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -24,6 +25,8 @@ LOG_MODULE_REGISTER(mdio_shell, CONFIG_LOG_DEFAULT_LEVEL); #define DT_DRV_COMPAT adi_adin2111_mdio #elif DT_HAS_COMPAT_STATUS_OKAY(smsc_lan91c111_mdio) #define DT_DRV_COMPAT smsc_lan91c111_mdio +#elif DT_HAS_COMPAT_STATUS_OKAY(zephyr_mdio_gpio) +#define DT_DRV_COMPAT zephyr_mdio_gpio #else #error "No known devicetree compatible match for MDIO shell" #endif @@ -33,14 +36,14 @@ LOG_MODULE_REGISTER(mdio_shell, CONFIG_LOG_DEFAULT_LEVEL); /* * Scan the entire 5-bit address space of the MDIO bus * - * scan [] + * scan [] */ static int cmd_mdio_scan(const struct shell *sh, size_t argc, char **argv) { const struct device *dev; int cnt; uint16_t data; - uint16_t dev_addr; + uint16_t reg_addr; dev = DEVICE_DT_GET(MDIO_NODE_ID); if (!device_is_ready(dev)) { @@ -50,21 +53,21 @@ static int cmd_mdio_scan(const struct shell *sh, size_t argc, char **argv) } if (argc >= 2) { - dev_addr = strtol(argv[1], NULL, 16); + reg_addr = strtol(argv[1], NULL, 16); } else { - dev_addr = 0; + reg_addr = 0; } shell_print(sh, "Scanning bus for devices. Reading register 0x%x", - dev_addr); + reg_addr); cnt = 0; mdio_bus_enable(dev); for (int i = 0; i < 32; i++) { data = 0; - if (mdio_read(dev, i, dev_addr, &data) >= 0 && + if (mdio_read(dev, i, reg_addr, &data) >= 0 && data != UINT16_MAX) { cnt++; shell_print(sh, "Found MDIO device @ 0x%x", i); @@ -78,12 +81,12 @@ static int cmd_mdio_scan(const struct shell *sh, size_t argc, char **argv) return 0; } -/* mdio write */ +/* mdio write */ static int cmd_mdio_write(const struct shell *sh, size_t argc, char **argv) { const struct device *dev; uint16_t data; - uint16_t dev_addr; + uint16_t reg_addr; uint16_t port_addr; dev = DEVICE_DT_GET(MDIO_NODE_ID); @@ -94,12 +97,12 @@ static int cmd_mdio_write(const struct shell *sh, size_t argc, char **argv) } port_addr = strtol(argv[1], NULL, 16); - dev_addr = strtol(argv[2], NULL, 16); + reg_addr = strtol(argv[2], NULL, 16); data = strtol(argv[3], NULL, 16); mdio_bus_enable(dev); - if (mdio_write(dev, port_addr, dev_addr, data) < 0) { + if (mdio_write(dev, port_addr, reg_addr, data) < 0) { shell_error(sh, "Failed to write to device: %s", dev->name); mdio_bus_disable(dev); @@ -111,12 +114,12 @@ static int cmd_mdio_write(const struct shell *sh, size_t argc, char **argv) return 0; } -/* mdio read */ +/* mdio read */ static int cmd_mdio_read(const struct shell *sh, size_t argc, char **argv) { const struct device *dev; uint16_t data; - uint16_t dev_addr; + uint16_t reg_addr; uint16_t port_addr; dev = DEVICE_DT_GET(MDIO_NODE_ID); @@ -126,12 +129,83 @@ static int cmd_mdio_read(const struct shell *sh, size_t argc, char **argv) return -ENODEV; } + port_addr = strtol(argv[1], NULL, 16); + reg_addr = strtol(argv[2], NULL, 16); + + mdio_bus_enable(dev); + + if (mdio_read(dev, port_addr, reg_addr, &data) < 0) { + shell_error(sh, "Failed to read from device: %s", dev->name); + mdio_bus_disable(dev); + + return -EIO; + } + + mdio_bus_disable(dev); + + shell_print(sh, "%x[%x]: 0x%x", port_addr, reg_addr, data); + + return 0; +} + +/* mdio write_c45 */ +static int cmd_mdio_write_45(const struct shell *sh, size_t argc, char **argv) +{ + const struct device *dev; + uint16_t data; + uint16_t reg_addr; + uint8_t dev_addr; + uint8_t port_addr; + + dev = DEVICE_DT_GET(MDIO_NODE_ID); + if (!device_is_ready(dev)) { + shell_error(sh, "MDIO: Device driver %s is not ready.", dev->name); + + return -ENODEV; + } + + port_addr = strtol(argv[1], NULL, 16); + dev_addr = strtol(argv[2], NULL, 16); + reg_addr = strtol(argv[3], NULL, 16); + data = strtol(argv[4], NULL, 16); + + mdio_bus_enable(dev); + + if (mdio_write_c45(dev, port_addr, dev_addr, reg_addr, data) < 0) { + shell_error(sh, "Failed to write to device: %s", dev->name); + mdio_bus_disable(dev); + + return -EIO; + } + + mdio_bus_disable(dev); + + return 0; +} + +/* mdio read_c45 */ +static int cmd_mdio_read_c45(const struct shell *sh, size_t argc, char **argv) +{ + const struct device *dev; + uint16_t data; + uint16_t reg_addr; + uint8_t dev_addr; + uint8_t port_addr; + + dev = DEVICE_DT_GET(MDIO_NODE_ID); + if (!device_is_ready(dev)) { + shell_error(sh, "MDIO: Device driver %s is not ready.", dev->name); + + return -ENODEV; + } + port_addr = strtol(argv[1], NULL, 16); dev_addr = strtol(argv[2], NULL, 16); + reg_addr = strtol(argv[3], NULL, 16); mdio_bus_enable(dev); - if (mdio_read(dev, port_addr, dev_addr, &data) < 0) { + if (mdio_read_c45(dev, port_addr, dev_addr, reg_addr, &data) < 0) { shell_error(sh, "Failed to read from device: %s", dev->name); mdio_bus_disable(dev); @@ -140,21 +214,29 @@ static int cmd_mdio_read(const struct shell *sh, size_t argc, char **argv) mdio_bus_disable(dev); - shell_print(sh, "%x[%x]: 0x%x", port_addr, dev_addr, data); + shell_print(sh, "%x[%x:%x]: 0x%x", port_addr, dev_addr, reg_addr, data); return 0; } SHELL_STATIC_SUBCMD_SET_CREATE(sub_mdio_cmds, SHELL_CMD_ARG(scan, NULL, - "Scan MDIO bus for devices: scan []", + "Scan MDIO bus for devices: scan []", cmd_mdio_scan, 0, 1), SHELL_CMD_ARG(read, NULL, - "Read from MDIO device: read ", + "Read from MDIO device: read ", cmd_mdio_read, 3, 0), SHELL_CMD_ARG(write, NULL, - "Write to MDIO device: write ", + "Write to MDIO device: write ", cmd_mdio_write, 4, 0), + SHELL_CMD_ARG(read_c45, NULL, + "Read from MDIO Clause 45 device: " + "read_c45 ", + cmd_mdio_read_c45, 4, 0), + SHELL_CMD_ARG(write_c45, NULL, + "Write to MDIO Clause 45 device: " + "write_c45 ", + cmd_mdio_write_45, 5, 0), SHELL_SUBCMD_SET_END /* Array terminated. */ ); diff --git a/drivers/memc/CMakeLists.txt b/drivers/memc/CMakeLists.txt index ca967b1a045..8aaedc22073 100644 --- a/drivers/memc/CMakeLists.txt +++ b/drivers/memc/CMakeLists.txt @@ -11,6 +11,7 @@ zephyr_library_sources_ifdef(CONFIG_MEMC_MCUX_FLEXSPI memc_mcux_flexspi.c) zephyr_library_sources_ifdef(CONFIG_MEMC_MCUX_FLEXSPI_W956A8MBYA memc_mcux_flexspi_w956a8mbya.c) zephyr_library_sources_ifdef(CONFIG_MEMC_MCUX_FLEXSPI_S27KS0641 memc_mcux_flexspi_s27ks0641.c) zephyr_library_sources_ifdef(CONFIG_MEMC_MCUX_FLEXSPI_APS6408L memc_mcux_flexspi_aps6408l.c) +zephyr_library_sources_ifdef(CONFIG_MEMC_NXP_FLEXRAM memc_nxp_flexram.c) zephyr_library_sources_ifdef(CONFIG_MEMC_SAM_SMC memc_sam_smc.c) diff --git a/drivers/memc/Kconfig.mcux b/drivers/memc/Kconfig.mcux index ed7e73929db..e801e7577ae 100644 --- a/drivers/memc/Kconfig.mcux +++ b/drivers/memc/Kconfig.mcux @@ -1,4 +1,4 @@ -# Copyright (c) 2020-2022 NXP +# Copyright 2020-2023 NXP # Copyright (c) 2021 Basalte bv # Copyright (c) 2023, ithinx GmbH # Copyright (c) 2023, Tonies GmbH @@ -28,4 +28,23 @@ config MEMC_MCUX_FLEXSPI bool select PINCTRL -endif +endif # DT_HAS_NXP_IMX_FLEXSPI_ENABLED + + +if DT_HAS_NXP_FLEXRAM_ENABLED + +config MEMC_NXP_FLEXRAM + bool + default y + +config MEMC_NXP_FLEXRAM_MAGIC_ADDR_API + bool "NXP FlexRAM magic addr API" + help + Enable API to use flexRAM magic address functionality + +config MEMC_NXP_FLEXRAM_ERROR_INTERRUPT + bool "NXP FlexRAM error interrupt" + help + Allow flexram to generate error interrupts + +endif # DT_HAS_NXP_FLEXRAM_ENABLED diff --git a/drivers/memc/memc_mcux_flexspi.c b/drivers/memc/memc_mcux_flexspi.c index d67e730fd91..84ab86a793a 100644 --- a/drivers/memc/memc_mcux_flexspi.c +++ b/drivers/memc/memc_mcux_flexspi.c @@ -26,6 +26,8 @@ read-while-write hazards. This configuration is not recommended." #endif +#define FLEXSPI_MAX_LUT 64U + LOG_MODULE_REGISTER(memc_flexspi, CONFIG_MEMC_LOG_LEVEL); struct memc_flexspi_buf_cfg { @@ -35,6 +37,12 @@ struct memc_flexspi_buf_cfg { uint16_t buf_size; } __packed; +/* Structure tracking LUT offset and usage per each port */ +struct port_lut { + uint8_t lut_offset; + uint8_t lut_used; +}; + /* flexspi device data should be stored in RAM to avoid read-while-write hazards */ struct memc_flexspi_data { FLEXSPI_Type *base; @@ -49,6 +57,7 @@ struct memc_flexspi_data { flexspi_read_sample_clock_t rx_sample_clock; const struct pinctrl_dev_config *pincfg; size_t size[kFLEXSPI_PortCount]; + struct port_lut port_luts[kFLEXSPI_PortCount]; struct memc_flexspi_buf_cfg *buf_cfg; uint8_t buf_cfg_cnt; }; @@ -68,16 +77,6 @@ bool memc_flexspi_is_running_xip(const struct device *dev) return data->xip; } -int memc_flexspi_update_lut(const struct device *dev, uint32_t index, - const uint32_t *cmd, uint32_t count) -{ - struct memc_flexspi_data *data = dev->data; - - FLEXSPI_UpdateLUT(data->base, index, cmd, count); - - return 0; -} - int memc_flexspi_update_clock(const struct device *dev, flexspi_device_config_t *device_config, flexspi_port_t port, enum memc_flexspi_clock_t clock) @@ -108,20 +107,65 @@ int memc_flexspi_update_clock(const struct device *dev, int memc_flexspi_set_device_config(const struct device *dev, const flexspi_device_config_t *device_config, + const uint32_t *lut_array, + uint8_t lut_count, flexspi_port_t port) { + flexspi_device_config_t tmp_config; + uint32_t tmp_lut[FLEXSPI_MAX_LUT]; struct memc_flexspi_data *data = dev->data; + const uint32_t *lut_ptr = lut_array; + uint8_t lut_used = 0U; + unsigned int key = 0; if (port >= kFLEXSPI_PortCount) { LOG_ERR("Invalid port number"); return -EINVAL; } + if (data->port_luts[port].lut_used < lut_count) { + /* We cannot reuse the existing LUT slot, + * Check if the LUT table will fit into the remaining LUT slots + */ + for (uint8_t i = 0; i < kFLEXSPI_PortCount; i++) { + lut_used += data->port_luts[i].lut_used; + } + + if ((lut_used + lut_count) > FLEXSPI_MAX_LUT) { + return -ENOBUFS; + } + } + data->size[port] = device_config->flashSize * KB(1); - FLEXSPI_SetFlashConfig(data->base, - (flexspi_device_config_t *) device_config, - port); + if (memc_flexspi_is_running_xip(dev)) { + /* We need to avoid flash access while configuring the FlexSPI. + * To do this, we will copy the LUT array into stack-allocated + * temporary memory + */ + memcpy(tmp_lut, lut_array, lut_count * MEMC_FLEXSPI_CMD_SIZE); + lut_ptr = tmp_lut; + } + + memcpy(&tmp_config, device_config, sizeof(tmp_config)); + /* Update FlexSPI AWRSEQID and ARDSEQID values based on where the LUT + * array will actually be loaded. + */ + if (data->port_luts[port].lut_used < lut_count) { + /* Update lut offset with new value */ + data->port_luts[port].lut_offset = lut_used; + } + data->port_luts[port].lut_used = lut_count; + tmp_config.ARDSeqIndex += data->port_luts[port].lut_offset; + tmp_config.AWRSeqIndex += data->port_luts[port].lut_offset; + + /* Lock IRQs before reconfiguring FlexSPI, to prevent XIP */ + key = irq_lock(); + + FLEXSPI_SetFlashConfig(data->base, &tmp_config, port); + FLEXSPI_UpdateLUT(data->base, data->port_luts[port].lut_offset, + lut_ptr, lut_count); + irq_unlock(key); return 0; } @@ -139,7 +183,11 @@ int memc_flexspi_transfer(const struct device *dev, flexspi_transfer_t *transfer) { struct memc_flexspi_data *data = dev->data; - status_t status = FLEXSPI_TransferBlocking(data->base, transfer); + status_t status; + + /* Adjust transfer LUT index based on port */ + transfer->seqIndex += data->port_luts[transfer->port].lut_offset; + status = FLEXSPI_TransferBlocking(data->base, transfer); if (status != kStatus_Success) { LOG_ERR("Transfer error: %d", status); @@ -161,7 +209,7 @@ void *memc_flexspi_get_ahb_address(const struct device *dev, } for (i = 0; i < port; i++) { - offset += data->size[port]; + offset += data->size[i]; } return data->ahb_base + offset; @@ -252,12 +300,13 @@ static int memc_flexspi_pm_action(const struct device *dev, enum pm_device_actio } #endif -#if defined(CONFIG_XIP) && defined(CONFIG_CODE_FLEXSPI) -#define MEMC_FLEXSPI_CFG_XIP(node_id) DT_SAME_NODE(node_id, DT_NODELABEL(flexspi)) -#elif defined(CONFIG_XIP) && defined(CONFIG_CODE_FLEXSPI2) -#define MEMC_FLEXSPI_CFG_XIP(node_id) DT_SAME_NODE(node_id, DT_NODELABEL(flexspi2)) -#elif defined(CONFIG_SOC_SERIES_IMX_RT6XX) || defined(CONFIG_SOC_SERIES_IMX_RT5XX) -#define MEMC_FLEXSPI_CFG_XIP(node_id) DT_SAME_NODE(node_id, DT_NODELABEL(flexspi)) +#if defined(CONFIG_XIP) && defined(CONFIG_FLASH_MCUX_FLEXSPI_XIP) +/* Checks if image flash base address is in the FlexSPI AHB base region */ +#define MEMC_FLEXSPI_CFG_XIP(node_id) \ + ((CONFIG_FLASH_BASE_ADDRESS) >= DT_REG_ADDR_BY_IDX(node_id, 1)) && \ + ((CONFIG_FLASH_BASE_ADDRESS) < (DT_REG_ADDR_BY_IDX(node_id, 1) + \ + DT_REG_SIZE_BY_IDX(node_id, 1))) + #else #define MEMC_FLEXSPI_CFG_XIP(node_id) false #endif diff --git a/drivers/memc/memc_mcux_flexspi.h b/drivers/memc/memc_mcux_flexspi.h index 3d201c7b6d7..a8495fc9289 100644 --- a/drivers/memc/memc_mcux_flexspi.h +++ b/drivers/memc/memc_mcux_flexspi.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 NXP + * Copyright 2020,2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,25 +15,94 @@ enum memc_flexspi_clock_t { MEMC_FLEXSPI_CLOCK_42M, }; +/* Size of a command in the LUT table */ +#define MEMC_FLEXSPI_CMD_SIZE 4U + +/** + * @brief Wait for the FlexSPI bus to be idle + * + * Waits for the FlexSPI bus to be idle. Can be used when reconfiguring + * the FlexSPI to make sure no flash access is occurring before changing + * settings. + * + * @param dev: FlexSPI device + */ void memc_flexspi_wait_bus_idle(const struct device *dev); +/** + * @brief Check if FlexSPI is being used in XIP mode. + * + * Checks if the FlexSPI is being used for code execution in the current + * application. + * + * @param dev: FlexSPI device + * @retval true if FlexSPI being used for XIP + */ bool memc_flexspi_is_running_xip(const struct device *dev); -int memc_flexspi_update_lut(const struct device *dev, uint32_t index, - const uint32_t *cmd, uint32_t count); - +/** + * @brief Update clock selection of the FlexSPI device + * + * Updates clock selection of the FlexSPI device to a new clock speed. + * + * @param dev: FlexSPI device + * @param device_config: External device configuration. + * @param port: FlexSPI port to use for this external device + * @param clock: new clock selection to apply + * @return 0 on success, negative value on failure + */ int memc_flexspi_update_clock(const struct device *dev, flexspi_device_config_t *device_config, flexspi_port_t port, enum memc_flexspi_clock_t clock); +/** + * @brief configure new FlexSPI device + * + * Configures new device on the FlexSPI bus. + * @param dev: FlexSPI device + * @param device_config: External device configuration. + * @param lut_array: Lookup table of FlexSPI flash commands for device + * @param lut_count: number of command entries (16 bytes each) in LUT + * @param port: FlexSPI port to use for this external device + * @return 0 on success, negative value on failure + */ int memc_flexspi_set_device_config(const struct device *dev, const flexspi_device_config_t *device_config, + const uint32_t *lut_array, + uint8_t lut_count, flexspi_port_t port); + +/** + * @brief Perform software reset of FlexSPI + * + * Software reset of FlexSPI. Does not clear configuration registers. + * @param dev: FlexSPI device + * @return 0 on success, negative value on failure + */ int memc_flexspi_reset(const struct device *dev); +/** + * @brief Send blocking IP transfer + * + * Send blocking IP transfer using FlexSPI. + * @param dev: FlexSPI device + * @param transfer: FlexSPI transfer. seqIndex should be set as though the + * LUT array was loaded at offset 0. + * @return 0 on success, negative value on failure + */ int memc_flexspi_transfer(const struct device *dev, flexspi_transfer_t *transfer); +/** + * @brief Get AHB address for FlexSPI port + * + * Get AHB address for FlexSPI port. This address is memory mapped, and can be + * read from (and written to, for PSRAM) as though it were internal memory. + * @param dev: FlexSPI device + * @param port: FlexSPI port external device is on + * @param offset: byte offset from start of device to get AHB address for + * @return 0 on success, negative value on failure + */ void *memc_flexspi_get_ahb_address(const struct device *dev, flexspi_port_t port, off_t offset); diff --git a/drivers/memc/memc_mcux_flexspi_aps6408l.c b/drivers/memc/memc_mcux_flexspi_aps6408l.c index 0c295221a10..a9b51e77bfa 100644 --- a/drivers/memc/memc_mcux_flexspi_aps6408l.c +++ b/drivers/memc/memc_mcux_flexspi_aps6408l.c @@ -215,18 +215,13 @@ static int memc_flexspi_aps6408l_init(const struct device *dev) } if (memc_flexspi_set_device_config(data->controller, &config->config, - config->port)) { + (const uint32_t *) memc_flexspi_aps6408l_lut, + sizeof(memc_flexspi_aps6408l_lut) / MEMC_FLEXSPI_CMD_SIZE, + config->port)) { LOG_ERR("Could not set device configuration"); return -EINVAL; } - if (memc_flexspi_update_lut(data->controller, 0, - (const uint32_t *) memc_flexspi_aps6408l_lut, - sizeof(memc_flexspi_aps6408l_lut) / 4)) { - LOG_ERR("Could not update lut"); - return -EINVAL; - } - memc_flexspi_reset(data->controller); if (memc_flexspi_aps6408l_reset(dev)) { diff --git a/drivers/memc/memc_mcux_flexspi_s27ks0641.c b/drivers/memc/memc_mcux_flexspi_s27ks0641.c index ee7431c9201..36fc5bf8306 100644 --- a/drivers/memc/memc_mcux_flexspi_s27ks0641.c +++ b/drivers/memc/memc_mcux_flexspi_s27ks0641.c @@ -122,18 +122,13 @@ static int memc_flexspi_s27ks0641_init(const struct device *dev) } if (memc_flexspi_set_device_config(data->controller, &config->config, - config->port)) { + (const uint32_t *) memc_flexspi_s27ks0641_lut, + sizeof(memc_flexspi_s27ks0641_lut) / MEMC_FLEXSPI_CMD_SIZE, + config->port)) { LOG_ERR("Could not set device configuration"); return -EINVAL; } - if (memc_flexspi_update_lut(data->controller, 0, - (const uint32_t *) memc_flexspi_s27ks0641_lut, - sizeof(memc_flexspi_s27ks0641_lut) / 4)) { - LOG_ERR("Could not update lut"); - return -EINVAL; - } - memc_flexspi_reset(data->controller); if (memc_flexspi_s27ks0641_get_vendor_id(dev, &vendor_id)) { diff --git a/drivers/memc/memc_mcux_flexspi_w956a8mbya.c b/drivers/memc/memc_mcux_flexspi_w956a8mbya.c index ad24ecccdc7..60c5949b73f 100644 --- a/drivers/memc/memc_mcux_flexspi_w956a8mbya.c +++ b/drivers/memc/memc_mcux_flexspi_w956a8mbya.c @@ -114,18 +114,13 @@ static int memc_flexspi_w956a8mbya_init(const struct device *dev) } if (memc_flexspi_set_device_config(data->controller, &config->config, - config->port)) { + (const uint32_t *) memc_flexspi_w956a8mbya_lut, + sizeof(memc_flexspi_w956a8mbya_lut) / MEMC_FLEXSPI_CMD_SIZE, + config->port)) { LOG_ERR("Could not set device configuration"); return -EINVAL; } - if (memc_flexspi_update_lut(data->controller, 0, - (const uint32_t *) memc_flexspi_w956a8mbya_lut, - sizeof(memc_flexspi_w956a8mbya_lut) / 4)) { - LOG_ERR("Could not update lut"); - return -EINVAL; - } - memc_flexspi_reset(data->controller); if (memc_flexspi_w956a8mbya_get_vendor_id(dev, &vendor_id)) { diff --git a/drivers/memc/memc_nxp_flexram.c b/drivers/memc/memc_nxp_flexram.c new file mode 100644 index 00000000000..39da8349e1a --- /dev/null +++ b/drivers/memc/memc_nxp_flexram.c @@ -0,0 +1,231 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "memc_nxp_flexram.h" +#include +#include +#include +#include +#include +#include + +#include "fsl_device_registers.h" + + +#if defined(CONFIG_MEMC_NXP_FLEXRAM_MAGIC_ADDR_API) +BUILD_ASSERT(DT_PROP(FLEXRAM_DT_NODE, flexram_has_magic_addr), + "SOC does not support magic flexram addresses"); +#endif + +#define BANK_SIZE (DT_PROP(FLEXRAM_DT_NODE, flexram_bank_size) * 1024) +#define NUM_BANKS DT_PROP(FLEXRAM_DT_NODE, flexram_num_ram_banks) + +#define IS_CHILD_RAM_TYPE(node_id, compat) DT_NODE_HAS_COMPAT(node_id, compat) +#define DOES_RAM_TYPE_EXIST(compat) \ + DT_FOREACH_CHILD_SEP_VARGS(FLEXRAM_DT_NODE, IS_CHILD_RAM_TYPE, (+), compat) + +#if DOES_RAM_TYPE_EXIST(mmio_sram) +#define FIND_OCRAM_NODE(node_id) \ + COND_CODE_1(DT_NODE_HAS_COMPAT(node_id, mmio_sram), (node_id), ()) +#define OCRAM_DT_NODE DT_FOREACH_CHILD(FLEXRAM_DT_NODE, FIND_OCRAM_NODE) +#define OCRAM_START (DT_REG_ADDR(OCRAM_DT_NODE)) +#define OCRAM_END (OCRAM_START + DT_REG_SIZE(OCRAM_DT_NODE)) +#endif /* OCRAM */ +#if DOES_RAM_TYPE_EXIST(nxp_imx_dtcm) +#define FIND_DTCM_NODE(node_id) \ + COND_CODE_1(DT_NODE_HAS_COMPAT(node_id, nxp_imx_dtcm), (node_id), ()) +#define DTCM_DT_NODE DT_FOREACH_CHILD(FLEXRAM_DT_NODE, FIND_DTCM_NODE) +#define DTCM_START (DT_REG_ADDR(DTCM_DT_NODE)) +#define DTCM_END (DTCM_START + DT_REG_SIZE(DTCM_DT_NODE)) +#endif /* DTCM */ +#if DOES_RAM_TYPE_EXIST(nxp_imx_itcm) +#define FIND_ITCM_NODE(node_id) \ + COND_CODE_1(DT_NODE_HAS_COMPAT(node_id, nxp_imx_itcm), (node_id), ()) +#define ITCM_DT_NODE DT_FOREACH_CHILD(FLEXRAM_DT_NODE, FIND_ITCM_NODE) +#define ITCM_START (DT_REG_ADDR(ITCM_DT_NODE)) +#define ITCM_END (ITCM_START + DT_REG_SIZE(ITCM_DT_NODE)) +#endif /* ITCM */ + + +#ifdef FLEXRAM_RUNTIME_BANKS_USED + +#define PLUS_ONE_BANK(node_id, prop, idx) 1 +#define COUNT_BANKS \ + DT_FOREACH_PROP_ELEM_SEP(FLEXRAM_DT_NODE, flexram_bank_spec, PLUS_ONE_BANK, (+)) +BUILD_ASSERT(COUNT_BANKS == NUM_BANKS, "wrong number of flexram banks defined"); + +#ifdef OCRAM_DT_NODE +#define ADD_BANK_IF_OCRAM(node_id, prop, idx) \ + COND_CODE_1(IS_EQ(DT_PROP_BY_IDX(node_id, prop, idx), FLEXRAM_OCRAM), \ + (BANK_SIZE), (0)) +#define OCRAM_TOTAL \ + DT_FOREACH_PROP_ELEM_SEP(FLEXRAM_DT_NODE, flexram_bank_spec, ADD_BANK_IF_OCRAM, (+)) +BUILD_ASSERT((OCRAM_TOTAL) == DT_REG_SIZE(OCRAM_DT_NODE), "OCRAM node size is wrong"); +#endif /* OCRAM */ + +#ifdef DTCM_DT_NODE +#define ADD_BANK_IF_DTCM(node_id, prop, idx) \ + COND_CODE_1(IS_EQ(DT_PROP_BY_IDX(node_id, prop, idx), FLEXRAM_DTCM), \ + (BANK_SIZE), (0)) +#define DTCM_TOTAL \ + DT_FOREACH_PROP_ELEM_SEP(FLEXRAM_DT_NODE, flexram_bank_spec, ADD_BANK_IF_DTCM, (+)) +BUILD_ASSERT((DTCM_TOTAL) == DT_REG_SIZE(DTCM_DT_NODE), "DTCM node size is wrong"); +#endif /* DTCM */ + +#ifdef ITCM_DT_NODE +#define ADD_BANK_IF_ITCM(node_id, prop, idx) \ + COND_CODE_1(IS_EQ(DT_PROP_BY_IDX(node_id, prop, idx), FLEXRAM_ITCM), \ + (BANK_SIZE), (0)) +#define ITCM_TOTAL \ + DT_FOREACH_PROP_ELEM_SEP(FLEXRAM_DT_NODE, flexram_bank_spec, ADD_BANK_IF_ITCM, (+)) +BUILD_ASSERT((ITCM_TOTAL) == DT_REG_SIZE(ITCM_DT_NODE), "ITCM node size is wrong"); +#endif /* ITCM */ + +#endif /* FLEXRAM_RUNTIME_BANKS_USED */ + +static FLEXRAM_Type *const base = (FLEXRAM_Type *) DT_REG_ADDR(FLEXRAM_DT_NODE); + +#ifdef FLEXRAM_INTERRUPTS_USED +static flexram_callback_t flexram_callback; +static void *flexram_user_data; + +void memc_flexram_register_callback(flexram_callback_t callback, void *user_data) +{ + flexram_callback = callback; + flexram_user_data = user_data; +} + +static void nxp_flexram_isr(void *arg) +{ + ARG_UNUSED(arg); + + if (flexram_callback == NULL) { + return; + } + +#if defined(CONFIG_MEMC_NXP_FLEXRAM_ERROR_INTERRUPT) + if (base->INT_STATUS & FLEXRAM_INT_STATUS_OCRAM_ERR_STATUS_MASK) { + base->INT_STATUS |= FLEXRAM_INT_STATUS_OCRAM_ERR_STATUS_MASK; + flexram_callback(flexram_ocram_access_error, flexram_user_data); + } + if (base->INT_STATUS & FLEXRAM_INT_STATUS_DTCM_ERR_STATUS_MASK) { + base->INT_STATUS |= FLEXRAM_INT_STATUS_DTCM_ERR_STATUS_MASK; + flexram_callback(flexram_dtcm_access_error, flexram_user_data); + } + if (base->INT_STATUS & FLEXRAM_INT_STATUS_ITCM_ERR_STATUS_MASK) { + base->INT_STATUS |= FLEXRAM_INT_STATUS_ITCM_ERR_STATUS_MASK; + flexram_callback(flexram_itcm_access_error, flexram_user_data); + } +#endif /* CONFIG_MEMC_NXP_FLEXRAM_ERROR_INTERRUPT */ + +#if defined(CONFIG_MEMC_NXP_FLEXRAM_MAGIC_ADDR_API) + if (base->INT_STATUS & FLEXRAM_INT_STATUS_OCRAM_MAM_STATUS_MASK) { + base->INT_STATUS |= FLEXRAM_INT_STATUS_OCRAM_MAM_STATUS_MASK; + flexram_callback(flexram_ocram_magic_addr, flexram_user_data); + } + if (base->INT_STATUS & FLEXRAM_INT_STATUS_DTCM_MAM_STATUS_MASK) { + base->INT_STATUS |= FLEXRAM_INT_STATUS_DTCM_MAM_STATUS_MASK; + flexram_callback(flexram_dtcm_magic_addr, flexram_user_data); + } + if (base->INT_STATUS & FLEXRAM_INT_STATUS_ITCM_MAM_STATUS_MASK) { + base->INT_STATUS |= FLEXRAM_INT_STATUS_ITCM_MAM_STATUS_MASK; + flexram_callback(flexram_itcm_magic_addr, flexram_user_data); + } +#endif /* CONFIG_MEMC_NXP_FLEXRAM_MAGIC_ADDR_API */ +} + +#if defined(CONFIG_MEMC_NXP_FLEXRAM_MAGIC_ADDR_API) +int memc_flexram_set_ocram_magic_addr(uint32_t ocram_addr) +{ +#ifdef OCRAM_DT_NODE + ocram_addr -= DT_REG_ADDR(OCRAM_DT_NODE); + if (ocram_addr >= DT_REG_SIZE(OCRAM_DT_NODE)) { + return -EINVAL; + } + + base->OCRAM_MAGIC_ADDR &= ~FLEXRAM_OCRAM_MAGIC_ADDR_OCRAM_MAGIC_ADDR_MASK; + base->OCRAM_MAGIC_ADDR |= FLEXRAM_OCRAM_MAGIC_ADDR_OCRAM_MAGIC_ADDR(ocram_addr); + + base->INT_STAT_EN |= FLEXRAM_INT_STAT_EN_OCRAM_MAM_STAT_EN_MASK; + return 0; +#else + return -ENODEV; +#endif +} + +int memc_flexram_set_itcm_magic_addr(uint32_t itcm_addr) +{ +#ifdef ITCM_DT_NODE + itcm_addr -= DT_REG_ADDR(ITCM_DT_NODE); + if (itcm_addr >= DT_REG_SIZE(ITCM_DT_NODE)) { + return -EINVAL; + } + + base->ITCM_MAGIC_ADDR &= ~FLEXRAM_ITCM_MAGIC_ADDR_ITCM_MAGIC_ADDR_MASK; + base->ITCM_MAGIC_ADDR |= FLEXRAM_ITCM_MAGIC_ADDR_ITCM_MAGIC_ADDR(itcm_addr); + + base->INT_STAT_EN |= FLEXRAM_INT_STAT_EN_ITCM_MAM_STAT_EN_MASK; + return 0; +#else + return -ENODEV; +#endif +} + +int memc_flexram_set_dtcm_magic_addr(uint32_t dtcm_addr) +{ +#ifdef DTCM_DT_NODE + dtcm_addr -= DT_REG_ADDR(DTCM_DT_NODE); + if (dtcm_addr >= DT_REG_SIZE(DTCM_DT_NODE)) { + return -EINVAL; + } + + base->DTCM_MAGIC_ADDR &= ~FLEXRAM_DTCM_MAGIC_ADDR_DTCM_MAGIC_ADDR_MASK; + base->DTCM_MAGIC_ADDR |= FLEXRAM_DTCM_MAGIC_ADDR_DTCM_MAGIC_ADDR(dtcm_addr); + + base->INT_STAT_EN |= FLEXRAM_INT_STAT_EN_DTCM_MAM_STAT_EN_MASK; + return 0; +#else + return -ENODEV; +#endif +} +#endif /* CONFIG_MEMC_NXP_FLEXRAM_MAGIC_ADDR_API */ + +#endif /* FLEXRAM_INTERRUPTS_USED */ + +static int nxp_flexram_init(void) +{ + if (DT_PROP(FLEXRAM_DT_NODE, flexram_tcm_read_wait_mode)) { + base->TCM_CTRL |= FLEXRAM_TCM_CTRL_TCM_WWAIT_EN_MASK; + } + if (DT_PROP(FLEXRAM_DT_NODE, flexram_tcm_write_wait_mode)) { + base->TCM_CTRL |= FLEXRAM_TCM_CTRL_TCM_RWAIT_EN_MASK; + } + +#if defined(CONFIG_MEMC_NXP_FLEXRAM_ERROR_INTERRUPT) + base->INT_SIG_EN |= FLEXRAM_INT_SIG_EN_OCRAM_ERR_SIG_EN_MASK; + base->INT_SIG_EN |= FLEXRAM_INT_SIG_EN_DTCM_ERR_SIG_EN_MASK; + base->INT_SIG_EN |= FLEXRAM_INT_SIG_EN_ITCM_ERR_SIG_EN_MASK; + base->INT_STAT_EN |= FLEXRAM_INT_STAT_EN_OCRAM_ERR_STAT_EN_MASK; + base->INT_STAT_EN |= FLEXRAM_INT_STAT_EN_DTCM_ERR_STAT_EN_MASK; + base->INT_STAT_EN |= FLEXRAM_INT_STAT_EN_ITCM_ERR_STAT_EN_MASK; +#endif /* CONFIG_MEMC_NXP_FLEXRAM_ERROR_INTERRUPT */ + +#if defined(CONFIG_MEMC_NXP_FLEXRAM_MAGIC_ADDR_API) + base->INT_SIG_EN |= FLEXRAM_INT_SIG_EN_OCRAM_MAM_SIG_EN_MASK; + base->INT_SIG_EN |= FLEXRAM_INT_SIG_EN_DTCM_MAM_SIG_EN_MASK; + base->INT_SIG_EN |= FLEXRAM_INT_SIG_EN_ITCM_MAM_SIG_EN_MASK; +#endif /* CONFIG_MEMC_NXP_FLEXRAM_MAGIC_ADDR_API */ + +#ifdef FLEXRAM_INTERRUPTS_USED + IRQ_CONNECT(DT_IRQN(FLEXRAM_DT_NODE), DT_IRQ(FLEXRAM_DT_NODE, priority), + nxp_flexram_isr, NULL, 0); + irq_enable(DT_IRQN(FLEXRAM_DT_NODE)); +#endif /* FLEXRAM_INTERRUPTS_USED */ + + return 0; +} + +SYS_INIT(nxp_flexram_init, EARLY, 0); diff --git a/drivers/memc/memc_nxp_flexram.h b/drivers/memc/memc_nxp_flexram.h new file mode 100644 index 00000000000..5ea2e89d0cc --- /dev/null +++ b/drivers/memc/memc_nxp_flexram.h @@ -0,0 +1,98 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#define FLEXRAM_DT_NODE DT_INST(0, nxp_flexram) +#define IOMUXC_GPR_DT_NODE DT_NODELABEL(iomuxcgpr) + +#if defined(CONFIG_MEMC_NXP_FLEXRAM_MAGIC_ADDR_API) || \ + defined(CONFIG_MEMC_NXP_FLEXRAM_ERROR_INTERRUPT) +#define FLEXRAM_INTERRUPTS_USED +#endif + +#if DT_PROP_HAS_IDX(FLEXRAM_DT_NODE, flexram_bank_spec, 0) +#define FLEXRAM_RUNTIME_BANKS_USED 1 +#endif + +#ifdef FLEXRAM_INTERRUPTS_USED +enum memc_flexram_interrupt_cause { +#ifdef CONFIG_MEMC_NXP_FLEXRAM_ERROR_INTERRUPT + flexram_ocram_access_error, + flexram_itcm_access_error, + flexram_dtcm_access_error, +#endif +#ifdef CONFIG_MEMC_NXP_FLEXRAM_MAGIC_ADDR_API + flexram_ocram_magic_addr, + flexram_itcm_magic_addr, + flexram_dtcm_magic_addr, +#endif /* CONFIG_MEMC_NXP_FLEXRAM_MAGIC_ADDR_API */ +}; + +typedef void (*flexram_callback_t)(enum memc_flexram_interrupt_cause, void *user_data); + +void memc_flexram_register_callback(flexram_callback_t callback, void *user_data); +#endif /* FLEXRAM_INTERRUPTS_USED */ + +#ifdef FLEXRAM_RUNTIME_BANKS_USED + +/* + * call from platform_init to set up flexram if using runtime map + * must be inlined because cannot use stack + */ +#define GPR17_REG_FILL(node_id, prop, idx) + (DT_PROP_BY_IDX(node_id, prop, idx) << (2*idx)) +static inline void memc_flexram_dt_partition(void) +{ + /* iomuxc_gpr must be const (in ROM region) because used in reconfiguring ram */ + static IOMUXC_GPR_Type *const iomuxc_gpr = + (IOMUXC_GPR_Type *) DT_REG_ADDR(IOMUXC_GPR_DT_NODE); + /* do not create stack variables or use any data from ram in this function */ + iomuxc_gpr->GPR17 = DT_FOREACH_PROP_ELEM_SEP(FLEXRAM_DT_NODE, + flexram_bank_spec, GPR17_REG_FILL, (+)); + iomuxc_gpr->GPR16 |= IOMUXC_GPR_GPR16_FLEXRAM_BANK_CFG_SEL_MASK; +} +#endif /* FLEXRAM_RUNTIME_BANKS_USED */ + + +#ifdef CONFIG_MEMC_NXP_FLEXRAM_MAGIC_ADDR_API +/** @brief Sets magic address for OCRAM + * + * Magic address allows core interrupt from FlexRAM when address + * is accessed. + * + * @param ocram_addr: An address in OCRAM to set magic function on. + * @retval 0 on success + * @retval -EINVAL if ocram_addr is not in OCRAM + * @retval -ENODEV if there is no OCRAM allocation in flexram + */ +int memc_flexram_set_ocram_magic_addr(uint32_t ocram_addr); + +/** @brief Sets magic address for ITCM + * + * Magic address allows core interrupt from FlexRAM when address + * is accessed. + * + * @param itcm_addr: An address in ITCM to set magic function on. + * @retval 0 on success + * @retval -EINVAL if itcm_addr is not in ITCM + * @retval -ENODEV if there is no ITCM allocation in flexram + */ +int memc_flexram_set_itcm_magic_addr(uint32_t itcm_addr); + +/** @brief Sets magic address for DTCM + * + * Magic address allows core interrupt from FlexRAM when address + * is accessed. + * + * @param dtcm_addr: An address in DTCM to set magic function on. + * @retval 0 on success + * @retval -EINVAL if dtcm_addr is not in DTCM + * @retval -ENODEV if there is no DTCM allocation in flexram + */ +int memc_flexram_set_dtcm_magic_addr(uint32_t dtcm_addr); + +#endif /* CONFIG_MEMC_NXP_FLEXRAM_MAGIC_ADDR_API */ diff --git a/drivers/memc/memc_nxp_s32_qspi.c b/drivers/memc/memc_nxp_s32_qspi.c index b2dc1466d6f..f588a0bd9af 100644 --- a/drivers/memc/memc_nxp_s32_qspi.c +++ b/drivers/memc/memc_nxp_s32_qspi.c @@ -78,7 +78,7 @@ uint8_t memc_nxp_s32_qspi_get_instance(const struct device *dev) #define QSPI_DATA_CFG(n) \ IF_ENABLED(FEATURE_QSPI_DDR, ( \ - .dataRate = CONCAT(QSPI_IP_DATA_RATE_, \ + .dataRate = _CONCAT(QSPI_IP_DATA_RATE_, \ DT_INST_STRING_UPPER_TOKEN(n, data_rate)), \ .dataAlign = COND_CODE_1(DT_INST_PROP(n, hold_time_2x), \ (QSPI_IP_FLASH_DATA_ALIGN_2X_REFCLK), \ @@ -115,7 +115,7 @@ uint8_t memc_nxp_s32_qspi_get_instance(const struct device *dev) #define QSPI_DLL_CFG(n, side, side_upper) \ IF_ENABLED(FEATURE_QSPI_HAS_DLL, ( \ .dllSettings##side_upper = { \ - .dllMode = CONCAT(QSPI_IP_DLL_, \ + .dllMode = _CONCAT(QSPI_IP_DLL_, \ DT_INST_STRING_UPPER_TOKEN(n, side##_dll_mode)), \ .freqEnable = DT_INST_PROP(n, side##_dll_freq_enable), \ .coarseDelay = DT_INST_PROP(n, side##_dll_coarse_delay), \ @@ -129,7 +129,7 @@ uint8_t memc_nxp_s32_qspi_get_instance(const struct device *dev) )) #define QSPI_READ_MODE(n, side, side_upper) \ - CONCAT(QSPI_IP_READ_MODE_, DT_INST_STRING_UPPER_TOKEN(n, side##_rx_clock_source)) + _CONCAT(QSPI_IP_READ_MODE_, DT_INST_STRING_UPPER_TOKEN(n, side##_rx_clock_source)) #define QSPI_IDLE_SIGNAL_DRIVE(n, side, side_upper) \ IF_ENABLED(FEATURE_QSPI_CONFIGURABLE_ISD, ( \ @@ -160,7 +160,7 @@ uint8_t memc_nxp_s32_qspi_get_instance(const struct device *dev) BUILD_ASSERT(DT_INST_PROP_LEN(n, ahb_buffers_sizes) == QSPI_IP_AHB_BUFFERS, \ "ahb-buffers-sizes must be of size QSPI_IP_AHB_BUFFERS"); \ BUILD_ASSERT( \ - CONCAT(FEATURE_QSPI_, DT_INST_STRING_UPPER_TOKEN(n, a_rx_clock_source)) == 1,\ + _CONCAT(FEATURE_QSPI_, DT_INST_STRING_UPPER_TOKEN(n, a_rx_clock_source)) == 1,\ "a-rx-clock-source source mode selected is not supported"); \ \ static const Qspi_Ip_ControllerConfigType \ diff --git a/drivers/mfd/CMakeLists.txt b/drivers/mfd/CMakeLists.txt index 0d27ef2c034..5141a86c2ee 100644 --- a/drivers/mfd/CMakeLists.txt +++ b/drivers/mfd/CMakeLists.txt @@ -3,6 +3,9 @@ zephyr_library() +zephyr_library_sources_ifdef(CONFIG_MFD_MAX20335 mfd_max20335.c) +zephyr_library_sources_ifdef(CONFIG_MFD_NCT38XX mfd_nct38xx.c) zephyr_library_sources_ifdef(CONFIG_MFD_NPM1300 mfd_npm1300.c) zephyr_library_sources_ifdef(CONFIG_MFD_NPM6001 mfd_npm6001.c) zephyr_library_sources_ifdef(CONFIG_MFD_AXP192 mfd_axp192.c) +zephyr_library_sources_ifdef(CONFIG_MFD_AD5592 mfd_ad5592.c) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 114b78ad587..1a400d6383e 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -14,11 +14,14 @@ source "subsys/logging/Kconfig.template.log_config" config MFD_INIT_PRIORITY int "Initialization priority" - default 60 + default 80 help Multi-function devices initialization priority. +source "drivers/mfd/Kconfig.ad5592" source "drivers/mfd/Kconfig.axp192" +source "drivers/mfd/Kconfig.max20335" +source "drivers/mfd/Kconfig.nct38xx" source "drivers/mfd/Kconfig.npm1300" source "drivers/mfd/Kconfig.npm6001" diff --git a/drivers/mfd/Kconfig.ad5592 b/drivers/mfd/Kconfig.ad5592 new file mode 100644 index 00000000000..8b94f5517cb --- /dev/null +++ b/drivers/mfd/Kconfig.ad5592 @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Grinn +# SPDX -License-Identifier: Apache-2.0 + +config MFD_AD5592 + bool "Analog AD5592 SPI configurable ADC/DAC/GPIO chip" + default y + depends on DT_HAS_ADI_AD5592_ENABLED + depends on SPI + help + Enable driver for Analog AD5592. diff --git a/drivers/mfd/Kconfig.max20335 b/drivers/mfd/Kconfig.max20335 new file mode 100644 index 00000000000..3d146de17f0 --- /dev/null +++ b/drivers/mfd/Kconfig.max20335 @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Grinn +# SPDX -License-Identifier: Apache-2.0 + +config MFD_MAX20335 + bool "MAX20335 PMIC multi-function device driver" + default y + depends on DT_HAS_MAXIM_MAX20335_ENABLED + select I2C + help + Enable the Maxim MAX20335 PMIC multi-function device driver diff --git a/drivers/mfd/Kconfig.nct38xx b/drivers/mfd/Kconfig.nct38xx new file mode 100644 index 00000000000..aa852d974bb --- /dev/null +++ b/drivers/mfd/Kconfig.nct38xx @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Google, LLC +# SPDX -License-Identifier: Apache-2.0 + +config MFD_NCT38XX + bool "Nuvton NCT38xx multi-function device driver" + default y + depends on DT_HAS_NUVOTON_NCT38XX_ENABLED + select I2C + help + Enable the Nuvoton NCT38xx TCPC multi-function device driver. diff --git a/drivers/mfd/Kconfig.npm1300 b/drivers/mfd/Kconfig.npm1300 index cc3eb0ef303..506508bd902 100644 --- a/drivers/mfd/Kconfig.npm1300 +++ b/drivers/mfd/Kconfig.npm1300 @@ -8,3 +8,10 @@ config MFD_NPM1300 select I2C help Enable the Nordic nPM1300 PMIC multi-function device driver + +config MFD_NPM1300_INIT_PRIORITY + int "nPM1300 MFD initialization priority" + default MFD_INIT_PRIORITY + depends on MFD_NPM1300 + help + Multi-function device initialization priority for nPM1300. diff --git a/drivers/mfd/Kconfig.npm6001 b/drivers/mfd/Kconfig.npm6001 index 10360aa2347..b81c942f2d6 100644 --- a/drivers/mfd/Kconfig.npm6001 +++ b/drivers/mfd/Kconfig.npm6001 @@ -8,3 +8,10 @@ config MFD_NPM6001 select I2C help Enable the Nordic nPM6001 PMIC multi-function device driver + +config MFD_NPM6001_INIT_PRIORITY + int "nPM6001 MFD initialization priority" + default MFD_INIT_PRIORITY + depends on MFD_NPM6001 + help + Multi-function device initialization priority for nPM6001. diff --git a/drivers/mfd/mfd_ad5592.c b/drivers/mfd/mfd_ad5592.c new file mode 100644 index 00000000000..d8f8f60de39 --- /dev/null +++ b/drivers/mfd/mfd_ad5592.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2023 Grinn + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT adi_ad5592 + +#include +#include +#include +#include + +#include + +#define AD5592_GPIO_READBACK_EN BIT(10) +#define AD5592_LDAC_READBACK_EN BIT(6) +#define AD5592_REG_SOFTWARE_RESET 0x0FU +#define AD5592_SOFTWARE_RESET_MAGIC_VAL 0xDAC +#define AD5592_REV_VAL_MASK 0x3FF +#define AD5592_REG_SHIFT_VAL 11 +#define AD5592_REG_READBACK_SHIFT_VAL 2 + +#define AD5592_SPI_SPEC_CONF (SPI_WORD_SET(8) | SPI_TRANSFER_MSB | \ + SPI_OP_MODE_MASTER | SPI_MODE_CPOL) + +struct mfd_ad5592_config { + struct gpio_dt_spec reset_gpio; + struct spi_dt_spec bus; +}; + +int mfd_ad5592_read_raw(const struct device *dev, uint16_t *val) +{ + const struct mfd_ad5592_config *config = dev->config; + uint16_t nop_msg = 0; + + struct spi_buf tx_buf[] = { + { + .buf = &nop_msg, + .len = sizeof(nop_msg) + } + }; + + const struct spi_buf_set tx = { + .buffers = tx_buf, + .count = 1 + }; + + struct spi_buf rx_buf[] = { + { + .buf = val, + .len = sizeof(uint16_t) + } + }; + + const struct spi_buf_set rx = { + .buffers = rx_buf, + .count = 1 + }; + + return spi_transceive_dt(&config->bus, &tx, &rx); +} + +int mfd_ad5592_write_raw(const struct device *dev, uint16_t val) +{ + const struct mfd_ad5592_config *config = dev->config; + + struct spi_buf tx_buf[] = { + { + .buf = &val, + .len = sizeof(val) + } + }; + + const struct spi_buf_set tx = { + .buffers = tx_buf, + .count = 1 + }; + + return spi_write_dt(&config->bus, &tx); +} + +int mfd_ad5592_read_reg(const struct device *dev, uint8_t reg, uint8_t reg_data, uint16_t *val) +{ + uint16_t data; + uint16_t msg; + int ret; + + switch (reg) { + case AD5592_REG_GPIO_INPUT_EN: + msg = sys_cpu_to_be16(AD5592_GPIO_READBACK_EN | + (AD5592_REG_GPIO_INPUT_EN << AD5592_REG_SHIFT_VAL) | + reg_data); + break; + default: + msg = sys_cpu_to_be16(AD5592_LDAC_READBACK_EN | + (AD5592_REG_READ_AND_LDAC << AD5592_REG_SHIFT_VAL) | + reg << AD5592_REG_READBACK_SHIFT_VAL); + break; + } + + ret = mfd_ad5592_write_raw(dev, msg); + if (ret < 0) { + return ret; + } + + ret = mfd_ad5592_read_raw(dev, &data); + if (ret < 0) { + return ret; + } + + *val = sys_be16_to_cpu(data); + + return 0; +} + +int mfd_ad5592_write_reg(const struct device *dev, uint8_t reg, uint16_t val) +{ + uint16_t msg = sys_cpu_to_be16((reg << AD5592_REG_SHIFT_VAL) | (val & AD5592_REV_VAL_MASK)); + + return mfd_ad5592_write_raw(dev, msg); +} + +static int mfd_add592_software_reset(const struct device *dev) +{ + return mfd_ad5592_write_reg(dev, + AD5592_REG_SOFTWARE_RESET, + AD5592_SOFTWARE_RESET_MAGIC_VAL); +} + +static int mfd_ad5592_init(const struct device *dev) +{ + const struct mfd_ad5592_config *config = dev->config; + int ret; + + if (!spi_is_ready_dt(&config->bus)) { + return -ENODEV; + } + + if (!gpio_is_ready_dt(&config->reset_gpio)) { + return -ENODEV; + } + + ret = gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_INACTIVE); + if (ret < 0) { + return ret; + } + + ret = mfd_add592_software_reset(dev); + if (ret < 0) { + return ret; + } + + return 0; +} + +#define MFD_AD5592_DEFINE(inst) \ + static const struct mfd_ad5592_config mfd_ad5592_config_##inst = { \ + .reset_gpio = GPIO_DT_SPEC_INST_GET(inst, reset_gpios), \ + .bus = SPI_DT_SPEC_INST_GET(inst, AD5592_SPI_SPEC_CONF, 0), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, mfd_ad5592_init, NULL, \ + NULL, \ + &mfd_ad5592_config_##inst, \ + POST_KERNEL, \ + CONFIG_MFD_INIT_PRIORITY, \ + NULL); + +DT_INST_FOREACH_STATUS_OKAY(MFD_AD5592_DEFINE); diff --git a/drivers/mfd/mfd_max20335.c b/drivers/mfd/mfd_max20335.c new file mode 100644 index 00000000000..7ea6a9f198c --- /dev/null +++ b/drivers/mfd/mfd_max20335.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 Grinn + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT maxim_max20335 + +#include + +#include +#include + +#define MAX20335_REG_CHIP_ID 0x00 +#define MAX20335_CHIP_ID_VAL 0x04 + +struct mfd_max20335_config { + struct i2c_dt_spec bus; +}; + +static int mfd_max20335_init(const struct device *dev) +{ + const struct mfd_max20335_config *config = dev->config; + uint8_t val; + int ret; + + if (!i2c_is_ready_dt(&config->bus)) { + return -ENODEV; + } + + ret = i2c_reg_read_byte_dt(&config->bus, MAX20335_REG_CHIP_ID, &val); + if (ret < 0) { + return ret; + } + + if (val != MAX20335_CHIP_ID_VAL) { + return -ENODEV; + } + + return 0; +} + +#define MFD_MA20335_DEFINE(inst) \ + static const struct mfd_max20335_config mfd_max20335_config##inst = { \ + .bus = I2C_DT_SPEC_INST_GET(inst), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, mfd_max20335_init, NULL, NULL, \ + &mfd_max20335_config##inst, POST_KERNEL, \ + CONFIG_MFD_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(MFD_MA20335_DEFINE) diff --git a/drivers/mfd/mfd_nct38xx.c b/drivers/mfd/mfd_nct38xx.c new file mode 100644 index 00000000000..81b6ece4d1a --- /dev/null +++ b/drivers/mfd/mfd_nct38xx.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2023 Google, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nuvoton_nct38xx + +#include + +struct mfd_nct38xx_config { + const struct i2c_dt_spec i2c_dev; +}; + +struct mfd_nct38xx_data { + /* lock NC38xx register access */ + struct k_sem lock; +}; + +static int mfd_nct38xx_init(const struct device *dev) +{ + const struct mfd_nct38xx_config *config = dev->config; + struct mfd_nct38xx_data *data = dev->data; + + if (!device_is_ready(config->i2c_dev.bus)) { + return -ENODEV; + } + + k_sem_init(&data->lock, 1, 1); + + return 0; +} + +struct k_sem *mfd_nct38xx_get_lock_reference(const struct device *dev) +{ + struct mfd_nct38xx_data *data = dev->data; + + return &data->lock; +} + +const struct i2c_dt_spec *mfd_nct38xx_get_i2c_dt_spec(const struct device *dev) +{ + const struct mfd_nct38xx_config *config = dev->config; + + return &config->i2c_dev; +} + +#define MFD_NCT38XX_DEFINE(inst) \ + static struct mfd_nct38xx_data nct38xx_data_##inst; \ + static const struct mfd_nct38xx_config nct38xx_cfg_##inst = { \ + .i2c_dev = I2C_DT_SPEC_INST_GET(inst), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, mfd_nct38xx_init, NULL, &nct38xx_data_##inst, \ + &nct38xx_cfg_##inst, POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(MFD_NCT38XX_DEFINE) diff --git a/drivers/mfd/mfd_npm1300.c b/drivers/mfd/mfd_npm1300.c index d0632422556..ef06b6da7f0 100644 --- a/drivers/mfd/mfd_npm1300.c +++ b/drivers/mfd/mfd_npm1300.c @@ -64,6 +64,7 @@ static const struct event_reg_t event_reg[NPM1300_EVENT_MAX] = { [NPM1300_EVENT_BATTERY_DETECTED] = {0x0EU, 0x01U}, [NPM1300_EVENT_BATTERY_REMOVED] = {0x0EU, 0x02U}, [NPM1300_EVENT_SHIPHOLD_PRESS] = {0x12U, 0x01U}, + [NPM1300_EVENT_SHIPHOLD_RELEASE] = {0x12U, 0x02U}, [NPM1300_EVENT_WATCHDOG_WARN] = {0x12U, 0x08U}, [NPM1300_EVENT_VBUS_DETECTED] = {0x16U, 0x01U}, [NPM1300_EVENT_VBUS_REMOVED] = {0x16U, 0x02U}}; @@ -78,12 +79,14 @@ static void gpio_callback(const struct device *dev, struct gpio_callback *cb, ui static void work_callback(struct k_work *work) { struct mfd_npm1300_data *data = CONTAINER_OF(work, struct mfd_npm1300_data, work); + const struct mfd_npm1300_config *config = data->dev->config; uint8_t buf[MAIN_SIZE]; int ret; /* Read all MAIN registers into temporary buffer */ ret = mfd_npm1300_reg_read_burst(data->dev, MAIN_BASE, 0U, buf, sizeof(buf)); if (ret < 0) { + k_work_submit(&data->work); return; } @@ -96,10 +99,16 @@ static void work_callback(struct k_work *work) ret = mfd_npm1300_reg_write(data->dev, MAIN_BASE, offset, event_reg[i].mask); if (ret < 0) { + k_work_submit(&data->work); return; } } } + + /* Resubmit handler to queue if interrupt is still active */ + if (gpio_pin_get_dt(&config->host_int_gpios) != 0) { + k_work_submit(&data->work); + } } static int mfd_npm1300_init(const struct device *dev) @@ -288,6 +297,6 @@ int mfd_npm1300_remove_callback(const struct device *dev, struct gpio_callback * }; \ \ DEVICE_DT_INST_DEFINE(inst, mfd_npm1300_init, NULL, &data_##inst, &config##inst, \ - POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, NULL); + POST_KERNEL, CONFIG_MFD_NPM1300_INIT_PRIORITY, NULL); DT_INST_FOREACH_STATUS_OKAY(MFD_NPM1300_DEFINE) diff --git a/drivers/mfd/mfd_npm6001.c b/drivers/mfd/mfd_npm6001.c index 4bed77c4958..1a077791816 100644 --- a/drivers/mfd/mfd_npm6001.c +++ b/drivers/mfd/mfd_npm6001.c @@ -87,6 +87,6 @@ static int mfd_npm6001_init(const struct device *dev) }; \ \ DEVICE_DT_INST_DEFINE(inst, mfd_npm6001_init, NULL, NULL, &config##inst, POST_KERNEL, \ - CONFIG_MFD_INIT_PRIORITY, NULL); + CONFIG_MFD_NPM6001_INIT_PRIORITY, NULL); DT_INST_FOREACH_STATUS_OKAY(MFD_NPM6001_DEFINE) diff --git a/drivers/mipi_dsi/Kconfig.mcux b/drivers/mipi_dsi/Kconfig.mcux index 7e9c15f2d40..17d8d437dfe 100644 --- a/drivers/mipi_dsi/Kconfig.mcux +++ b/drivers/mipi_dsi/Kconfig.mcux @@ -14,3 +14,24 @@ config MIPI_DSI_MCUX_2L depends on DT_HAS_NXP_MIPI_DSI_2L_ENABLED help NXP MIPI DSI 2L controller driver + +if MIPI_DSI_MCUX_2L + +config MIPI_DSI_MCUX_2L_SMARTDMA + bool "Use smartDMA controller with MIPI DSI" + default y + depends on DMA_MCUX_SMARTDMA + help + Use SMARTDMA. This accelerator will automatically + convert RGB565 input data to BGR565 (little endian to big endian), + and write it to the MIPI DSI. + +config MIPI_DSI_MCUX_2L_SWAP16 + bool "Swap 16 byte color" + help + Swap 16 byte color data from little to big endian format. When + this Kconfig is enabled, the DSI expects RGB565 data in little endian + format, which will then be byte swapped. + + +endif # MIPI_DSI_MCUX_2L diff --git a/drivers/mipi_dsi/dsi_mcux.c b/drivers/mipi_dsi/dsi_mcux.c index f0eceb4697e..0093a2467a0 100644 --- a/drivers/mipi_dsi/dsi_mcux.c +++ b/drivers/mipi_dsi/dsi_mcux.c @@ -39,6 +39,9 @@ LOG_MODULE_REGISTER(dsi_mcux, CONFIG_MIPI_DSI_LOG_LEVEL); #define DSI_DPHY_PLL_CO_MIN 0 #define DSI_DPHY_PLL_CO_MAX 3 +/* MAX DSI TX payload */ +#define DSI_TX_MAX_PAYLOAD_BYTE (64U * 4U) + struct display_mcux_mipi_dsi_config { MIPI_DSI_Type base; dsi_dpi_config_t dpi_config; @@ -251,6 +254,14 @@ static ssize_t dsi_mcux_transfer(const struct device *dev, uint8_t channel, dsi_xfer.dscCmd = msg->cmd; dsi_xfer.flags = kDSI_TransferUseHighSpeed; dsi_xfer.txDataType = kDSI_TxDataDcsLongWr; + /* + * Cap transfer size. Note that we subtract six bytes here, + * one for the DSC command and one to insure that + * transfers are still aligned on a pixel boundary + * (two or three byte pixel sizes are supported). + */ + dsi_xfer.txDataSize = MIN(dsi_xfer.txDataSize, + (DSI_TX_MAX_PAYLOAD_BYTE - 6)); break; case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM: dsi_xfer.txDataType = kDSI_TxDataGenShortWrNoParam; @@ -285,11 +296,11 @@ static ssize_t dsi_mcux_transfer(const struct device *dev, uint8_t channel, if (msg->rx_len != 0) { /* Return rx_len on a read */ - return msg->rx_len; + return dsi_xfer.rxDataSize; } /* Return tx_len on a write */ - return msg->tx_len; + return dsi_xfer.txDataSize; } diff --git a/drivers/mipi_dsi/dsi_mcux_2l.c b/drivers/mipi_dsi/dsi_mcux_2l.c index 9f4dcdf0957..62ab1400a22 100644 --- a/drivers/mipi_dsi/dsi_mcux_2l.c +++ b/drivers/mipi_dsi/dsi_mcux_2l.c @@ -11,9 +11,14 @@ #include #include #include +#include +#include +#include +#include + +#include #include #include -#include #include @@ -23,6 +28,7 @@ struct mcux_mipi_dsi_config { MIPI_DSI_HOST_Type *base; dsi_dpi_config_t dpi_config; bool auto_insert_eotp; + bool noncontinuous_hs_clk; const struct device *bit_clk_dev; clock_control_subsys_t bit_clk_subsys; const struct device *esc_clk_dev; @@ -30,14 +36,108 @@ struct mcux_mipi_dsi_config { const struct device *pixel_clk_dev; clock_control_subsys_t pixel_clk_subsys; uint32_t dphy_ref_freq; +#ifdef CONFIG_MIPI_DSI_MCUX_2L_SMARTDMA + const struct device *smart_dma; +#else void (*irq_config_func)(const struct device *dev); +#endif }; struct mcux_mipi_dsi_data { dsi_handle_t mipi_handle; struct k_sem transfer_sem; +#ifdef CONFIG_MIPI_DSI_MCUX_2L_SMARTDMA + uint8_t dma_slot; +#endif }; + +/* MAX DSI TX payload */ +#define DSI_TX_MAX_PAYLOAD_BYTE (64U * 4U) + + +#ifdef CONFIG_MIPI_DSI_MCUX_2L_SMARTDMA + +/* Callback for DSI DMA transfer completion, called in ISR context */ +static void dsi_mcux_dma_cb(const struct device *dma_dev, + void *user_data, uint32_t channel, int status) +{ + const struct device *dev = user_data; + const struct mcux_mipi_dsi_config *config = dev->config; + struct mcux_mipi_dsi_data *data = dev->data; + uint32_t int_flags1, int_flags2; + + if (status != 0) { + LOG_ERR("SMARTDMA transfer failed"); + } else { + /* Disable DSI interrupts at transfer completion */ + DSI_DisableInterrupts(config->base, kDSI_InterruptGroup1ApbTxDone | + kDSI_InterruptGroup1HtxTo, 0U); + DSI_GetAndClearInterruptStatus(config->base, &int_flags1, &int_flags2); + k_sem_give(&data->transfer_sem); + } +} + +/* Helper function to transfer DSI color (DMA based implementation) */ +static int dsi_mcux_tx_color(const struct device *dev, uint8_t channel, + struct mipi_dsi_msg *msg) +{ + /* + * Color streams are a special case for this DSI peripheral, because + * the SMARTDMA peripheral (if enabled) can be used to accelerate + * the transfer of data to the DSI. The SMARTDMA has the additional + * advantage over traditional DMA of being able to to automatically + * byte swap color data. This is advantageous, as most graphical + * frameworks store RGB data in little endian format, but many + * MIPI displays expect color data in big endian format. + */ + const struct mcux_mipi_dsi_config *config = dev->config; + struct mcux_mipi_dsi_data *data = dev->data; + struct dma_config dma_cfg = {0}; + struct dma_block_config block = {0}; + int ret; + + if (channel != 0) { + return -ENOTSUP; /* DMA can only transfer on virtual channel 0 */ + } + + /* Configure smartDMA device, and run transfer */ + block.source_address = (uint32_t)msg->tx_buf; + block.block_size = msg->tx_len; + + dma_cfg.dma_callback = dsi_mcux_dma_cb; + dma_cfg.user_data = (struct device *)dev; + dma_cfg.head_block = █ + dma_cfg.block_count = 1; + dma_cfg.dma_slot = data->dma_slot; + dma_cfg.channel_direction = MEMORY_TO_PERIPHERAL; + ret = dma_config(config->smart_dma, 0, &dma_cfg); + if (ret < 0) { + LOG_ERR("Could not configure SMARTDMA"); + return ret; + } + /* + * SMARTDMA uses DSI interrupt line as input for the DMA + * transfer trigger. Therefore, we need to enable DSI TX + * interrupts in order to trigger the DMA engine. + * Note that if the MIPI IRQ is enabled in + * the NVIC, it will fire on every SMARTDMA transfer + */ + DSI_EnableInterrupts(config->base, kDSI_InterruptGroup1ApbTxDone | + kDSI_InterruptGroup1HtxTo, 0U); + /* Trigger DMA engine */ + ret = dma_start(config->smart_dma, 0); + if (ret < 0) { + LOG_ERR("Could not start SMARTDMA"); + return ret; + } + /* Wait for TX completion */ + k_sem_take(&data->transfer_sem, K_FOREVER); + return msg->tx_len; +} + +#else /* CONFIG_MIPI_DSI_MCUX_2L_SMARTDMA is not set */ + /* Callback for DSI transfer completion, called in ISR context */ static void dsi_transfer_complete(MIPI_DSI_HOST_Type *base, dsi_handle_t *handle, status_t status, void *userData) @@ -47,14 +147,75 @@ static void dsi_transfer_complete(MIPI_DSI_HOST_Type *base, k_sem_give(&data->transfer_sem); } + +/* Helper function to transfer DSI color (Interrupt based implementation) */ +static int dsi_mcux_tx_color(const struct device *dev, uint8_t channel, + struct mipi_dsi_msg *msg) +{ + const struct mcux_mipi_dsi_config *config = dev->config; + struct mcux_mipi_dsi_data *data = dev->data; + status_t status; + dsi_transfer_t xfer = { + .virtualChannel = channel, + .txData = msg->tx_buf, + .rxDataSize = (uint16_t)msg->rx_len, + .rxData = msg->rx_buf, + .sendDscCmd = true, + .dscCmd = msg->cmd, + .txDataType = kDSI_TxDataDcsLongWr, + /* default to high speed unless told to use low power */ + .flags = (msg->flags & MIPI_DSI_MSG_USE_LPM) ? 0 : kDSI_TransferUseHighSpeed, + }; + + /* + * Cap transfer size. Note that we subtract six bytes here, + * one for the DSC command and five to insure that + * transfers are still aligned on a pixel boundary + * (two or three byte pixel sizes are supported). + */ + xfer.txDataSize = MIN(msg->tx_len, (DSI_TX_MAX_PAYLOAD_BYTE - 6)); + + if (IS_ENABLED(CONFIG_MIPI_DSI_MCUX_2L_SWAP16)) { + /* Manually swap the 16 byte color data in software */ + uint8_t *src = (uint8_t *)xfer.txData; + uint8_t tmp; + + for (uint32_t i = 0; i < xfer.txDataSize; i += 2) { + tmp = src[i]; + src[i] = src[i + 1]; + src[i + 1] = tmp; + } + } + /* Send TX data using non-blocking DSI API */ + status = DSI_TransferNonBlocking(config->base, + &data->mipi_handle, &xfer); + /* Wait for transfer completion */ + k_sem_take(&data->transfer_sem, K_FOREVER); + if (status != kStatus_Success) { + LOG_ERR("Transmission failed"); + return -EIO; + } + return xfer.txDataSize; +} + +/* ISR is used for DSI interrupt based implementation, unnecessary if DMA is used */ +static int mipi_dsi_isr(const struct device *dev) +{ + const struct mcux_mipi_dsi_config *config = dev->config; + struct mcux_mipi_dsi_data *data = dev->data; + + DSI_TransferHandleIRQ(config->base, &data->mipi_handle); + return 0; +} + +#endif + static int dsi_mcux_attach(const struct device *dev, uint8_t channel, const struct mipi_dsi_device *mdev) { const struct mcux_mipi_dsi_config *config = dev->config; - struct mcux_mipi_dsi_data *data = dev->data; dsi_dphy_config_t dphy_config; - status_t status; dsi_config_t dsi_config; uint32_t dphy_bit_clk_freq; uint32_t dphy_esc_clk_freq; @@ -64,17 +225,54 @@ static int dsi_mcux_attach(const struct device *dev, DSI_GetDefaultConfig(&dsi_config); dsi_config.numLanes = mdev->data_lanes; dsi_config.autoInsertEoTp = config->auto_insert_eotp; + dsi_config.enableNonContinuousHsClk = config->noncontinuous_hs_clk; + + imxrt_pre_init_display_interface(); /* Init the DSI module. */ DSI_Init(config->base, &dsi_config); - /* Create transfer handle */ - status = DSI_TransferCreateHandle(config->base, &data->mipi_handle, - dsi_transfer_complete, data); +#ifdef CONFIG_MIPI_DSI_MCUX_2L_SMARTDMA + /* Connect DSI IRQ line to SMARTDMA trigger via + * INPUTMUX. + */ + /* Attach INPUTMUX from MIPI to SMARTDMA */ + INPUTMUX_Init(INPUTMUX); + INPUTMUX_AttachSignal(INPUTMUX, 0, kINPUTMUX_MipiIrqToSmartDmaInput); + /* Gate inputmux clock to save power */ + INPUTMUX_Deinit(INPUTMUX); - if (status != kStatus_Success) { + if (!device_is_ready(config->smart_dma)) { + return -ENODEV; + } + + struct mcux_mipi_dsi_data *data = dev->data; + + switch (mdev->pixfmt) { + case MIPI_DSI_PIXFMT_RGB888: + data->dma_slot = DMA_SMARTDMA_MIPI_RGB888_DMA; + break; + case MIPI_DSI_PIXFMT_RGB565: + if (IS_ENABLED(CONFIG_MIPI_DSI_MCUX_2L_SWAP16)) { + data->dma_slot = DMA_SMARTDMA_MIPI_RGB565_DMA_SWAP; + } else { + data->dma_slot = DMA_SMARTDMA_MIPI_RGB565_DMA; + } + break; + default: + LOG_ERR("SMARTDMA does not support pixel_format %u", + mdev->pixfmt); + return -ENODEV; + } +#else + struct mcux_mipi_dsi_data *data = dev->data; + + /* Create transfer handle */ + if (DSI_TransferCreateHandle(config->base, &data->mipi_handle, + dsi_transfer_complete, data) != kStatus_Success) { return -ENODEV; } +#endif /* Get the DPHY bit clock frequency */ if (clock_control_get_rate(config->bit_clk_dev, @@ -148,19 +346,39 @@ static int dsi_mcux_attach(const struct device *dev, return 0; } +static int dsi_mcux_detach(const struct device *dev, uint8_t channel, + const struct mipi_dsi_device *mdev) +{ + const struct mcux_mipi_dsi_config *config = dev->config; + + /* Enable DPHY auto power down */ + DSI_DeinitDphy(config->base); + /* Fully power off DPHY */ + config->base->PD_DPHY = 0x1; + /* Deinit MIPI */ + DSI_Deinit(config->base); + /* Call IMX RT clock function to gate clocks and power at SOC level */ + imxrt_deinit_display_interface(); + return 0; +} + + + static ssize_t dsi_mcux_transfer(const struct device *dev, uint8_t channel, struct mipi_dsi_msg *msg) { const struct mcux_mipi_dsi_config *config = dev->config; - struct mcux_mipi_dsi_data *data = dev->data; dsi_transfer_t dsi_xfer = {0}; status_t status; + int ret; dsi_xfer.virtualChannel = channel; dsi_xfer.txDataSize = msg->tx_len; dsi_xfer.txData = msg->tx_buf; dsi_xfer.rxDataSize = msg->rx_len; dsi_xfer.rxData = msg->rx_buf; + /* default to high speed unless told to use low power */ + dsi_xfer.flags = (msg->flags & MIPI_DSI_MSG_USE_LPM) ? 0 : kDSI_TransferUseHighSpeed; switch (msg->type) { case MIPI_DSI_DCS_READ: @@ -179,8 +397,20 @@ static ssize_t dsi_mcux_transfer(const struct device *dev, uint8_t channel, case MIPI_DSI_DCS_LONG_WRITE: dsi_xfer.sendDscCmd = true; dsi_xfer.dscCmd = msg->cmd; - dsi_xfer.flags = kDSI_TransferUseHighSpeed; dsi_xfer.txDataType = kDSI_TxDataDcsLongWr; + if (msg->flags & MCUX_DSI_2L_FB_DATA) { + /* + * Special case- transfer framebuffer data using + * SMARTDMA or non blocking DSI API. The framebuffer + * will also be color swapped, if enabled. + */ + ret = dsi_mcux_tx_color(dev, channel, msg); + if (ret < 0) { + LOG_ERR("Transmission failed"); + return -EIO; + } + return ret; + } break; case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM: dsi_xfer.txDataType = kDSI_TxDataGenShortWrNoParam; @@ -206,16 +436,7 @@ static ssize_t dsi_mcux_transfer(const struct device *dev, uint8_t channel, return -ENOTSUP; } - if (msg->type == MIPI_DSI_DCS_LONG_WRITE) { - /* Use a non-blocking transfer */ - status = DSI_TransferNonBlocking(config->base, - &data->mipi_handle, &dsi_xfer); - /* Wait for transfer completion */ - k_sem_take(&data->transfer_sem, K_FOREVER); - } else { - status = DSI_TransferBlocking(config->base, &dsi_xfer); - } - + status = DSI_TransferBlocking(config->base, &dsi_xfer); if (status != kStatus_Success) { LOG_ERR("Transmission failed"); return -EIO; @@ -233,30 +454,22 @@ static ssize_t dsi_mcux_transfer(const struct device *dev, uint8_t channel, static struct mipi_dsi_driver_api dsi_mcux_api = { .attach = dsi_mcux_attach, + .detach = dsi_mcux_detach, .transfer = dsi_mcux_transfer, }; -static int mipi_dsi_isr(const struct device *dev) -{ - const struct mcux_mipi_dsi_config *config = dev->config; - struct mcux_mipi_dsi_data *data = dev->data; - - DSI_TransferHandleIRQ(config->base, &data->mipi_handle); - return 0; -} - static int mcux_mipi_dsi_init(const struct device *dev) { const struct mcux_mipi_dsi_config *config = dev->config; struct mcux_mipi_dsi_data *data = dev->data; +#ifndef CONFIG_MIPI_DSI_MCUX_2L_SMARTDMA /* Enable IRQ */ config->irq_config_func(dev); +#endif k_sem_init(&data->transfer_sem, 0, 1); - imxrt_pre_init_display_interface(); - if (!device_is_ready(config->bit_clk_dev) || !device_is_ready(config->esc_clk_dev) || !device_is_ready(config->pixel_clk_dev)) { @@ -295,17 +508,22 @@ static int mcux_mipi_dsi_init(const struct device *dev) },)) #define MCUX_MIPI_DSI_DEVICE(id) \ - static void mipi_dsi_##n##_irq_config_func(const struct device *dev) \ + COND_CODE_1(CONFIG_MIPI_DSI_MCUX_2L_SMARTDMA, \ + (), (static void mipi_dsi_##n##_irq_config_func(const struct device *dev) \ { \ IRQ_CONNECT(DT_INST_IRQN(id), DT_INST_IRQ(id, priority), \ mipi_dsi_isr, DEVICE_DT_INST_GET(id), 0); \ irq_enable(DT_INST_IRQN(id)); \ - } \ + })) \ + \ static const struct mcux_mipi_dsi_config mipi_dsi_config_##id = { \ MCUX_DSI_DPI_CONFIG(id) \ + COND_CODE_1(CONFIG_MIPI_DSI_MCUX_2L_SMARTDMA, \ + (.smart_dma = DEVICE_DT_GET(DT_INST_DMAS_CTLR_BY_NAME(id, smartdma)),), \ + (.irq_config_func = mipi_dsi_##n##_irq_config_func,)) \ .base = (MIPI_DSI_HOST_Type *)DT_INST_REG_ADDR(id), \ - .irq_config_func = mipi_dsi_##n##_irq_config_func, \ .auto_insert_eotp = DT_INST_PROP(id, autoinsert_eotp), \ + .noncontinuous_hs_clk = DT_INST_PROP(id, noncontinuous_hs_clk), \ .dphy_ref_freq = DT_INST_PROP_OR(id, dphy_ref_frequency, 0), \ .bit_clk_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR_BY_NAME(id, dphy)), \ .bit_clk_subsys = \ diff --git a/drivers/misc/CMakeLists.txt b/drivers/misc/CMakeLists.txt index da3ee6da541..863f839184e 100644 --- a/drivers/misc/CMakeLists.txt +++ b/drivers/misc/CMakeLists.txt @@ -4,3 +4,5 @@ add_subdirectory_ifdef(CONFIG_ARM_ETHOS_U ethos_u) add_subdirectory_ifdef(CONFIG_FT800 ft8xx) add_subdirectory_ifdef(CONFIG_GROVE_LCD_RGB grove_lcd_rgb) add_subdirectory_ifdef(CONFIG_PIO_RPI_PICO pio_rpi_pico) +add_subdirectory_ifdef(CONFIG_NXP_S32_EMIOS nxp_s32_emios) +add_subdirectory_ifdef(CONFIG_TIMEAWARE_GPIO timeaware_gpio) diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index e8137dcc131..66d83fc693d 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -8,5 +8,7 @@ menu "Miscellaneous Drivers" source "drivers/misc/ft8xx/Kconfig" source "drivers/misc/grove_lcd_rgb/Kconfig" source "drivers/misc/pio_rpi_pico/Kconfig" +source "drivers/misc/nxp_s32_emios/Kconfig" +source "drivers/misc/timeaware_gpio/Kconfig" endmenu diff --git a/drivers/misc/ethos_u/CMakeLists.txt b/drivers/misc/ethos_u/CMakeLists.txt index 1bb2d158045..c251488eb3c 100644 --- a/drivers/misc/ethos_u/CMakeLists.txt +++ b/drivers/misc/ethos_u/CMakeLists.txt @@ -3,4 +3,4 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_library() -zephyr_library_sources(init.c) +zephyr_library_sources(ethos_u.c) diff --git a/drivers/misc/ethos_u/ethos_u.c b/drivers/misc/ethos_u/ethos_u.c new file mode 100644 index 00000000000..bae2b50c27a --- /dev/null +++ b/drivers/misc/ethos_u/ethos_u.c @@ -0,0 +1,161 @@ +/* + * Copyright 2021-2022 Arm Limited and/or its affiliates + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +LOG_MODULE_REGISTER(ethos_u, CONFIG_ARM_ETHOS_U_LOG_LEVEL); + +#define DT_DRV_COMPAT arm_ethos_u + +/******************************************************************************* + * Re-implementation/Overrides __((weak)) symbol functions from ethosu_driver.c + * To handle mutex and semaphores + *******************************************************************************/ + +void *ethosu_mutex_create(void) +{ + struct k_mutex *mutex; + + mutex = k_malloc(sizeof(*mutex)); + if (mutex == NULL) { + LOG_ERR("Failed allocate mutex"); + return NULL; + } + + k_mutex_init(mutex); + + return (void *)mutex; +} + +int ethosu_mutex_lock(void *mutex) +{ + int status; + + status = k_mutex_lock((struct k_mutex *)mutex, K_FOREVER); + if (status != 0) { + LOG_ERR("Failed to lock mutex with error - %d", status); + return -1; + } + + return 0; +} + +int ethosu_mutex_unlock(void *mutex) +{ + k_mutex_unlock((struct k_mutex *)mutex); + return 0; +} + +void *ethosu_semaphore_create(void) +{ + struct k_sem *sem; + + sem = k_malloc(sizeof(*sem)); + if (sem == NULL) { + LOG_ERR("Failed to allocate semaphore"); + return NULL; + } + + k_sem_init(sem, 0, 100); + + return (void *)sem; +} + +int ethosu_semaphore_take(void *sem) +{ + int status; + + status = k_sem_take((struct k_sem *)sem, K_FOREVER); + if (status != 0) { + LOG_ERR("Failed to take semaphore with error - %d", status); + return -1; + } + + return 0; +} + +int ethosu_semaphore_give(void *sem) +{ + k_sem_give((struct k_sem *)sem); + return 0; +} + +struct ethosu_dts_info { + void *base_addr; + bool secure_enable; + bool privilege_enable; + void (*irq_config)(void); +}; + +struct ethosu_data { + struct ethosu_driver drv; +}; + +void ethosu_zephyr_irq_handler(const struct device *dev) +{ + struct ethosu_data *data = dev->data; + struct ethosu_driver *drv = &data->drv; + + ethosu_irq_handler(drv); +} + +static int ethosu_zephyr_init(const struct device *dev) +{ + const struct ethosu_dts_info *config = dev->config; + struct ethosu_data *data = dev->data; + struct ethosu_driver *drv = &data->drv; + struct ethosu_driver_version version; + + LOG_DBG("Ethos-U DTS info. base_address=0x%p, secure_enable=%u, privilege_enable=%u", + config->base_addr, config->secure_enable, config->privilege_enable); + + ethosu_get_driver_version(&version); + + LOG_DBG("Version. major=%u, minor=%u, patch=%u", version.major, version.minor, + version.patch); + + if (ethosu_init(drv, config->base_addr, NULL, 0, config->secure_enable, + config->privilege_enable)) { + LOG_ERR("Failed to initialize NPU with ethosu_init()."); + return -EINVAL; + } + + config->irq_config(); + + return 0; +} + +#define ETHOSU_DEVICE_INIT(n) \ + static struct ethosu_data ethosu_data_##n; \ + \ + static void ethosu_zephyr_irq_config_##n(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), \ + DT_INST_IRQ(n, priority), \ + ethosu_zephyr_irq_handler, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + } \ + \ + static const struct ethosu_dts_info ethosu_dts_info_##n = { \ + .base_addr = (void *)DT_INST_REG_ADDR(n), \ + .secure_enable = DT_INST_PROP(n, secure_enable), \ + .privilege_enable = DT_INST_PROP(n, privilege_enable), \ + .irq_config = ðosu_zephyr_irq_config_##n, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, ethosu_zephyr_init, NULL, ðosu_data_##n, ðosu_dts_info_##n, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, NULL); + +DT_INST_FOREACH_STATUS_OKAY(ETHOSU_DEVICE_INIT); diff --git a/drivers/misc/ethos_u/init.c b/drivers/misc/ethos_u/init.c deleted file mode 100644 index b50e3facc47..00000000000 --- a/drivers/misc/ethos_u/init.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2021-2022 Arm Limited and/or its affiliates - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include -LOG_MODULE_REGISTER(ethos_u, CONFIG_ARM_ETHOS_U_LOG_LEVEL); - -#define DT_DRV_COMPAT arm_ethos_u - -/******************************************************************************* - * Re-implementation/Overrides __((weak)) symbol functions from ethosu_driver.c - * To handle mutex and semaphores - *******************************************************************************/ - -void *ethosu_mutex_create(void) -{ - struct k_mutex *mutex; - - mutex = k_malloc(sizeof(*mutex)); - if (mutex == NULL) { - LOG_ERR("Failed allocate mutex"); - return NULL; - } - - k_mutex_init(mutex); - - return (void *)mutex; -} - -int ethosu_mutex_lock(void *mutex) -{ - int status; - - status = k_mutex_lock((struct k_mutex *)mutex, K_FOREVER); - if (status != 0) { - LOG_ERR("Failed to lock mutex with error - %d", status); - return -1; - } - - return 0; -} - -int ethosu_mutex_unlock(void *mutex) -{ - k_mutex_unlock((struct k_mutex *)mutex); - return 0; -} - -void *ethosu_semaphore_create(void) -{ - struct k_sem *sem; - - sem = k_malloc(sizeof(*sem)); - if (sem == NULL) { - LOG_ERR("Failed to allocate semaphore"); - return NULL; - } - - k_sem_init(sem, 0, 100); - - return (void *)sem; -} - -int ethosu_semaphore_take(void *sem) -{ - int status; - - status = k_sem_take((struct k_sem *)sem, K_FOREVER); - if (status != 0) { - LOG_ERR("Failed to take semaphore with error - %d", status); - return -1; - } - - return 0; -} - -int ethosu_semaphore_give(void *sem) -{ - k_sem_give((struct k_sem *)sem); - return 0; -} - -struct ethosu_dts_info { - void *base_addr; - bool secure_enable; - bool privilege_enable; - void (*irq_config)(void); -}; - -struct ethosu_data { - struct ethosu_driver drv; -}; - -static int ethosu_zephyr_init(const struct device *dev) -{ - const struct ethosu_dts_info *config = dev->config; - struct ethosu_data *data = dev->data; - struct ethosu_driver *drv = &data->drv; - struct ethosu_driver_version version; - - LOG_DBG("Ethos-U DTS info. base_address=0x%p, secure_enable=%u, privilege_enable=%u", - config->base_addr, config->secure_enable, config->privilege_enable); - - ethosu_get_driver_version(&version); - - LOG_DBG("Version. major=%u, minor=%u, patch=%u", version.major, version.minor, - version.patch); - - if (ethosu_init(drv, config->base_addr, NULL, 0, config->secure_enable, - config->privilege_enable)) { - LOG_ERR("Failed to initialize NPU with ethosu_init()."); - return -EINVAL; - } - - config->irq_config(); - - return 0; -} - -#define ETHOSU_DEVICE_INIT(n) \ - static struct ethosu_data ethosu_data_##n; \ - \ - static void ethosu_zephyr_irq_handler_##n(void) \ - { \ - struct ethosu_driver *drv = ðosu_data_##n.drv; \ - ethosu_irq_handler(drv); \ - } \ - \ - static void ethosu_zephyr_irq_config_##n(void) \ - { \ - IRQ_DIRECT_CONNECT(DT_INST_IRQN(n), \ - DT_INST_IRQ(n, priority), \ - ethosu_zephyr_irq_handler_##n, 0); \ - irq_enable(DT_INST_IRQN(n)); \ - } \ - \ - static const struct ethosu_dts_info ethosu_dts_info_##n = { \ - .base_addr = (void *)DT_INST_REG_ADDR(n), \ - .secure_enable = DT_INST_PROP(n, secure_enable), \ - .privilege_enable = DT_INST_PROP(n, privilege_enable), \ - .irq_config = ðosu_zephyr_irq_config_##n, \ - }; \ - \ - DEVICE_DT_INST_DEFINE(n, ethosu_zephyr_init, NULL, ðosu_data_##n, ðosu_dts_info_##n, \ - POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, NULL); - -DT_INST_FOREACH_STATUS_OKAY(ETHOSU_DEVICE_INIT); diff --git a/drivers/misc/ft8xx/Kconfig b/drivers/misc/ft8xx/Kconfig index 6cc3773e662..1123c188c12 100644 --- a/drivers/misc/ft8xx/Kconfig +++ b/drivers/misc/ft8xx/Kconfig @@ -10,3 +10,10 @@ config FT800 select SPI help Enable driver for FT800 controller. + +config FT800_INIT_PRIORITY + int "FT800 init priority" + default 90 + depends on FT800 + help + FT800 driver initialization priority in POST_KERNEL. diff --git a/drivers/misc/ft8xx/ft8xx.c b/drivers/misc/ft8xx/ft8xx.c index 9b71dd3c92a..1dcbe581b13 100644 --- a/drivers/misc/ft8xx/ft8xx.c +++ b/drivers/misc/ft8xx/ft8xx.c @@ -168,7 +168,7 @@ static int ft8xx_init(const struct device *dev) } DEVICE_DT_INST_DEFINE(0, ft8xx_init, NULL, &ft8xx_data, &ft8xx_config, - APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, NULL); + POST_KERNEL, CONFIG_FT800_INIT_PRIORITY, NULL); int ft8xx_get_touch_tag(void) { diff --git a/drivers/misc/nxp_s32_emios/CMakeLists.txt b/drivers/misc/nxp_s32_emios/CMakeLists.txt new file mode 100644 index 00000000000..72320bb5eae --- /dev/null +++ b/drivers/misc/nxp_s32_emios/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources_ifdef(CONFIG_NXP_S32_EMIOS + nxp_s32_emios.c +) diff --git a/drivers/misc/nxp_s32_emios/Kconfig b/drivers/misc/nxp_s32_emios/Kconfig new file mode 100644 index 00000000000..83f60cf70d2 --- /dev/null +++ b/drivers/misc/nxp_s32_emios/Kconfig @@ -0,0 +1,22 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +config NXP_S32_EMIOS + bool "NXP S32 eMIOS drivers" + depends on DT_HAS_NXP_S32_EMIOS_ENABLED + help + Enable drivers for NXP S32 EMIOS + +if NXP_S32_EMIOS + +module = NXP_S32_EMIOS +module-str = NXP S32 eMIOS +source "subsys/logging/Kconfig.template.log_config" + +config NXP_S32_EMIOS_INIT_PRIORITY + int "NXP S32 eMIOS initialization priority" + default KERNEL_INIT_PRIORITY_DEVICE + help + System initialization priority for NXP S32 eMIOS drivers. + +endif diff --git a/drivers/misc/nxp_s32_emios/nxp_s32_emios.c b/drivers/misc/nxp_s32_emios/nxp_s32_emios.c new file mode 100644 index 00000000000..d22d94b3015 --- /dev/null +++ b/drivers/misc/nxp_s32_emios/nxp_s32_emios.c @@ -0,0 +1,140 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#define LOG_MODULE_NAME nxp_s32_emios +#include +LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_NXP_S32_EMIOS_LOG_LEVEL); + +#include +#include + +#define DT_DRV_COMPAT nxp_s32_emios + +struct nxp_s32_emios_config { + uint8_t instance; + Emios_Mcl_Ip_ConfigType *mcl_info; + void (*irq_config)(void); +}; + +static int nxp_s32_emios_init(const struct device *dev) +{ + const struct nxp_s32_emios_config *config = dev->config; + + if (Emios_Mcl_Ip_Init(config->instance, config->mcl_info)) { + LOG_ERR("Could not initialize eMIOS"); + return -EINVAL; + } + + config->irq_config(); + + return 0; +} + +#define MAX_MASTER_BUS_PERIOD 65535U +#define MIN_MASTER_BUS_PERIOD 2U +#define MAX_GLOB_PRESCALER 256U +#define MIN_GLOB_PRESCALER 1U + +#define NXP_S32_EMIOS_MASTER_BUS_MODE(mode) DT_CAT(EMIOS_IP_, mode) + +#define NXP_S32_EMIOS_INSTANCE_CHECK(idx, n) \ + ((DT_INST_REG_ADDR(n) == IP_EMIOS_##idx##_BASE) ? idx : 0) + +#define NXP_S32_EMIOS_GET_INSTANCE(n) \ + LISTIFY(__DEBRACKET eMIOS_INSTANCE_COUNT, NXP_S32_EMIOS_INSTANCE_CHECK, (|), n) + +#define NXP_S32_EMIOS_GENERATE_GLOBAL_CONFIG(n) \ + BUILD_ASSERT(IN_RANGE(DT_INST_PROP(n, clock_divider), \ + MIN_GLOB_PRESCALER, MAX_GLOB_PRESCALER), \ + "Divider for eMIOS global prescaler is out of range"); \ + const Emios_Ip_GlobalConfigType nxp_s32_emios_##n##_global_config = { \ + .allowDebugMode = true, \ + .clkDivVal = DT_INST_PROP(n, clock_divider) - 1U, \ + .enableGlobalTimeBase = true \ + }; + +#define NXP_S32_EMIOS_MASTER_BUS_VERIFY(node_id) \ + BUILD_ASSERT(IN_RANGE(DT_PROP(node_id, period), \ + MIN_MASTER_BUS_PERIOD, MAX_MASTER_BUS_PERIOD), \ + "Node "DT_NODE_PATH(node_id)": period is out of range"); + +#define NXP_S32_EMIOS_MASTER_BUS_CONFIG(node_id) \ + { \ + .hwChannel = DT_PROP(node_id, channel), \ + .defaultPeriod = DT_PROP(node_id, period), \ + .masterBusPrescaler = DT_PROP(node_id, prescaler) - 1, \ + .allowDebugMode = DT_PROP(node_id, freeze), \ + .masterMode = NXP_S32_EMIOS_MASTER_BUS_MODE(DT_STRING_TOKEN(node_id, mode)), \ + .masterBusAltPrescaler = 0, \ + }, + +#define NXP_S32_EMIOS_GENERATE_MASTER_BUS_CONFIG(n) \ + DT_FOREACH_CHILD_STATUS_OKAY(DT_INST_CHILD(n, master_bus), \ + NXP_S32_EMIOS_MASTER_BUS_VERIFY) \ + const Emios_Ip_MasterBusConfigType nxp_s32_emios_##n##_master_bus_config[] = { \ + DT_FOREACH_CHILD_STATUS_OKAY(DT_INST_CHILD(n, master_bus), \ + NXP_S32_EMIOS_MASTER_BUS_CONFIG) \ + }; + +#define NXP_S32_EMIOS_GENERATE_CONFIG(n) \ + NXP_S32_EMIOS_GENERATE_GLOBAL_CONFIG(n) \ + NXP_S32_EMIOS_GENERATE_MASTER_BUS_CONFIG(n) \ + const Emios_Mcl_Ip_ConfigType nxp_s32_emios_##n##_mcl_config = { \ + .channelsNumber = ARRAY_SIZE(nxp_s32_emios_##n##_master_bus_config), \ + .emiosGlobalConfig = &nxp_s32_emios_##n##_global_config, \ + .masterBusConfig = &nxp_s32_emios_##n##_master_bus_config \ + }; + +#define EMIOS_INTERRUPT_NAME(name) DT_CAT3(EMIOS, name, _IRQ) + +/* + * The real interrupt handlers only defined in some circumstances, just add + * weak implementations to avoid populating so many preprocessor directives + */ +#define EMIOS_INTERRUPT_DEFINE(node_id, prop, idx) \ + __weak void EMIOS_INTERRUPT_NAME(DT_STRING_TOKEN_BY_IDX(node_id, prop, idx))(void) {} + +#define NXP_S32_EMIOS_INTERRUPT_DEFINE(n) \ + DT_INST_FOREACH_PROP_ELEM(n, interrupt_names, EMIOS_INTERRUPT_DEFINE) + +#define EMIOS_INTERRUPT_CONFIG(node_id, prop, idx) \ + do { \ + IRQ_CONNECT(DT_IRQ_BY_IDX(node_id, idx, irq), \ + DT_IRQ_BY_IDX(node_id, idx, priority), \ + EMIOS_INTERRUPT_NAME(DT_STRING_TOKEN_BY_IDX(node_id, prop, idx)),\ + DEVICE_DT_GET(node_id), \ + 0); \ + irq_enable(DT_IRQ_BY_IDX(node_id, idx, irq)); \ + } while (false); + +#define NXP_S32_EMIOS_INTERRUPT_CONFIG(n) \ + static void nxp_s32_emios_##n##_interrupt_config(void) \ + { \ + DT_INST_FOREACH_PROP_ELEM(n, interrupt_names, EMIOS_INTERRUPT_CONFIG) \ + } + +#define NXP_S32_EMIOS_INIT_DEVICE(n) \ + NXP_S32_EMIOS_GENERATE_CONFIG(n) \ + NXP_S32_EMIOS_INTERRUPT_DEFINE(n) \ + NXP_S32_EMIOS_INTERRUPT_CONFIG(n) \ + const struct nxp_s32_emios_config nxp_s32_emios_##n##_config = { \ + .instance = NXP_S32_EMIOS_GET_INSTANCE(n), \ + .mcl_info = (Emios_Mcl_Ip_ConfigType *)&nxp_s32_emios_##n##_mcl_config, \ + .irq_config = nxp_s32_emios_##n##_interrupt_config, \ + }; \ + DEVICE_DT_INST_DEFINE(n, \ + &nxp_s32_emios_init, \ + NULL, \ + NULL, \ + &nxp_s32_emios_##n##_config, \ + POST_KERNEL, \ + CONFIG_NXP_S32_EMIOS_INIT_PRIORITY, \ + NULL); + +DT_INST_FOREACH_STATUS_OKAY(NXP_S32_EMIOS_INIT_DEVICE) diff --git a/drivers/misc/timeaware_gpio/CMakeLists.txt b/drivers/misc/timeaware_gpio/CMakeLists.txt new file mode 100644 index 00000000000..a93054ff217 --- /dev/null +++ b/drivers/misc/timeaware_gpio/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/misc/timeaware_gpio/timeaware_gpio.h) + +zephyr_library() + +zephyr_library_sources_ifdef(CONFIG_TIMEAWARE_GPIO_INTEL timeaware_gpio_intel.c) + +zephyr_library_sources_ifdef(CONFIG_USERSPACE timeaware_gpio_handlers.c) diff --git a/drivers/misc/timeaware_gpio/Kconfig b/drivers/misc/timeaware_gpio/Kconfig new file mode 100644 index 00000000000..a6d7f4a2eb3 --- /dev/null +++ b/drivers/misc/timeaware_gpio/Kconfig @@ -0,0 +1,26 @@ +# Timeaware gpio config options + +# Copyright (c) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + + +menuconfig TIMEAWARE_GPIO + bool "Timeaware GPIO driver" + help + Enable config options for timeaware GPIO driver. + +if TIMEAWARE_GPIO + +module = TIMEAWARE_GPIO +module-str = timeaware_gpio +source "subsys/logging/Kconfig.template.log_config" + +config TIMEAWARE_GPIO_INIT_PRIORITY + int "Timeaware GPIO initialization priority" + default KERNEL_INIT_PRIORITY_DEVICE + help + System initialization priority for timeaware GPIO drivers. + +source "drivers/misc/timeaware_gpio/Kconfig.timeaware_gpio_intel" + +endif # TIMEAWARE_GPIO diff --git a/drivers/misc/timeaware_gpio/Kconfig.timeaware_gpio_intel b/drivers/misc/timeaware_gpio/Kconfig.timeaware_gpio_intel new file mode 100644 index 00000000000..a62ee66dd25 --- /dev/null +++ b/drivers/misc/timeaware_gpio/Kconfig.timeaware_gpio_intel @@ -0,0 +1,11 @@ +# INTEL PMC TGPIO configuration options +# +# Copyright (c) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +config TIMEAWARE_GPIO_INTEL + bool "Intel Time aware GPIO driver" + default y + depends on DT_HAS_INTEL_TIMEAWARE_GPIO_ENABLED + help + Intel time aware GPIO driver found on Intel PCH subsystem diff --git a/drivers/misc/timeaware_gpio/timeaware_gpio_handlers.c b/drivers/misc/timeaware_gpio/timeaware_gpio_handlers.c new file mode 100644 index 00000000000..1904db4218d --- /dev/null +++ b/drivers/misc/timeaware_gpio/timeaware_gpio_handlers.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +static inline int z_vrfy_tgpio_port_get_time(const struct device *port, uint64_t *current_time) +{ + K_OOPS(Z_SYSCALL_DRIVER_TGPIO(port, get_time)); + K_OOPS(Z_SYSCALL_MEMORY_WRITE(current_time, sizeof(uint64_t))); + return z_impl_tgpio_port_get_time((const struct device *)port, (uint64_t *)current_time); +} +#include + +static inline int z_vrfy_tgpio_port_get_cycles_per_second(const struct device *port, + uint32_t *cycles) +{ + K_OOPS(Z_SYSCALL_DRIVER_TGPIO(port, cyc_per_sec)); + K_OOPS(Z_SYSCALL_MEMORY_WRITE(cycles, sizeof(uint32_t))); + return z_impl_tgpio_port_get_cycles_per_second((const struct device *)port, + (uint32_t *)cycles); +} +#include + +static inline int z_vrfy_tgpio_pin_periodic_output(const struct device *port, uint32_t pin, + uint64_t start_time, uint64_t repeat_interval, + bool periodic_enable) +{ + K_OOPS(Z_SYSCALL_DRIVER_TGPIO(port, set_perout)); + return z_impl_tgpio_pin_periodic_output((const struct device *)port, pin, start_time, + repeat_interval, periodic_enable); +} +#include + +static inline int z_vrfy_tgpio_pin_disable(const struct device *port, uint32_t pin) +{ + K_OOPS(Z_SYSCALL_DRIVER_TGPIO(port, pin_disable)); + return z_impl_tgpio_pin_disable((const struct device *)port, pin); +} +#include + +static inline int z_vrfy_tgpio_pin_config_ext_timestamp(const struct device *port, uint32_t pin, + uint32_t event_polarity) +{ + K_OOPS(Z_SYSCALL_DRIVER_TGPIO(port, config_ext_ts)); + return z_impl_tgpio_pin_config_ext_timestamp((const struct device *)port, pin, + event_polarity); +} +#include + +static inline int z_vrfy_tgpio_pin_read_ts_ec(const struct device *port, uint32_t pin, + uint64_t *timestamp, uint64_t *event_count) +{ + K_OOPS(Z_SYSCALL_DRIVER_TGPIO(port, read_ts_ec)); + return z_impl_tgpio_pin_read_ts_ec((const struct device *)port, pin, (uint64_t *)timestamp, + (uint64_t *)event_count); +} +#include diff --git a/drivers/misc/timeaware_gpio/timeaware_gpio_intel.c b/drivers/misc/timeaware_gpio/timeaware_gpio_intel.c new file mode 100644 index 00000000000..ae0e519a437 --- /dev/null +++ b/drivers/misc/timeaware_gpio/timeaware_gpio_intel.c @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT intel_timeaware_gpio + +#include +#include +#include +#include +#include +#include +#include + +/* TGPIO Register offsets */ +#define ART_L 0x00 /* ART lower 32 bit reg */ +#define ART_H 0x04 /* ART higher 32 bit reg */ +#define CTL 0x10 /* TGPIO control reg */ +#define COMPV31_0 0x20 /* Comparator lower 32 bit reg */ +#define COMPV63_32 0x24 /* Comparator higher 32 bit reg */ +#define PIV31_0 0x28 /* Periodic Interval lower 32 bit reg */ +#define PIV63_32 0x2c /* Periodic Interval higher 32 bit reg */ +#define TCV31_0 0x30 /* Time Capture lower 32 bit reg */ +#define TCV63_32 0x34 /* Time Capture higher 32 bit reg */ +#define ECCV31_0 0x38 /* Event Counter Capture lower 32 bit reg */ +#define ECCV63_32 0x3c /* Event Counter Capture higher 32 bit reg */ +#define EC31_0 0x40 /* Event Counter lower 32 bit reg */ +#define EC63_32 0x44 /* Event Counter higher 32 bit reg */ +#define REGSET_SIZE 0x100 /* Difference between 0 and 1 */ +#define UINT32_MASK 0xFFFFFFFF /* 32 bit Mask */ +#define UINT32_SIZE 32 + +/* Control Register */ +#define CTL_EN BIT(0) /* Control enable */ +#define CTL_DIR BIT(1) /* Control disable */ +#define CTL_EP GENMASK(3, 2) /* Recerved polarity */ +#define CTL_EP_RISING_EDGE (0 << 2) /* Rising edge */ +#define CTL_EP_FALLING_EDGE (1 << 2) /* Falling edge */ +#define CTL_EP_TOGGLE_EDGE (2 << 2) /* Toggle edge */ +#define CTL_PM BIT(4) /* Periodic mode */ + +/* Macro to get configuration data, required by DEVICE_MMIO_NAMED_* in init */ +#define DEV_CFG(_dev) \ + ((const struct tgpio_config *)(_dev)->config) +/* Macro to get runtime data, required by DEVICE_MMIO_NAMED_* in init */ +#define DEV_DATA(_dev) ((struct tgpio_runtime *)(_dev)->data) +/* Macro to individual pin regbase */ +#define pin_regs(addr, pin) (addr + (pin * REGSET_SIZE)) + +struct tgpio_config { + DEVICE_MMIO_NAMED_ROM(reg_base); + uint32_t max_pins; + uint32_t art_clock_freq; +}; + +struct tgpio_runtime { + DEVICE_MMIO_NAMED_RAM(reg_base); +}; + +static mm_reg_t regs(const struct device *dev) +{ + return DEVICE_MMIO_NAMED_GET(dev, reg_base); +} + +static int tgpio_intel_get_time(const struct device *dev, + uint64_t *current_time) +{ + *current_time = sys_read32(regs(dev) + ART_L); + *current_time += ((uint64_t)sys_read32(regs(dev) + ART_H) << UINT32_SIZE); + + return 0; +} + +static int tgpio_intel_cyc_per_sec(const struct device *dev, + uint32_t *cycles) +{ + *cycles = DEV_CFG(dev)->art_clock_freq; + + return 0; +} + +static int tgpio_intel_pin_disable(const struct device *dev, + uint32_t pin) +{ + mm_reg_t addr = regs(dev); + + if (pin >= DEV_CFG(dev)->max_pins) { + return -EINVAL; + } + + addr = pin_regs(addr, pin); + sys_write32(sys_read32(addr + CTL) & ~CTL_EN, addr + CTL); + + return 0; +} + +static int tgpio_intel_periodic_output(const struct device *dev, + uint32_t pin, + uint64_t start_time, + uint64_t repeat_interval, + bool periodic_enable) +{ + mm_reg_t addr = regs(dev); + uint32_t val; + + if (pin >= DEV_CFG(dev)->max_pins) { + return -EINVAL; + } + + addr = pin_regs(addr, pin); + tgpio_intel_pin_disable(dev, pin); + + /* Configure PIV */ + val = (repeat_interval >> UINT32_SIZE) & UINT32_MASK; + sys_write32(val, addr + PIV63_32); + val = repeat_interval & UINT32_MASK; + sys_write32(val, addr + PIV31_0); + + /* Configure COMPV */ + val = (start_time >> UINT32_SIZE) & UINT32_MASK; + sys_write32(val, addr + COMPV63_32); + val = start_time & UINT32_MASK; + sys_write32(val, addr + COMPV31_0); + + val = 0; + + /* Configure Periodic Mode */ + if (periodic_enable) { + val |= CTL_PM; + } + + /* Enable the pin */ + val |= CTL_EN; + sys_write32(val, addr + CTL); + + return 0; +} + +static int tgpio_intel_config_external_timestamp(const struct device *dev, + uint32_t pin, + uint32_t event_polarity) +{ + mm_reg_t addr = regs(dev); + uint32_t val; + + if (pin >= DEV_CFG(dev)->max_pins) { + return -EINVAL; + } + + addr = pin_regs(addr, pin); + tgpio_intel_pin_disable(dev, pin); + + /* Configure interrupt polarity */ + if (event_polarity == 0) { + val = CTL_EP_RISING_EDGE; + } else if (event_polarity == 1) { + val = CTL_EP_FALLING_EDGE; + } else { + val = CTL_EP_TOGGLE_EDGE; + } + + /* Configure direction = input */ + val |= CTL_DIR; + sys_write32(val, addr + CTL); + + /* Enable the pin */ + sys_write32(sys_read32(addr + CTL) | CTL_EN, addr + CTL); + + return 0; +} + +static int tgpio_intel_read_ts_ec(const struct device *dev, + uint32_t pin, + uint64_t *timestamp, + uint64_t *event_count) +{ + if (pin >= DEV_CFG(dev)->max_pins) { + return -EINVAL; + } + + *timestamp = sys_read32(regs(dev) + TCV31_0); + *timestamp += ((uint64_t)sys_read32(regs(dev) + TCV63_32) << UINT32_SIZE); + *event_count = sys_read32(regs(dev) + ECCV31_0); + *event_count += ((uint64_t)sys_read32(regs(dev) + ECCV63_32) << UINT32_SIZE); + + return 0; +} + +static const struct tgpio_driver_api api_funcs = { + .pin_disable = tgpio_intel_pin_disable, + .get_time = tgpio_intel_get_time, + .set_perout = tgpio_intel_periodic_output, + .config_ext_ts = tgpio_intel_config_external_timestamp, + .read_ts_ec = tgpio_intel_read_ts_ec, + .cyc_per_sec = tgpio_intel_cyc_per_sec, +}; + +static int tgpio_init(const struct device *dev) +{ + const struct tgpio_config *cfg = DEV_CFG(dev); + struct tgpio_runtime *rt = DEV_DATA(dev); + + device_map(&rt->reg_base, + cfg->reg_base.phys_addr & ~0xFFU, + cfg->reg_base.size, + K_MEM_CACHE_NONE); + + return 0; +} + +#define TGPIO_INTEL_DEV_CFG_DATA(n) \ + static const struct tgpio_config \ + tgpio_##n##_cfg = { \ + DEVICE_MMIO_NAMED_ROM_INIT(reg_base, DT_DRV_INST(n)), \ + .max_pins = DT_INST_PROP(n, max_pins), \ + .art_clock_freq = DT_INST_PROP(n, timer_clock), \ + }; \ + \ + static struct tgpio_runtime tgpio_##n##_runtime; \ + \ + DEVICE_DT_INST_DEFINE(n, \ + &tgpio_init, \ + NULL, \ + &tgpio_##n##_runtime, \ + &tgpio_##n##_cfg, \ + POST_KERNEL, CONFIG_TIMEAWARE_GPIO_INIT_PRIORITY,\ + &api_funcs); \ + +DT_INST_FOREACH_STATUS_OKAY(TGPIO_INTEL_DEV_CFG_DATA) diff --git a/drivers/mm/mm_drv_bank.c b/drivers/mm/mm_drv_bank.c index 03209ffec41..ca9ad9d051b 100644 --- a/drivers/mm/mm_drv_bank.c +++ b/drivers/mm/mm_drv_bank.c @@ -18,14 +18,14 @@ #include #include -void sys_mm_drv_bank_init(struct mem_drv_bank *bank, uint32_t bank_pages) +void sys_mm_drv_bank_init(struct sys_mm_drv_bank *bank, uint32_t bank_pages) { bank->unmapped_pages = 0; bank->mapped_pages = bank_pages; bank->max_mapped_pages = bank_pages; } -uint32_t sys_mm_drv_bank_page_mapped(struct mem_drv_bank *bank) +uint32_t sys_mm_drv_bank_page_mapped(struct sys_mm_drv_bank *bank) { bank->unmapped_pages--; bank->mapped_pages++; @@ -35,14 +35,14 @@ uint32_t sys_mm_drv_bank_page_mapped(struct mem_drv_bank *bank) return bank->mapped_pages; } -uint32_t sys_mm_drv_bank_page_unmapped(struct mem_drv_bank *bank) +uint32_t sys_mm_drv_bank_page_unmapped(struct sys_mm_drv_bank *bank) { bank->unmapped_pages++; bank->mapped_pages--; return bank->unmapped_pages; } -void sys_mm_drv_bank_stats_get(struct mem_drv_bank *bank, +void sys_mm_drv_bank_stats_get(struct sys_mm_drv_bank *bank, struct sys_memory_stats *stats) { stats->free_bytes = bank->unmapped_pages * @@ -53,7 +53,7 @@ void sys_mm_drv_bank_stats_get(struct mem_drv_bank *bank, CONFIG_MM_DRV_PAGE_SIZE; } -void sys_mm_drv_bank_stats_reset_max(struct mem_drv_bank *bank) +void sys_mm_drv_bank_stats_reset_max(struct sys_mm_drv_bank *bank) { bank->max_mapped_pages = bank->mapped_pages; } diff --git a/drivers/mm/mm_drv_intel_adsp.h b/drivers/mm/mm_drv_intel_adsp.h index b62e7ceb27d..8de9ccc42ca 100644 --- a/drivers/mm/mm_drv_intel_adsp.h +++ b/drivers/mm/mm_drv_intel_adsp.h @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/mm/mm_drv_intel_adsp_mtl_tlb.c b/drivers/mm/mm_drv_intel_adsp_mtl_tlb.c index 6e9b75b11f7..ea3bb385b3b 100644 --- a/drivers/mm/mm_drv_intel_adsp_mtl_tlb.c +++ b/drivers/mm/mm_drv_intel_adsp_mtl_tlb.c @@ -27,10 +27,12 @@ #include #include +#define SRAM_BANK_PAGE_NUM (SRAM_BANK_SIZE / CONFIG_MM_DRV_PAGE_SIZE) + static struct k_spinlock tlb_lock; extern struct k_spinlock sys_mm_drv_common_lock; -static struct mem_drv_bank hpsram_bank[L2_SRAM_BANK_NUM]; +static struct sys_mm_drv_bank hpsram_bank[L2_SRAM_BANK_NUM]; #ifdef CONFIG_SOC_INTEL_COMM_WIDGET #include @@ -625,7 +627,7 @@ static int sys_mm_drv_mm_init(const struct device *dev) uint32_t avalible_memory_size = ace_hpsram_get_bank_count() * SRAM_BANK_SIZE; - L2_PHYS_SRAM_REGION.num_blocks = avalible_memory_size / CONFIG_MM_DRV_PAGE_SIZE; + L2_PHYS_SRAM_REGION.info.num_blocks = avalible_memory_size / CONFIG_MM_DRV_PAGE_SIZE; ret = calculate_memory_regions(UNUSED_L2_START_ALIGNED); CHECKIF(ret != 0) { @@ -668,7 +670,7 @@ static int sys_mm_drv_mm_init(const struct device *dev) __ASSERT(false, "unused l2 pointer is outside of l2 sram range %p\n", - UNUSED_L2_START_ALIGNED); + (void *)UNUSED_L2_START_ALIGNED); return -EFAULT; } diff --git a/drivers/mm/mm_drv_intel_adsp_tlb.c b/drivers/mm/mm_drv_intel_adsp_tlb.c index 26d69371a2d..315496be8e0 100644 --- a/drivers/mm/mm_drv_intel_adsp_tlb.c +++ b/drivers/mm/mm_drv_intel_adsp_tlb.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/mm/mm_drv_ti_rat.c b/drivers/mm/mm_drv_ti_rat.c index da085b72f23..b82bbc162ac 100644 --- a/drivers/mm/mm_drv_ti_rat.c +++ b/drivers/mm/mm_drv_ti_rat.c @@ -19,6 +19,7 @@ * the address space. */ +#include #include #include #include diff --git a/drivers/modem/CMakeLists.txt b/drivers/modem/CMakeLists.txt index 96a10be34fb..a97568dfc65 100644 --- a/drivers/modem/CMakeLists.txt +++ b/drivers/modem/CMakeLists.txt @@ -12,33 +12,30 @@ zephyr_library_sources_ifdef(CONFIG_MODEM_IFACE_UART_ASYNC modem_iface_uart_asyn zephyr_library_sources_ifdef(CONFIG_MODEM_CMD_HANDLER modem_cmd_handler.c) zephyr_library_sources_ifdef(CONFIG_MODEM_SOCKET modem_socket.c) +zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/net/ip) +zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/net/lib/sockets) + if(CONFIG_MODEM_UBLOX_SARA) - zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/net/ip) zephyr_library_sources(ublox-sara-r4.c) endif() if(CONFIG_MODEM_QUECTEL_BG9X) - zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/net/ip) zephyr_library_sources(quectel-bg9x.c) endif() if(CONFIG_MODEM_WNCM14A2A) - zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/net/ip) zephyr_library_sources(wncm14a2a.c) endif() if(CONFIG_MODEM_GSM_PPP) - zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/net/ip) zephyr_library_sources(gsm_ppp.c) endif() if (CONFIG_MODEM_HL7800) - zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/net/ip) zephyr_library_sources(hl7800.c) endif() if (CONFIG_MODEM_SIM7080) - zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/net/ip) zephyr_library_sources(simcom-sim7080.c) endif() diff --git a/drivers/modem/Kconfig.cellular b/drivers/modem/Kconfig.cellular index 6869f047dad..7817fb599e3 100644 --- a/drivers/modem/Kconfig.cellular +++ b/drivers/modem/Kconfig.cellular @@ -13,7 +13,8 @@ config MODEM_CELLULAR select NET_L2_PPP_OPTION_MRU depends on (DT_HAS_QUECTEL_BG95_ENABLED || DT_HAS_ZEPHYR_GSM_PPP_ENABLED || \ DT_HAS_SIMCOM_SIM7080_ENABLED || DT_HAS_U_BLOX_SARA_R4_ENABLED || \ - DT_HAS_SWIR_HL7800_ENABLED) + DT_HAS_SWIR_HL7800_ENABLED || DT_HAS_TELIT_ME910G1_ENABLED || \ + DT_HAS_QUECTEL_EG25_G_ENABLED) help This driver uses the generic 3gpp AT commands, along with the standard protocols CMUX and PPP, to configure @@ -30,4 +31,8 @@ config MODEM_CELLULAR_APN string "APN" default "internet" +config MODEM_CELLULAR_PERIODIC_SCRIPT_MS + int "Periodic script interval in milliseconds" + default 2000 + endif diff --git a/drivers/modem/Kconfig.gsm b/drivers/modem/Kconfig.gsm index 24e608e590e..101c1e2ece4 100644 --- a/drivers/modem/Kconfig.gsm +++ b/drivers/modem/Kconfig.gsm @@ -2,14 +2,15 @@ # SPDX-License-Identifier: Apache-2.0 config MODEM_GSM_PPP - bool "Support GSM modems" + bool "[DEPRECATED] Support GSM modems" select MODEM_CONTEXT select MODEM_CMD_HANDLER select MODEM_IFACE_UART select NET_MGMT select NET_MGMT_EVENT + select DEPRECATED help - Enable GSM modems that support standard AT commands and PPP. + This driver is deprecated, use the MODEM_CELLULAR driver instead. if MODEM_GSM_PPP @@ -36,6 +37,25 @@ config MODEM_GSM_QUECTEL endchoice +choice MODEM_GSM_STATUS_COMMAND + prompt "Select status command Type" + default MODEM_GSM_STATUS_CMD_USE_CREG + help + Use particular type of AT command for cell tower registration status. + +config MODEM_GSM_STATUS_CMD_USE_CREG + bool "CREG command" + +config MODEM_GSM_STATUS_CMD_USE_CEREG + bool "CEREG command" + +endchoice + +config MODEM_GSM_STATUS_COMMAND + string "Status Command" + default "CREG" if MODEM_GSM_STATUS_CMD_USE_CREG + default "CEREG" if MODEM_GSM_STATUS_CMD_USE_CEREG + config MODEM_GSM_RX_STACK_SIZE int "Size of the stack allocated for receiving data from modem" default 512 diff --git a/drivers/modem/gsm_ppp.c b/drivers/modem/gsm_ppp.c index f1e8ff5ef99..154092ac356 100644 --- a/drivers/modem/gsm_ppp.c +++ b/drivers/modem/gsm_ppp.c @@ -169,8 +169,12 @@ static int modem_atoi(const char *s, const int err_value, } #endif -static void gsm_rx(struct gsm_modem *gsm) +static void gsm_rx(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct gsm_modem *gsm = p1; LOG_DBG("starting"); while (true) { @@ -525,7 +529,7 @@ static const struct modem_cmd read_cops_cmd = MODEM_CMD_ARGS_MAX("+COPS:", on_cmd_atcmdinfo_cops, 1U, 4U, ","); static const struct modem_cmd check_net_reg_cmd = - MODEM_CMD("+CREG: ", on_cmd_net_reg_sts, 2U, ","); + MODEM_CMD("+" CONFIG_MODEM_GSM_STATUS_COMMAND, on_cmd_net_reg_sts, 2U, ","); static const struct modem_cmd check_attached_cmd = MODEM_CMD("+CGATT:", on_cmd_atcmdinfo_attached, 1U, ","); @@ -751,7 +755,7 @@ static void gsm_finalize_connection(struct k_work *work) ret = modem_cmd_send_nolock(&gsm->context.iface, &gsm->context.cmd_handler, &check_net_reg_cmd, 1, - "AT+CREG?", + "AT+" CONFIG_MODEM_GSM_STATUS_COMMAND "?", &gsm->sem_response, GSM_CMD_SETUP_TIMEOUT); if ((ret < 0) || ((gsm->net_state != GSM_NET_ROAMING) && @@ -1323,7 +1327,7 @@ static int gsm_init(const struct device *dev) (void)k_thread_create(&gsm->rx_thread, gsm_rx_stack, K_KERNEL_STACK_SIZEOF(gsm_rx_stack), - (k_thread_entry_t) gsm_rx, + gsm_rx, gsm, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); (void)k_thread_name_set(&gsm->rx_thread, "gsm_rx"); diff --git a/drivers/modem/hl7800.c b/drivers/modem/hl7800.c index 9e59cf5e33b..c635016197e 100644 --- a/drivers/modem/hl7800.c +++ b/drivers/modem/hl7800.c @@ -23,6 +23,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_MODEM_LOG_LEVEL); #include #include +#include #include #include @@ -1762,9 +1763,9 @@ static bool on_cmd_atcmdinfo_imei(struct net_buf **buf, uint16_t len) */ static bool on_cmd_atcmdinfo_iccid(struct net_buf **buf, uint16_t len) { - int ret; char value[MDM_CCID_RESP_MAX_SIZE]; char *delim; + int iccid_len; size_t out_len; out_len = net_buf_linearize(value, sizeof(value), *buf, 0, len); @@ -1783,9 +1784,13 @@ static bool on_cmd_atcmdinfo_iccid(struct net_buf **buf, uint16_t len) LOG_INF("EID: %s", delim + 1); } - ret = snprintk(iface_ctx.mdm_iccid, sizeof(iface_ctx.mdm_iccid), "%s", value); - if (ret > MDM_HL7800_ICCID_MAX_STRLEN) { - LOG_WRN("ICCID too long: %d", ret); + iccid_len = strlen(value); + strncpy(iface_ctx.mdm_iccid, value, sizeof(iface_ctx.mdm_iccid)); + len = MIN(iccid_len, sizeof(iface_ctx.mdm_iccid) - 1); + iface_ctx.mdm_iccid[len] = '\0'; + + if (iccid_len > len) { + LOG_WRN("ICCID too long: %d (max %d)", iccid_len, len); } LOG_INF("ICCID: %s", iface_ctx.mdm_iccid); @@ -4477,8 +4482,12 @@ static void process_fw_update_rx(struct net_buf **rx_buf) #endif /* CONFIG_MODEM_HL7800_FW_UPDATE */ /* RX thread */ -static void hl7800_rx(void) +static void hl7800_rx(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct net_buf *rx_buf = NULL; struct net_buf *frag = NULL; int i, cmp_res; @@ -6421,7 +6430,7 @@ static int hl7800_init(const struct device *dev) k_thread_name_set( k_thread_create(&hl7800_rx_thread, hl7800_rx_stack, K_THREAD_STACK_SIZEOF(hl7800_rx_stack), - (k_thread_entry_t)hl7800_rx, NULL, NULL, NULL, + hl7800_rx, NULL, NULL, NULL, RX_THREAD_PRIORITY, 0, K_NO_WAIT), "hl7800 rx"); diff --git a/drivers/modem/modem_cellular.c b/drivers/modem/modem_cellular.c index b72adcafc6f..c3b97f0b618 100644 --- a/drivers/modem/modem_cellular.c +++ b/drivers/modem/modem_cellular.c @@ -22,6 +22,9 @@ LOG_MODULE_REGISTER(modem_cellular, CONFIG_MODEM_LOG_LEVEL); #include #include +#define MODEM_CELLULAR_PERIODIC_SCRIPT_TIMEOUT \ + K_MSEC(CONFIG_MODEM_CELLULAR_PERIODIC_SCRIPT_MS) + enum modem_cellular_state { MODEM_CELLULAR_STATE_IDLE = 0, MODEM_CELLULAR_STATE_RESET_PULSE, @@ -50,6 +53,8 @@ enum modem_cellular_event { MODEM_CELLULAR_EVENT_TIMEOUT, MODEM_CELLULAR_EVENT_REGISTERED, MODEM_CELLULAR_EVENT_DEREGISTERED, + MODEM_CELLULAR_EVENT_BUS_OPENED, + MODEM_CELLULAR_EVENT_BUS_CLOSED, }; struct modem_cellular_data { @@ -111,6 +116,7 @@ struct modem_cellular_config { const uint16_t shutdown_time_ms; const struct modem_chat_script *init_chat_script; const struct modem_chat_script *dial_chat_script; + const struct modem_chat_script *periodic_chat_script; }; static const char *modem_cellular_state_str(enum modem_cellular_state state) @@ -172,6 +178,10 @@ static const char *modem_cellular_event_str(enum modem_cellular_event event) return "registered"; case MODEM_CELLULAR_EVENT_DEREGISTERED: return "deregistered"; + case MODEM_CELLULAR_EVENT_BUS_OPENED: + return "bus opened"; + case MODEM_CELLULAR_EVENT_BUS_CLOSED: + return "bus closed"; } return ""; @@ -191,6 +201,26 @@ static void modem_cellular_delegate_event(struct modem_cellular_data *data, static void modem_cellular_event_handler(struct modem_cellular_data *data, enum modem_cellular_event evt); +static void modem_cellular_bus_pipe_handler(struct modem_pipe *pipe, + enum modem_pipe_event event, + void *user_data) +{ + struct modem_cellular_data *data = (struct modem_cellular_data *)user_data; + + switch (event) { + case MODEM_PIPE_EVENT_OPENED: + modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_BUS_OPENED); + break; + + case MODEM_PIPE_EVENT_CLOSED: + modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_BUS_CLOSED); + break; + + default: + break; + } +} + static void modem_cellular_dlci1_pipe_handler(struct modem_pipe *pipe, enum modem_pipe_event event, void *user_data) @@ -401,7 +431,7 @@ static int modem_cellular_on_idle_state_enter(struct modem_cellular_data *data) modem_chat_release(&data->chat); modem_ppp_release(data->ppp); modem_cmux_release(&data->cmux); - modem_pipe_close(data->uart_pipe); + modem_pipe_close_async(data->uart_pipe); k_sem_give(&data->suspended_sem); return 0; } @@ -447,10 +477,6 @@ static int modem_cellular_on_idle_state_leave(struct modem_cellular_data *data) gpio_pin_set_dt(&config->reset_gpio, 0); } - if (modem_pipe_open(data->uart_pipe) < 0) { - return -EAGAIN; - } - return 0; } @@ -556,14 +582,8 @@ static void modem_cellular_await_power_on_event_handler(struct modem_cellular_da static int modem_cellular_on_run_init_script_state_enter(struct modem_cellular_data *data) { - const struct modem_cellular_config *config = - (const struct modem_cellular_config *)data->dev->config; - - if (modem_chat_attach(&data->chat, data->uart_pipe) < 0) { - return -EAGAIN; - } - - return modem_chat_script_run(&data->chat, config->init_chat_script); + modem_pipe_attach(data->uart_pipe, modem_cellular_bus_pipe_handler, data); + return modem_pipe_open_async(data->uart_pipe); } static void modem_cellular_run_init_script_event_handler(struct modem_cellular_data *data, @@ -573,10 +593,21 @@ static void modem_cellular_run_init_script_event_handler(struct modem_cellular_d (const struct modem_cellular_config *)data->dev->config; switch (evt) { + case MODEM_CELLULAR_EVENT_BUS_OPENED: + modem_chat_attach(&data->chat, data->uart_pipe); + modem_chat_run_script_async(&data->chat, config->init_chat_script); + break; + case MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS: net_if_set_link_addr(modem_ppp_get_iface(data->ppp), data->imei, ARRAY_SIZE(data->imei), NET_LINK_UNKNOWN); + modem_chat_release(&data->chat); + modem_pipe_attach(data->uart_pipe, modem_cellular_bus_pipe_handler, data); + modem_pipe_close_async(data->uart_pipe); + break; + + case MODEM_CELLULAR_EVENT_BUS_CLOSED: modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_CONNECT_CMUX); break; @@ -603,19 +634,13 @@ static void modem_cellular_run_init_script_event_handler(struct modem_cellular_d } } -static int modem_cellular_on_run_init_script_state_leave(struct modem_cellular_data *data) -{ - modem_chat_release(&data->chat); - return 0; -} - static int modem_cellular_on_connect_cmux_state_enter(struct modem_cellular_data *data) { - if (modem_cmux_attach(&data->cmux, data->uart_pipe) < 0) { - return -EAGAIN; - } - - modem_cellular_start_timer(data, K_MSEC(500)); + /* + * Allow modem to switch bus into CMUX mode. Some modems disable UART RX while + * switching, resulting in UART RX errors as bus is no longer pulled up by modem. + */ + modem_cellular_start_timer(data, K_MSEC(100)); return 0; } @@ -624,6 +649,12 @@ static void modem_cellular_connect_cmux_event_handler(struct modem_cellular_data { switch (evt) { case MODEM_CELLULAR_EVENT_TIMEOUT: + modem_pipe_attach(data->uart_pipe, modem_cellular_bus_pipe_handler, data); + modem_pipe_open_async(data->uart_pipe); + break; + + case MODEM_CELLULAR_EVENT_BUS_OPENED: + modem_cmux_attach(&data->cmux, data->uart_pipe); modem_cmux_connect_async(&data->cmux); break; @@ -700,20 +731,23 @@ static int modem_cellular_on_open_dlci2_state_leave(struct modem_cellular_data * static int modem_cellular_on_run_dial_script_state_enter(struct modem_cellular_data *data) { - const struct modem_cellular_config *config = - (const struct modem_cellular_config *)data->dev->config; - - if (modem_chat_attach(&data->chat, data->dlci1_pipe) < 0) { - return -EAGAIN; - } - - return modem_chat_script_run(&data->chat, config->dial_chat_script); + /* Allow modem time to enter command mode before running dial script */ + modem_cellular_start_timer(data, K_MSEC(100)); + return 0; } static void modem_cellular_run_dial_script_event_handler(struct modem_cellular_data *data, enum modem_cellular_event evt) { + const struct modem_cellular_config *config = + (const struct modem_cellular_config *)data->dev->config; + switch (evt) { + case MODEM_CELLULAR_EVENT_TIMEOUT: + modem_chat_attach(&data->chat, data->dlci1_pipe); + modem_chat_run_script_async(&data->chat, config->dial_chat_script); + break; + case MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS: modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_AWAIT_REGISTERED); break; @@ -739,13 +773,26 @@ static int modem_cellular_on_await_registered_state_enter(struct modem_cellular_ return -EAGAIN; } + modem_cellular_start_timer(data, MODEM_CELLULAR_PERIODIC_SCRIPT_TIMEOUT); return modem_chat_attach(&data->chat, data->dlci2_pipe); } static void modem_cellular_await_registered_event_handler(struct modem_cellular_data *data, enum modem_cellular_event evt) { + const struct modem_cellular_config *config = + (const struct modem_cellular_config *)data->dev->config; + switch (evt) { + case MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS: + case MODEM_CELLULAR_EVENT_SCRIPT_FAILED: + modem_cellular_start_timer(data, MODEM_CELLULAR_PERIODIC_SCRIPT_TIMEOUT); + break; + + case MODEM_CELLULAR_EVENT_TIMEOUT: + modem_chat_run_script_async(&data->chat, config->periodic_chat_script); + break; + case MODEM_CELLULAR_EVENT_REGISTERED: modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_CARRIER_ON); break; @@ -759,16 +806,35 @@ static void modem_cellular_await_registered_event_handler(struct modem_cellular_ } } +static int modem_cellular_on_await_registered_state_leave(struct modem_cellular_data *data) +{ + modem_cellular_stop_timer(data); + return 0; +} + static int modem_cellular_on_carrier_on_state_enter(struct modem_cellular_data *data) { net_if_carrier_on(modem_ppp_get_iface(data->ppp)); + modem_cellular_start_timer(data, MODEM_CELLULAR_PERIODIC_SCRIPT_TIMEOUT); return 0; } static void modem_cellular_carrier_on_event_handler(struct modem_cellular_data *data, enum modem_cellular_event evt) { + const struct modem_cellular_config *config = + (const struct modem_cellular_config *)data->dev->config; + switch (evt) { + case MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS: + case MODEM_CELLULAR_EVENT_SCRIPT_FAILED: + modem_cellular_start_timer(data, MODEM_CELLULAR_PERIODIC_SCRIPT_TIMEOUT); + break; + + case MODEM_CELLULAR_EVENT_TIMEOUT: + modem_chat_run_script_async(&data->chat, config->periodic_chat_script); + break; + case MODEM_CELLULAR_EVENT_DEREGISTERED: modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT); break; @@ -784,6 +850,7 @@ static void modem_cellular_carrier_on_event_handler(struct modem_cellular_data * static int modem_cellular_on_carrier_on_state_leave(struct modem_cellular_data *data) { + modem_cellular_stop_timer(data); net_if_carrier_off(modem_ppp_get_iface(data->ppp)); modem_chat_release(&data->chat); modem_ppp_release(data->ppp); @@ -792,6 +859,7 @@ static int modem_cellular_on_carrier_on_state_leave(struct modem_cellular_data * static int modem_cellular_on_init_power_off_state_enter(struct modem_cellular_data *data) { + modem_pipe_close_async(data->uart_pipe); modem_cellular_start_timer(data, K_MSEC(2000)); return 0; } @@ -965,10 +1033,6 @@ static int modem_cellular_on_state_leave(struct modem_cellular_data *data) ret = modem_cellular_on_power_on_pulse_state_leave(data); break; - case MODEM_CELLULAR_STATE_RUN_INIT_SCRIPT: - ret = modem_cellular_on_run_init_script_state_leave(data); - break; - case MODEM_CELLULAR_STATE_OPEN_DLCI1: ret = modem_cellular_on_open_dlci1_state_leave(data); break; @@ -981,6 +1045,10 @@ static int modem_cellular_on_state_leave(struct modem_cellular_data *data) ret = modem_cellular_on_run_dial_script_state_leave(data); break; + case MODEM_CELLULAR_STATE_AWAIT_REGISTERED: + ret = modem_cellular_on_await_registered_state_leave(data); + break; + case MODEM_CELLULAR_STATE_CARRIER_ON: ret = modem_cellular_on_carrier_on_state_leave(data); break; @@ -1261,8 +1329,8 @@ MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_bg95_init_chat_script_cmds, MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match), MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match), MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match), - MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127,10,3,30,10,2", - 100)); + MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127", 300)); MODEM_CHAT_SCRIPT_DEFINE(quectel_bg95_init_chat_script, quectel_bg95_init_chat_script_cmds, abort_matches, modem_cellular_chat_callback_handler, 10); @@ -1277,6 +1345,56 @@ MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_bg95_dial_chat_script_cmds, MODEM_CHAT_SCRIPT_DEFINE(quectel_bg95_dial_chat_script, quectel_bg95_dial_chat_script_cmds, dial_abort_matches, modem_cellular_chat_callback_handler, 10); + +MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_bg95_periodic_chat_script_cmds, + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match)); + +MODEM_CHAT_SCRIPT_DEFINE(quectel_bg95_periodic_chat_script, + quectel_bg95_periodic_chat_script_cmds, abort_matches, + modem_cellular_chat_callback_handler, 4); +#endif + +#if DT_HAS_COMPAT_STATUS_OKAY(quectel_eg25_g) +MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_eg25_g_init_chat_script_cmds, + MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG=1", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG=1", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match), + MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match), + MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127,10,3,30,10,2", + 100)); + +MODEM_CHAT_SCRIPT_DEFINE(quectel_eg25_g_init_chat_script, quectel_eg25_g_init_chat_script_cmds, + abort_matches, modem_cellular_chat_callback_handler, 10); + +MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_eg25_g_dial_chat_script_cmds, + MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CGACT=0,1", allow_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGDCONT=1,\"IP\"," + "\""CONFIG_MODEM_CELLULAR_APN"\"", + ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP_NONE("ATD*99***1#", 0),); + +MODEM_CHAT_SCRIPT_DEFINE(quectel_eg25_g_dial_chat_script, quectel_eg25_g_dial_chat_script_cmds, + dial_abort_matches, modem_cellular_chat_callback_handler, 10); + +MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_eg25_g_periodic_chat_script_cmds, + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match)); + +MODEM_CHAT_SCRIPT_DEFINE(quectel_eg25_g_periodic_chat_script, + quectel_eg25_g_periodic_chat_script_cmds, abort_matches, + modem_cellular_chat_callback_handler, 4); #endif #if DT_HAS_COMPAT_STATUS_OKAY(zephyr_gsm_ppp) @@ -1297,8 +1415,14 @@ MODEM_CHAT_SCRIPT_CMDS_DEFINE(zephyr_gsm_ppp_init_chat_script_cmds, MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match), MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match), MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match), - MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127,10,3,30,10,2", - 100)); + MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match), + /* The 300ms delay after sending the AT+CMUX command is required + * for some modems to ensure they get enough time to enter CMUX + * mode before sending the first CMUX command. If this delay is + * too short, modems have been observed to simply deadlock, + * refusing to respond to any CMUX command. + */ + MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127", 300)); MODEM_CHAT_SCRIPT_DEFINE(zephyr_gsm_ppp_init_chat_script, zephyr_gsm_ppp_init_chat_script_cmds, abort_matches, modem_cellular_chat_callback_handler, 10); @@ -1313,6 +1437,15 @@ MODEM_CHAT_SCRIPT_CMDS_DEFINE(zephyr_gsm_ppp_dial_chat_script_cmds, MODEM_CHAT_SCRIPT_DEFINE(zephyr_gsm_ppp_dial_chat_script, zephyr_gsm_ppp_dial_chat_script_cmds, dial_abort_matches, modem_cellular_chat_callback_handler, 10); + +MODEM_CHAT_SCRIPT_CMDS_DEFINE(zephyr_gsm_ppp_periodic_chat_script_cmds, + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match)); + +MODEM_CHAT_SCRIPT_DEFINE(zephyr_gsm_ppp_periodic_chat_script, + zephyr_gsm_ppp_periodic_chat_script_cmds, abort_matches, + modem_cellular_chat_callback_handler, 4); #endif #if DT_HAS_COMPAT_STATUS_OKAY(simcom_sim7080) @@ -1333,8 +1466,8 @@ MODEM_CHAT_SCRIPT_CMDS_DEFINE(simcom_sim7080_init_chat_script_cmds, MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match), MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match), MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match), - MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127,10,3,30,10,2", - 100)); + MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127", 300)); MODEM_CHAT_SCRIPT_DEFINE(simcom_sim7080_init_chat_script, simcom_sim7080_init_chat_script_cmds, abort_matches, modem_cellular_chat_callback_handler, 10); @@ -1349,6 +1482,15 @@ MODEM_CHAT_SCRIPT_CMDS_DEFINE(simcom_sim7080_dial_chat_script_cmds, MODEM_CHAT_SCRIPT_DEFINE(simcom_sim7080_dial_chat_script, simcom_sim7080_dial_chat_script_cmds, dial_abort_matches, modem_cellular_chat_callback_handler, 10); + +MODEM_CHAT_SCRIPT_CMDS_DEFINE(simcom_sim7080_periodic_chat_script_cmds, + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match)); + +MODEM_CHAT_SCRIPT_DEFINE(simcom_sim7080_periodic_chat_script, + simcom_sim7080_periodic_chat_script_cmds, abort_matches, + modem_cellular_chat_callback_handler, 4); #endif #if DT_HAS_COMPAT_STATUS_OKAY(u_blox_sara_r4) @@ -1369,8 +1511,8 @@ MODEM_CHAT_SCRIPT_CMDS_DEFINE(u_blox_sara_r4_init_chat_script_cmds, MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match), MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match), MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match), - MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127,10,3,30,10,2", - 100)); + MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMUX=0,0,5,127", ok_match)); MODEM_CHAT_SCRIPT_DEFINE(u_blox_sara_r4_init_chat_script, u_blox_sara_r4_init_chat_script_cmds, abort_matches, modem_cellular_chat_callback_handler, 10); @@ -1385,6 +1527,15 @@ MODEM_CHAT_SCRIPT_CMDS_DEFINE(u_blox_sara_r4_dial_chat_script_cmds, MODEM_CHAT_SCRIPT_DEFINE(u_blox_sara_r4_dial_chat_script, u_blox_sara_r4_dial_chat_script_cmds, dial_abort_matches, modem_cellular_chat_callback_handler, 10); + +MODEM_CHAT_SCRIPT_CMDS_DEFINE(u_blox_sara_r4_periodic_chat_script_cmds, + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match)); + +MODEM_CHAT_SCRIPT_DEFINE(u_blox_sara_r4_periodic_chat_script, + u_blox_sara_r4_periodic_chat_script_cmds, abort_matches, + modem_cellular_chat_callback_handler, 4); #endif #if DT_HAS_COMPAT_STATUS_OKAY(swir_hl7800) @@ -1405,8 +1556,7 @@ MODEM_CHAT_SCRIPT_CMDS_DEFINE(swir_hl7800_init_chat_script_cmds, MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match), MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match), MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match), - MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127,10,3,30,10,2", - 100)); + MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127", 0)); MODEM_CHAT_SCRIPT_DEFINE(swir_hl7800_init_chat_script, swir_hl7800_init_chat_script_cmds, abort_matches, modem_cellular_chat_callback_handler, 10); @@ -1422,56 +1572,292 @@ MODEM_CHAT_SCRIPT_CMDS_DEFINE(swir_hl7800_dial_chat_script_cmds, MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match), MODEM_CHAT_SCRIPT_CMD_RESP_NONE("ATD*99***1#", 0)); +MODEM_CHAT_SCRIPT_CMDS_DEFINE(swir_hl7800_periodic_chat_script_cmds, + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match)); + +MODEM_CHAT_SCRIPT_DEFINE(swir_hl7800_periodic_chat_script, + swir_hl7800_periodic_chat_script_cmds, abort_matches, + modem_cellular_chat_callback_handler, 4); + MODEM_CHAT_SCRIPT_DEFINE(swir_hl7800_dial_chat_script, swir_hl7800_dial_chat_script_cmds, dial_abort_matches, modem_cellular_chat_callback_handler, 10); #endif +#if DT_HAS_COMPAT_STATUS_OKAY(telit_me910g1) +MODEM_CHAT_SCRIPT_CMDS_DEFINE(telit_me910g1_init_chat_script_cmds, + MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100), + MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100), + MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100), + MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100), + MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match), + /* The Telit me910g1 often has an error trying + * to set the PDP context. The radio must be on to set + * the context, and this step must be successful. + * It is moved to the init script to allow retries. + */ + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGDCONT=1,\"IP\"," + "\"" CONFIG_MODEM_CELLULAR_APN "\"", + ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG=1", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG=1", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match), + MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match), + MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127,10,3,30,10,2", + 300)); + +MODEM_CHAT_SCRIPT_DEFINE(telit_me910g1_init_chat_script, telit_me910g1_init_chat_script_cmds, + abort_matches, modem_cellular_chat_callback_handler, 10); + +MODEM_CHAT_SCRIPT_CMDS_DEFINE(telit_me910g1_dial_chat_script_cmds, + MODEM_CHAT_SCRIPT_CMD_RESP("AT", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP_NONE("ATD*99***1#", 0)); + +MODEM_CHAT_SCRIPT_DEFINE(telit_me910g1_dial_chat_script, telit_me910g1_dial_chat_script_cmds, + dial_abort_matches, modem_cellular_chat_callback_handler, 10); + +MODEM_CHAT_SCRIPT_CMDS_DEFINE(telit_me910g1_periodic_chat_script_cmds, + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match)); + +MODEM_CHAT_SCRIPT_DEFINE(telit_me910g1_periodic_chat_script, + telit_me910g1_periodic_chat_script_cmds, abort_matches, + modem_cellular_chat_callback_handler, 4); +#endif + #define MODEM_CELLULAR_INST_NAME(name, inst) \ _CONCAT(_CONCAT(_CONCAT(name, _), DT_DRV_COMPAT), inst) -#define MODEM_CELLULAR_DEVICE(inst) \ - MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ - \ - static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ - .chat_delimiter = {'\r'}, \ - .chat_filter = {'\n'}, \ - .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ - }; \ - \ - static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ - .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ - .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ - .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ - .power_pulse_duration_ms = 1500, \ - .reset_pulse_duration_ms = 100, \ - .startup_time_ms = 10000, \ - .shutdown_time_ms = 5000, \ - .init_chat_script = &_CONCAT(DT_DRV_COMPAT, _init_chat_script), \ - .dial_chat_script = &_CONCAT(DT_DRV_COMPAT, _dial_chat_script), \ - }; \ - \ - PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \ - \ - DEVICE_DT_INST_DEFINE(inst, modem_cellular_init, PM_DEVICE_DT_INST_GET(inst), \ - &MODEM_CELLULAR_INST_NAME(data, inst), \ +#define MODEM_CELLULAR_DEVICE_QUECTEL_BG95(inst) \ + MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ + \ + static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ + .chat_delimiter = {'\r'}, \ + .chat_filter = {'\n'}, \ + .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ + }; \ + \ + static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ + .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ + .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ + .power_pulse_duration_ms = 1500, \ + .reset_pulse_duration_ms = 100, \ + .startup_time_ms = 10000, \ + .shutdown_time_ms = 5000, \ + .init_chat_script = &quectel_bg95_init_chat_script, \ + .dial_chat_script = &quectel_bg95_dial_chat_script, \ + .periodic_chat_script = &quectel_bg95_periodic_chat_script, \ + }; \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \ + \ + DEVICE_DT_INST_DEFINE(inst, modem_cellular_init, PM_DEVICE_DT_INST_GET(inst), \ + &MODEM_CELLULAR_INST_NAME(data, inst), \ + &MODEM_CELLULAR_INST_NAME(config, inst), POST_KERNEL, 99, NULL); + +#define MODEM_CELLULAR_DEVICE_QUECTEL_EG25_G(inst) \ + MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ + \ + static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ + .chat_delimiter = {'\r'}, \ + .chat_filter = {'\n'}, \ + .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ + }; \ + \ + static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ + .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ + .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ + .power_pulse_duration_ms = 1500, \ + .reset_pulse_duration_ms = 500, \ + .startup_time_ms = 15000, \ + .shutdown_time_ms = 5000, \ + .init_chat_script = &quectel_eg25_g_init_chat_script, \ + .dial_chat_script = &quectel_eg25_g_dial_chat_script, \ + .periodic_chat_script = &_CONCAT(DT_DRV_COMPAT, _periodic_chat_script), \ + }; \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \ + \ + DEVICE_DT_INST_DEFINE(inst, modem_cellular_init, PM_DEVICE_DT_INST_GET(inst), \ + &MODEM_CELLULAR_INST_NAME(data, inst), \ + &MODEM_CELLULAR_INST_NAME(config, inst), POST_KERNEL, 99, NULL); + +#define MODEM_CELLULAR_DEVICE_GSM_PPP(inst) \ + MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ + \ + static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ + .chat_delimiter = {'\r'}, \ + .chat_filter = {'\n'}, \ + .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ + }; \ + \ + static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ + .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ + .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ + .power_pulse_duration_ms = 1500, \ + .reset_pulse_duration_ms = 100, \ + .startup_time_ms = 10000, \ + .shutdown_time_ms = 5000, \ + .init_chat_script = &zephyr_gsm_ppp_init_chat_script, \ + .dial_chat_script = &zephyr_gsm_ppp_dial_chat_script, \ + .periodic_chat_script = &zephyr_gsm_ppp_periodic_chat_script, \ + }; \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \ + \ + DEVICE_DT_INST_DEFINE(inst, modem_cellular_init, PM_DEVICE_DT_INST_GET(inst), \ + &MODEM_CELLULAR_INST_NAME(data, inst), \ + &MODEM_CELLULAR_INST_NAME(config, inst), POST_KERNEL, 99, NULL); + +#define MODEM_CELLULAR_DEVICE_SIMCOM_SIM7080(inst) \ + MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ + \ + static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ + .chat_delimiter = {'\r'}, \ + .chat_filter = {'\n'}, \ + .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ + }; \ + \ + static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ + .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ + .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ + .power_pulse_duration_ms = 1500, \ + .reset_pulse_duration_ms = 100, \ + .startup_time_ms = 10000, \ + .shutdown_time_ms = 5000, \ + .init_chat_script = &simcom_sim7080_init_chat_script, \ + .dial_chat_script = &simcom_sim7080_dial_chat_script, \ + .periodic_chat_script = &simcom_sim7080_periodic_chat_script, \ + }; \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \ + \ + DEVICE_DT_INST_DEFINE(inst, modem_cellular_init, PM_DEVICE_DT_INST_GET(inst), \ + &MODEM_CELLULAR_INST_NAME(data, inst), \ + &MODEM_CELLULAR_INST_NAME(config, inst), POST_KERNEL, 99, NULL); + +#define MODEM_CELLULAR_DEVICE_U_BLOX_SARA_R4(inst) \ + MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ + \ + static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ + .chat_delimiter = {'\r'}, \ + .chat_filter = {'\n'}, \ + .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ + }; \ + \ + static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ + .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ + .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ + .power_pulse_duration_ms = 1500, \ + .reset_pulse_duration_ms = 100, \ + .startup_time_ms = 10000, \ + .shutdown_time_ms = 5000, \ + .init_chat_script = &u_blox_sara_r4_init_chat_script, \ + .dial_chat_script = &u_blox_sara_r4_dial_chat_script, \ + .periodic_chat_script = &u_blox_sara_r4_periodic_chat_script, \ + }; \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \ + \ + DEVICE_DT_INST_DEFINE(inst, modem_cellular_init, PM_DEVICE_DT_INST_GET(inst), \ + &MODEM_CELLULAR_INST_NAME(data, inst), \ + &MODEM_CELLULAR_INST_NAME(config, inst), POST_KERNEL, 99, NULL); + +#define MODEM_CELLULAR_DEVICE_SWIR_HL7800(inst) \ + MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ + \ + static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ + .chat_delimiter = {'\r'}, \ + .chat_filter = {'\n'}, \ + .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ + }; \ + \ + static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ + .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ + .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ + .power_pulse_duration_ms = 1500, \ + .reset_pulse_duration_ms = 100, \ + .startup_time_ms = 10000, \ + .shutdown_time_ms = 5000, \ + .init_chat_script = &swir_hl7800_init_chat_script, \ + .dial_chat_script = &swir_hl7800_dial_chat_script, \ + .periodic_chat_script = &swir_hl7800_periodic_chat_script, \ + }; \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \ + \ + DEVICE_DT_INST_DEFINE(inst, modem_cellular_init, PM_DEVICE_DT_INST_GET(inst), \ + &MODEM_CELLULAR_INST_NAME(data, inst), \ + &MODEM_CELLULAR_INST_NAME(config, inst), POST_KERNEL, 99, NULL); + +#define MODEM_CELLULAR_DEVICE_TELIT_ME910G1(inst) \ + MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ + \ + static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ + .chat_delimiter = {'\r'}, \ + .chat_filter = {'\n'}, \ + .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ + }; \ + \ + static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ + .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ + .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ + .power_pulse_duration_ms = 5050, \ + .reset_pulse_duration_ms = 250, \ + .startup_time_ms = 15000, \ + .shutdown_time_ms = 5000, \ + .init_chat_script = &telit_me910g1_init_chat_script, \ + .dial_chat_script = &telit_me910g1_dial_chat_script, \ + .periodic_chat_script = &telit_me910g1_periodic_chat_script, \ + }; \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \ + \ + DEVICE_DT_INST_DEFINE(inst, modem_cellular_init, PM_DEVICE_DT_INST_GET(inst), \ + &MODEM_CELLULAR_INST_NAME(data, inst), \ &MODEM_CELLULAR_INST_NAME(config, inst), POST_KERNEL, 99, NULL); #define DT_DRV_COMPAT quectel_bg95 -DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE) +DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_QUECTEL_BG95) +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT quectel_eg25_g +DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_QUECTEL_EG25_G) #undef DT_DRV_COMPAT #define DT_DRV_COMPAT zephyr_gsm_ppp -DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE) +DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_GSM_PPP) #undef DT_DRV_COMPAT #define DT_DRV_COMPAT simcom_sim7080 -DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE) +DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_SIMCOM_SIM7080) #undef DT_DRV_COMPAT #define DT_DRV_COMPAT u_blox_sara_r4 -DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE) +DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_U_BLOX_SARA_R4) #undef DT_DRV_COMPAT #define DT_DRV_COMPAT swir_hl7800 -DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE) +DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_SWIR_HL7800) +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT telit_me910g1 +DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_TELIT_ME910G1) #undef DT_DRV_COMPAT diff --git a/drivers/modem/quectel-bg9x.c b/drivers/modem/quectel-bg9x.c index 04bb08d665e..714a7606ab6 100644 --- a/drivers/modem/quectel-bg9x.c +++ b/drivers/modem/quectel-bg9x.c @@ -846,8 +846,12 @@ static ssize_t offload_sendmsg(void *obj, const struct msghdr *msg, int flags) /* Func: modem_rx * Desc: Thread to process all messages received from the Modem. */ -static void modem_rx(void) +static void modem_rx(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + while (true) { /* Wait for incoming data */ @@ -1264,7 +1268,7 @@ static int modem_init(const struct device *dev) /* start RX thread */ k_thread_create(&modem_rx_thread, modem_rx_stack, K_KERNEL_STACK_SIZEOF(modem_rx_stack), - (k_thread_entry_t) modem_rx, + modem_rx, NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); /* Init RSSI query */ diff --git a/drivers/modem/simcom-sim7080.c b/drivers/modem/simcom-sim7080.c index 39fb66b6aa1..f0b31a1d1b6 100644 --- a/drivers/modem/simcom-sim7080.c +++ b/drivers/modem/simcom-sim7080.c @@ -802,8 +802,12 @@ static int offload_socket(int family, int type, int proto) /* * Process all messages received from the modem. */ -static void modem_rx(void) +static void modem_rx(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + while (true) { /* Wait for incoming data */ modem_iface_uart_rx_wait(&mctx.iface, K_FOREVER); @@ -1462,7 +1466,7 @@ static int parse_cgnsinf(char *gps_buf) gnss_data.run_status = 1; gnss_data.fix_status = 1; - strncpy(gnss_data.utc, utc, sizeof(gnss_data.utc)); + strncpy(gnss_data.utc, utc, sizeof(gnss_data.utc) - 1); ret = gnss_split_on_dot(lat, &number, &fraction); if (ret != 0) { @@ -2414,7 +2418,7 @@ static int modem_init(const struct device *dev) } k_thread_create(&modem_rx_thread, modem_rx_stack, K_KERNEL_STACK_SIZEOF(modem_rx_stack), - (k_thread_entry_t)modem_rx, NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); + modem_rx, NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); /* Init RSSI query */ k_work_init_delayable(&mdata.rssi_query_work, modem_rssi_query_work); diff --git a/drivers/modem/ublox-sara-r4.c b/drivers/modem/ublox-sara-r4.c index ca70b1465e0..a3fe3c45f83 100644 --- a/drivers/modem/ublox-sara-r4.c +++ b/drivers/modem/ublox-sara-r4.c @@ -936,8 +936,12 @@ MODEM_CMD_DEFINE(on_cmd_socknotifycreg) } /* RX thread */ -static void modem_rx(void) +static void modem_rx(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + while (true) { /* wait for incoming data */ modem_iface_uart_rx_wait(&mctx.iface, K_FOREVER); @@ -2220,7 +2224,7 @@ static int modem_init(const struct device *dev) /* start RX thread */ k_thread_create(&modem_rx_thread, modem_rx_stack, K_KERNEL_STACK_SIZEOF(modem_rx_stack), - (k_thread_entry_t) modem_rx, + modem_rx, NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); #if defined(CONFIG_MODEM_UBLOX_SARA_RSSI_WORK) diff --git a/drivers/modem/wncm14a2a.c b/drivers/modem/wncm14a2a.c index 669c19393d5..5b60d0aaff5 100644 --- a/drivers/modem/wncm14a2a.c +++ b/drivers/modem/wncm14a2a.c @@ -20,7 +20,7 @@ LOG_MODULE_REGISTER(LOG_DOMAIN); #include #include #include -#include +#include #include #include @@ -1057,8 +1057,12 @@ static void wncm14a2a_read_rx(struct net_buf **buf) } /* RX thread */ -static void wncm14a2a_rx(void) +static void wncm14a2a_rx(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct net_buf *rx_buf = NULL; struct net_buf *frag = NULL; int i; @@ -1430,7 +1434,7 @@ static int wncm14a2a_init(const struct device *dev) /* start RX thread */ k_thread_create(&wncm14a2a_rx_thread, wncm14a2a_rx_stack, K_KERNEL_STACK_SIZEOF(wncm14a2a_rx_stack), - (k_thread_entry_t) wncm14a2a_rx, + wncm14a2a_rx, NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); /* init RSSI query */ diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index cd9a0ee3e1b..d8ae5ca1b05 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -42,12 +42,15 @@ static void loopback_init(struct net_if *iface) if (IS_ENABLED(CONFIG_NET_IPV4)) { struct in_addr ipv4_loopback = INADDR_LOOPBACK_INIT; + struct in_addr netmask = { { { 255, 0, 0, 0 } } }; ifaddr = net_if_ipv4_addr_add(iface, &ipv4_loopback, NET_ADDR_AUTOCONF, 0); if (!ifaddr) { LOG_ERR("Failed to register IPv4 loopback address"); } + + net_if_ipv4_set_netmask(iface, &netmask); } if (IS_ENABLED(CONFIG_NET_IPV6)) { diff --git a/drivers/net/ppp.c b/drivers/net/ppp.c index c8d06fa146b..ecfdb7c3af1 100644 --- a/drivers/net/ppp.c +++ b/drivers/net/ppp.c @@ -31,7 +31,7 @@ LOG_MODULE_REGISTER(net_ppp, LOG_LEVEL); #include #include #include -#include +#include #include "../../subsys/net/ip/net_stats.h" #include "../../subsys/net/ip/net_private.h" diff --git a/drivers/net/slip.c b/drivers/net/slip.c index ba9bdd27d69..cf1fef83041 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -28,7 +28,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #include #include #include -#include +#include #include "slip.h" diff --git a/drivers/neural_net/CMakeLists.txt b/drivers/neural_net/CMakeLists.txt deleted file mode 100644 index 4ce3c7f3e26..00000000000 --- a/drivers/neural_net/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library() - -zephyr_library_sources_ifdef(CONFIG_INTEL_GNA intel_gna.c) diff --git a/drivers/neural_net/Kconfig b/drivers/neural_net/Kconfig deleted file mode 100644 index 001893744d7..00000000000 --- a/drivers/neural_net/Kconfig +++ /dev/null @@ -1,19 +0,0 @@ -# Neural network accelerator driver configuration options - -# Copyright (c) 2018 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -menuconfig NEURAL_NET_ACCEL - bool "Neural Network Accelerator drivers" - help - Enable support for Neural Network Accelerators - -if NEURAL_NET_ACCEL - -module = NEURAL_NET -module-str = neural_net -source "subsys/logging/Kconfig.template.log_config" - -source "drivers/neural_net/Kconfig.*" - -endif # NEURAL_NET diff --git a/drivers/neural_net/Kconfig.intel_gna b/drivers/neural_net/Kconfig.intel_gna deleted file mode 100644 index 55ddd68f1ff..00000000000 --- a/drivers/neural_net/Kconfig.intel_gna +++ /dev/null @@ -1,43 +0,0 @@ -# Neural network accelerator driver configuration options - -# Copyright (c) 2018 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -menuconfig INTEL_GNA - bool "Intel GNA Inferencing Engine" - help - Enable support for Intel's GMM and Neural Network Accelerator - -if INTEL_GNA - -config INTEL_GNA_INIT_PRIORITY - int "Init priority" - default 99 - help - Device driver initialization priority. - -config INTEL_GNA_MAX_MODELS - int "Max number of neural network models supported by driver" - default 4 - help - Max. number of unique neural network models required in the system - -config INTEL_GNA_MAX_PENDING_REQUESTS - int "Max number of pending inference requests" - default 4 - help - Maximum number of pending inference requests in the driver - -config INTEL_GNA_POWER_MODE - int "GNA operation mode" - default 0 - range 0 3 - help - Sets GNA operation mode for power saving - Levels are: - 0 ALWAYS_ON, GNA is always on with very minimal power save - 1 CLOCK_GATED, GNA clock is gated when not active - 2 POWER_GATED, GNA clock and power are gated when not active - 3 ALWAYS_OFF, GNA is tuned off and never used in the system - -endif # INTEL_GNA diff --git a/drivers/neural_net/intel_gna.c b/drivers/neural_net/intel_gna.c deleted file mode 100644 index a7b61a3554d..00000000000 --- a/drivers/neural_net/intel_gna.c +++ /dev/null @@ -1,526 +0,0 @@ -/* - * Copyright (c) 2018 Intel Corporation - * - * Author: Sathish Kuttan - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** @file - * @brief Intel GNA device driver - * - * Device driver implementation for Intel's - * Gaussian Mixture Model and Neural Network Accelerator (GNA) - */ - -#define DT_DRV_COMPAT intel_gna - -#include -#include -#include -#include - -#include -#include "intel_gna.h" - -#define LOG_LEVEL CONFIG_NEURAL_NET_LOG_LEVEL -#include -#include -LOG_MODULE_REGISTER(neural_net); - -#if LOG_LEVEL >= LOG_LEVEL_DBG -static void intel_gna_regs_dump(const struct device *dev); -static void intel_gna_config_desc_dump(const struct device *dev); -#define INTEL_GNA_REGS_DUMP(dev) intel_gna_regs_dump((dev)) -#define INTEL_GNA_CONFIG_DESC_DUMP(dev) intel_gna_config_desc_dump((dev)) -#else -#define INTEL_GNA_REGS_DUMP(dev) -#define INTEL_GNA_CONFIG_DESC_DUMP(dev) -#endif - -#define GNA_MODEL_VIRT_BASE_DEFAULT 0 - -DEVICE_DECLARE(gna); -static struct intel_gna_config_desc __aligned(GNA_PG_SIZE_IN_BYTES) - gna_config_desc; -static struct intel_gna_page_table __aligned(GNA_PG_SIZE_IN_BYTES) - gna_page_table[GNA_NUM_PG_TABLES_NEEDED]; - -static void intel_gna_interrupt_handler(const struct device *dev) -{ - struct intel_gna_data *const gna = dev->data; - - volatile struct intel_gna_regs *regs = gna->regs; - struct intel_gna_pending_resp pending_resp; - struct intel_gna_pending_req pending_req; - - /* check for generic / virtual address out of range error */ - if (regs->gnasts & (GNA_STS_VIRT_ADDR_OOR | GNA_STS_ERROR)) { - pending_resp.response.result = GNA_RESULT_GENERIC_ERROR; - } - - /* check for parameter out of range error */ - if (regs->gnasts & GNA_STS_PARAM_OOR) { - pending_resp.response.result = - GNA_RESULT_PARAM_OUT_OF_RANGE_ERROR; - } - - /* check for output buffer full error */ - if (regs->gnasts & GNA_STS_BUFFER_FULL) { - pending_resp.response.result = - GNA_RESULT_OUTPUT_BUFFER_FULL_ERROR; - } - - /* check for scoring completion out of range error */ - if (regs->gnasts & GNA_STS_SCORE_COMPL) { - pending_resp.response.result = GNA_RESULT_INFERENCE_COMPLETE; - } - - if (k_msgq_get(&gna->request_queue, &pending_req, K_NO_WAIT) != 0) { - LOG_ERR("Pending request queue is empty"); - } else { - sys_cache_data_invd_range(pending_req.model->output, - pending_req.output_len); - /* copy output from the model buffer to application buffer */ - memcpy(pending_req.output, pending_req.model->output, - pending_req.output_len); - pending_resp.response.output = pending_req.output; - pending_resp.response.output_len = pending_req.output_len; - pending_resp.callback = pending_req.callback; - - pending_resp.response.stats.cycles_per_sec = 200000000U; - if (regs->gnasts & GNA_STS_STATS_VALID) { - pending_resp.response.stats.total_cycles = regs->gnaptc; - pending_resp.response.stats.stall_cycles = regs->gnasc; - } else { - pending_resp.response.stats.total_cycles = 0U; - pending_resp.response.stats.stall_cycles = 0U; - } - - k_msgq_put(&gna->response_queue, &pending_resp, K_NO_WAIT); - - k_work_submit(&gna->gna_work); - } - - /* clear GNA operation and disable interrupt */ - regs->gnactrl |= GNA_CTRL_INTR_DISABLE | GNA_CTRL_ABORT_CLEAR; - gna->state = GNA_STATE_IDLE; -} - -static void gna_work_handler(struct k_work *work) -{ - struct intel_gna_data *gna = (struct intel_gna_data *)work; - struct intel_gna_pending_resp resp; - - while (k_msgq_get(&gna->response_queue, &resp, K_NO_WAIT) == 0) { - resp.callback(&resp.response); - } -} - -static int intel_gna_setup_page_table(void *physical, size_t size, - void *virtual) -{ - uint32_t page; - uint32_t dir_index; - uint32_t table_index; - uint32_t virt_addr = (uint32_t)virtual; - uint32_t phys_addr = (uint32_t)physical; - - LOG_DBG("physical %p size %u virtual %p", physical, size, virtual); - - if (((phys_addr + size - L2_SRAM_BASE) > L2_SRAM_SIZE) || - (phys_addr < L2_SRAM_BASE)) { - LOG_ERR("model at %p of size %u exceeds L2 SRAM space", - physical, size); - return -EINVAL; - } - - dir_index = GNA_VA_PG_DIR(virtual); - table_index = GNA_VA_PG_TABLE(virtual); - - if (dir_index >= GNA_NUM_PG_TABLES_NEEDED) { - LOG_ERR("virtual addr %p is in page dir %u (max %u)", - virtual, dir_index, - (uint32_t)GNA_NUM_PG_TABLES_NEEDED); - return -EINVAL; - } - - for (page = 0U; page < GNA_NUM_PAGES(size); page++) { - dir_index = GNA_VA_PG_DIR(virt_addr); - table_index = GNA_VA_PG_TABLE(virt_addr); - gna_page_table[dir_index].entry[table_index] = - GNA_PG_TABLE_ENTRY(phys_addr); - - LOG_DBG("di %u tb %u @ %p va %08x pa %08x ent %08x", - dir_index, table_index, - &gna_page_table[dir_index].entry[table_index], - virt_addr, phys_addr, - gna_page_table[dir_index].entry[table_index]); - phys_addr += GNA_PG_SIZE_IN_BYTES; - virt_addr += GNA_PG_SIZE_IN_BYTES; - } - - return 0; -} - -static int intel_gna_initialize(const struct device *dev) -{ - struct intel_gna_data *const gna = dev->data; - uint32_t page_dir_entry; - - k_msgq_init(&gna->request_queue, (char *)gna->requests, - sizeof(struct intel_gna_pending_req), - GNA_REQUEST_QUEUE_LEN); - - k_msgq_init(&gna->response_queue, (char *)gna->responses, - sizeof(struct intel_gna_pending_resp), - GNA_REQUEST_QUEUE_LEN); - - k_mem_slab_init(&gna->model_slab, (char *)gna->models, - sizeof(struct intel_gna_model), GNA_MAX_NUM_MODELS); - - k_work_init(&gna->gna_work, gna_work_handler); - - /* initialize the configuration descriptor's page directory table */ - for (int page = 0; page < GNA_CONFIG_DESC_PG_DIR_SIZE; page++) { - page_dir_entry = (page < GNA_NUM_PG_TABLES_NEEDED) ? - GNA_PG_DIR_ENTRY(&gna_page_table[page]) : (uint32_t)-1; - gna_config_desc.pagedir[page] = page_dir_entry; - LOG_DBG("%s: page %u pagetable %08x", - dev->name, page, gna_config_desc.pagedir[page]); - } - gna_config_desc.vamaxaddr = GNA_ADDRESSABLE_MEM_SIZE; - LOG_DBG("%s: max virtual address %08x", - dev->name, gna_config_desc.vamaxaddr); - - /* flush cache */ - sys_cache_data_flush_range((void *)&gna_config_desc, sizeof(gna_config_desc)); - - LOG_INF("%s: initialized (max %u models & max %u pending requests)", - dev->name, GNA_MAX_NUM_MODELS, - GNA_REQUEST_QUEUE_LEN); - LOG_INF("%s: max addressable memory %u MB", - dev->name, GNA_ADDRESSABLE_MEM_SIZE >> 20); - LOG_INF("%s: %u page table(s) at %p and %u bytes", - dev->name, (uint32_t)GNA_NUM_PG_TABLES_NEEDED, - gna_page_table, sizeof(gna_page_table)); - LOG_INF("%s: configuration descriptor at %p", - dev->name, &gna_config_desc); - - /* register interrupt handler */ - IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), - intel_gna_interrupt_handler, DEVICE_GET(gna), 0); - /* enable interrupt */ - irq_enable(INTEL_GNA_IRQ_ID); - - gna->state = GNA_STATE_INITIALIZED; - return 0; -} - -static int intel_gna_configure(const struct device *dev, - struct gna_config *cfg) -{ - struct intel_gna_data *const gna = dev->data; - volatile struct intel_gna_regs *regs = gna->regs; - - if (gna->state != GNA_STATE_INITIALIZED) { - LOG_ERR("Configuration attempt in invalid state (%u)", - gna->state); - return -EINVAL; - } - - if (cfg == NULL) { - LOG_ERR("Config pointer is NULL"); - return -EINVAL; - } - - gna->config = *cfg; - - regs->gnactrl |= GNA_CTRL_OPER_MODEL_XNN | - GNA_CTRL_ERR_INTR_ENABLE | GNA_CTRL_COMPL_INTR_ENABLE; - - switch (CONFIG_INTEL_GNA_POWER_MODE) { - case GNA_POWER_MODE_ALWAYS_ON: - regs->gnactrl |= GNA_CTRL_PM_OVRIDE_CLK_ON | - GNA_CTRL_PM_OVRIDE_PWR_ON; - break; - - case GNA_POWER_MODE_CLOCK_GATED: - regs->gnactrl |= GNA_CTRL_PM_OVRIDE_PWR_ON; - break; - - case GNA_POWER_MODE_POWER_GATED: - case GNA_POWER_MODE_ALWAYS_OFF: - break; - - default: - LOG_ERR("Invalid config CONFIG_INTEL_GNA_POWER_MODE (%u)", - CONFIG_INTEL_GNA_POWER_MODE); - break; - } - - /* assign the configuration descriptor address as the base */ - regs->gnadesbase = GNA_PHYS_ADDR_TO_PAGE(&gna_config_desc); - - INTEL_GNA_CONFIG_DESC_DUMP(dev); - - LOG_INF("Device %s (version %u.%u) configured with power mode %u", - dev->name, regs->gnaversion >> 1, - (uint32_t)(regs->gnaversion & BIT(0)), - CONFIG_INTEL_GNA_POWER_MODE); - - gna->state = GNA_STATE_IDLE; - return 0; -} - -static int intel_gna_register_model(const struct device *dev, - struct gna_model_info *model, - void **model_handle) -{ - struct intel_gna_data *const gna = dev->data; - struct intel_gna_model *gna_model; - struct gna_model_header *header; - uint32_t ro_size, rw_size = 0; - void *virtual_base; - void *ro_region; - - if ((gna->state != GNA_STATE_IDLE) && - (gna->state != GNA_STATE_ACTIVE)) { - LOG_ERR("Invalid state (%u)", gna->state); - return -EINVAL; - } - - if ((model_handle == NULL) || (model == NULL)) { - LOG_ERR("model and/or model_handle is NULL"); - return -EINVAL; - } - - if ((model->header == NULL) || (model->rw_region == NULL)) { - LOG_ERR("model header / rw_region is/are NULL"); - return -EINVAL; - } - - /* check for 64B alignment */ - if (((uint32_t)model->rw_region & BIT_MASK(6)) || - ((uint32_t)model->ro_region & BIT_MASK(6))) { - LOG_ERR("rw_region / ro_region not aligned to 64B"); - return -EINVAL; - } - - if (k_mem_slab_alloc(&gna->model_slab, (void **)&gna_model, - K_NO_WAIT)) { - LOG_ERR("No memory to register model"); - return -ENOMEM; - } - - LOG_INF("model header: %p rw: %p ro: %p", model->header, - model->rw_region, model->ro_region); - - header = model->header; - virtual_base = (void *)GNA_MODEL_VIRT_BASE_DEFAULT; - - LOG_INF("model_size: %u rw_region_size: %u", header->model_size, - header->rw_region_size); - - /* setup page table entries for RW region */ - if (model->rw_region && header->rw_region_size) { - /* calculate layer descriptor size */ - rw_size = header->layer_count * - sizeof(struct intel_gna_layer_desc); - /* round up to page boundary */ - rw_size = GNA_PAGES_TO_BYTES(GNA_NUM_PAGES(rw_size)); - /* add the input rw_region_size to get total rw_region_size */ - rw_size += header->rw_region_size; - - intel_gna_setup_page_table(model->rw_region, rw_size, - virtual_base); - sys_cache_data_flush_range(model->rw_region, rw_size); - } - - if (model->ro_region == NULL) { - ro_region = (void *)((uint32_t)model->rw_region + rw_size); - } else { - ro_region = model->ro_region; - } - - ro_size = header->model_size - rw_size; - - LOG_INF("rw_region: %p (%u) ro_region: %p (%u)", - model->rw_region, rw_size, ro_region, ro_size); - - /* setup page table entries for RO region */ - intel_gna_setup_page_table(ro_region, ro_size, - (void *)((uint32_t)virtual_base + rw_size)); - - sys_cache_data_flush_range(ro_region, ro_size); - sys_cache_data_flush_range(gna_page_table, sizeof(gna_page_table)); - - /* copy the model pointers */ - gna_model->model = *model; - gna_model->vabase = virtual_base; - gna_model->input = (void *)((uint32_t)model->rw_region + - *(uint32_t *)((uint32_t)model->rw_region + - header->input_ptr_offset)); - gna_model->output = (void *)((uint32_t)model->rw_region + - *(uint32_t *)((uint32_t)model->rw_region + - header->output_ptr_offset)); - gna_model->registered = true; - - LOG_INF("model->rw_region: %p", model->rw_region); - LOG_INF("input offset: %u", - *(uint32_t *)((uint32_t)model->rw_region + header->input_ptr_offset)); - LOG_INF("gna_model->input: %p", gna_model->input); - LOG_INF("output offset: %u", - *(uint32_t *)((uint32_t)model->rw_region + - header->output_ptr_offset)); - LOG_INF("gna_model->output: %p", gna_model->output); - LOG_DBG("returning model handle: %p", gna_model); - *model_handle = (void *)gna_model; - return 0; -} - -static int intel_gna_deregister_model(const struct device *dev, - void *model_handle) -{ - struct intel_gna_data *const gna = dev->data; - struct intel_gna_model *gna_model; - - if (model_handle == NULL) { - LOG_ERR("model_handle is NULL"); - return -EINVAL; - } - - gna_model = (struct intel_gna_model *)model_handle; - gna_model->registered = false; - k_mem_slab_free(&gna->model_slab, model_handle); - - return 0; -} - -static int intel_gna_infer(const struct device *dev, - struct gna_inference_req *req, - gna_callback callback) -{ - struct intel_gna_data *const gna = dev->data; - volatile struct intel_gna_regs *regs = gna->regs; - struct intel_gna_pending_req pending_req; - struct gna_model_header *header; - struct intel_gna_model *handle; - struct gna_model_info *model; - size_t input_size; - int ret; - - LOG_DBG("device %p", dev); - if (req == NULL) { - LOG_ERR("Invalid request pointer"); - return -EINVAL; - } - - if (callback == NULL) { - LOG_ERR("Invalid callback function pointer"); - return -EINVAL; - } - - handle = (struct intel_gna_model *)req->model_handle; - - if (handle->registered != true) { - LOG_ERR("Model is not registered. Handle %p", handle); - return -EINVAL; - } - - if (req->input == NULL) { - LOG_ERR("Invalid input buffer"); - return -EINVAL; - } - - if (req->output == NULL) { - LOG_ERR("Invalid output buffer"); - return -EINVAL; - } - - model = &handle->model; - header = model->header; - input_size = header->bytes_per_input * header->num_input_nodes; - - pending_req.model = handle; - pending_req.output = req->output; - pending_req.output_len = header->bytes_per_output * - header->num_output_nodes; - pending_req.callback = callback; - - ret = k_msgq_put(&gna->request_queue, &pending_req, K_NO_WAIT); - if (ret) { - LOG_ERR("Unable to queue request (code %d)", ret); - return ret; - } - - if (gna->state != GNA_STATE_IDLE) { - /* multiple pending requests are not yet supported */ - return -EBUSY; - } - - /* copy input */ - memcpy(handle->input, req->input, input_size); - sys_cache_data_flush_range(handle->input, input_size); - - /* assign layer descriptor base address to configuration descriptor */ - gna_config_desc.labase = (uint32_t)handle->vabase; - gna_config_desc.lacnt = (uint16_t)header->layer_count; - sys_cache_data_flush_range(&gna_config_desc, sizeof(gna_config_desc)); - - gna->state = GNA_STATE_ACTIVE; - regs->gnactrl = (regs->gnactrl & ~GNA_CTRL_INTR_DISABLE) | - GNA_CTRL_ACCEL_START | GNA_CTRL_STATS_ENABLE_STALL; - - return 0; -} - -#if LOG_LEVEL >= LOG_LEVEL_DBG -static void intel_gna_regs_dump(const struct device *dev) -{ - struct intel_gna_data *const gna = dev->data; - volatile struct intel_gna_regs *regs = gna->regs; - - LOG_DBG("gnasts :%08x", regs->gnasts); - LOG_DBG("gnactrl :%08x", regs->gnactrl); - LOG_DBG("gnamctl :%08x", regs->gnamctl); - LOG_DBG("gnaptc :%08x", regs->gnaptc); - LOG_DBG("gnasc :%08x", regs->gnasc); - LOG_DBG("gnaisi :%08x", regs->gnaisi); - LOG_DBG("gnais_low :%08x", regs->gnais_low); - LOG_DBG("gnais_high :%08x", regs->gnais_high); - LOG_DBG("gnabp_low :%08x", regs->gnabp_low); - LOG_DBG("gnabp_high :%08x", regs->gnabp_high); - LOG_DBG("gnadesbase :%08x", regs->gnadesbase); - LOG_DBG("gnaibuffs :%08x", regs->gnaibuffs); - LOG_DBG("ovrcfgctl :%08x", regs->gnaibuffs); - LOG_DBG("gnaversion :%08x", regs->gnaversion); -} - -static void intel_gna_config_desc_dump(const struct device *dev) -{ - struct intel_gna_data *const gna = dev->data; - volatile struct intel_gna_regs *regs = gna->regs; - - LOG_DBG("gnadesbase :%08x", regs->gnadesbase); - LOG_DBG("labase :%08x", gna_config_desc.labase); - LOG_DBG("lacnt :%u", gna_config_desc.lacnt); -} -#endif - -static const struct gna_driver_api gna_driver_api = { - .configure = intel_gna_configure, - .register_model = intel_gna_register_model, - .deregister_model = intel_gna_deregister_model, - .infer = intel_gna_infer, -}; - -static struct intel_gna_data intel_gna_driver_data = { - .regs = (volatile struct intel_gna_regs *)DT_INST_REG_ADDR(0), -}; - -DEVICE_DT_INST_DEFINE(0, intel_gna_initialize, - NULL, - (void *)&intel_gna_driver_data, NULL, - POST_KERNEL, CONFIG_INTEL_GNA_INIT_PRIORITY, - &gna_driver_api); diff --git a/drivers/neural_net/intel_gna.h b/drivers/neural_net/intel_gna.h deleted file mode 100644 index 9b1905ecd88..00000000000 --- a/drivers/neural_net/intel_gna.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (c) 2018 Intel Corporation - * - * Author: Sathish Kuttan - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** @file - * @brief Intel GNA device driver - * - * Device driver implementation for Intel's - * Gaussian Mixture Model and Neural Network Accelerator (GNA) - */ - -#ifndef __INTEL_GNA__ -#define __INTEL_GNA__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* number of requests that could be pending in driver */ -#define GNA_REQUEST_QUEUE_LEN CONFIG_INTEL_GNA_MAX_PENDING_REQUESTS -#define GNA_MAX_NUM_MODELS CONFIG_INTEL_GNA_MAX_MODELS - -/* values must match config values in Kconfig.intel_gna */ -#define GNA_POWER_MODE_ALWAYS_ON 0 -#define GNA_POWER_MODE_CLOCK_GATED 1 -#define GNA_POWER_MODE_POWER_GATED 2 -#define GNA_POWER_MODE_ALWAYS_OFF 3 - -#define INTEL_GNA_BASE_ADDR 0x0000E800 - -#define INTEL_GNA_IRQ_ID 0x00000506 -#define INTEL_GNA_IRQ_PRIORITY 3 - -#define GNA_STS_INTR_PENDING BIT(31) -#define GNA_STS_SATURATION_OCCURRED BIT(17) -#define GNA_STS_BUFFER_FULL BIT(16) -#define GNA_STS_ERROR BIT(15) -#define GNA_STS_PARAM_OOR BIT(8) -#define GNA_STS_VIRT_ADDR_OOR BIT(7) -#define GNA_STS_STATS_VALID BIT(3) -#define GNA_STS_SUSP_PAUSE BIT(2) -#define GNA_STS_SUSP_BREAKP BIT(1) -#define GNA_STS_SCORE_COMPL BIT(0) - -#define GNA_CTRL_INTR_DISABLE BIT(31) -#define GNA_CTRL_PM_IDLE_DISABLE BIT(18) -#define GNA_CTRL_PM_OVRIDE_CLK_ON BIT(17) -#define GNA_CTRL_PM_OVRIDE_PWR_ON BIT(16) -#define GNA_CTRL_STATS_ENABLE_STALL (1 << 12) -#define GNA_CTRL_STATS_MASK (BIT_MASK(4) << 12) -#define GNA_CTRL_ERR_INTR_ENABLE (1 << 10) -#define GNA_CTRL_COMPL_INTR_ENABLE (1 << 8) -#define GNA_CTRL_OPER_MODEL_XNN (1 << 5) -#define GNA_CTRL_ABORT_CLEAR (1 << 2) -#define GNA_CTRL_ACCEL_START (1 << 0) -#define GNA_CTRL_ACCEL_BUSY GNA_CTRL_ACCEL_START - -#define GNA_CONFIG_DESC_PG_DIR_SIZE 64 - -#define GNA_LAYER_DESC_ALIGN (128) - -#define GNA_ADDRESSABLE_MEM_SIZE L2_SRAM_SIZE -#define GNA_NUM_PG_TABLE_INDEX_BITS 10 -#define GNA_NUM_PG_TABLE_ENTRIES BIT(GNA_NUM_PG_TABLE_INDEX_BITS) -#define GNA_PG_SIZE_IN_BITSHIFT 12 -#define GNA_PG_SIZE_IN_BYTES BIT(GNA_PG_SIZE_IN_BITSHIFT) - -#define GNA_SHIFT_RNDUP(value, shift) (((value) + BIT_MASK(shift)) >> (shift)) - -#define GNA_NUM_PAGES(bytes) \ - GNA_SHIFT_RNDUP((bytes), GNA_PG_SIZE_IN_BITSHIFT) - -#define GNA_PAGES_TO_BYTES(pages) ((pages) << GNA_PG_SIZE_IN_BITSHIFT) - -#define GNA_MAX_NUM_PAGES GNA_NUM_PAGES(GNA_ADDRESSABLE_MEM_SIZE) - -#define GNA_NUM_PG_TABLES_NEEDED \ - GNA_SHIFT_RNDUP(GNA_MAX_NUM_PAGES, GNA_NUM_PG_TABLE_INDEX_BITS) - -#if GNA_NUM_PG_TABLES_NEEDED > GNA_CONFIG_DESC_PG_DIR_SIZE -#error GNA_NUM_PG_TABLES_NEEDED exceeds GNA_CONFIG_DESC_PG_DIR_SIZE -#endif - -#define GNA_GET_BITS(val, b_hi, b_lo) ((((uint32_t)(val)) << (31 - (b_hi))) >> \ - (31 - (b_hi) + (b_lo))) - -#define GNA_VA_PG_DIR(virt_addr) GNA_GET_BITS(virt_addr, 27, 22) -#define GNA_VA_PG_TABLE(virt_addr) GNA_GET_BITS(virt_addr, 21, 12) - -#define GNA_PHYS_ADDR_TO_PAGE(addr) ((uint32_t)(addr) >> \ - GNA_PG_SIZE_IN_BITSHIFT) -#define GNA_PG_DIR_ENTRY(phys_addr) GNA_PHYS_ADDR_TO_PAGE(phys_addr) -#define GNA_PG_BASE(addr) ((uint32_t)(addr) & \ - ~BIT_MASK(GNA_PG_SIZE_IN_BITSHIFT)) -#define GNA_PG_OFFSET(addr) ((uint32_t)(addr) & \ - BIT_MASK(GNA_PG_SIZE_IN_BITSHIFT)) -#define GNA_PG_TABLE_ENTRY(phys_addr) GNA_PHYS_ADDR_TO_PAGE(phys_addr) - -struct intel_gna_regs { - uint32_t gnasts; - uint32_t gnactrl; - uint32_t gnamctl; - uint32_t gnaptc; - uint32_t gnasc; - uint32_t gnaisi; - uint32_t gnais_low; - uint32_t gnais_high; - uint32_t gnabp_low; - uint32_t gnabp_high; - uint32_t reserved1[2]; - uint32_t gnadesbase; - uint32_t gnaibuffs; - uint32_t reserved2[2]; - uint32_t ovrcfgctl; - uint32_t reserved3[3]; - uint32_t gnaversion; -}; - -struct intel_gna_config_desc { - uint32_t reserved1[64]; - uint32_t labase; /* layer array base */ - uint16_t lacnt; /* layer array count */ - uint16_t reserved2; - uint32_t reserved3[62]; - uint32_t vamaxaddr; /* virtual address max address */ - uint32_t reserved4[3]; - /* page directory entries */ - uint32_t pagedir[GNA_CONFIG_DESC_PG_DIR_SIZE]; -} __packed; - -struct intel_gna_page_table { - uint32_t entry[GNA_NUM_PG_TABLE_ENTRIES]; -} __aligned(GNA_PG_SIZE_IN_BYTES); - -struct intel_gna_layer_desc { - uint32_t gna_words[8]; - uint32_t inarrayptr; - uint32_t outarrayactptr; - uint32_t outarraysumptr; - uint32_t outfbarrayactptr; - uint32_t wtfltarrayptr; - uint32_t constarrayptr; - uint32_t actoutputslistptr; - uint32_t actfuncsectdefptr; - uint32_t reserved[16]; -} __packed __aligned(GNA_LAYER_DESC_ALIGN); - -struct intel_gna_config { - struct gna_config config; -}; - -struct intel_gna_model { - struct gna_model_info model; - void *input; - void *output; - void *vabase; - bool registered; -}; - -struct intel_gna_pending_req { - struct intel_gna_model *model; - void *output; - size_t output_len; - gna_callback callback; -}; - -struct intel_gna_pending_resp { - struct gna_inference_resp response; - gna_callback callback; -}; - -enum gna_state { - GNA_STATE_UNINITIALIZED, - GNA_STATE_INITIALIZED, - GNA_STATE_IDLE, - GNA_STATE_ACTIVE, -}; - -struct intel_gna_data { - /* - * gna_cb_work must be the first element in the structure - * since it will be typecast as intel_gna_data in the work handler - */ - struct k_work gna_work; - volatile struct intel_gna_regs *regs; - struct k_mem_slab model_slab; - struct intel_gna_model models[GNA_MAX_NUM_MODELS]; - struct k_msgq request_queue; - struct intel_gna_pending_req requests[GNA_REQUEST_QUEUE_LEN]; - struct k_msgq response_queue; - struct intel_gna_pending_resp responses[GNA_REQUEST_QUEUE_LEN]; - enum gna_state state; - - struct gna_config config; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* __INTEL_GNA__ */ diff --git a/drivers/pcie/host/Kconfig b/drivers/pcie/host/Kconfig index 80925657702..515ef89ce28 100644 --- a/drivers/pcie/host/Kconfig +++ b/drivers/pcie/host/Kconfig @@ -73,9 +73,15 @@ config PCIE_PTM This will enable support both PTM root and PTM requester features. Up to the PCIe device driver to enable its PTM requester capability. +config PCIE_PRT + bool "Support for IRQ information retrieve via ACPI PRT (PCI Routing Table)" + default y if ACPI_DSDT_SUPPORT + help + This will enable retrieve interrupt routing information for PCI legacy + interrupt via ACPI PRT (PCI Routing Table) + config PCIE_SHELL bool "PCIe/new PCI Shell" - default y depends on SHELL help Enable commands for debugging PCI(e) using the built-in shell. diff --git a/drivers/pcie/host/msi.c b/drivers/pcie/host/msi.c index fc04fdccfa1..f78f5b171a6 100644 --- a/drivers/pcie/host/msi.c +++ b/drivers/pcie/host/msi.c @@ -38,7 +38,7 @@ static uint32_t pcie_msi_base(pcie_bdf_t bdf, bool *msi) #ifdef CONFIG_PCIE_MSI_MULTI_VECTOR -#include +#include __weak uint8_t arch_pcie_msi_vectors_allocate(unsigned int priority, msi_vector_t *vectors, diff --git a/drivers/pcie/host/pcie.c b/drivers/pcie/host/pcie.c index 1d6c1678094..a4d9fdbe504 100644 --- a/drivers/pcie/host/pcie.c +++ b/drivers/pcie/host/pcie.c @@ -291,7 +291,7 @@ unsigned int pcie_alloc_irq(pcie_bdf_t bdf) irq >= CONFIG_MAX_IRQ_LINES || arch_irq_is_used(irq)) { -#ifdef CONFIG_ACPI +#ifdef CONFIG_PCIE_PRT irq = acpi_legacy_irq_get(bdf); #else irq = arch_irq_allocate(); diff --git a/drivers/peci/peci_handlers.c b/drivers/peci/peci_handlers.c index 39147019d1c..64947a8743d 100644 --- a/drivers/peci/peci_handlers.c +++ b/drivers/peci/peci_handlers.c @@ -5,13 +5,13 @@ */ #include -#include +#include static inline int z_vrfy_peci_config(const struct device *dev, uint32_t bitrate) { - Z_OOPS(Z_SYSCALL_DRIVER_PECI(dev, config)); + K_OOPS(K_SYSCALL_DRIVER_PECI(dev, config)); return z_impl_peci_config(dev, bitrate); } @@ -19,7 +19,7 @@ static inline int z_vrfy_peci_config(const struct device *dev, static inline int z_vrfy_peci_enable(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_PECI(dev, enable)); + K_OOPS(K_SYSCALL_DRIVER_PECI(dev, enable)); return z_impl_peci_enable(dev); } @@ -27,7 +27,7 @@ static inline int z_vrfy_peci_enable(const struct device *dev) static inline int z_vrfy_peci_disable(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_PECI(dev, disable)); + K_OOPS(K_SYSCALL_DRIVER_PECI(dev, disable)); return z_impl_peci_disable(dev); } @@ -38,8 +38,8 @@ static inline int z_vrfy_peci_transfer(const struct device *dev, { struct peci_msg msg_copy; - Z_OOPS(Z_SYSCALL_DRIVER_PECI(dev, transfer)); - Z_OOPS(z_user_from_copy(&msg_copy, msg, sizeof(*msg))); + K_OOPS(K_SYSCALL_DRIVER_PECI(dev, transfer)); + K_OOPS(k_usermode_from_copy(&msg_copy, msg, sizeof(*msg))); return z_impl_peci_transfer(dev, &msg_copy); } diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index c46cf3691f7..9455b6e7c78 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -35,3 +35,6 @@ zephyr_library_sources_ifdef(CONFIG_PINCTRL_EMSDP pinctrl_emsdp.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_TI_CC32XX pinctrl_ti_cc32xx.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_NUMAKER pinctrl_numaker.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_QUICKLOGIC_EOS_S3 pinctrl_eos_s3.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_RA pinctrl_ra.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_IMX_SCU pinctrl_imx_scu.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_RZT2M pinctrl_rzt2m.c) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 164cbd11089..8a165725e4d 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -64,5 +64,7 @@ source "drivers/pinctrl/Kconfig.emsdp" source "drivers/pinctrl/Kconfig.ti_cc32xx" source "drivers/pinctrl/Kconfig.numaker" source "drivers/pinctrl/Kconfig.eos_s3" +source "drivers/pinctrl/Kconfig.ra" +source "drivers/pinctrl/Kconfig.rzt2m" endif # PINCTRL diff --git a/drivers/pinctrl/Kconfig.imx b/drivers/pinctrl/Kconfig.imx index b31a90e7291..506f5b30016 100644 --- a/drivers/pinctrl/Kconfig.imx +++ b/drivers/pinctrl/Kconfig.imx @@ -7,6 +7,13 @@ config PINCTRL_IMX help Enable pin controller driver for NXP iMX series MCUs +config PINCTRL_IMX_SCU + bool "Pin controller driver for SCU-based i.MX SoCs" + depends on DT_HAS_NXP_IMX_IOMUXC_SCU_ENABLED + default y + help + Enable pin controller driver for SCU-based NXP i.MX SoCs. + # TODO: Find better place for this option config MCUX_XBARA bool "MCUX XBARA driver" diff --git a/drivers/pinctrl/Kconfig.ra b/drivers/pinctrl/Kconfig.ra new file mode 100644 index 00000000000..6ad0ebd8c06 --- /dev/null +++ b/drivers/pinctrl/Kconfig.ra @@ -0,0 +1,9 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +config PINCTRL_RA + bool "Renesas RA series pin controller driver" + default y + depends on DT_HAS_RENESAS_RA_PINCTRL_ENABLED + help + Enable Renesas RA series pin controller driver. diff --git a/drivers/pinctrl/Kconfig.rzt2m b/drivers/pinctrl/Kconfig.rzt2m new file mode 100644 index 00000000000..236afdcf55e --- /dev/null +++ b/drivers/pinctrl/Kconfig.rzt2m @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +config PINCTRL_RZT2M + bool "Renesas RZ/T2M pin controller driver" + default y + depends on DT_HAS_RENESAS_RZT2M_PINCTRL_ENABLED + help + Renesas RZ/T2M pinctrl driver diff --git a/drivers/pinctrl/pinctrl_gecko.c b/drivers/pinctrl/pinctrl_gecko.c index 2aede54a325..cdb1118768f 100644 --- a/drivers/pinctrl/pinctrl_gecko.c +++ b/drivers/pinctrl/pinctrl_gecko.c @@ -249,6 +249,8 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintp GPIO->USARTROUTE[usart_num].CLKROUTE = (pin_config.pin << _GPIO_USART_CLKROUTE_PIN_SHIFT) | (pin_config.port << _GPIO_USART_CLKROUTE_PORT_SHIFT); + GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode, + pin_config.out); break; case GECKO_FUN_SPI_MOSI: @@ -258,6 +260,8 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintp GPIO->USARTROUTE[usart_num].TXROUTE = (pin_config.pin << _GPIO_USART_TXROUTE_PIN_SHIFT) | (pin_config.port << _GPIO_USART_TXROUTE_PORT_SHIFT); + GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode, + pin_config.out); break; case GECKO_FUN_SPI_MISO: @@ -267,6 +271,8 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintp GPIO->USARTROUTE[usart_num].RXROUTE = (pin_config.pin << _GPIO_USART_RXROUTE_PIN_SHIFT) | (pin_config.port << _GPIO_USART_RXROUTE_PORT_SHIFT); + GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode, + pin_config.out); break; #endif /* CONFIG_SOC_GECKO_SERIES1 */ #endif /* CONFIG_SPI_GECKO */ @@ -274,10 +280,6 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintp default: return -ENOTSUP; } -#if defined(CONFIG_SPI_GECKO) && !defined(CONFIG_SOC_GECKO_SERIES1) - GPIO_PinModeSet(pin_config.port, pin_config.pin, - pin_config.mode, pin_config.out); -#endif /* defined(CONFIG_SPI_GECKO) && !defined(CONFIG_SOC_GECKO_SERIES1) */ } return 0; diff --git a/drivers/pinctrl/pinctrl_ifx_cat1.c b/drivers/pinctrl/pinctrl_ifx_cat1.c index 8f2bbcb0e43..dbeaab855f3 100644 --- a/drivers/pinctrl/pinctrl_ifx_cat1.c +++ b/drivers/pinctrl/pinctrl_ifx_cat1.c @@ -52,41 +52,44 @@ static uint32_t soc_gpio_get_drv_mode(uint32_t flags) if (_flags & SOC_GPIO_OPENDRAIN) { /* drive_open_drain */ - drv_mode = CY_GPIO_DM_OD_DRIVESLOW_IN_OFF; + drv_mode = (_flags & SOC_GPIO_INPUTENABLE) ? CY_GPIO_DM_OD_DRIVESLOW + : CY_GPIO_DM_OD_DRIVESLOW_IN_OFF; } else if (_flags & SOC_GPIO_OPENSOURCE) { /* drive_open_source */ - drv_mode = CY_GPIO_DM_OD_DRIVESHIGH_IN_OFF; + drv_mode = (_flags & SOC_GPIO_INPUTENABLE) ? CY_GPIO_DM_OD_DRIVESHIGH + : CY_GPIO_DM_OD_DRIVESHIGH_IN_OFF; } else if (_flags & SOC_GPIO_PUSHPULL) { /* drive_push_pull */ - drv_mode = CY_GPIO_DM_STRONG_IN_OFF; + drv_mode = (_flags & SOC_GPIO_INPUTENABLE) ? CY_GPIO_DM_STRONG + : CY_GPIO_DM_STRONG_IN_OFF; } else if ((_flags & SOC_GPIO_PULLUP) && (_flags & SOC_GPIO_PULLDOWN)) { /* bias_pull_up and bias_pull_down */ - drv_mode = CY_GPIO_DM_PULLUP_DOWN_IN_OFF; + drv_mode = (_flags & SOC_GPIO_INPUTENABLE) ? CY_GPIO_DM_PULLUP_DOWN + : CY_GPIO_DM_PULLUP_DOWN_IN_OFF; } else if (_flags & SOC_GPIO_PULLUP) { /* bias_pull_up */ - drv_mode = CY_GPIO_DM_PULLUP_IN_OFF; + drv_mode = (_flags & SOC_GPIO_INPUTENABLE) ? CY_GPIO_DM_PULLUP + : CY_GPIO_DM_PULLUP_IN_OFF; } else if (_flags & SOC_GPIO_PULLDOWN) { /* bias_pull_down */ - drv_mode = CY_GPIO_DM_PULLDOWN_IN_OFF; + drv_mode = (_flags & SOC_GPIO_INPUTENABLE) ? CY_GPIO_DM_PULLDOWN + : CY_GPIO_DM_PULLDOWN_IN_OFF; + } else if ((_flags & SOC_GPIO_HIGHZ) | (_flags & SOC_GPIO_INPUTENABLE)) { + /* bias_pull_down */ + drv_mode = CY_GPIO_DM_HIGHZ; } else { /* nothing do here */ } - if (_flags & SOC_GPIO_INPUTENABLE) { - /* input_enable */ - drv_mode |= CY_GPIO_DM_HIGHZ; - } - return drv_mode; } -int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, - uintptr_t reg) +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) { ARG_UNUSED(reg); diff --git a/drivers/pinctrl/pinctrl_imx_scu.c b/drivers/pinctrl/pinctrl_imx_scu.c new file mode 100644 index 00000000000..67448ed5999 --- /dev/null +++ b/drivers/pinctrl/pinctrl_imx_scu.c @@ -0,0 +1,38 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include
    + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, + uint8_t pin_cnt, uintptr_t reg) +{ + sc_ipc_t ipc_handle; + int ret, i; + + ret = sc_ipc_open(&ipc_handle, DT_REG_ADDR(DT_NODELABEL(scu_mu))); + if (ret != SC_ERR_NONE) { + return -ENODEV; + } + + for (i = 0; i < pin_cnt; i++) { + /* TODO: for now, pad configuration is not supported. As such, + * the state of the pad is the following: + * 1) Normal configuration (no OD) + * 2) ISO off + * 3) Pull select and drive strength initialized by another + * entity (e.g: SCFW, Linux etc...) or set to the default + * values as specified in the TRM. + */ + ret = sc_pad_set_mux(ipc_handle, pins[i].pad, pins[i].mux, 0, 0); + if (ret != SC_ERR_NONE) { + return -EINVAL; + } + } + + return 0; +} diff --git a/drivers/pinctrl/pinctrl_ite_it8xxx2.c b/drivers/pinctrl/pinctrl_ite_it8xxx2.c index 3c8af74baf3..886a035483f 100644 --- a/drivers/pinctrl/pinctrl_ite_it8xxx2.c +++ b/drivers/pinctrl/pinctrl_ite_it8xxx2.c @@ -24,6 +24,10 @@ struct pinctrl_it8xxx2_gpio { uintptr_t func3_gcr[GPIO_GROUP_MEMBERS]; /* function 3 enable mask */ uint8_t func3_en_mask[GPIO_GROUP_MEMBERS]; + /* function 3 external control register */ + uintptr_t func3_ext[GPIO_GROUP_MEMBERS]; + /* function 3 external mask */ + uint8_t func3_ext_mask[GPIO_GROUP_MEMBERS]; /* function 4 general control register */ uintptr_t func4_gcr[GPIO_GROUP_MEMBERS]; /* function 4 enable mask */ @@ -132,6 +136,7 @@ static int pinctrl_gpio_it8xxx2_configure_pins(const pinctrl_soc_pin_t *pins) volatile uint8_t *reg_gpcr = (uint8_t *)gpio->reg_gpcr + pin; volatile uint8_t *reg_func3_gcr = (uint8_t *)(gpio->func3_gcr[pin]); volatile uint8_t *reg_func4_gcr = (uint8_t *)(gpio->func4_gcr[pin]); + volatile uint8_t *reg_func3_ext = (uint8_t *)(gpio->func3_ext[pin]); /* Handle PIN configuration. */ if (pinctrl_it8xxx2_set(pins)) { @@ -155,6 +160,11 @@ static int pinctrl_gpio_it8xxx2_configure_pins(const pinctrl_soc_pin_t *pins) /* Common settings for alternate function. */ *reg_gpcr &= ~(GPCR_PORT_PIN_MODE_INPUT | GPCR_PORT_PIN_MODE_OUTPUT); + /* Ensure that func3-ext setting is in default state. */ + if (reg_func3_ext != NULL) { + *reg_func3_ext &= ~gpio->func3_ext_mask[pin]; + } + switch (pins->alt_func) { case IT8XXX2_ALT_FUNC_1: /* Func1: Alternate function has been set above. */ @@ -169,6 +179,11 @@ static int pinctrl_gpio_it8xxx2_configure_pins(const pinctrl_soc_pin_t *pins) * Func3 also need to set the general control. */ *reg_func3_gcr |= gpio->func3_en_mask[pin]; + + /* Func3-external: Some pins require external setting. */ + if (reg_func3_ext != NULL) { + *reg_func3_ext |= gpio->func3_ext_mask[pin]; + } break; case IT8XXX2_ALT_FUNC_4: /* @@ -327,11 +342,6 @@ static int pinctrl_it8xxx2_init(const struct device *dev) */ gpio_base->GPIO_GCR &= ~IT8XXX2_GPIO_LPCRSTEN; - /* - * TODO: If UART2 swaps from bit2:1 to bit6:5 in H group, we - * have to set UART1PSEL = 1 in UART1PMR register. - */ - #ifdef CONFIG_SOC_IT8XXX2_REG_SET_V2 /* * Swap the default I2C2 SMCLK2/SMDAT2 pins from GPC7/GPD0 to GPF6/GPF7, @@ -345,23 +355,25 @@ static int pinctrl_it8xxx2_init(const struct device *dev) return 0; } -#define INIT_UNION_CONFIG(inst) \ - COND_CODE_1(DT_INST_PROP(inst, gpio_group), \ - (.gpio = { \ - .reg_gpcr = (uint8_t *)DT_INST_REG_ADDR_BY_IDX(inst, 0), \ - .func3_gcr = DT_INST_PROP(inst, func3_gcr), \ - .func3_en_mask = DT_INST_PROP(inst, func3_en_mask), \ - .func4_gcr = DT_INST_PROP(inst, func4_gcr), \ - .func4_en_mask = DT_INST_PROP(inst, func4_en_mask), \ - .volt_sel = DT_INST_PROP(inst, volt_sel), \ - .volt_sel_mask = DT_INST_PROP(inst, volt_sel_mask), \ - }), \ - (.ksi_kso = { \ - .reg_gctrl = (uint8_t *)DT_INST_REG_ADDR_BY_IDX(inst, 0), \ - .reg_ctrl = (uint8_t *)DT_INST_REG_ADDR_BY_IDX(inst, 1), \ - .pp_od_mask = (uint8_t)DT_INST_PROP(inst, pp_od_mask), \ - .pullup_mask = (uint8_t)DT_INST_PROP(inst, pullup_mask), \ - }) \ +#define INIT_UNION_CONFIG(inst) \ + COND_CODE_1(DT_INST_PROP(inst, gpio_group), \ + (.gpio = { \ + .reg_gpcr = (uint8_t *)DT_INST_REG_ADDR_BY_IDX(inst, 0), \ + .func3_gcr = DT_INST_PROP(inst, func3_gcr), \ + .func3_en_mask = DT_INST_PROP(inst, func3_en_mask), \ + .func3_ext = DT_INST_PROP_OR(inst, func3_ext, {0}), \ + .func3_ext_mask = DT_INST_PROP_OR(inst, func3_ext_mask, {0}), \ + .func4_gcr = DT_INST_PROP(inst, func4_gcr), \ + .func4_en_mask = DT_INST_PROP(inst, func4_en_mask), \ + .volt_sel = DT_INST_PROP(inst, volt_sel), \ + .volt_sel_mask = DT_INST_PROP(inst, volt_sel_mask), \ + }), \ + (.ksi_kso = { \ + .reg_gctrl = (uint8_t *)DT_INST_REG_ADDR_BY_IDX(inst, 0), \ + .reg_ctrl = (uint8_t *)DT_INST_REG_ADDR_BY_IDX(inst, 1), \ + .pp_od_mask = (uint8_t)DT_INST_PROP(inst, pp_od_mask), \ + .pullup_mask = (uint8_t)DT_INST_PROP(inst, pullup_mask), \ + }) \ ) #define PINCTRL_ITE_INIT(inst) \ diff --git a/drivers/pinctrl/pinctrl_kinetis.c b/drivers/pinctrl/pinctrl_kinetis.c index 5fdb07a8ced..45ac0ebe3cf 100644 --- a/drivers/pinctrl/pinctrl_kinetis.c +++ b/drivers/pinctrl/pinctrl_kinetis.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 NXP + * Copyright (c) 2022-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,9 +7,13 @@ #define DT_DRV_COMPAT nxp_kinetis_pinmux +#include #include +#include #include +LOG_MODULE_REGISTER(pinctrl_kinetis, CONFIG_PINCTRL_LOG_LEVEL); + /* Port register addresses. */ static PORT_Type *ports[] = { (PORT_Type *)DT_REG_ADDR(DT_NODELABEL(porta)), @@ -28,7 +32,8 @@ static PORT_Type *ports[] = { #define PINCFG(mux) ((mux) & Z_PINCTRL_KINETIS_PCR_MASK) struct pinctrl_mcux_config { - clock_ip_name_t clock_ip_name; + const struct device *clock_dev; + clock_control_subsys_t clock_subsys; }; int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, @@ -51,24 +56,36 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, static int pinctrl_mcux_init(const struct device *dev) { const struct pinctrl_mcux_config *config = dev->config; + int err; + + if (!device_is_ready(config->clock_dev)) { + LOG_ERR("clock control device not ready"); + return -ENODEV; + } - CLOCK_EnableClock(config->clock_ip_name); + err = clock_control_on(config->clock_dev, config->clock_subsys); + if (err) { + LOG_ERR("failed to enable clock (err %d)", err); + return -EINVAL; + } return 0; } -#if DT_NODE_HAS_STATUS(DT_INST(0, nxp_kinetis_ke1xf_sim), okay) -#define INST_DT_CLOCK_IP_NAME(n) \ - DT_REG_ADDR(DT_INST_PHANDLE(n, clocks)) + DT_INST_CLOCKS_CELL(n, name) -#else -#define INST_DT_CLOCK_IP_NAME(n) \ +#if DT_NODE_HAS_STATUS(DT_INST(0, nxp_kinetis_sim), okay) +#define PINCTRL_MCUX_DT_INST_CLOCK_SUBSYS(n) \ CLK_GATE_DEFINE(DT_INST_CLOCKS_CELL(n, offset), \ DT_INST_CLOCKS_CELL(n, bits)) +#else +#define PINCTRL_MCUX_DT_INST_CLOCK_SUBSYS(n) \ + DT_INST_CLOCKS_CELL(n, name) #endif #define PINCTRL_MCUX_INIT(n) \ static const struct pinctrl_mcux_config pinctrl_mcux_##n##_config = {\ - .clock_ip_name = INST_DT_CLOCK_IP_NAME(n), \ + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ + .clock_subsys = (clock_control_subsys_t) \ + PINCTRL_MCUX_DT_INST_CLOCK_SUBSYS(n), \ }; \ \ DEVICE_DT_INST_DEFINE(n, \ diff --git a/drivers/pinctrl/pinctrl_npcx.c b/drivers/pinctrl/pinctrl_npcx.c index 5759122018f..373a7158cfc 100644 --- a/drivers/pinctrl/pinctrl_npcx.c +++ b/drivers/pinctrl/pinctrl_npcx.c @@ -38,17 +38,10 @@ static const struct npcx_pwm_pinctrl_config pwm_pinctrl_cfg[] = { /* Pin-control local functions for peripheral devices */ static bool npcx_periph_pinmux_has_lock(int group) { -#if defined(CONFIG_SOC_SERIES_NPCX7) - if (group == 0x00 || (group >= 0x02 && group <= 0x04) || group == 0x06 || - group == 0x0b || group == 0x0f) { + if ((BIT(group) & NPCX_DEVALT_LK_GROUP_MASK) != 0) { return true; } -#elif defined(CONFIG_SOC_SERIES_NPCX9) - if (group == 0x00 || (group >= 0x02 && group <= 0x06) || group == 0x0b || - group == 0x0d || (group >= 0x0f && group <= 0x12)) { - return true; - } -#endif + return false; } diff --git a/drivers/pinctrl/pinctrl_ra.c b/drivers/pinctrl/pinctrl_ra.c new file mode 100644 index 00000000000..54aa881748c --- /dev/null +++ b/drivers/pinctrl/pinctrl_ra.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#define DT_DRV_COMPAT renesas_ra_pinctrl + +#define PORT_NUM 15 +#define PIN_NUM 16 + +enum { + PWPR_PFSWE_POS = 6, + PWPR_B0WI_POS = 7, +}; + +static inline uint32_t pinctrl_ra_read_PmnFPS(size_t port, size_t pin) +{ + return sys_read32(DT_INST_REG_ADDR_BY_NAME(0, pfs) + (port * PIN_NUM + pin) * 4); +} + +static inline void pinctrl_ra_write_PmnFPS(size_t port, size_t pin, uint32_t value) +{ + sys_write32(value, DT_INST_REG_ADDR_BY_NAME(0, pfs) + (port * PIN_NUM + pin) * 4); +} + +static inline uint32_t pinctrl_ra_read_PMISC_PWPR(size_t port, size_t pin) +{ + return sys_read32(DT_INST_REG_ADDR_BY_NAME(0, pmisc_pwpr)); +} + +static inline void pinctrl_ra_write_PMISC_PWPR(uint32_t value) +{ + sys_write32(value, DT_INST_REG_ADDR_BY_NAME(0, pmisc_pwpr)); +} + +static void pinctrl_ra_configure_pfs(const pinctrl_soc_pin_t *pinc) +{ + pinctrl_soc_pin_t pincfg; + + memcpy(&pincfg, pinc, sizeof(pinctrl_soc_pin_t)); + pincfg.pin = 0; + pincfg.port = 0; + + /* Clear PMR bits before configuring */ + if ((pincfg.config & PmnPFS_PMR_POS)) { + uint32_t val = pinctrl_ra_read_PmnFPS(pinc->port, pinc->pin); + + pinctrl_ra_write_PmnFPS(pinc->port, pinc->pin, val & ~(BIT(PmnPFS_PMR_POS))); + pinctrl_ra_write_PmnFPS(pinc->port, pinc->pin, pincfg.config & ~PmnPFS_PMR_POS); + } + + pinctrl_ra_write_PmnFPS(pinc->port, pinc->pin, pincfg.config); +} + +int pinctrl_ra_query_config(uint32_t port, uint32_t pin, struct pinctrl_ra_pin *const pincfg) +{ + if (port >= PORT_NUM || pin >= PIN_NUM) { + return -EINVAL; + } + + pincfg->config = pinctrl_ra_read_PmnFPS(port, pin); + return 0; +} + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) +{ + pinctrl_ra_write_PMISC_PWPR(0); + pinctrl_ra_write_PMISC_PWPR(BIT(PWPR_PFSWE_POS)); + + for (int i = 0; i < pin_cnt; i++) { + pinctrl_ra_configure_pfs(&pins[i]); + } + + pinctrl_ra_write_PMISC_PWPR(0); + pinctrl_ra_write_PMISC_PWPR(BIT(PWPR_B0WI_POS)); + + return 0; +} diff --git a/drivers/pinctrl/pinctrl_rzt2m.c b/drivers/pinctrl/pinctrl_rzt2m.c new file mode 100644 index 00000000000..0dff4461903 --- /dev/null +++ b/drivers/pinctrl/pinctrl_rzt2m.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_rzt2m_pinctrl + +#include +#include +#include + +#define PORT_NSR DT_INST_REG_ADDR_BY_NAME(0, port_nsr) +#define PTADR DT_INST_REG_ADDR_BY_NAME(0, ptadr) + +/* Port m mode control register */ +#define PMC(port) (PORT_NSR + 0x400 + port) +/* Port m function control register */ +#define PFC(port) (PORT_NSR + 0x600 + (0x4 * port)) +/* IO Buffer m function switching register */ +#define DRCTL(port, pin) (PORT_NSR + 0xa00 + (0x8 * port) + pin) +/* Port m region select register */ +#define RSELP(port) (PTADR + port) + +#define DRCTL_DRIVE_STRENGTH(val) (val & 0x3) +#define DRCTL_PULL_UP_DOWN(val) ((val & 0x3) << 2) +#define DRCTL_SCHMITT(val) ((val & 0x1) << 4) +#define DRCTL_SLEW_RATE(val) ((val & 0x1) << 5) +#define DRCTL_CONFIG(drive, pull, schmitt, slew) \ + (DRCTL_DRIVE_STRENGTH(drive) | DRCTL_PULL_UP_DOWN(pull) | DRCTL_SCHMITT(schmitt) | \ + DRCTL_SLEW_RATE(slew)) +#define PFC_FUNC_MASK(pin) (0xf << (pin * 4)) + +static void pinctrl_configure_pin(const pinctrl_soc_pin_t *pin) +{ + uint8_t rselp = sys_read8(RSELP(pin->port)); + uint32_t pfc = sys_read32(PFC(pin->port)) & ~(PFC_FUNC_MASK(pin->pin)); + uint8_t pmc = sys_read8(PMC(pin->port)); + + /* Set proper bit in the RSELP register to use as non-safety domain. */ + sys_write8(rselp | BIT(pin->pin), RSELP(pin->port)); + sys_write8(DRCTL_CONFIG( + pin->drive_strength, (pin->pull_up == 1 ? 1U : (pin->pull_down == 1 ? 2U : 0)), + pin->schmitt_enable, pin->slew_rate), + DRCTL(pin->port, pin->pin)); + + /* Select function for the pin. */ + sys_write32(pfc | pin->func << (pin->pin * 4), PFC(pin->port)); + + /* Set proper bit in the PMC register to use the pin as a peripheral IO. */ + sys_write8(pmc | BIT(pin->pin), PMC(pin->port)); +} + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) +{ + ARG_UNUSED(reg); + + for (uint8_t i = 0U; i < pin_cnt; i++) { + pinctrl_configure_pin(pins++); + } + + return 0; +} diff --git a/drivers/pm_cpu_ops/Kconfig b/drivers/pm_cpu_ops/Kconfig index c38c6779fa1..43d549f59bd 100644 --- a/drivers/pm_cpu_ops/Kconfig +++ b/drivers/pm_cpu_ops/Kconfig @@ -32,7 +32,6 @@ config PM_CPU_OPS_PSCI config PSCI_SHELL bool "Support for PSCI interface shell commands" - default y depends on SHELL && PM_CPU_OPS_PSCI help Say Y here if you need to enable PSCI interface shell commands diff --git a/drivers/power_domain/CMakeLists.txt b/drivers/power_domain/CMakeLists.txt index 0637e64f794..27b07c945f1 100644 --- a/drivers/power_domain/CMakeLists.txt +++ b/drivers/power_domain/CMakeLists.txt @@ -4,4 +4,5 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_GPIO power_domain_gpio.c) +zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_GPIO_MONITOR power_domain_gpio_monitor.c) zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_INTEL_ADSP power_domain_intel_adsp.c) diff --git a/drivers/power_domain/Kconfig b/drivers/power_domain/Kconfig index 6c8563d4724..22ffc388503 100644 --- a/drivers/power_domain/Kconfig +++ b/drivers/power_domain/Kconfig @@ -12,6 +12,12 @@ module = POWER_DOMAIN module-str = power_domain source "subsys/logging/Kconfig.template.log_config" +config POWER_DOMAIN_INIT_PRIORITY + int "Power domain init priority" + default 75 + help + Power domain initialization priority. + config POWER_DOMAIN_GPIO bool "GPIO controlled power domain" default y @@ -28,4 +34,11 @@ config POWER_DOMAIN_INTEL_ADSP help Include Intel ADSP power domain control mechanisms +config POWER_DOMAIN_GPIO_MONITOR + bool "GPIO monitor for sensing power on rail" + default y + depends on DT_HAS_POWER_DOMAIN_GPIO_MONITOR_ENABLED + depends on GPIO + select DEVICE_DEPS + endif diff --git a/drivers/power_domain/power_domain_gpio.c b/drivers/power_domain/power_domain_gpio.c index b4702ad13eb..15c60a65d75 100644 --- a/drivers/power_domain/power_domain_gpio.c +++ b/drivers/power_domain/power_domain_gpio.c @@ -125,17 +125,17 @@ static int pd_gpio_init(const struct device *dev) return pm_device_driver_init(dev, pd_gpio_pm_action); } -#define POWER_DOMAIN_DEVICE(id) \ - static const struct pd_gpio_config pd_gpio_##id##_cfg = { \ - .enable = GPIO_DT_SPEC_INST_GET(id, enable_gpios), \ - .startup_delay_us = DT_INST_PROP(id, startup_delay_us), \ - .off_on_delay_us = DT_INST_PROP(id, off_on_delay_us), \ - }; \ - static struct pd_gpio_data pd_gpio_##id##_data; \ - PM_DEVICE_DT_INST_DEFINE(id, pd_gpio_pm_action); \ - DEVICE_DT_INST_DEFINE(id, pd_gpio_init, PM_DEVICE_DT_INST_GET(id), \ - &pd_gpio_##id##_data, &pd_gpio_##id##_cfg, \ - POST_KERNEL, 75, \ +#define POWER_DOMAIN_DEVICE(id) \ + static const struct pd_gpio_config pd_gpio_##id##_cfg = { \ + .enable = GPIO_DT_SPEC_INST_GET(id, enable_gpios), \ + .startup_delay_us = DT_INST_PROP(id, startup_delay_us), \ + .off_on_delay_us = DT_INST_PROP(id, off_on_delay_us), \ + }; \ + static struct pd_gpio_data pd_gpio_##id##_data; \ + PM_DEVICE_DT_INST_DEFINE(id, pd_gpio_pm_action); \ + DEVICE_DT_INST_DEFINE(id, pd_gpio_init, PM_DEVICE_DT_INST_GET(id), \ + &pd_gpio_##id##_data, &pd_gpio_##id##_cfg, \ + POST_KERNEL, CONFIG_POWER_DOMAIN_INIT_PRIORITY, \ NULL); DT_INST_FOREACH_STATUS_OKAY(POWER_DOMAIN_DEVICE) diff --git a/drivers/power_domain/power_domain_gpio_monitor.c b/drivers/power_domain/power_domain_gpio_monitor.c new file mode 100644 index 00000000000..55e44570553 --- /dev/null +++ b/drivers/power_domain/power_domain_gpio_monitor.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT power_domain_gpio_monitor + +#include +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(power_domain_gpio_monitor, CONFIG_POWER_DOMAIN_LOG_LEVEL); + +struct pd_gpio_monitor_config { + struct gpio_dt_spec power_good_gpio; +}; + +struct pd_gpio_monitor_data { + struct gpio_callback callback; + const struct device *dev; + bool is_powered; +}; + +struct pd_visitor_context { + const struct device *domain; + enum pm_device_action action; +}; + +static int pd_on_domain_visitor(const struct device *dev, void *context) +{ + struct pd_visitor_context *visitor_context = context; + + /* Only run action if the device is on the specified domain */ + if (!dev->pm || (dev->pm->domain != visitor_context->domain)) { + return 0; + } + + dev->pm->usage = 0; + (void)pm_device_action_run(dev, visitor_context->action); + return 0; +} + +static void pd_gpio_monitor_callback(const struct device *port, + struct gpio_callback *cb, gpio_port_pins_t pins) +{ + struct pd_gpio_monitor_data *data = CONTAINER_OF(cb, struct pd_gpio_monitor_data, callback); + const struct pd_gpio_monitor_config *config = data->dev->config; + const struct device *dev = data->dev; + struct pd_visitor_context context = {.domain = dev}; + int rc; + + rc = gpio_pin_get_dt(&config->power_good_gpio); + if (rc < 0) { + LOG_WRN("Failed to read gpio logic level"); + return; + } + + data->is_powered = rc; + if (rc == 0) { + context.action = PM_DEVICE_ACTION_SUSPEND; + (void)device_supported_foreach(dev, pd_on_domain_visitor, &context); + context.action = PM_DEVICE_ACTION_TURN_OFF; + (void)device_supported_foreach(dev, pd_on_domain_visitor, &context); + return; + } + + pm_device_children_action_run(data->dev, PM_DEVICE_ACTION_TURN_ON, NULL); +} + +static int pd_gpio_monitor_pm_action(const struct device *dev, enum pm_device_action action) +{ + struct pd_gpio_monitor_data *data = dev->data; + + switch (action) { + case PM_DEVICE_ACTION_TURN_ON: + case PM_DEVICE_ACTION_TURN_OFF: + return -ENOTSUP; + case PM_DEVICE_ACTION_RESUME: + if (!data->is_powered) { + return -EAGAIN; + } + break; + default: + break; + } + + return 0; +} + +static int pd_gpio_monitor_init(const struct device *dev) +{ + const struct pd_gpio_monitor_config *config = dev->config; + struct pd_gpio_monitor_data *data = dev->data; + int rc; + + data->dev = dev; + + if (!gpio_is_ready_dt(&config->power_good_gpio)) { + LOG_ERR("GPIO port %s is not ready", config->power_good_gpio.port->name); + return -ENODEV; + } + + rc = gpio_pin_configure_dt(&config->power_good_gpio, GPIO_INPUT); + if (rc) { + LOG_ERR("Failed to configure GPIO"); + goto unconfigure_pin; + } + + rc = gpio_pin_interrupt_configure_dt(&config->power_good_gpio, GPIO_INT_EDGE_BOTH); + if (rc) { + gpio_pin_configure_dt(&config->power_good_gpio, GPIO_DISCONNECTED); + LOG_ERR("Failed to configure GPIO interrupt"); + goto unconfigure_interrupt; + } + + gpio_init_callback(&data->callback, pd_gpio_monitor_callback, + BIT(config->power_good_gpio.pin)); + rc = gpio_add_callback_dt(&config->power_good_gpio, &data->callback); + if (rc) { + LOG_ERR("Failed to add GPIO callback"); + goto remove_callback; + } + + pm_device_init_suspended(dev); + return pm_device_runtime_enable(dev); +remove_callback: + gpio_remove_callback(config->power_good_gpio.port, &data->callback); +unconfigure_interrupt: + gpio_pin_interrupt_configure_dt(&config->power_good_gpio, GPIO_INT_DISABLE); +unconfigure_pin: + gpio_pin_configure_dt(&config->power_good_gpio, GPIO_DISCONNECTED); + return rc; +} + +#define POWER_DOMAIN_DEVICE(inst) \ + static const struct pd_gpio_monitor_config pd_gpio_monitor_config_##inst = { \ + .power_good_gpio = GPIO_DT_SPEC_INST_GET(inst, gpios), \ + }; \ + static struct pd_gpio_monitor_data pd_gpio_monitor_data_##inst; \ + PM_DEVICE_DT_INST_DEFINE(inst, pd_gpio_monitor_pm_action); \ + DEVICE_DT_INST_DEFINE(inst, pd_gpio_monitor_init, \ + PM_DEVICE_DT_INST_GET(inst), &pd_gpio_monitor_data_##inst, \ + &pd_gpio_monitor_config_##inst, POST_KERNEL, \ + CONFIG_POWER_DOMAIN_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(POWER_DOMAIN_DEVICE) diff --git a/drivers/power_domain/power_domain_intel_adsp.c b/drivers/power_domain/power_domain_intel_adsp.c index 21df893b127..47828d6c744 100644 --- a/drivers/power_domain/power_domain_intel_adsp.c +++ b/drivers/power_domain/power_domain_intel_adsp.c @@ -17,6 +17,7 @@ struct pg_bits { uint32_t CPA_bit; }; +#ifdef CONFIG_PM_DEVICE static int pd_intel_adsp_set_power_enable(struct pg_bits *bits, bool power_enable) { uint16_t SPA_bit_mask = BIT(bits->SPA_bit); @@ -65,6 +66,8 @@ static int pd_intel_adsp_pm_action(const struct device *dev, enum pm_device_acti return ret; } +#endif /* CONFIG_PM_DEVICE */ + static int pd_intel_adsp_init(const struct device *dev) { pm_device_init_suspended(dev); @@ -73,14 +76,14 @@ static int pd_intel_adsp_init(const struct device *dev) #define DT_DRV_COMPAT intel_adsp_power_domain -#define POWER_DOMAIN_DEVICE(id) \ - static struct pg_bits pd_pg_reg##id = { \ - .SPA_bit = DT_INST_PROP(id, bit_position), \ - .CPA_bit = DT_INST_PROP(id, bit_position), \ - }; \ - PM_DEVICE_DT_INST_DEFINE(id, pd_intel_adsp_pm_action); \ - DEVICE_DT_INST_DEFINE(id, pd_intel_adsp_init, PM_DEVICE_DT_INST_GET(id),\ - &pd_pg_reg##id, NULL, POST_KERNEL, \ +#define POWER_DOMAIN_DEVICE(id) \ + static struct pg_bits pd_pg_reg##id = { \ + .SPA_bit = DT_INST_PROP(id, bit_position), \ + .CPA_bit = DT_INST_PROP(id, bit_position), \ + }; \ + PM_DEVICE_DT_INST_DEFINE(id, pd_intel_adsp_pm_action); \ + DEVICE_DT_INST_DEFINE(id, pd_intel_adsp_init, PM_DEVICE_DT_INST_GET(id), \ + &pd_pg_reg##id, NULL, POST_KERNEL, \ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, NULL); DT_INST_FOREACH_STATUS_OKAY(POWER_DOMAIN_DEVICE) diff --git a/drivers/ps2/ps2_handlers.c b/drivers/ps2/ps2_handlers.c index 71d1181a2d2..91835e85ea5 100644 --- a/drivers/ps2/ps2_handlers.c +++ b/drivers/ps2/ps2_handlers.c @@ -5,13 +5,13 @@ */ #include -#include +#include static inline int z_vrfy_ps2_config(const struct device *dev, ps2_callback_t callback_isr) { - Z_OOPS(Z_SYSCALL_DRIVER_PS2(dev, config)); - Z_OOPS(Z_SYSCALL_VERIFY_MSG(callback_isr == NULL, + K_OOPS(K_SYSCALL_DRIVER_PS2(dev, config)); + K_OOPS(K_SYSCALL_VERIFY_MSG(callback_isr == NULL, "callback not be set from user mode")); return z_impl_ps2_config(dev, callback_isr); } @@ -19,29 +19,29 @@ static inline int z_vrfy_ps2_config(const struct device *dev, static inline int z_vrfy_ps2_write(const struct device *dev, uint8_t value) { - Z_OOPS(Z_SYSCALL_DRIVER_PS2(dev, write)); + K_OOPS(K_SYSCALL_DRIVER_PS2(dev, write)); return z_impl_ps2_write(dev, value); } #include static inline int z_vrfy_ps2_read(const struct device *dev, uint8_t *value) { - Z_OOPS(Z_SYSCALL_DRIVER_PS2(dev, read)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(value, sizeof(uint8_t))); + K_OOPS(K_SYSCALL_DRIVER_PS2(dev, read)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(value, sizeof(uint8_t))); return z_impl_ps2_read(dev, value); } #include static inline int z_vrfy_ps2_enable_callback(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_PS2(dev, enable_callback)); + K_OOPS(K_SYSCALL_DRIVER_PS2(dev, enable_callback)); return z_impl_ps2_enable_callback(dev); } #include static inline int z_vrfy_ps2_disable_callback(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_PS2(dev, disable_callback)); + K_OOPS(K_SYSCALL_DRIVER_PS2(dev, disable_callback)); return z_impl_ps2_disable_callback(dev); } #include diff --git a/drivers/ps2/ps2_mchp_xec.c b/drivers/ps2/ps2_mchp_xec.c index ccd2957982e..f3b1a9e10bf 100644 --- a/drivers/ps2/ps2_mchp_xec.c +++ b/drivers/ps2/ps2_mchp_xec.c @@ -16,10 +16,8 @@ #include #endif #include -#ifdef CONFIG_PM_DEVICE #include #include -#endif #include #include #include diff --git a/drivers/ptp_clock/ptp_clock.c b/drivers/ptp_clock/ptp_clock.c index ba0d7e373e9..0ac0e5c242f 100644 --- a/drivers/ptp_clock/ptp_clock.c +++ b/drivers/ptp_clock/ptp_clock.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include #ifdef CONFIG_USERSPACE @@ -14,15 +14,15 @@ int z_vrfy_ptp_clock_get(const struct device *dev, struct net_ptp_time ptp_time; int ret; - Z_OOPS(Z_SYSCALL_DRIVER_PTP_CLOCK(dev, get)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(tm, sizeof(struct net_ptp_time))); + K_OOPS(K_SYSCALL_DRIVER_PTP_CLOCK(dev, get)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(tm, sizeof(struct net_ptp_time))); ret = z_impl_ptp_clock_get((const struct device *)dev, &ptp_time); if (ret != 0) { return 0; } - if (z_user_to_copy((void *)tm, &ptp_time, sizeof(ptp_time)) != 0) { + if (k_usermode_to_copy((void *)tm, &ptp_time, sizeof(ptp_time)) != 0) { return 0; } diff --git a/drivers/pwm/CMakeLists.txt b/drivers/pwm/CMakeLists.txt index 308a2f5b142..2bf100aceb2 100644 --- a/drivers/pwm/CMakeLists.txt +++ b/drivers/pwm/CMakeLists.txt @@ -39,6 +39,7 @@ zephyr_library_sources_ifdef(CONFIG_PWM_XMC4XXX_CCU4 pwm_xmc4xxx_ccu4.c) zephyr_library_sources_ifdef(CONFIG_PWM_XMC4XXX_CCU8 pwm_xmc4xxx_ccu8.c) zephyr_library_sources_ifdef(CONFIG_PWM_MCUX_CTIMER pwm_mcux_ctimer.c) zephyr_library_sources_ifdef(CONFIG_PWM_NUMAKER pwm_numaker.c) +zephyr_library_sources_ifdef(CONFIG_PWM_NXP_S32_EMIOS pwm_nxp_s32_emios.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE pwm_handlers.c) zephyr_library_sources_ifdef(CONFIG_PWM_CAPTURE pwm_capture.c) diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 184cbcc7cc0..8942ebd89b0 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -22,7 +22,6 @@ config PWM_INIT_PRIORITY config PWM_SHELL bool "PWM shell" - default y depends on SHELL help Enable the PWM related shell commands. @@ -99,4 +98,6 @@ source "drivers/pwm/Kconfig.mcux_ctimer" source "drivers/pwm/Kconfig.numaker" +source "drivers/pwm/Kconfig.nxp_s32_emios" + endif # PWM diff --git a/drivers/pwm/Kconfig.mcux_sctimer b/drivers/pwm/Kconfig.mcux_sctimer index a788208e8ad..0ca23f56847 100644 --- a/drivers/pwm/Kconfig.mcux_sctimer +++ b/drivers/pwm/Kconfig.mcux_sctimer @@ -5,6 +5,6 @@ config PWM_MCUX_SCTIMER bool "MCUX SCTimer PWM driver" default y depends on DT_HAS_NXP_SCTIMER_PWM_ENABLED - select PINCTRL + depends on CLOCK_CONTROL && PINCTRL help Enable sctimer based pwm driver. diff --git a/drivers/pwm/Kconfig.nrfx b/drivers/pwm/Kconfig.nrfx index 712021a7780..9a84c5fd21b 100644 --- a/drivers/pwm/Kconfig.nrfx +++ b/drivers/pwm/Kconfig.nrfx @@ -9,5 +9,6 @@ config PWM_NRFX select NRFX_PWM1 if HAS_HW_NRF_PWM1 select NRFX_PWM2 if HAS_HW_NRF_PWM2 select NRFX_PWM3 if HAS_HW_NRF_PWM3 + select PINCTRL help Enable support for nrfx Hardware PWM driver for nRF52 MCU series. diff --git a/drivers/pwm/Kconfig.nxp_s32_emios b/drivers/pwm/Kconfig.nxp_s32_emios new file mode 100644 index 00000000000..5d976ea2d59 --- /dev/null +++ b/drivers/pwm/Kconfig.nxp_s32_emios @@ -0,0 +1,11 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +config PWM_NXP_S32_EMIOS + bool "NXP S32 PWM-eMIOS driver" + default y + depends on DT_HAS_NXP_S32_EMIOS_PWM_ENABLED + select NXP_S32_EMIOS + select NOCACHE_MEMORY if ARCH_HAS_NOCACHE_MEMORY_SUPPORT + help + Enable support for the NXP S32 PWM-eMIOS. diff --git a/drivers/pwm/pwm_handlers.c b/drivers/pwm/pwm_handlers.c index 9993b24cf73..3ffaaa61e46 100644 --- a/drivers/pwm/pwm_handlers.c +++ b/drivers/pwm/pwm_handlers.c @@ -5,14 +5,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include static inline int z_vrfy_pwm_set_cycles(const struct device *dev, uint32_t channel, uint32_t period, uint32_t pulse, pwm_flags_t flags) { - Z_OOPS(Z_SYSCALL_DRIVER_PWM(dev, set_cycles)); + K_OOPS(K_SYSCALL_DRIVER_PWM(dev, set_cycles)); return z_impl_pwm_set_cycles((const struct device *)dev, channel, period, pulse, flags); } @@ -22,8 +22,8 @@ static inline int z_vrfy_pwm_get_cycles_per_sec(const struct device *dev, uint32_t channel, uint64_t *cycles) { - Z_OOPS(Z_SYSCALL_DRIVER_PWM(dev, get_cycles_per_sec)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(cycles, sizeof(uint64_t))); + K_OOPS(K_SYSCALL_DRIVER_PWM(dev, get_cycles_per_sec)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(cycles, sizeof(uint64_t))); return z_impl_pwm_get_cycles_per_sec((const struct device *)dev, channel, (uint64_t *)cycles); } @@ -34,7 +34,7 @@ static inline int z_vrfy_pwm_get_cycles_per_sec(const struct device *dev, static inline int z_vrfy_pwm_enable_capture(const struct device *dev, uint32_t channel) { - Z_OOPS(Z_SYSCALL_DRIVER_PWM(dev, enable_capture)); + K_OOPS(K_SYSCALL_DRIVER_PWM(dev, enable_capture)); return z_impl_pwm_enable_capture((const struct device *)dev, channel); } #include @@ -42,7 +42,7 @@ static inline int z_vrfy_pwm_enable_capture(const struct device *dev, static inline int z_vrfy_pwm_disable_capture(const struct device *dev, uint32_t channel) { - Z_OOPS(Z_SYSCALL_DRIVER_PWM(dev, disable_capture)); + K_OOPS(K_SYSCALL_DRIVER_PWM(dev, disable_capture)); return z_impl_pwm_disable_capture((const struct device *)dev, channel); } #include @@ -57,19 +57,19 @@ static inline int z_vrfy_pwm_capture_cycles(const struct device *dev, uint32_t pulse; int err; - Z_OOPS(Z_SYSCALL_DRIVER_PWM(dev, configure_capture)); - Z_OOPS(Z_SYSCALL_DRIVER_PWM(dev, enable_capture)); - Z_OOPS(Z_SYSCALL_DRIVER_PWM(dev, disable_capture)); + K_OOPS(K_SYSCALL_DRIVER_PWM(dev, configure_capture)); + K_OOPS(K_SYSCALL_DRIVER_PWM(dev, enable_capture)); + K_OOPS(K_SYSCALL_DRIVER_PWM(dev, disable_capture)); err = z_impl_pwm_capture_cycles((const struct device *)dev, channel, flags, &period, &pulse, timeout); if (period_cycles != NULL) { - Z_OOPS(z_user_to_copy(period_cycles, &period, + K_OOPS(k_usermode_to_copy(period_cycles, &period, sizeof(*period_cycles))); } if (pulse_cycles != NULL) { - Z_OOPS(z_user_to_copy(pulse_cycles, &pulse, + K_OOPS(k_usermode_to_copy(pulse_cycles, &pulse, sizeof(*pulse_cycles))); } diff --git a/drivers/pwm/pwm_mcux.c b/drivers/pwm/pwm_mcux.c index 23bbd3d0326..d753682f46e 100644 --- a/drivers/pwm/pwm_mcux.c +++ b/drivers/pwm/pwm_mcux.c @@ -199,7 +199,9 @@ static int pwm_mcux_init(const struct device *dev) pwm_config.reloadLogic = config->reload; pwm_config.clockSource = kPWM_BusClock; pwm_config.enableDebugMode = config->run_debug; +#if !defined(FSL_FEATURE_PWM_HAS_NO_WAITEN) || (!FSL_FEATURE_PWM_HAS_NO_WAITEN) pwm_config.enableWait = config->run_wait; +#endif status = PWM_Init(config->base, config->index, &pwm_config); if (status != kStatus_Success) { diff --git a/drivers/pwm/pwm_mcux_sctimer.c b/drivers/pwm/pwm_mcux_sctimer.c index fe5eda5d3d0..91d16092e8f 100644 --- a/drivers/pwm/pwm_mcux_sctimer.c +++ b/drivers/pwm/pwm_mcux_sctimer.c @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -23,6 +24,8 @@ struct pwm_mcux_sctimer_config { SCT_Type *base; uint32_t prescale; const struct pinctrl_dev_config *pincfg; + const struct device *clock_dev; + clock_control_subsys_t clock_subsys; }; struct pwm_mcux_sctimer_data { @@ -79,11 +82,11 @@ static int mcux_sctimer_pwm_set_cycles(const struct device *dev, data->period_cycles[channel] = period_cycles; - /* - * Do not divide by the prescale factor as this is accounted for in - * the SDK function - */ - clock_freq = CLOCK_GetFreq(kCLOCK_BusClk); + if (clock_control_get_rate(config->clock_dev, config->clock_subsys, + &clock_freq)) { + return -EINVAL; + } + pwm_freq = (clock_freq / config->prescale) / period_cycles; if (pwm_freq == 0) { @@ -117,8 +120,14 @@ static int mcux_sctimer_pwm_get_cycles_per_sec(const struct device *dev, uint64_t *cycles) { const struct pwm_mcux_sctimer_config *config = dev->config; + uint32_t clock_freq; - *cycles = CLOCK_GetFreq(kCLOCK_BusClk) / config->prescale; + if (clock_control_get_rate(config->clock_dev, config->clock_subsys, + &clock_freq)) { + return -EINVAL; + } + + *cycles = clock_freq / config->prescale; return 0; } @@ -138,7 +147,7 @@ static int mcux_sctimer_pwm_init(const struct device *dev) } SCTIMER_GetDefaultConfig(&pwm_config); - /* Divide the SCT clock by 8 */ + pwm_config.prescale_l = config->prescale - 1; status = SCTIMER_Init(config->base, &pwm_config); @@ -170,6 +179,8 @@ static const struct pwm_driver_api pwm_mcux_sctimer_driver_api = { .base = (SCT_Type *)DT_INST_REG_ADDR(n), \ .prescale = DT_INST_PROP(n, prescaler), \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ + .clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, name),\ }; \ \ DEVICE_DT_INST_DEFINE(n, \ diff --git a/drivers/pwm/pwm_nrfx.c b/drivers/pwm/pwm_nrfx.c index 373f8eef7e2..52257dce104 100644 --- a/drivers/pwm/pwm_nrfx.c +++ b/drivers/pwm/pwm_nrfx.c @@ -15,6 +15,22 @@ LOG_MODULE_REGISTER(pwm_nrfx, CONFIG_PWM_LOG_LEVEL); +/* NRFX_PWM_NRF52_ANOMALY_109_WORKAROUND_ENABLED can be undefined or defined + * to 0 or 1, hence the use of #if IS_ENABLED(). + */ +#if IS_ENABLED(NRFX_PWM_NRF52_ANOMALY_109_WORKAROUND_ENABLED) +#define ANOMALY_109_IRQ_CONNECT(...) IRQ_CONNECT(__VA_ARGS__) +#define ANOMALY_109_EGU_IRQ_CONNECT(idx) _EGU_IRQ_CONNECT(idx) +#define _EGU_IRQ_CONNECT(idx) \ + extern void nrfx_egu_##idx##_irq_handler(void); \ + IRQ_CONNECT(DT_IRQN(DT_NODELABEL(egu##idx)), \ + DT_IRQ(DT_NODELABEL(egu##idx), priority), \ + nrfx_isr, nrfx_egu_##idx##_irq_handler, 0) +#else +#define ANOMALY_109_IRQ_CONNECT(...) +#define ANOMALY_109_EGU_IRQ_CONNECT(idx) +#endif + #define PWM_NRFX_CH_POLARITY_MASK BIT(15) #define PWM_NRFX_CH_COMPARE_MASK BIT_MASK(15) #define PWM_NRFX_CH_VALUE(compare_value, inverted) \ @@ -238,6 +254,8 @@ static int pwm_nrfx_init(const struct device *dev) int ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + ANOMALY_109_EGU_IRQ_CONNECT(NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE); + if (ret < 0) { return ret; } @@ -343,9 +361,16 @@ static int pwm_nrfx_pm_action(const struct device *dev, .seq.length = NRF_PWM_CHANNEL_COUNT, \ .pcfg = PINCTRL_DT_DEV_CONFIG_GET(PWM(idx)), \ }; \ + static int pwm_nrfx_init##idx(const struct device *dev) \ + { \ + ANOMALY_109_IRQ_CONNECT( \ + DT_IRQN(PWM(idx)), DT_IRQ(PWM(idx), priority), \ + nrfx_isr, nrfx_pwm_##idx##_irq_handler, 0); \ + return pwm_nrfx_init(dev); \ + }; \ PM_DEVICE_DT_DEFINE(PWM(idx), pwm_nrfx_pm_action); \ DEVICE_DT_DEFINE(PWM(idx), \ - pwm_nrfx_init, PM_DEVICE_DT_GET(PWM(idx)), \ + pwm_nrfx_init##idx, PM_DEVICE_DT_GET(PWM(idx)), \ &pwm_nrfx_##idx##_data, \ &pwm_nrfx_##idx##_config, \ POST_KERNEL, CONFIG_PWM_INIT_PRIORITY, \ diff --git a/drivers/pwm/pwm_nxp_s32_emios.c b/drivers/pwm/pwm_nxp_s32_emios.c new file mode 100644 index 00000000000..e5a0513fb2f --- /dev/null +++ b/drivers/pwm/pwm_nxp_s32_emios.c @@ -0,0 +1,855 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include + +#ifdef CONFIG_PWM_CAPTURE +#include +#endif + +#define LOG_MODULE_NAME nxp_s32_emios_pwm +#include +LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_PWM_LOG_LEVEL); + +#define DT_DRV_COMPAT nxp_s32_emios_pwm + +/* + * Need to fill to this array at runtime, cannot do at build time like + * the HAL over configuration tool due to limitation of the integration + */ +#if EMIOS_PWM_IP_USED +extern uint8 eMios_Pwm_Ip_IndexInChState[EMIOS_PWM_IP_INSTANCE_COUNT][EMIOS_PWM_IP_CHANNEL_COUNT]; +#endif + +#ifdef CONFIG_PWM_CAPTURE +extern uint8 eMios_Icu_Ip_IndexInChState[EMIOS_ICU_IP_INSTANCE_COUNT][EMIOS_ICU_IP_NUM_OF_CHANNELS]; + +/* We need maximum three edges for measure both period and cycle */ +#define MAX_NUM_EDGE 3 + +struct pwm_nxp_s32_capture_data { + bool continuous; + bool inverted; + bool pulse_capture; + bool period_capture; + void *user_data; + pwm_capture_callback_handler_t callback; + eMios_Icu_ValueType edge_buff[MAX_NUM_EDGE]; +}; +#endif + +struct pwm_nxp_s32_data { + uint32_t emios_clk; +#if EMIOS_PWM_IP_USED + uint8_t start_pwm_ch; +#endif + +#ifdef CONFIG_PWM_CAPTURE + struct pwm_nxp_s32_capture_data capture[EMIOS_ICU_IP_NUM_OF_CHANNELS]; +#endif +}; + +#if EMIOS_PWM_IP_USED +struct pwm_nxp_s32_pulse_info { + uint8_t pwm_pulse_channels; + Emios_Pwm_Ip_ChannelConfigType *pwm_info; +}; +#endif + +struct pwm_nxp_s32_config { + eMIOS_Type *base; + uint8_t instance; + const struct device *clock_dev; + clock_control_subsys_t clock_subsys; + const struct pinctrl_dev_config *pincfg; + +#if EMIOS_PWM_IP_USED + struct pwm_nxp_s32_pulse_info *pulse_info; +#endif + +#ifdef CONFIG_PWM_CAPTURE + eMios_Icu_Ip_ConfigType * icu_cfg; +#endif +}; + +#if EMIOS_PWM_IP_USED +#ifdef EMIOS_PWM_IP_MODE_OPWFMB_USED +static int pwm_nxp_s32_set_cycles_internal_timebase(uint8_t instance, uint32_t channel, + uint32_t period_cycles, uint32_t pulse_cycles) +{ + bool need_update = false; + + if ((period_cycles > EMIOS_PWM_IP_MAX_CNT_VAL) || + (period_cycles <= EMIOS_PWM_IP_MIN_CNT_VAL)) { + LOG_ERR("period_cycles is out of range"); + return -EINVAL; + } + + if (Emios_Pwm_Ip_GetPeriod(instance, channel) != period_cycles) { + Emios_Pwm_Ip_SetPeriod(instance, channel, period_cycles); + need_update = true; + } + + if (Emios_Pwm_Ip_GetDutyCycle(instance, channel) != pulse_cycles) { + need_update = true; + if (Emios_Pwm_Ip_SetDutyCycle(instance, channel, pulse_cycles)) { + LOG_ERR("Cannot set pulse cycles"); + return -EIO; + } + } + + if (need_update) { + /* Force match so that the new period, duty cycle takes effect immediately */ + Emios_Pwm_Ip_ForceMatchTrailingEdge(instance, channel, true); + } + + return 0; +} +#endif + +#if defined(EMIOS_PWM_IP_MODE_OPWMCB_USED) || defined(EMIOS_PWM_IP_MODE_OPWMB_USED) +static int pwm_nxp_s32_set_cycles_external_timebase(uint8_t instance, uint32_t channel, + uint32_t period_cycles, uint32_t pulse_cycles) +{ + uint8_t master_channel; + + if ((period_cycles > EMIOS_PWM_IP_MAX_CNT_VAL) || + (period_cycles <= EMIOS_PWM_IP_MIN_CNT_VAL)) { + LOG_ERR("period_cycles is out of range"); + return -EINVAL; + } + + if (Emios_Pwm_Ip_GetPeriod(instance, channel) != period_cycles) { + /* + * This mode uses internal counter, so change period and cycle + * don't effect to the others + */ + master_channel = Emios_Pwm_Ip_GetMasterBusChannel(instance, channel); + + if (Emios_Mcl_Ip_SetCounterBusPeriod(instance, master_channel, period_cycles)) { + LOG_ERR("Cannot set counter period"); + return -EIO; + } + } + + if (Emios_Pwm_Ip_GetDutyCycle(instance, channel) != pulse_cycles) { + if (Emios_Pwm_Ip_SetDutyCycle(instance, channel, pulse_cycles)) { + LOG_ERR("Cannot set pulse cycles"); + return -EIO; + } + } + + return 0; +} +#endif + +static int pwm_nxp_s32_set_cycles(const struct device *dev, uint32_t channel, + uint32_t period_cycles, uint32_t pulse_cycles, + pwm_flags_t flags) +{ + const struct pwm_nxp_s32_config *config = dev->config; + struct pwm_nxp_s32_data *data = dev->data; + + Emios_Pwm_Ip_ChannelConfigType *pwm_info; + uint8_t logic_ch; + + if (channel >= EMIOS_PWM_IP_CHANNEL_COUNT) { + LOG_ERR("invalid channel %d", channel); + return -EINVAL; + } + + if (eMios_Pwm_Ip_IndexInChState[config->instance][channel] >= + EMIOS_PWM_IP_NUM_OF_CHANNELS_USED) { + LOG_ERR("Channel %d is not configured for PWM", channel); + return -EINVAL; + } + + logic_ch = eMios_Pwm_Ip_IndexInChState[config->instance][channel] - data->start_pwm_ch; + pwm_info = &config->pulse_info->pwm_info[logic_ch]; + + if ((flags & PWM_POLARITY_MASK) == pwm_info->OutputPolarity) { + LOG_ERR("Only support configuring output polarity at boot time"); + return -ENOTSUP; + } + + switch (pwm_info->Mode) { +#ifdef EMIOS_PWM_IP_MODE_OPWFMB_USED + case EMIOS_PWM_IP_MODE_OPWFMB_FLAG: + return pwm_nxp_s32_set_cycles_internal_timebase(config->instance, channel, + period_cycles, pulse_cycles); +#endif + +#ifdef EMIOS_PWM_IP_MODE_OPWMCB_USED + case EMIOS_PWM_IP_MODE_OPWMCB_TRAIL_EDGE_FLAG: + case EMIOS_PWM_IP_MODE_OPWMCB_LEAD_EDGE_FLAG: + if ((period_cycles % 2)) { + LOG_ERR("OPWMCB mode: period must be an even number"); + return -EINVAL; + } + + return pwm_nxp_s32_set_cycles_external_timebase(config->instance, channel, + (period_cycles + 2) / 2, + pulse_cycles); +#endif + +#if defined(EMIOS_PWM_IP_MODE_OPWMB_USED) + case EMIOS_PWM_IP_MODE_OPWMB_FLAG: + if ((Emios_Pwm_Ip_GetPhaseShift(config->instance, channel) + + pulse_cycles) > period_cycles) { + LOG_ERR("OPWMB mode: new duty cycle + phase shift must <= new period"); + return -EINVAL; + } + + return pwm_nxp_s32_set_cycles_external_timebase(config->instance, channel, + period_cycles, pulse_cycles); +#endif + + default: + /* Never reach here */ + break; + } + + return 0; +} +#endif + +#ifdef CONFIG_PWM_CAPTURE +static ALWAYS_INLINE eMios_Icu_ValueType pwm_nxp_s32_capture_calc(eMios_Icu_ValueType first_cnt, + eMios_Icu_ValueType second_cnt) +{ + if (first_cnt < second_cnt) { + return second_cnt - first_cnt; + } + + /* Counter top value is always 0xFFFF */ + return EMIOS_ICU_IP_COUNTER_MASK - first_cnt + second_cnt; +} + +static ALWAYS_INLINE eMios_Icu_ValueType pwm_nxp_s32_pulse_calc(bool inverted, + eMios_Icu_ValueType *edge_buff, + eMios_Icu_Ip_LevelType input_state) +{ + eMios_Icu_ValueType first_cnt, second_cnt; + + if (input_state ^ inverted) { + /* 3 edges captured is raise, fall, raise */ + first_cnt = edge_buff[0]; + second_cnt = edge_buff[1]; + } else { + /* 3 edges captured is fall, raise, fall */ + first_cnt = edge_buff[1]; + second_cnt = edge_buff[2]; + } + + return pwm_nxp_s32_capture_calc(first_cnt, second_cnt); +} + +static int pwm_nxp_s32_capture_configure(const struct device *dev, + uint32_t channel, + pwm_flags_t flags, + pwm_capture_callback_handler_t cb, + void *user_data) +{ + const struct pwm_nxp_s32_config *config = dev->config; + struct pwm_nxp_s32_data *data = dev->data; + + if (channel >= EMIOS_ICU_IP_NUM_OF_CHANNELS) { + LOG_ERR("Invalid channel %d", channel); + return -EINVAL; + } + + if (!flags) { + LOG_ERR("Invalid PWM capture flag"); + return -EINVAL; + } + + if (eMios_Icu_Ip_IndexInChState[config->instance][channel] >= + EMIOS_ICU_IP_NUM_OF_CHANNELS_USED) { + LOG_ERR("Channel %d is not configured for PWM", channel); + return -EINVAL; + } + + /* If interrupt is enabled --> channel is on-going */ + if (config->base->CH.UC[channel].C & eMIOS_C_FEN_MASK) { + LOG_ERR("Channel %d is busy", channel); + return -EBUSY; + } + + data->capture[channel].continuous = (flags & PWM_CAPTURE_MODE_MASK); + data->capture[channel].inverted = (flags & PWM_POLARITY_MASK); + data->capture[channel].pulse_capture = (flags & PWM_CAPTURE_TYPE_PULSE); + data->capture[channel].period_capture = (flags & PWM_CAPTURE_TYPE_PERIOD); + data->capture[channel].callback = cb; + data->capture[channel].user_data = user_data; + + return 0; +} + +static int pwm_nxp_s32_capture_enable(const struct device *dev, uint32_t channel) +{ + const struct pwm_nxp_s32_config *config = dev->config; + struct pwm_nxp_s32_data *data = dev->data; + + eMios_Icu_Ip_EdgeType edge; + uint8_t num_edge; + + if (channel >= EMIOS_ICU_IP_NUM_OF_CHANNELS) { + LOG_ERR("Invalid channel %d", channel); + return -EINVAL; + } + + if (eMios_Icu_Ip_IndexInChState[config->instance][channel] >= + EMIOS_ICU_IP_NUM_OF_CHANNELS_USED) { + LOG_ERR("Channel %d is not configured for PWM", channel); + return -EINVAL; + } + + if (!data->capture[channel].callback) { + LOG_ERR("Callback is not configured"); + return -EINVAL; + } + + /* If interrupt is enabled --> channel is on-going */ + if (config->base->CH.UC[channel].C & eMIOS_C_FEN_MASK) { + LOG_ERR("Channel %d is busy", channel); + return -EBUSY; + } + + /* If just measure period, we just need 2 edges */ + if (data->capture[channel].period_capture && !data->capture[channel].pulse_capture) { + num_edge = 2U; + edge = EMIOS_ICU_RISING_EDGE; + } else { + num_edge = 3U; + edge = EMIOS_ICU_BOTH_EDGES; + } + + Emios_Icu_Ip_SetActivation(config->instance, channel, edge); + + Emios_Icu_Ip_EnableNotification(config->instance, channel); + + Emios_Icu_Ip_StartTimestamp(config->instance, channel, + data->capture[channel].edge_buff, + MAX_NUM_EDGE, num_edge); + + return 0; +} + +static int pwm_nxp_s32_capture_disable(const struct device *dev, uint32_t channel) +{ + const struct pwm_nxp_s32_config *config = dev->config; + + if (channel >= EMIOS_ICU_IP_NUM_OF_CHANNELS) { + LOG_ERR("Invalid channel %d", channel); + return -EINVAL; + } + + if (eMios_Icu_Ip_IndexInChState[config->instance][channel] >= + EMIOS_ICU_IP_NUM_OF_CHANNELS_USED) { + LOG_ERR("Channel %d is not configured for PWM", channel); + return -EINVAL; + } + + Emios_Icu_Ip_StopTimestamp(config->instance, channel); + + return 0; +} + +static int pwm_nxp_s32_get_master_bus(const struct device *dev, uint32_t channel) +{ + const struct pwm_nxp_s32_config *config = dev->config; + uint8_t bus_select, master_bus; + + bus_select = (config->base->CH.UC[channel].C & eMIOS_C_BSL_MASK) >> eMIOS_C_BSL_SHIFT; + + switch (bus_select) { + case 0: + master_bus = 23U; + break; + case 1: + master_bus = (channel < 8U) ? 0U : ((channel < 16U) ? 8U : 16U); + break; + case 2: + master_bus = 22U; + break; + default: + /* Default is internal counter */ + master_bus = channel; + break; + } + + return master_bus; +} +#endif + +static int pwm_nxp_s32_get_cycles_per_sec(const struct device *dev, + uint32_t channel, + uint64_t *cycles) +{ + const struct pwm_nxp_s32_config *config = dev->config; + struct pwm_nxp_s32_data *data = dev->data; + + uint8_t master_bus = 0xFFU; + uint8_t internal_prescaler, global_prescaler; + +#if EMIOS_PWM_IP_USED + if (eMios_Pwm_Ip_IndexInChState[config->instance][channel] < + EMIOS_PWM_IP_NUM_OF_CHANNELS_USED) { + master_bus = Emios_Pwm_Ip_GetMasterBusChannel(config->instance, channel); + } +#endif + +#ifdef CONFIG_PWM_CAPTURE + if (eMios_Icu_Ip_IndexInChState[config->instance][channel] < + EMIOS_ICU_IP_NUM_OF_CHANNELS_USED) { + master_bus = pwm_nxp_s32_get_master_bus(dev, channel); + } +#endif + + if (master_bus == 0xFF) { + LOG_ERR("Channel %d is not configured for PWM", channel); + return -EINVAL; + } + + internal_prescaler = (config->base->CH.UC[master_bus].C2 & eMIOS_C2_UCEXTPRE_MASK) >> + eMIOS_C2_UCEXTPRE_SHIFT; + + /* Clock source for internal prescaler is from either eMIOS or eMIOS / global prescaler */ + if (config->base->CH.UC[master_bus].C2 & eMIOS_C2_UCPRECLK_MASK) { + *cycles = data->emios_clk / (internal_prescaler + 1); + } else { + global_prescaler = (config->base->MCR & eMIOS_MCR_GPRE_MASK) >> + eMIOS_MCR_GPRE_SHIFT; + *cycles = data->emios_clk / ((internal_prescaler + 1) * (global_prescaler + 1)); + } + + return 0; +} + +#if EMIOS_PWM_IP_USED +static int pwm_nxp_s32_pulse_gen_init(const struct device *dev) +{ + const struct pwm_nxp_s32_config *config = dev->config; + struct pwm_nxp_s32_data *data = dev->data; + + const Emios_Pwm_Ip_ChannelConfigType *pwm_info; + + uint8_t ch_id; + static uint8_t logic_ch; + + data->start_pwm_ch = logic_ch; + + for (ch_id = 0; ch_id < config->pulse_info->pwm_pulse_channels; ch_id++) { + pwm_info = &config->pulse_info->pwm_info[ch_id]; + eMios_Pwm_Ip_IndexInChState[config->instance][pwm_info->ChannelId] = logic_ch++; + Emios_Pwm_Ip_InitChannel(config->instance, pwm_info); + } + + return 0; +} +#endif + +#ifdef CONFIG_PWM_CAPTURE +static int pwm_nxp_s32_pulse_capture_init(const struct device *dev) +{ + const struct pwm_nxp_s32_config *config = dev->config; + + const eMios_Icu_Ip_ChannelConfigType *icu_info; + + uint8_t ch_id; + static uint8_t logic_ch; + + for (ch_id = 0; ch_id < config->icu_cfg->nNumChannels; ch_id++) { + icu_info = &(*config->icu_cfg->pChannelsConfig)[ch_id]; + eMios_Icu_Ip_IndexInChState[config->instance][icu_info->hwChannel] = logic_ch++; + } + + if (Emios_Icu_Ip_Init(config->instance, config->icu_cfg)) { + return -EINVAL; + } + + return 0; +} + +static void pwm_nxp_s32_capture_callback(const struct device *dev, uint32_t channel) +{ + const struct pwm_nxp_s32_config *config = dev->config; + struct pwm_nxp_s32_data *data = dev->data; + + uint32_t period = 0, pulse = 0; + + if (data->capture[channel].period_capture && !data->capture[channel].pulse_capture) { + period = pwm_nxp_s32_capture_calc(data->capture[channel].edge_buff[0], + data->capture[channel].edge_buff[1]); + } else { + if (data->capture[channel].pulse_capture) { + pulse = pwm_nxp_s32_pulse_calc(data->capture[channel].inverted, + data->capture[channel].edge_buff, + Emios_Icu_Ip_GetInputLevel(config->instance, + channel)); + } + + if (data->capture[channel].period_capture) { + period = pwm_nxp_s32_capture_calc(data->capture[channel].edge_buff[0], + data->capture[channel].edge_buff[2]); + } + } + + if (!data->capture[channel].continuous) { + Emios_Icu_Ip_StopTimestamp(config->instance, channel); + } + + data->capture[channel].callback(dev, channel, period, pulse, 0, + data->capture[channel].user_data); +} +#endif + +static int pwm_nxp_s32_init(const struct device *dev) +{ + const struct pwm_nxp_s32_config *config = dev->config; + struct pwm_nxp_s32_data *data = dev->data; + + int err = 0; + + if (!device_is_ready(config->clock_dev)) { + return -ENODEV; + } + + if (clock_control_get_rate(config->clock_dev, config->clock_subsys, + &data->emios_clk)) { + return -EINVAL; + } + + err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); + if (err < 0) { + return err; + } + +#if EMIOS_PWM_IP_USED + err = pwm_nxp_s32_pulse_gen_init(dev); + if (err < 0) { + return err; + } +#endif + +#ifdef CONFIG_PWM_CAPTURE + err = pwm_nxp_s32_pulse_capture_init(dev); + if (err < 0) { + return err; + } +#endif + + return err; +} + +static const struct pwm_driver_api pwm_nxp_s32_driver_api = { + .set_cycles = pwm_nxp_s32_set_cycles, + .get_cycles_per_sec = pwm_nxp_s32_get_cycles_per_sec, +#ifdef CONFIG_PWM_CAPTURE + .configure_capture = pwm_nxp_s32_capture_configure, + .enable_capture = pwm_nxp_s32_capture_enable, + .disable_capture = pwm_nxp_s32_capture_disable, +#endif +}; + +/* + * If timebase is configured in MCB up/down count mode: pwm period = (2 * master bus's period - 2) + */ +#define EMIOS_PWM_PERIOD_TIME_BASE(node_id) \ + COND_CODE_1(DT_ENUM_HAS_VALUE(node_id, mode, MCB_UP_DOWN_COUNTER), \ + (2 * DT_PROP_BY_PHANDLE(node_id, master_bus, period) - 2), \ + (DT_PROP_BY_PHANDLE(node_id, master_bus, period))) + +#define EMIOS_PWM_IS_MODE_OPWFMB(node_id) \ + DT_ENUM_HAS_VALUE(node_id, pwm_mode, OPWFMB) + +#define EMIOS_PWM_IS_MODE_OPWMCB(node_id) \ + UTIL_OR(DT_ENUM_HAS_VALUE(node_id, pwm_mode, OPWMCB_TRAIL_EDGE), \ + DT_ENUM_HAS_VALUE(node_id, pwm_mode, OPWMCB_LEAD_EDGE)) \ + +#define EMIOS_PWM_IS_MODE_OPWMB(node_id) \ + DT_ENUM_HAS_VALUE(node_id, pwm_mode, OPWMB) + +#define EMIOS_PWM_IS_MODE_SAIC(node_id) \ + DT_ENUM_HAS_VALUE(node_id, pwm_mode, SAIC) + +#define EMIOS_PWM_IS_CAPTURE_MODE(node_id) \ + EMIOS_PWM_IS_MODE_SAIC(node_id) + +#define EMIOS_PWM_LOG(node_id, msg) \ + DT_NODE_PATH(node_id) ": " DT_PROP(node_id, pwm_mode) ": " msg \ + +#define EMIOS_PWM_VERIFY_MASTER_BUS(node_id) \ + BUILD_ASSERT(BIT(DT_PROP(node_id, channel)) & \ + DT_PROP_BY_PHANDLE(node_id, master_bus, channel_mask), \ + EMIOS_PWM_LOG(node_id, "invalid master bus")); + +#define EMIOS_PWM_PULSE_GEN_COMMON_VERIFY(node_id) \ + BUILD_ASSERT(DT_NODE_HAS_PROP(node_id, duty_cycle), \ + EMIOS_PWM_LOG(node_id, "duty-cycle must be configured")); \ + BUILD_ASSERT(DT_NODE_HAS_PROP(node_id, polarity), \ + EMIOS_PWM_LOG(node_id, "polarity must be configured")); \ + BUILD_ASSERT(DT_NODE_HAS_PROP(node_id, input_filter), \ + EMIOS_PWM_LOG(node_id, "input-filter is not used")); + +#define EMIOS_PWM_VERIFY_MODE_OPWFMB(node_id) \ + EMIOS_PWM_PULSE_GEN_COMMON_VERIFY(node_id) \ + BUILD_ASSERT(DT_NODE_HAS_PROP(node_id, period), \ + EMIOS_PWM_LOG(node_id, "period must be configured")); \ + BUILD_ASSERT(IN_RANGE(DT_PROP(node_id, period), EMIOS_PWM_IP_MIN_CNT_VAL + 1, \ + EMIOS_PWM_IP_MAX_CNT_VAL), \ + EMIOS_PWM_LOG(node_id, "period is out of range")); \ + BUILD_ASSERT(DT_PROP(node_id, duty_cycle) <= DT_PROP(node_id, period), \ + EMIOS_PWM_LOG(node_id, "duty-cycle must <= period")); \ + BUILD_ASSERT(!DT_NODE_HAS_PROP(node_id, master_bus), \ + EMIOS_PWM_LOG(node_id, "master-bus must not be configured")); \ + BUILD_ASSERT(DT_PROP(node_id, dead_time) == 0, \ + EMIOS_PWM_LOG(node_id, "dead-time is not used")); \ + BUILD_ASSERT(DT_PROP(node_id, phase_shift) == 0, \ + EMIOS_PWM_LOG(node_id, "phase-shift is not used")); + +#define EMIOS_PWM_VERIFY_MODE_OPWMCB(node_id) \ + EMIOS_PWM_PULSE_GEN_COMMON_VERIFY(node_id) \ + BUILD_ASSERT(DT_ENUM_HAS_VALUE(DT_PHANDLE(node_id, master_bus), mode, \ + MCB_UP_DOWN_COUNTER), \ + EMIOS_PWM_LOG(node_id, "master-bus must be configured in MCB up-down")); \ + BUILD_ASSERT((DT_PROP(node_id, duty_cycle) + DT_PROP(node_id, dead_time)) <= \ + EMIOS_PWM_PERIOD_TIME_BASE(node_id), \ + EMIOS_PWM_LOG(node_id, "duty-cycle + dead-time must <= period")); \ + BUILD_ASSERT(DT_PROP(node_id, dead_time) <= DT_PROP(node_id, duty_cycle), \ + EMIOS_PWM_LOG(node_id, "dead-time must <= duty-cycle")); \ + BUILD_ASSERT(DT_PROP(node_id, phase_shift) == 0, \ + EMIOS_PWM_LOG(node_id, "phase-shift is not used")); \ + BUILD_ASSERT(!DT_NODE_HAS_PROP(node_id, period), \ + EMIOS_PWM_LOG(node_id, "period is not used," \ + " driver takes the value from master bus")); \ + BUILD_ASSERT(!DT_NODE_HAS_PROP(node_id, prescaler), \ + EMIOS_PWM_LOG(node_id, "prescaler is not used," \ + " driver takes the value from master bus")); \ + BUILD_ASSERT(DT_ENUM_HAS_VALUE(node_id, prescaler_src, PRESCALED_CLOCK), \ + EMIOS_PWM_LOG(node_id, "prescaler-src is not used," \ + " always use prescalered source")); \ + +#define EMIOS_PWM_VERIFY_MODE_OPWMB(node_id) \ + EMIOS_PWM_PULSE_GEN_COMMON_VERIFY(node_id) \ + BUILD_ASSERT(DT_ENUM_HAS_VALUE(DT_PHANDLE(node_id, master_bus), mode, MCB_UP_COUNTER), \ + EMIOS_PWM_LOG(node_id, "master-bus must be configured in MCB up")); \ + BUILD_ASSERT(!DT_NODE_HAS_PROP(node_id, period), \ + EMIOS_PWM_LOG(node_id, "period is not used," \ + " driver takes the value from master bus")); \ + BUILD_ASSERT((DT_PROP(node_id, duty_cycle) + DT_PROP(node_id, phase_shift)) <= \ + EMIOS_PWM_PERIOD_TIME_BASE(node_id), \ + EMIOS_PWM_LOG(node_id, "duty-cycle + phase-shift must <= period")); \ + BUILD_ASSERT(DT_PROP(node_id, dead_time) == 0, \ + EMIOS_PWM_LOG(node_id, "dead-time is not used")); \ + BUILD_ASSERT(!DT_NODE_HAS_PROP(node_id, prescaler), \ + EMIOS_PWM_LOG(node_id, "prescaler is not used")); \ + BUILD_ASSERT(DT_ENUM_HAS_VALUE(node_id, prescaler_src, PRESCALED_CLOCK), \ + EMIOS_PWM_LOG(node_id, "prescaler-src is not used," \ + " always use prescalered source")); \ + +#define EMIOS_PWM_VERIFY_MODE_SAIC(node_id) \ + IF_ENABLED(DT_NODE_HAS_PROP(node_id, master_bus), \ + (BUILD_ASSERT( \ + DT_ENUM_HAS_VALUE(DT_PHANDLE(node_id, master_bus), mode, MCB_UP_COUNTER), \ + EMIOS_PWM_LOG(node_id, "master-bus must be configured in MCB up"));)) \ + IF_ENABLED(DT_NODE_HAS_PROP(node_id, master_bus), \ + (BUILD_ASSERT(DT_PROP_BY_PHANDLE(node_id, master_bus, period) == 0xFFFF, \ + EMIOS_PWM_LOG(node_id, "master-bus period must be 0xFFFF"));)) \ + IF_ENABLED(UTIL_NOT(DT_NODE_HAS_PROP(node_id, master_bus)), \ + (BUILD_ASSERT( \ + BIT(DT_PROP(node_id, channel)) & DT_PROP(DT_GPARENT(node_id), internal_cnt),\ + EMIOS_PWM_LOG(node_id, "master-bus must be chosen," \ + " channel do not have has counter")))); \ + IF_ENABLED(UTIL_NOT(DT_NODE_HAS_PROP(node_id, master_bus)), \ + (BUILD_ASSERT(DT_NODE_HAS_PROP(node_id, prescaler), \ + EMIOS_PWM_LOG(node_id, "if use internal counter, prescaler must" \ + " be configured")))); \ + BUILD_ASSERT(!DT_NODE_HAS_PROP(node_id, duty_cycle), \ + EMIOS_PWM_LOG(node_id, "duty-cycle is not used")); \ + BUILD_ASSERT(!DT_NODE_HAS_PROP(node_id, polarity), \ + EMIOS_PWM_LOG(node_id, "polarity is not used")); \ + BUILD_ASSERT(!DT_NODE_HAS_PROP(node_id, period), \ + EMIOS_PWM_LOG(node_id, "period is not used")); \ + BUILD_ASSERT(DT_ENUM_HAS_VALUE(node_id, prescaler_src, PRESCALED_CLOCK), \ + EMIOS_PWM_LOG(node_id, "prescaler-src is not used," \ + " always use prescalered source")); + +#define _EMIOS_PWM_VERIFY_CONFIG(node_id) \ + IF_ENABLED(DT_NODE_HAS_PROP(node_id, master_bus), \ + (EMIOS_PWM_VERIFY_MASTER_BUS(node_id))) \ + IF_ENABLED(EMIOS_PWM_IS_MODE_OPWFMB(node_id), \ + (EMIOS_PWM_VERIFY_MODE_OPWFMB(node_id))) \ + IF_ENABLED(EMIOS_PWM_IS_MODE_OPWMCB(node_id), \ + (EMIOS_PWM_VERIFY_MODE_OPWMCB(node_id))) \ + IF_ENABLED(EMIOS_PWM_IS_MODE_OPWMB(node_id), \ + (EMIOS_PWM_VERIFY_MODE_OPWMB(node_id))) \ + IF_ENABLED(EMIOS_PWM_IS_MODE_SAIC(node_id), \ + (EMIOS_PWM_VERIFY_MODE_SAIC(node_id))) + +#if EMIOS_PWM_IP_USED +/* Macros used to glue devicetree with RTD's definition */ +#define EMIOS_PWM_BUS_A EMIOS_PWM_IP_BUS_A +#define EMIOS_PWM_BUS_B EMIOS_PWM_IP_BUS_BCDE +#define EMIOS_PWM_BUS_C EMIOS_PWM_IP_BUS_BCDE +#define EMIOS_PWM_BUS_D EMIOS_PWM_IP_BUS_BCDE +#define EMIOS_PWM_BUS_E EMIOS_PWM_IP_BUS_BCDE +#define EMIOS_PWM_BUS_F EMIOS_PWM_IP_BUS_F + +#define EMIOS_PWM_BUS(mode) DT_CAT(EMIOS_PWM_, mode) +#define EMIOS_PWM_MODE(mode) DT_CAT3(EMIOS_PWM_IP_MODE_, mode, _FLAG) +#define EMIOS_PWM_POLARITY(mode) DT_CAT(EMIOS_PWM_IP_, mode) +#define EMIOS_PWM_PS_SRC(mode) DT_CAT(EMIOS_PWM_IP_PS_SRC_, mode) + +#define _EMIOS_PWM_PULSE_GEN_CONFIG(node_id) \ + IF_ENABLED(UTIL_NOT(EMIOS_PWM_IS_CAPTURE_MODE(node_id)), \ + ({ \ + .ChannelId = DT_PROP(node_id, channel), \ + .Mode = EMIOS_PWM_MODE(DT_STRING_TOKEN(node_id, pwm_mode)), \ + .InternalPsSrc = EMIOS_PWM_PS_SRC(DT_STRING_TOKEN(node_id, prescaler_src)), \ + .InternalPs = DT_PROP_OR(node_id, prescaler, \ + DT_PROP_BY_PHANDLE(node_id, master_bus, prescaler)) - 1,\ + .Timebase = COND_CODE_1(DT_NODE_HAS_PROP(node_id, master_bus), \ + (EMIOS_PWM_BUS(DT_STRING_TOKEN( \ + DT_PHANDLE(node_id, master_bus), bus_type))), \ + (EMIOS_PWM_IP_BUS_INTERNAL)), \ + .PhaseShift = DT_PROP(node_id, phase_shift), \ + .DeadTime = DT_PROP(node_id, dead_time), \ + .OutputDisableSource = EMIOS_PWM_IP_OUTPUT_DISABLE_NONE, \ + .OutputPolarity = EMIOS_PWM_POLARITY(DT_STRING_TOKEN(node_id, polarity)), \ + .DebugMode = DT_PROP(node_id, freeze), \ + .PeriodCount = DT_PROP_OR(node_id, period, EMIOS_PWM_PERIOD_TIME_BASE(node_id)),\ + .DutyCycle = DT_PROP(node_id, duty_cycle), \ + },)) + +#define EMIOS_PWM_PULSE_GEN_CONFIG(n) \ + const Emios_Pwm_Ip_ChannelConfigType emios_pwm_##n##_init[] = { \ + DT_INST_FOREACH_CHILD_STATUS_OKAY(n, _EMIOS_PWM_PULSE_GEN_CONFIG) \ + }; \ + const struct pwm_nxp_s32_pulse_info emios_pwm_##n##_info = { \ + .pwm_pulse_channels = ARRAY_SIZE(emios_pwm_##n##_init), \ + .pwm_info = (Emios_Pwm_Ip_ChannelConfigType *)emios_pwm_##n##_init, \ + }; + +#define EMIOS_PWM_PULSE_GEN_GET_CONFIG(n) \ + .pulse_info = (struct pwm_nxp_s32_pulse_info *)&emios_pwm_##n##_info, +#else +#define EMIOS_PWM_PULSE_GEN_CONFIG(n) +#define EMIOS_PWM_PULSE_GEN_GET_CONFIG(n) +#endif + +#ifdef CONFIG_PWM_CAPTURE +/* Macros used to glue devicetree with RTD's definition */ +#define EMIOS_ICU_BUS_A EMIOS_ICU_BUS_A +#define EMIOS_ICU_BUS_B EMIOS_ICU_BUS_DIVERSE +#define EMIOS_ICU_BUS_C EMIOS_ICU_BUS_DIVERSE +#define EMIOS_ICU_BUS_D EMIOS_ICU_BUS_DIVERSE +#define EMIOS_ICU_BUS_E EMIOS_ICU_BUS_DIVERSE +#define EMIOS_ICU_BUS_F EMIOS_ICU_BUS_F + +#define DIGITAL_FILTER_0 EMIOS_DIGITAL_FILTER_BYPASSED +#define DIGITAL_FILTER_2 EMIOS_DIGITAL_FILTER_02 +#define DIGITAL_FILTER_4 EMIOS_DIGITAL_FILTER_04 +#define DIGITAL_FILTER_8 EMIOS_DIGITAL_FILTER_08 +#define DIGITAL_FILTER_16 EMIOS_DIGITAL_FILTER_16 + +#define EMIOS_PWM_CAPTURE_FILTER(filter) DT_CAT(DIGITAL_FILTER_, filter) +#define EMIOS_PWM_CAPTURE_MODE(mode) DT_CAT(EMIOS_ICU_, mode) +#define EMIOS_PWM_CAPTURE_BUS(mode) DT_CAT(EMIOS_ICU_, mode) + +#define EMIOS_PWM_CAPTURE_CB(n, ch) \ + DT_CAT5(pwm_nxp_s32_, n, _channel_, ch, _capture_callback) + +#define EMIOS_PWM_CALLBACK_DECLARE(node_id, n) \ + void EMIOS_PWM_CAPTURE_CB(n, DT_PROP(node_id, channel))(void) \ + { \ + pwm_nxp_s32_capture_callback(DEVICE_DT_INST_GET(n), DT_PROP(node_id, channel)); \ + } \ + +#define _EMIOS_PWM_PULSE_CAPTURE_CONFIG(node_id, n) \ + IF_ENABLED(EMIOS_PWM_IS_CAPTURE_MODE(node_id), \ + ({ \ + .hwChannel = DT_PROP(node_id, channel), \ + .ucMode = EMIOS_PWM_CAPTURE_MODE(DT_STRING_TOKEN(node_id, pwm_mode)), \ + .FreezeEn = DT_PROP(node_id, freeze), \ + .Prescaler = COND_CODE_1(DT_NODE_HAS_PROP(node_id, master_bus), \ + (DT_PROP_BY_PHANDLE(node_id, master_bus, prescaler)), \ + (DT_PROP(node_id, prescaler))) - 1, \ + .CntBus = COND_CODE_1(DT_NODE_HAS_PROP(node_id, master_bus), \ + (EMIOS_PWM_CAPTURE_BUS(DT_STRING_TOKEN( \ + DT_PHANDLE(node_id, master_bus), bus_type))),\ + (EMIOS_ICU_BUS_INTERNAL_COUNTER)), \ + .chMode = EMIOS_ICU_MODE_TIMESTAMP, \ + .chSubMode = EMIOS_ICU_MODE_WITHOUT_DMA, \ + .measurementMode = EMIOS_ICU_NO_MEASUREMENT, \ + .edgeAlignement = EMIOS_ICU_BOTH_EDGES, \ + .Filter = EMIOS_PWM_CAPTURE_FILTER(DT_PROP(node_id, input_filter)), \ + .callback = NULL_PTR, \ + .logicChStateCallback = NULL_PTR, \ + .callbackParams = 255U, \ + .bWithoutInterrupt = FALSE, \ + .timestampBufferType = EMIOS_ICU_CIRCULAR_BUFFER, \ + .eMiosChannelNotification = EMIOS_PWM_CAPTURE_CB(n, DT_PROP(node_id, channel)), \ + .eMiosOverflowNotification = NULL_PTR, \ + },)) + +#define EMIOS_PWM_PULSE_CAPTURE_CONFIG(n) \ + DT_INST_FOREACH_CHILD_STATUS_OKAY_VARGS(n, EMIOS_PWM_CALLBACK_DECLARE, n) \ + const eMios_Icu_Ip_ChannelConfigType emios_pwm_##n##_capture_init[] = { \ + DT_INST_FOREACH_CHILD_STATUS_OKAY_VARGS(n, _EMIOS_PWM_PULSE_CAPTURE_CONFIG, n) \ + }; \ + const eMios_Icu_Ip_ConfigType emios_pwm_##n##_capture_info = { \ + .nNumChannels = ARRAY_SIZE(emios_pwm_##n##_capture_init), \ + .pChannelsConfig = &emios_pwm_##n##_capture_init, \ + }; + +#define EMIOS_PWM_PULSE_CAPTURE_GET_CONFIG(n) \ + .icu_cfg = (eMios_Icu_Ip_ConfigType *)&emios_pwm_##n##_capture_info, +#else +#define EMIOS_PWM_PULSE_CAPTURE_CONFIG(n) +#define EMIOS_PWM_PULSE_CAPTURE_GET_CONFIG(n) +#endif + +#define EMIOS_PWM_VERIFY_CONFIG(n) \ + DT_INST_FOREACH_CHILD_STATUS_OKAY(n, _EMIOS_PWM_VERIFY_CONFIG) + +#define EMIOS_NXP_S32_INSTANCE_CHECK(idx, node_id) \ + ((DT_REG_ADDR(node_id) == IP_EMIOS_##idx##_BASE) ? idx : 0) + +#define EMIOS_NXP_S32_GET_INSTANCE(node_id) \ + LISTIFY(__DEBRACKET eMIOS_INSTANCE_COUNT, EMIOS_NXP_S32_INSTANCE_CHECK, (|), node_id) + +#define PWM_NXP_S32_INIT_DEVICE(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + EMIOS_PWM_VERIFY_CONFIG(n) \ + EMIOS_PWM_PULSE_GEN_CONFIG(n) \ + EMIOS_PWM_PULSE_CAPTURE_CONFIG(n) \ + static const struct pwm_nxp_s32_config pwm_nxp_s32_config_##n = { \ + .base = (eMIOS_Type *)DT_REG_ADDR(DT_INST_PARENT(n)), \ + .instance = EMIOS_NXP_S32_GET_INSTANCE(DT_INST_PARENT(n)), \ + .clock_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_INST_PARENT(n))), \ + .clock_subsys = (clock_control_subsys_t)DT_CLOCKS_CELL(DT_INST_PARENT(n), name),\ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + EMIOS_PWM_PULSE_GEN_GET_CONFIG(n) \ + EMIOS_PWM_PULSE_CAPTURE_GET_CONFIG(n) \ + }; \ + static struct pwm_nxp_s32_data pwm_nxp_s32_data_##n; \ + DEVICE_DT_INST_DEFINE(n, \ + &pwm_nxp_s32_init, \ + NULL, \ + &pwm_nxp_s32_data_##n, \ + &pwm_nxp_s32_config_##n, \ + POST_KERNEL, \ + CONFIG_PWM_INIT_PRIORITY, \ + &pwm_nxp_s32_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(PWM_NXP_S32_INIT_DEVICE) diff --git a/drivers/pwm/pwm_pca9685.c b/drivers/pwm/pwm_pca9685.c index 24596d7f377..f08bdd4cf9b 100644 --- a/drivers/pwm/pwm_pca9685.c +++ b/drivers/pwm/pwm_pca9685.c @@ -119,6 +119,7 @@ static int set_pre_scale(const struct device *dev, uint8_t value) struct pca9685_data *data = dev->data; uint8_t mode1; int ret; + uint8_t restart = RESTART; k_mutex_lock(&data->mutex, K_FOREVER); @@ -134,9 +135,7 @@ static int set_pre_scale(const struct device *dev, uint8_t value) } if ((mode1 & RESTART) == 0x00) { - LOG_ERR("RESTART bit should be set"); - ret = -EIO; - goto out; + restart = 0; } ret = set_reg(dev, ADDR_PRE_SCALE, value); @@ -152,7 +151,7 @@ static int set_pre_scale(const struct device *dev, uint8_t value) k_sleep(OSCILLATOR_STABILIZE); - ret = set_reg(dev, ADDR_MODE1, AUTO_INC | RESTART); + ret = set_reg(dev, ADDR_MODE1, AUTO_INC | restart); if (ret != 0) { goto out; } diff --git a/drivers/pwm/pwm_stm32.c b/drivers/pwm/pwm_stm32.c index 44f021a874d..ca989facd5d 100644 --- a/drivers/pwm/pwm_stm32.c +++ b/drivers/pwm/pwm_stm32.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2016 Linaro Limited. * Copyright (c) 2020 Teslabs Engineering S.L. + * Copyright (c) 2023 Nobleo Technology * * SPDX-License-Identifier: Apache-2.0 */ @@ -33,6 +34,22 @@ LOG_MODULE_REGISTER(pwm_stm32, CONFIG_PWM_LOG_LEVEL); #endif #ifdef CONFIG_PWM_CAPTURE + +/** + * @brief Capture state when in 4-channel support mode + */ +enum capture_state { + CAPTURE_STATE_IDLE = 0, + CAPTURE_STATE_WAIT_FOR_UPDATE_EVENT = 1, + CAPTURE_STATE_WAIT_FOR_PULSE_START = 2, + CAPTURE_STATE_WAIT_FOR_PERIOD_END = 3 +}; + +/** Return the complimentary channel number + * that is used to capture the end of the pulse. + */ +static const uint32_t complimentary_channel[] = {0, 2, 1, 4, 3}; + struct pwm_stm32_capture_data { pwm_capture_callback_handler_t callback; void *user_data; @@ -43,9 +60,16 @@ struct pwm_stm32_capture_data { bool capture_period; bool capture_pulse; bool continuous; + uint8_t channel; + + /* only used when four_channel_capture_support */ + enum capture_state state; }; -/* first capture is always nonsense, second is nonsense when polarity changed */ +/* When PWM capture is done by resetting the counter with UIF then the + * first capture is always nonsense, second is nonsense when polarity changed + * This is not the case when using four-channel-support. + */ #define SKIPPED_PWM_CAPTURES 2u #endif /*CONFIG_PWM_CAPTURE*/ @@ -70,6 +94,7 @@ struct pwm_stm32_config { const struct pinctrl_dev_config *pcfg; #ifdef CONFIG_PWM_CAPTURE void (*irq_config_func)(const struct device *dev); + const bool four_channel_capture_support; #endif /* CONFIG_PWM_CAPTURE */ }; @@ -115,6 +140,51 @@ static void (*const set_timer_compare[TIMER_MAX_CH])(TIM_TypeDef *, #endif }; +/** Channel to capture get function mapping. */ +#if !defined(CONFIG_SOC_SERIES_STM32F1X) && \ + !defined(CONFIG_SOC_SERIES_STM32F4X) && \ + !defined(CONFIG_SOC_SERIES_STM32G4X) && \ + !defined(CONFIG_SOC_SERIES_STM32MP1X) +static uint32_t __maybe_unused (*const get_channel_capture[])(const TIM_TypeDef *) = { +#else +static uint32_t __maybe_unused (*const get_channel_capture[])(TIM_TypeDef *) = { +#endif + LL_TIM_IC_GetCaptureCH1, LL_TIM_IC_GetCaptureCH2, + LL_TIM_IC_GetCaptureCH3, LL_TIM_IC_GetCaptureCH4 +}; + + +/** Channel to enable capture interrupt mapping. */ +static void __maybe_unused (*const enable_capture_interrupt[])(TIM_TypeDef *) = { + LL_TIM_EnableIT_CC1, LL_TIM_EnableIT_CC2, + LL_TIM_EnableIT_CC3, LL_TIM_EnableIT_CC4 +}; + +/** Channel to disable capture interrupt mapping. */ +static void __maybe_unused (*const disable_capture_interrupt[])(TIM_TypeDef *) = { + LL_TIM_DisableIT_CC1, LL_TIM_DisableIT_CC2, + LL_TIM_DisableIT_CC3, LL_TIM_DisableIT_CC4 +}; + +/** Channel to is capture active flag mapping. */ +#if !defined(CONFIG_SOC_SERIES_STM32F1X) && \ + !defined(CONFIG_SOC_SERIES_STM32F4X) && \ + !defined(CONFIG_SOC_SERIES_STM32G4X) && \ + !defined(CONFIG_SOC_SERIES_STM32MP1X) +static uint32_t __maybe_unused (*const is_capture_active[])(const TIM_TypeDef *) = { +#else +static uint32_t __maybe_unused (*const is_capture_active[])(TIM_TypeDef *) = { +#endif + LL_TIM_IsActiveFlag_CC1, LL_TIM_IsActiveFlag_CC2, + LL_TIM_IsActiveFlag_CC3, LL_TIM_IsActiveFlag_CC4 +}; + +/** Channel to clearing capture flag mapping. */ +static void __maybe_unused (*const clear_capture_interrupt[])(TIM_TypeDef *) = { + LL_TIM_ClearFlag_CC1, LL_TIM_ClearFlag_CC2, + LL_TIM_ClearFlag_CC3, LL_TIM_ClearFlag_CC4 +}; + /** * Obtain LL polarity from PWM flags. * @@ -270,12 +340,10 @@ static int pwm_stm32_set_cycles(const struct device *dev, uint32_t channel, } #ifdef CONFIG_PWM_CAPTURE - if ((channel == 1u) || (channel == 2u)) { - if (LL_TIM_IsEnabledIT_CC1(cfg->timer) || - LL_TIM_IsEnabledIT_CC2(cfg->timer)) { - LOG_ERR("Cannot set PWM output, capture in progress"); - return -EBUSY; - } + if (LL_TIM_IsEnabledIT_CC1(cfg->timer) || LL_TIM_IsEnabledIT_CC2(cfg->timer) || + LL_TIM_IsEnabledIT_CC3(cfg->timer) || LL_TIM_IsEnabledIT_CC4(cfg->timer)) { + LOG_ERR("Cannot set PWM output, capture in progress"); + return -EBUSY; } #endif /* CONFIG_PWM_CAPTURE */ @@ -391,8 +459,8 @@ static int pwm_stm32_set_cycles(const struct device *dev, uint32_t channel, } #ifdef CONFIG_PWM_CAPTURE -static int init_capture_channel(const struct device *dev, uint32_t channel, - pwm_flags_t flags, uint32_t ll_channel) +static int init_capture_channels(const struct device *dev, uint32_t channel, + pwm_flags_t flags) { const struct pwm_stm32_config *cfg = dev->config; bool is_inverted = (flags & PWM_POLARITY_MASK) == PWM_POLARITY_INVERTED; @@ -402,30 +470,21 @@ static int init_capture_channel(const struct device *dev, uint32_t channel, ic.ICPrescaler = TIM_ICPSC_DIV1; ic.ICFilter = LL_TIM_IC_FILTER_FDIV1; - if (ll_channel == LL_TIM_CHANNEL_CH1) { - if (channel == 1u) { - ic.ICActiveInput = LL_TIM_ACTIVEINPUT_DIRECTTI; - ic.ICPolarity = is_inverted ? LL_TIM_IC_POLARITY_FALLING - : LL_TIM_IC_POLARITY_RISING; - } else { - ic.ICActiveInput = LL_TIM_ACTIVEINPUT_INDIRECTTI; - ic.ICPolarity = is_inverted ? LL_TIM_IC_POLARITY_RISING - : LL_TIM_IC_POLARITY_FALLING; - } - } else { - if (channel == 1u) { - ic.ICActiveInput = LL_TIM_ACTIVEINPUT_INDIRECTTI; - ic.ICPolarity = is_inverted ? LL_TIM_IC_POLARITY_RISING - : LL_TIM_IC_POLARITY_FALLING; - } else { - ic.ICActiveInput = LL_TIM_ACTIVEINPUT_DIRECTTI; - ic.ICPolarity = is_inverted ? LL_TIM_IC_POLARITY_FALLING - : LL_TIM_IC_POLARITY_RISING; - } + /* Setup main channel */ + ic.ICActiveInput = LL_TIM_ACTIVEINPUT_DIRECTTI; + ic.ICPolarity = is_inverted ? LL_TIM_IC_POLARITY_FALLING : LL_TIM_IC_POLARITY_RISING; + + if (LL_TIM_IC_Init(cfg->timer, ch2ll[channel - 1], &ic) != SUCCESS) { + LOG_ERR("Could not initialize main channel for PWM capture"); + return -EIO; } - if (LL_TIM_IC_Init(cfg->timer, ll_channel, &ic) != SUCCESS) { - LOG_ERR("Could not initialize channel for PWM capture"); + /* Setup complimentary channel */ + ic.ICActiveInput = LL_TIM_ACTIVEINPUT_INDIRECTTI; + ic.ICPolarity = is_inverted ? LL_TIM_IC_POLARITY_RISING : LL_TIM_IC_POLARITY_FALLING; + + if (LL_TIM_IC_Init(cfg->timer, ch2ll[complimentary_channel[channel] - 1], &ic) != SUCCESS) { + LOG_ERR("Could not initialize complimentary channel for PWM capture"); return -EIO; } @@ -437,12 +496,17 @@ static int pwm_stm32_configure_capture(const struct device *dev, pwm_capture_callback_handler_t cb, void *user_data) { - /* - * Capture is implemented using the slave mode controller. - * This allows for high accuracy, but only CH1 and CH2 are supported. - * Alternatively all channels could be supported with ISR based resets. - * This is currently not implemented! + * Capture is implemented in two different ways, depending on the + * four-channel-capture-support setting in the node. + * - Two Channel Support: + * Only two channels (1 and 2) are available for capture. It uses + * the slave mode controller to reset the counter on each edge. + * - Four Channel Support: + * All four channels are available for capture. Instead of the + * slave mode controller it uses the ISR to reset the counter. + * This is slightly less accurate, but still within acceptable + * bounds. */ const struct pwm_stm32_config *cfg = dev->config; @@ -450,14 +514,21 @@ static int pwm_stm32_configure_capture(const struct device *dev, struct pwm_stm32_capture_data *cpt = &data->capture; int ret; - if ((channel != 1u) && (channel != 2u)) { - LOG_ERR("PWM capture only supported on first two channels"); - return -ENOTSUP; + if (!cfg->four_channel_capture_support) { + if ((channel != 1u) && (channel != 2u)) { + LOG_ERR("PWM capture only supported on first two channels"); + return -ENOTSUP; + } + } else { + if ((channel < 1u) || (channel > 4u)) { + LOG_ERR("PWM capture only exists on channels 1, 2, 3 and 4."); + return -ENOTSUP; + } } - if (LL_TIM_IsEnabledIT_CC1(cfg->timer) - || LL_TIM_IsEnabledIT_CC2(cfg->timer)) { - LOG_ERR("PWM Capture already in progress"); + if (LL_TIM_IsEnabledIT_CC1(cfg->timer) || LL_TIM_IsEnabledIT_CC2(cfg->timer) || + LL_TIM_IsEnabledIT_CC3(cfg->timer) || LL_TIM_IsEnabledIT_CC4(cfg->timer)) { + LOG_ERR("PWM capture already in progress"); return -EBUSY; } @@ -466,7 +537,8 @@ static int pwm_stm32_configure_capture(const struct device *dev, return -EINVAL; } - if (!IS_TIM_SLAVE_INSTANCE(cfg->timer)) { + if (!cfg->four_channel_capture_support && !IS_TIM_SLAVE_INSTANCE(cfg->timer)) { + /* slave mode is only used when not in four channel mode */ LOG_ERR("Timer does not support slave mode for PWM capture"); return -ENOTSUP; } @@ -480,22 +552,19 @@ static int pwm_stm32_configure_capture(const struct device *dev, /* Prevents faulty behavior while making changes */ LL_TIM_SetSlaveMode(cfg->timer, LL_TIM_SLAVEMODE_DISABLED); - ret = init_capture_channel(dev, channel, flags, LL_TIM_CHANNEL_CH1); - if (ret < 0) { - return ret; - } - - ret = init_capture_channel(dev, channel, flags, LL_TIM_CHANNEL_CH2); + ret = init_capture_channels(dev, channel, flags); if (ret < 0) { return ret; } - if (channel == 1u) { - LL_TIM_SetTriggerInput(cfg->timer, LL_TIM_TS_TI1FP1); - } else { - LL_TIM_SetTriggerInput(cfg->timer, LL_TIM_TS_TI2FP2); + if (!cfg->four_channel_capture_support) { + if (channel == 1u) { + LL_TIM_SetTriggerInput(cfg->timer, LL_TIM_TS_TI1FP1); + } else { + LL_TIM_SetTriggerInput(cfg->timer, LL_TIM_TS_TI2FP2); + } + LL_TIM_SetSlaveMode(cfg->timer, LL_TIM_SLAVEMODE_RESET); } - LL_TIM_SetSlaveMode(cfg->timer, LL_TIM_SLAVEMODE_RESET); LL_TIM_EnableARRPreload(cfg->timer); if (!IS_TIM_32B_COUNTER_INSTANCE(cfg->timer)) { @@ -512,14 +581,22 @@ static int pwm_stm32_enable_capture(const struct device *dev, uint32_t channel) { const struct pwm_stm32_config *cfg = dev->config; struct pwm_stm32_data *data = dev->data; + struct pwm_stm32_capture_data *cpt = &data->capture; - if ((channel != 1u) && (channel != 2u)) { - LOG_ERR("PWM capture only supported on first two channels"); - return -EINVAL; + if (!cfg->four_channel_capture_support) { + if ((channel != 1u) && (channel != 2u)) { + LOG_ERR("PWM capture only supported on first two channels"); + return -ENOTSUP; + } + } else { + if ((channel < 1u) || (channel > 4u)) { + LOG_ERR("PWM capture only exists on channels 1, 2, 3 and 4."); + return -ENOTSUP; + } } - if (LL_TIM_IsEnabledIT_CC1(cfg->timer) - || LL_TIM_IsEnabledIT_CC2(cfg->timer)) { + if (LL_TIM_IsEnabledIT_CC1(cfg->timer) || LL_TIM_IsEnabledIT_CC2(cfg->timer) || + LL_TIM_IsEnabledIT_CC3(cfg->timer) || LL_TIM_IsEnabledIT_CC4(cfg->timer)) { LOG_ERR("PWM capture already active"); return -EBUSY; } @@ -529,21 +606,22 @@ static int pwm_stm32_enable_capture(const struct device *dev, uint32_t channel) return -EINVAL; } - data->capture.skip_irq = SKIPPED_PWM_CAPTURES; + cpt->channel = channel; + cpt->state = CAPTURE_STATE_WAIT_FOR_PULSE_START; + data->capture.skip_irq = cfg->four_channel_capture_support ? 0 : SKIPPED_PWM_CAPTURES; data->capture.overflows = 0u; - LL_TIM_ClearFlag_CC1(cfg->timer); - LL_TIM_ClearFlag_CC2(cfg->timer); + + clear_capture_interrupt[channel - 1](cfg->timer); LL_TIM_ClearFlag_UPDATE(cfg->timer); LL_TIM_SetUpdateSource(cfg->timer, LL_TIM_UPDATESOURCE_COUNTER); - if (channel == 1u) { - LL_TIM_EnableIT_CC1(cfg->timer); - } else { - LL_TIM_EnableIT_CC2(cfg->timer); - } + + enable_capture_interrupt[channel - 1](cfg->timer); + + LL_TIM_CC_EnableChannel(cfg->timer, ch2ll[channel - 1]); + LL_TIM_CC_EnableChannel(cfg->timer, ch2ll[complimentary_channel[channel] - 1]); LL_TIM_EnableIT_UPDATE(cfg->timer); - LL_TIM_CC_EnableChannel(cfg->timer, LL_TIM_CHANNEL_CH1); - LL_TIM_CC_EnableChannel(cfg->timer, LL_TIM_CHANNEL_CH2); + LL_TIM_GenerateEvent_UPDATE(cfg->timer); return 0; } @@ -552,37 +630,27 @@ static int pwm_stm32_disable_capture(const struct device *dev, uint32_t channel) { const struct pwm_stm32_config *cfg = dev->config; - if ((channel != 1u) && (channel != 2u)) { - LOG_ERR("PWM capture only supported on first two channels"); - return -EINVAL; + if (!cfg->four_channel_capture_support) { + if ((channel != 1u) && (channel != 2u)) { + LOG_ERR("PWM capture only supported on first two channels"); + return -ENOTSUP; + } + } else { + if ((channel < 1u) || (channel > 4u)) { + LOG_ERR("PWM capture only exists on channels 1, 2, 3 and 4."); + return -ENOTSUP; + } } LL_TIM_SetUpdateSource(cfg->timer, LL_TIM_UPDATESOURCE_REGULAR); - if (channel == 1u) { - LL_TIM_DisableIT_CC1(cfg->timer); - } else { - LL_TIM_DisableIT_CC2(cfg->timer); - } - LL_TIM_DisableIT_UPDATE(cfg->timer); - LL_TIM_CC_DisableChannel(cfg->timer, LL_TIM_CHANNEL_CH1); - LL_TIM_CC_DisableChannel(cfg->timer, LL_TIM_CHANNEL_CH2); - return 0; -} + disable_capture_interrupt[channel - 1](cfg->timer); -static void get_pwm_capture(const struct device *dev, uint32_t channel) -{ - const struct pwm_stm32_config *cfg = dev->config; - struct pwm_stm32_data *data = dev->data; - struct pwm_stm32_capture_data *cpt = &data->capture; + LL_TIM_DisableIT_UPDATE(cfg->timer); + LL_TIM_CC_DisableChannel(cfg->timer, ch2ll[channel - 1]); + LL_TIM_CC_DisableChannel(cfg->timer, ch2ll[complimentary_channel[channel] - 1]); - if (channel == 1u) { - cpt->period = LL_TIM_IC_GetCaptureCH1(cfg->timer); - cpt->pulse = LL_TIM_IC_GetCaptureCH2(cfg->timer); - } else { - cpt->period = LL_TIM_IC_GetCaptureCH2(cfg->timer); - cpt->pulse = LL_TIM_IC_GetCaptureCH1(cfg->timer); - } + return 0; } static void pwm_stm32_isr(const struct device *dev) @@ -591,52 +659,101 @@ static void pwm_stm32_isr(const struct device *dev) struct pwm_stm32_data *data = dev->data; struct pwm_stm32_capture_data *cpt = &data->capture; int status = 0; - uint32_t in_ch = LL_TIM_IsEnabledIT_CC1(cfg->timer) ? 1u : 2u; - if (cpt->skip_irq == 0u) { + if (cpt->skip_irq != 0u) { if (LL_TIM_IsActiveFlag_UPDATE(cfg->timer)) { LL_TIM_ClearFlag_UPDATE(cfg->timer); - cpt->overflows++; } if (LL_TIM_IsActiveFlag_CC1(cfg->timer) - || LL_TIM_IsActiveFlag_CC2(cfg->timer)) { + || LL_TIM_IsActiveFlag_CC2(cfg->timer) + || LL_TIM_IsActiveFlag_CC3(cfg->timer) + || LL_TIM_IsActiveFlag_CC4(cfg->timer)) { LL_TIM_ClearFlag_CC1(cfg->timer); LL_TIM_ClearFlag_CC2(cfg->timer); + LL_TIM_ClearFlag_CC3(cfg->timer); + LL_TIM_ClearFlag_CC4(cfg->timer); + cpt->skip_irq--; + } - get_pwm_capture(dev, in_ch); + return; + } - if (cpt->overflows) { - LOG_ERR("counter overflow during PWM capture"); - status = -ERANGE; - } + if (LL_TIM_IsActiveFlag_UPDATE(cfg->timer)) { + LL_TIM_ClearFlag_UPDATE(cfg->timer); + if (cfg->four_channel_capture_support && + cpt->state == CAPTURE_STATE_WAIT_FOR_UPDATE_EVENT) { + /* Special handling of UPDATE event in case it's triggered */ + cpt->state = CAPTURE_STATE_WAIT_FOR_PERIOD_END; + } else { + cpt->overflows++; + } + } - if (!cpt->continuous) { - pwm_stm32_disable_capture(dev, in_ch); - } else { - cpt->overflows = 0u; - } + if (!cfg->four_channel_capture_support) { + if (is_capture_active[cpt->channel - 1](cfg->timer) || + is_capture_active[complimentary_channel[cpt->channel] - 1](cfg->timer)) { + clear_capture_interrupt[cpt->channel - 1](cfg->timer); + clear_capture_interrupt + [complimentary_channel[cpt->channel] - 1](cfg->timer); - if (cpt->callback != NULL) { - cpt->callback(dev, in_ch, - cpt->capture_period ? cpt->period : 0u, - cpt->capture_pulse ? cpt->pulse : 0u, - status, cpt->user_data); - } + cpt->period = get_channel_capture[cpt->channel - 1](cfg->timer); + cpt->pulse = get_channel_capture + [complimentary_channel[cpt->channel] - 1](cfg->timer); } } else { - if (LL_TIM_IsActiveFlag_UPDATE(cfg->timer)) { - LL_TIM_ClearFlag_UPDATE(cfg->timer); + if (cpt->state == CAPTURE_STATE_WAIT_FOR_PULSE_START && + is_capture_active[cpt->channel - 1](cfg->timer)) { + /* Reset the counter manually instead of automatically by HW + * This sets the pulse-start at 0 and makes the pulse-end + * and period related to that number. Sure we loose some + * accuracy but it's within acceptable range. + * + * This is done through an UPDATE event to also reset + * the prescalar. This could look like an overflow event + * and might therefore require special handling. + */ + cpt->state = CAPTURE_STATE_WAIT_FOR_UPDATE_EVENT; + LL_TIM_GenerateEvent_UPDATE(cfg->timer); + + } else if ((cpt->state == CAPTURE_STATE_WAIT_FOR_UPDATE_EVENT || + cpt->state == CAPTURE_STATE_WAIT_FOR_PERIOD_END) && + is_capture_active[cpt->channel - 1](cfg->timer)) { + cpt->state = CAPTURE_STATE_IDLE; + /* The end of the period. Both capture channels should now contain + * the timer value when the pulse and period ended respectively. + */ + cpt->pulse = get_channel_capture[complimentary_channel[cpt->channel] - 1] + (cfg->timer); + cpt->period = get_channel_capture[cpt->channel - 1](cfg->timer); } - if (LL_TIM_IsActiveFlag_CC1(cfg->timer) - || LL_TIM_IsActiveFlag_CC2(cfg->timer)) { - LL_TIM_ClearFlag_CC1(cfg->timer); - LL_TIM_ClearFlag_CC2(cfg->timer); - cpt->skip_irq--; + clear_capture_interrupt[cpt->channel - 1](cfg->timer); + + if (cpt->state != CAPTURE_STATE_IDLE) { + /* Still waiting for a complete capture */ + return; + } + + if (cpt->overflows) { + LOG_ERR("counter overflow during PWM capture"); + status = -ERANGE; } } + + if (!cpt->continuous) { + pwm_stm32_disable_capture(dev, cpt->channel); + } else { + cpt->overflows = 0u; + cpt->state = CAPTURE_STATE_WAIT_FOR_PULSE_START; + } + + if (cpt->callback != NULL) { + cpt->callback(dev, cpt->channel, cpt->capture_period ? cpt->period : 0u, + cpt->capture_pulse ? cpt->pulse : 0u, status, cpt->user_data); + } } + #endif /* CONFIG_PWM_CAPTURE */ static int pwm_stm32_get_cycles_per_sec(const struct device *dev, @@ -755,8 +872,9 @@ static void pwm_stm32_irq_config_func_##index(const struct device *dev) \ (IRQ_CONNECT_AND_ENABLE_DEFAULT(index)) \ ); \ } -#define CAPTURE_INIT(index) \ - .irq_config_func = pwm_stm32_irq_config_func_##index +#define CAPTURE_INIT(index) \ + .irq_config_func = pwm_stm32_irq_config_func_##index, \ + .four_channel_capture_support = DT_INST_PROP(index, four_channel_capture_support) #else #define IRQ_CONFIG_FUNC(index) #define CAPTURE_INIT(index) diff --git a/drivers/regulator/CMakeLists.txt b/drivers/regulator/CMakeLists.txt index 972618db12d..94c3a032aff 100644 --- a/drivers/regulator/CMakeLists.txt +++ b/drivers/regulator/CMakeLists.txt @@ -9,9 +9,11 @@ zephyr_library_sources_ifdef(CONFIG_REGULATOR_ADP5360 regulator_adp5360.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_FAKE regulator_fake.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_FIXED regulator_fixed.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_GPIO regulator_gpio.c) +zephyr_library_sources_ifdef(CONFIG_REGULATOR_MAX20335 regulator_max20335.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_NPM1100 regulator_npm1100.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_NPM1300 regulator_npm1300.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_NPM6001 regulator_npm6001.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_PCA9420 regulator_pca9420.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_SHELL regulator_shell.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_RPI_PICO regulator_rpi_pico.c) +zephyr_library_sources_ifdef(CONFIG_REGULATOR_NXP_VREF regulator_nxp_vref.c) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 94998fb6191..c35ae389669 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -17,7 +17,6 @@ config REGULATOR_THREAD_SAFE_REFCNT config REGULATOR_SHELL bool "Regulator shell" - default y depends on SHELL help Enable regulator shell framework, for interacting with regulators via @@ -32,10 +31,12 @@ source "drivers/regulator/Kconfig.adp5360" source "drivers/regulator/Kconfig.fake" source "drivers/regulator/Kconfig.fixed" source "drivers/regulator/Kconfig.gpio" +source "drivers/regulator/Kconfig.max20335" source "drivers/regulator/Kconfig.npm1100" source "drivers/regulator/Kconfig.npm1300" source "drivers/regulator/Kconfig.npm6001" source "drivers/regulator/Kconfig.pca9420" source "drivers/regulator/Kconfig.rpi_pico" +source "drivers/regulator/Kconfig.nxp_vref" endif # REGULATOR diff --git a/drivers/regulator/Kconfig.axp192 b/drivers/regulator/Kconfig.axp192 index c2ec403359e..8c8fad5cdb4 100644 --- a/drivers/regulator/Kconfig.axp192 +++ b/drivers/regulator/Kconfig.axp192 @@ -15,7 +15,7 @@ if REGULATOR_AXP192 config REGULATOR_AXP192_INIT_PRIORITY int "AXP192 regulator driver init priority" - default 76 + default 86 help Init priority for the axp192 regulator driver. It must be greater than MFD_INIT_PRIORITY. diff --git a/drivers/regulator/Kconfig.max20335 b/drivers/regulator/Kconfig.max20335 new file mode 100644 index 00000000000..a9b739e1f2c --- /dev/null +++ b/drivers/regulator/Kconfig.max20335 @@ -0,0 +1,18 @@ +# Copyright (c) 2023 Grinn +# SPDX -License-Identifier: Apache-2.0 + +config REGULATOR_MAX20335 + bool "MAX20335 PMIC regulator driver" + default y + depends on DT_HAS_MAXIM_MAX20335_REGULATOR_ENABLED + select I2C + select MFD + help + Enable the Maxim MAX20335 PMIC regulator driver + +config REGULATOR_MAXIM_MAX20335_INIT_PRIORITY + int "MAX20335 regulator driver init priority" + default 86 + depends on REGULATOR_MAX20335 + help + Init priority for the Maxim MAX20335 regulator driver. diff --git a/drivers/regulator/Kconfig.npm1300 b/drivers/regulator/Kconfig.npm1300 index a003f90f7a9..997934cabb7 100644 --- a/drivers/regulator/Kconfig.npm1300 +++ b/drivers/regulator/Kconfig.npm1300 @@ -14,14 +14,14 @@ if REGULATOR_NPM1300 config REGULATOR_NPM1300_COMMON_INIT_PRIORITY int "nPM1300 regulator driver init priority (common part)" - default 75 + default 85 help Init priority for the Nordic nPM1300 regulator driver (common part). It must be greater than I2C init priority. config REGULATOR_NPM1300_INIT_PRIORITY int "nPM1300 regulator driver init priority" - default 76 + default 86 help Init priority for the Nordic nPM1300 regulator driver. It must be greater than REGULATOR_NPM1300_COMMON_INIT_PRIORITY. diff --git a/drivers/regulator/Kconfig.npm6001 b/drivers/regulator/Kconfig.npm6001 index d4e361876ae..a9c290475de 100644 --- a/drivers/regulator/Kconfig.npm6001 +++ b/drivers/regulator/Kconfig.npm6001 @@ -12,7 +12,7 @@ config REGULATOR_NPM6001 config REGULATOR_NPM6001_INIT_PRIORITY int "nPM6001 regulator driver init priority" - default 76 + default 86 depends on REGULATOR_NPM6001 help Init priority for the Nordic nPM6001 regulator driver. diff --git a/drivers/regulator/Kconfig.nxp_vref b/drivers/regulator/Kconfig.nxp_vref new file mode 100644 index 00000000000..4c9bc54fd13 --- /dev/null +++ b/drivers/regulator/Kconfig.nxp_vref @@ -0,0 +1,14 @@ +# Copyright 2023 NXP +# SPDX -License-Identifier: Apache-2.0 + +config REGULATOR_NXP_VREF + bool "NXP VREF peripheral driver" + default y if DT_HAS_NXP_VREF_ENABLED + help + Enable the NXP VREF driver + +config REGULATOR_NXP_VREF_INIT_PRIORITY + int "NXP VREF peripheral driver init priority" + default 45 + help + Init priority for the NXP VREF peripheral. diff --git a/drivers/regulator/regulator_common.c b/drivers/regulator/regulator_common.c index adbacddac12..7f33040d2d9 100644 --- a/drivers/regulator/regulator_common.c +++ b/drivers/regulator/regulator_common.c @@ -3,8 +3,20 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include +static void regulator_delay(uint32_t delay_us) +{ + if (delay_us > 0U) { +#ifdef CONFIG_MULTITHREADING + k_sleep(K_USEC(delay_us)); +#else + k_busy_wait(delay_us); +#endif + } +} + void regulator_common_data_init(const struct device *dev) { struct regulator_common_data *data = dev->data; @@ -67,6 +79,7 @@ int regulator_common_init(const struct device *dev, bool is_enabled) return ret; } + regulator_delay(config->startup_delay_us); data->refcnt++; } @@ -94,12 +107,11 @@ int regulator_enable(const struct device *dev) (void)k_mutex_lock(&data->lock, K_FOREVER); #endif - data->refcnt++; - - if (data->refcnt == 1) { + if (data->refcnt == 0) { ret = api->enable(dev); - if (ret < 0) { - data->refcnt--; + if (ret == 0) { + data->refcnt++; + regulator_delay(config->off_on_delay_us); } } diff --git a/drivers/regulator/regulator_fixed.c b/drivers/regulator/regulator_fixed.c index 390f925cde6..c0b58273987 100644 --- a/drivers/regulator/regulator_fixed.c +++ b/drivers/regulator/regulator_fixed.c @@ -9,7 +9,6 @@ #include -#include #include #include #include @@ -18,8 +17,6 @@ LOG_MODULE_REGISTER(regulator_fixed, CONFIG_REGULATOR_LOG_LEVEL); struct regulator_fixed_config { struct regulator_common_config common; - uint32_t startup_delay_us; - uint32_t off_on_delay_us; struct gpio_dt_spec enable; }; @@ -41,10 +38,6 @@ static int regulator_fixed_enable(const struct device *dev) return ret; } - if (cfg->off_on_delay_us > 0U) { - k_sleep(K_USEC(cfg->off_on_delay_us)); - } - return 0; } @@ -109,8 +102,6 @@ static int regulator_fixed_init(const struct device *dev) if (ret < 0) { return ret; } - - k_busy_wait(cfg->startup_delay_us); } else { ret = gpio_pin_configure_dt(&cfg->enable, GPIO_OUTPUT_INACTIVE); if (ret < 0) { @@ -130,8 +121,6 @@ static int regulator_fixed_init(const struct device *dev) \ static const struct regulator_fixed_config config##inst = { \ .common = REGULATOR_DT_INST_COMMON_CONFIG_INIT(inst), \ - .startup_delay_us = DT_INST_PROP(inst, startup_delay_us), \ - .off_on_delay_us = DT_INST_PROP(inst, off_on_delay_us), \ .enable = GPIO_DT_SPEC_INST_GET_OR(inst, enable_gpios, {0}), \ }; \ \ diff --git a/drivers/regulator/regulator_gpio.c b/drivers/regulator/regulator_gpio.c index 93d6ebddff8..49d373897b3 100644 --- a/drivers/regulator/regulator_gpio.c +++ b/drivers/regulator/regulator_gpio.c @@ -7,7 +7,6 @@ #include -#include #include #include #include @@ -24,7 +23,6 @@ struct regulator_gpio_config { uint8_t states_cnt; const struct gpio_dt_spec enable; - int32_t startup_delay_us; }; struct regulator_gpio_data { @@ -73,10 +71,6 @@ static int regulator_gpio_enable(const struct device *dev) return ret; } - if (cfg->startup_delay_us > 0U) { - k_sleep(K_USEC(cfg->startup_delay_us)); - } - return 0; } @@ -229,7 +223,6 @@ static int regulator_gpio_init(const struct device *dev) .enable = GPIO_DT_SPEC_INST_GET_OR(inst, enable_gpios, {0}), \ .states = ((const int[])DT_INST_PROP(inst, states)), \ .states_cnt = DT_INST_PROP_LEN(inst, states) / 2, \ - .startup_delay_us = DT_INST_PROP_OR(inst, startup_delay_us, 0), \ }; \ DEVICE_DT_INST_DEFINE(inst, regulator_gpio_init, NULL, &data##inst, &config##inst, \ POST_KERNEL, CONFIG_REGULATOR_GPIO_INIT_PRIORITY, \ diff --git a/drivers/regulator/regulator_max20335.c b/drivers/regulator/regulator_max20335.c new file mode 100644 index 00000000000..5395c1de699 --- /dev/null +++ b/drivers/regulator/regulator_max20335.c @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2023 Grinn + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT maxim_max20335_regulator + +#include +#include +#include +#include +#include + +#define MAX20335_BUCK1_CFG 0x0DU +#define MAX20335_BUCK1_VSET 0x0EU +#define MAX20335_BUCK2_CFG 0x0FU +#define MAX20335_BUCK2_VSET 0x10U +#define MAX20335_BUCK12_CSET 0x11U +#define MAX20335_BUCK1_CSET_MASK 0xF0U +#define MAX20335_BUCK2_CSET_MASK 0x0FU +#define MAX20335_BUCK2_CSET_SHIFT 4 +#define MAX20335_BUCK_EN BIT(3) +#define MAX20335_BUCK_EN_MASK GENMASK(4, 3) + +#define MAX20335_LDO1_CFG 0x12U +#define MAX20335_LDO1_VSET 0x13U +#define MAX20335_LDO2_CFG 0x14U +#define MAX20335_LDO2_VSET 0x15U +#define MAX20335_LDO3_CFG 0x16U +#define MAX20335_LDO3_VSET 0x17U +#define MAX20335_LDO_MODE_MASK BIT(0) +#define MAX20335_LDO_EN BIT(1) +#define MAX20335_LDO_EN_MASK GENMASK(2, 1) + +enum max20335_pmic_sources { + MAX20335_PMIC_SOURCE_BUCK1, + MAX20335_PMIC_SOURCE_BUCK2, + MAX20335_PMIC_SOURCE_LDO1, + MAX20335_PMIC_SOURCE_LDO2, + MAX20335_PMIC_SOURCE_LDO3, +}; + +struct regulator_max20335_desc { + uint8_t vsel_reg; + uint8_t enable_mask; + uint8_t enable_val; + uint8_t cfg_reg; + const struct linear_range *uv_range; + const struct linear_range *ua_range; +}; + +struct regulator_max20335_config { + struct regulator_common_config common; + struct i2c_dt_spec bus; + const struct regulator_max20335_desc *desc; + uint8_t source; +}; + +struct regulator_max20335_data { + struct regulator_common_data common; +}; + +static const struct linear_range buck1_range = LINEAR_RANGE_INIT(700000, 25000U, 0x0U, 0x3FU); +static const struct linear_range buck2_range = LINEAR_RANGE_INIT(700000, 50000U, 0x0U, 0x3FU); +static const struct linear_range buck12_current_limit_range = + LINEAR_RANGE_INIT(50000, 25000U, 0x02U, 0x0FU); +static const struct linear_range ldo1_range = LINEAR_RANGE_INIT(800000, 100000U, 0x0U, 0x1CU); +static const struct linear_range ldo23_range = LINEAR_RANGE_INIT(900000, 100000U, 0x0U, 0x1FU); + +static const struct regulator_max20335_desc buck1_desc = { + .vsel_reg = MAX20335_BUCK1_VSET, + .enable_mask = MAX20335_BUCK_EN_MASK, + .enable_val = MAX20335_BUCK_EN, + .cfg_reg = MAX20335_BUCK1_CFG, + .uv_range = &buck1_range, + .ua_range = &buck12_current_limit_range, +}; + +static const struct regulator_max20335_desc buck2_desc = { + .vsel_reg = MAX20335_BUCK2_VSET, + .enable_mask = MAX20335_BUCK_EN_MASK, + .enable_val = MAX20335_BUCK_EN, + .cfg_reg = MAX20335_BUCK2_CFG, + .uv_range = &buck2_range, + .ua_range = &buck12_current_limit_range, +}; + +static const struct regulator_max20335_desc ldo1_desc = { + .vsel_reg = MAX20335_LDO1_VSET, + .enable_mask = MAX20335_LDO_EN_MASK, + .enable_val = MAX20335_LDO_EN, + .cfg_reg = MAX20335_LDO1_CFG, + .uv_range = &ldo1_range, +}; + +static const struct regulator_max20335_desc ldo2_desc = { + .vsel_reg = MAX20335_LDO2_VSET, + .enable_mask = MAX20335_LDO_EN_MASK, + .enable_val = MAX20335_LDO_EN, + .cfg_reg = MAX20335_LDO2_CFG, + .uv_range = &ldo23_range, +}; + +static const struct regulator_max20335_desc ldo3_desc = { + .vsel_reg = MAX20335_LDO3_VSET, + .enable_mask = MAX20335_LDO_EN_MASK, + .enable_val = MAX20335_LDO_EN, + .cfg_reg = MAX20335_LDO3_CFG, + .uv_range = &ldo23_range, +}; + +static int regulator_max20335_set_enable(const struct device *dev, bool enable) +{ + const struct regulator_max20335_config *config = dev->config; + + return i2c_reg_update_byte_dt(&config->bus, + config->desc->cfg_reg, + config->desc->enable_mask, + enable ? config->desc->enable_val : 0); +} + +static int regulator_max20335_enable(const struct device *dev) +{ + return regulator_max20335_set_enable(dev, true); +} + +static int regulator_max20335_disable(const struct device *dev) +{ + return regulator_max20335_set_enable(dev, false); +} + +static int regulator_max20335_set_mode(const struct device *dev, regulator_mode_t mode) +{ + const struct regulator_max20335_config *config = dev->config; + + if (mode > MAX20335_LOAD_SWITCH_MODE) { + return -ENOTSUP; + } + + switch (config->source) { + case MAX20335_PMIC_SOURCE_LDO1: + __fallthrough; + case MAX20335_PMIC_SOURCE_LDO2: + __fallthrough; + case MAX20335_PMIC_SOURCE_LDO3: + return i2c_reg_update_byte_dt(&config->bus, + config->desc->cfg_reg, + MAX20335_LDO_MODE_MASK, + mode); + default: + return -ENOTSUP; + } +} + +static unsigned int regulator_max20335_count_voltages(const struct device *dev) +{ + const struct regulator_max20335_config *config = dev->config; + + return linear_range_values_count(config->desc->uv_range); +} + +static int regulator_max20335_list_voltage(const struct device *dev, unsigned int idx, + int32_t *volt_uv) +{ + const struct regulator_max20335_config *config = dev->config; + + return linear_range_get_value(config->desc->uv_range, idx, volt_uv); +} + +static int regulator_max20335_set_buck_ldo_voltage(const struct device *dev, int32_t min_uv, + int32_t max_uv, const struct linear_range *range, + uint8_t vout_reg) +{ + const struct regulator_max20335_config *config = dev->config; + uint16_t idx; + int ret; + + ret = linear_range_get_win_index(range, min_uv, max_uv, &idx); + if (ret == -EINVAL) { + return ret; + } + + return i2c_reg_write_byte_dt(&config->bus, vout_reg, (uint8_t)idx); +} + +static int regulator_max20335_buck12_ldo123_get_voltage(const struct device *dev, + const struct linear_range *range, + uint8_t vout_reg, int32_t *volt_uv) +{ + const struct regulator_max20335_config *config = dev->config; + uint8_t idx; + int ret; + + ret = i2c_reg_read_byte_dt(&config->bus, vout_reg, &idx); + if (ret < 0) { + return ret; + } + + return linear_range_get_value(range, idx, volt_uv); +} + +static int regulator_max20335_get_voltage(const struct device *dev, int32_t *volt_uv) +{ + const struct regulator_max20335_config *config = dev->config; + + return regulator_max20335_buck12_ldo123_get_voltage(dev, + config->desc->uv_range, + config->desc->vsel_reg, + volt_uv); +} + +static int regulator_max20335_set_voltage(const struct device *dev, int32_t min_uv, int32_t max_uv) +{ + const struct regulator_max20335_config *config = dev->config; + + return regulator_max20335_set_buck_ldo_voltage(dev, + min_uv, + max_uv, + config->desc->uv_range, + config->desc->vsel_reg); +} + +static unsigned int regulator_max20335_count_current_limits(const struct device *dev) +{ + const struct regulator_max20335_config *config = dev->config; + + return linear_range_values_count(config->desc->ua_range); +} + +static int regulator_max20335_list_current_limit(const struct device *dev, unsigned int idx, + int32_t *current_ua) +{ + const struct regulator_max20335_config *config = dev->config; + + return linear_range_get_value(config->desc->ua_range, idx, current_ua); +} + +static int regulator_max20335_set_current_limit(const struct device *dev, + int32_t min_ua, + int32_t max_ua) +{ + const struct regulator_max20335_config *config = dev->config; + uint8_t val; + uint16_t idx; + int ret; + + ret = i2c_reg_read_byte_dt(&config->bus, MAX20335_BUCK12_CSET, &val); + if (ret < 0) { + return ret; + } + + ret = linear_range_get_win_index(config->desc->ua_range, min_ua, max_ua, &idx); + if (ret == -EINVAL) { + return ret; + } + + switch (config->source) { + case MAX20335_PMIC_SOURCE_BUCK1: + val = idx | (val & MAX20335_BUCK1_CSET_MASK); + break; + case MAX20335_PMIC_SOURCE_BUCK2: + val = (idx << MAX20335_BUCK2_CSET_SHIFT) | (val & MAX20335_BUCK2_CSET_MASK); + break; + default: + return -ENOTSUP; + } + + return i2c_reg_write_byte_dt(&config->bus, MAX20335_BUCK12_CSET, val); +} + +static int regulator_max20335_init(const struct device *dev) +{ + const struct regulator_max20335_config *config = dev->config; + + if (!i2c_is_ready_dt(&config->bus)) { + return -ENODEV; + } + + regulator_common_data_init(dev); + + return regulator_common_init(dev, false); +} + +static const struct regulator_driver_api api = { + .enable = regulator_max20335_enable, + .disable = regulator_max20335_disable, + .set_mode = regulator_max20335_set_mode, + .count_voltages = regulator_max20335_count_voltages, + .list_voltage = regulator_max20335_list_voltage, + .set_voltage = regulator_max20335_set_voltage, + .get_voltage = regulator_max20335_get_voltage, + .count_current_limits = regulator_max20335_count_current_limits, + .list_current_limit = regulator_max20335_list_current_limit, + .set_current_limit = regulator_max20335_set_current_limit, +}; + +#define REGULATOR_MAX20335_DEFINE(node_id, id, child_name, _source) \ + static const struct regulator_max20335_config regulator_max20335_config_##id = { \ + .common = REGULATOR_DT_COMMON_CONFIG_INIT(node_id), \ + .bus = I2C_DT_SPEC_GET(DT_GPARENT(node_id)), \ + .desc = &child_name##_desc, \ + .source = _source, \ + }; \ + \ + static struct regulator_max20335_data regulator_max20335_data_##id; \ + DEVICE_DT_DEFINE(node_id, regulator_max20335_init, NULL, \ + ®ulator_max20335_data_##id, \ + ®ulator_max20335_config_##id, \ + POST_KERNEL, \ + CONFIG_REGULATOR_MAXIM_MAX20335_INIT_PRIORITY, \ + &api); + +#define REGULATOR_MAX20335_DEFINE_COND(inst, child, source) \ + COND_CODE_1(DT_NODE_EXISTS(DT_INST_CHILD(inst, child)), \ + (REGULATOR_MAX20335_DEFINE(DT_INST_CHILD(inst, child), \ + child##inst, child, source)), \ + ()) + +#define REGULATOR_MAX20335_DEFINE_ALL(inst) \ + REGULATOR_MAX20335_DEFINE_COND(inst, buck1, MAX20335_PMIC_SOURCE_BUCK1) \ + REGULATOR_MAX20335_DEFINE_COND(inst, buck2, MAX20335_PMIC_SOURCE_BUCK2) \ + REGULATOR_MAX20335_DEFINE_COND(inst, ldo1, MAX20335_PMIC_SOURCE_LDO1) \ + REGULATOR_MAX20335_DEFINE_COND(inst, ldo2, MAX20335_PMIC_SOURCE_LDO2) \ + REGULATOR_MAX20335_DEFINE_COND(inst, ldo3, MAX20335_PMIC_SOURCE_LDO3) + +DT_INST_FOREACH_STATUS_OKAY(REGULATOR_MAX20335_DEFINE_ALL); diff --git a/drivers/regulator/regulator_npm1300.c b/drivers/regulator/regulator_npm1300.c index ad52374466d..8adb2d3cb81 100644 --- a/drivers/regulator/regulator_npm1300.c +++ b/drivers/regulator/regulator_npm1300.c @@ -48,6 +48,7 @@ enum npm1300_gpio_type { #define BUCK_OFFSET_SW_CTRL 0x0FU #define BUCK_OFFSET_VOUT_STAT 0x10U #define BUCK_OFFSET_CTRL0 0x15U +#define BUCK_OFFSET_STATUS 0x34U /* nPM1300 ldsw register offsets */ #define LDSW_OFFSET_EN_SET 0x00U @@ -61,6 +62,17 @@ enum npm1300_gpio_type { /* nPM1300 ship register offsets */ #define SHIP_OFFSET_SHIP 0x02U +#define BUCK1_ON_MASK 0x04U +#define BUCK2_ON_MASK 0x40U + +#define LDSW1_ON_MASK 0x03U +#define LDSW2_ON_MASK 0x0CU + +#define LDSW1_SOFTSTART_MASK 0x0CU +#define LDSW1_SOFTSTART_SHIFT 2U +#define LDSW2_SOFTSTART_MASK 0x30U +#define LDSW2_SOFTSTART_SHIFT 4U + struct regulator_npm1300_pconfig { const struct device *mfd; struct gpio_dt_spec dvs_state_pins[5]; @@ -74,6 +86,7 @@ struct regulator_npm1300_config { struct gpio_dt_spec enable_gpios; struct gpio_dt_spec retention_gpios; struct gpio_dt_spec pwm_gpios; + uint8_t soft_start; }; struct regulator_npm1300_data { @@ -141,10 +154,33 @@ static int retention_set_voltage(const struct device *dev, int32_t retention_uv) idx); } +static int buck_get_voltage_index(const struct device *dev, uint8_t chan, uint8_t *idx) +{ + const struct regulator_npm1300_config *config = dev->config; + uint8_t sel; + int ret; + + ret = mfd_npm1300_reg_read(config->mfd, BUCK_BASE, BUCK_OFFSET_SW_CTRL, &sel); + + if (ret < 0) { + return ret; + } + + if ((sel >> chan) & 1U) { + /* SW control */ + return mfd_npm1300_reg_read(config->mfd, BUCK_BASE, + BUCK_OFFSET_VOUT_NORM + (chan * 2U), idx); + } + + /* VSET pin control */ + return mfd_npm1300_reg_read(config->mfd, BUCK_BASE, BUCK_OFFSET_VOUT_STAT + chan, idx); +} + static int buck_set_voltage(const struct device *dev, uint8_t chan, int32_t min_uv, int32_t max_uv) { const struct regulator_npm1300_config *config = dev->config; uint8_t mask; + uint8_t curr_idx; uint16_t idx; int ret; @@ -154,6 +190,13 @@ static int buck_set_voltage(const struct device *dev, uint8_t chan, int32_t min_ return ret; } + /* Get current setting, and return if current and new index match */ + ret = buck_get_voltage_index(dev, chan, &curr_idx); + + if ((ret < 0) || (idx == curr_idx)) { + return ret; + } + ret = mfd_npm1300_reg_write(config->mfd, BUCK_BASE, BUCK_OFFSET_VOUT_NORM + (chan * 2U), idx); @@ -201,26 +244,10 @@ int regulator_npm1300_set_voltage(const struct device *dev, int32_t min_uv, int3 static int buck_get_voltage(const struct device *dev, uint8_t chan, int32_t *volt_uv) { - const struct regulator_npm1300_config *config = dev->config; - uint8_t sel; uint8_t idx; int ret; - ret = mfd_npm1300_reg_read(config->mfd, BUCK_BASE, BUCK_OFFSET_SW_CTRL, &sel); - - if (ret < 0) { - return ret; - } - - if ((sel >> chan) & 1U) { - /* SW control */ - ret = mfd_npm1300_reg_read(config->mfd, BUCK_BASE, - BUCK_OFFSET_VOUT_NORM + (chan * 2U), &idx); - } else { - /* VSET pin control */ - ret = mfd_npm1300_reg_read(config->mfd, BUCK_BASE, BUCK_OFFSET_VOUT_STAT + chan, - &idx); - } + ret = buck_get_voltage_index(dev, chan, &idx); if (ret < 0) { return ret; @@ -265,17 +292,34 @@ int regulator_npm1300_get_voltage(const struct device *dev, int32_t *volt_uv) static int set_buck_mode(const struct device *dev, uint8_t chan, regulator_mode_t mode) { const struct regulator_npm1300_config *config = dev->config; + uint8_t pfm_mask = BIT(chan); + uint8_t pfm_data; + uint8_t pwm_reg; + int ret; switch (mode) { case NPM1300_BUCK_MODE_PWM: - return mfd_npm1300_reg_write(config->mfd, BUCK_BASE, - BUCK_OFFSET_PWM_SET + (chan * 2U), 1U); + pfm_data = 0U; + pwm_reg = BUCK_OFFSET_PWM_SET; + break; case NPM1300_BUCK_MODE_AUTO: - return mfd_npm1300_reg_write(config->mfd, BUCK_BASE, - BUCK_OFFSET_PWM_CLR + (chan * 2U), 1U); + pfm_data = 0U; + pwm_reg = BUCK_OFFSET_PWM_CLR; + break; + case NPM1300_BUCK_MODE_PFM: + pfm_data = pfm_mask; + pwm_reg = BUCK_OFFSET_PWM_CLR; + break; default: return -ENOTSUP; } + + ret = mfd_npm1300_reg_update(config->mfd, BUCK_BASE, BUCK_OFFSET_CTRL0, pfm_data, pfm_mask); + if (ret < 0) { + return ret; + } + + return mfd_npm1300_reg_write(config->mfd, BUCK_BASE, pwm_reg + (chan * 2U), 1U); } static int set_ldsw_mode(const struct device *dev, uint8_t chan, regulator_mode_t mode) @@ -395,7 +439,7 @@ static int regulator_npm1300_set_ldsw_pin_ctrl(const struct device *dev, uint8_t ctrl = (pin + 1U) | (inv << 3U); - return mfd_npm1300_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_GPISEL + chan, type); + return mfd_npm1300_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_GPISEL + chan, ctrl); } int regulator_npm1300_set_pin_ctrl(const struct device *dev, const struct gpio_dt_spec *spec, @@ -481,16 +525,75 @@ int regulator_npm1300_common_init(const struct device *dev) return 0; } +static int get_enabled_reg(const struct device *dev, uint8_t base, uint8_t offset, uint8_t mask, + bool *enabled) +{ + const struct regulator_npm1300_config *config = dev->config; + uint8_t data; + + int ret = mfd_npm1300_reg_read(config->mfd, base, offset, &data); + + if (ret != 0) { + return ret; + } + + *enabled = (data & mask) != 0U; + + return 0; +} + +static int get_enabled(const struct device *dev, bool *enabled) +{ + const struct regulator_npm1300_config *config = dev->config; + + switch (config->source) { + case NPM1300_SOURCE_BUCK1: + return get_enabled_reg(dev, BUCK_BASE, BUCK_OFFSET_STATUS, BUCK1_ON_MASK, enabled); + case NPM1300_SOURCE_BUCK2: + return get_enabled_reg(dev, BUCK_BASE, BUCK_OFFSET_STATUS, BUCK2_ON_MASK, enabled); + case NPM1300_SOURCE_LDO1: + return get_enabled_reg(dev, LDSW_BASE, LDSW_OFFSET_STATUS, LDSW1_ON_MASK, enabled); + case NPM1300_SOURCE_LDO2: + return get_enabled_reg(dev, LDSW_BASE, LDSW_OFFSET_STATUS, LDSW2_ON_MASK, enabled); + default: + return -ENODEV; + } +} + +static int soft_start_set(const struct device *dev, uint8_t soft_start) +{ + const struct regulator_npm1300_config *config = dev->config; + + switch (config->source) { + case NPM1300_SOURCE_LDO1: + return mfd_npm1300_reg_update(config->mfd, LDSW_BASE, LDSW_OFFSET_CONFIG, + soft_start << LDSW1_SOFTSTART_SHIFT, + LDSW1_SOFTSTART_MASK); + case NPM1300_SOURCE_LDO2: + return mfd_npm1300_reg_update(config->mfd, LDSW_BASE, LDSW_OFFSET_CONFIG, + soft_start << LDSW2_SOFTSTART_SHIFT, + LDSW2_SOFTSTART_MASK); + default: + return -ENOTSUP; + } +} + int regulator_npm1300_init(const struct device *dev) { const struct regulator_npm1300_config *config = dev->config; + bool enabled; int ret = 0; if (!device_is_ready(config->mfd)) { return -ENODEV; } - ret = regulator_common_init(dev, false); + ret = get_enabled(dev, &enabled); + if (ret < 0) { + return ret; + } + + ret = regulator_common_init(dev, enabled); if (ret < 0) { return ret; } @@ -503,6 +606,14 @@ int regulator_npm1300_init(const struct device *dev) } } + /* Configure soft start */ + if (config->soft_start != UINT8_MAX) { + ret = soft_start_set(dev, config->soft_start); + if (ret != 0) { + return ret; + } + } + /* Configure GPIO pin control */ ret = regulator_npm1300_set_pin_ctrl(dev, &config->enable_gpios, NPM1300_GPIO_TYPE_ENABLE); if (ret != 0) { @@ -539,6 +650,7 @@ static const struct regulator_driver_api api = {.enable = regulator_npm1300_enab .mfd = DEVICE_DT_GET(DT_GPARENT(node_id)), \ .source = _source, \ .retention_uv = DT_PROP_OR(node_id, retention_microvolt, 0), \ + .soft_start = DT_ENUM_IDX_OR(node_id, soft_start_microamp, UINT8_MAX), \ .enable_gpios = GPIO_DT_SPEC_GET_OR(node_id, enable_gpios, {0}), \ .retention_gpios = GPIO_DT_SPEC_GET_OR(node_id, retention_gpios, {0}), \ .pwm_gpios = GPIO_DT_SPEC_GET_OR(node_id, pwm_gpios, {0})}; \ diff --git a/drivers/regulator/regulator_nxp_vref.c b/drivers/regulator/regulator_nxp_vref.c new file mode 100644 index 00000000000..3d2ba23010e --- /dev/null +++ b/drivers/regulator/regulator_nxp_vref.c @@ -0,0 +1,221 @@ +/* + * Copyright 2023 NXP + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_vref + +#include + +#include +#include +#include +#include +#include + +#include + +static const struct linear_range utrim_range = LINEAR_RANGE_INIT(1000000, 100000U, 0x0U, 0xBU); + +struct regulator_nxp_vref_data { + struct regulator_common_data common; +}; + +struct regulator_nxp_vref_config { + struct regulator_common_config common; + VREF_Type *base; + uint8_t gnd_sel; + uint16_t buf_start_delay; + uint16_t bg_start_time; +}; + +static int regulator_nxp_vref_enable(const struct device *dev) +{ + const struct regulator_nxp_vref_config *config = dev->config; + VREF_Type *const base = config->base; + + volatile uint32_t *const csr = &base->CSR; + + *csr |= VREF_CSR_LPBGEN_MASK | VREF_CSR_LPBG_BUF_EN_MASK; + /* Wait for bandgap startup */ + k_busy_wait(config->bg_start_time); + + /* Enable high accuracy bandgap */ + *csr |= VREF_CSR_HCBGEN_MASK; + + /* Monitor until stable */ + while (!(*csr & VREF_CSR_VREFST_MASK)) + ; + + /* Enable output buffer */ + *csr |= VREF_CSR_BUF21EN_MASK; + + return 0; +} + +static int regulator_nxp_vref_disable(const struct device *dev) +{ + const struct regulator_nxp_vref_config *config = dev->config; + VREF_Type *const base = config->base; + + /* + * Disable HC Bandgap, LP Bandgap, and Buf21 + * to achieve "Off" mode of VREF + */ + base->CSR &= ~(VREF_CSR_BUF21EN_MASK | VREF_CSR_HCBGEN_MASK | VREF_CSR_LPBGEN_MASK); + + return 0; +} + +static int regulator_nxp_vref_set_mode(const struct device *dev, regulator_mode_t mode) +{ + const struct regulator_nxp_vref_config *config = dev->config; + VREF_Type *const base = config->base; + uint32_t csr = base->CSR; + + if (mode == NXP_VREF_MODE_STANDBY) { + csr &= ~VREF_CSR_REGEN_MASK & + ~VREF_CSR_CHOPEN_MASK & + ~VREF_CSR_HI_PWR_LV_MASK & + ~VREF_CSR_BUF21EN_MASK; + } else if (mode == NXP_VREF_MODE_LOW_POWER) { + csr &= ~VREF_CSR_REGEN_MASK & + ~VREF_CSR_CHOPEN_MASK & + ~VREF_CSR_HI_PWR_LV_MASK; + csr |= VREF_CSR_BUF21EN_MASK; + } else if (mode == NXP_VREF_MODE_HIGH_POWER) { + csr &= ~VREF_CSR_REGEN_MASK & + ~VREF_CSR_CHOPEN_MASK; + csr |= VREF_CSR_HI_PWR_LV_MASK & + VREF_CSR_BUF21EN_MASK; + } else if (mode == NXP_VREF_MODE_INTERNAL_REGULATOR) { + csr |= VREF_CSR_REGEN_MASK & + VREF_CSR_CHOPEN_MASK & + VREF_CSR_HI_PWR_LV_MASK & + VREF_CSR_BUF21EN_MASK; + } else { + return -EINVAL; + } + + base->CSR = csr; + + k_busy_wait(config->buf_start_delay); + + return 0; +} + +static int regulator_nxp_vref_get_mode(const struct device *dev, regulator_mode_t *mode) +{ + const struct regulator_nxp_vref_config *config = dev->config; + VREF_Type *const base = config->base; + uint32_t csr = base->CSR; + + /* Check bits to determine mode */ + if (csr & VREF_CSR_REGEN_MASK) { + *mode = NXP_VREF_MODE_INTERNAL_REGULATOR; + } else if (csr & VREF_CSR_HI_PWR_LV_MASK) { + *mode = NXP_VREF_MODE_HIGH_POWER; + } else if (csr & VREF_CSR_BUF21EN_MASK) { + *mode = NXP_VREF_MODE_LOW_POWER; + } else { + *mode = NXP_VREF_MODE_STANDBY; + } + + return 0; +} + +static inline unsigned int regulator_nxp_vref_count_voltages(const struct device *dev) +{ + return linear_range_values_count(&utrim_range); +} + +static int regulator_nxp_vref_list_voltage(const struct device *dev, + unsigned int idx, int32_t *volt_uv) +{ + return linear_range_get_value(&utrim_range, idx, volt_uv); +} + +static int regulator_nxp_vref_set_voltage(const struct device *dev, + int32_t min_uv, int32_t max_uv) +{ + const struct regulator_nxp_vref_config *config = dev->config; + VREF_Type *const base = config->base; + uint16_t idx; + int ret; + + ret = linear_range_get_win_index(&utrim_range, min_uv, max_uv, &idx); + if (ret < 0) { + return ret; + } + + base->UTRIM &= ~VREF_UTRIM_TRIM2V1_MASK; + base->UTRIM |= VREF_UTRIM_TRIM2V1_MASK & idx; + + return 0; +} + +static int regulator_nxp_vref_get_voltage(const struct device *dev, + int32_t *volt_uv) +{ + const struct regulator_nxp_vref_config *config = dev->config; + VREF_Type *const base = config->base; + uint16_t idx; + int ret; + + /* Linear range index is the register value */ + idx = (base->UTRIM & VREF_UTRIM_TRIM2V1_MASK) >> VREF_UTRIM_TRIM2V1_SHIFT; + + ret = linear_range_get_value(&utrim_range, base->UTRIM, volt_uv); + + return ret; +} + +static const struct regulator_driver_api api = { + .enable = regulator_nxp_vref_enable, + .disable = regulator_nxp_vref_disable, + .set_mode = regulator_nxp_vref_set_mode, + .get_mode = regulator_nxp_vref_get_mode, + .set_voltage = regulator_nxp_vref_set_voltage, + .get_voltage = regulator_nxp_vref_get_voltage, + .list_voltage = regulator_nxp_vref_list_voltage, + .count_voltages = regulator_nxp_vref_count_voltages, +}; + +static int regulator_nxp_vref_init(const struct device *dev) +{ + const struct regulator_nxp_vref_config *config = dev->config; + VREF_Type *base = config->base; + int ret; + + regulator_common_data_init(dev); + + /* Select ground */ + base->CSR &= ~VREF_CSR_REFL_GRD_SEL_MASK; + base->CSR |= config->gnd_sel; + + ret = regulator_nxp_vref_disable(dev); + if (ret < 0) { + return ret; + } + + return regulator_common_init(dev, false); +} + +#define REGULATOR_NXP_VREF_DEFINE(inst) \ + static struct regulator_nxp_vref_data data_##inst; \ + \ + static const struct regulator_nxp_vref_config config_##inst = { \ + .common = REGULATOR_DT_INST_COMMON_CONFIG_INIT(inst), \ + .base = (VREF_Type *) DT_INST_REG_ADDR(inst), \ + .gnd_sel = DT_INST_ENUM_IDX_OR(inst, nxp_ground_select, 0), \ + .buf_start_delay = DT_INST_PROP(inst, \ + nxp_buffer_startup_delay_us), \ + .bg_start_time = DT_INST_PROP(inst, \ + nxp_bandgap_startup_time_us), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, regulator_nxp_vref_init, NULL, &data_##inst,\ + &config_##inst, POST_KERNEL, \ + CONFIG_REGULATOR_NXP_VREF_INIT_PRIORITY, &api); \ + +DT_INST_FOREACH_STATUS_OKAY(REGULATOR_NXP_VREF_DEFINE) diff --git a/drivers/regulator/regulator_pca9420.c b/drivers/regulator/regulator_pca9420.c index 71dd55525b8..c7978242871 100644 --- a/drivers/regulator/regulator_pca9420.c +++ b/drivers/regulator/regulator_pca9420.c @@ -18,6 +18,8 @@ /** General purpose registers */ /** @brief Top level system ctrl 0 */ #define PCA9420_TOP_CNTL0 0x09U +/** @brief Top level system ctrl 2 */ +#define PCA9420_TOP_CNTL2 0x0BU /** @brief Top level system ctrl 3 */ #define PCA9420_TOP_CNTL3 0x0CU @@ -36,6 +38,10 @@ #define PCA9420_TOP_CNTL0_VIN_ILIM_SEL_MASK 0xE0U #define PCA9420_TOP_CNTL0_VIN_ILIM_SEL_DISABLED 0x7U +/** @brief ASYS UVLO threshold selection */ +#define PCA9420_TOP_CNTL2_ASYS_UVLO_SEL_POS 6U +#define PCA9420_TOP_CNTL2_ASYS_UVLO_SEL_MASK 0xC0U + /** @brief I2C Mode control mask */ #define PCA9420_TOP_CNTL3_MODE_I2C_POS 3U #define PCA9420_TOP_CNTL3_MODE_I2C_MASK 0x18U @@ -102,6 +108,7 @@ struct regulator_pca9420_common_config { struct i2c_dt_spec i2c; int32_t vin_ilim_ua; bool enable_modesel_pins; + uint8_t asys_uvlo_sel_mv; }; struct regulator_pca9420_common_data { @@ -427,10 +434,20 @@ static int regulator_pca9420_common_init(const struct device *dev) PCA9420_VIN_ILIM_UA_LSB; } - return i2c_reg_update_byte_dt( + ret = i2c_reg_update_byte_dt( &config->i2c, PCA9420_TOP_CNTL0, PCA9420_TOP_CNTL0_VIN_ILIM_SEL_MASK, reg_val << PCA9420_TOP_CNTL0_VIN_ILIM_SEL_POS); + + if (ret != 0) { + return ret; + } + + /* configure ASYS UVLO threshold */ + return i2c_reg_update_byte_dt(&config->i2c, PCA9420_TOP_CNTL2, + PCA9420_TOP_CNTL2_ASYS_UVLO_SEL_MASK, + config->asys_uvlo_sel_mv << + PCA9420_TOP_CNTL2_ASYS_UVLO_SEL_POS); } #define REGULATOR_PCA9420_DEFINE(node_id, id, name, _parent) \ @@ -465,6 +482,8 @@ static int regulator_pca9420_common_init(const struct device *dev) .vin_ilim_ua = DT_INST_PROP(inst, nxp_vin_ilim_microamp), \ .enable_modesel_pins = \ DT_INST_PROP(inst, nxp_enable_modesel_pins), \ + .asys_uvlo_sel_mv = \ + DT_INST_ENUM_IDX(inst, nxp_asys_uvlo_sel_millivolt), \ }; \ \ static struct regulator_pca9420_common_data data_##inst; \ diff --git a/drivers/regulator/regulator_shell.c b/drivers/regulator/regulator_shell.c index 4caaa9f8815..74aa1f22ca6 100644 --- a/drivers/regulator/regulator_shell.c +++ b/drivers/regulator/regulator_shell.c @@ -221,6 +221,38 @@ static int cmd_vget(const struct shell *sh, size_t argc, char **argv) return 0; } +static int cmd_clist(const struct shell *sh, size_t argc, char **argv) +{ + const struct device *dev; + unsigned int current_cnt; + int32_t last_current_ua; + + ARG_UNUSED(argc); + + dev = device_get_binding(argv[1]); + if (dev == NULL) { + shell_error(sh, "Regulator device %s not available", argv[1]); + return -ENODEV; + } + + current_cnt = regulator_count_current_limits(dev); + + for (unsigned int i = 0U; i < current_cnt; i++) { + int32_t current_ua; + + (void)regulator_list_current_limit(dev, i, ¤t_ua); + + /* do not print repeated current limits */ + if ((i == 0U) || (last_current_ua != current_ua)) { + microtoshell(sh, 'A', current_ua); + } + + last_current_ua = current_ua; + } + + return 0; +} + static int cmd_iset(const struct shell *sh, size_t argc, char **argv) { const struct device *dev; @@ -449,6 +481,10 @@ SHELL_STATIC_SUBCMD_SET_CREATE( "Get voltage\n" "Usage: vget ", cmd_vget, 2, 0), + SHELL_CMD_ARG(clist, &dsub_device_name, + "List all supported current limits\n" + "Usage: clist ", + cmd_clist, 2, 0), SHELL_CMD_ARG(iset, &dsub_device_name, "Set current limit\n" "Input requires units, e.g. 200ma, 20.5ma, 10ua, 1a...\n" diff --git a/drivers/retained_mem/retained_mem_handlers.c b/drivers/retained_mem/retained_mem_handlers.c index 265ae7b15fd..d344e37b42c 100644 --- a/drivers/retained_mem/retained_mem_handlers.c +++ b/drivers/retained_mem/retained_mem_handlers.c @@ -5,11 +5,11 @@ */ #include -#include +#include static inline ssize_t z_vrfy_retained_mem_size(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_RETAINED_MEM)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_RETAINED_MEM)); return z_impl_retained_mem_size(dev); } #include @@ -17,8 +17,8 @@ static inline ssize_t z_vrfy_retained_mem_size(const struct device *dev) static inline int z_vrfy_retained_mem_read(const struct device *dev, off_t offset, uint8_t *buffer, size_t size) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_RETAINED_MEM)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(buffer, size)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_RETAINED_MEM)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(buffer, size)); return z_impl_retained_mem_read(dev, offset, buffer, size); } #include @@ -26,15 +26,15 @@ static inline int z_vrfy_retained_mem_read(const struct device *dev, off_t offse static inline int z_vrfy_retained_mem_write(const struct device *dev, off_t offset, const uint8_t *buffer, size_t size) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_RETAINED_MEM)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(buffer, size)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_RETAINED_MEM)); + K_OOPS(K_SYSCALL_MEMORY_READ(buffer, size)); return z_impl_retained_mem_write(dev, offset, buffer, size); } #include static inline int z_vrfy_retained_mem_clear(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_RETAINED_MEM)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_RETAINED_MEM)); return z_impl_retained_mem_clear(dev); } #include diff --git a/drivers/rtc/CMakeLists.txt b/drivers/rtc/CMakeLists.txt index a770523f33b..65d822dbe6e 100644 --- a/drivers/rtc/CMakeLists.txt +++ b/drivers/rtc/CMakeLists.txt @@ -5,6 +5,8 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/rtc.h) zephyr_library() +zephyr_library_sources_ifdef(CONFIG_RTC_AM1805 rtc_am1805.c) +zephyr_library_sources_ifdef(CONFIG_RTC_DS1307 rtc_ds1307.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE rtc_handlers.c) zephyr_library_sources_ifdef(CONFIG_RTC_EMUL rtc_emul.c) zephyr_library_sources_ifdef(CONFIG_RTC_PCF8523 rtc_pcf8523.c) @@ -13,3 +15,5 @@ zephyr_library_sources_ifdef(CONFIG_RTC_MOTOROLA_MC146818 rtc_mc146818.c) zephyr_library_sources_ifdef(CONFIG_RTC_STM32 rtc_ll_stm32.c) zephyr_library_sources_ifdef(CONFIG_RTC_SHELL rtc_shell.c) zephyr_library_sources_ifdef(CONFIG_RTC_FAKE rtc_fake.c) +zephyr_library_sources_ifdef(CONFIG_RTC_SMARTBOND rtc_smartbond.c) +zephyr_library_sources_ifdef(CONFIG_RTC_ATMEL_SAM rtc_sam.c) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 8df08f38009..10b228ceeab 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -41,11 +41,15 @@ config RTC_SHELL help RTC Shell commands +source "drivers/rtc/Kconfig.am1805" +source "drivers/rtc/Kconfig.ds1307" source "drivers/rtc/Kconfig.emul" source "drivers/rtc/Kconfig.fake" source "drivers/rtc/Kconfig.pcf8523" source "drivers/rtc/Kconfig.pcf8563" source "drivers/rtc/Kconfig.mc146818" +source "drivers/rtc/Kconfig.sam" source "drivers/rtc/Kconfig.stm32" +source "drivers/rtc/Kconfig.smartbond" endif # RTC diff --git a/drivers/rtc/Kconfig.am1805 b/drivers/rtc/Kconfig.am1805 new file mode 100644 index 00000000000..4c7319ebd0b --- /dev/null +++ b/drivers/rtc/Kconfig.am1805 @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2023 Linumiz +# Author: Sri Surya + +config RTC_AM1805 + bool "AMBIQ AM1805 RTC driver" + default y + depends on DT_HAS_AMBIQ_AM1805_ENABLED + select I2C + help + Enable the AMBIQ AM1805 RTC driver. + +if RTC_AM1805 + +config RTC_AM1805_THREAD_STACK_SIZE + int "Stack size for the am1805 interrupt thread" + default 512 + help + Size of the stack used for the thread handling interrupts and dispatching callbacks. + +config RTC_AM1805_THREAD_PRIO + int "Priority for the am1805 interrupt thread" + default 0 + help + Priority level for the thread handling interrupts and dispatching callbacks. + +endif diff --git a/drivers/rtc/Kconfig.ds1307 b/drivers/rtc/Kconfig.ds1307 new file mode 100644 index 00000000000..b350846f58e --- /dev/null +++ b/drivers/rtc/Kconfig.ds1307 @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2023 Arunmani Alagarsamy +# Author: Arunmani Alagarsamy + +config RTC_DS1307 + bool "MAXIM DS1307 RTC driver" + default y + depends on DT_HAS_MAXIM_DS1307_ENABLED + select I2C + help + Enable the MAXIM DS1307 RTC driver. diff --git a/drivers/rtc/Kconfig.sam b/drivers/rtc/Kconfig.sam new file mode 100644 index 00000000000..5968f66bc42 --- /dev/null +++ b/drivers/rtc/Kconfig.sam @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Bjarki Arge Andreasen +# SPDX-License-Identifier: Apache-2.0 + +config RTC_ATMEL_SAM + bool "Atmel SAM RTC driver" + default y + depends on DT_HAS_ATMEL_SAM_RTC_ENABLED + help + Atmel Real-Time Clock (RTC) driver used on SAM SoC series. diff --git a/drivers/rtc/Kconfig.smartbond b/drivers/rtc/Kconfig.smartbond new file mode 100644 index 00000000000..d21d3a962fa --- /dev/null +++ b/drivers/rtc/Kconfig.smartbond @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +config RTC_SMARTBOND + bool "Smartbond RTC driver" + depends on DT_HAS_RENESAS_SMARTBOND_RTC_ENABLED + default y + help + Build RTC driver for Smartbond SoCs. diff --git a/drivers/rtc/rtc_am1805.c b/drivers/rtc/rtc_am1805.c new file mode 100644 index 00000000000..b6282d0f8ae --- /dev/null +++ b/drivers/rtc/rtc_am1805.c @@ -0,0 +1,599 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 Linumiz + * Author: Sri Surya + */ + +#include +#include +#include +#include +#include +#include + +#define DT_DRV_COMPAT ambiq_am1805 + +LOG_MODULE_REGISTER(am1805, CONFIG_RTC_LOG_LEVEL); + +#define AM1805_IDENTITY_CODE 0x69 + +/* AM1805 register address */ +#define REG_HUNDREDS_ADDR 0x00 +#define REG_SECONDS_ADDR 0x01 +#define REG_MINUTES_ADDR 0x02 +#define REG_HOURS_ADDR 0x03 +#define REG_MDAY_ADDR 0x04 +#define REG_MONTH_ADDR 0x05 +#define REG_YEAR_ADDR 0x06 +#define REG_WDAY_ADDR 0x07 + +#define REG_ALM_HUNDREDS_ADDR 0x08 +#define REG_ALM_SECONDS_ADDR 0x09 +#define REG_ALM_MINUTES_ADDR 0x0A +#define REG_ALM_HOURS_ADDR 0x0B +#define REG_ALM_MDAY_ADDR 0x0C +#define REG_ALM_MONTH_ADDR 0x0D +#define REG_ALM_WDAY_ADDR 0x0E +#define REG_STATUS_ADDR 0x0F +#define REG_CONTROL1_ADDR 0x10 +#define REG_CONTROL2_ADDR 0x11 +#define REG_XT_CALIB_ADDR 0x14 +#define REG_TIMER_CTRL_ADDR 0x18 +#define REG_IRQ_MASK_ADDR 0x12 +#define REG_WATCHDOG_ADDR 0x1B +#define REG_OSC_STATUS_ADDR 0x1D + +/* AM1805 control bits */ +#define SECONDS_BITS GENMASK(6, 0) +#define MINUTES_BITS GENMASK(6, 0) +#define HOURS_BITS GENMASK(5, 0) +#define DATE_BITS GENMASK(5, 0) +#define MONTHS_BITS GENMASK(4, 0) +#define WEEKDAY_BITS GENMASK(2, 0) +#define YEAR_BITS GENMASK(7, 0) +#define REG_CONTROL2_OUT2S_BITS GENMASK(4, 2) +#define REG_TIMER_CTRL_RPT_BITS GENMASK(4, 2) +#define REG_XT_CALIB_OFF_MASK GENMASK(6, 0) + +#define REG_STATUS_ALM BIT(2) +#define REG_CONTROL1_STOP BIT(7) +#define REG_IRQ_MASK_AIE BIT(2) +#define REG_XT_CALIB_CMDX BIT(7) + +#define TIMER_CTRL_ALM_OFF 0x00 +#define TIMER_CTRL_ALM_DAY BIT(4) +#define TIMER_CTRL_ALM_YEAR BIT(2) +#define TIMER_CTRL_ALM_HR (BIT(2) | BIT(4)) +#define TIMER_CTRL_ALM_SEC GENMASK(4, 2) +#define TIMER_CTRL_ALM_MIN GENMASK(4, 3) +#define TIMER_CTRL_ALM_WEEK GENMASK(3, 2) + +#define REG_WATCHDOG_WDS BIT(7) +#define WRB_1_SECOND BIT(1) +#define WRB_4_SECONDS GENMASK(1, 0) + +#define REG_OSC_STATUS_ACAL_0 0x00 +#define REG_OSC_STATUS_ACAL_1 BIT(6) +#define REG_OSC_STATUS_ACAL_2 BIT(7) +#define REG_OSC_STATUS_ACAL_3 GENMASK(7, 6) +#define REG_OSC_STATUS_MASK BIT(1) +#define REG_STATUS_DEFAULT 0x00 + +#define AM1805_RTC_ALARM_TIME_MASK \ + (RTC_ALARM_TIME_MASK_SECOND | RTC_ALARM_TIME_MASK_MINUTE | RTC_ALARM_TIME_MASK_HOUR | \ + RTC_ALARM_TIME_MASK_MONTHDAY | RTC_ALARM_TIME_MASK_MONTH | RTC_ALARM_TIME_MASK_WEEKDAY) + +#ifdef CONFIG_RTC_ALARM +/* am1805-gpios property must be in the devicetree inorder to use the RTC_ALARM */ +#if !DT_ANY_INST_HAS_PROP_STATUS_OKAY(am1805_gpios) +#error "am1805-gpios" - property not available in devicetree. +#endif +#endif + +struct am1805_config { + const struct i2c_dt_spec int_i2c; +#ifdef CONFIG_RTC_ALARM + struct gpio_dt_spec int_gpio; +#endif +}; + +struct am1805_data { + struct k_mutex lock; +#ifdef CONFIG_RTC_ALARM + rtc_alarm_callback alarm_user_callback; + void *alarm_user_data; + /* For gpio-interrupt */ + struct gpio_callback am1805_callback; + struct k_thread am1805_thread; + struct k_sem int_sem; + + K_KERNEL_STACK_MEMBER(am1805_stack, CONFIG_RTC_AM1805_THREAD_STACK_SIZE); +#endif +}; + +/* To set the timer registers */ +static int am1805_set_time(const struct device *dev, const struct rtc_time *tm) +{ + int err; + uint8_t regs[7]; + + struct am1805_data *data = dev->data; + const struct am1805_config *config = dev->config; + + k_mutex_lock(&data->lock, K_FOREVER); + + /* To unlock Stop-bit */ + err = i2c_reg_update_byte_dt(&config->int_i2c, REG_CONTROL1_ADDR, + REG_CONTROL1_STOP, REG_CONTROL1_STOP); + if (err != 0) { + goto unlock; + } + + LOG_DBG("set time: year = %d, mon = %d, mday = %d, wday = %d, hour = %d, " + "min = %d, sec = %d", + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday, tm->tm_hour, tm->tm_min, + tm->tm_sec); + + regs[0] = bin2bcd(tm->tm_sec) & SECONDS_BITS; + regs[1] = bin2bcd(tm->tm_min) & MINUTES_BITS; + regs[2] = bin2bcd(tm->tm_hour) & HOURS_BITS; + regs[3] = bin2bcd(tm->tm_mday) & DATE_BITS; + regs[4] = bin2bcd(tm->tm_mon) & MONTHS_BITS; + regs[5] = bin2bcd(tm->tm_year) & YEAR_BITS; + regs[6] = bin2bcd(tm->tm_wday) & WEEKDAY_BITS; + + err = i2c_burst_write_dt(&config->int_i2c, REG_SECONDS_ADDR, regs, sizeof(regs)); + if (err != 0) { + goto unlock; + } + + /* To lock Stop-bit */ + err = i2c_reg_update_byte_dt(&config->int_i2c, REG_CONTROL1_ADDR, REG_CONTROL1_STOP, 0); + +unlock: + k_mutex_unlock(&data->lock); + + return err; +} + +/* To get from the timer registers */ +static int am1805_get_time(const struct device *dev, struct rtc_time *timeptr) +{ + int err; + uint8_t ctl_reg; + uint8_t regs[7]; + + struct am1805_data *data = dev->data; + const struct am1805_config *config = dev->config; + + k_mutex_lock(&data->lock, K_FOREVER); + + err = i2c_reg_read_byte_dt(&config->int_i2c, REG_CONTROL1_ADDR, &ctl_reg); + if (err != 0) { + goto unlock; + } + + err = ctl_reg & REG_CONTROL1_STOP; + if (err != 0) { + LOG_WRN("No control to get time now!!"); + goto unlock; + } + + err = i2c_burst_read_dt(&config->int_i2c, REG_SECONDS_ADDR, regs, sizeof(regs)); + if (err != 0) { + goto unlock; + } + + timeptr->tm_sec = bcd2bin(regs[0] & SECONDS_BITS); + timeptr->tm_min = bcd2bin(regs[1] & MINUTES_BITS); + timeptr->tm_hour = bcd2bin(regs[2] & HOURS_BITS); + timeptr->tm_mday = bcd2bin(regs[3] & DATE_BITS); + timeptr->tm_mon = bcd2bin(regs[4] & MONTHS_BITS); + timeptr->tm_year = bcd2bin(regs[5] & YEAR_BITS); + timeptr->tm_wday = bcd2bin(regs[6] & WEEKDAY_BITS); + + LOG_DBG("get time: year = %d, mon = %d, mday = %d, wday = %d, hour = %d, " + "min = %d, sec = %d", + timeptr->tm_year, timeptr->tm_mon, timeptr->tm_mday, timeptr->tm_wday, + timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec); + +unlock: + k_mutex_unlock(&data->lock); + + return err; +} + +#ifdef CONFIG_RTC_CALIBRATION +/* To Calibrate the XT oscillator */ +static int am1805_set_calibration(const struct device *dev, int32_t xt_clock_adj) +{ + int err; + uint8_t xt_calib_value; + + struct am1805_data *data = dev->data; + const struct am1805_config *config = dev->config; + uint8_t reg = REG_OSC_STATUS_MASK; + + if (xt_clock_adj < -320 || xt_clock_adj > 127) { + LOG_DBG("Cannot be calibrated adj = %d\n", xt_clock_adj); + return -EINVAL; + } else if (xt_clock_adj < -256) { + /* XTCAL=3 CMDX=1 OFFSETX=(adj+192)/2 */ + reg |= REG_OSC_STATUS_ACAL_3; + xt_calib_value = ((uint8_t)(xt_clock_adj + 192) >> 1); + xt_calib_value &= REG_XT_CALIB_OFF_MASK; + xt_calib_value |= REG_XT_CALIB_CMDX; + } else if (xt_clock_adj < -192) { + /* XTCAL=3 CMDX=0 OFFSETX=(adj+192) */ + reg |= REG_OSC_STATUS_ACAL_3; + xt_calib_value = (uint8_t)(xt_clock_adj + 192); + xt_calib_value &= REG_XT_CALIB_OFF_MASK; + } else if (xt_clock_adj < -128) { + /* XTCAL=2 CMDX=0 OFFSETX=(adj+128) */ + reg |= REG_OSC_STATUS_ACAL_2; + xt_calib_value = (uint8_t)(xt_clock_adj + 128); + xt_calib_value &= REG_XT_CALIB_OFF_MASK; + } else if (xt_clock_adj < -64) { + /* XTCAL=1 CMDX=0 OFFSETX=(adj+64) */ + reg |= REG_OSC_STATUS_ACAL_1; + xt_calib_value = (uint8_t)(xt_clock_adj + 64); + xt_calib_value &= REG_XT_CALIB_OFF_MASK; + } else if (xt_clock_adj < 64) { + /* XTCAL=0 CMDX=0 OFFSETX=(adj) */ + reg |= REG_OSC_STATUS_ACAL_0; + xt_calib_value = (uint8_t)(xt_clock_adj); + xt_calib_value &= REG_XT_CALIB_OFF_MASK; + } else if (xt_clock_adj < 128) { + /* XTCAL=0 CMDX=1 OFFSETX=(adj)/2 */ + reg |= REG_OSC_STATUS_ACAL_0; + xt_calib_value = ((uint8_t)(xt_clock_adj >> 1)); + xt_calib_value &= REG_XT_CALIB_OFF_MASK; + xt_calib_value |= REG_XT_CALIB_CMDX; + } + + k_mutex_lock(&data->lock, K_FOREVER); + + err = i2c_reg_write_byte_dt(&config->int_i2c, REG_OSC_STATUS_ADDR, reg); + if (err != 0) { + LOG_DBG("fail to set oscillator status register\n"); + goto unlock; + } + + /* Calibration XT Register */ + reg = xt_calib_value; + err = i2c_reg_write_byte_dt(&config->int_i2c, REG_XT_CALIB_ADDR, reg); + if (err != 0) { + LOG_DBG("fail to set XT calibration register\n"); + } + +unlock: + k_mutex_unlock(&data->lock); + + return err; +} + +static int am1805_get_calibration(const struct device *dev, int32_t *calib) +{ + int err; + bool cmdx; + uint8_t reg; + uint8_t xtcal; + + struct am1805_data *data = dev->data; + const struct am1805_config *config = dev->config; + + k_mutex_lock(&data->lock, K_FOREVER); + + err = i2c_reg_read_byte_dt(&config->int_i2c, REG_OSC_STATUS_ADDR, ®); + if (err != 0) { + goto unlock; + } + + /* First 2-bits (from MSB) */ + xtcal = reg >> 6; + + err = i2c_reg_read_byte_dt(&config->int_i2c, REG_XT_CALIB_ADDR, ®); + if (err != 0) { + goto unlock; + } + + *calib = reg; + /* First bit (from MSB) */ + cmdx = reg & BIT(7); + /* Set or Clear the bit-7 based on bit-6, to achieve the given range (in datasheet) */ + WRITE_BIT(reg, 7, (reg & BIT(6))); + WRITE_BIT(reg, 6, 0); + + LOG_DBG("XTCAL = %d, CMDX = %d, OFFSETX = %d\n", xtcal, cmdx, (int8_t) reg); + +unlock: + k_mutex_unlock(&data->lock); + + return err; +} +#endif + +#ifdef CONFIG_RTC_ALARM +/* To get from the alarm registers */ +static int am1805_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask, + struct rtc_time *timeptr) +{ + + int err; + uint8_t regs[6]; + + struct am1805_data *data = dev->data; + const struct am1805_config *config = dev->config; + + if (id != 0U) { + LOG_ERR("invalid ID %d", id); + return -EINVAL; + } + + k_mutex_lock(&data->lock, K_FOREVER); + + err = i2c_burst_read_dt(&config->int_i2c, REG_ALM_SECONDS_ADDR, regs, sizeof(regs)); + if (err != 0) { + goto unlock; + } + + timeptr->tm_sec = bcd2bin(regs[0] & SECONDS_BITS); + timeptr->tm_min = bcd2bin(regs[1] & MINUTES_BITS); + timeptr->tm_hour = bcd2bin(regs[2] & HOURS_BITS); + timeptr->tm_mday = bcd2bin(regs[3] & DATE_BITS); + timeptr->tm_mon = bcd2bin(regs[4] & MONTHS_BITS); + timeptr->tm_wday = bcd2bin(regs[5] & WEEKDAY_BITS); + + *mask = (AM1805_RTC_ALARM_TIME_MASK); + + LOG_DBG("get alarm: wday = %d, mon = %d, mday = %d, hour = %d, min = %d, sec = %d, " + "mask = 0x%04x", timeptr->tm_wday, timeptr->tm_mon, timeptr->tm_mday, + timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec, *mask); + +unlock: + k_mutex_unlock(&data->lock); + + return err; +} + +static int am1805_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask, + const struct rtc_time *timeptr) +{ + int err; + uint8_t regs[6]; + + struct am1805_data *data = dev->data; + const struct am1805_config *config = dev->config; + + if (id != 0U) { + LOG_ERR("invalid ID %d", id); + return -EINVAL; + } + + if ((mask & ~(AM1805_RTC_ALARM_TIME_MASK)) != 0U) { + LOG_ERR("unsupported alarm field mask 0x%04x", mask); + return -EINVAL; + } + + k_mutex_lock(&data->lock, K_FOREVER); + + /* Disable timer control registers before the initialization */ + err = i2c_reg_update_byte_dt(&config->int_i2c, REG_TIMER_CTRL_ADDR, + REG_TIMER_CTRL_RPT_BITS, 0); + if (err != 0) { + goto unlock; + } + + /* Clear the interrupt mask for alarm */ + err = i2c_reg_update_byte_dt(&config->int_i2c, REG_IRQ_MASK_ADDR, + REG_IRQ_MASK_AIE, 0); + if (err != 0) { + goto unlock; + } + + /* Clear the status bit */ + err = i2c_reg_update_byte_dt(&config->int_i2c, REG_STATUS_ADDR, + REG_STATUS_ALM, 0); + if (err != 0) { + goto unlock; + } + + /* When mask is 0 */ + if (mask == 0) { + LOG_DBG("The alarm is disabled"); + goto unlock; + } + + regs[0] = bin2bcd(timeptr->tm_sec) & SECONDS_BITS; + regs[1] = bin2bcd(timeptr->tm_min) & MINUTES_BITS; + regs[2] = bin2bcd(timeptr->tm_hour) & HOURS_BITS; + regs[3] = bin2bcd(timeptr->tm_mday) & DATE_BITS; + regs[4] = bin2bcd(timeptr->tm_mon) & MONTHS_BITS; + regs[5] = bin2bcd(timeptr->tm_wday) & WEEKDAY_BITS; + + LOG_DBG("set alarm: second = %d, min = %d, hour = %d, mday = %d, month = %d," + "wday = %d, mask = 0x%04x", + timeptr->tm_sec, timeptr->tm_min, timeptr->tm_hour, timeptr->tm_mday, + timeptr->tm_mon, timeptr->tm_wday, mask); + + err = i2c_burst_write_dt(&config->int_i2c, REG_ALM_SECONDS_ADDR, regs, sizeof(regs)); + if (err != 0) { + goto unlock; + } + + /* Enable irq timer after the initialization */ + err = i2c_reg_update_byte_dt(&config->int_i2c, REG_IRQ_MASK_ADDR, + REG_IRQ_MASK_AIE, REG_IRQ_MASK_AIE); + if (err != 0) { + goto unlock; + } + + /* Enable timer after the initialization for the config of repetation */ + err = i2c_reg_update_byte_dt(&config->int_i2c, REG_TIMER_CTRL_ADDR, + TIMER_CTRL_ALM_SEC, TIMER_CTRL_ALM_SEC); + +unlock: + k_mutex_unlock(&data->lock); + + return err; +} + +static int am1805_alarm_get_supported_fields(const struct device *dev, uint16_t id, uint16_t *mask) +{ + ARG_UNUSED(dev); + + if (id != 0U) { + LOG_ERR("invalid ID %d", id); + return -EINVAL; + } + + *mask = AM1805_RTC_ALARM_TIME_MASK; + + return 0; +} + +static int am1805_alarm_set_callback(const struct device *dev, uint16_t id, + rtc_alarm_callback callback, void *user_data) +{ + + struct am1805_data *data = dev->data; + const struct am1805_config *config = dev->config; + + if (config->int_gpio.port == NULL) { + return -ENOTSUP; + } + + if (id != 0U) { + LOG_ERR("invalid ID %d", id); + return -EINVAL; + } + + k_mutex_lock(&data->lock, K_FOREVER); + + /* Passing the callback function and userdata filled by the user */ + data->alarm_user_callback = callback; + data->alarm_user_data = user_data; + + k_mutex_unlock(&data->lock); + + return 0; +} + +static void am1805_interrupt_thread(const struct device *dev) +{ + struct am1805_data *data = dev->data; + + while (1) { + k_sem_take(&data->int_sem, K_FOREVER); + + if (data->alarm_user_callback == NULL) { + LOG_DBG("Interrupt received, But No Alarm-Callback Initilized!!\n"); + continue; + } + data->alarm_user_callback(dev, 0, data->alarm_user_data); + } +} + +static void am1805_gpio_callback_handler(const struct device *port, struct gpio_callback *cb, + gpio_port_pins_t pins) +{ + struct am1805_data *data = CONTAINER_OF(cb, struct am1805_data, am1805_callback); + + ARG_UNUSED(port); + ARG_UNUSED(pins); + + k_sem_give(&data->int_sem); +} +#endif + +static int am1805_init(const struct device *dev) +{ + int err; + uint8_t reg; + + const struct am1805_config *config = dev->config; + struct am1805_data *data = dev->data; + + k_mutex_init(&data->lock); + + if (!i2c_is_ready_dt(&config->int_i2c)) { + LOG_ERR("I2C bus not ready"); + return -ENODEV; + } + + err = i2c_reg_read_byte_dt(&config->int_i2c, REG_STATUS_ADDR, ®); + if (err != 0) { + LOG_ERR("failed to read the status register"); + return -ENODEV; + } + +#ifdef CONFIG_RTC_ALARM + k_tid_t tid; + + k_sem_init(&data->int_sem, 0, INT_MAX); + + if (!gpio_is_ready_dt(&config->int_gpio)) { + LOG_ERR("GPIO not ready"); + return -ENODEV; + } + + err = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT); + if (err != 0) { + LOG_ERR("failed to configure GPIO (err %d)", err); + return -ENODEV; + } + + err = gpio_pin_interrupt_configure_dt(&config->int_gpio, + GPIO_INT_EDGE_TO_INACTIVE); + if (err != 0) { + LOG_ERR("failed to configure interrupt (err %d)", err); + return -ENODEV; + } + + gpio_init_callback(&data->am1805_callback, am1805_gpio_callback_handler, + BIT(config->int_gpio.pin)); + + err = gpio_add_callback_dt(&config->int_gpio, &data->am1805_callback); + if (err != 0) { + LOG_ERR("failed to add GPIO callback (err %d)", err); + return -ENODEV; + } + + tid = k_thread_create(&data->am1805_thread, data->am1805_stack, + K_THREAD_STACK_SIZEOF(data->am1805_stack), + (k_thread_entry_t)am1805_interrupt_thread, (void *)dev, NULL, + NULL, CONFIG_RTC_AM1805_THREAD_PRIO, 0, K_NO_WAIT); + k_thread_name_set(tid, dev->name); +#endif + return 0; +} + +static const struct rtc_driver_api am1805_driver_api = { + .set_time = am1805_set_time, + .get_time = am1805_get_time, +#ifdef CONFIG_RTC_ALARM + .alarm_get_supported_fields = am1805_alarm_get_supported_fields, + .alarm_set_time = am1805_alarm_set_time, + .alarm_get_time = am1805_alarm_get_time, + .alarm_set_callback = am1805_alarm_set_callback, +#endif +#ifdef CONFIG_RTC_CALIBRATION + .set_calibration = am1805_set_calibration, + .get_calibration = am1805_get_calibration, +#endif +}; + +#define AM1805_INIT(inst) \ +static const struct am1805_config am1805_config_##inst = { \ + .int_i2c = I2C_DT_SPEC_INST_GET(inst), \ + IF_ENABLED(CONFIG_RTC_ALARM, \ + (.int_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, am1805_gpios, {0})))}; \ + \ +static struct am1805_data am1805_data_##inst; \ + \ +DEVICE_DT_INST_DEFINE(inst, &am1805_init, NULL, &am1805_data_##inst, \ + &am1805_config_##inst, POST_KERNEL, CONFIG_RTC_INIT_PRIORITY, \ + &am1805_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(AM1805_INIT) diff --git a/drivers/rtc/rtc_ds1307.c b/drivers/rtc/rtc_ds1307.c new file mode 100644 index 00000000000..bfbe0abe255 --- /dev/null +++ b/drivers/rtc/rtc_ds1307.c @@ -0,0 +1,160 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 Arunmani Alagarsamy + * Author: Arunmani Alagarsamy + */ + +#include +#include +#include +#include +#include + +#define DT_DRV_COMPAT maxim_ds1307 + +LOG_MODULE_REGISTER(ds1307, CONFIG_RTC_LOG_LEVEL); + +/* DS1307 registers */ +#define DS1307_REG_SECONDS 0x00 +#define DS1307_REG_MINUTES 0x01 +#define DS1307_REG_HOURS 0x02 +#define DS1307_REG_DAY 0x03 +#define DS1307_REG_DATE 0x04 +#define DS1307_REG_MONTH 0x05 +#define DS1307_REG_YEAR 0x06 +#define DS1307_REG_CTRL 0x07 + +#define SECONDS_BITS GENMASK(6, 0) +#define MINUTES_BITS GENMASK(7, 0) +#define HOURS_BITS GENMASK(5, 0) +#define DATE_BITS GENMASK(5, 0) +#define MONTHS_BITS GENMASK(4, 0) +#define WEEKDAY_BITS GENMASK(2, 0) +#define YEAR_BITS GENMASK(7, 0) +#define VALIDATE_24HR BIT(6) + +struct ds1307_config { + struct i2c_dt_spec i2c_bus; +}; + +struct ds1307_data { + struct k_spinlock lock; +}; + +static int ds1307_set_time(const struct device *dev, const struct rtc_time *tm) +{ + int err; + uint8_t regs[7]; + + struct ds1307_data *data = dev->data; + const struct ds1307_config *config = dev->config; + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + LOG_DBG("set time: year = %d, mon = %d, mday = %d, wday = %d, hour = %d, " + "min = %d, sec = %d", + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday, tm->tm_hour, tm->tm_min, + tm->tm_sec); + + regs[0] = bin2bcd(tm->tm_sec) & SECONDS_BITS; + regs[1] = bin2bcd(tm->tm_min); + regs[2] = bin2bcd(tm->tm_hour); + regs[3] = bin2bcd(tm->tm_wday); + regs[4] = bin2bcd(tm->tm_mday); + regs[5] = bin2bcd(tm->tm_mon); + regs[6] = bin2bcd((tm->tm_year % 100)); + + err = i2c_burst_write_dt(&config->i2c_bus, DS1307_REG_SECONDS, regs, sizeof(regs)); + + k_spin_unlock(&data->lock, key); + + return err; +} + +static int ds1307_get_time(const struct device *dev, struct rtc_time *timeptr) +{ + int err; + uint8_t regs[7]; + + struct ds1307_data *data = dev->data; + const struct ds1307_config *config = dev->config; + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + err = i2c_burst_read_dt(&config->i2c_bus, DS1307_REG_SECONDS, regs, sizeof(regs)); + if (err != 0) { + goto unlock; + } + + timeptr->tm_sec = bcd2bin(regs[0] & SECONDS_BITS); + timeptr->tm_min = bcd2bin(regs[1] & MINUTES_BITS); + timeptr->tm_hour = bcd2bin(regs[2] & HOURS_BITS); /* 24hr mode */ + timeptr->tm_wday = bcd2bin(regs[3] & WEEKDAY_BITS); + timeptr->tm_mday = bcd2bin(regs[4] & DATE_BITS); + timeptr->tm_mon = bcd2bin(regs[5] & MONTHS_BITS); + timeptr->tm_year = bcd2bin(regs[6] & YEAR_BITS); + timeptr->tm_year = timeptr->tm_year + 100; + + /* Not used */ + timeptr->tm_nsec = 0; + timeptr->tm_isdst = -1; + timeptr->tm_yday = -1; + + /* Validate the chip in 24hr mode */ + if (regs[2] & VALIDATE_24HR) { + err = -ENODATA; + goto unlock; + } + + LOG_DBG("get time: year = %d, mon = %d, mday = %d, wday = %d, hour = %d, " + "min = %d, sec = %d", + timeptr->tm_year, timeptr->tm_mon, timeptr->tm_mday, timeptr->tm_wday, + timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec); + +unlock: + k_spin_unlock(&data->lock, key); + + return err; +} + +static const struct rtc_driver_api ds1307_driver_api = { + .set_time = ds1307_set_time, + .get_time = ds1307_get_time, +}; + +static int ds1307_init(const struct device *dev) +{ + int err; + const struct ds1307_config *config = dev->config; + + if (!i2c_is_ready_dt(&config->i2c_bus)) { + LOG_ERR("I2C bus not ready"); + return -ENODEV; + } + + /* Disable squarewave output */ + err = i2c_reg_write_byte_dt(&config->i2c_bus, DS1307_REG_CTRL, 0x00); + if (err < 0) { + LOG_ERR("Error: SQW:%d\n", err); + } + + /* Make clock halt = 0 */ + err = i2c_reg_write_byte_dt(&config->i2c_bus, DS1307_REG_SECONDS, 0x00); + if (err < 0) { + LOG_ERR("Error: Set clock halt bit:%d\n", err); + } + + return 0; +} + +#define DS1307_DEFINE(inst) \ + static struct ds1307_data ds1307_data_##inst; \ + static const struct ds1307_config ds1307_config_##inst = { \ + .i2c_bus = I2C_DT_SPEC_INST_GET(inst), \ + }; \ + DEVICE_DT_INST_DEFINE(inst, &ds1307_init, NULL, &ds1307_data_##inst, \ + &ds1307_config_##inst, POST_KERNEL, CONFIG_RTC_INIT_PRIORITY, \ + &ds1307_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(DS1307_DEFINE) diff --git a/drivers/rtc/rtc_fake.c b/drivers/rtc/rtc_fake.c index 86d66ebd5f8..3a96da7141d 100644 --- a/drivers/rtc/rtc_fake.c +++ b/drivers/rtc/rtc_fake.c @@ -11,9 +11,9 @@ #include #include -#ifdef CONFIG_ZTEST_NEW_API +#ifdef CONFIG_ZTEST #include -#endif /* CONFIG_ZTEST_NEW_API */ +#endif /* CONFIG_ZTEST */ DEFINE_FAKE_VALUE_FUNC(int, rtc_fake_set_time, const struct device *, const struct rtc_time *); DEFINE_FAKE_VALUE_FUNC(int, rtc_fake_get_time, const struct device *, struct rtc_time *); @@ -40,7 +40,7 @@ DEFINE_FAKE_VALUE_FUNC(int, rtc_fake_set_calibration, const struct device *, int DEFINE_FAKE_VALUE_FUNC(int, rtc_fake_get_calibration, const struct device *, int32_t *); #endif /* CONFIG_RTC_CALIBRATION */ -#ifdef CONFIG_ZTEST_NEW_API +#ifdef CONFIG_ZTEST static void fake_rtc_reset_rule_before(const struct ztest_unit_test *test, void *fixture) { ARG_UNUSED(test); @@ -68,7 +68,7 @@ static void fake_rtc_reset_rule_before(const struct ztest_unit_test *test, void } ZTEST_RULE(fake_rtc_reset_rule, fake_rtc_reset_rule_before, NULL); -#endif /* CONFIG_ZTEST_NEW_API */ +#endif /* CONFIG_ZTEST */ struct rtc_driver_api rtc_fake_driver_api = { .set_time = rtc_fake_set_time, diff --git a/drivers/rtc/rtc_handlers.c b/drivers/rtc/rtc_handlers.c index a0e9cb34a8c..33bb9076971 100644 --- a/drivers/rtc/rtc_handlers.c +++ b/drivers/rtc/rtc_handlers.c @@ -5,20 +5,20 @@ */ #include -#include +#include static inline int z_vrfy_rtc_set_time(const struct device *dev, const struct rtc_time *timeptr) { - Z_OOPS(Z_SYSCALL_DRIVER_RTC(dev, set_time)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(timeptr, sizeof(struct rtc_time))); + K_OOPS(K_SYSCALL_DRIVER_RTC(dev, set_time)); + K_OOPS(K_SYSCALL_MEMORY_READ(timeptr, sizeof(struct rtc_time))); return z_impl_rtc_set_time(dev, timeptr); } #include static inline int z_vrfy_rtc_get_time(const struct device *dev, struct rtc_time *timeptr) { - Z_OOPS(Z_SYSCALL_DRIVER_RTC(dev, get_time)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(timeptr, sizeof(struct rtc_time))); + K_OOPS(K_SYSCALL_DRIVER_RTC(dev, get_time)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(timeptr, sizeof(struct rtc_time))); return z_impl_rtc_get_time(dev, timeptr); } #include @@ -27,8 +27,8 @@ static inline int z_vrfy_rtc_get_time(const struct device *dev, struct rtc_time static inline int z_vrfy_rtc_alarm_get_supported_fields(const struct device *dev, uint16_t id, uint16_t *mask) { - Z_OOPS(Z_SYSCALL_DRIVER_RTC(dev, alarm_get_supported_fields)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(mask, sizeof(uint16_t))); + K_OOPS(K_SYSCALL_DRIVER_RTC(dev, alarm_get_supported_fields)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(mask, sizeof(uint16_t))); return z_impl_rtc_alarm_get_supported_fields(dev, id, mask); } #include @@ -36,8 +36,8 @@ static inline int z_vrfy_rtc_alarm_get_supported_fields(const struct device *dev static inline int z_vrfy_rtc_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask, const struct rtc_time *timeptr) { - Z_OOPS(Z_SYSCALL_DRIVER_RTC(dev, alarm_set_time)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(timeptr, sizeof(struct rtc_time))); + K_OOPS(K_SYSCALL_DRIVER_RTC(dev, alarm_set_time)); + K_OOPS(K_SYSCALL_MEMORY_READ(timeptr, sizeof(struct rtc_time))); return z_impl_rtc_alarm_set_time(dev, id, mask, timeptr); } #include @@ -45,16 +45,16 @@ static inline int z_vrfy_rtc_alarm_set_time(const struct device *dev, uint16_t i static inline int z_vrfy_rtc_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask, struct rtc_time *timeptr) { - Z_OOPS(Z_SYSCALL_DRIVER_RTC(dev, alarm_get_time)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(mask, sizeof(uint16_t))); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(timeptr, sizeof(struct rtc_time))); + K_OOPS(K_SYSCALL_DRIVER_RTC(dev, alarm_get_time)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(mask, sizeof(uint16_t))); + K_OOPS(K_SYSCALL_MEMORY_WRITE(timeptr, sizeof(struct rtc_time))); return z_impl_rtc_alarm_get_time(dev, id, mask, timeptr); } #include static inline int z_vrfy_rtc_alarm_is_pending(const struct device *dev, uint16_t id) { - Z_OOPS(Z_SYSCALL_DRIVER_RTC(dev, alarm_is_pending)); + K_OOPS(K_SYSCALL_DRIVER_RTC(dev, alarm_is_pending)); return z_impl_rtc_alarm_is_pending(dev, id); } #include @@ -63,7 +63,7 @@ static inline int z_vrfy_rtc_alarm_is_pending(const struct device *dev, uint16_t #ifdef CONFIG_RTC_CALIBRATION static inline int z_vrfy_rtc_set_calibration(const struct device *dev, int32_t calibration) { - Z_OOPS(Z_SYSCALL_DRIVER_RTC(dev, set_calibration)); + K_OOPS(K_SYSCALL_DRIVER_RTC(dev, set_calibration)); return z_impl_rtc_set_calibration(dev, calibration); } @@ -71,8 +71,8 @@ static inline int z_vrfy_rtc_set_calibration(const struct device *dev, int32_t c static inline int z_vrfy_rtc_get_calibration(const struct device *dev, int32_t *calibration) { - Z_OOPS(Z_SYSCALL_DRIVER_RTC(dev, get_calibration)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(calibration, sizeof(int32_t))); + K_OOPS(K_SYSCALL_DRIVER_RTC(dev, get_calibration)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(calibration, sizeof(int32_t))); return z_impl_rtc_get_calibration(dev, calibration); } #include diff --git a/drivers/rtc/rtc_ll_stm32.c b/drivers/rtc/rtc_ll_stm32.c index 7380fb102fa..8714439ef47 100644 --- a/drivers/rtc/rtc_ll_stm32.c +++ b/drivers/rtc/rtc_ll_stm32.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2023 Prevas A/S + * Copyright (c) 2023 Syslinbit * * SPDX-License-Identifier: Apache-2.0 * @@ -15,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -23,26 +25,130 @@ #include +#include + LOG_MODULE_REGISTER(rtc_stm32, CONFIG_RTC_LOG_LEVEL); -/* Convert calendar start time */ +#if defined(CONFIG_SOC_SERIES_STM32L1X) && !defined(RTC_SUBSECOND_SUPPORT) +/* subsecond counting is not supported by some STM32L1x MCUs */ +#define HW_SUBSECOND_SUPPORT (0) +#else +#define HW_SUBSECOND_SUPPORT (1) +#endif + /* RTC start time: 1st, Jan, 2000 */ -/* struct tm start: 1st, Jan, 1900 */ -#define TM_TO_RTC_OFFSET 100 +#define RTC_YEAR_REF 2000 +/* struct tm start time: 1st, Jan, 1900 */ +#define TM_YEAR_REF 1900 + +/* Convert part per billion calibration value to a number of clock pulses added or removed each + * 2^20 clock cycles so it is suitable for the CALR register fields + * + * nb_pulses = ppb * 2^20 / 10^9 = ppb * 2^11 / 5^9 = ppb * 2048 / 1953125 + */ +#define PPB_TO_NB_PULSES(ppb) DIV_ROUND_CLOSEST((ppb) * 2048, 1953125) + +/* Convert CALR register value (number of clock pulses added or removed each 2^20 clock cycles) + * to part ber billion calibration value + * + * ppb = nb_pulses * 10^9 / 2^20 = nb_pulses * 5^9 / 2^11 = nb_pulses * 1953125 / 2048 + */ +#define NB_PULSES_TO_PPB(pulses) DIV_ROUND_CLOSEST((pulses) * 1953125, 2048) + +/* CALP field can only be 512 or 0 as in reality CALP is a single bit field representing 512 pulses + * added every 2^20 clock cycles + */ +#define MAX_CALP (512) +#define MAX_CALM (511) + +#define MAX_PPB NB_PULSES_TO_PPB(MAX_CALP) +#define MIN_PPB -NB_PULSES_TO_PPB(MAX_CALM) + +/* Timeout in microseconds used to wait for flags */ +#define RTC_TIMEOUT 1000000 struct rtc_stm32_config { - LL_RTC_InitTypeDef ll_rtc_config; + uint32_t async_prescaler; + uint32_t sync_prescaler; const struct stm32_pclken *pclken; }; struct rtc_stm32_data { - /* Currently empty */ + struct k_mutex lock; }; +static int rtc_stm32_enter_initialization_mode(bool kernel_available) +{ + if (kernel_available) { + LL_RTC_EnableInitMode(RTC); + bool success = WAIT_FOR(LL_RTC_IsActiveFlag_INIT(RTC), RTC_TIMEOUT, k_msleep(1)); + + if (!success) { + return -EIO; + } + } else { + /* kernel is not available so use the blocking but otherwise equivalent function + * provided by LL + */ + ErrorStatus status = LL_RTC_EnterInitMode(RTC); + + if (status != SUCCESS) { + return -EIO; + } + } + + return 0; +} + +static inline void rtc_stm32_leave_initialization_mode(void) +{ + LL_RTC_DisableInitMode(RTC); +} + +static int rtc_stm32_configure(const struct device *dev) +{ + const struct rtc_stm32_config *cfg = dev->config; + + int err = 0; + + uint32_t hour_format = LL_RTC_GetHourFormat(RTC); + uint32_t sync_prescaler = LL_RTC_GetSynchPrescaler(RTC); + uint32_t async_prescaler = LL_RTC_GetAsynchPrescaler(RTC); + + LL_RTC_DisableWriteProtection(RTC); + + /* configuration process requires to stop the RTC counter so do it + * only if needed to avoid inducing time drift at each reset + */ + if ((hour_format != LL_RTC_HOURFORMAT_24HOUR) || + (sync_prescaler != cfg->sync_prescaler) || + (async_prescaler != cfg->async_prescaler)) { + err = rtc_stm32_enter_initialization_mode(false); + if (err == 0) { + LL_RTC_SetHourFormat(RTC, LL_RTC_HOURFORMAT_24HOUR); + LL_RTC_SetSynchPrescaler(RTC, cfg->sync_prescaler); + LL_RTC_SetAsynchPrescaler(RTC, cfg->async_prescaler); + } + + rtc_stm32_leave_initialization_mode(); + } + +#ifdef RTC_CR_BYPSHAD + LL_RTC_EnableShadowRegBypass(RTC); +#endif /* RTC_CR_BYPSHAD */ + + LL_RTC_EnableWriteProtection(RTC); + + return err; +} + static int rtc_stm32_init(const struct device *dev) { const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); const struct rtc_stm32_config *cfg = dev->config; + struct rtc_stm32_data *data = dev->data; + + int err = 0; if (!device_is_ready(clk)) { LOG_ERR("clock control device not ready"); @@ -55,6 +161,8 @@ static int rtc_stm32_init(const struct device *dev) return -EIO; } + k_mutex_init(&data->lock); + /* Enable Backup access */ z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY); #if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) @@ -71,100 +179,242 @@ static int rtc_stm32_init(const struct device *dev) z_stm32_hsem_unlock(CFG_HW_RCC_SEMID); - if (LL_RTC_Init(RTC, ((LL_RTC_InitTypeDef *)&cfg->ll_rtc_config)) != SUCCESS) { - return -EIO; + err = rtc_stm32_configure(dev); + + return err; +} + +static int rtc_stm32_set_time(const struct device *dev, const struct rtc_time *timeptr) +{ + struct rtc_stm32_data *data = dev->data; + + uint32_t real_year = timeptr->tm_year + TM_YEAR_REF; + + int err = 0; + + if (real_year < RTC_YEAR_REF) { + /* RTC does not support years before 2000 */ + return -EINVAL; } -#ifdef RTC_CR_BYPSHAD + if (timeptr->tm_wday == -1) { + /* day of the week is expected */ + return -EINVAL; + } + + err = k_mutex_lock(&data->lock, K_NO_WAIT); + if (err) { + return err; + } + + LOG_INF("Setting clock"); LL_RTC_DisableWriteProtection(RTC); - LL_RTC_EnableShadowRegBypass(RTC); + + err = rtc_stm32_enter_initialization_mode(true); + if (err) { + k_mutex_unlock(&data->lock); + return err; + } + + LL_RTC_DATE_SetYear(RTC, bin2bcd(real_year - RTC_YEAR_REF)); + LL_RTC_DATE_SetMonth(RTC, bin2bcd(timeptr->tm_mon + 1)); + LL_RTC_DATE_SetDay(RTC, bin2bcd(timeptr->tm_mday)); + + if (timeptr->tm_wday == 0) { + /* sunday (tm_wday = 0) is not represented by the same value in hardware */ + LL_RTC_DATE_SetWeekDay(RTC, LL_RTC_WEEKDAY_SUNDAY); + } else { + /* all the other values are consistent with what is expected by hardware */ + LL_RTC_DATE_SetWeekDay(RTC, timeptr->tm_wday); + } + + + LL_RTC_TIME_SetHour(RTC, bin2bcd(timeptr->tm_hour)); + LL_RTC_TIME_SetMinute(RTC, bin2bcd(timeptr->tm_min)); + LL_RTC_TIME_SetSecond(RTC, bin2bcd(timeptr->tm_sec)); + + rtc_stm32_leave_initialization_mode(); + LL_RTC_EnableWriteProtection(RTC); -#endif /* RTC_CR_BYPSHAD */ - return 0; + k_mutex_unlock(&data->lock); + + return err; } -static const struct stm32_pclken rtc_clk[] = STM32_DT_INST_CLOCKS(0); +static int rtc_stm32_get_time(const struct device *dev, struct rtc_time *timeptr) +{ + struct rtc_stm32_data *data = dev->data; -static const struct rtc_stm32_config rtc_config = { - .ll_rtc_config = { - .HourFormat = LL_RTC_HOURFORMAT_24HOUR, -#if DT_INST_CLOCKS_CELL(1, bus) == STM32_SRC_LSI - /* prescaler values for LSI @ 32 KHz */ - .AsynchPrescaler = 0x7F, - .SynchPrescaler = 0x00F9, -#else /* DT_INST_CLOCKS_CELL(1, bus) == STM32_SRC_LSE */ - /* prescaler values for LSE @ 32768 Hz */ - .AsynchPrescaler = 0x7F, - .SynchPrescaler = 0x00FF, + uint32_t rtc_date, rtc_time; + +#if HW_SUBSECOND_SUPPORT + const struct rtc_stm32_config *cfg = dev->config; + uint32_t rtc_subsecond; #endif - }, - .pclken = rtc_clk, -}; -static int rtc_stm32_set_time(const struct device *dev, const struct rtc_time *timeptr) + int err = k_mutex_lock(&data->lock, K_NO_WAIT); + + if (err) { + return err; + } + + do { + /* read date, time and subseconds and relaunch if a day increment occurred + * while doing so as it will result in an erroneous result otherwise + */ + rtc_date = LL_RTC_DATE_Get(RTC); + do { + /* read time and subseconds and relaunch if a second increment occurred + * while doing so as it will result in an erroneous result otherwise + */ + rtc_time = LL_RTC_TIME_Get(RTC); +#if HW_SUBSECOND_SUPPORT + rtc_subsecond = LL_RTC_TIME_GetSubSecond(RTC); +#endif + } while (rtc_time != LL_RTC_TIME_Get(RTC)); + } while (rtc_date != LL_RTC_DATE_Get(RTC)); + + k_mutex_unlock(&data->lock); + + timeptr->tm_year = bcd2bin(__LL_RTC_GET_YEAR(rtc_date)) + RTC_YEAR_REF - TM_YEAR_REF; + /* tm_mon allowed values are 0-11 */ + timeptr->tm_mon = bcd2bin(__LL_RTC_GET_MONTH(rtc_date)) - 1; + timeptr->tm_mday = bcd2bin(__LL_RTC_GET_DAY(rtc_date)); + + int hw_wday = __LL_RTC_GET_WEEKDAY(rtc_date); + + if (hw_wday == LL_RTC_WEEKDAY_SUNDAY) { + /* LL_RTC_WEEKDAY_SUNDAY = 7 but a 0 is expected in tm_wday for sunday */ + timeptr->tm_wday = 0; + } else { + /* all other values are consistent between hardware and rtc_time structure */ + timeptr->tm_wday = hw_wday; + } + + timeptr->tm_hour = bcd2bin(__LL_RTC_GET_HOUR(rtc_time)); + timeptr->tm_min = bcd2bin(__LL_RTC_GET_MINUTE(rtc_time)); + timeptr->tm_sec = bcd2bin(__LL_RTC_GET_SECOND(rtc_time)); + +#if HW_SUBSECOND_SUPPORT + uint64_t temp = ((uint64_t)(cfg->sync_prescaler - rtc_subsecond)) * 1000000000L; + + timeptr->tm_nsec = DIV_ROUND_CLOSEST(temp, cfg->sync_prescaler + 1); +#else + timeptr->tm_nsec = 0; +#endif + + /* unknown values */ + timeptr->tm_yday = -1; + timeptr->tm_isdst = -1; + + return 0; +} + +#ifdef CONFIG_RTC_CALIBRATION +#if !defined(CONFIG_SOC_SERIES_STM32F2X) && \ + !(defined(CONFIG_SOC_SERIES_STM32L1X) && !defined(RTC_SMOOTHCALIB_SUPPORT)) +static int rtc_stm32_set_calibration(const struct device *dev, int32_t calibration) { - LOG_INF("Setting clock"); - LL_RTC_DisableWriteProtection(RTC); + ARG_UNUSED(dev); - LL_RTC_EnableInitMode(RTC); + /* Note : calibration is considered here to be ppb value to apply + * on clock period (not frequency) but with an opposite sign + */ - while (!LL_RTC_IsActiveFlag_INIT(RTC)) { - }; + if ((calibration > MAX_PPB) || (calibration < MIN_PPB)) { + /* out of supported range */ + return -EINVAL; + } - LL_RTC_DATE_SetYear(RTC, __LL_RTC_CONVERT_BIN2BCD(timeptr->tm_year - TM_TO_RTC_OFFSET)); - LL_RTC_DATE_SetMonth(RTC, __LL_RTC_CONVERT_BIN2BCD(timeptr->tm_mon + 1)); - LL_RTC_DATE_SetDay(RTC, __LL_RTC_CONVERT_BIN2BCD(timeptr->tm_mday)); + int32_t nb_pulses = PPB_TO_NB_PULSES(calibration); - LL_RTC_DATE_SetWeekDay(RTC, __LL_RTC_CONVERT_BIN2BCD(timeptr->tm_wday) + 1); + /* we tested calibration against supported range + * so theoretically nb_pulses is also within range + */ + __ASSERT_NO_MSG(nb_pulses <= MAX_CALP); + __ASSERT_NO_MSG(nb_pulses >= -MAX_CALM); - LL_RTC_TIME_SetHour(RTC, __LL_RTC_CONVERT_BIN2BCD(timeptr->tm_hour)); - LL_RTC_TIME_SetMinute(RTC, __LL_RTC_CONVERT_BIN2BCD(timeptr->tm_min)); - LL_RTC_TIME_SetSecond(RTC, __LL_RTC_CONVERT_BIN2BCD(timeptr->tm_sec)); + uint32_t calp, calm; - LL_RTC_DisableInitMode(RTC); + if (nb_pulses > 0) { + calp = LL_RTC_CALIB_INSERTPULSE_SET; + calm = MAX_CALP - nb_pulses; + } else { + calp = LL_RTC_CALIB_INSERTPULSE_NONE; + calm = -nb_pulses; + } + + /* wait for recalibration to be ok if a previous recalibration occurred */ + if (!WAIT_FOR(LL_RTC_IsActiveFlag_RECALP(RTC) == 0, 100000, k_msleep(1))) { + return -EIO; + } + + LL_RTC_DisableWriteProtection(RTC); + + MODIFY_REG(RTC->CALR, RTC_CALR_CALP | RTC_CALR_CALM, calp | calm); LL_RTC_EnableWriteProtection(RTC); return 0; } -static int rtc_stm32_get_time(const struct device *dev, struct rtc_time *timeptr) +static int rtc_stm32_get_calibration(const struct device *dev, int32_t *calibration) { ARG_UNUSED(dev); - uint32_t rtc_date, rtc_time; + uint32_t calr = sys_read32((mem_addr_t) &RTC->CALR); - /* Read time and date registers */ - rtc_time = LL_RTC_TIME_Get(RTC); - rtc_date = LL_RTC_DATE_Get(RTC); + bool calp_enabled = READ_BIT(calr, RTC_CALR_CALP); + uint32_t calm = READ_BIT(calr, RTC_CALR_CALM); - timeptr->tm_year = TM_TO_RTC_OFFSET + __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_YEAR(rtc_date)); - /* tm_mon allowed values are 0-11 */ - timeptr->tm_mon = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_MONTH(rtc_date)) - 1; - timeptr->tm_mday = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_DAY(rtc_date)); - timeptr->tm_wday = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_WEEKDAY(rtc_date)) - 1; + int32_t nb_pulses = -((int32_t) calm); - timeptr->tm_hour = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_HOUR(rtc_time)); - timeptr->tm_min = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_MINUTE(rtc_time)); - timeptr->tm_sec = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_SECOND(rtc_time)); + if (calp_enabled) { + nb_pulses += MAX_CALP; + } - timeptr->tm_nsec = LL_RTC_TIME_GetSubSecond(RTC); + *calibration = NB_PULSES_TO_PPB(nb_pulses); return 0; } +#endif +#endif /* CONFIG_RTC_CALIBRATION */ struct rtc_driver_api rtc_stm32_driver_api = { .set_time = rtc_stm32_set_time, .get_time = rtc_stm32_get_time, /* RTC_ALARM not supported */ /* RTC_UPDATE not supported */ +#ifdef CONFIG_RTC_CALIBRATION +#if !defined(CONFIG_SOC_SERIES_STM32F2X) && \ + !(defined(CONFIG_SOC_SERIES_STM32L1X) && !defined(RTC_SMOOTHCALIB_SUPPORT)) + .set_calibration = rtc_stm32_set_calibration, + .get_calibration = rtc_stm32_get_calibration, +#else +#error RTC calibration for devices without smooth calibration feature is not supported yet +#endif +#endif /* CONFIG_RTC_CALIBRATION */ +}; + +static const struct stm32_pclken rtc_clk[] = STM32_DT_INST_CLOCKS(0); + +BUILD_ASSERT(DT_INST_CLOCKS_HAS_IDX(0, 1), "RTC source clock not defined in the device tree"); + +static const struct rtc_stm32_config rtc_config = { +#if DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_LSI + /* prescaler values for LSI @ 32 KHz */ + .async_prescaler = 0x7F, + .sync_prescaler = 0x00F9, +#else /* DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_LSE */ + /* prescaler values for LSE @ 32768 Hz */ + .async_prescaler = 0x7F, + .sync_prescaler = 0x00FF, +#endif + .pclken = rtc_clk, }; -#define RTC_STM32_DEV_CFG(n) \ - static struct rtc_stm32_data rtc_data_##n = {}; \ - \ - DEVICE_DT_INST_DEFINE(n, &rtc_stm32_init, NULL, &rtc_data_##n, &rtc_config, POST_KERNEL, \ - CONFIG_RTC_INIT_PRIORITY, &rtc_stm32_driver_api); +static struct rtc_stm32_data rtc_data; -DT_INST_FOREACH_STATUS_OKAY(RTC_STM32_DEV_CFG); +DEVICE_DT_INST_DEFINE(0, &rtc_stm32_init, NULL, &rtc_data, &rtc_config, PRE_KERNEL_1, + CONFIG_RTC_INIT_PRIORITY, &rtc_stm32_driver_api); diff --git a/drivers/rtc/rtc_pcf8523.c b/drivers/rtc/rtc_pcf8523.c index 1e1a7a1ddfa..b6be011d61b 100644 --- a/drivers/rtc/rtc_pcf8523.c +++ b/drivers/rtc/rtc_pcf8523.c @@ -254,8 +254,12 @@ static int pcf8523_int1_enable_unlocked(const struct device *dev, bool enable) return 0; } -static void pcf8523_int1_thread(const struct device *dev) +static void pcf8523_int1_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; struct pcf8523_data *data = dev->data; rtc_alarm_callback alarm_callback = NULL; void *alarm_user_data = NULL; @@ -791,7 +795,7 @@ static int pcf8523_init(const struct device *dev) tid = k_thread_create(&data->int1_thread, data->int1_stack, K_THREAD_STACK_SIZEOF(data->int1_stack), - (k_thread_entry_t)pcf8523_int1_thread, (void *)dev, NULL, + pcf8523_int1_thread, (void *)dev, NULL, NULL, CONFIG_RTC_PCF8523_THREAD_PRIO, 0, K_NO_WAIT); k_thread_name_set(tid, "pcf8523"); diff --git a/drivers/rtc/rtc_sam.c b/drivers/rtc/rtc_sam.c new file mode 100644 index 00000000000..059a2b1b33e --- /dev/null +++ b/drivers/rtc/rtc_sam.c @@ -0,0 +1,712 @@ +/* + * Copyright (c) 2023 Bjarki Arge Andreasen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT atmel_sam_rtc + +#include +#include +#include +#include +#include + +#include +#include + +#define RTC_SAM_REG_GET_FIELD(value, field) \ + ((RTC_##field##_Msk & value) >> RTC_##field##_Pos) + +#define RTC_SAM_WPMR_DISABLE 0x52544300 +#define RTC_SAM_WPMR_ENABLE 0x52544301 + +#define RTC_SAM_CALIBRATE_PPB_MAX (1950000) +#define RTC_SAM_CALIBRATE_PPB_MIN (-1950000) +#define RTC_SAM_CALIBRATE_PPB_QUANTA (1500) +#define RTC_SAM_CALIBRATE_PPB_LOW_SCALE (30500) + +typedef void (*rtc_sam_irq_init_fn_ptr)(void); + +struct rtc_sam_config { + Rtc *regs; + uint16_t irq_num; + rtc_sam_irq_init_fn_ptr irq_init_fn_ptr; +}; + +struct rtc_sam_data { +#ifdef CONFIG_RTC_ALARM + rtc_alarm_callback alarm_callback; + void *alarm_user_data; +#endif /* CONFIG_RTC_ALARM */ +#ifdef CONFIG_RTC_UPDATE + rtc_update_callback update_callback; + void *update_user_data; +#endif /* CONFIG_RTC_UPDATE */ + struct k_spinlock lock; + struct k_sem cr_sec_evt_sem; + struct k_sem cr_upd_ack_sem; +}; + +static void rtc_sam_disable_wp(void) +{ + REG_RTC_WPMR = RTC_SAM_WPMR_DISABLE; +} + +static void rtc_sam_enable_wp(void) +{ + REG_RTC_WPMR = RTC_SAM_WPMR_ENABLE; +} + +static bool rtc_sam_validate_tm(const struct rtc_time *timeptr, uint32_t mask) +{ + if ((mask & RTC_ALARM_TIME_MASK_SECOND) && + (timeptr->tm_sec < 0 || timeptr->tm_sec > 59)) { + return false; + } + + if ((mask & RTC_ALARM_TIME_MASK_MINUTE) && + (timeptr->tm_min < 0 || timeptr->tm_min > 59)) { + return false; + } + + if ((mask & RTC_ALARM_TIME_MASK_HOUR) && + (timeptr->tm_hour < 0 || timeptr->tm_hour > 23)) { + return false; + } + + if ((mask & RTC_ALARM_TIME_MASK_MONTH) && + (timeptr->tm_mon < 0 || timeptr->tm_mon > 11)) { + return false; + } + + if ((mask & RTC_ALARM_TIME_MASK_MONTHDAY) && + (timeptr->tm_mday < 1 || timeptr->tm_mday > 31)) { + return false; + } + + if ((mask & RTC_ALARM_TIME_MASK_YEAR) && + (timeptr->tm_year < 0 || timeptr->tm_year > 199)) { + return false; + } + + return true; +} + +static uint32_t rtc_sam_timr_from_tm(const struct rtc_time *timeptr) +{ + uint32_t timr; + + timr = RTC_TIMR_SEC(bin2bcd(timeptr->tm_sec)); + timr |= RTC_TIMR_MIN(bin2bcd(timeptr->tm_min)); + timr |= RTC_TIMR_HOUR(bin2bcd(timeptr->tm_hour)); + + return timr; +} + +static uint32_t rtc_sam_calr_from_tm(const struct rtc_time *timeptr) +{ + uint32_t calr; + uint8_t centuries; + uint8_t years; + + calr = RTC_CALR_DATE(bin2bcd(timeptr->tm_mday)); + calr |= RTC_CALR_MONTH(bin2bcd(timeptr->tm_mon + 1)); + centuries = (uint8_t)((timeptr->tm_year / 100) + 19); + years = (uint8_t)((timeptr->tm_year % 100)); + calr |= RTC_CALR_CENT(bin2bcd(centuries)); + calr |= RTC_CALR_YEAR(bin2bcd(years)); + calr |= RTC_CALR_DAY(bin2bcd(timeptr->tm_wday + 1)); + return calr; +} + +static int rtc_sam_set_time(const struct device *dev, const struct rtc_time *timeptr) +{ + struct rtc_sam_data *data = dev->data; + const struct rtc_sam_config *config = dev->config; + Rtc *regs = config->regs; + + if (rtc_sam_validate_tm(timeptr, UINT32_MAX) == false) { + return -EINVAL; + } + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + k_sem_reset(&data->cr_sec_evt_sem); + k_sem_take(&data->cr_sec_evt_sem, K_MSEC(1100)); + k_sem_reset(&data->cr_upd_ack_sem); + + /* Enable update acknowledge interrupt */ + regs->RTC_IER = RTC_IER_ACKEN; + + rtc_sam_disable_wp(); + + /* Request update */ + regs->RTC_CR = (RTC_CR_UPDTIM | RTC_CR_UPDCAL); + + /* Await update acknowledge */ + if (k_sem_take(&data->cr_upd_ack_sem, K_MSEC(1100)) < 0) { + regs->RTC_CR = 0; + + rtc_sam_enable_wp(); + + /* Disable update acknowledge interrupt */ + regs->RTC_IDR = RTC_IDR_ACKDIS; + + k_spin_unlock(&data->lock, key); + return -EAGAIN; + } + + regs->RTC_TIMR = rtc_sam_timr_from_tm(timeptr); + regs->RTC_CALR = rtc_sam_calr_from_tm(timeptr); + regs->RTC_CR = 0; + rtc_sam_enable_wp(); + regs->RTC_IDR = RTC_IDR_ACKDIS; + k_spin_unlock(&data->lock, key); + return 0; +} + +static int rtc_sam_get_time(const struct device *dev, struct rtc_time *timeptr) +{ + const struct rtc_sam_config *config = dev->config; + Rtc *regs = config->regs; + + uint32_t timr0; + uint32_t calr0; + uint32_t timr1; + uint32_t calr1; + + /* Validate time and date */ + if (regs->RTC_VER & (RTC_VER_NVTIM | RTC_VER_NVCAL)) { + return -ENODATA; + } + + /* Read until synchronized (registers updated async) */ + while (1) { + timr0 = regs->RTC_TIMR; + calr0 = regs->RTC_CALR; + timr1 = regs->RTC_TIMR; + calr1 = regs->RTC_CALR; + + if ((timr0 == timr1) && (calr0 == calr1)) { + break; + } + } + + timeptr->tm_sec = bcd2bin(RTC_SAM_REG_GET_FIELD(timr0, TIMR_SEC)); + timeptr->tm_min = bcd2bin(RTC_SAM_REG_GET_FIELD(timr0, TIMR_MIN)); + timeptr->tm_hour = bcd2bin(RTC_SAM_REG_GET_FIELD(timr0, TIMR_HOUR)); + timeptr->tm_mday = bcd2bin(RTC_SAM_REG_GET_FIELD(calr0, CALR_DATE)); + timeptr->tm_mon = bcd2bin(RTC_SAM_REG_GET_FIELD(calr0, CALR_MONTH)) - 1; + + timeptr->tm_year = bcd2bin(RTC_SAM_REG_GET_FIELD(calr0, CALR_YEAR)); + timeptr->tm_year += ((int)bcd2bin(RTC_SAM_REG_GET_FIELD(calr0, CALR_CENT))) * 100; + timeptr->tm_year -= 1900; + + timeptr->tm_wday = bcd2bin(RTC_SAM_REG_GET_FIELD(calr0, CALR_DAY)) - 1; + timeptr->tm_yday = -1; + timeptr->tm_isdst = -1; + timeptr->tm_nsec = 0; + return 0; +} + +static void rtc_sam_isr(const struct device *dev) +{ + struct rtc_sam_data *data = dev->data; + const struct rtc_sam_config *config = dev->config; + Rtc *regs = config->regs; + + uint32_t sr = regs->RTC_SR; + + if (sr & RTC_SR_ACKUPD) { + regs->RTC_SCCR = RTC_SCCR_ACKCLR; + k_sem_give(&data->cr_upd_ack_sem); + } + +#ifdef CONFIG_RTC_ALARM + if (sr & RTC_SR_ALARM) { + regs->RTC_SCCR = RTC_SCCR_ALRCLR; + if (data->alarm_callback != NULL) { + data->alarm_callback(dev, 0, data->alarm_user_data); + } + } +#endif /* CONFIG_RTC_ALARM */ + +#ifdef CONFIG_RTC_UPDATE + if (sr & RTC_SR_SEC) { + regs->RTC_SCCR = RTC_SCCR_SECCLR; + if (data->update_callback != NULL) { + data->update_callback(dev, data->update_user_data); + } + + k_sem_give(&data->cr_sec_evt_sem); + } +#endif /* CONFIG_RTC_UPDATE */ +} + +#ifdef CONFIG_RTC_ALARM +static uint16_t rtc_sam_alarm_get_supported_mask(void) +{ + return (RTC_ALARM_TIME_MASK_SECOND + | RTC_ALARM_TIME_MASK_MINUTE + | RTC_ALARM_TIME_MASK_HOUR + | RTC_ALARM_TIME_MASK_MONTHDAY + | RTC_ALARM_TIME_MASK_MONTH); +} + +static uint32_t rtc_atmel_timalr_from_tm(const struct rtc_time *timeptr, uint32_t mask) +{ + uint32_t timalr = 0; + + if (mask & RTC_ALARM_TIME_MASK_SECOND) { + timalr |= RTC_TIMALR_SECEN; + timalr |= RTC_TIMALR_SEC(bin2bcd(timeptr->tm_sec)); + } + + if (mask & RTC_ALARM_TIME_MASK_MINUTE) { + timalr |= RTC_TIMALR_MINEN; + timalr |= RTC_TIMALR_MIN(bin2bcd(timeptr->tm_min)); + } + + if (mask & RTC_ALARM_TIME_MASK_HOUR) { + timalr |= RTC_TIMALR_HOUREN; + timalr |= RTC_TIMALR_HOUR(bin2bcd(timeptr->tm_hour)); + } + + return timalr; +} + +static uint32_t rtc_atmel_calalr_from_tm(const struct rtc_time *timeptr, uint32_t mask) +{ + uint32_t calalr = RTC_CALALR_MONTH(1) | RTC_CALALR_DATE(1); + + if (mask & RTC_ALARM_TIME_MASK_MONTH) { + calalr |= RTC_CALALR_MTHEN; + calalr |= RTC_CALALR_MONTH(bin2bcd(timeptr->tm_mon + 1)); + } + + if (mask & RTC_ALARM_TIME_MASK_MONTHDAY) { + calalr |= RTC_CALALR_DATEEN; + calalr |= RTC_CALALR_DATE(bin2bcd(timeptr->tm_mday)); + } + + return calalr; +} + +static uint32_t rtc_sam_alarm_mask_from_timalr(uint32_t timalr) +{ + uint32_t mask = 0; + + if (timalr & RTC_TIMALR_SECEN) { + mask |= RTC_ALARM_TIME_MASK_SECOND; + } + + if (timalr & RTC_TIMALR_MINEN) { + mask |= RTC_ALARM_TIME_MASK_MINUTE; + } + + if (timalr & RTC_TIMALR_HOUREN) { + mask |= RTC_ALARM_TIME_MASK_HOUR; + } + + return mask; +} + +static uint32_t rtc_sam_alarm_mask_from_calalr(uint32_t calalr) +{ + uint32_t mask = 0; + + if (calalr & RTC_CALALR_MTHEN) { + mask |= RTC_ALARM_TIME_MASK_MONTH; + } + + if (calalr & RTC_CALALR_DATEEN) { + mask |= RTC_ALARM_TIME_MASK_MONTHDAY; + } + + return mask; +} + +static void rtc_sam_tm_from_timalr_calalr(struct rtc_time *timeptr, uint32_t mask, + uint32_t timalr, uint32_t calalr) +{ + memset(timeptr, 0x00, sizeof(*timeptr)); + + if (mask & RTC_ALARM_TIME_MASK_SECOND) { + timeptr->tm_sec = bcd2bin(RTC_SAM_REG_GET_FIELD(timalr, TIMALR_SEC)); + } + + if (mask & RTC_ALARM_TIME_MASK_MINUTE) { + timeptr->tm_min = bcd2bin(RTC_SAM_REG_GET_FIELD(timalr, TIMALR_MIN)); + } + + if (mask & RTC_ALARM_TIME_MASK_HOUR) { + timeptr->tm_hour = bcd2bin(RTC_SAM_REG_GET_FIELD(timalr, TIMALR_HOUR)); + } + + if (mask & RTC_ALARM_TIME_MASK_MONTHDAY) { + timeptr->tm_mday = bcd2bin(RTC_SAM_REG_GET_FIELD(calalr, CALALR_DATE)); + } + + if (mask & RTC_ALARM_TIME_MASK_MONTH) { + timeptr->tm_mon = bcd2bin(RTC_SAM_REG_GET_FIELD(calalr, CALALR_MONTH)) - 1; + } +} + +static int rtc_sam_alarm_get_supported_fields(const struct device *dev, uint16_t id, + uint16_t *mask) +{ + ARG_UNUSED(dev); + ARG_UNUSED(id); + + *mask = rtc_sam_alarm_get_supported_mask(); + return 0; +} + +static int rtc_sam_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask, + const struct rtc_time *timeptr) +{ + struct rtc_sam_data *data = dev->data; + const struct rtc_sam_config *config = dev->config; + Rtc *regs = config->regs; + + uint32_t timalr; + uint32_t calalr; + uint32_t mask_supported; + + mask_supported = rtc_sam_alarm_get_supported_mask(); + + if ((id != 0)) { + return -EINVAL; + } + + if ((mask > 0) && (timeptr == NULL)) { + return -EINVAL; + } + + if (mask & ~mask_supported) { + return -EINVAL; + } + + if (rtc_sam_validate_tm(timeptr, mask) == false) { + return -EINVAL; + } + + timalr = rtc_atmel_timalr_from_tm(timeptr, mask); + calalr = rtc_atmel_calalr_from_tm(timeptr, mask); + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + irq_disable(config->irq_num); + rtc_sam_disable_wp(); + + /* Set RTC alarm time */ + regs->RTC_TIMALR = timalr; + regs->RTC_CALALR = calalr; + + rtc_sam_enable_wp(); + + /* Clear alarm pending status */ + regs->RTC_SCCR = RTC_SCCR_ALRCLR; + + irq_enable(config->irq_num); + k_spin_unlock(&data->lock, key); + return 0; +} + +static int rtc_sam_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask, + struct rtc_time *timeptr) +{ + struct rtc_sam_data *data = dev->data; + const struct rtc_sam_config *config = dev->config; + Rtc *regs = config->regs; + + uint32_t timalr; + uint32_t calalr; + + if ((id != 0) || (mask == NULL) || (timeptr == NULL)) { + return -EINVAL; + } + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + timalr = regs->RTC_TIMALR; + calalr = regs->RTC_CALALR; + + k_spin_unlock(&data->lock, key); + + *mask = rtc_sam_alarm_mask_from_timalr(timalr); + *mask |= rtc_sam_alarm_mask_from_calalr(calalr); + + rtc_sam_tm_from_timalr_calalr(timeptr, *mask, timalr, calalr); + return 0; +} + +static int rtc_sam_alarm_is_pending(const struct device *dev, uint16_t id) +{ + struct rtc_sam_data *data = dev->data; + const struct rtc_sam_config *config = dev->config; + Rtc *regs = config->regs; + + if (id != 0) { + return -EINVAL; + } + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + if ((regs->RTC_SR & RTC_SR_ALARM) == 0) { + k_spin_unlock(&data->lock, key); + + return 0; + } + + regs->RTC_SCCR = RTC_SCCR_ALRCLR; + k_spin_unlock(&data->lock, key); + return 1; +} + +static int rtc_sam_alarm_set_callback(const struct device *dev, uint16_t id, + rtc_alarm_callback callback, void *user_data) +{ + struct rtc_sam_data *data = dev->data; + const struct rtc_sam_config *config = dev->config; + Rtc *regs = config->regs; + + if (id != 0) { + return -EINVAL; + } + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + irq_disable(config->irq_num); + data->alarm_callback = callback; + data->alarm_user_data = user_data; + + if (data->alarm_callback) { + regs->RTC_IER = RTC_IER_ALREN; + } else { + regs->RTC_IDR = RTC_IDR_ALRDIS; + } + + irq_enable(config->irq_num); + k_spin_unlock(&data->lock, key); + return 0; +} +#endif /* CONFIG_RTC_ALARM */ + +#ifdef CONFIG_RTC_UPDATE +static int rtc_sam_update_set_callback(const struct device *dev, rtc_update_callback callback, + void *user_data) +{ + struct rtc_sam_data *data = dev->data; + const struct rtc_sam_config *config = dev->config; + Rtc *regs = config->regs; + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + irq_disable(config->irq_num); + + data->update_callback = callback; + data->update_user_data = user_data; + + if (data->update_callback) { + regs->RTC_IER = RTC_IER_SECEN; + } else { + regs->RTC_IDR = RTC_IDR_SECDIS; + } + + irq_enable(config->irq_num); + + k_spin_unlock(&data->lock, key); + + return 0; +} +#endif /* CONFIG_RTC_UPDATE */ + +#ifdef CONFIG_RTC_CALIBRATION +static int rtc_sam_set_calibration(const struct device *dev, int32_t calibration) +{ + struct rtc_sam_data *data = dev->data; + const struct rtc_sam_config *config = dev->config; + Rtc *regs = config->regs; + bool negative_calibration; + bool high_calibration; + uint32_t slow_clock_calibration; + uint32_t mr; + + if ((calibration < RTC_SAM_CALIBRATE_PPB_MIN) || + (calibration > RTC_SAM_CALIBRATE_PPB_MAX)) { + return -EINVAL; + } + + /* The value written to the register is absolute */ + if (calibration < 0) { + negative_calibration = true; + calibration = -calibration; + } else { + negative_calibration = false; + } + + /* + * Formula adapted from + * Atmel-11157-32-bit-Cortex-M4-Microcontroller-SAM4E16-SAM4E8_Datasheet.pdf + * section 15.6.2 + * + * Formula if RTC_MR_HIGHPPM is 0 + * + * RTC_MR_CORRECTION = (3906 / (20 * ppm)) - 1 + * + * Formula if RTC_MR_HIGHPPM is 1 + * + * RTC_MR_CORRECTION = (3906 / ppm) - 1 + * + * Since we are working with ppb, we adapt the formula by increasing the + * terms of the fraction by 1000, turning the ppm into ppb + * + * Adapted formula if RTC_MR_HIGHPPM is 0 + * + * RTC_MR_CORRECTION = (3906000 / (20 * ppb)) - 1 + * + * Adapted formula if RTC_MR_HIGHPPM is 1 + * + * RTC_MR_CORRECTION = (3906000 / ppb) - 1 + */ + if (calibration < RTC_SAM_CALIBRATE_PPB_QUANTA) { + high_calibration = false; + slow_clock_calibration = 0; + } else if (calibration < RTC_SAM_CALIBRATE_PPB_LOW_SCALE) { + high_calibration = false; + slow_clock_calibration = (uint32_t)((3906000 / (20 * calibration)) - 1); + } else { + high_calibration = true; + slow_clock_calibration = (uint32_t)((3906000 / calibration) - 1); + } + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + rtc_sam_disable_wp(); + + mr = regs->RTC_MR; + + if (negative_calibration == true) { + mr |= RTC_MR_NEGPPM; + } else { + mr &= ~RTC_MR_NEGPPM; + } + + mr &= ~RTC_MR_CORRECTION_Msk; + mr |= RTC_MR_CORRECTION(slow_clock_calibration); + + if (high_calibration == true) { + mr |= RTC_MR_HIGHPPM; + } else { + mr &= ~RTC_MR_HIGHPPM; + } + + regs->RTC_MR = mr; + + rtc_sam_enable_wp(); + + k_spin_unlock(&data->lock, key); + + return 0; +} + +static int rtc_sam_get_calibration(const struct device *dev, int32_t *calibration) +{ + const struct rtc_sam_config *config = dev->config; + Rtc *regs = config->regs; + + uint32_t mr; + int32_t correction; + + if (calibration == NULL) { + return -EINVAL; + } + + mr = regs->RTC_MR; + + correction = (int32_t)RTC_SAM_REG_GET_FIELD(mr, MR_CORRECTION); + + /* Formula documented in rtc_sam_set_calibration() */ + if (correction == 0) { + *calibration = 0; + } else if (mr & RTC_MR_HIGHPPM) { + *calibration = 3906000 / (correction + 1); + } else { + *calibration = 3906000 / ((correction + 1) * 20); + } + + if (mr & RTC_MR_NEGPPM) { + *calibration = -*calibration; + } + + return 0; +} +#endif /* CONFIG_RTC_CALIBRATION */ + +static struct rtc_driver_api rtc_sam_driver_api = { + .set_time = rtc_sam_set_time, + .get_time = rtc_sam_get_time, +#ifdef CONFIG_RTC_ALARM + .alarm_get_supported_fields = rtc_sam_alarm_get_supported_fields, + .alarm_set_time = rtc_sam_alarm_set_time, + .alarm_get_time = rtc_sam_alarm_get_time, + .alarm_is_pending = rtc_sam_alarm_is_pending, + .alarm_set_callback = rtc_sam_alarm_set_callback, +#endif /* CONFIG_RTC_ALARM */ +#ifdef CONFIG_RTC_UPDATE + .update_set_callback = rtc_sam_update_set_callback, +#endif /* CONFIG_RTC_UPDATE */ +#ifdef CONFIG_RTC_CALIBRATION + .set_calibration = rtc_sam_set_calibration, + .get_calibration = rtc_sam_get_calibration, +#endif /* CONFIG_RTC_CALIBRATION */ +}; + +static int rtc_sam_init(const struct device *dev) +{ + struct rtc_sam_data *data = dev->data; + const struct rtc_sam_config *config = dev->config; + Rtc *regs = config->regs; + + rtc_sam_disable_wp(); + regs->RTC_MR &= ~(RTC_MR_HRMOD | RTC_MR_PERSIAN); + regs->RTC_CR = 0; + rtc_sam_enable_wp(); + regs->RTC_IDR = (RTC_IDR_ACKDIS + | RTC_IDR_ALRDIS + | RTC_IDR_SECDIS + | RTC_IDR_TIMDIS + | RTC_IDR_CALDIS + | RTC_IDR_TDERRDIS); + + k_sem_init(&data->cr_sec_evt_sem, 0, 1); + k_sem_init(&data->cr_upd_ack_sem, 0, 1); + config->irq_init_fn_ptr(); + irq_enable(config->irq_num); + return 0; +} + +#define RTC_SAM_DEVICE(id) \ + static void rtc_sam_irq_init_##id(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), \ + rtc_sam_isr, DEVICE_DT_INST_GET(id), 0); \ + } \ + \ + static const struct rtc_sam_config rtc_sam_config_##id = { \ + .regs = (Rtc *)DT_INST_REG_ADDR(id), \ + .irq_num = DT_INST_IRQN(id), \ + .irq_init_fn_ptr = rtc_sam_irq_init_##id, \ + }; \ + \ + static struct rtc_sam_data rtc_sam_data_##id; \ + \ + DEVICE_DT_INST_DEFINE(id, rtc_sam_init, NULL, \ + &rtc_sam_data_##id, \ + &rtc_sam_config_##id, POST_KERNEL, \ + CONFIG_RTC_INIT_PRIORITY, \ + &rtc_sam_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(RTC_SAM_DEVICE); diff --git a/drivers/rtc/rtc_shell.c b/drivers/rtc/rtc_shell.c index c6de3f0a632..8dcaf46f875 100644 --- a/drivers/rtc/rtc_shell.c +++ b/drivers/rtc/rtc_shell.c @@ -197,8 +197,6 @@ static int cmd_get(const struct shell *sh, size_t argc, char **argv) { const struct device *dev = device_get_binding(argv[1]); - printk("in RTC Shell Get\n"); - if (!device_is_ready(dev)) { shell_error(sh, "device %s not ready", argv[1]); return -ENODEV; diff --git a/drivers/rtc/rtc_smartbond.c b/drivers/rtc/rtc_smartbond.c new file mode 100644 index 00000000000..a16c8ebaeef --- /dev/null +++ b/drivers/rtc/rtc_smartbond.c @@ -0,0 +1,641 @@ +/* + * Copyright (c) 2023 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(rtc_smartbond, CONFIG_RTC_LOG_LEVEL); + +#define DT_DRV_COMPAT renesas_smartbond_rtc + +#define SMARTBOND_IRQN DT_INST_IRQN(0) +#define SMARTBOND_IRQ_PRIO DT_INST_IRQ(0, priority) + +#define RTC_ALARMS_COUNT DT_PROP(DT_NODELABEL(rtc), alarms_count) + +#define TM_YEAR_REF 1900 +#define RTC_DIV_DENOM_1000 0 +#define RTC_DIV_DENOM_1024 1 + +#define RTC_SMARTBOND_SUPPORTED_ALARM_FIELDS \ + (RTC_ALARM_TIME_MASK_SECOND | RTC_ALARM_TIME_MASK_MINUTE | RTC_ALARM_TIME_MASK_HOUR | \ + RTC_ALARM_TIME_MASK_MONTH | RTC_ALARM_TIME_MASK_MONTHDAY) + +#define RTC_TIME_REG_SET_FIELD(_field, _var, _val) \ + ((_var) = \ + ((_var) & ~(RTC_RTC_TIME_REG_RTC_TIME_ ## _field ## _T_Msk | \ + RTC_RTC_TIME_REG_RTC_TIME_ ## _field ## _U_Msk)) | \ + (((_val) << RTC_RTC_TIME_REG_RTC_TIME_ ## _field ## _U_Pos) & \ + (RTC_RTC_TIME_REG_RTC_TIME_ ## _field ## _T_Msk | \ + RTC_RTC_TIME_REG_RTC_TIME_ ## _field ## _U_Msk))) + +#define RTC_CALENDAR_REG_SET_FIELD(_field, _var, _val) \ + ((_var) = \ + ((_var) & ~(RTC_RTC_CALENDAR_REG_RTC_CAL_ ## _field ## _T_Msk | \ + RTC_RTC_CALENDAR_REG_RTC_CAL_ ## _field ## _U_Msk)) | \ + (((_val) << RTC_RTC_CALENDAR_REG_RTC_CAL_ ## _field ## _U_Pos) & \ + (RTC_RTC_CALENDAR_REG_RTC_CAL_ ## _field ## _T_Msk | \ + RTC_RTC_CALENDAR_REG_RTC_CAL_ ## _field ## _U_Msk))) + +#define RTC_CALENDAR_ALARM_REG_SET_FIELD(_field, _var, _val) \ + ((_var) = \ + ((_var) & ~(RTC_RTC_CALENDAR_ALARM_REG_RTC_CAL_ ## _field ## _T_Msk | \ + RTC_RTC_CALENDAR_ALARM_REG_RTC_CAL_ ## _field ## _U_Msk)) | \ + (((_val) << RTC_RTC_CALENDAR_ALARM_REG_RTC_CAL_ ## _field ## _U_Pos) & \ + (RTC_RTC_CALENDAR_ALARM_REG_RTC_CAL_ ## _field ## _T_Msk | \ + RTC_RTC_CALENDAR_ALARM_REG_RTC_CAL_ ## _field ## _U_Msk))) + +#define RTC_TIME_ALARM_REG_SET_FIELD(_field, _var, _val) \ + ((_var) = \ + ((_var) & ~(RTC_RTC_TIME_ALARM_REG_RTC_TIME_ ## _field ## _T_Msk | \ + RTC_RTC_TIME_ALARM_REG_RTC_TIME_ ## _field ## _U_Msk)) | \ + (((_val) << RTC_RTC_TIME_ALARM_REG_RTC_TIME_ ## _field ## _U_Pos) & \ + (RTC_RTC_TIME_ALARM_REG_RTC_TIME_ ## _field ## _T_Msk | \ + RTC_RTC_TIME_ALARM_REG_RTC_TIME_ ## _field ## _U_Msk))) + +#define RTC_TIME_REG_GET_FIELD(_field, _var) \ + (((_var) & (RTC_RTC_TIME_REG_RTC_TIME_ ## _field ## _T_Msk | \ + RTC_RTC_TIME_REG_RTC_TIME_ ## _field ## _U_Msk)) >> \ + RTC_RTC_TIME_REG_RTC_TIME_ ## _field ## _U_Pos) + +#define RTC_CALENDAR_REG_GET_FIELD(_field, _var) \ + (((_var) & (RTC_RTC_CALENDAR_REG_RTC_CAL_ ## _field ## _T_Msk | \ + RTC_RTC_CALENDAR_REG_RTC_CAL_ ## _field ## _U_Msk)) >> \ + RTC_RTC_CALENDAR_REG_RTC_CAL_ ## _field ## _U_Pos) + +#define RTC_CALENDAR_ALARM_REG_GET_FIELD(_field, _var) \ + (((_var) & (RTC_RTC_CALENDAR_ALARM_REG_RTC_CAL_ ## _field ## _T_Msk | \ + RTC_RTC_CALENDAR_ALARM_REG_RTC_CAL_ ## _field ## _U_Msk)) >> \ + RTC_RTC_CALENDAR_ALARM_REG_RTC_CAL_ ## _field ## _U_Pos) + +#define RTC_TIME_ALARM_REG_GET_FIELD(_field, _var) \ + (((_var) & (RTC_RTC_TIME_ALARM_REG_RTC_TIME_ ## _field ## _T_Msk | \ + RTC_RTC_TIME_ALARM_REG_RTC_TIME_ ## _field ## _U_Msk)) >> \ + RTC_RTC_TIME_ALARM_REG_RTC_TIME_ ## _field ## _U_Pos) + +#define CLK_RTCDIV_REG_SET_FIELD(_field, _var, _val) \ + ((_var) = \ + ((_var) & ~CRG_TOP_CLK_RTCDIV_REG_RTC_DIV_ ## _field ## _Msk) | \ + (((_val) << CRG_TOP_CLK_RTCDIV_REG_RTC_DIV_ ## _field ## _Pos) & \ + CRG_TOP_CLK_RTCDIV_REG_RTC_DIV_ ## _field ## _Msk)) + +struct rtc_smartbond_data { + struct k_mutex lock; + bool is_rtc_configured; +#if defined(CONFIG_RTC_ALARM) + volatile bool is_alarm_pending; + rtc_alarm_callback alarm_cb; + void *alarm_user_data; +#endif +#if defined(CONFIG_RTC_UPDATE) + rtc_update_callback update_cb; + void *update_user_data; +#endif +}; + +#if defined(CONFIG_RTC_ALARM) || defined(CONFIG_RTC_UPDATE) +static void smartbond_rtc_isr(const struct device *dev) +{ + struct rtc_smartbond_data *data = dev->data; + /* Exercise which events asserted the RTC IRQ line. Register is cleared upon read. */ + uint32_t rtc_event_flags_reg = RTC->RTC_EVENT_FLAGS_REG; + /* RTC_EVENT_FLASH_REG will be updated regardless of the interrupt mask. */ + uint32_t rtc_interrupt_mask_reg = RTC->RTC_INTERRUPT_MASK_REG; + +#if defined(CONFIG_RTC_ALARM) + if ((rtc_event_flags_reg & RTC_RTC_EVENT_FLAGS_REG_RTC_EVENT_ALRM_Msk) && + !(rtc_interrupt_mask_reg & RTC_RTC_INTERRUPT_MASK_REG_RTC_ALRM_INT_MSK_Msk)) { + if (data->alarm_cb) { + data->alarm_cb(dev, 0, data->alarm_user_data); + data->is_alarm_pending = false; + } else { + data->is_alarm_pending = true; + } + } +#endif + +#if defined(CONFIG_RTC_UPDATE) + if ((rtc_event_flags_reg & RTC_RTC_EVENT_FLAGS_REG_RTC_EVENT_SEC_Msk) && + !(rtc_interrupt_mask_reg & RTC_RTC_INTERRUPT_MASK_REG_RTC_SEC_INT_MSK_Msk)) { + if (data->update_cb) { + data->update_cb(dev, data->update_user_data); + } + } +#endif +} +#endif + +static inline void rtc_smartbond_set_status(bool status) +{ + if (status) { + CRG_TOP->CLK_RTCDIV_REG |= CRG_TOP_CLK_RTCDIV_REG_RTC_DIV_ENABLE_Msk; + RTC->RTC_CONTROL_REG = 0; + } else { + RTC->RTC_CONTROL_REG = (RTC_RTC_CONTROL_REG_RTC_CAL_DISABLE_Msk | + RTC_RTC_CONTROL_REG_RTC_TIME_DISABLE_Msk); + CRG_TOP->CLK_RTCDIV_REG &= ~CRG_TOP_CLK_RTCDIV_REG_RTC_DIV_ENABLE_Msk; + } +} + +static uint32_t rtc_time_to_bcd(const struct rtc_time *timeptr) +{ + uint32_t rtc_time_reg = 0; + + RTC_TIME_REG_SET_FIELD(S, rtc_time_reg, bin2bcd(timeptr->tm_sec)); /*[0, 59]*/ + RTC_TIME_REG_SET_FIELD(M, rtc_time_reg, bin2bcd(timeptr->tm_min)); /*[0, 59]*/ + RTC_TIME_REG_SET_FIELD(HR, rtc_time_reg, bin2bcd(timeptr->tm_hour)); /*[0, 23]*/ + + return rtc_time_reg; +} + +static uint32_t rtc_calendar_to_bcd(const struct rtc_time *timeptr) +{ + uint32_t rtc_calendar_reg = 0; + + RTC_CALENDAR_REG_SET_FIELD(D, rtc_calendar_reg, bin2bcd(timeptr->tm_mday)); /*[1, 31]*/ + RTC_CALENDAR_REG_SET_FIELD(Y, rtc_calendar_reg, + bin2bcd((timeptr->tm_year + TM_YEAR_REF) % 100)); /*[year - 1900]*/ + RTC_CALENDAR_REG_SET_FIELD(C, rtc_calendar_reg, + bin2bcd((timeptr->tm_year + TM_YEAR_REF) / 100)); + RTC_CALENDAR_REG_SET_FIELD(M, rtc_calendar_reg, bin2bcd(timeptr->tm_mon + 1)); /*[0, 11]*/ + + if (timeptr->tm_wday != -1) { + rtc_calendar_reg |= ((timeptr->tm_wday + 1) & + RTC_RTC_CALENDAR_REG_RTC_DAY_Msk); /*[0, 6]*/ + } + + return rtc_calendar_reg; +} + +static void bcd_to_rtc_time(struct rtc_time *timeptr) +{ + uint32_t rtc_time_reg = RTC->RTC_TIME_REG; + + timeptr->tm_sec = bcd2bin(RTC_TIME_REG_GET_FIELD(S, rtc_time_reg)); + timeptr->tm_min = bcd2bin(RTC_TIME_REG_GET_FIELD(M, rtc_time_reg)); + timeptr->tm_hour = bcd2bin(RTC_TIME_REG_GET_FIELD(HR, rtc_time_reg)); + + timeptr->tm_nsec = 0; /*Unknown*/ +} + +static void bcd_to_rtc_calendar(struct rtc_time *timeptr) +{ + uint32_t rtc_calendar_reg = RTC->RTC_CALENDAR_REG; + + timeptr->tm_mday = bcd2bin(RTC_CALENDAR_REG_GET_FIELD(D, rtc_calendar_reg)); + timeptr->tm_mon = bcd2bin(RTC_CALENDAR_REG_GET_FIELD(M, rtc_calendar_reg)) - 1; + timeptr->tm_year = bcd2bin(RTC_CALENDAR_REG_GET_FIELD(Y, rtc_calendar_reg)) + + (bcd2bin(RTC_CALENDAR_REG_GET_FIELD(C, rtc_calendar_reg)) * 100) - TM_YEAR_REF; + timeptr->tm_wday = (rtc_calendar_reg & RTC_RTC_CALENDAR_REG_RTC_DAY_Msk) - 1; + + timeptr->tm_yday = timeptr->tm_isdst = -1; /*Unknown*/ +} + +static int rtc_smartbond_set_time(const struct device *dev, const struct rtc_time *timeptr) +{ + struct rtc_smartbond_data *data = dev->data; + int ret = 0; + uint32_t rtc_time_reg, rtc_calendar_reg, rtc_status_reg; + + if (timeptr == NULL) { + LOG_ERR("No pointer is provided to set time"); + return -EINVAL; + } + + if (timeptr->tm_year + TM_YEAR_REF < TM_YEAR_REF) { + LOG_ERR("RTC time exceeds HW capabilities"); + return -EINVAL; + } + + if ((timeptr->tm_yday != -1) || (timeptr->tm_isdst != -1) || (timeptr->tm_nsec != 0)) { + LOG_WRN("Unsupported RTC sub-values"); + } + + k_mutex_lock(&data->lock, K_FOREVER); + rtc_smartbond_set_status(false); + + /* Store current counter values as it might happen that the requested time is not valid */ + rtc_time_reg = RTC->RTC_TIME_REG; + rtc_calendar_reg = RTC->RTC_CALENDAR_REG; + + RTC->RTC_TIME_REG = rtc_time_to_bcd(timeptr); + RTC->RTC_CALENDAR_REG = rtc_calendar_to_bcd(timeptr); + + /* Check if the new values were valid, otherwise reset back to the previous ones. */ + rtc_status_reg = RTC->RTC_STATUS_REG; + if (!(rtc_status_reg & RTC_RTC_STATUS_REG_RTC_VALID_CAL_Msk) || + !(rtc_status_reg & RTC_RTC_STATUS_REG_RTC_VALID_TIME_Msk)) { + RTC->RTC_TIME_REG = rtc_time_reg; + RTC->RTC_CALENDAR_REG = rtc_calendar_reg; + ret = -EINVAL; + } + + /* Mark the very first valid RTC configuration; used to check if RTC contains valid data. */ + if (!data->is_rtc_configured && (ret == 0)) { + data->is_rtc_configured = true; + } + + /* It might happen that the very first time RTC is not configured correctly; do not care. */ + rtc_smartbond_set_status(true); + k_mutex_unlock(&data->lock); + + return ret; +} + +static int rtc_smartbond_get_time(const struct device *dev, struct rtc_time *timeptr) +{ + struct rtc_smartbond_data *data = dev->data; + + if (timeptr == NULL) { + LOG_ERR("No pointer is provided to store the requested time"); + return -EINVAL; + } + + if (!data->is_rtc_configured) { + LOG_ERR("RTC is not initialized yet"); + return -ENODATA; + } + + k_mutex_lock(&data->lock, K_FOREVER); + /* Stop RTC counters to obtain coherent data. */ + rtc_smartbond_set_status(false); + + bcd_to_rtc_time(timeptr); + bcd_to_rtc_calendar(timeptr); + + rtc_smartbond_set_status(true); + k_mutex_unlock(&data->lock); + + return 0; +} + +#if defined(CONFIG_RTC_ALARM) +BUILD_ASSERT(RTC_ALARMS_COUNT, "At least one alarm event should be supported"); + +/* Define a valid calendar value as a zero sub-field is not valid for the alarm calendar value */ +static uint32_t alarm_calendar_to_bcd(const struct rtc_time *timeptr, uint16_t mask) +{ + uint32_t rtc_calendar_alarm_reg = 0x0108; + + if (mask & RTC_ALARM_TIME_MASK_MONTHDAY) { + RTC_CALENDAR_ALARM_REG_SET_FIELD(D, rtc_calendar_alarm_reg, + bin2bcd(timeptr->tm_mday)); + } + + if (mask & RTC_ALARM_TIME_MASK_MONTH) { + RTC_CALENDAR_ALARM_REG_SET_FIELD(M, rtc_calendar_alarm_reg, + bin2bcd(timeptr->tm_mon + 1)); + } + + return rtc_calendar_alarm_reg; +} + +/* No need to parse the alarm mask as a zero sub-field is valid for the alarm time counter. */ +static inline uint32_t alarm_time_to_bcd(const struct rtc_time *timeptr) +{ + uint32_t rtc_time_alarm_reg = 0; + + RTC_TIME_ALARM_REG_SET_FIELD(S, rtc_time_alarm_reg, bin2bcd(timeptr->tm_sec)); /*[0, 59]*/ + RTC_TIME_ALARM_REG_SET_FIELD(M, rtc_time_alarm_reg, bin2bcd(timeptr->tm_min)); /*[0, 59]*/ + RTC_TIME_ALARM_REG_SET_FIELD(HR, rtc_time_alarm_reg, bin2bcd(timeptr->tm_hour)); /*[0, 23]*/ + + return rtc_time_alarm_reg; +} + +static void bcd_to_alarm_calendar(struct rtc_time *timeptr) +{ + uint32_t rtc_calendar_alarm_reg = RTC->RTC_CALENDAR_ALARM_REG; + + timeptr->tm_mday = bcd2bin(RTC_CALENDAR_ALARM_REG_GET_FIELD(D, rtc_calendar_alarm_reg)); + timeptr->tm_mon = bcd2bin(RTC_CALENDAR_ALARM_REG_GET_FIELD(M, rtc_calendar_alarm_reg)) - 1; + + timeptr->tm_yday = timeptr->tm_wday = timeptr->tm_isdst = timeptr->tm_year = -1; +} + +static void bcd_to_alarm_time(struct rtc_time *timeptr) +{ + uint32_t rtc_time_alarm_reg = RTC->RTC_TIME_ALARM_REG; + + timeptr->tm_sec = bcd2bin(RTC_TIME_ALARM_REG_GET_FIELD(S, rtc_time_alarm_reg)); + timeptr->tm_min = bcd2bin(RTC_TIME_ALARM_REG_GET_FIELD(M, rtc_time_alarm_reg)); + timeptr->tm_hour = bcd2bin(RTC_TIME_ALARM_REG_GET_FIELD(HR, rtc_time_alarm_reg)); + + timeptr->tm_nsec = 0; +} + +static uint32_t tm_to_rtc_alarm_mask(uint16_t mask) +{ + uint32_t rtc_alarm_enable_reg = 0; + + if (mask & RTC_ALARM_TIME_MASK_SECOND) { + rtc_alarm_enable_reg |= RTC_RTC_ALARM_ENABLE_REG_RTC_ALARM_SEC_EN_Msk; + } + if (mask & RTC_ALARM_TIME_MASK_MINUTE) { + rtc_alarm_enable_reg |= RTC_RTC_ALARM_ENABLE_REG_RTC_ALARM_MIN_EN_Msk; + } + if (mask & RTC_ALARM_TIME_MASK_HOUR) { + rtc_alarm_enable_reg |= RTC_RTC_ALARM_ENABLE_REG_RTC_ALARM_HOUR_EN_Msk; + } + if (mask & RTC_ALARM_TIME_MASK_MONTH) { + rtc_alarm_enable_reg |= RTC_RTC_ALARM_ENABLE_REG_RTC_ALARM_MNTH_EN_Msk; + } + if (mask & RTC_ALARM_TIME_MASK_MONTHDAY) { + rtc_alarm_enable_reg |= RTC_RTC_ALARM_ENABLE_REG_RTC_ALARM_DATE_EN_Msk; + } + + return rtc_alarm_enable_reg; +} + +static uint16_t rtc_to_tm_alarm_mask(uint32_t rtc_alarm_enable_reg) +{ + uint16_t mask = 0; + + if (rtc_alarm_enable_reg & RTC_RTC_ALARM_ENABLE_REG_RTC_ALARM_SEC_EN_Msk) { + mask |= RTC_ALARM_TIME_MASK_SECOND; + } + if (rtc_alarm_enable_reg & RTC_RTC_ALARM_ENABLE_REG_RTC_ALARM_MIN_EN_Msk) { + mask |= RTC_ALARM_TIME_MASK_MINUTE; + } + if (rtc_alarm_enable_reg & RTC_RTC_ALARM_ENABLE_REG_RTC_ALARM_HOUR_EN_Msk) { + mask |= RTC_ALARM_TIME_MASK_HOUR; + } + if (rtc_alarm_enable_reg & RTC_RTC_ALARM_ENABLE_REG_RTC_ALARM_MNTH_EN_Msk) { + mask |= RTC_ALARM_TIME_MASK_MONTH; + } + if (rtc_alarm_enable_reg & RTC_RTC_ALARM_ENABLE_REG_RTC_ALARM_DATE_EN_Msk) { + mask |= RTC_ALARM_TIME_MASK_MONTHDAY; + } + + return mask; +} + +static int rtc_smartbond_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask, + const struct rtc_time *timeptr) +{ + int ret = 0; + struct rtc_smartbond_data *data = dev->data; + uint32_t rtc_time_alarm_reg; + uint32_t rtc_calendar_alarm_reg; + uint32_t rtc_alarm_enable_reg; + uint32_t rtc_status_reg; + + if (id >= RTC_ALARMS_COUNT) { + LOG_ERR("Alarm id is out of range"); + return -EINVAL; + } + + if (mask & ~RTC_SMARTBOND_SUPPORTED_ALARM_FIELDS) { + LOG_ERR("Invalid alarm mask"); + return -EINVAL; + } + + if ((timeptr == NULL) && (mask != 0)) { + LOG_ERR("No pointer is provided to set alarm"); + return -EINVAL; + } + + if (!data->is_rtc_configured) { + LOG_WRN("RTC is not initialized yet"); + } + + k_mutex_lock(&data->lock, K_FOREVER); + + rtc_alarm_enable_reg = RTC->RTC_ALARM_ENABLE_REG; + + /* Disable alarm to obtain coherency and/or when the alarm mask is empty */ + RTC->RTC_ALARM_ENABLE_REG = 0; + RTC->RTC_INTERRUPT_DISABLE_REG = RTC_RTC_INTERRUPT_DISABLE_REG_RTC_ALRM_INT_DIS_Msk; + + if (mask) { + /* Store current counter values as it might happen requested alrm is not valid */ + rtc_time_alarm_reg = RTC->RTC_TIME_ALARM_REG; + rtc_calendar_alarm_reg = RTC->RTC_CALENDAR_ALARM_REG; + + RTC->RTC_TIME_ALARM_REG = alarm_time_to_bcd(timeptr); + RTC->RTC_CALENDAR_ALARM_REG = alarm_calendar_to_bcd(timeptr, mask); + + rtc_status_reg = RTC->RTC_STATUS_REG; + if (!(rtc_status_reg & RTC_RTC_STATUS_REG_RTC_VALID_CAL_ALM_Msk) || + !(rtc_status_reg & RTC_RTC_STATUS_REG_RTC_VALID_TIME_ALM_Msk)) { + RTC->RTC_TIME_ALARM_REG = rtc_time_alarm_reg; + RTC->RTC_CALENDAR_ALARM_REG = rtc_calendar_alarm_reg; + RTC->RTC_ALARM_ENABLE_REG = rtc_alarm_enable_reg; + ret = -EINVAL; + } else { + RTC->RTC_ALARM_ENABLE_REG = tm_to_rtc_alarm_mask(mask); + } + + RTC->RTC_INTERRUPT_ENABLE_REG = RTC_RTC_INTERRUPT_ENABLE_REG_RTC_ALRM_INT_EN_Msk; + } + + k_mutex_unlock(&data->lock); + + return ret; +} + +static int rtc_smartbond_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask, + struct rtc_time *timeptr) +{ + struct rtc_smartbond_data *data = dev->data; + + if (id >= RTC_ALARMS_COUNT) { + LOG_ERR("Alarm id is out of range"); + return -EINVAL; + } + + if ((timeptr == NULL) || (mask == NULL)) { + LOG_ERR("No pointer is provided to store the requested alarm time/mask"); + return -EINVAL; + } + + if (!data->is_rtc_configured) { + LOG_WRN("RTC is not initialized yet"); + } + + k_mutex_lock(&data->lock, K_FOREVER); + + bcd_to_alarm_calendar(timeptr); + bcd_to_alarm_time(timeptr); + *mask = rtc_to_tm_alarm_mask(RTC->RTC_ALARM_ENABLE_REG); + + k_mutex_unlock(&data->lock); + + return 0; +} + +static int rtc_smartbond_alarm_is_pending(const struct device *dev, uint16_t id) +{ + unsigned int key; + int status; + struct rtc_smartbond_data *data = dev->data; + + if (id >= RTC_ALARMS_COUNT) { + LOG_ERR("Alarm id is out of range"); + return -EINVAL; + } + + /* Globally disable interrupts as the status flag can be updated within ISR */ + key = DA1469X_IRQ_DISABLE(); + status = data->is_alarm_pending; + /* After reading, the alarm status should be cleared. */ + data->is_alarm_pending = 0; + DA1469X_IRQ_ENABLE(key); + + return status; +} + +static int rtc_smartbond_alarm_set_callback(const struct device *dev, uint16_t id, + rtc_alarm_callback callback, void *user_data) +{ + struct rtc_smartbond_data *data = dev->data; + + if (id >= RTC_ALARMS_COUNT) { + LOG_ERR("Alarm id is out of range"); + return -EINVAL; + } + + k_mutex_lock(&data->lock, K_FOREVER); + + data->alarm_cb = callback; + data->alarm_user_data = user_data; + + k_mutex_unlock(&data->lock); + + return 0; +} + +static int rtc_smartbond_alarm_get_supported_fields(const struct device *dev, uint16_t id, + uint16_t *mask) +{ + if (id >= RTC_ALARMS_COUNT) { + LOG_ERR("Alarm id is out of range"); + return -EINVAL; + } + + if (mask == NULL) { + LOG_ERR("Pointer to store the mask value is missed"); + return -EINVAL; + } + + *mask = (uint16_t)RTC_SMARTBOND_SUPPORTED_ALARM_FIELDS; + + return 0; +} +#endif + +#if defined(CONFIG_RTC_UPDATE) +static int rtc_smartbond_update_set_callback(const struct device *dev, rtc_update_callback callback, + void *user_data) +{ + struct rtc_smartbond_data *data = dev->data; + + k_mutex_lock(&data->lock, K_FOREVER); + + data->update_cb = callback; + data->update_user_data = user_data; + + if (data->update_cb) { + /* Enable asserting the RTC interrupt line when the second counter rolls over. */ + RTC->RTC_INTERRUPT_ENABLE_REG = RTC_RTC_INTERRUPT_ENABLE_REG_RTC_SEC_INT_EN_Msk; + } else { + RTC->RTC_INTERRUPT_DISABLE_REG = RTC_RTC_INTERRUPT_DISABLE_REG_RTC_SEC_INT_DIS_Msk; + } + + k_mutex_unlock(&data->lock); + + return 0; +} +#endif + +struct rtc_driver_api rtc_smartbond_driver_api = { + .get_time = rtc_smartbond_get_time, + .set_time = rtc_smartbond_set_time, +#if defined(CONFIG_RTC_ALARM) + .alarm_get_time = rtc_smartbond_alarm_get_time, + .alarm_set_time = rtc_smartbond_alarm_set_time, + .alarm_is_pending = rtc_smartbond_alarm_is_pending, + .alarm_set_callback = rtc_smartbond_alarm_set_callback, + .alarm_get_supported_fields = rtc_smartbond_alarm_get_supported_fields, +#endif +#if defined(CONFIG_RTC_UPDATE) + .update_set_callback = rtc_smartbond_update_set_callback, +#endif +}; + +static void rtc_smartbond_100HZ_clock_cfg(void) +{ + const struct device * const dev = DEVICE_DT_GET(DT_NODELABEL(osc)); + uint32_t lp_clk_rate; + uint32_t clk_rtcdiv_reg; + + if (!device_is_ready(dev)) { + __ASSERT_MSG_INFO("Clock device is not ready"); + } + + if (clock_control_get_rate(dev, (clock_control_subsys_t)SMARTBOND_CLK_LP_CLK, + &lp_clk_rate) < 0) { + __ASSERT_MSG_INFO("Cannot extract LP clock rate"); + } + + clk_rtcdiv_reg = CRG_TOP->CLK_RTCDIV_REG; + CLK_RTCDIV_REG_SET_FIELD(DENOM, clk_rtcdiv_reg, RTC_DIV_DENOM_1000); + CLK_RTCDIV_REG_SET_FIELD(INT, clk_rtcdiv_reg, lp_clk_rate / 100); + CLK_RTCDIV_REG_SET_FIELD(FRAC, clk_rtcdiv_reg, (lp_clk_rate % 100) * 10); + CRG_TOP->CLK_RTCDIV_REG = clk_rtcdiv_reg; +} + +static int rtc_smartbond_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + /* Wakeup device from RTC events (alarm/roll over) */ +#if CONFIG_PM + bool is_xtal32m_enabled = DT_NODE_HAS_STATUS(DT_NODELABEL(xtal32m), okay); + int pdc_idx = da1469x_pdc_add(MCU_PDC_TRIGGER_RTC_ALARM, MCU_PDC_MASTER_M33, + is_xtal32m_enabled ? MCU_PDC_EN_XTAL : 0); + + __ASSERT(pdc_idx >= 0, "Failed to add RTC PDC entry"); + da1469x_pdc_set(pdc_idx); + da1469x_pdc_ack(pdc_idx); +#endif + + rtc_smartbond_100HZ_clock_cfg(); + + /* Timer and calendar counters will not reset after SW reset */ + RTC->RTC_KEEP_RTC_REG |= RTC_RTC_KEEP_RTC_REG_RTC_KEEP_Msk; + +#if defined(CONFIG_RTC_ALARM) || defined(CONFIG_RTC_UPDATE) + IRQ_CONNECT(SMARTBOND_IRQN, SMARTBOND_IRQ_PRIO, smartbond_rtc_isr, + DEVICE_DT_INST_GET(0), 0); + irq_enable(SMARTBOND_IRQN); +#endif + + return 0; +} + +#define SMARTBOND_RTC_INIT(inst) \ + BUILD_ASSERT((inst) == 0, "multiple instances are not supported"); \ + \ + static struct rtc_smartbond_data rtc_smartbond_data_ ## inst; \ + \ + DEVICE_DT_INST_DEFINE(0, rtc_smartbond_init, NULL, \ + &rtc_smartbond_data_ ## inst, NULL, \ + POST_KERNEL, \ + CONFIG_RTC_INIT_PRIORITY, \ + &rtc_smartbond_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(SMARTBOND_RTC_INIT) diff --git a/drivers/sdhc/CMakeLists.txt b/drivers/sdhc/CMakeLists.txt index a29829de24a..431867fb2b8 100644 --- a/drivers/sdhc/CMakeLists.txt +++ b/drivers/sdhc/CMakeLists.txt @@ -6,4 +6,7 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_IMX_USDHC imx_usdhc.c) zephyr_library_sources_ifdef(CONFIG_SPI_SDHC sdhc_spi.c) zephyr_library_sources_ifdef(CONFIG_MCUX_SDIF mcux_sdif.c) +zephyr_library_sources_ifdef(CONFIG_SAM_HSMCI sam_hsmci.c) +zephyr_library_sources_ifdef(CONFIG_INTEL_EMMC_HOST intel_emmc_host.c) +zephyr_library_sources_ifdef(CONFIG_SDHC_INFINEON_CAT1 ifx_cat1_sdio.c) endif() diff --git a/drivers/sdhc/Kconfig b/drivers/sdhc/Kconfig index 0969c6fa73c..7e75e03a024 100644 --- a/drivers/sdhc/Kconfig +++ b/drivers/sdhc/Kconfig @@ -8,9 +8,12 @@ menuconfig SDHC if SDHC +source "drivers/sdhc/Kconfig.ifx_cat1" source "drivers/sdhc/Kconfig.imx" source "drivers/sdhc/Kconfig.spi" source "drivers/sdhc/Kconfig.mcux_sdif" +source "drivers/sdhc/Kconfig.sam_hsmci" +source "drivers/sdhc/Kconfig.intel" config SDHC_INIT_PRIORITY int "SDHC driver init priority" @@ -49,5 +52,4 @@ module = SDHC module-str = sdhc source "subsys/logging/Kconfig.template.log_config" - endif # SDHC diff --git a/drivers/sdhc/Kconfig.ifx_cat1 b/drivers/sdhc/Kconfig.ifx_cat1 new file mode 100644 index 00000000000..13dde4cf18f --- /dev/null +++ b/drivers/sdhc/Kconfig.ifx_cat1 @@ -0,0 +1,22 @@ +# Infineon CAT1 SDHC configuration options + +# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +config SDHC_INFINEON_CAT1 + bool "Infineon CAT1 SDHC driver" + default y + depends on DT_HAS_INFINEON_CAT1_SDHC_SDIO_ENABLED + select USE_INFINEON_SDIO + select SDHC_SUPPORTS_NATIVE_MODE + help + This option enables the SDHC driver for Infineon CAT1 family. + +if SDHC_INFINEON_CAT1 + +config SDHC_INIT_PRIORITY + default 70 + +endif diff --git a/drivers/sdhc/Kconfig.intel b/drivers/sdhc/Kconfig.intel new file mode 100644 index 00000000000..cebcfb066bf --- /dev/null +++ b/drivers/sdhc/Kconfig.intel @@ -0,0 +1,58 @@ +# Copyright (c) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +config INTEL_EMMC_HOST + bool "EMMC driver" + select SDHC_SUPPORTS_NATIVE_MODE + select EVENTS + default y + depends on DT_HAS_INTEL_EMMC_HOST_ENABLED + help + EMMC driver support. Though this driver can be easily port to + any HW which is complaint to eMMC spec, currently it is only + validated using intel's EMMC host controller. + +if INTEL_EMMC_HOST +config INTEL_EMMC_HOST_INTR + bool "EMMC host controller interrupt mode" + default y + help + EMMC host controller interrupt mode support. + +config INTEL_EMMC_HOST_DMA + bool "EMMC host controller DMA mode" + select DCACHE + help + EMMC host controller DMA mode support. + +config INTEL_EMMC_HOST_ADMA + bool "EMMC host controller ADMA mode" + depends on INTEL_EMMC_HOST_DMA + help + EMMC host controller ADMA mode support. + +config INTEL_EMMC_HOST_ADMA_DESC_SIZE + int "EMMC host controller ADMA Descriptor size" + depends on INTEL_EMMC_HOST_ADMA + default 32 + help + EMMC host controller ADMA Descriptor size. + +config INTEL_EMMC_HOST_AUTO_STOP + bool "auto stop command mode" + default y + help + Auto stop command mode support. + +config INTEL_EMMC_HOST_BLOCK_GAP + bool "Block gap mode" + depends on INTEL_EMMC_HOST_DMA + help + Block gap mode support. + +config INTEL_EMMC_HOST_TUNING + bool "Host tuning" + help + Host tuning support. + +endif diff --git a/drivers/sdhc/Kconfig.sam_hsmci b/drivers/sdhc/Kconfig.sam_hsmci new file mode 100644 index 00000000000..68265dcabed --- /dev/null +++ b/drivers/sdhc/Kconfig.sam_hsmci @@ -0,0 +1,38 @@ +# Copyright 2023 Nikhef +# SPDX -License-Identifier: Apache-2.0 + +config SAM_HSMCI + bool "ATMEL SAM HSMCI driver" + default y + depends on DT_HAS_ATMEL_SAM_HSMCI_ENABLED + select SDHC_SUPPORTS_NATIVE_MODE + help + Enable the ATMEL SAM HSMCI MMC/SD card driver. + +if SAM_HSMCI + +config SAM_HSMCI_PDCMODE + bool "Use PDC if available" + default y if SOC_SERIES_SAM4E + help + Use peripheral DMA controller, if supported + +config SAM_HSMCI_PWRSAVE + bool "Power save during card inactive" + default y + help + Power-save mode reduces the clock-speed during SD card + inactivity. + +if SAM_HSMCI_PWRSAVE + +config SAM_HSMCI_PWRSAVE_DIV + int "Divisor value of clock when in power-save mode" + default 7 + help + SD clock freqeuncy is divided by 2**(N+1) where N + is the divisor value. Valid values are 0 to 7. + +endif # SAM_HSMCI_PWRSAVE + +endif # SAM_HSMCI diff --git a/drivers/sdhc/ifx_cat1_sdio.c b/drivers/sdhc/ifx_cat1_sdio.c new file mode 100644 index 00000000000..d298e1d7b6b --- /dev/null +++ b/drivers/sdhc/ifx_cat1_sdio.c @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +/** + * @brief SDIO driver for Infineon CAT1 MCU family. + * + * This driver support only SDIO protocol of the SD interface for general + * I/O functions. + * + * Refer to the SD Specifications Part 1 SDIO Specifications Version 4.10 for more + * information on the SDIO protocol and specifications. + * + * Features + * - Supports 4-bit interface + * - Supports Ultra High Speed (UHS-I) mode + * - Supports Default Speed (DS), High Speed (HS), SDR12, SDR25 and SDR50 speed modes + * - Supports SDIO card interrupts in both 1-bit SD and 4-bit SD modes + * - Supports Standard capacity (SDSC), High capacity (SDHC) and + * Extended capacity (SDXC) memory + * + * Note (limitations): + * - current version of ifx_cat1_sdio supports only following set of commands: + * > GO_IDLE_STATE (CMD0) + * > SEND_RELATIVE_ADDR (CMD3) + * > IO_SEND_OP_COND (CMD5) + * > SELECT_CARD (CMD7) + * > VOLTAGE_SWITCH (CMD11) + * > GO_INACTIVE_STATE (CMD15) + * > IO_RW_DIRECT (CMD52) + * > IO_RW_EXTENDED (CMD53) + */ + +#define DT_DRV_COMPAT infineon_cat1_sdhc_sdio + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +LOG_MODULE_REGISTER(ifx_cat1_sdio, CONFIG_SDHC_LOG_LEVEL); + +#include + +#define IFX_CAT1_SDIO_F_MIN (SDMMC_CLOCK_400KHZ) +#define IFX_CAT1_SDIO_F_MAX (SD_CLOCK_50MHZ) + +struct ifx_cat1_sdio_config { + const struct pinctrl_dev_config *pincfg; + SDHC_Type *reg_addr; + uint8_t irq_priority; +}; + +struct ifx_cat1_sdio_data { + cyhal_sdio_t sdio_obj; + cyhal_resource_inst_t hw_resource; + cyhal_sdio_configurator_t cyhal_sdio_config; + enum sdhc_clock_speed clock_speed; + enum sdhc_bus_width bus_width; + + void *sdio_cb_user_data; + sdhc_interrupt_cb_t sdio_cb; +}; + +static uint32_t sdio_rca; +static const cy_stc_sd_host_init_config_t host_config = {false, CY_SD_HOST_DMA_ADMA2, false}; +static cy_en_sd_host_card_capacity_t sd_host_card_capacity = CY_SD_HOST_SDSC; +static cy_en_sd_host_card_type_t sd_host_card_type = CY_SD_HOST_NOT_EMMC; +static cy_stc_sd_host_sd_card_config_t sd_host_sd_card_config = { + .lowVoltageSignaling = false, + .busWidth = CY_SD_HOST_BUS_WIDTH_4_BIT, + .cardType = &sd_host_card_type, + .rca = &sdio_rca, + .cardCapacity = &sd_host_card_capacity, +}; + +/* List of available SDHC instances */ +static SDHC_Type *const IFX_CAT1_SDHC_BASE_ADDRESSES[CY_IP_MXSDHC_INSTANCES] = { +#ifdef SDHC0 + SDHC0, +#endif /* ifdef SDHC0 */ + +#ifdef SDHC1 + SDHC1, +#endif /* ifdef SDHC1 */ +}; + +static int32_t _get_hw_block_num(SDHC_Type *reg_addr) +{ + uint32_t i; + + for (i = 0u; i < CY_IP_MXSDHC_INSTANCES; i++) { + if (IFX_CAT1_SDHC_BASE_ADDRESSES[i] == reg_addr) { + return i; + } + } + + return -EINVAL; +} + +static int ifx_cat1_sdio_reset(const struct device *dev) +{ + struct ifx_cat1_sdio_data *dev_data = dev->data; + + cyhal_sdhc_software_reset((cyhal_sdhc_t *)&dev_data->sdio_obj); + + return 0; +} + +static int ifx_cat1_sdio_set_io(const struct device *dev, struct sdhc_io *ios) +{ + cy_rslt_t ret; + struct ifx_cat1_sdio_data *dev_data = dev->data; + cyhal_sdio_cfg_t config = {.frequencyhal_hz = ios->clock}; + + /* NOTE: Set bus width, set card power, set host signal voltage, + * set I/O timing does not support in current version of driver + */ + + /* Set host clock */ + if ((dev_data->clock_speed != ios->clock) && (ios->clock != 0)) { + + if ((ios->clock > IFX_CAT1_SDIO_F_MAX) || (ios->clock < IFX_CAT1_SDIO_F_MIN)) { + return -EINVAL; + } + + ret = cyhal_sdio_configure(&dev_data->sdio_obj, &config); + if (ret != CY_RSLT_SUCCESS) { + return -ENOTSUP; + } + + dev_data->clock_speed = ios->clock; + } + + return 0; +} + +static int ifx_cat1_sdio_card_busy(const struct device *dev) +{ + struct ifx_cat1_sdio_data *dev_data = dev->data; + + return cyhal_sdio_is_busy(&dev_data->sdio_obj) ? 1 : 0; +} + +static int ifx_cat1_sdio_request(const struct device *dev, struct sdhc_command *cmd, + struct sdhc_data *data) +{ + struct ifx_cat1_sdio_data *dev_data = dev->data; + int ret; + + switch (cmd->opcode) { + case CYHAL_SDIO_CMD_GO_IDLE_STATE: + case CYHAL_SDIO_CMD_SEND_RELATIVE_ADDR: + case CYHAL_SDIO_CMD_IO_SEND_OP_COND: + case CYHAL_SDIO_CMD_SELECT_CARD: + case CYHAL_SDIO_CMD_VOLTAGE_SWITCH: + case CYHAL_SDIO_CMD_GO_INACTIVE_STATE: + case CYHAL_SDIO_CMD_IO_RW_DIRECT: + ret = cyhal_sdio_send_cmd(&dev_data->sdio_obj, CYHAL_SDIO_XFER_TYPE_READ, + cmd->opcode, cmd->arg, cmd->response); + if (ret != CY_RSLT_SUCCESS) { + LOG_ERR("cyhal_sdio_send_cmd failed ret = %d \r\n", ret); + } + break; + + case CYHAL_SDIO_CMD_IO_RW_EXTENDED: + cyhal_sdio_transfer_type_t direction; + + direction = (cmd->arg & BIT(SDIO_CMD_ARG_RW_SHIFT)) ? CYHAL_SDIO_XFER_TYPE_WRITE + : CYHAL_SDIO_XFER_TYPE_READ; + + ret = cyhal_sdio_bulk_transfer(&dev_data->sdio_obj, direction, cmd->arg, data->data, + data->blocks * data->block_size, cmd->response); + + if (ret != CY_RSLT_SUCCESS) { + LOG_ERR("cyhal_sdio_bulk_transfer failed ret = %d \r\n", ret); + } + break; + + default: + ret = -ENOTSUP; + } + + return ret; +} + +static int ifx_cat1_sdio_get_card_present(const struct device *dev) +{ + return 1; +} + +static int ifx_cat1_sdio_get_host_props(const struct device *dev, struct sdhc_host_props *props) +{ + memset(props, 0, sizeof(*props)); + props->f_max = IFX_CAT1_SDIO_F_MAX; + props->f_min = IFX_CAT1_SDIO_F_MIN; + props->host_caps.bus_4_bit_support = true; + props->host_caps.high_spd_support = true; + props->host_caps.sdr50_support = true; + props->host_caps.sdio_async_interrupt_support = true; + props->host_caps.vol_330_support = true; + + return 0; +} + +static int ifx_cat1_sdio_enable_interrupt(const struct device *dev, sdhc_interrupt_cb_t callback, + int sources, void *user_data) +{ + struct ifx_cat1_sdio_data *data = dev->data; + const struct ifx_cat1_sdio_config *cfg = dev->config; + + if (sources != SDHC_INT_SDIO) { + return -ENOTSUP; + } + + if (callback == NULL) { + return -EINVAL; + } + + /* Record SDIO callback parameters */ + data->sdio_cb = callback; + data->sdio_cb_user_data = user_data; + + /* Enable CARD INTERRUPT event */ + cyhal_sdio_enable_event(&data->sdio_obj, CYHAL_SDIO_CARD_INTERRUPT, + cfg->irq_priority, true); + + return 0; +} + +static int ifx_cat1_sdio_disable_interrupt(const struct device *dev, int sources) +{ + struct ifx_cat1_sdio_data *data = dev->data; + const struct ifx_cat1_sdio_config *cfg = dev->config; + + if (sources != SDHC_INT_SDIO) { + return -ENOTSUP; + } + + data->sdio_cb = NULL; + data->sdio_cb_user_data = NULL; + + /* Disable CARD INTERRUPT event */ + cyhal_sdio_enable_event(&data->sdio_obj, CYHAL_SDIO_CARD_INTERRUPT, + cfg->irq_priority, false); + + return 0; +} + +static void ifx_cat1_sdio_event_callback(void *callback_arg, cyhal_sdio_event_t event) +{ + const struct device *dev = callback_arg; + struct ifx_cat1_sdio_data *data = dev->data; + + if ((event == CYHAL_SDIO_CARD_INTERRUPT) && (data->sdio_cb != NULL)) { + data->sdio_cb(dev, SDHC_INT_SDIO, data->sdio_cb_user_data); + } +} + +static int ifx_cat1_sdio_init(const struct device *dev) +{ + cy_rslt_t ret; + struct ifx_cat1_sdio_data *data = dev->data; + const struct ifx_cat1_sdio_config *config = dev->config; + + /* Configure dt provided device signals when available */ + ret = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); + if (ret) { + return ret; + } + + /* Dedicate SDIO HW resource */ + data->hw_resource.type = CYHAL_RSC_SDIODEV; + data->hw_resource.block_num = _get_hw_block_num(config->reg_addr); + + /* Initialize the SDIO peripheral */ + data->cyhal_sdio_config.resource = &data->hw_resource; + data->cyhal_sdio_config.host_config = &host_config, + data->cyhal_sdio_config.card_config = &sd_host_sd_card_config, + + ret = cyhal_sdio_init_cfg(&data->sdio_obj, &data->cyhal_sdio_config); + if (ret != CY_RSLT_SUCCESS) { + LOG_ERR("cyhal_sdio_init_cfg failed ret = %d \r\n", ret); + return ret; + } + + /* Register callback for SDIO events */ + cyhal_sdio_register_callback(&data->sdio_obj, ifx_cat1_sdio_event_callback, (void *)dev); + + return 0; +} + +static const struct sdhc_driver_api ifx_cat1_sdio_api = { + .reset = ifx_cat1_sdio_reset, + .request = ifx_cat1_sdio_request, + .set_io = ifx_cat1_sdio_set_io, + .get_card_present = ifx_cat1_sdio_get_card_present, + .card_busy = ifx_cat1_sdio_card_busy, + .get_host_props = ifx_cat1_sdio_get_host_props, + .enable_interrupt = ifx_cat1_sdio_enable_interrupt, + .disable_interrupt = ifx_cat1_sdio_disable_interrupt, +}; + +#define IFX_CAT1_SDHC_INIT(n) \ + \ + PINCTRL_DT_INST_DEFINE(n); \ + \ + static const struct ifx_cat1_sdio_config ifx_cat1_sdio_##n##_config = { \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .reg_addr = (SDHC_Type *)DT_INST_REG_ADDR(n), \ + .irq_priority = DT_INST_IRQ(n, priority)}; \ + \ + static struct ifx_cat1_sdio_data ifx_cat1_sdio_##n##_data; \ + \ + DEVICE_DT_INST_DEFINE(n, &ifx_cat1_sdio_init, NULL, &ifx_cat1_sdio_##n##_data, \ + &ifx_cat1_sdio_##n##_config, POST_KERNEL, CONFIG_SDHC_INIT_PRIORITY, \ + &ifx_cat1_sdio_api); + +DT_INST_FOREACH_STATUS_OKAY(IFX_CAT1_SDHC_INIT) diff --git a/drivers/sdhc/imx_usdhc.c b/drivers/sdhc/imx_usdhc.c index 49914137eec..8ae8fa9741f 100644 --- a/drivers/sdhc/imx_usdhc.c +++ b/drivers/sdhc/imx_usdhc.c @@ -75,6 +75,7 @@ struct usdhc_config { }; struct usdhc_data { + const struct device *dev; struct sdhc_host_props props; bool card_present; struct k_sem transfer_sem; @@ -82,6 +83,9 @@ struct usdhc_data { usdhc_handle_t transfer_handle; struct sdhc_io host_io; struct k_mutex access_mutex; + sdhc_interrupt_cb_t sdhc_cb; + struct gpio_callback cd_callback; + void *sdhc_cb_user_data; uint8_t usdhc_rx_dummy[128] __aligned(32); #ifdef CONFIG_IMX_USDHC_DMA_SUPPORT uint32_t *usdhc_dma_descriptor; /* ADMA descriptor table (noncachable) */ @@ -107,6 +111,55 @@ static void transfer_complete_cb(USDHC_Type *usdhc, usdhc_handle_t *handle, k_sem_give(&data->transfer_sem); } + +static void sdio_interrupt_cb(USDHC_Type *usdhc, void *user_data) +{ + const struct device *dev = user_data; + struct usdhc_data *data = dev->data; + + if (data->sdhc_cb) { + data->sdhc_cb(dev, SDHC_INT_SDIO, data->sdhc_cb_user_data); + } +} + +static void card_inserted_cb(USDHC_Type *usdhc, void *user_data) +{ + const struct device *dev = user_data; + struct usdhc_data *data = dev->data; + + if (data->sdhc_cb) { + data->sdhc_cb(dev, SDHC_INT_INSERTED, data->sdhc_cb_user_data); + } +} + +static void card_removed_cb(USDHC_Type *usdhc, void *user_data) +{ + const struct device *dev = user_data; + struct usdhc_data *data = dev->data; + + if (data->sdhc_cb) { + data->sdhc_cb(dev, SDHC_INT_REMOVED, data->sdhc_cb_user_data); + } +} + +static void card_detect_gpio_cb(const struct device *port, + struct gpio_callback *cb, + gpio_port_pins_t pins) +{ + struct usdhc_data *data = CONTAINER_OF(cb, struct usdhc_data, cd_callback); + const struct device *dev = data->dev; + const struct usdhc_config *cfg = dev->config; + + if (data->sdhc_cb) { + if (gpio_pin_get_dt(&cfg->detect_gpio)) { + data->sdhc_cb(dev, SDHC_INT_INSERTED, data->sdhc_cb_user_data); + } else { + data->sdhc_cb(dev, SDHC_INT_REMOVED, data->sdhc_cb_user_data); + } + } +} + + static int imx_usdhc_dat3_pull(const struct usdhc_config *cfg, bool pullup) { int ret = 0U; @@ -333,16 +386,10 @@ static int imx_usdhc_set_io(const struct device *dev, struct sdhc_io *ios) /* Set card power */ if ((host_io->power_mode != ios->power_mode) && (cfg->pwr_gpio.port)) { - if (host_io->power_mode == SDHC_POWER_ON) { - /* Send 74 clock cycles if SD card is just powering on */ - USDHC_SetCardActive(cfg->base, 0xFFFF); - } - if (cfg->pwr_gpio.port) { - if (ios->power_mode == SDHC_POWER_OFF) { - gpio_pin_set_dt(&cfg->pwr_gpio, 0); - } else if (ios->power_mode == SDHC_POWER_ON) { - gpio_pin_set_dt(&cfg->pwr_gpio, 1); - } + if (ios->power_mode == SDHC_POWER_OFF) { + gpio_pin_set_dt(&cfg->pwr_gpio, 0); + } else if (ios->power_mode == SDHC_POWER_ON) { + gpio_pin_set_dt(&cfg->pwr_gpio, 1); } host_io->power_mode = ios->power_mode; } @@ -353,6 +400,10 @@ static int imx_usdhc_set_io(const struct device *dev, struct sdhc_io *ios) case SDHC_TIMING_LEGACY: case SDHC_TIMING_HS: break; + case SDHC_TIMING_DDR50: + case SDHC_TIMING_DDR52: + /* Enable DDR mode */ + USDHC_EnableDDRMode(cfg->base, true, 0); case SDHC_TIMING_SDR12: case SDHC_TIMING_SDR25: pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_SLOW); @@ -371,8 +422,6 @@ static int imx_usdhc_set_io(const struct device *dev, struct sdhc_io *ios) return -ENOTSUP; #endif case SDHC_TIMING_SDR104: - case SDHC_TIMING_DDR50: - case SDHC_TIMING_DDR52: case SDHC_TIMING_HS200: pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_FAST); break; @@ -591,6 +640,10 @@ static int imx_usdhc_request(const struct device *dev, struct sdhc_command *cmd, int ret = 0; int retries = (int)cmd->retries; + if (cmd->opcode == SD_GO_IDLE_STATE) { + USDHC_SetCardActive(cfg->base, 0xFFFF); + } + host_cmd.index = cmd->opcode; host_cmd.argument = cmd->arg; /* Mask out part of response type field used for SPI commands */ @@ -645,6 +698,14 @@ static int imx_usdhc_request(const struct device *dev, struct sdhc_command *cmd, case SD_APP_SEND_NUM_WRITTEN_BLK: host_data.rxData = data->data; break; + case SDIO_RW_EXTENDED: + /* Use R/W bit to determine data direction */ + if (host_cmd.argument & BIT(SDIO_CMD_ARG_RW_SHIFT)) { + host_data.txData = data->data; + } else { + host_data.rxData = data->data; + } + break; default: return -ENOTSUP; @@ -757,8 +818,7 @@ static int imx_usdhc_get_card_present(const struct device *dev) } else if (cfg->detect_gpio.port) { data->card_present = gpio_pin_get_dt(&cfg->detect_gpio) > 0; } else { - LOG_WRN("No card presence method configured, assuming card is present"); - data->card_present = true; + data->card_present = USDHC_DetectCardInsert(cfg->base); } return ((int)data->card_present); } @@ -775,6 +835,132 @@ static int imx_usdhc_get_host_props(const struct device *dev, return 0; } +/* + * Enable SDHC card interrupt + */ +static int imx_usdhc_enable_interrupt(const struct device *dev, + sdhc_interrupt_cb_t callback, + int sources, void *user_data) +{ + const struct usdhc_config *cfg = dev->config; + struct usdhc_data *data = dev->data; + int ret; + + /* Record SDIO callback parameters */ + data->sdhc_cb = callback; + data->sdhc_cb_user_data = user_data; + + /* Disable interrupts, then enable what the user requested */ + USDHC_DisableInterruptStatus(cfg->base, kUSDHC_CardInterruptFlag); + USDHC_DisableInterruptSignal(cfg->base, kUSDHC_CardInterruptFlag); + if (cfg->detect_gpio.port) { + ret = gpio_pin_interrupt_configure_dt(&cfg->detect_gpio, + GPIO_INT_DISABLE); + if (ret) { + return ret; + } + } else { + USDHC_DisableInterruptSignal(cfg->base, kUSDHC_CardInsertionFlag); + USDHC_DisableInterruptStatus(cfg->base, kUSDHC_CardInsertionFlag); + USDHC_DisableInterruptSignal(cfg->base, kUSDHC_CardRemovalFlag); + USDHC_DisableInterruptStatus(cfg->base, kUSDHC_CardRemovalFlag); + } + + if (sources & SDHC_INT_SDIO) { + /* Enable SDIO card interrupt */ + USDHC_EnableInterruptStatus(cfg->base, kUSDHC_CardInterruptFlag); + USDHC_EnableInterruptSignal(cfg->base, kUSDHC_CardInterruptFlag); + } + if (sources & SDHC_INT_INSERTED) { + if (cfg->detect_gpio.port) { + /* Use GPIO interrupt */ + ret = gpio_pin_interrupt_configure_dt(&cfg->detect_gpio, + GPIO_INT_EDGE_TO_ACTIVE); + if (ret) { + return ret; + } + } else { + /* Enable card insertion interrupt */ + USDHC_EnableInterruptStatus(cfg->base, + kUSDHC_CardInsertionFlag); + USDHC_EnableInterruptSignal(cfg->base, + kUSDHC_CardInsertionFlag); + } + } + if (sources & SDHC_INT_REMOVED) { + if (cfg->detect_gpio.port) { + /* Use GPIO interrupt */ + ret = gpio_pin_interrupt_configure_dt(&cfg->detect_gpio, + GPIO_INT_EDGE_TO_INACTIVE); + if (ret) { + return ret; + } + } else { + /* Enable card removal interrupt */ + USDHC_EnableInterruptStatus(cfg->base, + kUSDHC_CardRemovalFlag); + USDHC_EnableInterruptSignal(cfg->base, + kUSDHC_CardRemovalFlag); + } + } + + return 0; +} + +static int imx_usdhc_disable_interrupt(const struct device *dev, int sources) +{ + const struct usdhc_config *cfg = dev->config; + struct usdhc_data *data = dev->data; + int ret; + + + if (sources & SDHC_INT_SDIO) { + /* Disable SDIO card interrupt */ + USDHC_DisableInterruptStatus(cfg->base, kUSDHC_CardInterruptFlag); + USDHC_DisableInterruptSignal(cfg->base, kUSDHC_CardInterruptFlag); + } + if (sources & SDHC_INT_INSERTED) { + if (cfg->detect_gpio.port) { + ret = gpio_pin_interrupt_configure_dt(&cfg->detect_gpio, + GPIO_INT_DISABLE); + if (ret) { + return ret; + } + } else { + /* Disable card insertion interrupt */ + USDHC_DisableInterruptStatus(cfg->base, + kUSDHC_CardInsertionFlag); + USDHC_DisableInterruptSignal(cfg->base, + kUSDHC_CardInsertionFlag); + } + } + if (sources & SDHC_INT_REMOVED) { + if (cfg->detect_gpio.port) { + ret = gpio_pin_interrupt_configure_dt(&cfg->detect_gpio, + GPIO_INT_DISABLE); + if (ret) { + return ret; + } + } else { + /* Disable card removal interrupt */ + USDHC_DisableInterruptStatus(cfg->base, + kUSDHC_CardRemovalFlag); + USDHC_DisableInterruptSignal(cfg->base, + kUSDHC_CardRemovalFlag); + } + } + + /* If all interrupt flags are disabled, remove callback */ + if ((USDHC_GetEnabledInterruptStatusFlags(cfg->base) & + (kUSDHC_CardInterruptFlag | kUSDHC_CardInsertionFlag | + kUSDHC_CardRemovalFlag)) == 0) { + data->sdhc_cb = NULL; + data->sdhc_cb_user_data = NULL; + } + + return 0; +} + static int imx_usdhc_isr(const struct device *dev) { const struct usdhc_config *cfg = dev->config; @@ -795,6 +981,9 @@ static int imx_usdhc_init(const struct device *dev) int ret; const usdhc_transfer_callback_t callbacks = { .TransferComplete = transfer_complete_cb, + .SdioInterrupt = sdio_interrupt_cb, + .CardInserted = card_inserted_cb, + .CardRemoved = card_removed_cb, }; if (!device_is_ready(cfg->clock_dev)) { @@ -833,7 +1022,14 @@ static int imx_usdhc_init(const struct device *dev) if (ret) { return ret; } + gpio_init_callback(&data->cd_callback, card_detect_gpio_cb, + BIT(cfg->detect_gpio.pin)); + ret = gpio_add_callback_dt(&cfg->detect_gpio, &data->cd_callback); + if (ret) { + return ret; + } } + data->dev = dev; k_mutex_init(&data->access_mutex); memset(&data->host_io, 0, sizeof(data->host_io)); return k_sem_init(&data->transfer_sem, 0, 1); @@ -847,6 +1043,8 @@ static const struct sdhc_driver_api usdhc_api = { .execute_tuning = imx_usdhc_execute_tuning, .card_busy = imx_usdhc_card_busy, .get_host_props = imx_usdhc_get_host_props, + .enable_interrupt = imx_usdhc_enable_interrupt, + .disable_interrupt = imx_usdhc_disable_interrupt, }; #ifdef CONFIG_NOCACHE_MEMORY diff --git a/drivers/sdhc/intel_emmc_host.c b/drivers/sdhc/intel_emmc_host.c new file mode 100644 index 00000000000..ec5c7934be1 --- /dev/null +++ b/drivers/sdhc/intel_emmc_host.c @@ -0,0 +1,1348 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT intel_emmc_host + +#include +#include +#include +#include +#include +#include "intel_emmc_host.h" +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(pcie) +BUILD_ASSERT(IS_ENABLED(CONFIG_PCIE), "DT need CONFIG_PCIE"); +#include +#endif + +#include +LOG_MODULE_REGISTER(emmc_hc, CONFIG_SDHC_LOG_LEVEL); + +typedef void (*emmc_isr_cb_t)(const struct device *dev); + +#ifdef CONFIG_INTEL_EMMC_HOST_ADMA_DESC_SIZE +#define ADMA_DESC_SIZE CONFIG_INTEL_EMMC_HOST_ADMA_DESC_SIZE +#else +#define ADMA_DESC_SIZE 0 +#endif + +struct emmc_config { +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(pcie) + struct pcie_dev *pcie; +#else + DEVICE_MMIO_ROM; +#endif + emmc_isr_cb_t config_func; + uint32_t max_bus_freq; + uint32_t min_bus_freq; + uint32_t power_delay_ms; + uint8_t hs200_mode: 1; + uint8_t hs400_mode: 1; + uint8_t dw_4bit: 1; + uint8_t dw_8bit: 1; +}; + +struct emmc_data { + DEVICE_MMIO_RAM; + uint32_t rca; + struct sdhc_io host_io; + struct k_sem lock; + struct k_event irq_event; + uint64_t desc_table[ADMA_DESC_SIZE]; + struct sdhc_host_props props; + bool card_present; +}; + +static void enable_interrupts(const struct device *dev) +{ + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + + regs->normal_int_stat_en = EMMC_HOST_NORMAL_INTR_MASK; + regs->err_int_stat_en = EMMC_HOST_ERROR_INTR_MASK; + regs->normal_int_signal_en = EMMC_HOST_NORMAL_INTR_MASK; + regs->err_int_signal_en = EMMC_HOST_ERROR_INTR_MASK; + regs->timeout_ctrl = EMMC_HOST_MAX_TIMEOUT; +} + +static void disable_interrupts(const struct device *dev) +{ + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + + /* Keep enable interrupt status register to update */ + regs->normal_int_stat_en = EMMC_HOST_NORMAL_INTR_MASK; + regs->err_int_stat_en = EMMC_HOST_ERROR_INTR_MASK; + + /* Disable only interrupt generation */ + regs->normal_int_signal_en &= 0; + regs->err_int_signal_en &= 0; + regs->timeout_ctrl = EMMC_HOST_MAX_TIMEOUT; +} + +static void clear_interrupts(const struct device *dev) +{ + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + + regs->normal_int_stat = EMMC_HOST_NORMAL_INTR_MASK_CLR; + regs->err_int_stat = EMMC_HOST_ERROR_INTR_MASK; +} + +static int emmc_set_voltage(const struct device *dev, enum sd_voltage signal_voltage) +{ + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + bool power_state = regs->power_ctrl & EMMC_HOST_POWER_CTRL_SD_BUS_POWER ? true : false; + int ret = 0; + + if (power_state) { + /* Turn OFF Bus Power before config clock */ + regs->power_ctrl &= ~EMMC_HOST_POWER_CTRL_SD_BUS_POWER; + } + + switch (signal_voltage) { + case SD_VOL_3_3_V: + if (regs->capabilities & EMMC_HOST_VOL_3_3_V_SUPPORT) { + regs->host_ctrl2 &= + ~(EMMC_HOST_CTRL2_1P8V_SIG_EN << EMMC_HOST_CTRL2_1P8V_SIG_LOC); + + /* 3.3v voltage select */ + regs->power_ctrl = EMMC_HOST_VOL_3_3_V_SELECT; + LOG_DBG("3.3V Selected for MMC Card"); + } else { + LOG_ERR("3.3V not supported by MMC Host"); + ret = -ENOTSUP; + } + break; + + case SD_VOL_3_0_V: + if (regs->capabilities & EMMC_HOST_VOL_3_0_V_SUPPORT) { + regs->host_ctrl2 &= + ~(EMMC_HOST_CTRL2_1P8V_SIG_EN << EMMC_HOST_CTRL2_1P8V_SIG_LOC); + + /* 3.0v voltage select */ + regs->power_ctrl = EMMC_HOST_VOL_3_0_V_SELECT; + LOG_DBG("3.0V Selected for MMC Card"); + } else { + LOG_ERR("3.0V not supported by MMC Host"); + ret = -ENOTSUP; + } + break; + + case SD_VOL_1_8_V: + if (regs->capabilities & EMMC_HOST_VOL_1_8_V_SUPPORT) { + regs->host_ctrl2 |= EMMC_HOST_CTRL2_1P8V_SIG_EN + << EMMC_HOST_CTRL2_1P8V_SIG_LOC; + + /* 1.8v voltage select */ + regs->power_ctrl = EMMC_HOST_VOL_1_8_V_SELECT; + LOG_DBG("1.8V Selected for MMC Card"); + } else { + LOG_ERR("1.8V not supported by MMC Host"); + ret = -ENOTSUP; + } + break; + + default: + ret = -EINVAL; + } + + if (power_state) { + /* Turn ON Bus Power */ + regs->power_ctrl |= EMMC_HOST_POWER_CTRL_SD_BUS_POWER; + } + + return ret; +} + +static int emmc_set_power(const struct device *dev, enum sdhc_power state) +{ + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + + if (state == SDHC_POWER_ON) { + /* Turn ON Bus Power */ + regs->power_ctrl |= EMMC_HOST_POWER_CTRL_SD_BUS_POWER; + } else { + /* Turn OFF Bus Power */ + regs->power_ctrl &= ~EMMC_HOST_POWER_CTRL_SD_BUS_POWER; + } + + k_msleep(10u); + + return 0; +} + +static bool emmc_disable_clock(const struct device *dev) +{ + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + + if (regs->present_state & EMMC_HOST_PSTATE_CMD_INHIBIT) { + LOG_ERR("present_state:%x", regs->present_state); + return false; + } + if (regs->present_state & EMMC_HOST_PSTATE_DAT_INHIBIT) { + LOG_ERR("present_state:%x", regs->present_state); + return false; + } + + regs->clock_ctrl &= ~EMMC_HOST_INTERNAL_CLOCK_EN; + regs->clock_ctrl &= ~EMMC_HOST_SD_CLOCK_EN; + + while ((regs->clock_ctrl & EMMC_HOST_SD_CLOCK_EN) != 0) { + ; + } + + return true; +} + +static bool emmc_enable_clock(const struct device *dev) +{ + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + + regs->clock_ctrl |= EMMC_HOST_INTERNAL_CLOCK_EN; + /* Wait for the stable Internal Clock */ + while ((regs->clock_ctrl & EMMC_HOST_INTERNAL_CLOCK_STABLE) == 0) { + ; + } + + /* Enable SD Clock */ + regs->clock_ctrl |= EMMC_HOST_SD_CLOCK_EN; + while ((regs->clock_ctrl & EMMC_HOST_SD_CLOCK_EN) == 0) { + ; + } + + return true; +} + +static bool emmc_clock_set(const struct device *dev, enum sdhc_clock_speed speed) +{ + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + uint8_t base_freq; + uint32_t clock_divider; + float freq; + bool ret; + + switch (speed) { + case SDMMC_CLOCK_400KHZ: + freq = EMMC_HOST_CLK_FREQ_400K; + break; + + case SD_CLOCK_25MHZ: + case MMC_CLOCK_26MHZ: + freq = EMMC_HOST_CLK_FREQ_25M; + break; + + case SD_CLOCK_50MHZ: + case MMC_CLOCK_52MHZ: + freq = EMMC_HOST_CLK_FREQ_50M; + break; + + case SD_CLOCK_100MHZ: + freq = EMMC_HOST_CLK_FREQ_100M; + break; + + case MMC_CLOCK_HS200: + freq = EMMC_HOST_CLK_FREQ_200M; + break; + + case SD_CLOCK_208MHZ: + default: + return false; + } + + ret = emmc_disable_clock(dev); + if (!ret) { + return false; + } + + base_freq = regs->capabilities >> 8; + clock_divider = (int)(base_freq / (freq * 2)); + + LOG_DBG("Clock divider for MMC Clk: %d Hz is %d", speed, clock_divider); + + SET_BITS(regs->clock_ctrl, EMMC_HOST_CLK_SDCLCK_FREQ_SEL_LOC, + EMMC_HOST_CLK_SDCLCK_FREQ_SEL_MASK, clock_divider); + SET_BITS(regs->clock_ctrl, EMMC_HOST_CLK_SDCLCK_FREQ_SEL_UPPER_LOC, + EMMC_HOST_CLK_SDCLCK_FREQ_SEL_UPPER_MASK, clock_divider >> 8); + + emmc_enable_clock(dev); + + return true; +} + +static int set_timing(const struct device *dev, enum sdhc_timing_mode timing) +{ + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + int ret = 0; + uint8_t mode; + + LOG_DBG("UHS Mode: %d", timing); + + switch (timing) { + case SDHC_TIMING_LEGACY: + case SDHC_TIMING_HS: + case SDHC_TIMING_SDR12: + mode = EMMC_HOST_UHSMODE_SDR12; + break; + + case SDHC_TIMING_SDR25: + mode = EMMC_HOST_UHSMODE_SDR25; + break; + + case SDHC_TIMING_SDR50: + mode = EMMC_HOST_UHSMODE_SDR50; + break; + + case SDHC_TIMING_SDR104: + mode = EMMC_HOST_UHSMODE_SDR104; + break; + + case SDHC_TIMING_DDR50: + case SDHC_TIMING_DDR52: + mode = EMMC_HOST_UHSMODE_DDR50; + break; + + case SDHC_TIMING_HS400: + case SDHC_TIMING_HS200: + mode = EMMC_HOST_UHSMODE_HS400; + break; + + default: + ret = -ENOTSUP; + } + + if (!ret) { + if (!emmc_disable_clock(dev)) { + LOG_ERR("Disable clk failed"); + return -EIO; + } + regs->host_ctrl2 |= EMMC_HOST_CTRL2_1P8V_SIG_EN << EMMC_HOST_CTRL2_1P8V_SIG_LOC; + SET_BITS(regs->host_ctrl2, EMMC_HOST_CTRL2_UHS_MODE_SEL_LOC, + EMMC_HOST_CTRL2_UHS_MODE_SEL_MASK, mode); + + emmc_enable_clock(dev); + } + + return ret; +} + +static int wait_for_cmd_complete(struct emmc_data *emmc, uint32_t time_out) +{ + int ret; + k_timeout_t wait_time; + uint32_t events; + + if (time_out == SDHC_TIMEOUT_FOREVER) { + wait_time = K_FOREVER; + } else { + wait_time = K_MSEC(time_out); + } + + events = k_event_wait(&emmc->irq_event, + EMMC_HOST_CMD_COMPLETE | ERR_INTR_STATUS_EVENT(EMMC_HOST_ERR_STATUS), + false, wait_time); + + if (events & EMMC_HOST_CMD_COMPLETE) { + ret = 0; + } else if (events & ERR_INTR_STATUS_EVENT(EMMC_HOST_ERR_STATUS)) { + LOG_ERR("wait for cmd complete error: %x", events); + ret = -EIO; + } else { + LOG_ERR("wait for cmd complete timeout"); + ret = -EAGAIN; + } + + return ret; +} + +static int poll_cmd_complete(const struct device *dev, uint32_t time_out) +{ + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + int ret = -EAGAIN; + int32_t retry = time_out; + + while (retry > 0) { + if (regs->normal_int_stat & EMMC_HOST_CMD_COMPLETE) { + regs->normal_int_stat = EMMC_HOST_CMD_COMPLETE; + ret = 0; + break; + } + + k_busy_wait(1000u); + retry--; + } + + if (regs->err_int_stat) { + LOG_ERR("err_int_stat:%x", regs->err_int_stat); + regs->err_int_stat &= regs->err_int_stat; + ret = -EIO; + } + + if (IS_ENABLED(CONFIG_INTEL_EMMC_HOST_ADMA)) { + if (regs->adma_err_stat) { + LOG_ERR("adma error: %x", regs->adma_err_stat); + ret = -EIO; + } + } + return ret; +} + +void emmc_host_sw_reset(const struct device *dev, enum emmc_sw_reset reset) +{ + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + + if (reset == EMMC_HOST_SW_RESET_DATA_LINE) { + regs->sw_reset = EMMC_HOST_SW_RESET_REG_DATA; + } else if (reset == EMMC_HOST_SW_RESET_CMD_LINE) { + regs->sw_reset = EMMC_HOST_SW_RESET_REG_CMD; + } else if (reset == EMMC_HOST_SW_RESET_ALL) { + regs->sw_reset = EMMC_HOST_SW_RESET_REG_ALL; + } + + while (regs->sw_reset != 0) { + ; + } + + k_sleep(K_MSEC(100u)); +} + +static int emmc_dma_init(const struct device *dev, struct sdhc_data *data, bool read) +{ + struct emmc_data *emmc = dev->data; + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + + if (IS_ENABLED(CONFIG_DCACHE) && !read) { + sys_cache_data_flush_range(data->data, (data->blocks * data->block_size)); + } + + if (IS_ENABLED(CONFIG_INTEL_EMMC_HOST_ADMA)) { + uint8_t *buff = data->data; + + /* Setup DMA trasnfer using ADMA2 */ + memset(emmc->desc_table, 0, sizeof(emmc->desc_table)); + +#if defined(CONFIG_INTEL_EMMC_HOST_ADMA_DESC_SIZE) + __ASSERT_NO_MSG(data->blocks < CONFIG_INTEL_EMMC_HOST_ADMA_DESC_SIZE); +#endif + for (int i = 0; i < data->blocks; i++) { + emmc->desc_table[i] = ((uint64_t)buff) << EMMC_HOST_ADMA_BUFF_ADD_LOC; + emmc->desc_table[i] |= data->block_size << EMMC_HOST_ADMA_BUFF_LEN_LOC; + + if (i == (data->blocks - 1u)) { + emmc->desc_table[i] |= EMMC_HOST_ADMA_BUFF_LINK_LAST; + emmc->desc_table[i] |= EMMC_HOST_ADMA_INTR_EN; + emmc->desc_table[i] |= EMMC_HOST_ADMA_BUFF_LAST; + } else { + emmc->desc_table[i] |= EMMC_HOST_ADMA_BUFF_LINK_NEXT; + } + emmc->desc_table[i] |= EMMC_HOST_ADMA_BUFF_VALID; + buff += data->block_size; + LOG_DBG("desc_table:%llx", emmc->desc_table[i]); + } + + regs->adma_sys_addr1 = (uint32_t)((uintptr_t)emmc->desc_table & ADDRESS_32BIT_MASK); + regs->adma_sys_addr2 = + (uint32_t)(((uintptr_t)emmc->desc_table >> 32) & ADDRESS_32BIT_MASK); + + LOG_DBG("adma: %llx %x %p", emmc->desc_table[0], regs->adma_sys_addr1, + emmc->desc_table); + } else { + /* Setup DMA trasnfer using SDMA */ + regs->sdma_sysaddr = (uint32_t)((uintptr_t)data->data); + LOG_DBG("sdma_sysaddr: %x", regs->sdma_sysaddr); + } + return 0; +} + +static int emmc_init_xfr(const struct device *dev, struct sdhc_data *data, bool read) +{ + struct emmc_data *emmc = dev->data; + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + uint16_t multi_block = 0u; + + if (IS_ENABLED(CONFIG_INTEL_EMMC_HOST_DMA)) { + emmc_dma_init(dev, data, read); + } + + if (IS_ENABLED(CONFIG_INTEL_EMMC_HOST_ADMA)) { + SET_BITS(regs->host_ctrl1, EMMC_HOST_CTRL1_DMA_SEL_LOC, + EMMC_HOST_CTRL1_DMA_SEL_MASK, 2u); + } else { + SET_BITS(regs->host_ctrl1, EMMC_HOST_CTRL1_DMA_SEL_LOC, + EMMC_HOST_CTRL1_DMA_SEL_MASK, 0u); + } + + /* Set Block Size Register */ + SET_BITS(regs->block_size, EMMC_HOST_DMA_BUF_SIZE_LOC, EMMC_HOST_DMA_BUF_SIZE_MASK, + EMMC_HOST_SDMA_BOUNDARY); + SET_BITS(regs->block_size, EMMC_HOST_BLOCK_SIZE_LOC, EMMC_HOST_BLOCK_SIZE_MASK, + data->block_size); + if (data->blocks > 1) { + multi_block = 1u; + } + if (IS_ENABLED(CONFIG_INTEL_EMMC_HOST_AUTO_STOP)) { + if (IS_ENABLED(CONFIG_INTEL_EMMC_HOST_ADMA) && + emmc->host_io.timing == SDHC_TIMING_SDR104) { + /* Auto cmd23 only applicable for ADMA */ + SET_BITS(regs->transfer_mode, EMMC_HOST_XFER_AUTO_CMD_EN_LOC, + EMMC_HOST_XFER_AUTO_CMD_EN_MASK, multi_block ? 2 : 0); + } else { + SET_BITS(regs->transfer_mode, EMMC_HOST_XFER_AUTO_CMD_EN_LOC, + EMMC_HOST_XFER_AUTO_CMD_EN_MASK, multi_block ? 1 : 0); + } + } else { + SET_BITS(regs->transfer_mode, EMMC_HOST_XFER_AUTO_CMD_EN_LOC, + EMMC_HOST_XFER_AUTO_CMD_EN_MASK, 0); + } + + if (!IS_ENABLED(CONFIG_INTEL_EMMC_HOST_AUTO_STOP)) { + /* Set block count regitser to 0 for infinite transfer mode */ + regs->block_count = 0; + SET_BITS(regs->transfer_mode, EMMC_HOST_XFER_BLOCK_CNT_EN_LOC, + EMMC_HOST_XFER_BLOCK_CNT_EN_MASK, 0); + } else { + regs->block_count = (uint16_t)data->blocks; + /* Enable block count in transfer register */ + SET_BITS(regs->transfer_mode, EMMC_HOST_XFER_BLOCK_CNT_EN_LOC, + EMMC_HOST_XFER_BLOCK_CNT_EN_MASK, multi_block ? 1 : 0); + } + + SET_BITS(regs->transfer_mode, EMMC_HOST_XFER_MULTI_BLOCK_SEL_LOC, + EMMC_HOST_XFER_MULTI_BLOCK_SEL_MASK, multi_block); + + /* Set data transfer direction, Read = 1, Write = 0 */ + SET_BITS(regs->transfer_mode, EMMC_HOST_XFER_DATA_DIR_LOC, EMMC_HOST_XFER_DATA_DIR_MASK, + read ? 1u : 0u); + + if (IS_ENABLED(CONFIG_INTEL_EMMC_HOST_DMA)) { + /* Enable DMA or not */ + SET_BITS(regs->transfer_mode, EMMC_HOST_XFER_DMA_EN_LOC, EMMC_HOST_XFER_DMA_EN_MASK, + 1u); + } else { + SET_BITS(regs->transfer_mode, EMMC_HOST_XFER_DMA_EN_LOC, EMMC_HOST_XFER_DMA_EN_MASK, + 0u); + } + + if (IS_ENABLED(CONFIG_INTEL_EMMC_HOST_BLOCK_GAP)) { + /* Set an interrupt at the block gap */ + SET_BITS(regs->block_gap_ctrl, EMMC_HOST_BLOCK_GAP_LOC, EMMC_HOST_BLOCK_GAP_MASK, + 1u); + } else { + SET_BITS(regs->block_gap_ctrl, EMMC_HOST_BLOCK_GAP_LOC, EMMC_HOST_BLOCK_GAP_MASK, + 0u); + } + + /* Set data timeout time */ + regs->timeout_ctrl = data->timeout_ms; + + return 0; +} + +static int wait_xfr_intr_complete(const struct device *dev, uint32_t time_out) +{ + struct emmc_data *emmc = dev->data; + uint32_t events; + int ret; + k_timeout_t wait_time; + + LOG_DBG(""); + + if (time_out == SDHC_TIMEOUT_FOREVER) { + wait_time = K_FOREVER; + } else { + wait_time = K_MSEC(time_out); + } + + events = k_event_wait(&emmc->irq_event, + EMMC_HOST_XFER_COMPLETE | + ERR_INTR_STATUS_EVENT(EMMC_HOST_DMA_TXFR_ERR), + false, wait_time); + + if (events & EMMC_HOST_XFER_COMPLETE) { + ret = 0; + } else if (events & ERR_INTR_STATUS_EVENT(0xFFFF)) { + LOG_ERR("wait for xfer complete error: %x", events); + ret = -EIO; + } else { + LOG_ERR("wait for xfer complete timeout"); + ret = -EAGAIN; + } + + return ret; +} + +static int wait_xfr_poll_complete(const struct device *dev, uint32_t time_out) +{ + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + int ret = -EAGAIN; + int32_t retry = time_out; + + LOG_DBG(""); + + while (retry > 0) { + if (regs->normal_int_stat & EMMC_HOST_XFER_COMPLETE) { + regs->normal_int_stat |= EMMC_HOST_XFER_COMPLETE; + ret = 0; + break; + } + + k_busy_wait(EMMC_HOST_MSEC_DELAY); + retry--; + } + + return ret; +} + +static int wait_xfr_complete(const struct device *dev, uint32_t time_out) +{ + int ret; + + if (IS_ENABLED(CONFIG_INTEL_EMMC_HOST_INTR)) { + ret = wait_xfr_intr_complete(dev, time_out); + } else { + ret = wait_xfr_poll_complete(dev, time_out); + } + return ret; +} + +static enum emmc_response_type emmc_decode_resp_type(enum sd_rsp_type type) +{ + enum emmc_response_type resp_type; + + switch (type & 0xF) { + case SD_RSP_TYPE_NONE: + resp_type = EMMC_HOST_RESP_NONE; + break; + case SD_RSP_TYPE_R1: + case SD_RSP_TYPE_R3: + case SD_RSP_TYPE_R4: + case SD_RSP_TYPE_R5: + resp_type = EMMC_HOST_RESP_LEN_48; + break; + case SD_RSP_TYPE_R1b: + resp_type = EMMC_HOST_RESP_LEN_48B; + break; + case SD_RSP_TYPE_R2: + resp_type = EMMC_HOST_RESP_LEN_136; + break; + + case SD_RSP_TYPE_R5b: + case SD_RSP_TYPE_R6: + case SD_RSP_TYPE_R7: + default: + resp_type = EMMC_HOST_INVAL_HOST_RESP_LEN; + } + + return resp_type; +} + +static void update_cmd_response(const struct device *dev, struct sdhc_command *sdhc_cmd) +{ + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + uint32_t resp0, resp1, resp2, resp3; + + if (sdhc_cmd->response_type == SD_RSP_TYPE_NONE) { + return; + } + + resp0 = regs->resp_01; + + if (sdhc_cmd->response_type == SD_RSP_TYPE_R2) { + resp1 = regs->resp_2 | (regs->resp_3 << 16u); + resp2 = regs->resp_4 | (regs->resp_5 << 16u); + resp3 = regs->resp_6 | (regs->resp_7 << 16u); + + LOG_DBG("cmd resp: %x %x %x %x", resp0, resp1, resp2, resp3); + + sdhc_cmd->response[0u] = resp3; + sdhc_cmd->response[1U] = resp2; + sdhc_cmd->response[2U] = resp1; + sdhc_cmd->response[3U] = resp0; + } else { + LOG_DBG("cmd resp: %x", resp0); + sdhc_cmd->response[0u] = resp0; + } +} + +static int emmc_host_send_cmd(const struct device *dev, const struct emmc_cmd_config *config) +{ + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + struct emmc_data *emmc = dev->data; + struct sdhc_command *sdhc_cmd = config->sdhc_cmd; + enum emmc_response_type resp_type = emmc_decode_resp_type(sdhc_cmd->response_type); + uint16_t cmd_reg; + int ret; + + LOG_DBG(""); + + /* Check if CMD line is available */ + if (regs->present_state & EMMC_HOST_PSTATE_CMD_INHIBIT) { + LOG_ERR("CMD line is not available"); + return -EBUSY; + } + + if (config->data_present && (regs->present_state & EMMC_HOST_PSTATE_DAT_INHIBIT)) { + LOG_ERR("Data line is not available"); + return -EBUSY; + } + + if (resp_type == EMMC_HOST_INVAL_HOST_RESP_LEN) { + LOG_ERR("Invalid eMMC resp type:%d", resp_type); + return -EINVAL; + } + + k_event_clear(&emmc->irq_event, EMMC_HOST_CMD_COMPLETE); + + regs->argument = sdhc_cmd->arg; + + cmd_reg = config->cmd_idx << EMMC_HOST_CMD_INDEX_LOC | + config->cmd_type << EMMC_HOST_CMD_TYPE_LOC | + config->data_present << EMMC_HOST_CMD_DATA_PRESENT_LOC | + config->idx_check_en << EMMC_HOST_CMD_IDX_CHECK_EN_LOC | + config->crc_check_en << EMMC_HOST_CMD_CRC_CHECK_EN_LOC | + resp_type << EMMC_HOST_CMD_RESP_TYPE_LOC; + regs->cmd = cmd_reg; + + LOG_DBG("CMD REG:%x %x", cmd_reg, regs->cmd); + if (IS_ENABLED(CONFIG_INTEL_EMMC_HOST_INTR)) { + ret = wait_for_cmd_complete(emmc, sdhc_cmd->timeout_ms); + } else { + ret = poll_cmd_complete(dev, sdhc_cmd->timeout_ms); + } + if (ret) { + LOG_ERR("Error on send cmd: %d, status:%d", config->cmd_idx, ret); + return ret; + } + + update_cmd_response(dev, sdhc_cmd); + + return 0; +} + +static int emmc_stop_transfer(const struct device *dev) +{ + struct emmc_data *emmc = dev->data; + struct sdhc_command hdc_cmd = {0}; + struct emmc_cmd_config cmd; + + hdc_cmd.arg = emmc->rca << EMMC_HOST_RCA_SHIFT; + hdc_cmd.response_type = SD_RSP_TYPE_R1; + hdc_cmd.timeout_ms = 1000; + + cmd.sdhc_cmd = &hdc_cmd; + cmd.cmd_idx = SD_STOP_TRANSMISSION; + cmd.cmd_type = EMMC_HOST_CMD_NORMAL; + cmd.data_present = false; + cmd.idx_check_en = false; + cmd.crc_check_en = false; + + return emmc_host_send_cmd(dev, &cmd); +} + +static int emmc_reset(const struct device *dev) +{ + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + + LOG_DBG(""); + + if (!(regs->present_state & EMMC_HOST_PSTATE_CARD_INSERTED)) { + LOG_ERR("No EMMC card found"); + return -ENODEV; + } + + /* Reset device to idle state */ + emmc_host_sw_reset(dev, EMMC_HOST_SW_RESET_ALL); + + clear_interrupts(dev); + + if (IS_ENABLED(CONFIG_INTEL_EMMC_HOST_INTR)) { + enable_interrupts(dev); + } else { + disable_interrupts(dev); + } + + return 0; +} + +static int read_data_port(const struct device *dev, struct sdhc_data *sdhc) +{ + struct emmc_data *emmc = dev->data; + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + uint32_t block_size = sdhc->block_size; + uint32_t i, block_cnt = sdhc->blocks; + uint32_t *data = (uint32_t *)sdhc->data; + k_timeout_t wait_time; + + if (sdhc->timeout_ms == SDHC_TIMEOUT_FOREVER) { + wait_time = K_FOREVER; + } else { + wait_time = K_MSEC(sdhc->timeout_ms); + } + + LOG_DBG(""); + + while (block_cnt--) { + if (IS_ENABLED(CONFIG_INTEL_EMMC_HOST_INTR)) { + uint32_t events; + + events = k_event_wait(&emmc->irq_event, EMMC_HOST_BUF_RD_READY, false, + wait_time); + k_event_clear(&emmc->irq_event, EMMC_HOST_BUF_RD_READY); + if (!(events & EMMC_HOST_BUF_RD_READY)) { + LOG_ERR("time out on EMMC_HOST_BUF_RD_READY:%d", + (sdhc->blocks - block_cnt)); + return -EIO; + } + } else { + while ((regs->present_state & EMMC_HOST_PSTATE_BUF_READ_EN) == 0) { + ; + } + } + + if (regs->present_state & EMMC_HOST_PSTATE_DAT_INHIBIT) { + for (i = block_size >> 2u; i != 0u; i--) { + *data = regs->data_port; + data++; + } + } + } + + return wait_xfr_complete(dev, sdhc->timeout_ms); +} + +static int write_data_port(const struct device *dev, struct sdhc_data *sdhc) +{ + struct emmc_data *emmc = dev->data; + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + uint32_t block_size = sdhc->block_size; + uint32_t i, block_cnt = sdhc->blocks; + uint32_t *data = (uint32_t *)sdhc->data; + k_timeout_t wait_time; + + if (sdhc->timeout_ms == SDHC_TIMEOUT_FOREVER) { + wait_time = K_FOREVER; + } else { + wait_time = K_MSEC(sdhc->timeout_ms); + } + + LOG_DBG(""); + + while ((regs->present_state & EMMC_HOST_PSTATE_BUF_WRITE_EN) == 0) { + ; + } + + while (1) { + uint32_t events; + + if (IS_ENABLED(CONFIG_INTEL_EMMC_HOST_INTR)) { + k_event_clear(&emmc->irq_event, EMMC_HOST_BUF_WR_READY); + } + + if (regs->present_state & EMMC_HOST_PSTATE_DAT_INHIBIT) { + for (i = block_size >> 2u; i != 0u; i--) { + regs->data_port = *data; + data++; + } + } + + LOG_DBG("EMMC_HOST_BUF_WR_READY"); + + if (!(--block_cnt)) { + break; + } + if (IS_ENABLED(CONFIG_INTEL_EMMC_HOST_INTR)) { + events = k_event_wait(&emmc->irq_event, EMMC_HOST_BUF_WR_READY, false, + wait_time); + k_event_clear(&emmc->irq_event, EMMC_HOST_BUF_WR_READY); + + if (!(events & EMMC_HOST_BUF_WR_READY)) { + LOG_ERR("time out on EMMC_HOST_BUF_WR_READY"); + return -EIO; + } + } else { + while ((regs->present_state & EMMC_HOST_PSTATE_BUF_WRITE_EN) == 0) { + ; + } + } + } + + return wait_xfr_complete(dev, sdhc->timeout_ms); +} + +static int emmc_send_cmd_no_data(const struct device *dev, uint32_t cmd_idx, + struct sdhc_command *cmd) +{ + struct emmc_cmd_config emmc_cmd; + + emmc_cmd.sdhc_cmd = cmd; + emmc_cmd.cmd_idx = cmd_idx; + emmc_cmd.cmd_type = EMMC_HOST_CMD_NORMAL; + emmc_cmd.data_present = false; + emmc_cmd.idx_check_en = false; + emmc_cmd.crc_check_en = false; + + return emmc_host_send_cmd(dev, &emmc_cmd); +} + +static int emmc_send_cmd_data(const struct device *dev, uint32_t cmd_idx, + struct sdhc_command *cmd, struct sdhc_data *data, bool read) +{ + struct emmc_cmd_config emmc_cmd; + int ret; + + emmc_cmd.sdhc_cmd = cmd; + emmc_cmd.cmd_idx = cmd_idx; + emmc_cmd.cmd_type = EMMC_HOST_CMD_NORMAL; + emmc_cmd.data_present = true; + emmc_cmd.idx_check_en = true; + emmc_cmd.crc_check_en = true; + + ret = emmc_init_xfr(dev, data, read); + if (ret) { + LOG_ERR("Error on init xfr"); + return ret; + } + + ret = emmc_host_send_cmd(dev, &emmc_cmd); + if (ret) { + return ret; + } + + if (IS_ENABLED(CONFIG_INTEL_EMMC_HOST_DMA)) { + ret = wait_xfr_complete(dev, data->timeout_ms); + } else { + if (read) { + ret = read_data_port(dev, data); + } else { + ret = write_data_port(dev, data); + } + } + + return ret; +} + +static int emmc_xfr(const struct device *dev, struct sdhc_command *cmd, struct sdhc_data *data, + bool read) +{ + struct emmc_data *emmc = dev->data; + int ret; + struct emmc_cmd_config emmc_cmd; + + ret = emmc_init_xfr(dev, data, read); + if (ret) { + LOG_ERR("error emmc init xfr"); + return ret; + } + emmc_cmd.sdhc_cmd = cmd; + emmc_cmd.cmd_type = EMMC_HOST_CMD_NORMAL; + emmc_cmd.data_present = true; + emmc_cmd.idx_check_en = true; + emmc_cmd.crc_check_en = true; + + k_event_clear(&emmc->irq_event, EMMC_HOST_XFER_COMPLETE); + k_event_clear(&emmc->irq_event, read ? EMMC_HOST_BUF_RD_READY : EMMC_HOST_BUF_WR_READY); + + if (data->blocks > 1) { + emmc_cmd.cmd_idx = read ? SD_READ_MULTIPLE_BLOCK : SD_WRITE_MULTIPLE_BLOCK; + ret = emmc_host_send_cmd(dev, &emmc_cmd); + } else { + emmc_cmd.cmd_idx = read ? SD_READ_SINGLE_BLOCK : SD_WRITE_SINGLE_BLOCK; + ret = emmc_host_send_cmd(dev, &emmc_cmd); + } + + if (ret) { + return ret; + } + + if (IS_ENABLED(CONFIG_INTEL_EMMC_HOST_DMA)) { + ret = wait_xfr_complete(dev, data->timeout_ms); + } else { + if (read) { + ret = read_data_port(dev, data); + } else { + ret = write_data_port(dev, data); + } + } + + if (!IS_ENABLED(CONFIG_INTEL_EMMC_HOST_AUTO_STOP)) { + emmc_stop_transfer(dev); + } + return ret; +} + +static int emmc_request(const struct device *dev, struct sdhc_command *cmd, struct sdhc_data *data) +{ + int ret; + + LOG_DBG(""); + + if (data) { + switch (cmd->opcode) { + case SD_WRITE_SINGLE_BLOCK: + case SD_WRITE_MULTIPLE_BLOCK: + LOG_DBG("SD_WRITE_SINGLE_BLOCK"); + ret = emmc_xfr(dev, cmd, data, false); + break; + + case SD_READ_SINGLE_BLOCK: + case SD_READ_MULTIPLE_BLOCK: + LOG_DBG("SD_READ_SINGLE_BLOCK"); + ret = emmc_xfr(dev, cmd, data, true); + break; + + case MMC_SEND_EXT_CSD: + LOG_DBG("EMMC_HOST_SEND_EXT_CSD"); + ret = emmc_send_cmd_data(dev, MMC_SEND_EXT_CSD, cmd, data, true); + break; + + default: + ret = emmc_send_cmd_data(dev, cmd->opcode, cmd, data, true); + } + } else { + ret = emmc_send_cmd_no_data(dev, cmd->opcode, cmd); + } + + return ret; +} + +static int emmc_set_io(const struct device *dev, struct sdhc_io *ios) +{ + struct emmc_data *emmc = dev->data; + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + struct sdhc_io *host_io = &emmc->host_io; + int ret; + + LOG_DBG("emmc I/O: DW %d, Clk %d Hz, card power state %s, voltage %s", ios->bus_width, + ios->clock, ios->power_mode == SDHC_POWER_ON ? "ON" : "OFF", + ios->signal_voltage == SD_VOL_1_8_V ? "1.8V" : "3.3V"); + + if (ios->clock && (ios->clock > emmc->props.f_max || ios->clock < emmc->props.f_min)) { + LOG_ERR("Invalid argument for clock freq: %d Support max:%d and Min:%d", ios->clock, + emmc->props.f_max, emmc->props.f_min); + return -EINVAL; + } + + /* Set HC clock */ + if (host_io->clock != ios->clock) { + LOG_DBG("Clock: %d", host_io->clock); + if (ios->clock != 0) { + /* Enable clock */ + LOG_DBG("CLOCK: %d", ios->clock); + if (!emmc_clock_set(dev, ios->clock)) { + return -ENOTSUP; + } + } else { + emmc_disable_clock(dev); + } + host_io->clock = ios->clock; + } + + /* Set data width */ + if (host_io->bus_width != ios->bus_width) { + LOG_DBG("bus_width: %d", host_io->bus_width); + + if (ios->bus_width == SDHC_BUS_WIDTH4BIT) { + SET_BITS(regs->host_ctrl1, EMMC_HOST_CTRL1_EXT_DAT_WIDTH_LOC, + EMMC_HOST_CTRL1_EXT_DAT_WIDTH_MASK, + ios->bus_width == SDHC_BUS_WIDTH8BIT ? 1 : 0); + } else { + SET_BITS(regs->host_ctrl1, EMMC_HOST_CTRL1_DAT_WIDTH_LOC, + EMMC_HOST_CTRL1_DAT_WIDTH_MASK, + ios->bus_width == SDHC_BUS_WIDTH4BIT ? 1 : 0); + } + host_io->bus_width = ios->bus_width; + } + + /* Set HC signal voltage */ + if (ios->signal_voltage != host_io->signal_voltage) { + LOG_DBG("signal_voltage: %d", ios->signal_voltage); + ret = emmc_set_voltage(dev, ios->signal_voltage); + if (ret) { + LOG_ERR("Set signal volatge failed:%d", ret); + return ret; + } + host_io->signal_voltage = ios->signal_voltage; + } + + /* Set card power */ + if (host_io->power_mode != ios->power_mode) { + LOG_DBG("power_mode: %d", ios->power_mode); + + ret = emmc_set_power(dev, ios->power_mode); + if (ret) { + LOG_ERR("Set Bus power failed:%d", ret); + return ret; + } + host_io->power_mode = ios->power_mode; + } + + /* Set I/O timing */ + if (host_io->timing != ios->timing) { + LOG_DBG("timing: %d", ios->timing); + + ret = set_timing(dev, ios->timing); + if (ret) { + LOG_ERR("Set timing failed:%d", ret); + return ret; + } + host_io->timing = ios->timing; + } + + return ret; +} + +static int emmc_get_card_present(const struct device *dev) +{ + struct emmc_data *emmc = dev->data; + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + + LOG_DBG(""); + + emmc->card_present = (bool)((regs->present_state >> 16u) & 1u); + + if (!emmc->card_present) { + LOG_ERR("No MMC device detected"); + } + + return ((int)emmc->card_present); +} + +static int emmc_execute_tuning(const struct device *dev) +{ + if (IS_ENABLED(CONFIG_INTEL_EMMC_HOST_TUNING)) { + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + + LOG_DBG("Tuning starting..."); + + regs->host_ctrl2 |= EMMC_HOST_START_TUNING; + while (!(regs->host_ctrl2 & EMMC_HOST_START_TUNING)) { + ; + } + + if (regs->host_ctrl2 & EMMC_HOST_TUNING_SUCCESS) { + LOG_DBG("Tuning Completed success"); + } else { + LOG_ERR("Tuning failed"); + return -EIO; + } + } + return 0; +} + +static int emmc_card_busy(const struct device *dev) +{ + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + + LOG_DBG(""); + + if (regs->present_state & 7u) { + return 1; + } + + return 0; +} + +static int emmc_get_host_props(const struct device *dev, struct sdhc_host_props *props) +{ + struct emmc_data *emmc = dev->data; + const struct emmc_config *config = dev->config; + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + uint64_t cap = regs->capabilities; + + LOG_DBG(""); + + memset(props, 0, sizeof(struct sdhc_host_props)); + props->f_max = config->max_bus_freq; + props->f_min = config->min_bus_freq; + props->power_delay = config->power_delay_ms; + + props->host_caps.vol_180_support = (bool)(cap & BIT(26u)); + props->host_caps.vol_300_support = (bool)(cap & BIT(25u)); + props->host_caps.vol_330_support = (bool)(bool)(cap & BIT(24u)); + props->host_caps.suspend_res_support = false; + props->host_caps.sdma_support = (bool)(cap & BIT(22u)); + props->host_caps.high_spd_support = (bool)(cap & BIT(21u)); + props->host_caps.adma_2_support = (bool)(cap & BIT(19u)); + + props->host_caps.max_blk_len = (cap >> 16u) & 0x3u; + props->host_caps.ddr50_support = (bool)(cap & BIT(34u)); + props->host_caps.sdr104_support = (bool)(cap & BIT(33u)); + props->host_caps.sdr50_support = (bool)(cap & BIT(32u)); + props->host_caps.bus_8_bit_support = true; + props->host_caps.bus_4_bit_support = true; + props->host_caps.hs200_support = (bool)config->hs200_mode; + props->host_caps.hs400_support = (bool)config->hs400_mode; + + emmc->props = *props; + + return 0; +} + +static void emmc_isr(const struct device *dev) +{ + struct emmc_data *emmc = dev->data; + volatile struct emmc_reg *regs = (struct emmc_reg *)DEVICE_MMIO_GET(dev); + + if (regs->normal_int_stat & EMMC_HOST_CMD_COMPLETE) { + regs->normal_int_stat |= EMMC_HOST_CMD_COMPLETE; + k_event_post(&emmc->irq_event, EMMC_HOST_CMD_COMPLETE); + } + + if (regs->normal_int_stat & EMMC_HOST_XFER_COMPLETE) { + regs->normal_int_stat |= EMMC_HOST_XFER_COMPLETE; + k_event_post(&emmc->irq_event, EMMC_HOST_XFER_COMPLETE); + } + + if (regs->normal_int_stat & EMMC_HOST_DMA_INTR) { + regs->normal_int_stat |= EMMC_HOST_DMA_INTR; + k_event_post(&emmc->irq_event, EMMC_HOST_DMA_INTR); + } + + if (regs->normal_int_stat & EMMC_HOST_BUF_WR_READY) { + regs->normal_int_stat |= EMMC_HOST_BUF_WR_READY; + k_event_post(&emmc->irq_event, EMMC_HOST_BUF_WR_READY); + } + + if (regs->normal_int_stat & EMMC_HOST_BUF_RD_READY) { + regs->normal_int_stat |= EMMC_HOST_BUF_RD_READY; + k_event_post(&emmc->irq_event, EMMC_HOST_BUF_RD_READY); + } + + if (regs->err_int_stat) { + LOG_ERR("err int:%x", regs->err_int_stat); + k_event_post(&emmc->irq_event, ERR_INTR_STATUS_EVENT(regs->err_int_stat)); + if (regs->err_int_stat & EMMC_HOST_DMA_TXFR_ERR) { + regs->err_int_stat |= EMMC_HOST_DMA_TXFR_ERR; + } else { + regs->err_int_stat |= regs->err_int_stat; + } + } + + if (regs->normal_int_stat) { + k_event_post(&emmc->irq_event, regs->normal_int_stat); + regs->normal_int_stat |= regs->normal_int_stat; + } + + if (regs->adma_err_stat) { + LOG_ERR("adma err:%x", regs->adma_err_stat); + } +} + +static int emmc_init(const struct device *dev) +{ + struct emmc_data *emmc = dev->data; + const struct emmc_config *config = dev->config; + + k_sem_init(&emmc->lock, 1, 1); + k_event_init(&emmc->irq_event); + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(pcie) + if (config->pcie) { + struct pcie_bar mbar; + + if (config->pcie->bdf == PCIE_BDF_NONE) { + LOG_ERR("Cannot probe eMMC PCI device: %x", config->pcie->id); + return -ENODEV; + } + + if (!pcie_probe_mbar(config->pcie->bdf, 0, &mbar)) { + LOG_ERR("eMMC MBAR not found"); + return -EINVAL; + } + + pcie_get_mbar(config->pcie->bdf, 0, &mbar); + pcie_set_cmd(config->pcie->bdf, PCIE_CONF_CMDSTAT_MEM, true); + device_map(DEVICE_MMIO_RAM_PTR(dev), mbar.phys_addr, mbar.size, K_MEM_CACHE_NONE); + pcie_set_cmd(config->pcie->bdf, PCIE_CONF_CMDSTAT_MASTER, true); + } else +#endif + { + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); + } + + LOG_DBG("MMC Device MMIO: %p", (void *)(struct emmc_reg *)DEVICE_MMIO_GET(dev)); + + if (IS_ENABLED(CONFIG_INTEL_EMMC_HOST_INTR)) { + config->config_func(dev); + } + return emmc_reset(dev); +} + +static const struct sdhc_driver_api emmc_api = { + .reset = emmc_reset, + .request = emmc_request, + .set_io = emmc_set_io, + .get_card_present = emmc_get_card_present, + .execute_tuning = emmc_execute_tuning, + .card_busy = emmc_card_busy, + .get_host_props = emmc_get_host_props, +}; + +#define EMMC_HOST_IRQ_FLAGS_SENSE0(n) 0 +#define EMMC_HOST_IRQ_FLAGS_SENSE1(n) DT_INST_IRQ(n, sense) +#define EMMC_HOST_IRQ_FLAGS(n)\ + _CONCAT(EMMC_HOST_IRQ_FLAGS_SENSE, DT_INST_IRQ_HAS_CELL(n, sense))(n) + +/* Not PCI(e) */ +#define EMMC_HOST_IRQ_CONFIG_PCIE0(n) \ + static void emmc_config_##n(const struct device *port) \ + { \ + ARG_UNUSED(port); \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), emmc_isr, \ + DEVICE_DT_INST_GET(n), EMMC_HOST_IRQ_FLAGS(n)); \ + irq_enable(DT_INST_IRQN(n)); \ + } + +/* PCI(e) with auto IRQ detection */ +#define EMMC_HOST_IRQ_CONFIG_PCIE1(n) \ + static void emmc_config_##n(const struct device *port) \ + { \ + BUILD_ASSERT(DT_INST_IRQN(n) == PCIE_IRQ_DETECT, \ + "Only runtime IRQ configuration is supported"); \ + BUILD_ASSERT(IS_ENABLED(CONFIG_DYNAMIC_INTERRUPTS), \ + "eMMC PCI device needs CONFIG_DYNAMIC_INTERRUPTS"); \ + const struct emmc_config *const dev_cfg = port->config; \ + unsigned int irq = pcie_alloc_irq(dev_cfg->pcie->bdf); \ + \ + if (irq == PCIE_CONF_INTR_IRQ_NONE) { \ + return; \ + } \ + pcie_connect_dynamic_irq(dev_cfg->pcie->bdf, irq, DT_INST_IRQ(n, priority), \ + (void (*)(const void *))emmc_isr, DEVICE_DT_INST_GET(n), \ + EMMC_HOST_IRQ_FLAGS(n)); \ + pcie_irq_enable(dev_cfg->pcie->bdf, irq); \ + } + +#define EMMC_HOST_IRQ_CONFIG(n) _CONCAT(EMMC_HOST_IRQ_CONFIG_PCIE, DT_INST_ON_BUS(n, pcie))(n) + +#define INIT_PCIE0(n) +#define INIT_PCIE1(n) DEVICE_PCIE_INST_INIT(n, pcie), +#define INIT_PCIE(n) _CONCAT(INIT_PCIE, DT_INST_ON_BUS(n, pcie))(n) + +#define REG_INIT_PCIE0(n) DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), +#define REG_INIT_PCIE1(n) +#define REG_INIT(n) _CONCAT(REG_INIT_PCIE, DT_INST_ON_BUS(n, pcie))(n) + +#define DEFINE_PCIE0(n) +#define DEFINE_PCIE1(n) DEVICE_PCIE_INST_DECLARE(n) +#define EMMC_HOST_PCIE_DEFINE(n) _CONCAT(DEFINE_PCIE, DT_INST_ON_BUS(n, pcie))(n) + +#define EMMC_HOST_DEV_CFG(n) \ + EMMC_HOST_PCIE_DEFINE(n); \ + EMMC_HOST_IRQ_CONFIG(n); \ + static const struct emmc_config emmc_config_data_##n = { \ + REG_INIT(n) INIT_PCIE(n).config_func = emmc_config_##n, \ + .hs200_mode = DT_INST_PROP_OR(n, mmc_hs200_1_8v, 0), \ + .hs400_mode = DT_INST_PROP_OR(n, mmc_hs400_1_8v, 0), \ + .dw_4bit = DT_INST_ENUM_HAS_VALUE(n, bus_width, 4), \ + .dw_8bit = DT_INST_ENUM_HAS_VALUE(n, bus_width, 8), \ + .max_bus_freq = DT_INST_PROP_OR(n, max_bus_freq, 40000), \ + .min_bus_freq = DT_INST_PROP_OR(n, min_bus_freq, 40000), \ + .power_delay_ms = DT_INST_PROP_OR(n, power_delay_ms, 500), \ + }; \ + \ + static struct emmc_data emmc_priv_data_##n; \ + \ + DEVICE_DT_INST_DEFINE(n, emmc_init, NULL, &emmc_priv_data_##n, &emmc_config_data_##n, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &emmc_api); + +DT_INST_FOREACH_STATUS_OKAY(EMMC_HOST_DEV_CFG) diff --git a/drivers/sdhc/intel_emmc_host.h b/drivers/sdhc/intel_emmc_host.h new file mode 100644 index 00000000000..7ae87359594 --- /dev/null +++ b/drivers/sdhc/intel_emmc_host.h @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_DISK_EMMC_HOST_H_ +#define ZEPHYR_DRIVERS_DISK_EMMC_HOST_H_ + +/* Bit map for command Register */ +#define EMMC_HOST_CMD_RESP_TYPE_LOC 0 +#define EMMC_HOST_CMD_CRC_CHECK_EN_LOC 3 +#define EMMC_HOST_CMD_IDX_CHECK_EN_LOC 4 +#define EMMC_HOST_CMD_DATA_PRESENT_LOC 5 +#define EMMC_HOST_CMD_TYPE_LOC 6 +#define EMMC_HOST_CMD_INDEX_LOC 8 + +/* Bit map for Transfer Mode Register */ +#define EMMC_HOST_XFER_DMA_EN_LOC 0 +#define EMMC_HOST_XFER_BLOCK_CNT_EN_LOC 1 +#define EMMC_HOST_XFER_AUTO_CMD_EN_LOC 2 +#define EMMC_HOST_XFER_DATA_DIR_LOC 4 +#define EMMC_HOST_XFER_MULTI_BLOCK_SEL_LOC 5 + +#define EMMC_HOST_XFER_DMA_EN_MASK 0x01 +#define EMMC_HOST_XFER_BLOCK_CNT_EN_MASK 0x01 +#define EMMC_HOST_XFER_AUTO_CMD_EN_MASK 0x03 +#define EMMC_HOST_XFER_DATA_DIR_MASK 0x01 +#define EMMC_HOST_XFER_MULTI_BLOCK_SEL_MASK 0x01 + +/* Bit map for Block Size and GAP Register */ +#define EMMC_HOST_BLOCK_SIZE_LOC 0 +#define EMMC_HOST_BLOCK_SIZE_MASK 0xFFF +#define EMMC_HOST_DMA_BUF_SIZE_LOC 12 +#define EMMC_HOST_DMA_BUF_SIZE_MASK 0x07 +#define EMMC_HOST_BLOCK_GAP_LOC 3 +#define EMMC_HOST_BLOCK_GAP_MASK 0x01 + +#define EMMC_HOST_ADMA_BUFF_ADD_LOC 32 +#define EMMC_HOST_ADMA_BUFF_LEN_LOC 16 +#define EMMC_HOST_ADMA_BUFF_LINK_NEXT (0x3 << 4) +#define EMMC_HOST_ADMA_BUFF_LINK_LAST (0x2 << 4) +#define EMMC_HOST_ADMA_INTR_EN BIT(2) +#define EMMC_HOST_ADMA_BUFF_LAST BIT(1) +#define EMMC_HOST_ADMA_BUFF_VALID BIT(0) + +/* Bit Map and length details for Clock Control Register */ +#define EMMC_HOST_CLK_SDCLCK_FREQ_SEL_LOC 8 +#define EMMC_HOST_CLK_SDCLCK_FREQ_SEL_UPPER_LOC 6 + +#define EMMC_HOST_CLK_SDCLCK_FREQ_SEL_MASK 0xFF +#define EMMC_HOST_CLK_SDCLCK_FREQ_SEL_UPPER_MASK 0x03 + +/* Bit Map for Host Control 1 Register */ +#define EMMC_HOST_CTRL1_DAT_WIDTH_LOC 1 +#define EMMC_HOST_CTRL1_DMA_SEL_LOC 3 +#define EMMC_HOST_CTRL1_EXT_DAT_WIDTH_LOC 5 + +#define EMMC_HOST_CTRL1_DMA_SEL_MASK 0x03 +#define EMMC_HOST_CTRL1_EXT_DAT_WIDTH_MASK 0x01 +#define EMMC_HOST_CTRL1_DAT_WIDTH_MASK 0x01 + +/** Constants Software Reset register */ +#define EMMC_HOST_SW_RESET_REG_ALL BIT(0) +#define EMMC_HOST_SW_RESET_REG_CMD BIT(1) +#define EMMC_HOST_SW_RESET_REG_DATA BIT(2) + +#define EMMC_HOST_RESPONSE_SIZE 4 +#define EMMC_HOST_OCR_BUSY_BIT BIT(31) +#define EMMC_HOST_OCR_CAPACITY_MASK 0x40000000U +#define EMMC_HOST_DUAL_VOLTAGE_RANGE 0x40FF8080U +#define EMMC_HOST_BLOCK_SIZE 512 + +#define EMMC_HOST_RCA_SHIFT 16 +#define EMMC_HOST_EXTCSD_SEC_COUNT 53 +#define EMMC_HOST_EXTCSD_GENERIC_CMD6_TIME 62 +#define EMMC_HOST_EXTCSD_BUS_WIDTH_ADDR 0xB7 +#define EMMC_HOST_EXTCSD_HS_TIMING_ADDR 0xB9 +#define EMMC_HOST_BUS_SPEED_HIGHSPEED 1 + +#define EMMC_HOST_CMD_COMPLETE_RETRY 10000 +#define EMMC_HOST_XFR_COMPLETE_RETRY 2000000 + +#define EMMC_HOST_CMD1_RETRY_TIMEOUT 1000 +#define EMMC_HOST_CMD6_TIMEOUT_MULT 10 + +#define EMMC_HOST_NORMAL_INTR_MASK 0x3f +#define EMMC_HOST_ERROR_INTR_MASK 0x13ff +#define EMMC_HOST_NORMAL_INTR_MASK_CLR 0x60ff + +#define EMMC_HOST_POWER_CTRL_SD_BUS_POWER 0x1 +#define EMMC_HOST_POWER_CTRL_SD_BUS_VOLT_SEL 0x5 + +#define EMMC_HOST_UHSMODE_SDR12 0x0 +#define EMMC_HOST_UHSMODE_SDR25 0x1 +#define EMMC_HOST_UHSMODE_SDR50 0x2 +#define EMMC_HOST_UHSMODE_SDR104 0x3 +#define EMMC_HOST_UHSMODE_DDR50 0x4 +#define EMMC_HOST_UHSMODE_HS400 0x5 + +#define EMMC_HOST_CTRL2_1P8V_SIG_EN 1 +#define EMMC_HOST_CTRL2_1P8V_SIG_LOC 3 +#define EMMC_HOST_CTRL2_UHS_MODE_SEL_LOC 0 +#define EMMC_HOST_CTRL2_UHS_MODE_SEL_MASK 0x07 + +/* Event/command status */ +#define EMMC_HOST_CMD_COMPLETE BIT(0) +#define EMMC_HOST_XFER_COMPLETE BIT(1) +#define EMMC_HOST_BLOCK_GAP_INTR BIT(2) +#define EMMC_HOST_DMA_INTR BIT(3) +#define EMMC_HOST_BUF_WR_READY BIT(4) +#define EMMC_HOST_BUF_RD_READY BIT(5) + +#define EMMC_HOST_CMD_TIMEOUT_ERR BIT(0) +#define EMMC_HOST_CMD_CRC_ERR BIT(1) +#define EMMC_HOST_CMD_END_BIT_ERR BIT(2) +#define EMMC_HOST_CMD_IDX_ERR BIT(3) +#define EMMC_HOST_DATA_TIMEOUT_ERR BIT(4) +#define EMMC_HOST_DATA_CRC_ERR BIT(5) +#define EMMC_HOST_DATA_END_BIT_ERR BIT(6) +#define EMMC_HOST_CUR_LMT_ERR BIT(7) +#define EMMC_HOST_DMA_TXFR_ERR BIT(12) +#define EMMC_HOST_ERR_STATUS 0xFFF + +/** PState register bits */ +#define EMMC_HOST_PSTATE_CMD_INHIBIT BIT(0) +#define EMMC_HOST_PSTATE_DAT_INHIBIT BIT(1) +#define EMMC_HOST_PSTATE_DAT_LINE_ACTIVE BIT(2) + +#define EMMC_HOST_PSTATE_WR_DMA_ACTIVE BIT(8) +#define EMMC_HOST_PSTATE_RD_DMA_ACTIVE BIT(9) + +#define EMMC_HOST_PSTATE_BUF_READ_EN BIT(11) +#define EMMC_HOST_PSTATE_BUF_WRITE_EN BIT(10) + +#define EMMC_HOST_PSTATE_CARD_INSERTED BIT(16) + +#define EMMC_HOST_MAX_TIMEOUT 0xe +#define EMMC_HOST_MSEC_DELAY 1000 + +/** Constants for Clock Control register */ +#define EMMC_HOST_INTERNAL_CLOCK_EN BIT(0) +#define EMMC_HOST_INTERNAL_CLOCK_STABLE BIT(1) +#define EMMC_HOST_SD_CLOCK_EN BIT(2) + +/** Clock frequency */ +#define EMMC_HOST_CLK_FREQ_400K 0.4 +#define EMMC_HOST_CLK_FREQ_25M 25 +#define EMMC_HOST_CLK_FREQ_50M 50 +#define EMMC_HOST_CLK_FREQ_100M 100 +#define EMMC_HOST_CLK_FREQ_200M 200 + +#define EMMC_HOST_TUNING_SUCCESS BIT(7) +#define EMMC_HOST_START_TUNING BIT(6) + +#define EMMC_HOST_VOL_3_3_V_SUPPORT BIT(24) +#define EMMC_HOST_VOL_3_3_V_SELECT (7 << 1) +#define EMMC_HOST_VOL_3_0_V_SUPPORT BIT(25) +#define EMMC_HOST_VOL_3_0_V_SELECT (6 << 1) +#define EMMC_HOST_VOL_1_8_V_SUPPORT BIT(26) +#define EMMC_HOST_VOL_1_8_V_SELECT (5 << 1) + +#define EMMC_HOST_CMD_WAIT_TIMEOUT_US 3000 +#define EMMC_HOST_CMD_CMPLETE_TIMEOUT_US 9000 +#define EMMC_HOST_XFR_CMPLETE_TIMEOUT_US 1000 +#define EMMC_HOST_SDMA_BOUNDARY 0x0 +#define EMMC_HOST_RCA_ADDRESS 0x2 + +#define EMMC_HOST_RESP_MASK (0xFF000000U) + +#define EMMC_HOST_SET_RESP(resp0, resp1) (resp0 >> 1) | ((resp1 & 1) << 30) + +#define SET_BITS(reg, pos, bit_width, val) \ + reg &= ~(bit_width << pos); \ + reg |= ((val & bit_width) << pos) + +/* get value from certain bit + */ +#define GET_BITS(reg_name, start, width) ((reg_name) & (((1 << (width)) - 1) << (start))) + +#define ERR_INTR_STATUS_EVENT(reg_bits) reg_bits << 16 + +#define ADDRESS_32BIT_MASK 0xFFFFFFFF + +struct emmc_reg { + volatile uint32_t sdma_sysaddr; /**< SDMA System Address */ + volatile uint16_t block_size; /**< Block Size */ + volatile uint16_t block_count; /**< Block Count */ + volatile uint32_t argument; /**< Argument */ + volatile uint16_t transfer_mode; /**< Transfer Mode */ + volatile uint16_t cmd; /**< Command */ + + volatile uint32_t resp_01; /**< Response Register 0 & 1 */ + volatile uint16_t resp_2; /**< Response Register 2*/ + volatile uint16_t resp_3; /**< Response Register 3 */ + volatile uint16_t resp_4; /**< Response Register 4 */ + volatile uint16_t resp_5; /**< Response Register 5 */ + volatile uint16_t resp_6; /**< Response Register 6 */ + volatile uint16_t resp_7; /**< Response Register 7 */ + volatile uint32_t data_port; /**< Buffer Data Port */ + volatile uint32_t present_state; /**< Present State */ + volatile uint8_t host_ctrl1; /**< Host Control 1 */ + volatile uint8_t power_ctrl; /**< Power Control */ + volatile uint8_t block_gap_ctrl; /**< Block Gap Control */ + volatile uint8_t wake_up_ctrl; /**< Wakeup Control */ + volatile uint16_t clock_ctrl; /**< Clock Control */ + volatile uint8_t timeout_ctrl; /**< Timeout Control */ + volatile uint8_t sw_reset; /**< Software Reset */ + volatile uint16_t normal_int_stat; /**< Normal Interrupt Status */ + volatile uint16_t err_int_stat; /**< Error Interrupt Status */ + volatile uint16_t normal_int_stat_en; /**< Normal Interrupt Status Enable */ + volatile uint16_t err_int_stat_en; /**< Error Interrupt Status Enable */ + volatile uint16_t normal_int_signal_en; /**< Normal Interrupt Signal Enable */ + volatile uint16_t err_int_signal_en; /**< Error Interrupt Signal Enable */ + volatile uint16_t auto_cmd_err_stat; /**< Auto CMD Error Status */ + volatile uint16_t host_ctrl2; /**< Host Control 2 */ + volatile uint64_t capabilities; /**< Capabilities */ + + volatile uint64_t max_current_cap; /**< Max Current Capabilities */ + volatile uint16_t force_err_autocmd_stat; /**< Force Event for Auto CMD Error Status*/ + volatile uint16_t force_err_int_stat; /**< Force Event for Error Interrupt Status */ + volatile uint8_t adma_err_stat; /**< ADMA Error Status */ + volatile uint8_t reserved[3]; + volatile uint32_t adma_sys_addr1; /**< ADMA System Address1 */ + volatile uint32_t adma_sys_addr2; /**< ADMA System Address2 */ + volatile uint16_t preset_val_0; /**< Preset Value 0 */ + volatile uint16_t preset_val_1; /**< Preset Value 1 */ + volatile uint16_t preset_val_2; /**< Preset Value 2 */ + volatile uint16_t preset_val_3; /**< Preset Value 3 */ + volatile uint16_t preset_val_4; /**< Preset Value 4 */ + volatile uint16_t preset_val_5; /**< Preset Value 5 */ + volatile uint16_t preset_val_6; /**< Preset Value 6 */ + volatile uint16_t preset_val_7; /**< Preset Value 7 */ + volatile uint32_t boot_timeout; /**< Boot Timeout */ + volatile uint16_t preset_val_8; /**< Preset Value 8 */ + volatile uint16_t reserved3; + volatile uint16_t vendor_reg; /**< Vendor Enhanced strobe */ + volatile uint16_t reserved4[56]; + volatile uint32_t reserved5[4]; + volatile uint16_t slot_intr_stat; /**< Slot Interrupt Status */ + volatile uint16_t host_cntrl_version; /**< Host Controller Version */ + volatile uint32_t reserved6[64]; + volatile uint32_t cq_ver; /**< Command Queue Version */ + volatile uint32_t cq_cap; /**< Command Queue Capabilities */ + volatile uint32_t cq_cfg; /**< Command Queue Configuration */ + volatile uint32_t cq_ctrl; /**< Command Queue Control */ + volatile uint32_t cq_intr_stat; /**< Command Queue Interrupt Status */ + volatile uint32_t cq_intr_stat_en; /**< Command Queue Interrupt Status Enable */ + volatile uint32_t cq_intr_sig_en; /**< Command Queue Interrupt Signal Enable */ + volatile uint32_t cq_intr_coalesc; /**< Command Queue Interrupt Coalescing */ + volatile uint32_t cq_tdlba; /**< Command Queue Task Desc List Base Addr */ + volatile uint32_t cq_tdlba_upr; /**< Command Queue Task Desc List Base Addr Upr */ + volatile uint32_t cq_task_db; /**< Command Queue Task DoorBell */ + volatile uint32_t cq_task_db_notify; /**< Command Queue Task DoorBell Notify */ + volatile uint32_t cq_dev_qstat; /**< Command Queue Device queue status */ + volatile uint32_t cq_dev_pend_task; /**< Command Queue Device pending tasks */ + volatile uint32_t cq_task_clr; /**< Command Queue Task Clr */ + volatile uint32_t reserved7; + volatile uint32_t cq_ssc1; /**< Command Queue Send Status Configuration 1 */ + volatile uint32_t cq_ssc2; /**< Command Queue Send Status Configuration 2 */ + volatile uint32_t cq_crdct; /**< Command response for direct command */ + volatile uint32_t reserved8; + volatile uint32_t cq_rmem; /**< Command response mode error mask */ + volatile uint32_t cq_terri; /**< Command Queue Task Error Information */ + volatile uint32_t cq_cri; /**< Command Queue Command response index */ + volatile uint32_t cq_cra; /**< Command Queue Command response argument */ + volatile uint32_t reserved9[425]; +}; + +enum emmc_sw_reset { + EMMC_HOST_SW_RESET_DATA_LINE = 0, + EMMC_HOST_SW_RESET_CMD_LINE, + EMMC_HOST_SW_RESET_ALL +}; + +enum emmc_cmd_type { + EMMC_HOST_CMD_NORMAL = 0, + EMMC_HOST_CMD_SUSPEND, + EMMC_HOST_CMD_RESUME, + EMMC_HOST_CMD_ABORT, +}; + +enum emmc_response_type { + EMMC_HOST_RESP_NONE = 0, + EMMC_HOST_RESP_LEN_136, + EMMC_HOST_RESP_LEN_48, + EMMC_HOST_RESP_LEN_48B, + EMMC_HOST_INVAL_HOST_RESP_LEN, +}; + +struct emmc_cmd_config { + struct sdhc_command *sdhc_cmd; + uint32_t cmd_idx; + enum emmc_cmd_type cmd_type; + bool data_present; + bool idx_check_en; + bool crc_check_en; +}; + +struct resp { + uint64_t resp_48bit; +}; +#endif /* _EMMC_HOST_HC_H_ */ diff --git a/drivers/sdhc/sam_hsmci.c b/drivers/sdhc/sam_hsmci.c new file mode 100644 index 00000000000..b7c3d3b8783 --- /dev/null +++ b/drivers/sdhc/sam_hsmci.c @@ -0,0 +1,683 @@ +/* + * Copyright 2023 Nikhef + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT atmel_sam_hsmci + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(hsmci, CONFIG_SDHC_LOG_LEVEL); + +#ifdef HSMCI_MR_PDCMODE +#ifdef CONFIG_SAM_HSMCI_PDCMODE +#define _HSMCI_PDCMODE +#endif +#endif + +#ifdef CONFIG_SAM_HSMCI_PWRSAVE +#if (CONFIG_SAM_HSMCI_PWRSAVE_DIV < 0) || (CONFIG_SAM_HSMCI_PWRSAVE_DIV > 7) +#error "CONFIG_SAM_HSMCI_PWRSAVE_DIV must be 0 to 7" +#endif +#endif + +#define _HSMCI_DEFAULT_TIMEOUT 5000 +#define _HSMCI_MAX_FREQ (SOC_ATMEL_SAM_MCK_FREQ_HZ >> 1) +#define _HSMCI_MIN_FREQ (_HSMCI_MAX_FREQ / 0x200) +#define _MSMCI_MAX_DIVISOR 0x1FF +#define _HSMCI_SR_ERR (HSMCI_SR_RINDE \ + | HSMCI_SR_RDIRE \ + | HSMCI_SR_RCRCE \ + | HSMCI_SR_RENDE \ + | HSMCI_SR_RTOE \ + | HSMCI_SR_DCRCE \ + | HSMCI_SR_DTOE \ + | HSMCI_SR_CSTOE \ + | HSMCI_SR_OVRE \ + | HSMCI_SR_UNRE) + +static const uint8_t _resp2size[] = { + [SD_RSP_TYPE_NONE] = HSMCI_CMDR_RSPTYP_NORESP, + [SD_RSP_TYPE_R1] = HSMCI_CMDR_RSPTYP_48_BIT, + [SD_RSP_TYPE_R1b] = HSMCI_CMDR_RSPTYP_R1B, + [SD_RSP_TYPE_R2] = HSMCI_CMDR_RSPTYP_136_BIT, + [SD_RSP_TYPE_R3] = HSMCI_CMDR_RSPTYP_48_BIT, + [SD_RSP_TYPE_R4] = HSMCI_CMDR_RSPTYP_48_BIT, + [SD_RSP_TYPE_R5] = 0 /* SDIO not supported */, + [SD_RSP_TYPE_R5b] = 0 /* SDIO not supported */, + [SD_RSP_TYPE_R6] = HSMCI_CMDR_RSPTYP_48_BIT, + [SD_RSP_TYPE_R7] = HSMCI_CMDR_RSPTYP_48_BIT, +}; + +/* timeout multiplier shift (actual value is 1 << _mul_shift[*]) */ +static const uint8_t _mul_shift[] = {0, 4, 7, 8, 10, 12, 16, 20}; +static const uint8_t _mul_shift_size = 8; + +struct sam_hsmci_config { + Hsmci *base; + const struct atmel_sam_pmc_config clock_cfg; + const struct pinctrl_dev_config *pincfg; + struct gpio_dt_spec carrier_detect; +}; + +struct sam_hsmci_data { + bool open_drain; + uint8_t cmd_in_progress; + struct k_mutex mtx; +}; + +static int sam_hsmci_reset(const struct device *dev) +{ + const struct sam_hsmci_config *config = dev->config; + Hsmci *hsmci = config->base; + + uint32_t mr = hsmci->HSMCI_MR; + uint32_t dtor = hsmci->HSMCI_DTOR; + uint32_t sdcr = hsmci->HSMCI_SDCR; + uint32_t cstor = hsmci->HSMCI_CSTOR; + uint32_t cfg = hsmci->HSMCI_CFG; + + hsmci->HSMCI_CR = HSMCI_CR_SWRST; + hsmci->HSMCI_MR = mr; + hsmci->HSMCI_DTOR = dtor; + hsmci->HSMCI_SDCR = sdcr; + hsmci->HSMCI_CSTOR = cstor; + hsmci->HSMCI_CFG = cfg; + + hsmci->HSMCI_CR = HSMCI_CR_PWSEN | HSMCI_CR_MCIEN; + return 0; +} + +static int sam_hsmci_get_host_props(const struct device *dev, struct sdhc_host_props *props) +{ + memset(props, 0, sizeof(*props)); + + props->f_max = _HSMCI_MAX_FREQ; + props->f_min = _HSMCI_MIN_FREQ; + /* high-speed not working yet due to limitations of the SDHC sm */ + props->host_caps.high_spd_support = false; + props->power_delay = 500; + props->is_spi = false; + props->max_current_330 = 4; + + return 0; +} + +static int sam_hsmci_set_io(const struct device *dev, struct sdhc_io *ios) +{ + const struct sam_hsmci_config *config = dev->config; + struct sam_hsmci_data *data = dev->data; + Hsmci *hsmci = config->base; + uint32_t frequency; + uint32_t div_val; + int ret; + + LOG_DBG("%s(clock=%d, bus_width=%d, timing=%d, mode=%d)", __func__, ios->clock, + ios->bus_width, ios->timing, ios->bus_mode); + + if (ios->clock > 0) { + if (ios->clock > _HSMCI_MAX_FREQ) { + return -ENOTSUP; + } + + ret = clock_control_get_rate(SAM_DT_PMC_CONTROLLER, + (clock_control_subsys_t)&config->clock_cfg, + &frequency); + + if (ret < 0) { + LOG_ERR("Failed to get clock rate, err=%d", ret); + return ret; + } + + div_val = frequency / ios->clock - 2; + + if (div_val < 0) { + div_val = 0; + } + + if (div_val > _MSMCI_MAX_DIVISOR) { + div_val = _MSMCI_MAX_DIVISOR; + } + + LOG_DBG("divider: %d (freq=%d)", div_val, frequency / (div_val + 2)); + + hsmci->HSMCI_MR &= ~HSMCI_MR_CLKDIV_Msk; + hsmci->HSMCI_MR |= + ((div_val & 1) ? HSMCI_MR_CLKODD : 0) | HSMCI_MR_CLKDIV(div_val >> 1); + } + + if (ios->bus_width) { + hsmci->HSMCI_SDCR &= ~HSMCI_SDCR_SDCBUS_Msk; + + switch (ios->bus_width) { + case SDHC_BUS_WIDTH1BIT: + hsmci->HSMCI_SDCR = HSMCI_SDCR_SDCBUS_1; + break; + case SDHC_BUS_WIDTH4BIT: + hsmci->HSMCI_SDCR = HSMCI_SDCR_SDCBUS_4; + break; + default: + return -ENOTSUP; + } + } + + data->open_drain = (ios->bus_mode == SDHC_BUSMODE_OPENDRAIN); + + if (ios->timing) { + switch (ios->timing) { + case SDHC_TIMING_LEGACY: + hsmci->HSMCI_CFG &= ~HSMCI_CFG_HSMODE; + break; + case SDHC_TIMING_HS: + hsmci->HSMCI_CFG |= HSMCI_CFG_HSMODE; + break; + default: + return -ENOTSUP; + } + } + + return 0; +} + +static int sam_hsmci_init(const struct device *dev) +{ + const struct sam_hsmci_config *config = dev->config; + int ret; + + /* Connect pins to the peripheral */ + ret = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + LOG_ERR("pinctrl_apply_state() => %d", ret); + return ret; + } + /* Enable module's clock */ + (void)clock_control_on(SAM_DT_PMC_CONTROLLER, (clock_control_subsys_t)&config->clock_cfg); + + /* init carrier detect (if set) */ + if (config->carrier_detect.port != NULL) { + if (!gpio_is_ready_dt(&config->carrier_detect)) { + LOG_ERR("GPIO port for carrier-detect pin is not ready"); + return -ENODEV; + } + ret = gpio_pin_configure_dt(&config->carrier_detect, GPIO_INPUT); + if (ret < 0) { + LOG_ERR("Couldn't configure carrier-detect pin; (%d)", ret); + return ret; + } + } + + Hsmci *hsmci = config->base; + + /* reset the device */ + hsmci->HSMCI_CR = HSMCI_CR_SWRST; + hsmci->HSMCI_CR = HSMCI_CR_PWSDIS; + hsmci->HSMCI_CR = HSMCI_CR_MCIEN; +#ifdef CONFIG_SAM_HSMCI_PWRSAVE + hsmci->HSMCI_MR = + HSMCI_MR_RDPROOF | HSMCI_MR_WRPROOF | HSMCI_MR_PWSDIV(CONFIG_SAM_HSMCI_PWRSAVE_DIV); + hsmci->HSMCI_CR = HSMCI_CR_PWSEN; +#else + hsmci->HSMCI_MR = HSMCI_MR_RDPROOF | HSMCI_MR_WRPROOF; +#endif + + return 0; +} + +static int sam_hsmci_get_card_present(const struct device *dev) +{ + const struct sam_hsmci_config *config = dev->config; + + if (config->carrier_detect.port == NULL) { + return 1; + } + + return gpio_pin_get_dt(&config->carrier_detect); +} + +static int sam_hsmci_card_busy(const struct device *dev) +{ + const struct sam_hsmci_config *config = dev->config; + Hsmci *hsmci = config->base; + + return (hsmci->HSMCI_SR & HSMCI_SR_NOTBUSY) == 0; +} + +static void sam_hsmci_send_clocks(Hsmci *hsmci) +{ + hsmci->HSMCI_MR &= ~(HSMCI_MR_WRPROOF | HSMCI_MR_RDPROOF | HSMCI_MR_FBYTE); + hsmci->HSMCI_ARGR = 0; + hsmci->HSMCI_CMDR = + HSMCI_CMDR_RSPTYP_NORESP | HSMCI_CMDR_SPCMD_INIT | HSMCI_CMDR_OPDCMD_OPENDRAIN; + while (!(hsmci->HSMCI_SR & HSMCI_SR_CMDRDY)) { + ; + } + hsmci->HSMCI_MR |= HSMCI_MR_WRPROOF | HSMCI_MR_RDPROOF; +} + +static int sam_hsmci_send_cmd(Hsmci *hsmci, struct sdhc_command *cmd, uint32_t cmdr, + struct sam_hsmci_data *data) +{ + uint32_t sr; + + hsmci->HSMCI_ARGR = cmd->arg; + + cmdr |= HSMCI_CMDR_CMDNB(cmd->opcode) | HSMCI_CMDR_MAXLAT_64; + if (data->open_drain) { + cmdr |= HSMCI_CMDR_OPDCMD_OPENDRAIN; + } + + uint8_t nrt = cmd->response_type & SDHC_NATIVE_RESPONSE_MASK; + + if (nrt > SD_RSP_TYPE_R7) { + return -ENOTSUP; + } + + cmdr |= _resp2size[nrt]; + hsmci->HSMCI_CMDR = cmdr; + do { + sr = hsmci->HSMCI_SR; + + /* special case ,ignore CRC status if response is R3 to clear it */ + if (nrt == SD_RSP_TYPE_R3 || nrt == SD_RSP_TYPE_NONE) { + sr &= ~HSMCI_SR_RCRCE; + } + + if ((sr & _HSMCI_SR_ERR) != 0) { + LOG_DBG("Status register error bits: %08x", sr & _HSMCI_SR_ERR); + return -EIO; + } + } while (!(sr & HSMCI_SR_CMDRDY)); + + if (nrt == SD_RSP_TYPE_R1b) { + do { + sr = hsmci->HSMCI_SR; + } while (!((sr & HSMCI_SR_NOTBUSY) && ((sr & HSMCI_SR_DTIP) == 0))); + } + + /* RSPR is just a FIFO, index is of no consequence */ + cmd->response[3] = hsmci->HSMCI_RSPR[0]; + cmd->response[2] = hsmci->HSMCI_RSPR[0]; + cmd->response[1] = hsmci->HSMCI_RSPR[0]; + cmd->response[0] = hsmci->HSMCI_RSPR[0]; + return 0; +} + +static int sam_hsmci_wait_write_end(Hsmci *hsmci) +{ + uint32_t sr = 0; + +#ifdef _HSMCI_PDCMODE + /* Timeout is included in HSMCI, see DTOE bit, not required explicitly. */ + do { + sr = hsmci->HSMCI_SR; + if (sr & (HSMCI_SR_UNRE | HSMCI_SR_OVRE | HSMCI_SR_DTOE | HSMCI_SR_DCRCE)) { + LOG_DBG("PDC sr 0x%08x error", sr); + return -EIO; + } + } while (!(sr & HSMCI_SR_TXBUFE)); +#endif + + do { + sr = hsmci->HSMCI_SR; + if (sr & (HSMCI_SR_UNRE | HSMCI_SR_OVRE | HSMCI_SR_DTOE | HSMCI_SR_DCRCE)) { + LOG_DBG("PDC sr 0x%08x last transfer error", sr); + return -EIO; + } + } while (!(sr & HSMCI_SR_NOTBUSY)); + + if (!(hsmci->HSMCI_SR & HSMCI_SR_FIFOEMPTY)) { + return -EIO; + } + return 0; +} + +static int sam_hsmci_wait_read_end(Hsmci *hsmci) +{ + uint32_t sr; + +#ifdef _HSMCI_PDCMODE + do { + sr = hsmci->HSMCI_SR; + if (sr & (HSMCI_SR_UNRE | HSMCI_SR_OVRE | HSMCI_SR_DTOE | HSMCI_SR_DCRCE)) { + LOG_DBG("PDC sr 0x%08x error", sr & (HSMCI_SR_UNRE | HSMCI_SR_OVRE | + HSMCI_SR_DTOE | HSMCI_SR_DCRCE)); + return -EIO; + } + } while (!(sr & HSMCI_SR_RXBUFF)); +#endif + + do { + sr = hsmci->HSMCI_SR; + if (sr & (HSMCI_SR_UNRE | HSMCI_SR_OVRE | HSMCI_SR_DTOE | HSMCI_SR_DCRCE)) { + return -EIO; + } + } while (!(sr & HSMCI_SR_XFRDONE)); + return 0; +} + +static int sam_hsmci_write_timeout(Hsmci *hsmci, int timeout_ms) +{ + /* convert to clocks (coarsely) */ + int clocks = ATMEL_SAM_DT_CPU_CLK_FREQ_HZ / 1000 * timeout_ms; + int mul, max_clock; + + for (int i = 0; i < _mul_shift_size; i++) { + mul = 1 << _mul_shift[i]; + max_clock = 15 * mul; + if (max_clock > clocks) { + hsmci->HSMCI_DTOR = ((i << HSMCI_DTOR_DTOMUL_Pos) & HSMCI_DTOR_DTOMUL_Msk) | + HSMCI_DTOR_DTOCYC((clocks + mul - 1) / mul); + return 0; + } + } + /* + * So, if it is > maximum timeout... we'll just put it on the maximum the driver supports + * its not nice.. but it should work.. what else is there to do? + */ + hsmci->HSMCI_DTOR = HSMCI_DTOR_DTOMUL_Msk | HSMCI_DTOR_DTOCYC_Msk; + return 0; +} + +static inline int wait_write_transfer_done(Hsmci *hsmci) +{ + int sr; + + do { + sr = hsmci->HSMCI_SR; + if (sr & (HSMCI_SR_UNRE | HSMCI_SR_OVRE | HSMCI_SR_DTOE | HSMCI_SR_DCRCE)) { + return -EIO; + } + } while (!(sr & HSMCI_SR_TXRDY)); + return 0; +} + +static inline int wait_read_transfer_done(Hsmci *hsmci) +{ + int sr; + + do { + sr = HSMCI->HSMCI_SR; + if (sr & (HSMCI_SR_UNRE | HSMCI_SR_OVRE | HSMCI_SR_DTOE | HSMCI_SR_DCRCE)) { + return -EIO; + } + } while (!(sr & HSMCI_SR_RXRDY)); + return 0; +} + +#ifndef _HSMCI_PDCMODE + +static int hsmci_do_manual_transfer(Hsmci *hsmci, bool byte_mode, bool is_write, void *data, + int transfer_count) +{ + int ret; + + if (is_write) { + if (byte_mode) { + const uint8_t *ptr = data; + + while (transfer_count-- > 0) { + ret = wait_write_transfer_done(hsmci); + if (ret != 0) { + return ret; + } + hsmci->HSMCI_TDR = *ptr; + ptr++; + } + } else { + const uint32_t *ptr = data; + + while (transfer_count-- > 0) { + ret = wait_write_transfer_done(hsmci); + if (ret != 0) { + return ret; + } + hsmci->HSMCI_TDR = *ptr; + ptr++; + } + } + ret = sam_hsmci_wait_write_end(hsmci); + } else { + if (byte_mode) { + uint8_t *ptr = data; + + while (transfer_count-- > 0) { + ret = wait_read_transfer_done(hsmci); + if (ret != 0) { + return ret; + } + *ptr = hsmci->HSMCI_RDR; + ptr++; + } + } else { + uint32_t *ptr = data; + + while (transfer_count-- > 0) { + ret = wait_read_transfer_done(hsmci); + if (ret != 0) { + return ret; + } + *ptr = hsmci->HSMCI_RDR; + ptr++; + } + } + ret = sam_hsmci_wait_read_end(hsmci); + } + return ret; +} + +#endif /* !_HSMCI_PDCMODE */ + +static int sam_hsmci_request_inner(const struct device *dev, struct sdhc_command *cmd, + struct sdhc_data *sd_data) +{ + const struct sam_hsmci_config *config = dev->config; + struct sam_hsmci_data *data = dev->data; + Hsmci *hsmci = config->base; + uint32_t sr; + uint32_t size; + uint32_t transfer_count; + uint32_t cmdr = 0; + int ret; + bool is_write, byte_mode; + + LOG_DBG("%s(opcode=%d, arg=%08x, data=%08x, rsptype=%d)", __func__, cmd->opcode, cmd->arg, + (uint32_t)sd_data, cmd->response_type & SDHC_NATIVE_RESPONSE_MASK); + + if (cmd->opcode == SD_GO_IDLE_STATE) { + /* send 74 clocks, as required by SD spec */ + sam_hsmci_send_clocks(hsmci); + } + + if (sd_data) { + cmdr |= HSMCI_CMDR_TRCMD_START_DATA; + + ret = sam_hsmci_write_timeout(hsmci, cmd->timeout_ms); + if (ret != 0) { + return ret; + } + + switch (cmd->opcode) { + case SD_WRITE_SINGLE_BLOCK: + cmdr |= HSMCI_CMDR_TRTYP_SINGLE; + cmdr |= HSMCI_CMDR_TRDIR_WRITE; + is_write = true; + break; + case SD_WRITE_MULTIPLE_BLOCK: + is_write = true; + cmdr |= HSMCI_CMDR_TRTYP_MULTIPLE; + cmdr |= HSMCI_CMDR_TRDIR_WRITE; + break; + case SD_APP_SEND_SCR: + case SD_SWITCH: + case SD_READ_SINGLE_BLOCK: + is_write = false; + cmdr |= HSMCI_CMDR_TRTYP_SINGLE; + cmdr |= HSMCI_CMDR_TRDIR_READ; + break; + case SD_READ_MULTIPLE_BLOCK: + is_write = false; + cmdr |= HSMCI_CMDR_TRTYP_MULTIPLE; + cmdr |= HSMCI_CMDR_TRDIR_READ; + break; + case SD_APP_SEND_NUM_WRITTEN_BLK: + is_write = false; + break; + default: + return -ENOTSUP; + } + + if ((sd_data->block_size & 0x3) == 0 && (((uint32_t)sd_data->data) & 0x3) == 0) { + size = (sd_data->block_size + 3) >> 2; + hsmci->HSMCI_MR &= ~HSMCI_MR_FBYTE; + byte_mode = true; + } else { + size = sd_data->block_size; + hsmci->HSMCI_MR |= HSMCI_MR_FBYTE; + byte_mode = false; + } + + hsmci->HSMCI_BLKR = + HSMCI_BLKR_BLKLEN(sd_data->block_size) | HSMCI_BLKR_BCNT(sd_data->blocks); + + transfer_count = size * sd_data->blocks; + +#ifdef _HSMCI_PDCMODE + hsmci->HSMCI_MR |= HSMCI_MR_PDCMODE; + + hsmci->HSMCI_RNCR = 0; + + if (is_write) { + hsmci->HSMCI_TCR = transfer_count; + hsmci->HSMCI_TPR = (uint32_t)sd_data->data; + } else { + hsmci->HSMCI_RCR = transfer_count; + hsmci->HSMCI_RPR = (uint32_t)sd_data->data; + hsmci->HSMCI_PTCR = HSMCI_PTCR_RXTEN; + } + + } else { + hsmci->HSMCI_MR &= ~HSMCI_MR_PDCMODE; +#endif /* _HSMCI_PDCMODE */ + } + + ret = sam_hsmci_send_cmd(hsmci, cmd, cmdr, data); + + if (sd_data) { +#ifdef _HSMCI_PDCMODE + if (ret == 0) { + if (is_write) { + hsmci->HSMCI_PTCR = HSMCI_PTCR_TXTEN; + ret = sam_hsmci_wait_write_end(hsmci); + } else { + ret = sam_hsmci_wait_read_end(hsmci); + } + } + hsmci->HSMCI_PTCR = HSMCI_PTCR_TXTDIS | HSMCI_PTCR_RXTDIS; + hsmci->HSMCI_MR &= ~HSMCI_MR_PDCMODE; +#else /* !_HSMCI_PDCMODE */ + if (ret == 0) { + ret = hsmci_do_manual_transfer(hsmci, byte_mode, is_write, sd_data->data, + transfer_count); + } +#endif /* _HSMCI_PDCMODE */ + } + + sr = hsmci->HSMCI_SR; + + LOG_DBG("RSP0=%08x, RPS1=%08x, RPS2=%08x,RSP3=%08x, SR=%08x", cmd->response[0], + cmd->response[1], cmd->response[2], cmd->response[3], sr); + + return ret; +} + +static void sam_hsmci_abort(const struct device *dev) +{ +#ifdef _HSMCI_PDCMODE + const struct sam_hsmci_config *config = dev->config; + Hsmci *hsmci = config->base; + + hsmci->HSMCI_PTCR = HSMCI_PTCR_RXTDIS | HSMCI_PTCR_TXTDIS; +#endif /* _HSMCI_PDCMODE */ + + struct sdhc_command cmd = { + .opcode = SD_STOP_TRANSMISSION, .arg = 0, .response_type = SD_RSP_TYPE_NONE}; + sam_hsmci_request_inner(dev, &cmd, NULL); +} + +static int sam_hsmci_request(const struct device *dev, struct sdhc_command *cmd, + struct sdhc_data *sd_data) +{ + struct sam_hsmci_data *dev_data = dev->data; + int busy_timeout = _HSMCI_DEFAULT_TIMEOUT; + int ret; + + ret = k_mutex_lock(&dev_data->mtx, K_MSEC(cmd->timeout_ms)); + if (ret) { + LOG_ERR("Could not access card"); + return -EBUSY; + } + +#ifdef CONFIG_SAM_HSMCI_PWRSAVE + const struct sam_hsmci_config *config = dev->config; + Hsmci *hsmci = config->base; + + hsmci->HSMCI_CR = HSMCI_CR_PWSDIS; +#endif /* CONFIG_SAM_HSMCI_PWRSAVE */ + + do { + ret = sam_hsmci_request_inner(dev, cmd, sd_data); + if (sd_data && (ret || sd_data->blocks > 1)) { + sam_hsmci_abort(dev); + while (busy_timeout > 0) { + if (!sam_hsmci_card_busy(dev)) { + break; + } + k_busy_wait(125); + busy_timeout -= 125; + } + if (busy_timeout <= 0) { + LOG_ERR("Card did not idle after CMD12"); + ret = -ETIMEDOUT; + } + } + } while (ret != 0 && (cmd->retries-- > 0)); + +#ifdef CONFIG_SAM_HSMCI_PWRSAVE + hsmci->HSMCI_CR = HSMCI_CR_PWSEN; +#endif /* CONFIG_SAM_HSMCI_PWRSAVE */ + + k_mutex_unlock(&dev_data->mtx); + + return ret; +} + +static const struct sdhc_driver_api hsmci_api = { + .reset = sam_hsmci_reset, + .get_host_props = sam_hsmci_get_host_props, + .set_io = sam_hsmci_set_io, + .get_card_present = sam_hsmci_get_card_present, + .request = sam_hsmci_request, + .card_busy = sam_hsmci_card_busy, +}; + +#define SAM_HSMCI_INIT(N) \ + PINCTRL_DT_INST_DEFINE(N); \ + static const struct sam_hsmci_config hsmci_##N##_config = { \ + .base = (Hsmci *)DT_INST_REG_ADDR(N), \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(N), \ + .clock_cfg = SAM_DT_INST_CLOCK_PMC_CFG(N), \ + .carrier_detect = GPIO_DT_SPEC_INST_GET_OR(N, cd_gpios, {0})}; \ + static struct sam_hsmci_data hsmci_##N##_data = {}; \ + DEVICE_DT_INST_DEFINE(N, &sam_hsmci_init, NULL, &hsmci_##N##_data, &hsmci_##N##_config, \ + POST_KERNEL, CONFIG_SDHC_INIT_PRIORITY, &hsmci_api); + +DT_INST_FOREACH_STATUS_OKAY(SAM_HSMCI_INIT) diff --git a/drivers/sensor/CMakeLists.txt b/drivers/sensor/CMakeLists.txt index 5839ea12e97..2fa37289ac2 100644 --- a/drivers/sensor/CMakeLists.txt +++ b/drivers/sensor/CMakeLists.txt @@ -2,13 +2,16 @@ add_subdirectory_ifdef(CONFIG_A01NYUB a01nyub) add_subdirectory_ifdef(CONFIG_ADC_CMP_NPCX nuvoton_adc_cmp_npcx) +add_subdirectory_ifdef(CONFIG_ADLTC2990 adltc2990) add_subdirectory_ifdef(CONFIG_ADT7310 adt7310) add_subdirectory_ifdef(CONFIG_ADT7420 adt7420) add_subdirectory_ifdef(CONFIG_ADXL345 adxl345) add_subdirectory_ifdef(CONFIG_ADXL362 adxl362) +add_subdirectory_ifdef(CONFIG_ADXL367 adxl367) add_subdirectory_ifdef(CONFIG_ADXL372 adxl372) add_subdirectory_ifdef(CONFIG_AK8975 ak8975) add_subdirectory_ifdef(CONFIG_AKM09918C akm09918c) +add_subdirectory_ifdef(CONFIG_AMD_SB_TSI amd_sb_tsi) add_subdirectory_ifdef(CONFIG_AMG88XX amg88xx) add_subdirectory_ifdef(CONFIG_AMS_AS5600 ams_as5600) add_subdirectory_ifdef(CONFIG_AMS_IAQ_CORE ams_iAQcore) @@ -27,19 +30,24 @@ add_subdirectory_ifdef(CONFIG_BMM150 bmm150) add_subdirectory_ifdef(CONFIG_BMP388 bmp388) add_subdirectory_ifdef(CONFIG_BQ274XX bq274xx) add_subdirectory_ifdef(CONFIG_CCS811 ccs811) +add_subdirectory_ifdef(CONFIG_CURRENT_AMP current_amp) add_subdirectory_ifdef(CONFIG_DHT dht) add_subdirectory_ifdef(CONFIG_DPS310 dps310) add_subdirectory_ifdef(CONFIG_DS18B20 ds18b20) add_subdirectory_ifdef(CONFIG_ENS210 ens210) add_subdirectory_ifdef(CONFIG_ESP32_TEMP esp32_temp) +add_subdirectory_ifdef(CONFIG_EXPLORIR_M explorir_m) +add_subdirectory_ifdef(CONFIG_F75303 f75303) add_subdirectory_ifdef(CONFIG_FDC2X1X fdc2x1x) add_subdirectory_ifdef(CONFIG_FXAS21002 fxas21002) add_subdirectory_ifdef(CONFIG_FXOS8700 fxos8700) add_subdirectory_ifdef(CONFIG_GROVE_SENSORS grove) add_subdirectory_ifdef(CONFIG_GROW_R502A grow_r502a) add_subdirectory_ifdef(CONFIG_HAS_STMEMSC stmemsc) +add_subdirectory_ifdef(CONFIG_HM330X hm330x) add_subdirectory_ifdef(CONFIG_HMC5883L hmc5883l) add_subdirectory_ifdef(CONFIG_HP206C hp206c) +add_subdirectory_ifdef(CONFIG_HS300X hs300x) add_subdirectory_ifdef(CONFIG_HTS221 hts221) add_subdirectory_ifdef(CONFIG_I3G4250D i3g4250d) add_subdirectory_ifdef(CONFIG_ICM42605 icm42605) @@ -65,6 +73,7 @@ add_subdirectory_ifdef(CONFIG_LIS2MDL lis2mdl) add_subdirectory_ifdef(CONFIG_LIS3MDL lis3mdl) add_subdirectory_ifdef(CONFIG_LM75 lm75) add_subdirectory_ifdef(CONFIG_LM77 lm77) +add_subdirectory_ifdef(CONFIG_LPS22DF lps22df) add_subdirectory_ifdef(CONFIG_LPS22HB lps22hb) add_subdirectory_ifdef(CONFIG_LPS22HH lps22hh) add_subdirectory_ifdef(CONFIG_LPS25HB lps25hb) @@ -76,6 +85,7 @@ add_subdirectory_ifdef(CONFIG_LSM6DSO16IS lsm6dso16is) add_subdirectory_ifdef(CONFIG_LSM6DSV16X lsm6dsv16x) add_subdirectory_ifdef(CONFIG_LSM9DS0_GYRO lsm9ds0_gyro) add_subdirectory_ifdef(CONFIG_LSM9DS0_MFD lsm9ds0_mfd) +add_subdirectory_ifdef(CONFIG_LTR_F216A ltrf216a) add_subdirectory_ifdef(CONFIG_MAX17055 max17055) add_subdirectory_ifdef(CONFIG_MAX17262 max17262) add_subdirectory_ifdef(CONFIG_MAX30101 max30101) @@ -84,6 +94,7 @@ add_subdirectory_ifdef(CONFIG_MAX31865 max31865) add_subdirectory_ifdef(CONFIG_MAX31875 max31875) add_subdirectory_ifdef(CONFIG_MAX44009 max44009) add_subdirectory_ifdef(CONFIG_MAX6675 max6675) +add_subdirectory_ifdef(CONFIG_MC3419 mc3419) add_subdirectory_ifdef(CONFIG_MCP9600 mcp9600) add_subdirectory_ifdef(CONFIG_MCP970X mcp970x) add_subdirectory_ifdef(CONFIG_MCP9808 mcp9808) @@ -131,16 +142,20 @@ add_subdirectory_ifdef(CONFIG_TEMP_NRF5 nrf5) add_subdirectory_ifdef(CONFIG_TH02 th02) add_subdirectory_ifdef(CONFIG_TI_HDC ti_hdc) add_subdirectory_ifdef(CONFIG_TI_HDC20XX ti_hdc20xx) +add_subdirectory_ifdef(CONFIG_TMAG5170 tmag5170) add_subdirectory_ifdef(CONFIG_TMD2620 tmd2620) add_subdirectory_ifdef(CONFIG_TMP007 tmp007) add_subdirectory_ifdef(CONFIG_TMP108 tmp108) add_subdirectory_ifdef(CONFIG_TMP112 tmp112) add_subdirectory_ifdef(CONFIG_TMP116 tmp116) +add_subdirectory_ifdef(CONFIG_TSL2540 tsl2540) +add_subdirectory_ifdef(CONFIG_TSL2561 tsl2561) add_subdirectory_ifdef(CONFIG_VCMP_IT8XXX2 ite_vcmp_it8xxx2) add_subdirectory_ifdef(CONFIG_VCNL4040 vcnl4040) add_subdirectory_ifdef(CONFIG_VEML7700 veml7700) add_subdirectory_ifdef(CONFIG_VL53L0X vl53l0x) add_subdirectory_ifdef(CONFIG_VL53L1X vl53l1x) +add_subdirectory_ifdef(CONFIG_VOLTAGE_DIVIDER voltage_divider) add_subdirectory_ifdef(CONFIG_WSEN_HIDS wsen_hids) add_subdirectory_ifdef(CONFIG_WSEN_PADS wsen_pads) add_subdirectory_ifdef(CONFIG_WSEN_PDUS wsen_pdus) @@ -154,5 +169,6 @@ zephyr_library_property(ALLOW_EMPTY TRUE) zephyr_library_sources_ifdef(CONFIG_USERSPACE sensor_handlers.c) zephyr_library_sources_ifdef(CONFIG_SENSOR_SHELL sensor_shell.c) +zephyr_library_sources_ifdef(CONFIG_SENSOR_SHELL_STREAM sensor_shell_stream.c) zephyr_library_sources_ifdef(CONFIG_SENSOR_SHELL_BATTERY shell_battery.c) zephyr_library_sources_ifdef(CONFIG_SENSOR_ASYNC_API sensor_decoders_init.c default_rtio_sensor.c) diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index 8311b4b4bf4..08d04774dcd 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -32,10 +32,26 @@ config SENSOR_SHELL depends on SHELL select CBPRINTF_FP_SUPPORT select SENSOR_ASYNC_API - default y if !SHELL_MINIMAL help This shell provides access to basic sensor data. +config SENSOR_SHELL_STREAM + bool "Sensor shell 'stream' command" + depends on SENSOR_SHELL + help + Add the 'stream' subcommand to the sensor shell. When run on drivers that + support streaming (usually hardware FIFO backed), the shell will continue + to print new values as they come until the stream is closed. + +config SENSOR_SHELL_THREAD_STACK_SIZE + int "Stack size for the sensor shell data processing thread" + depends on SENSOR_SHELL_STREAM + default 1024 + help + The sensor shell uses a dedicated thread to process data coming from the + sensors in either one-shot or streaming mode. Use this config to control + the size of that thread's stack. + config SENSOR_SHELL_BATTERY bool "Sensor shell 'battery' command" depends on SHELL @@ -58,13 +74,16 @@ config SENSOR_INFO comment "Device Drivers" source "drivers/sensor/a01nyub/Kconfig" +source "drivers/sensor/adltc2990/Kconfig" source "drivers/sensor/adt7310/Kconfig" source "drivers/sensor/adt7420/Kconfig" source "drivers/sensor/adxl345/Kconfig" source "drivers/sensor/adxl362/Kconfig" +source "drivers/sensor/adxl367/Kconfig" source "drivers/sensor/adxl372/Kconfig" source "drivers/sensor/ak8975/Kconfig" source "drivers/sensor/akm09918c/Kconfig" +source "drivers/sensor/amd_sb_tsi/Kconfig" source "drivers/sensor/amg88xx/Kconfig" source "drivers/sensor/ams_as5600/Kconfig" source "drivers/sensor/ams_iAQcore/Kconfig" @@ -83,18 +102,23 @@ source "drivers/sensor/bmm150/Kconfig" source "drivers/sensor/bmp388/Kconfig" source "drivers/sensor/bq274xx/Kconfig" source "drivers/sensor/ccs811/Kconfig" +source "drivers/sensor/current_amp/Kconfig" source "drivers/sensor/dht/Kconfig" source "drivers/sensor/dps310/Kconfig" source "drivers/sensor/ds18b20/Kconfig" source "drivers/sensor/ens210/Kconfig" source "drivers/sensor/esp32_temp/Kconfig" +source "drivers/sensor/explorir_m/Kconfig" +source "drivers/sensor/f75303/Kconfig" source "drivers/sensor/fdc2x1x/Kconfig" source "drivers/sensor/fxas21002/Kconfig" source "drivers/sensor/fxos8700/Kconfig" source "drivers/sensor/grove/Kconfig" source "drivers/sensor/grow_r502a/Kconfig" +source "drivers/sensor/hm330x/Kconfig" source "drivers/sensor/hmc5883l/Kconfig" source "drivers/sensor/hp206c/Kconfig" +source "drivers/sensor/hs300x/Kconfig" source "drivers/sensor/hts221/Kconfig" source "drivers/sensor/i3g4250d/Kconfig" source "drivers/sensor/icm42605/Kconfig" @@ -121,6 +145,7 @@ source "drivers/sensor/lis2mdl/Kconfig" source "drivers/sensor/lis3mdl/Kconfig" source "drivers/sensor/lm75/Kconfig" source "drivers/sensor/lm77/Kconfig" +source "drivers/sensor/lps22df/Kconfig" source "drivers/sensor/lps22hb/Kconfig" source "drivers/sensor/lps22hh/Kconfig" source "drivers/sensor/lps25hb/Kconfig" @@ -132,6 +157,7 @@ source "drivers/sensor/lsm6dso16is/Kconfig" source "drivers/sensor/lsm6dsv16x/Kconfig" source "drivers/sensor/lsm9ds0_gyro/Kconfig" source "drivers/sensor/lsm9ds0_mfd/Kconfig" +source "drivers/sensor/ltrf216a/Kconfig" source "drivers/sensor/max17055/Kconfig" source "drivers/sensor/max17262/Kconfig" source "drivers/sensor/max30101/Kconfig" @@ -140,6 +166,7 @@ source "drivers/sensor/max31865/Kconfig" source "drivers/sensor/max31875/Kconfig" source "drivers/sensor/max44009/Kconfig" source "drivers/sensor/max6675/Kconfig" +source "drivers/sensor/mc3419/Kconfig" source "drivers/sensor/mchp_tach_xec/Kconfig" source "drivers/sensor/mcp9600/Kconfig" source "drivers/sensor/mcp970x/Kconfig" @@ -187,15 +214,19 @@ source "drivers/sensor/tcs3400/Kconfig" source "drivers/sensor/th02/Kconfig" source "drivers/sensor/ti_hdc/Kconfig" source "drivers/sensor/ti_hdc20xx/Kconfig" +source "drivers/sensor/tmag5170/Kconfig" source "drivers/sensor/tmd2620/Kconfig" source "drivers/sensor/tmp007/Kconfig" source "drivers/sensor/tmp108/Kconfig" source "drivers/sensor/tmp112/Kconfig" source "drivers/sensor/tmp116/Kconfig" +source "drivers/sensor/tsl2540/Kconfig" +source "drivers/sensor/tsl2561/Kconfig" source "drivers/sensor/vcnl4040/Kconfig" source "drivers/sensor/veml7700/Kconfig" source "drivers/sensor/vl53l0x/Kconfig" source "drivers/sensor/vl53l1x/Kconfig" +source "drivers/sensor/voltage_divider/Kconfig" source "drivers/sensor/wsen_hids/Kconfig" source "drivers/sensor/wsen_itds/Kconfig" source "drivers/sensor/wsen_pads/Kconfig" diff --git a/drivers/sensor/a01nyub/Kconfig b/drivers/sensor/a01nyub/Kconfig index ff40a6f0682..5f137e0358a 100644 --- a/drivers/sensor/a01nyub/Kconfig +++ b/drivers/sensor/a01nyub/Kconfig @@ -6,5 +6,6 @@ config A01NYUB default y depends on DT_HAS_DFROBOT_A01NYUB_ENABLED depends on UART_INTERRUPT_DRIVEN + select UART_USE_RUNTIME_CONFIGURE help Enable driver for the DFRobot A01NYUB distance sensor. diff --git a/drivers/sensor/adltc2990/CMakeLists.txt b/drivers/sensor/adltc2990/CMakeLists.txt new file mode 100644 index 00000000000..d71bf940a69 --- /dev/null +++ b/drivers/sensor/adltc2990/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright(c) 2023 Carl Zeiss Meditec AG +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(adltc2990.c) +zephyr_library_sources_ifdef(CONFIG_EMUL_ADLTC2990 adltc2990_emul.c) +zephyr_include_directories_ifdef(CONFIG_EMUL_ADLTC2990 .) diff --git a/drivers/sensor/adltc2990/Kconfig b/drivers/sensor/adltc2990/Kconfig new file mode 100644 index 00000000000..75ac62b25f5 --- /dev/null +++ b/drivers/sensor/adltc2990/Kconfig @@ -0,0 +1,21 @@ +# ADLTC2990 Quad I2C Voltage, Current and Temperature sensor configuration options + +# Copyright(c) 2023 Carl Zeiss Meditec AG +# SPDX-License-Identifier: Apache-2.0 + +config ADLTC2990 + bool "ADLTC2990 Quad I2C Voltage, Current and Temperature Monitor" + default y + depends on DT_HAS_ADI_ADLTC2990_ENABLED + select I2C + help + Enable the driver for Analog Devices LTC2990 + Quad I2C Voltage, Current and Temperature Monitor. + +config EMUL_ADLTC2990 + bool "Emulator for ADLTC2990" + default y + depends on ADLTC2990 + depends on EMUL + help + Enable ADLTC2990 emulator. diff --git a/drivers/sensor/adltc2990/adltc2990.c b/drivers/sensor/adltc2990/adltc2990.c new file mode 100644 index 00000000000..d9ac1643306 --- /dev/null +++ b/drivers/sensor/adltc2990/adltc2990.c @@ -0,0 +1,471 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2023 Carl Zeiss Meditec AG + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT adi_adltc2990 + +#include +#include + +#include "adltc2990_reg.h" +#include "adltc2990.h" + +#include +LOG_MODULE_REGISTER(adltc2990, CONFIG_SENSOR_LOG_LEVEL); + +static enum adltc2990_monitoring_type adltc2990_get_v1_v2_measurement_modes(uint8_t mode_4_3, + uint8_t mode_2_0) +{ + if (mode_2_0 > ADLTC2990_MODE_2_0_MAX_VALUE || mode_4_3 > ADLTC2990_MODE_4_3_MAX_VALUE) { + LOG_ERR("Invalid Measurement Mode"); + return -EINVAL; + } + if (mode_4_3 == ADLTC2990_MEASURE_INTERNAL_TEMPERATURE_ONLY || + mode_4_3 == ADLTC2990_MEASURE_PINS_V3_V4_ONLY) { + return NOTHING; + } + + enum adltc2990_monitoring_type type = NOTHING; + + switch (mode_2_0) { + case ADLTC2990_MODE_V1_V2_TR2: + case ADLTC2990_MODE_V1_V2_V3_V4: { + type = VOLTAGE_SINGLEENDED; + break; + } + case ADLTC2990_MODE_V1_MINUS_V2_TR2: + case ADLTC2990_MODE_V1_MINUS_V2_V3_V4: + case ADLTC2990_MODE_V1_MINUS_V2_V3_MINUS_V4: { + type = VOLTAGE_DIFFERENTIAL; + break; + } + case ADLTC2990_MODE_TR1_V3_V4: + case ADLTC2990_MODE_TR1_V3_MINUS_V4: { + case ADLTC2990_MODE_TR1_TR2: + type = TEMPERATURE; + break; + } + default: { + break; + } + } + return type; +} + +static enum adltc2990_monitoring_type adltc2990_get_v3_v4_measurement_modes(uint8_t mode_4_3, + uint8_t mode_2_0) +{ + if (mode_2_0 > ADLTC2990_MODE_2_0_MAX_VALUE || mode_4_3 > ADLTC2990_MODE_4_3_MAX_VALUE) { + LOG_ERR("Invalid Measurement Mode"); + return -EINVAL; + } + if (mode_4_3 == ADLTC2990_MEASURE_INTERNAL_TEMPERATURE_ONLY || + mode_4_3 == ADLTC2990_MEASURE_PINS_V1_V2_ONLY) { + return NOTHING; + } + + enum adltc2990_monitoring_type type = NOTHING; + + switch (mode_2_0) { + case ADLTC2990_MODE_V1_V2_TR2: + case ADLTC2990_MODE_V1_MINUS_V2_TR2: + case ADLTC2990_MODE_TR1_TR2: { + type = TEMPERATURE; + break; + } + + case ADLTC2990_MODE_V1_MINUS_V2_V3_V4: + case ADLTC2990_MODE_TR1_V3_V4: + case ADLTC2990_MODE_V1_V2_V3_V4: { + type = VOLTAGE_SINGLEENDED; + break; + } + case ADLTC2990_MODE_TR1_V3_MINUS_V4: + case ADLTC2990_MODE_V1_MINUS_V2_V3_MINUS_V4: { + type = VOLTAGE_DIFFERENTIAL; + break; + } + default: { + break; + } + } + return type; +} + +static bool adltc2990_is_busy(const struct device *dev) +{ + const struct adltc2990_config *cfg = dev->config; + uint8_t status_reg = 0; + + i2c_reg_read_byte_dt(&cfg->bus, ADLTC2990_REG_STATUS, &status_reg); + return status_reg & BIT(0); +} + +static void adltc2990_get_v1_v2_val(const struct device *dev, struct sensor_value *val, + uint8_t num_values, uint8_t *const offset_index) +{ + struct adltc2990_data *data = dev->data; + + for (uint8_t index = 0; index < num_values; index++) { + val[index].val1 = data->pins_v1_v2_values[index] / 1000000; + val[index].val2 = data->pins_v1_v2_values[index] % 1000000; + *offset_index = index + 1; + } +} + +static void adltc2990_get_v3_v4_val(const struct device *dev, struct sensor_value *val, + uint8_t num_values, uint8_t const *const offset) +{ + struct adltc2990_data *data = dev->data; + + uint8_t offset_index = *offset; + + for (uint8_t index = 0; index < num_values; index++) { + val[index + offset_index].val1 = data->pins_v3_v4_values[index] / 1000000; + val[index + offset_index].val2 = data->pins_v3_v4_values[index] % 1000000; + } +} + +static int adltc2990_trigger_measurement(const struct device *dev) +{ + const struct adltc2990_config *cfg = dev->config; + + return i2c_reg_write_byte_dt(&cfg->bus, ADLTC2990_REG_TRIGGER, 0x1); +} + +static int32_t adltc2990_fetch_property_value(const struct device *dev, + enum adltc2990_monitoring_type type, + enum adltc2990_monitor_pins pin) +{ + const struct adltc2990_config *cfg = dev->config; + + uint8_t msb_value = 0, lsb_value = 0; + uint8_t msb_address, lsb_address; + + switch (pin) { + case V1: { + msb_address = ADLTC2990_REG_V1_MSB; + lsb_address = ADLTC2990_REG_V1_LSB; + break; + } + case V2: { + msb_address = ADLTC2990_REG_V2_MSB; + lsb_address = ADLTC2990_REG_V2_LSB; + break; + } + case V3: { + msb_address = ADLTC2990_REG_V3_MSB; + lsb_address = ADLTC2990_REG_V3_LSB; + break; + } + case V4: { + msb_address = ADLTC2990_REG_V4_MSB; + lsb_address = ADLTC2990_REG_V4_LSB; + break; + } + case INTERNAL_TEMPERATURE: { + msb_address = ADLTC2990_REG_INTERNAL_TEMP_MSB; + lsb_address = ADLTC2990_REG_INTERNAL_TEMP_LSB; + break; + } + case SUPPLY_VOLTAGE: { + msb_address = ADLTC2990_REG_VCC_MSB; + lsb_address = ADLTC2990_REG_VCC_LSB; + break; + } + default: { + LOG_ERR("Trying to access illegal register"); + return -EINVAL; + } + } + + i2c_reg_read_byte_dt(&cfg->bus, msb_address, &msb_value); + i2c_reg_read_byte_dt(&cfg->bus, lsb_address, &lsb_value); + uint16_t conversion_factor; + uint8_t negative_bit_index = 14U, sensor_val_divisor = 100U; + + if (type == VOLTAGE_SINGLEENDED) { + conversion_factor = ADLTC2990_VOLTAGE_SINGLEENDED_CONVERSION_FACTOR; + } else if (type == VOLTAGE_DIFFERENTIAL) { + conversion_factor = ADLTC2990_VOLTAGE_DIFFERENTIAL_CONVERSION_FACTOR; + } else if (type == TEMPERATURE) { + conversion_factor = ADLTC2990_TEMPERATURE_CONVERSION_FACTOR; + if (cfg->temp_format == ADLTC2990_TEMPERATURE_FORMAT_CELSIUS) { + negative_bit_index = 12U; + } + sensor_val_divisor = 1U; + } else { + LOG_ERR("unknown type"); + return -EINVAL; + } + + int16_t value = (msb_value << 8) + lsb_value; + + int32_t voltage_value = (value << (31 - negative_bit_index)) >> (31 - negative_bit_index); + + return (voltage_value * conversion_factor) / sensor_val_divisor; +} + +static int adltc2990_init(const struct device *dev) +{ + const struct adltc2990_config *cfg = dev->config; + + if (!i2c_is_ready_dt(&cfg->bus)) { + LOG_ERR("I2C bus %s not ready", cfg->bus.bus->name); + return -ENODEV; + } + + const uint8_t ctrl_reg_setting = cfg->temp_format << 7 | cfg->acq_format << 6 | 0 << 5 | + cfg->measurement_mode[1] << 3 | cfg->measurement_mode[0]; + + LOG_DBG("Setting Control Register to: 0x%x", ctrl_reg_setting); + int err = i2c_reg_write_byte_dt(&cfg->bus, ADLTC2990_REG_CONTROL, ctrl_reg_setting); + + if (err < 0) { + LOG_ERR("configuring for single bus failed: %d", err); + return err; + } + LOG_INF("Initializing ADLTC2990 with name %s", dev->name); + return 0; +} + +static int adltc2990_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + struct adltc2990_data *data = dev->data; + const struct adltc2990_config *cfg = dev->config; + enum adltc2990_monitoring_type mode_v1_v2 = adltc2990_get_v1_v2_measurement_modes( + cfg->measurement_mode[1], cfg->measurement_mode[0]); + enum adltc2990_monitoring_type mode_v3_v4 = adltc2990_get_v3_v4_measurement_modes( + cfg->measurement_mode[1], cfg->measurement_mode[0]); + + float voltage_divider_ratio; + + switch (chan) { + case SENSOR_CHAN_DIE_TEMP: { + data->internal_temperature = + adltc2990_fetch_property_value(dev, TEMPERATURE, INTERNAL_TEMPERATURE); + break; + } + case SENSOR_CHAN_CURRENT: { + if (!(mode_v1_v2 == VOLTAGE_DIFFERENTIAL || mode_v3_v4 == VOLTAGE_DIFFERENTIAL)) { + LOG_ERR("Sensor is not configured to measure Current"); + return -EINVAL; + } + if (mode_v1_v2 == VOLTAGE_DIFFERENTIAL) { + data->pins_v1_v2_values[0] = + adltc2990_fetch_property_value(dev, VOLTAGE_DIFFERENTIAL, V1) * + (ADLTC2990_MICROOHM_CONVERSION_FACTOR / + (float)cfg->pins_v1_v2.pins_current_resistor); + } + if (mode_v3_v4 == VOLTAGE_DIFFERENTIAL) { + data->pins_v3_v4_values[0] = + adltc2990_fetch_property_value(dev, VOLTAGE_DIFFERENTIAL, V3) * + (ADLTC2990_MICROOHM_CONVERSION_FACTOR / + (float)cfg->pins_v3_v4.pins_current_resistor); + } + break; + } + case SENSOR_CHAN_VOLTAGE: { + data->supply_voltage = + adltc2990_fetch_property_value(dev, VOLTAGE_SINGLEENDED, SUPPLY_VOLTAGE) + + 2500000; + + if (mode_v1_v2 == VOLTAGE_DIFFERENTIAL) { + data->pins_v1_v2_values[0] = + adltc2990_fetch_property_value(dev, VOLTAGE_DIFFERENTIAL, V1); + } else if (mode_v1_v2 == VOLTAGE_SINGLEENDED) { + uint32_t v1_r1 = cfg->pins_v1_v2.voltage_divider_resistors.v1_r1_r2[0]; + + uint32_t v1_r2 = cfg->pins_v1_v2.voltage_divider_resistors.v1_r1_r2[1]; + + voltage_divider_ratio = (v1_r1 + v1_r2) / (float)v1_r2; + data->pins_v1_v2_values[0] = + adltc2990_fetch_property_value(dev, VOLTAGE_SINGLEENDED, V1) * + voltage_divider_ratio; + + uint32_t v2_r1 = cfg->pins_v1_v2.voltage_divider_resistors.v2_r1_r2[0]; + + uint32_t v2_r2 = cfg->pins_v1_v2.voltage_divider_resistors.v2_r1_r2[1]; + + voltage_divider_ratio = (v2_r1 + v2_r2) / (float)v2_r2; + data->pins_v1_v2_values[1] = + adltc2990_fetch_property_value(dev, VOLTAGE_SINGLEENDED, V2) * + voltage_divider_ratio; + } + + if (mode_v3_v4 == VOLTAGE_DIFFERENTIAL) { + data->pins_v3_v4_values[0] = + adltc2990_fetch_property_value(dev, VOLTAGE_DIFFERENTIAL, V3); + } else if (mode_v3_v4 == VOLTAGE_SINGLEENDED) { + uint32_t v3_r1 = cfg->pins_v3_v4.voltage_divider_resistors.v3_r1_r2[0]; + + uint32_t v3_r2 = cfg->pins_v3_v4.voltage_divider_resistors.v3_r1_r2[1]; + + voltage_divider_ratio = (v3_r1 + v3_r2) / (float)v3_r2; + data->pins_v3_v4_values[0] = + adltc2990_fetch_property_value(dev, VOLTAGE_SINGLEENDED, V3) * + voltage_divider_ratio; + + uint32_t v4_r1 = cfg->pins_v3_v4.voltage_divider_resistors.v4_r1_r2[0]; + + uint32_t v4_r2 = cfg->pins_v3_v4.voltage_divider_resistors.v4_r1_r2[1]; + + voltage_divider_ratio = (v4_r1 + v4_r2) / (float)v4_r2; + data->pins_v3_v4_values[1] = + adltc2990_fetch_property_value(dev, VOLTAGE_SINGLEENDED, V4) * + voltage_divider_ratio; + } + break; + } + case SENSOR_CHAN_AMBIENT_TEMP: { + if (!(mode_v1_v2 == TEMPERATURE || mode_v3_v4 == TEMPERATURE)) { + LOG_ERR("Sensor is not configured to measure Ambient Temperature"); + return -EINVAL; + } + if (mode_v1_v2 == TEMPERATURE) { + data->pins_v1_v2_values[0] = + adltc2990_fetch_property_value(dev, TEMPERATURE, V1); + } + if (mode_v3_v4 == TEMPERATURE) { + data->pins_v3_v4_values[0] = + adltc2990_fetch_property_value(dev, TEMPERATURE, V3); + } + break; + } + case SENSOR_CHAN_ALL: { + if (adltc2990_is_busy(dev)) { + LOG_INF("ADLTC2990 conversion ongoing"); + return -EBUSY; + } + adltc2990_trigger_measurement(dev); + break; + } + default: { + LOG_ERR("does not measure channel: %d", chan); + return -ENOTSUP; + } + } + + return 0; +} + +static int adltc2990_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + if (val == NULL) { + LOG_ERR("Argument of type sensor_value* cannot be null "); + return -EINVAL; + } + struct adltc2990_data *data = dev->data; + const struct adltc2990_config *cfg = dev->config; + enum adltc2990_monitoring_type mode_v1_v2 = adltc2990_get_v1_v2_measurement_modes( + cfg->measurement_mode[1], cfg->measurement_mode[0]); + enum adltc2990_monitoring_type mode_v3_v4 = adltc2990_get_v3_v4_measurement_modes( + cfg->measurement_mode[1], cfg->measurement_mode[0]); + + uint8_t offset_index = 0, num_values_v1_v2 = 0, num_values_v3_v4 = 0; + + switch (chan) { + case SENSOR_CHAN_DIE_TEMP: { + val->val1 = (data->internal_temperature) / 1000000; + val->val2 = (data->internal_temperature) % 1000000; + LOG_DBG("Internal Temperature Value is:%d.%d", val->val1, val->val2); + break; + } + case SENSOR_CHAN_VOLTAGE: { + if (mode_v1_v2 == VOLTAGE_SINGLEENDED) { + LOG_DBG("Getting V1,V2"); + num_values_v1_v2 = ADLTC2990_VOLTAGE_SINGLE_ENDED_VALUES; + } else if (mode_v1_v2 == VOLTAGE_DIFFERENTIAL) { + LOG_DBG("Getting V3-V4"); + num_values_v1_v2 = ADLTC2990_VOLTAGE_DIFF_VALUES; + } + if (mode_v3_v4 == VOLTAGE_SINGLEENDED) { + LOG_DBG("Getting V3,V4"); + num_values_v3_v4 = ADLTC2990_VOLTAGE_SINGLE_ENDED_VALUES; + } else if (mode_v3_v4 == VOLTAGE_DIFFERENTIAL) { + LOG_DBG("Getting V3-V4"); + num_values_v3_v4 = ADLTC2990_VOLTAGE_DIFF_VALUES; + } + /* Add VCC to the last index */ + val[num_values_v1_v2 + num_values_v3_v4].val1 = data->supply_voltage / 1000000; + val[num_values_v1_v2 + num_values_v3_v4].val2 = data->supply_voltage % 1000000; + break; + } + case SENSOR_CHAN_CURRENT: { + if (!(mode_v1_v2 == VOLTAGE_DIFFERENTIAL || mode_v3_v4 == VOLTAGE_DIFFERENTIAL)) { + LOG_ERR("Sensor is not configured to measure Current"); + return -EINVAL; + } + if (mode_v1_v2 == VOLTAGE_DIFFERENTIAL && mode_v3_v4 == VOLTAGE_DIFFERENTIAL) { + LOG_DBG("Getting I12 and I34"); + num_values_v1_v2 = ADLTC2990_CURRENT_VALUES; + num_values_v3_v4 = ADLTC2990_CURRENT_VALUES; + } else if (mode_v1_v2 == VOLTAGE_DIFFERENTIAL) { + LOG_DBG("Getting I12"); + num_values_v1_v2 = ADLTC2990_CURRENT_VALUES; + } else if (mode_v3_v4 == VOLTAGE_DIFFERENTIAL) { + LOG_DBG("Getting I34"); + num_values_v3_v4 = ADLTC2990_CURRENT_VALUES; + } + break; + } + case SENSOR_CHAN_AMBIENT_TEMP: { + if (!(mode_v1_v2 == TEMPERATURE || mode_v3_v4 == TEMPERATURE)) { + LOG_ERR("Sensor is not configured to measure Ambient Temperature"); + return -EINVAL; + } + if (mode_v1_v2 == TEMPERATURE && mode_v3_v4 == TEMPERATURE) { + LOG_DBG("Getting T12 and T34"); + num_values_v1_v2 = ADLTC2990_TEMP_VALUES; + num_values_v3_v4 = ADLTC2990_TEMP_VALUES; + } else if (mode_v1_v2 == TEMPERATURE) { + LOG_DBG("Getting T12"); + num_values_v1_v2 = ADLTC2990_TEMP_VALUES; + } else if (mode_v3_v4 == TEMPERATURE) { + LOG_DBG("Getting T34"); + num_values_v3_v4 = ADLTC2990_TEMP_VALUES; + } + break; + } + default: { + return -ENOTSUP; + } + } + + adltc2990_get_v1_v2_val(dev, val, num_values_v1_v2, &offset_index); + adltc2990_get_v3_v4_val(dev, val, num_values_v3_v4, &offset_index); + return 0; +} + +static const struct sensor_driver_api adltc2990_driver_api = { + .sample_fetch = adltc2990_sample_fetch, + .channel_get = adltc2990_channel_get, +}; + +#define ADLTC2990_DEFINE(inst) \ + static struct adltc2990_data adltc2990_data_##inst; \ + static const struct adltc2990_config adltc2990_config_##inst = { \ + .bus = I2C_DT_SPEC_INST_GET(inst), \ + .temp_format = DT_INST_PROP(inst, temperature_format), \ + .acq_format = DT_INST_PROP(inst, acquistion_format), \ + .measurement_mode = DT_INST_PROP(inst, measurement_mode), \ + .pins_v1_v2.pins_current_resistor = \ + DT_INST_PROP_OR(inst, pins_v1_v2_current_resistor, 1), \ + .pins_v1_v2.voltage_divider_resistors.v1_r1_r2 = \ + DT_INST_PROP_OR(inst, pin_v1_voltage_divider_resistors, NULL), \ + .pins_v1_v2.voltage_divider_resistors.v2_r1_r2 = \ + DT_INST_PROP_OR(inst, pin_v2_voltage_divider_resistors, NULL), \ + .pins_v3_v4.pins_current_resistor = \ + DT_INST_PROP_OR(inst, pins_v3_v4_current_resistor, 1), \ + .pins_v3_v4.voltage_divider_resistors.v3_r1_r2 = \ + DT_INST_PROP_OR(inst, pin_v3_voltage_divider_resistors, NULL), \ + .pins_v3_v4.voltage_divider_resistors.v4_r1_r2 = \ + DT_INST_PROP_OR(inst, pin_v4_voltage_divider_resistors, NULL)}; \ + \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, adltc2990_init, NULL, &adltc2990_data_##inst, \ + &adltc2990_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &adltc2990_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(ADLTC2990_DEFINE) diff --git a/drivers/sensor/adltc2990/adltc2990.h b/drivers/sensor/adltc2990/adltc2990.h new file mode 100644 index 00000000000..af2d1995531 --- /dev/null +++ b/drivers/sensor/adltc2990/adltc2990.h @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2023 Carl Zeiss Meditec AG + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_ADLTC2990_H +#define ZEPHYR_DRIVERS_SENSOR_ADLTC2990_H + +#include +#include +#include +#include +#include + +enum adltc2990_monitor_pins { + V1, + V2, + V3, + V4, + INTERNAL_TEMPERATURE, + SUPPLY_VOLTAGE +}; + +enum adltc2990_monitoring_type { + NOTHING, + VOLTAGE_DIFFERENTIAL, + VOLTAGE_SINGLEENDED, + TEMPERATURE +}; + +union voltage_divider_resistors { + struct { + uint32_t v1_r1_r2[2]; + uint32_t v2_r1_r2[2]; + }; + struct { + uint32_t v3_r1_r2[2]; + uint32_t v4_r1_r2[2]; + }; +}; + +struct pins_configuration { + uint32_t pins_current_resistor; + union voltage_divider_resistors voltage_divider_resistors; +}; + +struct adltc2990_data { + int32_t internal_temperature; + int32_t supply_voltage; + int32_t pins_v1_v2_values[2]; + int32_t pins_v3_v4_values[2]; +}; + +struct adltc2990_config { + struct i2c_dt_spec bus; + uint8_t temp_format; + uint8_t acq_format; + uint8_t measurement_mode[2]; + struct pins_configuration pins_v1_v2; + struct pins_configuration pins_v3_v4; +}; + +#endif /* ZEPHYR_DRIVERS_SENSOR_ADLTC2990_H */ diff --git a/drivers/sensor/adltc2990/adltc2990_emul.c b/drivers/sensor/adltc2990/adltc2990_emul.c new file mode 100644 index 00000000000..80078f21dc5 --- /dev/null +++ b/drivers/sensor/adltc2990/adltc2990_emul.c @@ -0,0 +1,136 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2023 Carl Zeiss Meditec AG + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT adi_adltc2990 + +#include +#include +#include +#include +#include +#include +#include + +#include "adltc2990.h" +#include "adltc2990_reg.h" +#include "adltc2990_emul.h" + +LOG_MODULE_DECLARE(adltc2990, CONFIG_SENSOR_LOG_LEVEL); + +#define ADLTC2990_NUM_REGS ADLTC2990_REG_VCC_LSB + +struct adltc2990_emul_data { + uint8_t reg[ADLTC2990_NUM_REGS]; +}; + +struct adltc2990_emul_cfg { +}; + +void adltc2990_emul_set_reg(const struct emul *target, uint8_t reg_addr, const uint8_t *val) +{ + struct adltc2990_emul_data *data = target->data; + + __ASSERT_NO_MSG(reg_addr <= ADLTC2990_NUM_REGS); + memcpy(data->reg + reg_addr, val, 1); +} + +void adltc2990_emul_get_reg(const struct emul *target, uint8_t reg_addr, uint8_t *val) +{ + struct adltc2990_emul_data *data = target->data; + + __ASSERT_NO_MSG(reg_addr <= ADLTC2990_NUM_REGS); + memcpy(val, data->reg + reg_addr, 1); +} + +void adltc2990_emul_reset(const struct emul *target) +{ + struct adltc2990_emul_data *data = target->data; + + memset(data->reg, 0, ADLTC2990_NUM_REGS); +} + +static int adltc2990_emul_handle_write(const struct emul *target, uint8_t regn, uint8_t value) +{ + struct adltc2990_emul_data *data = target->data; + + switch (regn) { + case ADLTC2990_REG_CONTROL: + data->reg[ADLTC2990_REG_CONTROL] = value; + break; + + case ADLTC2990_REG_TRIGGER: + data->reg[ADLTC2990_REG_TRIGGER] = value; + break; + + default: + break; + } + return 0; +} + +static int adltc2990_emul_transfer_i2c(const struct emul *target, struct i2c_msg *msgs, + int num_msgs, int addr) +{ + struct adltc2990_emul_data *data = target->data; + + i2c_dump_msgs_rw(target->dev, msgs, num_msgs, addr, false); + + if (num_msgs < 1) { + LOG_ERR("Invalid number of messages: %d", num_msgs); + return -EIO; + } + if (FIELD_GET(I2C_MSG_READ, msgs->flags)) { + LOG_ERR("Unexpected read"); + return -EIO; + } + if (msgs->len < 1) { + LOG_ERR("Unexpected msg0 length %d", msgs->len); + return -EIO; + } + + uint8_t regn = msgs->buf[0]; + bool is_read = FIELD_GET(I2C_MSG_READ, msgs->flags) == 1; + bool is_stop = FIELD_GET(I2C_MSG_STOP, msgs->flags) == 1; + + if (!is_stop && !is_read) { + /* First message was a write with the register number, check next message */ + msgs++; + is_read = FIELD_GET(I2C_MSG_READ, msgs->flags) == 1; + is_stop = FIELD_GET(I2C_MSG_STOP, msgs->flags) == 1; + } + + if (is_read) { + for (int i = 0; i < msgs->len; ++i) { + msgs->buf[i] = data->reg[regn + i]; + } + } else { + int rc = adltc2990_emul_handle_write(target, regn, msgs->buf[1]); + + if (rc != 0) { + return rc; + } + } + return 0; +}; + +static int adltc2990_emul_init(const struct emul *target, const struct device *parent) +{ + ARG_UNUSED(parent); + adltc2990_emul_reset(target); + + return 0; +} + +static const struct i2c_emul_api adltc2990_emul_api_i2c = { + .transfer = adltc2990_emul_transfer_i2c, +}; + +#define ADLTC2990_EMUL(n) \ + const struct adltc2990_emul_cfg adltc2990_emul_cfg_##n; \ + struct adltc2990_emul_data adltc2990_emul_data_##n; \ + EMUL_DT_INST_DEFINE(n, adltc2990_emul_init, &adltc2990_emul_data_##n, \ + &adltc2990_emul_cfg_##n, &adltc2990_emul_api_i2c, NULL) + +DT_INST_FOREACH_STATUS_OKAY(ADLTC2990_EMUL) diff --git a/drivers/sensor/adltc2990/adltc2990_emul.h b/drivers/sensor/adltc2990/adltc2990_emul.h new file mode 100644 index 00000000000..1085d7dea70 --- /dev/null +++ b/drivers/sensor/adltc2990/adltc2990_emul.h @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2023 Carl Zeiss Meditec AG + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_ADLTC2990_ADLTC2990_EMUL_H +#define ZEPHYR_DRIVERS_SENSOR_ADLTC2990_ADLTC2990_EMUL_H + +#include +#include + +void adltc2990_emul_set_reg(const struct emul *target, uint8_t reg_addr, const uint8_t *val); + +void adltc2990_emul_get_reg(const struct emul *target, uint8_t reg_addr, uint8_t *val); + +void adltc2990_emul_reset(const struct emul *target); + +#endif /* ZEPHYR_DRIVERS_SENSOR_ADLTC2990_ADLTC2990_EMUL_H */ diff --git a/drivers/sensor/adltc2990/adltc2990_reg.h b/drivers/sensor/adltc2990/adltc2990_reg.h new file mode 100644 index 00000000000..7f5a82bebac --- /dev/null +++ b/drivers/sensor/adltc2990/adltc2990_reg.h @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2023 Carl Zeiss Meditec AG + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_ADLTC2990_REG_H +#define ZEPHYR_DRIVERS_SENSOR_ADLTC2990_REG_H + +#define ADLTC2990_REG_STATUS 0x00U +#define ADLTC2990_REG_CONTROL 0x01U +#define ADLTC2990_REG_TRIGGER 0x02U +#define ADLTC2990_REG_UNUSED 0x03U +#define ADLTC2990_REG_INTERNAL_TEMP_MSB 0x04U +#define ADLTC2990_REG_INTERNAL_TEMP_LSB 0x05U +#define ADLTC2990_REG_V1_MSB 0x06U +#define ADLTC2990_REG_V1_LSB 0x07U +#define ADLTC2990_REG_V2_MSB 0x08U +#define ADLTC2990_REG_V2_LSB 0x09U +#define ADLTC2990_REG_V3_MSB 0x0AU +#define ADLTC2990_REG_V3_LSB 0x0BU +#define ADLTC2990_REG_V4_MSB 0x0CU +#define ADLTC2990_REG_V4_LSB 0x0DU +#define ADLTC2990_REG_VCC_MSB 0x0EU +#define ADLTC2990_REG_VCC_LSB 0x0FU + +#define ADLTC2990_VOLTAGE_SINGLE_ENDED_VALUES 2U +#define ADLTC2990_VOLTAGE_DIFF_VALUES 1U +#define ADLTC2990_TEMP_VALUES 1U +#define ADLTC2990_CURRENT_VALUES 1U +#define ADLTC2990_MICROOHM_CONVERSION_FACTOR 1000000U + +#define ADLTC2990_MODE_V1_V2_TR2 0U +#define ADLTC2990_MODE_V1_MINUS_V2_TR2 1U +#define ADLTC2990_MODE_V1_MINUS_V2_V3_V4 2U +#define ADLTC2990_MODE_TR1_V3_V4 3U +#define ADLTC2990_MODE_TR1_V3_MINUS_V4 4U +#define ADLTC2990_MODE_TR1_TR2 5U +#define ADLTC2990_MODE_V1_MINUS_V2_V3_MINUS_V4 6U +#define ADLTC2990_MODE_V1_V2_V3_V4 7U + +#define ADLTC2990_MEASURE_INTERNAL_TEMPERATURE_ONLY 0U +#define ADLTC2990_MEASURE_PINS_V1_V2_ONLY 1U +#define ADLTC2990_MEASURE_PINS_V3_V4_ONLY 2U +#define ADLTC2990_MEASURE_ALL_PINS_PER_MODE_2_0 3U + +#define ADLTC2990_VOLTAGE_SINGLEENDED_CONVERSION_FACTOR 30518U +#define ADLTC2990_VOLTAGE_DIFFERENTIAL_CONVERSION_FACTOR 1942U +#define ADLTC2990_TEMPERATURE_CONVERSION_FACTOR 62500U + +#define ADLTC2990_MODE_2_0_MAX_VALUE 7U +#define ADLTC2990_MODE_4_3_MAX_VALUE 3U + +#define ADLTC2990_TEMPERATURE_FORMAT_CELSIUS 0U + +#endif /* ZEPHYR_DRIVERS_SENSOR_ADLTC2990_REG_H */ diff --git a/drivers/sensor/adt7310/CMakeLists.txt b/drivers/sensor/adt7310/CMakeLists.txt index 91b77949d8b..ad7205182ed 100644 --- a/drivers/sensor/adt7310/CMakeLists.txt +++ b/drivers/sensor/adt7310/CMakeLists.txt @@ -2,5 +2,5 @@ zephyr_library() -zephyr_library_sources_ifdef(CONFIG_ADT7310 adt7310.c) +zephyr_library_sources(adt7310.c) zephyr_library_sources_ifdef(CONFIG_ADT7310_TRIGGER adt7310_trigger.c) diff --git a/drivers/sensor/adt7310/adt7310_trigger.c b/drivers/sensor/adt7310/adt7310_trigger.c index 25d264f5768..be989a69910 100644 --- a/drivers/sensor/adt7310/adt7310_trigger.c +++ b/drivers/sensor/adt7310/adt7310_trigger.c @@ -30,8 +30,13 @@ static void adt7310_gpio_callback(const struct device *dev, struct gpio_callback } #if defined(CONFIG_ADT7310_TRIGGER_OWN_THREAD) -static void adt7310_thread(struct adt7310_data *drv_data) +static void adt7310_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct adt7310_data *drv_data = p1; + while (true) { k_sem_take(&drv_data->gpio_sem, K_FOREVER); if (drv_data->th_handler != NULL) { @@ -125,7 +130,7 @@ int adt7310_init_interrupt(const struct device *dev) k_sem_init(&drv_data->gpio_sem, 0, 1); k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_ADT7310_THREAD_STACK_SIZE, - (k_thread_entry_t)adt7310_thread, drv_data, + adt7310_thread, drv_data, NULL, NULL, K_PRIO_COOP(CONFIG_ADT7310_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_ADT7310_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/adt7420/adt7420_trigger.c b/drivers/sensor/adt7420/adt7420_trigger.c index 00065eab586..1a26903adc7 100644 --- a/drivers/sensor/adt7420/adt7420_trigger.c +++ b/drivers/sensor/adt7420/adt7420_trigger.c @@ -76,8 +76,13 @@ static void adt7420_gpio_callback(const struct device *dev, } #if defined(CONFIG_ADT7420_TRIGGER_OWN_THREAD) -static void adt7420_thread(struct adt7420_data *drv_data) +static void adt7420_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct adt7420_data *drv_data = p1; + while (true) { k_sem_take(&drv_data->gpio_sem, K_FOREVER); process_int(drv_data->dev); @@ -162,7 +167,7 @@ int adt7420_init_interrupt(const struct device *dev) k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_ADT7420_THREAD_STACK_SIZE, - (k_thread_entry_t)adt7420_thread, drv_data, + adt7420_thread, drv_data, NULL, NULL, K_PRIO_COOP(CONFIG_ADT7420_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_ADT7420_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/adxl362/adxl362_trigger.c b/drivers/sensor/adxl362/adxl362_trigger.c index ba30c0a1826..341e6dad04d 100644 --- a/drivers/sensor/adxl362/adxl362_trigger.c +++ b/drivers/sensor/adxl362/adxl362_trigger.c @@ -62,8 +62,13 @@ static void adxl362_gpio_callback(const struct device *dev, } #if defined(CONFIG_ADXL362_TRIGGER_OWN_THREAD) -static void adxl362_thread(struct adxl362_data *drv_data) +static void adxl362_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct adxl362_data *drv_data = p1; + while (true) { k_sem_take(&drv_data->gpio_sem, K_FOREVER); adxl362_thread_cb(drv_data->dev); @@ -171,7 +176,7 @@ int adxl362_init_interrupt(const struct device *dev) k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_ADXL362_THREAD_STACK_SIZE, - (k_thread_entry_t)adxl362_thread, drv_data, + adxl362_thread, drv_data, NULL, NULL, K_PRIO_COOP(CONFIG_ADXL362_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_ADXL362_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/adxl367/CMakeLists.txt b/drivers/sensor/adxl367/CMakeLists.txt new file mode 100644 index 00000000000..1496eb11266 --- /dev/null +++ b/drivers/sensor/adxl367/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2023 Analog Devices Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# +zephyr_library() + +zephyr_library_sources(adxl367.c) +zephyr_library_sources(adxl367_spi.c) +zephyr_library_sources(adxl367_i2c.c) +zephyr_library_sources_ifdef(CONFIG_ADXL367_TRIGGER adxl367_trigger.c) diff --git a/drivers/sensor/adxl367/Kconfig b/drivers/sensor/adxl367/Kconfig new file mode 100644 index 00000000000..e0b4660b0f3 --- /dev/null +++ b/drivers/sensor/adxl367/Kconfig @@ -0,0 +1,133 @@ +# Micropower, 3-Axis, +/-200g Digital Accelerometer + +# Copyright (c) 2023 Analog Devices Inc. +# SPDX-License-Identifier: Apache-2.0 + +menuconfig ADXL367 + bool "ADXL367 Three Axis High-g I2C/SPI accelerometer" + default y + depends on DT_HAS_ADI_ADXL367_ENABLED + select I2C if $(dt_compat_on_bus,$(DT_COMPAT_ADI_ADXL367),i2c) + select SPI if $(dt_compat_on_bus,$(DT_COMPAT_ADI_ADXL367),spi) + help + Enable driver for ADXL367 Three-Axis Digital Accelerometers. + +if ADXL367 + +choice ADXL367_OP_MODE + prompt "Operating mode" + default ADXL367_MEASUREMENT_MODE + +config ADXL367_MEASUREMENT_MODE + bool "Measurement Mode" + help + In this mode, acceleration data is provided continuously at the + output data rate (ODR). + +endchoice + +config ADXL367_ACTIVITY_THRESHOLD + int "Activity threshold in raw value" + range 0 8191 + default 100 + help + Threshold for activity detection. + +config ADXL367_INACTIVITY_THRESHOLD + int "In-activity threshold in raw value" + range 0 8191 + default 100 + help + Threshold for in-activity detection. + +config ADXL367_ACTIVITY_TIME + int "Activity time" + range 0 255 + default 100 + help + The activity timer implements a robust activity detection that + minimizes false positive motion triggers. When the timer is used, + only sustained motion can trigger activity detection. Value is the + number of samples. For example, at 100Hz ODR, 100 value translates + to 1 second. + +config ADXL367_INACTIVITY_TIME + int "In-activity time" + range 0 65535 + default 100 + help + The time that all enabled axes must be lower than the inactivity + threshold for an inactivity event to be detected. Value is the + number of samples. For example, at 100Hz ODR, 100 value translates + to 1 second. + +config ADXL367_ACTIVITY_DETECTION_MODE + bool "Use activity detection" + default y + help + Enable Activity detection. + +config ADXL367_INACTIVITY_DETECTION_MODE + bool "Use inactivity detection" + default y + help + Enable Inactivity detection. + + +config ADXL367_REFERENCED_ACTIVITY_DETECTION_MODE + bool "Use referenced activity detection" + default y + help + Activity detection can be configured as referenced or absolute. + When using absolute activity detection, acceleration samples are + compared directly to a user set threshold to determine whether + motion is present. + +config ADXL367_REFERENCED_INACTIVITY_DETECTION_MODE + bool "Use referenced inactivity detection" + default y + help + Inactivity detection can be configured as referenced or absolute. + When using absolute inactivity detection, acceleration samples are + compared directly to a user set threshold to determine whether + motion is present. + +choice ADXL367_TRIGGER_MODE + prompt "Trigger mode" + default ADXL367_TRIGGER_NONE + help + Specify the type of triggering used by the driver. + +config ADXL367_TRIGGER_NONE + bool "No trigger" + +config ADXL367_TRIGGER_GLOBAL_THREAD + bool "Use global thread" + depends on GPIO + select ADXL367_TRIGGER + +config ADXL367_TRIGGER_OWN_THREAD + bool "Use own thread" + depends on GPIO + select ADXL367_TRIGGER + +endchoice + +config ADXL367_TRIGGER + bool + +config ADXL367_THREAD_PRIORITY + int "Thread priority" + depends on ADXL367_TRIGGER_OWN_THREAD && ADXL367_TRIGGER + default 10 + help + Priority of thread used by the driver to handle interrupts. + +config ADXL367_THREAD_STACK_SIZE + int "Thread stack size" + depends on ADXL367_TRIGGER_OWN_THREAD && ADXL367_TRIGGER + default 1024 + help + Stack size of thread used by the driver to handle interrupts. + +endif # ADXL367 diff --git a/drivers/sensor/adxl367/adxl367.c b/drivers/sensor/adxl367/adxl367.c new file mode 100644 index 00000000000..f63b8f73a32 --- /dev/null +++ b/drivers/sensor/adxl367/adxl367.c @@ -0,0 +1,1095 @@ +/* + * Copyright (c) 2023 Analog Devices Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT adi_adxl367 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "adxl367.h" + +LOG_MODULE_REGISTER(ADXL367, CONFIG_SENSOR_LOG_LEVEL); + +static const uint8_t adxl367_scale_mul[3] = {1, 2, 4}; +static uint8_t samples_per_set; + +/** + * @brief Configures activity detection. + * + * @param dev - The device structure. + * @param th - Structure holding the activity threshold information: + * Enable/Disable Activity detection + * Enable/Disable Referenced Activity detection + * Set Threshold value + * @return 0 in case of success, negative error code otherwise. + */ +static int adxl367_setup_activity_detection(const struct device *dev, + const struct adxl367_activity_threshold *th) +{ + struct adxl367_data *data = dev->data; + int ret; + + + ret = data->hw_tf->write_reg_mask(dev, ADXL367_ACT_INACT_CTL, + ADXL367_ACT_INACT_CTL_ACT_EN_MSK | + ADXL367_ACT_INACT_CTL_ACT_REF_MSK, + FIELD_PREP(ADXL367_ACT_INACT_CTL_ACT_EN_MSK, th->enable) | + FIELD_PREP(ADXL367_ACT_INACT_CTL_ACT_REF_MSK, + th->referenced)); + if (ret != 0) { + return ret; + } + + ret = data->hw_tf->write_reg_mask(dev, ADXL367_THRESH_ACT_H, ADXL367_THRESH_H_MSK, + FIELD_PREP(ADXL367_THRESH_H_MSK, th->value >> 6)); + if (ret != 0) { + return ret; + } + + return data->hw_tf->write_reg_mask(dev, ADXL367_THRESH_ACT_L, ADXL367_THRESH_L_MSK, + FIELD_PREP(ADXL367_THRESH_L_MSK, th->value & 0x3F)); +} + +/** + * @brief Configures activity detection. + * + * @param dev - The device structure. + * @param th - Structure holding the inactivity threshold information: + * Enable/Disable inactivity detection + * Enable/Disable Referenced inactivity detection + * Set Threshold value + * + * @return 0 in case of success, negative error code otherwise. + */ +static int adxl367_setup_inactivity_detection(const struct device *dev, + const struct adxl367_activity_threshold *th) +{ + struct adxl367_data *data = dev->data; + int ret; + + ret = data->hw_tf->write_reg_mask(dev, ADXL367_ACT_INACT_CTL, + ADXL367_ACT_INACT_CTL_INACT_EN_MSK | + ADXL367_ACT_INACT_CTL_INACT_REF_MSK, + FIELD_PREP(ADXL367_ACT_INACT_CTL_INACT_EN_MSK, + th->enable) | + FIELD_PREP(ADXL367_ACT_INACT_CTL_INACT_REF_MSK, + th->referenced)); + if (ret != 0) { + return ret; + } + + ret = data->hw_tf->write_reg_mask(dev, ADXL367_THRESH_INACT_H, ADXL367_THRESH_H_MSK, + FIELD_PREP(ADXL367_THRESH_H_MSK, th->value >> 6)); + if (ret != 0) { + return ret; + } + + return data->hw_tf->write_reg_mask(dev, ADXL367_THRESH_INACT_L, ADXL367_THRESH_L_MSK, + FIELD_PREP(ADXL367_THRESH_L_MSK, th->value & 0x3F)); +} + +/** + * @brief Set the mode of operation. + * + * @param dev - The device structure. + * @param op_mode - Mode of operation. + * Accepted values: ADXL367_STANDBY + * ADXL367_MEASURE + * + * @return 0 in case of success, negative error code otherwise. + */ +static int adxl367_set_op_mode(const struct device *dev, + enum adxl367_op_mode op_mode) +{ + struct adxl367_data *data = dev->data; + int ret; + + ret = data->hw_tf->write_reg_mask(dev, ADXL367_POWER_CTL, + ADXL367_POWER_CTL_MEASURE_MSK, + FIELD_PREP(ADXL367_POWER_CTL_MEASURE_MSK, op_mode)); + if (ret != 0) { + return ret; + } + + if (op_mode == ADXL367_MEASURE) + /* Wait 100 ms to allow the acceleration outputs to settle */ + k_sleep(K_MSEC(100)); + + return 0; +} + +/** + * @brief Autosleep. When set to 1, autosleep is enabled, and the device enters + * wake-up mode automatically upon detection of inactivity. + * + * @param dev - The device structure. + * @param enable - Accepted values: true + * false + * + * @return 0 in case of success, negative error code otherwise. + */ +static int adxl367_set_autosleep(const struct device *dev, bool enable) +{ + struct adxl367_data *data = dev->data; + + return data->hw_tf->write_reg_mask(dev, ADXL367_POWER_CTL, + ADXL367_POWER_CTL_AUTOSLEEP_MSK, + FIELD_PREP(ADXL367_POWER_CTL_AUTOSLEEP_MSK, enable)); +} + +/** + * @brief Noise Mode. When set to 1, low noise mode is enabled + * + * @param dev - The device structure. + * @param enable - Accepted values: true + * false + * + * @return 0 in case of success, negative error code otherwise. + */ +static int adxl367_set_low_noise(const struct device *dev, bool enable) +{ + struct adxl367_data *data = dev->data; + + return data->hw_tf->write_reg_mask(dev, ADXL367_POWER_CTL, + ADXL367_POWER_CTL_NOISE_MSK, + FIELD_PREP(ADXL367_POWER_CTL_NOISE_MSK, enable)); +} + +/** + * @brief Link/Loop Activity Processing. + * + * @param dev - The device structure. + * @param mode - Mode of operation. + * Accepted values: ADXL367_DEFAULT + * ADXL367_LINKED + * ADXL367_LOOPED + * + * @return 0 in case of success, negative error code otherwise. + */ +static int adxl367_set_act_proc_mode(const struct device *dev, + enum adxl367_act_proc_mode mode) +{ + struct adxl367_data *data = dev->data; + + return data->hw_tf->write_reg_mask(dev, ADXL367_ACT_INACT_CTL, + ADXL367_ACT_INACT_CTL_LINKLOOP_MSK, + FIELD_PREP(ADXL367_ACT_INACT_CTL_LINKLOOP_MSK, mode)); +} + + +/** + * @brief Selects the Output Data Rate of the device. + * @param dev - The device structure. + * @param odr - Output Data Rate option. + * Accepted values: ADXL367_ODR_12P5HZ, + * ADXL367_ODR_25HZ, + * ADXL367_ODR_50HZ, + * ADXL367_ODR_100HZ, + * ADXL367_ODR_200HZ, + * ADXL367_ODR_400HZ + * @return 0 in case of success, negative error code otherwise. + */ +int adxl367_set_output_rate(const struct device *dev, enum adxl367_odr odr) +{ + struct adxl367_data *data = dev->data; + + return data->hw_tf->write_reg_mask(dev, + ADXL367_FILTER_CTL, + ADXL367_FILTER_CTL_ODR_MSK, + FIELD_PREP(ADXL367_FILTER_CTL_ODR_MSK, odr)); +} + +/** + * @brief Selects the measurement range. + * + * @param dev - The device structure. + * @param range - Range option. + * Accepted values: ADXL367_2G_RANGE, +/- 2g + * ADXL367_4G_RANGE, +/- 4g + * ADXL367_8G_RANGE +/- 8g + * + * @return 0 in case of success, negative error code otherwise. + */ +int adxl367_set_range(const struct device *dev, enum adxl367_range range) +{ + struct adxl367_data *data = dev->data; + + return data->hw_tf->write_reg_mask(dev, + ADXL367_FILTER_CTL, + ADXL367_FILTER_CTL_RANGE_MSK, + FIELD_PREP(ADXL367_FILTER_CTL_RANGE_MSK, range)); +} + +/** + * @brief Set the activity timer + * + * @param dev - The device structure. + * @param time - The value set in this register. + * + * @return 0 in case of success, negative error code otherwise. + */ +static int adxl367_set_activity_time(const struct device *dev, uint8_t time) +{ + struct adxl367_data *data = dev->data; + + return data->hw_tf->write_reg(dev, ADXL367_TIME_ACT, time); +} + +/** + * Set the inactivity timer + * @param dev - The device structure. + * @param time - is the 16-bit value set by the TIME_INACT_L register + * (eight LSBs) and the TIME_INACT_H register (eight MSBs). + * @return 0 in case of success, negative error code otherwise. + */ +static int adxl367_set_inactivity_time(const struct device *dev, + uint16_t time) +{ + int ret; + struct adxl367_data *data = dev->data; + + ret = data->hw_tf->write_reg(dev, ADXL367_TIME_INACT_H, time >> 8); + if (ret != 0) { + return ret; + } + + return data->hw_tf->write_reg(dev, ADXL367_TIME_INACT_L, time & 0xFF); +} + +/** + * @brief Performs self test. + * + * @param dev - The device structure. + * + * @return 0 in case of success, negative error code otherwise. + */ +int adxl367_self_test(const struct device *dev) +{ + int ret; + struct adxl367_data *data = dev->data; + const struct adxl367_dev_config *cfg = dev->config; + int16_t x_axis_1, x_axis_2, dif, min, max; + uint8_t read_val[2]; + + uint32_t st_delay_ms; + + /* 4 / ODR value in ms */ + switch (cfg->odr) { + case ADXL367_ODR_12P5HZ: + st_delay_ms = 320; + case ADXL367_ODR_25HZ: + st_delay_ms = 160; + case ADXL367_ODR_50HZ: + st_delay_ms = 80; + case ADXL367_ODR_100HZ: + st_delay_ms = 40; + case ADXL367_ODR_200HZ: + st_delay_ms = 20; + case ADXL367_ODR_400HZ: + st_delay_ms = 10; + default: + return -EINVAL; + } + + ret = adxl367_set_op_mode(dev, ADXL367_MEASURE); + if (ret != 0) { + return ret; + } + + ret = data->hw_tf->write_reg_mask(dev, ADXL367_SELF_TEST, ADXL367_SELF_TEST_ST_MSK, + FIELD_PREP(ADXL367_SELF_TEST_ST_MSK, 1)); + if (ret != 0) { + return ret; + } + + /* 4 / ODR */ + k_sleep(K_MSEC(st_delay_ms)); + + ret = data->hw_tf->read_reg_multiple(dev, ADXL367_X_DATA_H, read_val, 2); + if (ret != 0) { + return ret; + } + + x_axis_1 = ((int16_t)read_val[0] << 6) + (read_val[1] >> 2); + + /* extend sign to 16 bits */ + if ((x_axis_1 & BIT(13)) != 0) { + x_axis_1 |= GENMASK(15, 14); + } + + ret = data->hw_tf->write_reg_mask(dev, ADXL367_SELF_TEST, + ADXL367_SELF_TEST_ST_FORCE_MSK, + FIELD_PREP(ADXL367_SELF_TEST_ST_FORCE_MSK, 1)); + if (ret != 0) { + return ret; + } + + /* 4 / ODR */ + k_sleep(K_MSEC(st_delay_ms)); + + ret = data->hw_tf->read_reg_multiple(dev, ADXL367_X_DATA_H, read_val, 2); + if (ret != 0) { + return ret; + } + + x_axis_2 = ((int16_t)read_val[0] << 6) + (read_val[1] >> 2); + + /* extend sign to 16 bits */ + if ((x_axis_2 & BIT(13)) != 0) + x_axis_2 |= GENMASK(15, 14); + + ret = adxl367_set_op_mode(dev, ADXL367_STANDBY); + if (ret != 0) { + return ret; + } + + ret = data->hw_tf->write_reg_mask(dev, ADXL367_SELF_TEST, ADXL367_SELF_TEST_ST_FORCE_MSK | + ADXL367_SELF_TEST_ST_MSK, + FIELD_PREP(ADXL367_SELF_TEST_ST_FORCE_MSK, 0) | + FIELD_PREP(ADXL367_SELF_TEST_ST_MSK, 0)); + if (ret != 0) { + return ret; + } + + dif = x_axis_2 - x_axis_1; + min = ADXL367_SELF_TEST_MIN * adxl367_scale_mul[data->range]; + max = ADXL367_SELF_TEST_MAX * adxl367_scale_mul[data->range]; + + if ((dif >= min) && (dif <= max)) { + LOG_INF("ADXL367 passed self-test\n"); + ret = 0; + } else { + LOG_ERR("ADXL367 failed self-test\n"); + ret = -EINVAL; + } + + return ret; +} + +/** + * @brief Enables temperature reading. + * + * @param dev - The device structure. + * @param enable - 1 - ENABLE + * 2 - DISABLE + * + * @return 0 in case of success, negative error code otherwise. + */ +int adxl367_temp_read_en(const struct device *dev, bool enable) +{ + struct adxl367_data *data = dev->data; + + return data->hw_tf->write_reg_mask(dev, + ADXL367_TEMP_CTL, + ADXL367_TEMP_EN_MSK, + FIELD_PREP(ADXL367_TEMP_EN_MSK, enable)); +} + +/** + * @brief Sets the number of FIFO sample sets. + * + * @param dev - The device structure. + * @param sets_nb - Sample sets number. For example, if ADXL367_FIFO_FORMAT_XYZ + * is selected, a value of 2 will represent 6 entries. + * + * @return 0 in case of success, negative error code otherwise. + */ +int adxl367_set_fifo_sample_sets_nb(const struct device *dev, + uint16_t sets_nb) +{ + struct adxl367_data *data = dev->data; + int ret; + uint8_t fifo_samples_msb = sets_nb & BIT(9) ? 1U : 0U; + + /* bit 9 goes to FIFO_SAMPLES from ADXL367_FIFO_CONTROL */ + ret = data->hw_tf->write_reg_mask(dev, ADXL367_FIFO_CONTROL, + ADXL367_FIFO_CONTROL_FIFO_SAMPLES_MSK, + FIELD_PREP(ADXL367_FIFO_CONTROL_FIFO_SAMPLES_MSK, + fifo_samples_msb)); + if (ret != 0) { + return ret; + } + + /* write last 8 bits to ADXL367_FIFO_SAMPLES */ + return data->hw_tf->write_reg(dev, ADXL367_FIFO_SAMPLES, sets_nb & 0xFF); +} + +/** + * @brief Sets FIFO mode. + * + * @param dev - The device structure. + * @param mode - FIFO mode. + * Accepted values: ADXL367_FIFO_DISABLED, + * ADXL367_OLDEST_SAVED, + * ADXL367_STREAM_MODE, + * ADXL367_TRIGGERED_MODE + * + * @return 0 in case of success, negative error code otherwise. + */ +int adxl367_set_fifo_mode(const struct device *dev, + enum adxl367_fifo_mode mode) +{ + struct adxl367_data *data = dev->data; + + return data->hw_tf->write_reg_mask(dev, + ADXL367_FIFO_CONTROL, + ADXL367_FIFO_CONTROL_FIFO_MODE_MSK, + FIELD_PREP(ADXL367_FIFO_CONTROL_FIFO_MODE_MSK, mode)); +} + +/** + * @brief Sets FIFO read mode. + * + * @param dev - The device structure. + * @param read_mode - FIFO read mode. + * Accepted values: ADXL367_12B_CHID, + * ADXL367_8B, + * ADXL367_12B, + * ADXL367_14B_CHID + * + * @return 0 in case of success, negative error code otherwise. + */ +int adxl367_set_fifo_read_mode(const struct device *dev, + enum adxl367_fifo_read_mode read_mode) +{ + struct adxl367_data *data = dev->data; + + return data->hw_tf->write_reg_mask(dev, ADXL367_ADC_CTL, + ADXL367_FIFO_8_12BIT_MSK, + FIELD_PREP(ADXL367_FIFO_8_12BIT_MSK, read_mode)); +} + +/** + * @brief Sets FIFO format. + * + * @param dev - The device structure. + * @param format - FIFO format. + * Accepted values: ADXL367_FIFO_FORMAT_XYZ, + * ADXL367_FIFO_FORMAT_X, + * ADXL367_FIFO_FORMAT_Y, + * ADXL367_FIFO_FORMAT_Z, + * ADXL367_FIFO_FORMAT_XYZT, + * ADXL367_FIFO_FORMAT_XT, + * ADXL367_FIFO_FORMAT_YT, + * ADXL367_FIFO_FORMAT_ZT, + * ADXL367_FIFO_FORMAT_XYZA, + * ADXL367_FIFO_FORMAT_XA, + * ADXL367_FIFO_FORMAT_YA, + * ADXL367_FIFO_FORMAT_ZA + * + * @return 0 in case of success, negative error code otherwise. + */ +int adxl367_set_fifo_format(const struct device *dev, + enum adxl367_fifo_format format) +{ + int ret; + struct adxl367_data *data = dev->data; + + ret = data->hw_tf->write_reg_mask(dev, + ADXL367_FIFO_CONTROL, + ADXL367_FIFO_CONTROL_FIFO_CHANNEL_MSK, + FIELD_PREP(ADXL367_FIFO_CONTROL_FIFO_CHANNEL_MSK, format)); + if (ret != 0) { + return ret; + } + + switch (format) { + case ADXL367_FIFO_FORMAT_XYZ: + samples_per_set = 3; + break; + case ADXL367_FIFO_FORMAT_X: + case ADXL367_FIFO_FORMAT_Y: + case ADXL367_FIFO_FORMAT_Z: + samples_per_set = 1; + break; + case ADXL367_FIFO_FORMAT_XYZT: + case ADXL367_FIFO_FORMAT_XYZA: + samples_per_set = 4; + break; + case ADXL367_FIFO_FORMAT_XT: + case ADXL367_FIFO_FORMAT_YT: + case ADXL367_FIFO_FORMAT_ZT: + case ADXL367_FIFO_FORMAT_XA: + case ADXL367_FIFO_FORMAT_YA: + case ADXL367_FIFO_FORMAT_ZA: + samples_per_set = 2; + break; + default: + return -EINVAL; + } + + return 0; +} + +/** + * @brief Configures the FIFO feature. Uses ADXL367_14B_CHID read mode as + * default. + * + * @param dev - The device structure. + * @param mode - FIFO mode selection. + * Example: ADXL367_FIFO_DISABLED, + * ADXL367_OLDEST_SAVED, + * ADXL367_STREAM_MODE, + * ADXL367_TRIGGERED_MODE + * @param format - FIFO format selection. + * Example: ADXL367_FIFO_FORMAT_XYZ, + * ADXL367_FIFO_FORMAT_X, + * ADXL367_FIFO_FORMAT_Y, + * ADXL367_FIFO_FORMAT_Z, + * ADXL367_FIFO_FORMAT_XYZT, + * ADXL367_FIFO_FORMAT_XT, + * ADXL367_FIFO_FORMAT_YT, + * ADXL367_FIFO_FORMAT_ZT, + * ADXL367_FIFO_FORMAT_XYZA, + * ADXL367_FIFO_FORMAT_XA, + * ADXL367_FIFO_FORMAT_YA, + * ADXL367_FIFO_FORMAT_ZA + * @param read_mode - FIFO read mode. + * Accepted values: ADXL367_12B_CHID, + * ADXL367_8B, + * ADXL367_12B, + * ADXL367_14B_CHID + * @param sets_nb - Specifies the number of samples sets to store in the FIFO. + * + * @return 0 in case of success, negative error code otherwise. + */ +int adxl367_fifo_setup(const struct device *dev, + enum adxl367_fifo_mode mode, + enum adxl367_fifo_format format, + enum adxl367_fifo_read_mode read_mode, + uint8_t sets_nb) +{ + int ret; + + ret = adxl367_set_fifo_mode(dev, mode); + if (ret != 0) { + return ret; + } + + ret = adxl367_set_fifo_format(dev, format); + if (ret != 0) { + return ret; + } + + ret = adxl367_set_fifo_sample_sets_nb(dev, sets_nb); + if (ret != 0) { + return ret; + } + + return adxl367_set_fifo_read_mode(dev, read_mode); +} + +/** + * @brief Software reset. + * + * @param dev - The device structure. + * + * @return 0 in case of success, negative error code otherwise. + */ +static int adxl367_reset(const struct device *dev) +{ + int ret; + struct adxl367_data *data = dev->data; + + ret = adxl367_set_op_mode(dev, ADXL367_STANDBY); + if (ret != 0) { + return ret; + } + + /* Writing code 0x52 resets the device */ + ret = data->hw_tf->write_reg(dev, ADXL367_SOFT_RESET, ADXL367_RESET_CODE); + if (ret != 0) { + return ret; + } + + /* Delay required after performing software reset */ + k_sleep(K_MSEC(8)); + + return ret; +} + + +/** + * @brief Reads the 3-axis raw data from the accelerometer. + * + * @param dev - The device structure. + * @param accel_data - store the XYZ axis accelerometer data. + * + * @return 0 in case of success, negative error code otherwise. + */ +int adxl367_get_accel_data(const struct device *dev, + struct adxl367_xyz_accel_data *accel_data) +{ + int ret; + uint8_t xyz_values[6] = { 0 }; + uint8_t reg_data, nready = 1U; + struct adxl367_data *data = dev->data; + + while (nready != 0) { + ret = data->hw_tf->read_reg(dev, ADXL367_STATUS, ®_data); + if (ret != 0) { + return ret; + } + + if ((reg_data & ADXL367_STATUS_DATA_RDY) != 0) { + nready = 0U; + } + } + + ret = data->hw_tf->read_reg_multiple(dev, ADXL367_X_DATA_H, xyz_values, 6); + if (ret != 0) { + return ret; + } + + /* result is 14 bits long, ignore last 2 bits from low byte */ + accel_data->x = ((int16_t)xyz_values[0] << 6) + (xyz_values[1] >> 2); + accel_data->y = ((int16_t)xyz_values[2] << 6) + (xyz_values[3] >> 2); + accel_data->z = ((int16_t)xyz_values[4] << 6) + (xyz_values[5] >> 2); + + /* extend sign to 16 bits */ + if ((accel_data->x & BIT(13)) != 0) { + accel_data->x |= GENMASK(15, 14); + } + + if ((accel_data->y & BIT(13)) != 0) { + accel_data->y |= GENMASK(15, 14); + } + + if ((accel_data->z & BIT(13)) != 0) { + accel_data->z |= GENMASK(15, 14); + } + + return 0; +} + +/** + * @brief Reads the raw temperature of the device. If ADXL367_TEMP_EN is not + * set, use adxl367_temp_read_en() first to enable temperature reading. + * + * @param dev - The device structure. + * @param raw_temp - Raw value of temperature. + * + * @return 0 in case of success, negative error code otherwise. + */ +int adxl367_get_temp_data(const struct device *dev, int16_t *raw_temp) +{ + int ret; + uint8_t temp[2] = { 0 }; + uint8_t reg_data, nready = 1U; + struct adxl367_data *data = dev->data; + + while (nready != 0) { + ret = data->hw_tf->read_reg(dev, ADXL367_STATUS, ®_data); + if (ret != 0) { + return ret; + } + + if ((reg_data & ADXL367_STATUS_DATA_RDY) != 0) { + nready = 0U; + } + } + + ret = data->hw_tf->read_reg_multiple(dev, ADXL367_TEMP_H, temp, 2); + if (ret != 0) { + return ret; + } + + *raw_temp = ((int16_t)temp[0] << 6) + (temp[1] >> 2); + /* extend sign to 16 bits */ + if ((*raw_temp & BIT(13)) != 0) { + *raw_temp |= GENMASK(15, 14); + } + + return 0; +} + +static int adxl367_attr_set_thresh(const struct device *dev, + enum sensor_channel chan, + enum sensor_attribute attr, + const struct sensor_value *val) +{ + const struct adxl367_dev_config *cfg = dev->config; + struct adxl367_activity_threshold threshold; + int64_t llvalue; + int32_t value; + int64_t micro_ms2 = val->val1 * 1000000LL + val->val2; + + llvalue = llabs((micro_ms2 * 10) / SENSOR_G); + + value = (int32_t) llvalue; + + threshold.value = value; + threshold.enable = cfg->activity_th.enable; + threshold.referenced = cfg->activity_th.referenced; + + switch (chan) { + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_ACCEL_XYZ: + if (attr == SENSOR_ATTR_UPPER_THRESH) { + return adxl367_setup_activity_detection(dev, &threshold); + } else { + return adxl367_setup_inactivity_detection(dev, &threshold); + } + + default: + LOG_ERR("attr_set() not supported on this channel"); + return -ENOTSUP; + } +} + +static int adxl367_attr_set_odr(const struct device *dev, + enum sensor_channel chan, + enum sensor_attribute attr, + const struct sensor_value *val) +{ + enum adxl367_odr odr; + + switch (val->val1) { + case 12: + case 13: + odr = ADXL367_ODR_12P5HZ; + break; + case 25: + odr = ADXL367_ODR_25HZ; + break; + case 50: + odr = ADXL367_ODR_50HZ; + break; + case 100: + odr = ADXL367_ODR_100HZ; + break; + case 200: + odr = ADXL367_ODR_200HZ; + break; + case 400: + odr = ADXL367_ODR_400HZ; + break; + default: + return -EINVAL; + } + + return adxl367_set_output_rate(dev, odr); +} + +static int adxl367_attr_set(const struct device *dev, + enum sensor_channel chan, + enum sensor_attribute attr, + const struct sensor_value *val) +{ + switch (attr) { + case SENSOR_ATTR_SAMPLING_FREQUENCY: + return adxl367_attr_set_odr(dev, chan, attr, val); + case SENSOR_ATTR_UPPER_THRESH: + case SENSOR_ATTR_LOWER_THRESH: + return adxl367_attr_set_thresh(dev, chan, attr, val); + default: + return -ENOTSUP; + } +} + +static int adxl367_sample_fetch(const struct device *dev, + enum sensor_channel chan) +{ + struct adxl367_data *data = dev->data; + int ret; + + ret = adxl367_get_accel_data(dev, &data->sample); + if (ret != 0) { + return ret; + } + + return adxl367_get_temp_data(dev, &data->temp_val); +} + +static void adxl367_accel_convert(const struct device *dev, + struct sensor_value *val, int16_t value) +{ + struct adxl367_data *data = dev->data; + + int64_t micro_ms2 = value * (SENSOR_G * 250 / 10000 * + adxl367_scale_mul[data->range] / 1000); + + val->val1 = micro_ms2 / 1000000; + val->val2 = micro_ms2 % 1000000; +} + +static void adxl367_temp_convert(struct sensor_value *val, int16_t value) +{ + int64_t temp_data = (value + ADXL367_TEMP_OFFSET) * ADXL367_TEMP_SCALE; + + val->val1 = temp_data / ADXL367_TEMP_SCALE_DIV; + val->val2 = temp_data % ADXL367_TEMP_SCALE_DIV; +} + +static int adxl367_channel_get(const struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + struct adxl367_data *data = dev->data; + + switch (chan) { + case SENSOR_CHAN_ACCEL_X: + adxl367_accel_convert(dev, val, data->sample.x); + break; + case SENSOR_CHAN_ACCEL_Y: + adxl367_accel_convert(dev, val, data->sample.y); + break; + case SENSOR_CHAN_ACCEL_Z: + adxl367_accel_convert(dev, val, data->sample.z); + break; + case SENSOR_CHAN_ACCEL_XYZ: + adxl367_accel_convert(dev, val++, data->sample.x); + adxl367_accel_convert(dev, val++, data->sample.y); + adxl367_accel_convert(dev, val, data->sample.z); + break; + case SENSOR_CHAN_DIE_TEMP: + adxl367_temp_convert(val, data->temp_val); + default: + return -ENOTSUP; + } + + return 0; +} + +static const struct sensor_driver_api adxl367_api_funcs = { + .attr_set = adxl367_attr_set, + .sample_fetch = adxl367_sample_fetch, + .channel_get = adxl367_channel_get, +#ifdef CONFIG_ADXL367_TRIGGER + .trigger_set = adxl367_trigger_set, +#endif +}; + +static int adxl367_probe(const struct device *dev) +{ + const struct adxl367_dev_config *cfg = dev->config; + struct adxl367_data *data = dev->data; + uint8_t dev_id, part_id; + int ret; + + ret = adxl367_reset(dev); + if (ret != 0) { + return ret; + } + + ret = data->hw_tf->read_reg(dev, ADXL367_DEVID, &dev_id); + if (ret != 0) { + return ret; + } + ret = data->hw_tf->read_reg(dev, ADXL367_PART_ID, &part_id); + if (ret != 0) { + return ret; + } + + if (dev_id != ADXL367_DEVID_VAL || part_id != ADXL367_PARTID_VAL) { + LOG_ERR("failed to read id (0x%X:0x%X)\n", dev_id, part_id); + return -ENODEV; + } + + data->range = cfg->range; + +#ifdef CONFIG_ADXL367_TRIGGER + data->act_proc_mode = ADXL367_LINKED; +#else + data->act_proc_mode = ADXL367_LOOPED; +#endif + + ret = adxl367_self_test(dev); + if (ret != 0) { + return ret; + } + + ret = adxl367_temp_read_en(dev, cfg->temp_en); + if (ret != 0) { + return ret; + } + + ret = adxl367_set_autosleep(dev, cfg->autosleep); + if (ret != 0) { + return ret; + } + + ret = adxl367_set_low_noise(dev, cfg->low_noise); + if (ret != 0) { + return ret; + } + + ret = adxl367_setup_activity_detection(dev, &cfg->activity_th); + if (ret != 0) { + return ret; + } + + ret = adxl367_setup_inactivity_detection(dev, &cfg->inactivity_th); + if (ret != 0) { + return ret; + } + + ret = adxl367_set_activity_time(dev, cfg->activity_time); + if (ret != 0) { + return ret; + } + + ret = adxl367_set_inactivity_time(dev, cfg->inactivity_time); + if (ret != 0) { + return ret; + } + + ret = adxl367_set_output_rate(dev, cfg->odr); + if (ret != 0) { + return ret; + } + + ret = adxl367_fifo_setup(dev, cfg->fifo_config.fifo_mode, + cfg->fifo_config.fifo_format, + cfg->fifo_config.fifo_read_mode, + cfg->fifo_config.fifo_samples); + if (ret != 0) { + return ret; + } + +if (IS_ENABLED(CONFIG_ADXL367_TRIGGER)) { + ret = adxl367_init_interrupt(dev); + if (ret != 0) { + LOG_ERR("Failed to initialize interrupt!"); + return -EIO; + } +} + + ret = adxl367_set_op_mode(dev, cfg->op_mode); + if (ret != 0) { + return ret; + } + + ret = adxl367_set_range(dev, data->range); + if (ret != 0) { + return ret; + } + + return adxl367_set_act_proc_mode(dev, data->act_proc_mode); +} + +static int adxl367_init(const struct device *dev) +{ + int ret; + const struct adxl367_dev_config *cfg = dev->config; + + ret = cfg->bus_init(dev); + if (ret != 0) { + LOG_ERR("Failed to initialize sensor bus\n"); + return ret; + } + + return adxl367_probe(dev); +} + +#if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0 +#warning "ADXL367 driver enabled without any devices" +#endif + +/* + * Device creation macro, shared by ADXL367_DEFINE_SPI() and + * ADXL367_DEFINE_I2C(). + */ + +#define ADXL367_DEVICE_INIT(inst) \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, \ + adxl367_init, \ + NULL, \ + &adxl367_data_##inst, \ + &adxl367_config_##inst, \ + POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, \ + &adxl367_api_funcs); + +#ifdef CONFIG_ADXL367_TRIGGER +#define ADXL367_CFG_IRQ(inst) \ + .interrupt = GPIO_DT_SPEC_INST_GET(inst, int1_gpios), +#else +#define ADXL367_CFG_IRQ(inst) +#endif /* CONFIG_ADXL367_TRIGGER */ + +#define ADXL367_CONFIG(inst) \ + .odr = DT_INST_PROP(inst, odr), \ + .autosleep = false, \ + .low_noise = false, \ + .temp_en = true, \ + .range = ADXL367_2G_RANGE, \ + .activity_th.value = CONFIG_ADXL367_ACTIVITY_THRESHOLD, \ + .activity_th.referenced = \ + IS_ENABLED(CONFIG_ADXL367_REFERENCED_ACTIVITY_DETECTION_MODE), \ + .activity_th.enable = \ + IS_ENABLED(CONFIG_ADXL367_ACTIVITY_DETECTION_MODE), \ + .activity_time = CONFIG_ADXL367_ACTIVITY_TIME, \ + .inactivity_th.value = CONFIG_ADXL367_INACTIVITY_THRESHOLD, \ + .inactivity_th.referenced = \ + IS_ENABLED(CONFIG_ADXL367_REFERENCED_INACTIVITY_DETECTION_MODE),\ + .inactivity_th.enable = \ + IS_ENABLED(CONFIG_ADXL367_INACTIVITY_DETECTION_MODE), \ + .inactivity_time = CONFIG_ADXL367_INACTIVITY_TIME, \ + .fifo_config.fifo_mode = ADXL367_FIFO_DISABLED, \ + .fifo_config.fifo_format = ADXL367_FIFO_FORMAT_XYZ, \ + .fifo_config.fifo_samples = 128, \ + .fifo_config.fifo_read_mode = ADXL367_14B_CHID, \ + .op_mode = ADXL367_MEASURE, + +/* + * Instantiation macros used when a device is on a SPI bus. + */ + +#define ADXL367_CONFIG_SPI(inst) \ + { \ + .bus_init = adxl367_spi_init, \ + .spi = SPI_DT_SPEC_INST_GET(inst, SPI_WORD_SET(8) | \ + SPI_TRANSFER_MSB, 0), \ + ADXL367_CONFIG(inst) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, int1_gpios), \ + (ADXL367_CFG_IRQ(inst)), ()) \ + } + +#define ADXL367_DEFINE_SPI(inst) \ + static struct adxl367_data adxl367_data_##inst; \ + static const struct adxl367_dev_config adxl367_config_##inst = \ + ADXL367_CONFIG_SPI(inst); \ + ADXL367_DEVICE_INIT(inst) + +/* + * Instantiation macros used when a device is on an I2C bus. + */ + +#define ADXL367_CONFIG_I2C(inst) \ + { \ + .bus_init = adxl367_i2c_init, \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + ADXL367_CONFIG(inst) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, int1_gpios), \ + (ADXL367_CFG_IRQ(inst)), ()) \ + } + +#define ADXL367_DEFINE_I2C(inst) \ + static struct adxl367_data adxl367_data_##inst; \ + static const struct adxl367_dev_config adxl367_config_##inst = \ + ADXL367_CONFIG_I2C(inst); \ + ADXL367_DEVICE_INIT(inst) +/* + * Main instantiation macro. Use of COND_CODE_1() selects the right + * bus-specific macro at preprocessor time. + */ + +#define ADXL367_DEFINE(inst) \ + COND_CODE_1(DT_INST_ON_BUS(inst, spi), \ + (ADXL367_DEFINE_SPI(inst)), \ + (ADXL367_DEFINE_I2C(inst))) + +DT_INST_FOREACH_STATUS_OKAY(ADXL367_DEFINE) diff --git a/drivers/sensor/adxl367/adxl367.h b/drivers/sensor/adxl367/adxl367.h new file mode 100644 index 00000000000..8cef47420bb --- /dev/null +++ b/drivers/sensor/adxl367/adxl367.h @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2023 Analog Devices Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_ADXL367_ADXL367_H_ +#define ZEPHYR_DRIVERS_SENSOR_ADXL367_ADXL367_H_ + +#include +#include +#include +#include +#include +#include + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) +#include +#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) */ + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) +#include +#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */ + +/* + * ADXL367 registers definition + */ +#define ADXL367_DEVID 0x00u /* Analog Devices accelerometer ID */ +#define ADXL367_DEVID_MST 0x01u /* Analog Devices MEMS device ID */ +#define ADXL367_PART_ID 0x02u /* Device ID */ +#define ADXL367_REV_ID 0x03u /* product revision ID*/ +#define ADXL367_SERIAL_NR_3 0x04u /* Serial Number 3 */ +#define ADXL367_SERIAL_NR_2 0x05u /* Serial Number 2 */ +#define ADXL367_SERIAL_NR_1 0x06u /* Serial Number 1 */ +#define ADXL367_SERIAL_NR_0 0x07u /* Serial Number 0 */ +#define ADXL367_XDATA 0x08u /* X-axis acceleration data [13:6] */ +#define ADXL367_YDATA 0x09u /* Y-axis acceleration data [13:6] */ +#define ADXL367_ZDATA 0x0Au /* Z-axis acceleration data [13:6] */ +#define ADXL367_STATUS 0x0Bu /* Status */ +#define ADXL367_FIFO_ENTRIES_L 0x0Cu /* FIFO Entries Low */ +#define ADXL367_FIFO_ENTRIES_H 0x0Du /* FIFO Entries High */ +#define ADXL367_X_DATA_H 0x0Eu /* X-axis acceleration data [13:6] */ +#define ADXL367_X_DATA_L 0x0Fu /* X-axis acceleration data [5:0] */ +#define ADXL367_Y_DATA_H 0x10u /* Y-axis acceleration data [13:6] */ +#define ADXL367_Y_DATA_L 0x11u /* Y-axis acceleration data [5:0] */ +#define ADXL367_Z_DATA_H 0x12u /* Z-axis acceleration data [13:6] */ +#define ADXL367_Z_DATA_L 0x13u /* Z-axis acceleration data [5:0] */ +#define ADXL367_TEMP_H 0x14u /* Temperate data [13:6] */ +#define ADXL367_TEMP_L 0x15u /* Temperate data [5:0] */ +#define ADXL367_EX_ADC_H 0x16u /* Extended ADC data [13:6] */ +#define ADXL367_EX_ADC_L 0x17u /* Extended ADC data [5:0] */ +#define ADXL367_I2C_FIFO_DATA 0x18u /* I2C FIFO Data address */ +#define ADXL367_SOFT_RESET 0x1Fu /* Software reset register */ +#define ADXL367_THRESH_ACT_H 0x20u /* Activity Threshold [12:6] */ +#define ADXL367_THRESH_ACT_L 0x21u /* Activity Threshold [5:0] */ +#define ADXL367_TIME_ACT 0x22u /* Activity Time */ +#define ADXL367_THRESH_INACT_H 0x23u /* Inactivity Threshold [12:6] */ +#define ADXL367_THRESH_INACT_L 0x24u /* Inactivity Threshold [5:0] */ +#define ADXL367_TIME_INACT_H 0x25u /* Inactivity Time [12:6] */ +#define ADXL367_TIME_INACT_L 0x26u /* Inactivity Time [5:0] */ +#define ADXL367_ACT_INACT_CTL 0x27u /* Activity Inactivity Control */ +#define ADXL367_FIFO_CONTROL 0x28u /* FIFO Control */ +#define ADXL367_FIFO_SAMPLES 0x29u /* FIFO Samples */ +#define ADXL367_INTMAP1_LOWER 0x2Au /* Interrupt 1 mapping control lower */ +#define ADXL367_INTMAP2_LOWER 0x2Bu /* Interrupt 2 mapping control lower */ +#define ADXL367_FILTER_CTL 0x2Cu /* Filter Control register */ +#define ADXL367_POWER_CTL 0x2Du /* Power Control register */ +#define ADXL367_SELF_TEST 0x2Eu /* Self Test */ +#define ADXL367_TAP_THRESH 0x2Fu /* Tap Threshold */ +#define ADXL367_TAP_DUR 0x30u /* Tap Duration */ +#define ADXL367_TAP_LATENT 0x31u /* Tap Latency */ +#define ADXL367_TAP_WINDOW 0x32u /* Tap Window */ +#define ADXL367_X_OFFSET 0x33u /* X-axis offset */ +#define ADXL367_Y_OFFSET 0x34u /* Y-axis offset */ +#define ADXL367_Z_OFFSET 0x35u /* Z-axis offset */ +#define ADXL367_X_SENS 0x36u /* X-axis user sensitivity */ +#define ADXL367_Y_SENS 0x37u /* Y-axis user sensitivity */ +#define ADXL367_Z_SENS 0x38u /* Z-axis user sensitivity */ +#define ADXL367_TIMER_CTL 0x39u /* Timer Control */ +#define ADXL367_INTMAP1_UPPER 0x3Au /* Interrupt 1 mapping control upper */ +#define ADXL367_INTMAP2_UPPER 0x3Bu /* Interrupt 2 mapping control upper */ +#define ADXL367_ADC_CTL 0x3Cu /* ADC Control Register */ +#define ADXL367_TEMP_CTL 0x3Du /* Temperature Control Register */ +#define ADXL367_TEMP_ADC_OTH_H 0x3Eu /* Temperature ADC Over Threshold [12:6]*/ +#define ADXL367_TEMP_ADC_OTH_L 0x3Fu /* Temperature ADC Over Threshold [5:0]*/ +#define ADXL367_TEMP_ADC_UTH_H 0x40u /* Temperature ADC Under Threshold [12:6]*/ +#define ADXL367_TEMP_ADC_UTH_L 0x41u /* Temperature ADC Under Threshold [5:0]*/ +#define ADXL367_TEMP_ADC_TIMER 0x42u /* Temperature Activiy Inactivity Timer */ +#define ADXL367_AXIS_MASK 0x43u /* Axis Mask Register */ +#define ADXL367_STATUS_COPY 0x44u /* Status Copy Register */ +#define ADXL367_STATUS2 0x45u /* Status 2 Register */ + +#define ADXL367_DEVID_VAL 0xADu /* Analog Devices accelerometer ID */ +#define ADXL367_MST_DEVID_VAL 0x1Du /* Analog Devices MEMS device ID */ +#define ADXL367_PARTID_VAL 0xF7u /* Device ID */ +#define ADXL367_REVID_VAL 0x03u /* product revision ID*/ +#define ADXL367_RESET_CODE 0x52u /* Writing code 0x52 resets the device */ + +#define ADXL367_READ 0x01u +#define ADXL367_REG_READ(x) (((x & 0xFF) << 1) | ADXL367_READ) +#define ADXL367_REG_WRITE(x) ((x & 0xFF) << 1) +#define ADXL367_TO_REG(x) ((x) >> 1) +#define ADXL367_SPI_WRITE_REG 0x0Au +#define ADXL367_SPI_READ_REG 0x0Bu + +#define ADXL367_ABSOLUTE 0x00 +#define ADXL367_REFERENCED 0x01 + +/* ADXL367_POWER_CTL */ +#define ADXL367_POWER_CTL_EXT_CLK_MSK BIT(6) +#define ADXL367_POWER_CTL_NOISE_MSK GENMASK(5, 4) +#define ADXL367_POWER_CTL_WAKEUP_MSK BIT(3) +#define ADXL367_POWER_CTL_AUTOSLEEP_MSK BIT(2) +#define ADXL367_POWER_CTL_MEASURE_MSK GENMASK(1, 0) + +/* ADXL367_ACT_INACT_CTL */ +#define ADXL367_ACT_INACT_CTL_LINKLOOP_MSK GENMASK(5, 4) +#define ADXL367_ACT_INACT_CTL_INACT_REF_MSK BIT(3) +#define ADXL367_ACT_INACT_CTL_INACT_EN_MSK BIT(2) +#define ADXL367_ACT_INACT_CTL_ACT_REF_MSK BIT(1) +#define ADXL367_ACT_INACT_CTL_ACT_EN_MSK BIT(0) + +/* ADXL367_ACT_INACT_CTL_INACT_EN options */ +#define ADXL367_NO_INACTIVITY_DETECTION_ENABLED 0x0 +#define ADXL367_INACTIVITY_ENABLE 0x1 +#define ADXL367_NO_INACTIVITY_DETECTION_ENABLED_2 0x2 +#define ADXL367_REFERENCED_INACTIVITY_ENABLE 0x3 + +/* ADXL367_ACT_INACT_CTL_ACT_EN options */ +#define ADXL367_NO_ACTIVITY_DETECTION 0x0 +#define ADXL367_ACTIVITY_ENABLE 0x1 +#define ADXL367_NO_ACTIVITY_DETECTION_2 0x2 +#define ADXL367_REFERENCED_ACTIVITY_ENABLE 0x3 + +#define ADXL367_TEMP_OFFSET 1185 +#define ADXL367_TEMP_25C 165 +#define ADXL367_TEMP_SCALE 18518518LL +#define ADXL367_TEMP_SCALE_DIV 1000000000 + +#define ADXL367_THRESH_H_MSK GENMASK(6, 0) +#define ADXL367_THRESH_L_MSK GENMASK(7, 2) + +/* ADXL367_REG_TEMP_CTL definitions. */ +#define ADXL367_TEMP_INACT_EN_MSK BIT(3) +#define ADXL367_TEMP_ACT_EN_MSK BIT(1) +#define ADXL367_TEMP_EN_MSK BIT(0) + +/* ADXL367_SELF_TEST */ +#define ADXL367_SELF_TEST_ST_FORCE_MSK BIT(1) +#define ADXL367_SELF_TEST_ST_MSK BIT(0) + +/* ADXL367_REG_FILTER_CTL definitions */ +#define ADXL367_FILTER_CTL_RANGE_MSK GENMASK(7, 6) +#define ADXL367_FILTER_I2C_HS BIT(5) +#define ADXL367_FILTER_CTL_RES BIT(4) +#define ADXL367_FILTER_CTL_EXT_SAMPLE BIT(3) +#define ADXL367_FILTER_CTL_ODR_MSK GENMASK(2, 0) + +/* ADXL367_REG_FIFO_CONTROL */ +#define ADXL367_FIFO_CONTROL_FIFO_CHANNEL_MSK GENMASK(6, 3) +#define ADXL367_FIFO_CONTROL_FIFO_SAMPLES_MSK BIT(2) +#define ADXL367_FIFO_CONTROL_FIFO_MODE_MSK GENMASK(1, 0) + +/* ADXL367_REG_ADC_CTL definitions. */ +#define ADXL367_FIFO_8_12BIT_MSK GENMASK(7, 6) +#define ADXL367_ADC_INACT_EN BIT(3) +#define ADXL367_ADC_ACT_EN BIT(1) +#define ADXL367_ADC_EN BIT(0) + +/* ADXL367_REG_STATUS definitions */ +#define ADXL367_STATUS_ERR_USER_REGS BIT(7) +#define ADXL367_STATUS_AWAKE BIT(6) +#define ADXL367_STATUS_INACT BIT(5) +#define ADXL367_STATUS_ACT BIT(4) +#define ADXL367_STATUS_FIFO_OVERRUN BIT(3) +#define ADXL367_STATUS_FIFO_WATERMARK BIT(2) +#define ADXL367_STATUS_FIFO_RDY BIT(1) +#define ADXL367_STATUS_DATA_RDY BIT(0) + +/* ADXL367_INTMAP_LOWER */ +#define ADXL367_INT_LOW BIT(7) +#define ADXL367_AWAKE_INT BIT(6) +#define ADXL367_INACT_INT BIT(5) +#define ADXL367_ACT_INT BIT(4) +#define ADXL367_FIFO_OVERRUN BIT(3) +#define ADXL367_FIFO_WATERMARK BIT(2) +#define ADXL367_FIFO_RDY BIT(1) +#define ADXL367_DATA_RDY BIT(0) + +/* ADXL367_INTMAP_UPPER */ +#define ADXL367_ERR_FUSE BIT(7) +#define ADXL367_ERR_USER_REGS BIT(6) +#define ADXL367_KPALV_TIMER BIT(4) +#define ADXL367_TEMP_ADC_HI BIT(3) +#define ADXL367_TEMP_ADC_LOW BIT(2) +#define ADXL367_TAP_TWO BIT(1) +#define ADXL367_TAP_ONE BIT(0) + +/* Min change = 90mg. Sensitivity = 4LSB / mg */ +#define ADXL367_SELF_TEST_MIN (90 * 100 / 25) +/* Max change = 270mg. Sensitivity = 4LSB / mg */ +#define ADXL367_SELF_TEST_MAX (270 * 100 / 25) + +enum adxl367_axis { + ADXL367_X_AXIS, + ADXL367_Y_AXIS, + ADXL367_Z_AXIS +}; + +enum adxl367_op_mode { + ADXL367_STANDBY = 0, + ADXL367_MEASURE = 2, +}; + +enum adxl367_range { + ADXL367_2G_RANGE, + ADXL367_4G_RANGE, + ADXL367_8G_RANGE, +}; + +enum adxl367_act_proc_mode { + ADXL367_DEFAULT = 0, + ADXL367_LINKED = 1, + ADXL367_LOOPED = 3, +}; + +enum adxl367_odr { + ADXL367_ODR_12P5HZ, + ADXL367_ODR_25HZ, + ADXL367_ODR_50HZ, + ADXL367_ODR_100HZ, + ADXL367_ODR_200HZ, + ADXL367_ODR_400HZ, +}; + +enum adxl367_fifo_format { + ADXL367_FIFO_FORMAT_XYZ, + ADXL367_FIFO_FORMAT_X, + ADXL367_FIFO_FORMAT_Y, + ADXL367_FIFO_FORMAT_Z, + ADXL367_FIFO_FORMAT_XYZT, + ADXL367_FIFO_FORMAT_XT, + ADXL367_FIFO_FORMAT_YT, + ADXL367_FIFO_FORMAT_ZT, + ADXL367_FIFO_FORMAT_XYZA, + ADXL367_FIFO_FORMAT_XA, + ADXL367_FIFO_FORMAT_YA, + ADXL367_FIFO_FORMAT_ZA +}; + +enum adxl367_fifo_mode { + ADXL367_FIFO_DISABLED, + ADXL367_OLDEST_SAVED, + ADXL367_STREAM_MODE, + ADXL367_TRIGGERED_MODE +}; + +enum adxl367_fifo_read_mode { + ADXL367_12B_CHID, + ADXL367_8B, + ADXL367_12B, + ADXL367_14B_CHID +}; + +struct adxl367_fifo_config { + enum adxl367_fifo_mode fifo_mode; + enum adxl367_fifo_format fifo_format; + enum adxl367_fifo_read_mode fifo_read_mode; + uint16_t fifo_samples; +}; + +struct adxl367_activity_threshold { + uint16_t value; + bool referenced; + bool enable; +}; + +struct adxl367_xyz_accel_data { + int16_t x; + int16_t y; + int16_t z; +}; + +struct adxl367_transfer_function { + int (*read_reg_multiple)(const struct device *dev, uint8_t reg_addr, + uint8_t *value, uint16_t len); + int (*write_reg)(const struct device *dev, uint8_t reg_addr, + uint8_t value); + int (*read_reg)(const struct device *dev, uint8_t reg_addr, + uint8_t *value); + int (*write_reg_mask)(const struct device *dev, uint8_t reg_addr, + uint32_t mask, uint8_t value); +}; + +struct adxl367_data { + struct adxl367_xyz_accel_data sample; + int16_t temp_val; + const struct adxl367_transfer_function *hw_tf; + struct adxl367_fifo_config fifo_config; + enum adxl367_act_proc_mode act_proc_mode; + enum adxl367_range range; +#ifdef CONFIG_ADXL367_TRIGGER + struct gpio_callback gpio_cb; + + sensor_trigger_handler_t th_handler; + const struct sensor_trigger *th_trigger; + sensor_trigger_handler_t drdy_handler; + const struct sensor_trigger *drdy_trigger; + const struct device *dev; + +#if defined(CONFIG_ADXL367_TRIGGER_OWN_THREAD) + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_ADXL367_THREAD_STACK_SIZE); + struct k_sem gpio_sem; + struct k_thread thread; +#elif defined(CONFIG_ADXL367_TRIGGER_GLOBAL_THREAD) + struct k_work work; +#endif +#endif /* CONFIG_ADXL367_TRIGGER */ +}; + +struct adxl367_dev_config { +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) + struct i2c_dt_spec i2c; +#endif +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) + struct spi_dt_spec spi; +#endif + int (*bus_init)(const struct device *dev); + +#ifdef CONFIG_ADXL367_TRIGGER + struct gpio_dt_spec interrupt; +#endif + + enum adxl367_odr odr; + + /* Device Settings */ + bool autosleep; + bool low_noise; + bool temp_en; + + struct adxl367_activity_threshold activity_th; + struct adxl367_activity_threshold inactivity_th; + struct adxl367_fifo_config fifo_config; + + enum adxl367_range range; + enum adxl367_op_mode op_mode; + + uint16_t inactivity_time; + uint8_t activity_time; +}; + +int adxl367_spi_init(const struct device *dev); +int adxl367_i2c_init(const struct device *dev); +int adxl367_trigger_set(const struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); + +int adxl367_init_interrupt(const struct device *dev); + +#endif /* ZEPHYR_DRIVERS_SENSOR_ADXL367_ADXL367_H_ */ diff --git a/drivers/sensor/adxl367/adxl367_i2c.c b/drivers/sensor/adxl367/adxl367_i2c.c new file mode 100644 index 00000000000..762334ad8da --- /dev/null +++ b/drivers/sensor/adxl367/adxl367_i2c.c @@ -0,0 +1,103 @@ +/* adxl367_i2c.c - I2C routines for ADXL367 driver + */ + +/* + * Copyright (c) 2023 Analog Devices + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT adi_adxl367 + +#include +#include + +#include "adxl367.h" + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) + +LOG_MODULE_DECLARE(ADXL367, CONFIG_SENSOR_LOG_LEVEL); + +static int adxl367_bus_access(const struct device *dev, uint8_t reg, + void *data, size_t length) +{ + const struct adxl367_dev_config *config = dev->config; + + if ((reg & ADXL367_READ) != 0) { + return i2c_burst_read_dt(&config->i2c, + ADXL367_TO_REG(reg), + (uint8_t *) data, length); + } else { + if (length != 1) + return -EINVAL; + + return i2c_reg_write_byte_dt(&config->i2c, + ADXL367_TO_REG(reg), + *(uint8_t *)data); + } +} + +static int adxl367_i2c_reg_read(const struct device *dev, uint8_t reg_addr, + uint8_t *reg_data) +{ + return adxl367_bus_access(dev, ADXL367_REG_READ(reg_addr), reg_data, 1); +} + +static int adxl367_i2c_reg_read_multiple(const struct device *dev, + uint8_t reg_addr, + uint8_t *reg_data, + uint16_t count) +{ + return adxl367_bus_access(dev, ADXL367_REG_READ(reg_addr), + reg_data, count); +} + +static int adxl367_i2c_reg_write(const struct device *dev, + uint8_t reg_addr, + uint8_t reg_data) +{ + return adxl367_bus_access(dev, ADXL367_REG_WRITE(reg_addr), + ®_data, 1); +} + + +int adxl367_i2c_reg_write_mask(const struct device *dev, + uint8_t reg_addr, + uint32_t mask, + uint8_t data) +{ + int ret; + uint8_t tmp; + + ret = adxl367_i2c_reg_read(dev, reg_addr, &tmp); + if (ret != 0) { + return ret; + } + + tmp &= ~mask; + tmp |= data; + + return adxl367_i2c_reg_write(dev, reg_addr, tmp); +} + +static const struct adxl367_transfer_function adxl367_i2c_transfer_fn = { + .read_reg_multiple = adxl367_i2c_reg_read_multiple, + .write_reg = adxl367_i2c_reg_write, + .read_reg = adxl367_i2c_reg_read, + .write_reg_mask = adxl367_i2c_reg_write_mask, +}; + +int adxl367_i2c_init(const struct device *dev) +{ + struct adxl367_data *data = dev->data; + const struct adxl367_dev_config *config = dev->config; + + data->hw_tf = &adxl367_i2c_transfer_fn; + + if (!i2c_is_ready_dt(&config->i2c)) { + return -ENODEV; + } + + return 0; +} +#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */ diff --git a/drivers/sensor/adxl367/adxl367_spi.c b/drivers/sensor/adxl367/adxl367_spi.c new file mode 100644 index 00000000000..a5b9c633b68 --- /dev/null +++ b/drivers/sensor/adxl367/adxl367_spi.c @@ -0,0 +1,131 @@ +/* adxl367_spi.c - SPI routines for ADXL367 driver + */ + +/* + * Copyright (c) 2023 Analog Devices + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT adi_adxl367 + +#include +#include + +#include "adxl367.h" + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) + +LOG_MODULE_DECLARE(ADXL367, CONFIG_SENSOR_LOG_LEVEL); + +static int adxl367_bus_access(const struct device *dev, uint8_t reg, + void *data, size_t length) +{ + const struct adxl367_dev_config *config = dev->config; + uint8_t rw_reg, addr_reg; + + if ((reg & ADXL367_READ) != 0) { + rw_reg = ADXL367_SPI_READ_REG; + } else { + rw_reg = ADXL367_SPI_WRITE_REG; + } + + addr_reg = ADXL367_TO_REG(reg); + + const struct spi_buf buf[3] = { + { + .buf = &rw_reg, + .len = 1 + }, { + .buf = &addr_reg, + .len = 1 + }, { + .buf = data, + .len = length + } + }; + + struct spi_buf_set tx = { + .buffers = buf, + }; + + if ((reg & ADXL367_READ) != 0) { + const struct spi_buf_set rx = { + .buffers = buf, + .count = 3 + }; + + tx.count = 2; + + return spi_transceive_dt(&config->spi, &tx, &rx); + } + + tx.count = 3; + + return spi_write_dt(&config->spi, &tx); +} + +static int adxl367_spi_reg_read(const struct device *dev, uint8_t reg_addr, + uint8_t *reg_data) +{ + return adxl367_bus_access(dev, ADXL367_REG_READ(reg_addr), reg_data, 1); +} + +static int adxl367_spi_reg_read_multiple(const struct device *dev, + uint8_t reg_addr, + uint8_t *reg_data, + uint16_t count) +{ + return adxl367_bus_access(dev, ADXL367_REG_READ(reg_addr), + reg_data, count); +} + +static int adxl367_spi_reg_write(const struct device *dev, + uint8_t reg_addr, + uint8_t reg_data) +{ + return adxl367_bus_access(dev, ADXL367_REG_WRITE(reg_addr), + ®_data, 1); +} + +int adxl367_spi_reg_write_mask(const struct device *dev, + uint8_t reg_addr, + uint32_t mask, + uint8_t data) +{ + int ret; + uint8_t tmp; + + ret = adxl367_spi_reg_read(dev, reg_addr, &tmp); + if (ret != 0) { + return ret; + } + + tmp &= ~mask; + tmp |= data; + + return adxl367_spi_reg_write(dev, reg_addr, tmp); +} + +static const struct adxl367_transfer_function adxl367_spi_transfer_fn = { + .read_reg_multiple = adxl367_spi_reg_read_multiple, + .write_reg = adxl367_spi_reg_write, + .read_reg = adxl367_spi_reg_read, + .write_reg_mask = adxl367_spi_reg_write_mask, +}; + +int adxl367_spi_init(const struct device *dev) +{ + struct adxl367_data *data = dev->data; + const struct adxl367_dev_config *config = dev->config; + + data->hw_tf = &adxl367_spi_transfer_fn; + + if (!spi_is_ready_dt(&config->spi)) { + return -ENODEV; + } + + return 0; +} + +#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) */ diff --git a/drivers/sensor/adxl367/adxl367_trigger.c b/drivers/sensor/adxl367/adxl367_trigger.c new file mode 100644 index 00000000000..4e86d466343 --- /dev/null +++ b/drivers/sensor/adxl367/adxl367_trigger.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2023 Analog Devices Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include "adxl367.h" + +#include +LOG_MODULE_DECLARE(ADXL367, CONFIG_SENSOR_LOG_LEVEL); + +static void adxl367_thread_cb(const struct device *dev) +{ + const struct adxl367_dev_config *cfg = dev->config; + struct adxl367_data *drv_data = dev->data; + uint8_t status; + int ret; + + /* Clear the status */ + ret = drv_data->hw_tf->read_reg(dev, ADXL367_STATUS, &status); + if (ret != 0) { + return; + } + + if (drv_data->th_handler != NULL) { + if (((FIELD_GET(ADXL367_STATUS_INACT, status)) != 0) || + (FIELD_GET(ADXL367_STATUS_ACT, status)) != 0) { + drv_data->th_handler(dev, drv_data->th_trigger); + } + } + + if ((drv_data->drdy_handler != NULL) && + (FIELD_GET(ADXL367_STATUS_DATA_RDY, status) != 0)) { + drv_data->drdy_handler(dev, drv_data->drdy_trigger); + } + + ret = gpio_pin_interrupt_configure_dt(&cfg->interrupt, + GPIO_INT_EDGE_TO_ACTIVE); + __ASSERT(ret == 0, "Interrupt configuration failed"); +} + +static void adxl367_gpio_callback(const struct device *dev, + struct gpio_callback *cb, uint32_t pins) +{ + struct adxl367_data *drv_data = + CONTAINER_OF(cb, struct adxl367_data, gpio_cb); + const struct adxl367_dev_config *cfg = drv_data->dev->config; + + gpio_pin_interrupt_configure_dt(&cfg->interrupt, GPIO_INT_DISABLE); + +#if defined(CONFIG_ADXL367_TRIGGER_OWN_THREAD) + k_sem_give(&drv_data->gpio_sem); +#elif defined(CONFIG_ADXL367_TRIGGER_GLOBAL_THREAD) + k_work_submit(&drv_data->work); +#endif +} + +#if defined(CONFIG_ADXL367_TRIGGER_OWN_THREAD) +static void adxl367_thread(struct adxl367_data *drv_data) +{ + while (true) { + k_sem_take(&drv_data->gpio_sem, K_FOREVER); + adxl367_thread_cb(drv_data->dev); + } +} + +#elif defined(CONFIG_ADXL367_TRIGGER_GLOBAL_THREAD) +static void adxl367_work_cb(struct k_work *work) +{ + struct adxl367_data *drv_data = + CONTAINER_OF(work, struct adxl367_data, work); + + adxl367_thread_cb(drv_data->dev); +} +#endif + +int adxl367_trigger_set(const struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + const struct adxl367_dev_config *cfg = dev->config; + struct adxl367_data *drv_data = dev->data; + uint8_t int_mask, int_en, status; + int ret; + + ret = gpio_pin_interrupt_configure_dt(&cfg->interrupt, + GPIO_INT_DISABLE); + if (ret != 0) { + return ret; + } + + switch (trig->type) { + case SENSOR_TRIG_THRESHOLD: + drv_data->th_handler = handler; + drv_data->th_trigger = trig; + int_mask = ADXL367_ACT_INT | ADXL367_INACT_INT; + break; + case SENSOR_TRIG_DATA_READY: + drv_data->drdy_handler = handler; + drv_data->drdy_trigger = trig; + int_mask = ADXL367_DATA_RDY; + break; + default: + LOG_ERR("Unsupported sensor trigger"); + return -ENOTSUP; + } + + if (handler != NULL) { + int_en = int_mask; + } else { + int_en = 0U; + } + + ret = drv_data->hw_tf->write_reg_mask(dev, ADXL367_INTMAP1_LOWER, int_mask, int_en); + if (ret != 0) { + return ret; + } + + /* Clear status */ + ret = drv_data->hw_tf->read_reg(dev, ADXL367_STATUS, &status); + if (ret != 0) { + return ret; + } + + ret = gpio_pin_interrupt_configure_dt(&cfg->interrupt, + GPIO_INT_EDGE_TO_ACTIVE); + if (ret != 0) { + return ret; + } + + return 0; +} + +int adxl367_init_interrupt(const struct device *dev) +{ + const struct adxl367_dev_config *cfg = dev->config; + struct adxl367_data *drv_data = dev->data; + int ret; + + if (!gpio_is_ready_dt(&cfg->interrupt)) { + LOG_ERR("GPIO port %s not ready", cfg->interrupt.port->name); + return -EINVAL; + } + + ret = gpio_pin_configure_dt(&cfg->interrupt, GPIO_INPUT); + if (ret != 0) { + return ret; + } + + gpio_init_callback(&drv_data->gpio_cb, + adxl367_gpio_callback, + BIT(cfg->interrupt.pin)); + + ret = gpio_add_callback(cfg->interrupt.port, &drv_data->gpio_cb); + if (ret != 0) { + LOG_ERR("Failed to set gpio callback!"); + return ret; + } + + drv_data->dev = dev; + +#if defined(CONFIG_ADXL367_TRIGGER_OWN_THREAD) + k_sem_init(&drv_data->gpio_sem, 0, K_SEM_MAX_LIMIT); + + k_thread_create(&drv_data->thread, drv_data->thread_stack, + CONFIG_ADXL367_THREAD_STACK_SIZE, + (k_thread_entry_t)adxl367_thread, drv_data, + NULL, NULL, K_PRIO_COOP(CONFIG_ADXL367_THREAD_PRIORITY), + 0, K_NO_WAIT); +#elif defined(CONFIG_ADXL367_TRIGGER_GLOBAL_THREAD) + drv_data->work.handler = adxl367_work_cb; +#endif + + return 0; +} diff --git a/drivers/sensor/adxl372/adxl372.h b/drivers/sensor/adxl372/adxl372.h index 39d1959b220..13b4d93454b 100644 --- a/drivers/sensor/adxl372/adxl372.h +++ b/drivers/sensor/adxl372/adxl372.h @@ -365,14 +365,11 @@ int adxl372_i2c_init(const struct device *dev); int adxl372_get_status(const struct device *dev, uint8_t *status1, uint8_t *status2, uint16_t *fifo_entries); -int adxl372_reg_write_mask(const struct device *dev, - uint8_t reg_addr, uint32_t mask, uint8_t data); - int adxl372_trigger_set(const struct device *dev, const struct sensor_trigger *trig, sensor_trigger_handler_t handler); int adxl372_init_interrupt(const struct device *dev); -#endif /* CONFIG_ADT7420_TRIGGER */ +#endif /* CONFIG_ADXL372_TRIGGER */ #endif /* ZEPHYR_DRIVERS_SENSOR_ADXL372_ADXL372_H_ */ diff --git a/drivers/sensor/adxl372/adxl372_trigger.c b/drivers/sensor/adxl372/adxl372_trigger.c index adc3d0ba1f7..2d9cca6cfd8 100644 --- a/drivers/sensor/adxl372/adxl372_trigger.c +++ b/drivers/sensor/adxl372/adxl372_trigger.c @@ -69,8 +69,13 @@ static void adxl372_gpio_callback(const struct device *dev, } #if defined(CONFIG_ADXL372_TRIGGER_OWN_THREAD) -static void adxl372_thread(struct adxl372_data *drv_data) +static void adxl372_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct adxl372_data *drv_data = p1; + while (true) { k_sem_take(&drv_data->gpio_sem, K_FOREVER); adxl372_thread_cb(drv_data->dev); @@ -177,7 +182,7 @@ int adxl372_init_interrupt(const struct device *dev) k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_ADXL372_THREAD_STACK_SIZE, - (k_thread_entry_t)adxl372_thread, drv_data, + adxl372_thread, drv_data, NULL, NULL, K_PRIO_COOP(CONFIG_ADXL372_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_ADXL372_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/akm09918c/CMakeLists.txt b/drivers/sensor/akm09918c/CMakeLists.txt index 356b78dc8eb..7bfe5c3187f 100644 --- a/drivers/sensor/akm09918c/CMakeLists.txt +++ b/drivers/sensor/akm09918c/CMakeLists.txt @@ -4,5 +4,6 @@ zephyr_library() zephyr_library_sources(akm09918c.c) -zephyr_library_sources_ifdef(CONFIG_EMUL_AKM09918C akm09918c_emul.c) +zephyr_library_sources_ifdef(CONFIG_EMUL_AKM09918C akm09918c_emul.c) +zephyr_library_sources_ifdef(CONFIG_SENSOR_ASYNC_API akm09918c_async.c akm09918c_decoder.c) zephyr_include_directories_ifdef(CONFIG_EMUL_AKM09918C .) diff --git a/drivers/sensor/akm09918c/akm09918c.c b/drivers/sensor/akm09918c/akm09918c.c index f9c72ec21b9..50664bcdbc5 100644 --- a/drivers/sensor/akm09918c/akm09918c.c +++ b/drivers/sensor/akm09918c/akm09918c.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -19,7 +20,18 @@ LOG_MODULE_REGISTER(AKM09918C, CONFIG_SENSOR_LOG_LEVEL); -static int akm09918c_sample_fetch(const struct device *dev, enum sensor_channel chan) +/** + * @brief Perform the bus transaction to fetch samples + * + * @param dev Sensor device to operate on + * @param chan Channel ID to fetch + * @param x Location to write X channel sample. + * @param y Location to write Y channel sample. + * @param z Location to write Z channel sample. + * @return int 0 if successful or error code + */ +int akm09918c_sample_fetch_helper(const struct device *dev, enum sensor_channel chan, int16_t *x, + int16_t *y, int16_t *z) { struct akm09918c_data *data = dev->data; const struct akm09918c_config *cfg = dev->config; @@ -27,7 +39,7 @@ static int akm09918c_sample_fetch(const struct device *dev, enum sensor_channel if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_MAGN_X && chan != SENSOR_CHAN_MAGN_Y && chan != SENSOR_CHAN_MAGN_Z && chan != SENSOR_CHAN_MAGN_XYZ) { - LOG_WRN("Invalid channel %d", chan); + LOG_DBG("Invalid channel %d", chan); return -EINVAL; } @@ -54,13 +66,21 @@ static int akm09918c_sample_fetch(const struct device *dev, enum sensor_channel return -EBUSY; } - data->x_sample = sys_le16_to_cpu(buf[1] | (buf[2] << 8)); - data->y_sample = sys_le16_to_cpu(buf[3] | (buf[4] << 8)); - data->z_sample = sys_le16_to_cpu(buf[5] | (buf[6] << 8)); + *x = sys_le16_to_cpu(buf[1] | (buf[2] << 8)); + *y = sys_le16_to_cpu(buf[3] | (buf[4] << 8)); + *z = sys_le16_to_cpu(buf[5] | (buf[6] << 8)); return 0; } +static int akm09918c_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + struct akm09918c_data *data = dev->data; + + return akm09918c_sample_fetch_helper(dev, chan, &data->x_sample, &data->y_sample, + &data->z_sample); +} + static void akm09918c_convert(struct sensor_value *val, int16_t sample) { int64_t conv_val = sample * AKM09918C_MICRO_GAUSS_PER_BIT; @@ -85,7 +105,7 @@ static int akm09918c_channel_get(const struct device *dev, enum sensor_channel c } else if (chan == SENSOR_CHAN_MAGN_Z) { akm09918c_convert(val, data->z_sample); } else { - LOG_WRN("Invalid channel %d", chan); + LOG_DBG("Invalid channel %d", chan); return -ENOTSUP; } @@ -149,13 +169,6 @@ static int akm09918c_attr_set(const struct device *dev, enum sensor_channel chan return 0; } -static const struct sensor_driver_api akm09918c_driver_api = { - .sample_fetch = akm09918c_sample_fetch, - .channel_get = akm09918c_channel_get, - .attr_get = akm09918c_attr_get, - .attr_set = akm09918c_attr_set, -}; - static inline int akm09918c_check_who_am_i(const struct i2c_dt_spec *i2c) { uint8_t buffer[2]; @@ -204,6 +217,17 @@ static int akm09918c_init(const struct device *dev) return 0; } +static const struct sensor_driver_api akm09918c_driver_api = { + .sample_fetch = akm09918c_sample_fetch, + .channel_get = akm09918c_channel_get, + .attr_get = akm09918c_attr_get, + .attr_set = akm09918c_attr_set, +#ifdef CONFIG_SENSOR_ASYNC_API + .submit = akm09918c_submit, + .get_decoder = akm09918c_get_decoder, +#endif +}; + #define AKM09918C_DEFINE(inst) \ static struct akm09918c_data akm09918c_data_##inst; \ \ diff --git a/drivers/sensor/akm09918c/akm09918c.h b/drivers/sensor/akm09918c/akm09918c.h index 1745715287e..742c7d3be38 100644 --- a/drivers/sensor/akm09918c/akm09918c.h +++ b/drivers/sensor/akm09918c/akm09918c.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "akm09918c_reg.h" @@ -74,4 +75,24 @@ static inline void akm09918c_reg_to_hz(uint8_t reg, struct sensor_value *val) } } +/* + * RTIO types + */ + +struct akm09918c_decoder_header { + uint64_t timestamp; +} __attribute__((__packed__)); + +struct akm09918c_encoded_data { + struct akm09918c_decoder_header header; + int16_t readings[3]; +}; + +int akm09918c_sample_fetch_helper(const struct device *dev, enum sensor_channel chan, int16_t *x, + int16_t *y, int16_t *z); + +int akm09918c_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder); + +int akm09918c_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe); + #endif /* ZEPHYR_DRIVERS_SENSOR_AKM09918C_AKM09918C_H_ */ diff --git a/drivers/sensor/akm09918c/akm09918c_async.c b/drivers/sensor/akm09918c/akm09918c_async.c new file mode 100644 index 00000000000..438ca24780d --- /dev/null +++ b/drivers/sensor/akm09918c/akm09918c_async.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "akm09918c.h" + +LOG_MODULE_DECLARE(AKM09918C, CONFIG_SENSOR_LOG_LEVEL); + +int akm09918c_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +{ + uint32_t min_buf_len = sizeof(struct akm09918c_encoded_data); + int rc; + uint8_t *buf; + uint32_t buf_len; + struct akm09918c_encoded_data *edata; + + /* Get the buffer for the frame, it may be allocated dynamically by the rtio context */ + rc = rtio_sqe_rx_buf(iodev_sqe, min_buf_len, min_buf_len, &buf, &buf_len); + if (rc != 0) { + LOG_ERR("Failed to get a read buffer of size %u bytes", min_buf_len); + rtio_iodev_sqe_err(iodev_sqe, rc); + return rc; + } + + edata = (struct akm09918c_encoded_data *)buf; + edata->header.timestamp = k_ticks_to_ns_floor64(k_uptime_ticks()); + + rc = akm09918c_sample_fetch_helper(dev, SENSOR_CHAN_MAGN_XYZ, &edata->readings[0], + &edata->readings[1], &edata->readings[2]); + if (rc != 0) { + LOG_ERR("Failed to fetch samples"); + rtio_iodev_sqe_err(iodev_sqe, rc); + return rc; + } + + rtio_iodev_sqe_ok(iodev_sqe, 0); + + return 0; +} diff --git a/drivers/sensor/akm09918c/akm09918c_decoder.c b/drivers/sensor/akm09918c/akm09918c_decoder.c new file mode 100644 index 00000000000..9bd6b312b7a --- /dev/null +++ b/drivers/sensor/akm09918c/akm09918c_decoder.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "akm09918c.h" + +static int akm09918c_decoder_get_frame_count(const uint8_t *buffer, enum sensor_channel channel, + size_t channel_idx, uint16_t *frame_count) +{ + ARG_UNUSED(buffer); + ARG_UNUSED(channel); + ARG_UNUSED(channel_idx); + + /* This sensor lacks a FIFO; there will always only be one frame at a time. */ + *frame_count = 1; + return 0; +} + +static int akm09918c_decoder_get_size_info(enum sensor_channel channel, size_t *base_size, + size_t *frame_size) +{ + switch (channel) { + case SENSOR_CHAN_MAGN_X: + case SENSOR_CHAN_MAGN_Y: + case SENSOR_CHAN_MAGN_Z: + case SENSOR_CHAN_MAGN_XYZ: + *base_size = sizeof(struct sensor_three_axis_data); + *frame_size = sizeof(struct sensor_three_axis_sample_data); + return 0; + default: + return -ENOTSUP; + } +} + +/** Fixed shift value to use. All channels (MAGN_X, _Y, and _Z) have the same fixed range of + * +/- 49.12 Gauss. + */ +#define AKM09918C_SHIFT (6) + +static int akm09918c_convert_raw_to_q31(int16_t reading, q31_t *out) +{ + int64_t intermediate = ((int64_t)reading * AKM09918C_MICRO_GAUSS_PER_BIT) * + ((int64_t)INT32_MAX + 1) / + ((1 << AKM09918C_SHIFT) * INT64_C(1000000)); + + *out = CLAMP(intermediate, INT32_MIN, INT32_MAX); + return 0; +} + +static int akm09918c_decoder_decode(const uint8_t *buffer, enum sensor_channel channel, + size_t channel_idx, uint32_t *fit, + uint16_t max_count, void *data_out) +{ + const struct akm09918c_encoded_data *edata = (const struct akm09918c_encoded_data *)buffer; + + if (*fit != 0) { + return 0; + } + + switch (channel) { + case SENSOR_CHAN_MAGN_X: + case SENSOR_CHAN_MAGN_Y: + case SENSOR_CHAN_MAGN_Z: + case SENSOR_CHAN_MAGN_XYZ: { + struct sensor_three_axis_data *out = data_out; + + out->header.base_timestamp_ns = edata->header.timestamp; + out->header.reading_count = 1; + out->shift = AKM09918C_SHIFT; + + akm09918c_convert_raw_to_q31(edata->readings[0], &out->readings[0].x); + akm09918c_convert_raw_to_q31(edata->readings[1], &out->readings[0].y); + akm09918c_convert_raw_to_q31(edata->readings[2], &out->readings[0].z); + *fit = 1; + + return 1; + } + default: + return -EINVAL; + } +} + +SENSOR_DECODER_API_DT_DEFINE() = { + .get_frame_count = akm09918c_decoder_get_frame_count, + .get_size_info = akm09918c_decoder_get_size_info, + .decode = akm09918c_decoder_decode, +}; + +int akm09918c_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder) +{ + ARG_UNUSED(dev); + *decoder = &SENSOR_DECODER_NAME(); + + return 0; +} diff --git a/drivers/sensor/akm09918c/akm09918c_emul.c b/drivers/sensor/akm09918c/akm09918c_emul.c index 2112acc8c00..02dc28b35db 100644 --- a/drivers/sensor/akm09918c/akm09918c_emul.c +++ b/drivers/sensor/akm09918c/akm09918c_emul.c @@ -76,7 +76,7 @@ static int akm09918c_emul_transfer_i2c(const struct emul *target, struct i2c_msg { struct akm09918c_emul_data *data = target->data; - i2c_dump_msgs_rw("emul", msgs, num_msgs, addr, false); + i2c_dump_msgs_rw(target->dev, msgs, num_msgs, addr, false); if (num_msgs < 1) { LOG_ERR("Invalid number of messages: %d", num_msgs); @@ -87,7 +87,7 @@ static int akm09918c_emul_transfer_i2c(const struct emul *target, struct i2c_msg return -EIO; } if (msgs->len < 1) { - LOG_ERR("Unexpected msg0 length %s", msgs->len); + LOG_ERR("Unexpected msg0 length %d", msgs->len); return -EIO; } diff --git a/drivers/sensor/amd_sb_tsi/CMakeLists.txt b/drivers/sensor/amd_sb_tsi/CMakeLists.txt new file mode 100644 index 00000000000..e9a33c445ae --- /dev/null +++ b/drivers/sensor/amd_sb_tsi/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() +zephyr_library_sources(sb_tsi.c) +zephyr_library_sources_ifdef(CONFIG_EMUL_AMD_SB_TSI sb_tsi_emul.c) diff --git a/drivers/sensor/amd_sb_tsi/Kconfig b/drivers/sensor/amd_sb_tsi/Kconfig new file mode 100644 index 00000000000..93e7ddb52e1 --- /dev/null +++ b/drivers/sensor/amd_sb_tsi/Kconfig @@ -0,0 +1,21 @@ +# SB-TSI configuration options + +# Copyright (c) 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +config AMD_SB_TSI + bool "AMD SB Temperature Sensor Interface" + default y + depends on DT_HAS_AMD_SB_TSI_ENABLED + select I2C + help + Enable the driver for SB Temperature Sensor Interface. This + is an I2C temperature sensor on AMD SoCs. + +config EMUL_AMD_SB_TSI + bool "Emulator for AMD SB-TSI" + default y + depends on AMD_SB_TSI + depends on EMUL + help + Enable the hardware emulator for the AMD SB-TSI. diff --git a/drivers/sensor/amd_sb_tsi/sb_tsi.c b/drivers/sensor/amd_sb_tsi/sb_tsi.c new file mode 100644 index 00000000000..de0b91f570d --- /dev/null +++ b/drivers/sensor/amd_sb_tsi/sb_tsi.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT amd_sb_tsi + +#include +#include +#include +#include +#include +#include +#include "sb_tsi.h" + +LOG_MODULE_REGISTER(AMD_SB_TSI, CONFIG_SENSOR_LOG_LEVEL); + +struct sb_tsi_data { + uint8_t sample_int; + uint8_t sample_dec; +}; + +struct sb_tsi_config { + struct i2c_dt_spec i2c; +}; + +static int sb_tsi_sample_fetch(const struct device *dev, + enum sensor_channel chan) +{ + struct sb_tsi_data *data = dev->data; + const struct sb_tsi_config *config = dev->config; + enum pm_device_state pm_state; + int res; + + (void)pm_device_state_get(dev, &pm_state); + if (pm_state != PM_DEVICE_STATE_ACTIVE) { + return -EIO; + } + + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_AMBIENT_TEMP) { + return -ENOTSUP; + } + + /* + * ReadOrder specifies the order for atomically reading the temp. + * The reset value is 0, which means reading Int latches Dec. + */ + res = i2c_reg_read_byte_dt(&config->i2c, SB_TSI_TEMP_INT, &data->sample_int); + if (res) { + return res; + } + + res = i2c_reg_read_byte_dt(&config->i2c, SB_TSI_TEMP_DEC, &data->sample_dec); + if (res) { + return res; + } + + return 0; +} + +static int sb_tsi_channel_get(const struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + struct sb_tsi_data *data = dev->data; + + if (chan != SENSOR_CHAN_AMBIENT_TEMP) { + return -ENOTSUP; + } + + val->val1 = data->sample_int; + val->val2 = (data->sample_dec >> SB_TSI_TEMP_DEC_SHIFT) * + (1000000 / SB_TSI_TEMP_DEC_SCALE); + + return 0; +} + +static const struct sensor_driver_api sb_tsi_driver_api = { + .sample_fetch = sb_tsi_sample_fetch, + .channel_get = sb_tsi_channel_get, +}; + +static int sb_tsi_init(const struct device *dev) +{ + const struct sb_tsi_config *config = dev->config; + int res = 0; + + if (!i2c_is_ready_dt(&config->i2c)) { + LOG_ERR("I2C device not ready"); + return -ENODEV; + } + +#ifdef CONFIG_PM_DEVICE_RUNTIME + pm_device_init_suspended(dev); + + res = pm_device_runtime_enable(dev); + if (res) { + LOG_ERR("Failed to enable runtime power management"); + } +#endif + + return res; +} + +#ifdef CONFIG_PM_DEVICE +static int sb_tsi_pm_action(const struct device *dev, enum pm_device_action action) +{ + switch (action) { + case PM_DEVICE_ACTION_TURN_ON: + case PM_DEVICE_ACTION_RESUME: + case PM_DEVICE_ACTION_TURN_OFF: + case PM_DEVICE_ACTION_SUSPEND: + return 0; + default: + return -ENOTSUP; + } +} +#endif + +#define SB_TSI_INST(inst) \ + static struct sb_tsi_data sb_tsi_data_##inst; \ + static const struct sb_tsi_config sb_tsi_config_##inst = { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + }; \ + PM_DEVICE_DT_INST_DEFINE(inst, sb_tsi_pm_action); \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, sb_tsi_init, PM_DEVICE_DT_INST_GET(inst), \ + &sb_tsi_data_##inst, &sb_tsi_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &sb_tsi_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(SB_TSI_INST) diff --git a/drivers/sensor/amd_sb_tsi/sb_tsi.h b/drivers/sensor/amd_sb_tsi/sb_tsi.h new file mode 100644 index 00000000000..10cb0fa28c6 --- /dev/null +++ b/drivers/sensor/amd_sb_tsi/sb_tsi.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_SB_TSI_SB_TSI_H_ +#define ZEPHYR_DRIVERS_SENSOR_SB_TSI_SB_TSI_H_ + +#define SB_TSI_TEMP_INT 0x01 +#define SB_TSI_TEMP_DEC 0x10 +#define SB_TSI_TEMP_DEC_SHIFT 5 +#define SB_TSI_TEMP_DEC_SCALE 8 + +#endif diff --git a/drivers/sensor/amd_sb_tsi/sb_tsi_emul.c b/drivers/sensor/amd_sb_tsi/sb_tsi_emul.c new file mode 100644 index 00000000000..fee197f1d90 --- /dev/null +++ b/drivers/sensor/amd_sb_tsi/sb_tsi_emul.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT amd_sb_tsi + +#include +#include +#include +#include +#include +#include +#include "sb_tsi.h" + +LOG_MODULE_DECLARE(AMD_SB_TSI, CONFIG_SENSOR_LOG_LEVEL); + +#define NUM_REGS 128 + +struct sb_tsi_emul_data { + uint8_t reg[NUM_REGS]; +}; + +static void sb_tsi_emul_set_reg(const struct emul *target, uint8_t reg, uint8_t val) +{ + struct sb_tsi_emul_data *data = target->data; + + __ASSERT_NO_MSG(reg < NUM_REGS); + data->reg[reg] = val; +} + +static uint8_t sb_tsi_emul_get_reg(const struct emul *target, uint8_t reg) +{ + struct sb_tsi_emul_data *data = target->data; + + __ASSERT_NO_MSG(reg < NUM_REGS); + return data->reg[reg]; +} + +static void sb_tsi_emul_reset(const struct emul *target) +{ + struct sb_tsi_emul_data *data = target->data; + + memset(data->reg, 0, NUM_REGS); +} + +static int sb_tsi_emul_transfer_i2c(const struct emul *target, struct i2c_msg *msgs, + int num_msgs, int addr) +{ + /* Largely copied from emul_bmi160.c */ + unsigned int val; + int reg; + + __ASSERT_NO_MSG(msgs && num_msgs); + + i2c_dump_msgs_rw(target->dev, msgs, num_msgs, addr, false); + switch (num_msgs) { + case 2: + if (msgs->flags & I2C_MSG_READ) { + LOG_ERR("Unexpected read"); + return -EIO; + } + if (msgs->len != 1) { + LOG_ERR("Unexpected msg0 length %d", msgs->len); + return -EIO; + } + reg = msgs->buf[0]; + + /* Now process the 'read' part of the message */ + msgs++; + if (msgs->flags & I2C_MSG_READ) { + switch (msgs->len) { + case 1: + val = sb_tsi_emul_get_reg(target, reg); + msgs->buf[0] = val; + break; + default: + LOG_ERR("Unexpected msg1 length %d", msgs->len); + return -EIO; + } + } else { + if (msgs->len != 1) { + LOG_ERR("Unexpected msg1 length %d", msgs->len); + } + sb_tsi_emul_set_reg(target, reg, msgs->buf[0]); + } + break; + default: + LOG_ERR("Invalid number of messages: %d", num_msgs); + return -EIO; + } + + return 0; +} + +static int sb_tsi_emul_init(const struct emul *target, const struct device *parent) +{ + sb_tsi_emul_reset(target); + return 0; +} + +static int sb_tsi_emul_set_channel(const struct emul *target, enum sensor_channel chan, + q31_t value, int8_t shift) +{ + struct sb_tsi_emul_data *data = target->data; + int64_t scaled_value; + int32_t millicelsius; + int32_t reg_value; + + if (chan != SENSOR_CHAN_AMBIENT_TEMP) { + return -ENOTSUP; + } + + scaled_value = (int64_t)value << shift; + millicelsius = scaled_value * 1000 / ((int64_t)INT32_MAX + 1); + reg_value = CLAMP(millicelsius / 125, 0, 0x7ff); + + data->reg[SB_TSI_TEMP_INT] = reg_value >> 3; + data->reg[SB_TSI_TEMP_DEC] = (reg_value & 0x7) << 5; + + return 0; +} + +static int sb_tsi_emul_get_sample_range(const struct emul *target, enum sensor_channel chan, + q31_t *lower, q31_t *upper, q31_t *epsilon, int8_t *shift) +{ + if (chan != SENSOR_CHAN_AMBIENT_TEMP) { + return -ENOTSUP; + } + + *shift = 8; + *lower = 0; + *upper = (int64_t)(255.875 * ((int64_t)INT32_MAX + 1)) >> *shift; + *epsilon = (int64_t)(0.125 * ((int64_t)INT32_MAX + 1)) >> *shift; + + return 0; +} + +static const struct i2c_emul_api sb_tsi_emul_api_i2c = { + .transfer = sb_tsi_emul_transfer_i2c, +}; + +static const struct emul_sensor_backend_api sb_tsi_emul_api_sensor = { + .set_channel = sb_tsi_emul_set_channel, + .get_sample_range = sb_tsi_emul_get_sample_range, +}; + +#define SB_TSI_EMUL(n) \ + struct sb_tsi_emul_data sb_tsi_emul_data_##n; \ + EMUL_DT_INST_DEFINE(n, sb_tsi_emul_init, &sb_tsi_emul_data_##n, NULL, \ + &sb_tsi_emul_api_i2c, &sb_tsi_emul_api_sensor) + +DT_INST_FOREACH_STATUS_OKAY(SB_TSI_EMUL) diff --git a/drivers/sensor/amg88xx/amg88xx_trigger.c b/drivers/sensor/amg88xx/amg88xx_trigger.c index fa1e237edab..7b8d4979ec8 100644 --- a/drivers/sensor/amg88xx/amg88xx_trigger.c +++ b/drivers/sensor/amg88xx/amg88xx_trigger.c @@ -113,8 +113,13 @@ static void amg88xx_thread_cb(const struct device *dev) } #ifdef CONFIG_AMG88XX_TRIGGER_OWN_THREAD -static void amg88xx_thread(struct amg88xx_data *drv_data) +static void amg88xx_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct amg88xx_data *drv_data = p1; + while (42) { k_sem_take(&drv_data->gpio_sem, K_FOREVER); amg88xx_thread_cb(drv_data->dev); @@ -196,7 +201,7 @@ int amg88xx_init_interrupt(const struct device *dev) k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_AMG88XX_THREAD_STACK_SIZE, - (k_thread_entry_t)amg88xx_thread, drv_data, + amg88xx_thread, drv_data, NULL, NULL, K_PRIO_COOP(CONFIG_AMG88XX_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_AMG88XX_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/bma280/bma280_trigger.c b/drivers/sensor/bma280/bma280_trigger.c index a20ce6dc853..5c39950b49f 100644 --- a/drivers/sensor/bma280/bma280_trigger.c +++ b/drivers/sensor/bma280/bma280_trigger.c @@ -127,8 +127,13 @@ static void bma280_thread_cb(const struct device *dev) } #ifdef CONFIG_BMA280_TRIGGER_OWN_THREAD -static void bma280_thread(struct bma280_data *drv_data) +static void bma280_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct bma280_data *drv_data = p1; + while (1) { k_sem_take(&drv_data->gpio_sem, K_FOREVER); bma280_thread_cb(drv_data->dev); @@ -281,7 +286,7 @@ int bma280_init_interrupt(const struct device *dev) k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_BMA280_THREAD_STACK_SIZE, - (k_thread_entry_t)bma280_thread, drv_data, + bma280_thread, drv_data, NULL, NULL, K_PRIO_COOP(CONFIG_BMA280_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_BMA280_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/bmc150_magn/bmc150_magn_trigger.c b/drivers/sensor/bmc150_magn/bmc150_magn_trigger.c index c51d965bc51..230b5daa8ae 100644 --- a/drivers/sensor/bmc150_magn/bmc150_magn_trigger.c +++ b/drivers/sensor/bmc150_magn/bmc150_magn_trigger.c @@ -81,8 +81,12 @@ static void bmc150_magn_gpio_drdy_callback(const struct device *dev, k_sem_give(&data->sem); } -static void bmc150_magn_thread_main(struct bmc150_magn_data *data) +static void bmc150_magn_thread_main(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct bmc150_magn_data *data = p1; const struct bmc150_magn_config *config = data->dev->config; uint8_t reg_val; @@ -145,7 +149,7 @@ int bmc150_magn_init_interrupt(const struct device *dev) k_thread_create(&data->thread, data->thread_stack, CONFIG_BMC150_MAGN_TRIGGER_THREAD_STACK, - (k_thread_entry_t)bmc150_magn_thread_main, + bmc150_magn_thread_main, data, NULL, NULL, K_PRIO_COOP(10), 0, K_NO_WAIT); diff --git a/drivers/sensor/bmg160/bmg160_trigger.c b/drivers/sensor/bmg160/bmg160_trigger.c index c4c7696cf3e..dc6946e7ee9 100644 --- a/drivers/sensor/bmg160/bmg160_trigger.c +++ b/drivers/sensor/bmg160/bmg160_trigger.c @@ -181,8 +181,13 @@ static void bmg160_handle_int(const struct device *dev) static K_KERNEL_STACK_DEFINE(bmg160_thread_stack, CONFIG_BMG160_THREAD_STACK_SIZE); static struct k_thread bmg160_thread; -static void bmg160_thread_main(struct bmg160_device_data *bmg160) +static void bmg160_thread_main(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct bmg160_device_data *bmg160 = p1; + while (true) { k_sem_take(&bmg160->trig_sem, K_FOREVER); @@ -245,7 +250,7 @@ int bmg160_trigger_init(const struct device *dev) k_sem_init(&bmg160->trig_sem, 0, K_SEM_MAX_LIMIT); k_thread_create(&bmg160_thread, bmg160_thread_stack, CONFIG_BMG160_THREAD_STACK_SIZE, - (k_thread_entry_t)bmg160_thread_main, + bmg160_thread_main, bmg160, NULL, NULL, K_PRIO_COOP(CONFIG_BMG160_THREAD_PRIORITY), 0, K_NO_WAIT); diff --git a/drivers/sensor/bmi08x/CMakeLists.txt b/drivers/sensor/bmi08x/CMakeLists.txt index a3a13c2390a..0282cc73d20 100644 --- a/drivers/sensor/bmi08x/CMakeLists.txt +++ b/drivers/sensor/bmi08x/CMakeLists.txt @@ -2,8 +2,8 @@ zephyr_library() -zephyr_library_sources_ifdef(CONFIG_BMI08X bmi08x_accel.c) -zephyr_library_sources_ifdef(CONFIG_BMI08X bmi08x_gyro.c) -zephyr_library_sources_ifdef(CONFIG_BMI08X bmi08x.c) +zephyr_library_sources(bmi08x_accel.c) +zephyr_library_sources(bmi08x_gyro.c) +zephyr_library_sources(bmi08x.c) zephyr_library_sources_ifdef(CONFIG_BMI08X_ACCEL_TRIGGER bmi08x_accel_trigger.c) zephyr_library_sources_ifdef(CONFIG_BMI08X_GYRO_TRIGGER bmi08x_gyro_trigger.c) diff --git a/drivers/sensor/bmi160/bmi160_trigger.c b/drivers/sensor/bmi160/bmi160_trigger.c index 3110977427e..3cb870f1285 100644 --- a/drivers/sensor/bmi160/bmi160_trigger.c +++ b/drivers/sensor/bmi160/bmi160_trigger.c @@ -71,8 +71,10 @@ static void bmi160_handle_interrupts(const struct device *dev) static K_KERNEL_STACK_DEFINE(bmi160_thread_stack, CONFIG_BMI160_THREAD_STACK_SIZE); static struct k_thread bmi160_thread; -static void bmi160_thread_main(struct bmi160_data *data) +static void bmi160_thread_main(void *p1, void *p2, void *p3) { + struct bmi160_data *data = p1; + while (1) { k_sem_take(&data->sem, K_FOREVER); bmi160_handle_interrupts(data->dev); @@ -276,7 +278,7 @@ int bmi160_trigger_mode_init(const struct device *dev) k_thread_create(&bmi160_thread, bmi160_thread_stack, CONFIG_BMI160_THREAD_STACK_SIZE, - (k_thread_entry_t)bmi160_thread_main, + bmi160_thread_main, data, NULL, NULL, K_PRIO_COOP(CONFIG_BMI160_THREAD_PRIORITY), 0, K_NO_WAIT); diff --git a/drivers/sensor/bmi160/emul_bmi160.c b/drivers/sensor/bmi160/emul_bmi160.c index 78fe6d3ef88..3870346cd30 100644 --- a/drivers/sensor/bmi160/emul_bmi160.c +++ b/drivers/sensor/bmi160/emul_bmi160.c @@ -241,7 +241,7 @@ static int bmi160_emul_transfer_i2c(const struct emul *target, struct i2c_msg *m __ASSERT_NO_MSG(msgs && num_msgs); - i2c_dump_msgs_rw("emul", msgs, num_msgs, addr, false); + i2c_dump_msgs_rw(target->dev, msgs, num_msgs, addr, false); switch (num_msgs) { case 2: if (msgs->flags & I2C_MSG_READ) { diff --git a/drivers/sensor/bmi270/bmi270_trigger.c b/drivers/sensor/bmi270/bmi270_trigger.c index 1fc21b14251..656b5d23d16 100644 --- a/drivers/sensor/bmi270/bmi270_trigger.c +++ b/drivers/sensor/bmi270/bmi270_trigger.c @@ -85,8 +85,13 @@ static void bmi270_thread_cb(const struct device *dev) } #ifdef CONFIG_BMI270_TRIGGER_OWN_THREAD -static void bmi270_thread(struct bmi270_data *data) +static void bmi270_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct bmi270_data *data = p1; + while (1) { k_sem_take(&data->trig_sem, K_FOREVER); bmi270_thread_cb(data->dev); @@ -173,7 +178,7 @@ int bmi270_init_interrupts(const struct device *dev) #if CONFIG_BMI270_TRIGGER_OWN_THREAD k_sem_init(&data->trig_sem, 0, 1); k_thread_create(&data->thread, data->thread_stack, CONFIG_BMI270_THREAD_STACK_SIZE, - (k_thread_entry_t)bmi270_thread, data, NULL, NULL, + bmi270_thread, data, NULL, NULL, K_PRIO_COOP(CONFIG_BMI270_THREAD_PRIORITY), 0, K_NO_WAIT); #elif CONFIG_BMI270_TRIGGER_GLOBAL_THREAD k_work_init(&data->trig_work, bmi270_trig_work_cb); diff --git a/drivers/sensor/bmm150/CMakeLists.txt b/drivers/sensor/bmm150/CMakeLists.txt index 7b3ad8d04cb..d41b954038c 100644 --- a/drivers/sensor/bmm150/CMakeLists.txt +++ b/drivers/sensor/bmm150/CMakeLists.txt @@ -2,3 +2,4 @@ zephyr_library() zephyr_library_sources(bmm150.c bmm150_i2c.c bmm150_spi.c) +zephyr_library_sources_ifdef(CONFIG_BMM150_TRIGGER bmm150_trigger.c) diff --git a/drivers/sensor/bmm150/Kconfig b/drivers/sensor/bmm150/Kconfig index 54cf97456d3..93f652eb2b3 100644 --- a/drivers/sensor/bmm150/Kconfig +++ b/drivers/sensor/bmm150/Kconfig @@ -33,6 +33,31 @@ config BMM150_PRESET_HIGH_ACCURACY endchoice +choice BMM150_TRIGGER_MODE + prompt "Trigger mode" + default BMM150_TRIGGER_NONE + help + Specify the type of triggering to be used by the driver. + +config BMM150_TRIGGER_NONE + bool "No trigger" + +config BMM150_TRIGGER_GLOBAL_THREAD + bool "Use global thread" + select BMM150_TRIGGER + +config BMM150_TRIGGER_OWN_THREAD + bool "Use own thread" + select BMM150_TRIGGER + +config BMM150_TRIGGER_DIRECT + bool "Use IRQ handler" + select BMM150_TRIGGER +endchoice + +config BMM150_TRIGGER + bool + config BMM150_SAMPLING_RATE_RUNTIME bool "Dynamic sampling rate" help @@ -48,4 +73,18 @@ config BMM150_SAMPLING_REP_Z help Enable alteration of Z oversampling at runtime. +config BMM150_THREAD_PRIORITY + int "Own thread priority" + depends on BMM150_TRIGGER_OWN_THREAD + default 10 + help + Priority of the thread used by the driver to handle interrupts. + +config BMM150_THREAD_STACK_SIZE + int "Own thread stack size" + depends on BMM150_TRIGGER_OWN_THREAD + default 1024 + help + Stack size of thread used by the driver to handle interrupts. + endif # BMM150 diff --git a/drivers/sensor/bmm150/bmm150.c b/drivers/sensor/bmm150/bmm150.c index 6c480190a67..62393ca02ae 100644 --- a/drivers/sensor/bmm150/bmm150.c +++ b/drivers/sensor/bmm150/bmm150.c @@ -495,6 +495,10 @@ static const struct sensor_driver_api bmm150_api_funcs = { #endif .sample_fetch = bmm150_sample_fetch, .channel_get = bmm150_channel_get, + +#ifdef CONFIG_BMM150_TRIGGER + .trigger_set = bmm150_trigger_set, +#endif }; static int bmm150_full_por(const struct device *dev) @@ -668,6 +672,13 @@ static int bmm150_init(const struct device *dev) return -EIO; } +#ifdef CONFIG_BMM150_TRIGGER + if (bmm150_trigger_mode_init(dev) < 0) { + LOG_ERR("Cannot set up trigger mode."); + return -EINVAL; + } +#endif + return 0; } @@ -686,6 +697,13 @@ static int bmm150_init(const struct device *dev) (BMM150_CONFIG_I2C(inst)), \ (BMM150_CONFIG_SPI(inst))) +#if defined(CONFIG_BMM150_TRIGGER) +#define BMM150_INT_CFG(inst) \ + .drdy_int = GPIO_DT_SPEC_INST_GET(inst, drdy_gpios), +#else +#define BMM150_INT_CFG(inst) +#endif + /* * Main instantiation macro, which selects the correct bus-specific * instantiation macros for the instance. @@ -694,6 +712,7 @@ static int bmm150_init(const struct device *dev) static struct bmm150_data bmm150_data_##inst; \ static const struct bmm150_config bmm150_config_##inst = { \ BMM150_BUS_CFG(inst) \ + BMM150_INT_CFG(inst) \ }; \ \ PM_DEVICE_DT_INST_DEFINE(inst, pm_action); \ diff --git a/drivers/sensor/bmm150/bmm150.h b/drivers/sensor/bmm150/bmm150.h index d00497354a4..47fb3f736cd 100644 --- a/drivers/sensor/bmm150/bmm150.h +++ b/drivers/sensor/bmm150/bmm150.h @@ -157,13 +157,38 @@ struct bmm150_trim_regs { struct bmm150_config { union bmm150_bus bus; const struct bmm150_bus_io *bus_io; + +#ifdef CONFIG_BMM150_TRIGGER + struct gpio_dt_spec drdy_int; +#endif }; struct bmm150_data { - struct k_sem sem; struct bmm150_trim_regs tregs; int rep_xy, rep_z, odr, max_odr; int sample_x, sample_y, sample_z; + +#if defined(CONFIG_BMM150_TRIGGER) + struct gpio_callback gpio_cb; +#endif + +#ifdef CONFIG_BMM150_TRIGGER_OWN_THREAD + struct k_sem sem; +#endif + +#ifdef CONFIG_BMM150_TRIGGER_GLOBAL_THREAD + struct k_work work; +#endif + +#if defined(CONFIG_BMM150_TRIGGER_GLOBAL_THREAD) || \ + defined(CONFIG_BMM150_TRIGGER_DIRECT) + const struct device *dev; +#endif + +#ifdef CONFIG_BMM150_TRIGGER + const struct sensor_trigger *drdy_trigger; + sensor_trigger_handler_t drdy_handler; +#endif /* CONFIG_BMM150_TRIGGER */ }; enum bmm150_axis { @@ -198,6 +223,12 @@ enum bmm150_presets { /* Start-Up Time - from suspend to sleep (Max) */ #define BMM150_START_UP_TIME K_MSEC(3) +int bmm150_trigger_mode_init(const struct device *dev); + +int bmm150_trigger_set(const struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); + int bmm150_reg_update_byte(const struct device *dev, uint8_t reg, uint8_t mask, uint8_t value); diff --git a/drivers/sensor/bmm150/bmm150_trigger.c b/drivers/sensor/bmm150/bmm150_trigger.c new file mode 100644 index 00000000000..edfd5d89b68 --- /dev/null +++ b/drivers/sensor/bmm150/bmm150_trigger.c @@ -0,0 +1,175 @@ +/* Bosch BMM150 pressure sensor + * + * Copyright (c) 2020 Facebook, Inc. and its affiliates + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmm150-ds001.pdf + */ + +#include +#include +#include + +#include "bmm150.h" + +LOG_MODULE_DECLARE(BMM150, CONFIG_SENSOR_LOG_LEVEL); + +static void bmm150_handle_interrupts(const void *arg) +{ + const struct device *dev = (const struct device *)arg; + struct bmm150_data *data = dev->data; + + if (data->drdy_handler) { + data->drdy_handler(dev, data->drdy_trigger); + } +} + +#ifdef CONFIG_BMM150_TRIGGER_OWN_THREAD +static K_THREAD_STACK_DEFINE(bmm150_thread_stack, + CONFIG_BMM150_THREAD_STACK_SIZE); +static struct k_thread bmm150_thread; + +static void bmm150_thread_main(void *arg1, void *unused1, void *unused2) +{ + ARG_UNUSED(unused1); + ARG_UNUSED(unused2); + const struct device *dev = (const struct device *)arg1; + struct bmm150_data *data = dev->data; + + while (1) { + k_sem_take(&data->sem, K_FOREVER); + bmm150_handle_interrupts(dev); + } +} +#endif + +#ifdef CONFIG_BMM150_TRIGGER_GLOBAL_THREAD +static void bmm150_work_handler(struct k_work *work) +{ + struct bmm150_data *data = CONTAINER_OF(work, + struct bmm150_data, + work); + + bmm150_handle_interrupts(data->dev); +} +#endif + +static void bmm150_gpio_callback(const struct device *port, + struct gpio_callback *cb, + uint32_t pin) +{ + struct bmm150_data *data = CONTAINER_OF(cb, + struct bmm150_data, + gpio_cb); + + ARG_UNUSED(port); + ARG_UNUSED(pin); + +#if defined(CONFIG_BMM150_TRIGGER_OWN_THREAD) + k_sem_give(&data->sem); +#elif defined(CONFIG_BMM150_TRIGGER_GLOBAL_THREAD) + k_work_submit(&data->work); +#elif defined(CONFIG_BMM150_TRIGGER_DIRECT) + bmm150_handle_interrupts(data->dev); +#endif +} + +int bmm150_trigger_set( + const struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + uint16_t values[BMM150_AXIS_XYZR_MAX]; + struct bmm150_data *data = dev->data; + const struct bmm150_config *cfg = dev->config; + +#ifdef CONFIG_PM_DEVICE + enum pm_device_state state; + + (void)pm_device_state_get(dev, &state); + if (state != PM_DEVICE_STATE_ACTIVE) { + return -EBUSY; + } +#endif + + if (trig->type != SENSOR_TRIG_DATA_READY) { + return -ENOTSUP; + } + + data->drdy_trigger = trig; + data->drdy_handler = handler; + + if (bmm150_reg_update_byte(dev, + BMM150_REG_INT_DRDY, + BMM150_MASK_DRDY_EN, + (handler != NULL) << BMM150_SHIFT_DRDY_EN) < 0) { + LOG_ERR("Failed to enable DRDY interrupt"); + return -EIO; + } + + /* Clean data registers */ + if (cfg->bus_io->read(&cfg->bus, BMM150_REG_X_L, (uint8_t *)values, sizeof(values)) < 0) { + LOG_ERR("failed to read sample"); + return -EIO; + } + + return 0; +} + +int bmm150_trigger_mode_init(const struct device *dev) +{ + struct bmm150_data *data = dev->data; + const struct bmm150_config *cfg = dev->config; + int ret; + + if (!device_is_ready(cfg->drdy_int.port)) { + LOG_ERR("INT device is not ready"); + return -ENODEV; + } + +#if defined(CONFIG_BMM150_TRIGGER_OWN_THREAD) + k_sem_init(&data->sem, 0, 1); + k_thread_create( + &bmm150_thread, + bmm150_thread_stack, + CONFIG_BMM150_THREAD_STACK_SIZE, + bmm150_thread_main, + (void *)dev, + NULL, + NULL, + K_PRIO_COOP(CONFIG_BMM150_THREAD_PRIORITY), + 0, + K_NO_WAIT); +#elif defined(CONFIG_BMM150_TRIGGER_GLOBAL_THREAD) + k_work_init(&data->work, bmm150_work_handler); +#endif + +#if defined(CONFIG_BMM150_TRIGGER_GLOBAL_THREAD) || \ + defined(CONFIG_BMM150_TRIGGER_DIRECT) + data->dev = dev; +#endif + + ret = gpio_pin_configure_dt(&cfg->drdy_int, GPIO_INPUT); + if (ret < 0) { + return ret; + } + + gpio_init_callback(&data->gpio_cb, + bmm150_gpio_callback, + BIT(cfg->drdy_int.pin)); + + ret = gpio_add_callback(cfg->drdy_int.port, &data->gpio_cb); + if (ret < 0) { + return ret; + } + + ret = gpio_pin_interrupt_configure_dt(&cfg->drdy_int, + GPIO_INT_EDGE_TO_ACTIVE); + if (ret < 0) { + return ret; + } + + return 0; +} diff --git a/drivers/sensor/bq274xx/bq274xx.c b/drivers/sensor/bq274xx/bq274xx.c index e65db8fd29d..27810204798 100644 --- a/drivers/sensor/bq274xx/bq274xx.c +++ b/drivers/sensor/bq274xx/bq274xx.c @@ -321,6 +321,69 @@ static int bq27427_ccgain_quirk(const struct device *dev) return 0; } +static int bq274xx_ensure_chemistry(const struct device *dev) +{ + struct bq274xx_data *data = dev->data; + const struct bq274xx_config *const config = dev->config; + uint16_t chem_id = config->chemistry_id; + + if (chem_id == 0) { + /* No chemistry ID set, rely on the default of the device.*/ + return 0; + } + int ret; + uint16_t val; + + ret = bq274xx_ctrl_reg_write(dev, BQ274XX_CTRL_CHEM_ID); + if (ret < 0) { + LOG_ERR("Unable to write control register"); + return -EIO; + } + + ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_CONTROL, &val); + if (ret < 0) { + LOG_ERR("Unable to read register"); + return -EIO; + } + + LOG_DBG("Chem ID: %04x", val); + + if (val != chem_id) { + /* Only the bq27427 has a configurable Chemistry ID. On bq27421, it depends on the + * variant of the chip, so just error out if the chemistry ID is wrong. + */ + if (data->regs != &bq27427_regs) { + LOG_ERR("Unable to confirm chemistry ID 0x%04x. Device reported 0x%04x", + chem_id, val); + return -EIO; + } + + uint16_t cmd; + + switch (val) { + case BQ27427_CHEM_ID_A: + cmd = BQ27427_CTRL_CHEM_A; + break; + case BQ27427_CHEM_ID_B: + cmd = BQ27427_CTRL_CHEM_B; + break; + case BQ27427_CHEM_ID_C: + cmd = BQ27427_CTRL_CHEM_C; + break; + default: + LOG_ERR("Unsupported chemistry ID 0x%04x", val); + return -EINVAL; + } + + ret = bq274xx_ctrl_reg_write(dev, cmd); + if (ret < 0) { + LOG_ERR("Unable to configure chemistry"); + return -EIO; + } + } + return 0; +} + static int bq274xx_gauge_configure(const struct device *dev) { const struct bq274xx_config *const config = dev->config; @@ -390,6 +453,11 @@ static int bq274xx_gauge_configure(const struct device *dev) } } + ret = bq274xx_ensure_chemistry(dev); + if (ret < 0) { + return ret; + } + ret = bq274xx_mode_cfgupdate(dev, false); if (ret < 0) { return ret; @@ -626,7 +694,6 @@ static int bq274xx_gauge_init(const struct device *dev) struct bq274xx_data *data = dev->data; int ret; uint16_t id; - int32_t delay_remainder_ms; if (!device_is_ready(config->i2c.bus)) { LOG_ERR("I2C bus device not ready"); @@ -640,11 +707,7 @@ static int bq274xx_gauge_init(const struct device *dev) } #endif - delay_remainder_ms = POWER_UP_DELAY_MS - k_uptime_get_32(); - if (delay_remainder_ms > 0) { - LOG_DBG("Power up delay remainder: %dms", delay_remainder_ms); - k_msleep(delay_remainder_ms); - } + k_sleep(K_TIMEOUT_ABS_MS(POWER_UP_DELAY_MS)); ret = bq274xx_get_device_type(dev, &id); if (ret < 0) { @@ -803,6 +866,7 @@ static const struct sensor_driver_api bq274xx_battery_driver_api = { .design_capacity = DT_INST_PROP(index, design_capacity), \ .taper_current = DT_INST_PROP(index, taper_current), \ .terminate_voltage = DT_INST_PROP(index, terminate_voltage), \ + .chemistry_id = DT_INST_PROP_OR(index, chemistry_id, 0), \ .lazy_loading = DT_INST_PROP(index, zephyr_lazy_load), \ }; \ \ diff --git a/drivers/sensor/bq274xx/bq274xx.h b/drivers/sensor/bq274xx/bq274xx.h index ead248a4738..3fbf4f52f08 100644 --- a/drivers/sensor/bq274xx/bq274xx.h +++ b/drivers/sensor/bq274xx/bq274xx.h @@ -9,6 +9,7 @@ #include #include +#include /*** General Constant ***/ #define BQ274XX_UNSEAL_KEY_A 0x8000 /* Unseal code one on BQ27441-G1A and similar */ @@ -59,6 +60,11 @@ #define BQ274XX_CTRL_EXIT_CFGUPDATE 0x0043 #define BQ274XX_CTRL_EXIT_RESIM 0x0044 +/* BQ27427 */ +#define BQ27427_CTRL_CHEM_A 0x0030 +#define BQ27427_CTRL_CHEM_B 0x0031 +#define BQ27427_CTRL_CHEM_C 0x0032 + /*** Extended Data Commands ***/ #define BQ274XX_EXT_OPCONFIG 0x3A /* OpConfig() */ #define BQ274XX_EXT_CAPACITY 0x3C /* DesignCapacity() */ @@ -119,6 +125,7 @@ struct bq274xx_config { #if defined(CONFIG_BQ274XX_PM) || defined(CONFIG_BQ274XX_TRIGGER) struct gpio_dt_spec int_gpios; #endif + uint16_t chemistry_id; bool lazy_loading; }; diff --git a/drivers/sensor/bq274xx/bq274xx_trigger.c b/drivers/sensor/bq274xx/bq274xx_trigger.c index 9b276f3b5ff..40f20e8b955 100644 --- a/drivers/sensor/bq274xx/bq274xx_trigger.c +++ b/drivers/sensor/bq274xx/bq274xx_trigger.c @@ -31,8 +31,13 @@ static void bq274xx_handle_interrupts(const struct device *dev) static K_KERNEL_STACK_DEFINE(bq274xx_thread_stack, CONFIG_BQ274XX_THREAD_STACK_SIZE); static struct k_thread bq274xx_thread; -static void bq274xx_thread_main(struct bq274xx_data *data) +static void bq274xx_thread_main(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct bq274xx_data *data = p1; + while (1) { k_sem_take(&data->sem, K_FOREVER); bq274xx_handle_interrupts(data->dev); @@ -79,7 +84,7 @@ int bq274xx_trigger_mode_init(const struct device *dev) k_thread_create(&bq274xx_thread, bq274xx_thread_stack, CONFIG_BQ274XX_THREAD_STACK_SIZE, - (k_thread_entry_t)bq274xx_thread_main, + bq274xx_thread_main, data, NULL, NULL, K_PRIO_COOP(CONFIG_BQ274XX_THREAD_PRIORITY), 0, K_NO_WAIT); diff --git a/drivers/sensor/ccs811/ccs811_trigger.c b/drivers/sensor/ccs811/ccs811_trigger.c index 29750bd6bb3..5a7ef006d01 100644 --- a/drivers/sensor/ccs811/ccs811_trigger.c +++ b/drivers/sensor/ccs811/ccs811_trigger.c @@ -98,8 +98,13 @@ static void gpio_callback(const struct device *dev, } #ifdef CONFIG_CCS811_TRIGGER_OWN_THREAD -static void irq_thread(struct ccs811_data *drv_data) +static void irq_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct ccs811_data *drv_data = p1; + while (1) { k_sem_take(&drv_data->gpio_sem, K_FOREVER); process_irq(drv_data->dev); @@ -192,7 +197,7 @@ int ccs811_init_interrupt(const struct device *dev) k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_CCS811_THREAD_STACK_SIZE, - (k_thread_entry_t)irq_thread, drv_data, + irq_thread, drv_data, NULL, NULL, K_PRIO_COOP(CONFIG_CCS811_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_CCS811_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/current_amp/CMakeLists.txt b/drivers/sensor/current_amp/CMakeLists.txt new file mode 100644 index 00000000000..81410bdcc71 --- /dev/null +++ b/drivers/sensor/current_amp/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(current_amp.c) diff --git a/drivers/sensor/current_amp/Kconfig b/drivers/sensor/current_amp/Kconfig new file mode 100644 index 00000000000..62ea9bc0d12 --- /dev/null +++ b/drivers/sensor/current_amp/Kconfig @@ -0,0 +1,13 @@ +# Current sense amplifier driver +# +# Copyright (c) 2023 FTP Technologies +# +# SPDX-License-Identifier: Apache-2.0 + +config CURRENT_AMP + bool "Current sense amplifier driver" + default y + depends on DT_HAS_CURRENT_SENSE_AMPLIFIER_ENABLED + depends on ADC + help + Enable current sense amplifier driver. diff --git a/drivers/sensor/current_amp/current_amp.c b/drivers/sensor/current_amp/current_amp.c new file mode 100644 index 00000000000..d760e4b34b0 --- /dev/null +++ b/drivers/sensor/current_amp/current_amp.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2023 FTP Technologies + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT current_sense_amplifier + +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(current_amp, CONFIG_SENSOR_LOG_LEVEL); + +struct current_sense_amplifier_data { + struct adc_sequence sequence; + int16_t raw; +}; + +static int fetch(const struct device *dev, enum sensor_channel chan) +{ + const struct current_sense_amplifier_dt_spec *config = dev->config; + struct current_sense_amplifier_data *data = dev->data; + int ret; + + if ((chan != SENSOR_CHAN_CURRENT) && (chan != SENSOR_CHAN_ALL)) { + return -ENOTSUP; + } + + ret = adc_read_dt(&config->port, &data->sequence); + if (ret != 0) { + LOG_ERR("adc_read: %d", ret); + } + + return ret; +} + +static int get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) +{ + const struct current_sense_amplifier_dt_spec *config = dev->config; + struct current_sense_amplifier_data *data = dev->data; + int32_t raw_val = data->raw; + int32_t i_ma; + int ret; + + __ASSERT_NO_MSG(val != NULL); + + if (chan != SENSOR_CHAN_CURRENT) { + return -ENOTSUP; + } + + ret = adc_raw_to_millivolts_dt(&config->port, &raw_val); + if (ret != 0) { + LOG_ERR("raw_to_mv: %d", ret); + return ret; + } + + i_ma = raw_val; + current_sense_amplifier_scale_dt(config, &i_ma); + + LOG_DBG("%d/%d, %dmV, current:%duA", data->raw, + (1 << data->sequence.resolution) - 1, raw_val, i_ma); + + val->val1 = i_ma / 1000; + val->val2 = i_ma % 1000; + + return 0; +} + +static const struct sensor_driver_api current_api = { + .sample_fetch = fetch, + .channel_get = get, +}; + +#ifdef CONFIG_PM_DEVICE +static int pm_action(const struct device *dev, enum pm_device_action action) +{ + const struct current_sense_amplifier_dt_spec *config = dev->config; + int ret; + + if (config->power_gpio.port == NULL) { + LOG_ERR("PM not supported"); + return -ENOTSUP; + } + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + ret = gpio_pin_set_dt(&config->power_gpio, 1); + if (ret != 0) { + LOG_ERR("failed to set GPIO for PM resume"); + return ret; + } + break; + case PM_DEVICE_ACTION_SUSPEND: + ret = gpio_pin_set_dt(&config->power_gpio, 0); + if (ret != 0) { + LOG_ERR("failed to set GPIO for PM suspend"); + return ret; + } + break; + default: + return -ENOTSUP; + } + + return 0; +} +#endif + +static int current_init(const struct device *dev) +{ + const struct current_sense_amplifier_dt_spec *config = dev->config; + struct current_sense_amplifier_data *data = dev->data; + int ret; + + if (!adc_is_ready_dt(&config->port)) { + LOG_ERR("ADC is not ready"); + return -ENODEV; + } + +#ifdef CONFIG_PM_DEVICE + if (config->power_gpio.port != NULL) { + if (!gpio_is_ready_dt(&config->power_gpio)) { + LOG_ERR("Power GPIO is not ready"); + return -ENODEV; + } + + ret = gpio_pin_configure_dt(&config->power_gpio, GPIO_OUTPUT_ACTIVE); + if (ret != 0) { + LOG_ERR("failed to config GPIO: %d", ret); + return ret; + } + } +#endif + + ret = adc_channel_setup_dt(&config->port); + if (ret != 0) { + LOG_ERR("setup: %d", ret); + return ret; + } + + ret = adc_sequence_init_dt(&config->port, &data->sequence); + if (ret != 0) { + LOG_ERR("sequence init: %d", ret); + return ret; + } + + data->sequence.buffer = &data->raw; + data->sequence.buffer_size = sizeof(data->raw); + + return 0; +} + +#define CURRENT_SENSE_AMPLIFIER_INIT(inst) \ + static struct current_sense_amplifier_data current_amp_##inst##_data; \ + \ + static const struct current_sense_amplifier_dt_spec current_amp_##inst##_config = \ + CURRENT_SENSE_AMPLIFIER_DT_SPEC_GET(DT_DRV_INST(inst)); \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, pm_action); \ + \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, ¤t_init, PM_DEVICE_DT_INST_GET(inst), \ + ¤t_amp_##inst##_data, ¤t_amp_##inst##_config, \ + POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, ¤t_api); + +DT_INST_FOREACH_STATUS_OKAY(CURRENT_SENSE_AMPLIFIER_INIT) diff --git a/drivers/sensor/default_rtio_sensor.c b/drivers/sensor/default_rtio_sensor.c index 55db893f4d8..3f9377c33b3 100644 --- a/drivers/sensor/default_rtio_sensor.c +++ b/drivers/sensor/default_rtio_sensor.c @@ -12,6 +12,12 @@ LOG_MODULE_REGISTER(sensor_compat, CONFIG_SENSOR_LOG_LEVEL); +/* + * Ensure that the size of the generic header aligns with the sensor channel enum. If it doesn't, + * then cores that require aligned memory access will fail to read channel[0]. + */ +BUILD_ASSERT((sizeof(struct sensor_data_generic_header) % sizeof(enum sensor_channel)) == 0); + static void sensor_submit_fallback(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe); static void sensor_iodev_submit(struct rtio_iodev_sqe *iodev_sqe) @@ -22,8 +28,10 @@ static void sensor_iodev_submit(struct rtio_iodev_sqe *iodev_sqe) if (api->submit != NULL) { api->submit(dev, iodev_sqe); - } else { + } else if (!cfg->is_streaming) { sensor_submit_fallback(dev, iodev_sqe); + } else { + rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP); } } @@ -49,6 +57,21 @@ static inline int compute_num_samples(const enum sensor_channel *channels, size_ return num_samples; } +/** + * @brief Compute the required header size + * + * This function takes into account alignment of the q31 values that will follow the header. + * + * @param[in] num_output_samples The number of samples to represent + * @return The number of bytes needed for this sample frame's header + */ +static inline uint32_t compute_header_size(int num_output_samples) +{ + uint32_t size = sizeof(struct sensor_data_generic_header) + + (num_output_samples * sizeof(enum sensor_channel)); + return (size + 3) & ~0x3; +} + /** * @brief Compute the minimum number of bytes needed * @@ -57,8 +80,7 @@ static inline int compute_num_samples(const enum sensor_channel *channels, size_ */ static inline uint32_t compute_min_buf_len(int num_output_samples) { - return sizeof(struct sensor_data_generic_header) + (num_output_samples * sizeof(q31_t)) + - (num_output_samples * sizeof(enum sensor_channel)); + return compute_header_size(num_output_samples) + (num_output_samples * sizeof(q31_t)); } /** @@ -121,8 +143,7 @@ static void sensor_submit_fallback(const struct device *dev, struct rtio_iodev_s header->num_channels = num_output_samples; header->shift = 0; - q31_t *q = (q31_t *)(buf + sizeof(struct sensor_data_generic_header) + - num_output_samples * sizeof(enum sensor_channel)); + q31_t *q = (q31_t *)(buf + compute_header_size(num_output_samples)); /* Populate values, update shift, and set channels */ for (size_t i = 0, sample_idx = 0; i < cfg->count; ++i) { @@ -216,7 +237,7 @@ static void sensor_submit_fallback(const struct device *dev, struct rtio_iodev_s } sample_idx += num_samples; } - LOG_DBG("Total channels in header: %zu", header->num_channels); + LOG_DBG("Total channels in header: %" PRIu32, header->num_channels); rtio_iodev_sqe_ok(iodev_sqe, 0); } @@ -251,66 +272,205 @@ void sensor_processing_with_callback(struct rtio *ctx, sensor_processing_callbac * Default reader can only ever service a single frame at a time. * * @param[in] buffer The data buffer to parse + * @param[in] channel The channel to get the count for + * @param[in] channel_idx The index of the channel * @param[out] frame_count The number of frames in the buffer (always 1) * @return 0 in all cases */ -static int get_frame_count(const uint8_t *buffer, uint16_t *frame_count) +static int get_frame_count(const uint8_t *buffer, enum sensor_channel channel, size_t channel_idx, + uint16_t *frame_count) { - ARG_UNUSED(buffer); - *frame_count = 1; - return 0; + struct sensor_data_generic_header *header = (struct sensor_data_generic_header *)buffer; + size_t count = 0; + + switch (channel) { + case SENSOR_CHAN_ACCEL_XYZ: + channel = SENSOR_CHAN_ACCEL_X; + break; + case SENSOR_CHAN_GYRO_XYZ: + channel = SENSOR_CHAN_GYRO_X; + break; + case SENSOR_CHAN_MAGN_XYZ: + channel = SENSOR_CHAN_MAGN_X; + break; + default: + break; + } + for (size_t i = 0; i < header->num_channels; ++i) { + if (header->channels[i] == channel) { + if (channel_idx == count) { + *frame_count = 1; + return 0; + } + ++count; + } + } + + return -ENOTSUP; } -/** - * @brief Default decoder get the timestamp of the first frame - * - * @param[in] buffer The data buffer to parse - * @param[out] timestamp_ns The timestamp of the first frame - * @return 0 in all cases - */ -static int get_timestamp(const uint8_t *buffer, uint64_t *timestamp_ns) +int sensor_natively_supported_channel_size_info(enum sensor_channel channel, size_t *base_size, + size_t *frame_size) { - *timestamp_ns = ((struct sensor_data_generic_header *)buffer)->timestamp_ns; - return 0; + __ASSERT_NO_MSG(base_size != NULL); + __ASSERT_NO_MSG(frame_size != NULL); + + switch (channel) { + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_ACCEL_XYZ: + case SENSOR_CHAN_GYRO_X: + case SENSOR_CHAN_GYRO_Y: + case SENSOR_CHAN_GYRO_Z: + case SENSOR_CHAN_GYRO_XYZ: + case SENSOR_CHAN_MAGN_X: + case SENSOR_CHAN_MAGN_Y: + case SENSOR_CHAN_MAGN_Z: + case SENSOR_CHAN_MAGN_XYZ: + case SENSOR_CHAN_POS_DX: + case SENSOR_CHAN_POS_DY: + case SENSOR_CHAN_POS_DZ: + *base_size = sizeof(struct sensor_three_axis_data); + *frame_size = sizeof(struct sensor_three_axis_sample_data); + return 0; + case SENSOR_CHAN_DIE_TEMP: + case SENSOR_CHAN_AMBIENT_TEMP: + case SENSOR_CHAN_PRESS: + case SENSOR_CHAN_HUMIDITY: + case SENSOR_CHAN_LIGHT: + case SENSOR_CHAN_IR: + case SENSOR_CHAN_RED: + case SENSOR_CHAN_GREEN: + case SENSOR_CHAN_BLUE: + case SENSOR_CHAN_ALTITUDE: + case SENSOR_CHAN_PM_1_0: + case SENSOR_CHAN_PM_2_5: + case SENSOR_CHAN_PM_10: + case SENSOR_CHAN_DISTANCE: + case SENSOR_CHAN_CO2: + case SENSOR_CHAN_VOC: + case SENSOR_CHAN_GAS_RES: + case SENSOR_CHAN_VOLTAGE: + case SENSOR_CHAN_CURRENT: + case SENSOR_CHAN_POWER: + case SENSOR_CHAN_RESISTANCE: + case SENSOR_CHAN_ROTATION: + case SENSOR_CHAN_RPM: + case SENSOR_CHAN_GAUGE_VOLTAGE: + case SENSOR_CHAN_GAUGE_AVG_CURRENT: + case SENSOR_CHAN_GAUGE_STDBY_CURRENT: + case SENSOR_CHAN_GAUGE_MAX_LOAD_CURRENT: + case SENSOR_CHAN_GAUGE_TEMP: + case SENSOR_CHAN_GAUGE_STATE_OF_CHARGE: + case SENSOR_CHAN_GAUGE_FULL_CHARGE_CAPACITY: + case SENSOR_CHAN_GAUGE_REMAINING_CHARGE_CAPACITY: + case SENSOR_CHAN_GAUGE_NOM_AVAIL_CAPACITY: + case SENSOR_CHAN_GAUGE_FULL_AVAIL_CAPACITY: + case SENSOR_CHAN_GAUGE_AVG_POWER: + case SENSOR_CHAN_GAUGE_STATE_OF_HEALTH: + case SENSOR_CHAN_GAUGE_TIME_TO_EMPTY: + case SENSOR_CHAN_GAUGE_TIME_TO_FULL: + case SENSOR_CHAN_GAUGE_DESIGN_VOLTAGE: + case SENSOR_CHAN_GAUGE_DESIRED_VOLTAGE: + case SENSOR_CHAN_GAUGE_DESIRED_CHARGING_CURRENT: + *base_size = sizeof(struct sensor_q31_data); + *frame_size = sizeof(struct sensor_q31_sample_data); + return 0; + case SENSOR_CHAN_PROX: + *base_size = sizeof(struct sensor_byte_data); + *frame_size = sizeof(struct sensor_byte_sample_data); + return 0; + case SENSOR_CHAN_GAUGE_CYCLE_COUNT: + *base_size = sizeof(struct sensor_uint64_data); + *frame_size = sizeof(struct sensor_uint64_sample_data); + return 0; + default: + return -ENOTSUP; + } } -/** - * @brief Default decoder get the bitshift of the given channel (if possible) - * - * @param[in] buffer The data buffer to parse - * @param[in] channel_type The channel to query - * @param[out] shift The bitshift for the q31 value - * @return 0 on success - * @return -EINVAL if the @p channel_type couldn't be found - */ -static int get_shift(const uint8_t *buffer, enum sensor_channel channel_type, int8_t *shift) +static int get_q31_value(const struct sensor_data_generic_header *header, const q31_t *values, + enum sensor_channel channel, size_t channel_idx, q31_t *out) { - struct sensor_data_generic_header *header = (struct sensor_data_generic_header *)buffer; + size_t count = 0; - ARG_UNUSED(channel_type); - *shift = header->shift; - return 0; + for (size_t i = 0; i < header->num_channels; ++i) { + if (channel != header->channels[i]) { + continue; + } + if (count == channel_idx) { + *out = values[i]; + return 0; + } + ++count; + } + return -EINVAL; +} + +static int decode_three_axis(const struct sensor_data_generic_header *header, const q31_t *values, + struct sensor_three_axis_data *data_out, enum sensor_channel x, + enum sensor_channel y, enum sensor_channel z, size_t channel_idx) +{ + int rc; + + data_out->header.base_timestamp_ns = header->timestamp_ns; + data_out->header.reading_count = 1; + data_out->shift = header->shift; + data_out->readings[0].timestamp_delta = 0; + + rc = get_q31_value(header, values, x, channel_idx, &data_out->readings[0].values[0]); + if (rc < 0) { + return rc; + } + rc = get_q31_value(header, values, y, channel_idx, &data_out->readings[0].values[1]); + if (rc < 0) { + return rc; + } + rc = get_q31_value(header, values, z, channel_idx, &data_out->readings[0].values[2]); + if (rc < 0) { + return rc; + } + return 1; +} + +static int decode_q31(const struct sensor_data_generic_header *header, const q31_t *values, + struct sensor_q31_data *data_out, enum sensor_channel channel, + size_t channel_idx) +{ + int rc; + + data_out->header.base_timestamp_ns = header->timestamp_ns; + data_out->header.reading_count = 1; + data_out->shift = header->shift; + data_out->readings[0].timestamp_delta = 0; + + rc = get_q31_value(header, values, channel, channel_idx, &data_out->readings[0].value); + if (rc < 0) { + return rc; + } + return 1; } /** - * @brief Default decoder decode N samples + * @brief Decode up to N samples from the buffer * - * Decode up to N samples starting at the provided @p fit and @p cit. The appropriate channel types - * and q31 values will be placed in @p values and @p channels respectively. + * This function will never wrap frames. If 1 channel is available in the current frame and + * @p max_count is 2, only 1 channel will be decoded and the frame iterator will be modified + * so that the next call to decode will begin at the next frame. * - * @param[in] buffer The data buffer to decode - * @param[in,out] fit The starting frame iterator - * @param[in,out] cit The starting channel iterator - * @param[out] channels The decoded channel types - * @param[out] values The decoded q31 values - * @param[in] max_count The maximum number of values to decode - * @return > 0 The number of decoded values - * @return 0 Nothing else to decode on this @p buffer - * @return < 0 Error + * @param[in] buffer The buffer provided on the :c:struct:`rtio` context + * @param[in] channel The channel to decode + * @param[in] channel_idx The index of the channel + * @param[in,out] fit The current frame iterator + * @param[in] max_count The maximum number of channels to decode. + * @param[out] data_out The decoded data + * @return 0 no more samples to decode + * @return >0 the number of decoded frames + * @return <0 on error */ -static int decode(const uint8_t *buffer, sensor_frame_iterator_t *fit, - sensor_channel_iterator_t *cit, enum sensor_channel *channels, q31_t *values, - uint8_t max_count) +static int decode(const uint8_t *buffer, enum sensor_channel channel, size_t channel_idx, + uint32_t *fit, uint16_t max_count, void *data_out) { const struct sensor_data_generic_header *header = (const struct sensor_data_generic_header *)buffer; @@ -319,32 +479,92 @@ static int decode(const uint8_t *buffer, sensor_frame_iterator_t *fit, header->num_channels * sizeof(enum sensor_channel)); int count = 0; - if (*fit != 0 || *cit >= header->num_channels) { + if (*fit != 0 || max_count < 1) { return -EINVAL; } - /* Skip invalid channels */ - while (*cit < header->num_channels && header->channels[*cit] == SENSOR_CHAN_MAX) { - *cit += 1; + /* Check for 3d channel mappings */ + switch (channel) { + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_ACCEL_XYZ: + count = decode_three_axis(header, q, data_out, SENSOR_CHAN_ACCEL_X, + SENSOR_CHAN_ACCEL_Y, SENSOR_CHAN_ACCEL_Z, channel_idx); + break; + case SENSOR_CHAN_GYRO_X: + case SENSOR_CHAN_GYRO_Y: + case SENSOR_CHAN_GYRO_Z: + case SENSOR_CHAN_GYRO_XYZ: + count = decode_three_axis(header, q, data_out, SENSOR_CHAN_GYRO_X, + SENSOR_CHAN_GYRO_Y, SENSOR_CHAN_GYRO_Z, channel_idx); + break; + case SENSOR_CHAN_MAGN_X: + case SENSOR_CHAN_MAGN_Y: + case SENSOR_CHAN_MAGN_Z: + case SENSOR_CHAN_MAGN_XYZ: + count = decode_three_axis(header, q, data_out, SENSOR_CHAN_MAGN_X, + SENSOR_CHAN_MAGN_Y, SENSOR_CHAN_MAGN_Z, channel_idx); + break; + case SENSOR_CHAN_POS_DX: + case SENSOR_CHAN_POS_DY: + case SENSOR_CHAN_POS_DZ: + count = decode_three_axis(header, q, data_out, SENSOR_CHAN_POS_DX, + SENSOR_CHAN_POS_DY, SENSOR_CHAN_POS_DZ, channel_idx); + break; + case SENSOR_CHAN_DIE_TEMP: + case SENSOR_CHAN_AMBIENT_TEMP: + case SENSOR_CHAN_PRESS: + case SENSOR_CHAN_HUMIDITY: + case SENSOR_CHAN_LIGHT: + case SENSOR_CHAN_IR: + case SENSOR_CHAN_RED: + case SENSOR_CHAN_GREEN: + case SENSOR_CHAN_BLUE: + case SENSOR_CHAN_ALTITUDE: + case SENSOR_CHAN_PM_1_0: + case SENSOR_CHAN_PM_2_5: + case SENSOR_CHAN_PM_10: + case SENSOR_CHAN_DISTANCE: + case SENSOR_CHAN_CO2: + case SENSOR_CHAN_VOC: + case SENSOR_CHAN_GAS_RES: + case SENSOR_CHAN_VOLTAGE: + case SENSOR_CHAN_CURRENT: + case SENSOR_CHAN_POWER: + case SENSOR_CHAN_RESISTANCE: + case SENSOR_CHAN_ROTATION: + case SENSOR_CHAN_RPM: + case SENSOR_CHAN_GAUGE_VOLTAGE: + case SENSOR_CHAN_GAUGE_AVG_CURRENT: + case SENSOR_CHAN_GAUGE_STDBY_CURRENT: + case SENSOR_CHAN_GAUGE_MAX_LOAD_CURRENT: + case SENSOR_CHAN_GAUGE_TEMP: + case SENSOR_CHAN_GAUGE_STATE_OF_CHARGE: + case SENSOR_CHAN_GAUGE_FULL_CHARGE_CAPACITY: + case SENSOR_CHAN_GAUGE_REMAINING_CHARGE_CAPACITY: + case SENSOR_CHAN_GAUGE_NOM_AVAIL_CAPACITY: + case SENSOR_CHAN_GAUGE_FULL_AVAIL_CAPACITY: + case SENSOR_CHAN_GAUGE_AVG_POWER: + case SENSOR_CHAN_GAUGE_STATE_OF_HEALTH: + case SENSOR_CHAN_GAUGE_TIME_TO_EMPTY: + case SENSOR_CHAN_GAUGE_TIME_TO_FULL: + case SENSOR_CHAN_GAUGE_DESIGN_VOLTAGE: + case SENSOR_CHAN_GAUGE_DESIRED_VOLTAGE: + case SENSOR_CHAN_GAUGE_DESIRED_CHARGING_CURRENT: + count = decode_q31(header, q, data_out, channel, channel_idx); + break; + default: + break; } - - for (; *cit < header->num_channels && count < max_count; ++count) { - channels[count] = header->channels[*cit]; - values[count] = q[*cit]; - LOG_DBG("Decoding q[%u]@%p=%d", *cit, (void *)&q[*cit], q[*cit]); - *cit += 1; - } - - if (*cit >= header->num_channels) { + if (count > 0) { *fit = 1; - *cit = 0; } return count; } const struct sensor_decoder_api __sensor_default_decoder = { .get_frame_count = get_frame_count, - .get_timestamp = get_timestamp, - .get_shift = get_shift, + .get_size_info = sensor_natively_supported_channel_size_info, .decode = decode, }; diff --git a/drivers/sensor/ds18b20/CMakeLists.txt b/drivers/sensor/ds18b20/CMakeLists.txt index d95181e74c1..e7a2a706f86 100644 --- a/drivers/sensor/ds18b20/CMakeLists.txt +++ b/drivers/sensor/ds18b20/CMakeLists.txt @@ -2,4 +2,4 @@ zephyr_library() -zephyr_library_sources_ifdef(CONFIG_DS18B20 ds18b20.c) +zephyr_library_sources(ds18b20.c) diff --git a/drivers/sensor/explorir_m/CMakeLists.txt b/drivers/sensor/explorir_m/CMakeLists.txt new file mode 100644 index 00000000000..71125b505f3 --- /dev/null +++ b/drivers/sensor/explorir_m/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(explorir_m.c) diff --git a/drivers/sensor/explorir_m/Kconfig b/drivers/sensor/explorir_m/Kconfig new file mode 100644 index 00000000000..02806bf82a8 --- /dev/null +++ b/drivers/sensor/explorir_m/Kconfig @@ -0,0 +1,13 @@ +# ExplorIR-M CO2 sensor configuration options + +# Copyright (c) 2023, Vitrolife A/S +# SPDX-License-Identifier: Apache-2.0 + +config EXPLORIR_M + bool "ExplorIR-M CO2 Sensor" + default y + depends on DT_HAS_GSS_EXPLORIR_M_ENABLED + depends on UART_INTERRUPT_DRIVEN + select UART + help + Enable driver for ExplorIR-M CO2 Sensor. diff --git a/drivers/sensor/explorir_m/explorir_m.c b/drivers/sensor/explorir_m/explorir_m.c new file mode 100644 index 00000000000..058c43faf2b --- /dev/null +++ b/drivers/sensor/explorir_m/explorir_m.c @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2023, Vitrolife A/S + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.gassensing.co.uk/wp-content/uploads/2023/05/ExplorIR-M-Data-Sheet-Rev-4.13_3.pdf + * + */ + +#define DT_DRV_COMPAT gss_explorir_m + +#include + +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(explorir_m_sensor, CONFIG_SENSOR_LOG_LEVEL); + +#define EXPLORIR_M_BEGIN_CHAR ' ' + +#define EXPLORIR_M_SET_FILTER_CHAR 'A' +#define EXPLORIR_M_GET_FILTER_CHAR 'a' +#define EXPLORIR_M_MODE_CHAR 'K' +#define EXPLORIR_M_CO2_FILTERED_CHAR 'Z' +#define EXPLORIR_M_SCALING_CHAR '.' +#define EXPLORIR_M_NOT_RECOGNISED_CHAR '?' + +#define EXPLORIR_M_SEPARATOR_CHAR ' ' +#define EXPLORIR_M_PRE_END_CHAR '\r' +#define EXPLORIR_M_END_CHAR '\n' + +#define EXPLORIR_M_TYPE_INDEX 1 +#define EXPLORIR_M_VALUE_INDEX 3 + +#define EXPLORIR_M_BUFFER_LENGTH 16 + +#define EXPLORIR_M_MAX_RESPONSE_DELAY 200 /* Add margin to the specified 100 in datasheet */ +#define EXPLORIR_M_CO2_VALID_DELAY 1200 + +struct explorir_m_data { + struct k_mutex uart_mutex; + struct k_sem uart_rx_sem; + uint16_t filtered; + uint16_t scaling; + uint8_t read_index; + uint8_t read_buffer[EXPLORIR_M_BUFFER_LENGTH]; +}; + +struct explorir_m_cfg { + const struct device *uart_dev; + uart_irq_callback_user_data_t cb; +}; + +enum explorir_m_uart_set_usage { + EXPLORIR_M_SET_NONE, + EXPLORIR_M_SET_VAL_ONE, + EXPLORIR_M_SET_VAL_ONE_TWO, +}; + +enum EXPLORIR_M_MODE { + EXPLORIR_M_MODE_COMMAND, + EXPLORIR_M_MODE_STREAM, + EXPLORIR_M_MODE_POLL, +}; + +static void explorir_m_uart_flush(const struct device *uart_dev) +{ + uint8_t tmp; + + while (uart_fifo_read(uart_dev, &tmp, 1) > 0) { + continue; + } +} + +static void explorir_m_uart_flush_until_end(const struct device *uart_dev) +{ + uint8_t tmp; + uint32_t uptime; + + uptime = k_uptime_get_32(); + do { + uart_poll_in(uart_dev, &tmp); + } while (tmp != EXPLORIR_M_END_CHAR && + k_uptime_get_32() - uptime < EXPLORIR_M_MAX_RESPONSE_DELAY); +} + +static void explorir_m_buffer_reset(struct explorir_m_data *data) +{ + memset(data->read_buffer, 0, data->read_index); + data->read_index = 0; +} + +static int explorir_m_buffer_verify(const struct explorir_m_data *data, char type) +{ + char buffer_type = data->read_buffer[EXPLORIR_M_TYPE_INDEX]; + + if (data->read_buffer[0] == EXPLORIR_M_NOT_RECOGNISED_CHAR) { + LOG_WRN("Sensor did not recognise the command"); + return -EIO; + } + + if (buffer_type != type) { + LOG_WRN("Expected type %c but got %c", type, buffer_type); + return -EIO; + } + + if (data->read_buffer[0] != EXPLORIR_M_BEGIN_CHAR || + data->read_buffer[2] != EXPLORIR_M_SEPARATOR_CHAR || + data->read_buffer[data->read_index - 2] != EXPLORIR_M_PRE_END_CHAR) { + LOG_HEXDUMP_WRN(data->read_buffer, data->read_index, "Invalid buffer"); + return -EIO; + } + + return 0; +} + +static int explorir_m_buffer_process(struct explorir_m_data *data, char type, + struct sensor_value *val) +{ + if (explorir_m_buffer_verify(data, type) != 0) { + return -EIO; + } + + switch (type) { + case EXPLORIR_M_SET_FILTER_CHAR: + case EXPLORIR_M_MODE_CHAR: + break; + + case EXPLORIR_M_CO2_FILTERED_CHAR: + data->scaling = strtol(&data->read_buffer[EXPLORIR_M_VALUE_INDEX], NULL, 10); + break; + + case EXPLORIR_M_SCALING_CHAR: + data->filtered = strtol(&data->read_buffer[EXPLORIR_M_VALUE_INDEX], NULL, 10); + break; + + case EXPLORIR_M_GET_FILTER_CHAR: + val->val1 = strtol(&data->read_buffer[EXPLORIR_M_VALUE_INDEX], NULL, 10); + break; + + default: + LOG_ERR("Unknown type %c/0x%02x", type, type); + return -EIO; + } + + return 0; +} + +static void explorir_m_uart_isr(const struct device *uart_dev, void *user_data) +{ + const struct device *dev = user_data; + struct explorir_m_data *data = dev->data; + int rc, read_len; + + if (!device_is_ready(uart_dev)) { + LOG_DBG("UART device is not ready"); + return; + } + + if (!uart_irq_update(uart_dev)) { + LOG_DBG("Unable to process interrupts"); + return; + } + + if (!uart_irq_rx_ready(uart_dev)) { + LOG_DBG("No RX data"); + return; + } + + read_len = EXPLORIR_M_BUFFER_LENGTH - data->read_index; + rc = uart_fifo_read(uart_dev, &data->read_buffer[data->read_index], read_len); + + if (rc < 0 || rc == read_len) { + LOG_ERR("UART read failed: %d", rc < 0 ? rc : -ERANGE); + explorir_m_uart_flush(uart_dev); + LOG_HEXDUMP_WRN(data->read_buffer, data->read_index, "Discarding"); + explorir_m_buffer_reset(data); + } else { + data->read_index += rc; + + if (data->read_buffer[data->read_index - 1] != EXPLORIR_M_END_CHAR) { + return; + } + } + + k_sem_give(&data->uart_rx_sem); +} + +static void explorir_m_uart_terminate(const struct device *uart_dev) +{ + uart_poll_out(uart_dev, EXPLORIR_M_PRE_END_CHAR); + uart_poll_out(uart_dev, EXPLORIR_M_END_CHAR); +} + +static int explorir_m_await_receive(struct explorir_m_data *data) +{ + int rc = k_sem_take(&data->uart_rx_sem, K_MSEC(EXPLORIR_M_MAX_RESPONSE_DELAY)); + + /* Reset semaphore if sensor did not respond within maximum specified response time */ + if (rc == -EAGAIN) { + k_sem_reset(&data->uart_rx_sem); + } + + return rc; +} + +static int explorir_m_uart_transceive(const struct device *dev, char type, struct sensor_value *val, + enum explorir_m_uart_set_usage set) +{ + const struct explorir_m_cfg *cfg = dev->config; + struct explorir_m_data *data = dev->data; + char buf[EXPLORIR_M_BUFFER_LENGTH]; + int rc, len; + + if (val == NULL && set != EXPLORIR_M_SET_NONE) { + LOG_ERR("val is NULL but set is not NONE"); + return -EINVAL; + } + + k_mutex_lock(&data->uart_mutex, K_FOREVER); + + explorir_m_buffer_reset(data); + + uart_poll_out(cfg->uart_dev, type); + + if (set == EXPLORIR_M_SET_VAL_ONE) { + len = snprintf(buf, EXPLORIR_M_BUFFER_LENGTH, "%c%u", EXPLORIR_M_SEPARATOR_CHAR, + val->val1); + } else if (set == EXPLORIR_M_SET_VAL_ONE_TWO) { + len = snprintf(buf, EXPLORIR_M_BUFFER_LENGTH, "%c%u%c%u", EXPLORIR_M_SEPARATOR_CHAR, + val->val1, EXPLORIR_M_SEPARATOR_CHAR, val->val2); + } else { + len = 0; + } + + if (len == EXPLORIR_M_BUFFER_LENGTH) { + LOG_WRN("Set value truncated"); + } + for (int i = 0; i != len; i++) { + uart_poll_out(cfg->uart_dev, buf[i]); + } + + explorir_m_uart_terminate(cfg->uart_dev); + + rc = explorir_m_await_receive(data); + if (rc != 0) { + LOG_WRN("%c did not receive a response: %d", type, rc); + } + + if (rc == 0) { + rc = explorir_m_buffer_process(data, type, val); + } + + k_mutex_unlock(&data->uart_mutex); + + return rc; +} + +static int explorir_m_attr_get(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, struct sensor_value *val) +{ + if (chan != SENSOR_CHAN_CO2) { + return -ENOTSUP; + } + + switch (attr) { + case SENSOR_ATTR_EXPLORIR_M_FILTER: + return explorir_m_uart_transceive(dev, EXPLORIR_M_GET_FILTER_CHAR, val, + EXPLORIR_M_SET_NONE); + default: + return -ENOTSUP; + } +} + +static int explorir_m_attr_set(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ + if (chan != SENSOR_CHAN_CO2) { + return -ENOTSUP; + } + + switch (attr) { + case SENSOR_ATTR_EXPLORIR_M_FILTER: + if (val->val1 < 0 || val->val1 > 255) { + return -ERANGE; + } + return explorir_m_uart_transceive(dev, EXPLORIR_M_SET_FILTER_CHAR, + (struct sensor_value *)val, + EXPLORIR_M_SET_VAL_ONE); + default: + return -ENOTSUP; + } +} + +static int explorir_m_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + if (chan != SENSOR_CHAN_CO2 && chan != SENSOR_CHAN_ALL) { + return -ENOTSUP; + } + + return explorir_m_uart_transceive(dev, EXPLORIR_M_CO2_FILTERED_CHAR, NULL, + EXPLORIR_M_SET_NONE); +} + +static int explorir_m_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + struct explorir_m_data *data = dev->data; + + if (chan != SENSOR_CHAN_CO2) { + return -ENOTSUP; + } + + if (k_uptime_get() < EXPLORIR_M_CO2_VALID_DELAY) { + return -EAGAIN; + } + + val->val1 = data->filtered * data->scaling; + val->val2 = 0; + + return 0; +} + +static const struct sensor_driver_api explorir_m_api_funcs = { + .attr_set = explorir_m_attr_set, + .attr_get = explorir_m_attr_get, + .sample_fetch = explorir_m_sample_fetch, + .channel_get = explorir_m_channel_get, +}; + +static int explorir_m_init(const struct device *dev) +{ + const struct explorir_m_cfg *cfg = dev->config; + struct explorir_m_data *data = dev->data; + struct sensor_value val; + int rc; + + LOG_DBG("Initializing %s", dev->name); + + if (!device_is_ready(cfg->uart_dev)) { + return -ENODEV; + } + + k_mutex_init(&data->uart_mutex); + k_sem_init(&data->uart_rx_sem, 0, 1); + + uart_irq_rx_disable(cfg->uart_dev); + uart_irq_tx_disable(cfg->uart_dev); + + rc = uart_irq_callback_user_data_set(cfg->uart_dev, cfg->cb, (void *)dev); + if (rc != 0) { + LOG_ERR("UART IRQ setup failed: %d", rc); + return rc; + } + + /* Terminate garbled tx due to GPIO setup or crash during unfinished send */ + explorir_m_uart_terminate(cfg->uart_dev); + explorir_m_uart_flush_until_end(cfg->uart_dev); + + uart_irq_rx_enable(cfg->uart_dev); + + val.val1 = EXPLORIR_M_MODE_POLL; + explorir_m_uart_transceive(dev, EXPLORIR_M_MODE_CHAR, &val, EXPLORIR_M_SET_VAL_ONE); + explorir_m_uart_transceive(dev, EXPLORIR_M_SCALING_CHAR, NULL, EXPLORIR_M_SET_NONE); + + return rc; +} + +#define EXPLORIR_M_INIT(n) \ + \ + static struct explorir_m_data explorir_m_data_##n; \ + \ + static const struct explorir_m_cfg explorir_m_cfg_##n = { \ + .uart_dev = DEVICE_DT_GET(DT_INST_BUS(n)), \ + .cb = explorir_m_uart_isr, \ + }; \ + \ + SENSOR_DEVICE_DT_INST_DEFINE(n, explorir_m_init, NULL, &explorir_m_data_##n, \ + &explorir_m_cfg_##n, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &explorir_m_api_funcs); + +DT_INST_FOREACH_STATUS_OKAY(EXPLORIR_M_INIT) diff --git a/drivers/sensor/f75303/CMakeLists.txt b/drivers/sensor/f75303/CMakeLists.txt new file mode 100644 index 00000000000..9441b13f054 --- /dev/null +++ b/drivers/sensor/f75303/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() +zephyr_library_sources(f75303.c) +zephyr_library_sources_ifdef(CONFIG_EMUL_F75303 f75303_emul.c) diff --git a/drivers/sensor/f75303/Kconfig b/drivers/sensor/f75303/Kconfig new file mode 100644 index 00000000000..31c3865275d --- /dev/null +++ b/drivers/sensor/f75303/Kconfig @@ -0,0 +1,22 @@ +# F75303 temperature sensor configuration options + +# Copyright (c) 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +config F75303 + bool "F75303 Temperature Sensor" + default y + depends on DT_HAS_FINTEK_F75303_ENABLED + select I2C + help + Enable the driver for Fintek F75303 Temperature Sensor. + This device has three temperature channels - one local (on-chip), + and two remote. + +config EMUL_F75303 + bool "Emulator for F75303" + default y + depends on F75303 + depends on EMUL + help + Enable the hardware emulator for F75303 Temperature Sensor. diff --git a/drivers/sensor/f75303/f75303.c b/drivers/sensor/f75303/f75303.c new file mode 100644 index 00000000000..dd656fc26e0 --- /dev/null +++ b/drivers/sensor/f75303/f75303.c @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT fintek_f75303 + +#include +#include +#include +#include +#include +#include +#include +#include "f75303.h" + +#define F75303_SAMPLE_INT_SHIFT 3 +#define F75303_SAMPLE_FRAC_MASK GENMASK(2, 0) +#define F75303_SAMPLE_MICROCELSIUS_PER_BIT 125000 + +LOG_MODULE_REGISTER(F75303, CONFIG_SENSOR_LOG_LEVEL); + +static int f75303_fetch(const struct i2c_dt_spec *i2c, + uint8_t off_h, uint8_t off_l, uint16_t *sample) +{ + uint8_t val_h; + uint8_t val_l; + int res; + + res = i2c_reg_read_byte_dt(i2c, off_h, &val_h); + if (res) { + return res; + } + + res = i2c_reg_read_byte_dt(i2c, off_l, &val_l); + if (res) { + return res; + } + + *sample = val_h << 3 | val_l >> 5; + + return 0; +} + +static int f75303_fetch_local(const struct device *dev) +{ + struct f75303_data *data = dev->data; + const struct f75303_config *config = dev->config; + + return f75303_fetch(&config->i2c, + F75303_LOCAL_TEMP_H, + F75303_LOCAL_TEMP_L, + &data->sample_local); +} + +static int f75303_fetch_remote1(const struct device *dev) +{ + struct f75303_data *data = dev->data; + const struct f75303_config *config = dev->config; + + return f75303_fetch(&config->i2c, + F75303_REMOTE1_TEMP_H, + F75303_REMOTE1_TEMP_L, + &data->sample_remote1); +} + +static int f75303_fetch_remote2(const struct device *dev) +{ + struct f75303_data *data = dev->data; + const struct f75303_config *config = dev->config; + + return f75303_fetch(&config->i2c, + F75303_REMOTE2_TEMP_H, + F75303_REMOTE2_TEMP_L, + &data->sample_remote2); +} + +static int f75303_sample_fetch(const struct device *dev, + enum sensor_channel chan) +{ + enum pm_device_state pm_state; + int res; + + (void)pm_device_state_get(dev, &pm_state); + if (pm_state != PM_DEVICE_STATE_ACTIVE) { + return -EIO; + } + + switch ((uint32_t)chan) { + case SENSOR_CHAN_ALL: + res = f75303_fetch_local(dev); + if (res) { + break; + } + res = f75303_fetch_remote1(dev); + if (res) { + break; + } + res = f75303_fetch_remote2(dev); + break; + case SENSOR_CHAN_AMBIENT_TEMP: + return f75303_fetch_local(dev); + case SENSOR_CHAN_F75303_REMOTE1: + return f75303_fetch_remote1(dev); + case SENSOR_CHAN_F75303_REMOTE2: + return f75303_fetch_remote2(dev); + default: + return -ENOTSUP; + } + + return res; +} + +static int f75303_channel_get(const struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + struct f75303_data *data = dev->data; + uint16_t sample; + + switch ((uint32_t)chan) { + case SENSOR_CHAN_AMBIENT_TEMP: + sample = data->sample_local; + break; + case SENSOR_CHAN_F75303_REMOTE1: + sample = data->sample_remote1; + break; + case SENSOR_CHAN_F75303_REMOTE2: + sample = data->sample_remote2; + break; + default: + return -ENOTSUP; + } + + /* + * The reading is given in steps of 0.125 degrees celsius, i.e. the + * temperature in degrees celsius is equal to sample / 8. + */ + val->val1 = sample >> F75303_SAMPLE_INT_SHIFT; + val->val2 = (sample & F75303_SAMPLE_FRAC_MASK) * F75303_SAMPLE_MICROCELSIUS_PER_BIT; + + return 0; +} + +static const struct sensor_driver_api f75303_driver_api = { + .sample_fetch = f75303_sample_fetch, + .channel_get = f75303_channel_get, +}; + +static int f75303_init(const struct device *dev) +{ + const struct f75303_config *config = dev->config; + int res = 0; + + if (!i2c_is_ready_dt(&config->i2c)) { + LOG_ERR("I2C device not ready"); + return -ENODEV; + } + +#ifdef CONFIG_PM_DEVICE_RUNTIME + pm_device_init_suspended(dev); + + res = pm_device_runtime_enable(dev); + if (res) { + LOG_ERR("Failed to enable runtime power management"); + } +#endif + + return res; +} + +#ifdef CONFIG_PM_DEVICE +static int f75303_pm_action(const struct device *dev, enum pm_device_action action) +{ + switch (action) { + case PM_DEVICE_ACTION_TURN_ON: + case PM_DEVICE_ACTION_RESUME: + case PM_DEVICE_ACTION_TURN_OFF: + case PM_DEVICE_ACTION_SUSPEND: + return 0; + default: + return -ENOTSUP; + } +} +#endif + +#define F75303_INST(inst) \ + static struct f75303_data f75303_data_##inst; \ + static const struct f75303_config f75303_config_##inst = { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + }; \ + PM_DEVICE_DT_INST_DEFINE(inst, f75303_pm_action); \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, f75303_init, PM_DEVICE_DT_INST_GET(inst), \ + &f75303_data_##inst, &f75303_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &f75303_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(F75303_INST) diff --git a/drivers/sensor/f75303/f75303.h b/drivers/sensor/f75303/f75303.h new file mode 100644 index 00000000000..8b7ceb64748 --- /dev/null +++ b/drivers/sensor/f75303/f75303.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_F75303_F75303_H_ +#define ZEPHYR_DRIVERS_SENSOR_F75303_F75303_H_ + +#include +#include + +#define F75303_LOCAL_TEMP_H 0x00 +#define F75303_REMOTE1_TEMP_H 0x01 +#define F75303_REMOTE1_TEMP_L 0x10 +#define F75303_REMOTE2_TEMP_H 0x23 +#define F75303_REMOTE2_TEMP_L 0x24 +#define F75303_LOCAL_TEMP_L 0x29 + +struct f75303_data { + uint16_t sample_local; + uint16_t sample_remote1; + uint16_t sample_remote2; +}; + +struct f75303_config { + struct i2c_dt_spec i2c; +}; + +#endif diff --git a/drivers/sensor/f75303/f75303_emul.c b/drivers/sensor/f75303/f75303_emul.c new file mode 100644 index 00000000000..3e33a7b6f7b --- /dev/null +++ b/drivers/sensor/f75303/f75303_emul.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT fintek_f75303 + +#include +#include +#include +#include +#include +#include +#include +#include "f75303.h" + +LOG_MODULE_DECLARE(F75303, CONFIG_SENSOR_LOG_LEVEL); + +#define NUM_REGS 128 + +struct f75303_emul_data { + uint8_t reg[NUM_REGS]; +}; + +struct f75303_emul_cfg { +}; + +static void f75303_emul_set_reg(const struct emul *target, uint8_t reg, uint8_t val) +{ + struct f75303_emul_data *data = target->data; + + __ASSERT_NO_MSG(reg < NUM_REGS); + data->reg[reg] = val; +} + +static uint8_t f75303_emul_get_reg(const struct emul *target, uint8_t reg) +{ + struct f75303_emul_data *data = target->data; + + __ASSERT_NO_MSG(reg < NUM_REGS); + return data->reg[reg]; +} + +static void f75303_emul_reset(const struct emul *target) +{ + struct f75303_emul_data *data = target->data; + + memset(data->reg, 0, NUM_REGS); +} + +static int f75303_emul_transfer_i2c(const struct emul *target, struct i2c_msg *msgs, + int num_msgs, int addr) +{ + /* Largely copied from emul_bmi160.c */ + unsigned int val; + int reg; + + __ASSERT_NO_MSG(msgs && num_msgs); + + i2c_dump_msgs_rw(target->dev, msgs, num_msgs, addr, false); + switch (num_msgs) { + case 2: + if (msgs->flags & I2C_MSG_READ) { + LOG_ERR("Unexpected read"); + return -EIO; + } + if (msgs->len != 1) { + LOG_ERR("Unexpected msg0 length %d", msgs->len); + return -EIO; + } + reg = msgs->buf[0]; + + /* Now process the 'read' part of the message */ + msgs++; + if (msgs->flags & I2C_MSG_READ) { + switch (msgs->len) { + case 1: + val = f75303_emul_get_reg(target, reg); + msgs->buf[0] = val; + break; + default: + LOG_ERR("Unexpected msg1 length %d", msgs->len); + return -EIO; + } + } else { + if (msgs->len != 1) { + LOG_ERR("Unexpected msg1 length %d", msgs->len); + } + f75303_emul_set_reg(target, reg, msgs->buf[0]); + } + break; + default: + LOG_ERR("Invalid number of messages: %d", num_msgs); + return -EIO; + } + + return 0; +} + +static int f75303_emul_init(const struct emul *target, const struct device *parent) +{ + f75303_emul_reset(target); + return 0; +} + +static int f75303_emul_set_channel(const struct emul *target, enum sensor_channel chan, + q31_t value, int8_t shift) +{ + struct f75303_emul_data *data = target->data; + int64_t scaled_value; + int32_t millicelsius; + int32_t reg_value; + uint8_t reg_h, reg_l; + + switch ((int32_t)chan) { + case SENSOR_CHAN_AMBIENT_TEMP: + reg_h = F75303_LOCAL_TEMP_H; + reg_l = F75303_LOCAL_TEMP_L; + break; + case SENSOR_CHAN_F75303_REMOTE1: + reg_h = F75303_REMOTE1_TEMP_H; + reg_l = F75303_REMOTE1_TEMP_L; + break; + case SENSOR_CHAN_F75303_REMOTE2: + reg_h = F75303_REMOTE2_TEMP_H; + reg_l = F75303_REMOTE2_TEMP_L; + break; + default: + return -ENOTSUP; + } + + scaled_value = (int64_t)value << shift; + millicelsius = scaled_value * 1000 / ((int64_t)INT32_MAX + 1); + reg_value = CLAMP(millicelsius / 125, 0, 0x7ff); + + data->reg[reg_h] = reg_value >> 3; + data->reg[reg_l] = (reg_value & 0x7) << 5; + + return 0; +} + +static int f75303_emul_get_sample_range(const struct emul *target, enum sensor_channel chan, + q31_t *lower, q31_t *upper, q31_t *epsilon, int8_t *shift) +{ + if (chan != SENSOR_CHAN_AMBIENT_TEMP && + chan != (enum sensor_channel)SENSOR_CHAN_F75303_REMOTE1 && + chan != (enum sensor_channel)SENSOR_CHAN_F75303_REMOTE2) { + return -ENOTSUP; + } + + *shift = 8; + *lower = 0; + *upper = (int64_t)(255.875 * ((int64_t)INT32_MAX + 1)) >> *shift; + *epsilon = (int64_t)(0.125 * ((int64_t)INT32_MAX + 1)) >> *shift; + + return 0; +} + +static const struct i2c_emul_api f75303_emul_api_i2c = { + .transfer = f75303_emul_transfer_i2c, +}; + +static const struct emul_sensor_backend_api f75303_emul_api_sensor = { + .set_channel = f75303_emul_set_channel, + .get_sample_range = f75303_emul_get_sample_range, +}; + + +#define F75303_EMUL(n) \ + const struct f75303_emul_cfg f75303_emul_cfg_##n; \ + struct f75303_emul_data f75303_emul_data_##n; \ + EMUL_DT_INST_DEFINE(n, f75303_emul_init, &f75303_emul_data_##n, \ + &f75303_emul_cfg_##n, &f75303_emul_api_i2c, \ + &f75303_emul_api_sensor); + +DT_INST_FOREACH_STATUS_OKAY(F75303_EMUL) diff --git a/drivers/sensor/fdc2x1x/Kconfig b/drivers/sensor/fdc2x1x/Kconfig index bf6f7b148d7..2d6ac596bf3 100644 --- a/drivers/sensor/fdc2x1x/Kconfig +++ b/drivers/sensor/fdc2x1x/Kconfig @@ -7,7 +7,7 @@ menuconfig FDC2X1X bool "FDC2X1X Capacitance-to-Digital Converter" default y depends on DT_HAS_TI_FDC2X1X_ENABLED - depends on NEWLIB_LIBC || EXTERNAL_LIBC + depends on FULL_LIBC_SUPPORTED || EXTERNAL_LIBC select I2C help Enable driver for FDC2X1X Capacitance-to-Digital Converter. diff --git a/drivers/sensor/fdc2x1x/fdc2x1x.h b/drivers/sensor/fdc2x1x/fdc2x1x.h index 33b94168d67..7442de37631 100644 --- a/drivers/sensor/fdc2x1x/fdc2x1x.h +++ b/drivers/sensor/fdc2x1x/fdc2x1x.h @@ -159,7 +159,7 @@ struct fdc2x1x_data { const struct device *dev; #ifdef CONFIG_FDC2X1X_TRIGGER_OWN_THREAD - K_THREAD_STACK_MEMBER(thread_stack, CONFIG_FDC2X1X_THREAD_STACK_SIZE); + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_FDC2X1X_THREAD_STACK_SIZE); struct k_sem gpio_sem; struct k_thread thread; #elif CONFIG_FDC2X1X_TRIGGER_GLOBAL_THREAD diff --git a/drivers/sensor/fdc2x1x/fdc2x1x_trigger.c b/drivers/sensor/fdc2x1x/fdc2x1x_trigger.c index 61697d24605..519d5af0d61 100644 --- a/drivers/sensor/fdc2x1x/fdc2x1x_trigger.c +++ b/drivers/sensor/fdc2x1x/fdc2x1x_trigger.c @@ -60,8 +60,13 @@ static void fdc2x1x_gpio_callback(const struct device *dev, } #ifdef CONFIG_FDC2X1X_TRIGGER_OWN_THREAD -static void fdc2x1x_thread(struct fdc2x1x_data *drv_data) +static void fdc2x1x_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct fdc2x1x_data *drv_data = p1; + while (true) { k_sem_take(&drv_data->gpio_sem, K_FOREVER); fdc2x1x_thread_cb(drv_data->dev); @@ -158,7 +163,7 @@ int fdc2x1x_init_interrupt(const struct device *dev) k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_FDC2X1X_THREAD_STACK_SIZE, - (k_thread_entry_t)fdc2x1x_thread, + fdc2x1x_thread, drv_data, 0, NULL, K_PRIO_COOP(CONFIG_FDC2X1X_THREAD_PRIORITY), 0, K_NO_WAIT); diff --git a/drivers/sensor/fxas21002/fxas21002_trigger.c b/drivers/sensor/fxas21002/fxas21002_trigger.c index 966ed5e2cba..b32d2f5f7d0 100644 --- a/drivers/sensor/fxas21002/fxas21002_trigger.c +++ b/drivers/sensor/fxas21002/fxas21002_trigger.c @@ -68,8 +68,13 @@ static void fxas21002_handle_int(const struct device *dev) } #ifdef CONFIG_FXAS21002_TRIGGER_OWN_THREAD -static void fxas21002_thread_main(struct fxas21002_data *data) +static void fxas21002_thread_main(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct fxas21002_data *data = p1; + while (true) { k_sem_take(&data->trig_sem, K_FOREVER); fxas21002_handle_int(data->dev); @@ -173,7 +178,7 @@ int fxas21002_trigger_init(const struct device *dev) k_sem_init(&data->trig_sem, 0, K_SEM_MAX_LIMIT); k_thread_create(&data->thread, data->thread_stack, CONFIG_FXAS21002_THREAD_STACK_SIZE, - (k_thread_entry_t)fxas21002_thread_main, data, 0, NULL, + fxas21002_thread_main, data, 0, NULL, K_PRIO_COOP(CONFIG_FXAS21002_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_FXAS21002_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/fxos8700/fxos8700_trigger.c b/drivers/sensor/fxos8700/fxos8700_trigger.c index d9adaf8d38f..53d493ac44d 100644 --- a/drivers/sensor/fxos8700/fxos8700_trigger.c +++ b/drivers/sensor/fxos8700/fxos8700_trigger.c @@ -168,8 +168,13 @@ static void fxos8700_handle_int(const struct device *dev) } #ifdef CONFIG_FXOS8700_TRIGGER_OWN_THREAD -static void fxos8700_thread_main(struct fxos8700_data *data) +static void fxos8700_thread_main(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct fxos8700_data *data = p1; + while (true) { k_sem_take(&data->trig_sem, K_FOREVER); fxos8700_handle_int(data->dev); @@ -395,7 +400,7 @@ int fxos8700_trigger_init(const struct device *dev) k_sem_init(&data->trig_sem, 0, K_SEM_MAX_LIMIT); k_thread_create(&data->thread, data->thread_stack, CONFIG_FXOS8700_THREAD_STACK_SIZE, - (k_thread_entry_t)fxos8700_thread_main, + fxos8700_thread_main, data, NULL, NULL, K_PRIO_COOP(CONFIG_FXOS8700_THREAD_PRIORITY), 0, K_NO_WAIT); diff --git a/drivers/sensor/grow_r502a/grow_r502a_trigger.c b/drivers/sensor/grow_r502a/grow_r502a_trigger.c index 7f4e97874bd..1513b896d94 100644 --- a/drivers/sensor/grow_r502a/grow_r502a_trigger.c +++ b/drivers/sensor/grow_r502a/grow_r502a_trigger.c @@ -71,8 +71,13 @@ static void grow_r502a_gpio_callback(const struct device *dev, } #if defined(CONFIG_GROW_R502A_TRIGGER_OWN_THREAD) -static void grow_r502a_thread(struct grow_r502a_data *drv_data) +static void grow_r502a_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct grow_r502a_data *drv_data = p1; + while (true) { k_sem_take(&drv_data->gpio_sem, K_FOREVER); process_int(drv_data->gpio_dev); @@ -111,7 +116,7 @@ int grow_r502a_init_interrupt(const struct device *dev) k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_GROW_R502A_THREAD_STACK_SIZE, - (k_thread_entry_t)grow_r502a_thread, drv_data, NULL, + grow_r502a_thread, drv_data, NULL, NULL, K_PRIO_COOP(CONFIG_GROW_R502A_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_GROW_R502A_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/hm330x/CMakeLists.txt b/drivers/sensor/hm330x/CMakeLists.txt new file mode 100644 index 00000000000..5eeb7ae4849 --- /dev/null +++ b/drivers/sensor/hm330x/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(hm330x.c) diff --git a/drivers/sensor/hm330x/Kconfig b/drivers/sensor/hm330x/Kconfig new file mode 100644 index 00000000000..f1c34eea3fa --- /dev/null +++ b/drivers/sensor/hm330x/Kconfig @@ -0,0 +1,12 @@ +# Seeed Studio HM330x dust particle sensor configuration options + +# Copyright (c) 2023 Benjamin Cabé +# SPDX-License-Identifier: Apache-2.0 + +config HM330X + bool "HM330X dust particle sensor" + default y + depends on DT_HAS_SEEED_HM330X_ENABLED + select I2C + help + Enable driver for the HM330X dust particle sensor. diff --git a/drivers/sensor/hm330x/hm330x.c b/drivers/sensor/hm330x/hm330x.c new file mode 100644 index 00000000000..a1ec7baccd8 --- /dev/null +++ b/drivers/sensor/hm330x/hm330x.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2023 Benjamin Cabé + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT seeed_hm330x + +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(HM3301, CONFIG_SENSOR_LOG_LEVEL); + +#define HM330X_SELECT_COMM_CMD 0X88 + +#define HM330X_PM_1_0_ATM 10 +#define HM330X_PM_2_5_ATM 12 +#define HM330X_PM_10_ATM 14 + +#define HM330X_FRAME_LEN 29 + +struct hm330x_data { + uint16_t pm_1_0_sample; + uint16_t pm_2_5_sample; + uint16_t pm_10_sample; +}; + +struct hm330x_config { + struct i2c_dt_spec i2c; +}; + +static int hm330x_sample_fetch(const struct device *dev, + enum sensor_channel chan) +{ + struct hm330x_data *drv_data = dev->data; + const struct hm330x_config *config = dev->config; + uint8_t buf[HM330X_FRAME_LEN]; + uint8_t checksum = 0; + + __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL); + + if (i2c_burst_read_dt(&config->i2c, + 0, buf, HM330X_FRAME_LEN) < 0) { + return -EIO; + } + + drv_data->pm_1_0_sample = (buf[HM330X_PM_1_0_ATM] << 8) | buf[HM330X_PM_1_0_ATM + 1]; + drv_data->pm_2_5_sample = (buf[HM330X_PM_2_5_ATM] << 8) | buf[HM330X_PM_2_5_ATM + 1]; + drv_data->pm_10_sample = (buf[HM330X_PM_10_ATM] << 8) | buf[HM330X_PM_10_ATM + 1]; + + for (int i = 0; i < HM330X_FRAME_LEN - 1; i++) { + checksum += buf[i]; + } + if (checksum != buf[HM330X_FRAME_LEN - 1]) { + LOG_ERR("Checksum error"); + return -EBADMSG; + } + + return 0; +} + +static int hm330x_channel_get(const struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + struct hm330x_data *drv_data = dev->data; + + if (chan == SENSOR_CHAN_PM_1_0) { + val->val1 = drv_data->pm_1_0_sample; + val->val2 = 0; + } else if (chan == SENSOR_CHAN_PM_2_5) { + val->val1 = drv_data->pm_2_5_sample; + val->val2 = 0; + } else if (chan == SENSOR_CHAN_PM_10) { + val->val1 = drv_data->pm_10_sample; + val->val2 = 0; + } else { + return -ENOTSUP; + } + + return 0; +} + +static const struct sensor_driver_api hm330x_driver_api = { + .sample_fetch = hm330x_sample_fetch, + .channel_get = hm330x_channel_get +}; + +int hm330x_init(const struct device *dev) +{ + const struct hm330x_config *config = dev->config; + + if (!i2c_is_ready_dt(&config->i2c)) { + LOG_ERR("I2C bus device not ready"); + return -ENODEV; + } + + /** Enable I2C communications (module defaults to UART) */ + if (i2c_reg_write_byte_dt(&config->i2c, 0, HM330X_SELECT_COMM_CMD) < 0) { + LOG_ERR("Failed to switch to I2C"); + return -EIO; + } + + return 0; +} + +#define HM330X_DEFINE(inst) \ + static struct hm330x_data hm330x_data_##inst; \ + \ + static const struct hm330x_config hm330x_config##inst = { \ + .i2c = I2C_DT_SPEC_INST_GET(inst) \ + }; \ + \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, hm330x_init, NULL, &hm330x_data_##inst, \ + &hm330x_config##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &hm330x_driver_api); \ + +DT_INST_FOREACH_STATUS_OKAY(HM330X_DEFINE) diff --git a/drivers/sensor/hmc5883l/hmc5883l_trigger.c b/drivers/sensor/hmc5883l/hmc5883l_trigger.c index da73a10807c..c3a1d00891c 100644 --- a/drivers/sensor/hmc5883l/hmc5883l_trigger.c +++ b/drivers/sensor/hmc5883l/hmc5883l_trigger.c @@ -78,8 +78,13 @@ static void hmc5883l_thread_cb(const struct device *dev) } #ifdef CONFIG_HMC5883L_TRIGGER_OWN_THREAD -static void hmc5883l_thread(struct hmc5883l_data *drv_data) +static void hmc5883l_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct hmc5883l_data *drv_data = p1; + while (1) { k_sem_take(&drv_data->gpio_sem, K_FOREVER); hmc5883l_thread_cb(drv_data->dev); @@ -124,7 +129,7 @@ int hmc5883l_init_interrupt(const struct device *dev) k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_HMC5883L_THREAD_STACK_SIZE, - (k_thread_entry_t)hmc5883l_thread, + hmc5883l_thread, drv_data, NULL, NULL, K_PRIO_COOP(CONFIG_HMC5883L_THREAD_PRIORITY), 0, K_NO_WAIT); diff --git a/drivers/sensor/hs300x/CMakeLists.txt b/drivers/sensor/hs300x/CMakeLists.txt new file mode 100644 index 00000000000..f937e6bb6f1 --- /dev/null +++ b/drivers/sensor/hs300x/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(hs300x.c) diff --git a/drivers/sensor/hs300x/Kconfig b/drivers/sensor/hs300x/Kconfig new file mode 100644 index 00000000000..53060cb5c21 --- /dev/null +++ b/drivers/sensor/hs300x/Kconfig @@ -0,0 +1,12 @@ +# Renesas HS300x temperature and humidity sensor configuration options + +# Copyright (c) 2023 Ian Morris +# SPDX-License-Identifier: Apache-2.0 + +config HS300X + bool "HS300x Temperature and Humidity Sensor" + default y + depends on DT_HAS_RENESAS_HS300X_ENABLED + select I2C + help + Enable driver for HS300x temperature and humidity sensors. diff --git a/drivers/sensor/hs300x/hs300x.c b/drivers/sensor/hs300x/hs300x.c new file mode 100644 index 00000000000..9faabbb1e35 --- /dev/null +++ b/drivers/sensor/hs300x/hs300x.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2023 Ian Morris + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_hs300x + +#include +#include +#include +#include +#include +#include +#include + +#define HS300X_STATUS_MASK (BIT(0) | BIT(1)) + +LOG_MODULE_REGISTER(HS300X, CONFIG_SENSOR_LOG_LEVEL); + +struct hs300x_config { + struct i2c_dt_spec bus; +}; + +struct hs300x_data { + int16_t t_sample; + uint16_t rh_sample; +}; + +static int hs300x_read_sample(const struct device *dev, uint16_t *t_sample, uint16_t *rh_sample) +{ + const struct hs300x_config *cfg = dev->config; + uint8_t rx_buf[4]; + int rc; + + rc = i2c_read_dt(&cfg->bus, rx_buf, sizeof(rx_buf)); + if (rc < 0) { + LOG_ERR("Failed to read data from device."); + return rc; + } + + if ((rx_buf[3] & HS300X_STATUS_MASK) != 0) { + LOG_ERR("Stale data"); + return -EIO; + } + + *rh_sample = sys_get_be16(rx_buf); + *t_sample = sys_get_be16(&rx_buf[2]); + + /* Remove status bits (only present in temperature value)*/ + *t_sample >>= 2; + + return 0; +} + +static int hs300x_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + struct hs300x_data *data = dev->data; + const struct hs300x_config *cfg = dev->config; + int rc; + + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_AMBIENT_TEMP && + chan != SENSOR_CHAN_HUMIDITY) { + return -ENOTSUP; + } + + /* + * Initiate a measurement simply by sending 7-bit address followed + * by an eighth bit set to 0 (write) and NO data. + */ + rc = i2c_write_dt(&cfg->bus, NULL, 0); + if (rc < 0) { + LOG_ERR("Failed to start measurement."); + return rc; + } + + /* + * According to datasheet maximum time to make temperature and humidity + * measurements is 33ms, add a little safety margin... + */ + k_msleep(50); + + rc = hs300x_read_sample(dev, &data->t_sample, &data->rh_sample); + if (rc < 0) { + LOG_ERR("Failed to fetch data."); + return rc; + } + + return 0; +} + +static void hs300x_temp_convert(struct sensor_value *val, int16_t raw) +{ + int32_t micro_c; + + /* + * Convert to micro Celsius. See datasheet "Calculating Humidity and + * Temperature Output" section for more details on processing sample data. + */ + micro_c = (((int64_t)raw * 165000000) / 16383) - 40000000; + + val->val1 = micro_c / 1000000; + val->val2 = micro_c % 1000000; +} + +static void hs300x_rh_convert(struct sensor_value *val, uint16_t raw) +{ + int32_t micro_rh; + + /* + * Convert to micro %RH. See datasheet "Calculating Humidity and + * Temperature Output" section for more details on processing sample data. + */ + micro_rh = ((uint64_t)raw * 100000000) / 16383; + + val->val1 = micro_rh / 1000000; + val->val2 = micro_rh % 1000000; +} + +static int hs300x_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + const struct hs300x_data *data = dev->data; + + if (chan == SENSOR_CHAN_AMBIENT_TEMP) { + hs300x_temp_convert(val, data->t_sample); + } else if (chan == SENSOR_CHAN_HUMIDITY) { + hs300x_rh_convert(val, data->rh_sample); + } else { + return -ENOTSUP; + } + + return 0; +} + +static int hs300x_init(const struct device *dev) +{ + const struct hs300x_config *cfg = dev->config; + + if (!i2c_is_ready_dt(&cfg->bus)) { + LOG_ERR("I2C dev %s not ready", cfg->bus.bus->name); + return -ENODEV; + } + + return 0; +} + +static const struct sensor_driver_api hs300x_driver_api = {.sample_fetch = hs300x_sample_fetch, + .channel_get = hs300x_channel_get}; + +#define DEFINE_HS300X(n) \ + static struct hs300x_data hs300x_data_##n; \ + \ + static const struct hs300x_config hs300x_config_##n = {.bus = I2C_DT_SPEC_INST_GET(n)}; \ + \ + SENSOR_DEVICE_DT_INST_DEFINE(n, hs300x_init, NULL, &hs300x_data_##n, &hs300x_config_##n, \ + POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \ + &hs300x_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(DEFINE_HS300X) diff --git a/drivers/sensor/hts221/hts221_trigger.c b/drivers/sensor/hts221/hts221_trigger.c index 9019706a34b..1ebccb2a3c5 100644 --- a/drivers/sensor/hts221/hts221_trigger.c +++ b/drivers/sensor/hts221/hts221_trigger.c @@ -95,8 +95,13 @@ static void hts221_drdy_callback(const struct device *dev, } #ifdef CONFIG_HTS221_TRIGGER_OWN_THREAD -static void hts221_thread(struct hts221_data *data) +static void hts221_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct hts221_data *data = p1; + while (1) { k_sem_take(&data->drdy_sem, K_FOREVER); process_drdy(data->dev); @@ -163,7 +168,7 @@ int hts221_init_interrupt(const struct device *dev) k_thread_create(&data->thread, data->thread_stack, CONFIG_HTS221_THREAD_STACK_SIZE, - (k_thread_entry_t)hts221_thread, data, + hts221_thread, data, NULL, NULL, K_PRIO_COOP(CONFIG_HTS221_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_HTS221_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/icm42688/CMakeLists.txt b/drivers/sensor/icm42688/CMakeLists.txt index cf9308bb95c..fbc63b6a4b2 100644 --- a/drivers/sensor/icm42688/CMakeLists.txt +++ b/drivers/sensor/icm42688/CMakeLists.txt @@ -10,6 +10,7 @@ zephyr_library_sources( zephyr_library_sources_ifdef(CONFIG_SENSOR_ASYNC_API icm42688_rtio.c) zephyr_library_sources_ifdef(CONFIG_ICM42688_DECODER icm42688_decoder.c) +zephyr_library_sources_ifdef(CONFIG_ICM42688_STREAM icm42688_rtio_stream.c) zephyr_library_sources_ifdef(CONFIG_ICM42688_TRIGGER icm42688_trigger.c) zephyr_library_sources_ifdef(CONFIG_EMUL_ICM42688 icm42688_emul.c) zephyr_include_directories_ifdef(CONFIG_EMUL_ICM42688 .) diff --git a/drivers/sensor/icm42688/Kconfig b/drivers/sensor/icm42688/Kconfig index 2944a9d1183..d7ee43bc761 100644 --- a/drivers/sensor/icm42688/Kconfig +++ b/drivers/sensor/icm42688/Kconfig @@ -33,6 +33,7 @@ if ICM42688 choice prompt "Trigger mode" + default ICM42688_TRIGGER_NONE if ICM42688_STREAM default ICM42688_TRIGGER_GLOBAL_THREAD help Specify the type of triggering to be used by the driver @@ -50,6 +51,15 @@ config ICM42688_TRIGGER_OWN_THREAD endchoice +config ICM42688_STREAM + bool "Use hardware FIFO to stream data" + select ICM42688_TRIGGER + default y + depends on SPI_RTIO + depends on SENSOR_ASYNC_API + help + Use this config option to enable streaming sensor data via RTIO subsystem. + config ICM42688_TRIGGER bool diff --git a/drivers/sensor/icm42688/icm42688.c b/drivers/sensor/icm42688/icm42688.c index b8ebef4f147..a6b4cd06c52 100644 --- a/drivers/sensor/icm42688/icm42688.c +++ b/drivers/sensor/icm42688/icm42688.c @@ -82,7 +82,7 @@ int icm42688_channel_parse_readings(enum sensor_channel chan, int16_t readings[7 } static int icm42688_channel_get(const struct device *dev, enum sensor_channel chan, - struct sensor_value *val) + struct sensor_value *val) { struct icm42688_dev_data *data = dev->data; @@ -156,6 +156,17 @@ static int icm42688_attr_set(const struct device *dev, enum sensor_channel chan, res = -EINVAL; } break; + case SENSOR_CHAN_ALL: + if (attr == SENSOR_ATTR_BATCH_DURATION) { + if (val->val1 < 0) { + return -EINVAL; + } + new_config.batch_ticks = val->val1; + } else { + LOG_ERR("Unsupported attribute"); + res = -EINVAL; + } + break; default: LOG_ERR("Unsupported channel"); res = -EINVAL; @@ -204,6 +215,15 @@ static int icm42688_attr_get(const struct device *dev, enum sensor_channel chan, res = -EINVAL; } break; + case SENSOR_CHAN_ALL: + if (attr == SENSOR_ATTR_BATCH_DURATION) { + val->val1 = cfg->batch_ticks; + val->val2 = 0; + } else { + LOG_ERR("Unsupported attribute"); + res = -EINVAL; + } + break; default: LOG_ERR("Unsupported channel"); res = -EINVAL; @@ -251,14 +271,19 @@ int icm42688_init(const struct device *dev) } #endif - memset(&data->cfg, 0, sizeof(struct icm42688_cfg)); data->cfg.accel_mode = ICM42688_ACCEL_LN; - data->cfg.gyro_mode = ICM42688_GYRO_LN; data->cfg.accel_fs = ICM42688_ACCEL_FS_2G; - data->cfg.gyro_fs = ICM42688_GYRO_FS_125; data->cfg.accel_odr = ICM42688_ACCEL_ODR_1000; + data->cfg.gyro_mode = ICM42688_GYRO_LN; + data->cfg.gyro_fs = ICM42688_GYRO_FS_125; data->cfg.gyro_odr = ICM42688_GYRO_ODR_1000; - data->cfg.fifo_en = false; + data->cfg.temp_dis = false; + data->cfg.fifo_en = IS_ENABLED(CONFIG_ICM42688_STREAM); + data->cfg.batch_ticks = 0; + data->cfg.fifo_hires = 0; + data->cfg.interrupt1_drdy = 0; + data->cfg.interrupt1_fifo_ths = 0; + data->cfg.interrupt1_fifo_full = 0; res = icm42688_configure(dev, &data->cfg); if (res != 0) { @@ -284,8 +309,15 @@ void icm42688_unlock(const struct device *dev) #define ICM42688_SPI_CFG \ SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_TRANSFER_MSB +#define ICM42688_RTIO_DEFINE(inst) \ + SPI_DT_IODEV_DEFINE(icm42688_spi_iodev_##inst, DT_DRV_INST(inst), ICM42688_SPI_CFG, 0U); \ + RTIO_DEFINE(icm42688_rtio_##inst, 8, 4); + #define ICM42688_DEFINE_DATA(inst) \ - static struct icm42688_dev_data icm42688_driver_##inst; + IF_ENABLED(CONFIG_ICM42688_STREAM, (ICM42688_RTIO_DEFINE(inst))); \ + static struct icm42688_dev_data icm42688_driver_##inst = { \ + IF_ENABLED(CONFIG_ICM42688_STREAM, (.r = &icm42688_rtio_##inst, \ + .spi_iodev = &icm42688_spi_iodev_##inst,))}; #define ICM42688_INIT(inst) \ ICM42688_DEFINE_DATA(inst); \ diff --git a/drivers/sensor/icm42688/icm42688.h b/drivers/sensor/icm42688/icm42688.h index 18ae4606e72..5ec470cff27 100644 --- a/drivers/sensor/icm42688/icm42688.h +++ b/drivers/sensor/icm42688/icm42688.h @@ -380,11 +380,14 @@ struct icm42688_cfg { /* TODO timestamp options */ bool fifo_en; - uint16_t fifo_wm; + int32_t batch_ticks; bool fifo_hires; /* TODO additional FIFO options */ /* TODO interrupt options */ + bool interrupt1_drdy; + bool interrupt1_fifo_ths; + bool interrupt1_fifo_full; }; struct icm42688_trigger_entry { @@ -405,6 +408,15 @@ struct icm42688_dev_data { #elif defined(CONFIG_ICM42688_TRIGGER_GLOBAL_THREAD) struct k_work work; #endif +#ifdef CONFIG_ICM42688_STREAM + struct rtio_iodev_sqe *streaming_sqe; + struct rtio *r; + struct rtio_iodev *spi_iodev; + uint8_t int_status; + uint16_t fifo_count; + uint64_t timestamp; + atomic_t reading_fifo; +#endif /* CONFIG_ICM42688_STREAM */ const struct device *dev; struct gpio_callback gpio_cb; sensor_trigger_handler_t data_ready_handler; diff --git a/drivers/sensor/icm42688/icm42688_common.c b/drivers/sensor/icm42688/icm42688_common.c index 3ccd107cfbb..4df2f787092 100644 --- a/drivers/sensor/icm42688/icm42688_common.c +++ b/drivers/sensor/icm42688/icm42688_common.c @@ -12,6 +12,7 @@ #include "icm42688.h" #include "icm42688_reg.h" #include "icm42688_spi.h" +#include "icm42688_trigger.h" #include LOG_MODULE_REGISTER(ICM42688_LL, CONFIG_SENSOR_LOG_LEVEL); @@ -61,6 +62,62 @@ int icm42688_reset(const struct device *dev) return 0; } +static uint16_t icm42688_compute_fifo_wm(const struct icm42688_cfg *cfg) +{ + const bool accel_enabled = cfg->accel_mode != ICM42688_ACCEL_OFF; + const bool gyro_enabled = cfg->gyro_mode != ICM42688_GYRO_OFF; + const int pkt_size = cfg->fifo_hires ? 20 : (accel_enabled && gyro_enabled ? 16 : 8); + int accel_modr = 0; + int gyro_modr = 0; + int64_t modr; + + if (cfg->batch_ticks == 0 || (!accel_enabled && !gyro_enabled)) { + return 0; + } + + if (accel_enabled) { + struct sensor_value val = {0}; + + icm42688_accel_reg_to_hz(cfg->accel_odr, &val); + accel_modr = sensor_value_to_micro(&val) / 1000; + } + if (gyro_enabled) { + struct sensor_value val = {0}; + + icm42688_gyro_reg_to_odr(cfg->gyro_odr, &val); + gyro_modr = sensor_value_to_micro(&val) / 1000; + } + + if (accel_modr == 0) { + modr = gyro_modr; + } else if (gyro_modr == 0) { + modr = accel_modr; + } else { + /* Need to find the least common multiplier (LCM) */ + int n1 = accel_modr; + int n2 = gyro_modr; + + while (n1 != n2) { + if (n1 > n2) { + n1 -= n2; + } else { + n2 -= n1; + } + } + LOG_DBG("GCD=%d", n1); + modr = ((int64_t)accel_modr * (int64_t)gyro_modr) / n1; + } + /* At this point we have 'modr' as mHz which is 1 / msec. */ + + /* Convert 'modr' to bytes * batch_ticks / msec */ + modr *= (int64_t)cfg->batch_ticks * pkt_size; + + /* 'modr' = byte_ticks_per_msec / kticks_per_sec */ + modr = DIV_ROUND_UP(modr, CONFIG_SYS_CLOCK_TICKS_PER_SEC * INT64_C(1000)); + + return (uint16_t)MIN(modr, 0x7ff); +} + int icm42688_configure(const struct device *dev, struct icm42688_cfg *cfg) { struct icm42688_dev_data *dev_data = dev->data; @@ -165,8 +222,12 @@ int icm42688_configure(const struct device *dev, struct icm42688_cfg *cfg) } /* Pulse mode with async reset (resets interrupt line on int status read) */ - res = icm42688_spi_single_write(&dev_cfg->spi, REG_INT_CONFIG, - BIT_INT1_DRIVE_CIRCUIT | BIT_INT1_POLARITY); + if (IS_ENABLED(CONFIG_ICM42688_TRIGGER)) { + res = icm42688_trigger_enable_interrupt(dev, cfg); + } else { + res = icm42688_spi_single_write(&dev_cfg->spi, REG_INT_CONFIG, + BIT_INT1_DRIVE_CIRCUIT | BIT_INT1_POLARITY); + } if (res) { LOG_ERR("Error writing to INT_CONFIG"); return res; @@ -205,7 +266,8 @@ int icm42688_configure(const struct device *dev, struct icm42688_cfg *cfg) } /* Set watermark and interrupt handling first */ - uint8_t fifo_wml = (cfg->fifo_wm) & 0xFF; + uint16_t fifo_wm = icm42688_compute_fifo_wm(cfg); + uint8_t fifo_wml = fifo_wm & 0xFF; LOG_DBG("FIFO_CONFIG2( (0x%x)) (WM Low) 0x%x", REG_FIFO_CONFIG2, fifo_wml); res = icm42688_spi_single_write(&dev_cfg->spi, REG_FIFO_CONFIG2, fifo_wml); @@ -214,7 +276,7 @@ int icm42688_configure(const struct device *dev, struct icm42688_cfg *cfg) return -EINVAL; } - uint8_t fifo_wmh = (cfg->fifo_wm >> 8) & 0x0F; + uint8_t fifo_wmh = (fifo_wm >> 8) & 0x0F; LOG_DBG("FIFO_CONFIG3 (0x%x) (WM High) 0x%x", REG_FIFO_CONFIG3, fifo_wmh); res = icm42688_spi_single_write(&dev_cfg->spi, REG_FIFO_CONFIG3, fifo_wmh); diff --git a/drivers/sensor/icm42688/icm42688_decoder.c b/drivers/sensor/icm42688/icm42688_decoder.c index 781e7567ffd..3dc556ac61c 100644 --- a/drivers/sensor/icm42688/icm42688_decoder.c +++ b/drivers/sensor/icm42688/icm42688_decoder.c @@ -77,28 +77,6 @@ static int icm42688_get_shift(enum sensor_channel channel, int accel_fs, int gyr } } -static enum sensor_channel icm42688_get_channel_from_position(int pos) -{ - switch (pos) { - case 0: - return SENSOR_CHAN_DIE_TEMP; - case 1: - return SENSOR_CHAN_ACCEL_X; - case 2: - return SENSOR_CHAN_ACCEL_Y; - case 3: - return SENSOR_CHAN_ACCEL_Z; - case 4: - return SENSOR_CHAN_GYRO_X; - case 5: - return SENSOR_CHAN_GYRO_Y; - case 6: - return SENSOR_CHAN_GYRO_Z; - default: - return SENSOR_CHAN_MAX; - } -} - int icm42688_convert_raw_to_q31(struct icm42688_cfg *cfg, enum sensor_channel chan, int32_t reading, q31_t *out) { @@ -220,92 +198,500 @@ int icm42688_encode(const struct device *dev, const enum sensor_channel *const c return 0; } -static int icm42688_one_shot_decode(const uint8_t *buffer, sensor_frame_iterator_t *fit, - sensor_channel_iterator_t *cit, enum sensor_channel *channels, - q31_t *values, uint8_t max_count) +#define IS_ACCEL(chan) ((chan) >= SENSOR_CHAN_ACCEL_X && (chan) <= SENSOR_CHAN_ACCEL_XYZ) +#define IS_GYRO(chan) ((chan) >= SENSOR_CHAN_GYRO_X && (chan) <= SENSOR_CHAN_GYRO_XYZ) + +static inline q31_t icm42688_read_temperature_from_packet(const uint8_t *pkt) +{ + int32_t temperature; + int32_t whole; + int32_t fraction; + + /* Temperature always assumes a shift of 9 for a range of (-273,273) C */ + if (FIELD_GET(FIFO_HEADER_20, pkt[0]) == 1) { + temperature = (pkt[0xd] << 8) | pkt[0xe]; + + icm42688_temp_c(temperature, &whole, &fraction); + } else { + if (FIELD_GET(FIFO_HEADER_ACCEL, pkt[0]) == 1 && + FIELD_GET(FIFO_HEADER_GYRO, pkt[0]) == 1) { + temperature = pkt[0xd]; + } else { + temperature = pkt[0x7]; + } + + int64_t sensitivity = 207; + int64_t temperature100 = (temperature * 100) + (25 * sensitivity); + + whole = temperature100 / sensitivity; + fraction = + ((temperature100 - whole * sensitivity) * INT64_C(1000000)) / sensitivity; + } + __ASSERT_NO_MSG(whole >= -512 && whole <= 511); + return FIELD_PREP(GENMASK(31, 22), whole) | (fraction * GENMASK64(21, 0) / 1000000); +} + +static int icm42688_read_imu_from_packet(const uint8_t *pkt, bool is_accel, int fs, + uint8_t axis_offset, q31_t *out) +{ + int32_t value; + int64_t scale = 0; + int32_t max = BIT(15); + int offset = 1 + (axis_offset * 2); + + if (is_accel) { + switch (fs) { + case ICM42688_ACCEL_FS_2G: + scale = INT64_C(2) * BIT(31 - 5) * 9.80665; + break; + case ICM42688_ACCEL_FS_4G: + scale = INT64_C(4) * BIT(31 - 6) * 9.80665; + break; + case ICM42688_ACCEL_FS_8G: + scale = INT64_C(8) * BIT(31 - 7) * 9.80665; + break; + case ICM42688_ACCEL_FS_16G: + scale = INT64_C(16) * BIT(31 - 8) * 9.80665; + break; + } + } else { + switch (fs) { + case ICM42688_GYRO_FS_2000: + scale = 164; + break; + case ICM42688_GYRO_FS_1000: + scale = 328; + break; + case ICM42688_GYRO_FS_500: + scale = 655; + break; + case ICM42688_GYRO_FS_250: + scale = 1310; + break; + case ICM42688_GYRO_FS_125: + scale = 2620; + break; + case ICM42688_GYRO_FS_62_5: + scale = 5243; + break; + case ICM42688_GYRO_FS_31_25: + scale = 10486; + break; + case ICM42688_GYRO_FS_15_625: + scale = 20972; + break; + } + } + + if (!is_accel && FIELD_GET(FIFO_HEADER_ACCEL, pkt[0]) == 1) { + offset += 7; + } + + value = (int16_t)sys_le16_to_cpu((pkt[offset] << 8) | pkt[offset + 1]); + + if (FIELD_GET(FIFO_HEADER_20, pkt[0]) == 1) { + uint32_t mask = is_accel ? GENMASK(7, 4) : GENMASK(3, 0); + + offset = 0x11 + axis_offset; + value = (value << 4) | FIELD_GET(mask, pkt[offset]); + /* In 20 bit mode, FS can only be +/-16g and +/-2000dps */ + scale = is_accel ? (INT64_C(16) * BIT(8) * 9.80665) : 131; + max = is_accel ? BIT(18) : BIT(19); + if (value == -524288) { + /* Invalid 20 bit value */ + return -ENODATA; + } + } else { + if (value <= -32767) { + /* Invalid 16 bit value */ + return -ENODATA; + } + } + + *out = (q31_t)(value * scale / max); + return 0; +} + +static uint32_t accel_period_ns[] = { + [ICM42688_ACCEL_ODR_1_5625] = UINT32_C(10000000000000) / 15625, + [ICM42688_ACCEL_ODR_3_125] = UINT32_C(10000000000000) / 31250, + [ICM42688_ACCEL_ODR_6_25] = UINT32_C(10000000000000) / 62500, + [ICM42688_ACCEL_ODR_12_5] = UINT32_C(10000000000000) / 12500, + [ICM42688_ACCEL_ODR_25] = UINT32_C(1000000000) / 25, + [ICM42688_ACCEL_ODR_50] = UINT32_C(1000000000) / 50, + [ICM42688_ACCEL_ODR_100] = UINT32_C(1000000000) / 100, + [ICM42688_ACCEL_ODR_200] = UINT32_C(1000000000) / 200, + [ICM42688_ACCEL_ODR_500] = UINT32_C(1000000000) / 500, + [ICM42688_ACCEL_ODR_1000] = UINT32_C(1000000), + [ICM42688_ACCEL_ODR_2000] = UINT32_C(1000000) / 2, + [ICM42688_ACCEL_ODR_4000] = UINT32_C(1000000) / 4, + [ICM42688_ACCEL_ODR_8000] = UINT32_C(1000000) / 8, + [ICM42688_ACCEL_ODR_16000] = UINT32_C(1000000) / 16, + [ICM42688_ACCEL_ODR_32000] = UINT32_C(1000000) / 32, +}; + +static uint32_t gyro_period_ns[] = { + [ICM42688_GYRO_ODR_12_5] = UINT32_C(10000000000000) / 12500, + [ICM42688_GYRO_ODR_25] = UINT32_C(1000000000) / 25, + [ICM42688_GYRO_ODR_50] = UINT32_C(1000000000) / 50, + [ICM42688_GYRO_ODR_100] = UINT32_C(1000000000) / 100, + [ICM42688_GYRO_ODR_200] = UINT32_C(1000000000) / 200, + [ICM42688_GYRO_ODR_500] = UINT32_C(1000000000) / 500, + [ICM42688_GYRO_ODR_1000] = UINT32_C(1000000), + [ICM42688_GYRO_ODR_2000] = UINT32_C(1000000) / 2, + [ICM42688_GYRO_ODR_4000] = UINT32_C(1000000) / 4, + [ICM42688_GYRO_ODR_8000] = UINT32_C(1000000) / 8, + [ICM42688_GYRO_ODR_16000] = UINT32_C(1000000) / 16, + [ICM42688_GYRO_ODR_32000] = UINT32_C(1000000) / 32, +}; + +static int icm42688_fifo_decode(const uint8_t *buffer, enum sensor_channel channel, + size_t channel_idx, uint32_t *fit, uint16_t max_count, + void *data_out) +{ + const struct icm42688_fifo_data *edata = (const struct icm42688_fifo_data *)buffer; + const uint8_t *buffer_end = buffer + sizeof(struct icm42688_fifo_data) + edata->fifo_count; + int accel_frame_count = 0; + int gyro_frame_count = 0; + int count = 0; + int rc; + + if ((uintptr_t)buffer_end <= *fit || channel_idx != 0) { + return 0; + } + + ((struct sensor_data_header *)data_out)->base_timestamp_ns = edata->header.timestamp; + + buffer += sizeof(struct icm42688_fifo_data); + while (count < max_count && buffer < buffer_end) { + const bool is_20b = FIELD_GET(FIFO_HEADER_20, buffer[0]) == 1; + const bool has_accel = FIELD_GET(FIFO_HEADER_ACCEL, buffer[0]) == 1; + const bool has_gyro = FIELD_GET(FIFO_HEADER_GYRO, buffer[0]) == 1; + const uint8_t *frame_end = buffer; + + if (is_20b) { + frame_end += 20; + } else if (has_accel && has_gyro) { + frame_end += 16; + } else { + frame_end += 8; + } + if (has_accel) { + accel_frame_count++; + } + if (has_gyro) { + gyro_frame_count++; + } + + if ((uintptr_t)buffer < *fit) { + /* This frame was already decoded, move on to the next frame */ + buffer = frame_end; + continue; + } + if (channel == SENSOR_CHAN_DIE_TEMP) { + struct sensor_q31_data *data = (struct sensor_q31_data *)data_out; + + data->shift = 9; + if (has_accel) { + data->readings[count].timestamp_delta = + accel_period_ns[edata->accel_odr] * (accel_frame_count - 1); + } else { + data->readings[count].timestamp_delta = + gyro_period_ns[edata->gyro_odr] * (gyro_frame_count - 1); + } + data->readings[count].temperature = + icm42688_read_temperature_from_packet(buffer); + } else if (IS_ACCEL(channel) && has_accel) { + /* Decode accel */ + struct sensor_three_axis_data *data = + (struct sensor_three_axis_data *)data_out; + uint64_t period_ns = accel_period_ns[edata->accel_odr]; + + icm42688_get_shift(SENSOR_CHAN_ACCEL_XYZ, edata->header.accel_fs, + edata->header.gyro_fs, &data->shift); + + data->readings[count].timestamp_delta = (accel_frame_count - 1) * period_ns; + rc = icm42688_read_imu_from_packet(buffer, true, edata->header.accel_fs, 0, + &data->readings[count].x); + rc |= icm42688_read_imu_from_packet(buffer, true, edata->header.accel_fs, 1, + &data->readings[count].y); + rc |= icm42688_read_imu_from_packet(buffer, true, edata->header.accel_fs, 2, + &data->readings[count].z); + if (rc != 0) { + accel_frame_count--; + buffer = frame_end; + continue; + } + } else if (IS_GYRO(channel) && has_gyro) { + /* Decode gyro */ + struct sensor_three_axis_data *data = + (struct sensor_three_axis_data *)data_out; + uint64_t period_ns = accel_period_ns[edata->gyro_odr]; + + icm42688_get_shift(SENSOR_CHAN_GYRO_XYZ, edata->header.accel_fs, + edata->header.gyro_fs, &data->shift); + + data->readings[count].timestamp_delta = (gyro_frame_count - 1) * period_ns; + rc = icm42688_read_imu_from_packet(buffer, false, edata->header.gyro_fs, 0, + &data->readings[count].x); + rc |= icm42688_read_imu_from_packet(buffer, false, edata->header.gyro_fs, 1, + &data->readings[count].y); + rc |= icm42688_read_imu_from_packet(buffer, false, edata->header.gyro_fs, 2, + &data->readings[count].z); + if (rc != 0) { + gyro_frame_count--; + buffer = frame_end; + continue; + } + } + buffer = frame_end; + *fit = (uintptr_t)frame_end; + count++; + } + return count; +} + +static int icm42688_one_shot_decode(const uint8_t *buffer, enum sensor_channel channel, + size_t channel_idx, uint32_t *fit, uint16_t max_count, + void *data_out) { const struct icm42688_encoded_data *edata = (const struct icm42688_encoded_data *)buffer; - uint8_t channel_pos_read = edata->channels; + const struct icm42688_decoder_header *header = &edata->header; struct icm42688_cfg cfg = { .accel_fs = edata->header.accel_fs, .gyro_fs = edata->header.gyro_fs, }; - enum sensor_channel chan; - int pos; - int count = 0; - int num_samples = __builtin_popcount(channel_pos_read); - - channel_pos_read = edata->channels; + uint8_t channel_request; + int rc; if (*fit != 0) { return 0; } - - /* Skip channels already decoded */ - for (int i = 0; i < *cit && channel_pos_read; i++) { - pos = __builtin_ctz(channel_pos_read); - channel_pos_read &= ~BIT(pos); + if (max_count == 0 || channel_idx != 0) { + return -EINVAL; } - /* Decode remaining channels */ - while (channel_pos_read && *cit < num_samples && count < max_count) { - pos = __builtin_ctz(channel_pos_read); - chan = icm42688_get_channel_from_position(pos); + switch (channel) { + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_ACCEL_XYZ: { + channel_request = icm42688_encode_channel(SENSOR_CHAN_ACCEL_XYZ); + if ((channel_request & edata->channels) != channel_request) { + return -ENODATA; + } - channels[count] = chan; + struct sensor_three_axis_data *out = data_out; - icm42688_convert_raw_to_q31(&cfg, chan, edata->readings[pos], &values[count]); + out->header.base_timestamp_ns = edata->header.timestamp; + out->header.reading_count = 1; + rc = icm42688_get_shift(SENSOR_CHAN_ACCEL_XYZ, header->accel_fs, header->gyro_fs, + &out->shift); + if (rc != 0) { + return -EINVAL; + } - count++; - channel_pos_read &= ~BIT(pos); - *cit += 1; + icm42688_convert_raw_to_q31( + &cfg, SENSOR_CHAN_ACCEL_X, + edata->readings[icm42688_get_channel_position(SENSOR_CHAN_ACCEL_X)], + &out->readings[0].x); + icm42688_convert_raw_to_q31( + &cfg, SENSOR_CHAN_ACCEL_Y, + edata->readings[icm42688_get_channel_position(SENSOR_CHAN_ACCEL_Y)], + &out->readings[0].y); + icm42688_convert_raw_to_q31( + &cfg, SENSOR_CHAN_ACCEL_Z, + edata->readings[icm42688_get_channel_position(SENSOR_CHAN_ACCEL_Z)], + &out->readings[0].z); + *fit = 1; + return 1; } + case SENSOR_CHAN_GYRO_X: + case SENSOR_CHAN_GYRO_Y: + case SENSOR_CHAN_GYRO_Z: + case SENSOR_CHAN_GYRO_XYZ: { + channel_request = icm42688_encode_channel(SENSOR_CHAN_GYRO_XYZ); + if ((channel_request & edata->channels) != channel_request) { + return -ENODATA; + } - if (*cit >= __builtin_popcount(edata->channels)) { - *fit += 1; - *cit = 0; + struct sensor_three_axis_data *out = data_out; + + out->header.base_timestamp_ns = edata->header.timestamp; + out->header.reading_count = 1; + rc = icm42688_get_shift(SENSOR_CHAN_GYRO_XYZ, header->accel_fs, header->gyro_fs, + &out->shift); + if (rc != 0) { + return -EINVAL; + } + + out->readings[0].timestamp_delta = 0; + icm42688_convert_raw_to_q31( + &cfg, SENSOR_CHAN_GYRO_X, + edata->readings[icm42688_get_channel_position(SENSOR_CHAN_GYRO_X)], + &out->readings[0].x); + icm42688_convert_raw_to_q31( + &cfg, SENSOR_CHAN_GYRO_Y, + edata->readings[icm42688_get_channel_position(SENSOR_CHAN_GYRO_Y)], + &out->readings[0].y); + icm42688_convert_raw_to_q31( + &cfg, SENSOR_CHAN_GYRO_Z, + edata->readings[icm42688_get_channel_position(SENSOR_CHAN_GYRO_Z)], + &out->readings[0].z); + *fit = 1; + return 1; } + case SENSOR_CHAN_DIE_TEMP: { + channel_request = icm42688_encode_channel(SENSOR_CHAN_DIE_TEMP); + if ((channel_request & edata->channels) != channel_request) { + return -ENODATA; + } - return count; + struct sensor_q31_data *out = data_out; + + out->header.base_timestamp_ns = edata->header.timestamp; + out->header.reading_count = 1; + + rc = icm42688_get_shift(SENSOR_CHAN_DIE_TEMP, header->accel_fs, header->gyro_fs, + &out->shift); + if (rc != 0) { + return -EINVAL; + } + out->readings[0].timestamp_delta = 0; + icm42688_convert_raw_to_q31( + &cfg, SENSOR_CHAN_DIE_TEMP, + edata->readings[icm42688_get_channel_position(SENSOR_CHAN_DIE_TEMP)], + &out->readings[0].temperature); + *fit = 1; + return 1; + } + default: + return -EINVAL; + } } -static int icm42688_decoder_decode(const uint8_t *buffer, sensor_frame_iterator_t *fit, - sensor_channel_iterator_t *cit, enum sensor_channel *channels, - q31_t *values, uint8_t max_count) +static int icm42688_decoder_decode(const uint8_t *buffer, enum sensor_channel channel, + size_t channel_idx, uint32_t *fit, uint16_t max_count, + void *data_out) { - return icm42688_one_shot_decode(buffer, fit, cit, channels, values, max_count); + const struct icm42688_decoder_header *header = + (const struct icm42688_decoder_header *)buffer; + + if (header->is_fifo) { + return icm42688_fifo_decode(buffer, channel, channel_idx, fit, max_count, data_out); + } + return icm42688_one_shot_decode(buffer, channel, channel_idx, fit, max_count, data_out); } -static int icm42688_decoder_get_frame_count(const uint8_t *buffer, uint16_t *frame_count) +static int icm42688_decoder_get_frame_count(const uint8_t *buffer, enum sensor_channel channel, + size_t channel_idx, uint16_t *frame_count) { - ARG_UNUSED(buffer); - *frame_count = 1; + const struct icm42688_fifo_data *data = (const struct icm42688_fifo_data *)buffer; + const struct icm42688_decoder_header *header = &data->header; + + if (channel_idx != 0) { + return -ENOTSUP; + } + + if (!header->is_fifo) { + switch (channel) { + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_ACCEL_XYZ: + case SENSOR_CHAN_GYRO_X: + case SENSOR_CHAN_GYRO_Y: + case SENSOR_CHAN_GYRO_Z: + case SENSOR_CHAN_GYRO_XYZ: + case SENSOR_CHAN_DIE_TEMP: + *frame_count = 1; + return 0; + default: + return -ENOTSUP; + } + return 0; + } + + /* Skip the header */ + buffer += sizeof(struct icm42688_fifo_data); + + uint16_t count = 0; + const uint8_t *end = buffer + data->fifo_count; + + while (buffer < end) { + bool is_20b = FIELD_GET(FIFO_HEADER_20, buffer[0]); + int size = is_20b ? 3 : 2; + + if (FIELD_GET(FIFO_HEADER_ACCEL, buffer[0])) { + size += 6; + } + if (FIELD_GET(FIFO_HEADER_GYRO, buffer[0])) { + size += 6; + } + if (FIELD_GET(FIFO_HEADER_TIMESTAMP_FSYNC, buffer[0])) { + size += 2; + } + if (is_20b) { + size += 3; + } + + buffer += size; + ++count; + } + + *frame_count = count; return 0; } -static int icm42688_decoder_get_timestamp(const uint8_t *buffer, uint64_t *timestamp_ns) +static int icm42688_decoder_get_size_info(enum sensor_channel channel, size_t *base_size, + size_t *frame_size) { - const struct icm42688_decoder_header *header = - (const struct icm42688_decoder_header *)buffer; - - *timestamp_ns = header->timestamp; - return 0; + switch (channel) { + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_ACCEL_XYZ: + case SENSOR_CHAN_GYRO_X: + case SENSOR_CHAN_GYRO_Y: + case SENSOR_CHAN_GYRO_Z: + case SENSOR_CHAN_GYRO_XYZ: + *base_size = sizeof(struct sensor_three_axis_data); + *frame_size = sizeof(struct sensor_three_axis_sample_data); + return 0; + case SENSOR_CHAN_DIE_TEMP: + *base_size = sizeof(struct sensor_q31_data); + *frame_size = sizeof(struct sensor_q31_sample_data); + return 0; + default: + return -ENOTSUP; + } } -static int icm42688_decoder_get_shift(const uint8_t *buffer, enum sensor_channel channel_type, - int8_t *shift) +static bool icm24688_decoder_has_trigger(const uint8_t *buffer, enum sensor_trigger_type trigger) { - const struct icm42688_decoder_header *header = - (const struct icm42688_decoder_header *)buffer; + const struct icm42688_fifo_data *edata = (const struct icm42688_fifo_data *)buffer; - return icm42688_get_shift(channel_type, header->accel_fs, header->gyro_fs, shift); + if (!edata->header.is_fifo) { + return false; + } + + switch (trigger) { + case SENSOR_TRIG_DATA_READY: + return FIELD_GET(BIT_INT_STATUS_DATA_RDY, edata->int_status); + case SENSOR_TRIG_FIFO_WATERMARK: + return FIELD_GET(BIT_INT_STATUS_FIFO_THS, edata->int_status); + case SENSOR_TRIG_FIFO_FULL: + return FIELD_GET(BIT_INT_STATUS_FIFO_FULL, edata->int_status); + default: + return false; + } } SENSOR_DECODER_API_DT_DEFINE() = { .get_frame_count = icm42688_decoder_get_frame_count, - .get_timestamp = icm42688_decoder_get_timestamp, - .get_shift = icm42688_decoder_get_shift, + .get_size_info = icm42688_decoder_get_size_info, .decode = icm42688_decoder_decode, + .has_trigger = icm24688_decoder_has_trigger, }; int icm42688_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder) diff --git a/drivers/sensor/icm42688/icm42688_decoder.h b/drivers/sensor/icm42688/icm42688_decoder.h index 2ef806373c9..499cf3d0801 100644 --- a/drivers/sensor/icm42688/icm42688_decoder.h +++ b/drivers/sensor/icm42688/icm42688_decoder.h @@ -18,6 +18,15 @@ struct icm42688_decoder_header { uint8_t reserved: 2; } __attribute__((__packed__)); +struct icm42688_fifo_data { + struct icm42688_decoder_header header; + uint8_t int_status; + uint16_t gyro_odr: 4; + uint16_t accel_odr: 4; + uint16_t fifo_count: 11; + uint16_t reserved: 5; +} __attribute__((__packed__)); + struct icm42688_encoded_data { struct icm42688_decoder_header header; struct { diff --git a/drivers/sensor/icm42688/icm42688_reg.h b/drivers/sensor/icm42688/icm42688_reg.h index dfc348c072c..5f3b58f0b3c 100644 --- a/drivers/sensor/icm42688/icm42688_reg.h +++ b/drivers/sensor/icm42688/icm42688_reg.h @@ -286,4 +286,12 @@ #define MCLK_POLL_ATTEMPTS 100 #define SOFT_RESET_TIME_MS 2 /* 1ms + elbow room */ +/* FIFO header */ +#define FIFO_HEADER_ACCEL BIT(6) +#define FIFO_HEADER_GYRO BIT(5) +#define FIFO_HEADER_20 BIT(4) +#define FIFO_HEADER_TIMESTAMP_FSYNC GENMASK(3, 2) +#define FIFO_HEADER_ODR_ACCEL BIT(1) +#define FIFO_HEADER_ODR_GYRO BIT(0) + #endif /* ZEPHYR_DRIVERS_SENSOR_ICM42688_REG_H_ */ diff --git a/drivers/sensor/icm42688/icm42688_rtio.c b/drivers/sensor/icm42688/icm42688_rtio.c index c1b20689393..ccb9532ee45 100644 --- a/drivers/sensor/icm42688/icm42688_rtio.c +++ b/drivers/sensor/icm42688/icm42688_rtio.c @@ -8,6 +8,7 @@ #include "icm42688.h" #include "icm42688_decoder.h" #include "icm42688_reg.h" +#include "icm42688_rtio.h" #include "icm42688_spi.h" #include @@ -42,7 +43,7 @@ static int icm42688_rtio_sample_fetch(const struct device *dev, int16_t readings return 0; } -int icm42688_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +static int icm42688_submit_one_shot(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) { const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data; const enum sensor_channel *const channels = cfg->channels; @@ -78,4 +79,17 @@ int icm42688_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) return 0; } +int icm42688_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +{ + const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data; + + if (!cfg->is_streaming) { + return icm42688_submit_one_shot(dev, iodev_sqe); + } else if (IS_ENABLED(CONFIG_ICM42688_STREAM)) { + return icm42688_submit_stream(dev, iodev_sqe); + } else { + return -ENOTSUP; + } +} + BUILD_ASSERT(sizeof(struct icm42688_decoder_header) == 9); diff --git a/drivers/sensor/icm42688/icm42688_rtio.h b/drivers/sensor/icm42688/icm42688_rtio.h index 748c8a022b0..888e8e95357 100644 --- a/drivers/sensor/icm42688/icm42688_rtio.h +++ b/drivers/sensor/icm42688/icm42688_rtio.h @@ -7,6 +7,13 @@ #ifndef ZEPHYR_DRIVERS_SENSOR_ICM42688_RTIO_H_ #define ZEPHYR_DRIVERS_SENSOR_ICM42688_RTIO_H_ +#include +#include + int icm42688_submit(const struct device *sensor, struct rtio_iodev_sqe *iodev_sqe); +int icm42688_submit_stream(const struct device *sensor, struct rtio_iodev_sqe *iodev_sqe); + +void icm42688_fifo_event(const struct device *dev); + #endif /* ZEPHYR_DRIVERS_SENSOR_ICM42688_RTIO_H_ */ diff --git a/drivers/sensor/icm42688/icm42688_rtio_stream.c b/drivers/sensor/icm42688/icm42688_rtio_stream.c new file mode 100644 index 00000000000..57d1a66cfde --- /dev/null +++ b/drivers/sensor/icm42688/icm42688_rtio_stream.c @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "icm42688.h" +#include "icm42688_decoder.h" +#include "icm42688_reg.h" +#include "icm42688_rtio.h" + +LOG_MODULE_DECLARE(ICM42688_RTIO); + +int icm42688_submit_stream(const struct device *sensor, struct rtio_iodev_sqe *iodev_sqe) +{ + const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data; + struct icm42688_dev_data *data = sensor->data; + struct icm42688_cfg new_config = data->cfg; + + new_config.interrupt1_drdy = false; + new_config.interrupt1_fifo_ths = false; + new_config.interrupt1_fifo_full = false; + for (int i = 0; i < cfg->count; ++i) { + switch (cfg->triggers[i].trigger) { + case SENSOR_TRIG_DATA_READY: + new_config.interrupt1_drdy = true; + break; + case SENSOR_TRIG_FIFO_WATERMARK: + new_config.interrupt1_fifo_ths = true; + break; + case SENSOR_TRIG_FIFO_FULL: + new_config.interrupt1_fifo_full = true; + break; + default: + LOG_DBG("Trigger (%d) not supported", cfg->triggers[i].trigger); + break; + } + } + + if (new_config.interrupt1_drdy != data->cfg.interrupt1_drdy || + new_config.interrupt1_fifo_ths != data->cfg.interrupt1_fifo_ths || + new_config.interrupt1_fifo_full != data->cfg.interrupt1_fifo_full) { + int rc = icm42688_safely_configure(sensor, &new_config); + + if (rc != 0) { + LOG_ERR("Failed to configure sensor"); + return rc; + } + } + + data->streaming_sqe = iodev_sqe; + return 0; +} + +static void icm42688_complete_cb(struct rtio *r, const struct rtio_sqe *sqe, void *arg) +{ + const struct device *dev = arg; + struct icm42688_dev_data *drv_data = dev->data; + const struct icm42688_dev_cfg *drv_cfg = dev->config; + struct rtio_iodev_sqe *iodev_sqe = sqe->userdata; + + rtio_iodev_sqe_ok(iodev_sqe, drv_data->fifo_count); + + gpio_pin_interrupt_configure_dt(&drv_cfg->gpio_int1, GPIO_INT_EDGE_TO_ACTIVE); +} + +static void icm42688_fifo_count_cb(struct rtio *r, const struct rtio_sqe *sqe, void *arg) +{ + const struct device *dev = arg; + struct icm42688_dev_data *drv_data = dev->data; + const struct icm42688_dev_cfg *drv_cfg = dev->config; + struct rtio_iodev *spi_iodev = drv_data->spi_iodev; + uint8_t *fifo_count_buf = (uint8_t *)&drv_data->fifo_count; + uint16_t fifo_count = ((fifo_count_buf[0] << 8) | fifo_count_buf[1]); + + drv_data->fifo_count = fifo_count; + + /* Pull a operation from our device iodev queue, validated to only be reads */ + struct rtio_iodev_sqe *iodev_sqe = drv_data->streaming_sqe; + + drv_data->streaming_sqe = NULL; + + /* Not inherently an underrun/overrun as we may have a buffer to fill next time */ + if (iodev_sqe == NULL) { + LOG_DBG("No pending SQE"); + gpio_pin_interrupt_configure_dt(&drv_cfg->gpio_int1, GPIO_INT_EDGE_TO_ACTIVE); + return; + } + + const size_t packet_size = drv_data->cfg.fifo_hires ? 20 : 16; + const size_t min_read_size = sizeof(struct icm42688_fifo_data) + packet_size; + const size_t ideal_read_size = sizeof(struct icm42688_fifo_data) + fifo_count; + uint8_t *buf; + uint32_t buf_len; + + if (rtio_sqe_rx_buf(iodev_sqe, min_read_size, ideal_read_size, &buf, &buf_len) != 0) { + LOG_ERR("Failed to get buffer"); + rtio_iodev_sqe_err(iodev_sqe, -ENOMEM); + return; + } + LOG_DBG("Requesting buffer [%u, %u] got %u", (unsigned int)min_read_size, + (unsigned int)ideal_read_size, buf_len); + + /* Read FIFO and call back to rtio with rtio_sqe completion */ + /* TODO is packet format even needed? the fifo has a header per packet + * already + */ + struct icm42688_fifo_data hdr = { + .header = { + .is_fifo = true, + .gyro_fs = drv_data->cfg.gyro_fs, + .accel_fs = drv_data->cfg.accel_fs, + .timestamp = drv_data->timestamp, + }, + .int_status = drv_data->int_status, + .gyro_odr = drv_data->cfg.gyro_odr, + .accel_odr = drv_data->cfg.accel_odr, + }; + uint32_t buf_avail = buf_len; + + memcpy(buf, &hdr, sizeof(hdr)); + buf_avail -= sizeof(hdr); + + uint32_t read_len = MIN(fifo_count, buf_avail); + uint32_t pkts = read_len / packet_size; + + read_len = pkts * packet_size; + ((struct icm42688_fifo_data *)buf)->fifo_count = read_len; + + __ASSERT_NO_MSG(read_len % pkt_size == 0); + + uint8_t *read_buf = buf + sizeof(hdr); + + /* Flush out completions */ + struct rtio_cqe *cqe; + + do { + cqe = rtio_cqe_consume(r); + if (cqe != NULL) { + rtio_cqe_release(r, cqe); + } + } while (cqe != NULL); + + /* Setup new rtio chain to read the fifo data and report then check the + * result + */ + struct rtio_sqe *write_fifo_addr = rtio_sqe_acquire(r); + struct rtio_sqe *read_fifo_data = rtio_sqe_acquire(r); + struct rtio_sqe *complete_op = rtio_sqe_acquire(r); + const uint8_t reg_addr = REG_SPI_READ_BIT | FIELD_GET(REG_ADDRESS_MASK, REG_FIFO_DATA); + + rtio_sqe_prep_tiny_write(write_fifo_addr, spi_iodev, RTIO_PRIO_NORM, ®_addr, 1, NULL); + write_fifo_addr->flags = RTIO_SQE_TRANSACTION; + rtio_sqe_prep_read(read_fifo_data, spi_iodev, RTIO_PRIO_NORM, read_buf, read_len, + iodev_sqe); + + rtio_sqe_prep_callback(complete_op, icm42688_complete_cb, (void *)dev, iodev_sqe); + + rtio_submit(r, 0); +} + +static struct sensor_stream_trigger * +icm42688_get_read_config_trigger(const struct sensor_read_config *cfg, + enum sensor_trigger_type trig) +{ + for (int i = 0; i < cfg->count; ++i) { + if (cfg->triggers[i].trigger == trig) { + return &cfg->triggers[i]; + } + } + LOG_DBG("Unsupported trigger (%d)", trig); + return NULL; +} + +static void icm42688_int_status_cb(struct rtio *r, const struct rtio_sqe *sqr, void *arg) +{ + const struct device *dev = arg; + struct icm42688_dev_data *drv_data = dev->data; + const struct icm42688_dev_cfg *drv_cfg = dev->config; + struct rtio_iodev *spi_iodev = drv_data->spi_iodev; + struct rtio_iodev_sqe *streaming_sqe = drv_data->streaming_sqe; + struct sensor_read_config *read_config; + + if (streaming_sqe == NULL) { + return; + } + + read_config = (struct sensor_read_config *)streaming_sqe->sqe.iodev->data; + __ASSERT_NO_MSG(read_config != NULL); + + if (!read_config->is_streaming) { + /* Oops, not really configured for streaming data */ + return; + } + + struct sensor_stream_trigger *fifo_ths_cfg = + icm42688_get_read_config_trigger(read_config, SENSOR_TRIG_FIFO_WATERMARK); + bool has_fifo_ths_trig = fifo_ths_cfg != NULL && + FIELD_GET(BIT_INT_STATUS_FIFO_THS, drv_data->int_status) != 0; + + struct sensor_stream_trigger *fifo_full_cfg = + icm42688_get_read_config_trigger(read_config, SENSOR_TRIG_FIFO_FULL); + bool has_fifo_full_trig = fifo_full_cfg != NULL && + FIELD_GET(BIT_INT_STATUS_FIFO_FULL, drv_data->int_status) != 0; + + if (!has_fifo_ths_trig && !has_fifo_full_trig) { + gpio_pin_interrupt_configure_dt(&drv_cfg->gpio_int1, GPIO_INT_EDGE_TO_ACTIVE); + return; + } + + /* Flush completions */ + struct rtio_cqe *cqe; + + do { + cqe = rtio_cqe_consume(r); + if (cqe != NULL) { + rtio_cqe_release(r, cqe); + } + } while (cqe != NULL); + + enum sensor_stream_data_opt data_opt; + + if (has_fifo_ths_trig && !has_fifo_full_trig) { + /* Only care about fifo threshold */ + data_opt = fifo_ths_cfg->opt; + } else if (!has_fifo_ths_trig && has_fifo_full_trig) { + /* Only care about fifo full */ + data_opt = fifo_full_cfg->opt; + } else { + /* Both fifo threshold and full */ + data_opt = MIN(fifo_ths_cfg->opt, fifo_full_cfg->opt); + } + + if (data_opt == SENSOR_STREAM_DATA_NOP || data_opt == SENSOR_STREAM_DATA_DROP) { + uint8_t *buf; + uint32_t buf_len; + + /* Clear streaming_sqe since we're done with the call */ + drv_data->streaming_sqe = NULL; + if (rtio_sqe_rx_buf(streaming_sqe, sizeof(struct icm42688_fifo_data), + sizeof(struct icm42688_fifo_data), &buf, &buf_len) != 0) { + rtio_iodev_sqe_err(streaming_sqe, -ENOMEM); + return; + } + + struct icm42688_fifo_data *data = (struct icm42688_fifo_data *)buf; + + memset(buf, 0, buf_len); + data->header.timestamp = drv_data->timestamp; + data->int_status = drv_data->int_status; + data->fifo_count = 0; + rtio_iodev_sqe_ok(streaming_sqe, 0); + gpio_pin_interrupt_configure_dt(&drv_cfg->gpio_int1, GPIO_INT_EDGE_TO_ACTIVE); + if (data_opt == SENSOR_STREAM_DATA_DROP) { + /* Flush the FIFO */ + struct rtio_sqe *write_signal_path_reset = rtio_sqe_acquire(r); + uint8_t write_buffer[] = { + FIELD_GET(REG_ADDRESS_MASK, REG_SIGNAL_PATH_RESET), + BIT_FIFO_FLUSH, + }; + + rtio_sqe_prep_tiny_write(write_signal_path_reset, spi_iodev, RTIO_PRIO_NORM, + write_buffer, ARRAY_SIZE(write_buffer), NULL); + /* TODO Add a new flag for fire-and-forget so we don't have to block here */ + rtio_submit(r, 1); + ARG_UNUSED(rtio_cqe_consume(r)); + } + return; + } + + /* We need the data, read the fifo length */ + struct rtio_sqe *write_fifo_count_reg = rtio_sqe_acquire(r); + struct rtio_sqe *read_fifo_count = rtio_sqe_acquire(r); + struct rtio_sqe *check_fifo_count = rtio_sqe_acquire(r); + uint8_t reg = REG_SPI_READ_BIT | FIELD_GET(REG_ADDRESS_MASK, REG_FIFO_COUNTH); + uint8_t *read_buf = (uint8_t *)&drv_data->fifo_count; + + rtio_sqe_prep_tiny_write(write_fifo_count_reg, spi_iodev, RTIO_PRIO_NORM, ®, 1, NULL); + write_fifo_count_reg->flags = RTIO_SQE_TRANSACTION; + rtio_sqe_prep_read(read_fifo_count, spi_iodev, RTIO_PRIO_NORM, read_buf, 2, NULL); + rtio_sqe_prep_callback(check_fifo_count, icm42688_fifo_count_cb, arg, NULL); + + rtio_submit(r, 0); +} + +void icm42688_fifo_event(const struct device *dev) +{ + struct icm42688_dev_data *drv_data = dev->data; + struct rtio_iodev *spi_iodev = drv_data->spi_iodev; + struct rtio *r = drv_data->r; + + if (drv_data->streaming_sqe == NULL) { + return; + } + + drv_data->timestamp = k_ticks_to_ns_floor64(k_uptime_ticks()); + + /* + * Setup rtio chain of ops with inline calls to make decisions + * 1. read int status + * 2. call to check int status and get pending RX operation + * 4. read fifo len + * 5. call to determine read len + * 6. read fifo + * 7. call to report completion + */ + struct rtio_sqe *write_int_reg = rtio_sqe_acquire(r); + struct rtio_sqe *read_int_reg = rtio_sqe_acquire(r); + struct rtio_sqe *check_int_status = rtio_sqe_acquire(r); + uint8_t reg = REG_SPI_READ_BIT | FIELD_GET(REG_ADDRESS_MASK, REG_INT_STATUS); + + rtio_sqe_prep_tiny_write(write_int_reg, spi_iodev, RTIO_PRIO_NORM, ®, 1, NULL); + write_int_reg->flags = RTIO_SQE_TRANSACTION; + rtio_sqe_prep_read(read_int_reg, spi_iodev, RTIO_PRIO_NORM, &drv_data->int_status, 1, NULL); + rtio_sqe_prep_callback(check_int_status, icm42688_int_status_cb, (void *)dev, NULL); + rtio_submit(r, 0); +} diff --git a/drivers/sensor/icm42688/icm42688_trigger.c b/drivers/sensor/icm42688/icm42688_trigger.c index adaecf84baa..32b60f3cd75 100644 --- a/drivers/sensor/icm42688/icm42688_trigger.c +++ b/drivers/sensor/icm42688/icm42688_trigger.c @@ -12,6 +12,7 @@ #include "icm42688.h" #include "icm42688_reg.h" +#include "icm42688_rtio.h" #include "icm42688_spi.h" #include "icm42688_trigger.h" @@ -30,6 +31,9 @@ static void icm42688_gpio_callback(const struct device *dev, struct gpio_callbac #elif defined(CONFIG_ICM42688_TRIGGER_GLOBAL_THREAD) k_work_submit(&data->work); #endif + if (IS_ENABLED(CONFIG_ICM42688_STREAM)) { + icm42688_fifo_event(data->dev); + } } #if defined(CONFIG_ICM42688_TRIGGER_OWN_THREAD) || defined(CONFIG_ICM42688_TRIGGER_GLOBAL_THREAD) @@ -90,6 +94,8 @@ int icm42688_trigger_set(const struct device *dev, const struct sensor_trigger * switch (trig->type) { case SENSOR_TRIG_DATA_READY: + case SENSOR_TRIG_FIFO_WATERMARK: + case SENSOR_TRIG_FIFO_FULL: data->data_ready_handler = handler; data->data_ready_trigger = trig; @@ -146,7 +152,7 @@ int icm42688_trigger_init(const struct device *dev) return gpio_pin_interrupt_configure_dt(&cfg->gpio_int1, GPIO_INT_EDGE_TO_ACTIVE); } -int icm42688_trigger_enable_interrupt(const struct device *dev) +int icm42688_trigger_enable_interrupt(const struct device *dev, struct icm42688_cfg *new_cfg) { int res; const struct icm42688_dev_cfg *cfg = dev->config; @@ -164,9 +170,19 @@ int icm42688_trigger_enable_interrupt(const struct device *dev) return res; } - /* enable data ready interrupt on INT1 pin */ - return icm42688_spi_single_write(&cfg->spi, REG_INT_SOURCE0, - FIELD_PREP(BIT_UI_DRDY_INT1_EN, 1)); + /* enable interrupts on INT1 pin */ + uint8_t value = 0; + + if (new_cfg->interrupt1_drdy) { + value |= FIELD_PREP(BIT_UI_DRDY_INT1_EN, 1); + } + if (new_cfg->interrupt1_fifo_ths) { + value |= FIELD_PREP(BIT_FIFO_THS_INT1_EN, 1); + } + if (new_cfg->interrupt1_fifo_full) { + value |= FIELD_PREP(BIT_FIFO_FULL_INT1_EN, 1); + } + return icm42688_spi_single_write(&cfg->spi, REG_INT_SOURCE0, value); } void icm42688_lock(const struct device *dev) diff --git a/drivers/sensor/icm42688/icm42688_trigger.h b/drivers/sensor/icm42688/icm42688_trigger.h index 5ed382eb0d4..e0397591618 100644 --- a/drivers/sensor/icm42688/icm42688_trigger.h +++ b/drivers/sensor/icm42688/icm42688_trigger.h @@ -26,9 +26,10 @@ int icm42688_trigger_init(const struct device *dev); * @brief enable the trigger gpio interrupt * * @param dev icm42688 device pointer + * @param new_cfg New configuration to use for the device * @return int 0 on success, negative error code otherwise */ -int icm42688_trigger_enable_interrupt(const struct device *dev); +int icm42688_trigger_enable_interrupt(const struct device *dev, struct icm42688_cfg *new_cfg); /** * @brief lock access to the icm42688 device driver diff --git a/drivers/sensor/iis2dh/iis2dh_trigger.c b/drivers/sensor/iis2dh/iis2dh_trigger.c index edbcf01493b..d108c52c398 100644 --- a/drivers/sensor/iis2dh/iis2dh_trigger.c +++ b/drivers/sensor/iis2dh/iis2dh_trigger.c @@ -112,8 +112,13 @@ static void iis2dh_gpio_callback(const struct device *dev, } #ifdef CONFIG_IIS2DH_TRIGGER_OWN_THREAD -static void iis2dh_thread(struct iis2dh_data *iis2dh) +static void iis2dh_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct iis2dh_data *iis2dh = p1; + while (1) { k_sem_take(&iis2dh->gpio_sem, K_FOREVER); iis2dh_handle_interrupt(iis2dh->dev); @@ -149,7 +154,7 @@ int iis2dh_init_interrupt(const struct device *dev) k_thread_create(&iis2dh->thread, iis2dh->thread_stack, CONFIG_IIS2DH_THREAD_STACK_SIZE, - (k_thread_entry_t)iis2dh_thread, iis2dh, + iis2dh_thread, iis2dh, 0, NULL, K_PRIO_COOP(CONFIG_IIS2DH_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_IIS2DH_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/iis2dlpc/iis2dlpc_trigger.c b/drivers/sensor/iis2dlpc/iis2dlpc_trigger.c index 381e3318aa5..90cdb4b857f 100644 --- a/drivers/sensor/iis2dlpc/iis2dlpc_trigger.c +++ b/drivers/sensor/iis2dlpc/iis2dlpc_trigger.c @@ -233,8 +233,13 @@ static void iis2dlpc_gpio_callback(const struct device *dev, } #ifdef CONFIG_IIS2DLPC_TRIGGER_OWN_THREAD -static void iis2dlpc_thread(struct iis2dlpc_data *iis2dlpc) +static void iis2dlpc_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct iis2dlpc_data *iis2dlpc = p1; + while (1) { k_sem_take(&iis2dlpc->gpio_sem, K_FOREVER); iis2dlpc_handle_interrupt(iis2dlpc->dev); @@ -270,7 +275,7 @@ int iis2dlpc_init_interrupt(const struct device *dev) k_thread_create(&iis2dlpc->thread, iis2dlpc->thread_stack, CONFIG_IIS2DLPC_THREAD_STACK_SIZE, - (k_thread_entry_t)iis2dlpc_thread, iis2dlpc, + iis2dlpc_thread, iis2dlpc, NULL, NULL, K_PRIO_COOP(CONFIG_IIS2DLPC_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_IIS2DLPC_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/iis2iclx/iis2iclx_trigger.c b/drivers/sensor/iis2iclx/iis2iclx_trigger.c index 6360ab69d72..174583c75e7 100644 --- a/drivers/sensor/iis2iclx/iis2iclx_trigger.c +++ b/drivers/sensor/iis2iclx/iis2iclx_trigger.c @@ -182,8 +182,13 @@ static void iis2iclx_gpio_callback(const struct device *dev, } #ifdef CONFIG_IIS2ICLX_TRIGGER_OWN_THREAD -static void iis2iclx_thread(struct iis2iclx_data *iis2iclx) +static void iis2iclx_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct iis2iclx_data *iis2iclx = p1; + while (1) { k_sem_take(&iis2iclx->gpio_sem, K_FOREVER); iis2iclx_handle_interrupt(iis2iclx->dev); @@ -218,7 +223,7 @@ int iis2iclx_init_interrupt(const struct device *dev) k_thread_create(&iis2iclx->thread, iis2iclx->thread_stack, CONFIG_IIS2ICLX_THREAD_STACK_SIZE, - (k_thread_entry_t)iis2iclx_thread, + iis2iclx_thread, iis2iclx, NULL, NULL, K_PRIO_COOP(CONFIG_IIS2ICLX_THREAD_PRIORITY), 0, K_NO_WAIT); diff --git a/drivers/sensor/iis2mdc/iis2mdc_trigger.c b/drivers/sensor/iis2mdc/iis2mdc_trigger.c index 049cc5c3b95..fc9f203b033 100644 --- a/drivers/sensor/iis2mdc/iis2mdc_trigger.c +++ b/drivers/sensor/iis2mdc/iis2mdc_trigger.c @@ -83,8 +83,13 @@ static void iis2mdc_gpio_callback(const struct device *dev, } #ifdef CONFIG_IIS2MDC_TRIGGER_OWN_THREAD -static void iis2mdc_thread(struct iis2mdc_data *iis2mdc) +static void iis2mdc_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct iis2mdc_data *iis2mdc = p1; + while (1) { k_sem_take(&iis2mdc->gpio_sem, K_FOREVER); iis2mdc_handle_interrupt(iis2mdc->dev); @@ -118,7 +123,7 @@ int iis2mdc_init_interrupt(const struct device *dev) k_sem_init(&iis2mdc->gpio_sem, 0, K_SEM_MAX_LIMIT); k_thread_create(&iis2mdc->thread, iis2mdc->thread_stack, CONFIG_IIS2MDC_THREAD_STACK_SIZE, - (k_thread_entry_t)iis2mdc_thread, iis2mdc, + iis2mdc_thread, iis2mdc, NULL, NULL, K_PRIO_COOP(CONFIG_IIS2MDC_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_IIS2MDC_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/iis3dhhc/iis3dhhc_trigger.c b/drivers/sensor/iis3dhhc/iis3dhhc_trigger.c index ff964e30efc..0ce2df490b3 100644 --- a/drivers/sensor/iis3dhhc/iis3dhhc_trigger.c +++ b/drivers/sensor/iis3dhhc/iis3dhhc_trigger.c @@ -99,8 +99,13 @@ static void iis3dhhc_gpio_callback(const struct device *dev, } #ifdef CONFIG_IIS3DHHC_TRIGGER_OWN_THREAD -static void iis3dhhc_thread(struct iis3dhhc_data *iis3dhhc) +static void iis3dhhc_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct iis3dhhc_data *iis3dhhc = p1; + while (1) { k_sem_take(&iis3dhhc->gpio_sem, K_FOREVER); iis3dhhc_handle_interrupt(iis3dhhc->dev); @@ -136,7 +141,7 @@ int iis3dhhc_init_interrupt(const struct device *dev) k_thread_create(&iis3dhhc->thread, iis3dhhc->thread_stack, CONFIG_IIS3DHHC_THREAD_STACK_SIZE, - (k_thread_entry_t)iis3dhhc_thread, iis3dhhc, + iis3dhhc_thread, iis3dhhc, NULL, NULL, K_PRIO_COOP(CONFIG_IIS3DHHC_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_IIS3DHHC_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/isl29035/isl29035_trigger.c b/drivers/sensor/isl29035/isl29035_trigger.c index db4857917c6..a0a5d2af21f 100644 --- a/drivers/sensor/isl29035/isl29035_trigger.c +++ b/drivers/sensor/isl29035/isl29035_trigger.c @@ -121,8 +121,12 @@ static void isl29035_thread_cb(const struct device *dev) } #ifdef CONFIG_ISL29035_TRIGGER_OWN_THREAD -static void isl29035_thread(const struct device *dev) +static void isl29035_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; struct isl29035_driver_data *drv_data = dev->data; while (1) { @@ -205,7 +209,7 @@ int isl29035_init_interrupt(const struct device *dev) k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_ISL29035_THREAD_STACK_SIZE, - (k_thread_entry_t)isl29035_thread, + isl29035_thread, (void *)dev, NULL, NULL, K_PRIO_COOP(CONFIG_ISL29035_THREAD_PRIORITY), 0, K_NO_WAIT); diff --git a/drivers/sensor/ism330dhcx/ism330dhcx_trigger.c b/drivers/sensor/ism330dhcx/ism330dhcx_trigger.c index 788313b85c5..ac4c16b9506 100644 --- a/drivers/sensor/ism330dhcx/ism330dhcx_trigger.c +++ b/drivers/sensor/ism330dhcx/ism330dhcx_trigger.c @@ -226,8 +226,13 @@ static void ism330dhcx_gpio_callback(const struct device *dev, } #ifdef CONFIG_ISM330DHCX_TRIGGER_OWN_THREAD -static void ism330dhcx_thread(struct ism330dhcx_data *ism330dhcx) +static void ism330dhcx_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct ism330dhcx_data *ism330dhcx = p1; + while (1) { k_sem_take(&ism330dhcx->gpio_sem, K_FOREVER); ism330dhcx_handle_interrupt(ism330dhcx->dev); @@ -261,7 +266,7 @@ int ism330dhcx_init_interrupt(const struct device *dev) k_thread_create(&ism330dhcx->thread, ism330dhcx->thread_stack, CONFIG_ISM330DHCX_THREAD_STACK_SIZE, - (k_thread_entry_t)ism330dhcx_thread, + ism330dhcx_thread, ism330dhcx, NULL, NULL, K_PRIO_COOP(CONFIG_ISM330DHCX_THREAD_PRIORITY), 0, K_NO_WAIT); diff --git a/drivers/sensor/lis2dh/lis2dh.c b/drivers/sensor/lis2dh/lis2dh.c index 3aaa8ab83fe..a12bb0e097d 100644 --- a/drivers/sensor/lis2dh/lis2dh.c +++ b/drivers/sensor/lis2dh/lis2dh.c @@ -520,7 +520,9 @@ static int lis2dh_pm_action(const struct device *dev, .gpio_int = \ COND_CODE_1(ANYM_ON_INT1(inst), \ (GPIO_DT_SPEC_INST_GET_BY_IDX_COND(inst, irq_gpios, 0)), \ - (GPIO_DT_SPEC_INST_GET_BY_IDX_COND(inst, irq_gpios, 1))), + (GPIO_DT_SPEC_INST_GET_BY_IDX_COND(inst, irq_gpios, 1))), \ + .int1_mode = DT_INST_PROP(inst, int1_gpio_config), \ + .int2_mode = DT_INST_PROP(inst, int2_gpio_config), #else #define LIS2DH_CFG_INT(inst) #endif /* CONFIG_LIS2DH_TRIGGER */ diff --git a/drivers/sensor/lis2dh/lis2dh.h b/drivers/sensor/lis2dh/lis2dh.h index 72cc710ed9e..f746e983e28 100644 --- a/drivers/sensor/lis2dh/lis2dh.h +++ b/drivers/sensor/lis2dh/lis2dh.h @@ -29,11 +29,9 @@ #define LIS2DH_AUTOINCREMENT_ADDR BIT(7) #define LIS2DH_REG_CTRL0 0x1e -#define LIS2DH_SDO_PU_DISC_SHIFT 7 -#define LIS2DH_SDO_PU_DISC_MASK BIT(LIS2DH_SDO_PU_DISC_SHIFT) +#define LIS2DH_SDO_PU_DISC_MASK BIT(7) #define LIS2DH_REG_CTRL1 0x20 -#define LIS2DH_ACCEL_XYZ_SHIFT 0 #define LIS2DH_ACCEL_X_EN_BIT BIT(0) #define LIS2DH_ACCEL_Y_EN_BIT BIT(1) #define LIS2DH_ACCEL_Z_EN_BIT BIT(2) @@ -91,14 +89,15 @@ #define LIS2DH_HPIS2_EN_BIT BIT(1) #define LIS2DH_FDS_EN_BIT BIT(3) -#define LIS2DH_HPIS_EN_SHIFT 0 -#define LIS2DH_HPIS_EN_MASK BIT_MASK(2) << LIS2DH_HPIS_EN_SHIFT +#define LIS2DH_HPIS_EN_MASK BIT_MASK(2) #define LIS2DH_REG_CTRL3 0x22 -#define LIS2DH_EN_DRDY1_INT1_SHIFT 4 -#define LIS2DH_EN_DRDY1_INT1 BIT(LIS2DH_EN_DRDY1_INT1_SHIFT) +#define LIS2DH_EN_CLICK_INT1 BIT(7) +#define LIS2DH_EN_IA_INT1 BIT(6) +#define LIS2DH_EN_DRDY1_INT1 BIT(4) #define LIS2DH_REG_CTRL4 0x23 +#define LIS2DH_CTRL4_BDU_BIT BIT(7) #define LIS2DH_FS_SHIFT 4 #define LIS2DH_FS_MASK (BIT_MASK(2) << LIS2DH_FS_SHIFT) @@ -122,16 +121,12 @@ #endif #define LIS2DH_REG_CTRL5 0x24 -#define LIS2DH_LIR_INT2_SHIFT 1 -#define LIS2DH_LIR_INT1_SHIFT 3 -#define LIS2DH_EN_LIR_INT2 BIT(LIS2DH_LIR_INT2_SHIFT) -#define LIS2DH_EN_LIR_INT1 BIT(LIS2DH_LIR_INT1_SHIFT) +#define LIS2DH_EN_LIR_INT2 BIT(1) +#define LIS2DH_EN_LIR_INT1 BIT(3) #define LIS2DH_REG_CTRL6 0x25 -#define LIS2DH_EN_INT2_INT2_SHIFT 5 -#define LIS2DH_EN_INT2_INT2 BIT(LIS2DH_EN_INT2_INT2_SHIFT) -#define LIS2DH_EN_INT1_INT1_SHIFT 6 -#define LIS2DH_EN_INT1_INT1 BIT(LIS2DH_EN_INT1_INT1_SHIFT) +#define LIS2DH_EN_CLICK_INT2 BIT(7) +#define LIS2DH_EN_IA_INT2 BIT(5) #define LIS2DH_REG_REFERENCE 0x26 @@ -164,8 +159,8 @@ #define LIS2DH_REG_INT2_DUR 0x37 #define LIS2DH_INT_CFG_MODE_SHIFT 6 -#define LIS2DH_INT_CFG_AOI_CFG BIT(LIS2DH_INT_CFG_MODE_SHIFT + 1) -#define LIS2DH_INT_CFG_6D_CFG BIT(LIS2DH_INT_CFG_MODE_SHIFT) +#define LIS2DH_INT_CFG_AOI_CFG BIT(7) +#define LIS2DH_INT_CFG_6D_CFG BIT(6) #define LIS2DH_INT_CFG_ZHIE_ZUPE BIT(5) #define LIS2DH_INT_CFG_ZLIE_ZDOWNE BIT(4) #define LIS2DH_INT_CFG_YHIE_YUPE BIT(3) @@ -173,11 +168,26 @@ #define LIS2DH_INT_CFG_XHIE_XUPE BIT(1) #define LIS2DH_INT_CFG_XLIE_XDOWNE BIT(0) +#define LIS2DH_REG_CFG_CLICK 0x38 +#define LIS2DH_EN_CLICK_ZD BIT(5) +#define LIS2DH_EN_CLICK_ZS BIT(4) +#define LIS2DH_EN_CLICK_YD BIT(3) +#define LIS2DH_EN_CLICK_YS BIT(2) +#define LIS2DH_EN_CLICK_XD BIT(1) +#define LIS2DH_EN_CLICK_XS BIT(0) + +#define LIS2DH_REG_CLICK_SRC 0x39 +#define LIS2DH_CLICK_SRC_DCLICK BIT(5) +#define LIS2DH_CLICK_SRC_SCLICK BIT(4) + +#define LIS2DH_REG_CFG_CLICK_THS 0x3A +#define LIS2DH_CLICK_LIR BIT(7) + +#define LIS2DH_REG_TIME_LIMIT 0x3B + /* sample buffer size includes status register */ #define LIS2DH_BUF_SZ 7 -#define LIS2DH_CTRL4_BDU_BIT BIT(7) - union lis2dh_sample { uint8_t raw[LIS2DH_BUF_SZ]; struct { @@ -209,6 +219,8 @@ struct lis2dh_config { #ifdef CONFIG_LIS2DH_TRIGGER const struct gpio_dt_spec gpio_drdy; const struct gpio_dt_spec gpio_int; + const uint8_t int1_mode; + const uint8_t int2_mode; #endif /* CONFIG_LIS2DH_TRIGGER */ struct { bool is_lsm303agr_dev : 1; @@ -260,6 +272,8 @@ struct lis2dh_data { const struct sensor_trigger *trig_drdy; sensor_trigger_handler_t handler_anymotion; const struct sensor_trigger *trig_anymotion; + sensor_trigger_handler_t handler_tap; + const struct sensor_trigger *trig_tap; atomic_t trig_flags; enum sensor_channel chan_drdy; diff --git a/drivers/sensor/lis2dh/lis2dh_trigger.c b/drivers/sensor/lis2dh/lis2dh_trigger.c index 5b017ff0013..3c075b2a0e8 100644 --- a/drivers/sensor/lis2dh/lis2dh_trigger.c +++ b/drivers/sensor/lis2dh/lis2dh_trigger.c @@ -18,6 +18,14 @@ LOG_MODULE_DECLARE(lis2dh, CONFIG_SENSOR_LOG_LEVEL); #include "lis2dh.h" +static const gpio_flags_t gpio_int_cfg[5] = { + GPIO_INT_EDGE, + GPIO_INT_EDGE_RISING, + GPIO_INT_EDGE_FALLING, + GPIO_INT_LEVEL_HIGH, + GPIO_INT_LEVEL_LOW, + }; + static inline void setup_int1(const struct device *dev, bool enable) { @@ -25,7 +33,7 @@ static inline void setup_int1(const struct device *dev, gpio_pin_interrupt_configure_dt(&cfg->gpio_drdy, enable - ? GPIO_INT_LEVEL_ACTIVE + ? gpio_int_cfg[cfg->int1_mode] : GPIO_INT_DISABLE); } @@ -123,13 +131,14 @@ static inline void setup_int2(const struct device *dev, gpio_pin_interrupt_configure_dt(&cfg->gpio_int, enable - ? GPIO_INT_LEVEL_ACTIVE + ? gpio_int_cfg[cfg->int2_mode] : GPIO_INT_DISABLE); } -static int lis2dh_trigger_anym_set(const struct device *dev, - sensor_trigger_handler_t handler, - const struct sensor_trigger *trig) +/* common handler for any motion and tap triggers */ +static int lis2dh_trigger_anym_tap_set(const struct device *dev, + sensor_trigger_handler_t handler, + const struct sensor_trigger *trig) { const struct lis2dh_config *cfg = dev->config; struct lis2dh_data *lis2dh = dev->data; @@ -152,19 +161,34 @@ static int lis2dh_trigger_anym_set(const struct device *dev, } /* disable any movement interrupt events */ - status = lis2dh->hw_tf->write_reg( - dev, - cfg->hw.anym_on_int1 ? LIS2DH_REG_INT1_CFG : LIS2DH_REG_INT2_CFG, - 0); + status = lis2dh->hw_tf->write_reg(dev, + cfg->hw.anym_on_int1 ? + LIS2DH_REG_INT1_CFG : + LIS2DH_REG_INT2_CFG, + 0); + /* disable any click interrupt events */ + status = lis2dh->hw_tf->write_reg(dev, + LIS2DH_REG_CFG_CLICK, + 0); /* make sure any pending interrupt is cleared */ - status = lis2dh->hw_tf->read_reg( - dev, - cfg->hw.anym_on_int1 ? LIS2DH_REG_INT1_SRC : LIS2DH_REG_INT2_SRC, - ®_val); + status = lis2dh->hw_tf->read_reg(dev, + cfg->hw.anym_on_int1 ? + LIS2DH_REG_INT1_SRC : + LIS2DH_REG_INT2_SRC, + ®_val); + status = lis2dh->hw_tf->read_reg(dev, + LIS2DH_REG_CLICK_SRC, + ®_val); + + if (trig->type == SENSOR_TRIG_DELTA) { + lis2dh->handler_anymotion = handler; + lis2dh->trig_anymotion = trig; + } else if (trig->type == SENSOR_TRIG_TAP) { + lis2dh->handler_tap = handler; + lis2dh->trig_tap = trig; + } - lis2dh->handler_anymotion = handler; - lis2dh->trig_anymotion = trig; if ((handler == NULL) || (status < 0)) { return status; } @@ -181,17 +205,71 @@ static int lis2dh_trigger_anym_set(const struct device *dev, return 0; } +static int lis2dh_trigger_anym_set(const struct device *dev, + sensor_trigger_handler_t handler, + const struct sensor_trigger *trig) +{ + return lis2dh_trigger_anym_tap_set(dev, handler, trig); +} + +static int lis2dh_trigger_tap_set(const struct device *dev, + sensor_trigger_handler_t handler, + const struct sensor_trigger *trig) +{ + return lis2dh_trigger_anym_tap_set(dev, handler, trig); +} + static int lis2dh_start_trigger_int2(const struct device *dev) { struct lis2dh_data *lis2dh = dev->data; const struct lis2dh_config *cfg = dev->config; + int status = 0; + uint8_t reg = 0, mask = 0, val = 0; setup_int2(dev, true); - return lis2dh->hw_tf->write_reg( - dev, - cfg->hw.anym_on_int1 ? LIS2DH_REG_INT1_CFG : LIS2DH_REG_INT2_CFG, - (cfg->hw.anym_mode << LIS2DH_INT_CFG_MODE_SHIFT) | LIS2DH_ANYM_CFG); + bool has_anyt = (lis2dh->handler_tap != NULL); + bool has_anym = (lis2dh->handler_anymotion != NULL); + + /* configure any motion interrupt */ + reg = cfg->hw.anym_on_int1 ? LIS2DH_REG_INT1_CFG : LIS2DH_REG_INT2_CFG; + val = (cfg->hw.anym_mode << LIS2DH_INT_CFG_MODE_SHIFT) | LIS2DH_ANYM_CFG; + status = lis2dh->hw_tf->write_reg(dev, reg, val); + if (status < 0) { + LOG_ERR("Failed to configure any motion interrupt"); + return status; + } + + /* enable any motion detection on int line */ + reg = cfg->hw.anym_on_int1 ? LIS2DH_REG_CTRL3 : LIS2DH_REG_CTRL6; + mask = cfg->hw.anym_on_int1 ? LIS2DH_EN_IA_INT1 : LIS2DH_EN_IA_INT2; + val = has_anym ? mask : 0; + status = lis2dh->hw_tf->update_reg(dev, reg, mask, val); + if (status < 0) { + LOG_ERR("Failed to enable any motion detection on int line"); + return status; + } + + /* configure tap interrupt on all axes */ + reg = LIS2DH_REG_CFG_CLICK; + mask = LIS2DH_EN_CLICK_XS | LIS2DH_EN_CLICK_YS | LIS2DH_EN_CLICK_ZS; + val = has_anyt ? mask : 0; + status = lis2dh->hw_tf->update_reg(dev, reg, mask, val); + if (status < 0) { + LOG_ERR("Failed to configure tap interrupt"); + return status; + } + + /* set click detection on int line */ + reg = cfg->hw.anym_on_int1 ? LIS2DH_REG_CTRL3 : LIS2DH_REG_CTRL6; + mask = cfg->hw.anym_on_int1 ? LIS2DH_EN_CLICK_INT1 : LIS2DH_EN_CLICK_INT2; + val = has_anyt ? mask : 0; + status = lis2dh->hw_tf->update_reg(dev, reg, mask, val); + if (status < 0) { + LOG_ERR("Failed to enable click detection on int line"); + return status; + } + return 0; } int lis2dh_trigger_set(const struct device *dev, @@ -203,6 +281,8 @@ int lis2dh_trigger_set(const struct device *dev, return lis2dh_trigger_drdy_set(dev, trig->chan, handler, trig); } else if (trig->type == SENSOR_TRIG_DELTA) { return lis2dh_trigger_anym_set(dev, handler, trig); + } else if (trig->type == SENSOR_TRIG_TAP) { + return lis2dh_trigger_tap_set(dev, handler, trig); } return -ENOTSUP; @@ -243,11 +323,17 @@ int lis2dh_acc_slope_config(const struct device *dev, LOG_INF("int2_ths=0x%x range_g=%d ums2=%u", reg_val, range_g, slope_th_ums2 - 1); + /* Configure threshold for the any motion recognition */ status = lis2dh->hw_tf->write_reg(dev, cfg->hw.anym_on_int1 ? - LIS2DH_REG_INT1_THS : - LIS2DH_REG_INT2_THS, + LIS2DH_REG_INT1_THS : + LIS2DH_REG_INT2_THS, reg_val); + + /* Configure threshold for the Click recognition */ + status = lis2dh->hw_tf->write_reg(dev, + LIS2DH_REG_CFG_CLICK_THS, + LIS2DH_CLICK_LIR | reg_val); } else { /* SENSOR_ATTR_SLOPE_DUR */ /* * slope duration is measured in number of samples: @@ -259,10 +345,16 @@ int lis2dh_acc_slope_config(const struct device *dev, LOG_INF("int2_dur=0x%x", val->val1); + /* Configure time limit for the any motion recognition */ status = lis2dh->hw_tf->write_reg(dev, cfg->hw.anym_on_int1 ? - LIS2DH_REG_INT1_DUR : - LIS2DH_REG_INT2_DUR, + LIS2DH_REG_INT1_DUR : + LIS2DH_REG_INT2_DUR, + val->val1); + + /* Configure time limit for the Click recognition */ + status = lis2dh->hw_tf->write_reg(dev, + LIS2DH_REG_TIME_LIMIT, val->val1); } @@ -358,7 +450,6 @@ static void lis2dh_thread_cb(const struct device *dev) TRIGGED_INT1)) { if (likely(lis2dh->handler_drdy != NULL)) { lis2dh->handler_drdy(dev, lis2dh->trig_drdy); - } /* Reactivate level triggered interrupt if handler did not @@ -374,7 +465,7 @@ static void lis2dh_thread_cb(const struct device *dev) if (cfg->gpio_int.port && atomic_test_and_clear_bit(&lis2dh->trig_flags, TRIGGED_INT2)) { - uint8_t reg_val; + uint8_t reg_val = 0; if (cfg->hw.anym_latch) { /* clear interrupt to de-assert int line */ @@ -387,18 +478,34 @@ static void lis2dh_thread_cb(const struct device *dev) LOG_ERR("clearing interrupt 2 failed: %d", status); return; } + } + + if (likely(lis2dh->handler_anymotion != NULL) && + (reg_val >> LIS2DH_INT_CFG_MODE_SHIFT)) { + lis2dh->handler_anymotion(dev, lis2dh->trig_anymotion); LOG_DBG("@tick=%u int2_src=0x%x", k_cycle_get_32(), reg_val); } - if (likely(lis2dh->handler_anymotion != NULL)) { - lis2dh->handler_anymotion(dev, lis2dh->trig_anymotion); + /* read click interrupt */ + status = lis2dh->hw_tf->read_reg(dev, LIS2DH_REG_CLICK_SRC, + ®_val); + if (status < 0) { + LOG_ERR("clearing interrupt 2 failed: %d", status); + return; + } + + if (likely(lis2dh->handler_tap != NULL) && + (reg_val & LIS2DH_CLICK_SRC_SCLICK)) { + lis2dh->handler_tap(dev, lis2dh->trig_tap); + + LOG_DBG("@tick=%u click_src=0x%x", k_cycle_get_32(), reg_val); } /* Reactivate level triggered interrupt if handler did not * disable itself */ - if (lis2dh->handler_anymotion != NULL) { + if (lis2dh->handler_anymotion || lis2dh->handler_tap) { setup_int2(dev, true); } @@ -407,8 +514,13 @@ static void lis2dh_thread_cb(const struct device *dev) } #ifdef CONFIG_LIS2DH_TRIGGER_OWN_THREAD -static void lis2dh_thread(struct lis2dh_data *lis2dh) +static void lis2dh_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct lis2dh_data *lis2dh = p1; + while (1) { k_sem_take(&lis2dh->gpio_sem, K_FOREVER); lis2dh_thread_cb(lis2dh->dev); @@ -439,7 +551,7 @@ int lis2dh_init_interrupt(const struct device *dev) k_sem_init(&lis2dh->gpio_sem, 0, K_SEM_MAX_LIMIT); k_thread_create(&lis2dh->thread, lis2dh->thread_stack, CONFIG_LIS2DH_THREAD_STACK_SIZE, - (k_thread_entry_t)lis2dh_thread, lis2dh, NULL, NULL, + lis2dh_thread, lis2dh, NULL, NULL, K_PRIO_COOP(CONFIG_LIS2DH_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_LIS2DH_TRIGGER_GLOBAL_THREAD) lis2dh->work.handler = lis2dh_work_cb; @@ -522,49 +634,45 @@ int lis2dh_init_interrupt(const struct device *dev) } LOG_INF("%s: int2 on %s.%02u", dev->name, - cfg->gpio_int.port->name, - cfg->gpio_int.pin); + cfg->gpio_int.port->name, + cfg->gpio_int.pin); /* disable interrupt in case of warm (re)boot */ - status = lis2dh->hw_tf->write_reg( - dev, - cfg->hw.anym_on_int1 ? LIS2DH_REG_INT1_CFG : LIS2DH_REG_INT2_CFG, - 0); + status = lis2dh->hw_tf->write_reg(dev, + cfg->hw.anym_on_int1 ? + LIS2DH_REG_INT1_CFG : + LIS2DH_REG_INT2_CFG, + 0); + if (status < 0) { + LOG_ERR("Interrupt disable reg write failed (%d)", status); + return status; + } + status = lis2dh->hw_tf->write_reg(dev, + LIS2DH_REG_CFG_CLICK, + 0); if (status < 0) { LOG_ERR("Interrupt disable reg write failed (%d)", status); return status; } (void)memset(raw, 0, sizeof(raw)); - status = lis2dh->hw_tf->write_data( - dev, - cfg->hw.anym_on_int1 ? LIS2DH_REG_INT1_THS : LIS2DH_REG_INT2_THS, - raw, sizeof(raw)); + status = lis2dh->hw_tf->write_data(dev, + cfg->hw.anym_on_int1 ? + LIS2DH_REG_INT1_THS : + LIS2DH_REG_INT2_THS, + raw, sizeof(raw)); if (status < 0) { LOG_ERR("Burst write to THS failed (%d)", status); return status; } - if (cfg->hw.anym_on_int1) { - /* enable interrupt 1 on int1 line */ - status = lis2dh->hw_tf->update_reg(dev, LIS2DH_REG_CTRL3, - LIS2DH_EN_INT1_INT1, - LIS2DH_EN_INT1_INT1); - if (cfg->hw.anym_latch) { - /* latch int1 line interrupt */ - status = lis2dh->hw_tf->write_reg(dev, LIS2DH_REG_CTRL5, - LIS2DH_EN_LIR_INT1); - } - } else { - /* enable interrupt 2 on int2 line */ - status = lis2dh->hw_tf->update_reg(dev, LIS2DH_REG_CTRL6, - LIS2DH_EN_INT2_INT2, - LIS2DH_EN_INT2_INT2); - if (cfg->hw.anym_latch) { - /* latch int2 line interrupt */ - status = lis2dh->hw_tf->write_reg(dev, LIS2DH_REG_CTRL5, - LIS2DH_EN_LIR_INT2); - } + if (cfg->hw.anym_latch) { + /* latch line interrupt */ + status = lis2dh->hw_tf->write_reg(dev, + LIS2DH_REG_CTRL5, + cfg->hw.anym_on_int1 ? + LIS2DH_EN_LIR_INT1 : + LIS2DH_EN_LIR_INT2); } if (status < 0) { diff --git a/drivers/sensor/lis2ds12/lis2ds12.c b/drivers/sensor/lis2ds12/lis2ds12.c index ae7fa9eb81f..c9634b2179f 100644 --- a/drivers/sensor/lis2ds12/lis2ds12.c +++ b/drivers/sensor/lis2ds12/lis2ds12.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "lis2ds12.h" @@ -40,8 +41,9 @@ static int lis2ds12_set_odr(const struct device *dev, uint8_t odr) * 12,5Hz <= odr <= 800Hz are available in LP and HR mode only * odr == 1Hz is available in LP mode only */ - if ((odr >= 9 && cfg->pm != 3) || (odr < 9 && cfg->pm == 3) || - (odr == 1 && cfg->pm != 1)) { + if ((odr >= LIS2DS12_DT_ODR_1600Hz && cfg->pm != LIS2DS12_DT_HIGH_FREQUENCY) || + (odr < LIS2DS12_DT_ODR_1600Hz && cfg->pm == LIS2DS12_DT_HIGH_FREQUENCY) || + (odr == LIS2DS12_DT_ODR_1Hz_LP && cfg->pm != LIS2DS12_DT_LOW_POWER)) { LOG_ERR("%s: bad odr and pm combination", dev->name); return -ENOTSUP; } diff --git a/drivers/sensor/lis2ds12/lis2ds12_trigger.c b/drivers/sensor/lis2ds12/lis2ds12_trigger.c index 96069419907..d3494913315 100644 --- a/drivers/sensor/lis2ds12/lis2ds12_trigger.c +++ b/drivers/sensor/lis2ds12/lis2ds12_trigger.c @@ -67,8 +67,13 @@ static void lis2ds12_handle_int(const struct device *dev) } #ifdef CONFIG_LIS2DS12_TRIGGER_OWN_THREAD -static void lis2ds12_thread(struct lis2ds12_data *data) +static void lis2ds12_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct lis2ds12_data *data = p1; + while (1) { k_sem_take(&data->trig_sem, K_FOREVER); lis2ds12_handle_int(data->dev); @@ -159,7 +164,7 @@ int lis2ds12_trigger_init(const struct device *dev) k_thread_create(&data->thread, data->thread_stack, CONFIG_LIS2DS12_THREAD_STACK_SIZE, - (k_thread_entry_t)lis2ds12_thread, + lis2ds12_thread, data, NULL, NULL, K_PRIO_COOP(CONFIG_LIS2DS12_THREAD_PRIORITY), 0, K_NO_WAIT); diff --git a/drivers/sensor/lis2dw12/lis2dw12.c b/drivers/sensor/lis2dw12/lis2dw12.c index 2f77cbbf8c8..97452d78c41 100644 --- a/drivers/sensor/lis2dw12/lis2dw12.c +++ b/drivers/sensor/lis2dw12/lis2dw12.c @@ -476,6 +476,14 @@ static int lis2dw12_init(const struct device *dev) return ret; } +#ifdef CONFIG_LIS2DW12_THRESHOLD + ret = lis2dw12_wkup_dur_set(ctx, cfg->wakeup_duration); + if (ret < 0) { + LOG_ERR("wakeup duration config error %d", ret); + return ret; + } +#endif /* CONFIG_LIS2DW12_THRESHOLD */ + return 0; } @@ -521,6 +529,13 @@ static int lis2dw12_init(const struct device *dev) #define LIS2DW12_CONFIG_FREEFALL(inst) #endif /* CONFIG_LIS2DW12_FREEFALL */ +#ifdef CONFIG_LIS2DW12_THRESHOLD +#define LIS2DW12_CONFIG_THRESHOLD(inst) \ + .wakeup_duration = DT_INST_PROP(inst, wakeup_duration), +#else +#define LIS2DW12_CONFIG_THRESHOLD(inst) +#endif + #ifdef CONFIG_LIS2DW12_TRIGGER #define LIS2DW12_CFG_IRQ(inst) \ .gpio_int = GPIO_DT_SPEC_INST_GET(inst, irq_gpios), \ @@ -540,6 +555,7 @@ static int lis2dw12_init(const struct device *dev) .drdy_pulsed = DT_INST_PROP(inst, drdy_pulsed), \ LIS2DW12_CONFIG_TAP(inst) \ LIS2DW12_CONFIG_FREEFALL(inst) \ + LIS2DW12_CONFIG_THRESHOLD(inst) \ COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, irq_gpios), \ (LIS2DW12_CFG_IRQ(inst)), ()) diff --git a/drivers/sensor/lis2dw12/lis2dw12.h b/drivers/sensor/lis2dw12/lis2dw12.h index ba61a764114..d52312193c0 100644 --- a/drivers/sensor/lis2dw12/lis2dw12.h +++ b/drivers/sensor/lis2dw12/lis2dw12.h @@ -96,6 +96,9 @@ struct lis2dw12_device_config { uint8_t freefall_duration; uint8_t freefall_threshold; #endif /* CONFIG_LIS2DW12_FREEFALL */ +#ifdef CONFIG_LIS2DW12_THRESHOLD + uint8_t wakeup_duration; +#endif /* CONFIG_LIS2DW12_THRESHOLD */ #endif /* CONFIG_LIS2DW12_TRIGGER */ }; diff --git a/drivers/sensor/lis2dw12/lis2dw12_trigger.c b/drivers/sensor/lis2dw12/lis2dw12_trigger.c index 08030c993b6..e30d6d4c167 100644 --- a/drivers/sensor/lis2dw12/lis2dw12_trigger.c +++ b/drivers/sensor/lis2dw12/lis2dw12_trigger.c @@ -301,8 +301,13 @@ static void lis2dw12_gpio_callback(const struct device *dev, } #ifdef CONFIG_LIS2DW12_TRIGGER_OWN_THREAD -static void lis2dw12_thread(struct lis2dw12_data *lis2dw12) +static void lis2dw12_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct lis2dw12_data *lis2dw12 = p1; + while (1) { k_sem_take(&lis2dw12->gpio_sem, K_FOREVER); lis2dw12_handle_interrupt(lis2dw12->dev); @@ -451,7 +456,7 @@ int lis2dw12_init_interrupt(const struct device *dev) k_thread_create(&lis2dw12->thread, lis2dw12->thread_stack, CONFIG_LIS2DW12_THREAD_STACK_SIZE, - (k_thread_entry_t)lis2dw12_thread, lis2dw12, + lis2dw12_thread, lis2dw12, NULL, NULL, K_PRIO_COOP(CONFIG_LIS2DW12_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_LIS2DW12_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/lis2mdl/lis2mdl_trigger.c b/drivers/sensor/lis2mdl/lis2mdl_trigger.c index 4a77e2fa432..19930174ea0 100644 --- a/drivers/sensor/lis2mdl/lis2mdl_trigger.c +++ b/drivers/sensor/lis2mdl/lis2mdl_trigger.c @@ -96,8 +96,13 @@ static void lis2mdl_gpio_callback(const struct device *dev, } #ifdef CONFIG_LIS2MDL_TRIGGER_OWN_THREAD -static void lis2mdl_thread(struct lis2mdl_data *lis2mdl) +static void lis2mdl_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct lis2mdl_data *lis2mdl = p1; + while (1) { k_sem_take(&lis2mdl->gpio_sem, K_FOREVER); lis2mdl_handle_interrupt(lis2mdl->dev); @@ -131,7 +136,7 @@ int lis2mdl_init_interrupt(const struct device *dev) k_sem_init(&lis2mdl->gpio_sem, 0, K_SEM_MAX_LIMIT); k_thread_create(&lis2mdl->thread, lis2mdl->thread_stack, CONFIG_LIS2MDL_THREAD_STACK_SIZE, - (k_thread_entry_t)lis2mdl_thread, lis2mdl, + lis2mdl_thread, lis2mdl, NULL, NULL, K_PRIO_COOP(CONFIG_LIS2MDL_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_LIS2MDL_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/lis3mdl/lis3mdl_trigger.c b/drivers/sensor/lis3mdl/lis3mdl_trigger.c index 05993e1ceda..ba94076bd14 100644 --- a/drivers/sensor/lis3mdl/lis3mdl_trigger.c +++ b/drivers/sensor/lis3mdl/lis3mdl_trigger.c @@ -87,8 +87,13 @@ static void lis3mdl_thread_cb(const struct device *dev) } #ifdef CONFIG_LIS3MDL_TRIGGER_OWN_THREAD -static void lis3mdl_thread(struct lis3mdl_data *drv_data) +static void lis3mdl_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct lis3mdl_data *drv_data = p1; + while (1) { k_sem_take(&drv_data->gpio_sem, K_FOREVER); lis3mdl_thread_cb(drv_data->dev); @@ -140,7 +145,7 @@ int lis3mdl_init_interrupt(const struct device *dev) k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_LIS3MDL_THREAD_STACK_SIZE, - (k_thread_entry_t)lis3mdl_thread, drv_data, + lis3mdl_thread, drv_data, NULL, NULL, K_PRIO_COOP(CONFIG_LIS3MDL_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_LIS3MDL_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/lm75/lm75.c b/drivers/sensor/lm75/lm75.c index 5e117bb9b7c..e01a691a58e 100644 --- a/drivers/sensor/lm75/lm75.c +++ b/drivers/sensor/lm75/lm75.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include LOG_MODULE_REGISTER(LM75, CONFIG_SENSOR_LOG_LEVEL); @@ -62,14 +64,26 @@ static int lm75_sample_fetch(const struct device *dev, { struct lm75_data *data = dev->data; const struct lm75_config *cfg = dev->config; + enum pm_device_state pm_state; + int ret; + + (void)pm_device_state_get(dev, &pm_state); + if (pm_state != PM_DEVICE_STATE_ACTIVE) { + ret = -EIO; + return ret; + } switch (chan) { case SENSOR_CHAN_ALL: case SENSOR_CHAN_AMBIENT_TEMP: - return lm75_fetch_temp(cfg, data); + ret = lm75_fetch_temp(cfg, data); + break; default: - return -ENOTSUP; + ret = -ENOTSUP; + break; } + + return ret; } static int lm75_channel_get(const struct device *dev, @@ -96,21 +110,52 @@ static const struct sensor_driver_api lm75_driver_api = { int lm75_init(const struct device *dev) { const struct lm75_config *cfg = dev->config; + int ret = 0; - if (device_is_ready(cfg->i2c.bus)) { - return 0; + if (!device_is_ready(cfg->i2c.bus)) { + LOG_ERR("I2C dev not ready"); + return -ENODEV; } - LOG_ERR("I2C dev not ready"); - return -ENODEV; +#ifdef CONFIG_PM_DEVICE_RUNTIME + pm_device_init_suspended(dev); + + ret = pm_device_runtime_enable(dev); + if (ret < 0 && ret != -ENOTSUP) { + LOG_ERR("Failed to enable runtime power management"); + return ret; + } +#endif + + return ret; } +#ifdef CONFIG_PM_DEVICE + +static int lm75_pm_action(const struct device *dev, enum pm_device_action action) +{ + switch (action) { + case PM_DEVICE_ACTION_TURN_ON: + case PM_DEVICE_ACTION_RESUME: + case PM_DEVICE_ACTION_TURN_OFF: + case PM_DEVICE_ACTION_SUSPEND: + break; + default: + return -ENOTSUP; + } + + return 0; +} + +#endif + #define LM75_INST(inst) \ static struct lm75_data lm75_data_##inst; \ static const struct lm75_config lm75_config_##inst = { \ .i2c = I2C_DT_SPEC_INST_GET(inst), \ }; \ -SENSOR_DEVICE_DT_INST_DEFINE(inst, lm75_init, NULL, &lm75_data_##inst, \ +PM_DEVICE_DT_INST_DEFINE(inst, lm75_pm_action); \ +SENSOR_DEVICE_DT_INST_DEFINE(inst, lm75_init, PM_DEVICE_DT_INST_GET(inst), &lm75_data_##inst, \ &lm75_config_##inst, POST_KERNEL, \ CONFIG_SENSOR_INIT_PRIORITY, &lm75_driver_api); diff --git a/drivers/sensor/lps22df/CMakeLists.txt b/drivers/sensor/lps22df/CMakeLists.txt new file mode 100644 index 00000000000..bb5194cf9ba --- /dev/null +++ b/drivers/sensor/lps22df/CMakeLists.txt @@ -0,0 +1,12 @@ +# ST Microelectronics LPS22DF pressure and temperature sensor +# +# Copyright (c) 2023 STMicroelectronics +# +# SPDX-License-Identifier: Apache-2.0 +# +zephyr_library() + +zephyr_library_sources(lps22df.c) +zephyr_library_sources_ifdef(CONFIG_LPS22DF_TRIGGER lps22df_trigger.c) + +zephyr_library_include_directories(../stmemsc) diff --git a/drivers/sensor/lps22df/Kconfig b/drivers/sensor/lps22df/Kconfig new file mode 100644 index 00000000000..843c6e755c4 --- /dev/null +++ b/drivers/sensor/lps22df/Kconfig @@ -0,0 +1,59 @@ +# ST Microelectronics LPS22DF pressure and temperature sensor + +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +menuconfig LPS22DF + bool "LPS22DF pressure and temperature" + default y + depends on DT_HAS_ST_LPS22DF_ENABLED + select I2C if $(dt_compat_on_bus,$(DT_COMPAT_ST_LPS22DF),i2c) + select I3C if $(dt_compat_on_bus,$(DT_COMPAT_ST_LPS22DF),i3c) + select SPI if $(dt_compat_on_bus,$(DT_COMPAT_ST_LPS22DF),spi) + select HAS_STMEMSC + select USE_STDC_LPS22DF + help + Enable driver for LPS22DF I2C-based pressure and temperature + sensor. + +if LPS22DF + +choice LPS22DF_TRIGGER_MODE + prompt "Trigger mode" + default LPS22DF_TRIGGER_GLOBAL_THREAD + help + Specify the type of triggering to be used by the driver. + +config LPS22DF_TRIGGER_NONE + bool "No trigger" + +config LPS22DF_TRIGGER_GLOBAL_THREAD + bool "Use global thread" + depends on GPIO + select LPS22DF_TRIGGER + +config LPS22DF_TRIGGER_OWN_THREAD + bool "Use own thread" + depends on GPIO + select LPS22DF_TRIGGER + +endchoice # LPS22DF_TRIGGER_MODE + +config LPS22DF_TRIGGER + bool + +config LPS22DF_THREAD_PRIORITY + int "Thread priority" + depends on LPS22DF_TRIGGER_OWN_THREAD + default 10 + help + Priority of thread used by the driver to handle interrupts. + +config LPS22DF_THREAD_STACK_SIZE + int "Thread stack size" + depends on LPS22DF_TRIGGER_OWN_THREAD + default 1024 + help + Stack size of thread used by the driver to handle interrupts. + +endif # LPS22DF diff --git a/drivers/sensor/lps22df/lps22df.c b/drivers/sensor/lps22df/lps22df.c new file mode 100644 index 00000000000..a74ef75c245 --- /dev/null +++ b/drivers/sensor/lps22df/lps22df.c @@ -0,0 +1,338 @@ +/* ST Microelectronics LPS22DF pressure and temperature sensor + * + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.st.com/resource/en/datasheet/lps22df.pdf + */ + +#define DT_DRV_COMPAT st_lps22df + +#include +#include +#include +#include +#include +#include +#include + +#include "lps22df.h" + +#define LPS22DF_SWRESET_WAIT_TIME 50 + +LOG_MODULE_REGISTER(LPS22DF, CONFIG_SENSOR_LOG_LEVEL); + +static inline int lps22df_set_odr_raw(const struct device *dev, uint8_t odr) +{ + const struct lps22df_config * const cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lps22df_md_t md; + + md.odr = odr; + md.avg = cfg->avg; + md.lpf = cfg->lpf; + + return lps22df_mode_set(ctx, &md); +} + +static int lps22df_sample_fetch(const struct device *dev, + enum sensor_channel chan) +{ + struct lps22df_data *data = dev->data; + const struct lps22df_config * const cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lps22df_data_t raw_data; + + __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL); + + if (lps22df_data_get(ctx, &raw_data) < 0) { + LOG_DBG("Failed to read sample"); + return -EIO; + } + + data->sample_press = raw_data.pressure.raw; + data->sample_temp = raw_data.heat.raw; + + return 0; +} + +static inline void lps22df_press_convert(struct sensor_value *val, + int32_t raw_val) +{ + int32_t press_tmp = raw_val >> 8; /* raw value is left aligned (24 msb) */ + + /* Pressure sensitivity is 4096 LSB/hPa */ + /* Also convert hPa into kPa */ + + val->val1 = press_tmp / 40960; + + /* For the decimal part use (3125 / 128) as a factor instead of + * (1000000 / 40960) to avoid int32 overflow + */ + val->val2 = (press_tmp % 40960) * 3125 / 128; +} + +static inline void lps22df_temp_convert(struct sensor_value *val, + int16_t raw_val) +{ + /* Temperature sensitivity is 100 LSB/deg C */ + val->val1 = raw_val / 100; + val->val2 = ((int32_t)raw_val % 100) * 10000; +} + +static int lps22df_channel_get(const struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + struct lps22df_data *data = dev->data; + + if (chan == SENSOR_CHAN_PRESS) { + lps22df_press_convert(val, data->sample_press); + } else if (chan == SENSOR_CHAN_AMBIENT_TEMP) { + lps22df_temp_convert(val, data->sample_temp); + } else { + return -ENOTSUP; + } + + return 0; +} + +static const uint16_t lps22df_map[] = {0, 1, 4, 10, 25, 50, 75, 100, 200}; + +static int lps22df_odr_set(const struct device *dev, uint16_t freq) +{ + int odr; + + for (odr = 0; odr < ARRAY_SIZE(lps22df_map); odr++) { + if (freq == lps22df_map[odr]) { + break; + } + } + + if (odr == ARRAY_SIZE(lps22df_map)) { + LOG_DBG("bad frequency"); + return -EINVAL; + } + + if (lps22df_set_odr_raw(dev, odr) < 0) { + LOG_DBG("failed to set sampling rate"); + return -EIO; + } + + return 0; +} + +static int lps22df_attr_set(const struct device *dev, + enum sensor_channel chan, + enum sensor_attribute attr, + const struct sensor_value *val) +{ + if (chan != SENSOR_CHAN_ALL) { + LOG_WRN("attr_set() not supported on this channel."); + return -ENOTSUP; + } + + switch (attr) { + case SENSOR_ATTR_SAMPLING_FREQUENCY: + return lps22df_odr_set(dev, val->val1); + default: + LOG_DBG("operation not supported."); + return -ENOTSUP; + } + + return 0; +} + +static const struct sensor_driver_api lps22df_driver_api = { + .attr_set = lps22df_attr_set, + .sample_fetch = lps22df_sample_fetch, + .channel_get = lps22df_channel_get, +#if CONFIG_LPS22DF_TRIGGER + .trigger_set = lps22df_trigger_set, +#endif +}; + +static int lps22df_init_chip(const struct device *dev) +{ + const struct lps22df_config * const cfg = dev->config; + __maybe_unused struct lps22df_data *data = dev->data; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lps22df_id_t id; + lps22df_stat_t status; + uint8_t tries = 10; + int ret; + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) + if (cfg->i3c.bus != NULL) { + /* + * Need to grab the pointer to the I3C device descriptor + * before we can talk to the sensor. + */ + data->i3c_dev = i3c_device_find(cfg->i3c.bus, &cfg->i3c.dev_id); + if (data->i3c_dev == NULL) { + LOG_ERR("Cannot find I3C device descriptor"); + return -ENODEV; + } + } +#endif + + if (lps22df_id_get(ctx, &id) < 0) { + LOG_ERR("%s: Not able to read dev id", dev->name); + return -EIO; + } + + if (id.whoami != LPS22DF_ID) { + LOG_ERR("%s: Invalid chip ID 0x%02x", dev->name, id.whoami); + return -EIO; + } + + LOG_DBG("%s: chip id 0x%x", dev->name, id.whoami); + + /* Restore default configuration */ + if (lps22df_init_set(ctx, LPS22DF_RESET) < 0) { + LOG_ERR("%s: Not able to reset device", dev->name); + return -EIO; + } + + do { + if (!--tries) { + LOG_DBG("sw reset timed out"); + return -ETIMEDOUT; + } + k_usleep(LPS22DF_SWRESET_WAIT_TIME); + + if (lps22df_status_get(ctx, &status) < 0) { + return -EIO; + } + } while (status.sw_reset); + + /* Set bdu and if_inc recommended for driver usage */ + if (lps22df_init_set(ctx, LPS22DF_DRV_RDY) < 0) { + LOG_ERR("%s: Not able to set device to ready state", dev->name); + return -EIO; + } + + if (ON_I3C_BUS(cfg)) { + lps22df_bus_mode_t bus_mode; + + /* Select bus interface */ + bus_mode.filter = LPS22DF_AUTO; + bus_mode.interface = LPS22DF_SEL_BY_HW; + lps22df_bus_mode_set(ctx, &bus_mode); + + } + + /* set sensor default odr */ + LOG_DBG("%s: odr: %d", dev->name, cfg->odr); + ret = lps22df_set_odr_raw(dev, cfg->odr); + if (ret < 0) { + LOG_ERR("%s: Failed to set odr %d", dev->name, cfg->odr); + return ret; + } + + return 0; +} + +static int lps22df_init(const struct device *dev) +{ + if (lps22df_init_chip(dev) < 0) { + LOG_DBG("Failed to initialize chip"); + return -EIO; + } + +#ifdef CONFIG_LPS22DF_TRIGGER + if (lps22df_init_interrupt(dev) < 0) { + LOG_ERR("Failed to initialize interrupt."); + return -EIO; + } +#endif + + return 0; +} + +/* + * Instantiation macros used when a device is on a SPI bus. + */ + +#ifdef CONFIG_LPS22DF_TRIGGER +#define LPS22DF_CFG_IRQ(inst) \ + .gpio_int = GPIO_DT_SPEC_INST_GET(inst, drdy_gpios), +#else +#define LPS22DF_CFG_IRQ(inst) +#endif /* CONFIG_LPS22DF_TRIGGER */ + +#define LPS22DF_CONFIG_COMMON(inst) \ + .odr = DT_INST_PROP(inst, odr), \ + .lpf = DT_INST_PROP(inst, lpf), \ + .avg = DT_INST_PROP(inst, avg), \ + .drdy_pulsed = DT_INST_PROP(inst, drdy_pulsed), \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, drdy_gpios), \ + (LPS22DF_CFG_IRQ(inst)), ()) + +#define LPS22DF_SPI_OPERATION (SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | \ + SPI_MODE_CPOL | SPI_MODE_CPHA) \ + +#define LPS22DF_CONFIG_SPI(inst) \ + { \ + STMEMSC_CTX_SPI(&lps22df_config_##inst.stmemsc_cfg), \ + .stmemsc_cfg = { \ + .spi = SPI_DT_SPEC_INST_GET(inst, \ + LPS22DF_SPI_OPERATION, \ + 0), \ + }, \ + LPS22DF_CONFIG_COMMON(inst) \ + } + +/* + * Instantiation macros used when a device is on an I2C bus. + */ + +#define LPS22DF_CONFIG_I2C(inst) \ + { \ + STMEMSC_CTX_I2C(&lps22df_config_##inst.stmemsc_cfg), \ + .stmemsc_cfg = { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + }, \ + LPS22DF_CONFIG_COMMON(inst) \ + } + +/* + * Instantiation macros used when a device is on an I#C bus. + */ + +#define LPS22DF_CONFIG_I3C(inst) \ + { \ + STMEMSC_CTX_I3C(&lps22df_config_##inst.stmemsc_cfg), \ + .stmemsc_cfg = { \ + .i3c = &lps22df_data_##inst.i3c_dev, \ + }, \ + .i3c.bus = DEVICE_DT_GET(DT_INST_BUS(inst)), \ + .i3c.dev_id = I3C_DEVICE_ID_DT_INST(inst), \ + LPS22DF_CONFIG_COMMON(inst) \ + } + +#define LPS22DF_CONFIG_I3C_OR_I2C(inst) \ + COND_CODE_0(DT_INST_PROP_BY_IDX(inst, reg, 1), \ + (LPS22DF_CONFIG_I2C(inst)), \ + (LPS22DF_CONFIG_I3C(inst))) + +/* + * Main instantiation macro. Use of COND_CODE_1() selects the right + * bus-specific macro at preprocessor time. + */ + +#define LPS22DF_DEFINE(inst) \ + static struct lps22df_data lps22df_data_##inst; \ + static const struct lps22df_config lps22df_config_##inst = \ + COND_CODE_1(DT_INST_ON_BUS(inst, spi), \ + (LPS22DF_CONFIG_SPI(inst)), \ + (COND_CODE_1(DT_INST_ON_BUS(inst, i3c), \ + (LPS22DF_CONFIG_I3C_OR_I2C(inst)), \ + (LPS22DF_CONFIG_I2C(inst))))); \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, lps22df_init, NULL, &lps22df_data_##inst, \ + &lps22df_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &lps22df_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(LPS22DF_DEFINE) diff --git a/drivers/sensor/lps22df/lps22df.h b/drivers/sensor/lps22df/lps22df.h new file mode 100644 index 00000000000..044c08cbd93 --- /dev/null +++ b/drivers/sensor/lps22df/lps22df.h @@ -0,0 +1,99 @@ +/* ST Microelectronics LPS22DF pressure and temperature sensor + * + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.st.com/resource/en/datasheet/lps22df.pdf + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_LPS22DF_LPS22DF_H_ +#define ZEPHYR_DRIVERS_SENSOR_LPS22DF_LPS22DF_H_ + +#include +#include +#include "lps22df_reg.h" + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) +#include +#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) */ + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) +#include +#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */ + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) +#include +#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) */ + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) + #define ON_I3C_BUS(cfg) (cfg->i3c.bus != NULL) +#else + #define ON_I3C_BUS(cfg) (false) +#endif + +struct lps22df_config { + stmdev_ctx_t ctx; + union { +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) + const struct i2c_dt_spec i2c; +#endif +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) + const struct spi_dt_spec spi; +#endif +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) + struct i3c_device_desc **i3c; +#endif + } stmemsc_cfg; + uint8_t odr; + uint8_t lpf; + uint8_t avg; + uint8_t drdy_pulsed; +#ifdef CONFIG_LPS22DF_TRIGGER + struct gpio_dt_spec gpio_int; +#endif + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) + struct { + const struct device *bus; + const struct i3c_device_id dev_id; + } i3c; +#endif +}; + +struct lps22df_data { + int32_t sample_press; + int16_t sample_temp; + +#ifdef CONFIG_LPS22DF_TRIGGER + struct gpio_callback gpio_cb; + + const struct sensor_trigger *data_ready_trigger; + sensor_trigger_handler_t handler_drdy; + const struct device *dev; + +#if defined(CONFIG_LPS22DF_TRIGGER_OWN_THREAD) + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_LPS22DF_THREAD_STACK_SIZE); + struct k_thread thread; + struct k_sem intr_sem; +#elif defined(CONFIG_LPS22DF_TRIGGER_GLOBAL_THREAD) + struct k_work work; +#endif + +#endif /* CONFIG_LPS22DF_TRIGGER */ + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) + struct i3c_device_desc *i3c_dev; +#endif +}; + +#ifdef CONFIG_LPS22DF_TRIGGER +int lps22df_trigger_set(const struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); + +int lps22df_init_interrupt(const struct device *dev); +#endif + +#endif /* ZEPHYR_DRIVERS_SENSOR_LPS22DF_LPS22DF_H_ */ diff --git a/drivers/sensor/lps22df/lps22df_trigger.c b/drivers/sensor/lps22df/lps22df_trigger.c new file mode 100644 index 00000000000..c5d6a91dba8 --- /dev/null +++ b/drivers/sensor/lps22df/lps22df_trigger.c @@ -0,0 +1,251 @@ +/* ST Microelectronics LPS22DF pressure and temperature sensor + * + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.st.com/resource/en/datasheet/lps22df.pdf + */ + +#define DT_DRV_COMPAT st_lps22df + +#include +#include +#include +#include + +#include "lps22df.h" + +LOG_MODULE_DECLARE(LPS22DF, CONFIG_SENSOR_LOG_LEVEL); + +/** + * lps22df_enable_int - enable selected int pin to generate interrupt + */ +static int lps22df_enable_int(const struct device *dev, int enable) +{ + const struct lps22df_config * const cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lps22df_pin_int_route_t int_route; + + /* set interrupt */ + lps22df_pin_int_route_get(ctx, &int_route); + int_route.drdy_pres = enable; + return lps22df_pin_int_route_set(ctx, &int_route); +} + +/** + * lps22df_trigger_set - link external trigger to event data ready + */ +int lps22df_trigger_set(const struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + struct lps22df_data *lps22df = dev->data; + const struct lps22df_config * const cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lps22df_data_t raw_data; + + if (trig->chan != SENSOR_CHAN_ALL) { + LOG_WRN("trigger set not supported on this channel."); + return -ENOTSUP; + } + + lps22df->handler_drdy = handler; + lps22df->data_ready_trigger = trig; + if (handler) { + /* dummy read: re-trigger interrupt */ + if (lps22df_data_get(ctx, &raw_data) < 0) { + LOG_DBG("Failed to read sample"); + return -EIO; + } + return lps22df_enable_int(dev, 1); + } else { + return lps22df_enable_int(dev, 0); + } + + return -ENOTSUP; +} + +/** + * lps22df_handle_interrupt - handle the drdy event + * read data and call handler if registered any + */ +static void lps22df_handle_interrupt(const struct device *dev) +{ + int ret; + struct lps22df_data *lps22df = dev->data; + const struct lps22df_config *cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lps22df_all_sources_t status; + + if (lps22df_all_sources_get(ctx, &status) < 0) { + LOG_DBG("failed reading status reg"); + goto exit; + } + + if (status.drdy_pres == 0) { + goto exit; /* spurious interrupt */ + } + + if (lps22df->handler_drdy != NULL) { + lps22df->handler_drdy(dev, lps22df->data_ready_trigger); + } + + if (ON_I3C_BUS(cfg)) { + /* + * I3C IBI does not rely on GPIO. + * So no need to enable GPIO pin for interrupt trigger. + */ + return; + } + +exit: + ret = gpio_pin_interrupt_configure_dt(&cfg->gpio_int, + GPIO_INT_EDGE_TO_ACTIVE); + if (ret < 0) { + LOG_ERR("%s: Not able to configure pin_int", dev->name); + } +} + +static void lps22df_intr_callback(struct lps22df_data *lps22df) +{ +#if defined(CONFIG_LPS22DF_TRIGGER_OWN_THREAD) + k_sem_give(&lps22df->intr_sem); +#elif defined(CONFIG_LPS22DF_TRIGGER_GLOBAL_THREAD) + k_work_submit(&lps22df->work); +#endif /* CONFIG_LPS22DF_TRIGGER_OWN_THREAD */ +} + +static void lps22df_gpio_callback(const struct device *dev, + struct gpio_callback *cb, uint32_t pins) +{ + struct lps22df_data *lps22df = + CONTAINER_OF(cb, struct lps22df_data, gpio_cb); + + ARG_UNUSED(pins); + const struct lps22df_config *cfg = lps22df->dev->config; + int ret; + + ret = gpio_pin_interrupt_configure_dt(&cfg->gpio_int, GPIO_INT_DISABLE); + if (ret < 0) { + LOG_ERR("%s: Not able to configure pin_int", dev->name); + } + + lps22df_intr_callback(lps22df); +} + +#ifdef CONFIG_LPS22DF_TRIGGER_OWN_THREAD +static void lps22df_thread(struct lps22df_data *lps22df) +{ + while (1) { + k_sem_take(&lps22df->intr_sem, K_FOREVER); + lps22df_handle_interrupt(lps22df->dev); + } +} +#endif /* CONFIG_LPS22DF_TRIGGER_OWN_THREAD */ + +#ifdef CONFIG_LPS22DF_TRIGGER_GLOBAL_THREAD +static void lps22df_work_cb(struct k_work *work) +{ + struct lps22df_data *lps22df = + CONTAINER_OF(work, struct lps22df_data, work); + + lps22df_handle_interrupt(lps22df->dev); +} +#endif /* CONFIG_LPS22DF_TRIGGER_GLOBAL_THREAD */ + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) +static int lps22df_ibi_cb(struct i3c_device_desc *target, + struct i3c_ibi_payload *payload) +{ + const struct device *dev = target->dev; + struct lps22df_data *lps22df = dev->data; + + ARG_UNUSED(payload); + + lps22df_intr_callback(lps22df); + + return 0; +} +#endif + +int lps22df_init_interrupt(const struct device *dev) +{ + struct lps22df_data *lps22df = dev->data; + const struct lps22df_config *cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lps22df_int_mode_t mode; + int ret; + + /* setup data ready gpio interrupt */ + if (!gpio_is_ready_dt(&cfg->gpio_int) && !ON_I3C_BUS(cfg)) { + if (cfg->gpio_int.port) { + LOG_ERR("%s: device %s is not ready", dev->name, + cfg->gpio_int.port->name); + return -ENODEV; + } + + LOG_DBG("%s: gpio_int not defined in DT", dev->name); + return 0; + } + + lps22df->dev = dev; + +#if defined(CONFIG_LPS22DF_TRIGGER_OWN_THREAD) + k_sem_init(&lps22df->intr_sem, 0, K_SEM_MAX_LIMIT); + + k_thread_create(&lps22df->thread, lps22df->thread_stack, + CONFIG_LPS22DF_THREAD_STACK_SIZE, + (k_thread_entry_t)lps22df_thread, lps22df, + NULL, NULL, K_PRIO_COOP(CONFIG_LPS22DF_THREAD_PRIORITY), + 0, K_NO_WAIT); +#elif defined(CONFIG_LPS22DF_TRIGGER_GLOBAL_THREAD) + lps22df->work.handler = lps22df_work_cb; +#endif /* CONFIG_LPS22DF_TRIGGER_OWN_THREAD */ + + if (!ON_I3C_BUS(cfg)) { + ret = gpio_pin_configure_dt(&cfg->gpio_int, GPIO_INPUT); + if (ret < 0) { + LOG_ERR("Could not configure gpio"); + return ret; + } + + LOG_INF("%s: int on %s.%02u", dev->name, cfg->gpio_int.port->name, + cfg->gpio_int.pin); + + gpio_init_callback(&lps22df->gpio_cb, + lps22df_gpio_callback, + BIT(cfg->gpio_int.pin)); + + ret = gpio_add_callback(cfg->gpio_int.port, &lps22df->gpio_cb); + if (ret < 0) { + LOG_ERR("Could not set gpio callback"); + return ret; + } + } + + /* enable drdy in pulsed/latched mode */ + LOG_DBG("drdy_pulsed is %d", (int)cfg->drdy_pulsed); + mode.drdy_latched = ~cfg->drdy_pulsed; + if (lps22df_interrupt_mode_set(ctx, &mode) < 0) { + return -EIO; + } + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) + if (cfg->i3c.bus != NULL) { + /* I3C IBI does not utilize GPIO interrupt. */ + lps22df->i3c_dev->ibi_cb = lps22df_ibi_cb; + + if (i3c_ibi_enable(lps22df->i3c_dev) != 0) { + LOG_DBG("Could not enable I3C IBI"); + return -EIO; + } + + return 0; + } +#endif + + return gpio_pin_interrupt_configure_dt(&cfg->gpio_int, + GPIO_INT_EDGE_TO_ACTIVE); +} diff --git a/drivers/sensor/lps22hh/lps22hh_trigger.c b/drivers/sensor/lps22hh/lps22hh_trigger.c index bb8c7f406ef..e08a0259ee2 100644 --- a/drivers/sensor/lps22hh/lps22hh_trigger.c +++ b/drivers/sensor/lps22hh/lps22hh_trigger.c @@ -123,8 +123,13 @@ static void lps22hh_gpio_callback(const struct device *dev, } #ifdef CONFIG_LPS22HH_TRIGGER_OWN_THREAD -static void lps22hh_thread(struct lps22hh_data *lps22hh) +static void lps22hh_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct lps22hh_data *lps22hh = p1; + while (1) { k_sem_take(&lps22hh->intr_sem, K_FOREVER); lps22hh_handle_interrupt(lps22hh->dev); @@ -187,7 +192,7 @@ int lps22hh_init_interrupt(const struct device *dev) k_thread_create(&lps22hh->thread, lps22hh->thread_stack, CONFIG_LPS22HH_THREAD_STACK_SIZE, - (k_thread_entry_t)lps22hh_thread, lps22hh, + lps22hh_thread, lps22hh, NULL, NULL, K_PRIO_COOP(CONFIG_LPS22HH_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_LPS22HH_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/lsm6dsl/Kconfig b/drivers/sensor/lsm6dsl/Kconfig index 57d8f9a88b3..c21937cf922 100644 --- a/drivers/sensor/lsm6dsl/Kconfig +++ b/drivers/sensor/lsm6dsl/Kconfig @@ -130,7 +130,7 @@ config LSM6DSL_ACCEL_FS config LSM6DSL_ACCEL_ODR int "Accelerometer Output data rate frequency" - range 0 10 + range 0 11 default 0 help Specify the default accelerometer output data rate expressed in @@ -146,6 +146,7 @@ config LSM6DSL_ACCEL_ODR 8: 1666Hz 9: 3332Hz 10: 6664Hz + 11: 1.6Hz endmenu endif # LSM6DSL diff --git a/drivers/sensor/lsm6dsl/lsm6dsl.c b/drivers/sensor/lsm6dsl/lsm6dsl.c index 8b7dc2fe8dc..0a0f3525804 100644 --- a/drivers/sensor/lsm6dsl/lsm6dsl.c +++ b/drivers/sensor/lsm6dsl/lsm6dsl.c @@ -18,15 +18,17 @@ #include #include #include +#include #include "lsm6dsl.h" LOG_MODULE_REGISTER(LSM6DSL, CONFIG_SENSOR_LOG_LEVEL); static const uint16_t lsm6dsl_odr_map[] = {0, 12, 26, 52, 104, 208, 416, 833, - 1666, 3332, 6664}; + 1666, 3332, 6664, 1}; -#if defined(LSM6DSL_ACCEL_ODR_RUNTIME) || defined(LSM6DSL_GYRO_ODR_RUNTIME) +#if defined(LSM6DSL_ACCEL_ODR_RUNTIME) || defined(LSM6DSL_GYRO_ODR_RUNTIME) ||\ + defined(CONFIG_PM_DEVICE) static int lsm6dsl_freq_to_odr_val(uint16_t freq) { size_t i; @@ -48,8 +50,9 @@ static int lsm6dsl_odr_to_freq_val(uint16_t odr) return lsm6dsl_odr_map[odr]; } - /* invalid index, return last entry */ - return lsm6dsl_odr_map[ARRAY_SIZE(lsm6dsl_odr_map) - 1]; + /* invalid index, return the fastest entry (6.66kHz) */ + BUILD_ASSERT(ARRAY_SIZE(lsm6dsl_odr_map) > 10); + return lsm6dsl_odr_map[10]; } #ifdef LSM6DSL_ACCEL_FS_RUNTIME @@ -168,6 +171,8 @@ static int lsm6dsl_gyro_set_odr_raw(const struct device *dev, uint8_t odr) return -EIO; } + data->gyro_freq = lsm6dsl_odr_to_freq_val(odr); + return 0; } @@ -825,6 +830,59 @@ static int lsm6dsl_init(const struct device *dev) return 0; } +#ifdef CONFIG_PM_DEVICE +static int lsm6dsl_pm_action(const struct device *dev, + enum pm_device_action action) +{ + struct lsm6dsl_data *data = dev->data; + int ret = -EIO; + uint8_t accel_odr = 0; + uint8_t gyro_odr = 0; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + /* Restore saved ODR values */ + accel_odr = lsm6dsl_freq_to_odr_val(data->accel_freq); + ret = lsm6dsl_accel_set_odr_raw(dev, accel_odr); + if (ret < 0) { + LOG_ERR("Failed to resume accelerometer"); + break; + } + gyro_odr = lsm6dsl_freq_to_odr_val(data->gyro_freq); + ret = lsm6dsl_gyro_set_odr_raw(dev, gyro_odr); + if (ret < 0) { + LOG_ERR("Failed to resume gyro"); + break; + } + break; + case PM_DEVICE_ACTION_SUSPEND: + /* + * Set accelerometer ODR to power-down. Don't use the direct + * function to not overwrite the saved value + */ + ret = data->hw_tf->update_reg(dev, LSM6DSL_REG_CTRL1_XL, + LSM6DSL_MASK_CTRL1_XL_ODR_XL, 0); + if (ret < 0) { + LOG_ERR("Failed to suspend accelerometer"); + break; + } + /* Set gyro ODR to power-down */ + ret = data->hw_tf->update_reg(dev, LSM6DSL_REG_CTRL2_G, + LSM6DSL_MASK_CTRL2_G_ODR_G, 0); + if (ret < 0) { + LOG_ERR("Failed to suspend gyro"); + break; + } + + break; + default: + return -ENOTSUP; + } + + return ret; +} +#endif + #if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0 #warning "LSM6DSL driver enabled without any devices" @@ -836,9 +894,10 @@ static int lsm6dsl_init(const struct device *dev) */ #define LSM6DSL_DEVICE_INIT(inst) \ + PM_DEVICE_DT_INST_DEFINE(inst, lsm6dsl_pm_action); \ SENSOR_DEVICE_DT_INST_DEFINE(inst, \ lsm6dsl_init, \ - NULL, \ + PM_DEVICE_DT_INST_GET(inst), \ &lsm6dsl_data_##inst, \ &lsm6dsl_config_##inst, \ POST_KERNEL, \ diff --git a/drivers/sensor/lsm6dsl/lsm6dsl.h b/drivers/sensor/lsm6dsl/lsm6dsl.h index f424cbf2326..da176f4f692 100644 --- a/drivers/sensor/lsm6dsl/lsm6dsl.h +++ b/drivers/sensor/lsm6dsl/lsm6dsl.h @@ -667,6 +667,7 @@ struct lsm6dsl_data { #endif const struct lsm6dsl_transfer_function *hw_tf; uint16_t accel_freq; + uint16_t gyro_freq; #ifdef CONFIG_LSM6DSL_TRIGGER const struct device *dev; diff --git a/drivers/sensor/lsm6dsl/lsm6dsl_trigger.c b/drivers/sensor/lsm6dsl/lsm6dsl_trigger.c index b84464cb396..989d322678e 100644 --- a/drivers/sensor/lsm6dsl/lsm6dsl_trigger.c +++ b/drivers/sensor/lsm6dsl/lsm6dsl_trigger.c @@ -97,8 +97,12 @@ static void lsm6dsl_thread_cb(const struct device *dev) } #ifdef CONFIG_LSM6DSL_TRIGGER_OWN_THREAD -static void lsm6dsl_thread(const struct device *dev) +static void lsm6dsl_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; struct lsm6dsl_data *drv_data = dev->data; while (1) { @@ -156,7 +160,7 @@ int lsm6dsl_init_interrupt(const struct device *dev) k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_LSM6DSL_THREAD_STACK_SIZE, - (k_thread_entry_t)lsm6dsl_thread, (void *)dev, + lsm6dsl_thread, (void *)dev, NULL, NULL, K_PRIO_COOP(CONFIG_LSM6DSL_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_LSM6DSL_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/lsm6dso/lsm6dso.c b/drivers/sensor/lsm6dso/lsm6dso.c index 2344d2c02ee..fe6b65edbec 100644 --- a/drivers/sensor/lsm6dso/lsm6dso.c +++ b/drivers/sensor/lsm6dso/lsm6dso.c @@ -23,8 +23,8 @@ LOG_MODULE_REGISTER(LSM6DSO, CONFIG_SENSOR_LOG_LEVEL); -static const uint16_t lsm6dso_odr_map[] = {0, 12, 26, 52, 104, 208, 416, 833, - 1660, 3330, 6660}; +static const uint16_t lsm6dso_odr_map[] = {0, 12, 26, 52, 104, 208, 417, 833, + 1667, 3333, 6667}; static int lsm6dso_freq_to_odr_val(uint16_t freq) { diff --git a/drivers/sensor/lsm6dso/lsm6dso_trigger.c b/drivers/sensor/lsm6dso/lsm6dso_trigger.c index 8181c91c604..8f8bc527282 100644 --- a/drivers/sensor/lsm6dso/lsm6dso_trigger.c +++ b/drivers/sensor/lsm6dso/lsm6dso_trigger.c @@ -228,8 +228,13 @@ static void lsm6dso_gpio_callback(const struct device *dev, } #ifdef CONFIG_LSM6DSO_TRIGGER_OWN_THREAD -static void lsm6dso_thread(struct lsm6dso_data *lsm6dso) +static void lsm6dso_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct lsm6dso_data *lsm6dso = p1; + while (1) { k_sem_take(&lsm6dso->gpio_sem, K_FOREVER); lsm6dso_handle_interrupt(lsm6dso->dev); @@ -265,7 +270,7 @@ int lsm6dso_init_interrupt(const struct device *dev) k_thread_create(&lsm6dso->thread, lsm6dso->thread_stack, CONFIG_LSM6DSO_THREAD_STACK_SIZE, - (k_thread_entry_t)lsm6dso_thread, lsm6dso, + lsm6dso_thread, lsm6dso, NULL, NULL, K_PRIO_COOP(CONFIG_LSM6DSO_THREAD_PRIORITY), 0, K_NO_WAIT); k_thread_name_set(&lsm6dso->thread, "lsm6dso"); diff --git a/drivers/sensor/lsm6dso16is/lsm6dso16is_trigger.c b/drivers/sensor/lsm6dso16is/lsm6dso16is_trigger.c index c9bcc313bad..93ce4f6c0b0 100644 --- a/drivers/sensor/lsm6dso16is/lsm6dso16is_trigger.c +++ b/drivers/sensor/lsm6dso16is/lsm6dso16is_trigger.c @@ -256,8 +256,13 @@ static void lsm6dso16is_gpio_callback(const struct device *dev, } #ifdef CONFIG_LSM6DSO16IS_TRIGGER_OWN_THREAD -static void lsm6dso16is_thread(struct lsm6dso16is_data *lsm6dso16is) +static void lsm6dso16is_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct lsm6dso16is_data *lsm6dso16is = p1; + while (1) { k_sem_take(&lsm6dso16is->gpio_sem, K_FOREVER); lsm6dso16is_handle_interrupt(lsm6dso16is->dev); @@ -293,7 +298,7 @@ int lsm6dso16is_init_interrupt(const struct device *dev) k_thread_create(&lsm6dso16is->thread, lsm6dso16is->thread_stack, CONFIG_LSM6DSO16IS_THREAD_STACK_SIZE, - (k_thread_entry_t)lsm6dso16is_thread, lsm6dso16is, + lsm6dso16is_thread, lsm6dso16is, NULL, NULL, K_PRIO_COOP(CONFIG_LSM6DSO16IS_THREAD_PRIORITY), 0, K_NO_WAIT); k_thread_name_set(&lsm6dso16is->thread, "lsm6dso16is"); diff --git a/drivers/sensor/lsm6dsv16x/lsm6dsv16x.c b/drivers/sensor/lsm6dsv16x/lsm6dsv16x.c index b2bed66b47d..f7d53bc0b93 100644 --- a/drivers/sensor/lsm6dsv16x/lsm6dsv16x.c +++ b/drivers/sensor/lsm6dsv16x/lsm6dsv16x.c @@ -919,9 +919,10 @@ static int lsm6dsv16x_init(const struct device *dev) */ #ifdef CONFIG_LSM6DSV16X_TRIGGER -#define LSM6DSV16X_CFG_IRQ(inst) \ +#define LSM6DSV16X_CFG_IRQ(inst) \ .trig_enabled = true, \ - .gpio_drdy = GPIO_DT_SPEC_INST_GET(inst, irq_gpios), \ + .int1_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int1_gpios, { 0 }), \ + .int2_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int2_gpios, { 0 }), \ .drdy_pin = DT_INST_PROP(inst, drdy_pin) #else #define LSM6DSV16X_CFG_IRQ(inst) @@ -938,8 +939,7 @@ static int lsm6dsv16x_init(const struct device *dev) .gyro_odr = DT_INST_PROP(inst, gyro_odr), \ .gyro_range = DT_INST_PROP(inst, gyro_range), \ .drdy_pulsed = DT_INST_PROP(inst, drdy_pulsed), \ - COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, irq_gpios), \ - (LSM6DSV16X_CFG_IRQ(inst)), ()) + LSM6DSV16X_CFG_IRQ(inst) #define LSM6DSV16X_CONFIG_SPI(inst) \ { \ diff --git a/drivers/sensor/lsm6dsv16x/lsm6dsv16x.h b/drivers/sensor/lsm6dsv16x/lsm6dsv16x.h index 92a5e4cdcba..2b3819b306a 100644 --- a/drivers/sensor/lsm6dsv16x/lsm6dsv16x.h +++ b/drivers/sensor/lsm6dsv16x/lsm6dsv16x.h @@ -57,7 +57,8 @@ struct lsm6dsv16x_config { uint8_t gyro_range; uint8_t drdy_pulsed; #ifdef CONFIG_LSM6DSV16X_TRIGGER - const struct gpio_dt_spec gpio_drdy; + const struct gpio_dt_spec int1_gpio; + const struct gpio_dt_spec int2_gpio; uint8_t drdy_pin; bool trig_enabled; #endif /* CONFIG_LSM6DSV16X_TRIGGER */ @@ -102,6 +103,8 @@ struct lsm6dsv16x_data { uint8_t gyro_fs; #ifdef CONFIG_LSM6DSV16X_TRIGGER + struct gpio_dt_spec *drdy_gpio; + struct gpio_callback gpio_cb; sensor_trigger_handler_t handler_drdy_acc; const struct sensor_trigger *trig_drdy_acc; diff --git a/drivers/sensor/lsm6dsv16x/lsm6dsv16x_trigger.c b/drivers/sensor/lsm6dsv16x/lsm6dsv16x_trigger.c index b82e371bc9c..2911ee55cb7 100644 --- a/drivers/sensor/lsm6dsv16x/lsm6dsv16x_trigger.c +++ b/drivers/sensor/lsm6dsv16x/lsm6dsv16x_trigger.c @@ -233,7 +233,7 @@ static void lsm6dsv16x_handle_interrupt(const struct device *dev) #endif } - gpio_pin_interrupt_configure_dt(&cfg->gpio_drdy, + gpio_pin_interrupt_configure_dt(lsm6dsv16x->drdy_gpio, GPIO_INT_EDGE_TO_ACTIVE); } @@ -242,11 +242,10 @@ static void lsm6dsv16x_gpio_callback(const struct device *dev, { struct lsm6dsv16x_data *lsm6dsv16x = CONTAINER_OF(cb, struct lsm6dsv16x_data, gpio_cb); - const struct lsm6dsv16x_config *cfg = lsm6dsv16x->dev->config; ARG_UNUSED(pins); - gpio_pin_interrupt_configure_dt(&cfg->gpio_drdy, GPIO_INT_DISABLE); + gpio_pin_interrupt_configure_dt(lsm6dsv16x->drdy_gpio, GPIO_INT_DISABLE); #if defined(CONFIG_LSM6DSV16X_TRIGGER_OWN_THREAD) k_sem_give(&lsm6dsv16x->gpio_sem); @@ -256,8 +255,13 @@ static void lsm6dsv16x_gpio_callback(const struct device *dev, } #ifdef CONFIG_LSM6DSV16X_TRIGGER_OWN_THREAD -static void lsm6dsv16x_thread(struct lsm6dsv16x_data *lsm6dsv16x) +static void lsm6dsv16x_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct lsm6dsv16x_data *lsm6dsv16x = p1; + while (1) { k_sem_take(&lsm6dsv16x->gpio_sem, K_FOREVER); lsm6dsv16x_handle_interrupt(lsm6dsv16x->dev); @@ -282,8 +286,12 @@ int lsm6dsv16x_init_interrupt(const struct device *dev) stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; int ret; + lsm6dsv16x->drdy_gpio = (cfg->drdy_pin == 1) ? + (struct gpio_dt_spec *)&cfg->int1_gpio : + (struct gpio_dt_spec *)&cfg->int2_gpio; + /* setup data ready gpio interrupt (INT1 or INT2) */ - if (!gpio_is_ready_dt(&cfg->gpio_drdy)) { + if (!gpio_is_ready_dt(lsm6dsv16x->drdy_gpio)) { LOG_ERR("Cannot get pointer to drdy_gpio device"); return -EINVAL; } @@ -293,7 +301,7 @@ int lsm6dsv16x_init_interrupt(const struct device *dev) k_thread_create(&lsm6dsv16x->thread, lsm6dsv16x->thread_stack, CONFIG_LSM6DSV16X_THREAD_STACK_SIZE, - (k_thread_entry_t)lsm6dsv16x_thread, lsm6dsv16x, + lsm6dsv16x_thread, lsm6dsv16x, NULL, NULL, K_PRIO_COOP(CONFIG_LSM6DSV16X_THREAD_PRIORITY), 0, K_NO_WAIT); k_thread_name_set(&lsm6dsv16x->thread, "lsm6dsv16x"); @@ -301,7 +309,7 @@ int lsm6dsv16x_init_interrupt(const struct device *dev) lsm6dsv16x->work.handler = lsm6dsv16x_work_cb; #endif /* CONFIG_LSM6DSV16X_TRIGGER_OWN_THREAD */ - ret = gpio_pin_configure_dt(&cfg->gpio_drdy, GPIO_INPUT); + ret = gpio_pin_configure_dt(lsm6dsv16x->drdy_gpio, GPIO_INPUT); if (ret < 0) { LOG_DBG("Could not configure gpio"); return ret; @@ -309,9 +317,9 @@ int lsm6dsv16x_init_interrupt(const struct device *dev) gpio_init_callback(&lsm6dsv16x->gpio_cb, lsm6dsv16x_gpio_callback, - BIT(cfg->gpio_drdy.pin)); + BIT(lsm6dsv16x->drdy_gpio->pin)); - if (gpio_add_callback(cfg->gpio_drdy.port, &lsm6dsv16x->gpio_cb) < 0) { + if (gpio_add_callback(lsm6dsv16x->drdy_gpio->port, &lsm6dsv16x->gpio_cb) < 0) { LOG_DBG("Could not set gpio callback"); return -EIO; } @@ -328,6 +336,6 @@ int lsm6dsv16x_init_interrupt(const struct device *dev) return ret; } - return gpio_pin_interrupt_configure_dt(&cfg->gpio_drdy, + return gpio_pin_interrupt_configure_dt(lsm6dsv16x->drdy_gpio, GPIO_INT_EDGE_TO_ACTIVE); } diff --git a/drivers/sensor/lsm9ds0_gyro/lsm9ds0_gyro_trigger.c b/drivers/sensor/lsm9ds0_gyro/lsm9ds0_gyro_trigger.c index 35a46032406..08441deff79 100644 --- a/drivers/sensor/lsm9ds0_gyro/lsm9ds0_gyro_trigger.c +++ b/drivers/sensor/lsm9ds0_gyro/lsm9ds0_gyro_trigger.c @@ -80,8 +80,12 @@ static void lsm9ds0_gyro_gpio_drdy_callback(const struct device *dev, k_sem_give(&data->sem); } -static void lsm9ds0_gyro_thread_main(const struct device *dev) +static void lsm9ds0_gyro_thread_main(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; struct lsm9ds0_gyro_data *data = dev->data; while (1) { @@ -106,7 +110,7 @@ int lsm9ds0_gyro_init_interrupt(const struct device *dev) k_thread_create(&data->thread, data->thread_stack, CONFIG_LSM9DS0_GYRO_THREAD_STACK_SIZE, - (k_thread_entry_t)lsm9ds0_gyro_thread_main, + lsm9ds0_gyro_thread_main, (void *)dev, NULL, NULL, K_PRIO_COOP(10), 0, K_NO_WAIT); if (!gpio_is_ready_dt(&config->int_gpio)) { diff --git a/drivers/sensor/ltrf216a/CMakeLists.txt b/drivers/sensor/ltrf216a/CMakeLists.txt new file mode 100644 index 00000000000..f15dcc346b8 --- /dev/null +++ b/drivers/sensor/ltrf216a/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(ltrf216a.c) diff --git a/drivers/sensor/ltrf216a/Kconfig b/drivers/sensor/ltrf216a/Kconfig new file mode 100644 index 00000000000..fa9cfe9fdbf --- /dev/null +++ b/drivers/sensor/ltrf216a/Kconfig @@ -0,0 +1,12 @@ +# LTR-F216A light sensor configuration options + +# Copyright (c) 2023 Tridonic +# SPDX-License-Identifier: Apache-2.0 + +config LTR_F216A + bool "LiteOn LTR-F216A Light Sensor" + default y + depends on DT_HAS_LTR_F216A_ENABLED + select I2C + help + Enable driver for LiteOn LTR-F216A light sensors. diff --git a/drivers/sensor/ltrf216a/ltrf216a.c b/drivers/sensor/ltrf216a/ltrf216a.c new file mode 100644 index 00000000000..5f6f9282c75 --- /dev/null +++ b/drivers/sensor/ltrf216a/ltrf216a.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2023 Tridonic + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ltr_f216a + +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(ltrf216a, CONFIG_SENSOR_LOG_LEVEL); + +/* + * Driver for I2C illuminance sensor LiteOn LTR-F216A. + * + * Datasheet: + * + + * 7bit Address 0x53 + * 8bit Address 0xA6 read + * 8bit Address 0xA7 write + + * NOT IMPLEMENTED: + * - Interrupt + * - Modifying Gain (using default x3) + * - Modifying Resolution (using default 100ms) + * - Modifying Measurement Rate (using default 100ms) + * - Modifying Window Factor (using default 1) + */ + +#define LTRF216A_ALS_RESET_MASK BIT(4) +#define LTRF216A_ALS_ENABLE_MASK BIT(1) + +#define LTRF216A_ALS_DATA_STATUS BIT(3) + +/* Part Number ID 7:4 0b1011 = 0xB */ +/* Revision ID 3:0 0b0001 = 0x1*/ +#define LTRF216A_PART_ID_VALUE 0xB1 + +#define LTRF216A_MAIN_CTRL 0x00 +#define LTRF216A_ALS_MEAS_RES 0x04 +#define LTRF216A_ALS_GAIN 0x05 +#define LTRF216A_PART_ID 0x06 +#define LTRF216A_MAIN_STATUS 0x07 +#define LTRF216A_ALS_CLEAR_DATA_0 0x0a +#define LTRF216A_ALS_CLEAR_DATA_1 0x0b +#define LTRF216A_ALS_CLEAR_DATA_2 0x0c +#define LTRF216A_ALS_DATA_0 0x0d +#define LTRF216A_ALS_DATA_1 0x0e +#define LTRF216A_ALS_DATA_2 0x0f +#define LTRF216A_INT_CFG 0x19 +#define LTRF216A_INT_PST 0x1a +#define LTRF216A_ALS_THRES_UP_0 0x21 +#define LTRF216A_ALS_THRES_UP_1 0x22 +#define LTRF216A_ALS_THRES_UP_2 0x23 +#define LTRF216A_ALS_THRES_LOW_0 0x24 +#define LTRF216A_ALS_THRES_LOW_1 0x25 +#define LTRF216A_ALS_THRES_LOW_2 0x26 + +#define LTRF216A_WIN_FAC 1 + +#define LTRF216A_NUMBER_DATA_REGISTERS 3 + +struct ltrf216a_data { + uint8_t sample[3]; +}; + +struct ltrf216a_config { + struct i2c_dt_spec i2c; +}; + +static int ltrf216a_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + struct ltrf216a_data *drv_data = dev->data; + const struct ltrf216a_config *config = dev->config; + uint8_t status; + int result; + uint8_t value; + + __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_LIGHT); + + value = LTRF216A_ALS_ENABLE_MASK; + result = i2c_reg_write_byte_dt(&config->i2c, LTRF216A_MAIN_CTRL, LTRF216A_ALS_ENABLE_MASK); + if (result != 0) { + LOG_ERR("ltfr216a: enable failed"); + return result; + } + + result = i2c_reg_read_byte_dt(&config->i2c, LTRF216A_MAIN_STATUS, &status); + if (result != 0) { + LOG_ERR("ltfr216a: read main status failed"); + return -EIO; + } + + if ((status & LTRF216A_ALS_DATA_STATUS) == 0) { + LOG_WRN("ltfr216a: main status not ready"); + return -EBUSY; + } + + if (i2c_burst_read_dt(&config->i2c, LTRF216A_ALS_DATA_0, drv_data->sample, + LTRF216A_NUMBER_DATA_REGISTERS) != 0) { + LOG_ERR("ltfr216a: reading samples failed"); + return -EIO; + } + + return 0; +} + +static int ltrf216a_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + struct ltrf216a_data *drv_data = dev->data; + + if (chan != SENSOR_CHAN_LIGHT) { + return -ENOTSUP; + } + + uint32_t greendata = sys_get_le24(drv_data->sample); + + /* + * 0.45 -> 45 / 100, multiplied by 1000000 for millilux + * gain 3 (default), integration time 100ms=1 + */ + uint64_t microlux = (greendata * 45000 * LTRF216A_WIN_FAC * 10) / (3 * 1); + + val->val1 = microlux / 1000000; + val->val2 = microlux % 1000000; + + return 0; +} + +static const struct sensor_driver_api ltrf216a_driver_api = { + .sample_fetch = ltrf216a_sample_fetch, + .channel_get = ltrf216a_channel_get, +}; + +static int ltrf216a_chip_init(const struct device *dev) +{ + const struct ltrf216a_config *config = dev->config; + uint8_t value; + + if (!i2c_is_ready_dt(&config->i2c)) { + LOG_ERR("Bus device is not ready"); + return -ENODEV; + } + + if (i2c_reg_read_byte_dt(&config->i2c, LTRF216A_PART_ID, &value) != 0) { + return -EIO; + } + + if (value != LTRF216A_PART_ID_VALUE) { + LOG_ERR("Bad manufacturer id 0x%x", value); + return -ENOTSUP; + } + + return 0; +} + +#define LTRF216A_DEFINE(inst) \ + static struct ltrf216a_data ltrf216a_data_##inst; \ + \ + static const struct ltrf216a_config ltrf216a_config_##inst = { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + }; \ + \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, ltrf216a_chip_init, NULL, <rf216a_data_##inst, \ + <rf216a_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, <rf216a_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(LTRF216A_DEFINE) diff --git a/drivers/sensor/max17055/max17055.c b/drivers/sensor/max17055/max17055.c index a50069643af..c2db8255623 100644 --- a/drivers/sensor/max17055/max17055.c +++ b/drivers/sensor/max17055/max17055.c @@ -112,14 +112,23 @@ static int capacity_to_max17055(unsigned int rsense_mohms, uint16_t val_mha) } /** - * @brief Convert voltage in millivolts to MAX17055 units + * @brief Update empty voltage target in v_empty * + * @param v_empty The register value to update * @param val_mv Value in millivolts to convert - * @return corresponding value in MAX17055 units, ready to write to a register + * @return 0 on success, -EINVAL on invalid val_mv */ -static int voltage_mV_to_max17055(uint16_t val_mv) +static int max17055_update_vempty(uint16_t *v_empty, uint16_t val_mv) { - return (val_mv * 16) * 10 / 8; /* * 1.25 */ + uint32_t val = (val_mv / 10) << 7; + + if (val & ~VEMPTY_VE) { + return -EINVAL; + } + + *v_empty = (*v_empty & ~VEMPTY_VE) | (uint16_t)val; + + return 0; } static void set_millis(struct sensor_value *val, int val_millis) @@ -338,27 +347,38 @@ static int max17055_write_config(const struct device *dev) uint16_t d_qacc = design_capacity / 32; uint16_t d_pacc = d_qacc * 44138 / design_capacity; uint16_t i_chg_term = current_ma_to_max17055(config->rsense_mohms, config->i_chg_term); - uint16_t v_empty = voltage_mV_to_max17055(config->v_empty); + uint16_t v_empty; LOG_DBG("Writing configuration parameters"); - LOG_DBG("DesignCap: %u, dQAcc: %u, IChgTerm: %u, VEmpty: %u, dPAcc: %u", - design_capacity, d_qacc, i_chg_term, v_empty, d_pacc); + LOG_DBG("DesignCap: %u, dQAcc: %u, IChgTerm: %u, dPAcc: %u", + design_capacity, d_qacc, i_chg_term, d_pacc); if (max17055_reg_write(dev, DESIGN_CAP, design_capacity)) { return -EIO; } + if (max17055_reg_write(dev, D_QACC, d_qacc)) { return -EIO; } + if (max17055_reg_write(dev, ICHG_TERM, i_chg_term)) { return -EIO; } + + if (max17055_reg_read(dev, V_EMPTY, &v_empty)) { + return -EIO; + } + if (max17055_update_vempty(&v_empty, config->v_empty)) { + return -EINVAL; + } if (max17055_reg_write(dev, V_EMPTY, v_empty)) { return -EIO; } + if (max17055_reg_write(dev, D_PACC, d_pacc)) { return -EIO; } + if (max17055_reg_write(dev, MODEL_CFG, MODELCFG_REFRESH)) { return -EIO; } diff --git a/drivers/sensor/max17055/max17055.h b/drivers/sensor/max17055/max17055.h index 476b8663ec5..38bf100f0d9 100644 --- a/drivers/sensor/max17055/max17055.h +++ b/drivers/sensor/max17055/max17055.h @@ -41,6 +41,7 @@ enum { SOFT_WAKEUP_CLEAR = 0x0000, SOFT_WAKEUP_WAKEUP = 0x0090, STATUS_POR = 0x0002, + VEMPTY_VE = 0xff80, }; struct max17055_data { diff --git a/drivers/sensor/max31855/CMakeLists.txt b/drivers/sensor/max31855/CMakeLists.txt index 6ee5f2df493..b3ef4064956 100644 --- a/drivers/sensor/max31855/CMakeLists.txt +++ b/drivers/sensor/max31855/CMakeLists.txt @@ -2,4 +2,4 @@ zephyr_library() -zephyr_library_sources_ifdef(CONFIG_MAX31855 max31855.c) +zephyr_library_sources(max31855.c) diff --git a/drivers/sensor/mc3419/CMakeLists.txt b/drivers/sensor/mc3419/CMakeLists.txt new file mode 100644 index 00000000000..650f3e9777e --- /dev/null +++ b/drivers/sensor/mc3419/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2023 Linumiz + +zephyr_library() + +zephyr_library_sources(mc3419.c) +zephyr_library_sources_ifdef(CONFIG_MC3419_TRIGGER mc3419_trigger.c) diff --git a/drivers/sensor/mc3419/Kconfig b/drivers/sensor/mc3419/Kconfig new file mode 100644 index 00000000000..81e0665c3e0 --- /dev/null +++ b/drivers/sensor/mc3419/Kconfig @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2023 Linumiz + +menuconfig MC3419 + bool "MC3419 acclerometer driver" + default y + depends on DT_HAS_MEMSIC_MC3419_ENABLED + select I2C if $(dt_compat_on_bus,$(DT_COMPAT_MEMSIC_MC3419),i2c) + help + Enable driver for MC3419 acclerometer. + +if MC3419 + +config MC3419_TRIGGER + bool "Trigger mode" + +if MC3419_TRIGGER + +config MC3419_TRIGGER_OWN_THREAD + bool "Use own thread" + help + Enable trigger to run in own thread. By + default it is global thread mode. + +config MC3419_THREAD_PRIORITY + int "Own thread priority" + depends on MC3419_TRIGGER_OWN_THREAD + default 10 + +config MC3419_THREAD_STACK_SIZE + int "Own thread stask size" + depends on MC3419_TRIGGER_OWN_THREAD + default 1024 + +endif # MC3419_TRIGGER + +config MC3419_DECIMATION_RATE + int "Enable decimation rate" + range 0 15 + default 15 + help + This helps in producing slower interrupt. Internal Data + Rate is divide by this decimation rate. If decimation rate + is 0 then internal data rate is equal to output data rate, + then it produce interrupt floods. + +endif # MC3419 diff --git a/drivers/sensor/mc3419/mc3419.c b/drivers/sensor/mc3419/mc3419.c new file mode 100644 index 00000000000..41f69fd3646 --- /dev/null +++ b/drivers/sensor/mc3419/mc3419.c @@ -0,0 +1,314 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 Linumiz + */ + +#define DT_DRV_COMPAT memsic_mc3419 + +#include +#include +#include +#include +#include +#include "mc3419.h" + +LOG_MODULE_REGISTER(MC3419, CONFIG_SENSOR_LOG_LEVEL); + +static const uint16_t mc3419_accel_sense_map[] = {1, 2, 4, 8, 6}; +static struct mc3419_odr_map odr_map_table[] = { + {25}, {50}, {62, 500}, {100}, + {125}, {250}, {500}, {1000} +}; + +static int mc3419_get_odr_value(uint16_t freq, uint16_t m_freq) +{ + for (int i = 0; i < ARRAY_SIZE(odr_map_table); i++) { + if (odr_map_table[i].freq == freq && + odr_map_table[i].mfreq == m_freq) { + return i; + } + } + + return -EINVAL; +} + +static inline int mc3419_set_op_mode(const struct mc3419_config *cfg, + enum mc3419_op_mode mode) +{ + return i2c_reg_write_byte_dt(&cfg->i2c, MC3419_REG_OP_MODE, mode); +} + +static int mc3419_sample_fetch(const struct device *dev, + enum sensor_channel chan) +{ + int ret = 0; + const struct mc3419_config *cfg = dev->config; + struct mc3419_driver_data *data = dev->data; + + k_sem_take(&data->sem, K_FOREVER); + ret = i2c_burst_read_dt(&cfg->i2c, MC3419_REG_XOUT_L, + (uint8_t *)data->samples, + MC3419_SAMPLE_READ_SIZE); + k_sem_give(&data->sem); + return ret; +} + +static int mc3419_to_sensor_value(double sensitivity, int16_t *raw_data, + struct sensor_value *val) +{ + double value = sys_le16_to_cpu(*raw_data); + + value *= sensitivity * SENSOR_GRAVITY_DOUBLE / 1000; + + return sensor_value_from_double(val, value); +} + +static int mc3419_channel_get(const struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + int ret = 0; + struct mc3419_driver_data *data = dev->data; + + k_sem_take(&data->sem, K_FOREVER); + switch (chan) { + case SENSOR_CHAN_ACCEL_X: + ret = mc3419_to_sensor_value(data->sensitivity, &data->samples[0], val); + break; + case SENSOR_CHAN_ACCEL_Y: + ret = mc3419_to_sensor_value(data->sensitivity, &data->samples[1], val); + break; + case SENSOR_CHAN_ACCEL_Z: + ret = mc3419_to_sensor_value(data->sensitivity, &data->samples[2], val); + break; + case SENSOR_CHAN_ACCEL_XYZ: + ret = mc3419_to_sensor_value(data->sensitivity, &data->samples[0], &val[0]); + ret |= mc3419_to_sensor_value(data->sensitivity, &data->samples[1], &val[1]); + ret |= mc3419_to_sensor_value(data->sensitivity, &data->samples[2], &val[2]); + break; + default: + LOG_ERR("Unsupported channel"); + ret = -ENOTSUP; + } + + k_sem_give(&data->sem); + return ret; +} + +static int mc3419_set_accel_range(const struct device *dev, uint8_t range) +{ + int ret = 0; + const struct mc3419_config *cfg = dev->config; + struct mc3419_driver_data *data = dev->data; + + if (range >= MC3419_ACCL_RANGE_END) { + LOG_ERR("Accel resolution is out of range"); + return -EINVAL; + } + + ret = i2c_reg_update_byte_dt(&cfg->i2c, MC3419_REG_RANGE_SELECT_CTRL, + MC3419_RANGE_MASK, range << 4); + if (ret < 0) { + LOG_ERR("Failed to set resolution (%d)", ret); + return ret; + } + + data->sensitivity = (double)(mc3419_accel_sense_map[range] * + SENSOR_GRAIN_VALUE); + + return 0; +} + +static int mc3419_set_odr(const struct device *dev, + const struct sensor_value *val) +{ + int ret = 0; + int data_rate = 0; + const struct mc3419_config *cfg = dev->config; + + ret = mc3419_get_odr_value(val->val1, val->val2); + if (ret < 0) { + LOG_ERR("Failed to get odr value from odr map (%d)", ret); + return ret; + } + + data_rate = MC3419_BASE_ODR_VAL + ret; + + ret = i2c_reg_write_byte_dt(&cfg->i2c, MC3419_REG_SAMPLE_RATE, + data_rate); + if (ret < 0) { + LOG_ERR("Failed to set ODR (%d)", ret); + return ret; + } + + LOG_DBG("Set ODR Rate to 0x%x", data_rate); + ret = i2c_reg_write_byte_dt(&cfg->i2c, MC3419_REG_SAMPLE_RATE_2, + CONFIG_MC3419_DECIMATION_RATE); + if (ret < 0) { + LOG_ERR("Failed to set decimation rate (%d)", ret); + return ret; + } + + return 0; +} + +#if defined(CONFIG_MC3419_TRIGGER) +static int mc3419_set_anymotion_threshold(const struct device *dev, + const struct sensor_value *val) +{ + int ret = 0; + const struct mc3419_config *cfg = dev->config; + uint8_t buf[3] = {0}; + + if (val->val1 > MC3419_ANY_MOTION_THRESH_MAX) { + return -EINVAL; + } + + buf[0] = MC3419_REG_ANY_MOTION_THRES; + sys_put_le16((uint16_t)val->val1, &buf[1]); + + ret = i2c_write_dt(&cfg->i2c, buf, sizeof(buf)); + if (ret < 0) { + LOG_ERR("Failed to set anymotion threshold (%d)", ret); + return ret; + } + + return 0; +} + +static int mc3419_trigger_set(const struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + int ret = 0; + const struct mc3419_config *cfg = dev->config; + struct mc3419_driver_data *data = dev->data; + + k_sem_take(&data->sem, K_FOREVER); + ret = mc3419_set_op_mode(cfg, MC3419_MODE_STANDBY); + if (ret < 0) { + goto exit; + } + + ret = mc3419_configure_trigger(dev, trig, handler); + if (ret < 0) { + LOG_ERR("Failed to set trigger (%d)", ret); + } + +exit: + mc3419_set_op_mode(cfg, MC3419_MODE_WAKE); + + k_sem_give(&data->sem); + return ret; +} +#endif + +static int mc3419_attr_set(const struct device *dev, + enum sensor_channel chan, + enum sensor_attribute attr, + const struct sensor_value *val) +{ + int ret = 0; + struct mc3419_driver_data *data = dev->data; + + if (chan != SENSOR_CHAN_ACCEL_X && + chan != SENSOR_CHAN_ACCEL_Y && + chan != SENSOR_CHAN_ACCEL_Z && + chan != SENSOR_CHAN_ACCEL_XYZ) { + LOG_ERR("Not supported on this channel."); + return -ENOTSUP; + } + + k_sem_take(&data->sem, K_FOREVER); + ret = mc3419_set_op_mode(dev->config, MC3419_MODE_STANDBY); + if (ret < 0) { + goto exit; + } + + switch (attr) { + case SENSOR_ATTR_FULL_SCALE: + ret = mc3419_set_accel_range(dev, val->val1); + break; + case SENSOR_ATTR_SAMPLING_FREQUENCY: + ret = mc3419_set_odr(dev, val); + break; +#if defined(CONFIG_MC3419_TRIGGER) + case SENSOR_ATTR_SLOPE_TH: + ret = mc3419_set_anymotion_threshold(dev, val); + break; +#endif + default: + LOG_ERR("ACCEL attribute is not supported"); + ret = -EINVAL; + } + +exit: + mc3419_set_op_mode(dev->config, MC3419_MODE_WAKE); + + k_sem_give(&data->sem); + return ret; +} + +static int mc3419_init(const struct device *dev) +{ + int ret = 0; + struct mc3419_driver_data *data = dev->data; + const struct mc3419_config *cfg = dev->config; + + if (!(i2c_is_ready_dt(&cfg->i2c))) { + LOG_ERR("Bus device is not ready"); + return -ENODEV; + } + + k_sem_init(&data->sem, 1, 1); + +#if defined(CONFIG_MC3419_TRIGGER) + ret = mc3419_trigger_init(dev); + if (ret < 0) { + LOG_ERR("Could not initialize interrupts"); + return ret; + } +#endif + + /* Leave the sensor in default power on state, will be + * enabled by configure attr or setting trigger. + */ + + LOG_INF("MC3419 Initialized"); + + return ret; +} + +static const struct sensor_driver_api mc3419_api = { + .attr_set = mc3419_attr_set, +#if defined(CONFIG_MC3419_TRIGGER) + .trigger_set = mc3419_trigger_set, +#endif + .sample_fetch = mc3419_sample_fetch, + .channel_get = mc3419_channel_get, +}; + +#if defined(CONFIG_MC3419_TRIGGER) +#define MC3419_CFG_IRQ(idx) \ + .int_gpio = GPIO_DT_SPEC_INST_GET_OR(idx, int_gpios, { 0 }), \ + .int_cfg = DT_INST_PROP(idx, int_pin2), +#else +#define MC3419_CFG_IRQ(idx) +#endif + +#define MC3419_DEFINE(idx) \ + static const struct mc3419_config mc3419_config_##idx = { \ + .i2c = I2C_DT_SPEC_INST_GET(idx), \ + MC3419_CFG_IRQ(idx) \ + }; \ + static struct mc3419_driver_data mc3419_data_##idx; \ + SENSOR_DEVICE_DT_INST_DEFINE(idx, \ + mc3419_init, NULL, \ + &mc3419_data_##idx, \ + &mc3419_config_##idx, \ + POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, \ + &mc3419_api); + +DT_INST_FOREACH_STATUS_OKAY(MC3419_DEFINE) diff --git a/drivers/sensor/mc3419/mc3419.h b/drivers/sensor/mc3419/mc3419.h new file mode 100644 index 00000000000..6085c60bc48 --- /dev/null +++ b/drivers/sensor/mc3419/mc3419.h @@ -0,0 +1,102 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 Linumiz + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_MC3419_H_ +#define ZEPHYR_DRIVERS_SENSOR_MC3419_H_ + +#include +#include +#include +#include +#include + +/* Registers */ +#define MC3419_REG_INT_CTRL 0x06 +#define MC3419_REG_OP_MODE 0x07 +#define MC3419_REG_SAMPLE_RATE 0x08 +#define MC3419_REG_MOTION_CTRL 0x09 +#define MC3419_REG_XOUT_L 0x0D +#define MC3419_REG_YOUT_L 0x0F +#define MC3419_REG_ZOUT_L 0x11 +#define MC3419_REG_STATUS 0x13 +#define MC3419_REG_INT_STATUS 0x14 +#define MC3419_REG_RANGE_SELECT_CTRL 0x20 +#define MC3419_REG_SAMPLE_RATE_2 0x30 +#define MC3419_REG_COMM_CTRL 0x31 +#define MC3419_REG_ANY_MOTION_THRES 0x43 + +#define MC3419_RANGE_MASK GENMASK(6, 4) +#define MC3419_DATA_READY_MASK BIT(7) +#define MC3419_ANY_MOTION_MASK BIT(2) +#define MC3419_INT_CLEAR 0x00 +#define MC3419_INT_ROUTE 0x10 + +#define MC3419_ANY_MOTION_THRESH_MAX 0x7FFF +#define MC3419_SAMPLE_SIZE 3 +#define MC3419_SAMPLE_READ_SIZE (MC3419_SAMPLE_SIZE * (sizeof(int16_t))) + +#define SENSOR_GRAIN_VALUE (61LL / 1000.0) +#define SENSOR_GRAVITY_DOUBLE (SENSOR_G / 1000000.0) +#define MC3419_BASE_ODR_VAL 0x10 + +#define MC3419_TRIG_DATA_READY 0 +#define MC3419_TRIG_ANY_MOTION 1 +#define MC3419_TRIG_SIZE 2 + +enum mc3419_op_mode { + MC3419_MODE_STANDBY = 0x00, + MC3419_MODE_WAKE = 0x01 +}; + +struct mc3419_odr_map { + int16_t freq; + int16_t mfreq; +}; + +enum mc3419_accl_range { + MC3419_ACCl_RANGE_2G, + MC3419_ACCl_RANGE_4G, + MC3419_ACCl_RANGE_8G, + MC3419_ACCl_RANGE_16G, + MC3419_ACCl_RANGE_12G, + MC3419_ACCL_RANGE_END +}; + +struct mc3419_config { + struct i2c_dt_spec i2c; +#if defined(CONFIG_MC3419_TRIGGER) + struct gpio_dt_spec int_gpio; + bool int_cfg; +#endif +}; + +struct mc3419_driver_data { + double sensitivity; + struct k_sem sem; + int16_t samples[MC3419_SAMPLE_SIZE]; +#if defined(CONFIG_MC3419_TRIGGER) + const struct device *gpio_dev; + struct gpio_callback gpio_cb; + sensor_trigger_handler_t handler[MC3419_TRIG_SIZE]; + const struct sensor_trigger *trigger[MC3419_TRIG_SIZE]; +#if defined(CONFIG_MC3419_TRIGGER_OWN_THREAD) + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_MC3419_THREAD_STACK_SIZE); + struct k_thread thread; + struct k_sem trig_sem; +#else + struct k_work work; +#endif +#endif +}; + +#if defined(CONFIG_MC3419_TRIGGER) +int mc3419_trigger_init(const struct device *dev); +int mc3419_configure_trigger(const struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); +#endif + +#endif diff --git a/drivers/sensor/mc3419/mc3419_trigger.c b/drivers/sensor/mc3419/mc3419_trigger.c new file mode 100644 index 00000000000..ab44fe79d24 --- /dev/null +++ b/drivers/sensor/mc3419/mc3419_trigger.c @@ -0,0 +1,178 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 Linumiz + */ + +#include "mc3419.h" +#include + +LOG_MODULE_DECLARE(MC3419, CONFIG_SENSOR_LOG_LEVEL); + +static void mc3419_gpio_callback(const struct device *dev, + struct gpio_callback *cb, + uint32_t pin_mask) +{ + struct mc3419_driver_data *data = CONTAINER_OF(cb, + struct mc3419_driver_data, gpio_cb); + + const struct mc3419_config *cfg = data->gpio_dev->config; + + if ((pin_mask & BIT(cfg->int_gpio.pin)) == 0U) { + return; + } + +#if defined(CONFIG_MC3419_TRIGGER_OWN_THREAD) + k_sem_give(&data->trig_sem); +#else + k_work_submit(&data->work); +#endif +} + +static void mc3419_process_int(const struct device *dev) +{ + int ret = 0; + const struct mc3419_config *cfg = dev->config; + const struct mc3419_driver_data *data = dev->data; + uint8_t int_source = 0; + + ret = i2c_reg_read_byte_dt(&cfg->i2c, MC3419_REG_INT_STATUS, &int_source); + if (ret < 0) { + goto exit; + } + + if (int_source & MC3419_DATA_READY_MASK) { + if (data->handler[MC3419_TRIG_DATA_READY]) { + data->handler[MC3419_TRIG_DATA_READY](dev, + data->trigger[MC3419_TRIG_DATA_READY]); + } + } + + if (int_source & MC3419_ANY_MOTION_MASK) { + if (data->handler[MC3419_TRIG_ANY_MOTION]) { + data->handler[MC3419_TRIG_ANY_MOTION](dev, + data->trigger[MC3419_TRIG_ANY_MOTION]); + } + } +exit: + ret = i2c_reg_write_byte_dt(&cfg->i2c, MC3419_REG_INT_STATUS, + MC3419_INT_CLEAR); + if (ret < 0) { + LOG_ERR("Failed to clear interrupt (%d)", ret); + } +} + +#if defined(CONFIG_MC3419_TRIGGER_OWN_THREAD) +static void mc3419_thread(struct mc3419_driver_data *data) +{ + while (1) { + k_sem_take(&data->trig_sem, K_FOREVER); + mc3419_process_int(data->gpio_dev); + } +} +#else +static void mc3419_work_cb(struct k_work *work) +{ + struct mc3419_driver_data *data = CONTAINER_OF(work, + struct mc3419_driver_data, work); + + mc3419_process_int(data->gpio_dev); +} +#endif + +int mc3419_configure_trigger(const struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + int ret = 0; + uint8_t buf = 0; + const struct mc3419_config *cfg = dev->config; + struct mc3419_driver_data *data = dev->data; + + if (!(trig->type & SENSOR_TRIG_DATA_READY) && + !(trig->type & SENSOR_TRIG_MOTION)) { + LOG_ERR("Unsupported sensor trigger"); + return -ENOTSUP; + } + + if (trig->type & SENSOR_TRIG_DATA_READY) { + data->handler[MC3419_TRIG_DATA_READY] = handler; + data->trigger[MC3419_TRIG_DATA_READY] = trig; + buf |= MC3419_DATA_READY_MASK; + } + + if (trig->type & SENSOR_TRIG_MOTION) { + uint8_t int_mask = MC3419_ANY_MOTION_MASK; + + buf |= MC3419_ANY_MOTION_MASK; + data->handler[MC3419_TRIG_ANY_MOTION] = handler; + data->trigger[MC3419_TRIG_ANY_MOTION] = trig; + + ret = i2c_reg_update_byte_dt(&cfg->i2c, MC3419_REG_MOTION_CTRL, + int_mask, handler ? int_mask : 0); + if (ret < 0) { + LOG_ERR("Failed to configure motion interrupt (%d)", ret); + return ret; + } + } + + ret = i2c_reg_update_byte_dt(&cfg->i2c, MC3419_REG_INT_CTRL, + buf, buf); + if (ret < 0) { + LOG_ERR("Failed to configure interrupt (%d)", ret); + return ret; + } + + gpio_pin_interrupt_configure_dt(&cfg->int_gpio, GPIO_INT_EDGE_FALLING); + + return ret; +} + +int mc3419_trigger_init(const struct device *dev) +{ + int ret = 0; + struct mc3419_driver_data *data = dev->data; + const struct mc3419_config *cfg = dev->config; + + if (!gpio_is_ready_dt(&cfg->int_gpio)) { + LOG_ERR("GPIO port %s not ready", cfg->int_gpio.port->name); + return -ENODEV; + } + + ret = gpio_pin_configure_dt(&cfg->int_gpio, GPIO_INPUT); + if (ret < 0) { + LOG_ERR("Failed to configure interrupt gpio"); + return ret; + } + + data->gpio_dev = dev; + +#if defined(CONFIG_MC3419_TRIGGER_OWN_THREAD) + k_sem_init(&data->trig_sem, 0, 1); + k_thread_create(&data->thread, data->thread_stack, + CONFIG_MC3419_THREAD_STACK_SIZE, + (k_thread_entry_t)mc3419_thread, data, NULL, + NULL, K_PRIO_COOP(CONFIG_MC3419_THREAD_PRIORITY), 0, + K_NO_WAIT); +#else + k_work_init(&data->work, mc3419_work_cb); +#endif + gpio_init_callback(&data->gpio_cb, mc3419_gpio_callback, + BIT(cfg->int_gpio.pin)); + ret = gpio_add_callback(cfg->int_gpio.port, &data->gpio_cb); + if (ret < 0) { + LOG_ERR("Failed to set int callback"); + return ret; + } + + if (cfg->int_cfg) { + ret = i2c_reg_write_byte_dt(&cfg->i2c, MC3419_REG_COMM_CTRL, + MC3419_INT_ROUTE); + if (ret < 0) { + LOG_ERR("Failed to route the interrupt to INT2 pin (%d)", ret); + return ret; + } + } + + return 0; +} diff --git a/drivers/sensor/mcp970x/mcp970x.c b/drivers/sensor/mcp970x/mcp970x.c index 61d95fc5505..fb43f4d92e3 100644 --- a/drivers/sensor/mcp970x/mcp970x.c +++ b/drivers/sensor/mcp970x/mcp970x.c @@ -46,7 +46,7 @@ static int fetch(const struct device *dev, enum sensor_channel chan) return -ENOTSUP; } - ret = adc_read(config->adc.dev, &data->sequence); + ret = adc_read_dt(&config->adc, &data->sequence); if (ret != 0) { LOG_ERR("adc_read: %d", ret); } diff --git a/drivers/sensor/mcp9808/mcp9808_trigger.c b/drivers/sensor/mcp9808/mcp9808_trigger.c index 627f77f04b5..6c42661d073 100644 --- a/drivers/sensor/mcp9808/mcp9808_trigger.c +++ b/drivers/sensor/mcp9808/mcp9808_trigger.c @@ -129,8 +129,13 @@ static void alert_cb(const struct device *dev, struct gpio_callback *cb, #ifdef CONFIG_MCP9808_TRIGGER_OWN_THREAD -static void mcp9808_thread_main(struct mcp9808_data *data) +static void mcp9808_thread_main(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct mcp9808_data *data = p1; + while (true) { k_sem_take(&data->sem, K_FOREVER); process_int(data->dev); @@ -169,7 +174,7 @@ int mcp9808_setup_interrupt(const struct device *dev) k_thread_create(&mcp9808_thread, mcp9808_thread_stack, CONFIG_MCP9808_THREAD_STACK_SIZE, - (k_thread_entry_t)mcp9808_thread_main, data, NULL, NULL, + mcp9808_thread_main, data, NULL, NULL, K_PRIO_COOP(CONFIG_MCP9808_THREAD_PRIORITY), 0, K_NO_WAIT); #else /* CONFIG_MCP9808_TRIGGER_GLOBAL_THREAD */ diff --git a/drivers/sensor/mpu6050/mpu6050.c b/drivers/sensor/mpu6050/mpu6050.c index 9476b420bce..f00ca138c78 100644 --- a/drivers/sensor/mpu6050/mpu6050.c +++ b/drivers/sensor/mpu6050/mpu6050.c @@ -104,6 +104,7 @@ static int mpu6050_channel_get(const struct device *dev, break; case SENSOR_CHAN_DIE_TEMP: mpu6050_convert_temp(val, drv_data->temp); + break; default: return -ENOTSUP; } @@ -160,7 +161,7 @@ int mpu6050_init(const struct device *dev) return -EIO; } - if (id != MPU6050_CHIP_ID && id != MPU9250_CHIP_ID) { + if ((id != MPU6050_CHIP_ID) && (id != MPU9250_CHIP_ID) && (id != MPU6880_CHIP_ID)) { LOG_ERR("Invalid chip ID."); return -EINVAL; } diff --git a/drivers/sensor/mpu6050/mpu6050.h b/drivers/sensor/mpu6050/mpu6050.h index 305704a4596..0bc20a5c070 100644 --- a/drivers/sensor/mpu6050/mpu6050.h +++ b/drivers/sensor/mpu6050/mpu6050.h @@ -17,6 +17,7 @@ #define MPU6050_REG_CHIP_ID 0x75 #define MPU6050_CHIP_ID 0x68 #define MPU9250_CHIP_ID 0x71 +#define MPU6880_CHIP_ID 0x19 #define MPU6050_REG_GYRO_CFG 0x1B #define MPU6050_GYRO_FS_SHIFT 3 diff --git a/drivers/sensor/mpu6050/mpu6050_trigger.c b/drivers/sensor/mpu6050/mpu6050_trigger.c index 5415dbe1f41..69d45ea0182 100644 --- a/drivers/sensor/mpu6050/mpu6050_trigger.c +++ b/drivers/sensor/mpu6050/mpu6050_trigger.c @@ -77,8 +77,13 @@ static void mpu6050_thread_cb(const struct device *dev) } #ifdef CONFIG_MPU6050_TRIGGER_OWN_THREAD -static void mpu6050_thread(struct mpu6050_data *drv_data) +static void mpu6050_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct mpu6050_data *drv_data = p1; + while (1) { k_sem_take(&drv_data->gpio_sem, K_FOREVER); mpu6050_thread_cb(drv_data->dev); @@ -131,7 +136,7 @@ int mpu6050_init_interrupt(const struct device *dev) k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_MPU6050_THREAD_STACK_SIZE, - (k_thread_entry_t)mpu6050_thread, drv_data, + mpu6050_thread, drv_data, NULL, NULL, K_PRIO_COOP(CONFIG_MPU6050_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_MPU6050_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/mpu9250/mpu9250_trigger.c b/drivers/sensor/mpu9250/mpu9250_trigger.c index fdfeb016b19..5619bfb50dc 100644 --- a/drivers/sensor/mpu9250/mpu9250_trigger.c +++ b/drivers/sensor/mpu9250/mpu9250_trigger.c @@ -94,8 +94,13 @@ static void mpu9250_thread_cb(const struct device *dev) } #ifdef CONFIG_MPU9250_TRIGGER_OWN_THREAD -static void mpu9250_thread(struct mpu9250_data *drv_data) +static void mpu9250_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct mpu9250_data *drv_data = p1; + while (1) { k_sem_take(&drv_data->gpio_sem, K_FOREVER); mpu9250_thread_cb(drv_data->dev); @@ -160,7 +165,7 @@ int mpu9250_init_interrupt(const struct device *dev) k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_MPU9250_THREAD_STACK_SIZE, - (k_thread_entry_t)mpu9250_thread, drv_data, + mpu9250_thread, drv_data, NULL, NULL, K_PRIO_COOP(CONFIG_MPU9250_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_MPU9250_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/npm1300_charger/npm1300_charger.c b/drivers/sensor/npm1300_charger/npm1300_charger.c index 3049e4d7844..c6cfd8cbe2e 100644 --- a/drivers/sensor/npm1300_charger/npm1300_charger.c +++ b/drivers/sensor/npm1300_charger/npm1300_charger.c @@ -20,6 +20,7 @@ struct npm1300_charger_config { int32_t dischg_limit_microamp; int32_t vbus_limit_microamp; int32_t temp_thresholds[4U]; + int32_t dietemp_thresholds[2U]; uint32_t thermistor_ohms; uint16_t thermistor_beta; uint8_t thermistor_idx; @@ -34,6 +35,7 @@ struct npm1300_charger_data { uint16_t voltage; uint16_t current; uint16_t temp; + uint16_t dietemp; uint8_t status; uint8_t error; uint8_t ibat_stat; @@ -57,6 +59,7 @@ struct npm1300_charger_data { #define CHGR_OFFSET_TRICKLE_SEL 0x0EU #define CHGR_OFFSET_ITERM_SEL 0x0FU #define CHGR_OFFSET_NTC_TEMPS 0x10U +#define CHGR_OFFSET_DIE_TEMPS 0x18U #define CHGR_OFFSET_CHG_STAT 0x34U #define CHGR_OFFSET_ERR_REASON 0x36U #define CHGR_OFFSET_VBATLOW_EN 0x50U @@ -64,6 +67,7 @@ struct npm1300_charger_data { /* nPM1300 ADC register offsets */ #define ADC_OFFSET_TASK_VBAT 0x00U #define ADC_OFFSET_TASK_TEMP 0x01U +#define ADC_OFFSET_TASK_DIE 0x02U #define ADC_OFFSET_CONFIG 0x09U #define ADC_OFFSET_NTCR_SEL 0x0AU #define ADC_OFFSET_TASK_AUTO 0x0CU @@ -71,7 +75,10 @@ struct npm1300_charger_data { #define ADC_OFFSET_IBAT_EN 0x24U /* nPM1300 VBUS register offsets */ +#define VBUS_OFFSET_ILIMUPDATE 0x00U +#define VBUS_OFFSET_ILIM 0x01U #define VBUS_OFFSET_ILIMSTARTUP 0x02U +#define VBUS_OFFSET_DETECT 0x05U #define VBUS_OFFSET_STATUS 0x07U /* Ibat status */ @@ -99,12 +106,27 @@ struct adc_results_t { #define ADC_LSB_MASK 0x03U #define ADC_LSB_VBAT_SHIFT 0U #define ADC_LSB_NTC_SHIFT 2U +#define ADC_LSB_DIE_SHIFT 4U #define ADC_LSB_IBAT_SHIFT 4U /* NTC temp masks */ #define NTCTEMP_MSB_SHIFT 2U #define NTCTEMP_LSB_MASK 0x03U +/* dietemp masks */ +#define DIETEMP_MSB_SHIFT 2U +#define DIETEMP_LSB_MASK 0x03U + +/* VBUS masks */ +#define DETECT_HI_MASK 0x0AU +#define DETECT_HI_CURRENT 1500000 +#define DETECT_LO_CURRENT 500000 + +/* Dietemp calculation constants */ +#define DIETEMP_OFFSET_MDEGC 394670 +#define DIETEMP_FACTOR_MUL 3963000 +#define DIETEMP_FACTOR_DIV 5000 + /* Linear range for charger terminal voltage */ static const struct linear_range charger_volt_ranges[] = { LINEAR_RANGE_INIT(3500000, 50000, 0U, 3U), LINEAR_RANGE_INIT(4000000, 50000, 4U, 13U)}; @@ -132,10 +154,21 @@ static void calc_temp(const struct npm1300_charger_config *const config, uint16_ valp->val2 = (int32_t)(fmodf(temp, 1.f) * 1000000.f); } +static void calc_dietemp(const struct npm1300_charger_config *const config, uint16_t code, + struct sensor_value *valp) +{ + /* Ref: Datasheet Figure 36: Die temperature (Celcius) */ + int32_t temp = + DIETEMP_OFFSET_MDEGC - (((int32_t)code * DIETEMP_FACTOR_MUL) / DIETEMP_FACTOR_DIV); + + valp->val1 = temp / 1000; + valp->val2 = (temp % 1000) * 1000; +} + static uint32_t calc_ntc_res(const struct npm1300_charger_config *const config, int32_t temp_mdegc) { float inv_t0 = 1.f / 298.15f; - float temp = (float)temp_mdegc / 1000000.f; + float temp = (float)temp_mdegc / 1000.f; float inv_temp_k = 1.f / (temp + 273.15f); @@ -159,13 +192,11 @@ static void calc_current(const struct npm1300_charger_config *const config, full_scale_ma = config->dischg_limit_microamp / 1000; break; case IBAT_STAT_CHARGE_TRICKLE: - full_scale_ma = -config->current_microamp / 10000; - break; + /* Fallthrough */ case IBAT_STAT_CHARGE_COOL: - full_scale_ma = -config->current_microamp / 2000; - break; + /* Fallthrough */ case IBAT_STAT_CHARGE_NORMAL: - full_scale_ma = -config->current_microamp / 1000; + full_scale_ma = -config->current_microamp / 800; break; default: full_scale_ma = 0; @@ -213,6 +244,9 @@ int npm1300_charger_channel_get(const struct device *dev, enum sensor_channel ch valp->val1 = config->dischg_limit_microamp / 1000000; valp->val2 = config->dischg_limit_microamp % 1000000; break; + case SENSOR_CHAN_DIE_TEMP: + calc_dietemp(config, data->dietemp, valp); + break; default: return -ENOTSUP; } @@ -247,11 +281,12 @@ int npm1300_charger_sample_fetch(const struct device *dev, enum sensor_channel c data->voltage = adc_get_res(results.msb_vbat, results.lsb_a, ADC_LSB_VBAT_SHIFT); data->temp = adc_get_res(results.msb_ntc, results.lsb_a, ADC_LSB_NTC_SHIFT); + data->dietemp = adc_get_res(results.msb_die, results.lsb_a, ADC_LSB_DIE_SHIFT); data->current = adc_get_res(results.msb_ibat, results.lsb_b, ADC_LSB_IBAT_SHIFT); data->ibat_stat = results.ibat_stat; - /* Trigger temperature measurement */ - ret = mfd_npm1300_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_TASK_TEMP, 1U); + /* Trigger ntc and die temperature measurements */ + ret = mfd_npm1300_reg_write2(config->mfd, ADC_BASE, ADC_OFFSET_TASK_TEMP, 1U, 1U); if (ret != 0) { return ret; } @@ -293,6 +328,29 @@ static int set_ntc_thresholds(const struct npm1300_charger_config *const config) return 0; } +static int set_dietemp_thresholds(const struct npm1300_charger_config *const config) +{ + for (uint8_t idx = 0U; idx < 2U; idx++) { + if (config->dietemp_thresholds[idx] < INT32_MAX) { + /* Ref: Datasheet section 6.2.6: Charger thermal regulation */ + int32_t numerator = + (DIETEMP_OFFSET_MDEGC - config->dietemp_thresholds[idx]) * + DIETEMP_FACTOR_DIV; + uint16_t code = DIV_ROUND_CLOSEST(numerator, DIETEMP_FACTOR_MUL); + + int ret = mfd_npm1300_reg_write2( + config->mfd, CHGR_BASE, CHGR_OFFSET_DIE_TEMPS + (idx * 2U), + code >> DIETEMP_MSB_SHIFT, code & DIETEMP_LSB_MASK); + + if (ret != 0) { + return ret; + } + } + } + + return 0; +} + static int npm1300_charger_attr_get(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, struct sensor_value *val) { @@ -312,6 +370,32 @@ static int npm1300_charger_attr_get(const struct device *dev, enum sensor_channe val->val2 = 0U; } return ret; + + case SENSOR_CHAN_CURRENT: + if (attr != SENSOR_ATTR_UPPER_THRESH) { + return -ENOTSUP; + } + + ret = mfd_npm1300_reg_read(config->mfd, VBUS_BASE, VBUS_OFFSET_DETECT, &data); + if (ret < 0) { + return ret; + } + + if (data == 0U) { + /* No charger connected */ + val->val1 = 0; + val->val2 = 0; + } else if ((data & DETECT_HI_MASK) != 0U) { + /* CC1 or CC2 indicate 1.5A or 3A capability */ + val->val1 = DETECT_HI_CURRENT / 1000000; + val->val2 = DETECT_HI_CURRENT % 1000000; + } else { + val->val1 = DETECT_LO_CURRENT / 1000000; + val->val2 = DETECT_LO_CURRENT % 1000000; + } + + return 0; + default: return -ENOTSUP; } @@ -323,12 +407,12 @@ static int npm1300_charger_attr_set(const struct device *dev, enum sensor_channe const struct npm1300_charger_config *const config = dev->config; int ret; + if (attr != SENSOR_ATTR_CONFIGURATION) { + return -ENOTSUP; + } + switch ((uint32_t)chan) { case SENSOR_CHAN_GAUGE_DESIRED_CHARGING_CURRENT: - if (attr != SENSOR_ATTR_CONFIGURATION) { - return -ENOTSUP; - } - if (val->val1 == 0) { /* Disable charging */ return mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_EN_CLR, @@ -342,6 +426,27 @@ static int npm1300_charger_attr_set(const struct device *dev, enum sensor_channe } return mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_EN_SET, 1U); + case SENSOR_CHAN_CURRENT: + /* Set vbus current limit */ + int32_t current = (val->val1 * 1000000) + val->val2; + uint16_t idx; + + ret = linear_range_group_get_win_index(vbus_current_ranges, + ARRAY_SIZE(vbus_current_ranges), current, + current, &idx); + + if (ret == -EINVAL) { + return ret; + } + + ret = mfd_npm1300_reg_write(config->mfd, VBUS_BASE, VBUS_OFFSET_ILIM, idx); + if (ret != 0) { + return ret; + } + + /* Switch to new current limit, this will be reset automatically on USB removal */ + return mfd_npm1300_reg_write(config->mfd, VBUS_BASE, VBUS_OFFSET_ILIMUPDATE, 1U); + default: return -ENOTSUP; } @@ -357,7 +462,7 @@ int npm1300_charger_init(const struct device *dev) return -ENODEV; } - /* Configure thermistor */ + /* Configure temperature thresholds */ ret = mfd_npm1300_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_NTCR_SEL, config->thermistor_idx + 1U); if (ret != 0) { @@ -369,6 +474,11 @@ int npm1300_charger_init(const struct device *dev) return ret; } + ret = set_dietemp_thresholds(config); + if (ret != 0) { + return ret; + } + /* Configure termination voltages */ ret = linear_range_group_get_win_index(charger_volt_ranges, ARRAY_SIZE(charger_volt_ranges), config->term_microvolt, config->term_microvolt, @@ -458,8 +568,8 @@ int npm1300_charger_init(const struct device *dev) return ret; } - /* Trigger temperature measurement */ - ret = mfd_npm1300_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_TASK_TEMP, 1U); + /* Trigger ntc and die temperature measurements */ + ret = mfd_npm1300_reg_write2(config->mfd, ADC_BASE, ADC_OFFSET_TASK_TEMP, 1U, 1U); if (ret != 0) { return ret; } @@ -523,6 +633,9 @@ static const struct sensor_driver_api npm1300_charger_battery_driver_api = { .iterm_sel = DT_INST_ENUM_IDX(n, term_current_percent), \ .vbatlow_charge_enable = DT_INST_PROP(n, vbatlow_charge_enable), \ .disable_recharge = DT_INST_PROP(n, disable_recharge), \ + .dietemp_thresholds = {DT_INST_PROP_OR(n, dietemp_stop_millidegrees, INT32_MAX), \ + DT_INST_PROP_OR(n, dietemp_resume_millidegrees, \ + INT32_MAX)}, \ .temp_thresholds = {DT_INST_PROP_OR(n, thermistor_cold_millidegrees, INT32_MAX), \ DT_INST_PROP_OR(n, thermistor_cool_millidegrees, INT32_MAX), \ DT_INST_PROP_OR(n, thermistor_warm_millidegrees, INT32_MAX), \ diff --git a/drivers/sensor/ntc_thermistor/Kconfig b/drivers/sensor/ntc_thermistor/Kconfig index 3b73aebd205..8ab04aaf184 100644 --- a/drivers/sensor/ntc_thermistor/Kconfig +++ b/drivers/sensor/ntc_thermistor/Kconfig @@ -6,7 +6,8 @@ config NTC_THERMISTOR bool "NTC Thermistor" default y depends on DT_HAS_NTC_THERMISTOR_GENERIC_ENABLED || \ - DT_HAS_EPCOS_B57861S0103A039_ENABLED + DT_HAS_EPCOS_B57861S0103A039_ENABLED || \ + DT_HAS_MURATA_NCP15WB473_ENABLED select ADC help Enable driver for Zephyr NTC Thermistor. diff --git a/drivers/sensor/ntc_thermistor/ntc_thermistor.c b/drivers/sensor/ntc_thermistor/ntc_thermistor.c index 18c3b291645..4f76ddc30f8 100644 --- a/drivers/sensor/ntc_thermistor/ntc_thermistor.c +++ b/drivers/sensor/ntc_thermistor/ntc_thermistor.c @@ -6,6 +6,8 @@ #include #include +#include +#include #include #include "ntc_thermistor.h" @@ -26,6 +28,7 @@ static int ntc_thermistor_sample_fetch(const struct device *dev, enum sensor_cha { struct ntc_thermistor_data *data = dev->data; const struct ntc_thermistor_config *cfg = dev->config; + enum pm_device_state pm_state; int32_t val_mv; int res; struct adc_sequence sequence = { @@ -35,11 +38,16 @@ static int ntc_thermistor_sample_fetch(const struct device *dev, enum sensor_cha .calibrate = false, }; + (void)pm_device_state_get(dev, &pm_state); + if (pm_state != PM_DEVICE_STATE_ACTIVE) { + return -EIO; + } + k_mutex_lock(&data->mutex, K_FOREVER); adc_sequence_init_dt(&cfg->adc_channel, &sequence); res = adc_read(cfg->adc_channel.dev, &sequence); - if (res) { + if (!res) { val_mv = data->raw; res = adc_raw_to_millivolts_dt(&cfg->adc_channel, &val_mv); data->sample_val = val_mv; @@ -55,13 +63,12 @@ static int ntc_thermistor_channel_get(const struct device *dev, enum sensor_chan { struct ntc_thermistor_data *data = dev->data; const struct ntc_thermistor_config *cfg = dev->config; - uint32_t ohm, max_adc; + uint32_t ohm; int32_t temp; switch (chan) { case SENSOR_CHAN_AMBIENT_TEMP: - max_adc = (1 << (cfg->adc_channel.resolution - 1)) - 1; - ohm = ntc_get_ohm_of_thermistor(&cfg->ntc_cfg, max_adc, data->raw); + ohm = ntc_get_ohm_of_thermistor(&cfg->ntc_cfg, data->sample_val); temp = ntc_get_temp_mc(&cfg->ntc_cfg.type, ohm); val->val1 = temp / 1000; val->val2 = (temp % 1000) * 1000; @@ -93,50 +100,69 @@ static int ntc_thermistor_init(const struct device *dev) return err; } +#ifdef CONFIG_PM_DEVICE_RUNTIME + pm_device_init_suspended(dev); + + err = pm_device_runtime_enable(dev); + if (err) { + LOG_ERR("Failed to enable runtime power management"); + return err; + } +#endif + return 0; } -#define NTC_THERMISTOR_DEFINE(inst, id, comp_table) \ - BUILD_ASSERT(ARRAY_SIZE(comp_table) % 2 == 0, "Compensation table needs to be even size"); \ - \ - static int compare_ohm_##id##inst(const void *key, const void *element); \ - \ +#ifdef CONFIG_PM_DEVICE +static int ntc_thermistor_pm_action(const struct device *dev, enum pm_device_action action) +{ + switch (action) { + case PM_DEVICE_ACTION_TURN_ON: + case PM_DEVICE_ACTION_RESUME: + case PM_DEVICE_ACTION_TURN_OFF: + case PM_DEVICE_ACTION_SUSPEND: + return 0; + default: + return -ENOTSUP; + } +} +#endif + +#define NTC_THERMISTOR_DEFINE0(inst, id, _comp, _n_comp) \ static struct ntc_thermistor_data ntc_thermistor_driver_##id##inst; \ \ static const struct ntc_thermistor_config ntc_thermistor_cfg_##id##inst = { \ .adc_channel = ADC_DT_SPEC_INST_GET(inst), \ .ntc_cfg = \ { \ - .r25_ohm = DT_INST_PROP(inst, r25_ohm), \ .pullup_uv = DT_INST_PROP(inst, pullup_uv), \ .pullup_ohm = DT_INST_PROP(inst, pullup_ohm), \ .pulldown_ohm = DT_INST_PROP(inst, pulldown_ohm), \ .connected_positive = DT_INST_PROP(inst, connected_positive), \ .type = { \ - .comp = (const struct ntc_compensation *)comp_table, \ - .n_comp = ARRAY_SIZE(comp_table), \ - .ohm_cmp = compare_ohm_##id##inst, \ + .comp = _comp, \ + .n_comp = _n_comp, \ }, \ }, \ }; \ \ - static int compare_ohm_##id##inst(const void *key, const void *element) \ - { \ - return ntc_compensation_compare_ohm( \ - &ntc_thermistor_cfg_##id##inst.ntc_cfg.type, key, element); \ - } \ + PM_DEVICE_DT_INST_DEFINE(inst, ntc_thermistor_pm_action); \ \ SENSOR_DEVICE_DT_INST_DEFINE( \ - inst, ntc_thermistor_init, NULL, &ntc_thermistor_driver_##id##inst, \ - &ntc_thermistor_cfg_##id##inst, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \ - &ntc_thermistor_driver_api); + inst, ntc_thermistor_init, PM_DEVICE_DT_INST_GET(inst), \ + &ntc_thermistor_driver_##id##inst, &ntc_thermistor_cfg_##id##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &ntc_thermistor_driver_api); + +#define NTC_THERMISTOR_DEFINE(inst, id, comp) \ + NTC_THERMISTOR_DEFINE0(inst, id, comp, ARRAY_SIZE(comp)) /* ntc-thermistor-generic */ #define DT_DRV_COMPAT ntc_thermistor_generic #define NTC_THERMISTOR_GENERIC_DEFINE(inst) \ static const uint32_t comp_##inst[] = DT_INST_PROP(inst, zephyr_compensation_table); \ - NTC_THERMISTOR_DEFINE(inst, DT_DRV_COMPAT, comp_##inst) + NTC_THERMISTOR_DEFINE0(inst, DT_DRV_COMPAT, (struct ntc_compensation *)comp_##inst, \ + ARRAY_SIZE(comp_##inst) / 2) DT_INST_FOREACH_STATUS_OKAY(NTC_THERMISTOR_GENERIC_DEFINE) @@ -165,3 +191,29 @@ static __unused const struct ntc_compensation comp_epcos_b57861s0103a039[] = { DT_INST_FOREACH_STATUS_OKAY_VARGS(NTC_THERMISTOR_DEFINE, DT_DRV_COMPAT, comp_epcos_b57861s0103a039) + +/* murata,ncp15wb473 */ +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT murata_ncp15wb473 + +static __unused const struct ntc_compensation comp_murata_ncp15wb473[] = { + { -25, 655802 }, + { -15, 360850 }, + { -5, 206463 }, + { 5, 122259 }, + { 15, 74730 }, + { 25, 47000 }, + { 35, 30334 }, + { 45, 20048 }, + { 55, 13539 }, + { 65, 9328 }, + { 75, 6544 }, + { 85, 4674 }, + { 95, 3388 }, + { 105, 2494 }, + { 115, 1860 }, + { 125, 1406 }, +}; + +DT_INST_FOREACH_STATUS_OKAY_VARGS(NTC_THERMISTOR_DEFINE, DT_DRV_COMPAT, + comp_murata_ncp15wb473) diff --git a/drivers/sensor/ntc_thermistor/ntc_thermistor.h b/drivers/sensor/ntc_thermistor/ntc_thermistor.h index c8b0642bfb4..3a202d3bcb3 100644 --- a/drivers/sensor/ntc_thermistor/ntc_thermistor.h +++ b/drivers/sensor/ntc_thermistor/ntc_thermistor.h @@ -17,31 +17,16 @@ struct ntc_compensation { struct ntc_type { const struct ntc_compensation *comp; int n_comp; - int (*ohm_cmp)(const void *key, const void *element); }; struct ntc_config { bool connected_positive; - uint32_t r25_ohm; uint32_t pullup_uv; uint32_t pullup_ohm; uint32_t pulldown_ohm; struct ntc_type type; }; -/** - * @brief Helper comparison function for bsearch for specific - * ntc_type - * - * Ohms are sorted in descending order, perform comparison to find - * interval indexes where key falls between - * - * @param type: Pointer to ntc_type table info - * @param key: Key value bsearch is looking for - * @param element: Array element bsearch is searching - */ -int ntc_compensation_compare_ohm(const struct ntc_type *type, const void *key, const void *element); - /** * @brief Converts ohm to temperature in milli centigrade * @@ -56,11 +41,10 @@ int32_t ntc_get_temp_mc(const struct ntc_type *type, unsigned int ohm); * @brief Calculate the resistance read from NTC Thermistor * * @param cfg: NTC Thermistor configuration - * @param max_adc: Max ADC value - * @param raw_adc: Raw ADC value read + * @sample_mv: Measured voltage in mV * - * @return resistance from raw ADC value + * @return Thermistor resistance */ -uint32_t ntc_get_ohm_of_thermistor(const struct ntc_config *cfg, uint32_t max_adc, int16_t raw_adc); +uint32_t ntc_get_ohm_of_thermistor(const struct ntc_config *cfg, int sample_mv); #endif /* NTC_THERMISTOR_H */ diff --git a/drivers/sensor/ntc_thermistor/ntc_thermistor_calc.c b/drivers/sensor/ntc_thermistor/ntc_thermistor_calc.c index 347156fb335..51e1537a058 100644 --- a/drivers/sensor/ntc_thermistor/ntc_thermistor_calc.c +++ b/drivers/sensor/ntc_thermistor/ntc_thermistor_calc.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include "ntc_thermistor.h" @@ -29,47 +30,6 @@ static int ntc_fixp_linear_interpolate(int x0, int y0, int x1, int y1, int x) return y0 + ((y1 - y0) * (x - x0) / (x1 - x0)); } -/** - * ntc_compensation_compare_ohm() - Helper comparison function for bsearch - * - * Ohms are sorted in descending order, perform comparison to find - * interval indexes where key falls between - * - * @type: Pointer to ntc_type table info - * @key: Key value bsearch is looking for - * @element: Array element bsearch is searching - */ -int ntc_compensation_compare_ohm(const struct ntc_type *type, const void *key, const void *element) -{ - int sgn = 0; - const struct ntc_compensation *ntc_key = key; - const struct ntc_compensation *element_val = element; - int element_idx = element_val - type->comp; - - if (ntc_key->ohm > element_val->ohm) { - if (element_idx == 0) { - sgn = 0; - } else { - sgn = -1; - } - } else if (ntc_key->ohm == element_val->ohm) { - sgn = 0; - } else if (ntc_key->ohm < element_val->ohm) { - if (element_idx == (type->n_comp / 2) - 1) { - sgn = 0; - } else { - if (element_idx != (type->n_comp / 2) - 1 && - ntc_key->ohm > type->comp[element_idx + 1].ohm) { - sgn = 0; - } else { - sgn = 1; - } - } - } - - return sgn; -} - /** * ntc_lookup_comp() - Finds indicies where ohm falls between * @@ -79,35 +39,52 @@ int ntc_compensation_compare_ohm(const struct ntc_type *type, const void *key, c */ static void ntc_lookup_comp(const struct ntc_type *type, unsigned int ohm, int *i_low, int *i_high) { - const struct ntc_compensation *ptr; - struct ntc_compensation search_ohm_key = {.ohm = ohm}; + int low = 0; + int high = type->n_comp - 1; - ptr = bsearch(&search_ohm_key, type->comp, type->n_comp, sizeof(type->comp[0]), - type->ohm_cmp); - if (ptr) { - *i_low = ptr - type->comp; - *i_high = *i_low + 1; - } else { - *i_low = 0; - *i_high = 0; + if (ohm > type->comp[low].ohm) { + high = low; + } else if (ohm < type->comp[high].ohm) { + low = high; + } + + while (high - low > 1) { + int mid = (low + high) / 2; + + if (ohm > type->comp[mid].ohm) { + high = mid; + } else { + low = mid; + } } + + *i_low = low; + *i_high = high; } /** * ntc_get_ohm_of_thermistor() - Calculate the resistance read from NTC Thermistor * * @cfg: NTC Thermistor configuration - * @max_adc: Max ADC value - * @raw_adc: Raw ADC value read + * @sample_mv: Measured voltage in mV */ -uint32_t ntc_get_ohm_of_thermistor(const struct ntc_config *cfg, uint32_t max_adc, int16_t raw_adc) +uint32_t ntc_get_ohm_of_thermistor(const struct ntc_config *cfg, int sample_mv) { + int pullup_mv = cfg->pullup_uv / 1000; uint32_t ohm; + if (sample_mv <= 0) { + return cfg->connected_positive ? INT_MAX : 0; + } + + if (sample_mv >= pullup_mv) { + return cfg->connected_positive ? 0 : INT_MAX; + } + if (cfg->connected_positive) { - ohm = cfg->pulldown_ohm * max_adc / (raw_adc - 1); + ohm = cfg->pulldown_ohm * (pullup_mv - sample_mv) / sample_mv; } else { - ohm = cfg->pullup_ohm * (raw_adc - 1) / max_adc; + ohm = cfg->pullup_ohm * sample_mv / (pullup_mv - sample_mv); } return ohm; diff --git a/drivers/sensor/nuvoton_adc_cmp_npcx/adc_cmp_npcx.c b/drivers/sensor/nuvoton_adc_cmp_npcx/adc_cmp_npcx.c index 1aa694f6b46..cba37069ce9 100644 --- a/drivers/sensor/nuvoton_adc_cmp_npcx/adc_cmp_npcx.c +++ b/drivers/sensor/nuvoton_adc_cmp_npcx/adc_cmp_npcx.c @@ -92,7 +92,7 @@ static int adc_cmp_npcx_init(const struct device *dev) if (config->thr_mv != ADC_CMP_NPCX_UNDEFINED) { param.type = ADC_NPCX_THRESHOLD_PARAM_THVAL; /* Convert from millivolts to ADC raw register value */ - ret = adc_npcx_threshold_mv_to_thrval(config->thr_mv, + ret = adc_npcx_threshold_mv_to_thrval(config->adc, config->thr_mv, ¶m.val); if (ret) { goto init_error; @@ -135,7 +135,7 @@ static int adc_cmp_npcx_set_threshold(const struct device *dev, bool is_upper, param.type = ADC_NPCX_THRESHOLD_PARAM_THVAL; if (is_mv) { - ret = adc_npcx_threshold_mv_to_thrval(value, ¶m.val); + ret = adc_npcx_threshold_mv_to_thrval(config->adc, value, ¶m.val); if (ret) { return ret; } @@ -251,20 +251,23 @@ static const struct sensor_driver_api adc_cmp_npcx_api = { .channel_get = adc_cmp_npcx_channel_get, }; -#define NPCX_ADC_CMP_INIT(inst) \ - static struct adc_cmp_npcx_data adc_cmp_npcx_data_##inst; \ - static const struct adc_cmp_npcx_config adc_cmp_npcx_config_##inst = {\ - .adc = DEVICE_DT_GET(DT_INST_IO_CHANNELS_CTLR(inst)), \ - .chnsel = DT_INST_IO_CHANNELS_INPUT(inst), \ - .th_sel = inst, \ - .thr_mv = DT_INST_PROP_OR(inst, threshold_mv, \ - ADC_CMP_NPCX_UNDEFINED), \ - .comparison = DT_INST_STRING_TOKEN_OR(inst, \ - comparison, ADC_CMP_NPCX_UNDEFINED) \ - }; \ - SENSOR_DEVICE_DT_INST_DEFINE(inst, adc_cmp_npcx_init, NULL, \ - &adc_cmp_npcx_data_##inst, \ - &adc_cmp_npcx_config_##inst, POST_KERNEL, \ - CONFIG_SENSOR_INIT_PRIORITY, \ - &adc_cmp_npcx_api); +#define NPCX_ADC_CMP_INIT(inst) \ + static struct adc_cmp_npcx_data adc_cmp_npcx_data_##inst; \ + static const struct adc_cmp_npcx_config adc_cmp_npcx_config_##inst = { \ + .adc = DEVICE_DT_GET(DT_INST_IO_CHANNELS_CTLR(inst)), \ + .chnsel = DT_INST_IO_CHANNELS_INPUT(inst), \ + .th_sel = DT_INST_STRING_TOKEN_OR(inst, thr_sel, inst), \ + .thr_mv = DT_INST_PROP_OR(inst, threshold_mv, \ + ADC_CMP_NPCX_UNDEFINED), \ + .comparison = DT_INST_STRING_TOKEN_OR(inst, \ + comparison, ADC_CMP_NPCX_UNDEFINED) \ + }; \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, adc_cmp_npcx_init, NULL, \ + &adc_cmp_npcx_data_##inst, \ + &adc_cmp_npcx_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, \ + &adc_cmp_npcx_api); \ + BUILD_ASSERT(DT_INST_STRING_TOKEN_OR(inst, thr_sel, inst) < \ + DT_PROP(DT_INST_IO_CHANNELS_CTLR(inst), threshold_count), \ + "Exceed the number of threshold detectors adc supports"); DT_INST_FOREACH_STATUS_OKAY(NPCX_ADC_CMP_INIT) diff --git a/drivers/sensor/nuvoton_tach_npcx/tach_nuvoton_npcx.c b/drivers/sensor/nuvoton_tach_npcx/tach_nuvoton_npcx.c index c1654afee39..b373d998b64 100644 --- a/drivers/sensor/nuvoton_tach_npcx/tach_nuvoton_npcx.c +++ b/drivers/sensor/nuvoton_tach_npcx/tach_nuvoton_npcx.c @@ -176,7 +176,7 @@ static inline bool tach_npcx_is_captured(const struct device *dev) LOG_DBG("port A is captured %d, port b is captured %d", IS_BIT_SET(inst->TECTRL, NPCX_TECTRL_TAPND), - IS_BIT_SET(inst->TECTRL, NPCX_TECTRL_TAPND)); + IS_BIT_SET(inst->TECTRL, NPCX_TECTRL_TBPND)); /* * In mode 5, the flag TAPND or TBPND indicates a input captured on diff --git a/drivers/sensor/pcnt_esp32/CMakeLists.txt b/drivers/sensor/pcnt_esp32/CMakeLists.txt index 3445c493e55..1dadd4c6cd8 100644 --- a/drivers/sensor/pcnt_esp32/CMakeLists.txt +++ b/drivers/sensor/pcnt_esp32/CMakeLists.txt @@ -2,4 +2,4 @@ zephyr_library() -zephyr_library_sources_ifdef(CONFIG_PCNT_ESP32 pcnt_esp32.c) +zephyr_library_sources(pcnt_esp32.c) diff --git a/drivers/sensor/qdec_mcux/qdec_mcux.c b/drivers/sensor/qdec_mcux/qdec_mcux.c index 467fec4bcb7..ac95a4d0a7f 100644 --- a/drivers/sensor/qdec_mcux/qdec_mcux.c +++ b/drivers/sensor/qdec_mcux/qdec_mcux.c @@ -42,6 +42,7 @@ static enc_decoder_work_mode_t int_to_work_mode(int32_t val) static int qdec_mcux_attr_set(const struct device *dev, enum sensor_channel ch, enum sensor_attribute attr, const struct sensor_value *val) { + const struct qdec_mcux_config *config = dev->config; struct qdec_mcux_data *data = dev->data; if (ch != SENSOR_CHAN_ROTATION) { @@ -59,6 +60,8 @@ static int qdec_mcux_attr_set(const struct device *dev, enum sensor_channel ch, case SENSOR_ATTR_QDEC_ENABLE_SINGLE_PHASE: data->qdec_config.decoderWorkMode = int_to_work_mode(val->val1); + + WRITE_BIT(config->base->CTRL, ENC_CTRL_PH1_SHIFT, val->val1); return 0; default: return -ENOTSUP; diff --git a/drivers/sensor/qdec_nrfx/Kconfig b/drivers/sensor/qdec_nrfx/Kconfig index 245d56ef126..71c3ab1d5b0 100644 --- a/drivers/sensor/qdec_nrfx/Kconfig +++ b/drivers/sensor/qdec_nrfx/Kconfig @@ -7,5 +7,10 @@ config QDEC_NRFX depends on DT_HAS_NORDIC_NRF_QDEC_ENABLED select NRFX_QDEC0 if HAS_HW_NRF_QDEC0 select NRFX_QDEC1 if HAS_HW_NRF_QDEC1 + select NRFX_QDEC20 if HAS_HW_NRF_QDEC20 + select NRFX_QDEC21 if HAS_HW_NRF_QDEC21 + select NRFX_QDEC130 if HAS_HW_NRF_QDEC130 + select NRFX_QDEC131 if HAS_HW_NRF_QDEC131 + select PINCTRL help Enable support for nrfx QDEC driver for nRF MCU series. diff --git a/drivers/sensor/qdec_nrfx/qdec_nrfx.c b/drivers/sensor/qdec_nrfx/qdec_nrfx.c index b11ce70fb9c..10035e0a103 100644 --- a/drivers/sensor/qdec_nrfx/qdec_nrfx.c +++ b/drivers/sensor/qdec_nrfx/qdec_nrfx.c @@ -299,3 +299,19 @@ SENSOR_NRFX_QDEC_DEVICE(0); #ifdef CONFIG_HAS_HW_NRF_QDEC1 SENSOR_NRFX_QDEC_DEVICE(1); #endif + +#ifdef CONFIG_HAS_HW_NRF_QDEC20 +SENSOR_NRFX_QDEC_DEVICE(20); +#endif + +#ifdef CONFIG_HAS_HW_NRF_QDEC21 +SENSOR_NRFX_QDEC_DEVICE(21); +#endif + +#ifdef CONFIG_HAS_HW_NRF_QDEC130 +SENSOR_NRFX_QDEC_DEVICE(130); +#endif + +#ifdef CONFIG_HAS_HW_NRF_QDEC131 +SENSOR_NRFX_QDEC_DEVICE(131); +#endif diff --git a/drivers/sensor/sensor_handlers.c b/drivers/sensor/sensor_handlers.c index cc1bc84f03b..4643646c215 100644 --- a/drivers/sensor/sensor_handlers.c +++ b/drivers/sensor/sensor_handlers.c @@ -5,15 +5,15 @@ */ #include -#include +#include static inline int z_vrfy_sensor_attr_set(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, const struct sensor_value *val) { - Z_OOPS(Z_SYSCALL_DRIVER_SENSOR(dev, attr_set)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(val, sizeof(struct sensor_value))); + K_OOPS(K_SYSCALL_DRIVER_SENSOR(dev, attr_set)); + K_OOPS(K_SYSCALL_MEMORY_READ(val, sizeof(struct sensor_value))); return z_impl_sensor_attr_set((const struct device *)dev, chan, attr, (const struct sensor_value *)val); } @@ -24,8 +24,8 @@ static inline int z_vrfy_sensor_attr_get(const struct device *dev, enum sensor_attribute attr, struct sensor_value *val) { - Z_OOPS(Z_SYSCALL_DRIVER_SENSOR(dev, attr_get)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(val, sizeof(struct sensor_value))); + K_OOPS(K_SYSCALL_DRIVER_SENSOR(dev, attr_get)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(val, sizeof(struct sensor_value))); return z_impl_sensor_attr_get((const struct device *)dev, chan, attr, (struct sensor_value *)val); } @@ -33,7 +33,7 @@ static inline int z_vrfy_sensor_attr_get(const struct device *dev, static inline int z_vrfy_sensor_sample_fetch(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_SENSOR(dev, sample_fetch)); + K_OOPS(K_SYSCALL_DRIVER_SENSOR(dev, sample_fetch)); return z_impl_sensor_sample_fetch((const struct device *)dev); } #include @@ -41,7 +41,7 @@ static inline int z_vrfy_sensor_sample_fetch(const struct device *dev) static inline int z_vrfy_sensor_sample_fetch_chan(const struct device *dev, enum sensor_channel type) { - Z_OOPS(Z_SYSCALL_DRIVER_SENSOR(dev, sample_fetch)); + K_OOPS(K_SYSCALL_DRIVER_SENSOR(dev, sample_fetch)); return z_impl_sensor_sample_fetch_chan((const struct device *)dev, type); } @@ -51,8 +51,8 @@ static inline int z_vrfy_sensor_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) { - Z_OOPS(Z_SYSCALL_DRIVER_SENSOR(dev, channel_get)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(val, sizeof(struct sensor_value))); + K_OOPS(K_SYSCALL_DRIVER_SENSOR(dev, channel_get)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(val, sizeof(struct sensor_value))); return z_impl_sensor_channel_get((const struct device *)dev, chan, (struct sensor_value *)val); } @@ -62,8 +62,8 @@ static inline int z_vrfy_sensor_channel_get(const struct device *dev, static inline int z_vrfy_sensor_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SENSOR)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(decoder, sizeof(struct sensor_decoder_api))); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SENSOR)); + K_OOPS(K_SYSCALL_MEMORY_READ(decoder, sizeof(struct sensor_decoder_api))); return z_impl_sensor_get_decoder(dev, decoder); } #include @@ -73,9 +73,9 @@ static inline int z_vrfy_sensor_reconfigure_read_iodev(struct rtio_iodev *iodev, const enum sensor_channel *channels, size_t num_channels) { - Z_OOPS(Z_SYSCALL_OBJ(iodev, K_OBJ_RTIO_IODEV)); - Z_OOPS(Z_SYSCALL_OBJ(sensor, K_OBJ_DRIVER_SENSOR)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(channels, sizeof(enum sensor_channel) * num_channels)); + K_OOPS(K_SYSCALL_OBJ(iodev, K_OBJ_RTIO_IODEV)); + K_OOPS(K_SYSCALL_OBJ(sensor, K_OBJ_DRIVER_SENSOR)); + K_OOPS(K_SYSCALL_MEMORY_READ(channels, sizeof(enum sensor_channel) * num_channels)); return z_impl_sensor_reconfigure_read_iodev(iodev, sensor, channels, num_channels); } #include diff --git a/drivers/sensor/sensor_shell.c b/drivers/sensor/sensor_shell.c index 459ea0882f7..bfeac4e452f 100644 --- a/drivers/sensor/sensor_shell.c +++ b/drivers/sensor/sensor_shell.c @@ -16,6 +16,8 @@ #include #include +#include "sensor_shell.h" + LOG_MODULE_REGISTER(sensor_shell); #define SENSOR_GET_HELP \ @@ -23,6 +25,11 @@ LOG_MODULE_REGISTER(sensor_shell); "when no channels are provided. Syntax:\n" \ " .. " +#define SENSOR_STREAM_HELP \ + "Start/stop streaming sensor data. Data ready trigger will be used if no triggers " \ + "are provided. Syntax:\n" \ + " on|off incl|drop|nop" + #define SENSOR_ATTR_GET_HELP \ "Get the sensor's channel attribute. Syntax:\n" \ " [ .. " \ @@ -38,7 +45,7 @@ LOG_MODULE_REGISTER(sensor_shell); "Get or set the trigger type on a sensor. Currently only supports `data_ready`.\n" \ " " -const char *sensor_channel_name[SENSOR_CHAN_ALL] = { +const char *sensor_channel_name[SENSOR_CHAN_COMMON_COUNT] = { [SENSOR_CHAN_ACCEL_X] = "accel_x", [SENSOR_CHAN_ACCEL_Y] = "accel_y", [SENSOR_CHAN_ACCEL_Z] = "accel_z", @@ -96,6 +103,7 @@ const char *sensor_channel_name[SENSOR_CHAN_ALL] = { [SENSOR_CHAN_GAUGE_DESIGN_VOLTAGE] = "gauge_design_voltage", [SENSOR_CHAN_GAUGE_DESIRED_VOLTAGE] = "gauge_desired_voltage", [SENSOR_CHAN_GAUGE_DESIRED_CHARGING_CURRENT] = "gauge_desired_charging_current", + [SENSOR_CHAN_ALL] = "all", }; static const char *sensor_attribute_name[SENSOR_ATTR_COMMON_COUNT] = { @@ -114,6 +122,7 @@ static const char *sensor_attribute_name[SENSOR_ATTR_COMMON_COUNT] = { [SENSOR_ATTR_FEATURE_MASK] = "feature_mask", [SENSOR_ATTR_ALERT] = "alert", [SENSOR_ATTR_FF_DUR] = "ff_dur", + [SENSOR_ATTR_BATCH_DURATION] = "batch_dur", }; /* Forward declaration */ @@ -146,12 +155,32 @@ static const struct { TRIGGER_DATA_ENTRY(SENSOR_TRIG_FREEFALL, freefall, NULL), TRIGGER_DATA_ENTRY(SENSOR_TRIG_MOTION, motion, NULL), TRIGGER_DATA_ENTRY(SENSOR_TRIG_STATIONARY, stationary, NULL), + TRIGGER_DATA_ENTRY(SENSOR_TRIG_FIFO_WATERMARK, fifo_wm, NULL), + TRIGGER_DATA_ENTRY(SENSOR_TRIG_FIFO_FULL, fifo_full, NULL), }; +/** + * Lookup the sensor trigger data by name + * + * @param name The name of the trigger + * @return < 0 on error + * @return >= 0 if found + */ +static int sensor_trigger_name_lookup(const char *name) +{ + for (int i = 0; i < ARRAY_SIZE(sensor_trigger_table); ++i) { + if (strcmp(name, sensor_trigger_table[i].name) == 0) { + return i; + } + } + return -1; +} + enum dynamic_command_context { NONE, CTX_GET, CTX_ATTR_GET_SET, + CTX_STREAM_ON_OFF, }; static enum dynamic_command_context current_cmd_ctx = NONE; @@ -163,6 +192,7 @@ K_MUTEX_DEFINE(cmd_get_mutex); static enum sensor_channel iodev_sensor_shell_channels[SENSOR_CHAN_ALL]; static struct sensor_read_config iodev_sensor_shell_read_config = { .sensor = NULL, + .is_streaming = false, .channels = iodev_sensor_shell_channels, .count = 0, .max = ARRAY_SIZE(iodev_sensor_shell_channels), @@ -234,21 +264,18 @@ static int parse_sensor_value(const char *val_str, struct sensor_value *out) return 0; } -struct sensor_shell_processing_context { - const struct device *dev; - const struct shell *sh; -}; - -static void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t buf_len, - void *userdata) +void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t buf_len, void *userdata) { struct sensor_shell_processing_context *ctx = userdata; const struct sensor_decoder_api *decoder; - sensor_frame_iterator_t fit = {0}; - sensor_channel_iterator_t cit = {0}; - uint64_t timestamp; - enum sensor_channel channel; - q31_t q; + uint8_t decoded_buffer[128]; + struct { + uint64_t base_timestamp_ns; + int count; + uint64_t timestamp_delta; + int64_t values[3]; + int8_t shift; + } accumulator_buffer; int rc; ARG_UNUSED(buf_len); @@ -264,51 +291,190 @@ static void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t return; } - rc = decoder->get_timestamp(buf, ×tamp); - if (rc != 0) { - shell_error(ctx->sh, "Failed to get fetch timestamp for '%s'", ctx->dev->name); - return; - } - shell_print(ctx->sh, "Got samples at %" PRIu64 " ns", timestamp); - - while (decoder->decode(buf, &fit, &cit, &channel, &q, 1) > 0) { - int8_t shift; + for (int trigger = 0; decoder->has_trigger != NULL && trigger < SENSOR_TRIG_COMMON_COUNT; + ++trigger) { + if (!decoder->has_trigger(buf, trigger)) { + continue; + } + shell_info(ctx->sh, "Trigger (%d / %s) detected", trigger, + (sensor_trigger_table[trigger].name == NULL + ? "UNKNOWN" + : sensor_trigger_table[trigger].name)); + } + + for (int channel = 0; channel < SENSOR_CHAN_ALL; ++channel) { + uint32_t fit = 0; + size_t base_size; + size_t frame_size; + size_t channel_idx = 0; + uint16_t frame_count; + + if (channel == SENSOR_CHAN_ACCEL_X || channel == SENSOR_CHAN_ACCEL_Y || + channel == SENSOR_CHAN_ACCEL_Z || channel == SENSOR_CHAN_GYRO_X || + channel == SENSOR_CHAN_GYRO_Y || channel == SENSOR_CHAN_GYRO_Z || + channel == SENSOR_CHAN_MAGN_X || channel == SENSOR_CHAN_MAGN_Y || + channel == SENSOR_CHAN_MAGN_Z || channel == SENSOR_CHAN_POS_DY || + channel == SENSOR_CHAN_POS_DZ) { + continue; + } - rc = decoder->get_shift(buf, channel, &shift); + rc = decoder->get_size_info(channel, &base_size, &frame_size); if (rc != 0) { - shell_error(ctx->sh, "Failed to get bitshift for channel %d", channel); + /* Channel not supported, skipping */ continue; } - int64_t scaled_value = (int64_t)q << shift; - bool is_negative = scaled_value < 0; - int numerator; - int denominator; - - scaled_value = llabs(scaled_value); - numerator = (int)FIELD_GET(GENMASK64(31 + shift, 31), scaled_value); - denominator = (int)DIV_ROUND_CLOSEST( - FIELD_GET(GENMASK64(30, 0), scaled_value) * 1000000, - INT32_MAX); - - if (denominator == 1000000) { - numerator++; - denominator = 0; + if (base_size > ARRAY_SIZE(decoded_buffer)) { + shell_error(ctx->sh, + "Channel (%d) requires %zu bytes to decode, but only %zu are " + "available", + channel, base_size, ARRAY_SIZE(decoded_buffer)); + continue; } - if (channel >= ARRAY_SIZE(sensor_channel_name)) { - shell_print(ctx->sh, "channel idx=%d value=%s%d.%06d", channel, - is_negative ? "-" : "", numerator, denominator); - } else { - shell_print(ctx->sh, "channel idx=%d %s value=%s%d.%06d", channel, - sensor_channel_name[channel], is_negative ? "-" : "", numerator, - denominator); + while (decoder->get_frame_count(buf, channel, channel_idx, &frame_count) == 0) { + fit = 0; + memset(&accumulator_buffer, 0, sizeof(accumulator_buffer)); + while (decoder->decode(buf, channel, channel_idx, &fit, 1, decoded_buffer) > + 0) { + + switch (channel) { + case SENSOR_CHAN_ACCEL_XYZ: + case SENSOR_CHAN_GYRO_XYZ: + case SENSOR_CHAN_MAGN_XYZ: + case SENSOR_CHAN_POS_DX: { + struct sensor_three_axis_data *data = + (struct sensor_three_axis_data *)decoded_buffer; + + if (accumulator_buffer.count == 0) { + accumulator_buffer.base_timestamp_ns = + data->header.base_timestamp_ns; + } + accumulator_buffer.count++; + accumulator_buffer.shift = data->shift; + accumulator_buffer.timestamp_delta += + data->readings[0].timestamp_delta; + accumulator_buffer.values[0] += data->readings[0].values[0]; + accumulator_buffer.values[1] += data->readings[0].values[1]; + accumulator_buffer.values[2] += data->readings[0].values[2]; + break; + } + case SENSOR_CHAN_PROX: { + struct sensor_byte_data *data = + (struct sensor_byte_data *)decoded_buffer; + + if (accumulator_buffer.count == 0) { + accumulator_buffer.base_timestamp_ns = + data->header.base_timestamp_ns; + } + accumulator_buffer.count++; + accumulator_buffer.timestamp_delta += + data->readings[0].timestamp_delta; + accumulator_buffer.values[0] += data->readings[0].is_near; + break; + } + default: { + struct sensor_q31_data *data = + (struct sensor_q31_data *)decoded_buffer; + + if (accumulator_buffer.count == 0) { + accumulator_buffer.base_timestamp_ns = + data->header.base_timestamp_ns; + } + accumulator_buffer.count++; + accumulator_buffer.shift = data->shift; + accumulator_buffer.timestamp_delta += + data->readings[0].timestamp_delta; + accumulator_buffer.values[0] += data->readings[0].value; + break; + } + } + } + + /* Print the accumulated value average */ + switch (channel) { + case SENSOR_CHAN_ACCEL_XYZ: + case SENSOR_CHAN_GYRO_XYZ: + case SENSOR_CHAN_MAGN_XYZ: + case SENSOR_CHAN_POS_DX: { + struct sensor_three_axis_data *data = + (struct sensor_three_axis_data *)decoded_buffer; + + data->header.base_timestamp_ns = + accumulator_buffer.base_timestamp_ns; + data->header.reading_count = 1; + data->shift = accumulator_buffer.shift; + data->readings[0].timestamp_delta = + (uint32_t)(accumulator_buffer.timestamp_delta / + accumulator_buffer.count); + data->readings[0].values[0] = (q31_t)(accumulator_buffer.values[0] / + accumulator_buffer.count); + data->readings[0].values[1] = (q31_t)(accumulator_buffer.values[1] / + accumulator_buffer.count); + data->readings[0].values[2] = (q31_t)(accumulator_buffer.values[2] / + accumulator_buffer.count); + shell_info(ctx->sh, + "channel idx=%d %s shift=%d num_samples=%d " + "value=%" PRIsensor_three_axis_data, + channel, sensor_channel_name[channel], + data->shift, accumulator_buffer.count, + PRIsensor_three_axis_data_arg(*data, 0)); + break; + } + case SENSOR_CHAN_PROX: { + struct sensor_byte_data *data = + (struct sensor_byte_data *)decoded_buffer; + + data->header.base_timestamp_ns = + accumulator_buffer.base_timestamp_ns; + data->header.reading_count = 1; + data->readings[0].timestamp_delta = + (uint32_t)(accumulator_buffer.timestamp_delta / + accumulator_buffer.count); + data->readings[0].is_near = + accumulator_buffer.values[0] / accumulator_buffer.count; + + shell_info(ctx->sh, + "channel idx=%d %s num_samples=%d " + "value=%" PRIsensor_byte_data(is_near), + channel, sensor_channel_name[channel], + accumulator_buffer.count, + PRIsensor_byte_data_arg(*data, 0, is_near)); + break; + } + default: { + struct sensor_q31_data *data = + (struct sensor_q31_data *)decoded_buffer; + + data->header.base_timestamp_ns = + accumulator_buffer.base_timestamp_ns; + data->header.reading_count = 1; + data->shift = accumulator_buffer.shift; + data->readings[0].timestamp_delta = + (uint32_t)(accumulator_buffer.timestamp_delta / + accumulator_buffer.count); + data->readings[0].value = (q31_t)(accumulator_buffer.values[0] / + accumulator_buffer.count); + + shell_info(ctx->sh, + "channel idx=%d %s shift=%d num_samples=%d " + "value=%" PRIsensor_q31_data, + channel, + (channel >= ARRAY_SIZE(sensor_channel_name)) + ? "" + : sensor_channel_name[channel], + data->shift, accumulator_buffer.count, + PRIsensor_q31_data_arg(*data, 0)); + } + } + ++channel_idx; } } } static int cmd_get_sensor(const struct shell *sh, size_t argc, char *argv[]) { + static struct sensor_shell_processing_context ctx; const struct device *dev; int count = 0; int err; @@ -356,21 +522,27 @@ static int cmd_get_sensor(const struct shell *sh, size_t argc, char *argv[]) iodev_sensor_shell_read_config.sensor = dev; iodev_sensor_shell_read_config.count = count; - struct sensor_shell_processing_context ctx = { - .dev = dev, - .sh = sh, - }; + ctx.dev = dev; + ctx.sh = sh; err = sensor_read(&iodev_sensor_shell_read, &sensor_read_rtio, &ctx); if (err < 0) { shell_error(sh, "Failed to read sensor: %d", err); } - sensor_processing_with_callback(&sensor_read_rtio, sensor_shell_processing_callback); + if (!IS_ENABLED(CONFIG_SENSOR_SHELL_STREAM)) { + /* + * Streaming enables a thread that polls the RTIO context, so if it's enabled, we + * don't need a blocking read here. + */ + sensor_processing_with_callback(&sensor_read_rtio, + sensor_shell_processing_callback); + } k_mutex_unlock(&cmd_get_mutex); return 0; } + static int cmd_sensor_attr_set(const struct shell *shell_ptr, size_t argc, char *argv[]) { const struct device *dev; @@ -481,9 +653,37 @@ static int cmd_sensor_attr_get(const struct shell *shell_ptr, size_t argc, char } static void channel_name_get(size_t idx, struct shell_static_entry *entry); - SHELL_DYNAMIC_CMD_CREATE(dsub_channel_name, channel_name_get); +static void attribute_name_get(size_t idx, struct shell_static_entry *entry); +SHELL_DYNAMIC_CMD_CREATE(dsub_attribute_name, attribute_name_get); + +static void channel_name_get(size_t idx, struct shell_static_entry *entry) +{ + int cnt = 0; + + entry->syntax = NULL; + entry->handler = NULL; + entry->help = NULL; + if (current_cmd_ctx == CTX_GET) { + entry->subcmd = &dsub_channel_name; + } else if (current_cmd_ctx == CTX_ATTR_GET_SET) { + entry->subcmd = &dsub_attribute_name; + } else { + entry->subcmd = NULL; + } + + for (int i = 0; i < ARRAY_SIZE(sensor_channel_name); i++) { + if (sensor_channel_name[i] != NULL) { + if (cnt == idx) { + entry->syntax = sensor_channel_name[i]; + break; + } + cnt++; + } + } +} + static void attribute_name_get(size_t idx, struct shell_static_entry *entry) { int cnt = 0; @@ -493,7 +693,7 @@ static void attribute_name_get(size_t idx, struct shell_static_entry *entry) entry->help = NULL; entry->subcmd = &dsub_channel_name; - for (int i = 0; i < SENSOR_ATTR_COMMON_COUNT; i++) { + for (int i = 0; i < ARRAY_SIZE(sensor_attribute_name); i++) { if (sensor_attribute_name[i] != NULL) { if (cnt == idx) { entry->syntax = sensor_attribute_name[i]; @@ -503,27 +703,46 @@ static void attribute_name_get(size_t idx, struct shell_static_entry *entry) } } } -SHELL_DYNAMIC_CMD_CREATE(dsub_attribute_name, attribute_name_get); -static void channel_name_get(size_t idx, struct shell_static_entry *entry) +static void trigger_opt_get_for_stream(size_t idx, struct shell_static_entry *entry); +SHELL_DYNAMIC_CMD_CREATE(dsub_trigger_opt_get_for_stream, trigger_opt_get_for_stream); + +static void trigger_opt_get_for_stream(size_t idx, struct shell_static_entry *entry) +{ + entry->syntax = NULL; + entry->handler = NULL; + entry->help = NULL; + entry->subcmd = NULL; + + switch (idx) { + case SENSOR_STREAM_DATA_INCLUDE: + entry->syntax = "incl"; + break; + case SENSOR_STREAM_DATA_DROP: + entry->syntax = "drop"; + break; + case SENSOR_STREAM_DATA_NOP: + entry->syntax = "nop"; + break; + } +} + +static void trigger_name_get_for_stream(size_t idx, struct shell_static_entry *entry); +SHELL_DYNAMIC_CMD_CREATE(dsub_trigger_name_for_stream, trigger_name_get_for_stream); + +static void trigger_name_get_for_stream(size_t idx, struct shell_static_entry *entry) { int cnt = 0; entry->syntax = NULL; entry->handler = NULL; entry->help = NULL; - if (current_cmd_ctx == CTX_GET) { - entry->subcmd = &dsub_channel_name; - } else if (current_cmd_ctx == CTX_ATTR_GET_SET) { - entry->subcmd = &dsub_attribute_name; - } else { - entry->subcmd = NULL; - } + entry->subcmd = &dsub_trigger_opt_get_for_stream; - for (int i = 0; i < SENSOR_CHAN_ALL; i++) { - if (sensor_channel_name[i] != NULL) { + for (int i = 0; i < ARRAY_SIZE(sensor_trigger_table); i++) { + if (sensor_trigger_table[i].name != NULL) { if (cnt == idx) { - entry->syntax = sensor_channel_name[i]; + entry->syntax = sensor_trigger_table[i].name; break; } cnt++; @@ -531,6 +750,22 @@ static void channel_name_get(size_t idx, struct shell_static_entry *entry) } } +static void stream_on_off(size_t idx, struct shell_static_entry *entry) +{ + entry->syntax = NULL; + entry->handler = NULL; + entry->help = NULL; + + if (idx == 0) { + entry->syntax = "on"; + entry->subcmd = &dsub_trigger_name_for_stream; + } else if (idx == 1) { + entry->syntax = "off"; + entry->subcmd = NULL; + } +} +SHELL_DYNAMIC_CMD_CREATE(dsub_stream_on_off, stream_on_off); + static void device_name_get(size_t idx, struct shell_static_entry *entry); SHELL_DYNAMIC_CMD_CREATE(dsub_device_name, device_name_get); @@ -567,7 +802,7 @@ static void trigger_name_get(size_t idx, struct shell_static_entry *entry) entry->help = NULL; entry->subcmd = NULL; - for (int i = 0; i < SENSOR_TRIG_COMMON_COUNT; i++) { + for (int i = 0; i < ARRAY_SIZE(sensor_trigger_table); i++) { if (sensor_trigger_table[i].name != NULL) { if (cnt == idx) { entry->syntax = sensor_trigger_table[i].name; @@ -613,6 +848,18 @@ static void device_name_get_for_trigger(size_t idx, struct shell_static_entry *e SHELL_DYNAMIC_CMD_CREATE(dsub_trigger, device_name_get_for_trigger); +static void device_name_get_for_stream(size_t idx, struct shell_static_entry *entry) +{ + const struct device *dev = shell_device_lookup(idx, NULL); + + current_cmd_ctx = CTX_STREAM_ON_OFF; + entry->syntax = (dev != NULL) ? dev->name : NULL; + entry->handler = NULL; + entry->help = NULL; + entry->subcmd = &dsub_stream_on_off; +} +SHELL_DYNAMIC_CMD_CREATE(dsub_device_name_for_stream, device_name_get_for_stream); + static int cmd_get_sensor_info(const struct shell *sh, size_t argc, char **argv) { ARG_UNUSED(argc); @@ -621,8 +868,7 @@ static int cmd_get_sensor_info(const struct shell *sh, size_t argc, char **argv) #ifdef CONFIG_SENSOR_INFO const char *null_str = "(null)"; - STRUCT_SECTION_FOREACH(sensor_info, sensor) - { + STRUCT_SECTION_FOREACH(sensor_info, sensor) { shell_print(sh, "device name: %s, vendor: %s, model: %s, " "friendly name: %s", @@ -703,7 +949,7 @@ static void data_ready_trigger_handler(const struct device *sensor, static int cmd_trig_sensor(const struct shell *sh, size_t argc, char **argv) { const struct device *dev; - enum sensor_trigger_type trigger; + int trigger; int err; if (argc < 4) { @@ -719,12 +965,8 @@ static int cmd_trig_sensor(const struct shell *sh, size_t argc, char **argv) } /* Map the trigger string to an enum value */ - for (trigger = 0; trigger < ARRAY_SIZE(sensor_trigger_table); trigger++) { - if (strcmp(argv[3], sensor_trigger_table[trigger].name) == 0) { - break; - } - } - if (trigger >= SENSOR_TRIG_COMMON_COUNT || sensor_trigger_table[trigger].handler == NULL) { + trigger = sensor_trigger_name_lookup(argv[3]); + if (trigger < 0 || sensor_trigger_table[trigger].handler == NULL) { shell_error(sh, "Unsupported trigger type (%s)", argv[3]); return -ENOTSUP; } @@ -757,6 +999,8 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_sensor, cmd_sensor_attr_set, 2, 255), SHELL_CMD_ARG(attr_get, &dsub_device_name_for_attr, SENSOR_ATTR_GET_HELP, cmd_sensor_attr_get, 2, 255), + SHELL_COND_CMD(CONFIG_SENSOR_SHELL_STREAM, stream, &dsub_device_name_for_stream, + SENSOR_STREAM_HELP, cmd_sensor_stream), SHELL_COND_CMD(CONFIG_SENSOR_INFO, info, NULL, SENSOR_INFO_HELP, cmd_get_sensor_info), SHELL_CMD_ARG(trig, &dsub_trigger, SENSOR_TRIG_HELP, cmd_trig_sensor, diff --git a/drivers/sensor/sensor_shell.h b/drivers/sensor/sensor_shell.h new file mode 100644 index 00000000000..cfc8b2489db --- /dev/null +++ b/drivers/sensor/sensor_shell.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_SENSOR_SHELL_H +#define ZEPHYR_DRIVERS_SENSOR_SENSOR_SHELL_H + +#include +#include +#include +#include + +struct sensor_shell_processing_context { + const struct device *dev; + const struct shell *sh; +}; + +extern struct rtio sensor_read_rtio; + +int cmd_sensor_stream(const struct shell *shell_ptr, size_t argc, char *argv[]); + +void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t buf_len, void *userdata); + +#endif /* ZEPHYR_DRIVERS_SENSOR_SENSOR_SHELL_H */ diff --git a/drivers/sensor/sensor_shell_stream.c b/drivers/sensor/sensor_shell_stream.c new file mode 100644 index 00000000000..ab3b835aa10 --- /dev/null +++ b/drivers/sensor/sensor_shell_stream.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include + +#include "sensor_shell.h" + +/* Create a single common config for streaming */ +static struct sensor_stream_trigger iodev_sensor_shell_trigger; +static struct sensor_read_config iodev_sensor_shell_stream_config = { + .sensor = NULL, + .is_streaming = true, + .triggers = &iodev_sensor_shell_trigger, + .count = 0, + .max = 1, +}; +RTIO_IODEV_DEFINE(iodev_sensor_shell_stream, &__sensor_iodev_api, + &iodev_sensor_shell_stream_config); + +static void sensor_shell_processing_entry_point(void *a, void *b, void *c) +{ + ARG_UNUSED(a); + ARG_UNUSED(b); + ARG_UNUSED(c); + + while (true) { + sensor_processing_with_callback(&sensor_read_rtio, + sensor_shell_processing_callback); + } +} +K_THREAD_DEFINE(sensor_shell_processing_tid, CONFIG_SENSOR_SHELL_THREAD_STACK_SIZE, + sensor_shell_processing_entry_point, NULL, NULL, NULL, 0, 0, 0); + +int cmd_sensor_stream(const struct shell *shell_ptr, size_t argc, char *argv[]) +{ + static struct rtio_sqe *current_streaming_handle; + static struct sensor_shell_processing_context ctx; + const struct device *dev = device_get_binding(argv[1]); + + if (argc != 5 && argc != 3) { + shell_error(shell_ptr, "Wrong number of arguments (%zu)", argc); + return -EINVAL; + } + + if (dev == NULL) { + shell_error(shell_ptr, "Device unknown (%s)", argv[1]); + return -ENODEV; + } + + if (current_streaming_handle != NULL) { + shell_info(shell_ptr, "Disabling existing stream"); + rtio_sqe_cancel(current_streaming_handle); + } + + if (strcmp("off", argv[2]) == 0) { + return 0; + } + + if (strcmp("on", argv[2]) != 0) { + shell_error(shell_ptr, "Unknown streaming operation (%s)", argv[2]); + return -EINVAL; + } + + if (strcmp("double_tap", argv[3]) == 0) { + iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_DOUBLE_TAP; + } else if (strcmp("data_ready", argv[3]) == 0) { + iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_DATA_READY; + } else if (strcmp("delta", argv[3]) == 0) { + iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_DELTA; + } else if (strcmp("freefall", argv[3]) == 0) { + iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_FREEFALL; + } else if (strcmp("motion", argv[3]) == 0) { + iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_MOTION; + } else if (strcmp("near_far", argv[3]) == 0) { + iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_NEAR_FAR; + } else if (strcmp("stationary", argv[3]) == 0) { + iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_STATIONARY; + } else if (strcmp("threshold", argv[3]) == 0) { + iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_THRESHOLD; + } else if (strcmp("fifo_wm", argv[3]) == 0) { + iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_FIFO_WATERMARK; + } else if (strcmp("fifo_full", argv[3]) == 0) { + iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_FIFO_FULL; + } else if (strcmp("tap", argv[3]) == 0) { + iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_TAP; + } else { + shell_error(shell_ptr, "Invalid trigger (%s)", argv[3]); + return -EINVAL; + } + + if (strcmp("incl", argv[4]) == 0) { + iodev_sensor_shell_trigger.opt = SENSOR_STREAM_DATA_INCLUDE; + } else if (strcmp("drop", argv[4]) == 0) { + iodev_sensor_shell_trigger.opt = SENSOR_STREAM_DATA_DROP; + } else if (strcmp("nop", argv[4]) == 0) { + iodev_sensor_shell_trigger.opt = SENSOR_STREAM_DATA_NOP; + } else { + shell_error(shell_ptr, "Unknown trigger op (%s)", argv[4]); + return -EINVAL; + } + + shell_print(shell_ptr, "Enabling stream..."); + iodev_sensor_shell_stream_config.sensor = dev; + + iodev_sensor_shell_stream_config.count = 1; + + ctx.dev = dev; + ctx.sh = shell_ptr; + + int rc = sensor_stream(&iodev_sensor_shell_stream, &sensor_read_rtio, &ctx, + ¤t_streaming_handle); + + if (rc != 0) { + shell_error(shell_ptr, "Failed to start stream"); + } + return rc; +} diff --git a/drivers/sensor/sht3xd/sht3xd_trigger.c b/drivers/sensor/sht3xd/sht3xd_trigger.c index 03b2bffaea4..b6b398c5166 100644 --- a/drivers/sensor/sht3xd/sht3xd_trigger.c +++ b/drivers/sensor/sht3xd/sht3xd_trigger.c @@ -162,8 +162,13 @@ static void sht3xd_thread_cb(const struct device *dev) } #ifdef CONFIG_SHT3XD_TRIGGER_OWN_THREAD -static void sht3xd_thread(struct sht3xd_data *data) +static void sht3xd_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct sht3xd_data *data = p1; + while (1) { k_sem_take(&data->gpio_sem, K_FOREVER); sht3xd_thread_cb(data->dev); @@ -238,7 +243,7 @@ int sht3xd_init_interrupt(const struct device *dev) k_thread_create(&data->thread, data->thread_stack, CONFIG_SHT3XD_THREAD_STACK_SIZE, - (k_thread_entry_t)sht3xd_thread, data, + sht3xd_thread, data, NULL, NULL, K_PRIO_COOP(CONFIG_SHT3XD_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_SHT3XD_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/sm351lt/sm351lt.c b/drivers/sensor/sm351lt/sm351lt.c index 0663079ca89..7ec83253152 100644 --- a/drivers/sensor/sm351lt/sm351lt.c +++ b/drivers/sensor/sm351lt/sm351lt.c @@ -212,7 +212,7 @@ static int sm351lt_init(const struct device *dev) k_thread_create(&data->thread, data->thread_stack, CONFIG_SM351LT_THREAD_STACK_SIZE, - (k_thread_entry_t)sm351lt_thread, data, NULL, + sm351lt_thread, data, NULL, NULL, K_PRIO_COOP(CONFIG_SM351LT_THREAD_PRIORITY), 0, K_NO_WAIT); diff --git a/drivers/sensor/sm351lt/sm351lt.h b/drivers/sensor/sm351lt/sm351lt.h index 78b5aa01725..6e1edf67931 100644 --- a/drivers/sensor/sm351lt/sm351lt.h +++ b/drivers/sensor/sm351lt/sm351lt.h @@ -30,7 +30,7 @@ struct sm351lt_data { const struct sensor_trigger *changed_trigger; #if defined(CONFIG_SM351LT_TRIGGER_OWN_THREAD) - K_THREAD_STACK_MEMBER(thread_stack, CONFIG_SM351LT_THREAD_STACK_SIZE); + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_SM351LT_THREAD_STACK_SIZE); struct k_thread thread; struct k_sem gpio_sem; #elif defined(CONFIG_SM351LT_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/stm32_temp/stm32_temp.c b/drivers/sensor/stm32_temp/stm32_temp.c index e432461fee5..7ad72490e91 100644 --- a/drivers/sensor/stm32_temp/stm32_temp.c +++ b/drivers/sensor/stm32_temp/stm32_temp.c @@ -10,6 +10,7 @@ #include #include #include +#include #if defined(CONFIG_SOC_SERIES_STM32H5X) #include #endif /* CONFIG_SOC_SERIES_STM32H5X */ @@ -35,6 +36,7 @@ LOG_MODULE_REGISTER(stm32_temp, CONFIG_SENSOR_LOG_LEVEL); struct stm32_temp_data { const struct device *adc; const struct adc_channel_cfg adc_cfg; + ADC_TypeDef *adc_base; struct adc_sequence adc_seq; struct k_mutex mutex; int16_t sample_buffer; @@ -78,6 +80,10 @@ static int stm32_temp_sample_fetch(const struct device *dev, enum sensor_channel goto unlock; } + LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(data->adc_base), + LL_ADC_PATH_INTERNAL_TEMPSENSOR); + k_usleep(LL_ADC_DELAY_TEMPSENSOR_STAB_US); + rc = adc_read(data->adc, sp); if (rc == 0) { data->raw = data->sample_buffer; @@ -168,6 +174,7 @@ static int stm32_temp_init(const struct device *dev) static struct stm32_temp_data stm32_temp_dev_data = { .adc = DEVICE_DT_GET(DT_INST_IO_CHANNELS_CTLR(0)), + .adc_base = (ADC_TypeDef *)DT_REG_ADDR(DT_INST_IO_CHANNELS_CTLR(0)), .adc_cfg = { .gain = ADC_GAIN_1, .reference = ADC_REF_INTERNAL, diff --git a/drivers/sensor/stm32_vbat/stm32_vbat.c b/drivers/sensor/stm32_vbat/stm32_vbat.c index 489d4c0ae35..10c035baacf 100644 --- a/drivers/sensor/stm32_vbat/stm32_vbat.c +++ b/drivers/sensor/stm32_vbat/stm32_vbat.c @@ -9,6 +9,7 @@ #include #include #include +#include LOG_MODULE_REGISTER(stm32_vbat, CONFIG_SENSOR_LOG_LEVEL); @@ -21,6 +22,7 @@ LOG_MODULE_REGISTER(stm32_vbat, CONFIG_SENSOR_LOG_LEVEL); struct stm32_vbat_data { const struct device *adc; const struct adc_channel_cfg adc_cfg; + ADC_TypeDef *adc_base; struct adc_sequence adc_seq; struct k_mutex mutex; int16_t sample_buffer; @@ -50,6 +52,9 @@ static int stm32_vbat_sample_fetch(const struct device *dev, enum sensor_channel goto unlock; } + LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(data->adc_base), + LL_ADC_PATH_INTERNAL_VBAT); + rc = adc_read(data->adc, sp); if (rc == 0) { data->raw = data->sample_buffer; @@ -110,6 +115,7 @@ static int stm32_vbat_init(const struct device *dev) #define STM32_VBAT_DEFINE(inst) \ static struct stm32_vbat_data stm32_vbat_dev_data_##inst = { \ .adc = DEVICE_DT_GET(DT_INST_IO_CHANNELS_CTLR(inst)), \ + .adc_base = (ADC_TypeDef *)DT_REG_ADDR(DT_INST_IO_CHANNELS_CTLR(0)), \ .adc_cfg = { \ .gain = ADC_GAIN_1, \ .reference = ADC_REF_INTERNAL, \ diff --git a/drivers/sensor/stm32_vref/Kconfig b/drivers/sensor/stm32_vref/Kconfig index 375c0b4bc3d..192cd3fd922 100644 --- a/drivers/sensor/stm32_vref/Kconfig +++ b/drivers/sensor/stm32_vref/Kconfig @@ -7,6 +7,6 @@ config STM32_VREF bool "STM32 VREF Sensor" default y depends on DT_HAS_ST_STM32_VREF_ENABLED - select ADC + depends on ADC && (SOC_FAMILY_STM32 && !SOC_SERIES_STM32F1X) help Enable driver for STM32 Vref sensor. diff --git a/drivers/sensor/stm32_vref/stm32_vref.c b/drivers/sensor/stm32_vref/stm32_vref.c index 4e49e17e9e8..4dcb8324076 100644 --- a/drivers/sensor/stm32_vref/stm32_vref.c +++ b/drivers/sensor/stm32_vref/stm32_vref.c @@ -11,6 +11,7 @@ #include #include #include +#include #if defined(CONFIG_SOC_SERIES_STM32H5X) #include #endif /* CONFIG_SOC_SERIES_STM32H5X */ @@ -20,6 +21,7 @@ LOG_MODULE_REGISTER(stm32_vref, CONFIG_SENSOR_LOG_LEVEL); struct stm32_vref_data { const struct device *adc; const struct adc_channel_cfg adc_cfg; + ADC_TypeDef *adc_base; struct adc_sequence adc_seq; struct k_mutex mutex; int16_t sample_buffer; @@ -49,6 +51,12 @@ static int stm32_vref_sample_fetch(const struct device *dev, enum sensor_channel goto unlock; } + LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(data->adc_base), + LL_ADC_PATH_INTERNAL_VREFINT); +#ifdef LL_ADC_DELAY_VREFINT_STAB_US + k_usleep(LL_ADC_DELAY_VREFINT_STAB_US); +#endif + rc = adc_read(data->adc, sp); if (rc == 0) { data->raw = data->sample_buffer; @@ -135,6 +143,7 @@ static int stm32_vref_init(const struct device *dev) static struct stm32_vref_data stm32_vref_dev_data = { .adc = DEVICE_DT_GET(DT_INST_IO_CHANNELS_CTLR(0)), + .adc_base = (ADC_TypeDef *)DT_REG_ADDR(DT_INST_IO_CHANNELS_CTLR(0)), .adc_cfg = {.gain = ADC_GAIN_1, .reference = ADC_REF_INTERNAL, .acquisition_time = ADC_ACQ_TIME_MAX, diff --git a/drivers/sensor/stts751/stts751_trigger.c b/drivers/sensor/stts751/stts751_trigger.c index ec463370c56..5d827d4f1b1 100644 --- a/drivers/sensor/stts751/stts751_trigger.c +++ b/drivers/sensor/stts751/stts751_trigger.c @@ -96,8 +96,13 @@ static void stts751_gpio_callback(const struct device *dev, } #ifdef CONFIG_STTS751_TRIGGER_OWN_THREAD -static void stts751_thread(struct stts751_data *stts751) +static void stts751_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct stts751_data *stts751 = p1; + while (1) { k_sem_take(&stts751->gpio_sem, K_FOREVER); stts751_handle_interrupt(stts751->dev); @@ -131,7 +136,7 @@ int stts751_init_interrupt(const struct device *dev) k_thread_create(&stts751->thread, stts751->thread_stack, CONFIG_STTS751_THREAD_STACK_SIZE, - (k_thread_entry_t)stts751_thread, stts751, + stts751_thread, stts751, NULL, NULL, K_PRIO_COOP(CONFIG_STTS751_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_STTS751_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/sx9500/sx9500_trigger.c b/drivers/sensor/sx9500/sx9500_trigger.c index 127291b2a91..146e6753ef9 100644 --- a/drivers/sensor/sx9500/sx9500_trigger.c +++ b/drivers/sensor/sx9500/sx9500_trigger.c @@ -98,8 +98,13 @@ static void sx9500_gpio_cb(const struct device *port, k_sem_give(&data->sem); } -static void sx9500_thread_main(struct sx9500_data *data) +static void sx9500_thread_main(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct sx9500_data *data = p1; + while (1) { k_sem_take(&data->sem, K_FOREVER); sx9500_gpio_thread_cb(data->dev); @@ -170,7 +175,7 @@ int sx9500_setup_interrupt(const struct device *dev) #ifdef CONFIG_SX9500_TRIGGER_OWN_THREAD k_thread_create(&sx9500_thread, sx9500_thread_stack, CONFIG_SX9500_THREAD_STACK_SIZE, - (k_thread_entry_t)sx9500_thread_main, data, 0, NULL, + sx9500_thread_main, data, 0, NULL, K_PRIO_COOP(CONFIG_SX9500_THREAD_PRIORITY), 0, K_NO_WAIT); #endif diff --git a/drivers/sensor/tcn75a/tcn75a_trigger.c b/drivers/sensor/tcn75a/tcn75a_trigger.c index 90f6932a9e0..12635eb00c2 100644 --- a/drivers/sensor/tcn75a/tcn75a_trigger.c +++ b/drivers/sensor/tcn75a/tcn75a_trigger.c @@ -149,8 +149,13 @@ static void tcn75a_gpio_callback(const struct device *dev, struct gpio_callback } #ifdef CONFIG_TCN75A_TRIGGER_OWN_THREAD -static void tcn75a_thread_main(struct tcn75a_data *data) +static void tcn75a_thread_main(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct tcn75a_data *data = p1; + while (true) { k_sem_take(&data->trig_sem, K_FOREVER); tcn75a_handle_int(data->dev); @@ -193,7 +198,7 @@ int tcn75a_trigger_init(const struct device *dev) #if defined(CONFIG_TCN75A_TRIGGER_OWN_THREAD) k_sem_init(&data->trig_sem, 0, K_SEM_MAX_LIMIT); k_thread_create(&data->thread, data->thread_stack, CONFIG_TCN75A_THREAD_STACK_SIZE, - (k_thread_entry_t)tcn75a_thread_main, data, NULL, NULL, + tcn75a_thread_main, data, NULL, NULL, K_PRIO_COOP(CONFIG_TCN75A_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_TCN75A_TRIGGER_GLOBAL_THREAD) data->work.handler = tcn75a_work_handler; diff --git a/drivers/sensor/tmag5170/CMakeLists.txt b/drivers/sensor/tmag5170/CMakeLists.txt new file mode 100644 index 00000000000..f196c2019a2 --- /dev/null +++ b/drivers/sensor/tmag5170/CMakeLists.txt @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(tmag5170.c) +zephyr_library_sources_ifdef(CONFIG_TMAG5170_TRIGGER tmag5170_trigger.c) diff --git a/drivers/sensor/tmag5170/Kconfig b/drivers/sensor/tmag5170/Kconfig new file mode 100644 index 00000000000..592b2382448 --- /dev/null +++ b/drivers/sensor/tmag5170/Kconfig @@ -0,0 +1,69 @@ +# Texas Instruments TMAG5170 high-precision, linear 3D Hall-effect sensor with SPI bus interface + +# Copyright (c) 2023 Michal Morsisko +# SPDX-License-Identifier: Apache-2.0 + +menuconfig TMAG5170 + bool "TMAG5170 SPI Hall-effect sensor driver" + default y + depends on DT_HAS_TI_TMAG5170_ENABLED + select SPI + help + Enable driver for TMAG5170 Hall-effect sensor driver + +if TMAG5170 + +choice TMAG5170_TRIGGER_MODE + prompt "Trigger mode" + help + Specify the type of triggering to be used by the driver. + +config TMAG5170_TRIGGER_NONE + bool "No trigger" + +config TMAG5170_TRIGGER_GLOBAL_THREAD + bool "Use global thread" + depends on GPIO + select TMAG5170_TRIGGER + +config TMAG5170_TRIGGER_OWN_THREAD + bool "Use own thread" + depends on GPIO + select TMAG5170_TRIGGER + +config TMAG5170_TRIGGER_DIRECT + bool "Process trigger within interrupt context" + depends on GPIO + select TMAG5170_TRIGGER + +endchoice + +config TMAG5170_CRC + bool "Use CRC error detection" + default y + select CRC + help + Verify CRC of RX data and append CRC to TX data + +config TMAG5170_TRIGGER + bool + +if TMAG5170_TRIGGER + +config TMAG5170_THREAD_PRIORITY + int "Thread priority" + depends on TMAG5170_TRIGGER_OWN_THREAD + default 10 + help + Priority of thread used by the driver to handle interrupts. + +config TMAG5170_THREAD_STACK_SIZE + int "Thread stack size" + depends on TMAG5170_TRIGGER_OWN_THREAD + default 1024 + help + Stack size of thread used by the driver to handle interrupts. + +endif # TMAG5170_TRIGGER + +endif # TMAG5170 diff --git a/drivers/sensor/tmag5170/tmag5170.c b/drivers/sensor/tmag5170/tmag5170.c new file mode 100644 index 00000000000..2e34f52dfab --- /dev/null +++ b/drivers/sensor/tmag5170/tmag5170.c @@ -0,0 +1,586 @@ +/* + * Copyright (c) 2023 Michal Morsisko + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ti_tmag5170 + +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_TMAG5170_CRC) +#include +#endif + +#include "tmag5170.h" + +#define TMAG5170_REG_DEVICE_CONFIG 0x0U +#define TMAG5170_REG_SENSOR_CONFIG 0x1U +#define TMAG5170_REG_SYSTEM_CONFIG 0x2U +#define TMAG5170_REG_ALERT_CONFIG 0x3U +#define TMAG5170_REG_X_THRX_CONFIG 0x4U +#define TMAG5170_REG_Y_THRX_CONFIG 0x5U +#define TMAG5170_REG_Z_THRX_CONFIG 0x6U +#define TMAG5170_REG_T_THRX_CONFIG 0x7U +#define TMAG5170_REG_CONV_STATUS 0x8U +#define TMAG5170_REG_X_CH_RESULT 0x9U +#define TMAG5170_REG_Y_CH_RESULT 0xAU +#define TMAG5170_REG_Z_CH_RESULT 0xBU +#define TMAG5170_REG_TEMP_RESULT 0xCU +#define TMAG5170_REG_AFE_STATUS 0xDU +#define TMAG5170_REG_SYS_STATUS 0xEU +#define TMAG5170_REG_TEST_CONFIG 0xFU +#define TMAG5170_REG_OSC_MONITOR 0x10U +#define TMAG5170_REG_MAG_GAIN_CONFIG 0x11U +#define TMAG5170_REG_MAG_OFFSET_CONFIG 0x12U +#define TMAG5170_REG_ANGLE_RESULT 0x13U +#define TMAG5170_REG_MAGNITUDE_RESULT 0x14U + +#define TMAG5170_CONV_AVG_POS 12U +#define TMAG5170_CONV_AVG_MASK (BIT_MASK(3U) << TMAG5170_CONV_AVG_POS) +#define TMAG5170_CONV_AVG_SET(value) (((value) << TMAG5170_CONV_AVG_POS) &\ + TMAG5170_CONV_AVG_MASK) + +#define TMAG5170_MAG_TEMPCO_POS 8U +#define TMAG5170_MAG_TEMPCO_MASK (BIT_MASK(2U) << TMAG5170_MAG_TEMPCO_POS) +#define TMAG5170_MAG_TEMPCO_SET(value) (((value) << TMAG5170_MAG_TEMPCO_POS) &\ + TMAG5170_MAG_TEMPCO_MASK) + +#define TMAG5170_OPERATING_MODE_POS 4U +#define TMAG5170_OPERATING_MODE_MASK (BIT_MASK(3U) << TMAG5170_OPERATING_MODE_POS) +#define TMAG5170_OPERATING_MODE_SET(value) (((value) << TMAG5170_OPERATING_MODE_POS) &\ + TMAG5170_OPERATING_MODE_MASK) + +#define TMAG5170_T_CH_EN_POS 3U +#define TMAG5170_T_CH_EN_MASK (BIT_MASK(1U) << TMAG5170_T_CH_EN_POS) +#define TMAG5170_T_CH_EN_SET(value) (((value) << TMAG5170_T_CH_EN_POS) &\ + TMAG5170_T_CH_EN_MASK) + +#define TMAG5170_T_RATE_POS 2U +#define TMAG5170_T_RATE_MASK (BIT_MASK(1U) << TMAG5170_T_RATE_POS) +#define TMAG5170_T_RATE_SET(value) (((value) << TMAG5170_T_RATE_POS) &\ + TMAG5170_T_RATE_MASK) + +#define TMAG5170_ANGLE_EN_POS 14U +#define TMAG5170_ANGLE_EN_MASK (BIT_MASK(2U) << TMAG5170_ANGLE_EN_POS) +#define TMAG5170_ANGLE_EN_SET(value) (((value) << TMAG5170_ANGLE_EN_POS) &\ + TMAG5170_ANGLE_EN_MASK) + +#define TMAG5170_SLEEPTIME_POS 10U +#define TMAG5170_SLEEPTIME_MASK (BIT_MASK(4U) << TMAG5170_SLEEPTIME_POS) +#define TMAG5170_SLEEPTIME_SET(value) (((value) << TMAG5170_SLEEPTIME_POS) &\ + TMAG5170_SLEEPTIME_MASK) + +#define TMAG5170_MAG_CH_EN_POS 6U +#define TMAG5170_MAG_CH_EN_MASK (BIT_MASK(4U) << TMAG5170_MAG_CH_EN_POS) +#define TMAG5170_MAG_CH_EN_SET(value) (((value) << TMAG5170_MAG_CH_EN_POS) &\ + TMAG5170_MAG_CH_EN_MASK) + +#define TMAG5170_Z_RANGE_POS 4U +#define TMAG5170_Z_RANGE_MASK (BIT_MASK(2U) << TMAG5170_Z_RANGE_POS) +#define TMAG5170_Z_RANGE_SET(value) (((value) << TMAG5170_Z_RANGE_POS) &\ + TMAG5170_Z_RANGE_MASK) + +#define TMAG5170_Y_RANGE_POS 2U +#define TMAG5170_Y_RANGE_MASK (BIT_MASK(2U) << TMAG5170_Y_RANGE_POS) +#define TMAG5170_Y_RANGE_SET(value) (((value) << TMAG5170_Y_RANGE_POS) &\ + TMAG5170_Y_RANGE_MASK) + +#define TMAG5170_X_RANGE_POS 0U +#define TMAG5170_X_RANGE_MASK (BIT_MASK(2U) << TMAG5170_X_RANGE_POS) +#define TMAG5170_X_RANGE_SET(value) (((value) << TMAG5170_X_RANGE_POS) &\ + TMAG5170_X_RANGE_MASK) + +#define TMAG5170_RSLT_ALRT_POS 8U +#define TMAG5170_RSLT_ALRT_MASK (BIT_MASK(1U) << TMAG5170_RSLT_ALRT_POS) +#define TMAG5170_RSLT_ALRT_SET(value) (((value) << TMAG5170_RSLT_ALRT_POS) &\ + TMAG5170_RSLT_ALRT_MASK) + +#define TMAG5170_VER_POS 4U +#define TMAG5170_VER_MASK (BIT_MASK(2U) << TMAG5170_VER_POS) +#define TMAG5170_VER_GET(value) (((value) & TMAG5170_VER_MASK) >> TMAG5170_VER_POS) + +#define TMAG5170_A1_REV 0x0U +#define TMAG5170_A2_REV 0x1U + +#define TMAG5170_MAX_RANGE_50MT_IDX 0x0U +#define TMAG5170_MAX_RANGE_25MT_IDX 0x1U +#define TMAG5170_MAX_RANGE_100MT_IDX 0x2U +#define TMAG5170_MAX_RANGE_EXTEND_FACTOR 0x3U + +#define TMAG5170_CONFIGURATION_MODE 0x0U +#define TMAG5170_STAND_BY_MODE 0x1U +#define TMAG5170_ACTIVE_TRIGGER_MODE 0x3U +#define TMAG5170_SLEEP_MODE 0x5U +#define TMAG5170_DEEP_SLEEP_MODE 0x6U + +#define TMAG5170_MT_TO_GAUSS_RATIO 10U +#define TMAG5170_T_SENS_T0 25U +#define TMAG5170_T_ADC_T0 17522U +#define TMAG5170_T_ADC_RES 60U + +#define TMAG5170_CMD_TRIGGER_CONVERSION BIT(0U) + +#define TMAG5170_CRC_SEED 0xFU +#define TMAG5170_CRC_POLY 0x3U +#define TMAG5170_SPI_BUFFER_LEN 4U +#define TMAG5170_SET_CRC(buf, crc) ((uint8_t *)(buf))[3] |= (crc & 0x0F) +#define TMAG5170_ZERO_CRC(buf) ((uint8_t *)(buf))[3] &= 0xF0 +#define TMAG5170_GET_CRC(buf) ((uint8_t *)(buf))[3] & 0x0F + +LOG_MODULE_REGISTER(TMAG5170, CONFIG_SENSOR_LOG_LEVEL); + +static int tmag5170_transmit_raw(const struct tmag5170_dev_config *config, + uint8_t *buffer_tx, + uint8_t *buffer_rx) +{ + const struct spi_buf tx_buf = { + .buf = buffer_tx, + .len = TMAG5170_SPI_BUFFER_LEN, + }; + + const struct spi_buf_set tx = { + .buffers = &tx_buf, + .count = 1 + }; + + const struct spi_buf rx_buf = { + .buf = buffer_rx, + .len = TMAG5170_SPI_BUFFER_LEN, + }; + + const struct spi_buf_set rx = { + .buffers = &rx_buf, + .count = 1 + }; + + int ret = spi_transceive_dt(&config->bus, &tx, &rx); + + return ret; +} + +static int tmag5170_transmit(const struct device *dev, uint8_t *buffer_tx, uint8_t *buffer_rx) +{ +#if defined(CONFIG_TMAG5170_CRC) + TMAG5170_ZERO_CRC(buffer_tx); + uint8_t crc = crc4_ti(TMAG5170_CRC_SEED, buffer_tx, TMAG5170_SPI_BUFFER_LEN); + + TMAG5170_SET_CRC(buffer_tx, crc); +#endif + int ret = tmag5170_transmit_raw(dev->config, buffer_tx, buffer_rx); +#if defined(CONFIG_TMAG5170_CRC) + if (buffer_rx != NULL && ret == 0) { + uint8_t read_crc = TMAG5170_GET_CRC(buffer_rx); + + TMAG5170_ZERO_CRC(buffer_rx); + crc = crc4_ti(TMAG5170_CRC_SEED, buffer_rx, TMAG5170_SPI_BUFFER_LEN); + if (read_crc != crc) { + return -EIO; + } + } +#endif + + return ret; +} + +static int tmag5170_write_register(const struct device *dev, uint32_t reg, uint16_t data) +{ + uint8_t buffer_tx[4] = { reg, (data >> 8) & 0xFF, data & 0xFF, 0x00U }; + + return tmag5170_transmit(dev, buffer_tx, NULL); +} + +static int tmag5170_read_register(const struct device *dev, + uint32_t reg, + uint16_t *output, + uint8_t cmd) +{ + uint8_t buffer_tx[4] = { BIT(7) | reg, 0x00U, 0x00U, (cmd & BIT_MASK(4U)) << 4U }; + uint8_t buffer_rx[4] = { 0x00U }; + + int ret = tmag5170_transmit(dev, buffer_tx, buffer_rx); + + *output = (buffer_rx[1] << 8) | buffer_rx[2]; + + return ret; +} + +static int tmag5170_convert_magn_reading_to_gauss(struct sensor_value *output, + uint16_t chan_reading, + uint8_t chan_range, + uint8_t chip_revision) +{ + uint16_t max_range_mt = 0U; + + if (chan_range == TMAG5170_MAX_RANGE_50MT_IDX) { + max_range_mt = 50U; + } else if (chan_range == TMAG5170_MAX_RANGE_25MT_IDX) { + max_range_mt = 25U; + } else if (chan_range == TMAG5170_MAX_RANGE_100MT_IDX) { + max_range_mt = 100U; + } else { + return -ENOTSUP; + } + + if (chip_revision == TMAG5170_A2_REV) { + max_range_mt *= TMAG5170_MAX_RANGE_EXTEND_FACTOR; + } + + max_range_mt *= 2U; + + /* The sensor returns data in mT, we need to convert it to Gauss */ + uint32_t max_range_gauss = max_range_mt * TMAG5170_MT_TO_GAUSS_RATIO; + + /* Convert from 2's complementary system */ + int64_t result = chan_reading - ((chan_reading & 0x8000) << 1); + + result *= max_range_gauss; + + /* Scale to increase accuracy */ + result *= 100000; + + /* Divide as it is shown in datasheet */ + result /= 65536; + + /* Remove scale from the final result */ + output->val1 = result / 100000; + output->val2 = result % 100000; + + return 0; +} + +static void tmag5170_convert_temp_reading_to_celsius(struct sensor_value *output, + uint16_t chan_reading) +{ + int32_t result = chan_reading - TMAG5170_T_ADC_T0; + + result = (TMAG5170_T_SENS_T0 * 100000) + (100000 * result / (int32_t)TMAG5170_T_ADC_RES); + + output->val1 = result / 100000; + output->val2 = (result % 100000) * 10; +} + +static void tmag5170_covert_angle_reading_to_degrees(struct sensor_value *output, + uint16_t chan_reading) +{ + /* 12 MSBs store the integer part of the result, + * 4 LSBs store the fractional part of the result + */ + output->val1 = chan_reading >> 4; + output->val2 = ((chan_reading & 0xF) * 1000000) / 16; +} + +static int tmag5170_sample_fetch(const struct device *dev, + enum sensor_channel chan) +{ + const struct tmag5170_dev_config *cfg = dev->config; + struct tmag5170_data *drv_data = dev->data; + int ret = 0; + + if (cfg->operating_mode == TMAG5170_STAND_BY_MODE || + cfg->operating_mode == TMAG5170_ACTIVE_TRIGGER_MODE) { + uint16_t read_status; + + tmag5170_read_register(dev, + TMAG5170_REG_SYS_STATUS, + &read_status, + TMAG5170_CMD_TRIGGER_CONVERSION); + + /* Wait for the measurement to be ready. + * The waiting time will vary depending on the configuration + */ + k_sleep(K_MSEC(5U)); + } + + switch (chan) { + case SENSOR_CHAN_MAGN_X: + ret = tmag5170_read_register(dev, TMAG5170_REG_X_CH_RESULT, &drv_data->x, 0U); + break; + case SENSOR_CHAN_MAGN_Y: + ret = tmag5170_read_register(dev, TMAG5170_REG_Y_CH_RESULT, &drv_data->y, 0U); + break; + case SENSOR_CHAN_MAGN_Z: + ret = tmag5170_read_register(dev, TMAG5170_REG_Z_CH_RESULT, &drv_data->z, 0U); + break; + case SENSOR_CHAN_MAGN_XYZ: + ret = tmag5170_read_register(dev, TMAG5170_REG_X_CH_RESULT, &drv_data->x, 0U); + + if (ret == 0) { + ret = tmag5170_read_register(dev, + TMAG5170_REG_Y_CH_RESULT, + &drv_data->y, + 0U); + } + if (ret == 0) { + ret = tmag5170_read_register(dev, + TMAG5170_REG_Z_CH_RESULT, + &drv_data->z, + 0U); + } + break; + case SENSOR_CHAN_ROTATION: + ret = tmag5170_read_register(dev, + TMAG5170_REG_ANGLE_RESULT, + &drv_data->angle, + 0U); + break; + case SENSOR_CHAN_AMBIENT_TEMP: + ret = tmag5170_read_register(dev, + TMAG5170_REG_TEMP_RESULT, + &drv_data->temperature, + 0U); + break; + case SENSOR_CHAN_ALL: + ret = tmag5170_read_register(dev, + TMAG5170_REG_TEMP_RESULT, + &drv_data->temperature, + 0U); + + if (ret == 0) { + ret = tmag5170_read_register(dev, + TMAG5170_REG_ANGLE_RESULT, + &drv_data->angle, + 0U); + } + + if (ret == 0) { + ret = tmag5170_read_register(dev, + TMAG5170_REG_X_CH_RESULT, + &drv_data->x, + 0U); + } + + if (ret == 0) { + ret = tmag5170_read_register(dev, + TMAG5170_REG_Y_CH_RESULT, + &drv_data->y, + 0U); + } + + if (ret == 0) { + ret = tmag5170_read_register(dev, + TMAG5170_REG_Z_CH_RESULT, + &drv_data->z, + 0U); + } + + break; + default: + ret = -ENOTSUP; + break; + } + + return ret; +} + +static int tmag5170_channel_get(const struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + const struct tmag5170_dev_config *cfg = dev->config; + struct tmag5170_data *drv_data = dev->data; + int ret = 0; + + switch (chan) { + case SENSOR_CHAN_MAGN_XYZ: + ret = tmag5170_convert_magn_reading_to_gauss(val, + drv_data->x, + cfg->x_range, + drv_data->chip_revision); + + if (ret == 0) { + ret = tmag5170_convert_magn_reading_to_gauss(val + 1, + drv_data->y, + cfg->y_range, + drv_data->chip_revision); + } + + if (ret == 0) { + ret = tmag5170_convert_magn_reading_to_gauss(val + 2, + drv_data->z, + cfg->z_range, + drv_data->chip_revision); + } + break; + case SENSOR_CHAN_MAGN_X: + ret = tmag5170_convert_magn_reading_to_gauss(val, + drv_data->x, + cfg->x_range, + drv_data->chip_revision); + break; + case SENSOR_CHAN_MAGN_Y: + ret = tmag5170_convert_magn_reading_to_gauss(val, + drv_data->y, + cfg->y_range, + drv_data->chip_revision); + break; + case SENSOR_CHAN_MAGN_Z: + ret = tmag5170_convert_magn_reading_to_gauss(val, + drv_data->z, + cfg->z_range, + drv_data->chip_revision); + break; + case SENSOR_CHAN_ROTATION: + tmag5170_covert_angle_reading_to_degrees(val, drv_data->angle); + break; + case SENSOR_CHAN_AMBIENT_TEMP: + tmag5170_convert_temp_reading_to_celsius(val, drv_data->temperature); + break; + default: + ret = -ENOTSUP; + break; + } + + return ret; +} + +static int tmag5170_init_registers(const struct device *dev) +{ + const struct tmag5170_dev_config *cfg = dev->config; + struct tmag5170_data *drv_data = dev->data; + uint16_t test_cfg_reg = 0U; + int ret = 0; + +#if !defined(CONFIG_TMAG5170_CRC) + const uint8_t disable_crc_packet[4] = { 0x0FU, 0x0U, 0x04U, 0x07U }; + + ret = tmag5170_transmit_raw(cfg, disable_crc_packet, NULL); +#endif + if (ret == 0) { + ret = tmag5170_read_register(dev, TMAG5170_REG_TEST_CONFIG, &test_cfg_reg, 0U); + } + + if (ret == 0) { + drv_data->chip_revision = TMAG5170_VER_GET(test_cfg_reg); + + ret = tmag5170_write_register(dev, + TMAG5170_REG_SENSOR_CONFIG, + TMAG5170_ANGLE_EN_SET(cfg->angle_measurement) | + TMAG5170_SLEEPTIME_SET(cfg->sleep_time) | + TMAG5170_MAG_CH_EN_SET(cfg->magnetic_channels) | + TMAG5170_Z_RANGE_SET(cfg->z_range) | + TMAG5170_Y_RANGE_SET(cfg->y_range) | + TMAG5170_X_RANGE_SET(cfg->x_range)); + } + +#if defined(CONFIG_TMAG5170_TRIGGER) + if (ret == 0) { + ret = tmag5170_write_register(dev, + TMAG5170_REG_ALERT_CONFIG, + TMAG5170_RSLT_ALRT_SET(1U)); + } +#endif + if (ret == 0) { + ret = tmag5170_write_register(dev, + TMAG5170_REG_DEVICE_CONFIG, + TMAG5170_OPERATING_MODE_SET(cfg->operating_mode) | + TMAG5170_CONV_AVG_SET(cfg->oversampling) | + TMAG5170_MAG_TEMPCO_SET(cfg->magnet_type) | + TMAG5170_T_CH_EN_SET(cfg->tempeature_measurement) | + TMAG5170_T_RATE_SET(cfg->disable_temperature_oversampling)); + } + + return ret; +} + +#ifdef CONFIG_PM_DEVICE +static int tmag5170_pm_action(const struct device *dev, + enum pm_device_action action) +{ + int ret_val = 0; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + tmag5170_write_register(dev, + TMAG5170_REG_DEVICE_CONFIG, + TMAG5170_OPERATING_MODE_SET(TMAG5170_CONFIGURATION_MODE)); + /* As per datasheet, waking up from deep-sleep can take up to 500us */ + k_sleep(K_USEC(500)); + ret_val = tmag5170_init_registers(dev); + break; + case PM_DEVICE_ACTION_SUSPEND: + ret_val = tmag5170_write_register(dev, + TMAG5170_REG_DEVICE_CONFIG, + TMAG5170_OPERATING_MODE_SET(TMAG5170_DEEP_SLEEP_MODE)); + break; + default: + ret_val = -ENOTSUP; + } + + return ret_val; +} +#endif /* CONFIG_PM_DEVICE */ + +static const struct sensor_driver_api tmag5170_driver_api = { + .sample_fetch = tmag5170_sample_fetch, + .channel_get = tmag5170_channel_get, +#if defined(CONFIG_TMAG5170_TRIGGER) + .trigger_set = tmag5170_trigger_set +#endif +}; + +static int tmag5170_init(const struct device *dev) +{ + const struct tmag5170_dev_config *cfg = dev->config; + int ret = 0; + + if (!spi_is_ready_dt(&cfg->bus)) { + LOG_ERR("SPI dev %s not ready", cfg->bus.bus->name); + return -ENODEV; + } + + ret = tmag5170_init_registers(dev); + if (ret != 0) { + return ret; + } + +#if defined(CONFIG_TMAG5170_TRIGGER) + if (cfg->int_gpio.port) { + ret = tmag5170_trigger_init(dev); + } +#endif + + return ret; +} + +#define DEFINE_TMAG5170(_num) \ + static struct tmag5170_data tmag5170_data_##_num; \ + static const struct tmag5170_dev_config tmag5170_config_##_num = { \ + .bus = SPI_DT_SPEC_INST_GET(_num, \ + SPI_OP_MODE_MASTER | \ + SPI_TRANSFER_MSB | \ + SPI_WORD_SET(32), \ + 0), \ + .magnetic_channels = DT_INST_ENUM_IDX(_num, magnetic_channels), \ + .x_range = DT_INST_ENUM_IDX(_num, x_range), \ + .y_range = DT_INST_ENUM_IDX(_num, y_range), \ + .z_range = DT_INST_ENUM_IDX(_num, z_range), \ + .operating_mode = DT_INST_PROP(_num, operating_mode), \ + .oversampling = DT_INST_ENUM_IDX(_num, oversampling), \ + .tempeature_measurement = DT_INST_PROP(_num, enable_temperature_channel), \ + .magnet_type = DT_INST_ENUM_IDX(_num, magnet_type), \ + .angle_measurement = DT_INST_ENUM_IDX(_num, angle_measurement), \ + .disable_temperature_oversampling = DT_INST_PROP(_num, \ + disable_temperature_oversampling), \ + .sleep_time = DT_INST_ENUM_IDX(_num, sleep_time), \ + IF_ENABLED(CONFIG_TMAG5170_TRIGGER, \ + (.int_gpio = GPIO_DT_SPEC_INST_GET_OR(_num, int_gpios, { 0 }),)) \ + }; \ + PM_DEVICE_DT_INST_DEFINE(_num, tmag5170_pm_action); \ + \ + SENSOR_DEVICE_DT_INST_DEFINE(_num, \ + tmag5170_init, \ + PM_DEVICE_DT_INST_GET(_num), \ + &tmag5170_data_##_num, \ + &tmag5170_config_##_num, \ + POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, \ + &tmag5170_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(DEFINE_TMAG5170) diff --git a/drivers/sensor/tmag5170/tmag5170.h b/drivers/sensor/tmag5170/tmag5170.h new file mode 100644 index 00000000000..28f76d2e12b --- /dev/null +++ b/drivers/sensor/tmag5170/tmag5170.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023 Michal Morsisko + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_TMAG5170_TMAG5170_H_ +#define ZEPHYR_DRIVERS_SENSOR_TMAG5170_TMAG5170_H_ + +#include +#include +#include +#include + +struct tmag5170_dev_config { + struct spi_dt_spec bus; + uint8_t magnetic_channels; + uint8_t x_range; + uint8_t y_range; + uint8_t z_range; + uint8_t oversampling; + bool tempeature_measurement; + uint8_t magnet_type; + uint8_t angle_measurement; + bool disable_temperature_oversampling; + uint8_t sleep_time; + uint8_t operating_mode; +#if defined(CONFIG_TMAG5170_TRIGGER) + struct gpio_dt_spec int_gpio; +#endif +}; + +struct tmag5170_data { + uint8_t chip_revision; + uint16_t x; + uint16_t y; + uint16_t z; + uint16_t temperature; + uint16_t angle; +#if defined(CONFIG_TMAG5170_TRIGGER) + struct gpio_callback gpio_cb; + sensor_trigger_handler_t handler_drdy; + const struct sensor_trigger *trigger_drdy; + const struct device *dev; +#endif + +#if defined(CONFIG_TMAG5170_TRIGGER_OWN_THREAD) + struct k_sem sem; + struct k_thread thread; + + K_KERNEL_STACK_MEMBER(thread_stack, + CONFIG_TMAG5170_THREAD_STACK_SIZE); +#elif defined(CONFIG_TMAG5170_TRIGGER_GLOBAL_THREAD) + struct k_work work; +#endif +}; + +#if defined(CONFIG_TMAG5170_TRIGGER) +int tmag5170_trigger_set(const struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); + +int tmag5170_trigger_init(const struct device *dev); +#endif + +#endif /* ZEPHYR_DRIVERS_SENSOR_TMAG5170_TMAG5170_H_ */ diff --git a/drivers/sensor/tmag5170/tmag5170_trigger.c b/drivers/sensor/tmag5170/tmag5170_trigger.c new file mode 100644 index 00000000000..c1be9cd4e1f --- /dev/null +++ b/drivers/sensor/tmag5170/tmag5170_trigger.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2023 Michal Morsisko + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ti_tmag5170 + +#include +#include +#include +#include +#include + +#include "tmag5170.h" + +LOG_MODULE_DECLARE(TMAG5170, CONFIG_SENSOR_LOG_LEVEL); + +static void tmag5170_handle_interrupts(const void *arg) +{ + const struct device *dev = (const struct device *)arg; + struct tmag5170_data *data = dev->data; + + if (data->handler_drdy) { + data->handler_drdy(dev, data->trigger_drdy); + } +} + +#if defined(CONFIG_TMAG5170_TRIGGER_OWN_THREAD) +static void tmag5170_thread_main(void *arg1, void *unused1, void *unused2) +{ + ARG_UNUSED(unused1); + ARG_UNUSED(unused2); + const struct device *dev = (const struct device *)arg1; + struct tmag5170_data *data = dev->data; + + while (1) { + k_sem_take(&data->sem, K_FOREVER); + tmag5170_handle_interrupts(dev); + } +} +#endif + +#if defined(CONFIG_TMAG5170_TRIGGER_GLOBAL_THREAD) +static void tmag5170_work_handler(struct k_work *work) +{ + struct tmag5170_data *data = CONTAINER_OF(work, + struct tmag5170_data, + work); + + tmag5170_handle_interrupts(data->dev); +} +#endif + +static void tmag5170_gpio_callback(const struct device *port, + struct gpio_callback *cb, + uint32_t pin) +{ + struct tmag5170_data *data = CONTAINER_OF(cb, + struct tmag5170_data, + gpio_cb); + + ARG_UNUSED(port); + ARG_UNUSED(pin); + +#if defined(CONFIG_TMAG5170_TRIGGER_OWN_THREAD) + k_sem_give(&data->sem); +#elif defined(CONFIG_TMAG5170_TRIGGER_GLOBAL_THREAD) + k_work_submit(&data->work); +#elif defined(CONFIG_TMAG5170_TRIGGER_DIRECT) + tmag5170_handle_interrupts(data->dev); +#endif +} + +int tmag5170_trigger_set( + const struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + struct tmag5170_data *data = dev->data; + +#if defined(CONFIG_PM_DEVICE) + enum pm_device_state state; + + (void)pm_device_state_get(dev, &state); + if (state != PM_DEVICE_STATE_ACTIVE) { + return -EBUSY; + } +#endif + + if (trig->type != SENSOR_TRIG_DATA_READY) { + return -ENOTSUP; + } + + data->trigger_drdy = trig; + data->handler_drdy = handler; + + return 0; +} + +int tmag5170_trigger_init(const struct device *dev) +{ + struct tmag5170_data *data = dev->data; + const struct tmag5170_dev_config *cfg = dev->config; + int ret; + + if (!device_is_ready(cfg->int_gpio.port)) { + LOG_ERR("%s: device %s is not ready", dev->name, cfg->int_gpio.port->name); + return -ENODEV; + } + + data->dev = dev; + +#if defined(CONFIG_TMAG5170_TRIGGER_OWN_THREAD) + k_sem_init(&data->sem, 0, 1); + k_thread_create( + &data->thread, + data->thread_stack, + CONFIG_TMAG5170_THREAD_STACK_SIZE, + tmag5170_thread_main, + (void *)dev, + NULL, + NULL, + K_PRIO_COOP(CONFIG_TMAG5170_THREAD_PRIORITY), + 0, + K_NO_WAIT); +#elif defined(CONFIG_TMAG5170_TRIGGER_GLOBAL_THREAD) + data->work.handler = tmag5170_work_handler; +#endif + ret = gpio_pin_configure_dt(&cfg->int_gpio, GPIO_INPUT); + + if (ret < 0) { + return ret; + } + + gpio_init_callback(&data->gpio_cb, tmag5170_gpio_callback, BIT(cfg->int_gpio.pin)); + + ret = gpio_add_callback(cfg->int_gpio.port, &data->gpio_cb); + if (ret < 0) { + return ret; + } + + ret = gpio_pin_interrupt_configure_dt(&cfg->int_gpio, GPIO_INT_EDGE_FALLING); + if (ret < 0) { + return ret; + } + + return ret; +} diff --git a/drivers/sensor/tmp007/tmp007_trigger.c b/drivers/sensor/tmp007/tmp007_trigger.c index d123a68aabc..a3eb0b07303 100644 --- a/drivers/sensor/tmp007/tmp007_trigger.c +++ b/drivers/sensor/tmp007/tmp007_trigger.c @@ -105,8 +105,13 @@ static void tmp007_thread_cb(const struct device *dev) } #ifdef CONFIG_TMP007_TRIGGER_OWN_THREAD -static void tmp007_thread(struct tmp007_data *drv_data) +static void tmp007_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct tmp007_data *drv_data = p1; + while (1) { k_sem_take(&drv_data->gpio_sem, K_FOREVER); tmp007_thread_cb(drv_data->dev); @@ -185,7 +190,7 @@ int tmp007_init_interrupt(const struct device *dev) k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_TMP007_THREAD_STACK_SIZE, - (k_thread_entry_t)tmp007_thread, drv_data, + tmp007_thread, drv_data, NULL, NULL, K_PRIO_COOP(CONFIG_TMP007_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_TMP007_TRIGGER_GLOBAL_THREAD) diff --git a/drivers/sensor/tmp116/tmp116.c b/drivers/sensor/tmp116/tmp116.c index a327f522f05..4972ac443a2 100644 --- a/drivers/sensor/tmp116/tmp116.c +++ b/drivers/sensor/tmp116/tmp116.c @@ -257,8 +257,36 @@ static int tmp116_attr_set(const struct device *dev, } } +static int tmp116_attr_get(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, struct sensor_value *val) +{ + uint16_t data; + int rc; + + if (chan != SENSOR_CHAN_AMBIENT_TEMP) { + return -ENOTSUP; + } + + switch (attr) { + case SENSOR_ATTR_CONFIGURATION: + rc = tmp116_reg_read(dev, TMP116_REG_CFGR, &data); + if (rc < 0) { + return rc; + } + break; + default: + return -ENOTSUP; + } + + val->val1 = data; + val->val2 = 0; + + return 0; +} + static const struct sensor_driver_api tmp116_driver_api = { .attr_set = tmp116_attr_set, + .attr_get = tmp116_attr_get, .sample_fetch = tmp116_sample_fetch, .channel_get = tmp116_channel_get }; diff --git a/drivers/sensor/tsl2540/CMakeLists.txt b/drivers/sensor/tsl2540/CMakeLists.txt new file mode 100644 index 00000000000..dbc6ed78927 --- /dev/null +++ b/drivers/sensor/tsl2540/CMakeLists.txt @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(tsl2540.c) +zephyr_library_sources_ifdef(CONFIG_TSL2540_TRIGGER tsl2540_trigger.c) diff --git a/drivers/sensor/tsl2540/Kconfig b/drivers/sensor/tsl2540/Kconfig new file mode 100644 index 00000000000..b4d3e1ec510 --- /dev/null +++ b/drivers/sensor/tsl2540/Kconfig @@ -0,0 +1,54 @@ +# TSL2540 Ambient Light Sensor configuration options + +# Copyright (c) 2022 T-Mobile USA, Inc. +# SPDX-License-Identifier: Apache-2.0 + +menuconfig TSL2540 + bool "TSL2540 Ambient Light Sensor" + default y + depends on DT_HAS_AMS_TSL2540_ENABLED + select I2C + help + Enable driver for TSL2540 sensors. + +if TSL2540 + +config TSL2540_TRIGGER + bool + +choice + prompt "Trigger mode" + default TSL2540_TRIGGER_NONE + help + Specify the type of triggering to be used by the driver. + +config TSL2540_TRIGGER_NONE + bool "No trigger" + +config TSL2540_TRIGGER_GLOBAL_THREAD + bool "Use global thread" + depends on GPIO + select TSL2540_TRIGGER + +config TSL2540_TRIGGER_OWN_THREAD + bool "Use own thread" + depends on GPIO + select TSL2540_TRIGGER + +endchoice + +config TSL2540_THREAD_PRIORITY + int "Thread priority" + depends on TSL2540_TRIGGER_OWN_THREAD + default 10 + help + Priority of thread used by the driver to handle interrupts. + +config TSL2540_THREAD_STACK_SIZE + int "Thread stack size" + depends on TSL2540_TRIGGER_OWN_THREAD + default 1024 + help + Stack size of thread used by the driver to handle interrupts. + +endif # TSL2540 diff --git a/drivers/sensor/tsl2540/tsl2540.c b/drivers/sensor/tsl2540/tsl2540.c new file mode 100644 index 00000000000..fb3060d136e --- /dev/null +++ b/drivers/sensor/tsl2540/tsl2540.c @@ -0,0 +1,373 @@ +/* + * Copyright (c) 2022 T-Mobile USA, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ams_tsl2540 + +#include "tsl2540.h" + +#include + +#include +#include +#include +#include +#include +#include + +#define TSL2540_INTEGRATION_TIME_MS (2.81) +#define TSL2540_DEVICE_FACTOR (53.0) + +#define FIXED_ATTENUATION_TO_DBL(x) (x * 0.00001) + +LOG_MODULE_REGISTER(tsl2540, CONFIG_SENSOR_LOG_LEVEL); + +static int tsl2540_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + const struct tsl2540_config *cfg = dev->config; + struct tsl2540_data *data = dev->data; + int ret = 0; + + __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_LIGHT || + chan == SENSOR_CHAN_IR); + k_sem_take(&data->sem, K_FOREVER); + + if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_LIGHT) { + uint16_t le16_buffer; + + ret = i2c_burst_read_dt(&cfg->i2c_spec, TSL2540_REG_VIS_LOW, + (uint8_t *)&le16_buffer, sizeof(le16_buffer)); + if (ret) { + LOG_ERR("Could not fetch ambient light (visible)"); + k_sem_give(&data->sem); + return -EIO; + } + + data->count_vis = sys_le16_to_cpu(le16_buffer); + } + + if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_IR) { + uint16_t le16_buffer; + + ret = i2c_burst_read_dt(&cfg->i2c_spec, TSL2540_REG_IR_LOW, (uint8_t *)&le16_buffer, + sizeof(le16_buffer)); + if (ret) { + LOG_ERR("Could not fetch ambient light (IR)"); + k_sem_give(&data->sem); + return -EIO; + } + + data->count_ir = sys_le16_to_cpu(le16_buffer); + } + + k_sem_give(&data->sem); + + return ret; +} + +static int tsl2540_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + const struct tsl2540_config *cfg = dev->config; + struct tsl2540_data *data = dev->data; + int ret = 0; + double cpl; + double glass_attenuation = FIXED_ATTENUATION_TO_DBL(cfg->glass_attenuation); + double glass_ir_attenuation = FIXED_ATTENUATION_TO_DBL(cfg->glass_ir_attenuation); + + k_sem_take(&data->sem, K_FOREVER); + + cpl = (data->integration_time + 1) * TSL2540_INTEGRATION_TIME_MS; + cpl *= data->again; + + switch (chan) { + case SENSOR_CHAN_LIGHT: + sensor_value_from_double(val, data->count_vis / cpl * + TSL2540_DEVICE_FACTOR * glass_attenuation); + break; + case SENSOR_CHAN_IR: + sensor_value_from_double(val, data->count_ir / cpl * + TSL2540_DEVICE_FACTOR * glass_ir_attenuation); + break; + default: + ret = -ENOTSUP; + } + + k_sem_give(&data->sem); + + return ret; +} + +static int tsl2540_attr_set_gain(const struct device *dev, enum sensor_gain_tsl2540 gain) +{ + const struct tsl2540_config *cfg = dev->config; + struct tsl2540_data *data = dev->data; + uint8_t value = 0; + double again = 0.0; + + switch (gain) { + case TSL2540_SENSOR_GAIN_1_2: + value = TSL2540_CFG1_G1_2; + again = TSL2540_AGAIN_S1_2; + break; + case TSL2540_SENSOR_GAIN_1: + value = TSL2540_CFG1_G1; + again = TSL2540_AGAIN_S1; + break; + case TSL2540_SENSOR_GAIN_4: + value = TSL2540_CFG1_G4; + again = TSL2540_AGAIN_S4; + break; + case TSL2540_SENSOR_GAIN_16: + value = TSL2540_CFG1_G16; + again = TSL2540_AGAIN_S16; + break; + case TSL2540_SENSOR_GAIN_64: + value = TSL2540_CFG1_G64; + again = TSL2540_AGAIN_S64; + break; + case TSL2540_SENSOR_GAIN_128: + value = TSL2540_CFG1_G128; + again = TSL2540_CFG2_G128; + break; + } + + if (i2c_reg_write_byte_dt(&cfg->i2c_spec, TSL2540_REG_CFG_1, value) < 0) { + return -EIO; + } + + if (i2c_reg_write_byte_dt(&cfg->i2c_spec, TSL2540_REG_CFG_2, value) < 0) { + return -EIO; + } + + data->again = again; + + return 0; +} + +static int tsl2540_attr_set(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ + const struct tsl2540_config *cfg = dev->config; + struct tsl2540_data *data = dev->data; + int ret = 0; + uint8_t temp; + double it; + + if ((chan != SENSOR_CHAN_IR) & (chan != SENSOR_CHAN_LIGHT)) { + return -ENOTSUP; + } + + k_sem_take(&data->sem, K_FOREVER); + + i2c_reg_write_byte_dt(&cfg->i2c_spec, TSL2540_ENABLE_ADDR, TSL2540_ENABLE_MASK & + ~TSL2540_ENABLE_CONF); + +#if CONFIG_TSL2540_TRIGGER + if (chan == SENSOR_CHAN_LIGHT) { + if (attr == SENSOR_ATTR_UPPER_THRESH) { + double cpl; + uint16_t thld, le16_buffer; + double glass_attenuation = FIXED_ATTENUATION_TO_DBL(cfg->glass_attenuation); + + cpl = ((data->integration_time + 1) * TSL2540_INTEGRATION_TIME_MS); + cpl *= data->again; + cpl /= (TSL2540_DEVICE_FACTOR * glass_attenuation); + thld = sensor_value_to_double(val) * cpl; + LOG_DBG("attr: %d, cpl: %g, thld: %x\n", attr, cpl, thld); + + le16_buffer = sys_cpu_to_le16(thld); + ret = i2c_burst_write_dt( + &((const struct tsl2540_config *)dev->config)->i2c_spec, + TSL2540_REG_AIHT_LOW, (uint8_t *)&le16_buffer, sizeof(le16_buffer)); + + goto exit; + } + if (attr == SENSOR_ATTR_LOWER_THRESH) { + double cpl; + uint16_t thld, le16_buffer; + double glass_attenuation = FIXED_ATTENUATION_TO_DBL(cfg->glass_attenuation); + + cpl = ((data->integration_time + 1) * TSL2540_INTEGRATION_TIME_MS); + cpl *= data->again; + cpl /= (TSL2540_DEVICE_FACTOR * glass_attenuation); + thld = sensor_value_to_double(val) * cpl; + LOG_DBG("attr: %d, cpl: %g, thld: %x\n", attr, cpl, thld); + + le16_buffer = sys_cpu_to_le16(sys_cpu_to_le16(thld)); + + ret = i2c_burst_write_dt( + &((const struct tsl2540_config *)dev->config)->i2c_spec, + TSL2540_REG_AILT_LOW, (uint8_t *)&le16_buffer, sizeof(le16_buffer)); + + goto exit; + } + + } +#endif /* CONFIG_TSL2540_TRIGGER */ + + switch ((enum sensor_attribute_tsl2540)attr) { + case SENSOR_ATTR_GAIN: + tsl2540_attr_set_gain(dev, (enum sensor_gain_tsl2540)val->val1); + break; + case SENSOR_ATTR_INT_APERS: + temp = (uint8_t)val->val1; + + if (temp > 15) { + ret = -EINVAL; + goto exit; + } + + if (i2c_reg_write_byte_dt(&cfg->i2c_spec, TSL2540_REG_PERS, temp)) { + ret = -EIO; + goto exit; + } + break; + case SENSOR_ATTR_INTEGRATION_TIME: + it = sensor_value_to_double(val); + it /= TSL2540_INTEGRATION_TIME_MS; + if (it < 1 || it > 256) { + ret = -EINVAL; + goto exit; + } + it -= 1; + temp = (uint8_t)it; + if (i2c_reg_write_byte_dt(&cfg->i2c_spec, TSL2540_REG_ATIME, temp)) { + ret = -EIO; + goto exit; + } + + data->integration_time = temp; + ret = 0; + break; + case SENSOR_ATTR_TSL2540_SHUTDOWN_MODE: + data->enable_mode = TSL2540_ENABLE_DISABLE; + ret = i2c_reg_update_byte_dt(&cfg->i2c_spec, TSL2540_CFG3_ADDR, TSL2540_CFG3_MASK, + TSL2540_CFG3_CONF); + break; + case SENSOR_ATTR_TSL2540_CONTINUOUS_MODE: + data->enable_mode = TSL2540_ENABLE_CONF; + ret = i2c_reg_update_byte_dt(&cfg->i2c_spec, TSL2540_CFG3_ADDR, TSL2540_CFG3_MASK, + TSL2540_CFG3_CONF); + break; + case SENSOR_ATTR_TSL2540_CONTINUOUS_NO_WAIT_MODE: + data->enable_mode = TSL2540_ENABLE_AEN_PON; + ret = i2c_reg_update_byte_dt(&cfg->i2c_spec, TSL2540_CFG3_ADDR, TSL2540_CFG3_MASK, + TSL2540_CFG3_DFLT); + break; + } + +exit: + i2c_reg_update_byte_dt(&cfg->i2c_spec, TSL2540_ENABLE_ADDR, TSL2540_ENABLE_MASK, + data->enable_mode); + + k_sem_give(&data->sem); + + return ret; +} + +static int tsl2540_setup(const struct device *dev) +{ + struct sensor_value integration_time; + + /* Set ALS integration time */ + tsl2540_attr_set(dev, (enum sensor_channel)SENSOR_CHAN_LIGHT, + (enum sensor_attribute)SENSOR_ATTR_GAIN, + &(struct sensor_value){.val1 = TSL2540_SENSOR_GAIN_1_2, .val2 = 0}); + + sensor_value_from_double(&integration_time, 500.0); + tsl2540_attr_set(dev, (enum sensor_channel)SENSOR_CHAN_LIGHT, + (enum sensor_attribute)SENSOR_ATTR_INTEGRATION_TIME, &integration_time); + + return 0; +} + +static int tsl2540_init(const struct device *dev) +{ + const struct tsl2540_config *cfg = dev->config; + struct tsl2540_data *data = dev->data; + + data->enable_mode = TSL2540_ENABLE_DISABLE; + + k_sem_init(&data->sem, 1, K_SEM_MAX_LIMIT); + + if (!i2c_is_ready_dt(&cfg->i2c_spec)) { + LOG_ERR("I2C dev %s not ready", cfg->i2c_spec.bus->name); + return -ENODEV; + } + + i2c_reg_write_byte_dt(&cfg->i2c_spec, TSL2540_REG_PERS, 1); + i2c_reg_update_byte_dt(&cfg->i2c_spec, TSL2540_CFG3_ADDR, TSL2540_CFG3_MASK, + TSL2540_CFG3_DFLT); + + if (tsl2540_setup(dev)) { + LOG_ERR("Failed to setup ambient light functionality"); + return -EIO; + } + +#if CONFIG_TSL2540_TRIGGER + if (tsl2540_trigger_init(dev)) { + LOG_ERR("Could not initialize interrupts"); + return -EIO; + } +#endif + + LOG_DBG("Init complete"); + + return 0; +} + +static const struct sensor_driver_api tsl2540_driver_api = { + .sample_fetch = tsl2540_sample_fetch, + .channel_get = tsl2540_channel_get, + .attr_set = tsl2540_attr_set, +#ifdef CONFIG_TSL2540_TRIGGER + .trigger_set = tsl2540_trigger_set, +#endif +}; + +#ifdef CONFIG_PM_DEVICE +static int tsl2540_pm_action(const struct device *dev, enum pm_device_action action) +{ + + const struct tsl2540_config *cfg = dev->config; + struct tsl2540_data *data = dev->data; + int ret = 0; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + ret = i2c_reg_update_byte_dt(&cfg->i2c_spec, TSL2540_ENABLE_ADDR, + TSL2540_ENABLE_MASK, data->enable_mode); + break; + case PM_DEVICE_ACTION_SUSPEND: + ret = i2c_reg_update_byte_dt(&cfg->i2c_spec, TSL2540_ENABLE_ADDR, + TSL2540_ENABLE_MASK, TSL2540_ENABLE_DISABLE); + break; + default: + return -ENOTSUP; + } + + return ret; +} +#endif + +#define TSL2540_GLASS_ATTEN(inst) \ + .glass_attenuation = DT_INST_PROP(inst, glass_attenuation), \ + .glass_ir_attenuation = DT_INST_PROP(inst, glass_ir_attenuation), \ + +#define TSL2540_DEFINE(inst) \ + static struct tsl2540_data tsl2540_prv_data_##inst; \ + static const struct tsl2540_config tsl2540_config_##inst = { \ + .i2c_spec = I2C_DT_SPEC_INST_GET(inst), \ + IF_ENABLED(CONFIG_TSL2540_TRIGGER, \ + (.int_gpio = GPIO_DT_SPEC_INST_GET(inst, int_gpios),)) \ + TSL2540_GLASS_ATTEN(inst) \ + }; \ + PM_DEVICE_DT_INST_DEFINE(inst, tsl2540_pm_action); \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, &tsl2540_init, PM_DEVICE_DT_INST_GET(inst), \ + &tsl2540_prv_data_##inst, &tsl2540_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &tsl2540_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(TSL2540_DEFINE) diff --git a/drivers/sensor/tsl2540/tsl2540.h b/drivers/sensor/tsl2540/tsl2540.h new file mode 100644 index 00000000000..7cabaaeb519 --- /dev/null +++ b/drivers/sensor/tsl2540/tsl2540.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2022 T-Mobile USA, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_TSL2540_TSL2540_H_ +#define ZEPHYR_DRIVERS_SENSOR_TSL2540_TSL2540_H_ + +#include +#include +#include +#include + +#define TSL2540_REG_ATIME 0x81 +#define TSL2540_REG_WTIME 0x83 +#define TSL2540_REG_AILT_LOW 0x84 +#define TSL2540_REG_AILT_HI 0x85 +#define TSL2540_REG_AIHT_LOW 0x86 +#define TSL2540_REG_AIHT_HI 0x87 +#define TSL2540_REG_PERS 0x8c +#define TSL2540_REG_CFG_0 0x8d +#define TSL2540_REG_CFG_1 0x90 +#define TSL2540_REG_REVID 0x91 +#define TSL2540_REG_ID 0x92 +#define TSL2540_REG_STATUS 0x93 +#define TSL2540_REG_VIS_LOW 0x94 +#define TSL2540_REG_VIS_HI 0x95 +#define TSL2540_REG_IR_LOW 0x96 +#define TSL2540_REG_IR_HI 0x97 +#define TSL2540_REG_REVID2 0x9E +#define TSL2540_REG_CFG_2 0x9f + +#define TSL2540_AGAIN_S1_2 0.5 +#define TSL2540_AGAIN_S1 1 +#define TSL2540_AGAIN_S4 4 +#define TSL2540_AGAIN_S16 16 +#define TSL2540_AGAIN_S64 67 +#define TSL2540_AGAIN_S128 140 + +#define TSL2540_CFG1_G1_2 0x00 +#define TSL2540_CFG1_G1 0x00 +#define TSL2540_CFG1_G4 0x01 +#define TSL2540_CFG1_G16 0x02 +#define TSL2540_CFG1_G64 0x03 +#define TSL2540_CFG1_G128 0x03 + +#define TSL2540_CFG2_G1_2 0x00 +#define TSL2540_CFG2_G1 0x04 +#define TSL2540_CFG2_G4 0x04 +#define TSL2540_CFG2_G16 0x04 +#define TSL2540_CFG2_G64 0x04 +#define TSL2540_CFG2_G128 0x14 + +/* ENABLE(0x80: 0x00): Reserved:7:4 | WEN:3 | Reserved:2 | AEN:1 | PON:0 */ +#define TSL2540_ENABLE_ADDR 0x80 +#define TSL2540_ENABLE_MASK (BIT(3) | BIT(1) | BIT(0)) +#define TSL2540_ENABLE_CONF (BIT(3) | BIT(1) | BIT(0)) +#define TSL2540_ENABLE_AEN_PON (BIT(1) | BIT(0)) +#define TSL2540_ENABLE_DISABLE (0) + +/* CRG3(0xAB: 0x0C): INT_READ_CLEAR:7 | Reserved:6:5 | SAI:4 | Reserved:3:0 */ +#define TSL2540_CFG3_ADDR 0xAB +#define TSL2540_CFG3_MASK (BIT(7) | BIT(4)) +#define TSL2540_CFG3_CONF (BIT(7) | BIT(4)) +#define TSL2540_CFG3_DFLT (0) + +/* INTENAB(0xDD: 0x00): ASIEN:7 | Reserved:6:5 | AIEN:4 | Reserved:3:0 */ +#define TSL2540_INTENAB_ADDR 0xDD +#define TSL2540_INTENAB_MASK (BIT(7) | BIT(4)) +#define TSL2540_INTENAB_CONF (BIT(4)) + +#define TSL2540_INT_EN_AEN 0x90 + +struct tsl2540_config { + const struct i2c_dt_spec i2c_spec; +#ifdef CONFIG_TSL2540_TRIGGER + const struct gpio_dt_spec int_gpio; +#endif + const uint32_t glass_attenuation; + const uint32_t glass_ir_attenuation; +}; + +struct tsl2540_data { + const struct device *i2c; + struct k_sem sem; +#ifdef CONFIG_TSL2540_TRIGGER + const struct device *dev; + struct gpio_callback gpio_cb; + const struct sensor_trigger *als_trigger; + sensor_trigger_handler_t als_handler; +#endif +#ifdef CONFIG_TSL2540_TRIGGER_OWN_THREAD + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_TSL2540_THREAD_STACK_SIZE); + struct k_thread thread; + struct k_sem trig_sem; +#endif +#ifdef CONFIG_TSL2540_TRIGGER_GLOBAL_THREAD + struct k_work work; +#endif + uint8_t enable_mode; + uint16_t count_vis; + uint16_t count_ir; + uint8_t integration_time; + double again; +}; + +#ifdef CONFIG_TSL2540_TRIGGER +int tsl2540_trigger_init(const struct device *dev); + +int tsl2540_trigger_set(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); +#endif + +#endif diff --git a/drivers/sensor/tsl2540/tsl2540_trigger.c b/drivers/sensor/tsl2540/tsl2540_trigger.c new file mode 100644 index 00000000000..3251c3a45c9 --- /dev/null +++ b/drivers/sensor/tsl2540/tsl2540_trigger.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2022 T-Mobile USA, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "tsl2540.h" +#include + +LOG_MODULE_DECLARE(tsl2540, CONFIG_SENSOR_LOG_LEVEL); + +static void tsl2540_setup_int(const struct device *dev, bool enable) +{ + const struct tsl2540_config *config = dev->config; + gpio_flags_t flags = enable + ? GPIO_INT_EDGE_TO_ACTIVE + : GPIO_INT_DISABLE; + + gpio_pin_interrupt_configure_dt(&config->int_gpio, flags); +} + +static void tsl2540_handle_int(const struct device *dev) +{ + struct tsl2540_data *drv_data = dev->data; + + tsl2540_setup_int(dev, false); + +#if defined(CONFIG_TSL2540_TRIGGER_OWN_THREAD) + k_sem_give(&drv_data->trig_sem); +#elif defined(CONFIG_TSL2540_TRIGGER_GLOBAL_THREAD) + k_work_submit(&drv_data->work); +#endif +} + +static void tsl2540_gpio_callback(const struct device *dev, struct gpio_callback *cb, + uint32_t pin_mask) +{ + struct tsl2540_data *data = CONTAINER_OF(cb, struct tsl2540_data, gpio_cb); + + tsl2540_handle_int(data->dev); +} + +static void tsl2540_process_int(const struct device *dev) +{ + const struct tsl2540_config *config = dev->config; + struct tsl2540_data *data = dev->data; + uint8_t status; + + /* Read the status, cleared automatically in CFG3 */ + int ret = i2c_reg_read_byte_dt(&config->i2c_spec, TSL2540_REG_STATUS, &status); + + if (ret) { + LOG_ERR("Could not read status register (%#x), errno: %d", TSL2540_REG_STATUS, + ret); + return; + } + + if (BIT(7) & status) { /* ASAT */ + LOG_ERR("Interrupt status(%#x): %#x: ASAT", TSL2540_REG_STATUS, status); + } + + if (BIT(3) & status) { /* CINT */ + LOG_DBG("Interrupt status(%#x): %#x: CINT", TSL2540_REG_STATUS, status); + } + + if (BIT(4) & status) { /* AINT */ + LOG_DBG("Interrupt status(%#x): %#x: AINT", TSL2540_REG_STATUS, status); + if (data->als_handler != NULL) { + data->als_handler(dev, data->als_trigger); + } + } + + tsl2540_setup_int(dev, true); + + /* Check for pin that may be asserted while we were busy */ + int pv = gpio_pin_get_dt(&config->int_gpio); + + if (pv > 0) { + tsl2540_handle_int(dev); + } +} + +#ifdef CONFIG_TSL2540_TRIGGER_OWN_THREAD +static void tsl2540_thread_main(void *p1, void *p2, void *p3) +{ + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct tsl2540_data *data = p1; + + while (true) { + k_sem_take(&data->trig_sem, K_FOREVER); + tsl2540_process_int(data->dev); + } +} +#endif + +#ifdef CONFIG_TSL2540_TRIGGER_GLOBAL_THREAD +static void tsl2540_work_handler(struct k_work *work) +{ + struct tsl2540_data *data = CONTAINER_OF(work, struct tsl2540_data, work); + + tsl2540_process_int(data->dev); +} +#endif + +int tsl2540_trigger_set(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + const struct tsl2540_config *config = dev->config; + struct tsl2540_data *data = dev->data; + int ret; + + if (trig->type != SENSOR_TRIG_THRESHOLD) { + LOG_ERR("Unsupported sensor trigger type: %d", trig->type); + return -ENOTSUP; + } + + if (trig->chan != SENSOR_CHAN_LIGHT) { + LOG_ERR("Unsupported sensor trigger channel: %d", trig->chan); + return -ENOTSUP; + } + + + const struct i2c_dt_spec *i2c_spec = &config->i2c_spec; + + ret = i2c_reg_update_byte_dt(i2c_spec, TSL2540_INTENAB_ADDR, + TSL2540_INTENAB_MASK, TSL2540_INTENAB_CONF); + if (ret) { + LOG_ERR("%#x: I/O error: %d", TSL2540_INTENAB_ADDR, ret); + return -EIO; + } + + ret = i2c_reg_update_byte_dt(i2c_spec, TSL2540_CFG3_ADDR, + TSL2540_CFG3_MASK, TSL2540_CFG3_CONF); + if (ret) { + LOG_ERR("%#x: I/O error: %d", TSL2540_CFG3_ADDR, ret); + return -EIO; + } + + k_sem_take(&data->sem, K_FOREVER); + + data->als_handler = handler; + data->als_trigger = trig; + + if (handler != NULL) { + tsl2540_setup_int(dev, true); + + /* Check whether already asserted */ + int pv = gpio_pin_get_dt(&config->int_gpio); + + if (pv > 0) { + tsl2540_handle_int(dev); + } + } + + k_sem_give(&data->sem); + + return ret; +} + +int tsl2540_trigger_init(const struct device *dev) +{ + const struct tsl2540_config *config = dev->config; + struct tsl2540_data *data = dev->data; + int rc; + + /* Check device is defined */ + if (config->int_gpio.port == NULL) { + LOG_ERR("int-gpios is not defined in the device tree."); + return -EINVAL; + } + + /* Get the GPIO device */ + if (!gpio_is_ready_dt(&config->int_gpio)) { + LOG_ERR("%s: gpio controller %s not ready", dev->name, config->int_gpio.port->name); + return -ENODEV; + } + + rc = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT); + if (rc < 0) { + return rc; + } + + gpio_init_callback(&data->gpio_cb, tsl2540_gpio_callback, BIT(config->int_gpio.pin)); + + if (gpio_add_callback(config->int_gpio.port, &data->gpio_cb) < 0) { + LOG_ERR("Failed to set gpio callback!"); + return -EIO; + } + + data->dev = dev; + +#if defined(CONFIG_TSL2540_TRIGGER_OWN_THREAD) + k_sem_init(&data->trig_sem, 0, K_SEM_MAX_LIMIT); + k_thread_create(&data->thread, data->thread_stack, CONFIG_TSL2540_THREAD_STACK_SIZE, + tsl2540_thread_main, data, NULL, NULL, + K_PRIO_COOP(CONFIG_TSL2540_THREAD_PRIORITY), 0, K_NO_WAIT); + k_thread_name_set(&data->thread, "TSL2540 trigger"); +#elif defined(CONFIG_TSL2540_TRIGGER_GLOBAL_THREAD) + data->work.handler = tsl2540_work_handler; +#endif + + return 0; +} diff --git a/drivers/sensor/tsl2561/CMakeLists.txt b/drivers/sensor/tsl2561/CMakeLists.txt new file mode 100644 index 00000000000..7c2d251b150 --- /dev/null +++ b/drivers/sensor/tsl2561/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(tsl2561.c) diff --git a/drivers/sensor/tsl2561/Kconfig b/drivers/sensor/tsl2561/Kconfig new file mode 100644 index 00000000000..e5b975bad34 --- /dev/null +++ b/drivers/sensor/tsl2561/Kconfig @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Gustavo Silva +# SPDX-License-Identifier: Apache-2.0 + +config TSL2561 + bool "OSRAM-AMS TSL2561 light sensor" + default y + depends on DT_HAS_AMS_TSL2561_ENABLED + select I2C + help + Enable driver for TSL2561 sensor. diff --git a/drivers/sensor/tsl2561/tsl2561.c b/drivers/sensor/tsl2561/tsl2561.c new file mode 100644 index 00000000000..42efffb2242 --- /dev/null +++ b/drivers/sensor/tsl2561/tsl2561.c @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2023, Gustavo Silva + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ams_tsl2561 + +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(TSL2561, CONFIG_SENSOR_LOG_LEVEL); + +#define TSL2561_CHIP_ID 0x05 + +#define TSL2561_GAIN_1X 0x00 +#define TSL2561_GAIN_16X 0x01 + +#define TSL2561_INTEGRATION_13MS 0x00 +#define TSL2561_INTEGRATION_101MS 0x01 +#define TSL2561_INTEGRATION_402MS 0x02 + +/* Register set */ +#define TSL2561_REG_CONTROL 0x00 +#define TSL2561_REG_TIMING 0x01 +#define TSL2561_REG_THRESHLOWLOW 0x02 +#define TSL2561_REG_THRESHLOWHIGH 0x03 +#define TSL2561_REG_THRESHHIGHLOW 0x04 +#define TSL2561_REG_THRESHHIGHHIGH 0x05 +#define TSL2561_REG_INTERRUPT 0x06 +#define TSL2561_REG_ID 0x0A +#define TSL2561_REG_DATA0LOW 0x0C +#define TSL2561_REG_DATA0HIGH 0x0D +#define TSL2561_REG_DATA1LOW 0x0E +#define TSL2561_REG_DATA1HIGH 0x0F + +/* Command register fields */ +#define TSL2561_COMMAND_CMD BIT(7) +#define TSL2561_COMMAND_WORD BIT(5) + +/* Control register fields */ +#define TSL2561_CONTROL_POWER_UP 0x03 +#define TSL2561_CONTROL_POWER_DOWN 0x00 + +/* Timing register fields */ +#define TSL2561_TIMING_GAIN BIT(4) +#define TSL2561_TIMING_INTEG GENMASK(1, 0) + +/* ID register part number mask */ +#define TSL2561_ID_PARTNO GENMASK(7, 4) + +/* Lux calculation constants */ +#define TSL2561_LUX_SCALE 14U +#define TSL2561_RATIO_SCALE 9U +#define TSL2561_CH_SCALE 10U +#define TSL2561_CHSCALE_TINT0 0x7517 +#define TSL2561_CHSCALE_TINT1 0x0FE7 + +#define TSL2561_LUX_K1T 0X0040 /* 0.125 * 2^RATIO_SCALE */ +#define TSL2561_LUX_B1T 0X01F2 /* 0.0304 * 2^LUX_SCALE */ +#define TSL2561_LUX_M1T 0X01BE /* 0.0272 * 2^LUX_SCALE */ +#define TSL2561_LUX_K2T 0X0080 /* 0.250 * 2^RATIO_SCALE */ +#define TSL2561_LUX_B2T 0X0214 /* 0.0325 * 2^LUX_SCALE */ +#define TSL2561_LUX_M2T 0X02D1 /* 0.0440 * 2^LUX_SCALE */ +#define TSL2561_LUX_K3T 0X00C0 /* 0.375 * 2^RATIO_SCALE */ +#define TSL2561_LUX_B3T 0X023F /* 0.0351 * 2^LUX_SCALE */ +#define TSL2561_LUX_M3T 0X037B /* 0.0544 * 2^LUX_SCALE */ +#define TSL2561_LUX_K4T 0X0100 /* 0.50 * 2^RATIO_SCALE */ +#define TSL2561_LUX_B4T 0X0270 /* 0.0381 * 2^LUX_SCALE */ +#define TSL2561_LUX_M4T 0X03FE /* 0.0624 * 2^LUX_SCALE */ +#define TSL2561_LUX_K5T 0X0138 /* 0.61 * 2^RATIO_SCALE */ +#define TSL2561_LUX_B5T 0X016F /* 0.0224 * 2^LUX_SCALE */ +#define TSL2561_LUX_M5T 0X01FC /* 0.0310 * 2^LUX_SCALE */ +#define TSL2561_LUX_K6T 0X019A /* 0.80 * 2^RATIO_SCALE */ +#define TSL2561_LUX_B6T 0X00D2 /* 0.0128 * 2^LUX_SCALE */ +#define TSL2561_LUX_M6T 0X00FB /* 0.0153 * 2^LUX_SCALE */ +#define TSL2561_LUX_K7T 0X029A /* 1.3 * 2^RATIO_SCALE */ +#define TSL2561_LUX_B7T 0X0018 /* 0.00146 * 2^LUX_SCALE */ +#define TSL2561_LUX_M7T 0X0012 /* 0.00112 * 2^LUX_SCALE */ +#define TSL2561_LUX_K8T 0X029A /* 1.3 * 2^RATIO_SCALE */ +#define TSL2561_LUX_B8T 0X0000 /* 0.000 * 2^LUX_SCALE */ +#define TSL2561_LUX_M8T 0X0000 /* 0.000 * 2^LUX_SCALE */ + +struct tsl2561_config { + struct i2c_dt_spec i2c; + uint16_t integration_time; + uint8_t gain; +}; + +struct tsl2561_data { + uint16_t ch0; + uint16_t ch1; + uint32_t ch_scale; +}; + +static int tsl2561_reg_read(const struct device *dev, uint8_t reg, uint8_t *buf, uint8_t size) +{ + int ret; + const struct tsl2561_config *config = dev->config; + uint8_t cmd = (TSL2561_COMMAND_CMD | TSL2561_COMMAND_WORD | reg); + + ret = i2c_write_read_dt(&config->i2c, &cmd, 1U, buf, size); + if (ret < 0) { + LOG_ERR("Failed reading register 0x%02x", reg); + return ret; + } + + return 0; +} + +static int tsl2561_reg_write(const struct device *dev, uint8_t reg, uint8_t val) +{ + int ret; + const struct tsl2561_config *config = dev->config; + uint8_t buf[2]; + + buf[0] = (TSL2561_COMMAND_CMD | TSL2561_COMMAND_WORD | reg); + buf[1] = val; + + ret = i2c_write_dt(&config->i2c, buf, 2U); + if (ret < 0) { + LOG_ERR("Failed writing register 0x%02x", reg); + return ret; + } + + return 0; +} + +static int tsl2561_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + const struct tsl2561_config *config = dev->config; + struct tsl2561_data *data = dev->data; + uint8_t bytes[2]; + uint8_t ret; + + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_LIGHT) { + LOG_ERR("Unsupported sensor channel"); + return -ENOTSUP; + } + + ret = tsl2561_reg_write(dev, TSL2561_REG_CONTROL, TSL2561_CONTROL_POWER_UP); + if (ret < 0) { + LOG_ERR("Failed to power up device"); + return ret; + } + + /* Short sleep after power up. Not in the datasheet, but found by trial and error */ + k_msleep(5); + + k_msleep(config->integration_time); + + /* Read data register's lower and upper bytes consecutively */ + ret = tsl2561_reg_read(dev, TSL2561_REG_DATA0LOW, bytes, 2U); + if (ret < 0) { + LOG_ERR("Failed reading channel0 data"); + return ret; + } + data->ch0 = bytes[1] << 8 | bytes[0]; + + ret = tsl2561_reg_read(dev, TSL2561_REG_DATA1LOW, bytes, 2U); + if (ret < 0) { + LOG_ERR("Failed reading channel1 data"); + return ret; + } + data->ch1 = bytes[1] << 8 | bytes[0]; + + ret = tsl2561_reg_write(dev, TSL2561_REG_CONTROL, TSL2561_CONTROL_POWER_DOWN); + if (ret < 0) { + LOG_ERR("Failed to power down device"); + return ret; + } + + LOG_DBG("channel0: 0x%x; channel1: 0x%x", data->ch0, data->ch1); + + return 0; +} + +static int tsl2561_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + struct tsl2561_data *data = dev->data; + uint32_t channel0; + uint32_t channel1; + + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_LIGHT) { + return -ENOTSUP; + } + + channel0 = (data->ch0 * data->ch_scale) >> TSL2561_CH_SCALE; + channel1 = (data->ch1 * data->ch_scale) >> TSL2561_CH_SCALE; + + uint32_t ratio1 = 0; + + if (channel0 != 0) { + ratio1 = (channel1 << (TSL2561_RATIO_SCALE + 1)) / channel0; + } + + /* Round the ratio value */ + uint32_t ratio = (ratio1 + 1) >> 1; + + uint32_t b = 0; + uint32_t m = 0; + + if (ratio <= TSL2561_LUX_K1T) { + b = TSL2561_LUX_B1T; + m = TSL2561_LUX_M1T; + } else if (ratio <= TSL2561_LUX_K2T) { + b = TSL2561_LUX_B2T; + m = TSL2561_LUX_M2T; + } else if (ratio <= TSL2561_LUX_K3T) { + b = TSL2561_LUX_B3T; + m = TSL2561_LUX_M3T; + } else if (ratio <= TSL2561_LUX_K4T) { + b = TSL2561_LUX_B4T; + m = TSL2561_LUX_M4T; + } else if (ratio <= TSL2561_LUX_K5T) { + b = TSL2561_LUX_B5T; + m = TSL2561_LUX_M5T; + } else if (ratio <= TSL2561_LUX_K6T) { + b = TSL2561_LUX_B6T; + m = TSL2561_LUX_M6T; + } else if (ratio <= TSL2561_LUX_K7T) { + b = TSL2561_LUX_B7T; + m = TSL2561_LUX_M7T; + } else if (ratio > TSL2561_LUX_K8T) { + b = TSL2561_LUX_B8T; + m = TSL2561_LUX_M8T; + } + + int32_t tmp = ((channel0 * b) - (channel1 * m)); + + /* Round LSB (2^(LUX_SCALE−1)) */ + tmp += (1 << (TSL2561_LUX_SCALE - 1)); + + /* Strip off fractional portion */ + val->val1 = tmp >> TSL2561_LUX_SCALE; + + val->val2 = 0; + + return 0; +} + +static const struct sensor_driver_api tsl2561_driver_api = { + .sample_fetch = tsl2561_sample_fetch, + .channel_get = tsl2561_channel_get +}; + +static int tsl2561_sensor_setup(const struct device *dev) +{ + const struct tsl2561_config *config = dev->config; + struct tsl2561_data *data = dev->data; + uint8_t timing_reg; + uint8_t chip_id; + uint8_t tmp; + int ret; + + ret = tsl2561_reg_read(dev, TSL2561_REG_ID, &chip_id, 1U); + if (ret < 0) { + LOG_ERR("Failed reading chip ID"); + return ret; + } + + if (FIELD_GET(TSL2561_ID_PARTNO, chip_id) != TSL2561_CHIP_ID) { + LOG_ERR("Chip ID is invalid! Device @%02x is not TSL2561!", config->i2c.addr); + return -EIO; + } + + switch (config->integration_time) { + case 13: + tmp = TSL2561_INTEGRATION_13MS; + data->ch_scale = TSL2561_CHSCALE_TINT0; + break; + case 101: + tmp = TSL2561_INTEGRATION_101MS; + data->ch_scale = TSL2561_CHSCALE_TINT1; + break; + case 402: + tmp = TSL2561_INTEGRATION_402MS; + data->ch_scale = (1 << TSL2561_CH_SCALE); + break; + default: + LOG_ERR("Invalid integration time"); + return -EINVAL; + } + + timing_reg = TSL2561_TIMING_INTEG & tmp; + + switch (config->gain) { + case 1: + tmp = TSL2561_GAIN_1X; + data->ch_scale = data->ch_scale << 4; + break; + case 16: + tmp = TSL2561_GAIN_16X; + break; + default: + LOG_ERR("Invalid ADC gain"); + return -EINVAL; + } + + timing_reg |= FIELD_PREP(TSL2561_TIMING_GAIN, tmp); + + ret = tsl2561_reg_write(dev, TSL2561_REG_TIMING, timing_reg); + if (ret < 0) { + LOG_ERR("Failed setting timing register"); + return ret; + } + + return 0; +} + +static int tsl2561_init(const struct device *dev) +{ + const struct tsl2561_config *config = dev->config; + int ret; + + if (!i2c_is_ready_dt(&config->i2c)) { + LOG_ERR("I2C dev %s not ready", config->i2c.bus->name); + return -ENODEV; + } + + ret = tsl2561_sensor_setup(dev); + if (ret < 0) { + LOG_ERR("Failed to configure device"); + return ret; + } + + return 0; +} + +#define TSL2561_INIT_INST(n) \ + static struct tsl2561_data tsl2561_data_##n; \ + static const struct tsl2561_config tsl2561_config_##n = { \ + .i2c = I2C_DT_SPEC_INST_GET(n), \ + .integration_time = DT_INST_PROP(n, integration_time), \ + .gain = DT_INST_PROP(n, gain)}; \ + SENSOR_DEVICE_DT_INST_DEFINE(n, tsl2561_init, NULL, &tsl2561_data_##n, \ + &tsl2561_config_##n, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &tsl2561_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(TSL2561_INIT_INST) diff --git a/drivers/sensor/vcnl4040/Kconfig b/drivers/sensor/vcnl4040/Kconfig index 5973316ca6a..a4e6be8d715 100644 --- a/drivers/sensor/vcnl4040/Kconfig +++ b/drivers/sensor/vcnl4040/Kconfig @@ -21,7 +21,7 @@ config VCNL4040_ENABLE_ALS config VCNL4040_TRIGGER bool -choice +choice VCNL4040_TRIGGER prompt "Trigger mode" default VCNL4040_TRIGGER_NONE help diff --git a/drivers/sensor/vcnl4040/vcnl4040.h b/drivers/sensor/vcnl4040/vcnl4040.h index 755d9de31af..1341375f71b 100644 --- a/drivers/sensor/vcnl4040/vcnl4040.h +++ b/drivers/sensor/vcnl4040/vcnl4040.h @@ -118,7 +118,7 @@ struct vcnl4040_data { const struct sensor_trigger *als_trigger; #endif #ifdef CONFIG_VCNL4040_TRIGGER_OWN_THREAD - K_THREAD_STACK_MEMBER(thread_stack, CONFIG_VCNL4040_THREAD_STACK_SIZE); + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_VCNL4040_THREAD_STACK_SIZE); struct k_thread thread; struct k_sem trig_sem; #endif diff --git a/drivers/sensor/vcnl4040/vcnl4040_trigger.c b/drivers/sensor/vcnl4040/vcnl4040_trigger.c index f47d70d0b39..f2680b0b8be 100644 --- a/drivers/sensor/vcnl4040/vcnl4040_trigger.c +++ b/drivers/sensor/vcnl4040/vcnl4040_trigger.c @@ -86,8 +86,13 @@ static void vcnl4040_handle_int(const struct device *dev) } #ifdef CONFIG_VCNL4040_TRIGGER_OWN_THREAD -static void vcnl4040_thread_main(struct vcnl4040_data *data) +static void vcnl4040_thread_main(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct vcnl4040_data *data = p1; + while (true) { k_sem_take(&data->trig_sem, K_FOREVER); vcnl4040_handle_int(data->dev); @@ -266,7 +271,7 @@ int vcnl4040_trigger_init(const struct device *dev) k_sem_init(&data->trig_sem, 0, K_SEM_MAX_LIMIT); k_thread_create(&data->thread, data->thread_stack, CONFIG_VCNL4040_THREAD_STACK_SIZE, - (k_thread_entry_t)vcnl4040_thread_main, + vcnl4040_thread_main, data, NULL, NULL, K_PRIO_COOP(CONFIG_VCNL4040_THREAD_PRIORITY), 0, K_NO_WAIT); diff --git a/drivers/sensor/veml7700/veml7700.c b/drivers/sensor/veml7700/veml7700.c index 7f00e3fd14c..e008b725167 100644 --- a/drivers/sensor/veml7700/veml7700.c +++ b/drivers/sensor/veml7700/veml7700.c @@ -14,7 +14,7 @@ #include #include -#include "zephyr/drivers/sensor/veml7700.h" +#include LOG_MODULE_REGISTER(VEML7700, CONFIG_SENSOR_LOG_LEVEL); diff --git a/drivers/sensor/vl53l0x/vl53l0x.c b/drivers/sensor/vl53l0x/vl53l0x.c index 33143656443..bd822e9e6f2 100644 --- a/drivers/sensor/vl53l0x/vl53l0x.c +++ b/drivers/sensor/vl53l0x/vl53l0x.c @@ -28,9 +28,9 @@ LOG_MODULE_REGISTER(VL53L0X, CONFIG_SENSOR_LOG_LEVEL); /* All the values used in this driver are coming from ST datasheet and examples. * It can be found here: - * http://www.st.com/en/embedded-software/stsw-img005.html + * https://www.st.com/en/embedded-software/stsw-img005.html * There are also examples of use in the L4 cube FW: - * http://www.st.com/en/embedded-software/stm32cubel4.html + * https://www.st.com/en/embedded-software/stm32cubel4.html */ #define VL53L0X_INITIAL_ADDR 0x29 #define VL53L0X_REG_WHO_AM_I 0xC0 @@ -300,36 +300,6 @@ static const struct sensor_driver_api vl53l0x_api_funcs = { .channel_get = vl53l0x_channel_get, }; -#ifdef CONFIG_PM_DEVICE -static int vl53l0x_pm_action(const struct device *dev, - enum pm_device_action action) -{ - const struct vl53l0x_config *const config = dev->config; - int ret; - - switch (action) { - case PM_DEVICE_ACTION_RESUME: - ret = gpio_pin_set_dt(&config->xshut, 0); - if (ret < 0) { - LOG_ERR("[%s] XSHUT pin inactive", dev->name); - return ret; - } - break; - case PM_DEVICE_ACTION_SUSPEND: - ret = gpio_pin_set_dt(&config->xshut, 1); - if (ret < 0) { - LOG_ERR("[%s] XSHUT pin active", dev->name); - return ret; - } - break; - default: - return -ENOTSUP; - } - - return 0; -} -#endif - static int vl53l0x_init(const struct device *dev) { int r; @@ -378,6 +348,36 @@ static int vl53l0x_init(const struct device *dev) return 0; } +#ifdef CONFIG_PM_DEVICE +static int vl53l0x_pm_action(const struct device *dev, + enum pm_device_action action) +{ + const struct vl53l0x_config *const config = dev->config; + int ret; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + ret = vl53l0x_init(dev); + if (ret != 0) { + LOG_ERR("resume init: %d", ret); + } + break; + case PM_DEVICE_ACTION_SUSPEND: + /* HW Standby */ + ret = gpio_pin_set_dt(&config->xshut, 1); + if (ret < 0) { + LOG_ERR("[%s] XSHUT pin active", dev->name); + } + break; + default: + ret = -ENOTSUP; + break; + } + + return ret; +} +#endif + #define VL53L0X_INIT(inst) \ static struct vl53l0x_config vl53l0x_##inst##_config = { \ .i2c = I2C_DT_SPEC_INST_GET(inst), \ diff --git a/drivers/sensor/vl53l1x/vl53l1.c b/drivers/sensor/vl53l1x/vl53l1.c index 714007a1a71..35187423342 100644 --- a/drivers/sensor/vl53l1x/vl53l1.c +++ b/drivers/sensor/vl53l1x/vl53l1.c @@ -65,59 +65,56 @@ static VL53L1_Error vl53l1x_read_sensor(struct vl53l1x_data *drv_data) return VL53L1_ERROR_NONE; } +#ifdef CONFIG_VL53L1X_INTERRUPT_MODE static void vl53l1x_worker(struct k_work *work) { - if (IS_ENABLED(CONFIG_VL53L1X_INTERRUPT_MODE)) { - struct vl53l1x_data *drv_data = CONTAINER_OF(work, struct vl53l1x_data, work); + struct vl53l1x_data *drv_data = CONTAINER_OF(work, struct vl53l1x_data, work); - vl53l1x_read_sensor(drv_data); - } + vl53l1x_read_sensor(drv_data); } static void vl53l1x_gpio_callback(const struct device *dev, struct gpio_callback *cb, uint32_t pins) { - if (IS_ENABLED(CONFIG_VL53L1X_INTERRUPT_MODE)) { - struct vl53l1x_data *drv_data = CONTAINER_OF(cb, struct vl53l1x_data, gpio_cb); + struct vl53l1x_data *drv_data = CONTAINER_OF(cb, struct vl53l1x_data, gpio_cb); - k_work_submit(&drv_data->work); - } + k_work_submit(&drv_data->work); } static int vl53l1x_init_interrupt(const struct device *dev) { - if (IS_ENABLED(CONFIG_VL53L1X_INTERRUPT_MODE)) { - struct vl53l1x_data *drv_data = dev->data; - const struct vl53l1x_config *config = dev->config; - int ret; - - drv_data->dev = dev; + struct vl53l1x_data *drv_data = dev->data; + const struct vl53l1x_config *config = dev->config; + int ret; - if (!gpio_is_ready_dt(&config->gpio1)) { - LOG_ERR("%s: device %s is not ready", dev->name, config->gpio1.port->name); - return -ENODEV; - } + drv_data->dev = dev; - ret = gpio_pin_configure_dt(&config->gpio1, GPIO_INPUT | GPIO_PULL_UP); - if (ret < 0) { - LOG_ERR("[%s] Unable to configure GPIO interrupt", dev->name); - return -EIO; - } + if (!gpio_is_ready_dt(&config->gpio1)) { + LOG_ERR("%s: device %s is not ready", dev->name, config->gpio1.port->name); + return -ENODEV; + } - gpio_init_callback(&drv_data->gpio_cb, - vl53l1x_gpio_callback, - BIT(config->gpio1.pin)); + ret = gpio_pin_configure_dt(&config->gpio1, GPIO_INPUT | GPIO_PULL_UP); + if (ret < 0) { + LOG_ERR("[%s] Unable to configure GPIO interrupt", dev->name); + return -EIO; + } - ret = gpio_add_callback(config->gpio1.port, &drv_data->gpio_cb); - if (ret < 0) { - LOG_ERR("Failed to set gpio callback!"); - return -EIO; - } + gpio_init_callback(&drv_data->gpio_cb, + vl53l1x_gpio_callback, + BIT(config->gpio1.pin)); - drv_data->work.handler = vl53l1x_worker; + ret = gpio_add_callback(config->gpio1.port, &drv_data->gpio_cb); + if (ret < 0) { + LOG_ERR("Failed to set gpio callback!"); + return -EIO; } + + drv_data->work.handler = vl53l1x_worker; + return 0; } +#endif static int vl53l1x_initialize(const struct device *dev) { @@ -304,7 +301,6 @@ static int vl53l1x_sample_fetch(const struct device *dev, enum sensor_channel chan) { struct vl53l1x_data *drv_data = dev->data; - const struct vl53l1x_config *config = dev->config; VL53L1_Error ret; __ASSERT_NO_MSG((chan == SENSOR_CHAN_ALL) @@ -317,13 +313,15 @@ static int vl53l1x_sample_fetch(const struct device *dev, return -EBUSY; } - if (IS_ENABLED(CONFIG_VL53L1X_INTERRUPT_MODE)) { - ret = gpio_pin_interrupt_configure_dt(&config->gpio1, GPIO_INT_EDGE_TO_INACTIVE); - if (ret < 0) { - LOG_ERR("[%s] Unable to config interrupt", dev->name); - return -EIO; - } +#ifdef CONFIG_VL53L1X_INTERRUPT_MODE + const struct vl53l1x_config *config = dev->config; + + ret = gpio_pin_interrupt_configure_dt(&config->gpio1, GPIO_INT_EDGE_TO_INACTIVE); + if (ret < 0) { + LOG_ERR("[%s] Unable to config interrupt", dev->name); + return -EIO; } +#endif ret = VL53L1_StartMeasurement(&drv_data->vl53l1x); if (ret != VL53L1_ERROR_NONE) { diff --git a/drivers/sensor/voltage_divider/CMakeLists.txt b/drivers/sensor/voltage_divider/CMakeLists.txt new file mode 100644 index 00000000000..ec2af44de5c --- /dev/null +++ b/drivers/sensor/voltage_divider/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(voltage.c) diff --git a/drivers/sensor/voltage_divider/Kconfig b/drivers/sensor/voltage_divider/Kconfig new file mode 100644 index 00000000000..19027aa9361 --- /dev/null +++ b/drivers/sensor/voltage_divider/Kconfig @@ -0,0 +1,13 @@ +# Voltage sensor driver +# +# Copyright (c) 2023 FTP Technologies +# +# SPDX-License-Identifier: Apache-2.0 + +config VOLTAGE_DIVIDER + bool "Voltage sensor driver" + default y + depends on DT_HAS_VOLTAGE_DIVIDER_ENABLED + depends on ADC + help + Enable voltage sensor driver. diff --git a/drivers/sensor/voltage_divider/voltage.c b/drivers/sensor/voltage_divider/voltage.c new file mode 100644 index 00000000000..ef2b34c74b3 --- /dev/null +++ b/drivers/sensor/voltage_divider/voltage.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2023 FTP Technologies + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT voltage_divider + +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(voltage, CONFIG_SENSOR_LOG_LEVEL); + +struct voltage_config { + struct voltage_divider_dt_spec voltage; +#ifdef CONFIG_PM_DEVICE + struct gpio_dt_spec gpio_power; +#endif +}; + +struct voltage_data { + struct adc_sequence sequence; + int16_t raw; +}; + +static int fetch(const struct device *dev, enum sensor_channel chan) +{ + const struct voltage_config *config = dev->config; + struct voltage_data *data = dev->data; + int ret; + + if ((chan != SENSOR_CHAN_VOLTAGE) && (chan != SENSOR_CHAN_ALL)) { + return -ENOTSUP; + } + + ret = adc_read(config->voltage.port.dev, &data->sequence); + if (ret != 0) { + LOG_ERR("adc_read: %d", ret); + } + + return ret; +} + +static int get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) +{ + const struct voltage_config *config = dev->config; + struct voltage_data *data = dev->data; + int32_t raw_val = data->raw; + int32_t v_mv; + int ret; + + __ASSERT_NO_MSG(val != NULL); + + if (chan != SENSOR_CHAN_VOLTAGE) { + return -ENOTSUP; + } + + ret = adc_raw_to_millivolts_dt(&config->voltage.port, &raw_val); + if (ret != 0) { + LOG_ERR("raw_to_mv: %d", ret); + return ret; + } + + v_mv = raw_val; + + /* Note if full_ohms is not specified then unscaled voltage is returned */ + (void)voltage_divider_scale_dt(&config->voltage, &v_mv); + + LOG_DBG("%d of %d, %dmV, voltage:%dmV", data->raw, + (1 << data->sequence.resolution) - 1, raw_val, v_mv); + val->val1 = v_mv / 1000; + val->val2 = (v_mv * 1000) % 1000000; + + return ret; +} + +static const struct sensor_driver_api voltage_api = { + .sample_fetch = fetch, + .channel_get = get, +}; + +#ifdef CONFIG_PM_DEVICE +static int pm_action(const struct device *dev, enum pm_device_action action) +{ + const struct voltage_config *config = dev->config; + int ret; + + if (config->gpio_power.port == NULL) { + LOG_ERR("PM not supported"); + return -ENOTSUP; + } + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + ret = gpio_pin_set_dt(&config->gpio_power, 1); + if (ret != 0) { + LOG_ERR("failed to set GPIO for PM resume"); + } + break; + case PM_DEVICE_ACTION_SUSPEND: + ret = gpio_pin_set_dt(&config->gpio_power, 0); + if (ret != 0) { + LOG_ERR("failed to set GPIO for PM suspend"); + } + break; + default: + return -ENOTSUP; + } + + return ret; +} +#endif + +static int voltage_init(const struct device *dev) +{ + const struct voltage_config *config = dev->config; + struct voltage_data *data = dev->data; + int ret; + + if (!adc_is_ready_dt(&config->voltage.port)) { + LOG_ERR("ADC is not ready"); + return -ENODEV; + } + +#ifdef CONFIG_PM_DEVICE + if (config->gpio_power.port != NULL) { + if (!gpio_is_ready_dt(&config->gpio_power)) { + LOG_ERR("Power GPIO is not ready"); + return -ENODEV; + } + + ret = gpio_pin_configure_dt(&config->gpio_power, GPIO_OUTPUT_ACTIVE); + if (ret != 0) { + LOG_ERR("failed to initialize GPIO for reset"); + } + } +#endif + + ret = adc_channel_setup_dt(&config->voltage.port); + if (ret != 0) { + LOG_ERR("setup: %d", ret); + return ret; + } + + ret = adc_sequence_init_dt(&config->voltage.port, &data->sequence); + if (ret != 0) { + LOG_ERR("sequence init: %d", ret); + return ret; + } + + data->sequence.buffer = &data->raw; + data->sequence.buffer_size = sizeof(data->raw); + + return 0; +} + +#ifdef CONFIG_PM_DEVICE +#define POWER_GPIOS(inst) .gpio_power = GPIO_DT_SPEC_INST_GET_OR(inst, power_gpios, {0}), +#else +#define POWER_GPIOS(inst) +#endif + +#define VOLTAGE_INIT(inst) \ + static struct voltage_data voltage_##inst##_data; \ + \ + static const struct voltage_config voltage_##inst##_config = { \ + .voltage = VOLTAGE_DIVIDER_DT_SPEC_GET(DT_DRV_INST(inst)), \ + POWER_GPIOS(inst) \ + }; \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, pm_action); \ + \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, &voltage_init, PM_DEVICE_DT_INST_GET(inst), \ + &voltage_##inst##_data, &voltage_##inst##_config, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &voltage_api); + +DT_INST_FOREACH_STATUS_OKAY(VOLTAGE_INIT) diff --git a/drivers/sensor/wsen_hids/wsen_hids_trigger.c b/drivers/sensor/wsen_hids/wsen_hids_trigger.c index 2de3b04c821..e8c9472f5cd 100644 --- a/drivers/sensor/wsen_hids/wsen_hids_trigger.c +++ b/drivers/sensor/wsen_hids/wsen_hids_trigger.c @@ -89,8 +89,13 @@ static void hids_drdy_callback(const struct device *dev, struct gpio_callback *c } #ifdef CONFIG_WSEN_HIDS_TRIGGER_OWN_THREAD -static void hids_thread(struct hids_data *data) +static void hids_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct hids_data *data = p1; + while (true) { k_sem_take(&data->drdy_sem, K_FOREVER); hids_process_drdy_interrupt(data->dev); @@ -151,7 +156,7 @@ int hids_init_interrupt(const struct device *dev) k_sem_init(&data->drdy_sem, 0, K_SEM_MAX_LIMIT); k_thread_create(&data->thread, data->thread_stack, CONFIG_WSEN_HIDS_THREAD_STACK_SIZE, - (k_thread_entry_t)hids_thread, data, NULL, NULL, + hids_thread, data, NULL, NULL, K_PRIO_COOP(CONFIG_WSEN_HIDS_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_WSEN_HIDS_TRIGGER_GLOBAL_THREAD) data->work.handler = hids_work_cb; diff --git a/drivers/sensor/wsen_pads/wsen_pads_trigger.c b/drivers/sensor/wsen_pads/wsen_pads_trigger.c index a00fae8de16..13394e23d9a 100644 --- a/drivers/sensor/wsen_pads/wsen_pads_trigger.c +++ b/drivers/sensor/wsen_pads/wsen_pads_trigger.c @@ -112,8 +112,13 @@ static void pads_drdy_callback(const struct device *dev, struct gpio_callback *c } #ifdef CONFIG_WSEN_PADS_TRIGGER_OWN_THREAD -static void pads_thread(struct pads_data *data) +static void pads_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct pads_data *data = p1; + while (true) { k_sem_take(&data->drdy_sem, K_FOREVER); pads_process_drdy_interrupt(data->dev); @@ -168,7 +173,7 @@ int pads_init_interrupt(const struct device *dev) k_sem_init(&data->drdy_sem, 0, K_SEM_MAX_LIMIT); k_thread_create(&data->thread, data->thread_stack, CONFIG_WSEN_PADS_THREAD_STACK_SIZE, - (k_thread_entry_t)pads_thread, data, NULL, NULL, + pads_thread, data, NULL, NULL, K_PRIO_COOP(CONFIG_WSEN_PADS_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_WSEN_PADS_TRIGGER_GLOBAL_THREAD) data->work.handler = pads_work_cb; diff --git a/drivers/sensor/wsen_tids/wsen_tids_trigger.c b/drivers/sensor/wsen_tids/wsen_tids_trigger.c index 9b7837d2a9a..d2ed4d91fef 100644 --- a/drivers/sensor/wsen_tids/wsen_tids_trigger.c +++ b/drivers/sensor/wsen_tids/wsen_tids_trigger.c @@ -118,8 +118,13 @@ static void tids_threshold_callback(const struct device *dev, struct gpio_callba } #ifdef CONFIG_WSEN_TIDS_TRIGGER_OWN_THREAD -static void tids_thread(struct tids_data *tids) +static void tids_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct tids_data *tids = p1; + while (true) { k_sem_take(&tids->threshold_sem, K_FOREVER); tids_process_threshold_interrupt(tids->dev); @@ -226,7 +231,7 @@ int tids_init_interrupt(const struct device *dev) k_sem_init(&data->threshold_sem, 0, K_SEM_MAX_LIMIT); k_thread_create(&data->thread, data->thread_stack, CONFIG_WSEN_TIDS_THREAD_STACK_SIZE, - (k_thread_entry_t)tids_thread, data, NULL, NULL, + tids_thread, data, NULL, NULL, K_PRIO_COOP(CONFIG_WSEN_TIDS_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_WSEN_TIDS_TRIGGER_GLOBAL_THREAD) data->work.handler = tids_work_cb; diff --git a/drivers/serial/CMakeLists.txt b/drivers/serial/CMakeLists.txt index de3ec08af8b..bfc38603864 100644 --- a/drivers/serial/CMakeLists.txt +++ b/drivers/serial/CMakeLists.txt @@ -64,6 +64,10 @@ zephyr_library_sources_ifdef(CONFIG_UART_EMUL uart_emul.c) zephyr_library_sources_ifdef(CONFIG_UART_NUMAKER uart_numaker.c) zephyr_library_sources_ifdef(CONFIG_UART_EFINIX_SAPPIHIRE uart_efinix_sapphire.c) zephyr_library_sources_ifdef(CONFIG_UART_SEDI uart_sedi.c) +zephyr_library_sources_ifdef(CONFIG_UART_BCM2711_MU uart_bcm2711.c) +zephyr_library_sources_ifdef(CONFIG_UART_INTEL_LW uart_intel_lw.c) +zephyr_library_sources_ifdef(CONFIG_UART_RA uart_ra.c) +zephyr_library_sources_ifdef(CONFIG_UART_RZT2M uart_rzt2m.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE uart_handlers.c) @@ -80,6 +84,12 @@ endif() if(CONFIG_UART_NATIVE_TTY) zephyr_library_compile_definitions(NO_POSIX_CHEATS) zephyr_library_sources(uart_native_tty.c) + if (CONFIG_NATIVE_APPLICATION) + zephyr_library_sources(uart_native_tty_bottom.c) + else() + target_sources(native_simulator INTERFACE uart_native_tty_bottom.c) + endif() endif() zephyr_library_sources_ifdef(CONFIG_SERIAL_TEST serial_test.c) +zephyr_library_sources_ifdef(CONFIG_UART_ASYNC_RX_HELPER uart_async_rx.c) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 39156777336..5eb183c9a3e 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -125,6 +125,14 @@ config UART_PIPE data (as contrary to console UART driver) and all aspects of received protocol data are handled by application provided callback. +config UART_ASYNC_RX_HELPER + bool "Helper for UART asynchronous reception" + help + Module implements handling of reception of variable length data using + Asynchronous UART API. It can be used in cases where received data processing + is delayed. Module implements zero-copy approach with multiple reception + buffers. + comment "Serial Drivers" source "drivers/serial/Kconfig.b91" @@ -241,4 +249,12 @@ source "drivers/serial/Kconfig.efinix_sapphire" source "drivers/serial/Kconfig.sedi" +source "drivers/serial/Kconfig.bcm2711" + +source "drivers/serial/Kconfig.intel_lw" + +source "drivers/serial/Kconfig.ra" + +source "drivers/serial/Kconfig.rzt2m" + endif # SERIAL diff --git a/drivers/serial/Kconfig.bcm2711 b/drivers/serial/Kconfig.bcm2711 new file mode 100644 index 00000000000..8f60fcf0b7f --- /dev/null +++ b/drivers/serial/Kconfig.bcm2711 @@ -0,0 +1,11 @@ +# Copyright (c) 2023 honglin leng +# SPDX-License-Identifier: Apache-2.0 + +config UART_BCM2711_MU + bool "bcm2711_mu" + default y + depends on DT_HAS_BRCM_BCM2711_AUX_UART_ENABLED + select SERIAL_HAS_DRIVER + select SERIAL_SUPPORT_INTERRUPT + help + bcm2711_mu Low Power Serial Port. diff --git a/drivers/serial/Kconfig.emul b/drivers/serial/Kconfig.emul index 67134b9485c..b5362eb79ee 100644 --- a/drivers/serial/Kconfig.emul +++ b/drivers/serial/Kconfig.emul @@ -7,7 +7,20 @@ config UART_EMUL bool "Emulated UART driver [EXPERIMENTAL]" default y depends on DT_HAS_ZEPHYR_UART_EMUL_ENABLED + select SERIAL_SUPPORT_INTERRUPT select RING_BUFFER select EXPERIMENTAL help Enable the emulated UART driver. + +if UART_EMUL + +config UART_EMUL_WORK_Q_STACK_SIZE + int "UART emulator work queue stack size" + default 2048 + +config UART_EMUL_WORK_Q_PRIORITY + int "UART emulator work queue tread priority" + default 1 + +endif # UART_EMUL diff --git a/drivers/serial/Kconfig.intel_lw b/drivers/serial/Kconfig.intel_lw new file mode 100644 index 00000000000..478af03cf81 --- /dev/null +++ b/drivers/serial/Kconfig.intel_lw @@ -0,0 +1,30 @@ +# Copyright (c) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +menuconfig UART_INTEL_LW + bool "Intel Lightweight UART driver" + depends on DT_HAS_INTEL_LW_UART_ENABLED + select SERIAL_HAS_DRIVER + select SERIAL_SUPPORT_INTERRUPT + help + Enable the Intel Lightweight UART driver, that can be built into Intel NiosV CPU designs. + +if UART_INTEL_LW + +config UART_INTEL_LW_EOP + bool "Include end of packet register" + depends on UART_DRV_CMD && UART_INTERRUPT_DRIVEN + help + Use driver command CMD_ENABLE_EOP and CMD_DISABLE_EOP to use the feature. + +config UART_INTEL_LW_AUTO_LINE_CTRL_POLL + bool "Auto set RTS signal during poll out" + depends on UART_LINE_CTRL + help + Assert RTS before polling out a character, + and deassert RTS after the character is polled out. + Please note that this is not suitable, when polling out several characters. + Please use uart_drv_cmd with CMD_POLL_ASSERT_RTS before polling out. + Then use CMD_POLL_DEASSERT_RTS to resume normal operation after polling. + +endif # UART_INTEL_LW diff --git a/drivers/serial/Kconfig.it8xxx2 b/drivers/serial/Kconfig.it8xxx2 index 0a7a59ce08d..f89874fef41 100644 --- a/drivers/serial/Kconfig.it8xxx2 +++ b/drivers/serial/Kconfig.it8xxx2 @@ -4,6 +4,7 @@ config UART_ITE_IT8XXX2 bool "ITE IT8XXX2 UART driver" default y + select UART_NS16550_ITE_HIGH_SPEED_BUADRATE depends on DT_HAS_ITE_IT8XXX2_UART_ENABLED help IT8XXX2 uses shared ns16550.c driver which does not diff --git a/drivers/serial/Kconfig.nrfx b/drivers/serial/Kconfig.nrfx index c9c9d687a00..53553e3d06e 100644 --- a/drivers/serial/Kconfig.nrfx +++ b/drivers/serial/Kconfig.nrfx @@ -9,6 +9,7 @@ menuconfig UART_NRFX select SERIAL_HAS_DRIVER select SERIAL_SUPPORT_INTERRUPT select SERIAL_SUPPORT_ASYNC + select PINCTRL depends on DT_HAS_NORDIC_NRF_UART_ENABLED || DT_HAS_NORDIC_NRF_UARTE_ENABLED help Enable support for nrfx UART drivers for nRF MCU series. @@ -35,291 +36,25 @@ config UART_ASYNC_TX_CACHE_SIZE in RAM, because EasyDMA in UARTE peripherals can only transfer data from RAM. -# ----------------- port 0 ----------------- if HAS_HW_NRF_UART0 || HAS_HW_NRF_UARTE0 +nrfx_uart_num = 0 +rsource "Kconfig.nrfx_uart_instance" +endif -config UART_0_ENHANCED_POLL_OUT - bool "Efficient poll out on port 0" - default y - depends on HAS_HW_NRF_UARTE0 - help - When enabled, polling out does not trigger interrupt which stops TX. - Feature uses a PPI channel. - -config UART_0_INTERRUPT_DRIVEN - bool "Interrupt support on port 0" - depends on UART_INTERRUPT_DRIVEN - default y - help - This option enables UART interrupt support on port 0. - -config UART_0_ASYNC - bool "Asynchronous API support on port 0" - depends on UART_ASYNC_API && !UART_0_INTERRUPT_DRIVEN - default y - help - This option enables UART Asynchronous API support on port 0. - -config UART_0_NRF_PARITY_BIT - bool "Parity bit" - help - Enable parity bit. - -config UART_0_NRF_TX_BUFFER_SIZE - int "Size of RAM buffer" - depends on HAS_HW_NRF_UARTE0 - range 1 65535 - default 32 - help - Size of the transmit buffer for API function: fifo_fill. - This value is limited by range of TXD.MAXCNT register for - particular SoC. - -config UART_0_NRF_HW_ASYNC - bool "Use hardware RX byte counting" - depends on HAS_HW_NRF_UARTE0 - depends on UART_ASYNC_API - help - If default driver uses interrupts to count incoming bytes, it is possible - that with higher speeds and/or high cpu load some data can be lost. - It is recommended to use hardware byte counting in such scenarios. - Hardware RX byte counting requires timer instance and one PPI channel - -config UART_0_NRF_ASYNC_LOW_POWER - bool "Low power mode" - depends on HAS_HW_NRF_UARTE0 - depends on UART_ASYNC_API - help - When enabled, UARTE is enabled before each TX or RX usage and disabled - when not used. Disabling UARTE while in idle allows to achieve lowest - power consumption. It is only feasible if receiver is not always on. - -config UART_0_NRF_HW_ASYNC_TIMER - int "Timer instance" - depends on UART_0_NRF_HW_ASYNC - -config UART_0_GPIO_MANAGEMENT - bool "GPIO management on port 0" - depends on PM_DEVICE - default y - help - If enabled, the driver will configure the GPIOs used by the uart to - their default configuration when device is powered down. The GPIOs - will be configured back to correct state when UART is powered up. - -endif # HAS_HW_NRF_UART0 || HAS_HW_NRF_UARTE0 - -# ----------------- port 1 ----------------- if HAS_HW_NRF_UARTE1 +nrfx_uart_num = 1 +rsource "Kconfig.nrfx_uart_instance" +endif -config UART_1_INTERRUPT_DRIVEN - bool "Interrupt support on port 1" - depends on UART_INTERRUPT_DRIVEN - default y - help - This option enables UART interrupt support on port 1. - -config UART_1_ASYNC - bool "Asynchronous API support on port 1" - depends on UART_ASYNC_API && !UART_1_INTERRUPT_DRIVEN - default y - help - This option enables UART Asynchronous API support on port 1. - -config UART_1_ENHANCED_POLL_OUT - bool "Efficient poll out on port 1" - default y - help - When enabled, polling out does not trigger interrupt which stops TX. - Feature uses a PPI channel. - -config UART_1_NRF_PARITY_BIT - bool "Parity bit" - help - Enable parity bit. - -config UART_1_NRF_TX_BUFFER_SIZE - int "Size of RAM buffer" - depends on UART_INTERRUPT_DRIVEN - range 1 65535 - default 32 - help - Size of the transmit buffer for API function: fifo_fill. - This value is limited by range of TXD.MAXCNT register for - particular SoC. - -config UART_1_NRF_HW_ASYNC - bool "Use hardware RX byte counting" - depends on UART_1_ASYNC - help - If default driver uses interrupts to count incoming bytes, it is possible - that with higher speeds and/or high cpu load some data can be lost. - It is recommended to use hardware byte counting in such scenarios. - Hardware RX byte counting requires timer instance and one PPI channel - -config UART_1_NRF_ASYNC_LOW_POWER - bool "Low power mode" - depends on UART_ASYNC_API - help - When enabled, UARTE is enabled before each TX or RX usage and disabled - when not used. Disabling UARTE while in idle allows to achieve lowest - power consumption. It is only feasible if receiver is not always on. - -config UART_1_NRF_HW_ASYNC_TIMER - int "Timer instance" - depends on UART_1_NRF_HW_ASYNC - -config UART_1_GPIO_MANAGEMENT - bool "GPIO management on port 1" - depends on PM_DEVICE - default y - help - If enabled, the driver will configure the GPIOs used by the uart to - their default configuration when device is powered down. The GPIOs - will be configured back to correct state when UART is powered up. - -endif # HAS_HW_NRF_UARTE1 - -# ----------------- port 2 ----------------- if HAS_HW_NRF_UARTE2 +nrfx_uart_num = 2 +rsource "Kconfig.nrfx_uart_instance" +endif -config UART_2_INTERRUPT_DRIVEN - bool "Interrupt support on port 2" - depends on UART_INTERRUPT_DRIVEN - default y - help - This option enables UART interrupt support on port 2. - -config UART_2_ASYNC - bool "Asynchronous API support on port 2" - depends on UART_ASYNC_API && !UART_2_INTERRUPT_DRIVEN - default y - help - This option enables UART Asynchronous API support on port 2. - -config UART_2_ENHANCED_POLL_OUT - bool "Efficient poll out on port 2" - default y - help - When enabled, polling out does not trigger interrupt which stops TX. - Feature uses a PPI channel. - -config UART_2_NRF_PARITY_BIT - bool "Parity bit" - help - Enable parity bit. - -config UART_2_NRF_TX_BUFFER_SIZE - int "Size of RAM buffer" - range 1 65535 - default 32 - help - Size of the transmit buffer for API function: fifo_fill. - This value is limited by range of TXD.MAXCNT register for - particular SoC. - -config UART_2_NRF_HW_ASYNC - bool "Use hardware RX byte counting" - depends on UART_2_ASYNC - help - If default driver uses interrupts to count incoming bytes, it is possible - that with higher speeds and/or high cpu load some data can be lost. - It is recommended to use hardware byte counting in such scenarios. - Hardware RX byte counting requires timer instance and one PPI channel - -config UART_2_NRF_ASYNC_LOW_POWER - bool "Low power mode" - depends on UART_ASYNC_API - help - When enabled, UARTE is enabled before each TX or RX usage and disabled - when not used. Disabling UARTE while in idle allows to achieve lowest - power consumption. It is only feasible if receiver is not always on. - -config UART_2_NRF_HW_ASYNC_TIMER - int "Timer instance" - depends on UART_2_NRF_HW_ASYNC - -config UART_2_GPIO_MANAGEMENT - bool "GPIO management on port 2" - depends on PM_DEVICE - default y - help - If enabled, the driver will configure the GPIOs used by the uart to - their default configuration when device is powered down. The GPIOs - will be configured back to correct state when UART is powered up. - -endif # HAS_HW_NRF_UARTE2 - -# ----------------- port 3 ----------------- if HAS_HW_NRF_UARTE3 - -config UART_3_INTERRUPT_DRIVEN - bool "Interrupt support on port 3" - depends on UART_INTERRUPT_DRIVEN - default y - help - This option enables UART interrupt support on port 3. - -config UART_3_ASYNC - bool "Asynchronous API support on port 3" - depends on UART_ASYNC_API && !UART_3_INTERRUPT_DRIVEN - default y - help - This option enables UART Asynchronous API support on port 3. - -config UART_3_ENHANCED_POLL_OUT - bool "Efficient poll out on port 3" - default y - help - When enabled, polling out does not trigger interrupt which stops TX. - Feature uses a PPI channel. - -config UART_3_NRF_PARITY_BIT - bool "Parity bit" - help - Enable parity bit. - -config UART_3_NRF_TX_BUFFER_SIZE - int "Size of RAM buffer" - range 1 65535 - default 32 - help - Size of the transmit buffer for API function: fifo_fill. - This value is limited by range of TXD.MAXCNT register for - particular SoC. - -config UART_3_NRF_HW_ASYNC - bool "Use hardware RX byte counting" - depends on UART_3_ASYNC - help - If default driver uses interrupts to count incoming bytes, it is possible - that with higher speeds and/or high cpu load some data can be lost. - It is recommended to use hardware byte counting in such scenarios. - Hardware RX byte counting requires timer instance and one PPI channel - -config UART_3_NRF_ASYNC_LOW_POWER - bool "Low power mode" - depends on UART_ASYNC_API - help - When enabled, UARTE is enabled before each TX or RX usage and disabled - when not used. Disabling UARTE while in idle allows to achieve lowest - power consumption. It is only feasible if receiver is not always on. - -config UART_3_NRF_HW_ASYNC_TIMER - int "Timer instance" - depends on UART_3_NRF_HW_ASYNC - -config UART_3_GPIO_MANAGEMENT - bool "GPIO management on port 3" - depends on PM_DEVICE - default y - help - If enabled, the driver will configure the GPIOs used by the uart to - their default configuration when device is powered down. The GPIOs - will be configured back to correct state when UART is powered up. - -endif # HAS_HW_NRF_UARTE3 - +nrfx_uart_num = 3 +rsource "Kconfig.nrfx_uart_instance" +endif config NRFX_TIMER0 default y @@ -356,23 +91,4 @@ config NRFX_TIMER4 || UART_2_NRF_HW_ASYNC_TIMER = 4 \ || UART_3_NRF_HW_ASYNC_TIMER = 4 - -config UARTE_NRF_HW_ASYNC - def_bool y - depends on UART_0_NRF_HW_ASYNC \ - || UART_1_NRF_HW_ASYNC \ - || UART_2_NRF_HW_ASYNC \ - || UART_3_NRF_HW_ASYNC - select NRFX_PPI if HAS_HW_NRF_PPI - select NRFX_DPPI if HAS_HW_NRF_DPPIC - -config UART_ENHANCED_POLL_OUT - def_bool y - depends on UART_0_ENHANCED_POLL_OUT \ - || UART_1_ENHANCED_POLL_OUT \ - || UART_2_ENHANCED_POLL_OUT \ - || UART_3_ENHANCED_POLL_OUT - select NRFX_PPI if HAS_HW_NRF_PPI - select NRFX_DPPI if HAS_HW_NRF_DPPIC - endif # UART_NRFX diff --git a/drivers/serial/Kconfig.nrfx_uart_instance b/drivers/serial/Kconfig.nrfx_uart_instance new file mode 100644 index 00000000000..39e774e2544 --- /dev/null +++ b/drivers/serial/Kconfig.nrfx_uart_instance @@ -0,0 +1,77 @@ +#nRF UART(E) instance configuration + +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config UART_$(nrfx_uart_num)_INTERRUPT_DRIVEN + bool "Interrupt support on port $(nrfx_uart_num)" + depends on UART_INTERRUPT_DRIVEN + default y + help + This option enables UART interrupt support on port $(nrfx_uart_num). + +config UART_$(nrfx_uart_num)_ASYNC + bool "Asynchronous API support on port $(nrfx_uart_num)" + depends on UART_ASYNC_API && !UART_$(nrfx_uart_num)_INTERRUPT_DRIVEN + default y + help + This option enables UART Asynchronous API support on port $(nrfx_uart_num). + +config UART_$(nrfx_uart_num)_ENHANCED_POLL_OUT + bool "Efficient poll out on port $(nrfx_uart_num)" + default y + depends on HAS_HW_NRF_UARTE$(nrfx_uart_num) + select NRFX_PPI if HAS_HW_NRF_PPI + select NRFX_DPPI if HAS_HW_NRF_DPPIC + help + When enabled, polling out does not trigger interrupt which stops TX. + Feature uses a PPI channel. + +config UART_$(nrfx_uart_num)_NRF_PARITY_BIT + bool "Parity bit" + help + Enable parity bit. + +config UART_$(nrfx_uart_num)_NRF_TX_BUFFER_SIZE + int "Size of RAM buffer" + depends on UART_INTERRUPT_DRIVEN + range 1 65535 + default 32 + help + Size of the transmit buffer for API function: fifo_fill. + This value is limited by range of TXD.MAXCNT register for + particular SoC. + +config UART_$(nrfx_uart_num)_NRF_HW_ASYNC + bool "Use hardware RX byte counting" + depends on HAS_HW_NRF_UARTE$(nrfx_uart_num) + depends on UART_ASYNC_API + select NRFX_PPI if HAS_HW_NRF_PPI + select NRFX_DPPI if HAS_HW_NRF_DPPIC + help + If default driver uses interrupts to count incoming bytes, it is possible + that with higher speeds and/or high cpu load some data can be lost. + It is recommended to use hardware byte counting in such scenarios. + Hardware RX byte counting requires timer instance and one PPI channel. + +config UART_$(nrfx_uart_num)_NRF_ASYNC_LOW_POWER + bool "Low power mode" + depends on HAS_HW_NRF_UARTE$(nrfx_uart_num) + depends on UART_ASYNC_API + help + When enabled, UARTE is enabled before each TX or RX usage and disabled + when not used. Disabling UARTE while in idle allows to achieve lowest + power consumption. It is only feasible if receiver is not always on. + +config UART_$(nrfx_uart_num)_NRF_HW_ASYNC_TIMER + int "Timer instance" + depends on UART_$(nrfx_uart_num)_NRF_HW_ASYNC + +config UART_$(nrfx_uart_num)_GPIO_MANAGEMENT + bool "GPIO management on port $(nrfx_uart_num)" + depends on PM_DEVICE + default y + help + If enabled, the driver will configure the GPIOs used by the uart to + their default configuration when device is powered down. The GPIOs + will be configured back to correct state when UART is powered up. diff --git a/drivers/serial/Kconfig.ns16550 b/drivers/serial/Kconfig.ns16550 index 22988f5f699..1c97a08637e 100644 --- a/drivers/serial/Kconfig.ns16550 +++ b/drivers/serial/Kconfig.ns16550 @@ -60,18 +60,6 @@ config UART_NS16550_ACCESS_WORD_ONLY 16550 (DesignWare UART) only allows word access, byte access will raise exception. -config UART_NS16550_ACCESS_IOPORT - bool - help - When enabled, NS16550 will not be a memory mapped device. This option - must be selected at SoC/board level if needed. - -config UART_NS16550_SIMULT_ACCESS - bool - help - When enabled, NS16550 supports IO, MMIO, PCIe UART devices simultaneously. - For io-mapped instances, io-mapped DTS property need to be added in dtsi. - config UART_NS16550_PARENT_INIT_LEVEL bool "Boot level based on parent node" default y if ACPI @@ -89,6 +77,12 @@ config UART_NS16550_TI_K3 Texas Instruments K3 SoCs by enabling a vendor specific extended register set. +config UART_NS16550_ITE_HIGH_SPEED_BUADRATE + bool "IT8XXX2 specific baud rate configuration" + help + Enable IT8XXX2 specific baud rate configuration. + This applies to high-speed baud rate configuration. + menu "NS16550 Workarounds" config UART_NS16550_WA_ISR_REENABLE_INTERRUPT diff --git a/drivers/serial/Kconfig.nxp_s32 b/drivers/serial/Kconfig.nxp_s32 index bd8b3c4a4c8..84555fd9e83 100644 --- a/drivers/serial/Kconfig.nxp_s32 +++ b/drivers/serial/Kconfig.nxp_s32 @@ -7,7 +7,7 @@ config UART_NXP_S32_LINFLEXD depends on DT_HAS_NXP_S32_LINFLEXD_ENABLED select SERIAL_HAS_DRIVER select SERIAL_SUPPORT_INTERRUPT - select NOCACHE_MEMORY + select NOCACHE_MEMORY if ARCH_HAS_NOCACHE_MEMORY_SUPPORT help Enable the LINFlexD UART driver for NXP S32 family processors. diff --git a/drivers/serial/Kconfig.ra b/drivers/serial/Kconfig.ra new file mode 100644 index 00000000000..3e35afed2de --- /dev/null +++ b/drivers/serial/Kconfig.ra @@ -0,0 +1,11 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +config UART_RA + bool "Renesas RA Series UART Driver" + default y + depends on DT_HAS_RENESAS_RA_UART_SCI_ENABLED + select SERIAL_HAS_DRIVER + select SERIAL_SUPPORT_INTERRUPT + help + Enable Renesas RA series UART driver. diff --git a/drivers/serial/Kconfig.rzt2m b/drivers/serial/Kconfig.rzt2m new file mode 100644 index 00000000000..2561499a5b5 --- /dev/null +++ b/drivers/serial/Kconfig.rzt2m @@ -0,0 +1,12 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +config UART_RZT2M + bool "Renesas RZ/T2M UART Driver" + default y + depends on DT_HAS_RENESAS_RZT2M_UART_ENABLED + select SERIAL_HAS_DRIVER + select SERIAL_SUPPORT_INTERRUPT + select PINCTRL + help + Enable Renesas RZ/T2M UART Driver. diff --git a/drivers/serial/Kconfig.xen b/drivers/serial/Kconfig.xen index 010541f77d1..471e5eb7269 100644 --- a/drivers/serial/Kconfig.xen +++ b/drivers/serial/Kconfig.xen @@ -1,6 +1,6 @@ # Xen hypervisor console via UART setup # -# Copyright (c) 2021 EPAM Systems +# Copyright (c) 2021-2023 EPAM Systems # SPDX-License-Identifier: Apache-2.0 # @@ -10,20 +10,22 @@ config UART_XEN_HVC depends on DT_HAS_XEN_HVC_UART_ENABLED select SERIAL_HAS_DRIVER select SERIAL_SUPPORT_INTERRUPT - depends on !XEN_INITIAL_DOMAIN + depends on XEN && !XEN_DOM0 && !XEN_DOM0LESS help Enable Xen ring buffer based hypervisor console driver. Used for Zephyr as unprivileged domain. config UART_XEN_HVC_CONSOLEIO - bool "Xen hypervisor Dom0 console UART driver" + bool "Xen hypervisor consoleio UART driver" select SERIAL_HAS_DRIVER - depends on BOARD_XENVM - depends on XEN_INITIAL_DOMAIN + depends on XEN_DOM0 || XEN_DOM0LESS default y help Enable Xen hypervisor console driver. Used for Zephyr as - privileged domain (Dom0). + privileged domain (Dom0) or for Zephyr DomU in Dom0less + configuration. Dom0less configuration does not have + privileged domain. Thus, there is no console daemon and Xen + manages all domain outputs through the consoleio interface. config XEN_HVC_INIT_PRIORITY int "Xen hypervisor console init priority" @@ -35,7 +37,6 @@ config XEN_HVC_INIT_PRIORITY config XEN_EARLY_CONSOLEIO bool "Early printk/stdout through console_io Xen interface" - depends on BOARD_XENVM depends on UART_XEN_HVC help Enable setting of console_io symbol hook for stdout and printk. diff --git a/drivers/serial/serial_esp32_usb.c b/drivers/serial/serial_esp32_usb.c index 06b93e79329..14e4b798a8f 100644 --- a/drivers/serial/serial_esp32_usb.c +++ b/drivers/serial/serial_esp32_usb.c @@ -13,7 +13,7 @@ #include #include #include -#if defined(CONFIG_SOC_ESP32C3) +#if defined(CONFIG_SOC_SERIES_ESP32C3) #include #else #include @@ -22,7 +22,7 @@ #include #include -#ifdef CONFIG_SOC_ESP32C3 +#ifdef CONFIG_SOC_SERIES_ESP32C3 #define ISR_HANDLER isr_handler_t #else #define ISR_HANDLER intr_handler_t diff --git a/drivers/serial/uart_async_rx.c b/drivers/serial/uart_async_rx.c new file mode 100644 index 00000000000..68e17691c3e --- /dev/null +++ b/drivers/serial/uart_async_rx.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +static uint8_t inc(struct uart_async_rx *rx_data, uint8_t val) +{ + return (val + 1) & (rx_data->config->buf_cnt - 1); +} + +static struct uart_async_rx_buf *get_buf(struct uart_async_rx *rx_data, uint8_t idx) +{ + uint8_t *p = rx_data->config->buffer; + + p += idx * (rx_data->buf_len + sizeof(struct uart_async_rx_buf)); + + return (struct uart_async_rx_buf *)p; +} + +uint8_t *uart_async_rx_buf_req(struct uart_async_rx *rx_data) +{ + uint8_t *data = NULL; + + if (rx_data->free_buf_cnt != 0) { + struct uart_async_rx_buf *buf = get_buf(rx_data, rx_data->drv_buf_idx); + + data = buf->buffer; + rx_data->drv_buf_idx = inc(rx_data, rx_data->drv_buf_idx); + + atomic_dec(&rx_data->free_buf_cnt); + } + + return data; +} + +void uart_async_rx_on_rdy(struct uart_async_rx *rx_data, uint8_t *buffer, size_t length) +{ + /* Cannot use CONTAINER_OF because validation fails due to type mismatch: + * uint8_t * vs uint8_t []. + */ + struct uart_async_rx_buf *rx_buf = + (struct uart_async_rx_buf *)(buffer - offsetof(struct uart_async_rx_buf, buffer)); + + rx_buf->wr_idx += length; + __ASSERT_NO_MSG(rx_buf->wr_idx <= rx_data->buf_len); + + atomic_add(&rx_data->pending_bytes, length); +} + +static void buf_reset(struct uart_async_rx_buf *buf) +{ + buf->rd_idx = 0; + buf->wr_idx = 0; + buf->completed = 0; +} +static void usr_rx_buf_release(struct uart_async_rx *rx_data, struct uart_async_rx_buf *buf) +{ + buf_reset(buf); + rx_data->rd_buf_idx = inc(rx_data, rx_data->rd_buf_idx); + atomic_inc(&rx_data->free_buf_cnt); + __ASSERT_NO_MSG(rx_data->free_buf_cnt <= rx_data->config->buf_cnt); +} + +void uart_async_rx_on_buf_rel(struct uart_async_rx *rx_data, uint8_t *buffer) +{ + /* Cannot use CONTAINER_OF because validation fails due to type mismatch: + * uint8_t * vs uint8_t []. + */ + struct uart_async_rx_buf *rx_buf = + (struct uart_async_rx_buf *)(buffer - offsetof(struct uart_async_rx_buf, buffer)); + + rx_buf->completed = 1; + rx_data->wr_buf_idx = inc(rx_data, rx_data->wr_buf_idx); +} + +size_t uart_async_rx_data_claim(struct uart_async_rx *rx_data, uint8_t **data, size_t length) +{ + struct uart_async_rx_buf *buf; + int rem; + + if ((rx_data->pending_bytes == 0) || (length == 0)) { + return 0; + } + + do { + buf = get_buf(rx_data, rx_data->rd_buf_idx); + if ((buf->rd_idx == buf->wr_idx) && (buf->completed == 1)) { + usr_rx_buf_release(rx_data, buf); + } else { + break; + } + } while (1); + + *data = &buf->buffer[buf->rd_idx]; + rem = buf->wr_idx - buf->rd_idx; + + return MIN(length, rem); +} + +void uart_async_rx_data_consume(struct uart_async_rx *rx_data, size_t length) +{ + struct uart_async_rx_buf *buf = get_buf(rx_data, rx_data->rd_buf_idx); + + buf->rd_idx += length; + + atomic_sub(&rx_data->pending_bytes, length); + + __ASSERT_NO_MSG(buf->rd_idx <= buf->wr_idx); +} + +void uart_async_rx_reset(struct uart_async_rx *rx_data) +{ + rx_data->free_buf_cnt = rx_data->config->buf_cnt; + for (uint8_t i = 0; i < rx_data->config->buf_cnt; i++) { + buf_reset(get_buf(rx_data, i)); + } +} + +int uart_async_rx_init(struct uart_async_rx *rx_data, + const struct uart_async_rx_config *config) +{ + __ASSERT_NO_MSG(config->length / config->buf_cnt <= UINT8_MAX); + memset(rx_data, 0, sizeof(*rx_data)); + rx_data->config = config; + rx_data->buf_len = (config->length / config->buf_cnt) - UART_ASYNC_RX_BUF_OVERHEAD; + uart_async_rx_reset(rx_data); + + return 0; +} diff --git a/drivers/serial/uart_bcm2711.c b/drivers/serial/uart_bcm2711.c new file mode 100644 index 00000000000..c8de51bf5e2 --- /dev/null +++ b/drivers/serial/uart_bcm2711.c @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2023 honglin leng + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT brcm_bcm2711_aux_uart + +/** + * @brief BCM2711 Miniuart Serial Driver + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#define BCM2711_MU_IO 0x00 +#define BCM2711_MU_IER 0x04 +#define BCM2711_MU_IIR 0x08 +#define BCM2711_MU_LCR 0x0c +#define BCM2711_MU_MCR 0x10 +#define BCM2711_MU_LSR 0x14 +#define BCM2711_MU_MSR 0x18 +#define BCM2711_MU_SCRATCH 0x1c +#define BCM2711_MU_CNTL 0x20 +#define BCM2711_MU_STAT 0x24 +#define BCM2711_MU_BAUD 0x28 + +#define BCM2711_MU_IER_TX_INTERRUPT BIT(1) +#define BCM2711_MU_IER_RX_INTERRUPT BIT(0) + +#define BCM2711_MU_IIR_RX_INTERRUPT BIT(2) +#define BCM2711_MU_IIR_TX_INTERRUPT BIT(1) +#define BCM2711_MU_IIR_FLUSH 0xc6 + +#define BCM2711_MU_LCR_7BIT 0x02 +#define BCM2711_MU_LCR_8BIT 0x03 + +#define BCM2711_MU_LSR_TX_IDLE BIT(6) +#define BCM2711_MU_LSR_TX_EMPTY BIT(5) +#define BCM2711_MU_LSR_RX_OVERRUN BIT(1) +#define BCM2711_MU_LSR_RX_READY BIT(0) + +#define BCM2711_MU_CNTL_RX_ENABLE BIT(0) +#define BCM2711_MU_CNTL_TX_ENABLE BIT(1) + +struct bcm2711_uart_config { + DEVICE_MMIO_ROM; /* Must be first */ + uint32_t baud_rate; + uint32_t clocks; +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + void (*irq_config_func)(const struct device *dev); +#endif +}; + +struct bcm2711_uart_data { + DEVICE_MMIO_RAM; /* Must be first */ + mem_addr_t uart_addr; +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + uart_irq_callback_user_data_t callback; + void *cb_data; +#endif +}; + +static bool bcm2711_mu_lowlevel_can_getc(mem_addr_t base) +{ + return sys_read32(base + BCM2711_MU_LSR) & BCM2711_MU_LSR_RX_READY; +} + +static bool bcm2711_mu_lowlevel_can_putc(mem_addr_t base) +{ + return sys_read32(base + BCM2711_MU_LSR) & BCM2711_MU_LSR_TX_EMPTY; +} + +static void bcm2711_mu_lowlevel_putc(mem_addr_t base, uint8_t ch) +{ + /* Wait until there is data in the FIFO */ + while (!bcm2711_mu_lowlevel_can_putc(base)) + ; + + /* Send the character */ + sys_write32(ch, base + BCM2711_MU_IO); +} + +static void bcm2711_mu_lowlevel_init(mem_addr_t base, bool skip_baudrate_config, + uint32_t baudrate, uint32_t input_clock) +{ + uint32_t divider; + + /* Wait until there is data in the FIFO */ + while (!bcm2711_mu_lowlevel_can_putc(base)) + ; + + /* Disable port */ + sys_write32(0x0, base + BCM2711_MU_CNTL); + + /* Disable interrupts */ + sys_write32(0x0, base + BCM2711_MU_IER); + + /* Setup 8bit data width and baudrate */ + sys_write32(BCM2711_MU_LCR_8BIT, base + BCM2711_MU_LCR); + if (!skip_baudrate_config) { + divider = (input_clock / (baudrate * 8)); + sys_write32(divider - 1, base + BCM2711_MU_BAUD); + } + + /* Enable RX & TX port */ + sys_write32(BCM2711_MU_CNTL_RX_ENABLE | BCM2711_MU_CNTL_TX_ENABLE, base + BCM2711_MU_CNTL); +} + +/** + * @brief Initialize UART channel + * + * This routine is called to reset the chip in a quiescent state. + * It is assumed that this function is called only once per UART. + * + * @param dev UART device struct + * + * @return 0 + */ +static int uart_bcm2711_init(const struct device *dev) +{ + const struct bcm2711_uart_config *uart_cfg = dev->config; + struct bcm2711_uart_data *uart_data = dev->data; + + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); + uart_data->uart_addr = DEVICE_MMIO_GET(dev); + bcm2711_mu_lowlevel_init(uart_data->uart_addr, 1, uart_cfg->baud_rate, uart_cfg->clocks); +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + uart_cfg->irq_config_func(dev); +#endif + return 0; +} + +static void uart_bcm2711_poll_out(const struct device *dev, unsigned char c) +{ + struct bcm2711_uart_data *uart_data = dev->data; + + bcm2711_mu_lowlevel_putc(uart_data->uart_addr, c); +} + +static int uart_bcm2711_poll_in(const struct device *dev, unsigned char *c) +{ + struct bcm2711_uart_data *uart_data = dev->data; + + while (!bcm2711_mu_lowlevel_can_getc(uart_data->uart_addr)) + ; + + return sys_read32(uart_data->uart_addr + BCM2711_MU_IO) & 0xFF; +} + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + +static int uart_bcm2711_fifo_fill(const struct device *dev, + const uint8_t *tx_data, + int size) +{ + int num_tx = 0U; + struct bcm2711_uart_data *uart_data = dev->data; + + while ((size - num_tx) > 0) { + /* Send a character */ + bcm2711_mu_lowlevel_putc(uart_data->uart_addr, tx_data[num_tx]); + num_tx++; + } + + return num_tx; +} + +static int uart_bcm2711_fifo_read(const struct device *dev, uint8_t *rx_data, + const int size) +{ + int num_rx = 0U; + struct bcm2711_uart_data *uart_data = dev->data; + + while ((size - num_rx) > 0 && bcm2711_mu_lowlevel_can_getc(uart_data->uart_addr)) { + /* Receive a character */ + rx_data[num_rx++] = sys_read32(uart_data->uart_addr + BCM2711_MU_IO) & 0xFF; + } + return num_rx; +} + +static void uart_bcm2711_irq_tx_enable(const struct device *dev) +{ + struct bcm2711_uart_data *uart_data = dev->data; + + sys_write32(BCM2711_MU_IER_TX_INTERRUPT, uart_data->uart_addr + BCM2711_MU_IER); +} + +static void uart_bcm2711_irq_tx_disable(const struct device *dev) +{ + struct bcm2711_uart_data *uart_data = dev->data; + + sys_write32((uint32_t)(~BCM2711_MU_IER_TX_INTERRUPT), + uart_data->uart_addr + BCM2711_MU_IER); +} + +static int uart_bcm2711_irq_tx_ready(const struct device *dev) +{ + struct bcm2711_uart_data *uart_data = dev->data; + + return bcm2711_mu_lowlevel_can_putc(uart_data->uart_addr); +} + +static void uart_bcm2711_irq_rx_enable(const struct device *dev) +{ + struct bcm2711_uart_data *uart_data = dev->data; + + sys_write32(BCM2711_MU_IER_RX_INTERRUPT, uart_data->uart_addr + BCM2711_MU_IER); +} + +static void uart_bcm2711_irq_rx_disable(const struct device *dev) +{ + struct bcm2711_uart_data *uart_data = dev->data; + + sys_write32((uint32_t)(~BCM2711_MU_IER_RX_INTERRUPT), + uart_data->uart_addr + BCM2711_MU_IER); +} + +static int uart_bcm2711_irq_rx_ready(const struct device *dev) +{ + struct bcm2711_uart_data *uart_data = dev->data; + + return bcm2711_mu_lowlevel_can_getc(uart_data->uart_addr); +} + +static int uart_bcm2711_irq_is_pending(const struct device *dev) +{ + struct bcm2711_uart_data *uart_data = dev->data; + + return bcm2711_mu_lowlevel_can_getc(uart_data->uart_addr) || + bcm2711_mu_lowlevel_can_putc(uart_data->uart_addr); +} + +static int uart_bcm2711_irq_update(const struct device *dev) +{ + return 1; +} + +static void uart_bcm2711_irq_callback_set(const struct device *dev, + uart_irq_callback_user_data_t cb, + void *cb_data) +{ + struct bcm2711_uart_data *data = dev->data; + + data->callback = cb; + data->cb_data = cb_data; +} + +/** + * @brief Interrupt service routine. + * + * This simply calls the callback function, if one exists. + * + * Note: imx UART Tx interrupts when ready to send; Rx interrupts when char + * received. + * + * @param arg Argument to ISR. + */ +void uart_isr(const struct device *dev) +{ + struct bcm2711_uart_data *data = dev->data; + + if (data->callback) { + data->callback(dev, data->cb_data); + } +} +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + +static const struct uart_driver_api uart_bcm2711_driver_api = { + .poll_in = uart_bcm2711_poll_in, + .poll_out = uart_bcm2711_poll_out, + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + .fifo_fill = uart_bcm2711_fifo_fill, + .fifo_read = uart_bcm2711_fifo_read, + .irq_tx_enable = uart_bcm2711_irq_tx_enable, + .irq_tx_disable = uart_bcm2711_irq_tx_disable, + .irq_tx_ready = uart_bcm2711_irq_tx_ready, + .irq_rx_enable = uart_bcm2711_irq_rx_enable, + .irq_rx_disable = uart_bcm2711_irq_rx_disable, + .irq_rx_ready = uart_bcm2711_irq_rx_ready, + .irq_is_pending = uart_bcm2711_irq_is_pending, + .irq_update = uart_bcm2711_irq_update, + .irq_callback_set = uart_bcm2711_irq_callback_set, +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + +}; + +#define UART_DECLARE_CFG(n, IRQ_FUNC_INIT) \ + static const struct bcm2711_uart_config bcm2711_uart_##n##_config = { \ + DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), .baud_rate = DT_INST_PROP(n, current_speed), \ + .clocks = DT_INST_PROP(n, clock_frequency), IRQ_FUNC_INIT} + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN +#define UART_CONFIG_FUNC(n) \ + static void irq_config_func_##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), uart_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + } +#define UART_IRQ_CFG_FUNC_INIT(n) .irq_config_func = irq_config_func_##n +#define UART_INIT_CFG(n) UART_DECLARE_CFG(n, UART_IRQ_CFG_FUNC_INIT(n)) +#else +#define UART_CONFIG_FUNC(n) +#define UART_IRQ_CFG_FUNC_INIT +#define UART_INIT_CFG(n) UART_DECLARE_CFG(n, UART_IRQ_CFG_FUNC_INIT) +#endif + +#define UART_INIT(n) \ + static struct bcm2711_uart_data bcm2711_uart_##n##_data; \ + \ + static const struct bcm2711_uart_config bcm2711_uart_##n##_config; \ + \ + DEVICE_DT_INST_DEFINE(n, &uart_bcm2711_init, NULL, &bcm2711_uart_##n##_data, \ + &bcm2711_uart_##n##_config, PRE_KERNEL_1, \ + CONFIG_SERIAL_INIT_PRIORITY, &uart_bcm2711_driver_api); \ + \ + UART_CONFIG_FUNC(n) \ + \ + UART_INIT_CFG(n); + +DT_INST_FOREACH_STATUS_OKAY(UART_INIT) diff --git a/drivers/serial/uart_cc13xx_cc26xx.c b/drivers/serial/uart_cc13xx_cc26xx.c index f47fdd0bbc9..e5bbf40b394 100644 --- a/drivers/serial/uart_cc13xx_cc26xx.c +++ b/drivers/serial/uart_cc13xx_cc26xx.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,12 @@ struct uart_cc13xx_cc26xx_config { uint32_t sys_clk_freq; }; +enum uart_cc13xx_cc26xx_pm_locks { + UART_CC13XX_CC26XX_PM_LOCK_TX, + UART_CC13XX_CC26XX_PM_LOCK_RX, + UART_CC13XX_CC26XX_PM_LOCK_COUNT, +}; + struct uart_cc13xx_cc26xx_data { struct uart_config uart_config; const struct pinctrl_dev_config *pcfg; @@ -35,8 +42,7 @@ struct uart_cc13xx_cc26xx_data { #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ #ifdef CONFIG_PM Power_NotifyObj postNotify; - bool tx_constrained; - bool rx_constrained; + ATOMIC_DEFINE(pm_lock, UART_CC13XX_CC26XX_PM_LOCK_COUNT); #endif }; @@ -240,7 +246,7 @@ static void uart_cc13xx_cc26xx_irq_tx_enable(const struct device *dev) #ifdef CONFIG_PM struct uart_cc13xx_cc26xx_data *data = dev->data; - if (!data->tx_constrained) { + if (!atomic_test_and_set_bit(data->pm_lock, UART_CC13XX_CC26XX_PM_LOCK_TX)) { /* * When tx irq is enabled, it is implicit that we are expecting * to transmit using the uart, hence we should no longer go @@ -252,7 +258,6 @@ static void uart_cc13xx_cc26xx_irq_tx_enable(const struct device *dev) * would interfere with a transfer. */ pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); - data->tx_constrained = true; } #endif @@ -268,9 +273,8 @@ static void uart_cc13xx_cc26xx_irq_tx_disable(const struct device *dev) #ifdef CONFIG_PM struct uart_cc13xx_cc26xx_data *data = dev->data; - if (data->tx_constrained) { + if (atomic_test_and_clear_bit(data->pm_lock, UART_CC13XX_CC26XX_PM_LOCK_TX)) { pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); - data->tx_constrained = false; } #endif } @@ -294,9 +298,8 @@ static void uart_cc13xx_cc26xx_irq_rx_enable(const struct device *dev) * to receive from the uart, hence we can no longer go into * standby. */ - if (!data->rx_constrained) { + if (!atomic_test_and_set_bit(data->pm_lock, UART_CC13XX_CC26XX_PM_LOCK_RX)) { pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); - data->rx_constrained = true; } #endif @@ -310,9 +313,8 @@ static void uart_cc13xx_cc26xx_irq_rx_disable(const struct device *dev) #ifdef CONFIG_PM struct uart_cc13xx_cc26xx_data *data = dev->data; - if (data->rx_constrained) { + if (atomic_test_and_clear_bit(data->pm_lock, UART_CC13XX_CC26XX_PM_LOCK_RX)) { pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); - data->rx_constrained = false; } #endif @@ -497,8 +499,8 @@ static const struct uart_driver_api uart_cc13xx_cc26xx_driver_api = { do { \ struct uart_cc13xx_cc26xx_data *dev_data = dev->data; \ \ - dev_data->rx_constrained = false; \ - dev_data->tx_constrained = false; \ + atomic_clear_bit(dev_data->pm_lock, UART_CC13XX_CC26XX_PM_LOCK_RX); \ + atomic_clear_bit(dev_data->pm_lock, UART_CC13XX_CC26XX_PM_LOCK_TX); \ \ /* Set Power dependencies */ \ if (DT_INST_REG_ADDR(n) == 0x40001000) { \ diff --git a/drivers/serial/uart_emul.c b/drivers/serial/uart_emul.c index 4cb50731f9c..645c888e539 100644 --- a/drivers/serial/uart_emul.c +++ b/drivers/serial/uart_emul.c @@ -6,22 +6,31 @@ #define DT_DRV_COMPAT zephyr_uart_emul -#include -#include -#include -#include #include +#include +#include +#include #include +#include +#include + LOG_MODULE_REGISTER(uart_emul, CONFIG_UART_LOG_LEVEL); struct uart_emul_config { bool loopback; + size_t latch_buffer_size; +}; + +struct uart_emul_work { + struct k_work work; + const struct device *dev; }; /* Device run time data */ struct uart_emul_data { struct uart_config cfg; + int errors; struct ring_buf *rx_rb; struct k_spinlock rx_lock; @@ -31,9 +40,39 @@ struct uart_emul_data { struct ring_buf *tx_rb; struct k_spinlock tx_lock; + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + bool rx_irq_en; + bool tx_irq_en; + struct uart_emul_work irq_work; + uart_irq_callback_user_data_t irq_cb; + void *irq_cb_udata; +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ }; -int uart_emul_poll_in(const struct device *dev, unsigned char *p_char) +/* + * Define local thread to emulate different thread priorities. + * + * A UART driver may call back from within a thread with higher or lower priority + * than the thread calling the UART API. This can hide potential concurrency issues, + * especially if the thread priorities are the same, or even using the same thread + * in case the system work queue. + */ +K_THREAD_STACK_DEFINE(uart_emul_stack_area, CONFIG_UART_EMUL_WORK_Q_STACK_SIZE); +struct k_work_q uart_emul_work_q; + +int uart_emul_init_work_q(void) +{ + k_work_queue_init(&uart_emul_work_q); + k_work_queue_start(&uart_emul_work_q, uart_emul_stack_area, + K_THREAD_STACK_SIZEOF(uart_emul_stack_area), + CONFIG_UART_EMUL_WORK_Q_PRIORITY, NULL); + return 0; +} + +SYS_INIT(uart_emul_init_work_q, POST_KERNEL, 0); + +static int uart_emul_poll_in(const struct device *dev, unsigned char *p_char) { struct uart_emul_data *drv_data = dev->data; k_spinlock_key_t key; @@ -51,7 +90,7 @@ int uart_emul_poll_in(const struct device *dev, unsigned char *p_char) return 0; } -void uart_emul_poll_out(const struct device *dev, unsigned char out_char) +static void uart_emul_poll_out(const struct device *dev, unsigned char out_char) { struct uart_emul_data *drv_data = dev->data; const struct uart_emul_config *drv_cfg = dev->config; @@ -76,13 +115,17 @@ void uart_emul_poll_out(const struct device *dev, unsigned char out_char) } } -int uart_emul_err_check(const struct device *dev) +static int uart_emul_err_check(const struct device *dev) { - return 0; + struct uart_emul_data *drv_data = dev->data; + int errors = drv_data->errors; + + drv_data->errors = 0; + return errors; } #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE -int uart_emul_configure(const struct device *dev, const struct uart_config *cfg) +static int uart_emul_configure(const struct device *dev, const struct uart_config *cfg) { struct uart_emul_data *drv_data = dev->data; @@ -90,7 +133,7 @@ int uart_emul_configure(const struct device *dev, const struct uart_config *cfg) return 0; } -int uart_emul_config_get(const struct device *dev, struct uart_config *cfg) +static int uart_emul_config_get(const struct device *dev, struct uart_config *cfg) { const struct uart_emul_data *drv_data = dev->data; @@ -99,6 +142,194 @@ int uart_emul_config_get(const struct device *dev, struct uart_config *cfg) } #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ +#ifdef CONFIG_UART_INTERRUPT_DRIVEN +static int uart_emul_fifo_fill(const struct device *dev, const uint8_t *tx_data, int size) +{ + int ret; + struct uart_emul_data *data = dev->data; + const struct uart_emul_config *config = dev->config; + uint32_t put_size = MIN(config->latch_buffer_size, size); + + K_SPINLOCK(&data->tx_lock) { + ret = ring_buf_put(data->tx_rb, tx_data, put_size); + } + + if (config->loopback) { + uart_emul_put_rx_data(dev, (uint8_t *)tx_data, put_size); + } + if (data->tx_data_ready_cb) { + data->tx_data_ready_cb(dev, ring_buf_size_get(data->tx_rb), data->user_data); + } + + return ret; +} + +static int uart_emul_fifo_read(const struct device *dev, uint8_t *rx_data, int size) +{ + struct uart_emul_data *data = dev->data; + const struct uart_emul_config *config = dev->config; + uint32_t bytes_to_read; + + K_SPINLOCK(&data->rx_lock) { + bytes_to_read = MIN(config->latch_buffer_size, ring_buf_size_get(data->rx_rb)); + ring_buf_get(data->rx_rb, rx_data, bytes_to_read); + } + + return bytes_to_read; +} + +static int uart_emul_irq_tx_ready(const struct device *dev) +{ + bool ready = false; + struct uart_emul_data *data = dev->data; + + K_SPINLOCK(&data->tx_lock) { + if (!data->tx_irq_en) { + K_SPINLOCK_BREAK; + } + + ready = ring_buf_space_get(data->tx_rb) > 0; + } + + return ready; +} + +static int uart_emul_irq_rx_ready(const struct device *dev) +{ + bool ready = false; + struct uart_emul_data *data = dev->data; + + K_SPINLOCK(&data->rx_lock) { + if (!data->rx_irq_en) { + K_SPINLOCK_BREAK; + } + + ready = !ring_buf_is_empty(data->rx_rb); + } + + return ready; +} + +static void uart_emul_irq_handler(struct k_work *work) +{ + struct uart_emul_work *uwork = CONTAINER_OF(work, struct uart_emul_work, work); + const struct device *dev = uwork->dev; + struct uart_emul_data *data = dev->data; + uart_irq_callback_user_data_t cb = data->irq_cb; + void *udata = data->irq_cb_udata; + + if (cb == NULL) { + LOG_DBG("No IRQ callback configured for uart_emul device %p", dev); + return; + } + + while (true) { + bool have_work = false; + + K_SPINLOCK(&data->tx_lock) { + if (!data->tx_irq_en) { + K_SPINLOCK_BREAK; + } + + have_work = have_work || ring_buf_space_get(data->tx_rb) > 0; + } + + K_SPINLOCK(&data->rx_lock) { + if (!data->rx_irq_en) { + K_SPINLOCK_BREAK; + } + + have_work = have_work || !ring_buf_is_empty(data->rx_rb); + } + + if (!have_work) { + break; + } + + cb(dev, udata); + } +} + +static int uart_emul_irq_is_pending(const struct device *dev) +{ + return uart_emul_irq_tx_ready(dev) || uart_emul_irq_rx_ready(dev); +} + +static void uart_emul_irq_tx_enable(const struct device *dev) +{ + bool submit_irq_work; + struct uart_emul_data *const data = dev->data; + + K_SPINLOCK(&data->tx_lock) { + data->tx_irq_en = true; + submit_irq_work = ring_buf_space_get(data->tx_rb) > 0; + } + + if (submit_irq_work) { + (void)k_work_submit_to_queue(&uart_emul_work_q, &data->irq_work.work); + } +} + +static void uart_emul_irq_rx_enable(const struct device *dev) +{ + bool submit_irq_work; + struct uart_emul_data *const data = dev->data; + + K_SPINLOCK(&data->rx_lock) { + data->rx_irq_en = true; + submit_irq_work = !ring_buf_is_empty(data->rx_rb); + } + + if (submit_irq_work) { + (void)k_work_submit_to_queue(&uart_emul_work_q, &data->irq_work.work); + } +} + +static void uart_emul_irq_tx_disable(const struct device *dev) +{ + struct uart_emul_data *const data = dev->data; + + K_SPINLOCK(&data->tx_lock) { + data->tx_irq_en = false; + } +} + +static void uart_emul_irq_rx_disable(const struct device *dev) +{ + struct uart_emul_data *const data = dev->data; + + K_SPINLOCK(&data->rx_lock) { + data->rx_irq_en = false; + } +} + +static int uart_emul_irq_tx_complete(const struct device *dev) +{ + bool tx_complete = false; + struct uart_emul_data *const data = dev->data; + + K_SPINLOCK(&data->tx_lock) { + tx_complete = ring_buf_is_empty(data->tx_rb); + } + + return tx_complete; +} + +static void uart_emul_irq_callback_set(const struct device *dev, uart_irq_callback_user_data_t cb, + void *user_data) +{ + struct uart_emul_data *const data = dev->data; + + data->irq_cb = cb; + data->irq_cb_udata = user_data; +} + +static int uart_emul_irq_update(const struct device *dev) +{ + return 1; +} +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + static const struct uart_driver_api uart_emul_api = { .poll_in = uart_emul_poll_in, .poll_out = uart_emul_poll_out, @@ -106,7 +337,21 @@ static const struct uart_driver_api uart_emul_api = { .config_get = uart_emul_config_get, .configure = uart_emul_configure, #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ - .err_check = uart_emul_err_check + .err_check = uart_emul_err_check, +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + .fifo_fill = uart_emul_fifo_fill, + .fifo_read = uart_emul_fifo_read, + .irq_tx_enable = uart_emul_irq_tx_enable, + .irq_rx_enable = uart_emul_irq_rx_enable, + .irq_tx_disable = uart_emul_irq_tx_disable, + .irq_rx_disable = uart_emul_irq_rx_disable, + .irq_tx_ready = uart_emul_irq_tx_ready, + .irq_rx_ready = uart_emul_irq_rx_ready, + .irq_tx_complete = uart_emul_irq_tx_complete, + .irq_callback_set = uart_emul_irq_callback_set, + .irq_update = uart_emul_irq_update, + .irq_is_pending = uart_emul_irq_is_pending, +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ }; void uart_emul_callback_tx_data_ready_set(const struct device *dev, @@ -121,12 +366,26 @@ void uart_emul_callback_tx_data_ready_set(const struct device *dev, uint32_t uart_emul_put_rx_data(const struct device *dev, uint8_t *data, size_t size) { struct uart_emul_data *drv_data = dev->data; - k_spinlock_key_t key; uint32_t count; + __unused bool empty; + __unused bool irq_en; + + K_SPINLOCK(&drv_data->rx_lock) { + count = ring_buf_put(drv_data->rx_rb, data, size); + empty = ring_buf_is_empty(drv_data->rx_rb); + IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, (irq_en = drv_data->rx_irq_en;)); + } + + if (count < size) { + uart_emul_set_errors(dev, UART_ERROR_OVERRUN); + } + + IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, ( + if (count > 0 && irq_en && !empty) { + (void)k_work_submit_to_queue(&uart_emul_work_q, &drv_data->irq_work.work); + } + )) - key = k_spin_lock(&drv_data->rx_lock); - count = ring_buf_put(drv_data->rx_rb, data, size); - k_spin_unlock(&drv_data->rx_lock, key); return count; } @@ -168,9 +427,21 @@ uint32_t uart_emul_flush_tx_data(const struct device *dev) return count; } +void uart_emul_set_errors(const struct device *dev, int errors) +{ + struct uart_emul_data *drv_data = dev->data; + + drv_data->errors |= errors; +} + #define UART_EMUL_RX_FIFO_SIZE(inst) (DT_INST_PROP(inst, rx_fifo_size)) #define UART_EMUL_TX_FIFO_SIZE(inst) (DT_INST_PROP(inst, tx_fifo_size)) +#define UART_EMUL_IRQ_WORK_INIT(inst) \ + IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \ + (.irq_work = {.dev = DEVICE_DT_INST_GET(inst), \ + .work = Z_WORK_INITIALIZER(uart_emul_irq_handler)},)) + #define DEFINE_UART_EMUL(inst) \ \ RING_BUF_DECLARE(uart_emul_##inst##_rx_rb, UART_EMUL_RX_FIFO_SIZE(inst)); \ @@ -178,10 +449,12 @@ uint32_t uart_emul_flush_tx_data(const struct device *dev) \ static struct uart_emul_config uart_emul_cfg_##inst = { \ .loopback = DT_INST_PROP(inst, loopback), \ + .latch_buffer_size = DT_INST_PROP(inst, latch_buffer_size), \ }; \ static struct uart_emul_data uart_emul_data_##inst = { \ .rx_rb = &uart_emul_##inst##_rx_rb, \ .tx_rb = &uart_emul_##inst##_tx_rb, \ + UART_EMUL_IRQ_WORK_INIT(inst) \ }; \ \ DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &uart_emul_data_##inst, &uart_emul_cfg_##inst, \ diff --git a/drivers/serial/uart_handlers.c b/drivers/serial/uart_handlers.c index 1dd4dd78f10..954592aca28 100644 --- a/drivers/serial/uart_handlers.c +++ b/drivers/serial/uart_handlers.c @@ -5,19 +5,19 @@ */ #include -#include +#include #define UART_SIMPLE(op_) \ static inline int z_vrfy_uart_##op_(const struct device *dev) \ { \ - Z_OOPS(Z_SYSCALL_DRIVER_UART(dev, op_)); \ + K_OOPS(K_SYSCALL_DRIVER_UART(dev, op_)); \ return z_impl_uart_ ## op_(dev); \ } #define UART_SIMPLE_VOID(op_) \ static inline void z_vrfy_uart_##op_(const struct device *dev) \ { \ - Z_OOPS(Z_SYSCALL_DRIVER_UART(dev, op_)); \ + K_OOPS(K_SYSCALL_DRIVER_UART(dev, op_)); \ z_impl_uart_ ## op_(dev); \ } @@ -27,8 +27,8 @@ UART_SIMPLE(err_check) static inline int z_vrfy_uart_poll_in(const struct device *dev, unsigned char *p_char) { - Z_OOPS(Z_SYSCALL_DRIVER_UART(dev, poll_in)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(p_char, sizeof(unsigned char))); + K_OOPS(K_SYSCALL_DRIVER_UART(dev, poll_in)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(p_char, sizeof(unsigned char))); return z_impl_uart_poll_in(dev, p_char); } #include @@ -36,8 +36,8 @@ static inline int z_vrfy_uart_poll_in(const struct device *dev, static inline int z_vrfy_uart_poll_in_u16(const struct device *dev, uint16_t *p_u16) { - Z_OOPS(Z_SYSCALL_DRIVER_UART(dev, poll_in)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(p_u16, sizeof(uint16_t))); + K_OOPS(K_SYSCALL_DRIVER_UART(dev, poll_in)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(p_u16, sizeof(uint16_t))); return z_impl_uart_poll_in_u16(dev, p_u16); } #include @@ -45,7 +45,7 @@ static inline int z_vrfy_uart_poll_in_u16(const struct device *dev, static inline void z_vrfy_uart_poll_out(const struct device *dev, unsigned char out_char) { - Z_OOPS(Z_SYSCALL_DRIVER_UART(dev, poll_out)); + K_OOPS(K_SYSCALL_DRIVER_UART(dev, poll_out)); z_impl_uart_poll_out((const struct device *)dev, out_char); } #include @@ -53,7 +53,7 @@ static inline void z_vrfy_uart_poll_out(const struct device *dev, static inline void z_vrfy_uart_poll_out_u16(const struct device *dev, uint16_t out_u16) { - Z_OOPS(Z_SYSCALL_DRIVER_UART(dev, poll_out)); + K_OOPS(K_SYSCALL_DRIVER_UART(dev, poll_out)); z_impl_uart_poll_out_u16((const struct device *)dev, out_u16); } #include @@ -62,8 +62,8 @@ static inline void z_vrfy_uart_poll_out_u16(const struct device *dev, static inline int z_vrfy_uart_config_get(const struct device *dev, struct uart_config *cfg) { - Z_OOPS(Z_SYSCALL_DRIVER_UART(dev, config_get)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(cfg, sizeof(struct uart_config))); + K_OOPS(K_SYSCALL_DRIVER_UART(dev, config_get)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(cfg, sizeof(struct uart_config))); return z_impl_uart_config_get(dev, cfg); } @@ -72,8 +72,8 @@ static inline int z_vrfy_uart_config_get(const struct device *dev, static inline int z_vrfy_uart_configure(const struct device *dev, const struct uart_config *cfg) { - Z_OOPS(Z_SYSCALL_DRIVER_UART(dev, config_get)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(cfg, sizeof(struct uart_config))); + K_OOPS(K_SYSCALL_DRIVER_UART(dev, config_get)); + K_OOPS(K_SYSCALL_MEMORY_READ(cfg, sizeof(struct uart_config))); return z_impl_uart_configure(dev, cfg); } @@ -90,8 +90,8 @@ static inline int z_vrfy_uart_configure(const struct device *dev, static inline int z_vrfy_uart_tx(const struct device *dev, const uint8_t *buf, size_t len, int32_t timeout) { - Z_OOPS(Z_SYSCALL_DRIVER_UART(dev, tx)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(buf, len)); + K_OOPS(K_SYSCALL_DRIVER_UART(dev, tx)); + K_OOPS(K_SYSCALL_MEMORY_READ(buf, len)); return z_impl_uart_tx(dev, buf, len, timeout); } #include @@ -101,8 +101,8 @@ static inline int z_vrfy_uart_tx_u16(const struct device *dev, const uint16_t *buf, size_t len, int32_t timeout) { - Z_OOPS(Z_SYSCALL_DRIVER_UART(dev, tx)); - Z_OOPS(Z_SYSCALL_MEMORY_ARRAY_READ(buf, len, sizeof(uint16_t))); + K_OOPS(K_SYSCALL_DRIVER_UART(dev, tx)); + K_OOPS(K_SYSCALL_MEMORY_ARRAY_READ(buf, len, sizeof(uint16_t))); return z_impl_uart_tx_u16(dev, buf, len, timeout); } #include @@ -115,8 +115,8 @@ static inline int z_vrfy_uart_rx_enable(const struct device *dev, uint8_t *buf, size_t len, int32_t timeout) { - Z_OOPS(Z_SYSCALL_DRIVER_UART(dev, rx_enable)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(buf, len)); + K_OOPS(K_SYSCALL_DRIVER_UART(dev, rx_enable)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(buf, len)); return z_impl_uart_rx_enable(dev, buf, len, timeout); } #include @@ -126,8 +126,8 @@ static inline int z_vrfy_uart_rx_enable_u16(const struct device *dev, uint16_t *buf, size_t len, int32_t timeout) { - Z_OOPS(Z_SYSCALL_DRIVER_UART(dev, rx_enable)); - Z_OOPS(Z_SYSCALL_MEMORY_ARRAY_WRITE(buf, len, sizeof(uint16_t))); + K_OOPS(K_SYSCALL_DRIVER_UART(dev, rx_enable)); + K_OOPS(K_SYSCALL_MEMORY_ARRAY_WRITE(buf, len, sizeof(uint16_t))); return z_impl_uart_rx_enable_u16(dev, buf, len, timeout); } #include @@ -160,7 +160,7 @@ UART_SIMPLE(irq_update) static inline int z_vrfy_uart_line_ctrl_set(const struct device *dev, uint32_t ctrl, uint32_t val) { - Z_OOPS(Z_SYSCALL_DRIVER_UART(dev, line_ctrl_set)); + K_OOPS(K_SYSCALL_DRIVER_UART(dev, line_ctrl_set)); return z_impl_uart_line_ctrl_set((const struct device *)dev, ctrl, val); } @@ -169,8 +169,8 @@ static inline int z_vrfy_uart_line_ctrl_set(const struct device *dev, static inline int z_vrfy_uart_line_ctrl_get(const struct device *dev, uint32_t ctrl, uint32_t *val) { - Z_OOPS(Z_SYSCALL_DRIVER_UART(dev, line_ctrl_get)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(val, sizeof(uint32_t))); + K_OOPS(K_SYSCALL_DRIVER_UART(dev, line_ctrl_get)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(val, sizeof(uint32_t))); return z_impl_uart_line_ctrl_get((const struct device *)dev, ctrl, (uint32_t *)val); } @@ -181,7 +181,7 @@ static inline int z_vrfy_uart_line_ctrl_get(const struct device *dev, static inline int z_vrfy_uart_drv_cmd(const struct device *dev, uint32_t cmd, uint32_t p) { - Z_OOPS(Z_SYSCALL_DRIVER_UART(dev, drv_cmd)); + K_OOPS(K_SYSCALL_DRIVER_UART(dev, drv_cmd)); return z_impl_uart_drv_cmd((const struct device *)dev, cmd, p); } #include diff --git a/drivers/serial/uart_hvc_xen.c b/drivers/serial/uart_hvc_xen.c index 3911fbfae44..fc26e79f13a 100644 --- a/drivers/serial/uart_hvc_xen.c +++ b/drivers/serial/uart_hvc_xen.c @@ -233,14 +233,14 @@ int xen_console_init(const struct device *dev) data->dev = dev; - ret = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &data->evtchn); + ret = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, DOMID_SELF, &data->evtchn); if (ret) { LOG_ERR("%s: failed to get Xen console evtchn, ret = %d\n", __func__, ret); return ret; } - ret = hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &console_pfn); + ret = hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, DOMID_SELF, &console_pfn); if (ret) { LOG_ERR("%s: failed to get Xen console PFN, ret = %d\n", __func__, ret); diff --git a/drivers/serial/uart_intel_lw.c b/drivers/serial/uart_intel_lw.c new file mode 100644 index 00000000000..9b2a877fbdc --- /dev/null +++ b/drivers/serial/uart_intel_lw.c @@ -0,0 +1,1025 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief UART driver for Intel FPGA UART Core IP + * Reference : Embedded Peripherals IP User Guide (22.3 and above): 55. + * Lightweight UART Core + */ + +#define DT_DRV_COMPAT intel_lw_uart +#include +#include + +#include + +/* register offsets */ +#define INTEL_LW_UART_OFFSET (0x4) + +#define INTEL_LW_UART_RXDATA_REG_OFFSET (0 * INTEL_LW_UART_OFFSET) +#define INTEL_LW_UART_TXDATA_REG_OFFSET (1 * INTEL_LW_UART_OFFSET) +#define INTEL_LW_UART_STATUS_REG_OFFSET (2 * INTEL_LW_UART_OFFSET) +#define INTEL_LW_UART_CONTROL_REG_OFFSET (3 * INTEL_LW_UART_OFFSET) +#define INTEL_LW_UART_DIVISOR_REG_OFFSET (4 * INTEL_LW_UART_OFFSET) +#define INTEL_LW_UART_EOP_REG_OFFSET (5 * INTEL_LW_UART_OFFSET) + +/*status register mask */ +#define INTEL_LW_UART_STATUS_PE_MSK (0x1) +#define INTEL_LW_UART_STATUS_FE_MSK (0x2) +#define INTEL_LW_UART_STATUS_BRK_MSK (0x4) +#define INTEL_LW_UART_STATUS_ROE_MSK (0x8) +#define INTEL_LW_UART_STATUS_TOE_MSK (0x10) +#define INTEL_LW_UART_STATUS_TMT_MSK (0x20) +#define INTEL_LW_UART_STATUS_TRDY_MSK (0x40) +#define INTEL_LW_UART_STATUS_RRDY_MSK (0x80) +#define INTEL_LW_UART_STATUS_DCTS_MSK (0x400) +#define INTEL_LW_UART_STATUS_CTS_MSK (0x800) +#define INTEL_LW_UART_STATUS_E_MSK (0x100) +#define INTEL_LW_UART_STATUS_EOP_MSK (0x1000) + +/* control register mask */ +#define INTEL_LW_UART_CONTROL_TMT_MSK (0x20) +#define INTEL_LW_UART_CONTROL_TRDY_MSK (0x40) +#define INTEL_LW_UART_CONTROL_RRDY_MSK (0x80) +#define INTEL_LW_UART_CONTROL_E_MSK (0x100) +#define INTEL_LW_UART_CONTROL_TRBK_MSK (0x200) +#define INTEL_LW_UART_CONTROL_DCTS_MSK (0x400) +#define INTEL_LW_UART_CONTROL_RTS_MSK (0x800) +#define INTEL_LW_UART_CONTROL_EOP_MSK (0x1000) + +/* defined values */ +#define UART_INTEL_LW_NO_ERROR (0u) +#define INTEL_LW_UART_CLEAR_STATUS_VAL (0u) +#define INTEL_LW_UART_PENDING_MASK (INTEL_LW_UART_STATUS_RRDY_MSK | \ + INTEL_LW_UART_STATUS_TRDY_MSK | INTEL_LW_UART_STATUS_E_MSK \ + | INTEL_LW_UART_STATUS_EOP_MSK) + +/***********************/ +/* configuration flags */ +/* + * The value INTEL_LW_UART_FB is a value set in the devices flag field to + * indicate that the device has a fixed baud rate; i.e. if this flag is set + * software can not control the baud rate of the device. + */ +#define INTEL_LW_UART_FB 0x1 + +/* + * The value INTEL_LW_UART_FC is a value set in the device flag field to + * indicate the the device is using flow control, i.e. the driver must + * throttle on transmit if the nCTS pin is low. + */ +#define INTEL_LW_UART_FC 0x2 + +/* end of configuration flags */ +/******************************/ + +/* device data */ +struct uart_intel_lw_device_data { + struct uart_config uart_cfg; /* stores uart config from device tree*/ + struct k_spinlock lock; + uint32_t status_act; /* stores value of status register. */ +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + uart_irq_callback_user_data_t cb; /**< Callback function pointer */ + void *cb_data; /**< Callback function arg */ +#ifdef CONFIG_UART_INTEL_LW_EOP + uint8_t set_eop_cb; + uart_irq_callback_user_data_t cb_eop; /**< Callback function pointer */ + void *cb_data_eop; /**< Callback function arg */ +#endif /* CONFIG_UART_INTEL_LW_EOP */ + uint32_t control_val; /* stores value to set control register. */ +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +}; + +/* + * device config: + * stores data that cannot be changed during run time. + */ +struct uart_intel_lw_device_config { + mm_reg_t base; + uint32_t flags; /* refer to configuration flags */ +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + uart_irq_config_func_t irq_config_func; + unsigned int irq_num; +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +}; + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN +/** + * function prototypes + */ +static int uart_intel_lw_irq_update(const struct device *dev); +static int uart_intel_lw_irq_tx_ready(const struct device *dev); +static int uart_intel_lw_irq_rx_ready(const struct device *dev); +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + +/** + * @brief Poll the device for input. + * + * This is a non-blocking function. + * + * This driver supports interrupt driven api. + * Polling for data under normal operation, might cause unexpected behaviour. + * If users wish to poll in for data, please ensure that the data is not retrieved + * in interrupt. + * + * If UART_LINE_CTRL is enabled, please do not disable the hardware + * interrupt for this uart device, as the flow control is handled in uart_intel_lw_dcts_isr. + * + * @param dev UART device instance + * @param p_char Pointer to character + * + * @return 0 if a character arrived, -1 if input buffer is empty. + * -EINVAL if p_char is null pointer + */ +static int uart_intel_lw_poll_in(const struct device *dev, unsigned char *p_char) +{ + const struct uart_intel_lw_device_config *config = dev->config; + struct uart_intel_lw_device_data *data = dev->data; + int ret_val = -1; + uint32_t status; + + /* generate fatal error if CONFIG_ASSERT is enabled. */ + __ASSERT(p_char != NULL, "p_char is null pointer!"); + + /* Stop, if p_char is null pointer */ + if (p_char == NULL) { + return -EINVAL; + } + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + /* check if received character is ready.*/ + status = sys_read32(config->base + INTEL_LW_UART_STATUS_REG_OFFSET); + if (status & INTEL_LW_UART_STATUS_RRDY_MSK) { + /* got a character */ + *p_char = sys_read32(config->base + INTEL_LW_UART_RXDATA_REG_OFFSET); + ret_val = 0; + } + + k_spin_unlock(&data->lock, key); + + return ret_val; +} + +/** + * @brief Output a character in polled mode. + * + * This function will block until transmitter is ready. + * Then, a character will be transmitted. + * + * This driver supports interrupt driven api. + * Polling for data under normal operation, might cause unexpected behaviour. + * If users wish to poll out data, please ensure that the data is not transmitted + * in interrupt. + * + * If UART_LINE_CTRL is enabled and users wish to poll out only 1 character, + * please enable UART_INTEL_LW_AUTO_LINE_CTRL_POLL. Please note that this might + * be inefficient, in case of polling out several characters. Instead of using + * UART_INTEL_LW_AUTO_LINE_CTRL_POLL, please consider using the api: uart_drv_cmd + * with CMD_POLL_ASSERT_RTS before polling out. Then use CMD_POLL_DEASSERT_RTS to + * resume normal operation after all characters are polled out. + * + * Please do not set CMD_TRBK_EN, when polling out data. + * + * @param dev UART device instance + * @param c Character to send + */ +static void uart_intel_lw_poll_out(const struct device *dev, unsigned char c) +{ + const struct uart_intel_lw_device_config *config = dev->config; + struct uart_intel_lw_device_data *data = dev->data; + uint32_t status; + bool tx_is_free = false; + bool poll_out_done = false; + k_spinlock_key_t key; + + /* wait until uart is free to transmit.*/ + do { + key = k_spin_lock(&data->lock); + + if (tx_is_free == false) { + status = sys_read32(config->base + INTEL_LW_UART_STATUS_REG_OFFSET); + + /* wait until there is space in fifo. */ + if (status & INTEL_LW_UART_STATUS_TRDY_MSK) { +#ifdef CONFIG_UART_INTEL_LW_AUTO_LINE_CTRL_POLL + data->control_val |= INTEL_LW_UART_CONTROL_RTS_MSK; + sys_write32(data->control_val, config->base + + INTEL_LW_UART_CONTROL_REG_OFFSET); +#endif + sys_write32(c, config->base + INTEL_LW_UART_TXDATA_REG_OFFSET); + tx_is_free = true; + } + } else { + status = sys_read32(config->base + INTEL_LW_UART_STATUS_REG_OFFSET); + + /* wait until fifo data is shifted out. */ + if (status & INTEL_LW_UART_STATUS_TMT_MSK) { +#ifdef CONFIG_UART_INTEL_LW_AUTO_LINE_CTRL_POLL + data->control_val &= ~INTEL_LW_UART_CONTROL_RTS_MSK; + sys_write32(data->control_val, config->base + + INTEL_LW_UART_CONTROL_REG_OFFSET); +#endif + poll_out_done = true; + } + } + + k_spin_unlock(&data->lock, key); + } while (!poll_out_done); +} + +/** + * @brief Initialise an instance of the driver + * + * This function initialise the interrupt configuration for the driver. + * + * @param dev UART device instance + * + * @return 0 to indicate success. + */ +static int uart_intel_lw_init(const struct device *dev) +{ +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + struct uart_intel_lw_device_data *data = dev->data; + const struct uart_intel_lw_device_config *config = dev->config; + /* clear status to ensure, that interrupts are not triggered due to old status. */ + sys_write32(INTEL_LW_UART_CLEAR_STATUS_VAL, config->base + + INTEL_LW_UART_STATUS_REG_OFFSET); + + /* + * Enable hardware interrupt. + * The corresponding csr from IP still needs to be set, + * so that the IP generates interrupt signal. + */ + config->irq_config_func(dev); + +#ifdef CONFIG_UART_LINE_CTRL + /* Enable DCTS interrupt. */ + data->control_val = INTEL_LW_UART_CONTROL_DCTS_MSK; +#endif /* CONFIG_UART_LINE_CTRL */ + + sys_write32(data->control_val, config->base + INTEL_LW_UART_CONTROL_REG_OFFSET); + +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + + return 0; +} + +/** + * @brief Check if an error was received + * If error is received, it will be mapped to uart_rx_stop_reason. + * This function should be called after irq_update. + * If interrupt driven API is not enabled, + * this function will read and clear the status register. + * + * @param dev UART device struct + * + * @return UART_ERROR_OVERRUN, UART_ERROR_PARITY, UART_ERROR_FRAMING, + * UART_BREAK if an error was detected, 0 otherwise. + */ +static int uart_intel_lw_err_check(const struct device *dev) +{ + struct uart_intel_lw_device_data *data = dev->data; + int err = UART_INTEL_LW_NO_ERROR; + +#ifndef CONFIG_UART_INTERRUPT_DRIVEN + const struct uart_intel_lw_device_config *config = dev->config; + k_spinlock_key_t key = k_spin_lock(&data->lock); + + data->status_act = sys_read32(config->base + INTEL_LW_UART_STATUS_REG_OFFSET); +#endif + + if (data->status_act & INTEL_LW_UART_STATUS_E_MSK) { + if (data->status_act & INTEL_LW_UART_STATUS_PE_MSK) { + err |= UART_ERROR_PARITY; + } + + if (data->status_act & INTEL_LW_UART_STATUS_FE_MSK) { + err |= UART_ERROR_FRAMING; + } + + if (data->status_act & INTEL_LW_UART_STATUS_BRK_MSK) { + err |= UART_BREAK; + } + + if (data->status_act & INTEL_LW_UART_STATUS_ROE_MSK) { + err |= UART_ERROR_OVERRUN; + } + } + +#ifndef CONFIG_UART_INTERRUPT_DRIVEN + /* clear status */ + sys_write32(INTEL_LW_UART_CLEAR_STATUS_VAL, config->base + + INTEL_LW_UART_STATUS_REG_OFFSET); + k_spin_unlock(&data->lock, key); +#endif + + return err; +} + +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE +/*** + * @brief helper function to check, if the configuration is support. + * The only parameter that can be changed during runtime is the baudrate. + * + * @param cfg_stored The original configuration. + * @param cfg_in The input configuration. + * @return true if parameter other than baudrate remains the same. otherwise, false. + */ +static bool uart_intel_lw_check_configuration(const struct uart_config *cfg_stored, + const struct uart_config *cfg_in) +{ + bool ret_val = false; + + if ((cfg_stored->parity == cfg_in->parity) + && (cfg_stored->stop_bits == cfg_in->stop_bits) + && (cfg_stored->data_bits == cfg_in->data_bits) + && (cfg_stored->flow_ctrl == cfg_in->flow_ctrl)) { + ret_val = true; + } + + return ret_val; +} + +/** + * @brief Set UART configuration using data from *cfg_in. + * + * @param dev UART Device struct + * @param cfg_in The input configuration. + * + * @return 0 if success, -ENOTSUP, if input from cfg_in is not configurable. + * -EINVAL if cfg_in is null pointer + */ +static int uart_intel_lw_configure(const struct device *dev, + const struct uart_config *cfg_in) +{ + const struct uart_intel_lw_device_config *config = dev->config; + struct uart_intel_lw_device_data * const data = dev->data; + struct uart_config * const cfg_stored = &data->uart_cfg; + uint32_t divisor_val; + int ret_val; + + /* generate fatal error if CONFIG_ASSERT is enabled. */ + __ASSERT(cfg_in != NULL, "cfg_in is null pointer!"); + + /* Stop, if cfg_in is null pointer */ + if (cfg_in == NULL) { + return -EINVAL; + } + + /* check if configuration is supported. */ + if (uart_intel_lw_check_configuration(cfg_stored, cfg_in) + && !(config->flags & INTEL_LW_UART_FB)) { + /* parameter is valid, just return ok if baudrate is the same. */ + if (cfg_stored->baudrate != cfg_in->baudrate) { + /* calculate and set baudrate. */ + divisor_val = (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC/cfg_in->baudrate) - 1; + sys_write32(divisor_val, config->base + INTEL_LW_UART_DIVISOR_REG_OFFSET); + + /* update stored data. */ + cfg_stored->baudrate = cfg_in->baudrate; + } + + ret_val = 0; + } else { + /* return not supported */ + ret_val = -ENOTSUP; + } + + return ret_val; +} +#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ + +/** + * @brief Get UART configuration and stores in *cfg_out. + * + * @param dev UART Device struct + * @param cfg_out The output configuration. + * + * @return 0 if success. + * -EINVAL if cfg_out is null pointer + */ +static int uart_intel_lw_config_get(const struct device *dev, + struct uart_config *cfg_out) +{ + const struct uart_intel_lw_device_data *data = dev->data; + + /* generate fatal error if CONFIG_ASSERT is enabled. */ + __ASSERT(cfg_out != NULL, "cfg_out is null pointer!"); + + /* Stop, if cfg_out is null pointer */ + if (cfg_out == NULL) { + return -EINVAL; + } + + *cfg_out = data->uart_cfg; + return 0; +} + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN +/** + * @brief Fill FIFO with data + * This function is expected to be called from UART interrupt handler (ISR), + * if uart_irq_tx_ready() returns true. This function does not block! + * + * @param dev UART device struct + * @param tx_data Data to transmit + * @param size Number of bytes to send + * + * @return Number of bytes sent + */ +static int uart_intel_lw_fifo_fill(const struct device *dev, + const uint8_t *tx_data, + int size) +{ + const struct uart_intel_lw_device_config *config = dev->config; + struct uart_intel_lw_device_data *data = dev->data; + int ret_val = 0; + k_spinlock_key_t key; + + /* generate fatal error if CONFIG_ASSERT is enabled. */ + __ASSERT(tx_data != NULL, "tx_data is null pointer!"); + + /* Stop, if tx_data is null pointer */ + if (tx_data == NULL) { + return 0; + } + + /* Stop, if transmit break is set */ + if (data->control_val & INTEL_LW_UART_CONTROL_TRBK_MSK) { + return 0; + } + + do { + if (data->status_act & INTEL_LW_UART_STATUS_TRDY_MSK) { + key = k_spin_lock(&data->lock); + sys_write32(tx_data[ret_val++], config->base + + INTEL_LW_UART_TXDATA_REG_OFFSET); + data->status_act = sys_read32(config->base + + INTEL_LW_UART_STATUS_REG_OFFSET); + k_spin_unlock(&data->lock, key); + } else { + /* stop because tx fifo is full! */ + break; + } + } while ((size - ret_val) > 0); + + return ret_val; +} + +/** + * @brief Read data from FIFO + * This function is expected to be called from UART interrupt handler (ISR), + * if uart_irq_rx_ready() returns true. + * + * @param dev UART device struct + * @param rx_data Data container + * @param size Container size + * + * @return Number of bytes read + */ +static int uart_intel_lw_fifo_read(const struct device *dev, uint8_t *rx_data, + const int size) +{ + const struct uart_intel_lw_device_config *config = dev->config; + struct uart_intel_lw_device_data *data = dev->data; + int ret_val = 0; + k_spinlock_key_t key; + + /* generate fatal error if CONFIG_ASSERT is enabled. */ + __ASSERT(rx_data != NULL, "rx_data is null pointer!"); + + /* Stop, if rx_data is null pointer */ + if (rx_data == NULL) { + return 0; + } + + do { + if (data->status_act & INTEL_LW_UART_STATUS_RRDY_MSK) { + key = k_spin_lock(&data->lock); + rx_data[ret_val++] = sys_read32(config->base + + INTEL_LW_UART_RXDATA_REG_OFFSET); + data->status_act = sys_read32(config->base + + INTEL_LW_UART_STATUS_REG_OFFSET); + + k_spin_unlock(&data->lock, key); + } else { + break; + } + } while ((size - ret_val) > 0); + + return ret_val; +} + +/** + * @brief Enable TX interrupt + * + * @param dev UART device struct + */ +static void uart_intel_lw_irq_tx_enable(const struct device *dev) +{ + struct uart_intel_lw_device_data *data = dev->data; + const struct uart_intel_lw_device_config *config = dev->config; + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + data->control_val |= INTEL_LW_UART_CONTROL_TRDY_MSK; + +#ifdef CONFIG_UART_LINE_CTRL + /* also enable RTS, if flow control is enabled. */ + data->control_val |= INTEL_LW_UART_CONTROL_RTS_MSK; +#endif + + sys_write32(data->control_val, config->base + INTEL_LW_UART_CONTROL_REG_OFFSET); + + k_spin_unlock(&data->lock, key); +} + +/** + * @brief Disable TX interrupt + * + * @param dev UART device struct + */ +static void uart_intel_lw_irq_tx_disable(const struct device *dev) +{ + struct uart_intel_lw_device_data *data = dev->data; + const struct uart_intel_lw_device_config *config = dev->config; + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + data->control_val &= ~INTEL_LW_UART_CONTROL_TRDY_MSK; + +#ifdef CONFIG_UART_LINE_CTRL + /* also disable RTS, if flow control is enabled. */ + data->control_val &= ~INTEL_LW_UART_CONTROL_RTS_MSK; +#endif + + sys_write32(data->control_val, config->base + INTEL_LW_UART_CONTROL_REG_OFFSET); + + k_spin_unlock(&data->lock, key); +} + +/** + * @brief Check if UART TX buffer can accept a new char. + * + * @param dev UART device struct + * + * @return 1 if TX interrupt is enabled and at least one char can be written to UART. + * 0 if device is not ready to write a new byte. + */ +static int uart_intel_lw_irq_tx_ready(const struct device *dev) +{ + struct uart_intel_lw_device_data *data = dev->data; + int ret_val = 0; + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + /* if TX interrupt is enabled */ + if (data->control_val & INTEL_LW_UART_CONTROL_TRDY_MSK) { + /* IP core does not have fifo. Wait until tx data is completely shifted. */ + if (data->status_act & INTEL_LW_UART_STATUS_TMT_MSK) { + ret_val = 1; + } + } + +#ifdef CONFIG_UART_LINE_CTRL + /* if flow control is enabled, set tx not ready, if CTS is low. */ + if ((data->status_act & INTEL_LW_UART_STATUS_CTS_MSK) == 0) { + ret_val = 0; + } + +#endif /* CONFIG_UART_LINE_CTRL */ + + k_spin_unlock(&data->lock, key); + + return ret_val; +} + +/** + * @brief Check if nothing remains to be transmitted + * + * @param dev UART device struct + * + * @return 1 if nothing remains to be transmitted, 0 otherwise + */ +static int uart_intel_lw_irq_tx_complete(const struct device *dev) +{ + struct uart_intel_lw_device_data *data = dev->data; + int ret_val = 0; + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + if (data->status_act & INTEL_LW_UART_STATUS_TMT_MSK) { + ret_val = 1; + } + + k_spin_unlock(&data->lock, key); + + return ret_val; +} + +/** + * @brief Enable RX interrupt in + * + * @param dev UART device struct + */ +static void uart_intel_lw_irq_rx_enable(const struct device *dev) +{ + struct uart_intel_lw_device_data *data = dev->data; + const struct uart_intel_lw_device_config *config = dev->config; + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + data->control_val |= INTEL_LW_UART_CONTROL_RRDY_MSK; + sys_write32(data->control_val, config->base + INTEL_LW_UART_CONTROL_REG_OFFSET); + + k_spin_unlock(&data->lock, key); +} + +/** + * @brief Disable RX interrupt + * + * @param dev UART device struct + */ +static void uart_intel_lw_irq_rx_disable(const struct device *dev) +{ + struct uart_intel_lw_device_data *data = dev->data; + const struct uart_intel_lw_device_config *config = dev->config; + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + data->control_val &= ~INTEL_LW_UART_CONTROL_RRDY_MSK; + sys_write32(data->control_val, config->base + INTEL_LW_UART_CONTROL_REG_OFFSET); + + k_spin_unlock(&data->lock, key); +} + +/** + * @brief Check if Rx IRQ has been raised + * + * @param dev UART device struct + * + * @return 1 if an IRQ is ready, 0 otherwise + */ +static int uart_intel_lw_irq_rx_ready(const struct device *dev) +{ + struct uart_intel_lw_device_data *data = dev->data; + int ret_val = 0; + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + /* if RX interrupt is enabled */ + if (data->control_val & INTEL_LW_UART_CONTROL_RRDY_MSK) { + /* check for space in rx data register */ + if (data->status_act & INTEL_LW_UART_STATUS_RRDY_MSK) { + ret_val = 1; + } + } + + k_spin_unlock(&data->lock, key); + + return ret_val; +} + +/** + * @brief This function will cache the status register. + * + * @param dev UART device struct + * + * @return 1 for success. + */ +static int uart_intel_lw_irq_update(const struct device *dev) +{ + struct uart_intel_lw_device_data *data = dev->data; + const struct uart_intel_lw_device_config *config = dev->config; + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + data->status_act = sys_read32(config->base + INTEL_LW_UART_STATUS_REG_OFFSET); + + k_spin_unlock(&data->lock, key); + + return 1; +} + +/** + * @brief Check if any IRQ is pending + * + * @param dev UART device struct + * + * @return 1 if an IRQ is pending, 0 otherwise + */ +static int uart_intel_lw_irq_is_pending(const struct device *dev) +{ + struct uart_intel_lw_device_data *data = dev->data; + int ret_val = 0; + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + if (data->status_act & data->control_val & INTEL_LW_UART_PENDING_MASK) { + ret_val = 1; + } + + k_spin_unlock(&data->lock, key); + + return ret_val; +} + +/** + * @brief Set the callback function pointer for IRQ. + * + * @param dev UART device struct + * @param cb Callback function pointer. + * @param cb_data Data to pass to callback function. + */ +static void uart_intel_lw_irq_callback_set(const struct device *dev, + uart_irq_callback_user_data_t cb, + void *cb_data) +{ + struct uart_intel_lw_device_data *data = dev->data; + + k_spinlock_key_t key = k_spin_lock(&data->lock); + +#ifdef CONFIG_UART_INTEL_LW_EOP + if (data->set_eop_cb) { + data->cb_eop = cb; + data->cb_data_eop = cb_data; + data->set_eop_cb = 0; + } else { + data->cb = cb; + data->cb_data = cb_data; + } +#else + data->cb = cb; + data->cb_data = cb_data; +#endif /* CONFIG_UART_INTEL_LW_EOP */ + + k_spin_unlock(&data->lock, key); +} + +#ifdef CONFIG_UART_LINE_CTRL +/** + * @brief DCTS Interrupt service routine. + * + * Handles assertion and deassettion of CTS/RTS stignal + * + * @param dev Pointer to UART device struct + */ +static void uart_intel_lw_dcts_isr(const struct device *dev) +{ + struct uart_intel_lw_device_data *data = dev->data; + const struct uart_intel_lw_device_config *config = dev->config; + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + /* Assume that user follows zephyr requirement and update status in their call back. */ + if (data->status_act & INTEL_LW_UART_STATUS_CTS_MSK) { + + /* Assert RTS to inform other UART. */ + data->control_val |= INTEL_LW_UART_CONTROL_RTS_MSK; + sys_write32(data->control_val, config->base + + INTEL_LW_UART_CONTROL_REG_OFFSET); + } else { + /* other UART deasserts RTS */ + if (data->status_act & INTEL_LW_UART_STATUS_TMT_MSK) { + /* only deasserts if not transmitting. */ + data->control_val &= ~INTEL_LW_UART_CONTROL_RTS_MSK; + sys_write32(data->control_val, config->base + + INTEL_LW_UART_CONTROL_REG_OFFSET); + } + } + + k_spin_unlock(&data->lock, key); +} +#endif /* CONFIG_UART_LINE_CTRL */ + +/** + * @brief Interrupt service routine. + * + * This simply calls the callback function, if one exists. + * + * @param dev Pointer to UART device struct + * + */ +static void uart_intel_lw_isr(const struct device *dev) +{ + struct uart_intel_lw_device_data *data = dev->data; + const struct uart_intel_lw_device_config *config = dev->config; + + uart_irq_callback_user_data_t callback = data->cb; + + if (callback) { + callback(dev, data->cb_data); + } + + /* Post ISR */ +#if CONFIG_UART_INTEL_LW_EOP + data->status_act = sys_read32(config->base + INTEL_LW_UART_STATUS_REG_OFFSET); + if (data->status_act & INTEL_LW_UART_STATUS_EOP_MSK) { + callback = data->cb_eop; + if (callback) { + callback(dev, data->cb_data_eop); + } + } +#endif /* CONFIG_UART_INTEL_LW_EOP */ + +#ifdef CONFIG_UART_LINE_CTRL + data->status_act = sys_read32(config->base + INTEL_LW_UART_STATUS_REG_OFFSET); + /* handles RTS/CTS signal */ + if (data->status_act & INTEL_LW_UART_STATUS_DCTS_MSK) { + uart_intel_lw_dcts_isr(dev); + } +#endif + + /* clear status after all interrupts are handled. */ + sys_write32(INTEL_LW_UART_CLEAR_STATUS_VAL, config->base + + INTEL_LW_UART_STATUS_REG_OFFSET); +} + +#ifdef CONFIG_UART_DRV_CMD +/** + * @brief Send extra command to driver + * + * @param dev UART device struct + * @param cmd Command to driver + * @param p Parameter to the command + * + * @return 0 if successful, failed otherwise + */ +static int uart_intel_lw_drv_cmd(const struct device *dev, uint32_t cmd, + uint32_t p) +{ + struct uart_intel_lw_device_data *data = dev->data; + const struct uart_intel_lw_device_config *config = dev->config; + + int ret_val = -ENOTSUP; + k_spinlock_key_t key = k_spin_lock(&data->lock); + + switch (cmd) { +#if CONFIG_UART_INTEL_LW_EOP + case CMD_ENABLE_EOP: + /* enable EOP interrupt */ + data->control_val |= INTEL_LW_UART_CONTROL_EOP_MSK; + sys_write32(data->control_val, config->base + + INTEL_LW_UART_CONTROL_REG_OFFSET); + + /* set EOP character */ + sys_write32((uint8_t) p, config->base + INTEL_LW_UART_EOP_REG_OFFSET); + + /* after this, user needs to call uart_irq_callback_set + * to set data->cb_eop and data->cb_data_eop! + */ + data->set_eop_cb = 1; + ret_val = 0; + break; + + case CMD_DISABLE_EOP: + /* disable EOP interrupt */ + data->control_val &= ~INTEL_LW_UART_CONTROL_EOP_MSK; + sys_write32(data->control_val, config->base + + INTEL_LW_UART_CONTROL_REG_OFFSET); + + /* clear call back */ + data->cb_eop = NULL; + data->cb_data_eop = NULL; + ret_val = 0; + break; +#endif /* CONFIG_UART_INTEL_LW_EOP */ + + case CMD_TRBK_EN: + /* enable transmit break */ + data->control_val |= INTEL_LW_UART_CONTROL_TRBK_MSK; + sys_write32(data->control_val, config->base + + INTEL_LW_UART_CONTROL_REG_OFFSET); + ret_val = 0; + break; + + case CMD_TRBK_DIS: + /* disable transmit break */ + data->control_val &= ~INTEL_LW_UART_CONTROL_TRBK_MSK; + sys_write32(data->control_val, config->base + + INTEL_LW_UART_CONTROL_REG_OFFSET); + ret_val = 0; + break; + + case CMD_POLL_ASSERT_RTS: + /* assert RTS */ + data->control_val |= INTEL_LW_UART_CONTROL_RTS_MSK; + sys_write32(data->control_val, config->base + + INTEL_LW_UART_CONTROL_REG_OFFSET); + ret_val = 0; + break; + + case CMD_POLL_DEASSERT_RTS: + /* deassert RTS */ + data->control_val &= ~INTEL_LW_UART_CONTROL_RTS_MSK; + sys_write32(data->control_val, config->base + + INTEL_LW_UART_CONTROL_REG_OFFSET); + ret_val = 0; + break; + + default: + ret_val = -ENOTSUP; + break; + }; + + k_spin_unlock(&data->lock, key); + + return ret_val; +} + +#endif /* CONFIG_UART_DRV_CMD */ + +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + +static const struct uart_driver_api uart_intel_lw_driver_api = { + .poll_in = uart_intel_lw_poll_in, + .poll_out = uart_intel_lw_poll_out, + .err_check = uart_intel_lw_err_check, +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE + .configure = uart_intel_lw_configure, +#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ + .config_get = uart_intel_lw_config_get, + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + .fifo_fill = uart_intel_lw_fifo_fill, + .fifo_read = uart_intel_lw_fifo_read, + .irq_tx_enable = uart_intel_lw_irq_tx_enable, + .irq_tx_disable = uart_intel_lw_irq_tx_disable, + .irq_tx_ready = uart_intel_lw_irq_tx_ready, + .irq_tx_complete = uart_intel_lw_irq_tx_complete, + .irq_rx_enable = uart_intel_lw_irq_rx_enable, + .irq_rx_disable = uart_intel_lw_irq_rx_disable, + .irq_rx_ready = uart_intel_lw_irq_rx_ready, + .irq_is_pending = uart_intel_lw_irq_is_pending, + .irq_update = uart_intel_lw_irq_update, + .irq_callback_set = uart_intel_lw_irq_callback_set, +#endif + +#ifdef CONFIG_UART_DRV_CMD + .drv_cmd = uart_intel_lw_drv_cmd, +#endif +}; + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + +#define UART_INTEL_LW_IRQ_CONFIG_FUNC(n) \ + static void uart_intel_lw_irq_config_func_##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), \ + DT_INST_IRQ(n, priority), \ + uart_intel_lw_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + \ + irq_enable(DT_INST_IRQN(n)); \ + } + +#define UART_INTEL_LW_IRQ_CONFIG_INIT(n) \ + .irq_config_func = uart_intel_lw_irq_config_func_##n, \ + .irq_num = DT_INST_IRQN(n), + +#else + +#define UART_INTEL_LW_IRQ_CONFIG_FUNC(n) +#define UART_INTEL_LW_IRQ_CONFIG_INIT(n) + +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + +#define UART_INTEL_LW_DEVICE_INIT(n) \ +UART_INTEL_LW_IRQ_CONFIG_FUNC(n) \ +static struct uart_intel_lw_device_data uart_intel_lw_dev_data_##n = { \ + .uart_cfg = \ + { \ + .baudrate = DT_INST_PROP(n, current_speed), \ + .parity = DT_INST_ENUM_IDX_OR(n, parity, \ + UART_CFG_PARITY_NONE), \ + .stop_bits = DT_INST_ENUM_IDX_OR(n, stop_bits, \ + UART_CFG_STOP_BITS_1), \ + .data_bits = DT_INST_ENUM_IDX_OR(n, data_bits, \ + UART_CFG_DATA_BITS_8), \ + .flow_ctrl = DT_INST_PROP(n, hw_flow_control) ? \ + UART_CFG_FLOW_CTRL_RTS_CTS : \ + UART_CFG_FLOW_CTRL_NONE, \ + }, \ +}; \ + \ +static const struct uart_intel_lw_device_config uart_intel_lw_dev_cfg_##n = { \ + .base = DT_INST_REG_ADDR(n), \ + .flags = ((DT_INST_PROP(n, fixed_baudrate)?INTEL_LW_UART_FB:0) \ + |(DT_INST_PROP(n, hw_flow_control)?INTEL_LW_UART_FC:0)),\ + UART_INTEL_LW_IRQ_CONFIG_INIT(n) \ +}; \ + \ +DEVICE_DT_INST_DEFINE(n, \ + uart_intel_lw_init, \ + NULL, \ + &uart_intel_lw_dev_data_##n, \ + &uart_intel_lw_dev_cfg_##n, \ + PRE_KERNEL_1, \ + CONFIG_SERIAL_INIT_PRIORITY, \ + &uart_intel_lw_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(UART_INTEL_LW_DEVICE_INIT) diff --git a/drivers/serial/uart_liteuart.c b/drivers/serial/uart_liteuart.c index 073d565770e..d23b68b7c5c 100644 --- a/drivers/serial/uart_liteuart.c +++ b/drivers/serial/uart_liteuart.c @@ -273,8 +273,8 @@ static void liteuart_uart_irq_handler(const struct device *dev) data->callback(dev, data->cb_data); } - /* clear events */ - litex_write8(UART_EV_TX | UART_EV_RX, UART_EV_PENDING_ADDR); + /* Clear RX events, TX events still needed to enqueue the next transfer */ + litex_write8(UART_EV_RX, UART_EV_PENDING_ADDR); irq_unlock(key); } diff --git a/drivers/serial/uart_mchp_xec.c b/drivers/serial/uart_mchp_xec.c index 12143a2d20b..603a00656ad 100644 --- a/drivers/serial/uart_mchp_xec.c +++ b/drivers/serial/uart_mchp_xec.c @@ -219,7 +219,7 @@ struct uart_xec_dev_data { static const struct uart_driver_api uart_xec_driver_api; -#ifdef CONFIG_PM_DEVICE +#if defined(CONFIG_PM_DEVICE) && defined(CONFIG_UART_CONSOLE_INPUT_EXPIRED) static void uart_xec_pm_policy_state_lock_get(enum uart_xec_pm_policy_state_flag flag) { if (atomic_test_and_set_bit(pm_policy_state_flag, flag) == 0) { @@ -644,7 +644,7 @@ static int uart_xec_fifo_fill(const struct device *dev, const uint8_t *tx_data, k_spinlock_key_t key = k_spin_lock(&dev_data->lock); for (i = 0; (i < size) && (regs->LSR & LSR_THRE) != 0; i++) { -#ifdef CONFIG_PM_DEVICE +#if defined(CONFIG_PM_DEVICE) && defined(CONFIG_UART_CONSOLE_INPUT_EXPIRED) uart_xec_pm_policy_state_lock_get(UART_XEC_PM_POLICY_STATE_TX_FLAG); #endif regs->RTXB = tx_data[i]; @@ -933,7 +933,7 @@ static void uart_xec_isr(const struct device *dev) dev_data->cb(dev, dev_data->cb_data); } -#ifdef CONFIG_PM_DEVICE +#if defined(CONFIG_PM_DEVICE) && defined(CONFIG_UART_CONSOLE_INPUT_EXPIRED) if (uart_xec_irq_tx_complete(dev)) { uart_xec_pm_policy_state_lock_put(UART_XEC_PM_POLICY_STATE_TX_FLAG); } diff --git a/drivers/serial/uart_mcux_iuart.c b/drivers/serial/uart_mcux_iuart.c index 09ae22c906e..9a1f73f2a21 100644 --- a/drivers/serial/uart_mcux_iuart.c +++ b/drivers/serial/uart_mcux_iuart.c @@ -19,6 +19,8 @@ struct mcux_iuart_config { const struct device *clock_dev; clock_control_subsys_t clock_subsys; uint32_t baud_rate; + /* initial parity, 0 for none, 1 for odd, 2 for even */ + uint8_t parity; const struct pinctrl_dev_config *pincfg; #ifdef CONFIG_UART_INTERRUPT_DRIVEN void (*irq_config_func)(const struct device *dev); @@ -242,6 +244,20 @@ static int mcux_iuart_init(const struct device *dev) uart_config.baudRate_Bps = config->baud_rate; clock_control_on(config->clock_dev, config->clock_subsys); + switch (config->parity) { + case UART_CFG_PARITY_NONE: + uart_config.parityMode = kUART_ParityDisabled; + break; + case UART_CFG_PARITY_EVEN: + uart_config.parityMode = kUART_ParityEven; + break; + case UART_CFG_PARITY_ODD: + uart_config.parityMode = kUART_ParityOdd; + break; + default: + return -ENOTSUP; + } + UART_Init(config->base, &uart_config, clock_freq); err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); @@ -313,6 +329,7 @@ static const struct mcux_iuart_config mcux_iuart_##n##_config = { \ .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ .clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, name),\ .baud_rate = DT_INST_PROP(n, current_speed), \ + .parity = DT_INST_ENUM_IDX_OR(n, parity, UART_CFG_PARITY_NONE), \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ IRQ_FUNC_INIT \ } diff --git a/drivers/serial/uart_native_tty.c b/drivers/serial/uart_native_tty.c index 2027279d440..22f2b0e539f 100644 --- a/drivers/serial/uart_native_tty.c +++ b/drivers/serial/uart_native_tty.c @@ -5,7 +5,7 @@ * /dev/ttyACM0). Only polling Uart API is implemented. Driver can be configured via devicetree, * command line options or at runtime. * - * To learn more see Native TYY section at: + * To learn more see Native TTY section at: * https://docs.zephyrproject.org/latest/boards/posix/native_posix/doc/index.html * or * ${ZEPHYR_BASE}/boards/posix/native_posix/doc/index.rst @@ -18,18 +18,15 @@ #include #include -#include -#include -#include -#include -#include -#include +#include #include "cmdline.h" #include "posix_native_task.h" +#include "uart_native_tty_bottom.h" +#include "nsi_host_trampolines.h" -#define WARN(msg, ...) posix_print_warning(msg, ##__VA_ARGS__) -#define ERROR(msg, ...) posix_print_error_and_exit(msg, ##__VA_ARGS__) +#define WARN(...) nsi_print_warning(__VA_ARGS__) +#define ERROR(...) nsi_print_error_and_exit(__VA_ARGS__) #define DT_DRV_COMPAT zephyr_native_tty_uart @@ -48,170 +45,68 @@ struct native_tty_config { struct uart_config uart_config; }; -struct baudrate_termios_pair { - int baudrate; - speed_t termios_baudrate; -}; - -/** - * @brief Lookup table for mapping the baud rate to the macro understood by termios. - */ -static const struct baudrate_termios_pair baudrate_lut[] = { - {1200, B1200}, {1800, B1800}, {2400, B2400}, {4800, B4800}, - {9600, B9600}, {19200, B19200}, {38400, B38400}, {57600, B57600}, - {115200, B115200}, {230400, B230400}, {460800, B460800}, {500000, B500000}, - {576000, B576000}, {921600, B921600}, {1000000, B1000000}, {1152000, B1152000}, - {1500000, B1500000}, {2000000, B2000000}, {2500000, B2500000}, {3000000, B3000000}, - {3500000, B3500000}, {4000000, B4000000}, -}; - -/** - * @brief Set given termios to defaults appropriate for communicating with serial port devices. - * - * @param ter - */ -static inline void native_tty_termios_defaults_set(struct termios *ter) -{ - /* Set terminal in "serial" mode: - * - Not canonical (no line input) - * - No signal generation from Ctr+{C|Z..} - * - No echoing - */ - ter->c_lflag &= ~(ICANON | ISIG | ECHO); - - /* No special interpretation of output bytes. - * No conversion of newline to carriage return/line feed. - */ - ter->c_oflag &= ~(OPOST | ONLCR); - - /* No software flow control. */ - ter->c_iflag &= ~(IXON | IXOFF | IXANY); - - /* No blocking, return immediately with what is available. */ - ter->c_cc[VMIN] = 0; - ter->c_cc[VTIME] = 0; - - /* No special handling of bytes on receive. */ - ter->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); - - /* - Enable reading data and ignore control lines */ - ter->c_cflag |= CREAD | CLOCAL; -} - /** - * @brief Set the baud rate speed in the termios structure + * @brief Convert from uart_config to native_tty_bottom_cfg eqvivalent struct * - * @param ter - * @param baudrate + * @param bottom_cfg + * @param cfg * - * @retval 0 If successful, - * @retval -ENOTSUP If requested baud rate is not supported. + * @return 0 on success, negative errno otherwise. */ -static inline int native_tty_baud_speed_set(struct termios *ter, int baudrate) +static int native_tty_conv_to_bottom_cfg(struct native_tty_bottom_cfg *bottom_cfg, + const struct uart_config *cfg) { - for (int i = 0; i < ARRAY_SIZE(baudrate_lut); i++) { - if (baudrate_lut[i].baudrate == baudrate) { - cfsetospeed(ter, baudrate_lut[i].termios_baudrate); - cfsetispeed(ter, baudrate_lut[i].termios_baudrate); - return 0; - } - } - return -ENOTSUP; -} + bottom_cfg->baudrate = cfg->baudrate; -/** - * @brief Set parity setting in the termios structure - * - * @param ter - * @param parity - * - * @retval 0 If successful. - * @retval -ENOTSUP If requested parity is not supported. - */ -static inline int native_tty_baud_parity_set(struct termios *ter, enum uart_config_parity parity) -{ - switch (parity) { + switch (cfg->parity) { case UART_CFG_PARITY_NONE: - ter->c_cflag &= ~PARENB; + bottom_cfg->parity = NTB_PARITY_NONE; break; case UART_CFG_PARITY_ODD: - ter->c_cflag |= PARENB; - ter->c_cflag |= PARODD; + bottom_cfg->parity = NTB_PARITY_ODD; break; case UART_CFG_PARITY_EVEN: - ter->c_cflag |= PARENB; - ter->c_cflag &= ~PARODD; + bottom_cfg->parity = NTB_PARITY_EVEN; break; default: - /* Parity options mark and space (UART_CFG_PARITY_MARK and UART_CFG_PARITY_SPACE) - * are not supported on this driver. - */ return -ENOTSUP; } - return 0; -} -/** - * @brief Set the number of stop bits in the termios structure - * - * @param ter - * @param stop_bits - * - * @retval 0 If successful. - * @retval -ENOTSUP If requested number of stop bits is not supported. - */ -static inline int native_tty_stop_bits_set(struct termios *ter, - enum uart_config_stop_bits stop_bits) -{ - switch (stop_bits) { + switch (cfg->data_bits) { case UART_CFG_STOP_BITS_1: - ter->c_cflag &= ~CSTOPB; + bottom_cfg->stop_bits = NTB_STOP_BITS_1; break; case UART_CFG_STOP_BITS_2: - ter->c_cflag |= CSTOPB; + bottom_cfg->stop_bits = NTB_STOP_BITS_2; break; default: - /* Anything else is not supported in termios. */ return -ENOTSUP; } - return 0; -} -/** - * @brief Set the number of data bits in the termios structure - * - * @param ter - * @param stop_bits - * - * @retval 0 If successful. - * @retval -ENOTSUP If requested number of data bits is not supported. - */ -static inline int native_tty_data_bits_set(struct termios *ter, - enum uart_config_data_bits data_bits) -{ - unsigned int data_bits_to_set; - - switch (data_bits) { + switch (cfg->data_bits) { case UART_CFG_DATA_BITS_5: - data_bits_to_set = CS5; + bottom_cfg->data_bits = NTB_DATA_BITS_5; break; case UART_CFG_DATA_BITS_6: - data_bits_to_set = CS6; + bottom_cfg->data_bits = NTB_DATA_BITS_6; break; case UART_CFG_DATA_BITS_7: - data_bits_to_set = CS7; + bottom_cfg->data_bits = NTB_DATA_BITS_7; break; case UART_CFG_DATA_BITS_8: - data_bits_to_set = CS8; + bottom_cfg->data_bits = NTB_DATA_BITS_8; break; default: - /* Anything else is not supported in termios */ return -ENOTSUP; } - /* Clear all bits that set the data size */ - ter->c_cflag &= ~CSIZE; - ter->c_cflag |= data_bits_to_set; + if (cfg->flow_ctrl != UART_CFG_FLOW_CTRL_NONE) { + WARN("Could not set flow control, any kind of hw flow control is not supported.\n"); + return -ENOTSUP; + } + + bottom_cfg->flow_ctrl = NTB_FLOW_CTRL_NONE; + return 0; } @@ -225,10 +120,10 @@ static void native_tty_uart_poll_out(const struct device *dev, unsigned char out { struct native_tty_data *data = dev->data; - int ret = write(data->fd, &out_char, 1); + int ret = nsi_host_write(data->fd, &out_char, 1); if (ret == -1) { - ERROR("Could not write to %s, reason: %s\n", data->serial_port, strerror(errno)); + ERROR("Could not write to %s\n", data->serial_port); } } @@ -245,91 +140,21 @@ static int native_tty_uart_poll_in(const struct device *dev, unsigned char *p_ch { struct native_tty_data *data = dev->data; - return read(data->fd, p_char, 1) > 0 ? 0 : -1; + return nsi_host_read(data->fd, p_char, 1) > 0 ? 0 : -1; } static int native_tty_configure(const struct device *dev, const struct uart_config *cfg) { - int rc, err; int fd = ((struct native_tty_data *)dev->data)->fd; + struct native_tty_bottom_cfg bottom_cfg; - /* Structure used to control properties of a serial port */ - struct termios ter; - - /* Read current terminal driver settings */ - rc = tcgetattr(fd, &ter); - if (rc) { - WARN("Could not read terminal driver settings\n"); - return rc; - } - - native_tty_termios_defaults_set(&ter); - - rc = native_tty_baud_speed_set(&ter, cfg->baudrate); - if (rc) { - WARN("Could not set baudrate, as %d is not supported.\n", cfg->baudrate); - return rc; - } - - rc = native_tty_baud_parity_set(&ter, cfg->parity); - if (rc) { - WARN("Could not set parity.\n"); - return rc; - } - - rc = native_tty_stop_bits_set(&ter, cfg->stop_bits); - if (rc) { - WARN("Could not set number of data bits.\n"); - return rc; - } - - rc = native_tty_data_bits_set(&ter, cfg->data_bits); - if (rc) { - WARN("Could not set number of data bits.\n"); - return rc; - } - - if (cfg->flow_ctrl != UART_CFG_FLOW_CTRL_NONE) { - WARN("Could not set flow control, any kind of hw flow control is not supported.\n"); - return -ENOTSUP; - } - - rc = tcsetattr(fd, TCSANOW, &ter); - if (rc) { - err = errno; - WARN("Could not set serial port settings, reason: %s\n", strerror(err)); - return err; - } - - /* tcsetattr returns success if ANY of the requested changes were successfully carried out, - * not if ALL were. So we need to read back the settings and check if they are equal to the - * requested ones. - */ - struct termios read_ter; - - rc = tcgetattr(fd, &read_ter); + int rc = native_tty_conv_to_bottom_cfg(&bottom_cfg, cfg); if (rc) { - err = errno; - WARN("Could not read serial port settings, reason: %s\n", strerror(err)); - return err; - } - - if (ter.c_cflag != read_ter.c_cflag || ter.c_iflag != read_ter.c_iflag || - ter.c_oflag != read_ter.c_oflag || ter.c_lflag != read_ter.c_lflag || - ter.c_line != read_ter.c_line || ter.c_ispeed != read_ter.c_ispeed || - ter.c_ospeed != read_ter.c_ospeed || 0 != memcmp(ter.c_cc, read_ter.c_cc, NCCS)) { - WARN("Read serial port settings do not match set ones.\n"); - return -EBADE; - } - - /* Flush both input and output */ - rc = tcflush(fd, TCIOFLUSH); - if (rc) { - WARN("Could not flush serial port\n"); + WARN("Could not convert uart config to native tty bottom cfg\n"); return rc; } - return 0; + return native_tty_configure_bottom(fd, &bottom_cfg); } static int native_tty_serial_init(const struct device *dev) @@ -337,22 +162,24 @@ static int native_tty_serial_init(const struct device *dev) struct native_tty_data *data = dev->data; struct uart_config uart_config = ((struct native_tty_config *)dev->config)->uart_config; - /* Default value for cmd_serial_port is NULL, this is due to the set 's' type in command - * line opts. If it is anything else then it was configured via command line. + /* Default value for cmd_serial_port is NULL, this is due to the set 's' type in + * command line opts. If it is anything else then it was configured via command + * line. */ if (data->cmd_serial_port) { data->serial_port = data->cmd_serial_port; } - /* Default value for cmd_baudrate is UINT32_MAX, this is due to the set 'u' type in command - * line opts. If it is anything else then it was configured via command line. + /* Default value for cmd_baudrate is UINT32_MAX, this is due to the set 'u' type in + * command line opts. If it is anything else then it was configured via command + * line. */ if (data->cmd_baudrate != UINT32_MAX) { uart_config.baudrate = data->cmd_baudrate; } - /* Serial port needs to be set either in the devicetree or provided via command line opts, - * if that is not the case, then abort. + /* Serial port needs to be set either in the devicetree or provided via command line + * opts, if that is not the case, then abort. */ if (!data->serial_port) { ERROR("%s: path to the serial port was not set.\n", dev->name); @@ -361,11 +188,8 @@ static int native_tty_serial_init(const struct device *dev) /* Try to open a serial port as with read/write access, also prevent serial port * from becoming the controlling terminal. */ - data->fd = open(data->serial_port, O_RDWR | O_NOCTTY); - if (data->fd < 0) { - ERROR("%s: failed to open serial port %s, reason: %s\n", dev->name, - data->serial_port, strerror(errno)); - } + + data->fd = native_tty_open_tty_bottom(data->serial_port); if (native_tty_configure(dev, &uart_config)) { ERROR("%s: could not configure serial port %s\n", dev->name, data->serial_port); @@ -408,7 +232,6 @@ DT_INST_FOREACH_STATUS_OKAY(NATIVE_TTY_INSTANCE); #define INST_NAME(inst) DEVICE_DT_NAME(DT_DRV_INST(inst)) - #define NATIVE_TTY_COMMAND_LINE_OPTS(inst) \ { \ .option = INST_NAME(inst) "_port", \ @@ -429,7 +252,8 @@ DT_INST_FOREACH_STATUS_OKAY(NATIVE_TTY_INSTANCE); }, /** - * @brief Adds command line options for setting serial port and baud rate for each uart device. + * @brief Adds command line options for setting serial port and baud rate for each uart + * device. */ static void native_tty_add_serial_options(void) { @@ -441,7 +265,7 @@ static void native_tty_add_serial_options(void) #define NATIVE_TTY_CLEANUP(inst) \ if (native_tty_##inst##_data.fd != 0) { \ - close(native_tty_##inst##_data.fd); \ + nsi_host_close(native_tty_##inst##_data.fd); \ } /** diff --git a/drivers/serial/uart_native_tty_bottom.c b/drivers/serial/uart_native_tty_bottom.c new file mode 100644 index 00000000000..21a2f272f10 --- /dev/null +++ b/drivers/serial/uart_native_tty_bottom.c @@ -0,0 +1,246 @@ +/** + * @brief "Bottom" of native tty uart driver + * + * Copyright (c) 2023 Marko Sagadin + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "uart_native_tty_bottom.h" + +#include +#include +#include +#include +#include +#include + +#include + +#define WARN(...) nsi_print_warning(__VA_ARGS__) +#define ERROR(...) nsi_print_error_and_exit(__VA_ARGS__) + +#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) + +struct baudrate_termios_pair { + int baudrate; + speed_t termios_baudrate; +}; + +/** + * @brief Lookup table for mapping the baud rate to the macro understood by termios. + */ +static const struct baudrate_termios_pair baudrate_lut[] = { + {1200, B1200}, {1800, B1800}, {2400, B2400}, {4800, B4800}, + {9600, B9600}, {19200, B19200}, {38400, B38400}, {57600, B57600}, + {115200, B115200}, {230400, B230400}, {460800, B460800}, {500000, B500000}, + {576000, B576000}, {921600, B921600}, {1000000, B1000000}, {1152000, B1152000}, + {1500000, B1500000}, {2000000, B2000000}, {2500000, B2500000}, {3000000, B3000000}, + {3500000, B3500000}, {4000000, B4000000}, +}; + +/** + * @brief Set given termios to defaults appropriate for communicating with serial port devices. + * + * @param ter + */ +static inline void native_tty_termios_defaults_set(struct termios *ter) +{ + /* Set terminal in "serial" mode: + * - Not canonical (no line input) + * - No signal generation from Ctr+{C|Z..} + * - No echoing + */ + ter->c_lflag &= ~(ICANON | ISIG | ECHO); + + /* No special interpretation of output bytes. + * No conversion of newline to carriage return/line feed. + */ + ter->c_oflag &= ~(OPOST | ONLCR); + + /* No software flow control. */ + ter->c_iflag &= ~(IXON | IXOFF | IXANY); + + /* No blocking, return immediately with what is available. */ + ter->c_cc[VMIN] = 0; + ter->c_cc[VTIME] = 0; + + /* No special handling of bytes on receive. */ + ter->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); + + /* - Enable reading data and ignore control lines */ + ter->c_cflag |= CREAD | CLOCAL; +} + +/** + * @brief Set the baud rate speed in the termios structure + * + * @param ter + * @param baudrate + */ +static inline void native_tty_baud_speed_set(struct termios *ter, int baudrate) +{ + for (int i = 0; i < ARRAY_SIZE(baudrate_lut); i++) { + if (baudrate_lut[i].baudrate == baudrate) { + cfsetospeed(ter, baudrate_lut[i].termios_baudrate); + cfsetispeed(ter, baudrate_lut[i].termios_baudrate); + return; + } + } + ERROR("Could not set baudrate, as %d is not supported.\n", baudrate); +} + +/** + * @brief Set parity setting in the termios structure + * + * @param ter + * @param parity + */ +static inline void native_tty_baud_parity_set(struct termios *ter, + enum native_tty_bottom_parity parity) +{ + switch (parity) { + case NTB_PARITY_NONE: + ter->c_cflag &= ~PARENB; + break; + case NTB_PARITY_ODD: + ter->c_cflag |= PARENB; + ter->c_cflag |= PARODD; + break; + case NTB_PARITY_EVEN: + ter->c_cflag |= PARENB; + ter->c_cflag &= ~PARODD; + break; + default: + /* Parity options mark and space are not supported on this driver. */ + ERROR("Could not set parity.\n"); + } +} + +/** + * @brief Set the number of stop bits in the termios structure + * + * @param ter + * @param stop_bits + * + */ +static inline void native_tty_stop_bits_set(struct termios *ter, + enum native_tty_bottom_stop_bits stop_bits) +{ + switch (stop_bits) { + case NTB_STOP_BITS_1: + ter->c_cflag &= ~CSTOPB; + break; + case NTB_STOP_BITS_2: + ter->c_cflag |= CSTOPB; + break; + default: + /* Anything else is not supported in termios. */ + ERROR("Could not set number of data bits.\n"); + } +} + +/** + * @brief Set the number of data bits in the termios structure + * + * @param ter + * @param stop_bits + * + */ +static inline void native_tty_data_bits_set(struct termios *ter, + enum native_tty_bottom_data_bits data_bits) +{ + unsigned int data_bits_to_set = CS5; + + switch (data_bits) { + case NTB_DATA_BITS_5: + data_bits_to_set = CS5; + break; + case NTB_DATA_BITS_6: + data_bits_to_set = CS6; + break; + case NTB_DATA_BITS_7: + data_bits_to_set = CS7; + break; + case NTB_DATA_BITS_8: + data_bits_to_set = CS8; + break; + default: + /* Anything else is not supported in termios */ + ERROR("Could not set number of data bits.\n"); + } + + /* Clear all bits that set the data size */ + ter->c_cflag &= ~CSIZE; + ter->c_cflag |= data_bits_to_set; +} + +int native_tty_open_tty_bottom(const char *pathname) +{ + int fd = open(pathname, O_RDWR | O_NOCTTY); + + if (fd < 0) { + ERROR("Failed to open serial port %s, errno: %i\n", pathname, errno); + } + + return fd; +} + +int native_tty_configure_bottom(int fd, struct native_tty_bottom_cfg *cfg) +{ + int rc, err; + /* Structure used to control properties of a serial port */ + struct termios ter; + + /* Read current terminal driver settings */ + rc = tcgetattr(fd, &ter); + if (rc) { + WARN("Could not read terminal driver settings\n"); + return rc; + } + + native_tty_termios_defaults_set(&ter); + + native_tty_baud_speed_set(&ter, cfg->baudrate); + native_tty_baud_parity_set(&ter, cfg->parity); + native_tty_stop_bits_set(&ter, cfg->stop_bits); + native_tty_data_bits_set(&ter, cfg->data_bits); + + cfg->flow_ctrl = NTB_FLOW_CTRL_NONE; + + rc = tcsetattr(fd, TCSANOW, &ter); + if (rc) { + err = errno; + WARN("Could not set serial port settings, reason: %s\n", strerror(err)); + return err; + } + + /* tcsetattr returns success if ANY of the requested changes were successfully carried out, + * not if ALL were. So we need to read back the settings and check if they are equal to the + * requested ones. + */ + struct termios read_ter; + + rc = tcgetattr(fd, &read_ter); + if (rc) { + err = errno; + WARN("Could not read serial port settings, reason: %s\n", strerror(err)); + return err; + } + + if (ter.c_cflag != read_ter.c_cflag || ter.c_iflag != read_ter.c_iflag || + ter.c_oflag != read_ter.c_oflag || ter.c_lflag != read_ter.c_lflag || + ter.c_line != read_ter.c_line || ter.c_ispeed != read_ter.c_ispeed || + ter.c_ospeed != read_ter.c_ospeed || 0 != memcmp(ter.c_cc, read_ter.c_cc, NCCS)) { + WARN("Read serial port settings do not match set ones.\n"); + return -1; + } + + /* Flush both input and output */ + rc = tcflush(fd, TCIOFLUSH); + if (rc) { + WARN("Could not flush serial port\n"); + return rc; + } + + return 0; +} diff --git a/drivers/serial/uart_native_tty_bottom.h b/drivers/serial/uart_native_tty_bottom.h new file mode 100644 index 00000000000..08ed367e9ec --- /dev/null +++ b/drivers/serial/uart_native_tty_bottom.h @@ -0,0 +1,82 @@ +/** + * @brief "Bottom" of native tty uart driver + * + * When built with the native_simulator this will be built in the runner context, + * that is, with the host C library, and with the host include paths. + * + * Copyright (c) 2023 Marko Sagadin + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef DRIVERS_SERIAL_UART_NATIVE_TTY_BOTTOM_H +#define DRIVERS_SERIAL_UART_NATIVE_TTY_BOTTOM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* Below enums are just differently namespaced copies of uart_config_* enums. Options that are not + * supported on the host are not listed. + */ +enum native_tty_bottom_parity { + NTB_PARITY_NONE, + NTB_PARITY_ODD, + NTB_PARITY_EVEN, +}; + +enum native_tty_bottom_stop_bits { + NTB_STOP_BITS_1, + NTB_STOP_BITS_2, +}; + +enum native_tty_bottom_data_bits { + NTB_DATA_BITS_5, + NTB_DATA_BITS_6, + NTB_DATA_BITS_7, + NTB_DATA_BITS_8, +}; + +enum native_tty_bottom_flow_control { + NTB_FLOW_CTRL_NONE, +}; + +struct native_tty_bottom_cfg { + uint32_t baudrate; + enum native_tty_bottom_parity parity; + enum native_tty_bottom_stop_bits stop_bits; + enum native_tty_bottom_data_bits data_bits; + enum native_tty_bottom_flow_control flow_ctrl; +}; + +/* Note: None of these functions are public interfaces. They are internal to the native tty driver. + */ + +/** + * @brief Opens tty port on the given pathname + * + * Returned file descriptor can be then passed to native_tty_configure_bottom to configure it. + * + * @param pathname + * + * @return file descriptor + */ +int native_tty_open_tty_bottom(const char *pathname); + +/** + * @brief Configure tty port + * + * @param fd File descriptor of the tty port. + * @param cfg Configuration struct. + * + * @retval 0 if successful, + * @retval -1 otherwise. + */ +int native_tty_configure_bottom(int fd, struct native_tty_bottom_cfg *cfg); + +#ifdef __cplusplus +} +#endif + +#endif /* DRIVERS_SERIAL_UART_NATIVE_TTY_BOTTOM_H */ diff --git a/drivers/serial/uart_nrfx_uart.c b/drivers/serial/uart_nrfx_uart.c index 4eb4e231474..25dab17ea74 100644 --- a/drivers/serial/uart_nrfx_uart.c +++ b/drivers/serial/uart_nrfx_uart.c @@ -285,7 +285,7 @@ static void uart_nrfx_poll_out(const struct device *dev, unsigned char c) nrf_uart_txd_set(uart0_addr, (uint8_t)c); /* Wait until the transmitter is ready, i.e. the character is sent. */ - int res; + bool res; NRFX_WAIT_FOR(event_txdrdy_check(), 1000, 1, res); diff --git a/drivers/serial/uart_nrfx_uarte.c b/drivers/serial/uart_nrfx_uarte.c index b70af538abf..3a62057a47a 100644 --- a/drivers/serial/uart_nrfx_uarte.c +++ b/drivers/serial/uart_nrfx_uarte.c @@ -65,6 +65,16 @@ LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL); #define UARTE_ANY_ASYNC 1 #endif +#if defined(CONFIG_UART_0_NRF_HW_ASYNC) || defined(CONFIG_UART_1_NRF_HW_ASYNC) || \ + defined(CONFIG_UART_2_NRF_HW_ASYNC) || defined(CONFIG_UART_3_NRF_HW_ASYNC) +#define UARTE_HW_ASYNC 1 +#endif + +#if defined(CONFIG_UART_0_ENHANCED_POLL_OUT) || defined(CONFIG_UART_1_ENHANCED_POLL_OUT) || \ + defined(CONFIG_UART_2_ENHANCED_POLL_OUT) || defined(CONFIG_UART_3_ENHANCED_POLL_OUT) +#define UARTE_ENHANCED_POLL_OUT 1 +#endif + /* * RX timeout is divided into time slabs, this define tells how many divisions * should be made. More divisions - higher timeout accuracy and processor usage. @@ -205,7 +215,7 @@ static void endtx_isr(const struct device *dev) * * @param arg Argument to ISR. */ -static void uarte_nrfx_isr_int(void *arg) +static void uarte_nrfx_isr_int(const void *arg) { const struct device *dev = arg; const struct uarte_nrfx_config *config = dev->config; @@ -498,7 +508,7 @@ static int wait_tx_ready(const struct device *dev) * where static inline fails on linking. */ #define HW_RX_COUNTING_ENABLED(data) \ - (IS_ENABLED(CONFIG_UARTE_NRF_HW_ASYNC) ? data->async->hw_rx_counting : false) + (IS_ENABLED(UARTE_HW_ASYNC) ? data->async->hw_rx_counting : false) #endif /* UARTE_ANY_ASYNC */ @@ -1745,7 +1755,7 @@ static int uarte_instance_init(const struct device *dev, return err; } - if (IS_ENABLED(CONFIG_UART_ENHANCED_POLL_OUT) && + if (IS_ENABLED(UARTE_ENHANCED_POLL_OUT) && cfg->flags & UARTE_CFG_FLAG_PPI_ENDTX) { err = endtx_stoptx_ppi_init(uarte, data); if (err < 0) { diff --git a/drivers/serial/uart_ns16550.c b/drivers/serial/uart_ns16550.c index c7357d076f1..a41cdca7843 100644 --- a/drivers/serial/uart_ns16550.c +++ b/drivers/serial/uart_ns16550.c @@ -43,13 +43,8 @@ LOG_MODULE_REGISTER(uart_ns16550, CONFIG_UART_LOG_LEVEL); -#define INST_HAS_PCP_HELPER(inst) DT_INST_NODE_HAS_PROP(inst, pcp) || -#define INST_HAS_DLF_HELPER(inst) DT_INST_NODE_HAS_PROP(inst, dlf) || - -#define UART_NS16550_PCP_ENABLED \ - (DT_INST_FOREACH_STATUS_OKAY(INST_HAS_PCP_HELPER) 0) -#define UART_NS16550_DLF_ENABLED \ - (DT_INST_FOREACH_STATUS_OKAY(INST_HAS_DLF_HELPER) 0) +#define UART_NS16550_PCP_ENABLED DT_ANY_INST_HAS_PROP_STATUS_OKAY(pcp) +#define UART_NS16550_DLF_ENABLED DT_ANY_INST_HAS_PROP_STATUS_OKAY(dlf) #if DT_ANY_INST_ON_BUS_STATUS_OKAY(pcie) BUILD_ASSERT(IS_ENABLED(CONFIG_PCIE), "NS16550(s) in DT need CONFIG_PCIE"); @@ -63,6 +58,21 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_PCIE), "NS16550(s) in DT need CONFIG_PCIE"); #include #endif +/* If any node has property io-mapped set, we need to support IO port + * access in the code and device config struct. + * + * Note that DT_ANY_INST_HAS_PROP_STATUS_OKAY() always returns true + * as io-mapped property is considered always exists and present, + * even if its value is zero. Therefore we cannot use it, and has to + * resort to the follow helper to see if any okay nodes have io-mapped + * as 1. + */ +#define UART_NS16550_DT_PROP_IOMAPPED_HELPER(inst, prop, def) \ + DT_INST_PROP_OR(inst, prop, def) || + +#define UART_NS16550_IOPORT_ENABLED \ + (DT_INST_FOREACH_STATUS_OKAY_VARGS(UART_NS16550_DT_PROP_IOMAPPED_HELPER, io_mapped, 0) 0) + /* register definitions */ #define REG_THR 0x00 /* Transmitter holding reg. */ @@ -232,6 +242,23 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_PCIE), "NS16550(s) in DT need CONFIG_PCIE"); #define IIRC(dev) (((struct uart_ns16550_dev_data *)(dev)->data)->iir_cache) +#ifdef CONFIG_UART_NS16550_ITE_HIGH_SPEED_BUADRATE +/* Register definitions (ITE_IT8XXX2) */ +#define REG_ECSPMR 0x08 /* EC Serial port mode reg */ + +/* Fields for ITE IT8XXX2 UART module */ +#define ECSPMR_ECHS 0x02 /* EC high speed select */ + +/* IT8XXX2 UART high speed baud rate settings */ +#define UART_BAUDRATE_115200 115200 +#define UART_BAUDRATE_230400 230400 +#define UART_BAUDRATE_460800 460800 +#define IT8XXX2_230400_DIVISOR 32770 +#define IT8XXX2_460800_DIVISOR 32769 + +#define ECSPMR(dev) (get_port(dev) + REG_ECSPMR * reg_interval(dev)) +#endif + /* device config */ struct uart_ns16550_device_config { union { @@ -254,7 +281,7 @@ struct uart_ns16550_device_config { #if defined(CONFIG_PINCTRL) const struct pinctrl_dev_config *pincfg; #endif -#if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS) +#if UART_NS16550_IOPORT_ENABLED bool io_map; #endif #if UART_NS16550_RESET_ENABLED @@ -287,7 +314,7 @@ struct uart_ns16550_dev_data { static void ns16550_outbyte(const struct uart_ns16550_device_config *cfg, uintptr_t port, uint8_t val) { -#if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS) +#if UART_NS16550_IOPORT_ENABLED if (cfg->io_map) { if (IS_ENABLED(CONFIG_UART_NS16550_ACCESS_WORD_ONLY)) { sys_out32(val, port); @@ -310,7 +337,7 @@ static void ns16550_outbyte(const struct uart_ns16550_device_config *cfg, static uint8_t ns16550_inbyte(const struct uart_ns16550_device_config *cfg, uintptr_t port) { -#if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS) +#if UART_NS16550_IOPORT_ENABLED if (cfg->io_map) { if (IS_ENABLED(CONFIG_UART_NS16550_ACCESS_WORD_ONLY)) { return sys_in32(port); @@ -335,7 +362,7 @@ static uint8_t ns16550_inbyte(const struct uart_ns16550_device_config *cfg, static void ns16550_outword(const struct uart_ns16550_device_config *cfg, uintptr_t port, uint32_t val) { -#if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS) +#if UART_NS16550_IOPORT_ENABLED if (cfg->io_map) { sys_out32(val, port); } else { @@ -350,7 +377,7 @@ static void ns16550_outword(const struct uart_ns16550_device_config *cfg, static uint32_t ns16550_inword(const struct uart_ns16550_device_config *cfg, uintptr_t port) { -#if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS) +#if UART_NS16550_IOPORT_ENABLED if (cfg->io_map) { return sys_in32(port); } @@ -367,12 +394,10 @@ static inline uint8_t reg_interval(const struct device *dev) return config->reg_interval; } -static const struct uart_driver_api uart_ns16550_driver_api; - static inline uintptr_t get_port(const struct device *dev) { uintptr_t port; -#if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS) +#if UART_NS16550_IOPORT_ENABLED const struct uart_ns16550_device_config *config = dev->config; if (config->io_map) { @@ -387,6 +412,50 @@ static inline uintptr_t get_port(const struct device *dev) return port; } +static uint32_t get_uart_burdrate_divisor(const struct device *dev, + uint32_t baud_rate, + uint32_t pclk) +{ + ARG_UNUSED(dev); + /* + * calculate baud rate divisor. a variant of + * (uint32_t)(pclk / (16.0 * baud_rate) + 0.5) + */ + return ((pclk + (baud_rate << 3)) / baud_rate) >> 4; +} + +#ifdef CONFIG_UART_NS16550_ITE_HIGH_SPEED_BUADRATE +static uint32_t get_ite_uart_burdrate_divisor(const struct device *dev, + uint32_t baud_rate, + uint32_t pclk) +{ + const struct uart_ns16550_device_config * const dev_cfg = dev->config; + uint32_t divisor = 0; + + if (baud_rate > UART_BAUDRATE_115200) { + /* Baud rate divisor for high speed */ + if (baud_rate == UART_BAUDRATE_230400) { + divisor = IT8XXX2_230400_DIVISOR; + } else if (baud_rate == UART_BAUDRATE_460800) { + divisor = IT8XXX2_460800_DIVISOR; + } + /* + * This bit indicates that the supported baud rate of + * UART1/UART2 can be up to 230.4k and 460.8k. + * Other bits are reserved and have no setting, so we + * directly write the ECSPMR register. + */ + ns16550_outbyte(dev_cfg, ECSPMR(dev), ECSPMR_ECHS); + } else { + divisor = get_uart_burdrate_divisor(dev, baud_rate, pclk); + /* Set ECSPMR register as default */ + ns16550_outbyte(dev_cfg, ECSPMR(dev), 0); + } + + return divisor; +} +#endif + static void set_baud_rate(const struct device *dev, uint32_t baud_rate, uint32_t pclk) { struct uart_ns16550_dev_data * const dev_data = dev->data; @@ -395,13 +464,11 @@ static void set_baud_rate(const struct device *dev, uint32_t baud_rate, uint32_t uint8_t lcr_cache; if ((baud_rate != 0U) && (pclk != 0U)) { - /* - * calculate baud rate divisor. a variant of - * (uint32_t)(pclk / (16.0 * baud_rate) + 0.5) - */ - divisor = ((pclk + (baud_rate << 3)) - / baud_rate) >> 4; - +#ifdef CONFIG_UART_NS16550_ITE_HIGH_SPEED_BUADRATE + divisor = get_ite_uart_burdrate_divisor(dev, baud_rate, pclk); +#else + divisor = get_uart_burdrate_divisor(dev, baud_rate, pclk); +#endif /* set the DLAB to access the baud rate divisor registers */ lcr_cache = ns16550_inbyte(dev_cfg, LCR(dev)); ns16550_outbyte(dev_cfg, LCR(dev), LCR_DLAB | lcr_cache); @@ -665,7 +732,7 @@ static int uart_ns16550_init(const struct device *dev) } else #endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(pcie) */ { -#if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS) +#if UART_NS16550_IOPORT_ENABLED /* Map directly from DTS */ if (!dev_cfg->io_map) { #else @@ -1227,14 +1294,14 @@ static const struct uart_driver_api uart_ns16550_driver_api = { #endif }; -#define UART_NS16550_IRQ_FLAGS_SENSE0(n) 0 -#define UART_NS16550_IRQ_FLAGS_SENSE1(n) DT_INST_IRQ(n, sense) #define UART_NS16550_IRQ_FLAGS(n) \ - _CONCAT(UART_NS16550_IRQ_FLAGS_SENSE, DT_INST_IRQ_HAS_CELL(n, sense))(n) + COND_CODE_1(DT_INST_IRQ_HAS_CELL(n, sense), \ + (DT_INST_IRQ(n, sense)), \ + (0)) -/* not PCI(e) */ -#define UART_NS16550_IRQ_CONFIG_PCIE0(n) \ - static void irq_config_func##n(const struct device *dev) \ +/* IO-port or MMIO based UART */ +#define UART_NS16550_IRQ_CONFIG(n) \ + static void uart_ns16550_irq_config_func##n(const struct device *dev) \ { \ ARG_UNUSED(dev); \ IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \ @@ -1244,8 +1311,8 @@ static const struct uart_driver_api uart_ns16550_driver_api = { } /* PCI(e) with auto IRQ detection */ -#define UART_NS16550_IRQ_CONFIG_PCIE1(n) \ - static void irq_config_func##n(const struct device *dev) \ +#define UART_NS16550_IRQ_CONFIG_PCIE(n) \ + static void uart_ns16550_irq_config_func##n(const struct device *dev) \ { \ BUILD_ASSERT(DT_INST_IRQN(n) == PCIE_IRQ_DETECT, \ "Only runtime IRQ configuration is supported"); \ @@ -1264,89 +1331,32 @@ static const struct uart_driver_api uart_ns16550_driver_api = { pcie_irq_enable(dev_cfg->pcie->bdf, irq); \ } -#ifdef CONFIG_UART_NS16550_ACCESS_IOPORT -#define REG_INIT(n) \ - .port = DT_INST_REG_ADDR(n), \ - .io_map = true, -#else -#define REG_INIT_PCIE1(n) -#define REG_INIT_PCIE0(n) DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), - -#define DEV_REG_PORT_IO_1(n) \ - .port = DT_INST_REG_ADDR(n), -#define DEV_REG_PORT_IO_0(n) \ - _CONCAT(REG_INIT_PCIE, DT_INST_ON_BUS(n, pcie))(n) -#ifdef CONFIG_UART_NS16550_SIMULT_ACCESS -#define DEV_IO_INIT(n) \ - .io_map = DT_INST_PROP(n, io_mapped), -#else -#define DEV_IO_INIT(n) -#endif - -#define REG_INIT(n) \ - _CONCAT(DEV_REG_PORT_IO_, DT_INST_PROP(n, io_mapped))(n) \ - DEV_IO_INIT(n) -#endif - #ifdef CONFIG_UART_INTERRUPT_DRIVEN #define DEV_CONFIG_IRQ_FUNC_INIT(n) \ - .irq_config_func = irq_config_func##n, + .irq_config_func = uart_ns16550_irq_config_func##n, #define UART_NS16550_IRQ_FUNC_DECLARE(n) \ - static void irq_config_func##n(const struct device *dev); + static void uart_ns16550_irq_config_func##n(const struct device *dev); #define UART_NS16550_IRQ_FUNC_DEFINE(n) \ - _CONCAT(UART_NS16550_IRQ_CONFIG_PCIE, DT_INST_ON_BUS(n, pcie))(n) + UART_NS16550_IRQ_CONFIG(n) + +#define DEV_CONFIG_PCIE_IRQ_FUNC_INIT(n) \ + .irq_config_func = uart_ns16550_irq_config_func##n, +#define UART_NS16550_PCIE_IRQ_FUNC_DECLARE(n) \ + static void uart_ns16550_irq_config_func##n(const struct device *dev); +#define UART_NS16550_PCIE_IRQ_FUNC_DEFINE(n) \ + UART_NS16550_IRQ_CONFIG_PCIE(n) #else /* !CONFIG_UART_INTERRUPT_DRIVEN */ #define DEV_CONFIG_IRQ_FUNC_INIT(n) #define UART_NS16550_IRQ_FUNC_DECLARE(n) #define UART_NS16550_IRQ_FUNC_DEFINE(n) -#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ - -#if UART_NS16550_PCP_ENABLED -#define DEV_CONFIG_PCP_INIT(n) .pcp = DT_INST_PROP_OR(n, pcp, 0), -#else -#define DEV_CONFIG_PCP_INIT(n) -#endif -#define DEV_CONFIG_PCIE0(n) -#define DEV_CONFIG_PCIE1(n) DEVICE_PCIE_INST_INIT(n, pcie) -#define DEV_CONFIG_PCIE_INIT(n) \ - _CONCAT(DEV_CONFIG_PCIE, DT_INST_ON_BUS(n, pcie))(n) - -#define DEV_DECLARE_PCIE0(n) -#define DEV_DECLARE_PCIE1(n) DEVICE_PCIE_INST_DECLARE(n) -#define DEV_PCIE_DECLARE(n) \ - _CONCAT(DEV_DECLARE_PCIE, DT_INST_ON_BUS(n, pcie))(n) - -#define DEV_DATA_FLOW_CTRL0 UART_CFG_FLOW_CTRL_NONE -#define DEV_DATA_FLOW_CTRL1 UART_CFG_FLOW_CTRL_RTS_CTS -#define DEV_DATA_FLOW_CTRL(n) \ - _CONCAT(DEV_DATA_FLOW_CTRL, DT_INST_PROP_OR(n, hw_flow_control, 0)) - -#define DEV_DATA_DLF0(n) -#define DEV_DATA_DLF1(n) \ - .dlf = DT_INST_PROP(n, dlf), -#define DEV_DATA_DLF_INIT(n) \ - _CONCAT(DEV_DATA_DLF, DT_INST_NODE_HAS_PROP(n, dlf))(n) - -#ifdef CONFIG_UART_NS16550_PARENT_INIT_LEVEL -#define NS16550_BOOT_LEVEL0 PRE_KERNEL_1 -#define NS16550_BOOT_LEVEL1 POST_KERNEL -#define BOOT_LEVEL(n) \ - _CONCAT(NS16550_BOOT_LEVEL, DT_INST_ON_BUS(n, pcie)) -#else -#define BOOT_LEVEL(n) PRE_KERNEL_1 -#endif -#define UART_RESET_FUNC_INIT(n) \ - .reset_spec = RESET_DT_SPEC_INST_GET(n), +#define DEV_CONFIG_PCIE_IRQ_FUNC_INIT(n) +#define UART_NS16550_PCIE_IRQ_FUNC_DECLARE(n) +#define UART_NS16550_PCIE_IRQ_FUNC_DEFINE(n) +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ -#define UART_NS16550_DEVICE_INIT(n) \ - UART_NS16550_IRQ_FUNC_DECLARE(n); \ - DEV_PCIE_DECLARE(n); \ - IF_ENABLED(DT_INST_NODE_HAS_PROP(n, pinctrl_0), \ - (PINCTRL_DT_INST_DEFINE(n))); \ - static const struct uart_ns16550_device_config uart_ns16550_dev_cfg_##n = { \ - REG_INIT(n) \ +#define UART_NS16550_COMMON_DEV_CFG_INITIALIZER(n) \ COND_CODE_1(DT_INST_NODE_HAS_PROP(n, clock_frequency), ( \ .sys_clk_freq = DT_INST_PROP(n, clock_frequency), \ .clock_dev = NULL, \ @@ -1358,27 +1368,70 @@ static const struct uart_driver_api uart_ns16550_driver_api = { 0, clocks, clkid), \ ) \ ) \ - DEV_CONFIG_IRQ_FUNC_INIT(n) \ - DEV_CONFIG_PCP_INIT(n) \ + IF_ENABLED(DT_INST_NODE_HAS_PROP(n, pcp), \ + (.pcp = DT_INST_PROP_OR(n, pcp, 0),)) \ .reg_interval = (1 << DT_INST_PROP(n, reg_shift)), \ - DEV_CONFIG_PCIE_INIT(n) \ - IF_ENABLED(DT_INST_NODE_HAS_PROP(n, pinctrl_0), \ - (.pincfg = PINCTRL_DT_DEV_CONFIG_GET(DT_DRV_INST(n)),)) \ + IF_ENABLED(CONFIG_PINCTRL, \ + (.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),)) \ IF_ENABLED(DT_INST_NODE_HAS_PROP(n, resets), \ - (UART_RESET_FUNC_INIT(n))) \ - }; \ - static struct uart_ns16550_dev_data uart_ns16550_dev_data_##n = { \ + (.reset_spec = RESET_DT_SPEC_INST_GET(n),)) + +#define UART_NS16550_COMMON_DEV_DATA_INITIALIZER(n) \ .uart_config.baudrate = DT_INST_PROP_OR(n, current_speed, 0), \ .uart_config.parity = UART_CFG_PARITY_NONE, \ .uart_config.stop_bits = UART_CFG_STOP_BITS_1, \ .uart_config.data_bits = UART_CFG_DATA_BITS_8, \ - .uart_config.flow_ctrl = DEV_DATA_FLOW_CTRL(n), \ - DEV_DATA_DLF_INIT(n) \ + .uart_config.flow_ctrl = \ + COND_CODE_1(DT_INST_PROP_OR(n, hw_flow_control, 0), \ + (UART_CFG_FLOW_CTRL_RTS_CTS), \ + (UART_CFG_FLOW_CTRL_NONE)), \ + IF_ENABLED(DT_INST_NODE_HAS_PROP(n, dlf), \ + (.dlf = DT_INST_PROP_OR(n, dlf, 0),)) + +#define UART_NS16550_DEVICE_IO_MMIO_INIT(n) \ + UART_NS16550_IRQ_FUNC_DECLARE(n); \ + IF_ENABLED(CONFIG_PINCTRL, (PINCTRL_DT_INST_DEFINE(n))); \ + static const struct uart_ns16550_device_config uart_ns16550_dev_cfg_##n = { \ + COND_CODE_1(DT_INST_PROP_OR(n, io_mapped, 0), \ + (.port = DT_INST_REG_ADDR(n),), \ + (DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)),)) \ + IF_ENABLED(DT_INST_PROP_OR(n, io_mapped, 0), \ + (.io_map = true,)) \ + UART_NS16550_COMMON_DEV_CFG_INITIALIZER(n) \ + DEV_CONFIG_IRQ_FUNC_INIT(n) \ + }; \ + static struct uart_ns16550_dev_data uart_ns16550_dev_data_##n = { \ + UART_NS16550_COMMON_DEV_DATA_INITIALIZER(n) \ }; \ DEVICE_DT_INST_DEFINE(n, &uart_ns16550_init, NULL, \ &uart_ns16550_dev_data_##n, &uart_ns16550_dev_cfg_##n, \ - BOOT_LEVEL(n), CONFIG_SERIAL_INIT_PRIORITY, \ + PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \ &uart_ns16550_driver_api); \ UART_NS16550_IRQ_FUNC_DEFINE(n) +#define UART_NS16550_DEVICE_PCIE_INIT(n) \ + UART_NS16550_PCIE_IRQ_FUNC_DECLARE(n); \ + DEVICE_PCIE_INST_DECLARE(n); \ + IF_ENABLED(CONFIG_PINCTRL, (PINCTRL_DT_INST_DEFINE(n))); \ + static const struct uart_ns16550_device_config uart_ns16550_dev_cfg_##n = { \ + UART_NS16550_COMMON_DEV_CFG_INITIALIZER(n) \ + DEV_CONFIG_PCIE_IRQ_FUNC_INIT(n) \ + DEVICE_PCIE_INST_INIT(n, pcie) \ + }; \ + static struct uart_ns16550_dev_data uart_ns16550_dev_data_##n = { \ + UART_NS16550_COMMON_DEV_DATA_INITIALIZER(n) \ + }; \ + DEVICE_DT_INST_DEFINE(n, &uart_ns16550_init, NULL, \ + &uart_ns16550_dev_data_##n, &uart_ns16550_dev_cfg_##n, \ + COND_CODE_1(CONFIG_UART_NS16550_PARENT_INIT_LEVEL, \ + (POST_KERNEL), (PRE_KERNEL_1)), \ + CONFIG_SERIAL_INIT_PRIORITY, \ + &uart_ns16550_driver_api); \ + UART_NS16550_PCIE_IRQ_FUNC_DEFINE(n) + +#define UART_NS16550_DEVICE_INIT(n) \ + COND_CODE_1(DT_INST_ON_BUS(n, pcie), \ + (UART_NS16550_DEVICE_PCIE_INIT(n)), \ + (UART_NS16550_DEVICE_IO_MMIO_INIT(n))) + DT_INST_FOREACH_STATUS_OKAY(UART_NS16550_DEVICE_INIT) diff --git a/drivers/serial/uart_nxp_s32_linflexd.c b/drivers/serial/uart_nxp_s32_linflexd.c index fe1c6c51f86..4fa6badb796 100644 --- a/drivers/serial/uart_nxp_s32_linflexd.c +++ b/drivers/serial/uart_nxp_s32_linflexd.c @@ -4,6 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +#define DT_DRV_COMPAT nxp_s32_linflexd + +#include #include #include #include @@ -243,45 +246,54 @@ static void uart_nxp_s32_irq_callback_set(const struct device *dev, data->cb_data = cb_data; } -/** - * @brief Interrupt service routine. - * - * This simply calls the callback function, if one exists. - * - * Note: s32 UART Tx interrupts when ready to send; Rx interrupts when char - * received. - * - * @param arg Argument to ISR. - * - * @return N/A - */ - void uart_nxp_s32_isr(const struct device *dev) { + const struct uart_nxp_s32_config *config = dev->config; + + Linflexd_Uart_Ip_IRQHandler(config->instance); +} + +static void uart_nxp_s32_event_handler(const uint8 instance, + Linflexd_Uart_Ip_EventType event, + void *user_data) +{ + const struct device *dev = (const struct device *)user_data; + const struct uart_nxp_s32_config *config = dev->config; struct uart_nxp_s32_data *data = dev->data; + struct uart_nxp_s32_int *int_data = &(data->int_data); + Linflexd_Uart_Ip_StatusType status; - if (data->callback) { - data->callback(dev, data->cb_data); + if (event == LINFLEXD_UART_IP_EVENT_END_TRANSFER) { + /* + * Check the previous UART transmit has finished + * because Rx may also trigger this event + */ + status = Linflexd_Uart_Ip_GetTransmitStatus(config->instance, NULL); + if (status != LINFLEXD_UART_IP_STATUS_BUSY) { + int_data->tx_fifo_busy = false; + if (data->callback) { + data->callback(dev, data->cb_data); + } + } + } else if (event == LINFLEXD_UART_IP_EVENT_RX_FULL) { + int_data->rx_fifo_busy = false; + if (data->callback) { + data->callback(dev, data->cb_data); + } + } else if (event == LINFLEXD_UART_IP_EVENT_ERROR) { + if (data->callback) { + data->callback(dev, data->cb_data); + } + } else { + /* Other events are not used */ } } + #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ -/** - * @brief Initialize UART channel - * - * This routine is called to reset the chip in a quiescent state. - * It is assumed that this function is called only once per UART. - * - * @param dev UART device struct - * - * @return 0 - */ static int uart_nxp_s32_init(const struct device *dev) { const struct uart_nxp_s32_config *config = dev->config; - struct uart_nxp_s32_data *data = dev->data; - static uint8_t state_idx; - uint8_t key; int err; err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); @@ -289,24 +301,7 @@ static int uart_nxp_s32_init(const struct device *dev) return err; } - key = irq_lock(); - - /* Initialize UART with default configuration */ - data->hw_cfg.BaudRate = 115200; - data->hw_cfg.BaudRateMantissa = 26U; - data->hw_cfg.BaudRateFractionalDivisor = 1U; - data->hw_cfg.ParityCheck = false; - data->hw_cfg.ParityType = LINFLEXD_UART_IP_PARITY_EVEN; - data->hw_cfg.StopBitsCount = LINFLEXD_UART_IP_ONE_STOP_BIT; - data->hw_cfg.WordLength = LINFLEXD_UART_IP_8_BITS; - data->hw_cfg.TransferType = LINFLEXD_UART_IP_USING_INTERRUPTS; - data->hw_cfg.Callback = s32_uart_callback; - data->hw_cfg.CallbackParam = NULL; - data->hw_cfg.StateStruct = &Linflexd_Uart_Ip_apStateStructure[state_idx++]; - - Linflexd_Uart_Ip_Init(config->instance, &data->hw_cfg); - - irq_unlock(key); + Linflexd_Uart_Ip_Init(config->instance, &config->hw_cfg); return 0; } @@ -334,207 +329,63 @@ static const struct uart_driver_api uart_nxp_s32_driver_api = { }; -#define UART_NXP_S32_NODE(n) DT_NODELABEL(uart##n) - -#if defined(CONFIG_UART_INTERRUPT_DRIVEN) -#define UART_NXP_S32_INTERRUPT_DEFINE(n, isr_handler, parameter) \ - do { \ - IRQ_CONNECT(DT_IRQN(UART_NXP_S32_NODE(n)), \ - DT_IRQ(UART_NXP_S32_NODE(n), priority), \ - isr_handler, \ - parameter, \ - DT_IRQ(UART_NXP_S32_NODE(n), flags)); \ - \ - irq_enable(DT_IRQN(UART_NXP_S32_NODE(n))); \ +#define UART_NXP_S32_HW_INSTANCE_CHECK(i, n) \ + ((DT_INST_REG_ADDR(n) == IP_LINFLEX_##i##_BASE) ? i : 0) + +#define UART_NXP_S32_HW_INSTANCE(n) \ + LISTIFY(__DEBRACKET LINFLEXD_INSTANCE_COUNT, UART_NXP_S32_HW_INSTANCE_CHECK, (|), n) + +#define UART_NXP_S32_INTERRUPT_DEFINE(n) \ + do { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \ + uart_nxp_s32_isr, DEVICE_DT_INST_GET(n), \ + DT_INST_IRQ(n, flags)); \ + irq_enable(DT_INST_IRQN(n)); \ } while (0) -#else -#define UART_NXP_S32_INTERRUPT_DEFINE(n, isr_handler, parameter) -#endif +#define UART_NXP_S32_HW_CONFIG(n) \ + { \ + .BaudRate = 115200, \ + .BaudRateMantissa = 26U, \ + .BaudRateDivisor = 16U, \ + .BaudRateFractionalDivisor = 1U, \ + .ParityCheck = false, \ + .ParityType = LINFLEXD_UART_IP_PARITY_EVEN, \ + .StopBitsCount = LINFLEXD_UART_IP_ONE_STOP_BIT, \ + .WordLength = LINFLEXD_UART_IP_8_BITS, \ + .TransferType = LINFLEXD_UART_IP_USING_INTERRUPTS, \ + .StateStruct = &Linflexd_Uart_Ip_apStateStructure[n], \ + IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, ( \ + .Callback = uart_nxp_s32_event_handler, \ + .CallbackParam = (void *)DEVICE_DT_INST_GET(n), \ + )) \ + } #define UART_NXP_S32_INIT_DEVICE(n) \ - PINCTRL_DT_DEFINE(UART_NXP_S32_NODE(n)); \ - static struct uart_nxp_s32_data uart_nxp_s32_data_##n; \ + PINCTRL_DT_INST_DEFINE(n); \ + IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \ + (static struct uart_nxp_s32_data uart_nxp_s32_data_##n;)) \ static const struct uart_nxp_s32_config uart_nxp_s32_config_##n = { \ - .instance = n, \ - .base = (LINFLEXD_Type *)DT_REG_ADDR(UART_NXP_S32_NODE(n)), \ - .pincfg = PINCTRL_DT_DEV_CONFIG_GET(UART_NXP_S32_NODE(n)), \ + .instance = UART_NXP_S32_HW_INSTANCE(n), \ + .base = (LINFLEXD_Type *)DT_INST_REG_ADDR(n), \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .hw_cfg = UART_NXP_S32_HW_CONFIG(n), \ }; \ static int uart_nxp_s32_init_##n(const struct device *dev) \ { \ - UART_NXP_S32_INTERRUPT_DEFINE(n, Linflexd_Uart_Ip_IRQHandler, n);\ + IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \ + (UART_NXP_S32_INTERRUPT_DEFINE(n);)) \ \ return uart_nxp_s32_init(dev); \ } \ - DEVICE_DT_DEFINE(UART_NXP_S32_NODE(n), \ + DEVICE_DT_INST_DEFINE(n, \ &uart_nxp_s32_init_##n, \ NULL, \ - &uart_nxp_s32_data_##n, \ + COND_CODE_1(CONFIG_UART_INTERRUPT_DRIVEN, \ + (&uart_nxp_s32_data_##n), (NULL)), \ &uart_nxp_s32_config_##n, \ PRE_KERNEL_1, \ CONFIG_SERIAL_INIT_PRIORITY, \ &uart_nxp_s32_driver_api); -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(0), okay) -UART_NXP_S32_INIT_DEVICE(0) -#endif - -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(1), okay) -UART_NXP_S32_INIT_DEVICE(1) -#endif - -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(2), okay) -UART_NXP_S32_INIT_DEVICE(2) -#endif - -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(3), okay) -UART_NXP_S32_INIT_DEVICE(3) -#endif - -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(4), okay) -UART_NXP_S32_INIT_DEVICE(4) -#endif - -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(5), okay) -UART_NXP_S32_INIT_DEVICE(5) -#endif - -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(6), okay) -UART_NXP_S32_INIT_DEVICE(6) -#endif - -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(7), okay) -UART_NXP_S32_INIT_DEVICE(7) -#endif - -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(8), okay) -UART_NXP_S32_INIT_DEVICE(8) -#endif - -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(9), okay) -UART_NXP_S32_INIT_DEVICE(9) -#endif - -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(10), okay) -UART_NXP_S32_INIT_DEVICE(10) -#endif - -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(11), okay) -UART_NXP_S32_INIT_DEVICE(11) -#endif - -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(12), okay) -UART_NXP_S32_INIT_DEVICE(12) -#endif - -#ifdef CONFIG_UART_INTERRUPT_DRIVEN -static void s32_uart_device_event(const struct device *dev, Linflexd_Uart_Ip_EventType event, - void *user_data) -{ - const struct uart_nxp_s32_config *config = dev->config; - struct uart_nxp_s32_data *data = dev->data; - struct uart_nxp_s32_int *int_data = &(data->int_data); - Linflexd_Uart_Ip_StatusType status; - - ARG_UNUSED(user_data); - - if (event == LINFLEXD_UART_IP_EVENT_END_TRANSFER) { - /* - * Check the previous UART transmit has finished - * because Rx may also trigger this event - */ - status = Linflexd_Uart_Ip_GetTransmitStatus(config->instance, NULL); - if (status != LINFLEXD_UART_IP_STATUS_BUSY) { - int_data->tx_fifo_busy = false; - uart_nxp_s32_isr(dev); - } - } else if (event == LINFLEXD_UART_IP_EVENT_RX_FULL) { - int_data->rx_fifo_busy = false; - uart_nxp_s32_isr(dev); - } else if (event == LINFLEXD_UART_IP_EVENT_ERROR) { - uart_nxp_s32_isr(dev); - } else { - /* Other events are not used */ - } -} - -void s32_uart_callback(const uint8 instance, Linflexd_Uart_Ip_EventType event, void *user_data) -{ - const struct device *dev; - - switch (instance) { -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(0), okay) - case 0: - dev = DEVICE_DT_GET(UART_NXP_S32_NODE(0)); - break; -#endif -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(1), okay) - case 1: - dev = DEVICE_DT_GET(UART_NXP_S32_NODE(1)); - break; -#endif -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(2), okay) - case 2: - dev = DEVICE_DT_GET(UART_NXP_S32_NODE(2)); - break; -#endif -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(3), okay) - case 3: - dev = DEVICE_DT_GET(UART_NXP_S32_NODE(3)); - break; -#endif -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(4), okay) - case 4: - dev = DEVICE_DT_GET(UART_NXP_S32_NODE(4)); - break; -#endif -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(5), okay) - case 5: - dev = DEVICE_DT_GET(UART_NXP_S32_NODE(5)); - break; -#endif -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(6), okay) - case 6: - dev = DEVICE_DT_GET(UART_NXP_S32_NODE(6)); - break; -#endif -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(7), okay) - case 7: - dev = DEVICE_DT_GET(UART_NXP_S32_NODE(7)); - break; -#endif -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(8), okay) - case 8: - dev = DEVICE_DT_GET(UART_NXP_S32_NODE(8)); - break; -#endif -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(9), okay) - case 9: - dev = DEVICE_DT_GET(UART_NXP_S32_NODE(9)); - break; -#endif -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(10), okay) - case 10: - dev = DEVICE_DT_GET(UART_NXP_S32_NODE(10)); - break; -#endif -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(11), okay) - case 11: - dev = DEVICE_DT_GET(UART_NXP_S32_NODE(11)); - break; -#endif -#if DT_NODE_HAS_STATUS(UART_NXP_S32_NODE(12), okay) - case 12: - dev = DEVICE_DT_GET(UART_NXP_S32_NODE(12)); - break; -#endif - default: - dev = NULL; - break; - } - - if (dev != NULL) { - s32_uart_device_event(dev, event, user_data); - } -} -#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +DT_INST_FOREACH_STATUS_OKAY(UART_NXP_S32_INIT_DEVICE) diff --git a/drivers/serial/uart_nxp_s32_linflexd.h b/drivers/serial/uart_nxp_s32_linflexd.h index ce5180c26c1..997cd1e9112 100644 --- a/drivers/serial/uart_nxp_s32_linflexd.h +++ b/drivers/serial/uart_nxp_s32_linflexd.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 NXP + * Copyright 2022-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,6 +11,7 @@ struct uart_nxp_s32_config { uint32_t instance; LINFLEXD_Type *base; const struct pinctrl_dev_config *pincfg; + Linflexd_Uart_Ip_UserConfigType hw_cfg; }; #ifdef CONFIG_UART_INTERRUPT_DRIVEN @@ -23,16 +24,13 @@ struct uart_nxp_s32_int { }; #endif -struct uart_nxp_s32_data { - Linflexd_Uart_Ip_UserConfigType hw_cfg; - #ifdef CONFIG_UART_INTERRUPT_DRIVEN +struct uart_nxp_s32_data { struct uart_nxp_s32_int int_data; uart_irq_callback_user_data_t callback; void *cb_data; -#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ - }; +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ extern Linflexd_Uart_Ip_StateStructureType Linflexd_Uart_Ip_apStateStructure[LINFLEXD_UART_IP_NUMBER_OF_INSTANCES]; diff --git a/drivers/serial/uart_ra.c b/drivers/serial/uart_ra.c new file mode 100644 index 00000000000..a93ffff4b45 --- /dev/null +++ b/drivers/serial/uart_ra.c @@ -0,0 +1,395 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_ra_uart_sci + +#include +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(ra_uart_sci, CONFIG_UART_LOG_LEVEL); + +struct uart_ra_cfg { + mem_addr_t regs; + const struct device *clock_dev; + clock_control_subsys_t clock_id; + const struct pinctrl_dev_config *pcfg; +}; + +struct uart_ra_data { + struct uart_config current_config; + uint32_t clk_rate; + struct k_spinlock lock; +}; + +#define REG_MASK(reg) (BIT_MASK(_CONCAT(reg, _LEN)) << _CONCAT(reg, _POS)) + +/* Registers */ +#define SMR 0x00 /*!< Serial Mode Register */ +#define BRR 0x01 /*!< Bit Rate Register */ +#define SCR 0x02 /*!< Serial Control Register */ +#define TDR 0x03 /*!< Transmit Data Register */ +#define SSR 0x04 /*!< Serial Status Register */ +#define RDR 0x05 /*!< Receive Data Register */ +#define SEMR 0x07 /*!< Serial Extended Mode Register */ +#define MDDR 0x12 /*!< Modulation Duty Register */ +#define LSR 0x18 /*!< Line Status Register */ + +/* + * SMR (Serial Mode Register) + * + * - CKS[0..2]: Clock Select + * - MP[2..3]: Multi-Processor Mode(Valid only in asynchronous mode) + * - STOP[3..4]: Stop Bit Length(Valid only in asynchronous mode) + * - PM[4..5]: Parity Mode (Valid only when the PE bit is 1) + * - PE[5..6]: Parity Enable(Valid only in asynchronous mode) + * - CHR[6..7]: Character Length(Valid only in asynchronous mode) + * - CM[7..8]: Communication Mode + */ +#define SMR_CKS_POS (0) +#define SMR_CKS_LEN (2) +#define SMR_MP_POS (2) +#define SMR_MP_LEN (1) +#define SMR_STOP_POS (3) +#define SMR_STOP_LEN (1) +#define SMR_PM_POS (4) +#define SMR_PM_LEN (1) +#define SMR_PE_POS (5) +#define SMR_PE_LEN (1) +#define SMR_CHR_POS (6) +#define SMR_CHR_LEN (1) +#define SMR_CM_POS (7) +#define SMR_CM_LEN (1) + +/** + * SCR (Serial Control Register) + * + * - CKE[0..2]: Clock Enable + * - TEIE[2..3]: Transmit End Interrupt Enable + * - MPIE[3..4]: Multi-Processor Interrupt Enable (Valid in asynchronous + * - RE[4..5]: Receive Enable + * - TE[5..6]: Transmit Enable + * - RIE[6..7]: Receive Interrupt Enable + * - TIE[7..8]: Transmit Interrupt Enable + */ +#define SCR_CKE_POS (0) +#define SCR_CKE_LEN (2) +#define SCR_TEIE_POS (2) +#define SCR_TEIE_LEN (1) +#define SCR_MPIE_POS (3) +#define SCR_MPIE_LEN (1) +#define SCR_RE_POS (4) +#define SCR_RE_LEN (1) +#define SCR_TE_POS (5) +#define SCR_TE_LEN (1) +#define SCR_RIE_POS (6) +#define SCR_RIE_LEN (1) +#define SCR_TIE_POS (7) +#define SCR_TIE_LEN (1) + +/** + * SSR (Serial Status Register) + * + * - MPBT[0..1]: Multi-Processor Bit Transfer + * - MPB[1..2]: Multi-Processor + * - TEND[2..3]: Transmit End Flag + * - PER[3..4]: Parity Error Flag + * - FER[4..5]: Framing Error Flag + * - ORER[5..6]: Overrun Error Flag + * - RDRF[6..7]: Receive Data Full Flag + * - TDRE[7..8]: Transmit Data Empty Flag + */ +#define SSR_MPBT_POS (0) +#define SSR_MPBT_LEN (1) +#define SSR_MPB_POS (1) +#define SSR_MPB_LEN (1) +#define SSR_TEND_POS (2) +#define SSR_TEND_LEN (1) +#define SSR_PER_POS (3) +#define SSR_PER_LEN (1) +#define SSR_FER_POS (4) +#define SSR_FER_LEN (1) +#define SSR_ORER_POS (5) +#define SSR_ORER_LEN (1) +#define SSR_RDRF_POS (6) +#define SSR_RDRF_LEN (1) +#define SSR_TDRE_POS (7) +#define SSR_TDRE_LEN (1) + +/** + * SEMR (Serial Extended Mode Register) + * + * - ACS0[0..1]: Asynchronous Mode Clock Source Select + * - PADIS[1..2]: Preamble function Disable + * - BRME[2..3]: Bit Rate Modulation Enable + * - ABCSE[3..4]: Asynchronous Mode Extended Base Clock Select + * - ABCS[4..5]: Asynchronous Mode Base Clock Select + * - NFEN[5..6]: Digital Noise Filter Function Enable + * - BGDM[6..7]: Baud Rate Generator Double-Speed Mode Select + * - RXDESEL[7..8]: Asynchronous Start Bit Edge Detection Select + */ +#define SEMR_ACS0_POS (0) +#define SEMR_ACS0_LEN (1) +#define SEMR_PADIS_POS (1) +#define SEMR_PADIS_LEN (1) +#define SEMR_BRME_POS (2) +#define SEMR_BRME_LEN (1) +#define SEMR_ABCSE_POS (3) +#define SEMR_ABCSE_LEN (1) +#define SEMR_ABCS_POS (4) +#define SEMR_ABCS_LEN (1) +#define SEMR_NFEN_POS (5) +#define SEMR_NFEN_LEN (1) +#define SEMR_BGDM_POS (6) +#define SEMR_BGDM_LEN (1) +#define SEMR_RXDESEL_POS (7) +#define SEMR_RXDESEL_LEN (1) + +/** + * LSR (Line Status Register) + * + * - ORER[0..1]: Overrun Error Flag + * - FNUM[2..7]: Framing Error Count + * - PNUM[8..13]: Parity Error Count + */ +#define LSR_ORER_POS (0) +#define LSR_ORER_LEN (1) +#define LSR_FNUM_POS (2) +#define LSR_FNUM_LEN (5) +#define LSR_PNUM_POS (8) +#define LSR_PNUM_LEN (5) + +static uint8_t uart_ra_read_8(const struct device *dev, + uint32_t offs) +{ + const struct uart_ra_cfg *config = dev->config; + + return sys_read8(config->regs + offs); +} + +static void uart_ra_write_8(const struct device *dev, + uint32_t offs, uint8_t value) +{ + const struct uart_ra_cfg *config = dev->config; + + sys_write8(value, config->regs + offs); +} + +static uint16_t uart_ra_read_16(const struct device *dev, + uint32_t offs) +{ + const struct uart_ra_cfg *config = dev->config; + + return sys_read16(config->regs + offs); +} + +static void uart_ra_write_16(const struct device *dev, + uint32_t offs, uint16_t value) +{ + const struct uart_ra_cfg *config = dev->config; + + sys_write16(value, config->regs + offs); +} + +static void uart_ra_set_baudrate(const struct device *dev, + uint32_t baud_rate) +{ + struct uart_ra_data *data = dev->data; + uint8_t reg_val; + + reg_val = uart_ra_read_8(dev, SEMR); + reg_val |= REG_MASK(SEMR_BGDM); + reg_val &= ~(REG_MASK(SEMR_BRME) | REG_MASK(SEMR_ABCSE) | REG_MASK(SEMR_ABCS)); + uart_ra_write_8(dev, SEMR, reg_val); + + reg_val = (data->clk_rate / (16 * data->current_config.baudrate)) - 1; + uart_ra_write_8(dev, BRR, reg_val); +} + +static int uart_ra_poll_in(const struct device *dev, unsigned char *p_char) +{ + struct uart_ra_data *data = dev->data; + int ret = 0; + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + if ((uart_ra_read_8(dev, SSR) & REG_MASK(SSR_RDRF)) == 0) { + ret = -1; + goto unlock; + } + + *p_char = uart_ra_read_8(dev, RDR); +unlock: + k_spin_unlock(&data->lock, key); + + return ret; +} + +static void uart_ra_poll_out(const struct device *dev, unsigned char out_char) +{ + struct uart_ra_data *data = dev->data; + k_spinlock_key_t key = k_spin_lock(&data->lock); + + uart_ra_write_8(dev, TDR, out_char); + while (!(uart_ra_read_8(dev, SSR) & REG_MASK(SSR_TEND)) || + !(uart_ra_read_8(dev, SSR) & REG_MASK(SSR_TDRE))) { + ; + } + k_spin_unlock(&data->lock, key); +} + +static int uart_ra_configure(const struct device *dev, + const struct uart_config *cfg) +{ + struct uart_ra_data *data = dev->data; + + uint16_t reg_val; + k_spinlock_key_t key; + + if (cfg->parity != UART_CFG_PARITY_NONE || cfg->stop_bits != UART_CFG_STOP_BITS_1 || + cfg->data_bits != UART_CFG_DATA_BITS_8 || cfg->flow_ctrl != UART_CFG_FLOW_CTRL_NONE) { + return -ENOTSUP; + } + + key = k_spin_lock(&data->lock); + + /* Disable Transmit and Receive */ + reg_val = uart_ra_read_8(dev, SCR); + reg_val &= ~(REG_MASK(SCR_TE) | REG_MASK(SCR_RE)); + uart_ra_write_8(dev, SCR, reg_val); + + /* Resetting Errors Registers */ + reg_val = uart_ra_read_8(dev, SSR); + reg_val &= ~(REG_MASK(SSR_PER) | REG_MASK(SSR_FER) | REG_MASK(SSR_ORER) | + REG_MASK(SSR_RDRF) | REG_MASK(SSR_TDRE)); + uart_ra_write_8(dev, SSR, reg_val); + + reg_val = uart_ra_read_16(dev, LSR); + reg_val &= ~(REG_MASK(LSR_ORER)); + uart_ra_write_16(dev, LSR, reg_val); + + /* Select internal clock */ + reg_val = uart_ra_read_8(dev, SCR); + reg_val &= ~(REG_MASK(SCR_CKE)); + uart_ra_write_8(dev, SCR, reg_val); + + /* Serial Configuration (8N1) & Clock divider selection */ + reg_val = uart_ra_read_8(dev, SMR); + reg_val &= ~(REG_MASK(SMR_CM) | REG_MASK(SMR_CHR) | REG_MASK(SMR_PE) | REG_MASK(SMR_PM) | + REG_MASK(SMR_STOP) | REG_MASK(SMR_CKS)); + uart_ra_write_8(dev, SMR, reg_val); + + /* Set baudrate */ + uart_ra_set_baudrate(dev, cfg->baudrate); + + /* Enable Transmit & Receive + disable Interrupts */ + reg_val = uart_ra_read_8(dev, SCR); + reg_val |= (REG_MASK(SCR_TE) | REG_MASK(SCR_RE)); + reg_val &= + ~(REG_MASK(SCR_TIE) | REG_MASK(SCR_RIE) | REG_MASK(SCR_MPIE) | REG_MASK(SCR_TEIE)); + uart_ra_write_8(dev, SCR, reg_val); + + data->current_config = *cfg; + + k_spin_unlock(&data->lock, key); + + return 0; +} + +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE +static int uart_ra_config_get(const struct device *dev, + struct uart_config *cfg) +{ + struct uart_ra_data *data = dev->data; + + *cfg = data->current_config; + + return 0; +} +#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ + +static int uart_ra_init(const struct device *dev) +{ + const struct uart_ra_cfg *config = dev->config; + struct uart_ra_data *data = dev->data; + int ret; + + /* Configure dt provided device signals when available */ + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + return ret; + } + + if (!device_is_ready(config->clock_dev)) { + return -ENODEV; + } + + ret = clock_control_on(config->clock_dev, config->clock_id); + if (ret < 0) { + return ret; + } + + ret = clock_control_get_rate(config->clock_dev, config->clock_id, &data->clk_rate); + if (ret < 0) { + return ret; + } + + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); + + ret = uart_ra_configure(dev, &data->current_config); + if (ret != 0) { + return ret; + } + + return 0; +} + +static const struct uart_driver_api uart_ra_driver_api = { + .poll_in = uart_ra_poll_in, + .poll_out = uart_ra_poll_out, +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE + .configure = uart_ra_configure, + .config_get = uart_ra_config_get, +#endif +}; + +/* Device Instantiation */ +#define UART_RCAR_INIT_CFG(n) \ + PINCTRL_DT_DEFINE(DT_INST_PARENT(n)); \ + static const struct uart_ra_cfg uart_ra_cfg_##n = { \ + .regs = DT_REG_ADDR(DT_INST_PARENT(n)), \ + .clock_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_INST_PARENT(n))), \ + .clock_id = \ + (clock_control_subsys_t)DT_CLOCKS_CELL_BY_IDX(DT_INST_PARENT(n), 0, id), \ + .pcfg = PINCTRL_DT_DEV_CONFIG_GET(DT_INST_PARENT(n)), \ + } + +#define UART_RCAR_INIT(n) \ + UART_RCAR_INIT_CFG(n); \ + \ + static struct uart_ra_data uart_ra_data_##n = { \ + .current_config = { \ + .baudrate = DT_INST_PROP(n, current_speed), \ + .parity = UART_CFG_PARITY_NONE, \ + .stop_bits = UART_CFG_STOP_BITS_1, \ + .data_bits = UART_CFG_DATA_BITS_8, \ + .flow_ctrl = UART_CFG_FLOW_CTRL_NONE, \ + }, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, \ + uart_ra_init, \ + NULL, \ + &uart_ra_data_##n, \ + &uart_ra_cfg_##n, \ + PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \ + &uart_ra_driver_api); \ + \ + +DT_INST_FOREACH_STATUS_OKAY(UART_RCAR_INIT) diff --git a/drivers/serial/uart_rzt2m.c b/drivers/serial/uart_rzt2m.c new file mode 100644 index 00000000000..e4ebe251f21 --- /dev/null +++ b/drivers/serial/uart_rzt2m.c @@ -0,0 +1,446 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "uart_rzt2m.h" +#include "zephyr/spinlock.h" +#include "zephyr/sys/printk.h" +#include +#include +#include +#include +#include +#include +#include + +#define DT_DRV_COMPAT renesas_rzt2m_uart + +LOG_MODULE_REGISTER(uart_renesas_rzt2m, CONFIG_UART_LOG_LEVEL); + +struct rzt2m_device_config { + mm_reg_t base; + const struct pinctrl_dev_config *pin_config; + uart_irq_config_func_t irq_config_func; +}; + +struct rzt2m_device_data { + struct uart_config uart_cfg; + struct k_spinlock lock; +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + uart_irq_callback_user_data_t callback; + void *callback_data; +#endif +}; + +static int rzt2m_poll_in(const struct device *dev, unsigned char *c) +{ + if (!dev || !dev->config || !dev->data) { + return -ENODEV; + } + + const struct rzt2m_device_config *config = dev->config; + struct rzt2m_device_data *data = dev->data; + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + if (FRSR_R(*FRSR(config->base)) == 0) { + k_spin_unlock(&data->lock, key); + return -1; + } + *c = *RDR(config->base) & RDR_MASK_RDAT; + *CFCLR(config->base) |= CFCLR_MASK_RDRFC; + + if (FRSR_R(*FRSR(config->base)) == 0) { + *FFCLR(config->base) |= FFCLR_MASK_DRC; + } + + k_spin_unlock(&data->lock, key); + return 0; +} + +static void rzt2m_poll_out(const struct device *dev, unsigned char c) +{ + if (!dev || !dev->config || !dev->data) { + return; + } + + const struct rzt2m_device_config *config = dev->config; + struct rzt2m_device_data *data = dev->data; + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + int fifo_count = FTSR_T(*FTSR(config->base)); + + while (fifo_count == MAX_FIFO_DEPTH) { + fifo_count = FTSR_T(*FTSR(config->base)); + } + + *TDR(config->base) = c; + + /* Clear `Transmit data empty flag`. */ + *CFCLR(config->base) |= CFCLR_MASK_TDREC; + + k_spin_unlock(&data->lock, key); +} + +static int rzt2m_err_check(const struct device *dev) +{ + const struct rzt2m_device_config *config = dev->config; + + uint32_t status = *CSR(config->base); + uint32_t retval = 0; + + if (status & CSR_MASK_ORER) { + retval |= UART_ERROR_OVERRUN; + } + if (status & CSR_MASK_FER) { + retval |= UART_ERROR_FRAMING; + } + if (status & CSR_MASK_PER) { + retval |= UART_ERROR_PARITY; + } + + return retval; +} + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN +static int uart_rzt2m_irq_tx_ready(const struct device *dev); + +static int rzt2m_fifo_fill(const struct device *dev, const uint8_t *tx_data, int size) +{ + struct rzt2m_device_data *data = dev->data; + const struct rzt2m_device_config *config = dev->config; + int num_tx = 0; + k_spinlock_key_t key = k_spin_lock(&data->lock); + + while ((size - num_tx > 0) && uart_rzt2m_irq_tx_ready(dev)) { + *TDR(config->base) = (uint8_t)tx_data[num_tx++]; + } + + k_spin_unlock(&data->lock, key); + return num_tx; +} + +static int rzt2m_fifo_read(const struct device *dev, uint8_t *rx_data, const int size) +{ + struct rzt2m_device_data *data = dev->data; + const struct rzt2m_device_config *config = dev->config; + int num_rx = 0; + k_spinlock_key_t key = k_spin_lock(&data->lock); + + while (num_rx < size && (FRSR_R(*FRSR(config->base)))) { + rx_data[num_rx++] = *RDR(config->base); + } + *CFCLR(config->base) = CFCLR_MASK_RDRFC; + *FFCLR(config->base) = FFCLR_MASK_DRC; + k_spin_unlock(&data->lock, key); + return num_rx; +} + +static void uart_rzt2m_irq_rx_enable(const struct device *dev) +{ + const struct rzt2m_device_config *config = dev->config; + *CCR0(config->base) |= CCR0_MASK_RIE | CCR0_MASK_RE; +} + +static void uart_rzt2m_irq_rx_disable(const struct device *dev) +{ + const struct rzt2m_device_config *config = dev->config; + *CCR0(config->base) &= ~CCR0_MASK_RIE; +} + +static void uart_rzt2m_irq_tx_enable(const struct device *dev) +{ + const struct rzt2m_device_config *config = dev->config; + /* These bits must be set simultaneously. */ + *CCR0(config->base) |= CCR0_MASK_TE | CCR0_MASK_TIE | CCR0_MASK_TEIE; +} + +static void uart_rzt2m_irq_tx_disable(const struct device *dev) +{ + const struct rzt2m_device_config *config = dev->config; + *CCR0(config->base) &= ~(CCR0_MASK_TIE | CCR0_MASK_TEIE); +} + +static int uart_rzt2m_irq_tx_ready(const struct device *dev) +{ + const struct rzt2m_device_config *config = dev->config; + + if (FTSR_T(*FTSR(config->base)) == MAX_FIFO_DEPTH || + ((*CCR0(config->base) & CCR0_MASK_TIE) == 0)) { + return 0; + } + + return 1; +} + +static int uart_rzt2m_irq_rx_ready(const struct device *dev) +{ + const struct rzt2m_device_config *config = dev->config; + + if (FRSR_R(*FRSR(config->base))) { + return 1; + } + + return 0; +} + +static int uart_rzt2m_irq_is_pending(const struct device *dev) +{ + const struct rzt2m_device_config *config = dev->config; + + if ((*CSR(config->base) & (CSR_MASK_RDRF)) || (*FRSR(config->base) & FRSR_MASK_DR)) { + return 1; + } + return 0; +} + +static void uart_rzt2m_irq_callback_set(const struct device *dev, uart_irq_callback_user_data_t cb, + void *cb_data) +{ + struct rzt2m_device_data *data = dev->data; + + data->callback = cb; + data->callback_data = cb_data; +} + +static int uart_rzt2m_irq_update(const struct device *dev) +{ + const struct rzt2m_device_config *config = dev->config; + + *CFCLR(config->base) = CFCLR_MASK_RDRFC; + *FFCLR(config->base) = FFCLR_MASK_DRC; + return 1; +} +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + +static const struct uart_driver_api rzt2m_uart_api = { + .poll_in = rzt2m_poll_in, + .poll_out = rzt2m_poll_out, + .err_check = rzt2m_err_check, +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + .fifo_fill = rzt2m_fifo_fill, + .fifo_read = rzt2m_fifo_read, + .irq_rx_enable = uart_rzt2m_irq_rx_enable, + .irq_rx_disable = uart_rzt2m_irq_rx_disable, + .irq_tx_enable = uart_rzt2m_irq_tx_enable, + .irq_tx_disable = uart_rzt2m_irq_tx_disable, + .irq_tx_ready = uart_rzt2m_irq_tx_ready, + .irq_rx_ready = uart_rzt2m_irq_rx_ready, + .irq_is_pending = uart_rzt2m_irq_is_pending, + .irq_callback_set = uart_rzt2m_irq_callback_set, + .irq_update = uart_rzt2m_irq_update, +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +}; + +static int rzt2m_module_start(const struct device *dev) +{ + if (!dev || !dev->config || !dev->data) { + return -ENODEV; + } + + const struct rzt2m_device_config *config = dev->config; + struct rzt2m_device_data *data = dev->data; + int interface_id = BASE_TO_IFACE_ID(config->base); + unsigned int irqkey = irq_lock(); + volatile uint32_t dummy; + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + if (interface_id < 5) { + /* Dummy-read at least one time as stated in 8.3.1 of the User's Manual: Hardware */ + *MSTPCRA &= ~(MSTPCRA_MASK_SCIx(interface_id)); + dummy = *MSTPCRA; + } else { + LOG_ERR("SCI modules in the secure domain on RZT2M are not supported."); + return -ENOTSUP; + } + + /* Dummy-read at least five times as stated in 8.3.1 of the User's Manual: Hardware */ + dummy = *RDR(config->base); + dummy = *RDR(config->base); + dummy = *RDR(config->base); + dummy = *RDR(config->base); + dummy = *RDR(config->base); + + k_spin_unlock(&data->lock, key); + irq_unlock(irqkey); + return 0; +} + +static int rzt2m_uart_init(const struct device *dev) +{ + const struct rzt2m_device_config *config = dev->config; + struct rzt2m_device_data *data = dev->data; + uint32_t baud_setting = 0; + uint32_t baud_settings[] = {CCR2_BAUD_SETTING_9600, CCR2_BAUD_SETTING_115200}; + + rzt2m_unlock_prcrs(PRCRS_GPIO); + rzt2m_unlock_prcrn(PRCRN_PRC1 | PRCRN_PRC2); + + /* The module needs to be started + * to allow any operation on the registers of Serial Communications Interface. + */ + int ret = rzt2m_module_start(dev); + + if (ret) { + return ret; + } + + /* Disable transmitter, receiver, interrupts. */ + *CCR0(config->base) = CCR0_DEFAULT_VALUE; + while (*CCR0(config->base) & (CCR0_MASK_RE | CCR0_MASK_TE)) { + } + + *CCR1(config->base) = CCR1_DEFAULT_VALUE; + *CCR2(config->base) = CCR2_DEFAULT_VALUE; + *CCR3(config->base) = CCR3_DEFAULT_VALUE; + *CCR4(config->base) = CCR4_DEFAULT_VALUE; + + /* Configure pinmuxes */ + ret = pinctrl_apply_state(config->pin_config, PINCTRL_STATE_DEFAULT); + if (ret) { + return ret; + } + + *CFCLR(config->base) = CFCLR_ALL_FLAG_CLEAR; + *FFCLR(config->base) = FFCLR_MASK_DRC; + + /* Use FIFO mode. */ + *CCR3(config->base) |= (CCR3_MASK_FM); + + switch (data->uart_cfg.stop_bits) { + case UART_CFG_STOP_BITS_1: + /* Default value, already set. */ + break; + case UART_CFG_STOP_BITS_2: + *CCR3(config->base) |= CCR3_MASK_STP; + break; + default: + LOG_ERR("Selected bit stop length is not supported: %u.", data->uart_cfg.stop_bits); + return -ENOTSUP; + } + + switch (data->uart_cfg.data_bits) { + case UART_CFG_DATA_BITS_7: + *CCR3(config->base) |= CCR3_CHR_7BIT; + break; + case UART_CFG_DATA_BITS_8: + *CCR3(config->base) |= CCR3_CHR_8BIT; + break; + default: + LOG_ERR("Selected number of data bits is not supported: %u.", + data->uart_cfg.data_bits); + return -ENOTSUP; + } + + if (data->uart_cfg.baudrate > ARRAY_SIZE(baud_settings)) { + LOG_ERR("Selected baudrate variant is not supported: %u.", data->uart_cfg.baudrate); + return -ENOTSUP; + } + baud_setting = baud_settings[data->uart_cfg.baudrate]; + + *CCR2(config->base) &= ~(CCR2_MASK_BAUD_SETTING); + *CCR2(config->base) |= (baud_setting & CCR2_MASK_BAUD_SETTING); + + *CCR1(config->base) |= (CCR1_MASK_NFEN | CCR1_MASK_SPB2DT | CCR1_MASK_SPB2IO); + + switch (data->uart_cfg.parity) { + case UART_CFG_PARITY_NONE: + /* Default value, already set. */ + break; + case UART_CFG_PARITY_EVEN: + *CCR1(config->base) |= CCR1_MASK_PE; + break; + case UART_CFG_PARITY_ODD: + *CCR1(config->base) |= (CCR1_MASK_PE | CCR1_MASK_PM); + break; + default: + LOG_ERR("Unsupported parity: %u", data->uart_cfg.parity); + } + + /* Specify trigger thresholds and clear FIFOs. */ + *FCR(config->base) = FCR_MASK_TFRST | FCR_MASK_RFRST | FCR_TTRG_15 | FCR_RTRG_15; + + /* Enable the clock. */ + *CCR3(config->base) &= ~CCR3_MASK_CKE; + *CCR3(config->base) |= CCR3_CKE_ENABLE; + + /* Clear status flags. */ + *CFCLR(config->base) = CFCLR_ALL_FLAG_CLEAR; + *FFCLR(config->base) = FFCLR_MASK_DRC; + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + config->irq_config_func(dev); +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + + /* Start trasmitter and receiver. */ + *CCR0(config->base) |= (CCR0_MASK_TE | CCR0_MASK_RE); + while (!(*CCR0(config->base) & CCR0_MASK_RE)) { + } + while (!(*CCR0(config->base) & CCR0_MASK_TE)) { + } + + rzt2m_lock_prcrs(PRCRS_GPIO); + rzt2m_lock_prcrn(PRCRN_PRC1 | PRCRN_PRC2); + + return 0; +} + +static void uart_rzt2m_isr(const struct device *dev) +{ + const struct rzt2m_device_config *config = dev->config; +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + struct rzt2m_device_data *data = dev->data; + + if (data->callback) { + data->callback(dev, data->callback_data); + } +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + + *CFCLR(config->base) = CFCLR_MASK_RDRFC; + *FFCLR(config->base) = FFCLR_MASK_DRC; +} + +#define UART_RZT2M_IRQ_CONNECT(n, irq_name) \ + do { \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, irq_name, irq), \ + DT_INST_IRQ_BY_NAME(n, irq_name, priority), uart_rzt2m_isr, \ + DEVICE_DT_INST_GET(n), DT_INST_IRQ_BY_NAME(n, irq_name, flags)); \ + irq_enable(DT_INST_IRQ_BY_NAME(n, irq_name, irq)); \ + } while (false) + +#define UART_RZT2M_CONFIG_FUNC(n) \ + static void uart##n##_rzt2m_irq_config(const struct device *port) \ + { \ + UART_RZT2M_IRQ_CONNECT(n, rx_err); \ + UART_RZT2M_IRQ_CONNECT(n, rx); \ + UART_RZT2M_IRQ_CONNECT(n, tx); \ + UART_RZT2M_IRQ_CONNECT(n, tx_end); \ + } + +#define UART_RZT2M_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + static struct rzt2m_device_data rzt2m_uart_##n##data = { \ + .uart_cfg = \ + { \ + .baudrate = DT_INST_ENUM_IDX(n, current_speed), \ + .parity = DT_INST_ENUM_IDX_OR(n, parity, UART_CFG_PARITY_NONE), \ + .stop_bits = \ + DT_INST_ENUM_IDX_OR(n, stop_bits, UART_CFG_STOP_BITS_1), \ + .data_bits = \ + DT_INST_ENUM_IDX_OR(n, data_bits, UART_CFG_DATA_BITS_8), \ + }, \ + }; \ + UART_RZT2M_CONFIG_FUNC(n); \ + static const struct rzt2m_device_config rzt2m_uart_##n##_config = { \ + .base = DT_INST_REG_ADDR(n), \ + .irq_config_func = uart##n##_rzt2m_irq_config, \ + .pin_config = PINCTRL_DT_INST_DEV_CONFIG_GET(n)}; \ + DEVICE_DT_INST_DEFINE(n, &rzt2m_uart_init, NULL, &rzt2m_uart_##n##data, \ + &rzt2m_uart_##n##_config, PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \ + &rzt2m_uart_api); + +DT_INST_FOREACH_STATUS_OKAY(UART_RZT2M_INIT) diff --git a/drivers/serial/uart_rzt2m.h b/drivers/serial/uart_rzt2m.h new file mode 100644 index 00000000000..829064857b0 --- /dev/null +++ b/drivers/serial/uart_rzt2m.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SERIAL_UART_RZT2M_H_ +#define ZEPHYR_DRIVERS_SERIAL_UART_RZT2M_H_ + +#include + +#define MAX_FIFO_DEPTH 16 + +#define RDR(base) ((volatile uint32_t *)(base)) +#define TDR(base) ((volatile uint32_t *)(base + 0x04)) +#define CCR0(base) ((volatile uint32_t *)(base + 0x08)) +#define CCR1(base) ((volatile uint32_t *)(base + 0x0c)) +#define CCR2(base) ((volatile uint32_t *)(base + 0x10)) +#define CCR3(base) ((volatile uint32_t *)(base + 0x14)) +#define CCR4(base) ((volatile uint32_t *)(base + 0x18)) +#define FCR(base) ((volatile uint32_t *)(base + 0x24)) +#define CSR(base) ((volatile uint32_t *)(base + 0x48)) +#define FRSR(base) ((volatile uint32_t *)(base + 0x50)) +#define FTSR(base) ((volatile uint32_t *)(base + 0x54)) +#define CFCLR(base) ((volatile uint32_t *)(base + 0x68)) +#define FFCLR(base) ((volatile uint32_t *)(base + 0x70)) + +#define CCR0_DEFAULT_VALUE 0x0 +#define CCR1_DEFAULT_VALUE 0x00000010 +#define CCR2_DEFAULT_VALUE 0xff00ff04 +#define CCR3_DEFAULT_VALUE 0x00001203 +#define CCR4_DEFAULT_VALUE 0x0 + +#define RDR_MASK_RDAT GENMASK(8, 0) + +#define CCR0_MASK_RE BIT(0) +#define CCR0_MASK_TE BIT(4) +#define CCR0_MASK_DCME BIT(9) +#define CCR0_MASK_IDSEL BIT(10) +#define CCR0_MASK_RIE BIT(16) +#define CCR0_MASK_TIE BIT(20) +#define CCR0_MASK_TEIE BIT(21) +#define CCR0_MASK_SSE BIT(24) + +#define CCR1_MASK_CTSE BIT(0) +#define CCR1_MASK_SPB2DT BIT(4) +#define CCR1_MASK_SPB2IO BIT(5) +#define CCR1_MASK_PE BIT(8) +#define CCR1_MASK_PM BIT(9) +#define CCR1_MASK_NFEN BIT(28) + +#define CCR2_MASK_BGDM BIT(4) +#define CCR2_MASK_ABCS BIT(5) +#define CCR2_MASK_ABCSE BIT(6) +#define CCR2_MASK_BRR GENMASK(15, 8) +#define CCR2_MASK_BRME BIT(16) +#define CCR2_MASK_CKS GENMASK(21, 20) +#define CCR2_MASK_MDDR GENMASK(31, 24) +#define CCR2_MASK_BAUD_SETTING \ + (CCR2_MASK_BRME | CCR2_MASK_ABCSE | CCR2_MASK_ABCS | CCR2_MASK_BGDM | CCR2_MASK_CKS | \ + CCR2_MASK_BRR | CCR2_MASK_MDDR) + +#define CCR3_MASK_STP BIT(14) +#define CCR3_MASK_MP BIT(19) +#define CCR3_MASK_FM BIT(20) +#define CCR3_MASK_CKE (BIT(24) | BIT(25)) +#define CCR3_CKE_ENABLE BIT(24) +#define CCR3_CHR_7BIT (BIT(8) | BIT(9)) +#define CCR3_CHR_8BIT BIT(9) + +#define CCR4_MASK_ASEN BIT(16) +#define CCR4_MASK_ATEN BIT(17) + +#define FCR_MASK_TFRST BIT(15) +#define FCR_MASK_RFRST BIT(23) +#define FCR_MASK_TTRG GENMASK(12, 8) +#define FCR_MASK_RTRG GENMASK(20, 16) +#define FCR_TTRG_15 (15 << 8) +#define FCR_RTRG_15 (15 << 16) + +#define CSR_MASK_ORER BIT(24) +#define CSR_MASK_PER BIT(27) +#define CSR_MASK_FER BIT(28) +#define CSR_MASK_TDRE BIT(29) +#define CSR_MASK_TEND BIT(30) +#define CSR_MASK_RDRF BIT(31) + +#define FRSR_MASK_DR BIT(0) +#define FRSR_R(val) ((val >> 7) & 0x3f) + +#define FTSR_T(val) (val & 0x3f) + +#define CFCLR_MASK_ERSC BIT(4) +#define CFCLR_MASK_DCMFC BIT(16) +#define CFCLR_MASK_DPERC BIT(17) +#define CFCLR_MASK_DFERC BIT(18) +#define CFCLR_MASK_ORERC BIT(24) +#define CFCLR_MASK_MFFC BIT(26) +#define CFCLR_MASK_PERC BIT(27) +#define CFCLR_MASK_FERC BIT(28) +#define CFCLR_MASK_TDREC BIT(29) +#define CFCLR_MASK_RDRFC BIT(31) +#define CFCLR_ALL_FLAG_CLEAR \ + (CFCLR_MASK_ERSC | CFCLR_MASK_DCMFC | CFCLR_MASK_DPERC | CFCLR_MASK_DFERC | \ + CFCLR_MASK_ORERC | CFCLR_MASK_MFFC | CFCLR_MASK_PERC | CFCLR_MASK_FERC | \ + CFCLR_MASK_TDREC | CFCLR_MASK_RDRFC) + +#define FFCLR_MASK_DRC BIT(0) + +#define MSTPCRA (volatile uint32_t *)(0x80280000 + 0x300) +#define MSTPCRA_MASK_SCIx(x) BIT(x + 8) +#define BASE_TO_IFACE_ID(base) ((base & 0x1000000) ? 5 : ((base & 0xff00) >> 10) - 4) + +#define CCR2_MDDR_128 BIT(31) +#define CCR2_CKS_0 0 +#define CCR2_BRME_0 0 +#define CCR2_BRR_243 (0xf3 << 8) +#define CCR2_BRR_39 (0x27 << 8) +#define CCR2_BGDM_1 BIT(4) + +#define CCR2_BAUD_SETTING_9600 (CCR2_MDDR_128 | CCR2_BRR_243) +#define CCR2_BAUD_SETTING_115200 (CCR2_MDDR_128 | CCR2_BRR_39 | CCR2_BGDM_1) + +#endif /* ZEPHYR_DRIVERS_SERIAL_UART_RZT2M_H_ */ diff --git a/drivers/serial/uart_stm32.c b/drivers/serial/uart_stm32.c index 9243b10d7e7..fa2371cc1df 100644 --- a/drivers/serial/uart_stm32.c +++ b/drivers/serial/uart_stm32.c @@ -51,8 +51,7 @@ LOG_MODULE_REGISTER(uart_stm32, CONFIG_UART_LOG_LEVEL); #define STM32_UART_DOMAIN_CLOCK_SUPPORT 0 #endif -#define HAS_LPUART_1 (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(lpuart1), \ - st_stm32_lpuart, okay)) +#define HAS_LPUART DT_HAS_COMPAT_STATUS_OKAY(st_stm32_lpuart) /* Available everywhere except l1, f1, f2, f4. */ #ifdef USART_CR3_DEM @@ -61,7 +60,7 @@ LOG_MODULE_REGISTER(uart_stm32, CONFIG_UART_LOG_LEVEL); #define HAS_DRIVER_ENABLE 0 #endif -#if HAS_LPUART_1 +#if HAS_LPUART #ifdef USART_PRESC_PRESCALER uint32_t lpuartdiv_calc(const uint64_t clock_rate, const uint16_t presc_idx, const uint32_t baud_rate) @@ -87,7 +86,7 @@ uint32_t lpuartdiv_calc(const uint64_t clock_rate, const uint32_t baud_rate) return (uint32_t)lpuartdiv; } #endif /* USART_PRESC_PRESCALER */ -#endif /* HAS_LPUART_1 */ +#endif /* HAS_LPUART */ #ifdef CONFIG_PM static void uart_stm32_pm_policy_state_lock_get(const struct device *dev) @@ -135,7 +134,7 @@ static inline void uart_stm32_set_baudrate(const struct device *dev, uint32_t ba } } -#if HAS_LPUART_1 +#if HAS_LPUART if (IS_LPUART_INSTANCE(config->usart)) { uint32_t lpuartdiv; #ifdef USART_PRESC_PRESCALER @@ -178,7 +177,7 @@ static inline void uart_stm32_set_baudrate(const struct device *dev, uint32_t ba __ASSERT(LL_LPUART_ReadReg(config->usart, BRR) < 0x000FFFFFU, "BaudRateReg < 0xFFFF"); } else { -#endif /* HAS_LPUART_1 */ +#endif /* HAS_LPUART */ #ifdef USART_CR1_OVER8 LL_USART_SetOverSampling(config->usart, LL_USART_OVERSAMPLING_16); @@ -196,9 +195,9 @@ static inline void uart_stm32_set_baudrate(const struct device *dev, uint32_t ba __ASSERT(LL_USART_ReadReg(config->usart, BRR) >= 16, "BaudRateReg >= 16"); -#if HAS_LPUART_1 +#if HAS_LPUART } -#endif /* HAS_LPUART_1 */ +#endif /* HAS_LPUART */ } static inline void uart_stm32_set_parity(const struct device *dev, @@ -315,12 +314,12 @@ static inline uint32_t uart_stm32_cfg2ll_stopbits(const struct uart_stm32_config /* Some MCU's don't support 0.5 stop bits */ #ifdef LL_USART_STOPBITS_0_5 case UART_CFG_STOP_BITS_0_5: -#if HAS_LPUART_1 +#if HAS_LPUART if (IS_LPUART_INSTANCE(config->usart)) { /* return the default */ return LL_USART_STOPBITS_1; } -#endif /* HAS_LPUART_1 */ +#endif /* HAS_LPUART */ return LL_USART_STOPBITS_0_5; #endif /* LL_USART_STOPBITS_0_5 */ case UART_CFG_STOP_BITS_1: @@ -328,7 +327,7 @@ static inline uint32_t uart_stm32_cfg2ll_stopbits(const struct uart_stm32_config /* Some MCU's don't support 1.5 stop bits */ #ifdef LL_USART_STOPBITS_1_5 case UART_CFG_STOP_BITS_1_5: -#if HAS_LPUART_1 +#if HAS_LPUART if (IS_LPUART_INSTANCE(config->usart)) { /* return the default */ return LL_USART_STOPBITS_2; @@ -1580,6 +1579,13 @@ static int uart_stm32_async_rx_enable(const struct device *dev, return -EFAULT; } + /* Flush RX data buffer */ +#ifdef USART_SR_RXNE + LL_USART_ClearFlag_RXNE(config->usart); +#else + LL_USART_RequestRxDataFlush(config->usart); +#endif /* USART_SR_RXNE */ + /* Enable RX DMA requests */ uart_stm32_dma_rx_enable(dev); diff --git a/drivers/sip_svc/Kconfig.sip_smc_agilex b/drivers/sip_svc/Kconfig.sip_smc_agilex index 5b982e7c721..50e1247325c 100644 --- a/drivers/sip_svc/Kconfig.sip_smc_agilex +++ b/drivers/sip_svc/Kconfig.sip_smc_agilex @@ -4,7 +4,7 @@ config ARM_SIP_SVC_HAS_INTEL_SDM_MAILBOX_FIFO bool default y - depends on DT_HAS_INTEL_AGILEX_SOCFPGA_SIP_SMC_ENABLED + depends on DT_HAS_INTEL_SOCFPGA_AGILEX_SIP_SMC_ENABLED imply ARM_SIP_SVC_HAS_DRIVER help Support for SDM mailbox fifo in Intel SoC FPGA Agilex via SMC calls. diff --git a/drivers/sip_svc/sip_smc_intel_socfpga.c b/drivers/sip_svc/sip_smc_intel_socfpga.c index af6ffe95c71..09d351798e3 100644 --- a/drivers/sip_svc/sip_smc_intel_socfpga.c +++ b/drivers/sip_svc/sip_smc_intel_socfpga.c @@ -11,13 +11,13 @@ #include #include #include -#include +#include #include -LOG_MODULE_REGISTER(intel_agilex_socfpga_sip_smc, CONFIG_ARM_SIP_SVC_DRIVER_LOG_LEVEL); +LOG_MODULE_REGISTER(intel_socfpga_agilex_sip_smc, CONFIG_ARM_SIP_SVC_DRIVER_LOG_LEVEL); -#define DT_DRV_COMPAT intel_agilex_socfpga_sip_smc +#define DT_DRV_COMPAT intel_socfpga_agilex_sip_smc #define DT_SIP_SMC DT_COMPAT_GET_ANY_STATUS_OKAY(DT_DRV_COMPAT) @@ -39,6 +39,7 @@ static bool intel_sip_smc_plat_func_id_valid(const struct device *dev, uint32_t case SMC_FUNC_ID_REG_WRITE: case SMC_FUNC_ID_REG_UPDATE: case SMC_FUNC_ID_SET_HPS_BRIDGES: + case SMC_FUNC_ID_RSU_UPDATE_ADDR: valid = true; break; default: @@ -66,7 +67,7 @@ static uint32_t intel_sip_smc_plat_format_trans_id(const struct device *dev, uin { ARG_UNUSED(dev); - /*combine the transaction id and client id to get the job id*/ + /* Combine the transaction id and client id to get the job id*/ return (((client_idx & 0xF) << 4) | (trans_idx & 0xF)); } @@ -171,8 +172,9 @@ static void intel_sip_secure_monitor_call(const struct device *dev, unsigned lon { __ASSERT_NO_MSG(dev != NULL); __ASSERT_NO_MSG(res != NULL); + uint64_t start, end; - LOG_INF("Before %s call", DT_PROP(DT_SIP_SMC, method)); + LOG_DBG("Before %s call", DT_PROP(DT_SIP_SMC, method)); LOG_DBG("\tfunction_id %08lx", function_id); LOG_DBG("\targ0 %08lx", arg0); LOG_DBG("\targ1 %08lx", arg1); @@ -182,9 +184,14 @@ static void intel_sip_secure_monitor_call(const struct device *dev, unsigned lon LOG_DBG("\targ5 %08lx", arg5); LOG_DBG("\targ6 %08lx", arg6); + start = k_cycle_get_64(); arm_smccc_smc(function_id, arg0, arg1, arg2, arg3, arg4, arg5, arg6, res); + end = k_cycle_get_64(); - LOG_INF("After %s call", DT_PROP(DT_SIP_SMC, method)); + LOG_INF("Time taken for %08lx is %08lld ns", function_id, + k_cyc_to_ns_ceil64(end - start)); + + LOG_DBG("After %s call", DT_PROP(DT_SIP_SMC, method)); LOG_DBG("\tres->a0 %08lx", res->a0); LOG_DBG("\tres->a1 %08lx", res->a1); LOG_DBG("\tres->a2 %08lx", res->a2); diff --git a/drivers/smbus/Kconfig b/drivers/smbus/Kconfig index b80e1df2dd9..88eff8b0030 100644 --- a/drivers/smbus/Kconfig +++ b/drivers/smbus/Kconfig @@ -12,7 +12,6 @@ if SMBUS config SMBUS_SHELL bool "SMBus Shell" - default y depends on SHELL help Enable SMBus Shell. diff --git a/drivers/smbus/intel_pch_smbus.c b/drivers/smbus/intel_pch_smbus.c index c5713d984a6..e40fc3d0cb6 100644 --- a/drivers/smbus/intel_pch_smbus.c +++ b/drivers/smbus/intel_pch_smbus.c @@ -1005,10 +1005,10 @@ static void smbus_isr(const struct device *dev) /* Device macro initialization / DTS hackery */ -#define SMBUS_PCH_IRQ_FLAGS_SENSE0(n) 0 -#define SMBUS_PCH_IRQ_FLAGS_SENSE1(n) DT_INST_IRQ(n, sense) -#define SMBUS_PCH_IRQ_FLAGS(n) \ - _CONCAT(SMBUS_PCH_IRQ_FLAGS_SENSE, DT_INST_IRQ_HAS_CELL(n, sense))(n) +#define SMBUS_PCH_IRQ_FLAGS(n) \ + COND_CODE_1(DT_INST_IRQ_HAS_CELL(n, sense), \ + (DT_INST_IRQ(n, sense)), \ + (0)) #define SMBUS_IRQ_CONFIG(n) \ BUILD_ASSERT(IS_ENABLED(CONFIG_DYNAMIC_INTERRUPTS), \ diff --git a/drivers/smbus/smbus_handlers.c b/drivers/smbus/smbus_handlers.c index 0c979788830..b9c45e76cf7 100644 --- a/drivers/smbus/smbus_handlers.c +++ b/drivers/smbus/smbus_handlers.c @@ -5,13 +5,13 @@ */ #include -#include +#include #include static inline int z_vrfy_smbus_configure(const struct device *dev, uint32_t dev_config) { - Z_OOPS(Z_SYSCALL_DRIVER_SMBUS(dev, configure)); + K_OOPS(K_SYSCALL_DRIVER_SMBUS(dev, configure)); return z_impl_smbus_configure(dev, dev_config); } @@ -20,8 +20,8 @@ static inline int z_vrfy_smbus_configure(const struct device *dev, static inline int z_vrfy_smbus_get_config(const struct device *dev, uint32_t *dev_config) { - Z_OOPS(Z_SYSCALL_DRIVER_SMBUS(dev, get_config)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(dev_config, sizeof(uint32_t))); + K_OOPS(K_SYSCALL_DRIVER_SMBUS(dev, get_config)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(dev_config, sizeof(uint32_t))); return z_impl_smbus_get_config(dev, dev_config); } @@ -30,7 +30,7 @@ static inline int z_vrfy_smbus_get_config(const struct device *dev, static inline int z_vrfy_smbus_quick(const struct device *dev, uint16_t addr, enum smbus_direction rw) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); return z_impl_smbus_quick(dev, addr, rw); } @@ -39,7 +39,7 @@ static inline int z_vrfy_smbus_quick(const struct device *dev, uint16_t addr, static inline int z_vrfy_smbus_byte_write(const struct device *dev, uint16_t addr, uint8_t byte) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); return z_impl_smbus_byte_write(dev, addr, byte); } @@ -48,8 +48,8 @@ static inline int z_vrfy_smbus_byte_write(const struct device *dev, static inline int z_vrfy_smbus_byte_read(const struct device *dev, uint16_t addr, uint8_t *byte) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(byte, sizeof(uint8_t))); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(byte, sizeof(uint8_t))); return z_impl_smbus_byte_read(dev, addr, byte); } @@ -59,7 +59,7 @@ static inline int z_vrfy_smbus_byte_data_write(const struct device *dev, uint16_t addr, uint8_t cmd, uint8_t byte) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); return z_impl_smbus_byte_data_write(dev, addr, cmd, byte); } @@ -69,8 +69,8 @@ static inline int z_vrfy_smbus_byte_data_read(const struct device *dev, uint16_t addr, uint8_t cmd, uint8_t *byte) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(byte, sizeof(uint8_t))); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(byte, sizeof(uint8_t))); return z_impl_smbus_byte_data_read(dev, addr, cmd, byte); } @@ -80,7 +80,7 @@ static inline int z_vrfy_smbus_word_data_write(const struct device *dev, uint16_t addr, uint8_t cmd, uint16_t word) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); return z_impl_smbus_word_data_write(dev, addr, cmd, word); } @@ -90,8 +90,8 @@ static inline int z_vrfy_smbus_word_data_read(const struct device *dev, uint16_t addr, uint8_t cmd, uint16_t *word) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(word, sizeof(uint16_t))); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(word, sizeof(uint16_t))); return z_impl_smbus_word_data_read(dev, addr, cmd, word); } @@ -101,8 +101,8 @@ static inline int z_vrfy_smbus_pcall(const struct device *dev, uint16_t addr, uint8_t cmd, uint16_t send_word, uint16_t *recv_word) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(recv_word, sizeof(uint16_t))); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(recv_word, sizeof(uint16_t))); return z_impl_smbus_pcall(dev, addr, cmd, send_word, recv_word); } @@ -112,8 +112,8 @@ static inline int z_vrfy_smbus_block_write(const struct device *dev, uint16_t addr, uint8_t cmd, uint8_t count, uint8_t *buf) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(buf, count)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); + K_OOPS(K_SYSCALL_MEMORY_READ(buf, count)); return z_impl_smbus_block_write(dev, addr, cmd, count, buf); } @@ -123,8 +123,8 @@ static inline int z_vrfy_smbus_block_read(const struct device *dev, uint16_t addr, uint8_t cmd, uint8_t *count, uint8_t *buf) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(count, sizeof(uint8_t))); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(count, sizeof(uint8_t))); return z_impl_smbus_block_read(dev, addr, cmd, count, buf); } @@ -135,46 +135,28 @@ static inline int z_vrfy_smbus_block_pcall(const struct device *dev, uint8_t snd_count, uint8_t *snd_buf, uint8_t *rcv_count, uint8_t *rcv_buf) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(snd_buf, snd_count)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(rcv_count, sizeof(uint8_t))); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); + K_OOPS(K_SYSCALL_MEMORY_READ(snd_buf, snd_count)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(rcv_count, sizeof(uint8_t))); return z_impl_smbus_block_pcall(dev, addr, cmd, snd_count, snd_buf, rcv_count, rcv_buf); } #include -static inline int z_vrfy_smbus_smbalert_set_cb(const struct device *dev, - struct smbus_callback *cb) -{ - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); - - return z_impl_smbus_smbalert_set_cb(dev, cb); -} -#include - static inline int z_vrfy_smbus_smbalert_remove_cb(const struct device *dev, struct smbus_callback *cb) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); return z_impl_smbus_smbalert_remove_cb(dev, cb); } #include -static inline int z_vrfy_smbus_host_notify_set_cb(const struct device *dev, - struct smbus_callback *cb) -{ - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); - - return z_impl_smbus_host_notify_set_cb(dev, cb); -} -#include - static inline int z_vrfy_smbus_host_notify_remove_cb(const struct device *dev, struct smbus_callback *cb) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS)); return z_impl_smbus_host_notify_remove_cb(dev, cb); } diff --git a/drivers/spi/CMakeLists.txt b/drivers/spi/CMakeLists.txt index b9b2cd814f9..956b6d3397a 100644 --- a/drivers/spi/CMakeLists.txt +++ b/drivers/spi/CMakeLists.txt @@ -43,7 +43,10 @@ zephyr_library_sources_ifdef(CONFIG_SPI_OPENTITAN spi_opentitan.c) zephyr_library_sources_ifdef(CONFIG_SPI_NUMAKER spi_numaker.c) zephyr_library_sources_ifdef(CONFIG_SPI_AMBIQ spi_ambiq.c) zephyr_library_sources_ifdef(CONFIG_SPI_RPI_PICO_PIO spi_rpi_pico_pio.c) +zephyr_library_sources_ifdef(CONFIG_MSPI_AMBIQ mspi_ambiq.c) zephyr_library_sources_ifdef(CONFIG_SPI_RTIO spi_rtio.c) zephyr_library_sources_ifdef(CONFIG_SPI_ASYNC spi_signal.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE spi_handlers.c) +zephyr_library_sources_ifdef(CONFIG_SPI_INFINEON_CAT1 spi_ifx_cat1.c) +zephyr_library_sources_ifdef(CONFIG_SPI_SEDI spi_sedi.c) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index cbc11b374ab..24982cae90e 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -133,4 +133,8 @@ source "drivers/spi/Kconfig.ambiq" source "drivers/spi/Kconfig.rpi_pico" +source "drivers/spi/Kconfig.ifx_cat1" + +source "drivers/spi/Kconfig.sedi" + endif # SPI diff --git a/drivers/spi/Kconfig.ambiq b/drivers/spi/Kconfig.ambiq index 130b6575136..15eaf7463a4 100644 --- a/drivers/spi/Kconfig.ambiq +++ b/drivers/spi/Kconfig.ambiq @@ -13,3 +13,12 @@ config SPI_AMBIQ select AMBIQ_HAL_USE_SPI help Enable driver for Ambiq SPI. + +config MSPI_AMBIQ + bool "AMBIQ MSPI driver" + default y + depends on DT_HAS_AMBIQ_MSPI_ENABLED + select AMBIQ_HAL + select AMBIQ_HAL_USE_MSPI + help + Enable driver for Ambiq MSPI. diff --git a/drivers/spi/Kconfig.ifx_cat1 b/drivers/spi/Kconfig.ifx_cat1 new file mode 100644 index 00000000000..ab55fb6d67b --- /dev/null +++ b/drivers/spi/Kconfig.ifx_cat1 @@ -0,0 +1,12 @@ +# Infineon CAT1 SPI configuration options + +# Copyright (c) 2022 Cypress Semiconductor Corporation. +# SPDX-License-Identifier: Apache-2.0 + +config SPI_INFINEON_CAT1 + bool "Infineon CAT1 SPI driver" + default y + depends on DT_HAS_INFINEON_CAT1_SPI_ENABLED + select USE_INFINEON_SPI + help + This option enables the SPI driver for Infineon CAT1 family. diff --git a/drivers/spi/Kconfig.nrfx b/drivers/spi/Kconfig.nrfx index 5b642a32b68..c185efa9f8f 100644 --- a/drivers/spi/Kconfig.nrfx +++ b/drivers/spi/Kconfig.nrfx @@ -6,6 +6,7 @@ menuconfig SPI_NRFX default y depends on SOC_FAMILY_NRF depends on MULTITHREADING + select PINCTRL help Enable support for nrfx SPI drivers for nRF MCU series. @@ -26,6 +27,21 @@ config SPI_NRFX_SPIM select NRFX_SPIM2 if HAS_HW_NRF_SPIM2 select NRFX_SPIM3 if HAS_HW_NRF_SPIM3 select NRFX_SPIM4 if HAS_HW_NRF_SPIM4 + select NRFX_SPIM00 if HAS_HW_NRF_SPIM00 + select NRFX_SPIM20 if HAS_HW_NRF_SPIM20 + select NRFX_SPIM21 if HAS_HW_NRF_SPIM21 + select NRFX_SPIM22 if HAS_HW_NRF_SPIM22 + select NRFX_SPIM30 if HAS_HW_NRF_SPIM30 + select NRFX_SPIM120 if HAS_HW_NRF_SPIM120 + select NRFX_SPIM121 if HAS_HW_NRF_SPIM121 + select NRFX_SPIM130 if HAS_HW_NRF_SPIM130 + select NRFX_SPIM131 if HAS_HW_NRF_SPIM131 + select NRFX_SPIM132 if HAS_HW_NRF_SPIM132 + select NRFX_SPIM133 if HAS_HW_NRF_SPIM133 + select NRFX_SPIM134 if HAS_HW_NRF_SPIM134 + select NRFX_SPIM135 if HAS_HW_NRF_SPIM135 + select NRFX_SPIM136 if HAS_HW_NRF_SPIM136 + select NRFX_SPIM137 if HAS_HW_NRF_SPIM137 config SPI_NRFX_SPIS def_bool y diff --git a/drivers/spi/Kconfig.nxp_s32 b/drivers/spi/Kconfig.nxp_s32 index 6183c49a4ae..b1e431877c1 100644 --- a/drivers/spi/Kconfig.nxp_s32 +++ b/drivers/spi/Kconfig.nxp_s32 @@ -5,7 +5,7 @@ config NXP_S32_SPI bool "NXP S32 SPI driver" default y depends on DT_HAS_NXP_S32_SPI_ENABLED - select NOCACHE_MEMORY + select NOCACHE_MEMORY if ARCH_HAS_NOCACHE_MEMORY_SUPPORT help Enable support for NXP S32 SPI driver. diff --git a/drivers/spi/Kconfig.sedi b/drivers/spi/Kconfig.sedi new file mode 100644 index 00000000000..a9f9ca6c90a --- /dev/null +++ b/drivers/spi/Kconfig.sedi @@ -0,0 +1,14 @@ +# +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +config SPI_SEDI + bool "Intel SEDI SPI driver" + default y + depends on DT_HAS_INTEL_SEDI_SPI_ENABLED + help + This option enables the Intel SEDI SPI driver. + This driver is simply a shim driver built upon the SEDI + bare metal SPI driver in the hal-intel module diff --git a/drivers/spi/Kconfig.stm32 b/drivers/spi/Kconfig.stm32 index 0096d800df2..6a53f30cbc4 100644 --- a/drivers/spi/Kconfig.stm32 +++ b/drivers/spi/Kconfig.stm32 @@ -21,6 +21,7 @@ config SPI_STM32_INTERRUPT config SPI_STM32_DMA bool "STM32 MCU SPI DMA Support" select DMA + select CACHE_MANAGEMENT if CPU_HAS_DCACHE help Enable the SPI DMA mode for SPI instances that enable dma channels in their device tree node. @@ -31,5 +32,22 @@ config SPI_STM32_USE_HW_SS help Use Slave Select pin instead of software Slave Select. +config SPI_STM32F7_ERRATA_BUSY + bool + default y + depends on SOC_STM32F745XX || SOC_STM32F746XX || \ + SOC_STM32F750XX || SOC_STM32F756XX + help + Handles erratum "BSY bit may stay high at the end of a data + transfer in Slave mode". + Seen in Errata Sheet 0290 §2.11.2 + +if SPI_STM32F7_ERRATA_BUSY + +config SPI_STM32_BUSY_FLAG_TIMEOUT + int "timeout in us for the STM32 busy flag workaround" + default 10000 + +endif # SPI_STM32F7_ERRATA_BUSY endif # SPI_STM32 diff --git a/drivers/spi/mspi_ambiq.c b/drivers/spi/mspi_ambiq.c new file mode 100644 index 00000000000..03ad8b2c0ac --- /dev/null +++ b/drivers/spi/mspi_ambiq.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ambiq_mspi + +#include +LOG_MODULE_REGISTER(mspi_ambiq); + +#include +#include +#include + +#include "spi_context.h" +#include + +#define SPI_WORD_SIZE 8 +#define MSPI_MAX_FREQ 96000000 +#define MSPI_TIMEOUT_US 1000000 +#define PWRCTRL_MAX_WAIT_US 5 +#define MSPI_BUSY BIT(2) + +typedef int (*ambiq_mspi_pwr_func_t)(void); + +struct mspi_ambiq_config { + uint32_t base; + int size; + uint32_t clock_freq; + const struct pinctrl_dev_config *pcfg; + ambiq_mspi_pwr_func_t pwr_func; +}; + +struct mspi_ambiq_data { + struct spi_context ctx; + void *mspiHandle; + am_hal_mspi_dev_config_t mspicfg; +}; + +static int mspi_set_freq(uint32_t freq) +{ + uint32_t d = MSPI_MAX_FREQ / freq; + + switch (d) { + case AM_HAL_MSPI_CLK_96MHZ: + case AM_HAL_MSPI_CLK_48MHZ: + case AM_HAL_MSPI_CLK_32MHZ: + case AM_HAL_MSPI_CLK_24MHZ: + case AM_HAL_MSPI_CLK_16MHZ: + case AM_HAL_MSPI_CLK_12MHZ: + case AM_HAL_MSPI_CLK_8MHZ: + case AM_HAL_MSPI_CLK_6MHZ: + case AM_HAL_MSPI_CLK_4MHZ: + case AM_HAL_MSPI_CLK_3MHZ: + break; + default: + LOG_ERR("Frequency not supported!"); + d = AM_HAL_MSPI_CLK_INVALID; + break; + } + + return d; +} + +static int mspi_config(const struct device *dev, const struct spi_config *config) +{ + struct mspi_ambiq_data *data = dev->data; + int ret; + am_hal_mspi_dev_config_t mspicfg = {0}; + + if (config->operation & SPI_HALF_DUPLEX) { + LOG_ERR("Half-duplex not supported"); + return -ENOTSUP; + } + + if (SPI_WORD_SIZE_GET(config->operation) != 8) { + LOG_ERR("Word size must be %d", SPI_WORD_SIZE); + return -ENOTSUP; + } + + if ((config->operation & SPI_LINES_MASK) != SPI_LINES_SINGLE) { + LOG_ERR("Only single mode is currently supported"); + return -ENOTSUP; + } + + if (config->operation & SPI_LOCK_ON) { + LOG_ERR("Lock On not supported"); + return -ENOTSUP; + } + + if (config->operation & SPI_TRANSFER_LSB) { + LOG_ERR("LSB first not supported"); + return -ENOTSUP; + } + + if (config->operation & (SPI_MODE_CPOL | SPI_MODE_CPHA)) { + if (config->operation & (SPI_MODE_CPOL && SPI_MODE_CPHA)) { + mspicfg.eSpiMode = AM_HAL_MSPI_SPI_MODE_3; + } else if (config->operation & SPI_MODE_CPOL) { + mspicfg.eSpiMode = AM_HAL_MSPI_SPI_MODE_2; + } else if (config->operation & SPI_MODE_CPHA) { + mspicfg.eSpiMode = AM_HAL_MSPI_SPI_MODE_1; + } else { + mspicfg.eSpiMode = AM_HAL_MSPI_SPI_MODE_0; + } + } + + mspicfg.eClockFreq = mspi_set_freq(config->frequency); + if (mspicfg.eClockFreq == AM_HAL_MSPI_CLK_INVALID) { + return -ENOTSUP; + } + + mspicfg.eDeviceConfig = AM_HAL_MSPI_FLASH_SERIAL_CE0; + + ret = am_hal_mspi_disable(data->mspiHandle); + if (ret) { + return ret; + } + + ret = am_hal_mspi_device_configure(data->mspiHandle, &mspicfg); + if (ret) { + return ret; + } + + ret = am_hal_mspi_enable(data->mspiHandle); + + + return ret; +} + +static int mspi_ambiq_xfer(const struct device *dev, const struct spi_config *config) +{ + struct mspi_ambiq_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + int ret; + + am_hal_mspi_pio_transfer_t trans = {0}; + + trans.bSendAddr = true; + trans.bSendInstr = true; + trans.ui16DeviceInstr = *ctx->tx_buf; + spi_context_update_tx(ctx, 1, 1); + trans.ui32DeviceAddr = *ctx->tx_buf; + + if (ctx->rx_buf != NULL) { + spi_context_update_rx(ctx, 1, ctx->rx_len); + trans.eDirection = AM_HAL_MSPI_RX; + trans.pui32Buffer = (uint32_t *)ctx->rx_buf; + trans.ui32NumBytes = ctx->rx_len; + + } else if (ctx->tx_buf != NULL) { + spi_context_update_tx(ctx, 1, 1); + trans.eDirection = AM_HAL_MSPI_TX; + trans.pui32Buffer = (uint32_t *)ctx->tx_buf; + trans.ui32NumBytes = ctx->tx_len; + } + + ret = am_hal_mspi_blocking_transfer(data->mspiHandle, &trans, MSPI_TIMEOUT_US); + + spi_context_complete(ctx, dev, 0); + + return ret; +} + +static int mspi_ambiq_transceive(const struct device *dev, const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs) +{ + struct mspi_ambiq_data *data = dev->data; + + int ret = mspi_config(dev, config); + + if (ret) { + return ret; + } + + if (!tx_bufs && !rx_bufs) { + return 0; + } + + spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, 1); + + ret = mspi_ambiq_xfer(dev, config); + + return ret; +} + +static int mspi_ambiq_release(const struct device *dev, const struct spi_config *config) +{ + const struct mspi_ambiq_config *cfg = dev->config; + + if (sys_read32(cfg->base) & MSPI_BUSY) { + return -EBUSY; + } + + return 0; +} + +static struct spi_driver_api mspi_ambiq_driver_api = { + .transceive = mspi_ambiq_transceive, + .release = mspi_ambiq_release, +}; + +static int mspi_ambiq_init(const struct device *dev) +{ + struct mspi_ambiq_data *data = dev->data; + const struct mspi_ambiq_config *cfg = dev->config; + am_hal_mspi_config_t mspiCfg = {0}; + + mspiCfg.pTCB = NULL; + + int ret = am_hal_mspi_initialize((cfg->base - REG_MSPI_BASEADDR) / (cfg->size * 4), + &data->mspiHandle); + if (ret) { + return ret; + } + + ret = cfg->pwr_func(); + + ret = am_hal_mspi_configure(data->mspiHandle, &mspiCfg); + if (ret) { + return ret; + } + + ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); + + return ret; +} + +#define AMBIQ_MSPI_DEFINE(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + static int pwr_on_ambiq_mspi_##n(void) \ + { \ + uint32_t addr = DT_REG_ADDR(DT_INST_PHANDLE(n, ambiq_pwrcfg)) + \ + DT_INST_PHA(n, ambiq_pwrcfg, offset); \ + sys_write32((sys_read32(addr) | DT_INST_PHA(n, ambiq_pwrcfg, mask)), addr); \ + k_busy_wait(PWRCTRL_MAX_WAIT_US); \ + return 0; \ + } \ + static struct mspi_ambiq_data mspi_ambiq_data##n = { \ + SPI_CONTEXT_INIT_SYNC(mspi_ambiq_data##n, ctx)}; \ + static const struct mspi_ambiq_config mspi_ambiq_config##n = { \ + .base = DT_INST_REG_ADDR(n), \ + .size = DT_INST_REG_SIZE(n), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .pwr_func = pwr_on_ambiq_mspi_##n, \ + }; \ + DEVICE_DT_INST_DEFINE(n, mspi_ambiq_init, NULL, &mspi_ambiq_data##n, \ + &mspi_ambiq_config##n, POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, \ + &mspi_ambiq_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(AMBIQ_MSPI_DEFINE) diff --git a/drivers/spi/spi_ambiq.c b/drivers/spi/spi_ambiq.c index facfc09b035..16614798e32 100644 --- a/drivers/spi/spi_ambiq.c +++ b/drivers/spi/spi_ambiq.c @@ -46,11 +46,17 @@ static int spi_config(const struct device *dev, const struct spi_config *config) { struct spi_ambiq_data *data = dev->data; const struct spi_ambiq_config *cfg = dev->config; + struct spi_context *ctx = &(data->ctx); data->iom_cfg.eInterfaceMode = AM_HAL_IOM_SPI_MODE; int ret = 0; + if (spi_context_configured(ctx, config)) { + /* Already configured. No need to do it again. */ + return 0; + } + if (config->operation & SPI_HALF_DUPLEX) { LOG_ERR("Half-duplex not supported"); return -ENOTSUP; @@ -76,12 +82,14 @@ static int spi_config(const struct device *dev, const struct spi_config *config) return -ENOTSUP; } - if (config->operation & (SPI_MODE_CPOL | SPI_MODE_CPHA)) { - if (config->operation & (SPI_MODE_CPOL && SPI_MODE_CPHA)) { + if (config->operation & SPI_MODE_CPOL) { + if (config->operation & SPI_MODE_CPHA) { data->iom_cfg.eSpiMode = AM_HAL_IOM_SPI_MODE_3; - } else if (config->operation & SPI_MODE_CPOL) { + } else { data->iom_cfg.eSpiMode = AM_HAL_IOM_SPI_MODE_2; - } else if (config->operation & SPI_MODE_CPHA) { + } + } else { + if (config->operation & SPI_MODE_CPHA) { data->iom_cfg.eSpiMode = AM_HAL_IOM_SPI_MODE_1; } else { data->iom_cfg.eSpiMode = AM_HAL_IOM_SPI_MODE_0; @@ -103,6 +111,7 @@ static int spi_config(const struct device *dev, const struct spi_config *config) } data->iom_cfg.ui32ClockFreq = cfg->clock_freq; + ctx->config = config; /* Disable IOM instance as it cannot be configured when enabled*/ ret = am_hal_iom_disable(data->IOMHandle); @@ -121,33 +130,51 @@ static int spi_ambiq_xfer(const struct device *dev, const struct spi_config *con int ret = 0; am_hal_iom_transfer_t trans = {0}; - uint8_t *buf3; - - trans.eDirection = AM_HAL_IOM_FULLDUPLEX; - uint16_t cmd = *ctx->tx_buf; - - trans.ui32InstrLen = ctx->tx_len; - spi_context_update_tx(ctx, 1, 1); - cmd = __bswap_16(cmd | *ctx->tx_buf << 8); - trans.ui64Instr = cmd; + if (ctx->tx_len) { + trans.ui64Instr = *ctx->tx_buf; + trans.ui32InstrLen = 1; + spi_context_update_tx(ctx, 1, 1); - if (ctx->rx_buf != NULL) { - trans.pui32TxBuffer = (uint32_t *)ctx->tx_buf; - spi_context_update_rx(ctx, 1, ctx->rx_len); - buf3 = (uint8_t *)malloc(sizeof(uint8_t) * ctx->rx_len); + if (ctx->rx_buf != NULL) { + if (ctx->tx_len > 0) { + /* The instruction length can only be 0~5. */ + if (ctx->tx_len > 4) { + spi_context_complete(ctx, dev, 0); + return -ENOTSUP; + } + + /* Put the remaining TX data in instruction. */ + trans.ui32InstrLen += ctx->tx_len; + for (int i = 0; i < trans.ui32InstrLen - 1; i++) { + trans.ui64Instr = (trans.ui64Instr << 8) | (*ctx->tx_buf); + spi_context_update_tx(ctx, 1, 1); + } + } + + /* Set RX direction and hold CS to continue to receive data. */ + trans.eDirection = AM_HAL_IOM_RX; + trans.bContinue = true; + trans.pui32RxBuffer = (uint32_t *)ctx->rx_buf; + trans.ui32NumBytes = ctx->rx_len; + ret = am_hal_iom_blocking_transfer(data->IOMHandle, &trans); + } else if (ctx->tx_buf != NULL) { + /* Set TX direction to send data and release CS after transmission. */ + trans.eDirection = AM_HAL_IOM_TX; + trans.bContinue = false; + trans.ui32NumBytes = ctx->tx_len; + trans.pui32TxBuffer = (uint32_t *)ctx->tx_buf; + ret = am_hal_iom_blocking_transfer(data->IOMHandle, &trans); + } + } else { + /* Set RX direction to receive data and release CS after transmission. */ + trans.ui64Instr = 0; + trans.ui32InstrLen = 0; + trans.eDirection = AM_HAL_IOM_RX; + trans.bContinue = false; + trans.pui32RxBuffer = (uint32_t *)ctx->rx_buf; trans.ui32NumBytes = ctx->rx_len; - trans.pui32RxBuffer = (uint32_t *)&buf3; - ret = am_hal_iom_spi_blocking_fullduplex(data->IOMHandle, &trans); - - memcpy(ctx->rx_buf, &buf3, (ctx->rx_len * sizeof(uint8_t))); - - } else if (ctx->tx_buf != NULL) { - spi_context_update_tx(ctx, 1, 1); - trans.ui32NumBytes = ctx->tx_len; - trans.pui32TxBuffer = (uint32_t *)ctx->tx_buf; - trans.pui32RxBuffer = (uint32_t *)ctx->tx_buf; - ret = am_hal_iom_spi_blocking_fullduplex(data->IOMHandle, &trans); + ret = am_hal_iom_blocking_transfer(data->IOMHandle, &trans); } spi_context_complete(ctx, dev, 0); diff --git a/drivers/spi/spi_handlers.c b/drivers/spi/spi_handlers.c index 7793d6b8a3a..68b362b5ed2 100644 --- a/drivers/spi/spi_handlers.c +++ b/drivers/spi/spi_handlers.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include /* This assumes that bufs and buf_copy are copies from the values passed @@ -23,7 +23,7 @@ static struct spi_buf_set *copy_and_check(struct spi_buf_set *bufs, } /* Validate the array of struct spi_buf instances */ - Z_OOPS(Z_SYSCALL_MEMORY_ARRAY_READ(bufs->buffers, + K_OOPS(K_SYSCALL_MEMORY_ARRAY_READ(bufs->buffers, bufs->count, sizeof(struct spi_buf))); @@ -40,7 +40,7 @@ static struct spi_buf_set *copy_and_check(struct spi_buf_set *bufs, */ const struct spi_buf *buf = &bufs->buffers[i]; - Z_OOPS(Z_SYSCALL_MEMORY(buf->buf, buf->len, writable)); + K_OOPS(K_SYSCALL_MEMORY(buf->buf, buf->len, writable)); } return bufs; @@ -76,17 +76,17 @@ static inline int z_vrfy_spi_transceive(const struct device *dev, struct spi_buf_set rx_bufs_copy; struct spi_config config_copy; - Z_OOPS(Z_SYSCALL_MEMORY_READ(config, sizeof(*config))); - Z_OOPS(Z_SYSCALL_DRIVER_SPI(dev, transceive)); + K_OOPS(K_SYSCALL_MEMORY_READ(config, sizeof(*config))); + K_OOPS(K_SYSCALL_DRIVER_SPI(dev, transceive)); if (tx_bufs) { const struct spi_buf_set *tx = (const struct spi_buf_set *)tx_bufs; - Z_OOPS(Z_SYSCALL_MEMORY_READ(tx_bufs, + K_OOPS(K_SYSCALL_MEMORY_READ(tx_bufs, sizeof(struct spi_buf_set))); memcpy(&tx_bufs_copy, tx, sizeof(tx_bufs_copy)); - Z_OOPS(Z_SYSCALL_VERIFY(tx_bufs_copy.count < 32)); + K_OOPS(K_SYSCALL_VERIFY(tx_bufs_copy.count < 32)); } else { memset(&tx_bufs_copy, 0, sizeof(tx_bufs_copy)); } @@ -95,17 +95,17 @@ static inline int z_vrfy_spi_transceive(const struct device *dev, const struct spi_buf_set *rx = (const struct spi_buf_set *)rx_bufs; - Z_OOPS(Z_SYSCALL_MEMORY_READ(rx_bufs, + K_OOPS(K_SYSCALL_MEMORY_READ(rx_bufs, sizeof(struct spi_buf_set))); memcpy(&rx_bufs_copy, rx, sizeof(rx_bufs_copy)); - Z_OOPS(Z_SYSCALL_VERIFY(rx_bufs_copy.count < 32)); + K_OOPS(K_SYSCALL_VERIFY(rx_bufs_copy.count < 32)); } else { memset(&rx_bufs_copy, 0, sizeof(rx_bufs_copy)); } memcpy(&config_copy, config, sizeof(*config)); if (spi_cs_is_gpio(&config_copy)) { - Z_OOPS(Z_SYSCALL_OBJ(config_copy.cs.gpio.port, + K_OOPS(K_SYSCALL_OBJ(config_copy.cs.gpio.port, K_OBJ_DRIVER_GPIO)); } @@ -119,8 +119,8 @@ static inline int z_vrfy_spi_transceive(const struct device *dev, static inline int z_vrfy_spi_release(const struct device *dev, const struct spi_config *config) { - Z_OOPS(Z_SYSCALL_MEMORY_READ(config, sizeof(*config))); - Z_OOPS(Z_SYSCALL_DRIVER_SPI(dev, release)); + K_OOPS(K_SYSCALL_MEMORY_READ(config, sizeof(*config))); + K_OOPS(K_SYSCALL_DRIVER_SPI(dev, release)); return z_impl_spi_release((const struct device *)dev, config); } #include diff --git a/drivers/spi/spi_ifx_cat1.c b/drivers/spi/spi_ifx_cat1.c new file mode 100644 index 00000000000..ceafe8e6635 --- /dev/null +++ b/drivers/spi/spi_ifx_cat1.c @@ -0,0 +1,360 @@ +/* + * Copyright 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT infineon_cat1_spi + +#define LOG_LEVEL CONFIG_SPI_LOG_LEVEL +#include +LOG_MODULE_REGISTER(cat1_spi); + +#include "spi_context.h" + +#include +#include +#include + +#include +#include + +#define IFX_CAT1_SPI_LOCK_TMOUT_MS (30 * 1000) +#define IFX_CAT1_SPI_DEFAULT_OVERSAMPLE (4) +#define IFX_CAT1_SPI_MIN_DATA_WIDTH (8) +#define IFX_CAT1_SPI_MAX_DATA_WIDTH (32) + +/* Device config structure */ +struct ifx_cat1_spi_config { + CySCB_Type *reg_addr; + const struct pinctrl_dev_config *pcfg; + cy_stc_scb_spi_config_t scb_spi_config; + uint8_t irq_priority; +}; + +/* Data structure */ +struct ifx_cat1_spi_data { + struct spi_context ctx; + cyhal_spi_t obj; /* SPI CYHAL object */ + cyhal_resource_inst_t hw_resource; + uint8_t dfs_value; + size_t chunk_len; +}; + +static int32_t get_hw_block_num(CySCB_Type *reg_addr) +{ + uint32_t i; + + for (i = 0u; i < _SCB_ARRAY_SIZE; i++) { + if (_CYHAL_SCB_BASE_ADDRESSES[i] == reg_addr) { + return i; + } + } + + return -ENOMEM; +} + +static uint8_t get_dfs_value(struct spi_context *ctx) +{ + switch (SPI_WORD_SIZE_GET(ctx->config->operation)) { + case 8: + return 1; + case 16: + return 2; + case 32: + return 4; + default: + return 1; + } +} + +static void transfer_chunk(const struct device *dev) +{ + struct ifx_cat1_spi_data *const data = dev->data; + struct spi_context *ctx = &data->ctx; + int ret = 0; + size_t chunk_len = spi_context_max_continuous_chunk(ctx); + + if (chunk_len == 0) { + goto exit; + } + + data->chunk_len = chunk_len; + + cy_rslt_t result = cyhal_spi_transfer_async( + &data->obj, ctx->tx_buf, spi_context_tx_buf_on(ctx) ? chunk_len : 0, ctx->rx_buf, + spi_context_rx_buf_on(ctx) ? chunk_len : 0); + if (result == CY_RSLT_SUCCESS) { + return; + } + + ret = -EIO; + +exit: + spi_context_cs_control(ctx, false); + spi_context_complete(ctx, dev, ret); +} + +static void spi_interrupt_callback(void *arg, cyhal_spi_event_t event) +{ + const struct device *dev = (const struct device *)arg; + struct ifx_cat1_spi_data *const data = dev->data; + struct spi_context *ctx = &data->ctx; + + if (event & CYHAL_SPI_IRQ_ERROR) { +#if defined(CONFIG_SPI_ASYNC) + cyhal_spi_abort_async(&data->obj); +#endif + spi_context_cs_control(ctx, false); + spi_context_complete(ctx, dev, -EIO); + } + + if (event & CYHAL_SPI_IRQ_DONE) { + spi_context_update_tx(ctx, data->dfs_value, data->chunk_len); + spi_context_update_rx(ctx, data->dfs_value, data->chunk_len); + + transfer_chunk(dev); + } +} + +int spi_config(const struct device *dev, const struct spi_config *spi_cfg) +{ + cy_rslt_t result; + struct ifx_cat1_spi_data *const data = dev->data; + const struct ifx_cat1_spi_config *const config = dev->config; + cy_stc_scb_spi_config_t scb_spi_config = config->scb_spi_config; + struct spi_context *ctx = &data->ctx; + bool spi_mode_cpol = false; + bool spi_mode_cpha = false; + + /* check if configuration was changed from previous run, if so skip setup again */ + if (spi_context_configured(ctx, spi_cfg)) { + /* Already configured. No need to do it again. */ + return 0; + } + + if (SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_LOOP) { + return -ENOTSUP; + } + + if (SPI_WORD_SIZE_GET(spi_cfg->operation) > IFX_CAT1_SPI_MAX_DATA_WIDTH) { + LOG_ERR("Word size %d is greater than %d", SPI_WORD_SIZE_GET(spi_cfg->operation), + IFX_CAT1_SPI_MAX_DATA_WIDTH); + return -EINVAL; + } + + if (SPI_WORD_SIZE_GET(spi_cfg->operation) < IFX_CAT1_SPI_MIN_DATA_WIDTH) { + LOG_ERR("Word size %d is less than %d", SPI_WORD_SIZE_GET(spi_cfg->operation), + IFX_CAT1_SPI_MIN_DATA_WIDTH); + return -EINVAL; + } + + if (SPI_OP_MODE_GET(spi_cfg->operation) == SPI_OP_MODE_SLAVE) { + scb_spi_config.spiMode = CY_SCB_SPI_SLAVE; + scb_spi_config.oversample = 0; + scb_spi_config.enableMisoLateSample = false; + } else { + scb_spi_config.spiMode = CY_SCB_SPI_MASTER; + } + + if (SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPOL) { + spi_mode_cpol = true; + } + + if (SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPHA) { + spi_mode_cpha = true; + } + + if (SPI_WORD_SIZE_GET(spi_cfg->operation)) { + scb_spi_config.txDataWidth = SPI_WORD_SIZE_GET(spi_cfg->operation); + scb_spi_config.rxDataWidth = SPI_WORD_SIZE_GET(spi_cfg->operation); + } + + if (spi_mode_cpha) { + scb_spi_config.sclkMode = + spi_mode_cpol ? CY_SCB_SPI_CPHA1_CPOL1 : CY_SCB_SPI_CPHA1_CPOL0; + } else { + scb_spi_config.sclkMode = + spi_mode_cpol ? CY_SCB_SPI_CPHA0_CPOL1 : CY_SCB_SPI_CPHA0_CPOL0; + } + + scb_spi_config.enableMsbFirst = (spi_cfg->operation & SPI_TRANSFER_LSB) ? false : true; + + /* Force free resource */ + if (data->obj.base != NULL) { + cyhal_spi_free(&data->obj); + } + + /* Initialize the SPI peripheral */ + cyhal_spi_configurator_t spi_init_cfg = {.resource = &data->hw_resource, + .config = &scb_spi_config, + .gpios = {NC, {NC, NC, NC, NC}, NC, NC}}; + + result = cyhal_spi_init_cfg(&data->obj, &spi_init_cfg); + if (result != CY_RSLT_SUCCESS) { + return -ENOTSUP; + } + + /* Assigns a programmable divider to a selected IP block */ + en_clk_dst_t clk_idx = _cyhal_scb_get_clock_index(spi_init_cfg.resource->block_num); + + result = _cyhal_utils_peri_pclk_assign_divider(clk_idx, &data->obj.clock); + if (result != CY_RSLT_SUCCESS) { + return -ENOTSUP; + } + + /* Configure Slave select polarity */ + if (SPI_OP_MODE_GET(spi_cfg->operation) == SPI_OP_MODE_SLAVE) { + Cy_SCB_SPI_SetActiveSlaveSelectPolarity(data->obj.base, CY_SCB_SPI_SLAVE_SELECT0, + scb_spi_config.ssPolarity); + } + + /* Set the data rate */ + result = cyhal_spi_set_frequency(&data->obj, spi_cfg->frequency); + if (result != CY_RSLT_SUCCESS) { + return -EIO; + } + + /* Write 0 when NULL buffer is provided for Tx/Rx */ + data->obj.write_fill = 0; + + /* Register common SPI callback */ + cyhal_spi_register_callback(&data->obj, spi_interrupt_callback, (void *)dev); + cyhal_spi_enable_event(&data->obj, CYHAL_SPI_IRQ_DONE, config->irq_priority, true); + + /* Store spi config in context */ + ctx->config = spi_cfg; + + data->dfs_value = get_dfs_value(ctx); + + return 0; +} + +static int transceive(const struct device *dev, const struct spi_config *spi_cfg, + const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs, + bool asynchronous, spi_callback_t cb, void *userdata) +{ + int result; + struct ifx_cat1_spi_data *const data = dev->data; + struct spi_context *ctx = &data->ctx; + + spi_context_lock(ctx, asynchronous, cb, userdata, spi_cfg); + + result = spi_config(dev, spi_cfg); + if (result) { + LOG_ERR("Error in SPI Configuration (result: 0x%x)", result); + return result; + } + + spi_context_buffers_setup(ctx, tx_bufs, rx_bufs, data->dfs_value); + + spi_context_cs_control(ctx, true); + + transfer_chunk(dev); + + result = spi_context_wait_for_completion(&data->ctx); + + spi_context_release(ctx, result); + + return result; +} + +static int ifx_cat1_spi_transceive_sync(const struct device *dev, const struct spi_config *spi_cfg, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs) +{ + return transceive(dev, spi_cfg, tx_bufs, rx_bufs, false, NULL, NULL); +} + +#if defined(CONFIG_SPI_ASYNC) +static int ifx_cat1_spi_transceive_async(const struct device *dev, const struct spi_config *spi_cfg, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, spi_callback_t cb, + void *userdata) +{ + return transceive(dev, spi_cfg, tx_bufs, rx_bufs, true, cb, userdata); +} +#endif + +static int ifx_cat1_spi_release(const struct device *dev, const struct spi_config *spi_cfg) +{ + struct ifx_cat1_spi_data *const data = dev->data; + + cyhal_spi_free(&data->obj); + + return 0; +} + +static const struct spi_driver_api ifx_cat1_spi_api = { + .transceive = ifx_cat1_spi_transceive_sync, +#if defined(CONFIG_SPI_ASYNC) + .transceive_async = ifx_cat1_spi_transceive_async, +#endif + .release = ifx_cat1_spi_release, +}; + +static int ifx_cat1_spi_init(const struct device *dev) +{ + struct ifx_cat1_spi_data *const data = dev->data; + const struct ifx_cat1_spi_config *const config = dev->config; + int ret; + + /* Dedicate SCB HW resource */ + data->hw_resource.type = CYHAL_RSC_SCB; + data->hw_resource.block_num = get_hw_block_num(config->reg_addr); + + /* Configure dt provided device signals when available */ + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + return ret; + } + + /* Configure slave select (master) */ + spi_context_cs_configure_all(&data->ctx); + + spi_context_unlock_unconditionally(&data->ctx); + + return 0; +} + +#define IFX_CAT1_SPI_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + static struct ifx_cat1_spi_data spi_cat1_data_##n = { \ + SPI_CONTEXT_INIT_LOCK(spi_cat1_data_##n, ctx), \ + SPI_CONTEXT_INIT_SYNC(spi_cat1_data_##n, ctx), \ + SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(n), ctx)}; \ + static struct ifx_cat1_spi_config spi_cat1_config_##n = { \ + .reg_addr = (CySCB_Type *)DT_INST_REG_ADDR(n), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .scb_spi_config = \ + {.spiMode = CY_SCB_SPI_MASTER, /* overwrite by cfg */ \ + .sclkMode = CY_SCB_SPI_CPHA0_CPOL0, /* overwrite by cfg */ \ + .rxDataWidth = 8, /* overwrite by cfg */ \ + .txDataWidth = 8, /* overwrite by cfg */ \ + .enableMsbFirst = true, /* overwrite by cfg */ \ + .subMode = DT_INST_PROP_OR(n, sub_mode, CY_SCB_SPI_MOTOROLA), \ + .oversample = \ + DT_INST_PROP_OR(n, oversample, IFX_CAT1_SPI_DEFAULT_OVERSAMPLE), \ + .enableFreeRunSclk = DT_INST_PROP_OR(n, enable_free_run_sclk, false), \ + .enableInputFilter = DT_INST_PROP_OR(n, enable_input_filter, false), \ + .enableMisoLateSample = \ + DT_INST_PROP_OR(n, enable_miso_late_sample, true), \ + .enableTransferSeperation = \ + DT_INST_PROP_OR(n, enable_transfer_seperation, false), \ + .enableWakeFromSleep = DT_INST_PROP_OR(n, enableWakeFromSleep, false), \ + .ssPolarity = DT_INST_PROP_OR(n, ss_polarity, CY_SCB_SPI_ACTIVE_LOW), \ + .rxFifoTriggerLevel = DT_INST_PROP_OR(n, rx_fifo_trigger_level, 0), \ + .rxFifoIntEnableMask = DT_INST_PROP_OR(n, rx_fifo_int_enable_mask, 0), \ + .txFifoTriggerLevel = DT_INST_PROP_OR(n, tx_fifo_trigger_level, 0), \ + .txFifoIntEnableMask = DT_INST_PROP_OR(n, tx_fifo_int_enable_mask, 0), \ + .masterSlaveIntEnableMask = \ + DT_INST_PROP_OR(n, master_slave_int_enable_mask, 0)}, \ + \ + .irq_priority = DT_INST_IRQ(n, priority), \ + }; \ + DEVICE_DT_INST_DEFINE(n, &ifx_cat1_spi_init, NULL, &spi_cat1_data_##n, \ + &spi_cat1_config_##n, POST_KERNEL, \ + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &ifx_cat1_spi_api); + +DT_INST_FOREACH_STATUS_OKAY(IFX_CAT1_SPI_INIT) diff --git a/drivers/spi/spi_ll_stm32.c b/drivers/spi/spi_ll_stm32.c index 948b7641eaf..0241dbde254 100644 --- a/drivers/spi/spi_ll_stm32.c +++ b/drivers/spi/spi_ll_stm32.c @@ -25,13 +25,32 @@ LOG_MODULE_REGISTER(spi_ll_stm32); #include #include #include +#include + +#ifdef CONFIG_SOC_SERIES_STM32H7X +#include +#endif #ifdef CONFIG_NOCACHE_MEMORY #include +#elif defined(CONFIG_CACHE_MANAGEMENT) +#include #endif /* CONFIG_NOCACHE_MEMORY */ #include "spi_ll_stm32.h" +/* + * Check defined(CONFIG_DCACHE) because some platforms disable it in the tests + * e.g. nucleo_f746zg + */ +#if defined(CONFIG_CPU_HAS_DCACHE) && \ + defined(CONFIG_DCACHE) && \ + !defined(CONFIG_NOCACHE_MEMORY) +#define SPI_STM32_MANUAL_CACHE_COHERENCY_REQUIRED 1 +#else +#define SPI_STM32_MANUAL_CACHE_COHERENCY_REQUIRED 0 +#endif /* defined(CONFIG_CPU_HAS_DCACHE) && !defined(CONFIG_NOCACHE_MEMORY) */ + #define WAIT_1US 1U /* @@ -55,40 +74,30 @@ LOG_MODULE_REGISTER(spi_ll_stm32); #endif /* CONFIG_SOC_SERIES_STM32MP1X */ #ifdef CONFIG_SPI_STM32_DMA +static uint32_t bits2bytes(uint32_t bits) +{ + return bits / 8; +} -#ifdef CONFIG_SOC_SERIES_STM32H7X - -#define IS_NOCACHE_MEM_REGION(node_id) \ - COND_CODE_1(DT_ENUM_HAS_VALUE(node_id, zephyr_memory_attr, RAM_NOCACHE), \ - (1), \ - (0)) - -#define GET_MEM_REGION(node_id) \ - { \ - .start = DT_REG_ADDR(node_id), \ - .end = (DT_REG_ADDR(node_id) + DT_REG_SIZE(node_id)) - 1, \ - }, - -#define GET_MEM_REGION_IF_NOCACHE(node_id) \ - COND_CODE_1(IS_NOCACHE_MEM_REGION(node_id), \ - ( \ - GET_MEM_REGION(node_id) \ - ), ()) - -struct mem_region { - uintptr_t start; - uintptr_t end; -}; +/* dummy value used for transferring NOP when tx buf is null + * and use as dummy sink for when rx buf is null. + */ +#ifdef CONFIG_NOCACHE_MEMORY +/* + * If a nocache area is available, place it there to avoid potential DMA + * cache-coherency problems. + */ +static __aligned(32) uint32_t dummy_rx_tx_buffer + __attribute__((__section__(".nocache"))); -static const struct mem_region nocache_mem_regions[] = { - DT_MEMORY_ATTR_FOREACH_NODE(GET_MEM_REGION_IF_NOCACHE) -}; -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#else /* CONFIG_NOCACHE_MEMORY */ -/* dummy value used for transferring NOP when tx buf is null - * and use as dummy sink for when rx buf is null +/* + * If nocache areas are not available, cache coherency might need to be kept + * manually. See SPI_STM32_MANUAL_CACHE_COHERENCY_REQUIRED. */ -uint32_t dummy_rx_tx_buffer; +static __aligned(32) uint32_t dummy_rx_tx_buffer; +#endif /* CONFIG_NOCACHE_MEMORY */ /* This function is executed in the interrupt context */ static void dma_callback(const struct device *dev, void *arg, @@ -137,8 +146,11 @@ static int spi_stm32_dma_tx_load(const struct device *dev, const uint8_t *buf, /* tx direction has memory as source and periph as dest. */ if (buf == NULL) { - dummy_rx_tx_buffer = 0; /* if tx buff is null, then sends NOP on the line. */ + dummy_rx_tx_buffer = 0; +#if SPI_STM32_MANUAL_CACHE_COHERENCY_REQUIRED + arch_dcache_flush_range((void *)&dummy_rx_tx_buffer, sizeof(uint32_t)); +#endif /* CONFIG_CPU_HAS_DCACHE && !defined(CONFIG_NOCACHE_MEMORY) */ blk_cfg->source_address = (uint32_t)&dummy_rx_tx_buffer; blk_cfg->source_addr_adj = DMA_ADDR_ADJ_NO_CHANGE; } else { @@ -770,16 +782,10 @@ static bool buf_in_nocache(uintptr_t buf, size_t len_bytes) } #endif /* CONFIG_NOCACHE_MEMORY */ - for (size_t i = 0; i < ARRAY_SIZE(nocache_mem_regions); i++) { - const struct mem_region *mem_reg = &nocache_mem_regions[i]; + buf_within_nocache = mem_attr_check_buf( + (void *)buf, len_bytes, DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE)) == 0; - buf_within_nocache = - (buf >= mem_reg->start) && ((buf + len_bytes - 1) <= mem_reg->end); - if (buf_within_nocache) { - return true; - } - } - return false; + return buf_within_nocache; } static bool is_dummy_buffer(const struct spi_buf *buf) @@ -896,9 +902,15 @@ static int transceive_dma(const struct device *dev, } #endif +#ifdef CONFIG_SPI_STM32F7_ERRATA_BUSY + WAIT_FOR(ll_func_spi_dma_busy(spi) != 0, + CONFIG_SPI_STM32_BUSY_FLAG_TIMEOUT, + k_yield()); +#else /* wait until spi is no more busy (spi TX fifo is really empty) */ while (ll_func_spi_dma_busy(spi) == 0) { } +#endif #if !DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) /* toggle the DMA transfer request */ @@ -906,8 +918,11 @@ static int transceive_dma(const struct device *dev, LL_SPI_DisableDMAReq_RX(spi); #endif /* ! st_stm32h7_spi */ - spi_context_update_tx(&data->ctx, 1, dma_len); - spi_context_update_rx(&data->ctx, 1, dma_len); + uint8_t frame_size_bytes = bits2bytes( + SPI_WORD_SIZE_GET(config->operation)); + + spi_context_update_tx(&data->ctx, frame_size_bytes, dma_len); + spi_context_update_rx(&data->ctx, frame_size_bytes, dma_len); } /* spi complete relies on SPI Status Reg which cannot be disabled */ @@ -1037,7 +1052,7 @@ static int spi_stm32_init(const struct device *dev) return -ENODEV; } - LOG_INF(" SPI with DMA transfer"); + LOG_DBG("SPI with DMA transfer"); #endif /* CONFIG_SPI_STM32_DMA */ diff --git a/drivers/spi/spi_mcux_lpspi.c b/drivers/spi/spi_mcux_lpspi.c index 2ddee4a2b09..9b230d1c53f 100644 --- a/drivers/spi/spi_mcux_lpspi.c +++ b/drivers/spi/spi_mcux_lpspi.c @@ -248,6 +248,8 @@ static int spi_mcux_configure(const struct device *dev, } #ifdef CONFIG_SPI_MCUX_LPSPI_DMA +static int spi_mcux_dma_rxtx_load(const struct device *dev, + size_t *dma_size); /* This function is executed in the interrupt context */ static void spi_mcux_dma_callback(const struct device *dev, void *arg, @@ -276,6 +278,26 @@ static void spi_mcux_dma_callback(const struct device *dev, void *arg, data->status_flags |= SPI_MCUX_LPSPI_DMA_ERROR_FLAG; } } +#if CONFIG_SPI_ASYNC + if (data->ctx.asynchronous && + ((data->status_flags & SPI_MCUX_LPSPI_DMA_DONE_FLAG) == + SPI_MCUX_LPSPI_DMA_DONE_FLAG)) { + /* Load dma blocks of equal length */ + size_t dma_size = MIN(data->ctx.tx_len, data->ctx.rx_len); + + if (dma_size == 0) { + dma_size = MAX(data->ctx.tx_len, data->ctx.rx_len); + } + + spi_context_update_tx(&data->ctx, 1, dma_size); + spi_context_update_rx(&data->ctx, 1, dma_size); + + if (data->ctx.tx_len == 0 && data->ctx.rx_len == 0) { + spi_context_complete(&data->ctx, spi_dev, 0); + } + return; + } +#endif spi_context_complete(&data->ctx, spi_dev, 0); } @@ -386,6 +408,45 @@ static int wait_dma_rx_tx_done(const struct device *dev) } } +static inline int spi_mcux_dma_rxtx_load(const struct device *dev, + size_t *dma_size) +{ + struct spi_mcux_data *lpspi_data = dev->data; + int ret = 0; + + /* Clear status flags */ + lpspi_data->status_flags = 0U; + /* Load dma blocks of equal length */ + *dma_size = MIN(lpspi_data->ctx.tx_len, lpspi_data->ctx.rx_len); + if (*dma_size == 0) { + *dma_size = MAX(lpspi_data->ctx.tx_len, lpspi_data->ctx.rx_len); + } + + ret = spi_mcux_dma_tx_load(dev, lpspi_data->ctx.tx_buf, + *dma_size); + if (ret != 0) { + return ret; + } + + ret = spi_mcux_dma_rx_load(dev, lpspi_data->ctx.rx_buf, + *dma_size); + if (ret != 0) { + return ret; + } + + /* Start DMA */ + ret = dma_start(lpspi_data->dma_tx.dma_dev, + lpspi_data->dma_tx.channel); + if (ret != 0) { + return ret; + } + + ret = dma_start(lpspi_data->dma_rx.dma_dev, + lpspi_data->dma_rx.channel); + return ret; + +} + static int transceive_dma(const struct device *dev, const struct spi_config *spi_cfg, const struct spi_buf_set *tx_bufs, @@ -400,79 +461,75 @@ static int transceive_dma(const struct device *dev, int ret; size_t dma_size; - spi_context_lock(&data->ctx, asynchronous, cb, userdata, spi_cfg); + if (!asynchronous) { + spi_context_lock(&data->ctx, asynchronous, cb, userdata, spi_cfg); + } ret = spi_mcux_configure(dev, spi_cfg); if (ret) { - goto out; + if (!asynchronous) { + spi_context_release(&data->ctx, ret); + } + return ret; } - spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, 1); - - spi_context_cs_control(&data->ctx, true); - /* DMA is fast enough watermarks are not required */ LPSPI_SetFifoWatermarks(base, 0U, 0U); - /* Send each spi buf via DMA, updating context as DMA completes */ - while (data->ctx.rx_len > 0 || data->ctx.tx_len > 0) { - /* Clear status flags */ - data->status_flags = 0U; - /* Load dma blocks of equal length */ - dma_size = MIN(data->ctx.tx_len, data->ctx.rx_len); - if (dma_size == 0) { - dma_size = MAX(data->ctx.tx_len, data->ctx.rx_len); - } - ret = spi_mcux_dma_tx_load(dev, data->ctx.tx_buf, dma_size); - if (ret != 0) { - goto out; + if (!asynchronous) { + spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, 1); + spi_context_cs_control(&data->ctx, true); + + /* Send each spi buf via DMA, updating context as DMA completes */ + while (data->ctx.rx_len > 0 || data->ctx.tx_len > 0) { + /* Load dma block */ + ret = spi_mcux_dma_rxtx_load(dev, &dma_size); + if (ret != 0) { + goto out; + } + /* Enable DMA Requests */ + LPSPI_EnableDMA(base, kLPSPI_TxDmaEnable | kLPSPI_RxDmaEnable); + + /* Wait for DMA to finish */ + ret = wait_dma_rx_tx_done(dev); + if (ret != 0) { + goto out; + } + while ((LPSPI_GetStatusFlags(base) & kLPSPI_ModuleBusyFlag)) { + /* wait until module is idle */ + } + + /* Disable DMA */ + LPSPI_DisableDMA(base, kLPSPI_TxDmaEnable | kLPSPI_RxDmaEnable); + + /* Update SPI contexts with amount of data we just sent */ + spi_context_update_tx(&data->ctx, 1, dma_size); + spi_context_update_rx(&data->ctx, 1, dma_size); } + spi_context_cs_control(&data->ctx, false); - ret = spi_mcux_dma_rx_load(dev, data->ctx.rx_buf, dma_size); - if (ret != 0) { - goto out; - } +out: + spi_context_release(&data->ctx, ret); + } +#if CONFIG_SPI_ASYNC + else { + data->ctx.asynchronous = asynchronous; + data->ctx.callback = cb; + data->ctx.callback_data = userdata; - /* Start DMA */ - ret = dma_start(data->dma_tx.dma_dev, data->dma_tx.channel); - if (ret != 0) { - goto out; - } - ret = dma_start(data->dma_rx.dma_dev, data->dma_rx.channel); + ret = spi_mcux_dma_rxtx_load(dev, &dma_size); if (ret != 0) { goto out; } /* Enable DMA Requests */ LPSPI_EnableDMA(base, kLPSPI_TxDmaEnable | kLPSPI_RxDmaEnable); - - /* Wait for DMA to finish */ - ret = wait_dma_rx_tx_done(dev); - if (ret != 0) { - goto out; - } - - while ((LPSPI_GetStatusFlags(base) & kLPSPI_ModuleBusyFlag)) { - /* wait until module is idle */ - } - - /* Disable DMA */ - LPSPI_DisableDMA(base, kLPSPI_TxDmaEnable | kLPSPI_RxDmaEnable); - - /* Update SPI contexts with amount of data we just sent */ - spi_context_update_tx(&data->ctx, 1, dma_size); - spi_context_update_rx(&data->ctx, 1, dma_size); } - - spi_context_cs_control(&data->ctx, false); - -out: - spi_context_release(&data->ctx, ret); +#endif return ret; } - -#else +#endif static int transceive(const struct device *dev, const struct spi_config *spi_cfg, @@ -505,7 +562,6 @@ static int transceive(const struct device *dev, return ret; } -#endif /*CONFIG_SPI_MCUX_LPSPI_DMA */ static int spi_mcux_transceive(const struct device *dev, const struct spi_config *spi_cfg, @@ -513,10 +569,14 @@ static int spi_mcux_transceive(const struct device *dev, const struct spi_buf_set *rx_bufs) { #ifdef CONFIG_SPI_MCUX_LPSPI_DMA - return transceive_dma(dev, spi_cfg, tx_bufs, rx_bufs, false, NULL, NULL); -#else - return transceive(dev, spi_cfg, tx_bufs, rx_bufs, false, NULL, NULL); + const struct spi_mcux_data *data = dev->data; + + if (data->dma_rx.dma_dev && data->dma_tx.dma_dev) { + return transceive_dma(dev, spi_cfg, tx_bufs, rx_bufs, false, NULL, NULL); + } #endif /* CONFIG_SPI_MCUX_LPSPI_DMA */ + + return transceive(dev, spi_cfg, tx_bufs, rx_bufs, false, NULL, NULL); } #ifdef CONFIG_SPI_ASYNC @@ -527,7 +587,17 @@ static int spi_mcux_transceive_async(const struct device *dev, spi_callback_t cb, void *userdata) { +#ifdef CONFIG_SPI_MCUX_LPSPI_DMA + struct spi_mcux_data *data = dev->data; + + if (data->dma_rx.dma_dev && data->dma_tx.dma_dev) { + spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, 1); + } + + return transceive_dma(dev, spi_cfg, tx_bufs, rx_bufs, true, cb, userdata); +#else return transceive(dev, spi_cfg, tx_bufs, rx_bufs, true, cb, userdata); +#endif /* CONFIG_SPI_MCUX_LPSPI_DMA */ } #endif /* CONFIG_SPI_ASYNC */ @@ -559,14 +629,16 @@ static int spi_mcux_init(const struct device *dev) data->dev = dev; #ifdef CONFIG_SPI_MCUX_LPSPI_DMA - if (!device_is_ready(data->dma_tx.dma_dev)) { - LOG_ERR("%s device is not ready", data->dma_tx.dma_dev->name); - return -ENODEV; - } + if (data->dma_tx.dma_dev && data->dma_rx.dma_dev) { + if (!device_is_ready(data->dma_tx.dma_dev)) { + LOG_ERR("%s device is not ready", data->dma_tx.dma_dev->name); + return -ENODEV; + } - if (!device_is_ready(data->dma_rx.dma_dev)) { - LOG_ERR("%s device is not ready", data->dma_rx.dma_dev->name); - return -ENODEV; + if (!device_is_ready(data->dma_rx.dma_dev)) { + LOG_ERR("%s device is not ready", data->dma_rx.dma_dev->name); + return -ENODEV; + } } #endif /* CONFIG_SPI_MCUX_LPSPI_DMA */ @@ -589,33 +661,39 @@ static const struct spi_driver_api spi_mcux_driver_api = { }; #ifdef CONFIG_SPI_MCUX_LPSPI_DMA -#define SPI_DMA_CHANNELS(n) \ - .dma_tx = { \ - .dma_dev = DEVICE_DT_GET(DT_INST_DMAS_CTLR_BY_NAME(n, tx)), \ - .channel = \ - DT_INST_DMAS_CELL_BY_NAME(n, tx, mux), \ - .dma_cfg = { \ - .channel_direction = MEMORY_TO_PERIPHERAL, \ - .dma_callback = spi_mcux_dma_callback, \ - .source_data_size = 1, \ - .dest_data_size = 1, \ - .block_count = 1, \ - .dma_slot = DT_INST_DMAS_CELL_BY_NAME(n, tx, source) \ - } \ - }, \ - .dma_rx = { \ - .dma_dev = DEVICE_DT_GET(DT_INST_DMAS_CTLR_BY_NAME(n, rx)), \ - .channel = \ - DT_INST_DMAS_CELL_BY_NAME(n, rx, mux), \ - .dma_cfg = { \ - .channel_direction = PERIPHERAL_TO_MEMORY, \ - .dma_callback = spi_mcux_dma_callback, \ - .source_data_size = 1, \ - .dest_data_size = 1, \ - .block_count = 1, \ - .dma_slot = DT_INST_DMAS_CELL_BY_NAME(n, rx, source) \ - } \ - } +#define SPI_DMA_CHANNELS(n) \ + IF_ENABLED(DT_INST_DMAS_HAS_NAME(n, tx), \ + ( \ + .dma_tx = { \ + .dma_dev = DEVICE_DT_GET(DT_INST_DMAS_CTLR_BY_NAME(n, tx)), \ + .channel = \ + DT_INST_DMAS_CELL_BY_NAME(n, tx, mux), \ + .dma_cfg = { \ + .channel_direction = MEMORY_TO_PERIPHERAL, \ + .dma_callback = spi_mcux_dma_callback, \ + .source_data_size = 1, \ + .dest_data_size = 1, \ + .block_count = 1, \ + .dma_slot = DT_INST_DMAS_CELL_BY_NAME(n, tx, source) \ + } \ + }, \ + )) \ + IF_ENABLED(DT_INST_DMAS_HAS_NAME(n, rx), \ + ( \ + .dma_rx = { \ + .dma_dev = DEVICE_DT_GET(DT_INST_DMAS_CTLR_BY_NAME(n, rx)), \ + .channel = \ + DT_INST_DMAS_CELL_BY_NAME(n, rx, mux), \ + .dma_cfg = { \ + .channel_direction = PERIPHERAL_TO_MEMORY, \ + .dma_callback = spi_mcux_dma_callback, \ + .source_data_size = 1, \ + .dest_data_size = 1, \ + .block_count = 1, \ + .dma_slot = DT_INST_DMAS_CELL_BY_NAME(n, rx, source) \ + } \ + } \ + )) #else #define SPI_DMA_CHANNELS(n) #endif /* CONFIG_SPI_MCUX_LPSPI_DMA */ diff --git a/drivers/spi/spi_nrfx_spim.c b/drivers/spi/spi_nrfx_spim.c index 256250b5d08..8b187f54c52 100644 --- a/drivers/spi/spi_nrfx_spim.c +++ b/drivers/spi/spi_nrfx_spim.c @@ -672,3 +672,63 @@ SPI_NRFX_SPIM_DEFINE(3); #ifdef CONFIG_HAS_HW_NRF_SPIM4 SPI_NRFX_SPIM_DEFINE(4); #endif + +#ifdef CONFIG_HAS_HW_NRF_SPIM00 +SPI_NRFX_SPIM_DEFINE(00); +#endif + +#ifdef CONFIG_HAS_HW_NRF_SPIM20 +SPI_NRFX_SPIM_DEFINE(20); +#endif + +#ifdef CONFIG_HAS_HW_NRF_SPIM21 +SPI_NRFX_SPIM_DEFINE(21); +#endif + +#ifdef CONFIG_HAS_HW_NRF_SPIM22 +SPI_NRFX_SPIM_DEFINE(22); +#endif + +#ifdef CONFIG_HAS_HW_NRF_SPIM30 +SPI_NRFX_SPIM_DEFINE(30); +#endif + +#ifdef CONFIG_HAS_HW_NRF_SPIM120 +SPI_NRFX_SPIM_DEFINE(120); +#endif + +#ifdef CONFIG_HAS_HW_NRF_SPIM121 +SPI_NRFX_SPIM_DEFINE(121); +#endif + +#ifdef CONFIG_HAS_HW_NRF_SPIM130 +SPI_NRFX_SPIM_DEFINE(130); +#endif + +#ifdef CONFIG_HAS_HW_NRF_SPIM131 +SPI_NRFX_SPIM_DEFINE(131); +#endif + +#ifdef CONFIG_HAS_HW_NRF_SPIM132 +SPI_NRFX_SPIM_DEFINE(132); +#endif + +#ifdef CONFIG_HAS_HW_NRF_SPIM133 +SPI_NRFX_SPIM_DEFINE(133); +#endif + +#ifdef CONFIG_HAS_HW_NRF_SPIM134 +SPI_NRFX_SPIM_DEFINE(134); +#endif + +#ifdef CONFIG_HAS_HW_NRF_SPIM135 +SPI_NRFX_SPIM_DEFINE(135); +#endif + +#ifdef CONFIG_HAS_HW_NRF_SPIM136 +SPI_NRFX_SPIM_DEFINE(136); +#endif + +#ifdef CONFIG_HAS_HW_NRF_SPIM137 +SPI_NRFX_SPIM_DEFINE(137); +#endif diff --git a/drivers/spi/spi_nxp_s32.c b/drivers/spi/spi_nxp_s32.c index 30dbe4d134a..ae238407967 100644 --- a/drivers/spi/spi_nxp_s32.c +++ b/drivers/spi/spi_nxp_s32.c @@ -4,6 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +#define DT_DRV_COMPAT nxp_s32_spi + +#include #include #include "spi_nxp_s32.h" @@ -57,7 +60,8 @@ static int spi_nxp_s32_transfer_next_packet(const struct device *dev) * Keep CS signal asserted until the last package, there is no other way * than directly intervening to internal state of low level driver */ - Spi_Ip_apxStateStructureArray[config->instance]->KeepCs = !spi_nxp_s32_last_packet(data); + Spi_Ip_apxStateStructureArray[config->spi_hw_cfg->Instance]->KeepCs = + !spi_nxp_s32_last_packet(data); status = Spi_Ip_AsyncTransmit(&data->transfer_cfg, (uint8_t *)data->ctx.tx_buf, data->ctx.rx_buf, data->transfer_len, data_cb); @@ -71,11 +75,11 @@ static int spi_nxp_s32_transfer_next_packet(const struct device *dev) return 0; #else - while (Spi_Ip_GetStatus(config->instance) == SPI_IP_BUSY) { - Spi_Ip_ManageBuffers(config->instance); + while (Spi_Ip_GetStatus(config->spi_hw_cfg->Instance) == SPI_IP_BUSY) { + Spi_Ip_ManageBuffers(config->spi_hw_cfg->Instance); } - if (Spi_Ip_GetStatus(config->instance) == SPI_IP_FAULT) { + if (Spi_Ip_GetStatus(config->spi_hw_cfg->Instance) == SPI_IP_FAULT) { return -EIO; } @@ -273,12 +277,20 @@ static int spi_nxp_s32_configure(const struct device *dev, uint8_t frame_size; struct spi_nxp_s32_baudrate_param best_baud = {0}; + uint32_t clock_rate; + int err; if (spi_context_configured(&data->ctx, spi_cfg)) { /* This configuration is already in use */ return 0; } + err = clock_control_get_rate(config->clock_dev, config->clock_subsys, &clock_rate); + if (err) { + LOG_ERR("Failed to get clock frequency"); + return err; + } + clk_phase = !!(SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPHA); clk_polarity = !!(SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPOL); @@ -340,7 +352,7 @@ static int spi_nxp_s32_configure(const struct device *dev, return -ENOTSUP; } - spi_nxp_s32_getbestfreq(config->clock_frequency, spi_cfg->frequency, &best_baud); + spi_nxp_s32_getbestfreq(clock_rate, spi_cfg->frequency, &best_baud); data->transfer_cfg.Ctar &= ~(SPI_CTAR_BR_MASK | SPI_CTAR_PBR_MASK); data->transfer_cfg.Ctar |= SPI_CTAR_BR(best_baud.scaler) | @@ -486,12 +498,29 @@ static int spi_nxp_s32_init(const struct device *dev) { const struct spi_nxp_s32_config *config = dev->config; struct spi_nxp_s32_data *data = dev->data; - + uint32_t clock_rate; uint8_t scaler, prescaler; uint32_t ctar = 0; int ret = 0; + if (!device_is_ready(config->clock_dev)) { + LOG_ERR("Clock control device not ready"); + return -ENODEV; + } + + ret = clock_control_on(config->clock_dev, config->clock_subsys); + if (ret) { + LOG_ERR("Failed to enable clock"); + return ret; + } + + ret = clock_control_get_rate(config->clock_dev, config->clock_subsys, &clock_rate); + if (ret) { + LOG_ERR("Failed to get clock frequency"); + return ret; + } + ret = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); if (ret < 0) { return ret; @@ -502,7 +531,7 @@ static int spi_nxp_s32_init(const struct device *dev) } #ifdef CONFIG_NXP_S32_SPI_INTERRUPT - if (Spi_Ip_UpdateTransferMode(config->instance, SPI_IP_INTERRUPT)) { + if (Spi_Ip_UpdateTransferMode(config->spi_hw_cfg->Instance, SPI_IP_INTERRUPT)) { return -EBUSY; } @@ -513,18 +542,15 @@ static int spi_nxp_s32_init(const struct device *dev) * Update the delay timings configuration that are * applied for all inner CS signals of SPI module. */ - spi_nxp_s32_getbestdelay(config->clock_frequency, - config->sck_cs_delay, &scaler, &prescaler); + spi_nxp_s32_getbestdelay(clock_rate, config->sck_cs_delay, &scaler, &prescaler); ctar |= SPI_CTAR_ASC(scaler) | SPI_CTAR_PASC(prescaler); - spi_nxp_s32_getbestdelay(config->clock_frequency, - config->cs_sck_delay, &scaler, &prescaler); + spi_nxp_s32_getbestdelay(clock_rate, config->cs_sck_delay, &scaler, &prescaler); ctar |= SPI_CTAR_CSSCK(scaler) | SPI_CTAR_PCSSCK(prescaler); - spi_nxp_s32_getbestdelay(config->clock_frequency, - config->cs_cs_delay, &scaler, &prescaler); + spi_nxp_s32_getbestdelay(clock_rate, config->cs_cs_delay, &scaler, &prescaler); ctar |= SPI_CTAR_DT(scaler) | SPI_CTAR_PDT(prescaler); @@ -543,6 +569,13 @@ static int spi_nxp_s32_init(const struct device *dev) #ifdef CONFIG_NXP_S32_SPI_INTERRUPT +void spi_nxp_s32_isr(const struct device *dev) +{ + const struct spi_nxp_s32_config *config = dev->config; + + Spi_Ip_IrqHandler(config->spi_hw_cfg->Instance); +} + static void spi_nxp_s32_transfer_callback(const struct device *dev, Spi_Ip_EventType event) { struct spi_nxp_s32_data *data = dev->data; @@ -578,12 +611,17 @@ static const struct spi_driver_api spi_nxp_s32_driver_api = { .release = spi_nxp_s32_release, }; -#define SPI_NXP_S32_NODE(n) DT_NODELABEL(spi##n) -#define SPI_NXP_S32_NUM_CS(n) DT_PROP(SPI_NXP_S32_NODE(n), num_cs) -#define SPI_NXP_S32_IS_MASTER(n) !DT_PROP(SPI_NXP_S32_NODE(n), slave) +#define SPI_NXP_S32_HW_INSTANCE_CHECK(i, n) \ + ((DT_INST_REG_ADDR(n) == IP_SPI_##i##_BASE) ? i : 0) + +#define SPI_NXP_S32_HW_INSTANCE(n) \ + LISTIFY(__DEBRACKET SPI_INSTANCE_COUNT, SPI_NXP_S32_HW_INSTANCE_CHECK, (|), n) + +#define SPI_NXP_S32_NUM_CS(n) DT_INST_PROP(n, num_cs) +#define SPI_NXP_S32_IS_MASTER(n) !DT_INST_PROP(n, slave) #ifdef CONFIG_SPI_SLAVE -#define SPI_NXP_S32_SET_SLAVE(n) .SlaveMode = DT_PROP(SPI_NXP_S32_NODE(n), slave), +#define SPI_NXP_S32_SET_SLAVE(n) .SlaveMode = DT_INST_PROP(n, slave), #else #define SPI_NXP_S32_SET_SLAVE(n) #endif @@ -594,15 +632,12 @@ static const struct spi_driver_api spi_nxp_s32_driver_api = { .irq_config_func = spi_nxp_s32_config_func_##n, #define SPI_NXP_S32_INTERRUPT_DEFINE(n) \ - extern void Spi_Ip_SPI_##n##_IRQHandler(void); \ static void spi_nxp_s32_config_func_##n(const struct device *dev) \ { \ - IRQ_CONNECT(DT_IRQN(SPI_NXP_S32_NODE(n)), \ - DT_IRQ(SPI_NXP_S32_NODE(n), priority), \ - Spi_Ip_SPI_##n##_IRQHandler, \ - DEVICE_DT_GET(SPI_NXP_S32_NODE(n)), \ - DT_IRQ(SPI_NXP_S32_NODE(n), flags)); \ - irq_enable(DT_IRQN(SPI_NXP_S32_NODE(n))); \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \ + spi_nxp_s32_isr, DEVICE_DT_INST_GET(n), \ + DT_INST_IRQ(n, flags)); \ + irq_enable(DT_INST_IRQN(n)); \ } #define SPI_NXP_S32_CONFIG_CALLBACK_FUNC(n) \ @@ -612,7 +647,7 @@ static const struct spi_driver_api spi_nxp_s32_driver_api = { static void spi_nxp_s32_##n##_callback(uint8 instance, Spi_Ip_EventType event) \ { \ ARG_UNUSED(instance); \ - const struct device *dev = DEVICE_DT_GET(SPI_NXP_S32_NODE(n)); \ + const struct device *dev = DEVICE_DT_INST_GET(n); \ \ spi_nxp_s32_transfer_callback(dev, event); \ } @@ -629,7 +664,7 @@ static const struct spi_driver_api spi_nxp_s32_driver_api = { */ #define SPI_NXP_S32_INSTANCE_CONFIG(n) \ static const Spi_Ip_ConfigType spi_nxp_s32_default_config_##n = { \ - .Instance = n, \ + .Instance = SPI_NXP_S32_HW_INSTANCE(n), \ .Mcr = (SPI_MCR_MSTR(SPI_NXP_S32_IS_MASTER(n)) | \ SPI_MCR_CONT_SCKE(0U) | SPI_MCR_FRZ(0U) | \ SPI_MCR_MTFE(0U) | SPI_MCR_SMPL_PT(0U) | \ @@ -642,24 +677,24 @@ static const struct spi_driver_api spi_nxp_s32_driver_api = { #define SPI_NXP_S32_TRANSFER_CONFIG(n) \ .transfer_cfg = { \ - .Instance = n, \ + .Instance = SPI_NXP_S32_HW_INSTANCE(n), \ .Ctare = SPI_CTARE_FMSZE(0U) | SPI_CTARE_DTCP(1U), \ } #define SPI_NXP_S32_DEVICE(n) \ - PINCTRL_DT_DEFINE(SPI_NXP_S32_NODE(n)); \ + PINCTRL_DT_INST_DEFINE(n); \ SPI_NXP_S32_CALLBACK_DEFINE(n) \ SPI_NXP_S32_INTERRUPT_DEFINE(n) \ SPI_NXP_S32_INSTANCE_CONFIG(n); \ static const struct spi_nxp_s32_config spi_nxp_s32_config_##n = { \ - .instance = n, \ .num_cs = SPI_NXP_S32_NUM_CS(n), \ - .clock_frequency = DT_PROP(SPI_NXP_S32_NODE(n), clock_frequency), \ - .sck_cs_delay = DT_PROP_OR(SPI_NXP_S32_NODE(n), spi_sck_cs_delay, 0U), \ - .cs_sck_delay = DT_PROP_OR(SPI_NXP_S32_NODE(n), spi_cs_sck_delay, 0U), \ - .cs_cs_delay = DT_PROP_OR(SPI_NXP_S32_NODE(n), spi_cs_cs_delay, 0U), \ - .spi_hw_cfg = (Spi_Ip_ConfigType *)&spi_nxp_s32_default_config_##n, \ - .pincfg = PINCTRL_DT_DEV_CONFIG_GET(SPI_NXP_S32_NODE(n)), \ + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ + .clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, name), \ + .sck_cs_delay = DT_INST_PROP_OR(n, spi_sck_cs_delay, 0U), \ + .cs_sck_delay = DT_INST_PROP_OR(n, spi_cs_sck_delay, 0U), \ + .cs_cs_delay = DT_INST_PROP_OR(n, spi_cs_cs_delay, 0U), \ + .spi_hw_cfg = (Spi_Ip_ConfigType *)&spi_nxp_s32_default_config_##n, \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ SPI_NXP_S32_CONFIG_CALLBACK_FUNC(n) \ SPI_NXP_S32_CONFIG_INTERRUPT_FUNC(n) \ }; \ @@ -667,50 +702,12 @@ static const struct spi_driver_api spi_nxp_s32_driver_api = { SPI_NXP_S32_TRANSFER_CONFIG(n), \ SPI_CONTEXT_INIT_LOCK(spi_nxp_s32_data_##n, ctx), \ SPI_CONTEXT_INIT_SYNC(spi_nxp_s32_data_##n, ctx), \ - SPI_CONTEXT_CS_GPIOS_INITIALIZE(SPI_NXP_S32_NODE(n), ctx) \ + SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(n), ctx) \ }; \ - DEVICE_DT_DEFINE(SPI_NXP_S32_NODE(n), \ + DEVICE_DT_INST_DEFINE(n, \ &spi_nxp_s32_init, NULL, \ &spi_nxp_s32_data_##n, &spi_nxp_s32_config_##n, \ POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, \ &spi_nxp_s32_driver_api); -#if DT_NODE_HAS_STATUS(SPI_NXP_S32_NODE(0), okay) -SPI_NXP_S32_DEVICE(0); -#endif - -#if DT_NODE_HAS_STATUS(SPI_NXP_S32_NODE(1), okay) -SPI_NXP_S32_DEVICE(1); -#endif - -#if DT_NODE_HAS_STATUS(SPI_NXP_S32_NODE(2), okay) -SPI_NXP_S32_DEVICE(2); -#endif - -#if DT_NODE_HAS_STATUS(SPI_NXP_S32_NODE(3), okay) -SPI_NXP_S32_DEVICE(3); -#endif - -#if DT_NODE_HAS_STATUS(SPI_NXP_S32_NODE(4), okay) -SPI_NXP_S32_DEVICE(4); -#endif - -#if DT_NODE_HAS_STATUS(SPI_NXP_S32_NODE(5), okay) -SPI_NXP_S32_DEVICE(5); -#endif - -#if DT_NODE_HAS_STATUS(SPI_NXP_S32_NODE(6), okay) -SPI_NXP_S32_DEVICE(6); -#endif - -#if DT_NODE_HAS_STATUS(SPI_NXP_S32_NODE(7), okay) -SPI_NXP_S32_DEVICE(7); -#endif - -#if DT_NODE_HAS_STATUS(SPI_NXP_S32_NODE(8), okay) -SPI_NXP_S32_DEVICE(8); -#endif - -#if DT_NODE_HAS_STATUS(SPI_NXP_S32_NODE(9), okay) -SPI_NXP_S32_DEVICE(9); -#endif +DT_INST_FOREACH_STATUS_OKAY(SPI_NXP_S32_DEVICE) diff --git a/drivers/spi/spi_nxp_s32.h b/drivers/spi/spi_nxp_s32.h index 39bf630e646..68f0943b130 100644 --- a/drivers/spi/spi_nxp_s32.h +++ b/drivers/spi/spi_nxp_s32.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 NXP + * Copyright 2022-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -47,9 +47,9 @@ struct spi_nxp_s32_data { }; struct spi_nxp_s32_config { - uint8_t instance; uint8_t num_cs; - uint32_t clock_frequency; + const struct device *clock_dev; + clock_control_subsys_t clock_subsys; uint32_t sck_cs_delay; uint32_t cs_sck_delay; uint32_t cs_cs_delay; diff --git a/drivers/spi/spi_pl022.c b/drivers/spi/spi_pl022.c index d71516f17df..29f92d3050c 100644 --- a/drivers/spi/spi_pl022.c +++ b/drivers/spi/spi_pl022.c @@ -889,7 +889,7 @@ static int spi_pl022_init(const struct device *dev) #if defined(CONFIG_PINCTRL) ret = pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_DEFAULT); - if (ret) { + if (ret < 0) { LOG_ERR("Failed to apply pinctrl state"); return ret; } diff --git a/drivers/spi/spi_sedi.c b/drivers/spi/spi_sedi.c new file mode 100644 index 00000000000..b3c4d22f730 --- /dev/null +++ b/drivers/spi/spi_sedi.c @@ -0,0 +1,415 @@ +/* + * Copyright (c) 2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT intel_sedi_spi + +#include +#include +#include + +#define LOG_LEVEL CONFIG_SPI_LOG_LEVEL +#include +LOG_MODULE_REGISTER(spi_sedi); + +#include "sedi_driver_spi.h" +#include "spi_context.h" + + +struct spi_sedi_config { + DEVICE_MMIO_ROM; + sedi_spi_t spi_device; + void (*irq_config)(void); +}; + +struct spi_sedi_data { + DEVICE_MMIO_RAM; + struct spi_context ctx; + bool tx_data_updated; + bool rx_data_updated; + uint32_t tx_dummy_len; + uint32_t rx_dummy_len; +}; + +static int spi_sedi_configure(const struct device *dev, + const struct spi_config *config) +{ + struct spi_sedi_data *data = dev->data; + const struct spi_sedi_config *info = dev->config; + uint32_t word_size, cpol, cpha, loopback; + + if (spi_context_configured(&data->ctx, config) == true) { + return 0; + } + + word_size = SPI_WORD_SIZE_GET(config->operation); + sedi_spi_control(info->spi_device, SEDI_SPI_IOCTL_DATA_WIDTH, + word_size); + + /* CPOL and CPHA */ + cpol = SPI_MODE_GET(config->operation) & SPI_MODE_CPOL; + cpha = SPI_MODE_GET(config->operation) & SPI_MODE_CPHA; + + if ((cpol == 0) && (cpha == 0)) { + sedi_spi_control(info->spi_device, SEDI_SPI_IOCTL_CPOL0_CPHA0, + 0); + } else if ((cpol == 0) && (cpha == 1U)) { + sedi_spi_control(info->spi_device, SEDI_SPI_IOCTL_CPOL0_CPHA1, + 0); + } else if ((cpol == 1) && (cpha == 0U)) { + sedi_spi_control(info->spi_device, SEDI_SPI_IOCTL_CPOL1_CPHA0, + 0); + } else { + sedi_spi_control(info->spi_device, SEDI_SPI_IOCTL_CPOL1_CPHA1, + 0); + } + + /* MSB and LSB */ + if (config->operation & SPI_TRANSFER_LSB) { + sedi_spi_control(info->spi_device, SEDI_SPI_IOCTL_LSB, 0); + } + + /* Set loopack */ + loopback = SPI_MODE_GET(config->operation) & SPI_MODE_LOOP; + sedi_spi_control(info->spi_device, SEDI_SPI_IOCTL_LOOPBACK, loopback); + + /* Set baudrate */ + sedi_spi_control(info->spi_device, SEDI_SPI_IOCTL_SPEED_SET, + config->frequency); + + sedi_spi_control(info->spi_device, SEDI_SPI_IOCTL_CS_HW, config->slave); + + data->ctx.config = config; + spi_context_cs_control(&data->ctx, true); + + return 0; +} + +static int transceive(const struct device *dev, const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, bool asynchronous, + spi_callback_t cb, + void *userdata) +{ + const struct spi_sedi_config *info = dev->config; + struct spi_sedi_data *spi = dev->data; + struct spi_context *ctx = &spi->ctx; + int ret; + uint32_t transfer_bytes = 0; + uint8_t *data_out = NULL, *data_in = NULL; + uint32_t i, dummy_len = 0; + const struct spi_buf *buf; + bool is_multibufs = false; + + spi_context_lock(&spi->ctx, asynchronous, cb, userdata, config); + pm_device_busy_set(dev); + + /* Power up use default setting */ + ret = sedi_spi_set_power(info->spi_device, SEDI_POWER_FULL); + if (ret) { + goto out; + } + + /* If need to configure, re-configure */ + spi_sedi_configure(dev, config); + + spi->tx_data_updated = false; + spi->rx_data_updated = false; + /* Set buffers info */ + spi_context_buffers_setup(&spi->ctx, tx_bufs, rx_bufs, 1); + + if ((ctx->tx_count > 1) || (ctx->rx_count > 1)) { + is_multibufs = true; + } + + if (ctx->tx_count > ctx->rx_count) { + spi->tx_dummy_len = 0; + for (i = ctx->rx_count; i < ctx->tx_count; i++) { + buf = ctx->current_tx + i; + dummy_len += buf->len; + } + spi->rx_dummy_len = dummy_len; + } else if (ctx->tx_count < ctx->rx_count) { + spi->rx_dummy_len = 0; + for (i = ctx->tx_count; i < ctx->rx_count; i++) { + buf = ctx->current_rx + i; + dummy_len += buf->len; + } + spi->tx_dummy_len = dummy_len; + } else { + spi->tx_dummy_len = 0; + spi->rx_dummy_len = 0; + } + + if ((ctx->tx_len == 0) && (ctx->rx_len == 0)) { + spi_context_cs_control(&spi->ctx, true); + spi_context_complete(&spi->ctx, dev, 0); + return 0; + } + + /* For multiple buffers, using continuous mode */ + if (is_multibufs) { + sedi_spi_control(info->spi_device, SEDI_SPI_IOCTL_BUFFER_SETS, 1); + } + + if (ctx->tx_len == 0) { + /* rx only, nothing to tx */ + data_out = NULL; + data_in = (uint8_t *)ctx->rx_buf; + transfer_bytes = ctx->rx_len; + spi->tx_dummy_len -= transfer_bytes; + } else if (ctx->rx_len == 0) { + /* tx only, nothing to rx */ + data_out = (uint8_t *)ctx->tx_buf; + data_in = NULL; + transfer_bytes = ctx->tx_len; + spi->rx_dummy_len -= transfer_bytes; + } else if (ctx->tx_len == ctx->rx_len) { + /* rx and tx are the same length */ + data_out = (uint8_t *)ctx->tx_buf; + data_in = (uint8_t *)ctx->rx_buf; + transfer_bytes = ctx->tx_len; + } else if (ctx->tx_len > ctx->rx_len) { + /* Break up the tx into multiple transfers so we don't have to + * rx into a longer intermediate buffer. Leave chip select + * active between transfers. + */ + data_out = (uint8_t *)ctx->tx_buf; + data_in = ctx->rx_buf; + transfer_bytes = ctx->rx_len; + } else { + /* Break up the rx into multiple transfers so we don't have to + * tx from a longer intermediate buffer. Leave chip select + * active between transfers. + */ + data_out = (uint8_t *)ctx->tx_buf; + data_in = ctx->rx_buf; + transfer_bytes = ctx->tx_len; + } + + spi_context_cs_control(&spi->ctx, false); + + ret = sedi_spi_transfer(info->spi_device, data_out, data_in, + transfer_bytes); + + if (ret != SEDI_DRIVER_OK) { + goto out; + } + + ret = spi_context_wait_for_completion(&spi->ctx); + if (ret != 0) { + sedi_spi_status_t spi_status = {0}; + + sedi_spi_get_status(info->spi_device, &spi_status); + + /* SPI ABORT */ + sedi_spi_control(info->spi_device, SEDI_SPI_IOCTL_ABORT, 0); + /* Toggle GPIO back */ + spi_context_cs_control(&spi->ctx, true); + } +out: + spi_context_release(&spi->ctx, ret); + pm_device_busy_clear(dev); + + return ret; +} + +static int spi_sedi_transceive(const struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs) +{ + return transceive(dev, config, tx_bufs, rx_bufs, false, NULL, NULL); +} + +#ifdef CONFIG_SPI_ASYNC +static int spi_sedi_transceive_async(const struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, + spi_callback_t cb, + void *userdata) +{ + return transceive(dev, config, tx_bufs, rx_bufs, true, cb, userdata); +} +#endif /* CONFIG_SPI_ASYNC */ + +static int spi_sedi_release(const struct device *dev, + const struct spi_config *config) +{ + struct spi_sedi_data *spi = dev->data; + + if (!spi_context_configured(&spi->ctx, config)) { + return -EINVAL; + } + + spi_context_unlock_unconditionally(&spi->ctx); + + return 0; +} + +extern void spi_isr(sedi_spi_t device); + +void spi_sedi_callback(uint32_t event, void *param) +{ + const struct device *dev = (const struct device *)param; + const struct spi_sedi_config *info = dev->config; + struct spi_sedi_data *spi = dev->data; + struct spi_context *ctx = &spi->ctx; + int error; + + if (event == SEDI_SPI_EVENT_DATA_LOST) { + error = -EIO; + } else { + error = 0; + } + + if ((event == SEDI_SPI_EVENT_COMPLETE) || + (event == SEDI_SPI_EVENT_DATA_LOST)) { + spi_context_cs_control(&spi->ctx, true); + spi_context_complete(&spi->ctx, dev, error); + } else if (event == SEDI_SPI_EVENT_TX_FINISHED) { + spi_context_update_tx(ctx, 1, ctx->tx_len); + if (ctx->tx_len != 0) { + sedi_spi_update_tx_buf(info->spi_device, ctx->tx_buf, + ctx->tx_len); + if ((ctx->rx_len == 0) && + (spi->rx_data_updated == false)) { + /* Update rx length if always no rx */ + sedi_spi_update_rx_buf(info->spi_device, NULL, + spi->rx_dummy_len); + spi->rx_data_updated = true; + } + } else if (spi->tx_data_updated == false) { + sedi_spi_update_tx_buf(info->spi_device, NULL, + spi->tx_dummy_len); + spi->tx_data_updated = true; + } + } else if (event == SEDI_SPI_EVENT_RX_FINISHED) { + spi_context_update_rx(ctx, 1, ctx->rx_len); + if (ctx->rx_len != 0) { + sedi_spi_update_rx_buf(info->spi_device, ctx->rx_buf, + ctx->rx_len); + } + } +} + +static const struct spi_driver_api sedi_spi_api = { + .transceive = spi_sedi_transceive, +#ifdef CONFIG_SPI_ASYNC + .transceive_async = spi_sedi_transceive_async, +#endif /* CONFIG_SPI_ASYNC */ + .release = spi_sedi_release, +}; + +static int spi_sedi_init(const struct device *dev) +{ + const struct spi_sedi_config *info = dev->config; + struct spi_sedi_data *spi = dev->data; + int ret; + + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); + + ret = sedi_spi_init(info->spi_device, spi_sedi_callback, (void *)dev, + DEVICE_MMIO_GET(dev)); + if (ret != SEDI_DRIVER_OK) { + return -ENODEV; + } + + /* Init and connect IRQ */ + info->irq_config(); + + spi_context_unlock_unconditionally(&spi->ctx); + + return 0; +} + +#ifdef CONFIG_PM_DEVICE + +static int spi_suspend_device(const struct device *dev) +{ + const struct spi_sedi_config *config = dev->config; + + if (pm_device_is_busy(dev)) { + return -EBUSY; + } + + int ret = sedi_spi_set_power(config->spi_device, SEDI_POWER_SUSPEND); + + if (ret != SEDI_DRIVER_OK) { + return -EIO; + } + + return 0; +} + +static int spi_resume_device_from_suspend(const struct device *dev) +{ + const struct spi_sedi_config *config = dev->config; + int ret; + + ret = sedi_spi_set_power(config->spi_device, SEDI_POWER_FULL); + if (ret != SEDI_DRIVER_OK) { + return -EIO; + } + + pm_device_busy_clear(dev); + + return 0; +} + +static int spi_sedi_device_ctrl(const struct device *dev, + enum pm_device_action action) +{ + int ret = 0; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + ret = spi_suspend_device(dev); + break; + case PM_DEVICE_ACTION_RESUME: + ret = spi_resume_device_from_suspend(dev); + break; + default: + ret = -ENOTSUP; + } + + return ret; +} + +#endif /* CONFIG_PM_DEVICE */ + +#define SPI_SEDI_IRQ_FLAGS_SENSE0(n) 0 +#define SPI_SEDI_IRQ_FLAGS_SENSE1(n) DT_INST_IRQ(n, sense) +#define SPI_SEDI_IRQ_FLAGS(n) \ + _CONCAT(SPI_SEDI_IRQ_FLAGS_SENSE, DT_INST_IRQ_HAS_CELL(n, sense))(n) + +#define CREATE_SEDI_SPI_INSTANCE(num) \ + static void spi_##num##_irq_init(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(num), \ + DT_INST_IRQ(num, priority), \ + spi_isr, num, SPI_SEDI_IRQ_FLAGS(num)); \ + irq_enable(DT_INST_IRQN(num)); \ + } \ + static struct spi_sedi_data spi_##num##_data = { \ + SPI_CONTEXT_INIT_LOCK(spi_##num##_data, ctx), \ + SPI_CONTEXT_INIT_SYNC(spi_##num##_data, ctx), \ + }; \ + const static struct spi_sedi_config spi_##num##_config = { \ + DEVICE_MMIO_ROM_INIT(DT_DRV_INST(num)), \ + .spi_device = num, .irq_config = spi_##num##_irq_init, \ + }; \ + PM_DEVICE_DEFINE(spi_##num, spi_sedi_device_ctrl); \ + DEVICE_DT_INST_DEFINE(num, \ + &spi_sedi_init, \ + PM_DEVICE_GET(spi_##num), \ + &spi_##num##_data, \ + &spi_##num##_config, \ + POST_KERNEL, \ + CONFIG_SPI_INIT_PRIORITY, \ + &sedi_spi_api); + +DT_INST_FOREACH_STATUS_OKAY(CREATE_SEDI_SPI_INSTANCE) diff --git a/drivers/spi/spi_xec_qmspi_ldma.c b/drivers/spi/spi_xec_qmspi_ldma.c index a5ba08e600b..ab48e49c095 100644 --- a/drivers/spi/spi_xec_qmspi_ldma.c +++ b/drivers/spi/spi_xec_qmspi_ldma.c @@ -346,7 +346,6 @@ static int qmspi_configure(const struct device *dev, { const struct spi_qmspi_config *cfg = dev->config; struct spi_qmspi_data *qdata = dev->data; - const struct spi_config *curr_cfg = qdata->ctx.config; struct qmspi_regs *regs = cfg->regs; uint32_t smode; int ret; @@ -355,13 +354,11 @@ static int qmspi_configure(const struct device *dev, return -EINVAL; } - if (curr_cfg->frequency != config->frequency) { - qmspi_set_frequency(qdata, regs, config->frequency); + if (spi_context_configured(&qdata->ctx, config)) { + return 0; } - if (curr_cfg->operation == config->operation) { - return 0; /* no change required */ - } + qmspi_set_frequency(qdata, regs, config->frequency); /* check new configuration */ ret = spi_feature_support(config); diff --git a/drivers/spi/spi_xmc4xxx.c b/drivers/spi/spi_xmc4xxx.c index 9c48fb05098..97b32f20e04 100644 --- a/drivers/spi/spi_xmc4xxx.c +++ b/drivers/spi/spi_xmc4xxx.c @@ -123,10 +123,10 @@ static void spi_xmc4xxx_shift_frames(const struct device *dev) XMC_SPI_CH_STATUS_FLAG_RECEIVE_INDICATION | XMC_SPI_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION); - XMC_SPI_CH_Transmit(config->spi, tx_data, XMC_SPI_CH_MODE_STANDARD); - spi_context_update_tx(ctx, 1, 1); + XMC_SPI_CH_Transmit(config->spi, tx_data, XMC_SPI_CH_MODE_STANDARD); + #if defined(CONFIG_SPI_XMC4XXX_INTERRUPT) return; #endif @@ -195,7 +195,8 @@ static int spi_xmc4xxx_configure(const struct device *dev, const struct spi_conf bool CPOL = SPI_MODE_GET(settings) & SPI_MODE_CPOL; bool CPHA = SPI_MODE_GET(settings) & SPI_MODE_CPHA; XMC_SPI_CH_CONFIG_t usic_cfg = {.baudrate = spi_cfg->frequency}; - XMC_SPI_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL_t clock_settings; + XMC_SPI_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL_t clock_settings = + XMC_SPI_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL_0_DELAY_ENABLED; if (spi_context_configured(ctx, spi_cfg)) { return 0; @@ -468,7 +469,9 @@ static int spi_xmc4xxx_transceive_dma(const struct device *dev, const struct spi spi_context_cs_control(ctx, false); } +#if defined(CONFIG_SPI_XMC4XXX_INTERRUPT) irq_enable(config->irq_num_rx); +#endif spi_context_release(ctx, ret); return ret; diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index fb615c2b7cf..8a88e731986 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -65,7 +65,7 @@ config SYSTEM_CLOCK_LOCK_FREE_COUNT source "drivers/timer/Kconfig.altera_avalon" source "drivers/timer/Kconfig.ambiq" -source "drivers/timer/Kconfig.apic" +source "drivers/timer/Kconfig.x86" source "drivers/timer/Kconfig.arcv2" source "drivers/timer/Kconfig.arm_arch" source "drivers/timer/Kconfig.cavs" @@ -73,7 +73,6 @@ source "drivers/timer/Kconfig.cc13xx_cc26xx_rtc" source "drivers/timer/Kconfig.cortex_m_systick" source "drivers/timer/Kconfig.esp32c3_sys" source "drivers/timer/Kconfig.gecko" -source "drivers/timer/Kconfig.hpet" source "drivers/timer/Kconfig.ite_it8xxx2" source "drivers/timer/Kconfig.leon_gptimer" source "drivers/timer/Kconfig.litex" diff --git a/drivers/timer/Kconfig.apic b/drivers/timer/Kconfig.apic deleted file mode 100644 index 5e745beb945..00000000000 --- a/drivers/timer/Kconfig.apic +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (c) 2014-2015 Wind River Systems, Inc. -# Copyright (c) 2016 Cadence Design Systems, Inc. -# Copyright (c) 2019 Intel Corp. -# SPDX-License-Identifier: Apache-2.0 - -menuconfig APIC_TIMER - bool "New local APIC timer" - depends on X86 - depends on LOAPIC - select TICKLESS_CAPABLE - select SYSTEM_CLOCK_LOCK_FREE_COUNT - help - Use the x86 local APIC in one-shot mode as the system time - source. NOTE: this probably isn't what you want except on - older or idiosyncratic hardware (or environments like qemu - without complete APIC emulation). Modern hardware will work - better with CONFIG_APIC_TSC_DEADLINE_TIMER. - -if APIC_TIMER - -config APIC_TIMER_IRQ - int "Local APIC timer IRQ" - default 24 - help - This option specifies the IRQ used by the local APIC timer. - Note: this MUST be set to the index immediately after the - last IO-APIC IRQ (the timer is the first entry in the APIC - local vector table). This footgun is not intended to be - user-configurable and almost certainly should be managed via - a different mechanism. - -config APIC_TIMER_TSC - bool "Use invariant TSC for sys_clock_cycle_get_32()" - select TIMER_HAS_64BIT_CYCLE_COUNTER - help - If your CPU supports invariant TSC, and you know the ratio of the - TSC frequency to CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC (the local APIC - timer frequency), then enable this for a much faster and more - accurate sys_clock_cycle_get_32(). - -if APIC_TIMER_TSC - -config APIC_TIMER_TSC_N - int "TSC to local APIC timer frequency multiplier (N)" - default 1 - -config APIC_TIMER_TSC_M - int "TSC to local APIC timer frequency divisor (M)" - default 1 - -endif # APIC_TIMER_TSC - -endif # APIC_TIMER - -config APIC_TSC_DEADLINE_TIMER - bool "Even newer APIC timer using TSC deadline mode" - depends on X86 - select LOAPIC - select TICKLESS_CAPABLE - select TIMER_HAS_64BIT_CYCLE_COUNTER - help - Extremely simple timer driver based the local APIC TSC - deadline capability. The use of a free-running 64 bit - counter with comparator eliminates almost all edge cases - from the handling, and the near-instruction-cycle resolution - permits effectively unlimited precision where needed (the - limit becomes the CPU time taken to execute the timing - logic). SMP-safe and very fast, this should be the obvious - choice for any x86 device with invariant TSC and TSC - deadline capability. - -config APIC_TIMER_IRQ_PRIORITY - int "Local APIC timer interrupt priority" - depends on APIC_TIMER || APIC_TSC_DEADLINE_TIMER - default 4 - help - This option specifies the interrupt priority used by the - local APIC timer. diff --git a/drivers/timer/Kconfig.cortex_m_systick b/drivers/timer/Kconfig.cortex_m_systick index 31e4f56fce5..baf1f6c817e 100644 --- a/drivers/timer/Kconfig.cortex_m_systick +++ b/drivers/timer/Kconfig.cortex_m_systick @@ -3,6 +3,8 @@ # Copyright (c) 2019 Intel Corp. # SPDX-License-Identifier: Apache-2.0 +DT_CHOSEN_IDLE_TIMER := zephyr,cortex-m-idle-timer + config CORTEX_M_SYSTICK bool "Cortex-M SYSTICK timer" depends on CPU_CORTEX_M_HAS_SYSTICK @@ -40,3 +42,20 @@ config CORTEX_M_SYSTICK_64BIT_CYCLE_COUNTER This is set to y by default when the hardware clock is fast enough to wrap sys_clock_cycle_get_32() in about a minute or less. + +config CORTEX_M_SYSTICK_IDLE_TIMER + bool "Use an additional timer while entering IDLE" + default $(dt_chosen_enabled,$(DT_CHOSEN_IDLE_TIMER)) + depends on COUNTER + depends on TICKLESS_KERNEL + help + There are chips e.g. STMFX family that use SysTick as a system timer, + but SysTick is not clocked in low power mode. These chips usually have + another timer that is not stopped, but it has lower frequency e.g. + RTC, thus it can't be used as a main system timer. + + Use the IDLE timer for timeout (wakeup) when the system is entering + IDLE state. + + The chosen IDLE timer node has to support setting alarm from the + counter API. diff --git a/drivers/timer/Kconfig.hpet b/drivers/timer/Kconfig.hpet deleted file mode 100644 index c83af2b4615..00000000000 --- a/drivers/timer/Kconfig.hpet +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2014-2015 Wind River Systems, Inc. -# Copyright (c) 2016 Cadence Design Systems, Inc. -# Copyright (c) 2019 Intel Corp. -# SPDX-License-Identifier: Apache-2.0 - -config HPET_TIMER - bool "HPET timer" - default y - depends on DT_HAS_INTEL_HPET_ENABLED - select IOAPIC if X86 - select LOAPIC if X86 - imply TIMER_READS_ITS_FREQUENCY_AT_RUNTIME - select TICKLESS_CAPABLE - select TIMER_HAS_64BIT_CYCLE_COUNTER - help - This option selects High Precision Event Timer (HPET) as a - system timer. diff --git a/drivers/timer/Kconfig.nrf_rtc b/drivers/timer/Kconfig.nrf_rtc index acb6f123afe..baa917282bc 100644 --- a/drivers/timer/Kconfig.nrf_rtc +++ b/drivers/timer/Kconfig.nrf_rtc @@ -19,7 +19,7 @@ if NRF_RTC_TIMER config NRF_RTC_TIMER_USER_CHAN_COUNT int "Additional channels that can be used" - default 2 if NRF_802154_RADIO_DRIVER && SOC_NRF5340_CPUNET + default 2 if NRF_802154_RADIO_DRIVER && SOC_COMPATIBLE_NRF5340_CPUNET default 3 if NRF_802154_RADIO_DRIVER default 0 help diff --git a/drivers/timer/Kconfig.x86 b/drivers/timer/Kconfig.x86 new file mode 100644 index 00000000000..aa5f1a9c6d6 --- /dev/null +++ b/drivers/timer/Kconfig.x86 @@ -0,0 +1,98 @@ +# Copyright (c) 2014-2015 Wind River Systems, Inc. +# Copyright (c) 2016 Cadence Design Systems, Inc. +# Copyright (c) 2019-2023 Intel Corp. +# SPDX-License-Identifier: Apache-2.0 + +choice + prompt "Default System Timer" + default HPET_TIMER if SOC_FAMILY_INTEL_ISH || SOC_IA32 || SOC_LAKEMONT + default APIC_TSC_DEADLINE_TIMER + depends on X86 + help + Select Default System Timer. + +config HPET_TIMER + bool "HPET timer" + depends on DT_HAS_INTEL_HPET_ENABLED + select IOAPIC + select LOAPIC + imply TIMER_READS_ITS_FREQUENCY_AT_RUNTIME + select TICKLESS_CAPABLE + select TIMER_HAS_64BIT_CYCLE_COUNTER + help + This option selects High Precision Event Timer (HPET) as a + system timer. + +config APIC_TIMER + bool "Local APIC timer" + select LOAPIC + select TICKLESS_CAPABLE + select SYSTEM_CLOCK_LOCK_FREE_COUNT + help + Use the x86 local APIC in one-shot mode as the system time + source. NOTE: this probably isn't what you want except on + older or idiosyncratic hardware (or environments like qemu + without complete APIC emulation). Modern hardware will work + better with CONFIG_APIC_TSC_DEADLINE_TIMER. + +config APIC_TSC_DEADLINE_TIMER + bool "Local APIC timer using TSC deadline mode" + select LOAPIC + select TICKLESS_CAPABLE + select TIMER_HAS_64BIT_CYCLE_COUNTER + help + Extremely simple timer driver based the local APIC TSC + deadline capability. The use of a free-running 64 bit + counter with comparator eliminates almost all edge cases + from the handling, and the near-instruction-cycle resolution + permits effectively unlimited precision where needed (the + limit becomes the CPU time taken to execute the timing + logic). SMP-safe and very fast, this should be the obvious + choice for any x86 device with invariant TSC and TSC + deadline capability. + +endchoice + +if APIC_TIMER + +config APIC_TIMER_IRQ + int "Local APIC timer IRQ" + default 24 + help + This option specifies the IRQ used by the local APIC timer. + Note: this MUST be set to the index immediately after the + last IO-APIC IRQ (the timer is the first entry in the APIC + local vector table). This footgun is not intended to be + user-configurable and almost certainly should be managed via + a different mechanism. + +config APIC_TIMER_TSC + bool "Use invariant TSC for sys_clock_cycle_get_32()" + select TIMER_HAS_64BIT_CYCLE_COUNTER + help + If your CPU supports invariant TSC, and you know the ratio of the + TSC frequency to CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC (the local APIC + timer frequency), then enable this for a much faster and more + accurate sys_clock_cycle_get_32(). + +if APIC_TIMER_TSC + +config APIC_TIMER_TSC_N + int "TSC to local APIC timer frequency multiplier (N)" + default 1 + +config APIC_TIMER_TSC_M + int "TSC to local APIC timer frequency divisor (M)" + default 1 + +endif # APIC_TIMER_TSC + +endif # APIC_TIMER + +config APIC_TIMER_IRQ_PRIORITY + int "Local APIC timer interrupt priority" + depends on APIC_TIMER || APIC_TSC_DEADLINE_TIMER + default 4 + help + This option specifies the interrupt priority used by the + local APIC timer. diff --git a/drivers/timer/cortex_m_systick.c b/drivers/timer/cortex_m_systick.c index f415f99ea0d..13e499efec4 100644 --- a/drivers/timer/cortex_m_systick.c +++ b/drivers/timer/cortex_m_systick.c @@ -10,6 +10,7 @@ #include #include #include +#include #define COUNTER_MAX 0x00ffffff #define TIMER_STOPPED 0xff000000 @@ -77,6 +78,26 @@ static cycle_t announced_cycles; */ static volatile uint32_t overflow_cyc; +#ifdef CONFIG_CORTEX_M_SYSTICK_IDLE_TIMER +/* This local variable indicates that the timeout was set right before + * entering idle state. + * + * It is used for chips that has to use a separate idle timer in such + * case because the Cortex-m SysTick is not clocked in the low power + * mode state. + */ +static bool timeout_idle; + +/* Cycle counter before entering the idle state. */ +static cycle_t cycle_pre_idle; + +/* Idle timer value before entering the idle state. */ +static uint32_t idle_timer_pre_idle; + +/* Idle timer used for timer while entering the idle state */ +static const struct device *idle_timer = DEVICE_DT_GET(DT_CHOSEN(zephyr_cortex_m_idle_timer)); +#endif /* CONFIG_CORTEX_M_SYSTICK_IDLE_TIMER */ + /* This internal function calculates the amount of HW cycles that have * elapsed since the last time the absolute HW cycles counter has been * updated. 'cycle_count' may be updated either by the ISR, or when we @@ -101,10 +122,19 @@ static uint32_t elapsed(void) uint32_t ctrl = SysTick->CTRL; /* B */ uint32_t val2 = SysTick->VAL; /* C */ - /* SysTick behavior: The counter wraps at zero automatically, - * setting the COUNTFLAG field of the CTRL register when it - * does. Reading the control register automatically clears - * that field. + /* SysTick behavior: The counter wraps after zero automatically. + * The COUNTFLAG field of the CTRL register is set when it + * decrements from 1 to 0. Reading the control register + * automatically clears that field. When a timer is started, + * count begins at zero then wraps after the first cycle. + * Reference: + * Armv6-m (B3.3.1) https://developer.arm.com/documentation/ddi0419 + * Armv7-m (B3.3.1) https://developer.arm.com/documentation/ddi0403 + * Armv8-m (B11.1) https://developer.arm.com/documentation/ddi0553 + * + * First, manually wrap/realign val1 and val2 from [0:last_load-1] + * to [1:last_load]. This allows subsequent code to assume that + * COUNTFLAG and wrapping occur on the same cycle. * * If the count wrapped... * 1) Before A then COUNTFLAG will be set and val1 >= val2 @@ -115,6 +145,13 @@ static uint32_t elapsed(void) * So the count in val2 is post-wrap and last_load needs to be * added if and only if COUNTFLAG is set or val1 < val2. */ + if (val1 == 0) { + val1 = last_load; + } + if (val2 == 0) { + val2 = last_load; + } + if ((ctrl & SysTick_CTRL_COUNTFLAG_Msk) || (val1 < val2)) { overflow_cyc += last_load; @@ -143,6 +180,19 @@ void sys_clock_isr(void *arg) cycle_count += overflow_cyc; overflow_cyc = 0; +#ifdef CONFIG_CORTEX_M_SYSTICK_IDLE_TIMER + /* Rare case, when the interrupt was triggered, with previously programmed + * LOAD value, just before entering the idle mode (SysTick is clocked) or right + * after exiting the idle mode, before executing the procedure in the + * sys_clock_idle_exit function. + */ + if (timeout_idle) { + z_arm_int_exit(); + + return; + } +#endif /* CONFIG_CORTEX_M_SYSTICK_IDLE_TIMER */ + if (TICKLESS) { /* In TICKLESS mode, the SysTick.LOAD is re-programmed * in sys_clock_set_timeout(), followed by resetting of @@ -180,6 +230,36 @@ void sys_clock_set_timeout(int32_t ticks, bool idle) return; } +#ifdef CONFIG_CORTEX_M_SYSTICK_IDLE_TIMER + if (idle) { + uint64_t timeout_us = + ((uint64_t)ticks * USEC_PER_SEC) / CONFIG_SYS_CLOCK_TICKS_PER_SEC; + struct counter_alarm_cfg cfg = { + .callback = NULL, + .ticks = counter_us_to_ticks(idle_timer, timeout_us), + .user_data = NULL, + .flags = 0, + }; + + timeout_idle = true; + + /* Set the alarm using timer that runs the idle. + * Needed rump-up/setting time, lower accurency etc. should be + * included in the exit-latency in the power state definition. + */ + counter_cancel_channel_alarm(idle_timer, 0); + counter_set_channel_alarm(idle_timer, 0, &cfg); + + /* Store current values to calculate a difference in + * measurements after exiting the idle state. + */ + counter_get_value(idle_timer, &idle_timer_pre_idle); + cycle_pre_idle = cycle_count + elapsed(); + + return; + } +#endif /* CONFIG_CORTEX_M_SYSTICK_IDLE_TIMER */ + #if defined(CONFIG_TICKLESS_KERNEL) uint32_t delay; uint32_t val1, val2; @@ -284,6 +364,43 @@ uint64_t sys_clock_cycle_get_64(void) void sys_clock_idle_exit(void) { +#ifdef CONFIG_CORTEX_M_SYSTICK_IDLE_TIMER + if (timeout_idle) { + cycle_t systick_diff, missed_cycles; + uint32_t idle_timer_diff, idle_timer_post, dcycles, dticks; + uint64_t systick_us, idle_timer_us, measurement_diff_us; + + /* Get current values for both timers */ + counter_get_value(idle_timer, &idle_timer_post); + systick_diff = cycle_count + elapsed() - cycle_pre_idle; + + /* Calculate has much time has pasted since last measurement for both timers */ + idle_timer_diff = idle_timer_post - idle_timer_pre_idle; + idle_timer_us = counter_ticks_to_us(idle_timer, idle_timer_diff); + systick_us = + ((uint64_t)systick_diff * USEC_PER_SEC) / sys_clock_hw_cycles_per_sec(); + + /* Calculate difference in measurements to get how much time + * the SysTick missed in idle state. + */ + measurement_diff_us = idle_timer_us - systick_us; + missed_cycles = + (sys_clock_hw_cycles_per_sec() * measurement_diff_us) / USEC_PER_SEC; + + /* Update the cycle counter to include the cycles missed in idle */ + cycle_count += missed_cycles; + + /* Announce the passed ticks to the kernel */ + dcycles = cycle_count + elapsed() - announced_cycles; + dticks = dcycles / CYC_PER_TICK; + announced_cycles += dticks * CYC_PER_TICK; + sys_clock_announce(dticks); + + /* We've alredy performed all needed operations */ + timeout_idle = false; + } +#endif /* CONFIG_CORTEX_M_SYSTICK_IDLE_TIMER */ + if (last_load == TIMER_STOPPED) { SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; } @@ -298,9 +415,9 @@ static int sys_clock_driver_init(void) { NVIC_SetPriority(SysTick_IRQn, _IRQ_PRIO_OFFSET); - last_load = CYC_PER_TICK - 1; + last_load = CYC_PER_TICK; overflow_cyc = 0U; - SysTick->LOAD = last_load; + SysTick->LOAD = last_load - 1; SysTick->VAL = 0; /* resets timer to last_load */ SysTick->CTRL |= (SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk | diff --git a/drivers/timer/native_posix_timer.c b/drivers/timer/native_posix_timer.c index efe54e54bf0..31d1fc3bc69 100644 --- a/drivers/timer/native_posix_timer.c +++ b/drivers/timer/native_posix_timer.c @@ -10,7 +10,7 @@ * It also provides a custom k_busy_wait() which can be used with the * POSIX arch and InfClock SOC */ -#include "zephyr/types.h" +#include #include #include #include diff --git a/drivers/timer/npcx_itim_timer.c b/drivers/timer/npcx_itim_timer.c index a54db566d9e..fba2bc2b3c1 100644 --- a/drivers/timer/npcx_itim_timer.c +++ b/drivers/timer/npcx_itim_timer.c @@ -58,6 +58,7 @@ LOG_MODULE_REGISTER(itim, LOG_LEVEL_ERR); #define NPCX_ITIM_CLK_SEL_DELAY 92 /* Delay for clock selection (Unit:us) */ /* Timeout for enabling ITIM module: 100us (Unit:cycles) */ #define NPCX_ITIM_EN_TIMEOUT_CYCLES (100 * SYS_CYCLES_PER_USEC) +#define SYS_CYC_PER_EVT_CYC (sys_clock_hw_cycles_per_sec() / EVT_CYCLES_PER_SEC) /* Instance of system and event timers */ static struct itim64_reg *const sys_tmr = (struct itim64_reg *) @@ -70,6 +71,9 @@ static const struct npcx_clk_cfg itim_clk_cfg[] = NPCX_DT_CLK_CFG_ITEMS_LIST(0); static struct k_spinlock lock; /* Announced cycles in system timer before executing sys_clock_announce() */ static uint64_t cyc_sys_announced; +static uint64_t last_ticks; +static uint32_t last_elapsed; + /* Current target cycles of time-out signal in event timer */ static uint32_t cyc_evt_timeout; /* Total cycles of system timer stopped in "sleep/deep sleep" mode */ @@ -136,18 +140,33 @@ static inline void npcx_itim_evt_disable(void) /* ITIM local functions */ static int npcx_itim_start_evt_tmr_by_tick(int32_t ticks) { + k_spinlock_key_t key = k_spin_lock(&lock); + /* * Get desired cycles of event timer from the requested ticks which * round up to next tick boundary. */ + if (ticks == K_TICKS_FOREVER) { cyc_evt_timeout = NPCX_ITIM32_MAX_CNT; } else { + uint64_t next_cycs; + uint64_t curr = npcx_itim_get_sys_cyc64(); + uint32_t dcycles; + if (ticks <= 0) { ticks = 1; } - cyc_evt_timeout = MIN(EVT_CYCLES_FROM_TICKS(ticks), - NPCX_ITIM32_MAX_CNT); + + next_cycs = (last_ticks + last_elapsed + ticks) * SYS_CYCLES_PER_TICK; + if (unlikely(next_cycs <= curr)) { + cyc_evt_timeout = 1; + } else { + dcycles = next_cycs - curr; + cyc_evt_timeout = + CLAMP((dcycles / SYS_CYC_PER_EVT_CYC), 1, NPCX_ITIM32_MAX_CNT); + } + } LOG_DBG("ticks %x, cyc_evt_timeout %x", ticks, cyc_evt_timeout); @@ -159,9 +178,9 @@ static int npcx_itim_start_evt_tmr_by_tick(int32_t ticks) /* Upload counter of event timer */ evt_tmr->ITCNT32 = MAX(cyc_evt_timeout - 1, 1); + k_spin_unlock(&lock, key); /* Enable event timer and start ticking */ return npcx_itim_evt_enable(); - } static void npcx_itim_evt_isr(const struct device *dev) @@ -175,11 +194,12 @@ static void npcx_itim_evt_isr(const struct device *dev) if (IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { k_spinlock_key_t key = k_spin_lock(&lock); - uint32_t delta_ticks = (uint32_t)((npcx_itim_get_sys_cyc64() - - cyc_sys_announced) / SYS_CYCLES_PER_TICK); + uint64_t curr = npcx_itim_get_sys_cyc64(); + uint32_t delta_ticks = (uint32_t)((curr - cyc_sys_announced) / SYS_CYCLES_PER_TICK); - /* Store announced cycles of system timer */ - cyc_sys_announced = npcx_itim_get_sys_cyc64(); + cyc_sys_announced += delta_ticks * SYS_CYCLES_PER_TICK; + last_ticks += delta_ticks; + last_elapsed = 0; k_spin_unlock(&lock, key); /* Informs kernel that specified number of ticks have elapsed */ @@ -252,11 +272,13 @@ uint32_t sys_clock_elapsed(void) k_spinlock_key_t key = k_spin_lock(&lock); uint64_t delta_cycle = npcx_itim_get_sys_cyc64() - cyc_sys_announced; + uint32_t delta_ticks = (uint32_t)delta_cycle / SYS_CYCLES_PER_TICK; + last_elapsed = delta_ticks; k_spin_unlock(&lock, key); /* Return how many ticks elapsed since last sys_clock_announce() call */ - return (uint32_t)(delta_cycle / SYS_CYCLES_PER_TICK); + return delta_ticks; } uint32_t sys_clock_cycle_get_32(void) diff --git a/drivers/usb/CMakeLists.txt b/drivers/usb/CMakeLists.txt index 7a0570f146d..e0d9f196b29 100644 --- a/drivers/usb/CMakeLists.txt +++ b/drivers/usb/CMakeLists.txt @@ -5,3 +5,4 @@ add_subdirectory_ifdef(CONFIG_UHC_DRIVER uhc) add_subdirectory_ifdef(CONFIG_UVB uvb) add_subdirectory_ifdef(CONFIG_USB_BC12 bc12) add_subdirectory_ifdef(CONFIG_USB_DEVICE_DRIVER device) +add_subdirectory(common) diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 369b40f6fa3..bcccdf6b657 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -8,3 +8,4 @@ source "drivers/usb/udc/Kconfig" source "drivers/usb/uhc/Kconfig" source "drivers/usb/uvb/Kconfig" source "drivers/usb/device/Kconfig" +source "drivers/usb/common/Kconfig" diff --git a/drivers/usb/bc12/bc12_handlers.c b/drivers/usb/bc12/bc12_handlers.c index bf7ff8fcf39..dce82695a14 100644 --- a/drivers/usb/bc12/bc12_handlers.c +++ b/drivers/usb/bc12/bc12_handlers.c @@ -5,11 +5,11 @@ */ #include -#include +#include static inline int z_vrfy_bc12_set_role(const struct device *dev, enum bc12_role role) { - Z_OOPS(Z_SYSCALL_DRIVER_BC12(dev, set_role)); + K_OOPS(K_SYSCALL_DRIVER_BC12(dev, set_role)); return z_impl_bc12_set_role(dev, role); } @@ -17,8 +17,8 @@ static inline int z_vrfy_bc12_set_role(const struct device *dev, enum bc12_role static inline int z_vrfy_bc12_set_result_cb(const struct device *dev, bc12_callback_t cb, void *user_data) { - Z_OOPS(Z_SYSCALL_DRIVER_BC12(dev, set_result_cb)); - Z_OOPS(Z_SYSCALL_VERIFY_MSG(cb == NULL, "callbacks may not be set from user mode")); + K_OOPS(K_SYSCALL_DRIVER_BC12(dev, set_result_cb)); + K_OOPS(K_SYSCALL_VERIFY_MSG(cb == NULL, "callbacks may not be set from user mode")); return z_impl_bc12_set_result_cb(dev, cb, user_data); } diff --git a/drivers/usb/bc12/emul_bc12_pi3usb9201.c b/drivers/usb/bc12/emul_bc12_pi3usb9201.c index 6d6842939cd..f798d4d9ac0 100644 --- a/drivers/usb/bc12/emul_bc12_pi3usb9201.c +++ b/drivers/usb/bc12/emul_bc12_pi3usb9201.c @@ -192,7 +192,7 @@ static int pi3usb9201_emul_transfer(const struct emul *target, struct i2c_msg *m return -EIO; } - i2c_dump_msgs("emul", msgs, num_msgs, addr); + i2c_dump_msgs(target->dev, msgs, num_msgs, addr); /* Only single byte register access permitted. Write operations must * consist of 2 write bytes: register offset, register data. Read diff --git a/drivers/usb/common/CMakeLists.txt b/drivers/usb/common/CMakeLists.txt new file mode 100644 index 00000000000..56e4c734ced --- /dev/null +++ b/drivers/usb/common/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_subdirectory_ifdef(CONFIG_HAS_NRFX nrf_usbd_common) diff --git a/drivers/usb/common/Kconfig b/drivers/usb/common/Kconfig new file mode 100644 index 00000000000..7f6a02614b8 --- /dev/null +++ b/drivers/usb/common/Kconfig @@ -0,0 +1,4 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +rsource "nrf_usbd_common/Kconfig" diff --git a/drivers/usb/common/nrf_usbd_common/CMakeLists.txt b/drivers/usb/common/nrf_usbd_common/CMakeLists.txt new file mode 100644 index 00000000000..84952a8e5f8 --- /dev/null +++ b/drivers/usb/common/nrf_usbd_common/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_NRF_USBD_COMMON) + zephyr_library() + + zephyr_include_directories(.) + + zephyr_library_sources(nrf_usbd_common.c) +endif() diff --git a/drivers/usb/common/nrf_usbd_common/Kconfig b/drivers/usb/common/nrf_usbd_common/Kconfig new file mode 100644 index 00000000000..ae8f631fc72 --- /dev/null +++ b/drivers/usb/common/nrf_usbd_common/Kconfig @@ -0,0 +1,20 @@ +# Copyright (c) 2016-2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +module = NRF_USBD_COMMON +module-str = nRF USBD common +source "subsys/logging/Kconfig.template.log_config" + +config NRF_USBD_COMMON + bool "USBD driver" + depends on HAS_NRFX + depends on $(dt_has_compat,$(DT_COMPAT_NORDIC_NRF_USBD)) + +config NRF_USBD_ISO_IN_ZLP + bool "Send ZLP on ISO IN when not ready" + depends on NRF_USBD_COMMON + default y + help + Controls the response of the ISO IN endpoint to an IN token when no + data is ready to be sent. When enabled, ZLP is sent when no data is + ready. When disabled, no response is sent (bus timeout occurs). diff --git a/drivers/usb/common/nrf_usbd_common/nrf_usbd_common.c b/drivers/usb/common/nrf_usbd_common/nrf_usbd_common.c new file mode 100644 index 00000000000..3db193ee2f0 --- /dev/null +++ b/drivers/usb/common/nrf_usbd_common/nrf_usbd_common.c @@ -0,0 +1,1623 @@ +/* + * Copyright (c) 2016 - 2023, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* This file is undergoing transition towards native Zephyr nrf USB driver. */ + +/** @cond INTERNAL_HIDDEN */ + +#include + +#include "nrf_usbd_common.h" +#include "nrf_usbd_common_errata.h" +#include +#include + +#include +LOG_MODULE_REGISTER(nrf_usbd_common, CONFIG_NRF_USBD_COMMON_LOG_LEVEL); + +#define NRF_USBD_COMMON_EPIN_CNT 9 +#define NRF_USBD_COMMON_EPOUT_CNT 9 +#define NRF_USBD_COMMON_EP_NUM(ep) (ep & 0xF) +#define NRF_USBD_COMMON_EP_IS_IN(ep) ((ep & 0x80) == 0x80) +#define NRF_USBD_COMMON_EP_IS_OUT(ep) ((ep & 0x80) == 0) +#define NRF_USBD_COMMON_EP_IS_ISO(ep) ((ep & 0xF) >= 8) + +#ifndef NRF_USBD_COMMON_ISO_DEBUG +/* Also generate information about ISOCHRONOUS events and transfers. + * Turn this off if no ISOCHRONOUS transfers are going to be debugged and this + * option generates a lot of useless messages. + */ +#define NRF_USBD_COMMON_ISO_DEBUG 1 +#endif + +#ifndef NRF_USBD_COMMON_FAILED_TRANSFERS_DEBUG +/* Also generate debug information for failed transfers. + * It might be useful but may generate a lot of useless debug messages + * in some library usages (for example when transfer is generated and the + * result is used to check whatever endpoint was busy. + */ +#define NRF_USBD_COMMON_FAILED_TRANSFERS_DEBUG 1 +#endif + +#ifndef NRF_USBD_COMMON_DMAREQ_PROCESS_DEBUG +/* Generate additional messages that mark the status inside + * @ref usbd_dmareq_process. + * It is useful to debug library internals but may generate a lot of + * useless debug messages. + */ +#define NRF_USBD_COMMON_DMAREQ_PROCESS_DEBUG 1 +#endif + +#ifndef NRF_USBD_COMMON_USE_WORKAROUND_FOR_ANOMALY_211 +/* Anomaly 211 - Device remains in SUSPEND too long when host resumes + * a bus activity (sending SOF packets) without a RESUME condition. + */ +#define NRF_USBD_COMMON_USE_WORKAROUND_FOR_ANOMALY_211 0 +#endif + +/** + * @defgroup nrf_usbd_common_int USB Device driver internal part + * @internal + * @ingroup nrf_usbd_common + * + * This part contains auxiliary internal macros, variables and functions. + * @{ + */ + +/** + * @brief Assert endpoint number validity. + * + * Internal macro to be used during program creation in debug mode. + * Generates assertion if endpoint number is not valid. + * + * @param ep Endpoint number to validity check. + */ +#define NRF_USBD_COMMON_ASSERT_EP_VALID(ep) __ASSERT_NO_MSG( \ + ((NRF_USBD_COMMON_EP_IS_IN(ep) && \ + (NRF_USBD_COMMON_EP_NUM(ep) < NRF_USBD_COMMON_EPIN_CNT)) || \ + (NRF_USBD_COMMON_EP_IS_OUT(ep) && \ + (NRF_USBD_COMMON_EP_NUM(ep) < NRF_USBD_COMMON_EPOUT_CNT)))); + +/** + * @brief Lowest position of bit for IN endpoint. + * + * The first bit position corresponding to IN endpoint. + * @sa ep2bit bit2ep + */ +#define NRF_USBD_COMMON_EPIN_BITPOS_0 0 + +/** + * @brief Lowest position of bit for OUT endpoint. + * + * The first bit position corresponding to OUT endpoint + * @sa ep2bit bit2ep + */ +#define NRF_USBD_COMMON_EPOUT_BITPOS_0 16 + +/** + * @brief Input endpoint bits mask. + */ +#define NRF_USBD_COMMON_EPIN_BIT_MASK (0xFFFFU << NRF_USBD_COMMON_EPIN_BITPOS_0) + +/** + * @brief Output endpoint bits mask. + */ +#define NRF_USBD_COMMON_EPOUT_BIT_MASK (0xFFFFU << NRF_USBD_COMMON_EPOUT_BITPOS_0) + +/** + * @brief Isochronous endpoint bit mask + */ +#define USBD_EPISO_BIT_MASK \ + ((1U << NRF_USBD_COMMON_EP_BITPOS(NRF_USBD_COMMON_EPOUT8)) | \ + (1U << NRF_USBD_COMMON_EP_BITPOS(NRF_USBD_COMMON_EPIN8))) + +/** + * @brief Auxiliary macro to change EP number into bit position. + * + * This macro is used by @ref ep2bit function but also for statically check + * the bitpos values integrity during compilation. + * + * @param[in] ep Endpoint number. + * @return Endpoint bit position. + */ +#define NRF_USBD_COMMON_EP_BITPOS(ep) ((NRF_USBD_COMMON_EP_IS_IN(ep) \ + ? NRF_USBD_COMMON_EPIN_BITPOS_0 : NRF_USBD_COMMON_EPOUT_BITPOS_0) \ + + NRF_USBD_COMMON_EP_NUM(ep)) + +/** + * @brief Helper macro for creating an endpoint transfer event. + * + * @param[in] name Name of the created transfer event variable. + * @param[in] endpoint Endpoint number. + * @param[in] ep_stat Endpoint state to report. + * + * @return Initialized event constant variable. + */ +#define NRF_USBD_COMMON_EP_TRANSFER_EVENT(name, endpont, ep_stat) \ + const nrf_usbd_common_evt_t name = {NRF_USBD_COMMON_EVT_EPTRANSFER, \ + .data = {.eptransfer = {.ep = endpont, .status = ep_stat}}} + +/* Check it the bit positions values match defined DATAEPSTATUS bit positions */ +BUILD_ASSERT( + (NRF_USBD_COMMON_EP_BITPOS(NRF_USBD_COMMON_EPIN1) == USBD_EPDATASTATUS_EPIN1_Pos) && + (NRF_USBD_COMMON_EP_BITPOS(NRF_USBD_COMMON_EPIN2) == USBD_EPDATASTATUS_EPIN2_Pos) && + (NRF_USBD_COMMON_EP_BITPOS(NRF_USBD_COMMON_EPIN3) == USBD_EPDATASTATUS_EPIN3_Pos) && + (NRF_USBD_COMMON_EP_BITPOS(NRF_USBD_COMMON_EPIN4) == USBD_EPDATASTATUS_EPIN4_Pos) && + (NRF_USBD_COMMON_EP_BITPOS(NRF_USBD_COMMON_EPIN5) == USBD_EPDATASTATUS_EPIN5_Pos) && + (NRF_USBD_COMMON_EP_BITPOS(NRF_USBD_COMMON_EPIN6) == USBD_EPDATASTATUS_EPIN6_Pos) && + (NRF_USBD_COMMON_EP_BITPOS(NRF_USBD_COMMON_EPIN7) == USBD_EPDATASTATUS_EPIN7_Pos) && + (NRF_USBD_COMMON_EP_BITPOS(NRF_USBD_COMMON_EPOUT1) == USBD_EPDATASTATUS_EPOUT1_Pos) && + (NRF_USBD_COMMON_EP_BITPOS(NRF_USBD_COMMON_EPOUT2) == USBD_EPDATASTATUS_EPOUT2_Pos) && + (NRF_USBD_COMMON_EP_BITPOS(NRF_USBD_COMMON_EPOUT3) == USBD_EPDATASTATUS_EPOUT3_Pos) && + (NRF_USBD_COMMON_EP_BITPOS(NRF_USBD_COMMON_EPOUT4) == USBD_EPDATASTATUS_EPOUT4_Pos) && + (NRF_USBD_COMMON_EP_BITPOS(NRF_USBD_COMMON_EPOUT5) == USBD_EPDATASTATUS_EPOUT5_Pos) && + (NRF_USBD_COMMON_EP_BITPOS(NRF_USBD_COMMON_EPOUT6) == USBD_EPDATASTATUS_EPOUT6_Pos) && + (NRF_USBD_COMMON_EP_BITPOS(NRF_USBD_COMMON_EPOUT7) == USBD_EPDATASTATUS_EPOUT7_Pos), + "NRF_USBD_COMMON bit positions do not match hardware" +); + +/** + * @brief Current driver state. + */ +static nrfx_drv_state_t m_drv_state = NRFX_DRV_STATE_UNINITIALIZED; + +/** + * @brief Event handler for the driver. + * + * Event handler that would be called on events. + * + * @note Currently it cannot be null if any interrupt is activated. + */ +static nrf_usbd_common_event_handler_t m_event_handler; + +/** + * @brief Detected state of the bus. + * + * Internal state changed in interrupts handling when + * RESUME or SUSPEND event is processed. + * + * Values: + * - true - bus suspended + * - false - ongoing normal communication on the bus + * + * @note This is only the bus state and does not mean that the peripheral is in suspend state. + */ +static volatile bool m_bus_suspend; + +/** + * @brief Direction of last received Setup transfer. + * + * This variable is used to redirect internal setup data event + * into selected endpoint (IN or OUT). + */ +static nrf_usbd_common_ep_t m_last_setup_dir; + +/** + * @brief Mark endpoint readiness for DMA transfer. + * + * Bits in this variable are cleared and set in interrupts. + * 1 means that endpoint is ready for DMA transfer. + * 0 means that DMA transfer cannot be performed on selected endpoint. + */ +static uint32_t m_ep_ready; + +/** + * @brief Mark endpoint with prepared data to transfer by DMA. + * + * This variable can be set in interrupt context or within critical section. + * It would be cleared only from USBD interrupt. + * + * Mask prepared USBD data for transmission. + * It is cleared when no more data to transmit left. + */ +static uint32_t m_ep_dma_waiting; + +/* Semaphore to guard EasyDMA access. + * In USBD there is only one DMA channel working in background, and new transfer + * cannot be started when there is ongoing transfer on any other channel. + */ +static K_SEM_DEFINE(dma_available, 1, 1); + +/* Endpoint on which DMA was started. */ +static nrf_usbd_common_ep_t dma_ep; + +/** + * @brief Tracks whether total bytes transferred by DMA is even or odd. + */ +static uint8_t m_dma_odd; + +/** + * @brief First time enabling after reset. Used in nRF52 errata 223. + */ +static bool m_first_enable = true; + +/** + * @brief The structure that would hold transfer configuration to every endpoint + * + * The structure that holds all the data required by the endpoint to proceed + * with LIST functionality and generate quick callback directly when data + * buffer is ready. + */ +typedef struct { + nrf_usbd_common_transfer_t transfer_state; + bool more_transactions; + /** Number of transferred bytes in the current transfer. */ + size_t transfer_cnt; + /** Configured endpoint size. */ + uint16_t max_packet_size; + /** NRFX_SUCCESS or error code, never NRFX_ERROR_BUSY - this one is calculated. */ + nrf_usbd_common_ep_status_t status; +} usbd_ep_state_t; + +/** + * @brief The array of transfer configurations for the endpoints. + * + * The status of the transfer on each endpoint. + */ +static struct { + usbd_ep_state_t ep_out[NRF_USBD_COMMON_EPOUT_CNT]; /*!< Status for OUT endpoints. */ + usbd_ep_state_t ep_in[NRF_USBD_COMMON_EPIN_CNT]; /*!< Status for IN endpoints. */ +} m_ep_state; + +#define NRF_USBD_COMMON_FEEDER_BUFFER_SIZE NRF_USBD_COMMON_EPSIZE + +/** + * @brief Buffer used to send data directly from FLASH. + * + * This is internal buffer that would be used to emulate the possibility + * to transfer data directly from FLASH. + * We do not have to care about the source of data when calling transfer functions. + * + * We do not need more buffers that one, because only one transfer can be pending + * at once. + */ +static uint32_t m_tx_buffer[NRFX_CEIL_DIV(NRF_USBD_COMMON_FEEDER_BUFFER_SIZE, sizeof(uint32_t))]; + +/* Early declaration. Documentation above definition. */ +static void usbd_dmareq_process(void); +static inline void usbd_int_rise(void); +static void nrf_usbd_common_stop(void); + +/* Get EasyDMA end event address for given endpoint */ +static volatile uint32_t *usbd_ep_to_endevent(nrf_usbd_common_ep_t ep) +{ + int ep_in = NRF_USBD_COMMON_EP_IS_IN(ep); + int ep_num = NRF_USBD_COMMON_EP_NUM(ep); + + NRF_USBD_COMMON_ASSERT_EP_VALID(ep); + + if (!NRF_USBD_COMMON_EP_IS_ISO(ep_num)) { + if (ep_in) { + return &NRF_USBD->EVENTS_ENDEPIN[ep_num]; + } else { + return &NRF_USBD->EVENTS_ENDEPOUT[ep_num]; + } + } + + return ep_in ? &NRF_USBD->EVENTS_ENDISOIN : &NRF_USBD->EVENTS_ENDISOOUT; +} + +/* Return number of bytes last transferred by EasyDMA on given endpoint */ +static uint32_t usbd_ep_amount_get(nrf_usbd_common_ep_t ep) +{ + int ep_in = NRF_USBD_COMMON_EP_IS_IN(ep); + int ep_num = NRF_USBD_COMMON_EP_NUM(ep); + + NRF_USBD_COMMON_ASSERT_EP_VALID(ep); + + if (!NRF_USBD_COMMON_EP_IS_ISO(ep_num)) { + if (ep_in) { + return NRF_USBD->EPIN[ep_num].AMOUNT; + } else { + return NRF_USBD->EPOUT[ep_num].AMOUNT; + } + } + + return ep_in ? NRF_USBD->ISOIN.AMOUNT : NRF_USBD->ISOOUT.AMOUNT; +} + +/* Start EasyDMA on given endpoint */ +static void usbd_ep_dma_start(nrf_usbd_common_ep_t ep, uint32_t addr, size_t len) +{ + int ep_in = NRF_USBD_COMMON_EP_IS_IN(ep); + int ep_num = NRF_USBD_COMMON_EP_NUM(ep); + + NRF_USBD_COMMON_ASSERT_EP_VALID(ep); + + if (!NRF_USBD_COMMON_EP_IS_ISO(ep_num)) { + if (ep_in) { + NRF_USBD->EPIN[ep_num].PTR = addr; + NRF_USBD->EPIN[ep_num].MAXCNT = len; + NRF_USBD->TASKS_STARTEPIN[ep_num] = 1; + } else { + NRF_USBD->EPOUT[ep_num].PTR = addr; + NRF_USBD->EPOUT[ep_num].MAXCNT = len; + NRF_USBD->TASKS_STARTEPOUT[ep_num] = 1; + } + } else if (ep_in) { + NRF_USBD->ISOIN.PTR = addr; + NRF_USBD->ISOIN.MAXCNT = len; + NRF_USBD->TASKS_STARTISOIN = 1; + } else { + NRF_USBD->ISOOUT.PTR = addr; + NRF_USBD->ISOOUT.MAXCNT = len; + NRF_USBD->TASKS_STARTISOOUT = 1; + } +} + +static bool nrf_usbd_common_consumer(nrf_usbd_common_ep_transfer_t *p_next, + nrf_usbd_common_transfer_t *p_transfer, + size_t ep_size, size_t data_size) +{ + __ASSERT_NO_MSG(ep_size >= data_size); + __ASSERT_NO_MSG((p_transfer->p_data.rx == NULL) || nrfx_is_in_ram(p_transfer->p_data.rx)); + + size_t size = p_transfer->size; + + if (size < data_size) { + LOG_DBG("consumer: buffer too small: r: %u, l: %u", data_size, size); + /* Buffer size to small */ + p_next->size = 0; + p_next->p_data = p_transfer->p_data; + } else { + p_next->size = data_size; + p_next->p_data = p_transfer->p_data; + size -= data_size; + p_transfer->size = size; + p_transfer->p_data.addr += data_size; + } + return (ep_size == data_size) && (size != 0); +} + +static bool nrf_usbd_common_feeder(nrf_usbd_common_ep_transfer_t *p_next, + nrf_usbd_common_transfer_t *p_transfer, + size_t ep_size) +{ + size_t tx_size = p_transfer->size; + + if (tx_size > ep_size) { + tx_size = ep_size; + } + + if (!nrfx_is_in_ram(p_transfer->p_data.tx)) { + __ASSERT_NO_MSG(tx_size <= NRF_USBD_COMMON_FEEDER_BUFFER_SIZE); + memcpy(m_tx_buffer, (p_transfer->p_data.tx), tx_size); + p_next->p_data.tx = m_tx_buffer; + } else { + p_next->p_data = p_transfer->p_data; + } + + p_next->size = tx_size; + + p_transfer->size -= tx_size; + p_transfer->p_data.addr += tx_size; + + if (p_transfer->flags & NRF_USBD_COMMON_TRANSFER_ZLP_FLAG) { + return (tx_size != 0); + } else { + return (p_transfer->size != 0); + } +} + +/** + * @brief Change Driver endpoint number to HAL endpoint number. + * + * @param ep Driver endpoint identifier. + * + * @return Endpoint identifier in HAL. + * + * @sa nrf_usbd_common_ep_from_hal + */ +static inline uint8_t ep_to_hal(nrf_usbd_common_ep_t ep) +{ + NRF_USBD_COMMON_ASSERT_EP_VALID(ep); + return (uint8_t)ep; +} + +/** + * @brief Access selected endpoint state structure. + * + * Function used to change or just read the state of selected endpoint. + * It is used for internal transmission state. + * + * @param ep Endpoint number. + */ +static inline usbd_ep_state_t *ep_state_access(nrf_usbd_common_ep_t ep) +{ + NRF_USBD_COMMON_ASSERT_EP_VALID(ep); + return ((NRF_USBD_COMMON_EP_IS_IN(ep) ? m_ep_state.ep_in : m_ep_state.ep_out) + + NRF_USBD_COMMON_EP_NUM(ep)); +} + +/** + * @brief Change endpoint number to bit position. + * + * Bit positions are defined the same way as they are placed in DATAEPSTATUS register, + * but bits for endpoint 0 are included. + * + * @param ep Endpoint number. + * + * @return Bit position related to the given endpoint number. + * + * @sa bit2ep + */ +static inline uint8_t ep2bit(nrf_usbd_common_ep_t ep) +{ + NRF_USBD_COMMON_ASSERT_EP_VALID(ep); + return NRF_USBD_COMMON_EP_BITPOS(ep); +} + +/** + * @brief Change bit position to endpoint number. + * + * @param bitpos Bit position. + * + * @return Endpoint number corresponding to given bit position. + * + * @sa ep2bit + */ +static inline nrf_usbd_common_ep_t bit2ep(uint8_t bitpos) +{ + BUILD_ASSERT(NRF_USBD_COMMON_EPOUT_BITPOS_0 > NRF_USBD_COMMON_EPIN_BITPOS_0, + "OUT endpoint bits should be higher than IN endpoint bits"); + return (nrf_usbd_common_ep_t)((bitpos >= NRF_USBD_COMMON_EPOUT_BITPOS_0) + ? NRF_USBD_COMMON_EPOUT(bitpos - NRF_USBD_COMMON_EPOUT_BITPOS_0) + : NRF_USBD_COMMON_EPIN(bitpos)); +} + +/** + * @brief Mark that EasyDMA is working. + * + * Internal function to set the flag informing about EasyDMA transfer pending. + * This function is called always just after the EasyDMA transfer is started. + */ +static inline void usbd_dma_pending_set(void) +{ + if (nrf_usbd_common_errata_199()) { + *((volatile uint32_t *)0x40027C1C) = 0x00000082; + } +} + +/** + * @brief Mark that EasyDMA is free. + * + * Internal function to clear the flag informing about EasyDMA transfer pending. + * This function is called always just after the finished EasyDMA transfer is detected. + */ +static inline void usbd_dma_pending_clear(void) +{ + if (nrf_usbd_common_errata_199()) { + *((volatile uint32_t *)0x40027C1C) = 0x00000000; + } +} + +/** + * @brief Abort pending transfer on selected endpoint. + * + * @param ep Endpoint number. + * + * @note + * This function locks interrupts that may be costly. + * It is good idea to test if the endpoint is still busy before calling this function: + * @code + (m_ep_dma_waiting & (1U << ep2bit(ep))) + * @endcode + * This function would check it again, but it makes it inside critical section. + */ +static inline void usbd_ep_abort(nrf_usbd_common_ep_t ep) +{ + unsigned int irq_lock_key = irq_lock(); + usbd_ep_state_t *p_state = ep_state_access(ep); + + if (NRF_USBD_COMMON_EP_IS_OUT(ep)) { + /* Host -> Device */ + if ((~m_ep_dma_waiting) & (1U << ep2bit(ep))) { + /* If the bit in m_ep_dma_waiting in cleared - nothing would be + * processed inside transfer processing + */ + nrf_usbd_common_transfer_out_drop(ep); + } else { + p_state->more_transactions = false; + m_ep_dma_waiting &= ~(1U << ep2bit(ep)); + m_ep_ready &= ~(1U << ep2bit(ep)); + } + /* Aborted */ + p_state->status = NRF_USBD_COMMON_EP_ABORTED; + } else { + if (!NRF_USBD_COMMON_EP_IS_ISO(ep)) { + /* Workaround: Disarm the endpoint if there is any data buffered. */ + if (ep != NRF_USBD_COMMON_EPIN0) { + *((volatile uint32_t *)((uint32_t)(NRF_USBD) + 0x800)) = + 0x7B6 + (2u * (NRF_USBD_COMMON_EP_NUM(ep) - 1)); + uint8_t temp = + *((volatile uint32_t *)((uint32_t)(NRF_USBD) + 0x804)); + temp |= (1U << 1); + *((volatile uint32_t *)((uint32_t)(NRF_USBD) + 0x804)) |= temp; + (void)(*((volatile uint32_t *)((uint32_t)(NRF_USBD) + 0x804))); + } else { + *((volatile uint32_t *)((uint32_t)(NRF_USBD) + 0x800)) = 0x7B4; + uint8_t temp = + *((volatile uint32_t *)((uint32_t)(NRF_USBD) + 0x804)); + temp |= (1U << 2); + *((volatile uint32_t *)((uint32_t)(NRF_USBD) + 0x804)) |= temp; + (void)(*((volatile uint32_t *)((uint32_t)(NRF_USBD) + 0x804))); + } + } + if ((m_ep_dma_waiting | (~m_ep_ready)) & (1U << ep2bit(ep))) { + /* Device -> Host */ + m_ep_dma_waiting &= ~(1U << ep2bit(ep)); + m_ep_ready |= 1U << ep2bit(ep); + + p_state->more_transactions = false; + p_state->status = NRF_USBD_COMMON_EP_ABORTED; + NRF_USBD_COMMON_EP_TRANSFER_EVENT(evt, ep, NRF_USBD_COMMON_EP_ABORTED); + m_event_handler(&evt); + } + } + + irq_unlock(irq_lock_key); +} + +void nrf_usbd_common_ep_abort(nrf_usbd_common_ep_t ep) +{ + /* Only abort if there is no active DMA */ + k_sem_take(&dma_available, K_FOREVER); + usbd_ep_abort(ep); + k_sem_give(&dma_available); + + /* This function was holding DMA semaphore and could potentially prevent + * next DMA from executing. Fire IRQ handler to check if any DMA needs + * to be started. + */ + usbd_int_rise(); +} + +/** + * @brief Abort all pending endpoints. + * + * Function aborts all pending endpoint transfers. + */ +static void usbd_ep_abort_all(void) +{ + uint32_t ep_waiting = m_ep_dma_waiting | (m_ep_ready & NRF_USBD_COMMON_EPOUT_BIT_MASK); + + while (ep_waiting != 0) { + uint8_t bitpos = NRF_CTZ(ep_waiting); + + if (!NRF_USBD_COMMON_EP_IS_ISO(bit2ep(bitpos))) { + usbd_ep_abort(bit2ep(bitpos)); + } + ep_waiting &= ~(1U << bitpos); + } + + m_ep_ready = (((1U << NRF_USBD_COMMON_EPIN_CNT) - 1U) << NRF_USBD_COMMON_EPIN_BITPOS_0); +} + +/** + * @brief Force the USBD interrupt into pending state. + * + * This function is used to force USBD interrupt to be processed right now. + * It makes it possible to process all EasyDMA access on one thread priority level. + */ +static inline void usbd_int_rise(void) +{ + NVIC_SetPendingIRQ(USBD_IRQn); +} + +/** + * @name USBD interrupt runtimes. + * + * Interrupt runtimes that would be vectorized using @ref m_isr. + * @{ + */ + +static void ev_usbreset_handler(void) +{ + m_bus_suspend = false; + m_last_setup_dir = NRF_USBD_COMMON_EPOUT0; + + const nrf_usbd_common_evt_t evt = {.type = NRF_USBD_COMMON_EVT_RESET}; + + m_event_handler(&evt); +} + +static void nrf_usbd_dma_finished(nrf_usbd_common_ep_t ep) +{ + /* DMA finished, track if total bytes transferred is even or odd */ + m_dma_odd ^= usbd_ep_amount_get(ep) & 1; + usbd_dma_pending_clear(); + k_sem_give(&dma_available); + + usbd_ep_state_t *p_state = ep_state_access(ep); + + if (p_state->status == NRF_USBD_COMMON_EP_ABORTED) { + /* Clear transfer information just in case */ + m_ep_dma_waiting &= ~(1U << ep2bit(ep)); + } else if (!p_state->more_transactions) { + m_ep_dma_waiting &= ~(1U << ep2bit(ep)); + + if (NRF_USBD_COMMON_EP_IS_OUT(ep) || (ep == NRF_USBD_COMMON_EPIN8)) { + /* Send event to the user - for an ISO IN or any OUT endpoint, + * the whole transfer is finished in this moment + */ + NRF_USBD_COMMON_EP_TRANSFER_EVENT(evt, ep, NRF_USBD_COMMON_EP_OK); + m_event_handler(&evt); + } + } else if (ep == NRF_USBD_COMMON_EPOUT0) { + nrf_usbd_common_setup_data_clear(); + } +} + +static void ev_sof_handler(void) +{ + nrf_usbd_common_evt_t evt = { + NRF_USBD_COMMON_EVT_SOF, + .data = {.sof = {.framecnt = (uint16_t)NRF_USBD->FRAMECNTR}}}; + + /* Process isochronous endpoints */ + uint32_t iso_ready_mask = (1U << ep2bit(NRF_USBD_COMMON_EPIN8)); + + /* SIZE.ISOOUT is 0 only when no packet was received at all */ + if (NRF_USBD->SIZE.ISOOUT) { + iso_ready_mask |= (1U << ep2bit(NRF_USBD_COMMON_EPOUT8)); + } + m_ep_ready |= iso_ready_mask; + + m_event_handler(&evt); +} + +/** + * @brief React on data transfer finished. + * + * Auxiliary internal function. + * @param ep Endpoint number. + * @param bitpos Bit position for selected endpoint number. + */ +static void usbd_ep_data_handler(nrf_usbd_common_ep_t ep, uint8_t bitpos) +{ + LOG_DBG("USBD event: EndpointData: %x", ep); + /* Mark endpoint ready for next DMA access */ + m_ep_ready |= (1U << bitpos); + + if (NRF_USBD_COMMON_EP_IS_IN(ep)) { + /* IN endpoint (Device -> Host) */ + if (0 == (m_ep_dma_waiting & (1U << bitpos))) { + LOG_DBG("USBD event: EndpointData: In finished"); + /* No more data to be send - transmission finished */ + NRF_USBD_COMMON_EP_TRANSFER_EVENT(evt, ep, NRF_USBD_COMMON_EP_OK); + m_event_handler(&evt); + } + } else { + /* OUT endpoint (Host -> Device) */ + if (0 == (m_ep_dma_waiting & (1U << bitpos))) { + LOG_DBG("USBD event: EndpointData: Out waiting"); + /* No buffer prepared - send event to the application */ + NRF_USBD_COMMON_EP_TRANSFER_EVENT(evt, ep, NRF_USBD_COMMON_EP_WAITING); + m_event_handler(&evt); + } + } +} + +static void ev_setup_handler(void) +{ + LOG_DBG("USBD event: Setup (rt:%.2x r:%.2x v:%.4x i:%.4x l:%u )", + NRF_USBD->BMREQUESTTYPE, NRF_USBD->BREQUEST, + NRF_USBD->WVALUEL | (NRF_USBD->WVALUEH << 8), + NRF_USBD->WINDEXL | (NRF_USBD->WINDEXH << 8), + NRF_USBD->WLENGTHL | (NRF_USBD->WLENGTHH << 8)); + uint8_t bmRequestType = NRF_USBD->BMREQUESTTYPE; + + m_last_setup_dir = + ((bmRequestType & USBD_BMREQUESTTYPE_DIRECTION_Msk) == + (USBD_BMREQUESTTYPE_DIRECTION_HostToDevice << USBD_BMREQUESTTYPE_DIRECTION_Pos)) + ? NRF_USBD_COMMON_EPOUT0 + : NRF_USBD_COMMON_EPIN0; + + m_ep_dma_waiting &= ~((1U << ep2bit(NRF_USBD_COMMON_EPOUT0)) | + (1U << ep2bit(NRF_USBD_COMMON_EPIN0))); + m_ep_ready &= ~(1U << ep2bit(NRF_USBD_COMMON_EPOUT0)); + m_ep_ready |= 1U << ep2bit(NRF_USBD_COMMON_EPIN0); + + const nrf_usbd_common_evt_t evt = {.type = NRF_USBD_COMMON_EVT_SETUP}; + + m_event_handler(&evt); +} + +static void ev_usbevent_handler(void) +{ + uint32_t event = NRF_USBD->EVENTCAUSE; + + /* Clear handled events */ + NRF_USBD->EVENTCAUSE = event; + + if (event & USBD_EVENTCAUSE_ISOOUTCRC_Msk) { + LOG_DBG("USBD event: ISOOUTCRC"); + /* Currently no support */ + } + if (event & USBD_EVENTCAUSE_SUSPEND_Msk) { + LOG_DBG("USBD event: SUSPEND"); + m_bus_suspend = true; + const nrf_usbd_common_evt_t evt = {.type = NRF_USBD_COMMON_EVT_SUSPEND}; + + m_event_handler(&evt); + } + if (event & USBD_EVENTCAUSE_RESUME_Msk) { + LOG_DBG("USBD event: RESUME"); + m_bus_suspend = false; + const nrf_usbd_common_evt_t evt = {.type = NRF_USBD_COMMON_EVT_RESUME}; + + m_event_handler(&evt); + } + if (event & USBD_EVENTCAUSE_USBWUALLOWED_Msk) { + LOG_DBG("USBD event: WUREQ (%s)", m_bus_suspend ? "In Suspend" : "Active"); + if (m_bus_suspend) { + __ASSERT_NO_MSG(!nrf_usbd_common_suspend_check()); + m_bus_suspend = false; + + NRF_USBD->DPDMVALUE = USBD_DPDMVALUE_STATE_Resume + << USBD_DPDMVALUE_STATE_Pos; + NRF_USBD->TASKS_DPDMDRIVE = 1; + + const nrf_usbd_common_evt_t evt = {.type = NRF_USBD_COMMON_EVT_WUREQ}; + + m_event_handler(&evt); + } + } +} + +static void ev_epdata_handler(uint32_t dataepstatus) +{ + LOG_DBG("USBD event: EndpointEPStatus: %x", dataepstatus); + + /* All finished endpoint have to be marked as busy */ + while (dataepstatus) { + uint8_t bitpos = NRF_CTZ(dataepstatus); + nrf_usbd_common_ep_t ep = bit2ep(bitpos); + + dataepstatus &= ~(1UL << bitpos); + + (void)(usbd_ep_data_handler(ep, bitpos)); + } +} + +/** + * @brief Function to select the endpoint to start. + * + * Function that realizes algorithm to schedule right channel for EasyDMA transfer. + * It gets a variable with flags for the endpoints currently requiring transfer. + * + * @param[in] req Bit flags for channels currently requiring transfer. + * Bits 0...8 used for IN endpoints. + * Bits 16...24 used for OUT endpoints. + * @note + * This function would be never called with 0 as a @c req argument. + * @return The bit number of the endpoint that should be processed now. + */ +static uint8_t usbd_dma_scheduler_algorithm(uint32_t req) +{ + /* Only prioritized scheduling mode is supported. */ + return NRF_CTZ(req); +} + +/** + * @brief Get the size of isochronous endpoint. + * + * The size of isochronous endpoint is configurable. + * This function returns the size of isochronous buffer taking into account + * current configuration. + * + * @param[in] ep Endpoint number. + * + * @return The size of endpoint buffer. + */ +static inline size_t usbd_ep_iso_capacity(nrf_usbd_common_ep_t ep) +{ + (void)ep; + + if (NRF_USBD->ISOSPLIT == USBD_ISOSPLIT_SPLIT_HalfIN << USBD_ISOSPLIT_SPLIT_Pos) { + return NRF_USBD_COMMON_ISOSIZE / 2; + } + return NRF_USBD_COMMON_ISOSIZE; +} + +/** + * @brief Process all DMA requests. + * + * Function that have to be called from USBD interrupt handler. + * It have to be called when all the interrupts connected with endpoints transfer + * and DMA transfer are already handled. + */ +static void usbd_dmareq_process(void) +{ + if ((m_ep_dma_waiting & m_ep_ready) && + (k_sem_take(&dma_available, K_NO_WAIT) == 0)) { + uint32_t req; + + while (0 != (req = m_ep_dma_waiting & m_ep_ready)) { + uint8_t pos; + + if (NRFX_USBD_CONFIG_DMASCHEDULER_ISO_BOOST && + ((req & USBD_EPISO_BIT_MASK) != 0)) { + pos = usbd_dma_scheduler_algorithm(req & USBD_EPISO_BIT_MASK); + } else { + pos = usbd_dma_scheduler_algorithm(req); + } + nrf_usbd_common_ep_t ep = bit2ep(pos); + usbd_ep_state_t *p_state = ep_state_access(ep); + + nrf_usbd_common_ep_transfer_t transfer; + bool continue_transfer; + + __ASSERT_NO_MSG(p_state->more_transactions); + + if (NRF_USBD_COMMON_EP_IS_IN(ep)) { + /* Device -> Host */ + continue_transfer = nrf_usbd_common_feeder( + &transfer, &p_state->transfer_state, + p_state->max_packet_size); + } else { + /* Host -> Device */ + const size_t rx_size = nrf_usbd_common_epout_size_get(ep); + + continue_transfer = nrf_usbd_common_consumer( + &transfer, &p_state->transfer_state, + p_state->max_packet_size, rx_size); + + if (transfer.p_data.rx == NULL) { + /* Dropping transfer - allow processing */ + __ASSERT_NO_MSG(transfer.size == 0); + } else if (transfer.size < rx_size) { + LOG_DBG("Endpoint %x overload (r: %u, e: %u)", ep, + rx_size, transfer.size); + p_state->status = NRF_USBD_COMMON_EP_OVERLOAD; + m_ep_dma_waiting &= ~(1U << pos); + NRF_USBD_COMMON_EP_TRANSFER_EVENT(evt, ep, + NRF_USBD_COMMON_EP_OVERLOAD); + m_event_handler(&evt); + /* This endpoint will not be transmitted now, repeat the + * loop + */ + continue; + } else { + /* Nothing to do - only check integrity if assertions are + * enabled + */ + __ASSERT_NO_MSG(transfer.size == rx_size); + } + } + + if (!continue_transfer) { + p_state->more_transactions = false; + } + + usbd_dma_pending_set(); + m_ep_ready &= ~(1U << pos); + if (NRF_USBD_COMMON_ISO_DEBUG || (!NRF_USBD_COMMON_EP_IS_ISO(ep))) { + LOG_DBG("USB DMA process: Starting transfer on EP: %x, size: %u", + ep, transfer.size); + } + /* Update number of currently transferred bytes */ + p_state->transfer_cnt += transfer.size; + /* Start transfer to the endpoint buffer */ + dma_ep = ep; + usbd_ep_dma_start(ep, transfer.p_data.addr, transfer.size); + + /* Transfer started - exit the loop */ + return; + } + k_sem_give(&dma_available); + } else { + if (NRF_USBD_COMMON_DMAREQ_PROCESS_DEBUG) { + LOG_DBG("USB DMA process - EasyDMA busy"); + } + } +} + +/** + * @brief Begin errata 171. + */ +static inline void usbd_errata_171_begin(void) +{ + unsigned int irq_lock_key = irq_lock(); + + if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000) { + *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; + *((volatile uint32_t *)(0x4006EC14)) = 0x000000C0; + *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; + } else { + *((volatile uint32_t *)(0x4006EC14)) = 0x000000C0; + } + + irq_unlock(irq_lock_key); +} + +/** + * @brief End errata 171. + */ +static inline void usbd_errata_171_end(void) +{ + unsigned int irq_lock_key = irq_lock(); + + if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000) { + *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; + *((volatile uint32_t *)(0x4006EC14)) = 0x00000000; + *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; + } else { + *((volatile uint32_t *)(0x4006EC14)) = 0x00000000; + } + + irq_unlock(irq_lock_key); +} + +/** + * @brief Begin erratas 187 and 211. + */ +static inline void usbd_errata_187_211_begin(void) +{ + unsigned int irq_lock_key = irq_lock(); + + if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000) { + *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; + *((volatile uint32_t *)(0x4006ED14)) = 0x00000003; + *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; + } else { + *((volatile uint32_t *)(0x4006ED14)) = 0x00000003; + } + + irq_unlock(irq_lock_key); +} + +/** + * @brief End erratas 187 and 211. + */ +static inline void usbd_errata_187_211_end(void) +{ + unsigned int irq_lock_key = irq_lock(); + + if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000) { + *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; + *((volatile uint32_t *)(0x4006ED14)) = 0x00000000; + *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; + } else { + *((volatile uint32_t *)(0x4006ED14)) = 0x00000000; + } + + irq_unlock(irq_lock_key); +} + +/** + * @brief Enable USBD peripheral. + */ +static void usbd_enable(void) +{ + if (nrf_usbd_common_errata_187()) { + usbd_errata_187_211_begin(); + } + + if (nrf_usbd_common_errata_171()) { + usbd_errata_171_begin(); + } + + /* Enable the peripheral */ + NRF_USBD->ENABLE = 1; + + /* Waiting for peripheral to enable, this should take a few us */ + while ((NRF_USBD->EVENTCAUSE & USBD_EVENTCAUSE_READY_Msk) == 0) { + } + NRF_USBD->EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk; + + if (nrf_usbd_common_errata_171()) { + usbd_errata_171_end(); + } + + if (nrf_usbd_common_errata_187()) { + usbd_errata_187_211_end(); + } +} +/** @} */ + +/** + * @name Interrupt handlers + * + * @{ + */ +void nrf_usbd_common_irq_handler(void) +{ + volatile uint32_t *dma_endevent; + uint32_t epdatastatus = 0; + + /* Clear EPDATA event and only then get and clear EPDATASTATUS to make + * sure we don't miss any event. + */ + if (NRF_USBD->EVENTS_EPDATA) { + NRF_USBD->EVENTS_EPDATA = 0; + epdatastatus = NRF_USBD->EPDATASTATUS; + NRF_USBD->EPDATASTATUS = epdatastatus; + } + + /* Use common variable to store EP0DATADONE processing needed flag */ + if (NRF_USBD->EVENTS_EP0DATADONE) { + NRF_USBD->EVENTS_EP0DATADONE = 0; + epdatastatus |= BIT(ep2bit(m_last_setup_dir)); + } + + /* Check DMA end event only for last enabled DMA channel. Other channels + * cannot be active and there's no harm in rechecking the event multiple + * times (it is not a problem to check it even if DMA is not active). + * + * It is important to check DMA and handle DMA finished event before + * handling acknowledged data transfer bits (epdatastatus) to avoid + * a race condition between interrupt handler and host IN token. + */ + dma_endevent = usbd_ep_to_endevent(dma_ep); + if (*dma_endevent) { + *dma_endevent = 0; + nrf_usbd_dma_finished(dma_ep); + } + + /* Process acknowledged transfers so we can prepare next DMA (if any) */ + ev_epdata_handler(epdatastatus); + + if (NRF_USBD->EVENTS_USBRESET) { + NRF_USBD->EVENTS_USBRESET = 0; + ev_usbreset_handler(); + } + + /* Always check and clear SOF but call handler only if SOF interrupt + * is actually enabled. + */ + if (NRF_USBD->EVENTS_SOF) { + NRF_USBD->EVENTS_SOF = 0; + if (NRF_USBD->INTENSET & USBD_INTEN_SOF_Msk) { + ev_sof_handler(); + } + } + + if (NRF_USBD->EVENTS_USBEVENT) { + NRF_USBD->EVENTS_USBEVENT = 0; + ev_usbevent_handler(); + } + + /* Handle SETUP only if there is no active DMA on EP0 */ + if (unlikely(NRF_USBD->EVENTS_EP0SETUP) && + (k_sem_count_get(&dma_available) || + (dma_ep != NRF_USBD_COMMON_EPIN0 && dma_ep != NRF_USBD_COMMON_EPOUT0))) { + NRF_USBD->EVENTS_EP0SETUP = 0; + ev_setup_handler(); + } + + usbd_dmareq_process(); +} + +/** @} */ +/** @} */ + +nrfx_err_t nrf_usbd_common_init(nrf_usbd_common_event_handler_t event_handler) +{ + __ASSERT_NO_MSG(event_handler); + + if (m_drv_state != NRFX_DRV_STATE_UNINITIALIZED) { + return NRFX_ERROR_INVALID_STATE; + } + + m_event_handler = event_handler; + m_drv_state = NRFX_DRV_STATE_INITIALIZED; + + uint8_t n; + + for (n = 0; n < NRF_USBD_COMMON_EPIN_CNT; ++n) { + nrf_usbd_common_ep_t ep = NRF_USBD_COMMON_EPIN(n); + + nrf_usbd_common_ep_max_packet_size_set(ep, NRF_USBD_COMMON_EP_IS_ISO(ep) ? + (NRF_USBD_COMMON_ISOSIZE / 2) : NRF_USBD_COMMON_EPSIZE); + usbd_ep_state_t *p_state = ep_state_access(ep); + + p_state->status = NRF_USBD_COMMON_EP_OK; + p_state->more_transactions = false; + p_state->transfer_cnt = 0; + } + for (n = 0; n < NRF_USBD_COMMON_EPOUT_CNT; ++n) { + nrf_usbd_common_ep_t ep = NRF_USBD_COMMON_EPOUT(n); + + nrf_usbd_common_ep_max_packet_size_set(ep, NRF_USBD_COMMON_EP_IS_ISO(ep) ? + (NRF_USBD_COMMON_ISOSIZE / 2) : NRF_USBD_COMMON_EPSIZE); + usbd_ep_state_t *p_state = ep_state_access(ep); + + p_state->status = NRF_USBD_COMMON_EP_OK; + p_state->more_transactions = false; + p_state->transfer_cnt = 0; + } + + return NRFX_SUCCESS; +} + +void nrf_usbd_common_uninit(void) +{ + __ASSERT_NO_MSG(m_drv_state == NRFX_DRV_STATE_INITIALIZED); + + m_event_handler = NULL; + m_drv_state = NRFX_DRV_STATE_UNINITIALIZED; +} + +void nrf_usbd_common_enable(void) +{ + __ASSERT_NO_MSG(m_drv_state == NRFX_DRV_STATE_INITIALIZED); + + /* Prepare for READY event receiving */ + NRF_USBD->EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk; + + usbd_enable(); + + if (nrf_usbd_common_errata_223() && m_first_enable) { + NRF_USBD->ENABLE = 0; + + usbd_enable(); + + m_first_enable = false; + } + +#if NRF_USBD_COMMON_USE_WORKAROUND_FOR_ANOMALY_211 + if (nrf_usbd_common_errata_187() || nrf_usbd_common_errata_211()) +#else + if (nrf_usbd_common_errata_187()) +#endif + { + usbd_errata_187_211_begin(); + } + + if (nrf_usbd_common_errata_166()) { + *((volatile uint32_t *)((uint32_t)(NRF_USBD) + 0x800)) = 0x7E3; + *((volatile uint32_t *)((uint32_t)(NRF_USBD) + 0x804)) = 0x40; + __ISB(); + __DSB(); + } + + NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN << USBD_ISOSPLIT_SPLIT_Pos; + + if (IS_ENABLED(CONFIG_NRF_USBD_ISO_IN_ZLP)) { + NRF_USBD->ISOINCONFIG = USBD_ISOINCONFIG_RESPONSE_ZeroData + << USBD_ISOINCONFIG_RESPONSE_Pos; + } else { + NRF_USBD->ISOINCONFIG = USBD_ISOINCONFIG_RESPONSE_NoResp + << USBD_ISOINCONFIG_RESPONSE_Pos; + } + + m_ep_ready = (((1U << NRF_USBD_COMMON_EPIN_CNT) - 1U) << NRF_USBD_COMMON_EPIN_BITPOS_0); + m_ep_dma_waiting = 0; + m_dma_odd = 0; + __ASSERT_NO_MSG(k_sem_count_get(&dma_available) == 1); + usbd_dma_pending_clear(); + m_last_setup_dir = NRF_USBD_COMMON_EPOUT0; + + m_drv_state = NRFX_DRV_STATE_POWERED_ON; + +#if NRF_USBD_COMMON_USE_WORKAROUND_FOR_ANOMALY_211 + if (nrf_usbd_common_errata_187() && !nrf_usbd_common_errata_211()) +#else + if (nrf_usbd_common_errata_187()) +#endif + { + usbd_errata_187_211_end(); + } +} + +void nrf_usbd_common_disable(void) +{ + __ASSERT_NO_MSG(m_drv_state != NRFX_DRV_STATE_UNINITIALIZED); + + /* Make sure DMA is not active */ + k_sem_take(&dma_available, K_FOREVER); + + /* Stop just in case */ + nrf_usbd_common_stop(); + + /* Disable all parts */ + if (m_dma_odd) { + /* Prevent invalid bus request after next USBD enable by ensuring + * that total number of bytes transferred by DMA is even. + */ + NRF_USBD->EVENTS_ENDEPIN[0] = 0; + usbd_ep_dma_start(NRF_USBD_COMMON_EPIN0, (uint32_t)&m_dma_odd, 1); + while (!NRF_USBD->EVENTS_ENDEPIN[0]) { + } + NRF_USBD->EVENTS_ENDEPIN[0] = 0; + m_dma_odd = 0; + } + NRF_USBD->ENABLE = 0; + usbd_dma_pending_clear(); + k_sem_give(&dma_available); + m_drv_state = NRFX_DRV_STATE_INITIALIZED; + +#if NRF_USBD_COMMON_USE_WORKAROUND_FOR_ANOMALY_211 + if (nrf_usbd_common_errata_211()) { + usbd_errata_187_211_end(); + } +#endif +} + +void nrf_usbd_common_start(bool enable_sof) +{ + __ASSERT_NO_MSG(m_drv_state == NRFX_DRV_STATE_POWERED_ON); + m_bus_suspend = false; + + uint32_t int_mask = USBD_INTEN_USBRESET_Msk | USBD_INTEN_ENDEPIN0_Msk | + USBD_INTEN_ENDEPIN1_Msk | USBD_INTEN_ENDEPIN2_Msk | + USBD_INTEN_ENDEPIN3_Msk | USBD_INTEN_ENDEPIN4_Msk | + USBD_INTEN_ENDEPIN5_Msk | USBD_INTEN_ENDEPIN6_Msk | + USBD_INTEN_ENDEPIN7_Msk | USBD_INTEN_EP0DATADONE_Msk | + USBD_INTEN_ENDISOIN_Msk | USBD_INTEN_ENDEPOUT0_Msk | + USBD_INTEN_ENDEPOUT1_Msk | USBD_INTEN_ENDEPOUT2_Msk | + USBD_INTEN_ENDEPOUT3_Msk | USBD_INTEN_ENDEPOUT4_Msk | + USBD_INTEN_ENDEPOUT5_Msk | USBD_INTEN_ENDEPOUT6_Msk | + USBD_INTEN_ENDEPOUT7_Msk | USBD_INTEN_ENDISOOUT_Msk | + USBD_INTEN_USBEVENT_Msk | USBD_INTEN_EP0SETUP_Msk | + USBD_INTEN_EPDATA_Msk; + + if (enable_sof) { + int_mask |= USBD_INTEN_SOF_Msk; + } + + /* Enable all required interrupts */ + NRF_USBD->INTEN = int_mask; + + /* Enable interrupt globally */ + irq_enable(USBD_IRQn); + + /* Enable pullups */ + NRF_USBD->USBPULLUP = 1; +} + +static void nrf_usbd_common_stop(void) +{ + __ASSERT_NO_MSG(m_drv_state == NRFX_DRV_STATE_POWERED_ON); + + /* Clear interrupt */ + NVIC_ClearPendingIRQ(USBD_IRQn); + + if (irq_is_enabled(USBD_IRQn)) { + /* Abort transfers */ + usbd_ep_abort_all(); + + /* Disable pullups */ + NRF_USBD->USBPULLUP = 0; + + /* Disable interrupt globally */ + irq_disable(USBD_IRQn); + + /* Disable all interrupts */ + NRF_USBD->INTEN = 0; + } +} + +bool nrf_usbd_common_is_initialized(void) +{ + return (m_drv_state >= NRFX_DRV_STATE_INITIALIZED); +} + +bool nrf_usbd_common_is_enabled(void) +{ + return (m_drv_state >= NRFX_DRV_STATE_POWERED_ON); +} + +bool nrf_usbd_common_is_started(void) +{ + return (nrf_usbd_common_is_enabled() && irq_is_enabled(USBD_IRQn)); +} + +bool nrf_usbd_common_suspend(void) +{ + bool suspended = false; + unsigned int irq_lock_key = irq_lock(); + + if (m_bus_suspend) { + if (!(NRF_USBD->EVENTCAUSE & USBD_EVENTCAUSE_RESUME_Msk)) { + NRF_USBD->LOWPOWER = USBD_LOWPOWER_LOWPOWER_LowPower + << USBD_LOWPOWER_LOWPOWER_Pos; + (void)NRF_USBD->LOWPOWER; + if (NRF_USBD->EVENTCAUSE & USBD_EVENTCAUSE_RESUME_Msk) { + NRF_USBD->LOWPOWER = USBD_LOWPOWER_LOWPOWER_ForceNormal + << USBD_LOWPOWER_LOWPOWER_Pos; + } else { + suspended = true; + } + } + } + + irq_unlock(irq_lock_key); + + return suspended; +} + +bool nrf_usbd_common_wakeup_req(void) +{ + bool started = false; + unsigned int irq_lock_key = irq_lock(); + + if (m_bus_suspend && nrf_usbd_common_suspend_check()) { + NRF_USBD->LOWPOWER = USBD_LOWPOWER_LOWPOWER_ForceNormal + << USBD_LOWPOWER_LOWPOWER_Pos; + started = true; + + if (nrf_usbd_common_errata_171()) { + if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000) { + *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; + *((volatile uint32_t *)(0x4006EC14)) = 0x000000C0; + *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; + } else { + *((volatile uint32_t *)(0x4006EC14)) = 0x000000C0; + } + } + } + + irq_unlock(irq_lock_key); + + return started; +} + +bool nrf_usbd_common_suspend_check(void) +{ + return NRF_USBD->LOWPOWER != + (USBD_LOWPOWER_LOWPOWER_ForceNormal << USBD_LOWPOWER_LOWPOWER_Pos); +} + +bool nrf_usbd_common_bus_suspend_check(void) +{ + return m_bus_suspend; +} + +void nrf_usbd_common_force_bus_wakeup(void) +{ + m_bus_suspend = false; +} + +void nrf_usbd_common_ep_max_packet_size_set(nrf_usbd_common_ep_t ep, uint16_t size) +{ + /* Only the power of 2 size allowed for Control Endpoints */ + __ASSERT_NO_MSG((((size & (size - 1)) == 0) || (NRF_USBD_COMMON_EP_NUM(ep) != 0))); + /* Only non zero size allowed for Control Endpoints */ + __ASSERT_NO_MSG((size != 0) || (NRF_USBD_COMMON_EP_NUM(ep) != 0)); + /* Packet size cannot be higher than maximum buffer size */ + __ASSERT_NO_MSG((NRF_USBD_COMMON_EP_IS_ISO(ep) && (size <= usbd_ep_iso_capacity(ep))) || + (!NRF_USBD_COMMON_EP_IS_ISO(ep) && (size <= NRF_USBD_COMMON_EPSIZE))); + + usbd_ep_state_t *p_state = ep_state_access(ep); + + p_state->max_packet_size = size; +} + +uint16_t nrf_usbd_common_ep_max_packet_size_get(nrf_usbd_common_ep_t ep) +{ + usbd_ep_state_t const *p_state = ep_state_access(ep); + + return p_state->max_packet_size; +} + +bool nrf_usbd_common_ep_enable_check(nrf_usbd_common_ep_t ep) +{ + int ep_in = NRF_USBD_COMMON_EP_IS_IN(ep); + int ep_num = NRF_USBD_COMMON_EP_NUM(ep); + + NRF_USBD_COMMON_ASSERT_EP_VALID(ep); + + return (ep_in ? NRF_USBD->EPINEN : NRF_USBD->EPOUTEN) & BIT(ep_num); +} + +void nrf_usbd_common_ep_enable(nrf_usbd_common_ep_t ep) +{ + int ep_in = NRF_USBD_COMMON_EP_IS_IN(ep); + int ep_num = NRF_USBD_COMMON_EP_NUM(ep); + + if (nrf_usbd_common_ep_enable_check(ep)) { + return; + } + + if (ep_in) { + NRF_USBD->EPINEN |= BIT(ep_num); + } else { + NRF_USBD->EPOUTEN |= BIT(ep_num); + } + + if (ep >= NRF_USBD_COMMON_EPOUT1 && ep <= NRF_USBD_COMMON_EPOUT7) { + unsigned int irq_lock_key = irq_lock(); + + nrf_usbd_common_transfer_out_drop(ep); + m_ep_dma_waiting &= ~(1U << ep2bit(ep)); + + irq_unlock(irq_lock_key); + } +} + +void nrf_usbd_common_ep_disable(nrf_usbd_common_ep_t ep) +{ + int ep_in = NRF_USBD_COMMON_EP_IS_IN(ep); + int ep_num = NRF_USBD_COMMON_EP_NUM(ep); + + /* Only disable endpoint if there is no active DMA */ + k_sem_take(&dma_available, K_FOREVER); + usbd_ep_abort(ep); + if (ep_in) { + NRF_USBD->EPINEN &= ~BIT(ep_num); + } else { + NRF_USBD->EPOUTEN &= ~BIT(ep_num); + } + k_sem_give(&dma_available); + + /* This function was holding DMA semaphore and could potentially prevent + * next DMA from executing. Fire IRQ handler to check if any DMA needs + * to be started. + */ + usbd_int_rise(); +} + +nrfx_err_t nrf_usbd_common_ep_transfer(nrf_usbd_common_ep_t ep, + nrf_usbd_common_transfer_t const *p_transfer) +{ + nrfx_err_t ret; + const uint8_t ep_bitpos = ep2bit(ep); + unsigned int irq_lock_key = irq_lock(); + + __ASSERT_NO_MSG(p_transfer != NULL); + + /* Setup data transaction can go only in one direction at a time */ + if ((NRF_USBD_COMMON_EP_NUM(ep) == 0) && (ep != m_last_setup_dir)) { + ret = NRFX_ERROR_INVALID_ADDR; + if (NRF_USBD_COMMON_FAILED_TRANSFERS_DEBUG && + (NRF_USBD_COMMON_ISO_DEBUG || (!NRF_USBD_COMMON_EP_IS_ISO(ep)))) { + LOG_DBG("Transfer failed: Invalid EPr\n"); + } + } else if ((m_ep_dma_waiting | ((~m_ep_ready) & NRF_USBD_COMMON_EPIN_BIT_MASK)) & + (1U << ep_bitpos)) { + /* IN (Device -> Host) transfer has to be transmitted out to allow new transmission + */ + ret = NRFX_ERROR_BUSY; + if (NRF_USBD_COMMON_FAILED_TRANSFERS_DEBUG) { + LOG_DBG("Transfer failed: EP is busy"); + } + } else { + usbd_ep_state_t *p_state = ep_state_access(ep); + + __ASSERT_NO_MSG(NRF_USBD_COMMON_EP_IS_IN(ep) || + (p_transfer->p_data.rx == NULL) || + (nrfx_is_in_ram(p_transfer->p_data.rx))); + p_state->more_transactions = true; + p_state->transfer_state = *p_transfer; + + p_state->transfer_cnt = 0; + p_state->status = NRF_USBD_COMMON_EP_OK; + m_ep_dma_waiting |= 1U << ep_bitpos; + ret = NRFX_SUCCESS; + usbd_int_rise(); + } + + irq_unlock(irq_lock_key); + + return ret; +} + +nrf_usbd_common_ep_status_t nrf_usbd_common_ep_status_get(nrf_usbd_common_ep_t ep, size_t *p_size) +{ + nrf_usbd_common_ep_status_t ret; + usbd_ep_state_t const *p_state = ep_state_access(ep); + unsigned int irq_lock_key = irq_lock(); + + *p_size = p_state->transfer_cnt; + ret = (!p_state->more_transactions) ? p_state->status : NRF_USBD_COMMON_EP_BUSY; + + irq_unlock(irq_lock_key); + + return ret; +} + +size_t nrf_usbd_common_epout_size_get(nrf_usbd_common_ep_t ep) +{ + if (NRF_USBD_COMMON_EP_IS_ISO(ep)) { + size_t size = NRF_USBD->SIZE.ISOOUT; + + if ((size & USBD_SIZE_ISOOUT_ZERO_Msk) == + (USBD_SIZE_ISOOUT_ZERO_ZeroData << USBD_SIZE_ISOOUT_ZERO_Pos)) { + size = 0; + } + return size; + } + + return NRF_USBD->SIZE.EPOUT[NRF_USBD_COMMON_EP_NUM(ep)]; +} + +bool nrf_usbd_common_ep_is_busy(nrf_usbd_common_ep_t ep) +{ + return (0 != ((m_ep_dma_waiting | ((~m_ep_ready) & NRF_USBD_COMMON_EPIN_BIT_MASK)) & + (1U << ep2bit(ep)))); +} + +void nrf_usbd_common_ep_stall(nrf_usbd_common_ep_t ep) +{ + __ASSERT_NO_MSG(!NRF_USBD_COMMON_EP_IS_ISO(ep)); + + LOG_DBG("USB: EP %x stalled.", ep); + NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_Stall << USBD_EPSTALL_STALL_Pos) | ep; +} + +void nrf_usbd_common_ep_stall_clear(nrf_usbd_common_ep_t ep) +{ + __ASSERT_NO_MSG(!NRF_USBD_COMMON_EP_IS_ISO(ep)); + + if (NRF_USBD_COMMON_EP_IS_OUT(ep) && nrf_usbd_common_ep_stall_check(ep)) { + nrf_usbd_common_transfer_out_drop(ep); + } + NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_UnStall << USBD_EPSTALL_STALL_Pos) | ep; +} + +bool nrf_usbd_common_ep_stall_check(nrf_usbd_common_ep_t ep) +{ + int ep_in = NRF_USBD_COMMON_EP_IS_IN(ep); + int ep_num = NRF_USBD_COMMON_EP_NUM(ep); + + if (!NRF_USBD_COMMON_EP_IS_ISO(ep_num)) { + if (ep_in) { + return NRF_USBD->HALTED.EPIN[ep_num]; + } else { + return NRF_USBD->HALTED.EPOUT[ep_num]; + } + } + + return false; +} + +void nrf_usbd_common_ep_dtoggle_clear(nrf_usbd_common_ep_t ep) +{ + __ASSERT_NO_MSG(!NRF_USBD_COMMON_EP_IS_ISO(ep)); + + NRF_USBD->DTOGGLE = ep | (USBD_DTOGGLE_VALUE_Nop << USBD_DTOGGLE_VALUE_Pos); + NRF_USBD->DTOGGLE = ep | (USBD_DTOGGLE_VALUE_Data0 << USBD_DTOGGLE_VALUE_Pos); +} + +void nrf_usbd_common_setup_get(nrf_usbd_common_setup_t *p_setup) +{ + memset(p_setup, 0, sizeof(nrf_usbd_common_setup_t)); + p_setup->bmRequestType = NRF_USBD->BMREQUESTTYPE; + p_setup->bRequest = NRF_USBD->BREQUEST; + p_setup->wValue = NRF_USBD->WVALUEL | (NRF_USBD->WVALUEH << 8); + p_setup->wIndex = NRF_USBD->WINDEXL | (NRF_USBD->WINDEXH << 8); + p_setup->wLength = NRF_USBD->WLENGTHL | (NRF_USBD->WLENGTHH << 8); +} + +void nrf_usbd_common_setup_data_clear(void) +{ + NRF_USBD->TASKS_EP0RCVOUT = 1; +} + +void nrf_usbd_common_setup_clear(void) +{ + LOG_DBG(">> ep0status >>"); + NRF_USBD->TASKS_EP0STATUS = 1; +} + +void nrf_usbd_common_setup_stall(void) +{ + LOG_DBG("Setup stalled."); + NRF_USBD->TASKS_EP0STALL = 1; +} + +nrf_usbd_common_ep_t nrf_usbd_common_last_setup_dir_get(void) +{ + return m_last_setup_dir; +} + +void nrf_usbd_common_transfer_out_drop(nrf_usbd_common_ep_t ep) +{ + unsigned int irq_lock_key = irq_lock(); + + __ASSERT_NO_MSG(NRF_USBD_COMMON_EP_IS_OUT(ep)); + + m_ep_ready &= ~(1U << ep2bit(ep)); + if (!NRF_USBD_COMMON_EP_IS_ISO(ep)) { + NRF_USBD->SIZE.EPOUT[NRF_USBD_COMMON_EP_NUM(ep)] = 0; + } + + irq_unlock(irq_lock_key); +} + +/** @endcond */ diff --git a/drivers/usb/common/nrf_usbd_common/nrf_usbd_common.h b/drivers/usb/common/nrf_usbd_common/nrf_usbd_common.h new file mode 100644 index 00000000000..bb3db14a05b --- /dev/null +++ b/drivers/usb/common/nrf_usbd_common/nrf_usbd_common.h @@ -0,0 +1,679 @@ +/* + * Copyright (c) 2016 - 2023, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* This file is undergoing transition towards native Zephyr nrf USB driver. */ + +/** @cond INTERNAL_HIDDEN */ + +#ifndef NRF_USBD_COMMON_H__ +#define NRF_USBD_COMMON_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_usbd_common USBD driver + * @{ + * @ingroup nrf_usbd + * @brief Universal Serial Bus Device (USBD) peripheral driver. + */ + +/** + * @brief Number of bytes in the endpoint. + */ +#define NRF_USBD_COMMON_EPSIZE 64 + +/** + * @brief Number of bytes for isochronous endpoints. + * + * Number of bytes for isochronous endpoints in total. + * This number would be shared between IN and OUT endpoint. + * It may be also assigned totaly to one endpoint. + * @sa nrf_usbd_isosplit_set + * @sa nrf_usbd_isosplit_get + */ +#define NRF_USBD_COMMON_ISOSIZE 1023 + +/** + * @name Macros for creating endpoint identifiers. + * + * Auxiliary macros for creating endpoint identifiers compatible with the USB specification. + * @{ + */ + +/** + * @brief Create identifier for IN endpoint. + * + * Simple macro to create IN endpoint identifier for given endpoint number. + * + * @param[in] n Endpoint number. + * + * @return Endpoint identifier that connects endpoint number and endpoint direction. + */ +#define NRF_USBD_COMMON_EPIN(n) ((nrf_usbd_common_ep_t)(0x80 | n)) +/** + * @brief Create identifier for OUT endpoint. + * + * Simple macro to create OUT endpoint identifier for given endpoint number. + * + * @param[in] n Endpoint number. + * + * @return Endpoint identifier that connects endpoint number and endpoint direction. + */ +#define NRF_USBD_COMMON_EPOUT(n) ((nrf_usbd_common_ep_t)(n)) +/** @} */ + +/** + * @brief Endpoint identifier. + * + * Endpoint identifier used in the driver. + * This endpoint number is consistent with USB 2.0 specification. + */ +typedef enum { + NRF_USBD_COMMON_EPOUT0 = 0x00, /**< Endpoint OUT 0 */ + NRF_USBD_COMMON_EPOUT1 = 0x01, /**< Endpoint OUT 1 */ + NRF_USBD_COMMON_EPOUT2 = 0x02, /**< Endpoint OUT 2 */ + NRF_USBD_COMMON_EPOUT3 = 0x03, /**< Endpoint OUT 3 */ + NRF_USBD_COMMON_EPOUT4 = 0x04, /**< Endpoint OUT 4 */ + NRF_USBD_COMMON_EPOUT5 = 0x05, /**< Endpoint OUT 5 */ + NRF_USBD_COMMON_EPOUT6 = 0x06, /**< Endpoint OUT 6 */ + NRF_USBD_COMMON_EPOUT7 = 0x07, /**< Endpoint OUT 7 */ + NRF_USBD_COMMON_EPOUT8 = 0x08, /**< Endpoint OUT 8 */ + + NRF_USBD_COMMON_EPIN0 = 0x80, /**< Endpoint IN 0 */ + NRF_USBD_COMMON_EPIN1 = 0x81, /**< Endpoint IN 1 */ + NRF_USBD_COMMON_EPIN2 = 0x82, /**< Endpoint IN 2 */ + NRF_USBD_COMMON_EPIN3 = 0x83, /**< Endpoint IN 3 */ + NRF_USBD_COMMON_EPIN4 = 0x84, /**< Endpoint IN 4 */ + NRF_USBD_COMMON_EPIN5 = 0x85, /**< Endpoint IN 5 */ + NRF_USBD_COMMON_EPIN6 = 0x86, /**< Endpoint IN 6 */ + NRF_USBD_COMMON_EPIN7 = 0x87, /**< Endpoint IN 7 */ + NRF_USBD_COMMON_EPIN8 = 0x88, /**< Endpoint IN 8 */ +} nrf_usbd_common_ep_t; + +/** + * @brief Events generated by the driver. + * + * Enumeration of possible events that may be generated by the driver. + */ +typedef enum { + NRF_USBD_COMMON_EVT_SOF, /**< Start Of Frame event on USB bus detected. */ + NRF_USBD_COMMON_EVT_RESET, /**< Reset condition on USB bus detected. */ + NRF_USBD_COMMON_EVT_SUSPEND, /**< This device should go to suspend mode now. */ + NRF_USBD_COMMON_EVT_RESUME, /**< This device should resume from suspend now. */ + /** Wakeup request - the USBD peripheral is ready to generate + * WAKEUP signal after exiting low power mode. + */ + NRF_USBD_COMMON_EVT_WUREQ, + NRF_USBD_COMMON_EVT_SETUP, /**< Setup frame received and decoded. */ + /** For Rx (OUT: Host->Device): + * 1. The packet has been received but there is no buffer + * prepared for transfer already. + * 2. Whole transfer has been finished. + * + * For Tx (IN: Device->Host): + * The last packet from requested transfer has been transferred + * over USB bus and acknowledged. + */ + NRF_USBD_COMMON_EVT_EPTRANSFER, + NRF_USBD_COMMON_EVT_CNT /**< Number of defined events. */ +} nrf_usbd_common_event_type_t; + +/** + * @brief Endpoint status codes. + * + * Status codes that may be returned by @ref nrf_usbd_common_ep_status_get or, except for + * @ref NRF_USBD_COMMON_EP_BUSY, reported together with @ref NRF_USBD_COMMON_EVT_EPTRANSFER. + */ +typedef enum { + /** No error occurred. */ + NRF_USBD_COMMON_EP_OK, + /** Data received, no buffer prepared already - waiting for configured transfer. */ + NRF_USBD_COMMON_EP_WAITING, + /** Received number of bytes cannot fit given buffer. + * This error would also be returned when next_transfer function + * has been defined but currently received data cannot fit completely + * in current buffer. No data split from single endpoint transmission + * is supported. + * + * When this error is reported - data is left inside endpoint + * buffer. Clear endpoint or prepare new buffer and read it. + */ + NRF_USBD_COMMON_EP_OVERLOAD, + /** EP0 transfer can be aborted when new setup comes. + * Any other transfer can be aborted by USB reset or driver stopping. + */ + NRF_USBD_COMMON_EP_ABORTED, + /** Transfer is in progress. */ + NRF_USBD_COMMON_EP_BUSY, +} nrf_usbd_common_ep_status_t; + +/** + * @brief Event structure. + * + * Structure passed to event handler. + */ +typedef struct { + nrf_usbd_common_event_type_t type; /**< Event type. */ + union { + struct { + uint16_t framecnt; /**< Current value of frame counter. */ + } sof; /**< Data available for @ref NRF_USBD_COMMON_EVT_SOF. */ + struct { + nrf_usbd_common_ep_t ep; /**< Endpoint number. */ + } isocrc; /**< Isochronouns channel endpoint number. */ + struct { + nrf_usbd_common_ep_t ep; /**< Endpoint number. */ + nrf_usbd_common_ep_status_t status; /**< Status for the endpoint. */ + } eptransfer; /**< Endpoint transfer status. */ + } data; /**< Union to store event data. */ +} nrf_usbd_common_evt_t; + +/** + * @brief USBD event callback function type. + * + * @param[in] p_event Event information structure. + */ +typedef void (*nrf_usbd_common_event_handler_t)(nrf_usbd_common_evt_t const *p_event); + +/** + * @brief Universal data pointer. + * + * Universal data pointer that can be used for any type of transfer. + */ +typedef union { + void const *tx; /*!< Constant TX buffer pointer. */ + void *rx; /*!< Writable RX buffer pointer. */ + uint32_t addr; /*!< Numeric value used internally by the driver. */ +} nrf_usbd_common_data_ptr_t; + +/** + * @brief Structure to be filled with information about the next transfer. + * + * This is used mainly for transfer feeders and consumers. + * It describes a single endpoint transfer and therefore the size of the buffer + * can never be higher than the endpoint size. + */ +typedef struct { + /** Union with available data pointers used by the driver. */ + nrf_usbd_common_data_ptr_t p_data; + /** Size of the requested transfer. */ + size_t size; +} nrf_usbd_common_ep_transfer_t; + +/** + * @brief Flags for the current transfer. + * + * Flags configured for the transfer that can be merged using the bitwise 'or' operator (|). + */ +typedef enum { + NRF_USBD_COMMON_TRANSFER_ZLP_FLAG = 1U << 0, /*!< Add a zero-length packet. */ +} nrf_usbd_common_transfer_flags_t; + +/** + * @brief Total transfer configuration. + * + * This structure is used to configure total transfer information. + * It is used by internal built-in feeders and consumers. + */ +typedef struct { + /** Union with available data pointers used by the driver. */ + nrf_usbd_common_data_ptr_t p_data; + /** Total size of the requested transfer. */ + size_t size; + /*!< Transfer flags. Use the @ref nrf_usbd_common_transfer_flags_t values. */ + uint32_t flags; +} nrf_usbd_common_transfer_t; + +/** + * @brief Auxiliary macro for declaring IN transfer description with optional flags. + * + * The base macro for creating transfers with any configuration option. + * + * @param name Instance name. + * @param tx_buff Buffer to transfer. + * @param tx_size Transfer size. + * @param tx_flags Flags for the transfer (see @ref nrf_usbd_common_transfer_flags_t). + * + * @return Configured variable with total transfer description. + */ +#define NRF_USBD_COMMON_TRANSFER_IN(name, tx_buff, tx_size, tx_flags) \ + const nrf_usbd_common_transfer_t name = { \ + .p_data = {.tx = (tx_buff)}, .size = (tx_size), .flags = (tx_flags)} + +/** + * @brief Helper macro for declaring OUT transfer item (@ref nrf_usbd_common_transfer_t). + * + * @param name Instance name. + * @param rx_buff Buffer to transfer. + * @param rx_size Transfer size. + */ +#define NRF_USBD_COMMON_TRANSFER_OUT(name, rx_buff, rx_size) \ + const nrf_usbd_common_transfer_t name = { \ + .p_data = {.rx = (rx_buff)}, .size = (rx_size), .flags = 0} + +/** + * @brief Setup packet structure. + * + * Structure that contains interpreted SETUP packet as described in USB specification. + */ +typedef struct { + uint8_t bmRequestType; /*!< byte 0 */ + uint8_t bRequest; /*!< byte 1 */ + uint16_t wValue; /*!< byte 2, 3 */ + uint16_t wIndex; /*!< byte 4, 5 */ + uint16_t wLength; /*!< byte 6, 7 */ +} nrf_usbd_common_setup_t; + +/** + * @brief Driver initialization. + * + * @param[in] event_handler Event handler provided by the user. Cannot be null. + * + * @retval NRFX_SUCCESS Initialization successful. + * @retval NRFX_ERROR_INVALID_STATE Driver was already initialized. + */ +nrfx_err_t nrf_usbd_common_init(nrf_usbd_common_event_handler_t event_handler); + +/** + * @brief Driver deinitialization. + */ +void nrf_usbd_common_uninit(void); + +/** + * @brief Enable the USBD port. + * + * After calling this function USBD peripheral would be enabled. + * The USB LDO would be enabled. + * Enabled USBD peripheral would request HFCLK. + * This function does not enable external oscillator, so if it is not enabled by other part of the + * program after enabling USBD driver HFINT would be used for the USBD peripheral. + * It is perfectly fine until USBD is started. See @ref nrf_usbd_common_start. + * + * In normal situation this function should be called in reaction to USBDETECTED + * event from POWER peripheral. + * + * Interrupts and USB pins pull-up would stay disabled until @ref nrf_usbd_common_start + * function is called. + */ +void nrf_usbd_common_enable(void); + +/** + * @brief Disable the USBD port. + * + * After calling this function USBD peripheral would be disabled. + * No events would be detected or processed by the driver. + * Clock for the peripheral would be disconnected. + */ +void nrf_usbd_common_disable(void); + +/** + * @brief Start USB functionality. + * + * After calling this function USBD peripheral should be fully functional + * and all new incoming events / interrupts would be processed by the driver. + * + * Also only after calling this function host sees new connected device. + * + * Call this function when USBD power LDO regulator is ready - on USBPWRRDY event + * from POWER peripheral. + * + * Before USBD interrupts are enabled, external HFXO is requested. + * + * @param enable_sof The flag that is used to enable SOF processing. + * If it is false, SOF interrupt is left disabled and will not be generated. + * This improves power saving if SOF is not required. + * + * @note If the isochronous endpoints are going to be used, + * it is required to enable the SOF. + * In other case any isochronous endpoint would stay busy + * after first transmission. + */ +void nrf_usbd_common_start(bool enable_sof); + +/** + * @brief Check if driver is initialized. + * + * @retval false Driver is not initialized. + * @retval true Driver is initialized. + */ +bool nrf_usbd_common_is_initialized(void); + +/** + * @brief Check if driver is enabled. + * + * @retval false Driver is disabled. + * @retval true Driver is enabled. + */ +bool nrf_usbd_common_is_enabled(void); + +/** + * @brief Check if driver is started. + * + * @retval false Driver is not started. + * @retval true Driver is started (fully functional). + * @note The USBD peripheral interrupt state is checked. + */ +bool nrf_usbd_common_is_started(void); + +/** + * @brief Suspend USBD operation. + * + * The USBD peripheral is forced to go into the low power mode. + * The function has to be called in the reaction to @ref NRF_USBD_COMMON_EVT_SUSPEND event + * when the firmware is ready. + * + * After successful call of this function most of the USBD registers would be unavailable. + * + * @note Check returned value for the feedback if suspending was successful. + * + * @retval true USBD peripheral successfully suspended. + * @retval false USBD peripheral was not suspended due to resume detection. + */ +bool nrf_usbd_common_suspend(void); + +/** + * @brief Start wake up procedure. + * + * The USBD peripheral is forced to quit the low power mode. + * After calling this function all the USBD registers would be available. + * + * The hardware starts measuring time when wake up is possible. + * This may take 0-5 ms depending on how long the SUSPEND state was kept on the USB line. + + * When NRF_USBD_COMMON_EVT_WUREQ event is generated it means that Wake Up signaling has just been + * started on the USB lines. + * + * @note Do not expect only @ref NRF_USBD_COMMON_EVT_WUREQ event. + * There always may appear @ref NRF_USBD_COMMON_EVT_RESUME event. + * @note NRF_USBD_COMMON_EVT_WUREQ event means that Remote WakeUp signal + * has just begun to be generated. + * This may take up to 20 ms for the bus to become active. + * + * @retval true WakeUp procedure started. + * @retval false No WakeUp procedure started - bus is already active. + */ +bool nrf_usbd_common_wakeup_req(void); + +/** + * @brief Check if USBD is in SUSPEND mode. + * + * @note This is the information about peripheral itself, not about the bus state. + * + * @retval true USBD peripheral is suspended. + * @retval false USBD peripheral is active. + */ +bool nrf_usbd_common_suspend_check(void); + +/** + * @brief Check the bus state. + * + * This function checks if the bus state is suspended. + * + * @note The value returned by this function changes on SUSPEND and RESUME event processing. + * + * @retval true USBD bus is suspended. + * @retval false USBD bus is active. + */ +bool nrf_usbd_common_bus_suspend_check(void); + +/** + * @brief Force the bus state to active + */ +void nrf_usbd_common_force_bus_wakeup(void); + +/** + * @brief Configure packet size that should be supported by the endpoint. + * + * The real endpoint buffer size is always the same. + * This value sets max packet size that would be transmitted over the endpoint. + * This is required by the driver. + * + * @param[in] ep Endpoint number. + * @param[in] size Required maximum packet size. + * + * @note Endpoint size is always set to @ref NRF_USBD_COMMON_EPSIZE + * or @ref NRF_USBD_COMMON_ISOSIZE / 2 + * when @ref nrf_usbd_common_ep_enable function is called. + */ +void nrf_usbd_common_ep_max_packet_size_set(nrf_usbd_common_ep_t ep, uint16_t size); + +/** + * @brief Get configured endpoint packet size. + * + * Function to get configured endpoint size on the buffer. + * + * @param[in] ep Endpoint number. + * + * @return Maximum pocket size configured on selected endpoint. + */ +uint16_t nrf_usbd_common_ep_max_packet_size_get(nrf_usbd_common_ep_t ep); + +/** + * @brief Check if the selected endpoint is enabled. + * + * @param[in] ep Endpoint number to check. + * + * @retval true Endpoint is enabled. + * @retval false Endpoint is disabled. + */ +bool nrf_usbd_common_ep_enable_check(nrf_usbd_common_ep_t ep); + +/** + * @brief Enable selected endpoint. + * + * This function enables endpoint itself and its interrupts. + * + * @param[in] ep Endpoint number to enable. + * + * @note + * Max packet size is set to endpoint default maximum value. + * + * @sa nrf_usbd_common_ep_max_packet_size_set + */ +void nrf_usbd_common_ep_enable(nrf_usbd_common_ep_t ep); + +/** + * @brief Disable selected endpoint. + * + * This function disables endpoint itself and its interrupts. + * + * @param[in] ep Endpoint number to disable. + */ +void nrf_usbd_common_ep_disable(nrf_usbd_common_ep_t ep); + +/** + * @brief Start sending data over endpoint. + * + * Function initializes endpoint transmission. + * This is asynchronous function - it finishes immediately after configuration + * for transmission is prepared. + * + * @note Data buffer pointed by p_data have to be kept active till + * @ref NRF_USBD_COMMON_EVT_EPTRANSFER event is generated. + * + * @param[in] ep Endpoint number. + * For IN endpoint sending would be initiated. + * For OUT endpoint receiving would be initiated. + * @param[in] p_transfer Transfer parameters. + * + * @retval NRFX_SUCCESS Transfer queued or started. + * @retval NRFX_ERROR_BUSY Selected endpoint is pending. + * @retval NRFX_ERROR_INVALID_ADDR Unexpected transfer on EPIN0 or EPOUT0. + */ +nrfx_err_t nrf_usbd_common_ep_transfer(nrf_usbd_common_ep_t ep, + nrf_usbd_common_transfer_t const *p_transfer); + +/** + * @brief Get the information about last finished or current transfer. + * + * Function returns the status of the last buffer set for transfer on selected endpoint. + * The status considers last buffer set by @ref nrf_usbd_common_ep_transfer function or + * by transfer callback function. + * + * @param[in] ep Endpoint number. + * @param[out] p_size Information about the current/last transfer size. + * + * @return Endpoint status. + * + * @sa nrf_usbd_common_ep_status_t + */ +nrf_usbd_common_ep_status_t nrf_usbd_common_ep_status_get(nrf_usbd_common_ep_t ep, size_t *p_size); + +/** + * @brief Get number of received bytes. + * + * Get the number of received bytes. + * The function behavior is undefined when called on IN endpoint. + * + * @param[in] ep Endpoint number. + * + * @return Number of received bytes. + */ +size_t nrf_usbd_common_epout_size_get(nrf_usbd_common_ep_t ep); + +/** + * @brief Check if endpoint buffer is ready or is under USB IP control. + * + * Function to test if endpoint is busy. + * Endpoint that is busy cannot be accessed by MCU. + * It means that: + * - OUT (TX) endpoint: Last uploaded data is still in endpoint and is waiting + * to be received by the host. + * - IN (RX) endpoint: Endpoint is ready to receive data from the host + * and the endpoint does not have any data. + * When endpoint is not busy: + * - OUT (TX) endpoint: New data can be uploaded. + * - IN (RX) endpoint: New data can be downloaded using @ref nrf_usbd_common_ep_transfer + * function. + * + * @param[in] ep Endpoint number. + * + * @retval false Endpoint is not busy. + * @retval true Endpoint is busy. + */ +bool nrf_usbd_common_ep_is_busy(nrf_usbd_common_ep_t ep); + +/** + * @brief Stall endpoint + * + * Stall endpoit to send error information during next transfer request from + * the host. + * + * @note To stall endpoint it is safer to use @ref nrf_usbd_common_setup_stall + * @note Stalled endpoint would not be cleared when DMA transfer finishes. + * + * @param[in] ep Endpoint number to stall. + */ +void nrf_usbd_common_ep_stall(nrf_usbd_common_ep_t ep); + +/** + * @brief Clear stall flag on endpoint. + * + * This function clears endpoint that is stalled. + * @note + * If it is OUT endpoint (receiving) it would be also prepared for reception. + * It means that busy flag would be set. + * @note + * In endpoint (transmitting) would not be cleared - it gives possibility to + * write new data before transmitting. + * + * @param[in] ep Endpoint number. + */ +void nrf_usbd_common_ep_stall_clear(nrf_usbd_common_ep_t ep); + +/** + * @brief Check if endpoint is stalled. + * + * This function gets stall state of selected endpoint. + * + * @param[in] ep Endpoint number to check. + * + * @retval false Endpoint is not stalled. + * @retval true Endpoint is stalled. + */ +bool nrf_usbd_common_ep_stall_check(nrf_usbd_common_ep_t ep); + +/** + * @brief Clear current endpoint data toggle. + * + * @param[in] ep Endpoint number to clear. + */ +void nrf_usbd_common_ep_dtoggle_clear(nrf_usbd_common_ep_t ep); + +/** + * @brief Get parsed setup data. + * + * Function fills the parsed setup data structure. + * + * @param[out] p_setup Pointer to data structure that would be filled by + * parsed data. + */ +void nrf_usbd_common_setup_get(nrf_usbd_common_setup_t *p_setup); + +/** + * @brief Clear the control endpoint for packet reception during DATA stage. + * + * This function may be called if any more data in control write transfer is expected. + * Clears only OUT endpoint to be able to take another OUT data token. + * It does not allow STATUS stage. + * @sa nrf_usbd_common_setup_clear + */ +void nrf_usbd_common_setup_data_clear(void); + +/** + * @brief Clear setup endpoint. + * + * This function acknowledges setup when SETUP command was received and processed. + * It has to be called if no data respond for the SETUP command is sent. + */ +void nrf_usbd_common_setup_clear(void); + +/** + * @brief Stall setup endpoint. + * + * Mark an error on setup endpoint. + */ +void nrf_usbd_common_setup_stall(void); + +/** + * @brief Abort pending transfer on selected endpoint. + * + * @param[in] ep Endpoint number. + */ +void nrf_usbd_common_ep_abort(nrf_usbd_common_ep_t ep); + +/** + * @brief Get the information about expected transfer SETUP data direction. + * + * Function returns the information about last expected transfer direction. + * + * @retval NRF_USBD_COMMON_EPOUT0 Expecting OUT (Host->Device) direction or no data. + * @retval NRF_USBD_COMMON_EPIN0 Expecting IN (Device->Host) direction. + */ +nrf_usbd_common_ep_t nrf_usbd_common_last_setup_dir_get(void); + +/** + * @brief Drop transfer on OUT endpoint. + * + * @param[in] ep OUT endpoint ID. + */ +void nrf_usbd_common_transfer_out_drop(nrf_usbd_common_ep_t ep); + +/** @} */ + +void nrf_usbd_common_irq_handler(void); + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_USBD_COMMON_H__ */ + +/** @endcond */ diff --git a/drivers/usb/common/nrf_usbd_common/nrf_usbd_common_errata.h b/drivers/usb/common/nrf_usbd_common/nrf_usbd_common_errata.h new file mode 100644 index 00000000000..0ee23ccd2c5 --- /dev/null +++ b/drivers/usb/common/nrf_usbd_common/nrf_usbd_common_errata.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016 - 2023, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* This file is undergoing transition towards native Zephyr nrf USB driver. */ + +/** @cond INTERNAL_HIDDEN */ + +#ifndef NRF_USBD_COMMON_ERRATA_H__ +#define NRF_USBD_COMMON_ERRATA_H__ + +#include +#include + +#ifndef NRF_USBD_COMMON_ERRATA_ENABLE +/** + * @brief The constant that informs if errata should be enabled at all. + * + * If this constant is set to 0, all the Errata bug fixes will be automatically disabled. + */ +#define NRF_USBD_COMMON_ERRATA_ENABLE 1 +#endif + +/* Errata: ISO double buffering not functional. **/ +static inline bool nrf_usbd_common_errata_166(void) +{ + return NRF_USBD_COMMON_ERRATA_ENABLE && nrf52_errata_166(); +} + +/* Errata: USBD might not reach its active state. **/ +static inline bool nrf_usbd_common_errata_171(void) +{ + return NRF_USBD_COMMON_ERRATA_ENABLE && nrf52_errata_171(); +} + +/* Errata: USB cannot be enabled. **/ +static inline bool nrf_usbd_common_errata_187(void) +{ + return NRF_USBD_COMMON_ERRATA_ENABLE && nrf52_errata_187(); +} + +/* Errata: USBD cannot receive tasks during DMA. **/ +static inline bool nrf_usbd_common_errata_199(void) +{ + return NRF_USBD_COMMON_ERRATA_ENABLE && nrf52_errata_199(); +} + +/* Errata: Device remains in SUSPEND too long. */ +static inline bool nrf_usbd_common_errata_211(void) +{ + return NRF_USBD_COMMON_ERRATA_ENABLE && nrf52_errata_211(); +} + +/* Errata: Unexpected behavior after reset. **/ +static inline bool nrf_usbd_common_errata_223(void) +{ + return NRF_USBD_COMMON_ERRATA_ENABLE && nrf52_errata_223(); +} + +#endif /* NRF_USBD_COMMON_ERRATA_H__ */ + +/** @endcond */ diff --git a/drivers/usb/device/Kconfig b/drivers/usb/device/Kconfig index 768c0da7cf9..91db896eede 100644 --- a/drivers/usb/device/Kconfig +++ b/drivers/usb/device/Kconfig @@ -104,7 +104,7 @@ config USB_NRFX bool "Nordic Semiconductor USB Device Controller Driver" default y depends on DT_HAS_NORDIC_NRF_USBD_ENABLED - select NRFX_USBD + select NRF_USBD_COMMON select NRFX_POWER imply USB_DEVICE_REMOTE_WAKEUP help @@ -147,7 +147,7 @@ config USB_KINETIS config USB_MCUX bool "NXP MCUX USB Device Controller Driver" default y - depends on DT_HAS_NXP_MCUX_USBD_ENABLED + depends on DT_HAS_NXP_EHCI_ENABLED || DT_HAS_NXP_LPCIP3511_ENABLED help NXP MCUX USB Device Controller Driver for MXRT and LPC SoC's. diff --git a/drivers/usb/device/usb_dc_it82xx2.c b/drivers/usb/device/usb_dc_it82xx2.c index f67db012e1d..b5307252325 100644 --- a/drivers/usb/device/usb_dc_it82xx2.c +++ b/drivers/usb/device/usb_dc_it82xx2.c @@ -719,7 +719,7 @@ static void it82xx2_ep_in_out_config(uint8_t idx) } } -static void it82xx2_usb_dc_trans_done(uint8_t ep_ctrl, uint8_t ep_trans_type) +static void it82xx2_usb_dc_trans_done(void) { struct usb_it82xx2_regs *const usb_regs = (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); @@ -730,12 +730,12 @@ static void it82xx2_usb_dc_trans_done(uint8_t ep_ctrl, uint8_t ep_trans_type) int ret; for (uint8_t idx = 0 ; idx < EP4 ; idx++) { - ep_ctrl = ep_regs[idx].ep_ctrl; + uint8_t ep_ctrl = ep_regs[idx].ep_ctrl; /* check ready bit ,will be 0 when trans done */ if ((ep_ctrl & ENDPOINT_EN) && !(ep_ctrl & ENDPOINT_RDY)) { if (idx == EP0) { - ep_trans_type = ep_regs[idx].ep_transtype_sts & + uint8_t ep_trans_type = ep_regs[idx].ep_transtype_sts & DC_ALL_TRANS; /* set up*/ @@ -785,7 +785,6 @@ static void it82xx2_usb_dc_isr(void) uint8_t status = usb_regs->dc_interrupt_status & usb_regs->dc_interrupt_mask; /* mask non enable int */ - uint8_t ep_ctrl, ep_trans_type; /* reset */ if (status & DC_RESET_EVENT) { @@ -813,7 +812,7 @@ static void it82xx2_usb_dc_isr(void) if (status & DC_TRANS_DONE) { /* clear interrupt before new transaction */ usb_regs->dc_interrupt_status = DC_TRANS_DONE; - it82xx2_usb_dc_trans_done(ep_ctrl, ep_trans_type); + it82xx2_usb_dc_trans_done(); return; } diff --git a/drivers/usb/device/usb_dc_mcux.c b/drivers/usb/device/usb_dc_mcux.c index 27f7d254b8d..0667486b628 100644 --- a/drivers/usb/device/usb_dc_mcux.c +++ b/drivers/usb/device/usb_dc_mcux.c @@ -5,8 +5,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define DT_DRV_COMPAT nxp_mcux_usbd - #include #include #include @@ -21,15 +19,20 @@ #include "usb_device_dci.h" #ifdef CONFIG_USB_DC_NXP_EHCI +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nxp_ehci #include "usb_device_ehci.h" #endif #ifdef CONFIG_USB_DC_NXP_LPCIP3511 +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nxp_lpcip3511 #include "usb_device_lpcip3511.h" #endif #ifdef CONFIG_HAS_MCUX_CACHE #include #endif + #define LOG_LEVEL CONFIG_USB_DRIVER_LOG_LEVEL #include #include @@ -68,7 +71,34 @@ static void usb_isr_handler(void); #define EP_ABS_IDX(ep) (USB_EP_GET_IDX(ep) * 2 + \ (USB_EP_GET_DIR(ep) >> 7)) #define NUM_OF_EP_MAX (DT_INST_PROP(0, num_bidir_endpoints) * 2) -#define CONTROLLER_ID (DT_INST_ENUM_IDX(0, usb_controller_index)) + +#define NUM_INSTS DT_NUM_INST_STATUS_OKAY(nxp_ehci) + DT_NUM_INST_STATUS_OKAY(nxp_lpcip3511) +BUILD_ASSERT(NUM_INSTS <= 1, "Only one USB device supported"); + +/* Controller ID is for HAL usage */ +#if defined(CONFIG_SOC_SERIES_IMX_RT5XX) || \ + defined(CONFIG_SOC_SERIES_IMX_RT6XX) || \ + defined(CONFIG_SOC_LPC55S28) || \ + defined(CONFIG_SOC_LPC55S16) +#define CONTROLLER_ID kUSB_ControllerLpcIp3511Hs0 +#elif defined(CONFIG_SOC_LPC55S36) +#define CONTROLLER_ID kUSB_ControllerLpcIp3511Fs0 +#elif defined(CONFIG_SOC_LPC55S69_CPU0) || defined(CONFIG_SOC_LPC55S69_CPU1) +#if DT_NODE_HAS_STATUS(DT_NODELABEL(usbhs), okay) +#define CONTROLLER_ID kUSB_ControllerLpcIp3511Hs0 +#elif DT_NODE_HAS_STATUS(DT_NODELABEL(usbfs), okay) +#define CONTROLLER_ID kUSB_ControllerLpcIp3511Fs0 +#endif /* LPC55s69 */ +#elif defined(CONFIG_SOC_SERIES_IMX_RT) +#if DT_NODE_HAS_STATUS(DT_NODELABEL(usb1), okay) +#define CONTROLLER_ID kUSB_ControllerEhci0 +#elif DT_NODE_HAS_STATUS(DT_NODELABEL(usb2), okay) +#define CONTROLLER_ID kUSB_ControllerEhci1 +#endif /* IMX RT */ +#else +/* If SOC has EHCI or LPCIP3511 then probably just need to add controller ID to this code */ +#error "USB driver does not yet support this SOC" +#endif /* CONTROLLER ID */ /* We do not need a buffer for the write side on platforms that have USB RAM. * The SDK driver will copy the data buffer to be sent to USB RAM. @@ -89,7 +119,7 @@ K_HEAP_DEFINE(ep_buf_pool, 1024 * EP_BUF_NUMOF_BLOCKS); struct usb_ep_ctrl_data { usb_device_callback_message_struct_t transfer_message; - struct k_mem_block block; + void *block; usb_dc_ep_callback callback; uint16_t ep_mps; uint8_t ep_enabled : 1; @@ -276,21 +306,21 @@ int usb_dc_ep_configure(const struct usb_dc_ep_cfg_data *const cfg) /* Allocate buffers used during read operation */ if (USB_EP_DIR_IS_OUT(cfg->ep_addr)) { #endif - struct k_mem_block *block; + void **block; block = &(eps->block); - if (block->data) { - k_heap_free(&ep_buf_pool, block->data); - block->data = NULL; + if (*block) { + k_heap_free(&ep_buf_pool, *block); + *block = NULL; } - block->data = k_heap_alloc(&ep_buf_pool, cfg->ep_mps, K_NO_WAIT); - if (block->data == NULL) { + *block = k_heap_alloc(&ep_buf_pool, cfg->ep_mps, K_NO_WAIT); + if (*block == NULL) { LOG_ERR("Failed to allocate memory"); return -ENOMEM; } - memset(block->data, 0, cfg->ep_mps); + memset(*block, 0, cfg->ep_mps); #ifdef CONFIG_USB_DC_NXP_LPCIP3511 } #endif @@ -362,7 +392,7 @@ int usb_dc_ep_clear_stall(const uint8_t ep) (USB_EP_DIR_IS_OUT(ep))) { status = dev_state.dev_struct.controllerInterface->deviceRecv( dev_state.dev_struct.controllerHandle, ep, - (uint8_t *)dev_state.eps[ep_abs_idx].block.data, + (uint8_t *)dev_state.eps[ep_abs_idx].block, (uint32_t)dev_state.eps[ep_abs_idx].ep_mps); if (kStatus_USB_Success != status) { LOG_ERR("Failed to enable reception on 0x%02x", ep); @@ -438,7 +468,7 @@ int usb_dc_ep_enable(const uint8_t ep) (USB_EP_DIR_IS_OUT(ep))) { status = dev_state.dev_struct.controllerInterface->deviceRecv( dev_state.dev_struct.controllerHandle, ep, - (uint8_t *)dev_state.eps[ep_abs_idx].block.data, + (uint8_t *)dev_state.eps[ep_abs_idx].block, (uint32_t)dev_state.eps[ep_abs_idx].ep_mps); if (kStatus_USB_Success != status) { LOG_ERR("Failed to enable reception on 0x%02x", ep); @@ -520,7 +550,7 @@ int usb_dc_ep_write(const uint8_t ep, const uint8_t *const data, * if available. */ #ifndef CONFIG_USB_DC_NXP_LPCIP3511 - buffer = (uint8_t *)dev_state.eps[ep_abs_idx].block.data; + buffer = (uint8_t *)dev_state.eps[ep_abs_idx].block; if (data_len > dev_state.eps[ep_abs_idx].ep_mps) { len_to_send = dev_state.eps[ep_abs_idx].ep_mps; @@ -674,7 +704,7 @@ int usb_dc_ep_read_continue(uint8_t ep) status = dev_state.dev_struct.controllerInterface->deviceRecv( dev_state.dev_struct.controllerHandle, ep, - (uint8_t *)dev_state.eps[ep_abs_idx].block.data, + (uint8_t *)dev_state.eps[ep_abs_idx].block, dev_state.eps[ep_abs_idx].ep_mps); if (kStatus_USB_Success != status) { LOG_ERR("Failed to enable reception on ep 0x%02x", ep); diff --git a/drivers/usb/device/usb_dc_nrfx.c b/drivers/usb/device/usb_dc_nrfx.c index 76c27647509..49cb4621911 100644 --- a/drivers/usb/device/usb_dc_nrfx.c +++ b/drivers/usb/device/usb_dc_nrfx.c @@ -22,7 +22,8 @@ #include #include #include -#include +#include +#include #include @@ -288,12 +289,12 @@ static inline bool dev_ready(void) return get_usbd_ctx()->ready; } -static inline nrfx_usbd_ep_t ep_addr_to_nrfx(uint8_t ep) +static inline nrf_usbd_common_ep_t ep_addr_to_nrfx(uint8_t ep) { - return (nrfx_usbd_ep_t)ep; + return (nrf_usbd_common_ep_t)ep; } -static inline uint8_t nrfx_addr_to_ep(nrfx_usbd_ep_t ep) +static inline uint8_t nrfx_addr_to_ep(nrf_usbd_common_ep_t ep) { return (uint8_t)ep; } @@ -559,7 +560,7 @@ static void usbd_enable_endpoints(struct nrf_usbd_ctx *ctx) __ASSERT_NO_MSG(ep_ctx); if (ep_ctx->cfg.en) { - nrfx_usbd_ep_enable(ep_addr_to_nrfx(ep_ctx->cfg.addr)); + nrf_usbd_common_ep_enable(ep_addr_to_nrfx(ep_ctx->cfg.addr)); } } @@ -568,7 +569,7 @@ static void usbd_enable_endpoints(struct nrf_usbd_ctx *ctx) __ASSERT_NO_MSG(ep_ctx); if (ep_ctx->cfg.en) { - nrfx_usbd_ep_enable(ep_addr_to_nrfx(ep_ctx->cfg.addr)); + nrf_usbd_common_ep_enable(ep_addr_to_nrfx(ep_ctx->cfg.addr)); } } @@ -577,7 +578,7 @@ static void usbd_enable_endpoints(struct nrf_usbd_ctx *ctx) __ASSERT_NO_MSG(ep_ctx); if (ep_ctx->cfg.en) { - nrfx_usbd_ep_enable(ep_addr_to_nrfx(ep_ctx->cfg.addr)); + nrf_usbd_common_ep_enable(ep_addr_to_nrfx(ep_ctx->cfg.addr)); } } @@ -586,7 +587,7 @@ static void usbd_enable_endpoints(struct nrf_usbd_ctx *ctx) __ASSERT_NO_MSG(ep_ctx); if (ep_ctx->cfg.en) { - nrfx_usbd_ep_enable(ep_addr_to_nrfx(ep_ctx->cfg.addr)); + nrf_usbd_common_ep_enable(ep_addr_to_nrfx(ep_ctx->cfg.addr)); } } } @@ -606,7 +607,7 @@ static void ep_ctx_reset(struct nrf_usbd_ep_ctx *ep_ctx) /* Abort ongoing write operation. */ if (ep_ctx->write_in_progress) { - nrfx_usbd_ep_abort(ep_addr_to_nrfx(ep_ctx->cfg.addr)); + nrf_usbd_common_ep_abort(ep_addr_to_nrfx(ep_ctx->cfg.addr)); } ep_ctx->read_complete = true; @@ -673,9 +674,9 @@ static inline void usbd_work_process_pwr_events(struct usbd_pwr_event *pwr_evt) switch (pwr_evt->state) { case USBD_ATTACHED: - if (!nrfx_usbd_is_enabled()) { + if (!nrf_usbd_common_is_enabled()) { LOG_DBG("USB detected"); - nrfx_usbd_enable(); + nrf_usbd_common_enable(); err = hfxo_start(ctx); __ASSERT_NO_MSG(err >= 0); } @@ -687,7 +688,7 @@ static inline void usbd_work_process_pwr_events(struct usbd_pwr_event *pwr_evt) case USBD_POWERED: usbd_enable_endpoints(ctx); - nrfx_usbd_start(IS_ENABLED(CONFIG_USB_DEVICE_SOF)); + nrf_usbd_common_start(IS_ENABLED(CONFIG_USB_DEVICE_SOF)); ctx->ready = true; LOG_DBG("USB Powered"); @@ -699,7 +700,7 @@ static inline void usbd_work_process_pwr_events(struct usbd_pwr_event *pwr_evt) case USBD_DETACHED: ctx->ready = false; - nrfx_usbd_disable(); + nrf_usbd_common_disable(); err = hfxo_stop(ctx); __ASSERT_NO_MSG(err >= 0); @@ -712,7 +713,7 @@ static inline void usbd_work_process_pwr_events(struct usbd_pwr_event *pwr_evt) case USBD_SUSPENDED: if (dev_ready()) { - nrfx_usbd_suspend(); + nrf_usbd_common_suspend(); LOG_DBG("USB Suspend state"); if (ctx->status_cb) { @@ -771,7 +772,7 @@ static inline void usbd_work_process_setup(struct nrf_usbd_ep_ctx *ep_ctx) if (usb_reqtype_is_to_device(usbd_setup) && usbd_setup->wLength) { ctx->ctrl_read_len = usbd_setup->wLength; /* Allow data chunk on EP0 OUT */ - nrfx_usbd_setup_data_clear(); + nrf_usbd_common_setup_data_clear(); } else { ctx->ctrl_read_len = 0U; } @@ -791,9 +792,9 @@ static inline void usbd_work_process_recvreq(struct nrf_usbd_ctx *ctx, ep_ctx->read_complete = false; k_mutex_lock(&ctx->drv_lock, K_FOREVER); - NRFX_USBD_TRANSFER_OUT(transfer, ep_ctx->buf.data, - ep_ctx->cfg.max_sz); - nrfx_err_t err = nrfx_usbd_ep_transfer( + NRF_USBD_COMMON_TRANSFER_OUT(transfer, ep_ctx->buf.data, + ep_ctx->cfg.max_sz); + nrfx_err_t err = nrf_usbd_common_ep_transfer( ep_addr_to_nrfx(ep_ctx->cfg.addr), &transfer); if (err != NRFX_SUCCESS) { LOG_ERR("nRF USBD transfer error (OUT): 0x%02x", err); @@ -831,7 +832,7 @@ static inline void usbd_work_process_ep_events(struct usbd_ep_event *ep_evt) * no ZLP required. */ k_mutex_lock(&ctx->drv_lock, K_FOREVER); - nrfx_usbd_setup_clear(); + nrf_usbd_common_setup_clear(); k_mutex_unlock(&ctx->drv_lock); } ep_ctx->cfg.cb(ep_ctx->cfg.addr, @@ -842,14 +843,14 @@ static inline void usbd_work_process_ep_events(struct usbd_ep_event *ep_evt) } } -static void usbd_event_transfer_ctrl(nrfx_usbd_evt_t const *const p_event) +static void usbd_event_transfer_ctrl(nrf_usbd_common_evt_t const *const p_event) { struct nrf_usbd_ep_ctx *ep_ctx = endpoint_ctx(p_event->data.eptransfer.ep); if (NRF_USBD_EPIN_CHECK(p_event->data.eptransfer.ep)) { switch (p_event->data.eptransfer.status) { - case NRFX_USBD_EP_OK: { + case NRF_USBD_COMMON_EP_OK: { struct usbd_event *ev = usbd_evt_alloc(); if (!ev) { @@ -867,7 +868,7 @@ static void usbd_event_transfer_ctrl(nrfx_usbd_evt_t const *const p_event) } break; - case NRFX_USBD_EP_ABORTED: { + case NRF_USBD_COMMON_EP_ABORTED: { LOG_DBG("Endpoint 0x%02x write aborted", p_event->data.eptransfer.ep); } @@ -882,7 +883,7 @@ static void usbd_event_transfer_ctrl(nrfx_usbd_evt_t const *const p_event) } } else { switch (p_event->data.eptransfer.status) { - case NRFX_USBD_EP_WAITING: { + case NRF_USBD_COMMON_EP_WAITING: { struct usbd_event *ev = usbd_evt_alloc(); if (!ev) { @@ -901,23 +902,23 @@ static void usbd_event_transfer_ctrl(nrfx_usbd_evt_t const *const p_event) } break; - case NRFX_USBD_EP_OK: { + case NRF_USBD_COMMON_EP_OK: { struct nrf_usbd_ctx *ctx = get_usbd_ctx(); struct usbd_event *ev = usbd_evt_alloc(); if (!ev) { return; } - nrfx_usbd_ep_status_t err_code; + nrf_usbd_common_ep_status_t err_code; ev->evt_type = USBD_EVT_EP; ev->evt.ep_evt.evt_type = EP_EVT_RECV_COMPLETE; ev->evt.ep_evt.ep = ep_ctx; - err_code = nrfx_usbd_ep_status_get( + err_code = nrf_usbd_common_ep_status_get( p_event->data.eptransfer.ep, &ep_ctx->buf.len); - if (err_code != NRFX_USBD_EP_OK) { + if (err_code != NRF_USBD_COMMON_EP_OK) { LOG_ERR("_ep_status_get failed! Code: %d", err_code); __ASSERT_NO_MSG(0); @@ -927,7 +928,7 @@ static void usbd_event_transfer_ctrl(nrfx_usbd_evt_t const *const p_event) if (ctx->ctrl_read_len > ep_ctx->buf.len) { ctx->ctrl_read_len -= ep_ctx->buf.len; /* Allow next data chunk on EP0 OUT */ - nrfx_usbd_setup_data_clear(); + nrf_usbd_common_setup_data_clear(); } else { ctx->ctrl_read_len = 0U; } @@ -947,14 +948,14 @@ static void usbd_event_transfer_ctrl(nrfx_usbd_evt_t const *const p_event) } } -static void usbd_event_transfer_data(nrfx_usbd_evt_t const *const p_event) +static void usbd_event_transfer_data(nrf_usbd_common_evt_t const *const p_event) { struct nrf_usbd_ep_ctx *ep_ctx = endpoint_ctx(p_event->data.eptransfer.ep); if (NRF_USBD_EPIN_CHECK(p_event->data.eptransfer.ep)) { switch (p_event->data.eptransfer.status) { - case NRFX_USBD_EP_OK: { + case NRF_USBD_COMMON_EP_OK: { struct usbd_event *ev = usbd_evt_alloc(); if (!ev) { @@ -973,7 +974,7 @@ static void usbd_event_transfer_data(nrfx_usbd_evt_t const *const p_event) } break; - case NRFX_USBD_EP_ABORTED: { + case NRF_USBD_COMMON_EP_ABORTED: { LOG_DBG("Endpoint 0x%02x write aborted", p_event->data.eptransfer.ep); } @@ -989,7 +990,7 @@ static void usbd_event_transfer_data(nrfx_usbd_evt_t const *const p_event) } else { switch (p_event->data.eptransfer.status) { - case NRFX_USBD_EP_WAITING: { + case NRF_USBD_COMMON_EP_WAITING: { struct usbd_event *ev = usbd_evt_alloc(); if (!ev) { @@ -1009,7 +1010,7 @@ static void usbd_event_transfer_data(nrfx_usbd_evt_t const *const p_event) } break; - case NRFX_USBD_EP_OK: { + case NRF_USBD_COMMON_EP_OK: { struct usbd_event *ev = usbd_evt_alloc(); if (!ev) { @@ -1045,42 +1046,42 @@ static void usbd_event_transfer_data(nrfx_usbd_evt_t const *const p_event) /** * @brief nRFx USBD driver event handler function. */ -static void usbd_event_handler(nrfx_usbd_evt_t const *const p_event) +static void usbd_event_handler(nrf_usbd_common_evt_t const *const p_event) { struct usbd_event evt = {0}; bool put_evt = false; switch (p_event->type) { - case NRFX_USBD_EVT_SUSPEND: + case NRF_USBD_COMMON_EVT_SUSPEND: LOG_DBG("SUSPEND state detected"); evt.evt_type = USBD_EVT_POWER; evt.evt.pwr_evt.state = USBD_SUSPENDED; put_evt = true; break; - case NRFX_USBD_EVT_RESUME: + case NRF_USBD_COMMON_EVT_RESUME: LOG_DBG("RESUMING from suspend"); evt.evt_type = USBD_EVT_POWER; evt.evt.pwr_evt.state = USBD_RESUMED; put_evt = true; break; - case NRFX_USBD_EVT_WUREQ: + case NRF_USBD_COMMON_EVT_WUREQ: LOG_DBG("RemoteWU initiated"); evt.evt_type = USBD_EVT_POWER; evt.evt.pwr_evt.state = USBD_RESUMED; put_evt = true; break; - case NRFX_USBD_EVT_RESET: + case NRF_USBD_COMMON_EVT_RESET: evt.evt_type = USBD_EVT_RESET; put_evt = true; break; - case NRFX_USBD_EVT_SOF: + case NRF_USBD_COMMON_EVT_SOF: if (IS_ENABLED(CONFIG_USB_DEVICE_SOF)) { evt.evt_type = USBD_EVT_SOF; put_evt = true; } break; - case NRFX_USBD_EVT_EPTRANSFER: { + case NRF_USBD_COMMON_EVT_EPTRANSFER: { struct nrf_usbd_ep_ctx *ep_ctx; ep_ctx = endpoint_ctx(p_event->data.eptransfer.ep); @@ -1101,10 +1102,10 @@ static void usbd_event_handler(nrfx_usbd_evt_t const *const p_event) break; } - case NRFX_USBD_EVT_SETUP: { - nrfx_usbd_setup_t drv_setup; + case NRF_USBD_COMMON_EVT_SETUP: { + nrf_usbd_common_setup_t drv_setup; - nrfx_usbd_setup_get(&drv_setup); + nrf_usbd_common_setup_get(&drv_setup); if ((drv_setup.bRequest != USB_SREQ_SET_ADDRESS) || (USB_REQTYPE_GET_TYPE(drv_setup.bmRequestType) != USB_REQTYPE_TYPE_STANDARD)) { @@ -1147,8 +1148,8 @@ static inline void usbd_reinit(void) nrfx_err_t err; nrfx_power_usbevt_disable(); - nrfx_usbd_disable(); - nrfx_usbd_uninit(); + nrf_usbd_common_disable(); + nrf_usbd_common_uninit(); usbd_evt_flush(); @@ -1156,7 +1157,7 @@ static inline void usbd_reinit(void) __ASSERT_NO_MSG(ret == 0); nrfx_power_usbevt_enable(); - err = nrfx_usbd_init(usbd_event_handler); + err = nrf_usbd_common_init(usbd_event_handler); if (err != NRFX_SUCCESS) { LOG_DBG("nRF USBD driver reinit failed. Code: %d", err); @@ -1177,7 +1178,7 @@ static void usbd_sof_trigger_iso_read(void) struct usbd_event *ev; struct nrf_usbd_ep_ctx *ep_ctx; - ep_ctx = endpoint_ctx(NRFX_USBD_EPOUT8); + ep_ctx = endpoint_ctx(NRF_USBD_COMMON_EPOUT8); if (!ep_ctx) { LOG_ERR("There is no ISO ep"); return; @@ -1281,7 +1282,7 @@ int usb_dc_attach(void) (CLOCK_CONTROL_NRF_SUBSYS_HF))); IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), - nrfx_isr, nrfx_usbd_irq_handler, 0); + nrfx_isr, nrf_usbd_common_irq_handler, 0); nrfx_power_usbevt_enable(); @@ -1316,8 +1317,8 @@ int usb_dc_detach(void) usbd_evt_flush(); - if (nrfx_usbd_is_enabled()) { - nrfx_usbd_disable(); + if (nrf_usbd_common_is_enabled()) { + nrf_usbd_common_disable(); } (void)hfxo_stop(ctx); @@ -1397,6 +1398,12 @@ int usb_dc_ep_check_cap(const struct usb_dc_ep_cfg_data *const ep_cfg) return -1; } + if ((ep_cfg->ep_type != USB_DC_EP_ISOCHRONOUS) && + (NRF_USBD_EPISO_CHECK(ep_cfg->ep_addr))) { + LOG_WRN("iso endpoint can only be iso"); + return -1; + } + return 0; } @@ -1434,8 +1441,8 @@ int usb_dc_ep_configure(const struct usb_dc_ep_cfg_data *const ep_cfg) } } - nrfx_usbd_ep_max_packet_size_set(ep_addr_to_nrfx(ep_cfg->ep_addr), - ep_cfg->ep_mps); + nrf_usbd_common_ep_max_packet_size_set(ep_addr_to_nrfx(ep_cfg->ep_addr), + ep_cfg->ep_mps); return 0; } @@ -1455,11 +1462,11 @@ int usb_dc_ep_set_stall(const uint8_t ep) switch (ep_ctx->cfg.type) { case USB_DC_EP_CONTROL: - nrfx_usbd_setup_stall(); + nrf_usbd_common_setup_stall(); break; case USB_DC_EP_BULK: case USB_DC_EP_INTERRUPT: - nrfx_usbd_ep_stall(ep_addr_to_nrfx(ep)); + nrf_usbd_common_ep_stall(ep_addr_to_nrfx(ep)); break; case USB_DC_EP_ISOCHRONOUS: LOG_ERR("STALL unsupported on ISO endpoint"); @@ -1493,8 +1500,8 @@ int usb_dc_ep_clear_stall(const uint8_t ep) return -EINVAL; } - nrfx_usbd_ep_dtoggle_clear(ep_addr_to_nrfx(ep)); - nrfx_usbd_ep_stall_clear(ep_addr_to_nrfx(ep)); + nrf_usbd_common_ep_dtoggle_clear(ep_addr_to_nrfx(ep)); + nrf_usbd_common_ep_stall_clear(ep_addr_to_nrfx(ep)); LOG_DBG("Unstall on EP 0x%02x", ep); return 0; @@ -1522,7 +1529,7 @@ int usb_dc_ep_is_stalled(const uint8_t ep, uint8_t *const stalled) return -EINVAL; } - *stalled = (uint8_t) nrfx_usbd_ep_stall_check(ep_addr_to_nrfx(ep)); + *stalled = (uint8_t) nrf_usbd_common_ep_stall_check(ep_addr_to_nrfx(ep)); return 0; } @@ -1544,11 +1551,11 @@ int usb_dc_ep_enable(const uint8_t ep) /* ISO transactions for full-speed device do not support * toggle sequencing and should only send DATA0 PID. */ - nrfx_usbd_ep_dtoggle_clear(ep_addr_to_nrfx(ep)); + nrf_usbd_common_ep_dtoggle_clear(ep_addr_to_nrfx(ep)); /** Endpoint is enabled on SetInterface request. * This should also clear EP's halt status. */ - nrfx_usbd_ep_stall_clear(ep_addr_to_nrfx(ep)); + nrf_usbd_common_ep_stall_clear(ep_addr_to_nrfx(ep)); } if (ep_ctx->cfg.en) { return -EALREADY; @@ -1560,7 +1567,7 @@ int usb_dc_ep_enable(const uint8_t ep) /* Defer the endpoint enable if USBD is not ready yet. */ if (dev_ready()) { - nrfx_usbd_ep_enable(ep_addr_to_nrfx(ep)); + nrf_usbd_common_ep_enable(ep_addr_to_nrfx(ep)); } return 0; @@ -1581,8 +1588,8 @@ int usb_dc_ep_disable(const uint8_t ep) LOG_DBG("EP disable: 0x%02x", ep); - nrfx_usbd_ep_disable(ep_addr_to_nrfx(ep)); - /* Clear write_in_progress as nrfx_usbd_ep_disable() + nrf_usbd_common_ep_disable(ep_addr_to_nrfx(ep)); + /* Clear write_in_progress as nrf_usbd_common_ep_disable() * terminates endpoint transaction. */ ep_ctx->write_in_progress = false; @@ -1608,7 +1615,7 @@ int usb_dc_ep_flush(const uint8_t ep) ep_ctx->buf.len = 0U; ep_ctx->buf.curr = ep_ctx->buf.data; - nrfx_usbd_transfer_out_drop(ep_addr_to_nrfx(ep)); + nrf_usbd_common_transfer_out_drop(ep_addr_to_nrfx(ep)); return 0; } @@ -1676,15 +1683,15 @@ int usb_dc_ep_write(const uint8_t ep, const uint8_t *const data, * and perform appropriate action. */ if ((ep_ctx->cfg.type == USB_DC_EP_CONTROL) - && (nrfx_usbd_last_setup_dir_get() != ep)) { - nrfx_usbd_setup_clear(); + && (nrf_usbd_common_last_setup_dir_get() != ep)) { + nrf_usbd_common_setup_clear(); k_mutex_unlock(&ctx->drv_lock); return 0; } ep_ctx->write_in_progress = true; - NRFX_USBD_TRANSFER_IN(transfer, data, data_len, 0); - nrfx_err_t err = nrfx_usbd_ep_transfer(ep_addr_to_nrfx(ep), &transfer); + NRF_USBD_COMMON_TRANSFER_IN(transfer, data, data_len, 0); + nrfx_err_t err = nrf_usbd_common_ep_transfer(ep_addr_to_nrfx(ep), &transfer); if (err != NRFX_SUCCESS) { ep_ctx->write_in_progress = false; @@ -1864,7 +1871,7 @@ int usb_dc_ep_mps(const uint8_t ep) int usb_dc_wakeup_request(void) { - bool res = nrfx_usbd_wakeup_req(); + bool res = nrf_usbd_common_wakeup_req(); if (!res) { return -EAGAIN; @@ -1900,7 +1907,7 @@ static int usb_init(void) .handler = usb_dc_power_event_handler }; - err = nrfx_usbd_init(usbd_event_handler); + err = nrf_usbd_common_init(usbd_event_handler); if (err != NRFX_SUCCESS) { LOG_DBG("nRF USBD driver init failed. Code: %d", (uint32_t)err); return -EIO; diff --git a/drivers/usb/udc/Kconfig.nrf b/drivers/usb/udc/Kconfig.nrf index 0f424ffe5d0..93c5090bed2 100644 --- a/drivers/usb/udc/Kconfig.nrf +++ b/drivers/usb/udc/Kconfig.nrf @@ -5,7 +5,7 @@ config UDC_NRF bool "Nordic Semiconductor USB device controller driver" default y depends on DT_HAS_NORDIC_NRF_USBD_ENABLED - select NRFX_USBD + select NRF_USBD_COMMON select NRFX_POWER help nRF USB device controller driver. diff --git a/drivers/usb/udc/udc_nrf.c b/drivers/usb/udc/udc_nrf.c index 4610aff19f8..bca098347d8 100644 --- a/drivers/usb/udc/udc_nrf.c +++ b/drivers/usb/udc/udc_nrf.c @@ -21,7 +21,8 @@ #include #include -#include +#include +#include #include #include "udc_common.h" @@ -47,7 +48,7 @@ enum udc_nrf_event_type { struct udc_nrf_evt { enum udc_nrf_event_type type; union { - nrfx_usbd_evt_t hal_evt; + nrf_usbd_common_evt_t hal_evt; uint8_t ep; }; }; @@ -82,10 +83,10 @@ static struct onoff_client hfxo_cli; static void udc_nrf_clear_control_out(const struct device *dev) { - if (nrfx_usbd_last_setup_dir_get() == USB_CONTROL_EP_OUT && + if (nrf_usbd_common_last_setup_dir_get() == USB_CONTROL_EP_OUT && udc_nrf_setup_rcvd) { /* Allow data chunk on EP0 OUT */ - nrfx_usbd_setup_data_clear(); + nrf_usbd_common_setup_data_clear(); udc_nrf_setup_rcvd = false; LOG_INF("Allow data OUT"); } @@ -101,15 +102,15 @@ static void udc_event_xfer_in_next(const struct device *dev, const uint8_t ep) buf = udc_buf_peek(dev, ep); if (buf != NULL) { - nrfx_usbd_transfer_t xfer = { + nrf_usbd_common_transfer_t xfer = { .p_data = {.tx = buf->data}, .size = buf->len, .flags = udc_ep_buf_has_zlp(buf) ? - NRFX_USBD_TRANSFER_ZLP_FLAG : 0, + NRF_USBD_COMMON_TRANSFER_ZLP_FLAG : 0, }; nrfx_err_t err; - err = nrfx_usbd_ep_transfer(ep, &xfer); + err = nrf_usbd_common_ep_transfer(ep, &xfer); if (err != NRFX_SUCCESS) { LOG_ERR("ep 0x%02x nrfx error: %x", ep, err); /* REVISE: remove from endpoint queue? ASSERT? */ @@ -141,7 +142,7 @@ static void udc_event_xfer_ctrl_in(const struct device *dev, /* Update to next stage of control transfer */ udc_ctrl_update_stage(dev, buf); - nrfx_usbd_setup_clear(); + nrf_usbd_common_setup_clear(); } static void udc_event_fake_status_in(const struct device *dev) @@ -159,13 +160,13 @@ static void udc_event_fake_status_in(const struct device *dev) } static void udc_event_xfer_in(const struct device *dev, - nrfx_usbd_evt_t const *const event) + nrf_usbd_common_evt_t const *const event) { uint8_t ep = event->data.eptransfer.ep; struct net_buf *buf; switch (event->data.eptransfer.status) { - case NRFX_USBD_EP_OK: + case NRF_USBD_COMMON_EP_OK: buf = udc_buf_get(dev, ep); if (buf == NULL) { LOG_ERR("ep 0x%02x queue is empty", ep); @@ -181,7 +182,7 @@ static void udc_event_xfer_in(const struct device *dev, udc_submit_ep_event(dev, buf, 0); break; - case NRFX_USBD_EP_ABORTED: + case NRF_USBD_COMMON_EP_ABORTED: LOG_WRN("aborted IN ep 0x%02x", ep); buf = udc_buf_get_all(dev, ep); @@ -228,14 +229,14 @@ static void udc_event_xfer_out_next(const struct device *dev, const uint8_t ep) buf = udc_buf_peek(dev, ep); if (buf != NULL) { - nrfx_usbd_transfer_t xfer = { + nrf_usbd_common_transfer_t xfer = { .p_data = {.rx = buf->data}, .size = buf->size, .flags = 0, }; nrfx_err_t err; - err = nrfx_usbd_ep_transfer(ep, &xfer); + err = nrf_usbd_common_ep_transfer(ep, &xfer); if (err != NRFX_SUCCESS) { LOG_ERR("ep 0x%02x nrfx error: %x", ep, err); /* REVISE: remove from endpoint queue? ASSERT? */ @@ -249,24 +250,24 @@ static void udc_event_xfer_out_next(const struct device *dev, const uint8_t ep) } static void udc_event_xfer_out(const struct device *dev, - nrfx_usbd_evt_t const *const event) + nrf_usbd_common_evt_t const *const event) { uint8_t ep = event->data.eptransfer.ep; - nrfx_usbd_ep_status_t err_code; + nrf_usbd_common_ep_status_t err_code; struct net_buf *buf; size_t len; switch (event->data.eptransfer.status) { - case NRFX_USBD_EP_WAITING: + case NRF_USBD_COMMON_EP_WAITING: /* * There is nothing to do here, new transfer * will be tried in both cases later. */ break; - case NRFX_USBD_EP_OK: - err_code = nrfx_usbd_ep_status_get(ep, &len); - if (err_code != NRFX_USBD_EP_OK) { + case NRF_USBD_COMMON_EP_OK: + err_code = nrf_usbd_common_ep_status_get(ep, &len); + if (err_code != NRF_USBD_COMMON_EP_OK) { LOG_ERR("OUT transfer failed %d", err_code); } @@ -325,8 +326,8 @@ static int udc_event_xfer_setup(const struct device *dev) } udc_ep_buf_set_setup(buf); - nrfx_usbd_setup_get((nrfx_usbd_setup_t *)buf->data); - net_buf_add(buf, sizeof(nrfx_usbd_setup_t)); + nrf_usbd_common_setup_get((nrf_usbd_common_setup_t *)buf->data); + net_buf_add(buf, sizeof(nrf_usbd_common_setup_t)); udc_nrf_setup_rcvd = true; /* Update to next stage of control transfer */ @@ -348,8 +349,13 @@ static int udc_event_xfer_setup(const struct device *dev) return err; } -static void udc_nrf_thread(const struct device *dev) +static void udc_nrf_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; + while (true) { bool start_xfer = false; struct udc_nrf_evt evt; @@ -361,7 +367,7 @@ static void udc_nrf_thread(const struct device *dev) case UDC_NRF_EVT_HAL: ep = evt.hal_evt.data.eptransfer.ep; switch (evt.hal_evt.type) { - case NRFX_USBD_EVT_EPTRANSFER: + case NRF_USBD_COMMON_EVT_EPTRANSFER: start_xfer = true; if (USB_EP_DIR_IS_IN(ep)) { udc_event_xfer_in(dev, &evt.hal_evt); @@ -369,7 +375,7 @@ static void udc_nrf_thread(const struct device *dev) udc_event_xfer_out(dev, &evt.hal_evt); } break; - case NRFX_USBD_EVT_SETUP: + case NRF_USBD_COMMON_EVT_SETUP: udc_event_xfer_setup(dev); break; default: @@ -414,33 +420,33 @@ static void udc_sof_check_iso_out(const struct device *dev) } } -static void usbd_event_handler(nrfx_usbd_evt_t const *const hal_evt) +static void usbd_event_handler(nrf_usbd_common_evt_t const *const hal_evt) { switch (hal_evt->type) { - case NRFX_USBD_EVT_SUSPEND: + case NRF_USBD_COMMON_EVT_SUSPEND: LOG_INF("SUSPEND state detected"); - nrfx_usbd_suspend(); + nrf_usbd_common_suspend(); udc_set_suspended(udc_nrf_dev, true); udc_submit_event(udc_nrf_dev, UDC_EVT_SUSPEND, 0); break; - case NRFX_USBD_EVT_RESUME: + case NRF_USBD_COMMON_EVT_RESUME: LOG_INF("RESUMING from suspend"); udc_set_suspended(udc_nrf_dev, false); udc_submit_event(udc_nrf_dev, UDC_EVT_RESUME, 0); break; - case NRFX_USBD_EVT_WUREQ: + case NRF_USBD_COMMON_EVT_WUREQ: LOG_INF("Remote wakeup initiated"); break; - case NRFX_USBD_EVT_RESET: + case NRF_USBD_COMMON_EVT_RESET: LOG_INF("Reset"); udc_submit_event(udc_nrf_dev, UDC_EVT_RESET, 0); break; - case NRFX_USBD_EVT_SOF: + case NRF_USBD_COMMON_EVT_SOF: udc_submit_event(udc_nrf_dev, UDC_EVT_SOF, 0); udc_sof_check_iso_out(udc_nrf_dev); break; - case NRFX_USBD_EVT_EPTRANSFER: - case NRFX_USBD_EVT_SETUP: { + case NRF_USBD_COMMON_EVT_EPTRANSFER: + case NRF_USBD_COMMON_EVT_SETUP: { struct udc_nrf_evt evt = { .type = UDC_NRF_EVT_HAL, .hal_evt = *hal_evt, @@ -466,7 +472,7 @@ static void udc_nrf_power_handler(nrfx_power_usb_evt_t pwr_evt) case NRFX_POWER_USB_EVT_READY: LOG_INF("POWER event ready"); udc_submit_event(udc_nrf_dev, UDC_EVT_VBUS_READY, 0); - nrfx_usbd_start(true); + nrf_usbd_common_start(true); break; case NRFX_POWER_USB_EVT_REMOVED: LOG_INF("POWER event removed"); @@ -484,7 +490,7 @@ static void udc_nrf_fake_status_in(const struct device *dev) .ep = USB_CONTROL_EP_IN, }; - if (nrfx_usbd_last_setup_dir_get() == USB_CONTROL_EP_OUT) { + if (nrf_usbd_common_last_setup_dir_get() == USB_CONTROL_EP_OUT) { /* Let controller perform status IN stage */ k_msgq_put(&drv_msgq, &evt, K_NO_WAIT); } @@ -514,9 +520,9 @@ static int udc_nrf_ep_enqueue(const struct device *dev, static int udc_nrf_ep_dequeue(const struct device *dev, struct udc_ep_config *cfg) { - bool busy = nrfx_usbd_ep_is_busy(cfg->addr); + bool busy = nrf_usbd_common_ep_is_busy(cfg->addr); - nrfx_usbd_ep_abort(cfg->addr); + nrf_usbd_common_ep_abort(cfg->addr); if (USB_EP_DIR_IS_OUT(cfg->addr) || !busy) { struct net_buf *buf; @@ -545,14 +551,14 @@ static int udc_nrf_ep_enable(const struct device *dev, __ASSERT_NO_MSG(cfg); mps = (cfg->mps == 0) ? cfg->caps.mps : cfg->mps; - nrfx_usbd_ep_max_packet_size_set(cfg->addr, mps); - nrfx_usbd_ep_enable(cfg->addr); + nrf_usbd_common_ep_max_packet_size_set(cfg->addr, mps); + nrf_usbd_common_ep_enable(cfg->addr); if (!NRF_USBD_EPISO_CHECK(cfg->addr)) { /* ISO transactions for full-speed device do not support * toggle sequencing and should only send DATA0 PID. */ - nrfx_usbd_ep_dtoggle_clear(cfg->addr); - nrfx_usbd_ep_stall_clear(cfg->addr); + nrf_usbd_common_ep_dtoggle_clear(cfg->addr); + nrf_usbd_common_ep_stall_clear(cfg->addr); } LOG_DBG("Enable ep 0x%02x", cfg->addr); @@ -564,7 +570,7 @@ static int udc_nrf_ep_disable(const struct device *dev, struct udc_ep_config *cfg) { __ASSERT_NO_MSG(cfg); - nrfx_usbd_ep_disable(cfg->addr); + nrf_usbd_common_ep_disable(cfg->addr); LOG_DBG("Disable ep 0x%02x", cfg->addr); return 0; @@ -577,9 +583,9 @@ static int udc_nrf_ep_set_halt(const struct device *dev, if (cfg->addr == USB_CONTROL_EP_OUT || cfg->addr == USB_CONTROL_EP_IN) { - nrfx_usbd_setup_stall(); + nrf_usbd_common_setup_stall(); } else { - nrfx_usbd_ep_stall(cfg->addr); + nrf_usbd_common_ep_stall(cfg->addr); } return 0; @@ -590,8 +596,8 @@ static int udc_nrf_ep_clear_halt(const struct device *dev, { LOG_DBG("Clear halt ep 0x%02x", cfg->addr); - nrfx_usbd_ep_dtoggle_clear(cfg->addr); - nrfx_usbd_ep_stall_clear(cfg->addr); + nrf_usbd_common_ep_dtoggle_clear(cfg->addr); + nrf_usbd_common_ep_stall_clear(cfg->addr); return 0; } @@ -611,7 +617,7 @@ static int udc_nrf_set_address(const struct device *dev, const uint8_t addr) static int udc_nrf_host_wakeup(const struct device *dev) { - bool res = nrfx_usbd_wakeup_req(); + bool res = nrf_usbd_common_wakeup_req(); LOG_DBG("Host wakeup request"); if (!res) { @@ -625,7 +631,7 @@ static int udc_nrf_enable(const struct device *dev) { int ret; - nrfx_usbd_enable(); + nrf_usbd_common_enable(); sys_notify_init_spinwait(&hfxo_cli.notify); ret = onoff_request(hfxo_mgr, &hfxo_cli); @@ -641,7 +647,7 @@ static int udc_nrf_disable(const struct device *dev) { int ret; - nrfx_usbd_disable(); + nrf_usbd_common_disable(); ret = onoff_cancel_or_release(hfxo_mgr, &hfxo_cli); if (ret < 0) { @@ -670,12 +676,12 @@ static int udc_nrf_init(const struct device *dev) #endif IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), - nrfx_isr, nrfx_usbd_irq_handler, 0); + nrfx_isr, nrf_usbd_common_irq_handler, 0); (void)nrfx_power_init(&cfg->pwr); nrfx_power_usbevt_init(&cfg->evt); - ret = nrfx_usbd_init(usbd_event_handler); + ret = nrf_usbd_common_init(usbd_event_handler); if (ret != NRFX_SUCCESS) { LOG_ERR("nRF USBD driver initialization failed"); return -EIO; @@ -714,7 +720,7 @@ static int udc_nrf_shutdown(const struct device *dev) } nrfx_power_usbevt_disable(); - nrfx_usbd_uninit(); + nrf_usbd_common_uninit(); nrfx_power_usbevt_uninit(); #ifdef CONFIG_HAS_HW_NRF_USBREG irq_disable(USBREGULATOR_IRQn); @@ -733,7 +739,7 @@ static int udc_nrf_driver_init(const struct device *dev) k_mutex_init(&data->mutex); k_thread_create(&drv_stack_data, drv_stack, K_KERNEL_STACK_SIZEOF(drv_stack), - (k_thread_entry_t)udc_nrf_thread, + udc_nrf_thread, (void *)dev, NULL, NULL, K_PRIO_COOP(8), 0, K_NO_WAIT); @@ -743,14 +749,14 @@ static int udc_nrf_driver_init(const struct device *dev) ep_cfg_out[i].caps.out = 1; if (i == 0) { ep_cfg_out[i].caps.control = 1; - ep_cfg_out[i].caps.mps = NRFX_USBD_EPSIZE; + ep_cfg_out[i].caps.mps = NRF_USBD_COMMON_EPSIZE; } else if (i < (CFG_EPOUT_CNT + 1)) { ep_cfg_out[i].caps.bulk = 1; ep_cfg_out[i].caps.interrupt = 1; - ep_cfg_out[i].caps.mps = NRFX_USBD_EPSIZE; + ep_cfg_out[i].caps.mps = NRF_USBD_COMMON_EPSIZE; } else { ep_cfg_out[i].caps.iso = 1; - ep_cfg_out[i].caps.mps = NRFX_USBD_ISOSIZE / 2; + ep_cfg_out[i].caps.mps = NRF_USBD_COMMON_ISOSIZE / 2; } ep_cfg_out[i].addr = USB_EP_DIR_OUT | i; @@ -765,14 +771,14 @@ static int udc_nrf_driver_init(const struct device *dev) ep_cfg_in[i].caps.in = 1; if (i == 0) { ep_cfg_in[i].caps.control = 1; - ep_cfg_in[i].caps.mps = NRFX_USBD_EPSIZE; + ep_cfg_in[i].caps.mps = NRF_USBD_COMMON_EPSIZE; } else if (i < (CFG_EPIN_CNT + 1)) { ep_cfg_in[i].caps.bulk = 1; ep_cfg_in[i].caps.interrupt = 1; - ep_cfg_in[i].caps.mps = NRFX_USBD_EPSIZE; + ep_cfg_in[i].caps.mps = NRF_USBD_COMMON_EPSIZE; } else { ep_cfg_in[i].caps.iso = 1; - ep_cfg_in[i].caps.mps = NRFX_USBD_ISOSIZE / 2; + ep_cfg_in[i].caps.mps = NRF_USBD_COMMON_ISOSIZE / 2; } ep_cfg_in[i].addr = USB_EP_DIR_IN | i; diff --git a/drivers/usb/uhc/uhc_common.c b/drivers/usb/uhc/uhc_common.c index 659be150117..15377500a66 100644 --- a/drivers/usb/uhc/uhc_common.c +++ b/drivers/usb/uhc/uhc_common.c @@ -21,13 +21,11 @@ NET_BUF_POOL_VAR_DEFINE(uhc_ep_pool, int uhc_submit_event(const struct device *dev, const enum uhc_event_type type, - const int status, - struct uhc_transfer *const xfer) + const int status) { struct uhc_data *data = dev->data; struct uhc_event drv_evt = { .type = type, - .xfer = xfer, .status = status, .dev = dev, }; @@ -43,10 +41,18 @@ void uhc_xfer_return(const struct device *dev, struct uhc_transfer *const xfer, const int err) { + struct uhc_data *data = dev->data; + struct uhc_event drv_evt = { + .type = UHC_EVT_EP_REQUEST, + .xfer = xfer, + .dev = dev, + }; + sys_dlist_remove(&xfer->node); xfer->queued = 0; - xfer->claimed = 0; - uhc_submit_event(dev, UHC_EVT_EP_REQUEST, err, xfer); + xfer->err = err; + + data->event_cb(dev, &drv_evt); } struct uhc_transfer *uhc_xfer_get_next(const struct device *dev) @@ -74,13 +80,25 @@ int uhc_xfer_append(const struct device *dev, return 0; } +struct net_buf *uhc_xfer_buf_alloc(const struct device *dev, + const size_t size) +{ + return net_buf_alloc_len(&uhc_ep_pool, size, K_NO_WAIT); +} + +void uhc_xfer_buf_free(const struct device *dev, struct net_buf *const buf) +{ + net_buf_unref(buf); +} + struct uhc_transfer *uhc_xfer_alloc(const struct device *dev, const uint8_t addr, const uint8_t ep, const uint8_t attrib, const uint16_t mps, const uint16_t timeout, - void *const owner) + void *const udev, + void *const cb) { const struct uhc_api *api = dev->api; struct uhc_transfer *xfer = NULL; @@ -91,8 +109,8 @@ struct uhc_transfer *uhc_xfer_alloc(const struct device *dev, goto xfer_alloc_error; } - LOG_DBG("Allocate xfer, ep 0x%02x attrib 0x%02x owner %p", - ep, attrib, owner); + LOG_DBG("Allocate xfer, ep 0x%02x attrib 0x%02x cb %p", + ep, attrib, cb); if (k_mem_slab_alloc(&uhc_xfer_pool, (void **)&xfer, K_NO_WAIT)) { LOG_ERR("Failed to allocate transfer"); @@ -100,14 +118,13 @@ struct uhc_transfer *uhc_xfer_alloc(const struct device *dev, } memset(xfer, 0, sizeof(struct uhc_transfer)); - k_fifo_init(&xfer->queue); - k_fifo_init(&xfer->done); xfer->addr = addr; xfer->ep = ep; xfer->attrib = attrib; xfer->mps = mps; xfer->timeout = timeout; - xfer->owner = owner; + xfer->udev = udev; + xfer->cb = cb; xfer_alloc_error: api->unlock(dev); @@ -115,84 +132,70 @@ struct uhc_transfer *uhc_xfer_alloc(const struct device *dev, return xfer; } -int uhc_xfer_free(const struct device *dev, struct uhc_transfer *const xfer) +struct uhc_transfer *uhc_xfer_alloc_with_buf(const struct device *dev, + const uint8_t addr, + const uint8_t ep, + const uint8_t attrib, + const uint16_t mps, + const uint16_t timeout, + void *const udev, + void *const cb, + size_t size) { - const struct uhc_api *api = dev->api; + struct uhc_transfer *xfer; struct net_buf *buf; - int ret = 0; - - api->lock(dev); - if (xfer->queued || xfer->claimed) { - ret = -EBUSY; - LOG_ERR("Transfer is still claimed"); - goto xfer_free_error; + buf = uhc_xfer_buf_alloc(dev, size); + if (buf == NULL) { + return NULL; } - while (!k_fifo_is_empty(&xfer->queue)) { - buf = net_buf_get(&xfer->queue, K_NO_WAIT); - uhc_xfer_buf_free(dev, buf); - } - - while (!k_fifo_is_empty(&xfer->done)) { - buf = net_buf_get(&xfer->done, K_NO_WAIT); - uhc_xfer_buf_free(dev, buf); + xfer = uhc_xfer_alloc(dev, addr, ep, attrib, mps, timeout, udev, cb); + if (xfer == NULL) { + net_buf_unref(buf); + return NULL; } - k_mem_slab_free(&uhc_xfer_pool, (void *)xfer); - -xfer_free_error: - api->unlock(dev); + xfer->buf = buf; - return ret; + return xfer; } -struct net_buf *uhc_xfer_buf_alloc(const struct device *dev, - struct uhc_transfer *const xfer, - const size_t size) +int uhc_xfer_free(const struct device *dev, struct uhc_transfer *const xfer) { const struct uhc_api *api = dev->api; - struct net_buf *buf = NULL; + int ret = 0; api->lock(dev); - if (!uhc_is_initialized(dev)) { - goto buf_alloc_error; - } - - if (xfer->queued || xfer->claimed) { - goto buf_alloc_error; - } - - LOG_DBG("Allocate net_buf, ep 0x%02x, size %zd", xfer->ep, size); - buf = net_buf_alloc_len(&uhc_ep_pool, size, K_NO_WAIT); - if (!buf) { - LOG_ERR("Failed to allocate net_buf"); - goto buf_alloc_error; - } - - if (buf->size < size) { - LOG_ERR("Buffer is smaller than requested"); - net_buf_unref(buf); - buf = NULL; - goto buf_alloc_error; + if (xfer->queued) { + ret = -EBUSY; + LOG_ERR("Transfer is still queued"); + goto xfer_free_error; } - k_fifo_put(&xfer->queue, &buf->node); + k_mem_slab_free(&uhc_xfer_pool, (void *)xfer); -buf_alloc_error: +xfer_free_error: api->unlock(dev); - return buf; + return ret; } -int uhc_xfer_buf_free(const struct device *dev, struct net_buf *const buf) +int uhc_xfer_buf_add(const struct device *dev, + struct uhc_transfer *const xfer, + struct net_buf *buf) { const struct uhc_api *api = dev->api; int ret = 0; api->lock(dev); - net_buf_unref(buf); + if (xfer->queued) { + ret = -EBUSY; + } else { + xfer->buf = buf; + } + api->unlock(dev); return ret; @@ -210,12 +213,13 @@ int uhc_ep_enqueue(const struct device *dev, struct uhc_transfer *const xfer) goto ep_enqueue_error; } - xfer->claimed = 1; + xfer->queued = 1; ret = api->ep_enqueue(dev, xfer); if (ret) { - xfer->claimed = 0; + xfer->queued = 0; } + ep_enqueue_error: api->unlock(dev); @@ -235,6 +239,7 @@ int uhc_ep_dequeue(const struct device *dev, struct uhc_transfer *const xfer) } ret = api->ep_dequeue(dev, xfer); + xfer->queued = 0; ep_dequeue_error: api->unlock(dev); diff --git a/drivers/usb/uhc/uhc_common.h b/drivers/usb/uhc/uhc_common.h index f6c487b0dc8..e8b276cf239 100644 --- a/drivers/usb/uhc/uhc_common.h +++ b/drivers/usb/uhc/uhc_common.h @@ -58,54 +58,6 @@ static inline int uhc_unlock_internal(const struct device *dev) return k_mutex_unlock(&data->mutex); } -/** - * @brief Checks if the transfer is queued. - * - * @param[in] xfer Pointer to UHC transfer - * - * @return true if transfer is queued, false otherwise - */ -static inline bool uhc_xfer_is_queued(struct uhc_transfer *xfer) -{ - return xfer->queued; -} - -/** - * @brief Helper function to set queued flag - * - * This function can be used by the driver to set queued flag - * - * @param[in] xfer Pointer to UHC transfer - */ -static inline void uhc_xfer_queued(struct uhc_transfer *xfer) -{ - xfer->queued = true; -} - -/** - * @brief Checks if the setup flag is set. - * - * @param[in] xfer Pointer to UHC transfer - * - * @return true if setup flagh is set, false otherwise - */ -static inline bool uhc_xfer_is_setup(struct uhc_transfer *xfer) -{ - return xfer->setup; -} - -/** - * @brief Helper function to set setup flag - * - * This function can be used by the driver to set setup flag - * - * @param[in] xfer Pointer to UHC transfer - */ -static inline void uhc_xfer_setup(struct uhc_transfer *xfer) -{ - xfer->setup = true; -} - /** * @brief Helper function to return UHC transfer to a higher level. * @@ -119,29 +71,6 @@ void uhc_xfer_return(const struct device *dev, struct uhc_transfer *const xfer, const int err); -/** - * @brief Helper to move current buffer in the done-FIFO. - * - * Helper to move current buffer (probably completed) in the - * designated done-FIFO. - * - * @param[in] xfer Pointer to UHC transfer - * - * @return 0 on success, all other values should be treated as error. - * @retval -ENOMEM if there is no buffer in the queue - */ -static inline int uhc_xfer_done(struct uhc_transfer *xfer) -{ - struct net_buf *buf; - - buf = k_fifo_get(&xfer->queue, K_NO_WAIT); - if (buf) { - k_fifo_put(&xfer->done, &buf->node); - } - - return buf == NULL ? -ENOMEM : 0; -} - /** * @brief Helper to get next transfer to process. * @@ -173,14 +102,12 @@ int uhc_xfer_append(const struct device *dev, * @param[in] dev Pointer to device struct of the driver instance * @param[in] type Event type * @param[in] status Event status - * @param[in] xfer Pointer to UHC transfer * * @return 0 on success, all other values should be treated as error. * @retval -EPERM controller is not initialized */ int uhc_submit_event(const struct device *dev, const enum uhc_event_type type, - const int status, - struct uhc_transfer *const xfer); + const int status); #endif /* ZEPHYR_INCLUDE_UHC_COMMON_H */ diff --git a/drivers/usb/uhc/uhc_max3421e.c b/drivers/usb/uhc/uhc_max3421e.c index 0ab41d0ea9a..ac9aa2a526d 100644 --- a/drivers/usb/uhc/uhc_max3421e.c +++ b/drivers/usb/uhc/uhc_max3421e.c @@ -310,28 +310,19 @@ static int max3421e_xfer_control(const struct device *dev, const uint8_t hrsl) { struct max3421e_data *priv = uhc_get_private(dev); - struct net_buf *buf; + struct net_buf *buf = xfer->buf; int ret; /* Just restart if device NAKed packet */ - if (uhc_xfer_is_queued(xfer) && HRSLT_IS_NAK(hrsl)) { + if (HRSLT_IS_NAK(hrsl)) { return max3421e_hxfr_start(dev, priv->hxfr); } - buf = k_fifo_peek_head(&xfer->queue); - if (buf == NULL) { - LOG_ERR("No buffers to handle"); - return -ENODATA; - } - if (!uhc_xfer_is_queued(xfer) && xfer->setup) { - return -EINVAL; - } - - if (!xfer->setup) { - /* Handle SETUP stage */ + if (xfer->stage == UHC_CONTROL_STAGE_SETUP) { + LOG_DBG("Handle SETUP stage"); ret = max3421e_write(dev, MAX3421E_REG_SUDFIFO, - buf->data, MIN(buf->len, 8)); + xfer->setup_pkt, sizeof(xfer->setup_pkt)); if (ret) { return ret; } @@ -341,25 +332,26 @@ static int max3421e_xfer_control(const struct device *dev, return ret; } - uhc_xfer_setup(xfer); - uhc_xfer_queued(xfer); - return 0; } - if (buf->size != 0) { - /* handle DATA stage */ - ret = max3421e_xfer_data(dev, buf, xfer->ep); - } else { - /* handle ACK stage */ + if (buf != NULL && xfer->stage == UHC_CONTROL_STAGE_DATA) { + LOG_DBG("Handle DATA stage"); + return max3421e_xfer_data(dev, buf, xfer->ep); + } + + if (xfer->stage == UHC_CONTROL_STAGE_STATUS) { + LOG_DBG("Handle STATUS stage"); if (USB_EP_DIR_IS_IN(xfer->ep)) { ret = max3421e_hxfr_start(dev, MAX3421E_HXFR_HSOUT(0)); } else { ret = max3421e_hxfr_start(dev, MAX3421E_HXFR_HSIN(0)); } + + return ret; } - return ret; + return -EINVAL; } static int max3421e_xfer_bulk(const struct device *dev, @@ -367,26 +359,19 @@ static int max3421e_xfer_bulk(const struct device *dev, const uint8_t hrsl) { struct max3421e_data *priv = uhc_get_private(dev); - struct net_buf *buf; - int ret; + struct net_buf *buf = xfer->buf; /* Just restart if device NAKed packet */ - if (uhc_xfer_is_queued(xfer) && HRSLT_IS_NAK(hrsl)) { + if (HRSLT_IS_NAK(hrsl)) { return max3421e_hxfr_start(dev, priv->hxfr); } - buf = k_fifo_peek_head(&xfer->queue); if (buf == NULL) { - LOG_ERR("No buffers to handle"); + LOG_ERR("No buffer to handle"); return -ENODATA; } - ret = max3421e_xfer_data(dev, buf, xfer->ep); - if (!ret) { - uhc_xfer_queued(xfer); - } - - return ret; + return max3421e_xfer_data(dev, buf, xfer->ep); } static int max3421e_schedule_xfer(const struct device *dev) @@ -444,27 +429,27 @@ static int max3421e_hrslt_success(const struct device *dev) { struct max3421e_data *priv = uhc_get_private(dev); struct uhc_transfer *const xfer = priv->last_xfer; - struct net_buf *buf; + struct net_buf *buf = xfer->buf; + bool finished = false; int err = 0; size_t len; uint8_t bc; - buf = k_fifo_peek_head(&xfer->queue); - if (buf == NULL) { - return -ENODATA; - } - switch (MAX3421E_HXFR_TYPE(priv->hxfr)) { case MAX3421E_HXFR_TYPE_SETUP: - err = uhc_xfer_done(xfer); + if (xfer->buf != NULL) { + xfer->stage = UHC_CONTROL_STAGE_DATA; + } else { + xfer->stage = UHC_CONTROL_STAGE_STATUS; + } break; case MAX3421E_HXFR_TYPE_HSOUT: LOG_DBG("HSOUT"); - err = uhc_xfer_done(xfer); + finished = true; break; case MAX3421E_HXFR_TYPE_HSIN: LOG_DBG("HSIN"); - err = uhc_xfer_done(xfer); + finished = true; break; case MAX3421E_HXFR_TYPE_ISOOUT: LOG_ERR("ISO OUT is not implemented"); @@ -477,7 +462,11 @@ static int max3421e_hrslt_success(const struct device *dev) case MAX3421E_HXFR_TYPE_BULKOUT: if (buf->len == 0) { LOG_INF("hrslt bulk out %u", buf->len); - err = uhc_xfer_done(xfer); + if (xfer->ep == USB_CONTROL_EP_OUT) { + xfer->stage = UHC_CONTROL_STAGE_STATUS; + } else { + finished = true; + } } break; case MAX3421E_HXFR_TYPE_BULKIN: @@ -502,11 +491,25 @@ static int max3421e_hrslt_success(const struct device *dev) if (bc < MAX3421E_MAX_EP_SIZE || !net_buf_tailroom(buf)) { LOG_INF("hrslt bulk in %u, %u", bc, len); - err = uhc_xfer_done(xfer); + if (xfer->ep == USB_CONTROL_EP_IN) { + xfer->stage = UHC_CONTROL_STAGE_STATUS; + } else { + finished = true; + } } break; } + if (finished) { + LOG_DBG("Transfer finished"); + uhc_xfer_return(dev, xfer, 0); + priv->last_xfer = NULL; + } + + if (err) { + max3421e_xfer_drop_active(dev, err); + } + return err; } @@ -515,27 +518,13 @@ static int max3421e_handle_hxfrdn(const struct device *dev) struct max3421e_data *priv = uhc_get_private(dev); struct uhc_transfer *const xfer = priv->last_xfer; const uint8_t hrsl = priv->hrsl; - int ret; + int ret = 0; if (xfer == NULL) { LOG_ERR("No transfers to handle"); return -ENODATA; } - /* If an active xfer is not marked then something has gone wrong */ - if (!uhc_xfer_is_queued(xfer)) { - LOG_ERR("Active transfer not queued"); - max3421e_xfer_drop_active(dev, -EINVAL); - return -EINVAL; - } - - /* There should always be a buffer in the fifo when a xfer is active */ - if (k_fifo_is_empty(&xfer->queue)) { - LOG_ERR("No buffers to handle"); - max3421e_xfer_drop_active(dev, -ENODATA); - return -ENODATA; - } - switch (MAX3421E_HRSLT(hrsl)) { case MAX3421E_HR_NAK: /* @@ -549,27 +538,15 @@ static int max3421e_handle_hxfrdn(const struct device *dev) max3421e_xfer_drop_active(dev, -ETIMEDOUT); } - ret = 0; break; case MAX3421E_HR_STALL: max3421e_xfer_drop_active(dev, -EPIPE); - ret = 0; break; case MAX3421E_HR_TOGERR: LOG_WRN("Toggle error"); - ret = 0; break; case MAX3421E_HR_SUCCESS: ret = max3421e_hrslt_success(dev); - if (ret) { - max3421e_xfer_drop_active(dev, ret); - } else { - if (k_fifo_is_empty(&xfer->queue)) { - uhc_xfer_return(dev, xfer, 0); - priv->last_xfer = NULL; - } - } - break; default: /* TODO: Handle all reasonalbe result codes */ @@ -578,7 +555,7 @@ static int max3421e_handle_hxfrdn(const struct device *dev) break; } - return 0; + return ret; } static void max3421e_handle_condet(const struct device *dev) @@ -607,7 +584,7 @@ static void max3421e_handle_condet(const struct device *dev) type = UHC_EVT_DEV_CONNECTED_LS; } - uhc_submit_event(dev, type, 0, NULL); + uhc_submit_event(dev, type, 0); } static void max3421e_bus_event(const struct device *dev) @@ -617,13 +594,13 @@ static void max3421e_bus_event(const struct device *dev) if (atomic_test_and_clear_bit(&priv->state, MAX3421E_STATE_BUS_RESUME)) { /* Resume operation done event */ - uhc_submit_event(dev, UHC_EVT_RESUMED, 0, NULL); + uhc_submit_event(dev, UHC_EVT_RESUMED, 0); } if (atomic_test_and_clear_bit(&priv->state, MAX3421E_STATE_BUS_RESET)) { /* Reset operation done event */ - uhc_submit_event(dev, UHC_EVT_RESETED, 0, NULL); + uhc_submit_event(dev, UHC_EVT_RESETED, 0); } } @@ -654,7 +631,7 @@ static int max3421e_handle_bus_irq(const struct device *dev) /* Suspend operation Done Interrupt (bus suspended) */ if (hirq & MAX3421E_SUSDN) { ret = max3421e_hien_disable(dev, MAX3421E_SUSDN); - uhc_submit_event(dev, UHC_EVT_SUSPENDED, 0, NULL); + uhc_submit_event(dev, UHC_EVT_SUSPENDED, 0); } /* Peripheral Connect/Disconnect Interrupt */ @@ -664,7 +641,7 @@ static int max3421e_handle_bus_irq(const struct device *dev) /* Remote Wakeup Interrupt */ if (hirq & MAX3421E_RWU) { - uhc_submit_event(dev, UHC_EVT_RWUP, 0, NULL); + uhc_submit_event(dev, UHC_EVT_RWUP, 0); } /* Bus Reset or Bus Resume event */ @@ -675,8 +652,12 @@ static int max3421e_handle_bus_irq(const struct device *dev) return ret; } -static void uhc_max3421e_thread(const struct device *dev) +static void uhc_max3421e_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; struct max3421e_data *priv = uhc_get_private(dev); LOG_DBG("MAX3421E thread started"); @@ -695,7 +676,7 @@ static void uhc_max3421e_thread(const struct device *dev) */ err = max3421e_update_hrsl_hirq(dev); if (unlikely(err)) { - uhc_submit_event(dev, UHC_EVT_ERROR, err, NULL); + uhc_submit_event(dev, UHC_EVT_ERROR, err); } /* Host Transfer Done Interrupt */ @@ -713,20 +694,20 @@ static void uhc_max3421e_thread(const struct device *dev) if (priv->hirq & ~(MAX3421E_FRAME | MAX3421E_HXFRDN)) { err = max3421e_handle_bus_irq(dev); if (unlikely(err)) { - uhc_submit_event(dev, UHC_EVT_ERROR, err, NULL); + uhc_submit_event(dev, UHC_EVT_ERROR, err); } } /* Clear interrupts and schedule new bus transfer */ err = max3421e_clear_hirq(dev, priv->hirq); if (unlikely(err)) { - uhc_submit_event(dev, UHC_EVT_ERROR, err, NULL); + uhc_submit_event(dev, UHC_EVT_ERROR, err); } if (schedule) { err = max3421e_schedule_xfer(dev); if (unlikely(err)) { - uhc_submit_event(dev, UHC_EVT_ERROR, err, NULL); + uhc_submit_event(dev, UHC_EVT_ERROR, err); } } @@ -1099,7 +1080,7 @@ static int max3421e_driver_init(const struct device *dev) k_mutex_init(&data->mutex); k_thread_create(&drv_stack_data, drv_stack, K_KERNEL_STACK_SIZEOF(drv_stack), - (k_thread_entry_t)uhc_max3421e_thread, + uhc_max3421e_thread, (void *)dev, NULL, NULL, K_PRIO_COOP(2), 0, K_NO_WAIT); k_thread_name_set(&drv_stack_data, "uhc_max3421e"); diff --git a/drivers/usb/uhc/uhc_virtual.c b/drivers/usb/uhc/uhc_virtual.c index b6b044353d9..9e33f755573 100644 --- a/drivers/usb/uhc/uhc_virtual.c +++ b/drivers/usb/uhc/uhc_virtual.c @@ -78,24 +78,16 @@ static int vrt_xfer_control(const struct device *dev, struct uhc_transfer *const xfer) { struct uhc_vrt_data *priv = uhc_get_private(dev); + struct net_buf *buf = xfer->buf; struct uvb_packet *uvb_pkt; - struct net_buf *buf; + uint8_t *data = NULL; + size_t length = 0; - buf = k_fifo_peek_head(&xfer->queue); - if (buf == NULL) { - LOG_ERR("No buffers to handle"); - return -ENODATA; - } - - if (!uhc_xfer_is_queued(xfer) && xfer->setup) { - return -EINVAL; - } - - if (!xfer->setup) { + if (xfer->stage == UHC_CONTROL_STAGE_SETUP) { LOG_DBG("Handle SETUP stage"); uvb_pkt = uvb_alloc_pkt(UVB_REQUEST_SETUP, xfer->addr, USB_CONTROL_EP_OUT, - buf->data, buf->len); + xfer->setup_pkt, sizeof(xfer->setup_pkt)); if (uvb_pkt == NULL) { LOG_ERR("Failed to allocate UVB packet"); return -ENOMEM; @@ -103,17 +95,11 @@ static int vrt_xfer_control(const struct device *dev, priv->req = UVB_REQUEST_SETUP; priv->busy = true; - uhc_xfer_setup(xfer); - uhc_xfer_queued(xfer); return uvb_advert_pkt(priv->host_node, uvb_pkt); } - if (buf->size != 0) { - uint8_t *data; - size_t length; - - LOG_DBG("Handle DATA stage"); + if (buf != NULL && xfer->stage == UHC_CONTROL_STAGE_DATA) { if (USB_EP_DIR_IS_IN(xfer->ep)) { length = MIN(net_buf_tailroom(buf), xfer->mps); data = net_buf_tail(buf); @@ -122,6 +108,7 @@ static int vrt_xfer_control(const struct device *dev, data = buf->data; } + LOG_DBG("Handle DATA stage"); uvb_pkt = uvb_alloc_pkt(UVB_REQUEST_DATA, xfer->addr, xfer->ep, data, length); @@ -132,7 +119,11 @@ static int vrt_xfer_control(const struct device *dev, priv->req = UVB_REQUEST_DATA; priv->busy = true; - } else { + + return uvb_advert_pkt(priv->host_node, uvb_pkt); + } + + if (xfer->stage == UHC_CONTROL_STAGE_STATUS) { uint8_t ep; LOG_DBG("Handle STATUS stage"); @@ -144,7 +135,7 @@ static int vrt_xfer_control(const struct device *dev, uvb_pkt = uvb_alloc_pkt(UVB_REQUEST_DATA, xfer->addr, ep, - buf->data, 0); + NULL, 0); if (uvb_pkt == NULL) { LOG_ERR("Failed to allocate UVB packet"); return -ENOMEM; @@ -152,26 +143,21 @@ static int vrt_xfer_control(const struct device *dev, priv->req = UVB_REQUEST_DATA; priv->busy = true; + + return uvb_advert_pkt(priv->host_node, uvb_pkt); } - return uvb_advert_pkt(priv->host_node, uvb_pkt); + return -EINVAL; } static int vrt_xfer_bulk(const struct device *dev, struct uhc_transfer *const xfer) { struct uhc_vrt_data *priv = uhc_get_private(dev); + struct net_buf *buf = xfer->buf; struct uvb_packet *uvb_pkt; - struct net_buf *buf; uint8_t *data; size_t length; - int ret; - - buf = k_fifo_peek_head(&xfer->queue); - if (buf == NULL) { - LOG_ERR("No buffers to handle"); - return -ENODATA; - } if (USB_EP_DIR_IS_IN(xfer->ep)) { length = MIN(net_buf_tailroom(buf), xfer->mps); @@ -188,12 +174,7 @@ static int vrt_xfer_bulk(const struct device *dev, return -ENOMEM; } - ret = uvb_advert_pkt(priv->host_node, uvb_pkt); - if (!ret) { - uhc_xfer_queued(xfer); - } - - return ret; + return uvb_advert_pkt(priv->host_node, uvb_pkt); } static int vrt_schedule_xfer(const struct device *dev) @@ -218,31 +199,41 @@ static int vrt_schedule_xfer(const struct device *dev) return vrt_xfer_bulk(dev, priv->last_xfer); } -static int vrt_hrslt_success(const struct device *dev, - struct uvb_packet *const pkt) +static void vrt_hrslt_success(const struct device *dev, + struct uvb_packet *const pkt) { struct uhc_vrt_data *priv = uhc_get_private(dev); struct uhc_transfer *const xfer = priv->last_xfer; - struct net_buf *buf; + struct net_buf *buf = xfer->buf; + bool finished = false; size_t length; - int err = 0; - - buf = k_fifo_peek_head(&xfer->queue); - if (buf == NULL) { - return -ENODATA; - } switch (pkt->request) { case UVB_REQUEST_SETUP: - err = uhc_xfer_done(xfer); + if (xfer->buf != NULL) { + xfer->stage = UHC_CONTROL_STAGE_DATA; + } else { + xfer->stage = UHC_CONTROL_STAGE_STATUS; + } + break; case UVB_REQUEST_DATA: + if (xfer->stage == UHC_CONTROL_STAGE_STATUS) { + LOG_DBG("Status stage finished"); + finished = true; + break; + } + if (USB_EP_DIR_IS_OUT(pkt->ep)) { length = MIN(buf->len, xfer->mps); net_buf_pull(buf, length); LOG_DBG("OUT chunk %zu out of %u", length, buf->len); if (buf->len == 0) { - err = uhc_xfer_done(xfer); + if (pkt->ep == USB_CONTROL_EP_OUT) { + xfer->stage = UHC_CONTROL_STAGE_STATUS; + } else { + finished = true; + } } } else { length = MIN(net_buf_tailroom(buf), pkt->length); @@ -254,13 +245,21 @@ static int vrt_hrslt_success(const struct device *dev, LOG_DBG("IN chunk %zu out of %zu", length, net_buf_tailroom(buf)); if (pkt->length < xfer->mps || !net_buf_tailroom(buf)) { - err = uhc_xfer_done(xfer); + if (pkt->ep == USB_CONTROL_EP_IN) { + xfer->stage = UHC_CONTROL_STAGE_STATUS; + } else { + finished = true; + } } } break; } - return err; + if (finished) { + LOG_DBG("Transfer finished"); + uhc_xfer_return(dev, xfer, 0); + priv->last_xfer = NULL; + } } static void vrt_xfer_drop_active(const struct device *dev, int err) @@ -278,7 +277,7 @@ static int vrt_handle_reply(const struct device *dev, { struct uhc_vrt_data *priv = uhc_get_private(dev); struct uhc_transfer *const xfer = priv->last_xfer; - int ret; + int ret = 0; if (xfer == NULL) { LOG_ERR("No transfers to handle"); @@ -286,47 +285,19 @@ static int vrt_handle_reply(const struct device *dev, goto handle_reply_err; } - /* If an active xfer is not marked then something has gone wrong */ - if (!uhc_xfer_is_queued(xfer)) { - LOG_ERR("Active transfer not queued"); - vrt_xfer_drop_active(dev, -EINVAL); - ret = -EINVAL; - goto handle_reply_err; - } - - /* There should always be a buffer in the fifo when a xfer is active */ - if (k_fifo_is_empty(&xfer->queue)) { - LOG_ERR("No buffers to handle"); - vrt_xfer_drop_active(dev, -ENODATA); - ret = -ENODATA; - goto handle_reply_err; - } + priv->busy = false; switch (pkt->reply) { case UVB_REPLY_NACK: /* Restart last transaction */ - priv->busy = false; break; case UVB_REPLY_STALL: vrt_xfer_drop_active(dev, -EPIPE); - priv->busy = false; break; case UVB_REPLY_ACK: - ret = vrt_hrslt_success(dev, pkt); - priv->busy = false; - if (ret) { - vrt_xfer_drop_active(dev, ret); - } else { - if (k_fifo_is_empty(&xfer->queue)) { - LOG_DBG("Transfer done"); - uhc_xfer_return(dev, xfer, 0); - priv->last_xfer = NULL; - } - } - + vrt_hrslt_success(dev, pkt); break; default: - priv->busy = false; vrt_xfer_drop_active(dev, -EINVAL); ret = -EINVAL; break; @@ -349,7 +320,11 @@ static void xfer_work_handler(struct k_work *work) switch (ev->type) { case UHC_VRT_EVT_REPLY: - vrt_handle_reply(dev, ev->pkt); + err = vrt_handle_reply(dev, ev->pkt); + if (unlikely(err)) { + uhc_submit_event(dev, UHC_EVT_ERROR, err); + } + schedule = true; break; case UHC_VRT_EVT_XFER: @@ -374,7 +349,7 @@ static void xfer_work_handler(struct k_work *work) if (schedule && !priv->busy) { err = vrt_schedule_xfer(dev); if (unlikely(err)) { - uhc_submit_event(dev, UHC_EVT_ERROR, err, NULL); + uhc_submit_event(dev, UHC_EVT_ERROR, err); } } @@ -411,7 +386,7 @@ static void vrt_device_act(const struct device *dev, type = UHC_EVT_ERROR; } - uhc_submit_event(dev, type, 0, NULL); + uhc_submit_event(dev, type, 0); } static void uhc_vrt_uvb_cb(const void *const vrt_priv, diff --git a/drivers/usb_c/tcpc/CMakeLists.txt b/drivers/usb_c/tcpc/CMakeLists.txt index b81aa5224d6..cc5eaf71ea6 100644 --- a/drivers/usb_c/tcpc/CMakeLists.txt +++ b/drivers/usb_c/tcpc/CMakeLists.txt @@ -2,4 +2,5 @@ zephyr_library() +zephyr_library_sources_ifdef(CONFIG_USBC_TCPC_SHELL shell.c) zephyr_library_sources_ifdef(CONFIG_USBC_TCPC_STM32 ucpd_stm32.c) diff --git a/drivers/usb_c/tcpc/Kconfig b/drivers/usb_c/tcpc/Kconfig index 1e30c3cef1e..8d0e2ad1017 100644 --- a/drivers/usb_c/tcpc/Kconfig +++ b/drivers/usb_c/tcpc/Kconfig @@ -10,8 +10,8 @@ menuconfig USBC_TCPC_DRIVER if USBC_TCPC_DRIVER -config USBC_INIT_PRIORITY - int "USBC driver init priority" +config USBC_TCPC_INIT_PRIORITY + int "USB-C TCPC driver init priority" default 80 help USB-C device driver initialization priority. @@ -19,6 +19,12 @@ config USBC_INIT_PRIORITY Note that the priority needs to be lower than the USBC stack so that it can start before the USBC sub-system. +config USBC_TCPC_SHELL + bool "Shell commands for TCPC subsystem" + help + Enable support for TCPC shell commands that helps with USB-C diagnostics. + Example functions are printing vbus, chip information and dumping registers. + source "drivers/usb_c/tcpc/Kconfig.tcpc_stm32" module = USBC diff --git a/drivers/usb_c/tcpc/shell.c b/drivers/usb_c/tcpc/shell.c new file mode 100644 index 00000000000..43ea2a9077c --- /dev/null +++ b/drivers/usb_c/tcpc/shell.c @@ -0,0 +1,157 @@ +/* + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +/** Macro used to call the dump_std_reg function from the TCPC device pointer */ +#define TCPC_DUMP_DEV(dev) ret |= tcpc_dump_std_reg(dev); + +/** Macro used to call the dump_std_reg function from the USB-C connector node */ +#define TCPC_DUMP_CONN_NODE(node) TCPC_DUMP_DEV(DEVICE_DT_GET(DT_PROP(node, tcpc))) + +/** Macro used to call the vbus_measure function from the VBUS device pointer */ +#define TCPC_VBUS_DEV(dev) \ + { \ + int val; \ + ret |= usbc_vbus_measure(dev, &val); \ + shell_print(sh, "%s vbus: %d mV", dev->name, val); \ + } + +/** Macro used to call the vbus_measure function from the USB-C connector node */ +#define TCPC_VBUS_CONN_NODE(node) TCPC_VBUS_DEV(DEVICE_DT_GET(DT_PROP(node, vbus))) + +/** Macro used to call the get_chip function from the TCPC device pointer */ +#define TCPC_GET_CHIP_DEV(dev) \ + { \ + ret |= tcpc_get_chip_info(dev, &chip_info); \ + shell_print(sh, "Chip: %s", dev->name); \ + shell_print(sh, "\tVendor: %04x", chip_info.vendor_id); \ + shell_print(sh, "\tProduct: %04x", chip_info.product_id); \ + shell_print(sh, "\tDevice: %04x", chip_info.device_id); \ + shell_print(sh, "\tFirmware: %llx", chip_info.fw_version_number); \ + } + +/** Macro used to call the get_chip function from the USB-C connector node */ +#define TCPC_GET_CHIP_CONN_NODE(node) TCPC_GET_CHIP_DEV(DEVICE_DT_GET(DT_PROP(node, tcpc))) + +/** + * @brief Shell command that dumps standard registers of TCPCs for all available USB-C ports + * + * @param sh Shell structure + * @param argc Arguments count + * @param argv Device name + * @return int ORed return values of all the functions executed, 0 in case of success + */ +static int cmd_tcpc_dump(const struct shell *sh, size_t argc, char **argv) +{ + int ret = 0; + + if (argc <= 1) { + DT_FOREACH_STATUS_OKAY(usb_c_connector, TCPC_DUMP_CONN_NODE); + } else { + const struct device *dev = device_get_binding(argv[1]); + + if (dev != NULL) { + TCPC_DUMP_DEV(dev); + } else { + ret = -ENODEV; + } + } + + return ret; +} + +/** + * @brief Shell command that prints the vbus measures for all available USB-C ports + * + * @param sh Shell structure + * @param argc Arguments count + * @param argv Device name + * @return int ORed return values of all the functions executed, 0 in case of success + */ +static int cmd_tcpc_vbus(const struct shell *sh, size_t argc, char **argv) +{ + int ret = 0; + + if (argc <= 1) { + DT_FOREACH_STATUS_OKAY(usb_c_connector, TCPC_VBUS_CONN_NODE); + } else { + const struct device *dev = device_get_binding(argv[1]); + + if (dev != NULL) { + TCPC_VBUS_DEV(dev); + } else { + ret = -ENODEV; + } + } + + return ret; +} + +/** + * @brief Shell command that prints the TCPCs chips information for all available USB-C ports + * + * @param sh Shell structure + * @param argc Arguments count + * @param argv Device name + * @return int ORed return values of all the functions executed, 0 in case of success + */ +static int cmd_tcpc_chip_info(const struct shell *sh, size_t argc, char **argv) +{ + struct tcpc_chip_info chip_info; + int ret = 0; + + if (argc <= 1) { + DT_FOREACH_STATUS_OKAY(usb_c_connector, TCPC_GET_CHIP_CONN_NODE); + } else { + const struct device *dev = device_get_binding(argv[1]); + + if (dev != NULL) { + TCPC_GET_CHIP_DEV(dev); + } else { + ret = -ENODEV; + } + } + + return ret; +} + +/** + * @brief Function used to create subcommands with devices names + * + * @param idx counter of devices + * @param entry shell structure that will be filled + */ +static void device_name_get(size_t idx, struct shell_static_entry *entry) +{ + const struct device *dev = shell_device_lookup(idx, NULL); + + entry->syntax = (dev != NULL) ? dev->name : NULL; + entry->handler = NULL; + entry->help = NULL; + entry->subcmd = NULL; +} + +SHELL_DYNAMIC_CMD_CREATE(list_device_names, device_name_get); + +SHELL_STATIC_SUBCMD_SET_CREATE(sub_tcpc_cmds, + SHELL_CMD_ARG(dump, &list_device_names, + "Dump TCPC registers\n" + "Usage: tcpc dump []", + cmd_tcpc_dump, 1, 1), + SHELL_CMD_ARG(vbus, &list_device_names, + "Display VBUS voltage\n" + "Usage: tcpc vbus []", + cmd_tcpc_vbus, 1, 1), + SHELL_CMD_ARG(chip, &list_device_names, + "Display chip information\n" + "Usage: tcpc chip []", + cmd_tcpc_chip_info, 1, 1), + SHELL_SUBCMD_SET_END); + +SHELL_CMD_REGISTER(tcpc, &sub_tcpc_cmds, "TCPC (USB-C PD) diagnostics", NULL); diff --git a/drivers/usb_c/tcpc/ucpd_stm32.c b/drivers/usb_c/tcpc/ucpd_stm32.c index 812ddfaa7a1..2fca84346fc 100644 --- a/drivers/usb_c/tcpc/ucpd_stm32.c +++ b/drivers/usb_c/tcpc/ucpd_stm32.c @@ -1024,45 +1024,25 @@ static int ucpd_transmit_data(const struct device *dev, return 0; } -/** - * @brief Tests if a received Power Delivery message is pending - * - * @retval true if message is pending, else false - */ -static bool ucpd_is_rx_pending_msg(const struct device *dev, - enum pd_packet_type *type) -{ - struct tcpc_data *data = dev->data; - bool ret; - - ret = (*(uint32_t *)data->ucpd_rx_buffer > 0); - - if (ret & (type != NULL)) { - *type = *(uint16_t *)data->ucpd_rx_buffer; - } - - return ret; -} - /** * @brief Retrieves the Power Delivery message from the TCPC * - * @retval number of bytes received - * @retval -EIO on no message to retrieve - * @retval -EFAULT on buf being NULL + * @retval number of bytes received if msg parameter is provided + * @retval 0 if there is a message pending and the msg parameter is NULL + * @retval -ENODATA if there is no pending message */ -static int ucpd_receive_data(const struct device *dev, struct pd_msg *msg) +static int ucpd_get_rx_pending_msg(const struct device *dev, struct pd_msg *msg) { struct tcpc_data *data = dev->data; int ret = 0; - if (msg == NULL) { - return -EFAULT; + /* Make sure we have a message to retrieve */ + if (*(uint32_t *)data->ucpd_rx_buffer == 0) { + return -ENODATA; } - /* Make sure we have a message to retrieve */ - if (!ucpd_is_rx_pending_msg(dev, NULL)) { - return -EIO; + if (msg == NULL) { + return 0; } msg->type = *(uint16_t *)data->ucpd_rx_buffer; @@ -1386,7 +1366,7 @@ static int ucpd_init(const struct device *dev) LOG_DBG("Pinctrl signals configuration"); ret = pinctrl_apply_state(config->ucpd_pcfg, PINCTRL_STATE_DEFAULT); - if (ret < 0) { + if (ret != 0) { LOG_ERR("USB pinctrl setup failed (%d)", ret); return ret; } @@ -1443,8 +1423,7 @@ static const struct tcpc_driver_api driver_api = { .set_alert_handler_cb = ucpd_set_alert_handler_cb, .get_cc = ucpd_get_cc, .set_rx_enable = ucpd_set_rx_enable, - .is_rx_pending_msg = ucpd_is_rx_pending_msg, - .receive_data = ucpd_receive_data, + .get_rx_pending_msg = ucpd_get_rx_pending_msg, .transmit_data = ucpd_transmit_data, .select_rp_value = ucpd_select_rp_value, .get_rp_value = ucpd_get_rp_value, @@ -1500,7 +1479,7 @@ BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) > 0, &drv_data_##inst, \ &drv_config_##inst, \ POST_KERNEL, \ - CONFIG_USBC_INIT_PRIORITY, \ + CONFIG_USBC_TCPC_INIT_PRIORITY, \ &driver_api); DT_INST_FOREACH_STATUS_OKAY(TCPC_DRIVER_INIT) diff --git a/drivers/usb_c/vbus/Kconfig b/drivers/usb_c/vbus/Kconfig index 36e20e3c382..5b368a944ae 100644 --- a/drivers/usb_c/vbus/Kconfig +++ b/drivers/usb_c/vbus/Kconfig @@ -10,6 +10,12 @@ menuconfig USBC_VBUS_DRIVER if USBC_VBUS_DRIVER +config USBC_VBUS_INIT_PRIORITY + int "USB-C VBUS driver init priority" + default 85 + help + Initialization priority of the USB-C VBUS measurement drivers in POST_KERNEL. + source "drivers/usb_c/vbus/Kconfig.usbc_vbus_adc" endif # USBC_VBUS_DRIVER diff --git a/drivers/usb_c/vbus/usbc_vbus_adc.c b/drivers/usb_c/vbus/usbc_vbus_adc.c index 6ed645795d2..1b2d576a3ed 100644 --- a/drivers/usb_c/vbus/usbc_vbus_adc.c +++ b/drivers/usb_c/vbus/usbc_vbus_adc.c @@ -146,13 +146,12 @@ static int adc_vbus_init(const struct device *dev) /* Configure VBUS Measurement enable pin if defined */ if (gcp->port) { - ret = device_is_ready(gcp->port); - if (ret < 0) { + if (!device_is_ready(gcp->port)) { LOG_ERR("%s: device not ready", gcp->port->name); - return ret; + return -EIO; } ret = gpio_pin_configure_dt(gcp, GPIO_OUTPUT_INACTIVE); - if (ret < 0) { + if (ret != 0) { LOG_ERR("Failed to control feed %s.%u: %d", gcp->port->name, gcp->pin, ret); return ret; @@ -161,13 +160,12 @@ static int adc_vbus_init(const struct device *dev) /* Configure VBUS Discharge pin if defined */ if (gcd->port) { - ret = device_is_ready(gcd->port); - if (ret == false) { + if (!device_is_ready(gcd->port)) { LOG_ERR("%s: device not ready", gcd->port->name); - return ret; + return -EIO; } ret = gpio_pin_configure_dt(gcd, GPIO_OUTPUT_INACTIVE); - if (ret < 0) { + if (ret != 0) { LOG_ERR("Failed to control feed %s.%u: %d", gcd->port->name, gcd->pin, ret); return ret; @@ -179,13 +177,13 @@ static int adc_vbus_init(const struct device *dev) data->sequence.buffer_size = sizeof(data->sample); ret = adc_channel_setup_dt(&config->adc_channel); - if (ret < 0) { + if (ret != 0) { LOG_INF("Could not setup channel (%d)\n", ret); return ret; } ret = adc_sequence_init_dt(&config->adc_channel, &data->sequence); - if (ret < 0) { + if (ret != 0) { LOG_INF("Could not init sequence (%d)\n", ret); return ret; } @@ -218,7 +216,7 @@ BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) > 0, &drv_data_##inst, \ &drv_config_##inst, \ POST_KERNEL, \ - CONFIG_USBC_INIT_PRIORITY, \ + CONFIG_USBC_VBUS_INIT_PRIORITY, \ &driver_api); DT_INST_FOREACH_STATUS_OKAY(DRIVER_INIT) diff --git a/drivers/virtualization/virt_ivshmem_handlers.c b/drivers/virtualization/virt_ivshmem_handlers.c index bd49b8949eb..821ab16f304 100644 --- a/drivers/virtualization/virt_ivshmem_handlers.c +++ b/drivers/virtualization/virt_ivshmem_handlers.c @@ -5,14 +5,14 @@ */ #include -#include +#include #include static inline size_t z_vrfy_ivshmem_get_mem(const struct device *dev, uintptr_t *memmap) { - Z_OOPS(Z_SYSCALL_DRIVER_IVSHMEM(dev, get_mem)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(memmap, sizeof(uintptr_t))); + K_OOPS(K_SYSCALL_DRIVER_IVSHMEM(dev, get_mem)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(memmap, sizeof(uintptr_t))); return z_impl_ivshmem_get_mem(dev, memmap); } @@ -20,7 +20,7 @@ static inline size_t z_vrfy_ivshmem_get_mem(const struct device *dev, static inline uint32_t z_vrfy_ivshmem_get_id(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_IVSHMEM(dev, get_id)); + K_OOPS(K_SYSCALL_DRIVER_IVSHMEM(dev, get_id)); return z_impl_ivshmem_get_id(dev); } @@ -28,7 +28,7 @@ static inline uint32_t z_vrfy_ivshmem_get_id(const struct device *dev) static inline uint16_t z_vrfy_ivshmem_get_vectors(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_IVSHMEM(dev, get_vectors)); + K_OOPS(K_SYSCALL_DRIVER_IVSHMEM(dev, get_vectors)); return z_impl_ivshmem_get_vectors(dev); } @@ -37,7 +37,7 @@ static inline uint16_t z_vrfy_ivshmem_get_vectors(const struct device *dev) static inline int z_vrfy_ivshmem_int_peer(const struct device *dev, uint32_t peer_id, uint16_t vector) { - Z_OOPS(Z_SYSCALL_DRIVER_IVSHMEM(dev, int_peer)); + K_OOPS(K_SYSCALL_DRIVER_IVSHMEM(dev, int_peer)); return z_impl_ivshmem_int_peer(dev, peer_id, vector); } @@ -47,8 +47,8 @@ static inline int z_vrfy_ivshmem_register_handler(const struct device *dev, struct k_poll_signal *signal, uint16_t vector) { - Z_OOPS(Z_SYSCALL_DRIVER_IVSHMEM(dev, register_handler)); - Z_OOPS(Z_SYSCALL_OBJ(signal, K_OBJ_POLL_SIGNAL)); + K_OOPS(K_SYSCALL_DRIVER_IVSHMEM(dev, register_handler)); + K_OOPS(K_SYSCALL_OBJ(signal, K_OBJ_POLL_SIGNAL)); return z_impl_ivshmem_register_handler(dev, signal, vector); } @@ -59,8 +59,8 @@ static inline int z_vrfy_ivshmem_register_handler(const struct device *dev, static inline size_t z_vrfy_ivshmem_get_rw_mem_section(const struct device *dev, uintptr_t *memmap) { - Z_OOPS(Z_SYSCALL_DRIVER_IVSHMEM(dev, get_rw_mem_section)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(memmap, sizeof(uintptr_t))); + K_OOPS(K_SYSCALL_DRIVER_IVSHMEM(dev, get_rw_mem_section)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(memmap, sizeof(uintptr_t))); return z_impl_ivshmem_get_rw_mem_section(dev, memmap); } @@ -70,8 +70,8 @@ static inline size_t z_vrfy_ivshmem_get_output_mem_section(const struct device * uint32_t peer_id, uintptr_t *memmap) { - Z_OOPS(Z_SYSCALL_DRIVER_IVSHMEM(dev, get_output_mem_section)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(memmap, sizeof(uintptr_t))); + K_OOPS(K_SYSCALL_DRIVER_IVSHMEM(dev, get_output_mem_section)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(memmap, sizeof(uintptr_t))); return z_impl_ivshmem_get_output_mem_section(dev, peer_id, memmap); } @@ -80,7 +80,7 @@ static inline size_t z_vrfy_ivshmem_get_output_mem_section(const struct device * static inline uint32_t z_vrfy_ivshmem_get_state(const struct device *dev, uint32_t peer_id) { - Z_OOPS(Z_SYSCALL_DRIVER_IVSHMEM(dev, get_state)); + K_OOPS(K_SYSCALL_DRIVER_IVSHMEM(dev, get_state)); return z_impl_ivshmem_get_state(dev, peer_id); } @@ -89,7 +89,7 @@ static inline uint32_t z_vrfy_ivshmem_get_state(const struct device *dev, static inline int z_vrfy_ivshmem_set_state(const struct device *dev, uint32_t state) { - Z_OOPS(Z_SYSCALL_DRIVER_IVSHMEM(dev, set_state)); + K_OOPS(K_SYSCALL_DRIVER_IVSHMEM(dev, set_state)); return z_impl_ivshmem_set_state(dev, state); } @@ -97,7 +97,7 @@ static inline int z_vrfy_ivshmem_set_state(const struct device *dev, static inline uint32_t z_vrfy_ivshmem_get_max_peers(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_IVSHMEM(dev, get_max_peers)); + K_OOPS(K_SYSCALL_DRIVER_IVSHMEM(dev, get_max_peers)); return z_impl_ivshmem_get_max_peers(dev); } @@ -105,7 +105,7 @@ static inline uint32_t z_vrfy_ivshmem_get_max_peers(const struct device *dev) static inline uint16_t z_vrfy_ivshmem_get_protocol(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_IVSHMEM(dev, get_protocol)); + K_OOPS(K_SYSCALL_DRIVER_IVSHMEM(dev, get_protocol)); return z_impl_ivshmem_get_protocol(dev); } @@ -114,7 +114,7 @@ static inline uint16_t z_vrfy_ivshmem_get_protocol(const struct device *dev) static inline int z_vrfy_ivshmem_enable_interrupts(const struct device *dev, bool enable) { - Z_OOPS(Z_SYSCALL_DRIVER_IVSHMEM(dev, enable_interrupts)); + K_OOPS(K_SYSCALL_DRIVER_IVSHMEM(dev, enable_interrupts)); return z_impl_ivshmem_enable_interrupts(dev, enable); } diff --git a/drivers/virtualization/virt_ivshmem_shell.c b/drivers/virtualization/virt_ivshmem_shell.c index ebf92578597..6c9dc9631a5 100644 --- a/drivers/virtualization/virt_ivshmem_shell.c +++ b/drivers/virtualization/virt_ivshmem_shell.c @@ -23,8 +23,13 @@ K_THREAD_STACK_DEFINE(doorbell_stack, STACK_SIZE); static bool doorbell_started; static struct k_thread doorbell_thread; -static void doorbell_notification_thread(const struct shell *sh) +static void doorbell_notification_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct shell *sh = p1; + while (1) { unsigned int signaled; int vector; @@ -174,7 +179,7 @@ static int cmd_ivshmem_get_notified(const struct shell *sh, tid = k_thread_create( &doorbell_thread, doorbell_stack, STACK_SIZE, - (k_thread_entry_t)doorbell_notification_thread, + doorbell_notification_thread, (void *)sh, NULL, NULL, K_PRIO_COOP(2), 0, K_NO_WAIT); if (!tid) { diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig index 2fabe874b6d..a63a5741981 100644 --- a/drivers/w1/Kconfig +++ b/drivers/w1/Kconfig @@ -26,7 +26,6 @@ config W1_INIT_PRIORITY config W1_SHELL bool "1-Wire Shell" depends on SHELL - default y if !SHELL_MINIMAL help Enable 1-Wire Shell for testing. diff --git a/drivers/w1/Kconfig.zephyr_serial b/drivers/w1/Kconfig.zephyr_serial index 9555fb43a92..10eb274ee1e 100644 --- a/drivers/w1/Kconfig.zephyr_serial +++ b/drivers/w1/Kconfig.zephyr_serial @@ -8,6 +8,7 @@ config W1_ZEPHYR_SERIAL select SERIAL default y depends on DT_HAS_ZEPHYR_W1_SERIAL_ENABLED + select UART_USE_RUNTIME_CONFIGURE help This option enables the Zephyr serial 1-Wire master driver. diff --git a/drivers/w1/w1_handlers.c b/drivers/w1/w1_handlers.c index 5eac465c383..f2299705a26 100644 --- a/drivers/w1/w1_handlers.c +++ b/drivers/w1/w1_handlers.c @@ -4,12 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include static inline int z_vrfy_w1_reset_bus(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_W1(dev, reset_bus)); + K_OOPS(K_SYSCALL_DRIVER_W1(dev, reset_bus)); return z_impl_w1_reset_bus((const struct device *)dev); } @@ -17,7 +17,7 @@ static inline int z_vrfy_w1_reset_bus(const struct device *dev) static inline int z_vrfy_w1_read_bit(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_W1(dev, read_bit)); + K_OOPS(K_SYSCALL_DRIVER_W1(dev, read_bit)); return z_impl_w1_read_bit((const struct device *)dev); } @@ -25,7 +25,7 @@ static inline int z_vrfy_w1_read_bit(const struct device *dev) static inline int z_vrfy_w1_write_bit(const struct device *dev, bool bit) { - Z_OOPS(Z_SYSCALL_DRIVER_W1(dev, write_bit)); + K_OOPS(K_SYSCALL_DRIVER_W1(dev, write_bit)); return z_impl_w1_write_bit((const struct device *)dev, bit); } @@ -33,7 +33,7 @@ static inline int z_vrfy_w1_write_bit(const struct device *dev, bool bit) static inline int z_vrfy_w1_read_byte(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_W1(dev, read_byte)); + K_OOPS(K_SYSCALL_DRIVER_W1(dev, read_byte)); return z_impl_w1_read_byte((const struct device *)dev); } @@ -41,7 +41,7 @@ static inline int z_vrfy_w1_read_byte(const struct device *dev) static inline int z_vrfy_w1_write_byte(const struct device *dev, uint8_t byte) { - Z_OOPS(Z_SYSCALL_DRIVER_W1(dev, write_byte)); + K_OOPS(K_SYSCALL_DRIVER_W1(dev, write_byte)); return z_impl_w1_write_byte((const struct device *)dev, (uint8_t)byte); } @@ -50,8 +50,8 @@ static inline int z_vrfy_w1_write_byte(const struct device *dev, uint8_t byte) static inline int z_vrfy_w1_read_block(const struct device *dev, uint8_t *buffer, size_t len) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_W1)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(buffer, len)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_W1)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(buffer, len)); return z_impl_w1_read_block((const struct device *)dev, (uint8_t *)buffer, (size_t)len); @@ -61,8 +61,8 @@ static inline int z_vrfy_w1_read_block(const struct device *dev, static inline int z_vrfy_w1_write_block(const struct device *dev, const uint8_t *buffer, size_t len) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_W1)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(buffer, len)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_W1)); + K_OOPS(K_SYSCALL_MEMORY_READ(buffer, len)); return z_impl_w1_write_block((const struct device *)dev, (const uint8_t *)buffer, (size_t)len); @@ -71,7 +71,7 @@ static inline int z_vrfy_w1_write_block(const struct device *dev, static inline int z_vrfy_w1_change_bus_lock(const struct device *dev, bool lock) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_W1)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_W1)); return z_impl_w1_change_bus_lock((const struct device *)dev, lock); } @@ -80,7 +80,7 @@ static inline int z_vrfy_w1_change_bus_lock(const struct device *dev, bool lock) static inline int z_vrfy_w1_configure(const struct device *dev, enum w1_settings_type type, uint32_t value) { - Z_OOPS(Z_SYSCALL_DRIVER_W1(dev, configure)); + K_OOPS(K_SYSCALL_DRIVER_W1(dev, configure)); return z_impl_w1_configure(dev, type, value); } @@ -88,7 +88,7 @@ static inline int z_vrfy_w1_configure(const struct device *dev, static inline size_t z_vrfy_w1_get_slave_count(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_W1)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_W1)); return z_impl_w1_get_slave_count((const struct device *)dev); } @@ -100,9 +100,9 @@ static inline int z_vrfy_w1_search_bus(const struct device *dev, w1_search_callback_t callback, void *user_data) { - Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_W1)); + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_W1)); - Z_OOPS(Z_SYSCALL_VERIFY_MSG(callback == 0, + K_OOPS(K_SYSCALL_VERIFY_MSG(callback == 0, "callbacks may not be set from user mode")); /* user_data is not dereferenced, no need to check parameter */ diff --git a/drivers/watchdog/CMakeLists.txt b/drivers/watchdog/CMakeLists.txt index e72f3683c06..7f58a5461a9 100644 --- a/drivers/watchdog/CMakeLists.txt +++ b/drivers/watchdog/CMakeLists.txt @@ -39,6 +39,7 @@ zephyr_library_sources_ifdef(CONFIG_WDT_XILINX_AXI wdt_xilinx_axi.c) zephyr_library_sources_ifdef(CONFIG_WDT_INFINEON_CAT1 wdt_ifx_cat1.c) zephyr_library_sources_ifdef(CONFIG_WDT_OPENTITAN wdt_opentitan.c) zephyr_library_sources_ifdef(CONFIG_WDT_AMBIQ wdt_ambiq.c) +zephyr_library_sources_ifdef(CONFIG_WDT_XMC4XXX wdt_xmc4xxx.c) zephyr_library_sources_ifdef(CONFIG_WDT_DW wdt_dw.c wdt_dw_common.c) zephyr_library_sources_ifdef(CONFIG_WDT_INTEL_ADSP wdt_intel_adsp.c wdt_dw_common.c) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 2049d78faa0..2ee5545f39e 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -120,4 +120,6 @@ source "drivers/watchdog/Kconfig.ambiq" source "drivers/watchdog/Kconfig.shell" +source "drivers/watchdog/Kconfig.xmc4xxx" + endif # WATCHDOG diff --git a/drivers/watchdog/Kconfig.mcux b/drivers/watchdog/Kconfig.mcux index 805aae1cb32..c4b5a4d7fdd 100644 --- a/drivers/watchdog/Kconfig.mcux +++ b/drivers/watchdog/Kconfig.mcux @@ -25,3 +25,15 @@ config WDT_MCUX_WWDT depends on DT_HAS_NXP_LPC_WWDT_ENABLED help Enable the mcux wwdt driver. + +if WDT_MCUX_WWDT + +config WDT_MCUX_WWDT_WARNING_INTERRUPT_CFG + int "WWDT timeout warning interrupt configuration" + range 0 1023 + default 0 + help + WWDT timeout warning interrupt time. The units are + the number of watchdog counter ticks before timeout. + +endif # WDT_MCUX_WWDT diff --git a/drivers/watchdog/Kconfig.npm1300 b/drivers/watchdog/Kconfig.npm1300 index 8e9cd65024d..b18e4b69b13 100644 --- a/drivers/watchdog/Kconfig.npm1300 +++ b/drivers/watchdog/Kconfig.npm1300 @@ -13,7 +13,7 @@ config WDT_NPM1300 config WDT_NPM1300_INIT_PRIORITY int "nPM1300 Watchdog driver initialization priority" depends on WDT_NPM1300 - default 75 + default 85 help Initialization priority for the nPM1300 Watchdog driver. It must be greater than GPIO_NPM1300_INIT_PRIORITY. diff --git a/drivers/watchdog/Kconfig.npm6001 b/drivers/watchdog/Kconfig.npm6001 index 3230deffc26..0d3f864e5cf 100644 --- a/drivers/watchdog/Kconfig.npm6001 +++ b/drivers/watchdog/Kconfig.npm6001 @@ -13,6 +13,6 @@ config WDT_NPM6001 config WDT_NPM6001_INIT_PRIORITY int "nPM6001 Watchdog driver initialization priority" depends on WDT_NPM6001 - default 65 + default 85 help Initialization priority for the nPM6001 Watchdog driver. diff --git a/drivers/watchdog/Kconfig.nxp_s32 b/drivers/watchdog/Kconfig.nxp_s32 index 3f2dd42efb5..a44decb500c 100644 --- a/drivers/watchdog/Kconfig.nxp_s32 +++ b/drivers/watchdog/Kconfig.nxp_s32 @@ -1,10 +1,11 @@ -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # SPDX-License-Identifier: Apache-2.0 config WDT_NXP_S32 bool "NXP S32 SWT driver" default y depends on DT_HAS_NXP_S32_SWT_ENABLED - select NOCACHE_MEMORY + select CLOCK_CONTROL + select NOCACHE_MEMORY if ARCH_HAS_NOCACHE_MEMORY_SUPPORT help Enable the Software Watchdog Timer (SWT) driver. diff --git a/drivers/watchdog/Kconfig.shell b/drivers/watchdog/Kconfig.shell index 5f5a97a6bda..11503277e93 100644 --- a/drivers/watchdog/Kconfig.shell +++ b/drivers/watchdog/Kconfig.shell @@ -3,7 +3,6 @@ config WDT_SHELL bool "Watchdog (WDT) shell" - default y depends on SHELL help Enable WDT shell. diff --git a/drivers/watchdog/Kconfig.xmc4xxx b/drivers/watchdog/Kconfig.xmc4xxx new file mode 100644 index 00000000000..8c18d06da0d --- /dev/null +++ b/drivers/watchdog/Kconfig.xmc4xxx @@ -0,0 +1,22 @@ +# Infineon XMC4xxx WDT configuration + +# Copyright (C) 2023 SLB +# SPDX-License-Identifier: Apache-2.0 + +config WDT_XMC4XXX + bool "Infineon XMC4xxx MCU Family Watchdog (WDT) Driver" + default y + depends on DT_HAS_INFINEON_XMC4XXX_WATCHDOG_ENABLED + help + Enable WDT driver for Infineon XMC4xxx MCUs. + +if WDT_XMC4XXX && !WDT_DISABLE_AT_BOOT + +config WDT_XMC4XXX_DEFAULT_TIMEOUT_MAX_MS + int "Default watchdog timeout to use at startup" + default 20000 + help + Default watchdog timeout to use if the watchdog is not disabled + at startup. + +endif diff --git a/drivers/watchdog/wdt_cmsdk_apb.c b/drivers/watchdog/wdt_cmsdk_apb.c index 9d4fa1b979d..543a9ecf39e 100644 --- a/drivers/watchdog/wdt_cmsdk_apb.c +++ b/drivers/watchdog/wdt_cmsdk_apb.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include #include diff --git a/drivers/watchdog/wdt_handlers.c b/drivers/watchdog/wdt_handlers.c index 2af07851443..2ac872f1379 100644 --- a/drivers/watchdog/wdt_handlers.c +++ b/drivers/watchdog/wdt_handlers.c @@ -5,11 +5,11 @@ */ #include -#include +#include static inline int z_vrfy_wdt_setup(const struct device *dev, uint8_t options) { - Z_OOPS(Z_SYSCALL_DRIVER_WDT(dev, setup)); + K_OOPS(K_SYSCALL_DRIVER_WDT(dev, setup)); return z_impl_wdt_setup(dev, options); } @@ -17,7 +17,7 @@ static inline int z_vrfy_wdt_setup(const struct device *dev, uint8_t options) static inline int z_vrfy_wdt_disable(const struct device *dev) { - Z_OOPS(Z_SYSCALL_DRIVER_WDT(dev, disable)); + K_OOPS(K_SYSCALL_DRIVER_WDT(dev, disable)); return z_impl_wdt_disable(dev); } @@ -25,7 +25,7 @@ static inline int z_vrfy_wdt_disable(const struct device *dev) static inline int z_vrfy_wdt_feed(const struct device *dev, int channel_id) { - Z_OOPS(Z_SYSCALL_DRIVER_WDT(dev, feed)); + K_OOPS(K_SYSCALL_DRIVER_WDT(dev, feed)); return z_impl_wdt_feed(dev, channel_id); } diff --git a/drivers/watchdog/wdt_mcux_wwdt.c b/drivers/watchdog/wdt_mcux_wwdt.c index cef55b320a5..0181b3d406f 100644 --- a/drivers/watchdog/wdt_mcux_wwdt.c +++ b/drivers/watchdog/wdt_mcux_wwdt.c @@ -69,7 +69,7 @@ static int mcux_wwdt_disable(const struct device *dev) * This prescaler is different from the clock divider specified in Device Tree. */ #define MSEC_TO_WWDT_TICKS(clock_freq, msec) \ - ((uint32_t)(clock_freq * msec / MSEC_PER_SEC / 4)) + ((uint32_t)((clock_freq / MSEC_PER_SEC) * msec) / 4) static int mcux_wwdt_install_timeout(const struct device *dev, const struct wdt_timeout_cfg *cfg) @@ -115,7 +115,14 @@ static int mcux_wwdt_install_timeout(const struct device *dev, LOG_DBG("Enabling SoC reset"); } - data->callback = cfg->callback; + if (cfg->callback && (CONFIG_WDT_MCUX_WWDT_WARNING_INTERRUPT_CFG > 0)) { + data->callback = cfg->callback; + data->wwdt_config.warningValue = CONFIG_WDT_MCUX_WWDT_WARNING_INTERRUPT_CFG; + } else if (cfg->callback) { + return -ENOTSUP; + } + + data->timeout_valid = true; LOG_DBG("Installed timeout (timeoutValue = %d)", data->wwdt_config.timeoutValue); diff --git a/drivers/watchdog/wdt_nrfx.c b/drivers/watchdog/wdt_nrfx.c index 8d61f11d6fb..98fcb713b81 100644 --- a/drivers/watchdog/wdt_nrfx.c +++ b/drivers/watchdog/wdt_nrfx.c @@ -20,37 +20,36 @@ struct wdt_nrfx_data { }; struct wdt_nrfx_config { - nrfx_wdt_t wdt; - nrfx_wdt_config_t config; + nrfx_wdt_t wdt; }; static int wdt_nrf_setup(const struct device *dev, uint8_t options) { const struct wdt_nrfx_config *config = dev->config; - struct wdt_nrfx_data *data = dev->data; - uint32_t behaviour; + const struct wdt_nrfx_data *data = dev->data; + nrfx_err_t err_code; - /* Activate all available options. Run in all cases. */ - behaviour = NRF_WDT_BEHAVIOUR_RUN_SLEEP_MASK | NRF_WDT_BEHAVIOUR_RUN_HALT_MASK; + nrfx_wdt_config_t wdt_config = { + .reload_value = data->m_timeout + }; + +#if NRF_WDT_HAS_STOP + wdt_config.behaviour |= NRF_WDT_BEHAVIOUR_STOP_ENABLE_MASK; +#endif - /* Deactivate running in sleep mode. */ - if (options & WDT_OPT_PAUSE_IN_SLEEP) { - behaviour &= ~NRF_WDT_BEHAVIOUR_RUN_SLEEP_MASK; + if (!(options & WDT_OPT_PAUSE_IN_SLEEP)) { + wdt_config.behaviour |= NRF_WDT_BEHAVIOUR_RUN_SLEEP_MASK; } - /* Deactivate running when debugger is attached. */ - if (options & WDT_OPT_PAUSE_HALTED_BY_DBG) { - behaviour &= ~NRF_WDT_BEHAVIOUR_RUN_HALT_MASK; + if (!(options & WDT_OPT_PAUSE_HALTED_BY_DBG)) { + wdt_config.behaviour |= NRF_WDT_BEHAVIOUR_RUN_HALT_MASK; } - nrf_wdt_behaviour_set(config->wdt.p_reg, behaviour); - /* The watchdog timer is driven by the LFCLK clock running at 32768 Hz. - * The timeout value given in milliseconds needs to be converted here - * to watchdog ticks.*/ - nrf_wdt_reload_value_set( - config->wdt.p_reg, - (uint32_t)(((uint64_t)data->m_timeout * 32768U) - / 1000)); + err_code = nrfx_wdt_reconfigure(&config->wdt, &wdt_config); + + if (err_code != NRFX_SUCCESS) { + return -EBUSY; + } nrfx_wdt_enable(&config->wdt); @@ -59,9 +58,21 @@ static int wdt_nrf_setup(const struct device *dev, uint8_t options) static int wdt_nrf_disable(const struct device *dev) { - /* Started watchdog cannot be stopped on nRF devices. */ +#if NRFX_WDT_HAS_STOP + const struct wdt_nrfx_config *config = dev->config; + nrfx_err_t err_code; + + err_code = nrfx_wdt_stop(&config->wdt); + + if (err_code != NRFX_SUCCESS) { + return -ENOTSUP; + } + + return 0; +#else ARG_UNUSED(dev); return -EPERM; +#endif } static int wdt_nrf_install_timeout(const struct device *dev, @@ -162,8 +173,8 @@ static void wdt_event_handler(const struct device *dev, uint32_t requests) IRQ_CONNECT(DT_IRQN(WDT(idx)), DT_IRQ(WDT(idx), priority), \ nrfx_isr, nrfx_wdt_##idx##_irq_handler, 0); \ err_code = nrfx_wdt_init(&config->wdt, \ - &config->config, \ - wdt_##idx##_event_handler); \ + NULL, \ + wdt_##idx##_event_handler); \ if (err_code != NRFX_SUCCESS) { \ return -EBUSY; \ } \ @@ -175,11 +186,6 @@ static void wdt_event_handler(const struct device *dev, uint32_t requests) }; \ static const struct wdt_nrfx_config wdt_##idx##z_config = { \ .wdt = NRFX_WDT_INSTANCE(idx), \ - .config = { \ - .behaviour = NRF_WDT_BEHAVIOUR_RUN_SLEEP_MASK | \ - NRF_WDT_BEHAVIOUR_RUN_HALT_MASK, \ - .reload_value = 2000, \ - } \ }; \ DEVICE_DT_DEFINE(WDT(idx), \ wdt_##idx##_init, \ diff --git a/drivers/watchdog/wdt_nxp_fs26.c b/drivers/watchdog/wdt_nxp_fs26.c index 07cddc1bd3b..f6aed5079e4 100644 --- a/drivers/watchdog/wdt_nxp_fs26.c +++ b/drivers/watchdog/wdt_nxp_fs26.c @@ -27,9 +27,9 @@ LOG_MODULE_REGISTER(wdt_nxp_fs26); #define FS26_INIT_FS_TIMEOUT_MS 1000U /* Helper macros to set register values from Kconfig options */ -#define WD_ERR_LIMIT(x) CONCAT(WD_ERR_LIMIT_, x) -#define WD_RFR_LIMIT(x) CONCAT(WD_RFR_LIMIT_, x) -#define WDW_PERIOD(x) CONCAT(CONCAT(WDW_PERIOD_, x), MS) +#define WD_ERR_LIMIT(x) _CONCAT(WD_ERR_LIMIT_, x) +#define WD_RFR_LIMIT(x) _CONCAT(WD_RFR_LIMIT_, x) +#define WDW_PERIOD(x) _CONCAT(_CONCAT(WDW_PERIOD_, x), MS) #define BAD_WD_REFRESH_ERROR_STRING(x) \ ((((x) & BAD_WD_DATA) ? "error in the data" : \ @@ -580,8 +580,12 @@ static int wdt_nxp_fs26_disable(const struct device *dev) return 0; } -static void wdt_nxp_fs26_int_thread(const struct device *dev) +static void wdt_nxp_fs26_int_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; const struct wdt_nxp_fs26_config *config = dev->config; struct wdt_nxp_fs26_data *data = dev->data; struct fs26_spi_rx_frame rx_frame; @@ -661,7 +665,7 @@ static int wdt_nxp_fs26_init(const struct device *dev) k_thread_create(&data->int_thread, data->int_thread_stack, CONFIG_WDT_NXP_FS26_INT_THREAD_STACK_SIZE, - (k_thread_entry_t)wdt_nxp_fs26_int_thread, + wdt_nxp_fs26_int_thread, (void *)dev, NULL, NULL, K_PRIO_COOP(CONFIG_WDT_NXP_FS26_INT_THREAD_PRIO), 0, K_NO_WAIT); @@ -822,7 +826,7 @@ static const struct wdt_driver_api wdt_nxp_fs26_api = { static const struct wdt_nxp_fs26_config wdt_nxp_fs26_config_##n = { \ .spi = SPI_DT_SPEC_INST_GET(n, \ SPI_OP_MODE_MASTER | SPI_MODE_CPHA | SPI_WORD_SET(32), 0), \ - .wd_type = CONCAT(FS26_WD_, DT_INST_STRING_UPPER_TOKEN(n, type)), \ + .wd_type = _CONCAT(FS26_WD_, DT_INST_STRING_UPPER_TOKEN(n, type)), \ .int_gpio = GPIO_DT_SPEC_INST_GET(n, int_gpios), \ }; \ \ diff --git a/drivers/watchdog/wdt_nxp_s32.c b/drivers/watchdog/wdt_nxp_s32.c index 0b41d52312a..709cf9aaffb 100644 --- a/drivers/watchdog/wdt_nxp_s32.c +++ b/drivers/watchdog/wdt_nxp_s32.c @@ -1,10 +1,13 @@ /* - * Copyright 2022 NXP + * Copyright 2022-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ +#define DT_DRV_COMPAT nxp_s32_swt + #include +#include #include #include #include @@ -16,8 +19,9 @@ LOG_MODULE_REGISTER(swt_nxp_s32); #define PARAM_UNUSED 0 struct swt_nxp_s32_config { - uint32_t clock_freq; uint8_t instance; + const struct device *clock_dev; + clock_control_subsys_t clock_subsys; }; struct swt_nxp_s32_data { @@ -76,18 +80,26 @@ static int swt_nxp_s32_install_timeout(const struct device *dev, { const struct swt_nxp_s32_config *config = dev->config; struct swt_nxp_s32_data *data = dev->data; + uint32_t clock_rate; + int err; if (data->timeout_valid) { LOG_ERR("No more timeouts can be installed"); return -ENOMEM; } - data->swt_config.u32TimeoutValue = config->clock_freq / 1000U * cfg->window.max; + err = clock_control_get_rate(config->clock_dev, config->clock_subsys, &clock_rate); + if (err) { + LOG_ERR("Failed to get module clock frequency"); + return err; + } + + data->swt_config.u32TimeoutValue = clock_rate / 1000U * cfg->window.max; if (cfg->window.min) { data->swt_config.bEnWindow = true; data->swt_config.u32WindowValue = - config->clock_freq / 1000U * (cfg->window.max - cfg->window.min); + clock_rate / 1000U * (cfg->window.max - cfg->window.min); } else { data->swt_config.bEnWindow = false; data->swt_config.u32WindowValue = 0; @@ -119,6 +131,13 @@ static int swt_nxp_s32_feed(const struct device *dev, int channel_id) return 0; } +void swt_nxp_s32_isr(const struct device *dev) +{ + const struct swt_nxp_s32_config *config = dev->config; + + Swt_Ip_IrqHandler(config->instance); +} + static const struct wdt_driver_api swt_nxp_s32_driver_api = { .setup = swt_nxp_s32_setup, .disable = swt_nxp_s32_disable, @@ -126,17 +145,10 @@ static const struct wdt_driver_api swt_nxp_s32_driver_api = { .feed = swt_nxp_s32_feed, }; -#define SWT_NODE(n) DT_NODELABEL(swt##n) -#define RTU0_SWT_OFFSET_IDX 2 -#define RTU1_SWT_OFFSET_IDX 7 -#define RTU_SWT(n) \ - COND_CODE_1(CONFIG_NXP_S32_RTU_INDEX, (RTU1_SWT_OFFSET_IDX + n), \ - (RTU0_SWT_OFFSET_IDX + n)) - #define SWT_NXP_S32_CALLBACK(n) \ void swt_nxp_s32_##n##_callback(void) \ { \ - const struct device *dev = DEVICE_DT_GET(SWT_NODE(n)); \ + const struct device *dev = DEVICE_DT_INST_GET(n); \ struct swt_nxp_s32_data *data = dev->data; \ \ if (data->callback) { \ @@ -144,6 +156,12 @@ static const struct wdt_driver_api swt_nxp_s32_driver_api = { } \ } +#define SWT_NXP_S32_HW_INSTANCE_CHECK(i, n) \ + ((DT_INST_REG_ADDR(n) == IP_SWT_##i##_BASE) ? i : 0) + +#define SWT_NXP_S32_HW_INSTANCE(n) \ + LISTIFY(__DEBRACKET SWT_INSTANCE_COUNT, SWT_NXP_S32_HW_INSTANCE_CHECK, (|), n) + #define SWT_NXP_S32_DEVICE_INIT(n) \ SWT_NXP_S32_CALLBACK(n) \ static struct swt_nxp_s32_data swt_nxp_s32_data_##n = { \ @@ -161,23 +179,35 @@ static const struct wdt_driver_api swt_nxp_s32_driver_api = { }, \ }; \ static const struct swt_nxp_s32_config swt_nxp_s32_config_##n = { \ - .clock_freq = DT_PROP(SWT_NODE(n), clock_frequency), \ - .instance = (uint8_t)(RTU_SWT(n)), \ + .instance = SWT_NXP_S32_HW_INSTANCE(n), \ + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ + .clock_subsys = (clock_control_subsys_t) \ + DT_INST_CLOCKS_CELL(n, name), \ }; \ \ static int swt_nxp_s32_##n##_init(const struct device *dev) \ { \ - IRQ_CONNECT(DT_IRQN(SWT_NODE(n)), \ - DT_IRQ(SWT_NODE(n), priority), \ - Swt_Ip_IrqHandler, \ - (uint8_t)(RTU_SWT(n)), \ - DT_IRQ(SWT_NODE(n), flags)); \ - irq_enable(DT_IRQN(SWT_NODE(n))); \ + const struct swt_nxp_s32_config *config = dev->config; \ + int err; \ + \ + if (!device_is_ready(config->clock_dev)) { \ + return -ENODEV; \ + } \ + \ + err = clock_control_on(config->clock_dev, config->clock_subsys);\ + if (err) { \ + return err; \ + } \ + \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \ + swt_nxp_s32_isr, DEVICE_DT_INST_GET(n), \ + DT_INST_IRQ(n, flags)); \ + irq_enable(DT_INST_IRQN(n)); \ \ return 0; \ } \ \ - DEVICE_DT_DEFINE(SWT_NODE(n), \ + DEVICE_DT_INST_DEFINE(n, \ swt_nxp_s32_##n##_init, \ NULL, \ &swt_nxp_s32_data_##n, \ @@ -186,23 +216,4 @@ static const struct wdt_driver_api swt_nxp_s32_driver_api = { CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ &swt_nxp_s32_driver_api); - -#if DT_NODE_HAS_STATUS(SWT_NODE(0), okay) -SWT_NXP_S32_DEVICE_INIT(0) -#endif - -#if DT_NODE_HAS_STATUS(SWT_NODE(1), okay) -SWT_NXP_S32_DEVICE_INIT(1) -#endif - -#if DT_NODE_HAS_STATUS(SWT_NODE(2), okay) -SWT_NXP_S32_DEVICE_INIT(2) -#endif - -#if DT_NODE_HAS_STATUS(SWT_NODE(3), okay) -SWT_NXP_S32_DEVICE_INIT(3) -#endif - -#if DT_NODE_HAS_STATUS(SWT_NODE(4), okay) -SWT_NXP_S32_DEVICE_INIT(4) -#endif +DT_INST_FOREACH_STATUS_OKAY(SWT_NXP_S32_DEVICE_INIT) diff --git a/drivers/watchdog/wdt_smartbond.c b/drivers/watchdog/wdt_smartbond.c index 4e48aa5c5c4..5ae07671247 100644 --- a/drivers/watchdog/wdt_smartbond.c +++ b/drivers/watchdog/wdt_smartbond.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include #include diff --git a/drivers/watchdog/wdt_tco.c b/drivers/watchdog/wdt_tco.c index bc0e95386f2..599871bc5f0 100644 --- a/drivers/watchdog/wdt_tco.c +++ b/drivers/watchdog/wdt_tco.c @@ -11,8 +11,6 @@ LOG_MODULE_REGISTER(wdt_tco, CONFIG_WDT_LOG_LEVEL); -#define TCO_WDT_NODE DT_NODELABEL(tco_wdt) - #define BASE(d) ((struct tco_config *)(d)->config)->base #define TCO_RLD(d) (BASE(d) + 0x00) /* TCO Timer Reload/Curr. Value */ @@ -267,9 +265,9 @@ static struct tco_data wdt_data = { }; static const struct tco_config wdt_config = { - .base = DT_REG_ADDR(TCO_WDT_NODE), + .base = DT_INST_REG_ADDR(0), }; -DEVICE_DT_DEFINE(TCO_WDT_NODE, wdt_init, NULL, &wdt_data, &wdt_config, - POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, - &tco_driver_api); +DEVICE_DT_INST_DEFINE(0, wdt_init, NULL, &wdt_data, &wdt_config, + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, + &tco_driver_api); diff --git a/drivers/watchdog/wdt_xmc4xxx.c b/drivers/watchdog/wdt_xmc4xxx.c new file mode 100644 index 00000000000..e038bb0d4d5 --- /dev/null +++ b/drivers/watchdog/wdt_xmc4xxx.c @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2023 SLB + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT infineon_xmc4xxx_watchdog + +#include +#include + +#include +#include +#include + +#include +#include + +struct wdt_xmc4xxx_dev_data { + wdt_callback_t cb; + uint8_t mode; + bool timeout_valid; + bool is_serviced; +}; + +/* When the watchdog counter rolls over, the SCU will generate a */ +/* pre-warning event which gets routed to the ISR below. If the */ +/* watchdog is not serviced, the SCU will only reset the MCU */ +/* after the second time the counter rolls over. */ +/* Hence the reset will only happen after 2*cfg->window.max have elapsed. */ +/* We could potentially manually reset the MCU, but this way the context */ +/* information (i.e. that reset happened because of a watchdog) is lost. */ + +static void wdt_xmc4xxx_isr(const struct device *dev) +{ + struct wdt_xmc4xxx_dev_data *data = dev->data; + uint32_t event = XMC_SCU_INTERUPT_GetEventStatus(); + + /* todo add interrupt controller? */ + if ((event & XMC_SCU_INTERRUPT_EVENT_WDT_WARN) == 0) { + return; + } + + /* this is a level triggered interrupt. the event must be cleared */ + XMC_SCU_INTERRUPT_ClearEventStatus(XMC_SCU_INTERRUPT_EVENT_WDT_WARN); + + data->is_serviced = false; + + if (data->cb) { + data->cb(dev, 0); + } + + /* Ensure that watchdog is serviced if RESET_NONE mode is used */ + if (data->mode == WDT_FLAG_RESET_NONE && !data->is_serviced) { + XMC_WDT_Service(); + } + + XMC_WDT_ClearAlarm(); +} + +static int wdt_xmc4xxx_disable(const struct device *dev) +{ + struct wdt_xmc4xxx_dev_data *data = dev->data; + + XMC_WDT_Stop(); + XMC_WDT_Disable(); + + data->timeout_valid = false; + + return 0; +} + +static int wdt_xmc4xxx_setup(const struct device *dev, uint8_t options) +{ + struct wdt_xmc4xxx_dev_data *data = dev->data; + + if (!data->timeout_valid) { + return -EINVAL; + } + + if ((options & WDT_OPT_PAUSE_IN_SLEEP) != 0) { + SCU_CLK->SLEEPCR &= ~XMC_SCU_CLOCK_SLEEP_MODE_CONFIG_ENABLE_WDT; + } else { + SCU_CLK->SLEEPCR |= XMC_SCU_CLOCK_SLEEP_MODE_CONFIG_ENABLE_WDT; + } + + if ((options & WDT_OPT_PAUSE_HALTED_BY_DBG) != 0) { + XMC_WDT_SetDebugMode(XMC_WDT_DEBUG_MODE_STOP); + } else { + XMC_WDT_SetDebugMode(XMC_WDT_DEBUG_MODE_RUN); + } + + XMC_WDT_Start(); + + return 0; +} + +static int wdt_xmc4xxx_install_timeout(const struct device *dev, const struct wdt_timeout_cfg *cfg) +{ + XMC_WDT_CONFIG_t wdt_config = {0}; + struct wdt_xmc4xxx_dev_data *data = dev->data; + uint32_t wdt_clock; + + /* disable the watchdog if timeout was already installed */ + if (data->timeout_valid) { + wdt_xmc4xxx_disable(dev); + data->timeout_valid = false; + } + + if (cfg->window.min != 0 || cfg->window.max == 0) { + return -EINVAL; + } + + wdt_clock = XMC_SCU_CLOCK_GetWdtClockFrequency(); + + if ((uint64_t)cfg->window.max * wdt_clock / 1000 > UINT32_MAX) { + return -EINVAL; + } + + wdt_config.window_upper_bound = (uint64_t)cfg->window.max * wdt_clock / 1000; + + XMC_WDT_Init(&wdt_config); + XMC_WDT_SetDebugMode(XMC_WDT_MODE_PREWARNING); + XMC_SCU_INTERRUPT_EnableEvent(XMC_SCU_INTERRUPT_EVENT_WDT_WARN); + + if (cfg->flags == WDT_FLAG_RESET_NONE && cfg->callback == NULL) { + return -EINVAL; + } + + data->cb = cfg->callback; + data->mode = cfg->flags; + data->timeout_valid = true; + + return 0; +} + +static int wdt_xmc4xxx_feed(const struct device *dev, int channel_id) +{ + ARG_UNUSED(channel_id); + struct wdt_xmc4xxx_dev_data *data = dev->data; + + XMC_WDT_Service(); + data->is_serviced = true; + + return 0; +} + +static const struct wdt_driver_api wdt_xmc4xxx_api = { + .setup = wdt_xmc4xxx_setup, + .disable = wdt_xmc4xxx_disable, + .install_timeout = wdt_xmc4xxx_install_timeout, + .feed = wdt_xmc4xxx_feed, +}; + +static struct wdt_xmc4xxx_dev_data wdt_xmc4xxx_data; + +static void wdt_xmc4xxx_irq_config(void) +{ + IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), wdt_xmc4xxx_isr, + DEVICE_DT_INST_GET(0), 0); + irq_enable(DT_INST_IRQN(0)); +} + +static int wdt_xmc4xxx_init(const struct device *dev) +{ + wdt_xmc4xxx_irq_config(); + +#ifdef CONFIG_WDT_DISABLE_AT_BOOT + return 0; +#else + int ret; + const struct wdt_timeout_cfg cfg = {.window.max = CONFIG_WDT_XMC4XXX_DEFAULT_TIMEOUT_MAX_MS, + .flags = WDT_FLAG_RESET_SOC}; + + ret = wdt_xmc4xxx_install_timeout(dev, &cfg); + if (ret < 0) { + return ret; + } + + return wdt_xmc4xxx_setup(dev, WDT_OPT_PAUSE_HALTED_BY_DBG); +#endif +} +DEVICE_DT_INST_DEFINE(0, wdt_xmc4xxx_init, NULL, &wdt_xmc4xxx_data, NULL, PRE_KERNEL_1, + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &wdt_xmc4xxx_api); diff --git a/drivers/wifi/CMakeLists.txt b/drivers/wifi/CMakeLists.txt index b12ecf88a3e..df1e7c39465 100644 --- a/drivers/wifi/CMakeLists.txt +++ b/drivers/wifi/CMakeLists.txt @@ -8,3 +8,4 @@ add_subdirectory_ifdef(CONFIG_WIFI_ESP32 esp32) add_subdirectory_ifdef(CONFIG_WIFI_ESWIFI eswifi) add_subdirectory_ifdef(CONFIG_WIFI_SIMPLELINK simplelink) add_subdirectory_ifdef(CONFIG_WIFI_WINC1500 winc1500) +add_subdirectory_ifdef(CONFIG_WIFI_AIROC infineon) diff --git a/drivers/wifi/Kconfig b/drivers/wifi/Kconfig index 4bb4197bede..d7133f5be04 100644 --- a/drivers/wifi/Kconfig +++ b/drivers/wifi/Kconfig @@ -40,5 +40,6 @@ source "drivers/wifi/simplelink/Kconfig.simplelink" source "drivers/wifi/eswifi/Kconfig.eswifi" source "drivers/wifi/esp_at/Kconfig.esp_at" source "drivers/wifi/esp32/Kconfig.esp32" +source "drivers/wifi/infineon/Kconfig.airoc" endif # WIFI diff --git a/drivers/wifi/esp32/src/esp_wifi_drv.c b/drivers/wifi/esp32/src/esp_wifi_drv.c index cb343159854..bb89f3e8d2d 100644 --- a/drivers/wifi/esp32/src/esp_wifi_drv.c +++ b/drivers/wifi/esp32/src/esp_wifi_drv.c @@ -61,7 +61,7 @@ struct esp32_wifi_runtime { uint8_t state; }; -static void esp_wifi_event_task(void); +static void esp_wifi_event_task(void *, void *, void *); K_MSGQ_DEFINE(esp_wifi_msgq, sizeof(system_event_t), 10, 4); K_THREAD_STACK_DEFINE(esp_wifi_event_stack, CONFIG_ESP32_WIFI_EVENT_TASK_STACK_SIZE); @@ -262,8 +262,11 @@ static void esp_wifi_handle_disconnect_event(void) } } -static void esp_wifi_event_task(void) +static void esp_wifi_event_task(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + system_event_t evt; uint8_t s_con_cnt = 0; @@ -615,7 +618,7 @@ static int esp32_wifi_dev_init(const struct device *dev) k_tid_t tid = k_thread_create(&esp_wifi_event_thread, esp_wifi_event_stack, CONFIG_ESP32_WIFI_EVENT_TASK_STACK_SIZE, - (k_thread_entry_t)esp_wifi_event_task, NULL, NULL, NULL, + esp_wifi_event_task, NULL, NULL, NULL, CONFIG_ESP32_WIFI_EVENT_TASK_PRIO, K_INHERIT_PERMS, K_NO_WAIT); diff --git a/drivers/wifi/esp_at/Kconfig.esp_at b/drivers/wifi/esp_at/Kconfig.esp_at index afe02931ee6..9b7e38045d9 100644 --- a/drivers/wifi/esp_at/Kconfig.esp_at +++ b/drivers/wifi/esp_at/Kconfig.esp_at @@ -11,6 +11,7 @@ menuconfig WIFI_ESP_AT select MODEM_IFACE_UART select NET_L2_WIFI_MGMT select WIFI_OFFLOAD + imply UART_USE_RUNTIME_CONFIGURE help Enable Espressif AT Command offloaded WiFi driver. It is supported on any serial capable platform and communicates with Espressif chips diff --git a/drivers/wifi/esp_at/esp.c b/drivers/wifi/esp_at/esp.c index df20caae5b6..1ac21abc560 100644 --- a/drivers/wifi/esp_at/esp.c +++ b/drivers/wifi/esp_at/esp.c @@ -199,8 +199,13 @@ MODEM_CMD_DEFINE(on_cmd_error) } /* RX thread */ -static void esp_rx(struct esp_data *data) +static void esp_rx(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct esp_data *data = p1; + while (true) { /* wait for incoming data */ modem_iface_uart_rx_wait(&data->mctx.iface, K_FOREVER); @@ -1366,7 +1371,7 @@ static int esp_init(const struct device *dev) /* start RX thread */ k_thread_create(&esp_rx_thread, esp_rx_stack, K_KERNEL_STACK_SIZEOF(esp_rx_stack), - (k_thread_entry_t)esp_rx, + esp_rx, data, NULL, NULL, K_PRIO_COOP(CONFIG_WIFI_ESP_AT_RX_THREAD_PRIORITY), 0, K_NO_WAIT); diff --git a/drivers/wifi/eswifi/CMakeLists.txt b/drivers/wifi/eswifi/CMakeLists.txt index 7b324a27b13..9b3dae623af 100644 --- a/drivers/wifi/eswifi/CMakeLists.txt +++ b/drivers/wifi/eswifi/CMakeLists.txt @@ -5,6 +5,7 @@ if(CONFIG_WIFI_ESWIFI) zephyr_library_include_directories( # IP headers ${ZEPHYR_BASE}/subsys/net/ip + ${ZEPHYR_BASE}/subsys/net/lib/sockets ) zephyr_library_sources( diff --git a/drivers/wifi/eswifi/eswifi_bus_spi.c b/drivers/wifi/eswifi/eswifi_bus_spi.c index edade1ffdf8..9fb24dda907 100644 --- a/drivers/wifi/eswifi/eswifi_bus_spi.c +++ b/drivers/wifi/eswifi/eswifi_bus_spi.c @@ -219,8 +219,11 @@ static void eswifi_spi_read_msg(struct eswifi_dev *eswifi) eswifi_unlock(eswifi); } -static void eswifi_spi_poll_thread(void *p1) +static void eswifi_spi_poll_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct eswifi_dev *eswifi = p1; while (1) { @@ -255,7 +258,7 @@ int eswifi_spi_init(struct eswifi_dev *eswifi) k_thread_create(&spi->poll_thread, eswifi_spi_poll_stack, ESWIFI_SPI_THREAD_STACK_SIZE, - (k_thread_entry_t)eswifi_spi_poll_thread, eswifi, NULL, + eswifi_spi_poll_thread, eswifi, NULL, NULL, K_PRIO_COOP(CONFIG_WIFI_ESWIFI_THREAD_PRIO), 0, K_NO_WAIT); diff --git a/drivers/wifi/eswifi/eswifi_core.c b/drivers/wifi/eswifi/eswifi_core.c index 83ef8393552..0beecd4a4fc 100644 --- a/drivers/wifi/eswifi/eswifi_core.c +++ b/drivers/wifi/eswifi/eswifi_core.c @@ -490,8 +490,8 @@ int eswifi_mgmt_iface_status(const struct device *dev, } status->state = WIFI_STATE_COMPLETED; - strcpy(status->ssid, sta->ssid); - status->ssid_len = strlen(sta->ssid); + status->ssid_len = strnlen(sta->ssid, WIFI_SSID_MAX_LEN); + strncpy(status->ssid, sta->ssid, status->ssid_len); status->band = WIFI_FREQ_BAND_2_4_GHZ; status->channel = 0; diff --git a/drivers/wifi/eswifi/eswifi_shell.c b/drivers/wifi/eswifi/eswifi_shell.c index ee5cf4a15ba..de122d4ef1f 100644 --- a/drivers/wifi/eswifi/eswifi_shell.c +++ b/drivers/wifi/eswifi/eswifi_shell.c @@ -25,6 +25,7 @@ static int eswifi_shell_atcmd(const struct shell *sh, size_t argc, char **argv) { int i; + size_t len = 0; if (eswifi == NULL) { shell_print(sh, "no eswifi device registered"); @@ -40,9 +41,16 @@ static int eswifi_shell_atcmd(const struct shell *sh, size_t argc, memset(eswifi->buf, 0, sizeof(eswifi->buf)); for (i = 1; i < argc; i++) { - strcat(eswifi->buf, argv[i]); + size_t argv_len = strlen(argv[i]); + + if ((len + argv_len) >= sizeof(eswifi->buf) - 1) { + break; + } + + memcpy(eswifi->buf + len, argv[i], argv_len); + len += argv_len; } - strcat(eswifi->buf, "\r"); + eswifi->buf[len] = '\r'; shell_print(sh, "> %s", eswifi->buf); eswifi_at_cmd(eswifi, eswifi->buf); diff --git a/drivers/wifi/infineon/CMakeLists.txt b/drivers/wifi/infineon/CMakeLists.txt new file mode 100644 index 00000000000..20f69f18111 --- /dev/null +++ b/drivers/wifi/infineon/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# SPDX-License-Identifier: Apache-2.0 + +zephyr_include_directories(./) + +zephyr_library_sources_ifdef(CONFIG_WIFI_AIROC airoc_wifi.c) +zephyr_library_sources_ifdef(CONFIG_WIFI_AIROC airoc_whd_hal.c) + +zephyr_compile_definitions(CYBSP_WIFI_CAPABLE) +zephyr_compile_definitions(CY_RTOS_AWARE) +zephyr_compile_definitions(WHD_USE_CUSTOM_MALLOC_IMPL) +zephyr_compile_definitions(WHD_USE_CUSTOM_HAL_IMPL) diff --git a/drivers/wifi/infineon/Kconfig.airoc b/drivers/wifi/infineon/Kconfig.airoc new file mode 100644 index 00000000000..a3eac53862d --- /dev/null +++ b/drivers/wifi/infineon/Kconfig.airoc @@ -0,0 +1,142 @@ +# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# SPDX-License-Identifier: Apache-2.0 + +menuconfig WIFI_AIROC + bool "Infineon AIROC SoC Wi-Fi support" + select THREAD_CUSTOM_DATA + select WIFI_OFFLOAD + select NET_L2_WIFI_MGMT + select SDIO_STACK + select SDHC + select WIFI_USE_NATIVE_NETWORKING + select USE_INFINEON_ABSTRACTION_RTOS + depends on DT_HAS_INFINEON_AIROC_WIFI_ENABLED + help + Enable Infineon AIROC SoC Wi-Fi support. + +if WIFI_AIROC + +config AIROC_WIFI_EVENT_TASK_STACK_SIZE + int "Event Task Stack Size" + default 4096 + +config AIROC_WIFI_EVENT_TASK_PRIO + int "Event Task Priority" + default 4 + +config AIROC_WLAN_MFG_FIRMWARE + bool "WLAN Manufacturing Firmware" + help + Enable WLAN Manufacturing Firmware. + +config AIROC_WIFI_CUSTOM + bool "Custom CYW43xx device/module" + help + Select Custom CYW43xx device/module. For this option, + user must to provide path to FW, CLM and NVRAM for + custom or vendor CYW43xx modules. + +choice AIROC_PART + prompt "Select AIROC part" + depends on !AIROC_WIFI_CUSTOM + +config CYW4343W + bool "CYW4343W" + help + Enable Infineon AIROC CYW4343W Wi-Fi connectivity, + More information about CYW4343W device you can find on + https://www.infineon.com/cms/en/product/wireless-connectivity/airoc-wi-fi-plus-bluetooth-combos/cyw4343w/ + +config CYW4373 + bool "CYW4373" + help + Enable Infineon AIROC CYW4373 Wi-Fi connectivity, + More information about CYW4373 device you can find on + https://www.infineon.com/cms/en/product/wireless-connectivity/airoc-wi-fi-plus-bluetooth-combos/cyw4373/ + +config CYW43012 + bool "CYW43012" + help + Enable Infineon AIROC CYW43012 Wi-Fi connectivity, + More information about CYW43012 device you can find on + https://www.infineon.com/cms/en/product/wireless-connectivity/airoc-wi-fi-plus-bluetooth-combos/cyw43012/ + +config CYW43438 + bool "CYW43438" + help + Enable Infineon AIROC CYW43438 Wi-Fi connectivity, + More information about CYW43438 device you can find on + https://www.infineon.com/cms/en/product/wireless-connectivity/airoc-wi-fi-plus-bluetooth-combos/cyw43438/ + +config CYW43439 + bool "CYW43439" + help + Enable Infineon AIROC CYW43439 Wi-Fi connectivity, + More information about CYW43439 device you can find on + https://www.infineon.com/cms/en/product/wireless-connectivity/airoc-wi-fi-plus-bluetooth-combos/cyw43439/ +endchoice + +choice CYW43012_MODULE + prompt "Select CYW43012 module" + depends on CYW43012 && !AIROC_WIFI_CUSTOM + +config CYW43012_MURATA_1LV + bool "MURATA-1LV" + help + Murata Type 1LV module based on Infineon CYW43012 combo chipset + which supports Wi-Fi® 802.11a/b/g/n + Bluetooth® 5.0 BR/EDR/LE + up to 72.2Mbps PHY data rate on Wi-fi® and 3Mbps PHY data rate + on Bluetooth®. 2Mbps LE PHY is also supported. + + Detailed information about Murata Type 1LV module you can find on + https://www.murata.com/en-us/products/connectivitymodule/wi-fi-bluetooth/overview/lineup/type1lv +endchoice + +choice CYW4343W_MODULE + prompt "Select CYW4343W module" + depends on CYW4343W && !AIROC_WIFI_CUSTOM + +config CYW4343W_MURATA_1DX + bool "MURATA-1DX" + help + Murata Type 1DX modules based on Infineon CYW4343W combo chipset + which supports Wi-Fi® 802.11b/g/n + Bluetooth® 5.1 BR/EDR/LE + up to 65Mbps PHY data rate on Wi-fi® and 3Mbps PHY data rate + on Bluetooth®. + + Detailed information about Type 1DX module you can find on + https://www.murata.com/en-us/products/connectivitymodule/wi-fi-bluetooth/overview/lineup/type1dx +endchoice + +choice CYW4373_MODULE + prompt "Select CYW4373 module" + depends on CYW4373 && !AIROC_WIFI_CUSTOM + +config CYW4373_STERLING_LWB5PLUS + bool "STERLING-LWB5plus" + help + Laird Sterling LWB5+ 802.11ac / Bluetooth 5.0 M.2 Carrier Board + (E-Type Key w/ SDIO/UART) + + Detailed information about Type Sterling LWB5+ module you can find on + https://www.lairdconnect.com/wireless-modules/wifi-modules-bluetooth/sterling-lwb5-plus-wifi-5-bluetooth-5-module +endchoice + +choice CYW43439_MODULE + prompt "Select CYW43439 module" + depends on CYW43439 && !AIROC_WIFI_CUSTOM + +config CYW43439_MURATA_1YN + bool "MURATA_1YN" + help + Murata Type 1YN module based on Infineon CYW43439 combo chipset + which supports Wi-Fi® 802.11b/g/n + Bluetooth® 5.2 BR/EDR/LE + up to 65Mbps PHY data rate on Wi-fi® and 3Mbps PHY data rate on + Bluetooth®. + + Detailed information about Murata Type 1YN module you can find on + https://www.murata.com/en-us/products/connectivitymodule/wi-fi-bluetooth/overview/lineup/type1yn +endchoice + +endif # AIROC_WIFI diff --git a/drivers/wifi/infineon/airoc_whd_hal.c b/drivers/wifi/infineon/airoc_whd_hal.c new file mode 100644 index 00000000000..5b02d0bba49 --- /dev/null +++ b/drivers/wifi/infineon/airoc_whd_hal.c @@ -0,0 +1,438 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include + +#define DT_DRV_COMPAT infineon_airoc_wifi + +LOG_MODULE_REGISTER(infineon_airoc, CONFIG_WIFI_LOG_LEVEL); + +#ifdef __cplusplus +extern "C" { +#endif + +/** Defines the amount of stack memory available for the wifi thread. */ +#if !defined(CY_WIFI_THREAD_STACK_SIZE) +#define CY_WIFI_THREAD_STACK_SIZE (5120) +#endif + +/** Defines the priority of the thread that services wifi packets. Legal values are defined by the + * RTOS being used. + */ +#if !defined(CY_WIFI_THREAD_PRIORITY) +#define CY_WIFI_THREAD_PRIORITY (CY_RTOS_PRIORITY_HIGH) +#endif + +/** Defines the country this will operate in for wifi initialization parameters. See the + * wifi-host-driver's whd_country_code_t for legal options. + */ +#if !defined(CY_WIFI_COUNTRY) +#define CY_WIFI_COUNTRY (WHD_COUNTRY_AUSTRALIA) +#endif + +/** Defines the priority of the interrupt that handles out-of-band notifications from the wifi + * chip. Legal values are defined by the MCU running this code. + */ +#if !defined(CY_WIFI_OOB_INTR_PRIORITY) +#define CY_WIFI_OOB_INTR_PRIORITY (2) +#endif + +/** Defines whether to use the out-of-band pin to allow the WIFI chip to wake up the MCU. */ +#if defined(CY_WIFI_HOST_WAKE_SW_FORCE) +#define CY_USE_OOB_INTR (CY_WIFI_HOST_WAKE_SW_FORCE) +#else +#define CY_USE_OOB_INTR (1u) +#endif /* defined(CY_WIFI_HOST_WAKE_SW_FORCE) */ + +#define CY_WIFI_HOST_WAKE_IRQ_EVENT GPIO_INT_TRIG_LOW +#define DEFAULT_OOB_PIN (0) +#define WLAN_POWER_UP_DELAY_MS (250) +#define WLAN_CBUCK_DISCHARGE_MS (10) + +extern whd_resource_source_t resource_ops; + +struct whd_bus_priv { + whd_sdio_config_t sdio_config; + whd_bus_stats_t whd_bus_stats; + whd_sdio_t sdio_obj; +}; + +static whd_init_config_t init_config_default = { + .thread_stack_size = CY_WIFI_THREAD_STACK_SIZE, + .thread_stack_start = NULL, + .thread_priority = (uint32_t)CY_WIFI_THREAD_PRIORITY, + .country = CY_WIFI_COUNTRY +}; + +/****************************************************** + * Function + ******************************************************/ + +int airoc_wifi_power_on(const struct device *dev) +{ +#if DT_INST_NODE_HAS_PROP(0, wifi_reg_on_gpios) + int ret; + const struct airoc_wifi_config *config = dev->config; + + /* Check WIFI REG_ON gpio instance */ + if (!device_is_ready(config->wifi_reg_on_gpio.port)) { + LOG_ERR("Error: failed to configure wifi_reg_on %s pin %d", + config->wifi_reg_on_gpio.port->name, config->wifi_reg_on_gpio.pin); + return -EIO; + } + + /* Configure wifi_reg_on as output */ + ret = gpio_pin_configure_dt(&config->wifi_reg_on_gpio, GPIO_OUTPUT); + if (ret) { + LOG_ERR("Error %d: failed to configure wifi_reg_on %s pin %d", ret, + config->wifi_reg_on_gpio.port->name, config->wifi_reg_on_gpio.pin); + return ret; + } + ret = gpio_pin_set_dt(&config->wifi_reg_on_gpio, 0); + if (ret) { + return ret; + } + + /* Allow CBUCK regulator to discharge */ + (void)cyhal_system_delay_ms(WLAN_CBUCK_DISCHARGE_MS); + + /* WIFI power on */ + ret = gpio_pin_set_dt(&config->wifi_reg_on_gpio, 1); + if (ret) { + return ret; + } + (void)cyhal_system_delay_ms(WLAN_POWER_UP_DELAY_MS); +#endif /* DT_INST_NODE_HAS_PROP(0, reg_on_gpios) */ + + return 0; +} + +int airoc_wifi_init_primary(const struct device *dev, whd_interface_t *interface, + whd_netif_funcs_t *netif_funcs, whd_buffer_funcs_t *buffer_if) +{ + int ret; + struct airoc_wifi_data *data = dev->data; + const struct airoc_wifi_config *config = dev->config; + + whd_sdio_config_t whd_sdio_config = { + .sdio_1bit_mode = WHD_FALSE, + .high_speed_sdio_clock = WHD_FALSE, + }; + +#if DT_INST_NODE_HAS_PROP(0, wifi_host_wake_gpios) + whd_oob_config_t oob_config = { + .host_oob_pin = (void *)&config->wifi_host_wake_gpio, + .dev_gpio_sel = DEFAULT_OOB_PIN, + .is_falling_edge = + (CY_WIFI_HOST_WAKE_IRQ_EVENT == GPIO_INT_TRIG_LOW) ? WHD_TRUE : WHD_FALSE, + .intr_priority = CY_WIFI_OOB_INTR_PRIORITY}; + whd_sdio_config.oob_config = oob_config; +#endif + + if (airoc_wifi_power_on(dev)) { + LOG_ERR("airoc_wifi_power_on retuens fail"); + return -ENODEV; + } + + if (!device_is_ready(config->sdhc_dev)) { + LOG_ERR("SDHC device is not ready"); + return -ENODEV; + } + + ret = sd_init(config->sdhc_dev, &data->card); + if (ret) { + return ret; + } + + /* Init SDIO functions */ + ret = sdio_init_func(&data->card, &data->sdio_func1, BACKPLANE_FUNCTION); + if (ret) { + LOG_ERR("sdio_enable_func BACKPLANE_FUNCTION, error: %x", ret); + return ret; + } + ret = sdio_init_func(&data->card, &data->sdio_func2, WLAN_FUNCTION); + if (ret) { + LOG_ERR("sdio_enable_func WLAN_FUNCTION, error: %x", ret); + return ret; + } + ret = sdio_set_block_size(&data->sdio_func1, SDIO_64B_BLOCK); + if (ret) { + LOG_ERR("Can't set block size for BACKPLANE_FUNCTION, error: %x", ret); + return ret; + } + ret = sdio_set_block_size(&data->sdio_func2, SDIO_64B_BLOCK); + if (ret) { + LOG_ERR("Can't set block size for WLAN_FUNCTION, error: %x", ret); + return ret; + } + + /* Init wifi host driver (whd) */ + cy_rslt_t whd_ret = whd_init(&data->whd_drv, &init_config_default, &resource_ops, buffer_if, + netif_funcs); + if (whd_ret == CY_RSLT_SUCCESS) { + whd_ret = whd_bus_sdio_attach(data->whd_drv, &whd_sdio_config, + (whd_sdio_t)&data->card); + + if (whd_ret == CY_RSLT_SUCCESS) { + whd_ret = whd_wifi_on(data->whd_drv, interface); + } + + if (whd_ret != CY_RSLT_SUCCESS) { + whd_deinit(*interface); + return -ENODEV; + } + } + return 0; +} + +/* + * Implement SDIO CMD52/53 wrappers + */ + +static struct sdio_func *airoc_wifi_get_sdio_func(struct sd_card *sd, whd_bus_function_t function) +{ + struct airoc_wifi_data *data = CONTAINER_OF(sd, struct airoc_wifi_data, card); + struct sdio_func *func[] = {&sd->func0, &data->sdio_func1, &data->sdio_func2}; + + if (function > WLAN_FUNCTION) { + return NULL; + } + + return func[function]; +} + +whd_result_t whd_bus_sdio_cmd52(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction, + whd_bus_function_t function, uint32_t address, uint8_t value, + sdio_response_needed_t response_expected, uint8_t *response) +{ + int ret; + struct sd_card *sd = whd_driver->bus_priv->sdio_obj; + struct sdio_func *func = airoc_wifi_get_sdio_func(sd, function); + + WHD_BUS_STATS_INCREMENT_VARIABLE(whd_driver->bus_priv, cmd52); + + if (direction == BUS_WRITE) { + ret = sdio_rw_byte(func, address, value, response); + } else { + ret = sdio_read_byte(func, address, response); + } + WHD_BUS_STATS_CONDITIONAL_INCREMENT_VARIABLE(whd_driver->bus_priv, (ret != WHD_SUCCESS), + cmd52_fail); + + /* Possibly device might not respond to this cmd. So, don't check return value here */ + if ((ret != WHD_SUCCESS) && (address == SDIO_SLEEP_CSR)) { + return ret; + } + + CHECK_RETURN(ret); + return WHD_SUCCESS; +} + +whd_result_t whd_bus_sdio_cmd53(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction, + whd_bus_function_t function, sdio_transfer_mode_t mode, + uint32_t address, uint16_t data_size, uint8_t *data, + sdio_response_needed_t response_expected, uint32_t *response) +{ + whd_result_t ret; + struct sd_card *sd = whd_driver->bus_priv->sdio_obj; + struct sdio_func *func = airoc_wifi_get_sdio_func(sd, function); + + if (direction == BUS_WRITE) { + WHD_BUS_STATS_INCREMENT_VARIABLE(whd_driver->bus_priv, cmd53_write); + ret = sdio_write_addr(func, address, data, data_size); + } else { + WHD_BUS_STATS_INCREMENT_VARIABLE(whd_driver->bus_priv, cmd53_read); + ret = sdio_read_addr(func, address, data, data_size); + } + + WHD_BUS_STATS_CONDITIONAL_INCREMENT_VARIABLE( + whd_driver->bus_priv, ((ret != WHD_SUCCESS) && (direction == BUS_READ)), + cmd53_read_fail); + WHD_BUS_STATS_CONDITIONAL_INCREMENT_VARIABLE( + whd_driver->bus_priv, ((ret != WHD_SUCCESS) && (direction == BUS_WRITE)), + cmd53_write_fail); + + CHECK_RETURN(ret); + return WHD_SUCCESS; +} + +/* + * Implement SDIO Card interrupt + */ + +void whd_bus_sdio_irq_handler(const struct device *dev, int reason, const void *user_data) +{ + if (reason == SDHC_INT_SDIO) { + whd_driver_t whd_driver = (whd_driver_t)user_data; + + WHD_BUS_STATS_INCREMENT_VARIABLE(whd_driver->bus_priv, sdio_intrs); + + /* call thread notify to wake up WHD thread */ + whd_thread_notify_irq(whd_driver); + } +} + +whd_result_t whd_bus_sdio_irq_register(whd_driver_t whd_driver) +{ + /* Nothing to do here, all handles by whd_bus_sdio_irq_enable function */ + return WHD_SUCCESS; +} + +whd_result_t whd_bus_sdio_irq_enable(whd_driver_t whd_driver, whd_bool_t enable) +{ + int ret; + struct sd_card *sd = whd_driver->bus_priv->sdio_obj; + + /* Enable/disable SDIO Card interrupts */ + if (enable) { + ret = sdhc_enable_interrupt(sd->sdhc, whd_bus_sdio_irq_handler, SDHC_INT_SDIO, + whd_driver); + } else { + ret = sdhc_disable_interrupt(sd->sdhc, SDHC_INT_SDIO); + } + return ret; +} + +/* + * Implement OOB functionality + */ + +void whd_bus_sdio_oob_irq_handler(const struct device *port, struct gpio_callback *cb, + gpio_port_pins_t pins) +{ +#if DT_INST_NODE_HAS_PROP(0, wifi_host_wake_gpios) + struct airoc_wifi_data *data = CONTAINER_OF(cb, struct airoc_wifi_data, host_oob_pin_cb); + + /* Get OOB pin info */ + const whd_oob_config_t *oob_config = &data->whd_drv->bus_priv->sdio_config.oob_config; + const struct gpio_dt_spec *host_oob_pin = oob_config->host_oob_pin; + + /* Check OOB state is correct */ + int expected_event = (oob_config->is_falling_edge == WHD_TRUE) ? 0 : 1; + + if (!(pins & BIT(host_oob_pin->pin)) || (gpio_pin_get_dt(host_oob_pin) != expected_event)) { + WPRINT_WHD_ERROR(("Unexpected interrupt event %d\n", expected_event)); + WHD_BUS_STATS_INCREMENT_VARIABLE(data->whd_drv->bus_priv, error_intrs); + return; + } + + WHD_BUS_STATS_INCREMENT_VARIABLE(data->whd_drv->bus_priv, oob_intrs); + + /* Call thread notify to wake up WHD thread */ + whd_thread_notify_irq(data->whd_drv); + +#endif /* DT_INST_NODE_HAS_PROP(0, wifi-host-wake-gpios) */ +} + +whd_result_t whd_bus_sdio_register_oob_intr(whd_driver_t whd_driver) +{ +#if DT_INST_NODE_HAS_PROP(0, wifi_host_wake_gpios) + int ret; + const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(0)); + struct airoc_wifi_data *data = dev->data; + + /* Get OOB pin info */ + const whd_oob_config_t *oob_config = &whd_driver->bus_priv->sdio_config.oob_config; + const struct gpio_dt_spec *host_oob_pin = oob_config->host_oob_pin; + + /* Check if OOB pin is ready */ + if (!gpio_is_ready_dt(host_oob_pin)) { + WPRINT_WHD_ERROR(("%s: Failed at gpio_is_ready_dt for host_oob_pin\n", __func__)); + return WHD_HAL_ERROR; + } + + /* Configure OOB pin as output */ + ret = gpio_pin_configure_dt(host_oob_pin, GPIO_INPUT); + if (ret != 0) { + WPRINT_WHD_ERROR(( + " %s: Failed at gpio_pin_configure_dt for host_oob_pin, result code = %d\n", + __func__, ret)); + return WHD_HAL_ERROR; + } + + /* Initialize/add OOB pin callback */ + gpio_init_callback(&data->host_oob_pin_cb, whd_bus_sdio_oob_irq_handler, + BIT(host_oob_pin->pin)); + + ret = gpio_add_callback_dt(host_oob_pin, &data->host_oob_pin_cb); + if (ret != 0) { + WPRINT_WHD_ERROR( + ("%s: Failed at gpio_add_callback_dt for host_oob_pin, result code = %d\n", + __func__, ret)); + return WHD_HAL_ERROR; + } +#endif /* DT_INST_NODE_HAS_PROP(0, wifi_host_wake_gpios) */ + + return WHD_SUCCESS; +} + +whd_result_t whd_bus_sdio_unregister_oob_intr(whd_driver_t whd_driver) +{ +#if DT_INST_NODE_HAS_PROP(0, wifi_host_wake_gpios) + int ret; + const whd_oob_config_t *oob_config = &whd_driver->bus_priv->sdio_config.oob_config; + + /* Disable OOB pin interrupts */ + ret = gpio_pin_interrupt_configure_dt(oob_config->host_oob_pin, GPIO_INT_DISABLE); + if (ret != 0) { + WPRINT_WHD_ERROR(("%s: Failed at gpio_pin_interrupt_configure_dt for host_oob_pin, " + "result code = %d\n", + __func__, ret)); + return WHD_HAL_ERROR; + } +#endif /* DT_INST_NODE_HAS_PROP(0, wifi_host_wake_gpios) */ + return WHD_SUCCESS; +} + +whd_result_t whd_bus_sdio_enable_oob_intr(whd_driver_t whd_driver, whd_bool_t enable) +{ +#if DT_INST_NODE_HAS_PROP(0, wifi_host_wake_gpios) + int ret; + const whd_oob_config_t *oob_config = &whd_driver->bus_priv->sdio_config.oob_config; + uint32_t trig_conf = + (oob_config->is_falling_edge == WHD_TRUE) ? GPIO_INT_TRIG_LOW : GPIO_INT_TRIG_HIGH; + + /* Enable OOB pin interrupts */ + ret = gpio_pin_interrupt_configure_dt(oob_config->host_oob_pin, + GPIO_INT_ENABLE | GPIO_INT_EDGE | trig_conf); + if (ret != 0) { + WPRINT_WHD_ERROR(("%s: Failed at gpio_pin_interrupt_configure_dt for host_oob_pin, " + "result code = %d\n", + __func__, ret)); + return WHD_HAL_ERROR; + } +#endif /* DT_INST_NODE_HAS_PROP(0, wifi_host_wake_gpios) */ + return WHD_SUCCESS; +} + +/* + * Implement WHD memory wrappers + */ + +void *whd_mem_malloc(size_t size) +{ + return k_malloc(size); +} + +void *whd_mem_calloc(size_t nitems, size_t size) +{ + return k_calloc(nitems, size); +} + +void whd_mem_free(void *ptr) +{ + k_free(ptr); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif diff --git a/drivers/wifi/infineon/airoc_wifi.c b/drivers/wifi/infineon/airoc_wifi.c new file mode 100644 index 00000000000..c0c780822d8 --- /dev/null +++ b/drivers/wifi/infineon/airoc_wifi.c @@ -0,0 +1,772 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief AIROC Wi-Fi driver. + */ + +#define DT_DRV_COMPAT infineon_airoc_wifi + +#include +#include + +LOG_MODULE_REGISTER(infineon_airoc_wifi, CONFIG_WIFI_LOG_LEVEL); + +#ifndef AIROC_WIFI_TX_PACKET_POOL_COUNT +#define AIROC_WIFI_TX_PACKET_POOL_COUNT (10) +#endif + +#ifndef AIROC_WIFI_RX_PACKET_POOL_COUNT +#define AIROC_WIFI_RX_PACKET_POOL_COUNT (10) +#endif + +#ifndef AIROC_WIFI_PACKET_POOL_SIZE +#define AIROC_WIFI_PACKET_POOL_SIZE (1600) +#endif + +#define AIROC_WIFI_PACKET_POOL_COUNT \ + (AIROC_WIFI_TX_PACKET_POOL_COUNT + AIROC_WIFI_RX_PACKET_POOL_COUNT) + +#define AIROC_WIFI_WAIT_SEMA_MS (30 * 1000) +#define AIROC_WIFI_SCAN_TIMEOUT_MS (12 * 1000) + +/* AIROC private functions */ +static whd_result_t airoc_wifi_host_buffer_get(whd_buffer_t *buffer, whd_buffer_dir_t direction, + uint16_t size, uint32_t timeout_ms); +static void airoc_wifi_buffer_release(whd_buffer_t buffer, whd_buffer_dir_t direction); +static uint8_t *airoc_wifi_buffer_get_current_piece_data_pointer(whd_buffer_t buffer); +static uint16_t airoc_wifi_buffer_get_current_piece_size(whd_buffer_t buffer); +static whd_result_t airoc_wifi_buffer_set_size(whd_buffer_t buffer, unsigned short size); +static whd_result_t airoc_wifi_buffer_add_remove_at_front(whd_buffer_t *buffer, + int32_t add_remove_amount); +static void airoc_wifi_network_process_ethernet_data(whd_interface_t interface, + whd_buffer_t buffer); +int airoc_wifi_init_primary(const struct device *dev, whd_interface_t *interface, + whd_netif_funcs_t *netif_funcs, whd_buffer_funcs_t *buffer_if); + +/* Allocate network pool */ +NET_BUF_POOL_FIXED_DEFINE(airoc_pool, AIROC_WIFI_PACKET_POOL_COUNT, + AIROC_WIFI_PACKET_POOL_SIZE, 0, NULL); + +/* AIROC globals */ +static uint16_t ap_event_handler_index = 0xFF; + +/* Use global iface pointer to support any Ethernet driver */ +/* necessary for wifi callback functions */ +static struct net_if *airoc_wifi_iface; + +static whd_interface_t airoc_if; +static whd_interface_t airoc_sta_if; +static whd_interface_t airoc_ap_if; + +static const whd_event_num_t sta_link_events[] = { + WLC_E_LINK, WLC_E_DEAUTH_IND, WLC_E_DISASSOC_IND, + WLC_E_PSK_SUP, WLC_E_CSA_COMPLETE_IND, WLC_E_NONE}; + +static const whd_event_num_t ap_link_events[] = {WLC_E_DISASSOC_IND, WLC_E_DEAUTH_IND, + WLC_E_ASSOC_IND, WLC_E_REASSOC_IND, + WLC_E_AUTHORIZED, WLC_E_NONE}; + +static uint16_t sta_event_handler_index = 0xFF; +static void airoc_event_task(void); +static struct airoc_wifi_data airoc_wifi_data = {0}; + +static struct airoc_wifi_config airoc_wifi_config = { + .sdhc_dev = DEVICE_DT_GET(DT_INST_PARENT(0)), + .wifi_reg_on_gpio = GPIO_DT_SPEC_GET_OR(DT_DRV_INST(0), wifi_reg_on_gpios, {0}), + .wifi_host_wake_gpio = GPIO_DT_SPEC_GET_OR(DT_DRV_INST(0), wifi_host_wake_gpios, {0}), + .wifi_dev_wake_gpio = GPIO_DT_SPEC_GET_OR(DT_DRV_INST(0), wifi_dev_wake_gpios, {0}), +}; + +static whd_buffer_funcs_t airoc_wifi_buffer_if_default = { + .whd_host_buffer_get = airoc_wifi_host_buffer_get, + .whd_buffer_release = airoc_wifi_buffer_release, + .whd_buffer_get_current_piece_data_pointer = + airoc_wifi_buffer_get_current_piece_data_pointer, + .whd_buffer_get_current_piece_size = airoc_wifi_buffer_get_current_piece_size, + .whd_buffer_set_size = airoc_wifi_buffer_set_size, + .whd_buffer_add_remove_at_front = airoc_wifi_buffer_add_remove_at_front, +}; + +static whd_netif_funcs_t airoc_wifi_netif_if_default = { + .whd_network_process_ethernet_data = airoc_wifi_network_process_ethernet_data, +}; + +K_MSGQ_DEFINE(airoc_wifi_msgq, sizeof(whd_event_header_t), 10, 4); +K_THREAD_STACK_DEFINE(airoc_wifi_event_stack, CONFIG_AIROC_WIFI_EVENT_TASK_STACK_SIZE); +static struct k_thread airoc_wifi_event_thread; + +struct airoc_wifi_event_t { + uint8_t is_ap_event; + uint32_t event_type; +}; + +/* + * AIROC Wi-Fi helper functions + */ +whd_interface_t airoc_wifi_get_whd_interface(void) +{ + return airoc_if; +} + +static void airoc_wifi_scan_cb_search(whd_scan_result_t **result_ptr, void *user_data, + whd_scan_status_t status) +{ + if (status == WHD_SCAN_ABORTED) { + k_sem_give(&airoc_wifi_data.sema_scan); + return; + } + + if (status == WHD_SCAN_COMPLETED_SUCCESSFULLY) { + k_sem_give(&airoc_wifi_data.sema_scan); + } else if ((status == WHD_SCAN_INCOMPLETE) && (user_data != NULL) && + ((**result_ptr).SSID.length > 0)) { + + if (strncmp(((whd_scan_result_t *)user_data)->SSID.value, (**result_ptr).SSID.value, + (**result_ptr).SSID.length) == 0) { + memcpy(user_data, *result_ptr, sizeof(whd_scan_result_t)); + } + } +} + +static int convert_whd_security_to_zephyr(whd_security_t security) +{ + int zephyr_security = WIFI_SECURITY_TYPE_UNKNOWN; + + switch (security) { + case WHD_SECURITY_OPEN: + zephyr_security = WIFI_SECURITY_TYPE_NONE; + break; + case WHD_SECURITY_WEP_PSK: + zephyr_security = WIFI_SECURITY_TYPE_WEP; + break; + + case WHD_SECURITY_WPA3_WPA2_PSK: + case WHD_SECURITY_WPA2_AES_PSK: + zephyr_security = WIFI_SECURITY_TYPE_PSK; + break; + + case WHD_SECURITY_WPA2_AES_PSK_SHA256: + zephyr_security = WIFI_SECURITY_TYPE_PSK_SHA256; + break; + + case WHD_SECURITY_WPA3_SAE: + zephyr_security = WIFI_SECURITY_TYPE_SAE; + break; + + case WHD_SECURITY_WPA_AES_PSK: + zephyr_security = WIFI_SECURITY_TYPE_WPA_PSK; + break; + + default: + if ((security & ENTERPRISE_ENABLED) != 0) { + zephyr_security = WIFI_SECURITY_TYPE_EAP; + } + break; + } + return zephyr_security; +} + +static void parse_scan_result(whd_scan_result_t *p_whd_result, struct wifi_scan_result *p_zy_result) +{ + if (p_whd_result->SSID.length != 0) { + p_zy_result->ssid_length = p_whd_result->SSID.length; + strncpy(p_zy_result->ssid, p_whd_result->SSID.value, p_whd_result->SSID.length); + p_zy_result->channel = p_whd_result->channel; + p_zy_result->security = convert_whd_security_to_zephyr(p_whd_result->security); + p_zy_result->rssi = (int8_t)p_whd_result->signal_strength; + p_zy_result->mac_length = 6; + memcpy(p_zy_result->mac, &p_whd_result->BSSID, 6); + } +} + +static void scan_callback(whd_scan_result_t **result_ptr, void *user_data, whd_scan_status_t status) +{ + struct airoc_wifi_data *data = user_data; + whd_scan_result_t whd_scan_result; + struct wifi_scan_result zephyr_scan_result; + + if (status == WHD_SCAN_COMPLETED_SUCCESSFULLY || status == WHD_SCAN_ABORTED) { + data->scan_rslt_cb(data->iface, 0, NULL); + data->scan_rslt_cb = NULL; + /* NOTE: It is complete of scan packet, do not need to clean result_ptr, + * WHD will release result_ptr buffer + */ + return; + } + + /* We recived scan data so process it */ + if ((result_ptr != NULL) && (*result_ptr != NULL)) { + memcpy(&whd_scan_result, *result_ptr, sizeof(whd_scan_result_t)); + parse_scan_result(&whd_scan_result, &zephyr_scan_result); + data->scan_rslt_cb(data->iface, 0, &zephyr_scan_result); + } + memset(*result_ptr, 0, sizeof(whd_scan_result_t)); +} + +/* + * Implement WHD network buffers functions + */ +static whd_result_t airoc_wifi_host_buffer_get(whd_buffer_t *buffer, whd_buffer_dir_t direction, + uint16_t size, uint32_t timeout_ms) +{ + ARG_UNUSED(direction); + ARG_UNUSED(timeout_ms); + struct net_buf *buf; + + buf = net_buf_alloc_len(&airoc_pool, size, K_NO_WAIT); + if (buf == NULL) { + return WHD_BUFFER_ALLOC_FAIL; + } + *buffer = buf; + return WHD_SUCCESS; +} + +static void airoc_wifi_buffer_release(whd_buffer_t buffer, whd_buffer_dir_t direction) +{ + CY_UNUSED_PARAMETER(direction); + (void)net_buf_destroy((struct net_buf *)buffer); +} + +static uint8_t *airoc_wifi_buffer_get_current_piece_data_pointer(whd_buffer_t buffer) +{ + CY_ASSERT(buffer != NULL); + struct net_buf *buf = (struct net_buf *)buffer; + + return (uint8_t *)buf->data; +} + +static uint16_t airoc_wifi_buffer_get_current_piece_size(whd_buffer_t buffer) +{ + CY_ASSERT(buffer != NULL); + struct net_buf *buf = (struct net_buf *)buffer; + + return (uint16_t)buf->size; +} + +static whd_result_t airoc_wifi_buffer_set_size(whd_buffer_t buffer, unsigned short size) +{ + CY_ASSERT(buffer != NULL); + struct net_buf *buf = (struct net_buf *)buffer; + + buf->size = size; + return CY_RSLT_SUCCESS; +} + +static whd_result_t airoc_wifi_buffer_add_remove_at_front(whd_buffer_t *buffer, + int32_t add_remove_amount) +{ + CY_ASSERT(buffer != NULL); + struct net_buf **buf = (struct net_buf **)buffer; + + if (add_remove_amount > 0) { + (*buf)->len = (*buf)->size; + (*buf)->data = net_buf_pull(*buf, add_remove_amount); + } else { + (*buf)->data = net_buf_push(*buf, -add_remove_amount); + (*buf)->len = (*buf)->size; + } + return WHD_SUCCESS; +} + +static int airoc_mgmt_send(const struct device *dev, struct net_pkt *pkt) +{ + struct airoc_wifi_data *data = dev->data; + cy_rslt_t ret; + size_t pkt_len = net_pkt_get_len(pkt); + struct net_buf *buf = NULL; + + /* Read the packet payload */ + if (net_pkt_read(pkt, data->frame_buf, pkt_len) < 0) { + LOG_ERR("net_pkt_read failed"); + return -EIO; + } + + /* Allocate Network Buffer from pool with Packet Length + Data Header */ + buf = net_buf_alloc_len(&airoc_pool, pkt_len + sizeof(data_header_t), K_NO_WAIT); + if (buf == NULL) { + return -EIO; + } + + /* Reserve the buffer Headroom for WHD Data header */ + net_buf_reserve(buf, sizeof(data_header_t)); + + /* Copy the buffer to network Buffer pointer */ + (void)memcpy(buf->data, data->frame_buf, pkt_len); + + /* Call WHD API to send out the Packet */ + ret = whd_network_send_ethernet_data(airoc_if, (void *)buf); + if (ret != CY_RSLT_SUCCESS) { + LOG_ERR("whd_network_send_ethernet_data failed"); +#if defined(CONFIG_NET_STATISTICS_WIFI) + data->stats.errors.tx++; +#endif + return -EIO; + } + +#if defined(CONFIG_NET_STATISTICS_WIFI) + data->stats.bytes.sent += pkt_len; + data->stats.pkts.tx++; +#endif + + return 0; +} + +static void airoc_wifi_network_process_ethernet_data(whd_interface_t interface, whd_buffer_t buffer) +{ + struct net_pkt *pkt; + uint8_t *data = whd_buffer_get_current_piece_data_pointer(interface->whd_driver, buffer); + uint32_t len = whd_buffer_get_current_piece_size(interface->whd_driver, buffer); + bool net_pkt_unref_flag = false; + + if ((airoc_wifi_iface != NULL) && net_if_flag_is_set(airoc_wifi_iface, NET_IF_UP)) { + + pkt = net_pkt_rx_alloc_with_buffer(airoc_wifi_iface, len, AF_UNSPEC, 0, K_NO_WAIT); + + if (pkt != NULL) { + if (net_pkt_write(pkt, data, len) < 0) { + LOG_ERR("Failed to write pkt"); + net_pkt_unref_flag = true; + } + + if ((net_pkt_unref_flag) || (net_recv_data(airoc_wifi_iface, pkt) < 0)) { + LOG_ERR("Failed to push received data"); + net_pkt_unref_flag = true; + } + } else { + LOG_ERR("Failed to get net buffer"); + } + } + + /* Release a packet buffer */ + airoc_wifi_buffer_release(buffer, WHD_NETWORK_RX); + +#if defined(CONFIG_NET_STATISTICS_WIFI) + airoc_wifi_data.stats.bytes.received += len; + airoc_wifi_data.stats.pkts.rx++; +#endif + + if (net_pkt_unref_flag) { + net_pkt_unref(pkt); +#if defined(CONFIG_NET_STATISTICS_WIFI) + airoc_wifi_data.stats.errors.rx++; +#endif + } +} + +static void *link_events_handler(whd_interface_t ifp, const whd_event_header_t *event_header, + const uint8_t *event_data, void *handler_user_data) +{ + ARG_UNUSED(ifp); + ARG_UNUSED(event_data); + ARG_UNUSED(handler_user_data); + + k_msgq_put(&airoc_wifi_msgq, event_header, K_FOREVER); + return NULL; +} + +static void airoc_event_task(void) +{ + whd_event_header_t event_header; + + while (1) { + k_msgq_get(&airoc_wifi_msgq, &event_header, K_FOREVER); + + switch ((whd_event_num_t)event_header.event_type) { + case WLC_E_LINK: + break; + + case WLC_E_DEAUTH_IND: + case WLC_E_DISASSOC_IND: + net_if_dormant_on(airoc_wifi_iface); + break; + + default: + break; + } + } +} + +static void airoc_mgmt_init(struct net_if *iface) +{ + const struct device *dev = net_if_get_device(iface); + struct airoc_wifi_data *data = dev->data; + struct ethernet_context *eth_ctx = net_if_l2_data(iface); + + eth_ctx->eth_if_type = L2_ETH_IF_TYPE_WIFI; + data->iface = iface; + airoc_wifi_iface = iface; + + /* Read WLAN MAC Address */ + if (whd_wifi_get_mac_address(airoc_sta_if, &airoc_sta_if->mac_addr) != WHD_SUCCESS) { + LOG_ERR("Failed to get mac address"); + } else { + (void)memcpy(&data->mac_addr, &airoc_sta_if->mac_addr, + sizeof(airoc_sta_if->mac_addr)); + } + + /* Assign link local address. */ + if (net_if_set_link_addr(iface, data->mac_addr, 6, NET_LINK_ETHERNET)) { + LOG_ERR("Failed to set link addr"); + } + + /* Initialize Ethernet L2 stack */ + ethernet_init(iface); + + /* Not currently connected to a network */ + net_if_dormant_on(iface); + + /* L1 network layer (physical layer) is up */ + net_if_carrier_on(data->iface); +} + +static int airoc_mgmt_scan(const struct device *dev, struct wifi_scan_params *params, + scan_result_cb_t cb) +{ + struct airoc_wifi_data *data = dev->data; + + if (data->scan_rslt_cb != NULL) { + LOG_INF("Scan callback in progress"); + return -EINPROGRESS; + } + + if (k_sem_take(&data->sema_common, K_MSEC(AIROC_WIFI_WAIT_SEMA_MS)) != 0) { + return -EAGAIN; + } + + data->scan_rslt_cb = cb; + + /* Connect to the network */ + if (whd_wifi_scan(airoc_sta_if, params->scan_type, WHD_BSS_TYPE_ANY, &(data->ssid), NULL, + NULL, NULL, scan_callback, &(data->scan_result), data) != WHD_SUCCESS) { + LOG_ERR("Failed to start scan"); + k_sem_give(&data->sema_common); + return -EAGAIN; + } + + k_sem_give(&data->sema_common); + return 0; +} + +static int airoc_mgmt_connect(const struct device *dev, struct wifi_connect_req_params *params) +{ + struct airoc_wifi_data *data = (struct airoc_wifi_data *)dev->data; + whd_ssid_t ssid = {0}; + int ret = 0; + + if (k_sem_take(&data->sema_common, K_MSEC(AIROC_WIFI_WAIT_SEMA_MS)) != 0) { + return -EAGAIN; + } + + if (data->is_sta_connected) { + LOG_ERR("Already connected"); + ret = -EALREADY; + goto error; + } + + if (data->is_ap_up) { + LOG_ERR("Network interface is busy AP. Please first disable AP."); + ret = -EBUSY; + goto error; + } + + ssid.length = params->ssid_length; + memcpy(ssid.value, params->ssid, params->ssid_length); + + whd_scan_result_t scan_result; + whd_scan_result_t usr_result = {0}; + + usr_result.SSID.length = ssid.length; + memcpy(usr_result.SSID.value, ssid.value, ssid.length); + + if (whd_wifi_scan(airoc_sta_if, WHD_SCAN_TYPE_ACTIVE, WHD_BSS_TYPE_ANY, NULL, NULL, NULL, + NULL, airoc_wifi_scan_cb_search, &scan_result, + &(usr_result)) != WHD_SUCCESS) { + LOG_ERR("Failed start scan"); + ret = -EAGAIN; + goto error; + } + + if (k_sem_take(&airoc_wifi_data.sema_scan, K_MSEC(AIROC_WIFI_SCAN_TIMEOUT_MS)) != 0) { + whd_wifi_stop_scan(airoc_sta_if); + ret = -EAGAIN; + goto error; + } + + if (usr_result.security == 0) { + ret = -EAGAIN; + LOG_ERR("Could not scan device"); + goto error; + } + + /* Connect to the network */ + if (whd_wifi_join(airoc_sta_if, &usr_result.SSID, usr_result.security, params->psk, + params->psk_length) != WHD_SUCCESS) { + LOG_ERR("Failed to connect with network"); + + ret = -EAGAIN; + goto error; + } + +error: + if (ret < 0) { + net_if_dormant_on(data->iface); + } else { + net_if_dormant_off(data->iface); + data->is_sta_connected = true; +#if defined(CONFIG_NET_DHCPV4) + net_dhcpv4_restart(data->iface); +#endif /* defined(CONFIG_NET_DHCPV4) */ + } + + wifi_mgmt_raise_connect_result_event(data->iface, ret); + k_sem_give(&data->sema_common); + return ret; +} + +static int airoc_mgmt_disconnect(const struct device *dev) +{ + int ret = 0; + struct airoc_wifi_data *data = (struct airoc_wifi_data *)dev->data; + + if (k_sem_take(&data->sema_common, K_MSEC(AIROC_WIFI_WAIT_SEMA_MS)) != 0) { + return -EAGAIN; + } + + if (whd_wifi_leave(airoc_sta_if) != WHD_SUCCESS) { + k_sem_give(&data->sema_common); + ret = -EAGAIN; + } else { + data->is_sta_connected = false; + net_if_dormant_on(data->iface); + } + + wifi_mgmt_raise_disconnect_result_event(data->iface, ret); + k_sem_give(&data->sema_common); + + return ret; +} + +static void *airoc_wifi_ap_link_events_handler(whd_interface_t ifp, + const whd_event_header_t *event_header, + const uint8_t *event_data, void *handler_user_data) +{ + struct airoc_wifi_event_t airoc_event = { + .is_ap_event = 1, + .event_type = event_header->event_type + }; + + k_msgq_put(&airoc_wifi_msgq, &airoc_event, K_FOREVER); + + return NULL; +} + +static int airoc_mgmt_ap_enable(const struct device *dev, struct wifi_connect_req_params *params) +{ + struct airoc_wifi_data *data = dev->data; + whd_security_t security; + whd_ssid_t ssid; + uint8_t channel; + int ret = 0; + + if (k_sem_take(&data->sema_common, K_MSEC(AIROC_WIFI_WAIT_SEMA_MS)) != 0) { + return -EAGAIN; + } + + if (data->is_sta_connected) { + LOG_ERR("Network interface is busy in STA mode. Please first disconnect STA."); + ret = -EBUSY; + goto error; + } + + if (data->is_ap_up) { + LOG_ERR("Already AP is on - first disable"); + ret = -EAGAIN; + goto error; + } + + if (!data->second_interface_init) { + if (whd_add_secondary_interface(data->whd_drv, NULL, &airoc_ap_if) != + CY_RSLT_SUCCESS) { + LOG_ERR("Error Unable to bring up the whd secondary interface"); + ret = -EAGAIN; + goto error; + } + data->second_interface_init = true; + } + + ssid.length = params->ssid_length; + memcpy(ssid.value, params->ssid, ssid.length); + + /* make sure to set valid channels for 2G and 5G: + * - 2G channels from 1 to 11, + * - 5G channels from 36 to 165 + */ + if (((params->channel > 0) && (params->channel < 12)) || + ((params->channel > 35) && (params->channel < 166))) { + channel = params->channel; + } else { + channel = 1; + LOG_WRN("Discard of setting unsupported channel: %u (will set 1)", + params->channel); + } + + if (params->psk_length == 0) { + security = WHD_SECURITY_OPEN; + } else { + security = WHD_SECURITY_WPA2_AES_PSK; + } + + if (whd_wifi_init_ap(airoc_ap_if, &ssid, security, (const uint8_t *)params->psk, + params->psk_length, channel) != 0) { + LOG_ERR("Failed to init whd ap interface"); + ret = -EAGAIN; + goto error; + } + + if (whd_wifi_start_ap(airoc_ap_if) != 0) { + LOG_ERR("Failed to start whd ap interface"); + ret = -EAGAIN; + goto error; + } + + /* set event handler */ + if (whd_management_set_event_handler(airoc_ap_if, ap_link_events, + airoc_wifi_ap_link_events_handler, NULL, + &ap_event_handler_index) != 0) { + whd_wifi_stop_ap(airoc_ap_if); + ret = -EAGAIN; + goto error; + } + + data->is_ap_up = true; + airoc_if = airoc_ap_if; +error: + + k_sem_give(&data->sema_common); + return ret; +} + +#if defined(CONFIG_NET_STATISTICS_WIFI) +static int airoc_mgmt_wifi_stats(const struct device *dev, struct net_stats_wifi *stats) +{ + struct airoc_wifi_data *data = dev->data; + + stats->bytes.received = data->stats.bytes.received; + stats->bytes.sent = data->stats.bytes.sent; + stats->pkts.rx = data->stats.pkts.rx; + stats->pkts.tx = data->stats.pkts.tx; + stats->errors.rx = data->stats.errors.rx; + stats->errors.tx = data->stats.errors.tx; + stats->broadcast.rx = data->stats.broadcast.rx; + stats->broadcast.tx = data->stats.broadcast.tx; + stats->multicast.rx = data->stats.multicast.rx; + stats->multicast.tx = data->stats.multicast.tx; + stats->sta_mgmt.beacons_rx = data->stats.sta_mgmt.beacons_rx; + stats->sta_mgmt.beacons_miss = data->stats.sta_mgmt.beacons_miss; + + return 0; +} +#endif + +static int airoc_mgmt_ap_disable(const struct device *dev) +{ + cy_rslt_t whd_ret; + struct airoc_wifi_data *data = dev->data; + + if (k_sem_take(&data->sema_common, K_MSEC(AIROC_WIFI_WAIT_SEMA_MS)) != 0) { + return -EAGAIN; + } + + if (whd_wifi_deregister_event_handler(airoc_ap_if, ap_event_handler_index)) { + LOG_ERR("Can't whd_wifi_deregister_event_handler"); + } + + whd_ret = whd_wifi_stop_ap(airoc_ap_if); + if (whd_ret == CY_RSLT_SUCCESS) { + data->is_ap_up = false; + airoc_if = airoc_sta_if; + } else { + LOG_ERR("Can't stop wifi ap: %u", whd_ret); + } + + k_sem_give(&data->sema_common); + + if (whd_ret != CY_RSLT_SUCCESS) { + return -ENODEV; + } + + return 0; +} + +static int airoc_init(const struct device *dev) +{ + int ret; + cy_rslt_t whd_ret; + struct airoc_wifi_data *data = dev->data; + + k_tid_t tid = k_thread_create( + &airoc_wifi_event_thread, airoc_wifi_event_stack, + CONFIG_AIROC_WIFI_EVENT_TASK_STACK_SIZE, (k_thread_entry_t)airoc_event_task, NULL, + NULL, NULL, CONFIG_AIROC_WIFI_EVENT_TASK_PRIO, K_INHERIT_PERMS, K_NO_WAIT); + + if (!tid) { + LOG_ERR("ERROR spawning tx thread"); + return -EAGAIN; + } + k_thread_name_set(tid, "airoc_event"); + + whd_ret = airoc_wifi_init_primary(dev, &airoc_sta_if, &airoc_wifi_netif_if_default, + &airoc_wifi_buffer_if_default); + if (whd_ret != CY_RSLT_SUCCESS) { + LOG_ERR("airoc_wifi_init_primary failed ret = %d \r\n", whd_ret); + return -EAGAIN; + } + airoc_if = airoc_sta_if; + + whd_ret = whd_management_set_event_handler(airoc_sta_if, sta_link_events, + link_events_handler, NULL, &sta_event_handler_index); + if (whd_ret != CY_RSLT_SUCCESS) { + LOG_ERR("whd_management_set_event_handler failed ret = %d \r\n", whd_ret); + return -EAGAIN; + } + + ret = k_sem_init(&data->sema_common, 1, 1); + if (ret != 0) { + LOG_ERR("k_sem_init(sema_common) failure"); + return ret; + } + + ret = k_sem_init(&data->sema_scan, 0, 1); + if (ret != 0) { + LOG_ERR("k_sem_init(sema_scan) failure"); + return ret; + } + + return 0; +} + +static const struct wifi_mgmt_ops airoc_wifi_mgmt = { + .scan = airoc_mgmt_scan, + .connect = airoc_mgmt_connect, + .disconnect = airoc_mgmt_disconnect, + .ap_enable = airoc_mgmt_ap_enable, + .ap_disable = airoc_mgmt_ap_disable, +#if defined(CONFIG_NET_STATISTICS_ETHERNET) + .get_stats = airoc_mgmt_wifi_stats, +#endif +}; + +static const struct net_wifi_mgmt_offload airoc_api = { + .wifi_iface.iface_api.init = airoc_mgmt_init, + .wifi_iface.send = airoc_mgmt_send, + .wifi_mgmt_api = &airoc_wifi_mgmt, +}; + +NET_DEVICE_DT_INST_DEFINE(0, airoc_init, NULL, &airoc_wifi_data, &airoc_wifi_config, + CONFIG_WIFI_INIT_PRIORITY, &airoc_api, ETHERNET_L2, + NET_L2_GET_CTX_TYPE(ETHERNET_L2), WHD_LINK_MTU); diff --git a/drivers/wifi/infineon/airoc_wifi.h b/drivers/wifi/infineon/airoc_wifi.h new file mode 100644 index 00000000000..648423ab109 --- /dev/null +++ b/drivers/wifi/infineon/airoc_wifi.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +struct airoc_wifi_data { + struct sd_card card; + struct sdio_func sdio_func1; + struct sdio_func sdio_func2; + struct net_if *iface; + bool second_interface_init; + bool is_ap_up; + bool is_sta_connected; + uint8_t mac_addr[6]; + scan_result_cb_t scan_rslt_cb; + whd_ssid_t ssid; + whd_scan_result_t scan_result; + struct k_sem sema_common; + struct k_sem sema_scan; +#if defined(CONFIG_NET_STATISTICS_WIFI) + struct net_stats_wifi stats; +#endif + whd_driver_t whd_drv; + struct gpio_callback host_oob_pin_cb; + uint8_t frame_buf[NET_ETH_MAX_FRAME_SIZE]; +}; + +struct airoc_wifi_config { + const struct device *sdhc_dev; + struct gpio_dt_spec wifi_reg_on_gpio; + struct gpio_dt_spec wifi_host_wake_gpio; + struct gpio_dt_spec wifi_dev_wake_gpio; +}; + +/** + * \brief This function returns pointer type to handle instance + * of whd interface (whd_interface_t) which allocated in + * Zephyr AIROC driver (drivers/wifi/infineon/airoc_wifi.c) + */ + +whd_interface_t airoc_wifi_get_whd_interface(void); diff --git a/drivers/wifi/infineon/cybsp.h b/drivers/wifi/infineon/cybsp.h new file mode 100644 index 00000000000..dfa23ffbae5 --- /dev/null +++ b/drivers/wifi/infineon/cybsp.h @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* This is enpty/stub file used in WHD */ diff --git a/drivers/wifi/simplelink/CMakeLists.txt b/drivers/wifi/simplelink/CMakeLists.txt index 8e9a24b7c82..3dbe2a2807f 100644 --- a/drivers/wifi/simplelink/CMakeLists.txt +++ b/drivers/wifi/simplelink/CMakeLists.txt @@ -3,6 +3,7 @@ if(CONFIG_WIFI_SIMPLELINK) zephyr_library_include_directories( ${ZEPHYR_BASE}/subsys/net/lib/tls_credentials + ${ZEPHYR_BASE}/subsys/net/lib/sockets ) zephyr_library_sources( simplelink_support.c diff --git a/drivers/wifi/simplelink/Kconfig.simplelink b/drivers/wifi/simplelink/Kconfig.simplelink index 6e59c3702d3..f2c5ccacbab 100644 --- a/drivers/wifi/simplelink/Kconfig.simplelink +++ b/drivers/wifi/simplelink/Kconfig.simplelink @@ -8,6 +8,7 @@ menuconfig WIFI_SIMPLELINK select SIMPLELINK_HOST_DRIVER select WIFI_OFFLOAD select NET_L2_WIFI_MGMT + select FDTABLE if WIFI_SIMPLELINK diff --git a/drivers/wifi/winc1500/wifi_winc1500.c b/drivers/wifi/winc1500/wifi_winc1500.c index 26488293628..95d97fcfeaa 100644 --- a/drivers/wifi/winc1500/wifi_winc1500.c +++ b/drivers/wifi/winc1500/wifi_winc1500.c @@ -158,11 +158,11 @@ struct winc1500_data { static struct winc1500_data w1500_data; #if LOG_LEVEL > LOG_LEVEL_OFF - static void stack_stats(void) { log_stack_usage(&winc1500_thread_data); } +#endif /* LOG_LEVEL > LOG_LEVEL_OFF */ static char *socket_error_string(int8_t err) { @@ -285,8 +285,6 @@ static char *socket_message_to_string(uint8_t message) } } -#endif /* LOG_LEVEL > LOG_LEVEL_OFF */ - /** * This function is called when the socket is to be opened. */ @@ -641,6 +639,7 @@ static void handle_wifi_con_state_changed(void *pvMsg) LOG_DBG("Connected (%u)", pstrWifiState->u8ErrCode); w1500_data.connected = true; + w1500_data.connecting = false; wifi_mgmt_raise_connect_result_event(w1500_data.iface, 0); break; @@ -773,8 +772,9 @@ static void winc1500_wifi_cb(uint8_t message_type, void *pvMsg) default: break; } - +#if LOG_LEVEL > LOG_LEVEL_OFF stack_stats(); +#endif /* LOG_LEVEL > LOG_LEVEL_OFF */ } static void handle_socket_msg_connect(struct socket_data *sd, void *pvMsg) @@ -962,12 +962,17 @@ static void winc1500_socket_cb(SOCKET sock, uint8 message, void *pvMsg) break; } - +#if LOG_LEVEL > LOG_LEVEL_OFF stack_stats(); +#endif /* LOG_LEVEL > LOG_LEVEL_OFF */ } -static void winc1500_thread(void) +static void winc1500_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + while (1) { while (m2m_wifi_handle_events(NULL) != 0) { } @@ -1168,7 +1173,7 @@ static int winc1500_init(const struct device *dev) /* monitoring thread for winc wifi callbacks */ k_thread_create(&winc1500_thread_data, winc1500_stack, CONFIG_WIFI_WINC1500_THREAD_STACK_SIZE, - (k_thread_entry_t)winc1500_thread, NULL, NULL, NULL, + winc1500_thread, NULL, NULL, NULL, K_PRIO_COOP(CONFIG_WIFI_WINC1500_THREAD_PRIO), 0, K_NO_WAIT); k_thread_name_set(&winc1500_thread_data, "WINC1500"); diff --git a/drivers/xen/CMakeLists.txt b/drivers/xen/CMakeLists.txt index fe5a679fd9b..412be7d318d 100644 --- a/drivers/xen/CMakeLists.txt +++ b/drivers/xen/CMakeLists.txt @@ -1,6 +1,9 @@ # SPDX-License-Identifier: Apache-2.0 -# Copyright (c) 2021-2022 EPAM Systems +# Copyright (c) 2021-2023 EPAM Systems zephyr_sources(hvm.c) zephyr_sources(events.c) zephyr_sources_ifdef(CONFIG_XEN_GRANT_TABLE gnttab.c) +zephyr_sources(memory.c) + +add_subdirectory_ifdef(CONFIG_XEN_DOM0 dom0) diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index 547b3a7f9e7..361c71a3538 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 -# Copyright (c) 2022 EPAM Systems +# Copyright (c) 2022-2023 EPAM Systems -if SOC_XENVM +if XEN menu "Xen drivers" @@ -22,4 +22,4 @@ config XEN_GRANT_TABLE_INIT_PRIORITY endmenu -endif # SOC_XENVM +endif # XEN diff --git a/drivers/xen/dom0/CMakeLists.txt b/drivers/xen/dom0/CMakeLists.txt new file mode 100644 index 00000000000..c722beb6119 --- /dev/null +++ b/drivers/xen/dom0/CMakeLists.txt @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2023 EPAM Systems + +zephyr_sources(domctl.c) diff --git a/drivers/xen/dom0/domctl.c b/drivers/xen/dom0/domctl.c new file mode 100644 index 00000000000..2b1e3a6ca5b --- /dev/null +++ b/drivers/xen/dom0/domctl.c @@ -0,0 +1,305 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2023 EPAM Systems + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +static int do_domctl(xen_domctl_t *domctl) +{ + domctl->interface_version = XEN_DOMCTL_INTERFACE_VERSION; + return HYPERVISOR_domctl(domctl); +} + +int xen_domctl_scheduler_op(int domid, struct xen_domctl_scheduler_op *sched_op) +{ + xen_domctl_t domctl = { + .cmd = XEN_DOMCTL_scheduler_op, + .domain = domid, + .u.scheduler_op = *sched_op, + }; + + return do_domctl(&domctl); +} + +int xen_domctl_pausedomain(int domid) +{ + xen_domctl_t domctl = { + .cmd = XEN_DOMCTL_pausedomain, + .domain = domid, + }; + + return do_domctl(&domctl); +} + +int xen_domctl_unpausedomain(int domid) +{ + xen_domctl_t domctl = { + .cmd = XEN_DOMCTL_unpausedomain, + .domain = domid, + }; + + return do_domctl(&domctl); +} + +int xen_domctl_resumedomain(int domid) +{ + xen_domctl_t domctl = { + .cmd = XEN_DOMCTL_resumedomain, + .domain = domid, + }; + + return do_domctl(&domctl); +} + +int xen_domctl_getvcpucontext(int domid, int vcpu, vcpu_guest_context_t *ctxt) +{ + xen_domctl_t domctl = { + .cmd = XEN_DOMCTL_getvcpucontext, + .domain = domid, + .u.vcpucontext.vcpu = 0, + }; + + set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt); + + return do_domctl(&domctl); +} + +int xen_domctl_setvcpucontext(int domid, int vcpu, vcpu_guest_context_t *ctxt) +{ + xen_domctl_t domctl = { + .cmd = XEN_DOMCTL_setvcpucontext, + .domain = domid, + .u.vcpucontext.vcpu = 0, + }; + + set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt); + + return do_domctl(&domctl); +} + +int xen_domctl_getdomaininfo(int domid, xen_domctl_getdomaininfo_t *dom_info) +{ + int rc; + xen_domctl_t domctl = { + .cmd = XEN_DOMCTL_getdomaininfo, + .domain = domid, + }; + + rc = do_domctl(&domctl); + if (rc) { + return rc; + } + + memcpy(dom_info, &domctl.u.getdomaininfo, sizeof(*dom_info)); + + return 0; +} + +int xen_domctl_get_paging_mempool_size(int domid, uint64_t *size_mb) +{ + int rc; + xen_domctl_t domctl = { + .cmd = XEN_DOMCTL_get_paging_mempool_size, + .domain = domid, + }; + + rc = do_domctl(&domctl); + if (rc) + return rc; + + *size_mb = domctl.u.paging_mempool.size; + + return 0; +} + +int xen_domctl_set_paging_mempool_size(int domid, uint64_t size_mb) +{ + xen_domctl_t domctl = { + .cmd = XEN_DOMCTL_set_paging_mempool_size, + .domain = domid, + .u.paging_mempool.size = size_mb, + }; + + return do_domctl(&domctl); +} + +int xen_domctl_max_mem(int domid, uint64_t max_memkb) +{ + xen_domctl_t domctl = { + .cmd = XEN_DOMCTL_max_mem, + .domain = domid, + .u.max_mem.max_memkb = max_memkb, + }; + + return do_domctl(&domctl); +} + +int xen_domctl_set_address_size(int domid, int addr_size) +{ + xen_domctl_t domctl = { + .domain = domid, + .cmd = XEN_DOMCTL_set_address_size, + .u.address_size.size = addr_size, + }; + + return do_domctl(&domctl); +} + +int xen_domctl_iomem_permission(int domid, uint64_t first_mfn, + uint64_t nr_mfns, uint8_t allow_access) +{ + xen_domctl_t domctl = { + .domain = domid, + .cmd = XEN_DOMCTL_iomem_permission, + .u.iomem_permission.first_mfn = first_mfn, + .u.iomem_permission.nr_mfns = nr_mfns, + .u.iomem_permission.allow_access = allow_access, + }; + + return do_domctl(&domctl); +} + +int xen_domctl_memory_mapping(int domid, uint64_t first_gfn, uint64_t first_mfn, + uint64_t nr_mfns, uint32_t add_mapping) +{ + int ret; + uint64_t curr, nr_max, done; + xen_domctl_t domctl = { + .domain = domid, + .cmd = XEN_DOMCTL_memory_mapping, + .u.memory_mapping.add_mapping = add_mapping, + }; + + if (!nr_mfns) { + return 0; + } + + /* nr_mfns can be big and we need to handle this here */ + done = 0; + nr_max = nr_mfns; + do { + domctl.u.memory_mapping.first_gfn = first_gfn + done; + domctl.u.memory_mapping.first_mfn = first_mfn + done; + + curr = MIN(nr_mfns - done, nr_max); + domctl.u.memory_mapping.nr_mfns = curr; + + ret = do_domctl(&domctl); + if (ret < 0) { + if (ret == -E2BIG) { + /* Check if we not reach min amount */ + if (nr_max <= 1) { + break; + } + + /* Decrease amount twice and try again */ + nr_max = nr_max >> 1; + continue; + } else { + break; + } + } + + done += curr; + } while (done < nr_mfns); + + /* We may come here when get E2BIG and reach 1 at nr_max */ + if (!done) { + ret = -1; + } + + return ret; +} + +int xen_domctl_assign_dt_device(int domid, char *dtdev_path) +{ + xen_domctl_t domctl = { + .domain = domid, + .cmd = XEN_DOMCTL_assign_device, + .u.assign_device.flags = 0, + .u.assign_device.dev = XEN_DOMCTL_DEV_DT, + .u.assign_device.u.dt.size = strlen(dtdev_path), + }; + + set_xen_guest_handle(domctl.u.assign_device.u.dt.path, dtdev_path); + + return do_domctl(&domctl); + +} + +int xen_domctl_bind_pt_irq(int domid, uint32_t machine_irq, uint8_t irq_type, + uint8_t bus, uint8_t device, uint8_t intx, uint8_t isa_irq, + uint16_t spi) +{ + xen_domctl_t domctl = { + .domain = domid, + .cmd = XEN_DOMCTL_bind_pt_irq, + }; + struct xen_domctl_bind_pt_irq *bind = &(domctl.u.bind_pt_irq); + + switch (irq_type) { + case PT_IRQ_TYPE_SPI: + bind->irq_type = irq_type; + bind->machine_irq = machine_irq; + bind->u.spi.spi = spi; + break; + default: + /* TODO: implement other types */ + return -ENOTSUP; + } + + return do_domctl(&domctl); +} + +int xen_domctl_max_vcpus(int domid, int max_vcpus) +{ + xen_domctl_t domctl = { + .cmd = XEN_DOMCTL_max_vcpus, + .domain = domid, + .u.max_vcpus.max = max_vcpus, + }; + + return do_domctl(&domctl); +} + +int xen_domctl_createdomain(int domid, struct xen_domctl_createdomain *config) +{ + xen_domctl_t domctl = { + .cmd = XEN_DOMCTL_createdomain, + .domain = domid, + .u.createdomain = *config, + }; + + return do_domctl(&domctl); +} + +int xen_domctl_destroydomain(int domid) +{ + xen_domctl_t domctl = { + .cmd = XEN_DOMCTL_destroydomain, + .domain = domid, + }; + + return do_domctl(&domctl); +} + +int xen_domctl_cacheflush(int domid, struct xen_domctl_cacheflush *cacheflush) +{ + xen_domctl_t domctl = { + .cmd = XEN_DOMCTL_cacheflush, + .domain = domid, + .u.cacheflush = *cacheflush, + }; + + return do_domctl(&domctl); +} diff --git a/drivers/xen/events.c b/drivers/xen/events.c index e077b0f6cfa..a16cce8b5c5 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -47,6 +47,24 @@ int alloc_unbound_event_channel(domid_t remote_dom) return rc; } +#ifdef CONFIG_XEN_DOM0 +int alloc_unbound_event_channel_dom0(domid_t dom, domid_t remote_dom) +{ + int rc; + struct evtchn_alloc_unbound alloc = { + .dom = dom, + .remote_dom = remote_dom, + }; + + rc = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &alloc); + if (rc == 0) { + rc = alloc.port; + } + + return rc; +} +#endif /* CONFIG_XEN_DOM0 */ + int bind_interdomain_event_channel(domid_t remote_dom, evtchn_port_t remote_port, evtchn_cb_t cb, void *data) { diff --git a/drivers/xen/gnttab.c b/drivers/xen/gnttab.c index d871eb62d27..8ceb97e2db1 100644 --- a/drivers/xen/gnttab.c +++ b/drivers/xen/gnttab.c @@ -28,17 +28,24 @@ #include #include #include +#include LOG_MODULE_REGISTER(xen_gnttab); /* Timeout for grant table ops retrying */ #define GOP_RETRY_DELAY 200 +#define GNTTAB_SIZE DT_REG_SIZE_BY_IDX(DT_INST(0, xen_xen), 0) +BUILD_ASSERT(!(GNTTAB_SIZE % XEN_PAGE_SIZE), "Size of gnttab have to be aligned on XEN_PAGE_SIZE"); + /* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */ -#define NR_GRANT_FRAMES 1 +#define NR_GRANT_FRAMES (GNTTAB_SIZE / XEN_PAGE_SIZE) #define NR_GRANT_ENTRIES \ (NR_GRANT_FRAMES * XEN_PAGE_SIZE / sizeof(grant_entry_v1_t)) +BUILD_ASSERT(GNTTAB_SIZE <= CONFIG_KERNEL_VM_SIZE); +DEVICE_MMIO_TOPLEVEL_STATIC(grant_tables, DT_INST(0, xen_xen)); + static struct gnttab { struct k_sem sem; grant_entry_v1_t *table; @@ -307,15 +314,12 @@ static int gnttab_init(void) put_free_entry(gref); } - gnttab.table = (grant_entry_v1_t *) - DT_REG_ADDR_BY_IDX(DT_INST(0, xen_xen), 0); - for (i = 0; i < NR_GRANT_FRAMES; i++) { xatp.domid = DOMID_SELF; xatp.size = 0; xatp.space = XENMAPSPACE_grant_table; xatp.idx = i; - xatp.gpfn = xen_virt_to_gfn(gnttab.table) + i; + xatp.gpfn = xen_virt_to_gfn(Z_TOPLEVEL_ROM_NAME(grant_tables).phys_addr) + i; rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp); __ASSERT(!rc, "add_to_physmap failed; status = %d\n", rc); } @@ -327,6 +331,9 @@ static int gnttab_init(void) __ASSERT((!rc) && (!setup.status), "Table setup failed; status = %s\n", gnttabop_error(setup.status)); + DEVICE_MMIO_TOPLEVEL_MAP(grant_tables, K_MEM_CACHE_WB | K_MEM_PERM_RW); + gnttab.table = (grant_entry_v1_t *)DEVICE_MMIO_TOPLEVEL_GET(grant_tables); + LOG_DBG("%s: grant table mapped\n", __func__); return 0; diff --git a/drivers/xen/hvm.c b/drivers/xen/hvm.c index 67c254a8bbc..5244d34d433 100644 --- a/drivers/xen/hvm.c +++ b/drivers/xen/hvm.c @@ -11,23 +11,23 @@ #include -int hvm_set_parameter(int idx, uint64_t value) +int hvm_set_parameter(int idx, int domid, uint64_t value) { struct xen_hvm_param xhv; - xhv.domid = DOMID_SELF; + xhv.domid = domid; xhv.index = idx; xhv.value = value; return HYPERVISOR_hvm_op(HVMOP_set_param, &xhv); } -int hvm_get_parameter(int idx, uint64_t *value) +int hvm_get_parameter(int idx, int domid, uint64_t *value) { int ret = 0; struct xen_hvm_param xhv; - xhv.domid = DOMID_SELF; + xhv.domid = domid; xhv.index = idx; ret = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv); diff --git a/drivers/xen/memory.c b/drivers/xen/memory.c new file mode 100644 index 00000000000..6472ad74af2 --- /dev/null +++ b/drivers/xen/memory.c @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2023 EPAM Systems + */ + +#include +#include +#include +#include + +#include + +int xendom_add_to_physmap(int domid, unsigned long idx, + unsigned int space, xen_pfn_t gpfn) +{ + struct xen_add_to_physmap xatp = { + .domid = domid, + .idx = idx, + .space = space, + .gpfn = gpfn, + }; + + return HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp); +} + +int xendom_add_to_physmap_batch(int domid, int foreign_domid, + unsigned int space, unsigned int size, + xen_ulong_t *idxs, xen_pfn_t *gpfns, int *errs) +{ + struct xen_add_to_physmap_batch xatpb = { + .domid = domid, + .u.foreign_domid = foreign_domid, + .space = space, + .size = size, + }; + + set_xen_guest_handle(xatpb.gpfns, gpfns); + set_xen_guest_handle(xatpb.idxs, idxs); + set_xen_guest_handle(xatpb.errs, errs); + + return HYPERVISOR_memory_op(XENMEM_add_to_physmap_batch, &xatpb); +} + +int xendom_remove_from_physmap(int domid, xen_pfn_t gpfn) +{ + struct xen_remove_from_physmap xrfp = { + .domid = domid, + .gpfn = gpfn, + }; + + return HYPERVISOR_memory_op(XENMEM_remove_from_physmap, &xrfp); +} + +int xendom_populate_physmap(int domid, unsigned int extent_order, + unsigned int nr_extents, unsigned int mem_flags, + xen_pfn_t *extent_start) +{ + struct xen_memory_reservation reservation = { + .domid = domid, + .extent_order = extent_order, + .nr_extents = nr_extents, + .mem_flags = mem_flags, + }; + + set_xen_guest_handle(reservation.extent_start, extent_start); + + return HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation); +} diff --git a/dts/Kconfig b/dts/Kconfig index 46d1b85b6ec..0e71bd525c0 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -1,11 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -config HAS_DTS - bool - help - This option specifies that the target platform supports device tree - configuration. - menu "Devicetree Info" osource "$(KCONFIG_BINARY_DIR)/Kconfig.dts" diff --git a/dts/arc/synopsys/arc_iot.dtsi b/dts/arc/synopsys/arc_iot.dtsi index 1e8a67d443e..7d04321e0ee 100644 --- a/dts/arc/synopsys/arc_iot.dtsi +++ b/dts/arc/synopsys/arc_iot.dtsi @@ -76,6 +76,7 @@ compatible = "ns16550"; clock-frequency = <16000000>; reg = <0x80014000 0x100>; + io-mapped; interrupts = <86 0>; interrupt-parent = <&intc>; dlf = <0x01>; @@ -86,6 +87,7 @@ compatible = "ns16550"; clock-frequency = <16000000>; reg = <0x80014100 0x100>; + io-mapped; interrupts = <87 0>; interrupt-parent = <&intc>; reg-shift = <2>; @@ -96,6 +98,7 @@ compatible = "ns16550"; clock-frequency = <16000000>; reg = <0x80014200 0x1000>; + io-mapped; interrupts = <88 0>; interrupt-parent = <&intc>; reg-shift = <2>; @@ -106,6 +109,7 @@ compatible = "ns16550"; clock-frequency = <144000000>; reg = <0x80014300 0x100>; + io-mapped; interrupts = <89 0>; interrupt-parent = <&intc>; reg-shift = <2>; diff --git a/dts/arm/ambiq/ambiq_apollo4p.dtsi b/dts/arm/ambiq/ambiq_apollo4p.dtsi index f0d2675379f..3f722ae282f 100644 --- a/dts/arm/ambiq/ambiq_apollo4p.dtsi +++ b/dts/arm/ambiq/ambiq_apollo4p.dtsi @@ -173,6 +173,36 @@ ambiq,pwrcfg = <&pwrcfg 0x4 0x100>; }; + mspi0: spi@40060000 { + compatible = "ambiq,mspi"; + reg = <0x40060000 0x400>; + interrupts = <20 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x4 0x4000>; + }; + + mspi1: spi@40061000 { + compatible = "ambiq,mspi"; + reg = <0x40061000 0x400>; + interrupts = <21 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x4 0x8000>; + }; + + mspi2: spi@40062000 { + compatible = "ambiq,mspi"; + reg = <0x40062000 0x400>; + interrupts = <22 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x4 0x10000>; + }; + pinctrl: pin-controller@40010000 { compatible = "ambiq,apollo4-pinctrl"; reg = <0x40010000 0x800>; diff --git a/dts/arm/ambiq/ambiq_apollo4p_blue.dtsi b/dts/arm/ambiq/ambiq_apollo4p_blue.dtsi new file mode 100644 index 00000000000..65166caa335 --- /dev/null +++ b/dts/arm/ambiq/ambiq_apollo4p_blue.dtsi @@ -0,0 +1,244 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +/ { + clocks { + uartclk: apb-pclk { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + #clock-cells = <0>; + }; + xo32m: xo32m { + compatible = "ambiq,clkctrl"; + clock-frequency = ; + #clock-cells = <1>; + }; + xo32k: xo32k { + compatible = "ambiq,clkctrl"; + clock-frequency = ; + #clock-cells = <1>; + }; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-m4f"; + reg = <0>; + }; + }; + + /* TCM */ + tcm: tcm@10000000 { + compatible = "zephyr,memory-region"; + reg = <0x10000000 0x10000>; + zephyr,memory-region = "ITCM"; + }; + + /* SRAM */ + sram0: memory@10010000 { + compatible = "mmio-sram"; + reg = <0x10010000 0x2B0000>; + }; + + soc { + flash: flash-controller@18000 { + compatible = "ambiq,flash-controller"; + reg = <0x00018000 0x1e8000>; + + #address-cells = <1>; + #size-cells = <1>; + + /* MRAM region */ + flash0: flash@18000 { + compatible = "soc-nv-flash"; + reg = <0x00018000 0x1e8000>; + }; + }; + + pwrcfg: pwrcfg@40021000 { + compatible = "ambiq,pwrctrl"; + reg = <0x40021000 0x400>; + #pwrcfg-cells = <2>; + }; + + stimer0: stimer@40008800 { + compatible = "ambiq,stimer"; + reg = <0x40008800 0x80>; + interrupts = <32 0>; + status = "okay"; + }; + + counter0: counter@40008000 { + compatible = "ambiq,counter"; + reg = <0x40008000 0x80>; + interrupts = <67 0>; + status = "disabled"; + }; + + uart0: uart@4001c000 { + compatible = "ambiq,uart", "arm,pl011"; + reg = <0x4001c000 0x1000>; + interrupts = <15 0>; + interrupt-names = "UART0"; + status = "disabled"; + clocks = <&uartclk>; + ambiq,pwrcfg = <&pwrcfg 0x4 0x200>; + }; + uart1: uart@4001d000 { + compatible = "ambiq,uart", "arm,pl011"; + reg = <0x4001d000 0x1000>; + interrupts = <16 0>; + interrupt-names = "UART1"; + status = "disabled"; + clocks = <&uartclk>; + ambiq,pwrcfg = <&pwrcfg 0x4 0x400>; + }; + + uart2: uart@4001e000 { + compatible = "ambiq,uart", "arm,pl011"; + reg = <0x4001e000 0x1000>; + interrupts = <17 0>; + interrupt-names = "UART2"; + status = "disabled"; + clocks = <&uartclk>; + ambiq,pwrcfg = <&pwrcfg 0x4 0x800>; + }; + + uart3: uart@4001f000 { + compatible = "ambiq,uart", "arm,pl011"; + reg = <0x4001f000 0x1000>; + interrupts = <18 0>; + interrupt-names = "UART3"; + status = "disabled"; + clocks = <&uartclk>; + ambiq,pwrcfg = <&pwrcfg 0x4 0x1000>; + }; + + iom0: iom@40050000 { + reg = <0x40050000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <6 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x4 0x2>; + }; + + iom1: iom@40051000 { + reg = <0x40051000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <7 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x4 0x4>; + }; + + iom2: iom@40052000 { + reg = <0x40052000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <8 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x4 0x8>; + }; + + iom3: iom@40053000 { + reg = <0x40053000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <9 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x4 0x10>; + }; + + iom4: iom@40054000 { + reg = <0x40054000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <10 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x4 0x20>; + }; + + iom5: iom@40055000 { + reg = <0x40055000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <11 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x4 0x40>; + }; + + iom6: iom@40056000 { + reg = <0x40056000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <12 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x4 0x80>; + }; + + iom7: iom@40057000 { + reg = <0x40057000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <13 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x4 0x100>; + }; + + mspi0: spi@40060000 { + compatible = "ambiq,mspi"; + reg = <0x40060000 0x400>; + interrupts = <20 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x4 0x4000>; + }; + + mspi1: spi@40061000 { + compatible = "ambiq,mspi"; + reg = <0x40061000 0x400>; + interrupts = <21 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x4 0x8000>; + }; + + mspi2: spi@40062000 { + compatible = "ambiq,mspi"; + reg = <0x40062000 0x400>; + interrupts = <22 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x4 0x10000>; + }; + + pinctrl: pin-controller@40010000 { + compatible = "ambiq,apollo4-pinctrl"; + reg = <0x40010000 0x800>; + }; + + wdt0: watchdog@40024000 { + compatible = "ambiq,watchdog"; + reg = <0x40024000 0x400>; + interrupts = <1 0>; + clock-frequency = <16>; + status = "disabled"; + }; + + }; +}; + +&nvic { + arm,num-irq-priority-bits = <3>; +}; diff --git a/dts/arm/atmel/sam3x.dtsi b/dts/arm/atmel/sam3x.dtsi index f9dc33e458a..1fc5dbe9733 100644 --- a/dts/arm/atmel/sam3x.dtsi +++ b/dts/arm/atmel/sam3x.dtsi @@ -37,6 +37,13 @@ status = "okay"; }; + supc: supc@400e1a10 { + compatible = "atmel,sam-supc"; + reg = <0x400e1a10 0x20>; + #wakeup-source-id-cells = <1>; + status = "okay"; + }; + sram0: memory@20070000 { compatible = "mmio-sram"; reg = <0x20070000 0x18000>; @@ -246,6 +253,15 @@ clocks = <&pmc PMC_TYPE_PERIPHERAL 1>; user-nrst; }; + + rtc: rtc@400e1a60 { + compatible = "atmel,sam-rtc"; + reg = <0x400e1a60 0x100>; + interrupts = <2 0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 2>; + alarms-count = <1>; + status = "disabled"; + }; }; }; diff --git a/dts/arm/atmel/sam4e.dtsi b/dts/arm/atmel/sam4e.dtsi index 6aaf079e821..2e9e916eef2 100644 --- a/dts/arm/atmel/sam4e.dtsi +++ b/dts/arm/atmel/sam4e.dtsi @@ -47,6 +47,13 @@ status = "okay"; }; + supc: supc@400e1810 { + compatible = "atmel,sam-supc"; + reg = <0x400e1810 0x20>; + #wakeup-source-id-cells = <1>; + status = "okay"; + }; + sram0: memory@20000000 { compatible = "mmio-sram"; }; @@ -171,7 +178,10 @@ mdio: mdio@40034000 { compatible = "atmel,sam-mdio"; reg = <0x40034000 0x4000>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 44>; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; pinctrl: pinctrl@400e0e00 { @@ -294,6 +304,22 @@ clocks = <&pmc PMC_TYPE_PERIPHERAL 8>; status = "disabled"; }; + + hsmci: hsmci@40080000 { + compatible = "atmel,sam-hsmci"; + reg = <0x40080000 0x1000>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 16>; + status = "disabled"; + }; + + rtc: rtc@400e1860 { + compatible = "atmel,sam-rtc"; + reg = <0x400e1860 0x100>; + interrupts = <2 0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 2>; + alarms-count = <1>; + status = "disabled"; + }; }; }; diff --git a/dts/arm/atmel/sam4s.dtsi b/dts/arm/atmel/sam4s.dtsi index bbbc05e8f7f..8c7cf1acc2a 100644 --- a/dts/arm/atmel/sam4s.dtsi +++ b/dts/arm/atmel/sam4s.dtsi @@ -49,6 +49,13 @@ status = "okay"; }; + supc: supc@400e1410 { + compatible = "atmel,sam-supc"; + reg = <0x400e1410 0x20>; + #wakeup-source-id-cells = <1>; + status = "okay"; + }; + sram0: memory@20100000 { compatible = "mmio-sram"; }; @@ -240,6 +247,15 @@ clocks = <&pmc PMC_TYPE_PERIPHERAL 10>; status = "disabled"; }; + + rtc: rtc@400e1460 { + compatible = "atmel,sam-rtc"; + reg = <0x400e1460 0x100>; + interrupts = <2 0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 2>; + alarms-count = <1>; + status = "disabled"; + }; }; }; diff --git a/dts/arm/atmel/samc20x15.dtsi b/dts/arm/atmel/samc20x15.dtsi deleted file mode 100644 index fc1b141dab2..00000000000 --- a/dts/arm/atmel/samc20x15.dtsi +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2019 Gerson Fernando Budke - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -/ { - sram0: memory@20000000 { - reg = <0x20000000 DT_SIZE_K(4)>; - }; - - soc { - nvmctrl: nvmctrl@41004000 { - flash0: flash@0 { - reg = <0 DT_SIZE_K(32)>; - }; - }; - }; -}; diff --git a/dts/arm/atmel/samc20x16.dtsi b/dts/arm/atmel/samc20x16.dtsi deleted file mode 100644 index 8bffaf72078..00000000000 --- a/dts/arm/atmel/samc20x16.dtsi +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2019 Gerson Fernando Budke - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -/ { - sram0: memory@20000000 { - reg = <0x20000000 DT_SIZE_K(8)>; - }; - - soc { - nvmctrl: nvmctrl@41004000 { - flash0: flash@0 { - reg = <0 DT_SIZE_K(64)>; - }; - }; - }; -}; diff --git a/dts/arm/atmel/samc20x17.dtsi b/dts/arm/atmel/samc20x17.dtsi deleted file mode 100644 index 2149e2b5898..00000000000 --- a/dts/arm/atmel/samc20x17.dtsi +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2019 Gerson Fernando Budke - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -/ { - sram0: memory@20000000 { - reg = <0x20000000 DT_SIZE_K(16)>; - }; - - soc { - nvmctrl: nvmctrl@41004000 { - flash0: flash@0 { - reg = <0 DT_SIZE_K(128)>; - }; - }; - }; -}; diff --git a/dts/arm/atmel/samc20x18.dtsi b/dts/arm/atmel/samc20x18.dtsi deleted file mode 100644 index d819ae2492e..00000000000 --- a/dts/arm/atmel/samc20x18.dtsi +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2019 Gerson Fernando Budke - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -/ { - sram0: memory@20000000 { - reg = <0x20000000 DT_SIZE_K(32)>; - }; - - soc { - nvmctrl: nvmctrl@41004000 { - flash0: flash@0 { - reg = <0 DT_SIZE_K(256)>; - }; - }; - }; -}; diff --git a/dts/arm/atmel/samc21.dtsi b/dts/arm/atmel/samc21.dtsi index 63421dbdb63..d3cdfbda777 100644 --- a/dts/arm/atmel/samc21.dtsi +++ b/dts/arm/atmel/samc21.dtsi @@ -53,9 +53,7 @@ clock-names = "GCLK", "MCLK"; bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>; divider = <12>; - sjw = <1>; sample-point = <875>; - sjw-data = <1>; sample-point-data = <875>; status = "disabled"; }; @@ -69,9 +67,7 @@ clock-names = "GCLK", "MCLK"; bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>; divider = <12>; - sjw = <1>; sample-point = <875>; - sjw-data = <1>; sample-point-data = <875>; status = "disabled"; }; diff --git a/dts/arm/atmel/samc21x15.dtsi b/dts/arm/atmel/samc21x15.dtsi deleted file mode 100644 index 0e4ef466428..00000000000 --- a/dts/arm/atmel/samc21x15.dtsi +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2019 Gerson Fernando Budke - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -/ { - sram0: memory@20000000 { - reg = <0x20000000 DT_SIZE_K(4)>; - }; - - soc { - nvmctrl: nvmctrl@41004000 { - flash0: flash@0 { - reg = <0 DT_SIZE_K(32)>; - }; - }; - }; -}; diff --git a/dts/arm/atmel/samc21x16.dtsi b/dts/arm/atmel/samc21x16.dtsi deleted file mode 100644 index 7f66c19dbb3..00000000000 --- a/dts/arm/atmel/samc21x16.dtsi +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2019 Gerson Fernando Budke - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -/ { - sram0: memory@20000000 { - reg = <0x20000000 DT_SIZE_K(8)>; - }; - - soc { - nvmctrl: nvmctrl@41004000 { - flash0: flash@0 { - reg = <0 DT_SIZE_K(64)>; - }; - }; - }; -}; diff --git a/dts/arm/atmel/samc21x17.dtsi b/dts/arm/atmel/samc21x17.dtsi deleted file mode 100644 index b09568beb1b..00000000000 --- a/dts/arm/atmel/samc21x17.dtsi +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2019 Gerson Fernando Budke - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -/ { - sram0: memory@20000000 { - reg = <0x20000000 DT_SIZE_K(16)>; - }; - - soc { - nvmctrl: nvmctrl@41004000 { - flash0: flash@0 { - reg = <0 DT_SIZE_K(128)>; - }; - }; - }; -}; diff --git a/dts/arm/atmel/samc21x18.dtsi b/dts/arm/atmel/samc21x18.dtsi deleted file mode 100644 index 353c2d23253..00000000000 --- a/dts/arm/atmel/samc21x18.dtsi +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2019 Gerson Fernando Budke - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -/ { - sram0: memory@20000000 { - reg = <0x20000000 DT_SIZE_K(32)>; - }; - - soc { - nvmctrl: nvmctrl@41004000 { - flash0: flash@0 { - reg = <0 DT_SIZE_K(256)>; - }; - }; - }; -}; diff --git a/dts/arm/atmel/samd2x.dtsi b/dts/arm/atmel/samd2x.dtsi index feae5b3ccb9..c247daffc1a 100644 --- a/dts/arm/atmel/samd2x.dtsi +++ b/dts/arm/atmel/samd2x.dtsi @@ -33,7 +33,6 @@ sram0: memory@20000000 { compatible = "mmio-sram"; - reg = <0x20000000 0x8000>; }; id: device_id@80a00c { @@ -71,7 +70,6 @@ flash0: flash@0 { compatible = "soc-nv-flash"; - reg = <0 0x40000>; write-block-size = <4>; }; }; diff --git a/dts/arm/atmel/same5x.dtsi b/dts/arm/atmel/same5x.dtsi index 341d6e9d1ad..1d11fa32c97 100644 --- a/dts/arm/atmel/same5x.dtsi +++ b/dts/arm/atmel/same5x.dtsi @@ -22,6 +22,8 @@ compatible = "atmel,sam-mdio"; reg = <0x42000800 0x400>; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; }; }; diff --git a/dts/arm/atmel/same70.dtsi b/dts/arm/atmel/same70.dtsi index cd021e8a3bd..8c378d90d0d 100644 --- a/dts/arm/atmel/same70.dtsi +++ b/dts/arm/atmel/same70.dtsi @@ -57,6 +57,13 @@ status = "okay"; }; + supc: supc@400e1810 { + compatible = "atmel,sam-supc"; + reg = <0x400e1810 0x20>; + #wakeup-source-id-cells = <1>; + status = "okay"; + }; + eefc: flash-controller@400e0c00 { compatible = "atmel,sam-flash-controller"; reg = <0x400e0c00 0x200>; @@ -333,7 +340,10 @@ mdio: mdio@40050000 { compatible = "atmel,sam-mdio"; reg = <0x40050000 0x4000>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 39>; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; tc0: tc@4000c000 { @@ -417,9 +427,7 @@ clocks = <&pmc PMC_TYPE_PERIPHERAL 35>; divider = <6>; bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>; - sjw = <1>; sample-point = <875>; - sjw-data = <1>; sample-point-data = <875>; status = "disabled"; }; @@ -432,9 +440,7 @@ clocks = <&pmc PMC_TYPE_PERIPHERAL 37>; divider = <6>; bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>; - sjw = <1>; sample-point = <875>; - sjw-data = <1>; sample-point-data = <875>; status = "disabled"; }; @@ -445,6 +451,15 @@ clocks = <&pmc PMC_TYPE_PERIPHERAL 1>; user-nrst; }; + + rtc: rtc@400e1860 { + compatible = "atmel,sam-rtc"; + reg = <0x400e1860 0x100>; + interrupts = <2 0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 2>; + alarms-count = <1>; + status = "disabled"; + }; }; }; diff --git a/dts/arm/atmel/samx2xx14.dtsi b/dts/arm/atmel/samx2xx14.dtsi new file mode 100644 index 00000000000..8e345dda9a5 --- /dev/null +++ b/dts/arm/atmel/samx2xx14.dtsi @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023, Meta Platforms, Inc. and its affiliates. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&sram0 { + reg = <0x20000000 DT_SIZE_K(2)>; +}; + +&flash0 { + reg = <0 DT_SIZE_K(16)>; +}; diff --git a/dts/arm/atmel/samx2xx15.dtsi b/dts/arm/atmel/samx2xx15.dtsi new file mode 100644 index 00000000000..88bfa454b14 --- /dev/null +++ b/dts/arm/atmel/samx2xx15.dtsi @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023, Meta Platforms, Inc. and its affiliates. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&sram0 { + reg = <0x20000000 DT_SIZE_K(4)>; +}; + +&flash0 { + reg = <0 DT_SIZE_K(32)>; +}; diff --git a/dts/arm/atmel/samx2xx16.dtsi b/dts/arm/atmel/samx2xx16.dtsi new file mode 100644 index 00000000000..484c06315ce --- /dev/null +++ b/dts/arm/atmel/samx2xx16.dtsi @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023, Meta Platforms, Inc. and its affiliates. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&sram0 { + reg = <0x20000000 DT_SIZE_K(8)>; +}; + +&flash0 { + reg = <0 DT_SIZE_K(64)>; +}; diff --git a/dts/arm/atmel/samx2xx17.dtsi b/dts/arm/atmel/samx2xx17.dtsi new file mode 100644 index 00000000000..19b8b2607cf --- /dev/null +++ b/dts/arm/atmel/samx2xx17.dtsi @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023, Meta Platforms, Inc. and its affiliates. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&sram0 { + reg = <0x20000000 DT_SIZE_K(16)>; +}; + +&flash0 { + reg = <0 DT_SIZE_K(128)>; +}; diff --git a/dts/arm/atmel/samx2xx18.dtsi b/dts/arm/atmel/samx2xx18.dtsi new file mode 100644 index 00000000000..2abbffa6ee7 --- /dev/null +++ b/dts/arm/atmel/samx2xx18.dtsi @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023, Meta Platforms, Inc. and its affiliates. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&sram0 { + reg = <0x20000000 DT_SIZE_K(32)>; +}; + +&flash0 { + reg = <0 DT_SIZE_K(256)>; +}; diff --git a/dts/arm/cypress/psoc6.dtsi b/dts/arm/cypress/psoc6.dtsi index 4fc63f4b46f..a6ab61e9949 100644 --- a/dts/arm/cypress/psoc6.dtsi +++ b/dts/arm/cypress/psoc6.dtsi @@ -71,164 +71,164 @@ #address-cells = <1>; #size-cells = <1>; ranges = <0x40310000 0x40310000 0x2024>; + }; - hsiom: hsiom@40310000 { - compatible = "cypress,psoc6-hsiom"; - reg = <0x40310000 0x2024>; - interrupts = <15 1>, <16 1>; - status = "disabled"; - }; + hsiom: hsiom@40310000 { + compatible = "cypress,psoc6-hsiom"; + reg = <0x40310000 0x2024>; + interrupts = <15 1>, <16 1>; + status = "disabled"; + }; - gpio_prt0: gpio@40320000 { - compatible = "cypress,psoc6-gpio"; - reg = <0x40320000 0x80>; - interrupts = <0 1>; - gpio-controller; - ngpios = <6>; - #gpio-cells = <2>; - #cypress,pin-cells = <2>; - status = "disabled"; - }; - gpio_prt1: gpio@40320080 { - compatible = "cypress,psoc6-gpio"; - reg = <0x40320080 0x80>; - interrupts = <1 1>; - gpio-controller; - ngpios = <6>; - #gpio-cells = <2>; - #cypress,pin-cells = <2>; - status = "disabled"; - }; - gpio_prt2: gpio@40320100 { - compatible = "cypress,psoc6-gpio"; - reg = <0x40320100 0x80>; - interrupts = <2 1>; - gpio-controller; - ngpios = <8>; - #gpio-cells = <2>; - #cypress,pin-cells = <2>; - status = "disabled"; - }; - gpio_prt3: gpio@40320180 { - compatible = "cypress,psoc6-gpio"; - reg = <0x40320180 0x80>; - interrupts = <3 1>; - gpio-controller; - ngpios = <6>; - #gpio-cells = <2>; - #cypress,pin-cells = <2>; - status = "disabled"; - }; - gpio_prt4: gpio@40320200 { - compatible = "cypress,psoc6-gpio"; - reg = <0x40320200 0x80>; - interrupts = <4 1>; - gpio-controller; - ngpios = <4>; - #gpio-cells = <2>; - #cypress,pin-cells = <2>; - status = "disabled"; - }; - gpio_prt5: gpio@40320280 { - compatible = "cypress,psoc6-gpio"; - reg = <0x40320280 0x80>; - interrupts = <5 1>; - gpio-controller; - ngpios = <8>; - #gpio-cells = <2>; - #cypress,pin-cells = <2>; - status = "disabled"; - }; - gpio_prt6: gpio@40320300 { - compatible = "cypress,psoc6-gpio"; - reg = <0x40320300 0x80>; - interrupts = <6 1>; - gpio-controller; - ngpios = <8>; - #gpio-cells = <2>; - #cypress,pin-cells = <2>; - status = "disabled"; - }; - gpio_prt7: gpio@40320380 { - compatible = "cypress,psoc6-gpio"; - reg = <0x40320380 0x80>; - interrupts = <7 1>; - gpio-controller; - ngpios = <8>; - #gpio-cells = <2>; - #cypress,pin-cells = <2>; - status = "disabled"; - }; - gpio_prt8: gpio@40320400 { - compatible = "cypress,psoc6-gpio"; - reg = <0x40320400 0x80>; - interrupts = <8 1>; - gpio-controller; - ngpios = <8>; - #gpio-cells = <2>; - #cypress,pin-cells = <2>; - status = "disabled"; - }; - gpio_prt9: gpio@40320480 { - compatible = "cypress,psoc6-gpio"; - reg = <0x40320480 0x80>; - interrupts = <9 1>; - gpio-controller; - ngpios = <8>; - #gpio-cells = <2>; - #cypress,pin-cells = <2>; - status = "disabled"; - }; - gpio_prt10: gpio@40320500 { - compatible = "cypress,psoc6-gpio"; - reg = <0x40320500 0x80>; - interrupts = <10 1>; - gpio-controller; - ngpios = <8>; - #gpio-cells = <2>; - #cypress,pin-cells = <2>; - status = "disabled"; - }; - gpio_prt11: gpio@40320580 { - compatible = "cypress,psoc6-gpio"; - reg = <0x40320580 0x80>; - interrupts = <11 1>; - gpio-controller; - ngpios = <8>; - #gpio-cells = <2>; - #cypress,pin-cells = <2>; - status = "disabled"; - }; - gpio_prt12: gpio@40320600 { - compatible = "cypress,psoc6-gpio"; - reg = <0x40320600 0x80>; - interrupts = <12 1>; - gpio-controller; - ngpios = <8>; - #gpio-cells = <2>; - #cypress,pin-cells = <2>; - status = "disabled"; - }; - gpio_prt13: gpio@40320680 { - compatible = "cypress,psoc6-gpio"; - reg = <0x40320680 0x80>; - interrupts = <13 1>; - gpio-controller; - ngpios = <8>; - #gpio-cells = <2>; - #cypress,pin-cells = <2>; - status = "disabled"; - }; - gpio_prt14: gpio@40320700 { - compatible = "cypress,psoc6-gpio"; - reg = <0x40320700 0x80>; - interrupts = <14 1>; - gpio-controller; - ngpios = <2>; - #gpio-cells = <2>; - #cypress,pin-cells = <2>; - status = "disabled"; - }; + gpio_prt0: gpio@40320000 { + compatible = "cypress,psoc6-gpio"; + reg = <0x40320000 0x80>; + interrupts = <0 1>; + gpio-controller; + ngpios = <6>; + #gpio-cells = <2>; + #cypress,pin-cells = <2>; + status = "disabled"; + }; + gpio_prt1: gpio@40320080 { + compatible = "cypress,psoc6-gpio"; + reg = <0x40320080 0x80>; + interrupts = <1 1>; + gpio-controller; + ngpios = <6>; + #gpio-cells = <2>; + #cypress,pin-cells = <2>; + status = "disabled"; + }; + gpio_prt2: gpio@40320100 { + compatible = "cypress,psoc6-gpio"; + reg = <0x40320100 0x80>; + interrupts = <2 1>; + gpio-controller; + ngpios = <8>; + #gpio-cells = <2>; + #cypress,pin-cells = <2>; + status = "disabled"; + }; + gpio_prt3: gpio@40320180 { + compatible = "cypress,psoc6-gpio"; + reg = <0x40320180 0x80>; + interrupts = <3 1>; + gpio-controller; + ngpios = <6>; + #gpio-cells = <2>; + #cypress,pin-cells = <2>; + status = "disabled"; + }; + gpio_prt4: gpio@40320200 { + compatible = "cypress,psoc6-gpio"; + reg = <0x40320200 0x80>; + interrupts = <4 1>; + gpio-controller; + ngpios = <4>; + #gpio-cells = <2>; + #cypress,pin-cells = <2>; + status = "disabled"; + }; + gpio_prt5: gpio@40320280 { + compatible = "cypress,psoc6-gpio"; + reg = <0x40320280 0x80>; + interrupts = <5 1>; + gpio-controller; + ngpios = <8>; + #gpio-cells = <2>; + #cypress,pin-cells = <2>; + status = "disabled"; + }; + gpio_prt6: gpio@40320300 { + compatible = "cypress,psoc6-gpio"; + reg = <0x40320300 0x80>; + interrupts = <6 1>; + gpio-controller; + ngpios = <8>; + #gpio-cells = <2>; + #cypress,pin-cells = <2>; + status = "disabled"; + }; + gpio_prt7: gpio@40320380 { + compatible = "cypress,psoc6-gpio"; + reg = <0x40320380 0x80>; + interrupts = <7 1>; + gpio-controller; + ngpios = <8>; + #gpio-cells = <2>; + #cypress,pin-cells = <2>; + status = "disabled"; + }; + gpio_prt8: gpio@40320400 { + compatible = "cypress,psoc6-gpio"; + reg = <0x40320400 0x80>; + interrupts = <8 1>; + gpio-controller; + ngpios = <8>; + #gpio-cells = <2>; + #cypress,pin-cells = <2>; + status = "disabled"; + }; + gpio_prt9: gpio@40320480 { + compatible = "cypress,psoc6-gpio"; + reg = <0x40320480 0x80>; + interrupts = <9 1>; + gpio-controller; + ngpios = <8>; + #gpio-cells = <2>; + #cypress,pin-cells = <2>; + status = "disabled"; + }; + gpio_prt10: gpio@40320500 { + compatible = "cypress,psoc6-gpio"; + reg = <0x40320500 0x80>; + interrupts = <10 1>; + gpio-controller; + ngpios = <8>; + #gpio-cells = <2>; + #cypress,pin-cells = <2>; + status = "disabled"; + }; + gpio_prt11: gpio@40320580 { + compatible = "cypress,psoc6-gpio"; + reg = <0x40320580 0x80>; + interrupts = <11 1>; + gpio-controller; + ngpios = <8>; + #gpio-cells = <2>; + #cypress,pin-cells = <2>; + status = "disabled"; + }; + gpio_prt12: gpio@40320600 { + compatible = "cypress,psoc6-gpio"; + reg = <0x40320600 0x80>; + interrupts = <12 1>; + gpio-controller; + ngpios = <8>; + #gpio-cells = <2>; + #cypress,pin-cells = <2>; + status = "disabled"; + }; + gpio_prt13: gpio@40320680 { + compatible = "cypress,psoc6-gpio"; + reg = <0x40320680 0x80>; + interrupts = <13 1>; + gpio-controller; + ngpios = <8>; + #gpio-cells = <2>; + #cypress,pin-cells = <2>; + status = "disabled"; + }; + gpio_prt14: gpio@40320700 { + compatible = "cypress,psoc6-gpio"; + reg = <0x40320700 0x80>; + interrupts = <14 1>; + gpio-controller; + ngpios = <2>; + #gpio-cells = <2>; + #cypress,pin-cells = <2>; + status = "disabled"; }; spi0: spi@40610000 { diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.dtsi b/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.dtsi index 0a97178cfad..56957dddab0 100644 --- a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.dtsi +++ b/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.dtsi @@ -55,150 +55,151 @@ reg = <0x40310000 0x20000>; #address-cells = <1>; #size-cells = <0>; + }; - hsiom: hsiom@40310000 { - compatible = "infineon,cat1-hsiom"; - reg = <0x40310000 0x4000>; - interrupts = <15 6>, <16 6>; - status = "disabled"; - }; + hsiom: hsiom@40310000 { + compatible = "infineon,cat1-hsiom"; + reg = <0x40310000 0x4000>; + interrupts = <15 6>, <16 6>; + status = "disabled"; + }; - gpio_prt0: gpio@40320000 { - compatible = "infineon,cat1-gpio"; - reg = <0x40320000 0x80>; - interrupts = <0 6>; - gpio-controller; - ngpios = <6>; - status = "disabled"; - #gpio-cells = <2>; - }; - gpio_prt1: gpio@40320080 { - compatible = "infineon,cat1-gpio"; - reg = <0x40320080 0x80>; - interrupts = <1 6>; - gpio-controller; - ngpios = <6>; - status = "disabled"; - #gpio-cells = <2>; - }; - gpio_prt2: gpio@40320100 { - compatible = "infineon,cat1-gpio"; - reg = <0x40320100 0x80>; - interrupts = <2 6>; - gpio-controller; - ngpios = <8>; - status = "disabled"; - #gpio-cells = <2>; - }; - gpio_prt3: gpio@40320180 { - compatible = "infineon,cat1-gpio"; - reg = <0x40320180 0x80>; - interrupts = <3 6>; - gpio-controller; - ngpios = <6>; - status = "disabled"; - #gpio-cells = <2>; - }; - gpio_prt4: gpio@40320200 { - compatible = "infineon,cat1-gpio"; - reg = <0x40320200 0x80>; - interrupts = <4 6>; - gpio-controller; - ngpios = <2>; - status = "disabled"; - #gpio-cells = <2>; - }; - gpio_prt5: gpio@40320280 { - compatible = "infineon,cat1-gpio"; - reg = <0x40320280 0x80>; - interrupts = <5 6>; - gpio-controller; - ngpios = <8>; - status = "disabled"; - #gpio-cells = <2>; - }; - gpio_prt6: gpio@40320300 { - compatible = "infineon,cat1-gpio"; - reg = <0x40320300 0x80>; - interrupts = <6 6>; - gpio-controller; - ngpios = <8>; - status = "disabled"; - #gpio-cells = <2>; - }; - gpio_prt7: gpio@40320380 { - compatible = "infineon,cat1-gpio"; - reg = <0x40320380 0x80>; - interrupts = <7 6>; - gpio-controller; - ngpios = <8>; - status = "disabled"; - #gpio-cells = <2>; - }; - gpio_prt8: gpio@40320400 { - compatible = "infineon,cat1-gpio"; - reg = <0x40320400 0x80>; - interrupts = <8 6>; - gpio-controller; - ngpios = <8>; - status = "disabled"; - #gpio-cells = <2>; - }; - gpio_prt9: gpio@40320480 { - compatible = "infineon,cat1-gpio"; - reg = <0x40320480 0x80>; - interrupts = <9 6>; - gpio-controller; - ngpios = <8>; - status = "disabled"; - #gpio-cells = <2>; - }; - gpio_prt10: gpio@40320500 { - compatible = "infineon,cat1-gpio"; - reg = <0x40320500 0x80>; - interrupts = <10 6>; - gpio-controller; - ngpios = <8>; - status = "disabled"; - #gpio-cells = <2>; - }; - gpio_prt11: gpio@40320580 { - compatible = "infineon,cat1-gpio"; - reg = <0x40320580 0x80>; - interrupts = <11 6>; - gpio-controller; - ngpios = <8>; - status = "disabled"; - #gpio-cells = <2>; - }; - gpio_prt12: gpio@40320600 { - compatible = "infineon,cat1-gpio"; - reg = <0x40320600 0x80>; - interrupts = <12 6>; - gpio-controller; - ngpios = <8>; - status = "disabled"; - #gpio-cells = <2>; - }; - gpio_prt13: gpio@40320680 { - compatible = "infineon,cat1-gpio"; - reg = <0x40320680 0x80>; - interrupts = <13 6>; - gpio-controller; - ngpios = <8>; - status = "disabled"; - #gpio-cells = <2>; - }; - gpio_prt14: gpio@40320700 { - compatible = "infineon,cat1-gpio"; - reg = <0x40320700 0x80>; - interrupts = <14 6>; - gpio-controller; - ngpios = <2>; - status = "disabled"; - #gpio-cells = <2>; - }; + gpio_prt0: gpio@40320000 { + compatible = "infineon,cat1-gpio"; + reg = <0x40320000 0x80>; + interrupts = <0 6>; + gpio-controller; + ngpios = <6>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt1: gpio@40320080 { + compatible = "infineon,cat1-gpio"; + reg = <0x40320080 0x80>; + interrupts = <1 6>; + gpio-controller; + ngpios = <6>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt2: gpio@40320100 { + compatible = "infineon,cat1-gpio"; + reg = <0x40320100 0x80>; + interrupts = <2 6>; + gpio-controller; + ngpios = <8>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt3: gpio@40320180 { + compatible = "infineon,cat1-gpio"; + reg = <0x40320180 0x80>; + interrupts = <3 6>; + gpio-controller; + ngpios = <6>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt4: gpio@40320200 { + compatible = "infineon,cat1-gpio"; + reg = <0x40320200 0x80>; + interrupts = <4 6>; + gpio-controller; + ngpios = <2>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt5: gpio@40320280 { + compatible = "infineon,cat1-gpio"; + reg = <0x40320280 0x80>; + interrupts = <5 6>; + gpio-controller; + ngpios = <8>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt6: gpio@40320300 { + compatible = "infineon,cat1-gpio"; + reg = <0x40320300 0x80>; + interrupts = <6 6>; + gpio-controller; + ngpios = <8>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt7: gpio@40320380 { + compatible = "infineon,cat1-gpio"; + reg = <0x40320380 0x80>; + interrupts = <7 6>; + gpio-controller; + ngpios = <8>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt8: gpio@40320400 { + compatible = "infineon,cat1-gpio"; + reg = <0x40320400 0x80>; + interrupts = <8 6>; + gpio-controller; + ngpios = <8>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt9: gpio@40320480 { + compatible = "infineon,cat1-gpio"; + reg = <0x40320480 0x80>; + interrupts = <9 6>; + gpio-controller; + ngpios = <8>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt10: gpio@40320500 { + compatible = "infineon,cat1-gpio"; + reg = <0x40320500 0x80>; + interrupts = <10 6>; + gpio-controller; + ngpios = <8>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt11: gpio@40320580 { + compatible = "infineon,cat1-gpio"; + reg = <0x40320580 0x80>; + interrupts = <11 6>; + gpio-controller; + ngpios = <8>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt12: gpio@40320600 { + compatible = "infineon,cat1-gpio"; + reg = <0x40320600 0x80>; + interrupts = <12 6>; + gpio-controller; + ngpios = <8>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt13: gpio@40320680 { + compatible = "infineon,cat1-gpio"; + reg = <0x40320680 0x80>; + interrupts = <13 6>; + gpio-controller; + ngpios = <8>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt14: gpio@40320700 { + compatible = "infineon,cat1-gpio"; + reg = <0x40320700 0x80>; + interrupts = <14 6>; + gpio-controller; + ngpios = <2>; + status = "disabled"; + #gpio-cells = <2>; }; + uid: device_uid@16000600 { compatible = "infineon,cat1-uid"; reg = <0x16000600 0xb>; @@ -536,5 +537,12 @@ resolution = <16>; status = "disabled"; }; + + sdhc0: sdhc@40460000 { + compatible = "infineon,cat1-sdhc-sdio"; + reg = <0x40460000 0x2000>; + interrupts = <164 6>; + status = "disabled"; + }; }; }; diff --git a/dts/arm/infineon/psoc6/psoc6_02/psoc6_02.dtsi b/dts/arm/infineon/psoc6/psoc6_02/psoc6_02.dtsi index a4109291dfd..c61ba9e0ca4 100644 --- a/dts/arm/infineon/psoc6/psoc6_02/psoc6_02.dtsi +++ b/dts/arm/infineon/psoc6/psoc6_02/psoc6_02.dtsi @@ -541,5 +541,12 @@ resolution = <16>; status = "disabled"; }; + + sdhc0: sdhc@40460000 { + compatible = "infineon,cat1-sdhc-sdio"; + reg = <0x40460000 0x2000>; + interrupts = <164 6>; + status = "disabled"; + }; }; }; diff --git a/dts/arm/infineon/psoc6/psoc6_03/psoc6_03.dtsi b/dts/arm/infineon/psoc6/psoc6_03/psoc6_03.dtsi index 8e8ada040d2..14aefdc5ada 100644 --- a/dts/arm/infineon/psoc6/psoc6_03/psoc6_03.dtsi +++ b/dts/arm/infineon/psoc6/psoc6_03/psoc6_03.dtsi @@ -241,6 +241,12 @@ interrupts = <18 6>; status = "disabled"; }; + sdhc0: sdhc@40460000 { + compatible = "infineon,cat1-sdhc-sdio"; + reg = <0x40460000 0x2000>; + interrupts = <164 6>; + status = "disabled"; + }; }; }; diff --git a/dts/arm/infineon/psoc6/psoc6_04/psoc6_04.dtsi b/dts/arm/infineon/psoc6/psoc6_04/psoc6_04.dtsi index 73282624e3f..d44b0583f70 100644 --- a/dts/arm/infineon/psoc6/psoc6_04/psoc6_04.dtsi +++ b/dts/arm/infineon/psoc6/psoc6_04/psoc6_04.dtsi @@ -247,6 +247,12 @@ interrupts = <18 6>; status = "disabled"; }; + sdhc0: sdhc@40460000 { + compatible = "infineon,cat1-sdhc-sdio"; + reg = <0x40460000 0x2000>; + interrupts = <164 6>; + status = "disabled"; + }; }; }; diff --git a/dts/arm/infineon/xmc4500_F100x1024.dtsi b/dts/arm/infineon/xmc4500_F100x1024.dtsi index a085ce5816d..8a84230511d 100644 --- a/dts/arm/infineon/xmc4500_F100x1024.dtsi +++ b/dts/arm/infineon/xmc4500_F100x1024.dtsi @@ -9,7 +9,6 @@ #include / { - /* TODO: Add psram1 & dsram2 to MEMORY layout of linker */ psram1: memory@10000000 { compatible = "mmio-sram"; reg = <0x10000000 DT_SIZE_K(64)>; diff --git a/dts/arm/infineon/xmc4xxx.dtsi b/dts/arm/infineon/xmc4xxx.dtsi index 54a5744be15..82845683fc6 100644 --- a/dts/arm/infineon/xmc4xxx.dtsi +++ b/dts/arm/infineon/xmc4xxx.dtsi @@ -229,6 +229,13 @@ #pwm-cells = <3>; status = "disabled"; }; + + wdt0: watchdog@50008000 { + compatible = "infineon,xmc4xxx-watchdog"; + reg = <0x50008000 0x4000>; + interrupts = <0 1>; + status = "disabled"; + }; }; }; diff --git a/dts/arm/microchip/mec152x/mec152xhsz-pinctrl.dtsi b/dts/arm/microchip/mec152x/mec152xhsz-pinctrl.dtsi index c86a7cc519b..b5614be1969 100644 --- a/dts/arm/microchip/mec152x/mec152xhsz-pinctrl.dtsi +++ b/dts/arm/microchip/mec152x/mec152xhsz-pinctrl.dtsi @@ -1092,65 +1092,212 @@ /* PWM */ pwm0_gpio053_sleep: pwm0_gpio053_sleep { pinmux = < MCHP_XEC_PINMUX(053, MCHP_AF1) >; + low-power-enable; }; pwm0_alt_gpio241_sleep: pwm0_alt_gpio241_sleep { pinmux = < MCHP_XEC_PINMUX(0241, MCHP_AF1) >; + low-power-enable; }; pwm1_gpio054_sleep: pwm1_gpio054_sleep { pinmux = < MCHP_XEC_PINMUX(054, MCHP_AF1) >; + low-power-enable; }; pwm1_alt_gpio254_sleep: pwm1_alt_gpio254_sleep { pinmux = < MCHP_XEC_PINMUX(0254, MCHP_AF1) >; + low-power-enable; }; pwm2_gpio055_sleep: pwm2_gpio055_sleep { pinmux = < MCHP_XEC_PINMUX(055, MCHP_AF1) >; + low-power-enable; }; pwm2_alt_gpio045_sleep: pwm2_alt_gpio045_sleep { pinmux = < MCHP_XEC_PINMUX(045, MCHP_AF2) >; + low-power-enable; }; pwm3_gpio056_sleep: pwm3_gpio056_sleep { pinmux = < MCHP_XEC_PINMUX(056, MCHP_AF1) >; + low-power-enable; }; pwm3_alt_gpio047_sleep: pwm3_alt_gpio047_sleep { pinmux = < MCHP_XEC_PINMUX(047, MCHP_AF2) >; + low-power-enable; }; pwm4_gpio011_sleep: pwm4_gpio011_sleep { pinmux = < MCHP_XEC_PINMUX(011, MCHP_AF2) >; + low-power-enable; }; pwm5_gpio002_sleep: pwm5_gpio002_sleep { pinmux = < MCHP_XEC_PINMUX(02, MCHP_AF1) >; + low-power-enable; }; pwm6_gpio014_sleep: pwm6_gpio014_sleep { pinmux = < MCHP_XEC_PINMUX(014, MCHP_AF1) >; + low-power-enable; }; pwm6_alt_gpio063_sleep: pwm6_alt_gpio063_sleep { pinmux = < MCHP_XEC_PINMUX(063, MCHP_AF2) >; + low-power-enable; }; pwm7_gpio015_sleep: pwm7_gpio015_sleep { pinmux = < MCHP_XEC_PINMUX(015, MCHP_AF1) >; + low-power-enable; }; pwm7_alt_gpio061_sleep: pwm7_alt_gpio061_sleep { pinmux = < MCHP_XEC_PINMUX(061, MCHP_AF2) >; + low-power-enable; }; pwm8_gpio035_sleep: pwm8_gpio035_sleep { pinmux = < MCHP_XEC_PINMUX(035, MCHP_AF1) >; + low-power-enable; }; pwm8_alt_gpio175_sleep: pwm8_alt_gpio175_sleep { pinmux = < MCHP_XEC_PINMUX(0175, MCHP_AF3) >; + low-power-enable; + }; + + /* Keyscan */ + ksi0_gpio017_sleep: ksi0_gpio017_sleep { + pinmux = < MCHP_XEC_PINMUX(017, MCHP_AF1) >; + low-power-enable; + }; + + ksi1_gpio020_sleep: ksi1_gpio020_sleep { + pinmux = < MCHP_XEC_PINMUX(020, MCHP_AF1) >; + low-power-enable; + }; + + ksi2_gpio021_sleep: ksi2_gpio021_sleep { + pinmux = < MCHP_XEC_PINMUX(021, MCHP_AF1) >; + low-power-enable; + }; + + ksi3_gpio026_sleep: ksi3_gpio026_sleep { + pinmux = < MCHP_XEC_PINMUX(026, MCHP_AF1) >; + low-power-enable; + }; + + ksi4_gpio027_sleep: ksi4_gpio027_sleep { + pinmux = < MCHP_XEC_PINMUX(027, MCHP_AF1) >; + low-power-enable; + }; + + ksi5_gpio030_sleep: ksi5_gpio030_sleep { + pinmux = < MCHP_XEC_PINMUX(030, MCHP_AF1) >; + low-power-enable; + }; + + ksi6_gpio031_sleep: ksi6_gpio031_sleep { + pinmux = < MCHP_XEC_PINMUX(031, MCHP_AF1) >; + low-power-enable; + }; + + ksi7_gpio032_sleep: ksi7_gpio032_sleep { + pinmux = < MCHP_XEC_PINMUX(032, MCHP_AF1) >; + low-power-enable; + }; + + kso00_gpio040_sleep: kso00_gpio040_sleep { + pinmux = < MCHP_XEC_PINMUX(040, MCHP_AF2) >; + low-power-enable; + }; + + kso01_gpio045_sleep: kso01_gpio045_sleep { + pinmux = < MCHP_XEC_PINMUX(045, MCHP_AF1) >; + low-power-enable; + }; + + kso02_gpio046_sleep: kso02_gpio046_sleep { + pinmux = < MCHP_XEC_PINMUX(046, MCHP_AF1) >; + low-power-enable; + }; + + kso03_gpio047_sleep: kso03_gpio047_sleep { + pinmux = < MCHP_XEC_PINMUX(047, MCHP_AF1) >; + low-power-enable; + }; + + kso04_gpio107_sleep: kso04_gpio107_sleep { + pinmux = < MCHP_XEC_PINMUX(0107, MCHP_AF2) >; + low-power-enable; + }; + + kso05_gpio112_sleep: kso05_gpio112_sleep { + pinmux = < MCHP_XEC_PINMUX(0112, MCHP_AF1) >; + low-power-enable; + }; + + kso06_gpio113_sleep: kso06_gpio113_sleep { + pinmux = < MCHP_XEC_PINMUX(0113, MCHP_AF1) >; + low-power-enable; + }; + + kso07_gpio120_sleep: kso07_gpio120_sleep { + pinmux = < MCHP_XEC_PINMUX(0120, MCHP_AF1) >; + low-power-enable; + }; + + kso08_gpio121_sleep: kso08_gpio121_sleep { + pinmux = < MCHP_XEC_PINMUX(0121, MCHP_AF2) >; + low-power-enable; + }; + + kso09_gpio122_sleep: kso09_gpio122_sleep { + pinmux = < MCHP_XEC_PINMUX(0122, MCHP_AF2) >; + low-power-enable; + }; + + kso10_gpio123_sleep: kso10_gpio123_sleep { + pinmux = < MCHP_XEC_PINMUX(0123, MCHP_AF2) >; + low-power-enable; + }; + + kso11_gpio124_sleep: kso11_gpio124_sleep { + pinmux = < MCHP_XEC_PINMUX(0124, MCHP_AF2) >; + low-power-enable; + }; + + kso12_gpio125_sleep: kso12_gpio125_sleep { + pinmux = < MCHP_XEC_PINMUX(0125, MCHP_AF2) >; + low-power-enable; + }; + + kso13_gpio126_sleep: kso13_gpio126_sleep { + pinmux = < MCHP_XEC_PINMUX(0126, MCHP_AF2) >; + low-power-enable; + }; + + kso14_gpio152_sleep: kso14_gpio152_sleep { + pinmux = < MCHP_XEC_PINMUX(0152, MCHP_AF1) >; + low-power-enable; + }; + + kso15_gpio151_sleep: kso15_gpio151_sleep { + pinmux = < MCHP_XEC_PINMUX(0151, MCHP_AF2) >; + low-power-enable; + }; + + kso16_gpio132_sleep: kso16_gpio132_sleep { + pinmux = < MCHP_XEC_PINMUX(0132, MCHP_AF2) >; + low-power-enable; + }; + + kso17_gpio140_sleep: kso17_gpio140_sleep { + pinmux = < MCHP_XEC_PINMUX(0140, MCHP_AF3) >; + low-power-enable; }; /* EEPROM */ diff --git a/dts/arm/microchip/mec1727nsz.dtsi b/dts/arm/microchip/mec1727nsz.dtsi index 565e5f9ff45..a7484a335bb 100644 --- a/dts/arm/microchip/mec1727nsz.dtsi +++ b/dts/arm/microchip/mec1727nsz.dtsi @@ -11,14 +11,55 @@ #include #include -#include "mec172xnsz.dtsi" #include "mec172x/mec172x-vw-routing.dtsi" -#include "mec172x/mec172xnsz-pinctrl.dtsi" + +#include +#include / { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m4"; + reg = <0>; + cpu-power-states = <&idle &suspend_to_ram>; + }; + + power-states { + idle: idle { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + min-residency-us = <1000000>; + }; + + suspend_to_ram: suspend_to_ram { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-ram"; + min-residency-us = <2000000>; + }; + }; + }; + + flash0: flash@c0000 { + reg = <0x000C0000 0x58000>; + }; + flash1: flash@60000000 { reg = <0x60000000 0x80000>; }; + + sram0: memory@118000 { + compatible = "mmio-sram"; + reg = <0x00118000 0x10000>; + }; + + soc { + #include "mec172x_common.dtsi" + }; + }; &spi0 { @@ -44,6 +85,16 @@ }; }; +&nvic { + arm,num-irq-priority-bits = <3>; +}; + +&systick { + status = "disabled"; +}; + +#include "mec172x/mec172xnsz-pinctrl.dtsi" + &gpspi_wp_n_gpio076 { output-high; }; diff --git a/dts/arm/microchip/mec172x/mec172xnlj-pinctrl.dtsi b/dts/arm/microchip/mec172x/mec172xnlj-pinctrl.dtsi index ac5b43a67a3..47502d289c6 100644 --- a/dts/arm/microchip/mec172x/mec172xnlj-pinctrl.dtsi +++ b/dts/arm/microchip/mec172x/mec172xnlj-pinctrl.dtsi @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include "mec172xnsz-pinctrl.dtsi" &pinctrl { diff --git a/dts/arm/microchip/mec172x/mec172xnsz-pinctrl.dtsi b/dts/arm/microchip/mec172x/mec172xnsz-pinctrl.dtsi index 9b4d3047a51..fc79cf357fa 100644 --- a/dts/arm/microchip/mec172x/mec172xnsz-pinctrl.dtsi +++ b/dts/arm/microchip/mec172x/mec172xnsz-pinctrl.dtsi @@ -1214,4 +1214,134 @@ low-power-enable; }; + /* Keyscan */ + ksi0_gpio017_sleep: ksi0_gpio017_sleep { + pinmux = < MCHP_XEC_PINMUX(017, MCHP_AF1) >; + low-power-enable; + }; + + ksi1_gpio020_sleep: ksi1_gpio020_sleep { + pinmux = < MCHP_XEC_PINMUX(020, MCHP_AF1) >; + low-power-enable; + }; + + ksi2_gpio021_sleep: ksi2_gpio021_sleep { + pinmux = < MCHP_XEC_PINMUX(021, MCHP_AF1) >; + low-power-enable; + }; + + ksi3_gpio026_sleep: ksi3_gpio026_sleep { + pinmux = < MCHP_XEC_PINMUX(026, MCHP_AF1) >; + low-power-enable; + }; + + ksi4_gpio027_sleep: ksi4_gpio027_sleep { + pinmux = < MCHP_XEC_PINMUX(027, MCHP_AF1) >; + low-power-enable; + }; + + ksi5_gpio030_sleep: ksi5_gpio030_sleep { + pinmux = < MCHP_XEC_PINMUX(030, MCHP_AF1) >; + low-power-enable; + }; + + ksi6_gpio031_sleep: ksi6_gpio031_sleep { + pinmux = < MCHP_XEC_PINMUX(031, MCHP_AF1) >; + low-power-enable; + }; + + ksi7_gpio032_sleep: ksi7_gpio032_sleep { + pinmux = < MCHP_XEC_PINMUX(032, MCHP_AF1) >; + low-power-enable; + }; + + kso00_gpio040_sleep: kso00_gpio040_sleep { + pinmux = < MCHP_XEC_PINMUX(040, MCHP_AF2) >; + low-power-enable; + }; + + kso01_gpio045_sleep: kso01_gpio045_sleep { + pinmux = < MCHP_XEC_PINMUX(045, MCHP_AF1) >; + low-power-enable; + }; + + kso02_gpio046_sleep: kso02_gpio046_sleep { + pinmux = < MCHP_XEC_PINMUX(046, MCHP_AF1) >; + low-power-enable; + }; + + kso03_gpio047_sleep: kso03_gpio047_sleep { + pinmux = < MCHP_XEC_PINMUX(047, MCHP_AF1) >; + low-power-enable; + }; + + kso04_gpio107_sleep: kso04_gpio107_sleep { + pinmux = < MCHP_XEC_PINMUX(0107, MCHP_AF2) >; + low-power-enable; + }; + + kso05_gpio112_sleep: kso05_gpio112_sleep { + pinmux = < MCHP_XEC_PINMUX(0112, MCHP_AF1) >; + low-power-enable; + }; + + kso06_gpio113_sleep: kso06_gpio113_sleep { + pinmux = < MCHP_XEC_PINMUX(0113, MCHP_AF1) >; + low-power-enable; + }; + + kso07_gpio120_sleep: kso07_gpio120_sleep { + pinmux = < MCHP_XEC_PINMUX(0120, MCHP_AF1) >; + low-power-enable; + }; + + kso08_gpio121_sleep: kso08_gpio121_sleep { + pinmux = < MCHP_XEC_PINMUX(0121, MCHP_AF2) >; + low-power-enable; + }; + + kso09_gpio122_sleep: kso09_gpio122_sleep { + pinmux = < MCHP_XEC_PINMUX(0122, MCHP_AF2) >; + low-power-enable; + }; + + kso10_gpio123_sleep: kso10_gpio123_sleep { + pinmux = < MCHP_XEC_PINMUX(0123, MCHP_AF2) >; + low-power-enable; + }; + + kso11_gpio124_sleep: kso11_gpio124_sleep { + pinmux = < MCHP_XEC_PINMUX(0124, MCHP_AF2) >; + low-power-enable; + }; + + kso12_gpio125_sleep: kso12_gpio125_sleep { + pinmux = < MCHP_XEC_PINMUX(0125, MCHP_AF2) >; + low-power-enable; + }; + + kso13_gpio126_sleep: kso13_gpio126_sleep { + pinmux = < MCHP_XEC_PINMUX(0126, MCHP_AF2) >; + low-power-enable; + }; + + kso14_gpio152_sleep: kso14_gpio152_sleep { + pinmux = < MCHP_XEC_PINMUX(0152, MCHP_AF1) >; + low-power-enable; + }; + + kso15_gpio151_sleep: kso15_gpio151_sleep { + pinmux = < MCHP_XEC_PINMUX(0151, MCHP_AF2) >; + low-power-enable; + }; + + kso16_gpio132_sleep: kso16_gpio132_sleep { + pinmux = < MCHP_XEC_PINMUX(0132, MCHP_AF2) >; + low-power-enable; + }; + + kso17_gpio140_sleep: kso17_gpio140_sleep { + pinmux = < MCHP_XEC_PINMUX(0140, MCHP_AF3) >; + low-power-enable; + }; }; diff --git a/dts/arm/microchip/mec172x_common.dtsi b/dts/arm/microchip/mec172x_common.dtsi new file mode 100644 index 00000000000..03a6a00fb4f --- /dev/null +++ b/dts/arm/microchip/mec172x_common.dtsi @@ -0,0 +1,1001 @@ +/* + * Copyright (c) 2021 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +ecs: ecs@4000fc00 { + reg = <0x4000fc00 0x200>; +}; +pcr: pcr@40080100 { + compatible = "microchip,xec-pcr"; + reg = <0x40080100 0x100 0x4000a400 0x100>; + reg-names = "pcrr", "vbatr"; + interrupts = <174 0>; + core-clock-div = <1>; + /* MEC172x allows sources to be different */ + pll-32k-src = ; + periph-32k-src = ; + clk32kmon-period-min = <1435>; + clk32kmon-period-max = <1495>; + clk32kmon-duty-cycle-var-max = <132>; + clk32kmon-valid-min = <4>; + xtal-enable-delay-ms = <300>; + pll-lock-timeout-ms = <30>; + /* pin configured only if one of the sources is set to PIN */ + pinctrl-0 = <&clk_32khz_in_gpio165>; + pinctrl-names = "default"; + #clock-cells = <3>; +}; +ecia: ecia@4000e000 { + compatible = "microchip,xec-ecia"; + reg = <0x4000e000 0x400>; + direct-capable-girqs = <13 14 15 16 17 18 19 20 21 23>; + clocks = <&pcr 1 0 MCHP_XEC_PCR_CLK_PERIPH>; + #address-cells = <1>; + #size-cells = <1>; + + ranges = <0x0 0x4000e000 0x400>; + + girq8: girq8@0 { + compatible = "microchip,xec-ecia-girq"; + reg = <0x0 0x14>; + interrupts = <0 0>; + girq-id = <0>; + sources = <0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 21 22 24 25 + 26 27 28 29>; + status = "disabled"; + }; + girq9: girq9@14 { + compatible = "microchip,xec-ecia-girq"; + reg = <0x14 0x14>; + interrupts = <1 0>; + girq-id = <1>; + sources = <0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29>; + status = "disabled"; + }; + girq10: girq10@28 { + compatible = "microchip,xec-ecia-girq"; + reg = <0x28 0x14>; + interrupts = <2 0>; + girq-id = <2>; + sources = <0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30>; + status = "disabled"; + }; + girq11: girq11@3c { + compatible = "microchip,xec-ecia-girq"; + reg = <0x3c 0x14>; + interrupts = <3 0>; + girq-id = <3>; + sources = <0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30>; + status = "disabled"; + }; + girq12: girq12@50 { + compatible = "microchip,xec-ecia-girq"; + reg = <0x50 0x14>; + interrupts = <4 0>; + girq-id = <4>; + sources = <0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30>; + status = "disabled"; + }; + girq13: girq13@64 { + compatible = "microchip,xec-ecia-girq"; + reg = <0x64 0x14>; + interrupts = <5 0>; + girq-id = <5>; + sources = <0 1 2 3 4>; + status = "disabled"; + }; + girq14: girq14@78 { + compatible = "microchip,xec-ecia-girq"; + reg = <0x78 0x14>; + interrupts = <6 0>; + girq-id = <6>; + sources = <0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15>; + status = "disabled"; + }; + girq15: girq15@8c { + compatible = "microchip,xec-ecia-girq"; + reg = <0x8c 0x14>; + interrupts = <7 0>; + girq-id = <7>; + sources = <0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 22>; + status = "disabled"; + }; + girq16: girq16@a0 { + compatible = "microchip,xec-ecia-girq"; + reg = <0xa0 0x14>; + interrupts = <8 0>; + girq-id = <8>; + sources = <0 2 3>; + status = "disabled"; + }; + girq17: girq17@b4 { + compatible = "microchip,xec-ecia-girq"; + reg = <0xb4 0x14>; + interrupts = <9 0>; + girq-id = <9>; + sources = <0 1 2 3 4 8 9 10 11 12 13 14 15 + 16 17 20 21 22 23>; + status = "disabled"; + }; + girq18: girq18@c8 { + compatible = "microchip,xec-ecia-girq"; + reg = <0xc8 0x14>; + interrupts = <10 0>; + girq-id = <10>; + sources = <0 1 2 3 4 5 6 7 + 10 20 21 22 23 + 24 25 26 27 28>; + status = "disabled"; + }; + girq19: girq19@dc { + compatible = "microchip,xec-ecia-girq"; + reg = <0xdc 0x14>; + interrupts = <11 0>; + girq-id = <11>; + sources = <0 1 2 3 4 5 6 7 8 9 10>; + status = "disabled"; + }; + girq20: girq20@f0 { + compatible = "microchip,xec-ecia-girq"; + reg = <0xf0 0x14>; + interrupts = <12 0>; + girq-id = <12>; + sources = <3 9>; + status = "disabled"; + }; + girq21: girq21@104 { + compatible = "microchip,xec-ecia-girq"; + reg = <0x104 0x14>; + interrupts = <13 0>; + girq-id = <13>; + sources = <2 3 4 5 6 7 8 9 10 11 12 13 14 15 + 18 19 25 26>; + status = "disabled"; + }; + girq22: girq22@118 { + compatible = "microchip,xec-ecia-girq"; + reg = <0x118 0x14>; + interrupts = <255 0>; + girq-id = <14>; + sources = <0 1 2 3 4 5 9 15>; + status = "disabled"; + }; + girq23: girq23@12c { + compatible = "microchip,xec-ecia-girq"; + reg = <0x12c 0x14>; + interrupts = <14 0>; + girq-id = <15>; + sources = <0 1 2 3 4 5 6 7 8 9 10 16 17>; + status = "disabled"; + }; + girq24: girq24@140 { + compatible = "microchip,xec-ecia-girq"; + reg = <0x140 0x14>; + interrupts = <15 0>; + girq-id = <16>; + sources = <0 1 2 3 4 5 6 7 8 9 10 11 + 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27>; + status = "disabled"; + }; + girq25: girq25@154 { + compatible = "microchip,xec-ecia-girq"; + reg = <0x154 0x14>; + interrupts = <16 0>; + girq-id = <17>; + sources = <0 1 2 3 4 5 6 7 8 9 10 11 + 12 13 14 15>; + status = "disabled"; + }; + girq26: girq26@168 { + compatible = "microchip,xec-ecia-girq"; + reg = <0x168 0x14>; + interrupts = <17 0>; + girq-id = <18>; + sources = <0 1 2 3 4 5 6 12 13>; + status = "disabled"; + }; +}; +pinctrl: pin-controller@40081000 { + compatible = "microchip,xec-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x40081000 0x1000>; + + gpio_000_036: gpio@40081000 { + compatible = "microchip,xec-gpio-v2"; + reg = < 0x40081000 0x80 0x40081300 0x04 + 0x40081380 0x04 0x400813fc 0x04>; + interrupts = <3 2>; + gpio-controller; + port-id = <0>; + girq-id = <11>; + #gpio-cells=<2>; + }; + gpio_040_076: gpio@40081080 { + compatible = "microchip,xec-gpio-v2"; + reg = < 0x40081080 0x80 0x40081304 0x04 + 0x40081384 0x04 0x400813f8 0x4>; + interrupts = <2 2>; + gpio-controller; + port-id = <1>; + girq-id = <10>; + #gpio-cells=<2>; + }; + gpio_100_136: gpio@40081100 { + compatible = "microchip,xec-gpio-v2"; + reg = < 0x40081100 0x80 0x40081308 0x04 + 0x40081388 0x04 0x400813f4 0x04>; + gpio-controller; + interrupts = <1 2>; + port-id = <2>; + girq-id = <9>; + #gpio-cells=<2>; + }; + gpio_140_176: gpio@40081180 { + compatible = "microchip,xec-gpio-v2"; + reg = < 0x40081180 0x80 0x4008130c 0x04 + 0x4008138c 0x04 0x400813f0 0x04>; + gpio-controller; + interrupts = <0 2>; + port-id = <3>; + girq-id = <8>; + #gpio-cells=<2>; + }; + gpio_200_236: gpio@40081200 { + compatible = "microchip,xec-gpio-v2"; + reg = < 0x40081200 0x80 0x40081310 0x04 + 0x40081390 0x04 0x400813ec 0x04>; + gpio-controller; + interrupts = <4 2>; + port-id = <4>; + girq-id = <12>; + #gpio-cells=<2>; + }; + gpio_240_276: gpio@40081280 { + compatible = "microchip,xec-gpio-v2"; + reg = < 0x40081280 0x80 0x40081314 0x04 + 0x40081394 0x04 0x400813e8 0x04>; + gpio-controller; + interrupts = <17 2>; + port-id = <5>; + girq-id = <26>; + #gpio-cells=<2>; + }; +}; +wdog: watchdog@40000400 { + compatible = "microchip,xec-watchdog"; + reg = <0x40000400 0x400>; + interrupts = <171 0>; + girqs = <21 2>; + pcrs = <1 9>; +}; +rtimer: timer@40007400 { + compatible = "microchip,xec-rtos-timer"; + reg = <0x40007400 0x10>; + interrupts = <111 0>; + girqs = <23 10>; +}; +timer0: timer@40000c00 { + compatible = "microchip,xec-timer"; + clock-frequency = <48000000>; + reg = <0x40000c00 0x20>; + interrupts = <136 0>; + girqs = <23 0>; + pcrs = <1 30>; + max-value = <0xFFFF>; + prescaler = <0>; + status = "disabled"; +}; +timer1: timer@40000c20 { + compatible = "microchip,xec-timer"; + clock-frequency = <48000000>; + reg = <0x40000c20 0x20>; + interrupts = <137 0>; + girqs = <23 1>; + pcrs = <1 31>; + max-value = <0xFFFF>; + prescaler = <0>; + status = "disabled"; +}; +timer2: timer@40000c40 { + compatible = "microchip,xec-timer"; + clock-frequency = <48000000>; + reg = <0x40000c40 0x20>; + interrupts = <138 0>; + girqs = <23 2>; + pcrs = <3 21>; + max-value = <0xFFFF>; + prescaler = <0>; + status = "disabled"; +}; +timer3: timer@40000c60 { + compatible = "microchip,xec-timer"; + clock-frequency = <48000000>; + reg = <0x40000c60 0x20>; + interrupts = <139 0>; + girqs = <23 3>; + pcrs = <3 22>; + max-value = <0xFFFF>; + prescaler = <0>; + status = "disabled"; +}; +/* + * NOTE: When RTOS timer used as kernel timer, timer4 used + * to provide high speed busy wait counter. Keep disabled to + * prevent counter driver from claiming it. + */ +timer4: timer@40000c80 { + compatible = "microchip,xec-timer"; + clock-frequency = <48000000>; + reg = <0x40000c80 0x20>; + interrupts = <140 0>; + girqs = <23 4>; + pcrs = <3 23>; + max-value = <0xFFFFFFFF>; + prescaler = <0>; + status = "disabled"; +}; +timer5: timer@40000ca0 { + compatible = "microchip,xec-timer"; + clock-frequency = <48000000>; + reg = <0x40000ca0 0x20>; + interrupts = <141 0>; + girqs = <23 5>; + pcrs = <3 24>; + max-value = <0xFFFFFFFF>; + prescaler = <0>; + status = "disabled"; +}; +cntr0: timer@40000d00 { + reg = <0x40000d00 0x20>; + interrupts = <142 0>; + girqs = <23 6>; + pcrs = <4 2>; + status = "disabled"; +}; +cntr1: timer@40000d20 { + reg = <0x40000d20 0x20>; + interrupts = <143 0>; + girqs = <23 7>; + pcrs = <4 3>; + status = "disabled"; +}; +cntr2: timer@40000d40 { + reg = <0x40000d40 0x20>; + interrupts = <144 0>; + girqs = <23 8>; + pcrs = <4 3>; + status = "disabled"; +}; +cntr3: timer@40000d60 { + reg = <0x40000d60 0x20>; + interrupts = <145 0>; + girqs = <23 9>; + pcrs = <4 4>; + status = "disabled"; +}; +cctmr0: timer@40001000 { + reg = <0x40001000 0x40>; + interrupts = <146 0>, <147 0>, <148 0>, <149 0>, + <150 0>, <151 0>, <152 0>, <153 0>, + <154 0>; + girqs = <18 20>, <18 21>, <18 22>, <18 23>, <18 24>, + <18 25>, <18 26>, <18 27>, <18 28>; + pcrs = <3 30>; + status = "disabled"; +}; +hibtimer0: timer@40009800 { + reg = <0x40009800 0x20>; + interrupts = <112 0>; + girqs = <23 16>; +}; +hibtimer1: timer@40009820 { + reg = <0x40009820 0x20>; + interrupts = <113 0>; + girqs = <23 17>; +}; +weektmr0: timer@4000ac80 { + reg = <0x4000ac80 0x80>; + interrupts = <114 0>, <115 0>, <116 0>, + <117 0>, <118 0>; + girqs = <21 3>, <21 4>, <21 5>, <21 6>, <21 7>; + status = "disabled"; +}; +bbram: bb-ram@4000a800 { + compatible = "microchip,xec-bbram"; + reg = <0x4000a800 0x100>; + reg-names = "memory"; +}; +vci0: vci@4000ae00 { + reg = <0x4000ae00 0x40>; + interrupts = <121 0>, <122 0>, <123 0>, + <124 0>, <125 0>; + girqs = <21 10>, <21 11>, <21 12>, <21 13>, <21 14>; + status = "disabled"; +}; +dmac: dmac@40002400 { + compatible = "microchip,xec-dmac"; + reg = <0x40002400 0xc00>; + interrupts = <24 1>, <25 1>, <26 1>, <27 1>, + <28 1>, <29 1>, <30 1>, <31 1>, + <32 1>, <33 1>, <34 1>, <35 1>, + <36 1>, <37 1>, <38 1>, <39 1>; + girqs = < MCHP_XEC_ECIA(14, 0, 6, 24) + MCHP_XEC_ECIA(14, 1, 6, 25) + MCHP_XEC_ECIA(14, 2, 6, 26) + MCHP_XEC_ECIA(14, 3, 6, 27) + MCHP_XEC_ECIA(14, 4, 6, 28) + MCHP_XEC_ECIA(14, 5, 6, 29) + MCHP_XEC_ECIA(14, 6, 6, 30) + MCHP_XEC_ECIA(14, 7, 6, 31) + MCHP_XEC_ECIA(14, 8, 6, 32) + MCHP_XEC_ECIA(14, 9, 6, 33) + MCHP_XEC_ECIA(14, 10, 6, 34) + MCHP_XEC_ECIA(14, 11, 6, 35) + MCHP_XEC_ECIA(14, 12, 6, 36) + MCHP_XEC_ECIA(14, 13, 6, 37) + MCHP_XEC_ECIA(14, 14, 6, 38) + MCHP_XEC_ECIA(14, 15, 6, 39) >; + pcrs = <1 6>; + #dma-cells = <2>; + dma-channels = <16>; + dma-requests = <16>; + status = "disabled"; +}; +i2c_smb_0: i2c@40004000 { + compatible = "microchip,xec-i2c-v2"; + reg = <0x40004000 0x80>; + clock-frequency = ; + interrupts = <20 1>; + girqs = <13 0>; + pcrs = <1 10>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; +}; +i2c_smb_1: i2c@40004400 { + compatible = "microchip,xec-i2c-v2"; + reg = <0x40004400 0x80>; + clock-frequency = ; + interrupts = <21 1>; + girqs = <13 1>; + pcrs = <3 13>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; +}; +i2c_smb_2: i2c@40004800 { + compatible = "microchip,xec-i2c-v2"; + reg = <0x40004800 0x80>; + clock-frequency = ; + interrupts = <22 1>; + girqs = <13 2>; + pcrs = <3 14>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; +}; +i2c_smb_3: i2c@40004c00 { + compatible = "microchip,xec-i2c-v2"; + reg = <0x40004C00 0x80>; + clock-frequency = ; + interrupts = <23 1>; + girqs = <13 3>; + pcrs = <3 15>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; +}; +i2c_smb_4: i2c@40005000 { + compatible = "microchip,xec-i2c-v2"; + reg = <0x40005000 0x80>; + clock-frequency = ; + interrupts = <158 1>; + girqs = <13 4>; + pcrs = <3 20>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; +}; +ps2_0: ps2@40009000 { + compatible = "microchip,xec-ps2"; + reg = <0x40009000 0x40>; + interrupts = <100 1>; + girqs = <18 10>, <21 18>; + pcrs = <3 5>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; +}; +pwm0: pwm@40005800 { + compatible = "microchip,xec-pwm"; + reg = <0x40005800 0x20>; + pcrs = <1 4>; + status = "disabled"; + #pwm-cells = <3>; +}; +pwm1: pwm@40005810 { + compatible = "microchip,xec-pwm"; + reg = <0x40005810 0x20>; + pcrs = <1 20>; + status = "disabled"; + #pwm-cells = <3>; +}; +pwm2: pwm@40005820 { + compatible = "microchip,xec-pwm"; + reg = <0x40005820 0x20>; + pcrs = <1 21>; + status = "disabled"; + #pwm-cells = <3>; +}; +pwm3: pwm@40005830 { + compatible = "microchip,xec-pwm"; + reg = <0x40005830 0x20>; + pcrs = <1 22>; + status = "disabled"; + #pwm-cells = <3>; +}; +pwm4: pwm@40005840 { + compatible = "microchip,xec-pwm"; + reg = <0x40005840 0x20>; + pcrs = <1 23>; + status = "disabled"; + #pwm-cells = <3>; +}; +pwm5: pwm@40005850 { + compatible = "microchip,xec-pwm"; + reg = <0x40005850 0x20>; + pcrs = <1 24>; + status = "disabled"; + #pwm-cells = <3>; +}; +pwm6: pwm@40005860 { + compatible = "microchip,xec-pwm"; + reg = <0x40005860 0x20>; + pcrs = <1 25>; + status = "disabled"; + #pwm-cells = <3>; +}; +pwm7: pwm@40005870 { + compatible = "microchip,xec-pwm"; + reg = <0x40005870 0x20>; + pcrs = <1 26>; + status = "disabled"; + #pwm-cells = <3>; +}; +pwm8: pwm@40005880 { + compatible = "microchip,xec-pwm"; + reg = <0x40005880 0x20>; + pcrs = <1 27>; + status = "disabled"; + #pwm-cells = <3>; +}; +tach0: tach@40006000 { + compatible = "microchip,xec-tach"; + reg = <0x40006000 0x10>; + interrupts = <71 4>; + girqs = <17 1>; + pcrs = <1 2>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; +}; +tach1: tach@40006010 { + compatible = "microchip,xec-tach"; + reg = <0x40006010 0x10>; + interrupts = <72 4>; + girqs = <17 2>; + pcrs = <1 11>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; +}; +tach2: tach@40006020 { + compatible = "microchip,xec-tach"; + reg = <0x40006020 0x10>; + interrupts = <73 4>; + girqs = <17 3>; + pcrs = <1 12>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; +}; +tach3: tach@40006030 { + compatible = "microchip,xec-tach"; + reg = <0x40006030 0x10>; + interrupts = <159 4>; + girqs = <17 4>; + pcrs = <1 13>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; +}; +rpmfan0: rpmfan@4000a000 { + reg = <0x4000a000 0x80>; + interrupts = <74 1>, <75 1>; + girqs = <17 20>, <17 21>; + pcrs = <3 12>; + status = "disabled"; +}; +rpmfan1: rpmfan@4000a080 { + reg = <0x4000a080 0x80>; + interrupts = <76 1>, <77 1>; + girqs = <17 22>, <17 23>; + pcrs = <4 7>; + status = "disabled"; +}; +adc0: adc@40007c00 { + compatible = "microchip,xec-adc"; + reg = <0x40007c00 0x90>; + interrupts = <78 0>, <79 0>; + girqs = <17 8>, <17 9>; + pcrs = <3 3>; + status = "disabled"; + #io-channel-cells = <1>; + clktime = <32>; +}; +kscan0: kscan@40009c00 { + compatible = "microchip,xec-kscan"; + reg = <0x40009c00 0x18>; + interrupts = <135 0>; + girqs = <21 25>; + pcrs = <3 11>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; +}; +peci0: peci@40006400 { + compatible = "microchip,xec-peci"; + reg = <0x40006400 0x80>; + interrupts = <70 4>; + girqs = <17 0>; + pcrs = <1 1>; + #address-cells = <1>; + #size-cells = <0>; +}; +spi0: spi@40070000 { + reg = <0x40070000 0x400>; + interrupts = <91 2>; + girqs = < MCHP_XEC_ECIA(18, 1, 10, 91) >; + clocks = <&pcr 4 8 MCHP_XEC_PCR_CLK_PERIPH>; + clock-frequency = <12000000>; + lines = <1>; + chip-select = <0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; +}; +spi1: spi@40009400 { + reg = <0x40009400 0x80>; + interrupts = <92 2>, <93 2>; + girqs = <18 2>, <18 3>; + pcrs = <3 9>; + status = "disabled"; +}; +spi2: spi@40009480 { + reg = <0x40009480 0x80>; + interrupts = <94 2>, <95 2>; + girqs = <18 4>, <18 5>; + pcrs = <4 22>; + status = "disabled"; +}; +prochot0: prochot@40003400 { + reg = <0x40003400 0x20>; + interrupts = <87 0>; + girqs = <17 17>; + pcrs = <4 13>; + status = "disabled"; +}; +rcid0: rcid@40001400 { + reg = <0x40001400 0x80>; + interrupts = <80 0>; + girqs = <17 10>; + pcrs = <4 10>; + status = "disabled"; +}; +rcid1: rcid@40001480 { + reg = <0x40001480 0x80>; + interrupts = <81 0>; + girqs = <17 11>; + pcrs = <4 11>; + status = "disabled"; +}; +rcid2: rcid@40001500 { + reg = <0x40001500 0x80>; + interrupts = <82 0>; + girqs = <17 12>; + pcrs = <4 12>; + status = "disabled"; +}; +spip0: spip@40007000 { + reg = <0x40007000 0x100>; + interrupts = <90 0>; + girqs = <18 0>; + pcrs = <4 16>; + status = "disabled"; +}; +bbled0: bbled@4000b800 { + reg = <0x4000b800 0x100>; + interrupts = <83 0>; + girqs = <17 13>; + pcrs = <3 16>; + status = "disabled"; +}; +bbled1: bbled@4000b900 { + reg = <0x4000b900 0x100>; + interrupts = <84 0>; + girqs = <17 14>; + pcrs = <3 17>; + status = "disabled"; +}; +bbled2: bbled@4000ba00 { + reg = <0x4000ba00 0x100>; + interrupts = <85 0>; + girqs = <17 15>; + pcrs = <3 18>; + status = "disabled"; +}; +bbled3: bbled@4000bb00 { + reg = <0x4000bb00 0x100>; + interrupts = <86 0>; + girqs = <17 16>; + pcrs = <3 25>; + status = "disabled"; +}; +bclink0: bclink@4000cd00 { + reg = <0x4000cd00 0x20>; + interrupts = <96 0>, <97 0>; + girqs = <18 7>, <18 6>; + pcrs = <3 19>; + status = "disabled"; +}; +tfdp0: tfdp@40008c00 { + reg = <0x40008c00 0x10>; + pcrs = <1 7>; + status = "disabled"; +}; +glblcfg0: glblcfg@400fff00 { + reg = <0x400fff00 0x40>; + pcrs = <2 12>; + status = "disabled"; +}; +uart0: uart@400f2400 { + compatible = "microchip,xec-uart"; + reg = <0x400f2400 0x400>; + interrupts = <40 1>; + clock-frequency = <1843200>; + current-speed = <38400>; + girqs = <15 0>; + pcrs = <2 1>; + ldn = <9>; + status = "disabled"; +}; +uart1: uart@400f2800 { + compatible = "microchip,xec-uart"; + reg = <0x400f2800 0x400>; + interrupts = <41 1>; + clock-frequency = <1843200>; + current-speed = <38400>; + girqs = <15 1>; + pcrs = <2 2>; + ldn = <10>; + status = "disabled"; +}; +espi0: espi@400f3400 { + compatible = "microchip,xec-espi-v2"; + /* reg tuple contains one 32-bit address cell and one + * 32-bit length(size) cell. + */ + #address-cells = <1>; + #size-cells = <1>; + reg = < 0x400f3400 0x400 + 0x400f3800 0x400 + 0x400f9c00 0x400>; + reg-names = "io", "mem", "vw"; + interrupts = <103 3>, <104 3>, <105 3>, <106 3>, + <107 3>, <108 3>, <109 3>, <110 2>, + <156 3>; + interrupt-names = "pc", "bm1", "bm2", "ltr", "oob_up", + "oob_dn", "fc", "rst", "vw_chan_en"; + girqs = < MCHP_XEC_ECIA(19, 0, 11, 103) + MCHP_XEC_ECIA(19, 1, 11, 104) + MCHP_XEC_ECIA(19, 2, 11, 105) + MCHP_XEC_ECIA(19, 3, 11, 106) + MCHP_XEC_ECIA(19, 4, 11, 107) + MCHP_XEC_ECIA(19, 5, 11, 108) + MCHP_XEC_ECIA(19, 6, 11, 109) + MCHP_XEC_ECIA(19, 7, 11, 110) + MCHP_XEC_ECIA(19, 8, 11, 156) >; + pcrs = <2 19>; + status = "disabled"; + + espi_saf0: espi_saf@40008000 { + compatible = "microchip,xec-espi-saf-v2"; + reg = <0x40008000 0x400>, <0x40070000 0x400>, + <0x40071000 0x400>; + reg-names = "safbr", "safqspi", "safcomm"; + interrupts = <166 3>, <167 3>; + interrupt-names = "done", "err"; + girqs = < MCHP_XEC_ECIA(19, 9, 11, 166) >, + < MCHP_XEC_ECIA(19, 10, 11, 167) >; + pcrs = <2 27>; + status = "disabled"; + }; + + mbox0: mbox@400f0000 { + compatible = "microchip,xec-espi-host-dev"; + reg = <0x400f0000 0x200>; + interrupts = <60 3>; + girqs = < MCHP_XEC_ECIA(15, 20, 7, 60) >; + pcrs = <2 17>; + ldn = <0>; + status = "disabled"; + }; + kbc0: kbc@400f0400 { + compatible = "microchip,xec-espi-host-dev"; + reg = <0x400f0400 0x400>; + interrupts = <58 3>, <59 3>; + interrupt-names = "kbc_obe", "kbc_ibf"; + girqs = < MCHP_XEC_ECIA(15, 18, 7, 58) + MCHP_XEC_ECIA(15, 19, 7, 59) >; + ldn = <1>; + status = "disabled"; + }; + acpi_ec0: acpi_ec@400f0800 { + compatible = "microchip,xec-espi-host-dev"; + reg = <0x400f0800 0x400>; + interrupts = <45 3>, <46 3>; + interrupt-names = "acpi_ibf", "acpi_obe"; + girqs = < MCHP_XEC_ECIA(15, 5, 7, 45) + MCHP_XEC_ECIA(15, 6, 7, 46) >; + ldn = <2>; + status = "disabled"; + }; + acpi_ec1: acpi_ec@400f0c00 { + compatible = "microchip,xec-espi-host-dev"; + reg = <0x400f0c00 0x400>; + interrupts = <47 3>, <48 3>; + interrupt-names = "acpi_ibf", "acpi_obe"; + girqs = < MCHP_XEC_ECIA(15, 7, 7, 47) + MCHP_XEC_ECIA(15, 8, 7, 48) >; + ldn = <3>; + status = "disabled"; + }; + acpi_ec2: acpi_ec@400f1000 { + compatible = "microchip,xec-espi-host-dev"; + reg = <0x400f1000 0x400>; + interrupts = <49 3>, <50 3>; + interrupt-names = "acpi_ibf", "acpi_obe"; + girqs = < MCHP_XEC_ECIA(15, 9, 7, 49) + MCHP_XEC_ECIA(15, 10, 7, 50) >; + ldn = <4>; + status = "disabled"; + }; + acpi_ec3: acpi_ec@400f1400 { + compatible = "microchip,xec-espi-host-dev"; + reg = <0x400f1400 0x400>; + interrupts = <51 3>, <52 3>; + interrupt-names = "acpi_ibf", "acpi_obe"; + girqs = < MCHP_XEC_ECIA(15, 11, 7, 51) + MCHP_XEC_ECIA(15, 12, 7, 52) >; + ldn = <5>; + status = "disabled"; + }; + acpi_ec4: acpi_ec@400f1800 { + compatible = "microchip,xec-espi-host-dev"; + reg = <0x400f1800 0x400>; + interrupts = <53 3>, <54 3>; + interrupt-names = "acpi_ibf", "acpi_obe"; + girqs = < MCHP_XEC_ECIA(15, 13, 7, 53) + MCHP_XEC_ECIA(15, 14, 7, 54) >; + ldn = <6>; + status = "disabled"; + }; + acpi_pm1: acpi_pm1@400f1c00 { + compatible = "microchip,xec-espi-host-dev"; + reg = <0x400f1c00 0x400>; + interrupts = <55 3>, <56 3>, <57 3>; + interrupt-names = "pm1_ctl", "pm1_en", "pm1_sts"; + girqs = < MCHP_XEC_ECIA(15, 15, 7, 55) + MCHP_XEC_ECIA(15, 16, 7, 56) + MCHP_XEC_ECIA(15, 17, 7, 57) >; + ldn = <7>; + status = "disabled"; + }; + port92: port92@400f2000 { + compatible = "microchip,xec-espi-host-dev"; + reg = <0x400f2000 0x400>; + ldn = <8>; + status = "disabled"; + }; + emi0: emi@400f4000 { + compatible = "microchip,xec-espi-host-dev"; + reg = <0x400f4000 0x400>; + interrupts = <42 3>; + girqs = < MCHP_XEC_ECIA(15, 2, 7, 42) >; + ldn = <16>; + status = "disabled"; + }; + emi1: emi@400f4400 { + compatible = "microchip,xec-espi-host-dev"; + reg = <0x400f4400 0x400>; + interrupts = <43 3>; + girqs = < MCHP_XEC_ECIA(15, 3, 7, 43) >; + ldn = <17>; + status = "disabled"; + }; + emi2: emi@400f4800 { + compatible = "microchip,xec-espi-host-dev"; + reg = <0x400f4800 0x400>; + interrupts = <44 3>; + girqs = < MCHP_XEC_ECIA(15, 4, 7, 44) >; + ldn = <18>; + status = "disabled"; + }; + rtc0: rtc@400f5000 { + compatible = "microchip,xec-espi-host-dev"; + reg = <0x400f5000 0x100>; + interrupts = <119 3>, <120 3>; + girqs = < MCHP_XEC_ECIA(21, 8, 13, 119) + MCHP_XEC_ECIA(21, 9, 13, 120) >; + pcrs = <2 18>; + ldn = <20>; + status = "disabled"; + }; + /* Capture writes to host I/O 0x80 - 0x83 */ + p80bd0: p80bd@400f8000 { + compatible = "microchip,xec-espi-host-dev"; + reg = <0x400f8000 0x400>; + interrupts = <62 0>; + girqs = < MCHP_XEC_ECIA(15, 22, 7, 62) >; + pcrs = <2 25>; + ldn = <32>; + status = "disabled"; + }; + /* Capture writes to an 8-bit I/O and map to one of 0x80 to 0x83 */ + p80bd0_alias: p80bd@400f8400 { + compatible = "microchip,xec-espi-host-dev"; + reg = <0x400f8400 0x400>; + ldn = <33>; + host-io = <0x90>; + /* map 0x90 to 0x80 */ + host-io-addr-mask = <0x01>; + status = "disabled"; + }; +}; + +symcr: symcr@40100000 { + compatible = "microchip,xec-symcr"; + reg = <0x40100000 0x1000>; + interrupts = <68 1>; + clocks = <&pcr 3 26 MCHP_XEC_PCR_CLK_PERIPH>; + girqs = <16 3>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; +}; + +rom_api: rom_api@1f000 { + reg = <0x1f000 0x1000>; + status = "disabled"; +}; diff --git a/dts/arm/microchip/mec172xnlj.dtsi b/dts/arm/microchip/mec172xnlj.dtsi index 968c1e95c36..00d27b422c0 100644 --- a/dts/arm/microchip/mec172xnlj.dtsi +++ b/dts/arm/microchip/mec172xnlj.dtsi @@ -4,11 +4,68 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "mec172xnsz.dtsi" +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mec172x/mec172x-vw-routing.dtsi" / { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m4"; + reg = <0>; + cpu-power-states = <&idle &suspend_to_ram>; + }; + + power-states { + idle: idle { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + min-residency-us = <1000000>; + }; + + suspend_to_ram: suspend_to_ram { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-ram"; + min-residency-us = <2000000>; + }; + }; + }; + + flash0: flash@c0000 { + reg = <0x000C0000 0x58000>; + }; + + sram0: memory@118000 { + compatible = "mmio-sram"; + reg = <0x00118000 0x10000>; + }; soc { + #include "mec172x_common.dtsi" + + eeprom: eeprom@40002c00 { + compatible = "microchip,xec-eeprom"; + reg = <0x40002c00 0x400>; + interrupts = <155 2>; + size = <8192>; + girqs = <18 13>; + pcrs = <4 14>; + status = "disabled"; + }; + pwm9: pwm@40005890 { compatible = "microchip,xec-pwm"; reg = <0x40005890 0x20>; @@ -32,6 +89,14 @@ status = "disabled"; #pwm-cells = <3>; }; + }; }; +&nvic { + arm,num-irq-priority-bits = <3>; +}; + +&systick { + status = "disabled"; +}; diff --git a/dts/arm/microchip/mec172xnsz.dtsi b/dts/arm/microchip/mec172xnsz.dtsi index 8a95e8ec800..cbb84f21877 100644 --- a/dts/arm/microchip/mec172xnsz.dtsi +++ b/dts/arm/microchip/mec172xnsz.dtsi @@ -54,464 +54,8 @@ }; soc { - ecs: ecs@4000fc00 { - reg = <0x4000fc00 0x200>; - }; - pcr: pcr@40080100 { - compatible = "microchip,xec-pcr"; - reg = <0x40080100 0x100 0x4000a400 0x100>; - reg-names = "pcrr", "vbatr"; - interrupts = <174 0>; - core-clock-div = <1>; - /* MEC172x allows sources to be different */ - pll-32k-src = ; - periph-32k-src = ; - clk32kmon-period-min = <1435>; - clk32kmon-period-max = <1495>; - clk32kmon-duty-cycle-var-max = <132>; - clk32kmon-valid-min = <4>; - xtal-enable-delay-ms = <300>; - pll-lock-timeout-ms = <30>; - /* pin configured only if one of the sources is set to PIN */ - pinctrl-0 = <&clk_32khz_in_gpio165>; - pinctrl-names = "default"; - #clock-cells = <3>; - }; - ecia: ecia@4000e000 { - compatible = "microchip,xec-ecia"; - reg = <0x4000e000 0x400>; - direct-capable-girqs = <13 14 15 16 17 18 19 20 21 23>; - clocks = <&pcr 1 0 MCHP_XEC_PCR_CLK_PERIPH>; - #address-cells = <1>; - #size-cells = <1>; - - ranges = <0x0 0x4000e000 0x400>; + #include "mec172x_common.dtsi" - girq8: girq8@0 { - compatible = "microchip,xec-ecia-girq"; - reg = <0x0 0x14>; - interrupts = <0 0>; - girq-id = <0>; - sources = <0 1 2 3 4 5 6 7 - 8 9 10 11 12 13 14 15 - 16 17 18 21 22 24 25 - 26 27 28 29>; - status = "disabled"; - }; - girq9: girq9@14 { - compatible = "microchip,xec-ecia-girq"; - reg = <0x14 0x14>; - interrupts = <1 0>; - girq-id = <1>; - sources = <0 1 2 3 4 5 6 7 - 8 9 10 11 12 13 14 15 - 16 17 18 19 20 21 22 23 - 24 25 26 27 28 29>; - status = "disabled"; - }; - girq10: girq10@28 { - compatible = "microchip,xec-ecia-girq"; - reg = <0x28 0x14>; - interrupts = <2 0>; - girq-id = <2>; - sources = <0 1 2 3 4 5 6 7 - 8 9 10 11 12 13 14 15 - 16 17 18 19 20 21 22 23 - 24 25 26 27 28 29 30>; - status = "disabled"; - }; - girq11: girq11@3c { - compatible = "microchip,xec-ecia-girq"; - reg = <0x3c 0x14>; - interrupts = <3 0>; - girq-id = <3>; - sources = <0 1 2 3 4 5 6 7 - 8 9 10 11 12 13 14 15 - 16 17 18 19 20 21 22 23 - 24 25 26 27 28 29 30>; - status = "disabled"; - }; - girq12: girq12@50 { - compatible = "microchip,xec-ecia-girq"; - reg = <0x50 0x14>; - interrupts = <4 0>; - girq-id = <4>; - sources = <0 1 2 3 4 5 6 7 - 8 9 10 11 12 13 14 15 - 16 17 18 19 20 21 22 23 - 24 25 26 27 28 29 30>; - status = "disabled"; - }; - girq13: girq13@64 { - compatible = "microchip,xec-ecia-girq"; - reg = <0x64 0x14>; - interrupts = <5 0>; - girq-id = <5>; - sources = <0 1 2 3 4>; - status = "disabled"; - }; - girq14: girq14@78 { - compatible = "microchip,xec-ecia-girq"; - reg = <0x78 0x14>; - interrupts = <6 0>; - girq-id = <6>; - sources = <0 1 2 3 4 5 6 7 - 8 9 10 11 12 13 14 15>; - status = "disabled"; - }; - girq15: girq15@8c { - compatible = "microchip,xec-ecia-girq"; - reg = <0x8c 0x14>; - interrupts = <7 0>; - girq-id = <7>; - sources = <0 1 2 3 4 5 6 7 - 8 9 10 11 12 13 14 15 - 16 17 18 19 20 22>; - status = "disabled"; - }; - girq16: girq16@a0 { - compatible = "microchip,xec-ecia-girq"; - reg = <0xa0 0x14>; - interrupts = <8 0>; - girq-id = <8>; - sources = <0 2 3>; - status = "disabled"; - }; - girq17: girq17@b4 { - compatible = "microchip,xec-ecia-girq"; - reg = <0xb4 0x14>; - interrupts = <9 0>; - girq-id = <9>; - sources = <0 1 2 3 4 8 9 10 11 12 13 14 15 - 16 17 20 21 22 23>; - status = "disabled"; - }; - girq18: girq18@c8 { - compatible = "microchip,xec-ecia-girq"; - reg = <0xc8 0x14>; - interrupts = <10 0>; - girq-id = <10>; - sources = <0 1 2 3 4 5 6 7 - 10 20 21 22 23 - 24 25 26 27 28>; - status = "disabled"; - }; - girq19: girq19@dc { - compatible = "microchip,xec-ecia-girq"; - reg = <0xdc 0x14>; - interrupts = <11 0>; - girq-id = <11>; - sources = <0 1 2 3 4 5 6 7 8 9 10>; - status = "disabled"; - }; - girq20: girq20@f0 { - compatible = "microchip,xec-ecia-girq"; - reg = <0xf0 0x14>; - interrupts = <12 0>; - girq-id = <12>; - sources = <3 9>; - status = "disabled"; - }; - girq21: girq21@104 { - compatible = "microchip,xec-ecia-girq"; - reg = <0x104 0x14>; - interrupts = <13 0>; - girq-id = <13>; - sources = <2 3 4 5 6 7 8 9 10 11 12 13 14 15 - 18 19 25 26>; - status = "disabled"; - }; - girq22: girq22@118 { - compatible = "microchip,xec-ecia-girq"; - reg = <0x118 0x14>; - interrupts = <255 0>; - girq-id = <14>; - sources = <0 1 2 3 4 5 9 15>; - status = "disabled"; - }; - girq23: girq23@12c { - compatible = "microchip,xec-ecia-girq"; - reg = <0x12c 0x14>; - interrupts = <14 0>; - girq-id = <15>; - sources = <0 1 2 3 4 5 6 7 8 9 10 16 17>; - status = "disabled"; - }; - girq24: girq24@140 { - compatible = "microchip,xec-ecia-girq"; - reg = <0x140 0x14>; - interrupts = <15 0>; - girq-id = <16>; - sources = <0 1 2 3 4 5 6 7 8 9 10 11 - 12 13 14 15 16 17 18 19 - 20 21 22 23 24 25 26 27>; - status = "disabled"; - }; - girq25: girq25@154 { - compatible = "microchip,xec-ecia-girq"; - reg = <0x154 0x14>; - interrupts = <16 0>; - girq-id = <17>; - sources = <0 1 2 3 4 5 6 7 8 9 10 11 - 12 13 14 15>; - status = "disabled"; - }; - girq26: girq26@168 { - compatible = "microchip,xec-ecia-girq"; - reg = <0x168 0x14>; - interrupts = <17 0>; - girq-id = <18>; - sources = <0 1 2 3 4 5 6 12 13>; - status = "disabled"; - }; - }; - pinctrl: pin-controller@40081000 { - compatible = "microchip,xec-pinctrl"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0x40081000 0x1000>; - - gpio_000_036: gpio@40081000 { - compatible = "microchip,xec-gpio-v2"; - reg = < 0x40081000 0x80 0x40081300 0x04 - 0x40081380 0x04 0x400813fc 0x04>; - interrupts = <3 2>; - gpio-controller; - port-id = <0>; - girq-id = <11>; - #gpio-cells=<2>; - }; - gpio_040_076: gpio@40081080 { - compatible = "microchip,xec-gpio-v2"; - reg = < 0x40081080 0x80 0x40081304 0x04 - 0x40081384 0x04 0x400813f8 0x4>; - interrupts = <2 2>; - gpio-controller; - port-id = <1>; - girq-id = <10>; - #gpio-cells=<2>; - }; - gpio_100_136: gpio@40081100 { - compatible = "microchip,xec-gpio-v2"; - reg = < 0x40081100 0x80 0x40081308 0x04 - 0x40081388 0x04 0x400813f4 0x04>; - gpio-controller; - interrupts = <1 2>; - port-id = <2>; - girq-id = <9>; - #gpio-cells=<2>; - }; - gpio_140_176: gpio@40081180 { - compatible = "microchip,xec-gpio-v2"; - reg = < 0x40081180 0x80 0x4008130c 0x04 - 0x4008138c 0x04 0x400813f0 0x04>; - gpio-controller; - interrupts = <0 2>; - port-id = <3>; - girq-id = <8>; - #gpio-cells=<2>; - }; - gpio_200_236: gpio@40081200 { - compatible = "microchip,xec-gpio-v2"; - reg = < 0x40081200 0x80 0x40081310 0x04 - 0x40081390 0x04 0x400813ec 0x04>; - gpio-controller; - interrupts = <4 2>; - port-id = <4>; - girq-id = <12>; - #gpio-cells=<2>; - }; - gpio_240_276: gpio@40081280 { - compatible = "microchip,xec-gpio-v2"; - reg = < 0x40081280 0x80 0x40081314 0x04 - 0x40081394 0x04 0x400813e8 0x04>; - gpio-controller; - interrupts = <17 2>; - port-id = <5>; - girq-id = <26>; - #gpio-cells=<2>; - }; - }; - wdog: watchdog@40000400 { - compatible = "microchip,xec-watchdog"; - reg = <0x40000400 0x400>; - interrupts = <171 0>; - girqs = <21 2>; - pcrs = <1 9>; - }; - rtimer: timer@40007400 { - compatible = "microchip,xec-rtos-timer"; - reg = <0x40007400 0x10>; - interrupts = <111 0>; - girqs = <23 10>; - }; - timer0: timer@40000c00 { - compatible = "microchip,xec-timer"; - clock-frequency = <48000000>; - reg = <0x40000c00 0x20>; - interrupts = <136 0>; - girqs = <23 0>; - pcrs = <1 30>; - max-value = <0xFFFF>; - prescaler = <0>; - status = "disabled"; - }; - timer1: timer@40000c20 { - compatible = "microchip,xec-timer"; - clock-frequency = <48000000>; - reg = <0x40000c20 0x20>; - interrupts = <137 0>; - girqs = <23 1>; - pcrs = <1 31>; - max-value = <0xFFFF>; - prescaler = <0>; - status = "disabled"; - }; - timer2: timer@40000c40 { - compatible = "microchip,xec-timer"; - clock-frequency = <48000000>; - reg = <0x40000c40 0x20>; - interrupts = <138 0>; - girqs = <23 2>; - pcrs = <3 21>; - max-value = <0xFFFF>; - prescaler = <0>; - status = "disabled"; - }; - timer3: timer@40000c60 { - compatible = "microchip,xec-timer"; - clock-frequency = <48000000>; - reg = <0x40000c60 0x20>; - interrupts = <139 0>; - girqs = <23 3>; - pcrs = <3 22>; - max-value = <0xFFFF>; - prescaler = <0>; - status = "disabled"; - }; - /* - * NOTE: When RTOS timer used as kernel timer, timer4 used - * to provide high speed busy wait counter. Keep disabled to - * prevent counter driver from claiming it. - */ - timer4: timer@40000c80 { - compatible = "microchip,xec-timer"; - clock-frequency = <48000000>; - reg = <0x40000c80 0x20>; - interrupts = <140 0>; - girqs = <23 4>; - pcrs = <3 23>; - max-value = <0xFFFFFFFF>; - prescaler = <0>; - status = "disabled"; - }; - timer5: timer@40000ca0 { - compatible = "microchip,xec-timer"; - clock-frequency = <48000000>; - reg = <0x40000ca0 0x20>; - interrupts = <141 0>; - girqs = <23 5>; - pcrs = <3 24>; - max-value = <0xFFFFFFFF>; - prescaler = <0>; - status = "disabled"; - }; - cntr0: timer@40000d00 { - reg = <0x40000d00 0x20>; - interrupts = <142 0>; - girqs = <23 6>; - pcrs = <4 2>; - status = "disabled"; - }; - cntr1: timer@40000d20 { - reg = <0x40000d20 0x20>; - interrupts = <143 0>; - girqs = <23 7>; - pcrs = <4 3>; - status = "disabled"; - }; - cntr2: timer@40000d40 { - reg = <0x40000d40 0x20>; - interrupts = <144 0>; - girqs = <23 8>; - pcrs = <4 3>; - status = "disabled"; - }; - cntr3: timer@40000d60 { - reg = <0x40000d60 0x20>; - interrupts = <145 0>; - girqs = <23 9>; - pcrs = <4 4>; - status = "disabled"; - }; - cctmr0: timer@40001000 { - reg = <0x40001000 0x40>; - interrupts = <146 0>, <147 0>, <148 0>, <149 0>, - <150 0>, <151 0>, <152 0>, <153 0>, - <154 0>; - girqs = <18 20>, <18 21>, <18 22>, <18 23>, <18 24>, - <18 25>, <18 26>, <18 27>, <18 28>; - pcrs = <3 30>; - status = "disabled"; - }; - hibtimer0: timer@40009800 { - reg = <0x40009800 0x20>; - interrupts = <112 0>; - girqs = <23 16>; - }; - hibtimer1: timer@40009820 { - reg = <0x40009820 0x20>; - interrupts = <113 0>; - girqs = <23 17>; - }; - weektmr0: timer@4000ac80 { - reg = <0x4000ac80 0x80>; - interrupts = <114 0>, <115 0>, <116 0>, - <117 0>, <118 0>; - girqs = <21 3>, <21 4>, <21 5>, <21 6>, <21 7>; - status = "disabled"; - }; - bbram: bb-ram@4000a800 { - compatible = "microchip,xec-bbram"; - reg = <0x4000a800 0x100>; - reg-names = "memory"; - }; - vci0: vci@4000ae00 { - reg = <0x4000ae00 0x40>; - interrupts = <121 0>, <122 0>, <123 0>, - <124 0>, <125 0>; - girqs = <21 10>, <21 11>, <21 12>, <21 13>, <21 14>; - status = "disabled"; - }; - dmac: dmac@40002400 { - compatible = "microchip,xec-dmac"; - reg = <0x40002400 0xc00>; - interrupts = <24 1>, <25 1>, <26 1>, <27 1>, - <28 1>, <29 1>, <30 1>, <31 1>, - <32 1>, <33 1>, <34 1>, <35 1>, - <36 1>, <37 1>, <38 1>, <39 1>; - girqs = < MCHP_XEC_ECIA(14, 0, 6, 24) - MCHP_XEC_ECIA(14, 1, 6, 25) - MCHP_XEC_ECIA(14, 2, 6, 26) - MCHP_XEC_ECIA(14, 3, 6, 27) - MCHP_XEC_ECIA(14, 4, 6, 28) - MCHP_XEC_ECIA(14, 5, 6, 29) - MCHP_XEC_ECIA(14, 6, 6, 30) - MCHP_XEC_ECIA(14, 7, 6, 31) - MCHP_XEC_ECIA(14, 8, 6, 32) - MCHP_XEC_ECIA(14, 9, 6, 33) - MCHP_XEC_ECIA(14, 10, 6, 34) - MCHP_XEC_ECIA(14, 11, 6, 35) - MCHP_XEC_ECIA(14, 12, 6, 36) - MCHP_XEC_ECIA(14, 13, 6, 37) - MCHP_XEC_ECIA(14, 14, 6, 38) - MCHP_XEC_ECIA(14, 15, 6, 39) >; - pcrs = <1 6>; - #dma-cells = <2>; - dma-channels = <16>; - dma-requests = <16>; - status = "disabled"; - }; eeprom: eeprom@40002c00 { compatible = "microchip,xec-eeprom"; reg = <0x40002c00 0x400>; @@ -521,543 +65,6 @@ pcrs = <4 14>; status = "disabled"; }; - i2c_smb_0: i2c@40004000 { - compatible = "microchip,xec-i2c-v2"; - reg = <0x40004000 0x80>; - clock-frequency = ; - interrupts = <20 1>; - girqs = <13 0>; - pcrs = <1 10>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - i2c_smb_1: i2c@40004400 { - compatible = "microchip,xec-i2c-v2"; - reg = <0x40004400 0x80>; - clock-frequency = ; - interrupts = <21 1>; - girqs = <13 1>; - pcrs = <3 13>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - i2c_smb_2: i2c@40004800 { - compatible = "microchip,xec-i2c-v2"; - reg = <0x40004800 0x80>; - clock-frequency = ; - interrupts = <22 1>; - girqs = <13 2>; - pcrs = <3 14>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - i2c_smb_3: i2c@40004c00 { - compatible = "microchip,xec-i2c-v2"; - reg = <0x40004C00 0x80>; - clock-frequency = ; - interrupts = <23 1>; - girqs = <13 3>; - pcrs = <3 15>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - i2c_smb_4: i2c@40005000 { - compatible = "microchip,xec-i2c-v2"; - reg = <0x40005000 0x80>; - clock-frequency = ; - interrupts = <158 1>; - girqs = <13 4>; - pcrs = <3 20>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - ps2_0: ps2@40009000 { - compatible = "microchip,xec-ps2"; - reg = <0x40009000 0x40>; - interrupts = <100 1>; - girqs = <18 10>, <21 18>; - pcrs = <3 5>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - pwm0: pwm@40005800 { - compatible = "microchip,xec-pwm"; - reg = <0x40005800 0x20>; - pcrs = <1 4>; - status = "disabled"; - #pwm-cells = <3>; - }; - pwm1: pwm@40005810 { - compatible = "microchip,xec-pwm"; - reg = <0x40005810 0x20>; - pcrs = <1 20>; - status = "disabled"; - #pwm-cells = <3>; - }; - pwm2: pwm@40005820 { - compatible = "microchip,xec-pwm"; - reg = <0x40005820 0x20>; - pcrs = <1 21>; - status = "disabled"; - #pwm-cells = <3>; - }; - pwm3: pwm@40005830 { - compatible = "microchip,xec-pwm"; - reg = <0x40005830 0x20>; - pcrs = <1 22>; - status = "disabled"; - #pwm-cells = <3>; - }; - pwm4: pwm@40005840 { - compatible = "microchip,xec-pwm"; - reg = <0x40005840 0x20>; - pcrs = <1 23>; - status = "disabled"; - #pwm-cells = <3>; - }; - pwm5: pwm@40005850 { - compatible = "microchip,xec-pwm"; - reg = <0x40005850 0x20>; - pcrs = <1 24>; - status = "disabled"; - #pwm-cells = <3>; - }; - pwm6: pwm@40005860 { - compatible = "microchip,xec-pwm"; - reg = <0x40005860 0x20>; - pcrs = <1 25>; - status = "disabled"; - #pwm-cells = <3>; - }; - pwm7: pwm@40005870 { - compatible = "microchip,xec-pwm"; - reg = <0x40005870 0x20>; - pcrs = <1 26>; - status = "disabled"; - #pwm-cells = <3>; - }; - pwm8: pwm@40005880 { - compatible = "microchip,xec-pwm"; - reg = <0x40005880 0x20>; - pcrs = <1 27>; - status = "disabled"; - #pwm-cells = <3>; - }; - tach0: tach@40006000 { - compatible = "microchip,xec-tach"; - reg = <0x40006000 0x10>; - interrupts = <71 4>; - girqs = <17 1>; - pcrs = <1 2>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - tach1: tach@40006010 { - compatible = "microchip,xec-tach"; - reg = <0x40006010 0x10>; - interrupts = <72 4>; - girqs = <17 2>; - pcrs = <1 11>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - tach2: tach@40006020 { - compatible = "microchip,xec-tach"; - reg = <0x40006020 0x10>; - interrupts = <73 4>; - girqs = <17 3>; - pcrs = <1 12>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - tach3: tach@40006030 { - compatible = "microchip,xec-tach"; - reg = <0x40006030 0x10>; - interrupts = <159 4>; - girqs = <17 4>; - pcrs = <1 13>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - rpmfan0: rpmfan@4000a000 { - reg = <0x4000a000 0x80>; - interrupts = <74 1>, <75 1>; - girqs = <17 20>, <17 21>; - pcrs = <3 12>; - status = "disabled"; - }; - rpmfan1: rpmfan@4000a080 { - reg = <0x4000a080 0x80>; - interrupts = <76 1>, <77 1>; - girqs = <17 22>, <17 23>; - pcrs = <4 7>; - status = "disabled"; - }; - adc0: adc@40007c00 { - compatible = "microchip,xec-adc"; - reg = <0x40007c00 0x90>; - interrupts = <78 0>, <79 0>; - girqs = <17 8>, <17 9>; - pcrs = <3 3>; - status = "disabled"; - #io-channel-cells = <1>; - clktime = <32>; - }; - kscan0: kscan@40009c00 { - compatible = "microchip,xec-kscan"; - reg = <0x40009c00 0x18>; - interrupts = <135 0>; - girqs = <21 25>; - pcrs = <3 11>; - status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; - }; - peci0: peci@40006400 { - compatible = "microchip,xec-peci"; - reg = <0x40006400 0x80>; - interrupts = <70 4>; - girqs = <17 0>; - pcrs = <1 1>; - #address-cells = <1>; - #size-cells = <0>; - }; - spi0: spi@40070000 { - reg = <0x40070000 0x400>; - interrupts = <91 2>; - girqs = < MCHP_XEC_ECIA(18, 1, 10, 91) >; - clocks = <&pcr 4 8 MCHP_XEC_PCR_CLK_PERIPH>; - clock-frequency = <12000000>; - lines = <1>; - chip-select = <0>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - spi1: spi@40009400 { - reg = <0x40009400 0x80>; - interrupts = <92 2>, <93 2>; - girqs = <18 2>, <18 3>; - pcrs = <3 9>; - status = "disabled"; - }; - spi2: spi@40009480 { - reg = <0x40009480 0x80>; - interrupts = <94 2>, <95 2>; - girqs = <18 4>, <18 5>; - pcrs = <4 22>; - status = "disabled"; - }; - prochot0: prochot@40003400 { - reg = <0x40003400 0x20>; - interrupts = <87 0>; - girqs = <17 17>; - pcrs = <4 13>; - status = "disabled"; - }; - rcid0: rcid@40001400 { - reg = <0x40001400 0x80>; - interrupts = <80 0>; - girqs = <17 10>; - pcrs = <4 10>; - status = "disabled"; - }; - rcid1: rcid@40001480 { - reg = <0x40001480 0x80>; - interrupts = <81 0>; - girqs = <17 11>; - pcrs = <4 11>; - status = "disabled"; - }; - rcid2: rcid@40001500 { - reg = <0x40001500 0x80>; - interrupts = <82 0>; - girqs = <17 12>; - pcrs = <4 12>; - status = "disabled"; - }; - spip0: spip@40007000 { - reg = <0x40007000 0x100>; - interrupts = <90 0>; - girqs = <18 0>; - pcrs = <4 16>; - status = "disabled"; - }; - bbled0: bbled@4000b800 { - reg = <0x4000b800 0x100>; - interrupts = <83 0>; - girqs = <17 13>; - pcrs = <3 16>; - status = "disabled"; - }; - bbled1: bbled@4000b900 { - reg = <0x4000b900 0x100>; - interrupts = <84 0>; - girqs = <17 14>; - pcrs = <3 17>; - status = "disabled"; - }; - bbled2: bbled@4000ba00 { - reg = <0x4000ba00 0x100>; - interrupts = <85 0>; - girqs = <17 15>; - pcrs = <3 18>; - status = "disabled"; - }; - bbled3: bbled@4000bb00 { - reg = <0x4000bb00 0x100>; - interrupts = <86 0>; - girqs = <17 16>; - pcrs = <3 25>; - status = "disabled"; - }; - bclink0: bclink@4000cd00 { - reg = <0x4000cd00 0x20>; - interrupts = <96 0>, <97 0>; - girqs = <18 7>, <18 6>; - pcrs = <3 19>; - status = "disabled"; - }; - tfdp0: tfdp@40008c00 { - reg = <0x40008c00 0x10>; - pcrs = <1 7>; - status = "disabled"; - }; - glblcfg0: glblcfg@400fff00 { - reg = <0x400fff00 0x40>; - pcrs = <2 12>; - status = "disabled"; - }; - uart0: uart@400f2400 { - compatible = "microchip,xec-uart"; - reg = <0x400f2400 0x400>; - interrupts = <40 1>; - clock-frequency = <1843200>; - current-speed = <38400>; - girqs = <15 0>; - pcrs = <2 1>; - ldn = <9>; - status = "disabled"; - }; - uart1: uart@400f2800 { - compatible = "microchip,xec-uart"; - reg = <0x400f2800 0x400>; - interrupts = <41 1>; - clock-frequency = <1843200>; - current-speed = <38400>; - girqs = <15 1>; - pcrs = <2 2>; - ldn = <10>; - status = "disabled"; - }; - espi0: espi@400f3400 { - compatible = "microchip,xec-espi-v2"; - /* reg tuple contains one 32-bit address cell and one - * 32-bit length(size) cell. - */ - #address-cells = <1>; - #size-cells = <1>; - reg = < 0x400f3400 0x400 - 0x400f3800 0x400 - 0x400f9c00 0x400>; - reg-names = "io", "mem", "vw"; - interrupts = <103 3>, <104 3>, <105 3>, <106 3>, - <107 3>, <108 3>, <109 3>, <110 2>, - <156 3>; - interrupt-names = "pc", "bm1", "bm2", "ltr", "oob_up", - "oob_dn", "fc", "rst", "vw_chan_en"; - girqs = < MCHP_XEC_ECIA(19, 0, 11, 103) - MCHP_XEC_ECIA(19, 1, 11, 104) - MCHP_XEC_ECIA(19, 2, 11, 105) - MCHP_XEC_ECIA(19, 3, 11, 106) - MCHP_XEC_ECIA(19, 4, 11, 107) - MCHP_XEC_ECIA(19, 5, 11, 108) - MCHP_XEC_ECIA(19, 6, 11, 109) - MCHP_XEC_ECIA(19, 7, 11, 110) - MCHP_XEC_ECIA(19, 8, 11, 156) >; - pcrs = <2 19>; - status = "disabled"; - - espi_saf0: espi_saf@40008000 { - compatible = "microchip,xec-espi-saf-v2"; - reg = <0x40008000 0x400>, <0x40070000 0x400>, - <0x40071000 0x400>; - reg-names = "safbr", "safqspi", "safcomm"; - interrupts = <166 3>, <167 3>; - interrupt-names = "done", "err"; - girqs = < MCHP_XEC_ECIA(19, 9, 11, 166) >, - < MCHP_XEC_ECIA(19, 10, 11, 167) >; - pcrs = <2 27>; - status = "disabled"; - }; - - mbox0: mbox@400f0000 { - compatible = "microchip,xec-espi-host-dev"; - reg = <0x400f0000 0x200>; - interrupts = <60 3>; - girqs = < MCHP_XEC_ECIA(15, 20, 7, 60) >; - pcrs = <2 17>; - ldn = <0>; - status = "disabled"; - }; - kbc0: kbc@400f0400 { - compatible = "microchip,xec-espi-host-dev"; - reg = <0x400f0400 0x400>; - interrupts = <58 3>, <59 3>; - interrupt-names = "kbc_obe", "kbc_ibf"; - girqs = < MCHP_XEC_ECIA(15, 18, 7, 58) - MCHP_XEC_ECIA(15, 19, 7, 59) >; - ldn = <1>; - status = "disabled"; - }; - acpi_ec0: acpi_ec@400f0800 { - compatible = "microchip,xec-espi-host-dev"; - reg = <0x400f0800 0x400>; - interrupts = <45 3>, <46 3>; - interrupt-names = "acpi_ibf", "acpi_obe"; - girqs = < MCHP_XEC_ECIA(15, 5, 7, 45) - MCHP_XEC_ECIA(15, 6, 7, 46) >; - ldn = <2>; - status = "disabled"; - }; - acpi_ec1: acpi_ec@400f0c00 { - compatible = "microchip,xec-espi-host-dev"; - reg = <0x400f0c00 0x400>; - interrupts = <47 3>, <48 3>; - interrupt-names = "acpi_ibf", "acpi_obe"; - girqs = < MCHP_XEC_ECIA(15, 7, 7, 47) - MCHP_XEC_ECIA(15, 8, 7, 48) >; - ldn = <3>; - status = "disabled"; - }; - acpi_ec2: acpi_ec@400f1000 { - compatible = "microchip,xec-espi-host-dev"; - reg = <0x400f1000 0x400>; - interrupts = <49 3>, <50 3>; - interrupt-names = "acpi_ibf", "acpi_obe"; - girqs = < MCHP_XEC_ECIA(15, 9, 7, 49) - MCHP_XEC_ECIA(15, 10, 7, 50) >; - ldn = <4>; - status = "disabled"; - }; - acpi_ec3: acpi_ec@400f1400 { - compatible = "microchip,xec-espi-host-dev"; - reg = <0x400f1400 0x400>; - interrupts = <51 3>, <52 3>; - interrupt-names = "acpi_ibf", "acpi_obe"; - girqs = < MCHP_XEC_ECIA(15, 11, 7, 51) - MCHP_XEC_ECIA(15, 12, 7, 52) >; - ldn = <5>; - status = "disabled"; - }; - acpi_ec4: acpi_ec@400f1800 { - compatible = "microchip,xec-espi-host-dev"; - reg = <0x400f1800 0x400>; - interrupts = <53 3>, <54 3>; - interrupt-names = "acpi_ibf", "acpi_obe"; - girqs = < MCHP_XEC_ECIA(15, 13, 7, 53) - MCHP_XEC_ECIA(15, 14, 7, 54) >; - ldn = <6>; - status = "disabled"; - }; - acpi_pm1: acpi_pm1@400f1c00 { - compatible = "microchip,xec-espi-host-dev"; - reg = <0x400f1c00 0x400>; - interrupts = <55 3>, <56 3>, <57 3>; - interrupt-names = "pm1_ctl", "pm1_en", "pm1_sts"; - girqs = < MCHP_XEC_ECIA(15, 15, 7, 55) - MCHP_XEC_ECIA(15, 16, 7, 56) - MCHP_XEC_ECIA(15, 17, 7, 57) >; - ldn = <7>; - status = "disabled"; - }; - port92: port92@400f2000 { - compatible = "microchip,xec-espi-host-dev"; - reg = <0x400f2000 0x400>; - ldn = <8>; - status = "disabled"; - }; - emi0: emi@400f4000 { - compatible = "microchip,xec-espi-host-dev"; - reg = <0x400f4000 0x400>; - interrupts = <42 3>; - girqs = < MCHP_XEC_ECIA(15, 2, 7, 42) >; - ldn = <16>; - status = "disabled"; - }; - emi1: emi@400f4400 { - compatible = "microchip,xec-espi-host-dev"; - reg = <0x400f4400 0x400>; - interrupts = <43 3>; - girqs = < MCHP_XEC_ECIA(15, 3, 7, 43) >; - ldn = <17>; - status = "disabled"; - }; - emi2: emi@400f4800 { - compatible = "microchip,xec-espi-host-dev"; - reg = <0x400f4800 0x400>; - interrupts = <44 3>; - girqs = < MCHP_XEC_ECIA(15, 4, 7, 44) >; - ldn = <18>; - status = "disabled"; - }; - rtc0: rtc@400f5000 { - compatible = "microchip,xec-espi-host-dev"; - reg = <0x400f5000 0x100>; - interrupts = <119 3>, <120 3>; - girqs = < MCHP_XEC_ECIA(21, 8, 13, 119) - MCHP_XEC_ECIA(21, 9, 13, 120) >; - pcrs = <2 18>; - ldn = <20>; - status = "disabled"; - }; - /* Capture writes to host I/O 0x80 - 0x83 */ - p80bd0: p80bd@400f8000 { - compatible = "microchip,xec-espi-host-dev"; - reg = <0x400f8000 0x400>; - interrupts = <62 0>; - girqs = < MCHP_XEC_ECIA(15, 22, 7, 62) >; - pcrs = <2 25>; - ldn = <32>; - status = "disabled"; - }; - /* Capture writes to an 8-bit I/O and map to one of 0x80 to 0x83 */ - p80bd0_alias: p80bd@400f8400 { - compatible = "microchip,xec-espi-host-dev"; - reg = <0x400f8400 0x400>; - ldn = <33>; - host-io = <0x90>; - /* map 0x90 to 0x80 */ - host-io-addr-mask = <0x01>; - status = "disabled"; - }; - }; - - symcr: symcr@40100000 { - compatible = "microchip,xec-symcr"; - reg = <0x40100000 0x1000>; - interrupts = <68 1>; - clocks = <&pcr 3 26 MCHP_XEC_PCR_CLK_PERIPH>; - girqs = <16 3>; - status = "disabled"; - #address-cells = <1>; - #size-cells = <1>; - }; - - rom_api: rom_api@1f000 { - reg = <0x1f000 0x1000>; - status = "disabled"; - }; }; }; diff --git a/dts/arm/nordic/nrf51822.dtsi b/dts/arm/nordic/nrf51822.dtsi index c55b94cc660..222ccd4854c 100644 --- a/dts/arm/nordic/nrf51822.dtsi +++ b/dts/arm/nordic/nrf51822.dtsi @@ -99,6 +99,7 @@ reg = <0x40003000 0x1000>; clock-frequency = ; interrupts = <3 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <8>; status = "disabled"; }; @@ -126,6 +127,7 @@ reg = <0x40004000 0x1000>; clock-frequency = ; interrupts = <4 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <8>; status = "disabled"; }; diff --git a/dts/arm/nordic/nrf52805.dtsi b/dts/arm/nordic/nrf52805.dtsi index 212100d90e5..dd7845588e7 100644 --- a/dts/arm/nordic/nrf52805.dtsi +++ b/dts/arm/nordic/nrf52805.dtsi @@ -110,6 +110,7 @@ reg = <0x40003000 0x1000>; clock-frequency = ; interrupts = <3 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <14>; status = "disabled"; }; diff --git a/dts/arm/nordic/nrf52810.dtsi b/dts/arm/nordic/nrf52810.dtsi index 36bfda18511..82f5afb99f6 100644 --- a/dts/arm/nordic/nrf52810.dtsi +++ b/dts/arm/nordic/nrf52810.dtsi @@ -114,6 +114,7 @@ reg = <0x40003000 0x1000>; clock-frequency = ; interrupts = <3 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <10>; status = "disabled"; }; diff --git a/dts/arm/nordic/nrf52811.dtsi b/dts/arm/nordic/nrf52811.dtsi index 815bf16d6c1..9e03d5edb32 100644 --- a/dts/arm/nordic/nrf52811.dtsi +++ b/dts/arm/nordic/nrf52811.dtsi @@ -126,6 +126,7 @@ reg = <0x40003000 0x1000>; clock-frequency = ; interrupts = <3 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <14>; status = "disabled"; }; diff --git a/dts/arm/nordic/nrf52820.dtsi b/dts/arm/nordic/nrf52820.dtsi index c3d05fc6ec1..71ff85afbeb 100644 --- a/dts/arm/nordic/nrf52820.dtsi +++ b/dts/arm/nordic/nrf52820.dtsi @@ -122,6 +122,7 @@ reg = <0x40003000 0x1000>; clock-frequency = ; interrupts = <3 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <15>; status = "disabled"; }; @@ -157,6 +158,7 @@ reg = <0x40004000 0x1000>; clock-frequency = ; interrupts = <4 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <15>; status = "disabled"; }; diff --git a/dts/arm/nordic/nrf52832.dtsi b/dts/arm/nordic/nrf52832.dtsi index 929e5ffcee4..69de3aa591a 100644 --- a/dts/arm/nordic/nrf52832.dtsi +++ b/dts/arm/nordic/nrf52832.dtsi @@ -114,6 +114,7 @@ reg = <0x40003000 0x1000>; clock-frequency = ; interrupts = <3 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <8>; status = "disabled"; }; @@ -149,6 +150,7 @@ reg = <0x40004000 0x1000>; clock-frequency = ; interrupts = <4 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <8>; status = "disabled"; }; diff --git a/dts/arm/nordic/nrf52833.dtsi b/dts/arm/nordic/nrf52833.dtsi index 08c806cc99b..8003649385c 100644 --- a/dts/arm/nordic/nrf52833.dtsi +++ b/dts/arm/nordic/nrf52833.dtsi @@ -121,6 +121,7 @@ reg = <0x40003000 0x1000>; clock-frequency = ; interrupts = <3 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <16>; status = "disabled"; }; @@ -156,6 +157,7 @@ reg = <0x40004000 0x1000>; clock-frequency = ; interrupts = <4 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <16>; status = "disabled"; }; diff --git a/dts/arm/nordic/nrf52840.dtsi b/dts/arm/nordic/nrf52840.dtsi index f4209c67d19..9e3b79b3abd 100644 --- a/dts/arm/nordic/nrf52840.dtsi +++ b/dts/arm/nordic/nrf52840.dtsi @@ -116,6 +116,7 @@ reg = <0x40003000 0x1000>; clock-frequency = ; interrupts = <3 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <16>; status = "disabled"; }; @@ -151,6 +152,7 @@ reg = <0x40004000 0x1000>; clock-frequency = ; interrupts = <4 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <16>; status = "disabled"; }; @@ -537,16 +539,11 @@ }; cryptocell: crypto@5002a000 { - compatible = "nordic,nrf-cc310"; - reg = <0x5002A000 0x1000>; + compatible = "nordic,cryptocell", "arm,cryptocell-310"; + reg = <0x5002a000 0x1000>, <0x5002b000 0x1000>; + reg-names = "wrapper", "core"; + interrupts = <42 NRF_DEFAULT_IRQ_PRIORITY>; status = "okay"; - #address-cells = <1>; - #size-cells = <1>; - cryptocell310: crypto@5002b000 { - compatible = "arm,cryptocell-310"; - reg = <0x5002B000 0x1000>; - interrupts = <42 NRF_DEFAULT_IRQ_PRIORITY>; - }; }; }; }; diff --git a/dts/arm/nordic/nrf5340_cpuapp.dtsi b/dts/arm/nordic/nrf5340_cpuapp.dtsi index 1294203f00a..a6ae5d4a316 100644 --- a/dts/arm/nordic/nrf5340_cpuapp.dtsi +++ b/dts/arm/nordic/nrf5340_cpuapp.dtsi @@ -87,16 +87,11 @@ }; cryptocell: crypto@50844000 { - compatible = "nordic,nrf-cc312"; - reg = <0x50844000 0x1000>; + compatible = "nordic,cryptocell", "arm,cryptocell-312"; + reg = <0x50844000 0x1000>, <0x50845000 0x1000>; + reg-names = "wrapper", "core"; + interrupts = <68 NRF_DEFAULT_IRQ_PRIORITY>; status = "okay"; - #address-cells = <1>; - #size-cells = <1>; - cryptocell312: crypto@50845000 { - compatible = "arm,cryptocell-312"; - reg = <0x50845000 0x1000>; - interrupts = <68 NRF_DEFAULT_IRQ_PRIORITY>; - }; }; }; diff --git a/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi b/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi index 30e9b47bd82..e7aa0309f70 100644 --- a/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi +++ b/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi @@ -78,6 +78,7 @@ i2c0: i2c@8000 { reg = <0x8000 0x1000>; clock-frequency = ; interrupts = <8 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <16>; status = "disabled"; }; @@ -118,6 +119,7 @@ i2c1: i2c@9000 { reg = <0x9000 0x1000>; clock-frequency = ; interrupts = <9 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <16>; status = "disabled"; }; @@ -171,6 +173,7 @@ i2c2: i2c@b000 { reg = <0xb000 0x1000>; clock-frequency = ; interrupts = <11 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <16>; status = "disabled"; }; @@ -211,6 +214,7 @@ i2c3: i2c@c000 { reg = <0xc000 0x1000>; clock-frequency = ; interrupts = <12 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <16>; status = "disabled"; }; diff --git a/dts/arm/nordic/nrf91.dtsi b/dts/arm/nordic/nrf91.dtsi index a2a490ab0b1..23d2c7cf20e 100644 --- a/dts/arm/nordic/nrf91.dtsi +++ b/dts/arm/nordic/nrf91.dtsi @@ -48,16 +48,11 @@ /* Additional Secure peripherals */ cryptocell: crypto@50840000 { - compatible = "nordic,nrf-cc310"; - reg = <0x50840000 0x1000>; + compatible = "nordic,cryptocell", "arm,cryptocell-310"; + reg = <0x50840000 0x1000>, <0x50841000 0x1000>; + reg-names = "wrapper", "core"; + interrupts = <64 NRF_DEFAULT_IRQ_PRIORITY>; status = "okay"; - #address-cells = <1>; - #size-cells = <1>; - cryptocell310: crypto@50841000 { - compatible = "arm,cryptocell-310"; - reg = <0x50841000 0x1000>; - interrupts = <64 NRF_DEFAULT_IRQ_PRIORITY>; - }; }; ctrlap: ctrlap@50006000 { diff --git a/dts/arm/nordic/nrf91_peripherals.dtsi b/dts/arm/nordic/nrf91_peripherals.dtsi index bb456bc6349..2e437eb082d 100644 --- a/dts/arm/nordic/nrf91_peripherals.dtsi +++ b/dts/arm/nordic/nrf91_peripherals.dtsi @@ -158,6 +158,7 @@ i2c0: i2c@8000 { reg = <0x8000 0x1000>; clock-frequency = ; interrupts = <8 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <13>; status = "disabled"; }; @@ -173,6 +174,7 @@ i2c1: i2c@9000 { reg = <0x9000 0x1000>; clock-frequency = ; interrupts = <9 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <13>; status = "disabled"; }; @@ -188,6 +190,7 @@ i2c2: i2c@a000 { reg = <0xa000 0x1000>; clock-frequency = ; interrupts = <10 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <13>; status = "disabled"; }; @@ -203,6 +206,7 @@ i2c3: i2c@b000 { reg = <0xb000 0x1000>; clock-frequency = ; interrupts = <11 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <13>; status = "disabled"; }; diff --git a/dts/arm/nuvoton/m46x.dtsi b/dts/arm/nuvoton/m46x.dtsi index 2355a6fd82a..3e6efbb1745 100644 --- a/dts/arm/nuvoton/m46x.dtsi +++ b/dts/arm/nuvoton/m46x.dtsi @@ -428,6 +428,80 @@ #pwm-cells = <3>; status = "disabled"; }; + + canfd0: canfd@40020000 { + compatible = "nuvoton,numaker-canfd"; + reg = <0x40020000 0x200>, <0x40020200 0x1800>; + reg-names = "m_can", "message_ram"; + interrupts = <112 0>, <113 0>; + interrupt-names = "LINE_0", "LINE_1"; + resets = <&rst NUMAKER_CANFD0_RST>; + clocks = <&pcc NUMAKER_CANFD0_MODULE + NUMAKER_CLK_CLKSEL0_CANFD0SEL_HCLK + NUMAKER_CLK_CLKDIV5_CANFD0(1)>; + bosch,mram-cfg = <0x0 12 10 3 3 3 3 3>; + status = "disabled"; + sample-point = <875>; + sample-point-data = <875>; + }; + + canfd1: canfd@40024000 { + compatible = "nuvoton,numaker-canfd"; + reg = <0x40024000 0x200>, <0x40024200 0x1800>; + reg-names = "m_can", "message_ram"; + interrupts = <114 0>, <115 0>; + interrupt-names = "LINE_0", "LINE_1"; + resets = <&rst NUMAKER_CANFD1_RST>; + clocks = <&pcc NUMAKER_CANFD1_MODULE + NUMAKER_CLK_CLKSEL0_CANFD1SEL_HCLK + NUMAKER_CLK_CLKDIV5_CANFD1(1)>; + bosch,mram-cfg = <0x0 12 10 3 3 3 3 3>; + status = "disabled"; + sample-point = <875>; + sample-point-data = <875>; + }; + + canfd2: canfd@40028000 { + compatible = "nuvoton,numaker-canfd"; + reg = <0x40028000 0x200>, <0x40028200 0x1800>; + reg-names = "m_can", "message_ram"; + interrupts = <120 0>, <121 0>; + interrupt-names = "LINE_0", "LINE_1"; + resets = <&rst NUMAKER_CANFD2_RST>; + clocks = <&pcc NUMAKER_CANFD2_MODULE + NUMAKER_CLK_CLKSEL0_CANFD2SEL_HCLK + NUMAKER_CLK_CLKDIV5_CANFD2(1)>; + bosch,mram-cfg = <0x0 12 10 3 3 3 3 3>; + status = "disabled"; + sample-point = <875>; + sample-point-data = <875>; + }; + + canfd3: canfd@4002c000 { + compatible = "nuvoton,numaker-canfd"; + reg = <0x4002c000 0x200>, <0x4002c200 0x1800>; + reg-names = "m_can", "message_ram"; + interrupts = <122 0>, <123 0>; + interrupt-names = "LINE_0", "LINE_1"; + resets = <&rst NUMAKER_CANFD3_RST>; + clocks = <&pcc NUMAKER_CANFD3_MODULE + NUMAKER_CLK_CLKSEL0_CANFD3SEL_HCLK + NUMAKER_CLK_CLKDIV5_CANFD3(1)>; + bosch,mram-cfg = <0x0 12 10 3 3 3 3 3>; + status = "disabled"; + sample-point = <875>; + sample-point-data = <875>; + }; + + emac: ethernet@40012000 { + compatible = "nuvoton,numaker-ethernet"; + reg = <0x40012000 0x105C>; + interrupts = <66 0>; + resets = <&rst NUMAKER_EMAC0_RST>; + phy-addr = <1>; + clocks = <&pcc NUMAKER_EMAC0_MODULE 0 0>; + status = "disabled"; + }; }; }; diff --git a/dts/arm/nuvoton/npcx/npcx.dtsi b/dts/arm/nuvoton/npcx/npcx.dtsi index 46abbb44e87..c1a77c4fe69 100644 --- a/dts/arm/nuvoton/npcx/npcx.dtsi +++ b/dts/arm/nuvoton/npcx/npcx.dtsi @@ -350,6 +350,7 @@ reg = <0x400d1000 0x2000>; interrupts = <10 3>; clocks = <&pcc NPCX_CLOCK_BUS_APB1 NPCX_PWDWN_CTL4 4>; + vref-mv = <2816>; status = "disabled"; }; diff --git a/dts/arm/nuvoton/npcx/npcx4.dtsi b/dts/arm/nuvoton/npcx/npcx4.dtsi index cbad55d0df3..a01d5d69abf 100644 --- a/dts/arm/nuvoton/npcx/npcx4.dtsi +++ b/dts/arm/nuvoton/npcx/npcx4.dtsi @@ -59,6 +59,8 @@ }; soc { + compatible = "nuvoton,npcx4", "nuvoton,npcx", "simple-bus"; + /* Specific soc devices in npcx4 series */ itims: timer@400b0000 { compatible = "nuvoton,npcx-itim-timer"; @@ -257,10 +259,22 @@ /* ADC0 comparator configuration in npcx4 series */ adc0: adc@400d1000 { channel-count = <26>; - threshold-reg-offset = <0x80>; threshold-count = <6>; }; + /* ADC1 which reference voltage is AVCC */ + adc1: adc@400d5000 { + compatible = "nuvoton,npcx-adc"; + #io-channel-cells = <1>; + reg = <0x400d5000 0x2000>; + interrupts = <22 3>; + clocks = <&pcc NPCX_CLOCK_BUS_APB1 NPCX_PWDWN_CTL4 3>; + vref-mv = <3300>; + channel-count = <26>; + threshold-count = <6>; + status = "disabled"; + }; + /* FIU0 configuration in npcx4 series */ qspi_fiu0: quadspi@40020000 { clocks = <&pcc NPCX_CLOCK_BUS_FIU0 NPCX_PWDWN_CTL8 5>; @@ -278,6 +292,7 @@ sha0: sha@13c { compatible = "nuvoton,npcx-sha"; reg = <0x13c 0x3c>; + context-buffer-size = <228>; status = "disabled"; }; }; @@ -303,6 +318,7 @@ }; soc-id { + family-id = <0x23>; chip-id = <0x0a>; revision-reg = <0x0000FFFC 4>; }; diff --git a/dts/arm/nuvoton/npcx/npcx7.dtsi b/dts/arm/nuvoton/npcx/npcx7.dtsi index 7181592c84c..529d5bdef35 100644 --- a/dts/arm/nuvoton/npcx/npcx7.dtsi +++ b/dts/arm/nuvoton/npcx/npcx7.dtsi @@ -57,6 +57,8 @@ }; soc { + compatible = "nuvoton,npcx7", "nuvoton,npcx", "simple-bus"; + /* Specific soc devices in npcx7 series */ itims: timer@400bc000 { compatible = "nuvoton,npcx-itim-timer"; @@ -235,7 +237,6 @@ /* ADC0 comparator configuration in npcx7 series */ adc0: adc@400d1000 { channel-count = <10>; - threshold-reg-offset = <0x14>; threshold-count = <3>; }; diff --git a/dts/arm/nuvoton/npcx/npcx9.dtsi b/dts/arm/nuvoton/npcx/npcx9.dtsi index 14b74e6c262..4d0cb7dc69e 100644 --- a/dts/arm/nuvoton/npcx/npcx9.dtsi +++ b/dts/arm/nuvoton/npcx/npcx9.dtsi @@ -58,6 +58,8 @@ }; soc { + compatible = "nuvoton,npcx9", "nuvoton,npcx", "simple-bus"; + /* Specific soc devices in npcx9 series */ itims: timer@400b0000 { compatible = "nuvoton,npcx-itim-timer"; @@ -256,7 +258,6 @@ /* ADC0 comparator configuration in npcx9 series */ adc0: adc@400d1000 { channel-count = <12>; - threshold-reg-offset = <0x60>; threshold-count = <6>; }; @@ -268,6 +269,7 @@ sha0: sha@13c { compatible = "nuvoton,npcx-sha"; reg = <0x13c 0x3c>; + context-buffer-size = <212>; status = "disabled"; }; }; diff --git a/dts/arm/nuvoton/npcx4m3f.dtsi b/dts/arm/nuvoton/npcx4m3f.dtsi index 327e8754c77..334cd2db653 100644 --- a/dts/arm/nuvoton/npcx4m3f.dtsi +++ b/dts/arm/nuvoton/npcx4m3f.dtsi @@ -22,7 +22,7 @@ }; soc-id { - device-id = <0x2d>; + device-id = <0x25>; }; }; diff --git a/dts/arm/nuvoton/npcx4m8f.dtsi b/dts/arm/nuvoton/npcx4m8f.dtsi index 9baf3c255f9..ac141ab31b9 100644 --- a/dts/arm/nuvoton/npcx4m8f.dtsi +++ b/dts/arm/nuvoton/npcx4m8f.dtsi @@ -22,7 +22,7 @@ }; soc-id { - device-id = <0x2b>; + device-id = <0x23>; }; }; diff --git a/dts/arm/nxp/nxp_imx8ml_m7.dtsi b/dts/arm/nxp/nxp_imx8ml_m7.dtsi index 4afe8e138a6..f9406fc7546 100644 --- a/dts/arm/nxp/nxp_imx8ml_m7.dtsi +++ b/dts/arm/nxp/nxp_imx8ml_m7.dtsi @@ -155,10 +155,6 @@ status = "disabled"; }; - /* - * For now only UART4 is supported and - * tested with the serial driver - */ uart4: uart@30a60000 { compatible = "nxp,imx-iuart"; reg = <0x30a60000 0x10000>; @@ -167,6 +163,14 @@ status = "disabled"; }; + uart1: uart@30860000 { + compatible = "nxp,imx-iuart"; + reg = <0x30860000 0x10000>; + interrupts = <26 3>; + clocks = <&ccm IMX_CCM_UART1_CLK 0x7c 24>; + status = "disabled"; + }; + mailbox0: mailbox@30ab0000 { compatible = "nxp,imx-mu"; reg = <0x30ab0000 DT_SIZE_K(64)>; diff --git a/dts/arm/nxp/nxp_k66.dtsi b/dts/arm/nxp/nxp_k66.dtsi index 6ee4f202f44..2c2470fcf88 100644 --- a/dts/arm/nxp/nxp_k66.dtsi +++ b/dts/arm/nxp/nxp_k66.dtsi @@ -31,7 +31,6 @@ "rx-warning", "wake-up"; clocks = <&sim KINETIS_SIM_BUS_CLK 0x1030 4>; clk-source = <1>; - sjw = <1>; sample-point = <875>; status = "disabled"; }; diff --git a/dts/arm/nxp/nxp_k6x.dtsi b/dts/arm/nxp/nxp_k6x.dtsi index 91a5a2e32e1..909e07e3792 100644 --- a/dts/arm/nxp/nxp_k6x.dtsi +++ b/dts/arm/nxp/nxp_k6x.dtsi @@ -504,7 +504,6 @@ interrupt-names = "mb-0-15", "bus-off", "error", "tx-warning", "rx-warning", "wake-up"; clocks = <&sim KINETIS_SIM_BUS_CLK 0x103C 4>; clk-source = <1>; - sjw = <1>; sample-point = <875>; status = "disabled"; }; @@ -535,7 +534,7 @@ status = "disabled"; pit-channel = <0>; pit-period = <1000000>; - clock-frequency = <60000000>; + max-load-value = <0xffffffff>; }; }; }; diff --git a/dts/arm/nxp/nxp_k8x.dtsi b/dts/arm/nxp/nxp_k8x.dtsi index effa5b0c37c..61e0cd1fc39 100644 --- a/dts/arm/nxp/nxp_k8x.dtsi +++ b/dts/arm/nxp/nxp_k8x.dtsi @@ -394,7 +394,7 @@ status = "disabled"; pit-channel = <0>; pit-period = <1000000>; - clock-frequency = <60000000>; + max-load-value = <0xffffffff>; }; edma0: dma-controller@40008000 { diff --git a/dts/arm/nxp/nxp_ke1xf.dtsi b/dts/arm/nxp/nxp_ke1xf.dtsi index e0ad94d0894..0a834b2b67f 100644 --- a/dts/arm/nxp/nxp_ke1xf.dtsi +++ b/dts/arm/nxp/nxp_ke1xf.dtsi @@ -405,7 +405,6 @@ "mb-0-15"; clocks = <&scg KINETIS_SCG_BUS_CLK>; clk-source = <1>; - sjw = <1>; sample-point = <875>; status = "disabled"; }; @@ -418,7 +417,6 @@ "mb-0-15"; clocks = <&scg KINETIS_SCG_BUS_CLK>; clk-source = <1>; - sjw = <1>; sample-point = <875>; status = "disabled"; }; diff --git a/dts/arm/nxp/nxp_lpc51u68.dtsi b/dts/arm/nxp/nxp_lpc51u68.dtsi index 751cd17705f..964e863485b 100644 --- a/dts/arm/nxp/nxp_lpc51u68.dtsi +++ b/dts/arm/nxp/nxp_lpc51u68.dtsi @@ -152,6 +152,7 @@ reg = <0x40085000 0x1000>; status = "disabled"; interrupts = <12 0>; + clocks = <&syscon MCUX_SCTIMER_CLK>; prescaler = <1>; #pwm-cells = <3>; }; diff --git a/dts/arm/nxp/nxp_lpc55S0x_common.dtsi b/dts/arm/nxp/nxp_lpc55S0x_common.dtsi index 9f7abe6169b..ca7a25b765e 100644 --- a/dts/arm/nxp/nxp_lpc55S0x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S0x_common.dtsi @@ -223,9 +223,7 @@ interrupts = <43 0>, <44 0>; clocks = <&syscon MCUX_MCAN_CLK>; bosch,mram-cfg = <0x0 15 15 8 8 0 15 15>; - sjw = <1>; sample-point = <875>; - sjw-data = <1>; sample-point-data = <875>; status = "disabled"; }; diff --git a/dts/arm/nxp/nxp_lpc55S1x_common.dtsi b/dts/arm/nxp/nxp_lpc55S1x_common.dtsi index bbd71e2afa1..76d551555ef 100644 --- a/dts/arm/nxp/nxp_lpc55S1x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S1x_common.dtsi @@ -8,6 +8,7 @@ #include #include #include +#include #include / { @@ -61,7 +62,7 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x20010000 DT_SIZE_K(16)>; zephyr,memory-region = "USB_SRAM"; - zephyr,memory-attr = "RAM"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; }; @@ -217,9 +218,7 @@ interrupts = <43 0>, <44 0>; clocks = <&syscon MCUX_MCAN_CLK>; bosch,mram-cfg = <0x0 15 15 8 8 0 15 15>; - sjw = <1>; sample-point = <875>; - sjw-data = <1>; sample-point-data = <875>; status = "disabled"; }; @@ -241,11 +240,10 @@ }; usbhs: usbhs@144000 { - compatible = "nxp,mcux-usbd"; + compatible = "nxp,lpcip3511"; reg = <0x94000 0x1000>; interrupts = <47 1>; num-bidir-endpoints = <6>; - usb-controller-index = "LpcIp3511Hs0"; status = "disabled"; }; }; diff --git a/dts/arm/nxp/nxp_lpc55S2x_common.dtsi b/dts/arm/nxp/nxp_lpc55S2x_common.dtsi index 1e9222f5d07..16d9c1312c3 100644 --- a/dts/arm/nxp/nxp_lpc55S2x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S2x_common.dtsi @@ -9,6 +9,7 @@ #include #include #include +#include #include / { @@ -75,7 +76,7 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x40100000 DT_SIZE_K(16)>; zephyr,memory-region = "USB_SRAM"; - zephyr,memory-attr = "RAM"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; }; @@ -283,11 +284,10 @@ }; usbhs: usbhs@144000 { - compatible = "nxp,mcux-usbd"; + compatible = "nxp,lpcip3511"; reg = <0x94000 0x1000>; interrupts = <47 1>; num-bidir-endpoints = <6>; - usb-controller-index = "LpcIp3511Hs0"; status = "disabled"; }; }; diff --git a/dts/arm/nxp/nxp_lpc55S3x_common.dtsi b/dts/arm/nxp/nxp_lpc55S3x_common.dtsi index 51243bcb88e..dd011ece96d 100644 --- a/dts/arm/nxp/nxp_lpc55S3x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S3x_common.dtsi @@ -292,6 +292,34 @@ #io-channel-cells = <1>; dmas = <&dma0 21>, <&dma0 22>; dma-names = "adc0-dma0", "adc0-dma1"; + nxp,reference-supply = <&vref0>; + }; + + dac0: dac@b2000 { + compatible = "nxp,lpdac"; + reg = < 0xb2000 0x1000>; + interrupts = <74 0>; + status = "disabled"; + voltage-reference = <0>; + #io-channel-cells = <1>; + }; + + dac1: dac@b6000 { + compatible = "nxp,lpdac"; + reg = < 0xb6000 0x1000>; + interrupts = <75 0>; + status = "disabled"; + voltage-reference = <0>; + #io-channel-cells = <1>; + }; + + dac2: dac@b9000 { + compatible = "nxp,lpdac"; + reg = < 0xb9000 0x1000>; + interrupts = <76 0>; + status = "disabled"; + voltage-reference = <0>; + #io-channel-cells = <1>; }; can0: can@4009d000 { @@ -300,9 +328,7 @@ interrupts = <43 0>, <44 0>; clocks = <&syscon MCUX_MCAN_CLK>; bosch,mram-cfg = <0x0 15 15 8 8 0 15 15>; - sjw = <1>; sample-point = <875>; - sjw-data = <1>; sample-point-data = <875>; status = "disabled"; }; @@ -417,12 +443,11 @@ }; usbfs: usbfs@84000 { - compatible = "nxp,mcux-usbd"; + compatible = "nxp,lpcip3511"; reg = <0x84000 0x1000>; interrupts = <28 0>; num-bidir-endpoints = <5>; maximum-speed = "full-speed"; - usb-controller-index = "LpcIp3511Fs0"; status = "disabled"; }; @@ -431,9 +456,19 @@ reg = <0x85000 0x1000>; interrupts = <12 0>; status = "disabled"; + clocks = <&syscon MCUX_SCTIMER_CLK 0 0>; prescaler = <2>; #pwm-cells = <3>; }; + + vref0: vref@b5000 { + compatible = "nxp,vref"; + regulator-name = "lpc55s36-vref"; + reg = <0xb5000 0x30>; + status = "disabled"; + nxp,buffer-startup-delay-us = <400>; + nxp,bandgap-startup-time-us = <20>; + }; }; &nvic { diff --git a/dts/arm/nxp/nxp_lpc55S6x_common.dtsi b/dts/arm/nxp/nxp_lpc55S6x_common.dtsi index 1a727654e1a..5095a96738f 100644 --- a/dts/arm/nxp/nxp_lpc55S6x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S6x_common.dtsi @@ -10,6 +10,7 @@ #include #include #include +#include #include / { @@ -95,7 +96,7 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x100000 DT_SIZE_K(16)>; zephyr,memory-region = "USB_SRAM"; - zephyr,memory-attr = "RAM"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; syscon: syscon@0 { @@ -324,21 +325,19 @@ }; usbfs: usbfs@84000 { - compatible = "nxp,mcux-usbd"; + compatible = "nxp,lpcip3511"; reg = <0x84000 0x1000>; interrupts = <28 1>; num-bidir-endpoints = <5>; maximum-speed = "full-speed"; - usb-controller-index = "LpcIp3511Fs0"; status = "disabled"; }; usbhs: usbhs@94000 { - compatible = "nxp,mcux-usbd"; + compatible = "nxp,lpcip3511"; reg = <0x94000 0x1000>; interrupts = <47 1>; num-bidir-endpoints = <6>; - usb-controller-index = "LpcIp3511Hs0"; status = "disabled"; }; @@ -407,9 +406,42 @@ reg = <0x85000 0x1000>; interrupts = <12 0>; status = "disabled"; + clocks = <&syscon MCUX_SCTIMER_CLK>; prescaler = <2>; #pwm-cells = <3>; }; + + mrt: mrt@d000 { + compatible = "nxp,mrt"; + reg = <0xd000 0x100>; + interrupts = <9 0>; + num-channels = <4>; + num-bits = <24>; + clocks = <&syscon MCUX_MRT_CLK>; + #address-cells = <1>; + #size-cells = <0>; + + mrt_channel0: mrt_channel@0 { + compatible = "nxp,mrt-channel"; + reg = <0>; + status = "disabled"; + }; + mrt_channel1: mrt_channel@1 { + compatible = "nxp,mrt-channel"; + reg = <1>; + status = "disabled"; + }; + mrt_channel2: mrt_channel@2 { + compatible = "nxp,mrt-channel"; + reg = <2>; + status = "disabled"; + }; + mrt_channel3: mrt_channel@3 { + compatible = "nxp,mrt-channel"; + reg = <3>; + status = "disabled"; + }; + }; }; &nvic { diff --git a/dts/arm/nxp/nxp_rt1010.dtsi b/dts/arm/nxp/nxp_rt1010.dtsi index 00b1ce14b4e..84d47e0f35e 100644 --- a/dts/arm/nxp/nxp_rt1010.dtsi +++ b/dts/arm/nxp/nxp_rt1010.dtsi @@ -6,6 +6,15 @@ #include +&flexram { + flexram,num-ram-banks = <4>; + /* default fuse */ + flexram,bank-spec = , + , + , + ; +}; + &sysclk { clock-frequency = <500000000>; }; @@ -234,13 +243,12 @@ /* Fixup USB it has different base addr and interrupt numbers on RT1010 */ /delete-node/ usbd@402e0000; usb1: usbd@400e4000 { - compatible = "nxp,mcux-usbd"; + compatible = "nxp,ehci"; reg = <0x400e4000 0x200>; interrupts = <25 1>; interrupt-names = "usb_otg"; clocks = <&usbclk>; num-bidir-endpoints = <8>; - usb-controller-index = "Ehci0"; status = "disabled"; }; @@ -272,6 +280,8 @@ #pinmux-cells = <2>; reg = <0x401e0000 0x4000>; clocks = <&ccm IMX_CCM_SAI1_CLK 0x7C 18>; + /* Source clock from Audio PLL */ + clock-mux = <2>; /* Audio PLL Output Frequency is determined by: * (Fref * (DIV_SELECT + NUM/DENOM)) / POST_DIV * = (24MHz * (32 + 77 / 100)) / 1 = 786.48 MHz @@ -310,6 +320,8 @@ #pinmux-cells = <2>; reg = <0x401e8000 0x4000>; clocks = <&ccm IMX_CCM_SAI3_CLK 0x7C 22>; + /* Source clock from Audio PLL */ + clock-mux = <2>; pre-div = <0>; podf = <63>; pll-clocks = <&anatop 0x70 0xC000 0>, diff --git a/dts/arm/nxp/nxp_rt1015.dtsi b/dts/arm/nxp/nxp_rt1015.dtsi index 05aeeb86be1..59c62eb4452 100644 --- a/dts/arm/nxp/nxp_rt1015.dtsi +++ b/dts/arm/nxp/nxp_rt1015.dtsi @@ -7,6 +7,15 @@ #include +&flexram { + flexram,num-ram-banks = <4>; + /* default fuse */ + flexram,bank-spec = , + , + , + ; +}; + &sysclk { clock-frequency = <500000000>; }; diff --git a/dts/arm/nxp/nxp_rt1020.dtsi b/dts/arm/nxp/nxp_rt1020.dtsi index 6b2a26f5242..b42a17960fa 100644 --- a/dts/arm/nxp/nxp_rt1020.dtsi +++ b/dts/arm/nxp/nxp_rt1020.dtsi @@ -7,6 +7,19 @@ #include +&flexram { + flexram,num-ram-banks = <8>; + /* default fuse */ + flexram,bank-spec = , + , + , + , + , + , + , + ; +}; + &sysclk { clock-frequency = <500000000>; }; diff --git a/dts/arm/nxp/nxp_rt1024.dtsi b/dts/arm/nxp/nxp_rt1024.dtsi index c8332df17e0..62262bb2118 100644 --- a/dts/arm/nxp/nxp_rt1024.dtsi +++ b/dts/arm/nxp/nxp_rt1024.dtsi @@ -7,6 +7,19 @@ #include +&flexram { + flexram,num-ram-banks = <8>; + /* default fuse */ + flexram,bank-spec = , + , + , + , + , + , + , + ; +}; + &sysclk { clock-frequency = <500000000>; }; diff --git a/dts/arm/nxp/nxp_rt1040.dtsi b/dts/arm/nxp/nxp_rt1040.dtsi index 110680f44a7..c4aa2d57891 100644 --- a/dts/arm/nxp/nxp_rt1040.dtsi +++ b/dts/arm/nxp/nxp_rt1040.dtsi @@ -6,6 +6,10 @@ #include +&flexram { + flexram,num-ram-banks = <16>; +}; + &sysclk { clock-frequency = <500000000>; }; diff --git a/dts/arm/nxp/nxp_rt1050.dtsi b/dts/arm/nxp/nxp_rt1050.dtsi index 16b2669b416..0a66b9b791e 100644 --- a/dts/arm/nxp/nxp_rt1050.dtsi +++ b/dts/arm/nxp/nxp_rt1050.dtsi @@ -5,6 +5,27 @@ */ #include +&flexram { + flexram,num-ram-banks = <16>; + /* default fuse */ + flexram,bank-spec = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; +}; + &ccm { arm-podf { clock-div = <2>; diff --git a/dts/arm/nxp/nxp_rt1060.dtsi b/dts/arm/nxp/nxp_rt1060.dtsi index 62e01a5f609..8a9cba715e0 100644 --- a/dts/arm/nxp/nxp_rt1060.dtsi +++ b/dts/arm/nxp/nxp_rt1060.dtsi @@ -6,14 +6,33 @@ #include -/* i.MX rt1060 has two continuous on-chip RAM, one is part of the - * FlexRAM mapped at 0x20280000 (vs 0x20280000 on rt1050) and is - * configurable (256KB by defaults), the other one is dedicated 512KB - * ram (OCRAM2) mapped at 0x20200000. In order to have a continuous - * region, we describe them in one 768Kb unique node. - */ -&ocram { - reg = <0x20200000 DT_SIZE_K(768)>; +&flexram { + /* FlexRAM OCRAM is at a different address on RT1060 */ + /delete-node/ ocram@20200000; + ocram: ocram@20280000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x20280000 DT_SIZE_K(256)>; + zephyr,memory-region = "OCRAM"; + }; + + flexram,num-ram-banks = <16>; + /* default fuse */ + flexram,bank-spec = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; }; &ccm { @@ -26,9 +45,9 @@ }; }; -/* i.MX rt1060 has a second Ethernet controller. */ / { soc { + /* i.MX rt1060 has a second Ethernet controller. */ enet2: ethernet@402d4000 { compatible = "nxp,kinetis-ethernet"; reg = <0x402D4000 0x628>; @@ -42,6 +61,13 @@ interrupt-names = "IEEE1588_TMR"; }; }; + + /* RT1060 has a dedicated OCRAM region */ + ocram2: ocram@20200000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x20200000 DT_SIZE_K(512)>; + zephyr,memory-region = "OCRAM2"; + }; }; }; diff --git a/dts/arm/nxp/nxp_rt1064.dtsi b/dts/arm/nxp/nxp_rt1064.dtsi index fcb909e0cfc..73ed8827738 100644 --- a/dts/arm/nxp/nxp_rt1064.dtsi +++ b/dts/arm/nxp/nxp_rt1064.dtsi @@ -7,6 +7,27 @@ #include +&flexram { + flexram,num-ram-banks = <16>; + /* default fuse */ + flexram,bank-spec = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; +}; + &flexspi2 { status = "okay"; reg = <0x402a4000 0x4000>, <0x70000000 DT_SIZE_M(4)>; diff --git a/dts/arm/nxp/nxp_rt10xx.dtsi b/dts/arm/nxp/nxp_rt10xx.dtsi index 6e4f6278fae..e7e4e6448b2 100644 --- a/dts/arm/nxp/nxp_rt10xx.dtsi +++ b/dts/arm/nxp/nxp_rt10xx.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, NXP + * Copyright 2017,2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,6 +11,7 @@ #include #include #include +#include / { chosen { @@ -87,13 +88,17 @@ soc { flexram: flexram@400b0000 { - compatible = "nxp,imx-flexram"; + compatible = "nxp,flexram"; reg = <0x400b0000 0x4000>; interrupts = <38 0>; #address-cells = <1>; #size-cells = <1>; + status = "okay"; + + flexram,bank-size = <32>; + itcm: itcm@0 { compatible = "zephyr,memory-region", "nxp,imx-itcm"; reg = <0x00000000 DT_SIZE_K(128)>; @@ -790,24 +795,22 @@ }; usb1: usbd@402e0000 { - compatible = "nxp,mcux-usbd"; + compatible = "nxp,ehci"; reg = <0x402E0000 0x200>; interrupts = <113 1>; interrupt-names = "usb_otg"; clocks = <&usbclk>; num-bidir-endpoints = <8>; - usb-controller-index = "Ehci0"; status = "disabled"; }; usb2: usbd@402e0200 { - compatible = "nxp,mcux-usbd"; + compatible = "nxp,ehci"; reg = <0x402E0200 0x200>; interrupts = <112 1>; interrupt-names = "usb_otg"; clocks = <&usbclk>; num-bidir-endpoints = <8>; - usb-controller-index = "Ehci1"; status = "disabled"; }; @@ -856,6 +859,7 @@ <8 0>, <9 0>, <10 0>, <11 0>, <12 0>, <13 0>, <14 0>, <15 0>, <16 0>; + irq-shared-offset = <16>; clocks = <&ccm IMX_CCM_EDMA_CLK 0x7C 0x000000C0>; status = "disabled"; }; @@ -867,7 +871,6 @@ interrupt-names = "common"; clocks = <&ccm IMX_CCM_CAN_CLK 0x68 14>; clk-source = <2>; - sjw = <1>; sample-point = <875>; status = "disabled"; }; @@ -879,7 +882,6 @@ interrupt-names = "common"; clocks = <&ccm IMX_CCM_CAN_CLK 0x68 18>; clk-source = <2>; - sjw = <1>; sample-point = <875>; status = "disabled"; }; @@ -891,8 +893,6 @@ interrupt-names = "common"; clocks = <&ccm IMX_CCM_CAN_CLK 0x84 6>; clk-source = <2>; - sjw = <1>; - sjw-data = <1>; sample-point = <875>; sample-point-data = <875>; status = "disabled"; @@ -940,11 +940,13 @@ #pinmux-cells = <2>; reg = <0x40384000 0x4000>; clocks = <&ccm IMX_CCM_SAI1_CLK 0x7C 18>; + /* Source clock from Audio PLL */ + clock-mux = <2>; /* Audio PLL Output Frequency is determined by: * (Fref * (DIV_SELECT + NUM/DENOM)) / POST_DIV * = (24MHz * (32 + 77 / 100)) / 1 = 786.48 MHz */ - pll-clocks = <&anatop 0x70 0xC000 0>, + pll-clocks = <&anatop 0x70 0xC000 0>, <&anatop 0x70 0x7F 32>, <&anatop 0x70 0x180000 1>, <&anatop 0x80 0x3FFFFFFF 77>, @@ -978,6 +980,8 @@ #pinmux-cells = <2>; reg = <0x40388000 0x4000>; clocks = <&ccm IMX_CCM_SAI2_CLK 0x7C 20>; + /* Source clock from Audio PLL */ + clock-mux = <2>; pre-div = <0>; podf = <63>; pll-clocks = <&anatop 0x70 0xC000 0x0>, @@ -1003,6 +1007,8 @@ #pinmux-cells = <2>; reg = <0x4038C000 0x4000>; clocks = <&ccm IMX_CCM_SAI3_CLK 0x7C 22>; + /* Source clock from Audio PLL */ + clock-mux = <2>; pre-div = <0>; podf = <63>; pll-clocks = <&anatop 0x70 0xC000 0>, diff --git a/dts/arm/nxp/nxp_rt11xx.dtsi b/dts/arm/nxp/nxp_rt11xx.dtsi index b333816a2c8..eb14d37f834 100644 --- a/dts/arm/nxp/nxp_rt11xx.dtsi +++ b/dts/arm/nxp/nxp_rt11xx.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, NXP + * Copyright 2021,2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -619,7 +619,7 @@ reg = <0x40194000 0x4000>; interrupts = <186 0>; - flexpwm3_pwm0: pwm0 { + flexpwm3_pwm0: flexpwm3_pwm0 { compatible = "nxp,imx-pwm"; index = <0>; interrupts = <182 0>; @@ -749,24 +749,22 @@ }; usb1: usbd@40430000 { - compatible = "nxp,mcux-usbd"; + compatible = "nxp,ehci"; reg = <0x40430000 0x200>; interrupts = <136 1>; interrupt-names = "usb_otg"; clocks = <&xtal>; num-bidir-endpoints = <8>; - usb-controller-index = "Ehci0"; status = "disabled"; }; usb2: usbd@4042c000 { - compatible = "nxp,mcux-usbd"; + compatible = "nxp,ehci"; reg = <0x4042c000 0x200>; interrupts = <135 1>; interrupt-names = "usb_otg"; clocks = <&xtal>; num-bidir-endpoints = <8>; - usb-controller-index = "Ehci1"; status = "disabled"; }; @@ -808,8 +806,6 @@ interrupt-names = "common", "error"; clocks = <&ccm IMX_CCM_CAN1_CLK 0x68 14>; clk-source = <0>; - sjw = <1>; - sjw-data = <1>; sample-point = <875>; sample-point-data = <875>; status = "disabled"; @@ -822,8 +818,6 @@ interrupt-names = "common", "error"; clocks = <&ccm IMX_CCM_CAN2_CLK 0x68 18>; clk-source = <0>; - sjw = <1>; - sjw-data = <1>; sample-point = <875>; sample-point-data = <875>; status = "disabled"; @@ -836,8 +830,6 @@ interrupt-names = "common", "error"; clocks = <&ccm IMX_CCM_CAN3_CLK 0x84 6>; clk-source = <0>; - sjw = <1>; - sjw-data = <1>; sample-point = <875>; sample-point-data = <875>; status = "disabled"; @@ -953,6 +945,7 @@ <8 0>, <9 0>, <10 0>, <11 0>, <12 0>, <13 0>, <14 0>, <15 0>, <16 0>; + irq-shared-offset = <16>; }; edma_lpsr0: dma-controller@40c14000 { @@ -971,6 +964,7 @@ <8 0>, <9 0>, <10 0>, <11 0>, <12 0>, <13 0>, <14 0>, <15 0>, <16 0>; + irq-shared-offset = <16>; }; pxp: pxp@40814000 { @@ -994,6 +988,8 @@ #pinmux-cells = <2>; reg = <0x40404000 0x4000>; clocks = <&ccm IMX_CCM_SAI1_CLK 0x2004 4>; + /* Source from audio PLL */ + clock-mux = <4>; pre-div = <0>; podf = <4>; pll-clocks = <&anatop 0 0 0>, @@ -1015,6 +1011,8 @@ #pinmux-cells = <2>; reg = <0x40408000 0x4000>; clocks = <&ccm IMX_CCM_SAI2_CLK 0x2084 4>; + /* Source from audio PLL */ + clock-mux = <4>; pre-div = <0>; podf = <63>; pll-clocks = <&anatop 0 0 0>, @@ -1036,6 +1034,8 @@ #pinmux-cells = <2>; reg = <0x4040c000 0x4000>; clocks = <&ccm IMX_CCM_SAI3_CLK 0x2104 4>; + /* Source from audio PLL */ + clock-mux = <4>; pre-div = <0>; podf = <63>; pll-clocks = <&anatop 0 0 0>, @@ -1057,6 +1057,8 @@ #pinmux-cells = <2>; reg = <0x40c40000 0x4000>; clocks = <&ccm IMX_CCM_SAI4_CLK 0x2184 6>; + /* Source from audio PLL */ + clock-mux = <6>; pre-div = <0>; podf = <63>; pll-clocks = <&anatop 0 0 0>, diff --git a/dts/arm/nxp/nxp_rt11xx_cm4.dtsi b/dts/arm/nxp/nxp_rt11xx_cm4.dtsi index 1348bba3002..4fab1c307f3 100644 --- a/dts/arm/nxp/nxp_rt11xx_cm4.dtsi +++ b/dts/arm/nxp/nxp_rt11xx_cm4.dtsi @@ -54,7 +54,7 @@ }; mailbox_b: mailbox@40c4c000 { - compatible = "nxp,imx-mu-rev2"; + compatible = "nxp,imx-mu"; reg = <0x40c4c000 0x4000>; interrupts = <118 0>; rdc = <0>; diff --git a/dts/arm/nxp/nxp_rt11xx_cm7.dtsi b/dts/arm/nxp/nxp_rt11xx_cm7.dtsi index 63a7fc78319..88d1035ddc3 100644 --- a/dts/arm/nxp/nxp_rt11xx_cm7.dtsi +++ b/dts/arm/nxp/nxp_rt11xx_cm7.dtsi @@ -1,10 +1,11 @@ /* - * Copyright (c) 2021, NXP + * Copyright 2021-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ #include +#include / { cpus { @@ -22,12 +23,35 @@ /delete-node/ dma-controller@40c14000; flexram: flexram@40028000 { + compatible = "nxp,flexram"; + reg = <0x40028000 0x4000>; interrupts = <50 0>; #address-cells = <1>; #size-cells = <1>; + flexram,bank-size = <32>; + flexram,num-ram-banks = <16>; + flexram,has-magic-addr; + /* same as default fuse value */ + flexram,bank-spec = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + itcm: itcm@0 { compatible = "zephyr,memory-region", "nxp,imx-itcm"; reg = <0x00000000 DT_SIZE_K(256)>; @@ -39,6 +63,8 @@ reg = <0x20000000 DT_SIZE_K(256)>; zephyr,memory-region = "DTCM"; }; + + /* no ocram node for this bank-spec */ }; /* @@ -77,7 +103,7 @@ }; mailbox_a: mailbox@40c48000 { - compatible = "nxp,imx-mu-rev2"; + compatible = "nxp,imx-mu"; reg = <0x40c48000 0x4000>; interrupts = <118 0>; rdc = <0>; diff --git a/dts/arm/nxp/nxp_rt5xx.dtsi b/dts/arm/nxp/nxp_rt5xx.dtsi index 3391ed2f33f..931f5afb422 100644 --- a/dts/arm/nxp/nxp_rt5xx.dtsi +++ b/dts/arm/nxp/nxp_rt5xx.dtsi @@ -8,8 +8,9 @@ / { soc { - sram: sram@30018000 { - ranges = <0x20180000 0x30180000 0x300000>; + sram: sram@30000000 { + ranges = <0x0 0x10000000 0x500000 + 0x20000000 0x30000000 0x500000>; }; peripheral: peripheral@50000000 { diff --git a/dts/arm/nxp/nxp_rt5xx_common.dtsi b/dts/arm/nxp/nxp_rt5xx_common.dtsi index d7348758378..8a1a1aa3c3d 100644 --- a/dts/arm/nxp/nxp_rt5xx_common.dtsi +++ b/dts/arm/nxp/nxp_rt5xx_common.dtsi @@ -12,6 +12,7 @@ #include #include #include +#include / { chosen { @@ -69,6 +70,20 @@ #address-cells = <1>; #size-cells = <1>; + /* RT5XX SRAM partitions are shared + * between code and data. Boards can + * override the reg properties of either sram0 or sram_code nodes to + * change the balance of SRAM allocation. + * + * Note that the sram code region starts at an offset of 0x1B000, + * as the boot ROM will not load code before 0x1C000. The first + * 0x1000 of the image will contain the boot header. + */ + sram_code: memory@1b000 { + compatible = "mmio-sram"; + reg = <0x1b000 DT_SIZE_K(1428)>; + }; + sram0: memory@20180000 { compatible = "mmio-sram"; reg = <0x20180000 DT_SIZE_K(3072)>; @@ -78,7 +93,7 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x40140000 DT_SIZE_K(16)>; zephyr,memory-region = "SRAM1"; - zephyr,memory-attr = "RAM"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; }; @@ -323,11 +338,10 @@ }; usbhs: usbhs@144000 { - compatible = "nxp,mcux-usbd"; + compatible = "nxp,lpcip3511"; reg = <0x144000 0x1000>; interrupts = <50 1>; num-bidir-endpoints = <6>; - usb-controller-index = "LpcIp3511Hs0"; status = "disabled"; }; @@ -403,6 +417,7 @@ status = "disabled"; prescaler = <8>; #pwm-cells = <3>; + clocks = <&clkctl1 MCUX_SCTIMER_CLK>; }; wwdt0: watchdog@e000 { @@ -460,6 +475,15 @@ #io-channel-cells = <1>; }; + smartdma: dma@27020 { + compatible = "nxp,smartdma"; + reg = <0x27020 0x1000>; + program-mem = <0x24100000>; + interrupts = <73 0>; + status = "disabled"; + #dma-cells = <0>; + }; + ctimer0: ctimer@28000 { compatible = "nxp,lpc-ctimer"; reg = <0x28000 0x1000>; @@ -545,6 +569,47 @@ #address-cells = <3>; #size-cells = <0>; }; + + mbox:mbox@110000 { + compatible = "nxp,mbox-imx-mu"; + reg = <0x110000 0x100>; + interrupts = <34 0>; + rx-channels = <4>; + #mbox-cells = <1>; + status = "disabled"; + }; + + mrt: mrt@2d000 { + compatible = "nxp,mrt"; + reg = <0x2d000 0x100>; + interrupts = <9 0>; + num-channels = <4>; + num-bits = <24>; + clocks = <&clkctl1 MCUX_MRT_CLK>; + #address-cells = <1>; + #size-cells = <0>; + + mrt_channel0: mrt_channel@0 { + compatible = "nxp,mrt-channel"; + reg = <0>; + status = "disabled"; + }; + mrt_channel1: mrt_channel@1 { + compatible = "nxp,mrt-channel"; + reg = <1>; + status = "disabled"; + }; + mrt_channel2: mrt_channel@2 { + compatible = "nxp,mrt-channel"; + reg = <2>; + status = "disabled"; + }; + mrt_channel3: mrt_channel@3 { + compatible = "nxp,mrt-channel"; + reg = <3>; + status = "disabled"; + }; + }; }; &flexspi { diff --git a/dts/arm/nxp/nxp_rt5xx_ns.dtsi b/dts/arm/nxp/nxp_rt5xx_ns.dtsi index b5751704fbd..10e36fa7a24 100644 --- a/dts/arm/nxp/nxp_rt5xx_ns.dtsi +++ b/dts/arm/nxp/nxp_rt5xx_ns.dtsi @@ -8,8 +8,9 @@ / { soc { - sram: sram@20180000 { - ranges = <0x20180000 0x20180000 0x300000>; + sram: sram@20000000 { + ranges = <0x0 0x0 0x500000 + 0x20000000 0x20000000 0x500000>; }; peripheral: peripheral@40000000 { diff --git a/dts/arm/nxp/nxp_rt6xx.dtsi b/dts/arm/nxp/nxp_rt6xx.dtsi index fd6c53b10dd..3744184cc9c 100644 --- a/dts/arm/nxp/nxp_rt6xx.dtsi +++ b/dts/arm/nxp/nxp_rt6xx.dtsi @@ -8,8 +8,9 @@ / { soc { - sram: sram@30018000 { - ranges = <0x20180000 0x30180000 0x300000>; + sram: sram@30000000 { + ranges = <0x0 0x10000000 0x500000 + 0x20000000 0x30000000 0x500000>; }; peripheral: peripheral@50000000 { diff --git a/dts/arm/nxp/nxp_rt6xx_common.dtsi b/dts/arm/nxp/nxp_rt6xx_common.dtsi index abef67f81cf..0c81f71d140 100644 --- a/dts/arm/nxp/nxp_rt6xx_common.dtsi +++ b/dts/arm/nxp/nxp_rt6xx_common.dtsi @@ -10,6 +10,7 @@ #include #include #include +#include / { chosen { @@ -53,6 +54,20 @@ #address-cells = <1>; #size-cells = <1>; + /* RT6XX SRAM partitions are shared + * between code and data. Boards can + * override the reg properties of either sram0 or sram_code nodes to + * change the balance of SRAM allocation. + * + * Note that the sram code region starts at an offset of 0x1B000, + * as the boot ROM will not load code before 0x1C000. The first + * 0x1000 of the image will contain the boot header. + */ + sram_code: memory@1b000 { + compatible = "mmio-sram"; + reg = <0x1b000 DT_SIZE_K(1428)>; + }; + sram0: memory@20180000 { compatible = "mmio-sram"; reg = <0x20180000 DT_SIZE_K(3072)>; @@ -62,7 +77,7 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x40140000 DT_SIZE_K(16)>; zephyr,memory-region = "SRAM1"; - zephyr,memory-attr = "RAM"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; }; @@ -244,11 +259,10 @@ }; usbhs: usbhs@144000 { - compatible = "nxp,mcux-usbd"; + compatible = "nxp,lpcip3511"; reg = <0x144000 0x1000>; interrupts = <50 1>; num-bidir-endpoints = <6>; - usb-controller-index = "LpcIp3511Hs0"; status = "disabled"; }; @@ -312,6 +326,7 @@ reg = <0x146000 0x1000>; interrupts = <12 0>; status = "disabled"; + clocks = <&clkctl1 MCUX_SCTIMER_CLK>; prescaler = <8>; #pwm-cells = <3>; }; @@ -443,6 +458,38 @@ #address-cells = <3>; #size-cells = <0>; }; + + mrt: mrt@2d000 { + compatible = "nxp,mrt"; + reg = <0x2d000 0x100>; + interrupts = <9 0>; + num-channels = <4>; + num-bits = <24>; + clocks = <&clkctl1 MCUX_MRT_CLK>; + #address-cells = <1>; + #size-cells = <0>; + + mrt_channel0: mrt_channel@0 { + compatible = "nxp,mrt-channel"; + reg = <0>; + status = "disabled"; + }; + mrt_channel1: mrt_channel@1 { + compatible = "nxp,mrt-channel"; + reg = <1>; + status = "disabled"; + }; + mrt_channel2: mrt_channel@2 { + compatible = "nxp,mrt-channel"; + reg = <2>; + status = "disabled"; + }; + mrt_channel3: mrt_channel@3 { + compatible = "nxp,mrt-channel"; + reg = <3>; + status = "disabled"; + }; + }; }; &flexspi { diff --git a/dts/arm/nxp/nxp_rt6xx_ns.dtsi b/dts/arm/nxp/nxp_rt6xx_ns.dtsi index fafe3e9ffc4..04ce50e84b1 100644 --- a/dts/arm/nxp/nxp_rt6xx_ns.dtsi +++ b/dts/arm/nxp/nxp_rt6xx_ns.dtsi @@ -8,8 +8,9 @@ / { soc { - sram: sram@20180000 { - ranges = <0x20180000 0x20180000 0x300000>; + sram: sram@20000000 { + ranges = <0x0 0x0 0x500000 + 0x20000000 0x20000000 0x500000>; }; peripheral: peripheral@40000000 { diff --git a/dts/arm/nxp/nxp_s32k344_m7.dtsi b/dts/arm/nxp/nxp_s32k344_m7.dtsi index 4f8708defff..60196628a57 100644 --- a/dts/arm/nxp/nxp_s32k344_m7.dtsi +++ b/dts/arm/nxp/nxp_s32k344_m7.dtsi @@ -108,6 +108,9 @@ <5 5>, <6 6>, <7 7>, <8 16>, <9 17>, <10 18>, <11 19>, <12 20>, <13 21>, <14 22>, <15 23>; + nxp,wkpu = <&wkpu>; + nxp,wkpu-interrupts = <1 9>, <2 4>, <6 19>, + <8 27>, <9 25>, <13 8>, <15 24>; gpio-controller; #gpio-cells = <2>; ngpios = <16>; @@ -121,6 +124,9 @@ interrupt-parent = <&eirq0>; interrupts = <0 4>, <2 0>, <3 1>, <4 2>, <5 3>, <9 5>, <12 6>, <14 7>; + nxp,wkpu = <&wkpu>; + nxp,wkpu-interrupts = <0 35>, <4 63>, <9 38>, + <10 39>, <14 41>; gpio-controller; #gpio-cells = <2>; ngpios = <16>; @@ -135,6 +141,9 @@ interrupts = <0 8>, <1 9>, <2 10>, <3 11>, <4 12>, <5 13>, <8 14>, <9 15>, <10 24>, <11 25>, <12 26>, <13 27>, <14 28>, <15 29>; + nxp,wkpu = <&wkpu>; + nxp,wkpu-interrupts = <0 11>, <2 12>, <8 29>, + <9 21>, <11 20>, <12 16>, <13 15>, <15 37>; gpio-controller; #gpio-cells = <2>; ngpios = <16>; @@ -149,6 +158,9 @@ interrupt-parent = <&eirq0>; interrupts = <0 30>, <1 31>, <5 8>, <6 9>, <7 10>, <8 11>, <9 12>, <10 13>, <12 14>, <15 15>; + nxp,wkpu = <&wkpu>; + nxp,wkpu-interrupts = <0 17>, <1 18>, <3 42>, + <5 43>, <7 44>, <10 45>, <12 46>; gpio-controller; #gpio-cells = <2>; ngpios = <16>; @@ -164,6 +176,8 @@ <5 5>, <6 6>, <7 7>, <8 16>, <9 17>, <10 18>, <11 19>, <12 20>, <13 21>, <14 22>, <15 23>; + nxp,wkpu = <&wkpu>; + nxp,wkpu-interrupts = <6 7>, <7 6>, <9 14>, <11 22>; gpio-controller; #gpio-cells = <2>; ngpios = <16>; @@ -177,6 +191,9 @@ interrupt-parent = <&eirq0>; interrupts = <4 16>, <5 17>, <7 18>, <8 19>, <9 20>, <10 21>, <11 22>, <13 23>; + nxp,wkpu = <&wkpu>; + nxp,wkpu-interrupts = <2 40>, <4 47>, <7 48>, + <8 50>, <9 49>, <10 52>, <13 51>, <15 53>; gpio-controller; #gpio-cells = <2>; ngpios = <16>; @@ -192,6 +209,9 @@ <5 13>, <6 14>, <7 15>, <8 24>, <9 25>, <10 26>, <11 27>, <12 28>, <13 29>, <14 30>, <15 31>; + nxp,wkpu = <&wkpu>; + nxp,wkpu-interrupts = <0 10>, <2 13>, <3 5>, + <4 26>, <13 28>; gpio-controller; #gpio-cells = <2>; ngpios = <16>; @@ -205,6 +225,9 @@ interrupt-parent = <&eirq0>; interrupts = <1 24>, <4 25>, <5 26>, <6 27>, <7 28>, <8 29>, <11 30>, <12 31>; + nxp,wkpu = <&wkpu>; + nxp,wkpu-interrupts = <4 58>, <7 54>, <11 55>, + <13 56>, <15 57>; gpio-controller; #gpio-cells = <2>; ngpios = <16>; @@ -220,6 +243,9 @@ <4 4>, <5 5>, <6 6>, <8 7>, <9 8>, <10 9>, <11 10>, <12 11>, <13 12>, <14 13>, <15 14>; + nxp,wkpu = <&wkpu>; + nxp,wkpu-interrupts = <0 30>, <2 31>, <5 36>, + <6 33>, <11 32>, <14 34>; gpio-controller; #gpio-cells = <2>; ngpios = <16>; @@ -232,6 +258,9 @@ reg-names = "pgpdo", "mscr"; interrupt-parent = <&eirq0>; interrupts = <0 15>; + nxp,wkpu = <&wkpu>; + nxp,wkpu-interrupts = <0 23>, <2 59>, <5 60>, + <7 61>, <9 62>; gpio-controller; #gpio-cells = <2>; ngpios = <16>; @@ -289,6 +318,13 @@ }; }; + wkpu: wkpu@402b4000 { + compatible = "nxp,s32-wkpu"; + reg = <0x402b4000 0x4000>; + interrupts = <83 0>; + status = "disabled"; + }; + lpuart0: uart@40328000 { compatible = "nxp,kinetis-lpuart"; reg = <0x40328000 0x4000>; @@ -595,7 +631,192 @@ compatible = "nxp,s32-gmac"; interrupts = <105 0>, <106 0>, <107 0>, <108 0>; interrupt-names = "common", "tx", "rx", "safety"; - status = "disabled"; + }; + + edma0: dma-controller@4020c000 { + compatible = "nxp,mcux-edma-v3"; + reg = <0x4020c000 0x3000>, <0x40280000 0x4000>, <0x40284000 0x4000>; + dma-channels = <32>; + dma-requests = <64>; + dmamux-reg-offset = <3>; + channel-gap = <12 127>; + #dma-cells = <2>; + nxp,mem2mem; + interrupts = <4 0>, <5 0>, <6 0>, <7 0>, + <8 0>, <9 0>, <10 0>, <11 0>, + <12 0>, <13 0>, <14 0>, <15 0>, + <16 0>, <17 0>, <18 0>, <19 0>, + <20 0>, <21 0>, <22 0>, <23 0>, + <24 0>, <25 0>, <26 0>, <27 0>, + <28 0>, <29 0>, <30 0>, <31 0>, + <32 0>, <33 0>, <34 0>, <35 0>; + no-error-irq; + status = "disabled"; + }; + + emios0: emios@40088000 { + compatible = "nxp,s32-emios"; + reg = <0x40088000 0x4000>; + clocks = <&clock NXP_S32_EMIOS0_CLK>; + interrupts = <61 0>, <62 0>, <63 0>, + <64 0>, <65 0>, <66 0>; + interrupt-names = "0_0", "0_1", "0_2", + "0_3", "0_4", "0_5"; + internal-cnt = <0xC101FF>; + status = "disabled"; + + master_bus { + emios0_bus_a: emios0_bus_a { + channel = <23>; + bus-type = "BUS_A"; + channel-mask = <0x07FFFFF>; + status = "disabled"; + }; + + emios0_bus_b: emios0_bus_b { + channel = <0>; + bus-type = "BUS_B"; + channel-mask = <0x00000FE>; + status = "disabled"; + }; + + emios0_bus_c: emios0_bus_c { + channel = <8>; + bus-type = "BUS_C"; + channel-mask = <0x0000FE00>; + status = "disabled"; + }; + + emios0_bus_d: emios0_bus_d { + channel = <16>; + bus-type = "BUS_D"; + channel-mask = <0x00FE0000>; + status = "disabled"; + }; + + emios0_bus_f: emios0_bus_f { + channel = <22>; + bus-type = "BUS_F"; + channel-mask = <0x0BFFFFF>; + status = "disabled"; + }; + }; + + pwm { + compatible = "nxp,s32-emios-pwm"; + #pwm-cells = <3>; + status = "disabled"; + }; + }; + + emios1: emios@4008c000 { + compatible = "nxp,s32-emios"; + reg = <0x4008c000 0x4000>; + clocks = <&clock NXP_S32_EMIOS1_CLK>; + interrupts = <69 0>, <70 0>, <71 0>, + <72 0>, <73 0>, <74 0>; + interrupt-names = "1_0", "1_1", "1_2", + "1_3", "1_4", "1_5"; + internal-cnt = <0xC10101>; + status = "disabled"; + + master_bus { + emios1_bus_a: emios1_bus_a { + channel = <23>; + bus-type = "BUS_A"; + channel-mask = <0x07FFFFF>; + status = "disabled"; + }; + + emios1_bus_b: emios1_bus_b { + channel = <0>; + bus-type = "BUS_B"; + channel-mask = <0x00000FE>; + status = "disabled"; + }; + + emios1_bus_c: emios1_bus_c { + channel = <8>; + bus-type = "BUS_C"; + channel-mask = <0x0000FE00>; + status = "disabled"; + }; + + emios1_bus_d: emios1_bus_d { + channel = <16>; + bus-type = "BUS_D"; + channel-mask = <0x00FE0000>; + status = "disabled"; + }; + + emios1_bus_f: emios1_bus_f { + channel = <22>; + channel-mask = <0x0BFFFFF>; + bus-type = "BUS_F"; + status = "disabled"; + }; + }; + + pwm { + compatible = "nxp,s32-emios-pwm"; + #pwm-cells = <3>; + status = "disabled"; + }; + }; + + emios2: emios@40090000 { + compatible = "nxp,s32-emios"; + reg = <0x40090000 0x4000>; + clocks = <&clock NXP_S32_EMIOS2_CLK>; + interrupts = <77 0>, <78 0>, <79 0>, + <80 0>, <81 0>, <82 0>; + interrupt-names = "2_0", "2_1", "2_2", + "2_3", "2_4", "2_5"; + internal-cnt = <0xC10101>; + status = "disabled"; + + master_bus { + emios2_bus_a: emios2_bus_a { + channel = <23>; + bus-type = "BUS_A"; + channel-mask = <0x07FFFFF>; + status = "disabled"; + }; + + emios2_bus_b: emios2_bus_b { + channel = <0>; + bus-type = "BUS_B"; + channel-mask = <0x00000FE>; + status = "disabled"; + }; + + emios2_bus_c: emios2_bus_c { + channel = <8>; + bus-type = "BUS_C"; + channel-mask = <0x0000FE00>; + status = "disabled"; + }; + + emios2_bus_d: emios2_bus_d { + channel = <16>; + bus-type = "BUS_D"; + channel-mask = <0x00FE0000>; + status = "disabled"; + }; + + emios2_bus_f: emios2_bus_f { + channel = <22>; + bus-type = "BUS_F"; + channel-mask = <0x0BFFFFF>; + status = "disabled"; + }; + }; + + pwm { + compatible = "nxp,s32-emios-pwm"; + #pwm-cells = <3>; + status = "disabled"; + }; }; }; }; diff --git a/dts/arm/nxp/nxp_s32z27x_r52.dtsi b/dts/arm/nxp/nxp_s32z27x_r52.dtsi index 3d083083b91..4f92c8ca71a 100644 --- a/dts/arm/nxp/nxp_s32z27x_r52.dtsi +++ b/dts/arm/nxp/nxp_s32z27x_r52.dtsi @@ -1,5 +1,5 @@ /* - * Copyright 2022 NXP + * Copyright 2022-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,6 +7,7 @@ #include #include #include +#include / { cpus { @@ -80,6 +81,25 @@ soc { interrupt-parent = <&gic>; + clock: clock-controller@40030000 { + compatible = "nxp,s32-clock"; + reg = <0x40030000 0x10000>, + <0x40200000 0x10000>, + <0x40210000 0x10000>, + <0x40220000 0x10000>, + <0x40260000 0x10000>, + <0x40270000 0x10000>, + <0x40830000 0x10000>, + <0x41030000 0x10000>, + <0x41830000 0x10000>, + <0x42030000 0x10000>, + <0x42830000 0x10000>, + <0x44030000 0x10000>, + <0x440a0000 0x10000>; + #clock-cells = <1>; + status = "okay"; + }; + gic: interrupt-controller@47800000 { compatible = "arm,gic-v3", "arm,gic"; reg = <0x47800000 0x10000>, @@ -438,6 +458,7 @@ compatible = "nxp,s32-spi"; reg = <0x40130000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_SPI0_CLK>; num-cs = <5>; #address-cells = <1>; #size-cells = <0>; @@ -448,6 +469,7 @@ compatible = "nxp,s32-spi"; reg = <0x40140000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_SPI1_CLK>; num-cs = <5>; #address-cells = <1>; #size-cells = <0>; @@ -458,6 +480,7 @@ compatible = "nxp,s32-spi"; reg = <0x40930000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_SPI2_CLK>; num-cs = <5>; #address-cells = <1>; #size-cells = <0>; @@ -468,6 +491,7 @@ compatible = "nxp,s32-spi"; reg = <0x40940000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_SPI3_CLK>; num-cs = <5>; #address-cells = <1>; #size-cells = <0>; @@ -478,6 +502,7 @@ compatible = "nxp,s32-spi"; reg = <0x40950000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_SPI4_CLK>; num-cs = <5>; #address-cells = <1>; #size-cells = <0>; @@ -488,6 +513,7 @@ compatible = "nxp,s32-spi"; reg = <0x42130000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_SPI5_CLK>; num-cs = <5>; #address-cells = <1>; #size-cells = <0>; @@ -498,6 +524,7 @@ compatible = "nxp,s32-spi"; reg = <0x42140000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_SPI6_CLK>; num-cs = <5>; #address-cells = <1>; #size-cells = <0>; @@ -508,6 +535,7 @@ compatible = "nxp,s32-spi"; reg = <0x42150000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_SPI7_CLK>; num-cs = <5>; #address-cells = <1>; #size-cells = <0>; @@ -518,6 +546,7 @@ compatible = "nxp,s32-spi"; reg = <0x42930000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_SPI8_CLK>; num-cs = <5>; #address-cells = <1>; #size-cells = <0>; @@ -528,6 +557,7 @@ compatible = "nxp,s32-spi"; reg = <0x42940000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_SPI9_CLK>; num-cs = <5>; #address-cells = <1>; #size-cells = <0>; @@ -608,6 +638,8 @@ compatible = "nxp,s32-netc-emdio"; reg = <0x74b60000 0x1c44>; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; enetc_psi0: ethernet@74b00000 { @@ -668,7 +700,8 @@ status = "disabled"; interrupts = , ; - interrupt-names = "RX_TX_DATA_IRQ", "INT_ERROR_IRQ"; + interrupt-names = "rx_tx", "error"; + clocks = <&clock NXP_S32_P5_CANXL_PE_CLK>; }; can1: can@4751b000 { @@ -680,7 +713,8 @@ status = "disabled"; interrupts = , ; - interrupt-names = "RX_TX_DATA_IRQ", "INT_ERROR_IRQ"; + interrupt-names = "rx_tx", "error"; + clocks = <&clock NXP_S32_P5_CANXL_PE_CLK>; }; }; }; diff --git a/dts/arm/nxp/nxp_s32z27x_rtu0_r52.dtsi b/dts/arm/nxp/nxp_s32z27x_rtu0_r52.dtsi index 4c429b535e9..ec548c264cd 100644 --- a/dts/arm/nxp/nxp_s32z27x_rtu0_r52.dtsi +++ b/dts/arm/nxp/nxp_s32z27x_rtu0_r52.dtsi @@ -1,5 +1,5 @@ /* - * Copyright 2022 NXP + * Copyright 2022-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -20,6 +20,7 @@ compatible = "nxp,s32-sys-timer"; reg = <0x76200000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_RTU0_REG_INTF_CLK>; status = "disabled"; }; @@ -27,6 +28,7 @@ compatible = "nxp,s32-sys-timer"; reg = <0x76210000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_RTU0_REG_INTF_CLK>; status = "disabled"; }; @@ -34,6 +36,7 @@ compatible = "nxp,s32-sys-timer"; reg = <0x76020000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_RTU0_REG_INTF_CLK>; status = "disabled"; }; @@ -41,6 +44,7 @@ compatible = "nxp,s32-sys-timer"; reg = <0x76030000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_RTU0_REG_INTF_CLK>; status = "disabled"; }; @@ -48,6 +52,7 @@ compatible = "nxp,s32-swt"; reg = <0x76000000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_FIRC_CLK>; status = "disabled"; }; @@ -55,6 +60,7 @@ compatible = "nxp,s32-swt"; reg = <0x76010000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_FIRC_CLK>; status = "disabled"; }; @@ -62,6 +68,7 @@ compatible = "nxp,s32-swt"; reg = <0x76220000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_FIRC_CLK>; status = "disabled"; }; @@ -69,6 +76,7 @@ compatible = "nxp,s32-swt"; reg = <0x76230000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_FIRC_CLK>; status = "disabled"; }; @@ -76,6 +84,16 @@ compatible = "nxp,s32-swt"; reg = <0x76140000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_FIRC_CLK>; + status = "disabled"; + }; + + pit0: pit@76150000 { + compatible = "nxp,kinetis-pit"; + reg = <0x76150000 0x10000>; + interrupts = ; + clocks = <&clock NXP_S32_P0_REG_INTF_CLK>; + max-load-value = <0x00ffffff>; status = "disabled"; }; }; diff --git a/dts/arm/nxp/nxp_s32z27x_rtu1_r52.dtsi b/dts/arm/nxp/nxp_s32z27x_rtu1_r52.dtsi index a399f1b1e00..f316ac86fd9 100644 --- a/dts/arm/nxp/nxp_s32z27x_rtu1_r52.dtsi +++ b/dts/arm/nxp/nxp_s32z27x_rtu1_r52.dtsi @@ -1,5 +1,5 @@ /* - * Copyright 2022 NXP + * Copyright 2022-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -20,6 +20,7 @@ compatible = "nxp,s32-sys-timer"; reg = <0x76a00000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_RTU1_REG_INTF_CLK>; status = "disabled"; }; @@ -27,6 +28,7 @@ compatible = "nxp,s32-sys-timer"; reg = <0x76a10000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_RTU1_REG_INTF_CLK>; status = "disabled"; }; @@ -34,6 +36,7 @@ compatible = "nxp,s32-sys-timer"; reg = <0x76820000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_RTU1_REG_INTF_CLK>; status = "disabled"; }; @@ -41,6 +44,7 @@ compatible = "nxp,s32-sys-timer"; reg = <0x76830000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_RTU1_REG_INTF_CLK>; status = "disabled"; }; @@ -48,6 +52,7 @@ compatible = "nxp,s32-swt"; reg = <0x76800000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_FIRC_CLK>; status = "disabled"; }; @@ -55,6 +60,7 @@ compatible = "nxp,s32-swt"; reg = <0x76810000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_FIRC_CLK>; status = "disabled"; }; @@ -62,6 +68,7 @@ compatible = "nxp,s32-swt"; reg = <0x76a20000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_FIRC_CLK>; status = "disabled"; }; @@ -69,6 +76,7 @@ compatible = "nxp,s32-swt"; reg = <0x76a30000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_FIRC_CLK>; status = "disabled"; }; @@ -76,6 +84,16 @@ compatible = "nxp,s32-swt"; reg = <0x76940000 0x10000>; interrupts = ; + clocks = <&clock NXP_S32_FIRC_CLK>; + status = "disabled"; + }; + + pit0: pit@76950000 { + compatible = "nxp,kinetis-pit"; + reg = <0x76950000 0x10000>; + interrupts = ; + clocks = <&clock NXP_S32_P1_REG_INTF_CLK>; + max-load-value = <0x00ffffff>; status = "disabled"; }; }; diff --git a/dts/arm/renesas/ra/r7fa4m1ab3cfm.dtsi b/dts/arm/renesas/ra/r7fa4m1ab3cfm.dtsi new file mode 100644 index 00000000000..4836a58a0af --- /dev/null +++ b/dts/arm/renesas/ra/r7fa4m1ab3cfm.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define RA_SOC_PINS 64 +#define RA_SOC_HAS_MSTPCRE 1 +#define RA_SOC_MSTPD5_CHANNELS 1 + +#include +#include diff --git a/dts/arm/renesas/ra/ra-cm4-common.dtsi b/dts/arm/renesas/ra/ra-cm4-common.dtsi new file mode 100644 index 00000000000..60157ab8b72 --- /dev/null +++ b/dts/arm/renesas/ra/ra-cm4-common.dtsi @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m4"; + reg = <0>; + }; + }; + + clocks { + mosc: mosc { + compatible = "fixed-clock"; + clock-frequency = <1200000>; + status = "disabled"; + #clock-cells = <0>; + }; + + sosc: sosc { + compatible = "fixed-clock"; + clock-frequency = <32768>; + status = "disabled"; + #clock-cells = <0>; + }; + + hoco: hoco { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + status = "disabled"; + #clock-cells = <0>; + }; + + moco: moco { + compatible = "fixed-clock"; + clock-frequency = <8000000>; + status = "disabled"; + #clock-cells = <0>; + }; + + loco: loco { + compatible = "fixed-clock"; + clock-frequency = <32768>; + status = "disabled"; + #clock-cells = <0>; + }; + + pll: pll { + compatible = "fixed-factor-clock"; + status = "disabled"; + clocks = <&mosc>; + clock-div = <2>; + clock-mult = <8>; + #clock-cells = <0>; + }; + }; + + sram0: memory0@20000000 { + compatible = "mmio-sram"; + reg = <0x20000000 DT_SIZE_K(32)>; + }; + + soc { + interrupt-parent = <&icu>; + icu: interrupt-controller@40006000 { + compatible = "renesas,ra-interrupt-controller-unit"; + reg = <0x40006000 0x40>; + reg-names = "icu"; + interrupt-controller; + #interrupt-cells = <3>; + }; + + cgc: cgc@4001e000 { + compatible = "renesas,ra-clock-generation-circuit"; + reg = <0x4001e000 0x40 0x40047000 0x10>; + reg-names = "system", "mstp"; + #clock-cells = <1>; + + clock-source = <&moco>; + iclk-div = <16>; + pclka-div = <16>; + pclkb-div = <16>; + pclkc-div = <16>; + pclkd-div = <16>; + fclk-div = <16>; + }; + + fcu: flash-controller@4001c000 { + compatible = "renesas,ra-flash-controller"; + reg = <0x4001c000 0x44>; + reg-names = "fcache"; + + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash0@0 { + compatible = "soc-nv-flash"; + reg = <0x00000000 DT_SIZE_K(256)>; + }; + + flash1: flash1@40100000 { + compatible = "soc-nv-flash"; + reg = <0x40100000 DT_SIZE_K(8)>; + }; + }; + + ioport0: gpio@40040000 { + compatible = "renesas,ra-gpio"; + reg = <0x40040000 0x20>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + interrupts = , + , + , + , + , + ; + interrupt-names = "port-irq2", "port-irq3", "port-irq6", + "port-irq7", "port-irq10", "port-irq15"; + port-irq2-pins = <2>; + port-irq3-pins = <4>; + port-irq6-pins = <0>; + port-irq7-pins = <1 15>; + port-irq10-pins = <5>; + port-irq15-pins = <11>; + status = "disabled"; + }; + + ioport1: gpio@40040020 { + compatible = "renesas,ra-gpio"; + reg = <0x40040020 0x20>; + gpio-controller; + #gpio-cells = <2>; + interrupts = , + , + , + , + ; + interrupt-names = "port-irq0", "port-irq1", "port-irq2", + "port-irq3", "port-irq4"; + port-irq0-pins = <5>; + port-irq1-pins = <1>; + port-irq2-pins = <0>; + port-irq3-pins = <10>; + port-irq4-pins = <11>; + ngpios = <16>; + status = "disabled"; + }; + + ioport2: gpio@40040040 { + compatible = "renesas,ra-gpio"; + reg = <0x40040040 0x20>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + interrupts = , + , + , + , + ; + interrupt-names = "port-irq0", "port-irq1", "port-irq2", + "port-irq3", "port-irq9"; + port-irq0-pins = <6>; + port-irq1-pins = <5>; + port-irq2-pins = <13>; + port-irq3-pins = <12>; + status = "disabled"; + }; + + ioport3: gpio@40040060 { + compatible = "renesas,ra-gpio"; + reg = <0x40040060 0x20>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + interrupts = , + , + , + ; + interrupt-names = "port-irq5", "port-irq6", "port-irq8", "port-irq9"; + port-irq5-pins = <2>; + port-irq6-pins = <1>; + port-irq8-pins = <5>; + port-irq9-pins = <4>; + status = "disabled"; + }; + + ioport4: gpio@40040080 { + compatible = "renesas,ra-gpio"; + reg = <0x40040080 0x20>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + interrupts = , + , + , + , + , + , + ; + interrupt-names = "port-irq0", "port-irq4", "port-irq5", "port-irq6", + "port-irq7", "port-irq8", "port-irq9"; + port-irq0-pins = <0>; + port-irq4-pins = <2 11>; + port-irq5-pins = <1 10>; + port-irq6-pins = <9>; + port-irq7-pins = <8>; + port-irq8-pins = <15>; + port-irq9-pins = <14>; + status = "disabled"; + }; + + ioport5: gpio@400400a0 { + compatible = "renesas,ra-gpio"; + reg = <0x400400a0 0x20>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + interrupts = , + , + ; + interrupt-names = "port-irq11", "port-irq12", "port-irq14"; + port-irq11-pins = <1>; + port-irq12-pins = <2>; + port-irq14-pins = <5>; + status = "disabled"; + }; + + pinctrl: pinctrl@40040800 { + compatible = "renesas,ra-pinctrl"; + reg = <0x40040800 0x500 0x40040d03 0x1>; + reg-names = "pfs", "pmisc_pwpr"; + status = "okay"; + }; + + sci0: sci@40070000 { + compatible = "renesas,ra-uart-sci"; + reg = <0x40070000 0x20>; + interrupts = , + , + , + , + , + ; + interrupt-names = "rxi", "txi", "tei", "eri", "am", "rxi-or-eri"; + clocks = <&cgc RA_CLOCK_SCI(0)>; + #clock-cells = <1>; + status = "disabled"; + uart { + compatible = "renesas,ra-uart-sci"; + status = "disabled"; + }; + }; + + sci1: sci@40070020 { + compatible = "renesas,ra-uart-sci"; + reg = <0x40070020 0x20>; + interrupts = , + , + , + , + ; + interrupt-names = "rxi", "txi", "tei", "eri", "am"; + clocks = <&cgc RA_CLOCK_SCI(1)>; + #clock-cells = <1>; + status = "disabled"; + uart { + compatible = "renesas,ra-uart-sci"; + status = "disabled"; + }; + }; + + sci9: sci@40070120 { + compatible = "renesas,ra-uart-sci"; + reg = <0x40070120 0x20>; + interrupts = , + , + , + , + ; + interrupt-names = "rxi", "txi", "tei", "eri", "am"; + clocks = <&cgc RA_CLOCK_SCI(9)>; + #clock-cells = <1>; + status = "disabled"; + uart { + compatible = "renesas,ra-uart-sci"; + status = "disabled"; + }; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <4>; +}; diff --git a/dts/arm/renesas/ra/ra4-cm4-common.dtsi b/dts/arm/renesas/ra/ra4-cm4-common.dtsi new file mode 100644 index 00000000000..1d2397f85de --- /dev/null +++ b/dts/arm/renesas/ra/ra4-cm4-common.dtsi @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + soc { + ioport6: gpio@400400c0 { + compatible = "renesas,ra-gpio"; + reg = <0x400400c0 0x20>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + status = "disabled"; + }; + + ioport7: gpio@400400e0 { + compatible = "renesas,ra-gpio"; + reg = <0x400400e0 0x20>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + status = "disabled"; + }; + + ioport8: gpio@40040100 { + compatible = "renesas,ra-gpio"; + reg = <0x40040100 0x20>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + status = "disabled"; + }; + + ioport9: gpio@40040120 { + compatible = "renesas,ra-gpio"; + reg = <0x40040120 0x20>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + status = "disabled"; + }; + + sci2: sci@40070040 { + compatible = "renesas,ra-sci"; + reg = <0x40070040 0x20>; + interrupts = , + , + , + , + ; + interrupt-names = "rxi", "txi", "tei", "eri", "am"; + clocks = <&cgc RA_CLOCK_SCI(2)>; + #clock-cells = <1>; + status = "disabled"; + uart { + compatible = "renesas,ra-uart-sci"; + status = "disabled"; + }; + }; + }; +}; diff --git a/dts/arm/renesas/rcar/gen3/rcar_gen3_cr7.dtsi b/dts/arm/renesas/rcar/gen3/rcar_gen3_cr7.dtsi index 549443ee995..0f1cecf7d89 100644 --- a/dts/arm/renesas/rcar/gen3/rcar_gen3_cr7.dtsi +++ b/dts/arm/renesas/rcar/gen3/rcar_gen3_cr7.dtsi @@ -94,7 +94,6 @@ interrupt-parent = <&gic>; interrupts = ; - sjw = <1>; sample-point = <875>; status = "disabled"; }; diff --git a/dts/arm/renesas/rzt2m.dtsi b/dts/arm/renesas/rzt2m.dtsi new file mode 100644 index 00000000000..9c6c1688d63 --- /dev/null +++ b/dts/arm/renesas/rzt2m.dtsi @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "renesas,rzt2m-dev"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-r52"; + reg = <0>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-r52"; + reg = <1>; + }; + }; + + arch_timer: timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + interrupt-parent = <&gic>; + }; + + soc { + compatible = "renesas,rzt2m-soc"; + + interrupt-parent = <&gic>; + + gic: interrupt-controller@94000000 { + compatible = "arm,gic-v3", "arm,gic"; + reg = <0x94000000 0x10000>, + <0x94100000 0x80000>; + interrupt-controller; + #interrupt-cells = <4>; + status = "okay"; + }; + + cpu0_atcm: memory@0 { + compatible = "mmio-sram"; + reg = <0x00000000 DT_SIZE_K(512)>; + }; + + cpu0_btcm: memory@100000 { + compatible = "mmio-sram"; + reg = <0x00100000 DT_SIZE_K(64)>; + }; + + sram0: memory@10000000 { + compatible = "mmio-sram"; + reg = <0x10000000 DT_SIZE_M(2)>; + }; + + gsc: gsc@c0060000 { + /* Global System Counter */ + compatible = "syscon"; + reg = <0xc0060000 0x30>; + reg-io-width = <4>; + }; + + prcrn: prcrn@80281a10 { + /* Non-safety area */ + compatible = "syscon"; + reg = <0x80281a10 0x10>; + reg-io-width = <4>; + }; + + prcrs: prcrs@81281a00 { + /* Safety area */ + compatible = "syscon"; + reg = <0x81281a00 0x10>; + reg-io-width = <4>; + }; + + uart0: serial@80001000 { + compatible = "renesas,rzt2m-uart"; + reg = <0x80001000 0x1000>; + current-speed = <115200>; + interrupts = , + , + , + ; + interrupt-names = "rx_err", "rx", "tx", "tx_end"; + status = "disabled"; + }; + + uart3: serial@80001c00 { + compatible = "renesas,rzt2m-uart"; + reg = <0x80001c00 0x1000>; + current-speed = <115200>; + interrupts = , + , + , + ; + interrupt-names = "rx_err", "rx", "tx", "tx_end"; + status = "disabled"; + }; + + pinctrl: pinctrl@800a0000 { + compatible = "renesas,rzt2m-pinctrl"; + reg = <0x800a0000 0x1000 0x81030c00 0x1000>; + reg-names = "port_nsr", "ptadr"; + #address-cells = <1>; + #size-cells = <0>; + + gpio19: gpio@13 { + compatible = "renesas,rzt2m-gpio"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + reg = <0x13>; + }; + + gpio20: gpio@14 { + compatible = "renesas,rzt2m-gpio"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + reg = <0x14>; + }; + + gpio23: gpio@17 { + compatible = "renesas,rzt2m-gpio"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + reg = <0x17>; + }; + }; + }; +}; diff --git a/dts/arm/renesas/smartbond/da14695.dtsi b/dts/arm/renesas/smartbond/da14695.dtsi new file mode 100644 index 00000000000..37d75e4ecc4 --- /dev/null +++ b/dts/arm/renesas/smartbond/da14695.dtsi @@ -0,0 +1,12 @@ +/* Copyright (c) 2023 Renesas Electronics Corporation and/or its affiliates */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "da1469x.dtsi" + +&sram0 { + reg = <0x20000000 DT_SIZE_K(512)>; +}; + +&gpio1 { + ngpios = <12>; +}; diff --git a/dts/arm/renesas/smartbond/da1469x.dtsi b/dts/arm/renesas/smartbond/da1469x.dtsi index fa6ccd6bb25..6916b2b804c 100644 --- a/dts/arm/renesas/smartbond/da1469x.dtsi +++ b/dts/arm/renesas/smartbond/da1469x.dtsi @@ -149,6 +149,14 @@ }; }; + rtc: rtc@50000400 { + compatible = "renesas,smartbond-rtc"; + reg = <0x50000400 0x98>; + interrupts = <18 0>; + alarms-count = <1>; + status = "disabled"; + }; + wdog: watchdog@50000700 { compatible = "renesas,smartbond-watchdog"; reg = <0x50000700 0x8>; @@ -199,6 +207,22 @@ status = "disabled"; }; + uart2: uart@50020100 { + compatible = "renesas,smartbond-uart"; + reg = <0x50020100 0x100>; + periph-clock-config = <0x02>; + interrupts = <6 0>; + status = "disabled"; + }; + + uart3: uart@50020200 { + compatible = "renesas,smartbond-uart"; + reg = <0x50020200 0x100>; + periph-clock-config = <0x08>; + interrupts = <7 0>; + status = "disabled"; + }; + adc: adc@50030900 { compatible = "renesas,smartbond-adc"; reg = <0x50030900 0x1C>; @@ -207,7 +231,6 @@ #io-channel-cells = <1>; }; - sdadc: sdadc@50020800 { compatible = "renesas,smartbond-sdadc"; reg = <0x50020800 0x1C>; @@ -217,6 +240,13 @@ #io-channel-cells = <1>; }; + crypto: crypto@30040000 { + compatible = "renesas,smartbond-crypto"; + reg = <0x30040000 0x200>; + interrupts = <29 0>; + status = "disabled"; + }; + trng: trng@50040c00 { compatible = "renesas,smartbond-trng"; reg = <0x50040c00 0x0C>; @@ -273,6 +303,16 @@ interrupts = <15 0>, <21 0>; status = "disabled"; }; + + dma: dma@50040800 { + compatible = "renesas,smartbond-dma"; + reg = <0x50040800 0x110>; + interrupts = <1 0>; + status = "disabled"; + dma-channels = <8>; + block-count = <1>; + #dma-cells = <0>; + }; }; }; diff --git a/dts/arm/rpi_pico/rp2040.dtsi b/dts/arm/rpi_pico/rp2040.dtsi index 24c0a3e7bae..fd83297fa5a 100644 --- a/dts/arm/rpi_pico/rp2040.dtsi +++ b/dts/arm/rpi_pico/rp2040.dtsi @@ -138,10 +138,11 @@ }; i2c0: i2c@40044000 { - compatible = "snps,designware-i2c"; + compatible = "raspberrypi,pico-i2c", "snps,designware-i2c"; #address-cells = <1>; #size-cells = <0>; reg = <0x40044000 DT_SIZE_K(4)>; + resets = <&reset RPI_PICO_RESETS_RESET_I2C0>; clocks = <&system_clk>; interrupts = <23 RPI_PICO_DEFAULT_IRQ_PRIORITY>; interrupt-names = "i2c0"; @@ -149,10 +150,11 @@ }; i2c1: i2c@40048000 { - compatible = "snps,designware-i2c"; + compatible = "raspberrypi,pico-i2c", "snps,designware-i2c"; #address-cells = <1>; #size-cells = <0>; reg = <0x40048000 DT_SIZE_K(4)>; + resets = <&reset RPI_PICO_RESETS_RESET_I2C0>; clocks = <&system_clk>; interrupts = <24 RPI_PICO_DEFAULT_IRQ_PRIORITY>; interrupt-names = "i2c1"; @@ -187,6 +189,22 @@ #pwm-cells = <3>; }; + timer: timer@40054000 { + compatible = "raspberrypi,pico-timer"; + reg = <0x40054000 DT_SIZE_K(4)>; + resets = <&reset RPI_PICO_RESETS_RESET_TIMER>; + clocks = <&xtal_clk>; + interrupts = <0 RPI_PICO_DEFAULT_IRQ_PRIORITY>, + <1 RPI_PICO_DEFAULT_IRQ_PRIORITY>, + <2 RPI_PICO_DEFAULT_IRQ_PRIORITY>, + <3 RPI_PICO_DEFAULT_IRQ_PRIORITY>; + interrupt-names = "TIMER_IRQ_0", + "TIMER_IRQ_1", + "TIMER_IRQ_2", + "TIMER_IRQ_3"; + status = "disabled"; + }; + dma: dma@50000000 { compatible = "raspberrypi,pico-dma"; reg = <0x50000000 DT_SIZE_K(64)>; diff --git a/dts/arm/silabs/efm32_pg_1b.dtsi b/dts/arm/silabs/efm32_pg_1b.dtsi index f88fc07def7..30d242256dd 100644 --- a/dts/arm/silabs/efm32_pg_1b.dtsi +++ b/dts/arm/silabs/efm32_pg_1b.dtsi @@ -139,6 +139,13 @@ #gpio-cells = <2>; status = "disabled"; }; + pinctrl: pin-controller { + /* Pin controller is a "virtual" device since SiLabs SoCs do pin + * control in a distributed way (GPIO registers and PSEL + * registers on each peripheral). + */ + compatible = "silabs,gecko-pinctrl"; + }; }; wdog0: wdog@40052000 { diff --git a/dts/arm/silabs/efm32gg11b.dtsi b/dts/arm/silabs/efm32gg11b.dtsi index 732490ffd9a..a8435797a80 100644 --- a/dts/arm/silabs/efm32gg11b.dtsi +++ b/dts/arm/silabs/efm32gg11b.dtsi @@ -287,6 +287,14 @@ interrupts = <64 0>; status = "disabled"; }; + + pinctrl: pin-controller { + /* Pin controller is a "virtual" device since SiLabs SoCs do pin + * control in a distributed way (GPIO registers and PSEL + * registers on each peripheral). + */ + compatible = "silabs,gecko-pinctrl"; + }; }; }; diff --git a/dts/arm/silabs/efm32gg12b.dtsi b/dts/arm/silabs/efm32gg12b.dtsi index 3e7d105e6b3..d1c3e5aa70d 100644 --- a/dts/arm/silabs/efm32gg12b.dtsi +++ b/dts/arm/silabs/efm32gg12b.dtsi @@ -240,6 +240,14 @@ interrupts = <55 0>; status = "disabled"; }; + + pinctrl: pin-controller { + /* Pin controller is a "virtual" device since SiLabs SoCs do pin + * control in a distributed way (GPIO registers and PSEL + * registers on each peripheral). + */ + compatible = "silabs,gecko-pinctrl"; + }; }; }; diff --git a/dts/arm/silabs/efm32hg.dtsi b/dts/arm/silabs/efm32hg.dtsi index bf63ebdd6ad..e3854d6067a 100644 --- a/dts/arm/silabs/efm32hg.dtsi +++ b/dts/arm/silabs/efm32hg.dtsi @@ -140,6 +140,14 @@ status = "disabled"; }; }; + + pinctrl: pin-controller { + /* Pin controller is a "virtual" device since SiLabs SoCs do pin + * control in a distributed way (GPIO registers and PSEL + * registers on each peripheral). + */ + compatible = "silabs,gecko-pinctrl"; + }; }; }; diff --git a/dts/arm/silabs/efm32wg.dtsi b/dts/arm/silabs/efm32wg.dtsi index a12715acdf5..19182ebfbfe 100644 --- a/dts/arm/silabs/efm32wg.dtsi +++ b/dts/arm/silabs/efm32wg.dtsi @@ -185,6 +185,14 @@ status = "disabled"; }; }; + + pinctrl: pin-controller { + /* Pin controller is a "virtual" device since SiLabs SoCs do pin + * control in a distributed way (GPIO registers and PSEL + * registers on each peripheral). + */ + compatible = "silabs,gecko-pinctrl"; + }; }; }; diff --git a/dts/arm/silabs/efr32bg2x-pinctrl.dtsi b/dts/arm/silabs/efr32bg2x-pinctrl.dtsi index 388423e10d0..fb5fc1b8484 100644 --- a/dts/arm/silabs/efr32bg2x-pinctrl.dtsi +++ b/dts/arm/silabs/efr32bg2x-pinctrl.dtsi @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include &pinctrl { diff --git a/dts/arm/silabs/efr32bg2x.dtsi b/dts/arm/silabs/efr32bg2x.dtsi index e1f3726e429..2f50f1bcbda 100644 --- a/dts/arm/silabs/efr32bg2x.dtsi +++ b/dts/arm/silabs/efr32bg2x.dtsi @@ -5,11 +5,11 @@ */ #include -#include #include #include #include #include +#include / { chosen { @@ -17,6 +17,15 @@ zephyr,entropy = &trng; }; + clocks { + clk_hfxo: clk-hfxo { + #clock-cells = <0>; + compatible = "silabs,hfxo"; + clock-frequency = ; + ctune = <120>; + }; + }; + cpus { #address-cells = <1>; #size-cells = <0>; diff --git a/dts/arm/silabs/efr32fg1p.dtsi b/dts/arm/silabs/efr32fg1p.dtsi index 586bbcd36fd..a451d44cb2c 100644 --- a/dts/arm/silabs/efr32fg1p.dtsi +++ b/dts/arm/silabs/efr32fg1p.dtsi @@ -172,6 +172,14 @@ }; }; + + pinctrl: pin-controller { + /* Pin controller is a "virtual" device since SiLabs SoCs do pin + * control in a distributed way (GPIO registers and PSEL + * registers on each peripheral). + */ + compatible = "silabs,gecko-pinctrl"; + }; }; &nvic { diff --git a/dts/arm/silabs/efr32mg.dtsi b/dts/arm/silabs/efr32mg.dtsi index 65611091edf..cfbbde48af9 100644 --- a/dts/arm/silabs/efr32mg.dtsi +++ b/dts/arm/silabs/efr32mg.dtsi @@ -233,6 +233,14 @@ status = "disabled"; }; }; + + pinctrl: pin-controller { + /* Pin controller is a "virtual" device since SiLabs SoCs do pin + * control in a distributed way (GPIO registers and PSEL + * registers on each peripheral). + */ + compatible = "silabs,gecko-pinctrl"; + }; }; &nvic { diff --git a/dts/arm/silabs/efr32mg12p433f1024gm68.dtsi b/dts/arm/silabs/efr32mg12p433f1024gm68.dtsi new file mode 100644 index 00000000000..dea50625ec9 --- /dev/null +++ b/dts/arm/silabs/efr32mg12p433f1024gm68.dtsi @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018 Linaro Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + sram0: memory@20000000 { + reg = <0x20000000 DT_SIZE_K(256)>; + }; + + soc { + compatible = "silabs,efr32mg12p433f1024gm68", "silabs,efr32mg12p", "silabs,efr32", + "simple-bus"; + + flash-controller@400e0000 { + flash0: flash@0 { + reg = <0 DT_SIZE_K(1024)>; + }; + }; + }; +}; diff --git a/dts/arm/silabs/efr32mg21.dtsi b/dts/arm/silabs/efr32mg21.dtsi index 369a1f436f2..4ada3f6ff60 100644 --- a/dts/arm/silabs/efr32mg21.dtsi +++ b/dts/arm/silabs/efr32mg21.dtsi @@ -182,6 +182,14 @@ interrupts = <44 0>; status = "disabled"; }; + + pinctrl: pin-controller { + /* Pin controller is a "virtual" device since SiLabs SoCs do pin + * control in a distributed way (GPIO registers and PSEL + * registers on each peripheral). + */ + compatible = "silabs,gecko-pinctrl"; + }; }; }; diff --git a/dts/arm/silabs/efr32mg24.dtsi b/dts/arm/silabs/efr32mg24.dtsi index 1ee015b7334..b42b775397f 100644 --- a/dts/arm/silabs/efr32mg24.dtsi +++ b/dts/arm/silabs/efr32mg24.dtsi @@ -10,6 +10,7 @@ #include #include #include +#include / { chosen { @@ -17,6 +18,15 @@ zephyr,entropy = &se; }; + clocks { + clk_hfxo: clk-hfxo { + #clock-cells = <0>; + compatible = "silabs,hfxo"; + clock-frequency = ; + ctune = <140>; + }; + }; + cpus { #address-cells = <1>; #size-cells = <0>; diff --git a/dts/arm/silabs/efr32xg12p-pinctrl.dtsi b/dts/arm/silabs/efr32xg12p-pinctrl.dtsi new file mode 100644 index 00000000000..e500e3b18bd --- /dev/null +++ b/dts/arm/silabs/efr32xg12p-pinctrl.dtsi @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 Silicon Labs + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + /* configuration for uart0 device, default state */ + usart0_default: usart0_default { + group1 { + /* configure PA.1 as UART_RX */ + psels = , + ; + }; + group2 { + /* configure PA.0 as UART_TX */ + psels = , + ; + }; + }; +}; diff --git a/dts/arm/silabs/efr32xg13p-pinctrl.dtsi b/dts/arm/silabs/efr32xg13p-pinctrl.dtsi new file mode 100644 index 00000000000..e500e3b18bd --- /dev/null +++ b/dts/arm/silabs/efr32xg13p-pinctrl.dtsi @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 Silicon Labs + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + /* configuration for uart0 device, default state */ + usart0_default: usart0_default { + group1 { + /* configure PA.1 as UART_RX */ + psels = , + ; + }; + group2 { + /* configure PA.0 as UART_TX */ + psels = , + ; + }; + }; +}; diff --git a/dts/arm/silabs/efr32xg13p.dtsi b/dts/arm/silabs/efr32xg13p.dtsi index 3db40b5b5d4..96d9c6493d1 100644 --- a/dts/arm/silabs/efr32xg13p.dtsi +++ b/dts/arm/silabs/efr32xg13p.dtsi @@ -180,6 +180,14 @@ status = "disabled"; }; }; + + pinctrl: pin-controller { + /* Pin controller is a "virtual" device since SiLabs SoCs do pin + * control in a distributed way (GPIO registers and PSEL + * registers on each peripheral). + */ + compatible = "silabs,gecko-pinctrl"; + }; }; &nvic { diff --git a/dts/arm/silabs/efr32xg1p-pinctrl.dtsi b/dts/arm/silabs/efr32xg1p-pinctrl.dtsi new file mode 100644 index 00000000000..e500e3b18bd --- /dev/null +++ b/dts/arm/silabs/efr32xg1p-pinctrl.dtsi @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 Silicon Labs + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + /* configuration for uart0 device, default state */ + usart0_default: usart0_default { + group1 { + /* configure PA.1 as UART_RX */ + psels = , + ; + }; + group2 { + /* configure PA.0 as UART_TX */ + psels = , + ; + }; + }; +}; diff --git a/dts/arm/st/c0/stm32c0.dtsi b/dts/arm/st/c0/stm32c0.dtsi index 7133e2b026d..ef71f835ba2 100644 --- a/dts/arm/st/c0/stm32c0.dtsi +++ b/dts/arm/st/c0/stm32c0.dtsi @@ -293,14 +293,13 @@ interrupts = <12 0>; status = "disabled"; #io-channel-cells = <1>; - temp-channel = <9>; - vref-channel = <10>; resolutions = ; sampling-times = <2 4 8 13 20 40 80 161>; num-sampling-time-common-channels = <2>; + st,adc-sequencer = ; }; dma1: dma@40020000 { diff --git a/dts/arm/st/f0/stm32f0.dtsi b/dts/arm/st/f0/stm32f0.dtsi index 44706200883..e9e521cd47e 100644 --- a/dts/arm/st/f0/stm32f0.dtsi +++ b/dts/arm/st/f0/stm32f0.dtsi @@ -338,14 +338,13 @@ interrupts = <12 0>; status = "disabled"; #io-channel-cells = <1>; - temp-channel = <16>; - vref-channel = <17>; resolutions = ; sampling-times = <2 8 14 29 42 56 72 240>; num-sampling-time-common-channels = <1>; + st,adc-sequencer = ; }; dma1: dma@40020000 { diff --git a/dts/arm/st/f0/stm32f031.dtsi b/dts/arm/st/f0/stm32f031.dtsi index 513e25afb26..5d04c1d3eda 100644 --- a/dts/arm/st/f0/stm32f031.dtsi +++ b/dts/arm/st/f0/stm32f031.dtsi @@ -60,8 +60,3 @@ status = "disabled"; }; }; - -/* All STM32F0 series have ADC VBAT channel, except STM32F0x0 value line */ -&adc1 { - vbat-channel = <18>; -}; diff --git a/dts/arm/st/f0/stm32f042.dtsi b/dts/arm/st/f0/stm32f042.dtsi index e8aed739bd7..52744d1ff47 100644 --- a/dts/arm/st/f0/stm32f042.dtsi +++ b/dts/arm/st/f0/stm32f042.dtsi @@ -44,7 +44,6 @@ interrupts = <30 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; status = "disabled"; - sjw = <1>; sample-point = <875>; }; diff --git a/dts/arm/st/f0/stm32f072.dtsi b/dts/arm/st/f0/stm32f072.dtsi index 368ea324e4f..1c7ad8b1b67 100644 --- a/dts/arm/st/f0/stm32f072.dtsi +++ b/dts/arm/st/f0/stm32f072.dtsi @@ -16,7 +16,6 @@ interrupts = <30 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; status = "disabled"; - sjw = <1>; sample-point = <875>; }; diff --git a/dts/arm/st/f0/stm32f072X8.dtsi b/dts/arm/st/f0/stm32f072X8.dtsi new file mode 100644 index 00000000000..66669041b91 --- /dev/null +++ b/dts/arm/st/f0/stm32f072X8.dtsi @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 Jonas Otto + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +/ { + sram0: memory@20000000 { + reg = <0x20000000 DT_SIZE_K(16)>; + }; + + soc { + flash-controller@40022000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_K(64)>; + }; + }; + }; +}; diff --git a/dts/arm/st/f0/stm32f091.dtsi b/dts/arm/st/f0/stm32f091.dtsi index 2b68394f507..b1ad8f0646e 100644 --- a/dts/arm/st/f0/stm32f091.dtsi +++ b/dts/arm/st/f0/stm32f091.dtsi @@ -58,7 +58,6 @@ interrupts = <30 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; status = "disabled"; - sjw = <1>; sample-point = <875>; }; diff --git a/dts/arm/st/f1/stm32f1.dtsi b/dts/arm/st/f1/stm32f1.dtsi index 5b0d9f002c4..b70130db308 100644 --- a/dts/arm/st/f1/stm32f1.dtsi +++ b/dts/arm/st/f1/stm32f1.dtsi @@ -339,10 +339,9 @@ interrupts = <18 0>; status = "disabled"; #io-channel-cells = <1>; - temp-channel = <16>; - vref-channel = <17>; resolutions = ; sampling-times = <2 8 14 29 42 56 72 240>; + st,adc-sequencer = ; }; dma1: dma@40020000 { diff --git a/dts/arm/st/f1/stm32f103X8.dtsi b/dts/arm/st/f1/stm32f103X8.dtsi index a70d4c83a39..ae7150291be 100644 --- a/dts/arm/st/f1/stm32f103X8.dtsi +++ b/dts/arm/st/f1/stm32f103X8.dtsi @@ -54,7 +54,6 @@ interrupt-names = "TX", "RX0", "RX1", "SCE"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; status = "disabled"; - sjw = <1>; sample-point = <875>; }; }; diff --git a/dts/arm/st/f1/stm32f105.dtsi b/dts/arm/st/f1/stm32f105.dtsi index 9ff6104bf12..1a2ec793d99 100644 --- a/dts/arm/st/f1/stm32f105.dtsi +++ b/dts/arm/st/f1/stm32f105.dtsi @@ -40,7 +40,6 @@ interrupt-names = "TX", "RX0", "RX1", "SCE"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; status = "disabled"; - sjw = <1>; sample-point = <875>; }; @@ -52,7 +51,6 @@ /* also enabling clock for can1 (master instance) */ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x06000000>; status = "disabled"; - sjw = <1>; sample-point = <875>; }; diff --git a/dts/arm/st/f2/stm32f2.dtsi b/dts/arm/st/f2/stm32f2.dtsi index 778c30dd75d..845cd6fb5a2 100644 --- a/dts/arm/st/f2/stm32f2.dtsi +++ b/dts/arm/st/f2/stm32f2.dtsi @@ -366,14 +366,13 @@ interrupts = <18 0>; status = "disabled"; #io-channel-cells = <1>; - temp-channel = <16>; - vref-channel = <17>; resolutions = ; sampling-times = <3 15 28 58 84 112 144 480>; st,adc-clock-source = ; + st,adc-sequencer = ; }; dma1: dma@40026000 { diff --git a/dts/arm/st/f3/stm32f3.dtsi b/dts/arm/st/f3/stm32f3.dtsi index bef28bd44dc..a426a84ea3e 100644 --- a/dts/arm/st/f3/stm32f3.dtsi +++ b/dts/arm/st/f3/stm32f3.dtsi @@ -420,7 +420,6 @@ interrupt-names = "TX", "RX0", "RX1", "SCE"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; status = "disabled"; - sjw = <1>; sample-point = <875>; }; diff --git a/dts/arm/st/f3/stm32f302.dtsi b/dts/arm/st/f3/stm32f302.dtsi index 7120c7dc4fe..59f4b2f7077 100644 --- a/dts/arm/st/f3/stm32f302.dtsi +++ b/dts/arm/st/f3/stm32f302.dtsi @@ -109,14 +109,12 @@ interrupts = <18 0>; status = "disabled"; #io-channel-cells = <1>; - temp-channel = <16>; - vbat-channel = <17>; - vref-channel = <18>; resolutions = ; sampling-times = <2 3 5 8 20 62 182 602>; + st,adc-sequencer = ; }; }; }; diff --git a/dts/arm/st/f3/stm32f303.dtsi b/dts/arm/st/f3/stm32f303.dtsi index 0698c10c90f..01e5d4233df 100644 --- a/dts/arm/st/f3/stm32f303.dtsi +++ b/dts/arm/st/f3/stm32f303.dtsi @@ -148,14 +148,12 @@ status = "disabled"; vref-mv = <3000>; #io-channel-cells = <1>; - temp-channel = <16>; - vbat-channel = <17>; - vref-channel = <18>; resolutions = ; sampling-times = <2 3 5 8 20 62 182 602>; + st,adc-sequencer = ; }; adc2: adc@50000100 { @@ -166,12 +164,12 @@ status = "disabled"; vref-mv = <3000>; #io-channel-cells = <1>; - vref-channel = <18>; resolutions = ; sampling-times = <2 3 5 8 20 62 182 602>; + st,adc-sequencer = ; }; }; }; diff --git a/dts/arm/st/f3/stm32f334.dtsi b/dts/arm/st/f3/stm32f334.dtsi index b2036c52c24..f24fefc22df 100644 --- a/dts/arm/st/f3/stm32f334.dtsi +++ b/dts/arm/st/f3/stm32f334.dtsi @@ -35,14 +35,12 @@ interrupts = <18 0>; status = "disabled"; #io-channel-cells = <1>; - temp-channel = <16>; - vbat-channel = <17>; - vref-channel = <18>; resolutions = ; sampling-times = <2 3 5 8 20 62 182 602>; + st,adc-sequencer = ; }; rtc@40002800 { diff --git a/dts/arm/st/f3/stm32f373.dtsi b/dts/arm/st/f3/stm32f373.dtsi index 36225c63146..9c42331c36e 100644 --- a/dts/arm/st/f3/stm32f373.dtsi +++ b/dts/arm/st/f3/stm32f373.dtsi @@ -191,11 +191,9 @@ interrupts = <18 0>; status = "disabled"; #io-channel-cells = <1>; - temp-channel = <16>; - vref-channel = <17>; - vbat-channel = <18>; resolutions = ; sampling-times = <2 8 14 29 42 56 72 240>; + st,adc-sequencer = ; }; rtc@40002800 { diff --git a/dts/arm/st/f4/stm32f4.dtsi b/dts/arm/st/f4/stm32f4.dtsi index 11a2593964d..f53c9cdf228 100644 --- a/dts/arm/st/f4/stm32f4.dtsi +++ b/dts/arm/st/f4/stm32f4.dtsi @@ -28,10 +28,26 @@ #address-cells = <1>; #size-cells = <0>; - cpu@0 { + cpu0: cpu@0 { device_type = "cpu"; compatible = "arm,cortex-m4f"; reg = <0>; + cpu-power-states = <&stop>; + }; + + power-states { + stop: stop { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + /* It is really hard to establish these numbers precisely. + * We are basing on RTC as a wakeup source with 62,5us tick. + * It requires a proper margin. Additionally, sys_clock_announce + * works within system tick boundaries (100us by default), + * which also introduces some shift. + */ + min-residency-us = <400>; + exit-latency-us = <300>; + }; }; }; @@ -513,16 +529,13 @@ interrupts = <18 0>; status = "disabled"; #io-channel-cells = <1>; - /* Temperature and VBAT sensor share channel 18 */ - temp-channel = <18>; - vbat-channel = <18>; - vref-channel = <17>; resolutions = ; sampling-times = <3 15 28 56 84 112 144 480>; st,adc-clock-source = ; + st,adc-sequencer = ; }; dma1: dma@40026000 { diff --git a/dts/arm/st/f4/stm32f405.dtsi b/dts/arm/st/f4/stm32f405.dtsi index dfcd1a94fc5..a462d48a266 100644 --- a/dts/arm/st/f4/stm32f405.dtsi +++ b/dts/arm/st/f4/stm32f405.dtsi @@ -212,7 +212,6 @@ interrupt-names = "TX", "RX0", "RX1", "SCE"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; status = "disabled"; - sjw = <1>; sample-point = <875>; }; @@ -225,7 +224,6 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x06000000>; master-can-reg = <0x40006400>; status = "disabled"; - sjw = <1>; sample-point = <875>; }; @@ -258,6 +256,7 @@ STM32_ADC_RES(6, 0x03)>; sampling-times = <3 15 28 56 84 112 144 480>; st,adc-clock-source = ; + st,adc-sequencer = ; }; adc3: adc@40012200 { @@ -273,6 +272,7 @@ STM32_ADC_RES(6, 0x03)>; sampling-times = <3 15 28 56 84 112 144 480>; st,adc-clock-source = ; + st,adc-sequencer = ; }; dac1: dac@40007400 { diff --git a/dts/arm/st/f4/stm32f412.dtsi b/dts/arm/st/f4/stm32f412.dtsi index bf15b9f67fd..07f93afc963 100644 --- a/dts/arm/st/f4/stm32f412.dtsi +++ b/dts/arm/st/f4/stm32f412.dtsi @@ -222,7 +222,6 @@ interrupt-names = "TX", "RX0", "RX1", "SCE"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; status = "disabled"; - sjw = <1>; sample-point = <875>; }; @@ -235,7 +234,6 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x06000000>; master-can-reg = <0x40006400>; status = "disabled"; - sjw = <1>; sample-point = <875>; }; }; diff --git a/dts/arm/st/f4/stm32f413.dtsi b/dts/arm/st/f4/stm32f413.dtsi index 17d8137badd..ac61c7d351b 100644 --- a/dts/arm/st/f4/stm32f413.dtsi +++ b/dts/arm/st/f4/stm32f413.dtsi @@ -79,7 +79,6 @@ interrupt-names = "TX", "RX0", "RX1", "SCE"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x08000000>; status = "disabled"; - sjw = <1>; sample-point = <875>; }; }; diff --git a/dts/arm/st/f4/stm32f446.dtsi b/dts/arm/st/f4/stm32f446.dtsi index d7039c4ff1b..7b15fe2a9cf 100644 --- a/dts/arm/st/f4/stm32f446.dtsi +++ b/dts/arm/st/f4/stm32f446.dtsi @@ -65,7 +65,6 @@ interrupt-names = "TX", "RX0", "RX1", "SCE"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; status = "disabled"; - sjw = <1>; sample-point = <875>; }; @@ -78,7 +77,6 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x06000000>; master-can-reg = <0x40006400>; status = "disabled"; - sjw = <1>; sample-point = <875>; }; diff --git a/dts/arm/st/f7/stm32f7.dtsi b/dts/arm/st/f7/stm32f7.dtsi index a92e5138ce1..2df24d0c8d2 100644 --- a/dts/arm/st/f7/stm32f7.dtsi +++ b/dts/arm/st/f7/stm32f7.dtsi @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include / { @@ -47,7 +49,7 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x90000000 DT_SIZE_M(256)>; zephyr,memory-region = "QSPI"; - zephyr,memory-attr = "EXTMEM"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_EXTMEM) )>; }; clocks { @@ -402,7 +404,6 @@ interrupt-names = "TX", "RX0", "RX1", "SCE"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; status = "disabled"; - sjw = <1>; sample-point = <875>; }; @@ -741,16 +742,13 @@ interrupts = <18 0>; status = "disabled"; #io-channel-cells = <1>; - /* Temperature and VBAT sensor share channel 18 */ - temp-channel = <18>; - vbat-channel = <18>; - vref-channel = <17>; resolutions = ; sampling-times = <3 15 28 56 84 112 144 480>; st,adc-clock-source = ; + st,adc-sequencer = ; }; adc2: adc@40012100 { @@ -766,6 +764,7 @@ STM32_ADC_RES(6, 0x03)>; sampling-times = <3 15 28 56 84 112 144 480>; st,adc-clock-source = ; + st,adc-sequencer = ; }; adc3: adc@40012200 { @@ -781,6 +780,7 @@ STM32_ADC_RES(6, 0x03)>; sampling-times = <3 15 28 56 84 112 144 480>; st,adc-clock-source = ; + st,adc-sequencer = ; }; dac1: dac@40007400 { diff --git a/dts/arm/st/f7/stm32f745.dtsi b/dts/arm/st/f7/stm32f745.dtsi index 895525f9bc0..d63ddd881ba 100644 --- a/dts/arm/st/f7/stm32f745.dtsi +++ b/dts/arm/st/f7/stm32f745.dtsi @@ -72,7 +72,6 @@ interrupt-names = "TX", "RX0", "RX1", "SCE"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x04000000>; status = "disabled"; - sjw = <1>; sample-point = <875>; }; diff --git a/dts/arm/st/g0/stm32g0.dtsi b/dts/arm/st/g0/stm32g0.dtsi index 8c9120472ff..5f37fc667db 100644 --- a/dts/arm/st/g0/stm32g0.dtsi +++ b/dts/arm/st/g0/stm32g0.dtsi @@ -396,9 +396,6 @@ interrupts = <12 0>; status = "disabled"; #io-channel-cells = <1>; - temp-channel = <12>; - vref-channel = <13>; - vbat-channel = <14>; resolutions = ; num-sampling-time-common-channels = <2>; + st,adc-sequencer = ; }; dma1: dma@40020000 { diff --git a/dts/arm/st/g0/stm32g0b1.dtsi b/dts/arm/st/g0/stm32g0b1.dtsi index fd65aa54c08..b99063d67b8 100644 --- a/dts/arm/st/g0/stm32g0b1.dtsi +++ b/dts/arm/st/g0/stm32g0b1.dtsi @@ -14,7 +14,7 @@ clocks { clk_hsi48: clk-hsi48 { #clock-cells = <0>; - compatible = "fixed-clock"; + compatible = "st,stm32-hsi48-clock"; clock-frequency = ; status = "disabled"; }; @@ -38,9 +38,7 @@ interrupt-names = "LINE_0", "LINE_1"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00001000>; bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>; - sjw = <1>; sample-point = <875>; - sjw-data = <1>; sample-point-data = <875>; status = "disabled"; }; diff --git a/dts/arm/st/g4/stm32g4.dtsi b/dts/arm/st/g4/stm32g4.dtsi index 4cb4e702e6c..feec71388aa 100644 --- a/dts/arm/st/g4/stm32g4.dtsi +++ b/dts/arm/st/g4/stm32g4.dtsi @@ -109,14 +109,12 @@ interrupts = <18 0>; status = "disabled"; #io-channel-cells = <1>; - temp-channel = <16>; - vbat-channel = <17>; - vref-channel = <18>; resolutions = ; sampling-times = <3 7 13 25 48 93 248 641>; + st,adc-sequencer = ; }; adc2: adc@50000100 { @@ -131,6 +129,7 @@ STM32_ADC_RES(8, 0x02) STM32_ADC_RES(6, 0x03)>; sampling-times = <3 7 13 25 48 93 248 641>; + st,adc-sequencer = ; }; dac1: dac@50000800 { @@ -391,9 +390,7 @@ interrupt-names = "LINE_0", "LINE_1"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>; - sjw = <1>; sample-point = <875>; - sjw-data = <1>; sample-point-data = <875>; status = "disabled"; }; diff --git a/dts/arm/st/g4/stm32g473.dtsi b/dts/arm/st/g4/stm32g473.dtsi index d81eeb7f333..97565c33e73 100644 --- a/dts/arm/st/g4/stm32g473.dtsi +++ b/dts/arm/st/g4/stm32g473.dtsi @@ -39,6 +39,7 @@ STM32_ADC_RES(8, 0x02) STM32_ADC_RES(6, 0x03)>; sampling-times = <3 7 13 25 48 93 248 641>; + st,adc-sequencer = ; }; adc5: adc@50000600 { @@ -48,12 +49,12 @@ interrupts = <62 0>; status = "disabled"; #io-channel-cells = <1>; - temp-channel = <4>; resolutions = ; sampling-times = <3 7 13 25 48 93 248 641>; + st,adc-sequencer = ; }; spi4: spi@40013c00 { @@ -102,9 +103,7 @@ interrupt-names = "LINE_0", "LINE_1"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; bosch,mram-cfg = <0x6a0 28 8 3 3 0 3 3>; - sjw = <1>; sample-point = <875>; - sjw-data = <1>; sample-point-data = <875>; status = "disabled"; }; diff --git a/dts/arm/st/g4/stm32g491.dtsi b/dts/arm/st/g4/stm32g491.dtsi index 8d6990cbe23..865d3700d96 100644 --- a/dts/arm/st/g4/stm32g491.dtsi +++ b/dts/arm/st/g4/stm32g491.dtsi @@ -17,10 +17,8 @@ interrupts = <86 0>, <87 0>; interrupt-names = "LINE_0", "LINE_1"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; - sjw = <1>; bosch,mram-cfg = <0x350 28 8 3 3 0 3 3>; sample-point = <875>; - sjw-data = <1>; sample-point-data = <875>; status = "disabled"; }; @@ -64,12 +62,12 @@ interrupts = <47 0>; status = "disabled"; #io-channel-cells = <1>; - vref-channel = <18>; resolutions = ; sampling-times = <3 7 13 25 48 93 248 641>; + st,adc-sequencer = ; }; uart5: serial@40005000 { diff --git a/dts/arm/st/h5/stm32h5.dtsi b/dts/arm/st/h5/stm32h5.dtsi index 274ccda6511..d8a93a58619 100644 --- a/dts/arm/st/h5/stm32h5.dtsi +++ b/dts/arm/st/h5/stm32h5.dtsi @@ -263,14 +263,12 @@ status = "disabled"; vref-mv = <3300>; #io-channel-cells = <1>; - vbat-channel = <2>; - temp-channel = <16>; - vref-channel = <17>; resolutions = ; sampling-times = <3 7 13 25 48 93 248 641>; + st,adc-sequencer = ; }; rtc: rtc@44007800 { @@ -444,9 +442,7 @@ interrupt-names = "LINE_0", "LINE_1"; clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>; bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>; - sjw = <1>; sample-point = <875>; - sjw-data = <1>; sample-point-data = <875>; status = "disabled"; }; diff --git a/dts/arm/st/h5/stm32h562.dtsi b/dts/arm/st/h5/stm32h562.dtsi index 66df580219e..66ed8d3d927 100644 --- a/dts/arm/st/h5/stm32h562.dtsi +++ b/dts/arm/st/h5/stm32h562.dtsi @@ -178,6 +178,7 @@ STM32_ADC_RES(8, 0x02) STM32_ADC_RES(6, 0x03)>; sampling-times = <3 7 13 25 48 93 248 641>; + st,adc-sequencer = ; }; timers4: timers@40000800 { @@ -302,9 +303,7 @@ /* common clock FDCAN 1 & 2 */ clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>; bosch,mram-cfg = <0x350 28 8 3 3 0 3 3>; - sjw = <1>; sample-point = <875>; - sjw-data = <1>; sample-point-data = <875>; status = "disabled"; }; diff --git a/dts/arm/st/h7/stm32h7.dtsi b/dts/arm/st/h7/stm32h7.dtsi index c9f72afb784..58a01b962b2 100644 --- a/dts/arm/st/h7/stm32h7.dtsi +++ b/dts/arm/st/h7/stm32h7.dtsi @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include / { @@ -48,7 +50,7 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x90000000 DT_SIZE_M(256)>; zephyr,memory-region = "QSPI"; - zephyr,memory-attr = "EXTMEM"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_EXTMEM) )>; }; clocks { @@ -127,7 +129,7 @@ soc { flash: flash-controller@52002000 { - compatible = "st,stm32h7-flash-controller"; + compatible = "st,stm32-flash-controller", "st,stm32h7-flash-controller"; reg = <0x52002000 0x400>; interrupts = <4 0>; clocks = <&rcc STM32_CLOCK_BUS_AHB3 0x00000100>; @@ -473,9 +475,7 @@ interrupts = <19 0>, <21 0>, <63 0>; interrupt-names = "LINE_0", "LINE_1", "CALIB"; bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>; - sjw = <1>; sample-point = <875>; - sjw-data = <1>; sample-point-data = <875>; status = "disabled"; }; @@ -488,9 +488,7 @@ interrupts = <20 0>, <22 0>, <63 0>; interrupt-names = "LINE_0", "LINE_1", "CALIB"; bosch,mram-cfg = <0x350 28 8 3 3 0 3 3>; - sjw = <1>; sample-point = <875>; - sjw-data = <1>; sample-point-data = <875>; status = "disabled"; }; @@ -812,6 +810,7 @@ STM32_ADC_RES(10, 0x03) STM32_ADC_RES(8, 0x07)>; sampling-times = <2 3 9 17 33 65 388 811>; + st,adc-sequencer = ; }; adc2: adc@40022100 { @@ -827,6 +826,7 @@ STM32_ADC_RES(10, 0x03) STM32_ADC_RES(8, 0x07)>; sampling-times = <2 3 9 17 33 65 388 811>; + st,adc-sequencer = ; }; /* dual mode: adc1 and adc2 coupled */ @@ -843,6 +843,7 @@ STM32_ADC_RES(10, 0x03) STM32_ADC_RES(8, 0x07)>; sampling-times = <2 3 9 17 33 65 388 811>; + st,adc-sequencer = ; }; adc3: adc@58026000 { @@ -858,6 +859,7 @@ STM32_ADC_RES(10, 0x03) STM32_ADC_RES(8, 0x07)>; sampling-times = <2 3 9 17 33 65 388 811>; + st,adc-sequencer = ; }; dac1: dac@40007400 { diff --git a/dts/arm/st/h7/stm32h723.dtsi b/dts/arm/st/h7/stm32h723.dtsi index ad0827906b0..f1b0836f6e8 100644 --- a/dts/arm/st/h7/stm32h723.dtsi +++ b/dts/arm/st/h7/stm32h723.dtsi @@ -47,14 +47,12 @@ * ADC, so we redefine the resolution for these devices. */ adc3: adc@58026000 { - vbat-channel = <16>; - temp-channel = <17>; - vref-channel = <18>; resolutions = ; sampling-times = <3 7 13 25 48 93 248 641>; + st,adc-sequencer = ; }; dmamux1: dmamux@40020800 { @@ -125,9 +123,7 @@ interrupts = <159 0>, <160 0>, <63 0>; interrupt-names = "LINE_0", "LINE_1", "CALIB"; bosch,mram-cfg = <0x6a0 28 8 3 3 0 3 3>; - sjw = <1>; sample-point = <875>; - sjw-data = <1>; sample-point-data = <875>; status = "disabled"; }; diff --git a/dts/arm/st/h7/stm32h743.dtsi b/dts/arm/st/h7/stm32h743.dtsi index 6ba4a7a23ce..ca25961cde6 100644 --- a/dts/arm/st/h7/stm32h743.dtsi +++ b/dts/arm/st/h7/stm32h743.dtsi @@ -21,12 +21,6 @@ }; }; - adc3: adc@58026000 { - vbat-channel = <17>; - temp-channel = <18>; - vref-channel = <19>; - }; - dmamux1: dmamux@40020800 { dma-requests= <107>; }; diff --git a/dts/arm/st/h7/stm32h745.dtsi b/dts/arm/st/h7/stm32h745.dtsi index d0483adf653..5cfa418cc60 100644 --- a/dts/arm/st/h7/stm32h745.dtsi +++ b/dts/arm/st/h7/stm32h745.dtsi @@ -28,12 +28,6 @@ }; }; - adc3: adc@58026000 { - vbat-channel = <17>; - temp-channel = <18>; - vref-channel = <19>; - }; - dmamux1: dmamux@40020800 { dma-requests= <107>; }; diff --git a/dts/arm/st/h7/stm32h750.dtsi b/dts/arm/st/h7/stm32h750.dtsi index 73167a4e1b2..50d20175b55 100644 --- a/dts/arm/st/h7/stm32h750.dtsi +++ b/dts/arm/st/h7/stm32h750.dtsi @@ -21,12 +21,6 @@ }; }; - adc3: adc@58026000 { - vbat-channel = <17>; - temp-channel = <18>; - vref-channel = <19>; - }; - dmamux1: dmamux@40020800 { dma-requests= <107>; }; diff --git a/dts/arm/st/h7/stm32h7a3.dtsi b/dts/arm/st/h7/stm32h7a3.dtsi index cfcf5862991..7f85387ca06 100644 --- a/dts/arm/st/h7/stm32h7a3.dtsi +++ b/dts/arm/st/h7/stm32h7a3.dtsi @@ -24,12 +24,6 @@ }; }; - adc2: adc@40022100 { - vbat-channel = <14>; - temp-channel = <18>; - vref-channel = <19>; - }; - dmamux1: dmamux@40020800 { dma-requests= <107>; }; diff --git a/dts/arm/st/h7/stm32h7b0.dtsi b/dts/arm/st/h7/stm32h7b0.dtsi new file mode 100644 index 00000000000..043c3fee302 --- /dev/null +++ b/dts/arm/st/h7/stm32h7b0.dtsi @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Charles Dias + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* + * STM32H7B0 line contains the same peripherals as STM32H7A3, + * with addition of CRYPTO/HASH and OTFDEC peripherals. + */ +/ { + soc { + compatible = "st,stm32h7b0", "st,stm32h7", "simple-bus"; + + cryp: cryp@48021000 { + compatible = "st,stm32-cryp"; + reg = <0x48021000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000010>; + interrupts = <79 0>; + interrupt-names = "cryp"; + status = "disabled"; + }; + }; +}; diff --git a/dts/arm/st/h7/stm32h7b0Xb.dtsi b/dts/arm/st/h7/stm32h7b0Xb.dtsi new file mode 100644 index 00000000000..884e22edc8e --- /dev/null +++ b/dts/arm/st/h7/stm32h7b0Xb.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 Charles Dias + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +/ { + soc { + flash-controller@52002000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_K(128)>; + }; + }; + }; +}; diff --git a/dts/arm/st/h7/stm32h7b3.dtsi b/dts/arm/st/h7/stm32h7b3.dtsi index a104f58a192..f8b583b9d75 100644 --- a/dts/arm/st/h7/stm32h7b3.dtsi +++ b/dts/arm/st/h7/stm32h7b3.dtsi @@ -5,23 +5,13 @@ */ #include -#include +#include /* - * STM32H7B3 line contains the same peripherals as STM32H7A3, - * with addition of CRYPTO/HASH and OTFDEC peripherals + * STM32H7B3 line contains the same peripherals as STM32H7B0. */ / { soc { compatible = "st,stm32h7b3", "st,stm32h7", "simple-bus"; - - cryp: cryp@48021000 { - compatible = "st,stm32-cryp"; - reg = <0x48021000 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000010>; - interrupts = <79 0>; - interrupt-names = "cryp"; - status = "disabled"; - }; }; }; diff --git a/dts/arm/st/l0/stm32l0.dtsi b/dts/arm/st/l0/stm32l0.dtsi index 2a77be4c636..b05dbff210d 100644 --- a/dts/arm/st/l0/stm32l0.dtsi +++ b/dts/arm/st/l0/stm32l0.dtsi @@ -309,14 +309,13 @@ interrupts = <12 0>; status = "disabled"; #io-channel-cells = <1>; - temp-channel = <18>; - vref-channel = <17>; resolutions = ; sampling-times = <2 4 8 13 20 40 80 161>; num-sampling-time-common-channels = <1>; + st,adc-sequencer = ; }; dma1: dma@40020000 { diff --git a/dts/arm/st/l0/stm32l010.dtsi b/dts/arm/st/l0/stm32l010.dtsi index db206db3721..503bbf3bd0f 100644 --- a/dts/arm/st/l0/stm32l010.dtsi +++ b/dts/arm/st/l0/stm32l010.dtsi @@ -9,9 +9,5 @@ / { soc { compatible = "st,stm32l010", "st,stm32l0", "simple-bus"; - - eeprom: eeprom@8080000{ - reg = <0x08080000 512>; - }; }; }; diff --git a/dts/arm/st/l0/stm32l010X4.dtsi b/dts/arm/st/l0/stm32l010X4.dtsi new file mode 100644 index 00000000000..e1e25f4d5dc --- /dev/null +++ b/dts/arm/st/l0/stm32l010X4.dtsi @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 OS Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + sram0: memory@20000000 { + reg = <0x20000000 DT_SIZE_K(2)>; + }; + + soc { + eeprom: eeprom@8080000{ + reg = <0x08080000 128>; + }; + + flash-controller@40022000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_K(16)>; + }; + }; + }; +}; diff --git a/dts/arm/st/l0/stm32l010X6.dtsi b/dts/arm/st/l0/stm32l010X6.dtsi new file mode 100644 index 00000000000..df6ad2c514f --- /dev/null +++ b/dts/arm/st/l0/stm32l010X6.dtsi @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 OS Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + sram0: memory@20000000 { + reg = <0x20000000 DT_SIZE_K(8)>; + }; + + soc { + eeprom: eeprom@8080000{ + reg = <0x08080000 256>; + }; + + flash-controller@40022000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_K(32)>; + }; + }; + }; +}; diff --git a/dts/arm/st/l0/stm32l010X8.dtsi b/dts/arm/st/l0/stm32l010X8.dtsi new file mode 100644 index 00000000000..2d0b4a2e220 --- /dev/null +++ b/dts/arm/st/l0/stm32l010X8.dtsi @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 OS Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + sram0: memory@20000000 { + reg = <0x20000000 DT_SIZE_K(8)>; + }; + + soc { + eeprom: eeprom@8080000{ + reg = <0x08080000 256>; + }; + + flash-controller@40022000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_K(64)>; + }; + }; + }; +}; diff --git a/dts/arm/st/l0/stm32l010Xb.dtsi b/dts/arm/st/l0/stm32l010Xb.dtsi index 57433c87972..9b35bbe9f7b 100644 --- a/dts/arm/st/l0/stm32l010Xb.dtsi +++ b/dts/arm/st/l0/stm32l010Xb.dtsi @@ -13,6 +13,10 @@ }; soc { + eeprom: eeprom@8080000{ + reg = <0x08080000 512>; + }; + flash-controller@40022000 { flash0: flash@8000000 { reg = <0x08000000 DT_SIZE_K(128)>; diff --git a/dts/arm/st/l0/stm32l011X4.dtsi b/dts/arm/st/l0/stm32l011X4.dtsi index bb6dcfb70c4..e2d7b5eafd3 100644 --- a/dts/arm/st/l0/stm32l011X4.dtsi +++ b/dts/arm/st/l0/stm32l011X4.dtsi @@ -19,8 +19,8 @@ }; }; - adc1: adc@40012400 { - temp-channel = <18>; + eeprom: eeprom@8080000{ + reg = <0x08080000 512>; }; }; }; diff --git a/dts/arm/st/l0/stm32l031.dtsi b/dts/arm/st/l0/stm32l031.dtsi index 7cf9fdb8698..18cb9e5160c 100644 --- a/dts/arm/st/l0/stm32l031.dtsi +++ b/dts/arm/st/l0/stm32l031.dtsi @@ -30,9 +30,5 @@ eeprom: eeprom@8080000{ reg = <0x08080000 DT_SIZE_K(1)>; }; - - adc1: adc@40012400 { - temp-channel = <18>; - }; }; }; diff --git a/dts/arm/st/l0/stm32l051.dtsi b/dts/arm/st/l0/stm32l051.dtsi index 93266f7e02b..e6209dc531b 100644 --- a/dts/arm/st/l0/stm32l051.dtsi +++ b/dts/arm/st/l0/stm32l051.dtsi @@ -72,9 +72,5 @@ eeprom: eeprom@8080000{ reg = <0x08080000 DT_SIZE_K(2)>; }; - - adc1: adc@40012400 { - temp-channel = <18>; - }; }; }; diff --git a/dts/arm/st/l0/stm32l071.dtsi b/dts/arm/st/l0/stm32l071.dtsi index a01ea5800bf..56d88c5bd51 100644 --- a/dts/arm/st/l0/stm32l071.dtsi +++ b/dts/arm/st/l0/stm32l071.dtsi @@ -160,9 +160,5 @@ eeprom: eeprom@8080000{ reg = <0x08080000 DT_SIZE_K(6)>; }; - - adc1: adc@40012400 { - temp-channel = <18>; - }; }; }; diff --git a/dts/arm/st/l0/stm32l081.dtsi b/dts/arm/st/l0/stm32l081.dtsi new file mode 100644 index 00000000000..05a473a3e1b --- /dev/null +++ b/dts/arm/st/l0/stm32l081.dtsi @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 Caspar Friedrich + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + soc { + compatible = "st,stm32l081", "st,stm32l0", "simple-bus"; + }; +}; diff --git a/dts/arm/st/l0/stm32l081Xz.dtsi b/dts/arm/st/l0/stm32l081Xz.dtsi new file mode 100644 index 00000000000..d6f28ceecce --- /dev/null +++ b/dts/arm/st/l0/stm32l081Xz.dtsi @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 Caspar Friedrich + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + sram0: memory@20000000 { + reg = <0x20000000 DT_SIZE_K(20)>; + }; + + soc { + flash-controller@40022000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_K(192)>; + }; + }; + }; +}; diff --git a/dts/arm/st/l1/stm32l1.dtsi b/dts/arm/st/l1/stm32l1.dtsi index 2f7cc7deb03..0203f740c83 100644 --- a/dts/arm/st/l1/stm32l1.dtsi +++ b/dts/arm/st/l1/stm32l1.dtsi @@ -216,14 +216,13 @@ interrupts = <18 0>; status = "disabled"; #io-channel-cells = <1>; - temp-channel = <16>; - vref-channel = <17>; resolutions = ; sampling-times = <4 9 16 24 48 96 192 384>; st,adc-clock-source = ; + st,adc-sequencer = ; }; dac1: dac@40007400 { diff --git a/dts/arm/st/l4/stm32l4.dtsi b/dts/arm/st/l4/stm32l4.dtsi index b37f95def3e..f2b8c1a2ff6 100644 --- a/dts/arm/st/l4/stm32l4.dtsi +++ b/dts/arm/st/l4/stm32l4.dtsi @@ -390,14 +390,12 @@ interrupts = <18 0>; status = "disabled"; #io-channel-cells = <1>; - temp-channel = <17>; - vbat-channel = <18>; - vref-channel = <0>; resolutions = ; sampling-times = <3 7 13 25 48 93 248 641>; + st,adc-sequencer = ; }; adc2: adc@50040100 { @@ -412,6 +410,7 @@ STM32_ADC_RES(8, 0x02) STM32_ADC_RES(6, 0x03)>; sampling-times = <3 7 13 25 48 93 248 641>; + st,adc-sequencer = ; }; dma1: dma@40020000 { diff --git a/dts/arm/st/l4/stm32l431.dtsi b/dts/arm/st/l4/stm32l431.dtsi index d25d3bc1c22..9a9892a0f4d 100644 --- a/dts/arm/st/l4/stm32l431.dtsi +++ b/dts/arm/st/l4/stm32l431.dtsi @@ -107,7 +107,6 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; interrupts = <19 0>, <20 0>, <21 0>, <22 0>; interrupt-names = "TX", "RX0", "RX1", "SCE"; - sjw = <1>; sample-point = <875>; status = "disabled"; }; diff --git a/dts/arm/st/l4/stm32l432.dtsi b/dts/arm/st/l4/stm32l432.dtsi index 3ad6a2e3aae..9db0a1e244e 100644 --- a/dts/arm/st/l4/stm32l432.dtsi +++ b/dts/arm/st/l4/stm32l432.dtsi @@ -57,7 +57,6 @@ interrupt-names = "TX", "RX0", "RX1", "SCE"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; //RCC_APB1ENR1_CAN1EN status = "disabled"; - sjw = <1>; sample-point = <875>; }; diff --git a/dts/arm/st/l4/stm32l451.dtsi b/dts/arm/st/l4/stm32l451.dtsi index a8722ed5890..b566db4336a 100644 --- a/dts/arm/st/l4/stm32l451.dtsi +++ b/dts/arm/st/l4/stm32l451.dtsi @@ -141,7 +141,6 @@ interrupt-names = "TX", "RX0", "RX1", "SCE"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; //RCC_APB1ENR1_CAN1EN status = "disabled"; - sjw = <1>; sample-point = <875>; }; diff --git a/dts/arm/st/l4/stm32l471.dtsi b/dts/arm/st/l4/stm32l471.dtsi index e180b1310c0..c1f5b5978a0 100644 --- a/dts/arm/st/l4/stm32l471.dtsi +++ b/dts/arm/st/l4/stm32l471.dtsi @@ -232,7 +232,6 @@ interrupt-names = "TX", "RX0", "RX1", "SCE"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; //RCC_APB1ENR1_CAN1EN status = "disabled"; - sjw = <1>; sample-point = <875>; }; @@ -261,7 +260,6 @@ interrupts = <47 0>; status = "disabled"; #io-channel-cells = <1>; - temp-channel = <17>; }; rtc@40002800 { diff --git a/dts/arm/st/l4/stm32l496.dtsi b/dts/arm/st/l4/stm32l496.dtsi index d253a945415..c11eba47796 100644 --- a/dts/arm/st/l4/stm32l496.dtsi +++ b/dts/arm/st/l4/stm32l496.dtsi @@ -54,8 +54,8 @@ interrupts = <86 0>, <87 0>, <88 0>, <89 0>; interrupt-names = "TX", "RX0", "RX1", "SCE"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x04000000>; //RCC_APB1ENR1_CAN2EN + master-can-reg = <0x40006400>; status = "disabled"; - sjw = <1>; sample-point = <875>; }; diff --git a/dts/arm/st/l4/stm32l4p5.dtsi b/dts/arm/st/l4/stm32l4p5.dtsi index d84f2d164e7..03973dcf077 100644 --- a/dts/arm/st/l4/stm32l4p5.dtsi +++ b/dts/arm/st/l4/stm32l4p5.dtsi @@ -291,7 +291,6 @@ interrupt-names = "TX", "RX0", "RX1", "SCE"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; //RCC_APB1ENR1_CAN1EN status = "disabled"; - sjw = <1>; sample-point = <875>; }; diff --git a/dts/arm/st/l5/stm32l5.dtsi b/dts/arm/st/l5/stm32l5.dtsi index e5b9f1b7a62..c8c94319353 100644 --- a/dts/arm/st/l5/stm32l5.dtsi +++ b/dts/arm/st/l5/stm32l5.dtsi @@ -659,14 +659,12 @@ interrupts = <37 0>; status = "disabled"; #io-channel-cells = <1>; - temp-channel = <17>; - vbat-channel = <18>; - vref-channel = <0>; resolutions = ; sampling-times = <3 7 13 25 48 93 248 641>; + st,adc-sequencer = ; }; adc2: adc@42028100 { @@ -681,6 +679,7 @@ STM32_ADC_RES(8, 0x02) STM32_ADC_RES(6, 0x03)>; sampling-times = <3 7 13 25 48 93 248 641>; + st,adc-sequencer = ; }; usb: usb@4000d400 { diff --git a/dts/arm/st/mp1/stm32mp157.dtsi b/dts/arm/st/mp1/stm32mp157.dtsi index aaa653280cc..f70a96b6ead 100644 --- a/dts/arm/st/mp1/stm32mp157.dtsi +++ b/dts/arm/st/mp1/stm32mp157.dtsi @@ -39,6 +39,8 @@ }; soc { + compatible = "st,stm32mp157", "st,stm32mp1", "simple-bus"; + rcc: rcc@50000000 { compatible = "st,stm32mp1-rcc"; reg = <0x50000000 0x1000>; diff --git a/dts/arm/st/u5/stm32u5.dtsi b/dts/arm/st/u5/stm32u5.dtsi index 6e70397a6dc..7363181e663 100644 --- a/dts/arm/st/u5/stm32u5.dtsi +++ b/dts/arm/st/u5/stm32u5.dtsi @@ -443,7 +443,7 @@ #address-cells = <1>; #size-cells = <0>; reg = <0x40009400 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>; + clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000020>; interrupts = <68 0>; interrupt-names = "global"; st,static-prescaler; @@ -728,6 +728,35 @@ status = "disabled"; }; + /* + * The SDMMC domain clock can be chosen between ICLK and PLL1P. + * But ICLK is itself chosen among HSI48 (the default), PLL2Q, + * PLL1Q and MSIK. + * + * Currently, configuring ICLK is unsupported. When support for + * ICLK comes in the future, the clock source for sdmmc1 and + * sdmmc2 will have to be replaced with STM32_SRC_ICLK. + */ + sdmmc1: sdmmc@420c8000 { + compatible = "st,stm32-sdmmc"; + reg = <0x420c8000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x08000000>, + <&rcc STM32_SRC_HSI48 SDMMC_SEL(0)>; + resets = <&rctl STM32_RESET(AHB2L, 27U)>; + interrupts = <78 0>; + status = "disabled"; + }; + + sdmmc2: sdmmc@420c8c00 { + compatible = "st,stm32-sdmmc"; + reg = <0x420c8c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x10000000>, + <&rcc STM32_SRC_HSI48 SDMMC_SEL(0)>; + resets = <&rctl STM32_RESET(AHB2L, 28U)>; + interrupts = <79 0>; + status = "disabled"; + }; + dac1: dac@46021800 { compatible = "st,stm32-dac"; reg = <0x46021800 0x400>; @@ -743,15 +772,13 @@ interrupts = <37 0>; status = "disabled"; #io-channel-cells = <1>; - temp-channel = <19>; - vref-channel = <0>; - vbat-channel = <18>; resolutions = ; sampling-times = <5 6 12 20 36 68 391 814>; st,adc-clock-source = ; + st,adc-sequencer = ; }; adc4: adc@46021000 { @@ -761,9 +788,6 @@ interrupts = <113 0>; status = "disabled"; #io-channel-cells = <1>; - temp-channel = <13>; - vref-channel = <0>; - vbat-channel = <14>; resolutions = ; num-sampling-time-common-channels = <2>; st,adc-clock-source = ; + st,adc-sequencer = ; }; fdcan1: can@4000a400 { @@ -781,9 +806,7 @@ interrupt-names = "LINE_0", "LINE_1"; clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>; bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>; - sjw = <1>; sample-point = <875>; - sjw-data = <1>; sample-point-data = <875>; status = "disabled"; }; diff --git a/dts/arm/st/u5/stm32u595.dtsi b/dts/arm/st/u5/stm32u595.dtsi index 2d7ffe1145d..db489205f95 100644 --- a/dts/arm/st/u5/stm32u595.dtsi +++ b/dts/arm/st/u5/stm32u595.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2023 PSICONTROl nv + * Copyright (c) 2023 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,6 +10,8 @@ / { soc { + compatible = "st,stm32u595", "st,stm32u5", "simple-bus"; + pinctrl: pin-controller@42020000 { compatible = "st,stm32-pinctrl"; #address-cells = <1>; @@ -56,5 +59,42 @@ interrupt-names = "event", "error"; status = "disabled"; }; + + /* Available in STM32U59x/5Ax/5Fx/5Gx SoCs */ + adc2: adc@42028100 { + compatible = "st,stm32-adc"; + reg = <0x42028100 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000400>; + interrupts = <37 0>; + status = "disabled"; + #io-channel-cells = <1>; + resolutions = ; + sampling-times = <5 6 12 20 36 68 391 814>; + st,adc-clock-source = ; + st,adc-sequencer = ; + }; + + /* + * Available in STM32U59x/5Ax/5Fx/5Gx SoCs + * dual mode: adc1 and adc2 coupled + */ + adc1_2: adc@42028300 { + compatible = "st,stm32-adc"; + reg = <0x42028300 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000400>; + interrupts = <37 0>; + status = "disabled"; + #io-channel-cells = <1>; + resolutions = ; + sampling-times = <5 6 12 20 36 68 391 814>; + st,adc-clock-source = ; + st,adc-sequencer = ; + }; }; }; diff --git a/dts/arm/st/u5/stm32u599.dtsi b/dts/arm/st/u5/stm32u599.dtsi index d3ecfb7c56a..f72d22c5f1a 100644 --- a/dts/arm/st/u5/stm32u599.dtsi +++ b/dts/arm/st/u5/stm32u599.dtsi @@ -5,3 +5,9 @@ */ #include + +/ { + soc { + compatible = "st,stm32u599", "st,stm32u5", "simple-bus"; + }; +}; diff --git a/dts/arm/st/u5/stm32u5a5.dtsi b/dts/arm/st/u5/stm32u5a5.dtsi new file mode 100644 index 00000000000..bc8ba619020 --- /dev/null +++ b/dts/arm/st/u5/stm32u5a5.dtsi @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + soc { + compatible = "st,stm32u5a5", "st,stm32u5", "simple-bus"; + }; +}; diff --git a/dts/arm/st/u5/stm32u5a5Xj.dtsi b/dts/arm/st/u5/stm32u5a5Xj.dtsi new file mode 100644 index 00000000000..6719e89619d --- /dev/null +++ b/dts/arm/st/u5/stm32u5a5Xj.dtsi @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + sram0: memory@20000000 { + /* SRAM1 + SRAM2 + SRAM3 + SRAM5 */ + reg = <0x20000000 DT_SIZE_K(2496)>; + }; + sram1: memory@28000000 { + /* SRAM4 */ + reg = <0x28000000 DT_SIZE_K(16)>; + }; + + soc { + flash-controller@40022000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_M(4)>; + }; + }; + }; +}; diff --git a/dts/arm/st/u5/stm32u5a9.dtsi b/dts/arm/st/u5/stm32u5a9.dtsi new file mode 100644 index 00000000000..13cd1e1401d --- /dev/null +++ b/dts/arm/st/u5/stm32u5a9.dtsi @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + soc { + compatible = "st,stm32u5a9", "st,stm32u5", "simple-bus"; + }; +}; diff --git a/dts/arm/st/u5/stm32u5a9Xj.dtsi b/dts/arm/st/u5/stm32u5a9Xj.dtsi new file mode 100644 index 00000000000..1b9b7cadd75 --- /dev/null +++ b/dts/arm/st/u5/stm32u5a9Xj.dtsi @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + sram0: memory@20000000 { + /* SRAM1 + SRAM2 + SRAM3 + SRAM5 */ + /* 768K + 64K + 832K + 832K */ + reg = <0x20000000 DT_SIZE_K(2496)>; + }; + sram1: memory@28000000 { + /* SRAM4, low-power background autonomous mode */ + reg = <0x28000000 DT_SIZE_K(16)>; + }; + + soc { + flash-controller@40022000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_M(4)>; + }; + }; + }; +}; diff --git a/dts/arm/st/wb/stm32wb.dtsi b/dts/arm/st/wb/stm32wb.dtsi index 6f9f0ba4858..f6a1c785b86 100644 --- a/dts/arm/st/wb/stm32wb.dtsi +++ b/dts/arm/st/wb/stm32wb.dtsi @@ -413,14 +413,12 @@ interrupts = <18 0>; status = "disabled"; #io-channel-cells = <1>; - temp-channel = <17>; - vbat-channel = <18>; - vref-channel = <0>; resolutions = ; sampling-times = <3 7 13 25 48 93 248 641>; + st,adc-sequencer = ; }; iwdg: watchdog@40003000 { @@ -503,6 +501,14 @@ clocks = <&rcc STM32_CLOCK_BUS_AHB3 0x00040000>; status = "disabled"; }; + + aes1: aes@50060000 { + compatible = "st,stm32-aes"; + reg = <0x50060000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00010000>; + interrupts = <51 0>; + status = "disabled"; + }; }; die_temp: dietemp { diff --git a/dts/arm/st/wb/stm32wb55.dtsi b/dts/arm/st/wb/stm32wb55.dtsi index b5c3bc7a82c..42eee13072a 100644 --- a/dts/arm/st/wb/stm32wb55.dtsi +++ b/dts/arm/st/wb/stm32wb55.dtsi @@ -9,9 +9,5 @@ / { soc { compatible = "st,stm32wb55", "st,stm32wb", "simple-bus"; - - adc1: adc@50040000 { - temp-channel = <17>; - }; }; }; diff --git a/dts/arm/st/wba/stm32wba.dtsi b/dts/arm/st/wba/stm32wba.dtsi index d489143ec71..6c5cc8f869a 100644 --- a/dts/arm/st/wba/stm32wba.dtsi +++ b/dts/arm/st/wba/stm32wba.dtsi @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -188,6 +189,14 @@ }; }; + rtc: rtc@46007800 { + compatible = "st,stm32-rtc"; + reg = <0x46007800 0x400>; + interrupts = <2 0>; + clocks = <&rcc STM32_CLOCK_BUS_APB7 0x00200000>; + status = "disabled"; + }; + iwdg: watchdog@40003000 { compatible = "st,stm32-watchdog"; reg = <0x40003000 0x400>; @@ -388,9 +397,6 @@ interrupts = <65 0>; status = "disabled"; #io-channel-cells = <1>; - temp-channel = <19>; - vref-channel = <0>; - vbat-channel = <18>; resolutions = ; num-sampling-time-common-channels = <2>; st,adc-clock-source = ; + st,adc-sequencer = ; }; lptim1: timers@46004400 { @@ -432,6 +439,18 @@ health-test-config = <0xaac7>; status = "disabled"; }; + + gpdma1: dma@40020000 { + compatible = "st,stm32u5-dma"; + #dma-cells = <3>; + reg = <0x40020000 0x1000>; + interrupts = <29 0 30 0 31 0 32 0 33 0 34 0 35 0 36 0>; + clocks = <&rcc STM32_CLOCK_BUS_AHB1 0x1>; + dma-channels = <8>; + dma-requests = <52>; + dma-offset = <0>; + status = "disabled"; + }; }; }; diff --git a/dts/arm/st/wba/stm32wba52Xg.dtsi b/dts/arm/st/wba/stm32wba52Xg.dtsi index 49724f35e5c..f4ddcbbc9e7 100644 --- a/dts/arm/st/wba/stm32wba52Xg.dtsi +++ b/dts/arm/st/wba/stm32wba52Xg.dtsi @@ -12,6 +12,8 @@ }; soc { + compatible = "st,stm32wba52", "st,stm32wba", "simple-bus"; + flash-controller@40022000 { flash0: flash@8000000 { reg = <0x08000000 DT_SIZE_M(1)>; diff --git a/dts/arm/st/wl/stm32wl.dtsi b/dts/arm/st/wl/stm32wl.dtsi index 26da70106c1..cc4b4dc31c9 100644 --- a/dts/arm/st/wl/stm32wl.dtsi +++ b/dts/arm/st/wl/stm32wl.dtsi @@ -207,6 +207,18 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>; prescaler = <32768>; status = "disabled"; + + /* In STM32WL, the backup registers are defined as part of the TAMP + * peripheral. This peripheral is not implemented in Zephyr yet, however, + * the reference manual states that tamp_pclk is connected to rtc_pclk. + * It makes sense to have BBRAM instantiated as a child of RTC, so that + * the driver can verify that its parent device (RTC) is ready. + */ + bbram: backup_regs { + compatible = "st,stm32-bbram"; + st,backup-regs = <20>; + status = "disabled"; + }; }; iwdg: watchdog@40003000 { @@ -332,15 +344,13 @@ interrupts = <18 0>; status = "disabled"; #io-channel-cells = <1>; - temp-channel = <12>; - vref-channel = <13>; - vbat-channel = <14>; resolutions = ; sampling-times = <2 4 8 13 20 40 80 161>; num-sampling-time-common-channels = <2>; + st,adc-sequencer = ; }; dac1: dac@40007400 { diff --git a/dts/arm/ti/am62x_m4.dtsi b/dts/arm/ti/am62x_m4.dtsi index 22de7a14f82..8d5e5a14c40 100644 --- a/dts/arm/ti/am62x_m4.dtsi +++ b/dts/arm/ti/am62x_m4.dtsi @@ -8,6 +8,7 @@ #include #include #include +#include / { @@ -54,6 +55,16 @@ reg-shift = <2>; status = "disabled"; }; + + gpio0: gpio@4201010 { + compatible = "ti,davinci-gpio"; + reg = <0x4201010 0x100>; + #address-cells = <2>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <24>; + status = "disabled"; + }; }; &nvic { diff --git a/dts/arm64/broadcom/bcm2711.dtsi b/dts/arm64/broadcom/bcm2711.dtsi new file mode 100644 index 00000000000..038d8dc4d6c --- /dev/null +++ b/dts/arm64/broadcom/bcm2711.dtsi @@ -0,0 +1,95 @@ +/* + * Copyright 2023 honglin leng + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + reg = <0>; + }; + }; + + interrupt-parent = <&gic>; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + soc { + sram0: memory@200000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0x200000 0x80000>; + }; + + gic: interrupt-controller@ff841000 { + compatible = "arm,gic-v2", "arm,gic"; + reg = <0xff841000 0x1000>, + <0xff842000 0x2000>; + interrupt-controller; + #interrupt-cells = <4>; + status = "okay"; + }; + + gpio: gpio@fe200000 { + compatible = "simple-bus"; + reg = <0xfe200000 0xf4>; + #address-cells = <1>; + #size-cells = <0>; + + /* GPIO 0 ~ 27 */ + gpio0: gpio@0 { + compatible = "brcm,bcm2711-gpio"; + reg = <0>; + interrupts = ; + gpio-controller; + #gpio-cells = <2>; + ngpios = <28>; + status = "disabled"; + }; + + /* GPIO 28 ~ 45 */ + gpio1: gpio@1c { + compatible = "brcm,bcm2711-gpio"; + reg = <28>; + interrupts = ; + gpio-controller; + #gpio-cells = <2>; + ngpios = <18>; + status = "disabled"; + }; + }; + + uart1: uart@fe215040 { + compatible = "brcm,bcm2711-aux-uart"; + reg = <0xfe215040 0x40>; + clock-frequency = ; + interrupts = ; + status = "disabled"; + }; + }; +}; diff --git a/dts/arm64/fvp/fvp-aemv8r.dtsi b/dts/arm64/fvp/fvp-aemv8r.dtsi index 05ac898bf33..7b11948cfe1 100644 --- a/dts/arm64/fvp/fvp-aemv8r.dtsi +++ b/dts/arm64/fvp/fvp-aemv8r.dtsi @@ -118,11 +118,13 @@ mdio: mdio { compatible = "smsc,lan91c111-mdio"; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; - phy: phy { + phy: ethernet-phy@0 { compatible = "ethernet-phy"; status = "disabled"; - address = <0>; + reg = <0>; }; }; }; diff --git a/dts/arm64/intel/intel_socfpga_agilex.dtsi b/dts/arm64/intel/intel_socfpga_agilex.dtsi index 63ef2c9629f..19957a19988 100644 --- a/dts/arm64/intel/intel_socfpga_agilex.dtsi +++ b/dts/arm64/intel/intel_socfpga_agilex.dtsi @@ -112,7 +112,7 @@ }; sip_smc: smc{ - compatible = "intel,agilex-socfpga-sip-smc"; + compatible = "intel,socfpga-agilex-sip-smc"; method = "smc"; status = "disabled"; zephyr,num-clients = <2>; diff --git a/dts/arm64/intel/intel_socfpga_agilex5.dtsi b/dts/arm64/intel/intel_socfpga_agilex5.dtsi index 7ecdac4fc9e..6a98aa34df9 100644 --- a/dts/arm64/intel/intel_socfpga_agilex5.dtsi +++ b/dts/arm64/intel/intel_socfpga_agilex5.dtsi @@ -160,4 +160,11 @@ resets = <&reset RSTMGR_L4SYSTIMER1_RSTLINE>; status = "disabled"; }; + + sip_smc: smc{ + compatible = "intel,socfpga-agilex-sip-smc"; + method = "smc"; + status = "disabled"; + zephyr,num-clients = <2>; + }; }; diff --git a/dts/arm64/nxp/nxp_mimx8mm_a53.dtsi b/dts/arm64/nxp/nxp_mimx8mm_a53.dtsi index 605729969db..b7d80992d8e 100644 --- a/dts/arm64/nxp/nxp_mimx8mm_a53.dtsi +++ b/dts/arm64/nxp/nxp_mimx8mm_a53.dtsi @@ -17,7 +17,6 @@ chosen { zephyr,console = &uart2; zephyr,shell-uart = &uart2; - zephyr,sram = &sram0; }; cpus { diff --git a/dts/arm64/nxp/nxp_mimx8mn_a53.dtsi b/dts/arm64/nxp/nxp_mimx8mn_a53.dtsi index d76cc40438e..8902380f46a 100644 --- a/dts/arm64/nxp/nxp_mimx8mn_a53.dtsi +++ b/dts/arm64/nxp/nxp_mimx8mn_a53.dtsi @@ -17,7 +17,6 @@ chosen { zephyr,console = &uart2; zephyr,shell-uart = &uart2; - zephyr,sram = &sram0; }; cpus { diff --git a/dts/arm64/nxp/nxp_mimx93_a55.dtsi b/dts/arm64/nxp/nxp_mimx93_a55.dtsi index 1e73bff224f..22a61e2dfca 100644 --- a/dts/arm64/nxp/nxp_mimx93_a55.dtsi +++ b/dts/arm64/nxp/nxp_mimx93_a55.dtsi @@ -7,19 +7,13 @@ #include #include #include -#include +#include #include / { #address-cells = <1>; #size-cells = <1>; - chosen { - zephyr,console = &uart2; - zephyr,shell-uart = &uart2; - zephyr,sram = &sram0; - }; - cpus { #address-cells = <1>; #size-cells = <0>; @@ -76,7 +70,7 @@ }; ccm: ccm@44450000 { - compatible = "nxp,imx-ccm"; + compatible = "nxp,imx-ccm-rev2"; reg = <0x44450000 DT_SIZE_K(64)>; #clock-cells = <3>; }; @@ -87,7 +81,7 @@ interrupts = ; interrupt-names = "irq_0"; interrupt-parent = <&gic>; - clocks = <&ccm IMX_CCM_LPUART_CLK 0x6c 24>; + clocks = <&ccm IMX_CCM_LPUART1_CLK 0x6c 24>; status = "disabled"; }; @@ -97,7 +91,7 @@ interrupts = ; interrupt-names = "irq_0"; interrupt-parent = <&gic>; - clocks = <&ccm IMX_CCM_LPUART_CLK 0x6c 24>; + clocks = <&ccm IMX_CCM_LPUART2_CLK 0x6c 24>; status = "disabled"; }; }; diff --git a/dts/arm64/rockchip/rk3568.dtsi b/dts/arm64/rockchip/rk3568.dtsi new file mode 100644 index 00000000000..360851987a2 --- /dev/null +++ b/dts/arm64/rockchip/rk3568.dtsi @@ -0,0 +1,89 @@ +/* + * Copyright 2020 NXP + * Copyright 2022 HNU-ESNL + * Copyright 2022 openEuler SIG-Zephyr + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + + +/ { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "rockchip,rk3568"; + interrupt-parent = <&gic>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@000 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + enable-method = "psci"; + reg = <0x000>; + }; + + cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + enable-method = "psci"; + reg = <0x100>; + }; + + cpu@200 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + enable-method = "psci"; + reg = <0x200>; + + }; + + cpu@300 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + enable-method = "psci"; + reg = <0x300>; + }; + }; + + gic: interrupt-controller@fd400000 { + #address-cells = <1>; + compatible = "arm,gic-v3","arm,gic"; + #interrupt-cells = <4>; + interrupt-controller; + + reg = <0xfd400000 0x10000>, /* GICD */ + <0xfd460000 0xc0000>; /* GICR */ + status = "okay"; + }; + + psci { + compatible = "arm,psci-0.2", "arm,psci"; + method = "smc"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + interrupt-parent = <&gic>; + }; + + uart2: serial@fe660000 { + compatible = "rockchip,rk3568-uart", "ns16550"; + reg = <0xfe660000 0x10000>; + interrupts = ; + clock-frequency = <12000000>; + reg-shift = <2>; + status = "disabled"; + }; + +}; diff --git a/dts/bindings/adc/adi,ad5592-adc.yaml b/dts/bindings/adc/adi,ad5592-adc.yaml new file mode 100644 index 00000000000..2432b55d25a --- /dev/null +++ b/dts/bindings/adc/adi,ad5592-adc.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2023 Grinn +# SPDX-License-Identifier: Apache-2.0 + +description: AD5592 ADC Controller + +compatible: "adi,ad5592-adc" + +include: adc-controller.yaml + +properties: + "#io-channel-cells": + const: 1 + +io-channel-cells: + - input diff --git a/dts/bindings/adc/lltc,ltc2451.yaml b/dts/bindings/adc/lltc,ltc2451.yaml new file mode 100644 index 00000000000..b68f127337f --- /dev/null +++ b/dts/bindings/adc/lltc,ltc2451.yaml @@ -0,0 +1,16 @@ +# Copyright (c) 2023 Brill Power Ltd. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +description: Linear Technology LTC2451 ADC + +compatible: "lltc,ltc2451" + +include: i2c-device.yaml + +properties: + conversion-speed: + type: int + enum: + - 30 + - 60 + description: Set conversion speed in Hz diff --git a/dts/bindings/adc/maxim,max11102-17-base.yaml b/dts/bindings/adc/maxim,max11102-17-base.yaml new file mode 100644 index 00000000000..1a129d7f8cc --- /dev/null +++ b/dts/bindings/adc/maxim,max11102-17-base.yaml @@ -0,0 +1,11 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +include: [adc-controller.yaml, spi-device.yaml] + +properties: + "#io-channel-cells": + const: 1 + +io-channel-cells: + - input diff --git a/dts/bindings/adc/maxim,max11102.yaml b/dts/bindings/adc/maxim,max11102.yaml new file mode 100644 index 00000000000..78016a6e9fb --- /dev/null +++ b/dts/bindings/adc/maxim,max11102.yaml @@ -0,0 +1,13 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: Maxim Integrated 2 channels 12 bit 2 Msps SPI ADC + +compatible: "maxim,max11102" + +include: maxim,max11102-17-base.yaml + +properties: + chsel-gpios: + type: phandle-array + description: "GPIO for channel selection" diff --git a/dts/bindings/adc/maxim,max11103.yaml b/dts/bindings/adc/maxim,max11103.yaml new file mode 100644 index 00000000000..3438cede85e --- /dev/null +++ b/dts/bindings/adc/maxim,max11103.yaml @@ -0,0 +1,13 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: Maxim Integrated 2 channels 12 bit 3 Msps SPI ADC + +compatible: "maxim,max11103" + +include: maxim,max11102-17-base.yaml + +properties: + chsel-gpios: + type: phandle-array + description: "GPIO for channel selection" diff --git a/dts/bindings/adc/maxim,max11105.yaml b/dts/bindings/adc/maxim,max11105.yaml new file mode 100644 index 00000000000..467886b5071 --- /dev/null +++ b/dts/bindings/adc/maxim,max11105.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: Maxim Integrated 1 channel 12 bit 2 Msps SPI ADC + +compatible: "maxim,max11105" + +include: maxim,max11102-17-base.yaml diff --git a/dts/bindings/adc/maxim,max11106.yaml b/dts/bindings/adc/maxim,max11106.yaml new file mode 100644 index 00000000000..75ca22f661e --- /dev/null +++ b/dts/bindings/adc/maxim,max11106.yaml @@ -0,0 +1,13 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: Maxim Integrated 2 channels 10 bit 3 Msps SPI ADC + +compatible: "maxim,max11106" + +include: maxim,max11102-17-base.yaml + +properties: + chsel-gpios: + type: phandle-array + description: "GPIO for channel selection" diff --git a/dts/bindings/adc/maxim,max11110.yaml b/dts/bindings/adc/maxim,max11110.yaml new file mode 100644 index 00000000000..ec07b358b53 --- /dev/null +++ b/dts/bindings/adc/maxim,max11110.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: Maxim Integrated 1 channel 10 bit 2 Msps SPI ADC + +compatible: "maxim,max11110" + +include: maxim,max11102-17-base.yaml diff --git a/dts/bindings/adc/maxim,max11111.yaml b/dts/bindings/adc/maxim,max11111.yaml new file mode 100644 index 00000000000..e00a075ba51 --- /dev/null +++ b/dts/bindings/adc/maxim,max11111.yaml @@ -0,0 +1,13 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: Maxim Integrated 2 channels 8 bit 3 Msps SPI ADC + +compatible: "maxim,max11111" + +include: maxim,max11102-17-base.yaml + +properties: + chsel-gpios: + type: phandle-array + description: "GPIO for channel selection" diff --git a/dts/bindings/adc/maxim,max11115.yaml b/dts/bindings/adc/maxim,max11115.yaml new file mode 100644 index 00000000000..a968931b748 --- /dev/null +++ b/dts/bindings/adc/maxim,max11115.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: Maxim Integrated 1 channel 8 bit 2 Msps SPI ADC + +compatible: "maxim,max11115" + +include: maxim,max11102-17-base.yaml diff --git a/dts/bindings/adc/maxim,max11116.yaml b/dts/bindings/adc/maxim,max11116.yaml new file mode 100644 index 00000000000..c601f25d99e --- /dev/null +++ b/dts/bindings/adc/maxim,max11116.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: Maxim Integrated 1 channel 8 bit 3 Msps SPI ADC + +compatible: "maxim,max11116" + +include: maxim,max11102-17-base.yaml diff --git a/dts/bindings/adc/maxim,max11117.yaml b/dts/bindings/adc/maxim,max11117.yaml new file mode 100644 index 00000000000..078ec527aa1 --- /dev/null +++ b/dts/bindings/adc/maxim,max11117.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: Maxim Integrated 1 channel 10 bit 3 Msps SPI ADC + +compatible: "maxim,max11117" + +include: maxim,max11102-17-base.yaml diff --git a/dts/bindings/adc/nuvoton,npcx-adc.yaml b/dts/bindings/adc/nuvoton,npcx-adc.yaml index 78701bdc81a..50d37d19d80 100644 --- a/dts/bindings/adc/nuvoton,npcx-adc.yaml +++ b/dts/bindings/adc/nuvoton,npcx-adc.yaml @@ -16,14 +16,14 @@ properties: required: true pinctrl-names: required: true - channel-count: + vref-mv: type: int required: true - description: the number of ADC channels - threshold-reg-offset: + description: ADC reference voltage (Unit:mV) + channel-count: type: int required: true - description: the offset of threshold detector register address + description: the number of ADC channels threshold-count: type: int required: true diff --git a/dts/bindings/adc/nxp,lpc-lpadc.yaml b/dts/bindings/adc/nxp,lpc-lpadc.yaml index 0a8c2c74783..75b9c7fa357 100644 --- a/dts/bindings/adc/nxp,lpc-lpadc.yaml +++ b/dts/bindings/adc/nxp,lpc-lpadc.yaml @@ -71,6 +71,10 @@ properties: required: true description: Offset value B to use if CONFIG_LPADC_DO_OFFSET_CALIBRATION is false + nxp,reference-supply: + type: phandles + description: References to required regulators which must be enabled for LPADC to function + "#io-channel-cells": const: 1 diff --git a/dts/bindings/adc/st,stm32-adc.yaml b/dts/bindings/adc/st,stm32-adc.yaml index d9c2dac9dc4..df3eff62dbb 100644 --- a/dts/bindings/adc/st,stm32-adc.yaml +++ b/dts/bindings/adc/st,stm32-adc.yaml @@ -70,18 +70,6 @@ properties: default: 3300 description: Indicates the reference voltage of the ADC in mV (on the target board). - temp-channel: - type: int - description: Indicates the ADC channel of the internal temperature sensor. - - vref-channel: - type: int - description: Indicates the ADC channel of the internal voltage reference. - - vbat-channel: - type: int - description: Indicates the ADC channel of the internal vbat monitoring. - resolutions: type: array required: true @@ -109,5 +97,16 @@ properties: description: | Number of sampling time common channels for this ADC instance, if any. + st,adc-sequencer: + type: int + required: true + enum: + - 0 # NOT_FULLY_CONFIGURABLE + - 1 # FULLY_CONFIGURABLE + description: | + Type of ADC sequencer: + - : Not fully configurable sequencer + - : Fully configurable sequencer + io-channel-cells: - input diff --git a/dts/bindings/arm/nxp,imx-mu-rev2.yaml b/dts/bindings/arm/nxp,imx-mu-rev2.yaml deleted file mode 100644 index 7759e52293c..00000000000 --- a/dts/bindings/arm/nxp,imx-mu-rev2.yaml +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2018, NXP -# SPDX-License-Identifier: Apache-2.0 - -description: i.MX Messaging Unit - -compatible: "nxp,imx-mu-rev2" - -include: base.yaml - -properties: - reg: - required: true - - interrupts: - required: true - - rdc: - type: int - required: true - description: Set the RDC permission for this peripheral diff --git a/dts/bindings/audio/ti,tas6422dac.yaml b/dts/bindings/audio/ti,tas6422dac.yaml new file mode 100644 index 00000000000..5889d76f827 --- /dev/null +++ b/dts/bindings/audio/ti,tas6422dac.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2023 Centralp +# SPDX-License-Identifier: Apache-2.0 + +description: Texas Instruments TAS6422 Audio Amplifier + +compatible: "ti,tas6422dac" + +include: i2c-device.yaml + +properties: + mute-gpios: + type: phandle-array diff --git a/dts/bindings/auxdisplay/sparkfun,serlcd.yaml b/dts/bindings/auxdisplay/sparkfun,serlcd.yaml new file mode 100644 index 00000000000..1a4d5734f36 --- /dev/null +++ b/dts/bindings/auxdisplay/sparkfun,serlcd.yaml @@ -0,0 +1,34 @@ +# Copyright (c) 2023 Jan Henke +# SPDX-License-Identifier: Apache-2.0 + +description: | + SparkFun SerLCD Dot Character VFD Controller/Driver IC + + Example: + &i2c1 { + serlcd@72 { + compatible = "sparkfun,serlcd"; + reg = <0x72>; + columns = <16>; + rows = <2>; + }; + }; + +compatible: "sparkfun,serlcd" + +include: [auxdisplay-device.yaml, i2c-device.yaml] + +properties: + columns: + type: int + default: 16 + enum: + - 16 + - 20 + + rows: + type: int + default: 2 + enum: + - 2 + - 4 diff --git a/dts/bindings/base/zephyr,memory-attr.yaml b/dts/bindings/base/zephyr,memory-attr.yaml index e3c19b9b288..1a5611b5258 100644 --- a/dts/bindings/base/zephyr,memory-attr.yaml +++ b/dts/bindings/base/zephyr,memory-attr.yaml @@ -4,17 +4,19 @@ include: [base.yaml] properties: - zephyr,memory-attr: + zephyr,memory-region-mpu: type: string - enum: - - "RAM" - - "RAM_NOCACHE" - - "FLASH" - - "PPB" - - "IO" - - "EXTMEM" + deprecated: true + description: | + Signify that this node should result in a dedicated MPU region. + Deprecated in favor of 'zephyr,memory-attr'. + + zephyr,memory-attr: + type: int description: | - Attribute for the memory region. + Attribute or set of attributes (bitmask) for the memory region. See + 'include/zephyr/dt-bindings/memory-attr/memory-attr.h' for a + comprehensive list with description of possible values. reg: required: true diff --git a/dts/bindings/battery/battery.yaml b/dts/bindings/battery/battery.yaml new file mode 100644 index 00000000000..90bb20532d4 --- /dev/null +++ b/dts/bindings/battery/battery.yaml @@ -0,0 +1,25 @@ +# Copyright 2023 Cirrus Logic, Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: | + Static Battery Characteristics + + Properties are inherited from Linux. See + linux/Documentation/devicetree/bindings/power/supply/battery.yaml + +properties: + precharge-current-microamp: + type: int + description: current for pre-charge phase + + charge-term-current-microamp: + type: int + description: current for charge termination phase + + constant-charge-current-max-microamp: + type: int + description: maximum constant input current + + constant-charge-voltage-max-microvolt: + type: int + description: maximum constant input voltage diff --git a/dts/bindings/bluetooth/zephyr,bt-hci-spi.yaml b/dts/bindings/bluetooth/zephyr,bt-hci-spi.yaml index 1a5afdc6473..50d0e311461 100644 --- a/dts/bindings/bluetooth/zephyr,bt-hci-spi.yaml +++ b/dts/bindings/bluetooth/zephyr,bt-hci-spi.yaml @@ -28,10 +28,10 @@ properties: type: int default: 20 description: - Duration to delay between reading a valid header and reading the data associated - with that header. This delay gives the controller time to configure the SPI data - transaction after finishing the header transaction. Without this delay the host - can attempt to read before the controller is ready, resulting in empty data that - then needs to be read a second time. The default of 20uS was chosen as the lowest - delay that reliably eliminated double transmits between a nRF9160 host and a - nRF52832 controller. + Duration to delay between reading a valid header and transceiving the data + associated with that header. This delay gives the controller time to configure + the SPI data transaction after finishing the header transaction. Without this + delay the host can attempt to read/write before the controller is ready, + resulting in an ignored transaction that then needs to be performed a second time. + The default of 20uS was chosen as the lowest delay that reliably eliminated double + transactions between a nRF9160 host and a nRF52832 controller. diff --git a/dts/bindings/can/atmel,sam-can.yaml b/dts/bindings/can/atmel,sam-can.yaml index 0d0dc268f4c..e6930009194 100644 --- a/dts/bindings/can/atmel,sam-can.yaml +++ b/dts/bindings/can/atmel,sam-can.yaml @@ -1,4 +1,4 @@ -description: Specialization of Bosch m_can CAN-FD controller for Atmel SAM +description: Specialization of Bosch m_can CAN FD controller for Atmel SAM compatible: "atmel,sam-can" diff --git a/dts/bindings/can/atmel,sam0-can.yaml b/dts/bindings/can/atmel,sam0-can.yaml index 0a70dfd9d5e..486620a21b7 100644 --- a/dts/bindings/can/atmel,sam0-can.yaml +++ b/dts/bindings/can/atmel,sam0-can.yaml @@ -1,4 +1,4 @@ -description: Specialization of Bosch m_can CAN-FD controller for Atmel SAM0 +description: Specialization of Bosch m_can CAN FD controller for Atmel SAM0 compatible: "atmel,sam0-can" diff --git a/dts/bindings/can/bosch,m_can-base.yaml b/dts/bindings/can/bosch,m_can-base.yaml index 1663cf82082..0c59c671949 100644 --- a/dts/bindings/can/bosch,m_can-base.yaml +++ b/dts/bindings/can/bosch,m_can-base.yaml @@ -1,4 +1,4 @@ -description: Bosch M_CAN CAN-FD controller base +description: Bosch M_CAN CAN FD controller base include: [can-fd-controller.yaml] diff --git a/dts/bindings/can/can-controller.yaml b/dts/bindings/can/can-controller.yaml index d558a7ffc09..b2502dce1c3 100644 --- a/dts/bindings/can/can-controller.yaml +++ b/dts/bindings/can/can-controller.yaml @@ -6,26 +6,47 @@ properties: bus-speed: type: int required: true - description: bus speed in Baud/s + description: | + Initial bitrate in bit/s. + sample-point: + type: int + description: | + Initial sample point in per mille (e.g. 875 equals 87.5%). + + This property is required unless the timing is specified using time quanta based properties + (`sjw`, `prop-seg`, `phase-seg1`, and `phase-seg2`). + + If this property is present, the time quanta based timing properties are ignored. sjw: type: int - required: true - description: Resynchronization jump width (ISO 11898-1) + deprecated: true + default: 1 + description: | + Initial time quanta of resynchronization jump width (ISO 11898-1). + + Deprecated in favor of automatic calculation of a suitable default SJW based on existing + timing parameters. Default of 1 matches the default value previously used for all in-tree CAN + controller devicetree instances. + + Applications can still manually set the SJW using the CAN timing APIs. prop-seg: type: int - description: Time quantums of propagation segment (ISO 11898-1) + deprecated: true + description: | + Initial time quanta of propagation segment (ISO 11898-1). Deprecated in favor of setting + advanced timing parameters from the application. phase-seg1: type: int - description: Time quantums of phase buffer 1 segment (ISO 11898-1) + deprecated: true + description: | + Initial time quanta of phase buffer 1 segment (ISO 11898-1). Deprecated in favor of setting + advanced timing parameters from the application. phase-seg2: type: int - description: Time quantums of phase buffer 2 segment (ISO 11898-1) - sample-point: - type: int - description: > - Sample point in permille. - This param is required if segments are not given. - If the sample point is given, the segments are ignored. + deprecated: true + description: | + Initial time quanta of phase buffer 2 segment (ISO 11898-1). Deprecated in favor of setting + advanced timing parameters from the application. phys: type: phandle description: | diff --git a/dts/bindings/can/can-fd-controller.yaml b/dts/bindings/can/can-fd-controller.yaml index 4fdfff2b25b..3882518d626 100644 --- a/dts/bindings/can/can-fd-controller.yaml +++ b/dts/bindings/can/can-fd-controller.yaml @@ -1,4 +1,4 @@ -# Common fields for CAN-FD controllers +# Common fields for CAN FD controllers include: can-controller.yaml @@ -6,26 +6,47 @@ properties: bus-speed-data: type: int required: true - description: data phase bus speed in Baud/s + description: | + Initial data phase bitrate in bit/s. + sample-point-data: + type: int + description: | + Initial data phase sample point in per mille (e.g. 875 equals 87.5%). + + This property is required unless the timing is specified using time quanta based properties + (`sjw-data`, `prop-seg-data`, `phase-seg1-data`, and `phase-seg2-data`). + + If this property is present, the time quanta based timing properties are ignored. sjw-data: type: int - required: true - description: Resynchronization jump width for the data phase. (ISO11898-1:2015) + deprecated: true + default: 1 + description: | + Initial time quanta of resynchronization jump width for the data phase (ISO11898-1:2015). + + Deprecated in favor of automatic calculation of a suitable default SJW based on existing + timing parameters. Default of 1 matches the default value previously used for all in-tree CAN + controller devicetree instances. + + Applications can still manually set the SJW using the CAN timing APIs. prop-seg-data: type: int - description: Time quantums of propagation segment for the data phase. (ISO11898-1:2015) + deprecated: true + description: | + Initial time quanta of propagation segment for the data phase (ISO11898-1:2015). Deprecated in + favor of setting advanced timing parameters from the application. phase-seg1-data: type: int - description: Time quantums of phase buffer 1 segment for the data phase. (ISO11898-1:2015) + deprecated: true + description: | + Initial time quanta of phase buffer 1 segment for the data phase (ISO11898-1:2015). Deprecated + in favor of setting advanced timing parameters from the application. phase-seg2-data: type: int - description: Time quantums of phase buffer 2 segment for the data phase. (ISO11898-1:2015) - sample-point-data: - type: int - description: > - Sample point in permille for the data phase. - This param is required if segments are not given. - If the sample point is given, the segments are ignored. + deprecated: true + description: | + Initial time quanta of phase buffer 2 segment for the data phase (ISO11898-1:2015). Deprecated + in favor of setting advanced timing parameters from the application. tx-delay-comp-offset: type: int default: 0 diff --git a/dts/bindings/can/microchip,mcp251xfd.yaml b/dts/bindings/can/microchip,mcp251xfd.yaml new file mode 100644 index 00000000000..de86c320d30 --- /dev/null +++ b/dts/bindings/can/microchip,mcp251xfd.yaml @@ -0,0 +1,80 @@ +# Copyright (c) 2020 Abram Early +# SPDX-License-Identifier: Apache-2.0 + +description: | + Microchip MCP251XFD SPI CAN FD controller + + The MCP251XFD node is defined on an SPI bus. An example + configuration is: + + &mikrobus_spi { + cs-gpios = <&mikrobus_header 2 GPIO_ACTIVE_LOW>; + + mcp2518fd_mikroe_mcp2518fd_click: mcp2518fd@0 { + compatible = "microchip,mcp251xfd"; + status = "okay"; + + spi-max-frequency = <18000000>; + int-gpios = <&mikrobus_header 7 GPIO_ACTIVE_LOW>; + reg = <0x0>; + osc-freq = <40000000>; + + bus-speed = <125000>; + sample-point = <875>; + bus-speed-data = <1000000>; + sample-point-data = <875>; + }; + }; + +compatible: "microchip,mcp251xfd" + +include: [spi-device.yaml, can-fd-controller.yaml] + +properties: + osc-freq: + type: int + required: true + description: Frequency of the external oscillator in Hz. + + int-gpios: + type: phandle-array + required: true + description: | + The interrupt signal from the controller is active low in push-pull mode. + The property value should ensure the flags properly describe the signal + that is presented to the driver. + + pll-enable: + type: boolean + description: | + Enables controller PLL, which multiples input clock frequency x10. + This parameter also implicity sets whether the clock is from the PLL + output or directly from the oscillator. + If this option is enabled the clock source is the PLL, otherwise its + the oscillator. + + timestamp-prescaler: + type: int + default: 1 + description: | + Prescaler value for computing the timestamps of received messages. + The timestamp counter is derived from the internal clock divided by this value. + Valid range is [1, 1024]. + + sof-on-clko: + type: boolean + description: | + Output start-of-frame (SOF) signal on the CLKO pin every time + a Start bit of a CAN message is transmitted or received. If this option + is not set, then an internal clock (typically 40MHz or 20MHz) will be + output on CLKO pin instead. + + clko-div: + type: int + description: The factor to divide the system clock for CLKO pin. + default: 10 + enum: + - 1 + - 2 + - 4 + - 10 diff --git a/dts/bindings/can/nuvoton,numaker-canfd.yaml b/dts/bindings/can/nuvoton,numaker-canfd.yaml new file mode 100644 index 00000000000..e3d28f5ce28 --- /dev/null +++ b/dts/bindings/can/nuvoton,numaker-canfd.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2023 Nuvoton Technology Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Nuvoton NuMaker CAN FD controller, using Bosch M_CAN IP + +compatible: "nuvoton,numaker-canfd" + +include: ["bosch,m_can-base.yaml", reset-device.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + resets: + required: true + + clocks: + required: true diff --git a/dts/bindings/can/nxp,flexcan-fd.yaml b/dts/bindings/can/nxp,flexcan-fd.yaml index 5661c919c51..72c36292cc0 100644 --- a/dts/bindings/can/nxp,flexcan-fd.yaml +++ b/dts/bindings/can/nxp,flexcan-fd.yaml @@ -4,7 +4,7 @@ description: | NXP FlexCAN CANFD controller. - This is a specialization of the NXP FlexCAN CAN controller with support for CAN-FD. + This is a specialization of the NXP FlexCAN CAN controller with support for CAN FD. Example: flexcan3: can@401d8000 { @@ -15,8 +15,6 @@ description: | interrupt-names = "common"; clocks = <&ccm IMX_CCM_CAN_CLK 0x84 6>; clk-source = <2>; - sjw = <1>; - sjw-data = <1>; sample-point = <875>; sample-point-data = <875>; bus-speed = <125000>; diff --git a/dts/bindings/can/nxp,flexcan.yaml b/dts/bindings/can/nxp,flexcan.yaml index dca50aa8a65..f23d0f45d81 100644 --- a/dts/bindings/can/nxp,flexcan.yaml +++ b/dts/bindings/can/nxp,flexcan.yaml @@ -13,7 +13,6 @@ description: | interrupt-names = "warning", "error", "wake-up", "mb-0-15"; clocks = <&scg KINETIS_SCG_BUS_CLK>; clk-source = <1>; - sjw = <1>; sample-point = <875>; bus-speed = <125000>; pinctrl-0 = <&pinmux_flexcan0>; diff --git a/dts/bindings/can/nxp,lpc-mcan.yaml b/dts/bindings/can/nxp,lpc-mcan.yaml index 65a06baea87..a17b0132e62 100644 --- a/dts/bindings/can/nxp,lpc-mcan.yaml +++ b/dts/bindings/can/nxp,lpc-mcan.yaml @@ -1,4 +1,4 @@ -description: NXP LPC SoC series MCAN CAN-FD controller +description: NXP LPC SoC series MCAN CAN FD controller compatible: "nxp,lpc-mcan" diff --git a/dts/bindings/can/nxp,s32-canxl.yaml b/dts/bindings/can/nxp,s32-canxl.yaml index 8d498e47007..2a0f9408b65 100644 --- a/dts/bindings/can/nxp,s32-canxl.yaml +++ b/dts/bindings/can/nxp,s32-canxl.yaml @@ -1,4 +1,4 @@ -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # # SPDX-License-Identifier: Apache-2.0 @@ -15,10 +15,8 @@ properties: interrupts: required: true - clock-frequency: - type: int + clocks: required: true - description: Module clock frequency in Hz. pinctrl-0: required: true diff --git a/dts/bindings/can/st,stm32-fdcan.yaml b/dts/bindings/can/st,stm32-fdcan.yaml index 36a38d97ca3..d950bb4e924 100644 --- a/dts/bindings/can/st,stm32-fdcan.yaml +++ b/dts/bindings/can/st,stm32-fdcan.yaml @@ -1,4 +1,4 @@ -description: ST STM32 FDCAN CAN-FD controller +description: ST STM32 FDCAN CAN FD controller compatible: "st,stm32-fdcan" diff --git a/dts/bindings/can/st,stm32h7-fdcan.yaml b/dts/bindings/can/st,stm32h7-fdcan.yaml index 5679141fe8e..3cee6e29219 100644 --- a/dts/bindings/can/st,stm32h7-fdcan.yaml +++ b/dts/bindings/can/st,stm32h7-fdcan.yaml @@ -1,4 +1,4 @@ -description: ST STM32H7 series FDCAN CAN-FD controller +description: ST STM32H7 series FDCAN CAN FD controller compatible: "st,stm32h7-fdcan" diff --git a/dts/bindings/can/ti,tcan4x5x.yaml b/dts/bindings/can/ti,tcan4x5x.yaml new file mode 100644 index 00000000000..8f57f66ae85 --- /dev/null +++ b/dts/bindings/can/ti,tcan4x5x.yaml @@ -0,0 +1,64 @@ +# Copyright (c) 2023 Vestas Wind Systems A/S +# SPDX-License-Identifier: Apache-2.0 + +description: | + Texas Instruments TCAN4x5x SPI CAN FD controller. + + Example: + &spi0 { + tcan4x5x: can@0 { + compatible = ti,tcan4x5x"; + reg = <0>; + spi-max-frequency = <18000000>; + clock-frequency = <40000000>; + device-state-gpios = <&gpio0 0 GPIO_ACTIVE_LOW>; + device-wake-gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>; + int-gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; + bosch,mram-cfg = <0x0 15 15 5 5 0 10 10>; + sample-point = <875>; + sample-point-data = <875>; + bus-speed = <125000>; + bus-speed-data = <1000000>; + status = "okay"; + + can-transceiver { + max-bitrate = <8000000>; + }; + }; + }; + +compatible: "ti,tcan4x5x" + +include: ["bosch,m_can-base.yaml", "spi-device.yaml"] + +properties: + clock-frequency: + type: int + enum: + - 20000000 + - 40000000 + required: true + description: | + TCAN4x5x oscillator clock frequency in Hz (20MHz or 40MHz). + + device-state-gpios: + type: phandle-array + description: | + GPIO connected to the TCAN4x5x nWKRQ output. This signal is active low. + + device-wake-gpios: + type: phandle-array + description: | + GPIO connected to the TCAN4x5x WAKE input. This signal is high-voltage, active high. + + reset-gpios: + type: phandle-array + description: | + GPIO connected to the TCAN4x5x RST input. This signal is active high. + + int-gpios: + type: phandle-array + required: true + description: | + GPIO connected to the TCAN4x5x nINT interrupt output. This signal is open-drain, active low. diff --git a/dts/bindings/charger/maxim,max20335-charger.yaml b/dts/bindings/charger/maxim,max20335-charger.yaml new file mode 100644 index 00000000000..f830e03cec5 --- /dev/null +++ b/dts/bindings/charger/maxim,max20335-charger.yaml @@ -0,0 +1,15 @@ +# Copyright (c), 2023 Grinn +# SPDX -License-Identifier: Apache-2.0 + +description: Maxim MAX20335 battery charger + +include: battery.yaml + +compatible: "maxim,max20335-charger" + +properties: + constant-charge-current-max-microamp: + required: true + + constant-charge-voltage-max-microvolt: + required: true diff --git a/dts/bindings/charger/sbs,sbs-charger.yaml b/dts/bindings/charger/sbs,sbs-charger.yaml new file mode 100644 index 00000000000..526d796f2cc --- /dev/null +++ b/dts/bindings/charger/sbs,sbs-charger.yaml @@ -0,0 +1,11 @@ +# +# Copyright 2023 Cirrus Logic, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +description: SBS 1.1 compliant charger (http://www.sbs-forum.org/specs) + +compatible: "sbs,sbs-charger" + +include: [i2c-device.yaml] diff --git a/dts/bindings/charger/ti,bq24190.yaml b/dts/bindings/charger/ti,bq24190.yaml new file mode 100644 index 00000000000..6ff662c9c58 --- /dev/null +++ b/dts/bindings/charger/ti,bq24190.yaml @@ -0,0 +1,15 @@ +# Copyright 2023 Cirrus Logic, Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: Texas Instruments family of BQ24190 of charging ICs + +include: [battery.yaml, i2c-device.yaml] + +compatible: "ti,bq24190" + +properties: + constant-charge-current-max-microamp: + required: true + + constant-charge-voltage-max-microvolt: + required: true diff --git a/dts/bindings/clock/ambiq,clkctrl.yaml b/dts/bindings/clock/ambiq,clkctrl.yaml new file mode 100644 index 00000000000..e1b3f9534b3 --- /dev/null +++ b/dts/bindings/clock/ambiq,clkctrl.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2023 Ambiq Micro Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: Ambiq Apollo Series SoC Clock Controller + +compatible: "ambiq,clkctrl" + +include: [clock-controller.yaml, pinctrl-device.yaml, base.yaml] + +properties: + clock-frequency: + type: int + description: output clock frequency (Hz) + required: true + + pinctrl-0: + required: true + + pinctrl-names: + required: true + + "#clock-cells": + const: 1 diff --git a/dts/bindings/clock/intel,adsp-shim-clkctl.yaml b/dts/bindings/clock/intel,adsp-shim-clkctl.yaml index c0c73856ed2..99e8ec83c84 100644 --- a/dts/bindings/clock/intel,adsp-shim-clkctl.yaml +++ b/dts/bindings/clock/intel,adsp-shim-clkctl.yaml @@ -19,6 +19,10 @@ properties: type: int description: Index of HPRO clock encoding in the encoding array. + adsp-clkctl-clk-ipll: + type: int + description: Index of ACE integrated PLL clock encoding in the encoding array. + adsp-clkctl-freq-enc: type: array required: true diff --git a/dts/bindings/clock/nxp,imx-ccm.yaml b/dts/bindings/clock/nxp,imx-ccm.yaml index 9ddda734e81..f328b6f034a 100644 --- a/dts/bindings/clock/nxp,imx-ccm.yaml +++ b/dts/bindings/clock/nxp,imx-ccm.yaml @@ -8,9 +8,6 @@ compatible: "nxp,imx-ccm" include: [clock-controller.yaml, base.yaml] properties: - reg: - required: true - "#clock-cells": const: 3 diff --git a/dts/bindings/clock/pwm-clock.yaml b/dts/bindings/clock/pwm-clock.yaml new file mode 100644 index 00000000000..5e19a245809 --- /dev/null +++ b/dts/bindings/clock/pwm-clock.yaml @@ -0,0 +1,54 @@ +# Copyright (c) 2023 Andriy Gelman +# SPDX-License-Identifier: Apache-2.0 + +description: | + An external clock signal driven by a PWM pin. + + The devicetree must define a clock node: + + pwmclock: pwmclock { + status = "okay"; + compatible = "pwm-clock"; + #clock-cells = <1>; + pwms = <&pwm_ccu40 2 PWM_HZ(1000000) PWM_POLARITY_NORMAL>; + }; + + This will create a device node with a clock-controller + API. Internally the device node will use PWM API to start the + clock signals at 1MHz. Note that the PWM_HZ() macro converts the + frequency to time (nanoseconds units). This may result in rounding + errors if the clock frequency is not an integer number of nanoseconds. + The clock frequency can be explicitly set using the clock-frequency + property. + + The PWM node may need to be properly configured to generate + the target period (i.e. using prescaler options). See the documention + for the target PWM driver. + +compatible: "pwm-clock" + +include: [clock-controller.yaml, base.yaml] + +properties: + pwms: + type: phandle-array + required: true + + clock-frequency: + type: int + description: | + Exact output frequency, in case the PWM period is not exact + but was rounded to nanoseconds. This property is optional. + + pwm-on-delay: + type: int + default: 0 + description: + Optional blocking delay in micro seconds to make sure that the PWM + clock has started after returning from clock_control_on(). + + "#clock-cells": + const: 1 + +clock-cells: + - id diff --git a/dts/bindings/clock/renesas,ra-clock-generation-circuit.yaml b/dts/bindings/clock/renesas,ra-clock-generation-circuit.yaml new file mode 100644 index 00000000000..07b244ea79d --- /dev/null +++ b/dts/bindings/clock/renesas,ra-clock-generation-circuit.yaml @@ -0,0 +1,46 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas RA series Clock Generation Circuit + +compatible: "renesas,ra-clock-generation-circuit" + +include: [clock-controller.yaml, base.yaml] + +properties: + reg: + required: true + + iclk-div: + type: int + description: Division factor for ICLK + + fclk-div: + type: int + description: Division factor for FCLK + + pclka-div: + type: int + description: Division factor for PCLKA + + pclkb-div: + type: int + description: Division factor for PCLKB + + pclkc-div: + type: int + description: Division factor for PCLKC + + pclkd-div: + type: int + description: Division factor for PCLKD + + clock-source: + type: phandle + description: System clock sorce + + "#clock-cells": + const: 1 + +clock-cells: + - id diff --git a/dts/bindings/clock/silabs,hfxo.yaml b/dts/bindings/clock/silabs,hfxo.yaml new file mode 100644 index 00000000000..cd0d3ad1742 --- /dev/null +++ b/dts/bindings/clock/silabs,hfxo.yaml @@ -0,0 +1,9 @@ +compatible: "silabs,hfxo" + +include: fixed-clock.yaml + +properties: + ctune: + type: int + required: true + description: Load capacitance configuration diff --git a/dts/bindings/clock/st,stm32-hsi48-clock.yaml b/dts/bindings/clock/st,stm32-hsi48-clock.yaml new file mode 100644 index 00000000000..f8bcc88691b --- /dev/null +++ b/dts/bindings/clock/st,stm32-hsi48-clock.yaml @@ -0,0 +1,16 @@ +# Copyright (c) 2023, Aurelien Jarno +# SPDX-License-Identifier: Apache-2.0 + +description: STM32 HSI48 Clock + +compatible: "st,stm32-hsi48-clock" + +include: [fixed-clock.yaml] + +properties: + crs-usb-sof: + type: boolean + description: | + Clock Recovery System using USB SOF packet reception + Set the property to enable clock recovery of the HSI48 oscillator using + the USB SOF packet reception as a reference. diff --git a/dts/bindings/clock/st,stm32u5-pll-clock.yaml b/dts/bindings/clock/st,stm32u5-pll-clock.yaml index 6185050eac6..241c8acb841 100644 --- a/dts/bindings/clock/st,stm32u5-pll-clock.yaml +++ b/dts/bindings/clock/st,stm32u5-pll-clock.yaml @@ -71,3 +71,9 @@ properties: On PLL1, only division by 1 and even division values are allowed. No restrictions for PLL2 and PLL3 Valid range: 1 - 128 + + fracn: + type: int + description: | + PLLx FRACN value + Valid range: 0 - 8191 diff --git a/dts/bindings/counter/nxp,mrt-channel.yaml b/dts/bindings/counter/nxp,mrt-channel.yaml new file mode 100644 index 00000000000..c3ab744fc5a --- /dev/null +++ b/dts/bindings/counter/nxp,mrt-channel.yaml @@ -0,0 +1,15 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + NXP Multirate Timer Channel + + Must be a child node of an nxp,mrt compatible node. + +compatible: "nxp,mrt-channel" + +include: base.yaml + +properties: + reg: + required: true diff --git a/dts/bindings/counter/nxp,mrt.yaml b/dts/bindings/counter/nxp,mrt.yaml new file mode 100644 index 00000000000..e9e05b6c5b5 --- /dev/null +++ b/dts/bindings/counter/nxp,mrt.yaml @@ -0,0 +1,28 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP Multirate Timer + +compatible: "nxp,mrt" + +include: base.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + num-channels: + type: int + required: true + description: Number of channels on the IP version + + num-bits: + type: int + required: true + description: Timer width in bits of IP version + + clocks: + required: true diff --git a/dts/bindings/cpu/espressif,riscv.yaml b/dts/bindings/cpu/espressif,riscv.yaml index 5894435c061..a93894cd946 100644 --- a/dts/bindings/cpu/espressif,riscv.yaml +++ b/dts/bindings/cpu/espressif,riscv.yaml @@ -5,7 +5,7 @@ description: Espressif RISC-V CPU compatible: "espressif,riscv" -include: cpu.yaml +include: riscv,cpus.yaml properties: clock-source: diff --git a/dts/bindings/cpu/intel,alder_lake.yaml b/dts/bindings/cpu/intel,alder-lake.yaml similarity index 100% rename from dts/bindings/cpu/intel,alder_lake.yaml rename to dts/bindings/cpu/intel,alder-lake.yaml diff --git a/dts/bindings/cpu/intel,apollo-lake.yaml b/dts/bindings/cpu/intel,apollo-lake.yaml new file mode 100644 index 00000000000..1bef2bce04f --- /dev/null +++ b/dts/bindings/cpu/intel,apollo-lake.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2021 Intel Corp. +# SPDX-License-Identifier: Apache-2.0 + +description: Intel Apollo lake CPU + +compatible: "intel,apollo-lake" + +include: cpu.yaml diff --git a/dts/bindings/cpu/intel,apollo_lake.yaml b/dts/bindings/cpu/intel,apollo_lake.yaml deleted file mode 100644 index 3ac47c0a05d..00000000000 --- a/dts/bindings/cpu/intel,apollo_lake.yaml +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2021 Intel Corp. -# SPDX-License-Identifier: Apache-2.0 - -description: Intel Apollo lake CPU - -compatible: "intel,apollo_lake" - -include: cpu.yaml diff --git a/dts/bindings/cpu/intel,atom.yaml b/dts/bindings/cpu/intel,atom.yaml deleted file mode 100644 index d6c4dd771cd..00000000000 --- a/dts/bindings/cpu/intel,atom.yaml +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2021 Intel Corp. -# SPDX-License-Identifier: Apache-2.0 - -description: Intel Atom CPU - -compatible: "intel,atom" - -include: cpu.yaml diff --git a/dts/bindings/cpu/intel,elkhart-lake.yaml b/dts/bindings/cpu/intel,elkhart-lake.yaml new file mode 100644 index 00000000000..14ff85838e8 --- /dev/null +++ b/dts/bindings/cpu/intel,elkhart-lake.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2021 Intel Corp. +# SPDX-License-Identifier: Apache-2.0 + +description: Intel Elkhart Lake CPU + +compatible: "intel,elkhart-lake" + +include: cpu.yaml diff --git a/dts/bindings/cpu/intel,elkhart_lake.yaml b/dts/bindings/cpu/intel,elkhart_lake.yaml deleted file mode 100644 index bafa1a317a2..00000000000 --- a/dts/bindings/cpu/intel,elkhart_lake.yaml +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2021 Intel Corp. -# SPDX-License-Identifier: Apache-2.0 - -description: Intel Elkhart Lake CPU - -compatible: "intel,elkhart_lake" - -include: cpu.yaml diff --git a/dts/bindings/cpu/intel,niosv.yaml b/dts/bindings/cpu/intel,niosv.yaml index ca032db1bb4..0eaac730d84 100644 --- a/dts/bindings/cpu/intel,niosv.yaml +++ b/dts/bindings/cpu/intel,niosv.yaml @@ -5,4 +5,4 @@ description: INTEL FPGA NIOSV Softcore Processor compatible: "intel,niosv" -include: cpu.yaml +include: riscv,cpus.yaml diff --git a/dts/bindings/cpu/intel,raptor_lake.yaml b/dts/bindings/cpu/intel,raptor-lake.yaml similarity index 100% rename from dts/bindings/cpu/intel,raptor_lake.yaml rename to dts/bindings/cpu/intel,raptor-lake.yaml diff --git a/dts/bindings/cpu/ite,riscv-ite.yaml b/dts/bindings/cpu/ite,riscv-ite.yaml index 0f0651d059d..f358b0867ac 100644 --- a/dts/bindings/cpu/ite,riscv-ite.yaml +++ b/dts/bindings/cpu/ite,riscv-ite.yaml @@ -5,4 +5,4 @@ description: ITE IT8XXX2 RISC-V CPU compatible: "ite,riscv-ite" -include: cpu.yaml +include: riscv,cpus.yaml diff --git a/dts/bindings/cpu/neorv32-cpu.yaml b/dts/bindings/cpu/neorv32-cpu.yaml index 417ce963cee..b0983771e92 100644 --- a/dts/bindings/cpu/neorv32-cpu.yaml +++ b/dts/bindings/cpu/neorv32-cpu.yaml @@ -5,4 +5,4 @@ description: NEORV32 RISC-V CPU compatible: "neorv32-cpu" -include: cpu.yaml +include: riscv,cpus.yaml diff --git a/dts/bindings/cpu/nuclei,bumblebee.yaml b/dts/bindings/cpu/nuclei,bumblebee.yaml index 3e6c171b90f..8c9dfc7d35d 100644 --- a/dts/bindings/cpu/nuclei,bumblebee.yaml +++ b/dts/bindings/cpu/nuclei,bumblebee.yaml @@ -5,7 +5,7 @@ description: Nuclei Bumblebee RISC-V Core compatible: "nuclei,bumblebee" -include: cpu.yaml +include: riscv,cpus.yaml properties: mcause-exception-mask: diff --git a/dts/bindings/cpu/telink,b91.yaml b/dts/bindings/cpu/telink,b91.yaml index f70640234df..0b39cc85435 100644 --- a/dts/bindings/cpu/telink,b91.yaml +++ b/dts/bindings/cpu/telink,b91.yaml @@ -5,4 +5,4 @@ description: Telink RISC-V CPU compatible: "telink,b91" -include: cpu.yaml +include: riscv,cpus.yaml diff --git a/dts/bindings/crypto/nordic,nrf-cc310.yaml b/dts/bindings/crypto/nordic,nrf-cc310.yaml deleted file mode 100644 index 8ab48636848..00000000000 --- a/dts/bindings/crypto/nordic,nrf-cc310.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2018, Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -description: Nordic Control Interface for ARM TrustZone CryptoCell 310 - -compatible: "nordic,nrf-cc310" - -include: base.yaml - -properties: - reg: - required: true diff --git a/dts/bindings/crypto/nordic,nrf-cc312.yaml b/dts/bindings/crypto/nordic,nrf-cc312.yaml deleted file mode 100644 index bc0b227e7e5..00000000000 --- a/dts/bindings/crypto/nordic,nrf-cc312.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2018, 2020 Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -description: Nordic Control Interface for ARM TrustZone CryptoCell 312 - -compatible: "nordic,nrf-cc312" - -include: base.yaml - -properties: - reg: - required: true diff --git a/dts/bindings/crypto/nuvoton,npcx-sha.yaml b/dts/bindings/crypto/nuvoton,npcx-sha.yaml index 2670855d45b..237490840ad 100644 --- a/dts/bindings/crypto/nuvoton,npcx-sha.yaml +++ b/dts/bindings/crypto/nuvoton,npcx-sha.yaml @@ -10,3 +10,10 @@ include: base.yaml properties: reg: required: true + + context-buffer-size: + type: int + required: true + description: | + Size of the pre-allocated buffer for the SHA ROM API to store the + intermdiate computation result and final digest. diff --git a/dts/bindings/crypto/renesas,smartbond-crypto.yaml b/dts/bindings/crypto/renesas,smartbond-crypto.yaml new file mode 100644 index 00000000000..7bee8dd4f9b --- /dev/null +++ b/dts/bindings/crypto/renesas,smartbond-crypto.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2023 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +include: base.yaml + +description: Renesas SmartBond(tm) CRYPTO + +compatible: "renesas,smartbond-crypto" + +properties: + reg: + required: true + + interrupts: + required: true diff --git a/dts/bindings/dac/adi,ad5592-dac.yaml b/dts/bindings/dac/adi,ad5592-dac.yaml new file mode 100644 index 00000000000..3ac8087b91d --- /dev/null +++ b/dts/bindings/dac/adi,ad5592-dac.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2023 Grinn +# SPDX-License-Identifier: Apache-2.0 + +description: AD5592 DAC Controller + +compatible: "adi,ad5592-dac" + +include: dac-controller.yaml + +properties: + "#io-channel-cells": + const: 1 + +io-channel-cells: + - output diff --git a/dts/bindings/dac/adi,ad5628.yaml b/dts/bindings/dac/adi,ad5628.yaml new file mode 100644 index 00000000000..409a45bbfde --- /dev/null +++ b/dts/bindings/dac/adi,ad5628.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: Analog Devices 12-Bit 8-channel SPI DAC + +compatible: "adi,ad5628" + +include: adi,ad56xx-base.yaml diff --git a/dts/bindings/dac/adi,ad5648.yaml b/dts/bindings/dac/adi,ad5648.yaml new file mode 100644 index 00000000000..0f6d16909a1 --- /dev/null +++ b/dts/bindings/dac/adi,ad5648.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: Analog Devices 14-Bit 8-channel SPI DAC + +compatible: "adi,ad5648" + +include: adi,ad56xx-base.yaml diff --git a/dts/bindings/dac/adi,ad5668.yaml b/dts/bindings/dac/adi,ad5668.yaml new file mode 100644 index 00000000000..7ddc906ed01 --- /dev/null +++ b/dts/bindings/dac/adi,ad5668.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: Analog Devices 16-Bit 8-channel SPI DAC + +compatible: "adi,ad5668" + +include: adi,ad56xx-base.yaml diff --git a/dts/bindings/dac/adi,ad5672.yaml b/dts/bindings/dac/adi,ad5672.yaml new file mode 100644 index 00000000000..7e987faf1e5 --- /dev/null +++ b/dts/bindings/dac/adi,ad5672.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: Analog Devices 12-Bit 8-channel SPI DAC + +compatible: "adi,ad5672" + +include: adi,ad56xx-base.yaml diff --git a/dts/bindings/dac/adi,ad5674.yaml b/dts/bindings/dac/adi,ad5674.yaml new file mode 100644 index 00000000000..9ee6883dfb9 --- /dev/null +++ b/dts/bindings/dac/adi,ad5674.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: Analog Devices 12-Bit 16-channel SPI DAC + +compatible: "adi,ad5674" + +include: adi,ad56xx-base.yaml diff --git a/dts/bindings/dac/adi,ad5676.yaml b/dts/bindings/dac/adi,ad5676.yaml new file mode 100644 index 00000000000..2c9a21448e0 --- /dev/null +++ b/dts/bindings/dac/adi,ad5676.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: Analog Devices 16-Bit 8-channel SPI DAC + +compatible: "adi,ad5676" + +include: adi,ad56xx-base.yaml diff --git a/dts/bindings/dac/adi,ad5679.yaml b/dts/bindings/dac/adi,ad5679.yaml new file mode 100644 index 00000000000..ad6d8594e4b --- /dev/null +++ b/dts/bindings/dac/adi,ad5679.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: Analog Devices 16-Bit 16-channel SPI DAC + +compatible: "adi,ad5679" + +include: adi,ad56xx-base.yaml diff --git a/dts/bindings/dac/adi,ad5684.yaml b/dts/bindings/dac/adi,ad5684.yaml new file mode 100644 index 00000000000..c7709ffebf0 --- /dev/null +++ b/dts/bindings/dac/adi,ad5684.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: Analog Devices 12-Bit 4-channel SPI DAC + +compatible: "adi,ad5684" + +include: adi,ad56xx-base.yaml diff --git a/dts/bindings/dac/adi,ad5686.yaml b/dts/bindings/dac/adi,ad5686.yaml new file mode 100644 index 00000000000..eb950d8b5c1 --- /dev/null +++ b/dts/bindings/dac/adi,ad5686.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: Analog Devices 16-Bit 4-channel SPI DAC + +compatible: "adi,ad5686" + +include: adi,ad56xx-base.yaml diff --git a/dts/bindings/dac/adi,ad5687.yaml b/dts/bindings/dac/adi,ad5687.yaml new file mode 100644 index 00000000000..998498cff7e --- /dev/null +++ b/dts/bindings/dac/adi,ad5687.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: Analog Devices 12-Bit 2-channel SPI DAC + +compatible: "adi,ad5687" + +include: adi,ad56xx-base.yaml diff --git a/dts/bindings/dac/adi,ad5689.yaml b/dts/bindings/dac/adi,ad5689.yaml new file mode 100644 index 00000000000..b897f3ed37d --- /dev/null +++ b/dts/bindings/dac/adi,ad5689.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: Analog Devices 16-Bit 2-channel SPI DAC + +compatible: "adi,ad5689" + +include: adi,ad56xx-base.yaml diff --git a/dts/bindings/dac/adi,ad56xx-base.yaml b/dts/bindings/dac/adi,ad56xx-base.yaml new file mode 100644 index 00000000000..68043f46115 --- /dev/null +++ b/dts/bindings/dac/adi,ad56xx-base.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +include: [dac-controller.yaml, spi-device.yaml] + +properties: + "#io-channel-cells": + const: 1 + + reset-gpios: + type: phandle-array + description: "GPIO for reset" + +io-channel-cells: + - output diff --git a/dts/bindings/dac/nxp,lpdac.yaml b/dts/bindings/dac/nxp,lpdac.yaml new file mode 100644 index 00000000000..4b9e67f310f --- /dev/null +++ b/dts/bindings/dac/nxp,lpdac.yaml @@ -0,0 +1,29 @@ +# Copyright (c) 2023, NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP MCUX LPDAC + +compatible: "nxp,lpdac" + +include: [dac-controller.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + voltage-reference: + type: int + required: true + description: | + DAC voltage reference select. The meaning of the value may be + different for different SoCs. + + low-power-mode: + type: boolean + description: Enable low-power mode + + "#io-channel-cells": + const: 1 + +io-channel-cells: + - output diff --git a/dts/bindings/disk/zephyr,ram-disk.yaml b/dts/bindings/disk/zephyr,ram-disk.yaml new file mode 100644 index 00000000000..68b9709cede --- /dev/null +++ b/dts/bindings/disk/zephyr,ram-disk.yaml @@ -0,0 +1,35 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: RAM disk + +compatible: "zephyr,ram-disk" + +include: ["base.yaml", "memory-region.yaml"] + +properties: + disk-name: + type: string + required: true + description: | + Disk name. + + sector-size: + type: int + required: true + enum: [512, 1024, 2048, 4096, 8192, 16384, 32768, 65536] + description: | + Disk sector size in bytes. + + sector-count: + type: int + required: true + description: | + Number of sectors. + + ram-region: + type: phandle + description: | + Optional phandle to the memory region to be used as a RAM disk, + if not used a local buffer is defined for each disk instance. + Use it with caution as it makes memory contents easily accessible. diff --git a/dts/bindings/display/sinowealth,sh1106-i2c.yaml b/dts/bindings/display/sinowealth,sh1106-i2c.yaml new file mode 100644 index 00000000000..f476f838bbf --- /dev/null +++ b/dts/bindings/display/sinowealth,sh1106-i2c.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023, TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +description: SH1106 128x64 dot-matrix display controller on I2C bus + +compatible: "sinowealth,sh1106" + +include: ["solomon,ssd1306fb-common.yaml", "i2c-device.yaml"] diff --git a/dts/bindings/display/sinowealth,sh1106-spi.yaml b/dts/bindings/display/sinowealth,sh1106-spi.yaml new file mode 100644 index 00000000000..5fe3a2cf0f5 --- /dev/null +++ b/dts/bindings/display/sinowealth,sh1106-spi.yaml @@ -0,0 +1,14 @@ +# Copyright (c) 2023, TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +description: SH1106 128x64 dot-matrix display controller on SPI bus + +compatible: "sinowealth,sh1106" + +include: ["solomon,ssd1306fb-common.yaml", "spi-device.yaml"] + +properties: + data_cmd-gpios: + type: phandle-array + required: true + description: D/C# pin. diff --git a/dts/bindings/display/sitronix,st7735r.yaml b/dts/bindings/display/sitronix,st7735r.yaml index 987ff620ec5..90ead2b8731 100644 --- a/dts/bindings/display/sitronix,st7735r.yaml +++ b/dts/bindings/display/sitronix,st7735r.yaml @@ -1,7 +1,7 @@ # Copyright (c) 2020, Kim Bøndergaard # SPDX-License-Identifier: Apache-2.0 -description: ST7735R 160x128 display controller +description: ST7735R/ST7735S 160x128 (max) display controller compatible: "sitronix,st7735r" diff --git a/dts/bindings/display/solomon,ssd1306fb-common.yaml b/dts/bindings/display/solomon,ssd1306fb-common.yaml index a4949953bc6..c4e82d84324 100644 --- a/dts/bindings/display/solomon,ssd1306fb-common.yaml +++ b/dts/bindings/display/solomon,ssd1306fb-common.yaml @@ -48,3 +48,15 @@ properties: The RESET pin of SSD1306 is active low. If connected directly the MCU pin should be configured as active low. + + inversion-on: + type: boolean + description: Turn on display color inverting + + ready-time-ms: + type: int + default: 10 + description: | + Time it takes for the device from power up to become responsive and + accepting commands. Defaults to 10ms (found by trial and error) if not + provided. diff --git a/dts/bindings/dma/andestech,atcdmac300.yaml b/dts/bindings/dma/andestech,atcdmac300.yaml new file mode 100644 index 00000000000..931cc1ffaeb --- /dev/null +++ b/dts/bindings/dma/andestech,atcdmac300.yaml @@ -0,0 +1,84 @@ +# +# Copyright (c) 2023 Andes Technology Corporation. +# +# SPDX-License-Identifier: Apache-2.0 + +compatible: "andestech,atcdmac300" + +include: dma-controller.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + chain-transfer: + type: int + + "#dma-cells": + const: 3 + +dma-cells: + - channel + - slot + - channel-config + +description: | + Andes DMA controller + channel: a phandle to the DMA controller plus the following four integer cells: + 1. channel: the dma channel + 2. slot: DMA peripherial request ID + 3. channel-config: A 32bit mask specifying the DMA channel configuration + which is device dependent: + -bit 0-1 : Direction (see dma.h) + 0x0: MEM to MEM + 0x1: MEM to PERIPH + 0x2: PERIPH to MEM + 0x3: reserved for PERIPH to PERIPH + -bit 2 : Peripheral Increment Address + 0x0: no address increment between transfers + 0x1: increment address between transfers + -bit 3 : Memory Increment Address + 0x0: no address increment between transfers + 0x1: increment address between transfers + -bit 4-6 : Peripheral data size + 0x0: Byte (8 bits) + 0x1: Half-word (16 bits) + 0x2: Word (32 bits) + 0x3: Double word (64 bits) + 0x4: Quad word (128 bits) + 0x5: Eight word (256 bits) + 0x6-0x7: reserved + -bit 7-9 : Memory data size + 0x0: Byte (8 bits) + 0x1: Half-word (16 bits) + 0x2: Word (32 bits) + 0x3: Double word (64 bits) + 0x4: Quad word (128 bits) + 0x5: Eight word (256 bits) + 0x6-0x7: reserved + -bit 10 : Priority level + 0x0: lower priority + 0x1: higher priority + + examples for andes_v5_ae350 DMA instance + dma0: dma0@f0c00000 { + compatible = "andestech,atcdmac300"; + ... + dma-channels = <8>; + dma-requests = <16>; + status = "disabled"; + label = "DMA_0"; + }; + + For the client part, example for andes_ae350 DMA instance + Tx using channel 2, slot 0 + Rx using channel 3, slot 1 + spi1: spi@f0f00000 { + compatible = "andestech,atcspi200" + dmas = <&dma0 2 0 0x0129>, + <&dma0 3 1 0x012A>; + dma-names = "tx", "rx"; + }; diff --git a/dts/bindings/dma/intel,lpss.yaml b/dts/bindings/dma/intel,lpss.yaml index d9fc4a60f11..5f1954216f0 100644 --- a/dts/bindings/dma/intel,lpss.yaml +++ b/dts/bindings/dma/intel,lpss.yaml @@ -11,5 +11,10 @@ properties: "#dma-cells": const: 1 + dma-parent: + type: phandle + description: | + Parent device for LPSS DMA to get its base address. + dma-cells: - channel diff --git a/dts/bindings/dma/intel,sedi_dma.yaml b/dts/bindings/dma/intel,sedi_dma.yaml new file mode 100644 index 00000000000..3fe1036c00c --- /dev/null +++ b/dts/bindings/dma/intel,sedi_dma.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +description: Intel SEDI DMA controller. + +compatible: "intel,sedi_dma" + +include: dma-controller.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + peripheral-id: + type: int + description: Peripheral Instance ID + required: true diff --git a/dts/bindings/dma/nxp,mcux-edma-v3.yaml b/dts/bindings/dma/nxp,mcux-edma-v3.yaml new file mode 100644 index 00000000000..2711c3be124 --- /dev/null +++ b/dts/bindings/dma/nxp,mcux-edma-v3.yaml @@ -0,0 +1,14 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP MCUX EDMA version 3 controller + +compatible: "nxp,mcux-edma-v3" + +include: nxp,mcux-edma.yaml + +properties: + no-error-irq: + type: boolean + description: | + If the SoCs don't have a separate interrupt id for error IRQ. diff --git a/dts/bindings/dma/nxp,mcux-edma.yaml b/dts/bindings/dma/nxp,mcux-edma.yaml index 2ce3b9c6eca..50df791ebf7 100644 --- a/dts/bindings/dma/nxp,mcux-edma.yaml +++ b/dts/bindings/dma/nxp,mcux-edma.yaml @@ -10,6 +10,9 @@ include: dma-controller.yaml properties: reg: required: true + description: | + Specifies base physical address(s) and size of DMA and respective DMAMUX register(s) + that routes DMA sources interrupts: required: true @@ -20,6 +23,19 @@ properties: dma-requests: required: true + dmamux-reg-offset: + type: int + default: 0 + description: + The offset value for obtaining DMAMUX register index from DMAMUX channel. + Default value means DMAMUX channel is identical with DMAMUX register index + + channel-gap: + type: array + description: | + On some platforms, there may be a gap in the channels and + this array specifies the start and end of a single gap + nxp,mem2mem: type: boolean description: If the DMA controller supports memory to memory transfer @@ -28,26 +44,22 @@ properties: type: boolean description: If the DMA controller supports always on + irq-shared-offset: + type: int + default: 0 + description: | + Describes an offset between two channels share the same interrupt entry. + Default value means each channel has separate interrupt entry. + "#dma-cells": type: int required: true description: Number of items to expect in a DMAMUX specifier -# Parameter syntax of NXP follows the dmamux client dts syntax -# in the Linux kernel declared in -# https://git.kernel.org/pub/scm/linux/kernel/git/devicetree/devicetree-rebasing.git/tree/Bindings/dma/fsl-edma.txt -# # - #dma-cells : Must be <2>. -# The 1st cell specifies the DMAMUX(0 for DMAMUX0 and 1 for DMAMUX1). -# Specific request source can only be multiplexed by specific channels -# group called DMAMUX. -# The 2nd cell specifies the request source(slot) ID. +# The 1st cell specifies the DMA channel which will be used +# The 2nd cell specifies the request source (slot) ID. # See the SoC's reference manual for all the supported request sources. -# * DMA clients -# DMA client drivers that uses the DMA function must use the format described -# in the dma.txt file, using a two-cell specifier for each channel: the 1st -# specifies the channel group(DMAMUX) in which this request can be multiplexed, -# and the 2nd specifies the request source. dma-cells: - mux diff --git a/dts/bindings/dma/nxp,smartdma.yaml b/dts/bindings/dma/nxp,smartdma.yaml new file mode 100644 index 00000000000..0724616b5c1 --- /dev/null +++ b/dts/bindings/dma/nxp,smartdma.yaml @@ -0,0 +1,28 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP SmartDMA controller + +compatible: "nxp,smartdma" + +include: dma-controller.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + program-mem: + type: int + required: true + description: | + Program memory to load SMARTDMA routines into. Must be set to a RAM + region that the SMARTDMA can access on the chip. + + # SmartDMA does not support channels, so no DMA cells should be provided. + # the driver or application using SMARTDMA can set the DMA program to run + # using the `dma_slot` parameter. + "#dma-cells": + const: 0 diff --git a/dts/bindings/dma/nxp,sof-host-dma.yaml b/dts/bindings/dma/nxp,sof-host-dma.yaml new file mode 100644 index 00000000000..ebb03c46d8b --- /dev/null +++ b/dts/bindings/dma/nxp,sof-host-dma.yaml @@ -0,0 +1,12 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP SOF host DMA node + +compatible: "nxp,sof-host-dma" + +include: [base.yaml, dma-controller.yaml] + +properties: + dma-channels: + required: true diff --git a/dts/bindings/dma/renesas,smartbond-dma.yaml b/dts/bindings/dma/renesas,smartbond-dma.yaml new file mode 100644 index 00000000000..0845df77463 --- /dev/null +++ b/dts/bindings/dma/renesas,smartbond-dma.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2023 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +include: dma-controller.yaml + +description: Renesas Smartbond(tm) DMA + +compatible: "renesas,smartbond-dma" + +properties: + reg: + required: true + + interrupts: + required: true + + block-count: + required: true + type: int + const: 1 + description: Number of block counts supported diff --git a/dts/bindings/dsa/microchip_dsa.yaml b/dts/bindings/dsa/microchip_dsa.yaml index 8762fec748c..4a607b11ae4 100644 --- a/dts/bindings/dsa/microchip_dsa.yaml +++ b/dts/bindings/dsa/microchip_dsa.yaml @@ -12,16 +12,6 @@ properties: dsa-slave-ports: type: int description: Number of slave ports on the switch - spi-cpha: - type: boolean - description: | - Set to indicate phase starts with asserted half-phase (CPHA=1). - For this driver using this property requires also using cpol. - spi-cpol: - type: boolean - description: | - Set to indicate clock leading edge is falling (CPOL=1). - For this driver using this property requires also using cpha. reset-gpios: type: phandle-array description: | diff --git a/dts/bindings/ethernet/adi,adin1110.yaml b/dts/bindings/ethernet/adi,adin1110.yaml index 4f8bc6f8b25..8b94e1be839 100644 --- a/dts/bindings/ethernet/adi,adin1110.yaml +++ b/dts/bindings/ethernet/adi,adin1110.yaml @@ -20,7 +20,7 @@ description: | status = "okay"; #address-cells = <1>; #size-cells = <0>; - phy@1 { + ethernet-phy@1 { reg = <0x1>; compatible = "adi,adin2111-phy"; status = "okay"; diff --git a/dts/bindings/ethernet/adi,adin2111.yaml b/dts/bindings/ethernet/adi,adin2111.yaml index 8c0f9cb2025..f1b5c1b53c1 100644 --- a/dts/bindings/ethernet/adi,adin2111.yaml +++ b/dts/bindings/ethernet/adi,adin2111.yaml @@ -23,12 +23,12 @@ description: | status = "okay"; #address-cells = <1>; #size-cells = <0>; - phy@1 { + ethernet-phy@1 { reg = <0x1>; compatible = "adi,adin2111-phy"; status = "okay"; }; - phy@2 { + ethernet-phy@2 { reg = <0x2>; compatible = "adi,adin2111-phy"; status = "okay"; diff --git a/dts/bindings/ethernet/ethernet-phy.yaml b/dts/bindings/ethernet/ethernet-phy.yaml index 9568c036d2e..77278c2ca40 100644 --- a/dts/bindings/ethernet/ethernet-phy.yaml +++ b/dts/bindings/ethernet/ethernet-phy.yaml @@ -10,8 +10,7 @@ compatible: "ethernet-phy" include: phy.yaml properties: - address: - type: int + reg: required: true description: PHY address no-reset: diff --git a/dts/bindings/ethernet/microchip,lan865x.yaml b/dts/bindings/ethernet/microchip,lan865x.yaml new file mode 100644 index 00000000000..699bfca7dc6 --- /dev/null +++ b/dts/bindings/ethernet/microchip,lan865x.yaml @@ -0,0 +1,46 @@ +# Copyright (c) 2023 DENX Software Engineering GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: | + LAN865x standalone 10BASE-T1L Ethernet controller with SPI interface. + +compatible: "microchip,lan865x" + +include: [spi-device.yaml, ethernet-controller.yaml] + +properties: + tx-cut-through-mode: + type: boolean + description: Enable TX cut through mode + rx-cut-through-mode: + type: boolean + description: Enable RX cut through mode + plca-enable: + type: boolean + description: Enable or disable PLCA support + plca-node-id: + type: int + description: Specify the PLCA node ID number + plca-node-count: + type: int + description: Specify the PLCA node count + plca-burst-count: + type: int + description: Specify the PLCA burst count + plca-burst-timer: + type: int + description: Specify the PLCA burst timer value + plca-to-timer: + type: int + description: Specify the PLCA to timer value + int-gpios: + type: phandle-array + required: true + description: | + The interrupt pin of LAN865X is active low. + If connected directly the MCU pin should be configured + as active low. + rst-gpios: + type: phandle-array + required: true + description: The reset pin of LAN865X. diff --git a/dts/bindings/ethernet/nuvoton,numaker-ethernet.yaml b/dts/bindings/ethernet/nuvoton,numaker-ethernet.yaml new file mode 100644 index 00000000000..4cdf35c4f60 --- /dev/null +++ b/dts/bindings/ethernet/nuvoton,numaker-ethernet.yaml @@ -0,0 +1,30 @@ +# Copyright (c) 2023 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +description: Nuvoton, NuMaker Ethernet controller + +compatible: "nuvoton,numaker-ethernet" + +include: + - ethernet-controller.yaml + - ethernet,fixed-link.yaml + - reset-device.yaml + - pinctrl-device.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + resets: + required: true + + clocks: + required: true + + phy-addr: + type: int + description: Address of the phy controller + required: true diff --git a/dts/bindings/flash_controller/ambiq,flash-controller.yaml b/dts/bindings/flash_controller/ambiq,flash-controller.yaml new file mode 100644 index 00000000000..60cb1dee81b --- /dev/null +++ b/dts/bindings/flash_controller/ambiq,flash-controller.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023, Ambiq Micro Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: Ambiq flash controller + +compatible: "ambiq,flash-controller" + +include: flash-controller.yaml diff --git a/dts/bindings/fuel-gauge/ti,bq27z746.yaml b/dts/bindings/fuel-gauge/ti,bq27z746.yaml new file mode 100644 index 00000000000..3de382ca7c3 --- /dev/null +++ b/dts/bindings/fuel-gauge/ti,bq27z746.yaml @@ -0,0 +1,13 @@ +# Copyright (c) 2023, ithinx GmbH +# Copyright (c) 2023, Tonies GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +description: | + Texas Instruments BQ27Z746 fuel gauge. For more info visit + https://www.ti.com/product/BQ27Z746 + + +compatible: "ti,bq27z746" + +include: [i2c-device.yaml, fuel-gauge.yaml] diff --git a/dts/bindings/gnss/gnss-pps.yaml b/dts/bindings/gnss/gnss-pps.yaml new file mode 100644 index 00000000000..5ec554b69e2 --- /dev/null +++ b/dts/bindings/gnss/gnss-pps.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2023 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +properties: + pps-mode: + type: string + required: true + description: | + PPS output mode: + - GNSS_PPS_MODE_DISABLED: Output disabled + - GNSS_PPS_MODE_ENABLED: Output always enabled + - GNSS_PPS_MODE_ENABLED_AFTER_LOCK: Output enabled from first lock + - GNSS_PPS_MODE_ENABLED_WHILE_LOCKED: Output enabled only while locked + enum: + - GNSS_PPS_MODE_DISABLED + - GNSS_PPS_MODE_ENABLED + - GNSS_PPS_MODE_ENABLED_AFTER_LOCK + - GNSS_PPS_MODE_ENABLED_WHILE_LOCKED + + pps-pulse-width: + type: int + description: 1PPS pulse width + default: 100 diff --git a/dts/bindings/gnss/quectel,lc26g.yaml b/dts/bindings/gnss/quectel,lc26g.yaml new file mode 100644 index 00000000000..bfb278147c6 --- /dev/null +++ b/dts/bindings/gnss/quectel,lc26g.yaml @@ -0,0 +1,11 @@ +# Copyright (c) 2023 Trackunit Corporation +# Copyright (c) 2023 Bjarki Arge Andreasen +# SPDX-License-Identifier: Apache-2.0 + +description: Quectel LC26G GNSS modem + +compatible: "quectel,lc26g" + +include: + - uart-device.yaml + - gnss-pps.yaml diff --git a/dts/bindings/gnss/quectel,lc86g.yaml b/dts/bindings/gnss/quectel,lc86g.yaml new file mode 100644 index 00000000000..a3b762149d9 --- /dev/null +++ b/dts/bindings/gnss/quectel,lc86g.yaml @@ -0,0 +1,11 @@ +# Copyright (c) 2023 Trackunit Corporation +# Copyright (c) 2023 Bjarki Arge Andreasen +# SPDX-License-Identifier: Apache-2.0 + +description: Quectel LC86G GNSS modem + +compatible: "quectel,lc86g" + +include: + - uart-device.yaml + - gnss-pps.yaml diff --git a/dts/bindings/gnss/quectel-lc76g.yaml b/dts/bindings/gnss/quectel-lc76g.yaml new file mode 100644 index 00000000000..45c1da2fbae --- /dev/null +++ b/dts/bindings/gnss/quectel-lc76g.yaml @@ -0,0 +1,11 @@ +# Copyright (c) 2023 Trackunit Corporation +# Copyright (c) 2023 Bjarki Arge Andreasen +# SPDX-License-Identifier: Apache-2.0 + +description: Quectel LC76G GNSS modem + +compatible: "quectel,lc76g" + +include: + - uart-device.yaml + - gnss-pps.yaml diff --git a/dts/bindings/gpio/adi,ad5592-gpio.yaml b/dts/bindings/gpio/adi,ad5592-gpio.yaml new file mode 100644 index 00000000000..b815f557c51 --- /dev/null +++ b/dts/bindings/gpio/adi,ad5592-gpio.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2023 Grinn +# SPDX-License-Identifier: Apache-2.0 + +description: AD5592 GPIO Controller + +compatible: "adi,ad5592-gpio" + +include: gpio-controller.yaml + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/gpio/altr,pio-1.0.yaml b/dts/bindings/gpio/altr,pio-1.0.yaml new file mode 100644 index 00000000000..d9711130e7c --- /dev/null +++ b/dts/bindings/gpio/altr,pio-1.0.yaml @@ -0,0 +1,42 @@ +# Copyright (c) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Altera PIO node + +compatible: "altr,pio-1.0" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + + direction: + type: string + description: | + Direction can be set to bidir, input, inout or output. + It cannot be configure when during the runtime and should be + set according to the synthesized FPGA design. + default: output + enum: + - "bidir" + - "input" + - "inout" + - "output" + + outset: + type: boolean + description: | + Enable outset register to specify which bit of the output port to set. + + outclear: + type: boolean + description: | + Enable outclear register to specify which output bit to clear. + + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/gpio/brcm,bcm2711-gpio.yaml b/dts/bindings/gpio/brcm,bcm2711-gpio.yaml new file mode 100644 index 00000000000..9237ee6dfc5 --- /dev/null +++ b/dts/bindings/gpio/brcm,bcm2711-gpio.yaml @@ -0,0 +1,22 @@ +# Copyright (c) 2023 Chen Xingyu +# SPDX-License-Identifier: Apache-2.0 + +description: BCM2711 GPIO + +compatible: "brcm,bcm2711-gpio" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/gpio/infineon,tle9104.yaml b/dts/bindings/gpio/infineon,tle9104.yaml new file mode 100644 index 00000000000..5893f1a355a --- /dev/null +++ b/dts/bindings/gpio/infineon,tle9104.yaml @@ -0,0 +1,50 @@ +# +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# +# SPDX-License-Identifier: Apache-2.0 +# + +description: Infineon TLE9104 4-channel powertrain switch + +compatible: "infineon,tle9104" + +include: [gpio-controller.yaml, spi-device.yaml] + +properties: + "#gpio-cells": + const: 2 + + ngpios: + type: int + required: true + const: 4 + description: Number of GPIOs supported + + en-gpios: + type: phandle-array + description: "GPIO for enable" + + resn-gpios: + type: phandle-array + required: true + description: "GPIO for reset" + + in1-gpios: + type: phandle-array + description: "GPIO for controlling OUT1" + + in2-gpios: + type: phandle-array + description: "GPIO for controlling OUT2" + + in3-gpios: + type: phandle-array + description: "GPIO for controlling OUT3" + + in4-gpios: + type: phandle-array + description: "GPIO for controlling OUT4" + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/gpio/intel,sedi-gpio.yaml b/dts/bindings/gpio/intel,sedi-gpio.yaml new file mode 100644 index 00000000000..747546bd56f --- /dev/null +++ b/dts/bindings/gpio/intel,sedi-gpio.yaml @@ -0,0 +1,30 @@ +# +# Copyright (c) 2023 Intel Corporation. +# +# SPDX-License-Identifier: Apache-2.0 +# + +description: Intel SEDI GPIO + +compatible: "intel,sedi-gpio" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + peripheral-id: + type: int + description: Peripheral Instance ID + required: true + + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/gpio/m5stack,mbus-header.yaml b/dts/bindings/gpio/m5stack,mbus-header.yaml new file mode 100644 index 00000000000..2ad85dd7a64 --- /dev/null +++ b/dts/bindings/gpio/m5stack,mbus-header.yaml @@ -0,0 +1,28 @@ +# Copyright (c) 2023 Martin Kiepfer +# SPDX-License-Identifier: Apache-2.0 + +description: | + GPIO pins exposed on M5Stack M-Bus headers. + + This binding provides a nexus mapping for 30 pins as depicted below. + + 0 GND 1 ADC0 + 2 GND 3 ADC1 + 4 GND 5 RESET + 6 MOSI 7 DAC0 + 8 MISO 9 DAC1 + 10 SCK 11 3.3V + 12 RXD0 13 TXD0 + 14 RXD1 15 TXD1 + 16 intSDA 17 intSCL + 18 SDA 19 SCL + 20 GPIO 21 GPIO + 22 GPIO 23 GPIO + 24 NC 25 GPIO + 26 NC 27 5V + 28 NC 29 BAT + + +compatible: "m5stack,mbus-header" + +include: [gpio-nexus.yaml, base.yaml] diff --git a/dts/bindings/gpio/nuvoton,nct38xx-gpio-alert.yaml b/dts/bindings/gpio/nuvoton,nct38xx-gpio-alert.yaml index c6043983b28..4cae0a79eb2 100644 --- a/dts/bindings/gpio/nuvoton,nct38xx-gpio-alert.yaml +++ b/dts/bindings/gpio/nuvoton,nct38xx-gpio-alert.yaml @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 description: | - Nuvoton NCT38XX series I2C-based GPIO expander alert handler + Nuvoton NCT38XX series I2C-based GPIO expander alert handler. Example: nct3807_alert_1 { @@ -25,4 +25,4 @@ properties: type: phandles required: true description: | - NCT38XX devices which alert are handled by this alert handler. + List of NCT38XX multi-function devices managed by this alert handler. diff --git a/dts/bindings/gpio/nuvoton,nct38xx-gpio.yaml b/dts/bindings/gpio/nuvoton,nct38xx-gpio.yaml index 5f704e768da..5b9afbbc892 100644 --- a/dts/bindings/gpio/nuvoton,nct38xx-gpio.yaml +++ b/dts/bindings/gpio/nuvoton,nct38xx-gpio.yaml @@ -4,69 +4,83 @@ description: | Nuvoton NCT38XX series I2C-based GPIO expander + This must be a child of the NCT38xx multi-function device. + Example: &i2c0_0 { nct3807@70 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "nuvoton,nct38xx-gpio"; + compatible = "nuvoton,nct38xx"; reg = <0x70>; - gpio@0 { - compatible = "nuvoton,nct38xx-gpio-port"; - reg = <0x0>; - gpio-controller; - #gpio-cells = <2>; - ngpios = <8>; - pin_mask = <0xff>; - pinmux_mask = <0xf7>; - }; + nct3807-gpio { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nuvoton,nct38xx-gpio"; + + gpio@0 { + compatible = "nuvoton,nct38xx-gpio-port"; + reg = <0x0>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + pin_mask = <0xff>; + pinmux_mask = <0xf7>; + }; - gpio@1 { - compatible = "nuvoton,nct38xx-gpio-port"; - reg = <0x1>; - gpio-controller; - #gpio-cells = <2>; - ngpios = <8>; - pin_mask = <0xff>; + gpio@1 { + compatible = "nuvoton,nct38xx-gpio-port"; + reg = <0x1>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + pin_mask = <0xff>; + }; }; }; nct3808_0_P1@71 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "nuvoton,nct38xx-gpio"; + compatible = "nuvoton,nct38xx"; reg = <0x71>; - gpio@0 { - compatible = "nuvoton,nct38xx-gpio-port"; - reg = <0x0>; - gpio-controller; - #gpio-cells = <2>; - ngpios = <8>; - pin_mask = <0xdc>; - pinmux_mask = <0xff>; + nct3808-0-p1-gpio { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nuvoton,nct38xx-gpio"; + + gpio@0 { + compatible = "nuvoton,nct38xx-gpio-port"; + reg = <0x0>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + pin_mask = <0xdc>; + pinmux_mask = <0xff>; + }; }; }; nct3808_0_P2@75 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "nuvoton,nct38xx-gpio"; + compatible = "nuvoton,nct38xx"; reg = <0x75>; - gpio@0 { - compatible = "nuvoton,nct38xx-gpio-port"; - reg = <0x0>; - gpio-controller; - #gpio-cells = <2>; - ngpios = <8>; - pin_mask = <0xdc>; - pinmux_mask = <0xff>; + nct3808-0-P2-gpio { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nuvoton,nct38xx-gpio"; + + gpio@0 { + compatible = "nuvoton,nct38xx-gpio-port"; + reg = <0x0>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + pin_mask = <0xdc>; + pinmux_mask = <0xff>; + }; }; }; }; compatible: "nuvoton,nct38xx-gpio" -include: [i2c-device.yaml] +include: [base.yaml] diff --git a/dts/bindings/gpio/nxp,s32-gpio.yaml b/dts/bindings/gpio/nxp,s32-gpio.yaml index 3d19b61c9b3..5ebdb38979b 100644 --- a/dts/bindings/gpio/nxp,s32-gpio.yaml +++ b/dts/bindings/gpio/nxp,s32-gpio.yaml @@ -1,7 +1,39 @@ -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # SPDX-License-Identifier: Apache-2.0 -description: NXP S32 GPIO node +description: | + NXP S32 GPIO controller. + + The GPIO controller provides the option to route external input pad interrupts + to either the SIUL2 EIRQ interrupt controller or, when available on the SoC, + the WKPU interrupt controller. By default, GPIO interrupts are routed to the + SIUL2 EIRQ interrupt controller. + + To route external interrupts to the WKPU interrupt controller, the GPIO + specifier must be supplied with the flag `NXP_S32_GPIO_INT_WKPU`. For example, + the following snippet of devicetree source code instructs the GPIO controller + to route the interrupt from pin 9 of `gpioa` to the WKPU interrupt controller: + + #include + + &device { + gpios = <&gpioa 9 (NXP_S32_GPIO_INT_WKPU | GPIO_ACTIVE_HIGH)>; + }; + + Explicitly specifying the routing of a GPIO interrupt to a particular + interrupt controller allows for the allocation of distinct interrupt + priorities according to application-specific requirements. This is owing to + the fact that each interrupt controller features its own interrupt vector. + To illustrate, it is plausible to allocate the board's button interrupts to + the interrupt controller configured with a lower priority compared to the one + designated for the data-ready interrupt originating from a sensor. This + decision is justified by the potentially higher importance of the latter + interrupt to the overall system operation. + + The `NXP_S32_GPIO_INT_WKPU` flag is intended exclusively for specifying WKPU + as the interrupt controller for the corresponding GPIO. It's worth noting that + despite being named WKPU, the flag is not meant to configure GPIOs as wake-up + sources. compatible: "nxp,s32-gpio" @@ -20,6 +52,17 @@ properties: external interrupt signal, this is a list of GPIO pins and respective external interrupt lines (). + nxp,wkpu: + type: phandle + description: | + NXP WKPU controller associated to this GPIO port. + + nxp,wkpu-interrupts: + type: array + description: | + Map between WKPU external interrupt sources and pins of this GPIO port, + as in a tuple ``. + "#gpio-cells": const: 2 diff --git a/dts/bindings/gpio/renesas,ra-gpio.yaml b/dts/bindings/gpio/renesas,ra-gpio.yaml new file mode 100644 index 00000000000..ad18a0d45da --- /dev/null +++ b/dts/bindings/gpio/renesas,ra-gpio.yaml @@ -0,0 +1,83 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas RA series GPIO + +compatible: "renesas,ra-gpio" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + + port-irq0-pins: + type: array + description: Pins allow to assign port-irq0 + + port-irq1-pins: + type: array + description: Pins allow to assign port-irq1 + + port-irq2-pins: + type: array + description: Pins allow to assign port-irq2 + + port-irq3-pins: + type: array + description: Pins allow to assign port-irq3 + + port-irq4-pins: + type: array + description: Pins allow to assign port-irq4 + + port-irq5-pins: + type: array + description: Pins allow to assign port-irq5 + + port-irq6-pins: + type: array + description: Pins allow to assign port-irq6 + + port-irq7-pins: + type: array + description: Pins allow to assign port-irq7 + + port-irq8-pins: + type: array + description: Pins allow to assign port-irq8 + + port-irq9-pins: + type: array + description: Pins allow to assign port-irq9 + + port-irq10-pins: + type: array + description: Pins allow to assign port-irq10 + + port-irq11-pins: + type: array + description: Pins allow to assign port-irq11 + + port-irq12-pins: + type: array + description: Pins allow to assign port-irq12 + + port-irq13-pins: + type: array + description: Pins allow to assign port-irq13 + + port-irq14-pins: + type: array + description: Pins allow to assign port-irq14 + + port-irq15-pins: + type: array + description: Pins allow to assign port-irq15 + + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/gpio/renesas,rzt2m-gpio.yaml b/dts/bindings/gpio/renesas,rzt2m-gpio.yaml new file mode 100644 index 00000000000..e099c81753e --- /dev/null +++ b/dts/bindings/gpio/renesas,rzt2m-gpio.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 +description: Renesas RZT2M GPIO + +compatible: "renesas,rzt2m-gpio" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/gpio/ti,davinci-gpio-nexus.yaml b/dts/bindings/gpio/ti,davinci-gpio-nexus.yaml index 3cfccfa5ee3..1b38fe927ca 100644 --- a/dts/bindings/gpio/ti,davinci-gpio-nexus.yaml +++ b/dts/bindings/gpio/ti,davinci-gpio-nexus.yaml @@ -7,7 +7,7 @@ description: GPIO controller for Davinci and Keystone devices compatible: "ti,davinci-gpio-nexus" -include: [base.yaml, gpio-nexus.yaml] +include: [base.yaml, gpio-nexus.yaml, pinctrl-device.yaml] properties: "#gpio-cells": diff --git a/dts/bindings/gpio/ti,davinci-gpio.yaml b/dts/bindings/gpio/ti,davinci-gpio.yaml index 0472dfa1aa1..64c0bbd5db5 100644 --- a/dts/bindings/gpio/ti,davinci-gpio.yaml +++ b/dts/bindings/gpio/ti,davinci-gpio.yaml @@ -7,7 +7,7 @@ description: GPIO controller for Davinci and Keystone devices. compatible: "ti,davinci-gpio" -include: [gpio-controller.yaml, base.yaml] +include: [base.yaml, gpio-controller.yaml, pinctrl-device.yaml] properties: reg: diff --git a/dts/bindings/i2c/gpio-i2c-switch.yaml b/dts/bindings/i2c/gpio-i2c-switch.yaml new file mode 100644 index 00000000000..ebd932afc71 --- /dev/null +++ b/dts/bindings/i2c/gpio-i2c-switch.yaml @@ -0,0 +1,24 @@ +# Copyright (c) 2023, Ayush Singh +# Copyright (c) 2021, Jason Kridner, BeagleBoard.org Foundation +# SPDX-License-Identifier: Apache-2.0 + +description: | + GPIO enabled analog switch to isolate devices from an I2C bus + +compatible: "gpio-i2c-switch" + +include: i2c-controller.yaml + +properties: + "#address-cells": + required: true + const: 1 + "#size-cells": + required: true + const: 0 + controller: + type: phandle + required: true + gpios: + type: phandle-array + required: true diff --git a/dts/bindings/i2c/infineon,cat1-i2c.yaml b/dts/bindings/i2c/infineon,cat1-i2c.yaml index fa7ca1b8f4a..ef287709b76 100644 --- a/dts/bindings/i2c/infineon,cat1-i2c.yaml +++ b/dts/bindings/i2c/infineon,cat1-i2c.yaml @@ -3,7 +3,42 @@ # # SPDX-License-Identifier: Apache-2.0 -description: Infineon CAT1 I2C +description: | + Infineon CAT1 I2C driver + + This driver configures the SCB as an I2C device. + + Example devicetree configuration with vl53l0x Time-of-Flight (ToF) + ranging sensor connected on the bus: + + i2c3: &scb3 { + compatible = "infineon,cat1-i2c"; + status = "okay"; + + #address-cells = <1>; + #size-cells = <0>; + + pinctrl-0 = <&p6_0_scb3_i2c_scl &p6_1_scb3_i2c_sda>; + pinctrl-names = "default"; + + vl53l0x@29 { + compatible = "st,vl53l0x"; + reg = <0x29>; + }; + }; + + The pinctrl nodes need to be configured as open-drain and + input-enable: + + &p6_0_scb3_i2c_scl { + drive-open-drain; + input-enable; + }; + + &p6_1_scb3_i2c_sda { + drive-open-drain; + input-enable; + }; compatible: "infineon,cat1-i2c" diff --git a/dts/bindings/i2c/ite,common-i2c.yaml b/dts/bindings/i2c/ite,common-i2c.yaml index 251903efafc..1e4e90793da 100644 --- a/dts/bindings/i2c/ite,common-i2c.yaml +++ b/dts/bindings/i2c/ite,common-i2c.yaml @@ -30,6 +30,54 @@ properties: 4 = I2C_CHANNEL_E, 5 = I2C_CHANNEL_F, + channel-switch-sel: + type: int + required: true + enum: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + description: | + The default setting is as described below + 0 = I2C_CHA_LOCATE: Channel A is located at SMCLK0/SMDAT0 + 1 = I2C_CHB_LOCATE: Channel B is located at SMCLK1/SMDAT1 + 2 = I2C_CHC_LOCATE: Channel C is located at SMCLK2/SMDAT2 + 3 = I2C_CHD_LOCATE: Channel D is located at SMCLK3/SMDAT3 + 4 = I2C_CHE_LOCATE: Channel E is located at SMCLK4/SMDAT4 + 5 = I2C_CHF_LOCATE: Channel F is located at SMCLK5/SMDAT5 + + The following is an example of the 'channel-switch-sel' property + being swapped between node &i2c0 and &i2c2 in the application: + Note: The property of 'port-num' cannot be changed in the + application. + + Channel C is located at SMCLK0/SMDAT0: + &i2c0 { + channel-switch-sel = ; + pinctrl-0 = <&i2c2_clk_gpf6_default + &i2c2_data_gpf7_default>; + pinctrl-names = "default"; + scl-gpios = <&gpiof 6 0>; + sda-gpios = <&gpiof 7 0>; + }; + + Channel A is located at SMCLK2/SMDAT2: + &i2c2 { + channel-switch-sel = ; + pinctrl-0 = <&i2c0_clk_gpb3_default + &i2c0_data_gpb4_default>; + pinctrl-names = "default"; + scl-gpios = <&gpiob 3 0>; + sda-gpios = <&gpiob 4 0>; + }; + + If the property of 'channel-switch-sel' is changed, the pinctrl + setting and recovery pin in &i2c0 and &i2c2 nodes must also be + modified accordingly. + scl-gpios: type: phandle-array required: true diff --git a/dts/bindings/i2c/ite,enhance-i2c.yaml b/dts/bindings/i2c/ite,enhance-i2c.yaml index 98e3e4ec46b..446f3f09aea 100644 --- a/dts/bindings/i2c/ite,enhance-i2c.yaml +++ b/dts/bindings/i2c/ite,enhance-i2c.yaml @@ -24,3 +24,9 @@ properties: This option is used when the I2C target is enabled. It is necessary to prevent the target port from being configured with I2C host related initialization. + + target-pio-mode: + type: boolean + description: | + This option is used when the I2C target is enabled and it can + support PIO mode for I2C target transfer. diff --git a/dts/bindings/i2c/nordic,nrf-twi-common.yaml b/dts/bindings/i2c/nordic,nrf-twi-common.yaml index 621d45d0f4b..a2052e360d1 100644 --- a/dts/bindings/i2c/nordic,nrf-twi-common.yaml +++ b/dts/bindings/i2c/nordic,nrf-twi-common.yaml @@ -15,3 +15,10 @@ properties: pinctrl-0: required: true + + easydma-maxcnt-bits: + type: int + required: true + description: | + Maximum number of bits available in the EasyDMA MAXCNT register. This + property must be set at SoC level DTS files. diff --git a/dts/bindings/i2c/nxp,kinetis-i2c.yaml b/dts/bindings/i2c/nxp,kinetis-i2c.yaml index 86bf2897a93..32c41632140 100644 --- a/dts/bindings/i2c/nxp,kinetis-i2c.yaml +++ b/dts/bindings/i2c/nxp,kinetis-i2c.yaml @@ -15,5 +15,4 @@ properties: required: true pinctrl-0: - type: phandles required: true diff --git a/dts/bindings/i2c/raspberrypi,pico-i2c.yaml b/dts/bindings/i2c/raspberrypi,pico-i2c.yaml new file mode 100644 index 00000000000..ac055dcfd59 --- /dev/null +++ b/dts/bindings/i2c/raspberrypi,pico-i2c.yaml @@ -0,0 +1,5 @@ +description: Raspberry Pi Pico I2C + +compatible: "raspberrypi,pico-i2c" + +include: ["snps,designware-i2c.yaml", "reset-device.yaml"] diff --git a/dts/bindings/i2c/sifive,i2c0.yaml b/dts/bindings/i2c/sifive,i2c0.yaml index 81c94e29e6c..8adb27eaa23 100644 --- a/dts/bindings/i2c/sifive,i2c0.yaml +++ b/dts/bindings/i2c/sifive,i2c0.yaml @@ -5,7 +5,7 @@ description: SiFive Freedom I2C interface compatible: "sifive,i2c0" -include: i2c-controller.yaml +include: [i2c-controller.yaml, pinctrl-device.yaml] properties: reg: diff --git a/dts/bindings/i2c/telink,b91-i2c.yaml b/dts/bindings/i2c/telink,b91-i2c.yaml index d0de9f93891..fe700641748 100644 --- a/dts/bindings/i2c/telink,b91-i2c.yaml +++ b/dts/bindings/i2c/telink,b91-i2c.yaml @@ -3,7 +3,7 @@ description: Telink B91 I2C -include: i2c-controller.yaml +include: [i2c-controller.yaml, pinctrl-device.yaml] compatible: "telink,b91-i2c" @@ -12,5 +12,4 @@ properties: required: true pinctrl-0: - type: phandles required: true diff --git a/dts/bindings/i2c/zephyr,i2c-dump-allowlist.yaml b/dts/bindings/i2c/zephyr,i2c-dump-allowlist.yaml new file mode 100644 index 00000000000..b1657aa7459 --- /dev/null +++ b/dts/bindings/i2c/zephyr,i2c-dump-allowlist.yaml @@ -0,0 +1,16 @@ +# Copyright 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +description: Devices allowlist for i2c messages dump + +compatible: "zephyr,i2c-dump-allowlist" + +include: base.yaml + +properties: + status: + const: "okay" + + devices: + required: true + type: phandles diff --git a/dts/bindings/i2s/nxp,mcux-i2s.yaml b/dts/bindings/i2s/nxp,mcux-i2s.yaml index a4eae452396..25295432874 100644 --- a/dts/bindings/i2s/nxp,mcux-i2s.yaml +++ b/dts/bindings/i2s/nxp,mcux-i2s.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2021, NXP +# Copyright 2021,2023 NXP # SPDX-License-Identifier: Apache-2.0 description: NXP mcux SAI-I2S controller @@ -60,3 +60,8 @@ properties: nxp,tx-channel: type: int description: tx channel the maximum number is SOC dependent + + clock-mux: + required: true + type: int + description: Clock mux source for SAI root clock diff --git a/dts/bindings/i3c/nxp,mcux-i3c.yaml b/dts/bindings/i3c/nxp,mcux-i3c.yaml index a31d61d6a85..2fd62be9694 100644 --- a/dts/bindings/i3c/nxp,mcux-i3c.yaml +++ b/dts/bindings/i3c/nxp,mcux-i3c.yaml @@ -36,3 +36,12 @@ properties: type: int description: Slow clock divider for I3C required: true + + disable-open-drain-high-pp: + type: boolean + description: | + If false, open drain high time is 1 PPBAUD count, + which is short high and long low. + If true, open drain high time is same as ODBAUD + so that open drain clock is 50% duty cycle. + Default is false. diff --git a/dts/bindings/iio/afe/current-sense-amplifier.yaml b/dts/bindings/iio/afe/current-sense-amplifier.yaml index e50bda74fe4..777116d0cff 100644 --- a/dts/bindings/iio/afe/current-sense-amplifier.yaml +++ b/dts/bindings/iio/afe/current-sense-amplifier.yaml @@ -37,3 +37,11 @@ properties: default: 1 description: | Amplifier gain divider. The default is <1>. + + power-gpios: + type: phandle-array + description: | + Control power to the current amplifier. + + If present the corresponding GPIO must be set to an active level + to enable the current amplifier. diff --git a/dts/bindings/input/gpio-kbd-matrix.yaml b/dts/bindings/input/gpio-kbd-matrix.yaml new file mode 100644 index 00000000000..ef08ebaa44e --- /dev/null +++ b/dts/bindings/input/gpio-kbd-matrix.yaml @@ -0,0 +1,43 @@ +# Copyright 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +description: | + GPIO based keyboard matrix input device + + Implement an input device for a GPIO based keyboard matrix. + + Example configuration: + + kbd-matrix { + compatible = "gpio-kbd-matrix"; + row-gpios = <&gpio0 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>, + <&gpio0 1 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + col-gpios = <&gpio0 2 GPIO_ACTIVE_LOW>, + <&gpio0 3 GPIO_ACTIVE_LOW>, + <&gpio0 4 GPIO_ACTIVE_LOW>; + no-ghostkey-check; + }; + +compatible: "gpio-kbd-matrix" + +include: + - name: kbd-matrix-common.yaml + property-blocklist: + - row-size + - col-size + +properties: + row-gpios: + type: phandle-array + required: true + description: | + GPIO for the keyboard matrix rows, up to 8 different GPIOs. All row GPIO + pins must have interrupt support. + + col-gpios: + type: phandle-array + required: true + description: | + GPIO for the keyboard matrix columns, supports up to 32 different GPIOs. + The pins will be driven according to the GPIO_ACTIVE_HIGH or + GPIO_ACTIVE_LOW flags when selected, high impedance when not selected. diff --git a/dts/bindings/kscan/hynitron,cst816s.yaml b/dts/bindings/input/hynitron,cst816s.yaml similarity index 100% rename from dts/bindings/kscan/hynitron,cst816s.yaml rename to dts/bindings/input/hynitron,cst816s.yaml diff --git a/dts/bindings/input/ite,it8xxx2-kbd.yaml b/dts/bindings/input/ite,it8xxx2-kbd.yaml new file mode 100644 index 00000000000..d809f41fbbc --- /dev/null +++ b/dts/bindings/input/ite,it8xxx2-kbd.yaml @@ -0,0 +1,48 @@ +# Copyright (c) 2021 ITE Corporation. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +description: ITE it8xxx2 keyboard matrix controller + +compatible: "ite,it8xxx2-kbd" + +include: [kbd-matrix-common.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + wucctrl: + type: phandles + description: | + Configure wakeup controller, this controller is used to set that + when the interrupt is triggered in EC low power mode, it can wakeup + EC or not. Via this controller, we set the wakeup trigger edge, + enable, disable, and clear wakeup status for the specific pin which + may be gpio pins or alternate pins. + + kso16-gpios: + type: phandle-array + required: true + description: | + The KSO16 pin for the selected port. + + kso17-gpios: + type: phandle-array + required: true + description: | + The KSO17 pin for the selected port. + + pinctrl-0: + required: true + + pinctrl-names: + required: true + + row-size: + required: true + + col-size: + required: true diff --git a/dts/bindings/input/kbd-matrix-common.yaml b/dts/bindings/input/kbd-matrix-common.yaml new file mode 100644 index 00000000000..e399bd4431f --- /dev/null +++ b/dts/bindings/input/kbd-matrix-common.yaml @@ -0,0 +1,56 @@ +# Copyright 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +description: Keyboard matrix device + +include: base.yaml + +properties: + row-size: + type: int + description: | + The number of rows in the keyboard matrix. + + col-size: + type: int + description: | + The number of column in the keyboard matrix. + + poll-period-ms: + type: int + default: 5 + description: | + Defines the poll period in msecs between between matrix scans. Defaults + to 5ms if unsepcified. + + poll-timeout-ms: + type: int + default: 100 + description: | + How long to wait before going from polling back to idle state. Defaults + to 100ms if unspecified. + + debounce-down-ms: + type: int + default: 10 + description: | + Debouncing time for a key press event. Defaults to 10ms if unspecified. + + debounce-up-ms: + type: int + default: 20 + description: | + Debouncing time for a key release event. Defaults to 20ms if unspecified. + + settle-time-us: + type: int + default: 50 + description: | + Delay between setting column output and reading the row values. Defaults + to 50us if unspecified. + + no-ghostkey-check: + type: boolean + description: | + Ignore the ghost key checking in the driver if the diodes are used + in the matrix hardware. diff --git a/dts/bindings/kscan/microchip,cap1203.yaml b/dts/bindings/input/microchip,cap1203.yaml similarity index 100% rename from dts/bindings/kscan/microchip,cap1203.yaml rename to dts/bindings/input/microchip,cap1203.yaml diff --git a/dts/bindings/input/nuvoton,npcx-kbd.yaml b/dts/bindings/input/nuvoton,npcx-kbd.yaml index 9ba33d31aa1..b7c30c5388f 100644 --- a/dts/bindings/input/nuvoton,npcx-kbd.yaml +++ b/dts/bindings/input/nuvoton,npcx-kbd.yaml @@ -5,7 +5,7 @@ description: Nuvoton NPCX keyboard scan controller compatible: "nuvoton,npcx-kbd" -include: [base.yaml, pinctrl-device.yaml] +include: [kbd-matrix-common.yaml, pinctrl-device.yaml] properties: reg: @@ -31,33 +31,7 @@ properties: &wui_io25 &wui_io24 &wui_io23 &wui_io22>; row-size: - type: int - default: 8 required: true - description: | - The row size is used in the keyboard matrix. - valid range: 1 - 8 col-size: - type: int - default: 18 required: true - description: | - The column size is used in the keyboard matrix. - valid range: 1 - 18 - - debounce-down-ms: - type: int - default: 10 - description: Determines the time in msecs for debouncing a key press. - - debounce-up-ms: - type: int - default: 20 - description: Determines the time in msecs for debouncing a key release. - - no-ghostkey-check: - type: boolean - description: | - Ignore the ghost key checking in the driver if the diodes are used - in the matrix hardware. diff --git a/dts/bindings/input/st,stmpe811.yaml b/dts/bindings/input/st,stmpe811.yaml new file mode 100644 index 00000000000..2a39595d13f --- /dev/null +++ b/dts/bindings/input/st,stmpe811.yaml @@ -0,0 +1,127 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +description: STMPE811 I2C touchscreen controller + +compatible: "st,stmpe811" + +include: i2c-device.yaml + +properties: + int-gpios: + type: phandle-array + description: | + Interrupt GPIO. Used by the controller to signal touch data is + available. Active low. + + screen-width: + type: int + default: 0 + description: | + Screen width for scaling the reported coordinates. + Default: raw touchscreen resolution. + + screen-height: + type: int + default: 0 + description: | + Screen height for scaling the reported coordinates. + Default: raw touchscreen resolution. + + raw-x-min: + type: int + description: | + Signed raw X axis start for scaling the reported coordinates. + No effect if screen size is not set. + + raw-y-min: + type: int + description: | + Signed raw Y axis start for scaling the reported coordinates. + No effect if screen size is not set. + + raw-x-max: + type: int + description: | + Raw X axis end for scaling the reported coordinates. + No effect if screen size is not set. + + raw-y-max: + type: int + description: | + Raw Y axis end for scaling the reported coordinates. + No effect if screen size is not set. + + panel-driver-settling-time-us: + type: int + enum: + - 10 + - 100 + - 500 + - 1000 + - 5000 + - 10000 + - 50000 + - 100000 + required: true + description: | + Panel driver settling time (microseconds). For large panels (> 6"), a capacitor of 10 nF + is recommended at the touchscreen terminals for noise filtering. + As a general rule, 1-5 nF capacitors require around 500 us settling time, and 5-10 nF need + around 1 ms. When a larger capacitor is used, this value should be changed, as it can + lead to inaccuracy of the measurement. + + touch-detect-delay-us: + type: int + enum: + - 10 + - 50 + - 100 + - 500 + - 1000 + - 5000 + - 10000 + - 50000 + required: true + description: | + Touch detect delay (microseconds) is the delay from the activation of the pull-up resistor + in the X+ line to the time the device performs touch detection. + If no capacitor, or a smaller capacitor is used, this value can be lowered to + minimize detection latency, but it could lower the position stability. + + touch-average-control: + type: int + enum: + - 1 + - 2 + - 4 + - 8 + required: true + description: | + Average control (number of samples). + This parameter can be set to any of the possible values. + Higher values result in more filtering of noise, but also introduce + more latency in the touch detection process. + + Use cases that require low touch detection latency + may benefit from using a lower value for this parameter, + at the cost of less noise filtering. + + tracking-index: + type: int + enum: + - 0 + - 4 + - 8 + - 16 + - 32 + - 64 + - 92 + - 127 + required: true + description: | + Tracking index determines the minimal distance between + the current touch position and the previous touch position. + If the distance is shorter than the tracking index, it is discarded. + Lowering the tracking index increases the frequency of touch events, + but also increases the load on the system. diff --git a/dts/bindings/input/zephyr,lvgl-encoder-input.yaml b/dts/bindings/input/zephyr,lvgl-encoder-input.yaml new file mode 100644 index 00000000000..8f16c69a1c7 --- /dev/null +++ b/dts/bindings/input/zephyr,lvgl-encoder-input.yaml @@ -0,0 +1,32 @@ +# Copyright 2023 Fabian Blatz +# SPDX-License-Identifier: Apache-2.0 + +description: | + LVGL encoder indev pseudo-device + + Listens for button/encoder input events and routes the + lv_indev_data_t to the underlying encoder lv_indev_t managed by LVGL. + + Example configuration: + + encoder { + compatible = "zephyr,lvgl-encoder-input"; + rotation-input-code = ; + button-input-code = ; + }; + +compatible: "zephyr,lvgl-encoder-input" + +include: zephyr,lvgl-common-input.yaml + +properties: + rotation-input-code: + type: int + required: true + description: | + Input event code associated with rotation (INPUT_REL_*). + + button-input-code: + type: int + description: | + Input event key code for encoder button (INPUT_KEY_* or INPUT_BTN_*). diff --git a/dts/bindings/interrupt-controller/nxp,s32-wkpu.yaml b/dts/bindings/interrupt-controller/nxp,s32-wkpu.yaml new file mode 100644 index 00000000000..8afa1b56b50 --- /dev/null +++ b/dts/bindings/interrupt-controller/nxp,s32-wkpu.yaml @@ -0,0 +1,28 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP S32 Wake-up Unit + +compatible: "nxp,s32-wkpu" + +include: base.yaml + +properties: + reg: + required: true + +child-binding: + description: | + NXP S32 WKPU interrupt line configuration. Specific requirements for each + interrupt line can be specified by adding children nodes to this controller, + labeled `line_`. For example: + + line_0: line_0 { + filter-enable; + }; + + properties: + filter-enable: + type: boolean + description: | + Enable analog glitch filter on the external interrupt pad input. diff --git a/dts/bindings/interrupt-controller/renesas,ra-interrupt-controller-unit.yaml b/dts/bindings/interrupt-controller/renesas,ra-interrupt-controller-unit.yaml new file mode 100644 index 00000000000..dd13f876cdc --- /dev/null +++ b/dts/bindings/interrupt-controller/renesas,ra-interrupt-controller-unit.yaml @@ -0,0 +1,20 @@ +# Copyright (c) 2023, TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas RA series interrupt controller unit + +compatible: "renesas,ra-interrupt-controller-unit" + +include: [interrupt-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#interrupt-cells": + const: 3 + +interrupt-cells: + - irq + - priority + - flags diff --git a/dts/bindings/interrupt-controller/sifive,plic-1.0.0.yaml b/dts/bindings/interrupt-controller/sifive,plic-1.0.0.yaml index 839506f33ea..4698d7f8515 100644 --- a/dts/bindings/interrupt-controller/sifive,plic-1.0.0.yaml +++ b/dts/bindings/interrupt-controller/sifive,plic-1.0.0.yaml @@ -12,7 +12,3 @@ properties: type: int description: Number of external interrupts supported required: true - riscv,trigger-reg-offset: - type: int - default: 4224 - description: Offset of the trigger type register if supported diff --git a/dts/bindings/ipc/zephyr,ipc-icbmsg.yaml b/dts/bindings/ipc/zephyr,ipc-icbmsg.yaml new file mode 100644 index 00000000000..0fc6be01a49 --- /dev/null +++ b/dts/bindings/ipc/zephyr,ipc-icbmsg.yaml @@ -0,0 +1,22 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +description: Inter-core messaging backend with dynamically allocated buffers + +compatible: "zephyr,ipc-icbmsg" + +include: zephyr,ipc-icmsg.yaml + +properties: + tx-blocks: + description: number of allocable TX blocks + required: true + type: int + + rx-blocks: + description: number of allocable RX blocks + required: true + type: int diff --git a/dts/bindings/ipc/zephyr,ipc-icmsg.yaml b/dts/bindings/ipc/zephyr,ipc-icmsg.yaml index b67c9072980..41793005373 100644 --- a/dts/bindings/ipc/zephyr,ipc-icmsg.yaml +++ b/dts/bindings/ipc/zephyr,ipc-icmsg.yaml @@ -21,6 +21,19 @@ properties: required: true type: phandle + dcache-alignment: + type: int + description: | + Data cache alignment. If any side of the communication uses cache on + rx-region/tx-region this property must be the biggest value of the + invalidation or the write-back size for both sides of the communication. + If no side of the communication uses data cache this property could be + safely omitted. + For example: + Side A: no data cache + Side B: 32 Bytes write-back size, 16 Bytes invalidation size + dcache-alignment = 32; for both + mboxes: description: phandle to the MBOX controller (TX and RX are required) required: true diff --git a/dts/bindings/ipm/intel,sedi-ipm.yaml b/dts/bindings/ipm/intel,sedi-ipm.yaml new file mode 100644 index 00000000000..48acb7d9b70 --- /dev/null +++ b/dts/bindings/ipm/intel,sedi-ipm.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2020-2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +description: INTEL SEDI IPM controller. + +compatible: "intel,sedi-ipm" + +include: base.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + peripheral-id: + type: int + required: true + description: sedi instance id of ipm diff --git a/dts/bindings/arm/nxp,imx-mu.yaml b/dts/bindings/ipm/nxp,imx-mu.yaml similarity index 100% rename from dts/bindings/arm/nxp,imx-mu.yaml rename to dts/bindings/ipm/nxp,imx-mu.yaml diff --git a/dts/bindings/kscan/ite,it8xxx2-kscan.yaml b/dts/bindings/kscan/ite,it8xxx2-kscan.yaml deleted file mode 100644 index 47a06b44ee3..00000000000 --- a/dts/bindings/kscan/ite,it8xxx2-kscan.yaml +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2021 ITE Corporation. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0 - -description: ITE it8xxx2 keyboard matrix controller - -compatible: "ite,it8xxx2-kscan" - -include: [kscan.yaml, pinctrl-device.yaml] - -properties: - reg: - required: true - - interrupts: - required: true - - wucctrl: - type: phandles - description: | - Configure wakeup controller, this controller is used to set that - when the interrupt is triggered in EC low power mode, it can wakeup - EC or not. Via this controller, we set the wakeup trigger edge, - enable, disable, and clear wakeup status for the specific pin which - may be gpio pins or alternate pins. - - kso16-gpios: - type: phandle-array - required: true - description: | - The KSO16 pin for the selected port. - - kso17-gpios: - type: phandle-array - required: true - description: | - The KSO17 pin for the selected port. - - pinctrl-0: - required: true - - pinctrl-names: - required: true diff --git a/dts/bindings/led/nxp,pca9633.yaml b/dts/bindings/led/nxp,pca9633.yaml index ec82d694573..a7e13b45fc2 100644 --- a/dts/bindings/led/nxp,pca9633.yaml +++ b/dts/bindings/led/nxp,pca9633.yaml @@ -3,3 +3,8 @@ description: NXP PCA9633 LED compatible: "nxp,pca9633" include: i2c-device.yaml + +properties: + disable-allcall: + type: boolean + description: Disable response to LED All Call address request diff --git a/dts/bindings/led_strip/worldsemi,ws2812-spi.yaml b/dts/bindings/led_strip/worldsemi,ws2812-spi.yaml index 0eafd37fde7..3c8626c1ec3 100644 --- a/dts/bindings/led_strip/worldsemi,ws2812-spi.yaml +++ b/dts/bindings/led_strip/worldsemi,ws2812-spi.yaml @@ -24,14 +24,6 @@ include: [spi-device.yaml, ws2812.yaml] properties: - spi-cpol: - type: boolean - description: Set SPI clock polarity. - - spi-cpha: - type: boolean - description: Set SPI clock phase. - spi-one-frame: type: int required: true diff --git a/dts/bindings/mbox/nxp,mbox-imx-mu.yaml b/dts/bindings/mbox/nxp,mbox-imx-mu.yaml new file mode 100644 index 00000000000..bc8bb5d6abf --- /dev/null +++ b/dts/bindings/mbox/nxp,mbox-imx-mu.yaml @@ -0,0 +1,29 @@ +description: | + NXP i.MX Message Unit as Zephyr MBOX + +compatible: "nxp,mbox-imx-mu" + +include: [base.yaml, mailbox-controller.yaml] + +properties: + interrupts: + required: true + + rx-channels: + type: int + enum: [1, 2, 3, 4] + description: | + Number of receive channels enabled on this instance. + Setting this value to N, will enable channels 0 to N-1, consecutively. + It should be set by the receiver core coupled with this MU instance. + + For example, if receiver A wants to Rx on channels 0 to 3, then A must + set rx-channels of muA as follows: + + mruA { + rx-channels = <4>; + status = "okay"; + }; + +mbox-cells: + - channel diff --git a/dts/bindings/mdio/adi,adin2111-mdio.yaml b/dts/bindings/mdio/adi,adin2111-mdio.yaml index ab20d5cb33d..a42a1f82113 100644 --- a/dts/bindings/mdio/adi,adin2111-mdio.yaml +++ b/dts/bindings/mdio/adi,adin2111-mdio.yaml @@ -8,12 +8,3 @@ compatible: "adi,adin2111-mdio" include: mdio-controller.yaml on-bus: adin2111 - -properties: - "#address-cells": - required: true - const: 1 - - "#size-cells": - required: true - const: 0 diff --git a/dts/bindings/mdio/atmel,sam-mdio.yaml b/dts/bindings/mdio/atmel,sam-mdio.yaml index 4eb649b5b24..bc15ad2b76f 100644 --- a/dts/bindings/mdio/atmel,sam-mdio.yaml +++ b/dts/bindings/mdio/atmel,sam-mdio.yaml @@ -8,3 +8,7 @@ compatible: "atmel,sam-mdio" include: - name: mdio-controller.yaml - name: pinctrl-device.yaml + +properties: + clocks: + type: phandle-array diff --git a/dts/bindings/mdio/mdio-controller.yaml b/dts/bindings/mdio/mdio-controller.yaml index aed844bf8f8..9a2a6782d53 100644 --- a/dts/bindings/mdio/mdio-controller.yaml +++ b/dts/bindings/mdio/mdio-controller.yaml @@ -8,17 +8,10 @@ include: base.yaml bus: mdio properties: - protocol: - type: string - description: | - MDIO bus framing protocol to use for communication. Most devices - support clause 22. + "#address-cells": + required: true + const: 1 - - clause 22: IEEE802.3 clause 22 frame format - - clause 45: IEEE802.3 clause 45 frame format - - micrel SMI: Micrel Serial Management Interface frame format - enum: - - "clause 22" - - "clause 45" - - "micrel SMI" - default: "clause 22" + "#size-cells": + required: true + const: 0 diff --git a/dts/bindings/mdio/zephyr,mdio-gpio.yaml b/dts/bindings/mdio/zephyr,mdio-gpio.yaml new file mode 100644 index 00000000000..6e847f969e4 --- /dev/null +++ b/dts/bindings/mdio/zephyr,mdio-gpio.yaml @@ -0,0 +1,19 @@ +# Copyright (c) 2023 Aleksandr Senin +# SPDX-License-Identifier: Apache-2.0 + +description: Zephyr MDIO bitbang driver + +compatible: "zephyr,mdio-gpio" + +include: mdio-controller.yaml + +properties: + mdc-gpios: + type: phandle-array + required: true + description: GPIO pin for the MDC + + mdio-gpios: + type: phandle-array + required: true + description: GPIO pin for the MDIO diff --git a/dts/bindings/memory-controllers/nxp,flexram.yaml b/dts/bindings/memory-controllers/nxp,flexram.yaml new file mode 100644 index 00000000000..76248c06394 --- /dev/null +++ b/dts/bindings/memory-controllers/nxp,flexram.yaml @@ -0,0 +1,52 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP FlexRAM on-chip ram controller + +include: base.yaml + +compatible: "nxp,flexram" + +properties: + reg: + required: true + + interrupts: + required: true + + flexram,has-magic-addr: + type: boolean + description: | + Whether or not the flexram on the SOC has the + magic address feature, which allows for an interrupt + on arbitrary address access in any on chip RAM region. + + flexram,num-ram-banks: + type: int + required: true + description: | + Number of RAM banks in the SOC ram array + + flexram,bank-size: + type: int + required: true + description: | + Size of each RAM bank in KB + + flexram,bank-spec: + type: array + description: | + Custom mapping of runtime RAM bank partitions. If this + property is present, then it will be used. If this + property is not present, then the fusemap configuration + will be used. + + flexram,tcm-read-wait-mode: + type: boolean + description: | + TCM RAM read will finish in 2 cycles instead of 1. + + flexram,tcm-write-wait-mode: + type: boolean + description: | + TCM RAM write will finish in 2 cycles instead of 1. diff --git a/dts/bindings/mfd/adi,ad5592.yaml b/dts/bindings/mfd/adi,ad5592.yaml new file mode 100644 index 00000000000..d3e404ec143 --- /dev/null +++ b/dts/bindings/mfd/adi,ad5592.yaml @@ -0,0 +1,13 @@ +# Copyright (C) 2023 Grinn +# SPDX-License-Identifier: Apache-2.0 + +description: Analog AD5592 ADC/DAC/GPIO chip + +compatible: "adi,ad5592" + +include: spi-device.yaml + +properties: + reset-gpios: + type: phandle-array + description: RESET pin diff --git a/dts/bindings/mfd/maxim,max20335.yaml b/dts/bindings/mfd/maxim,max20335.yaml new file mode 100644 index 00000000000..deec53c872d --- /dev/null +++ b/dts/bindings/mfd/maxim,max20335.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2023 Grinn +# SPDX-License-Identifier: Apache-2.0 + +description: Maxim MAX20335 + +compatible: "maxim,max20335" + +include: i2c-device.yaml + +properties: + reg: + required: true diff --git a/dts/bindings/mfd/nuvoton,nct38xx.yaml b/dts/bindings/mfd/nuvoton,nct38xx.yaml new file mode 100644 index 00000000000..ea1e250b4d7 --- /dev/null +++ b/dts/bindings/mfd/nuvoton,nct38xx.yaml @@ -0,0 +1,14 @@ +# Copyright (c) 2023, Google, LLC +# SPDX-License-Identifier: Apache-2.0 + +description: | + Nuvoton NCT38xx multi-function device + + The NCT38xx provides a TCPC and an I/O Expander capabilities. + + The TCPC and I/O expander drivers are added to the devicetree + as children of the nuvoton,nct38xx device. + +compatible: "nuvoton,nct38xx" + +include: i2c-device.yaml diff --git a/dts/bindings/mipi-dsi/nxp,mipi-dsi-2l.yaml b/dts/bindings/mipi-dsi/nxp,mipi-dsi-2l.yaml index fc0a69870c5..02871f29641 100644 --- a/dts/bindings/mipi-dsi/nxp,mipi-dsi-2l.yaml +++ b/dts/bindings/mipi-dsi/nxp,mipi-dsi-2l.yaml @@ -70,3 +70,9 @@ properties: description: Maximum clock speed supported by the device, in Hz. Leave at default if no DPHY PLL is present + + noncontinuous-hs-clk: + type: boolean + description: + Enable non-contiuous high speed clock. Saves power but introduces latency + when transitioning to high speed mode. diff --git a/dts/bindings/misc/intel,timeaware-gpio.yaml b/dts/bindings/misc/intel,timeaware-gpio.yaml new file mode 100644 index 00000000000..149e95bbb6a --- /dev/null +++ b/dts/bindings/misc/intel,timeaware-gpio.yaml @@ -0,0 +1,22 @@ +# Copyright (c) 2022 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Intel TGPIO node + +compatible: "intel,timeaware-gpio" + +include: [base.yaml] + +properties: + reg: + required: true + + timer-clock: + type: int + required: true + description: ART timer clock frequency + + max-pins: + type: int + required: true + description: Total number of available pins diff --git a/dts/bindings/misc/nxp,s32-emios.yaml b/dts/bindings/misc/nxp,s32-emios.yaml new file mode 100644 index 00000000000..61c831a01a0 --- /dev/null +++ b/dts/bindings/misc/nxp,s32-emios.yaml @@ -0,0 +1,116 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + NXP S32 Enhanced Modular IO SubSystem (eMIOS) node for S32 SoCs. + eMIOS provides independent unified channels (UCs), some of channels + have internal counter that either can be used independently or used + as a reference timebase (master bus) for other channels. + +compatible: "nxp,s32-emios" + +include: [base.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + interrupt-names: + required: true + + clocks: + required: true + + clock-divider: + type: int + required: true + description: | + Clock divider value for the global prescaler. Could be in range [1 ... 256] + + internal-cnt: + type: int + required: true + description: | + A mask for channels that have internal counter, lsb is channel 0. + +child-binding: + child-binding: + description: | + Node for eMIOS master bus. Each channel is capable to become a master bus has + a node defined in root devicetree but is disabled by default. To allow using + the master bus, the devicetree node should be enabled and dts properties + should be configured as required by application. + + For example, to enable bus A of eMIOS instance 0 that can be used as timebase + for channels from 0 to 22, freezed in debug mode: + master_bus { + emios0_bus_a: emios0_bus_a { + channel = <23>; + bus-type = "BUS_A"; + channel-mask = <0x07FFFFF>; + prescaler = <1>; + period = <65535>; + mode = ; + freeze; + status = "okay"; + }; + }; + + properties: + channel: + type: int + required: true + description: | + Channel identifier for the master bus. + + channel-mask: + type: int + required: true + description: | + A channel mask for channels that by hardware design can use this master bus + as timebase for the operation, lsb is channel 0. The mask bit for this master bus + must always 0 because a master bus should not do other thing than a base timer. + + prescaler: + type: int + required: true + description: | + Clock divider value for internal UC prescaler. + Clock for internal counter = (eMIOS clock / global prescaler) / internal prescaler. + enum: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] + + bus-type: + type: string + required: true + description: | + Master bus type. + enum: + - "BUS_A" + - "BUS_B" + - "BUS_C" + - "BUS_D" + - "BUS_E" + - "BUS_F" + + mode: + type: string + required: true + description: | + Master bus mode. + enum: + - "MCB_UP_COUNTER" + - "MCB_UP_DOWN_COUNTER" + + period: + type: int + required: true + description: | + Default period (in ticks) for master bus at boot time. This determines PWM period + for channels use this bus as reference timebase. Could be in range [2 ... 65535] + + freeze: + type: boolean + description: Freeze internal counter when the chip enters Debug mode. diff --git a/dts/bindings/misc/renesas,ra-sci.yaml b/dts/bindings/misc/renesas,ra-sci.yaml new file mode 100644 index 00000000000..d5feedde201 --- /dev/null +++ b/dts/bindings/misc/renesas,ra-sci.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas RA SCI controller + +compatible: "renesas,ra-sci" + +include: [base.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + clocks: + required: true diff --git a/dts/bindings/misc/zephyr,log-uart.yaml b/dts/bindings/misc/zephyr,log-uart.yaml new file mode 100644 index 00000000000..2e0a065e3b2 --- /dev/null +++ b/dts/bindings/misc/zephyr,log-uart.yaml @@ -0,0 +1,16 @@ +# Copyright (c) 2023 Meta +# SPDX-License-Identifier: Apache-2.0 + +description: Log Backend UART + +compatible: "zephyr,log-uart" + +include: [base.yaml] + +properties: + + uarts: + type: phandles + required: true + description: | + UART devices to be used by the UART log backend. diff --git a/dts/bindings/modem/quectel,eg25-g.yaml b/dts/bindings/modem/quectel,eg25-g.yaml new file mode 100644 index 00000000000..45284ddf174 --- /dev/null +++ b/dts/bindings/modem/quectel,eg25-g.yaml @@ -0,0 +1,16 @@ +description: Quectel EG25-G modem + +compatible: "quectel,eg25-g" + +include: uart-device.yaml + +properties: + mdm-reset-gpios: + type: phandle-array + required: true + + mdm-dtr-gpios: + type: phandle-array + + mdm-wdisable-gpios: + type: phandle-array diff --git a/dts/bindings/modem/telit,me910g1.yaml b/dts/bindings/modem/telit,me910g1.yaml new file mode 100644 index 00000000000..2599b6cd237 --- /dev/null +++ b/dts/bindings/modem/telit,me910g1.yaml @@ -0,0 +1,23 @@ +# Copyright(c) 2023 Jeff Welder (Ellenby Technologies, Inc.) +# SPDX-License-Identifier: Apache-2.0 + +description: Telit ME910G1 Modem + +compatible: "telit,me910g1" + +include: uart-device.yaml + +properties: + mdm-power-gpios: + type: phandle-array + required: true + + mdm-reset-gpios: + type: phandle-array + required: true + + mdm-dtr-gpios: + type: phandle-array + + mdm-ri-gpios: + type: phandle-array diff --git a/dts/bindings/mtd/jedec,jesd216.yaml b/dts/bindings/mtd/jedec,jesd216.yaml index fcbc20ec84d..c55440456c2 100644 --- a/dts/bindings/mtd/jedec,jesd216.yaml +++ b/dts/bindings/mtd/jedec,jesd216.yaml @@ -68,3 +68,16 @@ properties: addressing is require to access the full address range, and automatically puts the device into 4-byte address mode when the device is initialized. + + page-size: + type: int + description: | + Number of bytes in a page from JESD216 BFP DW11 + + This property is only used in the CONFIG_SPI_NOR_SFDP_MINIMAL configuration. + It is ignored if the device is configured to use SFDP data + from the sfdp-bfp property (CONFIG_SPI_NOR_SFDP_DEVICETREE) or + if the SFDP parameters are read from the device at + runtime (CONFIG_SPI_NOR_SFDP_RUNTIME). + + The default value is 256 bytes if the value is not specified. diff --git a/dts/bindings/neural_net/intel,gna.yaml b/dts/bindings/neural_net/intel,gna.yaml deleted file mode 100644 index 9d363fededb..00000000000 --- a/dts/bindings/neural_net/intel,gna.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2021 Intel Corporation -# -# SPDX-License-Identifier: Apache-2.0 - -description: Intel Gaussian Mixture Model and Neural Network Accelerator (GNA) - -compatible: "intel,gna" - -include: [base.yaml] - -properties: - reg: - required: true - - interrupts: - required: true - - interrupt-parent: - required: true diff --git a/dts/bindings/pinctrl/infineon,cat1-pinctrl.yaml b/dts/bindings/pinctrl/infineon,cat1-pinctrl.yaml index 09e089b1baa..2335a08b098 100644 --- a/dts/bindings/pinctrl/infineon,cat1-pinctrl.yaml +++ b/dts/bindings/pinctrl/infineon,cat1-pinctrl.yaml @@ -21,6 +21,7 @@ description: | Pin configuration can also specify the pin properties, for example the 'bias-pull-up' property. Here is a list of the supported standard pin properties: + * bias-high-impedance * bias-pull-up * bias-pull-down * drive-open-drain @@ -105,6 +106,7 @@ child-binding: include: - name: pincfg-node.yaml property-allowlist: + - bias-high-impedance - bias-pull-down - bias-pull-up - drive-push-pull diff --git a/dts/bindings/pinctrl/ite,it8xxx2-pinctrl-func.yaml b/dts/bindings/pinctrl/ite,it8xxx2-pinctrl-func.yaml index 21bdf2b6c5e..4fe47c5ba03 100644 --- a/dts/bindings/pinctrl/ite,it8xxx2-pinctrl-func.yaml +++ b/dts/bindings/pinctrl/ite,it8xxx2-pinctrl-func.yaml @@ -14,6 +14,15 @@ properties: func3-en-mask: type: array + func3-ext: + type: array + description: | + When the alternate setting is configured as func3, in addition to + the setting of func3-gcr, some pins require external setting. + + func3-ext-mask: + type: array + func4-gcr: type: array diff --git a/dts/bindings/pinctrl/nxp,imx-iomuxc-scu.yaml b/dts/bindings/pinctrl/nxp,imx-iomuxc-scu.yaml new file mode 100644 index 00000000000..60dde5ae4c9 --- /dev/null +++ b/dts/bindings/pinctrl/nxp,imx-iomuxc-scu.yaml @@ -0,0 +1,25 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + Use this compatible for i.MX boards on which the + IOMUXC is managed by the SCU. + +compatible: "nxp,imx-iomuxc-scu" + +include: base.yaml + +child-binding: + description: SCFW-based IOMUXC pin mux. + properties: + pinmux: + required: true + type: array + description: | + This is an array of values defining the pin mux selection + with the following format: + + + + pad: Which pad to configure. + mux: Select which signal to route. diff --git a/dts/bindings/pinctrl/nxp,imx8-pinctrl.yaml b/dts/bindings/pinctrl/nxp,imx8-pinctrl.yaml new file mode 100644 index 00000000000..4f0427d5d95 --- /dev/null +++ b/dts/bindings/pinctrl/nxp,imx8-pinctrl.yaml @@ -0,0 +1,17 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: Use this compatible for i.MX8QM/QXP boards. + +compatible: "nxp,imx8-pinctrl" + +include: base.yaml + +child-binding: + description: i.MX8QM/QXP pin controller pin group + child-binding: + description: i.MX8QM/QXP pin controller pin configuration node. + properties: + pinmux: + required: true + type: phandles diff --git a/dts/bindings/pinctrl/nxp,kinetis-pinctrl.yaml b/dts/bindings/pinctrl/nxp,kinetis-pinctrl.yaml index ccc36d4f167..c5b2f5d6020 100644 --- a/dts/bindings/pinctrl/nxp,kinetis-pinctrl.yaml +++ b/dts/bindings/pinctrl/nxp,kinetis-pinctrl.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2022, NXP +# Copyright (c) 2022-2023, NXP # SPDX-License-Identifier: Apache-2.0 description: | @@ -63,7 +63,6 @@ child-binding: 0 DSE_0- low drive strength when pin is configured as output 1 DSE_1- high drive strength when pin is configured as output slew-rate: - required: true type: string enum: - "fast" diff --git a/dts/bindings/pinctrl/renesas,ra-pinctrl.yaml b/dts/bindings/pinctrl/renesas,ra-pinctrl.yaml new file mode 100644 index 00000000000..6a48dedf37e --- /dev/null +++ b/dts/bindings/pinctrl/renesas,ra-pinctrl.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +description: | + Renesas RA series pin controller + +compatible: "renesas,ra-pinctrl" + +include: base.yaml + +child-binding: + description: | + Definitions for a pinctrl state. + child-binding: + + properties: + pinmux: + required: true + type: array + description: | + An array of pins sharing the same group properties. Each + element of the array is an integer constructed from the + pin number and the alternative function of the pin. diff --git a/dts/bindings/pinctrl/renesas,rzt2m-pinctrl.yaml b/dts/bindings/pinctrl/renesas,rzt2m-pinctrl.yaml new file mode 100644 index 00000000000..82016017201 --- /dev/null +++ b/dts/bindings/pinctrl/renesas,rzt2m-pinctrl.yaml @@ -0,0 +1,93 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +description: | + The Renesas RZ/T2M pin controller is a node responsible for controlling + pin function selection and pin properties, such as routing the TX and RX of UART0 + to pin 5 and pin 6 of port 16. + + The node has the 'pinctrl' node label set in your SoC's devicetree, + so you can modify it like this: + + &pinctrl { + /* your modifications go here */ + }; + + All device pin configurations should be placed in child nodes of the + 'pinctrl' node, as shown in this example: + + /* You can put this in places like a board-pinctrl.dtsi file in + * your board directory, or a devicetree overlay in your application. + */ + + /* include pre-defined combinations for the SoC variant used by the board */ + #include + + &pinctrl { + uart0_default: uart0_default { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + }; + + The 'uart0_default' child node encodes the pin configurations for a + particular state of a device; in this case, the default (that is, active) + state. + + As shown, pin configurations are organized in groups within each child node. + Each group can specify a list of pin function selections in the 'pinmux' + property. + + A group can also specify shared pin properties common to all the specified + pins, such as the 'input-enable' property in group 2. + +compatible: "renesas,rzt2m-pinctrl" + +include: base.yaml + +child-binding: + description: | + Definitions for a pinctrl state. + child-binding: + + include: + - name: pincfg-node.yaml + property-allowlist: + - input-enable + - bias-pull-up + - bias-pull-down + - bias-high-impedance + - input-schmitt-enable + + properties: + pinmux: + required: true + type: array + description: | + An array of pins sharing the same group properties. Each + element of the array is an integer constructed from the + pin number and the alternative function of the pin. + drive-strength: + type: string + enum: + - "low" + - "middle" + - "high" + - "ultrahigh" + default: "low" + description: | + The drive strength of a pin, relative to full-driver strength. + The default value is "low", which is the reset value. + slew-rate: + type: string + enum: + - "slow" + - "fast" + default: "slow" + description: | + Select slew rate for a pin. The default is slow, which is the reset value. diff --git a/dts/bindings/power-domain/power-domain-gpio-monitor.yaml b/dts/bindings/power-domain/power-domain-gpio-monitor.yaml new file mode 100644 index 00000000000..d7dfd8779b7 --- /dev/null +++ b/dts/bindings/power-domain/power-domain-gpio-monitor.yaml @@ -0,0 +1,22 @@ +# Copyright (c) 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +description: | + Simple monitorig power domain + + This power domain monitors the state of a GPIO pin to detect whether a power + rail is on/off. Therefore, performing resume/suspend on power domain won't + change physical state of power rails and those action won't be triggerd on + child nodes. Additionally, due to the asynchronous nature of monitoring a + pending transaction won't be interrupted by power state change. + +compatible: "power-domain-gpio-monitor" + +include: power-domain.yaml + +properties: + gpios: + type: phandle-array + required: true + description: | + GPIO to use to sense if rail is powered on. diff --git a/dts/bindings/power/atmel,sam-supc.yaml b/dts/bindings/power/atmel,sam-supc.yaml new file mode 100644 index 00000000000..fdba03f87cf --- /dev/null +++ b/dts/bindings/power/atmel,sam-supc.yaml @@ -0,0 +1,47 @@ +# Copyright (c) 2023 Bjarki Arge Andreasen +# SPDX-License-Identifier: Apache-2.0 + +description: | + Atmel SAM SUPC (Supply-Controller) controller + + The supply controller manages the voltage reference, power supply and supply + monitoring of the device. It have a special feature that it can wake-up the + device from a low-power state using special peripherals as wake-up sources. + + The dedicated peripherals that can wake-up the core supply domain are: RTC, + RTT, Supply Monitor and GPIOs. In the first three peripherals it is necessary + inform the wakeup-source-id property on their respective nodes. + + rtc: rtc@xxx { + ... + wakeup-source-id = <&supc SUPC_WAKEUP_SOURCE_RTC>; + ... + }; + + The special peripheral will wake-up the device only when the standard property + wakeup-source is defined, e.g.: + + &rtc { + ... + wakeup-source; + ... + }; + + The SUPC wakeup source ids that can be enabled are defined in the + zephyr/include/zephyr/dt-bindings/power/atmel_sam_supc.h header file. + +compatible: "atmel,sam-supc" + +include: + - name: base.yaml + +properties: + reg: + required: true + + "#wakeup-source-id-cells": + type: int + const: 1 + +wakeup-source-id-cells: + - wakeup-source-id diff --git a/dts/bindings/pwm/nxp,kinetis-ftm-pwm.yaml b/dts/bindings/pwm/nxp,kinetis-ftm-pwm.yaml index 5dd363efb05..fd195c12086 100644 --- a/dts/bindings/pwm/nxp,kinetis-ftm-pwm.yaml +++ b/dts/bindings/pwm/nxp,kinetis-ftm-pwm.yaml @@ -12,7 +12,6 @@ properties: const: 3 pinctrl-0: - type: phandles required: true pwm-cells: diff --git a/dts/bindings/pwm/nxp,kinetis-tpm.yaml b/dts/bindings/pwm/nxp,kinetis-tpm.yaml index 1035b5242b6..7c710a5e39c 100644 --- a/dts/bindings/pwm/nxp,kinetis-tpm.yaml +++ b/dts/bindings/pwm/nxp,kinetis-tpm.yaml @@ -15,7 +15,6 @@ properties: required: true pinctrl-0: - type: phandles required: true "#pwm-cells": diff --git a/dts/bindings/pwm/nxp,s32-emios-pwm.yaml b/dts/bindings/pwm/nxp,s32-emios-pwm.yaml new file mode 100644 index 00000000000..37de69e39e1 --- /dev/null +++ b/dts/bindings/pwm/nxp,s32-emios-pwm.yaml @@ -0,0 +1,185 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + NXP S32 eMIOS PWM node for S32 SoCs. Each channel in eMIOS can be configured + to use for PWM operation. There are several PWM modes supported by this module, + some modes only support on channels that have internal counter, some modes + require to use a reference timebase from a master bus. + + For example to configuring eMIOS instance 0 with: + - Channel 0 for mode OPWFMB + - Channel 1 for mode OPWMB + - Channel 2 for mode OPWMCB with deadtime inserted at leading edge + - Channel 3 for mode SAIC, use internal timebase with input filter = 2 eMIOS clock + + emios0_pwm: pwm { + pwm_0 { + channel = <0>; + pwm-mode = "OPWFMB"; + prescaler = <8>; + period = <65534>; + duty-cycle = <32768>; + polarity = "ACTIVE_HIGH"; + }; + + pwm_1 { + channel = <1>; + master-bus = <&emios1_bus_a>; + pwm-mode = "OPWMB"; + duty-cycle = <32768>; + phase-shift = <100>; + polarity = "ACTIVE_LOW"; + }; + + pwm_2 { + channel = <2>; + master-bus = <&emios1_bus_b>; + pwm-mode = "OPWMCB_LEAD_EDGE"; + duty-cycle = <32768>; + dead-time = <100>; + polarity = "ACTIVE_LOW"; + }; + + pwm_3 { + channel = <3>; + pwm-mode = "SAIC"; + prescaler = <8>; + input-filter = <2>; + }; + }; + + OPWMB and OPWMCB modes use reference timebase, the master bus is chosen over + phandle 'master-bus'. For OPWMB mode, PWM's period is master bus's period and + is 2 * master bus's period - 2 for OPWMCB mode. Please notice that the devicetree + node for master bus should be enabled and configured for using, please see + 'nxp,s32-emios' bindings. + +compatible: "nxp,s32-emios-pwm" + +include: [pwm-controller.yaml, base.yaml, pinctrl-device.yaml] + +properties: + pinctrl-0: + required: true + + pinctrl-names: + required: true + + "#pwm-cells": + const: 3 + +pwm-cells: + - channel + # Period in terms of nanoseconds + - period + - flags + +child-binding: + description: | + eMIOS PWM channel configuration. + + properties: + channel: + type: int + required: true + description: eMIOS PWM channel + + master-bus: + type: phandle + description: | + A phandle to master-bus node that will be used as external timebase + for current channel, this can be bypassed if internal counter is used + for PWM operation. A master bus must be used exclusively, such as if + is used as a timebase for a channel in SAIC mode, do not use that + master bus as a timebase for generate PWM pulse. + + pwm-mode: + type: string + required: true + description: | + Select PWM mode: + - OPWFMB: provides waveforms with variable duty cycle and frequency, + this mode uses internal counter. + + - OPWMB: generate pulses with programmable leading and trailing + edge placement. The period is determined by period of + an external counter driven in MCB Up Mode. Changing PWM period + at runtime will impact to all channels share the same timebase. + The new period and cycle take effect in next period boundary. + + - OPWMCB: generates a center aligned PWM with dead time insertion to the + leading or trailing edge. The period is determined by period of + an external counter driven in MCB Up Down Mode. Changing PWM period + at runtime will impact to all channels share the same timebase, + The new period and cycle take effect in next period boundary. + + - SAIC: single action input capture mode, the eMIOS captures events as soon as + they occur. The value of latest captured event is stored and can be read + by software. + enum: + - "OPWFMB" + - "OPWMB" + - "OPWMCB_TRAIL_EDGE" + - "OPWMCB_LEAD_EDGE" + - "SAIC" + + polarity: + type: string + description: | + Output polarity for PWM channel. + enum: + - "ACTIVE_LOW" + - "ACTIVE_HIGH" + + duty-cycle: + type: int + description: | + Duty-cycle (in ticks) for PWM channel at boot time. + + period: + type: int + description: | + Period (in ticks) for OPWFMB at boot time. Period for the rest + of PWM mode depends on period's master bus. Must be in range [2 ... 65535]. + + freeze: + type: boolean + description: Freeze individual internal counter when the chip enters Debug mode. + + prescaler-src: + type: string + default: "PRESCALED_CLOCK" + description: | + Select clock source for internal counter prescaler. + enum: + - "PRESCALED_CLOCK" # Clock source = eMIOS clock / (global prescaler) + - "MODULE_CLOCK" # Clock source = eMIOS clock + + prescaler: + type: int + description: | + The clock divider for internal counter prescaler. + enum: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] + + dead-time: + type: int + default: 0 + description: | + Dead time (in ticks) for PWM channel in OPWMCB mode. + + phase-shift: + type: int + default: 0 + description: | + Phase Shift (in ticks) for PWM channel in OPWMB mode. + + input-filter: + type: int + default: 0 + enum: [0, 2, 4, 8, 16] + description: | + Select the minimim input pulse width, in filter clock cycles that can pass + through the input filter. The filter latency - the difference in time between + the input and the response is three clock edges. Default 0 means the filter + is bypassed. The clock source for programmable input filter is eMIOS clock. diff --git a/dts/bindings/pwm/st,stm32-pwm.yaml b/dts/bindings/pwm/st,stm32-pwm.yaml index 26d758ec7af..cf61c257971 100644 --- a/dts/bindings/pwm/st,stm32-pwm.yaml +++ b/dts/bindings/pwm/st,stm32-pwm.yaml @@ -11,6 +11,14 @@ properties: pinctrl-names: required: true + four-channel-capture-support: + type: boolean + description: | + Add support to capture on four channels. This is less accurate than + the default 2 channel support because the counter is reset by + interrupt instead of slave-mode controller. This option can also + be used as alternative for timers that does not support slave mode. + "#pwm-cells": const: 3 description: | diff --git a/dts/bindings/pwm/telink,b91-pwm.yaml b/dts/bindings/pwm/telink,b91-pwm.yaml index 7c96698f0f6..798cfcfb3ca 100644 --- a/dts/bindings/pwm/telink,b91-pwm.yaml +++ b/dts/bindings/pwm/telink,b91-pwm.yaml @@ -4,14 +4,13 @@ description: Telink B91 PWM -include: [pwm-controller.yaml, base.yaml] +include: [pwm-controller.yaml, pinctrl-device.yaml, base.yaml] compatible: "telink,b91-pwm" properties: pinctrl-0: - type: phandles required: true clock-frequency: diff --git a/dts/bindings/regulator/maxim,max20335-regulator.yaml b/dts/bindings/regulator/maxim,max20335-regulator.yaml new file mode 100644 index 00000000000..44086e0c4fa --- /dev/null +++ b/dts/bindings/regulator/maxim,max20335-regulator.yaml @@ -0,0 +1,49 @@ +# Copyright (c), 2023 Grinn +# SPDX -License-Identifier: Apache-2.0 + +description: | + Maxim MAX20335 PMIC + + The PMIC has two buck converters and three LDOs. All need to be defined as + children nodes, strictly following the BUCK1..2, LDO1..3 node names. For + example: + + pmic@28 { + reg = <0x28>; + ... + regulators { + compatible = maxim,max20335-regulator"; + + BUCK1 { + /* all properties for BUCK1 */ + }; + BUCK2 { + /* all properties for BUCK2 */ + }; + LDO1 { + /* all properties for LDO1 */ + }; + LDO2 { + /* all properties for LDO2 */ + }; + LDO3 { + /* all properties for LDO3 */ + }; + }; + }; + +compatible: "maxim,max20335-regulator" + +include: base.yaml + +child-binding: + include: + - name: regulator.yaml + property-allowlist: + - regulator-always-on + - regulator-boot-on + - regulator-max-microamp + - regulator-min-microvolt + - regulator-max-microvolt + - regulator-allowed-modes + - regulator-initial-mode diff --git a/dts/bindings/regulator/nordic,npm1300-regulator.yaml b/dts/bindings/regulator/nordic,npm1300-regulator.yaml index 987a3b522e1..c5364a49fe0 100644 --- a/dts/bindings/regulator/nordic,npm1300-regulator.yaml +++ b/dts/bindings/regulator/nordic,npm1300-regulator.yaml @@ -60,6 +60,8 @@ child-binding: - regulator-initial-mode - regulator-min-microamp - regulator-max-microamp + - startup-delay-us + - off-on-delay-us properties: retention-microvolt: @@ -83,3 +85,13 @@ child-binding: type: phandle-array description: | Retention mode controlled by specified regulator GPIO pin. + + soft-start-microamp: + type: int + enum: + - 10000 + - 20000 + - 35000 + - 50000 + description: | + Soft start current limit in microamps. diff --git a/dts/bindings/regulator/nxp,pca9420.yaml b/dts/bindings/regulator/nxp,pca9420.yaml index 1f881137601..2e4584d0a67 100644 --- a/dts/bindings/regulator/nxp,pca9420.yaml +++ b/dts/bindings/regulator/nxp,pca9420.yaml @@ -63,6 +63,18 @@ properties: To disable current limit, set property to zero. Defaults to 425mA, the IC default value. + nxp,asys-uvlo-sel-millivolt: + type: int + default: 2700 + enum: + - 2400 + - 2500 + - 2600 + - 2700 + description: | + ASYS UVLO (under voltage lock out) threshold, in millivolts. Defaults to + 2700mV to match the IC default value. + child-binding: include: - name: regulator.yaml diff --git a/dts/bindings/regulator/nxp,vref.yaml b/dts/bindings/regulator/nxp,vref.yaml new file mode 100644 index 00000000000..e3466ad29d5 --- /dev/null +++ b/dts/bindings/regulator/nxp,vref.yaml @@ -0,0 +1,41 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP VREF SOC peripheral + +compatible: "nxp,vref" + +include: + - name: base.yaml + - name: regulator.yaml + property-allowlist: + - regulator-name + - regulator-init-microvolt + - regulator-min-microvolt + - regulator-max-microvolt + - regulator-initial-mode + - regulator-allowed-modes + +properties: + reg: + required: true + + nxp,ground-select: + type: string + enum: + - "VREFL3V" # 0 + - "VSSA" # 1 + + nxp,buffer-startup-delay-us: + type: int + required: true + description: | + Buffer startup delay as specified in the + appropriate device data sheet, in microseconds. + + nxp,bandgap-startup-time-us: + type: int + required: true + description: | + Maximum bandgap startup time as specified in the + appropriate device data sheet, in microseconds. diff --git a/dts/bindings/regulator/regulator-fixed.yaml b/dts/bindings/regulator/regulator-fixed.yaml index 1033d333f08..4f3236d8c6c 100644 --- a/dts/bindings/regulator/regulator-fixed.yaml +++ b/dts/bindings/regulator/regulator-fixed.yaml @@ -13,6 +13,8 @@ include: - regulator-always-on - regulator-min-microvolt - regulator-max-microvolt + - startup-delay-us + - off-on-delay-us compatible: "regulator-fixed" @@ -29,13 +31,3 @@ properties: provide the GPIO polarity and open-drain status in the phandle selector. The Linux enable-active-high and gpio-open-drain properties are not valid for Zephyr devicetree files. - - startup-delay-us: - type: int - default: 0 - description: Startup time, in microseconds - - off-on-delay-us: - type: int - default: 0 - description: Off delay time, in microseconds diff --git a/dts/bindings/regulator/regulator-gpio.yaml b/dts/bindings/regulator/regulator-gpio.yaml index aa7aeb44eee..15c419a0043 100644 --- a/dts/bindings/regulator/regulator-gpio.yaml +++ b/dts/bindings/regulator/regulator-gpio.yaml @@ -34,6 +34,7 @@ include: - regulator-max-microvolt - regulator-always-on - regulator-boot-on + - startup-delay-us compatible: "regulator-gpio" @@ -70,7 +71,3 @@ properties: Example: enable-gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>; - - startup-delay-us: - type: int - description: startup time in microseconds diff --git a/dts/bindings/regulator/regulator.yaml b/dts/bindings/regulator/regulator.yaml index 16a21511ef9..167355d9224 100644 --- a/dts/bindings/regulator/regulator.yaml +++ b/dts/bindings/regulator/regulator.yaml @@ -147,7 +147,7 @@ properties: type: int description: | Set over current error limit. This is a limit where part of the hardware - propably is malfunctional and damage prevention is requested. Zero can be + probably is malfunctional and damage prevention is requested. Zero can be passed to disable error detection and value '1' indicates that detection should be enabled but limit setting can be omitted. @@ -172,7 +172,7 @@ properties: type: int description: | Set over voltage error limit. This is a limit where part of the hardware - propably is malfunctional and damage prevention is requested Zero can be + probably is malfunctional and damage prevention is requested Zero can be passed to disable error detection and value '1' indicates that detection should be enabled but limit setting can be omitted. Limit is given as microvolt offset from voltage set to regulator. @@ -200,7 +200,7 @@ properties: type: int description: | Set under voltage error limit. This is a limit where part of the hardware - propably is malfunctional and damage prevention is requested Zero can be + probably is malfunctional and damage prevention is requested Zero can be passed to disable error detection and value '1' indicates that detection should be enabled but limit setting can be omitted. Limit is given as microvolt offset from voltage set to regulator. @@ -227,7 +227,7 @@ properties: type: int description: | Set over temperature error limit. This is a limit where part of the - hardware propably is malfunctional and damage prevention is requested Zero + hardware probably is malfunctional and damage prevention is requested Zero can be passed to disable error detection and value '1' indicates that detection should be enabled but limit setting can be omitted. @@ -256,3 +256,11 @@ properties: description: | Maximum difference between current and target voltages that can be changed safely in a single step. + + startup-delay-us: + type: int + description: Startup time, in microseconds + + off-on-delay-us: + type: int + description: Off to on delay time, in microseconds diff --git a/dts/bindings/reset/aspeed,ast10x0-reset.yaml b/dts/bindings/reset/aspeed,ast10x0-reset.yaml index a6d7a14ecce..b4864cb5594 100644 --- a/dts/bindings/reset/aspeed,ast10x0-reset.yaml +++ b/dts/bindings/reset/aspeed,ast10x0-reset.yaml @@ -11,5 +11,5 @@ properties: "#reset-cells": const: 1 -clock-cells: - - reset_id +reset-cells: + - id diff --git a/dts/bindings/riscv/riscv,cpus.yaml b/dts/bindings/riscv/riscv,cpus.yaml index 961b54ca82d..883146d76b2 100644 --- a/dts/bindings/riscv/riscv,cpus.yaml +++ b/dts/bindings/riscv/riscv,cpus.yaml @@ -17,10 +17,3 @@ properties: description: RISC-V instruction set architecture required: true type: string - enum: - - rv32emc - - rv32imac - - rv32imafc - - rv32imafcb - - rv64imac - - rv64imafdc diff --git a/dts/bindings/rtc/ambiq,am1805.yaml b/dts/bindings/rtc/ambiq,am1805.yaml new file mode 100644 index 00000000000..be807778f2c --- /dev/null +++ b/dts/bindings/rtc/ambiq,am1805.yaml @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2023 Linumiz +# Author: Sri Surya + +description: AMBIQ AM1805 RTC + +compatible: "ambiq,am1805" + +include: + - name: rtc-device.yaml + - name: i2c-device.yaml + +properties: + reg: + required: true + + am1805-gpios: + type: phandle-array + description: | + GPIO connected to the AM1805 INT1 interrupt output. This signal is open-drain, active low. diff --git a/dts/bindings/rtc/atmel,sam-rtc.yaml b/dts/bindings/rtc/atmel,sam-rtc.yaml new file mode 100644 index 00000000000..7e787ebaf10 --- /dev/null +++ b/dts/bindings/rtc/atmel,sam-rtc.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2023 Bjarki Arge Andreasen +# SPDX-License-Identifier: Apache-2.0 + +description: Atmel SAM family RTC device + +compatible: "atmel,sam-rtc" + +include: rtc-device.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + clocks: + required: true diff --git a/dts/bindings/rtc/maxim,ds1307.yaml b/dts/bindings/rtc/maxim,ds1307.yaml new file mode 100644 index 00000000000..fc81e803cb4 --- /dev/null +++ b/dts/bindings/rtc/maxim,ds1307.yaml @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2023 Arunmani Alagarsamy +# Author: Arunmani Alagarsamy + +description: Maxim DS1307 RTC + +compatible: "maxim,ds1307" + +include: + - name: rtc-device.yaml + - name: i2c-device.yaml diff --git a/dts/bindings/rtc/nxp,kinetis-pit.yaml b/dts/bindings/rtc/nxp,kinetis-pit.yaml index 6d2f478ecb0..ad3ee44ab4c 100644 --- a/dts/bindings/rtc/nxp,kinetis-pit.yaml +++ b/dts/bindings/rtc/nxp,kinetis-pit.yaml @@ -1,4 +1,4 @@ -# Copyright 2020 NXP +# Copyright 2020,2023 NXP # SPDX-License-Identifier: Apache-2.0 description: NXP MCUX Periodic Interrupt Timer (PIT) @@ -11,6 +11,9 @@ properties: reg: required: true + clocks: + required: true + pit-channel: type: int required: true @@ -20,3 +23,8 @@ properties: type: int required: true description: pit default period in us + + max-load-value: + type: int + required: true + description: maximum load value supported diff --git a/dts/bindings/rtc/renesas,smartbond-rtc.yaml b/dts/bindings/rtc/renesas,smartbond-rtc.yaml new file mode 100644 index 00000000000..afe21aef79b --- /dev/null +++ b/dts/bindings/rtc/renesas,smartbond-rtc.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2023 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas SmartBond(tm) RTC node + +compatible: "renesas,smartbond-rtc" + +include: rtc-device.yaml + +properties: + reg: + required: true + + interrupts: + required: true diff --git a/dts/bindings/sd/zephyr,mmc-disk.yaml b/dts/bindings/sd/zephyr,mmc-disk.yaml index a5167721686..f702b341e1a 100644 --- a/dts/bindings/sd/zephyr,mmc-disk.yaml +++ b/dts/bindings/sd/zephyr,mmc-disk.yaml @@ -7,3 +7,15 @@ description: | compatible: "zephyr,mmc-disk" include: [sd-device.yaml] + +properties: + bus-width: + type: int + default: 8 + description: | + Indicates the way the MMC device is connected to the bus. + Defaults to the maximum possible number of bus lines. + enum: + - 1 + - 4 + - 8 diff --git a/dts/bindings/sdhc/atmel,sam-hsmci.yaml b/dts/bindings/sdhc/atmel,sam-hsmci.yaml new file mode 100644 index 00000000000..171f8774246 --- /dev/null +++ b/dts/bindings/sdhc/atmel,sam-hsmci.yaml @@ -0,0 +1,24 @@ +# Copyright 2023, Nikhef +# SPDX-License-Identifier: Apache-2.0 + +description: ATMEL (Microchip) SAM HSMCI SD host controller + +compatible: "atmel,sam-hsmci" + +include: [sdhc.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + pinctrl-0: + required: true + + pinctrl-names: + required: true + + clocks: + required: true + + cd-gpios: + type: phandle-array diff --git a/dts/bindings/sdhc/infineon,cat1-sdhc-sdio.yaml b/dts/bindings/sdhc/infineon,cat1-sdhc-sdio.yaml new file mode 100644 index 00000000000..8bb1071b02b --- /dev/null +++ b/dts/bindings/sdhc/infineon,cat1-sdhc-sdio.yaml @@ -0,0 +1,20 @@ +# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +description: Infineon CAT1 SDHC/SDIO controller + +compatible: "infineon,cat1-sdhc-sdio" + +include: [sdhc.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + pinctrl-0: + required: true + + pinctrl-names: + required: true diff --git a/dts/bindings/sdhc/intel,emmc-host.yaml b/dts/bindings/sdhc/intel,emmc-host.yaml new file mode 100644 index 00000000000..5464b3d5ca1 --- /dev/null +++ b/dts/bindings/sdhc/intel,emmc-host.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: eMMC host controller + +compatible: "intel,emmc-host" + +include: [sdhc.yaml, pcie-device.yaml] diff --git a/dts/bindings/sensor/adi,adltc2990.yaml b/dts/bindings/sensor/adi,adltc2990.yaml new file mode 100644 index 00000000000..443221aa66d --- /dev/null +++ b/dts/bindings/sensor/adi,adltc2990.yaml @@ -0,0 +1,86 @@ +# Copyright (c) 2023 Carl Zeiss Meditec AG +# SPDX-License-Identifier: Apache-2.0 + + +description: ADLTC2990 Quad I2C Voltage, Current and Temperature Monitor + +compatible: "adi,adltc2990" + +include: [sensor-device.yaml, i2c-device.yaml] + +properties: + temperature-format: + type: int + description: | + Define the temperature format. As per the datasheet, + b7 Temperature Format Temperature Reported In; Celsius = 0 (Default), Kelvin = 1 + default: 0 + enum: + - 0 + - 1 + + acquistion-format: + type: int + description: | + Define the acquisition format. As per the datasheet, + b6 Repeat/Single Repeated Acquisition = 0 (Default), Single Acquisition = 1 + default: 0 + enum: + - 0 + - 1 + + measurement-mode: + type: array + description: | + An array of two integers for configuring the chip measurement mode. + + The first integer defines the bits 2..0 in the control register. In all + cases the internal temperature and supply voltage are measured. In + addition the following input measurements are enabled per mode: + As per the datasheet, + ------------------------------------------- + b[2:0] | Mode [2:0] | Mode Description + 0 | 0 0 0 | V1, V2, TR2 (Default) + 1 | 0 0 1 | V1 – V2, TR2 + 2 | 0 1 0 | V1 – V2, V3, V4 + 3 | 0 1 1 | TR1, V3, V4 + 4 | 1 0 0 | TR1, V3 – V4 + 5 | 1 0 1 | TR1, TR2 + 6 | 1 1 0 | V1 – V2, V3 – V4 + 7 | 1 1 1 | V1, V2, V3, V4 + ------------------------------------------- + The second integer defines the bits 4..3 in the control register. This + allows a subset of the measurements to be enabled: + As Per the Datasheet, + ------------------------------------------------------------ + b[4:3] | Mode [4:3] | Mode Description + 0 | 0 0 | Internal Temperature Only (Default) + 1 | 0 1 | TR1, V1 or V1 – V2 Only per Mode [2:0] + 2 | 1 0 | TR2, V3 or V3 – V4 Only per Mode [2:0] + 3 | 1 1 | All Measurements per Mode [2:0] + ------------------------------------------------------------ + default: [0, 0] + + pins-v1-v2-current-resistor: + type: int + description: Define the resistor to be used for measuring current in microohms + + pin-v1-voltage-divider-resistors: + type: array + description: Define the resistor to be used for measuring Vout in milliohms + + pin-v2-voltage-divider-resistors: + type: array + description: Define the resistor to be used for measuring Vout in milliohms + + pins-v3-v4-current-resistor: + type: int + description: Define the resistor to be used for measuring current in microohms + + pin-v3-voltage-divider-resistors: + type: array + description: Define the resistor to be used for measuring Vout in milliohms + + pin-v4-voltage-divider-resistors: + type: array + description: Define the resistor to be used for measuring Vout in milliohms diff --git a/dts/bindings/sensor/adi,adxl367-common.yaml b/dts/bindings/sensor/adi,adxl367-common.yaml new file mode 100644 index 00000000000..722d13d92e0 --- /dev/null +++ b/dts/bindings/sensor/adi,adxl367-common.yaml @@ -0,0 +1,31 @@ +# Copyright (c) 2023 Analog Devices Inc. +# SPDX-License-Identifier: Apache-2.0 + +include: sensor-device.yaml + +properties: + odr: + type: int + default: 0 + description: | + Accelerometer sampling frequency (ODR). Default is power on reset value. + 0 # 12.5Hz + 1 # 25Hz + 2 # 50Hz + 3 # 100Hz + 4 # 200Hz + 5 # 400Hz + enum: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + + int1-gpios: + type: phandle-array + description: | + The INT1 signal defaults to active high as produced by the + sensor. The property value should ensure the flags properly + describe the signal that is presented to the driver. diff --git a/dts/bindings/sensor/adi,adxl367-i2c.yaml b/dts/bindings/sensor/adi,adxl367-i2c.yaml new file mode 100644 index 00000000000..faab9e577b9 --- /dev/null +++ b/dts/bindings/sensor/adi,adxl367-i2c.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 Analog Devices Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: ADXL367 3-axis nanopower accelerometer, accessed through I2C bus + +compatible: "adi,adxl367" + +include: ["i2c-device.yaml", "adi,adxl367-common.yaml"] diff --git a/dts/bindings/sensor/adi,adxl367-spi.yaml b/dts/bindings/sensor/adi,adxl367-spi.yaml new file mode 100644 index 00000000000..86d825f781c --- /dev/null +++ b/dts/bindings/sensor/adi,adxl367-spi.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 Analog Devices Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: ADXL367 3-axis nanopower accelerometer, accessed through SPI bus + +compatible: "adi,adxl367" + +include: ["spi-device.yaml", "adi,adxl367-common.yaml"] diff --git a/dts/bindings/sensor/adi,adxl372-common.yaml b/dts/bindings/sensor/adi,adxl372-common.yaml index 6c666dce8a9..547337fc70a 100644 --- a/dts/bindings/sensor/adi,adxl372-common.yaml +++ b/dts/bindings/sensor/adi,adxl372-common.yaml @@ -56,3 +56,10 @@ properties: - 2 - 3 - 4 + + int1-gpios: + type: phandle-array + description: | + The INT1 signal defaults to active high as produced by the + sensor. The property value should ensure the flags properly + describe the signal that is presented to the driver. diff --git a/dts/bindings/sensor/adi,adxl372-i2c.yaml b/dts/bindings/sensor/adi,adxl372-i2c.yaml index 2da0abcac77..1e732b1f9d4 100644 --- a/dts/bindings/sensor/adi,adxl372-i2c.yaml +++ b/dts/bindings/sensor/adi,adxl372-i2c.yaml @@ -1,16 +1,8 @@ # Copyright (c) 2018 Analog Devices Inc. # SPDX-License-Identifier: Apache-2.0 -description: ADXL372 3-axis high-g I2C/SPI accelerometer +description: ADXL372 3-axis high-g accelerometer, accessed through I2C bus compatible: "adi,adxl372" include: ["i2c-device.yaml", "adi,adxl372-common.yaml"] - -properties: - int1-gpios: - type: phandle-array - description: | - The INT1 signal defaults to active high as produced by the - sensor. The property value should ensure the flags properly - describe the signal that is presented to the driver. diff --git a/dts/bindings/sensor/adi,adxl372-spi.yaml b/dts/bindings/sensor/adi,adxl372-spi.yaml index 7d6863c3118..2cb4e674522 100644 --- a/dts/bindings/sensor/adi,adxl372-spi.yaml +++ b/dts/bindings/sensor/adi,adxl372-spi.yaml @@ -7,11 +7,3 @@ description: ADXL372 3-axis high-g accelerometer, accessed through SPI bus compatible: "adi,adxl372" include: ["spi-device.yaml", "adi,adxl372-common.yaml"] - -properties: - int1-gpios: - type: phandle-array - description: | - The INT1 signal defaults to active high as produced by the - sensor. The property value should ensure the flags properly - describe the signal that is presented to the driver. diff --git a/dts/bindings/sensor/amd,sb-tsi.yaml b/dts/bindings/sensor/amd,sb-tsi.yaml new file mode 100644 index 00000000000..f9204b79db2 --- /dev/null +++ b/dts/bindings/sensor/amd,sb-tsi.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +description: AMD SB Temperature Sensor Interface. + +compatible: "amd,sb-tsi" + +include: [sensor-device.yaml, i2c-device.yaml] diff --git a/dts/bindings/sensor/ams,tsl2540.yaml b/dts/bindings/sensor/ams,tsl2540.yaml new file mode 100644 index 00000000000..e47f8a8e8f0 --- /dev/null +++ b/dts/bindings/sensor/ams,tsl2540.yaml @@ -0,0 +1,34 @@ +# Copyright (c) 2022 T-Mobile USA, Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: | + TSL2540 series ambient light sensor. See datasheet at + https://ams.com/documents/20143/36005/TSL2540_DS000564_4-00.pdf/39728ac4-098c-9eca-b5ca-61d9c6f3a588 + +compatible: "ams,tsl2540" + +include: [sensor-device.yaml, i2c-device.yaml] + +properties: + int-gpios: + type: phandle-array + description: | + Identifies the interrupt pin + + glass-attenuation: + type: int + default: 100000 + description: | + Visible light attenuation. + Integer value for a represenation with 5 decimal points. + This default value (1.00000) is chosen for free open space (no glass). + Example: 1.2 would be 120000 + + glass-ir-attenuation: + type: int + default: 100000 + description: | + Infa-red light attenuation. + Integer value for a represenation with 5 decimal points. + This default value (1.00000) is chosen for free open space (no glass). + Example: 1.2 would be 120000 diff --git a/dts/bindings/sensor/ams,tsl2561.yaml b/dts/bindings/sensor/ams,tsl2561.yaml new file mode 100644 index 00000000000..fbc97a673e8 --- /dev/null +++ b/dts/bindings/sensor/ams,tsl2561.yaml @@ -0,0 +1,28 @@ +# Copyright (c) 2023, Gustavo Silva +# SPDX-License-Identifier: Apache-2.0 + +description: | + OSRAM ams TSL2561 light sensor. + +compatible: "ams,tsl2561" + +include: [sensor-device.yaml, i2c-device.yaml] + +properties: + integration-time: + type: int + default: 402 + description: | + ADC integration time in ms. The default value matches Timing Register's value at power on. + enum: + - 13 + - 101 + - 402 + gain: + type: int + default: 16 + description: | + ADC gain factor. The default value matches Timing Register's value at power on. + enum: + - 1 + - 16 diff --git a/dts/bindings/sensor/bosch,bmi270-i2c.yaml b/dts/bindings/sensor/bosch,bmi270-i2c.yaml index 6a487405585..ca21ba4f3ea 100644 --- a/dts/bindings/sensor/bosch,bmi270-i2c.yaml +++ b/dts/bindings/sensor/bosch,bmi270-i2c.yaml @@ -5,9 +5,3 @@ compatible: "bosch,bmi270" include: [i2c-device.yaml, "bosch,bmi270.yaml"] - -properties: - irq-gpios: - type: phandle-array - description: | - The INT1 and (optional) INT2 signal connections. diff --git a/dts/bindings/sensor/bosch,bmi270.yaml b/dts/bindings/sensor/bosch,bmi270.yaml index 2b50c164e46..8b486f2bcab 100644 --- a/dts/bindings/sensor/bosch,bmi270.yaml +++ b/dts/bindings/sensor/bosch,bmi270.yaml @@ -9,3 +9,9 @@ description: | include: sensor-device.yaml compatible: "bosch,bmi270" + +properties: + irq-gpios: + type: phandle-array + description: | + The INT1 and (optional) INT2 signal connections. diff --git a/dts/bindings/sensor/bosch,bmm150.yaml b/dts/bindings/sensor/bosch,bmm150.yaml index 579999968b5..9b546b81171 100644 --- a/dts/bindings/sensor/bosch,bmm150.yaml +++ b/dts/bindings/sensor/bosch,bmm150.yaml @@ -4,3 +4,10 @@ # Common fields for BMM150 include: sensor-device.yaml + +properties: + drdy-gpios: + type: phandle-array + description: | + This property specifies the connection for data ready pin. + The polarity default is active high when sensor data is ready. diff --git a/dts/bindings/sensor/fintek,f75303.yaml b/dts/bindings/sensor/fintek,f75303.yaml new file mode 100644 index 00000000000..842aa25bd18 --- /dev/null +++ b/dts/bindings/sensor/fintek,f75303.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +description: | + F75303 temperature sensor IC. This device has three temperature + channels - one local (on-chip), and two remote. + +compatible: "fintek,f75303" + +include: [sensor-device.yaml, i2c-device.yaml] diff --git a/dts/bindings/sensor/gss,explorir-m.yaml b/dts/bindings/sensor/gss,explorir-m.yaml new file mode 100644 index 00000000000..62de081c1be --- /dev/null +++ b/dts/bindings/sensor/gss,explorir-m.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023, Vitrolife A/S +# SPDX-License-Identifier: Apache-2.0 + +description: Gas Sensing Solutions CO2 sensor + +compatible: "gss,explorir-m" + +include: [sensor-device.yaml, uart-device.yaml] diff --git a/dts/bindings/sensor/istentek,ist8310.yaml b/dts/bindings/sensor/istentek,ist8310.yaml index a31821aa5e8..761278d24bb 100644 --- a/dts/bindings/sensor/istentek,ist8310.yaml +++ b/dts/bindings/sensor/istentek,ist8310.yaml @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 description: | - Istentek ist8310 Geomagnetic sensor. See more info at: + iSentek ist8310 Geomagnetic sensor. See more info at: https://isentek.com/products_view.php?PID=10&sn=13 compatible: "isentek,ist8310" diff --git a/dts/bindings/sensor/ltrf216a.yaml b/dts/bindings/sensor/ltrf216a.yaml new file mode 100644 index 00000000000..fdbd7304be0 --- /dev/null +++ b/dts/bindings/sensor/ltrf216a.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023, Trridonic +# SPDX-License-Identifier: Apache-2.0 + +description: LiteOn F216A ambient light sensor + +compatible: "ltr,f216a" + +include: [sensor-device.yaml, i2c-device.yaml] diff --git a/dts/bindings/sensor/memsic,mc3419.yaml b/dts/bindings/sensor/memsic,mc3419.yaml new file mode 100644 index 00000000000..accb86b667b --- /dev/null +++ b/dts/bindings/sensor/memsic,mc3419.yaml @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2023 Linumiz + +description: MC3419 3-axis accel sensor + +compatible: "memsic,mc3419" + +include: [sensor-device.yaml, i2c-device.yaml] + +properties: + int-gpios: + type: phandle-array + description: | + This property specifies the connection for INT, this pin + defaults to active low when sample produce interrupt. + + int-pin2: + type: boolean + description: | + This property is used for interrupt routing.The sensor + has two interrupt pins.By default the interrupt are routed + to interrupt pin 1, by enabled this property interrupt are + routed to interrupt pin 2. diff --git a/dts/bindings/sensor/murata,ncp15wb473.yaml b/dts/bindings/sensor/murata,ncp15wb473.yaml new file mode 100644 index 00000000000..2ea851719dd --- /dev/null +++ b/dts/bindings/sensor/murata,ncp15wb473.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +description: MURATA NCP15WB473 thermistor + +compatible: "murata,ncp15wb473" + +include: ntc-thermistor.yaml diff --git a/dts/bindings/sensor/nordic,npm1300-charger.yaml b/dts/bindings/sensor/nordic,npm1300-charger.yaml index cfb0420ecc9..2885cd0de76 100644 --- a/dts/bindings/sensor/nordic,npm1300-charger.yaml +++ b/dts/bindings/sensor/nordic,npm1300-charger.yaml @@ -114,3 +114,15 @@ properties: type: boolean description: | Disable automatic recharge. + + dietemp-stop-millidegrees: + type: int + description: | + Die temperature halt threshold in milli-degrees. + When die temperature exceeds this threshold, charging will be inhibited. + + dietemp-resume-millidegrees: + type: int + description: | + Die temperature resume threshold in milli-degrees. + When die temperature falls below this threshold, charging will be permitted. diff --git a/dts/bindings/sensor/ntc-thermistor.yaml b/dts/bindings/sensor/ntc-thermistor.yaml index 35fd96bec29..5c7fe3a4654 100644 --- a/dts/bindings/sensor/ntc-thermistor.yaml +++ b/dts/bindings/sensor/ntc-thermistor.yaml @@ -11,11 +11,6 @@ properties: description: | ADC IO channel connected to this NTC thermistor. - r25-ohm: - type: int - description: | - The resistance value of the thermistor at 25 C. - pullup-uv: type: int description: | diff --git a/dts/bindings/sensor/nuvoton,adc-cmp.yaml b/dts/bindings/sensor/nuvoton,adc-cmp.yaml index 769304b25b2..40d0e1b6e0c 100644 --- a/dts/bindings/sensor/nuvoton,adc-cmp.yaml +++ b/dts/bindings/sensor/nuvoton,adc-cmp.yaml @@ -1,6 +1,5 @@ # Copyright (c) 2022 Intel Corporation # SPDX-License-Identifier: Apache-2.0 - description: | This will perform signal comparision with threshold established. @@ -28,3 +27,15 @@ properties: enum: - ADC_CMP_NPCX_GREATER - ADC_CMP_NPCX_LESS_OR_EQUAL + + thr-sel: + type: string + description: | + Determines the register for threshold control and event. + enum: + - ADC_CMP_NPCX_THRCTL1 + - ADC_CMP_NPCX_THRCTL2 + - ADC_CMP_NPCX_THRCTL3 + - ADC_CMP_NPCX_THRCTL4 + - ADC_CMP_NPCX_THRCTL5 + - ADC_CMP_NPCX_THRCTL6 diff --git a/dts/bindings/sensor/renesas,hs300x.yaml b/dts/bindings/sensor/renesas,hs300x.yaml new file mode 100644 index 00000000000..cd24b67da74 --- /dev/null +++ b/dts/bindings/sensor/renesas,hs300x.yaml @@ -0,0 +1,10 @@ +# +# Copyright (c) 2023 Ian Morris +# +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas HS300x humidity and temperature sensor + +compatible: "renesas,hs300x" + +include: [sensor-device.yaml, i2c-device.yaml] diff --git a/dts/bindings/sensor/seeed,hm330x.yaml b/dts/bindings/sensor/seeed,hm330x.yaml new file mode 100644 index 00000000000..0b9e6facbb1 --- /dev/null +++ b/dts/bindings/sensor/seeed,hm330x.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2023 benjamin@zephyrproject.org +# SPDX-License-Identifier: Apache-2.0 + +description: | + Seeed Studio HM330x dust particle sensor + +compatible: "seeed,hm330x" + +include: [sensor-device.yaml, i2c-device.yaml] diff --git a/dts/bindings/sensor/st,iis2dlpc-common.yaml b/dts/bindings/sensor/st,iis2dlpc-common.yaml index 36c258df4b1..997b0b189f0 100644 --- a/dts/bindings/sensor/st,iis2dlpc-common.yaml +++ b/dts/bindings/sensor/st,iis2dlpc-common.yaml @@ -1,6 +1,20 @@ # Copyright (c) 2018 STMicroelectronics # SPDX-License-Identifier: Apache-2.0 +description: | + When setting the odr property in a .dts or .dtsi file you may include + st_iis2dlpc.h and use the macros defined there. + + Example: + #include + + iis2dlpc: iis2dlpc@0 { + ... + + tap-mode = ; + power-mode = ; + }; + include: sensor-device.yaml properties: @@ -16,36 +30,44 @@ properties: drdy-int: type: int default: 1 - enum: - - 1 # drdy is generated from INT1 - - 2 # drdy is generated from INT2 - description: Select DRDY pin number (1 or 2). + enum: [1, 2] + description: | + Select DRDY pin number (1 or 2). This number represents which of the two interrupt pins (INT1 or INT2) the drdy line is attached to. This property is not mandatory and if not present it defaults to 1 which is the configuration at power-up. + - 1 # drdy is generated from INT1 + - 2 # drdy is generated from INT2 + range: type: int default: 2 - description: Range in g. Default is power-up configuration. - enum: + description: | + Range in g. Default is power-up configuration. + - 16 # 16g (1.952 mg/LSB) - 8 # 8g (0.976 mg/LSB) - 4 # 4g (0.488 mg/LSB) - 2 # 2g (0.244 mg/LSB) + enum: [16, 8, 4, 2] + power-mode: type: int default: 0 - description: Specify the sensor power mode. Default is power-up configuration. - enum: - - 0 # Low Power M1 - - 1 # Low Power M2 - - 2 # Low Power M3 - - 3 # Low Power M4 - - 4 # High Performance + description: | + Specify the sensor power mode. Default is power-up configuration. + + - 0 # IIS2DLPC_DT_LP_M1 + - 1 # IIS2DLPC_DT_LP_M2 + - 2 # IIS2DLPC_DT_LP_M3 + - 3 # IIS2DLPC_DT_LP_M4 + - 4 # IIS2DLPC_DT_HP_MODE + + enum: [0, 1, 2, 3, 4] # tap and tap-tap configuration section # All default values are selected to match the power-up values. @@ -54,10 +76,13 @@ properties: tap-mode: type: int default: 0 - description: Tap mode. Default is power-up configuration. - enum: - - 0 # Only Single Tap - - 1 # Single and Double Tap + description: | + Tap mode. Default is power-up configuration. + + - 0 # IIS2DLPC_DT_SINGLE_TAP + - 1 # IIS2DLPC_DT_SINGLE_DOUBLE_TAP + + enum: [0, 1] tap-threshold: type: array diff --git a/dts/bindings/sensor/st,iis2iclx-common.yaml b/dts/bindings/sensor/st,iis2iclx-common.yaml index 9551c274ae1..0a312824c98 100644 --- a/dts/bindings/sensor/st,iis2iclx-common.yaml +++ b/dts/bindings/sensor/st,iis2iclx-common.yaml @@ -1,12 +1,27 @@ # Copyright (c) 2020 STMicroelectronics # SPDX-License-Identifier: Apache-2.0 +description: | + When setting the range, odr properties in a .dts or .dtsi file you may + include st_iis2iclx.h and use the macros defined there. + + Example: + #include + + iis2iclx: iis2iclx@0 { + ... + + range = ; + odr = ; + }; + include: sensor-device.yaml properties: drdy-gpios: type: phandle-array - description: DRDY pin + description: | + DRDY pin This pin defaults to active high when produced by the sensor. The property value should ensure the flags properly describe @@ -15,41 +30,45 @@ properties: int-pin: type: int default: 1 - enum: - - 1 # drdy is generated from INT1 - - 2 # drdy is generated from INT2 - description: Select DRDY pin number (1 or 2). + enum: [1, 2] + description: | + Select DRDY pin number (1 or 2). This number represents which of the two interrupt pins (INT1 or INT2) the drdy line is attached to. This property is not mandatory and if not present it defaults to 1 which is the configuration at power-up. + - 1 # drdy is generated from INT1 + - 2 # drdy is generated from INT2 + range: type: int default: 3 - description: Range in g. Default is power-up configuration. - enum: - - 0 # 500mg (0.015 mg/LSB) - - 1 # 3g (0.122 mg/LSB) - - 2 # 1g (0.031 mg/LSB) - - 3 # 2g (0.061 mg/LSB) + description: | + Range in g. Default is power-up configuration. + + - 0 # IIS2ICLX_DT_FS_500mG (0.015 mg/LSB) + - 1 # IIS2ICLX_DT_FS_3G (0.122 mg/LSB) + - 2 # IIS2ICLX_DT_FS_1G (0.031 mg/LSB) + - 3 # IIS2ICLX_DT_FS_2G (0.061 mg/LSB) + + enum: [0, 1, 2, 3] odr: type: int default: 0 - description: + description: | Specify the default accelerometer output data rate expressed in samples per second (Hz). Default is power-up configuration. - enum: - - 0 # Power-Down - - 1 # 12.5Hz - - 2 # 26Hz - - 3 # 52Hz - - 4 # 104Hz - - 5 # 208Hz - - 6 # 416Hz - - 7 # 833Hz - - 8 # 1660Hz - - 9 # 3330Hz - - 10 # 6660Hz + + - 0 # IIS2ICLX_DT_ODR_OFF + - 1 # IIS2ICLX_DT_ODR_12Hz5 + - 2 # IIS2ICLX_DT_ODR_26H + - 3 # IIS2ICLX_DT_ODR_52Hz + - 4 # IIS2ICLX_DT_ODR_104Hz + - 5 # IIS2ICLX_DT_ODR_208Hz + - 6 # IIS2ICLX_DT_ODR_416Hz + - 7 # IIS2ICLX_DT_ODR_833Hz + + enum: [0, 1, 2, 3, 4, 5, 6, 7] diff --git a/dts/bindings/sensor/st,ism330dhcx-common.yaml b/dts/bindings/sensor/st,ism330dhcx-common.yaml index 93d9be0890e..f00f37c1700 100644 --- a/dts/bindings/sensor/st,ism330dhcx-common.yaml +++ b/dts/bindings/sensor/st,ism330dhcx-common.yaml @@ -1,6 +1,20 @@ # Copyright (c) 2021 STMicroelectronics # SPDX-License-Identifier: Apache-2.0 +description: | + When setting the accel-odr and gyro-odr properties in a .dts or .dtsi file you may include + st_ism330dhcx.h and use the macros defined there. + + Example: + #include + + ism330dhcx: ism330dhcx@0 { + ... + + accel-odr = ; + gyro-odr = ; + }; + include: sensor-device.yaml properties: @@ -27,9 +41,7 @@ properties: (INT1 or INT2) the drdy line is attached to. This property is not mandatory and if not present it defaults to 1 which is the configuration at power-up. - enum: - - 1 - - 2 + enum: [1, 2] accel-odr: type: int @@ -38,30 +50,20 @@ properties: Specify the default accelerometer output data rate expressed in samples per second (Hz). Default is power-up configuration. - Selection - 0 Power-Down - 1 12.5Hz - 2 26Hz - 3 52Hz - 4 104Hz - 5 208Hz - 6 416Hz - 7 833Hz - 8 1660Hz - 9 3330Hz - 10 6660Hz - enum: - - 0 - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - - 7 - - 8 - - 9 - - 10 + - 0 # ISM330DHCX_DT_ODR_OFF + - 1 # ISM330DHCX_DT_ODR_12Hz5 + - 2 # ISM330DHCX_DT_ODR_26H + - 3 # ISM330DHCX_DT_ODR_52Hz + - 4 # ISM330DHCX_DT_ODR_104Hz + - 5 # ISM330DHCX_DT_ODR_208Hz + - 6 # ISM330DHCX_DT_ODR_416Hz + - 7 # ISM330DHCX_DT_ODR_833Hz + - 8 # ISM330DHCX_DT_ODR_1666Hz + - 9 # ISM330DHCX_DT_ODR_3332Hz + - 10 # ISM330DHCX_DT_ODR_6667Hz + - 11 # ISM330DHCX_DT_ODR_1Hz6 + + enum: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] accel-range: type: int @@ -69,16 +71,12 @@ properties: description: | Range in g. Default is power-up configuration. - Selection - 16 16g (0.488 mg/LSB) - 8 8g (0.244 mg/LSB) - 4 4g (0.122 mg/LSB) - 2 2g (0.061 mg/LSB) - enum: - - 16 - - 8 - - 4 - - 2 + - 16 # 16g (0.488 mg/LSB) + - 8 # 8g (0.244 mg/LSB) + - 4 # 4g (0.122 mg/LSB) + - 2 # 2g (0.061 mg/LSB) + + enum: [16, 8, 4, 2] gyro-odr: type: int @@ -87,30 +85,19 @@ properties: Specify the default gyro output data rate expressed in samples per second (Hz). Default is power-up configuration. - Selection - 0 Power-Down - 1 12.5Hz - 2 26Hz - 3 52Hz - 4 104Hz - 5 208Hz - 6 416Hz - 7 833Hz - 8 1660Hz - 9 3330Hz - 10 6660Hz - enum: - - 0 - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - - 7 - - 8 - - 9 - - 10 + - 0 # ISM330DHCX_DT_ODR_OFF + - 1 # ISM330DHCX_DT_ODR_12Hz5 + - 2 # ISM330DHCX_DT_ODR_26H + - 3 # ISM330DHCX_DT_ODR_52Hz + - 4 # ISM330DHCX_DT_ODR_104Hz + - 5 # ISM330DHCX_DT_ODR_208Hz + - 6 # ISM330DHCX_DT_ODR_416Hz + - 7 # ISM330DHCX_DT_ODR_833Hz + - 8 # ISM330DHCX_DT_ODR_1666Hz + - 9 # ISM330DHCX_DT_ODR_3332Hz + - 10 # ISM330DHCX_DT_ODR_6667Hz + + enum: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] gyro-range: type: int @@ -118,15 +105,10 @@ properties: description: | Range in dps. Default is power-up configuration. - Selection - 125 +/- 125dps - 250 +/- 250dps - 500 +/- 500dps - 1000 +/- 1000dps - 2000 +/- 2000dps - enum: - - 125 - - 250 - - 500 - - 1000 - - 2000 + - 125 # +/- 125dps + - 250 # +/- 250dps + - 500 # +/- 500dps + - 1000 # +/- 1000dps + - 2000 # +/- 2000dps + + enum: [125, 250, 500, 1000, 2000] diff --git a/dts/bindings/sensor/st,lis2dh-common.yaml b/dts/bindings/sensor/st,lis2dh-common.yaml index d86960e26d3..351fa0dc97f 100644 --- a/dts/bindings/sensor/st,lis2dh-common.yaml +++ b/dts/bindings/sensor/st,lis2dh-common.yaml @@ -1,6 +1,21 @@ # Copyright (c) 2018 STMicroelectronics # SPDX-License-Identifier: Apache-2.0 +description: | + When setting the int1-gpio-config/int2-gpio-config and anym-mode properties + in a .dts or .dtsi file you may include st_lis2dh.h and use the macros defined there. + + Example: + #include + + lis2dh: lis2dh@0 { + ... + + int1-gpio-config = ; + int2-gpio-config = ; + anym-mode = ; + }; + include: sensor-device.yaml properties: @@ -10,6 +25,40 @@ properties: The INT1 and (optional) INT2 signal connections. These signals are active-high as produced by the sensor. + int1-gpio-config: + type: int + default: 0 + description: | + Select the interrupt configuration for INT1 gpio. + + The default of 0 is the most common situation to avoid multiple interrupts + to be triggered by same event. + + - 0 # LIS2DH_DT_GPIO_INT_EDGE + - 1 # LIS2DH_DT_GPIO_INT_EDGE_RISING + - 2 # LIS2DH_DT_GPIO_INT_EDGE_FALLING + - 3 # LIS2DH_DT_GPIO_INT_LEVEL_HIGH + - 4 # LIS2DH_DT_GPIO_INT_LEVEL_LOW + + enum: [0, 1, 2, 3, 4] + + int2-gpio-config: + type: int + default: 0 + description: | + Select the interrupt configuration for INT2 gpio. + + The default of 0 is the most common situation to avoid multiple interrupts + to be triggered by same event. + + - 0 # LIS2DH_DT_GPIO_INT_EDGE + - 1 # LIS2DH_DT_GPIO_INT_EDGE_RISING + - 2 # LIS2DH_DT_GPIO_INT_EDGE_FALLING + - 3 # LIS2DH_DT_GPIO_INT_LEVEL_HIGH + - 4 # LIS2DH_DT_GPIO_INT_LEVEL_LOW + + enum: [0, 1, 2, 3, 4] + disconnect-sdo-sa0-pull-up: type: boolean description: | @@ -36,14 +85,11 @@ properties: description: | Select the interrupt mode for any movement. - 0 = OR combination of interrupt events - 1 = 6D movement recognition - 2 = AND combination of interrupt events - 3 = 6D position recognition - The default of 0 is the power-on-reset value. - enum: - - 0 - - 1 - - 2 - - 3 + + - 0 # LIS2DH_DT_ANYM_OR_COMBINATION + - 1 # LIS2DH_DT_ANYM_6D_MOVEMENT + - 2 # LIS2DH_DT_ANYM_AND_COMBINATION + - 3 # LIS2DH_DT_ANYM_6D_POSITION + + enum: [0, 1, 2, 3] diff --git a/dts/bindings/sensor/st,lis2ds12-common.yaml b/dts/bindings/sensor/st,lis2ds12-common.yaml index 4a5926c42ad..4ac18b40a55 100644 --- a/dts/bindings/sensor/st,lis2ds12-common.yaml +++ b/dts/bindings/sensor/st,lis2ds12-common.yaml @@ -1,6 +1,20 @@ # Copyright (c) 2021 STMicroelectronics # SPDX-License-Identifier: Apache-2.0 +description: | + When setting the odr and power-mode properties in a .dts or .dtsi file you may include + st_lis2ds12.h and use the macros defined there. + + Example: + #include + + lis2ds12: lis2ds12@0 { + ... + + power-mode = ; + odr = ; + }; + include: sensor-device.yaml properties: @@ -19,23 +33,25 @@ properties: description: | Range in g. Default is power-up configuration. - enum: - 16 # 16g (0.488 mg/LSB) - 8 # 8g (0.244 mg/LSB) - 4 # 4g (0.122 mg/LSB) - 2 # 2g (0.061 mg/LSB) + enum: [16, 8, 4, 2] + power-mode: type: int default: 0 description: | Specify the sensor power mode. Default is power-down mode - enum: - - 0 # Power Down (PD) - - 1 # Low Power (LP) - - 2 # High Resolution (HR) - - 3 # High Frequency (HF) + - 0 # LIS2DS12_DT_POWER_DOWN + - 1 # LIS2DS12_DT_LOW_POWER + - 2 # LIS2DS12_DT_HIGH_RESOLUTION + - 3 # LIS2DS12_DT_HIGH_FREQUENCY + + enum: [0, 1, 2, 3] odr: type: int @@ -43,16 +59,18 @@ properties: description: | Specify the default output data rate expressed in samples per second (Hz). Default is power-down mode - enum: - - 0 # Power-Down - - 1 # 1Hz (available in LP mode only) - - 2 # 12.5Hz (available in LP and HR mode) - - 3 # 25Hz (available in LP and HR mode) - - 4 # 50Hz (available in LP and HR mode) - - 5 # 100Hz (available in LP and HR mode) - - 6 # 200Hz (available in LP and HR mode) - - 7 # 400Hz (available in LP and HR mode) - - 8 # 800Hz (available in LP and HR mode) - - 9 # 1600Hz (available in HF mode only) - - 10 # 3200Hz (available in HF mode only) - - 11 # 6400Hz (available in HF mode only) + + - 0 # LIS2DS12_DT_ODR_OFF + - 1 # LIS2DS12_DT_ODR_1Hz_LP + - 2 # LIS2DS12_DT_ODR_12Hz5 + - 3 # LIS2DS12_DT_ODR_25Hz + - 4 # LIS2DS12_DT_ODR_50Hz + - 5 # LIS2DS12_DT_ODR_100Hz + - 6 # LIS2DS12_DT_ODR_200Hz + - 7 # LIS2DS12_DT_ODR_400Hz + - 8 # LIS2DS12_DT_ODR_800Hz + - 9 # LIS2DS12_DT_ODR_1600Hz + - 10 # LIS2DS12_DT_ODR_3200Hz_HF + - 11 # LIS2DS12_DT_ODR_6400Hz_HF + + enum: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] diff --git a/dts/bindings/sensor/st,lis2dw12-common.yaml b/dts/bindings/sensor/st,lis2dw12-common.yaml index 635e9d9e9d5..0c9f8dcee67 100644 --- a/dts/bindings/sensor/st,lis2dw12-common.yaml +++ b/dts/bindings/sensor/st,lis2dw12-common.yaml @@ -1,6 +1,23 @@ # Copyright (c) 2021 STMicroelectronics # SPDX-License-Identifier: Apache-2.0 +description: | + When setting the odr property in a .dts or .dtsi file you may include + st_lis2dw12.h and use the macros defined there. + + Example: + #include + + lis2dw12: lis2dw12@0 { + ... + + wakeup-duration = ; + ff-threshold = ; + tap-mode = ; + power-mode = ; + bw-filt = ; + }; + include: sensor-device.yaml properties: @@ -16,9 +33,8 @@ properties: int-pin: type: int default: 1 - enum: - - 1 - - 2 + enum: [1, 2] + description: | Select DRDY pin number (1 or 2). @@ -41,11 +57,7 @@ properties: 4 # 4g (0.488 mg/LSB) 2 # 2g (0.244 mg/LSB) - enum: - - 16 - - 8 - - 4 - - 2 + enum: [16, 8, 4, 2] odr: type: int @@ -56,17 +68,7 @@ properties: If 0 selected as the odr, the accelerometer initializes into power off state. - enum: - - 0 - - 1 - - 12 - - 25 - - 50 - - 100 - - 200 - - 400 - - 800 - - 1600 + enum: [0, 1, 12, 25, 50, 100, 200, 400, 800, 1600] bw-filt: type: int @@ -74,16 +76,12 @@ properties: description: | Digital filtering cutoff bandwidth. Default is power-up configuration. - 3 # ODR/20 (HP/LP) - 2 # ODR/10 (HP/LP) - 1 # ODR/ 4 (HP/LP) - 0 # ODR/ 2 (up to ODR = 800 Hz, 400 Hz when ODR = 1600 Hz) + - 0 # LIS2DW12_DT_FILTER_BW_ODR_DIV_2 + - 1 # LIS2DW12_DT_FILTER_BW_ODR_DIV_4 + - 2 # LIS2DW12_DT_FILTER_BW_ODR_DIV_10 + - 3 # LIS2DW12_DT_FILTER_BW_ODR_DIV_20 - enum: - - 3 - - 2 - - 1 - - 0 + enum: [0, 1, 2, 3] power-mode: type: int @@ -91,18 +89,13 @@ properties: description: | Specify the sensor power mode. Default is power-up configuration. - 0 # Low Power M1 - 1 # Low Power M2 - 2 # Low Power M3 - 3 # Low Power M4 - 4 # High Performance + - 0 # LIS2DW12_DT_LP_M1 + - 1 # LIS2DW12_DT_LP_M2 + - 2 # LIS2DW12_DT_LP_M3 + - 3 # LIS2DW12_DT_LP_M4 + - 4 # LIS2DW12_DT_HP_MODE - enum: - - 0 - - 1 - - 2 - - 3 - - 4 + enum: [0, 1, 2, 3, 4] # tap and tap-tap configuration section # All default values are selected to match the power-up values. @@ -114,12 +107,10 @@ properties: description: | Tap mode. Default is power-up configuration. - 0 # Only Single Tap - 1 # Single and Double Tap + - 0 # LIS2DW12_DT_SINGLE_TAP + - 1 # LIS2DW12_DT_SINGLE_DOUBLE_TAP - enum: - - 0 - - 1 + enum: [0, 1] tap-threshold: type: array @@ -228,21 +219,31 @@ properties: than the freefall threshold value for the freefall duration long, then a freefall trigger occurs. This value is 3 bits long. Default value chosen 3 (312 mg) refer to ST DT0100 design tip document. - 0 # ~156mg - 1 # ~219mg - 2 # ~250mg - 3 # ~312mg - 4 # ~344mg - 5 # ~406mg - 6 # ~469mg - 7 # ~500mg - - enum: - - 0 - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - - 7 + + - 0 # LIS2DW12_DT_FF_THRESHOLD_156_mg + - 1 # LIS2DW12_DT_FF_THRESHOLD_219_mg + - 2 # LIS2DW12_DT_FF_THRESHOLD_250_mg + - 3 # LIS2DW12_DT_FF_THRESHOLD_312_mg + - 4 # LIS2DW12_DT_FF_THRESHOLD_344_mg + - 5 # LIS2DW12_DT_FF_THRESHOLD_406_mg + - 6 # LIS2DW12_DT_FF_THRESHOLD_469_mg + - 7 # LIS2DW12_DT_FF_THRESHOLD_500_mg + + enum: [0, 1, 2, 3, 4, 5, 6, 7] + + wakeup-duration: + type: int + default: 0 + description: | + The wakeup duration. Default value is the register reset value. + If the accelerometer readings of the all axes are higher + than the wakeup threshold value for the wakeup duration long, + then a wakeup trigger occurs. This value is 2 bits long in the + register and 1 LSB = 1 * 1/ODR. + + - 0 # LIS2DW12_DT_WAKEUP_1_ODR + - 1 # LIS2DW12_DT_WAKEUP_2_ODR + - 2 # LIS2DW12_DT_WAKEUP_3_ODR + - 3 # LIS2DW12_DT_WAKEUP_4_ODR + + enum: [0, 1, 2, 3] diff --git a/dts/bindings/sensor/st,lps22df-common.yaml b/dts/bindings/sensor/st,lps22df-common.yaml new file mode 100644 index 00000000000..cc3f11c106f --- /dev/null +++ b/dts/bindings/sensor/st,lps22df-common.yaml @@ -0,0 +1,86 @@ +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + When setting the odr, lpf, avg properties in a .dts or .dtsi file + you may include st_lps22df.h and use the macros defined there. + + Example: + #include + + lps22df@5d { + ... + + odr = ; + lpf = ; + avg = ; + }; + +include: sensor-device.yaml + +properties: + drdy-gpios: + type: phandle-array + description: | + DRDY pin + + This pin defaults to active high when produced by the sensor. + The property value should ensure the flags properly describe + the signal that is presented to the driver. + + drdy-pulsed: + type: boolean + description: | + Selects the pulsed mode for data-ready interrupt when enabled, + and the latched mode when disabled. + + odr: + type: int + default: 0 + description: | + Specify the output data rate expressed in samples per second (Hz). + The default is the power-on reset value. + + - 0 # LPS22DF_DT_ODR_POWER_DOWN + - 1 # LPS22DF_DT_ODR_1HZ + - 2 # LPS22DF_DT_ODR_4HZ + - 3 # LPS22DF_DT_ODR_10HZ + - 4 # LPS22DF_DT_ODR_25HZ + - 5 # LPS22DF_DT_ODR_50HZ + - 6 # LPS22DF_DT_ODR_75HZ + - 7 # LPS22DF_DT_ODR_100HZ + - 8 # LPS22DF_DT_ODR_200HZ + + enum: [0, 1, 2, 3, 4, 5, 6, 7, 8] + + lpf: + type: int + default: 0 + description: | + Specify the low pass filter value to be applied to pressure data. + The default is the power-on reset value. + + - 0 # LPS22DF_DT_LP_FILTER_OFF + - 1 # LPS22DF_DT_LP_FILTER_ODR_4 + - 3 # LPS22DF_DT_LP_FILTER_ODR_9 + + enum: [0, 1, 3] + + avg: + type: int + default: 0 + description: | + Specify the average filter value (i.e. number of samples) to be applied + to pressure and temperature data. + The default is the power-on reset value. + + - 0 # LPS22DF_DT_AVG_4_SAMPLES + - 1 # LPS22DF_DT_AVG_8_SAMPLES + - 2 # LPS22DF_DT_AVG_16_SAMPLES + - 3 # LPS22DF_DT_AVG_32_SAMPLES + - 4 # LPS22DF_DT_AVG_64_SAMPLES + - 5 # LPS22DF_DT_AVG_128_SAMPLES + - 6 # LPS22DF_DT_AVG_256_SAMPLES + - 7 # LPS22DF_DT_AVG_512_SAMPLES + + enum: [0, 1, 2, 3, 4, 5, 6, 7] diff --git a/dts/bindings/sensor/st,lps22df-i2c.yaml b/dts/bindings/sensor/st,lps22df-i2c.yaml new file mode 100644 index 00000000000..11074528cf3 --- /dev/null +++ b/dts/bindings/sensor/st,lps22df-i2c.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STMicroelectronics LPS22DF pressure and temperature sensor connected to I2C + bus + +compatible: "st,lps22df" + +include: ["i2c-device.yaml", "st,lps22df-common.yaml"] diff --git a/dts/bindings/sensor/st,lps22df-i3c.yaml b/dts/bindings/sensor/st,lps22df-i3c.yaml new file mode 100644 index 00000000000..6bba397e0be --- /dev/null +++ b/dts/bindings/sensor/st,lps22df-i3c.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STMicroelectronics LPS22DF pressure and temperature sensor connected to I3C + bus + +compatible: "st,lps22df" + +include: ["i3c-device.yaml", "st,lps22df-common.yaml"] diff --git a/dts/bindings/sensor/st,lps22df-spi.yaml b/dts/bindings/sensor/st,lps22df-spi.yaml new file mode 100644 index 00000000000..219738d0e95 --- /dev/null +++ b/dts/bindings/sensor/st,lps22df-spi.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STMicroelectronics LPS22DF pressure and temperature sensor connected to SPI + bus + +compatible: "st,lps22df" + +include: ["spi-device.yaml", "st,lps22df-common.yaml"] diff --git a/dts/bindings/sensor/st,lps22hh-common.yaml b/dts/bindings/sensor/st,lps22hh-common.yaml index a704eac46ae..eeeffe25f96 100644 --- a/dts/bindings/sensor/st,lps22hh-common.yaml +++ b/dts/bindings/sensor/st,lps22hh-common.yaml @@ -1,6 +1,19 @@ # Copyright (c) 2021 STMicroelectronics # SPDX-License-Identifier: Apache-2.0 +description: | + When setting the odr property in a .dts or .dtsi file you may include + st_lps22hh.h and use the macros defined there. + + Example: + #include + + lps22hh: lps22hh@0 { + ... + + odr = ; + }; + include: sensor-device.yaml properties: @@ -19,12 +32,14 @@ properties: description: | Specify the default output data rate expressed in samples per second (Hz). The default is the power-on reset value. - enum: - - 0 # Power-Down - - 1 # 1Hz - - 2 # 10Hz - - 3 # 25Hz - - 4 # 50Hz - - 5 # 75Hz - - 6 # 100Hz - - 7 # 200Hz + + - 0 # LPS22HH_DT_ODR_POWER_DOWN + - 1 # LPS22HH_DT_ODR_1HZ + - 2 # LPS22HH_DT_ODR_10HZ + - 3 # LPS22HH_DT_ODR_25HZ + - 4 # LPS22HH_DT_ODR_50HZ + - 5 # LPS22HH_DT_ODR_75HZ + - 6 # LPS22HH_DT_ODR_100HZ + - 7 # LPS22HH_DT_ODR_200HZ + + enum: [0, 1, 2, 3, 4, 5, 6, 7] diff --git a/dts/bindings/sensor/st,lsm6dso-common.yaml b/dts/bindings/sensor/st,lsm6dso-common.yaml index e8de1e9a75d..0b4b17df720 100644 --- a/dts/bindings/sensor/st,lsm6dso-common.yaml +++ b/dts/bindings/sensor/st,lsm6dso-common.yaml @@ -1,6 +1,25 @@ # Copyright (c) 2021 STMicroelectronics # SPDX-License-Identifier: Apache-2.0 +description: | + When setting the accel-pm, accel-range, accel-odr, gyro-pm, gyro-range, + gyro-odr properties in a .dts or .dtsi file you may include st_lsm6dso.h + and use the macros defined there. + + Example: + #include + + lsm6dso: lsm6dso@0 { + ... + + accel-pm = ; + accel-range = ; + accel-odr = ; + gyro-pm = ; + gyro-range = ; + gyro-odr = ; + }; + include: sensor-device.yaml properties: @@ -33,21 +52,25 @@ properties: description: | Specify the accelerometer power mode. Default is power-up configuration. - enum: - - 0 # High Performance mode (default) - - 1 # Low/Normal Power mode - - 2 # Ultra Low Power mode + + - 0 # LSM6DSO_DT_XL_HP_MODE + - 1 # LSM6DSO_DT_XL_LP_NORMAL_MODE + - 2 # LSM6DSO_DT_XL_ULP_MODE + + enum: [0, 1, 2] accel-range: type: int default: 0 description: | Range in g. Default is power-up configuration. - enum: - - 0 # 2g (0.061 mg/LSB) (LSM6DSO32 will be double these values) - - 1 # 16g (0.488 mg/LSB) - - 2 # 4g (0.122 mg/LSB) - - 3 # 8g (0.244 mg/LSB) + + - 0 # LSM6DSO_DT_FS_2G (0.061 mg/LSB) (LSM6DSO32 will be double these values) + - 1 # LSM6DSO_DT_FS_16G (0.488 mg/LSB) + - 2 # LSM6DSO_DT_FS_4G (0.122 mg/LSB) + - 3 # LSM6DSO_DT_FS_8G (0.244 mg/LSB) + + enum: [0, 1, 2, 3] accel-odr: type: int @@ -55,18 +78,21 @@ properties: description: | Specify the default accelerometer output data rate expressed in samples per second (Hz). Default is power-up configuration. - enum: - - 0 # Power-Down - - 1 # 12.5Hz - - 2 # 26Hz - - 3 # 52Hz - - 4 # 104Hz - - 5 # 208Hz - - 6 # 417Hz - - 7 # 833Hz - - 8 # 1667Hz - - 9 # 3333Hz - - 10 # 6667Hz + + - 0 # LSM6DSO_DT_ODR_OFF + - 1 # LSM6DSO_DT_ODR_12Hz5 + - 2 # LSM6DSO_DT_ODR_26H + - 3 # LSM6DSO_DT_ODR_52Hz + - 4 # LSM6DSO_DT_ODR_104Hz + - 5 # LSM6DSO_DT_ODR_208Hz + - 6 # LSM6DSO_DT_ODR_417Hz + - 7 # LSM6DSO_DT_ODR_833Hz + - 8 # LSM6DSO_DT_ODR_1667Hz + - 9 # LSM6DSO_DT_ODR_3333Hz + - 10 # LSM6DSO_DT_ODR_6667Hz + - 11 # LSM6DSO_DT_ODR_1Hz6 + + enum: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] gyro-pm: type: int @@ -74,21 +100,25 @@ properties: description: | Specify the gyrometer power mode. Default is power-up configuration. - enum: - - 0 # High Performance mode (default) - - 1 # Low/Normal Power mode + + - 0 # LSM6DSO_DT_GY_HP_MODE + - 1 # LSM6DSO_DT_GY_NORMAL_MODE + + enum: [0, 1] gyro-range: type: int default: 0 description: | Range in dps. Default is power-up configuration. - enum: - - 0 # 250 dps (8.75 mdps/LSB) - - 1 # 125 dps (4.375 mdps/LSB) - - 2 # 500 dps (17.50 mdps/LSB) - - 4 # 1000 dps (35 mdps/LSB) - - 6 # 2000 dps (70 mdps/LSB) + + - 0 # LSM6DSO_DT_FS_250DPS (8.75 mdps/LSB) + - 1 # LSM6DSO_DT_FS_125DPS (4.375 mdps/LSB) + - 2 # LSM6DSO_DT_FS_500DPS (17.50 mdps/LSB) + - 4 # LSM6DSO_DT_FS_1000DPS (35 mdps/LSB) + - 6 # LSM6DSO_DT_FS_2000DPS (70 mdps/LSB) + + enum: [0, 1, 2, 4, 6] gyro-odr: type: int @@ -96,18 +126,20 @@ properties: description: | Specify the default gyro output data rate expressed in samples per second (Hz). Default is power-up configuration. - enum: - - 0 # Power-Down - - 1 # 12.5Hz - - 2 # 26Hz - - 3 # 52Hz - - 4 # 104Hz - - 5 # 208Hz - - 6 # 417Hz - - 7 # 833Hz - - 8 # 1667Hz - - 9 # 3333Hz - - 10 # 6667Hz + + - 0 # LSM6DSO_DT_ODR_OFF + - 1 # LSM6DSO_DT_ODR_12Hz5 + - 2 # LSM6DSO_DT_ODR_26H + - 3 # LSM6DSO_DT_ODR_52Hz + - 4 # LSM6DSO_DT_ODR_104Hz + - 5 # LSM6DSO_DT_ODR_208Hz + - 6 # LSM6DSO_DT_ODR_417Hz + - 7 # LSM6DSO_DT_ODR_833Hz + - 8 # LSM6DSO_DT_ODR_1667Hz + - 9 # LSM6DSO_DT_ODR_3333Hz + - 10 # LSM6DSO_DT_ODR_6667Hz + + enum: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] drdy-pulsed: type: boolean diff --git a/dts/bindings/sensor/st,lsm6dso16is-common.yaml b/dts/bindings/sensor/st,lsm6dso16is-common.yaml index 16304b5692c..49f7fd187fb 100644 --- a/dts/bindings/sensor/st,lsm6dso16is-common.yaml +++ b/dts/bindings/sensor/st,lsm6dso16is-common.yaml @@ -1,6 +1,23 @@ # Copyright (c) 2023 STMicroelectronics # SPDX-License-Identifier: Apache-2.0 +description: | + When setting the accel-range, accel-odr, gyro-range, gyro-odr properties in + a .dts or .dtsi file you may include st_lsm6dso16is.h and use the macros + defined there. + + Example: + #include + + lsm6dso16is: lsm6dso16is@0 { + ... + + accel-range = ; + accel-odr = ; + gyro-range = ; + gyro-odr = ; + }; + include: sensor-device.yaml properties: @@ -32,11 +49,13 @@ properties: default: 0 description: | Range in g. Default is power-up configuration. - enum: - - 0 # 2g (0.061 mg/LSB) - - 1 # 16g (0.488 mg/LSB) - - 2 # 4g (0.122 mg/LSB) - - 3 # 8g (0.244 mg/LSB) + + - 0 # LSM6DSO16IS_DT_FS_2G (0.061 mg/LSB) + - 1 # LSM6DSO16IS_DT_FS_16G (0.488 mg/LSB) + - 2 # LSM6DSO16IS_DT_FS_4G (0.122 mg/LSB) + - 3 # LSM6DSO16IS_DT_FS_8G (0.244 mg/LSB) + + enum: [0, 1, 2, 3] accel-odr: type: int @@ -46,41 +65,46 @@ properties: The values are taken in accordance to lsm6dso16is_xl_data_rate_t enumerative in hal/st module. Default is power-up configuration. - enum: - - 0x00 # Power-Down - - 0x01 # 12.5Hz High Performance - - 0x02 # 26Hz High Performance - - 0x03 # 52Hz High Performance - - 0x04 # 104Hz High Performance - - 0x05 # 208Hz High Performance - - 0x06 # 417Hz High Performance - - 0x07 # 833Hz High Performance - - 0x08 # 1667Hz High Performance - - 0x09 # 3333Hz High Performance - - 0x0a # 6667Hz High Performance - - 0x11 # 12.5Hz Low Power - - 0x12 # 26Hz Low Power - - 0x13 # 52Hz Low Power - - 0x14 # 104Hz Low Power - - 0x15 # 208Hz Low Power - - 0x16 # 417Hz Low Power - - 0x17 # 833Hz Low Power - - 0x18 # 1667Hz Low Power - - 0x19 # 3333Hz Low Power - - 0x1a # 6667Hz Low Power - - 0x1b # 1Hz6 Low Power + + - 0x00 # LSM6DSO16IS_DT_ODR_OFF + - 0x01 # LSM6DSO16IS_DT_ODR_12Hz5_HP + - 0x02 # LSM6DSO16IS_DT_ODR_26H_HP + - 0x03 # LSM6DSO16IS_DT_ODR_52Hz_HP + - 0x04 # LSM6DSO16IS_DT_ODR_104Hz_HP + - 0x05 # LSM6DSO16IS_DT_ODR_208Hz_HP + - 0x06 # LSM6DSO16IS_DT_ODR_416Hz_HP + - 0x07 # LSM6DSO16IS_DT_ODR_833Hz_HP + - 0x08 # LSM6DSO16IS_DT_ODR_1667Hz_HP + - 0x09 # LSM6DSO16IS_DT_ODR_3333Hz_HP + - 0x0a # LSM6DSO16IS_DT_ODR_6667Hz_HP + - 0x11 # LSM6DSO16IS_DT_ODR_12Hz5_LP + - 0x12 # LSM6DSO16IS_DT_ODR_26H_LP + - 0x13 # LSM6DSO16IS_DT_ODR_52Hz_LP + - 0x14 # LSM6DSO16IS_DT_ODR_104Hz_LP + - 0x15 # LSM6DSO16IS_DT_ODR_208Hz_LP + - 0x16 # LSM6DSO16IS_DT_ODR_416Hz_LP + - 0x17 # LSM6DSO16IS_DT_ODR_833Hz_LP + - 0x18 # LSM6DSO16IS_DT_ODR_1667Hz_LP + - 0x19 # LSM6DSO16IS_DT_ODR_3333Hz_LP + - 0x1a # LSM6DSO16IS_DT_ODR_6667Hz_LP + - 0x1b # LSM6DSO16IS_DT_ODR_1Hz6_LP + + enum: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b] gyro-range: type: int default: 0 description: | Range in dps. Default is power-up configuration. - enum: - - 0 # 250 dps (8.75 mdps/LSB) - - 1 # 125 dps (4.375 mdps/LSB) - - 2 # 500 dps (17.50 mdps/LSB) - - 4 # 1000 dps (35 mdps/LSB) - - 6 # 2000 dps (70 mdps/LSB) + + - 0x0 # LSM6DSO16IS_DT_FS_250DPS (8.75 mdps/LSB) + - 0x1 # LSM6DSO16IS_DT_FS_500DPS (17.50 mdps/LSB) + - 0x2 # LSM6DSO16IS_DT_FS_1000DPS (35 mdps/LSB) + - 0x3 # LSM6DSO16IS_DT_FS_2000DPS (70 mdps/LSB) + - 0x10 # LSM6DSO16IS_DT_FS_125DPS (4.375 mdps/LSB) + + enum: [0x0, 0x1, 0x2, 0x3, 0x10] gyro-odr: type: int @@ -90,28 +114,31 @@ properties: The values are taken in accordance to lsm6dso16is_gy_data_rate_t enumerative in hal/st module. Default is power-up configuration. - enum: - - 0x00 # Power-Down - - 0x01 # 12.5Hz High Performance - - 0x02 # 26Hz High Performance - - 0x03 # 52Hz High Performance - - 0x04 # 104Hz High Performance - - 0x05 # 208Hz High Performance - - 0x06 # 417Hz High Performance - - 0x07 # 833Hz High Performance - - 0x08 # 1667Hz High Performance - - 0x09 # 3333Hz High Performance - - 0x0a # 6667Hz High Performance - - 0x11 # 12.5Hz Low Power - - 0x12 # 26Hz Low Power - - 0x13 # 52Hz Low Power - - 0x14 # 104Hz Low Power - - 0x15 # 208Hz Low Power - - 0x16 # 417Hz Low Power - - 0x17 # 833Hz Low Power - - 0x18 # 1667Hz Low Power - - 0x19 # 3333Hz Low Power - - 0x1a # 6667Hz Low Power + + - 0x00 # LSM6DSO16IS_DT_ODR_OFF + - 0x01 # LSM6DSO16IS_DT_ODR_12Hz5_HP + - 0x02 # LSM6DSO16IS_DT_ODR_26H_HP + - 0x03 # LSM6DSO16IS_DT_ODR_52Hz_HP + - 0x04 # LSM6DSO16IS_DT_ODR_104Hz_HP + - 0x05 # LSM6DSO16IS_DT_ODR_208Hz_HP + - 0x06 # LSM6DSO16IS_DT_ODR_416Hz_HP + - 0x07 # LSM6DSO16IS_DT_ODR_833Hz_HP + - 0x08 # LSM6DSO16IS_DT_ODR_1667Hz_HP + - 0x09 # LSM6DSO16IS_DT_ODR_3333Hz_HP + - 0x0a # LSM6DSO16IS_DT_ODR_6667Hz_HP + - 0x11 # LSM6DSO16IS_DT_ODR_12Hz5_LP + - 0x12 # LSM6DSO16IS_DT_ODR_26H_LP + - 0x13 # LSM6DSO16IS_DT_ODR_52Hz_LP + - 0x14 # LSM6DSO16IS_DT_ODR_104Hz_LP + - 0x15 # LSM6DSO16IS_DT_ODR_208Hz_LP + - 0x16 # LSM6DSO16IS_DT_ODR_416Hz_LP + - 0x17 # LSM6DSO16IS_DT_ODR_833Hz_LP + - 0x18 # LSM6DSO16IS_DT_ODR_1667Hz_LP + - 0x19 # LSM6DSO16IS_DT_ODR_3333Hz_LP + - 0x1a # LSM6DSO16IS_DT_ODR_6667Hz_LP + + enum: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a] drdy-pulsed: type: boolean diff --git a/dts/bindings/sensor/st,lsm6dsv16x-common.yaml b/dts/bindings/sensor/st,lsm6dsv16x-common.yaml index d12e8c32426..99167a6506d 100644 --- a/dts/bindings/sensor/st,lsm6dsv16x-common.yaml +++ b/dts/bindings/sensor/st,lsm6dsv16x-common.yaml @@ -1,13 +1,39 @@ # Copyright (c) 2023 STMicroelectronics # SPDX-License-Identifier: Apache-2.0 +description: | + When setting the accel-range, accel-odr, gyro-range, gyro-odr properties in + a .dts or .dtsi file you may include st_lsm6dsv16x.h and use the macros + defined there. + + Example: + #include + + lsm6dsv16x: lsm6dsv16x@0 { + ... + + accel-range = ; + accel-odr = ; + gyro-range = ; + gyro-odr = ; + }; + include: sensor-device.yaml properties: - irq-gpios: + int1-gpios: + type: phandle-array + description: | + INT1 pin + + This pin defaults to active high when produced by the sensor. + The property value should ensure the flags properly describe + the signal that is presented to the driver. + + int2-gpios: type: phandle-array description: | - DRDY pin + INT2 pin This pin defaults to active high when produced by the sensor. The property value should ensure the flags properly describe @@ -32,11 +58,13 @@ properties: default: 0 description: | Range in g. Default is power-up configuration. - enum: - - 0 # 2g (0.061 mg/LSB) - - 1 # 4g (0.122 mg/LSB) - - 2 # 8g (0.244 mg/LSB) - - 3 # 16g (0.488 mg/LSB) + + - 0 # LSM6DSV16X_DT_FS_2G (0.061 mg/LSB) + - 1 # LSM6DSV16X_DT_FS_4G (0.122 mg/LSB) + - 2 # LSM6DSV16X_DT_FS_8G (0.244 mg/LSB) + - 3 # LSM6DSV16X_DT_FS_16G (0.488 mg/LSB) + + enum: [0, 1, 2, 3] accel-odr: type: int @@ -47,53 +75,59 @@ properties: module. Please note that this values will not change the operating mode, which will remain High Performance (device default) Default is power-up configuration. - enum: - - 0x00 # Power-Down - - 0x01 # 1Hz875 - - 0x02 # 7Hz5 - - 0x03 # 15Hz - - 0x04 # 30Hz - - 0x05 # 60Hz - - 0x06 # 120Hz - - 0x07 # 240Hz - - 0x08 # 480Hz - - 0x09 # 960Hz - - 0x0a # 1920Hz - - 0x0b # 3840Hz - - 0x0c # 7680Hz - - 0x13 # 15Hz625 (High Accuracy 1) - - 0x14 # 31Hz25 (High Accuracy 1) - - 0x15 # 62Hz5 (High Accuracy 1) - - 0x16 # 125Hz (High Accuracy 1) - - 0x17 # 250Hz (High Accuracy 1) - - 0x18 # 500Hz (High Accuracy 1) - - 0x19 # 1000Hz (High Accuracy 1) - - 0x1a # 2000Hz (High Accuracy 1) - - 0x1b # 4000Hz (High Accuracy 1) - - 0x1c # 8000Hz (High Accuracy 1) - - 0x23 # 12Hz5 (High Accuracy 2) - - 0x24 # 25Hz (High Accuracy 2) - - 0x25 # 50Hz (High Accuracy 2) - - 0x26 # 100Hz (High Accuracy 2) - - 0x27 # 200Hz (High Accuracy 2) - - 0x28 # 400Hz (High Accuracy 2) - - 0x29 # 800Hz (High Accuracy 2) - - 0x2a # 1600Hz (High Accuracy 2) - - 0x2b # 3200Hz (High Accuracy 2) - - 0x2c # 6400Hz (High Accuracy 2) + + - 0x00 # LSM6DSV16X_DT_ODR_OFF + - 0x01 # LSM6DSV16X_DT_ODR_AT_1Hz875 + - 0x02 # LSM6DSV16X_DT_ODR_AT_7Hz5 + - 0x03 # LSM6DSV16X_DT_ODR_AT_15Hz + - 0x04 # LSM6DSV16X_DT_ODR_AT_30Hz + - 0x05 # LSM6DSV16X_DT_ODR_AT_60Hz + - 0x06 # LSM6DSV16X_DT_ODR_AT_120Hz + - 0x07 # LSM6DSV16X_DT_ODR_AT_240Hz + - 0x08 # LSM6DSV16X_DT_ODR_AT_480Hz + - 0x09 # LSM6DSV16X_DT_ODR_AT_960Hz + - 0x0a # LSM6DSV16X_DT_ODR_AT_1920Hz + - 0x0b # LSM6DSV16X_DT_ODR_AT_3840Hz + - 0x0c # LSM6DSV16X_DT_ODR_AT_7680Hz + - 0x13 # LSM6DSV16X_DT_ODR_HA01_AT_15Hz625 + - 0x14 # LSM6DSV16X_DT_ODR_HA01_AT_31Hz25 + - 0x15 # LSM6DSV16X_DT_ODR_HA01_AT_62Hz5 + - 0x16 # LSM6DSV16X_DT_ODR_HA01_AT_125Hz + - 0x17 # LSM6DSV16X_DT_ODR_HA01_AT_250Hz + - 0x18 # LSM6DSV16X_DT_ODR_HA01_AT_500Hz + - 0x19 # LSM6DSV16X_DT_ODR_HA01_AT_1000Hz + - 0x1a # LSM6DSV16X_DT_ODR_HA01_AT_2000Hz + - 0x1b # LSM6DSV16X_DT_ODR_HA01_AT_4000Hz + - 0x1c # LSM6DSV16X_DT_ODR_HA01_AT_8000Hz + - 0x23 # LSM6DSV16X_DT_ODR_HA02_AT_12Hz5 + - 0x24 # LSM6DSV16X_DT_ODR_HA02_AT_25Hz + - 0x25 # LSM6DSV16X_DT_ODR_HA02_AT_50Hz + - 0x26 # LSM6DSV16X_DT_ODR_HA02_AT_100Hz + - 0x27 # LSM6DSV16X_DT_ODR_HA02_AT_200Hz + - 0x28 # LSM6DSV16X_DT_ODR_HA02_AT_400Hz + - 0x29 # LSM6DSV16X_DT_ODR_HA02_AT_800Hz + - 0x2a # LSM6DSV16X_DT_ODR_HA02_AT_1600Hz + - 0x2b # LSM6DSV16X_DT_ODR_HA02_AT_3200Hz + - 0x2c # LSM6DSV16X_DT_ODR_HA02_AT_6400Hz + + enum: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, + 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, + 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c] gyro-range: type: int default: 0 description: | Range in dps. Default is power-up configuration. - enum: - - 0 # 125 dps (4.375 mdps/LSB) - - 1 # 250 dps (8.75 mdps/LSB) - - 2 # 500 dps (17.50 mdps/LSB) - - 3 # 1000 dps (35 mdps/LSB) - - 4 # 2000 dps (70 mdps/LSB) - - 5 # 4000 dps (140 mdps/LSB) + + - 0x0 # LSM6DSV16X_DT_FS_125DPS (4.375 mdps/LSB) + - 0x1 # LSM6DSV16X_DT_FS_250DPS (8.75 mdps/LSB) + - 0x2 # LSM6DSV16X_DT_FS_500DPS (17.50 mdps/LSB) + - 0x3 # LSM6DSV16X_DT_FS_1000DPS (35 mdps/LSB) + - 0x4 # LSM6DSV16X_DT_FS_2000DPS (70 mdps/LSB) + - 0xc # LSM6DSV16X_DT_FS_4000DPS (140 mdps/LSB) + + enum: [0x0, 0x1, 0x2, 0x3, 0x4, 0xc] gyro-odr: type: int @@ -106,39 +140,44 @@ properties: DT are the only way to specifiy the odr accuracy even at runtime with SENSOR_ATTR_SAMPLING_FREQUENCY. Default is power-up configuration. - enum: - - 0x00 # Power-Down - - 0x02 # 7Hz5 - - 0x03 # 15Hz - - 0x04 # 30Hz - - 0x05 # 60Hz - - 0x06 # 120Hz - - 0x07 # 240Hz - - 0x08 # 480Hz - - 0x09 # 960Hz - - 0x0a # 1920Hz - - 0x0b # 3840Hz - - 0x0c # 7680Hz - - 0x13 # 15Hz625 (High Accuracy 1) - - 0x14 # 31Hz25 (High Accuracy 1) - - 0x15 # 62Hz5 (High Accuracy 1) - - 0x16 # 125Hz (High Accuracy 1) - - 0x17 # 250Hz (High Accuracy 1) - - 0x18 # 500Hz (High Accuracy 1) - - 0x19 # 1000Hz (High Accuracy 1) - - 0x1a # 2000Hz (High Accuracy 1) - - 0x1b # 4000Hz (High Accuracy 1) - - 0x1c # 8000Hz (High Accuracy 1) - - 0x23 # 12Hz5 (High Accuracy 2) - - 0x24 # 25Hz (High Accuracy 2) - - 0x25 # 50Hz (High Accuracy 2) - - 0x26 # 100Hz (High Accuracy 2) - - 0x27 # 200Hz (High Accuracy 2) - - 0x28 # 400Hz (High Accuracy 2) - - 0x29 # 800Hz (High Accuracy 2) - - 0x2a # 1600Hz (High Accuracy 2) - - 0x2b # 3200Hz (High Accuracy 2) - - 0x2c # 6400Hz (High Accuracy 2) + + - 0x00 # LSM6DSV16X_DT_ODR_OFF + - 0x01 # LSM6DSV16X_DT_ODR_AT_1Hz875 + - 0x02 # LSM6DSV16X_DT_ODR_AT_7Hz5 + - 0x03 # LSM6DSV16X_DT_ODR_AT_15Hz + - 0x04 # LSM6DSV16X_DT_ODR_AT_30Hz + - 0x05 # LSM6DSV16X_DT_ODR_AT_60Hz + - 0x06 # LSM6DSV16X_DT_ODR_AT_120Hz + - 0x07 # LSM6DSV16X_DT_ODR_AT_240Hz + - 0x08 # LSM6DSV16X_DT_ODR_AT_480Hz + - 0x09 # LSM6DSV16X_DT_ODR_AT_960Hz + - 0x0a # LSM6DSV16X_DT_ODR_AT_1920Hz + - 0x0b # LSM6DSV16X_DT_ODR_AT_3840Hz + - 0x0c # LSM6DSV16X_DT_ODR_AT_7680Hz + - 0x13 # LSM6DSV16X_DT_ODR_HA01_AT_15Hz625 + - 0x14 # LSM6DSV16X_DT_ODR_HA01_AT_31Hz25 + - 0x15 # LSM6DSV16X_DT_ODR_HA01_AT_62Hz5 + - 0x16 # LSM6DSV16X_DT_ODR_HA01_AT_125Hz + - 0x17 # LSM6DSV16X_DT_ODR_HA01_AT_250Hz + - 0x18 # LSM6DSV16X_DT_ODR_HA01_AT_500Hz + - 0x19 # LSM6DSV16X_DT_ODR_HA01_AT_1000Hz + - 0x1a # LSM6DSV16X_DT_ODR_HA01_AT_2000Hz + - 0x1b # LSM6DSV16X_DT_ODR_HA01_AT_4000Hz + - 0x1c # LSM6DSV16X_DT_ODR_HA01_AT_8000Hz + - 0x23 # LSM6DSV16X_DT_ODR_HA02_AT_12Hz5 + - 0x24 # LSM6DSV16X_DT_ODR_HA02_AT_25Hz + - 0x25 # LSM6DSV16X_DT_ODR_HA02_AT_50Hz + - 0x26 # LSM6DSV16X_DT_ODR_HA02_AT_100Hz + - 0x27 # LSM6DSV16X_DT_ODR_HA02_AT_200Hz + - 0x28 # LSM6DSV16X_DT_ODR_HA02_AT_400Hz + - 0x29 # LSM6DSV16X_DT_ODR_HA02_AT_800Hz + - 0x2a # LSM6DSV16X_DT_ODR_HA02_AT_1600Hz + - 0x2b # LSM6DSV16X_DT_ODR_HA02_AT_3200Hz + - 0x2c # LSM6DSV16X_DT_ODR_HA02_AT_6400Hz + + enum: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, + 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, + 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c] drdy-pulsed: type: boolean diff --git a/dts/bindings/sensor/ti,bq274xx.yaml b/dts/bindings/sensor/ti,bq274xx.yaml index 16032b625cf..f50aba228c1 100644 --- a/dts/bindings/sensor/ti,bq274xx.yaml +++ b/dts/bindings/sensor/ti,bq274xx.yaml @@ -31,6 +31,12 @@ properties: required: true description: Battery Terminate Voltage in mV + chemistry-id: + type: int + description: | + The value of the Chem ID register. When zero, the driver will not check the register. + See the reference manual for the specific BQ274xx variant for values. + int-gpios: type: phandle-array description: | diff --git a/dts/bindings/sensor/ti,tmag5170.yaml b/dts/bindings/sensor/ti,tmag5170.yaml new file mode 100644 index 00000000000..c68e704c900 --- /dev/null +++ b/dts/bindings/sensor/ti,tmag5170.yaml @@ -0,0 +1,213 @@ +# Copyright (c) 2023 Michal Morsisko +# SPDX-License-Identifier: Apache-2.0 + +description: Texas Instruments TMAG5170 high-precision, linear 3D Hall-effect sensor. + +compatible: "ti,tmag5170" + +include: [sensor-device.yaml, spi-device.yaml] + +properties: + int-gpios: + type: phandle-array + description: | + This property specifies the connection to ALERT sensor pin. + It will be used by the driver to notify the application about + data ready event. For this property to take effect, the + TMAG5170_TRIGGER must be set in project configuration + operating-mode: + type: int + required: true + description: | + Operating mode of the device. + 1 - stand-by mode - in this mode the device waits for application to trigger + the measurement. + 2 - active measure mode - continuous sampling on all enabled channels + as fast as possible. Recommended for devices that haven't got + strict power requirements and need frequent sampling. + 3 - active trigger mode - in this mode, similar to stand-by mode, the device + wait for application to trigger the measurement, but the time needed to finish + the conversion is shorter than in stand-by mode, on the cost of increased power + consumption. + 4 - duty-cycled - after each sample the device goes to sleep and then + automatically wakes up to take another sample. The sleep time is determined + by `sleep-time` property. Recommended for low-power devices that don't need + high frequency sampling. + enum: + - 1 + - 2 + - 3 + - 4 + magnetic-channels: + type: string + default: "XYZ" + description: | + Enables data acquisition of the magnetic axis channel(s) + If axis is enabled more than once, sensor will do pseudo-simultaneous + sampling. Refer to datasheet for more information, By default all axes + are enabled (XYZ) to allow the user to check if the sensor work as expected. + Following options are allowed: + None (chip reset value) + X + Y + XY + Z + ZX + YZ + XYZ (default) + XYX + YXY + YZY + ZYZ + ZXZ + XZX + XYZYX + XYZZYX + enum: + - "None" + - "X" + - "Y" + - "XY" + - "Z" + - "ZX" + - "YZ" + - "XYZ" + - "XYX" + - "YXY" + - "YZY" + - "ZYZ" + - "ZXZ" + - "XZX" + - "XYZYX" + - "XYZZYX" + x-range: + type: int + default: 0 + description: | + The maximum and minimum values that can be measured on X axis. + The wider the range, the worse the resolution. + 0 = ±50mT (TMAG5170A1)/ ±150mT(TMAG5170A2) - (default; chip reset value) + 1 = ±25mT (TMAG5170A1)/ ±75mT(TMAG5170A2) + 2 = ±100mT (TMAG5170A1)/ ±300mT(TMAG5170A2) + enum: + - 0 + - 1 + - 2 + y-range: + type: int + default: 0 + description: | + The maximum and minimum values that can be measured on Y axis. + The wider the range, the worse the resolution. + 0 = ±50mT (TMAG5170A1)/ ±150mT(TMAG5170A2) - (default; chip reset value) + 1 = ±25mT (TMAG5170A1)/ ±75mT(TMAG5170A2) + 2 = ±100mT (TMAG5170A1)/ ±300mT(TMAG5170A2) + enum: + - 0 + - 1 + - 2 + z-range: + type: int + default: 0 + description: | + The maximum and minimum values that can be measured on Z axis. + The wider the range, the worse the resolution. + 0 = ±50mT (TMAG5170A1)/ ±150mT(TMAG5170A2) - (default; chip reset value) + 1 = ±25mT (TMAG5170A1)/ ±75mT(TMAG5170A2) + 2 = ±100mT (TMAG5170A1)/ ±300mT(TMAG5170A2) + enum: + - 0 + - 1 + - 2 + oversampling: + type: int + default: 1 + description: | + Enables additional sampling of the sensor data to reduce the noise + effect. If temperature channel is enabled, temperature will be oversampled + too, unless `disable-temperature-oversampling` property is present. + Following options are allowed: + 1 (default; chip reset value) + 2 + 4 + 8 + 16 + 32 + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + enable-temperature-channel: + type: boolean + description: | + Enables temperature measurement + magnet-type: + type: string + default: "None" + description: | + Enables temperature compensation basing on the type of magnet. + Following options are allowed: + None (default; chip reset value) + NdBFe = 0.12%/deg C + SmCo = 0.03%/deg C + Ceramic = 0.2%/deg C + enum: + - "None" + - "NdBFe" + - "SmCo" + - "Ceramic" + angle-measurement: + type: string + default: "None" + description: | + Enable angle calculation using two axis data: + None (default; chip reset value) + XY + YZ + XZ + enum: + - "None" + - "XY" + - "YZ" + - "XZ" + disable-temperature-oversampling: + type: boolean + description: | + If true, temperature is always sampled once per conversion set + If false, temperature is oversampled according to `oversampling` + property. + sleep-time: + type: int + default: 1 + description: | + The time in miliseconds the sensor will be in sleep during conversions. + For this property to take effect sensor must be in `duty-cycled` mode. + Note that to calculate total time between conversions, the conversion time + itself must be taken into account. The conversion time is dependent + on the values of `oversampling`, `magnetic-channels`, `temperature-channel-enabled` + and `disable-temperature-oversampling` properties. + Following value are allowed: + 1 (default; chip reset value) + 5 + 10 + 15 + 20 + 30 + 50 + 100 + 500 + 1000 + enum: + - 1 + - 5 + - 10 + - 15 + - 20 + - 30 + - 50 + - 100 + - 500 + - 1000 diff --git a/dts/bindings/serial/brcm,bcm2711-aux-uart.yaml b/dts/bindings/serial/brcm,bcm2711-aux-uart.yaml new file mode 100644 index 00000000000..2f14db1d877 --- /dev/null +++ b/dts/bindings/serial/brcm,bcm2711-aux-uart.yaml @@ -0,0 +1,15 @@ +description: BCM2711 UART + +compatible: "brcm,bcm2711-aux-uart" + +include: [uart-controller.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + clock-frequency: + required: true diff --git a/dts/bindings/serial/intel,lw_uart.yaml b/dts/bindings/serial/intel,lw_uart.yaml new file mode 100644 index 00000000000..798dfa53225 --- /dev/null +++ b/dts/bindings/serial/intel,lw_uart.yaml @@ -0,0 +1,19 @@ +description: Intel Lightweight UART + +compatible: "intel,lw-uart" + +include: uart-controller.yaml + +properties: + reg: + required: true + description: Base address of the uart controller. + + current-speed: + required: true + description: Default baudrate of the uart controller. + + fixed-baudrate: + type: boolean + description: | + Baud rate cannot be changed by software (Divisor register is not writable) diff --git a/dts/bindings/serial/nxp,kinetis-lpsci.yaml b/dts/bindings/serial/nxp,kinetis-lpsci.yaml index 362038669cd..0934c02b3e1 100644 --- a/dts/bindings/serial/nxp,kinetis-lpsci.yaml +++ b/dts/bindings/serial/nxp,kinetis-lpsci.yaml @@ -12,5 +12,4 @@ properties: required: true pinctrl-0: - type: phandles required: true diff --git a/dts/bindings/serial/nxp,kinetis-uart.yaml b/dts/bindings/serial/nxp,kinetis-uart.yaml index 6a109b20143..394ce11bea5 100644 --- a/dts/bindings/serial/nxp,kinetis-uart.yaml +++ b/dts/bindings/serial/nxp,kinetis-uart.yaml @@ -15,5 +15,4 @@ properties: required: true pinctrl-0: - type: phandles required: true diff --git a/dts/bindings/serial/quicklogic,usbserialport-s3b.yaml b/dts/bindings/serial/quicklogic,usbserialport-s3b.yaml new file mode 100644 index 00000000000..36800dcd782 --- /dev/null +++ b/dts/bindings/serial/quicklogic,usbserialport-s3b.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2022 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +description: QuickLogic USBserialport_S3B serial interface + +compatible: "quicklogic,usbserialport-s3b" + +include: [uart-controller.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true diff --git a/dts/bindings/serial/quicklogic,usbserialport_s3b.yaml b/dts/bindings/serial/quicklogic,usbserialport_s3b.yaml deleted file mode 100644 index 55661083585..00000000000 --- a/dts/bindings/serial/quicklogic,usbserialport_s3b.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2022 Antmicro -# SPDX-License-Identifier: Apache-2.0 - -description: QuickLogic USBserialport_S3B serial interface - -compatible: "quicklogic,usbserialport-s3b" - -include: uart-controller.yaml - -properties: - reg: - required: true diff --git a/dts/bindings/serial/renesas,ra-uart-sci.yaml b/dts/bindings/serial/renesas,ra-uart-sci.yaml new file mode 100644 index 00000000000..94229b06924 --- /dev/null +++ b/dts/bindings/serial/renesas,ra-uart-sci.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas RA Series SCI based UART controller + +compatible: "renesas,ra-uart-sci" + +include: [uart-controller.yaml] diff --git a/dts/bindings/serial/renesas,rzt2m-uart.yaml b/dts/bindings/serial/renesas,rzt2m-uart.yaml new file mode 100644 index 00000000000..967972ac7c8 --- /dev/null +++ b/dts/bindings/serial/renesas,rzt2m-uart.yaml @@ -0,0 +1,26 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas RZ/T2M UART + +compatible: "renesas,rzt2m-uart" + +include: + - name: uart-controller.yaml + - name: pinctrl-device.yaml + +properties: + reg: + required: true + + current-speed: + required: true + description: | + Initial baud rate setting for UART. Only a fixed set of baud + rates is currently supported. + enum: + - 9600 + - 115200 + + interrupts: + required: true diff --git a/dts/bindings/serial/telink,b91-uart.yaml b/dts/bindings/serial/telink,b91-uart.yaml index b3affa70c68..b38be5dfd42 100644 --- a/dts/bindings/serial/telink,b91-uart.yaml +++ b/dts/bindings/serial/telink,b91-uart.yaml @@ -5,7 +5,7 @@ description: Telink B91 UART compatible: "telink,b91-uart" -include: uart-controller.yaml +include: [uart-controller.yaml, pinctrl-device.yaml] properties: reg: @@ -15,5 +15,4 @@ properties: required: true pinctrl-0: - type: phandles required: true diff --git a/dts/bindings/serial/zephyr,uart-emul.yaml b/dts/bindings/serial/zephyr,uart-emul.yaml index d3d50dc9e93..119aa49df6a 100644 --- a/dts/bindings/serial/zephyr,uart-emul.yaml +++ b/dts/bindings/serial/zephyr,uart-emul.yaml @@ -25,3 +25,9 @@ properties: description: | Connects TX to RX internally creating a loop back connection. Useful for testing. + + latch-buffer-size: + type: int + default: 1 + description: | + Size of the virtual UART latch buffer. diff --git a/dts/bindings/sip_svc/intel,agilex-socfpga-sip-smc.yaml b/dts/bindings/sip_svc/intel,agilex-socfpga-sip-smc.yaml index f7cb3af2b88..82a6f53dbf0 100644 --- a/dts/bindings/sip_svc/intel,agilex-socfpga-sip-smc.yaml +++ b/dts/bindings/sip_svc/intel,agilex-socfpga-sip-smc.yaml @@ -4,7 +4,7 @@ description: SiP SVC driver instance on Intel Agilex SOC FPGA for SMC call -compatible: "intel,agilex-socfpga-sip-smc" +compatible: "intel,socfpga-agilex-sip-smc" include: base.yaml diff --git a/dts/bindings/spi/ambiq,mspi.yaml b/dts/bindings/spi/ambiq,mspi.yaml new file mode 100644 index 00000000000..0c48f6605e6 --- /dev/null +++ b/dts/bindings/spi/ambiq,mspi.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +description: Ambiq MSPI + +compatible: "ambiq,mspi" + +include: [spi-controller.yaml, pinctrl-device.yaml, ambiq-pwrcfg.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + ambiq,pwrcfg: + required: true diff --git a/dts/bindings/spi/infineon,cat1-spi.yaml b/dts/bindings/spi/infineon,cat1-spi.yaml new file mode 100644 index 00000000000..4b1000b3497 --- /dev/null +++ b/dts/bindings/spi/infineon,cat1-spi.yaml @@ -0,0 +1,20 @@ +# Copyright (c) 2022 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +description: Infineon CAT1 SPI + +compatible: "infineon,cat1-spi" + +include: [spi-controller.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + pinctrl-0: + required: true diff --git a/dts/bindings/spi/intel,sedi-spi.yaml b/dts/bindings/spi/intel,sedi-spi.yaml new file mode 100644 index 00000000000..ef3af78460a --- /dev/null +++ b/dts/bindings/spi/intel,sedi-spi.yaml @@ -0,0 +1,23 @@ +# +# Copyright (c) 2023 Intel Corporation. +# +# SPDX-License-Identifier: Apache-2.0 +# + +description: Intel SEDI SPI controller + +compatible: "intel,sedi-spi" + +include: spi-controller.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + peripheral-id: + type: int + description: Peripheral Instance ID + required: true diff --git a/dts/bindings/spi/nxp,kinetis-dspi.yaml b/dts/bindings/spi/nxp,kinetis-dspi.yaml index 8d01c74e04e..61746937c39 100644 --- a/dts/bindings/spi/nxp,kinetis-dspi.yaml +++ b/dts/bindings/spi/nxp,kinetis-dspi.yaml @@ -36,7 +36,6 @@ properties: select assert. If not set, the minimum supported delay is used. pinctrl-0: - type: phandles required: true nxp,rx-tx-chn-share: diff --git a/dts/bindings/spi/nxp,s32-spi.yaml b/dts/bindings/spi/nxp,s32-spi.yaml index 722b3add3db..f505da6d8d1 100644 --- a/dts/bindings/spi/nxp,s32-spi.yaml +++ b/dts/bindings/spi/nxp,s32-spi.yaml @@ -1,4 +1,4 @@ -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # SPDX-License-Identifier: Apache-2.0 description: NXP S32 SPI controller @@ -20,11 +20,8 @@ properties: description: | The number of the Chip Select signals. - clock-frequency: - type: int + clocks: required: true - description: | - Module clock frequency in Hz. pinctrl-0: required: true diff --git a/dts/bindings/spi/spi-device.yaml b/dts/bindings/spi/spi-device.yaml index f820863b30d..6915b664890 100644 --- a/dts/bindings/spi/spi-device.yaml +++ b/dts/bindings/spi/spi-device.yaml @@ -40,3 +40,21 @@ properties: enum: - 0 - 32768 + spi-cpol: + type: boolean + description: | + SPI clock polarity which indicates the clock idle state. + If it is used, the clock idle state is logic high; otherwise, low. + spi-cpha: + type: boolean + description: | + SPI clock phase that indicates on which edge data is sampled. + If it is used, data is sampled on the second edge; otherwise, on the first edge. + spi-hold-cs: + type: boolean + description: | + In some cases, it is necessary for the master to manage SPI chip select + under software control, so that multiple spi transactions can be performed + without releasing it. A typical use case is variable length SPI packets + where the first spi transaction reads the length and the second spi transaction + reads length bytes. diff --git a/dts/bindings/spi/telink,b91-spi.yaml b/dts/bindings/spi/telink,b91-spi.yaml index e49e660d41d..7e66217f3dd 100644 --- a/dts/bindings/spi/telink,b91-spi.yaml +++ b/dts/bindings/spi/telink,b91-spi.yaml @@ -3,7 +3,7 @@ description: Telink B91 SPI -include: spi-controller.yaml +include: [spi-controller.yaml, pinctrl-device.yaml] compatible: "telink,b91-spi" @@ -19,7 +19,6 @@ properties: - "HSPI_MODULE" pinctrl-0: - type: phandles required: true cs0-pin: diff --git a/dts/bindings/test/vnd,adc-temp-sensor.yaml b/dts/bindings/test/vnd,adc-temp-sensor.yaml index 8bc33a7373a..89389b05401 100644 --- a/dts/bindings/test/vnd,adc-temp-sensor.yaml +++ b/dts/bindings/test/vnd,adc-temp-sensor.yaml @@ -5,7 +5,7 @@ description: Test ADC-based temperature sensor compatible: "vnd,adc-temp-sensor" -include: [base.yaml, reset-device.yaml] +include: [base.yaml, pinctrl-device.yaml, reset-device.yaml] properties: io-channels: @@ -18,12 +18,3 @@ properties: clocks: required: true - - pinctrl-0: - type: phandles - - pinctrl-1: - type: phandles - - pinctrl-2: - type: phandles diff --git a/dts/bindings/timer/nxp,s32-sys-timer.yaml b/dts/bindings/timer/nxp,s32-sys-timer.yaml index fbd8c8f3f70..54ac9d20d53 100644 --- a/dts/bindings/timer/nxp,s32-sys-timer.yaml +++ b/dts/bindings/timer/nxp,s32-sys-timer.yaml @@ -1,4 +1,4 @@ -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # SPDX-License-Identifier: Apache-2.0 description: NXP S32 System Timer Module (STM) @@ -14,10 +14,8 @@ properties: interrupts: required: true - clock-frequency: - type: int + clocks: required: true - description: Module clock frequency in Hz. prescaler: type: int diff --git a/dts/bindings/timer/raspberrypi,pico-timer.yaml b/dts/bindings/timer/raspberrypi,pico-timer.yaml new file mode 100644 index 00000000000..98afd1b9659 --- /dev/null +++ b/dts/bindings/timer/raspberrypi,pico-timer.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +description: RaspberryPi Pico timer + +compatible: "raspberrypi,pico-timer" + +include: [base.yaml, reset-device.yaml] diff --git a/dts/bindings/usb-c/usb-c-connector.yaml b/dts/bindings/usb-c/usb-c-connector.yaml index 1984486b7e6..c5e69653a33 100644 --- a/dts/bindings/usb-c/usb-c-connector.yaml +++ b/dts/bindings/usb-c/usb-c-connector.yaml @@ -29,7 +29,7 @@ description: | reg = <1>; tcpc = <&ucpd1>; vbus = <&vbus1>; - power-role = "SINK"; + power-role = "sink"; sink-pdos = ; op-sink-microwatt = <10000000>; diff --git a/dts/bindings/usb/nxp,ehci.yaml b/dts/bindings/usb/nxp,ehci.yaml new file mode 100644 index 00000000000..cf72a69545c --- /dev/null +++ b/dts/bindings/usb/nxp,ehci.yaml @@ -0,0 +1,8 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP EHCI USB device mode + +compatible: nxp,ehci + +include: "nxp,mcux-usbd.yaml" diff --git a/dts/bindings/usb/nxp,lpcip3511.yaml b/dts/bindings/usb/nxp,lpcip3511.yaml new file mode 100644 index 00000000000..70ea1188837 --- /dev/null +++ b/dts/bindings/usb/nxp,lpcip3511.yaml @@ -0,0 +1,8 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP LPCIP3511 USB device mode + +compatible: nxp,lpcip3511 + +include: "nxp,mcux-usbd.yaml" diff --git a/dts/bindings/usb/nxp,mcux-usbd.yaml b/dts/bindings/usb/nxp,mcux-usbd.yaml index 389f43e1da0..af0dd762137 100644 --- a/dts/bindings/usb/nxp,mcux-usbd.yaml +++ b/dts/bindings/usb/nxp,mcux-usbd.yaml @@ -4,8 +4,6 @@ description: | NPX MXRT and LPC USBOTG Controller in device mode -compatible: "nxp,mcux-usbd" - include: [usb-ep.yaml, pinctrl-device.yaml] properties: @@ -14,24 +12,3 @@ properties: interrupts: required: true - - usb-controller-index: - required: true - type: string - description: | - This is taken from the usb_controller_index_t enum that is included inside the NXP SDK - enum: - - "Khci0" - - "Khci1" - - "Ehci0" - - "Ehci1" - - "LpcIp3511Fs0" - - "LpcIp3511Fs1" - - "LpcIp3511Hs0" - - "LpcIp3511Hs1" - - "Ohci0" - - "Ohci1" - - "Ip3516Hs0" - - "Ip3516Hs1" - - "Dwc30" - - "Dwc31" diff --git a/dts/bindings/usb/usb-audio-feature-volume.yaml b/dts/bindings/usb/usb-audio-feature-volume.yaml new file mode 100644 index 00000000000..7a4356f4ed5 --- /dev/null +++ b/dts/bindings/usb/usb-audio-feature-volume.yaml @@ -0,0 +1,37 @@ +# Copyright (c) 2023, LISTENAI +# SPDX-License-Identifier: Apache-2.0 +# +# Specific fields for USB volume control. + +description: USB volume control specific fields. + +compatible: "usb-audio-feature-volume" + +include: base.yaml + +properties: + volume-max: + type: int + default: 0x0A00 + description: | + attention: this attribute is a signed value. + This attribute represents the maximum volume level. + The range from +127.9961 dB (0x7FFF) down to -127.9961 dB (0x8001). + Valid range: 0 - 0xFFFF + volume-min: + type: int + default: 0xBA00 + description: | + attention: this attribute is a signed value. + This attribute represents the minimum volume level. + The range from +127.9961 dB (0x7FFF) down to -127.9961 dB (0x8001). + Valid range: 0 - 0xFFFF + volume-res: + type: int + default: 0x100 + description: | + attention: this attribute can only take positive values. + This attribute represents the volume resolution(step). + 1 = 1/256 dB or 0.00390625 dB. + 0x100(256) = 1dB. + Valid range: 1 - 0x7FFF diff --git a/dts/bindings/usb/usb-audio-hp.yaml b/dts/bindings/usb/usb-audio-hp.yaml index 051c57c07d3..91968126c1e 100644 --- a/dts/bindings/usb/usb-audio-hp.yaml +++ b/dts/bindings/usb/usb-audio-hp.yaml @@ -7,7 +7,7 @@ description: USB Audio headphones specific fields. compatible: "usb-audio-hp" -include: usb-audio.yaml +include: [usb-audio.yaml, usb-audio-feature-volume.yaml] properties: resolution: diff --git a/dts/bindings/usb/usb-audio-hs.yaml b/dts/bindings/usb/usb-audio-hs.yaml index 3c4a39842a5..ce0245cc136 100644 --- a/dts/bindings/usb/usb-audio-hs.yaml +++ b/dts/bindings/usb/usb-audio-hs.yaml @@ -7,7 +7,7 @@ description: USB Audio headset specific fields. compatible: "usb-audio-hs" -include: usb-audio.yaml +include: [usb-audio.yaml, usb-audio-feature-volume.yaml] properties: mic-resolution: @@ -167,7 +167,6 @@ properties: type: boolean description: | Enable Volume feature. - Currently not supported. hp-feature-tone-control: type: boolean description: | diff --git a/dts/bindings/vendor-prefixes.txt b/dts/bindings/vendor-prefixes.txt index c38c3db55ac..29a7b78aa70 100644 --- a/dts/bindings/vendor-prefixes.txt +++ b/dts/bindings/vendor-prefixes.txt @@ -10,6 +10,7 @@ # # +aaeon AAEON Technology Inc. abb ABB abilis Abilis Systems abracon Abracon Corporation @@ -213,6 +214,7 @@ fcs Fairchild Semiconductor feixin Shenzhen Feixin Photoelectic Co., Ltd feiyang Shenzhen Fly Young Technology Co.,LTD. fii Foxconn Industrial Internet +fintek Feature Integration Technology Inc. firefly Firefly focaltech FocalTech Systems Co.,Ltd frida Shenzhen Frida LCD Co., Ltd. @@ -242,6 +244,7 @@ google Google, Inc. greeled GreeLed Electronic Ltd. grinn Grinn grmn Garmin Limited +gss Gas Sensing Solutions Ltd. gumstix Gumstix, Inc. hamamatsu Hamamatsu Photonics K.K. hannstar HannStar Display Corporation @@ -351,6 +354,7 @@ lontium Lontium Semiconductor Corporation loongson Loongson Technology Corporation Limited lowrisc lowRISC Community Interest Company lsi LSI Corp. (LSI Logic) +ltr LiteOn OptoElectronics lwn Liebherr-Werk Nenzing GmbH lxa Linux Automation GmbH m5stack M5Stack @@ -562,6 +566,7 @@ simcom SIMCom Wireless Solutions Co., LTD simtek Cypress Semiconductor Corporation (Simtek Corporation) sinlinx Sinlinx Electronics Technology Co., LTD sinovoip SinoVoip Co., Ltd +sinowealth Sino Wealth Electronic Ltd sipeed Shenzhen Sipeed Technology Co., Ltd. sirf SiRF Technology, Inc. sis Silicon Integrated Systems Corp. @@ -579,6 +584,7 @@ sony Sony Corporation spansion Spansion Inc. sparkfun SparkFun Electronics sprd Spreadtrum Communications Inc. +sqn Sequans Communications sst Silicon Storage Technology, Inc. sstar Xiamen Xingchen(SigmaStar) Technology Co., Ltd. (formerly part of MStar Semiconductor, Inc.) st STMicroelectronics @@ -604,6 +610,7 @@ tdo Shangai Top Display Optoelectronics Co., Ltd technexion TechNexion technologic Technologic Systems telink Telink Semiconductor +telit Telit Cinterion tempo Tempo Semiconductor techstar Shenzhen Techstar Electronics Co., Ltd. terasic Terasic Inc. diff --git a/dts/bindings/watchdog/infineon,xmc4xxx-watchdog.yaml b/dts/bindings/watchdog/infineon,xmc4xxx-watchdog.yaml new file mode 100644 index 00000000000..66afaa53e68 --- /dev/null +++ b/dts/bindings/watchdog/infineon,xmc4xxx-watchdog.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2023, SLB +# SPDX-License-Identifier: Apache-2.0 + +description: Infineon XMC4xxx watchdog + +compatible: "infineon,xmc4xxx-watchdog" + +include: base.yaml + +properties: + reg: + required: true + + interrupts: + required: true diff --git a/dts/bindings/watchdog/nxp,s32-swt.yaml b/dts/bindings/watchdog/nxp,s32-swt.yaml index 25fbbaa2f30..39179aaf5bc 100644 --- a/dts/bindings/watchdog/nxp,s32-swt.yaml +++ b/dts/bindings/watchdog/nxp,s32-swt.yaml @@ -1,4 +1,4 @@ -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # SPDX-License-Identifier: Apache-2.0 description: Software Watchdog Timer (SWT) @@ -14,7 +14,5 @@ properties: interrupts: required: true - clock-frequency: - type: int + clocks: required: true - description: Software Watchdog Timer module clock frequency, in Hz. diff --git a/dts/bindings/wifi/infineon,airoc-wifi.yaml b/dts/bindings/wifi/infineon,airoc-wifi.yaml new file mode 100644 index 00000000000..9c93b238a4e --- /dev/null +++ b/dts/bindings/wifi/infineon,airoc-wifi.yaml @@ -0,0 +1,50 @@ +# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +description: | + AIROC Wi-Fi Connectivity. + + Example of enabling AIROC Wi-Fi device (for SDIO): + &sdhc0 { + status = "okay"; + + /* SDIO pins */ + pinctrl-0 = <&p2_4_sdio_cmd &p2_5_sdio_clk &p2_0_sdio_data0 + &p2_1_sdio_data1 &p2_2_sdio_data2 &p2_3_sdio_data3>; + pinctrl-names = "default"; + + /* Wifi configuration */ + airoc-wifi { + status = "okay"; + compatible = "infineon,airoc-wifi-sdio"; + + /* Wi-Fi control gpios */ + wifi-reg-on-gpios = <&gpio_prt2 6 GPIO_ACTIVE_HIGH>; + wifi-host-wake-gpios = <&gpio_prt0 4 GPIO_ACTIVE_HIGH>; + }; + }; + +compatible: "infineon,airoc-wifi" + +include: [base.yaml, pinctrl-device.yaml] + +properties: + wifi-reg-on-gpios: + description: | + Power-up/down gpio to control the internal regulators used + by the WiFi section of AIROC Wi-Fi device. + type: phandle-array + + wifi-host-wake-gpios: + description: | + Host wake-up gpio. Signal from the AIROC Wi-Fi device + to the host indicating that the device requires attention. + type: phandle-array + + wifi-dev-wake-gpios: + description: | + WiFi device wake-up gpio. Signal from the host to the + AIROC Wi-Fi device indicating that the host requires attention. + type: phandle-array diff --git a/dts/bindings/xen/xen,xen-4.15.yaml b/dts/bindings/xen/xen,xen-4.15.yaml deleted file mode 100644 index 7456450d3ad..00000000000 --- a/dts/bindings/xen/xen,xen-4.15.yaml +++ /dev/null @@ -1,11 +0,0 @@ -description: Xen Platform Control Registers - -compatible: "xen,xen-4.15" - -include: base.yaml - -properties: - reg: - required: true - interrupts: - required: true diff --git a/dts/bindings/xen/xen,xen.yaml b/dts/bindings/xen/xen,xen.yaml new file mode 100644 index 00000000000..1627f6d9340 --- /dev/null +++ b/dts/bindings/xen/xen,xen.yaml @@ -0,0 +1,11 @@ +description: Xen Platform Control Registers + +compatible: "xen,xen" + +include: base.yaml + +properties: + reg: + required: true + interrupts: + required: true diff --git a/dts/riscv/andes/andes_v5_ae350.dtsi b/dts/riscv/andes/andes_v5_ae350.dtsi index 4a9456520a1..7af3e25ef62 100644 --- a/dts/riscv/andes/andes_v5_ae350.dtsi +++ b/dts/riscv/andes/andes_v5_ae350.dtsi @@ -21,7 +21,7 @@ device_type = "cpu"; reg = <0>; status = "okay"; - riscv,isa = "rv32imafdcxandes"; + riscv,isa = "rv32gc_xandes"; mmu-type = "riscv,sv32"; clock-frequency = <60000000>; i-cache-line-size = <32>; @@ -38,7 +38,7 @@ device_type = "cpu"; reg = <1>; status = "okay"; - riscv,isa = "rv32imafdcxandes"; + riscv,isa = "rv32gc_xandes"; mmu-type = "riscv,sv32"; clock-frequency = <60000000>; i-cache-line-size = <32>; @@ -55,7 +55,7 @@ device_type = "cpu"; reg = <2>; status = "okay"; - riscv,isa = "rv32imafdcxandes"; + riscv,isa = "rv32gc_xandes"; mmu-type = "riscv,sv32"; clock-frequency = <60000000>; i-cache-line-size = <32>; @@ -72,7 +72,7 @@ device_type = "cpu"; reg = <3>; status = "okay"; - riscv,isa = "rv32imafdcxandes"; + riscv,isa = "rv32gc_xandes"; mmu-type = "riscv,sv32"; clock-frequency = <60000000>; i-cache-line-size = <32>; @@ -89,7 +89,7 @@ device_type = "cpu"; reg = <4>; status = "okay"; - riscv,isa = "rv32imafdcxandes"; + riscv,isa = "rv32gc_xandes"; mmu-type = "riscv,sv32"; clock-frequency = <60000000>; i-cache-line-size = <32>; @@ -106,7 +106,7 @@ device_type = "cpu"; reg = <5>; status = "okay"; - riscv,isa = "rv32imafdcxandes"; + riscv,isa = "rv32gc_xandes"; mmu-type = "riscv,sv32"; clock-frequency = <60000000>; i-cache-line-size = <32>; @@ -123,7 +123,7 @@ device_type = "cpu"; reg = <6>; status = "okay"; - riscv,isa = "rv32imafdcxandes"; + riscv,isa = "rv32gc_xandes"; mmu-type = "riscv,sv32"; clock-frequency = <60000000>; i-cache-line-size = <32>; @@ -140,7 +140,7 @@ device_type = "cpu"; reg = <7>; status = "okay"; - riscv,isa = "rv32imafdcxandes"; + riscv,isa = "rv32gc_xandes"; mmu-type = "riscv,sv32"; clock-frequency = <60000000>; i-cache-line-size = <32>; @@ -171,10 +171,7 @@ #address-cells = <1>; #interrupt-cells = <2>; interrupt-controller; - reg = < 0xe4000000 0x00001000 - 0xe4002000 0x00000800 - 0xe4200000 0x00010000 >; - reg-names = "prio", "irq_en", "reg"; + reg = <0xe4000000 0x04000000>; riscv,max-priority = <255>; riscv,ndev = <1023>; interrupts-extended = <&CPU0_intc 11 &CPU1_intc 11 @@ -278,6 +275,9 @@ reg-names = "control", "mem"; interrupts = <4 1>; interrupt-parent = <&plic0>; + dmas = <&dma0 0 0 0x009>, + <&dma0 1 1 0x00A>; + dma-names = "tx", "rx"; #address-cells = <1>; #size-cells = <0>; clock-frequency = <66000000>; @@ -290,6 +290,9 @@ reg-names = "control"; interrupts = <5 1>; interrupt-parent = <&plic0>; + dmas = <&dma0 2 2 0x009>, + <&dma0 3 3 0x00A>; + dma-names = "tx", "rx"; #address-cells = <1>; #size-cells = <0>; clock-frequency = <66000000>; @@ -302,6 +305,10 @@ interrupts = <10 1>; interrupt-parent = <&plic0>; dma-channels = <8>; + dma-requests = <16>; + chain-transfer = <1>; + #dma-cells = <3>; + status = "disabled"; }; eth0: eth@e0100000 { diff --git a/dts/riscv/efinix/sapphire_soc.dtsi b/dts/riscv/efinix/sapphire_soc.dtsi index c61eec170ed..75043c9dfbb 100644 --- a/dts/riscv/efinix/sapphire_soc.dtsi +++ b/dts/riscv/efinix/sapphire_soc.dtsi @@ -30,7 +30,7 @@ compatible = "riscv"; device_type = "cpu"; reg = <0>; - riscv,isa = "rv32imac"; + riscv,isa = "rv32ima_zicsr_zifencei"; status = "okay"; timebase-frequency = <100000000>; @@ -55,10 +55,7 @@ #interrupt-cells = <2>; interrupt-controller; interrupts-extended = <&hlic 11>; - reg = < 0xf8c00000 0x00001000 - 0xf8c02000 0x00000800 - 0xf8e00000 0x00010000 >; - reg-names = "prio", "irq_en", "reg"; + reg = <0xf8c00000 0x04000000>; riscv,max-priority = <3>; riscv,ndev = <32>; }; diff --git a/dts/riscv/espressif/esp32c3/esp32c3_common.dtsi b/dts/riscv/espressif/esp32c3/esp32c3_common.dtsi index 10fc17ac03a..3b2bb6d0781 100644 --- a/dts/riscv/espressif/esp32c3/esp32c3_common.dtsi +++ b/dts/riscv/espressif/esp32c3/esp32c3_common.dtsi @@ -32,6 +32,7 @@ cpu0: cpu@0 { device_type = "cpu"; compatible = "espressif,riscv"; + riscv,isa = "rv32imc_zicsr"; reg = <0>; cpu-power-states = <&light_sleep &deep_sleep>; }; @@ -217,7 +218,6 @@ interrupts = ; interrupt-parent = <&intc>; clocks = <&rtc ESP32_TWAI_MODULE>; - sjw = <1>; sample-point = <875>; status = "disabled"; }; diff --git a/dts/riscv/gigadevice/gd32vf103.dtsi b/dts/riscv/gigadevice/gd32vf103.dtsi index d4b5bb46d8a..c9f37db5180 100644 --- a/dts/riscv/gigadevice/gd32vf103.dtsi +++ b/dts/riscv/gigadevice/gd32vf103.dtsi @@ -25,6 +25,7 @@ clock-frequency = ; mcause-exception-mask = <0x7ff>; compatible = "nuclei,bumblebee"; + riscv,isa = "rv32imac_zicsr_zifencei"; reg = <0>; }; }; diff --git a/dts/riscv/ite/it81xx2.dtsi b/dts/riscv/ite/it81xx2.dtsi index b9e8ba4e69d..32d47861ee7 100644 --- a/dts/riscv/ite/it81xx2.dtsi +++ b/dts/riscv/ite/it81xx2.dtsi @@ -57,280 +57,284 @@ #address-cells = <1>; #size-cells = <1>; status = "okay"; + }; + + pinctrla: pinctrl@f01610 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01610 8>; /* GPCR */ + func3-gcr = ; + func3-en-mask = <0 0 0 0 + 0x02 0x02 0x10 0x0C >; + func4-gcr = ; + func4-en-mask = <0 0 0 0 + 0 0 0 0 >; + volt-sel = ; + volt-sel-mask = <0 0 0 0 + 0x1 0x02 0x20 0x40 >; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrlb: pinctrl@f01618 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01618 8>; /* GPCR */ + func3-gcr = <0xf016f5 0xf016f5 NO_FUNC NO_FUNC + NO_FUNC NO_FUNC NO_FUNC 0xf01600>; + func3-en-mask = <0x01 0x02 0 0 + 0 0 0 0x02 >; + func4-gcr = ; + func4-en-mask = <0 0 0 0 + 0 0 0 0x40 >; + volt-sel = ; + volt-sel-mask = <0 0 0 0x02 + 0x01 0x80 0x40 0x10 >; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrlc: pinctrl@f01620 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01620 8>; /* GPCR */ + func3-gcr = ; + func3-en-mask = <0 0 0 0x10 + 0 0x10 0 0x02 >; + func4-gcr = ; + func4-en-mask = <0 0 0 0 + 0 0 0 0x80 >; + volt-sel = <0xf016e7 0xf016e4 0xf016e4 NO_FUNC + 0xf016e9 NO_FUNC 0xf016e9 0xf016e4>; + volt-sel-mask = <0x80 0x20 0x10 0 + 0x04 0 0x08 0x08 >; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrld: pinctrl@f01628 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01628 8>; /* GPCR */ + func3-gcr = ; + func3-en-mask = <0 0 0 0 + 0 0x02 0 0 >; + func4-gcr = ; + func4-en-mask = <0 0 0 0 + 0 0 0 0 >; + volt-sel = <0xf016e4 0xf016e4 0xf016e4 0xf016e5 + 0xf016e5 0xf016e7 0xf016e7 0xf016e7>; + volt-sel-mask = <0x04 0x02 0x01 0x80 + 0x40 0x10 0x20 0x40 >; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrle: pinctrl@f01630 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01630 8>; /* GPCR */ + func3-gcr = <0xf02032 NO_FUNC NO_FUNC NO_FUNC + NO_FUNC 0xf016f0 NO_FUNC 0xf02032>; + func3-en-mask = <0x01 0 0 0 + 0 0x08 0 0x01 >; + func4-gcr = <0xf016f3 NO_FUNC NO_FUNC NO_FUNC + NO_FUNC NO_FUNC NO_FUNC NO_FUNC >; + func4-en-mask = <0x01 0 0 0 + 0 0 0 0 >; + volt-sel = <0xf016e5 0xf016d4 0xf016d4 NO_FUNC + 0xf016e7 0xf016e7 0xf016e5 0xf016e5>; + volt-sel-mask = <0x20 0x40 0x80 0 + 0x04 0x08 0x10 0x08 >; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrlf: pinctrl@f01638 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01638 8>; /* GPCR */ + func3-gcr = ; + func3-en-mask = <0 0 0x02 0x02 + 0 0 0x10 0x10 >; + func4-gcr = ; + func4-en-mask = <0 0 0x40 0x40 + 0 0 0 0 >; + volt-sel = <0xf016d4 0xf016d4 0xf016e5 0xf016e5 + 0xf016e5 0xf016e6 0xf016e6 0xf016e6>; + volt-sel-mask = <0x10 0x20 0x04 0x02 + 0x01 0x80 0x40 0x20 >; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrlg: pinctrl@f01640 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01640 8>; /* GPCR */ + func3-gcr = <0xf016f0 0xf016f0 0xf016f0 NO_FUNC + NO_FUNC NO_FUNC 0xf016f0 NO_FUNC>; + func3-en-mask = <0x20 0x08 0x10 0 + 0 0 0x02 0 >; + func4-gcr = ; + func4-en-mask = <0 0 0 0 + 0 0 0 0 >; + volt-sel = <0xf016d4 0xf016e6 0xf016d4 NO_FUNC + NO_FUNC NO_FUNC 0xf016e6 NO_FUNC>; + volt-sel-mask = <0x04 0x10 0x08 0 + 0 0 0x08 0 >; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrlh: pinctrl@f01648 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01648 8>; /* GPCR */ + func3-gcr = ; + func3-en-mask = <0 0x20 0x20 0 + 0 0x04 0x08 0 >; + func3-ext = ; + func3-ext-mask = <0 0 0 0 + 0 0x01 0x01 0 >; + func4-gcr = ; + func4-en-mask = <0 0x04 0x08 0 + 0 0 0 0 >; + volt-sel = <0xf016e6 0xf016e6 0xf016e6 NO_FUNC + NO_FUNC 0xf016d3 0xf016d4 NO_FUNC>; + volt-sel-mask = <0x04 0x02 0x01 0 + 0 0x80 0x01 0 >; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrli: pinctrl@f01650 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01650 8>; /* GPCR */ + func3-gcr = ; + func3-en-mask = <0 0 0 0 + 0 0x08 0x08 0x08 >; + func4-gcr = ; + func4-en-mask = <0 0 0 0 + 0 0 0 0 >; + volt-sel = <0xf016d3 0xf016e8 0xf016e8 0xf016e8 + 0xf016e8 0xf016d3 0xf016d3 0xf016d3>; + volt-sel-mask = <0x08 0x10 0x20 0x40 + 0x80 0x10 0x20 0x40 >; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrlj: pinctrl@f01658 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01658 8>; /* GPCR */ + func3-gcr = <0xf016f4 NO_FUNC 0xf016f4 0xf016f4 + 0xf016f0 0xf016f0 NO_FUNC NO_FUNC>; + func3-en-mask = <0x01 0 0x01 0x02 + 0x02 0x03 0 0 >; + func4-gcr = ; + func4-en-mask = <0 0 0 0 + 0 0 0 0 >; + volt-sel = <0xf016e8 0xf016e8 0xf016e8 0xf016e8 + 0xf016d3 0xf016d3 0xf016d3 0xf016d7>; + volt-sel-mask = <0x01 0x02 0x04 0x08 + 0x01 0x02 0x04 0x04 >; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrlk: pinctrl@f01690 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01690 8>; /* GPCR */ + func3-gcr = ; + func3-en-mask = <0 0 0 0 + 0 0 0 0 >; + func4-gcr = ; + func4-en-mask = <0 0 0 0 + 0 0 0 0 >; + volt-sel = <0xf016d2 0xf016d2 0xf016d2 0xf016d2 + 0xf016d2 0xf016d2 0xf016d2 0xf016d2>; + volt-sel-mask = <0x01 0x02 0x04 0x08 + 0x10 0x20 0x40 0x80 >; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrll: pinctrl@f01698 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01698 8>; /* GPCR */ + func3-gcr = ; + func3-en-mask = <0 0 0 0 + 0 0 0 0 >; + func4-gcr = ; + func4-en-mask = <0 0 0 0 + 0 0 0 0 >; + volt-sel = <0xf016d1 0xf016d1 0xf016d1 0xf016d1 + 0xf016d1 0xf016d1 0xf016d1 0xf016d1>; + volt-sel-mask = <0x01 0x02 0x04 0x08 + 0x10 0x20 0x40 0x80 >; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrlm: pinctrl@f016a0 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f016a0 8>; /* GPCR */ + func3-gcr = ; + func3-en-mask = <0 0 0 0 + 0 0 0 0 >; + func4-gcr = ; + func4-en-mask = <0 0 0 0 + 0 0 0 0 >; + volt-sel = <0xf016ed 0xf016ed 0xf016ed 0xf016ed + 0xf016ed 0xf016ed 0xf016ed NO_FUNC >; + volt-sel-mask = <0x10 0x10 0x10 0x10 + 0x10 0x10 0x10 0 >; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrlksi: pinctrl@f01d06 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01d06 1 /* KSIGCTRL */ + 0x00f01d05 1>; /* KSICTRL */ + pp-od-mask = ; + pullup-mask = ; + #pinmux-cells = <2>; + }; + + pinctrlksoh: pinctrl@f01d0a { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01d0a 1 /* KSOHGCTRL */ + 0x00f01d02 1>; /* KSOCTRL */ + pp-od-mask = ; + pullup-mask = ; + #pinmux-cells = <2>; + }; - pinctrla: pinctrl@f01610 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01610 8>; /* GPCR */ - func3-gcr = ; - func3-en-mask = <0 0 0 0 - 0x02 0x02 0x10 0x0C >; - func4-gcr = ; - func4-en-mask = <0 0 0 0 - 0 0 0 0 >; - volt-sel = ; - volt-sel-mask = <0 0 0 0 - 0x1 0x02 0x20 0x40 >; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrlb: pinctrl@f01618 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01618 8>; /* GPCR */ - func3-gcr = <0xf016f5 0xf016f5 NO_FUNC NO_FUNC - NO_FUNC NO_FUNC NO_FUNC 0xf01600>; - func3-en-mask = <0x01 0x02 0 0 - 0 0 0 0x02 >; - func4-gcr = ; - func4-en-mask = <0 0 0 0 - 0 0 0 0x40 >; - volt-sel = ; - volt-sel-mask = <0 0 0 0x02 - 0x01 0x80 0x40 0x10 >; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrlc: pinctrl@f01620 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01620 8>; /* GPCR */ - func3-gcr = ; - func3-en-mask = <0 0 0 0x10 - 0 0x10 0 0x02 >; - func4-gcr = ; - func4-en-mask = <0 0 0 0 - 0 0 0 0x80 >; - volt-sel = <0xf016e7 0xf016e4 0xf016e4 NO_FUNC - 0xf016e9 NO_FUNC 0xf016e9 0xf016e4>; - volt-sel-mask = <0x80 0x20 0x10 0 - 0x04 0 0x08 0x08 >; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrld: pinctrl@f01628 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01628 8>; /* GPCR */ - func3-gcr = ; - func3-en-mask = <0 0 0 0 - 0 0x02 0 0 >; - func4-gcr = ; - func4-en-mask = <0 0 0 0 - 0 0 0 0 >; - volt-sel = <0xf016e4 0xf016e4 0xf016e4 0xf016e5 - 0xf016e5 0xf016e7 0xf016e7 0xf016e7>; - volt-sel-mask = <0x04 0x02 0x01 0x80 - 0x40 0x10 0x20 0x40 >; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrle: pinctrl@f01630 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01630 8>; /* GPCR */ - func3-gcr = <0xf02032 NO_FUNC NO_FUNC NO_FUNC - NO_FUNC 0xf016f0 NO_FUNC 0xf02032>; - func3-en-mask = <0x01 0 0 0 - 0 0x08 0 0x01 >; - func4-gcr = <0xf016f3 NO_FUNC NO_FUNC NO_FUNC - NO_FUNC NO_FUNC NO_FUNC NO_FUNC >; - func4-en-mask = <0x01 0 0 0 - 0 0 0 0 >; - volt-sel = <0xf016e5 0xf016d4 0xf016d4 NO_FUNC - 0xf016e7 0xf016e7 0xf016e5 0xf016e5>; - volt-sel-mask = <0x20 0x40 0x80 0 - 0x04 0x08 0x10 0x08 >; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrlf: pinctrl@f01638 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01638 8>; /* GPCR */ - func3-gcr = ; - func3-en-mask = <0 0 0x02 0x02 - 0 0 0x10 0x10 >; - func4-gcr = ; - func4-en-mask = <0 0 0x40 0x40 - 0 0 0 0 >; - volt-sel = <0xf016d4 0xf016d4 0xf016e5 0xf016e5 - 0xf016e5 0xf016e6 0xf016e6 0xf016e6>; - volt-sel-mask = <0x10 0x20 0x04 0x02 - 0x01 0x80 0x40 0x20 >; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrlg: pinctrl@f01640 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01640 8>; /* GPCR */ - func3-gcr = <0xf016f0 0xf016f0 0xf016f0 NO_FUNC - NO_FUNC NO_FUNC 0xf016f0 NO_FUNC>; - func3-en-mask = <0x20 0x08 0x10 0 - 0 0 0x02 0 >; - func4-gcr = ; - func4-en-mask = <0 0 0 0 - 0 0 0 0 >; - volt-sel = <0xf016d4 0xf016e6 0xf016d4 NO_FUNC - NO_FUNC NO_FUNC 0xf016e6 NO_FUNC>; - volt-sel-mask = <0x04 0x10 0x08 0 - 0 0 0x08 0 >; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrlh: pinctrl@f01648 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01648 8>; /* GPCR */ - func3-gcr = ; - func3-en-mask = <0 0x20 0x20 0 - 0 0x04 0x08 0 >; - func4-gcr = ; - func4-en-mask = <0 0x04 0x08 0 - 0 0 0 0 >; - volt-sel = <0xf016e6 0xf016e6 0xf016e6 NO_FUNC - NO_FUNC 0xf016d3 0xf016d4 NO_FUNC>; - volt-sel-mask = <0x04 0x02 0x01 0 - 0 0x80 0x01 0 >; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrli: pinctrl@f01650 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01650 8>; /* GPCR */ - func3-gcr = ; - func3-en-mask = <0 0 0 0 - 0 0x08 0x08 0x08 >; - func4-gcr = ; - func4-en-mask = <0 0 0 0 - 0 0 0 0 >; - volt-sel = <0xf016d3 0xf016e8 0xf016e8 0xf016e8 - 0xf016e8 0xf016d3 0xf016d3 0xf016d3>; - volt-sel-mask = <0x08 0x10 0x20 0x40 - 0x80 0x10 0x20 0x40 >; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrlj: pinctrl@f01658 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01658 8>; /* GPCR */ - func3-gcr = <0xf016f4 NO_FUNC 0xf016f4 0xf016f4 - 0xf016f0 0xf016f0 NO_FUNC NO_FUNC>; - func3-en-mask = <0x01 0 0x01 0x02 - 0x02 0x03 0 0 >; - func4-gcr = ; - func4-en-mask = <0 0 0 0 - 0 0 0 0 >; - volt-sel = <0xf016e8 0xf016e8 0xf016e8 0xf016e8 - 0xf016d3 0xf016d3 0xf016d3 0xf016d7>; - volt-sel-mask = <0x01 0x02 0x04 0x08 - 0x01 0x02 0x04 0x04 >; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrlk: pinctrl@f01690 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01690 8>; /* GPCR */ - func3-gcr = ; - func3-en-mask = <0 0 0 0 - 0 0 0 0 >; - func4-gcr = ; - func4-en-mask = <0 0 0 0 - 0 0 0 0 >; - volt-sel = <0xf016d2 0xf016d2 0xf016d2 0xf016d2 - 0xf016d2 0xf016d2 0xf016d2 0xf016d2>; - volt-sel-mask = <0x01 0x02 0x04 0x08 - 0x10 0x20 0x40 0x80 >; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrll: pinctrl@f01698 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01698 8>; /* GPCR */ - func3-gcr = ; - func3-en-mask = <0 0 0 0 - 0 0 0 0 >; - func4-gcr = ; - func4-en-mask = <0 0 0 0 - 0 0 0 0 >; - volt-sel = <0xf016d1 0xf016d1 0xf016d1 0xf016d1 - 0xf016d1 0xf016d1 0xf016d1 0xf016d1>; - volt-sel-mask = <0x01 0x02 0x04 0x08 - 0x10 0x20 0x40 0x80 >; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrlm: pinctrl@f016a0 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f016a0 8>; /* GPCR */ - func3-gcr = ; - func3-en-mask = <0 0 0 0 - 0 0 0 0 >; - func4-gcr = ; - func4-en-mask = <0 0 0 0 - 0 0 0 0 >; - volt-sel = <0xf016ed 0xf016ed 0xf016ed 0xf016ed - 0xf016ed 0xf016ed 0xf016ed NO_FUNC >; - volt-sel-mask = <0x10 0x10 0x10 0x10 - 0x10 0x10 0x10 0 >; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrlksi: pinctrl@f01d06 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01d06 1 /* KSIGCTRL */ - 0x00f01d05 1>; /* KSICTRL */ - pp-od-mask = ; - pullup-mask = ; - #pinmux-cells = <2>; - }; - - pinctrlksoh: pinctrl@f01d0a { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01d0a 1 /* KSOHGCTRL */ - 0x00f01d02 1>; /* KSOCTRL */ - pp-od-mask = ; - pullup-mask = ; - #pinmux-cells = <2>; - }; - - pinctrlksol: pinctrl@f01d0d { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01d0d 1 /* KSOLGCTRL */ - 0x00f01d02 1>; /* KSOCTRL */ - pp-od-mask = ; - pullup-mask = ; - #pinmux-cells = <2>; - }; + pinctrlksol: pinctrl@f01d0d { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01d0d 1 /* KSOLGCTRL */ + 0x00f01d02 1>; /* KSOCTRL */ + pp-od-mask = ; + pullup-mask = ; + #pinmux-cells = <2>; }; i2c0: i2c@f01c40 { @@ -343,6 +347,7 @@ interrupt-parent = <&intc>; status = "disabled"; port-num = ; + channel-switch-sel = ; scl-gpios = <&gpiob 3 0>; sda-gpios = <&gpiob 4 0>; clock-gate-offset = ; @@ -359,6 +364,7 @@ interrupt-parent = <&intc>; status = "disabled"; port-num = ; + channel-switch-sel = ; scl-gpios = <&gpioc 1 0>; sda-gpios = <&gpioc 2 0>; clock-gate-offset = ; @@ -375,6 +381,7 @@ interrupt-parent = <&intc>; status = "disabled"; port-num = ; + channel-switch-sel = ; scl-gpios = <&gpiof 6 0>; sda-gpios = <&gpiof 7 0>; clock-gate-offset = ; @@ -390,6 +397,7 @@ interrupt-parent = <&intc>; status = "disabled"; port-num = ; + channel-switch-sel = ; scl-gpios = <&gpioh 1 0>; sda-gpios = <&gpioh 2 0>; clock-gate-offset = ; @@ -404,6 +412,7 @@ interrupt-parent = <&intc>; status = "disabled"; port-num = ; + channel-switch-sel = ; scl-gpios = <&gpioe 0 0>; sda-gpios = <&gpioe 7 0>; clock-gate-offset = ; @@ -418,6 +427,7 @@ interrupt-parent = <&intc>; status = "disabled"; port-num = ; + channel-switch-sel = ; scl-gpios = <&gpioa 4 0>; sda-gpios = <&gpioa 5 0>; clock-gate-offset = ; diff --git a/dts/riscv/ite/it82xx2.dtsi b/dts/riscv/ite/it82xx2.dtsi index 7d9089005aa..6b3eea97aa9 100644 --- a/dts/riscv/ite/it82xx2.dtsi +++ b/dts/riscv/ite/it82xx2.dtsi @@ -440,280 +440,280 @@ #address-cells = <1>; #size-cells = <1>; status = "okay"; + }; - pinctrla: pinctrl@f01660 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01660 8>; /* GPCR */ - func3-gcr = ; - func3-en-mask = <0 0 0 0 - 0x02 0x02 0x10 0x0C >; - func4-gcr = ; - func4-en-mask = <0 0 0 0 - 0 0 0 0 >; - volt-sel = <0xf01648 0xf01648 0xf01648 0xf01648 - 0xf01648 0xf01648 0xf01648 0xf01648>; - volt-sel-mask = ; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrlb: pinctrl@f01668 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01668 8>; /* GPCR */ - func3-gcr = <0xf03e15 0xf03e15 0xf03e16 NO_FUNC - NO_FUNC 0xf03e16 NO_FUNC NO_FUNC>; - func3-en-mask = <0x01 0x02 0x40 0 - 0 0x40 0 0 >; - func4-gcr = ; - func4-en-mask = <0 0 0 0 - 0 0 0 0 >; - volt-sel = <0xf01649 0xf01649 0xf01649 0xf01649 - 0xf01649 0xf01649 0xf01649 NO_FUNC>; - volt-sel-mask = ; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrlc: pinctrl@f01670 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01670 8>; /* GPCR */ - func3-gcr = ; - func3-en-mask = <0 0 0 0x10 - 0 0x10 0 0x02 >; - func4-gcr = ; - func4-en-mask = <0 0 0 0 - 0 0 0 0x80 >; - volt-sel = <0xf0164a 0xf0164a 0xf0164a 0xf0164a - 0xf0164a 0xf0164a 0xf0164a 0xf0164a>; - volt-sel-mask = ; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrld: pinctrl@f01678 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01678 8>; /* GPCR */ - func3-gcr = ; - func3-en-mask = <0 0 0 0 - 0 0x02 0 0 >; - func4-gcr = <0xf03e16 NO_FUNC NO_FUNC NO_FUNC - NO_FUNC NO_FUNC NO_FUNC NO_FUNC>; - func4-en-mask = <0x80 0 0 0 - 0 0 0 0 >; - volt-sel = <0xf0164b 0xf0164b 0xf0164b 0xf0164b - 0xf0164b 0xf0164b 0xf0164b 0xf0164b>; - volt-sel-mask = ; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrle: pinctrl@f01680 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01680 8>; /* GPCR */ - func3-gcr = <0xf02032 0xf03e16 0xf03e16 NO_FUNC - NO_FUNC 0xf03e10 NO_FUNC 0xf02032>; - func3-en-mask = <0x01 0x20 0x20 0 - 0 0x08 0 0x01 >; - func4-gcr = <0xf03e13 NO_FUNC NO_FUNC NO_FUNC - NO_FUNC NO_FUNC NO_FUNC NO_FUNC >; - func4-en-mask = <0x01 0 0 0 - 0 0 0 0 >; - volt-sel = <0xf0164c 0xf0164c 0xf0164c 0xf0164c - 0xf0164c 0xf0164c 0xf0164c 0xf0164c>; - volt-sel-mask = ; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrlf: pinctrl@f01688 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01688 8>; /* GPCR */ - func3-gcr = <0xf03e15 0xf03e15 0xf03e10 0xf03e10 - NO_FUNC NO_FUNC 0xf03e11 NO_FUNC>; - func3-en-mask = <0x04 0x08 0x02 0x02 - 0 0 0x10 0 >; - func4-gcr = ; - func4-en-mask = <0 0 0 0 - 0 0 0 0 >; - volt-sel = <0xf0164d 0xf0164d 0xf0164d 0xf0164d - 0xf0164d 0xf0164d 0xf0164d 0xf0164d>; - volt-sel-mask = ; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrlg: pinctrl@f01690 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01690 8>; /* GPCR */ - func3-gcr = <0xf03e10 0xf03e10 0xf03e10 NO_FUNC - NO_FUNC NO_FUNC 0xf03e10 NO_FUNC>; - func3-en-mask = <0x20 0x08 0x10 0 - 0 0 0x02 0 >; - func4-gcr = ; - func4-en-mask = <0 0 0 0 - 0 0 0 0 >; - volt-sel = <0xf0164e 0xf0164e 0xf0164e NO_FUNC - NO_FUNC NO_FUNC 0xf0164e NO_FUNC >; - volt-sel-mask = ; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrlh: pinctrl@f01698 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01698 8>; /* GPCR */ - func3-gcr = ; - func3-en-mask = <0 0x20 0x20 0 - 0 0 0 0 >; - func4-gcr = ; - func4-en-mask = <0 0 0 0 - 0 0 0 0 >; - volt-sel = <0xf0164f 0xf0164f 0xf0164f 0xf0164f - 0xf0164f 0xf0164f 0xf0164f NO_FUNC>; - volt-sel-mask = ; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrli: pinctrl@f016a0 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f016a0 8>; /* GPCR */ - func3-gcr = ; - func3-en-mask = <0 0 0 0 - 0 0x08 0x08 0x08 >; - func4-gcr = ; - func4-en-mask = <0 0 0 0 - 0 0 0 0 >; - volt-sel = <0xf01650 0xf01650 0xf01650 0xf01650 - 0xf01650 0xf01650 0xf01650 0xf01650>; - volt-sel-mask = ; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrlj: pinctrl@f016a8 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f016a8 8>; /* GPCR */ - func3-gcr = <0xf03e14 NO_FUNC 0xf03e14 0xf03e14 - 0xf03e10 0xf03e10 NO_FUNC NO_FUNC>; - func3-en-mask = <0x01 0 0x01 0x02 - 0x02 0x03 0 0 >; - func4-gcr = ; - func4-en-mask = <0 0 0 0 - 0 0 0 0 >; - volt-sel = <0xf01651 0xf01651 0xf01651 0xf01651 - 0xf01651 0xf01651 NO_FUNC NO_FUNC >; - volt-sel-mask = ; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrlk: pinctrl@f016b0 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f016b0 8>; /* GPCR */ - func3-gcr = ; - func3-en-mask = <0 0 0 0 - 0 0 0 0 >; - func4-gcr = ; - func4-en-mask = <0 0 0 0 - 0 0 0 0 >; - volt-sel = <0xf01652 0xf01652 0xf01652 0xf01652 - 0xf01652 0xf01652 0xf01652 0xf01652>; - volt-sel-mask = ; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrll: pinctrl@f016b8 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f016b8 8>; /* GPCR */ - func3-gcr = ; - func3-en-mask = <0 0 0 0 - 0 0 0 0 >; - func4-gcr = ; - func4-en-mask = <0 0 0 0 - 0 0 0 0 >; - volt-sel = <0xf01653 0xf01653 0xf01653 0xf01653 - 0xf01653 0xf01653 0xf01653 0xf01653>; - volt-sel-mask = ; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrlm: pinctrl@f016c0 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f016c0 8>; /* GPCR */ - func3-gcr = ; - func3-en-mask = <0 0 0 0 - 0 0 0 0 >; - func4-gcr = ; - func4-en-mask = <0 0 0 0 - 0 0 0 0 >; - volt-sel = <0xf03e2d 0xf03e2d 0xf03e2d 0xf03e2d - 0xf03e2d 0xf03e2d 0xf03e2d NO_FUNC >; - volt-sel-mask = ; - #pinmux-cells = <2>; - gpio-group; - }; - - pinctrlksi: pinctrl@f01d40 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01d40 8 /* KSIGCTRL */ - 0x00f01d05 1>; /* KSICTRL */ - pp-od-mask = ; - pullup-mask = ; - #pinmux-cells = <2>; - }; - - pinctrlksol: pinctrl@f01d48 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01d48 8 /* KSOLGCTRL */ - 0x00f01d02 1>; /* KSOCTRL */ - pp-od-mask = ; - pullup-mask = ; - #pinmux-cells = <2>; - }; - - pinctrlksoh: pinctrl@f01d50 { - compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01d50 8 /* KSOHGCTRL */ - 0x00f01d02 1>; /* KSOCTRL */ - pp-od-mask = ; - pullup-mask = ; - #pinmux-cells = <2>; - }; + pinctrla: pinctrl@f01660 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01660 8>; /* GPCR */ + func3-gcr = ; + func3-en-mask = <0 0 0 0 + 0x02 0x02 0x10 0x0C >; + func4-gcr = ; + func4-en-mask = <0 0 0 0 + 0 0 0 0 >; + volt-sel = <0xf01648 0xf01648 0xf01648 0xf01648 + 0xf01648 0xf01648 0xf01648 0xf01648>; + volt-sel-mask = ; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrlb: pinctrl@f01668 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01668 8>; /* GPCR */ + func3-gcr = <0xf03e15 0xf03e15 0xf03e16 NO_FUNC + NO_FUNC 0xf03e16 NO_FUNC NO_FUNC>; + func3-en-mask = <0x01 0x02 0x40 0 + 0 0x40 0 0 >; + func4-gcr = ; + func4-en-mask = <0 0 0 0 + 0 0 0 0 >; + volt-sel = <0xf01649 0xf01649 0xf01649 0xf01649 + 0xf01649 0xf01649 0xf01649 NO_FUNC>; + volt-sel-mask = ; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrlc: pinctrl@f01670 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01670 8>; /* GPCR */ + func3-gcr = ; + func3-en-mask = <0 0 0 0x10 + 0 0x10 0 0x02 >; + func4-gcr = ; + func4-en-mask = <0 0 0 0 + 0 0 0 0x80 >; + volt-sel = <0xf0164a 0xf0164a 0xf0164a 0xf0164a + 0xf0164a 0xf0164a 0xf0164a 0xf0164a>; + volt-sel-mask = ; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrld: pinctrl@f01678 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01678 8>; /* GPCR */ + func3-gcr = ; + func3-en-mask = <0 0 0 0 + 0 0x02 0 0 >; + func4-gcr = <0xf03e16 NO_FUNC NO_FUNC NO_FUNC + NO_FUNC NO_FUNC NO_FUNC NO_FUNC>; + func4-en-mask = <0x80 0 0 0 + 0 0 0 0 >; + volt-sel = <0xf0164b 0xf0164b 0xf0164b 0xf0164b + 0xf0164b 0xf0164b 0xf0164b 0xf0164b>; + volt-sel-mask = ; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrle: pinctrl@f01680 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01680 8>; /* GPCR */ + func3-gcr = <0xf02032 0xf03e16 0xf03e16 NO_FUNC + NO_FUNC 0xf03e10 NO_FUNC 0xf02032>; + func3-en-mask = <0x01 0x20 0x20 0 + 0 0x08 0 0x01 >; + func4-gcr = <0xf03e13 NO_FUNC NO_FUNC NO_FUNC + NO_FUNC NO_FUNC NO_FUNC NO_FUNC >; + func4-en-mask = <0x01 0 0 0 + 0 0 0 0 >; + volt-sel = <0xf0164c 0xf0164c 0xf0164c 0xf0164c + 0xf0164c 0xf0164c 0xf0164c 0xf0164c>; + volt-sel-mask = ; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrlf: pinctrl@f01688 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01688 8>; /* GPCR */ + func3-gcr = <0xf03e15 0xf03e15 0xf03e10 0xf03e10 + NO_FUNC NO_FUNC 0xf03e11 NO_FUNC>; + func3-en-mask = <0x04 0x08 0x02 0x02 + 0 0 0x10 0 >; + func4-gcr = ; + func4-en-mask = <0 0 0 0 + 0 0 0 0 >; + volt-sel = <0xf0164d 0xf0164d 0xf0164d 0xf0164d + 0xf0164d 0xf0164d 0xf0164d 0xf0164d>; + volt-sel-mask = ; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrlg: pinctrl@f01690 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01690 8>; /* GPCR */ + func3-gcr = <0xf03e10 0xf03e10 0xf03e10 NO_FUNC + NO_FUNC NO_FUNC 0xf03e10 NO_FUNC>; + func3-en-mask = <0x20 0x08 0x10 0 + 0 0 0x02 0 >; + func4-gcr = ; + func4-en-mask = <0 0 0 0 + 0 0 0 0 >; + volt-sel = <0xf0164e 0xf0164e 0xf0164e NO_FUNC + NO_FUNC NO_FUNC 0xf0164e NO_FUNC >; + volt-sel-mask = ; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrlh: pinctrl@f01698 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01698 8>; /* GPCR */ + func3-gcr = ; + func3-en-mask = <0 0x20 0x20 0 + 0 0 0 0 >; + func4-gcr = ; + func4-en-mask = <0 0 0 0 + 0 0 0 0 >; + volt-sel = <0xf0164f 0xf0164f 0xf0164f 0xf0164f + 0xf0164f 0xf0164f 0xf0164f NO_FUNC>; + volt-sel-mask = ; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrli: pinctrl@f016a0 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f016a0 8>; /* GPCR */ + func3-gcr = ; + func3-en-mask = <0 0 0 0 + 0 0x08 0x08 0x08 >; + func4-gcr = ; + func4-en-mask = <0 0 0 0 + 0 0 0 0 >; + volt-sel = <0xf01650 0xf01650 0xf01650 0xf01650 + 0xf01650 0xf01650 0xf01650 0xf01650>; + volt-sel-mask = ; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrlj: pinctrl@f016a8 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f016a8 8>; /* GPCR */ + func3-gcr = <0xf03e14 NO_FUNC 0xf03e14 0xf03e14 + 0xf03e10 0xf03e10 NO_FUNC NO_FUNC>; + func3-en-mask = <0x01 0 0x01 0x02 + 0x02 0x03 0 0 >; + func4-gcr = ; + func4-en-mask = <0 0 0 0 + 0 0 0 0 >; + volt-sel = <0xf01651 0xf01651 0xf01651 0xf01651 + 0xf01651 0xf01651 NO_FUNC NO_FUNC >; + volt-sel-mask = ; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrlk: pinctrl@f016b0 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f016b0 8>; /* GPCR */ + func3-gcr = ; + func3-en-mask = <0 0 0 0 + 0 0 0 0 >; + func4-gcr = ; + func4-en-mask = <0 0 0 0 + 0 0 0 0 >; + volt-sel = <0xf01652 0xf01652 0xf01652 0xf01652 + 0xf01652 0xf01652 0xf01652 0xf01652>; + volt-sel-mask = ; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrll: pinctrl@f016b8 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f016b8 8>; /* GPCR */ + func3-gcr = ; + func3-en-mask = <0 0 0 0 + 0 0 0 0 >; + func4-gcr = ; + func4-en-mask = <0 0 0 0 + 0 0 0 0 >; + volt-sel = <0xf01653 0xf01653 0xf01653 0xf01653 + 0xf01653 0xf01653 0xf01653 0xf01653>; + volt-sel-mask = ; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrlm: pinctrl@f016c0 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f016c0 8>; /* GPCR */ + func3-gcr = ; + func3-en-mask = <0 0 0 0 + 0 0 0 0 >; + func4-gcr = ; + func4-en-mask = <0 0 0 0 + 0 0 0 0 >; + volt-sel = <0xf03e2d 0xf03e2d 0xf03e2d 0xf03e2d + 0xf03e2d 0xf03e2d 0xf03e2d NO_FUNC >; + volt-sel-mask = ; + #pinmux-cells = <2>; + gpio-group; + }; + + pinctrlksi: pinctrl@f01d40 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01d40 8 /* KSIGCTRL */ + 0x00f01d05 1>; /* KSICTRL */ + pp-od-mask = ; + pullup-mask = ; + #pinmux-cells = <2>; + }; + + pinctrlksol: pinctrl@f01d48 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01d48 8 /* KSOLGCTRL */ + 0x00f01d02 1>; /* KSOCTRL */ + pp-od-mask = ; + pullup-mask = ; + #pinmux-cells = <2>; + }; + + pinctrlksoh: pinctrl@f01d50 { + compatible = "ite,it8xxx2-pinctrl-func"; + reg = <0x00f01d50 8 /* KSOHGCTRL */ + 0x00f01d02 1>; /* KSOCTRL */ + pp-od-mask = ; + pullup-mask = ; + #pinmux-cells = <2>; }; wuc1: wakeup-controller@f01b00 { @@ -885,6 +885,7 @@ interrupt-parent = <&intc>; status = "disabled"; port-num = ; + channel-switch-sel = ; scl-gpios = <&gpiob 3 0>; sda-gpios = <&gpiob 4 0>; clock-gate-offset = ; @@ -899,6 +900,7 @@ interrupt-parent = <&intc>; status = "disabled"; port-num = ; + channel-switch-sel = ; scl-gpios = <&gpioc 1 0>; sda-gpios = <&gpioc 2 0>; clock-gate-offset = ; @@ -913,6 +915,7 @@ interrupt-parent = <&intc>; status = "disabled"; port-num = ; + channel-switch-sel = ; scl-gpios = <&gpiof 6 0>; sda-gpios = <&gpiof 7 0>; clock-gate-offset = ; @@ -927,6 +930,7 @@ interrupt-parent = <&intc>; status = "disabled"; port-num = ; + channel-switch-sel = ; scl-gpios = <&gpioh 1 0>; sda-gpios = <&gpioh 2 0>; clock-gate-offset = ; @@ -941,6 +945,7 @@ interrupt-parent = <&intc>; status = "disabled"; port-num = ; + channel-switch-sel = ; scl-gpios = <&gpioe 0 0>; sda-gpios = <&gpioe 7 0>; clock-gate-offset = ; @@ -955,6 +960,7 @@ interrupt-parent = <&intc>; status = "disabled"; port-num = ; + channel-switch-sel = ; scl-gpios = <&gpioa 4 0>; sda-gpios = <&gpioa 5 0>; clock-gate-offset = ; diff --git a/dts/riscv/ite/it8xxx2-pinctrl-map.dtsi b/dts/riscv/ite/it8xxx2-pinctrl-map.dtsi index 6e4ab0e6fac..b553c4fee8a 100644 --- a/dts/riscv/ite/it8xxx2-pinctrl-map.dtsi +++ b/dts/riscv/ite/it8xxx2-pinctrl-map.dtsi @@ -383,6 +383,12 @@ uart2_tx_gph2_default: uart2_tx_gph2_default { pinmuxs = <&pinctrlh 2 IT8XXX2_ALT_FUNC_4>; }; + uart2_rx_gph5_default: uart2_rx_gph5_default { + pinmuxs = <&pinctrlh 5 IT8XXX2_ALT_FUNC_3>; + }; + uart2_tx_gph6_default: uart2_tx_gph6_default { + pinmuxs = <&pinctrlh 6 IT8XXX2_ALT_FUNC_3>; + }; uart2_rx_gpf0_default: uart2_rx_gpf0_default { pinmuxs = <&pinctrlf 0 IT8XXX2_ALT_FUNC_3>; }; diff --git a/dts/riscv/ite/it8xxx2.dtsi b/dts/riscv/ite/it8xxx2.dtsi index c0e5933346d..454e9c0c177 100644 --- a/dts/riscv/ite/it8xxx2.dtsi +++ b/dts/riscv/ite/it8xxx2.dtsi @@ -29,6 +29,7 @@ #size-cells = <0>; cpu0: cpu@0 { compatible = "ite,riscv-ite"; + riscv,isa = "rv32imafc_zifencei"; device_type = "cpu"; reg = <0>; cpu-power-states = <&standby>; @@ -106,7 +107,7 @@ reg = <0x00f02700 0x0020>; status = "disabled"; current-speed = <115200>; - clock-frequency = <1804800>; + clock-frequency = <1843200>; interrupts = <38 IRQ_TYPE_EDGE_RISING>; interrupt-parent = <&intc>; reg-shift = <0>; @@ -116,7 +117,7 @@ reg = <0x00f02800 0x0020>; status = "disabled"; current-speed = <460800>; - clock-frequency = <1804800>; + clock-frequency = <1843200>; interrupts = <39 IRQ_TYPE_EDGE_RISING>; interrupt-parent = <&intc>; reg-shift = <0>; @@ -690,8 +691,8 @@ status = "disabled"; }; - kscan0: kscan@f01d00 { - compatible = "ite,it8xxx2-kscan"; + kbd: kbd@f01d00 { + compatible = "ite,it8xxx2-kbd"; reg = <0x00f01d00 0x29>; interrupt-parent = <&intc>; interrupts = ; diff --git a/dts/riscv/lowrisc/opentitan_earlgrey.dtsi b/dts/riscv/lowrisc/opentitan_earlgrey.dtsi index 55171ec2a57..2df96d71eeb 100644 --- a/dts/riscv/lowrisc/opentitan_earlgrey.dtsi +++ b/dts/riscv/lowrisc/opentitan_earlgrey.dtsi @@ -19,7 +19,7 @@ reg = <0x00>; status = "okay"; compatible = "riscv"; - riscv,isa = "rv32imc"; + riscv,isa = "rv32imcb_zicsr_zifencei"; hlic: interrupt-controller { #interrupt-cells = <0x01>; @@ -75,10 +75,7 @@ #interrupt-cells = <2>; interrupt-controller; interrupts-extended = <&hlic 11>; - reg = <0x48000000 0x00001000 - 0x48002000 0x00001000 - 0x48200000 0x00000008>; - reg-names = "prio", "irq_en", "reg"; + reg = <0x48000000 0x04000000>; riscv,max-priority = <7>; riscv,ndev = <184>; status = "okay"; diff --git a/dts/riscv/microchip/microchip-miv.dtsi b/dts/riscv/microchip/microchip-miv.dtsi index 5ef8b3a4931..305145b7e44 100644 --- a/dts/riscv/microchip/microchip-miv.dtsi +++ b/dts/riscv/microchip/microchip-miv.dtsi @@ -16,7 +16,7 @@ compatible = "microchip,miv", "riscv"; device_type = "cpu"; reg = <0>; - riscv,isa = "rv32imac"; + riscv,isa = "rv32ima_zicsr_zifencei"; hlic: interrupt-controller { compatible = "riscv,cpu-intc"; #address-cells = <0>; @@ -54,10 +54,7 @@ #interrupt-cells = <2>; interrupt-controller; interrupts-extended = <&hlic 11>; - reg = <0x40000000 0x2000 - 0x40002000 0x1fe000 - 0x40200000 0x2000000>; - reg-names = "prio", "irq_en", "reg"; + reg = <0x40000000 0x04000000>; riscv,max-priority = <1>; riscv,ndev = <31>; }; diff --git a/dts/riscv/microchip/mpfs-icicle.dtsi b/dts/riscv/microchip/mpfs-icicle.dtsi index 9c1d25161b5..4ed4d45e305 100644 --- a/dts/riscv/microchip/mpfs-icicle.dtsi +++ b/dts/riscv/microchip/mpfs-icicle.dtsi @@ -19,7 +19,7 @@ compatible = "riscv"; device_type = "cpu"; reg = < 0x0 >; - riscv,isa = "rv64imac"; + riscv,isa = "rv64imac_zicsr_zfencei"; hlic0: interrupt-controller { compatible = "riscv,cpu-intc"; #address-cells = <0>; @@ -33,7 +33,7 @@ compatible = "riscv"; device_type = "cpu"; reg = < 0x1 >; - riscv,isa = "rv64imafdc"; + riscv,isa = "rv64gc"; hlic1: interrupt-controller { compatible = "riscv,cpu-intc"; #address-cells = <0>; @@ -47,7 +47,7 @@ compatible = "riscv"; device_type = "cpu"; reg = < 0x2 >; - riscv,isa = "rv64imafdc"; + riscv,isa = "rv64gc"; hlic2: interrupt-controller { compatible = "riscv,cpu-intc"; #address-cells = <0>; @@ -61,7 +61,7 @@ compatible = "riscv"; device_type = "cpu"; reg = < 0x3 >; - riscv,isa = "rv64imafdc"; + riscv,isa = "rv64gc"; hlic3: interrupt-controller { compatible = "riscv,cpu-intc"; #address-cells = <0>; @@ -75,7 +75,7 @@ compatible = "riscv"; device_type = "cpu"; reg = < 0x4 >; - riscv,isa = "rv64imafdc"; + riscv,isa = "rv64gc"; hlic4: interrupt-controller { compatible = "riscv,cpu-intc"; #address-cells = <0>; @@ -121,10 +121,7 @@ interrupt-controller; interrupts-extended = <&hlic0 11 &hlic1 11>; - reg = <0x0c000000 0x00002000 - 0x0c002000 0x001fe000 - 0x0c200000 0x3e000000>; - reg-names = "prio", "irq_en", "reg"; + reg = <0x0c000000 0x04000000>; riscv,max-priority = <7>; riscv,ndev = <187>; }; diff --git a/dts/riscv/neorv32.dtsi b/dts/riscv/neorv32.dtsi index aa5243883bb..429d4372418 100644 --- a/dts/riscv/neorv32.dtsi +++ b/dts/riscv/neorv32.dtsi @@ -20,6 +20,7 @@ cpu0: cpu@0 { compatible = "neorv32-cpu"; + riscv,isa = "rv32imc_zicsr"; reg = <0>; device_type = "cpu"; diff --git a/dts/riscv/niosv/niosv-g.dtsi b/dts/riscv/niosv/niosv-g.dtsi index 587528a8972..90869676f2b 100644 --- a/dts/riscv/niosv/niosv-g.dtsi +++ b/dts/riscv/niosv/niosv-g.dtsi @@ -18,6 +18,7 @@ cpu0: cpu@0 { device_type = "cpu"; compatible = "intel,niosv"; + riscv,isa = "rv32ima_zicsr_zifencei"; reg = <0>; clock-frequency = <50000000>; @@ -51,7 +52,7 @@ uart0: serial@90078 { compatible = "altr,jtag-uart"; interrupts = <16>; - status = "disable"; + status = "disabled"; }; }; }; diff --git a/dts/riscv/niosv/niosv-m.dtsi b/dts/riscv/niosv/niosv-m.dtsi index 8ffc6f92f7a..88f8042383c 100644 --- a/dts/riscv/niosv/niosv-m.dtsi +++ b/dts/riscv/niosv/niosv-m.dtsi @@ -18,6 +18,7 @@ cpu0: cpu@0 { device_type = "cpu"; compatible = "intel,niosv"; + riscv,isa = "rv32ia_zicsr_zifencei"; reg = <0>; clock-frequency = <50000000>; @@ -51,7 +52,7 @@ uart0: serial@90078 { compatible = "altr,jtag-uart"; interrupts = <16>; - status = "disable"; + status = "disabled"; }; }; }; diff --git a/dts/riscv/openisa/rv32m1.dtsi b/dts/riscv/openisa/rv32m1.dtsi index 94f121658b9..567a6959f1f 100644 --- a/dts/riscv/openisa/rv32m1.dtsi +++ b/dts/riscv/openisa/rv32m1.dtsi @@ -23,12 +23,14 @@ cpu@0 { device_type = "cpu"; compatible = "riscv"; + riscv,isa = "rv32ima_zicsr_zifencei"; reg = <0>; }; cpu@1 { device_type = "cpu"; compatible = "riscv"; + riscv,isa = "rv32ima_zicsr_zifencei"; reg = <1>; }; }; diff --git a/dts/riscv/riscv32-litex-vexriscv.dtsi b/dts/riscv/riscv32-litex-vexriscv.dtsi index e1cff9f488f..3eefacccf6d 100644 --- a/dts/riscv/riscv32-litex-vexriscv.dtsi +++ b/dts/riscv/riscv32-litex-vexriscv.dtsi @@ -23,7 +23,7 @@ compatible = "riscv"; device_type = "cpu"; reg = <0>; - riscv,isa = "rv32imac"; + riscv,isa = "rv32ima_zicsr_zifencei"; status = "okay"; timebase-frequency = <32768>; }; diff --git a/dts/riscv/sifive/riscv32-fe310.dtsi b/dts/riscv/sifive/riscv32-fe310.dtsi index 597a4421121..c028db37c4e 100644 --- a/dts/riscv/sifive/riscv32-fe310.dtsi +++ b/dts/riscv/sifive/riscv32-fe310.dtsi @@ -30,7 +30,7 @@ compatible = "sifive,e31"; device_type = "cpu"; reg = <0>; - riscv,isa = "rv32imac"; + riscv,isa = "rv32imac_zicsr_zifencei"; status = "okay"; hlic: interrupt-controller { compatible = "riscv,cpu-intc"; @@ -123,10 +123,7 @@ #interrupt-cells = <2>; interrupt-controller; interrupts-extended = <&hlic 11>; - reg = <0x0c000000 0x00002000 - 0x0c002000 0x001fe000 - 0x0c200000 0x03e00000>; - reg-names = "prio", "irq_en", "reg"; + reg = <0x0c000000 0x04000000>; riscv,max-priority = <7>; riscv,ndev = <52>; }; diff --git a/dts/riscv/sifive/riscv64-fu540.dtsi b/dts/riscv/sifive/riscv64-fu540.dtsi index 5024743d1c3..ed56401d462 100644 --- a/dts/riscv/sifive/riscv64-fu540.dtsi +++ b/dts/riscv/sifive/riscv64-fu540.dtsi @@ -36,7 +36,7 @@ compatible = "sifive,e51"; device_type = "cpu"; reg = <0>; - riscv,isa = "rv64imac"; + riscv,isa = "rv64imac_zicsr_zifencei"; status = "okay"; hlic: interrupt-controller { @@ -120,10 +120,7 @@ #interrupt-cells = <2>; interrupt-controller; interrupts-extended = <&hlic 11>; - reg = <0x0c000000 0x00002000 - 0x0c002000 0x001fe000 - 0x0c200000 0x03e00000>; - reg-names = "prio", "irq_en", "reg"; + reg = <0x0c000000 0x04000000>; riscv,max-priority = <7>; riscv,ndev = <52>; }; diff --git a/dts/riscv/sifive/riscv64-fu740.dtsi b/dts/riscv/sifive/riscv64-fu740.dtsi index c8ac2a9d988..bbe45b98aab 100644 --- a/dts/riscv/sifive/riscv64-fu740.dtsi +++ b/dts/riscv/sifive/riscv64-fu740.dtsi @@ -35,7 +35,7 @@ compatible = "sifive,s7"; device_type = "cpu"; reg = <0>; - riscv,isa = "rv64imac"; + riscv,isa = "rv64imac_zicsr_zifencei"; status = "okay"; hlic: interrupt-controller { @@ -50,7 +50,7 @@ device_type = "cpu"; mmu-type = "riscv,sv39"; reg = <0x1>; - riscv,isa = "rv64imafdc"; + riscv,isa = "rv64gc"; cpu1_intc: interrupt-controller { compatible = "riscv,cpu-intc"; @@ -63,7 +63,7 @@ device_type = "cpu"; mmu-type = "riscv,sv39"; reg = <0x2>; - riscv,isa = "rv64imafdc"; + riscv,isa = "rv64gc"; cpu2_intc: interrupt-controller { compatible = "riscv,cpu-intc"; @@ -76,7 +76,7 @@ device_type = "cpu"; mmu-type = "riscv,sv39"; reg = <0x3>; - riscv,isa = "rv64imafdc"; + riscv,isa = "rv64gc"; cpu3_intc: interrupt-controller { compatible = "riscv,cpu-intc"; @@ -89,7 +89,7 @@ device_type = "cpu"; mmu-type = "riscv,sv39"; reg = <0x4>; - riscv,isa = "rv64imafdc"; + riscv,isa = "rv64gc"; cpu4_intc: interrupt-controller { compatible = "riscv,cpu-intc"; @@ -142,10 +142,7 @@ #interrupt-cells = <2>; interrupt-controller; interrupts-extended = <&hlic 11>; - reg = <0x0 0x0c000000 0x0 0x00002000 - 0x0 0x0c002000 0x0 0x001fe000 - 0x0 0x0c200000 0x0 0x03e00000>; - reg-names = "prio", "irq_en", "reg"; + reg = <0x0 0x0c000000 0x0 0x04000000>; riscv,max-priority = <7>; riscv,ndev = <52>; }; diff --git a/dts/riscv/starfive/starfive_jh7100_beagle_v.dtsi b/dts/riscv/starfive/starfive_jh7100_beagle_v.dtsi index 39382568adf..c355ac89a5f 100644 --- a/dts/riscv/starfive/starfive_jh7100_beagle_v.dtsi +++ b/dts/riscv/starfive/starfive_jh7100_beagle_v.dtsi @@ -35,7 +35,7 @@ mmu-type = "riscv,sv39"; next-level-cache = <&cachectrl>; reg = <0>; - riscv,isa = "rv64imafdc"; + riscv,isa = "rv64gc"; starfive,itim = <&itim0>; status = "okay"; tlb-split; @@ -64,7 +64,7 @@ mmu-type = "riscv,sv39"; next-level-cache = <&cachectrl>; reg = <1>; - riscv,isa = "rv64imafdc"; + riscv,isa = "rv64gc"; starfive,itim = <&itim1>; status = "okay"; tlb-split; @@ -129,10 +129,7 @@ interrupt-controller; interrupts-extended = <&cpu0intctrl 11 &cpu0intctrl 9 &cpu1intctrl 11 &cpu1intctrl 9 >; - reg = <0x0 0x0c000000 0x0 0x00002000 - 0x0 0x0c002000 0x0 0x001fe000 - 0x0 0x0c200000 0x0 0x03e00000>; - reg-names = "prio", "irq_en", "reg"; + reg = <0x0 0x0c000000 0x0 0x04000000>; riscv,max-priority = <7>; riscv,ndev = <127>; }; diff --git a/dts/riscv/telink/telink_b91.dtsi b/dts/riscv/telink/telink_b91.dtsi index 23ebf5bb4c4..a75929f2814 100644 --- a/dts/riscv/telink/telink_b91.dtsi +++ b/dts/riscv/telink/telink_b91.dtsi @@ -23,6 +23,13 @@ reg = <0>; clock-frequency = <24000000>; compatible ="telink,b91", "riscv"; + riscv,isa = "rv32imac_zicsr_zifencei"; + hlic: interrupt-controller { + compatible = "riscv,cpu-intc"; + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + }; }; }; @@ -123,10 +130,9 @@ #address-cells = <0>; #interrupt-cells = <2>; interrupt-controller; - reg = < 0xe4000000 0x00001000 - 0xe4002000 0x00000800 - 0xe4200000 0x00010000 >; - reg-names = "prio", "irq_en", "reg"; + interrupts-extended = <&hlic 11>; + interrupt-parent = <&cpu0>; + reg = <0xe4000000 0x00210000>; riscv,max-priority = <3>; riscv,ndev = <63>; }; diff --git a/dts/riscv/virt.dtsi b/dts/riscv/virt.dtsi index 6119c6112db..caef8cb28d3 100644 --- a/dts/riscv/virt.dtsi +++ b/dts/riscv/virt.dtsi @@ -164,11 +164,8 @@ plic: interrupt-controller@c000000 { riscv,max-priority = <7>; - riscv,ndev = < 0x35 >; - reg = <0x0c000000 0x00002000 - 0x0c002000 0x001fe000 - 0x0c200000 0x03e00000>; - reg-names = "prio", "irq_en", "reg"; + riscv,ndev = < 1024 >; + reg = <0x0c000000 0x04000000>; interrupts-extended = < &hlic0 0x0b &hlic0 0x09 &hlic1 0x0b &hlic1 0x09 diff --git a/dts/x86/intel/alder_lake.dtsi b/dts/x86/intel/alder_lake.dtsi index b0cca7e5200..610c9f4ba72 100644 --- a/dts/x86/intel/alder_lake.dtsi +++ b/dts/x86/intel/alder_lake.dtsi @@ -17,7 +17,7 @@ cpu@0 { device_type = "cpu"; - compatible = "intel,alder_lake"; + compatible = "intel,alder-lake"; d-cache-line-size = <64>; reg = <0>; }; @@ -57,7 +57,7 @@ #size-cells = <0>; vendor-id = <0x8086>; device-id = <0x54a3>; - interrupts = <16 IRQ_TYPE_LOWEST_LEVEL_LOW 3>; + interrupts = ; interrupt-parent = <&intc>; status = "okay"; @@ -228,6 +228,28 @@ interrupt-parent = <&intc>; status = "disabled"; }; + + emmc: emmc0 { + compatible = "intel,emmc-host"; + vendor-id = <0x8086>; + device-id = <0x54C4>; + interrupts = ; + interrupt-parent = <&intc>; + + max-bus-freq = <200000000>; + min-bus-freq = <400000>; + power-delay-ms = <500>; + mmc-hs400-1_8v; + mmc-hs200-1_8v; + + mmc { + compatible = "zephyr,mmc-disk"; + bus-width = <8>; + status = "okay"; + }; + + status = "okay"; + }; }; soc { @@ -239,6 +261,7 @@ uart0_legacy: uart@3f8 { compatible = "ns16550"; reg = <0x000003f8 0x100>; + io-mapped; clock-frequency = <1843200>; interrupts = <4 IRQ_TYPE_LOWEST_EDGE_RISING 3>; interrupt-parent = <&intc>; @@ -407,6 +430,14 @@ status = "okay"; }; + tgpio: tgpio@fe001200 { + compatible = "intel,timeaware-gpio"; + reg = <0xfe001200 0x100>; + timer-clock = <19200000>; + max-pins = <2>; + status = "okay"; + }; + hpet: hpet@fed00000 { compatible = "intel,hpet"; reg = <0xfed00000 0x400>; diff --git a/dts/x86/intel/apollo_lake.dtsi b/dts/x86/intel/apollo_lake.dtsi index 4de0525ae64..ffe50483434 100644 --- a/dts/x86/intel/apollo_lake.dtsi +++ b/dts/x86/intel/apollo_lake.dtsi @@ -16,7 +16,7 @@ cpu@0 { device_type = "cpu"; - compatible = "intel,apollo_lake"; + compatible = "intel,apollo-lake"; d-cache-line-size = <64>; reg = <0>; }; diff --git a/dts/x86/intel/atom.dtsi b/dts/x86/intel/atom.dtsi deleted file mode 100644 index fe8340163ba..00000000000 --- a/dts/x86/intel/atom.dtsi +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2017 Intel Corporation. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "skeleton.dtsi" -#include - -/ { - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu@0 { - device_type = "cpu"; - compatible = "intel,atom"; - d-cache-line-size = <64>; - reg = <0>; - }; - }; - - dram0: memory@0 { - device_type = "memory"; - reg = <0x0 DT_DRAM_SIZE>; - }; - - intc: ioapic@fec00000 { - compatible = "intel,ioapic"; - reg = <0xfec00000 0x1000>; - interrupt-controller; - #interrupt-cells = <3>; - }; - - intc_loapic: loapic@fee00000 { - compatible = "intel,loapic"; - reg = <0xfee00000 0x1000>; - interrupt-controller; - #interrupt-cells = <3>; - }; - - soc { - #address-cells = <1>; - #size-cells = <1>; - compatible = "simple-bus"; - ranges; - - - uart0: uart@3f8 { - compatible = "ns16550"; - reg = <0x000003f8 0x100>; - clock-frequency = <1843200>; - interrupts = <4 IRQ_TYPE_LOWEST_EDGE_RISING 3>; - interrupt-parent = <&intc>; - reg-shift = <0>; - status = "disabled"; - }; - - uart1: uart@2f8 { - compatible = "ns16550"; - reg = <0x000002f8 0x100>; - clock-frequency = <1843200>; - interrupts = <3 IRQ_TYPE_LOWEST_EDGE_RISING 3>; - interrupt-parent = <&intc>; - reg-shift = <0>; - status = "disabled"; - }; - - hpet: hpet@fed00000 { - compatible = "intel,hpet"; - reg = <0xfed00000 0x400>; - interrupts = <2 IRQ_TYPE_FIXED_EDGE_RISING 4>; - interrupt-parent = <&intc>; - - status = "disabled"; - }; - - rtc: counter: rtc@70 { - compatible = "motorola,mc146818"; - reg = <0x70 0x0D 0x71 0x0D>; - interrupts = <8 IRQ_TYPE_LOWEST_EDGE_RISING 3>; - interrupt-parent = <&intc>; - alarms-count = <1>; - - status = "okay"; - }; - - }; -}; diff --git a/dts/x86/intel/elkhart_lake.dtsi b/dts/x86/intel/elkhart_lake.dtsi index c499497e294..e23183df1d0 100644 --- a/dts/x86/intel/elkhart_lake.dtsi +++ b/dts/x86/intel/elkhart_lake.dtsi @@ -16,7 +16,7 @@ cpu@0 { device_type = "cpu"; - compatible = "intel,elkhart_lake"; + compatible = "intel,elkhart-lake"; d-cache-line-size = <64>; reg = <0>; }; @@ -204,7 +204,7 @@ #size-cells = <0>; vendor-id = <0x8086>; device-id = <0x4b23>; - interrupts = <16 IRQ_TYPE_LOWEST_LEVEL_LOW 3>; + interrupts = ; interrupt-parent = <&intc>; status = "okay"; diff --git a/dts/x86/intel/ia32.dtsi b/dts/x86/intel/ia32.dtsi index 6058fff6123..9d1715aa840 100644 --- a/dts/x86/intel/ia32.dtsi +++ b/dts/x86/intel/ia32.dtsi @@ -51,6 +51,7 @@ uart0: uart@3f8 { compatible = "ns16550"; reg = <0x000003f8 0x100>; + io-mapped; clock-frequency = <1843200>; interrupts = <4 IRQ_TYPE_LOWEST_EDGE_RISING 3>; interrupt-parent = <&intc>; @@ -61,6 +62,7 @@ uart1: uart@2f8 { compatible = "ns16550"; reg = <0x000002f8 0x100>; + io-mapped; clock-frequency = <1843200>; interrupts = <3 IRQ_TYPE_LOWEST_EDGE_RISING 3>; interrupt-parent = <&intc>; diff --git a/dts/x86/intel/intel_ish5.dtsi b/dts/x86/intel/intel_ish5.dtsi index fece4af299f..5f2ef6a1960 100644 --- a/dts/x86/intel/intel_ish5.dtsi +++ b/dts/x86/intel/intel_ish5.dtsi @@ -95,6 +95,16 @@ status = "okay"; }; + ipmhost: ipm@4100000 { + compatible = "intel,sedi-ipm"; + reg = <0x4100000 0x1000>; + peripheral-id = <0>; + interrupt-parent = <&intc>; + interrupts = <0 IRQ_TYPE_LOWEST_LEVEL_HIGH 2>; + + status = "okay"; + }; + uart0: uart@8100000 { compatible = "intel,sedi-uart"; reg = <0x08100000 0x1000>; @@ -140,5 +150,55 @@ clock-frequency = ; status = "disabled"; }; + + gpio0: gpio@100000 { + compatible = "intel,sedi-gpio"; + gpio-controller; + #gpio-cells = <2>; + peripheral-id = <0>; + reg = <0x00100000 0x1000>; + interrupt-parent = <&intc>; + ngpios = <32>; + interrupts = <13 IRQ_TYPE_LOWEST_LEVEL_HIGH 2>; + + status = "okay"; + }; + + spi0: spi@8000000 { + compatible = "intel,sedi-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x8000000 0x1000>; + peripheral-id = <0>; + interrupt-parent = <&intc>; + interrupts = <19 IRQ_TYPE_LOWEST_LEVEL_HIGH 2>; + + status = "okay"; + }; + + spi1: spi@8002000 { + compatible = "intel,sedi-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x8002000 0x1000>; + peripheral-id = <1>; + interrupt-parent = <&intc>; + interrupts = <20 IRQ_TYPE_LOWEST_LEVEL_HIGH 2>; + + status = "disabled"; + }; + + dma0: dma@10100000 { + compatible = "intel,sedi_dma"; + #dma-cells = <2>; + dma-channels = <8>; + peripheral-id = <0>; + reg = <0x10100000 0x1000>; + interrupts = <11 IRQ_TYPE_LOWEST_LEVEL_HIGH 2>; + interrupt-parent = <&intc>; + dma-buf-size-alignment = <4>; + dma-copy-alignment = <4>; + status = "okay"; + }; }; }; diff --git a/dts/x86/intel/intel_ish5_8.dtsi b/dts/x86/intel/intel_ish5_8.dtsi index 555b8e28e7b..5600798d8e8 100644 --- a/dts/x86/intel/intel_ish5_8.dtsi +++ b/dts/x86/intel/intel_ish5_8.dtsi @@ -35,3 +35,21 @@ status = "disabled"; }; + +&gpio0 { + interrupts = <16 IRQ_TYPE_LOWEST_LEVEL_HIGH 2>; + + status = "okay"; +}; + +&spi0 { + interrupts = <23 IRQ_TYPE_LOWEST_LEVEL_HIGH 2>; + + status = "okay"; +}; + +&spi1 { + interrupts = <24 IRQ_TYPE_LOWEST_LEVEL_HIGH 2>; + + status = "disabled"; +}; diff --git a/dts/x86/intel/raptor_lake.dtsi b/dts/x86/intel/raptor_lake.dtsi index 1e412336ae8..797a3fa0e54 100644 --- a/dts/x86/intel/raptor_lake.dtsi +++ b/dts/x86/intel/raptor_lake.dtsi @@ -56,7 +56,7 @@ #size-cells = <0>; vendor-id = <0x8086>; device-id = <0x7a23>; - interrupts = <18 IRQ_TYPE_LOWEST_LEVEL_LOW 3>; + interrupts = ; interrupt-parent = <&intc>; status = "okay"; @@ -75,6 +75,13 @@ status = "okay"; }; + i2c0_dma: i2c0_dma { + compatible = "intel,lpss"; + dma-parent = <&i2c0>; + #dma-cells = <1>; + status = "okay"; + }; + i2c1: i2c1 { compatible = "snps,designware-i2c"; clock-frequency = ; @@ -85,7 +92,14 @@ interrupts = ; interrupt-parent = <&intc>; - status = "okay"; + status = "disabled"; + }; + + i2c1_dma: i2c1_dma { + compatible = "intel,lpss"; + dma-parent = <&i2c1>; + #dma-cells = <1>; + status = "disabled"; }; i2c2: i2c2 { @@ -93,12 +107,21 @@ clock-frequency = ; #address-cells = <1>; #size-cells = <0>; + #address-cells = <1>; + #size-cells = <0>; vendor-id = <0x8086>; device-id = <0x7ace>; interrupts = ; interrupt-parent = <&intc>; - status = "okay"; + status = "disabled"; + }; + + i2c2_dma: i2c2_dma { + compatible = "intel,lpss"; + dma-parent = <&i2c2>; + #dma-cells = <1>; + status = "disabled"; }; i2c3: i2c3 { @@ -114,6 +137,13 @@ status = "disabled"; }; + i2c3_dma: i2c3_dma { + compatible = "intel,lpss"; + dma-parent = <&i2c3>; + #dma-cells = <1>; + status = "disabled"; + }; + i2c4: i2c4 { compatible = "snps,designware-i2c"; clock-frequency = ; @@ -127,6 +157,13 @@ status = "disabled"; }; + i2c4_dma: i2c4_dma { + compatible = "intel,lpss"; + dma-parent = <&i2c4>; + #dma-cells = <1>; + status = "disabled"; + }; + i2c5: i2c5 { compatible = "snps,designware-i2c"; clock-frequency = ; @@ -140,6 +177,13 @@ status = "disabled"; }; + i2c5_dma: i2c5_dma { + compatible = "intel,lpss"; + dma-parent = <&i2c5>; + #dma-cells = <1>; + status = "disabled"; + }; + i2c6: i2c6 { compatible = "snps,designware-i2c"; clock-frequency = ; @@ -153,6 +197,13 @@ status = "disabled"; }; + i2c6_dma: i2c6_dma { + compatible = "intel,lpss"; + dma-parent = <&i2c6>; + #dma-cells = <1>; + status = "disabled"; + }; + i2c7: i2c7 { compatible = "snps,designware-i2c"; clock-frequency = ; @@ -166,6 +217,13 @@ status = "disabled"; }; + i2c7_dma: i2c7_dma { + compatible = "intel,lpss"; + dma-parent = <&i2c7>; + #dma-cells = <1>; + status = "disabled"; + }; + spi0: spi0 { compatible = "intel,penwell-spi"; vendor-id = <0x8086>; @@ -249,54 +307,6 @@ current-speed = <115200>; status = "disabled"; }; - - uart3: uart3 { - compatible = "ns16550"; - vendor-id = <0x8086>; - device-id = <0x7adc>; - reg-shift = <2>; - clock-frequency = <1843200>; - interrupts = ; - interrupt-parent = <&intc>; - current-speed = <115200>; - status = "disabled"; - }; - - uart4: uart4 { - compatible = "ns16550"; - vendor-id = <0x8086>; - device-id = <0x7add>; - reg-shift = <2>; - clock-frequency = <1843200>; - interrupts = ; - interrupt-parent = <&intc>; - current-speed = <115200>; - status = "disabled"; - }; - - uart5: uart5 { - compatible = "ns16550"; - vendor-id = <0x8086>; - device-id = <0x7ade>; - reg-shift = <2>; - clock-frequency = <1843200>; - interrupts = ; - interrupt-parent = <&intc>; - current-speed = <115200>; - status = "disabled"; - }; - - uart6: uart6 { - compatible = "ns16550"; - vendor-id = <0x8086>; - device-id = <0x7adf>; - reg-shift = <2>; - clock-frequency = <1843200>; - interrupts = ; - interrupt-parent = <&intc>; - current-speed = <115200>; - status = "disabled"; - }; }; soc { @@ -315,6 +325,7 @@ uart_ec_0: uart@3f8 { compatible = "ns16550"; reg = <0x000003f8 0x100>; + io-mapped; clock-frequency = <1843200>; interrupts = <4 IRQ_TYPE_LOWEST_EDGE_RISING 3>; interrupt-parent = <&intc>; @@ -525,6 +536,14 @@ status = "okay"; }; + tgpio: tgpio@fe001200 { + compatible = "intel,timeaware-gpio"; + reg = <0xfe001200 0x100>; + timer-clock = <19200000>; + max-pins = <2>; + status = "okay"; + }; + hpet: hpet@fed00000 { compatible = "intel,hpet"; reg = <0xfed00000 0x400>; diff --git a/dts/xtensa/dc233c.dtsi b/dts/xtensa/dc233c.dtsi index 8a0eed405c3..81f5042c586 100644 --- a/dts/xtensa/dc233c.dtsi +++ b/dts/xtensa/dc233c.dtsi @@ -29,13 +29,13 @@ }; /* - * Although ROM is of size 32MB (0x02000000), limit this to 8KB so + * Although ROM is of size 32MB (0x02000000), limit this to 16KB so * fewer L2 page table entries are needed when MMU is enabled. */ rom0: memory@fe000000 { device_type = "memory"; compatible = "mmio-sram"; - reg = <0xfe000000 0x00002000>; + reg = <0xfe000000 0x00004000>; }; soc { diff --git a/dts/xtensa/espressif/esp32/esp32_common.dtsi b/dts/xtensa/espressif/esp32/esp32_common.dtsi index e862a653e9b..0f61150cead 100644 --- a/dts/xtensa/espressif/esp32/esp32_common.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_common.dtsi @@ -69,9 +69,10 @@ mdio: mdio { compatible = "espressif,esp32-mdio"; - protocol = "clause 22"; clocks = <&rtc ESP32_EMAC_MODULE>; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; pinctrl: pin-controller { @@ -345,7 +346,6 @@ interrupts = ; interrupt-parent = <&intc>; clocks = <&rtc ESP32_TWAI_MODULE>; - sjw = <1>; sample-point = <875>; status = "disabled"; }; diff --git a/dts/xtensa/espressif/esp32/esp32_d0wd_v3.dtsi b/dts/xtensa/espressif/esp32/esp32_d0wd_v3.dtsi index 6511f3d351a..b2232505a9a 100644 --- a/dts/xtensa/espressif/esp32/esp32_d0wd_v3.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_d0wd_v3.dtsi @@ -8,7 +8,7 @@ /* Reserved GPIO pins */ &gpio0 { - gpio-reserved-ranges = <20>,<24>,<28 31>; // NC + gpio-reserved-ranges = <20 1>, <24 1>, <28 4>; // NC }; /* Add flash or psram on board or application level */ diff --git a/dts/xtensa/espressif/esp32/esp32_d0wdr2_v3.dtsi b/dts/xtensa/espressif/esp32/esp32_d0wdr2_v3.dtsi index eb5e239c1aa..2703231b821 100644 --- a/dts/xtensa/espressif/esp32/esp32_d0wdr2_v3.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_d0wdr2_v3.dtsi @@ -8,9 +8,9 @@ /* Reserved GPIO pins */ &gpio0 { - gpio-reserved-ranges = <6 10>, // embeddef psram - <11>, // flash CS - <20>,<24>,<28 31>; // NC + gpio-reserved-ranges = <6 5>, // embeddef psram + <11 1>, // flash CS + <20 1>, <24 1>, <28 4>; // NC }; /* 2MB psram */ diff --git a/dts/xtensa/espressif/esp32/esp32_net.dtsi b/dts/xtensa/espressif/esp32/esp32_net.dtsi index 00657ac0425..b5357495666 100644 --- a/dts/xtensa/espressif/esp32/esp32_net.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_net.dtsi @@ -8,7 +8,7 @@ /* Reserved GPIO pins */ &gpio0 { - gpio-reserved-ranges = <20>,<24>,<28 31>; // NC + gpio-reserved-ranges = <20 1>, <24 1>, <28 4>; // NC }; &flash0 { diff --git a/dts/xtensa/espressif/esp32/esp32_pico_d4.dtsi b/dts/xtensa/espressif/esp32/esp32_pico_d4.dtsi index 8ed101d24bc..580d6fed892 100644 --- a/dts/xtensa/espressif/esp32/esp32_pico_d4.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_pico_d4.dtsi @@ -8,8 +8,8 @@ /* Reserved GPIO pins */ &gpio0 { - gpio-reserved-ranges = <6 8>,<11>,<16 17>, // embedded flash - <20>, <24>, <28 31>; // NC + gpio-reserved-ranges = <6 3>, <11 1>, <16 2>, // embedded flash + <20 1>, <24 1>, <28 4>; // NC }; /* 4MB flash */ diff --git a/dts/xtensa/espressif/esp32/esp32_pico_v3.dtsi b/dts/xtensa/espressif/esp32/esp32_pico_v3.dtsi index 76e4d4c05eb..d806b0b7c14 100644 --- a/dts/xtensa/espressif/esp32/esp32_pico_v3.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_pico_v3.dtsi @@ -8,8 +8,8 @@ /* Reserved GPIO pins */ &gpio0 { - gpio-reserved-ranges = <16 18>,<23>, // limitations - <24>,<28 31>; // NC + gpio-reserved-ranges = <16 3>, <23 1>, // limitations + <24 1>, <28 4>; // NC }; /* 4MB flash */ diff --git a/dts/xtensa/espressif/esp32/esp32_pico_v3_02.dtsi b/dts/xtensa/espressif/esp32/esp32_pico_v3_02.dtsi index 249debca752..9d108bd4e57 100644 --- a/dts/xtensa/espressif/esp32/esp32_pico_v3_02.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_pico_v3_02.dtsi @@ -8,8 +8,8 @@ /* Reserved GPIO pins */ &gpio0 { - gpio-reserved-ranges = <6 11>, // flash - <24 25>,<28 31>; // NC + gpio-reserved-ranges = <6 6>, // flash + <24 2>, <28 4>; // NC }; /* 8MB flash */ diff --git a/dts/xtensa/espressif/esp32/esp32_u4wdh.dtsi b/dts/xtensa/espressif/esp32/esp32_u4wdh.dtsi index d26074898fa..34ca79156ef 100644 --- a/dts/xtensa/espressif/esp32/esp32_u4wdh.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_u4wdh.dtsi @@ -8,7 +8,7 @@ /* Reserved GPIO pins */ &gpio0 { - gpio-reserved-ranges = <20>, <24>, <28 31>; + gpio-reserved-ranges = <20 1>, <24 1>, <28 4>; }; /* 4MB flash */ diff --git a/dts/xtensa/espressif/esp32/esp32_wroom_32ue_n16.dtsi b/dts/xtensa/espressif/esp32/esp32_wroom_32ue_n16.dtsi index 2461a803954..43ce14117a5 100644 --- a/dts/xtensa/espressif/esp32/esp32_wroom_32ue_n16.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_wroom_32ue_n16.dtsi @@ -8,12 +8,12 @@ /* Reserved GPIO pins */ &gpio0 { - gpio-reserved-ranges = <6 11>, // flash - <20>, <24>, <28 31>; // NC + gpio-reserved-ranges = <6 6>, // flash + <20 1>, <24 1>, <28 4>; // NC }; &gpio1 { - gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC + gpio-reserved-ranges = <6 2>; // GPIO37-38 NC }; /* 16MB flash */ diff --git a/dts/xtensa/espressif/esp32/esp32_wroom_32ue_n4.dtsi b/dts/xtensa/espressif/esp32/esp32_wroom_32ue_n4.dtsi index 9c8ef71acfd..8f5f3d9dd10 100644 --- a/dts/xtensa/espressif/esp32/esp32_wroom_32ue_n4.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_wroom_32ue_n4.dtsi @@ -8,12 +8,12 @@ /* Reserved GPIO pins */ &gpio0 { - gpio-reserved-ranges = <6 11>, // flash - <20>,<24>,<28 31>; // NC + gpio-reserved-ranges = <6 6>, // flash + <20 1>, <24 1>, <28 4>; // NC }; &gpio1 { - gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC + gpio-reserved-ranges = <6 2>; // GPIO37-38 NC }; /* 4MB flash */ diff --git a/dts/xtensa/espressif/esp32/esp32_wroom_32ue_n8.dtsi b/dts/xtensa/espressif/esp32/esp32_wroom_32ue_n8.dtsi index 4dee1868cc3..42813aa6e68 100644 --- a/dts/xtensa/espressif/esp32/esp32_wroom_32ue_n8.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_wroom_32ue_n8.dtsi @@ -8,12 +8,12 @@ /* Reserved GPIO pins */ &gpio0 { - gpio-reserved-ranges = <6 11>, // flash - <20>,<24>,<28 31>; // NC + gpio-reserved-ranges = <6 6>, // flash + <20 1>, <24 1>, <28 4>; // NC }; &gpio1 { - gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC + gpio-reserved-ranges = <6 2>; // GPIO37-38 NC }; /* 8MB flash */ diff --git a/dts/xtensa/espressif/esp32/esp32_wroom_da_n16.dtsi b/dts/xtensa/espressif/esp32/esp32_wroom_da_n16.dtsi index f034a5b2898..f9f3bd81201 100644 --- a/dts/xtensa/espressif/esp32/esp32_wroom_da_n16.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_wroom_da_n16.dtsi @@ -8,13 +8,13 @@ /* Reserved GPIO pins */ &gpio0 { - gpio-reserved-ranges = <2>,<25>, // NC/test - <6 11>, // flash - <20>,<24>,<28 31>; // NC + gpio-reserved-ranges = <2 1>, <25 1>, // NC/test + <6 6>, // flash + <20 1>, <24 1>, <28 4>; // NC }; &gpio1 { - gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC + gpio-reserved-ranges = <6 2>; // GPIO37-38 NC }; /* 16MB flash */ diff --git a/dts/xtensa/espressif/esp32/esp32_wroom_da_n4.dtsi b/dts/xtensa/espressif/esp32/esp32_wroom_da_n4.dtsi index 324c1bba2de..98f6d9dc9b2 100644 --- a/dts/xtensa/espressif/esp32/esp32_wroom_da_n4.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_wroom_da_n4.dtsi @@ -8,13 +8,13 @@ /* Reserved GPIO pins */ &gpio0 { - gpio-reserved-ranges = <2>,<25>, // NC/test - <6 11>, // flash - <20>,<24>,<28 31>; // NC + gpio-reserved-ranges = <2 1>, <25 1>, // NC/test + <6 6>, // flash + <20 1>, <24 1>, <28 4>; // NC }; &gpio1 { - gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC + gpio-reserved-ranges = <6 2>; // GPIO37-38 NC }; /* 4MB flash */ diff --git a/dts/xtensa/espressif/esp32/esp32_wroom_da_n8.dtsi b/dts/xtensa/espressif/esp32/esp32_wroom_da_n8.dtsi index ec5583c4406..7beeda4e136 100644 --- a/dts/xtensa/espressif/esp32/esp32_wroom_da_n8.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_wroom_da_n8.dtsi @@ -8,13 +8,13 @@ /* Reserved GPIO pins */ &gpio0 { - gpio-reserved-ranges = <2>,<25>, // NC/test - <6 11>, // flash - <20>,<24>,<28 31>; // NC + gpio-reserved-ranges = <2 1>, <25 1>, // NC/test + <6 6>, // flash + <20 1>, <24 1>, <28 4>; // NC }; &gpio1 { - gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC + gpio-reserved-ranges = <6 2>; // GPIO37-38 NC }; /* 8MB flash */ diff --git a/dts/xtensa/espressif/esp32/esp32_wrover_e_n16r2.dtsi b/dts/xtensa/espressif/esp32/esp32_wrover_e_n16r2.dtsi index 712d86fc0f4..393dfa7b951 100644 --- a/dts/xtensa/espressif/esp32/esp32_wrover_e_n16r2.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_wrover_e_n16r2.dtsi @@ -8,12 +8,12 @@ /* Reserved GPIO pins */ &gpio0 { - gpio-reserved-ranges = <6 11>,<16 17>, // flash&psram - <20>,<24>,<28 31>; // NC + gpio-reserved-ranges = <6 6>, <16 2>, // flash&psram + <20 1>, <24 1>, <28 4>; // NC }; &gpio1 { - gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC + gpio-reserved-ranges = <6 2>; // GPIO37-38 NC }; /* 16MB flash */ diff --git a/dts/xtensa/espressif/esp32/esp32_wrover_e_n16r4.dtsi b/dts/xtensa/espressif/esp32/esp32_wrover_e_n16r4.dtsi index 119e3e3ed6a..160800afdca 100644 --- a/dts/xtensa/espressif/esp32/esp32_wrover_e_n16r4.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_wrover_e_n16r4.dtsi @@ -8,12 +8,12 @@ /* Reserved GPIO pins */ &gpio0 { - gpio-reserved-ranges = <6 11>,<16 17>, // flash&psram - <20>,<24>,<28 31>; // NC + gpio-reserved-ranges = <6 6>, <16 2>, // flash&psram + <20 1>, <24 1>, <28 4>; // NC }; &gpio1 { - gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC + gpio-reserved-ranges = <6 2>; // GPIO37-38 NC }; /* 16MB flash */ diff --git a/dts/xtensa/espressif/esp32/esp32_wrover_e_n16r8.dtsi b/dts/xtensa/espressif/esp32/esp32_wrover_e_n16r8.dtsi index 10ab7f11fa1..acac866076f 100644 --- a/dts/xtensa/espressif/esp32/esp32_wrover_e_n16r8.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_wrover_e_n16r8.dtsi @@ -8,12 +8,12 @@ /* Reserved GPIO pins */ &gpio0 { - gpio-reserved-ranges = <6 11>,<16 17>, // flash&psram - <20>,<24>,<28 31>; // NC + gpio-reserved-ranges = <6 6>, <16 2>, // flash&psram + <20 1>, <24 1>, <28 4>; // NC }; &gpio1 { - gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC + gpio-reserved-ranges = <6 2>; // GPIO37-38 NC }; /* 16MB flash */ diff --git a/dts/xtensa/espressif/esp32/esp32_wrover_e_n4r2.dtsi b/dts/xtensa/espressif/esp32/esp32_wrover_e_n4r2.dtsi index b4367cc223d..8e463a3b3a7 100644 --- a/dts/xtensa/espressif/esp32/esp32_wrover_e_n4r2.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_wrover_e_n4r2.dtsi @@ -8,12 +8,12 @@ /* Reserved GPIO pins */ &gpio0 { - gpio-reserved-ranges = <6 11>,<16 17>, // flash&psram - <20>,<24>,<28 31>; // NC + gpio-reserved-ranges = <6 6>, <16 2>, // flash&psram + <20 1>, <24 1>, <28 4>; // NC }; &gpio1 { - gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC + gpio-reserved-ranges = <6 1>, <7 1>; // GPIO37-38 NC }; /* 4MB flash */ diff --git a/dts/xtensa/espressif/esp32/esp32_wrover_e_n4r8.dtsi b/dts/xtensa/espressif/esp32/esp32_wrover_e_n4r8.dtsi index ef6037b394c..0197755fba5 100644 --- a/dts/xtensa/espressif/esp32/esp32_wrover_e_n4r8.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_wrover_e_n4r8.dtsi @@ -8,12 +8,12 @@ /* Reserved GPIO pins */ &gpio0 { - gpio-reserved-ranges = <6 11>,<16 17>, // flash&psram - <20>,<24>,<28 31>; // NC + gpio-reserved-ranges = <6 6>, <16 2>, // flash&psram + <20 1>, <24 1>, <28 4>; // NC }; &gpio1 { - gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC + gpio-reserved-ranges = <6 1>, <7 1>; // GPIO37-38 NC }; /* 4MB flash */ diff --git a/dts/xtensa/espressif/esp32/esp32_wrover_e_n8r2.dtsi b/dts/xtensa/espressif/esp32/esp32_wrover_e_n8r2.dtsi index e8d902c73ae..5bc98caf706 100644 --- a/dts/xtensa/espressif/esp32/esp32_wrover_e_n8r2.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_wrover_e_n8r2.dtsi @@ -8,12 +8,12 @@ /* Reserved GPIO pins */ &gpio0 { - gpio-reserved-ranges = <6 11>,<16 17>, // flash&psram - <20>,<24>,<28 31>; // NC + gpio-reserved-ranges = <6 6>, <16 2>, // flash&psram + <20 1>, <24 1>, <28 4>; // NC }; &gpio1 { - gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC + gpio-reserved-ranges = <6 2>; // GPIO37-38 NC }; /* 8MB flash */ diff --git a/dts/xtensa/espressif/esp32/esp32_wrover_e_n8r8.dtsi b/dts/xtensa/espressif/esp32/esp32_wrover_e_n8r8.dtsi index 1ab318f3589..0f73058de08 100644 --- a/dts/xtensa/espressif/esp32/esp32_wrover_e_n8r8.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_wrover_e_n8r8.dtsi @@ -8,13 +8,13 @@ /* Reserved GPIO pins */ &gpio0 { - gpio-reserved-ranges = <20>, <24>, <28 31>; - gpio-reserved-ranges = <6 11>,<16 17>, // flash&psram - <20>,<24>,<28 31>; // NC + gpio-reserved-ranges = <20 1>, <24 1>, <28 4>; + gpio-reserved-ranges = <6 6>, <16 2>, // flash&psram + <20 1>, <24 1>, <28 4>; // NC }; &gpio1 { - gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC + gpio-reserved-ranges = <6 2>; // GPIO37-38 NC }; /* 8MB flash */ diff --git a/dts/xtensa/espressif/esp32s2/esp32s2_common.dtsi b/dts/xtensa/espressif/esp32s2/esp32s2_common.dtsi index 696e77a8ffb..b523ec53364 100644 --- a/dts/xtensa/espressif/esp32s2/esp32s2_common.dtsi +++ b/dts/xtensa/espressif/esp32s2/esp32s2_common.dtsi @@ -331,7 +331,6 @@ interrupts = ; interrupt-parent = <&intc>; clocks = <&rtc ESP32_TWAI_MODULE>; - sjw = <1>; sample-point = <875>; status = "disabled"; }; diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_appcpu.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_appcpu.dtsi new file mode 100644 index 00000000000..c405bfedecd --- /dev/null +++ b/dts/xtensa/espressif/esp32s3/esp32s3_appcpu.dtsi @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s3_common.dtsi" diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi index a5b98a9f52b..3c373272593 100644 --- a/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi +++ b/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi @@ -58,6 +58,16 @@ reg = <0x3fc88000 0x77FFF>; }; + ipmmem0: memory@3fcbd000 { + compatible = "mmio-sram"; + reg = <0x3fcbd000 0x400>; + }; + + shm0: memory@3fcbd400 { + compatible = "mmio-sram"; + reg = <0x3fcbd400 0x4000>; + }; + intc: interrupt-controller@600c2000 { #interrupt-cells = <1>; compatible = "espressif,esp32-intc"; @@ -107,6 +117,16 @@ status = "disabled"; }; + ipm0: ipm@3fcc1400 { + compatible = "espressif,esp32-ipm"; + reg = <0x3fcc1400 0x8>; + status = "disabled"; + shared-memory = <&ipmmem0>; + shared-memory-size = <0x400>; + interrupts = ; + interrupt-parent = <&intc>; + }; + uart0: uart@60000000 { compatible = "espressif,esp32-uart"; reg = <0x60000000 0x1000>; @@ -241,7 +261,6 @@ interrupts = ; interrupt-parent = <&intc>; clocks = <&rtc ESP32_TWAI_MODULE>; - sjw = <1>; sample-point = <875>; status = "disabled"; }; diff --git a/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi b/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi index f68c745f45d..de8aa8ed6fd 100644 --- a/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi +++ b/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi @@ -81,11 +81,10 @@ clkctl: clkctl { compatible = "intel,adsp-shim-clkctl"; adsp-clkctl-clk-wovcro = <0>; - adsp-clkctl-clk-lpro = <1>; - adsp-clkctl-clk-hpro = <2>; - adsp-clkctl-freq-enc = <0xc 0x0 0x4>; - adsp-clkctl-freq-mask = <0x0 0x0 0x0>; - adsp-clkctl-freq-default = <2>; + adsp-clkctl-clk-ipll = <1>; + adsp-clkctl-freq-enc = <0xc 0x4>; + adsp-clkctl-freq-mask = <0x0 0x0>; + adsp-clkctl-freq-default = <1>; adsp-clkctl-freq-lowest = <0>; wovcro-supported; }; @@ -514,32 +513,6 @@ interrupt-parent = <&ace_intc>; }; - watchdog0: watchdog@78300 { - compatible = "snps,designware-watchdog"; - reg = <0x78300 0x100>; - interrupts = <8 0 0>; - interrupt-parent = <&core_intc>; - clock-frequency = <32768>; - reset-pulse-length = <2>; - status = "okay"; - }; - - watchdog1: watchdog@78400 { - compatible = "snps,designware-watchdog"; - reg = <0x78400 0x100>; - clock-frequency = <32768>; - reset-pulse-length = <2>; - status = "okay"; - }; - - watchdog2: watchdog@78500 { - compatible = "snps,designware-watchdog"; - reg = <0x78500 0x100>; - clock-frequency = <32768>; - reset-pulse-length = <2>; - status = "okay"; - }; - /* This is actually an array of per-core designware * controllers, but the special setup and extra * masking layer makes it easier for MTL to handle diff --git a/dts/xtensa/intel/intel_adsp_ace20_lnl.dtsi b/dts/xtensa/intel/intel_adsp_ace20_lnl.dtsi index f47c94ddf1b..726e94bc271 100644 --- a/dts/xtensa/intel/intel_adsp_ace20_lnl.dtsi +++ b/dts/xtensa/intel/intel_adsp_ace20_lnl.dtsi @@ -95,11 +95,10 @@ clkctl: clkctl { compatible = "intel,adsp-shim-clkctl"; adsp-clkctl-clk-wovcro = <0>; - adsp-clkctl-clk-lpro = <1>; - adsp-clkctl-clk-hpro = <2>; - adsp-clkctl-freq-enc = <0xc 0x0 0x4>; - adsp-clkctl-freq-mask = <0x0 0x0 0x0>; - adsp-clkctl-freq-default = <2>; + adsp-clkctl-clk-ipll = <1>; + adsp-clkctl-freq-enc = <0xc 0x4>; + adsp-clkctl-freq-mask = <0x0 0x0>; + adsp-clkctl-freq-default = <1>; adsp-clkctl-freq-lowest = <0>; wovcro-supported; }; diff --git a/dts/xtensa/intel/intel_adsp_cavs25.dtsi b/dts/xtensa/intel/intel_adsp_cavs25.dtsi index 1039a00b094..36ad7afa218 100644 --- a/dts/xtensa/intel/intel_adsp_cavs25.dtsi +++ b/dts/xtensa/intel/intel_adsp_cavs25.dtsi @@ -98,7 +98,7 @@ wovcro-supported; }; - IMR1: memory@0xb0000000 { + IMR1: memory@b0000000 { compatible = "intel,adsp-imr"; reg = <0xB0000000 DT_SIZE_M(16)>; block-size = <0x1000>; diff --git a/dts/xtensa/intel/intel_adsp_cavs25_tgph.dtsi b/dts/xtensa/intel/intel_adsp_cavs25_tgph.dtsi index a03605df515..facb914904c 100644 --- a/dts/xtensa/intel/intel_adsp_cavs25_tgph.dtsi +++ b/dts/xtensa/intel/intel_adsp_cavs25_tgph.dtsi @@ -84,7 +84,7 @@ wovcro-supported; }; - IMR1: memory@0xb0000000 { + IMR1: memory@b0000000 { compatible = "intel,adsp-imr"; reg = <0xB0000000 DT_SIZE_M(16)>; block-size = <0x1000>; diff --git a/dts/xtensa/nxp/nxp_imx8.dtsi b/dts/xtensa/nxp/nxp_imx8.dtsi index 06b38e1bbee..7a8c23cedc4 100644 --- a/dts/xtensa/nxp/nxp_imx8.dtsi +++ b/dts/xtensa/nxp/nxp_imx8.dtsi @@ -6,6 +6,7 @@ #include #include +#include / { cpus { @@ -16,6 +17,16 @@ device_type = "cpu"; compatible = "cdns,tensilica-xtensa-lx6"; reg = <0>; + + #address-cells = <1>; + #size-cells = <0>; + + clic: interrupt-controller@0 { + compatible = "cdns,xtensa-core-intc"; + reg = <0>; + interrupt-controller; + #interrupt-cells = <3>; + }; }; }; @@ -30,4 +41,40 @@ compatible = "mmio-sram"; reg = <0x92c00000 DT_SIZE_K(512)>; }; + + /* LSIO MU2, used to interact with the SCFW */ + scu_mu: mailbox@5d1d0000 { + reg = <0x5d1d0000 DT_SIZE_K(64)>; + }; + + scu: system-controller { + ccm: clock-controller { + compatible = "nxp,imx-ccm"; + #clock-cells = <3>; + }; + + iomuxc: iomuxc { + compatible = "nxp,imx-iomuxc-scu"; + pinctrl: pinctrl { + compatible = "nxp,imx8-pinctrl"; + }; + }; + }; + + lpuart2: serial@5a080000 { + compatible = "nxp,imx-lpuart", "nxp,kinetis-lpuart"; + reg = <0x5a080000 DT_SIZE_K(4)>; + /* TODO: THIS INTID IS JUST A DUMMY ONE UNTIL IRQ_STEER + * DRIVER CAN BE USED ON i.MX8QM/QXP. DO NOT ATTEMPT TO + * ENABLE UART INTERRUPT SUPPORT. + * + * THE CURRENT INTID VALUE IS CHOSEN SUCH THAT gen_isr_tables.py + * WILL BREAK IF YOU ATTEMPT TO IRQ_CONNECT(). + */ + interrupt-parent = <&clic>; + interrupts = <259 0 0>; + /* this is actually LPUART2 clock but the macro indexing starts at 1 */ + clocks = <&ccm IMX_CCM_LPUART3_CLK 0x0 0x0>; + status = "disabled"; + }; }; diff --git a/dts/xtensa/nxp/nxp_imx8m.dtsi b/dts/xtensa/nxp/nxp_imx8m.dtsi index 9e72a3d59ed..21a094c0461 100644 --- a/dts/xtensa/nxp/nxp_imx8m.dtsi +++ b/dts/xtensa/nxp/nxp_imx8m.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 NXP + * Copyright 2021, 2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -64,12 +64,16 @@ uart4: uart@30a60000 { compatible = "nxp,imx-iuart"; reg = <0x30a60000 0x10000>; + /* TODO: This INTID is just a dummy + * until we can support UART interrupts + */ + interrupts = <29 0>; clocks = <&ccm IMX_CCM_UART4_CLK 0x6c 24>; status = "disabled"; }; mailbox0: mailbox@30e70000 { - compatible = "nxp,imx-mu-rev2"; + compatible = "nxp,imx-mu"; reg = <0x30e70000 0x10000>; interrupts = <7 0>; rdc = <0>; diff --git a/include/zephyr/acpi/acpi.h b/include/zephyr/acpi/acpi.h index dc6a25c8ea8..589cd7d6c4d 100644 --- a/include/zephyr/acpi/acpi.h +++ b/include/zephyr/acpi/acpi.h @@ -10,6 +10,11 @@ #define ACPI_RES_INVALID ACPI_RESOURCE_TYPE_MAX +#define ACPI_DRHD_FLAG_INCLUDE_PCI_ALL BIT(0) +#define ACPI_DMAR_FLAG_INTR_REMAP BIT(0) +#define ACPI_DMAR_FLAG_X2APIC_OPT_OUT BIT(1) +#define ACPI_DMAR_FLAG_DMA_CTRL_PLATFORM_OPT_IN BIT(2) + struct acpi_dev { ACPI_HANDLE handle; char *path; @@ -19,6 +24,22 @@ struct acpi_dev { ACPI_DEVICE_INFO *dev_info; }; +union acpi_dmar_id { + struct { + uint16_t function: 3; + uint16_t device: 5; + uint16_t bus: 8; + } bits; + + uint16_t raw; +}; + +struct acpi_mcfg { + ACPI_TABLE_HEADER header; + uint64_t _reserved; + ACPI_MCFG_ALLOCATION pci_segs[]; +} __packed; + /** * @brief Retrieve a legacy interrupt number for a PCI device. * @@ -59,11 +80,10 @@ int acpi_current_resource_free(ACPI_RESOURCE *res); * * @param bus_name the name of the bus * @param rt_table the IRQ routing table - * @param rt_size the the size of IRQ routing table + * @param rt_size number of elements in the IRQ routing table * @return return 0 on success or error code */ -int acpi_get_irq_routing_table(char *bus_name, - ACPI_PCI_ROUTING_TABLE *rt_table, size_t rt_size); +int acpi_get_irq_routing_table(char *bus_name, ACPI_PCI_ROUTING_TABLE *rt_table, size_t rt_size); /** * @brief Parse resource table for a given resource type. @@ -117,9 +137,47 @@ int acpi_device_type_get(ACPI_RESOURCE *res); * * @param signature pointer to the 4-character ACPI signature for the requested table * @param inst instance number for the requested table - * @param acpi_table pointer to the acpi table + * @return acpi_table pointer to the acpi table on success else return NULL + */ +void *acpi_table_get(char *signature, int inst); + +/** + * @brief retrieve acpi MAD table for the given type. + * + * @param type type of requested MAD table + * @param tables pointer to the MAD table + * @param num_inst number of instance for the requested table + * @return return 0 on success or error code + */ +int acpi_madt_entry_get(int type, ACPI_SUBTABLE_HEADER **tables, int *num_inst); + +/** + * @brief retrieve DMA remapping structure for the given type. + * + * @param type type of remapping structure + * @param tables pointer to the dmar id structure * @return return 0 on success or error code */ -int acpi_table_get(char *signature, int inst, void **acpi_table); +int acpi_dmar_entry_get(enum AcpiDmarType type, ACPI_SUBTABLE_HEADER **tables); +/** + * @brief retrieve acpi DRHD info for the given scope. + * + * @param scope scope of requested DHRD table + * @param dev_scope pointer to the sub table (optional) + * @param dmar_id pointer to the DHRD info + * @param num_inst number of instance for the requested table + * @param max_inst maximum number of entry for the given dmar_id buffer + * @return return 0 on success or error code + */ +int acpi_drhd_get(enum AcpiDmarScopeType scope, ACPI_DMAR_DEVICE_SCOPE *dev_scope, + union acpi_dmar_id *dmar_id, int *num_inst, int max_inst); + +/** + * @brief Retrieve the 'n'th enabled local apic info. + * + * @param cpu_num the cpu number + * @return local apic info on success or NULL otherwise + */ +ACPI_MADT_LOCAL_APIC *acpi_local_apic_get(int cpu_num); #endif diff --git a/include/zephyr/acpi/acpi_osal.h b/include/zephyr/acpi/acpi_osal.h new file mode 100644 index 00000000000..3332bd7ecc3 --- /dev/null +++ b/include/zephyr/acpi/acpi_osal.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_ARCH_X86_INCLUDE_ACPI_OSAL_H_ +#define ZEPHYR_ARCH_X86_INCLUDE_ACPI_OSAL_H_ + +#if defined(CONFIG_X86 || CONFIG_X86_64) +#include +#else +#error "Currently only x86 Architecture support ACPI !!" +#endif + +#endif /* ZEPHYR_ARCH_X86_INCLUDE_ACPI_OSAL_H_ */ diff --git a/include/zephyr/arch/arch_inlines.h b/include/zephyr/arch/arch_inlines.h index a4173d2a95b..4e1cd149dfb 100644 --- a/include/zephyr/arch/arch_inlines.h +++ b/include/zephyr/arch/arch_inlines.h @@ -15,7 +15,7 @@ #if defined(CONFIG_X86) || defined(CONFIG_X86_64) #include #elif defined(CONFIG_ARM) -#include +#include #elif defined(CONFIG_ARM64) #include #elif defined(CONFIG_ARC) diff --git a/include/zephyr/arch/arm/aarch32/cortex_m/arm_mpu_mem_cfg.h b/include/zephyr/arch/arm/aarch32/cortex_m/arm_mpu_mem_cfg.h deleted file mode 100644 index c16d1f4d782..00000000000 --- a/include/zephyr/arch/arm/aarch32/cortex_m/arm_mpu_mem_cfg.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2017 Linaro Limited. - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef _ARM_CORTEX_M_MPU_MEM_CFG_H_ -#define _ARM_CORTEX_M_MPU_MEM_CFG_H_ - -#include - -#if !defined(CONFIG_ARMV8_M_BASELINE) && !defined(CONFIG_ARMV8_M_MAINLINE) - -/* Flash Region Definitions */ -#if CONFIG_FLASH_SIZE <= 64 -#define REGION_FLASH_SIZE REGION_64K -#elif CONFIG_FLASH_SIZE <= 128 -#define REGION_FLASH_SIZE REGION_128K -#elif CONFIG_FLASH_SIZE <= 256 -#define REGION_FLASH_SIZE REGION_256K -#elif CONFIG_FLASH_SIZE <= 512 -#define REGION_FLASH_SIZE REGION_512K -#elif CONFIG_FLASH_SIZE <= 1024 -#define REGION_FLASH_SIZE REGION_1M -#elif CONFIG_FLASH_SIZE <= 2048 -#define REGION_FLASH_SIZE REGION_2M -#elif CONFIG_FLASH_SIZE <= 4096 -#define REGION_FLASH_SIZE REGION_4M -#elif CONFIG_FLASH_SIZE <= 8192 -#define REGION_FLASH_SIZE REGION_8M -#elif CONFIG_FLASH_SIZE <= 16384 -#define REGION_FLASH_SIZE REGION_16M -#elif CONFIG_FLASH_SIZE <= 65536 -#define REGION_FLASH_SIZE REGION_64M -#elif CONFIG_FLASH_SIZE <= 131072 -#define REGION_FLASH_SIZE REGION_128M -#elif CONFIG_FLASH_SIZE <= 262144 -#define REGION_FLASH_SIZE REGION_256M -#elif CONFIG_FLASH_SIZE <= 524288 -#define REGION_FLASH_SIZE REGION_512M -#else -#error "Unsupported flash size configuration" -#endif - -/* SRAM Region Definitions */ -#if CONFIG_SRAM_SIZE <= 16 -#define REGION_SRAM_SIZE REGION_16K -#elif CONFIG_SRAM_SIZE <= 32 -#define REGION_SRAM_SIZE REGION_32K -#elif CONFIG_SRAM_SIZE <= 64 -#define REGION_SRAM_SIZE REGION_64K -#elif CONFIG_SRAM_SIZE <= 128 -#define REGION_SRAM_SIZE REGION_128K -#elif CONFIG_SRAM_SIZE <= 256 -#define REGION_SRAM_SIZE REGION_256K -#elif CONFIG_SRAM_SIZE <= 512 -#define REGION_SRAM_SIZE REGION_512K -#elif CONFIG_SRAM_SIZE <= 1024 -#define REGION_SRAM_SIZE REGION_1M -#elif CONFIG_SRAM_SIZE <= 2048 -#define REGION_SRAM_SIZE REGION_2M -#elif CONFIG_SRAM_SIZE <= 4096 -#define REGION_SRAM_SIZE REGION_4M -#elif CONFIG_SRAM_SIZE <= 8192 -#define REGION_SRAM_SIZE REGION_8M -#elif CONFIG_SRAM_SIZE <= 16384 -#define REGION_SRAM_SIZE REGION_16M -#elif CONFIG_SRAM_SIZE == 32768 -#define REGION_SRAM_SIZE REGION_32M -#elif CONFIG_SRAM_SIZE == 65536 -#define REGION_SRAM_SIZE REGION_64M -#else -#error "Unsupported sram size configuration" -#endif - -#define MPU_REGION_SIZE_32 REGION_32B -#define MPU_REGION_SIZE_64 REGION_64B -#define MPU_REGION_SIZE_128 REGION_128B -#define MPU_REGION_SIZE_256 REGION_256B -#define MPU_REGION_SIZE_512 REGION_512B -#define MPU_REGION_SIZE_1024 REGION_1K -#define MPU_REGION_SIZE_2048 REGION_2K -#define MPU_REGION_SIZE_4096 REGION_4K -#define MPU_REGION_SIZE_8192 REGION_8K -#define MPU_REGION_SIZE_16384 REGION_16K -#define MPU_REGION_SIZE_32768 REGION_32K -#define MPU_REGION_SIZE_65536 REGION_64K -#define MPU_REGION_SIZE_131072 REGION_128K -#define MPU_REGION_SIZE_262144 REGION_256K -#define MPU_REGION_SIZE_524288 REGION_512K -#define MPU_REGION_SIZE_1048576 REGION_1M -#define MPU_REGION_SIZE_2097152 REGION_2M -#define MPU_REGION_SIZE_4194304 REGION_4M -#define MPU_REGION_SIZE_8388608 REGION_8M -#define MPU_REGION_SIZE_16777216 REGION_16M -#define MPU_REGION_SIZE_33554432 REGION_32M -#define MPU_REGION_SIZE_67108864 REGION_64M -#define MPU_REGION_SIZE_134217728 REGION_128M -#define MPU_REGION_SIZE_268435456 REGION_256M -#define MPU_REGION_SIZE_536870912 REGION_512M - -#define MPU_REGION_SIZE(x) MPU_REGION_SIZE_ ## x - -#define ARM_MPU_REGION_INIT(p_name, p_base, p_size, p_attr) \ - { .name = p_name, \ - .base = p_base, \ - .attr = p_attr(MPU_REGION_SIZE(p_size)), \ - } - -#else - -#define ARM_MPU_REGION_INIT(p_name, p_base, p_size, p_attr) \ - { .name = p_name, \ - .base = p_base, \ - .attr = p_attr(p_base, p_size), \ - } - -#endif /* !ARMV8_M_BASELINE && !ARMV8_M_MAINLINE */ - -#endif /* _ARM_CORTEX_M_MPU_MEM_CFG_H_ */ diff --git a/include/zephyr/arch/arm/aarch32/cortex_m/scripts/linker.ld b/include/zephyr/arch/arm/aarch32/cortex_m/scripts/linker.ld deleted file mode 100644 index 85d55b2de29..00000000000 --- a/include/zephyr/arch/arm/aarch32/cortex_m/scripts/linker.ld +++ /dev/null @@ -1,514 +0,0 @@ -/* - * Copyright (c) 2013-2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * Linker script for the Cortex-M platforms. - */ - -#include -#include - -#include -#include -#include - -/* physical address of RAM */ -#ifdef CONFIG_XIP -#define ROMABLE_REGION FLASH -#else -#define ROMABLE_REGION RAM -#endif -#define RAMABLE_REGION RAM - -#if USE_PARTITION_MANAGER - -#include - -#if CONFIG_NCS_IS_VARIANT_IMAGE && defined(PM_S0_ID) -/* We are linking against S1, create symbol containing the flash ID of S0. - * This is used when writing code operating on the "other" slot. - */ -_image_1_primary_slot_id = PM_S0_ID; - -#else /* ! CONFIG_NCS_IS_VARIANT_IMAGE */ - -#ifdef PM_S1_ID -/* We are linking against S0, create symbol containing the flash ID of S1. - * This is used when writing code operating on the "other" slot. - */ -_image_1_primary_slot_id = PM_S1_ID; -#endif /* PM_S1_ID */ - -#endif /* CONFIG_NCS_IS_VARIANT_IMAGE */ - -#define ROM_ADDR PM_ADDRESS -#define ROM_SIZE PM_SIZE - -#define RAM_SIZE PM_SRAM_SIZE -#define RAM_ADDR PM_SRAM_ADDRESS - -#else /* ! USE_PARTITION_MANAGER */ - -#if !defined(CONFIG_XIP) && (CONFIG_FLASH_SIZE == 0) -#define ROM_ADDR RAM_ADDR -#else -#define ROM_ADDR (CONFIG_FLASH_BASE_ADDRESS + CONFIG_FLASH_LOAD_OFFSET) -#endif - -#if CONFIG_FLASH_LOAD_SIZE > 0 -#define ROM_SIZE CONFIG_FLASH_LOAD_SIZE -#else -#define ROM_SIZE (CONFIG_FLASH_SIZE*1K - CONFIG_FLASH_LOAD_OFFSET) -#endif - -#if defined(CONFIG_XIP) -#if defined(CONFIG_IS_BOOTLOADER) -#define RAM_SIZE (CONFIG_BOOTLOADER_SRAM_SIZE * 1K) -#define RAM_ADDR (CONFIG_SRAM_BASE_ADDRESS + \ - (CONFIG_SRAM_SIZE * 1K - RAM_SIZE)) -#else -#define RAM_SIZE (CONFIG_SRAM_SIZE * 1K) -#define RAM_ADDR CONFIG_SRAM_BASE_ADDRESS -#endif -#else -#define RAM_SIZE (CONFIG_SRAM_SIZE * 1K - CONFIG_BOOTLOADER_SRAM_SIZE * 1K) -#define RAM_ADDR CONFIG_SRAM_BASE_ADDRESS -#endif - -#endif /* USE_PARTITION_MANAGER */ - -#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ccm), okay) -#define CCM_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_ccm)) -#define CCM_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_ccm)) -#endif - -#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_itcm), okay) -#define ITCM_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_itcm)) -#define ITCM_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_itcm)) -#endif - -#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay) -#define DTCM_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_dtcm)) -#define DTCM_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_dtcm)) -#endif - -#if defined(CONFIG_CUSTOM_SECTION_ALIGN) -_region_min_align = CONFIG_CUSTOM_SECTION_MIN_ALIGN_SIZE; -#else -/* Set alignment to CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE - * to make linker section alignment comply with MPU granularity. - */ -#if defined(CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE) -_region_min_align = CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE; -#else -/* If building without MPU support, use default 4-byte alignment. */ -_region_min_align = 4; -#endif -#endif - -#if !defined(CONFIG_CUSTOM_SECTION_ALIGN) && defined(CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT) -#define MPU_ALIGN(region_size) \ - . = ALIGN(_region_min_align); \ - . = ALIGN( 1 << LOG2CEIL(region_size)) -#else -#define MPU_ALIGN(region_size) \ - . = ALIGN(_region_min_align) -#endif - -MEMORY - { - FLASH (rx) : ORIGIN = ROM_ADDR, LENGTH = ROM_SIZE - RAM (wx) : ORIGIN = RAM_ADDR, LENGTH = RAM_SIZE - LINKER_DT_REGIONS() - /* Used by and documented in include/linker/intlist.ld */ - IDT_LIST (wx) : ORIGIN = 0xFFFFF7FF, LENGTH = 2K - } - -ENTRY(CONFIG_KERNEL_ENTRY) - -SECTIONS - { - -#include - - /* - * .plt and .iplt are here according to 'arm-zephyr-elf-ld --verbose', - * before text section. - */ - /DISCARD/ : - { - *(.plt) - } - - /DISCARD/ : - { - *(.iplt) - } - - GROUP_START(ROMABLE_REGION) - - __rom_region_start = ROM_ADDR; - - SECTION_PROLOGUE(rom_start,,) - { - -/* Located in generated directory. This file is populated by calling - * zephyr_linker_sources(ROM_START ...). This typically contains the vector - * table and debug information. - */ -#include - - } GROUP_LINK_IN(ROMABLE_REGION) - -#ifdef CONFIG_CODE_DATA_RELOCATION - -#include - -#endif /* CONFIG_CODE_DATA_RELOCATION */ - - SECTION_PROLOGUE(_TEXT_SECTION_NAME,,) - { - __text_region_start = .; - -#include - - *(.text) - *(".text.*") - *(".TEXT.*") - *(.gnu.linkonce.t.*) - - /* - * These are here according to 'arm-zephyr-elf-ld --verbose', - * after .gnu.linkonce.t.* - */ - *(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx) - . = ALIGN(4); - - } GROUP_LINK_IN(ROMABLE_REGION) - - __text_region_end = .; - -#if defined (CONFIG_CPP) - SECTION_PROLOGUE(.ARM.extab,,) - { - /* - * .ARM.extab section containing exception unwinding information. - */ - *(.ARM.extab* .gnu.linkonce.armextab.*) - } GROUP_LINK_IN(ROMABLE_REGION) -#endif - - SECTION_PROLOGUE(.ARM.exidx,,) - { - /* - * This section, related to stack and exception unwinding, is placed - * explicitly to prevent it from being shared between multiple regions. - * It must be defined for gcc to support 64-bit math and avoid - * section overlap. - */ - __exidx_start = .; -#if defined (__GCC_LINKER_CMD__) - *(.ARM.exidx* gnu.linkonce.armexidx.*) -#endif - __exidx_end = .; - } GROUP_LINK_IN(ROMABLE_REGION) - - __rodata_region_start = .; - -#include -#include - - SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) - { - *(.rodata) - *(".rodata.*") - *(.gnu.linkonce.r.*) - -/* Located in generated directory. This file is populated by the - * zephyr_linker_sources() Cmake function. - */ -#include - -#include - - /* - * For XIP images, in order to avoid the situation when __data_rom_start - * is 32-bit aligned, but the actual data is placed right after rodata - * section, which may not end exactly at 32-bit border, pad rodata - * section, so __data_rom_start points at data and it is 32-bit aligned. - * - * On non-XIP images this may enlarge image size up to 3 bytes. This - * generally is not an issue, since modern ROM and FLASH memory is - * usually 4k aligned. - */ - . = ALIGN(4); - } GROUP_LINK_IN(ROMABLE_REGION) - -#include - -#if defined(CONFIG_BUILD_ALIGN_LMA) - /* - * Include a padding section here to make sure that the LMA address - * of the sections in the RAMABLE_REGION are aligned with those - * section's VMA alignment requirements. - */ - SECTION_PROLOGUE(padding_section,,) - { - __rodata_region_end = .; - MPU_ALIGN(__rodata_region_end - ADDR(rom_start)); - } GROUP_LINK_IN(ROMABLE_REGION) -#else - __rodata_region_end = .; - MPU_ALIGN(__rodata_region_end - ADDR(rom_start)); -#endif - __rom_region_end = __rom_region_start + . - ADDR(rom_start); - - GROUP_END(ROMABLE_REGION) - - /* - * These are here according to 'arm-zephyr-elf-ld --verbose', - * before data section. - */ - /DISCARD/ : { - *(.got.plt) - *(.igot.plt) - *(.got) - *(.igot) - } - - GROUP_START(RAMABLE_REGION) - - . = RAM_ADDR; - /* Align the start of image RAM with the - * minimum granularity required by MPU. - */ - . = ALIGN(_region_min_align); - _image_ram_start = .; - -/* Located in generated directory. This file is populated by the - * zephyr_linker_sources() Cmake function. - */ -#include - -#if defined(CONFIG_USERSPACE) -#define APP_SHARED_ALIGN . = ALIGN(_region_min_align); -#define SMEM_PARTITION_ALIGN MPU_ALIGN - -#include - - _app_smem_size = _app_smem_end - _app_smem_start; - _app_smem_rom_start = LOADADDR(_APP_SMEM_SECTION_NAME); - - SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) - { - /* - * For performance, BSS section is assumed to be 4 byte aligned and - * a multiple of 4 bytes - */ - . = ALIGN(4); - __bss_start = .; - __kernel_ram_start = .; - - *(.bss) - *(".bss.*") - *(COMMON) - *(".kernel_bss.*") - -#ifdef CONFIG_CODE_DATA_RELOCATION -#include -#endif - - /* - * As memory is cleared in words only, it is simpler to ensure the BSS - * section ends on a 4 byte boundary. This wastes a maximum of 3 bytes. - */ - __bss_end = ALIGN(4); - } GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION) - -#include - -#endif /* CONFIG_USERSPACE */ - - GROUP_START(DATA_REGION) - - SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,) - { - __data_region_start = .; - __data_start = .; - *(.data) - *(".data.*") - *(".kernel.*") - -/* Located in generated directory. This file is populated by the - * zephyr_linker_sources() Cmake function. - */ -#include - -#ifdef CONFIG_CODE_DATA_RELOCATION -#include -#endif - __data_end = .; - - } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) - __data_size = __data_end - __data_start; - __data_load_start = LOADADDR(_DATA_SECTION_NAME); - - __data_region_load_start = LOADADDR(_DATA_SECTION_NAME); - -#include -#include - -#include - -/* Located in generated directory. This file is populated by the - * zephyr_linker_sources() Cmake function. - */ -#include - - __data_region_end = .; - -#ifndef CONFIG_USERSPACE - SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) - { - /* - * For performance, BSS section is assumed to be 4 byte aligned and - * a multiple of 4 bytes - */ - . = ALIGN(4); - __bss_start = .; - __kernel_ram_start = .; - - *(.bss) - *(".bss.*") - *(COMMON) - *(".kernel_bss.*") - -#ifdef CONFIG_CODE_DATA_RELOCATION -#include -#endif - - /* - * As memory is cleared in words only, it is simpler to ensure the BSS - * section ends on a 4 byte boundary. This wastes a maximum of 3 bytes. - */ - __bss_end = ALIGN(4); - } GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION) - - SECTION_PROLOGUE(_NOINIT_SECTION_NAME,(NOLOAD),) - { - /* - * This section is used for non-initialized objects that - * will not be cleared during the boot process. - */ - *(.noinit) - *(".noinit.*") - *(".kernel_noinit.*") - -/* Located in generated directory. This file is populated by the - * zephyr_linker_sources() Cmake function. - */ -#include - - } GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, RAMABLE_REGION) -#endif /* CONFIG_USERSPACE */ - - /* Define linker symbols */ - - __kernel_ram_end = RAM_ADDR + RAM_SIZE; - __kernel_ram_size = __kernel_ram_end - __kernel_ram_start; - -#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_itcm), okay) -GROUP_START(ITCM) - - SECTION_PROLOGUE(_ITCM_SECTION_NAME,,SUBALIGN(4)) - { - __itcm_start = .; - *(.itcm) - *(".itcm.*") - __itcm_end = .; - } GROUP_LINK_IN(ITCM AT> ROMABLE_REGION) - - __itcm_size = __itcm_end - __itcm_start; - __itcm_load_start = LOADADDR(_ITCM_SECTION_NAME); - -GROUP_END(ITCM) -#endif - -#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay) -GROUP_START(DTCM) - - SECTION_PROLOGUE(_DTCM_BSS_SECTION_NAME, (NOLOAD),SUBALIGN(4)) - { - __dtcm_start = .; - __dtcm_bss_start = .; - *(.dtcm_bss) - *(".dtcm_bss.*") - __dtcm_bss_end = .; - } GROUP_LINK_IN(DTCM) - - SECTION_PROLOGUE(_DTCM_NOINIT_SECTION_NAME, (NOLOAD),SUBALIGN(4)) - { - __dtcm_noinit_start = .; - *(.dtcm_noinit) - *(".dtcm_noinit.*") - __dtcm_noinit_end = .; - } GROUP_LINK_IN(DTCM) - - SECTION_PROLOGUE(_DTCM_DATA_SECTION_NAME,,SUBALIGN(4)) - { - __dtcm_data_start = .; - *(.dtcm_data) - *(".dtcm_data.*") - __dtcm_data_end = .; - } GROUP_LINK_IN(DTCM AT> ROMABLE_REGION) - - __dtcm_end = .; - - __dtcm_data_load_start = LOADADDR(_DTCM_DATA_SECTION_NAME); - -GROUP_END(DTCM) -#endif - -/* Located in generated directory. This file is populated by the - * zephyr_linker_sources() Cmake function. - */ -#include - -#include - - GROUP_END(RAMABLE_REGION) - -#include - - /DISCARD/ : { *(.note.GNU-stack) } - - SECTION_PROLOGUE(.ARM.attributes, 0,) - { - KEEP(*(.ARM.attributes)) - KEEP(*(.gnu.attributes)) - } - - /* Sections generated from 'zephyr,memory-region' nodes */ - LINKER_DT_SECTIONS() - -/* Must be last in romable region */ -SECTION_PROLOGUE(.last_section,,) -{ -#ifdef CONFIG_LINKER_LAST_SECTION_ID - /* Fill last section with a word to ensure location counter and actual rom - * region data usage match. */ - LONG(CONFIG_LINKER_LAST_SECTION_ID_PATTERN) -#endif -} GROUP_LINK_IN(ROMABLE_REGION) - -/* To provide the image size as a const expression, - * calculate this value here. */ -_flash_used = LOADADDR(.last_section) + SIZEOF(.last_section) - __rom_region_start; - - } diff --git a/include/zephyr/arch/arm/aarch32/cortex_r/scripts/linker.ld b/include/zephyr/arch/arm/aarch32/cortex_r/scripts/linker.ld deleted file mode 100644 index 545b371bbd5..00000000000 --- a/include/zephyr/arch/arm/aarch32/cortex_r/scripts/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2020 Stephanos Ioannidis - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/include/zephyr/arch/arm/aarch32/exc.h b/include/zephyr/arch/arm/aarch32/exc.h deleted file mode 100644 index b9d61573698..00000000000 --- a/include/zephyr/arch/arm/aarch32/exc.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2013-2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief ARM AArch32 public exception handling - * - * ARM AArch32-specific kernel exception handling interface. Included by - * arm/arch.h. - */ - -#ifndef ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_EXC_H_ -#define ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_EXC_H_ - -#if defined(CONFIG_CPU_CORTEX_M) -#include - -#include - -/* for assembler, only works with constants */ -#define Z_EXC_PRIO(pri) (((pri) << (8 - NUM_IRQ_PRIO_BITS)) & 0xff) - -/* - * In architecture variants with non-programmable fault exceptions - * (e.g. Cortex-M Baseline variants), hardware ensures processor faults - * are given the highest interrupt priority level. SVCalls are assigned - * the highest configurable priority level (level 0); note, however, that - * this interrupt level may be shared with HW interrupts. - * - * In Cortex variants with programmable fault exception priorities we - * assign the highest interrupt priority level (level 0) to processor faults - * with configurable priority. - * The highest priority level may be shared with either Zero-Latency IRQs (if - * support for the feature is enabled) or with SVCall priority level. - * Regular HW IRQs are always assigned priority levels lower than the priority - * levels for SVCalls, Zero-Latency IRQs and processor faults. - * - * PendSV IRQ (which is used in Cortex-M variants to implement thread - * context-switching) is assigned the lowest IRQ priority level. - */ -#if defined(CONFIG_CPU_CORTEX_M_HAS_PROGRAMMABLE_FAULT_PRIOS) -#define _EXCEPTION_RESERVED_PRIO 1 -#else -#define _EXCEPTION_RESERVED_PRIO 0 -#endif - -#define _EXC_FAULT_PRIO 0 -#define _EXC_ZERO_LATENCY_IRQS_PRIO 0 -#define _EXC_SVC_PRIO COND_CODE_1(CONFIG_ZERO_LATENCY_IRQS, \ - (CONFIG_ZERO_LATENCY_LEVELS), (0)) -#define _IRQ_PRIO_OFFSET (_EXCEPTION_RESERVED_PRIO + _EXC_SVC_PRIO) -#define IRQ_PRIO_LOWEST (BIT(NUM_IRQ_PRIO_BITS) - (_IRQ_PRIO_OFFSET) - 1) - -#define _EXC_IRQ_DEFAULT_PRIO Z_EXC_PRIO(_IRQ_PRIO_OFFSET) - -/* Use lowest possible priority level for PendSV */ -#define _EXC_PENDSV_PRIO 0xff -#define _EXC_PENDSV_PRIO_MASK Z_EXC_PRIO(_EXC_PENDSV_PRIO) -#endif /* CONFIG_CPU_CORTEX_M */ - -#ifdef _ASMLANGUAGE -GTEXT(z_arm_exc_exit); -#else -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) - -/* Registers s16-s31 (d8-d15, q4-q7) must be preserved across subroutine calls. - * - * Registers s0-s15 (d0-d7, q0-q3) do not have to be preserved (and can be used - * for passing arguments or returning results in standard procedure-call variants). - * - * Registers d16-d31 (q8-q15), do not have to be preserved. - */ -struct __fpu_sf { - uint32_t s[16]; /* s0~s15 (d0-d7) */ -#ifdef CONFIG_VFP_FEATURE_REGS_S64_D32 - uint64_t d[16]; /* d16~d31 */ -#endif - uint32_t fpscr; - uint32_t undefined; -}; -#endif - -/* Additional register state that is not stacked by hardware on exception - * entry. - * - * These fields are ONLY valid in the ESF copy passed into z_arm_fatal_error(). - * When information for a member is unavailable, the field is set to zero. - */ -#if defined(CONFIG_EXTRA_EXCEPTION_INFO) -struct __extra_esf_info { - _callee_saved_t *callee; - uint32_t msp; - uint32_t exc_return; -}; -#endif /* CONFIG_EXTRA_EXCEPTION_INFO */ - -#if defined(CONFIG_CPU_CORTEX_M) - -struct __esf { - struct __basic_sf { - sys_define_gpr_with_alias(a1, r0); - sys_define_gpr_with_alias(a2, r1); - sys_define_gpr_with_alias(a3, r2); - sys_define_gpr_with_alias(a4, r3); - sys_define_gpr_with_alias(ip, r12); - sys_define_gpr_with_alias(lr, r14); - sys_define_gpr_with_alias(pc, r15); - uint32_t xpsr; - } basic; -#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) - struct __fpu_sf fpu; -#endif -#if defined(CONFIG_EXTRA_EXCEPTION_INFO) - struct __extra_esf_info extra_info; -#endif -}; - -#else - -struct __esf { -#if defined(CONFIG_EXTRA_EXCEPTION_INFO) - struct __extra_esf_info extra_info; -#endif -#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) - struct __fpu_sf fpu; -#endif - struct __basic_sf { - sys_define_gpr_with_alias(a1, r0); - sys_define_gpr_with_alias(a2, r1); - sys_define_gpr_with_alias(a3, r2); - sys_define_gpr_with_alias(a4, r3); - sys_define_gpr_with_alias(ip, r12); - sys_define_gpr_with_alias(lr, r14); - sys_define_gpr_with_alias(pc, r15); - uint32_t xpsr; - } basic; -}; - -#endif - -extern uint32_t z_arm_coredump_fault_sp; - -typedef struct __esf z_arch_esf_t; - -#ifdef CONFIG_CPU_CORTEX_M -extern void z_arm_exc_exit(void); -#else -extern void z_arm_exc_exit(bool fatal); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _ASMLANGUAGE */ - -#endif /* ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_EXC_H_ */ diff --git a/include/zephyr/arch/arm/aarch32/arch.h b/include/zephyr/arch/arm/arch.h similarity index 91% rename from include/zephyr/arch/arm/aarch32/arch.h rename to include/zephyr/arch/arm/arch.h index 15426b39e06..a726bba8502 100644 --- a/include/zephyr/arch/arm/aarch32/arch.h +++ b/include/zephyr/arch/arm/arch.h @@ -22,29 +22,29 @@ /* ARM GPRs are often designated by two different names */ #define sys_define_gpr_with_alias(name1, name2) union { uint32_t name1, name2; } -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include -#include -#include +#include +#include #include #ifdef CONFIG_CPU_CORTEX_M -#include -#include +#include +#include #include #elif defined(CONFIG_CPU_AARCH32_CORTEX_R) || defined(CONFIG_CPU_AARCH32_CORTEX_A) -#include -#include +#include +#include #if defined(CONFIG_AARCH32_ARMV8_R) -#include -#include +#include +#include #else -#include +#include #endif #endif @@ -265,14 +265,14 @@ enum k_fatal_error_reason_arch { /* Legacy case: retain containing extern "C" with C++ */ #ifdef CONFIG_ARM_MPU #ifdef CONFIG_CPU_HAS_ARM_MPU -#include +#include #endif /* CONFIG_CPU_HAS_ARM_MPU */ #ifdef CONFIG_CPU_HAS_NXP_MPU -#include +#include #endif /* CONFIG_CPU_HAS_NXP_MPU */ #endif /* CONFIG_ARM_MPU */ #ifdef CONFIG_ARM_AARCH32_MMU -#include +#include #endif /* CONFIG_ARM_AARCH32_MMU */ #ifdef __cplusplus diff --git a/include/zephyr/arch/arm/aarch32/arch_inlines.h b/include/zephyr/arch/arm/arch_inlines.h similarity index 81% rename from include/zephyr/arch/arm/aarch32/arch_inlines.h rename to include/zephyr/arch/arm/arch_inlines.h index 5d86858b05b..96822e0eff1 100644 --- a/include/zephyr/arch/arm/aarch32/arch_inlines.h +++ b/include/zephyr/arch/arm/arch_inlines.h @@ -8,14 +8,14 @@ #define ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_ARCH_INLINES_H #include +#include +#include -#ifndef CONFIG_SMP static ALWAYS_INLINE _cpu_t *arch_curr_cpu(void) { /* Dummy implementation always return the first cpu */ - return &_kernel.cpus[0]; + return (_cpu_t *)(read_tpidruro() & TPIDRURO_CURR_CPU); } -#endif static ALWAYS_INLINE uint32_t arch_proc_id(void) { diff --git a/include/zephyr/arch/arm/aarch32/asm_inline.h b/include/zephyr/arch/arm/asm_inline.h similarity index 90% rename from include/zephyr/arch/arm/aarch32/asm_inline.h rename to include/zephyr/arch/arm/asm_inline.h index 0f1aa22310c..c083adcd47a 100644 --- a/include/zephyr/arch/arm/aarch32/asm_inline.h +++ b/include/zephyr/arch/arm/asm_inline.h @@ -15,7 +15,7 @@ */ #if defined(__GNUC__) -#include +#include #else #include #endif diff --git a/include/zephyr/arch/arm/aarch32/asm_inline_gcc.h b/include/zephyr/arch/arm/asm_inline_gcc.h similarity index 89% rename from include/zephyr/arch/arm/aarch32/asm_inline_gcc.h rename to include/zephyr/arch/arm/asm_inline_gcc.h index 71665eefdfb..3b8e8e19c92 100644 --- a/include/zephyr/arch/arm/aarch32/asm_inline_gcc.h +++ b/include/zephyr/arch/arm/asm_inline_gcc.h @@ -18,11 +18,12 @@ #ifndef _ASMLANGUAGE +#include #include -#include +#include #if defined(CONFIG_CPU_AARCH32_CORTEX_R) || defined(CONFIG_CPU_AARCH32_CORTEX_A) -#include +#include #endif #ifdef __cplusplus @@ -44,11 +45,15 @@ static ALWAYS_INLINE unsigned int arch_irq_lock(void) unsigned int key; #if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) +#if CONFIG_MP_MAX_NUM_CPUS == 1 || defined(CONFIG_ARMV8_M_BASELINE) __asm__ volatile("mrs %0, PRIMASK;" "cpsid i" : "=r" (key) : : "memory"); +#else +#error "Cortex-M0 and Cortex-M0+ require SoC specific support for cross core synchronisation." +#endif #elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) unsigned int tmp; @@ -64,7 +69,7 @@ static ALWAYS_INLINE unsigned int arch_irq_lock(void) || defined(CONFIG_ARMV7_A) __asm__ volatile( "mrs %0, cpsr;" - "and %0, #" TOSTR(I_BIT) ";" + "and %0, #" STRINGIFY(I_BIT) ";" "cpsid i;" : "=r" (key) : diff --git a/include/zephyr/arch/arm/aarch32/barrier.h b/include/zephyr/arch/arm/barrier.h similarity index 100% rename from include/zephyr/arch/arm/aarch32/barrier.h rename to include/zephyr/arch/arm/barrier.h diff --git a/include/zephyr/arch/arm/aarch32/cortex_a_r/armv8_timer.h b/include/zephyr/arch/arm/cortex_a_r/armv8_timer.h similarity index 100% rename from include/zephyr/arch/arm/aarch32/cortex_a_r/armv8_timer.h rename to include/zephyr/arch/arm/cortex_a_r/armv8_timer.h diff --git a/include/zephyr/arch/arm/aarch32/cortex_a_r/cmsis.h b/include/zephyr/arch/arm/cortex_a_r/cmsis.h similarity index 100% rename from include/zephyr/arch/arm/aarch32/cortex_a_r/cmsis.h rename to include/zephyr/arch/arm/cortex_a_r/cmsis.h diff --git a/include/zephyr/arch/arm/aarch32/cortex_a_r/cpu.h b/include/zephyr/arch/arm/cortex_a_r/cpu.h similarity index 98% rename from include/zephyr/arch/arm/aarch32/cortex_a_r/cpu.h rename to include/zephyr/arch/arm/cortex_a_r/cpu.h index 4c4901f5cbe..806d28247ac 100644 --- a/include/zephyr/arch/arm/aarch32/cortex_a_r/cpu.h +++ b/include/zephyr/arch/arm/cortex_a_r/cpu.h @@ -8,7 +8,7 @@ #define ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_CORTEX_A_R_CPU_H_ #if defined(CONFIG_ARM_MPU) -#include +#include #endif /* diff --git a/include/zephyr/arch/arm/cortex_a_r/exc.h b/include/zephyr/arch/arm/cortex_a_r/exc.h new file mode 100644 index 00000000000..92f074f1b36 --- /dev/null +++ b/include/zephyr/arch/arm/cortex_a_r/exc.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief ARM AArch32 Cortex-A and Cortex-R public exception handling + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_CORTEX_A_R_EXC_H_ +#define ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_CORTEX_A_R_EXC_H_ + +#ifdef _ASMLANGUAGE +GTEXT(z_arm_exc_exit); +#else +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) + +/* Registers s16-s31 (d8-d15, q4-q7) must be preserved across subroutine calls. + * + * Registers s0-s15 (d0-d7, q0-q3) do not have to be preserved (and can be used + * for passing arguments or returning results in standard procedure-call variants). + * + * Registers d16-d31 (q8-q15), do not have to be preserved. + */ +struct __fpu_sf { + uint32_t s[16]; /* s0~s15 (d0-d7) */ +#ifdef CONFIG_VFP_FEATURE_REGS_S64_D32 + uint64_t d[16]; /* d16~d31 */ +#endif + uint32_t fpscr; + uint32_t undefined; +}; +#endif + +/* Additional register state that is not stacked by hardware on exception + * entry. + * + * These fields are ONLY valid in the ESF copy passed into z_arm_fatal_error(). + * When information for a member is unavailable, the field is set to zero. + */ +#if defined(CONFIG_EXTRA_EXCEPTION_INFO) +struct __extra_esf_info { + _callee_saved_t *callee; + uint32_t msp; + uint32_t exc_return; +}; +#endif /* CONFIG_EXTRA_EXCEPTION_INFO */ + +struct __esf { +#if defined(CONFIG_EXTRA_EXCEPTION_INFO) + struct __extra_esf_info extra_info; +#endif +#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) + struct __fpu_sf fpu; +#endif + struct __basic_sf { + sys_define_gpr_with_alias(a1, r0); + sys_define_gpr_with_alias(a2, r1); + sys_define_gpr_with_alias(a3, r2); + sys_define_gpr_with_alias(a4, r3); + sys_define_gpr_with_alias(ip, r12); + sys_define_gpr_with_alias(lr, r14); + sys_define_gpr_with_alias(pc, r15); + uint32_t xpsr; + } basic; +}; + +extern uint32_t z_arm_coredump_fault_sp; + +typedef struct __esf z_arch_esf_t; + +extern void z_arm_exc_exit(bool fatal); + +#ifdef __cplusplus +} +#endif + +#endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_CORTEX_A_R_EXC_H_ */ diff --git a/include/zephyr/arch/arm/aarch32/cortex_a_r/lib_helpers.h b/include/zephyr/arch/arm/cortex_a_r/lib_helpers.h similarity index 94% rename from include/zephyr/arch/arm/aarch32/cortex_a_r/lib_helpers.h rename to include/zephyr/arch/arm/cortex_a_r/lib_helpers.h index a4e74b0daa4..7b89ddf515c 100644 --- a/include/zephyr/arch/arm/aarch32/cortex_a_r/lib_helpers.h +++ b/include/zephyr/arch/arm/cortex_a_r/lib_helpers.h @@ -72,6 +72,7 @@ MAKE_REG_HELPER(mair0, 0, 10, 2, 0); MAKE_REG_HELPER(vbar, 0, 12, 0, 0); MAKE_REG_HELPER(cntv_ctl, 0, 14, 3, 1); MAKE_REG_HELPER(ctr, 0, 0, 0, 1); +MAKE_REG_HELPER(tpidruro, 0, 13, 0, 3); MAKE_REG64_HELPER(ICC_SGI1R, 0, 12); MAKE_REG64_HELPER(cntvct, 1, 14); MAKE_REG64_HELPER(cntv_cval, 3, 14); @@ -98,5 +99,8 @@ MAKE_REG_HELPER(ICC_IGRPEN1_EL1, 0, 12, 12, 7); #define write_sysreg(val, reg) write_##reg(val) #define read_sysreg(reg) read_##reg() +#define sev() __asm__ volatile("sev" : : : "memory") +#define wfe() __asm__ volatile("wfe" : : : "memory") + #endif /* !_ASMLANGUAGE */ #endif /* ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_CORTEX_A_R_LIB_HELPERS_H_ */ diff --git a/include/zephyr/arch/arm/aarch32/cortex_a_r/mpu.h b/include/zephyr/arch/arm/cortex_a_r/mpu.h similarity index 100% rename from include/zephyr/arch/arm/aarch32/cortex_a_r/mpu.h rename to include/zephyr/arch/arm/cortex_a_r/mpu.h diff --git a/include/zephyr/arch/arm/aarch32/cortex_a_r/scripts/app_data_alignment.ld b/include/zephyr/arch/arm/cortex_a_r/scripts/app_data_alignment.ld similarity index 100% rename from include/zephyr/arch/arm/aarch32/cortex_a_r/scripts/app_data_alignment.ld rename to include/zephyr/arch/arm/cortex_a_r/scripts/app_data_alignment.ld diff --git a/include/zephyr/arch/arm/aarch32/cortex_a_r/scripts/linker.ld b/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld similarity index 100% rename from include/zephyr/arch/arm/aarch32/cortex_a_r/scripts/linker.ld rename to include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld diff --git a/include/zephyr/arch/arm/aarch32/cortex_a_r/sys_io.h b/include/zephyr/arch/arm/cortex_a_r/sys_io.h similarity index 100% rename from include/zephyr/arch/arm/aarch32/cortex_a_r/sys_io.h rename to include/zephyr/arch/arm/cortex_a_r/sys_io.h diff --git a/include/zephyr/arch/arm/aarch32/cortex_a_r/timer.h b/include/zephyr/arch/arm/cortex_a_r/timer.h similarity index 100% rename from include/zephyr/arch/arm/aarch32/cortex_a_r/timer.h rename to include/zephyr/arch/arm/cortex_a_r/timer.h diff --git a/include/zephyr/arch/arm/cortex_a_r/tpidruro.h b/include/zephyr/arch/arm/cortex_a_r/tpidruro.h new file mode 100644 index 00000000000..25eb275af9c --- /dev/null +++ b/include/zephyr/arch/arm/cortex_a_r/tpidruro.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Arm Limited (or its affiliates). All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief tpidruro bits allocation + * + * Among other things, the tpidruro holds the address for the current + * CPU's struct _cpu instance. But such a pointer is at least 4-bytes + * aligned. That leaves two of free bits for other purposes. + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_A_R_TPIDRURO_H_ +#define ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_A_R_TPIDRURO_H_ + +#define TPIDRURO_CURR_CPU 0xFFFFFFFCUL + +#endif /* ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_A_R_TPIDRURO_H_ */ diff --git a/include/zephyr/arch/arm/cortex_m/arm_mpu_mem_cfg.h b/include/zephyr/arch/arm/cortex_m/arm_mpu_mem_cfg.h new file mode 100644 index 00000000000..7f0d3e3ef66 --- /dev/null +++ b/include/zephyr/arch/arm/cortex_m/arm_mpu_mem_cfg.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017 Linaro Limited. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _ARM_CORTEX_M_MPU_MEM_CFG_H_ +#define _ARM_CORTEX_M_MPU_MEM_CFG_H_ + +#include + +#if !defined(CONFIG_ARMV8_M_BASELINE) && !defined(CONFIG_ARMV8_M_MAINLINE) + +/* Flash Region Definitions */ +#if CONFIG_FLASH_SIZE <= 64 +#define REGION_FLASH_SIZE REGION_64K +#elif CONFIG_FLASH_SIZE <= 128 +#define REGION_FLASH_SIZE REGION_128K +#elif CONFIG_FLASH_SIZE <= 256 +#define REGION_FLASH_SIZE REGION_256K +#elif CONFIG_FLASH_SIZE <= 512 +#define REGION_FLASH_SIZE REGION_512K +#elif CONFIG_FLASH_SIZE <= 1024 +#define REGION_FLASH_SIZE REGION_1M +#elif CONFIG_FLASH_SIZE <= 2048 +#define REGION_FLASH_SIZE REGION_2M +#elif CONFIG_FLASH_SIZE <= 4096 +#define REGION_FLASH_SIZE REGION_4M +#elif CONFIG_FLASH_SIZE <= 8192 +#define REGION_FLASH_SIZE REGION_8M +#elif CONFIG_FLASH_SIZE <= 16384 +#define REGION_FLASH_SIZE REGION_16M +#elif CONFIG_FLASH_SIZE <= 65536 +#define REGION_FLASH_SIZE REGION_64M +#elif CONFIG_FLASH_SIZE <= 131072 +#define REGION_FLASH_SIZE REGION_128M +#elif CONFIG_FLASH_SIZE <= 262144 +#define REGION_FLASH_SIZE REGION_256M +#elif CONFIG_FLASH_SIZE <= 524288 +#define REGION_FLASH_SIZE REGION_512M +#else +#error "Unsupported flash size configuration" +#endif + +/* SRAM Region Definitions */ +#if CONFIG_SRAM_SIZE <= 16 +#define REGION_SRAM_SIZE REGION_16K +#elif CONFIG_SRAM_SIZE <= 32 +#define REGION_SRAM_SIZE REGION_32K +#elif CONFIG_SRAM_SIZE <= 64 +#define REGION_SRAM_SIZE REGION_64K +#elif CONFIG_SRAM_SIZE <= 128 +#define REGION_SRAM_SIZE REGION_128K +#elif CONFIG_SRAM_SIZE <= 256 +#define REGION_SRAM_SIZE REGION_256K +#elif CONFIG_SRAM_SIZE <= 512 +#define REGION_SRAM_SIZE REGION_512K +#elif CONFIG_SRAM_SIZE <= 1024 +#define REGION_SRAM_SIZE REGION_1M +#elif CONFIG_SRAM_SIZE <= 2048 +#define REGION_SRAM_SIZE REGION_2M +#elif CONFIG_SRAM_SIZE <= 4096 +#define REGION_SRAM_SIZE REGION_4M +#elif CONFIG_SRAM_SIZE <= 8192 +#define REGION_SRAM_SIZE REGION_8M +#elif CONFIG_SRAM_SIZE <= 16384 +#define REGION_SRAM_SIZE REGION_16M +#elif CONFIG_SRAM_SIZE == 32768 +#define REGION_SRAM_SIZE REGION_32M +#elif CONFIG_SRAM_SIZE == 65536 +#define REGION_SRAM_SIZE REGION_64M +#else +#error "Unsupported sram size configuration" +#endif + +#endif /* !ARMV8_M_BASELINE && !ARMV8_M_MAINLINE */ + +#endif /* _ARM_CORTEX_M_MPU_MEM_CFG_H_ */ diff --git a/include/zephyr/arch/arm/aarch32/cortex_m/cmsis.h b/include/zephyr/arch/arm/cortex_m/cmsis.h similarity index 100% rename from include/zephyr/arch/arm/aarch32/cortex_m/cmsis.h rename to include/zephyr/arch/arm/cortex_m/cmsis.h diff --git a/include/zephyr/arch/arm/aarch32/cortex_m/cpu.h b/include/zephyr/arch/arm/cortex_m/cpu.h similarity index 100% rename from include/zephyr/arch/arm/aarch32/cortex_m/cpu.h rename to include/zephyr/arch/arm/cortex_m/cpu.h diff --git a/include/zephyr/arch/arm/cortex_m/exc.h b/include/zephyr/arch/arm/cortex_m/exc.h new file mode 100644 index 00000000000..8a2cfc8cc3f --- /dev/null +++ b/include/zephyr/arch/arm/cortex_m/exc.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief ARM AArch32 Cortex-M public exception handling + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_CORTEX_M_EXC_H_ +#define ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_CORTEX_M_EXC_H_ + +#include + +#include + +/* for assembler, only works with constants */ +#define Z_EXC_PRIO(pri) (((pri) << (8 - NUM_IRQ_PRIO_BITS)) & 0xff) + +/* + * In architecture variants with non-programmable fault exceptions + * (e.g. Cortex-M Baseline variants), hardware ensures processor faults + * are given the highest interrupt priority level. SVCalls are assigned + * the highest configurable priority level (level 0); note, however, that + * this interrupt level may be shared with HW interrupts. + * + * In Cortex variants with programmable fault exception priorities we + * assign the highest interrupt priority level (level 0) to processor faults + * with configurable priority. + * The highest priority level may be shared with either Zero-Latency IRQs (if + * support for the feature is enabled) or with SVCall priority level. + * Regular HW IRQs are always assigned priority levels lower than the priority + * levels for SVCalls, Zero-Latency IRQs and processor faults. + * + * PendSV IRQ (which is used in Cortex-M variants to implement thread + * context-switching) is assigned the lowest IRQ priority level. + */ +#if defined(CONFIG_CPU_CORTEX_M_HAS_PROGRAMMABLE_FAULT_PRIOS) +#define _EXCEPTION_RESERVED_PRIO 1 +#else +#define _EXCEPTION_RESERVED_PRIO 0 +#endif + +#define _EXC_FAULT_PRIO 0 +#define _EXC_ZERO_LATENCY_IRQS_PRIO 0 +#define _EXC_SVC_PRIO COND_CODE_1(CONFIG_ZERO_LATENCY_IRQS, \ + (CONFIG_ZERO_LATENCY_LEVELS), (0)) +#define _IRQ_PRIO_OFFSET (_EXCEPTION_RESERVED_PRIO + _EXC_SVC_PRIO) +#define IRQ_PRIO_LOWEST (BIT(NUM_IRQ_PRIO_BITS) - (_IRQ_PRIO_OFFSET) - 1) + +#define _EXC_IRQ_DEFAULT_PRIO Z_EXC_PRIO(_IRQ_PRIO_OFFSET) + +/* Use lowest possible priority level for PendSV */ +#define _EXC_PENDSV_PRIO 0xff +#define _EXC_PENDSV_PRIO_MASK Z_EXC_PRIO(_EXC_PENDSV_PRIO) + +#ifdef _ASMLANGUAGE +GTEXT(z_arm_exc_exit); +#else +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) + +/* Registers s16-s31 (d8-d15, q4-q7) must be preserved across subroutine calls. + * + * Registers s0-s15 (d0-d7, q0-q3) do not have to be preserved (and can be used + * for passing arguments or returning results in standard procedure-call variants). + * + * Registers d16-d31 (q8-q15), do not have to be preserved. + */ +struct __fpu_sf { + uint32_t s[16]; /* s0~s15 (d0-d7) */ +#ifdef CONFIG_VFP_FEATURE_REGS_S64_D32 + uint64_t d[16]; /* d16~d31 */ +#endif + uint32_t fpscr; + uint32_t undefined; +}; +#endif + +/* Additional register state that is not stacked by hardware on exception + * entry. + * + * These fields are ONLY valid in the ESF copy passed into z_arm_fatal_error(). + * When information for a member is unavailable, the field is set to zero. + */ +#if defined(CONFIG_EXTRA_EXCEPTION_INFO) +struct __extra_esf_info { + _callee_saved_t *callee; + uint32_t msp; + uint32_t exc_return; +}; +#endif /* CONFIG_EXTRA_EXCEPTION_INFO */ + +struct __esf { + struct __basic_sf { + sys_define_gpr_with_alias(a1, r0); + sys_define_gpr_with_alias(a2, r1); + sys_define_gpr_with_alias(a3, r2); + sys_define_gpr_with_alias(a4, r3); + sys_define_gpr_with_alias(ip, r12); + sys_define_gpr_with_alias(lr, r14); + sys_define_gpr_with_alias(pc, r15); + uint32_t xpsr; + } basic; +#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) + struct __fpu_sf fpu; +#endif +#if defined(CONFIG_EXTRA_EXCEPTION_INFO) + struct __extra_esf_info extra_info; +#endif +}; + +extern uint32_t z_arm_coredump_fault_sp; + +typedef struct __esf z_arch_esf_t; + +extern void z_arm_exc_exit(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_CORTEX_M_EXC_H_ */ diff --git a/include/zephyr/arch/arm/aarch32/cortex_m/fpu.h b/include/zephyr/arch/arm/cortex_m/fpu.h similarity index 100% rename from include/zephyr/arch/arm/aarch32/cortex_m/fpu.h rename to include/zephyr/arch/arm/cortex_m/fpu.h diff --git a/include/zephyr/arch/arm/aarch32/cortex_m/memory_map.h b/include/zephyr/arch/arm/cortex_m/memory_map.h similarity index 100% rename from include/zephyr/arch/arm/aarch32/cortex_m/memory_map.h rename to include/zephyr/arch/arm/cortex_m/memory_map.h diff --git a/include/zephyr/arch/arm/aarch32/cortex_m/nvic.h b/include/zephyr/arch/arm/cortex_m/nvic.h similarity index 100% rename from include/zephyr/arch/arm/aarch32/cortex_m/nvic.h rename to include/zephyr/arch/arm/cortex_m/nvic.h diff --git a/include/zephyr/arch/arm/cortex_m/scripts/linker.ld b/include/zephyr/arch/arm/cortex_m/scripts/linker.ld new file mode 100644 index 00000000000..5050c778627 --- /dev/null +++ b/include/zephyr/arch/arm/cortex_m/scripts/linker.ld @@ -0,0 +1,519 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Linker command/script file + * + * Linker script for the Cortex-M platforms. + */ + +#include +#include + +#include +#include +#include + +/* physical address of RAM */ +#ifdef CONFIG_XIP +#define ROMABLE_REGION FLASH +#else +#define ROMABLE_REGION RAM +#endif +#define RAMABLE_REGION RAM + +#if USE_PARTITION_MANAGER + +#include + +#if CONFIG_NCS_IS_VARIANT_IMAGE && defined(PM_S0_ID) +/* We are linking against S1, create symbol containing the flash ID of S0. + * This is used when writing code operating on the "other" slot. + */ +_image_1_primary_slot_id = PM_S0_ID; + +#else /* ! CONFIG_NCS_IS_VARIANT_IMAGE */ + +#ifdef PM_S1_ID +/* We are linking against S0, create symbol containing the flash ID of S1. + * This is used when writing code operating on the "other" slot. + */ +_image_1_primary_slot_id = PM_S1_ID; +#endif /* PM_S1_ID */ + +#endif /* CONFIG_NCS_IS_VARIANT_IMAGE */ + +#define ROM_ADDR PM_ADDRESS +#define ROM_SIZE PM_SIZE + +#define RAM_SIZE PM_SRAM_SIZE +#define RAM_ADDR PM_SRAM_ADDRESS + +#else /* ! USE_PARTITION_MANAGER */ + +#if !defined(CONFIG_XIP) && (CONFIG_FLASH_SIZE == 0) +#define ROM_ADDR RAM_ADDR +#else +#define ROM_ADDR (CONFIG_FLASH_BASE_ADDRESS + CONFIG_FLASH_LOAD_OFFSET) +#endif + +#if CONFIG_FLASH_LOAD_SIZE > 0 +#define ROM_SIZE CONFIG_FLASH_LOAD_SIZE +#else +#define ROM_SIZE (CONFIG_FLASH_SIZE * 1024 - CONFIG_FLASH_LOAD_OFFSET) +#endif + +#if defined(CONFIG_XIP) +#if defined(CONFIG_IS_BOOTLOADER) +#define RAM_SIZE (CONFIG_BOOTLOADER_SRAM_SIZE * 1K) +#define RAM_ADDR (CONFIG_SRAM_BASE_ADDRESS + \ + (CONFIG_SRAM_SIZE * 1K - RAM_SIZE)) +#else +#define RAM_SIZE (CONFIG_SRAM_SIZE * 1K) +#define RAM_ADDR CONFIG_SRAM_BASE_ADDRESS +#endif +#else +#define RAM_SIZE (CONFIG_SRAM_SIZE * 1K - CONFIG_BOOTLOADER_SRAM_SIZE * 1K) +#define RAM_ADDR CONFIG_SRAM_BASE_ADDRESS +#endif + +#endif /* USE_PARTITION_MANAGER */ + +#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ccm), okay) +#define CCM_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_ccm)) +#define CCM_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_ccm)) +#endif + +#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_itcm), okay) +#define ITCM_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_itcm)) +#define ITCM_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_itcm)) +#endif + +#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay) +#define DTCM_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_dtcm)) +#define DTCM_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_dtcm)) +#endif + +#if defined(CONFIG_CUSTOM_SECTION_ALIGN) +_region_min_align = CONFIG_CUSTOM_SECTION_MIN_ALIGN_SIZE; +#else +/* Set alignment to CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE + * to make linker section alignment comply with MPU granularity. + */ +#if defined(CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE) +_region_min_align = CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE; +#else +/* If building without MPU support, use default 4-byte alignment. */ +_region_min_align = 4; +#endif +#endif + +#if !defined(CONFIG_CUSTOM_SECTION_ALIGN) && defined(CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT) +#define MPU_ALIGN(region_size) \ + . = ALIGN(_region_min_align); \ + . = ALIGN( 1 << LOG2CEIL(region_size)) +#else +#define MPU_ALIGN(region_size) \ + . = ALIGN(_region_min_align) +#endif + +#include + +MEMORY + { + FLASH (rx) : ORIGIN = ROM_ADDR, LENGTH = ROM_SIZE + RAM (wx) : ORIGIN = RAM_ADDR, LENGTH = RAM_SIZE +#if defined(CONFIG_LINKER_DEVNULL_MEMORY) + DEVNULL_ROM (rx) : ORIGIN = DEVNULL_ADDR, LENGTH = DEVNULL_SIZE +#endif + LINKER_DT_REGIONS() + /* Used by and documented in include/linker/intlist.ld */ + IDT_LIST (wx) : ORIGIN = 0xFFFFF7FF, LENGTH = 2K + } + +ENTRY(CONFIG_KERNEL_ENTRY) + +SECTIONS + { + +#include + + /* + * .plt and .iplt are here according to 'arm-zephyr-elf-ld --verbose', + * before text section. + */ + /DISCARD/ : + { + *(.plt) + } + + /DISCARD/ : + { + *(.iplt) + } + + GROUP_START(ROMABLE_REGION) + + __rom_region_start = ROM_ADDR; + + SECTION_PROLOGUE(rom_start,,) + { + +/* Located in generated directory. This file is populated by calling + * zephyr_linker_sources(ROM_START ...). This typically contains the vector + * table and debug information. + */ +#include + + } GROUP_LINK_IN(ROMABLE_REGION) + +#ifdef CONFIG_CODE_DATA_RELOCATION + +#include + +#endif /* CONFIG_CODE_DATA_RELOCATION */ + + SECTION_PROLOGUE(_TEXT_SECTION_NAME,,) + { + __text_region_start = .; + +#include + + *(.text) + *(".text.*") + *(".TEXT.*") + *(.gnu.linkonce.t.*) + + /* + * These are here according to 'arm-zephyr-elf-ld --verbose', + * after .gnu.linkonce.t.* + */ + *(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx) + . = ALIGN(4); + + } GROUP_LINK_IN(ROMABLE_REGION) + + __text_region_end = .; + +#if defined (CONFIG_CPP) + SECTION_PROLOGUE(.ARM.extab,,) + { + /* + * .ARM.extab section containing exception unwinding information. + */ + *(.ARM.extab* .gnu.linkonce.armextab.*) + } GROUP_LINK_IN(ROMABLE_REGION) +#endif + + SECTION_PROLOGUE(.ARM.exidx,,) + { + /* + * This section, related to stack and exception unwinding, is placed + * explicitly to prevent it from being shared between multiple regions. + * It must be defined for gcc to support 64-bit math and avoid + * section overlap. + */ + __exidx_start = .; +#if defined (__GCC_LINKER_CMD__) + *(.ARM.exidx* gnu.linkonce.armexidx.*) +#endif + __exidx_end = .; + } GROUP_LINK_IN(ROMABLE_REGION) + + __rodata_region_start = .; + +#include +#include + + SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) + { + *(.rodata) + *(".rodata.*") + *(.gnu.linkonce.r.*) + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + +#include + + /* + * For XIP images, in order to avoid the situation when __data_rom_start + * is 32-bit aligned, but the actual data is placed right after rodata + * section, which may not end exactly at 32-bit border, pad rodata + * section, so __data_rom_start points at data and it is 32-bit aligned. + * + * On non-XIP images this may enlarge image size up to 3 bytes. This + * generally is not an issue, since modern ROM and FLASH memory is + * usually 4k aligned. + */ + . = ALIGN(4); + } GROUP_LINK_IN(ROMABLE_REGION) + +#include + +#if defined(CONFIG_BUILD_ALIGN_LMA) + /* + * Include a padding section here to make sure that the LMA address + * of the sections in the RAMABLE_REGION are aligned with those + * section's VMA alignment requirements. + */ + SECTION_PROLOGUE(padding_section,,) + { + __rodata_region_end = .; + MPU_ALIGN(__rodata_region_end - ADDR(rom_start)); + } GROUP_LINK_IN(ROMABLE_REGION) +#else + __rodata_region_end = .; + MPU_ALIGN(__rodata_region_end - ADDR(rom_start)); +#endif + __rom_region_end = __rom_region_start + . - ADDR(rom_start); + + GROUP_END(ROMABLE_REGION) + + /* + * These are here according to 'arm-zephyr-elf-ld --verbose', + * before data section. + */ + /DISCARD/ : { + *(.got.plt) + *(.igot.plt) + *(.got) + *(.igot) + } + + GROUP_START(RAMABLE_REGION) + + . = RAM_ADDR; + /* Align the start of image RAM with the + * minimum granularity required by MPU. + */ + . = ALIGN(_region_min_align); + _image_ram_start = .; + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + +#if defined(CONFIG_USERSPACE) +#define APP_SHARED_ALIGN . = ALIGN(_region_min_align); +#define SMEM_PARTITION_ALIGN MPU_ALIGN + +#include + + _app_smem_size = _app_smem_end - _app_smem_start; + _app_smem_rom_start = LOADADDR(_APP_SMEM_SECTION_NAME); + + SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) + { + /* + * For performance, BSS section is assumed to be 4 byte aligned and + * a multiple of 4 bytes + */ + . = ALIGN(4); + __bss_start = .; + __kernel_ram_start = .; + + *(.bss) + *(".bss.*") + *(COMMON) + *(".kernel_bss.*") + +#ifdef CONFIG_CODE_DATA_RELOCATION +#include +#endif + + /* + * As memory is cleared in words only, it is simpler to ensure the BSS + * section ends on a 4 byte boundary. This wastes a maximum of 3 bytes. + */ + __bss_end = ALIGN(4); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION) + +#include + +#endif /* CONFIG_USERSPACE */ + + GROUP_START(DATA_REGION) + + SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,) + { + __data_region_start = .; + __data_start = .; + *(.data) + *(".data.*") + *(".kernel.*") + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + +#ifdef CONFIG_CODE_DATA_RELOCATION +#include +#endif + __data_end = .; + + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + __data_size = __data_end - __data_start; + __data_load_start = LOADADDR(_DATA_SECTION_NAME); + + __data_region_load_start = LOADADDR(_DATA_SECTION_NAME); + +#include +#include + +#include + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + + __data_region_end = .; + +#ifndef CONFIG_USERSPACE + SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) + { + /* + * For performance, BSS section is assumed to be 4 byte aligned and + * a multiple of 4 bytes + */ + . = ALIGN(4); + __bss_start = .; + __kernel_ram_start = .; + + *(.bss) + *(".bss.*") + *(COMMON) + *(".kernel_bss.*") + +#ifdef CONFIG_CODE_DATA_RELOCATION +#include +#endif + + /* + * As memory is cleared in words only, it is simpler to ensure the BSS + * section ends on a 4 byte boundary. This wastes a maximum of 3 bytes. + */ + __bss_end = ALIGN(4); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION) + + SECTION_PROLOGUE(_NOINIT_SECTION_NAME,(NOLOAD),) + { + /* + * This section is used for non-initialized objects that + * will not be cleared during the boot process. + */ + *(.noinit) + *(".noinit.*") + *(".kernel_noinit.*") + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + + } GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, RAMABLE_REGION) +#endif /* CONFIG_USERSPACE */ + + /* Define linker symbols */ + + __kernel_ram_end = RAM_ADDR + RAM_SIZE; + __kernel_ram_size = __kernel_ram_end - __kernel_ram_start; + +#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_itcm), okay) +GROUP_START(ITCM) + + SECTION_PROLOGUE(_ITCM_SECTION_NAME,,SUBALIGN(4)) + { + __itcm_start = .; + *(.itcm) + *(".itcm.*") + __itcm_end = .; + } GROUP_LINK_IN(ITCM AT> ROMABLE_REGION) + + __itcm_size = __itcm_end - __itcm_start; + __itcm_load_start = LOADADDR(_ITCM_SECTION_NAME); + +GROUP_END(ITCM) +#endif + +#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay) +GROUP_START(DTCM) + + SECTION_PROLOGUE(_DTCM_BSS_SECTION_NAME, (NOLOAD),SUBALIGN(4)) + { + __dtcm_start = .; + __dtcm_bss_start = .; + *(.dtcm_bss) + *(".dtcm_bss.*") + __dtcm_bss_end = .; + } GROUP_LINK_IN(DTCM) + + SECTION_PROLOGUE(_DTCM_NOINIT_SECTION_NAME, (NOLOAD),SUBALIGN(4)) + { + __dtcm_noinit_start = .; + *(.dtcm_noinit) + *(".dtcm_noinit.*") + __dtcm_noinit_end = .; + } GROUP_LINK_IN(DTCM) + + SECTION_PROLOGUE(_DTCM_DATA_SECTION_NAME,,SUBALIGN(4)) + { + __dtcm_data_start = .; + *(.dtcm_data) + *(".dtcm_data.*") + __dtcm_data_end = .; + } GROUP_LINK_IN(DTCM AT> ROMABLE_REGION) + + __dtcm_end = .; + + __dtcm_data_load_start = LOADADDR(_DTCM_DATA_SECTION_NAME); + +GROUP_END(DTCM) +#endif + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + +#include + + GROUP_END(RAMABLE_REGION) + +#include + + /DISCARD/ : { *(.note.GNU-stack) } + + SECTION_PROLOGUE(.ARM.attributes, 0,) + { + KEEP(*(.ARM.attributes)) + KEEP(*(.gnu.attributes)) + } + + /* Sections generated from 'zephyr,memory-region' nodes */ + LINKER_DT_SECTIONS() + +/* Must be last in romable region */ +SECTION_PROLOGUE(.last_section,,) +{ +#ifdef CONFIG_LINKER_LAST_SECTION_ID + /* Fill last section with a word to ensure location counter and actual rom + * region data usage match. */ + LONG(CONFIG_LINKER_LAST_SECTION_ID_PATTERN) +#endif +} GROUP_LINK_IN(ROMABLE_REGION) + +/* To provide the image size as a const expression, + * calculate this value here. */ +_flash_used = LOADADDR(.last_section) + SIZEOF(.last_section) - __rom_region_start; + + } diff --git a/include/zephyr/arch/arm/aarch32/cortex_r/scripts/app_data_alignment.ld b/include/zephyr/arch/arm/cortex_r/scripts/app_data_alignment.ld similarity index 100% rename from include/zephyr/arch/arm/aarch32/cortex_r/scripts/app_data_alignment.ld rename to include/zephyr/arch/arm/cortex_r/scripts/app_data_alignment.ld diff --git a/include/zephyr/arch/arm/cortex_r/scripts/linker.ld b/include/zephyr/arch/arm/cortex_r/scripts/linker.ld new file mode 100644 index 00000000000..28aa5f7c376 --- /dev/null +++ b/include/zephyr/arch/arm/cortex_r/scripts/linker.ld @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2020 Stephanos Ioannidis + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include diff --git a/include/zephyr/arch/arm/aarch32/error.h b/include/zephyr/arch/arm/error.h similarity index 96% rename from include/zephyr/arch/arm/aarch32/error.h rename to include/zephyr/arch/arm/error.h index fdb0f1f1a45..603e1d00088 100644 --- a/include/zephyr/arch/arm/aarch32/error.h +++ b/include/zephyr/arch/arm/error.h @@ -15,8 +15,8 @@ #ifndef ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_ERROR_H_ #define ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_ERROR_H_ -#include -#include +#include +#include #include #ifdef __cplusplus diff --git a/include/zephyr/arch/arm/exc.h b/include/zephyr/arch/arm/exc.h new file mode 100644 index 00000000000..9cd664e2c6b --- /dev/null +++ b/include/zephyr/arch/arm/exc.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief ARM AArch32 public exception handling + * + * ARM AArch32-specific kernel exception handling interface. Included by + * arm/arch.h. + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_EXC_H_ +#define ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_EXC_H_ + +#if defined(CONFIG_CPU_CORTEX_M) +#include +#elif defined(CONFIG_CPU_AARCH32_CORTEX_A) || defined(CONFIG_CPU_AARCH32_CORTEX_R) +#include +#else +#error Unknown ARM architecture +#endif /* CONFIG_CPU_CORTEX_M */ + +#endif /* ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_EXC_H_ */ diff --git a/include/zephyr/arch/arm/aarch32/irq.h b/include/zephyr/arch/arm/irq.h similarity index 96% rename from include/zephyr/arch/arm/aarch32/irq.h rename to include/zephyr/arch/arm/irq.h index 5edcd1af4b2..357c91a83ae 100644 --- a/include/zephyr/arch/arm/aarch32/irq.h +++ b/include/zephyr/arch/arm/irq.h @@ -75,14 +75,6 @@ extern void z_arm_int_exit(void); extern void z_arm_interrupt_init(void); -/* macros convert value of its argument to a string */ -#define DO_TOSTR(s) #s -#define TOSTR(s) DO_TOSTR(s) - -/* concatenate the values of the arguments into one */ -#define DO_CONCAT(x, y) x ## y -#define CONCAT(x, y) DO_CONCAT(x, y) - /* Flags for use with IRQ_CONNECT() */ /** * Set this interrupt up as a zero-latency IRQ. If CONFIG_ZERO_LATENCY_LEVELS @@ -149,7 +141,7 @@ extern void _arch_isr_direct_pm(void); #define ARCH_ISR_DIRECT_HEADER() arch_isr_direct_header() #define ARCH_ISR_DIRECT_FOOTER(swap) arch_isr_direct_footer(swap) -/* arch/arm/core/aarch32/exc_exit.S */ +/* arch/arm/core/exc_exit.S */ extern void z_arm_int_exit(void); #ifdef CONFIG_TRACING_ISR @@ -241,7 +233,7 @@ extern void z_arm_irq_direct_dynamic_dispatch_no_reschedule(void); */ #define ARM_IRQ_DIRECT_DYNAMIC_CONNECT(irq_p, priority_p, flags_p, resch) \ IRQ_DIRECT_CONNECT(irq_p, priority_p, \ - CONCAT(z_arm_irq_direct_dynamic_dispatch_, resch), flags_p) + _CONCAT(z_arm_irq_direct_dynamic_dispatch_, resch), flags_p) #endif /* CONFIG_DYNAMIC_DIRECT_INTERRUPTS */ diff --git a/include/zephyr/arch/arm/aarch32/misc.h b/include/zephyr/arch/arm/misc.h similarity index 100% rename from include/zephyr/arch/arm/aarch32/misc.h rename to include/zephyr/arch/arm/misc.h diff --git a/include/zephyr/arch/arm/aarch32/mmu/arm_mmu.h b/include/zephyr/arch/arm/mmu/arm_mmu.h similarity index 100% rename from include/zephyr/arch/arm/aarch32/mmu/arm_mmu.h rename to include/zephyr/arch/arm/mmu/arm_mmu.h diff --git a/include/zephyr/arch/arm/aarch32/mpu/arm_mpu.h b/include/zephyr/arch/arm/mpu/arm_mpu.h similarity index 94% rename from include/zephyr/arch/arm/aarch32/mpu/arm_mpu.h rename to include/zephyr/arch/arm/mpu/arm_mpu.h index 65d9194b7a2..857465a4824 100644 --- a/include/zephyr/arch/arm/aarch32/mpu/arm_mpu.h +++ b/include/zephyr/arch/arm/mpu/arm_mpu.h @@ -11,12 +11,12 @@ defined(CONFIG_CPU_CORTEX_M4) || \ defined(CONFIG_CPU_CORTEX_M7) || \ defined(CONFIG_ARMV7_R) -#include +#include #elif defined(CONFIG_CPU_CORTEX_M23) || \ defined(CONFIG_CPU_CORTEX_M33) || \ defined(CONFIG_CPU_CORTEX_M55) || \ defined(CONFIG_AARCH32_ARMV8_R) -#include +#include #else #error "Unsupported ARM CPU" #endif diff --git a/include/zephyr/arch/arm/aarch32/mpu/arm_mpu_v7m.h b/include/zephyr/arch/arm/mpu/arm_mpu_v7m.h similarity index 98% rename from include/zephyr/arch/arm/aarch32/mpu/arm_mpu_v7m.h rename to include/zephyr/arch/arm/mpu/arm_mpu_v7m.h index a3b61844368..1ed8636ec50 100644 --- a/include/zephyr/arch/arm/aarch32/mpu/arm_mpu_v7m.h +++ b/include/zephyr/arch/arm/mpu/arm_mpu_v7m.h @@ -109,6 +109,12 @@ #define REGION_2G REGION_SIZE(2GB) #define REGION_4G REGION_SIZE(4GB) +#define ARM_MPU_REGION_INIT(p_name, p_base, p_size, p_attr) \ + { .name = p_name, \ + .base = p_base, \ + .attr = p_attr(size_to_mpu_rasr_size(p_size)), \ + } + /* Some helper defines for common regions */ /* On Cortex-M, we can only set the XN bit when CONFIG_XIP=y. When diff --git a/include/zephyr/arch/arm/aarch32/mpu/arm_mpu_v8.h b/include/zephyr/arch/arm/mpu/arm_mpu_v8.h similarity index 97% rename from include/zephyr/arch/arm/aarch32/mpu/arm_mpu_v8.h rename to include/zephyr/arch/arm/mpu/arm_mpu_v8.h index ee8f2e8ac07..cf60cca99da 100644 --- a/include/zephyr/arch/arm/aarch32/mpu/arm_mpu_v8.h +++ b/include/zephyr/arch/arm/mpu/arm_mpu_v8.h @@ -188,6 +188,13 @@ * that they do not overlap with other MPU regions). */ #if defined(CONFIG_AARCH32_ARMV8_R) + +#define ARM_MPU_REGION_INIT(p_name, p_base, p_size, p_attr) \ + { .name = p_name, \ + .base = p_base, \ + .attr = p_attr(p_base + p_size), \ + } + #define REGION_RAM_ATTR(limit) \ { \ .rbar = NOT_EXEC | \ @@ -246,6 +253,12 @@ } #else +#define ARM_MPU_REGION_INIT(p_name, p_base, p_size, p_attr) \ + { .name = p_name, \ + .base = p_base, \ + .attr = p_attr(p_base, p_size), \ + } + /* On Cortex-M, we can only set the XN bit when CONFIG_XIP=y. When * CONFIG_XIP=n, the entire image will be linked to SRAM, so we need to keep * the SRAM region XN bit clear or the application code will not be executable. diff --git a/include/zephyr/arch/arm/aarch32/mpu/nxp_mpu.h b/include/zephyr/arch/arm/mpu/nxp_mpu.h similarity index 99% rename from include/zephyr/arch/arm/aarch32/mpu/nxp_mpu.h rename to include/zephyr/arch/arm/mpu/nxp_mpu.h index 2b40050afa4..d1f5882bfed 100644 --- a/include/zephyr/arch/arm/aarch32/mpu/nxp_mpu.h +++ b/include/zephyr/arch/arm/mpu/nxp_mpu.h @@ -8,10 +8,6 @@ #ifndef _ASMLANGUAGE -#include - -#define NXP_MPU_BASE SYSMPU_BASE - #define NXP_MPU_REGION_NUMBER 12 /* Bus Master User Mode Access */ diff --git a/include/zephyr/arch/arm/aarch32/nmi.h b/include/zephyr/arch/arm/nmi.h similarity index 100% rename from include/zephyr/arch/arm/aarch32/nmi.h rename to include/zephyr/arch/arm/nmi.h diff --git a/include/zephyr/arch/arm/structs.h b/include/zephyr/arch/arm/structs.h new file mode 100644 index 00000000000..4fbf588c5cd --- /dev/null +++ b/include/zephyr/arch/arm/structs.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 Arm Limited (or its affiliates). All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ARM_STRUCTS_H_ +#define ZEPHYR_INCLUDE_ARM_STRUCTS_H_ + +#include + +#if defined(CONFIG_CPU_AARCH32_CORTEX_A) || defined(CONFIG_CPU_AARCH32_CORTEX_R) +/* Per CPU architecture specifics */ +struct _cpu_arch { + int8_t exc_depth; +}; + +#else + +/* Default definitions when no architecture specific definitions exist. */ + +/* Per CPU architecture specifics (empty) */ +struct _cpu_arch { +#ifdef __cplusplus + /* This struct will have a size 0 in C which is not allowed in C++ (it'll have a size 1). To + * prevent this, we add a 1 byte dummy variable. + */ + uint8_t dummy; +#endif +}; + +#endif + +#endif /* ZEPHYR_INCLUDE_ARM_STRUCTS_H_ */ diff --git a/include/zephyr/arch/arm/aarch32/syscall.h b/include/zephyr/arch/arm/syscall.h similarity index 99% rename from include/zephyr/arch/arm/aarch32/syscall.h rename to include/zephyr/arch/arm/syscall.h index f8561d8c24a..a4e067307ec 100644 --- a/include/zephyr/arch/arm/aarch32/syscall.h +++ b/include/zephyr/arch/arm/syscall.h @@ -26,7 +26,7 @@ #include #include -#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/zephyr/arch/arm/aarch32/thread.h b/include/zephyr/arch/arm/thread.h similarity index 95% rename from include/zephyr/arch/arm/aarch32/thread.h rename to include/zephyr/arch/arm/thread.h index 7ddd574c579..b4d34b137cb 100644 --- a/include/zephyr/arch/arm/aarch32/thread.h +++ b/include/zephyr/arch/arm/thread.h @@ -32,6 +32,9 @@ struct _callee_saved { uint32_t v7; /* r10 */ uint32_t v8; /* r11 */ uint32_t psp; /* r13 */ +#ifdef CONFIG_USE_SWITCH + uint32_t lr; /* lr */ +#endif }; typedef struct _callee_saved _callee_saved_t; @@ -74,6 +77,10 @@ struct _thread_arch { struct _preempt_float preempt_float; #endif +#if defined(CONFIG_CPU_AARCH32_CORTEX_A) || defined(CONFIG_CPU_AARCH32_CORTEX_R) + int8_t exception_depth; +#endif + #if defined(CONFIG_ARM_STORE_EXC_RETURN) || defined(CONFIG_USERSPACE) /* * Status variable holding several thread status flags diff --git a/include/zephyr/arch/arm64/arm_mem.h b/include/zephyr/arch/arm64/arm_mem.h index 23569f6c345..110f85a24ca 100644 --- a/include/zephyr/arch/arm64/arm_mem.h +++ b/include/zephyr/arch/arm64/arm_mem.h @@ -8,7 +8,7 @@ /* * Define ARM specific memory flags used by z_phys_map() - * followed public definitions in include/sys/mem_manage.h. + * followed public definitions in include/kernel/mm.h. */ /* For ARM64, K_MEM_CACHE_NONE is nGnRnE. */ #define K_MEM_ARM_DEVICE_nGnRnE K_MEM_CACHE_NONE diff --git a/include/zephyr/arch/arm64/cortex_r/arm_mpu.h b/include/zephyr/arch/arm64/cortex_r/arm_mpu.h index d208f2566a1..8df9aaf15f3 100644 --- a/include/zephyr/arch/arm64/cortex_r/arm_mpu.h +++ b/include/zephyr/arch/arm64/cortex_r/arm_mpu.h @@ -143,7 +143,7 @@ #define REGION_RAM_ATTR \ { \ /* AP, XN, SH */ \ - .rbar = NOT_EXEC | P_RW_U_NA_Msk | INNER_SHAREABLE_Msk, \ + .rbar = NOT_EXEC | P_RW_U_NA_Msk | OUTER_SHAREABLE_Msk, \ /* Cache-ability */ \ .mair_idx = MPU_MAIR_INDEX_SRAM, \ } @@ -227,14 +227,6 @@ struct arm_mpu_config { .attr = _attr, \ } -#define MPU_REGION_ENTRY_FROM_DTS(_name, _base, _size, _attr) \ - { \ - .name = _name, \ - .base = _base, \ - .limit = _base + _size, \ - .attr = _attr, \ - } - #define K_MEM_PARTITION_P_RW_U_RW ((k_mem_partition_attr_t) \ {(P_RW_U_RW_Msk), MPU_MAIR_INDEX_SRAM}) #define K_MEM_PARTITION_P_RW_U_NA ((k_mem_partition_attr_t) \ @@ -264,7 +256,8 @@ struct dynamic_region_info { #define ARM64_MPU_MAX_DYNAMIC_REGIONS \ 1 + /* data section */ \ (CONFIG_MAX_DOMAIN_PARTITIONS + 2) + \ - 2 /* user stack */ + (IS_ENABLED(CONFIG_ARM64_STACK_PROTECTION) ? 2 : 0) + \ + (IS_ENABLED(CONFIG_USERSPACE) ? 2 : 0) #endif /* _ASMLANGUAGE */ diff --git a/include/zephyr/arch/arm64/cpu.h b/include/zephyr/arch/arm64/cpu.h index bd291957959..468db381ef5 100644 --- a/include/zephyr/arch/arm64/cpu.h +++ b/include/zephyr/arch/arm64/cpu.h @@ -137,6 +137,7 @@ #define HCR_FMO_BIT BIT(3) #define HCR_IMO_BIT BIT(4) #define HCR_AMO_BIT BIT(5) +#define HCR_TGE_BIT BIT(27) #define HCR_RW_BIT BIT(31) /* System register interface to GICv3 */ diff --git a/include/zephyr/arch/arm64/hypercall.h b/include/zephyr/arch/arm64/hypercall.h index 7a0b7aecf2b..023ea10803d 100644 --- a/include/zephyr/arch/arm64/hypercall.h +++ b/include/zephyr/arch/arm64/hypercall.h @@ -1,7 +1,6 @@ +/* SPDX-License-Identifier: Apache-2.0 */ /* - * Copyright (c) 2021-2022 EPAM Systems - * - * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2021-2023 EPAM Systems */ #ifndef ZEPHYR_INCLUDE_ARCH_ARM64_HYPERCALL_H_ @@ -15,4 +14,8 @@ int HYPERVISOR_hvm_op(int op, void *param); int HYPERVISOR_memory_op(int op, void *param); int HYPERVISOR_grant_table_op(int op, void *uop, unsigned int count); +#ifdef CONFIG_XEN_DOM0 +int HYPERVISOR_domctl(void *param); +#endif + #endif /* ZEPHYR_INCLUDE_ARCH_ARM64_HYPERCALL_H_ */ diff --git a/include/zephyr/arch/arm64/thread.h b/include/zephyr/arch/arm64/thread.h index f458dcc2976..457a8c07839 100644 --- a/include/zephyr/arch/arm64/thread.h +++ b/include/zephyr/arch/arm64/thread.h @@ -51,7 +51,7 @@ struct z_arm64_fp_context { }; struct _thread_arch { -#if defined(CONFIG_USERSPACE) +#if defined(CONFIG_USERSPACE) || defined(CONFIG_ARM64_STACK_PROTECTION) #if defined(CONFIG_ARM_MMU) struct arm_mmu_ptables *ptables; #endif diff --git a/include/zephyr/arch/arm64/thread_stack.h b/include/zephyr/arch/arm64/thread_stack.h index aea9bc412c7..9ad29239135 100644 --- a/include/zephyr/arch/arm64/thread_stack.h +++ b/include/zephyr/arch/arm64/thread_stack.h @@ -7,11 +7,11 @@ #ifndef ZEPHYR_INCLUDE_ARCH_ARM64_THREAD_STACK_H_ #define ZEPHYR_INCLUDE_ARCH_ARM64_THREAD_STACK_H_ +#include #define ARCH_STACK_PTR_ALIGN 16 -#if CONFIG_USERSPACE -#include +#if defined(CONFIG_USERSPACE) || defined(CONFIG_ARM64_STACK_PROTECTION) #define Z_ARM64_STACK_BASE_ALIGN MEM_DOMAIN_ALIGN_AND_SIZE #define Z_ARM64_STACK_SIZE_ALIGN MEM_DOMAIN_ALIGN_AND_SIZE #else @@ -19,6 +19,14 @@ #define Z_ARM64_STACK_SIZE_ALIGN ARCH_STACK_PTR_ALIGN #endif +#if defined(CONFIG_ARM64_STACK_PROTECTION) +#define Z_ARM64_STACK_GUARD_SIZE MEM_DOMAIN_ALIGN_AND_SIZE +#define Z_ARM64_K_STACK_BASE_ALIGN MEM_DOMAIN_ALIGN_AND_SIZE +#else +#define Z_ARM64_STACK_GUARD_SIZE 0 +#define Z_ARM64_K_STACK_BASE_ALIGN ARCH_STACK_PTR_ALIGN +#endif + /* * [ see also comments in arch/arm64/core/thread.c ] * @@ -36,6 +44,8 @@ * | | * +-------------------+ <- thread.stack_info.start * | Privileged stack | } K_(THREAD|KERNEL)_STACK_RESERVED + * +-------------------+ <- thread stack limit (update on every context switch) + * | Stack guard | } Z_ARM64_STACK_GUARD_SIZE (protected by MMU/MPU) * +-------------------+ <- thread.stack_obj * * Low Memory addresses @@ -45,11 +55,12 @@ #define ARCH_THREAD_STACK_OBJ_ALIGN(size) Z_ARM64_STACK_BASE_ALIGN #define ARCH_THREAD_STACK_SIZE_ADJUST(size) \ ROUND_UP((size), Z_ARM64_STACK_SIZE_ALIGN) -#define ARCH_THREAD_STACK_RESERVED CONFIG_PRIVILEGED_STACK_SIZE +#define ARCH_THREAD_STACK_RESERVED CONFIG_PRIVILEGED_STACK_SIZE + \ + Z_ARM64_STACK_GUARD_SIZE /* kernel stack */ -#define ARCH_KERNEL_STACK_RESERVED 0 -#define ARCH_KERNEL_STACK_OBJ_ALIGN ARCH_STACK_PTR_ALIGN +#define ARCH_KERNEL_STACK_RESERVED Z_ARM64_STACK_GUARD_SIZE +#define ARCH_KERNEL_STACK_OBJ_ALIGN Z_ARM64_K_STACK_BASE_ALIGN #ifndef _ASMLANGUAGE diff --git a/include/zephyr/arch/cache.h b/include/zephyr/arch/cache.h index 59bdf61e0d0..8cbef3d2b9d 100644 --- a/include/zephyr/arch/cache.h +++ b/include/zephyr/arch/cache.h @@ -32,7 +32,7 @@ * * Enable the data cache. */ -extern void arch_dcache_enable(void); +void arch_dcache_enable(void); #define cache_data_enable arch_dcache_enable @@ -41,7 +41,7 @@ extern void arch_dcache_enable(void); * * Disable the data cache. */ -extern void arch_dcache_disable(void); +void arch_dcache_disable(void); #define cache_data_disable arch_dcache_disable @@ -54,7 +54,7 @@ extern void arch_dcache_disable(void); * @retval -ENOTSUP If not supported. * @retval -errno Negative errno for other failures. */ -extern int arch_dcache_flush_all(void); +int arch_dcache_flush_all(void); #define cache_data_flush_all arch_dcache_flush_all @@ -67,7 +67,7 @@ extern int arch_dcache_flush_all(void); * @retval -ENOTSUP If not supported. * @retval -errno Negative errno for other failures. */ -extern int arch_dcache_invd_all(void); +int arch_dcache_invd_all(void); #define cache_data_invd_all arch_dcache_invd_all @@ -80,7 +80,7 @@ extern int arch_dcache_invd_all(void); * @retval -ENOTSUP If not supported. * @retval -errno Negative errno for other failures. */ -extern int arch_dcache_flush_and_invd_all(void); +int arch_dcache_flush_and_invd_all(void); #define cache_data_flush_and_invd_all arch_dcache_flush_and_invd_all @@ -103,7 +103,7 @@ extern int arch_dcache_flush_and_invd_all(void); * @retval -ENOTSUP If not supported. * @retval -errno Negative errno for other failures. */ -extern int arch_dcache_flush_range(void *addr, size_t size); +int arch_dcache_flush_range(void *addr, size_t size); #define cache_data_flush_range(addr, size) arch_dcache_flush_range(addr, size) @@ -127,7 +127,7 @@ extern int arch_dcache_flush_range(void *addr, size_t size); * @retval -ENOTSUP If not supported. * @retval -errno Negative errno for other failures. */ -extern int arch_dcache_invd_range(void *addr, size_t size); +int arch_dcache_invd_range(void *addr, size_t size); #define cache_data_invd_range(addr, size) arch_dcache_invd_range(addr, size) @@ -152,7 +152,7 @@ extern int arch_dcache_invd_range(void *addr, size_t size); * @retval -errno Negative errno for other failures. */ -extern int arch_dcache_flush_and_invd_range(void *addr, size_t size); +int arch_dcache_flush_and_invd_range(void *addr, size_t size); #define cache_data_flush_and_invd_range(addr, size) \ arch_dcache_flush_and_invd_range(addr, size) @@ -172,7 +172,7 @@ extern int arch_dcache_flush_and_invd_range(void *addr, size_t size); * @retval size Size of the d-cache line. * @retval 0 If the d-cache is not enabled. */ -extern size_t arch_dcache_line_size_get(void); +size_t arch_dcache_line_size_get(void); #define cache_data_line_size_get arch_dcache_line_size_get @@ -187,7 +187,7 @@ extern size_t arch_dcache_line_size_get(void); * * Enable the instruction cache. */ -extern void arch_icache_enable(void); +void arch_icache_enable(void); #define cache_instr_enable arch_icache_enable @@ -196,7 +196,7 @@ extern void arch_icache_enable(void); * * Disable the instruction cache. */ -extern void arch_icache_disable(void); +void arch_icache_disable(void); #define cache_instr_disable arch_icache_disable @@ -209,7 +209,7 @@ extern void arch_icache_disable(void); * @retval -ENOTSUP If not supported. * @retval -errno Negative errno for other failures. */ -extern int arch_icache_flush_all(void); +int arch_icache_flush_all(void); #define cache_instr_flush_all arch_icache_flush_all @@ -222,7 +222,7 @@ extern int arch_icache_flush_all(void); * @retval -ENOTSUP If not supported. * @retval -errno Negative errno for other failures. */ -extern int arch_icache_invd_all(void); +int arch_icache_invd_all(void); #define cache_instr_invd_all arch_icache_invd_all @@ -235,7 +235,7 @@ extern int arch_icache_invd_all(void); * @retval -ENOTSUP If not supported. * @retval -errno Negative errno for other failures. */ -extern int arch_icache_flush_and_invd_all(void); +int arch_icache_flush_and_invd_all(void); #define cache_instr_flush_and_invd_all arch_icache_flush_and_invd_all @@ -258,7 +258,7 @@ extern int arch_icache_flush_and_invd_all(void); * @retval -ENOTSUP If not supported. * @retval -errno Negative errno for other failures. */ -extern int arch_icache_flush_range(void *addr, size_t size); +int arch_icache_flush_range(void *addr, size_t size); #define cache_instr_flush_range(addr, size) arch_icache_flush_range(addr, size) @@ -282,7 +282,7 @@ extern int arch_icache_flush_range(void *addr, size_t size); * @retval -ENOTSUP If not supported. * @retval -errno Negative errno for other failures. */ -extern int arch_icache_invd_range(void *addr, size_t size); +int arch_icache_invd_range(void *addr, size_t size); #define cache_instr_invd_range(addr, size) arch_icache_invd_range(addr, size) @@ -306,7 +306,7 @@ extern int arch_icache_invd_range(void *addr, size_t size); * @retval -ENOTSUP If not supported. * @retval -errno Negative errno for other failures. */ -extern int arch_icache_flush_and_invd_range(void *addr, size_t size); +int arch_icache_flush_and_invd_range(void *addr, size_t size); #define cache_instr_flush_and_invd_range(addr, size) \ arch_icache_flush_and_invd_range(addr, size) @@ -327,7 +327,7 @@ extern int arch_icache_flush_and_invd_range(void *addr, size_t size); * @retval 0 If the d-cache is not enabled. */ -extern size_t arch_icache_line_size_get(void); +size_t arch_icache_line_size_get(void); #define cache_instr_line_size_get arch_icache_line_size_get diff --git a/include/zephyr/arch/cpu.h b/include/zephyr/arch/cpu.h index 5fbe8f8c628..17ec125b395 100644 --- a/include/zephyr/arch/cpu.h +++ b/include/zephyr/arch/cpu.h @@ -16,7 +16,7 @@ #elif defined(CONFIG_ARM64) #include #elif defined(CONFIG_ARM) -#include +#include #elif defined(CONFIG_ARC) #include #elif defined(CONFIG_NIOS2) diff --git a/include/zephyr/arch/riscv/common/linker.ld b/include/zephyr/arch/riscv/common/linker.ld index 3dbec5f0a20..eb5c4782441 100644 --- a/include/zephyr/arch/riscv/common/linker.ld +++ b/include/zephyr/arch/riscv/common/linker.ld @@ -72,6 +72,8 @@ #define MPU_ALIGN(region_size) . = ALIGN(4) #endif +#include + MEMORY { #ifdef CONFIG_XIP @@ -79,6 +81,10 @@ MEMORY #endif RAM (rwx) : ORIGIN = RAM_BASE, LENGTH = RAM_SIZE +#if defined(CONFIG_LINKER_DEVNULL_MEMORY) + DEVNULL_ROM (rx) : ORIGIN = DEVNULL_ADDR, LENGTH = DEVNULL_SIZE +#endif + LINKER_DT_REGIONS() /* Used by and documented in include/linker/intlist.ld */ @@ -396,6 +402,10 @@ SECTION_PROLOGUE(.last_section,,) /* Fill last section with a word to ensure location counter and actual rom * region data usage match. */ LONG(CONFIG_LINKER_LAST_SECTION_ID_PATTERN) + /* __rom_region_size is used when configuring the PMP entry of the ROM region. + * Addresses (pmpaddr) in PMP registers need to be aligned to 4. Align + * __rom_region_size to 4 to meet that requirement. */ + MPU_MIN_SIZE_ALIGN #endif } GROUP_LINK_IN(ROMABLE_REGION) diff --git a/include/zephyr/arch/structs.h b/include/zephyr/arch/structs.h index 570c3959b7e..703ec81f889 100644 --- a/include/zephyr/arch/structs.h +++ b/include/zephyr/arch/structs.h @@ -27,6 +27,8 @@ #include #elif defined(CONFIG_RISCV) #include +#elif defined(CONFIG_ARM) +#include #else /* Default definitions when no architecture specific definitions exist. */ diff --git a/include/zephyr/arch/syscall.h b/include/zephyr/arch/syscall.h index 3c745921070..b657717e3d4 100644 --- a/include/zephyr/arch/syscall.h +++ b/include/zephyr/arch/syscall.h @@ -18,7 +18,7 @@ #elif defined(CONFIG_ARM64) #include #elif defined(CONFIG_ARM) -#include +#include #elif defined(CONFIG_ARC) #include #elif defined(CONFIG_RISCV) diff --git a/include/zephyr/arch/x86/acpi.h b/include/zephyr/arch/x86/acpi.h deleted file mode 100644 index df4a5dcc089..00000000000 --- a/include/zephyr/arch/x86/acpi.h +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (c) 2020 Intel Corporation - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_INCLUDE_ARCH_X86_ACPI_H -#define ZEPHYR_INCLUDE_ARCH_X86_ACPI_H - -#ifndef _ASMLANGUAGE - -#define ACPI_RSDP_SIGNATURE 0x2052545020445352 /* == "RSD PTR " */ - -/* Root System Description Pointer */ -struct acpi_rsdp { - char signature[8]; - uint8_t chksum; - char oem_id[6]; - uint8_t revision; - uint32_t rsdt_ptr; - uint32_t length; - uint64_t xsdt_ptr; - uint8_t ext_chksum; - uint8_t _reserved[3]; -} __packed; - -/* Standard table header */ -struct acpi_sdt { - uint32_t signature; - uint32_t length; - uint8_t revision; - uint8_t chksum; - char oem_id[6]; - char oem_table_id[8]; - uint32_t oem_revision; - uint32_t creator_id; - uint32_t creator_revision; -} __packed; - -/* Root System Description Table */ -struct acpi_rsdt { - struct acpi_sdt sdt; - uint32_t table_ptrs[]; -} __packed; - -/* eXtended System Descriptor Table */ -struct acpi_xsdt { - struct acpi_sdt sdt; - uint64_t table_ptrs[]; -} __packed; - -/* MCFG table storing MMIO addresses for PCI configuration space */ - -#define ACPI_MCFG_SIGNATURE 0x4746434d /* 'MCFG' */ - -struct acpi_mcfg { - struct acpi_sdt sdt; - uint64_t _reserved; - struct { - uint64_t base_addr; - uint16_t seg_group_num; - uint8_t start_bus; - uint8_t end_bus; - } pci_segs[]; -} __packed; - -/* MADT table storing IO-APIC and multiprocessor configuration */ - -#define ACPI_MADT_SIGNATURE 0x43495041 /* 'APIC' */ - -struct acpi_madt_entry { - uint8_t type; /* See ACPI_MADT_ENTRY_* below */ - uint8_t length; -} __packed; - -#define ACPI_MADT_ENTRY_CPU 0 - -struct acpi_madt { - struct acpi_sdt sdt; - uint32_t loapic; /* local APIC MMIO address */ - uint32_t flags; /* see ACPI_MADT_FLAGS_* below */ - struct acpi_madt_entry entries[]; -} __packed; - -#define ACPI_MADT_FLAGS_PICS 0x01 /* legacy 8259s installed */ - -struct acpi_cpu { - struct acpi_madt_entry entry; - uint8_t acpi_id; - uint8_t apic_id; /* local APIC ID */ - uint8_t flags; /* see ACPI_CPU_FLAGS_* below */ -} __packed; - -#define ACPI_CPU_FLAGS_ENABLED 0x01 - -/* Generic DMA Remapping entry structure part */ -struct acpi_dmar_entry { - uint16_t type; /* See ACPI_DMAR_TYPE_* below */ - uint16_t length; -} __packed; - -#define ACPI_DMAR_TYPE_DRHD 0 /* DMA Remapping Hardware Unit Definition */ -#define ACPI_DMAR_TYPE_RMRR 1 /* Do not care atm (legacy usage) */ -#define ACPI_DMAR_TYPE_ATSR 2 /* Do not care atm (PCIE ATS support) */ -#define ACPI_DMAR_TYPE_RHSA 3 /* Do not care atm (NUMA specific ) */ -#define ACPI_DMAR_TYPE_ANDD 4 /* Do not care atm (ACPI DSDT related) */ -#define ACPI_DMAR_TYPE_SACT 5 /* Do not care atm */ - -/* PCI Device/Function Pair (forming the BDF, with start_bus_num below) */ -struct acpi_dmar_dev_path { - uint8_t device; - uint8_t function; -} __packed; - -#define ACPI_DMAR_DEV_PATH_SIZE 2 - -/* DMA Remapping Device Scope */ -struct acpi_dmar_dev_scope { - uint8_t type; /* See ACPI_DRHD_DEV_SCOPE_* below */ - uint8_t length; /* 6 + X where X is Path attribute size */ - uint16_t _reserved; - uint8_t enumeration_id; - uint8_t start_bus_num; /* PCI bus, forming BDF with each Path below */ - struct acpi_dmar_dev_path path[]; /* One is at least always found */ -} __packed; - -#define ACPI_DMAR_DEV_SCOPE_MIN_SIZE 6 - -#define ACPI_DRHD_DEV_SCOPE_PCI_EPD 0x01 -#define ACPI_DRHD_DEV_SCOPE_PCI_SUB_H 0x02 -#define ACPI_DRHD_DEV_SCOPE_IOAPIC 0x03 -#define ACPI_DRHD_DEV_SCOPE_MSI_CAP_HPET 0x04 -#define ACPI_DRHD_DEV_SCOPE_NAMESPACE_DEV 0x05 - -struct acpi_drhd { - struct acpi_dmar_entry entry; - uint8_t flags; /* See ACPI_DRHD_FLAG_* below */ - uint8_t _reserved; - uint16_t segment_num; /* Associated PCI segment */ - uint64_t base_address; /* Base address of the remapping hw */ - struct acpi_dmar_dev_scope device_scope[]; -} __packed; - -#define ACPI_DRHD_MIN_SIZE 16 - -#define ACPI_DRHD_FLAG_INCLUDE_PCI_ALL BIT(0) - -#define ACPI_DMAR_SIGNATURE 0x52414D44 /* 'DMAR' */ - -#define ACPI_DMAR_FLAG_INTR_REMAP BIT(0) -#define ACPI_DMAR_FLAG_X2APIC_OPT_OUT BIT(1) -#define ACPI_DMAR_FLAG_DMA_CTRL_PLATFORM_OPT_IN BIT(2) - -/* DMA Remapping reporting structure */ -struct acpi_dmar { - struct acpi_sdt sdt; - uint8_t host_addr_width; - uint8_t flags; - uint8_t _reserved[10]; - struct acpi_dmar_entry remap_entries[]; -} __packed; - -union acpi_dmar_id { - struct { - uint16_t function : 3; - uint16_t device : 5; - uint16_t bus : 8; - } bits; - - uint16_t raw; -}; - -#if defined(CONFIG_X86_ACPI) - -void *z_acpi_find_table(uint32_t signature); - -struct acpi_cpu *z_acpi_get_cpu(int n); - -struct acpi_dmar *z_acpi_find_dmar(void); - -struct acpi_drhd *z_acpi_find_drhds(int *n); - -struct acpi_dmar_dev_scope *z_acpi_get_drhd_dev_scopes(struct acpi_drhd *drhd, - int *n); - -struct acpi_dmar_dev_path * -z_acpi_get_dev_scope_paths(struct acpi_dmar_dev_scope *dev_scope, int *n); - -uint16_t z_acpi_get_dev_id_from_dmar(uint8_t dev_scope_type); - -#else /* CONFIG_X86_ACPI */ - -#define z_acpi_find_table(...) NULL -#define z_acpi_get_cpu(...) NULL -#define z_acpi_find_dmar(...) NULL -#define z_acpi_find_drhds(...) NULL -#define z_acpi_get_drhd_dev_scopes(...) NULL -#define z_acpi_get_dev_scope_paths(...) NULL -#define z_acpi_get_dev_id_from_dmar(...) USHRT_MAX - -#endif /* CONFIG_X86_ACPI */ - -#endif /* _ASMLANGUAGE */ - -#endif /* ZEPHYR_INCLUDE_ARCH_X86_ACPI_H */ diff --git a/include/zephyr/arch/x86/ia32/linker.ld b/include/zephyr/arch/x86/ia32/linker.ld index 4d3ebe03f85..a0e2f5c6732 100644 --- a/include/zephyr/arch/x86/ia32/linker.ld +++ b/include/zephyr/arch/x86/ia32/linker.ld @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include diff --git a/include/zephyr/arch/x86/legacy_bios.h b/include/zephyr/arch/x86/legacy_bios.h new file mode 100644 index 00000000000..a5abd67d8c5 --- /dev/null +++ b/include/zephyr/arch/x86/legacy_bios.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_ARCH_X86_INCLUDE_LEGACY_BIOS_H_ +#define ZEPHYR_ARCH_X86_INCLUDE_LEGACY_BIOS_H_ + +void *bios_acpi_rsdp_get(void); + +#endif /* ZEPHYR_ARCH_X86_INCLUDE_LEGACY_BIOS_H_ */ diff --git a/include/zephyr/arch/x86/memory.ld b/include/zephyr/arch/x86/memory.ld index 8cc19fd6484..72b400dd079 100644 --- a/include/zephyr/arch/x86/memory.ld +++ b/include/zephyr/arch/x86/memory.ld @@ -29,7 +29,7 @@ #include #include -#include +#include /* Bounds of physical RAM from DTS */ #define PHYS_RAM_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_sram)) diff --git a/include/zephyr/arch/x86/x86_acpi_osal.h b/include/zephyr/arch/x86/x86_acpi_osal.h new file mode 100644 index 00000000000..8f742b024b7 --- /dev/null +++ b/include/zephyr/arch/x86/x86_acpi_osal.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +#ifndef ZEPHYR_ARCH_X86_INCLUDE_X86_ACPI_H_ +#define ZEPHYR_ARCH_X86_INCLUDE_X86_ACPI_H_ + +#if defined(CONFIG_X86_EFI) +static inline void *acpi_rsdp_get(void) +{ + void *rsdp = efi_get_acpi_rsdp(); + + if (!rsdp) { + rsdp = bios_acpi_rsdp_get(); + } + + return rsdp; +} +#else +static inline void *acpi_rsdp_get(void) +{ + return bios_acpi_rsdp_get(); +} +#endif /* CONFIG_X86_EFI */ +#endif /* ZEPHYR_ARCH_X86_INCLUDE_X86_ACPI_H_ */ diff --git a/include/zephyr/audio/codec.h b/include/zephyr/audio/codec.h index e65b00d87f3..082fd3e4ae3 100644 --- a/include/zephyr/audio/codec.h +++ b/include/zephyr/audio/codec.h @@ -32,64 +32,65 @@ extern "C" { * PCM audio sample rates */ typedef enum { - AUDIO_PCM_RATE_8K = 8000, - AUDIO_PCM_RATE_16K = 16000, - AUDIO_PCM_RATE_24K = 24000, - AUDIO_PCM_RATE_32K = 32000, - AUDIO_PCM_RATE_44P1K = 44100, - AUDIO_PCM_RATE_48K = 48000, - AUDIO_PCM_RATE_96K = 96000, - AUDIO_PCM_RATE_192K = 192000, + AUDIO_PCM_RATE_8K = 8000, /**< 8 kHz sample rate */ + AUDIO_PCM_RATE_16K = 16000, /**< 16 kHz sample rate */ + AUDIO_PCM_RATE_24K = 24000, /**< 24 kHz sample rate */ + AUDIO_PCM_RATE_32K = 32000, /**< 32 kHz sample rate */ + AUDIO_PCM_RATE_44P1K = 44100, /**< 44.1 kHz sample rate */ + AUDIO_PCM_RATE_48K = 48000, /**< 48 kHz sample rate */ + AUDIO_PCM_RATE_96K = 96000, /**< 96 kHz sample rate */ + AUDIO_PCM_RATE_192K = 192000, /**< 192 kHz sample rate */ } audio_pcm_rate_t; /** * PCM audio sample bit widths */ typedef enum { - AUDIO_PCM_WIDTH_16_BITS = 16, - AUDIO_PCM_WIDTH_20_BITS = 20, - AUDIO_PCM_WIDTH_24_BITS = 24, - AUDIO_PCM_WIDTH_32_BITS = 32, + AUDIO_PCM_WIDTH_16_BITS = 16, /**< 16-bit sample width */ + AUDIO_PCM_WIDTH_20_BITS = 20, /**< 20-bit sample width */ + AUDIO_PCM_WIDTH_24_BITS = 24, /**< 24-bit sample width */ + AUDIO_PCM_WIDTH_32_BITS = 32, /**< 32-bit sample width */ } audio_pcm_width_t; /** * Digital Audio Interface (DAI) type */ typedef enum { - AUDIO_DAI_TYPE_I2S, /* I2S Interface */ - AUDIO_DAI_TYPE_INVALID, /* Other interfaces can be added here */ + AUDIO_DAI_TYPE_I2S, /**< I2S Interface */ + AUDIO_DAI_TYPE_INVALID, /**< Other interfaces can be added here */ } audio_dai_type_t; /** - * Codec properties that can be set by audio_codec_set_property() + * Codec properties that can be set by audio_codec_set_property(). */ typedef enum { - AUDIO_PROPERTY_OUTPUT_VOLUME, - AUDIO_PROPERTY_OUTPUT_MUTE, + AUDIO_PROPERTY_OUTPUT_VOLUME, /**< Output volume */ + AUDIO_PROPERTY_OUTPUT_MUTE, /**< Output mute/unmute */ } audio_property_t; /** - * Audio channel identifiers to use in audio_codec_set_property() + * Audio channel identifiers to use in audio_codec_set_property(). */ typedef enum { - AUDIO_CHANNEL_FRONT_LEFT, - AUDIO_CHANNEL_FRONT_RIGHT, - AUDIO_CHANNEL_LFE, - AUDIO_CHANNEL_FRONT_CENTER, - AUDIO_CHANNEL_REAR_LEFT, - AUDIO_CHANNEL_REAR_RIGHT, - AUDIO_CHANNEL_REAR_CENTER, - AUDIO_CHANNEL_SIDE_LEFT, - AUDIO_CHANNEL_SIDE_RIGHT, - AUDIO_CHANNEL_ALL, + AUDIO_CHANNEL_FRONT_LEFT, /**< Front left channel */ + AUDIO_CHANNEL_FRONT_RIGHT, /**< Front right channel */ + AUDIO_CHANNEL_LFE, /**< Low frequency effect channel */ + AUDIO_CHANNEL_FRONT_CENTER, /**< Front center channel */ + AUDIO_CHANNEL_REAR_LEFT, /**< Rear left channel */ + AUDIO_CHANNEL_REAR_RIGHT, /**< Rear right channel */ + AUDIO_CHANNEL_REAR_CENTER, /**< Rear center channel */ + AUDIO_CHANNEL_SIDE_LEFT, /**< Side left channel */ + AUDIO_CHANNEL_SIDE_RIGHT, /**< Side right channel */ + AUDIO_CHANNEL_ALL, /**< All channels */ } audio_channel_t; /** - * Digital Audio Interface Configuration + * @brief Digital Audio Interface Configuration. + * * Configuration is dependent on DAI type */ typedef union { - struct i2s_config i2s; /* I2S configuration */ + struct i2s_config i2s; /**< I2S configuration */ /* Other DAI types go here */ } audio_dai_cfg_t; @@ -97,19 +98,48 @@ typedef union { * Codec configuration parameters */ struct audio_codec_cfg { - uint32_t mclk_freq; /* MCLK input frequency in Hz */ - audio_dai_type_t dai_type; /* Digital interface type */ - audio_dai_cfg_t dai_cfg; /* DAI configuration info */ + uint32_t mclk_freq; /**< MCLK input frequency in Hz */ + audio_dai_type_t dai_type; /**< Digital interface type */ + audio_dai_cfg_t dai_cfg; /**< DAI configuration info */ }; /** * Codec property values */ typedef union { - int vol; /* Volume level in 0.5dB resolution */ - bool mute; /* mute if true, unmute if false */ + int vol; /**< Volume level in 0.5dB resolution */ + bool mute; /**< Mute if @a true, unmute if @a false */ } audio_property_value_t; +/** + * @brief Codec error type + */ +enum audio_codec_error_type { + /** Output over-current */ + AUDIO_CODEC_ERROR_OVERCURRENT = BIT(0), + + /** Codec over-temperature */ + AUDIO_CODEC_ERROR_OVERTEMPERATURE = BIT(1), + + /** Power low voltage */ + AUDIO_CODEC_ERROR_UNDERVOLTAGE = BIT(2), + + /** Power high voltage */ + AUDIO_CODEC_ERROR_OVERVOLTAGE = BIT(3), + + /** Output direct-current */ + AUDIO_CODEC_ERROR_DC = BIT(4), +}; + +/** + * @typedef audio_codec_error_callback_t + * @brief Callback for error interrupt + * + * @param dev Pointer to the codec device + * @param errors Device errors (bitmask of @ref audio_codec_error_type values) + */ +typedef void (*audio_codec_error_callback_t)(const struct device *dev, uint32_t errors); + /** * @cond INTERNAL_HIDDEN * @@ -125,6 +155,9 @@ struct audio_codec_api { audio_channel_t channel, audio_property_value_t val); int (*apply_properties)(const struct device *dev); + int (*clear_errors)(const struct device *dev); + int (*register_error_callback)(const struct device *dev, + audio_codec_error_callback_t cb); }; /** * @endcond @@ -222,6 +255,55 @@ static inline int audio_codec_apply_properties(const struct device *dev) return api->apply_properties(dev); } +/** + * @brief Clear any codec errors + * + * Clear all codec errors. + * If an error interrupt exists, it will be de-asserted. + * + * @param dev Pointer to the device structure for codec driver instance. + * + * @return 0 on success, negative error code on failure + */ +static inline int audio_codec_clear_errors(const struct device *dev) +{ + const struct audio_codec_api *api = + (const struct audio_codec_api *)dev->api; + + if (api->clear_errors == NULL) { + return -ENOSYS; + } + + return api->clear_errors(dev); +} + +/** + * @brief Register a callback function for codec error + * + * The callback will be called from a thread, so I2C or SPI operations are + * safe. However, the thread's stack is limited and defined by the + * driver. It is currently up to the caller to ensure that the callback + * does not overflow the stack. + * + * @param dev Pointer to the audio codec device + * @param cb The function that should be called when an error is detected + * fires + * + * @return 0 if successful, negative errno code if failure. + */ +static inline int audio_codec_register_error_callback(const struct device *dev, + audio_codec_error_callback_t cb) +{ + const struct audio_codec_api *api = + (const struct audio_codec_api *)dev->api; + + if (api->register_error_callback == NULL) { + return -ENOSYS; + } + + return api->register_error_callback(dev, cb); +} + #ifdef __cplusplus } #endif diff --git a/include/zephyr/audio/dmic.h b/include/zephyr/audio/dmic.h index 78e996c9b06..e6736b8676c 100644 --- a/include/zephyr/audio/dmic.h +++ b/include/zephyr/audio/dmic.h @@ -43,110 +43,129 @@ extern "C" { * DMIC driver states */ enum dmic_state { - DMIC_STATE_UNINIT, /* Uninitialized */ - DMIC_STATE_INITIALIZED, /* Initialized */ - DMIC_STATE_CONFIGURED, /* Configured */ - DMIC_STATE_ACTIVE, /* Active */ - DMIC_STATE_PAUSED, /* Paused */ + DMIC_STATE_UNINIT, /**< Uninitialized */ + DMIC_STATE_INITIALIZED, /**< Initialized */ + DMIC_STATE_CONFIGURED, /**< Configured */ + DMIC_STATE_ACTIVE, /**< Active */ + DMIC_STATE_PAUSED, /**< Paused */ }; /** * DMIC driver trigger commands */ enum dmic_trigger { - DMIC_TRIGGER_STOP, /* stop stream */ - DMIC_TRIGGER_START, /* start stream */ - DMIC_TRIGGER_PAUSE, /* pause the stream */ - DMIC_TRIGGER_RELEASE, /* release paused stream */ - DMIC_TRIGGER_RESET, /* reset */ + DMIC_TRIGGER_STOP, /**< Stop stream */ + DMIC_TRIGGER_START, /**< Start stream */ + DMIC_TRIGGER_PAUSE, /**< Pause stream */ + DMIC_TRIGGER_RELEASE, /**< Release paused stream */ + DMIC_TRIGGER_RESET, /**< Reset stream */ }; /** * PDM Channels LEFT / RIGHT */ enum pdm_lr { - PDM_CHAN_LEFT, - PDM_CHAN_RIGHT, + PDM_CHAN_LEFT, /**< Left channel */ + PDM_CHAN_RIGHT, /**< Right channel */ }; /** * PDM Input/Output signal configuration */ struct pdm_io_cfg { - /* parameters global to all PDM controllers */ - - /* minimum clock frequency supported by the mic */ + /** + * @name Parameters common to all PDM controllers + *@{ + */ + /** Minimum clock frequency supported by the mic */ uint32_t min_pdm_clk_freq; - /* maximum clock frequency supported by the mic */ + /** Maximum clock frequency supported by the mic */ uint32_t max_pdm_clk_freq; - /* minimum duty cycle in % supported by the mic */ + /** Minimum duty cycle in % supported by the mic */ uint8_t min_pdm_clk_dc; - /* maximum duty cycle in % supported by the mic */ + /** Maximum duty cycle in % supported by the mic */ uint8_t max_pdm_clk_dc; + /** + * @} + */ - /* parameters unique to each PDM controller */ - - /* Bit mask to optionally invert PDM clock */ + /** + * @name Parameters unique to each PDM controller + * @{ + */ + /** Bit mask to optionally invert PDM clock */ uint8_t pdm_clk_pol; - /* Bit mask to optionally invert mic data */ + /** Bit mask to optionally invert mic data */ uint8_t pdm_data_pol; - /* Collection of clock skew values for each PDM port */ + /** Collection of clock skew values for each PDM port */ uint32_t pdm_clk_skew; + /** + * @} + */ }; /** * Configuration of the PCM streams to be output by the PDM hardware + * + * @note if either \ref pcm_rate or \ref pcm_width is set to 0 for a stream, + * the stream would be disabled */ struct pcm_stream_cfg { - /* - * if either rate or width is set to 0 for a stream, - * the stream would be disabled - */ - - /* PCM sample rate of stream */ + /** PCM sample rate of stream */ uint32_t pcm_rate; - /* PCM sample width of stream */ + /** PCM sample width of stream */ uint8_t pcm_width; - /* PCM sample block size per transfer */ + /** PCM sample block size per transfer */ uint16_t block_size; - /* SLAB for DMIC driver to allocate buffers for stream */ + /** SLAB for DMIC driver to allocate buffers for stream */ struct k_mem_slab *mem_slab; }; /** * Mapping/ordering of the PDM channels to logical PCM output channel + * + * Since each controller can have 2 audio channels (stereo), + * there can be a total of 8x2=16 channels. The actual number of channels + * shall be described in \ref act_num_chan. + * + * If 2 streams are enabled, the channel order will be the same for + * both streams. + * + * Each channel is described as a 4-bit number, the least significant + * bit indicates LEFT/RIGHT selection of the PDM controller. + * + * The most significant 3 bits indicate the PDM controller number: + * - bits 0-3 are for channel 0, bit 0 indicates LEFT or RIGHT + * - bits 4-7 are for channel 1, bit 4 indicates LEFT or RIGHT + * and so on. + * + * CONSTRAINT: The LEFT and RIGHT channels of EACH PDM controller needs + * to be adjacent to each other. */ struct pdm_chan_cfg { - /* - * mapping of PDM controller and mic channel to logical channel - * since each controller can have 2 audio channels (stereo), - * there can be total of 8x2=16 channels. - * The actual number of channels shall be described in - * pcm_stream_cfg.num_chan. - * if 2 streams are enabled, the channel order will be the same for - * both streams - * Each channel is described as a 4 bit number, the least significant - * bit indicates LEFT/RIGHT selection of the PDM controller. - * The most significant 3 bits indicate the PDM controller number. - * bits 0-3 are for channel 0, bit 0 indicates LEFT or RIGHT - * bits 4-7 are for channel 1, bit 4 indicates LEFT or RIGHT - * and so on. - * CONSTRAINT: The LEFT and RIGHT channels of EACH PDM controller needs - * to be adjacent to each other. + /** + * @name Requested channel map + * @{ + */ + uint32_t req_chan_map_lo; /**< Channels 0 to 7 */ + uint32_t req_chan_map_hi; /**< Channels 8 to 15 */ + /** @} */ + + /** + * @name Actual channel map that the driver could configure + * @{ */ - /* Requested channel map */ - uint32_t req_chan_map_lo; /* Channels 0 to 7 */ - uint32_t req_chan_map_hi; /* Channels 8 to 15 */ - /* Actual channel map that the driver could configure */ - uint32_t act_chan_map_lo; /* Channels 0 to 7 */ - uint32_t act_chan_map_hi; /* Channels 8 to 15 */ - /* requested number of channels */ + uint32_t act_chan_map_lo; /**< Channels 0 to 7 */ + uint32_t act_chan_map_hi; /**< Channels 8 to 15 */ + /** @} */ + + /** Requested number of channels */ uint8_t req_num_chan; - /* Actual number of channels that the driver could configure */ + /** Actual number of channels that the driver could configure */ uint8_t act_num_chan; - /* requested number of streams for each channel */ + /** Requested number of streams for each channel */ uint8_t req_num_streams; - /* Actual number of streams that the driver could configure */ + /** Actual number of streams that the driver could configure */ uint8_t act_num_streams; }; @@ -155,7 +174,7 @@ struct pdm_chan_cfg { */ struct dmic_cfg { struct pdm_io_cfg io; - /* + /** * Array of pcm_stream_cfg for application to provide * configuration for each stream */ diff --git a/include/zephyr/bindesc.h b/include/zephyr/bindesc.h new file mode 100644 index 00000000000..4280cf91d21 --- /dev/null +++ b/include/zephyr/bindesc.h @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2023 Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ZEPHYR_BINDESC_H_ +#define ZEPHYR_INCLUDE_ZEPHYR_BINDESC_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* + * Corresponds to the definitions in scripts/west_commands/bindesc.py. + * Do not change without syncing the definitions in both files! + */ +#define BINDESC_MAGIC 0xb9863e5a7ea46046 +#define BINDESC_ALIGNMENT 4 +#define BINDESC_TYPE_UINT 0x0 +#define BINDESC_TYPE_STR 0x1 +#define BINDESC_TYPE_BYTES 0x2 +#define BINDESC_TYPE_DESCRIPTORS_END 0xf + +/** + * @brief Binary Descriptor Definition + * @defgroup bindesc_define Bindesc Define + * @{ + */ + +/* + * Corresponds to the definitions in scripts/west_commands/bindesc.py. + * Do not change without syncing the definitions in both files! + */ + +/** The app version string such as "1.2.3" */ +#define BINDESC_ID_APP_VERSION_STRING 0x800 + +/** The app version major such as 1 */ +#define BINDESC_ID_APP_VERSION_MAJOR 0x801 + +/** The app version minor such as 2 */ +#define BINDESC_ID_APP_VERSION_MINOR 0x802 + +/** The app version patchlevel such as 3 */ +#define BINDESC_ID_APP_VERSION_PATCHLEVEL 0x803 + +/** The app version number such as 0x10203 */ +#define BINDESC_ID_APP_VERSION_NUMBER 0x804 + +/** The kernel version string such as "3.4.0" */ +#define BINDESC_ID_KERNEL_VERSION_STRING 0x900 + +/** The kernel version major such as 3 */ +#define BINDESC_ID_KERNEL_VERSION_MAJOR 0x901 + +/** The kernel version minor such as 4 */ +#define BINDESC_ID_KERNEL_VERSION_MINOR 0x902 + +/** The kernel version patchlevel such as 0 */ +#define BINDESC_ID_KERNEL_VERSION_PATCHLEVEL 0x903 + +/** The kernel version number such as 0x30400 */ +#define BINDESC_ID_KERNEL_VERSION_NUMBER 0x904 + +/** The year the image was compiled in */ +#define BINDESC_ID_BUILD_TIME_YEAR 0xa00 + +/** The month of the year the image was compiled in */ +#define BINDESC_ID_BUILD_TIME_MONTH 0xa01 + +/** The day of the month the image was compiled in */ +#define BINDESC_ID_BUILD_TIME_DAY 0xa02 + +/** The hour of the day the image was compiled in */ +#define BINDESC_ID_BUILD_TIME_HOUR 0xa03 + +/** The minute the image was compiled in */ +#define BINDESC_ID_BUILD_TIME_MINUTE 0xa04 + +/** The second the image was compiled in */ +#define BINDESC_ID_BUILD_TIME_SECOND 0xa05 + +/** The UNIX time (seconds since midnight of 1970/01/01) the image was compiled in */ +#define BINDESC_ID_BUILD_TIME_UNIX 0xa06 + +/** The date and time of compilation such as "2023/02/05 00:07:04" */ +#define BINDESC_ID_BUILD_DATE_TIME_STRING 0xa07 + +/** The date of compilation such as "2023/02/05" */ +#define BINDESC_ID_BUILD_DATE_STRING 0xa08 + +/** The time of compilation such as "00:07:04" */ +#define BINDESC_ID_BUILD_TIME_STRING 0xa09 + +/** The name of the host that compiled the image */ +#define BINDESC_ID_HOST_NAME 0xb00 + +/** The C compiler name */ +#define BINDESC_ID_C_COMPILER_NAME 0xb01 + +/** The C compiler version */ +#define BINDESC_ID_C_COMPILER_VERSION 0xb02 + +/** The C++ compiler name */ +#define BINDESC_ID_CXX_COMPILER_NAME 0xb03 + +/** The C++ compiler version */ +#define BINDESC_ID_CXX_COMPILER_VERSION 0xb04 + +#define BINDESC_TAG_DESCRIPTORS_END BINDESC_TAG(DESCRIPTORS_END, 0x0fff) + +/** + * @cond INTERNAL_HIDDEN + */ + +/* + * Utility macro to generate a tag from a type and an ID + * + * type - Type of the descriptor, UINT, STR or BYTES + * id - Unique ID for the descriptor, must fit in 12 bits + */ +#define BINDESC_TAG(type, id) ((BINDESC_TYPE_##type & 0xf) << 12 | (id & 0x0fff)) + +/** + * @endcond + */ + +#if !IS_ENABLED(_LINKER) + +#include + +/** + * @cond INTERNAL_HIDDEN + */ + +/* + * Utility macro to get the name of a bindesc entry + */ +#define BINDESC_NAME(name) bindesc_entry_##name + +/* Convenience helper for declaring a binary descriptor entry. */ +#define __BINDESC_ENTRY_DEFINE(name) \ + __aligned(BINDESC_ALIGNMENT) const struct bindesc_entry BINDESC_NAME(name) \ + __in_section(_bindesc_entry, static, name) __used __noasan + +/** + * @endcond + */ + +/** + * @brief Define a binary descriptor of type string. + * + * @details + * Define a string that is registered in the binary descriptor header. + * The defined string can be accessed using @ref BINDESC_GET_STR + * + * @note The defined string is not static, so its name must not collide with + * any other symbol in the executable. + * + * @param name Name of the descriptor + * @param id Unique ID of the descriptor + * @param value A string value for the descriptor + */ +#define BINDESC_STR_DEFINE(name, id, value) \ + __BINDESC_ENTRY_DEFINE(name) = { \ + .tag = BINDESC_TAG(STR, id), \ + .len = (uint16_t)sizeof(value), \ + .data = value, \ + } + +/** + * @brief Define a binary descriptor of type uint. + * + * @details + * Define an integer that is registered in the binary descriptor header. + * The defined integer can be accessed using @ref BINDESC_GET_UINT + * + * @note The defined integer is not static, so its name must not collide with + * any other symbol in the executable. + * + * @param name Name of the descriptor + * @param id Unique ID of the descriptor + * @param value An integer value for the descriptor + */ +#define BINDESC_UINT_DEFINE(name, id, value) \ + __BINDESC_ENTRY_DEFINE(name) = { \ + .tag = BINDESC_TAG(UINT, id), \ + .len = (uint16_t)sizeof(uint32_t), \ + .data = sys_uint32_to_array(value), \ + } + +/** + * @brief Define a binary descriptor of type bytes. + * + * @details + * Define a uint8_t array that is registered in the binary descriptor header. + * The defined array can be accessed using @ref BINDESC_GET_BYTES. + * The value should be given as an array literal, wrapped in parentheses, for + * example: + * + * BINDESC_BYTES_DEFINE(name, id, ({1, 2, 3, 4})); + * + * @note The defined array is not static, so its name must not collide with + * any other symbol in the executable. + * + * @param name Name of the descriptor + * @param id Unique ID of the descriptor + * @param value A uint8_t array as data for the descriptor + */ +#define BINDESC_BYTES_DEFINE(name, id, value) \ + __BINDESC_ENTRY_DEFINE(name) = { \ + .tag = BINDESC_TAG(BYTES, id), \ + .len = (uint16_t)sizeof((uint8_t [])__DEBRACKET value), \ + .data = __DEBRACKET value, \ + } + +/** + * @brief Get the value of a string binary descriptor + * + * @details + * Get the value of a string binary descriptor, previously defined by + * BINDESC_STR_DEFINE. + * + * @param name Name of the descriptor + */ +#define BINDESC_GET_STR(name) BINDESC_NAME(name).data + +/** + * @brief Get the value of a uint binary descriptor + * + * @details + * Get the value of a uint binary descriptor, previously defined by + * BINDESC_UINT_DEFINE. + * + * @param name Name of the descriptor + */ +#define BINDESC_GET_UINT(name) *(uint32_t *)&(BINDESC_NAME(name).data) + +/** + * @brief Get the value of a bytes binary descriptor + * + * @details + * Get the value of a string binary descriptor, previously defined by + * BINDESC_BYTES_DEFINE. The returned value can be accessed as an array: + * + * for (size_t i = 0; i < BINDESC_GET_SIZE(name); i++) + * BINDESC_GET_BYTES(name)[i]; + * + * @param name Name of the descriptor + */ +#define BINDESC_GET_BYTES(name) BINDESC_NAME(name).data + +/** + * @brief Get the size of a binary descriptor + * + * @details + * Get the size of a binary descriptor. This is particularly useful for + * bytes binary descriptors where there's no null terminator. + * + * @param name Name of the descriptor + */ +#define BINDESC_GET_SIZE(name) BINDESC_NAME(name).len + +/** + * @} + */ + +/* + * An entry of the binary descriptor header. Each descriptor is + * described by one of these entries. + */ +struct bindesc_entry { + /** Tag of the entry */ + uint16_t tag; + /** Length of the descriptor data */ + uint16_t len; + /** Value of the entry. This is either an integer or a string */ + uint8_t data[]; +} __packed; + +/* + * We're assuming that `struct bindesc_entry` has a specific layout in + * memory, so it's worth making sure that the layout is really what we + * think it is. If these assertions fail for your toolchain/platform, + * please open a bug report. + */ +BUILD_ASSERT(offsetof(struct bindesc_entry, tag) == 0, "Incorrect memory layout"); +BUILD_ASSERT(offsetof(struct bindesc_entry, len) == 2, "Incorrect memory layout"); +BUILD_ASSERT(offsetof(struct bindesc_entry, data) == 4, "Incorrect memory layout"); + +#if IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_STRING) +extern const struct bindesc_entry BINDESC_NAME(kernel_version_string); +#endif /* IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_STRING) */ + +#if IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_MAJOR) +extern const struct bindesc_entry BINDESC_NAME(kernel_version_major); +#endif /* IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_MAJOR) */ + +#if IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_MINOR) +extern const struct bindesc_entry BINDESC_NAME(kernel_version_minor); +#endif /* IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_MINOR) */ + +#if IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_PATCHLEVEL) +extern const struct bindesc_entry BINDESC_NAME(kernel_version_patchlevel); +#endif /* IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_PATCHLEVEL) */ + +#if IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_NUMBER) +extern const struct bindesc_entry BINDESC_NAME(kernel_version_number); +#endif /* IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_NUMBER) */ + +#if IS_ENABLED(CONFIG_BINDESC_APP_VERSION_STRING) +extern const struct bindesc_entry BINDESC_NAME(app_version_string); +#endif /* IS_ENABLED(CONFIG_BINDESC_APP_VERSION_STRING) */ + +#if IS_ENABLED(CONFIG_BINDESC_APP_VERSION_MAJOR) +extern const struct bindesc_entry BINDESC_NAME(app_version_major); +#endif /* IS_ENABLED(CONFIG_BINDESC_APP_VERSION_MAJOR) */ + +#if IS_ENABLED(CONFIG_BINDESC_APP_VERSION_MINOR) +extern const struct bindesc_entry BINDESC_NAME(app_version_minor); +#endif /* IS_ENABLED(CONFIG_BINDESC_APP_VERSION_MINOR) */ + +#if IS_ENABLED(CONFIG_BINDESC_APP_VERSION_PATCHLEVEL) +extern const struct bindesc_entry BINDESC_NAME(app_version_patchlevel); +#endif /* IS_ENABLED(CONFIG_BINDESC_APP_VERSION_PATCHLEVEL) */ + +#if IS_ENABLED(CONFIG_BINDESC_APP_VERSION_NUMBER) +extern const struct bindesc_entry BINDESC_NAME(app_version_number); +#endif /* IS_ENABLED(CONFIG_BINDESC_APP_VERSION_NUMBER) */ + +#if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_YEAR) +extern const struct bindesc_entry BINDESC_NAME(build_time_year); +#endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_YEAR) */ + +#if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_MONTH) +extern const struct bindesc_entry BINDESC_NAME(build_time_month); +#endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_MONTH) */ + +#if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_DAY) +extern const struct bindesc_entry BINDESC_NAME(build_time_day); +#endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_DAY) */ + +#if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_HOUR) +extern const struct bindesc_entry BINDESC_NAME(build_time_hour); +#endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_HOUR) */ + +#if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_MINUTE) +extern const struct bindesc_entry BINDESC_NAME(build_time_minute); +#endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_MINUTE) */ + +#if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_SECOND) +extern const struct bindesc_entry BINDESC_NAME(build_time_second); +#endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_SECOND) */ + +#if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_UNIX) +extern const struct bindesc_entry BINDESC_NAME(build_time_unix); +#endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_UNIX) */ + +#if IS_ENABLED(CONFIG_BINDESC_BUILD_DATE_TIME_STRING) +extern const struct bindesc_entry BINDESC_NAME(build_date_time_string); +#endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_DATE_TIME_STRING) */ + +#if IS_ENABLED(CONFIG_BINDESC_BUILD_DATE_STRING) +extern const struct bindesc_entry BINDESC_NAME(build_date_string); +#endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_DATE_STRING) */ + +#if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_STRING) +extern const struct bindesc_entry BINDESC_NAME(build_time_string); +#endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_STRING) */ + +#if IS_ENABLED(CONFIG_BINDESC_HOST_NAME) +extern const struct bindesc_entry BINDESC_NAME(host_name); +#endif /* IS_ENABLED(CONFIG_BINDESC_HOST_NAME) */ + +#if IS_ENABLED(CONFIG_BINDESC_C_COMPILER_NAME) +extern const struct bindesc_entry BINDESC_NAME(c_compiler_name); +#endif /* IS_ENABLED(CONFIG_BINDESC_C_COMPILER_NAME) */ + +#if IS_ENABLED(CONFIG_BINDESC_C_COMPILER_VERSION) +extern const struct bindesc_entry BINDESC_NAME(c_compiler_version); +#endif /* IS_ENABLED(CONFIG_BINDESC_C_COMPILER_VERSION) */ + +#if IS_ENABLED(CONFIG_BINDESC_CXX_COMPILER_NAME) +extern const struct bindesc_entry BINDESC_NAME(cxx_compiler_name); +#endif /* IS_ENABLED(CONFIG_BINDESC_CXX_COMPILER_NAME) */ + +#if IS_ENABLED(CONFIG_BINDESC_CXX_COMPILER_VERSION) +extern const struct bindesc_entry BINDESC_NAME(cxx_compiler_version); +#endif /* IS_ENABLED(CONFIG_BINDESC_CXX_COMPILER_VERSION) */ + +#endif /* !IS_ENABLED(_LINKER) */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_ZEPHYR_BINDESC_H_ */ diff --git a/include/zephyr/bluetooth/a2dp-codec.h b/include/zephyr/bluetooth/a2dp-codec.h index 9e4e5ea3479..3da36420dcd 100644 --- a/include/zephyr/bluetooth/a2dp-codec.h +++ b/include/zephyr/bluetooth/a2dp-codec.h @@ -26,36 +26,76 @@ extern "C" { #endif -/* Sampling Frequency */ -#define A2DP_SBC_SAMP_FREQ_16000 BIT(7) -#define A2DP_SBC_SAMP_FREQ_32000 BIT(6) -#define A2DP_SBC_SAMP_FREQ_44100 BIT(5) -#define A2DP_SBC_SAMP_FREQ_48000 BIT(4) +/** + * @name Sampling Frequency + * @{ + */ +#define A2DP_SBC_SAMP_FREQ_16000 BIT(7) /**< 16 kHz */ +#define A2DP_SBC_SAMP_FREQ_32000 BIT(6) /**< 32 kHz */ +#define A2DP_SBC_SAMP_FREQ_44100 BIT(5) /**< 44.1 kHz */ +#define A2DP_SBC_SAMP_FREQ_48000 BIT(4) /**< 48 kHz */ +/** @} */ -/* Channel Mode */ -#define A2DP_SBC_CH_MODE_MONO BIT(3) -#define A2DP_SBC_CH_MODE_DUAL BIT(2) -#define A2DP_SBC_CH_MODE_STREO BIT(1) -#define A2DP_SBC_CH_MODE_JOINT BIT(0) +/** + * @name Channel Mode + * @{ + */ +#define A2DP_SBC_CH_MODE_MONO BIT(3) /**< Mono */ +#define A2DP_SBC_CH_MODE_DUAL BIT(2) /**< Dual Channel */ +#define A2DP_SBC_CH_MODE_STREO BIT(1) /**< Stereo */ +#define A2DP_SBC_CH_MODE_JOINT BIT(0) /**< Joint Stereo */ +/** @} */ -/* Block Length */ -#define A2DP_SBC_BLK_LEN_4 BIT(7) -#define A2DP_SBC_BLK_LEN_8 BIT(6) -#define A2DP_SBC_BLK_LEN_12 BIT(5) -#define A2DP_SBC_BLK_LEN_16 BIT(4) +/** + * @name Block Length + * @{ + */ +#define A2DP_SBC_BLK_LEN_4 BIT(7) /**< 4 blocks */ +#define A2DP_SBC_BLK_LEN_8 BIT(6) /**< 8 blocks */ +#define A2DP_SBC_BLK_LEN_12 BIT(5) /**< 12 blocks */ +#define A2DP_SBC_BLK_LEN_16 BIT(4) /**< 16 blocks */ +/** @} */ -/* Subbands */ -#define A2DP_SBC_SUBBAND_4 BIT(3) -#define A2DP_SBC_SUBBAND_8 BIT(2) +/** + * @name Subbands + * @{ + */ +#define A2DP_SBC_SUBBAND_4 BIT(3) /**< 4 subbands */ +#define A2DP_SBC_SUBBAND_8 BIT(2) /**< 8 subbands */ +/** @} */ -/* Allocation Method */ -#define A2DP_SBC_ALLOC_MTHD_SNR BIT(1) -#define A2DP_SBC_ALLOC_MTHD_LOUDNESS BIT(0) +/** + * @name Bit pool Allocation Method + * @{ + */ +#define A2DP_SBC_ALLOC_MTHD_SNR BIT(1) /**< Allocate based on loudness of the subband signal */ +#define A2DP_SBC_ALLOC_MTHD_LOUDNESS BIT(0) /**< Allocate based on the signal-to-noise ratio */ +/** @} */ +/** + * Gets the sampling rate from a codec preset + * @param preset Codec preset + */ #define BT_A2DP_SBC_SAMP_FREQ(preset) ((preset->config[0] >> 4) & 0x0f) +/** + * Gets the channel mode from a codec preset + * @param preset Codec preset + */ #define BT_A2DP_SBC_CHAN_MODE(preset) ((preset->config[0]) & 0x0f) +/** + * Gets the block length from a codec preset + * @param preset Codec preset + */ #define BT_A2DP_SBC_BLK_LEN(preset) ((preset->config[1] >> 4) & 0x0f) +/** + * Gets the number subbands from a codec preset + * @param preset Codec preset + */ #define BT_A2DP_SBC_SUB_BAND(preset) ((preset->config[1] >> 2) & 0x03) +/** + * Gets the bitpool allocation method from a codec preset + * @param preset Codec preset + */ #define BT_A2DP_SBC_ALLOC_MTHD(preset) ((preset->config[1]) & 0x03) /** @brief SBC Codec */ diff --git a/include/zephyr/bluetooth/a2dp.h b/include/zephyr/bluetooth/a2dp.h index 3df6db1a6fd..f7e8ff35ea1 100644 --- a/include/zephyr/bluetooth/a2dp.h +++ b/include/zephyr/bluetooth/a2dp.h @@ -1,5 +1,5 @@ /** @file - * @brief Advance Audio Distribution Profile header. + * @brief Advanced Audio Distribution Profile header. */ /* diff --git a/include/zephyr/bluetooth/audio/audio.h b/include/zephyr/bluetooth/audio/audio.h index 58506030686..17bac991f18 100644 --- a/include/zephyr/bluetooth/audio/audio.h +++ b/include/zephyr/bluetooth/audio/audio.h @@ -479,6 +479,31 @@ struct bt_audio_codec_qos { * Value range 0 to @ref BT_AUDIO_PD_MAX. */ uint32_t pd; + +#if defined(CONFIG_BT_ISO_TEST_PARAMS) + /** @brief Maximum PDU size + * + * Maximum size, in octets, of the payload from link layer to link + * layer. + * + * Value range @ref BT_ISO_PDU_MIN to @ref BT_ISO_PDU_MAX. + */ + uint16_t max_pdu; + + /** @brief Burst number + * + * Value range @ref BT_ISO_BN_MIN to @ref BT_ISO_BN_MAX. + */ + uint8_t burst_number; + + /** @brief Number of subevents + * + * Maximum number of subevents in each CIS or BIS event. + * + * Value range @ref BT_ISO_NSE_MIN to @ref BT_ISO_NSE_MAX. + */ + uint8_t num_subevents; +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ }; /** @@ -567,40 +592,92 @@ struct bt_audio_codec_qos_pref { */ /** - * @brief Codec parser error codes for @ref bt_audio_codec_cfg. + * @brief Convert assigned numbers frequency to frequency value. + * + * @param freq The assigned numbers frequency to convert. + * + * @retval -EINVAL if arguments are invalid. + * @retval The converted frequency value in Hz. */ -enum bt_audio_codec_cfg_parse_err { - - /** @brief The requested type is not present in the data set. */ - BT_AUDIO_CODEC_PARSE_ERR_SUCCESS = 0, - - /** @brief The requested type is not present in the data set. */ - BT_AUDIO_CODEC_PARSE_ERR_TYPE_NOT_FOUND = -1, +int bt_audio_codec_cfg_freq_to_freq_hz(enum bt_audio_codec_config_freq freq); - /** @brief The value found is invalid. */ - BT_AUDIO_CODEC_PARSE_ERR_INVALID_VALUE_FOUND = -2, - - /** @brief The parameters specified to the function call are not valid. */ - BT_AUDIO_CODEC_PARSE_ERR_INVALID_PARAM = -3, -}; +/** + * @brief Convert frequency value to assigned numbers frequency. + * + * @param freq_hz The frequency value to convert. + * + * @retval -EINVAL if arguments are invalid. + * @retval The assigned numbers frequency (@ref bt_audio_codec_config_freq). + */ +int bt_audio_codec_cfg_freq_hz_to_freq(uint32_t freq_hz); /**@brief Extract the frequency from a codec configuration. * * @param codec_cfg The codec configuration to extract data from. * - * @return The frequency in Hz if found else a negative value of type - * @ref bt_audio_codec_cfg_parse_err. + * @retval A @ref bt_audio_codec_config_freq value + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size or value */ int bt_audio_codec_cfg_get_freq(const struct bt_audio_codec_cfg *codec_cfg); +/** + * @brief Set the frequency of a codec configuration. + * + * @param codec_cfg The codec configuration to set data for. + * @param freq The assigned numbers frequency to set. + * + * @retval The data_len of @p codec_cfg on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cfg_set_freq(struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_codec_config_freq freq); + +/** + * @brief Convert assigned numbers frame duration to duration in microseconds. + * + * @param frame_dur The assigned numbers frame duration to convert. + * + * @retval -EINVAL if arguments are invalid. + * @retval The converted frame duration value in microseconds. + */ +int bt_audio_codec_cfg_frame_dur_to_frame_dur_us(enum bt_audio_codec_config_frame_dur frame_dur); + +/** + * @brief Convert frame duration in microseconds to assigned numbers frame duration. + * + * @param frame_dur_us The frame duration in microseconds to convert. + * + * @retval -EINVAL if arguments are invalid. + * @retval The assigned numbers frame duration (@ref bt_audio_codec_config_frame_dur). + */ +int bt_audio_codec_cfg_frame_dur_us_to_frame_dur(uint32_t frame_dur_us); + /** @brief Extract frame duration from BT codec config * * @param codec_cfg The codec configuration to extract data from. * - * @return Frame duration in microseconds if value is found else a negative value - * of type @ref bt_audio_codec_cfg_parse_err. + * @retval A @ref bt_audio_codec_config_frame_dur value + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size or value + */ +int bt_audio_codec_cfg_get_frame_dur(const struct bt_audio_codec_cfg *codec_cfg); + +/** + * @brief Set the frame duration of a codec configuration. + * + * @param codec_cfg The codec configuration to set data for. + * @param frame_dur The assigned numbers frame duration to set. + * + * @retval The data_len of @p codec_cfg on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory */ -int bt_audio_codec_cfg_get_frame_duration_us(const struct bt_audio_codec_cfg *codec_cfg); +int bt_audio_codec_cfg_set_frame_dur(struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_codec_config_frame_dur frame_dur); /** @brief Extract channel allocation from BT codec config * @@ -613,11 +690,26 @@ int bt_audio_codec_cfg_get_frame_duration_us(const struct bt_audio_codec_cfg *co * @param codec_cfg The codec configuration to extract data from. * @param chan_allocation Pointer to the variable to store the extracted value in. * - * @return BT_AUDIO_CODEC_PARSE_SUCCESS if value is found and stored in the pointer provided - * else a negative value of type @ref bt_audio_codec_cfg_parse_err. + * @retval 0 if value is found and stored in the pointer provided + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size or value + */ +int bt_audio_codec_cfg_get_chan_allocation(const struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_location *chan_allocation); + +/** + * @brief Set the channel allocation of a codec configuration. + * + * @param codec_cfg The codec configuration to set data for. + * @param chan_allocation The channel allocation to set. + * + * @retval The data_len of @p codec_cfg on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory */ -int bt_audio_codec_cfg_get_chan_allocation_val(const struct bt_audio_codec_cfg *codec_cfg, - enum bt_audio_location *chan_allocation); +int bt_audio_codec_cfg_set_chan_allocation(struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_location chan_allocation); /** @brief Extract frame size in octets from BT codec config * @@ -632,11 +724,26 @@ int bt_audio_codec_cfg_get_chan_allocation_val(const struct bt_audio_codec_cfg * * * @param codec_cfg The codec configuration to extract data from. * - * @return Frame length in octets if value is found else a negative value - * of type @ref bt_audio_codec_cfg_parse_err. + * @retval Frame length in octets + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size or value */ int bt_audio_codec_cfg_get_octets_per_frame(const struct bt_audio_codec_cfg *codec_cfg); +/** + * @brief Set the octets per codec frame of a codec configuration. + * + * @param codec_cfg The codec configuration to set data for. + * @param octets_per_frame The octets per codec frame to set. + * + * @retval The data_len of @p codec_cfg on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cfg_set_octets_per_frame(struct bt_audio_codec_cfg *codec_cfg, + uint16_t octets_per_frame); + /** @brief Extract number of audio frame blockss in each SDU from BT codec config * * The overall SDU size will be octets_per_frame * frame_blocks_per_sdu * number-of-channels. @@ -652,33 +759,875 @@ int bt_audio_codec_cfg_get_octets_per_frame(const struct bt_audio_codec_cfg *cod * if the type is not found. In this case the function will only fail if a NULL * pointer is provided. * - * @return The count of codec frames in each SDU if value is found else a negative value - * of type @ref bt_audio_codec_cfg_parse_err - unless when \p fallback_to_default is true - * then the value 1 is returned if frames per sdu is not found. + * @retval The count of codec frames in each SDU if value is found else of @p fallback_to_default + * is true then the value 1 is returned if frames per sdu is not found. + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size or value */ int bt_audio_codec_cfg_get_frame_blocks_per_sdu(const struct bt_audio_codec_cfg *codec_cfg, bool fallback_to_default); -/** @brief Lookup a specific value based on type +/** + * @brief Set the frame blocks per SDU of a codec configuration. * - * Depending on context bt_audio_codec_cfg will be either codec capabilities, codec configuration - * or meta data. + * @param codec_cfg The codec configuration to set data for. + * @param frame_blocks The frame blocks per SDU to set. * - * Typically types used are: - * @ref bt_audio_codec_capability_type - * @ref bt_audio_codec_config_type - * @ref bt_audio_metadata_type + * @retval The data_len of @p codec_cfg on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cfg_set_frame_blocks_per_sdu(struct bt_audio_codec_cfg *codec_cfg, + uint8_t frame_blocks); + +/** @brief Lookup a specific codec configuration value * * @param[in] codec_cfg The codec data to search in. * @param[in] type The type id to look for * @param[out] data Pointer to the data-pointer to update when item is found * @return Length of found @p data or 0 if not found */ -uint8_t bt_audio_codec_cfg_get_val(const struct bt_audio_codec_cfg *codec_cfg, uint8_t type, - const uint8_t **data); +uint8_t bt_audio_codec_cfg_get_val(const struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_codec_config_type type, const uint8_t **data); + +/** + * @brief Set or add a specific codec configuration value + * + * @param codec_cfg The codec data to set the value in. + * @param type The type id to set + * @param data Pointer to the data-pointer to set + * @param data_len Length of @p data + * + * @retval The data_len of @p codec_cfg on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cfg_set_val(struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_codec_config_type type, const uint8_t *data, + size_t data_len); + +/** @brief Lookup a specific metadata value based on type + * + * + * @param[in] codec_cfg The codec data to search in. + * @param[in] type The type id to look for + * @param[out] data Pointer to the data-pointer to update when item is found + * + * @retval Length of found @p data (may be 0) + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + */ +int bt_audio_codec_cfg_meta_get_val(const struct bt_audio_codec_cfg *codec_cfg, uint8_t type, + const uint8_t **data); + +/** + * @brief Set or add a specific codec configuration metadata value. + * + * @param codec_cfg The codec configuration to set the value in. + * @param type The type id to set. + * @param data Pointer to the data-pointer to set. + * @param data_len Length of @p data. + * + * @retval The meta_len of @p codec_cfg on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cfg_meta_set_val(struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_metadata_type type, const uint8_t *data, + size_t data_len); + +/** @brief Extract preferred contexts + * + * See @ref BT_AUDIO_METADATA_TYPE_PREF_CONTEXT for more information about this value. + * + * @param codec_cfg The codec data to search in. + * + * @retval The preferred context type if positive or 0 + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size + */ +int bt_audio_codec_cfg_meta_get_pref_context(const struct bt_audio_codec_cfg *codec_cfg); + +/** + * @brief Set the preferred context of a codec configuration metadata. + * + * @param codec_cfg The codec configuration to set data for. + * @param ctx The preferred context to set. + * + * @retval The data_len of @p codec_cfg on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cfg_meta_set_pref_context(struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_context ctx); + +/** @brief Extract stream contexts + * + * See @ref BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT for more information about this value. + * + * @param codec_cfg The codec data to search in. + * + * @retval The stream context type if positive or 0 + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size + */ +int bt_audio_codec_cfg_meta_get_stream_context(const struct bt_audio_codec_cfg *codec_cfg); + +/** + * @brief Set the stream context of a codec configuration metadata. + * + * @param codec_cfg The codec configuration to set data for. + * @param ctx The stream context to set. + * + * @retval The data_len of @p codec_cfg on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cfg_meta_set_stream_context(struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_context ctx); + +/** @brief Extract program info + * + * See @ref BT_AUDIO_METADATA_TYPE_PROGRAM_INFO for more information about this value. + * + * @param[in] codec_cfg The codec data to search in. + * @param[out] program_info Pointer to the UTF-8 formatted program info. + * + * @retval The length of the @p program_info (may be 0) + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + */ +int bt_audio_codec_cfg_meta_get_program_info(const struct bt_audio_codec_cfg *codec_cfg, + const uint8_t **program_info); + +/** + * @brief Set the program info of a codec configuration metadata. + * + * @param codec_cfg The codec configuration to set data for. + * @param program_info The program info to set. + * @param program_info_len The length of @p program_info. + * + * @retval The data_len of @p codec_cfg on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cfg_meta_set_program_info(struct bt_audio_codec_cfg *codec_cfg, + const uint8_t *program_info, size_t program_info_len); + +/** @brief Extract stream language + * + * See @ref BT_AUDIO_METADATA_TYPE_STREAM_LANG for more information about this value. + * + * @param codec_cfg The codec data to search in. + * + * @retval The stream language if positive or 0 + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size + */ +int bt_audio_codec_cfg_meta_get_stream_lang(const struct bt_audio_codec_cfg *codec_cfg); + +/** + * @brief Set the stream language of a codec configuration metadata. + * + * @param codec_cfg The codec configuration to set data for. + * @param stream_lang The 24-bit stream language to set. + * + * @retval The data_len of @p codec_cfg on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cfg_meta_set_stream_lang(struct bt_audio_codec_cfg *codec_cfg, + uint32_t stream_lang); + +/** @brief Extract CCID list + * + * See @ref BT_AUDIO_METADATA_TYPE_CCID_LIST for more information about this value. + * + * @param[in] codec_cfg The codec data to search in. + * @param[out] ccid_list Pointer to the array containing 8-bit CCIDs. + * + * @retval The length of the @p ccid_list (may be 0) + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + */ +int bt_audio_codec_cfg_meta_get_ccid_list(const struct bt_audio_codec_cfg *codec_cfg, + const uint8_t **ccid_list); +/** + * @brief Set the CCID list of a codec configuration metadata. + * + * @param codec_cfg The codec configuration to set data for. + * @param ccid_list The program info to set. + * @param ccid_list_len The length of @p ccid_list. + * + * @retval The data_len of @p codec_cfg on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cfg_meta_set_ccid_list(struct bt_audio_codec_cfg *codec_cfg, + const uint8_t *ccid_list, size_t ccid_list_len); + +/** @brief Extract parental rating + * + * See @ref BT_AUDIO_METADATA_TYPE_PARENTAL_RATING for more information about this value. + * + * @param codec_cfg The codec data to search in. + * + * @retval The parental rating if positive or 0 + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size + */ +int bt_audio_codec_cfg_meta_get_parental_rating(const struct bt_audio_codec_cfg *codec_cfg); + +/** + * @brief Set the parental rating of a codec configuration metadata. + * + * @param codec_cfg The codec configuration to set data for. + * @param parental_rating The parental rating to set. + * + * @retval The data_len of @p codec_cfg on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cfg_meta_set_parental_rating(struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_parental_rating parental_rating); + +/** @brief Extract program info URI + * + * See @ref BT_AUDIO_METADATA_TYPE_PROGRAM_INFO_URI for more information about this value. + * + * @param[in] codec_cfg The codec data to search in. + * @param[out] program_info_uri Pointer to the UTF-8 formatted program info URI. + * + * @retval The length of the @p ccid_list (may be 0) + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + */ +int bt_audio_codec_cfg_meta_get_program_info_uri(const struct bt_audio_codec_cfg *codec_cfg, + const uint8_t **program_info_uri); + +/** + * @brief Set the program info URI of a codec configuration metadata. + * + * @param codec_cfg The codec configuration to set data for. + * @param program_info_uri The program info URI to set. + * @param program_info_uri_len The length of @p program_info_uri. + * + * @retval The data_len of @p codec_cfg on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cfg_meta_set_program_info_uri(struct bt_audio_codec_cfg *codec_cfg, + const uint8_t *program_info_uri, + size_t program_info_uri_len); + +/** @brief Extract audio active state + * + * See @ref BT_AUDIO_METADATA_TYPE_AUDIO_STATE for more information about this value. + * + * @param codec_cfg The codec data to search in. + * + * @retval The preferred context type if positive or 0 + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size + */ +int bt_audio_codec_cfg_meta_get_audio_active_state(const struct bt_audio_codec_cfg *codec_cfg); + +/** + * @brief Set the audio active state of a codec configuration metadata. + * + * @param codec_cfg The codec configuration to set data for. + * @param state The audio active state to set. + * + * @retval The data_len of @p codec_cfg on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cfg_meta_set_audio_active_state(struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_active_state state); + +/** @brief Extract broadcast audio immediate rendering flag + * + * See @ref BT_AUDIO_METADATA_TYPE_BROADCAST_IMMEDIATE for more information about this value. + * + * @param codec_cfg The codec data to search in. + * + * @retval 0 if the flag was found + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not the flag was not found + */ +int bt_audio_codec_cfg_meta_get_bcast_audio_immediate_rend_flag( + const struct bt_audio_codec_cfg *codec_cfg); + +/** + * @brief Set the broadcast audio immediate rendering flag of a codec configuration metadata. + * + * @param codec_cfg The codec configuration to set data for. + * + * @retval The data_len of @p codec_cfg on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cfg_meta_set_bcast_audio_immediate_rend_flag( + struct bt_audio_codec_cfg *codec_cfg); + +/** @brief Extract extended metadata + * + * See @ref BT_AUDIO_METADATA_TYPE_EXTENDED for more information about this value. + * + * @param[in] codec_cfg The codec data to search in. + * @param[out] extended_meta Pointer to the extended metadata. + * + * @retval The length of the @p ccid_list (may be 0) + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + */ +int bt_audio_codec_cfg_meta_get_extended(const struct bt_audio_codec_cfg *codec_cfg, + const uint8_t **extended_meta); + +/** + * @brief Set the extended metadata of a codec configuration metadata. + * + * @param codec_cfg The codec configuration to set data for. + * @param extended_meta The extended metadata to set. + * @param extended_meta_len The length of @p extended_meta. + * + * @retval The data_len of @p codec_cfg on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cfg_meta_set_extended(struct bt_audio_codec_cfg *codec_cfg, + const uint8_t *extended_meta, size_t extended_meta_len); + +/** @brief Extract vendor specific metadata + * + * See @ref BT_AUDIO_METADATA_TYPE_VENDOR for more information about this value. + * + * @param[in] codec_cfg The codec data to search in. + * @param[out] vendor_meta Pointer to the vendor specific metadata. + * + * @retval The length of the @p ccid_list (may be 0) + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + */ +int bt_audio_codec_cfg_meta_get_vendor(const struct bt_audio_codec_cfg *codec_cfg, + const uint8_t **vendor_meta); + +/** + * @brief Set the vendor specific metadata of a codec configuration metadata. + * + * @param codec_cfg The codec configuration to set data for. + * @param vendor_meta The vendor specific metadata to set. + * @param vendor_meta_len The length of @p vendor_meta. + * + * @retval The data_len of @p codec_cfg on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cfg_meta_set_vendor(struct bt_audio_codec_cfg *codec_cfg, + const uint8_t *vendor_meta, size_t vendor_meta_len); /** @} */ /* End of bt_audio_codec_cfg */ +/** + * @brief Audio codec capabilities APIs + * @defgroup bt_audio_codec_cap Codec capability parsing APIs + * + * Functions to parse codec capability data when formatted as LTV wrapped into @ref + * bt_audio_codec_cap. + * + * @{ + */ + +/** + * @brief Lookup a specific value based on type + * + * @param[in] codec_cap The codec data to search in. + * @param[in] type The type id to look for + * @param[out] data Pointer to the data-pointer to update when item is found + * + * @return Length of found @p data or 0 if not found + */ +uint8_t bt_audio_codec_cap_get_val(const struct bt_audio_codec_cap *codec_cap, + enum bt_audio_codec_capability_type type, const uint8_t **data); + +/** + * @brief Set or add a specific codec capability value + * + * @param codec_cap The codec data to set the value in. + * @param type The type id to set + * @param data Pointer to the data-pointer to set + * @param data_len Length of @p data + * + * @retval The data_len of @p codec_cap on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cap_set_val(struct bt_audio_codec_cap *codec_cap, + enum bt_audio_codec_capability_type type, const uint8_t *data, + size_t data_len); + +/** + * @brief Extract the frequency from a codec capability. + * + * @param codec_cap The codec capabilities to extract data from. + * + * @retval Bitfield of supported frequencies (@ref bt_audio_codec_cap_freq) if 0 or positive + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size or value + */ +int bt_audio_codec_cap_get_freq(const struct bt_audio_codec_cap *codec_cap); + +/** + * @brief Set the supported frequencies of a codec capability. + * + * @param codec_cap The codec capabilities to set data for. + * @param freq The supported frequencies to set. + * + * @retval The data_len of @p codec_cap on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cap_set_freq(struct bt_audio_codec_cap *codec_cap, + enum bt_audio_codec_cap_freq freq); + +/** + * @brief Extract the frequency from a codec capability. + * + * @param codec_cap The codec capabilities to extract data from. + * + * @retval Bitfield of supported frame durations if 0 or positive + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size or value + */ +int bt_audio_codec_cap_get_frame_dur(const struct bt_audio_codec_cap *codec_cap); + +/** + * @brief Set the frame duration of a codec capability. + * + * @param codec_cap The codec capabilities to set data for. + * @param frame_dur The frame duration to set. + * + * @retval The data_len of @p codec_cap on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cap_set_frame_dur(struct bt_audio_codec_cap *codec_cap, + enum bt_audio_codec_cap_frame_dur frame_dur); + +/** + * @brief Extract the frequency from a codec capability. + * + * @param codec_cap The codec capabilities to extract data from. + * + * @retval Bitfield of supported channel counts if 0 or positive + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size or value + */ +int bt_audio_codec_cap_get_supported_audio_chan_counts(const struct bt_audio_codec_cap *codec_cap); + +/** + * @brief Set the channel count of a codec capability. + * + * @param codec_cap The codec capabilities to set data for. + * @param chan_count The channel count frequency to set. + * + * @retval The data_len of @p codec_cap on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cap_set_supported_audio_chan_counts( + struct bt_audio_codec_cap *codec_cap, enum bt_audio_codec_cap_chan_count chan_count); + +/** + * @brief Extract the supported octets per codec frame from a codec capability. + * + * @param[in] codec_cap The codec capabilities to extract data from. + * @param[out] codec_frame Struct to place the resulting values in + * + * @retval 0 on success + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size or value + */ +int bt_audio_codec_cap_get_octets_per_frame( + const struct bt_audio_codec_cap *codec_cap, + struct bt_audio_codec_octets_per_codec_frame *codec_frame); + +/** + * @brief Set the octets per codec frame of a codec capability. + * + * @param codec_cap The codec capabilities to set data for. + * @param codec_frame The octets per codec frame to set. + * + * @retval The data_len of @p codec_cap on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cap_set_octets_per_frame( + struct bt_audio_codec_cap *codec_cap, + const struct bt_audio_codec_octets_per_codec_frame *codec_frame); + +/** + * @brief Extract the maximum codec frames per SDU from a codec capability. + * + * @param codec_cap The codec capabilities to extract data from. + * + * @retval Maximum number of codec frames per SDU supported + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size or value + */ +int bt_audio_codec_cap_get_max_codec_frames_per_sdu(const struct bt_audio_codec_cap *codec_cap); + +/** + * @brief Set the maximum codec frames per SDU of a codec capability. + * + * @param codec_cap The codec capabilities to set data for. + * @param codec_frames_per_sdu The maximum codec frames per SDU to set. + * + * @retval The data_len of @p codec_cap on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cap_set_max_codec_frames_per_sdu(struct bt_audio_codec_cap *codec_cap, + uint8_t codec_frames_per_sdu); + +/** @brief Lookup a specific metadata value based on type + * + * @param[in] codec_cap The codec data to search in. + * @param[in] type The type id to look for + * @param[out] data Pointer to the data-pointer to update when item is found + * + * @retval Length of found @p data (may be 0) + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + */ +int bt_audio_codec_cap_meta_get_val(const struct bt_audio_codec_cap *codec_cap, uint8_t type, + const uint8_t **data); + +/** + * @brief Set or add a specific codec capability metadata value. + * + * @param codec_cap The codec capability to set the value in. + * @param type The type id to set. + * @param data Pointer to the data-pointer to set. + * @param data_len Length of @p data. + * + * @retval The meta_len of @p codec_cap on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cap_meta_set_val(struct bt_audio_codec_cap *codec_cap, + enum bt_audio_metadata_type type, const uint8_t *data, + size_t data_len); + +/** @brief Extract preferred contexts + * + * See @ref BT_AUDIO_METADATA_TYPE_PREF_CONTEXT for more information about this value. + * + * @param codec_cap The codec data to search in. + * + * @retval The preferred context type if positive or 0 + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size + */ +int bt_audio_codec_cap_meta_get_pref_context(const struct bt_audio_codec_cap *codec_cap); + +/** + * @brief Set the preferred context of a codec capability metadata. + * + * @param codec_cap The codec capability to set data for. + * @param ctx The preferred context to set. + * + * @retval The data_len of @p codec_cap on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cap_meta_set_pref_context(struct bt_audio_codec_cap *codec_cap, + enum bt_audio_context ctx); + +/** @brief Extract stream contexts + * + * See @ref BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT for more information about this value. + * + * @param codec_cap The codec data to search in. + * + * @retval The stream context type if positive or 0 + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size + */ +int bt_audio_codec_cap_meta_get_stream_context(const struct bt_audio_codec_cap *codec_cap); + +/** + * @brief Set the stream context of a codec capability metadata. + * + * @param codec_cap The codec capability to set data for. + * @param ctx The stream context to set. + * + * @retval The data_len of @p codec_cap on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cap_meta_set_stream_context(struct bt_audio_codec_cap *codec_cap, + enum bt_audio_context ctx); + +/** @brief Extract program info + * + * See @ref BT_AUDIO_METADATA_TYPE_PROGRAM_INFO for more information about this value. + * + * @param[in] codec_cap The codec data to search in. + * @param[out] program_info Pointer to the UTF-8 formatted program info. + * + * @retval The length of the @p program_info (may be 0) + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + */ +int bt_audio_codec_cap_meta_get_program_info(const struct bt_audio_codec_cap *codec_cap, + const uint8_t **program_info); + +/** + * @brief Set the program info of a codec capability metadata. + * + * @param codec_cap The codec capability to set data for. + * @param program_info The program info to set. + * @param program_info_len The length of @p program_info. + * + * @retval The data_len of @p codec_cap on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cap_meta_set_program_info(struct bt_audio_codec_cap *codec_cap, + const uint8_t *program_info, size_t program_info_len); + +/** @brief Extract stream language + * + * See @ref BT_AUDIO_METADATA_TYPE_STREAM_LANG for more information about this value. + * + * @param codec_cap The codec data to search in. + * + * @retval The stream language if positive or 0 + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size + */ +int bt_audio_codec_cap_meta_get_stream_lang(const struct bt_audio_codec_cap *codec_cap); + +/** + * @brief Set the stream language of a codec capability metadata. + * + * @param codec_cap The codec capability to set data for. + * @param stream_lang The 24-bit stream language to set. + * + * @retval The data_len of @p codec_cap on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cap_meta_set_stream_lang(struct bt_audio_codec_cap *codec_cap, + uint32_t stream_lang); + +/** @brief Extract CCID list + * + * See @ref BT_AUDIO_METADATA_TYPE_CCID_LIST for more information about this value. + * + * @param[in] codec_cap The codec data to search in. + * @param[out] ccid_list Pointer to the array containing 8-bit CCIDs. + * + * @retval The length of the @p ccid_list (may be 0) + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + */ +int bt_audio_codec_cap_meta_get_ccid_list(const struct bt_audio_codec_cap *codec_cap, + const uint8_t **ccid_list); + +/** + * @brief Set the CCID list of a codec capability metadata. + * + * @param codec_cap The codec capability to set data for. + * @param ccid_list The program info to set. + * @param ccid_list_len The length of @p ccid_list. + * + * @retval The data_len of @p codec_cap on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cap_meta_set_ccid_list(struct bt_audio_codec_cap *codec_cap, + const uint8_t *ccid_list, size_t ccid_list_len); + +/** @brief Extract parental rating + * + * See @ref BT_AUDIO_METADATA_TYPE_PARENTAL_RATING for more information about this value. + * + * @param codec_cap The codec data to search in. + * + * @retval The parental rating if positive or 0 + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size + */ +int bt_audio_codec_cap_meta_get_parental_rating(const struct bt_audio_codec_cap *codec_cap); + +/** + * @brief Set the parental rating of a codec capability metadata. + * + * @param codec_cap The codec capability to set data for. + * @param parental_rating The parental rating to set. + * + * @retval The data_len of @p codec_cap on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cap_meta_set_parental_rating(struct bt_audio_codec_cap *codec_cap, + enum bt_audio_parental_rating parental_rating); + +/** @brief Extract program info URI + * + * See @ref BT_AUDIO_METADATA_TYPE_PROGRAM_INFO_URI for more information about this value. + * + * @param[in] codec_cap The codec data to search in. + * @param[out] program_info_uri Pointer to the UTF-8 formatted program info URI. + * + * @retval The length of the @p ccid_list (may be 0) + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + */ +int bt_audio_codec_cap_meta_get_program_info_uri(const struct bt_audio_codec_cap *codec_cap, + const uint8_t **program_info_uri); + +/** + * @brief Set the program info URI of a codec capability metadata. + * + * @param codec_cap The codec capability to set data for. + * @param program_info_uri The program info URI to set. + * @param program_info_uri_len The length of @p program_info_uri. + * + * @retval The data_len of @p codec_cap on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cap_meta_set_program_info_uri(struct bt_audio_codec_cap *codec_cap, + const uint8_t *program_info_uri, + size_t program_info_uri_len); + +/** @brief Extract audio active state + * + * See @ref BT_AUDIO_METADATA_TYPE_AUDIO_STATE for more information about this value. + * + * @param codec_cap The codec data to search in. + * + * @retval The preferred context type if positive or 0 + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size + */ +int bt_audio_codec_cap_meta_get_audio_active_state(const struct bt_audio_codec_cap *codec_cap); + +/** + * @brief Set the audio active state of a codec capability metadata. + * + * @param codec_cap The codec capability to set data for. + * @param state The audio active state to set. + * + * @retval The data_len of @p codec_cap on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cap_meta_set_audio_active_state(struct bt_audio_codec_cap *codec_cap, + enum bt_audio_active_state state); + +/** @brief Extract broadcast audio immediate rendering flag + * + * See @ref BT_AUDIO_METADATA_TYPE_BROADCAST_IMMEDIATE for more information about this value. + * + * @param codec_cap The codec data to search in. + * + * @retval 0 if the flag was found + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not the flag was not found + */ +int bt_audio_codec_cap_meta_get_bcast_audio_immediate_rend_flag( + const struct bt_audio_codec_cap *codec_cap); + +/** + * @brief Set the broadcast audio immediate rendering flag of a codec capability metadata. + * + * @param codec_cap The codec capability to set data for. + * + * @retval The data_len of @p codec_cap on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cap_meta_set_bcast_audio_immediate_rend_flag( + struct bt_audio_codec_cap *codec_cap); + +/** @brief Extract extended metadata + * + * See @ref BT_AUDIO_METADATA_TYPE_EXTENDED for more information about this value. + * + * @param[in] codec_cap The codec data to search in. + * @param[out] extended_meta Pointer to the extended metadata. + * + * @retval The length of the @p ccid_list (may be 0) + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + */ +int bt_audio_codec_cap_meta_get_extended(const struct bt_audio_codec_cap *codec_cap, + const uint8_t **extended_meta); + +/** + * @brief Set the extended metadata of a codec capability metadata. + * + * @param codec_cap The codec capability to set data for. + * @param extended_meta The extended metadata to set. + * @param extended_meta_len The length of @p extended_meta. + * + * @retval The data_len of @p codec_cap on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cap_meta_set_extended(struct bt_audio_codec_cap *codec_cap, + const uint8_t *extended_meta, size_t extended_meta_len); + +/** @brief Extract vendor specific metadata + * + * See @ref BT_AUDIO_METADATA_TYPE_VENDOR for more information about this value. + * + * @param[in] codec_cap The codec data to search in. + * @param[out] vendor_meta Pointer to the vendor specific metadata. + * + * @retval The length of the @p ccid_list (may be 0) + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + */ +int bt_audio_codec_cap_meta_get_vendor(const struct bt_audio_codec_cap *codec_cap, + const uint8_t **vendor_meta); + +/** + * @brief Set the vendor specific metadata of a codec capability metadata. + * + * @param codec_cap The codec capability to set data for. + * @param vendor_meta The vendor specific metadata to set. + * @param vendor_meta_len The length of @p vendor_meta. + * + * @retval The data_len of @p codec_cap on success + * @retval -EINVAL if arguments are invalid + * @retval -ENOMEM if the new value could not set or added due to memory + */ +int bt_audio_codec_cap_meta_set_vendor(struct bt_audio_codec_cap *codec_cap, + const uint8_t *vendor_meta, size_t vendor_meta_len); + +/** @} */ /* End of bt_audio_codec_cap */ + #ifdef __cplusplus } #endif diff --git a/include/zephyr/bluetooth/audio/bap.h b/include/zephyr/bluetooth/audio/bap.h index 269e37d5aba..77c63ba598b 100644 --- a/include/zephyr/bluetooth/audio/bap.h +++ b/include/zephyr/bluetooth/audio/bap.h @@ -20,6 +20,12 @@ #include #include + +#ifdef __cplusplus +extern "C" { +#endif + + #if defined(CONFIG_BT_BAP_SCAN_DELEGATOR) #define BT_BAP_SCAN_DELEGATOR_MAX_METADATA_LEN CONFIG_BT_BAP_SCAN_DELEGATOR_MAX_METADATA_LEN #define BT_BAP_SCAN_DELEGATOR_MAX_SUBGROUPS CONFIG_BT_BAP_SCAN_DELEGATOR_MAX_SUBGROUPS @@ -400,7 +406,9 @@ struct bt_bap_scan_delegator_cb { * requested for the sync. * @param[in] bis_sync_req Array of bitfields of which BIS indexes * that is requested to sync for each subgroup - * by the Broadcast Assistant. + * by the Broadcast Assistant. A value of 0 + * indicates a request to terminate the BIG + * sync. * * @return 0 in case of accept, or other value to reject. */ @@ -478,6 +486,10 @@ struct bt_bap_stream { /** Stream user data */ void *user_data; +#if defined(CONFIG_BT_BAP_DEBUG_STREAM_SEQ_NUM) + uint16_t _prev_seq_num; +#endif /* CONFIG_BT_BAP_DEBUG_STREAM_SEQ_NUM */ + /* Internally used list node */ sys_snode_t _node; }; @@ -1043,6 +1055,35 @@ struct bt_bap_unicast_group_param { * @note This is a recommendation to the controller, which the controller may ignore. */ uint8_t packing; + +#if defined(CONFIG_BT_ISO_TEST_PARAMS) + /** @brief Central to Peripheral flush timeout + * + * The flush timeout in multiples of ISO_Interval for each payload sent + * from the Central to Peripheral. + * + * Value range from @ref BT_ISO_FT_MIN to @ref BT_ISO_FT_MAX + */ + uint8_t c_to_p_ft; + + /** @brief Peripheral to Central flush timeout + * + * The flush timeout in multiples of ISO_Interval for each payload sent + * from the Peripheral to Central. + * + * Value range from @ref BT_ISO_FT_MIN to @ref BT_ISO_FT_MAX. + */ + uint8_t p_to_c_ft; + + /** @brief ISO interval + * + * Time between consecutive CIS anchor points. + * + * Value range from @ref BT_ISO_ISO_INTERVAL_MIN to + * @ref BT_ISO_ISO_INTERVAL_MAX. + */ + uint16_t iso_interval; +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ }; /** @@ -1400,7 +1441,7 @@ struct bt_bap_broadcast_source_subgroup_param { }; /** Broadcast Source create parameters */ -struct bt_bap_broadcast_source_create_param { +struct bt_bap_broadcast_source_param { /** The number of parameters in @p subgroup_params */ size_t params_count; @@ -1433,6 +1474,34 @@ struct bt_bap_broadcast_source_create_param { * [42 72 6F 61 64 63 61 73 74 20 43 6F 64 65 00 00] */ uint8_t broadcast_code[BT_AUDIO_BROADCAST_CODE_SIZE]; + +#if defined(CONFIG_BT_ISO_TEST_PARAMS) + /** @brief Immediate Repetition Count + * + * The number of times the scheduled payloads are transmitted in a + * given event. + * + * Value range from @ref BT_ISO_MIN_IRC to @ref BT_ISO_MAX_IRC. + */ + uint8_t irc; + + /** @brief Pre-transmission offset + * + * Offset used for pre-transmissions. + * + * Value range from @ref BT_ISO_MIN_PTO to @ref BT_ISO_MAX_PTO. + */ + uint8_t pto; + + /** @brief ISO interval + * + * Time between consecutive BIS anchor points. + * + * Value range from @ref BT_ISO_ISO_INTERVAL_MIN to + * @ref BT_ISO_ISO_INTERVAL_MAX. + */ + uint16_t iso_interval; +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ }; /** @@ -1451,7 +1520,7 @@ struct bt_bap_broadcast_source_create_param { * * @return Zero on success or (negative) error code otherwise. */ -int bt_bap_broadcast_source_create(struct bt_bap_broadcast_source_create_param *param, +int bt_bap_broadcast_source_create(struct bt_bap_broadcast_source_param *param, struct bt_bap_broadcast_source **source); /** @@ -1460,15 +1529,21 @@ int bt_bap_broadcast_source_create(struct bt_bap_broadcast_source_create_param * * Reconfigure an audio broadcast source with a new codec and codec quality of * service parameters. This can only be done when the source is stopped. * + * Since this may modify the Broadcast Audio Source Endpoint (BASE), + * bt_bap_broadcast_source_get_base() should be called after this to get the new BASE information. + * + * If the @p param.params_count is smaller than the number of subgroups that have been created in + * the Broadcast Source, only the first @p param.params_count subgroups are updated. If a stream + * exist in a subgroup not part of @p param, then that stream is left as is (i.e. it is not removed; + * the only way to remove a stream from a Broadcast Source is to recreate the Broadcast Source). + * * @param source Pointer to the broadcast source - * @param codec_cfg Codec configuration. - * @param qos Quality of Service configuration + * @param param Pointer to parameters used to reconfigure the broadcast source. * * @return Zero on success or (negative) error code otherwise. */ int bt_bap_broadcast_source_reconfig(struct bt_bap_broadcast_source *source, - struct bt_audio_codec_cfg *codec_cfg, - struct bt_audio_codec_qos *qos); + struct bt_bap_broadcast_source_param *param); /** * @brief Modify the metadata of an audio broadcast source. @@ -1536,7 +1611,7 @@ int bt_bap_broadcast_source_delete(struct bt_bap_broadcast_source *source); * * @return Zero on success or (negative) error code otherwise. */ -int bt_bap_broadcast_source_get_id(const struct bt_bap_broadcast_source *source, +int bt_bap_broadcast_source_get_id(struct bt_bap_broadcast_source *source, uint32_t *const broadcast_id); /** @@ -2073,4 +2148,8 @@ int bt_bap_broadcast_assistant_read_recv_state(struct bt_conn *conn, /** @} */ /* end of bt_bap */ +#ifdef __cplusplus +} +#endif + #endif /* ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_BAP_ */ diff --git a/include/zephyr/bluetooth/audio/bap_lc3_preset.h b/include/zephyr/bluetooth/audio/bap_lc3_preset.h index c8b82054e01..952451d4b16 100644 --- a/include/zephyr/bluetooth/audio/bap_lc3_preset.h +++ b/include/zephyr/bluetooth/audio/bap_lc3_preset.h @@ -31,7 +31,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 8_1_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_8_1_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_8_1(_loc, _stream_context), \ @@ -41,7 +41,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 8_2_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_8_2_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_8_2(_loc, _stream_context), \ @@ -51,7 +51,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 16_1_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_16_1_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_16_1(_loc, _stream_context), \ @@ -63,7 +63,7 @@ struct bt_bap_lc3_preset { * Mandatory to support as both unicast client and server * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_16_2_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_16_2(_loc, _stream_context), \ @@ -73,7 +73,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 24_1_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_24_1_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_24_1(_loc, _stream_context), \ @@ -85,7 +85,7 @@ struct bt_bap_lc3_preset { * Mandatory to support as unicast server * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_24_2_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_24_2(_loc, _stream_context), \ @@ -95,7 +95,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 32_1_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_32_1_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_32_1(_loc, _stream_context), \ @@ -105,7 +105,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 32_2_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_32_2_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_32_2(_loc, _stream_context), \ @@ -115,7 +115,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 441_1_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_441_1_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_441_1(_loc, _stream_context), \ @@ -126,7 +126,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 441_2_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_441_2_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_441_2(_loc, _stream_context), \ @@ -137,7 +137,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 48_1_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_48_1_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_1(_loc, _stream_context), \ @@ -147,7 +147,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 48_2_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_48_2_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_2(_loc, _stream_context), \ @@ -157,7 +157,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 48_3_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_48_3_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_3(_loc, _stream_context), \ @@ -167,7 +167,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 48_4_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_48_4_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_4(_loc, _stream_context), \ @@ -177,7 +177,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 8_5_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_48_5_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_5(_loc, _stream_context), \ @@ -187,7 +187,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 48_6_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_48_6_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_6(_loc, _stream_context), \ @@ -197,7 +197,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 8_1_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ /* Following presets are for unicast high reliability audio data */ #define BT_BAP_LC3_UNICAST_PRESET_8_1_2(_loc, _stream_context) \ @@ -208,7 +208,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 8_2_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_8_2_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_8_2(_loc, _stream_context), \ @@ -218,7 +218,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 16_1_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_16_1_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_16_1(_loc, _stream_context), \ @@ -228,7 +228,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 16_2_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_16_2_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_16_2(_loc, _stream_context), \ @@ -238,7 +238,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 24_1_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_24_1_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_24_1(_loc, _stream_context), \ @@ -248,7 +248,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 24_2_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_24_2_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_24_2(_loc, _stream_context), \ @@ -258,7 +258,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 32_1_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_32_1_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_32_1(_loc, _stream_context), \ @@ -268,7 +268,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 32_2_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_32_2_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_32_2(_loc, _stream_context), \ @@ -278,7 +278,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 441_1_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_441_1_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_441_1(_loc, _stream_context), \ @@ -289,7 +289,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 441_2_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_441_2_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_441_2(_loc, _stream_context), \ @@ -300,7 +300,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 48_1_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_48_1_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_1(_loc, _stream_context), \ @@ -310,7 +310,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 48_2_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_48_2_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_2(_loc, _stream_context), \ @@ -320,7 +320,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 48_3_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_48_3_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_3(_loc, _stream_context), \ @@ -330,7 +330,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 48_4_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_48_4_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_4(_loc, _stream_context), \ @@ -340,7 +340,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 48_5_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_48_5_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_5(_loc, _stream_context), \ @@ -350,7 +350,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Unicast 48_6_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_UNICAST_PRESET_48_6_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_6(_loc, _stream_context), \ @@ -360,7 +360,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 8_1_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ /* LC3 Broadcast presets defined by table 6.4 in the BAP v1.0 specification */ #define BT_BAP_LC3_BROADCAST_PRESET_8_1_1(_loc, _stream_context) \ @@ -371,7 +371,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 8_2_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_8_2_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_8_2(_loc, _stream_context), \ @@ -381,7 +381,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 16_1_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_16_1_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_16_1(_loc, _stream_context), \ @@ -393,7 +393,7 @@ struct bt_bap_lc3_preset { * Mandatory to support as both broadcast source and sink * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_16_2_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_16_2(_loc, _stream_context), \ @@ -403,7 +403,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 24_1_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_24_1_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_24_1(_loc, _stream_context), \ @@ -415,7 +415,7 @@ struct bt_bap_lc3_preset { * Mandatory to support as broadcast sink * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_24_2_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_24_2(_loc, _stream_context), \ @@ -425,7 +425,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 32_1_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_32_1_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_32_1(_loc, _stream_context), \ @@ -435,7 +435,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 32_2_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_32_2_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_32_2(_loc, _stream_context), \ @@ -445,7 +445,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 441_1_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_441_1_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_441_1(_loc, _stream_context), \ @@ -456,7 +456,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 441_2_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_441_2_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_441_2(_loc, _stream_context), \ @@ -467,7 +467,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 48_1_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_1_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_1(_loc, _stream_context), \ @@ -477,7 +477,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 48_2_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_2_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_2(_loc, _stream_context), \ @@ -487,7 +487,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 48_3_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_3_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_3(_loc, _stream_context), \ @@ -497,7 +497,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 48_4_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_4_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_4(_loc, _stream_context), \ @@ -507,7 +507,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 48_5_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_5_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_5(_loc, _stream_context), \ @@ -517,7 +517,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 48_6_1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_6_1(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_6(_loc, _stream_context), \ @@ -527,7 +527,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 8_1_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ /* Following presets are for broadcast high reliability audio data */ #define BT_BAP_LC3_BROADCAST_PRESET_8_1_2(_loc, _stream_context) \ @@ -538,7 +538,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 8_2_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_8_2_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_8_2(_loc, _stream_context), \ @@ -548,7 +548,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 16_1_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_16_1_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_16_1(_loc, _stream_context), \ @@ -560,7 +560,7 @@ struct bt_bap_lc3_preset { * Mandatory to support as both broadcast source and sink * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_16_2_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_16_2(_loc, _stream_context), \ @@ -570,7 +570,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 24_1_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_24_1_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_24_1(_loc, _stream_context), \ @@ -582,7 +582,7 @@ struct bt_bap_lc3_preset { * Mandatory to support as broadcast sink * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_24_2_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_24_2(_loc, _stream_context), \ @@ -592,7 +592,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 32_1_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_32_1_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_32_1(_loc, _stream_context), \ @@ -602,7 +602,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 32_2_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_32_2_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_32_2(_loc, _stream_context), \ @@ -612,7 +612,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 441_1_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_441_1_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_441_1(_loc, _stream_context), \ @@ -623,7 +623,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 441_2_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_441_2_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_441_2(_loc, _stream_context), \ @@ -634,7 +634,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 48_1_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_1_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_1(_loc, _stream_context), \ @@ -644,7 +644,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 48_2_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_2_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_2(_loc, _stream_context), \ @@ -654,7 +654,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 48_3_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_3_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_3(_loc, _stream_context), \ @@ -664,7 +664,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 48_4_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_4_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_4(_loc, _stream_context), \ @@ -674,7 +674,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 48_5_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_5_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_5(_loc, _stream_context), \ @@ -684,7 +684,7 @@ struct bt_bap_lc3_preset { * @brief Helper to declare LC3 Broadcast 48_6_2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_6_2(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_6(_loc, _stream_context), \ diff --git a/include/zephyr/bluetooth/audio/cap.h b/include/zephyr/bluetooth/audio/cap.h index fd2c455588c..06da5700506 100644 --- a/include/zephyr/bluetooth/audio/cap.h +++ b/include/zephyr/bluetooth/audio/cap.h @@ -393,6 +393,34 @@ struct bt_cap_initiator_broadcast_create_param { * [42 72 6F 61 64 63 61 73 74 20 43 6F 64 65 00 00] */ uint8_t broadcast_code[BT_AUDIO_BROADCAST_CODE_SIZE]; + +#if defined(CONFIG_BT_ISO_TEST_PARAMS) + /** @brief Immediate Repetition Count + * + * The number of times the scheduled payloads are transmitted in a + * given event. + * + * Value range from @ref BT_ISO_MIN_IRC to @ref BT_ISO_MAX_IRC. + */ + uint8_t irc; + + /** @brief Pre-transmission offset + * + * Offset used for pre-transmissions. + * + * Value range from @ref BT_ISO_MIN_PTO to @ref BT_ISO_MAX_PTO. + */ + uint8_t pto; + + /** @brief ISO interval + * + * Time between consecutive BIS anchor points. + * + * Value range from @ref BT_ISO_ISO_INTERVAL_MIN to + * @ref BT_ISO_ISO_INTERVAL_MAX. + */ + uint16_t iso_interval; +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ }; /** @@ -608,6 +636,244 @@ struct bt_cap_broadcast_to_unicast_param { int bt_cap_initiator_broadcast_to_unicast(const struct bt_cap_broadcast_to_unicast_param *param, struct bt_bap_unicast_group **unicast_group); +/** + * @brief Discovers audio support on a remote device. + * + * This will discover the Common Audio Service (CAS) on the remote device, to + * verify if the remote device supports the Common Audio Profile. + * + * @note @kconfig{CONFIG_BT_CAP_COMMANDER} must be enabled for this function. If + * @kconfig{CONFIG_BT_CAP_INITIATOR} is also enabled, it does not matter if + * bt_cap_commander_unicast_discover() or bt_cap_initiator_unicast_discover() is used. + * + * @param conn Connection to a remote server. + * + * @return 0 on success or negative error value on failure. + */ +int bt_cap_commander_unicast_discover(struct bt_conn *conn); + +struct bt_cap_commander_broadcast_reception_start_member_param { + /** Coordinated or ad-hoc set member. */ + union bt_cap_set_member member; + + /** Address of the advertiser. */ + bt_addr_le_t addr; + + /** SID of the advertising set. */ + uint8_t adv_sid; + + /** + * @brief Periodic advertising interval in milliseconds. + * + * BT_BAP_PA_INTERVAL_UNKNOWN if unknown. + */ + uint16_t pa_interval; + + /** 24-bit broadcast ID */ + uint32_t broadcast_id; + + /** + * @brief Pointer to array of subgroups + * + * At least one bit in one of the subgroups bis_sync parameters shall be set. + */ + struct bt_bap_scan_delegator_subgroup *subgroups; + + /** Number of subgroups */ + size_t num_subgroups; +}; + +/** Parameters for starting broadcast reception */ +struct bt_cap_commander_broadcast_reception_start_param { + /** The type of the set. */ + enum bt_cap_set_type type; + + /** The set of devices for this procedure */ + struct bt_cap_commander_broadcast_reception_start_member_param *param; + + /** The number of parameters in @p param */ + size_t count; +}; + +/** + * @brief Starts the reception of broadcast audio on one or more remote Common Audio Profile + * Acceptors + * + * @param param The parameters to start the broadcast audio + * + * @return 0 on success or negative error value on failure. + */ +int bt_cap_commander_broadcast_reception_start( + const struct bt_cap_commander_broadcast_reception_start_param *param); + +/** Parameters for stopping broadcast reception */ +struct bt_cap_commander_broadcast_reception_stop_param { + /** The type of the set. */ + enum bt_cap_set_type type; + + /** Coordinated or ad-hoc set member. */ + union bt_cap_set_member *members; + + /** The number of members in @p members */ + size_t count; +}; + +/** + * @brief Stops the reception of broadcast audio on one or more remote Common Audio Profile + * Acceptors + * + * @param param The parameters to stop the broadcast audio + * + * @return 0 on success or negative error value on failure. + */ +int bt_cap_commander_broadcast_reception_stop( + const struct bt_cap_commander_broadcast_reception_stop_param *param); + +/** Parameters for changing absolute volume */ +struct bt_cap_commander_change_volume_param { + /** The type of the set. */ + enum bt_cap_set_type type; + + /** Coordinated or ad-hoc set member. */ + union bt_cap_set_member *members; + + /** The number of members in @p members */ + size_t count; + + /** The absolute volume to set */ + uint8_t volume; +}; + +/** + * @brief Change the volume on one or more Common Audio Profile Acceptors + * + * @param param The parameters for the volume change + * + * @return 0 on success or negative error value on failure. + */ +int bt_cap_commander_change_volume(const struct bt_cap_commander_change_volume_param *param); + +struct bt_cap_commander_change_volume_offset_member_param { + /** Coordinated or ad-hoc set member. */ + union bt_cap_set_member member; + + /** + * @brief The offset to set + * + * Value shall be between @ref BT_VOCS_MIN_OFFSET and @ref BT_VOCS_MAX_OFFSET + */ + int16_t offset; +}; + +/** Parameters for changing volume offset */ +struct bt_cap_commander_change_volume_offset_param { + /** The type of the set. */ + enum bt_cap_set_type type; + + /** The set of devices for this procedure */ + struct bt_cap_commander_change_volume_offset_member_param *param; + + /** The number of parameters in @p param */ + size_t count; +}; + +/** + * @brief Change the volume offset on one or more Common Audio Profile Acceptors + * + * @param param The parameters for the volume offset change + * + * @return 0 on success or negative error value on failure. + */ +int bt_cap_commander_change_volume_offset( + const struct bt_cap_commander_change_volume_offset_param *param); + +/** Parameters for changing volume mute state */ +struct bt_cap_commander_change_volume_mute_state_param { + /** The type of the set. */ + enum bt_cap_set_type type; + + /** Coordinated or ad-hoc set member. */ + union bt_cap_set_member *members; + + /** The number of members in @p members */ + size_t count; + + /** + * @brief The volume mute state to set + * + * true to mute, and false to unmute + */ + bool mute; +}; + +/** + * @brief Change the volume mute state on one or more Common Audio Profile Acceptors + * + * @param param The parameters for the volume mute state change + * + * @return 0 on success or negative error value on failure. + */ +int bt_cap_commander_change_volume_mute_state( + const struct bt_cap_commander_change_volume_mute_state_param *param); + +/** Parameters for changing microphone mute state */ +struct bt_cap_commander_change_microphone_mute_state_param { + /** The type of the set. */ + enum bt_cap_set_type type; + + /** Coordinated or ad-hoc set member. */ + union bt_cap_set_member *members; + + /** The number of members in @p members */ + size_t count; + + /** + * @brief The microphone mute state to set + * + * true to mute, and false to unmute + */ + bool mute; +}; + +/** + * @brief Change the microphone mute state on one or more Common Audio Profile Acceptors + * + * @param param The parameters for the microphone mute state change + * + * @return 0 on success or negative error value on failure. + */ +int bt_cap_commander_change_microphone_mute_state( + const struct bt_cap_commander_change_microphone_mute_state_param *param); + +struct bt_cap_commander_change_microphone_gain_setting_member_param { + /** Coordinated or ad-hoc set member. */ + union bt_cap_set_member member; + + /** @brief The microphone gain setting to set */ + int8_t gain; +}; + +/** Parameters for changing microphone mute state */ +struct bt_cap_commander_change_microphone_gain_setting_param { + /** The type of the set. */ + enum bt_cap_set_type type; + + /** The set of devices for this procedure */ + struct bt_cap_commander_change_microphone_gain_setting_member_param *param; + + /** The number of parameters in @p param */ + size_t count; +}; + +/** + * @brief Change the microphone gain setting on one or more Common Audio Profile Acceptors + * + * @param param The parameters for the microphone gain setting change + * + * @return 0 on success or negative error value on failure. + */ +int bt_cap_commander_change_microphone_gain_setting( + const struct bt_cap_commander_change_microphone_gain_setting_param *param); #ifdef __cplusplus } #endif diff --git a/include/zephyr/bluetooth/audio/lc3.h b/include/zephyr/bluetooth/audio/lc3.h index cec566e5983..ab42f9fdbdf 100644 --- a/include/zephyr/bluetooth/audio/lc3.h +++ b/include/zephyr/bluetooth/audio/lc3.h @@ -20,6 +20,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -28,7 +29,7 @@ extern "C" { /** * @brief LC3 codec ID */ -#define BT_AUDIO_CODEC_LC3_ID 0x06 +#define BT_HCI_CODING_FORMAT_LC3 0x06 /** * @brief Codec capability type id's @@ -66,67 +67,129 @@ enum bt_audio_codec_capability_type { BT_AUDIO_CODEC_LC3_FRAME_COUNT = 0x05, }; -/** - * @brief LC3 8 Khz frequency capability - */ -#define BT_AUDIO_CODEC_LC3_FREQ_8KHZ BIT(0) -/** - * @brief LC3 11.025 Khz frequency capability - */ -#define BT_AUDIO_CODEC_LC3_FREQ_11KHZ BIT(1) -/** - * @brief LC3 16 Khz frequency capability - */ -#define BT_AUDIO_CODEC_LC3_FREQ_16KHZ BIT(2) -/** - * @brief LC3 22.05 Khz frequency capability - */ -#define BT_AUDIO_CODEC_LC3_FREQ_22KHZ BIT(3) -/** - * @brief LC3 24 Khz frequency capability - */ -#define BT_AUDIO_CODEC_LC3_FREQ_24KHZ BIT(4) -/** - * @brief LC3 32 Khz frequency capability - */ -#define BT_AUDIO_CODEC_LC3_FREQ_32KHZ BIT(5) -/** - * @brief LC3 44.1 Khz frequency capability - */ -#define BT_AUDIO_CODEC_LC3_FREQ_44KHZ BIT(6) -/** - * @brief LC3 48 Khz frequency capability - */ -#define BT_AUDIO_CODEC_LC3_FREQ_48KHZ BIT(7) -/** - * @brief LC3 any frequency capability - */ -#define BT_AUDIO_CODEC_LC3_FREQ_ANY \ - (BT_AUDIO_CODEC_LC3_FREQ_8KHZ | BT_AUDIO_CODEC_LC3_FREQ_16KHZ | \ - BT_AUDIO_CODEC_LC3_FREQ_24KHZ | BT_AUDIO_CODEC_LC3_FREQ_32KHZ | \ - BT_AUDIO_CODEC_LC3_FREQ_44KHZ | BT_AUDIO_CODEC_LC3_FREQ_48KHZ) +/** @brief Supported frequencies bitfield */ +enum bt_audio_codec_cap_freq { + /** + * @brief LC3 8 Khz frequency capability + */ + BT_AUDIO_CODEC_LC3_FREQ_8KHZ = BIT(0), + /** + * @brief LC3 11.025 Khz frequency capability + */ + BT_AUDIO_CODEC_LC3_FREQ_11KHZ = BIT(1), + /** + * @brief LC3 16 Khz frequency capability + */ + BT_AUDIO_CODEC_LC3_FREQ_16KHZ = BIT(2), + /** + * @brief LC3 22.05 Khz frequency capability + */ + BT_AUDIO_CODEC_LC3_FREQ_22KHZ = BIT(3), + /** + * @brief LC3 24 Khz frequency capability + */ + BT_AUDIO_CODEC_LC3_FREQ_24KHZ = BIT(4), + /** + * @brief LC3 32 Khz frequency capability + */ + BT_AUDIO_CODEC_LC3_FREQ_32KHZ = BIT(5), + /** + * @brief LC3 44.1 Khz frequency capability + */ + BT_AUDIO_CODEC_LC3_FREQ_44KHZ = BIT(6), + /** + * @brief LC3 48 Khz frequency capability + */ + BT_AUDIO_CODEC_LC3_FREQ_48KHZ = BIT(7), + /** + * @brief LC3 88.2 Khz frequency capability + */ + BT_AUDIO_CODEC_LC3_FREQ_88KHZ = BIT(8), + /** + * @brief LC3 96 Khz frequency capability + */ + BT_AUDIO_CODEC_LC3_FREQ_96KHZ = BIT(9), + /** + * @brief LC3 176.4 Khz frequency capability + */ + BT_AUDIO_CODEC_LC3_FREQ_176KHZ = BIT(10), + /** + * @brief LC3 192 Khz frequency capability + */ + BT_AUDIO_CODEC_LC3_FREQ_192KHZ = BIT(11), + /** + * @brief LC3 384 Khz frequency capability + */ + BT_AUDIO_CODEC_LC3_FREQ_384KHZ = BIT(12), + /** + * @brief LC3 any frequency capability + */ + BT_AUDIO_CODEC_LC3_FREQ_ANY = + (BT_AUDIO_CODEC_LC3_FREQ_8KHZ | BT_AUDIO_CODEC_LC3_FREQ_11KHZ | + BT_AUDIO_CODEC_LC3_FREQ_16KHZ | BT_AUDIO_CODEC_LC3_FREQ_22KHZ | + BT_AUDIO_CODEC_LC3_FREQ_24KHZ | BT_AUDIO_CODEC_LC3_FREQ_32KHZ | + BT_AUDIO_CODEC_LC3_FREQ_44KHZ | BT_AUDIO_CODEC_LC3_FREQ_48KHZ | + BT_AUDIO_CODEC_LC3_FREQ_88KHZ | BT_AUDIO_CODEC_LC3_FREQ_96KHZ | + BT_AUDIO_CODEC_LC3_FREQ_176KHZ | BT_AUDIO_CODEC_LC3_FREQ_192KHZ | + BT_AUDIO_CODEC_LC3_FREQ_384KHZ), +}; -/** - * @brief LC3 7.5 msec frame duration capability - */ -#define BT_AUDIO_CODEC_LC3_DURATION_7_5 BIT(0) -/** - * @brief LC3 10 msec frame duration capability - */ -#define BT_AUDIO_CODEC_LC3_DURATION_10 BIT(1) -/** - * @brief LC3 any frame duration capability - */ -#define BT_AUDIO_CODEC_LC3_DURATION_ANY \ - (BT_AUDIO_CODEC_LC3_DURATION_7_5 | BT_AUDIO_CODEC_LC3_DURATION_10) -/** - * @brief LC3 7.5 msec preferred frame duration capability - */ -#define BT_AUDIO_CODEC_LC3_DURATION_PREFER_7_5 BIT(4) -/** - * @brief LC3 10 msec preferred frame duration capability - */ -#define BT_AUDIO_CODEC_LC3_DURATION_PREFER_10 BIT(5) +/** @brief Supported frame durations bitfield */ +enum bt_audio_codec_cap_frame_dur { + /** + * @brief LC3 7.5 msec frame duration capability + */ + BT_AUDIO_CODEC_LC3_DURATION_7_5 = BIT(0), + /** + * @brief LC3 10 msec frame duration capability + */ + BT_AUDIO_CODEC_LC3_DURATION_10 = BIT(1), + /** + * @brief LC3 any frame duration capability + */ + BT_AUDIO_CODEC_LC3_DURATION_ANY = + (BT_AUDIO_CODEC_LC3_DURATION_7_5 | BT_AUDIO_CODEC_LC3_DURATION_10), + + /** + * @brief LC3 7.5 msec preferred frame duration capability. + * + * This shall only be set if @ref BT_AUDIO_CODEC_LC3_DURATION_7_5 is also set, and if @ref + * BT_AUDIO_CODEC_LC3_DURATION_PREFER_10 is not set. + */ + BT_AUDIO_CODEC_LC3_DURATION_PREFER_7_5 = BIT(4), + /** + * @brief LC3 10 msec preferred frame duration capability + * + * This shall only be set if @ref BT_AUDIO_CODEC_LC3_DURATION_10 is also set, and if @ref + * BT_AUDIO_CODEC_LC3_DURATION_PREFER_7_5 is not set. + */ + BT_AUDIO_CODEC_LC3_DURATION_PREFER_10 = BIT(5), +}; + +enum bt_audio_codec_cap_chan_count { + /** Supporting 1 channel */ + BT_AUDIO_CODEC_CAP_CHAN_COUNT_1 = BIT(0), + /** Supporting 2 channel */ + BT_AUDIO_CODEC_CAP_CHAN_COUNT_2 = BIT(1), + /** Supporting 3 channel */ + BT_AUDIO_CODEC_CAP_CHAN_COUNT_3 = BIT(2), + /** Supporting 4 channel */ + BT_AUDIO_CODEC_CAP_CHAN_COUNT_4 = BIT(3), + /** Supporting 5 channel */ + BT_AUDIO_CODEC_CAP_CHAN_COUNT_5 = BIT(4), + /** Supporting 6 channel */ + BT_AUDIO_CODEC_CAP_CHAN_COUNT_6 = BIT(5), + /** Supporting 7 channel */ + BT_AUDIO_CODEC_CAP_CHAN_COUNT_7 = BIT(6), + /** Supporting 8 channel */ + BT_AUDIO_CODEC_CAP_CHAN_COUNT_8 = BIT(7), + /** Supporting all channels */ + BT_AUDIO_CODEC_CAP_CHAN_COUNT_ALL = + (BT_AUDIO_CODEC_CAP_CHAN_COUNT_1 | BT_AUDIO_CODEC_CAP_CHAN_COUNT_2 | + BT_AUDIO_CODEC_CAP_CHAN_COUNT_3 | BT_AUDIO_CODEC_CAP_CHAN_COUNT_4 | + BT_AUDIO_CODEC_CAP_CHAN_COUNT_5 | BT_AUDIO_CODEC_CAP_CHAN_COUNT_6 | + BT_AUDIO_CODEC_CAP_CHAN_COUNT_7 | BT_AUDIO_CODEC_CAP_CHAN_COUNT_8), +}; /** * @brief LC3 minimum supported channel counts @@ -147,13 +210,20 @@ enum bt_audio_codec_capability_type { * BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1, 3) */ #define BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(...) \ - ((uint8_t)((FOR_EACH(BIT, (|), __VA_ARGS__)) >> 1)) + ((enum bt_audio_codec_cap_chan_count)((FOR_EACH(BIT, (|), __VA_ARGS__)) >> 1)) struct BT_AUDIO_CODEC_LC3_frame_len { uint16_t min; uint16_t max; }; +struct bt_audio_codec_octets_per_codec_frame { + /** Minimum number of octets supported per codec frame */ + uint16_t min; + /** Maximum number of octets supported per codec frame */ + uint16_t max; +}; + /** * @brief Codec configuration type IDs * @@ -165,88 +235,91 @@ struct BT_AUDIO_CODEC_LC3_frame_len { enum bt_audio_codec_config_type { /** @brief LC3 Sample Frequency configuration type. */ - BT_AUDIO_CODEC_CONFIG_LC3_FREQ = 0x01, + BT_AUDIO_CODEC_CONFIG_LC3_FREQ = 0x01, /** @brief LC3 Frame Duration configuration type. */ - BT_AUDIO_CODEC_CONFIG_LC3_DURATION = 0x02, + BT_AUDIO_CODEC_CONFIG_LC3_DURATION = 0x02, /** @brief LC3 channel Allocation configuration type. */ - BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC = 0x03, + BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC = 0x03, /** @brief LC3 Frame Length configuration type. */ - BT_AUDIO_CODEC_CONFIG_LC3_FRAME_LEN = 0x04, + BT_AUDIO_CODEC_CONFIG_LC3_FRAME_LEN = 0x04, /** @brief Codec frame blocks, per SDU configuration type. */ - BT_AUDIO_CODEC_CONFIG_LC3_FRAME_BLKS_PER_SDU = 0x05, + BT_AUDIO_CODEC_CONFIG_LC3_FRAME_BLKS_PER_SDU = 0x05, }; -/** - * @brief 8 Khz codec Sample Frequency configuration - */ -#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_8KHZ 0x01 -/** - * @brief 11.025 Khz codec Sample Frequency configuration - */ -#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_11KHZ 0x02 -/** - * @brief 16 Khz codec Sample Frequency configuration - */ -#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_16KHZ 0x03 -/** - * @brief 22.05 Khz codec Sample Frequency configuration - */ -#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_22KHZ 0x04 -/** - * @brief 24 Khz codec Sample Frequency configuration - */ -#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_24KHZ 0x05 -/** - * @brief 32 Khz codec Sample Frequency configuration - */ -#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_32KHZ 0x06 -/** - * @brief 44.1 Khz codec Sample Frequency configuration - */ -#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_44KHZ 0x07 -/** - * @brief 48 Khz codec Sample Frequency configuration - */ -#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ 0x08 -/** - * @brief 88.2 Khz codec Sample Frequency configuration - */ -#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_88KHZ 0x09 -/** - * @brief 96 Khz codec Sample Frequency configuration - */ -#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_96KHZ 0x0a -/** - * @brief 176.4 Khz codec Sample Frequency configuration - */ -#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_176KHZ 0x0b -/** - * @brief 192 Khz codec Sample Frequency configuration - */ -#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_192KHZ 0x0c -/** - * @brief 384 Khz codec Sample Frequency configuration - */ -#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_384KHZ 0x0d - -/** - * @brief LC3 7.5 msec Frame Duration configuration - */ -#define BT_AUDIO_CODEC_CONFIG_LC3_DURATION_7_5 0x00 -/** - * @brief LC3 10 msec Frame Duration configuration - */ -#define BT_AUDIO_CODEC_CONFIG_LC3_DURATION_10 0x01 +enum bt_audio_codec_config_freq { + /** + * @brief 8 Khz codec Sample Frequency configuration + */ + BT_AUDIO_CODEC_CONFIG_LC3_FREQ_8KHZ = 0x01, + /** + * @brief 11.025 Khz codec Sample Frequency configuration + */ + BT_AUDIO_CODEC_CONFIG_LC3_FREQ_11KHZ = 0x02, + /** + * @brief 16 Khz codec Sample Frequency configuration + */ + BT_AUDIO_CODEC_CONFIG_LC3_FREQ_16KHZ = 0x03, + /** + * @brief 22.05 Khz codec Sample Frequency configuration + */ + BT_AUDIO_CODEC_CONFIG_LC3_FREQ_22KHZ = 0x04, + /** + * @brief 24 Khz codec Sample Frequency configuration + */ + BT_AUDIO_CODEC_CONFIG_LC3_FREQ_24KHZ = 0x05, + /** + * @brief 32 Khz codec Sample Frequency configuration + */ + BT_AUDIO_CODEC_CONFIG_LC3_FREQ_32KHZ = 0x06, + /** + * @brief 44.1 Khz codec Sample Frequency configuration + */ + BT_AUDIO_CODEC_CONFIG_LC3_FREQ_44KHZ = 0x07, + /** + * @brief 48 Khz codec Sample Frequency configuration + */ + BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ = 0x08, + /** + * @brief 88.2 Khz codec Sample Frequency configuration + */ + BT_AUDIO_CODEC_CONFIG_LC3_FREQ_88KHZ = 0x09, + /** + * @brief 96 Khz codec Sample Frequency configuration + */ + BT_AUDIO_CODEC_CONFIG_LC3_FREQ_96KHZ = 0x0a, + /** + * @brief 176.4 Khz codec Sample Frequency configuration + */ + BT_AUDIO_CODEC_CONFIG_LC3_FREQ_176KHZ = 0x0b, + /** + * @brief 192 Khz codec Sample Frequency configuration + */ + BT_AUDIO_CODEC_CONFIG_LC3_FREQ_192KHZ = 0x0c, + /** + * @brief 384 Khz codec Sample Frequency configuration + */ + BT_AUDIO_CODEC_CONFIG_LC3_FREQ_384KHZ = 0x0d, +}; +enum bt_audio_codec_config_frame_dur { + /** + * @brief LC3 7.5 msec Frame Duration configuration + */ + BT_AUDIO_CODEC_CONFIG_LC3_DURATION_7_5 = 0x00, + /** + * @brief LC3 10 msec Frame Duration configuration + */ + BT_AUDIO_CODEC_CONFIG_LC3_DURATION_10 = 0x01, +}; /** * @brief Helper to declare LC3 codec capability * - * _max_frames_per_sdu value is optional and will be included only if != 1 + * ``_max_frames_per_sdu`` value is optional and will be included only if != 1 */ /* COND_CODE_1 is used to omit an LTV entry in case the _frames_per_sdu is 1. * COND_CODE_1 will evaluate to second argument if the flag parameter(first argument) is 1 @@ -281,8 +354,8 @@ enum bt_audio_codec_config_type { /** * @brief Helper to declare LC3 codec * - * @param _freq Supported Sampling Frequencies bitfield (see BT_AUDIO_CODEC_LC3_FREQ_*) - * @param _duration Supported Frame Durations bitfield (see BT_AUDIO_CODEC_LC3_DURATION_*) + * @param _freq Supported Sampling Frequencies bitfield (see ``BT_AUDIO_CODEC_LC3_FREQ_*``) + * @param _duration Supported Frame Durations bitfield (see ``BT_AUDIO_CODEC_LC3_DURATION_*``) * @param _chan_count Supported channels (see @ref BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT) * @param _len_min Minimum number of octets supported per codec frame * @param _len_max Maximum number of octets supported per codec frame @@ -292,7 +365,7 @@ enum bt_audio_codec_config_type { */ #define BT_AUDIO_CODEC_CAP_LC3(_freq, _duration, _chan_count, _len_min, _len_max, \ _max_frames_per_sdu, _prefer_context) \ - BT_AUDIO_CODEC_CAP(BT_AUDIO_CODEC_LC3_ID, 0x0000, 0x0000, \ + BT_AUDIO_CODEC_CAP(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, \ BT_AUDIO_CODEC_CAP_LC3_DATA(_freq, _duration, _chan_count, _len_min, \ _len_max, _max_frames_per_sdu), \ BT_AUDIO_CODEC_CAP_LC3_META(_prefer_context)) @@ -300,8 +373,8 @@ enum bt_audio_codec_config_type { /** * @brief Helper to declare LC3 codec data configuration * - * @param _freq Sampling frequency (BT_AUDIO_CODEC_CONFIG_LC3_FREQ_*) - * @param _duration Frame duration (BT_AUDIO_CODEC_CONFIG_LC3_DURATION_*) + * @param _freq Sampling frequency (``BT_AUDIO_CODEC_CONFIG_LC3_FREQ_*``) + * @param _duration Frame duration (``BT_AUDIO_CODEC_CONFIG_LC3_DURATION_*``) * @param _loc Audio channel location bitfield (@ref bt_audio_location) * @param _len Octets per frame (16-bit integer) * @param _frames_per_sdu Frames per SDU (8-bit integer). This value is optional and will be @@ -332,16 +405,16 @@ enum bt_audio_codec_config_type { /** * @brief Helper to declare LC3 codec configuration. * - * @param _freq Sampling frequency (BT_AUDIO_CODEC_CONFIG_LC3_FREQ_*) - * @param _duration Frame duration (BT_AUDIO_CODEC_CONFIG_LC3_DURATION_*) + * @param _freq Sampling frequency (``BT_AUDIO_CODEC_CONFIG_LC3_FREQ_*``) + * @param _duration Frame duration (``BT_AUDIO_CODEC_CONFIG_LC3_DURATION_*``) * @param _loc Audio channel location bitfield (@ref bt_audio_location) * @param _len Octets per frame (16-bit integer) * @param _frames_per_sdu Frames per SDU (8-bit integer) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_AUDIO_CODEC_LC3_CONFIG(_freq, _duration, _loc, _len, _frames_per_sdu, _stream_context) \ BT_AUDIO_CODEC_CFG( \ - BT_AUDIO_CODEC_LC3_ID, 0x0000, 0x0000, \ + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, \ BT_AUDIO_CODEC_CFG_LC3_DATA(_freq, _duration, _loc, _len, _frames_per_sdu), \ BT_AUDIO_CODEC_CFG_LC3_META(_stream_context)) @@ -349,7 +422,7 @@ enum bt_audio_codec_config_type { * @brief Helper to declare LC3 8.1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_AUDIO_CODEC_LC3_CONFIG_8_1(_loc, _stream_context) \ BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_8KHZ, \ @@ -359,7 +432,7 @@ enum bt_audio_codec_config_type { * @brief Helper to declare LC3 8.2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_AUDIO_CODEC_LC3_CONFIG_8_2(_loc, _stream_context) \ BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_8KHZ, \ @@ -369,7 +442,7 @@ enum bt_audio_codec_config_type { * @brief Helper to declare LC3 16.1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_AUDIO_CODEC_LC3_CONFIG_16_1(_loc, _stream_context) \ BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_16KHZ, \ @@ -379,7 +452,7 @@ enum bt_audio_codec_config_type { * @brief Helper to declare LC3 16.2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_AUDIO_CODEC_LC3_CONFIG_16_2(_loc, _stream_context) \ BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_16KHZ, \ @@ -390,7 +463,7 @@ enum bt_audio_codec_config_type { * @brief Helper to declare LC3 24.1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_AUDIO_CODEC_LC3_CONFIG_24_1(_loc, _stream_context) \ BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_24KHZ, \ @@ -400,7 +473,7 @@ enum bt_audio_codec_config_type { * @brief Helper to declare LC3 24.2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_AUDIO_CODEC_LC3_CONFIG_24_2(_loc, _stream_context) \ BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_24KHZ, \ @@ -410,7 +483,7 @@ enum bt_audio_codec_config_type { * @brief Helper to declare LC3 32.1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_AUDIO_CODEC_LC3_CONFIG_32_1(_loc, _stream_context) \ BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_32KHZ, \ @@ -420,7 +493,7 @@ enum bt_audio_codec_config_type { * @brief Helper to declare LC3 32.2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_AUDIO_CODEC_LC3_CONFIG_32_2(_loc, _stream_context) \ BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_32KHZ, \ @@ -430,7 +503,7 @@ enum bt_audio_codec_config_type { * @brief Helper to declare LC3 441.1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_AUDIO_CODEC_LC3_CONFIG_441_1(_loc, _stream_context) \ BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_44KHZ, \ @@ -440,7 +513,7 @@ enum bt_audio_codec_config_type { * @brief Helper to declare LC3 441.2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_AUDIO_CODEC_LC3_CONFIG_441_2(_loc, _stream_context) \ BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_44KHZ, \ @@ -450,7 +523,7 @@ enum bt_audio_codec_config_type { * @brief Helper to declare LC3 48.1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_AUDIO_CODEC_LC3_CONFIG_48_1(_loc, _stream_context) \ BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ, \ @@ -460,7 +533,7 @@ enum bt_audio_codec_config_type { * @brief Helper to declare LC3 48.2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_AUDIO_CODEC_LC3_CONFIG_48_2(_loc, _stream_context) \ BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ, \ @@ -470,7 +543,7 @@ enum bt_audio_codec_config_type { * @brief Helper to declare LC3 48.3 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_AUDIO_CODEC_LC3_CONFIG_48_3(_loc, _stream_context) \ BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ, \ @@ -480,7 +553,7 @@ enum bt_audio_codec_config_type { * @brief Helper to declare LC3 48.4 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_AUDIO_CODEC_LC3_CONFIG_48_4(_loc, _stream_context) \ BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ, \ @@ -490,7 +563,7 @@ enum bt_audio_codec_config_type { * @brief Helper to declare LC3 48.5 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_AUDIO_CODEC_LC3_CONFIG_48_5(_loc, _stream_context) \ BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ, \ @@ -500,7 +573,7 @@ enum bt_audio_codec_config_type { * @brief Helper to declare LC3 48.6 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_AUDIO_CODEC_LC3_CONFIG_48_6(_loc, _stream_context) \ BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ, \ diff --git a/include/zephyr/bluetooth/bluetooth.h b/include/zephyr/bluetooth/bluetooth.h index 6f3aeb96775..c97e1445cb3 100644 --- a/include/zephyr/bluetooth/bluetooth.h +++ b/include/zephyr/bluetooth/bluetooth.h @@ -1690,6 +1690,10 @@ struct bt_le_per_adv_sync *bt_le_per_adv_sync_lookup_addr(const bt_addr_le_t *ad * to periodic advertising reports from an advertiser. Scan shall either be * disabled or extended scan shall be enabled. * + * This function does not timeout, and will continue to look for an advertiser until it either + * finds it or bt_le_per_adv_sync_delete() is called. It is thus suggested to implement a timeout + * when using this, if it is expected to find the advertiser within a reasonable timeframe. + * * @param[in] param Periodic advertising sync parameters. * @param[out] out_sync Periodic advertising sync object on. * diff --git a/include/zephyr/bluetooth/conn.h b/include/zephyr/bluetooth/conn.h index f8a15bea9b8..bdc644d82e9 100644 --- a/include/zephyr/bluetooth/conn.h +++ b/include/zephyr/bluetooth/conn.h @@ -884,6 +884,9 @@ int bt_le_set_auto_conn(const bt_addr_le_t *addr, * @note When @kconfig{CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY} is enabled then the * security level will always be level 3. * + * @note When @ref BT_SECURITY_FORCE_PAIR within @p sec is enabled then the pairing + * procedure will always be initiated. + * * @param conn Connection object. * @param sec Requested security level. * diff --git a/include/zephyr/bluetooth/ead.h b/include/zephyr/bluetooth/ead.h index ba4de42ce40..8aaee2e4136 100644 --- a/include/zephyr/bluetooth/ead.h +++ b/include/zephyr/bluetooth/ead.h @@ -11,6 +11,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /** * @brief Encrypted Advertising Data (EAD) * @defgroup bt_ead Encrypted Advertising Data (EAD) @@ -104,4 +108,8 @@ int bt_ead_decrypt(const uint8_t session_key[BT_EAD_KEY_SIZE], const uint8_t iv[ * @} */ +#ifdef __cplusplus +} +#endif + #endif /* ZEPHYR_INCLUDE_BLUETOOTH_EAD_H_ */ diff --git a/include/zephyr/bluetooth/gatt.h b/include/zephyr/bluetooth/gatt.h index f0ee8d5981a..c53422648f0 100644 --- a/include/zephyr/bluetooth/gatt.h +++ b/include/zephyr/bluetooth/gatt.h @@ -72,7 +72,7 @@ enum bt_gatt_perm { /** @brief Attribute prepare write permission. * - * If set, allows prepare writes with use of BT_GATT_WRITE_FLAG_PREPARE + * If set, allows prepare writes with use of ``BT_GATT_WRITE_FLAG_PREPARE`` * passed to write callback. */ BT_GATT_PERM_PREPARE_WRITE = BIT(6), @@ -140,7 +140,7 @@ struct bt_gatt_attr; * @param offset Offset to start reading from * * @return Number of bytes read, or in case of an error - * BT_GATT_ERR() with a specific BT_ATT_ERR_* error code. + * ``BT_GATT_ERR()`` with a specific ``BT_ATT_ERR_*`` error code. */ typedef ssize_t (*bt_gatt_attr_read_func_t)(struct bt_conn *conn, const struct bt_gatt_attr *attr, @@ -155,10 +155,10 @@ typedef ssize_t (*bt_gatt_attr_read_func_t)(struct bt_conn *conn, * @param buf Buffer with the data to write * @param len Number of bytes in the buffer * @param offset Offset to start writing from - * @param flags Flags (BT_GATT_WRITE_FLAG_*) + * @param flags Flags (``BT_GATT_WRITE_FLAG_*``) * * @return Number of bytes written, or in case of an error - * BT_GATT_ERR() with a specific BT_ATT_ERR_* error code. + * ``BT_GATT_ERR()`` with a specific ``BT_ATT_ERR_*`` error code. */ typedef ssize_t (*bt_gatt_attr_write_func_t)(struct bt_conn *conn, const struct bt_gatt_attr *attr, @@ -178,7 +178,7 @@ struct bt_gatt_attr { uint16_t handle; /** @brief Attribute permissions. * - * Will be 0 if returned from bt_gatt_discover(). + * Will be 0 if returned from ``bt_gatt_discover()``. */ uint16_t perm; }; @@ -370,7 +370,8 @@ struct bt_gatt_cpf { /** @brief Register GATT callbacks. * - * Register callbacks to monitor the state of GATT. + * Register callbacks to monitor the state of GATT. The callback struct + * must remain valid for the remainder of the program. * * @param cb Callback struct. */ @@ -379,8 +380,8 @@ void bt_gatt_cb_register(struct bt_gatt_cb *cb); /** @brief Register GATT service. * * Register GATT service. Applications can make use of - * macros such as BT_GATT_PRIMARY_SERVICE, BT_GATT_CHARACTERISTIC, - * BT_GATT_DESCRIPTOR, etc. + * macros such as ``BT_GATT_PRIMARY_SERVICE``, ``BT_GATT_CHARACTERISTIC``, + * ``BT_GATT_DESCRIPTOR``, etc. * * When using @kconfig{CONFIG_BT_SETTINGS} then all services that should have * bond configuration loaded, i.e. CCC values, must be registered before @@ -400,7 +401,7 @@ void bt_gatt_cb_register(struct bt_gatt_cb *cb); * @param svc Service containing the available attributes * * @return 0 in case of success or negative value in case of error. - * @return -EAGAIN if `bt_init()` has been called but `settings_load()` hasn't yet. + * @return -EAGAIN if ``bt_init()`` has been called but ``settings_load()`` hasn't yet. */ int bt_gatt_service_register(struct bt_gatt_service *svc); @@ -432,8 +433,8 @@ enum { * @param handle Attribute handle found. * @param user_data Data given. * - * @return BT_GATT_ITER_CONTINUE if should continue to the next attribute. - * @return BT_GATT_ITER_STOP to stop. + * @return ``BT_GATT_ITER_CONTINUE`` if should continue to the next attribute. + * @return ``BT_GATT_ITER_STOP`` to stop. */ typedef uint8_t (*bt_gatt_attr_func_t)(const struct bt_gatt_attr *attr, uint16_t handle, @@ -488,7 +489,7 @@ struct bt_gatt_attr *bt_gatt_attr_next(const struct bt_gatt_attr *attr); * * Find the attribute with the matching UUID. * To limit the search to a service set the attr to the service attributes and - * the attr_count to the service attribute count . + * the ``attr_count`` to the service attribute count . * * @param attr Pointer to an attribute that serves as the starting point * for the search of a match for the UUID. @@ -515,7 +516,7 @@ uint16_t bt_gatt_attr_get_handle(const struct bt_gatt_attr *attr); * * @param attr A Characteristic Attribute. * - * @note The user_data of the attribute must of type @ref bt_gatt_chrc. + * @note The ``user_data`` of the attribute must of type @ref bt_gatt_chrc. * * @return the handle of the corresponding Characteristic Value. The value will * be zero (the invalid handle) if @p attr was not a characteristic @@ -546,7 +547,7 @@ ssize_t bt_gatt_attr_read(struct bt_conn *conn, const struct bt_gatt_attr *attr, * * Read service attribute value from local database storing the result into * buffer after encoding it. - * @note Only use this with attributes which user_data is a bt_uuid. + * @note Only use this with attributes which ``user_data`` is a ``bt_uuid``. * * @param conn Connection object. * @param attr Attribute to read. @@ -583,7 +584,7 @@ ssize_t bt_gatt_attr_read_service(struct bt_conn *conn, * * Helper macro to statically define service structure array. Each element * of the array is linked to the service attribute array which is also - * defined in this scope using _attrs_def macro. + * defined in this scope using ``_attrs_def`` macro. * * @param _name Name of service structure array. * @param _instances Array of instances to pass as user context to the @@ -645,7 +646,7 @@ ssize_t bt_gatt_attr_read_service(struct bt_conn *conn, * * Read include service attribute value from local database storing the result * into buffer after encoding it. - * @note Only use this with attributes which user_data is a bt_gatt_include. + * @note Only use this with attributes which user_data is a ``bt_gatt_include``. * * @param conn Connection object. * @param attr Attribute to read. @@ -675,7 +676,7 @@ ssize_t bt_gatt_attr_read_included(struct bt_conn *conn, * * Read characteristic attribute value from local database storing the result * into buffer after encoding it. - * @note Only use this with attributes which user_data is a bt_gatt_chrc. + * @note Only use this with attributes which ``user_data`` is a ``bt_gatt_chrc``. * * @param conn Connection object. * @param attr Attribute to read. @@ -705,7 +706,7 @@ ssize_t bt_gatt_attr_read_chrc(struct bt_conn *conn, * * @param _uuid Characteristic attribute uuid. * @param _props Characteristic attribute properties, - * a bitmap of BT_GATT_CHRC_* macros. + * a bitmap of ``BT_GATT_CHRC_*`` macros. * @param _perm Characteristic Attribute access permissions, * a bitmap of @ref bt_gatt_perm values. * @param _read Characteristic Attribute read callback @@ -1458,10 +1459,10 @@ struct bt_gatt_discover_params { uint16_t end_handle; /** Discover type */ uint8_t type; -#if defined(CONFIG_BT_GATT_AUTO_DISCOVER_CCC) +#if defined(CONFIG_BT_GATT_AUTO_DISCOVER_CCC) || defined(__DOXYGEN__) /** Only for stack-internal use, used for automatic discovery. */ struct bt_gatt_subscribe_params *sub_params; -#endif /* defined(CONFIG_BT_GATT_AUTO_DISCOVER_CCC) */ +#endif /* defined(CONFIG_BT_GATT_AUTO_DISCOVER_CCC) || defined(__DOXYGEN__) */ #if defined(CONFIG_BT_EATT) enum bt_att_chan_opt chan_opt; #endif /* CONFIG_BT_EATT */ @@ -1572,6 +1573,8 @@ struct bt_gatt_read_params { #if defined(CONFIG_BT_EATT) enum bt_att_chan_opt chan_opt; #endif /* CONFIG_BT_EATT */ + /** Internal */ + uint16_t _att_mtu; }; /** @brief Read Attribute Value by handle @@ -1582,9 +1585,21 @@ struct bt_gatt_read_params { * depending on how many instances of given the UUID exists with the * start_handle being updated for each instance. * - * If an instance does contain a long value which cannot be read entirely the - * caller will need to read the remaining data separately using the handle and - * offset. + * To perform a GATT Long Read procedure, start with a Characteristic Value + * Read (by setting @c offset @c 0 and @c handle_count @c 1) and then return + * @ref BT_GATT_ITER_CONTINUE from the callback. This is equivalent to calling + * @ref bt_gatt_read again, but with the correct offset to continue the read. + * This may be repeated until the procedure is complete, which is signaled by + * the callback being called with @p data set to @c NULL. + * + * Note that returning @ref BT_GATT_ITER_CONTINUE is really starting a new ATT + * operation, so this can fail to allocate resources. However, all API errors + * are reported as if the server returned @ref BT_ATT_ERR_UNLIKELY. There is no + * way to distinguish between this condition and a @ref BT_ATT_ERR_UNLIKELY + * response from the server itself. + * + * Note that the effect of returning @ref BT_GATT_ITER_CONTINUE from the + * callback varies depending on the type of read operation. * * The Response comes in callback @p params->func. The callback is run from * the context specified by 'config BT_RECV_CONTEXT'. @@ -1826,12 +1841,12 @@ struct bt_gatt_subscribe_params { uint16_t value_handle; /** Subscribe CCC handle */ uint16_t ccc_handle; -#if defined(CONFIG_BT_GATT_AUTO_DISCOVER_CCC) +#if defined(CONFIG_BT_GATT_AUTO_DISCOVER_CCC) || defined(__DOXYGEN__) /** Subscribe End handle (for automatic discovery) */ uint16_t end_handle; /** Discover parameters used when ccc_handle = 0 */ struct bt_gatt_discover_params *disc_params; -#endif /* CONFIG_BT_GATT_AUTO_DISCOVER_CCC */ +#endif /* defined(CONFIG_BT_GATT_AUTO_DISCOVER_CCC) || defined(__DOXYGEN__) */ /** Subscribe value */ uint16_t value; #if defined(CONFIG_BT_SMP) diff --git a/include/zephyr/bluetooth/hci_types.h b/include/zephyr/bluetooth/hci_types.h index dc1566a0df4..f1cb92f372c 100644 --- a/include/zephyr/bluetooth/hci_types.h +++ b/include/zephyr/bluetooth/hci_types.h @@ -778,6 +778,8 @@ struct bt_hci_rp_read_bd_addr { #define BT_HCI_CODING_FORMAT_TRANSPARENT 0x03 #define BT_HCI_CODING_FORMAT_LINEAR_PCM 0x04 #define BT_HCI_CODING_FORMAT_MSBC 0x05 +#define BT_HCI_CODING_FORMAT_LC3 0x06 +#define BT_HCI_CODING_FORMAT_G729A 0x07 #define BT_HCI_CODING_FORMAT_VS 0xFF diff --git a/include/zephyr/bluetooth/iso.h b/include/zephyr/bluetooth/iso.h index b9fc3e549dc..68ceec3ac3d 100644 --- a/include/zephyr/bluetooth/iso.h +++ b/include/zephyr/bluetooth/iso.h @@ -200,7 +200,7 @@ struct bt_iso_chan_io_qos { */ struct bt_iso_chan_path *path; -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) /** @brief Maximum PDU size * * Maximum size, in octets, of the payload from link layer to link @@ -219,7 +219,7 @@ struct bt_iso_chan_io_qos { * Value range @ref BT_ISO_BN_MIN to @ref BT_ISO_BN_MAX. */ uint8_t burst_number; -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ }; /** @brief ISO Channel QoS structure. */ @@ -241,7 +241,7 @@ struct bt_iso_chan_qos { */ struct bt_iso_chan_io_qos *tx; -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) /** @brief Number of subevents * * Maximum number of subevents in each CIS or BIS event. @@ -249,7 +249,7 @@ struct bt_iso_chan_qos { * Value range @ref BT_ISO_NSE_MIN to @ref BT_ISO_NSE_MAX. */ uint8_t num_subevents; -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ }; /** @brief ISO Channel Data Path structure. */ @@ -335,19 +335,33 @@ struct bt_iso_cig_param { */ uint8_t num_cis; - /** @brief Channel interval in us. + /** @brief Channel interval in us for SDUs sent from Central to Peripheral. * * Value range BT_ISO_SDU_INTERVAL_MIN - BT_ISO_SDU_INTERVAL_MAX. */ - uint32_t interval; + uint32_t c_to_p_interval; - /** @brief Channel Latency in ms. + /** @brief Channel interval in us for SDUs sent from Peripheral to Central. + * + * Value range BT_ISO_SDU_INTERVAL_MIN - BT_ISO_SDU_INTERVAL_MAX. + */ + uint32_t p_to_c_interval; + + /** @brief Channel Latency in ms for SDUs sent from Central to Peripheral * * Value range BT_ISO_LATENCY_MIN - BT_ISO_LATENCY_MAX. * * This value is ignored if any advanced ISO parameters are set. */ - uint16_t latency; + uint16_t c_to_p_latency; + + /** @brief Channel Latency in ms for SDUs sent from Peripheral to Central + * + * Value range BT_ISO_LATENCY_MIN - BT_ISO_LATENCY_MAX. + * + * This value is ignored if any advanced ISO parameters are set. + */ + uint16_t p_to_c_latency; /** @brief Channel peripherals sleep clock accuracy Only for CIS * @@ -371,7 +385,7 @@ struct bt_iso_cig_param { */ uint8_t framing; -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) /** @brief Central to Peripheral flush timeout * * The flush timeout in multiples of ISO_Interval for each payload sent @@ -398,8 +412,7 @@ struct bt_iso_cig_param { * @ref BT_ISO_ISO_INTERVAL_MAX. */ uint16_t iso_interval; -#endif /* CONFIG_BT_ISO_ADVANCED */ - +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ }; /** ISO connection parameters structure */ @@ -470,7 +483,7 @@ struct bt_iso_big_create_param { */ uint8_t bcode[BT_ISO_BROADCAST_CODE_SIZE]; -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) /** @brief Immediate Repetition Count * * The number of times the scheduled payloads are transmitted in a @@ -496,7 +509,7 @@ struct bt_iso_big_create_param { * @ref BT_ISO_ISO_INTERVAL_MAX. */ uint16_t iso_interval; -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ }; /** @brief Broadcast Isochronous Group (BIG) Sync Parameters */ @@ -808,10 +821,17 @@ int bt_iso_cig_terminate(struct bt_iso_cig *cig); */ int bt_iso_chan_connect(const struct bt_iso_connect_param *param, size_t count); -/** @brief Disconnect ISO channel +/** @brief Disconnect connected ISO channel + * + * Disconnect connected ISO channel. + * + * If the device is a central and the connection is pending it will be + * canceled and as a result the channel bt_iso_chan_ops.disconnected() callback is called. + * + * If the device is a peripheral and the connection is pending it will be rejected, as a peripheral + * shall wait for a CIS Established event (which may trigger a bt_iso_chan_ops.disconnected() + * callback in case of an error). * - * Disconnect ISO channel, if the connection is pending it will be - * canceled and as a result the channel disconnected() callback is called. * Regarding to input parameter, to get details see reference description * to bt_iso_chan_connect() API above. * diff --git a/include/zephyr/bluetooth/l2cap.h b/include/zephyr/bluetooth/l2cap.h index 5c23a05ec7d..34d1f2dc2ab 100644 --- a/include/zephyr/bluetooth/l2cap.h +++ b/include/zephyr/bluetooth/l2cap.h @@ -453,6 +453,7 @@ struct bt_l2cap_server { * authorization. * * @param conn The connection that is requesting authorization + * @param server Pointer to the server structure this callback relates to * @param chan Pointer to received the allocated channel * * @return 0 in case of success or negative value in case of error. @@ -460,7 +461,8 @@ struct bt_l2cap_server { * @return -EACCES if application did not authorize the connection. * @return -EPERM if encryption key size is too short. */ - int (*accept)(struct bt_conn *conn, struct bt_l2cap_chan **chan); + int (*accept)(struct bt_conn *conn, struct bt_l2cap_server *server, + struct bt_l2cap_chan **chan); sys_snode_t node; }; diff --git a/include/zephyr/bluetooth/mesh/access.h b/include/zephyr/bluetooth/mesh/access.h index 5b1653c2487..817fba918ef 100644 --- a/include/zephyr/bluetooth/mesh/access.h +++ b/include/zephyr/bluetooth/mesh/access.h @@ -30,6 +30,9 @@ #define BT_MESH_MODEL_UUIDS_UNASSIGNED() #endif +#define BT_MESH_MODEL_RUNTIME_INIT(_user_data) \ + .rt = &(struct bt_mesh_model_rt_ctx){ .user_data = (_user_data) }, + /** * @brief Access layer * @defgroup bt_mesh_access Access layer @@ -137,19 +140,23 @@ extern "C" { * @param _mods Array of models. * @param _vnd_mods Array of vendor models. */ -#define BT_MESH_ELEM(_loc, _mods, _vnd_mods) \ -{ \ - .loc = (_loc), \ - .model_count = ARRAY_SIZE(_mods), \ - .vnd_model_count = ARRAY_SIZE(_vnd_mods), \ - .models = (_mods), \ - .vnd_models = (_vnd_mods), \ +#define BT_MESH_ELEM(_loc, _mods, _vnd_mods) \ +{ \ + .rt = &(struct bt_mesh_elem_rt_ctx) { 0 }, \ + .loc = (_loc), \ + .model_count = ARRAY_SIZE(_mods), \ + .vnd_model_count = ARRAY_SIZE(_vnd_mods), \ + .models = (_mods), \ + .vnd_models = (_vnd_mods), \ } /** Abstraction that describes a Mesh Element */ struct bt_mesh_elem { - /** Unicast Address. Set at runtime during provisioning. */ - uint16_t addr; + /** Mesh Element runtime information */ + struct bt_mesh_elem_rt_ctx { + /** Unicast Address. Set at runtime during provisioning. */ + uint16_t addr; + } * const rt; /** Location Descriptor (GATT Bluetooth Namespace Descriptors) */ const uint16_t loc; @@ -159,9 +166,9 @@ struct bt_mesh_elem { const uint8_t vnd_model_count; /** The list of SIG models in this element */ - struct bt_mesh_model * const models; + const struct bt_mesh_model * const models; /** The list of vendor models in this element */ - struct bt_mesh_model * const vnd_models; + const struct bt_mesh_model * const vnd_models; }; /** @@ -370,7 +377,7 @@ struct bt_mesh_model_op { * * @return Zero on success or (negative) error code otherwise. */ - int (*const func)(struct bt_mesh_model *model, + int (*const func)(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf); }; @@ -403,7 +410,7 @@ struct bt_mesh_model_op { * This macro uses compound literal feature of C99 standard and thus is available only from C, * not C++. */ -#define BT_MESH_MODEL_NONE ((struct bt_mesh_model []){}) +#define BT_MESH_MODEL_NONE ((const struct bt_mesh_model []){}) /** * @brief Composition data SIG model entry with callback functions @@ -425,6 +432,7 @@ struct bt_mesh_model_op { #define BT_MESH_MODEL_CNT_CB(_id, _op, _pub, _user_data, _keys, _grps, _cb) \ { \ .id = (_id), \ + BT_MESH_MODEL_RUNTIME_INIT(_user_data) \ .pub = _pub, \ .keys = (uint16_t []) BT_MESH_MODEL_KEYS_UNUSED(_keys), \ .keys_cnt = _keys, \ @@ -433,7 +441,6 @@ struct bt_mesh_model_op { BT_MESH_MODEL_UUIDS_UNASSIGNED() \ .op = _op, \ .cb = _cb, \ - .user_data = _user_data, \ } /** @@ -458,6 +465,7 @@ struct bt_mesh_model_op { { \ .vnd.company = (_company), \ .vnd.id = (_id), \ + BT_MESH_MODEL_RUNTIME_INIT(_user_data) \ .op = _op, \ .pub = _pub, \ .keys = (uint16_t []) BT_MESH_MODEL_KEYS_UNUSED(_keys), \ @@ -465,7 +473,6 @@ struct bt_mesh_model_op { .groups = (uint16_t []) BT_MESH_MODEL_GROUPS_UNASSIGNED(_grps), \ .groups_cnt = _grps, \ BT_MESH_MODEL_UUIDS_UNASSIGNED() \ - .user_data = _user_data, \ .cb = _cb, \ } @@ -505,6 +512,7 @@ struct bt_mesh_model_op { #define BT_MESH_MODEL_METADATA_CB(_id, _op, _pub, _user_data, _cb, _metadata) \ { \ .id = (_id), \ + BT_MESH_MODEL_RUNTIME_INIT(_user_data) \ .pub = _pub, \ .keys = (uint16_t []) BT_MESH_MODEL_KEYS_UNUSED(CONFIG_BT_MESH_MODEL_KEY_COUNT), \ .keys_cnt = CONFIG_BT_MESH_MODEL_KEY_COUNT, \ @@ -513,7 +521,6 @@ struct bt_mesh_model_op { BT_MESH_MODEL_UUIDS_UNASSIGNED() \ .op = _op, \ .cb = _cb, \ - .user_data = _user_data, \ .metadata = _metadata, \ } #else @@ -559,6 +566,7 @@ struct bt_mesh_model_op { { \ .vnd.company = (_company), \ .vnd.id = (_id), \ + BT_MESH_MODEL_RUNTIME_INIT(_user_data) \ .op = _op, \ .pub = _pub, \ .keys = (uint16_t []) BT_MESH_MODEL_KEYS_UNUSED(CONFIG_BT_MESH_MODEL_KEY_COUNT), \ @@ -566,7 +574,6 @@ struct bt_mesh_model_op { .groups = (uint16_t []) BT_MESH_MODEL_GROUPS_UNASSIGNED(CONFIG_BT_MESH_MODEL_GROUP_COUNT), \ .groups_cnt = CONFIG_BT_MESH_MODEL_GROUP_COUNT, \ BT_MESH_MODEL_UUIDS_UNASSIGNED() \ - .user_data = _user_data, \ .cb = _cb, \ .metadata = _metadata, \ } @@ -690,7 +697,7 @@ struct bt_mesh_model_op { */ struct bt_mesh_model_pub { /** The model the context belongs to. Initialized by the stack. */ - struct bt_mesh_model *mod; + const struct bt_mesh_model *mod; uint16_t addr; /**< Publish Address. */ const uint8_t *uuid; /**< Label UUID if Publish Address is Virtual Address. */ @@ -735,7 +742,7 @@ struct bt_mesh_model_pub { * * @return Zero on success or (negative) error code otherwise. */ - int (*update)(struct bt_mesh_model *mod); + int (*update)(const struct bt_mesh_model *mod); /** Publish Period Timer. Only for stack-internal use. */ struct k_work_delayable timer; @@ -805,7 +812,7 @@ struct bt_mesh_model_cb { * * @return 0 on success, error otherwise. */ - int (*const settings_set)(struct bt_mesh_model *model, + int (*const settings_set)(const struct bt_mesh_model *model, const char *name, size_t len_rd, settings_read_cb read_cb, void *cb_arg); @@ -821,7 +828,7 @@ struct bt_mesh_model_cb { * * @return 0 on success, error otherwise. */ - int (*const start)(struct bt_mesh_model *model); + int (*const start)(const struct bt_mesh_model *model); /** @brief Model init callback. * @@ -835,7 +842,7 @@ struct bt_mesh_model_cb { * * @return 0 on success, error otherwise. */ - int (*const init)(struct bt_mesh_model *model); + int (*const init)(const struct bt_mesh_model *model); /** @brief Model reset callback. * @@ -847,7 +854,7 @@ struct bt_mesh_model_cb { * * @param model Model this callback belongs to. */ - void (*const reset)(struct bt_mesh_model *model); + void (*const reset)(const struct bt_mesh_model *model); /** @brief Callback used to store pending model's user data. * @@ -857,7 +864,7 @@ struct bt_mesh_model_cb { * * @param model Model this callback belongs to. */ - void (*const pending_store)(struct bt_mesh_model *model); + void (*const pending_store)(const struct bt_mesh_model *model); }; /** Vendor model ID */ @@ -877,10 +884,19 @@ struct bt_mesh_model { const struct bt_mesh_mod_id_vnd vnd; }; - /* Internal information, mainly for persistent storage */ - uint8_t elem_idx; /* Belongs to Nth element */ - uint8_t mod_idx; /* Is the Nth model in the element */ - uint16_t flags; /* Model flags for internal bookkeeping */ + /* Model runtime information */ + struct bt_mesh_model_rt_ctx { + uint8_t elem_idx; /* Belongs to Nth element */ + uint8_t mod_idx; /* Is the Nth model in the element */ + uint16_t flags; /* Model flags for internal bookkeeping */ + +#ifdef CONFIG_BT_MESH_MODEL_EXTENSIONS + /* Pointer to the next model in a model extension list. */ + const struct bt_mesh_model *next; +#endif + /** Model-specific user data */ + void *user_data; + } * const rt; /** Model Publication */ struct bt_mesh_model_pub * const pub; @@ -893,7 +909,7 @@ struct bt_mesh_model { uint16_t * const groups; const uint16_t groups_cnt; -#if CONFIG_BT_MESH_LABEL_COUNT > 0 +#if (CONFIG_BT_MESH_LABEL_COUNT > 0) || defined(__DOXYGEN__) /** List of Label UUIDs the model is subscribed to. */ const uint8_t ** const uuids; #endif @@ -904,18 +920,10 @@ struct bt_mesh_model { /** Model callback structure. */ const struct bt_mesh_model_cb * const cb; -#ifdef CONFIG_BT_MESH_MODEL_EXTENSIONS - /* Pointer to the next model in a model extension list. */ - struct bt_mesh_model *next; -#endif - -#ifdef CONFIG_BT_MESH_LARGE_COMP_DATA_SRV +#if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV) || defined(__DOXYGEN__) /* Pointer to the array of model metadata entries. */ struct bt_mesh_models_metadata_entry **metadata; #endif - - /** Model-specific user data */ - void *user_data; }; /** Callback structure for monitoring model message sending */ @@ -952,7 +960,7 @@ struct bt_mesh_send_cb { * * @return 0 on success, or (negative) error code on failure. */ -int bt_mesh_model_send(struct bt_mesh_model *model, +int bt_mesh_model_send(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *msg, const struct bt_mesh_send_cb *cb, @@ -971,7 +979,7 @@ int bt_mesh_model_send(struct bt_mesh_model *model, * * @return 0 on success, or (negative) error code on failure. */ -int bt_mesh_model_publish(struct bt_mesh_model *model); +int bt_mesh_model_publish(const struct bt_mesh_model *model); /** @brief Check if a message is being retransmitted. * @@ -992,7 +1000,7 @@ static inline bool bt_mesh_model_pub_is_retransmission(const struct bt_mesh_mode * * @return Pointer to the element that the given model belongs to. */ -struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod); +const struct bt_mesh_elem *bt_mesh_model_elem(const struct bt_mesh_model *mod); /** @brief Find a SIG model. * @@ -1002,7 +1010,7 @@ struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod); * @return A pointer to the Mesh model matching the given parameters, or NULL * if no SIG model with the given ID exists in the given element. */ -struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem, +const struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem, uint16_t id); /** @brief Find a vendor model. @@ -1014,7 +1022,7 @@ struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem, * @return A pointer to the Mesh model matching the given parameters, or NULL * if no vendor model with the given ID exists in the given element. */ -struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem, +const struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem, uint16_t company, uint16_t id); /** @brief Get whether the model is in the primary element of the device. @@ -1025,7 +1033,7 @@ struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem, */ static inline bool bt_mesh_model_in_primary(const struct bt_mesh_model *mod) { - return (mod->elem_idx == 0); + return (mod->rt->elem_idx == 0); } /** @brief Immediately store the model's user data in persistent storage. @@ -1039,7 +1047,7 @@ static inline bool bt_mesh_model_in_primary(const struct bt_mesh_model *mod) * * @return 0 on success, or (negative) error code on failure. */ -int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd, +int bt_mesh_model_data_store(const struct bt_mesh_model *mod, bool vnd, const char *name, const void *data, size_t data_len); @@ -1054,7 +1062,7 @@ int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd, * * @param mod Mesh model. */ -void bt_mesh_model_data_store_schedule(struct bt_mesh_model *mod); +void bt_mesh_model_data_store_schedule(const struct bt_mesh_model *mod); /** @brief Let a model extend another. * @@ -1070,13 +1078,17 @@ void bt_mesh_model_data_store_schedule(struct bt_mesh_model *mod); * extension list and element, giving the models extended subscription list * capacity. * + * If @kconfig{CONFIG_BT_MESH_COMP_PAGE_1} is enabled, it is not allowed to call + * this function before the @ref bt_mesh_model_cb.init callback is called + * for both models, except if it is called as part of the final callback. + * * @param extending_mod Mesh model that is extending the base model. * @param base_mod The model being extended. * * @retval 0 Successfully extended the base_mod model. */ -int bt_mesh_model_extend(struct bt_mesh_model *extending_mod, - struct bt_mesh_model *base_mod); +int bt_mesh_model_extend(const struct bt_mesh_model *extending_mod, + const struct bt_mesh_model *base_mod); /** @brief Let a model correspond to another. * @@ -1098,8 +1110,8 @@ int bt_mesh_model_extend(struct bt_mesh_model *extending_mod, * @retval -ENOTSUP Composition Data Page 1 is not supported. */ -int bt_mesh_model_correspond(struct bt_mesh_model *corresponding_mod, - struct bt_mesh_model *base_mod); +int bt_mesh_model_correspond(const struct bt_mesh_model *corresponding_mod, + const struct bt_mesh_model *base_mod); /** @brief Check if model is extended by another model. * @@ -1107,7 +1119,7 @@ int bt_mesh_model_correspond(struct bt_mesh_model *corresponding_mod, * * @retval true If model is extended by another model, otherwise false */ -bool bt_mesh_model_is_extended(struct bt_mesh_model *model); +bool bt_mesh_model_is_extended(const struct bt_mesh_model *model); /** @brief Indicate that the composition data will change on next bootup. * @@ -1134,7 +1146,7 @@ struct bt_mesh_comp { uint16_t vid; /**< Version ID */ size_t elem_count; /**< The number of elements in this device. */ - struct bt_mesh_elem *elem; /**< List of elements. */ + const struct bt_mesh_elem *elem; /**< List of elements. */ }; /** Composition data page 2 record. */ diff --git a/include/zephyr/bluetooth/mesh/blob_cli.h b/include/zephyr/bluetooth/mesh/blob_cli.h index 3bf65beae39..8e239b31457 100644 --- a/include/zephyr/bluetooth/mesh/blob_cli.h +++ b/include/zephyr/bluetooth/mesh/blob_cli.h @@ -291,7 +291,7 @@ struct bt_mesh_blob_cli { const struct bt_mesh_blob_cli_cb *cb; /* Runtime state */ - struct bt_mesh_model *mod; + const struct bt_mesh_model *mod; struct { struct bt_mesh_blob_target *target; diff --git a/include/zephyr/bluetooth/mesh/blob_srv.h b/include/zephyr/bluetooth/mesh/blob_srv.h index 57237f1d4bb..bf807bad92f 100644 --- a/include/zephyr/bluetooth/mesh/blob_srv.h +++ b/include/zephyr/bluetooth/mesh/blob_srv.h @@ -136,7 +136,7 @@ struct bt_mesh_blob_srv { const struct bt_mesh_blob_io *io; struct k_work_delayable rx_timeout; struct bt_mesh_blob_block block; - struct bt_mesh_model *mod; + const struct bt_mesh_model *mod; enum bt_mesh_blob_xfer_phase phase; struct bt_mesh_blob_srv_state { diff --git a/include/zephyr/bluetooth/mesh/cfg_cli.h b/include/zephyr/bluetooth/mesh/cfg_cli.h index d2221da38da..0e8c26131ff 100644 --- a/include/zephyr/bluetooth/mesh/cfg_cli.h +++ b/include/zephyr/bluetooth/mesh/cfg_cli.h @@ -332,7 +332,7 @@ struct bt_mesh_cfg_cli_cb { /** Mesh Configuration Client Model Context */ struct bt_mesh_cfg_cli { /** Composition data model entry pointer. */ - struct bt_mesh_model *model; + const struct bt_mesh_model *model; /** Optional callback for Mesh Configuration Client Status messages. */ const struct bt_mesh_cfg_cli_cb *cb; @@ -1690,6 +1690,7 @@ uint16_t bt_mesh_comp_p0_elem_mod(struct bt_mesh_comp_p0_elem *elem, int idx); */ struct bt_mesh_mod_id_vnd bt_mesh_comp_p0_elem_mod_vnd(struct bt_mesh_comp_p0_elem *elem, int idx); +/** Composition data page 1 element representation */ struct bt_mesh_comp_p1_elem { /** The number of SIG models in this element */ size_t nsig; diff --git a/include/zephyr/bluetooth/mesh/dfd_srv.h b/include/zephyr/bluetooth/mesh/dfd_srv.h index 666e0d8ad3d..f15768080d7 100644 --- a/include/zephyr/bluetooth/mesh/dfd_srv.h +++ b/include/zephyr/bluetooth/mesh/dfd_srv.h @@ -210,7 +210,7 @@ struct bt_mesh_dfd_srv_cb { /** Firmware Distribution Server instance. */ struct bt_mesh_dfd_srv { const struct bt_mesh_dfd_srv_cb *cb; - struct bt_mesh_model *mod; + const struct bt_mesh_model *mod; struct bt_mesh_dfu_cli dfu; struct bt_mesh_dfu_target targets[CONFIG_BT_MESH_DFD_SRV_TARGETS_MAX]; struct bt_mesh_blob_target_pull pull_ctxs[CONFIG_BT_MESH_DFD_SRV_TARGETS_MAX]; diff --git a/include/zephyr/bluetooth/mesh/dfu_cli.h b/include/zephyr/bluetooth/mesh/dfu_cli.h index 51f534f2828..3cbc220d825 100644 --- a/include/zephyr/bluetooth/mesh/dfu_cli.h +++ b/include/zephyr/bluetooth/mesh/dfu_cli.h @@ -190,7 +190,7 @@ struct bt_mesh_dfu_cli { /* runtime state */ uint32_t op; - struct bt_mesh_model *mod; + const struct bt_mesh_model *mod; struct { const struct bt_mesh_dfu_slot *slot; diff --git a/include/zephyr/bluetooth/mesh/dfu_metadata.h b/include/zephyr/bluetooth/mesh/dfu_metadata.h index 8aea661ede7..bec65897ac7 100644 --- a/include/zephyr/bluetooth/mesh/dfu_metadata.h +++ b/include/zephyr/bluetooth/mesh/dfu_metadata.h @@ -87,7 +87,7 @@ int bt_mesh_dfu_metadata_encode(const struct bt_mesh_dfu_metadata *metadata, /** @brief Compute hash of the Composition Data state. * - * The format of the Composition Data is defined in MshPRFv1.0.1, section 4.2.1.1. + * The format of the Composition Data is defined in MshPRTv1.1: 4.2.2.1. * * @param buf Pointer to buffer holding Composition Data. * @param key 128-bit key to be used in the hash computation. diff --git a/include/zephyr/bluetooth/mesh/dfu_srv.h b/include/zephyr/bluetooth/mesh/dfu_srv.h index 53d9144713c..e136701e664 100644 --- a/include/zephyr/bluetooth/mesh/dfu_srv.h +++ b/include/zephyr/bluetooth/mesh/dfu_srv.h @@ -184,7 +184,7 @@ struct bt_mesh_dfu_srv { size_t img_count; /* Runtime state */ - struct bt_mesh_model *mod; + const struct bt_mesh_model *mod; struct { /* Effect of transfer, @see bt_mesh_dfu_effect. */ uint8_t effect; diff --git a/include/zephyr/bluetooth/mesh/health_cli.h b/include/zephyr/bluetooth/mesh/health_cli.h index 2f13dd88ccf..2d8904ea6f2 100644 --- a/include/zephyr/bluetooth/mesh/health_cli.h +++ b/include/zephyr/bluetooth/mesh/health_cli.h @@ -26,7 +26,7 @@ extern "C" { /** Health Client Model Context */ struct bt_mesh_health_cli { /** Composition data model entry pointer. */ - struct bt_mesh_model *model; + const struct bt_mesh_model *model; /** Publication structure instance */ struct bt_mesh_model_pub pub; diff --git a/include/zephyr/bluetooth/mesh/health_srv.h b/include/zephyr/bluetooth/mesh/health_srv.h index 9665e3bc62a..3eef7e459f7 100644 --- a/include/zephyr/bluetooth/mesh/health_srv.h +++ b/include/zephyr/bluetooth/mesh/health_srv.h @@ -53,7 +53,7 @@ struct bt_mesh_health_srv_cb { * * @return 0 on success, or (negative) error code otherwise. */ - int (*fault_get_cur)(struct bt_mesh_model *model, uint8_t *test_id, + int (*fault_get_cur)(const struct bt_mesh_model *model, uint8_t *test_id, uint16_t *company_id, uint8_t *faults, uint8_t *fault_count); @@ -79,7 +79,7 @@ struct bt_mesh_health_srv_cb { * * @return 0 on success, or (negative) error code otherwise. */ - int (*fault_get_reg)(struct bt_mesh_model *model, uint16_t company_id, + int (*fault_get_reg)(const struct bt_mesh_model *model, uint16_t company_id, uint8_t *test_id, uint8_t *faults, uint8_t *fault_count); @@ -91,7 +91,7 @@ struct bt_mesh_health_srv_cb { * * @return 0 on success, or (negative) error code otherwise. */ - int (*fault_clear)(struct bt_mesh_model *model, uint16_t company_id); + int (*fault_clear)(const struct bt_mesh_model *model, uint16_t company_id); /** @brief Run a self-test. * @@ -108,7 +108,7 @@ struct bt_mesh_health_srv_cb { * (negative) error code otherwise. Note that the fault array will not * be reported back to the client if the test execution didn't start. */ - int (*fault_test)(struct bt_mesh_model *model, uint8_t test_id, + int (*fault_test)(const struct bt_mesh_model *model, uint8_t test_id, uint16_t company_id); /** @brief Start calling attention to the device. @@ -125,7 +125,7 @@ struct bt_mesh_health_srv_cb { * * @param model Health Server model to start the attention state of. */ - void (*attn_on)(struct bt_mesh_model *model); + void (*attn_on)(const struct bt_mesh_model *model); /** @brief Stop the attention state. * @@ -134,7 +134,7 @@ struct bt_mesh_health_srv_cb { * * @param model */ - void (*attn_off)(struct bt_mesh_model *model); + void (*attn_off)(const struct bt_mesh_model *model); }; /** @@ -149,7 +149,7 @@ struct bt_mesh_health_srv_cb { /** Mesh Health Server Model Context */ struct bt_mesh_health_srv { /** Composition data model entry pointer. */ - struct bt_mesh_model *model; + const struct bt_mesh_model *model; /** Optional callback struct */ const struct bt_mesh_health_srv_cb *cb; @@ -219,7 +219,7 @@ struct bt_mesh_health_srv { * * @return 0 on success, or (negative) error code otherwise. */ -int bt_mesh_health_srv_fault_update(struct bt_mesh_elem *elem); +int bt_mesh_health_srv_fault_update(const struct bt_mesh_elem *elem); /** @cond INTERNAL_HIDDEN */ extern const struct bt_mesh_model_op bt_mesh_health_srv_op[]; diff --git a/include/zephyr/bluetooth/mesh/large_comp_data_cli.h b/include/zephyr/bluetooth/mesh/large_comp_data_cli.h index b7ed0776204..520fcb3a6b5 100644 --- a/include/zephyr/bluetooth/mesh/large_comp_data_cli.h +++ b/include/zephyr/bluetooth/mesh/large_comp_data_cli.h @@ -69,7 +69,7 @@ struct bt_mesh_large_comp_data_cli_cb { /** Large Composition Data Client model context */ struct bt_mesh_large_comp_data_cli { /** Model entry pointer. */ - struct bt_mesh_model *model; + const struct bt_mesh_model *model; /** Internal parameters for tracking message responses. */ struct bt_mesh_msg_ack_ctx ack_ctx; diff --git a/include/zephyr/bluetooth/mesh/main.h b/include/zephyr/bluetooth/mesh/main.h index ab274729cf8..a4e98b97f8c 100644 --- a/include/zephyr/bluetooth/mesh/main.h +++ b/include/zephyr/bluetooth/mesh/main.h @@ -1,5 +1,5 @@ /** @file - * @brief Bluetooth mesh Profile APIs. + * @brief Bluetooth mesh Protocol APIs. */ /* diff --git a/include/zephyr/bluetooth/mesh/od_priv_proxy_cli.h b/include/zephyr/bluetooth/mesh/od_priv_proxy_cli.h index f9734d78d3e..0234158b046 100644 --- a/include/zephyr/bluetooth/mesh/od_priv_proxy_cli.h +++ b/include/zephyr/bluetooth/mesh/od_priv_proxy_cli.h @@ -22,7 +22,7 @@ extern "C" { /** On-Demand Private Proxy Client Model Context */ struct bt_mesh_od_priv_proxy_cli { /** Solicitation PDU RPL model entry pointer. */ - struct bt_mesh_model *model; + const struct bt_mesh_model *model; /* Internal parameters for tracking message responses. */ struct bt_mesh_msg_ack_ctx ack_ctx; diff --git a/include/zephyr/bluetooth/mesh/priv_beacon_cli.h b/include/zephyr/bluetooth/mesh/priv_beacon_cli.h index 835dc38c773..ac77b45839f 100644 --- a/include/zephyr/bluetooth/mesh/priv_beacon_cli.h +++ b/include/zephyr/bluetooth/mesh/priv_beacon_cli.h @@ -90,7 +90,7 @@ struct bt_mesh_priv_beacon_cli_cb { /** Mesh Private Beacon Client model */ struct bt_mesh_priv_beacon_cli { - struct bt_mesh_model *model; + const struct bt_mesh_model *model; /* Internal parameters for tracking message responses. */ struct bt_mesh_msg_ack_ctx ack_ctx; @@ -101,14 +101,20 @@ struct bt_mesh_priv_beacon_cli { /** @brief Set the target's Private Beacon state. * + * This method can be used asynchronously by setting @p rsp as NULL. + * This way the method will not wait for response and will return + * immediately after sending the command. + * @param net_idx Network index to encrypt with. * @param addr Target node address. - * @param val New Private Beacon value. Returns response status on success. + * @param val New Private Beacon value. + * @param rsp If set, returns response status on success. * * @return 0 on success, or (negative) error code otherwise. */ int bt_mesh_priv_beacon_cli_set(uint16_t net_idx, uint16_t addr, - struct bt_mesh_priv_beacon *val); + struct bt_mesh_priv_beacon *val, + struct bt_mesh_priv_beacon *rsp); /** @brief Get the target's Private Beacon state. * @@ -122,16 +128,20 @@ int bt_mesh_priv_beacon_cli_get(uint16_t net_idx, uint16_t addr, struct bt_mesh_priv_beacon *val); /** @brief Set the target's Private GATT Proxy state. + * + * This method can be used asynchronously by setting @p rsp as NULL. + * This way the method will not wait for response and will return + * immediately after sending the command. * * @param net_idx Network index to encrypt with. * @param addr Target node address. - * @param val New Private GATT Proxy value. Returns response status on - * success. + * @param val New Private GATT Proxy value. + * @param rsp If set, returns response status on success. * * @return 0 on success, or (negative) error code otherwise. */ int bt_mesh_priv_beacon_cli_gatt_proxy_set(uint16_t net_idx, uint16_t addr, - uint8_t *val); + uint8_t val, uint8_t *rsp); /** @brief Get the target's Private GATT Proxy state. * @@ -145,16 +155,21 @@ int bt_mesh_priv_beacon_cli_gatt_proxy_get(uint16_t net_idx, uint16_t addr, uint8_t *val); /** @brief Set the target's Private Node Identity state. + * + * This method can be used asynchronously by setting @p rsp as NULL. + * This way the method will not wait for response and will return + * immediately after sending the command. * * @param net_idx Network index to encrypt with. * @param addr Target node address. - * @param val New Private Node Identity value. Returns response status on - * success. + * @param val New Private Node Identity value. + * @param rsp If set, returns response status on success. * * @return 0 on success, or (negative) error code otherwise. */ int bt_mesh_priv_beacon_cli_node_id_set(uint16_t net_idx, uint16_t addr, - struct bt_mesh_priv_node_id *val); + struct bt_mesh_priv_node_id *val, + struct bt_mesh_priv_node_id *rsp); /** @brief Get the target's Private Node Identity state. * diff --git a/include/zephyr/bluetooth/mesh/proxy.h b/include/zephyr/bluetooth/mesh/proxy.h index 60a397b9484..03576acf9bf 100644 --- a/include/zephyr/bluetooth/mesh/proxy.h +++ b/include/zephyr/bluetooth/mesh/proxy.h @@ -97,9 +97,9 @@ int bt_mesh_proxy_connect(uint16_t net_idx); */ int bt_mesh_proxy_disconnect(uint16_t net_idx); -/** @brief Schedule advertising of Solicitation PDUs on Proxy Client . +/** @brief Schedule advertising of Solicitation PDUs. * - * Once called Proxy Client will schedule advertising Solicitation PDUs for the amount of time + * Once called, the device will schedule advertising Solicitation PDUs for the amount of time * defined by @c adv_int * (@c CONFIG_BT_MESH_SOL_ADV_XMIT + 1), where @c adv_int is 20ms * for Bluetooth v5.0 or higher, or 100ms otherwise. * diff --git a/include/zephyr/bluetooth/mesh/rpr_cli.h b/include/zephyr/bluetooth/mesh/rpr_cli.h index 5c0374fecc3..414e2887bdf 100644 --- a/include/zephyr/bluetooth/mesh/rpr_cli.h +++ b/include/zephyr/bluetooth/mesh/rpr_cli.h @@ -91,7 +91,7 @@ struct bt_mesh_rpr_cli { enum bt_mesh_rpr_link_state state; } link; - struct bt_mesh_model *mod; + const struct bt_mesh_model *mod; }; /** @brief Get scanning capabilities of Remote Provisioning Server. diff --git a/include/zephyr/bluetooth/mesh/sar_cfg_cli.h b/include/zephyr/bluetooth/mesh/sar_cfg_cli.h index 7882174512e..5e8409d3841 100644 --- a/include/zephyr/bluetooth/mesh/sar_cfg_cli.h +++ b/include/zephyr/bluetooth/mesh/sar_cfg_cli.h @@ -27,7 +27,7 @@ extern "C" { /** Mesh SAR Configuration Client Model Context */ struct bt_mesh_sar_cfg_cli { /** Access model pointer. */ - struct bt_mesh_model *model; + const struct bt_mesh_model *model; /* Publication structure instance */ struct bt_mesh_model_pub pub; diff --git a/include/zephyr/bluetooth/mesh/sol_pdu_rpl_cli.h b/include/zephyr/bluetooth/mesh/sol_pdu_rpl_cli.h index 5a3dcdd784d..5a6c49bd211 100644 --- a/include/zephyr/bluetooth/mesh/sol_pdu_rpl_cli.h +++ b/include/zephyr/bluetooth/mesh/sol_pdu_rpl_cli.h @@ -22,7 +22,7 @@ extern "C" { /** Solicitation PDU RPL Client Model Context */ struct bt_mesh_sol_pdu_rpl_cli { /** Solicitation PDU RPL model entry pointer. */ - struct bt_mesh_model *model; + const struct bt_mesh_model *model; /* Internal parameters for tracking message responses. */ struct bt_mesh_msg_ack_ctx ack_ctx; diff --git a/include/zephyr/bluetooth/services/ots.h b/include/zephyr/bluetooth/services/ots.h index 29095642521..224731925db 100644 --- a/include/zephyr/bluetooth/services/ots.h +++ b/include/zephyr/bluetooth/services/ots.h @@ -937,6 +937,17 @@ struct bt_ots_client_cb { */ int bt_ots_client_register(struct bt_ots_client *ots_inst); +/** @brief Unregister an Object Transfer Service Instance. + * + * Unregister an Object Transfer Service instance when disconnect from the peer. + * Call this function when an ACL using OTS instance is disconnected. + * + * @param[in] index Index of OTS instance. + * + * @return int 0 if success, ERRNO on failure. + */ +int bt_ots_client_unregister(uint8_t index); + /** @brief OTS Indicate Handler function. * * Set this function as callback for indicate handler when discovering OTS. diff --git a/include/zephyr/bluetooth/testing.h b/include/zephyr/bluetooth/testing.h index 9cfda4e1177..58aae9726ff 100644 --- a/include/zephyr/bluetooth/testing.h +++ b/include/zephyr/bluetooth/testing.h @@ -39,9 +39,9 @@ struct bt_test_cb { const void *payload, size_t payload_len); void (*mesh_model_recv)(uint16_t src, uint16_t dst, const void *payload, size_t payload_len); - void (*mesh_model_bound)(uint16_t addr, struct bt_mesh_model *model, + void (*mesh_model_bound)(uint16_t addr, const struct bt_mesh_model *model, uint16_t key_idx); - void (*mesh_model_unbound)(uint16_t addr, struct bt_mesh_model *model, + void (*mesh_model_unbound)(uint16_t addr, const struct bt_mesh_model *model, uint16_t key_idx); void (*mesh_prov_invalid_bearer)(uint8_t opcode); void (*mesh_trans_incomp_timer_exp)(void); diff --git a/include/zephyr/canbus/isotp.h b/include/zephyr/canbus/isotp.h index 6ce32c48edb..222cef70a31 100644 --- a/include/zephyr/canbus/isotp.h +++ b/include/zephyr/canbus/isotp.h @@ -11,8 +11,8 @@ * ISO-TP is a transport protocol for CAN (Controller Area Network) */ -#ifndef ZEPHYR_INCLUDE_ISOTP_H_ -#define ZEPHYR_INCLUDE_ISOTP_H_ +#ifndef ZEPHYR_INCLUDE_CANBUS_ISOTP_H_ +#define ZEPHYR_INCLUDE_CANBUS_ISOTP_H_ /** * @brief CAN ISO-TP Protocol @@ -34,10 +34,16 @@ * DLC Data length code * FC Flow Control * FF First Frame + * SF Single Frame * FS Flow Status * AE Address Extension + * SN Sequence Number + * ST Separation time * SA Source Address * TA Target Address + * RX_DL CAN RX LL data size + * TX_DL CAN TX LL data size + * PCI Process Control Information */ /* @@ -128,6 +134,33 @@ extern "C" { #endif +/** + * @name ISO-TP message ID flags + * @anchor ISOTP_MSG_FLAGS + * + * @{ + */ + +/** Message uses ISO-TP extended addressing (first payload byte of CAN frame) */ +#define ISOTP_MSG_EXT_ADDR BIT(0) + +/** + * Message uses ISO-TP fixed addressing (according to SAE J1939). Only valid in combination with + * ``ISOTP_MSG_IDE``. + */ +#define ISOTP_MSG_FIXED_ADDR BIT(1) + +/** Message uses extended (29-bit) CAN ID */ +#define ISOTP_MSG_IDE BIT(2) + +/** Message uses CAN FD format (FDF) */ +#define ISOTP_MSG_FDF BIT(3) + +/** Message uses CAN FD Baud Rate Switch (BRS). Only valid in combination with ``ISOTP_MSG_FDF``. */ +#define ISOTP_MSG_BRS BIT(4) + +/** @} */ + /** * @brief ISO-TP message id struct * @@ -146,12 +179,19 @@ struct isotp_msg_id { }; /** ISO-TP extended address (if used) */ uint8_t ext_addr; - /** Indicates the CAN identifier type (0 for standard or 1 for extended) */ - uint8_t ide : 1; - /** Indicates if ISO-TP extended addressing is used */ - uint8_t use_ext_addr : 1; - /** Indicates if ISO-TP fixed addressing (acc. to SAE J1939) is used */ - uint8_t use_fixed_addr : 1; + /** + * ISO-TP frame data length (TX_DL for TX address or RX_DL for RX address). + * + * Valid values are 8 for classical CAN or 8, 12, 16, 20, 24, 32, 48 and 64 for CAN FD. + * + * 0 will be interpreted as 8 or 64 (if ISOTP_MSG_FDF is set). + * + * The value for incoming transmissions (RX_DL) is determined automatically based on the + * received first frame and does not need to be set during initialization. + */ + uint8_t dl; + /** Flags. @see @ref ISOTP_MSG_FLAGS. */ + uint8_t flags; }; /* @@ -194,7 +234,7 @@ struct isotp_recv_ctx; * When calling this routine, a filter is applied in the CAN device, and the * context is initialized. The context must be valid until calling unbind. * - * @param ctx Context to store the internal states. + * @param rctx Context to store the internal states. * @param can_dev The CAN device to be used for sending and receiving. * @param rx_addr Identifier for incoming data. * @param tx_addr Identifier for FC frames. @@ -204,7 +244,7 @@ struct isotp_recv_ctx; * @retval ISOTP_N_OK on success * @retval ISOTP_NO_FREE_FILTER if CAN device has no filters left. */ -int isotp_bind(struct isotp_recv_ctx *ctx, const struct device *can_dev, +int isotp_bind(struct isotp_recv_ctx *rctx, const struct device *can_dev, const struct isotp_msg_id *rx_addr, const struct isotp_msg_id *tx_addr, const struct isotp_fc_opts *opts, @@ -218,9 +258,9 @@ int isotp_bind(struct isotp_recv_ctx *ctx, const struct device *can_dev, * buffers are freed. * The context can be discarded safely after calling this function. * - * @param ctx Context that should be unbound. + * @param rctx Context that should be unbound. */ -void isotp_unbind(struct isotp_recv_ctx *ctx); +void isotp_unbind(struct isotp_recv_ctx *rctx); /** * @brief Read out received data from fifo. @@ -230,7 +270,7 @@ void isotp_unbind(struct isotp_recv_ctx *ctx); * If an error occurs, the function returns a negative number and leaves the * data buffer unchanged. * - * @param ctx Context that is already bound. + * @param rctx Context that is already bound. * @param data Pointer to a buffer where the data is copied to. * @param len Size of the buffer. * @param timeout Timeout for incoming data. @@ -239,8 +279,7 @@ void isotp_unbind(struct isotp_recv_ctx *ctx); * @retval ISOTP_RECV_TIMEOUT when "timeout" timed out * @retval ISOTP_N_* on error */ -int isotp_recv(struct isotp_recv_ctx *ctx, uint8_t *data, size_t len, - k_timeout_t timeout); +int isotp_recv(struct isotp_recv_ctx *rctx, uint8_t *data, size_t len, k_timeout_t timeout); /** * @brief Get the net buffer on data reception @@ -252,7 +291,7 @@ int isotp_recv(struct isotp_recv_ctx *ctx, uint8_t *data, size_t len, * The net-buffers are referenced and must be freed with net_buf_unref after the * data is processed. * - * @param ctx Context that is already bound. + * @param rctx Context that is already bound. * @param buffer Pointer where the net_buf pointer is written to. * @param timeout Timeout for incoming data. * @@ -260,8 +299,7 @@ int isotp_recv(struct isotp_recv_ctx *ctx, uint8_t *data, size_t len, * @retval ISOTP_RECV_TIMEOUT when "timeout" timed out * @retval ISOTP_N_* on error */ -int isotp_recv_net(struct isotp_recv_ctx *ctx, struct net_buf **buffer, - k_timeout_t timeout); +int isotp_recv_net(struct isotp_recv_ctx *rctx, struct net_buf **buffer, k_timeout_t timeout); /** * @brief Send data @@ -272,7 +310,7 @@ int isotp_recv_net(struct isotp_recv_ctx *ctx, struct net_buf **buffer, * If a complete_cb is given, this function is non-blocking, and the callback * is called on completion with the return value as a parameter. * - * @param ctx Context to store the internal states. + * @param sctx Context to store the internal states. * @param can_dev The CAN device to be used for sending and receiving. * @param data Data to be sent. * @param len Length of the data to be sent. @@ -284,7 +322,7 @@ int isotp_recv_net(struct isotp_recv_ctx *ctx, struct net_buf **buffer, * @retval ISOTP_N_OK on success * @retval ISOTP_N_* on error */ -int isotp_send(struct isotp_send_ctx *ctx, const struct device *can_dev, +int isotp_send(struct isotp_send_ctx *sctx, const struct device *can_dev, const uint8_t *data, size_t len, const struct isotp_msg_id *tx_addr, const struct isotp_msg_id *rx_addr, @@ -442,4 +480,4 @@ struct isotp_recv_ctx { } #endif -#endif /* ZEPHYR_INCLUDE_ISOTP_H_ */ +#endif /* ZEPHYR_INCLUDE_CANBUS_ISOTP_H_ */ diff --git a/include/zephyr/data/navigation.h b/include/zephyr/data/navigation.h new file mode 100644 index 00000000000..0759df984ea --- /dev/null +++ b/include/zephyr/data/navigation.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DATA_NAVIGATION_H_ +#define ZEPHYR_INCLUDE_DATA_NAVIGATION_H_ + +#include + +/** + * @brief Navigation utilities + * @defgroup navigation Navigation + * @ingroup utilities + * @{ + */ + +/** + * @brief Navigation data structure + * + * @details The structure describes the momentary navigation details of a + * point relative to a sphere (commonly Earth) + */ +struct navigation_data { + /** Latitudal position in nanodegrees (0 to +-180E9) */ + int64_t latitude; + /** Longitudal position in nanodegrees (0 to +-180E9) */ + int64_t longitude; + /** Bearing angle in millidegrees (0 to 360E3) */ + uint32_t bearing; + /** Speed in millimeters per second */ + uint32_t speed; + /** Altitude in millimeters */ + int32_t altitude; +}; + +/** + * @brief Calculate the distance between two navigation points along the + * surface of the sphere they are relative to. + * + * @param distance Destination for calculated distance in millimeters + * @param p1 First navigation point + * @param p2 Second navigation point + * + * @return 0 if successful + * @return -EINVAL if either navigation point is invalid + */ +int navigation_distance(uint64_t *distance, const struct navigation_data *p1, + const struct navigation_data *p2); + +/** + * @brief Calculate the bearing from one navigation point to another + * + * @param bearing Destination for calculated bearing angle in millidegrees + * @param from First navigation point + * @param to Second navigation point + * + * @return 0 if successful + * @return -EINVAL if either navigation point is invalid + */ +int navigation_bearing(uint32_t *bearing, const struct navigation_data *from, + const struct navigation_data *to); + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_DATA_NAVIGATION_H_ */ diff --git a/include/zephyr/device.h b/include/zephyr/device.h index ce9b6c1312e..630a059c155 100644 --- a/include/zephyr/device.h +++ b/include/zephyr/device.h @@ -118,8 +118,8 @@ typedef int16_t device_handle_t; * stored in @ref device.data. * @param config Pointer to the device's private constant data, which will be * stored in @ref device.config. - * @param level The device's initialization level. See @ref sys_init for - * details. + * @param level The device's initialization level (PRE_KERNEL_1, PRE_KERNEL_2 or + * POST_KERNEL). * @param prio The device's priority within its initialization level. See * SYS_INIT() for details. * @param api Pointer to the device's API structure. Can be `NULL`. @@ -169,7 +169,8 @@ typedef int16_t device_handle_t; * stored in @ref device.data. * @param config Pointer to the device's private constant data, which will be * stored in @ref device.config field. - * @param level The device's initialization level. See SYS_INIT() for details. + * @param level The device's initialization level (PRE_KERNEL_1, PRE_KERNEL_2 or + * POST_KERNEL). * @param prio The device's priority within its initialization level. See * SYS_INIT() for details. * @param api Pointer to the device's API structure. Can be `NULL`. @@ -931,6 +932,25 @@ static inline bool z_impl_device_is_ready(const struct device *dev) DEVICE_NAME_GET(dev_id)) = \ Z_DEVICE_INIT(name, pm, data, config, api, state, deps) +/* deprecated device initialization levels */ +#define Z_DEVICE_LEVEL_DEPRECATED_EARLY \ + __WARN("EARLY device driver level is deprecated") +#define Z_DEVICE_LEVEL_DEPRECATED_PRE_KERNEL_1 +#define Z_DEVICE_LEVEL_DEPRECATED_PRE_KERNEL_2 +#define Z_DEVICE_LEVEL_DEPRECATED_POST_KERNEL +#define Z_DEVICE_LEVEL_DEPRECATED_APPLICATION \ + __WARN("APPLICATION device driver level is deprecated") +#define Z_DEVICE_LEVEL_DEPRECATED_SMP \ + __WARN("SMP device driver level is deprecated") + +/** + * @brief Issue a warning if the given init level is deprecated. + * + * @param level Init level + */ +#define Z_DEVICE_LEVEL_CHECK_DEPRECATED_LEVEL(level) \ + Z_DEVICE_LEVEL_DEPRECATED_##level + /** * @brief Define the init entry for a device. * @@ -942,6 +962,8 @@ static inline bool z_impl_device_is_ready(const struct device *dev) * @param prio Initialization priority. */ #define Z_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, init_fn_, level, prio) \ + Z_DEVICE_LEVEL_CHECK_DEPRECATED_LEVEL(level) \ + \ static const Z_DECL_ALIGN(struct init_entry) __used __noasan \ Z_INIT_ENTRY_SECTION(level, prio, \ Z_DEVICE_INIT_SUB_PRIO(node_id)) \ @@ -983,7 +1005,6 @@ static inline bool z_impl_device_is_ready(const struct device *dev) \ Z_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, init_fn, level, prio) -#if defined(CONFIG_HAS_DTS) || defined(__DOXYGEN__) /** * @brief Declare a device for each status "okay" devicetree node. * @@ -998,7 +1019,6 @@ static inline bool z_impl_device_is_ready(const struct device *dev) extern const struct device DEVICE_DT_NAME_GET(node_id); DT_FOREACH_STATUS_OKAY_NODE(Z_MAYBE_DEVICE_DECLARE_INTERNAL) -#endif /* CONFIG_HAS_DTS */ /** @endcond */ diff --git a/include/zephyr/devicetree.h b/include/zephyr/devicetree.h index ff0ecb0a33f..017bcab442a 100644 --- a/include/zephyr/devicetree.h +++ b/include/zephyr/devicetree.h @@ -17,6 +17,7 @@ #define DEVICETREE_H #include +#include #if !defined(_LINKER) && !defined(_ASMLANGUAGE) #include @@ -2409,6 +2410,77 @@ */ #define DT_IRQ(node_id, cell) DT_IRQ_BY_IDX(node_id, 0, cell) +/** + * @cond INTERNAL_HIDDEN + */ + +/* DT helper macro to get interrupt-parent node */ +#define DT_PARENT_INTC_INTERNAL(node_id) DT_PROP(node_id, interrupt_parent) +/* DT helper macro to get the node's interrupt grandparent node */ +#define DT_GPARENT_INTC_INTERNAL(node_id) DT_PARENT_INTC_INTERNAL(DT_PARENT_INTC_INTERNAL(node_id)) +/* DT helper macro to check if a node is an interrupt controller */ +#define DT_IS_INTC_INTERNAL(node_id) DT_NODE_HAS_PROP(node_id, interrupt_controller) +/* DT helper macro to check if the node has a parent interrupt controller */ +#define DT_HAS_PARENT_INTC_INTERNAL(node_id) \ + /* node has `interrupt-parent`? */ \ + IF_ENABLED(DT_NODE_HAS_PROP(node_id, interrupt_parent), \ + /* `interrupt-parent` node is an interrupt controller? */ \ + (IF_ENABLED(DT_IS_INTC_INTERNAL(DT_PARENT_INTC_INTERNAL(node_id)), \ + /* `interrupt-parent` node has interrupt cell(s) ? 1 : 0 */ \ + (COND_CODE_0(DT_NUM_IRQS(DT_PARENT_INTC_INTERNAL(node_id)), (0), \ + (1)))))) +/* DT helper macro to check if the node has a grandparent interrupt controller */ +#define DT_HAS_GPARENT_INTC_INTERNAL(node_id) \ + IF_ENABLED(DT_HAS_PARENT_INTC_INTERNAL(node_id), \ + (DT_HAS_PARENT_INTC_INTERNAL(DT_PARENT_INTC_INTERNAL(node_id)))) + +/** + * DT helper macro to get the as-seen interrupt number in devicetree, + * or ARM GIC IRQ encoded output from `gen_defines.py` + */ +#define DT_IRQN_BY_IDX_INTERNAL(node_id, idx) DT_IRQ_BY_IDX(node_id, idx, irq) + +/* DT helper macro to get the node's parent intc's (only) irq number */ +#define DT_PARENT_INTC_IRQN_INTERNAL(node_id) DT_IRQ(DT_PARENT_INTC_INTERNAL(node_id), irq) +/* DT helper macro to get the node's grandparent intc's (only) irq number */ +#define DT_GPARENT_INTC_IRQN_INTERNAL(node_id) DT_IRQ(DT_GPARENT_INTC_INTERNAL(node_id), irq) + +/* DT helper macro to encode a node's IRQN to level 2 according to the multi-level scheme */ +#define DT_IRQN_L2_INTERNAL(node_id, idx) \ + (IRQ_TO_L2(DT_IRQN_BY_IDX_INTERNAL(node_id, idx)) | \ + DT_PARENT_INTC_IRQN_INTERNAL(node_id)) +/* DT helper macro to encode a node's IRQN to level 3 according to the multi-level scheme */ +#define DT_IRQN_L3_INTERNAL(node_id, idx) \ + (IRQ_TO_L3(DT_IRQN_BY_IDX_INTERNAL(node_id, idx)) | \ + IRQ_TO_L2(DT_PARENT_INTC_IRQN_INTERNAL(node_id)) | \ + DT_GPARENT_INTC_IRQN_INTERNAL(node_id)) +/** + * DT helper macro to encode a node's interrupt number according to the Zephyr's multi-level scheme + * See doc/kernel/services/interrupts.rst for details + */ +#define DT_MULTI_LEVEL_IRQN_INTERNAL(node_id, idx) \ + COND_CODE_1(DT_HAS_GPARENT_INTC_INTERNAL(node_id), (DT_IRQN_L3_INTERNAL(node_id, idx)), \ + (COND_CODE_1(DT_HAS_PARENT_INTC_INTERNAL(node_id), \ + (DT_IRQN_L2_INTERNAL(node_id, idx)), \ + (DT_IRQN_BY_IDX_INTERNAL(node_id, idx))))) + +/** + * INTERNAL_HIDDEN @endcond + */ + +/** + * @brief Get the node's Zephyr interrupt number at index + * If @kconfig{CONFIG_MULTI_LEVEL_INTERRUPTS} is enabled, the interrupt number at index will be + * multi-level encoded + * @param node_id node identifier + * @param idx logical index into the interrupt specifier array + * @return the Zephyr interrupt number + */ +#define DT_IRQN_BY_IDX(node_id, idx) \ + COND_CODE_1(IS_ENABLED(CONFIG_MULTI_LEVEL_INTERRUPTS), \ + (DT_MULTI_LEVEL_IRQN_INTERNAL(node_id, idx)), \ + (DT_IRQN_BY_IDX_INTERNAL(node_id, idx))) + /** * @brief Get a node's (only) irq number * @@ -2419,7 +2491,7 @@ * @param node_id node identifier * @return the interrupt number for the node's only interrupt */ -#define DT_IRQN(node_id) DT_IRQ(node_id, irq) +#define DT_IRQN(node_id) DT_IRQN_BY_IDX(node_id, 0) /** * @} @@ -2797,7 +2869,6 @@ * * @code{.c} * struct gpio_dt_spec specs[] = { - * struct gpio_dt_spec specs[] = { * GPIO_DT_SPEC_GET_BY_IDX(DT_NODELABEL(n), my_gpios, 0), * GPIO_DT_SPEC_GET_BY_IDX(DT_NODELABEL(n), my_gpios, 1) * }; @@ -3826,7 +3897,15 @@ * @param inst instance number * @return the interrupt number for the node's only interrupt */ -#define DT_INST_IRQN(inst) DT_INST_IRQ(inst, irq) +#define DT_INST_IRQN(inst) DT_IRQN(DT_DRV_INST(inst)) + +/** + * @brief Get a `DT_DRV_COMPAT`'s irq number at index + * @param inst instance number + * @param idx logical index into the interrupt specifier array + * @return the interrupt number for the node's idx-th interrupt + */ +#define DT_INST_IRQN_BY_IDX(inst, idx) DT_IRQN_BY_IDX(DT_DRV_INST(inst), idx) /** * @brief Get a `DT_DRV_COMPAT`'s bus node identifier @@ -3888,6 +3967,39 @@ #define DT_INST_STRING_UNQUOTED_OR(inst, name, default_value) \ DT_STRING_UNQUOTED_OR(DT_DRV_INST(inst), name, default_value) +/* + * @brief Test if any enabled node with the given compatible is on + * the given bus type + * + * This is like DT_ANY_INST_ON_BUS_STATUS_OKAY(), except it can also + * be useful for handling multiple compatibles in single source file. + * + * Example devicetree overlay: + * + * @code{.dts} + * &i2c0 { + * temp: temperature-sensor@76 { + * compatible = "vnd,some-sensor"; + * reg = <0x76>; + * }; + * }; + * @endcode + * + * Example usage, assuming `i2c0` is an I2C bus controller node, and + * therefore `temp` is on an I2C bus: + * + * @code{.c} + * DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(vnd_some_sensor, i2c) // 1 + * @endcode + * + * @param compat lowercase-and-underscores compatible, without quotes + * @param bus a binding's bus type as a C token, lowercased and without quotes + * @return 1 if any enabled node with that compatible is on that bus type, + * 0 otherwise + */ +#define DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(compat, bus) \ + IS_ENABLED(UTIL_CAT(DT_CAT(DT_COMPAT_, compat), _BUS_##bus)) + /** * @brief Test if any `DT_DRV_COMPAT` node is on a bus of a given type * and has status okay @@ -3921,7 +4033,7 @@ * 0 otherwise */ #define DT_ANY_INST_ON_BUS_STATUS_OKAY(bus) \ - DT_COMPAT_ON_BUS_INTERNAL(DT_DRV_COMPAT, bus) + DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(DT_DRV_COMPAT, bus) /** * @brief Check if any `DT_DRV_COMPAT` node with status `okay` has a given @@ -4253,9 +4365,6 @@ /** @brief Helper for DT_NODE_HAS_STATUS */ #define DT_NODE_HAS_STATUS_INTERNAL(node_id, status) \ IS_ENABLED(DT_CAT3(node_id, _STATUS_, status)) -/** @brief Helper for test cases and DT_ANY_INST_ON_BUS_STATUS_OKAY() */ -#define DT_COMPAT_ON_BUS_INTERNAL(compat, bus) \ - IS_ENABLED(UTIL_CAT(DT_CAT(DT_COMPAT_, compat), _BUS_##bus)) /** @brief Helper macro to OR multiple has property checks in a loop macro */ #define DT_INST_NODE_HAS_PROP_AND_OR(inst, prop) \ @@ -4286,6 +4395,5 @@ #include #include #include -#include #endif /* DEVICETREE_H */ diff --git a/include/zephyr/devicetree/memory-attr.h b/include/zephyr/devicetree/memory-attr.h deleted file mode 100644 index 65fcfe0ca50..00000000000 --- a/include/zephyr/devicetree/memory-attr.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2023 Carlo Caione - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_INCLUDE_MEMORY_ATTR_H_ -#define ZEPHYR_INCLUDE_MEMORY_ATTR_H_ - -#include -#include -#include - -/** - * @file - * @brief Memory-attr helpers - */ - -/** - * @defgroup devicetree-memory-attr Memory attributes - * @ingroup devicetree - * @{ - */ - -/** @cond INTERNAL_HIDDEN */ - -#define _DT_MEM_ATTR zephyr_memory_attr -#define _DT_ATTR(token) UTIL_CAT(UTIL_CAT(REGION_, token), _ATTR) - -#define _UNPACK(node_id, fn) \ - fn(COND_CODE_1(DT_NODE_HAS_PROP(node_id, zephyr_memory_region), \ - (LINKER_DT_NODE_REGION_NAME(node_id)), \ - (DT_NODE_FULL_NAME(node_id))), \ - DT_REG_ADDR(node_id), \ - DT_REG_SIZE(node_id), \ - _DT_ATTR(DT_STRING_TOKEN(node_id, _DT_MEM_ATTR))), - -#define _APPLY(node_id, fn) \ - COND_CODE_1(DT_NODE_HAS_PROP(node_id, _DT_MEM_ATTR), \ - (_UNPACK(node_id, fn)), \ - ()) - - -#define _FILTER(node_id, fn) \ - COND_CODE_1(DT_NODE_HAS_PROP(node_id, _DT_MEM_ATTR), \ - (fn(node_id)), \ - ()) - -/** @endcond */ - -/** - * @brief Invokes @p fn for every node in the tree with property - * `zephyr,memory-attr` - * - * The macro @p fn must take one parameter, which will be a node identifier - * with the `zephyr,memory-attr` property. The macro is expanded once for each - * node in the tree. The order that nodes are visited in is not specified. - * - * @param fn macro to invoke - */ -#define DT_MEMORY_ATTR_FOREACH_NODE(fn) \ - DT_FOREACH_STATUS_OKAY_NODE_VARGS(_FILTER, fn) - -/** - * @brief Invokes @p fn for MPU/MMU regions generation from the device tree - * nodes with `zephyr,memory-attr` property. - * - * Helper macro to invoke a @p fn macro on all the memory regions declared - * using the `zephyr,memory-attr` property - * - * The macro @p fn must take the form: - * - * @code{.c} - * #define MPU_FN(name, base, size, attr) ... - * @endcode - * - * The @p name, @p base and @p size parameters are retrieved from the DT node. - * When the `zephyr,memory-region` property is present in the node, the @p name - * parameter is retrived from there, otherwise the full node name is used. - * - * The `zephyr,memory-attr` enum property is passed as an extended token - * to the @p fn macro using the @p attr parameter in the form of a macro - * REGION_{attr}_ATTR. - * - * The following enums are supported for the `zephyr,memory-attr` property (see - * `zephyr,memory-attr.yaml` for a complete list): - * - * - RAM - * - RAM_NOCACHE - * - FLASH - * - PPB - * - IO - * - EXTMEM - * - * This means that usually the user code would provide some macros or defines - * with the same name of the extended property, that is: - * - * - REGION_RAM_ATTR - * - REGION_RAM_NOCACHE_ATTR - * - REGION_FLASH_ATTR - * - REGION_PPB_ATTR - * - REGION_IO_ATTR - * - REGION_EXTMEM_ATTR - * - * Example devicetree fragment: - * - * @code{.dts} - * / { - * soc { - * res0: memory@20000000 { - * reg = <0x20000000 0x4000>; - * zephyr,memory-region = "MY_NAME"; - * zephyr,memory-attr = "RAM_NOCACHE"; - * }; - * - * res1: memory@30000000 { - * reg = <0x30000000 0x2000>; - * zephyr,memory-attr = "RAM"; - * }; - - * }; - * }; - * @endcode - * - * Example usage: - * - * @code{.c} - * #define REGION_RAM_NOCACHE_ATTR 0xAAAA - * #define REGION_RAM_ATTR 0xBBBB - * #define REGION_FLASH_ATTR 0xCCCC - * - * #define MPU_FN(p_name, p_base, p_size, p_attr) \ - * { \ - * .name = p_name, \ - * .base = p_base, \ - * .size = p_size, \ - * .attr = p_attr, \ - * } - * - * static const struct arm_mpu_region mpu_regions[] = { - * DT_MEMORY_ATTR_APPLY(MPU_FN) - * }; - * @endcode - * - * This expands to: - * - * @code{.c} - * static const struct arm_mpu_region mpu_regions[] = { - * { "MY_NAME", 0x20000000, 0x4000, 0xAAAA }, - * { "memory@30000000", 0x30000000, 0x2000, 0xBBBB }, - * }; - * @endcode - * - * @param fn macro to invoke - */ -#define DT_MEMORY_ATTR_APPLY(fn) \ - DT_FOREACH_STATUS_OKAY_NODE_VARGS(_APPLY, fn) - -/** - * @} - */ - -#endif /* ZEPHYR_INCLUDE_MEMORY_ATTR_H_ */ diff --git a/include/zephyr/drivers/adc.h b/include/zephyr/drivers/adc.h index d7e11bbee9b..989ec79ce11 100644 --- a/include/zephyr/drivers/adc.h +++ b/include/zephyr/drivers/adc.h @@ -681,6 +681,21 @@ static inline int z_impl_adc_read(const struct device *dev, return api->read(dev, sequence); } +/** + * @brief Set a read request from a struct adc_dt_spec. + * + * @param spec ADC specification from Devicetree. + * @param sequence Structure specifying requested sequence of samplings. + * + * @return A value from adc_read(). + * @see adc_read() + */ +static inline int adc_read_dt(const struct adc_dt_spec *spec, + const struct adc_sequence *sequence) +{ + return adc_read(spec->dev, sequence); +} + /** * @brief Set an asynchronous read request. * diff --git a/include/zephyr/drivers/adc/adc_npcx_threshold.h b/include/zephyr/drivers/adc/adc_npcx_threshold.h index 0d2b3954a44..4254baa4582 100644 --- a/include/zephyr/drivers/adc/adc_npcx_threshold.h +++ b/include/zephyr/drivers/adc/adc_npcx_threshold.h @@ -41,13 +41,15 @@ struct adc_npcx_threshold_param { * @note This function is available only if @kconfig{CONFIG_ADC_CMP_NPCX} * is selected. * + * @param dev Pointer to the device structure for the driver instance. * @param val_mv Input value in millivolts to be converted. * @param thrval Pointer of variable to hold the result of conversion. * * @returns 0 on success, negative result if input cannot be converted due to * overflow. */ -int adc_npcx_threshold_mv_to_thrval(uint32_t val_mv, uint32_t *thrval); +int adc_npcx_threshold_mv_to_thrval(const struct device *dev, uint32_t val_mv, + uint32_t *thrval); /** * @brief Set ADC threshold parameter. diff --git a/include/zephyr/drivers/adc/current_sense_amplifier.h b/include/zephyr/drivers/adc/current_sense_amplifier.h index 6035eeb4ed2..888167b1ae9 100644 --- a/include/zephyr/drivers/adc/current_sense_amplifier.h +++ b/include/zephyr/drivers/adc/current_sense_amplifier.h @@ -8,12 +8,14 @@ #define ZEPHYR_INCLUDE_DRIVERS_ADC_CURRENT_SENSE_AMPLIFIER_H_ #include +#include struct current_sense_amplifier_dt_spec { const struct adc_dt_spec port; uint32_t sense_micro_ohms; uint32_t sense_gain_mult; uint32_t sense_gain_div; + struct gpio_dt_spec power_gpio; }; /** @@ -32,6 +34,7 @@ struct current_sense_amplifier_dt_spec { .sense_micro_ohms = DT_PROP(node_id, sense_resistor_micro_ohms), \ .sense_gain_mult = DT_PROP(node_id, sense_gain_mult), \ .sense_gain_div = DT_PROP(node_id, sense_gain_div), \ + .power_gpio = GPIO_DT_SPEC_GET_OR(node_id, power_gpios, {0}), \ } /** diff --git a/include/zephyr/drivers/bluetooth/hci_driver.h b/include/zephyr/drivers/bluetooth/hci_driver.h index b0b310dc265..b318ad55ffb 100644 --- a/include/zephyr/drivers/bluetooth/hci_driver.h +++ b/include/zephyr/drivers/bluetooth/hci_driver.h @@ -89,6 +89,8 @@ static inline uint8_t bt_hci_evt_get_flags(uint8_t evt) * for so-called high priority HCI events, which should instead be delivered to * the host stack through bt_recv_prio(). * + * @note This function must only be called from a cooperative thread. + * * @param buf Network buffer containing data from the controller. * * @return 0 on success or negative error number on failure. @@ -240,6 +242,19 @@ int bt_hci_driver_register(const struct bt_hci_driver *drv); */ int bt_hci_transport_setup(const struct device *dev); +/** + * @brief Teardown the HCI transport. + * + * @note A weak version of this function is included in the IPC driver, so + * defining it is optional. NRF5340 includes support to put network core + * in reset state. + * + * @param dev The device structure for the bus connecting to the IC + * + * @return 0 on success, negative error value on faulure + */ +int bt_hci_transport_teardown(const struct device *dev); + /** Allocate an HCI event buffer. * * This function allocates a new buffer for an HCI event. It is given the diff --git a/include/zephyr/drivers/can.h b/include/zephyr/drivers/can.h index 44f4b360689..0028abb330d 100644 --- a/include/zephyr/drivers/can.h +++ b/include/zephyr/drivers/can.h @@ -6,6 +6,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** + * @file + * @brief Controller Area Network (CAN) driver API. + */ + #ifndef ZEPHYR_INCLUDE_DRIVERS_CAN_H_ #define ZEPHYR_INCLUDE_DRIVERS_CAN_H_ @@ -55,7 +60,7 @@ extern "C" { */ #define CAN_MAX_DLC 8U /** - * @brief Maximum data length code for CAN-FD. + * @brief Maximum data length code for CAN FD. */ #define CANFD_MAX_DLC 15U @@ -89,7 +94,7 @@ extern "C" { /** Controller is not allowed to send dominant bits. */ #define CAN_MODE_LISTENONLY BIT(1) -/** Controller allows transmitting/receiving CAN-FD frames. */ +/** Controller allows transmitting/receiving CAN FD frames. */ #define CAN_MODE_FD BIT(2) /** Controller does not retransmit in case of lost arbitration or missing ACK */ @@ -139,13 +144,13 @@ enum can_state { /** Frame is a Remote Transmission Request (RTR) */ #define CAN_FRAME_RTR BIT(1) -/** Frame uses CAN-FD format (FDF) */ +/** Frame uses CAN FD format (FDF) */ #define CAN_FRAME_FDF BIT(2) -/** Frame uses CAN-FD Baud Rate Switch (BRS). Only valid in combination with ``CAN_FRAME_FDF``. */ +/** Frame uses CAN FD Baud Rate Switch (BRS). Only valid in combination with ``CAN_FRAME_FDF``. */ #define CAN_FRAME_BRS BIT(3) -/** CAN-FD Error State Indicator (ESI). Indicates that the transmitting node is in error-passive +/** CAN FD Error State Indicator (ESI). Indicates that the transmitting node is in error-passive * state. Only valid in combination with ``CAN_FRAME_FDF``. */ #define CAN_FRAME_ESI BIT(4) @@ -181,7 +186,9 @@ struct can_frame { #endif /** The frame payload data. */ union { + /** Payload data accessed as unsigned 8 bit values. */ uint8_t data[CAN_MAX_DLEN]; + /** Payload data accessed as unsigned 32 bit values. */ uint32_t data_32[DIV_ROUND_UP(CAN_MAX_DLEN, sizeof(uint32_t))]; }; }; @@ -202,7 +209,7 @@ struct can_frame { /** Filter matches data frames */ #define CAN_FILTER_DATA BIT(2) -/** Filter matches CAN-FD frames (FDF) */ +/** Filter matches CAN FD frames (FDF) */ #define CAN_FILTER_FDF BIT(3) /** @} */ @@ -234,11 +241,6 @@ struct can_bus_err_cnt { uint8_t rx_err_cnt; }; -/** Synchronization Jump Width (SJW) value to indicate that the SJW should not - * be changed by the timing calculation. - */ -#define CAN_SJW_NO_CHANGE 0 - /** * @brief CAN bus timing structure * @@ -331,7 +333,7 @@ typedef int (*can_set_timing_t)(const struct device *dev, const struct can_timing *timing); /** - * @brief Optional callback API upon setting CAN-FD bus timing for the data phase. + * @brief Optional callback API upon setting CAN FD bus timing for the data phase. * See @a can_set_timing_data() for argument description */ typedef int (*can_set_timing_data_t)(const struct device *dev, @@ -466,6 +468,7 @@ __subsystem struct can_driver_api { /** @cond INTERNAL_HIDDEN */ STATS_SECT_START(can) +STATS_SECT_ENTRY32(bit_error) STATS_SECT_ENTRY32(bit0_error) STATS_SECT_ENTRY32(bit1_error) STATS_SECT_ENTRY32(stuff_error) @@ -476,6 +479,7 @@ STATS_SECT_ENTRY32(rx_overrun) STATS_SECT_END; STATS_NAME_START(can) +STATS_NAME(can, bit_error) STATS_NAME(can, bit0_error) STATS_NAME(can, bit1_error) STATS_NAME(can, stuff_error) @@ -492,7 +496,9 @@ STATS_NAME_END(can); * additions */ struct can_device_state { + /** Common device state. */ struct device_state devstate; + /** CAN device statistics */ struct stats_can stats; }; @@ -506,16 +512,41 @@ struct can_device_state { /** @endcond */ +/** + * @brief Increment the bit error counter for a CAN device + * + * The bit error counter is incremented when the CAN controller is unable to + * transmit either a dominant or a recessive bit. + * + * @note This error counter should only be incremented if the CAN controller is unable to + * distinquish between failure to transmit a dominant versus failure to transmit a recessive bit. If + * the CAN controller supports distinguishing between the two, the `bit0` or `bit1` error counter + * shall be incremented instead. + * + * @see CAN_STATS_BIT0_ERROR_INC() + * @see CAN_STATS_BIT1_ERROR_INC() + * + * @param dev_ Pointer to the device structure for the driver instance. + */ +#define CAN_STATS_BIT_ERROR_INC(dev_) \ + STATS_INC(Z_CAN_GET_STATS(dev_), bit_error) + /** * @brief Increment the bit0 error counter for a CAN device * * The bit0 error counter is incremented when the CAN controller is unable to * transmit a dominant bit. * + * Incrementing this counter will automatically increment the bit error counter. + * @see CAN_STATS_BIT_ERROR_INC() + * * @param dev_ Pointer to the device structure for the driver instance. */ -#define CAN_STATS_BIT0_ERROR_INC(dev_) \ - STATS_INC(Z_CAN_GET_STATS(dev_), bit0_error) +#define CAN_STATS_BIT0_ERROR_INC(dev_) \ + do { \ + STATS_INC(Z_CAN_GET_STATS(dev_), bit0_error); \ + CAN_STATS_BIT_ERROR_INC(dev_); \ + } while (0) /** * @brief Increment the bit1 (recessive) error counter for a CAN device @@ -523,10 +554,16 @@ struct can_device_state { * The bit1 error counter is incremented when the CAN controller is unable to * transmit a recessive bit. * + * Incrementing this counter will automatically increment the bit error counter. + * @see CAN_STATS_BIT_ERROR_INC() + * * @param dev_ Pointer to the device structure for the driver instance. */ -#define CAN_STATS_BIT1_ERROR_INC(dev_) \ - STATS_INC(Z_CAN_GET_STATS(dev_), bit1_error) +#define CAN_STATS_BIT1_ERROR_INC(dev_) \ + do { \ + STATS_INC(Z_CAN_GET_STATS(dev_), bit1_error); \ + CAN_STATS_BIT_ERROR_INC(dev_); \ + } while (0) /** * @brief Increment the stuffing error counter for a CAN device @@ -615,7 +652,7 @@ struct can_device_state { { \ struct can_device_state *state = \ CONTAINER_OF(dev->state, struct can_device_state, devstate); \ - stats_init(&state->stats.s_hdr, STATS_SIZE_32, 7, \ + stats_init(&state->stats.s_hdr, STATS_SIZE_32, 8, \ STATS_NAME_INIT_PARMS(can)); \ stats_register(dev->name, &(state->stats.s_hdr)); \ if (init_fn != NULL) { \ @@ -660,6 +697,7 @@ struct can_device_state { #else /* CONFIG_CAN_STATS */ +#define CAN_STATS_BIT_ERROR_INC(dev_) #define CAN_STATS_BIT0_ERROR_INC(dev_) #define CAN_STATS_BIT1_ERROR_INC(dev_) #define CAN_STATS_STUFF_ERROR_INC(dev_) @@ -803,7 +841,7 @@ __syscall int can_calc_timing(const struct device *dev, struct can_timing *res, * @param dev Pointer to the device structure for the driver instance. * * @return Pointer to the minimum supported timing parameter values, or NULL if - * CAN-FD support is not implemented by the driver. + * CAN FD support is not implemented by the driver. */ __syscall const struct can_timing *can_get_timing_data_min(const struct device *dev); @@ -827,7 +865,7 @@ static inline const struct can_timing *z_impl_can_get_timing_data_min(const stru * @param dev Pointer to the device structure for the driver instance. * * @return Pointer to the maximum supported timing parameter values, or NULL if - * CAN-FD support is not implemented by the driver. + * CAN FD support is not implemented by the driver. */ __syscall const struct can_timing *can_get_timing_data_max(const struct device *dev); @@ -863,9 +901,7 @@ __syscall int can_calc_timing_data(const struct device *dev, struct can_timing * uint32_t bitrate, uint16_t sample_pnt); /** - * @brief Configure the bus timing for the data phase of a CAN-FD controller. - * - * If the sjw equals CAN_SJW_NO_CHANGE, the sjw parameter is not changed. + * @brief Configure the bus timing for the data phase of a CAN FD controller. * * @note @kconfig{CONFIG_CAN_FD_MODE} must be selected for this function to be * available. @@ -879,13 +915,13 @@ __syscall int can_calc_timing_data(const struct device *dev, struct can_timing * * @retval -EBUSY if the CAN controller is not in stopped state. * @retval -EIO General input/output error, failed to configure device. * @retval -ENOTSUP if the timing parameters are not supported by the driver. - * @retval -ENOSYS if CAN-FD support is not implemented by the driver. + * @retval -ENOSYS if CAN FD support is not implemented by the driver. */ __syscall int can_set_timing_data(const struct device *dev, const struct can_timing *timing_data); /** - * @brief Set the bitrate for the data phase of the CAN-FD controller + * @brief Set the bitrate for the data phase of the CAN FD controller * * CAN in Automation (CiA) 301 v4.2.0 recommends a sample point location of * 87.5% percent for all bitrates. However, some CAN controllers have @@ -936,8 +972,6 @@ int can_calc_prescaler(const struct device *dev, struct can_timing *timing, /** * @brief Configure the bus timing of a CAN controller. * - * If the sjw equals CAN_SJW_NO_CHANGE, the sjw parameter is not changed. - * * @see can_set_timing_data() * * @param dev Pointer to the device structure for the driver instance. @@ -980,6 +1014,8 @@ static inline int z_impl_can_get_capabilities(const struct device *dev, can_mode * enable the CAN controller to participate in CAN communication, and enable the CAN tranceiver, if * supported. * + * Starting the CAN controller resets all the CAN controller statistics. + * * @see can_stop() * @see can_transceiver_enable() * @@ -1342,6 +1378,187 @@ static inline void can_set_state_change_callback(const struct device *dev, /** @} */ +/** + * @name CAN statistics + * + * @{ + */ + +/** + * @brief Get the bit error counter for a CAN device + * + * The bit error counter is incremented when the CAN controller is unable to + * transmit either a dominant or a recessive bit. + * + * @note @kconfig{CONFIG_CAN_STATS} must be selected for this function to be + * available. + * + * @param dev Pointer to the device structure for the driver instance. + * @return bit error counter + */ +__syscall uint32_t can_stats_get_bit_errors(const struct device *dev); + +#ifdef CONFIG_CAN_STATS +static inline uint32_t z_impl_can_stats_get_bit_errors(const struct device *dev) +{ + return Z_CAN_GET_STATS(dev).bit_error; +} +#endif /* CONFIG_CAN_STATS */ + +/** + * @brief Get the bit0 error counter for a CAN device + * + * The bit0 error counter is incremented when the CAN controller is unable to + * transmit a dominant bit. + * + * @note @kconfig{CONFIG_CAN_STATS} must be selected for this function to be + * available. + * + * @see can_stats_get_bit_errors() + * + * @param dev Pointer to the device structure for the driver instance. + * @return bit0 error counter + */ +__syscall uint32_t can_stats_get_bit0_errors(const struct device *dev); + +#ifdef CONFIG_CAN_STATS +static inline uint32_t z_impl_can_stats_get_bit0_errors(const struct device *dev) +{ + return Z_CAN_GET_STATS(dev).bit0_error; +} +#endif /* CONFIG_CAN_STATS */ + +/** + * @brief Get the bit1 error counter for a CAN device + * + * The bit1 error counter is incremented when the CAN controller is unable to + * transmit a recessive bit. + * + * @note @kconfig{CONFIG_CAN_STATS} must be selected for this function to be + * available. + * + * @see can_stats_get_bit_errors() + * + * @param dev Pointer to the device structure for the driver instance. + * @return bit1 error counter + */ +__syscall uint32_t can_stats_get_bit1_errors(const struct device *dev); + +#ifdef CONFIG_CAN_STATS +static inline uint32_t z_impl_can_stats_get_bit1_errors(const struct device *dev) +{ + return Z_CAN_GET_STATS(dev).bit1_error; +} +#endif /* CONFIG_CAN_STATS */ + +/** + * @brief Get the stuffing error counter for a CAN device + * + * The stuffing error counter is incremented when the CAN controller detects a + * bit stuffing error. + * + * @note @kconfig{CONFIG_CAN_STATS} must be selected for this function to be + * available. + * + * @param dev Pointer to the device structure for the driver instance. + * @return stuffing error counter + */ +__syscall uint32_t can_stats_get_stuff_errors(const struct device *dev); + +#ifdef CONFIG_CAN_STATS +static inline uint32_t z_impl_can_stats_get_stuff_errors(const struct device *dev) +{ + return Z_CAN_GET_STATS(dev).stuff_error; +} +#endif /* CONFIG_CAN_STATS */ + +/** + * @brief Get the CRC error counter for a CAN device + * + * The CRC error counter is incremented when the CAN controller detects a frame + * with an invalid CRC. + * + * @note @kconfig{CONFIG_CAN_STATS} must be selected for this function to be + * available. + * + * @param dev Pointer to the device structure for the driver instance. + * @return CRC error counter + */ +__syscall uint32_t can_stats_get_crc_errors(const struct device *dev); + +#ifdef CONFIG_CAN_STATS +static inline uint32_t z_impl_can_stats_get_crc_errors(const struct device *dev) +{ + return Z_CAN_GET_STATS(dev).crc_error; +} +#endif /* CONFIG_CAN_STATS */ + +/** + * @brief Get the form error counter for a CAN device + * + * The form error counter is incremented when the CAN controller detects a + * fixed-form bit field containing illegal bits. + * + * @note @kconfig{CONFIG_CAN_STATS} must be selected for this function to be + * available. + * + * @param dev Pointer to the device structure for the driver instance. + * @return form error counter + */ +__syscall uint32_t can_stats_get_form_errors(const struct device *dev); + +#ifdef CONFIG_CAN_STATS +static inline uint32_t z_impl_can_stats_get_form_errors(const struct device *dev) +{ + return Z_CAN_GET_STATS(dev).form_error; +} +#endif /* CONFIG_CAN_STATS */ + +/** + * @brief Get the acknowledge error counter for a CAN device + * + * The acknowledge error counter is incremented when the CAN controller does not + * monitor a dominant bit in the ACK slot. + * + * @note @kconfig{CONFIG_CAN_STATS} must be selected for this function to be + * available. + * + * @param dev Pointer to the device structure for the driver instance. + * @return acknowledge error counter + */ +__syscall uint32_t can_stats_get_ack_errors(const struct device *dev); + +#ifdef CONFIG_CAN_STATS +static inline uint32_t z_impl_can_stats_get_ack_errors(const struct device *dev) +{ + return Z_CAN_GET_STATS(dev).ack_error; +} +#endif /* CONFIG_CAN_STATS */ + +/** + * @brief Get the RX overrun counter for a CAN device + * + * The RX overrun counter is incremented when the CAN controller receives a CAN + * frame matching an installed filter but lacks the capacity to store it (either + * due to an already full RX mailbox or a full RX FIFO). + * + * @note @kconfig{CONFIG_CAN_STATS} must be selected for this function to be + * available. + * + * @param dev Pointer to the device structure for the driver instance. + * @return RX overrun counter + */ +__syscall uint32_t can_stats_get_rx_overruns(const struct device *dev); + +#ifdef CONFIG_CAN_STATS +static inline uint32_t z_impl_can_stats_get_rx_overruns(const struct device *dev) +{ + return Z_CAN_GET_STATS(dev).rx_overrun; +} +#endif /* CONFIG_CAN_STATS */ + +/** @} */ + /** * @name CAN utility functions * @@ -1360,7 +1577,7 @@ static inline uint8_t can_dlc_to_bytes(uint8_t dlc) static const uint8_t dlc_table[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64}; - return dlc > 0x0F ? 64 : dlc_table[dlc]; + return dlc_table[MIN(dlc, ARRAY_SIZE(dlc_table) - 1)]; } /** @@ -1413,12 +1630,12 @@ static inline bool can_frame_matches_filter(const struct can_frame *frame, } if ((frame->flags & CAN_FRAME_FDF) != 0 && (filter->flags & CAN_FILTER_FDF) == 0) { - /* CAN-FD format frame, classic format filter */ + /* CAN FD format frame, classic format filter */ return false; } if ((frame->flags & CAN_FRAME_FDF) == 0 && (filter->flags & CAN_FILTER_FDF) != 0) { - /* Classic frame, CAN-FD format filter */ + /* Classic frame, CAN FD format filter */ return false; } diff --git a/include/zephyr/drivers/can/can_mcan.h b/include/zephyr/drivers/can/can_mcan.h index c1a1fb9f85d..b29adc857f7 100644 --- a/include/zephyr/drivers/can/can_mcan.h +++ b/include/zephyr/drivers/can/can_mcan.h @@ -127,6 +127,17 @@ #define CAN_MCAN_PSR_ACT GENMASK(4, 3) #define CAN_MCAN_PSR_LEC GENMASK(2, 0) +enum can_mcan_psr_lec { + CAN_MCAN_PSR_LEC_NO_ERROR = 0, + CAN_MCAN_PSR_LEC_STUFF_ERROR = 1, + CAN_MCAN_PSR_LEC_FORM_ERROR = 2, + CAN_MCAN_PSR_LEC_ACK_ERROR = 3, + CAN_MCAN_PSR_LEC_BIT1_ERROR = 4, + CAN_MCAN_PSR_LEC_BIT0_ERROR = 5, + CAN_MCAN_PSR_LEC_CRC_ERROR = 6, + CAN_MCAN_PSR_LEC_NO_CHANGE = 7 +}; + /* Transmitter Delay Compensation register */ #define CAN_MCAN_TDCR 0x048 #define CAN_MCAN_TDCR_TDCO GENMASK(14, 8) @@ -629,7 +640,7 @@ */ #define CAN_MCAN_DT_MRAM_DEFINE(node_id, _name) \ BUILD_ASSERT(CAN_MCAN_DT_MRAM_OFFSET(node_id) == 0, "offset must be 0"); \ - static char __noinit __nocache __aligned(4) _name[CAN_MCAN_DT_MRAM_ELEMENTS_SIZE(node_id)]; + static char __nocache_noinit __aligned(4) _name[CAN_MCAN_DT_MRAM_ELEMENTS_SIZE(node_id)]; /** * @brief Assert that the Message RAM configuration meets the Bosch M_CAN IP core restrictions diff --git a/include/zephyr/drivers/can/can_sja1000.h b/include/zephyr/drivers/can/can_sja1000.h index a85dc2ffa53..fe826296db9 100644 --- a/include/zephyr/drivers/can/can_sja1000.h +++ b/include/zephyr/drivers/can/can_sja1000.h @@ -176,7 +176,6 @@ struct can_sja1000_data { struct k_sem tx_idle; can_tx_callback_t tx_callback; void *tx_user_data; - uint32_t sjw; void *custom; }; diff --git a/include/zephyr/drivers/charger.h b/include/zephyr/drivers/charger.h new file mode 100644 index 00000000000..6159f41dcc0 --- /dev/null +++ b/include/zephyr/drivers/charger.h @@ -0,0 +1,285 @@ +/* + * Copyright 2023 Cirrus Logic, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Charger APIs + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_CHARGER_H_ +#define ZEPHYR_INCLUDE_DRIVERS_CHARGER_H_ + +/** + * @brief Charger Interface + * @defgroup charger_interface Charger Interface + * @ingroup io_interfaces + * @{ + */ + +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @brief Runtime Dynamic Battery Parameters + */ +enum charger_property { + /** Indicates if external supply is present for the charger. */ + /** Value should be of type enum charger_online */ + CHARGER_PROP_ONLINE = 0, + /** Reports whether or not a battery is present. */ + /** Value should be of type bool*/ + CHARGER_PROP_PRESENT, + /** Represents the charging status of the charger. */ + /** Value should be of type enum charger_status */ + CHARGER_PROP_STATUS, + /** Represents the charging algo type of the charger. */ + /** Value should be of type enum charger_charge_type */ + CHARGER_PROP_CHARGE_TYPE, + /** Represents the health of the charger. */ + /** Value should be of type enum charger_health */ + CHARGER_PROP_HEALTH, + /** Configuration of current sink used for charging in µA */ + CHARGER_PROP_CONSTANT_CHARGE_CURRENT_UA, + /** Configuration of current sink used for conditioning in µA */ + CHARGER_PROP_PRECHARGE_CURRENT_UA, + /** Configuration of charge termination target in µA */ + CHARGER_PROP_CHARGE_TERM_CURRENT_UA, + /** Configuration of charge voltage regulation target in µV */ + CHARGER_PROP_CONSTANT_CHARGE_VOLTAGE_UV, + /** Reserved to demark end of common charger properties */ + CHARGER_PROP_COMMON_COUNT, + /** + * Reserved to demark downstream custom properties - use this value as the actual value may + * change over future versions of this API + */ + CHARGER_PROP_CUSTOM_BEGIN = CHARGER_PROP_COMMON_COUNT + 1, + /** Reserved to demark end of valid enum properties */ + CHARGER_PROP_MAX = UINT16_MAX, +}; + +/** + * @typedef charger_prop_t + * @brief A charger property's identifier + * + * See charger_property for a list of identifiers + */ +typedef uint16_t charger_prop_t; + +/** + * @brief External supply states + */ +enum charger_online { + /** External supply not present */ + CHARGER_ONLINE_OFFLINE = 0, + /** External supply is present and of fixed output */ + CHARGER_ONLINE_FIXED, + /** External supply is present and of programmable output*/ + CHARGER_ONLINE_PROGRAMMABLE, +}; + +/** + * @brief Charging states + */ +enum charger_status { + /** Charging device state is unknown */ + CHARGER_STATUS_UNKNOWN = 0, + /** Charging device is charging a battery */ + CHARGER_STATUS_CHARGING, + /** Charging device is not able to charge a battery */ + CHARGER_STATUS_DISCHARGING, + /** Charging device is not charging a battery */ + CHARGER_STATUS_NOT_CHARGING, + /** The battery is full and the charging device will not attempt charging */ + CHARGER_STATUS_FULL, +}; + +/** + * @brief Charge algorithm types + */ +enum charger_charge_type { + /** Charge type is unknown */ + CHARGER_CHARGE_TYPE_UNKNOWN = 0, + /** Charging is not occurring */ + CHARGER_CHARGE_TYPE_NONE, + /** + * Charging is occurring at the slowest desired charge rate, + * typically for battery detection or preconditioning + */ + CHARGER_CHARGE_TYPE_TRICKLE, + /** Charging is occurring at the fastest desired charge rate */ + CHARGER_CHARGE_TYPE_FAST, + /** Charging is occurring at a moderate charge rate */ + CHARGER_CHARGE_TYPE_STANDARD, + /* + * Charging is being dynamically adjusted by the charger device + */ + CHARGER_CHARGE_TYPE_ADAPTIVE, + /* + * Charging is occurring at a reduced charge rate to preserve + * battery health + */ + CHARGER_CHARGE_TYPE_LONGLIFE, + /* + * The charger device is being bypassed and the power conversion + * is being handled externally, typically by a "smart" wall adaptor + */ + CHARGER_CHARGE_TYPE_BYPASS, +}; + +/** + * @brief Charger health conditions + * + * These conditions determine the ability to, or the rate of, charge + */ +enum charger_health { + /** Charger health condition is unknown */ + CHARGER_HEALTH_UNKNOWN = 0, + /** Charger health condition is good */ + CHARGER_HEALTH_GOOD, + /** The charger device is overheated */ + CHARGER_HEALTH_OVERHEAT, + /** The battery voltage has exceeded its overvoltage threshold */ + CHARGER_HEALTH_OVERVOLTAGE, + /** + * The battery or charger device is experiencing an unspecified + * failure. + */ + CHARGER_HEALTH_UNSPEC_FAILURE, + /** The battery temperature is below the "cold" threshold */ + CHARGER_HEALTH_COLD, + /** The charger device's watchdog timer has expired */ + CHARGER_HEALTH_WATCHDOG_TIMER_EXPIRE, + /** The charger device's safety timer has expired */ + CHARGER_HEALTH_SAFETY_TIMER_EXPIRE, + /** The charger device requires calibration */ + CHARGER_HEALTH_CALIBRATION_REQUIRED, + /** The battery temperature is in the "warm" range */ + CHARGER_HEALTH_WARM, + /** The battery temperature is in the "cool" range */ + CHARGER_HEALTH_COOL, + /** The battery temperature is below the "hot" threshold */ + CHARGER_HEALTH_HOT, + /** The charger device does not detect a battery */ + CHARGER_HEALTH_NO_BATTERY, +}; + +/** + * @brief container for a charger_property value + * + */ +union charger_propval { + /* Fields have the format: */ + /* CHARGER_PROPERTY_FIELD */ + /* type property_field; */ + + /** CHARGER_PROP_ONLINE */ + enum charger_online online; + /** CHARGER_PROP_PRESENT */ + bool present; + /** CHARGER_PROP_STATUS */ + enum charger_status status; + /** CHARGER_PROP_CHARGE_TYPE */ + enum charger_charge_type charge_type; + /** CHARGER_PROP_HEALTH */ + enum charger_health health; + /** CHARGER_PROP_CONSTANT_CHARGE_CURRENT_UA */ + uint32_t const_charge_current_ua; + /** CHARGER_PROP_PRECHARGE_CURRENT_UA */ + uint32_t precharge_current_ua; + /** CHARGER_PROP_CHARGE_TERM_CURRENT_UA */ + uint32_t charge_term_current_ua; + /** CHARGER_PROP_CONSTANT_CHARGE_VOLTAGE_UV */ + uint32_t const_charge_voltage_uv; +}; + +/** + * @typedef charger_get_property_t + * @brief Callback API for getting a charger property. + * + * See charger_get_property() for argument description + */ +typedef int (*charger_get_property_t)(const struct device *dev, const charger_prop_t prop, + union charger_propval *val); + +/** + * @typedef charger_set_property_t + * @brief Callback API for setting a charger property. + * + * See charger_set_property() for argument description + */ +typedef int (*charger_set_property_t)(const struct device *dev, const charger_prop_t prop, + const union charger_propval *val); + +/** + * @brief Charging device API + * + * Caching is entirely on the onus of the client + */ +__subsystem struct charger_driver_api { + charger_get_property_t get_property; + charger_set_property_t set_property; +}; + +/** + * @brief Fetch a battery charger property + * + * @param dev Pointer to the battery charger device + * @param prop Charger property to get + * @param val Pointer to charger_propval union + * + * @retval 0 if successful + * @retval < 0 if getting property failed + */ +__syscall int charger_get_prop(const struct device *dev, const charger_prop_t prop, + union charger_propval *val); + +static inline int z_impl_charger_get_prop(const struct device *dev, const charger_prop_t prop, + union charger_propval *val) +{ + const struct charger_driver_api *api = (const struct charger_driver_api *)dev->api; + + return api->get_property(dev, prop, val); +} + +/** + * @brief Set a battery charger property + * + * @param dev Pointer to the battery charger device + * @param prop Charger property to set + * @param val Pointer to charger_propval union + * + * @retval 0 if successful + * @retval < 0 if setting property failed + */ +__syscall int charger_set_prop(const struct device *dev, const charger_prop_t prop, + const union charger_propval *val); + +static inline int z_impl_charger_set_prop(const struct device *dev, const charger_prop_t prop, + const union charger_propval *val) +{ + const struct charger_driver_api *api = (const struct charger_driver_api *)dev->api; + + return api->set_property(dev, prop, val); +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#include + +#endif /* ZEPHYR_INCLUDE_DRIVERS_CHARGER_H_ */ diff --git a/include/zephyr/drivers/clock_control/clock_control_ambiq.h b/include/zephyr/drivers/clock_control/clock_control_ambiq.h new file mode 100644 index 00000000000..02ca16b54db --- /dev/null +++ b/include/zephyr/drivers/clock_control/clock_control_ambiq.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Ambiq Micro Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_CLOCK_CONTROL_AMBIQ_H_ +#define ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_CLOCK_CONTROL_AMBIQ_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Clocks handled by the CLOCK peripheral. + * + * Enum shall be used as a sys argument in clock_control API. + */ +enum clock_control_ambiq_type { + CLOCK_CONTROL_AMBIQ_TYPE_HFXTAL_BLE, + CLOCK_CONTROL_AMBIQ_TYPE_HFXTAL_USB, + CLOCK_CONTROL_AMBIQ_TYPE_HFXTAL_ADC, + CLOCK_CONTROL_AMBIQ_TYPE_HFXTAL_AUADC, + CLOCK_CONTROL_AMBIQ_TYPE_HCXTAL_DBGCTRL, + CLOCK_CONTROL_AMBIQ_TYPE_HCXTAL_CLKGEN_MISC, + CLOCK_CONTROL_AMBIQ_TYPE_HCXTAL_CLKGEN_CLKOUT, + CLOCK_CONTROL_AMBIQ_TYPE_HCXTAL_PDM, + CLOCK_CONTROL_AMBIQ_TYPE_HCXTAL_IIS, + CLOCK_CONTROL_AMBIQ_TYPE_HCXTAL_IOM, + CLOCK_CONTROL_AMBIQ_TYPE_LFXTAL, + CLOCK_CONTROL_AMBIQ_TYPE_MAX +}; + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_CLOCK_CONTROL_AMBIQ_H_ */ diff --git a/include/zephyr/drivers/clock_control/stm32_clock_control.h b/include/zephyr/drivers/clock_control/stm32_clock_control.h index c69718f1048..f18c351c0d5 100644 --- a/include/zephyr/drivers/clock_control/stm32_clock_control.h +++ b/include/zephyr/drivers/clock_control/stm32_clock_control.h @@ -143,6 +143,8 @@ #define STM32_PLL_Q_DIVISOR DT_PROP_OR(DT_NODELABEL(pll), div_q, 1) #define STM32_PLL_R_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll), div_r) #define STM32_PLL_R_DIVISOR DT_PROP_OR(DT_NODELABEL(pll), div_r, 1) +#define STM32_PLL_FRACN_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll), fracn) +#define STM32_PLL_FRACN_VALUE DT_PROP_OR(DT_NODELABEL(pll), fracn, 1) #endif #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(plli2s), st_stm32f4_plli2s_clock, okay) @@ -172,6 +174,8 @@ #define STM32_PLL2_Q_DIVISOR DT_PROP_OR(DT_NODELABEL(pll2), div_q, 1) #define STM32_PLL2_R_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll2), div_r) #define STM32_PLL2_R_DIVISOR DT_PROP_OR(DT_NODELABEL(pll2), div_r, 1) +#define STM32_PLL2_FRACN_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll2), fracn) +#define STM32_PLL2_FRACN_VALUE DT_PROP_OR(DT_NODELABEL(pll2), fracn, 1) #endif #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll3), st_stm32h7_pll_clock, okay) || \ @@ -185,6 +189,8 @@ #define STM32_PLL3_Q_DIVISOR DT_PROP_OR(DT_NODELABEL(pll3), div_q, 1) #define STM32_PLL3_R_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll3), div_r) #define STM32_PLL3_R_DIVISOR DT_PROP_OR(DT_NODELABEL(pll3), div_r, 1) +#define STM32_PLL3_FRACN_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll3), fracn) +#define STM32_PLL3_FRACN_VALUE DT_PROP_OR(DT_NODELABEL(pll3), fracn, 1) #endif #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32f1_pll_clock, okay) @@ -379,6 +385,10 @@ #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_hsi48), fixed_clock, okay) #define STM32_HSI48_ENABLED 1 #define STM32_HSI48_FREQ DT_PROP(DT_NODELABEL(clk_hsi48), clock_frequency) +#elif DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_hsi48), st_stm32_hsi48_clock, okay) +#define STM32_HSI48_ENABLED 1 +#define STM32_HSI48_FREQ DT_PROP(DT_NODELABEL(clk_hsi48), clock_frequency) +#define STM32_HSI48_CRS_USB_SOF DT_PROP(DT_NODELABEL(clk_hsi48), crs_usb_sof) #endif #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(perck), st_stm32_clock_mux, okay) diff --git a/include/zephyr/drivers/counter.h b/include/zephyr/drivers/counter.h index 2fd86d5d989..5da1a257d21 100644 --- a/include/zephyr/drivers/counter.h +++ b/include/zephyr/drivers/counter.h @@ -32,8 +32,11 @@ extern "C" { #endif -/**@defgroup COUNTER_FLAGS Counter device capabilities - * @{ */ +/** + * @anchor COUNTER_FLAGS + * @name Counter device capabilities + * @{ + */ /** * @brief Counter count up flag. @@ -42,7 +45,9 @@ extern "C" { /**@} */ -/**@defgroup COUNTER_TOP_FLAGS Flags used by @ref counter_top_cfg. +/** + * @anchor COUNTER_TOP_FLAGS + * @name Flags used by counter_top_cfg. * @{ */ @@ -64,7 +69,9 @@ extern "C" { /**@} */ -/**@defgroup COUNTER_ALARM_FLAGS Alarm configuration flags +/** + * @anchor COUNTER_ALARM_FLAGS + * @name Alarm configuration flags * * @brief Used in alarm configuration structure (@ref counter_alarm_cfg). * @{ */ @@ -87,7 +94,9 @@ extern "C" { /**@} */ -/**@defgroup COUNTER_GUARD_PERIOD_FLAGS Counter guard period flags +/** + * @anchor COUNTER_GUARD_PERIOD_FLAGS + * @name Counter guard period flags * * @brief Used by @ref counter_set_guard_period and * @ref counter_get_guard_period. @@ -113,27 +122,36 @@ typedef void (*counter_alarm_callback_t)(const struct device *dev, void *user_data); /** @brief Alarm callback structure. - * - * @param callback Callback called on alarm (cannot be NULL). - * @param ticks Number of ticks that triggers the alarm. It can be relative (to - * now) or an absolute value (see @ref COUNTER_ALARM_CFG_ABSOLUTE). - * Both, relative and absolute, alarm values can be any value - * between zero and the current top value (see @ref counter_get_top_value). - * When setting an absolute alarm value close to the current counter - * value there is a risk that the counter will have counted past the - * given absolute value before the driver manages to activate the alarm. - * Therefore a guard period can be defined that lets the driver decide - * unambiguously whether it is late or not (see @ref counter_set_guard_period). - * If the counter is clock driven then ticks can be converted to - * microseconds (see @ref counter_ticks_to_us). Alternatively, - * the counter implementation may count asynchronous events. - * @param user_data User data returned in callback. - * @param flags Alarm flags. See @ref COUNTER_ALARM_FLAGS. */ struct counter_alarm_cfg { + /** + * Callback called on alarm (cannot be NULL). + */ counter_alarm_callback_t callback; + /** + * Number of ticks that triggers the alarm. + * + * It can be relative (to now) or an absolute value (see @ref + * COUNTER_ALARM_CFG_ABSOLUTE). Both, relative and absolute, alarm + * values can be any value between zero and the current top value (see + * @ref counter_get_top_value). When setting an absolute alarm value + * close to the current counter value there is a risk that the counter + * will have counted past the given absolute value before the driver + * manages to activate the alarm. Therefore a guard period can be + * defined that lets the driver decide unambiguously whether it is late + * or not (see @ref counter_set_guard_period). If the counter is clock + * driven then ticks can be converted to microseconds (see @ref + * counter_ticks_to_us). Alternatively, the counter implementation may + * count asynchronous events. + */ uint32_t ticks; + /** + * User data returned in callback. + */ void *user_data; + /** + * Alarm flags (see @ref COUNTER_ALARM_FLAGS). + */ uint32_t flags; }; @@ -146,34 +164,46 @@ typedef void (*counter_top_callback_t)(const struct device *dev, void *user_data); /** @brief Top value configuration structure. - * - * @param ticks Top value. - * @param callback Callback function. Can be NULL. - * @param user_data User data passed to callback function. Not valid if - * callback is NULL. - * @param flags Flags. See @ref COUNTER_TOP_FLAGS. */ struct counter_top_cfg { + /** + * Top value. + */ uint32_t ticks; + /** + * Callback function (can be NULL). + */ counter_top_callback_t callback; + /** + * User data passed to callback function (not valid if callback is NULL). + */ void *user_data; + /** + * Flags (see @ref COUNTER_TOP_FLAGS). + */ uint32_t flags; }; /** @brief Structure with generic counter features. - * - * @param max_top_value Maximal (default) top value on which counter is reset - * (cleared or reloaded). - * @param freq Frequency of the source clock if synchronous events are - * counted. - * @param flags Flags. See @ref COUNTER_FLAGS. - * @param channels Number of channels that can be used for setting alarm, - * see @ref counter_set_channel_alarm. */ struct counter_config_info { + /** + * Maximal (default) top value on which counter is reset (cleared or reloaded). + */ uint32_t max_top_value; + /** + * Frequency of the source clock if synchronous events are counted. + */ uint32_t freq; + /** + * Flags (see @ref COUNTER_FLAGS). + */ uint8_t flags; + /** + * Number of channels that can be used for setting alarm. + * + * @see counter_set_channel_alarm + */ uint8_t channels; }; @@ -618,7 +648,7 @@ static inline int z_impl_counter_set_guard_period(const struct device *dev, /** * @brief Return guard period. * - * See @ref counter_set_guard_period. + * @see counter_set_guard_period. * * @param dev Pointer to the device structure for the driver instance. * @param flags See @ref COUNTER_GUARD_PERIOD_FLAGS. diff --git a/include/zephyr/drivers/dma.h b/include/zephyr/drivers/dma.h index eb04334101d..2905c6fc434 100644 --- a/include/zephyr/drivers/dma.h +++ b/include/zephyr/drivers/dma.h @@ -28,12 +28,21 @@ extern "C" { * @{ */ +/** + * @brief DMA channel direction + */ enum dma_channel_direction { + /** Memory to memory */ MEMORY_TO_MEMORY = 0x0, + /** Memory to peripheral */ MEMORY_TO_PERIPHERAL, + /** Peripheral to memory */ PERIPHERAL_TO_MEMORY, + /** Peripheral to peripheral */ PERIPHERAL_TO_PERIPHERAL, + /** Host to memory */ HOST_TO_MEMORY, + /** Memory to host */ MEMORY_TO_HOST, /** @@ -53,20 +62,31 @@ enum dma_channel_direction { DMA_CHANNEL_DIRECTION_MAX = 0x7 }; -/** Valid values for @a source_addr_adj and @a dest_addr_adj */ +/** + * @brief DMA address adjustment + * + * Valid values for @a source_addr_adj and @a dest_addr_adj + */ enum dma_addr_adj { + /** Increment the address */ DMA_ADDR_ADJ_INCREMENT, + /** Decrement the address */ DMA_ADDR_ADJ_DECREMENT, + /** No change the address */ DMA_ADDR_ADJ_NO_CHANGE, }; -/* channel attributes */ +/** + * @brief DMA channel attributes + */ enum dma_channel_filter { DMA_CHANNEL_NORMAL, /* normal DMA channel */ DMA_CHANNEL_PERIODIC, /* can be triggered by periodic sources */ }; -/* DMA attributes */ +/** + * @brief DMA attributes + */ enum dma_attribute_type { DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, DMA_ATTR_BUFFER_SIZE_ALIGNMENT, @@ -78,65 +98,73 @@ enum dma_attribute_type { * @struct dma_block_config * @brief DMA block configuration structure. * - * @param source_address is block starting address at source - * @param source_gather_interval is the address adjustment at gather boundary - * @param dest_address is block starting address at destination - * @param dest_scatter_interval is the address adjustment at scatter boundary - * @param dest_scatter_count is the continuous transfer count between scatter - * boundaries - * @param source_gather_count is the continuous transfer count between gather - * boundaries - * - * @param block_size is the number of bytes to be transferred for this block. - * - * @param config is a bit field with the following parts: - * - * source_gather_en [ 0 ] - 0-disable, 1-enable. - * dest_scatter_en [ 1 ] - 0-disable, 1-enable. - * source_addr_adj [ 2 : 3 ] - 00-increment, 01-decrement, - * 10-no change. - * dest_addr_adj [ 4 : 5 ] - 00-increment, 01-decrement, - * 10-no change. - * source_reload_en [ 6 ] - reload source address at the end of - * block transfer - * 0-disable, 1-enable. - * dest_reload_en [ 7 ] - reload destination address at the end - * of block transfer - * 0-disable, 1-enable. - * fifo_mode_control [ 8 : 11 ] - How full of the fifo before transfer - * start. HW specific. - * flow_control_mode [ 12 ] - 0-source request served upon data - * availability. - * 1-source request postponed until - * destination request happens. - * reserved [ 13 : 15 ] + * Aside from source address, destination address, and block size many of these options are hardware + * and driver dependent. */ struct dma_block_config { #ifdef CONFIG_DMA_64BIT + /** block starting address at source */ uint64_t source_address; + /** block starting address at destination */ uint64_t dest_address; #else + /** block starting address at source */ uint32_t source_address; + /** block starting address at destination */ uint32_t dest_address; #endif + /** Address adjustment at gather boundary */ uint32_t source_gather_interval; + /** Address adjustment at scatter boundary */ uint32_t dest_scatter_interval; + /** Continuous transfer count between scatter boundaries */ uint16_t dest_scatter_count; + /** Continuous transfer count between gather boundaries */ uint16_t source_gather_count; + /** Number of bytes to be transferred for this block */ uint32_t block_size; + /** Pointer to next block in a transfer list */ struct dma_block_config *next_block; + /** Enable source gathering when set to 1 */ uint16_t source_gather_en : 1; + /** Enable destination scattering when set to 1 */ uint16_t dest_scatter_en : 1; + /** + * Source address adjustment option + * + * - 0b00 increment + * - 0b01 decrement + * - 0b10 no change + */ uint16_t source_addr_adj : 2; + /** + * Destination address adjustment + * + * - 0b00 increment + * - 0b01 decrement + * - 0b10 no change + */ uint16_t dest_addr_adj : 2; + /** Reload source address at the end of block transfer */ uint16_t source_reload_en : 1; + /** Reload destination address at the end of block transfer */ uint16_t dest_reload_en : 1; + /** FIFO fill before starting transfer, HW specific meaning */ uint16_t fifo_mode_control : 4; + /** + * Transfer flow control mode + * + * - 0b0 source request service upon data availability + * - 0b1 source request postponed until destination request happens + */ uint16_t flow_control_mode : 1; - uint16_t reserved : 3; + + uint16_t _reserved : 3; }; +/** The DMA callback event has occurred at the completion of a transfer list */ #define DMA_STATUS_COMPLETE 0 +/** The DMA callback has occurred at the completion of a single transfer block in a transfer list */ #define DMA_STATUS_BLOCK 1 /** @@ -151,10 +179,11 @@ struct dma_block_config { * @param dev Pointer to the DMA device calling the callback. * @param user_data A pointer to some user data or NULL * @param channel The channel number - * @param status - 0-DMA_STATUS_COMPLETE buffer fully consumed - * - 1-DMA_STATUS_BLOCK buffer consumption reached a configured block + * @param status Status of the transfer + * - DMA_STATUS_COMPLETE buffer fully consumed + * - DMA_STATUS_BLOCK buffer consumption reached a configured block * or water mark - * - a negative errno otherwise + * - A negative errno otherwise */ typedef void (*dma_callback_t)(const struct device *dev, void *user_data, uint32_t channel, int status); @@ -162,86 +191,99 @@ typedef void (*dma_callback_t)(const struct device *dev, void *user_data, /** * @struct dma_config * @brief DMA configuration structure. - * - * @param dma_slot [ 0 : 7 ] - which peripheral and direction - * (HW specific) - * @param channel_direction [ 8 : 10 ] - 000-memory to memory, - * 001-memory to peripheral, - * 010-peripheral to memory, - * 011-peripheral to peripheral, - * 100-host to memory - * 101-memory to host - * ... - * @param complete_callback_en [ 11 ] - 0-callback invoked at completion only - * 1-callback invoked at completion of - * each block - * @param error_callback_en [ 12 ] - 0-error callback enabled - * 1-error callback disabled - * @param source_handshake [ 13 ] - 0-HW, 1-SW - * @param dest_handshake [ 14 ] - 0-HW, 1-SW - * @param channel_priority [ 15 : 18 ] - DMA channel priority - * @param source_chaining_en [ 19 ] - enable/disable source block chaining - * 0-disable, 1-enable - * @param dest_chaining_en [ 20 ] - enable/disable destination block - * chaining. - * 0-disable, 1-enable - * @param linked_channel [ 21 : 27 ] - after channel count exhaust will - * initiate a channel service request - * at this channel - * @param cyclic [ 28 ] - enable/disable cyclic buffer - * 0-disable, 1-enable - * @param reserved [ 29 : 31 ] - * @param source_data_size [ 0 : 15 ] - width of source data (in bytes) - * @param dest_data_size [ 16 : 31 ] - width of dest data (in bytes) - * @param source_burst_length [ 0 : 15 ] - number of source data units - * @param dest_burst_length [ 16 : 31 ] - number of destination data units - * @param block_count is the number of blocks used for block chaining, this - * depends on availability of the DMA controller. - * @param user_data private data from DMA client. - * @param dma_callback see dma_callback_t for details */ struct dma_config { + /** Which peripheral and direction, HW specific */ uint32_t dma_slot : 8; + /** + * Direction the transfers are occurring + * + * - 0b000 memory to memory, + * - 0b001 memory to peripheral, + * - 0b010 peripheral to memory, + * - 0b011 peripheral to peripheral, + * - 0b100 host to memory + * - 0b101 memory to host + * - others hardware specific + */ uint32_t channel_direction : 3; + /** + * Completion callback enable + * + * - 0b0 callback invoked at transfer list completion only + * - 0b1 callback invoked at completion of each block + */ uint32_t complete_callback_en : 1; + /** + * Error callback enable + * + * - 0b0 error callback enabled + * - 0b1 error callback disabled + */ uint32_t error_callback_en : 1; + /** + * Source handshake, HW specific + * + * - 0b0 HW + * - 0b1 SW + */ uint32_t source_handshake : 1; + /** + * Destination handshake, HW specific + * + * - 0b0 HW + * - 0b1 SW + */ uint32_t dest_handshake : 1; + /** + * Channel priority for arbitration, HW specific + */ uint32_t channel_priority : 4; + /** Source chaining enable, HW specific */ uint32_t source_chaining_en : 1; + /** Destination chaining enable, HW specific */ uint32_t dest_chaining_en : 1; + /** Linked channel, HW specific */ uint32_t linked_channel : 7; + /** Cyclic transfer list, HW specific */ uint32_t cyclic : 1; - uint32_t reserved : 3; + + uint32_t _reserved : 3; + /** Width of source data (in bytes) */ uint32_t source_data_size : 16; + /** Width of destination data (in bytes) */ uint32_t dest_data_size : 16; + /** Source burst length in bytes */ uint32_t source_burst_length : 16; + /** Destination burst length in bytes */ uint32_t dest_burst_length : 16; + /** Number of blocks in transfer list */ uint32_t block_count; + /** Pointer to the first block in the transfer list */ struct dma_block_config *head_block; + /** Optional attached user data for callbacks */ void *user_data; + /** Optional callback for completion and error events */ dma_callback_t dma_callback; }; /** * DMA runtime status structure - * - * busy - is current DMA transfer busy or idle - * dir - DMA transfer direction - * pending_length - data length pending to be transferred in bytes - * or platform dependent. - * free - free buffer space - * write_position - write position in a circular dma buffer - * read_position - read position in a circular dma buffer - * */ struct dma_status { + /** Is the current DMA transfer busy or idle */ bool busy; + /** Direction fo the transfer */ enum dma_channel_direction dir; + /** Pending length to be transferred in bytes, HW specific */ uint32_t pending_length; + /** Available buffers space, HW specific */ uint32_t free; + /** Write position in circular DMA buffer, HW specific */ uint32_t write_position; + /** Read position in circular DMA buffer, HW specific */ uint32_t read_position; + /** Total copied, HW specific */ uint64_t total_copied; }; @@ -249,19 +291,17 @@ struct dma_status { * DMA context structure * Note: the dma_context shall be the first member * of DMA client driver Data, got by dev->data - * - * magic - magic code to identify the context - * dma_channels - dma channels - * atomic - driver atomic_t pointer - * */ struct dma_context { + /** magic code to identify the context */ int32_t magic; + /** number of dma channels */ int dma_channels; + /** atomic holding bit flags for each channel to mark as used/unused */ atomic_t *atomic; }; -/* magic code to identify context content */ +/** Magic code to identify context content */ #define DMA_MAGIC 0x47494749 /** @@ -386,6 +426,8 @@ static inline int dma_reload(const struct device *dev, uint32_t channel, * Start is allowed on channels that have already been started and must report * success. * + * @funcprops \isr_ok + * * @param dev Pointer to the device structure for the driver instance. * @param channel Numeric identification of the channel where the transfer will * be processed @@ -412,6 +454,8 @@ static inline int z_impl_dma_start(const struct device *dev, uint32_t channel) * Stop is allowed on channels that have already been stopped and must report * success. * + * @funcprops \isr_ok + * * @param dev Pointer to the device structure for the driver instance. * @param channel Numeric identification of the channel where the transfer was * being processed @@ -436,6 +480,8 @@ static inline int z_impl_dma_stop(const struct device *dev, uint32_t channel) * Implementations must check the validity of the channel state and ID passed * in and return -EINVAL if either are invalid. * + * @funcprops \isr_ok + * * @param dev Pointer to the device structure for the driver instance. * @param channel Numeric identification of the channel to suspend * @@ -462,6 +508,8 @@ static inline int z_impl_dma_suspend(const struct device *dev, uint32_t channel) * Implementations must check the validity of the channel state and ID passed * in and return -EINVAL if either are invalid. * + * @funcprops \isr_ok + * * @param dev Pointer to the device structure for the driver instance. * @param channel Numeric identification of the channel to resume * @@ -488,6 +536,8 @@ static inline int z_impl_dma_resume(const struct device *dev, uint32_t channel) * request DMA channel resources * return -EINVAL if there is no valid channel available. * + * @funcprops \isr_ok + * * @param dev Pointer to the device structure for the driver instance. * @param filter_param filter function parameter * @@ -531,6 +581,8 @@ static inline int z_impl_dma_request_channel(const struct device *dev, * * release DMA channel resources * + * @funcprops \isr_ok + * * @param dev Pointer to the device structure for the driver instance. * @param channel channel number * @@ -587,6 +639,8 @@ static inline int z_impl_dma_chan_filter(const struct device *dev, * Implementations must check the validity of the channel ID passed in and * return -EINVAL if it is invalid or -ENOSYS if not supported. * + * @funcprops \isr_ok + * * @param dev Pointer to the device structure for the driver instance. * @param channel Numeric identification of the channel where the transfer was * being processed @@ -616,6 +670,8 @@ static inline int dma_get_status(const struct device *dev, uint32_t channel, * Implementations must check the validity of the type passed in and * return -EINVAL if it is invalid or -ENOSYS if not supported. * + * @funcprops \isr_ok + * * @param dev Pointer to the device structure for the driver instance. * @param type Numeric identification of the attribute * @param value A non-NULL pointer to the variable where the read value is to be placed @@ -637,7 +693,7 @@ static inline int dma_get_attribute(const struct device *dev, uint32_t type, uin /** * @brief Look-up generic width index to be used in registers * - * WARNING: This look-up works for most controllers, but *may* not work for + * @warning This look-up works for most controllers, but *may* not work for * yours. Ensure your controller expects the most common register * bit values before using this convenience function. If your * controller does not support these values, you will have to write @@ -666,7 +722,7 @@ static inline uint32_t dma_width_index(uint32_t size) /** * @brief Look-up generic burst index to be used in registers * - * WARNING: This look-up works for most controllers, but *may* not work for + * @warning This look-up works for most controllers, but *may* not work for * yours. Ensure your controller expects the most common register * bit values before using this convenience function. If your * controller does not support these values, you will have to write @@ -693,7 +749,7 @@ static inline uint32_t dma_burst_index(uint32_t burst) } /** - * Get the device tree property describing the buffer address alignment + * @brief Get the device tree property describing the buffer address alignment * * Useful when statically defining or allocating buffers for DMA usage where * memory alignment often matters. @@ -704,7 +760,7 @@ static inline uint32_t dma_burst_index(uint32_t burst) #define DMA_BUF_ADDR_ALIGNMENT(node) DT_PROP(node, dma_buf_addr_alignment) /** - * Get the device tree property describing the buffer size alignment + * @brief Get the device tree property describing the buffer size alignment * * Useful when statically defining or allocating buffers for DMA usage where * memory alignment often matters. @@ -715,7 +771,7 @@ static inline uint32_t dma_burst_index(uint32_t burst) #define DMA_BUF_SIZE_ALIGNMENT(node) DT_PROP(node, dma_buf_size_alignment) /** - * Get the device tree property describing the minimal chunk of data possible to be copied + * @brief Get the device tree property describing the minimal chunk of data possible to be copied * * @param node Node identifier, e.g. DT_NODELABEL(dma_0) * @return minimal Minimal chunk of data possible to be copied diff --git a/include/zephyr/drivers/dma/dma_intel_lpss.h b/include/zephyr/drivers/dma/dma_intel_lpss.h index c3cf3bef81e..8ef05b688f9 100644 --- a/include/zephyr/drivers/dma/dma_intel_lpss.h +++ b/include/zephyr/drivers/dma/dma_intel_lpss.h @@ -7,7 +7,6 @@ #ifndef ZEPHYR_INCLUDE_DRIVERS_DMA_INTEL_LPSS_H_ #define ZEPHYR_INCLUDE_DRIVERS_DMA_INTEL_LPSS_H_ -#define DMA_INTEL_LPSS_INIT_PRIORITY 80 #define DMA_INTEL_LPSS_OFFSET 0x800 #define DMA_INTEL_LPSS_REMAP_LOW 0x240 #define DMA_INTEL_LPSS_REMAP_HI 0x244 @@ -16,5 +15,7 @@ #define DMA_INTEL_LPSS_ADDR_RIGHT_SHIFT 32 void dma_intel_lpss_isr(const struct device *dev); +int dma_intel_lpss_setup(const struct device *dev); +void dma_intel_lpss_set_base(const struct device *dev, uintptr_t base); #endif /* ZEPHYR_INCLUDE_DRIVERS_DMA_INTEL_LPSS_H_ */ diff --git a/include/zephyr/drivers/dma/dma_mcux_lpc.h b/include/zephyr/drivers/dma/dma_mcux_lpc.h new file mode 100644 index 00000000000..5bae1f8f39e --- /dev/null +++ b/include/zephyr/drivers/dma/dma_mcux_lpc.h @@ -0,0 +1,56 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_DMA_DMA_MCUX_LPC_H_ +#define ZEPHYR_INCLUDE_DRIVERS_DMA_DMA_MCUX_LPC_H_ + +/* + * LPC DMA engine channel hardware trigger attributes. + * These attributes can be set to the "dma_slot" field + * in a dma_config structure to configure a channel for + * hardware triggering. + */ + +/* Peripheral request enable. When set, the peripheral + * request line associated with this channel is used to pace DMA transfers. + */ +#define LPC_DMA_PERIPH_REQ_EN BIT(0) + +/* Hardware trigger enable. When set, the hardware trigger connected to this + * channel via INPUTMUX can be used to trigger a transfer + */ +#define LPC_DMA_HWTRIG_EN BIT(1) + +/* HW trigger polarity. When this bit is set, the trigger will be active + * high or rising edge triggered, based on TRIG_TYPE selection + */ +#define LPC_DMA_TRIGPOL_HIGH_RISING BIT(2) + +/* HW trigger type. When this bit is set, the trigger will be level triggered. + * When it is cleared, the hardware trigger will be edge triggered. + */ +#define LPC_DMA_TRIGTYPE_LEVEL BIT(3) + +/* HW trigger burst mode. When set, the hardware trigger will cause a burst + * transfer to occur, the length of which is determined by BURST_POWER. + * When cleared, a single transfer (of the width selected by XFERCFG register) + * will occur. + */ +#define LPC_DMA_TRIGBURST BIT(4) + +/* HW trigger burst power. Note that due to the size limit of the dma_slot + * field, the maximum transfer burst possible is 128. The hardware supports + * up to 1024 transfers in BURSTPOWER. The value set here will result in + * 2^BURSTPOWER transfers occurring. So for BURSTPOWER=3, 8 transfers would + * occur. + */ +#define LPC_DMA_BURSTPOWER(pwr) (((pwr) & 0x7) << 5) + + +/* Used by driver to extract burstpower setting */ +#define LPC_DMA_GET_BURSTPOWER(slot) (((slot) & 0xE0) >> 5) + +#endif /* ZEPHYR_INCLUDE_DRIVERS_DMA_DMA_MCUX_LPC_H_ */ diff --git a/include/zephyr/drivers/dma/dma_mcux_smartdma.h b/include/zephyr/drivers/dma/dma_mcux_smartdma.h new file mode 100644 index 00000000000..0e09d348d8f --- /dev/null +++ b/include/zephyr/drivers/dma/dma_mcux_smartdma.h @@ -0,0 +1,53 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_DMA_MCUX_SMARTDMA_H_ +#define ZEPHYR_INCLUDE_DRIVERS_DMA_MCUX_SMARTDMA_H_ + +/* Write RGB565 data to MIPI DSI via DMA. */ +#define DMA_SMARTDMA_MIPI_RGB565_DMA 0 +/* Write RGB888 data to MIPI DSI via DMA */ +#define DMA_SMARTDMA_MIPI_RGB888_DMA 1 +/* Write RGB565 data to MIPI DSI via DMA. Rotate output data by 180 degrees */ +#define DMA_SMARTDMA_MIPI_RGB565_180 2 +/* Write RGB888 data to MIPI DSI via DMA. Rotate output data by 180 degrees */ +#define DMA_SMARTDMA_MIPI_RGB888_180 3 + +/* Write RGB565 data to MIPI DSI via DMA. Swap data endianness, so that + * little endian RGB565 data will be written big endian style. + */ +#define DMA_SMARTDMA_MIPI_RGB565_DMA_SWAP 4 +/* Write RGB888 data to MIPI DSI via DMA. Swap data endianness, so that + * little endian RGB888 data will be written big endian style. + */ +#define DMA_SMARTDMA_MIPI_RGB888_DMA_SWAP 5 +/* Write RGB565 data to MIPI DSI via DMA. Rotate output data by 180 degrees, + * and swap data endianness + */ +#define DMA_SMARTDMA_MIPI_RGB565_180_SWAP 6 +/* Write RGB888 data to MIPI DSI via DMA. Rotate output data by 180 degrees, + * and swap data endianness + */ +#define DMA_SMARTDMA_MIPI_RGB888_180_SWAP 7 + + + +/** + * @brief install SMARTDMA firmware + * + * Install a custom firmware for the smartDMA. This function allows the user + * to install a custom firmware into the smartDMA, which implements + * different API functions than the standard MCUX SDK firmware. + * @param dev: smartDMA device + * @param firmware: address of buffer containing smartDMA firmware + * @param len: length of firmware buffer + */ +void dma_smartdma_install_fw(const struct device *dev, uint8_t *firmware, + uint32_t len); + +#define GD32_DMA_FEATURES_FIFO_THRESHOLD(threshold) (threshold & 0x3) + +#endif /* ZEPHYR_INCLUDE_DRIVERS_DMA_MCUX_SMARTDMA_H_ */ diff --git a/include/zephyr/drivers/dma/dma_smartbond.h b/include/zephyr/drivers/dma/dma_smartbond.h new file mode 100644 index 00000000000..c154488039d --- /dev/null +++ b/include/zephyr/drivers/dma/dma_smartbond.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef DMA_SMARTBOND_H_ +#define DMA_SMARTBOND_H_ + +/** + * @brief Vendror-specific DMA peripheral triggering sources. + * + * A valid triggering source should be provided when DMA + * is configured for peripheral to peripheral or memory to peripheral + * transactions. + */ +enum dma_smartbond_trig_mux { + DMA_SMARTBOND_TRIG_MUX_SPI = 0x0, + DMA_SMARTBOND_TRIG_MUX_SPI2 = 0x1, + DMA_SMARTBOND_TRIG_MUX_UART = 0x2, + DMA_SMARTBOND_TRIG_MUX_UART2 = 0x3, + DMA_SMARTBOND_TRIG_MUX_I2C = 0x4, + DMA_SMARTBOND_TRIG_MUX_I2C2 = 0x5, + DMA_SMARTBOND_TRIG_MUX_USB = 0x6, + DMA_SMARTBOND_TRIG_MUX_UART3 = 0x7, + DMA_SMARTBOND_TRIG_MUX_PCM = 0x8, + DMA_SMARTBOND_TRIG_MUX_SRC = 0x9, + DMA_SMARTBOND_TRIG_MUX_GPADC = 0xC, + DMA_SMARTBOND_TRIG_MUX_SDADC = 0xD, + DMA_SMARTBOND_TRIG_MUX_NONE = 0xF +}; + +#endif /* DMA_SMARTBOND_H_ */ diff --git a/include/zephyr/drivers/edac.h b/include/zephyr/drivers/edac.h index 34dcb730dc3..bbdd304bb8e 100644 --- a/include/zephyr/drivers/edac.h +++ b/include/zephyr/drivers/edac.h @@ -16,8 +16,6 @@ #include -typedef void (*edac_notify_callback_f)(const struct device *dev, void *data); - /** * @defgroup edac EDAC API * @ingroup io_interfaces @@ -34,6 +32,14 @@ enum edac_error_type { EDAC_ERROR_TYPE_DRAM_UC = BIT(1) }; +/** + * @cond INTERNAL_HIDDEN + * + * For internal use only, skip these in public documentation. + */ + +typedef void (*edac_notify_callback_f)(const struct device *dev, void *data); + /** * @brief EDAC driver API * @@ -64,7 +70,16 @@ __subsystem struct edac_driver_api { edac_notify_callback_f cb); }; -/* Optional interfaces */ +/** + * INTERNAL_HIDDEN @endcond + */ + +/** + * @name Optional interfaces + * @{ + * + * EDAC Optional Interfaces + */ /** * @brief Set injection parameter param1 @@ -231,7 +246,14 @@ static inline int edac_inject_error_trigger(const struct device *dev) return api->inject_error_trigger(dev); } -/* Mandatory interfaces */ +/** @} */ /* End of EDAC Optional Interfaces */ + +/** + * @name Mandatory interfaces + * @{ + * + * EDAC Mandatory Interfaces + */ /** * @brief Get ECC Error Log @@ -388,8 +410,9 @@ static inline int edac_notify_callback_set(const struct device *dev, return api->notify_cb_set(dev, cb); } -/** - * @} - */ + +/** @} */ /* End of EDAC Mandatory Interfaces */ + +/** @} */ /* End of EDAC API */ #endif /* ZEPHYR_INCLUDE_DRIVERS_EDAC_H_ */ diff --git a/include/zephyr/drivers/eeprom.h b/include/zephyr/drivers/eeprom.h index 2494d3e6754..7da3d2a079d 100644 --- a/include/zephyr/drivers/eeprom.h +++ b/include/zephyr/drivers/eeprom.h @@ -32,11 +32,31 @@ extern "C" { #endif +/** + * @cond INTERNAL_HIDDEN + * + * For internal driver use only, skip these in public documentation. + */ + +/** + * @brief Callback API upon reading from the EEPROM. + * See @a eeprom_read() for argument description + */ typedef int (*eeprom_api_read)(const struct device *dev, off_t offset, void *data, size_t len); + +/** + * @brief Callback API upon writing to the EEPROM. + * See @a eeprom_write() for argument description + */ typedef int (*eeprom_api_write)(const struct device *dev, off_t offset, const void *data, size_t len); + +/** + * @brief Callback API upon getting the EEPROM size. + * See @a eeprom_get_size() for argument description + */ typedef size_t (*eeprom_api_size)(const struct device *dev); __subsystem struct eeprom_driver_api { @@ -45,6 +65,8 @@ __subsystem struct eeprom_driver_api { eeprom_api_size size; }; +/** @endcond */ + /** * @brief Read data from EEPROM * diff --git a/include/zephyr/drivers/emul.h b/include/zephyr/drivers/emul.h index 9ef6fb9ada5..7c306de9889 100644 --- a/include/zephyr/drivers/emul.h +++ b/include/zephyr/drivers/emul.h @@ -191,11 +191,9 @@ const struct emul *emul_get_binding(const char *name); * @} */ -#if defined(CONFIG_HAS_DTS) || defined(__DOXYGEN__) #define Z_MAYBE_EMUL_DECLARE_INTERNAL(node_id) extern const struct emul EMUL_DT_NAME_GET(node_id); DT_FOREACH_STATUS_OKAY_NODE(Z_MAYBE_EMUL_DECLARE_INTERNAL); -#endif /* CONFIG_HAS_DTS || __DOXYGEN__ */ #ifdef __cplusplus } diff --git a/include/zephyr/drivers/emul_fuel_gauge.h b/include/zephyr/drivers/emul_fuel_gauge.h index 63b85d227c1..5abd7ec4f6f 100644 --- a/include/zephyr/drivers/emul_fuel_gauge.h +++ b/include/zephyr/drivers/emul_fuel_gauge.h @@ -54,8 +54,9 @@ __subsystem struct fuel_gauge_emul_driver_api { * @retval 0 If successful. * @retval -EINVAL if mV or mA are 0. */ -static inline int emul_fuel_gauge_set_battery_charging(const struct emul *target, uint32_t uV, - int uA) +__syscall int emul_fuel_gauge_set_battery_charging(const struct emul *target, uint32_t uV, int uA); +static inline int z_impl_emul_fuel_gauge_set_battery_charging(const struct emul *target, + uint32_t uV, int uA) { const struct fuel_gauge_emul_driver_api *backend_api = (const struct fuel_gauge_emul_driver_api *)target->backend_api; @@ -76,7 +77,8 @@ static inline int emul_fuel_gauge_set_battery_charging(const struct emul *target * @retval 0 If successful. * @retval -ENOTSUP if not supported by emulator. */ -static inline int emul_fuel_gauge_is_battery_cutoff(const struct emul *target, bool *cutoff) +__syscall int emul_fuel_gauge_is_battery_cutoff(const struct emul *target, bool *cutoff); +static inline int z_impl_emul_fuel_gauge_is_battery_cutoff(const struct emul *target, bool *cutoff) { const struct fuel_gauge_emul_driver_api *backend_api = (const struct fuel_gauge_emul_driver_api *)target->backend_api; @@ -91,6 +93,8 @@ static inline int emul_fuel_gauge_is_battery_cutoff(const struct emul *target, b } #endif +#include + /** * @} */ diff --git a/include/zephyr/drivers/entropy.h b/include/zephyr/drivers/entropy.h index 2c9ce51f307..1e1573d29a8 100644 --- a/include/zephyr/drivers/entropy.h +++ b/include/zephyr/drivers/entropy.h @@ -29,10 +29,16 @@ extern "C" { #endif +/** @brief Driver is allowed to busy-wait for random data to be ready */ +#define ENTROPY_BUSYWAIT BIT(0) + /** * @typedef entropy_get_entropy_t * @brief Callback API to get entropy. * + * @note This call has to be thread safe to satisfy requirements + * of the random subsystem. + * * See entropy_get_entropy() for argument description */ typedef int (*entropy_get_entropy_t)(const struct device *dev, @@ -48,6 +54,12 @@ typedef int (*entropy_get_entropy_isr_t)(const struct device *dev, uint8_t *buffer, uint16_t length, uint32_t flags); + +/** + * @brief Entropy driver API structure. + * + * This is the mandatory API any Entropy driver needs to expose. + */ __subsystem struct entropy_driver_api { entropy_get_entropy_t get_entropy; entropy_get_entropy_isr_t get_entropy_isr; @@ -79,9 +91,6 @@ static inline int z_impl_entropy_get_entropy(const struct device *dev, return api->get_entropy(dev, buffer, length); } -/* Busy-wait for random data to be ready */ -#define ENTROPY_BUSYWAIT BIT(0) - /** * @brief Fills a buffer with entropy in a non-blocking or busy-wait manner. * Callable from ISRs. diff --git a/include/zephyr/drivers/flash.h b/include/zephyr/drivers/flash.h index de5e7c2116e..ae24ac96a75 100644 --- a/include/zephyr/drivers/flash.h +++ b/include/zephyr/drivers/flash.h @@ -471,6 +471,16 @@ __syscall int flash_ex_op(const struct device *dev, uint16_t code, #define FLASH_EX_OP_VENDOR_BASE 0x8000 #define FLASH_EX_OP_IS_VENDOR(c) ((c) & FLASH_EX_OP_VENDOR_BASE) +/** + * @brief Enumeration for extra flash operations + */ +enum flash_ex_op_types { + /* + * Reset flash device. + */ + FLASH_EX_OP_RESET = 0, +}; + static inline int z_impl_flash_ex_op(const struct device *dev, uint16_t code, const uintptr_t in, void *out) { diff --git a/include/zephyr/drivers/fuel_gauge.h b/include/zephyr/drivers/fuel_gauge.h index 5be69baa8ab..760201d6f76 100644 --- a/include/zephyr/drivers/fuel_gauge.h +++ b/include/zephyr/drivers/fuel_gauge.h @@ -26,9 +26,7 @@ extern "C" { #include -/* Keep these alphabetized wrt property name */ - -enum fuel_gauge_property { +enum fuel_gauge_prop_type { /** Runtime Dynamic Battery Parameters */ /** * Provide a 1 minute average of the current on the battery. @@ -72,9 +70,9 @@ enum fuel_gauge_property { FUEL_GAUGE_VOLTAGE, /** Battery Mode (flags) */ FUEL_GAUGE_SBS_MODE, - /** Battery desired Max Charging Current (mA) */ + /** Battery desired Max Charging Current (uA) */ FUEL_GAUGE_CHARGE_CURRENT, - /** Battery desired Max Charging Voltage (mV) */ + /** Battery desired Max Charging Voltage (uV) */ FUEL_GAUGE_CHARGE_VOLTAGE, /** Alarm, Status and Error codes (flags) */ FUEL_GAUGE_STATUS, @@ -115,109 +113,65 @@ enum fuel_gauge_property { typedef uint16_t fuel_gauge_prop_t; -struct fuel_gauge_get_property { - /** Battery fuel gauge property to get */ - fuel_gauge_prop_t property_type; - - /** Negative error status set by callee e.g. -ENOTSUP for an unsupported property */ - int status; - - /** Property field for getting */ - union { - /* Fields have the format: */ - /* FUEL_GAUGE_PROPERTY_FIELD */ - /* type property_field; */ - - /* Dynamic Battery Info */ - /** FUEL_GAUGE_AVG_CURRENT */ - int avg_current; - /** FUEL_GAUGE_CHARGE_CUTOFF */ - bool cutoff; - /** FUEL_GAUGE_CURRENT */ - int current; - /** FUEL_GAUGE_CYCLE_COUNT */ - uint32_t cycle_count; - /** FUEL_GAUGE_FLAGS */ - uint32_t flags; - /** FUEL_GAUGE_FULL_CHARGE_CAPACITY */ - uint32_t full_charge_capacity; - /** FUEL_GAUGE_REMAINING_CAPACITY */ - uint32_t remaining_capacity; - /** FUEL_GAUGE_RUNTIME_TO_EMPTY */ - uint32_t runtime_to_empty; - /** FUEL_GAUGE_RUNTIME_TO_FULL */ - uint32_t runtime_to_full; - /** FUEL_GAUGE_SBS_MFR_ACCESS */ - uint16_t sbs_mfr_access_word; - /** FUEL_GAUGE_ABSOLUTE_STATE_OF_CHARGE */ - uint8_t absolute_state_of_charge; - /** FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE */ - uint8_t relative_state_of_charge; - /** FUEL_GAUGE_TEMPERATURE */ - uint16_t temperature; - /** FUEL_GAUGE_VOLTAGE */ - int voltage; - /** FUEL_GAUGE_SBS_MODE */ - uint16_t sbs_mode; - /** FUEL_GAUGE_CHARGE_CURRENT */ - uint16_t chg_current; - /** FUEL_GAUGE_CHARGE_VOLTAGE */ - uint16_t chg_voltage; - /** FUEL_GAUGE_STATUS */ - uint16_t fg_status; - /** FUEL_GAUGE_DESIGN_CAPACITY */ - uint16_t design_cap; - /** FUEL_GAUGE_DESIGN_VOLTAGE */ - uint16_t design_volt; - /** FUEL_GAUGE_SBS_ATRATE */ - int16_t sbs_at_rate; - /** FUEL_GAUGE_SBS_ATRATE_TIME_TO_FULL */ - uint16_t sbs_at_rate_time_to_full; - /** FUEL_GAUGE_SBS_ATRATE_TIME_TO_EMPTY */ - uint16_t sbs_at_rate_time_to_empty; - /** FUEL_GAUGE_SBS_ATRATE_OK */ - bool sbs_at_rate_ok; - /** FUEL_GAUGE_SBS_REMAINING_CAPACITY_ALARM */ - uint16_t sbs_remaining_capacity_alarm; - /** FUEL_GAUGE_SBS_REMAINING_TIME_ALARM */ - uint16_t sbs_remaining_time_alarm; - } value; -}; - -struct fuel_gauge_set_property { - /** Battery fuel gauge property to set */ - fuel_gauge_prop_t property_type; - - /** Negative error status set by callee e.g. -ENOTSUP for an unsupported property */ - int status; - - /** Property field for setting */ - union { - /* Fields have the format: */ - /* FUEL_GAUGE_PROPERTY_FIELD */ - /* type property_field; */ - - /* Writable Dynamic Battery Info */ - /** FUEL_GAUGE_SBS_MFR_ACCESS */ - uint16_t sbs_mfr_access_word; - /** FUEL_GAUGE_SBS_REMAINING_CAPACITY_ALARM */ - uint16_t sbs_remaining_capacity_alarm; - /** FUEL_GAUGE_SBS_REMAINING_TIME_ALARM */ - uint16_t sbs_remaining_time_alarm; - /** FUEL_GAUGE_SBS_MODE */ - uint16_t sbs_mode; - /** FUEL_GAUGE_SBS_ATRATE */ - int16_t sbs_at_rate; - } value; -}; - -/** Buffer properties are separated due to size */ -struct fuel_gauge_get_buffer_property { - /** Battery fuel gauge property to get */ - fuel_gauge_prop_t property_type; - - /** Negative error status set by callee e.g. -ENOTSUP for an unsupported property */ - int status; +/** Property field to value/type union */ +union fuel_gauge_prop_val { + /* Fields have the format: */ + /* FUEL_GAUGE_PROPERTY_FIELD */ + /* type property_field; */ + + /* Dynamic Battery Info */ + /** FUEL_GAUGE_AVG_CURRENT */ + int avg_current; + /** FUEL_GAUGE_CHARGE_CUTOFF */ + bool cutoff; + /** FUEL_GAUGE_CURRENT */ + int current; + /** FUEL_GAUGE_CYCLE_COUNT */ + uint32_t cycle_count; + /** FUEL_GAUGE_FLAGS */ + uint32_t flags; + /** FUEL_GAUGE_FULL_CHARGE_CAPACITY */ + uint32_t full_charge_capacity; + /** FUEL_GAUGE_REMAINING_CAPACITY */ + uint32_t remaining_capacity; + /** FUEL_GAUGE_RUNTIME_TO_EMPTY */ + uint32_t runtime_to_empty; + /** FUEL_GAUGE_RUNTIME_TO_FULL */ + uint32_t runtime_to_full; + /** FUEL_GAUGE_SBS_MFR_ACCESS */ + uint16_t sbs_mfr_access_word; + /** FUEL_GAUGE_ABSOLUTE_STATE_OF_CHARGE */ + uint8_t absolute_state_of_charge; + /** FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE */ + uint8_t relative_state_of_charge; + /** FUEL_GAUGE_TEMPERATURE */ + uint16_t temperature; + /** FUEL_GAUGE_VOLTAGE */ + int voltage; + /** FUEL_GAUGE_SBS_MODE */ + uint16_t sbs_mode; + /** FUEL_GAUGE_CHARGE_CURRENT */ + uint32_t chg_current; + /** FUEL_GAUGE_CHARGE_VOLTAGE */ + uint32_t chg_voltage; + /** FUEL_GAUGE_STATUS */ + uint16_t fg_status; + /** FUEL_GAUGE_DESIGN_CAPACITY */ + uint16_t design_cap; + /** FUEL_GAUGE_DESIGN_VOLTAGE */ + uint16_t design_volt; + /** FUEL_GAUGE_SBS_ATRATE */ + int16_t sbs_at_rate; + /** FUEL_GAUGE_SBS_ATRATE_TIME_TO_FULL */ + uint16_t sbs_at_rate_time_to_full; + /** FUEL_GAUGE_SBS_ATRATE_TIME_TO_EMPTY */ + uint16_t sbs_at_rate_time_to_empty; + /** FUEL_GAUGE_SBS_ATRATE_OK */ + bool sbs_at_rate_ok; + /** FUEL_GAUGE_SBS_REMAINING_CAPACITY_ALARM */ + uint16_t sbs_remaining_capacity_alarm; + /** FUEL_GAUGE_SBS_REMAINING_TIME_ALARM */ + uint16_t sbs_remaining_time_alarm; }; /** @@ -248,8 +202,8 @@ struct sbs_gauge_device_chemistry { * * See fuel_gauge_get_property() for argument description */ -typedef int (*fuel_gauge_get_property_t)(const struct device *dev, - struct fuel_gauge_get_property *props, size_t props_len); +typedef int (*fuel_gauge_get_property_t)(const struct device *dev, fuel_gauge_prop_t prop, + union fuel_gauge_prop_val *val); /** * @typedef fuel_gauge_set_property_t @@ -257,8 +211,8 @@ typedef int (*fuel_gauge_get_property_t)(const struct device *dev, * * See fuel_gauge_set_property() for argument description */ -typedef int (*fuel_gauge_set_property_t)(const struct device *dev, - struct fuel_gauge_set_property *props, size_t props_len); +typedef int (*fuel_gauge_set_property_t)(const struct device *dev, fuel_gauge_prop_t prop, + union fuel_gauge_prop_val val); /** * @typedef fuel_gauge_get_buffer_property_t @@ -267,7 +221,7 @@ typedef int (*fuel_gauge_set_property_t)(const struct device *dev, * See fuel_gauge_get_buffer_property() for argument description */ typedef int (*fuel_gauge_get_buffer_property_t)(const struct device *dev, - struct fuel_gauge_get_buffer_property *prop, + fuel_gauge_prop_t prop_type, void *dst, size_t dst_len); /** @@ -281,6 +235,12 @@ typedef int (*fuel_gauge_battery_cutoff_t)(const struct device *dev); /* Caching is entirely on the onus of the client */ __subsystem struct fuel_gauge_driver_api { + /** + * Note: Historically this API allowed drivers to implement a custom multi-get/set property + * function, this was added so drivers could potentially optimize batch read with their + * specific chip. However, it was removed because of no existing concrete case upstream. + * If this need is demonstrated, we can add this back in as an API field. + */ fuel_gauge_get_property_t get_property; fuel_gauge_set_property_t set_property; fuel_gauge_get_buffer_property_t get_buffer_property; @@ -291,21 +251,16 @@ __subsystem struct fuel_gauge_driver_api { * @brief Fetch a battery fuel-gauge property * * @param dev Pointer to the battery fuel-gauge device - * @param props pointer to array of fuel_gauge_get_property struct where the property struct - * field is set by the caller to determine what property is read from the - * fuel gauge device into the fuel_gauge_get_property struct's value field. The props array - * maintains the same order of properties as it was given. - * @param props_len number of properties in props array - * - * @return return=0 if successful, return < 0 if getting all properties failed, return > 0 if some - * properties failed where return=number of failing properties. + * @param prop Type of property to be fetched from device + * @param val pointer to a union fuel_gauge_prop_val where the property is read into from the + * fuel gauge device. + * @return 0 if successful, negative errno code if failure. */ -__syscall int fuel_gauge_get_prop(const struct device *dev, struct fuel_gauge_get_property *props, - size_t props_len); +__syscall int fuel_gauge_get_prop(const struct device *dev, fuel_gauge_prop_t prop, + union fuel_gauge_prop_val *val); -static inline int z_impl_fuel_gauge_get_prop(const struct device *dev, - struct fuel_gauge_get_property *props, - size_t props_len) +static inline int z_impl_fuel_gauge_get_prop(const struct device *dev, fuel_gauge_prop_t prop, + union fuel_gauge_prop_val *val) { const struct fuel_gauge_driver_api *api = (const struct fuel_gauge_driver_api *)dev->api; @@ -313,55 +268,112 @@ static inline int z_impl_fuel_gauge_get_prop(const struct device *dev, return -ENOSYS; } - return api->get_property(dev, props, props_len); + return api->get_property(dev, prop, val); +} + +/** + * @brief Fetch multiple battery fuel-gauge properies. The default implementation is the same as + * calling fuel_gauge_get_prop() multiple times. A driver may implement the `get_properties` field + * of the fuel gauge driver APIs struct to override this implementation. + * + * @param dev Pointer to the battery fuel-gauge device + * @param props Array of the type of property to be fetched from device, each index corresponds + * to the same index of the vals input array. + * @param vals Pointer to array of union fuel_gauge_prop_val where the property is read into from + * the fuel gauge device. The vals array is not permuted. + * @param len number of properties in props & vals array + * + * @return 0 if successful, negative errno code of first failing property + */ + +__syscall int fuel_gauge_get_props(const struct device *dev, fuel_gauge_prop_t *props, + union fuel_gauge_prop_val *vals, size_t len); +static inline int z_impl_fuel_gauge_get_props(const struct device *dev, + fuel_gauge_prop_t *props, + union fuel_gauge_prop_val *vals, size_t len) +{ + const struct fuel_gauge_driver_api *api = dev->api; + + for (int i = 0; i < len; i++) { + int ret = api->get_property(dev, props[i], vals + i); + + if (ret) { + return ret; + } + } + + return 0; } /** * @brief Set a battery fuel-gauge property * * @param dev Pointer to the battery fuel-gauge device - * @param props pointer to array of fuel_gauge_set_property struct where the property struct - * field is set by the caller to determine what property is written to the fuel gauge device from - * the fuel_gauge_get_property struct's value field. - * @param props_len number of properties in props array + * @param prop Type of property that's being set + * @param val Value to set associated prop property. * - * @return return=0 if successful, return < 0 if setting all properties failed, return > 0 if some - * properties failed where return=number of failing properties. + * @return 0 if successful, negative errno code of first failing property */ -__syscall int fuel_gauge_set_prop(const struct device *dev, struct fuel_gauge_set_property *props, - size_t props_len); +__syscall int fuel_gauge_set_prop(const struct device *dev, fuel_gauge_prop_t prop, + union fuel_gauge_prop_val val); -static inline int z_impl_fuel_gauge_set_prop(const struct device *dev, - struct fuel_gauge_set_property *props, - size_t props_len) +static inline int z_impl_fuel_gauge_set_prop(const struct device *dev, fuel_gauge_prop_t prop, + union fuel_gauge_prop_val val) { - const struct fuel_gauge_driver_api *api = (const struct fuel_gauge_driver_api *)dev->api; + const struct fuel_gauge_driver_api *api = dev->api; if (api->set_property == NULL) { return -ENOSYS; } - return api->set_property(dev, props, props_len); + return api->set_property(dev, prop, val); +} +/** + * @brief Set a battery fuel-gauge property + * + * @param dev Pointer to the battery fuel-gauge device + * @param props Array of the type of property to be set, each index corresponds + * to the same index of the vals input array. + * @param vals Pointer to array of union fuel_gauge_prop_val where the property is written + * the fuel gauge device. The vals array is not permuted. + * @param len number of properties in props array + * + * @return return=0 if successful. Otherwise, return array index of failing property. + */ +__syscall int fuel_gauge_set_props(const struct device *dev, fuel_gauge_prop_t *props, + union fuel_gauge_prop_val *vals, size_t len); + +static inline int z_impl_fuel_gauge_set_props(const struct device *dev, + fuel_gauge_prop_t *props, + union fuel_gauge_prop_val *vals, size_t len) +{ + for (int i = 0; i < len; i++) { + int ret = fuel_gauge_set_prop(dev, props[i], vals[i]); + + if (ret) { + return ret; + } + } + + return 0; } /** * @brief Fetch a battery fuel-gauge buffer property * * @param dev Pointer to the battery fuel-gauge device - * @param prop pointer to single fuel_gauge_get_buffer_property struct where the property struct - * field is set by the caller to determine what property is read from the - * fuel gauge device into the dst field. + * @param prop_type Type of property to be fetched from device * @param dst byte array or struct that will hold the buffer data that is read from the fuel gauge * @param dst_len the length of the destination array in bytes * * @return return=0 if successful, return < 0 if getting property failed, return 0 on success */ -__syscall int fuel_gauge_get_buffer_prop(const struct device *dev, - struct fuel_gauge_get_buffer_property *prop, void *dst, - size_t dst_len); + +__syscall int fuel_gauge_get_buffer_prop(const struct device *dev, fuel_gauge_prop_t prop_type, + void *dst, size_t dst_len); static inline int z_impl_fuel_gauge_get_buffer_prop(const struct device *dev, - struct fuel_gauge_get_buffer_property *prop, + fuel_gauge_prop_t prop_type, void *dst, size_t dst_len) { const struct fuel_gauge_driver_api *api = (const struct fuel_gauge_driver_api *)dev->api; @@ -370,7 +382,7 @@ static inline int z_impl_fuel_gauge_get_buffer_prop(const struct device *dev, return -ENOSYS; } - return api->get_buffer_property(dev, prop, dst, dst_len); + return api->get_buffer_property(dev, prop_type, dst, dst_len); } /** diff --git a/include/zephyr/drivers/gna.h b/include/zephyr/drivers/gna.h deleted file mode 100644 index 6fc406507eb..00000000000 --- a/include/zephyr/drivers/gna.h +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2018 Intel Corporation. - * - * Author: Sathish Kuttan - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Public API header file for Intel GNA driver - */ - -#ifndef __INCLUDE_GNA__ -#define __INCLUDE_GNA__ - -/** - * @defgroup gna_interface GNA Interface - * @ingroup io_interfaces - * @{ - * - * This file contains the driver APIs for Intel's - * Gaussian Mixture Model and Neural Network Accelerator (GNA) - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * GNA driver configuration structure. - * Currently empty. - */ -struct gna_config { -#ifdef __cplusplus - char no_empty_structs; /* technically a gcc C extension */ -#endif -}; - -/** - * GNA Neural Network model header - * Describes the key parameters of the neural network model - */ -struct gna_model_header { - uint32_t labase_offset; - uint32_t model_size; - uint32_t gna_mode; - uint32_t layer_count; - uint32_t bytes_per_input; - uint32_t bytes_per_output; - uint32_t num_input_nodes; - uint32_t num_output_nodes; - uint32_t input_ptr_offset; - uint32_t output_ptr_offset; - uint32_t rw_region_size; - uint32_t input_scaling_factor; - uint32_t output_scaling_factor; -}; - -/** - * GNA Neural Network model information to be provided by application - * during model registration - */ -struct gna_model_info { - struct gna_model_header *header; - void *rw_region; - void *ro_region; -}; - -/** - * Request to perform inference on the given neural network model - */ -struct gna_inference_req { - void *model_handle; - void *input; - void *output; - void *intermediate; -}; - -/** - * Statistics of the inference operation returned after completion - */ -struct gna_inference_stats { - uint32_t total_cycles; - uint32_t stall_cycles; - uint32_t cycles_per_sec; -}; - -/** - * Result of an inference operation - */ -enum gna_result { - GNA_RESULT_INFERENCE_COMPLETE, - GNA_RESULT_SATURATION_OCCURRED, - GNA_RESULT_OUTPUT_BUFFER_FULL_ERROR, - GNA_RESULT_PARAM_OUT_OF_RANGE_ERROR, - GNA_RESULT_GENERIC_ERROR, -}; - -/** - * Structure containing a response to the inference request - */ -struct gna_inference_resp { - enum gna_result result; - void *output; - size_t output_len; - struct gna_inference_stats stats; -}; - -/** - * @cond INTERNAL_HIDDEN - * - * Internal documentation. Skip in public documentation - */ -typedef int (*gna_callback)(struct gna_inference_resp *result); - -typedef int (*gna_api_config)(const struct device *dev, - struct gna_config *cfg); -typedef int (*gna_api_register)(const struct device *dev, - struct gna_model_info *model, - void **model_handle); -typedef int (*gna_api_deregister)(const struct device *dev, - void *model_handle); -typedef int (*gna_api_infer)(const struct device *dev, - struct gna_inference_req *req, - gna_callback callback); - -struct gna_driver_api { - gna_api_config configure; - gna_api_register register_model; - gna_api_deregister deregister_model; - gna_api_infer infer; -}; - -/** - * @endcond - */ - -/** - * @brief Configure the GNA device. - * - * Configure the GNA device. The GNA device must be configured before - * registering a model or performing inference - * - * @param dev Pointer to the device structure for the driver instance. - * @param cfg Device configuration information - * - * @retval 0 If the configuration is successful - * @retval A negative error code in case of a failure. - */ -static inline int gna_configure(const struct device *dev, - struct gna_config *cfg) -{ - const struct gna_driver_api *api = - (const struct gna_driver_api *)dev->api; - - return api->configure(dev, cfg); -} - -/** - * @brief Register a neural network model - * - * Register a neural network model with the GNA device - * A model needs to be registered before it can be used to perform inference - * - * @param dev Pointer to the device structure for the driver instance. - * @param model Information about the neural network model - * @param model_handle Handle to the registered model if registration succeeds - * - * @retval 0 If registration of the model is successful. - * @retval A negative error code in case of a failure. - */ -static inline int gna_register_model(const struct device *dev, - struct gna_model_info *model, - void **model_handle) -{ - const struct gna_driver_api *api = - (const struct gna_driver_api *)dev->api; - - return api->register_model(dev, model, model_handle); -} - -/** - * @brief De-register a previously registered neural network model - * - * De-register a previously registered neural network model from the GNA device - * De-registration may be done to free up memory for registering another model - * Once de-registered, the model can no longer be used to perform inference - * - * @param dev Pointer to the device structure for the driver instance. - * @param model Model handle output by gna_register_model API - * - * @retval 0 If de-registration of the model is successful. - * @retval A negative error code in case of a failure. - */ -static inline int gna_deregister_model(const struct device *dev, void *model) -{ - const struct gna_driver_api *api = - (const struct gna_driver_api *)dev->api; - - return api->deregister_model(dev, model); -} - -/** - * @brief Perform inference on a model with input vectors - * - * Make an inference request on a previously registered model with an of - * input data vector - * A callback is provided for notification of inference completion - * - * @param dev Pointer to the device structure for the driver instance. - * @param req Information required to perform inference on a neural network - * @param callback A callback function to notify inference completion - * - * @retval 0 If the request is accepted - * @retval A negative error code in case of a failure. - */ -static inline int gna_infer(const struct device *dev, - struct gna_inference_req *req, - gna_callback callback) -{ - const struct gna_driver_api *api = - (const struct gna_driver_api *)dev->api; - - return api->infer(dev, req, callback); -} - -#ifdef __cplusplus -} -#endif - -/** - * @} - */ - -#endif /* __INCLUDE_GNA__ */ diff --git a/include/zephyr/drivers/gnss.h b/include/zephyr/drivers/gnss.h new file mode 100644 index 00000000000..4c25bd84a43 --- /dev/null +++ b/include/zephyr/drivers/gnss.h @@ -0,0 +1,496 @@ +/* + * Copyright (c) 2023 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file gnss.h + * @brief Public GNSS API. + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_GNSS_H_ +#define ZEPHYR_INCLUDE_DRIVERS_GNSS_H_ + +/** + * @brief GNSS Interface + * @defgroup gnss_interface GNSS Interface + * @ingroup io_interfaces + * @{ + */ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** GNSS PPS modes */ +enum gnss_pps_mode { + /** PPS output disabled */ + GNSS_PPS_MODE_DISABLED = 0, + /** PPS output always enabled */ + GNSS_PPS_MODE_ENABLED = 1, + /** PPS output enabled from first lock */ + GNSS_PPS_MODE_ENABLED_AFTER_LOCK = 2, + /** PPS output enabled while locked */ + GNSS_PPS_MODE_ENABLED_WHILE_LOCKED = 3 +}; + +/** API for setting fix rate */ +typedef int (*gnss_set_fix_rate_t)(const struct device *dev, uint32_t fix_interval_ms); + +/** API for getting fix rate */ +typedef int (*gnss_get_fix_rate_t)(const struct device *dev, uint32_t *fix_interval_ms); + +/** + * @brief GNSS periodic tracking configuration + * + * @note Setting either active_time or inactive_time to 0 will disable periodic + * function. + */ +struct gnss_periodic_config { + /** The time the GNSS will spend in the active state in ms */ + uint32_t active_time_ms; + /** The time the GNSS will spend in the inactive state in ms */ + uint32_t inactive_time_ms; +}; + +/** API for setting periodic tracking configuration */ +typedef int (*gnss_set_periodic_config_t)(const struct device *dev, + const struct gnss_periodic_config *periodic_config); + +/** API for setting periodic tracking configuration */ +typedef int (*gnss_get_periodic_config_t)(const struct device *dev, + struct gnss_periodic_config *periodic_config); + +/** GNSS navigation modes */ +enum gnss_navigation_mode { + /** Dynamics have no impact on tracking */ + GNSS_NAVIGATION_MODE_ZERO_DYNAMICS = 0, + /** Low dynamics have higher impact on tracking */ + GNSS_NAVIGATION_MODE_LOW_DYNAMICS = 1, + /** Low and high dynamics have equal impact on tracking */ + GNSS_NAVIGATION_MODE_BALANCED_DYNAMICS = 2, + /** High dynamics have higher impact on tracking */ + GNSS_NAVIGATION_MODE_HIGH_DYNAMICS = 3 +}; + +/** API for setting navigation mode */ +typedef int (*gnss_set_navigation_mode_t)(const struct device *dev, + enum gnss_navigation_mode mode); + +/** API for getting navigation mode */ +typedef int (*gnss_get_navigation_mode_t)(const struct device *dev, + enum gnss_navigation_mode *mode); + +/** Systems contained in gnss_systems_t */ +enum gnss_system { + /** Global Positioning System (GPS) */ + GNSS_SYSTEM_GPS = BIT(0), + /** GLObal NAvigation Satellite System (GLONASS) */ + GNSS_SYSTEM_GLONASS = BIT(1), + /** Galileo */ + GNSS_SYSTEM_GALILEO = BIT(2), + /** BeiDou Navigation Satellite System */ + GNSS_SYSTEM_BEIDOU = BIT(3), + /** Quasi-Zenith Satellite System (QZSS) */ + GNSS_SYSTEM_QZSS = BIT(4), + /** Indian Regional Navigation Satellite System (IRNSS) */ + GNSS_SYSTEM_IRNSS = BIT(5), + /** Satellite-Based Augmentation System (SBAS) */ + GNSS_SYSTEM_SBAS = BIT(6), + /** Indoor Messaging System (IMES) */ + GNSS_SYSTEM_IMES = BIT(7), +}; + +/** Type storing bitmask of GNSS systems */ +typedef uint32_t gnss_systems_t; + +/** API for enabling systems */ +typedef int (*gnss_set_enabled_systems_t)(const struct device *dev, gnss_systems_t systems); + +/** API for getting enabled systems */ +typedef int (*gnss_get_enabled_systems_t)(const struct device *dev, gnss_systems_t *systems); + +/** API for getting enabled systems */ +typedef int (*gnss_get_supported_systems_t)(const struct device *dev, gnss_systems_t *systems); + +/** GNSS fix status */ +enum gnss_fix_status { + /** No GNSS fix aqcuired */ + GNSS_FIX_STATUS_NO_FIX = 0, + /** GNSS fix aqcuired */ + GNSS_FIX_STATUS_GNSS_FIX = 1, + /** Differential GNSS fix acquired */ + GNSS_FIX_STATUS_DGNSS_FIX = 2, + /** Estimated fix acquired */ + GNSS_FIX_STATUS_ESTIMATED_FIX = 3, +}; + +/** GNSS fix quality */ +enum gnss_fix_quality { + /** Invalid fix */ + GNSS_FIX_QUALITY_INVALID = 0, + /** Standard positioning service */ + GNSS_FIX_QUALITY_GNSS_SPS = 1, + /** Differential GNSS */ + GNSS_FIX_QUALITY_DGNSS = 2, + /** Precise positioning service */ + GNSS_FIX_QUALITY_GNSS_PPS = 3, + /** Real-time kinematic */ + GNSS_FIX_QUALITY_RTK = 4, + /** Floating real-time kinematic */ + GNSS_FIX_QUALITY_FLOAT_RTK = 5, + /** Estimated fix */ + GNSS_FIX_QUALITY_ESTIMATED = 6, +}; + +/** GNSS info data structure */ +struct gnss_info { + /** Number of satellites being tracked */ + uint16_t satellites_cnt; + /** Horizontal dilution of precision in 1/1000 */ + uint16_t hdop; + /** The fix status */ + enum gnss_fix_status fix_status; + /** The fix quality */ + enum gnss_fix_quality fix_quality; +}; + +/** GNSS time data structure */ +struct gnss_time { + /** Hour [0, 23] */ + uint8_t hour; + /** Minute [0, 59] */ + uint8_t minute; + /** Millisecond [0, 59999] */ + uint16_t millisecond; + /** Day of month [1, 31] */ + uint8_t month_day; + /** Month [1, 12] */ + uint8_t month; + /** Year [0, 99] */ + uint8_t century_year; +}; + +/** GNSS API structure */ +__subsystem struct gnss_driver_api { + gnss_set_fix_rate_t set_fix_rate; + gnss_get_fix_rate_t get_fix_rate; + gnss_set_periodic_config_t set_periodic_config; + gnss_get_periodic_config_t get_periodic_config; + gnss_set_navigation_mode_t set_navigation_mode; + gnss_get_navigation_mode_t get_navigation_mode; + gnss_set_enabled_systems_t set_enabled_systems; + gnss_get_enabled_systems_t get_enabled_systems; + gnss_get_supported_systems_t get_supported_systems; +}; + +/** GNSS data structure */ +struct gnss_data { + /** Navigation data acquired */ + struct navigation_data nav_data; + /** GNSS info when navigation data was acquired */ + struct gnss_info info; + /** UTC time when data was acquired */ + struct gnss_time utc; +}; + +/** Template for GNSS data callback */ +typedef void (*gnss_data_callback_t)(const struct device *dev, const struct gnss_data *data); + +/** GNSS callback structure */ +struct gnss_data_callback { + /** Filter callback to GNSS data from this device if not NULL */ + const struct device *dev; + /** Callback called when GNSS data is published */ + gnss_data_callback_t callback; +}; + +/** GNSS satellite structure */ +struct gnss_satellite { + /** Pseudo-random noise sequence */ + uint8_t prn; + /** Signal-to-noise ratio in dB */ + uint8_t snr; + /** Elevation in degrees [0, 90] */ + uint8_t elevation; + /** Azimuth relative to True North in degrees [0, 359] */ + uint16_t azimuth; + /** System of satellite */ + enum gnss_system system; + /** True if satellite is being tracked */ + uint8_t is_tracked : 1; +}; + +/** Template for GNSS satellites callback */ +typedef void (*gnss_satellites_callback_t)(const struct device *dev, + const struct gnss_satellite *satellites, + uint16_t size); + +/** GNSS callback structure */ +struct gnss_satellites_callback { + /** Filter callback to GNSS data from this device if not NULL */ + const struct device *dev; + /** Callback called when GNSS satellites is published */ + gnss_satellites_callback_t callback; +}; + +/** + * @brief Set the GNSS fix rate + * + * @param dev Device instance + * @param fix_interval_ms Fix interval to set in milliseconds + * + * @return 0 if successful + * @return -errno negative errno code on failure + */ +__syscall int gnss_set_fix_rate(const struct device *dev, uint32_t fix_interval_ms); + +static inline int z_impl_gnss_set_fix_rate(const struct device *dev, uint32_t fix_interval_ms) +{ + const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api; + + if (api->set_fix_rate == NULL) { + return -ENOSYS; + } + + return api->set_fix_rate(dev, fix_interval_ms); +} + +/** + * @brief Get the GNSS fix rate + * + * @param dev Device instance + * @param fix_interval_ms Destination for fix interval in milliseconds + * + * @return 0 if successful + * @return -errno negative errno code on failure + */ +__syscall int gnss_get_fix_rate(const struct device *dev, uint32_t *fix_interval_ms); + +static inline int z_impl_gnss_get_fix_rate(const struct device *dev, uint32_t *fix_interval_ms) +{ + const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api; + + if (api->get_fix_rate == NULL) { + return -ENOSYS; + } + + return api->get_fix_rate(dev, fix_interval_ms); +} + +/** + * @brief Set the GNSS periodic tracking configuration + * + * @param dev Device instance + * @param config Periodic tracking configuration to set + * + * @return 0 if successful + * @return -errno negative errno code on failure + */ +__syscall int gnss_set_periodic_config(const struct device *dev, + const struct gnss_periodic_config *config); + +static inline int z_impl_gnss_set_periodic_config(const struct device *dev, + const struct gnss_periodic_config *config) +{ + const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api; + + if (api->set_periodic_config == NULL) { + return -ENOSYS; + } + + return api->set_periodic_config(dev, config); +} + +/** + * @brief Get the GNSS periodic tracking configuration + * + * @param dev Device instance + * @param config Destination for periodic tracking configuration + * + * @return 0 if successful + * @return -errno negative errno code on failure + */ +__syscall int gnss_get_periodic_config(const struct device *dev, + struct gnss_periodic_config *config); + +static inline int z_impl_gnss_get_periodic_config(const struct device *dev, + struct gnss_periodic_config *config) +{ + const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api; + + if (api->get_periodic_config == NULL) { + return -ENOSYS; + } + + return api->get_periodic_config(dev, config); +} + +/** + * @brief Set the GNSS navigation mode + * + * @param dev Device instance + * @param mode Navigation mode to set + * + * @return 0 if successful + * @return -errno negative errno code on failure + */ +__syscall int gnss_set_navigation_mode(const struct device *dev, + enum gnss_navigation_mode mode); + +static inline int z_impl_gnss_set_navigation_mode(const struct device *dev, + enum gnss_navigation_mode mode) +{ + const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api; + + if (api->set_navigation_mode == NULL) { + return -ENOSYS; + } + + return api->set_navigation_mode(dev, mode); +} + +/** + * @brief Get the GNSS navigation mode + * + * @param dev Device instance + * @param mode Destination for navigation mode + * + * @return 0 if successful + * @return -errno negative errno code on failure + */ +__syscall int gnss_get_navigation_mode(const struct device *dev, + enum gnss_navigation_mode *mode); + +static inline int z_impl_gnss_get_navigation_mode(const struct device *dev, + enum gnss_navigation_mode *mode) +{ + const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api; + + if (api->get_navigation_mode == NULL) { + return -ENOSYS; + } + + return api->get_navigation_mode(dev, mode); +} + +/** + * @brief Set enabled GNSS systems + * + * @param dev Device instance + * @param systems Systems to enable + * + * @return 0 if successful + * @return -errno negative errno code on failure + */ +__syscall int gnss_set_enabled_systems(const struct device *dev, gnss_systems_t systems); + +static inline int z_impl_gnss_set_enabled_systems(const struct device *dev, + gnss_systems_t systems) +{ + const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api; + + if (api->set_enabled_systems == NULL) { + return -ENOSYS; + } + + return api->set_enabled_systems(dev, systems); +} + +/** + * @brief Get enabled GNSS systems + * + * @param dev Device instance + * @param systems Destination for enabled systems + * + * @return 0 if successful + * @return -errno negative errno code on failure + */ +__syscall int gnss_get_enabled_systems(const struct device *dev, gnss_systems_t *systems); + +static inline int z_impl_gnss_get_enabled_systems(const struct device *dev, + gnss_systems_t *systems) +{ + const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api; + + if (api->get_enabled_systems == NULL) { + return -ENOSYS; + } + + return api->get_enabled_systems(dev, systems); +} + +/** + * @brief Get supported GNSS systems + * + * @param dev Device instance + * @param systems Destination for supported systems + * + * @return 0 if successful + * @return -errno negative errno code on failure + */ +__syscall int gnss_get_supported_systems(const struct device *dev, gnss_systems_t *systems); + +static inline int z_impl_gnss_get_supported_systems(const struct device *dev, + gnss_systems_t *systems) +{ + const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api; + + if (api->get_supported_systems == NULL) { + return -ENOSYS; + } + + return api->get_supported_systems(dev, systems); +} + +/** + * @brief Register a callback structure for GNSS data published + * + * @param _dev Device pointer + * @param _callback The callback function + */ +#if CONFIG_GNSS +#define GNSS_DATA_CALLBACK_DEFINE(_dev, _callback) \ + static const STRUCT_SECTION_ITERABLE(gnss_data_callback, \ + _gnss_data_callback__##_callback) = { \ + .dev = _dev, \ + .callback = _callback, \ + } +#else +#define GNSS_DATA_CALLBACK_DEFINE(_dev, _callback) +#endif + +/** + * @brief Register a callback structure for GNSS satellites published + * + * @param _dev Device pointer + * @param _callback The callback function + */ +#if CONFIG_GNSS_SATELLITES +#define GNSS_SATELLITES_CALLBACK_DEFINE(_dev, _callback) \ + static const STRUCT_SECTION_ITERABLE(gnss_satellites_callback, \ + _gnss_satellites_callback__##_callback) = { \ + .dev = _dev, \ + .callback = _callback, \ + } +#else +#define GNSS_SATELLITES_CALLBACK_DEFINE(_dev, _callback) +#endif + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#include + +#endif /* ZEPHYR_INCLUDE_DRIVERS_GNSS_H_ */ diff --git a/include/zephyr/drivers/gpio.h b/include/zephyr/drivers/gpio.h index 3d77108b853..99d6d677a65 100644 --- a/include/zephyr/drivers/gpio.h +++ b/include/zephyr/drivers/gpio.h @@ -846,6 +846,7 @@ static inline bool gpio_is_ready_dt(const struct gpio_dt_spec *spec) * @param flags Interrupt configuration flags as defined by GPIO_INT_*. * * @retval 0 If successful. + * @retval -ENOSYS If the operation is not implemented by the driver. * @retval -ENOTSUP If any of the configuration options is not supported * (unless otherwise directed by flag documentation). * @retval -EINVAL Invalid argument. @@ -871,6 +872,10 @@ static inline int z_impl_gpio_pin_interrupt_configure(const struct device *port, enum gpio_int_trig trig; enum gpio_int_mode mode; + if (api->pin_interrupt_configure == NULL) { + return -ENOSYS; + } + __ASSERT((flags & (GPIO_INT_DISABLE | GPIO_INT_ENABLE)) != (GPIO_INT_DISABLE | GPIO_INT_ENABLE), "Cannot both enable and disable interrupts"); @@ -1695,7 +1700,9 @@ static inline void gpio_init_callback(struct gpio_callback *callback, * @brief Add an application callback. * @param port Pointer to the device structure for the driver instance. * @param callback A valid Application's callback structure pointer. - * @return 0 if successful, negative errno code on failure. + * @retval 0 If successful + * @retval -ENOSYS If driver does not implement the operation + * @retval -errno Other negative errno code on failure. * * @note Callbacks may be added to the device from within a callback * handler invocation, but whether they are invoked for the current @@ -1710,7 +1717,7 @@ static inline int gpio_add_callback(const struct device *port, (const struct gpio_driver_api *)port->api; if (api->manage_callback == NULL) { - return -ENOTSUP; + return -ENOSYS; } return api->manage_callback(port, callback, true); @@ -1737,7 +1744,9 @@ static inline int gpio_add_callback_dt(const struct gpio_dt_spec *spec, * @brief Remove an application callback. * @param port Pointer to the device structure for the driver instance. * @param callback A valid application's callback structure pointer. - * @return 0 if successful, negative errno code on failure. + * @retval 0 If successful + * @retval -ENOSYS If driver does not implement the operation + * @retval -errno Other negative errno code on failure. * * @warning It is explicitly permitted, within a callback handler, to * remove the registration for the callback that is running, i.e. @p @@ -1756,7 +1765,7 @@ static inline int gpio_remove_callback(const struct device *port, (const struct gpio_driver_api *)port->api; if (api->manage_callback == NULL) { - return -ENOTSUP; + return -ENOSYS; } return api->manage_callback(port, callback, false); @@ -1791,6 +1800,7 @@ static inline int gpio_remove_callback_dt(const struct gpio_dt_spec *spec, * * @retval status != 0 if at least one gpio interrupt is pending. * @retval 0 if no gpio interrupt is pending. + * @retval -ENOSYS If driver does not implement the operation */ __syscall int gpio_get_pending_int(const struct device *dev); @@ -1800,7 +1810,7 @@ static inline int z_impl_gpio_get_pending_int(const struct device *dev) (const struct gpio_driver_api *)dev->api; if (api->get_pending_int == NULL) { - return -ENOTSUP; + return -ENOSYS; } return api->get_pending_int(dev); diff --git a/include/zephyr/drivers/i2c.h b/include/zephyr/drivers/i2c.h index 95d0cf1e9c1..f0268322ecb 100644 --- a/include/zephyr/drivers/i2c.h +++ b/include/zephyr/drivers/i2c.h @@ -227,7 +227,7 @@ typedef int (*i2c_api_transfer_cb_t)(const struct device *dev, i2c_callback_t cb, void *userdata); #endif /* CONFIG_I2C_CALLBACK */ -#if defined(CONFIG_I2C_RTIO) || defined(DOXYGEN) +#if defined(CONFIG_I2C_RTIO) || defined(__DOXYGEN__) /** * @typedef i2c_api_iodev_submit @@ -488,33 +488,33 @@ static inline bool i2c_is_ready_dt(const struct i2c_dt_spec *spec) * D: R len=01: 6c * @endcode * - * @param name Name of this dump, displayed at the top. + * @param dev Target for the messages being sent. Its name will be printed in the log. * @param msgs Array of messages to dump. * @param num_msgs Number of messages to dump. * @param addr Address of the I2C target device. * @param dump_read Dump data from I2C reads, otherwise only writes have data dumped. */ -void i2c_dump_msgs_rw(const char *name, const struct i2c_msg *msgs, - uint8_t num_msgs, uint16_t addr, bool dump_read); +void i2c_dump_msgs_rw(const struct device *dev, const struct i2c_msg *msgs, uint8_t num_msgs, + uint16_t addr, bool dump_read); /** * @brief Dump out an I2C message, before it is executed. * * This is equivalent to: * - * i2c_dump_msgs_rw(name, msgs, num_msgs, addr, false); + * i2c_dump_msgs_rw(dev, msgs, num_msgs, addr, false); * * The read messages' data isn't dumped. * - * @param name Name of this dump, displayed at the top. + * @param dev Target for the messages being sent. Its name will be printed in the log. * @param msgs Array of messages to dump. * @param num_msgs Number of messages to dump. * @param addr Address of the I2C target device. */ -static inline void i2c_dump_msgs(const char *name, const struct i2c_msg *msgs, +static inline void i2c_dump_msgs(const struct device *dev, const struct i2c_msg *msgs, uint8_t num_msgs, uint16_t addr) { - i2c_dump_msgs_rw(name, msgs, num_msgs, addr, false); + i2c_dump_msgs_rw(dev, msgs, num_msgs, addr, false); } #if defined(CONFIG_I2C_STATS) || defined(__DOXYGEN__) @@ -772,13 +772,13 @@ static inline int z_impl_i2c_transfer(const struct device *dev, i2c_xfer_stats(dev, msgs, num_msgs); if (IS_ENABLED(CONFIG_I2C_DUMP_MESSAGES)) { - i2c_dump_msgs_rw(dev->name, msgs, num_msgs, addr, true); + i2c_dump_msgs_rw(dev, msgs, num_msgs, addr, true); } return res; } -#ifdef CONFIG_I2C_CALLBACK +#if defined(CONFIG_I2C_CALLBACK) || defined(__DOXYGEN__) /** * @brief Perform data transfer to another I2C device in controller mode. @@ -787,7 +787,7 @@ static inline int z_impl_i2c_transfer(const struct device *dev, * to another I2C device asynchronously with a callback completion. * * @see i2c_transfer() - * @funcprop \isr_ok + * @funcprops \isr_ok * * @param dev Pointer to the device structure for an I2C controller * driver configured in controller mode. @@ -915,7 +915,7 @@ static inline int i2c_write_read_cb_dt(const struct i2c_dt_spec *spec, struct i2 read_buf, num_read, cb, userdata); } -#ifdef CONFIG_POLL +#if defined(CONFIG_POLL) || defined(__DOXYGEN__) /** @cond INTERNAL_HIDDEN */ void z_i2c_transfer_signal_cb(const struct device *dev, int result, void *userdata); @@ -928,14 +928,14 @@ void z_i2c_transfer_signal_cb(const struct device *dev, int result, void *userda * to another I2C device asynchronously with a k_poll_signal completion. * * @see i2c_transfer_cb() - * @funcprop \isr_ok + * @funcprops \isr_ok * * @param dev Pointer to the device structure for an I2C controller * driver configured in controller mode. * @param msgs Array of messages to transfer, must live until callback completes. * @param num_msgs Number of messages to transfer. * @param addr Address of the I2C target device. - * @param signal Signal to notify of transfer completion. + * @param sig Signal to notify of transfer completion. * * @retval 0 If successful. * @retval -EIO General input / output error. @@ -962,7 +962,7 @@ static inline int i2c_transfer_signal(const struct device *dev, #endif /* CONFIG_I2C_CALLBACK */ -#if defined(CONFIG_I2C_RTIO) || defined(DOXYGEN) +#if defined(CONFIG_I2C_RTIO) || defined(__DOXYGEN__) /** * @brief Submit request(s) to an I2C device with RTIO @@ -987,7 +987,8 @@ extern const struct rtio_iodev_api i2c_iodev_api; * These do not need to be shared globally but doing so * will save a small amount of memory. * - * @param node DT_NODE + * @param name Symbolic name of the iodev to define + * @param node_id Devicetree node identifier */ #define I2C_DT_IODEV_DEFINE(name, node_id) \ const struct i2c_dt_spec _i2c_dt_spec_##name = \ diff --git a/include/zephyr/drivers/i3c.h b/include/zephyr/drivers/i3c.h index 58a85d35566..36a93fc01de 100644 --- a/include/zephyr/drivers/i3c.h +++ b/include/zephyr/drivers/i3c.h @@ -27,8 +27,9 @@ extern "C" { #endif -/* - * Bus Characteristic Register (BCR) +/** + * @name Bus Characteristic Register (BCR) + * * - BCR[7:6]: Device Role * - 0: I3C Target * - 1: I3C Controller capable @@ -55,24 +56,82 @@ extern "C" { * - BCR[0]: Max Data Speed Limitation * - 0: No Limitation * - 1: Limitation obtained via GETMXDS CCC. + * + * @{ + */ + +/** + * @brief Max Data Speed Limitation bit. + * + * 0 - No Limitation. + * 1 - Limitation obtained via GETMXDS CCC. */ #define I3C_BCR_MAX_DATA_SPEED_LIMIT BIT(0) + +/** @brief IBI Request Capable bit. */ #define I3C_BCR_IBI_REQUEST_CAPABLE BIT(1) + +/** + * @brief IBI Payload bit. + * + * 0 - No data bytes following the accepted IBI. + * 1 - One data byte (MDB, Mandatory Data Byte) follows the accepted IBI. + * Additional data bytes may also follows. + */ #define I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE BIT(2) + +/** + * @brief Offline Capable bit. + * + * 0 - Will always respond to I3C commands. + * 1 - Will not always respond to I3C commands. + */ #define I3C_BCR_OFFLINE_CAPABLE BIT(3) + +/** + * @brief Virtual Target Support bit. + * + * 0 - Is not a virtual target. + * 1 - Is a virtual target. + */ #define I3C_BCR_VIRTUAL_TARGET BIT(4) + +/** + * @brief Advanced Capabilities bit. + * + * 0 - Does not support optional advanced capabilities. + * 1 - Supports optional advanced capabilities which can be viewed via + * GETCAPS CCC. + */ #define I3C_BCR_ADV_CAPABILITIES BIT(5) +/** Device Role - I3C Target. */ #define I3C_BCR_DEVICE_ROLE_I3C_TARGET 0U + +/** Device Role - I3C Controller Capable. */ #define I3C_BCR_DEVICE_ROLE_I3C_CONTROLLER_CAPABLE 1U +/** Device Role bit shift value. */ #define I3C_BCR_DEVICE_ROLE_SHIFT 6U + +/** Device Role bit shift mask. */ #define I3C_BCR_DEVICE_ROLE_MASK (0x03U << I3C_BCR_DEVICE_ROLE_SHIFT) +/** + * @brief Device Role + * + * Obtain Device Role value from the BCR value obtained via GETBCR. + * + * @param bcr BCR value + */ #define I3C_BCR_DEVICE_ROLE(bcr) \ (((bcr) & I3C_BCR_DEVICE_ROLE_MASK) >> I3C_BCR_DEVICE_ROLE_SHIFT) -/* +/** @} */ + +/** + * @name Device Characteristic Register (DCR) + * * Legacy Virtual Register (LVR) * - LVR[7:5]: I2C device index: * - 0: I2C device has a 50 ns spike filter where @@ -85,26 +144,74 @@ extern "C" { * - 0: FM+ mode * - 1: FM mode * - LVR[3:0]: Reserved. + * + * @{ */ + +/** I2C FM+ Mode. */ #define I3C_DCR_I2C_FM_PLUS_MODE 0 + +/** I2C FM Mode. */ #define I3C_DCR_I2C_FM_MODE 1 +/** I2C Mode Indicator bit shift value. */ #define I3C_DCR_I2C_MODE_SHIFT 4 + +/** I2C Mode Indicator bitmask. */ #define I3C_DCR_I2C_MODE_MASK BIT(4) +/** + * @brief I2C Mode + * + * Obtain I2C Mode value from the DCR value obtained via GETDCR. + * + * @param dcr DCR value + */ #define I3C_DCR_I2C_MODE(dcr) \ (((mode) & I3C_DCR_I2C_MODE_MASK) >> I3C_DCR_I2C_MODE_SHIFT) +/** + * @brief I2C Device Index 0. + * + * I2C device has a 50 ns spike filter where it is not affected by high + * frequency on SCL. + */ #define I3C_DCR_I2C_DEV_IDX_0 0 + +/** + * @brief I2C Device Index 1. + * + * I2C device does not have a 50 ns spike filter but can work with high + * frequency on SCL. + */ #define I3C_DCR_I2C_DEV_IDX_1 1 + +/** + * @brief I2C Device Index 2. + * + * I2C device does not have a 50 ns spike filter and cannot work with high + * frequency on SCL. + */ #define I3C_DCR_I2C_DEV_IDX_2 2 +/** I2C Device Index bit shift value. */ #define I3C_DCR_I2C_DEV_IDX_SHIFT 5 + +/** I2C Device Index bitmask. */ #define I3C_DCR_I2C_DEV_IDX_MASK (0x07U << I3C_DCR_I2C_DEV_IDX_SHIFT) +/** + * @brief I2C Device Index + * + * Obtain I2C Device Index value from the DCR value obtained via GETDCR. + * + * @param dcr DCR value + */ #define I3C_DCR_I2C_DEV_IDX(dcr) \ (((dcr) & I3C_DCR_I2C_DEV_IDX_MASK) >> I3C_DCR_I2C_DEV_IDX_SHIFT) +/** @} */ + /** * @brief I3C bus mode */ @@ -258,6 +365,12 @@ enum i3c_sdr_target_error_codes { I3C_ERROR_TE_INVALID, }; +/** + * @brief I3C Transfer API + * @defgroup i3c_transfer_api I3C Transfer API + * @{ + */ + /* * I3C_MSG_* are I3C Message flags. */ @@ -328,6 +441,13 @@ enum i3c_sdr_target_error_codes { /** I3C HDR-BT (Bulk Transport) */ #define I3C_MSG_HDR_BT I3C_MSG_HDR_MODE3 +/** @} */ + +/** + * @addtogroup i3c_transfer_api + * @{ + */ + /** * @brief One I3C Message. * @@ -361,6 +481,8 @@ struct i3c_msg { uint8_t hdr_mode; }; +/** @} */ + /** * @brief Type of configuration being passed to configure function. */ @@ -770,8 +892,13 @@ struct i3c_device_id { * Field @c node should not be initialized or modified manually. */ struct i3c_device_desc { - /** Private, do not modify */ + /** + * Used to attach this node onto a linked list. + * + * @cond INTERNAL_HIDDEN + */ sys_snode_t node; + /** @endcond */ /** I3C bus to which this target device is attached */ const struct device * const bus; @@ -894,8 +1021,13 @@ struct i3c_device_desc { uint8_t max_ibi; } data_length; - /** Private data by the controller to aid in transactions. Do not modify. */ + /** + * Private data by the controller to aid in transactions. Do not modify. + * + * @cond INTERNAL_HIDDEN + */ void *controller_priv; + /** @endcond */ #if defined(CONFIG_I3C_USE_IBI) || defined(__DOXYGEN__) /** @@ -919,8 +1051,13 @@ struct i3c_device_desc { * reference to I3C controller device APIs. */ struct i3c_i2c_device_desc { - /** Private, do not modify */ + /** + * Used to attach this node onto a linked list. + * + * @cond INTERNAL_HIDDEN + */ sys_snode_t node; + /** @endcond */ /** I3C bus to which this I2C device is attached */ const struct device *bus; @@ -944,8 +1081,13 @@ struct i3c_i2c_device_desc { */ const uint8_t lvr; - /** Private data by the controller to aid in transactions. Do not modify. */ + /** + * Private data by the controller to aid in transactions. Do not modify. + * + * @cond INTERNAL_HIDDEN + */ void *controller_priv; + /** @endcond */ }; /** @@ -1400,6 +1542,11 @@ static inline int z_impl_i3c_do_ccc(const struct device *dev, return api->do_ccc(dev, payload); } +/** + * @addtogroup i3c_transfer_api + * @{ + */ + /** * @brief Perform data transfer from the controller to a I3C target device. * @@ -1438,6 +1585,8 @@ static inline int z_impl_i3c_transfer(struct i3c_device_desc *target, return api->i3c_xfers(target->bus, target, msgs, num_msgs); } +/** @} */ + /** * Find a registered I3C target device. * @@ -1466,6 +1615,11 @@ struct i3c_device_desc *i3c_device_find(const struct device *dev, return api->i3c_device_find(dev, id); } +/** + * @addtogroup i3c_ibi + * @{ + */ + /** * @brief Raise an In-Band Interrupt (IBI). * @@ -1574,6 +1728,13 @@ static inline int i3c_device_is_ibi_capable(struct i3c_device_desc *target) == I3C_BCR_IBI_REQUEST_CAPABLE; } +/** @} */ + +/** + * @addtogroup i3c_transfer_api + * @{ + */ + /** * @brief Write a set amount of data to an I3C target device. * @@ -1835,6 +1996,8 @@ static inline int i3c_reg_update_byte(struct i3c_device_desc *target, void i3c_dump_msgs(const char *name, const struct i3c_msg *msgs, uint8_t num_msgs, struct i3c_device_desc *target); +/** @} */ + /** * @brief Generic helper function to perform bus initialization. * diff --git a/include/zephyr/drivers/i3c/addresses.h b/include/zephyr/drivers/i3c/addresses.h index 95f05f180e1..c85255d8a69 100644 --- a/include/zephyr/drivers/i3c/addresses.h +++ b/include/zephyr/drivers/i3c/addresses.h @@ -22,16 +22,32 @@ extern "C" { #endif +/** Broadcast Address on I3C bus. */ #define I3C_BROADCAST_ADDR 0x7E + +/** Maximum value of device addresses. */ #define I3C_MAX_ADDR 0x7F struct i3c_dev_list; +/** + * Enum to indicate whether an address is reserved, has I2C/I3C device attached, + * or no device attached. + */ enum i3c_addr_slot_status { + /** Address has not device attached. */ I3C_ADDR_SLOT_STATUS_FREE = 0U, + + /** Address is reserved. */ I3C_ADDR_SLOT_STATUS_RSVD, + + /** Address is associated with an I3C device. */ I3C_ADDR_SLOT_STATUS_I3C_DEV, + + /** Address is associated with an I2C device. */ I3C_ADDR_SLOT_STATUS_I2C_DEV, + + /** Bit masks used to filter status bits. */ I3C_ADDR_SLOT_STATUS_MASK = 0x03U, }; @@ -97,10 +113,11 @@ bool i3c_addr_slots_is_free(struct i3c_addr_slots *slots, * assigned to a new device. * * @param slots Pointer to the address slots structure. + * @param start_addr Where to start searching * * @return The next free address, or 0 if none found. */ -uint8_t i3c_addr_slots_next_free_find(struct i3c_addr_slots *slots); +uint8_t i3c_addr_slots_next_free_find(struct i3c_addr_slots *slots, uint8_t start_addr); /** * @brief Mark the address as free (not used) in device list. diff --git a/include/zephyr/drivers/i3c/ccc.h b/include/zephyr/drivers/i3c/ccc.h index fcb0ac6e1e4..606d44f79ae 100644 --- a/include/zephyr/drivers/i3c/ccc.h +++ b/include/zephyr/drivers/i3c/ccc.h @@ -304,17 +304,25 @@ struct i3c_ccc_events { uint8_t events; } __packed; -/* For Enable Events */ +/** Enable Events (ENEC) - Target Interrupt Requests. */ #define I3C_CCC_ENEC_EVT_ENINTR BIT(0) + +/** Enable Events (ENEC) - Controller Role Requests. */ #define I3C_CCC_ENEC_EVT_ENCR BIT(1) + +/** Enable Events (ENEC) - Hot-Join Event. */ #define I3C_CCC_ENEC_EVT_ENHJ BIT(3) #define I3C_CCC_ENEC_EVT_ALL \ (I3C_CCC_ENEC_EVT_ENINTR | I3C_CCC_ENEC_EVT_ENCR | I3C_CCC_ENEC_EVT_ENHJ) -/* For Disable Events */ +/** Disable Events (DISEC) - Target Interrupt Requests. */ #define I3C_CCC_DISEC_EVT_DISINTR BIT(0) + +/** Disable Events (DISEC) - Controller Role Requests. */ #define I3C_CCC_DISEC_EVT_DISCR BIT(1) + +/** Disable Events (DISEC) - Hot-Join Event. */ #define I3C_CCC_DISEC_EVT_DISHJ BIT(3) #define I3C_CCC_DISEC_EVT_ALL \ @@ -324,10 +332,17 @@ struct i3c_ccc_events { * Events for both enabling and disabling since * they have the same bits. */ + +/** Events - Target Interrupt Requests. */ #define I3C_CCC_EVT_INTR BIT(0) + +/** Events - Controller Role Requests. */ #define I3C_CCC_EVT_CR BIT(1) + +/** Events - Hot-Join Event. */ #define I3C_CCC_EVT_HJ BIT(3) +/** Bitmask for all events. */ #define I3C_CCC_EVT_ALL \ (I3C_CCC_EVT_INTR | I3C_CCC_EVT_CR | I3C_CCC_EVT_HJ) @@ -488,14 +503,24 @@ struct i3c_ccc_getdcr { * @brief Indicate which format of GETSTATUS to use. */ enum i3c_ccc_getstatus_fmt { + /** GETSTATUS Format 1 */ GETSTATUS_FORMAT_1, + + /** GETSTATUS Format 2 */ GETSTATUS_FORMAT_2, }; +/** + * @brief Defining byte values for GETSTATUS Format 2. + */ enum i3c_ccc_getstatus_defbyte { + /** Target status. */ GETSTATUS_FORMAT_2_TGTSTAT = 0x00U, + + /** PRECR - Alternate status format describing Controller-capable device. */ GETSTATUS_FORMAT_2_PRECR = 0x91U, + /** Invalid defining byte. */ GETSTATUS_FORMAT_2_INVALID = 0x100U }; @@ -546,28 +571,51 @@ union i3c_ccc_getstatus { } fmt2; } __packed; +/** GETSTATUS Format 1 - Protocol Error bit. */ #define I3C_CCC_GETSTATUS_PROTOCOL_ERR BIT(5) +/** GETSTATUS Format 1 - Activity Mode bit shift value. */ #define I3C_CCC_GETSTATUS_ACTIVITY_MODE_SHIFT 6 +/** GETSTATUS Format 1 - Activity Mode bitmask. */ #define I3C_CCC_GETSTATUS_ACTIVITY_MODE_MASK \ (0x03U << I3C_CCC_GETSTATUS_ACTIVITY_MODE_SHIFT) +/** + * @brief GETSTATUS Format 1 - Activity Mode + * + * Obtain Activity Mode from GETSTATUS Format 1 value obtained via + * GETSTATUS. + * + * @param status GETSTATUS Format 1 value + */ #define I3C_CCC_GETSTATUS_ACTIVITY_MODE(status) \ (((status) & I3C_CCC_GETSTATUS_ACTIVITY_MODE_MASK) \ >> I3C_CCC_GETSTATUS_ACTIVITY_MODE_SHIFT) +/** GETSTATUS Format 1 - Number of Pending Interrupts bit shift value. */ #define I3C_CCC_GETSTATUS_NUM_INT_SHIFT 0 +/** GETSTATUS Format 1 - Number of Pending Interrupts bitmask. */ #define I3C_CCC_GETSTATUS_NUM_INT_MASK \ (0x0FU << I3C_CCC_GETSTATUS_NUM_INT_SHIFT) +/** + * @brief GETSTATUS Format 1 - Number of Pending Interrupts + * + * Obtain Number of Pending Interrupts from GETSTATUS Format 1 value + * obtained via GETSTATUS. + * + * @param status GETSTATUS Format 1 value + */ #define I3C_CCC_GETSTATUS_NUM_INT(status) \ (((status) & I3C_CCC_GETSTATUS_NUM_INT_MASK) \ >> I3C_CCC_GETSTATUS_NUM_INT_SHIFT) +/** GETSTATUS Format 2 - PERCR - Deep Sleep Detected bit. */ #define I3C_CCC_GETSTATUS_PRECR_DEEP_SLEEP_DETECTED BIT(0) +/** GETSTATUS Format 2 - PERCR - Handoff Delay NACK. */ #define I3C_CCC_GETSTATUS_PRECR_HANDOFF_DELAY_NACK BIT(1) /** @@ -654,59 +702,122 @@ union i3c_ccc_getmxds { } fmt3; } __packed; +/** Get Max Data Speed (GETMXDS) - Default Max Sustained Data Rate. */ #define I3C_CCC_GETMXDS_MAX_SDR_FSCL_MAX 0 + +/** Get Max Data Speed (GETMXDS) - 8MHz Max Sustained Data Rate. */ #define I3C_CCC_GETMXDS_MAX_SDR_FSCL_8MHZ 1 + +/** Get Max Data Speed (GETMXDS) - 6MHz Max Sustained Data Rate. */ #define I3C_CCC_GETMXDS_MAX_SDR_FSCL_6MHZ 2 + +/** Get Max Data Speed (GETMXDS) - 4MHz Max Sustained Data Rate. */ #define I3C_CCC_GETMXDS_MAX_SDR_FSCL_4MHZ 3 + +/** Get Max Data Speed (GETMXDS) - 2MHz Max Sustained Data Rate. */ #define I3C_CCC_GETMXDS_MAX_SDR_FSCL_2MHZ 4 +/** Get Max Data Speed (GETMXDS) - Clock to Data Turnaround <= 8ns. */ #define I3C_CCC_GETMXDS_TSCO_8NS 0 + +/** Get Max Data Speed (GETMXDS) - Clock to Data Turnaround <= 9ns. */ #define I3C_CCC_GETMXDS_TSCO_9NS 1 + +/** Get Max Data Speed (GETMXDS) - Clock to Data Turnaround <= 10ns. */ #define I3C_CCC_GETMXDS_TSCO_10NS 2 + +/** Get Max Data Speed (GETMXDS) - Clock to Data Turnaround <= 11ns. */ #define I3C_CCC_GETMXDS_TSCO_11NS 3 + +/** Get Max Data Speed (GETMXDS) - Clock to Data Turnaround <= 12ns. */ #define I3C_CCC_GETMXDS_TSCO_12NS 4 + +/** Get Max Data Speed (GETMXDS) - Clock to Data Turnaround > 12ns. */ #define I3C_CCC_GETMXDS_TSCO_GT_12NS 7 +/** Get Max Data Speed (GETMXDS) - maxWr - Optional Defining Byte Support. */ #define I3C_CCC_GETMXDS_MAXWR_DEFINING_BYTE_SUPPORT BIT(3) +/** Get Max Data Speed (GETMXDS) - Max Sustained Data Rate bit shift value. */ #define I3C_CCC_GETMXDS_MAXWR_MAX_SDR_FSCL_SHIFT 0 +/** Get Max Data Speed (GETMXDS) - Max Sustained Data Rate bitmask. */ #define I3C_CCC_GETMXDS_MAXWR_MAX_SDR_FSCL_MASK \ (0x07U << I3C_CCC_GET_MXDS_MAXWR_MAX_SDR_FSCL_SHIFT) +/** + * @brief Get Max Data Speed (GETMXDS) - maxWr - Max Sustained Data Rate + * + * Obtain Max Sustained Data Rate value from GETMXDS maxWr value + * obtained via GETMXDS. + * + * @param maxwr GETMXDS maxWr value. + */ #define I3C_CCC_GETMXDS_MAXWR_MAX_SDR_FSCL(maxwr) \ (((maxwr) & \ I3C_CCC_GETMXDS_MAXWR_MAX_SDR_FSCL_MASK) \ >> I3C_CCC_GETMXDS_MAXWR_MAX_SDR_FSCL_SHIFT) +/** Get Max Data Speed (GETMXDS) - maxRd - Write-to-Read Permits Stop Between. */ #define I3C_CCC_GETMXDS_MAXRD_W2R_PERMITS_STOP_BETWEEN BIT(6) +/** Get Max Data Speed (GETMXDS) - maxRd - Clock to Data Turnaround bit shift value. */ #define I3C_CCC_GETMXDS_MAXRD_TSCO_SHIFT 3 +/** Get Max Data Speed (GETMXDS) - maxRd - Clock to Data Turnaround bitmask. */ #define I3C_CCC_GETMXDS_MAXRD_TSCO_MASK \ (0x07U << I3C_CCC_GETMXDS_MAXRD_TSCO_SHIFT) +/** + * @brief Get Max Data Speed (GETMXDS) - maxRd - Clock to Data Turnaround + * + * Obtain Clock to Data Turnaround value from GETMXDS maxRd value + * obtained via GETMXDS. + * + * @param maxrd GETMXDS maxRd value. + */ #define I3C_CCC_GETMXDS_MAXRD_TSCO(maxrd) \ (((maxrd) & I3C_CCC_GETMXDS_MAXRD_TSCO_MASK) \ >> I3C_CCC_GETMXDS_MAXRD_TSCO_SHIFT) +/** Get Max Data Speed (GETMXDS) - maxRd - Max Sustained Data Rate bit shift value. */ #define I3C_CCC_GETMXDS_MAXRD_MAX_SDR_FSCL_SHIFT 0 +/** Get Max Data Speed (GETMXDS) - maxRd - Max Sustained Data Rate bitmask. */ #define I3C_CCC_GETMXDS_MAXRD_MAX_SDR_FSCL_MASK \ (0x07U << I3C_CCC_GET_MXDS_MAXRD_MAX_SDR_FSCL_SHIFT) +/** + * @brief Get Max Data Speed (GETMXDS) - maxRd - Max Sustained Data Rate + * + * Obtain Max Sustained Data Rate value from GETMXDS maxRd value + * obtained via GETMXDS. + * + * @param maxrd GETMXDS maxRd value. + */ #define I3C_CCC_GETMXDS_MAXRD_MAX_SDR_FSCL(maxrd) \ (((maxrd) & \ I3C_CCC_GETMXDS_MAXRD_MAX_SDR_FSCL_MASK) \ >> I3C_CCC_GETMXDS_MAXRD_MAX_SDR_FSCL_SHIFT) +/** Get Max Data Speed (GETMXDS) - CRDHLY1 - Set Bus Activity State bit shift value. */ #define I3C_CCC_GETMXDS_CRDHLY1_SET_BUS_ACT_STATE BIT(2) +/** Get Max Data Speed (GETMXDS) - CRDHLY1 - Controller Handoff Activity State bit shift value. */ #define I3C_CCC_GETMXDS_CRDHLY1_CTRL_HANDOFF_ACT_STATE_SHIFT 0 +/** Get Max Data Speed (GETMXDS) - CRDHLY1 - Controller Handoff Activity State bitmask. */ #define I3C_CCC_GETMXDS_CRDHLY1_CTRL_HANDOFF_ACT_STATE_MASK \ (0x03U << I3C_CCC_GETMXDS_CRDHLY1_SET_BUS_ACT_STATE_SHIFT) +/** + * @brief Get Max Data Speed (GETMXDS) - CRDHLY1 - Controller Handoff Activity State + * + * Obtain Controller Handoff Activity State value from GETMXDS value + * obtained via GETMXDS. + * + * @param crhdly1 GETMXDS value. + */ #define I3C_CCC_GETMXDS_CRDHLY1_CTRL_HANDOFF_ACT_STATE(crhdly1) \ (((crhdly1) & \ I3C_CCC_GETMXDS_CRDHLY1_SET_BUS_ACT_STATE_MASK) \ @@ -724,51 +835,163 @@ struct i3c_ccc_getcaps { uint8_t getcaps[4]; } __packed; +/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR-DDR mode bit. */ #define I3C_CCC_GETCAPS1_HDR_DDR BIT(0) + +/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR-BT mode bit. */ #define I3C_CCC_GETCAPS1_HDR_BT BIT(3) +/** + * @brief Get Optional Feature Capabilities (GETCAPS) - HDR Mode + * + * Get the bit corresponding to HDR mode. + * + * @param x HDR mode + */ #define I3C_CCC_GETCAPS1_HDR_MODE(x) BIT(x) + +/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 0. */ #define I3C_CCC_GETCAPS1_HDR_MODE0 BIT(0) + +/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 1. */ #define I3C_CCC_GETCAPS1_HDR_MODE1 BIT(1) + +/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 2. */ #define I3C_CCC_GETCAPS1_HDR_MODE2 BIT(2) + +/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 3. */ #define I3C_CCC_GETCAPS1_HDR_MODE3 BIT(3) + +/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 4. */ #define I3C_CCC_GETCAPS1_HDR_MODE4 BIT(4) + +/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 5. */ #define I3C_CCC_GETCAPS1_HDR_MODE5 BIT(5) + +/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 6. */ #define I3C_CCC_GETCAPS1_HDR_MODE6 BIT(6) + +/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 7. */ #define I3C_CCC_GETCAPS1_HDR_MODE7 BIT(7) +/** Get Optional Feature Capabilities (GETCAPS) Format 2 - HDR-DDR Write Abort bit. */ #define I3C_CCC_GETCAPS2_HDRDDR_WRITE_ABORT BIT(6) + +/** Get Optional Feature Capabilities (GETCAPS) Format 2 - HDR-DDR Abort CRC bit. */ #define I3C_CCC_GETCAPS2_HDRDDR_ABORT_CRC BIT(7) +/** + * @brief Get Optional Feature Capabilities (GETCAPS) Format 2 - + * Group Address Capabilities bit shift value. + */ #define I3C_CCC_GETCAPS2_GRPADDR_CAP_SHIFT 4 + +/** + * @brief Get Optional Feature Capabilities (GETCAPS) Format 2 - + * Group Address Capabilities bitmask. + */ #define I3C_CCC_GETCAPS2_GRPADDR_CAP_MASK \ (0x03U << I3C_CCC_GETCAPS2_GRPADDR_CAP_SHIFT) + +/** + * @brief Get Optional Feature Capabilities (GETCAPS) Format 2 - Group Address Capabilities. + * + * Obtain Group Address Capabilities value from GETCAPS Format 2 value + * obtained via GETCAPS. + * + * @param getcaps2 GETCAPS2 value. + */ #define I3C_CCC_GETCAPS2_GRPADDR_CAP(getcaps2) \ (((getcaps2) & \ I3C_CCC_GETCAPS2_GRPADDR_CAP_MASK) \ >> I3C_CCC_GETCAPS_GRPADDR_CAP_SHIFT) +/** + * @brief Get Optional Feature Capabilities (GETCAPS) Format 2 - + * I3C 1.x Specification Version bit shift value. + */ #define I3C_CCC_GETCAPS2_SPEC_VER_SHIFT 0 + +/** + * @brief Get Optional Feature Capabilities (GETCAPS) Format 2 - + * I3C 1.x Specification Version bitmask. + */ #define I3C_CCC_GETCAPS2_SPEC_VER_MASK \ (0x0FU << I3C_CCC_GETCAPS2_SPEC_VER_SHIFT) + +/** + * @brief Get Optional Feature Capabilities (GETCAPS) Format 2 - + * I3C 1.x Specification Version. + * + * Obtain I3C 1.x Specification Version value from GETCAPS Format 2 value + * obtained via GETCAPS. + * + * @param getcaps2 GETCAPS2 value. + */ #define I3C_CCC_GETCAPS2_SPEC_VER(getcaps2) \ (((getcaps2) & \ I3C_CCC_GETCAPS2_SPEC_VER_MASK) \ >> I3C_CCC_GETCAPS_SPEC_VER_SHIFT) -#define I3C_CCC_GETCAPS3_MLAME_SUPPORT BIT(0) +/** + * @brief Get Optional Feature Capabilities (GETCAPS) Format 3 - + * Multi-Lane Data Transfer Support bit. + */ +#define I3C_CCC_GETCAPS3_MLANE_SUPPORT BIT(0) + +/** + * @brief Get Optional Feature Capabilities (GETCAPS) Format 3 - + * Device to Device Transfer (D2DXFER) Support bit. + */ #define I3C_CCC_GETCAPS3_D2DXFER_SUPPORT BIT(1) -#define I3C_CCC_GETCAPS3_D3DXFER_IBI_CAPABLE BIT(2) + +/** + * @brief Get Optional Feature Capabilities (GETCAPS) Format 3 - + * Device to Device Transfer (D2DXFER) IBI Capable bit. + */ +#define I3C_CCC_GETCAPS3_D2DXFER_IBI_CAPABLE BIT(2) + +/** + * @brief Get Optional Feature Capabilities (GETCAPS) Format 3 - + * Defining Byte Support in GETCAPS bit. + */ #define I3C_CCC_GETCAPS3_GETCAPS_DEFINING_BYTE_SUPPORT BIT(3) + +/** + * @brief Get Optional Feature Capabilities (GETCAPS) Format 3 - + * Defining Byte Support in GETSTATUS bit. + */ #define I3C_CCC_GETCAPS3_GETSTATUS_DEFINING_BYTE_SUPPORT BIT(4) + +/** + * @brief Get Optional Feature Capabilities (GETCAPS) Format 3 - + * HDR-BT CRC-32 Support bit. + */ #define I3C_CCC_GETCAPS3_HDRBT_CRC32_SUPPORT BIT(5) + +/** + * @brief Get Optional Feature Capabilities (GETCAPS) Format 3 - + * IBI MDB Support for Pending Read Notification bit. + */ #define I3C_CCC_GETCAPS3_IBI_MDR_PENDING_READ_NOTIFICATION BIT(6) +/** + * @brief Enum for I3C Reset Action (RSTACT) Defining Byte Values. + */ enum i3c_ccc_rstact_defining_byte { + /** No Reset on Target Reset Pattern. */ I3C_CCC_RSTACT_NO_RESET = 0x00U, + + /** Reset the I3C Peripheral Only. */ I3C_CCC_RSTACT_PERIPHERAL_ONLY = 0x01U, + + /** Reset the Whole Target. */ I3C_CCC_RSTACT_RESET_WHOLE_TARGET = 0x02U, + + /** Debug Network Adapter Reset. */ I3C_CCC_RSTACT_DEBUG_NETWORK_ADAPTER = 0x03U, + + /** Virtual Target Detect. */ I3C_CCC_RSTACT_VIRTUAL_TARGET_DETECT = 0x04U, }; diff --git a/include/zephyr/drivers/i3c/ibi.h b/include/zephyr/drivers/i3c/ibi.h index 8156db1c22e..2483b5de5a2 100644 --- a/include/zephyr/drivers/i3c/ibi.h +++ b/include/zephyr/drivers/i3c/ibi.h @@ -44,7 +44,7 @@ enum i3c_ibi_type { I3C_IBI_TYPE_MAX = I3C_IBI_HOTJOIN, - /* + /** * Not an actual IBI type, but simply used by * the IBI workq for generic callbacks. */ @@ -87,9 +87,12 @@ struct i3c_ibi_payload { */ struct i3c_ibi_work { /** - * Private, do not modify. + * @cond INTERNAL_HIDDEN + * + * Used for keeping track of work in a queue. */ sys_snode_t node; + /** @endcond */ /** * k_work struct. diff --git a/include/zephyr/drivers/i3c/target_device.h b/include/zephyr/drivers/i3c/target_device.h index 6cfac503c61..ca699814078 100644 --- a/include/zephyr/drivers/i3c/target_device.h +++ b/include/zephyr/drivers/i3c/target_device.h @@ -9,7 +9,7 @@ /** * @brief I3C Target Device API - * @defgroup i3c_target_device Target Device API + * @defgroup i3c_target_device I3C Target Device API * @ingroup i3c_interface * @{ */ @@ -217,7 +217,7 @@ struct i3c_target_driver_api { }; /** - * @brief Writes to the Target's TX FIFO + * @brief Writes to the target's TX FIFO * * Write to the TX FIFO @p dev I3C bus driver using the provided * buffer and length. Some I3C targets will NACK read requests until data diff --git a/include/zephyr/drivers/ieee802154/cc1200.h b/include/zephyr/drivers/ieee802154/cc1200.h index 3581a26e15d..2ef9e2f6b73 100644 --- a/include/zephyr/drivers/ieee802154/cc1200.h +++ b/include/zephyr/drivers/ieee802154/cc1200.h @@ -23,7 +23,6 @@ */ struct cc1200_rf_registers_set { uint32_t chan_center_freq0; - uint16_t channel_limit; /* to fit in uint16_t, spacing is a multiple of 100 Hz, * 12.5KHz for instance will be 125. */ diff --git a/include/zephyr/drivers/interrupt_controller/intc_ra_icu.h b/include/zephyr/drivers/interrupt_controller/intc_ra_icu.h new file mode 100644 index 00000000000..fcbef647d29 --- /dev/null +++ b/include/zephyr/drivers/interrupt_controller/intc_ra_icu.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#ifndef ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_RA_ICU_H_ +#define ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_RA_ICU_H_ + +#define RA_ICU_FLAG_EVENT_OFFSET 8 +#define RA_ICU_FLAG_EVENT_MASK (BIT_MASK(8) << RA_ICU_FLAG_EVENT_OFFSET) +#define RA_ICU_FLAG_INTCFG_OFFSET 16 +#define RA_ICU_FLAG_INTCFG_MASK (BIT_MASK(8) << RA_ICU_FLAG_INTCFG_OFFSET) + +enum icu_irq_mode { + ICU_FALLING, + ICU_RISING, + ICU_BOTH_EDGE, + ICU_LOW_LEVEL, +}; + +typedef void (*ra_isr_handler)(const void *); + +extern void ra_icu_clear_int_flag(unsigned int irqn); + +extern int ra_icu_query_available_irq(uint32_t event); +extern int ra_icu_query_exists_irq(uint32_t event); + +extern void ra_icu_query_irq_config(unsigned int irq, uint32_t *intcfg, ra_isr_handler *pisr, + const void **cbarg); + +extern int ra_icu_irq_connect_dynamic(unsigned int irq, unsigned int priority, + void (*routine)(const void *parameter), const void *parameter, + uint32_t flags); + +#endif /* ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_RA_ICU_H_ */ diff --git a/include/zephyr/drivers/interrupt_controller/intc_wkpu_nxp_s32.h b/include/zephyr/drivers/interrupt_controller/intc_wkpu_nxp_s32.h new file mode 100644 index 00000000000..c87a783e422 --- /dev/null +++ b/include/zephyr/drivers/interrupt_controller/intc_wkpu_nxp_s32.h @@ -0,0 +1,68 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief Driver for Wake-up interrupt/event controller in NXP S32 MCUs + */ + +#ifndef ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_WKPU_NXP_S32_H_ +#define ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_WKPU_NXP_S32_H_ + +#include + +/* Wrapper callback for WKPU line */ +typedef void (*wkpu_nxp_s32_callback_t)(uint8_t pin, void *arg); + +/** + * @brief Unset WKPU callback for line + * + * @param dev WKPU device + * @param line WKPU line + */ +void wkpu_nxp_s32_unset_callback(const struct device *dev, uint8_t line); + +/** + * @brief Set WKPU callback for line + * + * @param dev WKPU device + * @param line WKPU line + * @param cb Callback + * @param pin GPIO pin + * @param arg Callback data + * + * @retval 0 on SUCCESS + * @retval -EBUSY if callback for the line is already set + */ +int wkpu_nxp_s32_set_callback(const struct device *dev, uint8_t line, + wkpu_nxp_s32_callback_t cb, uint8_t pin, void *arg); + +/** + * @brief Set edge event and enable interrupt for WKPU line + * + * @param dev WKPU device + * @param line WKPU line + * @param edge_type Type of edge event + */ +void wkpu_nxp_s32_enable_interrupt(const struct device *dev, uint8_t line, + Wkpu_Ip_EdgeType edge_type); + +/** + * @brief Disable interrupt for WKPU line + * + * @param dev WKPU device + * @param line WKPU line + */ +void wkpu_nxp_s32_disable_interrupt(const struct device *dev, uint8_t line); + +/** + * @brief Get pending interrupt for WKPU device + * + * @param dev WKPU device + * @return A mask contains pending flags + */ +uint64_t wkpu_nxp_s32_get_pending(const struct device *dev); + +#endif /* ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_WKPU_NXP_S32_H_ */ diff --git a/include/zephyr/drivers/interrupt_controller/riscv_plic.h b/include/zephyr/drivers/interrupt_controller/riscv_plic.h index 1cec5cc8109..22c57a4b696 100644 --- a/include/zephyr/drivers/interrupt_controller/riscv_plic.h +++ b/include/zephyr/drivers/interrupt_controller/riscv_plic.h @@ -12,24 +12,26 @@ #ifndef ZEPHYR_INCLUDE_DRIVERS_RISCV_PLIC_H_ #define ZEPHYR_INCLUDE_DRIVERS_RISCV_PLIC_H_ +#include + /** * @brief Enable interrupt * - * @param irq interrupt ID + * @param irq Multi-level encoded interrupt ID */ void riscv_plic_irq_enable(uint32_t irq); /** * @brief Disable interrupt * - * @param irq interrupt ID + * @param irq Multi-level encoded interrupt ID */ void riscv_plic_irq_disable(uint32_t irq); /** * @brief Check if an interrupt is enabled * - * @param irq interrupt ID + * @param irq Multi-level encoded interrupt ID * @return Returns true if interrupt is enabled, false otherwise */ int riscv_plic_irq_is_enabled(uint32_t irq); @@ -37,7 +39,7 @@ int riscv_plic_irq_is_enabled(uint32_t irq); /** * @brief Set interrupt priority * - * @param irq interrupt ID + * @param irq Multi-level encoded interrupt ID * @param prio interrupt priority */ void riscv_plic_set_priority(uint32_t irq, uint32_t prio); @@ -47,6 +49,13 @@ void riscv_plic_set_priority(uint32_t irq, uint32_t prio); * * @return Returns the ID of an active interrupt */ -int riscv_plic_get_irq(void); +unsigned int riscv_plic_get_irq(void); + +/** + * @brief Get active interrupt controller device + * + * @return Returns device pointer of the active interrupt device + */ +const struct device *riscv_plic_get_dev(void); #endif /* ZEPHYR_INCLUDE_DRIVERS_RISCV_PLIC_H_ */ diff --git a/include/zephyr/drivers/mdio.h b/include/zephyr/drivers/mdio.h index 8fe0ada27ff..1d030c0f586 100644 --- a/include/zephyr/drivers/mdio.h +++ b/include/zephyr/drivers/mdio.h @@ -6,6 +6,7 @@ /* * Copyright (c) 2021 IP-Logix Inc. + * Copyright 2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -31,14 +32,6 @@ extern "C" { * These are for internal use only, so skip these in * public documentation. */ - -/** Order of items in this enum must match the `protocol` dts binding */ -enum MDIO_PROTOCOL { - CLAUSE_22 = 0, - CLAUSE_45 = 1, - MICREL_SMI = 2, -}; - __subsystem struct mdio_driver_api { /** Enable the MDIO bus device */ void (*bus_enable)(const struct device *dev); @@ -47,12 +40,20 @@ __subsystem struct mdio_driver_api { void (*bus_disable)(const struct device *dev); /** Read data from MDIO bus */ - int (*read)(const struct device *dev, uint8_t prtad, uint8_t devad, + int (*read)(const struct device *dev, uint8_t prtad, uint8_t regad, uint16_t *data); /** Write data to MDIO bus */ - int (*write)(const struct device *dev, uint8_t prtad, uint8_t devad, + int (*write)(const struct device *dev, uint8_t prtad, uint8_t regad, uint16_t data); + + /** Read data from MDIO bus using Clause 45 access */ + int (*read_c45)(const struct device *dev, uint8_t prtad, uint8_t devad, + uint16_t regad, uint16_t *data); + + /** Write data to MDIO bus using Clause 45 access */ + int (*write_c45)(const struct device *dev, uint8_t prtad, uint8_t devad, + uint16_t regad, uint16_t data); }; /** * @endcond @@ -98,23 +99,28 @@ static inline void z_impl_mdio_bus_disable(const struct device *dev) * * @param[in] dev Pointer to the device structure for the controller * @param[in] prtad Port address - * @param[in] devad Device address + * @param[in] regad Register address * @param data Pointer to receive read data * * @retval 0 If successful. * @retval -EIO General input / output error. * @retval -ETIMEDOUT If transaction timedout on the bus + * @retval -ENOSYS if read is not supported */ -__syscall int mdio_read(const struct device *dev, uint8_t prtad, uint8_t devad, +__syscall int mdio_read(const struct device *dev, uint8_t prtad, uint8_t regad, uint16_t *data); static inline int z_impl_mdio_read(const struct device *dev, uint8_t prtad, - uint8_t devad, uint16_t *data) + uint8_t regad, uint16_t *data) { const struct mdio_driver_api *api = (const struct mdio_driver_api *)dev->api; - return api->read(dev, prtad, devad, data); + if (api->read == NULL) { + return -ENOSYS; + } + + return api->read(dev, prtad, regad, data); } @@ -126,23 +132,96 @@ static inline int z_impl_mdio_read(const struct device *dev, uint8_t prtad, * * @param[in] dev Pointer to the device structure for the controller * @param[in] prtad Port address - * @param[in] devad Device address + * @param[in] regad Register address * @param[in] data Data to write * * @retval 0 If successful. * @retval -EIO General input / output error. * @retval -ETIMEDOUT If transaction timedout on the bus + * @retval -ENOSYS if write is not supported */ -__syscall int mdio_write(const struct device *dev, uint8_t prtad, uint8_t devad, +__syscall int mdio_write(const struct device *dev, uint8_t prtad, uint8_t regad, uint16_t data); static inline int z_impl_mdio_write(const struct device *dev, uint8_t prtad, - uint8_t devad, uint16_t data) + uint8_t regad, uint16_t data) { const struct mdio_driver_api *api = (const struct mdio_driver_api *)dev->api; - return api->write(dev, prtad, devad, data); + if (api->write == NULL) { + return -ENOSYS; + } + + return api->write(dev, prtad, regad, data); +} + +/** + * @brief Read from MDIO Bus using Clause 45 access + * + * This routine provides an interface to perform a read on the MDIO bus using + * IEEE 802.3 Clause 45 access. + * + * @param[in] dev Pointer to the device structure for the controller + * @param[in] prtad Port address + * @param[in] devad Device address + * @param[in] regad Register address + * @param data Pointer to receive read data + * + * @retval 0 If successful. + * @retval -EIO General input / output error. + * @retval -ETIMEDOUT If transaction timedout on the bus + * @retval -ENOSYS if write using Clause 45 access is not supported + */ +__syscall int mdio_read_c45(const struct device *dev, uint8_t prtad, + uint8_t devad, uint16_t regad, uint16_t *data); + +static inline int z_impl_mdio_read_c45(const struct device *dev, uint8_t prtad, + uint8_t devad, uint16_t regad, + uint16_t *data) +{ + const struct mdio_driver_api *api = + (const struct mdio_driver_api *)dev->api; + + if (api->read_c45 == NULL) { + return -ENOSYS; + } + + return api->read_c45(dev, prtad, devad, regad, data); +} + +/** + * @brief Write to MDIO bus using Clause 45 access + * + * This routine provides an interface to perform a write on the MDIO bus using + * IEEE 802.3 Clause 45 access. + * + * @param[in] dev Pointer to the device structure for the controller + * @param[in] prtad Port address + * @param[in] devad Device address + * @param[in] regad Register address + * @param[in] data Data to write + * + * @retval 0 If successful. + * @retval -EIO General input / output error. + * @retval -ETIMEDOUT If transaction timedout on the bus + * @retval -ENOSYS if write using Clause 45 access is not supported + */ +__syscall int mdio_write_c45(const struct device *dev, uint8_t prtad, + uint8_t devad, uint16_t regad, uint16_t data); + +static inline int z_impl_mdio_write_c45(const struct device *dev, uint8_t prtad, + uint8_t devad, uint16_t regad, + uint16_t data) +{ + const struct mdio_driver_api *api = + (const struct mdio_driver_api *)dev->api; + + if (api->write_c45 == NULL) { + return -ENOSYS; + } + + return api->write_c45(dev, prtad, devad, regad, data); } #ifdef __cplusplus diff --git a/include/zephyr/drivers/mdio/mdio_adin2111.h b/include/zephyr/drivers/mdio/mdio_adin2111.h deleted file mode 100644 index bf971861434..00000000000 --- a/include/zephyr/drivers/mdio/mdio_adin2111.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2023 PHOENIX CONTACT Electronics GmbH - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_INCLUDE_DRIVERS_MDIO_ADIN2111_H__ -#define ZEPHYR_INCLUDE_DRIVERS_MDIO_ADIN2111_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Read from MDIO Bus using Clause 45 access - * - * @note The caller is responsible for device lock. - * Shall not be called from ISR. - * - * @param[in] dev MDIO device. - * @param[in] prtad Port address. - * @param[in] devad Device address. - * @param[in] regad Register address. - * @param[out] data Pointer to receive read data. - * - * @retval 0 If successful. - * @retval -EIO General input / output error. - * @retval -ETIMEDOUT If transaction timedout on the bus. - * @retval <0 Error, a negative errno code. - */ -int adin2111_mdio_c45_read(const struct device *dev, uint8_t prtad, - uint8_t devad, uint16_t regad, uint16_t *data); - -/** - * @brief Write to MDIO bus using Clause 45 access - * - * @note The caller is responsible for device lock. - * Shall not be called from ISR. - * - * @param[in] dev MDIO device. - * @param[in] prtad Port address. - * @param[in] devad Device address. - * @param[in] regad Register address. - * @param[in] data Data to write. - * - * @retval 0 If successful. - * @retval -EIO General input / output error. - * @retval -ETIMEDOUT If transaction timedout on the bus. - * @retval <0 Error, a negative errno code. - */ -int adin2111_mdio_c45_write(const struct device *dev, uint8_t prtad, - uint8_t devad, uint16_t regad, uint16_t data); - -#ifdef __cplusplus -} -#endif - -#endif /* ZEPHYR_INCLUDE_DRIVERS_MDIO_ADIN2111_H__ */ diff --git a/include/zephyr/drivers/mfd/ad5592.h b/include/zephyr/drivers/mfd/ad5592.h new file mode 100644 index 00000000000..014ccdd02ba --- /dev/null +++ b/include/zephyr/drivers/mfd/ad5592.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2023 Grinn + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_MFD_AD5592_H_ +#define ZEPHYR_INCLUDE_DRIVERS_MFD_AD5592_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define AD5592_REG_SEQ_ADC 0x02U +#define AD5592_REG_ADC_CONFIG 0x04U +#define AD5592_REG_LDAC_EN 0x05U +#define AD5592_REG_GPIO_PULLDOWN 0x06U +#define AD5592_REG_READ_AND_LDAC 0x07U +#define AD5592_REG_GPIO_OUTPUT_EN 0x08U +#define AD5592_REG_GPIO_SET 0x09U +#define AD5592_REG_GPIO_INPUT_EN 0x0AU +#define AD5592_REG_PD_REF_CTRL 0x0BU + +#define AD5592_EN_REF BIT(9) + +#define AD5592_PIN_MAX 8U + +/** + * @defgroup mdf_interface_ad5592 MFD AD5592 interface + * @ingroup mfd_interfaces + * @{ + */ + +/** + * @brief Read raw data from the chip + * + * @param[in] dev Pointer to MFD device + * @param[in] val Pointer to data buffer + * + * @retval 0 if success + * @retval negative errno if failure + */ +int mfd_ad5592_read_raw(const struct device *dev, uint16_t *val); + +/** + * @brief Write raw data to chip + * + * @param[in] dev Pointer to MFD device + * @param[in] val Data to be written + * + * + * @retval 0 if success + * @retval negative errno if failure + */ +int mfd_ad5592_write_raw(const struct device *dev, uint16_t val); + +/** + * @brief Read data from provided register + * + * @param[in] dev Pointer to MFD device + * @param[in] reg Register to be read + * @param[in] reg_data Additional data passed to selected register + * @param[in] val Pointer to data buffer + * + * @retval 0 if success + * @retval negative errno if failure + */ +int mfd_ad5592_read_reg(const struct device *dev, uint8_t reg, uint8_t reg_data, uint16_t *val); + +/** + * @brief Write data to provided register + * + * @param[in] dev Pointer to MFD device + * @param[in] reg Register to be written + * @param[in] val Data to be written + * + * @retval 0 if success + * @retval negative errno if failure + */ +int mfd_ad5592_write_reg(const struct device *dev, uint8_t reg, uint16_t val); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_MFD_AD5952_H_ */ diff --git a/include/zephyr/drivers/mfd/nct38xx.h b/include/zephyr/drivers/mfd/nct38xx.h new file mode 100644 index 00000000000..40e1a87fc26 --- /dev/null +++ b/include/zephyr/drivers/mfd/nct38xx.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 Google, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_MFD_NCT38XX_H_ +#define ZEPHYR_INCLUDE_DRIVERS_MFD_NCT38XX_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Get the semaphore reference for a NCT38xx instance. Callers + * should pass the return value to k_sem_take/k_sem_give + * + * @param[in] dev Pointer to device struct of the driver instance + * + * @return Address of the semaphore + */ +struct k_sem *mfd_nct38xx_get_lock_reference(const struct device *dev); + +/** + * @brief Get the I2C DT spec reference for a NCT38xx instance. + * + * @param[in] dev Pointer to device struct of the driver instance + * + * @return Address of the I2C DT spec + */ +const struct i2c_dt_spec *mfd_nct38xx_get_i2c_dt_spec(const struct device *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_MFD_NCT38XX_H_ */ diff --git a/include/zephyr/drivers/mfd/npm1300.h b/include/zephyr/drivers/mfd/npm1300.h index 13f6ee84365..b86f2f31c8f 100644 --- a/include/zephyr/drivers/mfd/npm1300.h +++ b/include/zephyr/drivers/mfd/npm1300.h @@ -28,6 +28,7 @@ enum mfd_npm1300_event_t { NPM1300_EVENT_BATTERY_DETECTED, NPM1300_EVENT_BATTERY_REMOVED, NPM1300_EVENT_SHIPHOLD_PRESS, + NPM1300_EVENT_SHIPHOLD_RELEASE, NPM1300_EVENT_WATCHDOG_WARN, NPM1300_EVENT_VBUS_DETECTED, NPM1300_EVENT_VBUS_REMOVED, diff --git a/include/zephyr/drivers/mipi_dsi.h b/include/zephyr/drivers/mipi_dsi.h index 6373c1010f0..e6ac1e0a787 100644 --- a/include/zephyr/drivers/mipi_dsi.h +++ b/include/zephyr/drivers/mipi_dsi.h @@ -18,6 +18,7 @@ * @ingroup io_interfaces * @{ */ +#include #include #include #include @@ -217,6 +218,12 @@ struct mipi_dsi_device { uint32_t mode_flags; }; +/* + * Per message flag to indicate the message must be sent + * using Low Power Mode instead of controller default. + */ +#define MIPI_DSI_MSG_USE_LPM BIT(0x0) + /** MIPI-DSI read/write message. */ struct mipi_dsi_msg { /** Payload data type. */ @@ -241,6 +248,8 @@ __subsystem struct mipi_dsi_driver_api { const struct mipi_dsi_device *mdev); ssize_t (*transfer)(const struct device *dev, uint8_t channel, struct mipi_dsi_msg *msg); + int (*detach)(const struct device *dev, uint8_t channel, + const struct mipi_dsi_device *mdev); }; /** @@ -336,6 +345,29 @@ ssize_t mipi_dsi_dcs_read(const struct device *dev, uint8_t channel, ssize_t mipi_dsi_dcs_write(const struct device *dev, uint8_t channel, uint8_t cmd, const void *buf, size_t len); + +/** + * @brief Detach a device from the MIPI-DSI bus + * + * @param dev MIPI-DSI host device. + * @param channel Device channel (VID). + * @param mdev MIPI-DSI device description. + * + * @return 0 on success, negative on error + */ +static inline int mipi_dsi_detach(const struct device *dev, + uint8_t channel, + const struct mipi_dsi_device *mdev) +{ + const struct mipi_dsi_driver_api *api = (const struct mipi_dsi_driver_api *)dev->api; + + if (api->detach == NULL) { + return -ENOSYS; + } + + return api->detach(dev, channel, mdev); +} + #ifdef __cplusplus } #endif diff --git a/include/zephyr/drivers/mipi_dsi/mipi_dsi_mcux_2l.h b/include/zephyr/drivers/mipi_dsi/mipi_dsi_mcux_2l.h new file mode 100644 index 00000000000..927fcba5e55 --- /dev/null +++ b/include/zephyr/drivers/mipi_dsi/mipi_dsi_mcux_2l.h @@ -0,0 +1,16 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DRIVERS_MIPI_DSI_MCUX_2L_ +#define ZEPHYR_INCLUDE_DRIVERS_MIPI_DSI_MCUX_2L_ + +/* + * HW specific flag- indicates to the MIPI DSI 2L peripheral that the + * data being sent is framebuffer data, which the DSI peripheral may + * byte swap depending on KConfig settings + */ +#define MCUX_DSI_2L_FB_DATA BIT(0x1) + +#endif /* ZEPHYR_INCLUDE_DRIVERS_MIPI_DSI_MCUX_2L_ */ diff --git a/include/zephyr/drivers/misc/timeaware_gpio/timeaware_gpio.h b/include/zephyr/drivers/misc/timeaware_gpio/timeaware_gpio.h new file mode 100644 index 00000000000..b65b697f54f --- /dev/null +++ b/include/zephyr/drivers/misc/timeaware_gpio/timeaware_gpio.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Public APIs for Time-aware GPIO drivers + */ +#ifndef ZEPHYR_DRIVERS_MISC_TIMEAWARE_GPIO_TIMEAWARE_GPIO +#define ZEPHYR_DRIVERS_MISC_TIMEAWARE_GPIO_TIMEAWARE_GPIO + +/** + * @brief Time-aware GPIO Interface + * @defgroup tgpio_interface Time-aware GPIO Interface + * @ingroup io_interfaces + * @{ + */ + +#include +#include + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Event polarity + */ +enum tgpio_pin_polarity { + TGPIO_RISING_EDGE = 0, + TGPIO_FALLING_EDGE, + TGPIO_TOGGLE_EDGE, +}; + +/** + * @cond INTERNAL_HIDDEN + * + * TGPIO driver API definition and system call entry points + * + * (Internal use only.) + */ + +__subsystem struct tgpio_driver_api { + int (*pin_disable)(const struct device *dev, uint32_t pin); + int (*get_time)(const struct device *dev, uint64_t *current_time); + int (*cyc_per_sec)(const struct device *dev, uint32_t *cycles); + int (*set_perout)(const struct device *dev, uint32_t pin, uint64_t start_time, + uint64_t repeat_interval, bool periodic_enable); + int (*config_ext_ts)(const struct device *dev, uint32_t pin, uint32_t event_polarity); + int (*read_ts_ec)(const struct device *dev, uint32_t pin, uint64_t *timestamp, + uint64_t *event_count); +}; + +/** + * @endcond + */ + +/** + * @brief Get time from ART timer + * + * @param dev TGPIO device + * @param current_time Pointer to store timer value in cycles + * + * @return 0 if successful + * @return negative errno code on failure. + */ +__syscall int tgpio_port_get_time(const struct device *dev, uint64_t *current_time); + +static inline int z_impl_tgpio_port_get_time(const struct device *dev, uint64_t *current_time) +{ + const struct tgpio_driver_api *api = (const struct tgpio_driver_api *)dev->api; + + return api->get_time(dev, current_time); +} + +/** + * @brief Get current running rate + * + * @param dev TGPIO device + * @param cycles pointer to store current running requency + * + * @return 0 if successful, negative errno code on failure. + */ +__syscall int tgpio_port_get_cycles_per_second(const struct device *dev, uint32_t *cycles); + +static inline int z_impl_tgpio_port_get_cycles_per_second(const struct device *dev, + uint32_t *cycles) +{ + const struct tgpio_driver_api *api = (const struct tgpio_driver_api *)dev->api; + + return api->cyc_per_sec(dev, cycles); +} + +/** + * @brief Disable operation on pin + * + * @param dev TGPIO device + * @param pin TGPIO pin + * + * @return 0 if successful, negative errno code on failure. + */ +__syscall int tgpio_pin_disable(const struct device *dev, uint32_t pin); + +static inline int z_impl_tgpio_pin_disable(const struct device *dev, uint32_t pin) +{ + const struct tgpio_driver_api *api = (const struct tgpio_driver_api *)dev->api; + + return api->pin_disable(dev, pin); +} + +/** + * @brief Enable/Continue operation on pin + * + * @param dev TGPIO device + * @param pin TGPIO pin + * @param event_polarity TGPIO pin event polarity + * + * @return 0 if successful, negative errno code on failure. + */ +__syscall int tgpio_pin_config_ext_timestamp(const struct device *dev, uint32_t pin, + uint32_t event_polarity); + +static inline int z_impl_tgpio_pin_config_ext_timestamp(const struct device *dev, uint32_t pin, + uint32_t event_polarity) +{ + const struct tgpio_driver_api *api = (const struct tgpio_driver_api *)dev->api; + + return api->config_ext_ts(dev, pin, event_polarity); +} + +/** + * @brief Enable periodic pulse generation on a pin + * + * @param dev TGPIO device + * @param pin TGPIO pin + * @param start_time start_time of first pulse in hw cycles + * @param repeat_interval repeat interval between two pulses in hw cycles + * @param periodic_enable enables periodic mode if 'true' is passed. + * + * @return 0 if successful, negative errno code on failure. + */ +__syscall int tgpio_pin_periodic_output(const struct device *dev, uint32_t pin, + uint64_t start_time, uint64_t repeat_interval, + bool periodic_enable); + +static inline int z_impl_tgpio_pin_periodic_output(const struct device *dev, uint32_t pin, + uint64_t start_time, uint64_t repeat_interval, + bool periodic_enable) +{ + const struct tgpio_driver_api *api = (const struct tgpio_driver_api *)dev->api; + + return api->set_perout(dev, pin, start_time, repeat_interval, periodic_enable); +} + +/** + * @brief Read timestamp and event counter from TGPIO + * + * @param dev TGPIO device + * @param pin TGPIO pin + * @param timestamp timestamp of the last pulse received + * @param event_count number of pulses received since the pin is enabled + * + * @return 0 if successful, negative errno code on failure. + */ +__syscall int tgpio_pin_read_ts_ec(const struct device *dev, uint32_t pin, uint64_t *timestamp, + uint64_t *event_count); + +static inline int z_impl_tgpio_pin_read_ts_ec(const struct device *dev, uint32_t pin, + uint64_t *timestamp, uint64_t *event_count) +{ + const struct tgpio_driver_api *api = (const struct tgpio_driver_api *)dev->api; + + return api->read_ts_ec(dev, pin, timestamp, event_count); +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#include + +#endif /* ZEPHYR_DRIVERS_MISC_TIMEAWARE_GPIO_TIMEAWARE_GPIO */ diff --git a/include/zephyr/drivers/mm/mm_drv_bank.h b/include/zephyr/drivers/mm/mm_drv_bank.h index 9e1a51ebcbf..75fb57467ce 100644 --- a/include/zephyr/drivers/mm/mm_drv_bank.h +++ b/include/zephyr/drivers/mm/mm_drv_bank.h @@ -9,9 +9,10 @@ * @brief Memory Banks Driver APIs * * This contains generic APIs to be used by a system-wide memory management - * driver to track page usage within memory banks. It is incumbent upon the - * caller to ensure that proper locking is used to protect the data when - * using these APIs. + * driver to track page usage within memory banks. + * + * @note The caller of these functions needs to ensure proper locking + * to protect the data when using these APIs. */ #ifndef ZEPHYR_INCLUDE_DRIVERS_MM_DRV_BANK_H @@ -21,11 +22,31 @@ #include #include -#define SRAM_BANK_PAGE_NUM (SRAM_BANK_SIZE / CONFIG_MM_DRV_PAGE_SIZE) +/** + * @brief Memory Banks Driver APIs + * @defgroup mm_drv_bank_apis Memory Banks Driver APIs + * + * This contains APIs for a system-wide memory management driver to + * track page usage within memory banks. + * + * @note The caller of these functions needs to ensure proper locking + * to protect the data when using these APIs. + * + * @ingroup memory_management + * @{ + */ -struct mem_drv_bank { +/** + * @brief Information about memory banks. + */ +struct sys_mm_drv_bank { + /** Number of unmapped pages. */ uint32_t unmapped_pages; + + /** Number of mapped pages. */ uint32_t mapped_pages; + + /** Maximum number of mapped pages since last counter reset. */ uint32_t max_mapped_pages; }; @@ -38,10 +59,10 @@ struct mem_drv_bank { * it will start with all pages mapped. In next phase of driver initialization * unused pages will be unmapped. * - * @param bank Pointer to the memory bank structure used for tracking - * @param bank_pages Number of pages in the memory bank + * @param[in,out] bank Pointer to the memory bank structure used for tracking + * @param[in] bank_pages Number of pages in the memory bank */ -void sys_mm_drv_bank_init(struct mem_drv_bank *bank, uint32_t bank_pages); +void sys_mm_drv_bank_init(struct sys_mm_drv_bank *bank, uint32_t bank_pages); /** * @brief Track the mapping of a page in the specified memory bank @@ -49,11 +70,11 @@ void sys_mm_drv_bank_init(struct mem_drv_bank *bank, uint32_t bank_pages); * This function is used to update the number of mapped pages within the * specified memory bank. * - * @param bank Pointer to the memory bank's data structure + * @param[in,out] bank Pointer to the memory bank's data structure * * @return The number of pages mapped within the memory bank */ -uint32_t sys_mm_drv_bank_page_mapped(struct mem_drv_bank *bank); +uint32_t sys_mm_drv_bank_page_mapped(struct sys_mm_drv_bank *bank); /** * @brief Track the unmapping of a page in the specified memory bank @@ -61,11 +82,11 @@ uint32_t sys_mm_drv_bank_page_mapped(struct mem_drv_bank *bank); * This function is used to update the number of unmapped pages within the * specified memory bank. * - * @param bank Pointer to the memory bank's data structure + * @param[in,out] bank Pointer to the memory bank's data structure * * @return The number of unmapped pages within the memory bank */ -uint32_t sys_mm_drv_bank_page_unmapped(struct mem_drv_bank *bank); +uint32_t sys_mm_drv_bank_page_unmapped(struct sys_mm_drv_bank *bank); /** * @brief Reset the max number of pages mapped in the bank @@ -74,19 +95,23 @@ uint32_t sys_mm_drv_bank_page_unmapped(struct mem_drv_bank *bank); * the specified memory bank to the current number of pages mapped in * that memory bank. * - * @param bank Pointer to the memory bank's data structure + * @param[in,out] bank Pointer to the memory bank's data structure */ -void sys_mm_drv_bank_stats_reset_max(struct mem_drv_bank *bank); +void sys_mm_drv_bank_stats_reset_max(struct sys_mm_drv_bank *bank); /** * @brief Retrieve the memory usage stats for the specified memory bank * * This routine extracts the system memory stats from the memory bank. * - * @param bank Pointer to the memory bank's data structure - * @param stats Pointer to memory into which to copy the system memory stats + * @param[in] bank Pointer to the memory bank's data structure + * @param[in,out] stats Pointer to memory into which to copy the system memory stats */ -void sys_mm_drv_bank_stats_get(struct mem_drv_bank *bank, +void sys_mm_drv_bank_stats_get(struct sys_mm_drv_bank *bank, struct sys_memory_stats *stats); +/** + * @} + */ + #endif /* ZEPHYR_INCLUDE_DRIVERS_MM_DRV_BANK_H */ diff --git a/include/zephyr/drivers/mm/system_mm.h b/include/zephyr/drivers/mm/system_mm.h index e407041889e..d523b706723 100644 --- a/include/zephyr/drivers/mm/system_mm.h +++ b/include/zephyr/drivers/mm/system_mm.h @@ -15,7 +15,7 @@ #ifndef ZEPHYR_INCLUDE_DRIVERS_SYSTEM_MM_H_ #define ZEPHYR_INCLUDE_DRIVERS_SYSTEM_MM_H_ -#include +#include #ifndef _ASMLANGUAGE @@ -26,12 +26,20 @@ extern "C" { /** * @brief Memory Management Driver APIs * @defgroup mm_drv_apis Memory Management Driver APIs + * + * This contains APIs for a system-wide memory management + * driver. Only one instance is permitted on the system. + * * @ingroup memory_management * @{ */ -/* - * Caching mode definitions. These are mutually exclusive. +/** + * @name Caching mode definitions. + * + * These are mutually exclusive. + * + * @{ */ /** No caching */ @@ -46,9 +54,16 @@ extern "C" { /** Reserved bits for cache modes */ #define SYS_MM_MEM_CACHE_MASK (BIT(3) - 1) -/* - * Region permission attributes. +/** + * @} + */ + +/** + * @name Region permission attributes. + * * Default should be read-only, no user, no exec. + * + * @{ */ /** Region will have read/write access (and not read-only) */ @@ -60,6 +75,18 @@ extern "C" { /** Region will be accessible to user mode (normally supervisor-only) */ #define SYS_MM_MEM_PERM_USER BIT(5) +/** + * @} + */ + +/** + * @name Memory Mapping and Unmapping + * + * On mapping and unmapping of memory. + * + * @{ + */ + /** * @brief Map one physical page into the virtual address space * @@ -177,25 +204,6 @@ int sys_mm_drv_unmap_page(void *virt); */ int sys_mm_drv_unmap_region(void *virt, size_t size); -/** - * @brief Get the mapped physical memory address from virtual address. - * - * The function queries the translation tables to find the physical - * memory address of a mapped virtual address. - * - * Behavior when providing unaligned address is undefined, this - * is assumed to be page aligned. - * - * @param virt Page-aligned virtual address - * @param[out] phys Mapped physical address (can be NULL if only checking - * if virtual address is mapped) - * - * @retval 0 if mapping is found and valid - * @retval -EINVAL if invalid arguments are provided - * @retval -EFAULT if virtual address is not mapped - */ -int sys_mm_drv_page_phys_get(void *virt, uintptr_t *phys); - /** * @brief Remap virtual pages into new address * @@ -225,6 +233,18 @@ int sys_mm_drv_page_phys_get(void *virt, uintptr_t *phys); */ int sys_mm_drv_remap_region(void *virt_old, size_t size, void *virt_new); +/** + * @} + */ + +/** + * @name Memory Moving + * + * On moving already mapped memory. + * + * @{ + */ + /** * @brief Physically move memory, with copy * @@ -294,6 +314,17 @@ int sys_mm_drv_move_region(void *virt_old, size_t size, void *virt_new, int sys_mm_drv_move_array(void *virt_old, size_t size, void *virt_new, uintptr_t *phys_new, size_t phys_cnt); +/** + * @} + */ + +/** + * @name Memory Mapping Attributes + * + * On manipulating attributes of already mapped memory. + * + * @{ + */ /** * @brief Update memory page flags @@ -340,6 +371,37 @@ int sys_mm_drv_update_page_flags(void *virt, uint32_t flags); int sys_mm_drv_update_region_flags(void *virt, size_t size, uint32_t flags); +/** + * @} + */ + +/** + * @name Memory Mappings Query + * + * On querying information on memory mappings. + * + * @{ + */ + +/** + * @brief Get the mapped physical memory address from virtual address. + * + * The function queries the translation tables to find the physical + * memory address of a mapped virtual address. + * + * Behavior when providing unaligned address is undefined, this + * is assumed to be page aligned. + * + * @param virt Page-aligned virtual address + * @param[out] phys Mapped physical address (can be NULL if only checking + * if virtual address is mapped) + * + * @retval 0 if mapping is found and valid + * @retval -EINVAL if invalid arguments are provided + * @retval -EFAULT if virtual address is not mapped + */ +int sys_mm_drv_page_phys_get(void *virt, uintptr_t *phys); + /** * @brief Represents an available memory region. * @@ -387,6 +449,10 @@ const struct sys_mm_drv_region *sys_mm_drv_query_memory_regions(void); */ void sys_mm_drv_query_memory_regions_free(const struct sys_mm_drv_region *regions); +/** + * @} + */ + /** * @} */ diff --git a/include/zephyr/drivers/power/atmel_sam_supc.h b/include/zephyr/drivers/power/atmel_sam_supc.h new file mode 100644 index 00000000000..e31e3d7565f --- /dev/null +++ b/include/zephyr/drivers/power/atmel_sam_supc.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Bjarki Arge Andreasen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_POWER_ATMEL_SAM_SUPC_H_ +#define ZEPHYR_INCLUDE_DRIVERS_POWER_ATMEL_SAM_SUPC_H_ + +#define SAM_DT_SUPC_CONTROLLER DEVICE_DT_GET(DT_NODELABEL(supc)) + +#define SAM_DT_SUPC_WAKEUP_SOURCE_ID(node_id) \ + DT_PROP_BY_IDX(node_id, wakeup_source_id wakeup_source_id) + +#define SAM_DT_INST_SUPC_WAKEUP_SOURCE_ID(inst) \ + SAM_DT_SUPC_WAKEUP_SOURCE_ID(DT_DRV_INST(inst)) + +#endif /* ZEPHYR_INCLUDE_DRIVERS_POWER_ATMEL_SAM_SUPC_H_ */ diff --git a/include/zephyr/drivers/regulator.h b/include/zephyr/drivers/regulator.h index a2e28440591..bad9de28239 100644 --- a/include/zephyr/drivers/regulator.h +++ b/include/zephyr/drivers/regulator.h @@ -76,6 +76,9 @@ typedef int (*regulator_set_voltage_t)(const struct device *dev, int32_t min_uv, int32_t max_uv); typedef int (*regulator_get_voltage_t)(const struct device *dev, int32_t *volt_uv); +typedef unsigned int (*regulator_count_current_limits_t)(const struct device *dev); +typedef int (*regulator_list_current_limit_t)(const struct device *dev, + unsigned int idx, int32_t *current_ua); typedef int (*regulator_set_current_limit_t)(const struct device *dev, int32_t min_ua, int32_t max_ua); typedef int (*regulator_get_current_limit_t)(const struct device *dev, @@ -95,6 +98,8 @@ __subsystem struct regulator_driver_api { regulator_list_voltage_t list_voltage; regulator_set_voltage_t set_voltage; regulator_get_voltage_t get_voltage; + regulator_count_current_limits_t count_current_limits; + regulator_list_current_limit_t list_current_limit; regulator_set_current_limit_t set_current_limit; regulator_get_current_limit_t get_current_limit; regulator_set_mode_t set_mode; @@ -135,6 +140,10 @@ struct regulator_common_config { int32_t min_ua; /** Maximum allowed current, in microamps. */ int32_t max_ua; + /** Startup delay, in microseconds. */ + uint32_t startup_delay_us; + /** Off to on delay, in microseconds. */ + uint32_t off_on_delay_us; /** Allowed modes */ const regulator_mode_t *allowed_modes; /** Number of allowed modes */ @@ -162,6 +171,8 @@ struct regulator_common_config { INT32_MIN), \ .max_ua = DT_PROP_OR(node_id, regulator_max_microamp, \ INT32_MAX), \ + .startup_delay_us = DT_PROP_OR(node_id, startup_delay_us, 0), \ + .off_on_delay_us = DT_PROP_OR(node_id, off_on_delay_us, 0), \ .allowed_modes = (const regulator_mode_t []) \ DT_PROP_OR(node_id, regulator_allowed_modes, {}), \ .allowed_modes_cnt = \ @@ -485,6 +496,57 @@ static inline int regulator_get_voltage(const struct device *dev, return api->get_voltage(dev, volt_uv); } +/** + * @brief Obtain the number of supported current limit levels. + * + * Each current limit level supported by a regulator gets an index, starting from + * zero. The total number of supported current limit levels can be used together with + * regulator_list_current_limit() to list all supported current limit levels. + * + * @param dev Regulator device instance. + * + * @return Number of supported current limits. + */ +static inline unsigned int regulator_count_current_limits(const struct device *dev) +{ + const struct regulator_driver_api *api = + (const struct regulator_driver_api *)dev->api; + + if (api->count_current_limits == NULL) { + return 0U; + } + + return api->count_current_limits(dev); +} + +/** + * @brief Obtain the value of a current limit given an index. + * + * Each current limit level supported by a regulator gets an index, starting from + * zero. Together with regulator_count_current_limits(), this function can be used + * to iterate over all supported current limits. + * + * @param dev Regulator device instance. + * @param idx Current index. + * @param[out] current_ua Where current for the given @p index will be stored, in + * microamps. + * + * @retval 0 If @p index corresponds to a supported current limit. + * @retval -EINVAL If @p index does not correspond to a supported current limit. + */ +static inline int regulator_list_current_limit(const struct device *dev, + unsigned int idx, int32_t *current_ua) +{ + const struct regulator_driver_api *api = + (const struct regulator_driver_api *)dev->api; + + if (api->list_current_limit == NULL) { + return -EINVAL; + } + + return api->list_current_limit(dev, idx, current_ua); +} + /** * @brief Set output current limit. * diff --git a/include/zephyr/drivers/sdhc.h b/include/zephyr/drivers/sdhc.h index 78529af2f4b..092fca8a9ef 100644 --- a/include/zephyr/drivers/sdhc.h +++ b/include/zephyr/drivers/sdhc.h @@ -231,17 +231,44 @@ struct sdhc_host_props { bool is_spi; /*!< Is the host using SPI mode */ }; +/** + * @brief SD host controller interrupt sources + * + * Interrupt sources for SD host controller. + */ +enum sdhc_interrupt_source { + SDHC_INT_SDIO = BIT(0), /*!< Card interrupt, used by SDIO cards */ + SDHC_INT_INSERTED = BIT(1), /*!< Card was inserted into slot */ + SDHC_INT_REMOVED = BIT(2), /*!< Card was removed from slot */ +}; + +/** + * @typedef sdhc_interrupt_cb_t + * @brief SDHC card interrupt callback prototype + * + * Function prototype for SDHC card interrupt callback. + * @param dev: SDHC device that produced interrupt + * @param reason: one of @ref sdhc_interrupt_source values. + * @param user_data: User data, set via @ref sdhc_enable_interrupt + */ +typedef void (*sdhc_interrupt_cb_t)(const struct device *dev, int reason, + const void *user_data); + __subsystem struct sdhc_driver_api { int (*reset)(const struct device *dev); int (*request)(const struct device *dev, - struct sdhc_command *cmd, - struct sdhc_data *data); + struct sdhc_command *cmd, + struct sdhc_data *data); int (*set_io)(const struct device *dev, struct sdhc_io *ios); int (*get_card_present)(const struct device *dev); int (*execute_tuning)(const struct device *dev); int (*card_busy)(const struct device *dev); int (*get_host_props)(const struct device *dev, - struct sdhc_host_props *props); + struct sdhc_host_props *props); + int (*enable_interrupt)(const struct device *dev, + sdhc_interrupt_cb_t callback, + int sources, void *user_data); + int (*disable_interrupt)(const struct device *dev, int sources); }; /** @@ -260,8 +287,7 @@ __syscall int sdhc_hw_reset(const struct device *dev); static inline int z_impl_sdhc_hw_reset(const struct device *dev) { - const struct sdhc_driver_api *api = - (const struct sdhc_driver_api *)dev->api; + const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api; if (!api->reset) { return -ENOSYS; @@ -285,13 +311,13 @@ static inline int z_impl_sdhc_hw_reset(const struct device *dev) * @retval -EIO: I/O error */ __syscall int sdhc_request(const struct device *dev, struct sdhc_command *cmd, - struct sdhc_data *data); + struct sdhc_data *data); static inline int z_impl_sdhc_request(const struct device *dev, - struct sdhc_command *cmd, struct sdhc_data *data) + struct sdhc_command *cmd, + struct sdhc_data *data) { - const struct sdhc_driver_api *api = - (const struct sdhc_driver_api *)dev->api; + const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api; if (!api->request) { return -ENOSYS; @@ -315,10 +341,9 @@ static inline int z_impl_sdhc_request(const struct device *dev, __syscall int sdhc_set_io(const struct device *dev, struct sdhc_io *io); static inline int z_impl_sdhc_set_io(const struct device *dev, - struct sdhc_io *io) + struct sdhc_io *io) { - const struct sdhc_driver_api *api = - (const struct sdhc_driver_api *)dev->api; + const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api; if (!api->set_io) { return -ENOSYS; @@ -342,8 +367,7 @@ __syscall int sdhc_card_present(const struct device *dev); static inline int z_impl_sdhc_card_present(const struct device *dev) { - const struct sdhc_driver_api *api = - (const struct sdhc_driver_api *)dev->api; + const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api; if (!api->get_card_present) { return -ENOSYS; @@ -368,8 +392,7 @@ __syscall int sdhc_execute_tuning(const struct device *dev); static inline int z_impl_sdhc_execute_tuning(const struct device *dev) { - const struct sdhc_driver_api *api = - (const struct sdhc_driver_api *)dev->api; + const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api; if (!api->execute_tuning) { return -ENOSYS; @@ -393,8 +416,7 @@ __syscall int sdhc_card_busy(const struct device *dev); static inline int z_impl_sdhc_card_busy(const struct device *dev) { - const struct sdhc_driver_api *api = - (const struct sdhc_driver_api *)dev->api; + const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api; if (!api->card_busy) { return -ENOSYS; @@ -415,13 +437,12 @@ static inline int z_impl_sdhc_card_busy(const struct device *dev) * @retval -ENOTSUP host controller does not support this call */ __syscall int sdhc_get_host_props(const struct device *dev, - struct sdhc_host_props *props); + struct sdhc_host_props *props); static inline int z_impl_sdhc_get_host_props(const struct device *dev, - struct sdhc_host_props *props) + struct sdhc_host_props *props) { - const struct sdhc_driver_api *api = - (const struct sdhc_driver_api *)dev->api; + const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api; if (!api->get_host_props) { return -ENOSYS; @@ -430,6 +451,64 @@ static inline int z_impl_sdhc_get_host_props(const struct device *dev, return api->get_host_props(dev, props); } +/** + * @brief Enable SDHC interrupt sources. + * + * Enables SDHC interrupt sources. Each subsequent call of this function + * should replace the previous callback set, and leave only the interrupts + * specified in the "sources" argument enabled. + * @param dev: SDHC device + * @param callback: Callback called when interrupt occurs + * @param sources: bitmask of @ref sdhc_interrupt_source values + * indicating which interrupts should produce a callback + * @param user_data: parameter that will be passed to callback function + * @retval 0 interrupts were enabled, and callback was installed + * @retval -ENOTSUP: controller does not support this function + * @retval -EIO: I/O error + */ +__syscall int sdhc_enable_interrupt(const struct device *dev, + sdhc_interrupt_cb_t callback, + int sources, void *user_data); + +static inline int z_impl_sdhc_enable_interrupt(const struct device *dev, + sdhc_interrupt_cb_t callback, + int sources, void *user_data) +{ + const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api; + + if (!api->enable_interrupt) { + return -ENOSYS; + } + + return api->enable_interrupt(dev, callback, sources, user_data); +} + +/** + * @brief Disable SDHC interrupt sources + * + * Disables SDHC interrupt sources. If multiple sources are enabled, only + * the ones specified in "sources" will be masked. + * @param dev: SDHC device + * @param sources: bitmask of @ref sdhc_interrupt_source values + * indicating which interrupts should be disabled. + * @retval 0 interrupts were disabled + * @retval -ENOTSUP: controller does not support this function + * @retval -EIO: I/O error + */ +__syscall int sdhc_disable_interrupt(const struct device *dev, int sources); + +static inline int z_impl_sdhc_disable_interrupt(const struct device *dev, + int sources) +{ + const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api; + + if (!api->disable_interrupt) { + return -ENOSYS; + } + + return api->disable_interrupt(dev, sources); +} + /** * @} */ diff --git a/include/zephyr/drivers/sensor.h b/include/zephyr/drivers/sensor.h index 1569f4a27b3..e652c3a2040 100644 --- a/include/zephyr/drivers/sensor.h +++ b/include/zephyr/drivers/sensor.h @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -250,6 +251,12 @@ enum sensor_trigger_type { /** Trigger fires when no motion has been detected for a while. */ SENSOR_TRIG_STATIONARY, + + /** Trigger fires when the FIFO watermark has been reached. */ + SENSOR_TRIG_FIFO_WATERMARK, + + /** Trigger fires when the FIFO becomes full. */ + SENSOR_TRIG_FIFO_FULL, /** * Number of all common sensor triggers. */ @@ -327,6 +334,10 @@ enum sensor_attribute { * to the new sampling frequency. */ SENSOR_ATTR_FF_DUR, + + /** Hardware batch duration in ticks */ + SENSOR_ATTR_BATCH_DURATION, + /** * Number of all common sensor attributes. */ @@ -403,46 +414,6 @@ typedef int (*sensor_channel_get_t)(const struct device *dev, enum sensor_channel chan, struct sensor_value *val); -/** - * @typedef sensor_frame_iterator_t - * @brief Used for iterating over the data frames via the sensor_decoder_api. - * - * Example usage: - * - * @code(.c) - * sensor_frame_iterator_t fit = {0}, fit_last; - * sensor_channel_iterator_t cit = {0}, cit_last; - * - * while (true) { - * int num_decoded_channels; - * enum sensor_channel channel; - * q31_t value; - * - * fit_last = fit; - * num_decoded_channels = decoder->decode(buffer, &fit, &cit, &channel, &value, 1); - * - * if (num_decoded_channels <= 0) { - * printk("Done decoding buffer\n"); - * break; - * } - * - * printk("Decoded channel (%d) with value %s0.%06" PRIi64 "\n", q < 0 ? "-" : "", - * abs(q) * INT64_C(1000000) / (INT64_C(1) << 31)); - * - * if (fit_last != fit) { - * printk("Finished decoding frame\n"); - * } - * } - * @endcode - */ -typedef uint32_t sensor_frame_iterator_t; - -/** - * @typedef sensor_channel_iterator_t - * @brief Used for iterating over data channels in the same frame via sensor_decoder_api - */ -typedef uint32_t sensor_channel_iterator_t; - /** * @brief Decodes a single raw data buffer * @@ -454,60 +425,129 @@ struct sensor_decoder_api { * @brief Get the number of frames in the current buffer. * * @param[in] buffer The buffer provided on the @ref rtio context. + * @param[in] channel The channel to get the count for + * @param[in] channel_idx The index of the channel * @param[out] frame_count The number of frames on the buffer (at least 1) * @return 0 on success - * @return <0 on error + * @return -ENOTSUP if the channel/channel_idx aren't found */ - int (*get_frame_count)(const uint8_t *buffer, uint16_t *frame_count); + int (*get_frame_count)(const uint8_t *buffer, enum sensor_channel channel, + size_t channel_idx, uint16_t *frame_count); /** - * @brief Get the timestamp associated with the first frame. + * @brief Get the size required to decode a given channel * - * @param[in] buffer The buffer provided on the @ref rtio context. - * @param[out] timestamp_ns The closest timestamp for when the first frame was generated - * as attained by k_uptime_ticks(). + * When decoding a single frame, use @p base_size. For every additional frame, add another + * @p frame_size. As an example, to decode 3 frames use: 'base_size + 2 * frame_size'. + * + * @param[in] channel The channel to query + * @param[out] base_size The size of decoding the first frame + * @param[out] frame_size The additional size of every additional frame * @return 0 on success - * @return <0 on error + * @return -ENOTSUP if the channel is not supported */ - int (*get_timestamp)(const uint8_t *buffer, uint64_t *timestamp_ns); + int (*get_size_info)(enum sensor_channel channel, size_t *base_size, size_t *frame_size); /** - * @brief Get the shift count of a particular channel (multiplier) + * @brief Decode up to @p max_count samples from the buffer * - * This value can be used by shifting the q31_t value resulting in the SI unit of the - * reading. It is guaranteed that the shift for a channel will not change between frames. + * Decode samples of channel @ref sensor_channel across multiple frames. If there exist + * multiple instances of the same channel, @p channel_index is used to differentiate them. + * As an example, assume a sensor provides 2 distance measurements: * - * @param[in] buffer The buffer provided on the @ref rtio context. - * @param[in] channel_type The c:enum:`sensor_channel` to query - * @param[out] shift The bit shift of the channel for this data buffer. - * @return 0 on success - * @return -EINVAL if the @p channel_type doesn't exist in the buffer - * @return <0 on error - */ - int (*get_shift)(const uint8_t *buffer, enum sensor_channel channel_type, int8_t *shift); - - /** - * @brief Decode up to N samples from the buffer + * @code{.c} + * // Decode the first channel instance of 'distance' + * decoder->decode(buffer, SENSOR_CHAN_DISTANCE, 0, &fit, 5, out); + * ... * - * This function will never wrap frames. If 1 channel is available in the current frame and - * @p max_count is 2, only 1 channel will be decoded and the frame iterator will be modified - * so that the next call to decode will begin at the next frame. + * // Decode the second channel instance of 'distance' + * decoder->decode(buffer, SENSOR_CHAN_DISTANCE, 1, &fit, 5, out); + * @endcode * * @param[in] buffer The buffer provided on the @ref rtio context + * @param[in] channel The channel to decode + * @param[in] channel_idx The index of the channel * @param[in,out] fit The current frame iterator - * @param[in,out] cit The current channel iterator - * @param[out] channels The channels that were decoded - * @param[out] values The scaled data that was decoded * @param[in] max_count The maximum number of channels to decode. - * @retval > 0 The number of decoded values - * @retval 0 Nothing else to decode on the @p buffer - * @retval < 0 Error + * @param[out] data_out The decoded data + * @return 0 no more samples to decode + * @return >0 the number of decoded frames + * @return <0 on error */ - int (*decode)(const uint8_t *buffer, sensor_frame_iterator_t *fit, - sensor_channel_iterator_t *cit, enum sensor_channel *channels, q31_t *values, - uint8_t max_count); + int (*decode)(const uint8_t *buffer, enum sensor_channel channel, size_t channel_idx, + uint32_t *fit, uint16_t max_count, void *data_out); + + /** + * @brief Check if the given trigger type is present + * + * @param[in] buffer The buffer provided on the @ref rtio context + * @param[in] trigger The trigger type in question + * @return Whether the trigger is present in the buffer + */ + bool (*has_trigger)(const uint8_t *buffer, enum sensor_trigger_type trigger); +}; + +/** + * @brief Used for iterating over the data frames via the sensor_decoder_api. + * + * Example usage: + * + * @code(.c) + * struct sensor_decode_context ctx = SENSOR_DECODE_CONTEXT_INIT( + * decoder, buffer, SENSOR_CHAN_ACCEL_XYZ, 0); + * + * while (true) { + * struct sensor_three_axis_data accel_out_data; + * + * num_decoded_channels = sensor_decode(ctx, &accel_out_data, 1); + * + * if (num_decoded_channels <= 0) { + * printk("Done decoding buffer\n"); + * break; + * } + * + * printk("Decoded (%" PRId32 ", %" PRId32 ", %" PRId32 ")\n", accel_out_data.readings[0].x, + * accel_out_data.readings[0].y, accel_out_data.readings[0].z); + * } + * @endcode + */ +struct sensor_decode_context { + const struct sensor_decoder_api *decoder; + const uint8_t *buffer; + enum sensor_channel channel; + size_t channel_idx; + uint32_t fit; }; +/** + * @brief Initialize a sensor_decode_context + */ +#define SENSOR_DECODE_CONTEXT_INIT(decoder_, buffer_, channel_, channel_index_) \ + { \ + .decoder = (decoder_), \ + .buffer = (buffer_), \ + .channel = (channel_), \ + .channel_idx = (channel_index_), \ + .fit = 0, \ + } + +/** + * @brief Decode N frames using a sensor_decode_context + * + * @param[in,out] ctx The context to use for decoding + * @param[out] out The output buffer + * @param[in] max_count Maximum number of frames to decode + * @return The decode result from sensor_decoder_api's decode function + */ +static inline int sensor_decode(struct sensor_decode_context *ctx, void *out, uint16_t max_count) +{ + return ctx->decoder->decode(ctx->buffer, ctx->channel, ctx->channel_idx, &ctx->fit, + max_count, out); +} + +int sensor_natively_supported_channel_size_info(enum sensor_channel channel, size_t *base_size, + size_t *frame_size); + /** * @typedef sensor_get_decoder_t * @brief Get the decoder associate with the given device @@ -517,13 +557,38 @@ struct sensor_decoder_api { typedef int (*sensor_get_decoder_t)(const struct device *dev, const struct sensor_decoder_api **api); +/** + * @brief Options for what to do with the associated data when a trigger is consumed + */ +enum sensor_stream_data_opt { + /** @brief Include whatever data is associated with the trigger */ + SENSOR_STREAM_DATA_INCLUDE = 0, + /** @brief Do nothing with the associated trigger data, it may be consumed later */ + SENSOR_STREAM_DATA_NOP = 1, + /** @brief Flush/clear whatever data is associated with the trigger */ + SENSOR_STREAM_DATA_DROP = 2, +}; + +struct sensor_stream_trigger { + enum sensor_trigger_type trigger; + enum sensor_stream_data_opt opt; +}; + +#define SENSOR_STREAM_TRIGGER_PREP(_trigger, _opt) \ + { \ + .trigger = (_trigger), .opt = (_opt), \ + } /* * Internal data structure used to store information about the IODevice for async reading and * streaming sensor data. */ struct sensor_read_config { const struct device *sensor; - enum sensor_channel *const channels; + const bool is_streaming; + union { + enum sensor_channel *const channels; + struct sensor_stream_trigger *const triggers; + }; size_t count; const size_t max; }; @@ -543,14 +608,45 @@ struct sensor_read_config { * @endcode */ #define SENSOR_DT_READ_IODEV(name, dt_node, ...) \ - static enum sensor_channel __channel_array_##name[] = {__VA_ARGS__}; \ - static struct sensor_read_config __sensor_read_config_##name = { \ + static enum sensor_channel _CONCAT(__channel_array_, name)[] = {__VA_ARGS__}; \ + static struct sensor_read_config _CONCAT(__sensor_read_config_, name) = { \ .sensor = DEVICE_DT_GET(dt_node), \ - .channels = __channel_array_##name, \ - .count = ARRAY_SIZE(__channel_array_##name), \ - .max = ARRAY_SIZE(__channel_array_##name), \ + .is_streaming = false, \ + .channels = _CONCAT(__channel_array_, name), \ + .count = ARRAY_SIZE(_CONCAT(__channel_array_, name)), \ + .max = ARRAY_SIZE(_CONCAT(__channel_array_, name)), \ }; \ - RTIO_IODEV_DEFINE(name, &__sensor_iodev_api, &__sensor_read_config_##name) + RTIO_IODEV_DEFINE(name, &__sensor_iodev_api, _CONCAT(&__sensor_read_config_, name)) + +/** + * @brief Define a stream instance of a sensor + * + * Use this macro to generate a @ref rtio_iodev for starting a stream that's triggered by specific + * interrupts. Example: + * + * @code(.c) + * SENSOR_DT_STREAM_IODEV(imu_stream, DT_ALIAS(imu), + * {SENSOR_TRIG_FIFO_WATERMARK, SENSOR_STREAM_DATA_INCLUDE}, + * {SENSOR_TRIG_FIFO_FULL, SENSOR_STREAM_DATA_NOP}); + * + * int main(void) { + * struct rtio_sqe *handle; + * sensor_stream(&imu_stream, &rtio, NULL, &handle); + * k_msleep(1000); + * rtio_sqe_cancel(handle); + * } + * @endcode + */ +#define SENSOR_DT_STREAM_IODEV(name, dt_node, ...) \ + static struct sensor_stream_trigger _CONCAT(__trigger_array_, name)[] = {__VA_ARGS__}; \ + static struct sensor_read_config _CONCAT(__sensor_read_config_, name) = { \ + .sensor = DEVICE_DT_GET(dt_node), \ + .is_streaming = true, \ + .triggers = _CONCAT(__trigger_array_, name), \ + .count = ARRAY_SIZE(_CONCAT(__trigger_array_, name)), \ + .max = ARRAY_SIZE(_CONCAT(__trigger_array_, name)), \ + }; \ + RTIO_IODEV_DEFINE(name, &__sensor_iodev_api, &_CONCAT(__sensor_read_config_, name)) /* Used to submit an RTIO sqe to the sensor's iodev */ typedef int (*sensor_submit_t)(const struct device *sensor, struct rtio_iodev_sqe *sqe); @@ -780,11 +876,14 @@ struct __attribute__((__packed__)) sensor_data_generic_header { * The number of channels present in the frame. This will be the true number of elements in * channel_info and in the q31 values that follow the header. */ - size_t num_channels; + uint32_t num_channels; /* Shift value for all samples in the frame */ int8_t shift; + /* This padding is needed to make sure that the 'channels' field is aligned */ + int8_t _padding[sizeof(enum sensor_channel) - 1]; + /* Channels present in the frame */ enum sensor_channel channels[0]; }; @@ -856,7 +955,7 @@ static inline int z_impl_sensor_reconfigure_read_iodev(struct rtio_iodev *iodev, { struct sensor_read_config *cfg = (struct sensor_read_config *)iodev->data; - if (cfg->max < num_channels) { + if (cfg->max < num_channels || cfg->is_streaming) { return -ENOMEM; } @@ -864,6 +963,28 @@ static inline int z_impl_sensor_reconfigure_read_iodev(struct rtio_iodev *iodev, memcpy(cfg->channels, channels, num_channels * sizeof(enum sensor_channel)); cfg->count = num_channels; return 0; +} + +static inline int sensor_stream(struct rtio_iodev *iodev, struct rtio *ctx, void *userdata, + struct rtio_sqe **handle) +{ + if (IS_ENABLED(CONFIG_USERSPACE)) { + struct rtio_sqe sqe; + + rtio_sqe_prep_read_multishot(&sqe, iodev, RTIO_PRIO_NORM, userdata); + rtio_sqe_copy_in_get_handles(ctx, &sqe, handle, 1); + } else { + struct rtio_sqe *sqe = rtio_sqe_acquire(ctx); + + if (sqe == NULL) { + return -ENOMEM; + } + if (handle != NULL) { + *handle = sqe; + } + rtio_sqe_prep_read_multishot(sqe, iodev, RTIO_PRIO_NORM, userdata); + } + rtio_submit(ctx, 0); return 0; } @@ -1236,8 +1357,6 @@ static inline int64_t sensor_value_to_micro(const struct sensor_value *val) * @} */ -#if defined(CONFIG_HAS_DTS) || defined(__DOXYGEN__) - /** * @brief Get the decoder name for the current driver * @@ -1285,7 +1404,6 @@ static inline int64_t sensor_value_to_micro(const struct sensor_value *val) ()) DT_FOREACH_STATUS_OKAY_NODE(Z_MAYBE_SENSOR_DECODER_DECLARE_INTERNAL) -#endif /* defined(CONFIG_HAS_DTS) || defined(__DOXYGEN__) */ #ifdef __cplusplus } diff --git a/include/zephyr/drivers/sensor/adc_cmp_npcx.h b/include/zephyr/drivers/sensor/adc_cmp_npcx.h index fc66fd80a11..0fa7f14ca1f 100644 --- a/include/zephyr/drivers/sensor/adc_cmp_npcx.h +++ b/include/zephyr/drivers/sensor/adc_cmp_npcx.h @@ -12,6 +12,17 @@ enum adc_cmp_npcx_comparison { ADC_CMP_NPCX_LESS_OR_EQUAL, }; +/* Supported ADC threshold controllers in NPCX series */ +enum npcx_adc_cmp_thrctl { + ADC_CMP_NPCX_THRCTL1, + ADC_CMP_NPCX_THRCTL2, + ADC_CMP_NPCX_THRCTL3, + ADC_CMP_NPCX_THRCTL4, + ADC_CMP_NPCX_THRCTL5, + ADC_CMP_NPCX_THRCTL6, + ADC_CMP_NPCX_THRCTL_COUNT, +}; + enum adc_cmp_npcx_sensor_attribute { SENSOR_ATTR_LOWER_VOLTAGE_THRESH = SENSOR_ATTR_PRIV_START, SENSOR_ATTR_UPPER_VOLTAGE_THRESH, diff --git a/include/zephyr/drivers/sensor/explorir_m.h b/include/zephyr/drivers/sensor/explorir_m.h new file mode 100644 index 00000000000..efef562447c --- /dev/null +++ b/include/zephyr/drivers/sensor/explorir_m.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023, Vitrolife A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_EXPLORIR_M_H_ +#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_EXPLORIR_M_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +enum sensor_attribute_explorir_m { + /* Sensor integrated low-pass filter. Values 16, 32, 64, and 128 is allowed */ + SENSOR_ATTR_EXPLORIR_M_FILTER = SENSOR_ATTR_PRIV_START, +}; + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_EXPLORIR_M_H_ */ diff --git a/include/zephyr/drivers/sensor/f75303.h b/include/zephyr/drivers/sensor/f75303.h new file mode 100644 index 00000000000..3865e8f7e72 --- /dev/null +++ b/include/zephyr/drivers/sensor/f75303.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_F75303_H_ +#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_F75303_H_ + +#include + +/* F75303 specific channels */ +enum sensor_channel_f75303 { + SENSOR_CHAN_F75303_REMOTE1 = SENSOR_CHAN_PRIV_START, + SENSOR_CHAN_F75303_REMOTE2, +}; + +#endif diff --git a/include/zephyr/drivers/sensor/tsl2540.h b/include/zephyr/drivers/sensor/tsl2540.h new file mode 100644 index 00000000000..63a2adfe48b --- /dev/null +++ b/include/zephyr/drivers/sensor/tsl2540.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022 T-Mobile USA, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Extended public API for AMS's TSL2540 ambient light sensor + * + * This exposes attributes for the TSL2540 which can be used for + * setting the on-chip gain and integration time parameters. + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_TSL2540_H_ +#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_TSL2540_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum sensor_attribute_tsl2540 { + /* Sensor Gain */ + SENSOR_ATTR_GAIN = SENSOR_ATTR_PRIV_START + 1, + /* Sensor Integration Time (in ms) */ + SENSOR_ATTR_INTEGRATION_TIME, + /* Sensor ALS interrupt persistence filters */ + SENSOR_ATTR_INT_APERS, + /* Shutdown the sensor */ + SENSOR_ATTR_TSL2540_SHUTDOWN_MODE, + /* Turn on continuous conversion */ + SENSOR_ATTR_TSL2540_CONTINUOUS_MODE, + /* Turn on continuous conversion without wait */ + SENSOR_ATTR_TSL2540_CONTINUOUS_NO_WAIT_MODE, +}; + +enum sensor_gain_tsl2540 { + TSL2540_SENSOR_GAIN_1_2, + TSL2540_SENSOR_GAIN_1, + TSL2540_SENSOR_GAIN_4, + TSL2540_SENSOR_GAIN_16, + TSL2540_SENSOR_GAIN_64, + TSL2540_SENSOR_GAIN_128, +}; + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_TSL2540_H_ */ diff --git a/include/zephyr/drivers/sensor_data_types.h b/include/zephyr/drivers/sensor_data_types.h new file mode 100644 index 00000000000..dd7f1f39c6d --- /dev/null +++ b/include/zephyr/drivers/sensor_data_types.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_DATA_TYPES_H +#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_DATA_TYPES_H + +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct sensor_data_header { + /** + * The closest timestamp for when the first frame was generated as attained by + * :c:func:`k_uptime_ticks`. + */ + uint64_t base_timestamp_ns; + /** + * The number of elements in the 'readings' array. + * + * This must be at least 1 + */ + uint16_t reading_count; +}; + +/** + * Data for a sensor channel which reports on three axes. This is used by: + * - :c:enum:`SENSOR_CHAN_ACCEL_X` + * - :c:enum:`SENSOR_CHAN_ACCEL_Y` + * - :c:enum:`SENSOR_CHAN_ACCEL_Z` + * - :c:enum:`SENSOR_CHAN_ACCEL_XYZ` + * - :c:enum:`SENSOR_CHAN_GYRO_X` + * - :c:enum:`SENSOR_CHAN_GYRO_Y` + * - :c:enum:`SENSOR_CHAN_GYRO_Z` + * - :c:enum:`SENSOR_CHAN_GYRO_XYZ` + * - :c:enum:`SENSOR_CHAN_MAGN_X` + * - :c:enum:`SENSOR_CHAN_MAGN_Y` + * - :c:enum:`SENSOR_CHAN_MAGN_Z` + * - :c:enum:`SENSOR_CHAN_MAGN_XYZ` + * - :c:enum:`SENSOR_CHAN_POS_DX` + * - :c:enum:`SENSOR_CHAN_POS_DY` + * - :c:enum:`SENSOR_CHAN_POS_DZ` + */ +struct sensor_three_axis_data { + struct sensor_data_header header; + int8_t shift; + struct sensor_three_axis_sample_data { + uint32_t timestamp_delta; + union { + q31_t values[3]; + q31_t v[3]; + struct { + q31_t x; + q31_t y; + q31_t z; + }; + }; + } readings[1]; +}; + +#define PRIsensor_three_axis_data PRIu64 "ns, (%" PRIq(6) ", %" PRIq(6) ", %" PRIq(6) ")" + +#define PRIsensor_three_axis_data_arg(data_, readings_offset_) \ + (data_).header.base_timestamp_ns + (data_).readings[(readings_offset_)].timestamp_delta, \ + PRIq_arg((data_).readings[(readings_offset_)].x, 6, (data_).shift), \ + PRIq_arg((data_).readings[(readings_offset_)].y, 6, (data_).shift), \ + PRIq_arg((data_).readings[(readings_offset_)].z, 6, (data_).shift) + +/** + * Data from a sensor where we only care about an event occurring. This is used to report triggers. + */ +struct sensor_occurrence_data { + struct sensor_data_header header; + struct sensor_occurrence_sample_data { + uint32_t timestamp_delta; + } readings[1]; +}; + +#define PRIsensor_occurrence_data PRIu64 "ns" + +#define PRIsensor_occurrence_data_arg(data_, readings_offset_) \ + (data_).header.base_timestamp_ns + (data_).readings[(readings_offset_)].timestamp_delta + +struct sensor_q31_data { + struct sensor_data_header header; + int8_t shift; + struct sensor_q31_sample_data { + uint32_t timestamp_delta; + union { + q31_t value; + q31_t light; /**< Unit: lux */ + q31_t pressure; /**< Unit: kilopascal */ + q31_t temperature; /**< Unit: degrees Celsius */ + q31_t percent; /**< Unit: percent */ + q31_t distance; /**< Unit: meters */ + q31_t density; /**< Unit: ug/m^3 */ + q31_t density_ppm; /**< Unit: parts per million */ + q31_t density_ppb; /**< Unit: parts per billion */ + q31_t resistance; /**< Unit: ohms */ + q31_t voltage; /**< Unit: volts */ + q31_t current; /**< Unit: amps */ + q31_t power; /**< Unit: watts */ + q31_t angle; /**< Unit: degrees */ + q31_t electric_charge; /**< Unit: mAh */ + }; + } readings[1]; +}; + +#define PRIsensor_q31_data PRIu64 "ns (%" PRIq(6) ")" + +#define PRIsensor_q31_data_arg(data_, readings_offset_) \ + (data_).header.base_timestamp_ns + (data_).readings[(readings_offset_)].timestamp_delta, \ + PRIq_arg((data_).readings[(readings_offset_)].value, 6, (data_).shift) + +/** + * Data from a sensor that produces a byte of data. This is used by: + * - :c:enum:`SENSOR_CHAN_PROX` + */ +struct sensor_byte_data { + struct sensor_data_header header; + struct sensor_byte_sample_data { + uint32_t timestamp_delta; + union { + uint8_t value; + struct { + uint8_t is_near: 1; + uint8_t padding: 7; + }; + }; + } readings[1]; +}; + +#define PRIsensor_byte_data(field_name_) PRIu64 "ns (" STRINGIFY(field_name_) " = %" PRIu8 ")" + +#define PRIsensor_byte_data_arg(data_, readings_offset_, field_name_) \ + (data_).header.base_timestamp_ns + (data_).readings[(readings_offset_)].timestamp_delta, \ + (data_).readings[(readings_offset_)].field_name_ + +/** + * Data from a sensor that produces a count like value. This is used by: + * - :c:enum:`SENSOR_CHAN_GAUGE_CYCLE_COUNT` + */ +struct sensor_uint64_data { + struct sensor_data_header header; + struct sensor_uint64_sample_data { + uint32_t timestamp_delta; + uint64_t value; + } readings[1]; +}; + +#define PRIsensor_uint64_data PRIu64 "ns (%" PRIu64 ")" + +#define PRIsensor_uint64_data_arg(data_, readings_offset_) \ + (data_).header.base_timestamp_ns + (data_).readings[(readings_offset_)].timestamp_delta, \ + (data_).readings[(readings_offset_)].value + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_DATA_TYPES_H */ diff --git a/include/zephyr/drivers/serial/uart_async_rx.h b/include/zephyr/drivers/serial/uart_async_rx.h new file mode 100644 index 00000000000..646a2befc94 --- /dev/null +++ b/include/zephyr/drivers/serial/uart_async_rx.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Helper module for receiving using UART Asynchronous API. + */ + +#ifndef ZEPHYR_DRIVERS_SERIAL_UART_ASYNC_RX_H_ +#define ZEPHYR_DRIVERS_SERIAL_UART_ASYNC_RX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* @brief RX buffer structure which holds the buffer and its state. */ +struct uart_async_rx_buf { + /* Write index which is incremented whenever new data is reported to be + * received to that buffer. + */ + uint8_t wr_idx; + + /* Read index which is incremented whenever data is consumed from the buffer. + * Read index cannot be higher than the write index. + */ + uint8_t rd_idx; + + /* Set to one if buffer is released by the driver. */ + uint8_t completed; + + /* Location which is passed to the UART driver. */ + uint8_t buffer[]; +}; + +/** @brief UART asynchronous RX helper structure. */ +struct uart_async_rx { + /* Pointer to the configuration structure. Structure must be persistent. */ + const struct uart_async_rx_config *config; + + /* Total amount of pending bytes. Bytes may be spread across multiple RX buffers. */ + atomic_t pending_bytes; + + /* Number of buffers which are free. */ + atomic_t free_buf_cnt; + + /* Single buffer size. */ + uint8_t buf_len; + + /* Index of the next buffer to be provided to the driver. */ + uint8_t drv_buf_idx; + + /* Current buffer to which data is written. */ + uint8_t wr_buf_idx; + + /* Current buffer from which data is being consumed. */ + uint8_t rd_buf_idx; +}; + +/** @brief UART asynchronous RX helper configuration structure. */ +struct uart_async_rx_config { + /* Pointer to the buffer. */ + uint8_t *buffer; + + /* Buffer length. */ + size_t length; + + /* Number of buffers into provided space shall be split. */ + uint8_t buf_cnt; +}; + +/** @brief Get RX buffer length. + * + * @param async_rx Pointer to the helper instance. + * + * @return Buffer length. + */ +static inline uint8_t uart_async_rx_get_buf_len(struct uart_async_rx *async_rx) +{ + return async_rx->buf_len; +} + +/** @brief Get amount of space dedicated for managing each buffer state. + * + * User buffer provided during the initialization is split into chunks and each + * chunk has overhead. This overhead can be used to calculate actual space used + * for UART data. + * + * @return Overhead space in bytes. + */ +#define UART_ASYNC_RX_BUF_OVERHEAD offsetof(struct uart_async_rx_buf, buffer) + +/** @brief Initialize the helper instance. + * + * @param async_rx Pointer to the helper instance. + * @param config Configuration. Must be persistent. + * + * @retval 0 on successful initialization. + */ +int uart_async_rx_init(struct uart_async_rx *async_rx, + const struct uart_async_rx_config *config); + +/** @brief Reset state of the helper instance. + * + * Helper can be reset after RX abort to discard all received data and bring + * the helper to its initial state. + * + * @param async_rx Pointer to the helper instance. + */ +void uart_async_rx_reset(struct uart_async_rx *async_rx); + +/** @brief Indicate received data. + * + * Function shall be called from @ref UART_RX_RDY context. + * + * @param async_rx Pointer to the helper instance. + * @param buffer Buffer received in the UART driver event. + * @param length Length received in the UART driver event. + */ +void uart_async_rx_on_rdy(struct uart_async_rx *async_rx, uint8_t *buffer, size_t length); + +/** @brief Get next RX buffer. + * + * Returned pointer shall be provided to @ref uart_rx_buf_rsp or @ref uart_rx_enable. + * If null is returned that indicates that there are no available buffers since all + * buffers are used by the driver or contain not consumed data. + * + * @param async_rx Pointer to the helper instance. + * + * @return Pointer to the next RX buffer or null if no buffer available. + */ +uint8_t *uart_async_rx_buf_req(struct uart_async_rx *async_rx); + +/** @brief Indicate that buffer is no longer used by the UART driver. + * + * Function shall be called on @ref UART_RX_BUF_RELEASED event. + * + * @param async_rx Pointer to the helper instance. + * @param buf Buffer pointer received in the UART driver event. + */ +void uart_async_rx_on_buf_rel(struct uart_async_rx *async_rx, uint8_t *buf); + +/** @brief Claim received data for processing. + * + * Helper module works in the zero copy mode. It provides a pointer to the buffer + * that was directly used by the UART driver. Since received data is spread across + * multiple buffers there is no possibility to read all data at once. It can only be + * consumed in chunks. After data is processed, @ref uart_async_rx_data_consume is + * used to indicate that data is consumed. + * + * @param async_rx Pointer to the helper instance. + * @param data Location where address to the buffer is written. Untouched if no data to claim. + * @param length Amount of requested data. + * + * @return Amount valid of data in the @p data buffer. 0 is returned when there is no data. + */ +size_t uart_async_rx_data_claim(struct uart_async_rx *async_rx, uint8_t **data, size_t length); + +/** @brief Consume claimed data. + * + * It pairs with @ref uart_async_rx_data_claim. + * + * @param async_rx Pointer to the helper instance. + * @param length Amount of data to consume. It must be less or equal than amount of claimed data. + */ +void uart_async_rx_data_consume(struct uart_async_rx *async_rx, size_t length); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_DRIVERS_SERIAL_UART_ASYNC_RX_H_ */ diff --git a/include/zephyr/drivers/serial/uart_emul.h b/include/zephyr/drivers/serial/uart_emul.h index 68a289841df..08e6be05b1a 100644 --- a/include/zephyr/drivers/serial/uart_emul.h +++ b/include/zephyr/drivers/serial/uart_emul.h @@ -83,6 +83,14 @@ uint32_t uart_emul_flush_rx_data(const struct device *dev); */ uint32_t uart_emul_flush_tx_data(const struct device *dev); +/** + * @brief Sets one or more driver errors + * + * @param dev The emulated UART device instance + * @param errors The @ref uart_rx_stop_reason errors to set + */ +void uart_emul_set_errors(const struct device *dev, int errors); + #ifdef __cplusplus } #endif diff --git a/include/zephyr/drivers/serial/uart_intel_lw.h b/include/zephyr/drivers/serial/uart_intel_lw.h new file mode 100644 index 00000000000..8ad8c26aab8 --- /dev/null +++ b/include/zephyr/drivers/serial/uart_intel_lw.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * Header file for the INTEL LW UART + */ + +#ifndef ZEPHYR_DRIVERS_SERIAL_UART_INTEL_LW_H_ +#define ZEPHYR_DRIVERS_SERIAL_UART_INTEL_LW_H_ + +/* End of packet feature. + * Driver will trigger interrupt upon receiving end of package character. + * Please enable CONFIG_UART_INTEL_LW_EOP to use this feature. + * Use the api: uart_drv_cmd with CMD_ENABLE_EOP to enable the feature. + * This cmd will write the ip register and also set a flag to the driver. + * The flag will modify uart_irq_callback_user_data_set + * to set call back function for eop interrupt. + * Flag is cleared after uart_irq_callback_user_data_set is called. + */ +#define CMD_ENABLE_EOP 0x01 +#define CMD_DISABLE_EOP 0x02 + +/* Transmit break feature. + * Use uart_drv_cmd with CMD_TRBK_EN to break ongoing transmit. + * After this cmd, uart is unable to transmit any data. + * Please use CMD_TRBK_DIS to resume normal operation. + * Please also call uart_intel_lw_err_check, to clear the error caused + * by transmit break. + */ +#define CMD_TRBK_EN 0x03 +#define CMD_TRBK_DIS 0x04 + +/* This driver supports interrupt driven api. + * Polling for data under normal operation, might cause unexpected behaviour. + * If users wish to poll for data, please use the api: + * uart_drv_cmd with CMD_POLL_ASSERT_RTS before polling out/in. + * Then use CMD_POLL_DEASSERT_RTS to resume normal operation after polling. + */ +#define CMD_POLL_ASSERT_RTS 0x05 +#define CMD_POLL_DEASSERT_RTS 0x06 + +#endif /* ZEPHYR_DRIVERS_SERIAL_UART_INTEL_LW_H_ */ diff --git a/include/zephyr/drivers/sip_svc/sip_svc_agilex_smc.h b/include/zephyr/drivers/sip_svc/sip_svc_agilex_smc.h index 88c9002af17..4e430e72bf9 100644 --- a/include/zephyr/drivers/sip_svc/sip_svc_agilex_smc.h +++ b/include/zephyr/drivers/sip_svc/sip_svc_agilex_smc.h @@ -55,6 +55,7 @@ #define SMC_FUNC_ID_REG_WRITE 0xC2000402 #define SMC_FUNC_ID_REG_UPDATE 0xC2000403 #define SMC_FUNC_ID_SET_HPS_BRIDGES 0xC2000404 +#define SMC_FUNC_ID_RSU_UPDATE_ADDR 0xC2000405 /* @brief ASYNC SMC Function IDs */ diff --git a/include/zephyr/drivers/sip_svc/sip_svc_proto.h b/include/zephyr/drivers/sip_svc/sip_svc_proto.h index 63eebec2cd3..08d2510e061 100644 --- a/include/zephyr/drivers/sip_svc/sip_svc_proto.h +++ b/include/zephyr/drivers/sip_svc/sip_svc_proto.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Intel Corporation. + * Copyright (c) 2023, Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/include/zephyr/drivers/smbus.h b/include/zephyr/drivers/smbus.h index b624462f425..c4995febb7b 100644 --- a/include/zephyr/drivers/smbus.h +++ b/include/zephyr/drivers/smbus.h @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** + * @file + * @brief Public SMBus Driver APIs + */ + #ifndef ZEPHYR_INCLUDE_DRIVERS_SMBUS_H_ #define ZEPHYR_INCLUDE_DRIVERS_SMBUS_H_ @@ -606,11 +611,8 @@ static inline int z_impl_smbus_get_config(const struct device *dev, * @retval -ENOSYS If function smbus_smbalert_set_cb() is not implemented * by the driver. */ -__syscall int smbus_smbalert_set_cb(const struct device *dev, - struct smbus_callback *cb); - -static inline int z_impl_smbus_smbalert_set_cb(const struct device *dev, - struct smbus_callback *cb) +static inline int smbus_smbalert_set_cb(const struct device *dev, + struct smbus_callback *cb) { const struct smbus_driver_api *api = (const struct smbus_driver_api *)dev->api; @@ -660,11 +662,8 @@ static inline int z_impl_smbus_smbalert_remove_cb(const struct device *dev, * @retval -ENOSYS If function smbus_host_notify_set_cb() is not implemented * by the driver. */ -__syscall int smbus_host_notify_set_cb(const struct device *dev, - struct smbus_callback *cb); - -static inline int z_impl_smbus_host_notify_set_cb(const struct device *dev, - struct smbus_callback *cb) +static inline int smbus_host_notify_set_cb(const struct device *dev, + struct smbus_callback *cb) { const struct smbus_driver_api *api = (const struct smbus_driver_api *)dev->api; diff --git a/include/zephyr/drivers/spi.h b/include/zephyr/drivers/spi.h index 3e121a1da0e..fa3b8834c9e 100644 --- a/include/zephyr/drivers/spi.h +++ b/include/zephyr/drivers/spi.h @@ -332,7 +332,10 @@ struct spi_config { .frequency = DT_PROP(node_id, spi_max_frequency), \ .operation = (operation_) | \ DT_PROP(node_id, duplex) | \ - DT_PROP(node_id, frame_format), \ + DT_PROP(node_id, frame_format) | \ + COND_CODE_1(DT_PROP(node_id, spi_cpol), SPI_MODE_CPOL, (0)) | \ + COND_CODE_1(DT_PROP(node_id, spi_cpha), SPI_MODE_CPHA, (0)) | \ + COND_CODE_1(DT_PROP(node_id, spi_hold_cs), SPI_HOLD_ON_CS, (0)), \ .slave = DT_REG_ADDR(node_id), \ .cs = SPI_CS_CONTROL_INIT(node_id, delay_), \ } @@ -775,7 +778,7 @@ static inline int spi_transceive_dt(const struct spi_dt_spec *spec, * * @note This function is synchronous. * - * @note This function is an helper function calling spi_transceive. + * @note This function is a helper function calling spi_transceive. * * @param dev Pointer to the device structure for the driver instance * @param config Pointer to a valid spi_config structure instance. @@ -816,7 +819,7 @@ static inline int spi_read_dt(const struct spi_dt_spec *spec, * * @note This function is synchronous. * - * @note This function is an helper function calling spi_transceive. + * @note This function is a helper function calling spi_transceive. * * @param dev Pointer to the device structure for the driver instance * @param config Pointer to a valid spi_config structure instance. @@ -852,8 +855,7 @@ static inline int spi_write_dt(const struct spi_dt_spec *spec, return spi_write(spec->bus, &spec->config, tx_bufs); } -/* Doxygen defines this so documentation is generated. */ -#ifdef CONFIG_SPI_ASYNC +#if defined(CONFIG_SPI_ASYNC) || defined(__DOXYGEN__) /** * @brief Read/write the specified amount of data from the SPI driver. @@ -894,7 +896,7 @@ static inline int spi_transceive_cb(const struct device *dev, return api->transceive_async(dev, config, tx_bufs, rx_bufs, callback, userdata); } -#ifdef CONFIG_POLL +#if defined(CONFIG_POLL) || defined(__DOXYGEN__) /** @cond INTERNAL_HIDDEN */ void z_spi_transfer_signal_cb(const struct device *dev, int result, void *userdata); @@ -941,8 +943,7 @@ static inline int spi_transceive_signal(const struct device *dev, /** * @brief Alias for spi_transceive_signal for backwards compatibility * - * @deprecated - * @see spi_transceive_signal + * @deprecated Use @ref spi_transceive_signal instead. */ __deprecated static inline int spi_transceive_async(const struct device *dev, const struct spi_config *config, @@ -958,7 +959,7 @@ __deprecated static inline int spi_transceive_async(const struct device *dev, * * @note This function is asynchronous. * - * @note This function is an helper function calling spi_transceive_signal. + * @note This function is a helper function calling spi_transceive_signal. * * @note This function is available only if @kconfig{CONFIG_SPI_ASYNC} * and @kconfig{CONFIG_POLL} are selected. @@ -987,8 +988,7 @@ static inline int spi_read_signal(const struct device *dev, /** * @brief Alias for spi_read_signal for backwards compatibility * - * @deprecated - * @see spi_read_signal + * @deprecated Use @ref spi_read_signal instead. */ __deprecated static inline int spi_read_async(const struct device *dev, const struct spi_config *config, @@ -1003,7 +1003,7 @@ __deprecated static inline int spi_read_async(const struct device *dev, * * @note This function is asynchronous. * - * @note This function is an helper function calling spi_transceive_async. + * @note This function is a helper function calling spi_transceive_async. * * @note This function is available only if @kconfig{CONFIG_SPI_ASYNC} * and @kconfig{CONFIG_POLL} are selected. @@ -1030,10 +1030,9 @@ static inline int spi_write_signal(const struct device *dev, } /** - * @brief Alias for spi_read_signal for backwards compatibility + * @brief Alias for spi_write_signal for backwards compatibility * - * @deprecated - * @see spi_read_signal + * @deprecated Use @ref spi_write_signal instead. */ __deprecated static inline int spi_write_async(const struct device *dev, const struct spi_config *config, @@ -1048,18 +1047,14 @@ __deprecated static inline int spi_write_async(const struct device *dev, #endif /* CONFIG_SPI_ASYNC */ -#if defined(CONFIG_SPI_RTIO) || defined(DOXYGEN) +#if defined(CONFIG_SPI_RTIO) || defined(__DOXYGEN__) /** * @brief Submit a SPI device with a request * - * @param dev SPI device * @param iodev_sqe Prepared submissions queue entry connected to an iodev * defined by SPI_IODEV_DEFINE. * Must live as long as the request is in flight. - * - * @retval 0 If successful. - * @retval -errno Negative errno code on failure. */ static inline void spi_iodev_submit(struct rtio_iodev_sqe *iodev_sqe) { @@ -1078,7 +1073,10 @@ extern const struct rtio_iodev_api spi_iodev_api; * These do not need to be shared globally but doing so * will save a small amount of memory. * - * @param node DT_NODE + * @param name Symbolic name to use for defining the iodev + * @param node_id Devicetree node identifier + * @param operation_ SPI operational mode + * @param delay_ Chip select delay in microseconds */ #define SPI_DT_IODEV_DEFINE(name, node_id, operation_, delay_) \ const struct spi_dt_spec _spi_dt_spec_##name = \ @@ -1103,11 +1101,11 @@ static inline bool spi_is_ready_iodev(const struct rtio_iodev *spi_iodev) /** * @brief Copy the tx_bufs and rx_bufs into a set of RTIO requests * - * @param r rtio context - * @param iodev iodev to transceive with - * @param tx_bufs transmit buffer set - * @param rx_bufs receive buffer set - * @param sqe[out] Last sqe submitted, NULL if not enough memory + * @param[in] r rtio context + * @param[in] iodev iodev to transceive with + * @param[in] tx_bufs transmit buffer set + * @param[in] rx_bufs receive buffer set + * @param[out] last_sqe last sqe submitted, NULL if not enough memory * * @retval Number of submission queue entries * @retval -ENOMEM out of memory diff --git a/include/zephyr/drivers/uart.h b/include/zephyr/drivers/uart.h index 8604d3fa543..6d68da64a58 100644 --- a/include/zephyr/drivers/uart.h +++ b/include/zephyr/drivers/uart.h @@ -31,11 +31,11 @@ extern "C" { /** @brief Line control signals. */ enum uart_line_ctrl { - UART_LINE_CTRL_BAUD_RATE = BIT(0), - UART_LINE_CTRL_RTS = BIT(1), - UART_LINE_CTRL_DTR = BIT(2), - UART_LINE_CTRL_DCD = BIT(3), - UART_LINE_CTRL_DSR = BIT(4), + UART_LINE_CTRL_BAUD_RATE = BIT(0), /**< Baud rate */ + UART_LINE_CTRL_RTS = BIT(1), /**< Request To Send (RTS) */ + UART_LINE_CTRL_DTR = BIT(2), /**< Data Terminal Ready (DTR) */ + UART_LINE_CTRL_DCD = BIT(3), /**< Data Carrier Detect (DCD) */ + UART_LINE_CTRL_DSR = BIT(4), /**< Data Set Ready (DSR) */ }; /** @@ -75,28 +75,28 @@ enum uart_rx_stop_reason { /** @brief Parity modes */ enum uart_config_parity { - UART_CFG_PARITY_NONE, - UART_CFG_PARITY_ODD, - UART_CFG_PARITY_EVEN, - UART_CFG_PARITY_MARK, - UART_CFG_PARITY_SPACE, + UART_CFG_PARITY_NONE, /**< No parity */ + UART_CFG_PARITY_ODD, /**< Odd parity */ + UART_CFG_PARITY_EVEN, /**< Even parity */ + UART_CFG_PARITY_MARK, /**< Mark parity */ + UART_CFG_PARITY_SPACE, /**< Space parity */ }; /** @brief Number of stop bits. */ enum uart_config_stop_bits { - UART_CFG_STOP_BITS_0_5, - UART_CFG_STOP_BITS_1, - UART_CFG_STOP_BITS_1_5, - UART_CFG_STOP_BITS_2, + UART_CFG_STOP_BITS_0_5, /**< 0.5 stop bit */ + UART_CFG_STOP_BITS_1, /**< 1 stop bit */ + UART_CFG_STOP_BITS_1_5, /**< 1.5 stop bits */ + UART_CFG_STOP_BITS_2, /**< 2 stop bits */ }; /** @brief Number of data bits. */ enum uart_config_data_bits { - UART_CFG_DATA_BITS_5, - UART_CFG_DATA_BITS_6, - UART_CFG_DATA_BITS_7, - UART_CFG_DATA_BITS_8, - UART_CFG_DATA_BITS_9, + UART_CFG_DATA_BITS_5, /**< 5 data bits */ + UART_CFG_DATA_BITS_6, /**< 6 data bits */ + UART_CFG_DATA_BITS_7, /**< 7 data bits */ + UART_CFG_DATA_BITS_8, /**< 8 data bits */ + UART_CFG_DATA_BITS_9, /**< 9 data bits */ }; /** @@ -107,27 +107,21 @@ enum uart_config_data_bits { * In other cases, flow control is managed by hardware/driver. */ enum uart_config_flow_control { - UART_CFG_FLOW_CTRL_NONE, - UART_CFG_FLOW_CTRL_RTS_CTS, - UART_CFG_FLOW_CTRL_DTR_DSR, - UART_CFG_FLOW_CTRL_RS485, + UART_CFG_FLOW_CTRL_NONE, /**< No flow control */ + UART_CFG_FLOW_CTRL_RTS_CTS, /**< RTS/CTS flow control */ + UART_CFG_FLOW_CTRL_DTR_DSR, /**< DTR/DSR flow control */ + UART_CFG_FLOW_CTRL_RS485, /**< RS485 flow control */ }; /** * @brief UART controller configuration structure - * - * @param baudrate Baudrate setting in bps - * @param parity Parity bit, use @ref uart_config_parity - * @param stop_bits Stop bits, use @ref uart_config_stop_bits - * @param data_bits Data bits, use @ref uart_config_data_bits - * @param flow_ctrl Flow control setting, use @ref uart_config_flow_control */ struct uart_config { - uint32_t baudrate; - uint8_t parity; - uint8_t stop_bits; - uint8_t data_bits; - uint8_t flow_ctrl; + uint32_t baudrate; /**< Baudrate setting in bps */ + uint8_t parity; /**< Parity bit, use @ref uart_config_parity */ + uint8_t stop_bits; /**< Stop bits, use @ref uart_config_stop_bits */ + uint8_t data_bits; /**< Data bits, use @ref uart_config_data_bits */ + uint8_t flow_ctrl; /**< Flow control setting, use @ref uart_config_flow_control */ }; /** @@ -285,7 +279,7 @@ struct uart_event_rx { /** @brief UART RX buffer released event data. */ struct uart_event_rx_buf { - /* @brief Pointer to buffer that is no longer in use. */ + /** @brief Pointer to buffer that is no longer in use. */ uint8_t *buf; }; diff --git a/include/zephyr/drivers/usb/uhc.h b/include/zephyr/drivers/usb/uhc.h index aff6b27bc74..5f499af6c1d 100644 --- a/include/zephyr/drivers/usb/uhc.h +++ b/include/zephyr/drivers/usb/uhc.h @@ -25,6 +25,15 @@ * @{ */ +/** + * @brief USB control transfer stage + */ +enum uhc_control_stage { + UHC_CONTROL_STAGE_SETUP = 0, + UHC_CONTROL_STAGE_DATA, + UHC_CONTROL_STAGE_STATUS, +}; + /** * UHC endpoint buffer info * @@ -38,10 +47,10 @@ struct uhc_transfer { /** dlist node */ sys_dnode_t node; - /** FIFO requests to process */ - struct k_fifo queue; - /** FIFO to keep completed requests */ - struct k_fifo done; + /** Control transfer setup packet */ + uint8_t setup_pkt[8]; + /** Transfer data buffer */ + struct net_buf *buf; /** Device (peripheral) address */ uint8_t addr; /** Endpoint to which request is associated */ @@ -52,14 +61,16 @@ struct uhc_transfer { uint16_t mps; /** Timeout in number of frames */ uint16_t timeout; - /** Flag marks request buffer claimed by the controller */ - unsigned int claimed : 1; /** Flag marks request buffer is queued */ unsigned int queued : 1; - /** Flag marks setup stage of transfer */ - unsigned int setup : 1; - /** Transfer owner */ - void *owner; + /** Control stage status, up to the driver to use it or not */ + unsigned int stage : 2; + /** Pointer to USB device (opaque for the UHC) */ + void *udev; + /** Pointer to transfer completion callback (opaque for the UHC) */ + void *cb; + /** Transfer result, 0 on success, other values on error */ + int err; }; /** @@ -105,13 +116,11 @@ struct uhc_event { /** Event type */ enum uhc_event_type type; union { - /** Event value */ - uint32_t value; + /** Event status value, if any */ + int status; /** Pointer to request used only for UHC_EVT_EP_REQUEST */ struct uhc_transfer *xfer; }; - /** Event status, 0 on success, other (transfer) values on error */ - int status; /** Pointer to controller's device struct */ const struct device *dev; }; @@ -321,8 +330,8 @@ static inline int uhc_bus_resume(const struct device *dev) * @brief Allocate UHC transfer * * Allocate a new transfer from common transfer pool. - * Transfer has no buffers after allocation, these can be - * requested and assigned separately. + * Transfer has no buffer after allocation, but can be allocated + * and added from different pools. * * @param[in] dev Pointer to device struct of the driver instance * @param[in] addr Device (peripheral) address @@ -330,7 +339,8 @@ static inline int uhc_bus_resume(const struct device *dev) * @param[in] attrib Endpoint attributes * @param[in] mps Maximum packet size of the endpoint * @param[in] timeout Timeout in number of frames - * @param[in] owner Transfer owner + * @param[in] udev Opaque pointer to USB device + * @param[in] cb Transfer completion callback * * @return pointer to allocated transfer or NULL on error. */ @@ -340,7 +350,35 @@ struct uhc_transfer *uhc_xfer_alloc(const struct device *dev, const uint8_t attrib, const uint16_t mps, const uint16_t timeout, - void *const owner); + void *const udev, + void *const cb); + +/** + * @brief Allocate UHC transfer with buffer + * + * Allocate a new transfer from common transfer pool with buffer. + * + * @param[in] dev Pointer to device struct of the driver instance + * @param[in] addr Device (peripheral) address + * @param[in] ep Endpoint address + * @param[in] attrib Endpoint attributes + * @param[in] mps Maximum packet size of the endpoint + * @param[in] timeout Timeout in number of frames + * @param[in] udev Opaque pointer to USB device + * @param[in] cb Transfer completion callback + * @param[in] size Size of the buffer + * + * @return pointer to allocated transfer or NULL on error. + */ +struct uhc_transfer *uhc_xfer_alloc_with_buf(const struct device *dev, + const uint8_t addr, + const uint8_t ep, + const uint8_t attrib, + const uint16_t mps, + const uint16_t timeout, + void *const udev, + void *const cb, + size_t size); /** * @brief Free UHC transfer and any buffers @@ -355,20 +393,32 @@ struct uhc_transfer *uhc_xfer_alloc(const struct device *dev, int uhc_xfer_free(const struct device *dev, struct uhc_transfer *const xfer); +/** + * @brief Add UHC transfer buffer + * + * Add a previously allocated buffer to the transfer. + * + * @param[in] dev Pointer to device struct of the driver instance + * @param[in] xfer Pointer to UHC transfer + * @param[in] buf Pointer to UHC request buffer + * + * @return pointer to allocated request or NULL on error. + */ +int uhc_xfer_buf_add(const struct device *dev, + struct uhc_transfer *const xfer, + struct net_buf *buf); /** * @brief Allocate UHC transfer buffer * * Allocate a new buffer from common request buffer pool and - * assign it to the transfer. + * assign it to the transfer if the xfer parameter is not NULL. * * @param[in] dev Pointer to device struct of the driver instance - * @param[in] xfer Pointer to UHC transfer * @param[in] size Size of the request buffer * * @return pointer to allocated request or NULL on error. */ struct net_buf *uhc_xfer_buf_alloc(const struct device *dev, - struct uhc_transfer *const xfer, const size_t size); /** @@ -378,10 +428,8 @@ struct net_buf *uhc_xfer_buf_alloc(const struct device *dev, * * @param[in] dev Pointer to device struct of the driver instance * @param[in] buf Pointer to UHC request buffer - * - * @return 0 on success, all other values should be treated as error. */ -int uhc_xfer_buf_free(const struct device *dev, struct net_buf *const buf); +void uhc_xfer_buf_free(const struct device *dev, struct net_buf *const buf); /** * @brief Queue USB host controller transfer diff --git a/include/zephyr/drivers/usb_c/usbc_tcpc.h b/include/zephyr/drivers/usb_c/usbc_tcpc.h index 2788aea2e40..1b62a39db68 100644 --- a/include/zephyr/drivers/usb_c/usbc_tcpc.h +++ b/include/zephyr/drivers/usb_c/usbc_tcpc.h @@ -136,8 +136,7 @@ __subsystem struct tcpc_driver_api { int (*set_vconn)(const struct device *dev, bool enable); int (*set_roles)(const struct device *dev, enum tc_power_role power_role, enum tc_data_role data_role); - int (*receive_data)(const struct device *dev, struct pd_msg *msg); - bool (*is_rx_pending_msg)(const struct device *dev, enum pd_packet_type *type); + int (*get_rx_pending_msg)(const struct device *dev, struct pd_msg *msg); int (*set_rx_enable)(const struct device *dev, bool enable); int (*set_cc_polarity)(const struct device *dev, enum tc_cc_polarity polarity); int (*transmit_data)(const struct device *dev, struct pd_msg *msg); @@ -152,8 +151,8 @@ __subsystem struct tcpc_driver_api { int (*set_debug_accessory)(const struct device *dev, bool enable); int (*set_debug_detach)(const struct device *dev); int (*set_drp_toggle)(const struct device *dev, bool enable); - bool (*get_snk_ctrl)(const struct device *dev); - bool (*get_src_ctrl)(const struct device *dev); + int (*get_snk_ctrl)(const struct device *dev); + int (*get_src_ctrl)(const struct device *dev); int (*get_chip_info)(const struct device *dev, struct tcpc_chip_info *chip_info); int (*set_low_power_mode)(const struct device *dev, bool enable); int (*sop_prime_enable)(const struct device *dev, bool enable); @@ -232,6 +231,7 @@ static inline int tcpc_is_cc_only_one_rd(enum tc_cc_voltage_state cc1, * * @retval 0 on success * @retval -EIO on failure + * @retval -EAGAIN if initialization should be postponed */ static inline int tcpc_init(const struct device *dev) { @@ -455,50 +455,25 @@ static inline int tcpc_set_roles(const struct device *dev, } /** - * @brief Tests if a received Power Delivery message is pending + * @brief Retrieves the Power Delivery message from the TCPC. + * If buf is NULL, then only the status is returned, where 0 means there is a message pending and + * -ENODATA means there is no pending message. * - * @param dev Runtime device structure - * @param type pointer to where message type is written. Can be NULL - * - * @retval true if message is pending, else false - * @retval -EIO on failure - * @retval -ENOSYS if not implemented - */ -static inline bool tcpc_is_rx_pending_msg(const struct device *dev, - enum pd_packet_type *type) -{ - const struct tcpc_driver_api *api = - (const struct tcpc_driver_api *)dev->api; - - if (api->is_rx_pending_msg == NULL) { - return -ENOSYS; - } - - return api->is_rx_pending_msg(dev, type); -} - -/** - * @brief Retrieves the Power Delivery message from the TCPC - * - * @param dev Runtime device structure - * @param buf pointer where the pd_buf pointer is written + * @param dev Runtime device structure + * @param buf pointer where the pd_buf pointer is written, NULL if only checking the status * - * @retval Greater or equal to 0 is the number of bytes received + * @retval Greater or equal to 0 is the number of bytes received if buf parameter is provided + * @retval 0 if there is a message pending and buf parameter is NULL * @retval -EIO on failure - * @retval -EFAULT on buf being NULL - * @retval -ENOSYS if not implemented + * @retval -ENODATA if no message is pending */ -static inline int tcpc_receive_data(const struct device *dev, - struct pd_msg *buf) +static inline int tcpc_get_rx_pending_msg(const struct device *dev, struct pd_msg *buf) { - const struct tcpc_driver_api *api = - (const struct tcpc_driver_api *)dev->api; + const struct tcpc_driver_api *api = (const struct tcpc_driver_api *)dev->api; - if (api->receive_data == NULL) { - return -ENOSYS; - } + __ASSERT(api->get_rx_pending_msg != NULL, "Callback pointer should not be NULL"); - return api->receive_data(dev, buf); + return api->get_rx_pending_msg(dev, buf); } /** @@ -767,7 +742,7 @@ static inline int tcpc_set_drp_toggle(const struct device *dev, bool enable) * @retval false if not sinking power * @retval -ENOSYS if not implemented */ -static inline bool tcpc_get_snk_ctrl(const struct device *dev) +static inline int tcpc_get_snk_ctrl(const struct device *dev) { const struct tcpc_driver_api *api = (const struct tcpc_driver_api *)dev->api; @@ -788,7 +763,7 @@ static inline bool tcpc_get_snk_ctrl(const struct device *dev) * @retval false if not sourcing power * @retval -ENOSYS if not implemented */ -static inline bool tcpc_get_src_ctrl(const struct device *dev) +static inline int tcpc_get_src_ctrl(const struct device *dev) { const struct tcpc_driver_api *api = (const struct tcpc_driver_api *)dev->api; diff --git a/include/zephyr/dsp/dsp.h b/include/zephyr/dsp/dsp.h index d475c68a007..cfaa817cf2e 100644 --- a/include/zephyr/dsp/dsp.h +++ b/include/zephyr/dsp/dsp.h @@ -38,6 +38,8 @@ #include +#include + #include "zdsp_backend.h" #endif /* INCLUDE_ZEPHYR_DSP_DSP_H_ */ diff --git a/include/zephyr/dsp/print_format.h b/include/zephyr/dsp/print_format.h new file mode 100644 index 00000000000..695691424df --- /dev/null +++ b/include/zephyr/dsp/print_format.h @@ -0,0 +1,66 @@ +/* Copyright (c) 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ZEPHYR_DSP_PRINT_FORMAT_H +#define ZEPHYR_INCLUDE_ZEPHYR_DSP_PRINT_FORMAT_H + +#include +#include +#include + +/** + * @ingroup math_dsp + * @defgroup math_printing Helper macros for printing Q values. + * + * Extends the existing inttypes headers for print formatting. Useage: + * @code{c} + * printk("Value=%" PRIq "\n", PRIq_arg(value, 6, 2)); + * @endcode + * + * For a Q value representing 0.5, the expected output will be: + * "Value=2.000000" + * + * @{ + */ + +/** + * @brief Insert Q value format string + */ +#define PRIq(precision) "s%" PRIu32 ".%0" STRINGIFY(precision) PRIu32 + +static inline int64_t ___PRIq_arg_shift(int64_t q, int shift) +{ + if (shift < 0) { + return llabs(q) >> -shift; + } else { + return llabs(q) << shift; + } +} + +#define __EXP2(a, b) a ## b +#define __EXP(a, b) __EXP2(a ## e, b) +#define __CONSTPOW(C, x) __EXP(C, x) + +#define __PRIq_arg_shift(q, shift) ___PRIq_arg_shift(q, ((shift) + (8 * (4 - (int)sizeof(q))))) +#define __PRIq_arg_get(q, shift, h, l) FIELD_GET(GENMASK64(h, l), __PRIq_arg_shift(q, shift)) +#define __PRIq_arg_get_int(q, shift) __PRIq_arg_get(q, shift, 63, 31) +#define __PRIq_arg_get_frac(q, precision, shift) \ + ((__PRIq_arg_get(q, shift, 30, 0) * __CONSTPOW(1, precision)) / INT32_MAX) + +/** + * @brief Insert Q value arguments to print format + * + * @param[in] q The q value + * @param[in] precision Number of decimal points to print + * @param[in] shift The "scale" to shift @p q by + */ +#define PRIq_arg(q, precision, shift) \ + ((q) < 0 ? "-" : ""), (uint32_t)__PRIq_arg_get_int(q, shift), \ + (uint32_t)__PRIq_arg_get_frac(q, precision, shift) + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_ZEPHYR_DSP_PRINT_FORMAT_H */ diff --git a/include/zephyr/dt-bindings/adc/stm32_adc.h b/include/zephyr/dt-bindings/adc/stm32_adc.h index 527a55ef9ed..20f257275e9 100644 --- a/include/zephyr/dt-bindings/adc/stm32_adc.h +++ b/include/zephyr/dt-bindings/adc/stm32_adc.h @@ -74,4 +74,14 @@ #define ASYNC 2 /** @} */ +/** + * @name STM32 ADC sequencer type + * This value is to set + * One or both values may not apply to all series. Refer to the RefMan + * @{ + */ +#define NOT_FULLY_CONFIGURABLE 0 +#define FULLY_CONFIGURABLE 1 +/** @} */ + #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_STM32_ADC_H_ */ diff --git a/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h b/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h index f4b1377cadd..9f80b662c60 100644 --- a/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h +++ b/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h @@ -49,4 +49,8 @@ #define MCUX_LCDIF_PIXEL_CLK 33 +#define MCUX_SCTIMER_CLK 34 + +#define MCUX_MRT_CLK 40 + #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_MCUX_LPC_SYSCON_H_ */ diff --git a/include/zephyr/dt-bindings/clock/nxp_s32z2_clock.h b/include/zephyr/dt-bindings/clock/nxp_s32z2_clock.h new file mode 100644 index 00000000000..6471a2c5406 --- /dev/null +++ b/include/zephyr/dt-bindings/clock/nxp_s32z2_clock.h @@ -0,0 +1,300 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_NXP_S32Z2_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_NXP_S32Z2_CLOCK_H_ + +#define NXP_S32_FIRC_CLK 1U +#define NXP_S32_FXOSC_CLK 2U +#define NXP_S32_SIRC_CLK 3U +#define NXP_S32_COREPLL_CLK 4U +#define NXP_S32_PERIPHPLL_CLK 5U +#define NXP_S32_DDRPLL_CLK 6U +#define NXP_S32_LFAST0_PLL_CLK 7U +#define NXP_S32_LFAST1_PLL_CLK 8U +#define NXP_S32_COREPLL_PHI0_CLK 9U +#define NXP_S32_COREPLL_DFS0_CLK 10U +#define NXP_S32_COREPLL_DFS1_CLK 11U +#define NXP_S32_COREPLL_DFS2_CLK 12U +#define NXP_S32_COREPLL_DFS3_CLK 13U +#define NXP_S32_COREPLL_DFS4_CLK 14U +#define NXP_S32_COREPLL_DFS5_CLK 15U +#define NXP_S32_PERIPHPLL_PHI0_CLK 16U +#define NXP_S32_PERIPHPLL_PHI1_CLK 17U +#define NXP_S32_PERIPHPLL_PHI2_CLK 18U +#define NXP_S32_PERIPHPLL_PHI3_CLK 19U +#define NXP_S32_PERIPHPLL_PHI4_CLK 20U +#define NXP_S32_PERIPHPLL_PHI5_CLK 21U +#define NXP_S32_PERIPHPLL_PHI6_CLK 22U +#define NXP_S32_PERIPHPLL_DFS0_CLK 23U +#define NXP_S32_PERIPHPLL_DFS1_CLK 24U +#define NXP_S32_PERIPHPLL_DFS2_CLK 25U +#define NXP_S32_PERIPHPLL_DFS3_CLK 26U +#define NXP_S32_PERIPHPLL_DFS4_CLK 27U +#define NXP_S32_PERIPHPLL_DFS5_CLK 28U +#define NXP_S32_DDRPLL_PHI0_CLK 29U +#define NXP_S32_LFAST0_PLL_PH0_CLK 30U +#define NXP_S32_LFAST1_PLL_PH0_CLK 31U +#define NXP_S32_ETH_RGMII_REF_CLK 32U +#define NXP_S32_TMR_1588_CLK 33U +#define NXP_S32_ETH0_EXT_RX_CLK 34U +#define NXP_S32_ETH0_EXT_TX_CLK 35U +#define NXP_S32_ETH1_EXT_RX_CLK 36U +#define NXP_S32_ETH1_EXT_TX_CLK 37U +#define NXP_S32_LFAST0_EXT_REF_CLK 38U +#define NXP_S32_LFAST1_EXT_REF_CLK 39U +#define NXP_S32_DDR_CLK 40U +#define NXP_S32_P0_SYS_CLK 41U +#define NXP_S32_P1_SYS_CLK 42U +#define NXP_S32_P1_SYS_DIV2_CLK 43U +#define NXP_S32_P1_SYS_DIV4_CLK 44U +#define NXP_S32_P2_SYS_CLK 45U +#define NXP_S32_CORE_M33_CLK 46U +#define NXP_S32_P2_SYS_DIV2_CLK 47U +#define NXP_S32_P2_SYS_DIV4_CLK 48U +#define NXP_S32_P3_SYS_CLK 49U +#define NXP_S32_CE_SYS_DIV2_CLK 50U +#define NXP_S32_CE_SYS_DIV4_CLK 51U +#define NXP_S32_P3_SYS_DIV2_NOC_CLK 52U +#define NXP_S32_P3_SYS_DIV4_CLK 53U +#define NXP_S32_P4_SYS_CLK 54U +#define NXP_S32_P4_SYS_DIV2_CLK 55U +#define NXP_S32_HSE_SYS_DIV2_CLK 56U +#define NXP_S32_P5_SYS_CLK 57U +#define NXP_S32_P5_SYS_DIV2_CLK 58U +#define NXP_S32_P5_SYS_DIV4_CLK 59U +#define NXP_S32_P2_MATH_CLK 60U +#define NXP_S32_P2_MATH_DIV3_CLK 61U +#define NXP_S32_GLB_LBIST_CLK 62U +#define NXP_S32_RTU0_CORE_CLK 63U +#define NXP_S32_RTU0_CORE_DIV2_CLK 64U +#define NXP_S32_RTU1_CORE_CLK 65U +#define NXP_S32_RTU1_CORE_DIV2_CLK 66U +#define NXP_S32_P0_PSI5_S_UTIL_CLK 67U +#define NXP_S32_P4_PSI5_S_UTIL_CLK 68U +#define NXP_S32_ADC0_CLK 70U +#define NXP_S32_ADC1_CLK 71U +#define NXP_S32_CE_EDMA_CLK 72U +#define NXP_S32_CE_PIT0_CLK 73U +#define NXP_S32_CE_PIT1_CLK 74U +#define NXP_S32_CE_PIT2_CLK 75U +#define NXP_S32_CE_PIT3_CLK 76U +#define NXP_S32_CE_PIT4_CLK 77U +#define NXP_S32_CE_PIT5_CLK 78U +#define NXP_S32_CLKOUT0_CLK 79U +#define NXP_S32_CLKOUT1_CLK 80U +#define NXP_S32_CLKOUT2_CLK 81U +#define NXP_S32_CLKOUT3_CLK 82U +#define NXP_S32_CLKOUT4_CLK 83U +#define NXP_S32_CTU_CLK 84U +#define NXP_S32_DMACRC0_CLK 85U +#define NXP_S32_DMACRC1_CLK 86U +#define NXP_S32_DMACRC4_CLK 87U +#define NXP_S32_DMACRC5_CLK 88U +#define NXP_S32_DMAMUX0_CLK 89U +#define NXP_S32_DMAMUX1_CLK 90U +#define NXP_S32_DMAMUX4_CLK 91U +#define NXP_S32_DMAMUX5_CLK 92U +#define NXP_S32_EDMA0_CLK 93U +#define NXP_S32_EDMA1_CLK 94U +#define NXP_S32_EDMA3_CLK 95U +#define NXP_S32_EDMA4_CLK 96U +#define NXP_S32_EDMA5_CLK 97U +#define NXP_S32_ETH0_TX_MII_CLK 98U +#define NXP_S32_ENET0_CLK 99U +#define NXP_S32_P3_CAN_PE_CLK 100U +#define NXP_S32_FLEXCAN0_CLK 101U +#define NXP_S32_FLEXCAN1_CLK 102U +#define NXP_S32_FLEXCAN2_CLK 103U +#define NXP_S32_FLEXCAN3_CLK 104U +#define NXP_S32_FLEXCAN4_CLK 105U +#define NXP_S32_FLEXCAN5_CLK 106U +#define NXP_S32_FLEXCAN6_CLK 107U +#define NXP_S32_FLEXCAN7_CLK 108U +#define NXP_S32_FLEXCAN8_CLK 109U +#define NXP_S32_FLEXCAN9_CLK 110U +#define NXP_S32_FLEXCAN10_CLK 111U +#define NXP_S32_FLEXCAN11_CLK 112U +#define NXP_S32_FLEXCAN12_CLK 113U +#define NXP_S32_FLEXCAN13_CLK 114U +#define NXP_S32_FLEXCAN14_CLK 115U +#define NXP_S32_FLEXCAN15_CLK 116U +#define NXP_S32_FLEXCAN16_CLK 117U +#define NXP_S32_FLEXCAN17_CLK 118U +#define NXP_S32_FLEXCAN18_CLK 119U +#define NXP_S32_FLEXCAN19_CLK 120U +#define NXP_S32_FLEXCAN20_CLK 121U +#define NXP_S32_FLEXCAN21_CLK 122U +#define NXP_S32_FLEXCAN22_CLK 123U +#define NXP_S32_FLEXCAN23_CLK 124U +#define NXP_S32_P0_FR_PE_CLK 125U +#define NXP_S32_FRAY0_CLK 126U +#define NXP_S32_FRAY1_CLK 127U +#define NXP_S32_GTM_CLK 128U +#define NXP_S32_IIIC0_CLK 129U +#define NXP_S32_IIIC1_CLK 130U +#define NXP_S32_IIIC2_CLK 131U +#define NXP_S32_P0_LIN_BAUD_CLK 132U +#define NXP_S32_LIN0_CLK 133U +#define NXP_S32_LIN1_CLK 134U +#define NXP_S32_LIN2_CLK 135U +#define NXP_S32_P1_LIN_BAUD_CLK 136U +#define NXP_S32_LIN3_CLK 137U +#define NXP_S32_LIN4_CLK 138U +#define NXP_S32_LIN5_CLK 139U +#define NXP_S32_P4_LIN_BAUD_CLK 140U +#define NXP_S32_LIN6_CLK 141U +#define NXP_S32_LIN7_CLK 142U +#define NXP_S32_LIN8_CLK 143U +#define NXP_S32_P5_LIN_BAUD_CLK 144U +#define NXP_S32_LIN9_CLK 145U +#define NXP_S32_LIN10_CLK 146U +#define NXP_S32_LIN11_CLK 147U +#define NXP_S32_MSCDSPI_CLK 148U +#define NXP_S32_MSCLIN_CLK 149U +#define NXP_S32_NANO_CLK 150U +#define NXP_S32_P0_CLKOUT_SRC_CLK 151U +#define NXP_S32_P0_CTU_PER_CLK 152U +#define NXP_S32_P0_DSPI_MSC_CLK 153U +#define NXP_S32_P0_EMIOS_LCU_CLK 154U +#define NXP_S32_P0_GTM_CLK 155U +#define NXP_S32_P0_GTM_NOC_CLK 156U +#define NXP_S32_P0_GTM_TS_CLK 157U +#define NXP_S32_P0_LIN_CLK 158U +#define NXP_S32_P0_NANO_CLK 159U +#define NXP_S32_P0_PSI5_125K_CLK 160U +#define NXP_S32_P0_PSI5_189K_CLK 161U +#define NXP_S32_P0_PSI5_S_BAUD_CLK 162U +#define NXP_S32_P0_PSI5_S_CORE_CLK 163U +#define NXP_S32_P0_PSI5_S_TRIG0_CLK 164U +#define NXP_S32_P0_PSI5_S_TRIG1_CLK 165U +#define NXP_S32_P0_PSI5_S_TRIG2_CLK 166U +#define NXP_S32_P0_PSI5_S_TRIG3_CLK 167U +#define NXP_S32_P0_PSI5_S_UART_CLK 168U +#define NXP_S32_P0_PSI5_S_WDOG0_CLK 169U +#define NXP_S32_P0_PSI5_S_WDOG1_CLK 170U +#define NXP_S32_P0_PSI5_S_WDOG2_CLK 171U +#define NXP_S32_P0_PSI5_S_WDOG3_CLK 172U +#define NXP_S32_P0_REG_INTF_2X_CLK 173U +#define NXP_S32_P0_REG_INTF_CLK 174U +#define NXP_S32_P1_CLKOUT_SRC_CLK 175U +#define NXP_S32_P1_DSPI60_CLK 176U +#define NXP_S32_ETH_TS_CLK 177U +#define NXP_S32_ETH_TS_DIV4_CLK 178U +#define NXP_S32_ETH0_REF_RMII_CLK 179U +#define NXP_S32_ETH0_RX_MII_CLK 180U +#define NXP_S32_ETH0_RX_RGMII_CLK 181U +#define NXP_S32_ETH0_TX_RGMII_CLK 182U +#define NXP_S32_ETH0_PS_TX_CLK 183U +#define NXP_S32_ETH1_REF_RMII_CLK 184U +#define NXP_S32_ETH1_RX_MII_CLK 185U +#define NXP_S32_ETH1_RX_RGMII_CLK 186U +#define NXP_S32_ETH1_TX_MII_CLK 187U +#define NXP_S32_ETH1_TX_RGMII_CLK 188U +#define NXP_S32_ETH1_PS_TX_CLK 189U +#define NXP_S32_P1_LFAST0_REF_CLK 190U +#define NXP_S32_P1_LFAST1_REF_CLK 191U +#define NXP_S32_P1_NETC_AXI_CLK 192U +#define NXP_S32_P1_LIN_CLK 193U +#define NXP_S32_P1_REG_INTF_CLK 194U +#define NXP_S32_P2_DBG_ATB_CLK 195U +#define NXP_S32_P2_REG_INTF_CLK 196U +#define NXP_S32_P3_AES_CLK 197U +#define NXP_S32_P3_CLKOUT_SRC_CLK 198U +#define NXP_S32_P3_DBG_TS_CLK 199U +#define NXP_S32_P3_REG_INTF_CLK 200U +#define NXP_S32_P3_SYS_MON1_CLK 201U +#define NXP_S32_P3_SYS_MON2_CLK 202U +#define NXP_S32_P3_SYS_MON3_CLK 203U +#define NXP_S32_P4_CLKOUT_SRC_CLK 204U +#define NXP_S32_P4_DSPI60_CLK 205U +#define NXP_S32_P4_EMIOS_LCU_CLK 206U +#define NXP_S32_P4_LIN_CLK 207U +#define NXP_S32_P4_PSI5_125K_CLK 208U +#define NXP_S32_P4_PSI5_189K_CLK 209U +#define NXP_S32_P4_PSI5_S_BAUD_CLK 210U +#define NXP_S32_P4_PSI5_S_CORE_CLK 211U +#define NXP_S32_P4_PSI5_S_TRIG0_CLK 212U +#define NXP_S32_P4_PSI5_S_TRIG1_CLK 213U +#define NXP_S32_P4_PSI5_S_TRIG2_CLK 214U +#define NXP_S32_P4_PSI5_S_TRIG3_CLK 215U +#define NXP_S32_P4_PSI5_S_UART_CLK 216U +#define NXP_S32_P4_PSI5_S_WDOG0_CLK 217U +#define NXP_S32_P4_PSI5_S_WDOG1_CLK 218U +#define NXP_S32_P4_PSI5_S_WDOG2_CLK 219U +#define NXP_S32_P4_PSI5_S_WDOG3_CLK 220U +#define NXP_S32_P4_QSPI0_2X_CLK 221U +#define NXP_S32_P4_QSPI0_1X_CLK 222U +#define NXP_S32_P4_QSPI1_2X_CLK 223U +#define NXP_S32_P4_QSPI1_1X_CLK 224U +#define NXP_S32_P4_REG_INTF_2X_CLK 225U +#define NXP_S32_P4_REG_INTF_CLK 226U +#define NXP_S32_P4_SDHC_IP_CLK 227U +#define NXP_S32_P4_SDHC_IP_DIV2_CLK 228U +#define NXP_S32_P5_DIPORT_CLK 229U +#define NXP_S32_P5_AE_CLK 230U +#define NXP_S32_P5_CANXL_PE_CLK 231U +#define NXP_S32_P5_CANXL_CHI_CLK 232U +#define NXP_S32_P5_CLKOUT_SRC_CLK 233U +#define NXP_S32_P5_LIN_CLK 234U +#define NXP_S32_P5_REG_INTF_CLK 235U +#define NXP_S32_P6_REG_INTF_CLK 236U +#define NXP_S32_PIT0_CLK 237U +#define NXP_S32_PIT1_CLK 238U +#define NXP_S32_PIT4_CLK 239U +#define NXP_S32_PIT5_CLK 240U +#define NXP_S32_P0_PSI5_1US_CLK 241U +#define NXP_S32_PSI5_0_CLK 242U +#define NXP_S32_P4_PSI5_1US_CLK 243U +#define NXP_S32_PSI5_1_CLK 244U +#define NXP_S32_PSI5S_0_CLK 245U +#define NXP_S32_PSI5S_1_CLK 246U +#define NXP_S32_QSPI0_CLK 247U +#define NXP_S32_QSPI1_CLK 248U +#define NXP_S32_RTU0_CORE_MON1_CLK 249U +#define NXP_S32_RTU0_CORE_MON2_CLK 250U +#define NXP_S32_RTU0_CORE_DIV2_MON1_CLK 251U +#define NXP_S32_RTU0_CORE_DIV2_MON2_CLK 252U +#define NXP_S32_RTU0_CORE_DIV2_MON3_CLK 253U +#define NXP_S32_RTU0_REG_INTF_CLK 254U +#define NXP_S32_RTU1_CORE_MON1_CLK 255U +#define NXP_S32_RTU1_CORE_MON2_CLK 256U +#define NXP_S32_RTU1_CORE_DIV2_MON1_CLK 257U +#define NXP_S32_RTU1_CORE_DIV2_MON2_CLK 258U +#define NXP_S32_RTU1_CORE_DIV2_MON3_CLK 259U +#define NXP_S32_RTU1_REG_INTF_CLK 260U +#define NXP_S32_P4_SDHC_CLK 261U +#define NXP_S32_RXLUT_CLK 262U +#define NXP_S32_SDHC0_CLK 263U +#define NXP_S32_SINC_CLK 264U +#define NXP_S32_SIPI0_CLK 265U +#define NXP_S32_SIPI1_CLK 266U +#define NXP_S32_SIUL2_0_CLK 267U +#define NXP_S32_SIUL2_1_CLK 268U +#define NXP_S32_SIUL2_4_CLK 269U +#define NXP_S32_SIUL2_5_CLK 270U +#define NXP_S32_P0_DSPI_CLK 271U +#define NXP_S32_SPI0_CLK 272U +#define NXP_S32_SPI1_CLK 273U +#define NXP_S32_P1_DSPI_CLK 274U +#define NXP_S32_SPI2_CLK 275U +#define NXP_S32_SPI3_CLK 276U +#define NXP_S32_SPI4_CLK 277U +#define NXP_S32_P4_DSPI_CLK 278U +#define NXP_S32_SPI5_CLK 279U +#define NXP_S32_SPI6_CLK 280U +#define NXP_S32_SPI7_CLK 281U +#define NXP_S32_P5_DSPI_CLK 282U +#define NXP_S32_SPI8_CLK 283U +#define NXP_S32_SPI9_CLK 284U +#define NXP_S32_SRX0_CLK 285U +#define NXP_S32_SRX1_CLK 286U +#define NXP_S32_CORE_PLL_REFCLKOUT 287U +#define NXP_S32_CORE_PLL_FBCLKOUT 288U +#define NXP_S32_PERIPH_PLL_REFCLKOUT 289U +#define NXP_S32_PERIPH_PLL_FBCLKOUT 290U + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_NXP_S32Z2_CLOCK_H_ */ diff --git a/include/zephyr/dt-bindings/clock/r7fa4m1xxxxxx-clock.h b/include/zephyr/dt-bindings/clock/r7fa4m1xxxxxx-clock.h new file mode 100644 index 00000000000..355c4982a3d --- /dev/null +++ b/include/zephyr/dt-bindings/clock/r7fa4m1xxxxxx-clock.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DT_BINDINGS_CLOCK_R7FA4M1XXXXXX_CLOCK_H_ +#define ZEPHYR_DT_BINDINGS_CLOCK_R7FA4M1XXXXXX_CLOCK_H_ + +#include + +#endif /* ZEPHYR_DT_BINDINGS_CLOCK_R7FA4M1XXXXXX_CLOCK_H_ */ diff --git a/include/zephyr/dt-bindings/clock/renesas-ra-cgc.h b/include/zephyr/dt-bindings/clock/renesas-ra-cgc.h new file mode 100644 index 00000000000..31bb65ecc45 --- /dev/null +++ b/include/zephyr/dt-bindings/clock/renesas-ra-cgc.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DT_BINDINGS_CLOCK_RENESAS_RA_CGC_H_ +#define ZEPHYR_DT_BINDINGS_CLOCK_RENESAS_RA_CGC_H_ + +#define RA_CLOCK(grp, func, ch) ((grp << 28) | (func << 20) | ch) + +#define RA_CLOCK_GROUP(mod) (((mod >> 28) & 0xF) * 4) +#define RA_CLOCK_BIT(mod) BIT(((mod >> 20) & 0xFF) - ((mod >> 0) & 0xF)) + +#define RA_CLOCK_DMAC(channel) RA_CLOCK(0, 22, channel) +#define RA_CLOCK_DTC(channel) RA_CLOCK(0, 22, channel) +#define RA_CLOCK_CAN(channel) RA_CLOCK(1, 2, channel) +#define RA_CLOCK_CEC(channel) RA_CLOCK(1, 3U, channel) +#define RA_CLOCK_I3C(channel) RA_CLOCK(1, 4U, channel) +#define RA_CLOCK_IRDA(channel) RA_CLOCK(1, 5U, channel) +#define RA_CLOCK_QSPI(channel) RA_CLOCK(1, 6U, channel) +#define RA_CLOCK_IIC(channel) RA_CLOCK(1, 9U, channel) +#define RA_CLOCK_USBFS(channel) RA_CLOCK(1, 11U, channel) +#define RA_CLOCK_USBHS(channel) RA_CLOCK(1, 12U, channel) +#define RA_CLOCK_EPTPC(channel) RA_CLOCK(1, 13U, channel) +#define RA_CLOCK_ETHER(channel) RA_CLOCK(1, 15U, channel) +#define RA_CLOCK_OSPI(channel) RA_CLOCK(1, 16U, channel) +#define RA_CLOCK_SPI(channel) RA_CLOCK(1, 19U, channel) +#define RA_CLOCK_SCI(channel) RA_CLOCK(1, 31U, channel) +#define RA_CLOCK_CAC(channel) RA_CLOCK(2, 0U, channel) +#define RA_CLOCK_CRC(channel) RA_CLOCK(2, 1U, channel) +#define RA_CLOCK_PDC(channel) RA_CLOCK(2, 2U, channel) +#define RA_CLOCK_CTSU(channel) RA_CLOCK(2, 3U, channel) +#define RA_CLOCK_SLCDC(channel) RA_CLOCK(2, 4U, channel) +#define RA_CLOCK_GLCDC(channel) RA_CLOCK(2, 4U, channel) +#define RA_CLOCK_JPEG(channel) RA_CLOCK(2, 5U, channel) +#define RA_CLOCK_DRW(channel) RA_CLOCK(2, 6U, channel) +#define RA_CLOCK_SSI(channel) RA_CLOCK(2, 8U, channel) +#define RA_CLOCK_SRC(channel) RA_CLOCK(2, 9U, channel) +#define RA_CLOCK_SDHIMMC(channel) RA_CLOCK(2, 12U, channel) +#define RA_CLOCK_DOC(channel) RA_CLOCK(2, 13U, channel) +#define RA_CLOCK_ELC(channel) RA_CLOCK(2, 14U, channel) +#define RA_CLOCK_CEU(channel) RA_CLOCK(2, 16U, channel) +#define RA_CLOCK_TFU(channel) RA_CLOCK(2, 20U, channel) +#define RA_CLOCK_IIRFA(channel) RA_CLOCK(2, 21U, channel) +#define RA_CLOCK_CANFD(channel) RA_CLOCK(2, 27U, channel) +#define RA_CLOCK_TRNG(channel) RA_CLOCK(2, 28U, channel) +#define RA_CLOCK_SCE(channel) RA_CLOCK(2, 31U, channel) +#define RA_CLOCK_AES(channel) RA_CLOCK(2, 31U, channel) +#define RA_CLOCK_POEG(channel) RA_CLOCK(3, 14U, channel) +#define RA_CLOCK_ADC(channel) RA_CLOCK(3, 16U, channel) +#define RA_CLOCK_SDADC(channel) RA_CLOCK(3, 17U, channel) +#define RA_CLOCK_DAC8(channel) RA_CLOCK(3, 19U, channel) +#define RA_CLOCK_DAC(channel) RA_CLOCK(3, 20U, channel) +#define RA_CLOCK_TSN(channel) RA_CLOCK(3, 22U, channel) +#define RA_CLOCK_ACMPHS(channel) RA_CLOCK(3, 28U, channel) +#define RA_CLOCK_ACMPLP(channel) RA_CLOCK(3, 29U, channel) +#define RA_CLOCK_OPAMP(channel) RA_CLOCK(3, 31U, channel) +#define RA_CLOCK_AGT(channel) RA_CLOCK(4, 3U, channel) +#define RA_CLOCK_KEY(channel) RA_CLOCK(4, 4U, channel) +#define RA_CLOCK_ULPT(channel) RA_CLOCK(4, 9U, channel) +#define RA_CLOCK_GPT(channel) RA_CLOCK(5, 31U, channel) + +#endif /* ZEPHYR_DT_BINDINGS_CLOCK_RENESAS_RA_CGC_H_ */ diff --git a/include/zephyr/dt-bindings/clock/stm32u5_clock.h b/include/zephyr/dt-bindings/clock/stm32u5_clock.h index 900f77620f8..ca4b774d802 100644 --- a/include/zephyr/dt-bindings/clock/stm32u5_clock.h +++ b/include/zephyr/dt-bindings/clock/stm32u5_clock.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2022 Linaro Limited + * Copyright (c) 2023 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -87,8 +88,8 @@ #define USART1_SEL(val) STM32_CLOCK(val, 3, 0, CCIPR1_REG) #define USART2_SEL(val) STM32_CLOCK(val, 3, 2, CCIPR1_REG) #define USART3_SEL(val) STM32_CLOCK(val, 3, 4, CCIPR1_REG) -#define USART4_SEL(val) STM32_CLOCK(val, 3, 6, CCIPR1_REG) -#define USART5_SEL(val) STM32_CLOCK(val, 3, 8, CCIPR1_REG) +#define UART4_SEL(val) STM32_CLOCK(val, 3, 6, CCIPR1_REG) +#define UART5_SEL(val) STM32_CLOCK(val, 3, 8, CCIPR1_REG) #define I2C1_SEL(val) STM32_CLOCK(val, 3, 10, CCIPR1_REG) #define I2C2_SEL(val) STM32_CLOCK(val, 3, 12, CCIPR1_REG) #define I2C4_SEL(val) STM32_CLOCK(val, 3, 14, CCIPR1_REG) @@ -106,7 +107,14 @@ #define SAE_SEL(val) STM32_CLOCK(val, 1, 11, CCIPR2_REG) #define RNG_SEL(val) STM32_CLOCK(val, 3, 12, CCIPR2_REG) #define SDMMC_SEL(val) STM32_CLOCK(val, 1, 14, CCIPR2_REG) +#define DSIHOST_SEL(val) STM32_CLOCK(val, 1, 15, CCIPR2_REG) +#define USART6_SEL(val) STM32_CLOCK(val, 1, 16, CCIPR2_REG) +#define LTDC_SEL(val) STM32_CLOCK(val, 1, 18, CCIPR2_REG) #define OCTOSPI_SEL(val) STM32_CLOCK(val, 3, 20, CCIPR2_REG) +#define HSPI_SEL(val) STM32_CLOCK(val, 3, 22, CCIPR2_REG) +#define I2C5_SEL(val) STM32_CLOCK(val, 3, 24, CCIPR2_REG) +#define I2C6_SEL(val) STM32_CLOCK(val, 3, 26, CCIPR2_REG) +#define USBPHYC_SEL(val) STM32_CLOCK(val, 3, 30, CCIPR2_REG) /** CCIPR3 devices */ #define LPUART1_SEL(val) STM32_CLOCK(val, 7, 0, CCIPR3_REG) #define SPI3_SEL(val) STM32_CLOCK(val, 3, 3, CCIPR3_REG) @@ -118,5 +126,10 @@ #define ADF1_SEL(val) STM32_CLOCK(val, 7, 16, CCIPR3_REG) /** BDCR devices */ #define RTC_SEL(val) STM32_CLOCK(val, 3, 8, BDCR_REG) +/** + * Dummy: Add a specifier when no selection is possible, value may not occur + * in used RCC regs + */ +#define NO_SEL 0xFF #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32U5_CLOCK_H_ */ diff --git a/include/zephyr/dt-bindings/clock/stm32wba_clock.h b/include/zephyr/dt-bindings/clock/stm32wba_clock.h index 757cb8a0552..50ec4703e3f 100644 --- a/include/zephyr/dt-bindings/clock/stm32wba_clock.h +++ b/include/zephyr/dt-bindings/clock/stm32wba_clock.h @@ -72,6 +72,8 @@ #define CCIPR1_REG 0xE0 #define CCIPR2_REG 0xE4 #define CCIPR3_REG 0xE8 +/** @brief RCC_BCDR1 register offset (RM0493.pdf) */ +#define BCDR1_REG 0xF0 /** @brief Device clk sources selection helpers */ /** CCIPR1 devices */ @@ -90,5 +92,7 @@ #define I2C3_SEL(val) STM32_CLOCK(val, 3, 6, CCIPR3_REG) #define LPTIM1_SEL(val) STM32_CLOCK(val, 3, 10, CCIPR3_REG) #define ADC_SEL(val) STM32_CLOCK(val, 7, 12, CCIPR3_REG) +/** BCDR1 devices */ +#define RTC_SEL(val) STM32_CLOCK(val, 3, 8, BCDR1_REG) #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32WBA_CLOCK_H_ */ diff --git a/include/zephyr/dt-bindings/gpio/nxp-s32-gpio.h b/include/zephyr/dt-bindings/gpio/nxp-s32-gpio.h new file mode 100644 index 00000000000..ebd789e5d8b --- /dev/null +++ b/include/zephyr/dt-bindings/gpio/nxp-s32-gpio.h @@ -0,0 +1,39 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_NXP_S32_GPIO_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_NXP_S32_GPIO_H_ + +/** + * @brief NXP S32 GPIO specific flags + * + * The driver flags are encoded in the 8 upper bits of @ref gpio_dt_flags_t as + * follows: + * + * - Bit 8: Interrupt controller to which the respective GPIO interrupt is routed. + * + * @ingroup gpio_interface + * @{ + */ + +/** @cond INTERNAL_HIDDEN */ +#define NXP_S32_GPIO_INT_CONTROLLER_POS 8 +#define NXP_S32_GPIO_INT_CONTROLLER_MASK (0x1U << NXP_S32_GPIO_INT_CONTROLLER_POS) +/** @endcond */ + +/** + * @name NXP S32 GPIO interrupt controller routing flags + * @brief NXP S32 GPIO interrupt controller routing flags + * @{ + */ + +/** Interrupt routed to the WKPU controller */ +#define NXP_S32_GPIO_INT_WKPU (0x1U << NXP_S32_GPIO_INT_CONTROLLER_POS) + +/** @} */ + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_NXP_S32_GPIO_H_ */ diff --git a/include/zephyr/dt-bindings/gpio/renesas-rzt2m-gpio.h b/include/zephyr/dt-bindings/gpio/renesas-rzt2m-gpio.h new file mode 100644 index 00000000000..8bd26d46434 --- /dev/null +++ b/include/zephyr/dt-bindings/gpio/renesas-rzt2m-gpio.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_RENESAS_RZT2M_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_RENESAS_RZT2M_H_ +#include + +#define RZT2M_GPIO_DRIVE_OFFSET 8 +#define RZT2M_GPIO_DRIVE_MASK GENMASK(RZT2M_GPIO_DRIVE_OFFSET + 2, RZT2M_GPIO_DRIVE_OFFSET) + +/** + * @brief Select GPIO pin drive strength + */ +#define RZT2M_GPIO_DRIVE_LOW (0U << RZT2M_GPIO_DRIVE_OFFSET) +#define RZT2M_GPIO_DRIVE_MIDDLE (1U << RZT2M_GPIO_DRIVE_OFFSET) +#define RZT2M_GPIO_DRIVE_HIGH (2U << RZT2M_GPIO_DRIVE_OFFSET) +#define RZT2M_GPIO_DRIVE_ULTRA_HIGH (3U << RZT2M_GPIO_DRIVE_OFFSET) + +#define RZT2M_GPIO_SCHMITT_TRIGGER_OFFSET 10 +#define RZT2M_GPIO_SCHMITT_TRIGGER_MASK BIT(RZT2M_GPIO_SCHMITT_TRIGGER_OFFSET) + +/** + * @brief Enable GPIO pin schmitt trigger + */ +#define RZT2M_GPIO_SCHMITT_TRIGGER BIT(RZT2M_GPIO_SCHMITT_TRIGGER_OFFSET) + +#define RZT2M_GPIO_SLEW_RATE_OFFSET 11 +#define RZT2M_GPIO_SLEW_RATE_MASK BIT(RZT2M_GPIO_SLEW_RATE_OFFSET) + +/** + * @brief Select GPIO pin slew rate + */ +#define RZT2M_GPIO_SLEW_RATE_SLOW 0U +#define RZT2M_GPIO_SLEW_RATE_FAST BIT(RZT2M_GPIO_SLEW_RATE_OFFSET) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_RENESAS_RZT2M_H_ */ diff --git a/include/zephyr/dt-bindings/i2c/it8xxx2-i2c.h b/include/zephyr/dt-bindings/i2c/it8xxx2-i2c.h index a42879d1331..199e813308e 100644 --- a/include/zephyr/dt-bindings/i2c/it8xxx2-i2c.h +++ b/include/zephyr/dt-bindings/i2c/it8xxx2-i2c.h @@ -20,4 +20,12 @@ #define CGC_OFFSET_SMBB ((IT8XXX2_ECPM_CGCTRL4R_OFF << 8) | 0x08) #define CGC_OFFSET_SMBA ((IT8XXX2_ECPM_CGCTRL4R_OFF << 8) | 0x04) +/* I2C channel switch selection */ +#define I2C_CHA_LOCATE 0 +#define I2C_CHB_LOCATE 1 +#define I2C_CHC_LOCATE 2 +#define I2C_CHD_LOCATE 3 +#define I2C_CHE_LOCATE 4 +#define I2C_CHF_LOCATE 5 + #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_I2C_IT8XXX2_H_ */ diff --git a/include/zephyr/dt-bindings/interrupt-controller/renesas-ra-icu.h b/include/zephyr/dt-bindings/interrupt-controller/renesas-ra-icu.h new file mode 100644 index 00000000000..77372b76e21 --- /dev/null +++ b/include/zephyr/dt-bindings/interrupt-controller/renesas-ra-icu.h @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DT_BINDINGS_INTERRUPT_CONTROLLER_RENESAS_RA_ICU_H_ +#define ZEPHYR_DT_BINDINGS_INTERRUPT_CONTROLLER_RENESAS_RA_ICU_H_ + +#define RA_ICU_IRQ_UNSPECIFIED (-1) + +#define RA_ICU_PORT_IRQ0 (1 << 8) +#define RA_ICU_PORT_IRQ1 (2 << 8) +#define RA_ICU_PORT_IRQ2 (3 << 8) +#define RA_ICU_PORT_IRQ3 (4 << 8) +#define RA_ICU_PORT_IRQ4 (5 << 8) +#define RA_ICU_PORT_IRQ5 (6 << 8) +#define RA_ICU_PORT_IRQ6 (7 << 8) +#define RA_ICU_PORT_IRQ7 (8 << 8) +#define RA_ICU_PORT_IRQ8 (9 << 8) +#define RA_ICU_PORT_IRQ9 (10 << 8) +#define RA_ICU_PORT_IRQ10 (11 << 8) +#define RA_ICU_PORT_IRQ11 (12 << 8) +#define RA_ICU_PORT_IRQ12 (13 << 8) +#define RA_ICU_PORT_IRQ14 (15 << 8) +#define RA_ICU_PORT_IRQ15 (16 << 8) +#define RA_ICU_DMAC0_INT (17 << 8) +#define RA_ICU_DMAC1_INT (18 << 8) +#define RA_ICU_DMAC2_INT (19 << 8) +#define RA_ICU_DMAC3_INT (20 << 8) +#define RA_ICU_DTC_COMPLETE (21 << 8) +#define RA_ICU_ICU_SNZCANCEL (23 << 8) +#define RA_ICU_FCU_FRDYI (24 << 8) +#define RA_ICU_LVD_LVD1 (25 << 8) +#define RA_ICU_LVD_LVD2 (26 << 8) +#define RA_ICU_VBATT_LVD (27 << 8) +#define RA_ICU_MOSC_STOP (28 << 8) +#define RA_ICU_SYSTEM_SNZREQ (29 << 8) +#define RA_ICU_AGT0_AGTI (30 << 8) +#define RA_ICU_AGT0_AGTCMAI (31 << 8) +#define RA_ICU_AGT0_AGTCMBI (32 << 8) +#define RA_ICU_AGT1_AGTI (33 << 8) +#define RA_ICU_AGT1_AGTCMAI (34 << 8) +#define RA_ICU_AGT1_AGTCMBI (35 << 8) +#define RA_ICU_IWDT_NMIUNDF (36 << 8) +#define RA_ICU_WDT_NMIUNDF (37 << 8) +#define RA_ICU_RTC_ALM (38 << 8) +#define RA_ICU_RTC_PRD (39 << 8) +#define RA_ICU_RTC_CUP (40 << 8) +#define RA_ICU_ADC140_ADI (41 << 8) +#define RA_ICU_ADC140_GBADI (42 << 8) +#define RA_ICU_ADC140_CMPAI (43 << 8) +#define RA_ICU_ADC140_CMPBI (44 << 8) +#define RA_ICU_ADC140_WCMPM (45 << 8) +#define RA_ICU_ADC140_WCMPUM (46 << 8) +#define RA_ICU_ACMP_LP0 (47 << 8) +#define RA_ICU_ACMP_LP1 (48 << 8) +#define RA_ICU_USBFS_D0FIFO (49 << 8) +#define RA_ICU_USBFS_D1FIFO (50 << 8) +#define RA_ICU_USBFS_USBI (51 << 8) +#define RA_ICU_USBFS_USBR (52 << 8) +#define RA_ICU_IIC0_RXI (53 << 8) +#define RA_ICU_IIC0_TXI (54 << 8) +#define RA_ICU_IIC0_TEI (55 << 8) +#define RA_ICU_IIC0_EEI (56 << 8) +#define RA_ICU_IIC0_WUI (57 << 8) +#define RA_ICU_IIC1_RXI (58 << 8) +#define RA_ICU_IIC1_TXI (59 << 8) +#define RA_ICU_IIC1_TEI (60 << 8) +#define RA_ICU_IIC1_EEI (61 << 8) +#define RA_ICU_SSIE0_SSITXI (62 << 8) +#define RA_ICU_SSIE0_SSIRXI (63 << 8) +#define RA_ICU_SSIE0_SSIF (64 << 8) +#define RA_ICU_CTSU_CTSUWR (65 << 8) +#define RA_ICU_CTSU_CTSURD (66 << 8) +#define RA_ICU_CTSU_CTSUFN (67 << 8) +#define RA_ICU_KEY_INTKR (68 << 8) +#define RA_ICU_DOC_DOPCI (69 << 8) +#define RA_ICU_CAC_FERRI (70 << 8) +#define RA_ICU_CAC_MENDI (71 << 8) +#define RA_ICU_CAC_OVFI (72 << 8) +#define RA_ICU_CAN0_ERS (73 << 8) +#define RA_ICU_CAN0_RXF (74 << 8) +#define RA_ICU_CAN0_TXF (75 << 8) +#define RA_ICU_CAN0_RXM (76 << 8) +#define RA_ICU_CAN0_TXM (77 << 8) +#define RA_ICU_IOPORT_GROUP1 (78 << 8) +#define RA_ICU_IOPORT_GROUP2 (79 << 8) +#define RA_ICU_IOPORT_GROUP3 (80 << 8) +#define RA_ICU_IOPORT_GROUP4 (81 << 8) +#define RA_ICU_ELC_SWEVT0 (82 << 8) +#define RA_ICU_ELC_SWEVT1 (83 << 8) +#define RA_ICU_POEG_GROUP0 (84 << 8) +#define RA_ICU_POEG_GROUP1 (85 << 8) +#define RA_ICU_GPT0_CCMPA (86 << 8) +#define RA_ICU_GPT0_CCMPB (87 << 8) +#define RA_ICU_GPT0_CMPC (88 << 8) +#define RA_ICU_GPT0_CMPD (89 << 8) +#define RA_ICU_GPT0_CMPE (90 << 8) +#define RA_ICU_GPT0_CMPF (91 << 8) +#define RA_ICU_GPT0_OVF (92 << 8) +#define RA_ICU_GPT0_UDF (93 << 8) +#define RA_ICU_GPT1_CCMPA (94 << 8) +#define RA_ICU_GPT1_CCMPB (95 << 8) +#define RA_ICU_GPT1_CMPC (96 << 8) +#define RA_ICU_GPT1_CMPD (97 << 8) +#define RA_ICU_GPT1_CMPE (98 << 8) +#define RA_ICU_GPT1_CMPF (99 << 8) +#define RA_ICU_GPT1_OVF (100 << 8) +#define RA_ICU_GPT1_UDF (101 << 8) +#define RA_ICU_GPT2_CCMPA (102 << 8) +#define RA_ICU_GPT2_CCMPB (103 << 8) +#define RA_ICU_GPT2_CMPC (104 << 8) +#define RA_ICU_GPT2_CMPD (105 << 8) +#define RA_ICU_GPT2_CMPE (106 << 8) +#define RA_ICU_GPT2_CMPF (107 << 8) +#define RA_ICU_GPT2_OVF (108 << 8) +#define RA_ICU_GPT2_UDF (109 << 8) +#define RA_ICU_GPT3_CCMPA (110 << 8) +#define RA_ICU_GPT3_CCMPB (111 << 8) +#define RA_ICU_GPT3_CMPC (112 << 8) +#define RA_ICU_GPT3_CMPD (113 << 8) +#define RA_ICU_GPT3_CMPE (114 << 8) +#define RA_ICU_GPT3_CMPF (115 << 8) +#define RA_ICU_GPT3_OVF (116 << 8) +#define RA_ICU_GPT3_UDF (117 << 8) +#define RA_ICU_GPT4_CCMPA (118 << 8) +#define RA_ICU_GPT4_CCMPB (119 << 8) +#define RA_ICU_GPT4_CMPC (120 << 8) +#define RA_ICU_GPT4_CMPD (121 << 8) +#define RA_ICU_GPT4_CMPE (122 << 8) +#define RA_ICU_GPT4_CMPF (123 << 8) +#define RA_ICU_GPT4_OVF (124 << 8) +#define RA_ICU_GPT4_UDF (125 << 8) +#define RA_ICU_GPT5_CCMPA (126 << 8) +#define RA_ICU_GPT5_CCMPB (127 << 8) +#define RA_ICU_GPT5_CMPC (128 << 8) +#define RA_ICU_GPT5_CMPD (129 << 8) +#define RA_ICU_GPT5_CMPE (130 << 8) +#define RA_ICU_GPT5_CMPF (131 << 8) +#define RA_ICU_GPT5_OVF (132 << 8) +#define RA_ICU_GPT5_UDF (133 << 8) +#define RA_ICU_GPT6_CCMPA (134 << 8) +#define RA_ICU_GPT6_CCMPB (135 << 8) +#define RA_ICU_GPT6_CMPC (136 << 8) +#define RA_ICU_GPT6_CMPD (137 << 8) +#define RA_ICU_GPT6_CMPE (138 << 8) +#define RA_ICU_GPT6_CMPF (139 << 8) +#define RA_ICU_GPT6_OVF (140 << 8) +#define RA_ICU_GPT6_UDF (141 << 8) +#define RA_ICU_GPT7_CCMPA (142 << 8) +#define RA_ICU_GPT7_CCMPB (143 << 8) +#define RA_ICU_GPT7_CMPC (144 << 8) +#define RA_ICU_GPT7_CMPD (145 << 8) +#define RA_ICU_GPT7_CMPE (146 << 8) +#define RA_ICU_GPT7_CMPF (147 << 8) +#define RA_ICU_GPT7_OVF (148 << 8) +#define RA_ICU_GPT7_UDF (149 << 8) +#define RA_ICU_GPT_UVWEDGE (150 << 8) +#define RA_ICU_SCI0_RXI (151 << 8) +#define RA_ICU_SCI0_TXI (152 << 8) +#define RA_ICU_SCI0_TEI (153 << 8) +#define RA_ICU_SCI0_ERI (154 << 8) +#define RA_ICU_SCI0_AM (155 << 8) +#define RA_ICU_SCI0_RXI_OR_ERI (156 << 8) +#define RA_ICU_SCI1_RXI (157 << 8) +#define RA_ICU_SCI1_TXI (158 << 8) +#define RA_ICU_SCI1_TEI (159 << 8) +#define RA_ICU_SCI1_ERI (160 << 8) +#define RA_ICU_SCI1_AM (161 << 8) +#define RA_ICU_SCI2_RXI (162 << 8) +#define RA_ICU_SCI2_TXI (163 << 8) +#define RA_ICU_SCI2_TEI (164 << 8) +#define RA_ICU_SCI2_ERI (165 << 8) +#define RA_ICU_SCI2_AM (166 << 8) +#define RA_ICU_SCI9_RXI (167 << 8) +#define RA_ICU_SCI9_TXI (168 << 8) +#define RA_ICU_SCI9_TEI (169 << 8) +#define RA_ICU_SCI9_ERI (170 << 8) +#define RA_ICU_SCI9_AM (171 << 8) +#define RA_ICU_SPI0_SPRI (172 << 8) +#define RA_ICU_SPI0_SPTI (173 << 8) +#define RA_ICU_SPI0_SPII (174 << 8) +#define RA_ICU_SPI0_SPEI (175 << 8) +#define RA_ICU_SPI0_SPTEND (176 << 8) +#define RA_ICU_SPI1_SPRI (177 << 8) +#define RA_ICU_SPI1_SPTI (178 << 8) +#define RA_ICU_SPI1_SPII (179 << 8) +#define RA_ICU_SPI1_SPEI (180 << 8) +#define RA_ICU_SPI1_SPTEND (181 << 8) + +#endif /* ZEPHYR_DT_BINDINGS_INTERRUPT_CONTROLLER_RENESAS_RA_ICU_H_ */ diff --git a/include/zephyr/dt-bindings/memory-attr/memory-attr-arm.h b/include/zephyr/dt-bindings/memory-attr/memory-attr-arm.h new file mode 100644 index 00000000000..a0e8736712e --- /dev/null +++ b/include/zephyr/dt-bindings/memory-attr/memory-attr-arm.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_MEM_ATTR_ARM_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_MEM_ATTR_ARM_H_ + +#include +#include + +/* + * Architecture specific ARM MPU related attributes. + * + * This list is to seamlessy support the MPU regions configuration using DT and + * the `zephyr,memory-attr` property. + * + * This is legacy and it should NOT be extended further. If new MPU region + * types must be added, these must rely on the generic memory attributes. + */ +#define DT_MEM_ARM_MASK DT_MEM_ARCH_ATTR_MASK +#define DT_MEM_ARM_GET(x) ((x) & DT_MEM_ARM_MASK) +#define DT_MEM_ARM(x) ((x) << DT_MEM_ARCH_ATTR_SHIFT) + +#define ATTR_MPU_RAM BIT(0) +#define ATTR_MPU_RAM_NOCACHE BIT(1) +#define ATTR_MPU_FLASH BIT(2) +#define ATTR_MPU_PPB BIT(3) +#define ATTR_MPU_IO BIT(4) +#define ATTR_MPU_EXTMEM BIT(5) + +#define DT_MEM_ARM_MPU_RAM DT_MEM_ARM(ATTR_MPU_RAM) +#define DT_MEM_ARM_MPU_RAM_NOCACHE DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) +#define DT_MEM_ARM_MPU_FLASH DT_MEM_ARM(ATTR_MPU_FLASH) +#define DT_MEM_ARM_MPU_PPB DT_MEM_ARM(ATTR_MPU_PPB) +#define DT_MEM_ARM_MPU_IO DT_MEM_ARM(ATTR_MPU_IO) +#define DT_MEM_ARM_MPU_EXTMEM DT_MEM_ARM(ATTR_MPU_EXTMEM) +#define DT_MEM_ARM_MPU_UNKNOWN DT_MEM_ARCH_ATTR_UNKNOWN + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_MEM_ATTR_ARM_H_ */ diff --git a/include/zephyr/dt-bindings/memory-attr/memory-attr-riscv.h b/include/zephyr/dt-bindings/memory-attr/memory-attr-riscv.h new file mode 100644 index 00000000000..5aebb111a56 --- /dev/null +++ b/include/zephyr/dt-bindings/memory-attr/memory-attr-riscv.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_MEM_ATTR_RISCV_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_MEM_ATTR_RISCV_H_ + +#include +#include + +/* + * Architecture specific RISCV related attributes. + */ +#define DT_MEM_RISCV_MASK DT_MEM_ARCH_ATTR_MASK +#define DT_MEM_RISCV_GET(x) ((x) & DT_MEM_RISCV_MASK) +#define DT_MEM_RISCV(x) ((x) << DT_MEM_ARCH_ATTR_SHIFT) + +#define ATTR_RISCV_TYPE_MAIN BIT(0) +#define ATTR_RISCV_TYPE_IO BIT(1) +#define ATTR_RISCV_TYPE_EMPTY BIT(2) +#define ATTR_RISCV_AMO_SWAP BIT(3) +#define ATTR_RISCV_AMO_LOGICAL BIT(4) +#define ATTR_RISCV_AMO_ARITHMETIC BIT(5) +#define ATTR_RISCV_IO_IDEMPOTENT_READ BIT(6) +#define ATTR_RISCV_IO_IDEMPOTENT_WRITE BIT(7) + +#define DT_MEM_RISCV_TYPE_MAIN DT_MEM_RISCV(ATTR_RISCV_TYPE_MAIN) +#define DT_MEM_RISCV_TYPE_IO DT_MEM_RISCV(ATTR_RISCV_TYPE_IO) +#define DT_MEM_RISCV_TYPE_EMPTY DT_MEM_RISCV(ATTR_RISCV_TYPE_EMPTY) +#define DT_MEM_RISCV_AMO_SWAP DT_MEM_RISCV(ATTR_RISCV_AMO_SWAP) +#define DT_MEM_RISCV_AMO_LOGICAL DT_MEM_RISCV(ATTR_RISCV_AMO_LOGICAL) +#define DT_MEM_RISCV_AMO_ARITHMETIC DT_MEM_RISCV(ATTR_RISCV_AMO_ARITHMETIC) +#define DT_MEM_RISCV_IO_IDEMPOTENT_READ DT_MEM_RISCV(ATTR_RISCV_IO_IDEMPOTENT_READ) +#define DT_MEM_RISCV_IO_IDEMPOTENT_WRITE DT_MEM_RISCV(ATTR_RISCV_IO_IDEMPOTENT_WRITE) +#define DT_MEM_RISCV_UNKNOWN DT_MEM_ARCH_ATTR_UNKNOWN + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_MEM_ATTR_RISCV_H_ */ diff --git a/include/zephyr/dt-bindings/memory-attr/memory-attr-xtensa.h b/include/zephyr/dt-bindings/memory-attr/memory-attr-xtensa.h new file mode 100644 index 00000000000..ba48e0c21e8 --- /dev/null +++ b/include/zephyr/dt-bindings/memory-attr/memory-attr-xtensa.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_MEM_ATTR_XTENSA_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_MEM_ATTR_XTENSA_H_ + +#include +#include + +/* + * Architecture specific Xtensa related attributes. + */ +#define DT_MEM_XTENSA_MASK DT_MEM_ARCH_ATTR_MASK +#define DT_MEM_XTENSA_GET(x) ((x) & DT_MEM_XTENSA_MASK) +#define DT_MEM_XTENSA(x) ((x) << DT_MEM_ARCH_ATTR_SHIFT) + +#define ATTR_XTENSA_INSTR_ROM BIT(0) +#define ATTR_XTENSA_INSTR_RAM BIT(1) +#define ATTR_XTENSA_DATA_ROM BIT(2) +#define ATTR_XTENSA_DATA_RAM BIT(3) +#define ATTR_XTENSA_XLMI BIT(4) + +#define DT_MEM_XTENSA_INSTR_ROM DT_MEM_XTENSA(ATTR_XTENSA_INSTR_ROM) +#define DT_MEM_XTENSA_INSTR_RAM DT_MEM_XTENSA(ATTR_XTENSA_INSTR_RAM) +#define DT_MEM_XTENSA_DATA_ROM DT_MEM_XTENSA(ATTR_XTENSA_DATA_ROM) +#define DT_MEM_XTENSA_DATA_RAM DT_MEM_XTENSA(ATTR_XTENSA_DATA_RAM) +#define DT_MEM_XTENSA_XLMI DT_MEM_XTENSA(ATTR_XTENSA_XLMI) +#define DT_MEM_XTENSA_UNKNOWN DT_MEM_ARCH_ATTR_UNKNOWN + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_MEM_ATTR_XTENSA_H_ */ diff --git a/include/zephyr/dt-bindings/memory-attr/memory-attr.h b/include/zephyr/dt-bindings/memory-attr/memory-attr.h new file mode 100644 index 00000000000..9023a2b56a6 --- /dev/null +++ b/include/zephyr/dt-bindings/memory-attr/memory-attr.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_MEM_ATTR_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_MEM_ATTR_H_ + +#include + +/* + * Generic memory attributes. + * + * Generic memory attributes that should be common to all architectures. + */ +#define DT_MEM_ATTR_MASK GENMASK(15, 0) +#define DT_MEM_ATTR_GET(x) ((x) & DT_MEM_ATTR_MASK) +#define DT_MEM_ATTR_SHIFT (0) + +#define DT_MEM_CACHEABLE BIT(0) /* cacheable */ +#define DT_MEM_NON_VOLATILE BIT(1) /* non-volatile */ +#define DT_MEM_OOO BIT(2) /* out-of-order */ +#define DT_MEM_DMA BIT(3) /* DMA-able */ +#define DT_MEM_UNKNOWN BIT(15) /* must be last */ +/* to be continued */ + +/* + * Software specific memory attributes. + * + * Software can define their own memory attributes if needed using the + * provided mask. + */ +#define DT_MEM_SW_ATTR_MASK GENMASK(19, 16) +#define DT_MEM_SW_ATTR_GET(x) ((x) & DT_MEM_SW_ATTR_MASK) +#define DT_MEM_SW_ATTR_SHIFT (16) +#define DT_MEM_SW_ATTR_UNKNOWN BIT(19) + +/* + * Architecture specific memory attributes. + * + * Architectures can define their own memory attributes if needed using the + * provided mask. + * + * See for example `include/zephyr/dt-bindings/memory-attr/memory-attr-arm.h` + */ +#define DT_MEM_ARCH_ATTR_MASK GENMASK(31, 20) +#define DT_MEM_ARCH_ATTR_GET(x) ((x) & DT_MEM_ARCH_ATTR_MASK) +#define DT_MEM_ARCH_ATTR_SHIFT (20) +#define DT_MEM_ARCH_ATTR_UNKNOWN BIT(31) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_MEM_ATTR_H_ */ diff --git a/include/zephyr/dt-bindings/memory-controller/nxp,flexram.h b/include/zephyr/dt-bindings/memory-controller/nxp,flexram.h new file mode 100644 index 00000000000..2c35e655fc9 --- /dev/null +++ b/include/zephyr/dt-bindings/memory-controller/nxp,flexram.h @@ -0,0 +1,15 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_MEMORY_CONTROLLER_NXP_FLEXRAM_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_MEMORY_CONTROLLER_NXP_FLEXRAM_H_ + +#define FLEXRAM_NONE 0 +#define FLEXRAM_OCRAM 1 +#define FLEXRAM_DTCM 2 +#define FLEXRAM_ITCM 3 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_MEMORY_CONTROLLER_NXP_FLEXRAM_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/imx8qm-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/imx8qm-pinctrl.h new file mode 100644 index 00000000000..9748a2ce4aa --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/imx8qm-pinctrl.h @@ -0,0 +1,18 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_IMX8QM_PINCTRL_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_IMX8QM_PINCTRL_H_ + +/* values for pad field */ +#define SC_P_UART0_RTS_B 23 +#define SC_P_UART0_CTS_B 24 + +/* mux values */ +#define IMX8QM_DMA_LPUART2_RX_UART0_RTS_B 2 /* UART0_RTS_B ---> DMA_LPUART2_RX */ +#define IMX8QM_DMA_LPUART2_TX_UART0_CTS_B 2 /* DMA_LPUART2_TX ---> UART0_CTS_B */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_IMX8QM_PINCTRL_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/imx8qxp-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/imx8qxp-pinctrl.h new file mode 100644 index 00000000000..0143540f6bf --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/imx8qxp-pinctrl.h @@ -0,0 +1,18 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_IMX8QXP_PINCTRL_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_IMX8QXP_PINCTRL_H_ + +/* values for pad field */ +#define SC_P_UART2_TX 113 +#define SC_P_UART2_RX 114 + +/* mux values */ +#define IMX8QXP_DMA_LPUART2_RX_UART2_RX 0 /* UART2_RX ---> DMA_LPUART2_RX */ +#define IMX8QXP_DMA_LPUART2_TX_UART2_TX 0 /* DMA_LPUART2_TX ---> UART2_TX */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_IMX8QXP_PINCTRL_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/renesas-rzt2m-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/renesas-rzt2m-pinctrl.h new file mode 100644 index 00000000000..ed1cbf7ee96 --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/renesas-rzt2m-pinctrl.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __RENESAS_RZT2M_PINCTRL_H__ +#define __RENESAS_RZT2M_PINCTRL_H__ + +#define RZT2M_PINMUX(port, pin, func) ((port << 16) | (pin << 8) | func) + +#define UART0TX_P16_5 RZT2M_PINMUX(16, 5, 1) +#define UART0RX_P16_6 RZT2M_PINMUX(16, 6, 2) + +#define UART3TX_P18_0 RZT2M_PINMUX(18, 0, 4) +#define UART3RX_P17_7 RZT2M_PINMUX(17, 7, 4) + +#endif /* __RENESAS_RZT2M_PINCTRL_H__ */ diff --git a/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-r7fa4m1xxxxxx.h b/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-r7fa4m1xxxxxx.h new file mode 100644 index 00000000000..dfe21b00183 --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-r7fa4m1xxxxxx.h @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DT_BINDINGS_PINCTRL_RENESAS_PINCTRL_R7FA4M1XXXXXX_H_ +#define ZEPHYR_DT_BINDINGS_PINCTRL_RENESAS_PINCTRL_R7FA4M1XXXXXX_H_ + +#include + +#define P000_AMP0P RA_PINCFG__40(0, 0, 0x02, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P000_AN000 RA_PINCFG__40(0, 0, 0x01, RA_PINCFG_ANALOG) +#define P000_TS21 RA_PINCFG__40(0, 0, 0x0C, RA_PINCFG_FUNC) +#define P001_AMP0M RA_PINCFG__40(0, 1, 0x02, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P001_AN001 RA_PINCFG__40(0, 1, 0x01, RA_PINCFG_ANALOG) +#define P001_TS22 RA_PINCFG__40(0, 1, 0x0C, RA_PINCFG_FUNC) +#define P002_AMP0O RA_PINCFG__48(0, 2, 0x02, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P002_AN002 RA_PINCFG__48(0, 2, 0x01, RA_PINCFG_ANALOG) +#define P003_AMP1O RA_PINCFG__64(0, 3, 0x02, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P003_AN003 RA_PINCFG__64(0, 3, 0x01, RA_PINCFG_ANALOG) +#define P004_AMP2O RA_PINCFG__64(0, 4, 0x02, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P004_AN004 RA_PINCFG__64(0, 4, 0x01, RA_PINCFG_ANALOG) +#define P005_AMP3P RA_PINCFG_100(0, 5, 0x02, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P005_AN011 RA_PINCFG_100(0, 5, 0x01, RA_PINCFG_ANALOG) +#define P006_AMP3M RA_PINCFG_100(0, 6, 0x02, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P006_AN012 RA_PINCFG_100(0, 6, 0x01, RA_PINCFG_ANALOG) +#define P007_AMP3O RA_PINCFG_100(0, 7, 0x02, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P007_AN013 RA_PINCFG_100(0, 7, 0x01, RA_PINCFG_ANALOG) +#define P008_AN014 RA_PINCFG_100(0, 8, 0x01, RA_PINCFG_ANALOG) +#define P010_AMP2M RA_PINCFG__40(0, 0, 0x02, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P010_AN005 RA_PINCFG__40(0, 0, 0x01, RA_PINCFG_ANALOG) +#define P010_TS30 RA_PINCFG__40(0, 0, 0x0C, RA_PINCFG_FUNC) +#define P010_VREFH0 RA_PINCFG__40(0, 0, 0x03, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P011_AN006 RA_PINCFG__40(0, 1, 0x01, RA_PINCFG_ANALOG) +#define P011_TS31 RA_PINCFG__40(0, 1, 0x0C, RA_PINCFG_FUNC) +#define P011_VREFL0 RA_PINCFG__40(0, 1, 0x03, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P012_AN007 RA_PINCFG__40(0, 2, 0x01, RA_PINCFG_ANALOG) +#define P012_VREFH RA_PINCFG__40(0, 2, 0x03, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P013_AN008 RA_PINCFG__40(0, 3, 0x01, RA_PINCFG_ANALOG) +#define P013_VREFL RA_PINCFG__40(0, 3, 0x03, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P014_AN009 RA_PINCFG__40(0, 4, 0x01, RA_PINCFG_ANALOG) +#define P014_DA0 RA_PINCFG__40(0, 4, 0x02, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P015_AN010 RA_PINCFG__40(0, 5, 0x01, RA_PINCFG_ANALOG) +#define P015_TS28 RA_PINCFG__40(0, 5, 0x0C, RA_PINCFG_FUNC) +#define P100_AGTIO0 RA_PINCFG__40(1, 0, 0x01, RA_PINCFG_FUNC) +#define P100_AN022 RA_PINCFG__40(1, 0, 0x01, RA_PINCFG_ANALOG) +#define P100_CMPIN0 RA_PINCFG__40(1, 0, 0x02, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P100_GTETRGA RA_PINCFG__40(1, 0, 0x02, RA_PINCFG_FUNC) +#define P100_GTIOC5B RA_PINCFG__40(1, 0, 0x03, RA_PINCFG_FUNC) +#define P100_KR00 RA_PINCFG__40(1, 0, 0x08, RA_PINCFG_FUNC) +#define P100_MISO0 RA_PINCFG__40(1, 0, 0x04, RA_PINCFG_FUNC) +#define P100_MISOA RA_PINCFG__40(1, 0, 0x06, RA_PINCFG_FUNC) +#define P100_RXD0 RA_PINCFG__40(1, 0, 0x04, RA_PINCFG_FUNC) +#define P100_SCK1 RA_PINCFG__40(1, 0, 0x05, RA_PINCFG_FUNC) +#define P100_SCL0 RA_PINCFG__40(1, 0, 0x04, RA_PINCFG_FUNC) +#define P100_SCL1 RA_PINCFG__40(1, 0, 0x07, RA_PINCFG_FUNC) +#define P100_VL1 RA_PINCFG__40(1, 0, 0x0D, RA_PINCFG_FUNC) +#define P101_AGTEE0 RA_PINCFG__40(1, 1, 0x01, RA_PINCFG_FUNC) +#define P101_AN021 RA_PINCFG__40(1, 1, 0x01, RA_PINCFG_ANALOG) +#define P101_CMPREF0 RA_PINCFG__40(1, 1, 0x02, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P101_CTS1_RTS1 RA_PINCFG__40(1, 1, 0x05, RA_PINCFG_FUNC) +#define P101_GTETRGB RA_PINCFG__40(1, 1, 0x02, RA_PINCFG_FUNC) +#define P101_GTIOC5A RA_PINCFG__40(1, 1, 0x03, RA_PINCFG_FUNC) +#define P101_KR01 RA_PINCFG__40(1, 1, 0x08, RA_PINCFG_FUNC) +#define P101_MOSI0 RA_PINCFG__40(1, 1, 0x04, RA_PINCFG_FUNC) +#define P101_MOSIA RA_PINCFG__40(1, 1, 0x06, RA_PINCFG_FUNC) +#define P101_SDA0 RA_PINCFG__40(1, 1, 0x04, RA_PINCFG_FUNC) +#define P101_SDA1 RA_PINCFG__40(1, 1, 0x07, RA_PINCFG_FUNC) +#define P101_SS1 RA_PINCFG__40(1, 1, 0x05, RA_PINCFG_FUNC) +#define P101_TXD0 RA_PINCFG__40(1, 1, 0x04, RA_PINCFG_FUNC) +#define P101_VL2 RA_PINCFG__40(1, 1, 0x0D, RA_PINCFG_FUNC) +#define P102_ADTRG0 RA_PINCFG__40(1, 2, 0x0A, RA_PINCFG_FUNC) +#define P102_AGTO0 RA_PINCFG__40(1, 2, 0x01, RA_PINCFG_FUNC) +#define P102_AN020 RA_PINCFG__40(1, 2, 0x01, RA_PINCFG_ANALOG) +#define P102_CMPIN1 RA_PINCFG__40(1, 2, 0x02, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P102_CRX0 RA_PINCFG__40(1, 2, 0x10, RA_PINCFG_FUNC) +#define P102_GTIOC2B RA_PINCFG__40(1, 2, 0x03, RA_PINCFG_FUNC) +#define P102_GTOWLO RA_PINCFG__40(1, 2, 0x02, RA_PINCFG_FUNC) +#define P102_KR02 RA_PINCFG__40(1, 2, 0x08, RA_PINCFG_FUNC) +#define P102_MOSI2 RA_PINCFG__40(1, 2, 0x05, RA_PINCFG_FUNC) +#define P102_RSPCKA RA_PINCFG__40(1, 2, 0x06, RA_PINCFG_FUNC) +#define P102_SCK0 RA_PINCFG__40(1, 2, 0x04, RA_PINCFG_FUNC) +#define P102_SDA2 RA_PINCFG__40(1, 2, 0x05, RA_PINCFG_FUNC) +#define P102_TXD2 RA_PINCFG__40(1, 2, 0x05, RA_PINCFG_FUNC) +#define P102_VL3 RA_PINCFG__40(1, 2, 0x0D, RA_PINCFG_FUNC) +#define P103_AN019 RA_PINCFG__48(1, 3, 0x01, RA_PINCFG_ANALOG) +#define P103_CMPREF1 RA_PINCFG__48(1, 3, 0x02, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P103_CTS0_RTS0 RA_PINCFG__48(1, 3, 0x04, RA_PINCFG_FUNC) +#define P103_CTX0 RA_PINCFG__48(1, 3, 0x10, RA_PINCFG_FUNC) +#define P103_GTIOC2A RA_PINCFG__48(1, 3, 0x03, RA_PINCFG_FUNC) +#define P103_GTOWUP RA_PINCFG__48(1, 3, 0x02, RA_PINCFG_FUNC) +#define P103_KR03 RA_PINCFG__48(1, 3, 0x08, RA_PINCFG_FUNC) +#define P103_SS0 RA_PINCFG__48(1, 3, 0x04, RA_PINCFG_FUNC) +#define P103_SSLA0 RA_PINCFG__48(1, 3, 0x06, RA_PINCFG_FUNC) +#define P103_VL4 RA_PINCFG__48(1, 3, 0x0D, RA_PINCFG_FUNC) +#define P104_COM0 RA_PINCFG__48(1, 4, 0x0D, RA_PINCFG_FUNC) +#define P104_GTETRGB RA_PINCFG__48(1, 4, 0x02, RA_PINCFG_FUNC) +#define P104_GTIOC1B RA_PINCFG__48(1, 4, 0x03, RA_PINCFG_FUNC) +#define P104_KR04 RA_PINCFG__48(1, 4, 0x08, RA_PINCFG_FUNC) +#define P104_MISO0 RA_PINCFG__48(1, 4, 0x04, RA_PINCFG_FUNC) +#define P104_RXD0 RA_PINCFG__48(1, 4, 0x04, RA_PINCFG_FUNC) +#define P104_SCL0 RA_PINCFG__48(1, 4, 0x04, RA_PINCFG_FUNC) +#define P104_SSLA1 RA_PINCFG__48(1, 4, 0x06, RA_PINCFG_FUNC) +#define P104_TS13 RA_PINCFG__48(1, 4, 0x0C, RA_PINCFG_FUNC) +#define P105_COM1 RA_PINCFG__64(1, 5, 0x0D, RA_PINCFG_FUNC) +#define P105_GTETRGA RA_PINCFG__64(1, 5, 0x02, RA_PINCFG_FUNC) +#define P105_GTIOC1A RA_PINCFG__64(1, 5, 0x03, RA_PINCFG_FUNC) +#define P105_KR05 RA_PINCFG__64(1, 5, 0x08, RA_PINCFG_FUNC) +#define P105_SSLA2 RA_PINCFG__64(1, 5, 0x06, RA_PINCFG_FUNC) +#define P105_TS34 RA_PINCFG__64(1, 5, 0x0C, RA_PINCFG_FUNC) +#define P106_COM2 RA_PINCFG__64(1, 6, 0x0D, RA_PINCFG_FUNC) +#define P106_GTIOC0B RA_PINCFG__64(1, 6, 0x03, RA_PINCFG_FUNC) +#define P106_KR06 RA_PINCFG__64(1, 6, 0x08, RA_PINCFG_FUNC) +#define P106_SSLA3 RA_PINCFG__64(1, 6, 0x06, RA_PINCFG_FUNC) +#define P107_COM3 RA_PINCFG__64(1, 7, 0x0D, RA_PINCFG_FUNC) +#define P107_GTIOC0A RA_PINCFG__64(1, 7, 0x03, RA_PINCFG_FUNC) +#define P107_KR07 RA_PINCFG__64(1, 7, 0x08, RA_PINCFG_FUNC) +#define P108_CTS9_RTS9 RA_PINCFG__40(1, 8, 0x05, RA_PINCFG_FUNC) +#define P108_GTIOC0B RA_PINCFG__40(1, 8, 0x03, RA_PINCFG_FUNC) +#define P108_GTOULO RA_PINCFG__40(1, 8, 0x02, RA_PINCFG_FUNC) +#define P108_SS9 RA_PINCFG__40(1, 8, 0x05, RA_PINCFG_FUNC) +#define P108_SSLB0 RA_PINCFG__40(1, 8, 0x06, RA_PINCFG_FUNC) +#define P109_CLKOUT RA_PINCFG__40(1, 9, 0x09, RA_PINCFG_FUNC) +#define P109_CTX0 RA_PINCFG__40(1, 9, 0x10, RA_PINCFG_FUNC) +#define P109_GTIOC1A RA_PINCFG__40(1, 9, 0x03, RA_PINCFG_FUNC) +#define P109_GTOVUP RA_PINCFG__40(1, 9, 0x02, RA_PINCFG_FUNC) +#define P109_MOSI9 RA_PINCFG__40(1, 9, 0x05, RA_PINCFG_FUNC) +#define P109_MOSIB RA_PINCFG__40(1, 9, 0x06, RA_PINCFG_FUNC) +#define P109_SCK1 RA_PINCFG__40(1, 9, 0x04, RA_PINCFG_FUNC) +#define P109_SDA9 RA_PINCFG__40(1, 9, 0x05, RA_PINCFG_FUNC) +#define P109_SEG23 RA_PINCFG__40(1, 9, 0x0D, RA_PINCFG_FUNC) +#define P109_TS10 RA_PINCFG__40(1, 9, 0x0C, RA_PINCFG_FUNC) +#define P109_TXD9 RA_PINCFG__40(1, 9, 0x05, RA_PINCFG_FUNC) +#define P110_CRX0 RA_PINCFG__40(1, 0, 0x10, RA_PINCFG_FUNC) +#define P110_CTS2_RTS2 RA_PINCFG__40(1, 0, 0x04, RA_PINCFG_FUNC) +#define P110_GTIOC1B RA_PINCFG__40(1, 0, 0x03, RA_PINCFG_FUNC) +#define P110_GTOVLO RA_PINCFG__40(1, 0, 0x02, RA_PINCFG_FUNC) +#define P110_MISO9 RA_PINCFG__40(1, 0, 0x05, RA_PINCFG_FUNC) +#define P110_MISOB RA_PINCFG__40(1, 0, 0x06, RA_PINCFG_FUNC) +#define P110_RXD9 RA_PINCFG__40(1, 0, 0x05, RA_PINCFG_FUNC) +#define P110_SCL9 RA_PINCFG__40(1, 0, 0x05, RA_PINCFG_FUNC) +#define P110_SEG24 RA_PINCFG__40(1, 0, 0x0D, RA_PINCFG_FUNC) +#define P110_SS2 RA_PINCFG__40(1, 0, 0x04, RA_PINCFG_FUNC) +#define P110_VCOUT RA_PINCFG__40(1, 0, 0x09, RA_PINCFG_FUNC) +#define P111_CAPH RA_PINCFG__40(1, 1, 0x0D, RA_PINCFG_FUNC) +#define P111_GTIOC3A RA_PINCFG__40(1, 1, 0x03, RA_PINCFG_FUNC) +#define P111_RSPCKB RA_PINCFG__40(1, 1, 0x06, RA_PINCFG_FUNC) +#define P111_SCK2 RA_PINCFG__40(1, 1, 0x04, RA_PINCFG_FUNC) +#define P111_SCK9 RA_PINCFG__40(1, 1, 0x05, RA_PINCFG_FUNC) +#define P111_TS12 RA_PINCFG__40(1, 1, 0x0C, RA_PINCFG_FUNC) +#define P112_CAPL RA_PINCFG__40(1, 2, 0x0D, RA_PINCFG_FUNC) +#define P112_GTIOC3B RA_PINCFG__40(1, 2, 0x03, RA_PINCFG_FUNC) +#define P112_MOSI2 RA_PINCFG__40(1, 2, 0x04, RA_PINCFG_FUNC) +#define P112_SCK1 RA_PINCFG__40(1, 2, 0x05, RA_PINCFG_FUNC) +#define P112_SDA2 RA_PINCFG__40(1, 2, 0x04, RA_PINCFG_FUNC) +#define P112_SSIBCK0 RA_PINCFG__40(1, 2, 0x12, RA_PINCFG_FUNC) +#define P112_SSLB0 RA_PINCFG__40(1, 2, 0x06, RA_PINCFG_FUNC) +#define P112_TSCAP RA_PINCFG__40(1, 2, 0x0C, RA_PINCFG_FUNC) +#define P112_TXD2 RA_PINCFG__40(1, 2, 0x04, RA_PINCFG_FUNC) +#define P113_GTIOC2A RA_PINCFG__64(1, 3, 0x03, RA_PINCFG_FUNC) +#define P113_SEG00COM4 RA_PINCFG__64(1, 3, 0x0D, RA_PINCFG_FUNC) +#define P113_SSIFS0 RA_PINCFG__64(1, 3, 0x12, RA_PINCFG_FUNC) +#define P113_SSILRCK0 RA_PINCFG__64(1, 3, 0x12, RA_PINCFG_FUNC) +#define P113_TS27 RA_PINCFG__64(1, 3, 0x0C, RA_PINCFG_FUNC) +#define P114_GTIOC2B RA_PINCFG_100(1, 4, 0x03, RA_PINCFG_FUNC) +#define P114_SEG25 RA_PINCFG_100(1, 4, 0x0D, RA_PINCFG_FUNC) +#define P114_SSIRXD0 RA_PINCFG_100(1, 4, 0x12, RA_PINCFG_FUNC) +#define P114_TS29 RA_PINCFG_100(1, 4, 0x0C, RA_PINCFG_FUNC) +#define P115_GTIOC4A RA_PINCFG_100(1, 5, 0x03, RA_PINCFG_FUNC) +#define P115_SEG26 RA_PINCFG_100(1, 5, 0x0D, RA_PINCFG_FUNC) +#define P115_SSITXD0 RA_PINCFG_100(1, 5, 0x12, RA_PINCFG_FUNC) +#define P115_TS35 RA_PINCFG_100(1, 5, 0x0C, RA_PINCFG_FUNC) +#define P202_GTIOC5B RA_PINCFG_100(2, 2, 0x03, RA_PINCFG_FUNC) +#define P202_MISO9 RA_PINCFG_100(2, 2, 0x05, RA_PINCFG_FUNC) +#define P202_MISOB RA_PINCFG_100(2, 2, 0x06, RA_PINCFG_FUNC) +#define P202_RXD9 RA_PINCFG_100(2, 2, 0x05, RA_PINCFG_FUNC) +#define P202_SCK2 RA_PINCFG_100(2, 2, 0x04, RA_PINCFG_FUNC) +#define P202_SCL9 RA_PINCFG_100(2, 2, 0x05, RA_PINCFG_FUNC) +#define P202_SEG16 RA_PINCFG_100(2, 2, 0x0D, RA_PINCFG_FUNC) +#define P203_CTS2_RTS2 RA_PINCFG_100(2, 3, 0x04, RA_PINCFG_FUNC) +#define P203_GTIOC5A RA_PINCFG_100(2, 3, 0x03, RA_PINCFG_FUNC) +#define P203_MOSI9 RA_PINCFG_100(2, 3, 0x05, RA_PINCFG_FUNC) +#define P203_MOSIB RA_PINCFG_100(2, 3, 0x06, RA_PINCFG_FUNC) +#define P203_SDA9 RA_PINCFG_100(2, 3, 0x05, RA_PINCFG_FUNC) +#define P203_SEG15 RA_PINCFG_100(2, 3, 0x0D, RA_PINCFG_FUNC) +#define P203_SS2 RA_PINCFG_100(2, 3, 0x04, RA_PINCFG_FUNC) +#define P203_TSCAP RA_PINCFG_100(2, 3, 0x0C, RA_PINCFG_FUNC) +#define P203_TXD9 RA_PINCFG_100(2, 3, 0x05, RA_PINCFG_FUNC) +#define P204_AGTIO1 RA_PINCFG__64(2, 4, 0x01, RA_PINCFG_FUNC) +#define P204_CACREF RA_PINCFG__64(2, 4, 0x0A, RA_PINCFG_FUNC) +#define P204_GTIOC4B RA_PINCFG__64(2, 4, 0x03, RA_PINCFG_FUNC) +#define P204_GTIW RA_PINCFG__64(2, 4, 0x02, RA_PINCFG_FUNC) +#define P204_RSPCKB RA_PINCFG__64(2, 4, 0x06, RA_PINCFG_FUNC) +#define P204_SCK0 RA_PINCFG__64(2, 4, 0x04, RA_PINCFG_FUNC) +#define P204_SCK9 RA_PINCFG__64(2, 4, 0x05, RA_PINCFG_FUNC) +#define P204_SCL0 RA_PINCFG__64(2, 4, 0x07, RA_PINCFG_FUNC) +#define P204_SEG14 RA_PINCFG__64(2, 4, 0x0D, RA_PINCFG_FUNC) +#define P204_TS00 RA_PINCFG__64(2, 4, 0x0C, RA_PINCFG_FUNC) +#define P204_USB_OVRCUR_B RA_PINCFG__64(2, 4, 0x13, RA_PINCFG_FUNC) +#define P205_AGTO1 RA_PINCFG__64(2, 5, 0x01, RA_PINCFG_FUNC) +#define P205_CLKOUT RA_PINCFG__64(2, 5, 0x09, RA_PINCFG_FUNC) +#define P205_CTS9_RTS9 RA_PINCFG__64(2, 5, 0x05, RA_PINCFG_FUNC) +#define P205_GTIOC4A RA_PINCFG__64(2, 5, 0x03, RA_PINCFG_FUNC) +#define P205_GTIV RA_PINCFG__64(2, 5, 0x02, RA_PINCFG_FUNC) +#define P205_MOSI0 RA_PINCFG__64(2, 5, 0x04, RA_PINCFG_FUNC) +#define P205_SCL1 RA_PINCFG__64(2, 5, 0x07, RA_PINCFG_FUNC) +#define P205_SDA0 RA_PINCFG__64(2, 5, 0x04, RA_PINCFG_FUNC) +#define P205_SEG13 RA_PINCFG__64(2, 5, 0x0D, RA_PINCFG_FUNC) +#define P205_SS9 RA_PINCFG__64(2, 5, 0x05, RA_PINCFG_FUNC) +#define P205_SSLB0 RA_PINCFG__64(2, 5, 0x06, RA_PINCFG_FUNC) +#define P205_TSCAP RA_PINCFG__64(2, 5, 0x0C, RA_PINCFG_FUNC) +#define P205_TXD0 RA_PINCFG__64(2, 5, 0x04, RA_PINCFG_FUNC) +#define P205_USB_OVRCUR_A RA_PINCFG__64(2, 5, 0x13, RA_PINCFG_FUNC) +#define P206_GTIU RA_PINCFG__48(2, 6, 0x02, RA_PINCFG_FUNC) +#define P206_MISO0 RA_PINCFG__48(2, 6, 0x04, RA_PINCFG_FUNC) +#define P206_RXD0 RA_PINCFG__48(2, 6, 0x04, RA_PINCFG_FUNC) +#define P206_SCL0 RA_PINCFG__48(2, 6, 0x04, RA_PINCFG_FUNC) +#define P206_SDA1 RA_PINCFG__48(2, 6, 0x07, RA_PINCFG_FUNC) +#define P206_SEG12 RA_PINCFG__48(2, 6, 0x0D, RA_PINCFG_FUNC) +#define P206_SSLB1 RA_PINCFG__48(2, 6, 0x06, RA_PINCFG_FUNC) +#define P206_TS01 RA_PINCFG__48(2, 6, 0x0C, RA_PINCFG_FUNC) +#define P206_USB_VBUSEN RA_PINCFG__48(2, 6, 0x13, RA_PINCFG_FUNC) +#define P212_AGTEE1 RA_PINCFG__40(2, 2, 0x01, RA_PINCFG_FUNC) +#define P212_GTETRGB RA_PINCFG__40(2, 2, 0x02, RA_PINCFG_FUNC) +#define P212_GTIOC0B RA_PINCFG__40(2, 2, 0x03, RA_PINCFG_FUNC) +#define P212_MISO1 RA_PINCFG__40(2, 2, 0x05, RA_PINCFG_FUNC) +#define P212_RXD1 RA_PINCFG__40(2, 2, 0x05, RA_PINCFG_FUNC) +#define P212_SCL1 RA_PINCFG__40(2, 2, 0x05, RA_PINCFG_FUNC) +#define P213_GTETRGA RA_PINCFG__40(2, 3, 0x02, RA_PINCFG_FUNC) +#define P213_GTIOC0A RA_PINCFG__40(2, 3, 0x03, RA_PINCFG_FUNC) +#define P213_MOSI1 RA_PINCFG__40(2, 3, 0x05, RA_PINCFG_FUNC) +#define P213_SDA1 RA_PINCFG__40(2, 3, 0x05, RA_PINCFG_FUNC) +#define P213_TXD1 RA_PINCFG__40(2, 3, 0x05, RA_PINCFG_FUNC) +#define P300_GTIOC0A RA_PINCFG__40(3, 0, 0x03, RA_PINCFG_FUNC) +#define P300_GTOUUP RA_PINCFG__40(3, 0, 0x02, RA_PINCFG_FUNC) +#define P300_SSLB1 RA_PINCFG__40(3, 0, 0x06, RA_PINCFG_FUNC) +#define P301_AGTIO0 RA_PINCFG__40(3, 1, 0x01, RA_PINCFG_FUNC) +#define P301_COM5 RA_PINCFG__40(3, 1, 0x10, RA_PINCFG_FUNC) +#define P301_CTS9_RTS9 RA_PINCFG__40(3, 1, 0x05, RA_PINCFG_FUNC) +#define P301_GTIOC4B RA_PINCFG__40(3, 1, 0x03, RA_PINCFG_FUNC) +#define P301_GTOULO RA_PINCFG__40(3, 1, 0x02, RA_PINCFG_FUNC) +#define P301_MISO2 RA_PINCFG__40(3, 1, 0x04, RA_PINCFG_FUNC) +#define P301_RXD2 RA_PINCFG__40(3, 1, 0x04, RA_PINCFG_FUNC) +#define P301_SCL2 RA_PINCFG__40(3, 1, 0x04, RA_PINCFG_FUNC) +#define P301_SEG01 RA_PINCFG__40(3, 1, 0x0D, RA_PINCFG_FUNC) +#define P301_SS9 RA_PINCFG__40(3, 1, 0x05, RA_PINCFG_FUNC) +#define P301_SSLB2 RA_PINCFG__40(3, 1, 0x06, RA_PINCFG_FUNC) +#define P301_TS09 RA_PINCFG__40(3, 1, 0x0C, RA_PINCFG_FUNC) +#define P302_COM6 RA_PINCFG__48(3, 2, 0x10, RA_PINCFG_FUNC) +#define P302_GTIOC4A RA_PINCFG__48(3, 2, 0x03, RA_PINCFG_FUNC) +#define P302_GTOUUP RA_PINCFG__48(3, 2, 0x02, RA_PINCFG_FUNC) +#define P302_MOSI2 RA_PINCFG__48(3, 2, 0x04, RA_PINCFG_FUNC) +#define P302_SDA2 RA_PINCFG__48(3, 2, 0x04, RA_PINCFG_FUNC) +#define P302_SEG02 RA_PINCFG__48(3, 2, 0x0D, RA_PINCFG_FUNC) +#define P302_SSLB3 RA_PINCFG__48(3, 2, 0x06, RA_PINCFG_FUNC) +#define P302_TS08 RA_PINCFG__48(3, 2, 0x0C, RA_PINCFG_FUNC) +#define P302_TXD2 RA_PINCFG__48(3, 2, 0x04, RA_PINCFG_FUNC) +#define P303_COM7 RA_PINCFG__64(3, 3, 0x10, RA_PINCFG_FUNC) +#define P303_GTIOC7B RA_PINCFG__64(3, 3, 0x03, RA_PINCFG_FUNC) +#define P303_SEG03 RA_PINCFG__64(3, 3, 0x0D, RA_PINCFG_FUNC) +#define P303_TS02 RA_PINCFG__64(3, 3, 0x0C, RA_PINCFG_FUNC) +#define P304_GTIOC7A RA_PINCFG__64(3, 4, 0x03, RA_PINCFG_FUNC) +#define P304_SEG20 RA_PINCFG__64(3, 4, 0x0D, RA_PINCFG_FUNC) +#define P304_TS11 RA_PINCFG__64(3, 4, 0x0C, RA_PINCFG_FUNC) +#define P305_SEG19 RA_PINCFG_100(3, 5, 0x0D, RA_PINCFG_FUNC) +#define P306_SEG18 RA_PINCFG_100(3, 6, 0x0D, RA_PINCFG_FUNC) +#define P307_SEG17 RA_PINCFG_100(3, 7, 0x0D, RA_PINCFG_FUNC) +#define P400_AGTIO1 RA_PINCFG__48(4, 0, 0x01, RA_PINCFG_FUNC) +#define P400_AUDIO_CLK RA_PINCFG__48(4, 0, 0x12, RA_PINCFG_FUNC) +#define P400_CACREF RA_PINCFG__48(4, 0, 0x0A, RA_PINCFG_FUNC) +#define P400_GTIOC6A RA_PINCFG__48(4, 0, 0x04, RA_PINCFG_FUNC) +#define P400_SCK0 RA_PINCFG__48(4, 0, 0x04, RA_PINCFG_FUNC) +#define P400_SCK1 RA_PINCFG__48(4, 0, 0x05, RA_PINCFG_FUNC) +#define P400_SCL0 RA_PINCFG__48(4, 0, 0x07, RA_PINCFG_FUNC) +#define P400_SEG04 RA_PINCFG__48(4, 0, 0x0D, RA_PINCFG_FUNC) +#define P400_TS20 RA_PINCFG__48(4, 0, 0x0C, RA_PINCFG_FUNC) +#define P401_CTS0_RTS0 RA_PINCFG__64(4, 1, 0x04, RA_PINCFG_FUNC) +#define P401_CTX0 RA_PINCFG__64(4, 1, 0x10, RA_PINCFG_FUNC) +#define P401_GTETRGA RA_PINCFG__64(4, 1, 0x03, RA_PINCFG_FUNC) +#define P401_GTIOC6B RA_PINCFG__64(4, 1, 0x04, RA_PINCFG_FUNC) +#define P401_MOSI1 RA_PINCFG__64(4, 1, 0x05, RA_PINCFG_FUNC) +#define P401_SDA0 RA_PINCFG__64(4, 1, 0x07, RA_PINCFG_FUNC) +#define P401_SDA1 RA_PINCFG__64(4, 1, 0x05, RA_PINCFG_FUNC) +#define P401_SEG05 RA_PINCFG__64(4, 1, 0x0D, RA_PINCFG_FUNC) +#define P401_SS0 RA_PINCFG__64(4, 1, 0x04, RA_PINCFG_FUNC) +#define P401_TS19 RA_PINCFG__64(4, 1, 0x0C, RA_PINCFG_FUNC) +#define P401_TXD1 RA_PINCFG__64(4, 1, 0x05, RA_PINCFG_FUNC) +#define P402_AGTIO0 RA_PINCFG__64(4, 2, 0x01, RA_PINCFG_FUNC) +#define P402_AGTIO1 RA_PINCFG__64(4, 2, 0x02, RA_PINCFG_FUNC) +#define P402_CRX0 RA_PINCFG__64(4, 2, 0x10, RA_PINCFG_FUNC) +#define P402_MISO1 RA_PINCFG__64(4, 2, 0x05, RA_PINCFG_FUNC) +#define P402_RTCIC0 RA_PINCFG__64(4, 2, 0x00, RA_PINCFG_GPIO) +#define P402_RXD1 RA_PINCFG__64(4, 2, 0x05, RA_PINCFG_FUNC) +#define P402_SCL1 RA_PINCFG__64(4, 2, 0x05, RA_PINCFG_FUNC) +#define P402_SEG06 RA_PINCFG__64(4, 2, 0x0D, RA_PINCFG_FUNC) +#define P402_TS18 RA_PINCFG__64(4, 2, 0x0C, RA_PINCFG_FUNC) +#define P403_AGTIO0 RA_PINCFG_100(4, 3, 0x01, RA_PINCFG_FUNC) +#define P403_AGTIO1 RA_PINCFG_100(4, 3, 0x02, RA_PINCFG_FUNC) +#define P403_CTS1_RTS1 RA_PINCFG_100(4, 3, 0x05, RA_PINCFG_FUNC) +#define P403_GTIOC3A RA_PINCFG_100(4, 3, 0x04, RA_PINCFG_FUNC) +#define P403_RTCIC1 RA_PINCFG_100(4, 3, 0x00, RA_PINCFG_GPIO) +#define P403_SS1 RA_PINCFG_100(4, 3, 0x05, RA_PINCFG_FUNC) +#define P403_SSIBCK0 RA_PINCFG_100(4, 3, 0x12, RA_PINCFG_FUNC) +#define P403_TS17 RA_PINCFG_100(4, 3, 0x0C, RA_PINCFG_FUNC) +#define P404_GTIOC3B RA_PINCFG_100(4, 4, 0x04, RA_PINCFG_FUNC) +#define P404_RTCIC2 RA_PINCFG_100(4, 4, 0x00, RA_PINCFG_GPIO) +#define P404_SSIFS0 RA_PINCFG_100(4, 4, 0x12, RA_PINCFG_FUNC) +#define P404_SSILRCK0 RA_PINCFG_100(4, 4, 0x12, RA_PINCFG_FUNC) +#define P405_GTIOC1A RA_PINCFG_100(4, 5, 0x04, RA_PINCFG_FUNC) +#define P405_SSITXD0 RA_PINCFG_100(4, 5, 0x12, RA_PINCFG_FUNC) +#define P406_GTIOC1B RA_PINCFG_100(4, 6, 0x04, RA_PINCFG_FUNC) +#define P406_SSIRXD0 RA_PINCFG_100(4, 6, 0x12, RA_PINCFG_FUNC) +#define P407_ADTRG0 RA_PINCFG__40(4, 7, 0x0A, RA_PINCFG_FUNC) +#define P407_AGTIO0 RA_PINCFG__40(4, 7, 0x01, RA_PINCFG_FUNC) +#define P407_CTS0_RTS0 RA_PINCFG__40(4, 7, 0x04, RA_PINCFG_FUNC) +#define P407_RTCOUT RA_PINCFG__40(4, 7, 0x09, RA_PINCFG_FUNC) +#define P407_SDA0 RA_PINCFG__40(4, 7, 0x07, RA_PINCFG_FUNC) +#define P407_SEG11 RA_PINCFG__40(4, 7, 0x0D, RA_PINCFG_FUNC) +#define P407_SS0 RA_PINCFG__40(4, 7, 0x04, RA_PINCFG_FUNC) +#define P407_SSLB3 RA_PINCFG__40(4, 7, 0x06, RA_PINCFG_FUNC) +#define P407_TS03 RA_PINCFG__40(4, 7, 0x0C, RA_PINCFG_FUNC) +#define P407_USB_VBUS RA_PINCFG__40(4, 7, 0x13, RA_PINCFG_FUNC) +#define P408_CTS1_RTS1 RA_PINCFG__40(4, 8, 0x04, RA_PINCFG_FUNC) +#define P408_GTIOC5B RA_PINCFG__40(4, 8, 0x04, RA_PINCFG_FUNC) +#define P408_GTOWLO RA_PINCFG__40(4, 8, 0x03, RA_PINCFG_FUNC) +#define P408_MISO9 RA_PINCFG__40(4, 8, 0x05, RA_PINCFG_FUNC) +#define P408_RXD9 RA_PINCFG__40(4, 8, 0x05, RA_PINCFG_FUNC) +#define P408_SCL0 RA_PINCFG__40(4, 8, 0x07, RA_PINCFG_FUNC) +#define P408_SCL9 RA_PINCFG__40(4, 8, 0x05, RA_PINCFG_FUNC) +#define P408_SEG10 RA_PINCFG__40(4, 8, 0x0D, RA_PINCFG_FUNC) +#define P408_SS1 RA_PINCFG__40(4, 8, 0x04, RA_PINCFG_FUNC) +#define P408_TS04 RA_PINCFG__40(4, 8, 0x0C, RA_PINCFG_FUNC) +#define P408_USB_ID RA_PINCFG__40(4, 8, 0x13, RA_PINCFG_FUNC) +#define P409_GTIOC5A RA_PINCFG__48(4, 9, 0x04, RA_PINCFG_FUNC) +#define P409_GTOWUP RA_PINCFG__48(4, 9, 0x03, RA_PINCFG_FUNC) +#define P409_MOSI9 RA_PINCFG__48(4, 9, 0x05, RA_PINCFG_FUNC) +#define P409_SDA9 RA_PINCFG__48(4, 9, 0x05, RA_PINCFG_FUNC) +#define P409_SEG09 RA_PINCFG__48(4, 9, 0x0D, RA_PINCFG_FUNC) +#define P409_TS05 RA_PINCFG__48(4, 9, 0x0C, RA_PINCFG_FUNC) +#define P409_TXD9 RA_PINCFG__48(4, 9, 0x05, RA_PINCFG_FUNC) +#define P409_USB_EXICEN RA_PINCFG__48(4, 9, 0x13, RA_PINCFG_FUNC) +#define P410_AGTOB1 RA_PINCFG__64(4, 0, 0x01, RA_PINCFG_FUNC) +#define P410_GTIOC6B RA_PINCFG__64(4, 0, 0x04, RA_PINCFG_FUNC) +#define P410_GTOVLO RA_PINCFG__64(4, 0, 0x03, RA_PINCFG_FUNC) +#define P410_MISO0 RA_PINCFG__64(4, 0, 0x04, RA_PINCFG_FUNC) +#define P410_MISOA RA_PINCFG__64(4, 0, 0x06, RA_PINCFG_FUNC) +#define P410_RXD0 RA_PINCFG__64(4, 0, 0x04, RA_PINCFG_FUNC) +#define P410_SCL0 RA_PINCFG__64(4, 0, 0x04, RA_PINCFG_FUNC) +#define P410_SEG08 RA_PINCFG__64(4, 0, 0x0D, RA_PINCFG_FUNC) +#define P410_TS06 RA_PINCFG__64(4, 0, 0x0C, RA_PINCFG_FUNC) +#define P411_AGTOA1 RA_PINCFG__64(4, 1, 0x01, RA_PINCFG_FUNC) +#define P411_GTIOC6A RA_PINCFG__64(4, 1, 0x04, RA_PINCFG_FUNC) +#define P411_GTOVUP RA_PINCFG__64(4, 1, 0x03, RA_PINCFG_FUNC) +#define P411_MOSI0 RA_PINCFG__64(4, 1, 0x04, RA_PINCFG_FUNC) +#define P411_MOSIA RA_PINCFG__64(4, 1, 0x06, RA_PINCFG_FUNC) +#define P411_SDA0 RA_PINCFG__64(4, 1, 0x04, RA_PINCFG_FUNC) +#define P411_SEG07 RA_PINCFG__64(4, 1, 0x0D, RA_PINCFG_FUNC) +#define P411_TS07 RA_PINCFG__64(4, 1, 0x0C, RA_PINCFG_FUNC) +#define P411_TXD0 RA_PINCFG__64(4, 1, 0x04, RA_PINCFG_FUNC) +#define P412_RSPCKA RA_PINCFG_100(4, 2, 0x06, RA_PINCFG_FUNC) +#define P412_SCK0 RA_PINCFG_100(4, 2, 0x04, RA_PINCFG_FUNC) +#define P413_CTS0_RTS0 RA_PINCFG_100(4, 3, 0x04, RA_PINCFG_FUNC) +#define P413_SS0 RA_PINCFG_100(4, 3, 0x04, RA_PINCFG_FUNC) +#define P413_SSLA0 RA_PINCFG_100(4, 3, 0x06, RA_PINCFG_FUNC) +#define P414_GTIOC0B RA_PINCFG_100(4, 4, 0x04, RA_PINCFG_FUNC) +#define P414_SSLA1 RA_PINCFG_100(4, 4, 0x06, RA_PINCFG_FUNC) +#define P415_GTIOC0A RA_PINCFG_100(4, 5, 0x04, RA_PINCFG_FUNC) +#define P415_SSLA2 RA_PINCFG_100(4, 5, 0x06, RA_PINCFG_FUNC) +#define P500_AGTOA0 RA_PINCFG__48(5, 0, 0x01, RA_PINCFG_FUNC) +#define P500_AN016 RA_PINCFG__48(5, 0, 0x01, RA_PINCFG_ANALOG) +#define P500_CMPREF1 RA_PINCFG__48(5, 0, 0x02, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P500_GTIOC2A RA_PINCFG__48(5, 0, 0x04, RA_PINCFG_FUNC) +#define P500_GTIU RA_PINCFG__48(5, 0, 0x03, RA_PINCFG_FUNC) +#define P500_SEG34 RA_PINCFG__48(5, 0, 0x0D, RA_PINCFG_FUNC) +#define P500_USB_VBUSEN RA_PINCFG__48(5, 0, 0x13, RA_PINCFG_FUNC) +#define P501_AGTOB0 RA_PINCFG__64(5, 1, 0x01, RA_PINCFG_FUNC) +#define P501_AN017 RA_PINCFG__64(5, 1, 0x01, RA_PINCFG_ANALOG) +#define P501_CMPIN1 RA_PINCFG__64(5, 1, 0x02, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P501_GTIOC2B RA_PINCFG__64(5, 1, 0x04, RA_PINCFG_FUNC) +#define P501_GTIV RA_PINCFG__64(5, 1, 0x03, RA_PINCFG_FUNC) +#define P501_MOSI1 RA_PINCFG__64(5, 1, 0x05, RA_PINCFG_FUNC) +#define P501_SDA1 RA_PINCFG__64(5, 1, 0x05, RA_PINCFG_FUNC) +#define P501_SEG35 RA_PINCFG__64(5, 1, 0x0D, RA_PINCFG_FUNC) +#define P501_TXD1 RA_PINCFG__64(5, 1, 0x05, RA_PINCFG_FUNC) +#define P501_USB_OVRCUR_A RA_PINCFG__64(5, 1, 0x13, RA_PINCFG_FUNC) +#define P502_AN018 RA_PINCFG__64(5, 2, 0x01, RA_PINCFG_ANALOG) +#define P502_CMPREF0 RA_PINCFG__64(5, 2, 0x02, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P502_GTIOC3B RA_PINCFG__64(5, 2, 0x04, RA_PINCFG_FUNC) +#define P502_GTIW RA_PINCFG__64(5, 2, 0x03, RA_PINCFG_FUNC) +#define P502_MISO1 RA_PINCFG__64(5, 2, 0x05, RA_PINCFG_FUNC) +#define P502_RXD1 RA_PINCFG__64(5, 2, 0x05, RA_PINCFG_FUNC) +#define P502_SCL1 RA_PINCFG__64(5, 2, 0x05, RA_PINCFG_FUNC) +#define P502_SEG36 RA_PINCFG__64(5, 2, 0x0D, RA_PINCFG_FUNC) +#define P502_USB_OVRCUR_B RA_PINCFG__64(5, 2, 0x13, RA_PINCFG_FUNC) +#define P503_AN023 RA_PINCFG_100(5, 3, 0x01, RA_PINCFG_ANALOG) +#define P503_CMPIN0 RA_PINCFG_100(5, 3, 0x02, RA_PINCFG_FUNC | RA_PINCFG_ANALOG) +#define P503_SCK1 RA_PINCFG_100(5, 3, 0x05, RA_PINCFG_FUNC) +#define P503_SEG37 RA_PINCFG_100(5, 3, 0x0D, RA_PINCFG_FUNC) +#define P503_USB_EXICEN RA_PINCFG_100(5, 3, 0x13, RA_PINCFG_FUNC) +#define P504_AN024 RA_PINCFG_100(5, 4, 0x01, RA_PINCFG_ANALOG) +#define P504_CTS1_RTS1 RA_PINCFG_100(5, 4, 0x05, RA_PINCFG_FUNC) +#define P504_SS1 RA_PINCFG_100(5, 4, 0x05, RA_PINCFG_FUNC) +#define P504_USB_ID RA_PINCFG_100(5, 4, 0x13, RA_PINCFG_FUNC) +#define P505_AN025 RA_PINCFG_100(5, 5, 0x01, RA_PINCFG_ANALOG) +#define P600_GTIOC6B RA_PINCFG_100(6, 0, 0x01, RA_PINCFG_FUNC) +#define P600_SCK9 RA_PINCFG_100(6, 0, 0x05, RA_PINCFG_FUNC) +#define P600_SEG33 RA_PINCFG_100(6, 0, 0x0D, RA_PINCFG_FUNC) +#define P601_GTIOC6A RA_PINCFG_100(6, 1, 0x01, RA_PINCFG_FUNC) +#define P601_MISO9 RA_PINCFG_100(6, 1, 0x05, RA_PINCFG_FUNC) +#define P601_RXD9 RA_PINCFG_100(6, 1, 0x05, RA_PINCFG_FUNC) +#define P601_SCL9 RA_PINCFG_100(6, 1, 0x05, RA_PINCFG_FUNC) +#define P601_SEG32 RA_PINCFG_100(6, 1, 0x0D, RA_PINCFG_FUNC) +#define P602_GTIOC7B RA_PINCFG_100(6, 2, 0x01, RA_PINCFG_FUNC) +#define P602_MOSI9 RA_PINCFG_100(6, 2, 0x05, RA_PINCFG_FUNC) +#define P602_SDA9 RA_PINCFG_100(6, 2, 0x05, RA_PINCFG_FUNC) +#define P602_SEG31 RA_PINCFG_100(6, 2, 0x0D, RA_PINCFG_FUNC) +#define P602_TXD9 RA_PINCFG_100(6, 2, 0x05, RA_PINCFG_FUNC) +#define P603_CTS9_RTS9 RA_PINCFG_100(6, 3, 0x05, RA_PINCFG_FUNC) +#define P603_GTIOC7A RA_PINCFG_100(6, 3, 0x01, RA_PINCFG_FUNC) +#define P603_SEG30 RA_PINCFG_100(6, 3, 0x0D, RA_PINCFG_FUNC) +#define P603_SS9 RA_PINCFG_100(6, 3, 0x05, RA_PINCFG_FUNC) +#define P608_GTIOC4B RA_PINCFG_100(6, 8, 0x01, RA_PINCFG_FUNC) +#define P608_SEG27 RA_PINCFG_100(6, 8, 0x0D, RA_PINCFG_FUNC) +#define P609_GTIOC5A RA_PINCFG_100(6, 9, 0x01, RA_PINCFG_FUNC) +#define P609_SEG28 RA_PINCFG_100(6, 9, 0x0D, RA_PINCFG_FUNC) +#define P610_GTIOC5B RA_PINCFG_100(6, 0, 0x01, RA_PINCFG_FUNC) +#define P610_SEG29 RA_PINCFG_100(6, 0, 0x0D, RA_PINCFG_FUNC) +#define P708_MISO1 RA_PINCFG_100(7, 8, 0x05, RA_PINCFG_FUNC) +#define P708_RXD1 RA_PINCFG_100(7, 8, 0x05, RA_PINCFG_FUNC) +#define P708_SCL1 RA_PINCFG_100(7, 8, 0x05, RA_PINCFG_FUNC) +#define P708_SSLA3 RA_PINCFG_100(7, 8, 0x06, RA_PINCFG_FUNC) +#define P808_SEG21 RA_PINCFG_100(8, 8, 0x0D, RA_PINCFG_FUNC) +#define P809_SEG22 RA_PINCFG_100(8, 9, 0x0D, RA_PINCFG_FUNC) +#define P914_USB_DP RA_PINCFG__40(9, 4, 0x00, RA_PINCFG_GPIO) +#define P915_USB_DM RA_PINCFG__40(9, 5, 0x00, RA_PINCFG_GPIO) +#endif diff --git a/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-ra-common.h b/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-ra-common.h new file mode 100644 index 00000000000..88ea7ece75d --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-ra-common.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_RENESAS_PINCTRL_RA_COMMON_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_RENESAS_PINCTRL_RA_COMMON_H_ + +#define PORT4_POS 29 +#define PORT4_MASK 0x1 +#define PSEL_POS 24 +#define PSEL_MASK 0x5 +#define PORT_POS 21 +#define PORT_MASK 0x3 +#define PIN_POS 17 +#define PIN_MASK 0xF +#define OPT_POS 0 +#define OPT_MASK 0x1B000 + +#define RA_PINCFG_GPIO 0x00000 +#define RA_PINCFG_FUNC 0x10000 +#define RA_PINCFG_ANALOG 0x08000 + +#define RA_PINCFG(port, pin, psel, opt) \ + ((((psel)&PSEL_MASK) << PSEL_POS) | (((pin)&PIN_MASK) << PIN_POS) | \ + (((port)&PORT_MASK) << PORT_POS) | ((((port) >> 3) & PORT4_MASK) << PORT4_POS) | \ + (((opt)&OPT_MASK) << OPT_POS)) + +#if RA_SOC_PINS >= 40 +#define RA_PINCFG__40(port, pin, psel, opt) RA_PINCFG(port, pin, psel, opt) +#endif + +#if RA_SOC_PINS >= 48 +#define RA_PINCFG__48(port, pin, psel, opt) RA_PINCFG(port, pin, psel, opt) +#endif + +#if RA_SOC_PINS >= 64 +#define RA_PINCFG__64(port, pin, psel, opt) RA_PINCFG(port, pin, psel, opt) +#endif + +#if RA_SOC_PINS >= 100 +#define RA_PINCFG_100(port, pin, psel, opt) RA_PINCFG(port, pin, psel, opt) +#endif + +#endif diff --git a/include/zephyr/dt-bindings/power/atmel_sam_supc.h b/include/zephyr/dt-bindings/power/atmel_sam_supc.h new file mode 100644 index 00000000000..547a97ef704 --- /dev/null +++ b/include/zephyr/dt-bindings/power/atmel_sam_supc.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 Bjarki Arge Andreasen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_POWER_ATMEL_SAM_SUPC_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_POWER_ATMEL_SAM_SUPC_H_ + +#define SUPC_WAKEUP_SOURCE_FWUP 0 +#define SUPC_WAKEUP_SOURCE_SM 1 +#define SUPC_WAKEUP_SOURCE_RTT 2 +#define SUPC_WAKEUP_SOURCE_RTC 3 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_POWER_ATMEL_SAM_SUPC_H_ */ diff --git a/include/zephyr/dt-bindings/regulator/max20335.h b/include/zephyr/dt-bindings/regulator/max20335.h new file mode 100644 index 00000000000..d7d23f03c96 --- /dev/null +++ b/include/zephyr/dt-bindings/regulator/max20335.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Grinn + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_MAX20335_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_MAX20335_H_ + +/** + * @defgroup regulator_max20335 MAX20335 Devicetree helpers. + * @ingroup regulator_interface + * @{ + */ + +/** + * @name MAX20335 Regulator modes + * @{ + */ +/** LDO mode */ +#define MAX20335_LDO_MODE 0 +/** Load switch mode */ +#define MAX20335_LOAD_SWITCH_MODE 1 +/** @} */ + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_MAX20335_H_*/ diff --git a/include/zephyr/dt-bindings/regulator/npm1300.h b/include/zephyr/dt-bindings/regulator/npm1300.h index 3293fe562d4..bf3f8cfa3ee 100644 --- a/include/zephyr/dt-bindings/regulator/npm1300.h +++ b/include/zephyr/dt-bindings/regulator/npm1300.h @@ -20,6 +20,7 @@ /* Buck modes */ #define NPM1300_BUCK_MODE_AUTO 0x00U #define NPM1300_BUCK_MODE_PWM 0x01U +#define NPM1300_BUCK_MODE_PFM 0x04U /* LDSW / LDO modes */ #define NPM1300_LDSW_MODE_LDO 0x02U diff --git a/include/zephyr/dt-bindings/regulator/nxp_vref.h b/include/zephyr/dt-bindings/regulator/nxp_vref.h new file mode 100644 index 00000000000..37c3856496a --- /dev/null +++ b/include/zephyr/dt-bindings/regulator/nxp_vref.h @@ -0,0 +1,29 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_NXP_VREF_H +#define ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_NXP_VREF_H + +/** + * @defgroup regulator_nxp_vref Devicetree helpers + * @ingroup regulator_interface + * @{ + */ + +/** + * @name NXP VREF Regulator API Modes + * @{ + */ +#define NXP_VREF_MODE_STANDBY 0 +#define NXP_VREF_MODE_LOW_POWER 1 +#define NXP_VREF_MODE_HIGH_POWER 2 +#define NXP_VREF_MODE_INTERNAL_REGULATOR 3 + +/** @} */ + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_NXP_VREF_H */ diff --git a/include/zephyr/dt-bindings/sensor/bq274xx.h b/include/zephyr/dt-bindings/sensor/bq274xx.h new file mode 100644 index 00000000000..9e8c259068e --- /dev/null +++ b/include/zephyr/dt-bindings/sensor/bq274xx.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 The Zephyr Contributors. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Relevant documents: + * - BQ27421 + * Datasheet: https://www.ti.com/lit/gpn/bq27421-g1 + * Technical reference manual: https://www.ti.com/lit/pdf/sluuac5 + * - BQ27427 + * Datasheet: https://www.ti.com/lit/gpn/bq27427 + * Technical reference manual: https://www.ti.com/lit/pdf/sluucd5 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_SENSOR_BQ274XX_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_SENSOR_BQ274XX_H_ + +/* Chemistry IDs for BQ27427 */ +#define BQ27427_CHEM_ID_A 0x3230 +#define BQ27427_CHEM_ID_B 0x1202 +#define BQ27427_CHEM_ID_C 0x3142 + +/* Chemistry IDs for BQ27421 variants */ +#define BQ27421_G1A_CHEM_ID 0x0128 +#define BQ27421_G1B_CHEM_ID 0x0312 +#define BQ27421_G1D_CHEM_ID 0x3142 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_SENSOR_BQ274XX_H_ */ diff --git a/include/zephyr/dt-bindings/sensor/iis2dlpc.h b/include/zephyr/dt-bindings/sensor/iis2dlpc.h new file mode 100644 index 00000000000..abf6df1cc44 --- /dev/null +++ b/include/zephyr/dt-bindings/sensor/iis2dlpc.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_ST_IIS2DLPC_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_ST_IIS2DLPC_H_ + +/* power-modes */ +#define IIS2DLPC_DT_LP_M1 0 +#define IIS2DLPC_DT_LP_M2 1 +#define IIS2DLPC_DT_LP_M3 2 +#define IIS2DLPC_DT_LP_M4 3 +#define IIS2DLPC_DT_HP_MODE 4 + +/* Filter bandwidth */ +#define IIS2DLPC_DT_FILTER_BW_ODR_DIV_2 0 +#define IIS2DLPC_DT_FILTER_BW_ODR_DIV_4 1 +#define IIS2DLPC_DT_FILTER_BW_ODR_DIV_10 2 +#define IIS2DLPC_DT_FILTER_BW_ODR_DIV_20 3 + +/* Tap mode */ +#define IIS2DLPC_DT_SINGLE_TAP 0 +#define IIS2DLPC_DT_SINGLE_DOUBLE_TAP 1 + +/* Free-Fall threshold */ +#define IIS2DLPC_DT_FF_THRESHOLD_156_mg 0 +#define IIS2DLPC_DT_FF_THRESHOLD_219_mg 1 +#define IIS2DLPC_DT_FF_THRESHOLD_250_mg 2 +#define IIS2DLPC_DT_FF_THRESHOLD_312_mg 3 +#define IIS2DLPC_DT_FF_THRESHOLD_344_mg 4 +#define IIS2DLPC_DT_FF_THRESHOLD_406_mg 5 +#define IIS2DLPC_DT_FF_THRESHOLD_469_mg 6 +#define IIS2DLPC_DT_FF_THRESHOLD_500_mg 7 + +/* wakeup duration */ +#define IIS2DLPC_DT_WAKEUP_1_ODR 0 +#define IIS2DLPC_DT_WAKEUP_2_ODR 1 +#define IIS2DLPC_DT_WAKEUP_3_ODR 2 +#define IIS2DLPC_DT_WAKEUP_4_ODR 3 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_ST_IIS2DLPC_H_ */ diff --git a/include/zephyr/dt-bindings/sensor/iis2iclx.h b/include/zephyr/dt-bindings/sensor/iis2iclx.h new file mode 100644 index 00000000000..544486e0984 --- /dev/null +++ b/include/zephyr/dt-bindings/sensor/iis2iclx.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_ST_IIS2ICLX_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_ST_IIS2ICLX_H_ + +/* Accel range */ +#define IIS2ICLX_DT_FS_500mG 0 +#define IIS2ICLX_DT_FS_3G 1 +#define IIS2ICLX_DT_FS_1G 2 +#define IIS2ICLX_DT_FS_2G 3 + +/* Accel Data rates */ +#define IIS2ICLX_DT_ODR_OFF 0x0 +#define IIS2ICLX_DT_ODR_12Hz5 0x1 +#define IIS2ICLX_DT_ODR_26H 0x2 +#define IIS2ICLX_DT_ODR_52Hz 0x3 +#define IIS2ICLX_DT_ODR_104Hz 0x4 +#define IIS2ICLX_DT_ODR_208Hz 0x5 +#define IIS2ICLX_DT_ODR_416Hz 0x6 +#define IIS2ICLX_DT_ODR_833Hz 0x7 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_ST_IIS2ICLX_H_ */ diff --git a/include/zephyr/dt-bindings/sensor/ism330dhcx.h b/include/zephyr/dt-bindings/sensor/ism330dhcx.h new file mode 100644 index 00000000000..7d857eb165a --- /dev/null +++ b/include/zephyr/dt-bindings/sensor/ism330dhcx.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_ST_ISM330DHCX_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_ST_ISM330DHCX_H_ + +/* Accel and Gyro Data rates */ +#define ISM330DHCX_DT_ODR_OFF 0x0 +#define ISM330DHCX_DT_ODR_12Hz5 0x1 +#define ISM330DHCX_DT_ODR_26H 0x2 +#define ISM330DHCX_DT_ODR_52Hz 0x3 +#define ISM330DHCX_DT_ODR_104Hz 0x4 +#define ISM330DHCX_DT_ODR_208Hz 0x5 +#define ISM330DHCX_DT_ODR_416Hz 0x6 +#define ISM330DHCX_DT_ODR_833Hz 0x7 +#define ISM330DHCX_DT_ODR_1666Hz 0x8 +#define ISM330DHCX_DT_ODR_3332Hz 0x9 +#define ISM330DHCX_DT_ODR_6667Hz 0xa +#define ISM330DHCX_DT_ODR_1Hz6 0xb + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_ST_ISM330DHCX_H_ */ diff --git a/include/zephyr/dt-bindings/sensor/lis2dh.h b/include/zephyr/dt-bindings/sensor/lis2dh.h new file mode 100644 index 00000000000..a697f34cc80 --- /dev/null +++ b/include/zephyr/dt-bindings/sensor/lis2dh.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_ST_LIS2DH_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_ST_LIS2DH_H_ + +/* GPIO interrupt configuration */ +#define LIS2DH_DT_GPIO_INT_EDGE 0 +#define LIS2DH_DT_GPIO_INT_EDGE_RISING 1 +#define LIS2DH_DT_GPIO_INT_EDGE_FALLING 2 +#define LIS2DH_DT_GPIO_INT_LEVEL_HIGH 3 +#define LIS2DH_DT_GPIO_INT_LEVEL_LOW 4 + +/* Any Motion mode */ +#define LIS2DH_DT_ANYM_OR_COMBINATION 0 +#define LIS2DH_DT_ANYM_6D_MOVEMENT 1 +#define LIS2DH_DT_ANYM_AND_COMBINATION 2 +#define LIS2DH_DT_ANYM_6D_POSITION 3 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_ST_LIS2DH_H_ */ diff --git a/include/zephyr/dt-bindings/sensor/lis2ds12.h b/include/zephyr/dt-bindings/sensor/lis2ds12.h new file mode 100644 index 00000000000..04d808bfa72 --- /dev/null +++ b/include/zephyr/dt-bindings/sensor/lis2ds12.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_ST_LIS2DS12_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_ST_LIS2DS12_H_ + +/* power-modes */ +#define LIS2DS12_DT_POWER_DOWN 0 +#define LIS2DS12_DT_LOW_POWER 1 +#define LIS2DS12_DT_HIGH_RESOLUTION 2 +#define LIS2DS12_DT_HIGH_FREQUENCY 3 + +/* Data rate */ +#define LIS2DS12_DT_ODR_OFF 0 +#define LIS2DS12_DT_ODR_1Hz_LP 1 /* available in LP mode only */ +#define LIS2DS12_DT_ODR_12Hz5 2 /* available in LP and HR mode */ +#define LIS2DS12_DT_ODR_25Hz 3 /* available in LP and HR mode */ +#define LIS2DS12_DT_ODR_50Hz 4 /* available in LP and HR mode */ +#define LIS2DS12_DT_ODR_100Hz 5 /* available in LP and HR mode */ +#define LIS2DS12_DT_ODR_200Hz 6 /* available in LP and HR mode */ +#define LIS2DS12_DT_ODR_400Hz 7 /* available in LP and HR mode */ +#define LIS2DS12_DT_ODR_800Hz 8 /* available in LP and HR mode */ +#define LIS2DS12_DT_ODR_1600Hz 9 /* available in HF mode only */ +#define LIS2DS12_DT_ODR_3200Hz_HF 10 /* available in HF mode only */ +#define LIS2DS12_DT_ODR_6400Hz_HF 11 /* available in HF mode only */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_ST_LIS2DS12_H_ */ diff --git a/include/zephyr/dt-bindings/sensor/lis2dw12.h b/include/zephyr/dt-bindings/sensor/lis2dw12.h new file mode 100644 index 00000000000..9e5892ec0a5 --- /dev/null +++ b/include/zephyr/dt-bindings/sensor/lis2dw12.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_ST_LIS2DW12_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_ST_LIS2DW12_H_ + +/* power-modes */ +#define LIS2DW12_DT_LP_M1 0 +#define LIS2DW12_DT_LP_M2 1 +#define LIS2DW12_DT_LP_M3 2 +#define LIS2DW12_DT_LP_M4 3 +#define LIS2DW12_DT_HP_MODE 4 + +/* Filter bandwidth */ +#define LIS2DW12_DT_FILTER_BW_ODR_DIV_2 0 +#define LIS2DW12_DT_FILTER_BW_ODR_DIV_4 1 +#define LIS2DW12_DT_FILTER_BW_ODR_DIV_10 2 +#define LIS2DW12_DT_FILTER_BW_ODR_DIV_20 3 + +/* Tap mode */ +#define LIS2DW12_DT_SINGLE_TAP 0 +#define LIS2DW12_DT_SINGLE_DOUBLE_TAP 1 + +/* Free-Fall threshold */ +#define LIS2DW12_DT_FF_THRESHOLD_156_mg 0 +#define LIS2DW12_DT_FF_THRESHOLD_219_mg 1 +#define LIS2DW12_DT_FF_THRESHOLD_250_mg 2 +#define LIS2DW12_DT_FF_THRESHOLD_312_mg 3 +#define LIS2DW12_DT_FF_THRESHOLD_344_mg 4 +#define LIS2DW12_DT_FF_THRESHOLD_406_mg 5 +#define LIS2DW12_DT_FF_THRESHOLD_469_mg 6 +#define LIS2DW12_DT_FF_THRESHOLD_500_mg 7 + +/* wakeup duration */ +#define LIS2DW12_DT_WAKEUP_1_ODR 0 +#define LIS2DW12_DT_WAKEUP_2_ODR 1 +#define LIS2DW12_DT_WAKEUP_3_ODR 2 +#define LIS2DW12_DT_WAKEUP_4_ODR 3 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_ST_LIS2DW12_H_ */ diff --git a/include/zephyr/dt-bindings/sensor/lps22df.h b/include/zephyr/dt-bindings/sensor/lps22df.h new file mode 100644 index 00000000000..95668ae6390 --- /dev/null +++ b/include/zephyr/dt-bindings/sensor/lps22df.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_ST_LPS22DF_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_ST_LPS22DF_H_ + +/* Data rate */ +#define LPS22DF_DT_ODR_POWER_DOWN 0 +#define LPS22DF_DT_ODR_1HZ 1 +#define LPS22DF_DT_ODR_4HZ 2 +#define LPS22DF_DT_ODR_10HZ 3 +#define LPS22DF_DT_ODR_25HZ 4 +#define LPS22DF_DT_ODR_50HZ 5 +#define LPS22DF_DT_ODR_75HZ 6 +#define LPS22DF_DT_ODR_100HZ 7 +#define LPS22DF_DT_ODR_200HZ 8 + +/* Low Pass filter */ +#define LPS22DF_DT_LP_FILTER_OFF 0 +#define LPS22DF_DT_LP_FILTER_ODR_4 1 +#define LPS22DF_DT_LP_FILTER_ODR_9 3 + +/* Average (number of samples) filter */ +#define LPS22DF_DT_AVG_4_SAMPLES 0 +#define LPS22DF_DT_AVG_8_SAMPLES 1 +#define LPS22DF_DT_AVG_16_SAMPLES 2 +#define LPS22DF_DT_AVG_32_SAMPLES 3 +#define LPS22DF_DT_AVG_64_SAMPLES 4 +#define LPS22DF_DT_AVG_128_SAMPLES 5 +#define LPS22DF_DT_AVG_256_SAMPLES 6 +#define LPS22DF_DT_AVG_512_SAMPLES 7 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_ST_LPS22DF_H_ */ diff --git a/include/zephyr/dt-bindings/sensor/lps22hh.h b/include/zephyr/dt-bindings/sensor/lps22hh.h new file mode 100644 index 00000000000..728f872bc37 --- /dev/null +++ b/include/zephyr/dt-bindings/sensor/lps22hh.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_ST_LPS22HH_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_ST_LPS22HH_H_ + +/* Data rate */ +#define LPS22HH_DT_ODR_POWER_DOWN 0 +#define LPS22HH_DT_ODR_1HZ 1 +#define LPS22HH_DT_ODR_10HZ 2 +#define LPS22HH_DT_ODR_25HZ 3 +#define LPS22HH_DT_ODR_50HZ 4 +#define LPS22HH_DT_ODR_75HZ 5 +#define LPS22HH_DT_ODR_100HZ 6 +#define LPS22HH_DT_ODR_200HZ 7 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_ST_LPS22HH_H_ */ diff --git a/include/zephyr/dt-bindings/sensor/lsm6dso.h b/include/zephyr/dt-bindings/sensor/lsm6dso.h new file mode 100644 index 00000000000..7d3775bae3d --- /dev/null +++ b/include/zephyr/dt-bindings/sensor/lsm6dso.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_ST_LSM6DSO_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_ST_LSM6DSO_H_ + +/* Accel power-modes */ +#define LSM6DSO_DT_XL_HP_MODE 0 +#define LSM6DSO_DT_XL_LP_NORMAL_MODE 1 +#define LSM6DSO_DT_XL_ULP_MODE 2 + +/* Gyro power-modes */ +#define LSM6DSO_DT_GY_HP_MODE 0 +#define LSM6DSO_DT_GY_NORMAL_MODE 1 + +/* Accel range */ +#define LSM6DSO_DT_FS_2G 0 +#define LSM6DSO_DT_FS_16G 1 +#define LSM6DSO_DT_FS_4G 2 +#define LSM6DSO_DT_FS_8G 3 + +/* Gyro range */ +#define LSM6DSO_DT_FS_250DPS 0 +#define LSM6DSO_DT_FS_125DPS 1 +#define LSM6DSO_DT_FS_500DPS 2 +#define LSM6DSO_DT_FS_1000DPS 4 +#define LSM6DSO_DT_FS_2000DPS 6 + +/* Accel and Gyro Data rates */ +#define LSM6DSO_DT_ODR_OFF 0x0 +#define LSM6DSO_DT_ODR_12Hz5 0x1 +#define LSM6DSO_DT_ODR_26H 0x2 +#define LSM6DSO_DT_ODR_52Hz 0x3 +#define LSM6DSO_DT_ODR_104Hz 0x4 +#define LSM6DSO_DT_ODR_208Hz 0x5 +#define LSM6DSO_DT_ODR_417Hz 0x6 +#define LSM6DSO_DT_ODR_833Hz 0x7 +#define LSM6DSO_DT_ODR_1667Hz 0x8 +#define LSM6DSO_DT_ODR_3333Hz 0x9 +#define LSM6DSO_DT_ODR_6667Hz 0xa +#define LSM6DSO_DT_ODR_1Hz6 0xb + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_ST_LSM6DSO_H_ */ diff --git a/include/zephyr/dt-bindings/sensor/lsm6dso16is.h b/include/zephyr/dt-bindings/sensor/lsm6dso16is.h new file mode 100644 index 00000000000..385f41145cf --- /dev/null +++ b/include/zephyr/dt-bindings/sensor/lsm6dso16is.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_ST_LSM6DSO16IS_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_ST_LSM6DSO16IS_H_ + +/* Accel range */ +#define LSM6DSO16IS_DT_FS_2G 0 +#define LSM6DSO16IS_DT_FS_16G 1 +#define LSM6DSO16IS_DT_FS_4G 2 +#define LSM6DSO16IS_DT_FS_8G 3 + +/* Gyro range */ +#define LSM6DSO16IS_DT_FS_250DPS 0x0 +#define LSM6DSO16IS_DT_FS_500DPS 0x1 +#define LSM6DSO16IS_DT_FS_1000DPS 0x2 +#define LSM6DSO16IS_DT_FS_2000DPS 0x3 +#define LSM6DSO16IS_DT_FS_125DPS 0x10 + +/* Accel and Gyro Data rates */ +#define LSM6DSO16IS_DT_ODR_OFF 0x0 +#define LSM6DSO16IS_DT_ODR_12Hz5_HP 0x1 +#define LSM6DSO16IS_DT_ODR_26H_HP 0x2 +#define LSM6DSO16IS_DT_ODR_52Hz_HP 0x3 +#define LSM6DSO16IS_DT_ODR_104Hz_HP 0x4 +#define LSM6DSO16IS_DT_ODR_208Hz_HP 0x5 +#define LSM6DSO16IS_DT_ODR_416Hz_HP 0x6 +#define LSM6DSO16IS_DT_ODR_833Hz_HP 0x7 +#define LSM6DSO16IS_DT_ODR_1667Hz_HP 0x8 +#define LSM6DSO16IS_DT_ODR_3333Hz_HP 0x9 +#define LSM6DSO16IS_DT_ODR_6667Hz_HP 0xa +#define LSM6DSO16IS_DT_ODR_12Hz5_LP 0x11 +#define LSM6DSO16IS_DT_ODR_26H_LP 0x12 +#define LSM6DSO16IS_DT_ODR_52Hz_LP 0x13 +#define LSM6DSO16IS_DT_ODR_104Hz_LP 0x14 +#define LSM6DSO16IS_DT_ODR_208Hz_LP 0x15 +#define LSM6DSO16IS_DT_ODR_416Hz_LP 0x16 +#define LSM6DSO16IS_DT_ODR_833Hz_LP 0x17 +#define LSM6DSO16IS_DT_ODR_1667Hz_LP 0x18 +#define LSM6DSO16IS_DT_ODR_3333Hz_LP 0x19 +#define LSM6DSO16IS_DT_ODR_6667Hz_LP 0x1a +#define LSM6DSO16IS_DT_ODR_1Hz6_LP 0x1b + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_ST_LSM6DSO16IS_H_ */ diff --git a/include/zephyr/dt-bindings/sensor/lsm6dsv16x.h b/include/zephyr/dt-bindings/sensor/lsm6dsv16x.h new file mode 100644 index 00000000000..533dd5e3feb --- /dev/null +++ b/include/zephyr/dt-bindings/sensor/lsm6dsv16x.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_ST_LSM6DSV16X_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_ST_LSM6DSV16X_H_ + +/* Accel range */ +#define LSM6DSV16X_DT_FS_2G 0 +#define LSM6DSV16X_DT_FS_4G 1 +#define LSM6DSV16X_DT_FS_8G 2 +#define LSM6DSV16X_DT_FS_16G 3 + +/* Gyro range */ +#define LSM6DSV16X_DT_FS_125DPS 0x0 +#define LSM6DSV16X_DT_FS_250DPS 0x1 +#define LSM6DSV16X_DT_FS_500DPS 0x2 +#define LSM6DSV16X_DT_FS_1000DPS 0x3 +#define LSM6DSV16X_DT_FS_2000DPS 0x4 +#define LSM6DSV16X_DT_FS_4000DPS 0xc + +/* Accel and Gyro Data rates */ +#define LSM6DSV16X_DT_ODR_OFF 0x0 +#define LSM6DSV16X_DT_ODR_AT_1Hz875 0x1 +#define LSM6DSV16X_DT_ODR_AT_7Hz5 0x2 +#define LSM6DSV16X_DT_ODR_AT_15Hz 0x3 +#define LSM6DSV16X_DT_ODR_AT_30Hz 0x4 +#define LSM6DSV16X_DT_ODR_AT_60Hz 0x5 +#define LSM6DSV16X_DT_ODR_AT_120Hz 0x6 +#define LSM6DSV16X_DT_ODR_AT_240Hz 0x7 +#define LSM6DSV16X_DT_ODR_AT_480Hz 0x8 +#define LSM6DSV16X_DT_ODR_AT_960Hz 0x9 +#define LSM6DSV16X_DT_ODR_AT_1920Hz 0xA +#define LSM6DSV16X_DT_ODR_AT_3840Hz 0xB +#define LSM6DSV16X_DT_ODR_AT_7680Hz 0xC +#define LSM6DSV16X_DT_ODR_HA01_AT_15Hz625 0x13 +#define LSM6DSV16X_DT_ODR_HA01_AT_31Hz25 0x14 +#define LSM6DSV16X_DT_ODR_HA01_AT_62Hz5 0x15 +#define LSM6DSV16X_DT_ODR_HA01_AT_125Hz 0x16 +#define LSM6DSV16X_DT_ODR_HA01_AT_250Hz 0x17 +#define LSM6DSV16X_DT_ODR_HA01_AT_500Hz 0x18 +#define LSM6DSV16X_DT_ODR_HA01_AT_1000Hz 0x19 +#define LSM6DSV16X_DT_ODR_HA01_AT_2000Hz 0x1A +#define LSM6DSV16X_DT_ODR_HA01_AT_4000Hz 0x1B +#define LSM6DSV16X_DT_ODR_HA01_AT_8000Hz 0x1C +#define LSM6DSV16X_DT_ODR_HA02_AT_12Hz5 0x23 +#define LSM6DSV16X_DT_ODR_HA02_AT_25Hz 0x24 +#define LSM6DSV16X_DT_ODR_HA02_AT_50Hz 0x25 +#define LSM6DSV16X_DT_ODR_HA02_AT_100Hz 0x26 +#define LSM6DSV16X_DT_ODR_HA02_AT_200Hz 0x27 +#define LSM6DSV16X_DT_ODR_HA02_AT_400Hz 0x28 +#define LSM6DSV16X_DT_ODR_HA02_AT_800Hz 0x29 +#define LSM6DSV16X_DT_ODR_HA02_AT_1600Hz 0x2A +#define LSM6DSV16X_DT_ODR_HA02_AT_3200Hz 0x2B +#define LSM6DSV16X_DT_ODR_HA02_AT_6400Hz 0x2C + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_ST_LSM6DSV16X_H_ */ diff --git a/include/zephyr/fs/fs_interface.h b/include/zephyr/fs/fs_interface.h index 2692ea168a7..5db637635b9 100644 --- a/include/zephyr/fs/fs_interface.h +++ b/include/zephyr/fs/fs_interface.h @@ -13,7 +13,7 @@ extern "C" { #endif -#if (CONFIG_FILE_SYSTEM_MAX_FILE_NAME - 0) > 0 +#if defined(CONFIG_FILE_SYSTEM_MAX_FILE_NAME) && (CONFIG_FILE_SYSTEM_MAX_FILE_NAME - 0) > 0 #define MAX_FILE_NAME CONFIG_FILE_SYSTEM_MAX_FILE_NAME #else /* CONFIG_FILE_SYSTEM_MAX_FILE_NAME */ diff --git a/include/zephyr/fs/nvs.h b/include/zephyr/fs/nvs.h index 30315d77b20..1d0a4e3b1d3 100644 --- a/include/zephyr/fs/nvs.h +++ b/include/zephyr/fs/nvs.h @@ -94,6 +94,11 @@ int nvs_clear(struct nvs_fs *fs); /** * @brief Write an entry to the file system. * + * @note When @p len parameter is equal to @p 0 then entry is effectively removed (it is + * equivalent to calling of nvs_delete). Any calls to nvs_read for entries with data of length + * @p 0 will return error.@n It is not possible to distinguish between deleted entry and entry + * with data of length 0. + * * @param fs Pointer to file system * @param id Id of the entry to be written * @param data Pointer to the data to be written diff --git a/include/zephyr/input/input_kbd_matrix.h b/include/zephyr/input/input_kbd_matrix.h new file mode 100644 index 00000000000..0566f14d2cd --- /dev/null +++ b/include/zephyr/input/input_kbd_matrix.h @@ -0,0 +1,245 @@ +/* + * Copyright 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_INPUT_KBD_MATRIX_H_ +#define ZEPHYR_INCLUDE_INPUT_KBD_MATRIX_H_ + +/** + * @brief Keyboard Matrix API + * @defgroup input_kbd_matrix Keyboard Matrix API + * @ingroup io_interfaces + * @{ + */ + +#include +#include +#include +#include +#include + +/** Special drive_column argument for not driving any column */ +#define INPUT_KBD_MATRIX_COLUMN_DRIVE_NONE -1 + +/** Special drive_column argument for driving all the columns */ +#define INPUT_KBD_MATRIX_COLUMN_DRIVE_ALL -2 + +/** Number of tracked scan cycles */ +#define INPUT_KBD_MATRIX_SCAN_OCURRENCES 30U + +/** + * @brief Keyboard matrix internal APIs. + */ +struct input_kbd_matrix_api { + /** + * @brief Request to drive a specific column. + * + * Request to drive a specific matrix column, or none, or all. + * + * @param dev Pointer to the keyboard matrix device. + * @param col The column to drive, or + * @ref INPUT_KBD_MATRIX_COLUMN_DRIVE_NONE or + * @ref INPUT_KBD_MATRIX_COLUMN_DRIVE_ALL. + */ + void (*drive_column)(const struct device *dev, int col); + /** + * @brief Read the matrix row. + * + * @param dev Pointer to the keyboard matrix device. + */ + int (*read_row)(const struct device *dev); + /** + * @brief Request to put the matrix in detection mode. + * + * Request to put the driver in detection mode, this is called after a + * request to drive all the column and typically involves reenabling + * interrupts row pin changes. + * + * @param dev Pointer to the keyboard matrix device. + * @param enable Whether detection mode has to be enabled or disabled. + */ + void (*set_detect_mode)(const struct device *dev, bool enabled); +}; + +/** + * @brief Common keyboard matrix config. + * + * This structure **must** be placed first in the driver's config structure. + */ +struct input_kbd_matrix_common_config { + const struct input_kbd_matrix_api *api; + uint8_t row_size; + uint8_t col_size; + uint32_t poll_period_us; + uint32_t poll_timeout_ms; + uint32_t debounce_down_ms; + uint32_t debounce_up_ms; + uint32_t settle_time_us; + bool ghostkey_check; + + /* extra data pointers */ + uint8_t *matrix_stable_state; + uint8_t *matrix_unstable_state; + uint8_t *matrix_previous_state; + uint8_t *matrix_new_state; + uint8_t *scan_cycle_idx; +}; + +#define INPUT_KBD_MATRIX_DATA_NAME(node_id, name) \ + _CONCAT(__input_kbd_matrix_, \ + _CONCAT(name, DEVICE_DT_NAME_GET(node_id))) + +/** + * @brief Defines the common keyboard matrix support data from devicetree, + * specify row and col count. + */ +#define INPUT_KBD_MATRIX_DT_DEFINE_ROW_COL(node_id, _row_size, _col_size) \ + BUILD_ASSERT(IN_RANGE(_row_size, 1, 8), "invalid row-size"); \ + BUILD_ASSERT(IN_RANGE(_col_size, 1, UINT8_MAX), "invalid col-size"); \ + static uint8_t INPUT_KBD_MATRIX_DATA_NAME(node_id, stable_state)[_col_size]; \ + static uint8_t INPUT_KBD_MATRIX_DATA_NAME(node_id, unstable_state)[_col_size]; \ + static uint8_t INPUT_KBD_MATRIX_DATA_NAME(node_id, previous_state)[_col_size]; \ + static uint8_t INPUT_KBD_MATRIX_DATA_NAME(node_id, new_state)[_col_size]; \ + static uint8_t INPUT_KBD_MATRIX_DATA_NAME(node_id, scan_cycle_idx)[_row_size * _col_size]; + +/** + * @brief Defines the common keyboard matrix support data from devicetree. + */ +#define INPUT_KBD_MATRIX_DT_DEFINE(node_id) \ + INPUT_KBD_MATRIX_DT_DEFINE_ROW_COL( \ + node_id, DT_PROP(node_id, row_size), DT_PROP(node_id, col_size)) + +/** + * @brief Defines the common keyboard matrix support data from devicetree + * instance, specify row and col count. + * + * @param inst Instance. + * @param row_size The matrix row count. + * @param col_size The matrix column count. + */ +#define INPUT_KBD_MATRIX_DT_INST_DEFINE_ROW_COL(inst, row_size, col_size) \ + INPUT_KBD_MATRIX_DT_DEFINE_ROW_COL(DT_DRV_INST(inst), row_size, col_size) + +/** + * @brief Defines the common keyboard matrix support data from devicetree instance. + * + * @param inst Instance. + */ +#define INPUT_KBD_MATRIX_DT_INST_DEFINE(inst) \ + INPUT_KBD_MATRIX_DT_DEFINE(DT_DRV_INST(inst)) + +/** + * @brief Initialize common keyboard matrix config from devicetree, specify row and col count. + * + * @param node_id The devicetree node identifier. + * @param _api Pointer to a @ref input_kbd_matrix_api structure. + * @param _row_size The matrix row count. + * @param _col_size The matrix column count. + */ +#define INPUT_KBD_MATRIX_DT_COMMON_CONFIG_INIT_ROW_COL(node_id, _api, _row_size, _col_size) \ + { \ + .api = _api, \ + .row_size = _row_size, \ + .col_size = _col_size, \ + .poll_period_us = DT_PROP(node_id, poll_period_ms) * USEC_PER_MSEC, \ + .poll_timeout_ms = DT_PROP(node_id, poll_timeout_ms), \ + .debounce_down_ms = DT_PROP(node_id, debounce_down_ms), \ + .debounce_up_ms = DT_PROP(node_id, debounce_up_ms), \ + .settle_time_us = DT_PROP(node_id, settle_time_us), \ + .ghostkey_check = !DT_PROP(node_id, no_ghostkey_check), \ + \ + .matrix_stable_state = INPUT_KBD_MATRIX_DATA_NAME(node_id, stable_state), \ + .matrix_unstable_state = INPUT_KBD_MATRIX_DATA_NAME(node_id, unstable_state), \ + .matrix_previous_state = INPUT_KBD_MATRIX_DATA_NAME(node_id, previous_state), \ + .matrix_new_state = INPUT_KBD_MATRIX_DATA_NAME(node_id, new_state), \ + .scan_cycle_idx = INPUT_KBD_MATRIX_DATA_NAME(node_id, scan_cycle_idx), \ + } + +/** + * @brief Initialize common keyboard matrix config from devicetree. + * + * @param node_id The devicetree node identifier. + * @param api Pointer to a @ref input_kbd_matrix_api structure. + */ +#define INPUT_KBD_MATRIX_DT_COMMON_CONFIG_INIT(node_id, api) \ + INPUT_KBD_MATRIX_DT_COMMON_CONFIG_INIT_ROW_COL( \ + node_id, api, DT_PROP(node_id, row_size), DT_PROP(node_id, col_size)) + +/** + * @brief Initialize common keyboard matrix config from devicetree instance, + * specify row and col count. + * + * @param inst Instance. + * @param api Pointer to a @ref input_kbd_matrix_api structure. + * @param row_size The matrix row count. + * @param col_size The matrix column count. + */ +#define INPUT_KBD_MATRIX_DT_INST_COMMON_CONFIG_INIT_ROW_COL(inst, api, row_size, col_size) \ + INPUT_KBD_MATRIX_DT_COMMON_CONFIG_INIT_ROW_COL(DT_DRV_INST(inst), api, row_size, col_size) + +/** + * @brief Initialize common keyboard matrix config from devicetree instance. + * + * @param inst Instance. + * @param api Pointer to a @ref input_kbd_matrix_api structure. + */ +#define INPUT_KBD_MATRIX_DT_INST_COMMON_CONFIG_INIT(inst, api) \ + INPUT_KBD_MATRIX_DT_COMMON_CONFIG_INIT(DT_DRV_INST(inst), api) + +/** + * @brief Common keyboard matrix data. + * + * This structure **must** be placed first in the driver's data structure. + */ +struct input_kbd_matrix_common_data { + /* Track previous cycles, used for debouncing. */ + uint8_t scan_clk_cycle[INPUT_KBD_MATRIX_SCAN_OCURRENCES]; + uint8_t scan_cycles_idx; + + struct k_sem poll_lock; + + struct k_thread thread; + + K_KERNEL_STACK_MEMBER(thread_stack, + CONFIG_INPUT_KBD_MATRIX_THREAD_STACK_SIZE); +}; + +/** + * @brief Validate the offset of the common data structures. + * + * @param config Name of the config structure. + * @param data Name of the data structure. + */ +#define INPUT_KBD_STRUCT_CHECK(config, data) \ + BUILD_ASSERT(offsetof(config, common) == 0, \ + "struct input_kbd_matrix_common_config must be placed first"); \ + BUILD_ASSERT(offsetof(data, common) == 0, \ + "struct input_kbd_matrix_common_data must be placed first") + +/** + * @brief Start scanning the keyboard matrix + * + * Starts the keyboard matrix scanning cycle, this should be called in reaction + * of a press event, after the device has been put in detect mode. + * + * @param dev Keyboard matrix device instance. + */ +void input_kbd_matrix_poll_start(const struct device *dev); + +/** + * @brief Common function to initialize a keyboard matrix device at init time. + * + * This function must be called at the end of the device init function. + * + * @param dev Keyboard matrix device instance. + * + * @retval 0 If initialized successfully. + * @retval -errno Negative errno in case of failure. + */ +int input_kbd_matrix_common_init(const struct device *dev); + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_INPUT_KBD_MATRIX_H_ */ diff --git a/include/zephyr/internal/syscall_handler.h b/include/zephyr/internal/syscall_handler.h new file mode 100644 index 00000000000..f692c17dc1f --- /dev/null +++ b/include/zephyr/internal/syscall_handler.h @@ -0,0 +1,641 @@ +/* + * Copyright (c) 2017, Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_SYSCALL_HANDLER_H_ +#define ZEPHYR_INCLUDE_SYSCALL_HANDLER_H_ + +/** + * @brief User mode and Syscall APIs + * @defgroup syscall_apis User mode and Syscall APIs + * @ingroup internal_api + * @{ + */ + +#if defined(CONFIG_USERSPACE) || defined(__DOXYGEN__) + +#ifndef _ASMLANGUAGE +#include +#include +#include +#include +#include + +extern const _k_syscall_handler_t _k_syscall_table[K_SYSCALL_LIMIT]; + +enum _obj_init_check { + _OBJ_INIT_TRUE = 0, + _OBJ_INIT_FALSE = -1, + _OBJ_INIT_ANY = 1 +}; + +/** + * Return true if we are currently handling a system call from user mode + * + * Inside z_vrfy functions, we always know that we are handling + * a system call invoked from user context. + * + * However, some checks that are only relevant to user mode must + * instead be placed deeper within the implementation. This + * API is useful to conditionally make these checks. + * + * For performance reasons, whenever possible, checks should be placed + * in the relevant z_vrfy function since these are completely skipped + * when a syscall is invoked. + * + * This will return true only if we are handling a syscall for a + * user thread. If the system call was invoked from supervisor mode, + * or we are not handling a system call, this will return false. + * + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + * + * @return whether the current context is handling a syscall for a user + * mode thread + */ +static inline bool k_is_in_user_syscall(void) +{ + /* This gets set on entry to the syscall's generasted z_mrsh + * function and then cleared on exit. This code path is only + * encountered when a syscall is made from user mode, system + * calls from supervisor mode bypass everything directly to + * the implementation function. + */ + return !k_is_in_isr() && _current->syscall_frame != NULL; +} + +/** + * Ensure a system object is a valid object of the expected type + * + * Searches for the object and ensures that it is indeed an object + * of the expected type, that the caller has the right permissions on it, + * and that the object has been initialized. + * + * This function is intended to be called on the kernel-side system + * call handlers to validate kernel object pointers passed in from + * userspace. + * + * @param ko Kernel object metadata pointer, or NULL + * @param otype Expected type of the kernel object, or K_OBJ_ANY if type + * doesn't matter + * @param init Indicate whether the object needs to already be in initialized + * or uninitialized state, or that we don't care + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + * + * @return 0 If the object is valid + * -EBADF if not a valid object of the specified type + * -EPERM If the caller does not have permissions + * -EINVAL Object is not initialized + */ +int k_object_validate(struct k_object *ko, enum k_objects otype, + enum _obj_init_check init); + +/** + * Dump out error information on failed k_object_validate() call + * + * @param retval Return value from k_object_validate() + * @param obj Kernel object we were trying to verify + * @param ko If retval=-EPERM, struct k_object * that was looked up, or NULL + * @param otype Expected type of the kernel object + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + * + */ +void k_object_dump_error(int retval, const void *obj, + struct k_object *ko, enum k_objects otype); + +/** + * Kernel object validation function + * + * Retrieve metadata for a kernel object. This function is implemented in + * the gperf script footer, see gen_kobject_list.py + * + * @param obj Address of kernel object to get metadata + * @return Kernel object's metadata, or NULL if the parameter wasn't the + * memory address of a kernel object + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + * + */ +struct k_object *k_object_find(const void *obj); + +typedef void (*_wordlist_cb_func_t)(struct k_object *ko, void *context); + +/** + * Iterate over all the kernel object metadata in the system + * + * @param func function to run on each struct k_object + * @param context Context pointer to pass to each invocation + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + * + */ +void k_object_wordlist_foreach(_wordlist_cb_func_t func, void *context); + +/** + * Copy all kernel object permissions from the parent to the child + * + * @param parent Parent thread, to get permissions from + * @param child Child thread, to copy permissions to + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + * + */ +void k_thread_perms_inherit(struct k_thread *parent, struct k_thread *child); + +/** + * Grant a thread permission to a kernel object + * + * @param ko Kernel object metadata to update + * @param thread The thread to grant permission + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + * + */ +void k_thread_perms_set(struct k_object *ko, struct k_thread *thread); + +/** + * Revoke a thread's permission to a kernel object + * + * @param ko Kernel object metadata to update + * @param thread The thread to grant permission + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + * + */ +void k_thread_perms_clear(struct k_object *ko, struct k_thread *thread); + +/** + * Revoke access to all objects for the provided thread + * + * @note Unlike k_thread_perms_clear(), this function will not clear + * permissions on public objects. + * + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + * + * @param thread Thread object to revoke access + */ +void k_thread_perms_all_clear(struct k_thread *thread); + +/** + * Clear initialization state of a kernel object + * + * Intended for thread objects upon thread exit, or for other kernel objects + * that were released back to an object pool. + * + * @param obj Address of the kernel object + * + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +void k_object_uninit(const void *obj); + +/** + * Initialize and reset permissions to only access by the caller + * + * Intended for scenarios where objects are fetched from slab pools + * and may have had different permissions set during prior usage. + * + * This is only intended for pools of objects, where such objects are + * acquired and released to the pool. If an object has already been used, + * we do not want stale permission information hanging around, the object + * should only have permissions on the caller. Objects which are not + * managed by a pool-like mechanism should not use this API. + * + * The object will be marked as initialized and the calling thread + * granted access to it. + * + * @param obj Address of the kernel object + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +void k_object_recycle(const void *obj); + +/** + * @brief Obtain the size of a C string passed from user mode + * + * Given a C string pointer and a maximum size, obtain the true + * size of the string (not including the trailing NULL byte) just as + * if calling strnlen() on it, with the same semantics of strnlen() with + * respect to the return value and the maxlen parameter. + * + * Any memory protection faults triggered by the examination of the string + * will be safely handled and an error code returned. + * + * NOTE: Doesn't guarantee that user mode has actual access to this + * string, you will need to still do a K_SYSCALL_MEMORY_READ() + * with the obtained size value to guarantee this. + * + * @param src String to measure size of + * @param maxlen Maximum number of characters to examine + * @param err Pointer to int, filled in with -1 on memory error, 0 on + * success + * @return undefined on error, or strlen(src) if that is less than maxlen, or + * maxlen if there were no NULL terminating characters within the + * first maxlen bytes. + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +static inline size_t k_usermode_string_nlen(const char *src, size_t maxlen, + int *err) +{ + return arch_user_string_nlen(src, maxlen, err); +} + +/** + * @brief Copy data from userspace into a resource pool allocation + * + * Given a pointer and a size, allocate a similarly sized buffer in the + * caller's resource pool and copy all the data within it to the newly + * allocated buffer. This will need to be freed later with k_free(). + * + * Checks are done to ensure that the current thread would have read + * access to the provided buffer. + * + * @param src Source memory address + * @param size Size of the memory buffer + * @return An allocated buffer with the data copied within it, or NULL + * if some error condition occurred + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +void *k_usermode_alloc_from_copy(const void *src, size_t size); + +/** + * @brief Copy data from user mode + * + * Given a userspace pointer and a size, copies data from it into a provided + * destination buffer, performing checks to ensure that the caller would have + * appropriate access when in user mode. + * + * @param dst Destination memory buffer + * @param src Source memory buffer, in userspace + * @param size Number of bytes to copy + * @retval 0 On success + * @retval EFAULT On memory access error + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +int k_usermode_from_copy(void *dst, const void *src, size_t size); + +/** + * @brief Copy data to user mode + * + * Given a userspace pointer and a size, copies data to it from a provided + * source buffer, performing checks to ensure that the caller would have + * appropriate access when in user mode. + * + * @param dst Destination memory buffer, in userspace + * @param src Source memory buffer + * @param size Number of bytes to copy + * @retval 0 On success + * @retval EFAULT On memory access error + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +int k_usermode_to_copy(void *dst, const void *src, size_t size); + +/** + * @brief Copy a C string from userspace into a resource pool allocation + * + * Given a C string and maximum length, duplicate the string using an + * allocation from the calling thread's resource pool. This will need to be + * freed later with k_free(). + * + * Checks are performed to ensure that the string is valid memory and that + * the caller has access to it in user mode. + * + * @param src Source string pointer, in userspace + * @param maxlen Maximum size of the string including trailing NULL + * @return The duplicated string, or NULL if an error occurred. + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +char *k_usermode_string_alloc_copy(const char *src, size_t maxlen); + +/** + * @brief Copy a C string from userspace into a provided buffer + * + * Given a C string and maximum length, copy the string into a buffer. + * + * Checks are performed to ensure that the string is valid memory and that + * the caller has access to it in user mode. + * + * @param dst Destination buffer + * @param src Source string pointer, in userspace + * @param maxlen Maximum size of the string including trailing NULL + * @retval 0 on success + * @retval EINVAL if the source string is too long with respect + * to maxlen + * @retval EFAULT On memory access error + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +int k_usermode_string_copy(char *dst, const char *src, size_t maxlen); + +/** + * @brief Induce a kernel oops + * + * This macro can be used to induce a kernel oops which will kill the + * calling thread. + * + * @param expr Expression to be evaluated + * + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +#define K_OOPS(expr) \ + do { \ + if (expr) { \ + arch_syscall_oops(_current->syscall_frame); \ + } \ + } while (false) + +/** + * @brief Runtime expression check for system call arguments + * + * Used in handler functions to perform various runtime checks on arguments, + * and generate a kernel oops if anything is not expected, printing a custom + * message. + * + * @param expr Boolean expression to verify, a false result will trigger an + * oops + * @param fmt Printf-style format string (followed by appropriate variadic + * arguments) to print on verification failure + * @return False on success, True on failure + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +#define K_SYSCALL_VERIFY_MSG(expr, fmt, ...) ({ \ + bool expr_copy = !(expr); \ + if (expr_copy) { \ + TOOLCHAIN_IGNORE_WSHADOW_BEGIN \ + LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); \ + TOOLCHAIN_IGNORE_WSHADOW_END \ + LOG_ERR("syscall %s failed check: " fmt, \ + __func__, ##__VA_ARGS__); \ + } \ + expr_copy; }) + +/** + * @brief Runtime expression check for system call arguments + * + * Used in handler functions to perform various runtime checks on arguments, + * and generate a kernel oops if anything is not expected. + * + * @param expr Boolean expression to verify, a false result will trigger an + * oops. A stringified version of this expression will be printed. + * @return 0 on success, nonzero on failure + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +#define K_SYSCALL_VERIFY(expr) K_SYSCALL_VERIFY_MSG(expr, #expr) + +/** + * @brief Runtime check that a user thread has read and/or write permission to + * a memory area + * + * Checks that the particular memory area is readable and/or writeable by the + * currently running thread if the CPU was in user mode, and generates a kernel + * oops if it wasn't. Prevents userspace from getting the kernel to read and/or + * modify memory the thread does not have access to, or passing in garbage + * pointers that would crash/pagefault the kernel if dereferenced. + * + * @param ptr Memory area to examine + * @param size Size of the memory area + * @param write If the thread should be able to write to this memory, not just + * read it + * @return 0 on success, nonzero on failure + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +#define K_SYSCALL_MEMORY(ptr, size, write) \ + K_SYSCALL_VERIFY_MSG(arch_buffer_validate((void *)ptr, size, write) \ + == 0, \ + "Memory region %p (size %zu) %s access denied", \ + (void *)(ptr), (size_t)(size), \ + write ? "write" : "read") + +/** + * @brief Runtime check that a user thread has read permission to a memory area + * + * Checks that the particular memory area is readable by the currently running + * thread if the CPU was in user mode, and generates a kernel oops if it + * wasn't. Prevents userspace from getting the kernel to read memory the thread + * does not have access to, or passing in garbage pointers that would + * crash/pagefault the kernel if dereferenced. + * + * @param ptr Memory area to examine + * @param size Size of the memory area + * @return 0 on success, nonzero on failure + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +#define K_SYSCALL_MEMORY_READ(ptr, size) \ + K_SYSCALL_MEMORY(ptr, size, 0) + +/** + * @brief Runtime check that a user thread has write permission to a memory area + * + * Checks that the particular memory area is readable and writable by the + * currently running thread if the CPU was in user mode, and generates a kernel + * oops if it wasn't. Prevents userspace from getting the kernel to read or + * modify memory the thread does not have access to, or passing in garbage + * pointers that would crash/pagefault the kernel if dereferenced. + * + * @param ptr Memory area to examine + * @param size Size of the memory area + * @return 0 on success, nonzero on failure + * + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +#define K_SYSCALL_MEMORY_WRITE(ptr, size) \ + K_SYSCALL_MEMORY(ptr, size, 1) + +#define K_SYSCALL_MEMORY_ARRAY(ptr, nmemb, size, write) \ + ({ \ + size_t product; \ + K_SYSCALL_VERIFY_MSG(!size_mul_overflow((size_t)(nmemb), \ + (size_t)(size), \ + &product), \ + "%zux%zu array is too large", \ + (size_t)(nmemb), (size_t)(size)) || \ + K_SYSCALL_MEMORY(ptr, product, write); \ + }) + +/** + * @brief Validate user thread has read permission for sized array + * + * Used when the memory region is expressed in terms of number of elements and + * each element size, handles any overflow issues with computing the total + * array bounds. Otherwise see _SYSCALL_MEMORY_READ. + * + * @param ptr Memory area to examine + * @param nmemb Number of elements in the array + * @param size Size of each array element + * @return 0 on success, nonzero on failure + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +#define K_SYSCALL_MEMORY_ARRAY_READ(ptr, nmemb, size) \ + K_SYSCALL_MEMORY_ARRAY(ptr, nmemb, size, 0) + +/** + * @brief Validate user thread has read/write permission for sized array + * + * Used when the memory region is expressed in terms of number of elements and + * each element size, handles any overflow issues with computing the total + * array bounds. Otherwise see _SYSCALL_MEMORY_WRITE. + * + * @param ptr Memory area to examine + * @param nmemb Number of elements in the array + * @param size Size of each array element + * @return 0 on success, nonzero on failure + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +#define K_SYSCALL_MEMORY_ARRAY_WRITE(ptr, nmemb, size) \ + K_SYSCALL_MEMORY_ARRAY(ptr, nmemb, size, 1) + +static inline int k_object_validation_check(struct k_object *ko, + const void *obj, + enum k_objects otype, + enum _obj_init_check init) +{ + int ret; + + ret = k_object_validate(ko, otype, init); + +#ifdef CONFIG_LOG + if (ret != 0) { + k_object_dump_error(ret, obj, ko, otype); + } +#else + ARG_UNUSED(obj); +#endif + + return ret; +} + +#define K_SYSCALL_IS_OBJ(ptr, type, init) \ + K_SYSCALL_VERIFY_MSG(k_object_validation_check( \ + k_object_find((const void *)ptr), \ + (const void *)ptr, \ + type, init) == 0, "access denied") + +/** + * @brief Runtime check driver object pointer for presence of operation + * + * Validates if the driver object is capable of performing a certain operation. + * + * @param ptr Untrusted device instance object pointer + * @param api_name Name of the driver API struct (e.g. gpio_driver_api) + * @param op Driver operation (e.g. manage_callback) + * + * @return 0 on success, nonzero on failure + * + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +#define K_SYSCALL_DRIVER_OP(ptr, api_name, op) \ + ({ \ + struct api_name *__device__ = (struct api_name *) \ + ((const struct device *)ptr)->api; \ + K_SYSCALL_VERIFY_MSG(__device__->op != NULL, \ + "Operation %s not defined for driver " \ + "instance %p", \ + # op, __device__); \ + }) + +/** + * @brief Runtime check that device object is of a specific driver type + * + * Checks that the driver object passed in is initialized, the caller has + * correct permissions, and that it belongs to the specified driver + * subsystems. Additionally, all devices store a structure pointer of the + * driver's API. If this doesn't match the value provided, the check will fail. + * + * This provides an easy way to determine if a device object not only + * belongs to a particular subsystem, but is of a specific device driver + * implementation. Useful for defining out-of-subsystem system calls + * which are implemented for only one driver. + * + * @param _device Untrusted device pointer + * @param _dtype Expected kernel object type for the provided device pointer + * @param _api Expected driver API structure memory address + * @return 0 on success, nonzero on failure + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +#define K_SYSCALL_SPECIFIC_DRIVER(_device, _dtype, _api) \ + ({ \ + const struct device *_dev = (const struct device *)_device; \ + K_SYSCALL_OBJ(_dev, _dtype) || \ + K_SYSCALL_VERIFY_MSG(_dev->api == _api, \ + "API structure mismatch"); \ + }) + +/** + * @brief Runtime check kernel object pointer for non-init functions + * + * Calls k_object_validate and triggers a kernel oops if the check fails. + * For use in system call handlers which are not init functions; a fatal + * error will occur if the object is not initialized. + * + * @param ptr Untrusted kernel object pointer + * @param type Expected kernel object type + * @return 0 on success, nonzero on failure + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +#define K_SYSCALL_OBJ(ptr, type) \ + K_SYSCALL_IS_OBJ(ptr, type, _OBJ_INIT_TRUE) + +/** + * @brief Runtime check kernel object pointer for non-init functions + * + * See description of _SYSCALL_IS_OBJ. No initialization checks are done. + * Intended for init functions where objects may be re-initialized at will. + * + * @param ptr Untrusted kernel object pointer + * @param type Expected kernel object type + * @return 0 on success, nonzero on failure + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ + +#define K_SYSCALL_OBJ_INIT(ptr, type) \ + K_SYSCALL_IS_OBJ(ptr, type, _OBJ_INIT_ANY) + +/** + * @brief Runtime check kernel object pointer for non-init functions + * + * See description of _SYSCALL_IS_OBJ. Triggers a fatal error if the object is + * initialized. Intended for init functions where objects, once initialized, + * can only be re-used when their initialization state expires due to some + * other mechanism. + * + * @param ptr Untrusted kernel object pointer + * @param type Expected kernel object type + * @return 0 on success, nonzero on failure + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ + +#define K_SYSCALL_OBJ_NEVER_INIT(ptr, type) \ + K_SYSCALL_IS_OBJ(ptr, type, _OBJ_INIT_FALSE) + +#include + +#endif /* _ASMLANGUAGE */ + +#endif /* CONFIG_USERSPACE */ +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_SYSCALL_HANDLER_H_ */ diff --git a/include/zephyr/ipc/icmsg.h b/include/zephyr/ipc/icmsg.h index cdd1cb064d1..a3b43690cc4 100644 --- a/include/zephyr/ipc/icmsg.h +++ b/include/zephyr/ipc/icmsg.h @@ -12,8 +12,8 @@ #include #include #include +#include #include -#include #ifdef __cplusplus extern "C" { @@ -33,19 +33,14 @@ enum icmsg_state { }; struct icmsg_config_t { - uintptr_t tx_shm_addr; - uintptr_t rx_shm_addr; - size_t tx_shm_size; - size_t rx_shm_size; struct mbox_channel mbox_tx; struct mbox_channel mbox_rx; }; struct icmsg_data_t { /* Tx/Rx buffers. */ - struct spsc_pbuf *tx_ib; - struct spsc_pbuf *rx_ib; - atomic_t tx_buffer_state; + struct pbuf *tx_pb; + struct pbuf *rx_pb; #ifdef CONFIG_IPC_SERVICE_ICMSG_SHMEM_ACCESS_SYNC struct k_mutex tx_lock; #endif @@ -59,12 +54,6 @@ struct icmsg_data_t { struct k_work_delayable notify_work; struct k_work mbox_work; atomic_t state; - /* No-copy */ -#ifdef CONFIG_IPC_SERVICE_ICMSG_NOCOPY_RX - atomic_t rx_buffer_state; - const void *rx_buffer; - uint16_t rx_len; -#endif }; /** @brief Open an icmsg instance @@ -134,151 +123,6 @@ int icmsg_send(const struct icmsg_config_t *conf, struct icmsg_data_t *dev_data, const void *msg, size_t len); -/** @brief Get an empty TX buffer to be sent using @ref icmsg_send_nocopy - * - * This function can be called to get an empty TX buffer so that the - * application can directly put its data into the sending buffer avoiding copy - * performed by the icmsg library. - * - * It is the application responsibility to correctly fill the allocated TX - * buffer with data and passing correct parameters to @ref - * icmsg_send_nocopy function to perform data no-copy-send mechanism. - * - * The size parameter can be used to request a buffer with a certain size: - * - if the size can be accommodated the function returns no errors and the - * buffer is allocated - * - if the requested size is too big, the function returns -ENOMEM and the - * the buffer is not allocated. - * - if the requested size is '0' the buffer is allocated with the maximum - * allowed size. - * - * In all the cases on return the size parameter contains the maximum size for - * the returned buffer. - * - * When the function returns no errors, the buffer is intended as allocated - * and it is released under one of two conditions: (1) when sending the buffer - * using @ref icmsg_send_nocopy (and in this case the buffer is automatically - * released by the backend), (2) when using @ref icmsg_drop_tx_buffer on a - * buffer not sent. - * - * @param[in] conf Structure containing configuration parameters for the icmsg - * instance. - * @param[inout] dev_data Structure containing run-time data used by the icmsg - * instance. - * @param[out] data Pointer to the empty TX buffer. - * @param[inout] size Pointer to store the requested TX buffer size. If the - * function returns -ENOMEM, this parameter returns the - * maximum allowed size. - * - * @retval -ENOBUFS when there are no TX buffers available. - * @retval -EALREADY when a buffer was already claimed and not yet released. - * @retval -ENOMEM when the requested size is too big (and the size parameter - * contains the maximum allowed size). - * - * @retval 0 on success. - */ -int icmsg_get_tx_buffer(const struct icmsg_config_t *conf, - struct icmsg_data_t *dev_data, - void **data, size_t *size); - -/** @brief Drop and release a TX buffer - * - * Drop and release a TX buffer. It is possible to drop only TX buffers - * obtained by using @ref icmsg_get_tx_buffer. - * - * @param[in] conf Structure containing configuration parameters for the icmsg - * instance. - * @param[inout] dev_data Structure containing run-time data used by the icmsg - * instance. - * @param[in] data Pointer to the TX buffer. - * - * @retval -EALREADY when the buffer was already dropped. - * @retval -ENXIO when the buffer was not obtained using @ref - * ipc_service_get_tx_buffer - * - * @retval 0 on success. - */ -int icmsg_drop_tx_buffer(const struct icmsg_config_t *conf, - struct icmsg_data_t *dev_data, - const void *data); - -/** @brief Send a message from a buffer obtained by @ref icmsg_get_tx_buffer - * to the remote icmsg instance. - * - * This is equivalent to @ref icmsg_send but in this case the TX buffer must - * have been obtained by using @ref icmsg_get_tx_buffer. - * - * The API user has to take the responsibility for getting the TX buffer using - * @ref icmsg_get_tx_buffer and filling the TX buffer with the data. - * - * After the @ref icmsg_send_nocopy function is issued the TX buffer is no - * more owned by the sending task and must not be touched anymore unless the - * function fails and returns an error. - * - * If this function returns an error, @ref icmsg_drop_tx_buffer can be used - * to drop the TX buffer. - * - * @param[in] conf Structure containing configuration parameters for the icmsg - * instance. - * @param[inout] dev_data Structure containing run-time data used by the icmsg - * instance. - * @param[in] msg Pointer to a buffer containing data to send. - * @param[in] len Size of data in the @p msg buffer. - * - * - * @return Size of sent data on success. - * @retval -EBUSY when the instance has not finished handshake with the remote - * instance. - * @retval -ENODATA when the requested data to send is empty. - * @retval -EBADMSG when the requested data to send is too big. - * @retval -ENXIO when the buffer was not obtained using @ref - * ipc_service_get_tx_buffer - * @retval other errno codes from dependent modules. - */ -int icmsg_send_nocopy(const struct icmsg_config_t *conf, - struct icmsg_data_t *dev_data, - const void *msg, size_t len); - -#ifdef CONFIG_IPC_SERVICE_ICMSG_NOCOPY_RX -/** @brief Hold RX buffer to be used outside of the received callback. - * - * @param[in] conf Structure containing configuration parameters for the icmsg - * instance. - * @param[inout] dev_data Structure containing run-time data used by the icmsg - * instance. - * @param[in] data Pointer to the buffer to be held. - * - * @retval 0 on success. - * @retval -EBUSY when the instance has not finished handshake with the remote - * instance. - * @retval -EINVAL when the @p data argument does not point to a valid RX - * buffer. - * @retval -EALREADY when the buffer is already held. - */ -int icmsg_hold_rx_buffer(const struct icmsg_config_t *conf, - struct icmsg_data_t *dev_data, - const void *data); - -/** @brief Release RX buffer for future use. - * - * @param[in] conf Structure containing configuration parameters for the icmsg - * instance. - * @param[inout] dev_data Structure containing run-time data used by the icmsg - * instance. - * @param[in] data Pointer to the buffer to be released. - * - * @retval 0 on success. - * @retval -EBUSY when the instance has not finished handshake with the remote - * instance. - * @retval -EINVAL when the @p data argument does not point to a valid RX - * buffer. - * @retval -EALREADY when the buffer is not held. - */ -int icmsg_release_rx_buffer(const struct icmsg_config_t *conf, - struct icmsg_data_t *dev_data, - const void *data); -#endif - /** * @} */ diff --git a/include/zephyr/ipc/icmsg_me.h b/include/zephyr/ipc/icmsg_me.h index 554f5785ba8..9736b0148c6 100644 --- a/include/zephyr/ipc/icmsg_me.h +++ b/include/zephyr/ipc/icmsg_me.h @@ -247,118 +247,6 @@ int icmsg_me_send(const struct icmsg_config_t *conf, struct icmsg_me_data_t *data, icmsg_me_ept_id_t id, const void *msg, size_t len); -/** @brief Get an empty TX buffer to be sent using @ref icmsg_me_send_nocopy - * - * This function is a wrapper around @ref icmsg_get_tx_buffer aligning buffer - * size and pointers to fit header required by the multi-endpoint feature. - * It shares all properites and usage scenarios with @ref icmsg_get_tx_buffer. - * - * @param[in] conf Structure containing configuration parameters for the - & underlying icmsg instance. - * @param[inout] data Structure containing run-time data used by the icmsg_me - * instance. The structure is initialized with - * @ref icmsg_me_init and its content must be preserved - * while the icmsg_me instance is active. - * @param[out] buffer Pointer to the empty TX buffer. - * @param[inout] size Pointer to store the requested TX buffer size. If the - * function returns -ENOMEM, this parameter returns the - * maximum allowed size. - * @param[in] wait Timeout value to wait for a free buffer acceptable by - * the function caller. Only K_NO_WAIT is supported by icmsg. - * - * @retval 0 on success. - * @retval -ENOTSUP when requested unsupported @p wait timeout. - * @retval -ENOBUFS when there are no TX buffers available. - * @retval -ENOMEM when the requested size is too big (and the size parameter - * contains the maximum allowed size). - * @retval other errno codes from dependent modules. - */ -int icmsg_me_get_tx_buffer(const struct icmsg_config_t *conf, - struct icmsg_me_data_t *data, - void **buffer, uint32_t *size, k_timeout_t wait); - -/** @brief Drop and release a TX buffer - * - * This function is a wrapper around @ref icmsg_drop_tx_buffer aligning buffer - * pointer to fit header required by the multi-endpoint feature. This function - * shares all properties and usage scenarios with @ref icmsg_drop_tx_buffer. - * - * @param[in] conf Structure containing configuration parameters for the - * underlying icmsg instance. - * @param[inout] data Structure containing run-time data used by the icmsg_me - * instance. The structure is initialized with - * @ref icmsg_me_init and its content must be preserved - * while the icmsg_me instance is active. - * @param[in] buffer Pointer to the TX buffer obtained with - * @ref icmsg_me_get_tx_buffer. - * - * @retval 0 on success. - * @retval other errno codes from dependent modules. - */ -int icmsg_me_drop_tx_buffer(const struct icmsg_config_t *conf, - struct icmsg_me_data_t *data, - const void *buffer); - -/** @brief Send a message from a buffer obtained by @ref icmsg_me_get_tx_buffer - * to the remote icmsg_me instance. - * - * This function is a wrapper around @ref icmsg_send_nocopy aligning buffer - * size and pointer to fit header required by the multi-endpoint feature. This - * function shares all properties and usage scenarios with - * @ref icmsg_send_nocopy. - * - * @param[in] conf Structure containing configuration parameters for the - * underlying icmsg instance. - * @param[inout] data Structure containing run-time data used by the icmsg_me - * instance. The structure is initialized with - * @ref icmsg_me_init and its content must be preserved - * while the icmsg_me instance is active. - * @param[in] id Id of the endpoint to use. - * @param[in] msg Pointer to a buffer containing data to send. - * @param[in] len Size of data in the @p msg buffer. - * - * - * @return Size of sent data on success. - * @retval other errno codes from dependent modules. - */ -int icmsg_me_send_nocopy(const struct icmsg_config_t *conf, - struct icmsg_me_data_t *data, icmsg_me_ept_id_t id, - const void *msg, size_t len); - -#ifdef CONFIG_IPC_SERVICE_ICMSG_ME_NOCOPY_RX -/** @brief Hold RX buffer to be used outside of the received callback. - * - * @param[in] conf Structure containing configuration parameters for the - * underlying icmsg instance. - * @param[inout] data Structure containing run-time data used by the icmsg_me - * instance. The structure is initialized with - * @ref icmsg_me_init and its content must be preserved - * while the icmsg_me instance is active. - * @param[in] buffer Pointer to the buffer to be held. - * - * @retval 0 on success. - * @retval other errno codes from dependent modules. - */ -int icmsg_me_hold_rx_buffer(const struct icmsg_config_t *conf, - struct icmsg_me_data_t *data, void *buffer); - -/** @brief Release RX buffer for future use. - * - * @param[in] conf Structure containing configuration parameters for the - * underlying icmsg instance. - * @param[inout] data Structure containing run-time data used by the icmsg_me - * instance. The structure is initialized with - * @ref icmsg_me_init and its content must be preserved - * while the icmsg_me instance is active. - * @param[in] buffer Pointer to the buffer to be released. - * - * @retval 0 on success. - * @retval other errno codes from dependent modules. - */ -int icmsg_me_release_rx_buffer(const struct icmsg_config_t *conf, - struct icmsg_me_data_t *data, void *buffer); -#endif /* CONFIG_IPC_SERVICE_ICMSG_ME_NOCOPY_RX */ - /** * @} */ diff --git a/include/zephyr/ipc/pbuf.h b/include/zephyr/ipc/pbuf.h new file mode 100644 index 00000000000..7e61950c808 --- /dev/null +++ b/include/zephyr/ipc/pbuf.h @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_IPC_PBUF_H_ +#define ZEPHYR_INCLUDE_IPC_PBUF_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Packed buffer API + * @defgroup pbuf Packed Buffer API + * @ingroup ipc + * @{ + */ + +/** @brief Size of packet length field. */ +#define PBUF_PACKET_LEN_SZ sizeof(uint32_t) + +/* Amount of data that is left unused to distinguish between empty and full. */ +#define _PBUF_IDX_SIZE sizeof(uint32_t) + +/* Minimal length of the data field in the buffer to store the smalest packet + * possible. + * (+1) for at least one byte of data. + * (+_PBUF_IDX_SIZE) to distinguish buffer full and buffer empty. + * Rounded up to keep wr/rd indexes pointing to aligned address. + */ +#define _PBUF_MIN_DATA_LEN ROUND_UP(PBUF_PACKET_LEN_SZ + 1 + _PBUF_IDX_SIZE, _PBUF_IDX_SIZE) + +/** @brief Control block of packet buffer. + * + * The structure contains configuration data. + */ +struct pbuf_cfg { + volatile uint32_t *rd_idx_loc; /* Address of the variable holding + * index value of the first valid byte + * in data[]. + */ + volatile uint32_t *wr_idx_loc; /* Address of the variable holding + * index value of the first free byte + * in data[]. + */ + uint32_t dcache_alignment; /* CPU data cache line size in bytes. + * Used for validation - TODO: To be + * replaced by flags. + */ + uint32_t len; /* Length of data[] in bytes. */ + uint8_t *data_loc; /* Location of the data[]. */ +}; + +/** + * @brief Data block of the packed buffer. + * + * The structure contains local copies of wr and rd indexes used by writer and + * reader respecitvely. + */ +struct pbuf_data { + volatile uint32_t wr_idx; /* Index of the first holding first + * free byte in data[]. Used for + * writing. + */ + volatile uint32_t rd_idx; /* Index of the first holding first + * valid byte in data[]. Used for + * reading. + */ +}; + + +/** + * @brief Scure packed buffer. + * + * The packet buffer implements lightweight unidirectional packet + * buffer with read/write semantics on top of a memory region shared + * by the reader and writer. It embeds cache and memory barrier management to + * ensure correct data access. + * + * This structure supports single writer and reader. Data stored in the buffer + * is encapsulated to a message (with length header). The read/write API is + * written in a way to protect the data from being corrupted. + */ +struct pbuf { + const struct pbuf_cfg *const cfg; /* Configuration of the + * buffer. + */ + struct pbuf_data data; /* Data used to read and write + * to the buffer + */ +}; + +/** + * @brief Macro for configuration initialization. + * + * It is recommended to use this macro to initialize packed buffer + * configuration. + * + * @param mem_addr Memory address for pbuf. + * @param size Size of the memory. + * @param dcache_align Data cache alignment. + */ +#define PBUF_CFG_INIT(mem_addr, size, dcache_align) \ +{ \ + .rd_idx_loc = (uint32_t *)(mem_addr), \ + .wr_idx_loc = (uint32_t *)((uint8_t *)(mem_addr) + \ + MAX(dcache_align, _PBUF_IDX_SIZE)), \ + .data_loc = (uint8_t *)((uint8_t *)(mem_addr) + \ + MAX(dcache_align, _PBUF_IDX_SIZE) + _PBUF_IDX_SIZE), \ + .len = (uint32_t)((uint32_t)(size) - MAX(dcache_align, _PBUF_IDX_SIZE) - \ + _PBUF_IDX_SIZE), \ + .dcache_alignment = (dcache_align), \ +} + +/** + * @brief Macro calculates memory overhead taken by the header in shared memory. + * + * It contains the read index, write index and padding. + * + * @param dcache_align Data cache alignment. + */ +#define PBUF_HEADER_OVERHEAD(dcache_align) \ + (MAX(dcache_align, _PBUF_IDX_SIZE) + _PBUF_IDX_SIZE) + +/** + * @brief Statically define and initialize pbuf. + * + * @param name Name of the pbuf. + * @param mem_addr Memory address for pbuf. + * @param size Size of the memory. + * @param dcache_align Data cache line size. + */ +#define PBUF_DEFINE(name, mem_addr, size, dcache_align) \ + BUILD_ASSERT(dcache_align >= 0, \ + "Cache line size must be non negative."); \ + BUILD_ASSERT((size) > 0 && IS_PTR_ALIGNED_BYTES(size, _PBUF_IDX_SIZE), \ + "Incorrect size."); \ + BUILD_ASSERT(IS_PTR_ALIGNED_BYTES(mem_addr, MAX(dcache_align, _PBUF_IDX_SIZE)), \ + "Misaligned memory."); \ + BUILD_ASSERT(size >= (MAX(dcache_align, _PBUF_IDX_SIZE) + _PBUF_IDX_SIZE + \ + _PBUF_MIN_DATA_LEN), "Insufficient size."); \ + \ + static const struct pbuf_cfg cfg_##name = \ + PBUF_CFG_INIT(mem_addr, size, dcache_align); \ + static struct pbuf name = { \ + .cfg = &cfg_##name, \ + } + +/** + * @brief Initialize the packet buffer. + * + * This function initializes the packet buffer based on provided configuration. + * If the configuration is incorrect, the function will return error. + * + * It is recommended to use PBUF_DEFINE macro for build time initialization. + * + * @param pb Pointer to the packed buffer containing + * configuration and data. Configuration has to be + * fixed before the initialization. + * @retval 0 on success. + * @retval -EINVAL when the input parameter is incorrect. + */ +int pbuf_init(struct pbuf *pb); + +/** + * @brief Write specified amount of data to the packet buffer. + * + * This function call writes specified amount of data to the packet buffer if + * the buffer will fit the data. + * + * @param pb A buffer to which to write. + * @param buf Pointer to the data to be written to the buffer. + * @param len Number of bytes to be written to the buffer. Must be positive. + * @retval int Number of bytes written, negative error code on fail. + * -EINVAL, if any of input parameter is incorrect. + * -ENOMEM, if len is bigger than the buffer can fit. + */ + +int pbuf_write(struct pbuf *pb, const char *buf, uint16_t len); + +/** + * @brief Read specified amount of data from the packet buffer. + * + * Single read allows to read the message send by the single write. + * The provided %p buf must be big enough to store the whole message. + * + * @param pb A buffer from which data will be read. + * @param buf Data pointer to which read data will be written. + * If NULL, len of stored message is returned. + * @param len Number of bytes to be read from the buffer. + * @retval int Bytes read, negative error code on fail. + * Bytes to be read, if buf == NULL. + * -EINVAL, if any of input parameter is incorrect. + * -ENOMEM, if message can not fit in provided buf. + * -EAGAIN, if not whole message is ready yet. + */ +int pbuf_read(struct pbuf *pb, char *buf, uint16_t len); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_IPC_PBUF_H_ */ diff --git a/include/zephyr/irq.h b/include/zephyr/irq.h index d6229f69ea8..1fa559edccd 100644 --- a/include/zephyr/irq.h +++ b/include/zephyr/irq.h @@ -70,6 +70,31 @@ irq_connect_dynamic(unsigned int irq, unsigned int priority, flags); } +/** + * Disconnect a dynamic interrupt. + * + * Use this in conjunction with shared interrupts to remove a routine/parameter + * pair from the list of clients using the same interrupt line. If the interrupt + * is not being shared then the associated _sw_isr_table entry will be replaced + * by (NULL, z_irq_spurious) (default entry). + * + * @param irq IRQ line number + * @param priority Interrupt priority + * @param routine Interrupt service routine + * @param parameter ISR parameter + * @param flags Arch-specific IRQ configuration flags + * + * @return 0 in case of success, negative value otherwise + */ +static inline int +irq_disconnect_dynamic(unsigned int irq, unsigned int priority, + void (*routine)(const void *parameter), + const void *parameter, uint32_t flags) +{ + return arch_irq_disconnect_dynamic(irq, priority, routine, + parameter, flags); +} + /** * @brief Initialize a 'direct' interrupt handler. * @@ -255,137 +280,6 @@ void z_smp_global_unlock(unsigned int key); #define irq_unlock(key) arch_irq_unlock(key) #endif -/** - * @brief Return IRQ level - * This routine returns the interrupt level number of the provided interrupt. - * - * @param irq IRQ number in its zephyr format - * - * @return 1 if IRQ level 1, 2 if IRQ level 2, 3 if IRQ level 3 - */ -static inline unsigned int irq_get_level(unsigned int irq) -{ - const uint32_t mask2 = BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS) << - CONFIG_1ST_LEVEL_INTERRUPT_BITS; - const uint32_t mask3 = BIT_MASK(CONFIG_3RD_LEVEL_INTERRUPT_BITS) << - (CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS); - - if (IS_ENABLED(CONFIG_3RD_LEVEL_INTERRUPTS) && (irq & mask3) != 0) { - return 3; - } - - if (IS_ENABLED(CONFIG_2ND_LEVEL_INTERRUPTS) && (irq & mask2) != 0) { - return 2; - } - - return 1; -} - -#if defined(CONFIG_2ND_LEVEL_INTERRUPTS) -/** - * @brief Return the 2nd level interrupt number - * - * This routine returns the second level irq number of the zephyr irq - * number passed in - * - * @param irq IRQ number in its zephyr format - * - * @return 2nd level IRQ number - */ -static inline unsigned int irq_from_level_2(unsigned int irq) -{ -#if defined(CONFIG_3RD_LEVEL_INTERRUPTS) - return ((irq >> CONFIG_1ST_LEVEL_INTERRUPT_BITS) & - BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS)) - 1; -#else - return (irq >> CONFIG_1ST_LEVEL_INTERRUPT_BITS) - 1; -#endif -} - -/** - * @brief Converts irq from level 1 to level 2 format - * - * - * This routine converts the input into the level 2 irq number format - * - * @note Values >= 0xFF are invalid - * - * @param irq IRQ number in its zephyr format - * - * @return 2nd level IRQ number - */ -static inline unsigned int irq_to_level_2(unsigned int irq) -{ - return (irq + 1) << CONFIG_1ST_LEVEL_INTERRUPT_BITS; -} - -/** - * @brief Returns the parent IRQ of the level 2 raw IRQ number - * - * - * The parent of a 2nd level interrupt is in the 1st byte - * - * @param irq IRQ number in its zephyr format - * - * @return 2nd level IRQ parent - */ -static inline unsigned int irq_parent_level_2(unsigned int irq) -{ - return irq & BIT_MASK(CONFIG_1ST_LEVEL_INTERRUPT_BITS); -} -#endif - -#ifdef CONFIG_3RD_LEVEL_INTERRUPTS -/** - * @brief Return the 3rd level interrupt number - * - * - * This routine returns the third level irq number of the zephyr irq - * number passed in - * - * @param irq IRQ number in its zephyr format - * - * @return 3rd level IRQ number - */ -static inline unsigned int irq_from_level_3(unsigned int irq) -{ - return (irq >> (CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS)) - 1; -} - -/** - * @brief Converts irq from level 1 to level 3 format - * - * - * This routine converts the input into the level 3 irq number format - * - * @note Values >= 0xFF are invalid - * - * @param irq IRQ number in its zephyr format - * - * @return 3rd level IRQ number - */ -static inline unsigned int irq_to_level_3(unsigned int irq) -{ - return (irq + 1) << (CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS); -} - -/** - * @brief Returns the parent IRQ of the level 3 raw IRQ number - * - * - * The parent of a 3rd level interrupt is in the 2nd byte - * - * @param irq IRQ number in its zephyr format - * - * @return 3rd level IRQ parent - */ -static inline unsigned int irq_parent_level_3(unsigned int irq) -{ - return (irq >> CONFIG_1ST_LEVEL_INTERRUPT_BITS) & - BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS); -} -#endif - /** * @brief Enable an IRQ. * diff --git a/include/zephyr/irq_multilevel.h b/include/zephyr/irq_multilevel.h new file mode 100644 index 00000000000..3a2b5116602 --- /dev/null +++ b/include/zephyr/irq_multilevel.h @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Public interface for multi-level interrupts + */ +#ifndef ZEPHYR_INCLUDE_IRQ_MULTILEVEL_H_ +#define ZEPHYR_INCLUDE_IRQ_MULTILEVEL_H_ + +#ifndef _ASMLANGUAGE +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Return IRQ level + * This routine returns the interrupt level number of the provided interrupt. + * + * @param irq IRQ number in its zephyr format + * + * @return 1 if IRQ level 1, 2 if IRQ level 2, 3 if IRQ level 3 + */ +static inline unsigned int irq_get_level(unsigned int irq) +{ + const uint32_t mask2 = BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS) << + CONFIG_1ST_LEVEL_INTERRUPT_BITS; + const uint32_t mask3 = BIT_MASK(CONFIG_3RD_LEVEL_INTERRUPT_BITS) << + (CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS); + + if (IS_ENABLED(CONFIG_3RD_LEVEL_INTERRUPTS) && (irq & mask3) != 0) { + return 3; + } + + if (IS_ENABLED(CONFIG_2ND_LEVEL_INTERRUPTS) && (irq & mask2) != 0) { + return 2; + } + + return 1; +} + +/** + * @brief Return the 2nd level interrupt number + * + * This routine returns the second level irq number of the zephyr irq + * number passed in + * + * @param irq IRQ number in its zephyr format + * + * @return 2nd level IRQ number + */ +static inline unsigned int irq_from_level_2(unsigned int irq) +{ + if (IS_ENABLED(CONFIG_3RD_LEVEL_INTERRUPTS)) { + return ((irq >> CONFIG_1ST_LEVEL_INTERRUPT_BITS) & + BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS)) - 1; + } else { + return (irq >> CONFIG_1ST_LEVEL_INTERRUPT_BITS) - 1; + } +} + +/** + * @brief Preprocessor macro to convert `irq` from level 1 to level 2 format + * + * @param irq IRQ number in its zephyr format + * + * @return 2nd level IRQ number + */ +#define IRQ_TO_L2(irq) ((irq + 1) << CONFIG_1ST_LEVEL_INTERRUPT_BITS) + +/** + * @brief Converts irq from level 1 to level 2 format + * + * + * This routine converts the input into the level 2 irq number format + * + * @note Values >= 0xFF are invalid + * + * @param irq IRQ number in its zephyr format + * + * @return 2nd level IRQ number + */ +static inline unsigned int irq_to_level_2(unsigned int irq) +{ + return IRQ_TO_L2(irq); +} + +/** + * @brief Returns the parent IRQ of the level 2 raw IRQ number + * + * + * The parent of a 2nd level interrupt is in the 1st byte + * + * @param irq IRQ number in its zephyr format + * + * @return 2nd level IRQ parent + */ +static inline unsigned int irq_parent_level_2(unsigned int irq) +{ + return irq & BIT_MASK(CONFIG_1ST_LEVEL_INTERRUPT_BITS); +} + +/** + * @brief Return the 3rd level interrupt number + * + * + * This routine returns the third level irq number of the zephyr irq + * number passed in + * + * @param irq IRQ number in its zephyr format + * + * @return 3rd level IRQ number + */ +static inline unsigned int irq_from_level_3(unsigned int irq) +{ + return (irq >> (CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS)) - 1; +} + +/** + * @brief Preprocessor macro to convert `irq` from level 1 to level 3 format + * + * @param irq IRQ number in its zephyr format + * + * @return 3rd level IRQ number + */ +#define IRQ_TO_L3(irq) \ + ((irq + 1) << (CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS)) + +/** + * @brief Converts irq from level 1 to level 3 format + * + * + * This routine converts the input into the level 3 irq number format + * + * @note Values >= 0xFF are invalid + * + * @param irq IRQ number in its zephyr format + * + * @return 3rd level IRQ number + */ +static inline unsigned int irq_to_level_3(unsigned int irq) +{ + return IRQ_TO_L3(irq); +} + +/** + * @brief Returns the parent IRQ of the level 3 raw IRQ number + * + * + * The parent of a 3rd level interrupt is in the 2nd byte + * + * @param irq IRQ number in its zephyr format + * + * @return 3rd level IRQ parent + */ +static inline unsigned int irq_parent_level_3(unsigned int irq) +{ + return (irq >> CONFIG_1ST_LEVEL_INTERRUPT_BITS) & + BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS); +} + +#ifdef __cplusplus +} +#endif + +#endif /* _ASMLANGUAGE */ +#endif /* ZEPHYR_INCLUDE_IRQ_MULTILEVEL_H_ */ diff --git a/include/zephyr/kernel.h b/include/zephyr/kernel.h index e847ee272be..fac7df01904 100644 --- a/include/zephyr/kernel.h +++ b/include/zephyr/kernel.h @@ -58,12 +58,12 @@ BUILD_ASSERT(sizeof(intptr_t) == sizeof(long)); #define K_LOWEST_APPLICATION_THREAD_PRIO (K_LOWEST_THREAD_PRIO - 1) #ifdef CONFIG_POLL -#define _POLL_EVENT_OBJ_INIT(obj) \ +#define Z_POLL_EVENT_OBJ_INIT(obj) \ .poll_events = SYS_DLIST_STATIC_INIT(&obj.poll_events), -#define _POLL_EVENT sys_dlist_t poll_events +#define Z_DECL_POLL_EVENT sys_dlist_t poll_events; #else -#define _POLL_EVENT_OBJ_INIT(obj) -#define _POLL_EVENT +#define Z_POLL_EVENT_OBJ_INIT(obj) +#define Z_DECL_POLL_EVENT #endif struct k_thread; @@ -118,7 +118,7 @@ typedef void (*k_thread_user_cb_t)(const struct k_thread *thread, * list which means creation of new threads and terminations of existing * threads are blocked until this API returns. */ -extern void k_thread_foreach(k_thread_user_cb_t user_cb, void *user_data); +void k_thread_foreach(k_thread_user_cb_t user_cb, void *user_data); /** * @brief Iterate over all the threads in the system without locking. @@ -147,7 +147,7 @@ extern void k_thread_foreach(k_thread_user_cb_t user_cb, void *user_data); * Do not reuse the memory that was occupied by k_thread structure of aborted * task if it was aborted after this function was called in any context. */ -extern void k_thread_foreach_unlocked( +void k_thread_foreach_unlocked( k_thread_user_cb_t user_cb, void *user_data); /** @} */ @@ -371,7 +371,7 @@ __syscall k_tid_t k_thread_create(struct k_thread *new_thread, * @param p2 2nd entry point parameter * @param p3 3rd entry point parameter */ -extern FUNC_NORETURN void k_thread_user_mode_enter(k_thread_entry_t entry, +FUNC_NORETURN void k_thread_user_mode_enter(k_thread_entry_t entry, void *p1, void *p2, void *p3); @@ -440,7 +440,7 @@ __syscall int k_thread_stack_space_get(const struct k_thread *thread, /** * @brief Assign the system heap as a thread's resource pool * - * Similar to z_thread_heap_assign(), but the thread will use + * Similar to k_thread_heap_assign(), but the thread will use * the kernel heap to draw memory. * * Use with caution, as a malicious thread could perform DoS attacks on the @@ -531,6 +531,10 @@ __syscall int32_t k_usleep(int32_t us); * k_sleep(). For example k_busy_wait(1000) may take slightly more or * less time than k_sleep(K_MSEC(1)), with the offset dependent on * clock tolerances. + * + * @note In case when @kconfig{CONFIG_SYSTEM_CLOCK_SLOPPY_IDLE} and + * @kconfig{CONFIG_PM} options are enabled, this function may not work. + * The timer/clock used for delay processing may be disabled/inactive. */ __syscall void k_busy_wait(uint32_t usec_to_wait); @@ -568,19 +572,20 @@ __syscall void k_yield(void); __syscall void k_wakeup(k_tid_t thread); /** - * @brief Get thread ID of the current thread. + * @brief Query thread ID of the current thread. * * This unconditionally queries the kernel via a system call. * + * @note Use k_current_get() unless absolutely sure this is necessary. + * This should only be used directly where the thread local + * variable cannot be used or may contain invalid values + * if thread local storage (TLS) is enabled. If TLS is not + * enabled, this is the same as k_current_get(). + * * @return ID of current thread. */ __attribute_const__ -__syscall k_tid_t z_current_get(void); - -#ifdef CONFIG_THREAD_LOCAL_STORAGE -/* Thread-local cache of current thread ID, set in z_thread_entry() */ -extern __thread k_tid_t z_tls_current; -#endif +__syscall k_tid_t k_sched_current_thread_query(void); /** * @brief Get thread ID of the current thread. @@ -592,9 +597,12 @@ __attribute_const__ static inline k_tid_t k_current_get(void) { #ifdef CONFIG_THREAD_LOCAL_STORAGE + /* Thread-local cache of current thread ID, set in z_thread_entry() */ + extern __thread k_tid_t z_tls_current; + return z_tls_current; #else - return z_current_get(); + return k_sched_current_thread_query(); #endif } @@ -613,11 +621,7 @@ static inline k_tid_t k_current_get(void) * this is done via blocking the caller (in the same manner as * k_thread_join()), but in interrupt context on SMP systems the * implementation is required to spin for threads that are running on - * other CPUs. Note that as specified, this means that on SMP - * platforms it is possible for application code to create a deadlock - * condition by simultaneously aborting a cycle of threads using at - * least one termination from interrupt context. Zephyr cannot detect - * all such conditions. + * other CPUs. * * @param thread ID of thread to abort. */ @@ -635,8 +639,8 @@ __syscall void k_thread_abort(k_tid_t thread); */ __syscall void k_thread_start(k_tid_t thread); -extern k_ticks_t z_timeout_expires(const struct _timeout *timeout); -extern k_ticks_t z_timeout_remaining(const struct _timeout *timeout); +k_ticks_t z_timeout_expires(const struct _timeout *timeout); +k_ticks_t z_timeout_remaining(const struct _timeout *timeout); #ifdef CONFIG_SYS_CLOCK_EXISTS @@ -676,9 +680,6 @@ static inline k_ticks_t z_impl_k_thread_timeout_remaining_ticks( * @cond INTERNAL_HIDDEN */ -/* timeout has timed out and is not on _timeout_q anymore */ -#define _EXPIRED (-2) - struct _static_thread_data { struct k_thread *init_thread; k_thread_stack_t *init_stack; @@ -689,10 +690,22 @@ struct _static_thread_data { void *init_p3; int init_prio; uint32_t init_options; - int32_t init_delay; const char *init_name; +#ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME + int32_t init_delay_ms; +#else + k_timeout_t init_delay; +#endif }; +#ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME +#define Z_THREAD_INIT_DELAY_INITIALIZER(ms) .init_delay_ms = (ms) +#define Z_THREAD_INIT_DELAY(thread) SYS_TIMEOUT_MS((thread)->init_delay_ms) +#else +#define Z_THREAD_INIT_DELAY_INITIALIZER(ms) .init_delay = SYS_TIMEOUT_MS(ms) +#define Z_THREAD_INIT_DELAY(thread) (thread)->init_delay +#endif + #define Z_THREAD_INITIALIZER(thread, stack, stack_size, \ entry, p1, p2, p3, \ prio, options, delay, tname) \ @@ -706,8 +719,8 @@ struct _static_thread_data { .init_p3 = (void *)p3, \ .init_prio = (prio), \ .init_options = (options), \ - .init_delay = (delay), \ .init_name = STRINGIFY(tname), \ + Z_THREAD_INIT_DELAY_INITIALIZER(delay) \ } /* @@ -862,7 +875,7 @@ __syscall void k_thread_priority_set(k_tid_t thread, int prio); * may result in scheduled threads running in an incorrect deadline * order. * - * @note Despite the API naming, the scheduler makes no guarantees the + * @note Despite the API naming, the scheduler makes no guarantees * the thread WILL be scheduled within that deadline, nor does it take * extra metadata (like e.g. the "runtime" and "period" parameters in * Linux sched_setattr()) that allows the kernel to validate the @@ -961,6 +974,11 @@ int k_thread_cpu_pin(k_tid_t thread, int cpu); * will be canceled. On resume, the thread will begin running * immediately and return from the blocked call. * + * When the target thread is active on another CPU, the caller will block until + * the target thread is halted (suspended or aborted). But if the caller is in + * an interrupt context, it will spin waiting for that target thread active on + * another CPU to halt. + * * If @a thread is already suspended, the routine has no effect. * * @param thread ID of thread to suspend. @@ -1005,7 +1023,7 @@ __syscall void k_thread_resume(k_tid_t thread); * @param slice Maximum time slice length (in milliseconds). * @param prio Highest thread priority level eligible for time slicing. */ -extern void k_sched_time_slice_set(int32_t slice, int prio); +void k_sched_time_slice_set(int32_t slice, int prio); /** * @brief Set thread time slice @@ -1066,7 +1084,7 @@ void k_thread_time_slice_set(struct k_thread *th, int32_t slice_ticks, * @return false if invoked by a thread. * @return true if invoked by an ISR. */ -extern bool k_is_in_isr(void); +bool k_is_in_isr(void); /** * @brief Determine if code is running in a preemptible thread. @@ -1138,7 +1156,7 @@ static inline bool k_is_pre_kernel(void) * In general this is a historical API not well-suited to modern * applications, use with care. */ -extern void k_sched_lock(void); +void k_sched_lock(void); /** * @brief Unlock the scheduler. @@ -1147,7 +1165,7 @@ extern void k_sched_lock(void); * A thread must call the routine once for each time it called k_sched_lock() * before the thread becomes preemptible. */ -extern void k_sched_unlock(void); +void k_sched_unlock(void); /** * @brief Set current thread's custom data. @@ -1462,6 +1480,10 @@ struct k_timer { void *user_data; SYS_PORT_TRACING_TRACKING_FIELD(k_timer) + +#ifdef CONFIG_OBJ_CORE_TIMER + struct k_obj_core obj_core; +#endif }; #define Z_TIMER_INITIALIZER(obj, expiry, stop) \ @@ -1540,7 +1562,7 @@ typedef void (*k_timer_stop_t)(struct k_timer *timer); * @param expiry_fn Function to invoke each time the timer expires. * @param stop_fn Function to invoke if the timer is stopped while running. */ -extern void k_timer_init(struct k_timer *timer, +void k_timer_init(struct k_timer *timer, k_timer_expiry_t expiry_fn, k_timer_stop_t stop_fn); @@ -1822,30 +1844,28 @@ static inline uint64_t k_cycle_get_64(void) * @} */ -/** - * @cond INTERNAL_HIDDEN - */ - struct k_queue { sys_sflist_t data_q; struct k_spinlock lock; _wait_q_t wait_q; - _POLL_EVENT; + Z_DECL_POLL_EVENT SYS_PORT_TRACING_TRACKING_FIELD(k_queue) }; +/** + * @cond INTERNAL_HIDDEN + */ + #define Z_QUEUE_INITIALIZER(obj) \ { \ .data_q = SYS_SFLIST_STATIC_INIT(&obj.data_q), \ .lock = { }, \ .wait_q = Z_WAIT_Q_INIT(&obj.wait_q), \ - _POLL_EVENT_OBJ_INIT(obj) \ + Z_POLL_EVENT_OBJ_INIT(obj) \ } -extern void *z_queue_node_peek(sys_sfnode_t *node, bool needs_free); - /** * INTERNAL_HIDDEN @endcond */ @@ -1892,7 +1912,7 @@ __syscall void k_queue_cancel_wait(struct k_queue *queue); * @param queue Address of the queue. * @param data Address of the data item. */ -extern void k_queue_append(struct k_queue *queue, void *data); +void k_queue_append(struct k_queue *queue, void *data); /** * @brief Append an element to a queue. @@ -1924,7 +1944,7 @@ __syscall int32_t k_queue_alloc_append(struct k_queue *queue, void *data); * @param queue Address of the queue. * @param data Address of the data item. */ -extern void k_queue_prepend(struct k_queue *queue, void *data); +void k_queue_prepend(struct k_queue *queue, void *data); /** * @brief Prepend an element to a queue. @@ -1957,7 +1977,7 @@ __syscall int32_t k_queue_alloc_prepend(struct k_queue *queue, void *data); * @param prev Address of the previous data item. * @param data Address of the data item. */ -extern void k_queue_insert(struct k_queue *queue, void *prev, void *data); +void k_queue_insert(struct k_queue *queue, void *prev, void *data); /** * @brief Atomically append a list of elements to a queue. @@ -1977,7 +1997,7 @@ extern void k_queue_insert(struct k_queue *queue, void *prev, void *data); * @retval -EINVAL on invalid supplied data * */ -extern int k_queue_append_list(struct k_queue *queue, void *head, void *tail); +int k_queue_append_list(struct k_queue *queue, void *head, void *tail); /** * @brief Atomically add a list of elements to a queue. @@ -1994,7 +2014,7 @@ extern int k_queue_append_list(struct k_queue *queue, void *head, void *tail); * @retval 0 on success * @retval -EINVAL on invalid data */ -extern int k_queue_merge_slist(struct k_queue *queue, sys_slist_t *list); +int k_queue_merge_slist(struct k_queue *queue, sys_slist_t *list); /** * @brief Get an element from a queue. @@ -2202,6 +2222,11 @@ struct k_event { struct k_spinlock lock; SYS_PORT_TRACING_TRACKING_FIELD(k_event) + +#ifdef CONFIG_OBJ_CORE_EVENT + struct k_obj_core obj_core; +#endif + }; #define Z_EVENT_INITIALIZER(obj) \ @@ -2360,6 +2385,9 @@ static inline uint32_t k_event_test(struct k_event *event, uint32_t events_mask) struct k_fifo { struct k_queue _queue; +#ifdef CONFIG_OBJ_CORE_FIFO + struct k_obj_core obj_core; +#endif }; /** @@ -2387,11 +2415,13 @@ struct k_fifo { * * @param fifo Address of the FIFO queue. */ -#define k_fifo_init(fifo) \ - ({ \ +#define k_fifo_init(fifo) \ + ({ \ SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_fifo, init, fifo); \ - k_queue_init(&(fifo)->_queue); \ - SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_fifo, init, fifo); \ + k_queue_init(&(fifo)->_queue); \ + K_OBJ_CORE_INIT(K_OBJ_CORE(fifo), _obj_type_fifo); \ + K_OBJ_CORE_LINK(K_OBJ_CORE(fifo)); \ + SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_fifo, init, fifo); \ }) /** @@ -2587,13 +2617,16 @@ struct k_fifo { * @param name Name of the FIFO queue. */ #define K_FIFO_DEFINE(name) \ - STRUCT_SECTION_ITERABLE_ALTERNATE(k_queue, k_fifo, name) = \ + STRUCT_SECTION_ITERABLE(k_fifo, name) = \ Z_FIFO_INITIALIZER(name) /** @} */ struct k_lifo { struct k_queue _queue; +#ifdef CONFIG_OBJ_CORE_LIFO + struct k_obj_core obj_core; +#endif }; /** @@ -2622,11 +2655,13 @@ struct k_lifo { * * @param lifo Address of the LIFO queue. */ -#define k_lifo_init(lifo) \ - ({ \ +#define k_lifo_init(lifo) \ + ({ \ SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_lifo, init, lifo); \ - k_queue_init(&(lifo)->_queue); \ - SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_lifo, init, lifo); \ + k_queue_init(&(lifo)->_queue); \ + K_OBJ_CORE_INIT(K_OBJ_CORE(lifo), _obj_type_lifo); \ + K_OBJ_CORE_LINK(K_OBJ_CORE(lifo)); \ + SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_lifo, init, lifo); \ }) /** @@ -2707,7 +2742,7 @@ struct k_lifo { * @param name Name of the fifo. */ #define K_LIFO_DEFINE(name) \ - STRUCT_SECTION_ITERABLE_ALTERNATE(k_queue, k_lifo, name) = \ + STRUCT_SECTION_ITERABLE(k_lifo, name) = \ Z_LIFO_INITIALIZER(name) /** @} */ @@ -2727,6 +2762,10 @@ struct k_stack { uint8_t flags; SYS_PORT_TRACING_TRACKING_FIELD(k_stack) + +#ifdef CONFIG_OBJ_CORE_STACK + struct k_obj_core obj_core; +#endif }; #define Z_STACK_INITIALIZER(obj, stack_buffer, stack_num_entries) \ @@ -2883,6 +2922,10 @@ struct k_mutex { int owner_orig_prio; SYS_PORT_TRACING_TRACKING_FIELD(k_mutex) + +#ifdef CONFIG_OBJ_CORE_MUTEX + struct k_obj_core obj_core; +#endif }; /** @@ -2980,6 +3023,10 @@ __syscall int k_mutex_unlock(struct k_mutex *mutex); struct k_condvar { _wait_q_t wait_q; + +#ifdef CONFIG_OBJ_CORE_CONDVAR + struct k_obj_core obj_core; +#endif }; #define Z_CONDVAR_INITIALIZER(obj) \ @@ -3064,10 +3111,13 @@ struct k_sem { unsigned int count; unsigned int limit; - _POLL_EVENT; + Z_DECL_POLL_EVENT SYS_PORT_TRACING_TRACKING_FIELD(k_sem) +#ifdef CONFIG_OBJ_CORE_SEM + struct k_obj_core obj_core; +#endif }; #define Z_SEM_INITIALIZER(obj, initial_count, count_limit) \ @@ -3075,7 +3125,7 @@ struct k_sem { .wait_q = Z_WAIT_Q_INIT(&obj.wait_q), \ .count = initial_count, \ .limit = count_limit, \ - _POLL_EVENT_OBJ_INIT(obj) \ + Z_POLL_EVENT_OBJ_INIT(obj) \ } /** @@ -3301,7 +3351,7 @@ int k_work_submit_to_queue(struct k_work_q *queue, * * @return as with k_work_submit_to_queue(). */ -extern int k_work_submit(struct k_work *work); +int k_work_submit(struct k_work *work); /** @brief Wait for last-submitted instance to complete. * @@ -3604,7 +3654,7 @@ int k_work_schedule_for_queue(struct k_work_q *queue, * * @return as with k_work_schedule_for_queue(). */ -extern int k_work_schedule(struct k_work_delayable *dwork, +int k_work_schedule(struct k_work_delayable *dwork, k_timeout_t delay); /** @brief Reschedule a work item to a queue after a delay. @@ -3658,7 +3708,7 @@ int k_work_reschedule_for_queue(struct k_work_q *queue, * * @return as with k_work_reschedule_for_queue(). */ -extern int k_work_reschedule(struct k_work_delayable *dwork, +int k_work_reschedule(struct k_work_delayable *dwork, k_timeout_t delay); /** @brief Flush delayable work. @@ -4179,7 +4229,7 @@ static inline int k_work_user_submit_to_queue(struct k_work_user_q *work_q, * @param name optional thread name. If not null a copy is made into the * thread's name buffer. */ -extern void k_work_user_queue_start(struct k_work_user_q *work_q, +void k_work_user_queue_start(struct k_work_user_q *work_q, k_thread_stack_t *stack, size_t stack_size, int prio, const char *name); @@ -4248,7 +4298,7 @@ struct k_work_poll { * @param work Address of triggered work item. * @param handler Function to invoke each time work item is processed. */ -extern void k_work_poll_init(struct k_work_poll *work, +void k_work_poll_init(struct k_work_poll *work, k_work_handler_t handler); /** @@ -4285,7 +4335,7 @@ extern void k_work_poll_init(struct k_work_poll *work, * @retval -EINVAL Work item is being processed or has completed its work. * @retval -EADDRINUSE Work item is pending on a different workqueue. */ -extern int k_work_poll_submit_to_queue(struct k_work_q *work_q, +int k_work_poll_submit_to_queue(struct k_work_q *work_q, struct k_work_poll *work, struct k_poll_event *events, int num_events, @@ -4322,7 +4372,7 @@ extern int k_work_poll_submit_to_queue(struct k_work_q *work_q, * @retval -EINVAL Work item is being processed or has completed its work. * @retval -EADDRINUSE Work item is pending on a different workqueue. */ -extern int k_work_poll_submit(struct k_work_poll *work, +int k_work_poll_submit(struct k_work_poll *work, struct k_poll_event *events, int num_events, k_timeout_t timeout); @@ -4341,7 +4391,7 @@ extern int k_work_poll_submit(struct k_work_poll *work, * @retval 0 Work item canceled. * @retval -EINVAL Work item is being processed or has completed its work. */ -extern int k_work_poll_cancel(struct k_work_poll *work); +int k_work_poll_cancel(struct k_work_poll *work); /** @} */ @@ -4374,12 +4424,16 @@ struct k_msgq { /** Number of used messages */ uint32_t used_msgs; - _POLL_EVENT; + Z_DECL_POLL_EVENT /** Message queue */ uint8_t flags; SYS_PORT_TRACING_TRACKING_FIELD(k_msgq) + +#ifdef CONFIG_OBJ_CORE_MSGQ + struct k_obj_core obj_core; +#endif }; /** * @cond INTERNAL_HIDDEN @@ -4396,7 +4450,7 @@ struct k_msgq { .read_ptr = q_buffer, \ .write_ptr = q_buffer, \ .used_msgs = 0, \ - _POLL_EVENT_OBJ_INIT(obj) \ + Z_POLL_EVENT_OBJ_INIT(obj) \ } /** @@ -4423,10 +4477,8 @@ struct k_msgq_attrs { * @brief Statically define and initialize a message queue. * * The message queue's ring buffer contains space for @a q_max_msgs messages, - * each of which is @a q_msg_size bytes long. The buffer is aligned to a - * @a q_align -byte boundary, which must be a power of 2. To ensure that each - * message is similarly aligned to this boundary, @a q_msg_size must also be - * a multiple of @a q_align. + * each of which is @a q_msg_size bytes long. Alignment of the message queue's + * ring buffer is not necessary, setting @a q_align to 1 is sufficient. * * The message queue can be accessed outside the module where it is defined * using: @@ -4436,7 +4488,7 @@ struct k_msgq_attrs { * @param q_name Name of the message queue. * @param q_msg_size Message size (in bytes). * @param q_max_msgs Maximum number of messages that can be queued. - * @param q_align Alignment of the message queue's ring buffer. + * @param q_align Alignment of the message queue's ring buffer (power of 2). * */ #define K_MSGQ_DEFINE(q_name, q_msg_size, q_max_msgs, q_align) \ @@ -4452,10 +4504,8 @@ struct k_msgq_attrs { * This routine initializes a message queue object, prior to its first use. * * The message queue's ring buffer must contain space for @a max_msgs messages, - * each of which is @a msg_size bytes long. The buffer must be aligned to an - * N-byte boundary, where N is a power of 2 (i.e. 1, 2, 4, ...). To ensure - * that each message is similarly aligned to this boundary, @a q_msg_size - * must also be a multiple of N. + * each of which is @a msg_size bytes long. Alignment of the message queue's + * ring buffer is not necessary. * * @param msgq Address of the message queue. * @param buffer Pointer to ring buffer that holds queued messages. @@ -4655,10 +4705,6 @@ struct k_mbox_msg { uint32_t info; /** sender's message data buffer */ void *tx_data; - /** internal use only - needed for legacy API support */ - void *_rx_data; - /** message data block descriptor */ - struct k_mem_block tx_block; /** source thread id */ k_tid_t rx_source_thread; /** target thread id */ @@ -4682,6 +4728,10 @@ struct k_mbox { struct k_spinlock lock; SYS_PORT_TRACING_TRACKING_FIELD(k_mbox) + +#ifdef CONFIG_OBJ_CORE_MAILBOX + struct k_obj_core obj_core; +#endif }; /** * @cond INTERNAL_HIDDEN @@ -4717,14 +4767,14 @@ struct k_mbox { * * @param mbox Address of the mailbox. */ -extern void k_mbox_init(struct k_mbox *mbox); +void k_mbox_init(struct k_mbox *mbox); /** * @brief Send a mailbox message in a synchronous manner. * * This routine sends a message to @a mbox and waits for a receiver to both - * receive and process it. The message data may be in a buffer, in a memory - * pool block, or non-existent (i.e. an empty message). + * receive and process it. The message data may be in a buffer or non-existent + * (i.e. an empty message). * * @param mbox Address of the mailbox. * @param tx_msg Address of the transmit message descriptor. @@ -4738,23 +4788,23 @@ extern void k_mbox_init(struct k_mbox *mbox); * @retval -ENOMSG Returned without waiting. * @retval -EAGAIN Waiting period timed out. */ -extern int k_mbox_put(struct k_mbox *mbox, struct k_mbox_msg *tx_msg, +int k_mbox_put(struct k_mbox *mbox, struct k_mbox_msg *tx_msg, k_timeout_t timeout); /** * @brief Send a mailbox message in an asynchronous manner. * * This routine sends a message to @a mbox without waiting for a receiver - * to process it. The message data may be in a buffer, in a memory pool block, - * or non-existent (i.e. an empty message). Optionally, the semaphore @a sem - * will be given when the message has been both received and completely - * processed by the receiver. + * to process it. The message data may be in a buffer or non-existent + * (i.e. an empty message). Optionally, the semaphore @a sem will be given + * when the message has been both received and completely processed by + * the receiver. * * @param mbox Address of the mailbox. * @param tx_msg Address of the transmit message descriptor. * @param sem Address of a semaphore, or NULL if none is needed. */ -extern void k_mbox_async_put(struct k_mbox *mbox, struct k_mbox_msg *tx_msg, +void k_mbox_async_put(struct k_mbox *mbox, struct k_mbox_msg *tx_msg, struct k_sem *sem); /** @@ -4774,7 +4824,7 @@ extern void k_mbox_async_put(struct k_mbox *mbox, struct k_mbox_msg *tx_msg, * @retval -ENOMSG Returned without waiting. * @retval -EAGAIN Waiting period timed out. */ -extern int k_mbox_get(struct k_mbox *mbox, struct k_mbox_msg *rx_msg, +int k_mbox_get(struct k_mbox *mbox, struct k_mbox_msg *rx_msg, void *buffer, k_timeout_t timeout); /** @@ -4790,7 +4840,7 @@ extern int k_mbox_get(struct k_mbox *mbox, struct k_mbox_msg *rx_msg, * @param buffer Address of the buffer to receive data, or NULL to discard * the data. */ -extern void k_mbox_data_get(struct k_mbox_msg *rx_msg, void *buffer); +void k_mbox_data_get(struct k_mbox_msg *rx_msg, void *buffer); /** @} */ @@ -4814,11 +4864,15 @@ struct k_pipe { _wait_q_t writers; /**< Writer wait queue */ } wait_q; /** Wait queue */ - _POLL_EVENT; + Z_DECL_POLL_EVENT uint8_t flags; /**< Flags */ SYS_PORT_TRACING_TRACKING_FIELD(k_pipe) + +#ifdef CONFIG_OBJ_CORE_PIPE + struct k_obj_core obj_core; +#endif }; /** @@ -4838,7 +4892,7 @@ struct k_pipe { .readers = Z_WAIT_Q_INIT(&obj.wait_q.readers), \ .writers = Z_WAIT_Q_INIT(&obj.wait_q.writers) \ }, \ - _POLL_EVENT_OBJ_INIT(obj) \ + Z_POLL_EVENT_OBJ_INIT(obj) \ .flags = 0, \ } @@ -5004,31 +5058,37 @@ __syscall void k_pipe_buffer_flush(struct k_pipe *pipe); * @cond INTERNAL_HIDDEN */ -struct k_mem_slab { - _wait_q_t wait_q; - struct k_spinlock lock; +struct k_mem_slab_info { uint32_t num_blocks; - size_t block_size; - char *buffer; - char *free_list; + size_t block_size; uint32_t num_used; #ifdef CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION uint32_t max_used; #endif +}; + +struct k_mem_slab { + _wait_q_t wait_q; + struct k_spinlock lock; + char *buffer; + char *free_list; + struct k_mem_slab_info info; SYS_PORT_TRACING_TRACKING_FIELD(k_mem_slab) + +#ifdef CONFIG_OBJ_CORE_MEM_SLAB + struct k_obj_core obj_core; +#endif }; -#define Z_MEM_SLAB_INITIALIZER(obj, slab_buffer, slab_block_size, \ - slab_num_blocks) \ - { \ - .wait_q = Z_WAIT_Q_INIT(&obj.wait_q), \ - .lock = {}, \ - .num_blocks = slab_num_blocks, \ - .block_size = slab_block_size, \ - .buffer = slab_buffer, \ - .free_list = NULL, \ - .num_used = 0, \ +#define Z_MEM_SLAB_INITIALIZER(_slab, _slab_buffer, _slab_block_size, \ + _slab_num_blocks) \ + { \ + .wait_q = Z_WAIT_Q_INIT(&(_slab).wait_q), \ + .lock = {}, \ + .buffer = _slab_buffer, \ + .free_list = NULL, \ + .info = {_slab_num_blocks, _slab_block_size, 0} \ } @@ -5116,7 +5176,7 @@ struct k_mem_slab { * @retval -EINVAL invalid data supplied * */ -extern int k_mem_slab_init(struct k_mem_slab *slab, void *buffer, +int k_mem_slab_init(struct k_mem_slab *slab, void *buffer, size_t block_size, uint32_t num_blocks); /** @@ -5141,7 +5201,7 @@ extern int k_mem_slab_init(struct k_mem_slab *slab, void *buffer, * @retval -EAGAIN Waiting period timed out. * @retval -EINVAL Invalid data supplied */ -extern int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem, +int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem, k_timeout_t timeout); /** @@ -5153,7 +5213,7 @@ extern int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem, * @param slab Address of the memory slab. * @param mem Pointer to the memory block (as returned by k_mem_slab_alloc()). */ -extern void k_mem_slab_free(struct k_mem_slab *slab, void *mem); +void k_mem_slab_free(struct k_mem_slab *slab, void *mem); /** * @brief Get the number of used blocks in a memory slab. @@ -5167,7 +5227,7 @@ extern void k_mem_slab_free(struct k_mem_slab *slab, void *mem); */ static inline uint32_t k_mem_slab_num_used_get(struct k_mem_slab *slab) { - return slab->num_used; + return slab->info.num_used; } /** @@ -5183,7 +5243,7 @@ static inline uint32_t k_mem_slab_num_used_get(struct k_mem_slab *slab) static inline uint32_t k_mem_slab_max_used_get(struct k_mem_slab *slab) { #ifdef CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION - return slab->max_used; + return slab->info.max_used; #else ARG_UNUSED(slab); return 0; @@ -5202,7 +5262,7 @@ static inline uint32_t k_mem_slab_max_used_get(struct k_mem_slab *slab) */ static inline uint32_t k_mem_slab_num_free_get(struct k_mem_slab *slab) { - return slab->num_blocks - slab->num_used; + return slab->info.num_blocks - slab->info.num_used; } /** @@ -5260,7 +5320,8 @@ struct k_heap { * @param mem Pointer to memory. * @param bytes Size of memory region, in bytes */ -void k_heap_init(struct k_heap *h, void *mem, size_t bytes); +void k_heap_init(struct k_heap *h, void *mem, + size_t bytes) __attribute_nonnull(1); /** @brief Allocate aligned memory from a k_heap * @@ -5282,7 +5343,7 @@ void k_heap_init(struct k_heap *h, void *mem, size_t bytes); * @return Pointer to memory the caller can now use */ void *k_heap_aligned_alloc(struct k_heap *h, size_t align, size_t bytes, - k_timeout_t timeout); + k_timeout_t timeout) __attribute_nonnull(1); /** * @brief Allocate memory from a k_heap @@ -5306,7 +5367,7 @@ void *k_heap_aligned_alloc(struct k_heap *h, size_t align, size_t bytes, * @return A pointer to valid heap memory, or NULL */ void *k_heap_alloc(struct k_heap *h, size_t bytes, - k_timeout_t timeout); + k_timeout_t timeout) __attribute_nonnull(1); /** * @brief Free memory allocated by k_heap_alloc() @@ -5318,7 +5379,7 @@ void *k_heap_alloc(struct k_heap *h, size_t bytes, * @param h Heap to which to return the memory * @param mem A valid memory block, or NULL */ -void k_heap_free(struct k_heap *h, void *mem); +void k_heap_free(struct k_heap *h, void *mem) __attribute_nonnull(1); /* Hand-calculated minimum heap sizes needed to return a successful * 1-byte allocation. See details in lib/os/heap.[ch] @@ -5415,7 +5476,7 @@ void k_heap_free(struct k_heap *h, void *mem); * * @return Address of the allocated memory if successful; otherwise NULL. */ -extern void *k_aligned_alloc(size_t align, size_t size); +void *k_aligned_alloc(size_t align, size_t size); /** * @brief Allocate memory from the heap. @@ -5428,7 +5489,7 @@ extern void *k_aligned_alloc(size_t align, size_t size); * * @return Address of the allocated memory if successful; otherwise NULL. */ -extern void *k_malloc(size_t size); +void *k_malloc(size_t size); /** * @brief Free memory allocated from heap. @@ -5440,7 +5501,7 @@ extern void *k_malloc(size_t size); * * @param ptr Pointer to previously allocated memory. */ -extern void k_free(void *ptr); +void k_free(void *ptr); /** * @brief Allocate memory from heap, array style @@ -5453,7 +5514,7 @@ extern void k_free(void *ptr); * * @return Address of the allocated memory if successful; otherwise NULL. */ -extern void *k_calloc(size_t nmemb, size_t size); +void *k_calloc(size_t nmemb, size_t size); /** @} */ @@ -5665,7 +5726,7 @@ struct k_poll_event { * @param obj Kernel object or poll signal. */ -extern void k_poll_event_init(struct k_poll_event *event, uint32_t type, +void k_poll_event_init(struct k_poll_event *event, uint32_t type, int mode, void *obj); /** @@ -5770,11 +5831,6 @@ __syscall void k_poll_signal_check(struct k_poll_signal *sig, __syscall int k_poll_signal_raise(struct k_poll_signal *sig, int result); -/** - * @internal - */ -extern void z_handle_obj_poll_events(sys_dlist_t *events, uint32_t state); - /** @} */ /** @@ -5824,6 +5880,7 @@ static inline void k_cpu_atomic_idle(unsigned int key) */ /** + * @cond INTERNAL_HIDDEN * @internal */ #ifdef ARCH_EXCEPT @@ -5850,6 +5907,9 @@ static inline void k_cpu_atomic_idle(unsigned int key) } while (false) #endif /* _ARCH__EXCEPT */ +/** + * INTERNAL_HIDDEN @endcond + */ /** * @brief Fatally terminate a thread @@ -5874,6 +5934,10 @@ static inline void k_cpu_atomic_idle(unsigned int key) */ #define k_panic() z_except_reason(K_ERR_KERNEL_PANIC) +/** + * @cond INTERNAL_HIDDEN + */ + /* * private APIs that are utilized by one or more public APIs */ @@ -5881,15 +5945,11 @@ static inline void k_cpu_atomic_idle(unsigned int key) /** * @internal */ -extern void z_init_thread_base(struct _thread_base *thread_base, - int priority, uint32_t initial_state, - unsigned int options); - #ifdef CONFIG_MULTITHREADING /** * @internal */ -extern void z_init_static_threads(void); +void z_init_static_threads(void); #else /** * @internal @@ -5900,17 +5960,10 @@ extern void z_init_static_threads(void); /** * @internal */ -extern bool z_is_thread_essential(void); - -#ifdef CONFIG_SMP -void z_smp_thread_init(void *arg, struct k_thread *thread); -void z_smp_thread_swap(void); -#endif - +void z_timer_expiration_handler(struct _timeout *t); /** - * @internal + * INTERNAL_HIDDEN @endcond */ -extern void z_timer_expiration_handler(struct _timeout *t); #ifdef CONFIG_PRINTK /** @@ -6012,7 +6065,7 @@ int k_thread_runtime_stats_all_get(k_thread_runtime_stats_t *stats); * @param thread ID of thread * @return -EINVAL if invalid thread ID, otherwise 0 */ -extern int k_thread_runtime_stats_enable(k_tid_t thread); +int k_thread_runtime_stats_enable(k_tid_t thread); /** * @brief Disable gathering of runtime statistics for specified thread @@ -6023,7 +6076,7 @@ extern int k_thread_runtime_stats_enable(k_tid_t thread); * @param thread ID of thread * @return -EINVAL if invalid thread ID, otherwise 0 */ -extern int k_thread_runtime_stats_disable(k_tid_t thread); +int k_thread_runtime_stats_disable(k_tid_t thread); /** * @brief Enable gathering of system runtime statistics @@ -6032,7 +6085,7 @@ extern int k_thread_runtime_stats_disable(k_tid_t thread); * it does not affect the gathering of similar statistics for individual * threads. */ -extern void k_sys_runtime_stats_enable(void); +void k_sys_runtime_stats_enable(void); /** * @brief Disable gathering of system runtime statistics @@ -6041,7 +6094,7 @@ extern void k_sys_runtime_stats_enable(void); * it does not affect the gathering of similar statistics for individual * threads. */ -extern void k_sys_runtime_stats_disable(void); +void k_sys_runtime_stats_disable(void); #ifdef __cplusplus } diff --git a/include/zephyr/kernel/internal/mm.h b/include/zephyr/kernel/internal/mm.h new file mode 100644 index 00000000000..c859e939234 --- /dev/null +++ b/include/zephyr/kernel/internal/mm.h @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_KERNEL_INTERNAL_MM_H +#define ZEPHYR_INCLUDE_KERNEL_INTERNAL_MM_H + +#include +#include + +/** + * @defgroup kernel_mm_internal_apis Kernel Memory Management Internal APIs + * @ingroup internal_api + * @{ + */ + +/* + * This is the offset to subtract from a virtual address mapped in the + * kernel's permanent mapping of RAM, to obtain its physical address. + * + * virt_addr = phys_addr + Z_MEM_VM_OFFSET + * + * This only works for virtual addresses within the interval + * [CONFIG_KERNEL_VM_BASE, CONFIG_KERNEL_VM_BASE + (CONFIG_SRAM_SIZE * 1024)). + * + * These macros are intended for assembly, linker code, and static initializers. + * Use with care. + * + * Note that when demand paging is active, these will only work with page + * frames that are pinned to their virtual mapping at boot. + * + * TODO: This will likely need to move to an arch API or need additional + * constraints defined. + */ +#ifdef CONFIG_MMU +#define Z_MEM_VM_OFFSET ((CONFIG_KERNEL_VM_BASE + CONFIG_KERNEL_VM_OFFSET) - \ + (CONFIG_SRAM_BASE_ADDRESS + CONFIG_SRAM_OFFSET)) +#else +#define Z_MEM_VM_OFFSET 0 +#endif + +#define Z_MEM_PHYS_ADDR(virt) ((virt) - Z_MEM_VM_OFFSET) +#define Z_MEM_VIRT_ADDR(phys) ((phys) + Z_MEM_VM_OFFSET) + +#if Z_MEM_VM_OFFSET != 0 +#define Z_VM_KERNEL 1 +#ifdef CONFIG_XIP +#error "XIP and a virtual memory kernel are not allowed" +#endif +#endif + +#ifndef _ASMLANGUAGE +#include +#include +#include +#include + +/* Just like Z_MEM_PHYS_ADDR() but with type safety and assertions */ +static inline uintptr_t z_mem_phys_addr(void *virt) +{ + uintptr_t addr = (uintptr_t)virt; + +#if defined(CONFIG_KERNEL_VM_USE_CUSTOM_MEM_RANGE_CHECK) + __ASSERT(sys_mm_is_virt_addr_in_range(virt), + "address %p not in permanent mappings", virt); +#elif defined(CONFIG_MMU) + __ASSERT( +#if CONFIG_KERNEL_VM_BASE != 0 + (addr >= CONFIG_KERNEL_VM_BASE) && +#endif +#if (CONFIG_KERNEL_VM_BASE + CONFIG_KERNEL_VM_SIZE) != 0 + (addr < (CONFIG_KERNEL_VM_BASE + + (CONFIG_KERNEL_VM_SIZE))), +#else + false, +#endif + "address %p not in permanent mappings", virt); +#else + /* Should be identity-mapped */ + __ASSERT( +#if CONFIG_SRAM_BASE_ADDRESS != 0 + (addr >= CONFIG_SRAM_BASE_ADDRESS) && +#endif +#if (CONFIG_SRAM_BASE_ADDRESS + (CONFIG_SRAM_SIZE * 1024UL)) != 0 + (addr < (CONFIG_SRAM_BASE_ADDRESS + + (CONFIG_SRAM_SIZE * 1024UL))), +#else + false, +#endif + "physical address 0x%lx not in RAM", + (unsigned long)addr); +#endif /* CONFIG_MMU */ + + /* TODO add assertion that this page is pinned to boot mapping, + * the above checks won't be sufficient with demand paging + */ + + return Z_MEM_PHYS_ADDR(addr); +} + +/* Just like Z_MEM_VIRT_ADDR() but with type safety and assertions */ +static inline void *z_mem_virt_addr(uintptr_t phys) +{ +#if defined(CONFIG_KERNEL_VM_USE_CUSTOM_MEM_RANGE_CHECK) + __ASSERT(sys_mm_is_phys_addr_in_range(phys), + "physical address 0x%lx not in RAM", (unsigned long)phys); +#else + __ASSERT( +#if CONFIG_SRAM_BASE_ADDRESS != 0 + (phys >= CONFIG_SRAM_BASE_ADDRESS) && +#endif +#if (CONFIG_SRAM_BASE_ADDRESS + (CONFIG_SRAM_SIZE * 1024UL)) != 0 + (phys < (CONFIG_SRAM_BASE_ADDRESS + + (CONFIG_SRAM_SIZE * 1024UL))), +#else + false, +#endif + "physical address 0x%lx not in RAM", (unsigned long)phys); +#endif + + /* TODO add assertion that this page frame is pinned to boot mapping, + * the above check won't be sufficient with demand paging + */ + + return (void *)Z_MEM_VIRT_ADDR(phys); +} + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Map a physical memory region into the kernel's virtual address space + * + * This function is intended for mapping memory-mapped I/O regions into + * the virtual address space. Given a physical address and a size, return a + * linear address representing the base of where the physical region is mapped + * in the virtual address space for the Zephyr kernel. + * + * This function alters the active page tables in the area reserved + * for the kernel. This function will choose the virtual address + * and return it to the caller. + * + * Portable code should never assume that phys_addr and linear_addr will + * be equal. + * + * Caching and access properties are controlled by the 'flags' parameter. + * Unused bits in 'flags' are reserved for future expansion. + * A caching mode must be selected. By default, the region is read-only + * with user access and code execution forbidden. This policy is changed + * by passing K_MEM_CACHE_* and K_MEM_PERM_* macros into the 'flags' parameter. + * + * If there is insufficient virtual address space for the mapping this will + * generate a kernel panic. + * + * This API is only available if CONFIG_MMU is enabled. + * + * It is highly discouraged to use this function to map system RAM page + * frames. It may conflict with anonymous memory mappings and demand paging + * and produce undefined behavior. Do not use this for RAM unless you know + * exactly what you are doing. If you need a chunk of memory, use k_mem_map(). + * If you need a contiguous buffer of physical memory, statically declare it + * and pin it at build time, it will be mapped when the system boots. + * + * This API is part of infrastructure still under development and may + * change. + * + * @param virt [out] Output virtual address storage location + * @param phys Physical address base of the memory region + * @param size Size of the memory region + * @param flags Caching mode and access flags, see K_MAP_* macros + */ +void z_phys_map(uint8_t **virt_ptr, uintptr_t phys, size_t size, + uint32_t flags); + +/** + * Unmap a virtual memory region from kernel's virtual address space. + * + * This function is intended to be used by drivers and early boot routines + * where temporary memory mappings need to be made. This allows these + * memory mappings to be discarded once they are no longer needed. + * + * This function alters the active page tables in the area reserved + * for the kernel. + * + * This will align the input parameters to page boundaries so that + * this can be used with the virtual address as returned by + * z_phys_map(). + * + * This API is only available if CONFIG_MMU is enabled. + * + * It is highly discouraged to use this function to unmap memory mappings. + * It may conflict with anonymous memory mappings and demand paging and + * produce undefined behavior. Do not use this unless you know exactly + * what you are doing. + * + * This API is part of infrastructure still under development and may + * change. + * + * @param virt Starting address of the virtual address region to be unmapped. + * @param size Size of the virtual address region + */ +void z_phys_unmap(uint8_t *virt, size_t size); + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif /* !_ASMLANGUAGE */ +#endif /* ZEPHYR_INCLUDE_KERNEL_INTERNAL_MM_H */ diff --git a/include/zephyr/kernel/sched_priq.h b/include/zephyr/kernel/internal/sched_priq.h similarity index 100% rename from include/zephyr/kernel/sched_priq.h rename to include/zephyr/kernel/internal/sched_priq.h diff --git a/include/zephyr/kernel/internal/smp.h b/include/zephyr/kernel/internal/smp.h new file mode 100644 index 00000000000..d4f70d3c07b --- /dev/null +++ b/include/zephyr/kernel/internal/smp.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_KERNEL_INTERNAL_SMP_H_ +#define ZEPHYR_INCLUDE_KERNEL_INTERNAL_SMP_H_ + +struct k_thread; + +/** + * @internal + */ +#ifdef CONFIG_SOF +void z_smp_thread_init(void *arg, struct k_thread *thread); +void z_smp_thread_swap(void); +#endif + +void z_init_cpu(int id); +void z_sched_ipi(void); +void z_smp_start_cpu(int id); + +#endif diff --git a/include/zephyr/kernel/mempool_heap.h b/include/zephyr/kernel/mempool_heap.h deleted file mode 100644 index d9126facc01..00000000000 --- a/include/zephyr/kernel/mempool_heap.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2020 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef ZEPHYR_INCLUDE_MEMPOOL_HEAP_H_ -#define ZEPHYR_INCLUDE_MEMPOOL_HEAP_H_ - -/* Compatibility implementation of a k_mem_pool backend in terms of a - * k_heap - */ - -/* The "ID" of a k_heap-based mempool is just the tuple of the data - * block pointer and the heap that allocated it - */ -struct k_mem_block_id { - void *data; - struct k_heap *heap; -}; - -/* Note the data pointer gets unioned with the same value stored in - * the ID field to save space. - */ -struct k_mem_block { - union { - void *data; - struct k_mem_block_id id; - }; -}; - -#endif /* ZEPHYR_INCLUDE_MEMPOOL_HEAP_H_ */ diff --git a/include/zephyr/kernel/mm.h b/include/zephyr/kernel/mm.h new file mode 100644 index 00000000000..392dc4b7cde --- /dev/null +++ b/include/zephyr/kernel/mm.h @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_KERNEL_MM_H +#define ZEPHYR_INCLUDE_KERNEL_MM_H + +#include +#include +#if defined(CONFIG_ARM_MMU) && defined(CONFIG_ARM64) +#include +#endif + +#include +#include + +/** + * @brief Kernel Memory Management + * @defgroup kernel_memory_management Kernel Memory Management + * @ingroup kernel_apis + * @{ + */ + +/** + * @name Caching mode definitions. + * + * These are mutually exclusive. + * + * @{ + */ + +/** No caching. Most drivers want this. */ +#define K_MEM_CACHE_NONE 2 + +/** Write-through caching. Used by certain drivers. */ +#define K_MEM_CACHE_WT 1 + +/** Full write-back caching. Any RAM mapped wants this. */ +#define K_MEM_CACHE_WB 0 + +/* + * ARM64 Specific flags are defined in arch/arm64/arm_mem.h, + * pay attention to be not conflicted when updating these flags. + */ + +/** Reserved bits for cache modes in k_map() flags argument */ +#define K_MEM_CACHE_MASK (BIT(3) - 1) + +/** @} */ + +/** + * @name Region permission attributes. + * + * Default is read-only, no user, no exec + * + * @{ + */ + +/** Region will have read/write access (and not read-only) */ +#define K_MEM_PERM_RW BIT(3) + +/** Region will be executable (normally forbidden) */ +#define K_MEM_PERM_EXEC BIT(4) + +/** Region will be accessible to user mode (normally supervisor-only) */ +#define K_MEM_PERM_USER BIT(5) + +/** @} */ + +/** + * @name Region mapping behaviour attributes + * + * @{ + */ + +/** Region will be mapped to 1:1 virtual and physical address */ +#define K_MEM_DIRECT_MAP BIT(6) + +/** @} */ + +#ifndef _ASMLANGUAGE +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name k_mem_map() control flags + * + * @{ + */ + +/** + * @brief The mapped region is not guaranteed to be zeroed. + * + * This may improve performance. The associated page frames may contain + * indeterminate data, zeroes, or even sensitive information. + * + * This may not be used with K_MEM_PERM_USER as there are no circumstances + * where this is safe. + */ +#define K_MEM_MAP_UNINIT BIT(16) + +/** + * Region will be pinned in memory and never paged + * + * Such memory is guaranteed to never produce a page fault due to page-outs + * or copy-on-write once the mapping call has returned. Physical page frames + * will be pre-fetched as necessary and pinned. + */ +#define K_MEM_MAP_LOCK BIT(17) + +/** @} */ + +/** + * Return the amount of free memory available + * + * The returned value will reflect how many free RAM page frames are available. + * If demand paging is enabled, it may still be possible to allocate more. + * + * The information reported by this function may go stale immediately if + * concurrent memory mappings or page-ins take place. + * + * @return Free physical RAM, in bytes + */ +size_t k_mem_free_get(void); + +/** + * Map anonymous memory into Zephyr's address space + * + * This function effectively increases the data space available to Zephyr. + * The kernel will choose a base virtual address and return it to the caller. + * The memory will have access permissions for all contexts set per the + * provided flags argument. + * + * If user thread access control needs to be managed in any way, do not enable + * K_MEM_PERM_USER flags here; instead manage the region's permissions + * with memory domain APIs after the mapping has been established. Setting + * K_MEM_PERM_USER here will allow all user threads to access this memory + * which is usually undesirable. + * + * Unless K_MEM_MAP_UNINIT is used, the returned memory will be zeroed. + * + * The mapped region is not guaranteed to be physically contiguous in memory. + * Physically contiguous buffers should be allocated statically and pinned + * at build time. + * + * Pages mapped in this way have write-back cache settings. + * + * The returned virtual memory pointer will be page-aligned. The size + * parameter, and any base address for re-mapping purposes must be page- + * aligned. + * + * Note that the allocation includes two guard pages immediately before + * and after the requested region. The total size of the allocation will be + * the requested size plus the size of these two guard pages. + * + * Many K_MEM_MAP_* flags have been implemented to alter the behavior of this + * function, with details in the documentation for these flags. + * + * @param size Size of the memory mapping. This must be page-aligned. + * @param flags K_MEM_PERM_*, K_MEM_MAP_* control flags. + * @return The mapped memory location, or NULL if insufficient virtual address + * space, insufficient physical memory to establish the mapping, + * or insufficient memory for paging structures. + */ +void *k_mem_map(size_t size, uint32_t flags); + +/** + * Un-map mapped memory + * + * This removes a memory mapping for the provided page-aligned region. + * Associated page frames will be free and the kernel may re-use the associated + * virtual address region. Any paged out data pages may be discarded. + * + * Calling this function on a region which was not mapped to begin with is + * undefined behavior. + * + * @param addr Page-aligned memory region base virtual address + * @param size Page-aligned memory region size + */ +void k_mem_unmap(void *addr, size_t size); + +/** + * Given an arbitrary region, provide a aligned region that covers it + * + * The returned region will have both its base address and size aligned + * to the provided alignment value. + * + * @param aligned_addr [out] Aligned address + * @param aligned_size [out] Aligned region size + * @param addr Region base address + * @param size Region size + * @param align What to align the address and size to + * @retval offset between aligned_addr and addr + */ +size_t k_mem_region_align(uintptr_t *aligned_addr, size_t *aligned_size, + uintptr_t addr, size_t size, size_t align); + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif /* !_ASMLANGUAGE */ +#endif /* ZEPHYR_INCLUDE_KERNEL_MM_H */ diff --git a/include/zephyr/kernel/mm/demand_paging.h b/include/zephyr/kernel/mm/demand_paging.h new file mode 100644 index 00000000000..10412d3a766 --- /dev/null +++ b/include/zephyr/kernel/mm/demand_paging.h @@ -0,0 +1,375 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_KERNEL_MM_DEMAND_PAGING_H +#define ZEPHYR_INCLUDE_KERNEL_MM_DEMAND_PAGING_H + +#include + +#include +#include + +/** + * @defgroup demand_paging Demand Paging + * @ingroup kernel_memory_management + */ + +/** + * @defgroup mem-demand-paging Demand Paging APIs + * @ingroup demand_paging + * @{ + */ + +#ifndef _ASMLANGUAGE +#include +#include +#include +#include + +/** + * Paging Statistics. + */ +struct k_mem_paging_stats_t { +#if defined(CONFIG_DEMAND_PAGING_STATS) || defined(__DOXYGEN__) + struct { + /** Number of page faults */ + unsigned long cnt; + + /** Number of page faults with IRQ locked */ + unsigned long irq_locked; + + /** Number of page faults with IRQ unlocked */ + unsigned long irq_unlocked; + +#if !defined(CONFIG_DEMAND_PAGING_ALLOW_IRQ) || defined(__DOXYGEN__) + /** Number of page faults while in ISR */ + unsigned long in_isr; +#endif + } pagefaults; + + struct { + /** Number of clean pages selected for eviction */ + unsigned long clean; + + /** Number of dirty pages selected for eviction */ + unsigned long dirty; + } eviction; +#endif /* CONFIG_DEMAND_PAGING_STATS */ +}; + +/** + * Paging Statistics Histograms. + */ +struct k_mem_paging_histogram_t { +#if defined(CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM) || defined(__DOXYGEN__) + /* Counts for each bin in timing histogram */ + unsigned long counts[CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM_NUM_BINS]; + + /* Bounds for the bins in timing histogram, + * excluding the first and last (hence, NUM_SLOTS - 1). + */ + unsigned long bounds[CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM_NUM_BINS]; +#endif /* CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM */ +}; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Evict a page-aligned virtual memory region to the backing store + * + * Useful if it is known that a memory region will not be used for some time. + * All the data pages within the specified region will be evicted to the + * backing store if they weren't already, with their associated page frames + * marked as available for mappings or page-ins. + * + * None of the associated page frames mapped to the provided region should + * be pinned. + * + * Note that there are no guarantees how long these pages will be evicted, + * they could take page faults immediately. + * + * If CONFIG_DEMAND_PAGING_ALLOW_IRQ is enabled, this function may not be + * called by ISRs as the backing store may be in-use. + * + * @param addr Base page-aligned virtual address + * @param size Page-aligned data region size + * @retval 0 Success + * @retval -ENOMEM Insufficient space in backing store to satisfy request. + * The region may be partially paged out. + */ +int k_mem_page_out(void *addr, size_t size); + +/** + * Load a virtual data region into memory + * + * After the function completes, all the page frames associated with this + * function will be paged in. However, they are not guaranteed to stay there. + * This is useful if the region is known to be used soon. + * + * If CONFIG_DEMAND_PAGING_ALLOW_IRQ is enabled, this function may not be + * called by ISRs as the backing store may be in-use. + * + * @param addr Base page-aligned virtual address + * @param size Page-aligned data region size + */ +void k_mem_page_in(void *addr, size_t size); + +/** + * Pin an aligned virtual data region, paging in as necessary + * + * After the function completes, all the page frames associated with this + * region will be resident in memory and pinned such that they stay that way. + * This is a stronger version of z_mem_page_in(). + * + * If CONFIG_DEMAND_PAGING_ALLOW_IRQ is enabled, this function may not be + * called by ISRs as the backing store may be in-use. + * + * @param addr Base page-aligned virtual address + * @param size Page-aligned data region size + */ +void k_mem_pin(void *addr, size_t size); + +/** + * Un-pin an aligned virtual data region + * + * After the function completes, all the page frames associated with this + * region will be no longer marked as pinned. This does not evict the region, + * follow this with z_mem_page_out() if you need that. + * + * @param addr Base page-aligned virtual address + * @param size Page-aligned data region size + */ +void k_mem_unpin(void *addr, size_t size); + +/** + * Get the paging statistics since system startup + * + * This populates the paging statistics struct being passed in + * as argument. + * + * @param[in,out] stats Paging statistics struct to be filled. + */ +__syscall void k_mem_paging_stats_get(struct k_mem_paging_stats_t *stats); + +struct k_thread; +/** + * Get the paging statistics since system startup for a thread + * + * This populates the paging statistics struct being passed in + * as argument for a particular thread. + * + * @param[in] thread Thread + * @param[in,out] stats Paging statistics struct to be filled. + */ +__syscall +void k_mem_paging_thread_stats_get(struct k_thread *thread, + struct k_mem_paging_stats_t *stats); + +/** + * Get the eviction timing histogram + * + * This populates the timing histogram struct being passed in + * as argument. + * + * @param[in,out] hist Timing histogram struct to be filled. + */ +__syscall void k_mem_paging_histogram_eviction_get( + struct k_mem_paging_histogram_t *hist); + +/** + * Get the backing store page-in timing histogram + * + * This populates the timing histogram struct being passed in + * as argument. + * + * @param[in,out] hist Timing histogram struct to be filled. + */ +__syscall void k_mem_paging_histogram_backing_store_page_in_get( + struct k_mem_paging_histogram_t *hist); + +/** + * Get the backing store page-out timing histogram + * + * This populates the timing histogram struct being passed in + * as argument. + * + * @param[in,out] hist Timing histogram struct to be filled. + */ +__syscall void k_mem_paging_histogram_backing_store_page_out_get( + struct k_mem_paging_histogram_t *hist); + +#include + +/** @} */ + +/** + * Eviction algorithm APIs + * + * @defgroup mem-demand-paging-eviction Eviction Algorithm APIs + * @ingroup demand_paging + * @{ + */ + +/** + * Select a page frame for eviction + * + * The kernel will invoke this to choose a page frame to evict if there + * are no free page frames. + * + * This function will never be called before the initial + * k_mem_paging_eviction_init(). + * + * This function is invoked with interrupts locked. + * + * @param [out] dirty Whether the page to evict is dirty + * @return The page frame to evict + */ +struct z_page_frame *k_mem_paging_eviction_select(bool *dirty); + +/** + * Initialization function + * + * Called at POST_KERNEL to perform any necessary initialization tasks for the + * eviction algorithm. k_mem_paging_eviction_select() is guaranteed to never be + * called until this has returned, and this will only be called once. + */ +void k_mem_paging_eviction_init(void); + +/** @} */ + +/** + * Backing store APIs + * + * @defgroup mem-demand-paging-backing-store Backing Store APIs + * @ingroup demand_paging + * @{ + */ + +/** + * Reserve or fetch a storage location for a data page loaded into a page frame + * + * The returned location token must be unique to the mapped virtual address. + * This location will be used in the backing store to page out data page + * contents for later retrieval. The location value must be page-aligned. + * + * This function may be called multiple times on the same data page. If its + * page frame has its Z_PAGE_FRAME_BACKED bit set, it is expected to return + * the previous backing store location for the data page containing a cached + * clean copy. This clean copy may be updated on page-out, or used to + * discard clean pages without needing to write out their contents. + * + * If the backing store is full, some other backing store location which caches + * a loaded data page may be selected, in which case its associated page frame + * will have the Z_PAGE_FRAME_BACKED bit cleared (as it is no longer cached). + * + * pf->addr will indicate the virtual address the page is currently mapped to. + * Large, sparse backing stores which can contain the entire address space + * may simply generate location tokens purely as a function of pf->addr with no + * other management necessary. + * + * This function distinguishes whether it was called on behalf of a page + * fault. A free backing store location must always be reserved in order for + * page faults to succeed. If the page_fault parameter is not set, this + * function should return -ENOMEM even if one location is available. + * + * This function is invoked with interrupts locked. + * + * @param pf Virtual address to obtain a storage location + * @param [out] location storage location token + * @param page_fault Whether this request was for a page fault + * @return 0 Success + * @return -ENOMEM Backing store is full + */ +int k_mem_paging_backing_store_location_get(struct z_page_frame *pf, + uintptr_t *location, + bool page_fault); + +/** + * Free a backing store location + * + * Any stored data may be discarded, and the location token associated with + * this address may be re-used for some other data page. + * + * This function is invoked with interrupts locked. + * + * @param location Location token to free + */ +void k_mem_paging_backing_store_location_free(uintptr_t location); + +/** + * Copy a data page from Z_SCRATCH_PAGE to the specified location + * + * Immediately before this is called, Z_SCRATCH_PAGE will be mapped read-write + * to the intended source page frame for the calling context. + * + * Calls to this and k_mem_paging_backing_store_page_in() will always be + * serialized, but interrupts may be enabled. + * + * @param location Location token for the data page, for later retrieval + */ +void k_mem_paging_backing_store_page_out(uintptr_t location); + +/** + * Copy a data page from the provided location to Z_SCRATCH_PAGE. + * + * Immediately before this is called, Z_SCRATCH_PAGE will be mapped read-write + * to the intended destination page frame for the calling context. + * + * Calls to this and k_mem_paging_backing_store_page_out() will always be + * serialized, but interrupts may be enabled. + * + * @param location Location token for the data page + */ +void k_mem_paging_backing_store_page_in(uintptr_t location); + +/** + * Update internal accounting after a page-in + * + * This is invoked after k_mem_paging_backing_store_page_in() and interrupts + * have been* re-locked, making it safe to access the z_page_frame data. + * The location value will be the same passed to + * k_mem_paging_backing_store_page_in(). + * + * The primary use-case for this is to update custom fields for the backing + * store in the page frame, to reflect where the data should be evicted to + * if it is paged out again. This may be a no-op in some implementations. + * + * If the backing store caches paged-in data pages, this is the appropriate + * time to set the Z_PAGE_FRAME_BACKED bit. The kernel only skips paging + * out clean data pages if they are noted as clean in the page tables and the + * Z_PAGE_FRAME_BACKED bit is set in their associated page frame. + * + * @param pf Page frame that was loaded in + * @param location Location of where the loaded data page was retrieved + */ +void k_mem_paging_backing_store_page_finalize(struct z_page_frame *pf, + uintptr_t location); + +/** + * Backing store initialization function. + * + * The implementation may expect to receive page in/out calls as soon as this + * returns, but not before that. Called at POST_KERNEL. + * + * This function is expected to do two things: + * - Initialize any internal data structures and accounting for the backing + * store. + * - If the backing store already contains all or some loaded kernel data pages + * at boot time, Z_PAGE_FRAME_BACKED should be appropriately set for their + * associated page frames, and any internal accounting set up appropriately. + */ +void k_mem_paging_backing_store_init(void); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* !_ASMLANGUAGE */ +#endif /* ZEPHYR_INCLUDE_KERNEL_MM_DEMAND_PAGING_H */ diff --git a/include/zephyr/kernel/obj_core.h b/include/zephyr/kernel/obj_core.h new file mode 100644 index 00000000000..1dedccbfc4f --- /dev/null +++ b/include/zephyr/kernel/obj_core.h @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2023, Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __KERNEL_OBJ_CORE_H__ +#define __KERNEL_OBJ_CORE_H__ + +#include + +/** + * @defgroup obj_core_apis Object Core APIs + * @ingroup kernel_apis + * @{ + */ + +/** + * @brief Convert kernel object pointer into its object core pointer + */ +#define K_OBJ_CORE(kobj) (&((kobj)->obj_core)) + +/** + * @brief Generate new object type IDs based on a 4 letter string + */ +#define K_OBJ_TYPE_ID_GEN(s) ((s[0] << 24) | (s[1] << 16) | (s[2] << 8) | (s[3])) + +/* Known kernel object types */ + +/** Condition variable object type */ +#define K_OBJ_TYPE_CONDVAR_ID K_OBJ_TYPE_ID_GEN("COND") +/** CPU object type */ +#define K_OBJ_TYPE_CPU_ID K_OBJ_TYPE_ID_GEN("CPU_") +/** Event object type */ +#define K_OBJ_TYPE_EVENT_ID K_OBJ_TYPE_ID_GEN("EVNT") +/** FIFO object type */ +#define K_OBJ_TYPE_FIFO_ID K_OBJ_TYPE_ID_GEN("FIFO") +/** Kernel object type */ +#define K_OBJ_TYPE_KERNEL_ID K_OBJ_TYPE_ID_GEN("KRNL") +/** LIFO object type */ +#define K_OBJ_TYPE_LIFO_ID K_OBJ_TYPE_ID_GEN("LIFO") +/** Memory block object type */ +#define K_OBJ_TYPE_MEM_BLOCK_ID K_OBJ_TYPE_ID_GEN("MBLK") +/** Mailbox object type */ +#define K_OBJ_TYPE_MBOX_ID K_OBJ_TYPE_ID_GEN("MBOX") +/** Memory slab object type */ +#define K_OBJ_TYPE_MEM_SLAB_ID K_OBJ_TYPE_ID_GEN("SLAB") +/** Message queue object type */ +#define K_OBJ_TYPE_MSGQ_ID K_OBJ_TYPE_ID_GEN("MSGQ") +/** Mutex object type */ +#define K_OBJ_TYPE_MUTEX_ID K_OBJ_TYPE_ID_GEN("MUTX") +/** Pipe object type */ +#define K_OBJ_TYPE_PIPE_ID K_OBJ_TYPE_ID_GEN("PIPE") +/** Semaphore object type */ +#define K_OBJ_TYPE_SEM_ID K_OBJ_TYPE_ID_GEN("SEM4") +/** Stack object type */ +#define K_OBJ_TYPE_STACK_ID K_OBJ_TYPE_ID_GEN("STCK") +/** Thread object type */ +#define K_OBJ_TYPE_THREAD_ID K_OBJ_TYPE_ID_GEN("THRD") +/** Timer object type */ +#define K_OBJ_TYPE_TIMER_ID K_OBJ_TYPE_ID_GEN("TIMR") + +struct k_obj_type; +struct k_obj_core; + +/** + * @cond INTERNAL_HIDDEN + */ + +#ifdef CONFIG_OBJ_CORE +#define K_OBJ_CORE_INIT(_objp, _obj_type) \ + extern struct k_obj_type _obj_type; \ + k_obj_core_init(_objp, &_obj_type) + +#define K_OBJ_CORE_LINK(objp) k_obj_core_link(objp) +#else +#define K_OBJ_CORE_INIT(objp, type) do { } while (0) +#define K_OBJ_CORE_LINK(objp) do { } while (0) +#endif + +/** + * INTERNAL_HIDDEN @endcond + */ + +/** + * Tools may use this list as an entry point to identify all registered + * object types and the object cores linked to them. + */ +extern sys_slist_t z_obj_type_list; + +/** Object core statistics descriptor */ +struct k_obj_core_stats_desc { + size_t raw_size; /**< Internal representation stats buffer size */ + size_t query_size; /**< Stats buffer size used for reporting */ + + /** Function pointer to retrieve internal representation of stats */ + int (*raw)(struct k_obj_core *obj_core, void *stats); + /** Function pointer to retrieve reported statistics */ + int (*query)(struct k_obj_core *obj_core, void *stats); + /** Function pointer to reset object's statistics */ + int (*reset)(struct k_obj_core *obj_core); + /** Function pointer to disable object's statistics gathering */ + int (*disable)(struct k_obj_core *obj_core); + /** Function pointer to enable object's statistics gathering */ + int (*enable)(struct k_obj_core *obj_core); +}; + +/** Object type structure */ +struct k_obj_type { + sys_snode_t node; /**< Node within list of object types */ + sys_slist_t list; /**< List of objects of this object type */ + uint32_t id; /**< Unique type ID */ + size_t obj_core_offset; /**< Offset to obj_core field */ +#ifdef CONFIG_OBJ_CORE_STATS + /** Pointer to object core statistics descriptor */ + struct k_obj_core_stats_desc *stats_desc; +#endif +}; + +/** Object core structure */ +struct k_obj_core { + sys_snode_t node; /**< Object node within object type's list */ + struct k_obj_type *type; /**< Object type to which object belongs */ +#ifdef CONFIG_OBJ_CORE_STATS + void *stats; /**< Pointer to kernel object's stats */ +#endif +}; + +/** + * @brief Initialize a specific object type + * + * Initializes a specific object type and links it into the object core + * framework. + * + * @param type Pointer to the object type to initialize + * @param id A means to identify the object type + * @param off Offset of object core within the structure + * + * @retval Pointer to initialized object type + */ +struct k_obj_type *z_obj_type_init(struct k_obj_type *type, + uint32_t id, size_t off); + +/** + * @brief Find a specific object type by ID + * + * Given an object type ID, this function searches for the object type that + * is associated with the specified type ID @a type_id. + * + * @param type_id Type ID associated with object type + * + * @retval NULL if object type not found + * @retval Pointer to object type if found + */ +struct k_obj_type *k_obj_type_find(uint32_t type_id); + +/** + * @brief Walk the object type's list of object cores + * + * This function takes a global spinlock and walks the object type's list + * of object cores and invokes the callback function on each element while + * holding that lock. Although this will ensure that the list is not modified, + * one can expect a significant penalty in terms of performance and latency. + * + * The callback function shall either return non-zero to stop further walking, + * or it shall return 0 to continue walking. + * + * @param type Pointer to the object type + * @param func Callback to invoke on each object core of the object type + * @param data Custom data passed to the callback + * + * @retval non-zero if walk is terminated by the callback; otherwise 0 + */ +int k_obj_type_walk_locked(struct k_obj_type *type, + int (*func)(struct k_obj_core *, void *), + void *data); + +/** + * @brief Walk the object type's list of object cores + * + * This function is similar to k_obj_type_walk_locked() except that it walks + * the list without obtaining the global spinlock. No synchronization is + * provided here. Mutation of the list of objects while this function is in + * progress must be prevented at the application layer, otherwise + * undefined/unreliable behavior, corruption and/or crashes may result. + * + * The callback function shall either return non-zero to stop further walking, + * or it shall return 0 to continue walking. + * + * @param type Pointer to the object type + * @param func Callback to invoke on each object core of the object type + * @param data Custom data passed to the callback + * + * @retval non-zero if walk is terminated by the callback; otherwise 0 + */ +int k_obj_type_walk_unlocked(struct k_obj_type *type, + int (*func)(struct k_obj_core *, void *), + void *data); + +/** + * @brief Initialize the core of the kernel object + * + * Initializing the kernel object core associates it with the specified + * kernel object type. + * + * @param obj_core Pointer to the kernel object to initialize + * @param type Pointer to the kernel object type + */ +void k_obj_core_init(struct k_obj_core *obj_core, struct k_obj_type *type); + +/** + * @brief Link the kernel object to the kernel object type list + * + * A kernel object can be optionally linked into the kernel object type's + * list of objects. A kernel object must have been initialized before it + * can be linked. Linked kernel objects can be traversed and have information + * extracted from them by system tools. + * + * @param obj_core Pointer to the kernel object + */ +void k_obj_core_link(struct k_obj_core *obj_core); + +/** + * @brief Automatically link the kernel object after initializing it + * + * A useful wrapper to both initialize the core of the kernel object and + * automatically link it into the kernel object type's list of objects. + * + * @param obj_core Pointer to the kernel object to initialize + * @param type Pointer to the kernel object type + */ +void k_obj_core_init_and_link(struct k_obj_core *obj_core, + struct k_obj_type *type); + +/** + * @brief Unlink the kernel object from the kernel object type list + * + * Kernel objects can be unlinked from their respective kernel object type + * lists. If on a list, it must be done at the end of the kernel object's life + * cycle. + * + * @param obj_core Pointer to the kernel object + */ +void k_obj_core_unlink(struct k_obj_core *obj_core); + +/** @} */ + +/** + * @defgroup obj_core_stats_apis Object Core Statistics APIs + * @ingroup kernel_apis + * @{ + */ + +#ifdef CONFIG_OBJ_CORE_STATS +/** + * @brief Initialize the object type's stats descriptor + * + * This routine initializes the object type's stats descriptor. + * + * @param type Pointer to the object type + * @param stats_desc Pointer to the object core statistics descriptor + */ +static inline void k_obj_type_stats_init(struct k_obj_type *type, + struct k_obj_core_stats_desc *stats_desc) +{ + type->stats_desc = stats_desc; +} + +/** + * @brief Initialize the object core for statistics + * + * This routine initializes the object core to operate within the object core + * statistics framework. + * + * @param obj_core Pointer to the object core + * @param stats Pointer to the object's raw statistics + */ +static inline void k_obj_core_stats_init(struct k_obj_core *obj_core, + void *stats) +{ + obj_core->stats = stats; +} +#endif + +/** + * @brief Register kernel object for gathering statistics + * + * Before a kernel object can gather statistics, it must be registered to do + * so. Registering will also automatically enable the kernel object to gather + * its statistics. + * + * @param obj_core Pointer to kernel object core + * @param stats Pointer to raw kernel statistics + * @param stats_len Size of raw kernel statistics buffer + * + * @retval 0 on success + * @retval -errno on failure + */ +int k_obj_core_stats_register(struct k_obj_core *obj_core, void *stats, + size_t stats_len); + +/** + * @brief Deregister kernel object from gathering statistics + * + * Deregistering a kernel object core from gathering statistics prevents it + * from gathering any more statistics. It is expected to be invoked at the end + * of a kernel object's life cycle. + * + * @param obj_core Pointer to kernel object core + * + * @retval 0 on success + * @retval -errno on failure + */ +int k_obj_core_stats_deregister(struct k_obj_core *obj_core); + +/** + * @brief Retrieve the raw statistics associated with the kernel object + * + * This function copies the raw statistics associated with the kernel object + * core specified by @a obj_core into the buffer @a stats. Note that the size + * of the buffer (@a stats_len) must match the size specified by the kernel + * object type's statistics descriptor. + * + * @param obj_core Pointer to kernel object core + * @param stats Pointer to memory buffer into which to copy raw stats + * @param stats_len Length of the memory buffer + * + * @retval 0 on success + * @retval -errno on failure + */ +int k_obj_core_stats_raw(struct k_obj_core *obj_core, void *stats, + size_t stats_len); + +/** + * @brief Retrieve the statistics associated with the kernel object + * + * This function copies the statistics associated with the kernel object core + * specified by @a obj_core into the buffer @a stats. Unlike the raw statistics + * this may report calculated values such as averages. Note that the size of + * the buffer (@a stats_len) must match the size specified by the kernel object + * type's statistics descriptor. + * + * @param obj_core Pointer to kernel object core + * @param stats Pointer to memory buffer into which to copy the queried stats + * @param stats_len Length of the memory buffer + * + * @retval 0 on success + * @retval -errno on failure + */ +int k_obj_core_stats_query(struct k_obj_core *obj_core, void *stats, + size_t stats_len); + +/** + * @brief Reset the stats associated with the kernel object + * + * This function resets the statistics associated with the kernel object core + * specified by @a obj_core. + * + * @param obj_core Pointer to kernel object core + * + * @retval 0 on success + * @retval -errno on failure + */ +int k_obj_core_stats_reset(struct k_obj_core *obj_core); + +/** + * @brief Stop gathering the stats associated with the kernel object + * + * This function temporarily stops the gathering of statistics associated with + * the kernel object core specified by @a obj_core. The gathering of statistics + * can be resumed by invoking :c:func :`k_obj_core_stats_enable`. + * + * @param obj_core Pointer to kernel object core + * + * @retval 0 on success + * @retval -errno on failure + */ +int k_obj_core_stats_disable(struct k_obj_core *obj_core); + +/** + * @brief Reset the stats associated with the kernel object + * + * This function resumes the gathering of statistics associated with the kernel + * object core specified by @a obj_core. + * + * @param obj_core Pointer to kernel object core + * + * @retval 0 on success + * @retval -errno on failure + */ +int k_obj_core_stats_enable(struct k_obj_core *obj_core); + +/** @} */ +#endif /* __KERNEL_OBJ_CORE_H__ */ diff --git a/include/zephyr/kernel/thread.h b/include/zephyr/kernel/thread.h index eaed5b5d21d..b152dfb909a 100644 --- a/include/zephyr/kernel/thread.h +++ b/include/zephyr/kernel/thread.h @@ -8,7 +8,7 @@ #define ZEPHYR_INCLUDE_KERNEL_THREAD_H_ #ifdef CONFIG_DEMAND_PAGING_THREAD_STATS -#include +#include #endif #include @@ -121,8 +121,12 @@ struct _thread_base { #ifdef CONFIG_SCHED_CPU_MASK /* "May run on" bits for each CPU */ +#if CONFIG_MP_MAX_NUM_CPUS <= 8 uint8_t cpu_mask; +#else + uint16_t cpu_mask; #endif +#endif /* CONFIG_SCHED_CPU_MASK */ /* data returned by APIs */ void *swap_data; @@ -343,6 +347,15 @@ struct k_thread { struct _pipe_desc pipe_desc; #endif +#ifdef CONFIG_OBJ_CORE_THREAD + struct k_obj_core obj_core; +#endif + +#ifdef CONFIG_SMP + /** threads waiting in k_thread_suspend() */ + _wait_q_t halt_queue; +#endif + /** arch-specifics: must always be at the end */ struct _thread_arch arch; }; @@ -350,8 +363,4 @@ struct k_thread { typedef struct k_thread _thread_t; typedef struct k_thread *k_tid_t; -void z_init_cpu(int id); -void z_sched_ipi(void); -void z_smp_start_cpu(int id); - #endif diff --git a/include/zephyr/kernel/thread_stack.h b/include/zephyr/kernel/thread_stack.h index 41c4c5e4ebf..133f055c08f 100644 --- a/include/zephyr/kernel/thread_stack.h +++ b/include/zephyr/kernel/thread_stack.h @@ -153,51 +153,6 @@ static inline char *z_stack_ptr_align(char *ptr) extern struct z_thread_stack_element \ sym[nmemb][Z_KERNEL_STACK_LEN(size)] -/** - * @brief Obtain an extern reference to a stack - * - * This macro properly brings the symbol of a thread stack defined - * elsewhere into scope. - * - * @deprecated Use @c K_KERNEL_STACK_DECLARE() instead. - * - * @param sym Thread stack symbol name - */ -#define K_KERNEL_STACK_EXTERN(sym) __DEPRECATED_MACRO \ - extern k_thread_stack_t sym[] - -/** - * @brief Obtain an extern reference to a stack array - * - * This macro properly brings the symbol of a stack array defined - * elsewhere into scope. - * - * @deprecated Use @c K_KERNEL_STACK_ARRAY_DECLARE() instead. - * - * @param sym Thread stack symbol name - * @param nmemb Number of stacks defined - * @param size Size of the stack memory region - */ -#define K_KERNEL_STACK_ARRAY_EXTERN(sym, nmemb, size) __DEPRECATED_MACRO \ - extern struct z_thread_stack_element \ - sym[nmemb][Z_KERNEL_STACK_LEN(size)] - -/** - * @brief Obtain an extern reference to a pinned stack array - * - * This macro properly brings the symbol of a pinned stack array - * defined elsewhere into scope. - * - * @deprecated Use @c K_KERNEL_PINNED_STACK_ARRAY_DECLARE() instead. - * - * @param sym Thread stack symbol name - * @param nmemb Number of stacks defined - * @param size Size of the stack memory region - */ -#define K_KERNEL_PINNED_STACK_ARRAY_EXTERN(sym, nmemb, size) __DEPRECATED_MACRO \ - extern struct z_thread_stack_element \ - sym[nmemb][Z_KERNEL_STACK_LEN(size)] - /** * @brief Define a toplevel kernel stack memory region in specified section * @@ -342,8 +297,6 @@ static inline char *Z_KERNEL_STACK_BUFFER(k_thread_stack_t *sym) #define Z_THREAD_STACK_BUFFER Z_KERNEL_STACK_BUFFER #define K_THREAD_STACK_DECLARE K_KERNEL_STACK_DECLARE #define K_THREAD_STACK_ARRAY_DECLARE K_KERNEL_STACK_ARRAY_DECLARE -#define K_THREAD_STACK_EXTERN K_KERNEL_STACK_EXTERN -#define K_THREAD_STACK_ARRAY_EXTERN K_KERNEL_STACK_ARRAY_EXTERN #define K_THREAD_PINNED_STACK_DEFINE K_KERNEL_PINNED_STACK_DEFINE #define K_THREAD_PINNED_STACK_ARRAY_DEFINE \ K_KERNEL_PINNED_STACK_ARRAY_DEFINE @@ -467,35 +420,6 @@ static inline char *Z_KERNEL_STACK_BUFFER(k_thread_stack_t *sym) extern struct z_thread_stack_element \ sym[nmemb][K_THREAD_STACK_LEN(size)] -/** - * @brief Obtain an extern reference to a stack - * - * This macro properly brings the symbol of a thread stack defined - * elsewhere into scope. - * - * @deprecated Use @c K_THREAD_STACK_DECLARE() instead. - * - * @param sym Thread stack symbol name - */ -#define K_THREAD_STACK_EXTERN(sym) __DEPRECATED_MACRO \ - extern k_thread_stack_t sym[] - -/** - * @brief Obtain an extern reference to a thread stack array - * - * This macro properly brings the symbol of a stack array defined - * elsewhere into scope. - * - * @deprecated Use @c K_THREAD_STACK_ARRAY_DECLARE() instead. - * - * @param sym Thread stack symbol name - * @param nmemb Number of stacks defined - * @param size Size of the stack memory region - */ -#define K_THREAD_STACK_ARRAY_EXTERN(sym, nmemb, size) __DEPRECATED_MACRO \ - extern struct z_thread_stack_element \ - sym[nmemb][K_THREAD_STACK_LEN(size)] - /** * @brief Return the size in bytes of a stack memory region * @@ -701,13 +625,13 @@ static inline char *Z_KERNEL_STACK_BUFFER(k_thread_stack_t *sym) * A user thread can only be started with a stack defined in this way if * the thread starting it is in supervisor mode. * - * This is now deprecated, as stacks defined in this way are not usable from - * user mode. Use K_KERNEL_STACK_MEMBER. + * @deprecated This is now deprecated, as stacks defined in this way are not + * usable from user mode. Use K_KERNEL_STACK_MEMBER. * * @param sym Thread stack symbol name * @param size Size of the stack memory region */ -#define K_THREAD_STACK_MEMBER(sym, size) \ +#define K_THREAD_STACK_MEMBER(sym, size) __DEPRECATED_MACRO \ Z_THREAD_STACK_DEFINE_IN(sym, size,) /** @} */ diff --git a/include/zephyr/kernel_includes.h b/include/zephyr/kernel_includes.h index 4e19fa1bd96..752c92da46d 100644 --- a/include/zephyr/kernel_includes.h +++ b/include/zephyr/kernel_includes.h @@ -13,6 +13,10 @@ #ifndef ZEPHYR_INCLUDE_KERNEL_INCLUDES_H_ #define ZEPHYR_INCLUDE_KERNEL_INCLUDES_H_ +#ifndef ZEPHYR_INCLUDE_KERNEL_H_ +#error Please do not include kernel-specific headers directly, use instead +#endif + #include #include #include @@ -20,13 +24,13 @@ #include #include #include -#include +#include #include #include #include #include +#include #include -#include #include #include #include @@ -40,5 +44,7 @@ #include #include #include +/* FIXME This needs to be removed. Exposes some private APIs to SOF */ +#include #endif /* ZEPHYR_INCLUDE_KERNEL_INCLUDES_H_ */ diff --git a/include/zephyr/kernel_structs.h b/include/zephyr/kernel_structs.h index aa1379d66af..986165006eb 100644 --- a/include/zephyr/kernel_structs.h +++ b/include/zephyr/kernel_structs.h @@ -23,12 +23,13 @@ #if !defined(_ASMLANGUAGE) #include #include -#include +#include #include #include #include #include #include +#include #endif #ifdef __cplusplus @@ -59,9 +60,12 @@ extern "C" { /* Thread is suspended */ #define _THREAD_SUSPENDED (BIT(4)) -/* Thread is being aborted */ +/* Thread is in the process of aborting */ #define _THREAD_ABORTING (BIT(5)) +/* Thread is in the process of suspending */ +#define _THREAD_SUSPENDING (BIT(6)) + /* Thread is present in the ready queue */ #define _THREAD_QUEUED (BIT(7)) @@ -141,8 +145,12 @@ struct _cpu { uint32_t usage0; #ifdef CONFIG_SCHED_THREAD_USAGE_ALL - struct k_cycle_stats usage; + struct k_cycle_stats *usage; +#endif #endif + +#ifdef CONFIG_OBJ_CORE_SYSTEM + struct k_obj_core obj_core; #endif /* Per CPU architecture specifics */ @@ -183,6 +191,13 @@ struct z_kernel { #if defined(CONFIG_THREAD_MONITOR) struct k_thread *threads; /* singly linked list of ALL threads */ #endif +#ifdef CONFIG_SCHED_THREAD_USAGE_ALL + struct k_cycle_stats usage[CONFIG_MP_MAX_NUM_CPUS]; +#endif + +#ifdef CONFIG_OBJ_CORE_SYSTEM + struct k_obj_core obj_core; +#endif #if defined(CONFIG_SMP) && defined(CONFIG_SCHED_IPI_SUPPORTED) /* Need to signal an IPI at the next scheduling point */ @@ -205,7 +220,7 @@ bool z_smp_cpu_mobile(void); #define _current_cpu ({ __ASSERT_NO_MSG(!z_smp_cpu_mobile()); \ arch_curr_cpu(); }) -#define _current z_current_get() +#define _current k_sched_current_thread_query() #else #define _current_cpu (&_kernel.cpus[0]) @@ -220,7 +235,7 @@ typedef struct { struct _priq_rb waitq; } _wait_q_t; -extern bool z_priq_rb_lessthan(struct rbnode *a, struct rbnode *b); +bool z_priq_rb_lessthan(struct rbnode *a, struct rbnode *b); #define Z_WAIT_Q_INIT(wait_q) { { { .lessthan_fn = z_priq_rb_lessthan } } } diff --git a/include/zephyr/kernel_version.h b/include/zephyr/kernel_version.h index 6d3109fed30..7a21b437768 100644 --- a/include/zephyr/kernel_version.h +++ b/include/zephyr/kernel_version.h @@ -44,7 +44,7 @@ extern "C" { * * @return kernel version */ -extern uint32_t sys_kernel_version_get(void); +uint32_t sys_kernel_version_get(void); /** * @} diff --git a/include/zephyr/linker/common-ram.ld b/include/zephyr/linker/common-ram.ld index 8ae67c73257..c03351abf98 100644 --- a/include/zephyr/linker/common-ram.ld +++ b/include/zephyr/linker/common-ram.ld @@ -23,6 +23,15 @@ . = ALIGN(CONFIG_ARCH_SW_ISR_TABLE_ALIGN); *(_SW_ISR_TABLE_SECTION_SYMS) } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + +#if defined(CONFIG_SHARED_INTERRUPTS) + SECTION_DATA_PROLOGUE(shared_sw_isr_table,,) + { + /* TODO: does this section require alignment? */ + KEEP(*(_SHARED_SW_ISR_TABLE_SECTION_SYMS)) + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) +#endif + #endif SECTION_DATA_PROLOGUE(device_states,,) @@ -71,7 +80,10 @@ ITERABLE_SECTION_RAM_GC_ALLOWED(k_sem, 4) ITERABLE_SECTION_RAM_GC_ALLOWED(k_event, 4) ITERABLE_SECTION_RAM_GC_ALLOWED(k_queue, 4) + ITERABLE_SECTION_RAM_GC_ALLOWED(k_fifo, 4) + ITERABLE_SECTION_RAM_GC_ALLOWED(k_lifo, 4) ITERABLE_SECTION_RAM_GC_ALLOWED(k_condvar, 4) + ITERABLE_SECTION_RAM_GC_ALLOWED(sys_mem_blocks_ptr, 4) ITERABLE_SECTION_RAM(net_buf_pool, 4) diff --git a/include/zephyr/linker/common-rom/common-rom-kernel-devices.ld b/include/zephyr/linker/common-rom/common-rom-kernel-devices.ld index 6b26691fa59..dfa19d13492 100644 --- a/include/zephyr/linker/common-rom/common-rom-kernel-devices.ld +++ b/include/zephyr/linker/common-rom/common-rom-kernel-devices.ld @@ -22,6 +22,26 @@ ITERABLE_SECTION_ROM_NUMERIC(device, 4) +#if defined(CONFIG_GEN_SW_ISR_TABLE) && defined(CONFIG_SHARED_INTERRUPTS) + /* since z_shared_isr() is not referenced anywhere when + * zephyr_pre0.elf is built, the linker will end up dropping it. + * Later on, during the second linking stage (when zephyr.elf is + * built), the symbol will be added to the text section since it's + * now being referenced (thanks to isr_tables.c). This is very + * problematic because adding the z_shared_isr symbol between + * the linking stages will end up shifting the addresses of the + * functions, which, in turn, will end up messing the ISR table + * (as the entries from _sw_isr_table will end up pointing to + * old addresses of the registered ISRs). To prevent this from + * happening, instruct the linker to avoid dropping z_shared_isr + * if it's not being referenced anywhere. + */ + SECTION_PROLOGUE(.text.z_shared_isr,,) + { + KEEP(*(.text.z_shared_isr)) + } GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) +#endif + #if defined(CONFIG_GEN_SW_ISR_TABLE) && !defined(CONFIG_DYNAMIC_INTERRUPTS) SECTION_PROLOGUE(sw_isr_table,,) { @@ -33,6 +53,15 @@ . = ALIGN(CONFIG_ARCH_SW_ISR_TABLE_ALIGN); *(_SW_ISR_TABLE_SECTION_SYMS) } GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + +#if defined(CONFIG_SHARED_INTERRUPTS) + SECTION_PROLOGUE(shared_sw_isr_table,,) + { + /* TODO: does this section require alignment? */ + KEEP(*(_SHARED_SW_ISR_TABLE_SECTION_SYMS)) + } GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) +#endif + #endif /* verify we don't have rogue .z_init_ initlevel sections */ @@ -46,7 +75,7 @@ /* Build-time assignment of permissions to kernel objects to * threads declared with K_THREAD_DEFINE() */ - ITERABLE_SECTION_ROM(z_object_assignment, 4) + ITERABLE_SECTION_ROM(k_object_assignment, 4) #endif SECTION_DATA_PROLOGUE(app_shmem_regions,,) diff --git a/include/zephyr/linker/common-rom/common-rom-logging.ld b/include/zephyr/linker/common-rom/common-rom-logging.ld index f39fed01b21..9bb3e34626c 100644 --- a/include/zephyr/linker/common-rom/common-rom-logging.ld +++ b/include/zephyr/linker/common-rom/common-rom-logging.ld @@ -2,7 +2,14 @@ #include +#if defined(CONFIG_LOG_FMT_SECTION_STRIP) && defined(DEVNULL_REGION) + SECTION_PROLOGUE(log_strings,(COPY),SUBALIGN(4)) + { + Z_LINK_ITERABLE(log_strings); + } GROUP_ROM_LINK_IN(DEVNULL_REGION, DEVNULL_REGION) +#else ITERABLE_SECTION_ROM(log_strings, 4) +#endif ITERABLE_SECTION_ROM(log_const, 4) diff --git a/include/zephyr/linker/common-rom/common-rom-misc.ld b/include/zephyr/linker/common-rom/common-rom-misc.ld index 74657c847a1..1fbf777ba55 100644 --- a/include/zephyr/linker/common-rom/common-rom-misc.ld +++ b/include/zephyr/linker/common-rom/common-rom-misc.ld @@ -39,6 +39,10 @@ ITERABLE_SECTION_ROM(zbus_channel_observation, 4) #endif /* CONFIG_ZBUS */ +#ifdef CONFIG_LLEXT + ITERABLE_SECTION_ROM(llext_const_symbol, 4) +#endif /* CONFIG_LLEXT */ + SECTION_DATA_PROLOGUE(symbol_to_keep,,) { __symbol_to_keep_start = .; @@ -55,3 +59,11 @@ ITERABLE_SECTION_ROM(shell_dynamic_subcmds, 4) ITERABLE_SECTION_ROM(cfb_font, 4) + +#if defined(CONFIG_GNSS) + ITERABLE_SECTION_ROM(gnss_data_callback, 4) +#endif + +#if defined(CONFIG_GNSS_SATELLITES) + ITERABLE_SECTION_ROM(gnss_satellites_callback, 4) +#endif diff --git a/include/zephyr/linker/common-rom/common-rom-net.ld b/include/zephyr/linker/common-rom/common-rom-net.ld index e535f5f1fd0..71c1c1e089f 100644 --- a/include/zephyr/linker/common-rom/common-rom-net.ld +++ b/include/zephyr/linker/common-rom/common-rom-net.ld @@ -17,3 +17,7 @@ #if defined(CONFIG_HTTP_SERVER) ITERABLE_SECTION_ROM(http_service_desc, 4) #endif + +#if defined(CONFIG_COAP_SERVER) + ITERABLE_SECTION_ROM(coap_service, 4) +#endif diff --git a/include/zephyr/linker/irq-vector-table-section.ld b/include/zephyr/linker/irq-vector-table-section.ld index af4da725706..17c483db98f 100644 --- a/include/zephyr/linker/irq-vector-table-section.ld +++ b/include/zephyr/linker/irq-vector-table-section.ld @@ -6,6 +6,6 @@ KEEP(*(_IRQ_VECTOR_TABLE_SECTION_SYMS)) /* * Some ARM platforms require this symbol to be placed after the IRQ vector * table (like STM32F0). The symbol defined here is overriding the one in - * arch/arm/core/aarch32/vector_table.ld when the IRQ vector table is enbled. + * arch/arm/core/vector_table.ld when the IRQ vector table is enbled. */ _vector_end = .; diff --git a/include/zephyr/linker/kobject-text.ld b/include/zephyr/linker/kobject-text.ld index 47a989f4c23..b1c2b69e6df 100644 --- a/include/zephyr/linker/kobject-text.ld +++ b/include/zephyr/linker/kobject-text.ld @@ -18,8 +18,8 @@ PROVIDE(z_object_gperf_find = .); PROVIDE(z_object_gperf_wordlist_foreach = .); #else - PROVIDE(z_object_find = .); - PROVIDE(z_object_wordlist_foreach = .); + PROVIDE(k_object_find = .); + PROVIDE(k_object_wordlist_foreach = .); #endif #endif diff --git a/include/zephyr/linker/linker-devnull.h b/include/zephyr/linker/linker-devnull.h new file mode 100644 index 00000000000..d5455dd6da2 --- /dev/null +++ b/include/zephyr/linker/linker-devnull.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * DESCRIPTION + * Platform independent set of macros for creating a memory segment for + * aggregating data that shall be kept in the elf file but not in the binary. + */ + +#ifndef ZEPHYR_INCLUDE_LINKER_LINKER_DEVNULL_H_ + +#if defined(CONFIG_LINKER_DEVNULL_MEMORY) + +#if defined(CONFIG_XIP) +#if (!defined(ROM_ADDR) && !defined(ROM_BASE)) || !defined(ROM_SIZE) +#error "ROM_SIZE, ROM_ADDR or ROM_BASE not defined" +#endif +#endif /* CONFIG_XIP */ + +#if (!defined(RAM_ADDR) && !defined(RAM_BASE)) || !defined(RAM_SIZE) +#error "RAM_SIZE, RAM_ADDR or RAM_BASE not defined" +#endif + +#if defined(CONFIG_XIP) && !defined(ROM_ADDR) +#define ROM_ADDR ROM_BASE +#endif + +#if !defined(RAM_ADDR) +#define RAM_ADDR RAM_BASE +#endif + +#define ROM_END_ADDR (ROM_ADDR + ROM_SIZE) +#define DEVNULL_SIZE CONFIG_LINKER_DEVNULL_MEMORY_SIZE +#define ROM_DEVNULL_END_ADDR (ROM_END_ADDR + DEVNULL_SIZE) +#define MAX_ADDR UINT32_MAX + +/* Determine where to put the devnull region. It should be adjacent to the ROM + * region. If ROM starts after RAM or the distance between ROM and RAM is big + * enough to fit the devnull region then devnull region is placed just after + * the ROM region. If it cannot be done then the devnull region is placed before + * the ROM region. It is possible that the devnull region cannot be placed + * adjacent to the ROM (e.g. ROM starts at 0 and RAM follows ROM). In that + * case compilation fails and the devnull region is not supported in that + * configuration. + */ +#if !defined(CONFIG_XIP) + +#if RAM_ADDR >= DEVNULL_SIZE +#define DEVNULL_ADDR (RAM_ADDR - DEVNULL_SIZE) +#else +#define DEVNULL_ADDR (RAM_ADDR + RAM_SIZE) +#endif + +#else /* CONFIG_XIP */ + +#if ((ROM_ADDR > RAM_ADDR) && ((MAX_ADDR - ROM_END_ADDR) >= DEVNULL_SIZE)) || \ + ((ROM_END_ADDR + DEVNULL_SIZE) <= RAM_ADDR) +#define DEVNULL_ADDR ROM_END_ADDR +#elif ROM_ADDR > DEVNULL_SIZE +#define DEVNULL_ADDR (ROM_ADDR - DEVNULL_SIZE) +#else +#error "Cannot place devnull segment adjacent to ROM region." +#endif + +#endif /* CONFIG_XIP */ + +#define DEVNULL_REGION DEVNULL_ROM + +#endif /* CONFIG_LINKER_DEVNULL_MEMORY */ + +#endif /* ZEPHYR_INCLUDE_LINKER_LINKER_DEVNULL_H_ */ diff --git a/include/zephyr/linker/linker-tool-gcc.h b/include/zephyr/linker/linker-tool-gcc.h index e5364b5a3d9..ab8a3ad7f9a 100644 --- a/include/zephyr/linker/linker-tool-gcc.h +++ b/include/zephyr/linker/linker-tool-gcc.h @@ -15,7 +15,7 @@ #ifndef ZEPHYR_INCLUDE_LINKER_LINKER_TOOL_GCC_H_ #define ZEPHYR_INCLUDE_LINKER_LINKER_TOOL_GCC_H_ -#include +#include #if defined(CONFIG_ARM) #if defined(CONFIG_BIG_ENDIAN) diff --git a/include/zephyr/linker/section_tags.h b/include/zephyr/linker/section_tags.h index 65df354a7b0..5678a07325b 100644 --- a/include/zephyr/linker/section_tags.h +++ b/include/zephyr/linker/section_tags.h @@ -18,6 +18,10 @@ #define __irq_vector_table Z_GENERIC_SECTION(_IRQ_VECTOR_TABLE_SECTION_NAME) #define __sw_isr_table Z_GENERIC_SECTION(_SW_ISR_TABLE_SECTION_NAME) +#ifdef CONFIG_SHARED_INTERRUPTS +#define __shared_sw_isr_table Z_GENERIC_SECTION(_SHARED_SW_ISR_TABLE_SECTION_NAME) +#endif /* CONFIG_SHARED_INTERRUPTS */ + /* Attribute macros to place code and data into IMR memory */ #define __imr __in_section_unique(imr) #define __imrdata __in_section_unique(imrdata) @@ -45,8 +49,10 @@ #if defined(CONFIG_NOCACHE_MEMORY) #define __nocache __in_section_unique(_NOCACHE_SECTION_NAME) +#define __nocache_noinit __nocache #else #define __nocache +#define __nocache_noinit __noinit #endif /* CONFIG_NOCACHE_MEMORY */ #if defined(CONFIG_KERNEL_COHERENCE) diff --git a/include/zephyr/linker/sections.h b/include/zephyr/linker/sections.h index ff6dae15dcc..2f1049d09f3 100644 --- a/include/zephyr/linker/sections.h +++ b/include/zephyr/linker/sections.h @@ -39,6 +39,11 @@ #define _SW_ISR_TABLE_SECTION_NAME .gnu.linkonce.sw_isr_table #define _SW_ISR_TABLE_SECTION_SYMS .gnu.linkonce.sw_isr_table* +#ifdef CONFIG_SHARED_INTERRUPTS +#define _SHARED_SW_ISR_TABLE_SECTION_NAME .gnu.linkonce.shared_sw_isr_table +#define _SHARED_SW_ISR_TABLE_SECTION_SYMS .gnu.linkonce.shared_sw_isr_table* +#endif /* CONFIG_SHARED_INTERRUPTS */ + /* Architecture-specific sections */ #if defined(CONFIG_ARM) #define _KINETIS_FLASH_CONFIG_SECTION_NAME kinetis_flash_config diff --git a/include/zephyr/llext/buf_loader.h b/include/zephyr/llext/buf_loader.h new file mode 100644 index 00000000000..5a50e215bd3 --- /dev/null +++ b/include/zephyr/llext/buf_loader.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_LLEXT_BUF_LOADER_H +#define ZEPHYR_LLEXT_BUF_LOADER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief LLEXT buffer loader + * @defgroup llext_buf_loader Linkable loadable extensions buffer loader + * @ingroup llext + * @{ + */ + +/** + * @brief An extension loader from a provided buffer containing an ELF + */ +struct llext_buf_loader { + /** Extension loader */ + struct llext_loader loader; + + /** @cond ignore */ + const uint8_t *buf; + size_t len; + size_t pos; + /** @endcond */ +}; + +/** @cond ignore */ +int llext_buf_read(struct llext_loader *ldr, void *buf, size_t len); +int llext_buf_seek(struct llext_loader *ldr, size_t pos); +void *llext_buf_peek(struct llext_loader *ldr, size_t pos); +/** @endcond */ + +/** + * @brief Initialize an extension buf loader + * + * @param _buf Buffer containing an ELF binary + * @param _buf_len Buffer length in bytes + */ +#define LLEXT_BUF_LOADER(_buf, _buf_len) \ + { \ + .loader = { \ + .read = llext_buf_read, \ + .seek = llext_buf_seek, \ + .peek = llext_buf_peek, \ + }, \ + .buf = (_buf), \ + .len = (_buf_len), \ + .pos = 0 \ + } + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_LLEXT_BUF_LOADER_H */ diff --git a/include/zephyr/llext/elf.h b/include/zephyr/llext/elf.h new file mode 100644 index 00000000000..6dc3cc4e5c8 --- /dev/null +++ b/include/zephyr/llext/elf.h @@ -0,0 +1,498 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + */ +#ifndef ZEPHYR_LLEXT_ELF_H +#define ZEPHYR_LLEXT_ELF_H + +#include + +/** + * @brief ELF types and parsing + * + * Reference documents can be found here https://refspecs.linuxfoundation.org/elf/ + * + * @defgroup elf ELF data types and defines + * @ingroup llext + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Unsigned program address */ +typedef uint32_t elf32_addr; +/** Unsigned medium integer */ +typedef uint16_t elf32_half; +/** Unsigned file offset */ +typedef uint32_t elf32_off; +/** Signed integer */ +typedef int32_t elf32_sword; +/** Unsigned integer */ +typedef uint32_t elf32_word; + +/** Unsigned program address */ +typedef uint64_t elf64_addr; +/** Unsigned medium integer */ +typedef uint16_t elf64_half; +/** Unsigned file offset */ +typedef uint64_t elf64_off; +/** Signed integer */ +typedef int32_t elf64_sword; +/** Unsigned integer */ +typedef uint32_t elf64_word; +/** Signed long integer */ +typedef int64_t elf64_sxword; +/** Unsigned long integer */ +typedef uint64_t elf64_xword; + + +/** + * @brief ELF identifier block + * + * 4 byte magic (.ELF) + * 1 byte class (Invalid, 32 bit, 64 bit) + * 1 byte endianness (Invalid, LSB, MSB) + * 1 byte version (1) + * 1 byte OS ABI (0 None, 1 HP-UX, 2 NetBSD, 3 Linux) + * 1 byte ABI (0) + * 7 bytes padding + */ +#define EI_NIDENT 16 + +/** + * @brief ELF Header(32-bit) + */ +struct elf32_ehdr { + /** Magic string identifying ELF binary */ + unsigned char e_ident[EI_NIDENT]; + /** Type of ELF */ + elf32_half e_type; + /** Machine type */ + elf32_half e_machine; + /** Object file version */ + elf32_word e_version; + /** Virtual address of entry */ + elf32_addr e_entry; + /** Program header table offset */ + elf32_off e_phoff; + /** Section header table offset */ + elf32_off e_shoff; + /** Processor specific flags */ + elf32_word e_flags; + /** ELF header size */ + elf32_half e_ehsize; + /** Program header count */ + elf32_half e_phentsize; + /** Program header count */ + elf32_half e_phnum; + /** Section header size */ + elf32_half e_shentsize; + /** Section header count */ + elf32_half e_shnum; + /** Section header containing section header string table */ + elf32_half e_shstrndx; +}; + +/** + * @brief ELF Header(64-bit) + */ +struct elf64_ehdr { + /** Magic string identifying ELF binary */ + unsigned char e_ident[EI_NIDENT]; + /** Type of ELF */ + elf64_half e_type; + /** Machine type */ + elf64_half e_machine; + /** Object file version */ + elf64_word e_version; + /** Virtual address of entry */ + elf64_addr e_entry; + /** Program header table offset */ + elf64_off e_phoff; + /** Section header table offset */ + elf64_off e_shoff; + /** Processor specific flags */ + elf64_word e_flags; + /** ELF header size */ + elf64_half e_ehsize; + /** Program header size */ + elf64_half e_phentsize; + /** Program header count */ + elf64_half e_phnum; + /** Section header size */ + elf64_half e_shentsize; + /** Section header count */ + elf64_half e_shnum; + /** Section header containing section header string table */ + elf64_half e_shstrndx; +}; + +/** Relocatable (unlinked) ELF */ +#define ET_REL 1 + +/** Executable (without PIC/PIE) ELF */ +#define ET_EXEC 2 + +/** Dynamic (executable with PIC/PIE or shared lib) ELF */ +#define ET_DYN 3 + +/** Core Dump */ +#define ET_CORE 4 + +/** + * @brief Section Header(32-bit) + */ +struct elf32_shdr { + /** Section header name index in section header string table */ + elf32_word sh_name; + /** Section type */ + elf32_word sh_type; + /** Section header attributes */ + elf32_word sh_flags; + /** Address of section in the image */ + elf32_addr sh_addr; + /** Location of section in the ELF binary in bytes */ + elf32_off sh_offset; + /** Section size in bytes */ + elf32_word sh_size; + /** Section header table link index, depends on section type */ + elf32_word sh_link; + /** Section info, depends on section type */ + elf32_word sh_info; + /** Section address alignment */ + elf32_word sh_addralign; + /** Section contains table of fixed size entries sh_entsize bytes large */ + elf32_word sh_entsize; +}; + +/** + * @brief Section Header(64-bit) + */ +struct elf64_shdr { + /** Section header name index in section header string table */ + elf64_word sh_name; + /** Section type */ + elf64_word sh_type; + /** Section header attributes */ + elf64_xword sh_flags; + /** Address of section in the image */ + elf64_addr sh_addr; + /** Location of section in the ELF binary in bytes */ + elf64_off sh_offset; + /** Section size in bytes */ + elf64_xword sh_size; + /** Section header table link index, depends on section type */ + elf64_word sh_link; + /** Section info, depends on section type */ + elf64_word sh_info; + /** Section address alignment */ + elf64_xword sh_addralign; + /** Section contains table of fixed size entries sh_entsize bytes large */ + elf64_xword sh_entsize; +}; + +#define SHT_PROGBITS 0x1 +#define SHT_SYMTAB 0x2 +#define SHT_STRTAB 0x3 +#define SHT_RELA 0x4 +#define SHT_NOBITS 0x8 +#define SHT_REL 0x9 +#define SHT_DYNSYM 0xB + +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 + +/** + * @brief Symbol table entry(32-bit) + */ +struct elf32_sym { + /** Name of the symbol as an index into the symbol string table */ + elf32_word st_name; + /** Value or location of the symbol */ + elf32_addr st_value; + /** Size of the symbol */ + elf32_word st_size; + /** Symbol binding and type information */ + unsigned char st_info; + /** Symbol visibility */ + unsigned char st_other; + /** Symbols related section given by section header index */ + elf32_half st_shndx; +}; + +/** + * @brief Symbol table entry(64-bit) + */ +struct elf64_sym { + /** Name of the symbol as an index into the symbol string table */ + elf64_word st_name; + /** Value or location of the symbol */ + elf64_addr st_value; + /** Size of the symbol */ + elf64_xword st_size; + /** Symbol binding and type information */ + unsigned char st_info; + /** Symbol visibility */ + unsigned char st_other; + /** Symbols related section given by section header index */ + elf64_half st_shndx; +}; + +#define SHN_UNDEF 0 +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 + +#define STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_COMMON 5 +#define STT_LOOS 10 +#define STT_HIOS 12 +#define STT_LOPROC 13 +#define STT_HIPROC 15 + +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 +#define STB_LOOS 10 +#define STB_HIOS 12 +#define STB_LOPROC 13 +#define STB_HIPROC 15 + +/** + * @brief Symbol binding from 32bit st_info + * + * @param i Value of st_info + */ +#define ELF32_ST_BIND(i) ((i) >> 4) + +/** + * @brief Symbol type from 32bit st_info + * + * @param i Value of st_info + */ +#define ELF32_ST_TYPE(i) ((i) & 0xf) + +/** + * @brief Symbol binding from 32bit st_info + * + * @param i Value of st_info + */ +#define ELF64_ST_BIND(i) ((i) >> 4) + + +/** + * @brief Symbol type from 32bit st_info + * + * @param i Value of st_info + */ +#define ELF64_ST_TYPE(i) ((i) & 0xf) + +/** + * @brief Relocation entry for 32-bit ELFs + */ +struct elf32_rel { + /** Offset in the section to perform a relocation */ + elf32_addr r_offset; + + /** Information about the relocation, related symbol and type */ + elf32_word r_info; +}; + +struct elf32_rela { + elf32_addr r_offset; + elf32_word r_info; + elf32_word r_addend; +}; + +/** + * @brief Relocation symbol index from r_info + * + * @param i Value of r_info + */ +#define ELF32_R_SYM(i) ((i) >> 8) + +/** + * @brief Relocation type from r_info + * + * @param i Value of r_info + */ +#define ELF32_R_TYPE(i) ((i) & 0xff) + +/** + * @brief Relocation entry for 64-bit ELFs + */ +struct elf64_rel { + /** Offset in section to perform a relocation */ + elf64_addr r_offset; + /** Information about relocation, related symbol and type */ + elf64_xword r_info; +}; + +struct elf64_rela { + elf64_addr r_offset; + elf64_word r_info; + elf64_word r_addend; +}; + +/** @brief Relocation symbol from r_info + * + * @param i Value of r_info + */ +#define ELF64_R_SYM(i) ((i) >> 32) + +/** + * @brief Relocation type from r_info + * + * @param i Value of r_info + */ +#define ELF64_R_TYPE(i) ((i) & 0xffffffff) + +#define R_386_NONE 0 +#define R_386_32 1 +#define R_386_PC32 2 +#define R_386_GOT32 3 +#define R_386_PLT32 4 +#define R_386_COPY 5 +#define R_386_GLOB_DAT 6 +#define R_386_JMP_SLOT 7 +#define R_386_RELATIVE 8 +#define R_386_GOTOFF 9 + +#define R_ARM_NONE 0 +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 +#define R_ARM_REL32 3 +#define R_ARM_COPY 4 +#define R_ARM_CALL 28 +#define R_ARM_V4BX 40 + +#define R_XTENSA_NONE 0 +#define R_XTENSA_32 1 +#define R_XTENSA_SLOT0_OP 20 + +/** + * @brief Program header(32-bit) + */ +struct elf32_phdr { + elf32_word p_type; + elf32_off p_offset; + elf32_addr p_vaddr; + elf32_addr p_paddr; + elf32_word p_filesz; + elf32_word p_memsz; + elf32_word p_flags; + elf32_word p_align; +}; + +/** + * @brief Program header(64-bit) + */ +struct elf64_phdr { + elf64_word p_type; + elf64_off p_offset; + elf64_addr p_vaddr; + elf64_addr p_paddr; + elf64_xword p_filesz; + elf64_xword p_memsz; + elf64_word p_flags; + elf64_xword p_align; +}; + +/** + * @brief Program segment type + */ +#define PT_LOAD 1 + +/** + * @brief Dynamic section entry(32-bit) + */ +struct elf32_dyn { + elf32_sword d_tag; + union { + elf32_word d_val; + elf32_addr d_ptr; + } d_un; +}; + +/** + * @brief Dynamic section entry(64-bit) + */ +struct elf64_dyn { + elf64_sxword d_tag; + union { + elf64_xword d_val; + elf64_addr d_ptr; + } d_un; +}; + +#if defined(CONFIG_64BIT) || defined(__DOXYGEN__) +/** Machine sized elf header structure */ +typedef struct elf64_ehdr elf_ehdr_t; +/** Machine sized section header structure */ +typedef struct elf64_shdr elf_shdr_t; +/** Machine sized program header structure */ +typedef struct elf64_phdr elf_phdr_t; +/** Machine sized program address */ +typedef elf64_addr elf_addr; +/** Machine sized small integer */ +typedef elf64_half elf_half; +/** Machine sized integer */ +typedef elf64_xword elf_word; +/** Machine sized relocation struct */ +typedef struct elf64_rel elf_rel_t; +typedef struct elf64_rela elf_rela_t; +/** Machine sized symbol struct */ +typedef struct elf64_sym elf_sym_t; +/** Machine sized macro alias for obtaining a relocation symbol */ +#define ELF_R_SYM ELF64_R_SYM +/** Machine sized macro alias for obtaining a relocation type */ +#define ELF_R_TYPE ELF64_R_TYPE +/** Machine sized macro alias for obtaining a symbol bind */ +#define ELF_ST_BIND ELF64_ST_BIND +/** Machine sized macro alias for obtaining a symbol type */ +#define ELF_ST_TYPE ELF64_ST_TYPE +#else +/** Machine sized elf header structure */ +typedef struct elf32_ehdr elf_ehdr_t; +/** Machine sized section header structure */ +typedef struct elf32_shdr elf_shdr_t; +/** Machine sized program header structure */ +typedef struct elf32_phdr elf_phdr_t; +/** Machine sized program address */ +typedef elf32_addr elf_addr; +/** Machine sized small integer */ +typedef elf32_half elf_half; +/** Machine sized integer */ +typedef elf32_word elf_word; +/** Machine sized relocation struct */ +typedef struct elf32_rel elf_rel_t; +typedef struct elf32_rela elf_rela_t; +/** Machine sized symbol struct */ +typedef struct elf32_sym elf_sym_t; +/** Machine sized macro alias for obtaining a relocation symbol */ +#define ELF_R_SYM ELF32_R_SYM +/** Machine sized macro alias for obtaining a relocation type */ +#define ELF_R_TYPE ELF32_R_TYPE +/** Machine sized macro alias for obtaining a symbol bind */ +#define ELF_ST_BIND ELF32_ST_BIND +/** Machine sized macro alias for obtaining a symbol type */ +#define ELF_ST_TYPE ELF32_ST_TYPE +#endif + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* ZEPHYR_LLEXT_ELF_H */ diff --git a/include/zephyr/llext/llext.h b/include/zephyr/llext/llext.h new file mode 100644 index 00000000000..a4458a05468 --- /dev/null +++ b/include/zephyr/llext/llext.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_LLEXT_H +#define ZEPHYR_LLEXT_H + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Linkable loadable extensions + * @defgroup llext Linkable loadable extensions + * @ingroup os_services + * @{ + */ + +/** + * @brief Enum of memory regions for lookup tables + */ +enum llext_mem { + LLEXT_MEM_TEXT, + LLEXT_MEM_DATA, + LLEXT_MEM_RODATA, + LLEXT_MEM_BSS, + LLEXT_MEM_SYMTAB, + LLEXT_MEM_STRTAB, + LLEXT_MEM_SHSTRTAB, + + LLEXT_MEM_COUNT, +}; + +/** + * @brief Linkable loadable extension + */ +struct llext { + /** @cond ignore */ + sys_snode_t _llext_list; + /** @endcond */ + + /** Name of the llext */ + char name[16]; + + /** Lookup table of llext memory regions */ + void *mem[LLEXT_MEM_COUNT]; + + /** Memory allocated on heap */ + bool mem_on_heap[LLEXT_MEM_COUNT]; + + /** Total size of the llext memory usage */ + size_t mem_size; + + /** Exported symbols from the llext, may be linked against by other llext */ + struct llext_symtable sym_tab; +}; + +/** + * @brief List head of loaded extensions + */ +sys_slist_t *llext_list(void); + +/** + * @brief Find an llext by name + * + * @param[in] name String name of the llext + * @retval NULL if no llext not found + * @retval llext if llext found + */ +struct llext *llext_by_name(const char *name); + +/** + * @brief Load and link an extension + * + * Loads relevant ELF data into memory and provides a structure to work with it. + * + * Only relocatable ELF files are currently supported (partially linked). + * + * @param[in] loader An extension loader that provides input data and context + * @param[in] name A string identifier for the extension + * @param[out] ext A pointer to a statically allocated llext struct + * + * @retval 0 Success + * @retval -ENOMEM Not enough memory + * @retval -EINVAL Invalid ELF stream + */ +int llext_load(struct llext_loader *loader, const char *name, struct llext **ext); + +/** + * @brief Unload an extension + * + * @param[in] ext Extension to unload + */ +void llext_unload(struct llext *ext); + +/** + * @brief Find the address for an arbitrary symbol name. + * + * @param[in] sym_table Symbol table to lookup symbol in, if NULL uses base table + * @param[in] sym_name Symbol name to find + * + * @retval NULL if no symbol found + * @retval addr Address of symbol in memory if found + */ +const void * const llext_find_sym(const struct llext_symtable *sym_table, const char *sym_name); + +/** + * @brief Call a function by name + * + * Expects a symbol representing a void fn(void) style function exists + * and may be called. + * + * @param[in] ext Extension to call function in + * @param[in] sym_name Function name (exported symbol) in the extension + * + * @retval 0 success + * @retval -EINVAL invalid symbol name + */ +int llext_call_fn(struct llext *ext, const char *sym_name); + +/** + * @brief Architecture specific function for updating op codes given a relocation + * + * Elf files contain a series of relocations described in a section. These relocation + * instructions are architecture specific and each architecture supporting extensions + * must implement this. They are instructions on how to rewrite opcodes given + * the actual placement of some symbolic data such as a section, function, + * or object. + * + * @param[in] rel Relocation data provided by elf + * @param[in] opaddr Address of operation to rewrite with relocation + * @param[in] opval Value of looked up symbol to relocate + */ +void arch_elf_relocate(elf_rela_t *rel, uintptr_t opaddr, uintptr_t opval); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_LLEXT_H */ diff --git a/include/zephyr/llext/loader.h b/include/zephyr/llext/loader.h new file mode 100644 index 00000000000..3102f17cf1a --- /dev/null +++ b/include/zephyr/llext/loader.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_LLEXT_LOADER_H +#define ZEPHYR_LLEXT_LOADER_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Loader context for llext + * @defgroup llext_loader Loader context for llext + * @ingroup llext + * @{ + */ + +/** + * @brief Enum of sections for lookup tables + */ +enum llext_section { + LLEXT_SECT_TEXT, + LLEXT_SECT_DATA, + LLEXT_SECT_RODATA, + LLEXT_SECT_BSS, + + LLEXT_SECT_REL_TEXT, + LLEXT_SECT_REL_DATA, + LLEXT_SECT_REL_RODATA, + LLEXT_SECT_REL_BSS, + + LLEXT_SECT_SYMTAB, + LLEXT_SECT_STRTAB, + LLEXT_SECT_SHSTRTAB, + + LLEXT_SECT_COUNT, +}; + +enum llext_mem; + +/** + * @brief Linkable loadable extension loader context + */ +struct llext_loader { + /** + * @brief Read (copy) from the loader + * + * Copies len bytes into buf from the current position of the + * loader. + * + * @param[in] ldr Loader + * @param[in] out Output location + * @param[in] len Length to copy into the output location + * + * @retval 0 Success + * @retval -errno Error reading (any errno) + */ + int (*read)(struct llext_loader *ldr, void *out, size_t len); + + /** + * @brief Seek to a new absolute location + * + * Changes the location of the loader position to a new absolute + * given position. + * + * @param[in] ldr Loader + * @param[in] pos Position in stream to move loader + * + * @retval 0 Success + * @retval -errno Error reading (any errno) + */ + int (*seek)(struct llext_loader *ldr, size_t pos); + + /** + * @brief Peek at an absolute location + * + * Return a pointer to the buffer at specified offset. + * + * @param[in] ldr Loader + * @param[in] pos Position to obtain a pointer to + * + * @retval pointer into the buffer + */ + void *(*peek)(struct llext_loader *ldr, size_t pos); + + /** @cond ignore */ + elf_ehdr_t hdr; + elf_shdr_t sects[LLEXT_SECT_COUNT]; + enum llext_mem *sect_map; + uint32_t sect_cnt; + /** @endcond */ +}; + +static inline int llext_read(struct llext_loader *l, void *buf, size_t len) +{ + return l->read(l, buf, len); +} + +static inline int llext_seek(struct llext_loader *l, size_t pos) +{ + return l->seek(l, pos); +} + +static inline void *llext_peek(struct llext_loader *l, size_t pos) +{ + if (l->peek) { + return l->peek(l, pos); + } + + return NULL; +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_LLEXT_LOADER_H */ diff --git a/include/zephyr/llext/symbol.h b/include/zephyr/llext/symbol.h new file mode 100644 index 00000000000..84e43d22b5b --- /dev/null +++ b/include/zephyr/llext/symbol.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_LLEXT_SYMBOL_H +#define ZEPHYR_LLEXT_SYMBOL_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +/** + * @brief Linkable loadable extension symbol + * @defgroup llext_symbols LLEXT symbols + * @ingroup llext + * @{ + */ + +/** + * @brief Constant symbols are unchangeable named memory addresses + * + * Symbols may be named function or global objects that have been exported + * for linking. These constant symbols are useful in the base image + * as they may be placed in ROM. + */ +struct llext_const_symbol { + /** Name of symbol */ + const char *const name; + + /** Address of symbol */ + const void *const addr; +}; + +/** + * @brief Symbols are named memory addresses + * + * Symbols may be named function or global objects that have been exported + * for linking. These are mutable and should come from extensions where + * the location may need updating depending on where memory is placed. + */ +struct llext_symbol { + /** Name of symbol */ + const char *name; + + /** Address of symbol */ + void *addr; +}; + + +/** + * @brief A symbol table + * + * An array of symbols + */ +struct llext_symtable { + /** Number of symbols in the table */ + size_t sym_cnt; + + /** Array of symbols */ + struct llext_symbol *syms; +}; + + +/** + * @brief Export a constant symbol to a table of symbols + * + * Takes a symbol (function or object) by symbolic name and adds the name + * and address of the symbol to a table of symbols that may be used for linking. + * + * @param x Symbol to export + */ +#define EXPORT_SYMBOL(x) \ + static const STRUCT_SECTION_ITERABLE(llext_const_symbol, x ## _sym) = { \ + .name = STRINGIFY(x), .addr = &x, \ + } + +/** + * @brief Export a system call to a table of symbols + * + * Takes a system call name and uses @a EXPORT_SYMBOL() to export the respective + * function. + * + * @param x System call to export + */ +#define EXPORT_SYSCALL(x) EXPORT_SYMBOL(z_impl_ ## x) + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + + +#endif /* ZEPHYR_LLEXT_SYMBOL_H */ diff --git a/include/zephyr/logging/log.h b/include/zephyr/logging/log.h index b5ee3b67ab4..d04f5b1ab82 100644 --- a/include/zephyr/logging/log.h +++ b/include/zephyr/logging/log.h @@ -290,7 +290,7 @@ void z_log_vprintk(const char *fmt, va_list ap); #define _LOG_LEVEL_RESOLVE(...) LOG_LEVEL_NONE #else #define _LOG_LEVEL_RESOLVE(...) \ - Z_LOG_EVAL(LOG_LEVEL, \ + Z_LOG_EVAL(COND_CODE_0(LOG_LEVEL, (1), (LOG_LEVEL)), \ (GET_ARG_N(2, __VA_ARGS__, LOG_LEVEL)), \ (GET_ARG_N(2, __VA_ARGS__, CONFIG_LOG_DEFAULT_LEVEL))) #endif @@ -298,14 +298,19 @@ void z_log_vprintk(const char *fmt, va_list ap); /* Return first argument */ #define _LOG_ARG1(arg1, ...) arg1 -#define _LOG_MODULE_CONST_DATA_CREATE(_name, _level) \ - IF_ENABLED(LOG_IN_CPLUSPLUS, (extern)) \ - const STRUCT_SECTION_ITERABLE_ALTERNATE(log_const, \ - log_source_const_data, \ - Z_LOG_ITEM_CONST_DATA(_name)) = \ - { \ - .name = STRINGIFY(_name), \ - .level = _level \ +#define _LOG_MODULE_CONST_DATA_CREATE(_name, _level) \ + IF_ENABLED(CONFIG_LOG_FMT_SECTION, ( \ + static const char UTIL_CAT(_name, _str)[] \ + __in_section(_log_strings, static, _CONCAT(_name, _)) __used __noasan = \ + STRINGIFY(_name);)) \ + IF_ENABLED(LOG_IN_CPLUSPLUS, (extern)) \ + const STRUCT_SECTION_ITERABLE_ALTERNATE(log_const, \ + log_source_const_data, \ + Z_LOG_ITEM_CONST_DATA(_name)) = \ + { \ + .name = COND_CODE_1(CONFIG_LOG_FMT_SECTION, \ + (UTIL_CAT(_name, _str)), (STRINGIFY(_name))), \ + .level = _level \ } #define _LOG_MODULE_DYNAMIC_DATA_CREATE(_name) \ @@ -324,10 +329,11 @@ void z_log_vprintk(const char *fmt, va_list ap); * is enabled, override level is set or module specific level is set (not off). */ #define Z_DO_LOG_MODULE_REGISTER(...) \ - Z_LOG_EVAL(CONFIG_LOG_OVERRIDE_LEVEL, \ + COND_CODE_1(CONFIG_LOG, \ + (Z_LOG_EVAL(CONFIG_LOG_OVERRIDE_LEVEL, \ (1), \ (Z_LOG_EVAL(_LOG_LEVEL_RESOLVE(__VA_ARGS__), (1), (0))) \ - ) + )), (0)) /** * @brief Create module-specific state and register the module with Logger. diff --git a/include/zephyr/logging/log_backend_net.h b/include/zephyr/logging/log_backend_net.h new file mode 100644 index 00000000000..9141b481b8d --- /dev/null +++ b/include/zephyr/logging/log_backend_net.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 David Corbeil + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_LOG_BACKEND_NET_H_ +#define ZEPHYR_LOG_BACKEND_NET_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Allows user to set a server IP address at runtime + * + * @details This function allows the user to set an IPv4 or IPv6 address at runtime. It can be + * called either before or after the backend has been initialized. If it gets called when + * the net logger backend context is running, it'll release it and create another one with + * the new address next time process() gets called. + * + * @param addr String that contains the IP address. + * + * @return True if parsing could be done, false otherwise. + */ +bool log_backend_net_set_addr(const char *addr); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_LOG_BACKEND_NET_H_ */ diff --git a/include/zephyr/logging/log_core.h b/include/zephyr/logging/log_core.h index 869dcc8643e..bc4cb2d8f36 100644 --- a/include/zephyr/logging/log_core.h +++ b/include/zephyr/logging/log_core.h @@ -84,8 +84,6 @@ extern "C" { #define Z_LOG_EVAL1(_eval_level, _iftrue, _iffalse) \ __COND_CODE(_LOG_ZZZZ##_eval_level, _iftrue, _iffalse) -#define _LOG_ZZZZ0 _LOG_YYYY, -#define _LOG_ZZZZ0U _LOG_YYYY, #define _LOG_ZZZZ1 _LOG_YYYY, #define _LOG_ZZZZ1U _LOG_YYYY, #define _LOG_ZZZZ2 _LOG_YYYY, @@ -251,13 +249,15 @@ static inline char z_log_minimal_level_to_char(int level) #define Z_LOG(_level, ...) \ Z_LOG2(_level, 0, __log_current_const_data, __log_current_dynamic_data, __VA_ARGS__) -#define Z_LOG_INSTANCE(_level, _inst, ...) \ +#define Z_LOG_INSTANCE(_level, _inst, ...) do { \ + (void)_inst; \ Z_LOG2(_level, 1, \ COND_CODE_1(CONFIG_LOG_RUNTIME_FILTERING, (NULL), (Z_LOG_INST(_inst))), \ (struct log_source_dynamic_data *)COND_CODE_1( \ CONFIG_LOG_RUNTIME_FILTERING, \ (Z_LOG_INST(_inst)), (NULL)), \ - __VA_ARGS__) + __VA_ARGS__); \ +} while (0) /*****************************************************************************/ /****************** Macros for hexdump logging *******************************/ @@ -290,7 +290,7 @@ static inline char z_log_minimal_level_to_char(int level) break; \ } \ /* For instance logging check instance specific static level */ \ - if (_inst & !IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING)) { \ + if (_inst && !IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING)) { \ if (_level > ((struct log_source_const_data *)_source)->level) { \ break; \ } \ @@ -413,7 +413,7 @@ TYPE_SECTION_END_EXTERN(struct log_source_const_data, log_const); z_log_printf_arg_checker(__VA_ARGS__); \ } \ Z_LOG_MSG_CREATE(!IS_ENABLED(CONFIG_USERSPACE), _mode, \ - Z_LOG_LOCAL_DOMAIN_ID, (uintptr_t)_is_raw, \ + Z_LOG_LOCAL_DOMAIN_ID, (const void *)(uintptr_t)_is_raw, \ LOG_LEVEL_INTERNAL_RAW_STRING, NULL, 0, __VA_ARGS__);\ } while (0) diff --git a/include/zephyr/logging/log_frontend.h b/include/zephyr/logging/log_frontend.h index 058afa1f576..132a78eb748 100644 --- a/include/zephyr/logging/log_frontend.h +++ b/include/zephyr/logging/log_frontend.h @@ -12,7 +12,7 @@ */ void log_frontend_init(void); -/** @brief Log message. +/** @brief Log generic message. * * Message details does not contain timestamp. Since function is called in the * context of log message call, implementation can use its own timestamping scheme. @@ -32,6 +32,52 @@ void log_frontend_msg(const void *source, const struct log_msg_desc desc, uint8_t *package, const void *data); +/** @brief Log message with 0 arguments. + * + * Optimized version for log message which does not have arguments (only string). + * This API is optional and is used only if optimizing common log messages is enabled. + * + * @param source Pointer to a structure associated with given source. It points to + * static structure or dynamic structure if runtime filtering is enabled. + * @ref log_const_source_id or @ref log_dynamic_source_id can be used to determine + * source id. + * @param level Severity level. + * @param fmt String. + */ +void log_frontend_simple_0(const void *source, uint32_t level, const char *fmt); + +/** @brief Log message with 1 argument. + * + * Optimized version for log message which has one argument that fits in a 32 bit word. + * This API is optional and is used only if optimizing common log messages is enabled. + * + * @param source Pointer to a structure associated with given source. It points to + * static structure or dynamic structure if runtime filtering is enabled. + * @ref log_const_source_id or @ref log_dynamic_source_id can be used to determine + * source id. + * @param level Severity level. + * @param fmt String. + * @param arg Argument passed to the string. + */ +void log_frontend_simple_1(const void *source, uint32_t level, const char *fmt, uint32_t arg); + +/** @brief Log message with 2 arguments. + * + * Optimized version for log message which has two arguments that fit in a 32 bit word. + * This API is optional and is used only if optimizing common log messages is enabled. + * + * @param source Pointer to a structure associated with given source. It points to + * static structure or dynamic structure if runtime filtering is enabled. + * @ref log_const_source_id or @ref log_dynamic_source_id can be used to determine + * source id. + * @param level Severity level. + * @param fmt String. + * @param arg0 First argument passed to the string. + * @param arg1 Second argument passed to the string. + */ +void log_frontend_simple_2(const void *source, uint32_t level, + const char *fmt, uint32_t arg0, uint32_t arg1); + /** @brief Panic state notification. */ void log_frontend_panic(void); diff --git a/include/zephyr/logging/log_instance.h b/include/zephyr/logging/log_instance.h index 8eca2b46a71..dbaf72f3b06 100644 --- a/include/zephyr/logging/log_instance.h +++ b/include/zephyr/logging/log_instance.h @@ -137,11 +137,16 @@ struct log_source_dynamic_data { /** * @brief Declare a logger instance pointer in the module structure. * + * If logging is disabled then element in the structure is still declared to avoid + * compilation issues. If compiler supports zero length arrays then it is utilized + * to not use any space, else a byte array is created. + * * @param _name Name of a structure element that will have a pointer to logging * instance object. */ #define LOG_INSTANCE_PTR_DECLARE(_name) \ - IF_ENABLED(CONFIG_LOG, (Z_LOG_INSTANCE_STRUCT * _name)) + COND_CODE_1(CONFIG_LOG, (Z_LOG_INSTANCE_STRUCT * _name), \ + (int _name[TOOLCHAIN_HAS_ZLA ? 0 : 1])) #define Z_LOG_RUNTIME_INSTANCE_REGISTER(_module_name, _inst_name) \ STRUCT_SECTION_ITERABLE_ALTERNATE(log_dynamic, log_source_dynamic_data, \ diff --git a/include/zephyr/logging/log_msg.h b/include/zephyr/logging/log_msg.h index 0279fb0d2cd..39cbf1cedbc 100644 --- a/include/zephyr/logging/log_msg.h +++ b/include/zephyr/logging/log_msg.h @@ -79,11 +79,10 @@ struct log_msg_hdr { const void *source; log_timestamp_t timestamp; #endif -#if CONFIG_LOG_THREAD_ID_PREFIX +#if defined(CONFIG_LOG_THREAD_ID_PREFIX) void *tid; #endif }; - /* Messages are aligned to alignment required by cbprintf package. */ #define Z_LOG_MSG_ALIGNMENT CBPRINTF_PACKAGE_ALIGNMENT @@ -141,6 +140,9 @@ enum z_log_msg_mode { * more code size. */ Z_LOG_MSG_MODE_ZERO_COPY, + + /* Mode optimized for simple messages with 0 to 2 32 bit word arguments.*/ + Z_LOG_MSG_MODE_SIMPLE, }; #define Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, _plen, _dlen) \ @@ -227,6 +229,102 @@ enum z_log_msg_mode { #define Z_LOG_ARM64_VLA_PROTECT() compiler_barrier() +#define _LOG_MSG_SIMPLE_XXXX0 1 +#define _LOG_MSG_SIMPLE_XXXX1 1 +#define _LOG_MSG_SIMPLE_XXXX2 1 + +/* Determine if amount of arguments (less than 3) qualifies to simple message. */ +#define LOG_MSG_SIMPLE_ARG_CNT_CHECK(...) \ + COND_CODE_1(UTIL_CAT(_LOG_MSG_SIMPLE_XXXX, NUM_VA_ARGS_LESS_1(__VA_ARGS__)), (1), (0)) + +/* Set of marcos used to determine if arguments type allows simplified message creation mode. */ +#define LOG_MSG_SIMPLE_ARG_TYPE_CHECK_0(fmt) 1 +#define LOG_MSG_SIMPLE_ARG_TYPE_CHECK_1(fmt, arg) Z_CBPRINTF_IS_WORD_NUM(arg) +#define LOG_MSG_SIMPLE_ARG_TYPE_CHECK_2(fmt, arg0, arg1) \ + Z_CBPRINTF_IS_WORD_NUM(arg0) && Z_CBPRINTF_IS_WORD_NUM(arg1) + +/** brief Determine if string arguments types allow to use simplified message creation mode. + * + * @param ... String with arguments. + */ +#define LOG_MSG_SIMPLE_ARG_TYPE_CHECK(...) \ + UTIL_CAT(LOG_MSG_SIMPLE_ARG_TYPE_CHECK_, NUM_VA_ARGS_LESS_1(__VA_ARGS__))(__VA_ARGS__) + +/** @brief Check if message can be handled using simplified method. + * + * Following conditions must be met: + * - 32 bit platform + * - Number of arguments from 0 to 2 + * - Type of an argument must be a numeric value that fits in 32 bit word. + * + * @param ... String with arguments. + * + * @retval 1 if message qualifies. + * @retval 0 if message does not qualify. + */ +#define LOG_MSG_SIMPLE_CHECK(...) \ + COND_CODE_1(CONFIG_64BIT, (0), (\ + COND_CODE_1(LOG_MSG_SIMPLE_ARG_CNT_CHECK(__VA_ARGS__), ( \ + LOG_MSG_SIMPLE_ARG_TYPE_CHECK(__VA_ARGS__)), (0)))) + +/* Helper macro for handing log with one argument. Macro casts the first argument to uint32_t. */ +#define Z_LOG_MSG_SIMPLE_CREATE_1(_source, _level, ...) \ + z_log_msg_simple_create_1(_source, _level, GET_ARG_N(1, __VA_ARGS__), \ + (uint32_t)(uintptr_t)GET_ARG_N(2, __VA_ARGS__)) + +/* Helper macro for handing log with two arguments. Macro casts arguments to uint32_t. + */ +#define Z_LOG_MSG_SIMPLE_CREATE_2(_source, _level, ...) \ + z_log_msg_simple_create_2(_source, _level, GET_ARG_N(1, __VA_ARGS__), \ + (uint32_t)(uintptr_t)GET_ARG_N(2, __VA_ARGS__), \ + (uint32_t)(uintptr_t)GET_ARG_N(3, __VA_ARGS__)) + +/* Call specific function based on the number of arguments. + * Since up 2 to arguments are supported COND_CODE_0 and COND_CODE_1 can be used to + * handle all cases (0, 1 and 2 arguments). When tracing is enable then for each + * function a macro is create. The difference between function and macro is that + * macro is applied to any input arguments so we need to make sure that it is + * always called with proper number of arguments. For that it is wrapped around + * into another macro and dummy arguments to cover for cases when there is less + * arguments in a log call. + */ +#define Z_LOG_MSG_SIMPLE_FUNC2(arg_cnt, _source, _level, ...) \ + COND_CODE_0(arg_cnt, \ + (z_log_msg_simple_create_0(_source, _level, GET_ARG_N(1, __VA_ARGS__))), \ + (COND_CODE_1(arg_cnt, ( \ + Z_LOG_MSG_SIMPLE_CREATE_1(_source, _level, __VA_ARGS__, dummy) \ + ), ( \ + Z_LOG_MSG_SIMPLE_CREATE_2(_source, _level, __VA_ARGS__, dummy, dummy) \ + ) \ + ))) + +/** @brief Call specific function to create a log message. + * + * Macro picks matching function (based on number of arguments) and calls it. + * String arguments are casted to uint32_t. + * + * @param _source Source. + * @param _level Severity level. + * @param ... String with arguments. + */ +#define LOG_MSG_SIMPLE_FUNC(_source, _level, ...) \ + Z_LOG_MSG_SIMPLE_FUNC2(NUM_VA_ARGS_LESS_1(__VA_ARGS__), _source, _level, __VA_ARGS__) + +/** @brief Create log message using simplified method. + * + * Macro is gated by the argument count check to run @ref LOG_MSG_SIMPLE_FUNC only + * on entries with 2 or less arguments. + * + * @param _domain_id Domain ID. + * @param _source Pointer to the source structure. + * @param _level Severity level. + * @param ... String with arguments. + */ +#define Z_LOG_MSG_SIMPLE_ARGS_CREATE(_domain_id, _source, _level, ...) \ + IF_ENABLED(LOG_MSG_SIMPLE_ARG_CNT_CHECK(__VA_ARGS__), (\ + LOG_MSG_SIMPLE_FUNC(_source, _level, __VA_ARGS__); \ + )) + #define Z_LOG_MSG_STACK_CREATE(_cstr_cnt, _domain_id, _source, _level, _data, _dlen, ...) \ do { \ int _plen; \ @@ -430,6 +528,19 @@ do { \ _level, Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \ _mode = Z_LOG_MSG_MODE_ZERO_COPY; \ } else { \ + IF_ENABLED(UTIL_AND(IS_ENABLED(CONFIG_LOG_SIMPLE_MSG_OPTIMIZE), \ + UTIL_AND(UTIL_NOT(_domain_id), UTIL_NOT(_cstr_cnt))), \ + ( \ + bool can_simple = LOG_MSG_SIMPLE_CHECK(__VA_ARGS__); \ + if (can_simple && ((_dlen) == 0) && !k_is_user_context()) { \ + LOG_MSG_DBG("create fast message\n");\ + Z_LOG_MSG_SIMPLE_ARGS_CREATE(_domain_id, _source, _level, \ + Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \ + _mode = Z_LOG_MSG_MODE_SIMPLE; \ + break; \ + } \ + ) \ + ) \ LOG_MSG_DBG("create on stack message\n");\ Z_LOG_MSG_STACK_CREATE(_cstr_cnt, _domain_id, _source, _level, _data, \ _dlen, Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \ @@ -503,7 +614,37 @@ struct log_msg *z_log_msg_alloc(uint32_t wlen); void z_log_msg_finalize(struct log_msg *msg, const void *source, const struct log_msg_desc desc, const void *data); -/** @brief Create simple message from message details and string package. +/** @brief Create log message using simplified method for string with no arguments. + * + * @param source Pointer to the source structure. + * @param level Severity level. + * @param fmt String pointer. + */ +__syscall void z_log_msg_simple_create_0(const void *source, uint32_t level, + const char *fmt); + +/** @brief Create log message using simplified method for string with a one argument. + * + * @param source Pointer to the source structure. + * @param level Severity level. + * @param fmt String pointer. + * @param arg String argument. + */ +__syscall void z_log_msg_simple_create_1(const void *source, uint32_t level, + const char *fmt, uint32_t arg); + +/** @brief Create log message using simplified method for string with two arguments. + * + * @param source Pointer to the source structure. + * @param level Severity level. + * @param fmt String pointer. + * @param arg0 String argument. + * @param arg1 String argument. + */ +__syscall void z_log_msg_simple_create_2(const void *source, uint32_t level, + const char *fmt, uint32_t arg0, uint32_t arg1); + +/** @brief Create a logging message from message details and string package. * * @param source Source. * @@ -538,11 +679,11 @@ __syscall void z_log_msg_static_create(const void *source, * * @param ap Variable list of string arguments. */ -__syscall void z_log_msg_runtime_vcreate(uint8_t domain_id, const void *source, - uint8_t level, const void *data, - size_t dlen, uint32_t package_flags, - const char *fmt, - va_list ap); +void z_log_msg_runtime_vcreate(uint8_t domain_id, const void *source, + uint8_t level, const void *data, + size_t dlen, uint32_t package_flags, + const char *fmt, + va_list ap); /** @brief Create message at runtime. * @@ -666,7 +807,7 @@ static inline log_timestamp_t log_msg_get_timestamp(struct log_msg *msg) */ static inline void *log_msg_get_tid(struct log_msg *msg) { -#if CONFIG_LOG_THREAD_ID_PREFIX +#if defined(CONFIG_LOG_THREAD_ID_PREFIX) return msg->hdr.tid; #else ARG_UNUSED(msg); diff --git a/include/zephyr/logging/log_output.h b/include/zephyr/logging/log_output.h index e55170605c9..dff4ff81dcd 100644 --- a/include/zephyr/logging/log_output.h +++ b/include/zephyr/logging/log_output.h @@ -159,7 +159,7 @@ void log_output_process(const struct log_output *log_output, log_timestamp_t timestamp, const char *domain, const char *source, - const k_tid_t tid, + k_tid_t tid, uint8_t level, const uint8_t *package, const uint8_t *data, diff --git a/include/zephyr/lorawan/lorawan.h b/include/zephyr/lorawan/lorawan.h index 924ed6ec276..2e07e99d694 100644 --- a/include/zephyr/lorawan/lorawan.h +++ b/include/zephyr/lorawan/lorawan.h @@ -107,7 +107,7 @@ struct lorawan_join_otaa { * increasing for each OTAA join with the same EUI. The DevNonce * should be stored in non-volatile memory by the application. */ - uint32_t dev_nonce; + uint16_t dev_nonce; }; /** @@ -175,22 +175,32 @@ struct lorawan_downlink_cb { }; /** - * @brief Add battery level callback function. + * @brief Defines the battery level callback handler function signature. + * + * @retval 0 if the node is connected to an external power source + * @retval 1..254 battery level, where 1 is the minimum and 254 is the maximum value + * @retval 255 if the node was not able to measure the battery level + */ +typedef uint8_t (*lorawan_battery_level_cb_t)(void); + +/** + * @brief Defines the datarate changed callback handler function signature. + * + * @param dr Updated datarate. + */ +typedef void (*lorawan_dr_changed_cb_t)(enum lorawan_datarate dr); + +/** + * @brief Register a battery level callback function. * * Provide the LoRaWAN stack with a function to be called whenever a battery - * level needs to be read. As per LoRaWAN specification the callback needs to - * return "0: node is connected to an external power source, - * 1..254: battery level, where 1 is the minimum and 254 is the maximum - * value, - * 255: the node was not able to measure the battery level" + * level needs to be read. * * Should no callback be provided the lorawan backend will report 255. * - * @param battery_lvl_cb Pointer to the battery level function - * - * @return 0 if successful, negative errno code if failure + * @param cb Pointer to the battery level function */ -int lorawan_set_battery_level_callback(uint8_t (*battery_lvl_cb)(void)); +void lorawan_register_battery_level_callback(lorawan_battery_level_cb_t cb); /** * @brief Register a callback to be run on downlink packets @@ -205,12 +215,9 @@ void lorawan_register_downlink_callback(struct lorawan_downlink_cb *cb); * The callback is called once upon successfully joining a network and again * each time the datarate changes due to ADR. * - * The callback function takes one parameter: - * - dr - updated datarate - * - * @param dr_cb Pointer to datarate update callback + * @param cb Pointer to datarate update callback */ -void lorawan_register_dr_changed_callback(void (*dr_cb)(enum lorawan_datarate)); +void lorawan_register_dr_changed_callback(lorawan_dr_changed_cb_t cb); /** * @brief Join the LoRaWAN network diff --git a/include/zephyr/mem_mgmt/mem_attr.h b/include/zephyr/mem_mgmt/mem_attr.h new file mode 100644 index 00000000000..a8da629c3e3 --- /dev/null +++ b/include/zephyr/mem_mgmt/mem_attr.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2023 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_MEM_ATTR_H_ +#define ZEPHYR_INCLUDE_MEM_ATTR_H_ + +/** + * @brief Memory-Attr Interface + * @defgroup memory_attr_interface Memory-Attr Interface + * @ingroup mem_mgmt + * @{ + */ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond INTERNAL_HIDDEN */ + +#define __MEM_ATTR zephyr_memory_attr + +#define _FILTER(node_id, fn) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, __MEM_ATTR), \ + (fn(node_id)), \ + ()) + +/** @endcond */ + +/** + * @brief Invokes @p fn for every status `okay` node in the tree with property + * `zephyr,memory-attr` + * + * The macro @p fn must take one parameter, which will be a node identifier + * with the `zephyr,memory-attr` property. The macro is expanded once for each + * node in the tree with status `okay`. The order that nodes are visited in is + * not specified. + * + * @param fn macro to invoke + */ +#define DT_MEMORY_ATTR_FOREACH_STATUS_OKAY_NODE(fn) \ + DT_FOREACH_STATUS_OKAY_NODE_VARGS(_FILTER, fn) + +/** + * @brief memory-attr region structure. + * + * This structure represents the data gathered from DT about a memory-region + * marked with memory attributes. + */ +struct mem_attr_region_t { + /** Memory node full name */ + const char *dt_name; + /** Memory region physical address */ + uintptr_t dt_addr; + /** Memory region size */ + size_t dt_size; + /** Memory region attributes */ + uint32_t dt_attr; +}; + +/** + * @brief Get the list of memory regions. + * + * Get the list of enabled memory regions with their memory-attribute as + * gathered by DT. + * + * @param region Pointer to pointer to the list of memory regions. + * + * @retval Number of memory regions returned in the parameter. + */ +size_t mem_attr_get_regions(const struct mem_attr_region_t **region); + +/** + * @brief Check if a buffer has correct size and attributes. + * + * This function is used to check if a given buffer with a given set of + * attributes fully match a memory region in terms of size and attributes. + * + * This is usually used to verify that a buffer has the expected attributes + * (for example the buffer is cacheable / non-cacheable or belongs to RAM / + * FLASH, etc...) and it has been correctly allocated. + * + * The expected set of attributes for the buffer is and-matched against the + * full set of attributes for the memory region it belongs to (bitmask). So the + * buffer is considered matching when at least that set of attributes are valid + * for the memory region (but the region can be marked also with other + * attributes besides the one passed as parameter). + * + * @param addr Virtual address of the user buffer. + * @param size Size of the user buffer. + * @param attr Expected / desired attribute for the buffer. + * + * @retval 0 if the buffer has the correct size and attribute. + * @retval -ENOSYS if the operation is not supported (for example if the MMU is enabled). + * @retval -ENOTSUP if the wrong parameters were passed. + * @retval -EINVAL if the buffer has the wrong set of attributes. + * @retval -ENOSPC if the buffer is too big for the region it belongs to. + * @retval -ENOBUFS if the buffer is entirely allocated outside a memory region. + */ +int mem_attr_check_buf(void *addr, size_t size, uint32_t attr); + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_MEM_ATTR_H_ */ diff --git a/include/zephyr/mgmt/ec_host_cmd/backend.h b/include/zephyr/mgmt/ec_host_cmd/backend.h index fe0581b092e..ed61e0e33c2 100644 --- a/include/zephyr/mgmt/ec_host_cmd/backend.h +++ b/include/zephyr/mgmt/ec_host_cmd/backend.h @@ -43,11 +43,14 @@ struct ec_host_cmd_rx_ctx { /** * Buffer to hold received data. The buffer is provided by the handler if * CONFIG_EC_HOST_CMD_HANDLER_RX_BUFFER_SIZE > 0. Otherwise, the backend should provide - * the buffer on its own and overwrites @a buf pointer in the init function. + * the buffer on its own and overwrites @a buf pointer and @a len_max + * in the init function. */ uint8_t *buf; /** Number of bytes written to @a buf by backend. */ size_t len; + /** Maximum number of bytes to receive with one request packet. */ + size_t len_max; }; /** @@ -63,7 +66,7 @@ struct ec_host_cmd_tx_buf { void *buf; /** Number of bytes to write from @a buf. */ size_t len; - /** Size of @a buf. */ + /** Maximum number of bytes to send with one response packet. */ size_t len_max; }; diff --git a/include/zephyr/mgmt/ec_host_cmd/ec_host_cmd.h b/include/zephyr/mgmt/ec_host_cmd/ec_host_cmd.h index 5b03ae7c5f3..018aa60e980 100644 --- a/include/zephyr/mgmt/ec_host_cmd/ec_host_cmd.h +++ b/include/zephyr/mgmt/ec_host_cmd/ec_host_cmd.h @@ -170,8 +170,8 @@ struct ec_host_cmd_handler { */ #define EC_HOST_CMD_HANDLER(_id, _function, _version_mask, _request_type, _response_type) \ const STRUCT_SECTION_ITERABLE(ec_host_cmd_handler, __cmd##_id) = { \ - .id = _id, \ .handler = _function, \ + .id = _id, \ .version_mask = _version_mask, \ .min_rqt_size = sizeof(_request_type), \ .min_rsp_size = sizeof(_response_type), \ @@ -190,8 +190,8 @@ struct ec_host_cmd_handler { */ #define EC_HOST_CMD_HANDLER_UNBOUND(_id, _function, _version_mask) \ const STRUCT_SECTION_ITERABLE(ec_host_cmd_handler, __cmd##_id) = { \ - .id = _id, \ .handler = _function, \ + .id = _id, \ .version_mask = _version_mask, \ .min_rqt_size = 0, \ .min_rsp_size = 0, \ diff --git a/include/zephyr/mgmt/mcumgr/grp/fs_mgmt/fs_mgmt.h b/include/zephyr/mgmt/mcumgr/grp/fs_mgmt/fs_mgmt.h index 5f07c2ed2d8..9db23ac0b0e 100644 --- a/include/zephyr/mgmt/mcumgr/grp/fs_mgmt/fs_mgmt.h +++ b/include/zephyr/mgmt/mcumgr/grp/fs_mgmt/fs_mgmt.h @@ -73,6 +73,15 @@ enum fs_mgmt_err_code_t { /** The requested checksum or hash type was not found or is not supported by this build. */ FS_MGMT_ERR_CHECKSUM_HASH_NOT_FOUND, + + /** The specified mount point was not found or is not mounted. */ + FS_MGMT_ERR_MOUNT_POINT_NOT_FOUND, + + /** The specified mount point is that of a read-only filesystem. */ + FS_MGMT_ERR_READ_ONLY_FILESYSTEM, + + /** The operation cannot be performed because the file is empty with no contents. */ + FS_MGMT_ERR_FILE_EMPTY, }; #ifdef __cplusplus diff --git a/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt_client.h b/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt_client.h index 8cede40d64e..61e12afb164 100644 --- a/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt_client.h +++ b/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt_client.h @@ -11,6 +11,13 @@ #include #include +/** + * @brief MCUmgr Image management client API + * @defgroup mcumgr_img_mgmt_client MCUmgr img_mgmt_client API + * @ingroup mcumgr + * @{ + */ + #ifdef __cplusplus extern "C" { #endif @@ -186,6 +193,10 @@ int img_mgmt_client_state_read(struct img_mgmt_client *client, struct mcumgr_ima int img_mgmt_client_erase(struct img_mgmt_client *client, uint32_t slot); +/** + * @} + */ + #ifdef __cplusplus } #endif diff --git a/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt.h b/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt.h index e1ac45e6389..505ee655474 100644 --- a/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt.h +++ b/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt.h @@ -41,6 +41,12 @@ enum os_mgmt_err_code_t { /** Query was not recognized. */ OS_MGMT_ERR_QUERY_YIELDS_NO_ANSWER, + + /** RTC is not set */ + OS_MGMT_ERR_RTC_NOT_SET, + + /** RTC command failed */ + OS_MGMT_ERR_RTC_COMMAND_FAILED, }; /* Bitmask values used by the os info command handler. Note that the width of this variable is diff --git a/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt_client.h b/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt_client.h index 12e8abde246..0b12ccdb684 100644 --- a/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt_client.h +++ b/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt_client.h @@ -10,6 +10,13 @@ #include #include +/** + * @brief MCUmgr OS management client API + * @defgroup mcumgr_os_mgmt_client MCUmgr os_mgmt_client API + * @ingroup mcumgr + * @{ + */ + #ifdef __cplusplus extern "C" { #endif @@ -54,6 +61,10 @@ int os_mgmt_client_echo(struct os_mgmt_client *client, const char *echo_string); */ int os_mgmt_client_reset(struct os_mgmt_client *client); +/** + * @} + */ + #ifdef __cplusplus } #endif diff --git a/include/zephyr/mgmt/mcumgr/grp/settings_mgmt/settings_mgmt.h b/include/zephyr/mgmt/mcumgr/grp/settings_mgmt/settings_mgmt.h index 2a1a3f77747..9aab1cdcc4a 100644 --- a/include/zephyr/mgmt/mcumgr/grp/settings_mgmt/settings_mgmt.h +++ b/include/zephyr/mgmt/mcumgr/grp/settings_mgmt/settings_mgmt.h @@ -37,6 +37,15 @@ enum settings_mgmt_ret_code_t { /** The provided key name does not support being read. */ SETTINGS_MGMT_ERR_READ_NOT_SUPPORTED, + + /** The provided root key name does not exist. */ + SETTINGS_MGMT_ERR_ROOT_KEY_NOT_FOUND, + + /** The provided key name does not support being written. */ + SETTINGS_MGMT_ERR_WRITE_NOT_SUPPORTED, + + /** The provided key name does not support being deleted. */ + SETTINGS_MGMT_ERR_DELETE_NOT_SUPPORTED, }; #ifdef __cplusplus diff --git a/include/zephyr/mgmt/mcumgr/mgmt/callbacks.h b/include/zephyr/mgmt/mcumgr/mgmt/callbacks.h index c3a9a5687d8..43ee5ed6f95 100644 --- a/include/zephyr/mgmt/mcumgr/mgmt/callbacks.h +++ b/include/zephyr/mgmt/mcumgr/mgmt/callbacks.h @@ -197,6 +197,12 @@ enum os_mgmt_group_events { /** Callback when an info command needs to output data, data is os_mgmt_info_append. */ MGMT_EVT_OP_OS_MGMT_INFO_APPEND = MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_OS, 2), + /** Callback when a datetime get command has been received. */ + MGMT_EVT_OP_OS_MGMT_DATETIME_GET = MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_OS, 3), + + /** Callback when a datetime set command has been received, data is struct rtc_time(). */ + MGMT_EVT_OP_OS_MGMT_DATETIME_SET = MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_OS, 4), + /** Used to enable all os_mgmt_group events. */ MGMT_EVT_OP_OS_MGMT_ALL = MGMT_DEF_EVT_OP_ALL(MGMT_EVT_GRP_OS), }; diff --git a/include/zephyr/mgmt/mcumgr/mgmt/mgmt.h b/include/zephyr/mgmt/mcumgr/mgmt/mgmt.h index e681ea2b939..ed84b037633 100644 --- a/include/zephyr/mgmt/mcumgr/mgmt/mgmt.h +++ b/include/zephyr/mgmt/mcumgr/mgmt/mgmt.h @@ -71,6 +71,9 @@ typedef int (*mgmt_handler_fn)(struct smp_streamer *ctxt); struct mgmt_handler { mgmt_handler_fn mh_read; mgmt_handler_fn mh_write; +#if IS_ENABLED(CONFIG_MCUMGR_MGMT_HANDLER_USER_DATA) + void *user_data; +#endif }; /** @@ -120,6 +123,16 @@ void mgmt_unregister_group(struct mgmt_group *group); */ const struct mgmt_handler *mgmt_find_handler(uint16_t group_id, uint16_t command_id); +/** + * @brief Finds a registered command group. + * + * @param group_id The command group id to find. + * + * @return The requested command group on success; + * NULL on failure. + */ +const struct mgmt_group *mgmt_find_group(uint16_t group_id); + #if IS_ENABLED(CONFIG_MCUMGR_SMP_SUPPORT_ORIGINAL_PROTOCOL) /** * @brief Finds a registered error translation function for converting from SMP diff --git a/include/zephyr/mgmt/mcumgr/smp/smp_client.h b/include/zephyr/mgmt/mcumgr/smp/smp_client.h index 88b2af701b0..2e0eee2cfe6 100644 --- a/include/zephyr/mgmt/mcumgr/smp/smp_client.h +++ b/include/zephyr/mgmt/mcumgr/smp/smp_client.h @@ -13,6 +13,13 @@ #include #include +/** + * @brief MCUmgr SMP client API + * @defgroup mcumgr_smp_client SMP client API + * @ingroup mcumgr + * @{ + */ + /** * @brief SMP client object */ @@ -102,6 +109,10 @@ void smp_client_buf_free(struct net_buf *nb); int smp_client_send_cmd(struct smp_client_object *smp_client, struct net_buf *nb, smp_client_res_fn cb, void *user_data, int timeout_in_sec); +/** + * @} + */ + #ifdef __cplusplus } #endif diff --git a/include/zephyr/modbus/modbus.h b/include/zephyr/modbus/modbus.h index 45fc6fd0f21..1fba0ac669d 100644 --- a/include/zephyr/modbus/modbus.h +++ b/include/zephyr/modbus/modbus.h @@ -31,7 +31,7 @@ #define ZEPHYR_INCLUDE_MODBUS_H_ #include - +#include #ifdef __cplusplus extern "C" { #endif @@ -41,6 +41,22 @@ extern "C" { /** Length of MBAP Header plus function code */ #define MODBUS_MBAP_AND_FC_LENGTH (MODBUS_MBAP_LENGTH + 1) +/** @name Modbus exception codes + * @{ + */ +/* Modbus exception codes */ +#define MODBUS_EXC_NONE 0 +#define MODBUS_EXC_ILLEGAL_FC 1 +#define MODBUS_EXC_ILLEGAL_DATA_ADDR 2 +#define MODBUS_EXC_ILLEGAL_DATA_VAL 3 +#define MODBUS_EXC_SERVER_DEVICE_FAILURE 4 +#define MODBUS_EXC_ACK 5 +#define MODBUS_EXC_SERVER_DEVICE_BUSY 6 +#define MODBUS_EXC_MEM_PARITY_ERROR 8 +#define MODBUS_EXC_GW_PATH_UNAVAILABLE 10 +#define MODBUS_EXC_GW_TARGET_FAILED_TO_RESP 11 +/** @} */ + /** * @brief Frame struct used internally and for raw ADU support. */ @@ -384,6 +400,57 @@ int modbus_iface_get_by_name(const char *iface_name); typedef int (*modbus_raw_cb_t)(const int iface, const struct modbus_adu *adu, void *user_data); +/** + * @brief Custom function code handler function signature. + * + * Modbus allows user defined function codes which can be used to extend + * the base protocol. These callbacks can also be used to implement + * function codes currently not supported by Zephyr's Modbus subsystem. + * + * If an error occurs during the handling of the request, the handler should + * signal this by setting excep_code to a modbus exception code. + * + * User data pointer can be used to pass state between subsequent calls to + * the handler. + * + * @param iface Modbus interface index + * @param rx_adu Pointer to the received ADU struct + * @param tx_adu Pointer to the outgoing ADU struct + * @param excep_code Pointer to possible exception code + * @param user_data Pointer to user data + * + * @retval true If response should be sent, false otherwise + */ +typedef bool (*modbus_custom_cb_t)(const int iface, + const struct modbus_adu *const rx_adu, + struct modbus_adu *const tx_adu, + uint8_t *const excep_code, + void *const user_data); + +/** @cond INTERNAL_HIDDEN */ +/** + * @brief Custom function code definition. + */ +struct modbus_custom_fc { + sys_snode_t node; + modbus_custom_cb_t cb; + void *user_data; + uint8_t fc; + uint8_t excep_code; +}; +/** @endcond INTERNAL_HIDDEN */ + +/** + * @brief Helper macro for initializing custom function code structs + */ +#define MODBUS_CUSTOM_FC_DEFINE(name, user_cb, user_fc, userdata) \ + static struct modbus_custom_fc modbus_cfg_##name = { \ + .cb = user_cb, \ + .user_data = userdata, \ + .fc = user_fc, \ + .excep_code = MODBUS_EXC_NONE, \ + } + /** * @brief Modbus interface mode */ @@ -535,6 +602,24 @@ void modbus_raw_set_server_failure(struct modbus_adu *adu); */ int modbus_raw_backend_txn(const int iface, struct modbus_adu *adu); +/** + * @brief Register a user-defined function code handler. + * + * The Modbus specification allows users to define standard function codes + * missing from Zephyr's Modbus implementation as well as add non-standard + * function codes in the ranges 65 to 72 and 100 to 110 (decimal), as per + * specification. + * + * This function registers a new handler at runtime for the given + * function code. + * + * @param iface Modbus client interface index + * @param custom_fc User defined function code and callback pair + * + * @retval 0 on success + */ +int modbus_register_user_fc(const int iface, struct modbus_custom_fc *custom_fc); + #ifdef __cplusplus } #endif diff --git a/include/zephyr/modem/backend/uart.h b/include/zephyr/modem/backend/uart.h index 600d5435a1e..0ddef4df734 100644 --- a/include/zephyr/modem/backend/uart.h +++ b/include/zephyr/modem/backend/uart.h @@ -31,9 +31,11 @@ struct modem_backend_uart_isr { struct modem_backend_uart_async { uint8_t *receive_bufs[2]; uint32_t receive_buf_size; - struct ring_buf receive_rdb[2]; + struct ring_buf receive_rb; + struct k_spinlock receive_rb_lock; uint8_t *transmit_buf; uint32_t transmit_buf_size; + struct k_work rx_disabled_work; atomic_t state; }; diff --git a/include/zephyr/modem/chat.h b/include/zephyr/modem/chat.h index 5f2ff4a9165..d46ffc7c24a 100644 --- a/include/zephyr/modem/chat.h +++ b/include/zephyr/modem/chat.h @@ -35,19 +35,20 @@ typedef void (*modem_chat_match_callback)(struct modem_chat *chat, char **argv, * @brief Modem chat match */ struct modem_chat_match { - /* Match array */ + /** Match array */ const uint8_t *match; - const uint8_t match_size; - - /* Separators array */ + /** Size of match */ + uint8_t match_size; + /** Separators array */ const uint8_t *separators; - const uint8_t separators_size; - - /* Set if modem chat instance shall use wildcards when matching */ - const bool wildcards; - - /* Type of modem chat instance */ - const modem_chat_match_callback callback; + /** Size of separators array */ + uint8_t separators_size; + /** Set if modem chat instance shall use wildcards when matching */ + uint8_t wildcards : 1; + /** Set if script shall not continue to next step in case of match */ + uint8_t partial : 1; + /** Type of modem chat instance */ + modem_chat_match_callback callback; }; #define MODEM_CHAT_MATCH(_match, _separators, _callback) \ @@ -66,6 +67,17 @@ struct modem_chat_match { .callback = _callback, \ } +#define MODEM_CHAT_MATCH_INITIALIZER(_match, _separators, _callback, _wildcards, _partial) \ + { \ + .match = (uint8_t *)(_match), \ + .match_size = (uint8_t)(sizeof(_match) - 1), \ + .separators = (uint8_t *)(_separators), \ + .separators_size = (uint8_t)(sizeof(_separators) - 1), \ + .wildcards = _wildcards, \ + .partial = _partial, \ + .callback = _callback, \ + } + #define MODEM_CHAT_MATCH_DEFINE(_sym, _match, _separators, _callback) \ const static struct modem_chat_match _sym = MODEM_CHAT_MATCH(_match, _separators, _callback) @@ -76,36 +88,47 @@ struct modem_chat_match { * @brief Modem chat script chat */ struct modem_chat_script_chat { - /** Request to send to modem formatted as char string */ - const char *request; + /** Request to send to modem */ + const uint8_t *request; + /** Size of request */ + uint16_t request_size; /** Expected responses to request */ - const struct modem_chat_match *const response_matches; + const struct modem_chat_match *response_matches; /** Number of elements in expected responses */ - const uint16_t response_matches_size; + uint16_t response_matches_size; /** Timeout before chat script may continue to next step in milliseconds */ uint16_t timeout; }; #define MODEM_CHAT_SCRIPT_CMD_RESP(_request, _response_match) \ { \ - .request = _request, .response_matches = &_response_match, \ - .response_matches_size = 1, .timeout = 0, \ + .request = (uint8_t *)(_request), \ + .request_size = (uint16_t)(sizeof(_request) - 1), \ + .response_matches = &_response_match, \ + .response_matches_size = 1, \ + .timeout = 0, \ } #define MODEM_CHAT_SCRIPT_CMD_RESP_MULT(_request, _response_matches) \ { \ - .request = _request, .response_matches = _response_matches, \ - .response_matches_size = ARRAY_SIZE(_response_matches), .timeout = 0, \ + .request = (uint8_t *)(_request), \ + .request_size = (uint16_t)(sizeof(_request) - 1), \ + .response_matches = _response_matches, \ + .response_matches_size = ARRAY_SIZE(_response_matches), \ + .timeout = 0, \ } #define MODEM_CHAT_SCRIPT_CMD_RESP_NONE(_request, _timeout) \ { \ - .request = _request, .response_matches = NULL, .response_matches_size = 0, \ + .request = (uint8_t *)(_request), \ + .request_size = (uint16_t)(sizeof(_request) - 1), \ + .response_matches = NULL, \ + .response_matches_size = 0, \ .timeout = _timeout, \ } #define MODEM_CHAT_SCRIPT_CMDS_DEFINE(_sym, ...) \ - const static struct modem_chat_script_chat _sym[] = {__VA_ARGS__} + const struct modem_chat_script_chat _sym[] = {__VA_ARGS__} enum modem_chat_script_result { MODEM_CHAT_SCRIPT_RESULT_SUCCESS, @@ -132,19 +155,19 @@ struct modem_chat_script { /** Array of script chats */ const struct modem_chat_script_chat *script_chats; /** Elements in array of script chats */ - const uint16_t script_chats_size; + uint16_t script_chats_size; /** Array of abort matches */ - const struct modem_chat_match *const abort_matches; + const struct modem_chat_match *abort_matches; /** Number of elements in array of abort matches */ - const uint16_t abort_matches_size; + uint16_t abort_matches_size; /** Callback called when script execution terminates */ modem_chat_script_callback callback; /** Timeout in seconds within which the script execution must terminate */ - const uint32_t timeout; + uint32_t timeout; }; #define MODEM_CHAT_SCRIPT_DEFINE(_sym, _script_chats, _abort_matches, _callback, _timeout) \ - static struct modem_chat_script _sym = { \ + const static struct modem_chat_script _sym = { \ .name = #_sym, \ .script_chats = _script_chats, \ .script_chats_size = ARRAY_SIZE(_script_chats), \ @@ -213,6 +236,8 @@ struct modem_chat { struct k_work script_abort_work; uint16_t script_chat_it; atomic_t script_state; + enum modem_chat_script_result script_result; + struct k_sem script_stopped_sem; /* Script sending */ uint16_t script_send_request_pos; @@ -279,6 +304,18 @@ int modem_chat_init(struct modem_chat *chat, const struct modem_chat_config *con */ int modem_chat_attach(struct modem_chat *chat, struct modem_pipe *pipe); +/** + * @brief Run script asynchronously + * @param chat Chat instance + * @param script Script to run + * @returns 0 if script successfully started + * @returns -EBUSY if a script is currently running + * @returns -EPERM if modem pipe is not attached + * @returns -EINVAL if arguments or script is invalid + * @note Script runs asynchronously until complete or aborted. + */ +int modem_chat_run_script_async(struct modem_chat *chat, const struct modem_chat_script *script); + /** * @brief Run script * @param chat Chat instance @@ -287,9 +324,25 @@ int modem_chat_attach(struct modem_chat *chat, struct modem_pipe *pipe); * @returns -EBUSY if a script is currently running * @returns -EPERM if modem pipe is not attached * @returns -EINVAL if arguments or script is invalid - * @note Script runs asynchronously until complete or aborted. + * @note Script runs until complete or aborted. */ -int modem_chat_script_run(struct modem_chat *chat, const struct modem_chat_script *script); +int modem_chat_run_script(struct modem_chat *chat, const struct modem_chat_script *script); + +/** + * @brief Run script asynchronously + * @note Function exists for backwards compatibility and should be deprecated + * @param chat Chat instance + * @param script Script to run + * @returns 0 if script successfully started + * @returns -EBUSY if a script is currently running + * @returns -EPERM if modem pipe is not attached + * @returns -EINVAL if arguments or script is invalid + */ +static inline int modem_chat_script_run(struct modem_chat *chat, + const struct modem_chat_script *script) +{ + return modem_chat_run_script_async(chat, script); +} /** * @brief Abort script diff --git a/include/zephyr/modem/cmux.h b/include/zephyr/modem/cmux.h index b64c00b9927..4562cb544d9 100644 --- a/include/zephyr/modem/cmux.h +++ b/include/zephyr/modem/cmux.h @@ -33,14 +33,14 @@ extern "C" { #endif -struct modem_cmux; +/** + * @brief Modem CMUX + * @defgroup modem_cmux Modem CMUX + * @ingroup modem + * @{ + */ -enum modem_cmux_state { - MODEM_CMUX_STATE_DISCONNECTED = 0, - MODEM_CMUX_STATE_CONNECTING, - MODEM_CMUX_STATE_CONNECTED, - MODEM_CMUX_STATE_DISCONNECTING, -}; +struct modem_cmux; enum modem_cmux_event { MODEM_CMUX_EVENT_CONNECTED = 0, @@ -50,6 +50,17 @@ enum modem_cmux_event { typedef void (*modem_cmux_callback)(struct modem_cmux *cmux, enum modem_cmux_event event, void *user_data); +/** + * @cond INTERNAL_HIDDEN + */ + +enum modem_cmux_state { + MODEM_CMUX_STATE_DISCONNECTED = 0, + MODEM_CMUX_STATE_CONNECTING, + MODEM_CMUX_STATE_CONNECTED, + MODEM_CMUX_STATE_DISCONNECTING, +}; + enum modem_cmux_receive_state { MODEM_CMUX_RECEIVE_STATE_SOF = 0, MODEM_CMUX_RECEIVE_STATE_RESYNC_0, @@ -74,11 +85,6 @@ enum modem_cmux_dlci_state { MODEM_CMUX_DLCI_STATE_CLOSING, }; -enum modem_cmux_dlci_event { - MODEM_CMUX_DLCI_EVENT_OPENED, - MODEM_CMUX_DLCI_EVENT_CLOSED, -}; - struct modem_cmux_dlci { sys_snode_t node; @@ -157,6 +163,10 @@ struct modem_cmux { struct k_event event; }; +/** + * @endcond + */ + /** * @brief Contains CMUX instance configuration data */ @@ -205,7 +215,7 @@ struct modem_pipe *modem_cmux_dlci_init(struct modem_cmux *cmux, struct modem_cm const struct modem_cmux_dlci_config *config); /** - * @brief Initialize CMUX instance + * @brief Attach CMUX instance to pipe * * @param cmux CMUX instance * @param pipe Pipe instance to attach CMUX instance to @@ -243,7 +253,8 @@ int modem_cmux_connect_async(struct modem_cmux *cmux); * * @param cmux CMUX instance * - * @note When disconnected, the bus pipe can be used directly again + * @note The bus pipe must be released using modem_cmux_release() after disconnecting + * before being reused. */ int modem_cmux_disconnect(struct modem_cmux *cmux); @@ -254,12 +265,27 @@ int modem_cmux_disconnect(struct modem_cmux *cmux); * * @param cmux CMUX instance * - * @note When disconnected, the bus pipe can be used directly again + * @note The bus pipe must be released using modem_cmux_release() after disconnecting + * before being reused. */ int modem_cmux_disconnect_async(struct modem_cmux *cmux); +/** + * @brief Release CMUX instance from pipe + * + * @details Releases the pipe and hard resets the CMUX instance internally. CMUX should + * be disconnected using modem_cmux_disconnect(). + * + * @param cmux CMUX instance + * + * @note The bus pipe can be used directly again after CMUX instance is released. + */ void modem_cmux_release(struct modem_cmux *cmux); +/** + * @} + */ + #ifdef __cplusplus } #endif diff --git a/include/zephyr/modem/pipe.h b/include/zephyr/modem/pipe.h index 4fdd98155da..abf8d74918e 100644 --- a/include/zephyr/modem/pipe.h +++ b/include/zephyr/modem/pipe.h @@ -14,8 +14,37 @@ extern "C" { #endif +/** + * @brief Modem Pipe + * @defgroup modem_pipe Modem Pipe + * @ingroup modem + * @{ + */ + +/** Modem pipe event */ +enum modem_pipe_event { + MODEM_PIPE_EVENT_OPENED = 0, + MODEM_PIPE_EVENT_RECEIVE_READY, + MODEM_PIPE_EVENT_CLOSED, +}; + +/** + * @cond INTERNAL_HIDDEN + */ + struct modem_pipe; +/** + * @endcond + */ + +typedef void (*modem_pipe_api_callback)(struct modem_pipe *pipe, enum modem_pipe_event event, + void *user_data); + +/** + * @cond INTERNAL_HIDDEN + */ + typedef int (*modem_pipe_api_open)(void *data); typedef int (*modem_pipe_api_transmit)(void *data, const uint8_t *buf, size_t size); @@ -36,15 +65,6 @@ enum modem_pipe_state { MODEM_PIPE_STATE_OPEN, }; -enum modem_pipe_event { - MODEM_PIPE_EVENT_OPENED = 0, - MODEM_PIPE_EVENT_RECEIVE_READY, - MODEM_PIPE_EVENT_CLOSED, -}; - -typedef void (*modem_pipe_api_callback)(struct modem_pipe *pipe, enum modem_pipe_event event, - void *user_data); - struct modem_pipe { void *data; struct modem_pipe_api *api; @@ -53,6 +73,7 @@ struct modem_pipe { enum modem_pipe_state state; struct k_mutex lock; struct k_condvar condvar; + bool receive_ready_pending; }; /** @@ -64,10 +85,17 @@ struct modem_pipe { */ void modem_pipe_init(struct modem_pipe *pipe, void *data, struct modem_pipe_api *api); +/** + * @endcond + */ + /** * @brief Open pipe * * @param pipe Pipe instance + * + * @retval 0 if pipe was successfully opened or was already open + * @retval -errno code otherwise */ int modem_pipe_open(struct modem_pipe *pipe); @@ -75,6 +103,12 @@ int modem_pipe_open(struct modem_pipe *pipe); * @brief Open pipe asynchronously * * @param pipe Pipe instance + * + * @note The MODEM_PIPE_EVENT_OPENED event is invoked immediately if pipe is + * already opened. + * + * @retval 0 if pipe open was called successfully or pipe was already open + * @retval -errno code otherwise */ int modem_pipe_open_async(struct modem_pipe *pipe); @@ -84,6 +118,9 @@ int modem_pipe_open_async(struct modem_pipe *pipe); * @param pipe Pipe instance * @param callback Callback called when pipe event occurs * @param user_data Free to use user data passed with callback + * + * @note The MODEM_PIPE_EVENT_RECEIVE_READY event is invoked immediately if pipe has pending + * data ready to receive. */ void modem_pipe_attach(struct modem_pipe *pipe, modem_pipe_api_callback callback, void *user_data); @@ -126,6 +163,9 @@ void modem_pipe_release(struct modem_pipe *pipe); * @brief Close pipe * * @param pipe Pipe instance + * + * @retval 0 if pipe open was called closed or pipe was already closed + * @retval -errno code otherwise */ int modem_pipe_close(struct modem_pipe *pipe); @@ -133,9 +173,19 @@ int modem_pipe_close(struct modem_pipe *pipe); * @brief Close pipe asynchronously * * @param pipe Pipe instance + * + * @note The MODEM_PIPE_EVENT_CLOSED event is invoked immediately if pipe is + * already closed. + * + * @retval 0 if pipe close was called successfully or pipe was already closed + * @retval -errno code otherwise */ int modem_pipe_close_async(struct modem_pipe *pipe); +/** + * @cond INTERNAL_HIDDEN + */ + /** * @brief Notify user of pipe that it has opened * @@ -163,6 +213,14 @@ void modem_pipe_notify_closed(struct modem_pipe *pipe); */ void modem_pipe_notify_receive_ready(struct modem_pipe *pipe); +/** + * @endcond + */ + +/** + * @} + */ + #ifdef __cplusplus } #endif diff --git a/include/zephyr/modem/ppp.h b/include/zephyr/modem/ppp.h index dc592fb90f9..c0eca885fcd 100644 --- a/include/zephyr/modem/ppp.h +++ b/include/zephyr/modem/ppp.h @@ -20,6 +20,20 @@ extern "C" { #endif +/** + * @brief Modem PPP + * @defgroup modem_ppp Modem PPP + * @ingroup modem + * @{ + */ + +/** L2 network interface init callback */ +typedef void (*modem_ppp_init_iface)(struct net_if *iface); + +/** + * @cond INTERNAL_HIDDEN + */ + enum modem_ppp_receive_state { /* Searching for start of frame and header */ MODEM_PPP_RECEIVE_STATE_HDR_SOF = 0, @@ -57,8 +71,6 @@ enum modem_ppp_transmit_state { MODEM_PPP_TRANSMIT_STATE_EOF, }; -typedef void (*modem_ppp_init_iface)(struct net_if *iface); - struct modem_ppp { /* Network interface instance is bound to */ struct net_if *iface; @@ -97,8 +109,16 @@ struct modem_ppp { /* Work */ struct k_work send_work; struct k_work process_work; + +#if defined(CONFIG_NET_STATISTICS_PPP) + struct net_stats_ppp stats; +#endif }; +/** + * @endcond + */ + /** * @brief Attach pipe to instance and connect * @@ -122,6 +142,10 @@ struct net_if *modem_ppp_get_iface(struct modem_ppp *ppp); */ void modem_ppp_release(struct modem_ppp *ppp); +/** + * @cond INTERNAL_HIDDEN + */ + /** * @brief Initialize modem PPP instance device * @param dev Device instance associated with network interface @@ -129,6 +153,10 @@ void modem_ppp_release(struct modem_ppp *ppp); */ int modem_ppp_init_internal(const struct device *dev); +/** + * @endcond + */ + /** * @brief Define a modem PPP module and bind it to a network interface * @@ -159,6 +187,9 @@ int modem_ppp_init_internal(const struct device *dev); modem_ppp_init_internal, NULL, &_name, NULL, _prio, &modem_ppp_ppp_api, \ PPP_L2, NET_L2_GET_CTX_TYPE(PPP_L2), _mtu) +/** + * @} + */ #ifdef __cplusplus } diff --git a/include/zephyr/multi_heap/shared_multi_heap.h b/include/zephyr/multi_heap/shared_multi_heap.h index 0d5e66bf293..a9cdf120fae 100644 --- a/include/zephyr/multi_heap/shared_multi_heap.h +++ b/include/zephyr/multi_heap/shared_multi_heap.h @@ -88,7 +88,7 @@ enum shared_multi_heap_attr { */ struct shared_multi_heap_region { /** Memory heap attribute */ - unsigned int attr; + uint32_t attr; /** Memory heap starting virtual address */ uintptr_t addr; diff --git a/include/zephyr/net/buf.h b/include/zephyr/net/buf.h index 91d0f601183..f7378fc3962 100644 --- a/include/zephyr/net/buf.h +++ b/include/zephyr/net/buf.h @@ -1358,6 +1358,13 @@ static inline void net_buf_destroy(struct net_buf *buf) { struct net_buf_pool *pool = net_buf_pool_get(buf->pool_id); + if (buf->__buf) { + if (!(buf->flags & NET_BUF_EXTERNAL_DATA)) { + pool->alloc->cb->unref(buf, buf->__buf); + } + buf->__buf = NULL; + } + k_lifo_put(&pool->free, buf); } diff --git a/include/zephyr/net/capture.h b/include/zephyr/net/capture.h index b4d9ce323a1..ac8ccdb905d 100644 --- a/include/zephyr/net/capture.h +++ b/include/zephyr/net/capture.h @@ -166,6 +166,8 @@ static inline int net_capture_disable(const struct device *dev) #endif } +/** @cond INTERNAL_HIDDEN */ + /** * @brief Send captured packet. * @@ -192,8 +194,6 @@ static inline int net_capture_send(const struct device *dev, struct net_if *ifac #endif } -/** @cond INTERNAL_HIDDEN */ - /** * @brief Check if the network packet needs to be captured or not. * This is called for every network packet being sent. diff --git a/include/zephyr/net/coap.h b/include/zephyr/net/coap.h index 6fc21a6280b..a907d1311e1 100644 --- a/include/zephyr/net/coap.h +++ b/include/zephyr/net/coap.h @@ -60,7 +60,9 @@ enum coap_option_num { COAP_OPTION_SIZE2 = 28, /**< Size2 (RFC 7959) */ COAP_OPTION_PROXY_URI = 35, /**< Proxy-Uri */ COAP_OPTION_PROXY_SCHEME = 39, /**< Proxy-Scheme */ - COAP_OPTION_SIZE1 = 60 /**< Size1 */ + COAP_OPTION_SIZE1 = 60, /**< Size1 */ + COAP_OPTION_ECHO = 252, /**< Echo (RFC 9175) */ + COAP_OPTION_REQUEST_TAG = 292 /**< Request-Tag (RFC 9175) */ }; /** @@ -236,6 +238,29 @@ typedef int (*coap_method_t)(struct coap_resource *resource, typedef void (*coap_notify_t)(struct coap_resource *resource, struct coap_observer *observer); +/** + * @brief Event types for observer event callbacks. + */ +enum coap_observer_event { + /** An observer was added. */ + COAP_OBSERVER_ADDED = 0, + /** An observer was removed. */ + COAP_OBSERVER_REMOVED, +}; + +/** + * @typedef coap_observer_event_handler_t + * @brief Type of the handler being called when a resource's observers has been modified. + * Either an observer was added or removed. + * + * @param resource A pointer to a CoAP resource for which the event occurred + * @param observer The observer being added/removed + * @param event The event type + */ +typedef void (*coap_observer_event_handler_t)(struct coap_resource *resource, + struct coap_observer *observer, + enum coap_observer_event event); + /** * @brief Description of CoAP resource. * @@ -250,6 +275,13 @@ struct coap_resource { void *user_data; sys_slist_t observers; int age; +#if defined(CONFIG_COAP_OBSERVER_EVENTS) || defined(DOXYGEN) + /** + * Optional observer event callback function + * Only available when @kconfig{CONFIG_COAP_OBSERVER_EVENTS} is enabled. + */ + coap_observer_event_handler_t observer_event_handler; +#endif }; /** @@ -272,7 +304,7 @@ struct coap_packet { uint8_t hdr_len; /**< CoAP header length */ uint16_t opt_len; /**< Total options length (delta + len + value) */ uint16_t delta; /**< Used for delta calculation in CoAP packet */ -#if defined(CONFIG_COAP_KEEP_USER_DATA) || defined(DOXGEN) +#if defined(CONFIG_COAP_KEEP_USER_DATA) || defined(DOXYGEN) /** * Application specific user data. * Only available when @kconfig{CONFIG_COAP_KEEP_USER_DATA} is enabled. @@ -371,6 +403,15 @@ uint8_t coap_header_get_token(const struct coap_packet *cpkt, uint8_t *token); */ uint8_t coap_header_get_code(const struct coap_packet *cpkt); +/** + * @brief Modifies the code of the CoAP packet. + * + * @param cpkt CoAP packet representation + * @param code CoAP code + * @return 0 on success, -EINVAL on failure + */ +int coap_header_set_code(const struct coap_packet *cpkt, uint8_t code); + /** * @brief Returns the message id associated with the CoAP packet. * @@ -392,6 +433,20 @@ uint16_t coap_header_get_id(const struct coap_packet *cpkt); const uint8_t *coap_packet_get_payload(const struct coap_packet *cpkt, uint16_t *len); +/** + * @brief Verify if CoAP URI path matches with provided options. + * + * @param path Null-terminated array of strings. + * @param options Parsed options from coap_packet_parse() + * @param opt_num Number of options + * + * @return true if the CoAP URI path matches, + * false otherwise. + */ +bool coap_uri_path_match(const char * const *path, + struct coap_option *options, + uint8_t opt_num); + /** * @brief Parses the CoAP packet in data, validating it and * initializing @a cpkt. @a data must remain valid while @a cpkt is used. @@ -566,18 +621,52 @@ int coap_packet_append_payload_marker(struct coap_packet *cpkt); int coap_packet_append_payload(struct coap_packet *cpkt, const uint8_t *payload, uint16_t payload_len); +/** + * @brief Check if a CoAP packet is a CoAP request. + * + * @param cpkt Packet to be checked. + * + * @return true if the packet is a request, + * false otherwise. + */ +bool coap_packet_is_request(const struct coap_packet *cpkt); + /** * @brief When a request is received, call the appropriate methods of * the matching resources. * * @param cpkt Packet received * @param resources Array of known resources + * @param resources_len Number of resources in the array * @param options Parsed options from coap_packet_parse() * @param opt_num Number of options * @param addr Peer address * @param addr_len Peer address length * - * @retval 0 in case of success. + * @retval >= 0 in case of success. + * @retval -ENOTSUP in case of invalid request code. + * @retval -EPERM in case resource handler is not implemented. + * @retval -ENOENT in case the resource is not found. + */ +int coap_handle_request_len(struct coap_packet *cpkt, + struct coap_resource *resources, + size_t resources_len, + struct coap_option *options, + uint8_t opt_num, + struct sockaddr *addr, socklen_t addr_len); + +/** + * @brief When a request is received, call the appropriate methods of + * the matching resources. + * + * @param cpkt Packet received + * @param resources Array of known resources (terminated with empty resource) + * @param options Parsed options from coap_packet_parse() + * @param opt_num Number of options + * @param addr Peer address + * @param addr_len Peer address length + * + * @retval >= 0 in case of success. * @retval -ENOTSUP in case of invalid request code. * @retval -EPERM in case resource handler is not implemented. * @retval -ENOENT in case the resource is not found. @@ -839,10 +928,30 @@ bool coap_register_observer(struct coap_resource *resource, * * @param resource Resource in which to remove the observer * @param observer Observer to be removed + * + * @return true if the observer was found and removed. */ -void coap_remove_observer(struct coap_resource *resource, +bool coap_remove_observer(struct coap_resource *resource, struct coap_observer *observer); +/** + * @brief Returns the observer that matches address @a addr + * and has token @a token. + * + * @param observers Pointer to the array of observers + * @param len Size of the array of observers + * @param addr Address of the endpoint observing a resource + * @param token Pointer to the token + * @param token_len Length of valid bytes in the token + * + * @return A pointer to a observer if a match is found, NULL + * otherwise. + */ +struct coap_observer *coap_find_observer( + struct coap_observer *observers, size_t len, + const struct sockaddr *addr, + const uint8_t *token, uint8_t token_len); + /** * @brief Returns the observer that matches address @a addr. * @@ -850,6 +959,9 @@ void coap_remove_observer(struct coap_resource *resource, * @param len Size of the array of observers * @param addr Address of the endpoint observing a resource * + * @note The function coap_find_observer() should be preferred + * if both the observer's address and token are known. + * * @return A pointer to a observer if a match is found, NULL * otherwise. */ @@ -857,6 +969,24 @@ struct coap_observer *coap_find_observer_by_addr( struct coap_observer *observers, size_t len, const struct sockaddr *addr); +/** + * @brief Returns the observer that has token @a token. + * + * @param observers Pointer to the array of observers + * @param len Size of the array of observers + * @param token Pointer to the token + * @param token_len Length of valid bytes in the token + * + * @note The function coap_find_observer() should be preferred + * if both the observer's address and token are known. + * + * @return A pointer to a observer if a match is found, NULL + * otherwise. + */ +struct coap_observer *coap_find_observer_by_token( + struct coap_observer *observers, size_t len, + const uint8_t *token, uint8_t token_len); + /** * @brief Returns the next available observer representation. * diff --git a/include/zephyr/net/coap_client.h b/include/zephyr/net/coap_client.h index 86c4911de5b..c3de1abee27 100644 --- a/include/zephyr/net/coap_client.h +++ b/include/zephyr/net/coap_client.h @@ -20,6 +20,7 @@ */ #include +#include #define MAX_COAP_MSG_LEN (CONFIG_COAP_CLIENT_MESSAGE_HEADER_SIZE + \ @@ -89,6 +90,7 @@ struct coap_client_internal_request { struct coap_pending pending; struct coap_client_request coap_request; struct coap_packet request; + uint8_t request_tag[COAP_TOKEN_MAX_LEN]; }; struct coap_client { @@ -100,6 +102,8 @@ struct coap_client { uint8_t send_buf[MAX_COAP_MSG_LEN]; uint8_t recv_buf[MAX_COAP_MSG_LEN]; struct coap_client_internal_request requests[CONFIG_COAP_CLIENT_MAX_REQUESTS]; + struct coap_option echo_option; + bool send_echo; }; /** @endcond */ diff --git a/include/zephyr/net/coap_link_format.h b/include/zephyr/net/coap_link_format.h index 17374202b6d..cabfb9ff859 100644 --- a/include/zephyr/net/coap_link_format.h +++ b/include/zephyr/net/coap_link_format.h @@ -24,15 +24,45 @@ extern "C" { /** * This resource should be added before all other resources that should be - * included in the responses of the .well-known/core resource. + * included in the responses of the .well-known/core resource if is to be used with + * coap_well_known_core_get. */ #define COAP_WELL_KNOWN_CORE_PATH \ ((const char * const[]) { ".well-known", "core", NULL }) +/** + * @brief Build a CoAP response for a .well-known/core CoAP request. + * + * @param resource Array of known resources, terminated with an empty resource + * @param request A pointer to the .well-known/core CoAP request + * @param response A pointer to a CoAP response, will be initialized + * @param data A data pointer to be used to build the CoAP response + * @param data_len The maximum length of the data buffer + * + * @return 0 in case of success or negative in case of error. + */ int coap_well_known_core_get(struct coap_resource *resource, - struct coap_packet *request, + const struct coap_packet *request, struct coap_packet *response, - uint8_t *data, uint16_t len); + uint8_t *data, uint16_t data_len); + +/** + * @brief Build a CoAP response for a .well-known/core CoAP request. + * + * @param resources Array of known resources + * @param resources_len Number of resources in the array + * @param request A pointer to the .well-known/core CoAP request + * @param response A pointer to a CoAP response, will be initialized + * @param data A data pointer to be used to build the CoAP response + * @param data_len The maximum length of the data buffer + * + * @return 0 in case of success or negative in case of error. + */ +int coap_well_known_core_get_len(struct coap_resource *resources, + size_t resources_len, + const struct coap_packet *request, + struct coap_packet *response, + uint8_t *data, uint16_t data_len); /** * In case you want to add attributes to the resources included in the diff --git a/include/zephyr/net/coap_service.h b/include/zephyr/net/coap_service.h new file mode 100644 index 00000000000..3e3201308b9 --- /dev/null +++ b/include/zephyr/net/coap_service.h @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2023 Basalte bv + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** @file + * @brief CoAP Service API + * + * An API for applications to respond to CoAP requests + */ + +#ifndef ZEPHYR_INCLUDE_NET_COAP_SERVICE_H_ +#define ZEPHYR_INCLUDE_NET_COAP_SERVICE_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief CoAP Service API + * @defgroup coap_service CoAP service API + * @ingroup networking + * @{ + */ + +/** + * @name CoAP Service configuration flags + * @anchor COAP_SERVICE_FLAGS + * @{ + */ + +/** Start the service on boot. */ +#define COAP_SERVICE_AUTOSTART BIT(0) + +/** @} */ + +/** @cond INTERNAL_HIDDEN */ + +struct coap_service_data { + int sock_fd; + struct coap_observer observers[CONFIG_COAP_SERVICE_OBSERVERS]; + struct coap_pending pending[CONFIG_COAP_SERVICE_PENDING_MESSAGES]; +}; + +struct coap_service { + const char *name; + const char *host; + uint16_t *port; + uint8_t flags; + struct coap_resource *res_begin; + struct coap_resource *res_end; + struct coap_service_data *data; +}; + +#define __z_coap_service_define(_name, _host, _port, _flags, _res_begin, _res_end) \ + static struct coap_service_data coap_service_data_##_name; \ + const STRUCT_SECTION_ITERABLE(coap_service, _name) = { \ + .name = STRINGIFY(_name), \ + .host = _host, \ + .port = (uint16_t *)(_port), \ + .flags = _flags, \ + .res_begin = (_res_begin), \ + .res_end = (_res_end), \ + .data = &coap_service_data_##_name, \ + } + +/** @endcond */ + +/** + * @brief Define a static CoAP resource owned by the service named @p _service . + * + * @note The handlers registered with the resource can return a CoAP response code to reply with + * an acknowledge without any payload, nothing is sent if the return value is 0 or negative. + * As seen in the example. + * + * @code{.c} + * static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios); + * + * static int led_put(struct coap_resource *resource, struct coap_packet *request, + * struct sockaddr *addr, socklen_t addr_len) + * { + * const uint8_t *payload; + * uint16_t payload_len; + * + * payload = coap_packet_get_payload(request, &payload_len); + * if (payload_len != 1) { + * return COAP_RESPONSE_CODE_BAD_REQUEST; + * } + * + * if (gpio_pin_set_dt(&led, payload[0]) < 0) { + * return COAP_RESPONSE_CODE_INTERNAL_ERROR; + * } + * + * return COAP_RESPONSE_CODE_CHANGED; + * } + * + * COAP_RESOURCE_DEFINE(my_resource, my_service, { + * .put = led_put, + * }); + * @endcode + * + * @param _name Name of the resource. + * @param _service Name of the associated service. + */ +#define COAP_RESOURCE_DEFINE(_name, _service, ...) \ + STRUCT_SECTION_ITERABLE_ALTERNATE(coap_resource_##_service, coap_resource, _name) \ + = __VA_ARGS__ + +/** + * @brief Define a CoAP service with static resources. + * + * @note The @p _host parameter can be `NULL`. If not, it is used to specify an IP address either in + * IPv4 or IPv6 format a fully-qualified hostname or a virtual host, otherwise the any address is + * used. + * + * @note The @p _port parameter must be non-`NULL`. It points to a location that specifies the port + * number to use for the service. If the specified port number is zero, then an ephemeral port + * number will be used and the actual port number assigned will be written back to memory. For + * ephemeral port numbers, the memory pointed to by @p _port must be writeable. + * + * @param _name Name of the service. + * @param _host IP address or hostname associated with the service. + * @param[inout] _port Pointer to port associated with the service. + * @param _flags Configuration flags @see @ref COAP_SERVICE_FLAGS. + */ +#define COAP_SERVICE_DEFINE(_name, _host, _port, _flags) \ + extern struct coap_resource _CONCAT(_coap_resource_##_name, _list_start)[]; \ + extern struct coap_resource _CONCAT(_coap_resource_##_name, _list_end)[]; \ + __z_coap_service_define(_name, _host, _port, _flags, \ + &_CONCAT(_coap_resource_##_name, _list_start)[0], \ + &_CONCAT(_coap_resource_##_name, _list_end)[0]) + +/** + * @brief Count the number of CoAP services. + * + * @param[out] _dst Pointer to location where result is written. + */ +#define COAP_SERVICE_COUNT(_dst) STRUCT_SECTION_COUNT(coap_service, _dst) + +/** + * @brief Count CoAP service static resources. + * + * @param _service Pointer to a service. + */ +#define COAP_SERVICE_RESOURCE_COUNT(_service) ((_service)->res_end - (_service)->res_begin) + +/** + * @brief Check if service has the specified resource. + * + * @param _service Pointer to a service. + * @param _resource Pointer to a resource. + */ +#define COAP_SERVICE_HAS_RESOURCE(_service, _resource) \ + ((_service)->res_begin <= _resource && _resource < (_service)->res_end) + +/** + * @brief Iterate over all CoAP services. + * + * @param _it Name of iterator (of type @ref coap_service) + */ +#define COAP_SERVICE_FOREACH(_it) STRUCT_SECTION_FOREACH(coap_service, _it) + +/** + * @brief Iterate over static CoAP resources associated with a given @p _service. + * + * @note This macro requires that @p _service is defined with @ref COAP_SERVICE_DEFINE. + * + * @param _service Name of CoAP service + * @param _it Name of iterator (of type @ref coap_resource) + */ +#define COAP_RESOURCE_FOREACH(_service, _it) \ + STRUCT_SECTION_FOREACH_ALTERNATE(coap_resource_##_service, coap_resource, _it) + +/** + * @brief Iterate over all static resources associated with @p _service . + * + * @note This macro is suitable for a @p _service defined with @ref COAP_SERVICE_DEFINE. + * + * @param _service Pointer to COAP service + * @param _it Name of iterator (of type @ref coap_resource) + */ +#define COAP_SERVICE_FOREACH_RESOURCE(_service, _it) \ + for (struct coap_resource *_it = (_service)->res_begin; ({ \ + __ASSERT(_it <= (_service)->res_end, "unexpected list end location"); \ + _it < (_service)->res_end; \ + }); _it++) + +/** + * @brief Start the provided @p service . + * + * @note This function is suitable for a @p service defined with @ref COAP_SERVICE_DEFINE. + * + * @param service Pointer to CoAP service + * @retval 0 in case of success. + * @retval -EALREADY in case of an already running service. + * @retval -ENOMEM in case the server has no available context. + */ +int coap_service_start(const struct coap_service *service); + +/** + * @brief Stop the provided @p service . + * + * @note This function is suitable for a @p service defined with @ref COAP_SERVICE_DEFINE. + * + * @param service Pointer to CoAP service + * @retval 0 in case of success. + * @retval -EALREADY in case the service isn't running. + */ +int coap_service_stop(const struct coap_service *service); + +/** + * @brief Send a CoAP message from the provided @p service . + * + * @note This function is suitable for a @p service defined with @ref COAP_SERVICE_DEFINE. + * + * @param service Pointer to CoAP service + * @param cpkt CoAP Packet to send + * @param addr Peer address + * @param addr_len Peer address length + * @return 0 in case of success or negative in case of error. + */ +int coap_service_send(const struct coap_service *service, const struct coap_packet *cpkt, + const struct sockaddr *addr, socklen_t addr_len); + +/** + * @brief Send a CoAP message from the provided @p resource . + * + * @note This function is suitable for a @p resource defined with @ref COAP_RESOURCE_DEFINE. + * + * @param resource Pointer to CoAP resource + * @param cpkt CoAP Packet to send + * @param addr Peer address + * @param addr_len Peer address length + * @return 0 in case of success or negative in case of error. + */ +int coap_resource_send(const struct coap_resource *resource, const struct coap_packet *cpkt, + const struct sockaddr *addr, socklen_t addr_len); + +/** + * @brief Parse a CoAP observe request for the provided @p resource . + * + * @note This function is suitable for a @p resource defined with @ref COAP_RESOURCE_DEFINE. + * + * If the observe option value is equal to 0, an observer will be added, if the value is equal + * to 1, an existing observer will be removed. + * + * @param resource Pointer to CoAP resource + * @param request CoAP request to parse + * @param addr Peer address + * @return the observe option value in case of success or negative in case of error. + */ +int coap_resource_parse_observe(struct coap_resource *resource, const struct coap_packet *request, + const struct sockaddr *addr); + +/** + * @brief Lookup an observer by address and remove it from the @p resource . + * + * @note This function is suitable for a @p resource defined with @ref COAP_RESOURCE_DEFINE. + * + * @param resource Pointer to CoAP resource + * @param addr Peer address + * @return 0 in case of success or negative in case of error. + */ +int coap_resource_remove_observer_by_addr(struct coap_resource *resource, + const struct sockaddr *addr); + +/** + * @brief Lookup an observer by token and remove it from the @p resource . + * + * @note This function is suitable for a @p resource defined with @ref COAP_RESOURCE_DEFINE. + * + * @param resource Pointer to CoAP resource + * @param token Pointer to the token + * @param token_len Length of valid bytes in the token + * @return 0 in case of success or negative in case of error. + */ +int coap_resource_remove_observer_by_token(struct coap_resource *resource, + const uint8_t *token, uint8_t token_len); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_NET_COAP_SERVICE_H_ */ diff --git a/include/zephyr/net/conn_mgr_connectivity.h b/include/zephyr/net/conn_mgr_connectivity.h index 0af270cd5b9..0d92cdbf8d7 100644 --- a/include/zephyr/net/conn_mgr_connectivity.h +++ b/include/zephyr/net/conn_mgr_connectivity.h @@ -39,18 +39,25 @@ extern "C" { NET_MGMT_EVENT_BIT) #define _NET_MGMT_CONN_IF_EVENT (NET_MGMT_IFACE_BIT | _NET_MGMT_CONN_BASE) -enum net_event_ethernet_cmd { +/** @endcond */ + +enum net_event_conn_cmd { NET_EVENT_CONN_CMD_IF_TIMEOUT = 1, NET_EVENT_CONN_CMD_IF_FATAL_ERROR, }; +/** + * @brief net_mgmt event raised when a connection attempt times out + */ #define NET_EVENT_CONN_IF_TIMEOUT \ (_NET_MGMT_CONN_IF_EVENT | NET_EVENT_CONN_CMD_IF_TIMEOUT) +/** + * @brief net_mgmt event raised when a non-recoverable connectivity error occurs on an iface + */ #define NET_EVENT_CONN_IF_FATAL_ERROR \ (_NET_MGMT_CONN_IF_EVENT | NET_EVENT_CONN_CMD_IF_FATAL_ERROR) -/** @endcond */ /** * @brief Per-iface connectivity flags @@ -76,7 +83,7 @@ enum conn_mgr_if_flag { * No auto-down * * When set, conn_mgr will not automatically take the iface admin-down when it stops - * trying to connect, even if NET_CONNECTION_MANAGER_AUTO_IF_DOWN is enabled. + * trying to connect, even if CONFIG_NET_CONNECTION_MANAGER_AUTO_IF_DOWN is enabled. */ CONN_MGR_IF_NO_AUTO_DOWN, @@ -86,7 +93,9 @@ enum conn_mgr_if_flag { /** @endcond */ }; -/** Value to use with @ref conn_mgr_conn_binding.timeout to indicate no timeout */ +/** Value to use with @ref conn_mgr_if_set_timeout and @ref conn_mgr_conn_binding.timeout to + * indicate no timeout + */ #define CONN_MGR_IF_NO_TIMEOUT 0 /** @@ -95,7 +104,7 @@ enum conn_mgr_if_flag { * If the provided iface has been bound to a connectivity implementation, initiate * network connect/association. * - * Automatically takes the iface admin-up (by calling net_if_up) if it isn't already. + * Automatically takes the iface admin-up (by calling @ref net_if_up) if it isn't already. * * Non-Blocking. * @@ -231,23 +240,27 @@ int conn_mgr_if_get_timeout(struct net_if *iface); * * @param iface - Pointer to the network interface to modify. * @param timeout - The timeout value to set (in seconds). - * Pass CONN_MGR_IF_NO_TIMEOUT to disable the timeout. + * Pass @ref CONN_MGR_IF_NO_TIMEOUT to disable the timeout. * @retval 0 on success. * @retval -ENOTSUP if the provided iface is not bound to a connectivity implementation. */ int conn_mgr_if_set_timeout(struct net_if *iface, int timeout); /** - * @brief Initialize all connectivity implementation bindings - * - * + * @} + */ + +/** + * @brief Connection Manager Bulk API + * @defgroup conn_mgr_connectivity_bulk Connection Manager Connectivity Bulk API + * @ingroup networking + * @{ */ -void conn_mgr_conn_init(void); /** * @brief Convenience function that takes all available ifaces into the admin-up state. * - * Essentially a wrapper for net_if_up. + * Essentially a wrapper for @ref net_if_up. * * @param skip_ignored - If true, only affect ifaces that aren't ignored by conn_mgr. * Otherwise, affect all ifaces. @@ -260,7 +273,7 @@ int conn_mgr_all_if_up(bool skip_ignored); /** * @brief Convenience function that takes all available ifaces into the admin-down state. * - * Essentially a wrapper for net_if_down. + * Essentially a wrapper for @ref net_if_down. * * @param skip_ignored - If true, only affect ifaces that aren't ignored by conn_mgr. * Otherwise, affect all ifaces. @@ -273,7 +286,7 @@ int conn_mgr_all_if_down(bool skip_ignored); * @brief Convenience function that takes all available ifaces into the admin-up state, and * connects those that support connectivity. * - * Essentially a wrapper for net_if_up and conn_mgr_if_connect. + * Essentially a wrapper for @ref net_if_up and @ref conn_mgr_if_connect. * * @param skip_ignored - If true, only affect ifaces that aren't ignored by conn_mgr. * Otherwise, affect all ifaces. @@ -286,7 +299,7 @@ int conn_mgr_all_if_connect(bool skip_ignored); * @brief Convenience function that disconnects all available ifaces that support connectivity * without putting them into admin-down state (unless auto-down is enabled for the iface). * - * Essentially a wrapper for net_if_down. + * Essentially a wrapper for @ref net_if_down. * * @param skip_ignored - If true, only affect ifaces that aren't ignored by conn_mgr. * Otherwise, affect all ifaces. diff --git a/include/zephyr/net/conn_mgr_connectivity_impl.h b/include/zephyr/net/conn_mgr_connectivity_impl.h index 8e8218bda0b..51b826d3491 100644 --- a/include/zephyr/net/conn_mgr_connectivity_impl.h +++ b/include/zephyr/net/conn_mgr_connectivity_impl.h @@ -41,12 +41,12 @@ struct conn_mgr_conn_binding; struct conn_mgr_conn_api { /** * @brief When called, the connectivity implementation should start attempting to - * establish connectivity for (associate with a network) the bound iface pointed + * establish connectivity (association with a network) for the bound iface pointed * to by if_conn->iface. * * Must be non-blocking. * - * Called by conn_mgr_if_connect. + * Called by @ref conn_mgr_if_connect. */ int (*connect)(struct conn_mgr_conn_binding *const binding); @@ -57,7 +57,7 @@ struct conn_mgr_conn_api { * * Must be non-blocking. * - * Called by conn_mgr_if_disconnect. + * Called by @ref conn_mgr_if_disconnect. */ int (*disconnect)(struct conn_mgr_conn_binding *const binding); @@ -189,7 +189,7 @@ struct conn_mgr_conn_binding { * The connectivity implementation should give up on establishing connectivity after this * timeout, even if persistence is enabled. * - * Set to CONN_MGR_IF_NO_TIMEOUT to indicate that no timeout should be used. + * Set to @ref CONN_MGR_IF_NO_TIMEOUT to indicate that no timeout should be used. */ int timeout; @@ -273,7 +273,7 @@ static inline void conn_mgr_binding_lock(struct conn_mgr_conn_binding *binding) /** * @brief Unlocks the passed-in binding. * - * Call this after any call to conn_mgr_binding_lock once done accessing binding data. + * Call this after any call to @ref conn_mgr_binding_lock once done accessing binding data. * * Reentrant. * @@ -289,13 +289,13 @@ static inline void conn_mgr_binding_unlock(struct conn_mgr_conn_binding *binding /** * @brief Set the value of the specified connectivity flag for the provided binding * - * Can be used from any thread or callback without calling conn_mgr_binding_lock. + * Can be used from any thread or callback without calling @ref conn_mgr_binding_lock. * * For use only by connectivity implementations * - * @param binding - The binding to check - * @param flag - The flag to check - * @param value - New value for the specified flag + * @param binding The binding to check + * @param flag The flag to check + * @param value New value for the specified flag */ static inline void conn_mgr_binding_set_flag(struct conn_mgr_conn_binding *binding, enum conn_mgr_if_flag flag, bool value) @@ -313,13 +313,13 @@ static inline void conn_mgr_binding_set_flag(struct conn_mgr_conn_binding *bindi /** * @brief Check the value of the specified connectivity flag for the provided binding * - * Can be used from any thread or callback without calling conn_mgr_binding_lock. + * Can be used from any thread or callback without calling @ref conn_mgr_binding_lock. * * For use only by connectivity implementations * - * @param binding - The binding to check - * @param flag - The flag to check - * @return bool - The value of the specified flag + * @param binding The binding to check + * @param flag The flag to check + * @return bool The value of the specified flag */ static inline bool conn_mgr_binding_get_flag(struct conn_mgr_conn_binding *binding, enum conn_mgr_if_flag flag) diff --git a/include/zephyr/net/conn_mgr_monitor.h b/include/zephyr/net/conn_mgr_monitor.h index 1bff698a86c..94c50d90f19 100644 --- a/include/zephyr/net/conn_mgr_monitor.h +++ b/include/zephyr/net/conn_mgr_monitor.h @@ -11,7 +11,14 @@ extern "C" { #endif -#if defined(CONFIG_NET_CONNECTION_MANAGER) +#if defined(CONFIG_NET_CONNECTION_MANAGER) || defined(__DOXYGEN__) + +/** + * @brief Connection Manager API + * @defgroup conn_mgr Connection Manager API + * @ingroup networking + * @{ + */ struct net_if; struct net_l2; @@ -31,7 +38,7 @@ void conn_mgr_mon_resend_status(void); * and if the iface was connected before being ignored, events will be fired as though it * disconnected at that moment. * - * @param iface - iface to be ignored. + * @param iface iface to be ignored. */ void conn_mgr_ignore_iface(struct net_if *iface); @@ -44,14 +51,16 @@ void conn_mgr_ignore_iface(struct net_if *iface); * and if the iface was connected before being watched, events will be fired as though * it connected in that moment. * - * @param iface - iface to no longer ignore. + * All ifaces default to watched at boot. + * + * @param iface iface to no longer ignore. */ void conn_mgr_watch_iface(struct net_if *iface); /** * @brief Check whether the provided iface is currently ignored. * - * @param iface - The iface to check. + * @param iface The iface to check. * @retval true if the iface is being ignored by conn_mgr. * @retval false if the iface is being watched by conn_mgr. */ @@ -62,7 +71,7 @@ bool conn_mgr_is_iface_ignored(struct net_if *iface); * * This is a wrapper for conn_mgr_ignore_iface that ignores all ifaces that use the L2. * - * @param l2 - L2 to be ignored. + * @param l2 L2 to be ignored. */ void conn_mgr_ignore_l2(const struct net_l2 *l2); @@ -71,10 +80,14 @@ void conn_mgr_ignore_l2(const struct net_l2 *l2); * * This is a wrapper for conn_mgr_watch_iface that watches all ifaces that use the L2. * - * @param l2 - L2 to watch. + * @param l2 L2 to watch. */ void conn_mgr_watch_l2(const struct net_l2 *l2); +/** + * @} + */ + #else #define conn_mgr_mon_resend_status(...) diff --git a/include/zephyr/net/dsa.h b/include/zephyr/net/dsa.h index 755521b1325..479690509a3 100644 --- a/include/zephyr/net/dsa.h +++ b/include/zephyr/net/dsa.h @@ -16,7 +16,7 @@ /** * @brief DSA definitions and helpers - * @defgroup DSA - Distributed Switch Architecture definitions and helpers + * @defgroup DSA Distributed Switch Architecture definitions and helpers * @ingroup networking * @{ */ diff --git a/include/zephyr/net/http/service.h b/include/zephyr/net/http/service.h index a7af97cb500..b6997334de4 100644 --- a/include/zephyr/net/http/service.h +++ b/include/zephyr/net/http/service.h @@ -135,7 +135,7 @@ struct http_service_desc { #define HTTP_SERVICE_FOREACH(_it) STRUCT_SECTION_FOREACH(http_service_desc, _it) /** - * @brief Iterate over static HTTP reesources associated with a given @p _service. + * @brief Iterate over static HTTP resources associated with a given @p _service. * * @note This macro requires that @p _service is defined with @ref HTTP_SERVICE_DEFINE. * diff --git a/include/zephyr/net/icmp.h b/include/zephyr/net/icmp.h new file mode 100644 index 00000000000..a5b9f6b2455 --- /dev/null +++ b/include/zephyr/net/icmp.h @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** @file icmp.h + * + * @defgroup icmp Send and receive IPv4 or IPv6 ICMP Echo Request messages. + * @ingroup networking + * @{ + * @brief ICMP sending and receiving. + */ + +#ifndef ZEPHYR_INCLUDE_NET_ICMP_H_ +#define ZEPHYR_INCLUDE_NET_ICMP_H_ + +#include + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define NET_ICMPV4_ECHO_REQUEST 8 +#define NET_ICMPV4_ECHO_REPLY 0 +#define NET_ICMPV6_ECHO_REQUEST 128 +#define NET_ICMPV6_ECHO_REPLY 129 + +struct net_icmp_ctx; +struct net_icmp_ip_hdr; +struct net_icmp_ping_params; + +/** + * @typedef net_icmp_handler_t + * @brief Handler function that is called when ICMP response is received. + * + * @param ctx ICMP context to use. + * @param pkt Received ICMP response network packet. + * @param ip_hdr IP header of the packet. + * @param icmp_hdr ICMP header of the packet. + * @param user_data A valid pointer to user data or NULL + */ +typedef int (*net_icmp_handler_t)(struct net_icmp_ctx *ctx, + struct net_pkt *pkt, + struct net_icmp_ip_hdr *ip_hdr, + struct net_icmp_hdr *icmp_hdr, + void *user_data); + +/** + * @typedef net_icmp_offload_ping_handler_t + * @brief Handler function that is called when an Echo-Request is sent + * to offloaded device. This handler is typically setup by the + * device driver so that it can catch the ping request and send + * it to the offloaded device. + * + * @param ctx ICMP context used in this request. + * @param iface Network interface, can be set to NULL in which case the + * interface is selected according to destination address. + * @param dst IP address of the target host. + * @param params Echo-Request specific parameters. May be NULL in which case + * suitable default parameters are used. + * @param user_data User supplied opaque data passed to the handler. May be NULL. + * + */ +typedef int (*net_icmp_offload_ping_handler_t)(struct net_icmp_ctx *ctx, + struct net_if *iface, + struct sockaddr *dst, + struct net_icmp_ping_params *params, + void *user_data); + +/** + * @brief ICMP context structure. + */ +struct net_icmp_ctx { + /** List node */ + sys_snode_t node; + + /** ICMP response handler */ + net_icmp_handler_t handler; + + /** Network interface where the ICMP request was sent */ + struct net_if *iface; + + /** Opaque user supplied data */ + void *user_data; + + /** ICMP type of the response we are waiting */ + uint8_t type; + + /** ICMP code of the response type we are waiting */ + uint8_t code; +}; + +/** + * @brief Struct presents either IPv4 or IPv6 header in ICMP response message. + */ +struct net_icmp_ip_hdr { + union { + /** IPv4 header in response message. */ + struct net_ipv4_hdr *ipv4; + + /** IPv6 header in response message. */ + struct net_ipv6_hdr *ipv6; + }; + + /** Is the header IPv4 or IPv6 one. Value of either AF_INET or AF_INET6 */ + sa_family_t family; +}; + +/** + * @brief Struct presents parameters that are needed when sending + * Echo-Request (ping) messages. + */ +struct net_icmp_ping_params { + /** An identifier to aid in matching Echo Replies to this Echo Request. + * May be zero. + */ + uint16_t identifier; + + /** A sequence number to aid in matching Echo Replies to this + * Echo Request. May be zero. + */ + uint16_t sequence; + + /** Can be either IPv4 Type-of-service field value, or IPv6 Traffic + * Class field value. Represents combined DSCP and ECN values. + */ + uint8_t tc_tos; + + /** Network packet priority. */ + int priority; + + /* Arbitrary payload data that will be included in the Echo Reply + * verbatim. May be NULL. + */ + const void *data; + + /** Size of the Payload Data in bytes. May be zero. In case data + * pointer is NULL, the function will generate the payload up to + * the requested size. + */ + size_t data_size; +}; + +/** + * @brief Initialize the ICMP context structure. Must be called before + * ICMP messages can be sent. This will register handler to the + * system. + * + * @param ctx ICMP context used in this request. + * @param type Type of ICMP message we are handling. + * @param code Code of ICMP message we are handling. + * @param handler Callback function that is called when a response is received. + */ +int net_icmp_init_ctx(struct net_icmp_ctx *ctx, uint8_t type, uint8_t code, + net_icmp_handler_t handler); + +/** + * @brief Cleanup the ICMP context structure. This will unregister the ICMP handler + * from the system. + * + * @param ctx ICMP context used in this request. + */ +int net_icmp_cleanup_ctx(struct net_icmp_ctx *ctx); + +/** + * @brief Send ICMP echo request message. + * + * @param ctx ICMP context used in this request. + * @param iface Network interface, can be set to NULL in which case the + * interface is selected according to destination address. + * @param dst IP address of the target host. + * @param params Echo-Request specific parameters. May be NULL in which case + * suitable default parameters are used. + * @param user_data User supplied opaque data passed to the handler. May be NULL. + * + * @return Return 0 if the sending succeed, <0 otherwise. + */ +int net_icmp_send_echo_request(struct net_icmp_ctx *ctx, + struct net_if *iface, + struct sockaddr *dst, + struct net_icmp_ping_params *params, + void *user_data); + +/** + * @brief ICMP offload context structure. + */ +struct net_icmp_offload { + /** List node */ + sys_snode_t node; + + /** + * ICMP response handler. Currently there is only one handler. + * This means that one offloaded ping request/response can be going + * on at the same time. + */ + net_icmp_handler_t handler; + + /** ICMP offloaded ping handler */ + net_icmp_offload_ping_handler_t ping_handler; + + /** Offloaded network interface */ + struct net_if *iface; +}; + +/** + * @brief Register a handler function that is called when an Echo-Request + * is sent to the offloaded device. This function is typically + * called by a device driver so that it can do the actual offloaded + * ping call. + * + * @param ctx ICMP offload context used for this interface. + * @param iface Network interface of the offloaded device. + * @param ping_handler Function to be called when offloaded ping request is done. + * + * @return Return 0 if the register succeed, <0 otherwise. + */ +int net_icmp_register_offload_ping(struct net_icmp_offload *ctx, + struct net_if *iface, + net_icmp_offload_ping_handler_t ping_handler); + +/** + * @brief Unregister the offload handler. + * + * @param ctx ICMP offload context used for this interface. + * + * @return Return 0 if the call succeed, <0 otherwise. + */ +int net_icmp_unregister_offload_ping(struct net_icmp_offload *ctx); + +/** + * @brief Get a ICMP response handler function for an offloaded device. + * When a ping response is received by the driver, it should call + * the handler function with proper parameters so that the ICMP response + * is received by the net stack. + * + * @param ctx ICMP offload context used in this request. + * @param resp_handler Function to be called when offloaded ping response + * is received by the offloaded driver. The ICMP response handler + * function is returned and the caller should call it when appropriate. + * + * @return Return 0 if the call succeed, <0 otherwise. + */ +int net_icmp_get_offload_rsp_handler(struct net_icmp_offload *ctx, + net_icmp_handler_t *resp_handler); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_NET_ICMP_H */ + +/**@} */ diff --git a/include/zephyr/net/ieee802154.h b/include/zephyr/net/ieee802154.h index a17405b1000..e4ef8bba6f8 100644 --- a/include/zephyr/net/ieee802154.h +++ b/include/zephyr/net/ieee802154.h @@ -6,7 +6,9 @@ /** * @file - * @brief IEEE 802.15.4 L2 stack public header + * @brief IEEE 802.15.4 native L2 stack public header + * + * @note All references to the standard in this file cite IEEE 802.15.4-2020. */ #ifndef ZEPHYR_INCLUDE_NET_IEEE802154_H_ @@ -23,52 +25,216 @@ extern "C" { #endif /** - * @brief IEEE 802.15.4 library - * @defgroup ieee802154 IEEE 802.15.4 Library - * @ingroup networking + * @defgroup ieee802154 IEEE 802.15.4 and Thread APIs + * @ingroup connectivity + * + * @brief IEEE 802.15.4 native and OpenThread L2, configuration, management and + * driver APIs + * + * @details The IEEE 802.15.4 and Thread subsystems comprise the OpenThread L2 + * subsystem, the native IEEE 802.15.4 L2 subsystem ("Soft" MAC), a mostly + * vendor and protocol agnostic driver API shared between the OpenThread and + * native L2 stacks ("Hard" MAC and PHY) as well as several APIs to configure + * the subsystem (shell, net management, Kconfig, devicetree, etc.). + * + * The **OpenThread subsystem API** integrates the external OpenThread stack into Zephyr. It builds upon + * Zephyr's native IEEE 802.15.4 driver API. + * + * The **native IEEE 802.15.4 subsystem APIs** are exposed at different levels + * and address several audiences: + * - shell (end users, application developers): + * - a set of IEEE 802.15.4 shell commands (see `shell> ieee802154 help`) + * - application API (application developers): + * - IPv6, DGRAM and RAW sockets for actual peer-to-peer, multicast and + * broadcast data exchange between nodes including connection specific + * configuration (sample coming soon, see + * https://github.com/linux-wpan/wpan-tools/tree/master/examples for now + * which inspired our API and therefore has a similar socket API), + * - Kconfig and devicetree configuration options (net config library + * extension, subsystem-wide MAC and PHY Kconfig/DT options, driver/vendor + * specific Kconfig/DT options, watch out for options prefixed with + * IEEE802154/ieee802154), + * - Network Management: runtime configuration of the IEEE 802.15.4 + * protocols stack at the MAC (L2) and PHY (L1) levels + * (see @ref ieee802154_mgmt), + * - L2 integration (subsystem contributors): + * - see @ref ieee802154_l2 + * - implementation of Zephyr's internal L2-level socket and network context + * abstractions (context/socket operations, see @ref net_l2), + * - protocol-specific extension to the interface structure (see @ref net_if) + * - protocol-specific extensions to the network packet structure + * (see @ref net_pkt), + * + * - OpenThread and native IEEE 802.15.4 share a common **driver API** (driver + * maintainers/contributors): + * - see @ref ieee802154_driver + * - a basic, mostly PHY-level driver API to be implemented by all drivers, + * - several "hard MAC" (hardware/firmware offloading) extension points for + * performance critical or timing sensitive aspects of the protocol + */ + +/** + * @defgroup ieee802154_l2 IEEE 802.15.4 L2 + * @ingroup ieee802154 + * + * @brief IEEE 802.15.4 L2 APIs + * + * @details This API provides integration with Zephyr's sockets and network + * contexts. **Application and driver developers should never interface directly + * with this API.** It is of interest to subsystem maintainers only. + * + * The API implements and extends the following structures: + * - implements Zephyr's internal L2-level socket and network context + * abstractions (context/socket operations, see @ref net_l2), + * - protocol-specific extension to the interface structure (see @ref net_if) + * - protocol-specific extensions to the network packet structure + * (see @ref net_pkt), + * + * @note All section, table and figure references are to the IEEE 802.15.4-2020 + * standard. + * * @{ */ -/* References are to the IEEE 802.15.4-2020 standard */ -#define IEEE802154_MAX_PHY_PACKET_SIZE 127 /* see section 11.3, aMaxPhyPacketSize */ -#define IEEE802154_FCS_LENGTH 2 /* see section 7.2.1.1 */ +/** + * @brief Represents the PHY constant aMaxPhyPacketSize, see section 11.3. + * + * @note Currently only 127 byte sized packets are supported although some PHYs + * (e.g. SUN, MSK, LECIM, ...) support larger packet sizes. Needs to be changed + * once those PHYs should be fully supported. + */ +#define IEEE802154_MAX_PHY_PACKET_SIZE 127 + +/** + * @brief Represents the frame check sequence length, see section 7.2.1.1. + * + * @note Currently only a 2 byte FCS is supported although some PHYs (e.g. SUN, + * TVWS, ...) optionally support a 4 byte FCS. Needs to be changed once those + * PHYs should be fully supported. + */ +#define IEEE802154_FCS_LENGTH 2 + +/** + * @brief IEEE 802.15.4 "hardware" MTU (not to be confused with L3/IP MTU), i.e. + * the actual payload available to the next higher layer. + * + * @details This is equivalent to the IEEE 802.15.4 MAC frame length minus + * checksum bytes which is again equivalent to the PHY payload aka PSDU length + * minus checksum bytes. This definition exists for compatibility with the same + * concept in Linux and Zephyr's L3. It is not a concept from the IEEE 802.15.4 + * standard. + * + * @note Currently only the original frame size from the 2006 standard version + * and earlier is supported. The 2015+ standard introduced PHYs with larger PHY + * payload. These are not (yet) supported in Zephyr. + */ #define IEEE802154_MTU (IEEE802154_MAX_PHY_PACKET_SIZE - IEEE802154_FCS_LENGTH) + /* TODO: Support flexible MTU and FCS lengths for IEEE 802.15.4-2015ff */ +/** IEEE 802.15.4 short address length. */ #define IEEE802154_SHORT_ADDR_LENGTH 2 + +/** IEEE 802.15.4 extended address length. */ #define IEEE802154_EXT_ADDR_LENGTH 8 + +/** IEEE 802.15.4 maximum address length. */ #define IEEE802154_MAX_ADDR_LENGTH IEEE802154_EXT_ADDR_LENGTH +/** + * A special channel value that symbolizes "all" channels or "any" channel - + * depending on context. + */ #define IEEE802154_NO_CHANNEL USHRT_MAX -/* See IEEE 802.15.4-2020, sections 6.1 and 7.3.5 */ +/** + * Represents the IEEE 802.15.4 broadcast short address, see sections 6.1 and + * 8.4.3, table 8-94, macShortAddress. + */ #define IEEE802154_BROADCAST_ADDRESS 0xffff + +/** + * Represents a special IEEE 802.15.4 short address that indicates that a device + * has been associated with a coordinator but did not receive a short address, + * see sections 6.4.1 and 8.4.3, table 8-94, macShortAddress. + */ #define IEEE802154_NO_SHORT_ADDRESS_ASSIGNED 0xfffe -/* See IEEE 802.15.4-2020, section 6.1 */ +/** Represents the IEEE 802.15.4 broadcast PAN ID, see section 6.1. */ #define IEEE802154_BROADCAST_PAN_ID 0xffff -/* See IEEE 802.15.4-2020, section 7.3.5 */ +/** + * Represents a special value of the macShortAddress MAC PIB attribute, while the + * device is not associated, see section 8.4.3, table 8-94. + */ #define IEEE802154_SHORT_ADDRESS_NOT_ASSOCIATED IEEE802154_BROADCAST_ADDRESS -#define IEEE802154_PAN_ID_NOT_ASSOCIATED IEEE802154_BROADCAST_PAN_ID -/* MAC PIB attribute aUnitBackoffPeriod, see section 8.4.2, table 8-93, in symbol periods, valid for - * all PHYs except SUN PHY in the 920 MHz band. +/** + * Represents a special value of the macPanId MAC PIB attribute, while the + * device is not associated, see section 8.4.3, table 8-94. */ -#define IEEE802154_A_UNIT_BACKOFF_PERIOD(turnaround_time) \ - (turnaround_time + IEEE802154_PHY_A_CCA_TIME) -#define IEEE802154_A_UNIT_BACKOFF_PERIOD_US(turnaround_time, symbol_period) \ - (IEEE802154_A_UNIT_BACKOFF_PERIOD(turnaround_time) * symbol_period) +#define IEEE802154_PAN_ID_NOT_ASSOCIATED IEEE802154_BROADCAST_PAN_ID +/** Interface-level security attributes, see section 9.5. */ struct ieee802154_security_ctx { + /** + * Interface-level outgoing frame counter, section 9.5, table 9-8, + * secFrameCounter. + * + * Only used when the driver does not implement key-specific frame + * counters. + */ uint32_t frame_counter; + + /** @cond INTERNAL_HIDDEN */ struct cipher_ctx enc; struct cipher_ctx dec; + /** INTERNAL_HIDDEN @endcond */ + + /** + * @brief Interface-level frame encryption security key material + * + * @details Currently native L2 only supports a single secKeySource, see + * section 9.5, table 9-9, in combination with secKeyMode zero (implicit + * key mode), see section 9.4.2.3, table 9-7. + * + * @warning This is no longer in accordance with the 2015+ versions of + * the standard and needs to be extended in the future for full security + * procedure compliance. + */ uint8_t key[16]; + + /** Length in bytes of the interface-level security key material. */ uint8_t key_len; + + /** + * @brief Frame security level, possible values are defined in section + * 9.4.2.2, table 9-6. + * + * @warning Currently native L2 allows to configure one common security + * level for all frame types, commands and information elements. This is + * no longer in accordance with the 2015+ versions of the standard and + * needs to be extended in the future for full security procedure + * compliance. + */ uint8_t level : 3; + + /** + * @brief Frame security key mode + * + * @details Currently only implicit key mode is partially supported, see + * section 9.4.2.3, table 9-7, secKeyMode. + * + * @warning This is no longer in accordance with the 2015+ versions of + * the standard and needs to be extended in the future for full security + * procedure compliance. + */ uint8_t key_mode : 2; + + /** @cond INTERNAL_HIDDEN */ uint8_t _unused : 3; + /** INTERNAL_HIDDEN @endcond */ }; enum ieee802154_device_role { @@ -77,63 +243,77 @@ enum ieee802154_device_role { IEEE802154_DEVICE_ROLE_PAN_COORDINATOR, }; -/* This not meant to be used by any code but the IEEE 802.15.4 L2 stack */ +/** IEEE 802.15.4 L2 context. */ struct ieee802154_context { - /* PAN ID + /** + * @brief PAN ID * - * The identifier of the PAN on which the device is operating. If this - * value is 0xffff, the device is not associated. See section 8.4.3.1, - * table 8-94, macPanId. + * @details The identifier of the PAN on which the device is operating. + * If this value is 0xffff, the device is not associated. See section + * 8.4.3.1, table 8-94, macPanId. * * in CPU byte order */ uint16_t pan_id; - /* Channel Number + /** + * @brief Channel Number * - * The RF channel to use for all transmissions and receptions, see - * section 11.3, table 11-2, phyCurrentChannel. The allowable range + * @details The RF channel to use for all transmissions and receptions, + * see section 11.3, table 11-2, phyCurrentChannel. The allowable range * of values is PHY dependent as defined in section 10.1.3. * * in CPU byte order */ uint16_t channel; - /* Short Address + /** + * @brief Short Address (in CPU byte order) * - * Range: + * @details Range: * * 0x0000–0xfffd: associated, short address was assigned * * 0xfffe: associated but no short address assigned * * 0xffff: not associated (default), * * See section 6.4.1, table 6-4 (Usage of the shart address) and * section 8.4.3.1, table 8-94, macShortAddress. - * - * in CPU byte order */ uint16_t short_addr; - /* Extended Address + /** + * @brief Extended Address (in little endian) * - * The extended address is device specific, usually permanently stored - * on the device and immutable. + * @details The extended address is device specific, usually permanently + * stored on the device and immutable. * * See section 8.4.3.1, table 8-94, macExtendedAddress. - * - * in little endian */ uint8_t ext_addr[IEEE802154_MAX_ADDR_LENGTH]; - struct net_linkaddr_storage linkaddr; /* in big endian */ + /** Link layer address (in big endian) */ + struct net_linkaddr_storage linkaddr; + #ifdef CONFIG_NET_L2_IEEE802154_SECURITY + /** Security context */ struct ieee802154_security_ctx sec_ctx; #endif + #ifdef CONFIG_NET_L2_IEEE802154_MGMT - struct ieee802154_req_params *scan_ctx; /* guarded by scan_ctx_lock */ + /** Pointer to scanning parameters and results, guarded by scan_ctx_lock */ + struct ieee802154_req_params *scan_ctx; + + /** + * Used to maintain integrity of data for all fields in this struct + * unless otherwise documented on field level. + */ struct k_sem scan_ctx_lock; - /* see section 8.4.3.1, table 8-94, macCoordExtendedAddress, the address - * of the coordinator through which the device is associated. + /** + * @brief Coordinator extended address + * + * @details see section 8.4.3.1, table 8-94, macCoordExtendedAddress, + * the address of the coordinator through which the device is + * associated. * * A value of zero indicates that a coordinator extended address is * unknown (default). @@ -142,8 +322,11 @@ struct ieee802154_context { */ uint8_t coord_ext_addr[IEEE802154_MAX_ADDR_LENGTH]; - /* see section 8.4.3.1, table 8-94, macCoordShortAddress, the short - * address assigned to the coordinator through which the device is + /** + * @brief Coordinator short address + * + * @details see section 8.4.3.1, table 8-94, macCoordShortAddress, the + * short address assigned to the coordinator through which the device is * associated. * * A value of 0xfffe indicates that the coordinator is only using its @@ -154,36 +337,66 @@ struct ieee802154_context { */ uint16_t coord_short_addr; #endif + + /** Transmission power in dBm. */ int16_t tx_power; + + /** L2 flags */ enum net_l2_flags flags; - /* The sequence number added to the transmitted Data frame or MAC - * command, see section 8.4.3.1, table 8-94, macDsn. + /** + * @brief Data sequence number + * + * @details The sequence number added to the transmitted Data frame or + * MAC command, see section 8.4.3.1, table 8-94, macDsn. */ uint8_t sequence; - /* See section 6.1: A device may be operating as end device - * (0 - default), coordinator (1), or PAN coordinator (2). + /** + * @brief Device Role + * + * @details See section 6.1: A device may be operating as end device + * (0), coordinator (1), or PAN coordinator (2). If no device role is + * explicitly configured then the device will be treated as an end + * device. * * A value of 3 is undefined. * - * Can be read/set via enum ieee802154_device_role. + * Can be read/set via @ref ieee802154_device_role. */ uint8_t device_role : 2; + /** @cond INTERNAL_HIDDEN */ uint8_t _unused : 5; + /** INTERNAL_HIDDEN @endcond */ + + /** + * ACK requested flag, guarded by ack_lock + */ + uint8_t ack_requested: 1; + + /** ACK expected sequence number, guarded by ack_lock */ + uint8_t ack_seq; - uint8_t ack_requested : 1; /* guarded by ack_lock */ - uint8_t ack_seq; /* guarded by ack_lock */ + /** ACK lock, guards ack_* fields */ struct k_sem ack_lock; - struct k_sem ctx_lock; /* guards all mutable context attributes unless - * otherwise mentioned on attribute level - */ + /** + * @brief Context lock + * + * @details This lock guards all mutable context attributes unless + * otherwise mentioned on attribute level. + */ + struct k_sem ctx_lock; }; +/** @cond INTERNAL_HIDDEN */ + +/* L2 context type to be used with NET_L2_GET_CTX_TYPE */ #define IEEE802154_L2_CTX_TYPE struct ieee802154_context +/** INTERNAL_HIDDEN @endcond */ + #ifdef __cplusplus } #endif diff --git a/include/zephyr/net/ieee802154_ie.h b/include/zephyr/net/ieee802154_ie.h new file mode 100644 index 00000000000..0be4c1576e5 --- /dev/null +++ b/include/zephyr/net/ieee802154_ie.h @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2023 Florian Grandel, Zephyr Project. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief IEEE 802.15.4 MAC information element (IE) related types and helpers + * + * This is not to be included by the application. This file contains only those + * parts of the types required for IE support that need to be visible to IEEE + * 802.15.4 drivers and L2 at the same time, i.e. everything related to header + * IE representation, parsing and generation. + * + * All specification references in this file refer to IEEE 802.15.4-2020. + * + * @note All structs and attributes in this file that directly represent parts + * of IEEE 802.15.4 frames are in LITTLE ENDIAN, see section 4, especially + * section 4.3. + */ + +#ifndef ZEPHYR_INCLUDE_NET_IEEE802154_IE_H_ +#define ZEPHYR_INCLUDE_NET_IEEE802154_IE_H_ + +#include +#include + +/** + * @addtogroup ieee802154_driver + * @{ + * + * @name IEEE 802.15.4, section 7.4.2: MAC header information elements + * @{ + */ + +/** + * @brief Information Element Types. + * + * @details See sections 7.4.2.1 and 7.4.3.1. + */ +enum ieee802154_ie_type { + IEEE802154_IE_TYPE_HEADER = 0x0, + IEEE802154_IE_TYPE_PAYLOAD, +}; + +/** + * @brief Header Information Element IDs. + * + * @details See section 7.4.2.1, table 7-7, partial list, only IEs actually used + * are implemented. + */ +enum ieee802154_header_ie_element_id { + IEEE802154_HEADER_IE_ELEMENT_ID_VENDOR_SPECIFIC_IE = 0x00, + IEEE802154_HEADER_IE_ELEMENT_ID_CSL_IE = 0x1a, + IEEE802154_HEADER_IE_ELEMENT_ID_RIT_IE = 0x1b, + IEEE802154_HEADER_IE_ELEMENT_ID_RENDEZVOUS_TIME_IE = 0x1d, + IEEE802154_HEADER_IE_ELEMENT_ID_TIME_CORRECTION_IE = 0x1e, + IEEE802154_HEADER_IE_ELEMENT_ID_HEADER_TERMINATION_1 = 0x7e, + IEEE802154_HEADER_IE_ELEMENT_ID_HEADER_TERMINATION_2 = 0x7f, + /* partial list, add additional ids as needed */ +}; + +/** @cond INTERNAL_HIDDEN */ +#define IEEE802154_VENDOR_SPECIFIC_IE_OUI_LEN 3 +/** INTERNAL_HIDDEN @endcond */ + +/** @brief Vendor Specific Header IE, see section 7.4.2.3. */ +struct ieee802154_header_ie_vendor_specific { + uint8_t vendor_oui[IEEE802154_VENDOR_SPECIFIC_IE_OUI_LEN]; + uint8_t *vendor_specific_info; +} __packed; + +/** @brief Full CSL IE, see section 7.4.2.3. */ +struct ieee802154_header_ie_csl_full { + uint16_t csl_phase; + uint16_t csl_period; + uint16_t csl_rendezvous_time; +} __packed; + +/** @brief Reduced CSL IE, see section 7.4.2.3. */ +struct ieee802154_header_ie_csl_reduced { + uint16_t csl_phase; + uint16_t csl_period; +} __packed; + +/** @brief Generic CSL IE, see section 7.4.2.3. */ +struct ieee802154_header_ie_csl { + union { + struct ieee802154_header_ie_csl_full full; + struct ieee802154_header_ie_csl_reduced reduced; + }; +} __packed; + +/** @brief RIT IE, see section 7.4.2.4. */ +struct ieee802154_header_ie_rit { + uint8_t time_to_first_listen; + uint8_t number_of_repeat_listen; + uint16_t repeat_listen_interval; +} __packed; + +/** + * @brief Full Rendezvous Time IE, see section 7.4.2.6 + * (macCslInterval is nonzero). + */ +struct ieee802154_header_ie_rendezvous_time_full { + uint16_t rendezvous_time; + uint16_t wakeup_interval; +} __packed; + +/** + * @brief Reduced Rendezvous Time IE, see section 7.4.2.6 + * (macCslInterval is zero). + */ +struct ieee802154_header_ie_rendezvous_time_reduced { + uint16_t rendezvous_time; +} __packed; + +/** @brief Rendezvous Time IE, see section 7.4.2.6. */ +struct ieee802154_header_ie_rendezvous_time { + union { + struct ieee802154_header_ie_rendezvous_time_full full; + struct ieee802154_header_ie_rendezvous_time_reduced reduced; + }; +} __packed; + +/** @brief Time Correction IE, see section 7.4.2.7. */ +struct ieee802154_header_ie_time_correction { + uint16_t time_sync_info; +} __packed; + +/* @brief Generic Header IE, see section 7.4.2.1. */ +struct ieee802154_header_ie { +#if CONFIG_LITTLE_ENDIAN + uint16_t length : 7; + uint16_t element_id_low : 1; /* see enum ieee802154_header_ie_element_id */ + uint16_t element_id_high : 7; + uint16_t type : 1; /* always 0 */ +#else + uint16_t element_id_low : 1; /* see enum ieee802154_header_ie_element_id */ + uint16_t length : 7; + uint16_t type : 1; /* always 0 */ + uint16_t element_id_high : 7; +#endif + union { + struct ieee802154_header_ie_vendor_specific vendor_specific; + struct ieee802154_header_ie_csl csl; + struct ieee802154_header_ie_rit rit; + struct ieee802154_header_ie_rendezvous_time rendezvous_time; + struct ieee802154_header_ie_time_correction time_correction; + /* add additional supported header IEs here */ + } content; +} __packed; + +/** @brief The header IE's header length (2 bytes). */ +#define IEEE802154_HEADER_IE_HEADER_LENGTH sizeof(uint16_t) + + +/** @cond INTERNAL_HIDDEN */ +#define IEEE802154_DEFINE_HEADER_IE(_element_id, _length, _content, _content_type) \ + (struct ieee802154_header_ie) { \ + .length = (_length), \ + .element_id_high = (_element_id) >> 1U, .element_id_low = (_element_id) & 0x01, \ + .type = IEEE802154_IE_TYPE_HEADER, \ + .content._content_type = _content, \ + } + +#define IEEE802154_DEFINE_HEADER_IE_VENDOR_SPECIFIC_CONTENT_LEN(_vendor_specific_info_len) \ + (IEEE802154_VENDOR_SPECIFIC_IE_OUI_LEN + (_vendor_specific_info_len)) + +#define IEEE802154_DEFINE_HEADER_IE_VENDOR_SPECIFIC_CONTENT(_vendor_oui, _vendor_specific_info) \ + (struct ieee802154_header_ie_vendor_specific) { \ + .vendor_oui = _vendor_oui, .vendor_specific_info = (_vendor_specific_info), \ + } + +#define IEEE802154_DEFINE_HEADER_IE_CSL_REDUCED_CONTENT(_csl_phase, _csl_period) \ + (struct ieee802154_header_ie_csl_reduced) { \ + .csl_phase = sys_cpu_to_le16(_csl_phase), \ + .csl_period = sys_cpu_to_le16(_csl_period), \ + } + +#define IEEE802154_DEFINE_HEADER_IE_CSL_FULL_CONTENT(_csl_phase, _csl_period, \ + _csl_rendezvous_time) \ + (struct ieee802154_header_ie_csl_full) { \ + .csl_phase = sys_cpu_to_le16(_csl_phase), \ + .csl_period = sys_cpu_to_le16(_csl_period), \ + .csl_rendezvous_time = sys_cpu_to_le16(_csl_rendezvous_time), \ + } + +#define IEEE802154_HEADER_IE_TIME_CORRECTION_NACK 0x8000 +#define IEEE802154_HEADER_IE_TIME_CORRECTION_MASK 0x0fff +#define IEEE802154_HEADER_IE_TIME_CORRECTION_SIGN_BIT_MASK 0x0800 + +#define IEEE802154_DEFINE_HEADER_IE_TIME_CORRECTION_CONTENT(_ack, _time_correction_us) \ + (struct ieee802154_header_ie_time_correction) { \ + .time_sync_info = sys_cpu_to_le16( \ + (!(_ack) * IEEE802154_HEADER_IE_TIME_CORRECTION_NACK) | \ + ((_time_correction_us) & IEEE802154_HEADER_IE_TIME_CORRECTION_MASK)), \ + } +/** INTERNAL_HIDDEN @endcond */ + +/** + * @brief Define a vendor specific header IE, see section 7.4.2.3. + * + * @details Example usage (all parameters in little endian): + * + * @code{.c} + * uint8_t vendor_specific_info[] = {...some vendor specific IE content...}; + * struct ieee802154_header_ie header_ie = IEEE802154_DEFINE_HEADER_IE_VENDOR_SPECIFIC( + * {0x9b, 0xb8, 0xea}, vendor_specific_info, sizeof(vendor_specific_info)); + * @endcode + * + * @param _vendor_oui an initializer for a 3 byte vendor oui array in little + * endian + * @param _vendor_specific_info pointer to a variable length uint8_t array with + * the vendor specific IE content + * @param _vendor_specific_info_len the length of the vendor specific IE content + * (in bytes) + */ +#define IEEE802154_DEFINE_HEADER_IE_VENDOR_SPECIFIC(_vendor_oui, _vendor_specific_info, \ + _vendor_specific_info_len) \ + IEEE802154_DEFINE_HEADER_IE(IEEE802154_HEADER_IE_ELEMENT_ID_VENDOR_SPECIFIC_IE, \ + IEEE802154_DEFINE_HEADER_IE_VENDOR_SPECIFIC_CONTENT_LEN( \ + _vendor_specific_info_len), \ + IEEE802154_DEFINE_HEADER_IE_VENDOR_SPECIFIC_CONTENT( \ + _vendor_oui, _vendor_specific_info), \ + vendor_specific) + +/** + * @brief Define a reduced CSL IE, see section 7.4.2.3. + * + * @details Example usage (all parameters in CPU byte order): + * + * @code{.c} + * uint16_t csl_phase = ...; + * uint16_t csl_period = ...; + * struct ieee802154_header_ie header_ie = + * IEEE802154_DEFINE_HEADER_IE_CSL_REDUCED(csl_phase, csl_period); + * @endcode + * + * @param _csl_phase CSL phase in CPU byte order + * @param _csl_period CSL period in CPU byte order + */ +#define IEEE802154_DEFINE_HEADER_IE_CSL_REDUCED(_csl_phase, _csl_period) \ + IEEE802154_DEFINE_HEADER_IE( \ + IEEE802154_HEADER_IE_ELEMENT_ID_CSL_IE, \ + sizeof(struct ieee802154_header_ie_csl_reduced), \ + IEEE802154_DEFINE_HEADER_IE_CSL_REDUCED_CONTENT(_csl_phase, _csl_period), \ + csl.reduced) + +/** + * @brief Define a full CSL IE, see section 7.4.2.3. + * + * @details Example usage (all parameters in CPU byte order): + * + * @code{.c} + * uint16_t csl_phase = ...; + * uint16_t csl_period = ...; + * uint16_t csl_rendezvous_time = ...; + * struct ieee802154_header_ie header_ie = + * IEEE802154_DEFINE_HEADER_IE_CSL_REDUCED(csl_phase, csl_period, csl_rendezvous_time); + * @endcode + * + * @param _csl_phase CSL phase in CPU byte order + * @param _csl_period CSL period in CPU byte order + * @param _csl_rendezvous_time CSL rendezvous time in CPU byte order + */ +#define IEEE802154_DEFINE_HEADER_IE_CSL_FULL(_csl_phase, _csl_period, _csl_rendezvous_time) \ + IEEE802154_DEFINE_HEADER_IE(IEEE802154_HEADER_IE_ELEMENT_ID_CSL_IE, \ + sizeof(struct ieee802154_header_ie_csl_full), \ + IEEE802154_DEFINE_HEADER_IE_CSL_FULL_CONTENT( \ + _csl_phase, _csl_period, _csl_rendezvous_time), \ + csl.full) + +/** + * @brief Define a Time Correction IE, see section 7.4.2.7. + * + * @details Example usage (parameter in CPU byte order): + * + * @code{.c} + * uint16_t time_sync_info = ...; + * struct ieee802154_header_ie header_ie = + * IEEE802154_DEFINE_HEADER_IE_TIME_CORRECTION(true, time_sync_info); + * @endcode + * + * @param _ack whether or not the enhanced ACK frame that receives this IE is an + * ACK (true) or NACK (false) + * @param _time_correction_us the positive or negative deviation from expected + * RX time in microseconds + */ +#define IEEE802154_DEFINE_HEADER_IE_TIME_CORRECTION(_ack, _time_correction_us) \ + IEEE802154_DEFINE_HEADER_IE( \ + IEEE802154_HEADER_IE_ELEMENT_ID_TIME_CORRECTION_IE, \ + sizeof(struct ieee802154_header_ie_time_correction), \ + IEEE802154_DEFINE_HEADER_IE_TIME_CORRECTION_CONTENT(_ack, _time_correction_us), \ + time_correction) + +/** + * @brief Retrieve the time correction value in microseconds from a Time Correction IE, + * see section 7.4.2.7. + * + * @param[in] ie pointer to the Time Correction IE structure + * + * @return The time correction value in microseconds. + */ +static inline int16_t +ieee802154_header_ie_get_time_correction_us(struct ieee802154_header_ie_time_correction *ie) +{ + if (ie->time_sync_info & IEEE802154_HEADER_IE_TIME_CORRECTION_SIGN_BIT_MASK) { + /* Negative integer */ + return (int16_t)ie->time_sync_info | ~IEEE802154_HEADER_IE_TIME_CORRECTION_MASK; + } + + /* Positive integer */ + return (int16_t)ie->time_sync_info & IEEE802154_HEADER_IE_TIME_CORRECTION_MASK; +} + +/** + * @brief Set the element ID of a header IE. + * + * @param[in] ie pointer to a header IE + * @param[in] element_id IE element id in CPU byte order + */ +static inline void ieee802154_header_ie_set_element_id(struct ieee802154_header_ie *ie, + uint8_t element_id) +{ + ie->element_id_high = element_id >> 1U; + ie->element_id_low = element_id & 0x01; +} + +/** + * @brief Get the element ID of a header IE. + * + * @param[in] ie pointer to a header IE + * + * @return header IE element id in CPU byte order + */ +static inline uint8_t ieee802154_header_ie_get_element_id(struct ieee802154_header_ie *ie) +{ + return (ie->element_id_high << 1U) | ie->element_id_low; +} + +/** @brief The length in bytes of a "Time Correction" header IE. */ +#define IEEE802154_TIME_CORRECTION_HEADER_IE_LEN \ + (IEEE802154_HEADER_IE_HEADER_LENGTH + sizeof(struct ieee802154_header_ie_time_correction)) + +/** @brief The length in bytes of a "Header Termination 1" header IE. */ +#define IEEE802154_HEADER_TERMINATION_1_HEADER_IE_LEN IEEE802154_HEADER_IE_HEADER_LENGTH + +/** + * @} + * + * @} + */ + +#endif /* ZEPHYR_INCLUDE_NET_IEEE802154_IE_H_ */ diff --git a/include/zephyr/net/ieee802154_mgmt.h b/include/zephyr/net/ieee802154_mgmt.h index 07aa688232f..3711e818d24 100644 --- a/include/zephyr/net/ieee802154_mgmt.h +++ b/include/zephyr/net/ieee802154_mgmt.h @@ -8,7 +8,7 @@ * @file * @brief IEEE 802.15.4 Management interface public header * - * All references to the standard in this file cite IEEE 802.15.4-2020. + * @note All references to the standard in this file cite IEEE 802.15.4-2020. */ #ifndef ZEPHYR_INCLUDE_NET_IEEE802154_MGMT_H_ @@ -22,12 +22,26 @@ extern "C" { #endif /** + * @defgroup ieee802154_mgmt IEEE 802.15.4 Net Management + * @ingroup ieee802154 + * * @brief IEEE 802.15.4 net management library - * @defgroup ieee802154_mgmt IEEE 802.15.4 Net Management Library - * @ingroup networking + * + * @details The IEEE 802.15.4 net management library provides runtime + * configuration features that applications can interface with directly. + * + * Most of these commands are also accessible via shell commands. See the + * shell's help feature (`shell> ieee802154 help`). + * + * @note All section, table and figure references are to the IEEE 802.15.4-2020 + * standard. + * * @{ */ +/** + * @cond INTERNAL_HIDDEN + */ #define _NET_IEEE802154_LAYER NET_MGMT_LAYER_L2 #define _NET_IEEE802154_CODE 0x154 @@ -36,186 +50,256 @@ extern "C" { NET_MGMT_LAYER_CODE(_NET_IEEE802154_CODE)) #define _NET_IEEE802154_EVENT (_NET_IEEE802154_BASE | NET_MGMT_EVENT_BIT) -/* All attributes and parameters are given in CPU byte order - * (scalars) or big endian (byte arrays) unless otherwise - * specified. +enum net_request_ieee802154_cmd { + NET_REQUEST_IEEE802154_CMD_SET_ACK = 1, + NET_REQUEST_IEEE802154_CMD_UNSET_ACK, + NET_REQUEST_IEEE802154_CMD_PASSIVE_SCAN, + NET_REQUEST_IEEE802154_CMD_ACTIVE_SCAN, + NET_REQUEST_IEEE802154_CMD_CANCEL_SCAN, + NET_REQUEST_IEEE802154_CMD_ASSOCIATE, + NET_REQUEST_IEEE802154_CMD_DISASSOCIATE, + NET_REQUEST_IEEE802154_CMD_SET_CHANNEL, + NET_REQUEST_IEEE802154_CMD_GET_CHANNEL, + NET_REQUEST_IEEE802154_CMD_SET_PAN_ID, + NET_REQUEST_IEEE802154_CMD_GET_PAN_ID, + NET_REQUEST_IEEE802154_CMD_SET_EXT_ADDR, + NET_REQUEST_IEEE802154_CMD_GET_EXT_ADDR, + NET_REQUEST_IEEE802154_CMD_SET_SHORT_ADDR, + NET_REQUEST_IEEE802154_CMD_GET_SHORT_ADDR, + NET_REQUEST_IEEE802154_CMD_GET_TX_POWER, + NET_REQUEST_IEEE802154_CMD_SET_TX_POWER, + NET_REQUEST_IEEE802154_CMD_SET_SECURITY_SETTINGS, + NET_REQUEST_IEEE802154_CMD_GET_SECURITY_SETTINGS, +}; + +/** + * INTERNAL_HIDDEN @endcond + */ + +/** + * @name Command Macros + * + * @brief IEEE 802.15.4 net management commands. + * + * @details These IEEE 802.15.4 subsystem net management commands can be called + * by applications via @ref net_mgmt macro. + * + * All attributes and parameters are given in CPU byte order (scalars) or big + * endian (byte arrays) unless otherwise specified. * - * The following IEEE 802.15.4 MAC management service primitives - * are referenced below: + * The following IEEE 802.15.4 MAC management service primitives are referenced + * in this enumeration: * - MLME-ASSOCIATE.request, see section 8.2.3 * - MLME-DISASSOCIATE.request, see section 8.2.4 * - MLME-SET/GET.request, see section 8.2.6 * - MLME-SCAN.request, see section 8.2.11 * - * The following IEEE 802.15.4 MAC data service primitives - * are referenced below: + * The following IEEE 802.15.4 MAC data service primitives are referenced in + * this enumeration: * - MLME-DATA.request, see section 8.3.2 * * MAC PIB attributes (mac.../sec...): see sections 8.4.3 and 9.5. * PHY PIB attributes (phy...): see section 11.3. * Both are accessed through MLME-SET/GET primitives. + * + * @{ */ -enum net_request_ieee802154_cmd { - NET_REQUEST_IEEE802154_CMD_SET_ACK = 1, /* sets AckTx for all subsequent - * MLME-DATA (aka TX) requests - */ - NET_REQUEST_IEEE802154_CMD_UNSET_ACK, /* unsets AckTx for all subsequent - * MLME-DATA requests - */ - NET_REQUEST_IEEE802154_CMD_PASSIVE_SCAN, /* MLME-SCAN(PASSIVE, ...) request */ - NET_REQUEST_IEEE802154_CMD_ACTIVE_SCAN, /* MLME-SCAN(ACTIVE, ...) request */ - NET_REQUEST_IEEE802154_CMD_CANCEL_SCAN, /* not-standard */ - NET_REQUEST_IEEE802154_CMD_ASSOCIATE, /* MLME-ASSOCIATE(...) request */ - NET_REQUEST_IEEE802154_CMD_DISASSOCIATE, /* MLME-DISASSOCIATE(...) request */ - NET_REQUEST_IEEE802154_CMD_SET_CHANNEL, /* MLME-SET(phyCurrentChannel) request */ - NET_REQUEST_IEEE802154_CMD_GET_CHANNEL, /* MLME-GET(phyCurrentChannel) request */ - NET_REQUEST_IEEE802154_CMD_SET_PAN_ID, /* MLME-SET(macPanId) request */ - NET_REQUEST_IEEE802154_CMD_GET_PAN_ID, /* MLME-GET(macPanId) request */ - NET_REQUEST_IEEE802154_CMD_SET_EXT_ADDR, /* non-standard, see chapters 7.1 and 8.4.3.1, in - * big endian byte order - */ - NET_REQUEST_IEEE802154_CMD_GET_EXT_ADDR, /* like MLME-GET(macExtendedAddress) but in big - * endian byte order - */ - NET_REQUEST_IEEE802154_CMD_SET_SHORT_ADDR, /* MLME-SET(macShortAddress) request, only - * allowed for co-ordinators - */ - NET_REQUEST_IEEE802154_CMD_GET_SHORT_ADDR, /* MLME-GET(macShortAddress) request */ - NET_REQUEST_IEEE802154_CMD_GET_TX_POWER, /* MLME-SET(phyUnicastTxPower/phyBroadcastTxPower) - * request (currently not distinguished) - */ - NET_REQUEST_IEEE802154_CMD_SET_TX_POWER, /* MLME-GET(phyUnicastTxPower/phyBroadcastTxPower) - * request - */ - - NET_REQUEST_IEEE802154_CMD_SET_SECURITY_SETTINGS, /* implies macSecurityEnabled=true, - * configures basic sec* MAC PIB - * attributes - */ - NET_REQUEST_IEEE802154_CMD_GET_SECURITY_SETTINGS, /* gets the configured sec* attributes */ -}; - -#define NET_REQUEST_IEEE802154_SET_ACK \ - (_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_SET_ACK) +/** Sets AckTx for all subsequent MLME-DATA (aka TX) requests. */ +#define NET_REQUEST_IEEE802154_SET_ACK (_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_SET_ACK) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_ACK); -#define NET_REQUEST_IEEE802154_UNSET_ACK \ +/** Unsets AckTx for all subsequent MLME-DATA requests. */ +#define NET_REQUEST_IEEE802154_UNSET_ACK \ (_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_UNSET_ACK) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_UNSET_ACK); -#define NET_REQUEST_IEEE802154_PASSIVE_SCAN \ +/** + * MLME-SCAN(PASSIVE, ...) request + * + * See @ref ieee802154_req_params for associated command parameters. + */ +#define NET_REQUEST_IEEE802154_PASSIVE_SCAN \ (_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_PASSIVE_SCAN) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_PASSIVE_SCAN); -#define NET_REQUEST_IEEE802154_ACTIVE_SCAN \ +/** + * MLME-SCAN(ACTIVE, ...) request + * + * See @ref ieee802154_req_params for associated command parameters. + */ +#define NET_REQUEST_IEEE802154_ACTIVE_SCAN \ (_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_ACTIVE_SCAN) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_ACTIVE_SCAN); -#define NET_REQUEST_IEEE802154_CANCEL_SCAN \ +/** Cancels an ongoing MLME-SCAN(...) command (non-standard). */ +#define NET_REQUEST_IEEE802154_CANCEL_SCAN \ (_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_CANCEL_SCAN) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_CANCEL_SCAN); -#define NET_REQUEST_IEEE802154_ASSOCIATE \ +/** MLME-ASSOCIATE(...) request */ +#define NET_REQUEST_IEEE802154_ASSOCIATE \ (_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_ASSOCIATE) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_ASSOCIATE); -#define NET_REQUEST_IEEE802154_DISASSOCIATE \ +/** MLME-DISASSOCIATE(...) request */ +#define NET_REQUEST_IEEE802154_DISASSOCIATE \ (_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_DISASSOCIATE) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_DISASSOCIATE); -#define NET_REQUEST_IEEE802154_SET_CHANNEL \ +/** MLME-SET(phyCurrentChannel) request */ +#define NET_REQUEST_IEEE802154_SET_CHANNEL \ (_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_SET_CHANNEL) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_CHANNEL); -#define NET_REQUEST_IEEE802154_GET_CHANNEL \ +/** MLME-GET(phyCurrentChannel) request */ +#define NET_REQUEST_IEEE802154_GET_CHANNEL \ (_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_GET_CHANNEL) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_CHANNEL); -#define NET_REQUEST_IEEE802154_SET_PAN_ID \ +/** MLME-SET(macPanId) request */ +#define NET_REQUEST_IEEE802154_SET_PAN_ID \ (_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_SET_PAN_ID) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_PAN_ID); -#define NET_REQUEST_IEEE802154_GET_PAN_ID \ +/** MLME-GET(macPanId) request */ +#define NET_REQUEST_IEEE802154_GET_PAN_ID \ (_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_GET_PAN_ID) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_PAN_ID); -#define NET_REQUEST_IEEE802154_SET_EXT_ADDR \ +/** + * Sets the extended interface address (non-standard), see sections 7.1 + * and 8.4.3.1, in big endian byte order + */ +#define NET_REQUEST_IEEE802154_SET_EXT_ADDR \ (_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_SET_EXT_ADDR) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_EXT_ADDR); -#define NET_REQUEST_IEEE802154_GET_EXT_ADDR \ +/** like MLME-GET(macExtendedAddress) but in big endian byte order */ +#define NET_REQUEST_IEEE802154_GET_EXT_ADDR \ (_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_GET_EXT_ADDR) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_EXT_ADDR); -#define NET_REQUEST_IEEE802154_SET_SHORT_ADDR \ +/** MLME-SET(macShortAddress) request, only allowed for co-ordinators */ +#define NET_REQUEST_IEEE802154_SET_SHORT_ADDR \ (_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_SET_SHORT_ADDR) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_SHORT_ADDR); -#define NET_REQUEST_IEEE802154_GET_SHORT_ADDR \ +/** MLME-GET(macShortAddress) request */ +#define NET_REQUEST_IEEE802154_GET_SHORT_ADDR \ (_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_GET_SHORT_ADDR) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_SHORT_ADDR); -#define NET_REQUEST_IEEE802154_GET_TX_POWER \ - (_NET_IEEE802154_BASE | \ - NET_REQUEST_IEEE802154_CMD_GET_TX_POWER) +/** + * MLME-SET(phyUnicastTxPower/phyBroadcastTxPower) request (currently + * not distinguished) + */ +#define NET_REQUEST_IEEE802154_GET_TX_POWER \ + (_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_GET_TX_POWER) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_TX_POWER); -#define NET_REQUEST_IEEE802154_SET_TX_POWER \ - (_NET_IEEE802154_BASE | \ - NET_REQUEST_IEEE802154_CMD_SET_TX_POWER) +/** MLME-GET(phyUnicastTxPower/phyBroadcastTxPower) request */ +#define NET_REQUEST_IEEE802154_SET_TX_POWER \ + (_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_SET_TX_POWER) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_TX_POWER); #ifdef CONFIG_NET_L2_IEEE802154_SECURITY -#define NET_REQUEST_IEEE802154_SET_SECURITY_SETTINGS \ - (_NET_IEEE802154_BASE | \ - NET_REQUEST_IEEE802154_CMD_SET_SECURITY_SETTINGS) +/** + * Configures basic sec* MAC PIB attributes, implies + * macSecurityEnabled=true. + * + * See @ref ieee802154_security_params for associated command parameters. + */ +#define NET_REQUEST_IEEE802154_SET_SECURITY_SETTINGS \ + (_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_SET_SECURITY_SETTINGS) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_SECURITY_SETTINGS); -#define NET_REQUEST_IEEE802154_GET_SECURITY_SETTINGS \ - (_NET_IEEE802154_BASE | \ - NET_REQUEST_IEEE802154_CMD_GET_SECURITY_SETTINGS) +/** + * Gets the configured sec* attributes. + * + * See @ref ieee802154_security_params for associated command parameters. + */ +#define NET_REQUEST_IEEE802154_GET_SECURITY_SETTINGS \ + (_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_GET_SECURITY_SETTINGS) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_SECURITY_SETTINGS); #endif /* CONFIG_NET_L2_IEEE802154_SECURITY */ +/** + * @} + */ + +/** + * @cond INTERNAL_HIDDEN + */ + enum net_event_ieee802154_cmd { NET_EVENT_IEEE802154_CMD_SCAN_RESULT = 1, }; +/** + * INTERNAL_HIDDEN @endcond + */ + +/** + * @name Event Macros + * + * @brief IEEE 802.15.4 net management events. + * + * @details These IEEE 802.15.4 subsystem net management events can be + * subscribed to by applications via @ref net_mgmt_init_event_callback, @ref + * net_mgmt_add_event_callback and @ref net_mgmt_del_event_callback. + * + * @{ + */ + +/** + * Signals the result of the @ref NET_REQUEST_IEEE802154_ACTIVE_SCAN or @ref + * NET_REQUEST_IEEE802154_PASSIVE_SCAN net management commands. + * + * See @ref ieee802154_req_params for associated event parameters. + */ #define NET_EVENT_IEEE802154_SCAN_RESULT \ (_NET_IEEE802154_EVENT | NET_EVENT_IEEE802154_CMD_SCAN_RESULT) +/** + * @} + */ + +/** + * @cond INTERNAL_HIDDEN + */ #define IEEE802154_IS_CHAN_SCANNED(_channel_set, _chan) \ (_channel_set & BIT(_chan - 1)) #define IEEE802154_IS_CHAN_UNSCANNED(_channel_set, _chan) \ (!IEEE802154_IS_CHAN_SCANNED(_channel_set, _chan)) -/* Useful define to request all 16 channels of channel page zero - * in the 2450 MHz band to be scanned, from 11 to 26 included. +#define IEEE802154_ALL_CHANNELS UINT32_MAX + +/** + * INTERNAL_HIDDEN @endcond */ -#define IEEE802154_ALL_CHANNELS (0x03FFFC00) /** * @brief Scanning parameters diff --git a/include/zephyr/net/ieee802154_pkt.h b/include/zephyr/net/ieee802154_pkt.h index a1dca472448..d5fdc712b49 100644 --- a/include/zephyr/net/ieee802154_pkt.h +++ b/include/zephyr/net/ieee802154_pkt.h @@ -68,7 +68,6 @@ struct net_pkt_cb_ieee802154 { }; /* Flags */ - uint8_t arb : 1; /* ACK Request Bit is set in the frame */ uint8_t ack_fpb : 1; /* Frame Pending Bit was set in the ACK */ uint8_t frame_secured : 1; /* Frame is authenticated and * encrypted according to its @@ -80,9 +79,6 @@ struct net_pkt_cb_ieee802154 { * e.g. Frame Counter injection. */ #if defined(CONFIG_NET_L2_OPENTHREAD) - uint8_t fv2015: 1; /* Frame version is IEEE 802.15.4 (0b10), - * see section 7.2.2.10, table 7-3. - */ uint8_t ack_seb : 1; /* Security Enabled Bit was set in the ACK */ #endif }; @@ -201,16 +197,6 @@ static inline void net_pkt_set_ieee802154_txpwr(struct net_pkt *pkt, int8_t txpw } #endif /* CONFIG_IEEE802154_SELECTIVE_TXPOWER */ -static inline bool net_pkt_ieee802154_arb(struct net_pkt *pkt) -{ - return net_pkt_cb_ieee802154(pkt)->arb; -} - -static inline void net_pkt_set_ieee802154_arb(struct net_pkt *pkt, bool arb) -{ - net_pkt_cb_ieee802154(pkt)->arb = arb; -} - static inline bool net_pkt_ieee802154_ack_fpb(struct net_pkt *pkt) { return net_pkt_cb_ieee802154(pkt)->ack_fpb; @@ -262,16 +248,6 @@ static inline void net_pkt_set_ieee802154_ack_keyid(struct net_pkt *pkt, uint8_t net_pkt_cb_ieee802154(pkt)->ack_keyid = keyid; } -static inline bool net_pkt_ieee802154_fv2015(struct net_pkt *pkt) -{ - return net_pkt_cb_ieee802154(pkt)->fv2015; -} - -static inline void net_pkt_set_ieee802154_fv2015(struct net_pkt *pkt, bool fv2015) -{ - net_pkt_cb_ieee802154(pkt)->fv2015 = fv2015; -} - static inline bool net_pkt_ieee802154_ack_seb(struct net_pkt *pkt) { return net_pkt_cb_ieee802154(pkt)->ack_seb; diff --git a/include/zephyr/net/ieee802154_radio.h b/include/zephyr/net/ieee802154_radio.h index 861523cbf6a..de0cf89da4c 100644 --- a/include/zephyr/net/ieee802154_radio.h +++ b/include/zephyr/net/ieee802154_radio.h @@ -1,14 +1,15 @@ /* * Copyright (c) 2016 Intel Corporation. + * Copyright (c) 2023 F. Grandel, Zephyr Project * * SPDX-License-Identifier: Apache-2.0 */ /** * @file - * @brief Public IEEE 802.15.4 Radio API + * @brief Public IEEE 802.15.4 Driver API * - * All references to the spec refer to IEEE 802.15.4-2020. + * @note All references to the standard in this file cite IEEE 802.15.4-2020. */ #ifndef ZEPHYR_INCLUDE_NET_IEEE802154_RADIO_H_ @@ -19,6 +20,7 @@ #include #include #include +#include #include #ifdef __cplusplus @@ -26,105 +28,421 @@ extern "C" { #endif /** - * @addtogroup ieee802154 + * @defgroup ieee802154_driver IEEE 802.15.4 Drivers + * @ingroup ieee802154 + * + * @brief IEEE 802.15.4 driver API + * + * @details This API provides a common representation of vendor-specific + * hardware and firmware to the native IEEE 802.15.4 L2 and OpenThread stacks. + * **Application developers should never interface directly with this API.** It + * is of interest to driver maintainers only. + * + * The IEEE 802.15.4 driver API consists of two separate parts: + * - a basic, mostly PHY-level driver API to be implemented by all drivers, + * - several optional MAC-level extension points to offload performance + * critical or timing sensitive aspects at MAC level to the driver hardware + * or firmware ("hard" MAC). + * + * Implementing the basic driver API will ensure integration with the native L2 + * stack as well as basic support for OpenThread. Depending on the hardware, + * offloading to vendor-specific hardware or firmware features may be required + * to achieve full compliance with the Thread protocol or IEEE 802.15.4 + * subprotocols (e.g. fast enough ACK packages, precise timing of timed TX/RX in + * the TSCH or CSL subprotocols). + * + * Whether or not MAC-level offloading extension points need to be implemented + * is to be decided by individual driver maintainers. Upper layers SHOULD + * provide a "soft" MAC fallback whenever possible. + * + * @note All section, table and figure references are to the IEEE 802.15.4-2020 + * standard. + * * @{ */ -/* See section 6.1: "Some of the timing parameters in definition of the MAC are in units of PHY - * symbols. For PHYs that have multiple symbol periods, the duration to be used for the MAC - * parameters is defined in that PHY clause." +/** + * @name IEEE 802.15.4-2020, Section 6: MAC functional description + * @{ */ -#define IEEE802154_PHY_SUN_FSK_863MHZ_915MHZ_SYMBOL_PERIOD_US 20U /* see section 19.1, table 19-1 */ -#define IEEE802154_PHY_OQPSK_2450MHZ_SYMBOL_PERIOD_US 16U /* see section 12.3.3 */ -/* TODO: Get PHY-specific symbol period from radio API. Requires an attribute getter, see - * https://github.com/zephyrproject-rtos/zephyr/issues/50336#issuecomment-1251122582. - * For now we assume PHYs that current drivers actually implement. +/** + * The symbol period (and therefore symbol rate) is defined in section 6.1: "Some + * of the timing parameters in definition of the MAC are in units of PHY symbols. + * For PHYs that have multiple symbol periods, the duration to be used for the + * MAC parameters is defined in that PHY clause." + * + * This is not necessarily the true physical symbol period, so take care to use + * this macro only when either the symbol period used for MAC timing is the same + * as the physical symbol period or if you actually mean the MAC timing symbol + * period. + * + * PHY specific symbol periods are defined in PHY specific sections below. */ -#define IEEE802154_PHY_SYMBOL_PERIOD_US(is_subg_phy) \ - ((is_subg_phy) ? IEEE802154_PHY_SUN_FSK_863MHZ_915MHZ_SYMBOL_PERIOD_US \ - : IEEE802154_PHY_OQPSK_2450MHZ_SYMBOL_PERIOD_US) +#define IEEE802154_PHY_SYMBOLS_PER_SECOND(symbol_period_ns) (NSEC_PER_SEC / symbol_period_ns) -/* The inverse of the symbol period as defined in section 6.1. This is not necessarily the true - * physical symbol period, so take care to use this macro only when either the symbol period used - * for MAC timing is the same as the physical symbol period or if you actually mean the MAC timing - * symbol period. +/** @} */ + + +/** + * @name IEEE 802.15.4-2020, Section 8: MAC services + * @{ */ -#define IEEE802154_PHY_SYMBOLS_PER_SECOND(symbol_period) (USEC_PER_SEC / symbol_period) -/* in bytes, see section 19.2.4 */ -#define IEEE802154_PHY_SUN_FSK_PHR_LEN 2 +/** + * The number of PHY symbols forming a superframe slot when the superframe order + * is equal to zero, see sections 8.4.2, table 8-93, aBaseSlotDuration and + * section 6.2.1. + */ +#define IEEE802154_MAC_A_BASE_SLOT_DURATION 60U -/* Default PHY PIB attribute aTurnaroundTime, in PHY symbols, see section 11.3, table 11-1. */ -#define IEEE802154_PHY_A_TURNAROUND_TIME_DEFAULT 12U +/** + * The number of slots contained in any superframe, see section 8.4.2, + * table 8-93, aNumSuperframeSlots. + */ +#define IEEE802154_MAC_A_NUM_SUPERFRAME_SLOTS 16U -/* PHY PIB attribute aTurnaroundTime for SUN, RS-GFSK, TVWS, and LECIM FSK PHY, - * in PHY symbols, see section 11.3, table 11-1. +/** + * The number of PHY symbols forming a superframe when the superframe order is + * equal to zero, see section 8.4.2, table 8-93, aBaseSuperframeDuration. */ -#define IEEE802154_PHY_A_TURNAROUND_TIME_1MS(symbol_period) \ - DIV_ROUND_UP(USEC_PER_MSEC, symbol_period) +#define IEEE802154_MAC_A_BASE_SUPERFRAME_DURATION \ + (IEEE802154_MAC_A_BASE_SLOT_DURATION * IEEE802154_MAC_A_NUM_SUPERFRAME_SLOTS) -/* TODO: Get PHY-specific turnaround time from radio API, see - * https://github.com/zephyrproject-rtos/zephyr/issues/50336#issuecomment-1251122582. - * For now we assume PHYs that current drivers actually implement. +/** + * MAC PIB attribute aUnitBackoffPeriod, see section 8.4.2, table 8-93, in symbol + * periods, valid for all PHYs except SUN PHY in the 920 MHz band. */ -#define IEEE802154_PHY_A_TURNAROUND_TIME(is_subg_phy) \ - ((is_subg_phy) ? IEEE802154_PHY_A_TURNAROUND_TIME_1MS( \ - IEEE802154_PHY_SYMBOL_PERIOD_US(is_subg_phy)) \ - : IEEE802154_PHY_A_TURNAROUND_TIME_DEFAULT) +#define IEEE802154_MAC_A_UNIT_BACKOFF_PERIOD(turnaround_time) \ + (turnaround_time + IEEE802154_PHY_A_CCA_TIME) -/* PHY PIB attribute aCcaTime, in PHY symbols, all PHYs except for SUN O-QPSK, - * see section 11.3, table 11-1. +/** + * Default macResponseWaitTime in multiples of aBaseSuperframeDuration as + * defined in section 8.4.3.1, table 8-94. + */ +#define IEEE802154_MAC_RESPONSE_WAIT_TIME_DEFAULT 32U + +/** @} */ + + +/** + * @name IEEE 802.15.4-2020, Section 10: General PHY requirements + * @{ */ -#define IEEE802154_PHY_A_CCA_TIME 8U /** - * @brief IEEE 802.15.4 Channel assignments + * @brief PHY channel pages, see section 10.1.3 * - * Channel numbering for 868 MHz, 915 MHz, and 2450 MHz bands (channel page zero). + * @details A device driver must support the mandatory channel pages, frequency + * bands and channels of at least one IEEE 802.15.4 PHY. * - * - Channel 0 is for 868.3 MHz. - * - Channels 1-10 are for 906 to 924 MHz with 2 MHz channel spacing. - * - Channels 11-26 are for 2405 to 2530 MHz with 5 MHz channel spacing. + * Channel page and number assignments have developed over several versions of + * the standard and are not particularly well documented. Therefore some notes + * about peculiarities of channel pages and channel numbering: + * - The 2006 version of the standard had a read-only phyChannelsSupported PHY + * PIB attribute that represented channel page/number combinations as a + * bitmap. This attribute was removed in later versions of the standard as the + * number of channels increased beyond what could be represented by a bit map. + * That's the reason why it was decided to represent supported channels as a + * combination of channel pages and ranges instead. + * - In the 2020 version of the standard, 13 channel pages are explicitly + * defined, but up to 32 pages could in principle be supported. This was a + * hard requirement in the 2006 standard. In later standards it is implicit + * from field specifications, e.g. the MAC PIB attribute macChannelPage + * (section 8.4.3.4, table 8-100) or channel page fields used in the SRM + * protocol (see section 8.2.26.5). + * - ASK PHY (channel page one) was deprecated in the 2015 version of the + * standard. The 2020 version of the standard is a bit ambivalent whether + * channel page one disappeared as well or should be interpreted as O-QPSK now + * (see section 10.1.3.3). In Zephyr this ambivalence is resolved by + * deprecating channel page one. + * - For some PHYs the standard doesn't clearly specify a channel page, namely + * the GFSK, RS-GFSK, CMB and TASK PHYs. These are all rather new and left out + * in our list as long as no driver wants to implement them. * - * For more information, please refer to section 10.1.3. + * @warning The bit numbers are not arbitrary but represent the channel + * page numbers as defined by the standard. Therefore do not change the + * bit numbering. */ -enum ieee802154_channel { - IEEE802154_SUB_GHZ_CHANNEL_MIN = 0, - IEEE802154_SUB_GHZ_CHANNEL_MAX = 10, - IEEE802154_2_4_GHZ_CHANNEL_MIN = 11, - IEEE802154_2_4_GHZ_CHANNEL_MAX = 26, -}; - -enum ieee802154_hw_caps { - - /* - * PHY capabilities +enum ieee802154_phy_channel_page { + /** + * Channel page zero supports the 2.4G channels of the O-QPSK PHY and + * all channels from the BPSK PHYs initially defined in the 2003 + * editions of the standard. For channel page zero, 16 channels are + * available in the 2450 MHz band (channels 11-26, O-QPSK), 10 in the + * 915 MHz band (channels 1-10, BPSK), and 1 in the 868 MHz band + * (channel 0, BPSK). * - * The following capabilities describe features of the underlying radio - * hardware (PHY/L1). + * You can retrieve the channels supported by a specific driver on this + * page via @ref IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES attribute. * - * Note: A device driver must support the mandatory channel pages, - * frequency bands and channels of at least one IEEE 802.15.4 PHY. + * see section 10.1.3.3 + */ + IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915 = BIT(0), + + /** Formerly ASK PHY - deprecated in IEEE 802.15.4-2015 */ + IEEE802154_ATTR_PHY_CHANNEL_PAGE_ONE_DEPRECATED = BIT(1), + + /** O-QPSK PHY - 868 MHz and 915 MHz bands, see section 10.1.3.3 */ + IEEE802154_ATTR_PHY_CHANNEL_PAGE_TWO_OQPSK_868_915 = BIT(2), + + /** CSS PHY - 2450 MHz band, see section 10.1.3.4 */ + IEEE802154_ATTR_PHY_CHANNEL_PAGE_THREE_CSS = BIT(3), + + /** UWB PHY - SubG, low and high bands, see section 10.1.3.5 */ + IEEE802154_ATTR_PHY_CHANNEL_PAGE_FOUR_HRP_UWB = BIT(4), + + /** O-QPSK PHY - 780 MHz band, see section 10.1.3.2 */ + IEEE802154_ATTR_PHY_CHANNEL_PAGE_FIVE_OQPSK_780 = BIT(5), + + /** reserved - not currently assigned */ + IEEE802154_ATTR_PHY_CHANNEL_PAGE_SIX_RESERVED = BIT(6), + + /** MSK PHY - 780 MHz and 2450 MHz bands, see sections 10.1.3.6, 10.1.3.7 */ + IEEE802154_ATTR_PHY_CHANNEL_PAGE_SEVEN_MSK = BIT(7), + + /** LRP UWB PHY, see sections 10.1.3.8 */ + IEEE802154_ATTR_PHY_CHANNEL_PAGE_EIGHT_LRP_UWB = BIT(8), + + /** + * SUN FSK/OFDM/O-QPSK PHYs - predefined bands, operating modes and + * channels, see sections 10.1.3.9 */ + IEEE802154_ATTR_PHY_CHANNEL_PAGE_NINE_SUN_PREDEFINED = BIT(9), /** - * 2.4Ghz radio supported + * SUN FSK/OFDM/O-QPSK PHYs - generic modulation and channel + * description, see sections 10.1.3.9, 7.4.4.11 + */ + IEEE802154_ATTR_PHY_CHANNEL_PAGE_TEN_SUN_FSK_GENERIC = BIT(10), + + /** O-QPSK PHY - 2380 MHz band, see section 10.1.3.10 */ + IEEE802154_ATTR_PHY_CHANNEL_PAGE_ELEVEN_OQPSK_2380 = BIT(11), + + /** LECIM DSSS/FSK PHYs, see section 10.1.3.11 */ + IEEE802154_ATTR_PHY_CHANNEL_PAGE_TWELVE_LECIM = BIT(12), + + /** RCC PHY, see section 10.1.3.12 */ + IEEE802154_ATTR_PHY_CHANNEL_PAGE_THIRTEEN_RCC = BIT(13), +}; + +/** + * Represents a supported channel range, see @ref + * ieee802154_phy_supported_channels. + */ +struct ieee802154_phy_channel_range { + uint16_t from_channel; + uint16_t to_channel; +}; + +/** + * Represents a list channels supported by a driver for a given interface, see + * @ref IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES. + */ +struct ieee802154_phy_supported_channels { + /** + * @brief Pointer to an array of channel range structures. * - * TODO: Replace with channel page attribute. + * @warning The pointer must be valid and constant throughout the life + * of the interface. */ - IEEE802154_HW_2_4_GHZ = BIT(0), + const struct ieee802154_phy_channel_range *const ranges; + + /** @brief The number of currently available channel ranges. */ + const uint8_t num_ranges; +}; + +/** + * @brief Allocate memory for the supported channels driver attribute with a + * single channel range constant across all driver instances. This is what most + * IEEE 802.15.4 drivers need. + * + * @details Example usage: + * + * @code{.c} + * IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26); + * @endcode + * + * The attribute may then be referenced like this: + * + * @code{.c} + * ... &drv_attr.phy_supported_channels ... + * @endcode + * + * See @ref ieee802154_attr_get_channel_page_and_range() for a further shortcut + * that can be combined with this macro. + * + * @param drv_attr name of the local static variable to be declared for the + * local attributes structure + * @param from the first channel to be supported + * @param to the last channel to be supported + */ +#define IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, from, to) \ + static const struct { \ + const struct ieee802154_phy_channel_range phy_channel_range; \ + const struct ieee802154_phy_supported_channels phy_supported_channels; \ + } drv_attr = { \ + .phy_channel_range = {.from_channel = (from), .to_channel = (to)}, \ + .phy_supported_channels = \ + { \ + .ranges = &drv_attr.phy_channel_range, \ + .num_ranges = 1U, \ + }, \ + } + +/** @} */ + + +/** + * @name IEEE 802.15.4-2020, Section 11: PHY services + * @{ + */ + +/** + * Default PHY PIB attribute aTurnaroundTime, in PHY symbols, see section 11.3, + * table 11-1. + */ +#define IEEE802154_PHY_A_TURNAROUND_TIME_DEFAULT 12U + +/** + * PHY PIB attribute aTurnaroundTime for SUN, RS-GFSK, TVWS, and LECIM FSK PHY, + * in PHY symbols, see section 11.3, table 11-1. + */ +#define IEEE802154_PHY_A_TURNAROUND_TIME_1MS(symbol_period_ns) \ + DIV_ROUND_UP(NSEC_PER_MSEC, symbol_period_ns) + +/** + * PHY PIB attribute aCcaTime, in PHY symbols, all PHYs except for SUN O-QPSK, + * see section 11.3, table 11-1. + */ +#define IEEE802154_PHY_A_CCA_TIME 8U + +/** @} */ + + + +/** + * @name IEEE 802.15.4-2020, Section 12: O-QPSK PHY + * @{ + */ + +/** O-QPSK 868Mhz band symbol period, see section 12.3.3 */ +#define IEEE802154_PHY_OQPSK_868MHZ_SYMBOL_PERIOD_NS 40000LL + +/** + * O-QPSK 780MHz, 915MHz, 2380MHz and 2450MHz bands symbol period, + * see section 12.3.3 + */ +#define IEEE802154_PHY_OQPSK_780_TO_2450MHZ_SYMBOL_PERIOD_NS 16000LL + +/** @} */ + + +/** + * @name IEEE 802.15.4-2020, Section 13: BPSK PHY + * @{ + */ + +/** BPSK 868MHz band symbol period, see section 13.3.3 */ +#define IEEE802154_PHY_BPSK_868MHZ_SYMBOL_PERIOD_NS 50000LL + +/** BPSK 915MHz band symbol period, see section 13.3.3 */ +#define IEEE802154_PHY_BPSK_915MHZ_SYMBOL_PERIOD_NS 25000LL + +/** @} */ + + +/** + * @name IEEE 802.15.4-2020, Section 15: HRP UWB PHY + * + * @details For HRP UWB the symbol period is derived from the preamble symbol period + * (T_psym), see section 11.3, table 11-1 and section 15.2.5, table 15-4 + * (confirmed in IEEE 802.15.4z, section 15.1). Choosing among those periods + * cannot be done based on channel page and channel alone. The mean pulse + * repetition frequency must also be known, see the 'UwbPrf' parameter of the + * MCPS-DATA.request primitive (section 8.3.2, table 8-88) and the preamble + * parameters for HRP-ERDEV length 91 codes (IEEE 802.15.4z, section 15.2.6.2, + * table 15-7b). + * @{ + */ + +/** Nominal PRF 4MHz symbol period */ +#define IEEE802154_PHY_HRP_UWB_PRF4_TPSYM_SYMBOL_PERIOD_NS 3974.36F +/** Nominal PRF 16MHz symbol period */ +#define IEEE802154_PHY_HRP_UWB_PRF16_TPSYM_SYMBOL_PERIOD_NS 993.59F +/** Nominal PRF 64MHz symbol period */ +#define IEEE802154_PHY_HRP_UWB_PRF64_TPSYM_SYMBOL_PERIOD_NS 1017.63F +/** ERDEV symbol period */ +#define IEEE802154_PHY_HRP_UWB_ERDEV_TPSYM_SYMBOL_PERIOD_NS 729.17F + +/** @brief represents the nominal pulse rate frequency of an HRP UWB PHY */ +enum ieee802154_phy_hrp_uwb_nominal_prf { + /** standard modes, see section 8.3.2, table 8-88. */ + IEEE802154_PHY_HRP_UWB_PRF_OFF = 0, + IEEE802154_PHY_HRP_UWB_NOMINAL_4_M = BIT(0), + IEEE802154_PHY_HRP_UWB_NOMINAL_16_M = BIT(1), + IEEE802154_PHY_HRP_UWB_NOMINAL_64_M = BIT(2), /** - * Sub-GHz radio supported + * enhanced ranging device (ERDEV) modes not specified in table 8-88, + * see IEEE 802.15.4z, section 15.1, section 15.2.6.2, table 15-7b, + * section 15.3.4.2 and section 15.3.4.3. + */ + IEEE802154_PHY_HRP_UWB_NOMINAL_64_M_BPRF = BIT(3), + IEEE802154_PHY_HRP_UWB_NOMINAL_128_M_HPRF = BIT(4), + IEEE802154_PHY_HRP_UWB_NOMINAL_256_M_HPRF = BIT(5), +}; + +/** RDEV device mask */ +#define IEEE802154_PHY_HRP_UWB_RDEV \ + (IEEE802154_PHY_HRP_UWB_NOMINAL_4_M | IEEE802154_PHY_HRP_UWB_NOMINAL_16_M | \ + IEEE802154_PHY_HRP_UWB_NOMINAL_64_M) + +/** ERDEV device mask */ +#define IEEE802154_PHY_HRP_UWB_ERDEV \ + (IEEE802154_PHY_HRP_UWB_NOMINAL_64_M_BPRF | IEEE802154_PHY_HRP_UWB_NOMINAL_128_M_HPRF | \ + IEEE802154_PHY_HRP_UWB_NOMINAL_256_M_HPRF) + +/** @} */ + + +/** + * @name IEEE 802.15.4-2020, Section 19: SUN FSK PHY + * @{ + */ + +/** SUN FSK 863Mhz and 915MHz band symbol periods, see section 19.1, table 19-1 */ +#define IEEE802154_PHY_SUN_FSK_863MHZ_915MHZ_SYMBOL_PERIOD_NS 20000LL + +/** SUN FSK PHY header length, in bytes, see section 19.2.4 */ +#define IEEE802154_PHY_SUN_FSK_PHR_LEN 2 + +/** @} */ + +/** + * @name IEEE 802.15.4 Driver API + * @{ + */ + +/** + * IEEE 802.15.4 driver capabilities + * + * Any driver properties that can be represented in binary form should be + * modeled as capabilities. These are called "hardware" capabilities for + * historical reasons but may also represent driver firmware capabilities (e.g. + * MAC offloading features). + */ +enum ieee802154_hw_caps { + + /* + * PHY capabilities * - * TODO: Replace with channel page attribute. + * The following capabilities describe features of the underlying radio + * hardware (PHY/L1). */ - IEEE802154_HW_SUB_GHZ = BIT(1), /** Energy detection (ED) supported (optional) */ - IEEE802154_HW_ENERGY_SCAN = BIT(2), - + IEEE802154_HW_ENERGY_SCAN = BIT(0), /* * MAC offloading capabilities (optional) @@ -142,37 +460,63 @@ enum ieee802154_hw_caps { */ /** Frame checksum verification supported */ - IEEE802154_HW_FCS = BIT(3), + IEEE802154_HW_FCS = BIT(1), /** Filtering of PAN ID, extended and short address supported */ - IEEE802154_HW_FILTER = BIT(4), + IEEE802154_HW_FILTER = BIT(2), /** Promiscuous mode supported */ - IEEE802154_HW_PROMISC = BIT(5), + IEEE802154_HW_PROMISC = BIT(3), /** CSMA-CA procedure supported on TX */ - IEEE802154_HW_CSMA = BIT(6), + IEEE802154_HW_CSMA = BIT(4), /** Waits for ACK on TX if AR bit is set in TX pkt */ - IEEE802154_HW_TX_RX_ACK = BIT(7), + IEEE802154_HW_TX_RX_ACK = BIT(5), /** Supports retransmission on TX ACK timeout */ - IEEE802154_HW_RETRANSMISSION = BIT(8), + IEEE802154_HW_RETRANSMISSION = BIT(6), /** Sends ACK on RX if AR bit is set in RX pkt */ - IEEE802154_HW_RX_TX_ACK = BIT(9), + IEEE802154_HW_RX_TX_ACK = BIT(7), /** TX at specified time supported */ - IEEE802154_HW_TXTIME = BIT(10), + IEEE802154_HW_TXTIME = BIT(8), - /** TX directly from sleep supported */ - IEEE802154_HW_SLEEP_TO_TX = BIT(11), + /** TX directly from sleep supported + * + * @note This HW capability does not conform to the requirements + * specified in #61227 as it closely couples the driver to OpenThread's + * capability and device model which is different from Zephyr's: + * - "Sleeping" is a well defined term in Zephyr related to internal + * power and thread management and different from "RX off" as + * defined in OT. + * - Currently all OT-capable drivers have the "sleep to TX" + * capability anyway plus we expect future drivers to implement it + * ootb as well, so no information is actually conveyed by this + * capability. + * - The `start()`/`stop()` API of a net device controls the + * interface's operational state. Drivers MUST respond with + * -ENETDOWN when calling `tx()` while their operational state is + * "DOWN", only devices in the "UP" state MAY transmit packets (RFC + * 2863). + * - A migration path has been defined in #63670 for actual removal of + * this capability in favor of a standard compliant + * `configure(rx_on/rx_off)` call, see there for details. + * + * @deprecated Drivers and L2 SHALL not introduce additional references + * to this capability and remove existing ones as outlined in #63670. + */ + IEEE802154_HW_SLEEP_TO_TX = BIT(9), /** Timed RX window scheduling supported */ - IEEE802154_HW_RXTIME = BIT(12), + IEEE802154_HW_RXTIME = BIT(10), /** TX security supported (key management, encryption and authentication) */ - IEEE802154_HW_TX_SEC = BIT(13), + IEEE802154_HW_TX_SEC = BIT(11), + + /** RxOnWhenIdle handling supported */ + IEEE802154_RX_ON_WHEN_IDLE = BIT(12), /* Note: Update also IEEE802154_HW_CAPS_BITS_COMMON_COUNT when changing * the ieee802154_hw_caps type. @@ -180,11 +524,12 @@ enum ieee802154_hw_caps { }; /** @brief Number of bits used by ieee802154_hw_caps type. */ -#define IEEE802154_HW_CAPS_BITS_COMMON_COUNT (14) +#define IEEE802154_HW_CAPS_BITS_COMMON_COUNT (13) /** @brief This and higher values are specific to the protocol- or driver-specific extensions. */ #define IEEE802154_HW_CAPS_BITS_PRIV_START IEEE802154_HW_CAPS_BITS_COMMON_COUNT +/** Filter type, see @ref ieee802154_radio_api::filter */ enum ieee802154_filter_type { IEEE802154_FILTER_TYPE_IEEE_ADDR, IEEE802154_FILTER_TYPE_SHORT_ADDR, @@ -193,36 +538,59 @@ enum ieee802154_filter_type { IEEE802154_FILTER_TYPE_SRC_SHORT_ADDR, }; +/** Driver events, see @ref IEEE802154_CONFIG_EVENT_HANDLER */ enum ieee802154_event { - IEEE802154_EVENT_TX_STARTED, /* Data transmission started */ - IEEE802154_EVENT_RX_FAILED, /* Data reception failed */ - IEEE802154_EVENT_SLEEP, /* Sleep pending */ + /** Data transmission started */ + IEEE802154_EVENT_TX_STARTED, + /** Data reception failed */ + IEEE802154_EVENT_RX_FAILED, + /** + * An RX slot ended, requires @ref IEEE802154_HW_RXTIME. + * + * @note This event SHALL not be triggered by drivers when RX is + * synchronously switched of due to a call to `stop()` or an RX slot + * being configured. + */ + IEEE802154_EVENT_RX_OFF, }; +/** RX failed event reasons, see @ref IEEE802154_EVENT_RX_FAILED */ enum ieee802154_rx_fail_reason { - IEEE802154_RX_FAIL_NOT_RECEIVED, /* Nothing received */ - IEEE802154_RX_FAIL_INVALID_FCS, /* Frame had invalid checksum */ - IEEE802154_RX_FAIL_ADDR_FILTERED, /* Address did not match */ - IEEE802154_RX_FAIL_OTHER /* General reason */ + /** Nothing received */ + IEEE802154_RX_FAIL_NOT_RECEIVED, + /** Frame had invalid checksum */ + IEEE802154_RX_FAIL_INVALID_FCS, + /** Address did not match */ + IEEE802154_RX_FAIL_ADDR_FILTERED, + /** General reason */ + IEEE802154_RX_FAIL_OTHER }; +/** Energy scan callback */ typedef void (*energy_scan_done_cb_t)(const struct device *dev, int16_t max_ed); +/** Driver event callback */ typedef void (*ieee802154_event_cb_t)(const struct device *dev, enum ieee802154_event evt, void *event_params); +/** Filter value, see @ref ieee802154_radio_api::filter */ struct ieee802154_filter { -/** @cond INTERNAL_HIDDEN */ union { - uint8_t *ieee_addr; /* in little endian */ - uint16_t short_addr; /* in CPU byte order */ - uint16_t pan_id; /* in CPU byte order */ + /** Extended address, in little endian */ + uint8_t *ieee_addr; + /** Short address, in CPU byte order */ + uint16_t short_addr; + /** PAN ID, in CPU byte order */ + uint16_t pan_id; }; -/** @endcond */ }; +/** + * Key configuration for transmit security offloading, see @ref + * IEEE802154_CONFIG_MAC_KEYS. + */ struct ieee802154_key { /** Key material */ uint8_t *key_value; @@ -236,7 +604,7 @@ struct ieee802154_key { uint8_t *key_id; }; -/** IEEE802.15.4 Transmission mode. */ +/** IEEE 802.15.4 Transmission mode. */ enum ieee802154_tx_mode { /** Transmit packet immediately, no CCA. */ IEEE802154_TX_MODE_DIRECT, @@ -252,7 +620,7 @@ enum ieee802154_tx_mode { IEEE802154_TX_MODE_CSMA_CA, /** - * Transmit packet in the future, at specified time, no CCA. + * Transmit packet in the future, at the specified time, no CCA. * * @note requires IEEE802154_HW_TXTIME capability. */ @@ -262,6 +630,9 @@ enum ieee802154_tx_mode { * Transmit packet in the future, perform CCA before transmission. * * @note requires IEEE802154_HW_TXTIME capability. + * + * @note Required for Thread 1.2 Coordinated Sampled Listening feature + * (see Thread specification 1.2.0, ch. 3.2.6.3). */ IEEE802154_TX_MODE_TXTIME_CCA, @@ -272,113 +643,457 @@ enum ieee802154_tx_mode { IEEE802154_TX_MODE_PRIV_START = IEEE802154_TX_MODE_COMMON_COUNT, }; -/** IEEE802.15.4 Frame Pending Bit table address matching mode. */ +/** IEEE 802.15.4 Frame Pending Bit table address matching mode. */ enum ieee802154_fpb_mode { - /** The pending bit shall be set only for addresses found in the list. - */ + /** The pending bit shall be set only for addresses found in the list. */ IEEE802154_FPB_ADDR_MATCH_THREAD, - /** The pending bit shall be cleared for short addresses found in - * the list. + /** The pending bit shall be cleared for short addresses found in the + * list. */ IEEE802154_FPB_ADDR_MATCH_ZIGBEE, }; -/** IEEE802.15.4 driver configuration types. */ +/** IEEE 802.15.4 driver configuration types. */ enum ieee802154_config_type { - /** Indicates how radio driver should set Frame Pending bit in ACK - * responses for Data Requests. If enabled, radio driver should - * determine whether to set the bit or not based on the information - * provided with ``IEEE802154_CONFIG_ACK_FPB`` config and FPB address - * matching mode specified. Otherwise, Frame Pending bit should be set - * to ``1`` (see section 6.7.3). - * Requires IEEE802154_HW_TX_RX_ACK capability. + /** + * Indicates how the driver should set the Frame Pending bit in ACK + * responses for Data Requests. If enabled, the driver should determine + * whether to set the bit or not based on the information provided with + * @ref IEEE802154_CONFIG_ACK_FPB config and FPB address matching mode + * specified. Otherwise, Frame Pending bit should be set to ``1`` (see + * section 6.7.3). + * + * @note requires @ref IEEE802154_HW_TX_RX_ACK capability and is + * available in any interface operational state. */ IEEE802154_CONFIG_AUTO_ACK_FPB, - /** Indicates whether to set ACK Frame Pending bit for specific address - * or not. Disabling the Frame Pending bit with no address provided - * (NULL pointer) should disable it for all enabled addresses. - * Requires IEEE802154_HW_TX_RX_ACK capability. + /** + * Indicates whether to set ACK Frame Pending bit for specific address + * or not. Disabling the Frame Pending bit with no address provided + * (NULL pointer) should disable it for all enabled addresses. + * + * @note requires @ref IEEE802154_HW_TX_RX_ACK capability and is + * available in any interface operational state. */ IEEE802154_CONFIG_ACK_FPB, - /** Indicates whether the device is a PAN coordinator. */ + /** + * Indicates whether the device is a PAN coordinator. This influences + * packet filtering. + * + * @note Available in any interface operational state. + */ IEEE802154_CONFIG_PAN_COORDINATOR, - /** Enable/disable promiscuous mode. */ + /** + * Enable/disable promiscuous mode. + * + * @note Available in any interface operational state. + */ IEEE802154_CONFIG_PROMISCUOUS, - /** Specifies new radio event handler. Specifying NULL as a handler - * will disable radio events notification. + /** + * Specifies new IEEE 802.15.4 driver event handler. Specifying NULL as + * a handler will disable events notification. + * + * @note Available in any interface operational state. */ IEEE802154_CONFIG_EVENT_HANDLER, - /** Updates MAC keys and key index for radios supporting transmit security. */ + /** + * Updates MAC keys, key index and the per-key frame counter for drivers + * supporting transmit security offloading, see section 9.5, tables 9-9 + * and 9-10. The key configuration SHALL NOT be accepted if the frame + * counter (in case frame counter per key is true) is not strictly + * larger than the current frame counter associated with the same key, + * see sections 8.2.2, 9.2.4 g/h) and 9.4.3. + * + * @note Requires @ref IEEE802154_HW_TX_SEC capability and is available + * in any interface operational state. + */ IEEE802154_CONFIG_MAC_KEYS, - /** Sets the current MAC frame counter value for radios supporting transmit security. */ + /** + * Sets the current MAC frame counter value associated with the + * interface for drivers supporting transmit security offloading, see + * section 9.5, table 9-8, secFrameCounter. + * + * @warning The frame counter MUST NOT be accepted if it is not + * strictly greater than the current frame counter associated with the + * interface, see sections 8.2.2, 9.2.4 g/h) and 9.4.3. Otherwise the + * replay protection provided by the frame counter may be compromised. + * Drivers SHALL return -EINVAL in case the configured frame counter + * does not conform to this requirement. + * + * @note Requires @ref IEEE802154_HW_TX_SEC capability and is available + * in any interface operational state. + */ IEEE802154_CONFIG_FRAME_COUNTER, - /** Sets the current MAC frame counter value if the provided value is greater than - * the current one. + /** + * Sets the current MAC frame counter value if the provided value is greater than + * the current one. + * + * @note Requires @ref IEEE802154_HW_TX_SEC capability and is available + * in any interface operational state. + * + * @warning This configuration option does not conform to the + * requirements specified in #61227 as it is redundant with @ref + * IEEE802154_CONFIG_FRAME_COUNTER, and will therefore be deprecated in + * the future. */ IEEE802154_CONFIG_FRAME_COUNTER_IF_LARGER, - /** Configure a radio reception window. This can be used for any - * scheduled reception, e.g.: Zigbee GP device, CSL, TSCH, etc. + /** + * Set or unset a radio reception window (RX slot). This can be used for + * any scheduled reception, e.g.: Zigbee GP device, CSL, TSCH, etc. + * + * @details The start and duration parameters of the RX slot are + * relative to the network subsystem's local clock. If the start + * parameter of the RX slot is -1 then any previously configured RX + * slot SHALL be canceled immediately. If the start parameter is any + * value in the past (including 0) or the duration parameter is zero + * then the receiver SHALL remain off forever until the RX slot has + * either been removed or re-configured to point to a future start + * time. If an RX slot is configured while the previous RX slot is + * still scheduled, then the previous slot SHALL be cancelled and the + * new slot scheduled instead. + * + * RX slots MAY be programmed while the driver is "DOWN". If any past + * or future RX slot is configured when calling `start()` then the + * interface SHALL be placed in "UP" state but the receiver SHALL not + * be started. + * + * The driver SHALL take care to start/stop the receiver autonomously, + * asynchronously and automatically around the RX slot. The driver + * SHALL resume power just before the RX slot and suspend it again + * after the slot unless another programmed event forces the driver not + * to suspend. The driver SHALL switch to the programmed channel + * before the RX slot and back to the channel set with set_channel() + * after the RX slot. If the driver interface is "DOWN" when the start + * time of an RX slot arrives, then the RX slot SHALL not be observed + * and the receiver SHALL remain off. + * + * If the driver is "UP" while configuring an RX slot, the driver SHALL + * turn off the receiver immediately and (possibly asynchronously) put + * the driver into the lowest possible power saving mode until the + * start of the RX slot. If the driver is "UP" while the RX slot is + * deleted, then the driver SHALL enable the receiver immediately. The + * receiver MUST be ready to receive packets before returning from the + * `configure()` operation in this case. + * + * This behavior means that setting an RX slot implicitly sets the MAC + * PIB attribute macRxOnWhenIdle (see section 8.4.3.1, table 8-94) to + * "false" while deleting the RX slot implicitly sets macRxOnWhenIdle to + * "true". * - * @note requires IEEE802154_HW_RXTIME capability. + * @note requires @ref IEEE802154_HW_RXTIME capability and is available + * in any interface operational state. + * + * @note Required for Thread 1.2 Coordinated Sampled Listening feature + * (see Thread specification 1.2.0, ch. 3.2.6.3). */ IEEE802154_CONFIG_RX_SLOT, - /** Configure CSL receiver (Endpoint) period - * - * In order to configure a CSL receiver the upper layer should combine several - * configuration options in the following way: - * 1. Use ``IEEE802154_CONFIG_ENH_ACK_HEADER_IE`` once to inform the radio driver of the - * short and extended addresses of the peer to which it should inject CSL IEs. - * 2. Use ``IEEE802154_CONFIG_CSL_RX_TIME`` periodically, before each use of - * ``IEEE802154_CONFIG_CSL_PERIOD`` setting parameters of the nearest CSL RX window, - * and before each use of IEEE_CONFIG_RX_SLOT setting parameters of the following (not - * the nearest one) CSL RX window, to allow the radio driver to calculate the proper - * CSL Phase to the nearest CSL window to inject in the CSL IEs for both transmitted - * data and ACK frames. - * 3. Use ``IEEE802154_CONFIG_CSL_PERIOD`` on each value change to update the current CSL - * period value which will be injected in the CSL IEs together with the CSL Phase - * based on ``IEEE802154_CONFIG_CSL_RX_TIME``. - * 4. Use ``IEEE802154_CONFIG_RX_SLOT`` periodically to schedule the immediate receive - * window earlier enough before the expected window start time, taking into account - * possible clock drifts and scheduling uncertainties. - * - * This diagram shows the usage of the four options over time: - * Start CSL Schedule CSL window - * - * ENH_ACK_HEADER_IE CSL_RX_TIME (following window) - * | | - * | CSL_RX_TIME (nearest window) | RX_SLOT (nearest window) - * | | | | - * | | CSL_PERIOD | | - * | | | | | - * v v v v v - * ----------------------------------------------------------[ CSL window ]-----+ - * ^ | - * | | - * +--------------------- loop ---------+ + /** + * Enables or disables a device as a CSL receiver and configures its CSL + * period. + * + * @details Configures the CSL period in units of 10 symbol periods. + * Values greater than zero enable CSL if the driver supports it and the + * device starts to operate as a CSL receiver. Setting this to zero + * disables CSL on the device. If the driver does not support CSL, the + * configuration call SHALL return -ENOTSUP. + * + * See section 7.4.2.3 and section 8.4.3.6, table 8-104, macCslPeriod. + * + * @note Confusingly the standard calls the CSL receiver "CSL + * coordinator" (i.e. "coordinating the CSL protocol timing", see + * section 6.12.2.2), although, typically, a CSL coordinator is NOT also + * an IEEE 802.15.4 FFD coordinator or PAN coordintor but a simple RFD + * end device (compare the device roles outlined in sections 5.1, 5.3, + * 5.5 and 6.1). To avoid confusion we therefore prefer calling CSL + * coordinators (typically an RFD end device) "CSL receivers" and CSL + * peer devices (typically FFD coordinators or PAN coordinators) "CSL + * transmitters". Also note that at this time, we do NOT support + * unsynchronized transmission with CSL wake up frames as specified in + * section 6.12.2.4.4. + * + * To offload CSL receiver timing to the driver the upper layer SHALL + * combine several configuration options in the following way: + * + * 1. Use @ref IEEE802154_CONFIG_ENH_ACK_HEADER_IE once with an + * appropriate pre-filled CSL IE and the CSL phase set to an + * arbitrary value or left uninitialized. The CSL phase SHALL be + * injected on-the-fly by the driver at runtime as outlined in 2. + * below. Adding a short and extended address will inform the driver + * of the specific CSL receiver to which it SHALL inject CSL IEs. If + * no addresses are given then the CSL IE will be injected into all + * enhanced ACK frames as soon as CSL is enabled. This configuration + * SHALL be done before enabling CSL by setting a CSL period greater + * than zero. + * + * 2. Configure @ref IEEE802154_CONFIG_EXPECTED_RX_TIME immediately + * followed by @ref IEEE802154_CONFIG_CSL_PERIOD. To prevent race + * conditions, the upper layer SHALL ensure that the receiver is not + * enabled during or between the two calls (e.g. by a previously + * configured RX slot) nor SHALL a frame be transmitted concurrently. + * + * The expected RX time SHALL point to the end of SFD of an ideally + * timed RX frame in an arbitrary past or future CSL channel sample, + * i.e. whose "end of SFD" arrives exactly at the locally predicted + * time inside the CSL channel sample. + * + * The driver SHALL derive CSL anchor points and the CSL phase from + * the given expected RX time as follows: + * + * cslAnchorPointNs = last expected RX time + * + PHY-specific PHR duration in ns + * + * startOfMhrNs = start of MHR of the frame containing the + * CSL IE relative to the local network clock + * + * cslPhase = (startOfMhrNs - cslAnchorPointNs) + * / (10 * PHY specific symbol period in ns) + * % cslPeriod + * + * The driver SHALL set the CSL phase in the IE configured in 1. and + * inject that IE on-the-fly into outgoing enhanced ACK frames if the + * destination address conforms to the IE's address filter. + * + * 3. Use @ref IEEE802154_CONFIG_RX_SLOT periodically to schedule + * each CSL channel sample early enough before its start time. The + * size of the CSL channel sample SHALL take relative clock drift and + * scheduling uncertainties with respect to CSL transmitters into + * account as specified by the standard such that at least the full + * SHR of a legitimate RX frame is guaranteed to land inside the + * channel sample. + * + * To this avail, the last configured expected RX time plus an + * integer number of CSL periods SHALL point to a fixed offset of the + * RX slot (not necessarily its center): + * + * expectedRxTimeNs_N = last expected RX time + * + N * (cslPeriod * 10 * PHY-specific symbol period in ns) + * + * expectedRxTimeNs_N - rxSlot_N.start == const for all N + * + * While the configured CSL period is greater than zero, drivers + * SHOULD validate the offset of the expected RX time inside each RX + * slot accordingly. If the driver finds that the offset varies from + * slot to slot, drivers SHOULD log the difference but SHALL + * nevertheless accept and schedule the RX slot with a zero success + * value to work around minor implementation or rounding errors in + * upper layers. + * + * Configure and start a CSL receiver: + * + * ENH_ACK_HEADER_IE + * | + * | EXPECTED_RX_TIME (end of SFD of a perfectly timed RX frame + * | | in any past or future channel sample) + * | | + * | | CSL_PERIOD (>0) RX_SLOT + * | | | | + * v v v v + * -----------------------------------------------[-CSL channel sample ]----+ + * ^ | + * | | + * +--------------------- loop ---------+ + * + * Disable CSL on the receiver: + * + * CSL_PERIOD (=0) + * | + * v + * --------------------- + * + * Update the CSL period to a new value: + * + * EXPECTED_RX_TIME (based on updated period) + * | + * | CSL_PERIOD (>0, updated) RX_SLOT + * | | | + * v v v + * -----------------------------------------------[-CSL channel sample ]----+ + * ^ | + * | | + * +--------------------- loop ---------+ + * + * @note Available in any interface operational state. + * + * @note Required for Thread 1.2 Coordinated Sampled Listening feature + * (see Thread specification 1.2.0, ch. 3.2.6.3). */ IEEE802154_CONFIG_CSL_PERIOD, - /** Configure the next CSL receive window (i.e. "channel sample") center, - * in units of nanoseconds relative to the network subsystem's local clock. + /** + * Configure a timepoint at which an RX frame is expected to arrive. + * + * @details Configure the nanosecond resolution timepoint relative to + * the network subsystem's local clock at which an RX frame's end of SFD + * (i.e. equivalently its end of SHR, start of PHR, or in the case of + * PHYs with RDEV or ERDEV capability the RMARKER) is expected to arrive + * at the local antenna assuming perfectly synchronized local and remote + * network clocks and zero distance between antennas. + * + * This parameter MAY be used to offload parts of timing sensitive TDMA + * (e.g. TSCH, beacon-enabled PAN including DSME), low-energy (e.g. + * CSL, RIT) or ranging (TDoA) protocols to the driver. In these + * protocols, medium access is tightly controlled such that the expected + * arrival time of a frame can be predicted within a well-defined time + * window. This feature will typically be combined with @ref + * IEEE802154_CONFIG_RX_SLOT although this is not a hard requirement. + * + * The "expected RX time" MAY be interpreted slightly differently + * depending on the protocol context: + * - CSL phase (i.e. time to the next expected CSL transmission) or anchor + * time (i.e. any arbitrary timepoint with "zero CSL phase") SHALL be + * derived by adding the PHY header duration to the expected RX time + * to calculate the "start of MHR" ("first symbol of MAC", see section + * 6.12.2.1) required by the CSL protocol, compare @ref + * IEEE802154_CONFIG_CSL_PERIOD. + * - In TSCH the expected RX time MAY be set to macTsRxOffset + + * macTsRxWait / 2. Then the time correction SHALL be calculated as + * the expected RX time minus actual arrival timestamp, see section + * 6.5.4.3. + * - In ranging applications, time difference of arrival (TDOA) MAY be + * calculated inside the driver comparing actual RMARKER timestamps + * against the assumed synchronized time at which the ranging frame + * was sent, see IEEE 802.15.4z. + * + * In case of periodic protocols (e.g. CSL channel samples, periodic + * beacons of a single PAN, periodic ranging "blinks"), a single + * timestamp at any time in the past or in the future may be given from + * which other expected timestamps can be derived by adding or + * substracting multiples of the RX period. See e.g. the CSL + * documentation in this API. + * + * Additionally this parameter MAY be used by drivers to discipline + * their local representation of a distributed network clock by deriving + * synchronization instants related to a remote representation of the + * same clock (as in PTP). + * + * @note Available in any interface operational state. + * + * @note Required for Thread 1.2 Coordinated Sampled Listening feature + * (see Thread specification 1.2.0, ch. 3.2.6.3). */ - IEEE802154_CONFIG_CSL_RX_TIME, + IEEE802154_CONFIG_EXPECTED_RX_TIME, - /** Indicates whether to inject IE into ENH ACK Frame for specific address - * or not. Disabling the ENH ACK with no address provided (NULL pointer) - * should disable it for all enabled addresses. + /** + * Adds a header information element (IE) to be injected into enhanced + * ACK frames generated by the driver if the given destination address + * filter matches. + * + * @details Drivers implementing the @ref IEEE802154_HW_RX_TX_ACK + * capability generate ACK frames autonomously. Setting this + * configuration will ask the driver to inject the given preconfigured + * header IE when generating enhanced ACK frames where appropriate by + * the standard. IEs for all other frame types SHALL be provided by L2. + * + * The driver shall return -ENOTSUP in the following cases: + * - It does not support the @ref IEEE802154_HW_RX_TX_ACK, + * - It does not support header IE injection, + * - It cannot inject the runtime fields on-the-fly required for the + * given IE element ID (see list below). + * + * Enhanced ACK header IEs (element IDs in parentheses) that either + * need to be rejected or explicitly supported and parsed by the driver + * because they require on-the-fly timing information injection are: + * - CSL IE (0x1a) + * - Rendezvous Time IE (0x1d) + * - Time Correction IE (0x1e) + * + * Drivers accepting this configuration option SHALL check the list of + * configured IEs for each outgoing enhanced ACK frame, select the ones + * appropriate for the received frame based on their element ID, inject + * any required runtime information on-the-fly and include the selected + * IEs into the enhanced ACK frame's MAC header. + * + * Drivers supporting enhanced ACK header IE injection SHALL + * autonomously inject header termination IEs as required by the + * standard. + * + * A destination short address and extended address MAY be given by L2 + * to filter the devices to which the given IE is included. Setting the + * short address to the broadcast address and the extended address to + * NULL will inject the given IE into all ACK frames unless a more + * specific filter is also present for any given destination device + * (fallback configuration). L2 SHALL take care to either set both + * address fields to valid device addresses or none. + * + * This configuration type may be called several times with distinct + * element IDs and/or addresses. The driver SHALL either store all + * configured IE/address combinations or return -ENOMEM if no + * additional configuration can be stored. + * + * Configuring a header IE with a previously configured element ID and + * address filter SHALL override the previous configuration. This + * implies that repetition of the same header IE/address combination is + * NOT supported. + * + * Configuring an existing element ID/address filter combination with + * the header IE's length field set to zero SHALL remove that + * configuration. SHALL remove the fallback configuration if no address + * is given. + * + * Configuring a header IE for an address filter with the header IE + * pointer set to NULL SHALL remove all header IE's for that address + * filter. SHALL remove ALL header IE configuration (including but not + * limited to fallbacks) if no address is given. + * + * If any of the deleted configurations didn't previously exist, then + * the call SHALL be ignored. Whenever the length field is set to zero, + * the content fields MUST NOT be accessed by the driver. + * + * L2 SHALL minimize the space required to keep IE configuration inside + * the driver by consolidating address filters and by removing + * configuation that is no longer required. + * + * @note requires @ref IEEE802154_HW_RX_TX_ACK capability and is + * available in any interface operational state. Currently we only + * support header IEs but that may change in the future. + * + * @note Required for Thread 1.2 Coordinated Sampled Listening feature + * (see Thread specification 1.2.0, ch. 3.2.6.3). + * + * @note Required for Thread 1.2 Link Metrics feature (see Thread + * specification 1.2.0, ch. 4.11.3.3). */ IEEE802154_CONFIG_ENH_ACK_HEADER_IE, + /** + * Enable/disable RxOnWhenIdle MAC PIB attribute (Table 8-94). + * + * Since there is no clear guidance in IEEE 802.15.4 specification about the definition of + * an "idle period", this implementation expects that drivers use the RxOnWhenIdle attribute + * to determine next radio state (false --> off, true --> receive) in the following + * scenarios: + * - Finalization of a regular frame reception task, provided that: + * - The frame is received without errors and passes the filtering and it's not an + * spurious ACK. + * - ACK is not requested or transmission of ACK is not possible due to internal + * conditions. + * - Finalization of a frame transmission or transmission of an ACK frame, when ACK is not + * requested in the transmitted frame. + * - Finalization of the reception operation of a requested ACK due to: + * - ACK timeout expiration. + * - Reception of an invalid ACK or not an ACK frame. + * - Reception of the proper ACK, unless the transmitted frame was a Data Request Command + * and the frame pending bit on the received ACK is set to true. In this case the radio + * platform implementation SHOULD keep the receiver on until a determined timeout which + * triggers an idle period start. + * - Finalization of a stand alone CCA task. + * - Finalization of a CCA operation with busy result during CSMA/CA procedure. + * - Finalization of an Energy Detection task. + * - Finalization of a scheduled radio reception window + * (see @ref IEEE802154_CONFIG_RX_SLOT). + */ + IEEE802154_CONFIG_RX_ON_WHEN_IDLE, + /** Number of types defined in ieee802154_config_type. */ IEEE802154_CONFIG_COMMON_COUNT, @@ -386,56 +1101,82 @@ enum ieee802154_config_type { IEEE802154_CONFIG_PRIV_START = IEEE802154_CONFIG_COMMON_COUNT, }; -/** IEEE802.15.4 driver configuration data. */ +/** + * Configuring an RX slot with the start parameter set to this value will cancel + * and delete any previously configured RX slot. + */ +#define IEEE802154_CONFIG_RX_SLOT_NONE -1LL + +/** + * Configuring an RX slot with this start parameter while the driver is "down", + * will keep RX off when the driver is being started. Configuring an RX slot + * with this start value while the driver is "up" will immediately switch RX off + * until either the slot is deleted, see @ref IEEE802154_CONFIG_RX_SLOT_NONE or + * a slot with a future start parameter is configured and that start time + * arrives. + */ +#define IEEE802154_CONFIG_RX_SLOT_OFF 0LL + +/** IEEE 802.15.4 driver configuration data. */ struct ieee802154_config { /** Configuration data. */ union { - /** ``IEEE802154_CONFIG_AUTO_ACK_FPB`` */ + /** see @ref IEEE802154_CONFIG_AUTO_ACK_FPB */ struct { bool enabled; enum ieee802154_fpb_mode mode; } auto_ack_fpb; - /** ``IEEE802154_CONFIG_ACK_FPB`` */ + /** see @ref IEEE802154_CONFIG_ACK_FPB */ struct { uint8_t *addr; /* in little endian for both, short and extended address */ bool extended; bool enabled; } ack_fpb; - /** ``IEEE802154_CONFIG_PAN_COORDINATOR`` */ + /** see @ref IEEE802154_CONFIG_PAN_COORDINATOR */ bool pan_coordinator; - /** ``IEEE802154_CONFIG_PROMISCUOUS`` */ + /** see @ref IEEE802154_CONFIG_PROMISCUOUS */ bool promiscuous; - /** ``IEEE802154_CONFIG_EVENT_HANDLER`` */ + /** see @ref IEEE802154_CONFIG_RX_ON_WHEN_IDLE */ + bool rx_on_when_idle; + + /** see @ref IEEE802154_CONFIG_EVENT_HANDLER */ ieee802154_event_cb_t event_handler; - /** ``IEEE802154_CONFIG_MAC_KEYS`` - * Pointer to an array containing a list of keys used - * for MAC encryption. Refer to secKeyIdLookupDescriptor and - * secKeyDescriptor in IEEE 802.15.4 + /** + * @brief see @ref IEEE802154_CONFIG_MAC_KEYS + * + * @details Pointer to an array containing a list of keys used + * for MAC encryption. Refer to secKeyIdLookupDescriptor and + * secKeyDescriptor in IEEE 802.15.4 * - * key_value field points to a buffer containing the 16 byte - * key. The buffer is copied by the callee. + * The key_value field points to a buffer containing the 16 byte + * key. The buffer SHALL be copied by the driver before + * returning from the call. * - * The variable length array is terminated by key_value field - * set to NULL. + * The variable length array is terminated by key_value field + * set to NULL. */ struct ieee802154_key *mac_keys; - /** ``IEEE802154_CONFIG_FRAME_COUNTER`` */ + /** see @ref IEEE802154_CONFIG_FRAME_COUNTER */ uint32_t frame_counter; - /** ``IEEE802154_CONFIG_RX_SLOT`` */ + /** see @ref IEEE802154_CONFIG_RX_SLOT */ struct { /** * Nanosecond resolution timestamp relative to the * network subsystem's local clock defining the start of * the RX window during which the receiver is expected - * to be listening (i.e. not including any startup - * times). + * to be listening (i.e. not including any driver + * startup times). + * + * Configuring an rx_slot with the start attribute set + * to -1 will cancel and delete any previously active rx + * slot. */ net_time_t start; @@ -443,7 +1184,11 @@ struct ieee802154_config { * Nanosecond resolution duration of the RX window * relative to the above RX window start time during * which the receiver is expected to be listening (i.e. - * not including any shutdown times). + * not including any shutdown times). Only positive + * values larger than or equal zero are allowed. + * + * Setting the duration to zero will disable the + * receiver, no matter what the start parameter. */ net_time_t duration; @@ -451,38 +1196,51 @@ struct ieee802154_config { } rx_slot; /** - * ``IEEE802154_CONFIG_CSL_PERIOD`` - * - * The CSL period in units of 10 symbol periods, - * see section 7.4.2.3. + * see @ref IEEE802154_CONFIG_CSL_PERIOD * * in CPU byte order */ uint32_t csl_period; /** - * ``IEEE802154_CONFIG_CSL_RX_TIME`` - * - * Nanosecond resolution timestamp relative to the network - * subsystem's local clock defining the center of the CSL RX window - * at which the receiver is expected to be fully started up - * (i.e. not including any startup times). + * see @ref IEEE802154_CONFIG_EXPECTED_RX_TIME */ - net_time_t csl_rx_time; + net_time_t expected_rx_time; - /** ``IEEE802154_CONFIG_ENH_ACK_HEADER_IE`` */ + /** see @ref IEEE802154_CONFIG_ENH_ACK_HEADER_IE */ struct { /** - * header IEs to be added to the Enh-Ack frame + * Pointer to the header IE, see section 7.4.2.1, + * figure 7-21 * - * in little endian + * Certain header IEs may be incomplete if they require + * timing information to be injected at runtime + * on-the-fly, see the list in @ref + * IEEE802154_CONFIG_ENH_ACK_HEADER_IE. + */ + struct ieee802154_header_ie *header_ie; + + /** + * Filters the devices that will receive this IE by + * extended address. MAY be set to NULL to configure a + * fallback for all devices (implies that short_addr + * MUST also be set to @ref + * IEEE802154_BROADCAST_ADDRESS). + * + * in big endian */ - const uint8_t *data; - uint16_t data_len; - /** in CPU byte order */ - uint16_t short_addr; - /** in big endian */ const uint8_t *ext_addr; + + /** + * Filters the devices that will receive this IE by + * short address. MAY be set to @ref + * IEEE802154_BROADCAST_ADDRESS to configure a fallback + * for all devices (implies that ext_addr MUST also set + * to NULL in this case). + * + * in CPU byte order + */ + uint16_t short_addr; } ack_ie; }; }; @@ -494,15 +1252,37 @@ struct ieee802154_config { * details. */ enum ieee802154_attr { + /** + * Retrieves a bit field with supported channel pages. This attribute + * SHALL be implemented by all drivers. + */ + IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_PAGES, + + /** + * Retrieves a pointer to the array of supported channel ranges within + * the currently configured channel page. This attribute SHALL be + * implemented by all drivers. + */ + IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES, + + /** + * Retrieves a bit field with supported HRP UWB nominal pulse repetition + * frequencies. This attribute SHALL be implemented by all devices that + * support channel page four (HRP UWB). + */ + IEEE802154_ATTR_PHY_HRP_UWB_SUPPORTED_PRFS, + /** Number of attributes defined in ieee802154_attr. */ IEEE802154_ATTR_COMMON_COUNT, - /** This and higher values are specific to the protocol- or driver-specific extensions. */ + /** This and higher values are specific to the protocol- or + * driver-specific extensions. + */ IEEE802154_ATTR_PRIV_START = IEEE802154_ATTR_COMMON_COUNT, }; /** - * @brief IEEE 802.15.4 driver attributes. + * @brief IEEE 802.15.4 driver attribute values. * * @details This structure is reserved to scalar and structured attributes that * originate in the driver implementation and can neither be implemented as @@ -511,31 +1291,202 @@ enum ieee802154_attr { * configuration data that originate from L2. * * @note To keep this union reasonably small, any attribute requiring a large - * memory area, SHALL be provided pointing to memory allocated from the driver's - * stack. Clients that need to persist the attribute value SHALL therefore copy - * such memory before returning control to the driver. + * memory area, SHALL be provided pointing to static memory allocated by the + * driver and valid throughout the lifetime of the driver instance. */ struct ieee802154_attr_value { union { - /* TODO: Please remove when first attribute is added. */ - uint8_t dummy; + /* TODO: Implement configuration of phyCurrentPage once drivers + * need to support channel page switching at runtime. + */ + /** + * @brief A bit field that represents the supported channel + * pages, see @ref ieee802154_phy_channel_page. + * + * @note To keep the API extensible as required by the standard, + * supported pages are modeled as a bitmap to support drivers + * that implement runtime switching between multiple channel + * pages. + * + * @note Currently none of the Zephyr drivers implements more + * than one channel page at runtime, therefore only one bit will + * be set and the current channel page (see the PHY PIB + * attribute phyCurrentPage, section 11.3, table 11-2) is + * considered to be read-only, fixed and "well known" via the + * supported channel pages attribute. + */ + uint32_t phy_supported_channel_pages; - /* TODO: Add driver specific PHY attributes (symbol rate, - * aTurnaroundTime, aCcaTime, channels, channel pages, etc.) + /** + * @brief Pointer to a structure representing channel ranges + * currently available on the selected channel page. + * + * @warning The pointer must be valid and constant throughout + * the life of the interface. + * + * @details The selected channel page corresponds to the + * phyCurrentPage PHY PIB attribute, see the description of + * phy_supported_channel_pages above. Currently it can be + * retrieved via the @ref + * IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_PAGES attribute. + * + * Most drivers will expose a single channel page with a single, + * often zero-based, fixed channel range. + * + * Some notable exceptions: + * * The legacy channel page (zero) exposes ranges in different + * bands and even PHYs that are usually not implemented by a + * single driver. + * * SUN and LECIM PHYs specify a large number of bands and + * operating modes on a single page with overlapping channel + * ranges each. Some of these ranges are not zero-based or + * contain "holes". This explains why several ranges may be + * necessary to represent all available channels. + * * UWB PHYs often support partial channel ranges on the same + * channel page depending on the supported bands. + * + * In these cases, drivers may expose custom configuration + * attributes (Kconfig, devicetree, runtime, ...) that allow + * switching between sub-ranges within the same channel page + * (e.g. switching between SubG and 2.4G bands on channel page + * zero or switching between multiple operating modes in the SUN + * or LECIM PHYs. */ + const struct ieee802154_phy_supported_channels *phy_supported_channels; + + /* TODO: Allow the PRF to be configured for each TX call once + * drivers need to support PRF switching at runtime. + */ + /** + * @brief A bit field representing supported HRP UWB pulse + * repetition frequencies (PRF), see enum + * ieee802154_phy_hrp_uwb_nominal_prf. + * + * @note Currently none of the Zephyr HRP UWB drivers implements + * more than one nominal PRF at runtime, therefore only one bit + * will be set and the current PRF (UwbPrf, MCPS-DATA.request, + * section 8.3.2, table 8-88) is considered to be read-only, + * fixed and "well known" via the supported PRF attribute. + */ + uint32_t phy_hrp_uwb_supported_nominal_prfs; }; }; /** - * @brief IEEE 802.15.4 radio interface API. + * @brief Helper function to handle channel page and range to be called from + * drivers' attr_get() implementation. This only applies to drivers with a + * single channel page. + * + * @param attr The attribute to be retrieved. + * @param phy_supported_channel_page The driver's unique channel page. + * @param phy_supported_channels Pointer to the structure that contains the + * driver's channel range or ranges. + * @param value The pointer to the value struct provided by the user. + * + * @retval 0 if the attribute could be resolved + * @retval -ENOENT if the attribute could not be resolved + */ +static inline int ieee802154_attr_get_channel_page_and_range( + enum ieee802154_attr attr, + const enum ieee802154_phy_channel_page phy_supported_channel_page, + const struct ieee802154_phy_supported_channels *phy_supported_channels, + struct ieee802154_attr_value *value) +{ + switch (attr) { + case IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_PAGES: + value->phy_supported_channel_pages = phy_supported_channel_page; + return 0; + + case IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES: + value->phy_supported_channels = phy_supported_channels; + return 0; + + default: + return -ENOENT; + } +} + +/** + * @brief IEEE 802.15.4 driver interface API. + * + * @note This structure is called "radio" API for backwards compatibility. A + * better name would be "IEEE 802.15.4 driver API" as typical drivers will not + * only implement L1/radio (PHY) features but also L2 (MAC) features if the + * vendor-specific driver hardware or firmware offers offloading opportunities. + * + * @details While L1-level driver features are exclusively implemented by + * drivers and MAY be mandatory to support certain application requirements, L2 + * features SHOULD be optional by default and only need to be implemented for + * performance optimization or precise timing as deemed necessary by driver + * maintainers. Fallback implementations ("Soft MAC") SHOULD be provided in the + * driver-independent L2 layer for all L2/MAC features especially if these + * features are not implemented in vendor hardware/firmware by a majority of + * existing in-tree drivers. If, however, a driver offers offloading + * opportunities then L2 implementations SHALL delegate performance critical or + * resource intensive tasks to the driver. * + * All drivers SHALL support two externally observable interface operational + * states: "UP" and "DOWN". Drivers MAY additionally support a "TESTING" + * interface state (see `continuous_carrier()`). + * + * The following rules apply: + * * An interface is considered "UP" when it is able to transmit and receive + * packets, "DOWN" otherwise (see precise definitions of the corresponding + * ifOperStatus values in RFC 2863, section 3.1.14, @ref net_if_oper_state and + * the `continuous_carrier()` exception below). A device that has its receiver + * temporarily disabled during "UP" state due to an active receive window + * configuration is still considered "UP". + * * Upper layers will assume that the interface managed by the driver is "UP" + * after a call to `start()` returned zero or `-EALREADY`. Upper layers assume + * that the interface is "DOWN" after calling `stop()` returned zero or + * `-EALREADY`. + * * The driver SHALL block `start()`/`stop()` calls until the interface fully + * transitioned to the new state (e.g. the receiver is operational, ongoing + * transmissions were finished, etc.). Drivers SHOULD yield the calling thread + * (i.e. "sleep") if waiting for the new state without CPU interaction is + * possible. + * * Drivers are responsible of guaranteeing atomicity of state changes. + * Appropriate means of synchronization SHALL be implemented (locking, atomic + * flags, ...). + * * While the interface is "DOWN", the driver SHALL be placed in the lowest + * possible power state. The driver MAY return from a call to `stop()` before + * it reaches the lowest possible power state, i.e. manage power + * asynchronously. While the interface is "UP", the driver SHOULD + * autonomously and asynchronously transition to lower power states whenever + * possible. If the driver claims to support timed RX/TX capabilities and the + * upper layers configure an RX slot, then the driver SHALL immediately + * transition (asynchronously) to the lowest possible power state until the + * start of the RX slot or until a scheduled packet needs to be transmitted. + * * The driver SHALL NOT change the interface's "UP"/"DOWN" state on its own. + * Initially, the interface SHALL be in the "DOWN" state. + * * Drivers that implement the optional `continuous_carrier()` operation will + * be considered to be in the RFC 2863 "testing" ifOperStatus state if that + * operation returns zero. This state is active until either `start()` or + * `stop()` is called. If `continuous_carrier()` returns a non-zero value then + * the previous state is assumed by upper layers. + * * If calls to `start()`/`stop()` return any other value than zero or + * `-EALREADY`, upper layers will consider the interface to be in a + * "lowerLayerDown" state as defined in RFC 2863. + * * The RFC 2863 "dormant", "unknown" and "notPresent" ifOperStatus states are + * currently not supported. The "lowerLevelUp" state. + * * The `ed_scan()`, `cca()` and `tx()` operations SHALL only be supported in + * the "UP" state and return `-ENETDOWN` in any other state. See the + * function-level API documentation below for further details. + * + * @note In case of devices that support timed RX/TX, the "UP" state is not + * equal to "receiver enabled". If a receive window (i.e. RX slot, see @ref + * IEEE802154_CONFIG_RX_SLOT) is configured before calling `start()` then the + * receiver will not be enabled when transitioning to the "UP" state. + * Configuring a receive window while the interface is "UP" will cause the + * receiver to be disabled immediately until the configured reception time has + * arrived. */ struct ieee802154_radio_api { /** * @brief network interface API * * @note Network devices must extend the network interface API. It is - * therefore mandatory to place it at the top of the radio API struct so + * therefore mandatory to place it at the top of the driver API struct so * that it can be cast to a network interface. */ struct net_if_api iface_api; @@ -543,7 +1494,11 @@ struct ieee802154_radio_api { /** * @brief Get the device driver capabilities. * - * @param dev pointer to radio device + * @note Implementations SHALL be **isr-ok** and MUST NOT **sleep**. MAY + * be called in any interface state once the driver is fully initialized + * ("ready"). + * + * @param dev pointer to IEEE 802.15.4 driver device * * @return Bit field with all supported device driver capabilities. */ @@ -552,24 +1507,38 @@ struct ieee802154_radio_api { /** * @brief Clear Channel Assessment - Check channel's activity * - * @param dev pointer to radio device + * @note Implementations SHALL be **isr-ok** and MAY **sleep**. SHALL + * return -ENETDOWN unless the interface is "UP". + * + * @param dev pointer to IEEE 802.15.4 driver device * * @retval 0 the channel is available * @retval -EBUSY The channel is busy. - * @retval -EIO The CCA procedure could not be executed. + * @retval -EWOULDBLOCK The operation is called from ISR context but + * temporarily cannot be executed without blocking. + * @retval -ENETDOWN The interface is not "UP". * @retval -ENOTSUP CCA is not supported by this driver. + * @retval -EIO The CCA procedure could not be executed. */ int (*cca)(const struct device *dev); /** * @brief Set current channel * - * @param dev pointer to radio device + * @note Implementations SHALL be **isr-ok** and MAY **sleep**. SHALL + * return -EIO unless the interface is either "UP" or "DOWN". + * + * @param dev pointer to IEEE 802.15.4 driver device * @param channel the number of the channel to be set in CPU byte order * * @retval 0 channel was successfully set + * @retval -EALREADY The previous channel is the same as the requested + * channel. * @retval -EINVAL The given channel is not within the range of valid - * channels of the driver's current channel page. + * channels of the driver's current channel page, see the + * IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES driver attribute. + * @retval -EWOULDBLOCK The operation is called from ISR context but + * temporarily cannot be executed without blocking. * @retval -ENOTSUP The given channel is within the range of valid * channels of the driver's current channel page but unsupported by the * current driver. @@ -582,7 +1551,10 @@ struct ieee802154_radio_api { * * @note requires IEEE802154_HW_FILTER capability. * - * @param dev pointer to radio device + * @note Implementations SHALL be **isr-ok** and MAY **sleep**. SHALL + * return -EIO unless the interface is either "UP" or "DOWN". + * + * @param dev pointer to IEEE 802.15.4 driver device * @param set true to set the filter, false to remove it * @param type the type of entity to be added/removed from the filter * list (a PAN ID or a source/destination address) @@ -591,6 +1563,8 @@ struct ieee802154_radio_api { * @retval 0 The filter was successfully added/removed. * @retval -EINVAL The given filter entity or filter entity type * was not valid. + * @retval -EWOULDBLOCK The operation is called from ISR context but + * temporarily cannot be executed without blocking. * @retval -ENOTSUP Setting/removing this filter or filter type * is not supported by this driver. * @retval -EIO Error while setting/removing the filter. @@ -603,12 +1577,17 @@ struct ieee802154_radio_api { /** * @brief Set TX power level in dbm * - * @param dev pointer to radio device + * @note Implementations SHALL be **isr-ok** and MAY **sleep**. SHALL + * return -EIO unless the interface is either "UP" or "DOWN". + * + * @param dev pointer to IEEE 802.15.4 driver device * @param dbm TX power in dbm * * @retval 0 The TX power was successfully set. * @retval -EINVAL The given dbm value is invalid or not supported by * the driver. + * @retval -EWOULDBLOCK The operation is called from ISR context but + * temporarily cannot be executed without blocking. * @retval -EIO The TX power could not be set. */ int (*set_txpower)(const struct device *dev, int16_t dbm); @@ -616,23 +1595,55 @@ struct ieee802154_radio_api { /** * @brief Transmit a packet fragment as a single frame * - * @warning The driver must not take ownership of the given network + * @details Depending on the level of offloading features supported by + * the driver, the frame MAY not be fully encrypted/authenticated or it + * MAY not contain an FCS. It is the responsibility of L2 + * implementations to prepare the frame according to the offloading + * capabilities announced by the driver and to decide whether CCA, + * CSMA/CA, ACK or retransmission procedures need to be executed outside + * ("soft MAC") or inside ("hard MAC") the driver . + * + * All frames originating from L2 SHALL have all required IEs + * pre-allocated and pre-filled such that the driver does not have to + * parse and manipulate IEs at all. This includes ACK packets if the + * driver does not have the @ref IEEE802154_HW_RX_TX_ACK capability. + * Also see @ref IEEE802154_CONFIG_ENH_ACK_HEADER_IE for drivers that + * have the @ref IEEE802154_HW_RX_TX_ACK capability. + * + * IEs that cannot be prepared by L2 unless the TX time is known (e.g. + * CSL IE, Rendezvous Time IE, Time Correction IE, ...) SHALL be sent in + * any of the timed TX modes with appropriate timing information + * pre-filled in the IE such that drivers do not have to parse and + * manipulate IEs at all unless the frame is generated by the driver + * itself. + * + * In case any of the timed TX modes is supported and used (see @ref + * ieee802154_hw_caps and @ref ieee802154_tx_mode), the driver SHALL + * take responsibility of scheduling and sending the packet at the + * precise programmed time autonomously without further interaction by + * upper layers. The call to `tx()` will block until the package has + * either been sent successfully (possibly including channel acquisition + * and packet acknowledgment) or a terminal transmission error occurred. + * The driver SHALL sleep and keep power consumption to the lowest + * possible level until the scheduled transmission time arrives or + * during any other idle waiting time. + * + * @warning The driver SHALL NOT take ownership of the given network * packet and frame (fragment) buffer. Any data required by the driver - * (including the actual frame content) must be read synchronously and - * copied internally if transmission is delayed or executed - * asynchronously. Both, the packet and the buffer may be re-used or - * released immediately after the function returns. - * - * @note Depending on the level of offloading features supported by the - * driver, the frame may not be fully encrypted/authenticated, may not - * contain an FCS or may contain incomplete information elements (IEs). - * It is the responsibility of L2 implementations to prepare the frame - * according to the offloading capabilities announced by the driver and - * to decide whether CCA, CSMA/CA or ACK procedures need to be executed - * in software ("soft MAC") or will be provided by the driver itself - * ("hard MAC"). - * - * @param dev pointer to radio device + * including the actual frame content must be read synchronously and + * copied internally if needed at a later time (e.g. the contents of IEs + * required for protocol configuration, states of frame counters, + * sequence numbers, etc). Both, the packet and the buffer MAY be + * re-used or released by upper layers immediately after the function + * returns. + * + * @note Implementations MAY **sleep** and will usually NOT be + * **isr-ok** - especially when timed TX, CSMA/CA, retransmissions, + * auto-ACK or any other offloading feature is supported that implies + * considerable idle waiting time. SHALL return `-ENETDOWN` unless the + * interface is "UP". + * + * @param dev pointer to IEEE 802.15.4 driver device * @param mode the transmission mode, some of which require specific * offloading capabilities. * @param pkt pointer to the network packet to be transmitted. @@ -643,35 +1654,65 @@ struct ieee802154_radio_api { * supports ACK offloading and the frame requested acknowlegment (AR bit * set), this means that the packet was successfully acknowledged by its * peer. - * @retval -ENOTSUP The given TX mode is not supported. - * @retval -EIO The frame could not be sent due to some unspecified - * error. + * @retval -EINVAL Invalid packet (e.g. an expected IE is missing or the + * encryption/authentication state is not as expected). * @retval -EBUSY The frame could not be sent because the medium was * busy (CSMA/CA or CCA offloading feature only). * @retval -ENOMSG The frame was not confirmed by an ACK packet (TX ACK * offloading feature only). * @retval -ENOBUFS The frame could not be scheduled due to missing - * internal buffer resources (timed TX offloading feature only). + * internal resources (timed TX offloading feature only). + * @retval -ENETDOWN The interface is not "UP". + * @retval -ENOTSUP The given TX mode is not supported. + * @retval -EIO The frame could not be sent due to some unspecified + * driver error (e.g. the driver being busy). */ int (*tx)(const struct device *dev, enum ieee802154_tx_mode mode, struct net_pkt *pkt, struct net_buf *frag); /** - * @brief Start the device and place it in receive mode. + * @brief Start the device. + * + * @details Upper layers will assume the interface is "UP" if this + * operation returns with zero or `-EALREADY`. The interface is placed + * in receive mode before returning from this operation unless an RX + * slot has been configured (even if it lies in the past, see @ref + * IEEE802154_CONFIG_RX_SLOT). * - * @param dev pointer to radio device + * @note Implementations SHALL be **isr-ok** and MAY **sleep**. MAY be + * called in any interface state once the driver is fully initialized + * ("ready"). + * + * @param dev pointer to IEEE 802.15.4 driver device * * @retval 0 The driver was successfully started. + * @retval -EALREADY The driver was already "UP". + * @retval -EWOULDBLOCK The operation is called from ISR context but + * temporarily cannot be executed without blocking. * @retval -EIO The driver could not be started. */ int (*start)(const struct device *dev); /** - * @brief Stop the device and switch off the receiver (sleep mode). + * @brief Stop the device. + * + * @details Upper layers will assume the interface is "DOWN" if this + * operation returns with zero or `-EALREADY`. The driver switches off + * the receiver before returning if it was previously on. The driver + * enters the lowest possible power mode after this operation is called. + * This MAY happen asynchronously (i.e. after the operation already + * returned control). + * + * @note Implementations SHALL be **isr-ok** and MAY **sleep**. MAY be + * called in any interface state once the driver is fully initialized + * ("ready"). * - * @param dev pointer to radio device + * @param dev pointer to IEEE 802.15.4 driver device * * @retval 0 The driver was successfully stopped. + * @retval -EWOULDBLOCK The operation is called from ISR context but + * temporarily cannot be executed without blocking. + * @retval -EALREADY The driver was already "DOWN". * @retval -EIO The driver could not be stopped. */ int (*stop)(const struct device *dev); @@ -679,50 +1720,63 @@ struct ieee802154_radio_api { /** * @brief Start continuous carrier wave transmission. * - * @details To leave this mode, `start()` or `stop()` should be called, - * putting the radio driver in receive or sleep mode, respectively. + * @details The method blocks until the interface has started to emit a + * continuous carrier. To leave this mode, `start()` or `stop()` should + * be called, which will put the driver back into the "UP" or "DOWN" + * states, respectively. * - * @param dev pointer to radio device + * @note Implementations MAY **sleep** and will usually NOT be + * **isr-ok**. MAY be called in any interface state once the driver is + * fully initialized ("ready"). + * + * @param dev pointer to IEEE 802.15.4 driver device * * @retval 0 continuous carrier wave transmission started + * @retval -EALREADY The driver was already in "TESTING" state and + * emitting a continuous carrier. * @retval -EIO not started */ int (*continuous_carrier)(const struct device *dev); /** - * @brief Set radio driver configuration. + * @brief Set or update driver configuration. + * + * @details The method blocks until the interface has been reconfigured + * atomically with respect to ongoing package reception, transmission or + * any other ongoing driver operation. + * + * @note Implementations SHALL be **isr-ok** and MAY **sleep**. MAY be + * called in any interface state once the driver is fully initialized + * ("ready"). Some configuration options may not be supported in all + * interface operational states, see the detailed specifications in @ref + * ieee802154_config_type. In this case the operation returns `-EACCES`. * - * @param dev pointer to radio device + * @param dev pointer to IEEE 802.15.4 driver device * @param type the configuration type to be set * @param config the configuration parameters to be set for the given * configuration type * * @retval 0 configuration successful - * @retval -ENOTSUP The given configuration type is not supported by - * this driver. * @retval -EINVAL The configuration parameters are invalid for the * given configuration type. + * @retval -ENOTSUP The given configuration type is not supported by + * this driver. + * @retval -EACCES The given configuration type is supported by this + * driver but cannot be configured in the current interface operational + * state. * @retval -ENOMEM The configuration cannot be saved due to missing * memory resources. * @retval -ENOENT The resource referenced in the configuration * parameters cannot be found in the configuration. + * @retval -EWOULDBLOCK The operation is called from ISR context but + * temporarily cannot be executed without blocking. + * @retval -EIO An internal error occurred while trying to configure the + * given configuration parameter. */ int (*configure)(const struct device *dev, enum ieee802154_config_type type, const struct ieee802154_config *config); - /** - * @brief Get the available amount of Sub-GHz channels. - * - * TODO: Replace with a combination of channel page and channel - * attributes. - * - * @param dev pointer to radio device - * - * @return number of available channels in the sub-gigahertz band - */ - uint16_t (*get_subg_channel_count)(const struct device *dev); - /** * @brief Run an energy detection scan. * @@ -730,7 +1784,10 @@ struct ieee802154_radio_api { * * @note The radio channel must be set prior to calling this function. * - * @param dev pointer to radio device + * @note Implementations SHALL be **isr-ok** and MAY **sleep**. SHALL + * return `-ENETDOWN` unless the interface is "UP". + * + * @param dev pointer to IEEE 802.15.4 driver device * @param duration duration of energy scan in ms * @param done_cb function called when the energy scan has finished * @@ -740,7 +1797,9 @@ struct ieee802154_radio_api { * this time * @retval -EALREADY a previous energy detection scan has not finished * yet. + * @retval -ENETDOWN The interface is not "UP". * @retval -ENOTSUP This driver does not support energy scans. + * @retval -EIO The energy detection procedure could not be executed. */ int (*ed_scan)(const struct device *dev, uint16_t duration, @@ -754,11 +1813,14 @@ struct ieee802154_radio_api { * See @ref net_time_t for semantic details. * * @note requires IEEE802154_HW_TXTIME and/or IEEE802154_HW_RXTIME - * capabilities. + * capabilities. Implementations SHALL be **isr-ok** and MUST NOT + * **sleep**. MAY be called in any interface state once the driver is + * fully initialized ("ready"). * - * @param dev pointer to radio device + * @param dev pointer to IEEE 802.15.4 driver device * - * @return nanoseconds relative to the network subsystem's local clock + * @return nanoseconds relative to the network subsystem's local clock, + * -1 if an error occurred or the operation is not supported */ net_time_t (*get_time)(const struct device *dev); @@ -774,9 +1836,11 @@ struct ieee802154_radio_api { * capabilities. * * @note Implementations may estimate this value based on current - * operating conditions (e.g. temperature). + * operating conditions (e.g. temperature). Implementations SHALL be + * **isr-ok** and MUST NOT **sleep**. MAY be called in any interface + * state once the driver is fully initialized ("ready"). * - * @param dev pointer to radio device + * @param dev pointer to IEEE 802.15.4 driver device * * @return current estimated clock accuracy in PPM */ @@ -791,12 +1855,17 @@ struct ieee802154_radio_api { * and cannot be directly or indirectly derived by L2. Boolean * attributes SHALL be implemented as @ref ieee802154_hw_caps. * + * @note Implementations SHALL be **isr-ok** and MUST NOT **sleep**. MAY + * be called in any interface state once the driver is fully initialized + * ("ready"). + * * @retval 0 The requested attribute is supported by the driver and the * value can be retrieved from the corresponding @ref ieee802154_attr_value * member. * * @retval -ENOENT The driver does not provide the requested attribute. - * The value structure has does not been updated with attribute data. + * The value structure has not been updated with attribute data. The + * content of the value attribute is undefined. */ int (*attr_get)(const struct device *dev, enum ieee802154_attr attr, @@ -804,14 +1873,24 @@ struct ieee802154_radio_api { }; /* Make sure that the network interface API is properly setup inside - * IEEE 802154 radio API struct (it is the first one). + * IEEE 802.15.4 driver API struct (it is the first one). */ BUILD_ASSERT(offsetof(struct ieee802154_radio_api, iface_api) == 0); +/** @} */ + +/** + * @name IEEE 802.15.4 driver utils + * @{ + */ + +/** @cond INTERNAL_HIDDEN */ #define IEEE802154_AR_FLAG_SET (0x20) +/** INTERNAL_HIDDEN @endcond */ /** - * @brief Check if AR flag is set on the frame inside given net_pkt + * @brief Check if the AR flag is set on the frame inside the given @ref + * net_pkt. * * @param frag A valid pointer on a net_buf structure, must not be NULL, * and its length should be at least 1 byte (ImmAck frames are the @@ -824,41 +1903,50 @@ static inline bool ieee802154_is_ar_flag_set(struct net_buf *frag) return (*frag->data & IEEE802154_AR_FLAG_SET); } +/** @} */ + /** - * @brief Radio driver ACK handling callback into L2 that radio - * drivers must call when receiving an ACK package. + * @name IEEE 802.15.4 driver callbacks + * @{ + */ + +/* TODO: Fix drivers to either unref the packet before they return NET_OK or to + * return NET_CONTINUE instead. See note below. + */ +/** + * @brief IEEE 802.15.4 driver ACK handling callback into L2 that drivers must + * call when receiving an ACK package. * * @details The IEEE 802.15.4 standard prescribes generic procedures for ACK * handling on L2 (MAC) level. L2 stacks therefore have to provides a * fast and re-usable generic implementation of this callback for - * radio drivers to call when receiving an ACK packet. + * drivers to call when receiving an ACK packet. * - * Note: This function is part of Zephyr's 802.15.4 stack L1 -> L2 - * "inversion-of-control" adaptation API and must be implemented by - * all IEEE 802.15.4 L2 stacks. + * Note: This function is part of Zephyr's 802.15.4 stack driver -> L2 + * "inversion-of-control" adaptation API and must be implemented by all + * IEEE 802.15.4 L2 stacks. * * @param iface A valid pointer on a network interface that received the packet * @param pkt A valid pointer on a packet to check * * @return NET_OK if L2 handles the ACK package, NET_CONTINUE or NET_DROP otherwise. * - * Note: Deviating from other functions in the net stack returning net_verdict, - * this function will not unref the package even if it returns NET_OK. - * - * TODO: Fix this deviating behavior. + * @warning Deviating from other functions in the net stack returning + * net_verdict, this function will not unref the package even if it returns + * NET_OK. */ extern enum net_verdict ieee802154_handle_ack(struct net_if *iface, struct net_pkt *pkt); /** - * @brief Radio driver initialization callback into L2 called by radio drivers + * @brief IEEE 802.15.4 driver initialization callback into L2 called by drivers * to initialize the active L2 stack for a given interface. * - * @details Radio drivers must call this function as part of their own - * initialization routine. + * @details Drivers must call this function as part of their own initialization + * routine. * - * Note: This function is part of Zephyr's 802.15.4 stack L1 -> L2 - * "inversion-of-control" adaptation API and must be implemented by - * all IEEE 802.15.4 L2 stacks. + * Note: This function is part of Zephyr's 802.15.4 stack driver -> L2 + * "inversion-of-control" adaptation API and must be implemented by all + * IEEE 802.15.4 L2 stacks. * * @param iface A valid pointer on a network interface */ @@ -868,6 +1956,8 @@ extern void ieee802154_init(struct net_if *iface); #define ieee802154_init(_iface_) #endif /* CONFIG_IEEE802154_RAW_MODE */ +/** @} */ + #ifdef __cplusplus } #endif diff --git a/include/zephyr/net/ieee802154_radio_openthread.h b/include/zephyr/net/ieee802154_radio_openthread.h index 56a9bd8de0d..f6f9949d328 100644 --- a/include/zephyr/net/ieee802154_radio_openthread.h +++ b/include/zephyr/net/ieee802154_radio_openthread.h @@ -34,7 +34,7 @@ enum ieee802154_openthread_tx_mode { * This mode is a non-standard experimental OpenThread feature. It allows transmission * of a packet within a certain time window. * The earliest transmission time is specified as in the other TXTIME modes: - * When the first CCA reports an idle channel then the first symbol of the packet's SHR + * When the first CCA reports an idle channel then the first symbol of the packet's PHR * SHALL be present at the local antenna at the time represented by the scheduled * TX timestamp (referred to as T_tx below). * @@ -48,7 +48,7 @@ enum ieee802154_openthread_tx_mode { * (see @ref IEEE802154_OPENTHREAD_ATTR_T_RECCA and * @ref IEEE802154_OPENTHREAD_ATTR_T_CCATX). Based on these attributes the upper layer * can calculate the latest point in time (T_txmax) that the first symbol of the scheduled - * packet's SHR SHALL be present at the local antenna: + * packet's PHR SHALL be present at the local antenna: * * T_maxtxdelay = max_extra_cca_attempts * (aCcaTime + T_recca) - T_recca + T_ccatx * T_txmax = T_tx + T_maxtxdelay @@ -79,6 +79,17 @@ enum ieee802154_openthread_config_type { IEEE802154_OPENTHREAD_CONFIG_MAX_EXTRA_CCA_ATTEMPTS = IEEE802154_CONFIG_PRIV_START }; +/** + * Thread vendor OUI for vendor specific header or nested information elements, + * see IEEE 802.15.4-2020, sections 7.4.2.2 and 7.4.4.30. + * + * in little endian + */ +#define IEEE802154_OPENTHREAD_THREAD_IE_VENDOR_OUI { 0x9b, 0xb8, 0xea } + +/** length of IEEE 802.15.4-2020 vendor OUIs */ +#define IEEE802154_OPENTHREAD_VENDOR_OUI_LEN 3 + /** OpenThread specific configuration data of ieee802154 driver. */ struct ieee802154_openthread_config { union { diff --git a/include/zephyr/net/lwm2m.h b/include/zephyr/net/lwm2m.h index 6262f6d103d..a57b5542f88 100644 --- a/include/zephyr/net/lwm2m.h +++ b/include/zephyr/net/lwm2m.h @@ -49,6 +49,7 @@ #define LWM2M_OBJECT_PORTFOLIO_ID 16 /**< Portfolio object */ #define LWM2M_OBJECT_BINARYAPPDATACONTAINER_ID 19 /**< Binary App Data Container object */ #define LWM2M_OBJECT_EVENT_LOG_ID 20 /**< Event Log object */ +#define LWM2M_OBJECT_OSCORE_ID 21 /**< OSCORE object */ #define LWM2M_OBJECT_GATEWAY_ID 25 /**< Gateway object */ /* clang-format on */ diff --git a/include/zephyr/net/mdio.h b/include/zephyr/net/mdio.h new file mode 100644 index 00000000000..e7161a7a766 --- /dev/null +++ b/include/zephyr/net/mdio.h @@ -0,0 +1,233 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Definitions for IEEE 802.3 management interface + */ + +#ifndef ZEPHYR_INCLUDE_NET_MDIO_H_ +#define ZEPHYR_INCLUDE_NET_MDIO_H_ + +/** + * @brief Definitions for IEEE 802.3 management interface + * @defgroup ethernet_mdio IEEE 802.3 management interface + * @ingroup ethernet + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** MDIO transaction operation code */ +enum mdio_opcode { + /** IEEE 802.3 22.2.4.5.4 write operation */ + MDIO_OP_C22_WRITE = 1, + + /** IEEE 802.3 22.2.4.5.4 read operation */ + MDIO_OP_C22_READ = 2, + + /** IEEE 802.3 45.3.4 address operation */ + MDIO_OP_C45_ADDRESS = 0, + + /** IEEE 802.3 45.3.4 write operation */ + MDIO_OP_C45_WRITE = 1, + + /** IEEE 802.3 45.3.4 post-read-increment-address operation */ + MDIO_OP_C45_READ_INC = 2, + + /** IEEE 802.3 45.3.4 read operation */ + MDIO_OP_C45_READ = 3 +}; + +/* MDIO Manageable Device addresses */ +/** Physical Medium Attachment / Physical Medium Dependent */ +#define MDIO_MMD_PMAPMD 0x01U +/** WAN Interface Sublayer */ +#define MDIO_MMD_WIS 0x02U +/** Physical Coding Sublayer */ +#define MDIO_MMD_PCS 0x03U +/** PHY Extender Sublayer */ +#define MDIO_MMD_PHYXS 0x04U +/** DTE Extender Sublayer */ +#define MDIO_MMD_DTEXS 0x05U +/** Transmission Convergence */ +#define MDIO_MMD_TC 0x06U +/** Auto-negotiation */ +#define MDIO_MMD_AN 0x07U +/** Separated PMA (1) */ +#define MDIO_MMD_SEPARATED_PMA1 0x08U +/** Separated PMA (2) */ +#define MDIO_MMD_SEPARATED_PMA2 0x09U +/** Separated PMA (3) */ +#define MDIO_MMD_SEPARATED_PMA3 0x0AU +/** Separated PMA (4) */ +#define MDIO_MMD_SEPARATED_PMA4 0x0BU +/** Clause 22 extension */ +#define MDIO_MMD_C22EXT 0x1DU +/** Vendor Specific 1 */ +#define MDIO_MMD_VENDOR_SPECIFIC1 0x1EU +/** Vendor Specific 2 */ +#define MDIO_MMD_VENDOR_SPECIFIC2 0x1FU + +/* MDIO generic registers */ +/** Control 1 */ +#define MDIO_CTRL1 0x0000U +/** Status 1 */ +#define MDIO_STAT1 0x0001U +/** Device identifier (1) */ +#define MDIO_DEVID1 0x0002U +/** Device identifier (2) */ +#define MDIO_DEVID2 0x0003U +/** Speed ability */ +#define MDIO_SPEED 0x0004U +/** Devices in package (1) */ +#define MDIO_DEVS1 0x0005U +/** Devices in package (2) */ +#define MDIO_DEVS2 0x0006U +/** Control 2 */ +#define MDIO_CTRL2 0x0007U +/** Status 2 */ +#define MDIO_STAT2 0x0008U +/** Package identifier (1) */ +#define MDIO_PKGID1 0x000EU +/** Package identifier (2) */ +#define MDIO_PKGID2 0x000FU + + +/* BASE-T1 registers */ +/** BASE-T1 Auto-negotiation control */ +#define MDIO_AN_T1_CTRL 0x0200U +/** BASE-T1 Auto-negotiation status */ +#define MDIO_AN_T1_STAT 0x0201U +/** BASE-T1 Auto-negotiation advertisement register [15:0] */ +#define MDIO_AN_T1_ADV_L 0x0202U +/** BASE-T1 Auto-negotiation advertisement register [31:16] */ +#define MDIO_AN_T1_ADV_M 0x0203U +/** BASE-T1 Auto-negotiation advertisement register [47:32] */ +#define MDIO_AN_T1_ADV_H 0x0204U + +/* BASE-T1 Auto-negotiation Control register */ +/** Auto-negotiation Restart */ +#define MDIO_AN_T1_CTRL_RESTART BIT(9) +/** Auto-negotiation Enable */ +#define MDIO_AN_T1_CTRL_EN BIT(12) + +/* BASE-T1 Auto-negotiation Status register */ +/** Link Status */ +#define MDIO_AN_T1_STAT_LINK_STATUS BIT(2) +/** Auto-negotiation Ability */ +#define MDIO_AN_T1_STAT_ABLE BIT(3) +/** Auto-negotiation Remote Fault */ +#define MDIO_AN_T1_STAT_REMOTE_FAULT BIT(4) +/** Auto-negotiation Complete */ +#define MDIO_AN_T1_STAT_COMPLETE BIT(5) +/** Page Received */ +#define MDIO_AN_T1_STAT_PAGE_RX BIT(6) + +/* BASE-T1 Auto-negotiation Advertisement register [15:0] */ +/** Pause Ability */ +#define MDIO_AN_T1_ADV_L_PAUSE_CAP BIT(10) +/** Pause Ability */ +#define MDIO_AN_T1_ADV_L_PAUSE_ASYM BIT(11) +/** Force Master/Slave Configuration */ +#define MDIO_AN_T1_ADV_L_FORCE_MS BIT(12) +/** Remote Fault */ +#define MDIO_AN_T1_ADV_L_REMOTE_FAULT BIT(13) +/** Acknowledge (ACK) */ +#define MDIO_AN_T1_ADV_L_ACK BIT(14) +/** Next Page Request */ +#define MDIO_AN_T1_ADV_L_NEXT_PAGE_REQ BIT(15) + +/* BASE-T1 Auto-negotiation Advertisement register [31:16] */ +/** 10BASE-T1L Ability */ +#define MDIO_AN_T1_ADV_M_B10L BIT(14) +/** Master/slave Configuration */ +#define MDIO_AN_T1_ADV_M_MST BIT(4) + +/* BASE-T1 Auto-negotiation Advertisement register [47:32] */ +/* 10BASE-T1L High Level Transmit Operating Mode Request */ +#define MDIO_AN_T1_ADV_H_10L_TX_HI_REQ BIT(12) +/* 10BASE-T1L High Level Transmit Operating Mode Ability */ +#define MDIO_AN_T1_ADV_H_10L_TX_HI BIT(13) + + +/* 10BASE-T1L registers */ +/** 10BASE-T1L PMA control */ +#define MDIO_PMA_B10L_CTRL 0x08F6U +/** 10BASE-T1L PMA status */ +#define MDIO_PMA_B10L_STAT 0x08F7U +/** 10BASE-T1L PMA link status*/ +#define MDIO_PMA_B10L_LINK_STAT 0x8302U +/** 10BASE-T1L PCS control */ +#define MDIO_PCS_B10L_CTRL 0x08E6U +/** 10BASE-T1L PCS status */ +#define MDIO_PCS_B10L_STAT 0x08E7U + +/* 10BASE-T1L PMA control register */ +/** 10BASE-T1L Transmit Disable Mode */ +#define MDIO_PMA_B10L_CTRL_TX_DIS_MODE_EN BIT(14) +/** 10BASE-T1L Transmit Voltage Amplitude Control */ +#define MDIO_PMA_B10L_CTRL_TX_LVL_HI BIT(12) +/** 10BASE-T1L EEE Enable */ +#define MDIO_PMA_B10L_CTRL_EEE BIT(10) +/** 10BASE-T1L PMA Loopback */ +#define MDIO_PMA_B10L_CTRL_LB_PMA_LOC_EN BIT(0) + +/* 10BASE-T1L PMA status register */ +/** 10BASE-T1L PMA receive link up */ +#define MDIO_PMA_B10L_STAT_LINK BIT(0) +/** 10BASE-T1L Fault condition detected */ +#define MDIO_PMA_B10L_STAT_FAULT BIT(1) +/** 10BASE-T1L Receive polarity is reversed */ +#define MDIO_PMA_B10L_STAT_POLARITY BIT(2) +/** 10BASE-T1L Able to detect fault on receive path */ +#define MDIO_PMA_B10L_STAT_RECV_FAULT BIT(9) +/** 10BASE-T1L PHY has EEE ability */ +#define MDIO_PMA_B10L_STAT_EEE BIT(10) +/** 10BASE-T1L PMA has low-power ability */ +#define MDIO_PMA_B10L_STAT_LOW_POWER BIT(11) +/** 10BASE-T1L PHY has 2.4 Vpp operating mode ability */ +#define MDIO_PMA_B10L_STAT_2V4_ABLE BIT(12) +/** 10BASE-T1L PHY has loopback ability */ +#define MDIO_PMA_B10L_STAT_LB_ABLE BIT(13) + +/* 10BASE-T1L PMA link status*/ +/** 10BASE-T1L Remote Receiver Status OK Latch Low */ +#define MDIO_PMA_B10L_LINK_STAT_REM_RCVR_STAT_OK_LL BIT(9) +/** 10BASE-T1L Remote Receiver Status OK */ +#define MDIO_PMA_B10L_LINK_STAT_REM_RCVR_STAT_OK BIT(8) +/** 10BASE-T1L Local Receiver Status OK */ +#define MDIO_PMA_B10L_LINK_STAT_LOC_RCVR_STAT_OK_LL BIT(7) +/** 10BASE-T1L Local Receiver Status OK */ +#define MDIO_PMA_B10L_LINK_STAT_LOC_RCVR_STAT_OK BIT(6) +/** 10BASE-T1L Descrambler Status OK Latch Low */ +#define MDIO_PMA_B10L_LINK_STAT_DSCR_STAT_OK_LL BIT(5) +/** 10BASE-T1L Descrambler Status OK */ +#define MDIO_PMA_B10L_LINK_STAT_DSCR_STAT_OK BIT(4) +/** 10BASE-T1L Link Status OK Latch Low */ +#define MDIO_PMA_B10L_LINK_STAT_LINK_STAT_OK_LL BIT(1) +/** 10BASE-T1L Link Status OK */ +#define MDIO_PMA_B10L_LINK_STAT_LINK_STAT_OK BIT(0) + +/* 10BASE-T1L PCS control */ +/** 10BASE-T1L PCS Loopback Enable */ +#define MDIO_PCS_B10L_CTRL_LB_PCS_EN BIT(14) + +/* 10BASE-T1L PCS status */ +/** 10BASE-T1L PCS Descrambler Status */ +#define MDIO_PCS_B10L_STAT_DSCR_STAT_OK_LL BIT(2) + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_NET_MDIO_H_ */ diff --git a/include/zephyr/net/mqtt.h b/include/zephyr/net/mqtt.h index ecdefea120b..906cd8f6be6 100644 --- a/include/zephyr/net/mqtt.h +++ b/include/zephyr/net/mqtt.h @@ -348,13 +348,13 @@ struct mqtt_sec_config { /** Indicates the list of ciphers to be used for the session. * May be NULL to use the default ciphers. */ - int *cipher_list; + const int *cipher_list; /** Indicates the number of entries in the sec tag list. */ uint32_t sec_tag_count; /** Indicates the list of security tags to be used for the session. */ - sec_tag_t *sec_tag_list; + const sec_tag_t *sec_tag_list; /** Indicates the preference for enabling TLS session caching. */ int session_cache; diff --git a/include/zephyr/net/net_context.h b/include/zephyr/net/net_context.h index 7ab30dd0cb1..ea116a24846 100644 --- a/include/zephyr/net/net_context.h +++ b/include/zephyr/net/net_context.h @@ -322,6 +322,15 @@ __net_socket struct net_context { #endif #if defined(CONFIG_NET_CONTEXT_DSCP_ECN) uint8_t dscp_ecn; +#endif +#if defined(CONFIG_NET_CONTEXT_REUSEADDR) + bool reuseaddr; +#endif +#if defined(CONFIG_NET_CONTEXT_REUSEPORT) + bool reuseport; +#endif +#if defined(CONFIG_NET_IPV4_MAPPING_TO_IPV6) + bool ipv6_v6only; #endif } options; @@ -663,6 +672,23 @@ static inline void net_context_set_iface(struct net_context *context, context->iface = net_if_get_by_iface(iface); } +/** + * @brief Bind network interface to this context. + * + * @details This function binds network interface to this context. + * + * @param context Network context. + * @param iface Network interface. + */ +static inline void net_context_bind_iface(struct net_context *context, + struct net_if *iface) +{ + NET_ASSERT(iface); + + context->flags |= NET_CONTEXT_BOUND_TO_IFACE; + net_context_set_iface(context, iface); +} + static inline uint8_t net_context_get_ipv4_ttl(struct net_context *context) { return context->ipv4_ttl; @@ -1073,6 +1099,9 @@ enum net_context_option { NET_OPT_RCVBUF = 6, NET_OPT_SNDBUF = 7, NET_OPT_DSCP_ECN = 8, + NET_OPT_REUSEADDR = 9, + NET_OPT_REUSEPORT = 10, + NET_OPT_IPV6_V6ONLY = 11, }; /** diff --git a/include/zephyr/net/net_if.h b/include/zephyr/net/net_if.h index 92a59ad3b73..788c3316391 100644 --- a/include/zephyr/net/net_if.h +++ b/include/zephyr/net/net_if.h @@ -106,7 +106,7 @@ struct net_if_mcast_addr { /** * @brief Network Interface IPv6 prefixes * - * Stores the multicast IP addresses assigned to this network interface. + * Stores the IPV6 prefixes assigned to this network interface. */ struct net_if_ipv6_prefix { /** Prefix lifetime */ @@ -872,6 +872,15 @@ static inline bool net_if_is_ip_offloaded(struct net_if *iface) #endif } +/** + * @brief Return offload status of a given network interface. + * + * @param iface Network interface + * + * @return True if IP or socket offloading is active, false otherwise. + */ +bool net_if_is_offloaded(struct net_if *iface); + /** * @brief Return the IP offload plugin * @@ -3013,6 +3022,20 @@ struct net_if_api { #define NET_DEVICE_DT_INST_OFFLOAD_DEFINE(inst, ...) \ NET_DEVICE_DT_OFFLOAD_DEFINE(DT_DRV_INST(inst), __VA_ARGS__) +/** + * @brief Count the number of network interfaces. + * + * @param[out] _dst Pointer to location where result is written. + */ +#define NET_IFACE_COUNT(_dst) \ + do { \ + extern struct net_if _net_if_list_start[]; \ + extern struct net_if _net_if_list_end[]; \ + *(_dst) = ((uintptr_t)_net_if_list_end - \ + (uintptr_t)_net_if_list_start) / \ + sizeof(struct net_if); \ + } while (0) + #ifdef __cplusplus } #endif diff --git a/include/zephyr/net/net_ip.h b/include/zephyr/net/net_ip.h index 6c78428c1c7..b392184a815 100644 --- a/include/zephyr/net/net_ip.h +++ b/include/zephyr/net/net_ip.h @@ -423,11 +423,11 @@ enum net_priority { NET_PRIORITY_BK = 1, /**< Background (lowest) */ NET_PRIORITY_BE = 0, /**< Best effort (default) */ NET_PRIORITY_EE = 2, /**< Excellent effort */ - NET_PRIORITY_CA = 3, /**< Critical applications (highest) */ + NET_PRIORITY_CA = 3, /**< Critical applications */ NET_PRIORITY_VI = 4, /**< Video, < 100 ms latency and jitter */ NET_PRIORITY_VO = 5, /**< Voice, < 10 ms latency and jitter */ NET_PRIORITY_IC = 6, /**< Internetwork control */ - NET_PRIORITY_NC = 7 /**< Network control */ + NET_PRIORITY_NC = 7 /**< Network control (highest) */ } __packed; #define NET_MAX_PRIORITIES 8 /* How many priority values there are */ @@ -1239,6 +1239,39 @@ static inline void net_ipv6_addr_create_ll_allrouters_mcast(struct in6_addr *add net_ipv6_addr_create(addr, 0xff02, 0, 0, 0, 0, 0, 0, 0x0002); } +/** + * @brief Create IPv4 mapped IPv6 address + * + * @param addr4 IPv4 address + * @param addr6 IPv6 address to be created + */ +static inline void net_ipv6_addr_create_v4_mapped(const struct in_addr *addr4, + struct in6_addr *addr6) +{ + net_ipv6_addr_create(addr6, 0, 0, 0, 0, 0, 0xffff, + ntohs(addr4->s4_addr16[0]), + ntohs(addr4->s4_addr16[1])); +} + +/** + * @brief Is the IPv6 address an IPv4 mapped one. The v4 mapped addresses + * look like \::ffff:a.b.c.d + * + * @param addr IPv6 address + * + * @return True if IPv6 address is a IPv4 mapped address, False otherwise. + */ +static inline bool net_ipv6_addr_is_v4_mapped(const struct in6_addr *addr) +{ + if (UNALIGNED_GET(&addr->s6_addr32[0]) == 0 && + UNALIGNED_GET(&addr->s6_addr32[1]) == 0 && + UNALIGNED_GET(&addr->s6_addr16[5]) == 0xffff) { + return true; + } + + return false; +} + /** * @brief Create IPv6 address interface identifier * diff --git a/include/zephyr/net/net_pkt.h b/include/zephyr/net/net_pkt.h index 199f78d2361..c5878213a02 100644 --- a/include/zephyr/net/net_pkt.h +++ b/include/zephyr/net/net_pkt.h @@ -151,16 +151,7 @@ struct net_pkt { #endif uint8_t overwrite : 1; /* Is packet content being overwritten? */ - uint8_t sent_or_eof : 1; /* For outgoing packet: is this sent or not - * For incoming packet of a socket: last - * packet before EOF - * Used only if defined(CONFIG_NET_TCP) - */ - uint8_t pkt_queued : 1; /* For outgoing packet: is this packet - * queued to be sent but has not reached - * the driver yet. - * Used only if defined(CONFIG_NET_TCP) - */ + uint8_t eof : 1; /* Last packet before EOF */ uint8_t ptp_pkt : 1; /* For outgoing packet: is this packet * a L2 PTP packet. * Used only if defined (CONFIG_NET_L2_PTP) @@ -203,7 +194,12 @@ struct net_pkt { uint8_t l2_processed : 1; /* Set to 1 if this packet has already been * processed by the L2 */ - + uint8_t chksum_done : 1; /* Checksum has already been computed for + * the packet. + */ +#if defined(CONFIG_NET_IP_FRAGMENT) + uint8_t ip_reassembled : 1; /* Packet is a reassembled IP packet. */ +#endif /* bitfield byte alignment boundary */ #if defined(CONFIG_NET_IP) @@ -228,7 +224,7 @@ struct net_pkt { #endif }; -#if defined(CONFIG_NET_IPV4_FRAGMENT) || defined(CONFIG_NET_IPV6_FRAGMENT) +#if defined(CONFIG_NET_IP_FRAGMENT) union { #if defined(CONFIG_NET_IPV4_FRAGMENT) struct { @@ -244,7 +240,7 @@ struct net_pkt { } ipv6_fragment; #endif /* CONFIG_NET_IPV6_FRAGMENT */ }; -#endif /* CONFIG_NET_IPV4_FRAGMENT || CONFIG_NET_IPV6_FRAGMENT */ +#endif /* CONFIG_NET_IP_FRAGMENT */ #if defined(CONFIG_NET_IPV6) /* Where is the start of the last header before payload data @@ -407,6 +403,17 @@ static inline void net_pkt_set_l2_processed(struct net_pkt *pkt, pkt->l2_processed = is_l2_processed; } +static inline bool net_pkt_is_chksum_done(struct net_pkt *pkt) +{ + return !!(pkt->chksum_done); +} + +static inline void net_pkt_set_chksum_done(struct net_pkt *pkt, + bool is_chksum_done) +{ + pkt->chksum_done = is_chksum_done; +} + static inline uint8_t net_pkt_ip_hdr_len(struct net_pkt *pkt) { #if defined(CONFIG_NET_IP) @@ -455,26 +462,6 @@ static inline void net_pkt_set_ip_ecn(struct net_pkt *pkt, uint8_t ecn) #endif } -static inline uint8_t net_pkt_sent(struct net_pkt *pkt) -{ - return pkt->sent_or_eof; -} - -static inline void net_pkt_set_sent(struct net_pkt *pkt, bool sent) -{ - pkt->sent_or_eof = sent; -} - -static inline uint8_t net_pkt_queued(struct net_pkt *pkt) -{ - return pkt->pkt_queued; -} - -static inline void net_pkt_set_queued(struct net_pkt *pkt, bool send) -{ - pkt->pkt_queued = send; -} - static inline uint8_t net_pkt_tcp_1st_msg(struct net_pkt *pkt) { #if defined(CONFIG_NET_TCP) @@ -494,34 +481,25 @@ static inline void net_pkt_set_tcp_1st_msg(struct net_pkt *pkt, bool is_1st) #endif } -#if defined(CONFIG_NET_SOCKETS) static inline uint8_t net_pkt_eof(struct net_pkt *pkt) { - return pkt->sent_or_eof; + return pkt->eof; } static inline void net_pkt_set_eof(struct net_pkt *pkt, bool eof) { - pkt->sent_or_eof = eof; + pkt->eof = eof; } -#endif -#if defined(CONFIG_NET_ROUTE) static inline bool net_pkt_forwarding(struct net_pkt *pkt) { - return pkt->forwarding; + return !!(pkt->forwarding); } static inline void net_pkt_set_forwarding(struct net_pkt *pkt, bool forward) { pkt->forwarding = forward; } -#else -static inline bool net_pkt_forwarding(struct net_pkt *pkt) -{ - return false; -} -#endif #if defined(CONFIG_NET_IPV4) static inline uint8_t net_pkt_ipv4_ttl(struct net_pkt *pkt) @@ -860,6 +838,33 @@ static inline void net_pkt_set_ipv6_fragment_id(struct net_pkt *pkt, } #endif /* CONFIG_NET_IPV6_FRAGMENT */ +#if defined(CONFIG_NET_IP_FRAGMENT) +static inline bool net_pkt_is_ip_reassembled(struct net_pkt *pkt) +{ + return !!(pkt->ip_reassembled); +} + +static inline void net_pkt_set_ip_reassembled(struct net_pkt *pkt, + bool reassembled) +{ + pkt->ip_reassembled = reassembled; +} +#else /* CONFIG_NET_IP_FRAGMENT */ +static inline bool net_pkt_is_ip_reassembled(struct net_pkt *pkt) +{ + ARG_UNUSED(pkt); + + return false; +} + +static inline void net_pkt_set_ip_reassembled(struct net_pkt *pkt, + bool reassembled) +{ + ARG_UNUSED(pkt); + ARG_UNUSED(reassembled); +} +#endif /* CONFIG_NET_IP_FRAGMENT */ + static inline uint8_t net_pkt_priority(struct net_pkt *pkt) { return pkt->priority; @@ -965,6 +970,16 @@ static inline void net_pkt_set_timestamp(struct net_pkt *pkt, pkt->timestamp.second = timestamp->second; pkt->timestamp.nanosecond = timestamp->nanosecond; } + +static inline net_time_t net_pkt_timestamp_ns(struct net_pkt *pkt) +{ + return net_ptp_time_to_ns(&pkt->timestamp); +} + +static inline void net_pkt_set_timestamp_ns(struct net_pkt *pkt, net_time_t timestamp) +{ + pkt->timestamp = ns_to_net_ptp_time(timestamp); +} #else static inline struct net_ptp_time *net_pkt_timestamp(struct net_pkt *pkt) { @@ -979,6 +994,19 @@ static inline void net_pkt_set_timestamp(struct net_pkt *pkt, ARG_UNUSED(pkt); ARG_UNUSED(timestamp); } + +static inline net_time_t net_pkt_timestamp_ns(struct net_pkt *pkt) +{ + ARG_UNUSED(pkt); + + return 0; +} + +static inline void net_pkt_set_timestamp_ns(struct net_pkt *pkt, net_time_t timestamp) +{ + ARG_UNUSED(pkt); + ARG_UNUSED(timestamp); +} #endif /* CONFIG_NET_PKT_TIMESTAMP || CONFIG_NET_PKT_TXTIME */ #if defined(CONFIG_NET_PKT_RXTIME_STATS) || defined(CONFIG_NET_PKT_TXTIME_STATS) @@ -1009,7 +1037,7 @@ static inline void net_pkt_set_create_time(struct net_pkt *pkt, #endif /* CONFIG_NET_PKT_RXTIME_STATS || CONFIG_NET_PKT_TXTIME_STATS */ /** - * @deprecated Use @ref net_pkt_timestamp instead. + * @deprecated Use @ref net_pkt_timestamp or @ref net_pkt_timestamp_ns instead. */ static inline uint64_t net_pkt_txtime(struct net_pkt *pkt) { @@ -1023,7 +1051,8 @@ static inline uint64_t net_pkt_txtime(struct net_pkt *pkt) } /** - * @deprecated Use @ref net_pkt_set_timestamp instead. + * @deprecated Use @ref net_pkt_set_timestamp or @ref net_pkt_set_timestamp_ns + * instead. */ static inline void net_pkt_set_txtime(struct net_pkt *pkt, uint64_t txtime) { @@ -1155,7 +1184,7 @@ static inline void net_pkt_set_ll_proto_type(struct net_pkt *pkt, uint16_t type) #if defined(CONFIG_NET_IPV4_AUTO) static inline bool net_pkt_ipv4_auto(struct net_pkt *pkt) { - return pkt->ipv4_auto_arp_msg; + return !!(pkt->ipv4_auto_arp_msg); } static inline void net_pkt_set_ipv4_auto(struct net_pkt *pkt, @@ -1182,7 +1211,7 @@ static inline void net_pkt_set_ipv4_auto(struct net_pkt *pkt, #if defined(CONFIG_NET_LLDP) static inline bool net_pkt_is_lldp(struct net_pkt *pkt) { - return pkt->lldp_pkt; + return !!(pkt->lldp_pkt); } static inline void net_pkt_set_lldp(struct net_pkt *pkt, bool is_lldp) @@ -1207,7 +1236,7 @@ static inline void net_pkt_set_lldp(struct net_pkt *pkt, bool is_lldp) #if defined(CONFIG_NET_L2_PPP) static inline bool net_pkt_is_ppp(struct net_pkt *pkt) { - return pkt->ppp_msg; + return !!(pkt->ppp_msg); } static inline void net_pkt_set_ppp(struct net_pkt *pkt, @@ -1262,7 +1291,7 @@ static inline void net_pkt_set_overwrite(struct net_pkt *pkt, bool overwrite) static inline bool net_pkt_is_being_overwritten(struct net_pkt *pkt) { - return pkt->overwrite; + return !!(pkt->overwrite); } #ifdef CONFIG_NET_PKT_FILTER diff --git a/include/zephyr/net/net_time.h b/include/zephyr/net/net_time.h index 6277ea994c8..3e37ccacedb 100644 --- a/include/zephyr/net/net_time.h +++ b/include/zephyr/net/net_time.h @@ -12,13 +12,17 @@ * Inspired by * https://github.com/torvalds/linux/blob/master/include/linux/ktime.h and * https://github.com/torvalds/linux/blob/master/[tools/]include/linux/time64.h + * + * @defgroup net_time Network time representation. + * @ingroup networking + * @{ */ #ifndef ZEPHYR_INCLUDE_NET_NET_TIME_H_ #define ZEPHYR_INCLUDE_NET_NET_TIME_H_ /* Include required for NSEC_PER_* constants. */ -#include "zephyr/sys_clock.h" +#include #ifdef __cplusplus extern "C" { @@ -112,4 +116,8 @@ typedef int64_t net_time_t; } #endif +/** + * @} + */ + #endif /* ZEPHYR_INCLUDE_NET_NET_TIME_H_ */ diff --git a/include/zephyr/net/openthread.h b/include/zephyr/net/openthread.h index 34aa78df824..81c2629d6c0 100644 --- a/include/zephyr/net/openthread.h +++ b/include/zephyr/net/openthread.h @@ -5,16 +5,16 @@ */ /** @file - * @brief OpenThread l2 stack public header + * @brief OpenThread L2 stack public header */ #ifndef ZEPHYR_INCLUDE_NET_OPENTHREAD_H_ #define ZEPHYR_INCLUDE_NET_OPENTHREAD_H_ /** - * @brief OpenThread l2 stack api - * @defgroup OpenThread l2 layer - * @ingroup networking + * @brief OpenThread Layer 2 abstraction layer + * @defgroup openthread OpenThread L2 abstraction layer + * @ingroup ieee802154 * @{ */ diff --git a/include/zephyr/net/ppp.h b/include/zephyr/net/ppp.h index 4067d37f4cc..a72d4f1feac 100644 --- a/include/zephyr/net/ppp.h +++ b/include/zephyr/net/ppp.h @@ -483,9 +483,6 @@ struct ppp_context { /** This tells how many network protocols are up */ int network_protos_up; - /** Is network carrier up */ - uint16_t is_net_carrier_up : 1; - /** Is PPP ready to receive packets */ uint16_t is_ready_to_serve : 1; diff --git a/include/zephyr/net/socket.h b/include/zephyr/net/socket.h index 50070f0c7a5..f32753a7952 100644 --- a/include/zephyr/net/socket.h +++ b/include/zephyr/net/socket.h @@ -996,7 +996,11 @@ static inline char *inet_ntop(sa_family_t family, const void *src, char *dst, #define EAI_FAMILY DNS_EAI_FAMILY #endif /* defined(CONFIG_NET_SOCKETS_POSIX_NAMES) */ +#if defined(CONFIG_NET_INTERFACE_NAME) +#define IFNAMSIZ CONFIG_NET_INTERFACE_NAME_LEN +#else #define IFNAMSIZ Z_DEVICE_MAX_NAME_LEN +#endif /** Interface description structure */ struct ifreq { @@ -1010,7 +1014,7 @@ struct ifreq { /** sockopt: Recording debugging information (ignored, for compatibility) */ #define SO_DEBUG 1 -/** sockopt: address reuse (ignored, for compatibility) */ +/** sockopt: address reuse */ #define SO_REUSEADDR 2 /** sockopt: Type of the socket */ #define SO_TYPE 3 @@ -1021,7 +1025,7 @@ struct ifreq { /** sockopt: Transmission of broadcast messages is supported (ignored, for compatibility) */ #define SO_BROADCAST 6 -/** sockopt: Size of socket socket send buffer (ignored, for compatibility) */ +/** sockopt: Size of socket send buffer */ #define SO_SNDBUF 7 /** sockopt: Size of socket recv buffer */ #define SO_RCVBUF 8 @@ -1032,7 +1036,7 @@ struct ifreq { #define SO_OOBINLINE 10 /** sockopt: Socket lingers on close (ignored, for compatibility) */ #define SO_LINGER 13 -/** sockopt: Allow multiple sockets to reuse a single port (ignored, for compatibility) */ +/** sockopt: Allow multiple sockets to reuse a single port */ #define SO_REUSEPORT 15 /** sockopt: Receive low watermark (ignored, for compatibility) */ @@ -1102,6 +1106,12 @@ struct net_socket_register { bool is_offloaded; bool (*is_supported)(int family, int type, int proto); int (*handler)(int family, int type, int proto); +#if defined(CONFIG_NET_SOCKETS_OBJ_CORE) + /* Store also the name of the socket type in order to be able to + * print it later. + */ + const char * const name; +#endif }; #define NET_SOCKET_DEFAULT_PRIO CONFIG_NET_SOCKETS_PRIORITY_DEFAULT @@ -1109,6 +1119,15 @@ struct net_socket_register { #define NET_SOCKET_GET_NAME(socket_name, prio) \ __net_socket_register_##prio##_##socket_name +#if defined(CONFIG_NET_SOCKETS_OBJ_CORE) +#define K_OBJ_TYPE_SOCK K_OBJ_TYPE_ID_GEN("SOCK") + +#define NET_SOCKET_REGISTER_NAME(_name) \ + .name = STRINGIFY(_name), +#else +#define NET_SOCKET_REGISTER_NAME(_name) +#endif + #define _NET_SOCKET_REGISTER(socket_name, prio, _family, _is_supported, _handler, _is_offloaded) \ static const STRUCT_SECTION_ITERABLE(net_socket_register, \ NET_SOCKET_GET_NAME(socket_name, prio)) = { \ @@ -1116,6 +1135,7 @@ struct net_socket_register { .is_offloaded = _is_offloaded, \ .is_supported = _is_supported, \ .handler = _handler, \ + NET_SOCKET_REGISTER_NAME(socket_name) \ } #define NET_SOCKET_REGISTER(socket_name, prio, _family, _is_supported, _handler) \ diff --git a/include/zephyr/net/socketcan.h b/include/zephyr/net/socketcan.h index 29ec5b3638d..c4916487d99 100644 --- a/include/zephyr/net/socketcan.h +++ b/include/zephyr/net/socketcan.h @@ -49,7 +49,7 @@ enum { #define CAN_MTU (sizeof(struct socketcan_frame)) #endif /* !CONFIG_CAN_FD_MODE */ -/* CAN-FD specific flags from Linux Kernel (include/uapi/linux/can.h) */ +/* CAN FD specific flags from Linux Kernel (include/uapi/linux/can.h) */ #define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */ #define CANFD_ESI 0x02 /* error state indicator of the transmitting node */ #define CANFD_FDF 0x04 /* mark CAN FD for dual use of struct canfd_frame */ diff --git a/include/zephyr/net/socketcan_utils.h b/include/zephyr/net/socketcan_utils.h index 24a95776e0b..22364cd328b 100644 --- a/include/zephyr/net/socketcan_utils.h +++ b/include/zephyr/net/socketcan_utils.h @@ -44,7 +44,11 @@ static inline void socketcan_to_can_frame(const struct socketcan_frame *sframe, zframe->flags |= (sframe->flags & CANFD_BRS) != 0 ? CAN_FRAME_BRS : 0; zframe->id = sframe->can_id & BIT_MASK(29); zframe->dlc = can_bytes_to_dlc(sframe->len); - memcpy(zframe->data, sframe->data, MIN(sizeof(sframe->data), sizeof(zframe->data))); + + if ((zframe->flags & CAN_FRAME_RTR) == 0U) { + memcpy(zframe->data, sframe->data, + MIN(sframe->len, MIN(sizeof(sframe->data), sizeof(zframe->data)))); + } } /** @@ -71,7 +75,10 @@ static inline void socketcan_from_can_frame(const struct can_frame *zframe, sframe->flags |= CANFD_BRS; } - memcpy(sframe->data, zframe->data, MIN(sizeof(zframe->data), sizeof(sframe->data))); + if ((zframe->flags & CAN_FRAME_RTR) == 0U) { + memcpy(sframe->data, zframe->data, + MIN(sframe->len, MIN(sizeof(zframe->data), sizeof(sframe->data)))); + } } /** diff --git a/include/zephyr/net/tftp.h b/include/zephyr/net/tftp.h index 791dcbf6c8e..61db441e548 100644 --- a/include/zephyr/net/tftp.h +++ b/include/zephyr/net/tftp.h @@ -6,7 +6,10 @@ /** @file tftp.h * - * @brief Zephyr TFTP Implementation + * @defgroup tftp_client TFTP Client library + * @ingroup networking + * @{ + * @brief TFTP Client Implementation */ #ifndef ZEPHYR_INCLUDE_NET_TFTP_H_ @@ -33,29 +36,37 @@ extern "C" { */ #define TFTP_HEADER_SIZE 4 -/* Maximum amount of data that can be sent or received */ +/** Maximum amount of data that can be sent or received */ #define TFTPC_MAX_BUF_SIZE (TFTP_BLOCK_SIZE + TFTP_HEADER_SIZE) -/* TFTP Client Error codes. */ -#define TFTPC_SUCCESS 0 -#define TFTPC_DUPLICATE_DATA -1 -#define TFTPC_BUFFER_OVERFLOW -2 -#define TFTPC_UNKNOWN_FAILURE -3 -#define TFTPC_REMOTE_ERROR -4 -#define TFTPC_RETRIES_EXHAUSTED -5 +/** + * @name TFTP client error codes. + * @{ + */ +#define TFTPC_SUCCESS 0 /**< Success. */ +#define TFTPC_DUPLICATE_DATA -1 /**< Duplicate data received. */ +#define TFTPC_BUFFER_OVERFLOW -2 /**< User buffer is too small. */ +#define TFTPC_UNKNOWN_FAILURE -3 /**< Unknown failure. */ +#define TFTPC_REMOTE_ERROR -4 /**< Remote server error. */ +#define TFTPC_RETRIES_EXHAUSTED -5 /**< Retries exhausted. */ +/** + * @} + */ /** * @brief TFTP Asynchronous Events notified to the application from the module * through the callback registered by the application. */ enum tftp_evt_type { - /** DATA event when data is received from remote server. + /** + * DATA event when data is received from remote server. * * @note DATA event structure contains payload data and size. */ TFTP_EVT_DATA, - /** ERROR event when error is received from remote server. + /** + * ERROR event when error is received from remote server. * * @note ERROR event structure contains error code and message. */ @@ -123,17 +134,18 @@ struct tftpc { uint8_t tftp_buf[TFTPC_MAX_BUF_SIZE]; }; -/* @brief This function gets data from a "file" on the remote server. +/** + * @brief This function gets data from a "file" on the remote server. * * @param client Client information of type @ref tftpc. * @param remote_file Name of the remote file to get. * @param mode TFTP Client "mode" setting. * - * @return The size of data being received if the operation completed successfully. - * TFTPC_BUFFER_OVERFLOW if the file is larger than the user buffer. - * TFTPC_REMOTE_ERROR if the server failed to process our request. - * TFTPC_RETRIES_EXHAUSTED if the client timed out waiting for server. - * -EINVAL if `client` is NULL. + * @retval The size of data being received if the operation completed successfully. + * @retval TFTPC_BUFFER_OVERFLOW if the file is larger than the user buffer. + * @retval TFTPC_REMOTE_ERROR if the server failed to process our request. + * @retval TFTPC_RETRIES_EXHAUSTED if the client timed out waiting for server. + * @retval -EINVAL if `client` is NULL. * * @note This function blocks until the transfer is completed or network error happens. The * integrity of the `client` structure must be ensured until the function returns. @@ -141,7 +153,8 @@ struct tftpc { int tftp_get(struct tftpc *client, const char *remote_file, const char *mode); -/* @brief This function puts data to a "file" on the remote server. +/** + * @brief This function puts data to a "file" on the remote server. * * @param client Client information of type @ref tftpc. * @param remote_file Name of the remote file to put. @@ -149,10 +162,10 @@ int tftp_get(struct tftpc *client, * @param user_buf Data buffer containing the data to put. * @param user_buf_size Length of the data to put. * - * @return The size of data being sent if the operation completed successfully. - * TFTPC_REMOTE_ERROR if the server failed to process our request. - * TFTPC_RETRIES_EXHAUSTED if the client timed out waiting for server. - * -EINVAL if `client` or `user_buf` is NULL or if `user_buf_size` is zero. + * @retval The size of data being sent if the operation completed successfully. + * @retval TFTPC_REMOTE_ERROR if the server failed to process our request. + * @retval TFTPC_RETRIES_EXHAUSTED if the client timed out waiting for server. + * @retval -EINVAL if `client` or `user_buf` is NULL or if `user_buf_size` is zero. * * @note This function blocks until the transfer is completed or network error happens. The * integrity of the `client` structure must be ensured until the function returns. @@ -166,3 +179,5 @@ int tftp_put(struct tftpc *client, #endif #endif /* ZEPHYR_INCLUDE_NET_TFTP_H_ */ + +/** @} */ diff --git a/include/zephyr/net/tls_credentials.h b/include/zephyr/net/tls_credentials.h index 8436774ec65..77e2a230852 100644 --- a/include/zephyr/net/tls_credentials.h +++ b/include/zephyr/net/tls_credentials.h @@ -66,6 +66,8 @@ enum tls_credential_type { * - TLS_CREDENTIAL_PSK with TLS_CREDENTIAL_PSK_ID. * Such pairs of credentials must be assigned the same secure tag to be * correctly handled in the system. + * + * @note Negative values are reserved for internal use. */ typedef int sec_tag_t; diff --git a/include/zephyr/net/wifi.h b/include/zephyr/net/wifi.h index 294fdc53c5d..5c7d5b493fa 100644 --- a/include/zephyr/net/wifi.h +++ b/include/zephyr/net/wifi.h @@ -27,6 +27,10 @@ #define WIFI_LISTEN_INTERVAL_MIN 0 #define WIFI_LISTEN_INTERVAL_MAX 65535 +#ifdef __cplusplus +extern "C" { +#endif + /** IEEE 802.11 security types. */ enum wifi_security_type { /** No security. */ @@ -52,7 +56,7 @@ enum wifi_security_type { }; /** Helper function to get user-friendly security type name. */ -const char * const wifi_security_txt(enum wifi_security_type security); +const char *wifi_security_txt(enum wifi_security_type security); /** IEEE 802.11w - Management frame protection. */ enum wifi_mfp_options { @@ -69,7 +73,7 @@ enum wifi_mfp_options { }; /** Helper function to get user-friendly MFP name.*/ -const char * const wifi_mfp_txt(enum wifi_mfp_options mfp); +const char *wifi_mfp_txt(enum wifi_mfp_options mfp); /** * @brief IEEE 802.11 operational frequency bands (not exhaustive). @@ -91,7 +95,7 @@ enum wifi_frequency_bands { }; /** Helper function to get user-friendly frequency band name. */ -const char * const wifi_band_txt(enum wifi_frequency_bands band); +const char *wifi_band_txt(enum wifi_frequency_bands band); #define WIFI_SSID_MAX_LEN 32 #define WIFI_PSK_MIN_LEN 8 @@ -135,7 +139,7 @@ enum wifi_iface_state { }; /** Helper function to get user-friendly interface state name. */ -const char * const wifi_state_txt(enum wifi_iface_state state); +const char *wifi_state_txt(enum wifi_iface_state state); /** Wi-Fi interface modes. * @@ -161,7 +165,7 @@ enum wifi_iface_mode { }; /** Helper function to get user-friendly interface mode name. */ -const char * const wifi_mode_txt(enum wifi_iface_mode mode); +const char *wifi_mode_txt(enum wifi_iface_mode mode); /** Wi-Fi link operating modes * @@ -193,7 +197,7 @@ enum wifi_link_mode { }; /** Helper function to get user-friendly link mode name. */ -const char * const wifi_link_mode_txt(enum wifi_link_mode link_mode); +const char *wifi_link_mode_txt(enum wifi_link_mode link_mode); /** Wi-Fi scanning types. */ enum wifi_scan_type { @@ -212,7 +216,7 @@ enum wifi_ps { }; /** Helper function to get user-friendly ps name. */ -const char * const wifi_ps_txt(enum wifi_ps ps_name); +const char *wifi_ps_txt(enum wifi_ps ps_name); /** Wi-Fi power save modes. */ enum wifi_ps_mode { @@ -226,7 +230,7 @@ enum wifi_ps_mode { }; /** Helper function to get user-friendly ps mode name. */ -const char * const wifi_ps_mode_txt(enum wifi_ps_mode ps_mode); +const char *wifi_ps_mode_txt(enum wifi_ps_mode ps_mode); /* Interface index Min and Max values */ #define WIFI_INTERFACE_INDEX_MIN 1 @@ -269,7 +273,7 @@ enum wifi_twt_operation { }; /** Helper function to get user-friendly twt operation name. */ -const char * const wifi_twt_operation_txt(enum wifi_twt_operation twt_operation); +const char *wifi_twt_operation_txt(enum wifi_twt_operation twt_operation); /** Wi-Fi Target Wake Time (TWT) negotiation types. */ enum wifi_twt_negotiation_type { @@ -282,7 +286,7 @@ enum wifi_twt_negotiation_type { }; /** Helper function to get user-friendly twt negotiation type name. */ -const char * const wifi_twt_negotiation_type_txt(enum wifi_twt_negotiation_type twt_negotiation); +const char *wifi_twt_negotiation_type_txt(enum wifi_twt_negotiation_type twt_negotiation); /** Wi-Fi Target Wake Time (TWT) setup commands. */ enum wifi_twt_setup_cmd { @@ -305,7 +309,7 @@ enum wifi_twt_setup_cmd { }; /** Helper function to get user-friendly twt setup cmd name. */ -const char * const wifi_twt_setup_cmd_txt(enum wifi_twt_setup_cmd twt_setup); +const char *wifi_twt_setup_cmd_txt(enum wifi_twt_setup_cmd twt_setup); /** Wi-Fi Target Wake Time (TWT) negotiation status. */ enum wifi_twt_setup_resp_status { @@ -397,7 +401,7 @@ enum wifi_ps_wakeup_mode { }; /** Helper function to get user-friendly ps wakeup mode name. */ -const char * const wifi_ps_wakeup_mode_txt(enum wifi_ps_wakeup_mode ps_wakeup_mode); +const char *wifi_ps_wakeup_mode_txt(enum wifi_ps_wakeup_mode ps_wakeup_mode); /** Wi-Fi power save error codes. */ enum wifi_config_ps_param_fail_reason { @@ -444,6 +448,10 @@ static inline const char *wifi_ps_get_config_err_code_str(int16_t err_no) return ""; } +#ifdef __cplusplus +} +#endif + /** * @} */ diff --git a/include/zephyr/net/wifi_mgmt.h b/include/zephyr/net/wifi_mgmt.h index 8f1b145e233..78800f451e7 100644 --- a/include/zephyr/net/wifi_mgmt.h +++ b/include/zephyr/net/wifi_mgmt.h @@ -38,7 +38,7 @@ extern "C" { #ifdef CONFIG_WIFI_MGMT_SCAN_SSID_FILT_MAX #define WIFI_MGMT_SCAN_SSID_FILT_MAX CONFIG_WIFI_MGMT_SCAN_SSID_FILT_MAX #else -#define WIFI_MGMT_SCAN_SSID_FILT_MAX 0 +#define WIFI_MGMT_SCAN_SSID_FILT_MAX 1 #endif /* CONFIG_WIFI_MGMT_SCAN_SSID_FILT_MAX */ #ifdef CONFIG_WIFI_MGMT_SCAN_CHAN_MAX_MANUAL @@ -322,11 +322,11 @@ struct wifi_connect_req_params { /** SSID length */ uint8_t ssid_length; /* Max 32 */ /** Pre-shared key */ - uint8_t *psk; + const uint8_t *psk; /** Pre-shared key length */ uint8_t psk_length; /* Min 8 - Max 64 */ /** SAE password (same as PSK but with no length restrictions), optional */ - uint8_t *sae_password; + const uint8_t *sae_password; /** SAE password length */ uint8_t sae_password_length; /* No length restrictions */ /** Frequency band */ diff --git a/include/zephyr/net/wifi_utils.h b/include/zephyr/net/wifi_utils.h index c9ef9979f91..c16eef0e5b2 100644 --- a/include/zephyr/net/wifi_utils.h +++ b/include/zephyr/net/wifi_utils.h @@ -57,12 +57,9 @@ int wifi_utils_parse_scan_bands(char *scan_bands_str, uint8_t *band_map); /** - * @brief Convert a string containing a list of SSIDs to an array of SSID strings. + * @brief Append a string containing an SSID to an array of SSID strings. * - * @details The function will parse a string which specifies Wi-Fi SSIDs - * as a comma separated string and convert it to an array. - * - * @param scan_ssids_str List of SSIDs expressed as a comma separated list. + * @param scan_ssids_str string to be appended in the list of scanned SSIDs. * @param ssids Pointer to an array where the SSIDs pointers are to be stored. * @param num_ssids Maximum number of SSIDs that can be stored. * diff --git a/include/zephyr/pm/policy.h b/include/zephyr/pm/policy.h index b2e648b5ba6..e77004bbbe8 100644 --- a/include/zephyr/pm/policy.h +++ b/include/zephyr/pm/policy.h @@ -40,8 +40,10 @@ typedef void (*pm_policy_latency_changed_cb_t)(int32_t latency); * @note All fields in this structure are meant for private usage. */ struct pm_policy_latency_subscription { + /** @cond INTERNAL_HIDDEN */ sys_snode_t node; pm_policy_latency_changed_cb_t cb; + /** @endcond */ }; /** @@ -50,8 +52,10 @@ struct pm_policy_latency_subscription { * @note All fields in this structure are meant for private usage. */ struct pm_policy_latency_request { + /** @cond INTERNAL_HIDDEN */ sys_snode_t node; uint32_t value_us; + /** @endcond */ }; /** @@ -60,8 +64,10 @@ struct pm_policy_latency_request { * @note All fields in this structure are meant for private usage. */ struct pm_policy_event { + /** @cond INTERNAL_HIDDEN */ sys_snode_t node; uint32_t value_cyc; + /** @endcond */ }; /** @cond INTERNAL_HIDDEN */ diff --git a/include/zephyr/pm/state.h b/include/zephyr/pm/state.h index 1d21ffd997a..cc387879411 100644 --- a/include/zephyr/pm/state.h +++ b/include/zephyr/pm/state.h @@ -329,6 +329,7 @@ struct pm_state_info { } +#if defined(CONFIG_PM) || defined(__DOXYGEN__) /** * Obtain information about all supported states by a CPU. * @@ -343,6 +344,18 @@ uint8_t pm_state_cpu_get_all(uint8_t cpu, const struct pm_state_info **states); * @} */ +#else /* CONFIG_PM */ + +static inline uint8_t pm_state_cpu_get_all(uint8_t cpu, const struct pm_state_info **states) +{ + ARG_UNUSED(cpu); + ARG_UNUSED(states); + + return 0; +} + +#endif /* CONFIG_PM */ + #ifdef __cplusplus } #endif diff --git a/include/zephyr/posix/dirent.h b/include/zephyr/posix/dirent.h index 31c2a2cee4c..43c68983ebb 100644 --- a/include/zephyr/posix/dirent.h +++ b/include/zephyr/posix/dirent.h @@ -24,9 +24,9 @@ struct dirent { }; /* Directory related operations */ -extern DIR *opendir(const char *dirname); -extern int closedir(DIR *dirp); -extern struct dirent *readdir(DIR *dirp); +DIR *opendir(const char *dirname); +int closedir(DIR *dirp); +struct dirent *readdir(DIR *dirp); #ifdef __cplusplus } diff --git a/include/zephyr/posix/posix_types.h b/include/zephyr/posix/posix_types.h index ed56e78c225..73a7485f000 100644 --- a/include/zephyr/posix/posix_types.h +++ b/include/zephyr/posix/posix_types.h @@ -7,7 +7,7 @@ #ifndef ZEPHYR_INCLUDE_POSIX_TYPES_H_ #define ZEPHYR_INCLUDE_POSIX_TYPES_H_ -#ifndef CONFIG_ARCH_POSIX +#if !(defined(CONFIG_ARCH_POSIX) && defined(CONFIG_EXTERNAL_LIBC)) #include #endif diff --git a/include/zephyr/posix/pthread.h b/include/zephyr/posix/pthread.h index 45940123cf5..d978e914a5e 100644 --- a/include/zephyr/posix/pthread.h +++ b/include/zephyr/posix/pthread.h @@ -442,7 +442,9 @@ int pthread_attr_getstack(const pthread_attr_t *attr, void **stackaddr, size_t *stacksize); int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize); +#ifdef CONFIG_PTHREAD_IPC int pthread_once(pthread_once_t *once, void (*initFunc)(void)); +#endif void pthread_exit(void *retval); int pthread_join(pthread_t thread, void **status); int pthread_cancel(pthread_t pthread); diff --git a/include/zephyr/posix/sys/stat.h b/include/zephyr/posix/sys/stat.h index 01251c65ace..2d19df29700 100644 --- a/include/zephyr/posix/sys/stat.h +++ b/include/zephyr/posix/sys/stat.h @@ -114,7 +114,7 @@ struct stat { #define st_mtime st_mtim.tv_sec #define st_ctime st_ctim.tv_sec #if defined(__linux) && defined(__x86_64__) - __uint64_t __glibc_reserved[3]; + uint64_t __glibc_reserved[3]; #endif #else #if defined(__rtems__) diff --git a/include/zephyr/posix/sys/utsname.h b/include/zephyr/posix/sys/utsname.h index f00497f17f3..32046f431d8 100644 --- a/include/zephyr/posix/sys/utsname.h +++ b/include/zephyr/posix/sys/utsname.h @@ -13,7 +13,7 @@ extern "C" { struct utsname { char sysname[sizeof("Zephyr")]; char nodename[CONFIG_POSIX_UNAME_NODENAME_LEN + 1]; - char release[sizeof("99.99.99")]; + char release[sizeof("99.99.99-rc1")]; char version[CONFIG_POSIX_UNAME_VERSION_LEN + 1]; char machine[sizeof(CONFIG_ARCH)]; }; diff --git a/include/zephyr/posix/unistd.h b/include/zephyr/posix/unistd.h index ec8bf7e6adb..b55cf702fec 100644 --- a/include/zephyr/posix/unistd.h +++ b/include/zephyr/posix/unistd.h @@ -23,16 +23,16 @@ extern "C" { #ifdef CONFIG_POSIX_API /* File related operations */ -extern int close(int file); -extern ssize_t write(int file, const void *buffer, size_t count); -extern ssize_t read(int file, void *buffer, size_t count); -extern off_t lseek(int file, off_t offset, int whence); +int close(int file); +ssize_t write(int file, const void *buffer, size_t count); +ssize_t read(int file, void *buffer, size_t count); +off_t lseek(int file, off_t offset, int whence); /* File System related operations */ -extern int rename(const char *old, const char *newp); -extern int unlink(const char *path); -extern int stat(const char *path, struct stat *buf); -extern int mkdir(const char *path, mode_t mode); +int rename(const char *old, const char *newp); +int unlink(const char *path); +int stat(const char *path, struct stat *buf); +int mkdir(const char *path, mode_t mode); FUNC_NORETURN void _exit(int status); diff --git a/include/zephyr/random/rand32.h b/include/zephyr/random/rand32.h index 4bf39fe45de..cb9ef54ca63 100644 --- a/include/zephyr/random/rand32.h +++ b/include/zephyr/random/rand32.h @@ -1,86 +1,15 @@ /* * Copyright (c) 2013-2014 Wind River Systems, Inc. + * Copyright (c) 2023 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ -/** - * @file - * @brief Random number generator header file - * - * This header file declares prototypes for the kernel's random number - * generator APIs. - * - * Typically, a platform enables the appropriate source for the random - * number generation based on the hardware platform's capabilities or - * (for testing purposes only) enables the TEST_RANDOM_GENERATOR - * configuration option. - */ - #ifndef ZEPHYR_INCLUDE_RANDOM_RAND32_H_ #define ZEPHYR_INCLUDE_RANDOM_RAND32_H_ -#include -#include -#include - -/** - * @brief Random Function APIs - * @defgroup random_api Random Function APIs - * @ingroup crypto - * @{ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Return a 32-bit random value that should pass general - * randomness tests. - * - * @note The random value returned is not a cryptographically secure - * random number value. - * - * @return 32-bit random value. - */ -__syscall uint32_t sys_rand32_get(void); - -/** - * @brief Fill the destination buffer with random data values that should - * pass general randomness tests. - * - * @note The random values returned are not considered cryptographically - * secure random number values. - * - * @param [out] dst destination buffer to fill with random data. - * @param len size of the destination buffer. - * - */ -__syscall void sys_rand_get(void *dst, size_t len); - -/** - * @brief Fill the destination buffer with cryptographically secure - * random data values. - * - * @note If the random values requested do not need to be cryptographically - * secure then use sys_rand_get() instead. - * - * @param [out] dst destination buffer to fill. - * @param len size of the destination buffer. - * - * @return 0 if success, -EIO if entropy reseed error - * - */ -__syscall int sys_csrand_get(void *dst, size_t len); - -#ifdef __cplusplus -} -#endif +#include -/** - * @} - */ +#warning " is deprecated, include instead" -#include #endif /* ZEPHYR_INCLUDE_RANDOM_RAND32_H_ */ diff --git a/include/zephyr/random/random.h b/include/zephyr/random/random.h new file mode 100644 index 00000000000..e4b52f683aa --- /dev/null +++ b/include/zephyr/random/random.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Random number generator header file + * + * This header file declares prototypes for the kernel's random number + * generator APIs. + * + * Typically, a platform enables the appropriate source for the random + * number generation based on the hardware platform's capabilities or + * (for testing purposes only) enables the TEST_RANDOM_GENERATOR + * configuration option. + */ + +#ifndef ZEPHYR_INCLUDE_RANDOM_RANDOM_H_ +#define ZEPHYR_INCLUDE_RANDOM_RANDOM_H_ + +#include +#include +#include + +/** + * @brief Random Function APIs + * @defgroup random_api Random Function APIs + * @ingroup crypto + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Return a 32-bit random value that should pass general + * randomness tests. + * + * @note The random value returned is not a cryptographically secure + * random number value. + * + * @return 32-bit random value. + */ +__syscall uint32_t sys_rand32_get(void); + +/** + * @brief Fill the destination buffer with random data values that should + * pass general randomness tests. + * + * @note The random values returned are not considered cryptographically + * secure random number values. + * + * @param [out] dst destination buffer to fill with random data. + * @param len size of the destination buffer. + * + */ +__syscall void sys_rand_get(void *dst, size_t len); + +/** + * @brief Fill the destination buffer with cryptographically secure + * random data values. + * + * @note If the random values requested do not need to be cryptographically + * secure then use sys_rand_get() instead. + * + * @param [out] dst destination buffer to fill. + * @param len size of the destination buffer. + * + * @return 0 if success, -EIO if entropy reseed error + * + */ +__syscall int sys_csrand_get(void *dst, size_t len); + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#include +#endif /* ZEPHYR_INCLUDE_RANDOM_RANDOM_H_ */ diff --git a/include/zephyr/retention/blinfo.h b/include/zephyr/retention/blinfo.h new file mode 100644 index 00000000000..0ecd051771f --- /dev/null +++ b/include/zephyr/retention/blinfo.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Public API for boot mode interface + */ + +#ifndef ZEPHYR_INCLUDE_RETENTION_BLINFO_ +#define ZEPHYR_INCLUDE_RETENTION_BLINFO_ + +#include +#include +#include + +#if defined(CONFIG_RETENTION_BOOTLOADER_INFO_TYPE_MCUBOOT) +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Bootloader info interface + * @defgroup bootloader_info_interface Bootloader info interface + * @ingroup retention_api + * @{ + */ + +#if IS_ENABLED(CONFIG_RETENTION_BOOTLOADER_INFO_OUTPUT_FUNCTION) || defined(__DOXYGEN__) +/** + * @brief Returns bootinfo information. + * + * @param key The information to return (for MCUboot: minor TLV). + * @param val Where the return information will be placed. + * @param val_len_max The maximum size of the provided buffer. + * + * @retval 0 If successful. + * @retval -EOVERFLOW If the data is too large to fit the supplied buffer. + * @retval -EIO If the requested key was not found. + * @retval -errno Error code. + */ +int blinfo_lookup(uint16_t key, char *val, int val_len_max); +#endif + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_RETENTION_BLINFO_ */ diff --git a/include/zephyr/rtio/rtio.h b/include/zephyr/rtio/rtio.h index f608d213c37..fe0f5b72c97 100644 --- a/include/zephyr/rtio/rtio.h +++ b/include/zephyr/rtio/rtio.h @@ -211,7 +211,6 @@ struct rtio_cqe; struct rtio_sqe; struct rtio_sqe_pool; struct rtio_cqe_pool; -struct rtio_block_pool; struct rtio_iodev; struct rtio_iodev_sqe; /** @endcond */ @@ -310,13 +309,6 @@ struct rtio_cqe_pool { struct rtio_cqe *pool; }; -struct rtio_block_pool { - /* Memory pool associated with this RTIO context. */ - struct sys_mem_blocks *mempool; - /* The size (in bytes) of a single block in the mempool */ - const uint32_t blk_size; -}; - /** * @brief An RTIO context containing what can be viewed as a pair of queues. * @@ -362,7 +354,7 @@ struct rtio { #ifdef CONFIG_RTIO_SYS_MEM_BLOCKS /* Mem block pool */ - struct rtio_block_pool *block_pool; + struct sys_mem_blocks *block_pool; #endif /* Submission queue */ @@ -375,6 +367,26 @@ struct rtio { /** The memory partition associated with all RTIO context information */ extern struct k_mem_partition rtio_partition; +/** + * @brief Get the mempool block size of the RTIO context + * + * @param[in] r The RTIO context + * @return The size of each block in the context's mempool + * @return 0 if the context doesn't have a mempool + */ +static inline size_t rtio_mempool_block_size(const struct rtio *r) +{ +#ifndef CONFIG_RTIO_SYS_MEM_BLOCKS + ARG_UNUSED(r); + return 0; +#else + if (r == NULL || r->block_pool == NULL) { + return 0; + } + return BIT(r->block_pool->info.blk_sz_shift); +#endif +} + /** * @brief Compute the mempool block index for a given pointer * @@ -386,11 +398,11 @@ extern struct k_mem_partition rtio_partition; static inline uint16_t __rtio_compute_mempool_block_index(const struct rtio *r, const void *ptr) { uintptr_t addr = (uintptr_t)ptr; - struct sys_mem_blocks *mem_pool = r->block_pool->mempool; - uint32_t block_size = r->block_pool->blk_size; + struct sys_mem_blocks *mem_pool = r->block_pool; + uint32_t block_size = rtio_mempool_block_size(r); uintptr_t buff = (uintptr_t)mem_pool->buffer; - uint32_t buff_size = mem_pool->num_blocks * block_size; + uint32_t buff_size = mem_pool->info.num_blocks * block_size; if (addr < buff || addr >= buff + buff_size) { return UINT16_MAX; @@ -648,31 +660,50 @@ static inline void rtio_cqe_pool_free(struct rtio_cqe_pool *pool, struct rtio_cq pool->pool_free++; } -static inline int rtio_block_pool_alloc(struct rtio_block_pool *pool, size_t min_sz, +static inline int rtio_block_pool_alloc(struct rtio *r, size_t min_sz, size_t max_sz, uint8_t **buf, uint32_t *buf_len) { +#ifndef CONFIG_RTIO_SYS_MEM_BLOCKS + ARG_UNUSED(r); + ARG_UNUSED(min_sz); + ARG_UNUSED(max_sz); + ARG_UNUSED(buf); + ARG_UNUSED(buf_len); + return -ENOTSUP; +#else + const uint32_t block_size = rtio_mempool_block_size(r); uint32_t bytes = max_sz; + /* Not every context has a block pool and the block size may return 0 in + * that case + */ + if (block_size == 0) { + return -ENOMEM; + } + do { - size_t num_blks = DIV_ROUND_UP(bytes, pool->blk_size); - int rc = sys_mem_blocks_alloc_contiguous(pool->mempool, num_blks, (void **)buf); + size_t num_blks = DIV_ROUND_UP(bytes, block_size); + int rc = sys_mem_blocks_alloc_contiguous(r->block_pool, num_blks, (void **)buf); if (rc == 0) { - *buf_len = num_blks * pool->blk_size; + *buf_len = num_blks * block_size; return 0; } - bytes -= pool->blk_size; + bytes -= block_size; } while (bytes >= min_sz); return -ENOMEM; +#endif } -static inline void rtio_block_pool_free(struct rtio_block_pool *pool, void *buf, uint32_t buf_len) +static inline void rtio_block_pool_free(struct rtio *r, void *buf, uint32_t buf_len) { - size_t num_blks = buf_len / pool->blk_size; +#ifdef CONFIG_RTIO_SYS_MEM_BLOCKS + size_t num_blks = buf_len >> r->block_pool->info.blk_sz_shift; - sys_mem_blocks_free_contiguous(pool->mempool, buf, num_blks); + sys_mem_blocks_free_contiguous(r->block_pool, buf, num_blks); +#endif } /* Do not try and reformat the macros */ @@ -733,16 +764,11 @@ static inline void rtio_block_pool_free(struct rtio_block_pool *pool, void *buf, */ #define RTIO_DMEM COND_CODE_1(CONFIG_USERSPACE, (K_APP_DMEM(rtio_partition) static), (static)) -#define Z_RTIO_BLOCK_POOL_DEFINE(name, blk_sz, blk_cnt, blk_align) \ - RTIO_BMEM uint8_t __aligned(WB_UP(blk_align)) \ - _block_pool_##name[blk_cnt*WB_UP(blk_sz)]; \ - _SYS_MEM_BLOCKS_DEFINE_WITH_EXT_BUF(_sys_blocks_##name, WB_UP(blk_sz), \ - blk_cnt, _block_pool_##name, \ - RTIO_DMEM); \ - static struct rtio_block_pool name = { \ - .mempool = &_sys_blocks_##name, \ - .blk_size = blk_sz, \ - } +#define Z_RTIO_BLOCK_POOL_DEFINE(name, blk_sz, blk_cnt, blk_align) \ + RTIO_BMEM uint8_t __aligned(WB_UP(blk_align)) \ + _block_pool_##name[blk_cnt*WB_UP(blk_sz)]; \ + _SYS_MEM_BLOCKS_DEFINE_WITH_EXT_BUF(name, WB_UP(blk_sz), blk_cnt, _block_pool_##name, \ + RTIO_DMEM) #define Z_RTIO_DEFINE(name, _sqe_pool, _cqe_pool, _block_pool) \ IF_ENABLED(CONFIG_RTIO_SUBMIT_SEM, \ @@ -967,8 +993,8 @@ static inline struct rtio_cqe *rtio_cqe_consume_block(struct rtio *r) #endif node = rtio_mpsc_pop(&r->cq); while (node == NULL) { - node = rtio_mpsc_pop(&r->cq); Z_SPIN_DELAY(1); + node = rtio_mpsc_pop(&r->cq); } cqe = CONTAINER_OF(node, struct rtio_cqe, q); @@ -999,10 +1025,10 @@ static inline uint32_t rtio_cqe_compute_flags(struct rtio_iodev_sqe *iodev_sqe) #ifdef CONFIG_RTIO_SYS_MEM_BLOCKS if (iodev_sqe->sqe.op == RTIO_OP_RX && iodev_sqe->sqe.flags & RTIO_SQE_MEMPOOL_BUFFER) { struct rtio *r = iodev_sqe->r; - struct sys_mem_blocks *mem_pool = r->block_pool->mempool; - uint32_t block_size = r->block_pool->blk_size; - int blk_index = (iodev_sqe->sqe.buf - mem_pool->buffer) / block_size; - int blk_count = iodev_sqe->sqe.buf_len / block_size; + struct sys_mem_blocks *mem_pool = r->block_pool; + int blk_index = (iodev_sqe->sqe.buf - mem_pool->buffer) >> + mem_pool->info.blk_sz_shift; + int blk_count = iodev_sqe->sqe.buf_len >> mem_pool->info.blk_sz_shift; flags = RTIO_CQE_FLAG_PREP_MEMPOOL(blk_index, blk_count); } @@ -1038,13 +1064,13 @@ static inline int z_impl_rtio_cqe_get_mempool_buffer(const struct rtio *r, struc if (RTIO_CQE_FLAG_GET(cqe->flags) == RTIO_CQE_FLAG_MEMPOOL_BUFFER) { int blk_idx = RTIO_CQE_FLAG_MEMPOOL_GET_BLK_IDX(cqe->flags); int blk_count = RTIO_CQE_FLAG_MEMPOOL_GET_BLK_CNT(cqe->flags); + uint32_t blk_size = rtio_mempool_block_size(r); - *buff = r->block_pool->mempool->buffer + blk_idx * r->block_pool->blk_size; - *buff_len = blk_count * r->block_pool->blk_size; - __ASSERT_NO_MSG(*buff >= r->block_pool->mempool->buffer); + *buff = r->block_pool->buffer + blk_idx * blk_size; + *buff_len = blk_count * blk_size; + __ASSERT_NO_MSG(*buff >= r->block_pool->buffer); __ASSERT_NO_MSG(*buff < - r->block_pool->mempool->buffer + - r->block_pool->blk_size * r->block_pool->mempool->num_blocks); + r->block_pool->buffer + blk_size * r->block_pool->info.num_blocks); return 0; } return -EINVAL; @@ -1176,8 +1202,7 @@ static inline int rtio_sqe_rx_buf(const struct rtio_iodev_sqe *iodev_sqe, uint32 return 0; } - int rc = rtio_block_pool_alloc(r->block_pool, min_buf_len, max_buf_len, - buf, buf_len); + int rc = rtio_block_pool_alloc(r, min_buf_len, max_buf_len, buf, buf_len); if (rc == 0) { sqe->buf = *buf; sqe->buf_len = *buf_len; @@ -1222,7 +1247,7 @@ static inline void z_impl_rtio_release_buffer(struct rtio *r, void *buff, uint32 return; } - rtio_block_pool_free(r->block_pool, buff, buff_len); + rtio_block_pool_free(r, buff, buff_len); #else ARG_UNUSED(r); ARG_UNUSED(buff); diff --git a/include/zephyr/sd/sd.h b/include/zephyr/sd/sd.h index e73777873c5..69d3057e8ad 100644 --- a/include/zephyr/sd/sd.h +++ b/include/zephyr/sd/sd.h @@ -39,6 +39,19 @@ enum card_type { CARD_MMC = 3, /*!< MMC memory card */ }; +/** + * @brief SDIO function definition + * + * SDIO function definition. Used to store function information + * per each SDIO function + */ +struct sdio_func { + enum sdio_func_num num; /*!< Function number */ + struct sd_card *card; /*!< Card this function is present on */ + struct sdio_cis cis; /*!< CIS tuple data for this function */ + uint16_t block_size; /*!< Current block size for this function */ +}; + /** * @brief SD card structure @@ -64,6 +77,9 @@ struct sd_card { enum card_status status; /*!< Card status */ enum card_type type; /*!< Card type */ uint16_t flags; /*!< Card flags */ + uint8_t bus_width; /*!< Desired bus width */ + uint32_t cccr_flags; /*!< SDIO CCCR data */ + struct sdio_func func0; /*!< Function 0 common card data */ uint8_t card_buffer[CONFIG_SD_BUFFER_SIZE] __aligned(CONFIG_SDHC_BUFFER_ALIGNMENT); /* Card internal buffer */ }; diff --git a/include/zephyr/sd/sd_spec.h b/include/zephyr/sd/sd_spec.h index ed0426766ec..ed61932e655 100644 --- a/include/zephyr/sd/sd_spec.h +++ b/include/zephyr/sd/sd_spec.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 NXP + * Copyright 2022-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -54,6 +54,8 @@ enum sd_opcode { SD_ERASE_BLOCK_START = 32, SD_ERASE_BLOCK_END = 33, SD_ERASE_BLOCK_OPERATION = 38, + SDIO_RW_DIRECT = 52, + SDIO_RW_EXTENDED = 53, SD_APP_CMD = 55, SD_SPI_READ_OCR = 58, /* SPI mode only */ SD_SPI_CRC_ON_OFF = 59, /* SPI mode only */ @@ -244,6 +246,7 @@ enum sd_support_flag { SD_3000MV_FLAG = BIT(6), SD_CMD23_FLAG = BIT(7), SD_SPEED_CLASS_CONTROL_FLAG = BIT(8), + SD_MEM_PRESENT_FLAG = BIT(9), }; @@ -298,9 +301,9 @@ enum mmc_ocr_flag { MMC_OCR_PWR_BUSY_FLAG = BIT(31) }; -#define SDIO_OCR_IO_NUMBER_SHIFT (28U) +#define SDIO_OCR_IO_NUMBER_SHIFT 28 /* Lower 24 bits hold SDIO I/O OCR */ -#define SDIO_IO_OCR_MASK (0xFFFFFFU) +#define SDIO_IO_OCR_MASK 0xFFFFFF /** * @brief SDIO OCR bit flags @@ -491,7 +494,7 @@ struct sd_switch_caps { }; -#define SD_PRODUCT_NAME_BYTES (5U) +#define SD_PRODUCT_NAME_BYTES 5 /** * @brief SD card identification register @@ -754,8 +757,158 @@ enum sd_spec_version { }; -#define SDMMC_DEFAULT_BLOCK_SIZE (512U) +#define SDMMC_DEFAULT_BLOCK_SIZE 512 #define MMC_EXT_CSD_BYTES 512 +/** + * @brief SDIO function number + * + * SDIO function number used to select function when performing I/O on SDIO card + */ +enum sdio_func_num { + SDIO_FUNC_NUM_0 = 0, + SDIO_FUNC_NUM_1 = 1, + SDIO_FUNC_NUM_2 = 2, + SDIO_FUNC_NUM_3 = 3, + SDIO_FUNC_NUM_4 = 4, + SDIO_FUNC_NUM_5 = 5, + SDIO_FUNC_NUM_6 = 6, + SDIO_FUNC_NUM_7 = 7, + SDIO_FUNC_MEMORY = 8, +}; + +/** + * @brief SDIO I/O direction + * + * SDIO I/O direction (read or write) + */ +enum sdio_io_dir { + SDIO_IO_READ = 0, + SDIO_IO_WRITE = 1, +}; + +#define SDIO_CMD_ARG_RW_SHIFT 31 /*!< read/write flag shift */ +#define SDIO_CMD_ARG_FUNC_NUM_SHIFT 28 /*!< function number shift */ +#define SDIO_DIRECT_CMD_ARG_RAW_SHIFT 27 /*!< direct raw flag shift */ +#define SDIO_CMD_ARG_REG_ADDR_SHIFT 9 /*!< direct reg addr shift */ +#define SDIO_CMD_ARG_REG_ADDR_MASK 0x1FFFF /*!< direct reg addr mask */ +#define SDIO_DIRECT_CMD_DATA_MASK 0xFF /*!< data mask */ + +#define SDIO_EXTEND_CMD_ARG_BLK_SHIFT 27 /*!< extended write block mode */ +#define SDIO_EXTEND_CMD_ARG_OP_CODE_SHIFT 26 /*!< op code (increment address) */ + +/** + * @brief Card common control register definitions + * + * Card common control registers, present on all SDIO cards + */ +#define SDIO_CCCR_CCCR 0x00 /*!< SDIO CCCR revision register */ +#define SDIO_CCCR_CCCR_REV_MASK 0x0F +#define SDIO_CCCR_CCCR_REV_SHIFT 0x0 +#define SDIO_CCCR_CCCR_REV_1_00 0x0 /*!< CCCR/FBR Version 1.00 */ +#define SDIO_CCCR_CCCR_REV_1_10 0x1 /*!< CCCR/FBR Version 1.10 */ +#define SDIO_CCCR_CCCR_REV_2_00 0x2 /*!< CCCR/FBR Version 2.00 */ +#define SDIO_CCCR_CCCR_REV_3_00 0x3 /*!< CCCR/FBR Version 3.00 */ + +#define SDIO_CCCR_SD 0x01 /*!< SD spec version register */ +#define SDIO_CCCR_SD_SPEC_MASK 0x0F +#define SDIO_CCCR_SD_SPEC_SHIFT 0x0 + +#define SDIO_CCCR_IO_EN 0x02 /*!< SDIO IO Enable register */ + +#define SDIO_CCCR_IO_RD 0x03 /*!< SDIO IO Ready register */ + +#define SDIO_CCCR_INT_EN 0x04 /*!< SDIO Interrupt enable register */ + +#define SDIO_CCCR_INT_P 0x05 /*!< SDIO Interrupt pending register */ + +#define SDIO_CCCR_ABORT 0x06 /*!< SDIO IO abort register */ + +#define SDIO_CCCR_BUS_IF 0x07 /*!< SDIO bus interface control register */ +#define SDIO_CCCR_BUS_IF_WIDTH_MASK 0x3 /*!< SDIO bus width setting mask */ +#define SDIO_CCCR_BUS_IF_WIDTH_1_BIT 0x00 /*!< 1 bit SDIO bus setting */ +#define SDIO_CCCR_BUS_IF_WIDTH_4_BIT 0x02 /*!< 4 bit SDIO bus setting */ +#define SDIO_CCCR_BUS_IF_WIDTH_8_BIT 0x03 /*!< 8 bit SDIO bus setting */ + +#define SDIO_CCCR_CAPS 0x08 /*!< SDIO card capabilities */ +#define SDIO_CCCR_CAPS_SDC BIT(0) /*!< support CMD52 while data transfer */ +#define SDIO_CCCR_CAPS_SMB BIT(1) /*!< support multiple block transfer */ +#define SDIO_CCCR_CAPS_SRW BIT(2) /*!< support read wait control */ +#define SDIO_CCCR_CAPS_SBS BIT(3) /*!< support bus control */ +#define SDIO_CCCR_CAPS_S4MI BIT(4) /*!< support block gap interrupt */ +#define SDIO_CCCR_CAPS_E4MI BIT(5) /*!< enable block gap interrupt */ +#define SDIO_CCCR_CAPS_LSC BIT(6) /*!< low speed card */ +#define SDIO_CCCR_CAPS_BLS BIT(7) /*!< low speed card with 4 bit support */ + +#define SDIO_CCCR_CIS 0x09 /*!< SDIO CIS tuples pointer */ + +#define SDIO_CCCR_SPEED 0x13 /*!< SDIO bus speed select */ +#define SDIO_CCCR_SPEED_SHS BIT(0) /*!< high speed support */ +#define SDIO_CCCR_SPEED_MASK 0xE /*!< bus speed select mask*/ +#define SDIO_CCCR_SPEED_SHIFT 0x1 /*!< bus speed select shift */ +#define SDIO_CCCR_SPEED_SDR12 0x0 /*!< select SDR12 */ +#define SDIO_CCCR_SPEED_HS 0x1 /*!< select High speed mode */ +#define SDIO_CCCR_SPEED_SDR25 0x1 /*!< select SDR25 */ +#define SDIO_CCCR_SPEED_SDR50 0x2 /*!< select SDR50 */ +#define SDIO_CCCR_SPEED_SDR104 0x3 /*!< select SDR104 */ +#define SDIO_CCCR_SPEED_DDR50 0x4 /*!< select DDR50 */ + +#define SDIO_CCCR_UHS 0x14 /*!< SDIO UHS support */ +#define SDIO_CCCR_UHS_SDR50 BIT(0) /*!< SDR50 support */ +#define SDIO_CCCR_UHS_SDR104 BIT(1) /*!< SDR104 support */ +#define SDIO_CCCR_UHS_DDR50 BIT(2) /*!< DDR50 support */ + +#define SDIO_CCCR_DRIVE_STRENGTH 0x15 /*!< SDIO drive strength */ +#define SDIO_CCCR_DRIVE_STRENGTH_A BIT(0) /*!< drive type A */ +#define SDIO_CCCR_DRIVE_STRENGTH_C BIT(1) /*!< drive type C */ +#define SDIO_CCCR_DRIVE_STRENGTH_D BIT(2) /*!< drive type D */ + +#define SDIO_FBR_BASE(n) ((n) * 0x100) /*!< Get function base register addr */ + +#define SDIO_FBR_CIS 0x09 /*!< SDIO function base register CIS pointer */ +#define SDIO_FBR_CSA 0x0C /*!< SDIO function base register CSA pointer */ +#define SDIO_FBR_BLK_SIZE 0x10 /*!< SDIO function base register block size */ + + +#define SDIO_MAX_IO_NUMS 7 /*!< Maximum number of I/O functions for SDIO */ + +#define SDIO_TPL_CODE_NULL 0x00 /*!< NULL CIS tuple code */ +#define SDIO_TPL_CODE_MANIFID 0x20 /*!< manufacturer ID CIS tuple code */ +#define SDIO_TPL_CODE_FUNCID 0x21 /*!< function ID CIS tuple code */ +#define SDIO_TPL_CODE_FUNCE 0x22 /*!< function extension CIS tuple code */ +#define SDIO_TPL_CODE_END 0xFF /*!< End CIS tuple code */ + +/** + * @brief Card common control register flags + * + * flags to indicate capabilities supported by an SDIO card, read from the CCCR + * registers + */ +enum sdio_cccr_flags { + SDIO_SUPPORT_HS = BIT(0), + SDIO_SUPPORT_SDR50 = BIT(1), + SDIO_SUPPORT_SDR104 = BIT(2), + SDIO_SUPPORT_DDR50 = BIT(3), + SDIO_SUPPORT_4BIT_LS_BUS = BIT(4), + SDIO_SUPPORT_MULTIBLOCK = BIT(5), +}; + +/** + * @brief SDIO common CIS tuple properties + * + * CIS tuple properties. Note that additional properties exist for + * functions 1-7, but we do not read this data as the stack does not utilize it. + */ +struct sdio_cis { + /* Manufacturer ID string tuple */ + uint16_t manf_id; /*!< manufacturer ID */ + uint16_t manf_code; /*!< manufacturer code */ + /* Function identification tuple */ + uint8_t func_id; /*!< sdio device class function id */ + /* Function extension table */ + uint16_t max_blk_size; /*!< Max transfer block size */ + uint8_t max_speed; /*!< Max transfer speed */ + uint16_t rdy_timeout; /*!< I/O ready timeout */ +}; #ifdef __cplusplus } diff --git a/include/zephyr/sd/sdio.h b/include/zephyr/sd/sdio.h new file mode 100644 index 00000000000..546a68d2bbb --- /dev/null +++ b/include/zephyr/sd/sdio.h @@ -0,0 +1,212 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Public API for SDIO subsystem + */ + +#ifndef ZEPHYR_INCLUDE_SD_SDIO_H_ +#define ZEPHYR_INCLUDE_SD_SDIO_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialize SDIO function. + * + * Initializes SDIO card function. The card function will not be enabled, + * but after this call returns the SDIO function structure can be used to read + * and write data from the card. + * @param func: function structure to initialize + * @param card: SD card to enable function on + * @param num: function number to initialize + * @retval 0 function was initialized successfully + * @retval -EIO: I/O error + */ +int sdio_init_func(struct sd_card *card, struct sdio_func *func, + enum sdio_func_num num); + +/** + * @brief Enable SDIO function + * + * Enables SDIO card function. @ref sdio_init_func must be called to + * initialized the function structure before enabling it in the card. + * @param func: function to enable + * @retval 0 function was enabled successfully + * @retval -ETIMEDOUT: card I/O timed out + * @retval -EIO: I/O error + */ +int sdio_enable_func(struct sdio_func *func); + +/** + * @brief Set block size of SDIO function + * + * Set desired block size for SDIO function, used by block transfers + * to SDIO registers. + * @param func: function to set block size for + * @param bsize: block size + * @retval 0 block size was set + * @retval -EINVAL: unsupported/invalid block size + * @retval -EIO: I/O error + */ +int sdio_set_block_size(struct sdio_func *func, uint16_t bsize); + +/** + * @brief Read byte from SDIO register + * + * Reads byte from SDIO register + * @param func: function to read from + * @param reg: register address to read from + * @param val: filled with byte value read from register + * @retval 0 read succeeded + * @retval -EBUSY: card is busy with another request + * @retval -ETIMEDOUT: card read timed out + * @retval -EIO: I/O error + */ +int sdio_read_byte(struct sdio_func *func, uint32_t reg, uint8_t *val); + +/** + * @brief Write byte to SDIO register + * + * Writes byte to SDIO register + * @param func: function to write to + * @param reg: register address to write to + * @param write_val: value to write to register + * @retval 0 write succeeded + * @retval -EBUSY: card is busy with another request + * @retval -ETIMEDOUT: card write timed out + * @retval -EIO: I/O error + */ +int sdio_write_byte(struct sdio_func *func, uint32_t reg, uint8_t write_val); + +/** + * @brief Write byte to SDIO register, and read result + * + * Writes byte to SDIO register, and reads the register after write + * @param func: function to write to + * @param reg: register address to write to + * @param write_val: value to write to register + * @param read_val: filled with value read from register + * @retval 0 write succeeded + * @retval -EBUSY: card is busy with another request + * @retval -ETIMEDOUT: card write timed out + * @retval -EIO: I/O error + */ +int sdio_rw_byte(struct sdio_func *func, uint32_t reg, uint8_t write_val, + uint8_t *read_val); + +/** + * @brief Read bytes from SDIO fifo + * + * Reads bytes from SDIO register, treating it as a fifo. Reads will + * all be done from same address. + * @param func: function to read from + * @param reg: register address of fifo + * @param data: filled with data read from fifo + * @param len: length of data to read from card + * @retval 0 read succeeded + * @retval -EBUSY: card is busy with another request + * @retval -ETIMEDOUT: card read timed out + * @retval -EIO: I/O error + */ +int sdio_read_fifo(struct sdio_func *func, uint32_t reg, uint8_t *data, + uint32_t len); + +/** + * @brief Write bytes to SDIO fifo + * + * Writes bytes to SDIO register, treating it as a fifo. Writes will + * all be done to same address. + * @param func: function to write to + * @param reg: register address of fifo + * @param data: data to write to fifo + * @param len: length of data to write to card + * @retval 0 write succeeded + * @retval -EBUSY: card is busy with another request + * @retval -ETIMEDOUT: card write timed out + * @retval -EIO: I/O error + */ +int sdio_write_fifo(struct sdio_func *func, uint32_t reg, uint8_t *data, + uint32_t len); + +/** + * @brief Read blocks from SDIO fifo + * + * Reads blocks from SDIO register, treating it as a fifo. Reads will + * all be done from same address. + * @param func: function to read from + * @param reg: register address of fifo + * @param data: filled with data read from fifo + * @param blocks: number of blocks to read from fifo + * @retval 0 read succeeded + * @retval -EBUSY: card is busy with another request + * @retval -ETIMEDOUT: card read timed out + * @retval -EIO: I/O error + */ +int sdio_read_blocks_fifo(struct sdio_func *func, uint32_t reg, uint8_t *data, + uint32_t blocks); + +/** + * @brief Write blocks to SDIO fifo + * + * Writes blocks from SDIO register, treating it as a fifo. Writes will + * all be done to same address. + * @param func: function to write to + * @param reg: register address of fifo + * @param data: data to write to fifo + * @param blocks: number of blocks to write to fifo + * @retval 0 write succeeded + * @retval -EBUSY: card is busy with another request + * @retval -ETIMEDOUT: card write timed out + * @retval -EIO: I/O error + */ +int sdio_write_blocks_fifo(struct sdio_func *func, uint32_t reg, uint8_t *data, + uint32_t blocks); + +/** + * @brief Copy bytes from an SDIO card + * + * Copies bytes from an SDIO card, starting from provided address. + * @param func: function to read from + * @param reg: register address to start copy at + * @param data: buffer to copy data into + * @param len: length of data to read + * @retval 0 read succeeded + * @retval -EBUSY: card is busy with another request + * @retval -ETIMEDOUT: card read timed out + * @retval -EIO: I/O error + */ +int sdio_read_addr(struct sdio_func *func, uint32_t reg, uint8_t *data, + uint32_t len); + +/** + * @brief Copy bytes to an SDIO card + * + * Copies bytes to an SDIO card, starting from provided address. + * + * @param func: function to write to + * @param reg: register address to start copy at + * @param data: buffer to copy data from + * @param len: length of data to write + * @retval 0 write succeeded + * @retval -EBUSY: card is busy with another request + * @retval -ETIMEDOUT: card write timed out + * @retval -EIO: I/O error + */ +int sdio_write_addr(struct sdio_func *func, uint32_t reg, uint8_t *data, + uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_SD_SDMMC_H_ */ diff --git a/include/zephyr/sensing/sensing_sensor.h b/include/zephyr/sensing/sensing_sensor.h index 39d94d71fb3..8c9e0c83811 100644 --- a/include/zephyr/sensing/sensing_sensor.h +++ b/include/zephyr/sensing/sensing_sensor.h @@ -114,7 +114,7 @@ static inline int sensing_sensor_dev_init( }; \ DEVICE_DT_DEFINE(node_id, sensing_sensor_dev_init, NULL, \ &_CONCAT(__sensing_sensor_ctx_, Z_DEVICE_DT_DEV_ID(node_id)), \ - NULL, APPLICATION, 10, api_ptr) + NULL, POST_KERNEL, 99, api_ptr) /** * @brief Get registered context data pointer for a sensor instance. diff --git a/include/zephyr/shell/shell.h b/include/zephyr/shell/shell.h index 437169fd281..8382dc8290a 100644 --- a/include/zephyr/shell/shell.h +++ b/include/zephyr/shell/shell.h @@ -350,8 +350,8 @@ struct shell_static_entry { SHELL_EXPR_CMD_ARG(1, _syntax, _subcmd, _help, \ _handler, _mand, _opt)\ ), \ - (static shell_cmd_handler dummy_##syntax##_handler __unused = _handler;\ - static const union shell_cmd_entry dummy_subcmd_##syntax __unused = { \ + (static shell_cmd_handler dummy_handler_##_syntax __unused = _handler;\ + static const union shell_cmd_entry dummy_subcmd_##_syntax __unused = { \ .entry = (const struct shell_static_entry *)_subcmd\ } \ ) \ @@ -530,7 +530,7 @@ static int UTIL_CAT(UTIL_CAT(cmd_dict_, UTIL_CAT(_handler, _)), \ * @param[in] _name Name of the dictionary subcommand set * @param[in] _handler Command handler common for all dictionary commands. * @see shell_dict_cmd_handler - * @param[in] ... Dictionary pairs: (command_syntax, value). Value will be + * @param[in] ... Dictionary triplets: (command_syntax, value, helper). Value will be * passed to the _handler as user data. * * Example usage: @@ -863,7 +863,7 @@ struct shell { LOG_INSTANCE_PTR_DECLARE(log); - const char *thread_name; + const char *name; struct k_thread *thread; k_thread_stack_t *stack; }; @@ -910,7 +910,7 @@ extern void z_shell_print_stream(const void *user_ctx, const char *data, .stats = Z_SHELL_STATS_PTR(_name), \ .log_backend = Z_SHELL_LOG_BACKEND_PTR(_name), \ LOG_INSTANCE_PTR_INIT(log, shell, _name) \ - .thread_name = STRINGIFY(_name), \ + .name = STRINGIFY(_name), \ .thread = &_name##_thread, \ .stack = _name##_stack \ } diff --git a/include/zephyr/shell/shell_backend.h b/include/zephyr/shell/shell_backend.h new file mode 100644 index 00000000000..ae8f8a5afc3 --- /dev/null +++ b/include/zephyr/shell/shell_backend.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef SHELL_BACKEND_H__ +#define SHELL_BACKEND_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Get backend. + * + * @param[in] idx Pointer to the backend instance. + * + * @return Pointer to the backend instance. + */ +static inline const struct shell *shell_backend_get(uint32_t idx) +{ + const struct shell *backend; + + STRUCT_SECTION_GET(shell, idx, &backend); + + return backend; +} + +/** + * @brief Get number of backends. + * + * @return Number of backends. + */ +static inline int shell_backend_count_get(void) +{ + int cnt; + + STRUCT_SECTION_COUNT(shell, &cnt); + + return cnt; +} + +/** + * @brief Get backend by name. + * + * @param[in] backend_name Name of the backend as defined by the SHELL_DEFINE. + * + * @retval Pointer to the backend instance if found, NULL if backend is not found. + */ +const struct shell *shell_backend_get_by_name(const char *backend_name); + +#ifdef __cplusplus +} +#endif + +#endif /* SHELL_BACKEND_H__ */ diff --git a/include/zephyr/shell/shell_uart.h b/include/zephyr/shell/shell_uart.h index adf8a4044aa..5032c56f65e 100644 --- a/include/zephyr/shell/shell_uart.h +++ b/include/zephyr/shell/shell_uart.h @@ -7,88 +7,30 @@ #ifndef SHELL_UART_H__ #define SHELL_UART_H__ -#include -#include -#include #include +#include #ifdef __cplusplus extern "C" { #endif -extern const struct shell_transport_api shell_uart_transport_api; - -/** @brief Shell UART transport instance control block (RW data). */ -struct shell_uart_ctrl_blk { - const struct device *dev; - shell_transport_handler_t handler; - void *context; - atomic_t tx_busy; - bool blocking_tx; -#ifdef CONFIG_MCUMGR_TRANSPORT_SHELL - struct smp_shell_data smp; -#endif /* CONFIG_MCUMGR_TRANSPORT_SHELL */ -}; - -#ifdef CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN -#define Z_UART_SHELL_TX_RINGBUF_DECLARE(_name, _size) \ - RING_BUF_DECLARE(_name##_tx_ringbuf, _size) - -#define Z_UART_SHELL_RX_TIMER_DECLARE(_name) /* Empty */ -#define Z_UART_SHELL_TX_RINGBUF_PTR(_name) (&_name##_tx_ringbuf) - -#define Z_UART_SHELL_RX_TIMER_PTR(_name) NULL - -#define Z_UART_SHELL_DTR_TIMER_DECLARE(_name) static struct k_timer _name##_dtr_timer -#define Z_UART_SHELL_DTR_TIMER_PTR(_name) (&_name##_dtr_timer) - -#else /* CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN */ -#define Z_UART_SHELL_TX_RINGBUF_DECLARE(_name, _size) /* Empty */ -#define Z_UART_SHELL_RX_TIMER_DECLARE(_name) static struct k_timer _name##_timer -#define Z_UART_SHELL_TX_RINGBUF_PTR(_name) NULL -#define Z_UART_SHELL_RX_TIMER_PTR(_name) (&_name##_timer) -#define Z_UART_SHELL_DTR_TIMER_DECLARE(_name) /* Empty */ -#define Z_UART_SHELL_DTR_TIMER_PTR(_name) NULL -#endif /* CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN */ - -/** @brief Shell UART transport instance structure. */ -struct shell_uart { - struct shell_uart_ctrl_blk *ctrl_blk; - struct k_timer *timer; - struct k_timer *dtr_timer; - struct ring_buf *tx_ringbuf; - struct ring_buf *rx_ringbuf; -}; - -/** @brief Macro for creating shell UART transport instance. */ -#define SHELL_UART_DEFINE(_name, _tx_ringbuf_size, _rx_ringbuf_size) \ - static struct shell_uart_ctrl_blk _name##_ctrl_blk; \ - Z_UART_SHELL_RX_TIMER_DECLARE(_name); \ - Z_UART_SHELL_DTR_TIMER_DECLARE(_name); \ - Z_UART_SHELL_TX_RINGBUF_DECLARE(_name, _tx_ringbuf_size); \ - RING_BUF_DECLARE(_name##_rx_ringbuf, _rx_ringbuf_size); \ - static const struct shell_uart _name##_shell_uart = { \ - .ctrl_blk = &_name##_ctrl_blk, \ - .timer = Z_UART_SHELL_RX_TIMER_PTR(_name), \ - .dtr_timer = Z_UART_SHELL_DTR_TIMER_PTR(_name), \ - .tx_ringbuf = Z_UART_SHELL_TX_RINGBUF_PTR(_name), \ - .rx_ringbuf = &_name##_rx_ringbuf, \ - }; \ - struct shell_transport _name = { \ - .api = &shell_uart_transport_api, \ - .ctx = (struct shell_uart *)&_name##_shell_uart \ - } - /** - * @brief This function provides pointer to shell uart backend instance. + * @brief This function provides pointer to the shell UART backend instance. * - * Function returns pointer to the shell uart instance. This instance can be + * Function returns pointer to the shell UART instance. This instance can be * next used with shell_execute_cmd function in order to test commands behavior. * * @returns Pointer to the shell instance. */ const struct shell *shell_backend_uart_get_ptr(void); +/** + * @brief This function provides pointer to the smp shell data of the UART shell transport. + * + * @returns Pointer to the smp shell data. + */ +struct smp_shell_data *shell_uart_smp_shell_data_get_ptr(void); + #ifdef __cplusplus } #endif diff --git a/include/zephyr/sip_svc/sip_svc_controller.h b/include/zephyr/sip_svc/sip_svc_controller.h index e74033670ff..2ce9394230b 100644 --- a/include/zephyr/sip_svc/sip_svc_controller.h +++ b/include/zephyr/sip_svc/sip_svc_controller.h @@ -13,11 +13,21 @@ #ifdef CONFIG_ARM_SIP_SVC_SUBSYS +#include + /** * @brief Length of SVC conduit name in sip svc subsystem. * */ -#define SIP_SVC_SUBSYS_CONDUIT_NAME_LENGTH (4) +#define SIP_SVC_SUBSYS_CONDUIT_NAME_LENGTH (4U) + +/** + * @brief Open lock states in sip_svc atomic variable + */ +enum open_state { + SIP_SVC_OPEN_UNLOCKED = 0, + SIP_SVC_OPEN_LOCKED +}; /** * @brief Arm SiP Service client data. @@ -73,8 +83,8 @@ struct sip_svc_controller { k_tid_t tid; #if CONFIG_ARM_SIP_SVC_SUBSYS_SINGLY_OPEN - /* Mutex to restrict one client access */ - struct k_mutex open_mutex; + /* Atomic variable to restrict one client access */ + atomic_t open_lock; #endif /* Mutex for protecting database access */ struct k_mutex data_mutex; @@ -93,6 +103,10 @@ struct sip_svc_controller { */ #define SIP_SVC_CONTROLLER_DEFINE(inst, conduit_name, sip_dev, sip_num_clients, \ sip_max_transactions, sip_resp_size) \ + BUILD_ASSERT( \ + ((sip_num_clients <= CONFIG_ARM_SIP_SVC_SUBSYS_MAX_CLIENT_COUNT) && \ + (sip_num_clients > 0)), \ + "Number of client should be within 1 and ARM_SIP_SVC_SUBSYS_MAX_CLIENT_COUNT"); \ static STRUCT_SECTION_ITERABLE(sip_svc_controller, sip_svc_##inst) = { \ .method = conduit_name, \ .dev = sip_dev, \ diff --git a/include/zephyr/spinlock.h b/include/zephyr/spinlock.h index d97bda761d5..51c160b0f85 100644 --- a/include/zephyr/spinlock.h +++ b/include/zephyr/spinlock.h @@ -43,9 +43,28 @@ struct z_spinlock_key { * application code. */ struct k_spinlock { +/** + * @cond INTERNAL_HIDDEN + */ #ifdef CONFIG_SMP +#ifdef CONFIG_TICKET_SPINLOCKS + /* + * Ticket spinlocks are conceptually two atomic variables, + * one indicating the current FIFO head (spinlock owner), + * and the other indicating the current FIFO tail. + * Spinlock is acquired in the following manner: + * - current FIFO tail value is atomically incremented while it's + * original value is saved as a "ticket" + * - we spin until the FIFO head becomes equal to the ticket value + * + * Spinlock is released by atomic increment of the FIFO head + */ + atomic_t owner; + atomic_t tail; +#else atomic_t locked; -#endif +#endif /* CONFIG_TICKET_SPINLOCKS */ +#endif /* CONFIG_SMP */ #ifdef CONFIG_SPIN_VALIDATE /* Stores the thread that holds the lock with the locking CPU @@ -76,6 +95,9 @@ struct k_spinlock { */ char dummy; #endif +/** + * INTERNAL_HIDDEN @endcond + */ }; /* There's a spinlock validation framework available when asserts are @@ -170,10 +192,22 @@ static ALWAYS_INLINE k_spinlock_key_t k_spin_lock(struct k_spinlock *l) z_spinlock_validate_pre(l); #ifdef CONFIG_SMP +#ifdef CONFIG_TICKET_SPINLOCKS + /* + * Enqueue ourselves to the end of a spinlock waiters queue + * receiving a ticket + */ + atomic_val_t ticket = atomic_inc(&l->tail); + /* Spin until our ticket is served */ + while (atomic_get(&l->owner) != ticket) { + arch_spin_relax(); + } +#else while (!atomic_cas(&l->locked, 0, 1)) { arch_spin_relax(); } -#endif +#endif /* CONFIG_TICKET_SPINLOCKS */ +#endif /* CONFIG_SMP */ z_spinlock_validate_post(l); return k; @@ -199,16 +233,47 @@ static ALWAYS_INLINE int k_spin_trylock(struct k_spinlock *l, k_spinlock_key_t * z_spinlock_validate_pre(l); #ifdef CONFIG_SMP +#ifdef CONFIG_TICKET_SPINLOCKS + /* + * atomic_get and atomic_cas operations below are not executed + * simultaneously. + * So in theory k_spin_trylock can lock an already locked spinlock. + * To reproduce this the following conditions should be met after we + * executed atomic_get and before we executed atomic_cas: + * + * - spinlock needs to be taken 0xffff_..._ffff + 1 times + * (which requires 0xffff_..._ffff number of CPUs, as k_spin_lock call + * is blocking) or + * - spinlock needs to be taken and released 0xffff_..._ffff times and + * then taken again + * + * In real-life systems this is considered non-reproducible given that + * required actions need to be done during this tiny window of several + * CPU instructions (which execute with interrupt locked, + * so no preemption can happen here) + */ + atomic_val_t ticket_val = atomic_get(&l->owner); + + if (!atomic_cas(&l->tail, ticket_val, ticket_val + 1)) { + goto busy; + } +#else if (!atomic_cas(&l->locked, 0, 1)) { - arch_irq_unlock(key); - return -EBUSY; + goto busy; } -#endif +#endif /* CONFIG_TICKET_SPINLOCKS */ +#endif /* CONFIG_SMP */ z_spinlock_validate_post(l); k->key = key; return 0; + +#ifdef CONFIG_SMP +busy: + arch_irq_unlock(key); + return -EBUSY; +#endif /* CONFIG_SMP */ } /** @@ -249,6 +314,10 @@ static ALWAYS_INLINE void k_spin_unlock(struct k_spinlock *l, #endif /* CONFIG_SPIN_VALIDATE */ #ifdef CONFIG_SMP +#ifdef CONFIG_TICKET_SPINLOCKS + /* Give the spinlock to the next CPU in a FIFO */ + atomic_inc(&l->owner); +#else /* Strictly we don't need atomic_clear() here (which is an * exchange operation that returns the old value). We are always * setting a zero and (because we hold the lock) know the existing @@ -257,7 +326,8 @@ static ALWAYS_INLINE void k_spin_unlock(struct k_spinlock *l, * Zephyr framework for that. */ atomic_clear(&l->locked); -#endif +#endif /* CONFIG_TICKET_SPINLOCKS */ +#endif /* CONFIG_SMP */ arch_irq_unlock(key.key); } @@ -265,6 +335,26 @@ static ALWAYS_INLINE void k_spin_unlock(struct k_spinlock *l, * @cond INTERNAL_HIDDEN */ +#if defined(CONFIG_SMP) && defined(CONFIG_TEST) +/* + * @brief Checks if spinlock is held by some CPU, including the local CPU. + * This API shouldn't be used outside the tests for spinlock + * + * @param l A pointer to the spinlock + * @retval true - if spinlock is held by some CPU; false - otherwise + */ +static ALWAYS_INLINE bool z_spin_is_locked(struct k_spinlock *l) +{ +#ifdef CONFIG_TICKET_SPINLOCKS + atomic_val_t ticket_val = atomic_get(&l->owner); + + return !atomic_cas(&l->tail, ticket_val, ticket_val); +#else + return l->locked; +#endif /* CONFIG_TICKET_SPINLOCKS */ +} +#endif /* defined(CONFIG_SMP) && defined(CONFIG_TEST) */ + /* Internal function: releases the lock, but leaves local interrupts disabled */ static ALWAYS_INLINE void k_spin_release(struct k_spinlock *l) { @@ -273,8 +363,12 @@ static ALWAYS_INLINE void k_spin_release(struct k_spinlock *l) __ASSERT(z_spin_unlock_valid(l), "Not my spinlock %p", l); #endif #ifdef CONFIG_SMP +#ifdef CONFIG_TICKET_SPINLOCKS + atomic_inc(&l->owner); +#else atomic_clear(&l->locked); -#endif +#endif /* CONFIG_TICKET_SPINLOCKS */ +#endif /* CONFIG_SMP */ } #if defined(CONFIG_SPIN_VALIDATE) && defined(__GNUC__) diff --git a/include/zephyr/storage/disk_access.h b/include/zephyr/storage/disk_access.h index 66b513853a7..53774e7666e 100644 --- a/include/zephyr/storage/disk_access.h +++ b/include/zephyr/storage/disk_access.h @@ -63,6 +63,9 @@ int disk_access_status(const char *pdrv); * * Function to read data from disk to a memory buffer. * + * Note: if he disk is of NVMe type, user will need to ensure data_buf + * pointer is 4-bytes aligned. + * * @param[in] pdrv Disk name * @param[in] data_buf Pointer to the memory buffer to put data. * @param[in] start_sector Start disk sector to read from @@ -78,6 +81,9 @@ int disk_access_read(const char *pdrv, uint8_t *data_buf, * * Function write data from memory buffer to disk. * + * Note: if he disk is of NVMe type, user will need to ensure data_buf + * pointer is 4-bytes aligned. + * * @param[in] pdrv Disk name * @param[in] data_buf Pointer to the memory buffer * @param[in] start_sector Start disk sector to write to diff --git a/include/zephyr/sw_isr_table.h b/include/zephyr/sw_isr_table.h index 3fd687d2c58..f43efafad49 100644 --- a/include/zephyr/sw_isr_table.h +++ b/include/zephyr/sw_isr_table.h @@ -15,6 +15,7 @@ #define ZEPHYR_INCLUDE_SW_ISR_TABLE_H_ #if !defined(_ASMLANGUAGE) +#include #include #include @@ -23,10 +24,10 @@ extern "C" { #endif /* Default vector for the IRQ vector table */ -extern void _isr_wrapper(void); +void _isr_wrapper(void); /* Spurious interrupt handler. Throws an error if called */ -extern void z_irq_spurious(const void *unused); +void z_irq_spurious(const void *unused); /* * Note the order: arg first, then ISR. This allows a table entry to be @@ -43,6 +44,12 @@ struct _isr_table_entry { */ extern struct _isr_table_entry _sw_isr_table[]; +struct _irq_parent_entry { + const struct device *dev; + unsigned int irq; + unsigned int offset; +}; + /* * Data structure created in a special binary .intlist section for each * configured interrupt. gen_irq_tables.py pulls this out of the binary and @@ -61,6 +68,22 @@ struct _isr_list { const void *param; }; +#ifdef CONFIG_SHARED_INTERRUPTS +struct z_shared_isr_client { + void (*isr)(const void *arg); + const void *arg; +}; + +struct z_shared_isr_table_entry { + struct z_shared_isr_client clients[CONFIG_SHARED_IRQ_MAX_NUM_CLIENTS]; + size_t client_num; +}; + +void z_shared_isr(const void *data); + +extern struct z_shared_isr_table_entry z_shared_sw_isr_table[]; +#endif /* CONFIG_SHARED_INTERRUPTS */ + /** This interrupt gets put directly in the vector table */ #define ISR_FLAG_DIRECT BIT(0) @@ -81,6 +104,11 @@ struct _isr_list { #ifdef CONFIG_DYNAMIC_INTERRUPTS void z_isr_install(unsigned int irq, void (*routine)(const void *), const void *param); + +#ifdef CONFIG_SHARED_INTERRUPTS +int z_isr_uninstall(unsigned int irq, void (*routine)(const void *), + const void *param); +#endif /* CONFIG_SHARED_INTERRUPTS */ #endif #ifdef __cplusplus diff --git a/include/zephyr/sys/__assert.h b/include/zephyr/sys/__assert.h index 1fa0b86daa8..fc0b9476ea6 100644 --- a/include/zephyr/sys/__assert.h +++ b/include/zephyr/sys/__assert.h @@ -26,7 +26,7 @@ extern "C" { #endif /* Wrapper around printk to avoid including printk.h in assert.h */ -void assert_print(const char *fmt, ...); +void __printf_like(1, 2) assert_print(const char *fmt, ...); #ifdef __cplusplus } diff --git a/include/zephyr/sys/arch_interface.h b/include/zephyr/sys/arch_interface.h index 0cf8cfb24a4..e694bce55cc 100644 --- a/include/zephyr/sys/arch_interface.h +++ b/include/zephyr/sys/arch_interface.h @@ -6,6 +6,7 @@ /** * @defgroup arch-interface Architecture Interface + * @ingroup internal_api * @brief Internal kernel APIs with public scope * * Any public kernel APIs that are implemented as inline functions and need to @@ -323,6 +324,24 @@ int arch_irq_connect_dynamic(unsigned int irq, unsigned int priority, void (*routine)(const void *parameter), const void *parameter, uint32_t flags); +/** + * Arch-specific hook to dynamically uninstall a shared interrupt. + * If the interrupt is not being shared, then the associated + * _sw_isr_table entry will be replaced by (NULL, z_irq_spurious) + * (default entry). + * + * @param irq IRQ line number + * @param priority Interrupt priority + * @param routine Interrupt service routine + * @param parameter ISR parameter + * @param flags Arch-specific IRQ configuration flag + * + * @return 0 in case of success, negative value otherwise + */ +int arch_irq_disconnect_dynamic(unsigned int irq, unsigned int priority, + void (*routine)(const void *parameter), + const void *parameter, uint32_t flags); + /** * @def ARCH_IRQ_CONNECT(irq, pri, isr, arg, flags) * @@ -512,7 +531,7 @@ static inline unsigned int arch_num_cpus(void); * should be enabled when invoking the system call marshallers from the * dispatch table. Thread preemption may occur when handling system calls. * - * Call ids are untrusted and must be bounds-checked, as the value is used to + * Call IDs are untrusted and must be bounds-checked, as the value is used to * index the system call dispatch table, containing function pointers to the * specific system call code. * @@ -623,7 +642,7 @@ static inline uintptr_t arch_syscall_invoke6(uintptr_t arg1, uintptr_t arg2, /** * Indicate whether we are currently running in user mode * - * @return true if the CPU is currently running with user permissions + * @return True if the CPU is currently running with user permissions */ static inline bool arch_is_user_context(void); @@ -750,11 +769,11 @@ int arch_mem_domain_partition_add(struct k_mem_domain *domain, * if the supplied memory buffer spans multiple enabled memory management * regions (even if all such regions permit user access). * - * @warning 0 size buffer has undefined behavior. + * @warning Buffer of size zero (0) has undefined behavior. * * @param addr start address of the buffer * @param size the size of the buffer - * @param write If nonzero, additionally check if the area is writable. + * @param write If non-zero, additionally check if the area is writable. * Otherwise, just check if the memory can be read. * * @return nonzero if the permissions don't match. @@ -769,10 +788,12 @@ int arch_buffer_validate(void *addr, size_t size, int write); * This call returns the optimal virtual address alignment in order to permit * such optimization in the following MMU mapping call. * - * @param[in] phys Physical address of region to be mapped, aligned to MMU_PAGE_SIZE - * @param[in] size Size of region to be mapped, aligned to MMU_PAGE_SIZE + * @param[in] phys Physical address of region to be mapped, + * aligned to @kconfig{CONFIG_MMU_PAGE_SIZE} + * @param[in] size Size of region to be mapped, + * aligned to @kconfig{CONFIG_MMU_PAGE_SIZE} * - * @retval alignment to apply on the virtual address of this region + * @return Alignment to apply on the virtual address of this region */ size_t arch_virt_region_align(uintptr_t phys, size_t size); @@ -816,9 +837,9 @@ FUNC_NORETURN void arch_syscall_oops(void *ssf); /** * @brief Safely take the length of a potentially bad string * - * This must not fault, instead the err parameter must have -1 written to it. + * This must not fault, instead the @p err parameter must have -1 written to it. * This function otherwise should work exactly like libc strnlen(). On success - * *err should be set to 0. + * @p err should be set to 0. * * @param s String to measure * @param maxsize Max length of the string @@ -880,15 +901,15 @@ static inline bool arch_mem_coherent(void *ptr) * is not sufficient on many architectures and coordination with the * arch_switch() implementation is likely required. * - * @arg old_thread The old thread to be flushed before being allowed - * to run on other CPUs. - * @arg old_switch_handle The switch handle to be stored into - * old_thread (it will not be valid until the - * cache is flushed so is not present yet). - * This will be NULL if inside z_swap() - * (because the arch_switch() has not saved it - * yet). - * @arg new_thread The new thread to be invalidated before it runs locally. + * @param old_thread The old thread to be flushed before being allowed + * to run on other CPUs. + * @param old_switch_handle The switch handle to be stored into + * old_thread (it will not be valid until the + * cache is flushed so is not present yet). + * This will be NULL if inside z_swap() + * (because the arch_switch() has not saved it + * yet). + * @param new_thread The new thread to be invalidated before it runs locally. */ #ifndef CONFIG_KERNEL_COHERENCE static inline void arch_cohere_stacks(struct k_thread *old_thread, diff --git a/include/zephyr/sys/atomic.h b/include/zephyr/sys/atomic.h index 2521a6fff98..bcb122bf38a 100644 --- a/include/zephyr/sys/atomic.h +++ b/include/zephyr/sys/atomic.h @@ -147,7 +147,7 @@ static inline bool atomic_test_bit(const atomic_t *target, int bit) * @param target Address of atomic variable or array. * @param bit Bit number (starting from 0). * - * @return true if the bit was set, false if it wasn't. + * @return false if the bit was already cleared, true if it wasn't. */ static inline bool atomic_test_and_clear_bit(atomic_t *target, int bit) { @@ -171,7 +171,7 @@ static inline bool atomic_test_and_clear_bit(atomic_t *target, int bit) * @param target Address of atomic variable or array. * @param bit Bit number (starting from 0). * - * @return true if the bit was set, false if it wasn't. + * @return true if the bit was already set, false if it wasn't. */ static inline bool atomic_test_and_set_bit(atomic_t *target, int bit) { diff --git a/include/zephyr/sys/atomic_arch.h b/include/zephyr/sys/atomic_arch.h index fad339bf933..7305743c4fb 100644 --- a/include/zephyr/sys/atomic_arch.h +++ b/include/zephyr/sys/atomic_arch.h @@ -11,39 +11,39 @@ /* Arch specific atomic primitives */ -extern bool atomic_cas(atomic_t *target, atomic_val_t old_value, +bool atomic_cas(atomic_t *target, atomic_val_t old_value, atomic_val_t new_value); -extern bool atomic_ptr_cas(atomic_ptr_t *target, void *old_value, +bool atomic_ptr_cas(atomic_ptr_t *target, void *old_value, void *new_value); -extern atomic_val_t atomic_add(atomic_t *target, atomic_val_t value); +atomic_val_t atomic_add(atomic_t *target, atomic_val_t value); -extern atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value); +atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value); -extern atomic_val_t atomic_inc(atomic_t *target); +atomic_val_t atomic_inc(atomic_t *target); -extern atomic_val_t atomic_dec(atomic_t *target); +atomic_val_t atomic_dec(atomic_t *target); -extern atomic_val_t atomic_get(const atomic_t *target); +atomic_val_t atomic_get(const atomic_t *target); -extern void *atomic_ptr_get(const atomic_ptr_t *target); +void *atomic_ptr_get(const atomic_ptr_t *target); -extern atomic_val_t atomic_set(atomic_t *target, atomic_val_t value); +atomic_val_t atomic_set(atomic_t *target, atomic_val_t value); -extern void *atomic_ptr_set(atomic_ptr_t *target, void *value); +void *atomic_ptr_set(atomic_ptr_t *target, void *value); -extern atomic_val_t atomic_clear(atomic_t *target); +atomic_val_t atomic_clear(atomic_t *target); -extern void *atomic_ptr_clear(atomic_ptr_t *target); +void *atomic_ptr_clear(atomic_ptr_t *target); -extern atomic_val_t atomic_or(atomic_t *target, atomic_val_t value); +atomic_val_t atomic_or(atomic_t *target, atomic_val_t value); -extern atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value); +atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value); -extern atomic_val_t atomic_and(atomic_t *target, atomic_val_t value); +atomic_val_t atomic_and(atomic_t *target, atomic_val_t value); -extern atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value); +atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value); #endif /* ZEPHYR_INCLUDE_SYS_ATOMIC_ARCH_H_ */ diff --git a/include/zephyr/sys/atomic_c.h b/include/zephyr/sys/atomic_c.h index ee368c28f42..0ea6e6dfa34 100644 --- a/include/zephyr/sys/atomic_c.h +++ b/include/zephyr/sys/atomic_c.h @@ -39,9 +39,9 @@ static inline atomic_val_t atomic_dec(atomic_t *target) } -extern atomic_val_t atomic_get(const atomic_t *target); +atomic_val_t atomic_get(const atomic_t *target); -extern atomic_ptr_val_t atomic_ptr_get(const atomic_ptr_t *target); +atomic_ptr_val_t atomic_ptr_get(const atomic_ptr_t *target); __syscall atomic_val_t atomic_set(atomic_t *target, atomic_val_t value); diff --git a/include/zephyr/sys/barrier.h b/include/zephyr/sys/barrier.h index dacc0ba62f5..5390cb38cf0 100644 --- a/include/zephyr/sys/barrier.h +++ b/include/zephyr/sys/barrier.h @@ -11,7 +11,7 @@ #if defined(CONFIG_BARRIER_OPERATIONS_ARCH) # if defined(CONFIG_ARM) -# include +# include # elif defined(CONFIG_ARM64) # include # endif diff --git a/include/zephyr/sys/byteorder.h b/include/zephyr/sys/byteorder.h index eebab0fb0be..978255fd02d 100644 --- a/include/zephyr/sys/byteorder.h +++ b/include/zephyr/sys/byteorder.h @@ -168,6 +168,49 @@ * @return 48-bit integer in big-endian format. */ +/** @def sys_uint16_to_array + * @brief Convert 16-bit unsigned integer to byte array. + * + * @details Byte order aware macro to treat an unsigned integer + * as an array, rather than an integer literal. For example, + * `0x0123` would be converted to `{0x01, 0x23}` for big endian + * machines, and `{0x23, 0x01}` for little endian machines. + * + * @param val 16-bit unsigned integer. + * + * @return 16-bit unsigned integer as byte array. + */ + +/** @def sys_uint32_to_array + * @brief Convert 32-bit unsigned integer to byte array. + * + * @details Byte order aware macro to treat an unsigned integer + * as an array, rather than an integer literal. For example, + * `0x01234567` would be converted to `{0x01, 0x23, 0x45, 0x67}` + * for big endian machines, and `{0x67, 0x45, 0x23, 0x01}` for + * little endian machines. + * + * @param val 32-bit unsigned integer. + * + * @return 32-bit unsigned integer as byte array. + */ + +/** @def sys_uint64_to_array + * @brief Convert 64-bit unsigned integer to byte array. + * + * @details Byte order aware macro to treat an unsigned integer + * as an array, rather than an integer literal. For example, + * `0x0123456789abcdef` would be converted to + * `{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}` + * for big endian machines, and + * `{0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01}` for + * little endian machines. + * + * @param val 64-bit unsigned integer. + * + * @return 64-bit unsigned integer as byte array. + */ + #ifdef CONFIG_LITTLE_ENDIAN #define sys_le16_to_cpu(val) (val) #define sys_cpu_to_le16(val) (val) @@ -189,6 +232,27 @@ #define sys_cpu_to_be48(val) __bswap_48(val) #define sys_be64_to_cpu(val) __bswap_64(val) #define sys_cpu_to_be64(val) __bswap_64(val) + +#define sys_uint16_to_array(val) { \ + ((val) & 0xff), \ + (((val) >> 8) & 0xff)} + +#define sys_uint32_to_array(val) { \ + ((val) & 0xff), \ + (((val) >> 8) & 0xff), \ + (((val) >> 16) & 0xff), \ + (((val) >> 24) & 0xff)} + +#define sys_uint64_to_array(val) { \ + ((val) & 0xff), \ + (((val) >> 8) & 0xff), \ + (((val) >> 16) & 0xff), \ + (((val) >> 24) & 0xff), \ + (((val) >> 32) & 0xff), \ + (((val) >> 40) & 0xff), \ + (((val) >> 48) & 0xff), \ + (((val) >> 56) & 0xff)} + #else #define sys_le16_to_cpu(val) __bswap_16(val) #define sys_cpu_to_le16(val) __bswap_16(val) @@ -210,6 +274,27 @@ #define sys_cpu_to_be48(val) (val) #define sys_be64_to_cpu(val) (val) #define sys_cpu_to_be64(val) (val) + +#define sys_uint16_to_array(val) { \ + (((val) >> 8) & 0xff), \ + ((val) & 0xff)} + +#define sys_uint32_to_array(val) { \ + (((val) >> 24) & 0xff), \ + (((val) >> 16) & 0xff), \ + (((val) >> 8) & 0xff), \ + ((val) & 0xff)} + +#define sys_uint64_to_array(val) { \ + (((val) >> 56) & 0xff), \ + (((val) >> 48) & 0xff), \ + (((val) >> 40) & 0xff), \ + (((val) >> 32) & 0xff), \ + (((val) >> 24) & 0xff), \ + (((val) >> 16) & 0xff), \ + (((val) >> 8) & 0xff), \ + ((val) & 0xff)} + #endif /** diff --git a/include/zephyr/sys/cbprintf_cxx.h b/include/zephyr/sys/cbprintf_cxx.h index a1e8c963285..3b65b229517 100644 --- a/include/zephyr/sys/cbprintf_cxx.h +++ b/include/zephyr/sys/cbprintf_cxx.h @@ -88,6 +88,57 @@ static inline int z_cbprintf_cxx_is_pchar(T arg, bool const_as_fixed) _Pragma("GCC diagnostic pop") } +/* C++ version for determining if variable type is numeric and fits in 32 bit word. */ +static inline int z_cbprintf_cxx_is_word_num(char) +{ + return 1; +} + +static inline int z_cbprintf_cxx_is_word_num(unsigned char) +{ + return 1; +} + +static inline int z_cbprintf_cxx_is_word_num(short) +{ + return 1; +} + +static inline int z_cbprintf_cxx_is_word_num(unsigned short) +{ + return 1; +} + +static inline int z_cbprintf_cxx_is_word_num(int) +{ + return 1; +} + +static inline int z_cbprintf_cxx_is_word_num(unsigned int) +{ + return 1; +} + +static inline int z_cbprintf_cxx_is_word_num(long) +{ + return (sizeof(long) <= sizeof(uint32_t)) ? 1 : 0; +} + +static inline int z_cbprintf_cxx_is_word_num(unsigned long) +{ + return (sizeof(long) <= sizeof(uint32_t)) ? 1 : 0; +} + +template < typename T > +static inline int z_cbprintf_cxx_is_word_num(T arg) +{ + ARG_UNUSED(arg); + _Pragma("GCC diagnostic push") + _Pragma("GCC diagnostic ignored \"-Wpointer-arith\"") + return 0; + _Pragma("GCC diagnostic pop") +} + /* C++ version for calculating argument size. */ static inline size_t z_cbprintf_cxx_arg_size(float f) { diff --git a/include/zephyr/sys/cbprintf_internal.h b/include/zephyr/sys/cbprintf_internal.h index 61bd250a30c..eed2bbc3944 100644 --- a/include/zephyr/sys/cbprintf_internal.h +++ b/include/zephyr/sys/cbprintf_internal.h @@ -113,6 +113,31 @@ extern "C" { 0) #endif +/** @brief Check if argument fits in 32 bit word. + * + * @param x Input argument. + * + * @retval 1 if variable is of type that fits in 32 bit word. + * @retval 0 if variable is of different type. + */ +#ifdef __cplusplus +#define Z_CBPRINTF_IS_WORD_NUM(x) \ + z_cbprintf_cxx_is_word_num(x) +#else +#define Z_CBPRINTF_IS_WORD_NUM(x) \ + _Generic(x, \ + char : 1, \ + unsigned char : 1, \ + short : 1, \ + unsigned short : 1, \ + int : 1, \ + unsigned int : 1, \ + long : sizeof(long) <= 4, \ + unsigned long : sizeof(long) <= 4, \ + default : \ + 0) +#endif + /* @brief Check if argument is a certain type of char pointer. What exectly is checked * depends on @p flags. If flags is 0 then 1 is returned if @p x is a char pointer. * diff --git a/include/zephyr/sys/crc.h b/include/zephyr/sys/crc.h index 7c131f4cbfd..e29fce45d9e 100644 --- a/include/zephyr/sys/crc.h +++ b/include/zephyr/sys/crc.h @@ -47,6 +47,8 @@ extern "C" { * These values should be used with the @ref crc dispatch function. */ enum crc_type { + CRC4, /**< Use @ref crc4 */ + CRC4_TI, /**< Use @ref crc4_ti */ CRC7_BE, /**< Use @ref crc7_be */ CRC8, /**< Use @ref crc8 */ CRC8_CCITT, /**< Use @ref crc8_ccitt */ @@ -278,6 +280,41 @@ uint8_t crc8_ccitt(uint8_t initial_value, const void *buf, size_t len); */ uint8_t crc7_be(uint8_t seed, const uint8_t *src, size_t len); +/** + * @brief Compute the CRC-4 checksum of a buffer. + * + * Used by the TMAG5170 sensor. Uses 0x03 as the + * polynomial with no reflection. 4 most significant + * bits of the CRC result will be set to zero. + * + * @param seed Value to seed the CRC with + * @param src Input bytes for the computation + * @param len Length of the input in bytes + * + * @return The computed CRC4 value + */ +uint8_t crc4_ti(uint8_t seed, const uint8_t *src, size_t len); + +/** + * @brief Generic function for computing CRC 4 + * + * Compute CRC 4 by passing in the address of the input, the input length + * and polynomial used in addition to the initial value. The input buffer + * must be aligned to a whole byte. It is guaranteed that 4 most significant + * bits of the result will be set to zero. + * + * @param src Input bytes for the computation + * @param len Length of the input in bytes + * @param polynomial The polynomial to use omitting the leading x^4 + * coefficient + * @param initial_value Initial value for the CRC computation + * @param reversed Should we use reflected/reversed values or not + * + * @return The computed CRC4 value + */ +uint8_t crc4(const uint8_t *src, size_t len, uint8_t polynomial, uint8_t initial_value, + bool reversed); + /** * @brief Compute a CRC checksum, in a generic way. * @@ -305,6 +342,10 @@ static inline uint32_t crc_by_type(enum crc_type type, const uint8_t *src, size_ bool last) { switch (type) { + case CRC4: + return crc4(src, len, poly, seed, reflect); + case CRC4_TI: + return crc4_ti(seed, src, len); case CRC7_BE: return crc7_be(seed, src, len); case CRC8: diff --git a/include/zephyr/sys/device_mmio.h b/include/zephyr/sys/device_mmio.h index 4358e246339..c50a12782ee 100644 --- a/include/zephyr/sys/device_mmio.h +++ b/include/zephyr/sys/device_mmio.h @@ -2,15 +2,6 @@ * Copyright (c) 2020 Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 - * - * Definitions and helper macros for managing driver memory-mapped - * input/output (MMIO) regions appropriately in either RAM or ROM. - * - * In most cases drivers will just want to include device.h, but - * including this separately may be needed for arch-level driver code - * which uses the DEVICE_MMIO_TOPLEVEL variants and including the - * main device.h would introduce header dependency loops due to that - * header's reliance on kernel.h. */ #ifndef ZEPHYR_INCLUDE_SYS_DEVICE_MMIO_H #define ZEPHYR_INCLUDE_SYS_DEVICE_MMIO_H @@ -21,6 +12,16 @@ /** * @defgroup device-mmio Device memory-mapped IO management * @ingroup device_model + * + * Definitions and helper macros for managing driver memory-mapped + * input/output (MMIO) regions appropriately in either RAM or ROM. + * + * In most cases drivers will just want to include device.h, but + * including this separately may be needed for arch-level driver code + * which uses the DEVICE_MMIO_TOPLEVEL variants and including the + * main device.h would introduce header dependency loops due to that + * header's reliance on kernel.h. + * * @{ */ @@ -44,7 +45,7 @@ #ifndef _ASMLANGUAGE #include #include -#include +#include #include #ifdef DEVICE_MMIO_IS_IN_RAM @@ -85,12 +86,12 @@ struct z_device_mmio_rom { * * @see k_map() * - * @param virt_addr [out] Output linear address storage location, most - * users will want some DEVICE_MMIO_RAM_PTR() value - * @param phys_addr Physical address base of the MMIO region - * @param size Size of the MMIO region - * @param flags Caching mode and access flags, see K_MEM_CACHE_* and - * K_MEM_PERM_* macros + * @param[out] virt_addr Output linear address storage location, most + * users will want some DEVICE_MMIO_RAM_PTR() value + * @param[in] phys_addr Physical address base of the MMIO region + * @param[in] size Size of the MMIO region + * @param[in] flags Caching mode and access flags, see K_MEM_CACHE_* and + * K_MEM_PERM_* macros */ __boot_func static inline void device_map(mm_reg_t *virt_addr, uintptr_t phys_addr, @@ -161,12 +162,16 @@ struct z_device_mmio_rom { * * Example for a driver named "foo": * + * @code{.c} + * * struct foo_driver_data { * DEVICE_MMIO_RAM; * int wibble; * ... * } * + * @endcode + * * No build-time initialization of this memory is necessary; it * will be set up in the init function by DEVICE_MMIO_MAP(). * @@ -210,12 +215,16 @@ struct z_device_mmio_rom { * * Example for a driver named "foo": * + * @code{.c} + * * struct foo_config { * DEVICE_MMIO_ROM; * int baz; * ... * } * + * @endcode + * * @see DEVICE_MMIO_ROM_INIT() */ #define DEVICE_MMIO_ROM struct z_device_mmio_rom _mmio @@ -240,12 +249,16 @@ struct z_device_mmio_rom { * * Example for a driver belonging to the "foo" subsystem: * + * @code{.c} + * * struct foo_config my_config = { * DEVICE_MMIO_ROM_INIT(DT_DRV_INST(...)), * .baz = 2; * ... * } * + * @endcode + * * @see DEVICE_MMIO_ROM() * * @param node_id DTS node_id @@ -332,6 +345,8 @@ struct z_device_mmio_rom { * * Example for a driver named "foo": * + * @code{.c} + * * struct foo_driver_data { * int blarg; * DEVICE_MMIO_NAMED_RAM(corge); @@ -340,6 +355,8 @@ struct z_device_mmio_rom { * ... * } * + * @endcode + * * No build-time initialization of this memory is necessary; it * will be set up in the init function by DEVICE_MMIO_NAMED_MAP(). * @@ -385,6 +402,8 @@ struct z_device_mmio_rom { * * Example for a driver named "foo": * + * @code{.c} + * * struct foo_config { * int bar; * DEVICE_MMIO_NAMED_ROM(corge); @@ -393,6 +412,8 @@ struct z_device_mmio_rom { * ... * } * + * @endcode + * * @see DEVICE_MMIO_NAMED_ROM_INIT() * * @param name Member name to store within config @@ -422,6 +443,8 @@ struct z_device_mmio_rom { * Example for an instance of a driver belonging to the "foo" subsystem * that will have two regions named 'corge' and 'grault': * + * @code{.c} + * * struct foo_config my_config = { * bar = 7; * DEVICE_MMIO_NAMED_ROM_INIT(corge, DT_DRV_INST(...)); @@ -430,6 +453,8 @@ struct z_device_mmio_rom { * ... * } * + * @endcode + * * @see DEVICE_MMIO_NAMED_ROM() * * @param name Member name within config for the MMIO region diff --git a/include/zephyr/sys/dlist.h b/include/zephyr/sys/dlist.h index 0c269f5da92..03f2a5e94c8 100644 --- a/include/zephyr/sys/dlist.h +++ b/include/zephyr/sys/dlist.h @@ -165,7 +165,7 @@ typedef struct _dnode sys_dnode_t; * } * * @param __dl A pointer on a sys_dlist_t to iterate on - * @param __cn A pointer to peek each entry of the list + * @param __cn A container struct type pointer to peek each entry of the list * @param __n The field name of sys_dnode_t within the container struct */ #define SYS_DLIST_FOR_EACH_CONTAINER(__dl, __cn, __n) \ @@ -184,8 +184,8 @@ typedef struct _dnode sys_dnode_t; * } * * @param __dl A pointer on a sys_dlist_t to iterate on - * @param __cn A pointer to peek each entry of the list - * @param __cns A pointer for the loop to run safely + * @param __cn A container struct type pointer to peek each entry of the list + * @param __cns A container struct type pointer for the loop to run safely * @param __n The field name of sys_dnode_t within the container struct */ #define SYS_DLIST_FOR_EACH_CONTAINER_SAFE(__dl, __cn, __cns, __n) \ @@ -534,6 +534,24 @@ static inline sys_dnode_t *sys_dlist_get(sys_dlist_t *list) return node; } +/** + * @brief Compute the size of the given list in O(n) time + * + * @param list A pointer on the list + * + * @return an integer equal to the size of the list, or 0 if empty + */ +static inline size_t sys_dlist_len(sys_dlist_t *list) +{ + size_t len = 0; + sys_dnode_t *node = NULL; + + SYS_DLIST_FOR_EACH_NODE(list, node) { + len++; + } + return len; +} + /** @} */ #ifdef __cplusplus diff --git a/include/zephyr/sys/heap_listener.h b/include/zephyr/sys/heap_listener.h index 5923d5e2635..a2f49d2a7ed 100644 --- a/include/zephyr/sys/heap_listener.h +++ b/include/zephyr/sys/heap_listener.h @@ -195,7 +195,7 @@ void heap_listener_notify_resize(uintptr_t heap_id, void *old_heap_end, void *ne * @code * void on_heap_alloc(uintptr_t heap_id, void *mem, size_t bytes) * { - * LOG_INF("Memory allocated at %p, size %ld", heap_id, mem, bytes); + * LOG_INF("Memory allocated at %p, size %ld", mem, bytes); * } * * HEAP_LISTENER_ALLOC_DEFINE(my_listener, HEAP_ID_LIBC, on_heap_alloc); @@ -221,7 +221,7 @@ void heap_listener_notify_resize(uintptr_t heap_id, void *old_heap_end, void *ne * @code * void on_heap_free(uintptr_t heap_id, void *mem, size_t bytes) * { - * LOG_INF("Memory freed at %p, size %ld", heap_id, mem, bytes); + * LOG_INF("Memory freed at %p, size %ld", mem, bytes); * } * * HEAP_LISTENER_FREE_DEFINE(my_listener, HEAP_ID_LIBC, on_heap_free); diff --git a/include/zephyr/sys/internal/kobject_internal.h b/include/zephyr/sys/internal/kobject_internal.h new file mode 100644 index 00000000000..ea19d0f9a8d --- /dev/null +++ b/include/zephyr/sys/internal/kobject_internal.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_SYS_INTERNAL_KOBJECT_INTERNAL_H +#define ZEPHYR_INCLUDE_SYS_INTERNAL_KOBJECT_INTERNAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup usermode_internal_apis User Mode Internal APIs + * @ingroup internal_api + * @{ + */ + +#if defined(CONFIG_USERSPACE) || defined(__DOXYGEN__) +#if defined(CONFIG_GEN_PRIV_STACKS) || defined(__DOXYGEN__) +/* Metadata struct for K_OBJ_THREAD_STACK_ELEMENT */ +struct z_stack_data { + /* Size of the entire stack object, including reserved areas */ + size_t size; + + /* Stack buffer for privilege mode elevations */ + uint8_t *priv; +}; +#endif /* CONFIG_GEN_PRIV_STACKS */ + +/* Object extra data. Only some objects use this, determined by object type */ +union k_object_data { + /* Backing mutex for K_OBJ_SYS_MUTEX */ + struct k_mutex *mutex; + + /* Numerical thread ID for K_OBJ_THREAD */ + unsigned int thread_id; + +#if defined(CONFIG_GEN_PRIV_STACKS) || defined(__DOXYGEN__) + /* Metadata for K_OBJ_THREAD_STACK_ELEMENT */ + const struct z_stack_data *stack_data; +#else + /* Stack buffer size for K_OBJ_THREAD_STACK_ELEMENT */ + size_t stack_size; +#endif /* CONFIG_GEN_PRIV_STACKS */ + + /* Futex wait queue and spinlock for K_OBJ_FUTEX */ + struct z_futex_data *futex_data; + + /* All other objects */ + int unused; +}; + +/** + * @brief Table generated by gperf, these objects are retrieved via + * k_object_find(). + * + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +struct k_object { + void *name; + uint8_t perms[CONFIG_MAX_THREAD_BYTES]; + uint8_t type; + uint8_t flags; + union k_object_data data; +} __packed __aligned(4); + +struct k_object_assignment { + struct k_thread *thread; + void * const *objects; +}; + + +/** + * Lookup a kernel object and init its metadata if it exists + * + * Calling this on an object will make it usable from userspace. + * Intended to be called as the last statement in kernel object init + * functions. + * + * @param obj Address of the kernel object + * + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +void k_object_init(const void *obj); + + +#else +/* LCOV_EXCL_START */ +static inline void k_object_init(const void *obj) +{ + ARG_UNUSED(obj); +} +/* LCOV_EXCL_STOP */ +#endif /* !CONFIG_USERSPACE */ + +#ifdef CONFIG_DYNAMIC_OBJECTS +/** + * Allocate memory and install as a generic kernel object + * + * This is a low-level function to allocate some memory, and register that + * allocated memory in the kernel object lookup tables with type K_OBJ_ANY. + * Initialization state and thread permissions will be cleared. The + * returned k_object's data value will be uninitialized. + * + * Most users will want to use k_object_alloc() instead. + * + * Memory allocated will be drawn from the calling thread's reasource pool + * and may be freed later by passing the actual object pointer (found + * in the returned k_object's 'name' member) to k_object_free(). + * + * @param align Required memory alignment for the allocated object + * @param size Size of the allocated object + * @return NULL on insufficient memory + * @return A pointer to the associated k_object that is installed in the + * kernel object tables + * + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +struct k_object *k_object_create_dynamic_aligned(size_t align, size_t size); + +/** + * Allocate memory and install as a generic kernel object + * + * This is a low-level function to allocate some memory, and register that + * allocated memory in the kernel object lookup tables with type K_OBJ_ANY. + * Initialization state and thread permissions will be cleared. The + * returned k_object's data value will be uninitialized. + * + * Most users will want to use k_object_alloc() instead. + * + * Memory allocated will be drawn from the calling thread's reasource pool + * and may be freed later by passing the actual object pointer (found + * in the returned k_object's 'name' member) to k_object_free(). + * + * @param size Size of the allocated object + * @return NULL on insufficient memory + * @return A pointer to the associated k_object that is installed in the + * kernel object tables + * + * @note This is an internal API. Do not use unless you are extending + * functionality in the Zephyr tree. + */ +static inline struct k_object *k_object_create_dynamic(size_t size) +{ + return k_object_create_dynamic_aligned(0, size); +} + +#else + +/* LCOV_EXCL_START */ +static inline struct k_object *k_object_create_dynamic_aligned(size_t align, + size_t size) +{ + ARG_UNUSED(align); + ARG_UNUSED(size); + + return NULL; +} + +static inline struct k_object *k_object_create_dynamic(size_t size) +{ + ARG_UNUSED(size); + + return NULL; +} + +/* LCOV_EXCL_STOP */ +#endif /* CONFIG_DYNAMIC_OBJECTS */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/zephyr/sys/kobject.h b/include/zephyr/sys/kobject.h index 64db4d781c9..628bb967551 100644 --- a/include/zephyr/sys/kobject.h +++ b/include/zephyr/sys/kobject.h @@ -10,6 +10,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -48,54 +49,6 @@ enum k_objects { */ #ifdef CONFIG_USERSPACE -#ifdef CONFIG_GEN_PRIV_STACKS -/* Metadata struct for K_OBJ_THREAD_STACK_ELEMENT */ -struct z_stack_data { - /* Size of the entire stack object, including reserved areas */ - size_t size; - - /* Stack buffer for privilege mode elevations */ - uint8_t *priv; -}; -#endif /* CONFIG_GEN_PRIV_STACKS */ - -/* Object extra data. Only some objects use this, determined by object type */ -union z_object_data { - /* Backing mutex for K_OBJ_SYS_MUTEX */ - struct k_mutex *mutex; - - /* Numerical thread ID for K_OBJ_THREAD */ - unsigned int thread_id; - -#ifdef CONFIG_GEN_PRIV_STACKS - /* Metadata for K_OBJ_THREAD_STACK_ELEMENT */ - const struct z_stack_data *stack_data; -#else - /* Stack buffer size for K_OBJ_THREAD_STACK_ELEMENT */ - size_t stack_size; -#endif /* CONFIG_GEN_PRIV_STACKS */ - - /* Futex wait queue and spinlock for K_OBJ_FUTEX */ - struct z_futex_data *futex_data; - - /* All other objects */ - int unused; -}; - -/* Table generated by gperf, these objects are retrieved via - * z_object_find() */ -struct z_object { - void *name; - uint8_t perms[CONFIG_MAX_THREAD_BYTES]; - uint8_t type; - uint8_t flags; - union z_object_data data; -} __packed __aligned(4); - -struct z_object_assignment { - struct k_thread *thread; - void * const *objects; -}; /** * @brief Grant a static thread access to a list of kernel objects @@ -112,7 +65,7 @@ struct z_object_assignment { #define K_THREAD_ACCESS_GRANT(name_, ...) \ static void * const _CONCAT(_object_list_, name_)[] = \ { __VA_ARGS__, NULL }; \ - static const STRUCT_SECTION_ITERABLE(z_object_assignment, \ + static const STRUCT_SECTION_ITERABLE(k_object_assignment, \ _CONCAT(_object_access_, name_)) = \ { (&_k_thread_obj_ ## name_), \ (_CONCAT(_object_list_, name_)) } @@ -126,17 +79,6 @@ struct z_object_assignment { /** Driver Object */ #define K_OBJ_FLAG_DRIVER BIT(3) -/** - * Lookup a kernel object and init its metadata if it exists - * - * Calling this on an object will make it usable from userspace. - * Intended to be called as the last statement in kernel object init - * functions. - * - * @param obj Address of the kernel object - */ -void z_object_init(const void *obj); - /** * Grant a thread access to a kernel object * @@ -192,18 +134,23 @@ __syscall void k_object_release(const void *object); */ void k_object_access_all_grant(const void *object); +/** + * Check if a kernel object is of certain type and is valid. + * + * This checks if the kernel object exists, of certain type, + * and has been initialized. + * + * @param obj Address of the kernel object + * @param otype Object type (use K_OBJ_ANY for ignoring type checking) + * @return True if kernel object (@a obj) exists, of certain type, and + * has been initialized. False otherwise. + */ +bool k_object_is_valid(const void *obj, enum k_objects otype); + #else /* LCOV_EXCL_START */ #define K_THREAD_ACCESS_GRANT(thread, ...) -/** - * @internal - */ -static inline void z_object_init(const void *obj) -{ - ARG_UNUSED(obj); -} - /** * @internal */ @@ -236,6 +183,15 @@ static inline void k_object_access_all_grant(const void *object) { ARG_UNUSED(object); } + +static inline bool k_object_is_valid(const void *obj, enum k_objects otype) +{ + ARG_UNUSED(obj); + ARG_UNUSED(otype); + + return true; +} + /* LCOV_EXCL_STOP */ #endif /* !CONFIG_USERSPACE */ @@ -275,52 +231,6 @@ __syscall void *k_object_alloc(enum k_objects otype); */ __syscall void *k_object_alloc_size(enum k_objects otype, size_t size); -/** - * Allocate memory and install as a generic kernel object - * - * This is a low-level function to allocate some memory, and register that - * allocated memory in the kernel object lookup tables with type K_OBJ_ANY. - * Initialization state and thread permissions will be cleared. The - * returned z_object's data value will be uninitialized. - * - * Most users will want to use k_object_alloc() instead. - * - * Memory allocated will be drawn from the calling thread's reasource pool - * and may be freed later by passing the actual object pointer (found - * in the returned z_object's 'name' member) to k_object_free(). - * - * @param align Required memory alignment for the allocated object - * @param size Size of the allocated object - * @return NULL on insufficient memory - * @return A pointer to the associated z_object that is installed in the - * kernel object tables - */ -struct z_object *z_dynamic_object_aligned_create(size_t align, size_t size); - -/** - * Allocate memory and install as a generic kernel object - * - * This is a low-level function to allocate some memory, and register that - * allocated memory in the kernel object lookup tables with type K_OBJ_ANY. - * Initialization state and thread permissions will be cleared. The - * returned z_object's data value will be uninitialized. - * - * Most users will want to use k_object_alloc() instead. - * - * Memory allocated will be drawn from the calling thread's reasource pool - * and may be freed later by passing the actual object pointer (found - * in the returned z_object's 'name' member) to k_object_free(). - * - * @param size Size of the allocated object - * @return NULL on insufficient memory - * @return A pointer to the associated z_object that is installed in the - * kernel object tables - */ -static inline struct z_object *z_dynamic_object_create(size_t size) -{ - return z_dynamic_object_aligned_create(0, size); -} - /** * Free a kernel object previously allocated with k_object_alloc() * @@ -350,22 +260,6 @@ static inline void *z_impl_k_object_alloc_size(enum k_objects otype, return NULL; } -static inline struct z_object *z_dynamic_object_aligned_create(size_t align, - size_t size) -{ - ARG_UNUSED(align); - ARG_UNUSED(size); - - return NULL; -} - -static inline struct z_object *z_dynamic_object_create(size_t size) -{ - ARG_UNUSED(size); - - return NULL; -} - /** * @brief Free an object * diff --git a/include/zephyr/sys/libc-hooks.h b/include/zephyr/sys/libc-hooks.h index d1a1afcbf40..e00efc6de26 100644 --- a/include/zephyr/sys/libc-hooks.h +++ b/include/zephyr/sys/libc-hooks.h @@ -92,9 +92,7 @@ __syscall size_t zephyr_fwrite(const void *ZRESTRICT ptr, size_t size, extern struct k_mem_partition z_malloc_partition; #endif -#if defined(CONFIG_NEWLIB_LIBC) || (defined(CONFIG_STACK_CANARIES) && \ - !defined(CONFIG_STACK_CANARIES_TLS)) || \ -defined(CONFIG_PICOLIBC) || defined(CONFIG_NEED_LIBC_MEM_PARTITION) +#ifdef CONFIG_NEED_LIBC_MEM_PARTITION /* - All newlib globals will be placed into z_libc_partition. * - Minimal C library globals, if any, will be placed into * z_libc_partition. diff --git a/include/zephyr/sys/list_gen.h b/include/zephyr/sys/list_gen.h index 6029e4eceb4..f1aa1b3a510 100644 --- a/include/zephyr/sys/list_gen.h +++ b/include/zephyr/sys/list_gen.h @@ -234,4 +234,15 @@ return false; \ } +#define Z_GENLIST_LEN(__lname, __nname) \ + static inline size_t sys_##__lname##_len(sys_##__lname##_t * list) \ + { \ + size_t len = 0; \ + static sys_##__nname##_t * node; \ + Z_GENLIST_FOR_EACH_NODE(__lname, list, node) { \ + len++; \ + } \ + return len; \ + } + #endif /* ZEPHYR_INCLUDE_SYS_LIST_GEN_H_ */ diff --git a/include/zephyr/sys/math_extras.h b/include/zephyr/sys/math_extras.h index aeaf5331088..e66a966f7bd 100644 --- a/include/zephyr/sys/math_extras.h +++ b/include/zephyr/sys/math_extras.h @@ -5,13 +5,15 @@ */ /** - * @file * @brief Extra arithmetic and bit manipulation functions. + * @defgroup math_extras Math extras + * @ingroup utilities * - * @details This header file provides portable wrapper functions for a number of - * arithmetic and bit-counting functions that are often provided by compiler - * builtins. If the compiler does not have an appropriate builtin, a portable C + * Portable wrapper functions for a number of arithmetic and bit-counting functions that are often + * provided by compiler builtins. If the compiler does not have an appropriate builtin, a portable C * implementation is used instead. + * + * @{ */ #ifndef ZEPHYR_INCLUDE_SYS_MATH_EXTRAS_H_ @@ -28,10 +30,44 @@ * true if the operation overflowed. */ /**@{*/ + +/** + * @brief Add two unsigned 16-bit integers. + * @param a First operand. + * @param b Second operand. + * @param result Pointer to the result. + * @return true if the operation overflowed. + */ static bool u16_add_overflow(uint16_t a, uint16_t b, uint16_t *result); + +/** + * @brief Add two unsigned 32-bit integers. + * @param a First operand. + * @param b Second operand. + * @param result Pointer to the result. + * @return true if the operation overflowed. + */ + static bool u32_add_overflow(uint32_t a, uint32_t b, uint32_t *result); + +/** + * @brief Add two unsigned 64-bit integers. + * @param a First operand. + * @param b Second operand. + * @param result Pointer to the result. + * @return true if the operation overflowed. + */ static bool u64_add_overflow(uint64_t a, uint64_t b, uint64_t *result); + +/** + * @brief Add two size_t integers. + * @param a First operand. + * @param b Second operand. + * @param result Pointer to the result. + * @return true if the operation overflowed. + */ static bool size_add_overflow(size_t a, size_t b, size_t *result); + /**@}*/ /** @@ -41,10 +77,43 @@ static bool size_add_overflow(size_t a, size_t b, size_t *result); * true if the operation overflowed. */ /**@{*/ + +/** + * @brief Multiply two unsigned 16-bit integers. + * @param a First operand. + * @param b Second operand. + * @param result Pointer to the result. + * @return true if the operation overflowed. + */ static bool u16_mul_overflow(uint16_t a, uint16_t b, uint16_t *result); + +/** + * @brief Multiply two unsigned 32-bit integers. + * @param a First operand. + * @param b Second operand. + * @param result Pointer to the result. + * @return true if the operation overflowed. + */ + static bool u32_mul_overflow(uint32_t a, uint32_t b, uint32_t *result); +/** + * @brief Multiply two unsigned 64-bit integers. + * @param a First operand. + * @param b Second operand. + * @param result Pointer to the result. + * @return true if the operation overflowed. + */ static bool u64_mul_overflow(uint64_t a, uint64_t b, uint64_t *result); + +/** + * @brief Multiply two size_t integers. + * @param a First operand. + * @param b Second operand. + * @param result Pointer to the result. + * @return true if the operation overflowed. + */ static bool size_mul_overflow(size_t a, size_t b, size_t *result); + /**@}*/ /** @@ -54,8 +123,21 @@ static bool size_mul_overflow(size_t a, size_t b, size_t *result); * When `x = 0`, this is the size of `x` in bits. */ /**@{*/ + +/** + * @brief Count the number of leading zero bits in a 32-bit integer. + * @param x Integer to count leading zeros in. + * @return Number of leading zero bits in `x`. + */ static int u32_count_leading_zeros(uint32_t x); + +/** + * @brief Count the number of leading zero bits in a 64-bit integer. + * @param x Integer to count leading zeros in. + * @return Number of leading zero bits in `x`. + */ static int u64_count_leading_zeros(uint64_t x); + /**@}*/ /** @@ -65,8 +147,23 @@ static int u64_count_leading_zeros(uint64_t x); * When `x = 0`, this is the size of `x` in bits. */ /**@{*/ + +/** + * @brief Count the number of trailing zero bits in a 32-bit integer. + * @param x Integer to count trailing zeros in. + * @return Number of trailing zero bits in `x`. + */ static int u32_count_trailing_zeros(uint32_t x); + +/** + * @brief Count the number of trailing zero bits in a 64-bit integer. + * @param x Integer to count trailing zeros in. + * @return Number of trailing zero bits in `x`. + */ static int u64_count_trailing_zeros(uint64_t x); + +/**@}*/ + /**@}*/ #include diff --git a/include/zephyr/sys/mem_blocks.h b/include/zephyr/sys/mem_blocks.h index 53f6cbf2bb2..fe1565e3a8c 100644 --- a/include/zephyr/sys/mem_blocks.h +++ b/include/zephyr/sys/mem_blocks.h @@ -82,12 +82,17 @@ typedef sys_mem_blocks_t *(*sys_multi_mem_blocks_choice_fn_t) * @cond INTERNAL_HIDDEN */ -struct sys_mem_blocks { - /* Number of blocks */ - uint32_t num_blocks; +struct sys_mem_blocks_info { + uint32_t num_blocks; /* Total number of blocks */ + uint8_t blk_sz_shift; /* Bit shift for block size */ +#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS + uint32_t used_blocks; /* Current number of blocks in use */ + uint32_t max_used_blocks; /* Maximum number of blocks in use */ +#endif +}; - /* Bit shift for block size */ - uint8_t blk_sz_shift; +struct sys_mem_blocks { + struct sys_mem_blocks_info info; /* Memory block buffer */ uint8_t *buffer; @@ -98,11 +103,10 @@ struct sys_mem_blocks { #ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS /* Spinlock guarding access to memory block internals */ struct k_spinlock lock; - - uint32_t used_blocks; - uint32_t max_used_blocks; #endif - +#ifdef CONFIG_OBJ_CORE_SYS_MEM_BLOCKS + struct k_obj_core obj_core; +#endif }; struct sys_multi_mem_blocks { @@ -124,12 +128,15 @@ struct sys_multi_mem_blocks { #define _SYS_MEM_BLOCKS_DEFINE_WITH_EXT_BUF(name, blk_sz, num_blks, buf, mbmod) \ _SYS_BITARRAY_DEFINE(_sys_mem_blocks_bitmap_##name, \ num_blks, mbmod); \ - mbmod sys_mem_blocks_t name = { \ - .num_blocks = num_blks, \ - .blk_sz_shift = ilog2(blk_sz), \ + mbmod struct sys_mem_blocks name = { \ + .info = {num_blks, ilog2(blk_sz)}, \ .buffer = buf, \ .bitmap = &_sys_mem_blocks_bitmap_##name, \ - } + }; \ + STRUCT_SECTION_ITERABLE_ALTERNATE(sys_mem_blocks_ptr, \ + sys_mem_blocks *, \ + __##name##_ptr) = &name; \ + LINKER_KEEP(__##name##_ptr); /** * @brief Create a memory block object with a new backing buffer. diff --git a/include/zephyr/sys/mem_manage.h b/include/zephyr/sys/mem_manage.h index 3f0c0f4b5fd..850a1376eaf 100644 --- a/include/zephyr/sys/mem_manage.h +++ b/include/zephyr/sys/mem_manage.h @@ -7,670 +7,58 @@ #ifndef ZEPHYR_INCLUDE_SYS_MEM_MANAGE_H #define ZEPHYR_INCLUDE_SYS_MEM_MANAGE_H -#include -#include -#if defined(CONFIG_ARM_MMU) && defined(CONFIG_ARM64) -#include -#endif +#include /** * @brief Memory Management * @defgroup memory_management Memory Management * @ingroup os_services * @{ - * @} */ -/* - * Caching mode definitions. These are mutually exclusive. - */ - -/** No caching. Most drivers want this. */ -#define K_MEM_CACHE_NONE 2 - -/** Write-through caching. Used by certain drivers. */ -#define K_MEM_CACHE_WT 1 - -/** Full write-back caching. Any RAM mapped wants this. */ -#define K_MEM_CACHE_WB 0 - -/* - * ARM64 Specific flags are defined in arch/arm64/arm_mem.h, - * pay attention to be not conflicted when updating these flags. - */ - -/** Reserved bits for cache modes in k_map() flags argument */ -#define K_MEM_CACHE_MASK (BIT(3) - 1) - -/* - * Region permission attributes. Default is read-only, no user, no exec - */ - -/** Region will have read/write access (and not read-only) */ -#define K_MEM_PERM_RW BIT(3) - -/** Region will be executable (normally forbidden) */ -#define K_MEM_PERM_EXEC BIT(4) - -/** Region will be accessible to user mode (normally supervisor-only) */ -#define K_MEM_PERM_USER BIT(5) - -/* - * Region mapping behaviour attributes - */ - -/** Region will be mapped to 1:1 virtual and physical address */ -#define K_MEM_DIRECT_MAP BIT(6) - -/* - * This is the offset to subtract from a virtual address mapped in the - * kernel's permanent mapping of RAM, to obtain its physical address. - * - * virt_addr = phys_addr + Z_MEM_VM_OFFSET - * - * This only works for virtual addresses within the interval - * [CONFIG_KERNEL_VM_BASE, CONFIG_KERNEL_VM_BASE + (CONFIG_SRAM_SIZE * 1024)). - * - * These macros are intended for assembly, linker code, and static initializers. - * Use with care. - * - * Note that when demand paging is active, these will only work with page - * frames that are pinned to their virtual mapping at boot. - * - * TODO: This will likely need to move to an arch API or need additional - * constraints defined. - */ -#ifdef CONFIG_MMU -#define Z_MEM_VM_OFFSET ((CONFIG_KERNEL_VM_BASE + CONFIG_KERNEL_VM_OFFSET) - \ - (CONFIG_SRAM_BASE_ADDRESS + CONFIG_SRAM_OFFSET)) -#else -#define Z_MEM_VM_OFFSET 0 -#endif - -#define Z_MEM_PHYS_ADDR(virt) ((virt) - Z_MEM_VM_OFFSET) -#define Z_MEM_VIRT_ADDR(phys) ((phys) + Z_MEM_VM_OFFSET) - -#if Z_MEM_VM_OFFSET != 0 -#define Z_VM_KERNEL 1 -#ifdef CONFIG_XIP -#error "XIP and a virtual memory kernel are not allowed" -#endif -#endif - #ifndef _ASMLANGUAGE +#include #include -#include -#include -#include - -struct k_mem_paging_stats_t { -#ifdef CONFIG_DEMAND_PAGING_STATS - struct { - /** Number of page faults */ - unsigned long cnt; - - /** Number of page faults with IRQ locked */ - unsigned long irq_locked; - - /** Number of page faults with IRQ unlocked */ - unsigned long irq_unlocked; - -#ifndef CONFIG_DEMAND_PAGING_ALLOW_IRQ - /** Number of page faults while in ISR */ - unsigned long in_isr; -#endif - } pagefaults; - - struct { - /** Number of clean pages selected for eviction */ - unsigned long clean; - - /** Number of dirty pages selected for eviction */ - unsigned long dirty; - } eviction; -#endif /* CONFIG_DEMAND_PAGING_STATS */ -}; - -struct k_mem_paging_histogram_t { -#ifdef CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM - /* Counts for each bin in timing histogram */ - unsigned long counts[CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM_NUM_BINS]; - - /* Bounds for the bins in timing histogram, - * excluding the first and last (hence, NUM_SLOTS - 1). - */ - unsigned long bounds[CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM_NUM_BINS]; -#endif /* CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM */ -}; - -/* Just like Z_MEM_PHYS_ADDR() but with type safety and assertions */ -static inline uintptr_t z_mem_phys_addr(void *virt) -{ - uintptr_t addr = (uintptr_t)virt; - -#ifdef CONFIG_MMU - __ASSERT((addr >= CONFIG_KERNEL_VM_BASE) && - (addr < (CONFIG_KERNEL_VM_BASE + - (CONFIG_KERNEL_VM_SIZE))), - "address %p not in permanent mappings", virt); -#else - /* Should be identity-mapped */ - __ASSERT((addr >= CONFIG_SRAM_BASE_ADDRESS) && - (addr < (CONFIG_SRAM_BASE_ADDRESS + - (CONFIG_SRAM_SIZE * 1024UL))), - "physical address 0x%lx not in RAM", - (unsigned long)addr); -#endif /* CONFIG_MMU */ - - /* TODO add assertion that this page is pinned to boot mapping, - * the above checks won't be sufficient with demand paging - */ - - return Z_MEM_PHYS_ADDR(addr); -} - -/* Just like Z_MEM_VIRT_ADDR() but with type safety and assertions */ -static inline void *z_mem_virt_addr(uintptr_t phys) -{ - __ASSERT((phys >= CONFIG_SRAM_BASE_ADDRESS) && - (phys < (CONFIG_SRAM_BASE_ADDRESS + - (CONFIG_SRAM_SIZE * 1024UL))), - "physical address 0x%lx not in RAM", (unsigned long)phys); - - /* TODO add assertion that this page frame is pinned to boot mapping, - * the above check won't be sufficient with demand paging - */ - - return (void *)Z_MEM_VIRT_ADDR(phys); -} - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Map a physical memory region into the kernel's virtual address space - * - * This function is intended for mapping memory-mapped I/O regions into - * the virtual address space. Given a physical address and a size, return a - * linear address representing the base of where the physical region is mapped - * in the virtual address space for the Zephyr kernel. - * - * This function alters the active page tables in the area reserved - * for the kernel. This function will choose the virtual address - * and return it to the caller. - * - * Portable code should never assume that phys_addr and linear_addr will - * be equal. - * - * Caching and access properties are controlled by the 'flags' parameter. - * Unused bits in 'flags' are reserved for future expansion. - * A caching mode must be selected. By default, the region is read-only - * with user access and code execution forbidden. This policy is changed - * by passing K_MEM_CACHE_* and K_MEM_PERM_* macros into the 'flags' parameter. - * - * If there is insufficient virtual address space for the mapping this will - * generate a kernel panic. - * - * This API is only available if CONFIG_MMU is enabled. - * - * It is highly discouraged to use this function to map system RAM page - * frames. It may conflict with anonymous memory mappings and demand paging - * and produce undefined behavior. Do not use this for RAM unless you know - * exactly what you are doing. If you need a chunk of memory, use k_mem_map(). - * If you need a contiguous buffer of physical memory, statically declare it - * and pin it at build time, it will be mapped when the system boots. - * - * This API is part of infrastructure still under development and may - * change. - * - * @param virt [out] Output virtual address storage location - * @param phys Physical address base of the memory region - * @param size Size of the memory region - * @param flags Caching mode and access flags, see K_MAP_* macros - */ -void z_phys_map(uint8_t **virt_ptr, uintptr_t phys, size_t size, - uint32_t flags); - -/** - * Unmap a virtual memory region from kernel's virtual address space. - * - * This function is intended to be used by drivers and early boot routines - * where temporary memory mappings need to be made. This allows these - * memory mappings to be discarded once they are no longer needed. - * - * This function alters the active page tables in the area reserved - * for the kernel. - * - * This will align the input parameters to page boundaries so that - * this can be used with the virtual address as returned by - * z_phys_map(). - * - * This API is only available if CONFIG_MMU is enabled. - * - * It is highly discouraged to use this function to unmap memory mappings. - * It may conflict with anonymous memory mappings and demand paging and - * produce undefined behavior. Do not use this unless you know exactly - * what you are doing. - * - * This API is part of infrastructure still under development and may - * change. - * - * @param virt Starting address of the virtual address region to be unmapped. - * @param size Size of the virtual address region - */ -void z_phys_unmap(uint8_t *virt, size_t size); - -/* - * k_mem_map() control flags - */ - -/** - * @brief The mapped region is not guaranteed to be zeroed. - * - * This may improve performance. The associated page frames may contain - * indeterminate data, zeroes, or even sensitive information. - * - * This may not be used with K_MEM_PERM_USER as there are no circumstances - * where this is safe. - */ -#define K_MEM_MAP_UNINIT BIT(16) - -/** - * Region will be pinned in memory and never paged - * - * Such memory is guaranteed to never produce a page fault due to page-outs - * or copy-on-write once the mapping call has returned. Physical page frames - * will be pre-fetched as necessary and pinned. - */ -#define K_MEM_MAP_LOCK BIT(17) - -/** - * Return the amount of free memory available - * - * The returned value will reflect how many free RAM page frames are available. - * If demand paging is enabled, it may still be possible to allocate more. - * - * The information reported by this function may go stale immediately if - * concurrent memory mappings or page-ins take place. - * - * @return Free physical RAM, in bytes - */ -size_t k_mem_free_get(void); - -/** - * Map anonymous memory into Zephyr's address space - * - * This function effectively increases the data space available to Zephyr. - * The kernel will choose a base virtual address and return it to the caller. - * The memory will have access permissions for all contexts set per the - * provided flags argument. - * - * If user thread access control needs to be managed in any way, do not enable - * K_MEM_PERM_USER flags here; instead manage the region's permissions - * with memory domain APIs after the mapping has been established. Setting - * K_MEM_PERM_USER here will allow all user threads to access this memory - * which is usually undesirable. - * - * Unless K_MEM_MAP_UNINIT is used, the returned memory will be zeroed. - * - * The mapped region is not guaranteed to be physically contiguous in memory. - * Physically contiguous buffers should be allocated statically and pinned - * at build time. - * - * Pages mapped in this way have write-back cache settings. - * - * The returned virtual memory pointer will be page-aligned. The size - * parameter, and any base address for re-mapping purposes must be page- - * aligned. - * - * Note that the allocation includes two guard pages immediately before - * and after the requested region. The total size of the allocation will be - * the requested size plus the size of these two guard pages. - * - * Many K_MEM_MAP_* flags have been implemented to alter the behavior of this - * function, with details in the documentation for these flags. - * - * @param size Size of the memory mapping. This must be page-aligned. - * @param flags K_MEM_PERM_*, K_MEM_MAP_* control flags. - * @return The mapped memory location, or NULL if insufficient virtual address - * space, insufficient physical memory to establish the mapping, - * or insufficient memory for paging structures. - */ -void *k_mem_map(size_t size, uint32_t flags); - -/** - * Un-map mapped memory - * - * This removes a memory mapping for the provided page-aligned region. - * Associated page frames will be free and the kernel may re-use the associated - * virtual address region. Any paged out data pages may be discarded. - * - * Calling this function on a region which was not mapped to begin with is - * undefined behavior. - * - * @param addr Page-aligned memory region base virtual address - * @param size Page-aligned memory region size - */ -void k_mem_unmap(void *addr, size_t size); - -/** - * Given an arbitrary region, provide a aligned region that covers it - * - * The returned region will have both its base address and size aligned - * to the provided alignment value. - * - * @param aligned_addr [out] Aligned address - * @param aligned_size [out] Aligned region size - * @param addr Region base address - * @param size Region size - * @param align What to align the address and size to - * @retval offset between aligned_addr and addr - */ -size_t k_mem_region_align(uintptr_t *aligned_addr, size_t *aligned_size, - uintptr_t addr, size_t size, size_t align); /** - * @defgroup demand_paging Demand Paging - * @ingroup memory_management - */ -/** - * @defgroup mem-demand-paging Demand Paging APIs - * @ingroup demand_paging - * @{ - */ - -/** - * Evict a page-aligned virtual memory region to the backing store - * - * Useful if it is known that a memory region will not be used for some time. - * All the data pages within the specified region will be evicted to the - * backing store if they weren't already, with their associated page frames - * marked as available for mappings or page-ins. - * - * None of the associated page frames mapped to the provided region should - * be pinned. - * - * Note that there are no guarantees how long these pages will be evicted, - * they could take page faults immediately. - * - * If CONFIG_DEMAND_PAGING_ALLOW_IRQ is enabled, this function may not be - * called by ISRs as the backing store may be in-use. - * - * @param addr Base page-aligned virtual address - * @param size Page-aligned data region size - * @retval 0 Success - * @retval -ENOMEM Insufficient space in backing store to satisfy request. - * The region may be partially paged out. - */ -int k_mem_page_out(void *addr, size_t size); - -/** - * Load a virtual data region into memory + * @brief Check if a physical address is within range of physical memory. * - * After the function completes, all the page frames associated with this - * function will be paged in. However, they are not guaranteed to stay there. - * This is useful if the region is known to be used soon. + * This checks if the physical address (@p virt) is within + * permissible range, e.g. between + * :kconfig:option:`CONFIG_SRAM_BASE_ADDRESS` and + * (:kconfig:option:`CONFIG_SRAM_BASE_ADDRESS` + + * :kconfig:option:`CONFIG_SRAM_SIZE`). * - * If CONFIG_DEMAND_PAGING_ALLOW_IRQ is enabled, this function may not be - * called by ISRs as the backing store may be in-use. + * @note Only used if + * :kconfig:option:`CONFIG_KERNEL_VM_USE_CUSTOM_MEM_RANGE_CHECK` + * is enabled. * - * @param addr Base page-aligned virtual address - * @param size Page-aligned data region size - */ -void k_mem_page_in(void *addr, size_t size); - -/** - * Pin an aligned virtual data region, paging in as necessary - * - * After the function completes, all the page frames associated with this - * region will be resident in memory and pinned such that they stay that way. - * This is a stronger version of z_mem_page_in(). - * - * If CONFIG_DEMAND_PAGING_ALLOW_IRQ is enabled, this function may not be - * called by ISRs as the backing store may be in-use. - * - * @param addr Base page-aligned virtual address - * @param size Page-aligned data region size - */ -void k_mem_pin(void *addr, size_t size); - -/** - * Un-pin an aligned virtual data region + * @param phys Physical address to be checked. * - * After the function completes, all the page frames associated with this - * region will be no longer marked as pinned. This does not evict the region, - * follow this with z_mem_page_out() if you need that. - * - * @param addr Base page-aligned virtual address - * @param size Page-aligned data region size + * @return True if physical address is within range, false if not. */ -void k_mem_unpin(void *addr, size_t size); +bool sys_mm_is_phys_addr_in_range(uintptr_t phys); /** - * Get the paging statistics since system startup + * @brief Check if a virtual address is within range of virtual memory. * - * This populates the paging statistics struct being passed in - * as argument. + * This checks if the virtual address (@p virt) is within + * permissible range, e.g. between + * :kconfig:option:`CONFIG_KERNEL_VM_BASE` and + * (:kconfig:option:`CONFIG_KERNEL_VM_BASE` + + * :kconfig:option:`CONFIG_KERNEL_VM_SIZE`). * - * @param[in,out] stats Paging statistics struct to be filled. - */ -__syscall void k_mem_paging_stats_get(struct k_mem_paging_stats_t *stats); - -struct k_thread; -/** - * Get the paging statistics since system startup for a thread + * @note Only used if + * :kconfig:option:`CONFIG_KERNEL_VM_USE_CUSTOM_MEM_RANGE_CHECK` + * is enabled. * - * This populates the paging statistics struct being passed in - * as argument for a particular thread. + * @param virt Virtual address to be checked. * - * @param[in] thread Thread - * @param[in,out] stats Paging statistics struct to be filled. + * @return True if virtual address is within range, false if not. */ -__syscall -void k_mem_paging_thread_stats_get(struct k_thread *thread, - struct k_mem_paging_stats_t *stats); - -/** - * Get the eviction timing histogram - * - * This populates the timing histogram struct being passed in - * as argument. - * - * @param[in,out] hist Timing histogram struct to be filled. - */ -__syscall void k_mem_paging_histogram_eviction_get( - struct k_mem_paging_histogram_t *hist); - -/** - * Get the backing store page-in timing histogram - * - * This populates the timing histogram struct being passed in - * as argument. - * - * @param[in,out] hist Timing histogram struct to be filled. - */ -__syscall void k_mem_paging_histogram_backing_store_page_in_get( - struct k_mem_paging_histogram_t *hist); - -/** - * Get the backing store page-out timing histogram - * - * This populates the timing histogram struct being passed in - * as argument. - * - * @param[in,out] hist Timing histogram struct to be filled. - */ -__syscall void k_mem_paging_histogram_backing_store_page_out_get( - struct k_mem_paging_histogram_t *hist); - -#include +bool sys_mm_is_virt_addr_in_range(void *virt); /** @} */ -/** - * Eviction algorithm APIs - * - * @defgroup mem-demand-paging-eviction Eviction Algorithm APIs - * @ingroup demand_paging - * @{ - */ - -/** - * Select a page frame for eviction - * - * The kernel will invoke this to choose a page frame to evict if there - * are no free page frames. - * - * This function will never be called before the initial - * k_mem_paging_eviction_init(). - * - * This function is invoked with interrupts locked. - * - * @param [out] dirty Whether the page to evict is dirty - * @return The page frame to evict - */ -struct z_page_frame *k_mem_paging_eviction_select(bool *dirty); - -/** - * Initialization function - * - * Called at POST_KERNEL to perform any necessary initialization tasks for the - * eviction algorithm. k_mem_paging_eviction_select() is guaranteed to never be - * called until this has returned, and this will only be called once. - */ -void k_mem_paging_eviction_init(void); - -/** @} */ - -/** - * Backing store APIs - * - * @defgroup mem-demand-paging-backing-store Backing Store APIs - * @ingroup demand_paging - * @{ - */ - -/** - * Reserve or fetch a storage location for a data page loaded into a page frame - * - * The returned location token must be unique to the mapped virtual address. - * This location will be used in the backing store to page out data page - * contents for later retrieval. The location value must be page-aligned. - * - * This function may be called multiple times on the same data page. If its - * page frame has its Z_PAGE_FRAME_BACKED bit set, it is expected to return - * the previous backing store location for the data page containing a cached - * clean copy. This clean copy may be updated on page-out, or used to - * discard clean pages without needing to write out their contents. - * - * If the backing store is full, some other backing store location which caches - * a loaded data page may be selected, in which case its associated page frame - * will have the Z_PAGE_FRAME_BACKED bit cleared (as it is no longer cached). - * - * pf->addr will indicate the virtual address the page is currently mapped to. - * Large, sparse backing stores which can contain the entire address space - * may simply generate location tokens purely as a function of pf->addr with no - * other management necessary. - * - * This function distinguishes whether it was called on behalf of a page - * fault. A free backing store location must always be reserved in order for - * page faults to succeed. If the page_fault parameter is not set, this - * function should return -ENOMEM even if one location is available. - * - * This function is invoked with interrupts locked. - * - * @param pf Virtual address to obtain a storage location - * @param [out] location storage location token - * @param page_fault Whether this request was for a page fault - * @return 0 Success - * @return -ENOMEM Backing store is full - */ -int k_mem_paging_backing_store_location_get(struct z_page_frame *pf, - uintptr_t *location, - bool page_fault); - -/** - * Free a backing store location - * - * Any stored data may be discarded, and the location token associated with - * this address may be re-used for some other data page. - * - * This function is invoked with interrupts locked. - * - * @param location Location token to free - */ -void k_mem_paging_backing_store_location_free(uintptr_t location); - -/** - * Copy a data page from Z_SCRATCH_PAGE to the specified location - * - * Immediately before this is called, Z_SCRATCH_PAGE will be mapped read-write - * to the intended source page frame for the calling context. - * - * Calls to this and k_mem_paging_backing_store_page_in() will always be - * serialized, but interrupts may be enabled. - * - * @param location Location token for the data page, for later retrieval - */ -void k_mem_paging_backing_store_page_out(uintptr_t location); - -/** - * Copy a data page from the provided location to Z_SCRATCH_PAGE. - * - * Immediately before this is called, Z_SCRATCH_PAGE will be mapped read-write - * to the intended destination page frame for the calling context. - * - * Calls to this and k_mem_paging_backing_store_page_out() will always be - * serialized, but interrupts may be enabled. - * - * @param location Location token for the data page - */ -void k_mem_paging_backing_store_page_in(uintptr_t location); - -/** - * Update internal accounting after a page-in - * - * This is invoked after k_mem_paging_backing_store_page_in() and interrupts - * have been* re-locked, making it safe to access the z_page_frame data. - * The location value will be the same passed to - * k_mem_paging_backing_store_page_in(). - * - * The primary use-case for this is to update custom fields for the backing - * store in the page frame, to reflect where the data should be evicted to - * if it is paged out again. This may be a no-op in some implementations. - * - * If the backing store caches paged-in data pages, this is the appropriate - * time to set the Z_PAGE_FRAME_BACKED bit. The kernel only skips paging - * out clean data pages if they are noted as clean in the page tables and the - * Z_PAGE_FRAME_BACKED bit is set in their associated page frame. - * - * @param pf Page frame that was loaded in - * @param location Location of where the loaded data page was retrieved - */ -void k_mem_paging_backing_store_page_finalize(struct z_page_frame *pf, - uintptr_t location); - -/** - * Backing store initialization function. - * - * The implementation may expect to receive page in/out calls as soon as this - * returns, but not before that. Called at POST_KERNEL. - * - * This function is expected to do two things: - * - Initialize any internal data structures and accounting for the backing - * store. - * - If the backing store already contains all or some loaded kernel data pages - * at boot time, Z_PAGE_FRAME_BACKED should be appropriately set for their - * associated page frames, and any internal accounting set up appropriately. - */ -void k_mem_paging_backing_store_init(void); - -/** @} */ - -#ifdef __cplusplus -} -#endif - #endif /* !_ASMLANGUAGE */ #endif /* ZEPHYR_INCLUDE_SYS_MEM_MANAGE_H */ diff --git a/include/zephyr/sys/mpsc_pbuf.h b/include/zephyr/sys/mpsc_pbuf.h index a80cc2db464..72f6e99515b 100644 --- a/include/zephyr/sys/mpsc_pbuf.h +++ b/include/zephyr/sys/mpsc_pbuf.h @@ -19,7 +19,7 @@ extern "C" { /** * @brief Multi producer, single consumer packet buffer API * @defgroup mpsc_buf MPSC (Multi producer, single consumer) packet buffer API - * @ingroup kernel_apis + * @ingroup datastructure_apis * @{ */ diff --git a/include/zephyr/sys/printk.h b/include/zephyr/sys/printk.h index b5821ed971e..795018ae4f8 100644 --- a/include/zephyr/sys/printk.h +++ b/include/zephyr/sys/printk.h @@ -44,8 +44,8 @@ extern "C" { */ #ifdef CONFIG_PRINTK -extern __printf_like(1, 2) void printk(const char *fmt, ...); -extern __printf_like(1, 0) void vprintk(const char *fmt, va_list ap); +__printf_like(1, 2) void printk(const char *fmt, ...); +__printf_like(1, 0) void vprintk(const char *fmt, va_list ap); #else static inline __printf_like(1, 2) void printk(const char *fmt, ...) @@ -69,9 +69,9 @@ static inline __printf_like(1, 0) void vprintk(const char *fmt, va_list ap) #else -extern __printf_like(3, 4) int snprintk(char *str, size_t size, +__printf_like(3, 4) int snprintk(char *str, size_t size, const char *fmt, ...); -extern __printf_like(3, 0) int vsnprintk(char *str, size_t size, +__printf_like(3, 0) int vsnprintk(char *str, size_t size, const char *fmt, va_list ap); #endif diff --git a/include/zephyr/sys/reboot.h b/include/zephyr/sys/reboot.h index 50d68870683..293a5875451 100644 --- a/include/zephyr/sys/reboot.h +++ b/include/zephyr/sys/reboot.h @@ -32,7 +32,7 @@ extern "C" { * * When successful, this routine does not return. */ -extern FUNC_NORETURN void sys_reboot(int type); +FUNC_NORETURN void sys_reboot(int type); #ifdef __cplusplus } diff --git a/include/zephyr/sys/ring_buffer.h b/include/zephyr/sys/ring_buffer.h index 812824ade58..bd2cd5ef1ef 100644 --- a/include/zephyr/sys/ring_buffer.h +++ b/include/zephyr/sys/ring_buffer.h @@ -25,6 +25,16 @@ extern "C" { "Size too big" /** @endcond */ +/** + * @file + * @defgroup ring_buffer_apis Ring Buffer APIs + * @ingroup datastructure_apis + * + * @brief Simple ring buffer implementation. + * + * @{ + */ + /** * @brief A structure to represent a ring buffer */ @@ -41,16 +51,6 @@ struct ring_buf { /** @endcond */ }; -/** - * @file - * @defgroup ring_buffer_apis Ring Buffer APIs - * @ingroup datastructure_apis - * - * @brief Simple ring buffer implementation. - * - * @{ - */ - /** * @brief Function to force ring_buf internal states to given value * diff --git a/include/zephyr/sys/sflist.h b/include/zephyr/sys/sflist.h index 307d3497f4e..97580800831 100644 --- a/include/zephyr/sys/sflist.h +++ b/include/zephyr/sys/sflist.h @@ -489,6 +489,17 @@ static inline bool sys_sflist_find_and_remove(sys_sflist_t *list, Z_GENLIST_FIND_AND_REMOVE(sflist, sfnode) +/** + * @brief Compute the size of the given list in O(n) time + * + * @param list A pointer on the list + * + * @return an integer equal to the size of the list, or 0 if empty + */ +static inline size_t sys_sflist_len(sys_sflist_t *list); + +Z_GENLIST_LEN(sflist, sfnode) + /** @} */ #ifdef __cplusplus diff --git a/include/zephyr/sys/slist.h b/include/zephyr/sys/slist.h index 87ef6719159..095c89ffe02 100644 --- a/include/zephyr/sys/slist.h +++ b/include/zephyr/sys/slist.h @@ -420,6 +420,17 @@ Z_GENLIST_REMOVE(slist, snode) static inline bool sys_slist_find_and_remove(sys_slist_t *list, sys_snode_t *node); +/** + * @brief Compute the size of the given list in O(n) time + * + * @param list A pointer on the list + * + * @return an integer equal to the size of the list, or 0 if empty + */ +static inline size_t sys_slist_len(sys_slist_t *list); + +Z_GENLIST_LEN(slist, snode) + /** @} */ Z_GENLIST_FIND_AND_REMOVE(slist, snode) diff --git a/include/zephyr/sys/spsc_pbuf.h b/include/zephyr/sys/spsc_pbuf.h index 682d610e34b..0e7f018fa63 100644 --- a/include/zephyr/sys/spsc_pbuf.h +++ b/include/zephyr/sys/spsc_pbuf.h @@ -16,11 +16,12 @@ extern "C" { /** * @brief Single producer, single consumer packet buffer API - * @ingroup kernel_apis + * @defgroup spsc_buf SPSC (Single producer, single consumer) packet buffer API + * @ingroup datastructure_apis * @{ */ -/**@defgroup SPSC_PBUF_FLAGS MPSC packet buffer flags +/**@defgroup SPSC_PBUF_FLAGS SPSC packet buffer flags * @{ */ diff --git a/include/zephyr/sys/time_units.h b/include/zephyr/sys/time_units.h index 527b7371f23..7f2db1a1f55 100644 --- a/include/zephyr/sys/time_units.h +++ b/include/zephyr/sys/time_units.h @@ -40,7 +40,8 @@ extern "C" { /** @brief System-wide macro to convert milliseconds to kernel timeouts */ -#define SYS_TIMEOUT_MS(ms) ((ms) == SYS_FOREVER_MS ? K_FOREVER : K_MSEC(ms)) +#define SYS_TIMEOUT_MS(ms) Z_TIMEOUT_TICKS((ms) == SYS_FOREVER_MS ? \ + K_TICKS_FOREVER : Z_TIMEOUT_MS_TICKS(ms)) /* Exhaustively enumerated, highly optimized time unit conversion API */ @@ -69,14 +70,11 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * @brief Get the system timer frequency. * @return system timer frequency in Hz */ -static TIME_CONSTEXPR inline int sys_clock_hw_cycles_per_sec(void) -{ #if defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) - return sys_clock_hw_cycles_per_sec_runtime_get(); +#define sys_clock_hw_cycles_per_sec() sys_clock_hw_cycles_per_sec_runtime_get() #else - return CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; +#define sys_clock_hw_cycles_per_sec() CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC #endif -} /** @internal * Macro determines if fast conversion algorithm can be used. It checks if @@ -89,7 +87,7 @@ static TIME_CONSTEXPR inline int sys_clock_hw_cycles_per_sec(void) * @retval true Use faster algorithm. * @retval false Use algorithm preventing overflow of intermediate value. */ -#define Z_TMCVT_USE_FAST_ALGO(from_hz, to_hz) \ +#define z_tmcvt_use_fast_algo(from_hz, to_hz) \ ((DIV_ROUND_UP(CONFIG_SYS_CLOCK_MAX_TIMEOUT_DAYS * 24ULL * 3600ULL * from_hz, \ UINT32_MAX) * to_hz) <= UINT32_MAX) @@ -111,70 +109,144 @@ static TIME_CONSTEXPR inline int sys_clock_hw_cycles_per_sec(void) * round_up - Return the ceiling of the resulting fraction * round_off - Return the nearest value to the resulting fraction * (pass both round_up/off as false to get "round_down") + * + * All of this must be implemented as expressions so that, when constant, + * the results may be used to initialize global variables. */ -static TIME_CONSTEXPR ALWAYS_INLINE uint64_t z_tmcvt(uint64_t t, uint32_t from_hz, - uint32_t to_hz, bool const_hz, - bool result32, bool round_up, - bool round_off) -{ - bool mul_ratio = const_hz && - (to_hz > from_hz) && ((to_hz % from_hz) == 0U); - bool div_ratio = const_hz && - (from_hz > to_hz) && ((from_hz % to_hz) == 0U); - - if (from_hz == to_hz) { - return result32 ? ((uint32_t)t) : t; - } - - uint64_t off = 0; - - if (!mul_ratio) { - uint32_t rdivisor = div_ratio ? (from_hz / to_hz) : from_hz; - - if (round_up) { - off = rdivisor - 1U; - } - if (round_off) { - off = rdivisor / 2U; - } - } - - /* Select (at build time!) between three different expressions for - * the same mathematical relationship, each expressed with and - * without truncation to 32 bits (I couldn't find a way to make - * the compiler correctly guess at the 32 bit result otherwise). - */ - if (div_ratio) { - t += off; - if (result32 && (t < BIT64(32))) { - return ((uint32_t)t) / (from_hz / to_hz); - } else { - return t / ((uint64_t)from_hz / to_hz); - } - } else if (mul_ratio) { - if (result32) { - return ((uint32_t)t) * (to_hz / from_hz); - } else { - return t * ((uint64_t)to_hz / from_hz); - } - } else { - if (result32) { - return (uint32_t)((t * to_hz + off) / from_hz); - } else if (const_hz && Z_TMCVT_USE_FAST_ALGO(from_hz, to_hz)) { - /* Faster algorithm but source is first multiplied by target frequency - * and it can overflow even though final result would not overflow. - * Kconfig option shall prevent use of this algorithm when there is a - * risk of overflow. - */ - return ((t * to_hz + off) / from_hz); - } else { - /* Slower algorithm but input is first divided before being multiplied - * which prevents overflow of intermediate value. - */ - return (t / from_hz) * to_hz + ((t % from_hz) * to_hz + off) / from_hz; - } - } -} + +/* true if the conversion is the identity */ +#define z_tmcvt_is_identity(__from_hz, __to_hz) \ + ((__to_hz) == (__from_hz)) + +/* true if the conversion requires a simple integer multiply */ +#define z_tmcvt_is_int_mul(__from_hz, __to_hz) \ + ((__to_hz) > (__from_hz) && (__to_hz) % (__from_hz) == 0U) + +/* true if the conversion requires a simple integer division */ +#define z_tmcvt_is_int_div(__from_hz, __to_hz) \ + ((__from_hz) > (__to_hz) && (__from_hz) % (__to_hz) == 0U) + +/* + * Compute the offset needed to round the result correctly when + * the conversion requires a simple integer division + */ +#define z_tmcvt_off_div(__from_hz, __to_hz, __round_up, __round_off) \ + ((__round_off) ? ((__from_hz) / (__to_hz)) / 2 : \ + (__round_up) ? ((__from_hz) / (__to_hz)) - 1 : \ + 0) + +/* Clang emits a divide-by-zero warning even though the int_div macro + * results are only used when the divisor will not be zero. Work + * around this by substituting 1 to make the compiler happy. + */ +#ifdef __clang__ +#define z_tmcvt_divisor(a, b) ((a) / (b) ?: 1) +#else +#define z_tmcvt_divisor(a, b) ((a) / (b)) +#endif + +/* + * Compute the offset needed to round the result correctly when + * the conversion requires a full mul/div + */ +#define z_tmcvt_off_gen(__from_hz, __to_hz, __round_up, __round_off) \ + ((__round_off) ? (__from_hz) / 2 : \ + (__round_up) ? (__from_hz) - 1 : \ + 0) + +/* Integer division 32-bit conversion */ +#define z_tmcvt_int_div_32(__t, __from_hz, __to_hz, __round_up, __round_off) \ + ((uint64_t) (__t) <= 0xffffffffU - \ + z_tmcvt_off_div(__from_hz, __to_hz, __round_up, __round_off) ? \ + ((uint32_t)((__t) + \ + z_tmcvt_off_div(__from_hz, __to_hz, \ + __round_up, __round_off)) / \ + z_tmcvt_divisor(__from_hz, __to_hz)) \ + : \ + (uint32_t) (((uint64_t) (__t) + \ + z_tmcvt_off_div(__from_hz, __to_hz, \ + __round_up, __round_off)) / \ + z_tmcvt_divisor(__from_hz, __to_hz)) \ + ) + +/* Integer multiplication 32-bit conversion */ +#define z_tmcvt_int_mul_32(__t, __from_hz, __to_hz) \ + (uint32_t) (__t)*((__to_hz) / (__from_hz)) + +/* General 32-bit conversion */ +#define z_tmcvt_gen_32(__t, __from_hz, __to_hz, __round_up, __round_off) \ + ((uint32_t) (((uint64_t) (__t)*(__to_hz) + \ + z_tmcvt_off_gen(__from_hz, __to_hz, __round_up, __round_off)) / (__from_hz))) + +/* Integer division 64-bit conversion */ +#define z_tmcvt_int_div_64(__t, __from_hz, __to_hz, __round_up, __round_off) \ + (((uint64_t) (__t) + z_tmcvt_off_div(__from_hz, __to_hz, \ + __round_up, __round_off)) / \ + z_tmcvt_divisor(__from_hz, __to_hz)) + +/* Integer multiplcation 64-bit conversion */ +#define z_tmcvt_int_mul_64(__t, __from_hz, __to_hz) \ + (uint64_t) (__t)*((__to_hz) / (__from_hz)) + +/* Fast 64-bit conversion. This relies on the multiply not overflowing */ +#define z_tmcvt_gen_64_fast(__t, __from_hz, __to_hz, __round_up, __round_off) \ + (((uint64_t) (__t)*(__to_hz) + \ + z_tmcvt_off_gen(__from_hz, __to_hz, __round_up, __round_off)) / (__from_hz)) + +/* Slow 64-bit conversion. This avoids overflowing the multiply */ +#define z_tmcvt_gen_64_slow(__t, __from_hz, __to_hz, __round_up, __round_off) \ + (((uint64_t) (__t) / (__from_hz))*(__to_hz) + \ + (((uint64_t) (__t) % (__from_hz))*(__to_hz) + \ + z_tmcvt_off_gen(__from_hz, __to_hz, __round_up, __round_off)) / (__from_hz)) + +/* General 64-bit conversion. Uses one of the two above macros */ +#define z_tmcvt_gen_64(__t, __from_hz, __to_hz, __round_up, __round_off) \ + (z_tmcvt_use_fast_algo(__from_hz, __to_hz) ? \ + z_tmcvt_gen_64_fast(__t, __from_hz, __to_hz, __round_up, __round_off) : \ + z_tmcvt_gen_64_slow(__t, __from_hz, __to_hz, __round_up, __round_off)) + +/* Convert, generating a 32-bit result */ +#define z_tmcvt_32(__t, __from_hz, __to_hz, __const_hz, __round_up, __round_off) \ + ((__const_hz) ? \ + ( \ + z_tmcvt_is_identity(__from_hz, __to_hz) ? \ + (uint32_t) (__t) \ + : \ + z_tmcvt_is_int_div(__from_hz, __to_hz) ? \ + z_tmcvt_int_div_32(__t, __from_hz, __to_hz, __round_up, __round_off) \ + : \ + z_tmcvt_is_int_mul(__from_hz, __to_hz) ? \ + z_tmcvt_int_mul_32(__t, __from_hz, __to_hz) \ + : \ + z_tmcvt_gen_32(__t, __from_hz, __to_hz, __round_up, __round_off) \ + ) \ + : \ + z_tmcvt_gen_32(__t, __from_hz, __to_hz, __round_up, __round_off) \ + ) + +/* Convert, generating a 64-bit result */ +#define z_tmcvt_64(__t, __from_hz, __to_hz, __const_hz, __round_up, __round_off) \ + ((__const_hz) ? \ + ( \ + z_tmcvt_is_identity(__from_hz, __to_hz) ? \ + (uint64_t) (__t) \ + : \ + z_tmcvt_is_int_div(__from_hz, __to_hz) ? \ + z_tmcvt_int_div_64(__t, __from_hz, __to_hz, __round_up, __round_off) \ + : \ + z_tmcvt_is_int_mul(__from_hz, __to_hz) ? \ + z_tmcvt_int_mul_64(__t, __from_hz, __to_hz) \ + : \ + z_tmcvt_gen_64(__t, __from_hz, __to_hz, __round_up, __round_off) \ + ) \ + : \ + z_tmcvt_gen_64_slow(__t, __from_hz, __to_hz, __round_up, __round_off) \ + ) + +#define z_tmcvt(__t, __from_hz, __to_hz, __const_hz, __result32, __round_up, __round_off) \ + ((__result32) ? \ + z_tmcvt_32(__t, __from_hz, __to_hz, __const_hz, __round_up, __round_off) : \ + z_tmcvt_64(__t, __from_hz, __to_hz, __const_hz, __round_up, __round_off)) /* The following code is programmatically generated using this perl * code, which enumerates all possible combinations of units, rounding @@ -194,6 +266,9 @@ static TIME_CONSTEXPR ALWAYS_INLINE uint64_t z_tmcvt(uint64_t t, uint32_t from_h * "ns" => "nanoseconds", * "cyc" => "hardware cycles", * "ticks" => "ticks"); + * my %human_round = ("ceil" => "Rounds up", + * "near" => "Round nearest", + * "floor" => "Truncates"); * * sub big { return $_[0] eq "us" || $_[0] eq "ns"; } * sub prefix { return $_[0] eq "ms" || $_[0] eq "us" || $_[0] eq "ns"; } @@ -206,16 +281,17 @@ static TIME_CONSTEXPR ALWAYS_INLINE uint64_t z_tmcvt(uint64_t t, uint32_t from_h * for(my $big=0; $big <= 1; $big++) { * my $sz = $big ? 64 : 32; * my $sym = "k_${from_unit}_to_${to_unit}_$round$sz"; - * my $type = "u${sz}_t"; + * my $type = "uint${sz}_t"; * my $const_hz = ($from_unit eq "cyc" || $to_unit eq "cyc") * ? "Z_CCYC" : "true"; - * my $ret32 = $big ? "false" : "true"; + * my $ret32 = $big ? "64" : "32"; * my $rup = $round eq "ceil" ? "true" : "false"; * my $roff = $round eq "near" ? "true" : "false"; * * my $hfrom = $human{$from_unit}; * my $hto = $human{$to_unit}; - * print "/", "** \@brief Convert $hfrom to $hto\n"; + * my $hround = $human_round{$round}; + * print "/", "** \@brief Convert $hfrom to $hto. $ret32 bits. $hround.\n"; * print " *\n"; * print " * Converts time values in $hfrom to $hto.\n"; * print " * Computes result in $sz bit precision.\n"; @@ -227,14 +303,16 @@ static TIME_CONSTEXPR ALWAYS_INLINE uint64_t z_tmcvt(uint64_t t, uint32_t from_h * print " * Truncates to the next lowest output unit.\n"; * } * print " *\n"; - * print " * \@return The converted time value\n"; + * print " * \@param t Source time in $hfrom. uint64_t\n"; + * print " *\n"; + * print " * \@return The converted time value in $hto. $type\n"; * print " *", "/\n"; * - * print "static TIME_CONSTEXPR inline $type $sym($type t)\n{\n\t"; - * print "/", "* Generated. Do not edit. See above. *", "/\n\t"; - * print "return z_tmcvt(t, Z_HZ_$from_unit, Z_HZ_$to_unit,"; - * print " $const_hz, $ret32, $rup, $roff);\n"; - * print "}\n\n"; + * print "/", "* Generated. Do not edit. See above. *", "/\n"; + * print "#define $sym(t) \\\n"; + * print "\tz_tmcvt_$ret32(t, Z_HZ_$from_unit, Z_HZ_$to_unit,"; + * print " $const_hz, $rup, $roff)\n"; + * print "\n\n"; * } * } * } @@ -251,1181 +329,1264 @@ static TIME_CONSTEXPR ALWAYS_INLINE uint64_t z_tmcvt(uint64_t t, uint32_t from_h #define Z_HZ_ticks CONFIG_SYS_CLOCK_TICKS_PER_SEC #define Z_CCYC (!IS_ENABLED(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME)) -/** @brief Convert milliseconds to hardware cycles +/** @brief Convert milliseconds to hardware cycles. 32 bits. Truncates. * * Converts time values in milliseconds to hardware cycles. * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in milliseconds. uint64_t + * + * @return The converted time value in hardware cycles. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ms_to_cyc_floor32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, true, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_ms_to_cyc_floor32(t) \ + z_tmcvt_32(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, false, false) -/** @brief Convert milliseconds to hardware cycles + +/** @brief Convert milliseconds to hardware cycles. 64 bits. Truncates. * * Converts time values in milliseconds to hardware cycles. * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in milliseconds. uint64_t + * + * @return The converted time value in hardware cycles. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ms_to_cyc_floor64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, false, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_ms_to_cyc_floor64(t) \ + z_tmcvt_64(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, false, false) + -/** @brief Convert milliseconds to hardware cycles +/** @brief Convert milliseconds to hardware cycles. 32 bits. Round nearest. * * Converts time values in milliseconds to hardware cycles. * Computes result in 32 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in milliseconds. uint64_t + * + * @return The converted time value in hardware cycles. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ms_to_cyc_near32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, true, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_ms_to_cyc_near32(t) \ + z_tmcvt_32(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, false, true) -/** @brief Convert milliseconds to hardware cycles + +/** @brief Convert milliseconds to hardware cycles. 64 bits. Round nearest. * * Converts time values in milliseconds to hardware cycles. * Computes result in 64 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in milliseconds. uint64_t + * + * @return The converted time value in hardware cycles. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ms_to_cyc_near64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, false, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_ms_to_cyc_near64(t) \ + z_tmcvt_64(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, false, true) + -/** @brief Convert milliseconds to hardware cycles +/** @brief Convert milliseconds to hardware cycles. 32 bits. Rounds up. * * Converts time values in milliseconds to hardware cycles. * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in milliseconds. uint64_t + * + * @return The converted time value in hardware cycles. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ms_to_cyc_ceil32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, true, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_ms_to_cyc_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, true, false) -/** @brief Convert milliseconds to hardware cycles + +/** @brief Convert milliseconds to hardware cycles. 64 bits. Rounds up. * * Converts time values in milliseconds to hardware cycles. * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in milliseconds. uint64_t + * + * @return The converted time value in hardware cycles. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ms_to_cyc_ceil64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, false, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_ms_to_cyc_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, true, false) + -/** @brief Convert milliseconds to ticks +/** @brief Convert milliseconds to ticks. 32 bits. Truncates. * * Converts time values in milliseconds to ticks. * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in milliseconds. uint64_t + * + * @return The converted time value in ticks. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ms_to_ticks_floor32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ms, Z_HZ_ticks, true, true, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_ms_to_ticks_floor32(t) \ + z_tmcvt_32(t, Z_HZ_ms, Z_HZ_ticks, true, false, false) -/** @brief Convert milliseconds to ticks + +/** @brief Convert milliseconds to ticks. 64 bits. Truncates. * * Converts time values in milliseconds to ticks. * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in milliseconds. uint64_t + * + * @return The converted time value in ticks. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ms_to_ticks_floor64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ms, Z_HZ_ticks, true, false, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_ms_to_ticks_floor64(t) \ + z_tmcvt_64(t, Z_HZ_ms, Z_HZ_ticks, true, false, false) + -/** @brief Convert milliseconds to ticks +/** @brief Convert milliseconds to ticks. 32 bits. Round nearest. * * Converts time values in milliseconds to ticks. * Computes result in 32 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in milliseconds. uint64_t + * + * @return The converted time value in ticks. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ms_to_ticks_near32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ms, Z_HZ_ticks, true, true, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_ms_to_ticks_near32(t) \ + z_tmcvt_32(t, Z_HZ_ms, Z_HZ_ticks, true, false, true) + -/** @brief Convert milliseconds to ticks +/** @brief Convert milliseconds to ticks. 64 bits. Round nearest. * * Converts time values in milliseconds to ticks. * Computes result in 64 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in milliseconds. uint64_t + * + * @return The converted time value in ticks. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ms_to_ticks_near64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ms, Z_HZ_ticks, true, false, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_ms_to_ticks_near64(t) \ + z_tmcvt_64(t, Z_HZ_ms, Z_HZ_ticks, true, false, true) + -/** @brief Convert milliseconds to ticks +/** @brief Convert milliseconds to ticks. 32 bits. Rounds up. * * Converts time values in milliseconds to ticks. * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in milliseconds. uint64_t + * + * @return The converted time value in ticks. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ms_to_ticks_ceil32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ms, Z_HZ_ticks, true, true, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_ms_to_ticks_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_ms, Z_HZ_ticks, true, true, false) + -/** @brief Convert milliseconds to ticks +/** @brief Convert milliseconds to ticks. 64 bits. Rounds up. * * Converts time values in milliseconds to ticks. * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in milliseconds. uint64_t + * + * @return The converted time value in ticks. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ms_to_ticks_ceil64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ms, Z_HZ_ticks, true, false, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_ms_to_ticks_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_ms, Z_HZ_ticks, true, true, false) -/** @brief Convert microseconds to hardware cycles + +/** @brief Convert microseconds to hardware cycles. 32 bits. Truncates. * * Converts time values in microseconds to hardware cycles. * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in microseconds. uint64_t + * + * @return The converted time value in hardware cycles. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_us_to_cyc_floor32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, true, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_us_to_cyc_floor32(t) \ + z_tmcvt_32(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, false, false) + -/** @brief Convert microseconds to hardware cycles +/** @brief Convert microseconds to hardware cycles. 64 bits. Truncates. * * Converts time values in microseconds to hardware cycles. * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in microseconds. uint64_t + * + * @return The converted time value in hardware cycles. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_us_to_cyc_floor64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, false, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_us_to_cyc_floor64(t) \ + z_tmcvt_64(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, false, false) -/** @brief Convert microseconds to hardware cycles + +/** @brief Convert microseconds to hardware cycles. 32 bits. Round nearest. * * Converts time values in microseconds to hardware cycles. * Computes result in 32 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in microseconds. uint64_t + * + * @return The converted time value in hardware cycles. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_us_to_cyc_near32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, true, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_us_to_cyc_near32(t) \ + z_tmcvt_32(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, false, true) + -/** @brief Convert microseconds to hardware cycles +/** @brief Convert microseconds to hardware cycles. 64 bits. Round nearest. * * Converts time values in microseconds to hardware cycles. * Computes result in 64 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in microseconds. uint64_t + * + * @return The converted time value in hardware cycles. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_us_to_cyc_near64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, false, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_us_to_cyc_near64(t) \ + z_tmcvt_64(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, false, true) -/** @brief Convert microseconds to hardware cycles + +/** @brief Convert microseconds to hardware cycles. 32 bits. Rounds up. * * Converts time values in microseconds to hardware cycles. * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in microseconds. uint64_t + * + * @return The converted time value in hardware cycles. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_us_to_cyc_ceil32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, true, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_us_to_cyc_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, true, false) + -/** @brief Convert microseconds to hardware cycles +/** @brief Convert microseconds to hardware cycles. 64 bits. Rounds up. * * Converts time values in microseconds to hardware cycles. * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in microseconds. uint64_t + * + * @return The converted time value in hardware cycles. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_us_to_cyc_ceil64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, false, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_us_to_cyc_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, true, false) -/** @brief Convert microseconds to ticks + +/** @brief Convert microseconds to ticks. 32 bits. Truncates. * * Converts time values in microseconds to ticks. * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in microseconds. uint64_t + * + * @return The converted time value in ticks. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_us_to_ticks_floor32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_us, Z_HZ_ticks, true, true, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_us_to_ticks_floor32(t) \ + z_tmcvt_32(t, Z_HZ_us, Z_HZ_ticks, true, false, false) + -/** @brief Convert microseconds to ticks +/** @brief Convert microseconds to ticks. 64 bits. Truncates. * * Converts time values in microseconds to ticks. * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in microseconds. uint64_t + * + * @return The converted time value in ticks. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_us_to_ticks_floor64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_us, Z_HZ_ticks, true, false, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_us_to_ticks_floor64(t) \ + z_tmcvt_64(t, Z_HZ_us, Z_HZ_ticks, true, false, false) + -/** @brief Convert microseconds to ticks +/** @brief Convert microseconds to ticks. 32 bits. Round nearest. * * Converts time values in microseconds to ticks. * Computes result in 32 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in microseconds. uint64_t + * + * @return The converted time value in ticks. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_us_to_ticks_near32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_us, Z_HZ_ticks, true, true, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_us_to_ticks_near32(t) \ + z_tmcvt_32(t, Z_HZ_us, Z_HZ_ticks, true, false, true) + -/** @brief Convert microseconds to ticks +/** @brief Convert microseconds to ticks. 64 bits. Round nearest. * * Converts time values in microseconds to ticks. * Computes result in 64 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in microseconds. uint64_t + * + * @return The converted time value in ticks. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_us_to_ticks_near64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_us, Z_HZ_ticks, true, false, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_us_to_ticks_near64(t) \ + z_tmcvt_64(t, Z_HZ_us, Z_HZ_ticks, true, false, true) + -/** @brief Convert microseconds to ticks +/** @brief Convert microseconds to ticks. 32 bits. Rounds up. * * Converts time values in microseconds to ticks. * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in microseconds. uint64_t + * + * @return The converted time value in ticks. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_us_to_ticks_ceil32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_us, Z_HZ_ticks, true, true, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_us_to_ticks_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_us, Z_HZ_ticks, true, true, false) -/** @brief Convert microseconds to ticks + +/** @brief Convert microseconds to ticks. 64 bits. Rounds up. * * Converts time values in microseconds to ticks. * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in microseconds. uint64_t + * + * @return The converted time value in ticks. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_us_to_ticks_ceil64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_us, Z_HZ_ticks, true, false, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_us_to_ticks_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_us, Z_HZ_ticks, true, true, false) + -/** @brief Convert nanoseconds to hardware cycles +/** @brief Convert nanoseconds to hardware cycles. 32 bits. Truncates. * * Converts time values in nanoseconds to hardware cycles. * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in nanoseconds. uint64_t + * + * @return The converted time value in hardware cycles. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ns_to_cyc_floor32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, true, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_ns_to_cyc_floor32(t) \ + z_tmcvt_32(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, false, false) -/** @brief Convert nanoseconds to hardware cycles + +/** @brief Convert nanoseconds to hardware cycles. 64 bits. Truncates. * * Converts time values in nanoseconds to hardware cycles. * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in nanoseconds. uint64_t + * + * @return The converted time value in hardware cycles. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ns_to_cyc_floor64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, false, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_ns_to_cyc_floor64(t) \ + z_tmcvt_64(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, false, false) + -/** @brief Convert nanoseconds to hardware cycles +/** @brief Convert nanoseconds to hardware cycles. 32 bits. Round nearest. * * Converts time values in nanoseconds to hardware cycles. * Computes result in 32 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in nanoseconds. uint64_t + * + * @return The converted time value in hardware cycles. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ns_to_cyc_near32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, true, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_ns_to_cyc_near32(t) \ + z_tmcvt_32(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, false, true) -/** @brief Convert nanoseconds to hardware cycles + +/** @brief Convert nanoseconds to hardware cycles. 64 bits. Round nearest. * * Converts time values in nanoseconds to hardware cycles. * Computes result in 64 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in nanoseconds. uint64_t + * + * @return The converted time value in hardware cycles. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ns_to_cyc_near64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, false, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_ns_to_cyc_near64(t) \ + z_tmcvt_64(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, false, true) + -/** @brief Convert nanoseconds to hardware cycles +/** @brief Convert nanoseconds to hardware cycles. 32 bits. Rounds up. * * Converts time values in nanoseconds to hardware cycles. * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in nanoseconds. uint64_t + * + * @return The converted time value in hardware cycles. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ns_to_cyc_ceil32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, true, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_ns_to_cyc_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, true, false) -/** @brief Convert nanoseconds to hardware cycles + +/** @brief Convert nanoseconds to hardware cycles. 64 bits. Rounds up. * * Converts time values in nanoseconds to hardware cycles. * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in nanoseconds. uint64_t + * + * @return The converted time value in hardware cycles. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ns_to_cyc_ceil64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, false, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_ns_to_cyc_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, true, false) + -/** @brief Convert nanoseconds to ticks +/** @brief Convert nanoseconds to ticks. 32 bits. Truncates. * * Converts time values in nanoseconds to ticks. * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in nanoseconds. uint64_t + * + * @return The converted time value in ticks. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ns_to_ticks_floor32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ns, Z_HZ_ticks, true, true, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_ns_to_ticks_floor32(t) \ + z_tmcvt_32(t, Z_HZ_ns, Z_HZ_ticks, true, false, false) + -/** @brief Convert nanoseconds to ticks +/** @brief Convert nanoseconds to ticks. 64 bits. Truncates. * * Converts time values in nanoseconds to ticks. * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in nanoseconds. uint64_t + * + * @return The converted time value in ticks. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ns_to_ticks_floor64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ns, Z_HZ_ticks, true, false, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_ns_to_ticks_floor64(t) \ + z_tmcvt_64(t, Z_HZ_ns, Z_HZ_ticks, true, false, false) + -/** @brief Convert nanoseconds to ticks +/** @brief Convert nanoseconds to ticks. 32 bits. Round nearest. * * Converts time values in nanoseconds to ticks. * Computes result in 32 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in nanoseconds. uint64_t + * + * @return The converted time value in ticks. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ns_to_ticks_near32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ns, Z_HZ_ticks, true, true, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_ns_to_ticks_near32(t) \ + z_tmcvt_32(t, Z_HZ_ns, Z_HZ_ticks, true, false, true) + -/** @brief Convert nanoseconds to ticks +/** @brief Convert nanoseconds to ticks. 64 bits. Round nearest. * * Converts time values in nanoseconds to ticks. * Computes result in 64 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in nanoseconds. uint64_t + * + * @return The converted time value in ticks. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ns_to_ticks_near64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ns, Z_HZ_ticks, true, false, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_ns_to_ticks_near64(t) \ + z_tmcvt_64(t, Z_HZ_ns, Z_HZ_ticks, true, false, true) -/** @brief Convert nanoseconds to ticks + +/** @brief Convert nanoseconds to ticks. 32 bits. Rounds up. * * Converts time values in nanoseconds to ticks. * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in nanoseconds. uint64_t + * + * @return The converted time value in ticks. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ns_to_ticks_ceil32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ns, Z_HZ_ticks, true, true, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_ns_to_ticks_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_ns, Z_HZ_ticks, true, true, false) + -/** @brief Convert nanoseconds to ticks +/** @brief Convert nanoseconds to ticks. 64 bits. Rounds up. * * Converts time values in nanoseconds to ticks. * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in nanoseconds. uint64_t + * + * @return The converted time value in ticks. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ns_to_ticks_ceil64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ns, Z_HZ_ticks, true, false, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_ns_to_ticks_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_ns, Z_HZ_ticks, true, true, false) -/** @brief Convert hardware cycles to milliseconds + +/** @brief Convert hardware cycles to milliseconds. 32 bits. Truncates. * * Converts time values in hardware cycles to milliseconds. * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in milliseconds. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_cyc_to_ms_floor32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, true, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_ms_floor32(t) \ + z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, false, false) + -/** @brief Convert hardware cycles to milliseconds +/** @brief Convert hardware cycles to milliseconds. 64 bits. Truncates. * * Converts time values in hardware cycles to milliseconds. * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in milliseconds. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_cyc_to_ms_floor64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, false, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_ms_floor64(t) \ + z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, false, false) -/** @brief Convert hardware cycles to milliseconds + +/** @brief Convert hardware cycles to milliseconds. 32 bits. Round nearest. * * Converts time values in hardware cycles to milliseconds. * Computes result in 32 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in milliseconds. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_cyc_to_ms_near32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, true, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_ms_near32(t) \ + z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, false, true) + -/** @brief Convert hardware cycles to milliseconds +/** @brief Convert hardware cycles to milliseconds. 64 bits. Round nearest. * * Converts time values in hardware cycles to milliseconds. * Computes result in 64 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in milliseconds. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_cyc_to_ms_near64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, false, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_ms_near64(t) \ + z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, false, true) -/** @brief Convert hardware cycles to milliseconds + +/** @brief Convert hardware cycles to milliseconds. 32 bits. Rounds up. * * Converts time values in hardware cycles to milliseconds. * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in milliseconds. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_cyc_to_ms_ceil32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, true, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_ms_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, true, false) + -/** @brief Convert hardware cycles to milliseconds +/** @brief Convert hardware cycles to milliseconds. 64 bits. Rounds up. * * Converts time values in hardware cycles to milliseconds. * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in milliseconds. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_cyc_to_ms_ceil64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, false, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_ms_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, true, false) + -/** @brief Convert hardware cycles to microseconds +/** @brief Convert hardware cycles to microseconds. 32 bits. Truncates. * * Converts time values in hardware cycles to microseconds. * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in microseconds. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_cyc_to_us_floor32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, true, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_us_floor32(t) \ + z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, false, false) + -/** @brief Convert hardware cycles to microseconds +/** @brief Convert hardware cycles to microseconds. 64 bits. Truncates. * * Converts time values in hardware cycles to microseconds. * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in microseconds. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_cyc_to_us_floor64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, false, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_us_floor64(t) \ + z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, false, false) + -/** @brief Convert hardware cycles to microseconds +/** @brief Convert hardware cycles to microseconds. 32 bits. Round nearest. * * Converts time values in hardware cycles to microseconds. * Computes result in 32 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in microseconds. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_cyc_to_us_near32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, true, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_us_near32(t) \ + z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, false, true) -/** @brief Convert hardware cycles to microseconds + +/** @brief Convert hardware cycles to microseconds. 64 bits. Round nearest. * * Converts time values in hardware cycles to microseconds. * Computes result in 64 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in microseconds. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_cyc_to_us_near64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, false, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_us_near64(t) \ + z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, false, true) + -/** @brief Convert hardware cycles to microseconds +/** @brief Convert hardware cycles to microseconds. 32 bits. Rounds up. * * Converts time values in hardware cycles to microseconds. * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in microseconds. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_cyc_to_us_ceil32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, true, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_us_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, true, false) -/** @brief Convert hardware cycles to microseconds + +/** @brief Convert hardware cycles to microseconds. 64 bits. Rounds up. * * Converts time values in hardware cycles to microseconds. * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in microseconds. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_cyc_to_us_ceil64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, false, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_us_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, true, false) + -/** @brief Convert hardware cycles to nanoseconds +/** @brief Convert hardware cycles to nanoseconds. 32 bits. Truncates. * * Converts time values in hardware cycles to nanoseconds. * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in nanoseconds. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_cyc_to_ns_floor32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, true, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_ns_floor32(t) \ + z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, false, false) -/** @brief Convert hardware cycles to nanoseconds + +/** @brief Convert hardware cycles to nanoseconds. 64 bits. Truncates. * * Converts time values in hardware cycles to nanoseconds. * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in nanoseconds. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_cyc_to_ns_floor64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, false, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_ns_floor64(t) \ + z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, false, false) + -/** @brief Convert hardware cycles to nanoseconds +/** @brief Convert hardware cycles to nanoseconds. 32 bits. Round nearest. * * Converts time values in hardware cycles to nanoseconds. * Computes result in 32 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in nanoseconds. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_cyc_to_ns_near32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, true, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_ns_near32(t) \ + z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, false, true) -/** @brief Convert hardware cycles to nanoseconds + +/** @brief Convert hardware cycles to nanoseconds. 64 bits. Round nearest. * * Converts time values in hardware cycles to nanoseconds. * Computes result in 64 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in nanoseconds. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_cyc_to_ns_near64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, false, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_ns_near64(t) \ + z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, false, true) + -/** @brief Convert hardware cycles to nanoseconds +/** @brief Convert hardware cycles to nanoseconds. 32 bits. Rounds up. * * Converts time values in hardware cycles to nanoseconds. * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in nanoseconds. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_cyc_to_ns_ceil32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, true, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_ns_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, true, false) + -/** @brief Convert hardware cycles to nanoseconds +/** @brief Convert hardware cycles to nanoseconds. 64 bits. Rounds up. * * Converts time values in hardware cycles to nanoseconds. * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in nanoseconds. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_cyc_to_ns_ceil64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, false, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_ns_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, true, false) + -/** @brief Convert hardware cycles to ticks +/** @brief Convert hardware cycles to ticks. 32 bits. Truncates. * * Converts time values in hardware cycles to ticks. * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in ticks. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_cyc_to_ticks_floor32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, true, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_ticks_floor32(t) \ + z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, false, false) + -/** @brief Convert hardware cycles to ticks +/** @brief Convert hardware cycles to ticks. 64 bits. Truncates. * * Converts time values in hardware cycles to ticks. * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in ticks. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_cyc_to_ticks_floor64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, false, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_ticks_floor64(t) \ + z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, false, false) -/** @brief Convert hardware cycles to ticks + +/** @brief Convert hardware cycles to ticks. 32 bits. Round nearest. * * Converts time values in hardware cycles to ticks. * Computes result in 32 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in ticks. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_cyc_to_ticks_near32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, true, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_ticks_near32(t) \ + z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, false, true) + -/** @brief Convert hardware cycles to ticks +/** @brief Convert hardware cycles to ticks. 64 bits. Round nearest. * * Converts time values in hardware cycles to ticks. * Computes result in 64 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in ticks. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_cyc_to_ticks_near64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, false, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_ticks_near64(t) \ + z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, false, true) -/** @brief Convert hardware cycles to ticks + +/** @brief Convert hardware cycles to ticks. 32 bits. Rounds up. * * Converts time values in hardware cycles to ticks. * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in ticks. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_cyc_to_ticks_ceil32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, true, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_ticks_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, true, false) + -/** @brief Convert hardware cycles to ticks +/** @brief Convert hardware cycles to ticks. 64 bits. Rounds up. * * Converts time values in hardware cycles to ticks. * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in ticks. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_cyc_to_ticks_ceil64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, false, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_cyc_to_ticks_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, true, false) -/** @brief Convert ticks to milliseconds + +/** @brief Convert ticks to milliseconds. 32 bits. Truncates. * * Converts time values in ticks to milliseconds. * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in milliseconds. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ticks_to_ms_floor32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_ms, true, true, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_ms_floor32(t) \ + z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_ms, true, false, false) + -/** @brief Convert ticks to milliseconds +/** @brief Convert ticks to milliseconds. 64 bits. Truncates. * * Converts time values in ticks to milliseconds. * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in milliseconds. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ticks_to_ms_floor64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_ms, true, false, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_ms_floor64(t) \ + z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_ms, true, false, false) -/** @brief Convert ticks to milliseconds + +/** @brief Convert ticks to milliseconds. 32 bits. Round nearest. * * Converts time values in ticks to milliseconds. * Computes result in 32 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in milliseconds. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ticks_to_ms_near32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_ms, true, true, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_ms_near32(t) \ + z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_ms, true, false, true) + -/** @brief Convert ticks to milliseconds +/** @brief Convert ticks to milliseconds. 64 bits. Round nearest. * * Converts time values in ticks to milliseconds. * Computes result in 64 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in milliseconds. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ticks_to_ms_near64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_ms, true, false, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_ms_near64(t) \ + z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_ms, true, false, true) + -/** @brief Convert ticks to milliseconds +/** @brief Convert ticks to milliseconds. 32 bits. Rounds up. * * Converts time values in ticks to milliseconds. * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in milliseconds. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ticks_to_ms_ceil32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_ms, true, true, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_ms_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_ms, true, true, false) + -/** @brief Convert ticks to milliseconds +/** @brief Convert ticks to milliseconds. 64 bits. Rounds up. * * Converts time values in ticks to milliseconds. * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in milliseconds. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ticks_to_ms_ceil64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_ms, true, false, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_ms_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_ms, true, true, false) + -/** @brief Convert ticks to microseconds +/** @brief Convert ticks to microseconds. 32 bits. Truncates. * * Converts time values in ticks to microseconds. * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in microseconds. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ticks_to_us_floor32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_us, true, true, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_us_floor32(t) \ + z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_us, true, false, false) -/** @brief Convert ticks to microseconds + +/** @brief Convert ticks to microseconds. 64 bits. Truncates. * * Converts time values in ticks to microseconds. * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in microseconds. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ticks_to_us_floor64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_us, true, false, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_us_floor64(t) \ + z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_us, true, false, false) + -/** @brief Convert ticks to microseconds +/** @brief Convert ticks to microseconds. 32 bits. Round nearest. * * Converts time values in ticks to microseconds. * Computes result in 32 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in microseconds. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ticks_to_us_near32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_us, true, true, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_us_near32(t) \ + z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_us, true, false, true) -/** @brief Convert ticks to microseconds + +/** @brief Convert ticks to microseconds. 64 bits. Round nearest. * * Converts time values in ticks to microseconds. * Computes result in 64 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in microseconds. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ticks_to_us_near64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_us, true, false, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_us_near64(t) \ + z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_us, true, false, true) + -/** @brief Convert ticks to microseconds +/** @brief Convert ticks to microseconds. 32 bits. Rounds up. * * Converts time values in ticks to microseconds. * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in microseconds. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ticks_to_us_ceil32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_us, true, true, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_us_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_us, true, true, false) -/** @brief Convert ticks to microseconds + +/** @brief Convert ticks to microseconds. 64 bits. Rounds up. * * Converts time values in ticks to microseconds. * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in microseconds. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ticks_to_us_ceil64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_us, true, false, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_us_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_us, true, true, false) + -/** @brief Convert ticks to nanoseconds +/** @brief Convert ticks to nanoseconds. 32 bits. Truncates. * * Converts time values in ticks to nanoseconds. * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in nanoseconds. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ticks_to_ns_floor32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_ns, true, true, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_ns_floor32(t) \ + z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_ns, true, false, false) -/** @brief Convert ticks to nanoseconds + +/** @brief Convert ticks to nanoseconds. 64 bits. Truncates. * * Converts time values in ticks to nanoseconds. * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in nanoseconds. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ticks_to_ns_floor64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_ns, true, false, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_ns_floor64(t) \ + z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_ns, true, false, false) + -/** @brief Convert ticks to nanoseconds +/** @brief Convert ticks to nanoseconds. 32 bits. Round nearest. * * Converts time values in ticks to nanoseconds. * Computes result in 32 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in nanoseconds. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ticks_to_ns_near32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_ns, true, true, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_ns_near32(t) \ + z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_ns, true, false, true) + -/** @brief Convert ticks to nanoseconds +/** @brief Convert ticks to nanoseconds. 64 bits. Round nearest. * * Converts time values in ticks to nanoseconds. * Computes result in 64 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in nanoseconds. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ticks_to_ns_near64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_ns, true, false, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_ns_near64(t) \ + z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_ns, true, false, true) + -/** @brief Convert ticks to nanoseconds +/** @brief Convert ticks to nanoseconds. 32 bits. Rounds up. * * Converts time values in ticks to nanoseconds. * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in nanoseconds. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ticks_to_ns_ceil32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_ns, true, true, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_ns_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_ns, true, true, false) + -/** @brief Convert ticks to nanoseconds +/** @brief Convert ticks to nanoseconds. 64 bits. Rounds up. * * Converts time values in ticks to nanoseconds. * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in nanoseconds. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ticks_to_ns_ceil64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_ns, true, false, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_ns_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_ns, true, true, false) -/** @brief Convert ticks to hardware cycles + +/** @brief Convert ticks to hardware cycles. 32 bits. Truncates. * * Converts time values in ticks to hardware cycles. * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in hardware cycles. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ticks_to_cyc_floor32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, true, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_cyc_floor32(t) \ + z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, false, false) + -/** @brief Convert ticks to hardware cycles +/** @brief Convert ticks to hardware cycles. 64 bits. Truncates. * * Converts time values in ticks to hardware cycles. * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in hardware cycles. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ticks_to_cyc_floor64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, false, false, false); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_cyc_floor64(t) \ + z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, false, false) -/** @brief Convert ticks to hardware cycles + +/** @brief Convert ticks to hardware cycles. 32 bits. Round nearest. * * Converts time values in ticks to hardware cycles. * Computes result in 32 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in hardware cycles. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ticks_to_cyc_near32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, true, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_cyc_near32(t) \ + z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, false, true) + -/** @brief Convert ticks to hardware cycles +/** @brief Convert ticks to hardware cycles. 64 bits. Round nearest. * * Converts time values in ticks to hardware cycles. * Computes result in 64 bit precision. * Rounds to the nearest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in hardware cycles. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ticks_to_cyc_near64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, false, false, true); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_cyc_near64(t) \ + z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, false, true) -/** @brief Convert ticks to hardware cycles + +/** @brief Convert ticks to hardware cycles. 32 bits. Rounds up. * * Converts time values in ticks to hardware cycles. * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in hardware cycles. uint32_t */ -static TIME_CONSTEXPR inline uint32_t k_ticks_to_cyc_ceil32(uint32_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, true, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_cyc_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, true, false) + -/** @brief Convert ticks to hardware cycles +/** @brief Convert ticks to hardware cycles. 64 bits. Rounds up. * * Converts time values in ticks to hardware cycles. * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * - * @return The converted time value + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in hardware cycles. uint64_t */ -static TIME_CONSTEXPR inline uint64_t k_ticks_to_cyc_ceil64(uint64_t t) -{ - /* Generated. Do not edit. See above. */ - return z_tmcvt(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, false, true, false); -} +/* Generated. Do not edit. See above. */ +#define k_ticks_to_cyc_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, true, false) #if defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) #include diff --git a/include/zephyr/sys/util.h b/include/zephyr/sys/util.h index e2c3f9d4fb5..a812ee4d37e 100644 --- a/include/zephyr/sys/util.h +++ b/include/zephyr/sys/util.h @@ -15,6 +15,7 @@ #define ZEPHYR_INCLUDE_SYS_UTIL_H_ #include +#include /* needs to be outside _ASMLANGUAGE so 'true' and 'false' can turn * into '1' and '0' for asm or linker scripts @@ -201,6 +202,27 @@ extern "C" { (POINTER_TO_UINT(ptr) - POINTER_TO_UINT(array)) / sizeof((array)[0]); \ }) +/** + * @brief Validate if two entities have a compatible type + * + * @param a the first entity to be compared + * @param b the second entity to be compared + * @return 1 if the two elements are compatible, 0 if they are not + */ +#define SAME_TYPE(a, b) __builtin_types_compatible_p(__typeof__(a), __typeof__(b)) + +/** + * @brief Validate CONTAINER_OF parameters, only applies to C mode. + */ +#ifndef __cplusplus +#define CONTAINER_OF_VALIDATE(ptr, type, field) \ + BUILD_ASSERT(SAME_TYPE(*(ptr), ((type *)0)->field) || \ + SAME_TYPE(*(ptr), void), \ + "pointer type mismatch in CONTAINER_OF"); +#else +#define CONTAINER_OF_VALIDATE(ptr, type, field) +#endif + /** * @brief Get a pointer to a structure containing the element * @@ -222,8 +244,20 @@ extern "C" { * @param field the name of the field within the struct @p ptr points to * @return a pointer to the structure that contains @p ptr */ -#define CONTAINER_OF(ptr, type, field) \ - ((type *)(((char *)(ptr)) - offsetof(type, field))) +#define CONTAINER_OF(ptr, type, field) \ + ({ \ + CONTAINER_OF_VALIDATE(ptr, type, field) \ + ((type *)(((char *)(ptr)) - offsetof(type, field))); \ + }) + +/** + * @brief Concatenate two tokens into one + * + * Concatenate two tokens, @p x and @p y, into a combined token during the preprocessor pass. + * This can be used to, for ex., build an identifier out of two parts, + * where one of those parts may be, for ex, a number, another macro, or a macro argument. + */ +#define CONCAT(x, y) _DO_CONCAT(x, y) /** * @brief Value of @p x rounded up to the next multiple of @p align. diff --git a/include/zephyr/sys/util_internal.h b/include/zephyr/sys/util_internal.h index 7850886b54b..2cde08332e2 100644 --- a/include/zephyr/sys/util_internal.h +++ b/include/zephyr/sys/util_internal.h @@ -50,7 +50,7 @@ #define Z_IS_ENABLED3(ignore_this, val, ...) val /* Implementation of IS_EQ(). Returns 1 if _0 and _1 are the same integer from - * 0 to 255, 0 otherwise. + * 0 to 4095, 0 otherwise. */ #define Z_IS_EQ(_0, _1) Z_HAS_COMMA(Z_CAT4(Z_IS_, _0, _EQ_, _1)()) @@ -150,262 +150,7 @@ #define MACRO_MC_15(m, a, ...) UTIL_CAT(m(a), MACRO_MC_14(m, __VA_ARGS__,)) /* Used by Z_IS_EQ */ -#define Z_IS_0_EQ_0(...) \, -#define Z_IS_1_EQ_1(...) \, -#define Z_IS_2_EQ_2(...) \, -#define Z_IS_3_EQ_3(...) \, -#define Z_IS_4_EQ_4(...) \, -#define Z_IS_5_EQ_5(...) \, -#define Z_IS_6_EQ_6(...) \, -#define Z_IS_7_EQ_7(...) \, -#define Z_IS_8_EQ_8(...) \, -#define Z_IS_9_EQ_9(...) \, -#define Z_IS_10_EQ_10(...) \, -#define Z_IS_11_EQ_11(...) \, -#define Z_IS_12_EQ_12(...) \, -#define Z_IS_13_EQ_13(...) \, -#define Z_IS_14_EQ_14(...) \, -#define Z_IS_15_EQ_15(...) \, -#define Z_IS_16_EQ_16(...) \, -#define Z_IS_17_EQ_17(...) \, -#define Z_IS_18_EQ_18(...) \, -#define Z_IS_19_EQ_19(...) \, -#define Z_IS_20_EQ_20(...) \, -#define Z_IS_21_EQ_21(...) \, -#define Z_IS_22_EQ_22(...) \, -#define Z_IS_23_EQ_23(...) \, -#define Z_IS_24_EQ_24(...) \, -#define Z_IS_25_EQ_25(...) \, -#define Z_IS_26_EQ_26(...) \, -#define Z_IS_27_EQ_27(...) \, -#define Z_IS_28_EQ_28(...) \, -#define Z_IS_29_EQ_29(...) \, -#define Z_IS_30_EQ_30(...) \, -#define Z_IS_31_EQ_31(...) \, -#define Z_IS_32_EQ_32(...) \, -#define Z_IS_33_EQ_33(...) \, -#define Z_IS_34_EQ_34(...) \, -#define Z_IS_35_EQ_35(...) \, -#define Z_IS_36_EQ_36(...) \, -#define Z_IS_37_EQ_37(...) \, -#define Z_IS_38_EQ_38(...) \, -#define Z_IS_39_EQ_39(...) \, -#define Z_IS_40_EQ_40(...) \, -#define Z_IS_41_EQ_41(...) \, -#define Z_IS_42_EQ_42(...) \, -#define Z_IS_43_EQ_43(...) \, -#define Z_IS_44_EQ_44(...) \, -#define Z_IS_45_EQ_45(...) \, -#define Z_IS_46_EQ_46(...) \, -#define Z_IS_47_EQ_47(...) \, -#define Z_IS_48_EQ_48(...) \, -#define Z_IS_49_EQ_49(...) \, -#define Z_IS_50_EQ_50(...) \, -#define Z_IS_51_EQ_51(...) \, -#define Z_IS_52_EQ_52(...) \, -#define Z_IS_53_EQ_53(...) \, -#define Z_IS_54_EQ_54(...) \, -#define Z_IS_55_EQ_55(...) \, -#define Z_IS_56_EQ_56(...) \, -#define Z_IS_57_EQ_57(...) \, -#define Z_IS_58_EQ_58(...) \, -#define Z_IS_59_EQ_59(...) \, -#define Z_IS_60_EQ_60(...) \, -#define Z_IS_61_EQ_61(...) \, -#define Z_IS_62_EQ_62(...) \, -#define Z_IS_63_EQ_63(...) \, -#define Z_IS_64_EQ_64(...) \, -#define Z_IS_65_EQ_65(...) \, -#define Z_IS_66_EQ_66(...) \, -#define Z_IS_67_EQ_67(...) \, -#define Z_IS_68_EQ_68(...) \, -#define Z_IS_69_EQ_69(...) \, -#define Z_IS_70_EQ_70(...) \, -#define Z_IS_71_EQ_71(...) \, -#define Z_IS_72_EQ_72(...) \, -#define Z_IS_73_EQ_73(...) \, -#define Z_IS_74_EQ_74(...) \, -#define Z_IS_75_EQ_75(...) \, -#define Z_IS_76_EQ_76(...) \, -#define Z_IS_77_EQ_77(...) \, -#define Z_IS_78_EQ_78(...) \, -#define Z_IS_79_EQ_79(...) \, -#define Z_IS_80_EQ_80(...) \, -#define Z_IS_81_EQ_81(...) \, -#define Z_IS_82_EQ_82(...) \, -#define Z_IS_83_EQ_83(...) \, -#define Z_IS_84_EQ_84(...) \, -#define Z_IS_85_EQ_85(...) \, -#define Z_IS_86_EQ_86(...) \, -#define Z_IS_87_EQ_87(...) \, -#define Z_IS_88_EQ_88(...) \, -#define Z_IS_89_EQ_89(...) \, -#define Z_IS_90_EQ_90(...) \, -#define Z_IS_91_EQ_91(...) \, -#define Z_IS_92_EQ_92(...) \, -#define Z_IS_93_EQ_93(...) \, -#define Z_IS_94_EQ_94(...) \, -#define Z_IS_95_EQ_95(...) \, -#define Z_IS_96_EQ_96(...) \, -#define Z_IS_97_EQ_97(...) \, -#define Z_IS_98_EQ_98(...) \, -#define Z_IS_99_EQ_99(...) \, -#define Z_IS_100_EQ_100(...) \, -#define Z_IS_101_EQ_101(...) \, -#define Z_IS_102_EQ_102(...) \, -#define Z_IS_103_EQ_103(...) \, -#define Z_IS_104_EQ_104(...) \, -#define Z_IS_105_EQ_105(...) \, -#define Z_IS_106_EQ_106(...) \, -#define Z_IS_107_EQ_107(...) \, -#define Z_IS_108_EQ_108(...) \, -#define Z_IS_109_EQ_109(...) \, -#define Z_IS_110_EQ_110(...) \, -#define Z_IS_111_EQ_111(...) \, -#define Z_IS_112_EQ_112(...) \, -#define Z_IS_113_EQ_113(...) \, -#define Z_IS_114_EQ_114(...) \, -#define Z_IS_115_EQ_115(...) \, -#define Z_IS_116_EQ_116(...) \, -#define Z_IS_117_EQ_117(...) \, -#define Z_IS_118_EQ_118(...) \, -#define Z_IS_119_EQ_119(...) \, -#define Z_IS_120_EQ_120(...) \, -#define Z_IS_121_EQ_121(...) \, -#define Z_IS_122_EQ_122(...) \, -#define Z_IS_123_EQ_123(...) \, -#define Z_IS_124_EQ_124(...) \, -#define Z_IS_125_EQ_125(...) \, -#define Z_IS_126_EQ_126(...) \, -#define Z_IS_127_EQ_127(...) \, -#define Z_IS_128_EQ_128(...) \, -#define Z_IS_129_EQ_129(...) \, -#define Z_IS_130_EQ_130(...) \, -#define Z_IS_131_EQ_131(...) \, -#define Z_IS_132_EQ_132(...) \, -#define Z_IS_133_EQ_133(...) \, -#define Z_IS_134_EQ_134(...) \, -#define Z_IS_135_EQ_135(...) \, -#define Z_IS_136_EQ_136(...) \, -#define Z_IS_137_EQ_137(...) \, -#define Z_IS_138_EQ_138(...) \, -#define Z_IS_139_EQ_139(...) \, -#define Z_IS_140_EQ_140(...) \, -#define Z_IS_141_EQ_141(...) \, -#define Z_IS_142_EQ_142(...) \, -#define Z_IS_143_EQ_143(...) \, -#define Z_IS_144_EQ_144(...) \, -#define Z_IS_145_EQ_145(...) \, -#define Z_IS_146_EQ_146(...) \, -#define Z_IS_147_EQ_147(...) \, -#define Z_IS_148_EQ_148(...) \, -#define Z_IS_149_EQ_149(...) \, -#define Z_IS_150_EQ_150(...) \, -#define Z_IS_151_EQ_151(...) \, -#define Z_IS_152_EQ_152(...) \, -#define Z_IS_153_EQ_153(...) \, -#define Z_IS_154_EQ_154(...) \, -#define Z_IS_155_EQ_155(...) \, -#define Z_IS_156_EQ_156(...) \, -#define Z_IS_157_EQ_157(...) \, -#define Z_IS_158_EQ_158(...) \, -#define Z_IS_159_EQ_159(...) \, -#define Z_IS_160_EQ_160(...) \, -#define Z_IS_161_EQ_161(...) \, -#define Z_IS_162_EQ_162(...) \, -#define Z_IS_163_EQ_163(...) \, -#define Z_IS_164_EQ_164(...) \, -#define Z_IS_165_EQ_165(...) \, -#define Z_IS_166_EQ_166(...) \, -#define Z_IS_167_EQ_167(...) \, -#define Z_IS_168_EQ_168(...) \, -#define Z_IS_169_EQ_169(...) \, -#define Z_IS_170_EQ_170(...) \, -#define Z_IS_171_EQ_171(...) \, -#define Z_IS_172_EQ_172(...) \, -#define Z_IS_173_EQ_173(...) \, -#define Z_IS_174_EQ_174(...) \, -#define Z_IS_175_EQ_175(...) \, -#define Z_IS_176_EQ_176(...) \, -#define Z_IS_177_EQ_177(...) \, -#define Z_IS_178_EQ_178(...) \, -#define Z_IS_179_EQ_179(...) \, -#define Z_IS_180_EQ_180(...) \, -#define Z_IS_181_EQ_181(...) \, -#define Z_IS_182_EQ_182(...) \, -#define Z_IS_183_EQ_183(...) \, -#define Z_IS_184_EQ_184(...) \, -#define Z_IS_185_EQ_185(...) \, -#define Z_IS_186_EQ_186(...) \, -#define Z_IS_187_EQ_187(...) \, -#define Z_IS_188_EQ_188(...) \, -#define Z_IS_189_EQ_189(...) \, -#define Z_IS_190_EQ_190(...) \, -#define Z_IS_191_EQ_191(...) \, -#define Z_IS_192_EQ_192(...) \, -#define Z_IS_193_EQ_193(...) \, -#define Z_IS_194_EQ_194(...) \, -#define Z_IS_195_EQ_195(...) \, -#define Z_IS_196_EQ_196(...) \, -#define Z_IS_197_EQ_197(...) \, -#define Z_IS_198_EQ_198(...) \, -#define Z_IS_199_EQ_199(...) \, -#define Z_IS_200_EQ_200(...) \, -#define Z_IS_201_EQ_201(...) \, -#define Z_IS_202_EQ_202(...) \, -#define Z_IS_203_EQ_203(...) \, -#define Z_IS_204_EQ_204(...) \, -#define Z_IS_205_EQ_205(...) \, -#define Z_IS_206_EQ_206(...) \, -#define Z_IS_207_EQ_207(...) \, -#define Z_IS_208_EQ_208(...) \, -#define Z_IS_209_EQ_209(...) \, -#define Z_IS_210_EQ_210(...) \, -#define Z_IS_211_EQ_211(...) \, -#define Z_IS_212_EQ_212(...) \, -#define Z_IS_213_EQ_213(...) \, -#define Z_IS_214_EQ_214(...) \, -#define Z_IS_215_EQ_215(...) \, -#define Z_IS_216_EQ_216(...) \, -#define Z_IS_217_EQ_217(...) \, -#define Z_IS_218_EQ_218(...) \, -#define Z_IS_219_EQ_219(...) \, -#define Z_IS_220_EQ_220(...) \, -#define Z_IS_221_EQ_221(...) \, -#define Z_IS_222_EQ_222(...) \, -#define Z_IS_223_EQ_223(...) \, -#define Z_IS_224_EQ_224(...) \, -#define Z_IS_225_EQ_225(...) \, -#define Z_IS_226_EQ_226(...) \, -#define Z_IS_227_EQ_227(...) \, -#define Z_IS_228_EQ_228(...) \, -#define Z_IS_229_EQ_229(...) \, -#define Z_IS_230_EQ_230(...) \, -#define Z_IS_231_EQ_231(...) \, -#define Z_IS_232_EQ_232(...) \, -#define Z_IS_233_EQ_233(...) \, -#define Z_IS_234_EQ_234(...) \, -#define Z_IS_235_EQ_235(...) \, -#define Z_IS_236_EQ_236(...) \, -#define Z_IS_237_EQ_237(...) \, -#define Z_IS_238_EQ_238(...) \, -#define Z_IS_239_EQ_239(...) \, -#define Z_IS_240_EQ_240(...) \, -#define Z_IS_241_EQ_241(...) \, -#define Z_IS_242_EQ_242(...) \, -#define Z_IS_243_EQ_243(...) \, -#define Z_IS_244_EQ_244(...) \, -#define Z_IS_245_EQ_245(...) \, -#define Z_IS_246_EQ_246(...) \, -#define Z_IS_247_EQ_247(...) \, -#define Z_IS_248_EQ_248(...) \, -#define Z_IS_249_EQ_249(...) \, -#define Z_IS_250_EQ_250(...) \, -#define Z_IS_251_EQ_251(...) \, -#define Z_IS_252_EQ_252(...) \, -#define Z_IS_253_EQ_253(...) \, -#define Z_IS_254_EQ_254(...) \, -#define Z_IS_255_EQ_255(...) \, +#include "util_internal_is_eq.h" /* * Generic sparse list of odd numbers (check the implementation of @@ -435,775 +180,13 @@ 48, EMPTY, 50, EMPTY, 52, EMPTY, 54, EMPTY, \ 56, EMPTY, 58, EMPTY, 60, EMPTY, 62, EMPTY -#define UTIL_INC_0 1 -#define UTIL_INC_1 2 -#define UTIL_INC_2 3 -#define UTIL_INC_3 4 -#define UTIL_INC_4 5 -#define UTIL_INC_5 6 -#define UTIL_INC_6 7 -#define UTIL_INC_7 8 -#define UTIL_INC_8 9 -#define UTIL_INC_9 10 -#define UTIL_INC_10 11 -#define UTIL_INC_11 12 -#define UTIL_INC_12 13 -#define UTIL_INC_13 14 -#define UTIL_INC_14 15 -#define UTIL_INC_15 16 -#define UTIL_INC_16 17 -#define UTIL_INC_17 18 -#define UTIL_INC_18 19 -#define UTIL_INC_19 20 -#define UTIL_INC_20 21 -#define UTIL_INC_21 22 -#define UTIL_INC_22 23 -#define UTIL_INC_23 24 -#define UTIL_INC_24 25 -#define UTIL_INC_25 26 -#define UTIL_INC_26 27 -#define UTIL_INC_27 28 -#define UTIL_INC_28 29 -#define UTIL_INC_29 30 -#define UTIL_INC_30 31 -#define UTIL_INC_31 32 -#define UTIL_INC_32 33 -#define UTIL_INC_33 34 -#define UTIL_INC_34 35 -#define UTIL_INC_35 36 -#define UTIL_INC_36 37 -#define UTIL_INC_37 38 -#define UTIL_INC_38 39 -#define UTIL_INC_39 40 -#define UTIL_INC_40 41 -#define UTIL_INC_41 42 -#define UTIL_INC_42 43 -#define UTIL_INC_43 44 -#define UTIL_INC_44 45 -#define UTIL_INC_45 46 -#define UTIL_INC_46 47 -#define UTIL_INC_47 48 -#define UTIL_INC_48 49 -#define UTIL_INC_49 50 -#define UTIL_INC_50 51 -#define UTIL_INC_51 52 -#define UTIL_INC_52 53 -#define UTIL_INC_53 54 -#define UTIL_INC_54 55 -#define UTIL_INC_55 56 -#define UTIL_INC_56 57 -#define UTIL_INC_57 58 -#define UTIL_INC_58 59 -#define UTIL_INC_59 60 -#define UTIL_INC_60 61 -#define UTIL_INC_61 62 -#define UTIL_INC_62 63 -#define UTIL_INC_63 64 -#define UTIL_INC_64 65 -#define UTIL_INC_65 66 -#define UTIL_INC_66 67 -#define UTIL_INC_67 68 -#define UTIL_INC_68 69 -#define UTIL_INC_69 70 -#define UTIL_INC_70 71 -#define UTIL_INC_71 72 -#define UTIL_INC_72 73 -#define UTIL_INC_73 74 -#define UTIL_INC_74 75 -#define UTIL_INC_75 76 -#define UTIL_INC_76 77 -#define UTIL_INC_77 78 -#define UTIL_INC_78 79 -#define UTIL_INC_79 80 -#define UTIL_INC_80 81 -#define UTIL_INC_81 82 -#define UTIL_INC_82 83 -#define UTIL_INC_83 84 -#define UTIL_INC_84 85 -#define UTIL_INC_85 86 -#define UTIL_INC_86 87 -#define UTIL_INC_87 88 -#define UTIL_INC_88 89 -#define UTIL_INC_89 90 -#define UTIL_INC_90 91 -#define UTIL_INC_91 92 -#define UTIL_INC_92 93 -#define UTIL_INC_93 94 -#define UTIL_INC_94 95 -#define UTIL_INC_95 96 -#define UTIL_INC_96 97 -#define UTIL_INC_97 98 -#define UTIL_INC_98 99 -#define UTIL_INC_99 100 -#define UTIL_INC_100 101 -#define UTIL_INC_101 102 -#define UTIL_INC_102 103 -#define UTIL_INC_103 104 -#define UTIL_INC_104 105 -#define UTIL_INC_105 106 -#define UTIL_INC_106 107 -#define UTIL_INC_107 108 -#define UTIL_INC_108 109 -#define UTIL_INC_109 110 -#define UTIL_INC_110 111 -#define UTIL_INC_111 112 -#define UTIL_INC_112 113 -#define UTIL_INC_113 114 -#define UTIL_INC_114 115 -#define UTIL_INC_115 116 -#define UTIL_INC_116 117 -#define UTIL_INC_117 118 -#define UTIL_INC_118 119 -#define UTIL_INC_119 120 -#define UTIL_INC_120 121 -#define UTIL_INC_121 122 -#define UTIL_INC_122 123 -#define UTIL_INC_123 124 -#define UTIL_INC_124 125 -#define UTIL_INC_125 126 -#define UTIL_INC_126 127 -#define UTIL_INC_127 128 -#define UTIL_INC_128 129 -#define UTIL_INC_129 130 -#define UTIL_INC_130 131 -#define UTIL_INC_131 132 -#define UTIL_INC_132 133 -#define UTIL_INC_133 134 -#define UTIL_INC_134 135 -#define UTIL_INC_135 136 -#define UTIL_INC_136 137 -#define UTIL_INC_137 138 -#define UTIL_INC_138 139 -#define UTIL_INC_139 140 -#define UTIL_INC_140 141 -#define UTIL_INC_141 142 -#define UTIL_INC_142 143 -#define UTIL_INC_143 144 -#define UTIL_INC_144 145 -#define UTIL_INC_145 146 -#define UTIL_INC_146 147 -#define UTIL_INC_147 148 -#define UTIL_INC_148 149 -#define UTIL_INC_149 150 -#define UTIL_INC_150 151 -#define UTIL_INC_151 152 -#define UTIL_INC_152 153 -#define UTIL_INC_153 154 -#define UTIL_INC_154 155 -#define UTIL_INC_155 156 -#define UTIL_INC_156 157 -#define UTIL_INC_157 158 -#define UTIL_INC_158 159 -#define UTIL_INC_159 160 -#define UTIL_INC_160 161 -#define UTIL_INC_161 162 -#define UTIL_INC_162 163 -#define UTIL_INC_163 164 -#define UTIL_INC_164 165 -#define UTIL_INC_165 166 -#define UTIL_INC_166 167 -#define UTIL_INC_167 168 -#define UTIL_INC_168 169 -#define UTIL_INC_169 170 -#define UTIL_INC_170 171 -#define UTIL_INC_171 172 -#define UTIL_INC_172 173 -#define UTIL_INC_173 174 -#define UTIL_INC_174 175 -#define UTIL_INC_175 176 -#define UTIL_INC_176 177 -#define UTIL_INC_177 178 -#define UTIL_INC_178 179 -#define UTIL_INC_179 180 -#define UTIL_INC_180 181 -#define UTIL_INC_181 182 -#define UTIL_INC_182 183 -#define UTIL_INC_183 184 -#define UTIL_INC_184 185 -#define UTIL_INC_185 186 -#define UTIL_INC_186 187 -#define UTIL_INC_187 188 -#define UTIL_INC_188 189 -#define UTIL_INC_189 190 -#define UTIL_INC_190 191 -#define UTIL_INC_191 192 -#define UTIL_INC_192 193 -#define UTIL_INC_193 194 -#define UTIL_INC_194 195 -#define UTIL_INC_195 196 -#define UTIL_INC_196 197 -#define UTIL_INC_197 198 -#define UTIL_INC_198 199 -#define UTIL_INC_199 200 -#define UTIL_INC_200 201 -#define UTIL_INC_201 202 -#define UTIL_INC_202 203 -#define UTIL_INC_203 204 -#define UTIL_INC_204 205 -#define UTIL_INC_205 206 -#define UTIL_INC_206 207 -#define UTIL_INC_207 208 -#define UTIL_INC_208 209 -#define UTIL_INC_209 210 -#define UTIL_INC_210 211 -#define UTIL_INC_211 212 -#define UTIL_INC_212 213 -#define UTIL_INC_213 214 -#define UTIL_INC_214 215 -#define UTIL_INC_215 216 -#define UTIL_INC_216 217 -#define UTIL_INC_217 218 -#define UTIL_INC_218 219 -#define UTIL_INC_219 220 -#define UTIL_INC_220 221 -#define UTIL_INC_221 222 -#define UTIL_INC_222 223 -#define UTIL_INC_223 224 -#define UTIL_INC_224 225 -#define UTIL_INC_225 226 -#define UTIL_INC_226 227 -#define UTIL_INC_227 228 -#define UTIL_INC_228 229 -#define UTIL_INC_229 230 -#define UTIL_INC_230 231 -#define UTIL_INC_231 232 -#define UTIL_INC_232 233 -#define UTIL_INC_233 234 -#define UTIL_INC_234 235 -#define UTIL_INC_235 236 -#define UTIL_INC_236 237 -#define UTIL_INC_237 238 -#define UTIL_INC_238 239 -#define UTIL_INC_239 240 -#define UTIL_INC_240 241 -#define UTIL_INC_241 242 -#define UTIL_INC_242 243 -#define UTIL_INC_243 244 -#define UTIL_INC_244 245 -#define UTIL_INC_245 246 -#define UTIL_INC_246 247 -#define UTIL_INC_247 248 -#define UTIL_INC_248 249 -#define UTIL_INC_249 250 -#define UTIL_INC_250 251 -#define UTIL_INC_251 252 -#define UTIL_INC_252 253 -#define UTIL_INC_253 254 -#define UTIL_INC_254 255 -#define UTIL_INC_255 256 +/* Used by UTIL_INC */ +#include "util_internal_util_inc.h" -#define UTIL_DEC_0 0 -#define UTIL_DEC_1 0 -#define UTIL_DEC_2 1 -#define UTIL_DEC_3 2 -#define UTIL_DEC_4 3 -#define UTIL_DEC_5 4 -#define UTIL_DEC_6 5 -#define UTIL_DEC_7 6 -#define UTIL_DEC_8 7 -#define UTIL_DEC_9 8 -#define UTIL_DEC_10 9 -#define UTIL_DEC_11 10 -#define UTIL_DEC_12 11 -#define UTIL_DEC_13 12 -#define UTIL_DEC_14 13 -#define UTIL_DEC_15 14 -#define UTIL_DEC_16 15 -#define UTIL_DEC_17 16 -#define UTIL_DEC_18 17 -#define UTIL_DEC_19 18 -#define UTIL_DEC_20 19 -#define UTIL_DEC_21 20 -#define UTIL_DEC_22 21 -#define UTIL_DEC_23 22 -#define UTIL_DEC_24 23 -#define UTIL_DEC_25 24 -#define UTIL_DEC_26 25 -#define UTIL_DEC_27 26 -#define UTIL_DEC_28 27 -#define UTIL_DEC_29 28 -#define UTIL_DEC_30 29 -#define UTIL_DEC_31 30 -#define UTIL_DEC_32 31 -#define UTIL_DEC_33 32 -#define UTIL_DEC_34 33 -#define UTIL_DEC_35 34 -#define UTIL_DEC_36 35 -#define UTIL_DEC_37 36 -#define UTIL_DEC_38 37 -#define UTIL_DEC_39 38 -#define UTIL_DEC_40 39 -#define UTIL_DEC_41 40 -#define UTIL_DEC_42 41 -#define UTIL_DEC_43 42 -#define UTIL_DEC_44 43 -#define UTIL_DEC_45 44 -#define UTIL_DEC_46 45 -#define UTIL_DEC_47 46 -#define UTIL_DEC_48 47 -#define UTIL_DEC_49 48 -#define UTIL_DEC_50 49 -#define UTIL_DEC_51 50 -#define UTIL_DEC_52 51 -#define UTIL_DEC_53 52 -#define UTIL_DEC_54 53 -#define UTIL_DEC_55 54 -#define UTIL_DEC_56 55 -#define UTIL_DEC_57 56 -#define UTIL_DEC_58 57 -#define UTIL_DEC_59 58 -#define UTIL_DEC_60 59 -#define UTIL_DEC_61 60 -#define UTIL_DEC_62 61 -#define UTIL_DEC_63 62 -#define UTIL_DEC_64 63 -#define UTIL_DEC_65 64 -#define UTIL_DEC_66 65 -#define UTIL_DEC_67 66 -#define UTIL_DEC_68 67 -#define UTIL_DEC_69 68 -#define UTIL_DEC_70 69 -#define UTIL_DEC_71 70 -#define UTIL_DEC_72 71 -#define UTIL_DEC_73 72 -#define UTIL_DEC_74 73 -#define UTIL_DEC_75 74 -#define UTIL_DEC_76 75 -#define UTIL_DEC_77 76 -#define UTIL_DEC_78 77 -#define UTIL_DEC_79 78 -#define UTIL_DEC_80 79 -#define UTIL_DEC_81 80 -#define UTIL_DEC_82 81 -#define UTIL_DEC_83 82 -#define UTIL_DEC_84 83 -#define UTIL_DEC_85 84 -#define UTIL_DEC_86 85 -#define UTIL_DEC_87 86 -#define UTIL_DEC_88 87 -#define UTIL_DEC_89 88 -#define UTIL_DEC_90 89 -#define UTIL_DEC_91 90 -#define UTIL_DEC_92 91 -#define UTIL_DEC_93 92 -#define UTIL_DEC_94 93 -#define UTIL_DEC_95 94 -#define UTIL_DEC_96 95 -#define UTIL_DEC_97 96 -#define UTIL_DEC_98 97 -#define UTIL_DEC_99 98 -#define UTIL_DEC_100 99 -#define UTIL_DEC_101 100 -#define UTIL_DEC_102 101 -#define UTIL_DEC_103 102 -#define UTIL_DEC_104 103 -#define UTIL_DEC_105 104 -#define UTIL_DEC_106 105 -#define UTIL_DEC_107 106 -#define UTIL_DEC_108 107 -#define UTIL_DEC_109 108 -#define UTIL_DEC_110 109 -#define UTIL_DEC_111 110 -#define UTIL_DEC_112 111 -#define UTIL_DEC_113 112 -#define UTIL_DEC_114 113 -#define UTIL_DEC_115 114 -#define UTIL_DEC_116 115 -#define UTIL_DEC_117 116 -#define UTIL_DEC_118 117 -#define UTIL_DEC_119 118 -#define UTIL_DEC_120 119 -#define UTIL_DEC_121 120 -#define UTIL_DEC_122 121 -#define UTIL_DEC_123 122 -#define UTIL_DEC_124 123 -#define UTIL_DEC_125 124 -#define UTIL_DEC_126 125 -#define UTIL_DEC_127 126 -#define UTIL_DEC_128 127 -#define UTIL_DEC_129 128 -#define UTIL_DEC_130 129 -#define UTIL_DEC_131 130 -#define UTIL_DEC_132 131 -#define UTIL_DEC_133 132 -#define UTIL_DEC_134 133 -#define UTIL_DEC_135 134 -#define UTIL_DEC_136 135 -#define UTIL_DEC_137 136 -#define UTIL_DEC_138 137 -#define UTIL_DEC_139 138 -#define UTIL_DEC_140 139 -#define UTIL_DEC_141 140 -#define UTIL_DEC_142 141 -#define UTIL_DEC_143 142 -#define UTIL_DEC_144 143 -#define UTIL_DEC_145 144 -#define UTIL_DEC_146 145 -#define UTIL_DEC_147 146 -#define UTIL_DEC_148 147 -#define UTIL_DEC_149 148 -#define UTIL_DEC_150 149 -#define UTIL_DEC_151 150 -#define UTIL_DEC_152 151 -#define UTIL_DEC_153 152 -#define UTIL_DEC_154 153 -#define UTIL_DEC_155 154 -#define UTIL_DEC_156 155 -#define UTIL_DEC_157 156 -#define UTIL_DEC_158 157 -#define UTIL_DEC_159 158 -#define UTIL_DEC_160 159 -#define UTIL_DEC_161 160 -#define UTIL_DEC_162 161 -#define UTIL_DEC_163 162 -#define UTIL_DEC_164 163 -#define UTIL_DEC_165 164 -#define UTIL_DEC_166 165 -#define UTIL_DEC_167 166 -#define UTIL_DEC_168 167 -#define UTIL_DEC_169 168 -#define UTIL_DEC_170 169 -#define UTIL_DEC_171 170 -#define UTIL_DEC_172 171 -#define UTIL_DEC_173 172 -#define UTIL_DEC_174 173 -#define UTIL_DEC_175 174 -#define UTIL_DEC_176 175 -#define UTIL_DEC_177 176 -#define UTIL_DEC_178 177 -#define UTIL_DEC_179 178 -#define UTIL_DEC_180 179 -#define UTIL_DEC_181 180 -#define UTIL_DEC_182 181 -#define UTIL_DEC_183 182 -#define UTIL_DEC_184 183 -#define UTIL_DEC_185 184 -#define UTIL_DEC_186 185 -#define UTIL_DEC_187 186 -#define UTIL_DEC_188 187 -#define UTIL_DEC_189 188 -#define UTIL_DEC_190 189 -#define UTIL_DEC_191 190 -#define UTIL_DEC_192 191 -#define UTIL_DEC_193 192 -#define UTIL_DEC_194 193 -#define UTIL_DEC_195 194 -#define UTIL_DEC_196 195 -#define UTIL_DEC_197 196 -#define UTIL_DEC_198 197 -#define UTIL_DEC_199 198 -#define UTIL_DEC_200 199 -#define UTIL_DEC_201 200 -#define UTIL_DEC_202 201 -#define UTIL_DEC_203 202 -#define UTIL_DEC_204 203 -#define UTIL_DEC_205 204 -#define UTIL_DEC_206 205 -#define UTIL_DEC_207 206 -#define UTIL_DEC_208 207 -#define UTIL_DEC_209 208 -#define UTIL_DEC_210 209 -#define UTIL_DEC_211 210 -#define UTIL_DEC_212 211 -#define UTIL_DEC_213 212 -#define UTIL_DEC_214 213 -#define UTIL_DEC_215 214 -#define UTIL_DEC_216 215 -#define UTIL_DEC_217 216 -#define UTIL_DEC_218 217 -#define UTIL_DEC_219 218 -#define UTIL_DEC_220 219 -#define UTIL_DEC_221 220 -#define UTIL_DEC_222 221 -#define UTIL_DEC_223 222 -#define UTIL_DEC_224 223 -#define UTIL_DEC_225 224 -#define UTIL_DEC_226 225 -#define UTIL_DEC_227 226 -#define UTIL_DEC_228 227 -#define UTIL_DEC_229 228 -#define UTIL_DEC_230 229 -#define UTIL_DEC_231 230 -#define UTIL_DEC_232 231 -#define UTIL_DEC_233 232 -#define UTIL_DEC_234 233 -#define UTIL_DEC_235 234 -#define UTIL_DEC_236 235 -#define UTIL_DEC_237 236 -#define UTIL_DEC_238 237 -#define UTIL_DEC_239 238 -#define UTIL_DEC_240 239 -#define UTIL_DEC_241 240 -#define UTIL_DEC_242 241 -#define UTIL_DEC_243 242 -#define UTIL_DEC_244 243 -#define UTIL_DEC_245 244 -#define UTIL_DEC_246 245 -#define UTIL_DEC_247 246 -#define UTIL_DEC_248 247 -#define UTIL_DEC_249 248 -#define UTIL_DEC_250 249 -#define UTIL_DEC_251 250 -#define UTIL_DEC_252 251 -#define UTIL_DEC_253 252 -#define UTIL_DEC_254 253 -#define UTIL_DEC_255 254 +/* Used by UTIL_DEC */ +#include "util_internal_util_dec.h" -#define UTIL_X2_0 0 -#define UTIL_X2_1 2 -#define UTIL_X2_2 4 -#define UTIL_X2_3 6 -#define UTIL_X2_4 8 -#define UTIL_X2_5 10 -#define UTIL_X2_6 12 -#define UTIL_X2_7 14 -#define UTIL_X2_8 16 -#define UTIL_X2_9 18 -#define UTIL_X2_10 20 -#define UTIL_X2_11 22 -#define UTIL_X2_12 24 -#define UTIL_X2_13 26 -#define UTIL_X2_14 28 -#define UTIL_X2_15 30 -#define UTIL_X2_16 32 -#define UTIL_X2_17 34 -#define UTIL_X2_18 36 -#define UTIL_X2_19 38 -#define UTIL_X2_20 40 -#define UTIL_X2_21 42 -#define UTIL_X2_22 44 -#define UTIL_X2_23 46 -#define UTIL_X2_24 48 -#define UTIL_X2_25 50 -#define UTIL_X2_26 52 -#define UTIL_X2_27 54 -#define UTIL_X2_28 56 -#define UTIL_X2_29 58 -#define UTIL_X2_30 60 -#define UTIL_X2_31 62 -#define UTIL_X2_32 64 -#define UTIL_X2_33 66 -#define UTIL_X2_34 68 -#define UTIL_X2_35 70 -#define UTIL_X2_36 72 -#define UTIL_X2_37 74 -#define UTIL_X2_38 76 -#define UTIL_X2_39 78 -#define UTIL_X2_40 80 -#define UTIL_X2_41 82 -#define UTIL_X2_42 84 -#define UTIL_X2_43 86 -#define UTIL_X2_44 88 -#define UTIL_X2_45 90 -#define UTIL_X2_46 92 -#define UTIL_X2_47 94 -#define UTIL_X2_48 96 -#define UTIL_X2_49 98 -#define UTIL_X2_50 100 -#define UTIL_X2_51 102 -#define UTIL_X2_52 104 -#define UTIL_X2_53 106 -#define UTIL_X2_54 108 -#define UTIL_X2_55 110 -#define UTIL_X2_56 112 -#define UTIL_X2_57 114 -#define UTIL_X2_58 116 -#define UTIL_X2_59 118 -#define UTIL_X2_60 120 -#define UTIL_X2_61 122 -#define UTIL_X2_62 124 -#define UTIL_X2_63 126 -#define UTIL_X2_64 128 -#define UTIL_X2_65 130 -#define UTIL_X2_66 132 -#define UTIL_X2_67 134 -#define UTIL_X2_68 136 -#define UTIL_X2_69 138 -#define UTIL_X2_70 140 -#define UTIL_X2_71 142 -#define UTIL_X2_72 144 -#define UTIL_X2_73 146 -#define UTIL_X2_74 148 -#define UTIL_X2_75 150 -#define UTIL_X2_76 152 -#define UTIL_X2_77 154 -#define UTIL_X2_78 156 -#define UTIL_X2_79 158 -#define UTIL_X2_80 160 -#define UTIL_X2_81 162 -#define UTIL_X2_82 164 -#define UTIL_X2_83 166 -#define UTIL_X2_84 168 -#define UTIL_X2_85 170 -#define UTIL_X2_86 172 -#define UTIL_X2_87 174 -#define UTIL_X2_88 176 -#define UTIL_X2_89 178 -#define UTIL_X2_90 180 -#define UTIL_X2_91 182 -#define UTIL_X2_92 184 -#define UTIL_X2_93 186 -#define UTIL_X2_94 188 -#define UTIL_X2_95 190 -#define UTIL_X2_96 192 -#define UTIL_X2_97 194 -#define UTIL_X2_98 196 -#define UTIL_X2_99 198 -#define UTIL_X2_100 200 -#define UTIL_X2_101 202 -#define UTIL_X2_102 204 -#define UTIL_X2_103 206 -#define UTIL_X2_104 208 -#define UTIL_X2_105 210 -#define UTIL_X2_106 212 -#define UTIL_X2_107 214 -#define UTIL_X2_108 216 -#define UTIL_X2_109 218 -#define UTIL_X2_110 220 -#define UTIL_X2_111 222 -#define UTIL_X2_112 224 -#define UTIL_X2_113 226 -#define UTIL_X2_114 228 -#define UTIL_X2_115 230 -#define UTIL_X2_116 232 -#define UTIL_X2_117 234 -#define UTIL_X2_118 236 -#define UTIL_X2_119 238 -#define UTIL_X2_120 240 -#define UTIL_X2_121 242 -#define UTIL_X2_122 244 -#define UTIL_X2_123 246 -#define UTIL_X2_124 248 -#define UTIL_X2_125 250 -#define UTIL_X2_126 252 -#define UTIL_X2_127 254 -#define UTIL_X2_128 256 -#define UTIL_X2_129 258 -#define UTIL_X2_130 260 -#define UTIL_X2_131 262 -#define UTIL_X2_132 264 -#define UTIL_X2_133 266 -#define UTIL_X2_134 268 -#define UTIL_X2_135 270 -#define UTIL_X2_136 272 -#define UTIL_X2_137 274 -#define UTIL_X2_138 276 -#define UTIL_X2_139 278 -#define UTIL_X2_140 280 -#define UTIL_X2_141 282 -#define UTIL_X2_142 284 -#define UTIL_X2_143 286 -#define UTIL_X2_144 288 -#define UTIL_X2_145 290 -#define UTIL_X2_146 292 -#define UTIL_X2_147 294 -#define UTIL_X2_148 296 -#define UTIL_X2_149 298 -#define UTIL_X2_150 300 -#define UTIL_X2_151 302 -#define UTIL_X2_152 304 -#define UTIL_X2_153 306 -#define UTIL_X2_154 308 -#define UTIL_X2_155 310 -#define UTIL_X2_156 312 -#define UTIL_X2_157 314 -#define UTIL_X2_158 316 -#define UTIL_X2_159 318 -#define UTIL_X2_160 320 -#define UTIL_X2_161 322 -#define UTIL_X2_162 324 -#define UTIL_X2_163 326 -#define UTIL_X2_164 328 -#define UTIL_X2_165 330 -#define UTIL_X2_166 332 -#define UTIL_X2_167 334 -#define UTIL_X2_168 336 -#define UTIL_X2_169 338 -#define UTIL_X2_170 340 -#define UTIL_X2_171 342 -#define UTIL_X2_172 344 -#define UTIL_X2_173 346 -#define UTIL_X2_174 348 -#define UTIL_X2_175 350 -#define UTIL_X2_176 352 -#define UTIL_X2_177 354 -#define UTIL_X2_178 356 -#define UTIL_X2_179 358 -#define UTIL_X2_180 360 -#define UTIL_X2_181 362 -#define UTIL_X2_182 364 -#define UTIL_X2_183 366 -#define UTIL_X2_184 368 -#define UTIL_X2_185 370 -#define UTIL_X2_186 372 -#define UTIL_X2_187 374 -#define UTIL_X2_188 376 -#define UTIL_X2_189 378 -#define UTIL_X2_190 380 -#define UTIL_X2_191 382 -#define UTIL_X2_192 384 -#define UTIL_X2_193 386 -#define UTIL_X2_194 388 -#define UTIL_X2_195 390 -#define UTIL_X2_196 392 -#define UTIL_X2_197 394 -#define UTIL_X2_198 396 -#define UTIL_X2_199 398 -#define UTIL_X2_200 400 -#define UTIL_X2_201 402 -#define UTIL_X2_202 404 -#define UTIL_X2_203 406 -#define UTIL_X2_204 408 -#define UTIL_X2_205 410 -#define UTIL_X2_206 412 -#define UTIL_X2_207 414 -#define UTIL_X2_208 416 -#define UTIL_X2_209 418 -#define UTIL_X2_210 420 -#define UTIL_X2_211 422 -#define UTIL_X2_212 424 -#define UTIL_X2_213 426 -#define UTIL_X2_214 428 -#define UTIL_X2_215 430 -#define UTIL_X2_216 432 -#define UTIL_X2_217 434 -#define UTIL_X2_218 436 -#define UTIL_X2_219 438 -#define UTIL_X2_220 440 -#define UTIL_X2_221 442 -#define UTIL_X2_222 444 -#define UTIL_X2_223 446 -#define UTIL_X2_224 448 -#define UTIL_X2_225 450 -#define UTIL_X2_226 452 -#define UTIL_X2_227 454 -#define UTIL_X2_228 456 -#define UTIL_X2_229 458 -#define UTIL_X2_230 460 -#define UTIL_X2_231 462 -#define UTIL_X2_232 464 -#define UTIL_X2_233 466 -#define UTIL_X2_234 468 -#define UTIL_X2_235 470 -#define UTIL_X2_236 472 -#define UTIL_X2_237 474 -#define UTIL_X2_238 476 -#define UTIL_X2_239 478 -#define UTIL_X2_240 480 -#define UTIL_X2_241 482 -#define UTIL_X2_242 484 -#define UTIL_X2_243 486 -#define UTIL_X2_244 488 -#define UTIL_X2_245 490 -#define UTIL_X2_246 492 -#define UTIL_X2_247 494 -#define UTIL_X2_248 496 -#define UTIL_X2_249 498 -#define UTIL_X2_250 500 -#define UTIL_X2_251 502 -#define UTIL_X2_252 504 -#define UTIL_X2_253 506 -#define UTIL_X2_254 508 -#define UTIL_X2_255 510 +/* Used by UTIL_X2 */ +#include "util_internal_util_x2.h" #endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_ */ diff --git a/include/zephyr/sys/util_internal_is_eq.h b/include/zephyr/sys/util_internal_is_eq.h new file mode 100644 index 00000000000..0734cf3506a --- /dev/null +++ b/include/zephyr/sys/util_internal_is_eq.h @@ -0,0 +1,4114 @@ +/* + * Copyright (c) 2011-2014, Wind River Systems, Inc. + * Copyright (c) 2020, Nordic Semiconductor ASA + * Copyright (c) 2023, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_ +#error "This header should not be used directly, please include util_internal.h instead" +#endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_ */ + +#ifndef ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_IS_EQ_H_ +#define ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_IS_EQ_H_ + +#define Z_IS_0_EQ_0(...) \, +#define Z_IS_1_EQ_1(...) \, +#define Z_IS_2_EQ_2(...) \, +#define Z_IS_3_EQ_3(...) \, +#define Z_IS_4_EQ_4(...) \, +#define Z_IS_5_EQ_5(...) \, +#define Z_IS_6_EQ_6(...) \, +#define Z_IS_7_EQ_7(...) \, +#define Z_IS_8_EQ_8(...) \, +#define Z_IS_9_EQ_9(...) \, +#define Z_IS_10_EQ_10(...) \, +#define Z_IS_11_EQ_11(...) \, +#define Z_IS_12_EQ_12(...) \, +#define Z_IS_13_EQ_13(...) \, +#define Z_IS_14_EQ_14(...) \, +#define Z_IS_15_EQ_15(...) \, +#define Z_IS_16_EQ_16(...) \, +#define Z_IS_17_EQ_17(...) \, +#define Z_IS_18_EQ_18(...) \, +#define Z_IS_19_EQ_19(...) \, +#define Z_IS_20_EQ_20(...) \, +#define Z_IS_21_EQ_21(...) \, +#define Z_IS_22_EQ_22(...) \, +#define Z_IS_23_EQ_23(...) \, +#define Z_IS_24_EQ_24(...) \, +#define Z_IS_25_EQ_25(...) \, +#define Z_IS_26_EQ_26(...) \, +#define Z_IS_27_EQ_27(...) \, +#define Z_IS_28_EQ_28(...) \, +#define Z_IS_29_EQ_29(...) \, +#define Z_IS_30_EQ_30(...) \, +#define Z_IS_31_EQ_31(...) \, +#define Z_IS_32_EQ_32(...) \, +#define Z_IS_33_EQ_33(...) \, +#define Z_IS_34_EQ_34(...) \, +#define Z_IS_35_EQ_35(...) \, +#define Z_IS_36_EQ_36(...) \, +#define Z_IS_37_EQ_37(...) \, +#define Z_IS_38_EQ_38(...) \, +#define Z_IS_39_EQ_39(...) \, +#define Z_IS_40_EQ_40(...) \, +#define Z_IS_41_EQ_41(...) \, +#define Z_IS_42_EQ_42(...) \, +#define Z_IS_43_EQ_43(...) \, +#define Z_IS_44_EQ_44(...) \, +#define Z_IS_45_EQ_45(...) \, +#define Z_IS_46_EQ_46(...) \, +#define Z_IS_47_EQ_47(...) \, +#define Z_IS_48_EQ_48(...) \, +#define Z_IS_49_EQ_49(...) \, +#define Z_IS_50_EQ_50(...) \, +#define Z_IS_51_EQ_51(...) \, +#define Z_IS_52_EQ_52(...) \, +#define Z_IS_53_EQ_53(...) \, +#define Z_IS_54_EQ_54(...) \, +#define Z_IS_55_EQ_55(...) \, +#define Z_IS_56_EQ_56(...) \, +#define Z_IS_57_EQ_57(...) \, +#define Z_IS_58_EQ_58(...) \, +#define Z_IS_59_EQ_59(...) \, +#define Z_IS_60_EQ_60(...) \, +#define Z_IS_61_EQ_61(...) \, +#define Z_IS_62_EQ_62(...) \, +#define Z_IS_63_EQ_63(...) \, +#define Z_IS_64_EQ_64(...) \, +#define Z_IS_65_EQ_65(...) \, +#define Z_IS_66_EQ_66(...) \, +#define Z_IS_67_EQ_67(...) \, +#define Z_IS_68_EQ_68(...) \, +#define Z_IS_69_EQ_69(...) \, +#define Z_IS_70_EQ_70(...) \, +#define Z_IS_71_EQ_71(...) \, +#define Z_IS_72_EQ_72(...) \, +#define Z_IS_73_EQ_73(...) \, +#define Z_IS_74_EQ_74(...) \, +#define Z_IS_75_EQ_75(...) \, +#define Z_IS_76_EQ_76(...) \, +#define Z_IS_77_EQ_77(...) \, +#define Z_IS_78_EQ_78(...) \, +#define Z_IS_79_EQ_79(...) \, +#define Z_IS_80_EQ_80(...) \, +#define Z_IS_81_EQ_81(...) \, +#define Z_IS_82_EQ_82(...) \, +#define Z_IS_83_EQ_83(...) \, +#define Z_IS_84_EQ_84(...) \, +#define Z_IS_85_EQ_85(...) \, +#define Z_IS_86_EQ_86(...) \, +#define Z_IS_87_EQ_87(...) \, +#define Z_IS_88_EQ_88(...) \, +#define Z_IS_89_EQ_89(...) \, +#define Z_IS_90_EQ_90(...) \, +#define Z_IS_91_EQ_91(...) \, +#define Z_IS_92_EQ_92(...) \, +#define Z_IS_93_EQ_93(...) \, +#define Z_IS_94_EQ_94(...) \, +#define Z_IS_95_EQ_95(...) \, +#define Z_IS_96_EQ_96(...) \, +#define Z_IS_97_EQ_97(...) \, +#define Z_IS_98_EQ_98(...) \, +#define Z_IS_99_EQ_99(...) \, +#define Z_IS_100_EQ_100(...) \, +#define Z_IS_101_EQ_101(...) \, +#define Z_IS_102_EQ_102(...) \, +#define Z_IS_103_EQ_103(...) \, +#define Z_IS_104_EQ_104(...) \, +#define Z_IS_105_EQ_105(...) \, +#define Z_IS_106_EQ_106(...) \, +#define Z_IS_107_EQ_107(...) \, +#define Z_IS_108_EQ_108(...) \, +#define Z_IS_109_EQ_109(...) \, +#define Z_IS_110_EQ_110(...) \, +#define Z_IS_111_EQ_111(...) \, +#define Z_IS_112_EQ_112(...) \, +#define Z_IS_113_EQ_113(...) \, +#define Z_IS_114_EQ_114(...) \, +#define Z_IS_115_EQ_115(...) \, +#define Z_IS_116_EQ_116(...) \, +#define Z_IS_117_EQ_117(...) \, +#define Z_IS_118_EQ_118(...) \, +#define Z_IS_119_EQ_119(...) \, +#define Z_IS_120_EQ_120(...) \, +#define Z_IS_121_EQ_121(...) \, +#define Z_IS_122_EQ_122(...) \, +#define Z_IS_123_EQ_123(...) \, +#define Z_IS_124_EQ_124(...) \, +#define Z_IS_125_EQ_125(...) \, +#define Z_IS_126_EQ_126(...) \, +#define Z_IS_127_EQ_127(...) \, +#define Z_IS_128_EQ_128(...) \, +#define Z_IS_129_EQ_129(...) \, +#define Z_IS_130_EQ_130(...) \, +#define Z_IS_131_EQ_131(...) \, +#define Z_IS_132_EQ_132(...) \, +#define Z_IS_133_EQ_133(...) \, +#define Z_IS_134_EQ_134(...) \, +#define Z_IS_135_EQ_135(...) \, +#define Z_IS_136_EQ_136(...) \, +#define Z_IS_137_EQ_137(...) \, +#define Z_IS_138_EQ_138(...) \, +#define Z_IS_139_EQ_139(...) \, +#define Z_IS_140_EQ_140(...) \, +#define Z_IS_141_EQ_141(...) \, +#define Z_IS_142_EQ_142(...) \, +#define Z_IS_143_EQ_143(...) \, +#define Z_IS_144_EQ_144(...) \, +#define Z_IS_145_EQ_145(...) \, +#define Z_IS_146_EQ_146(...) \, +#define Z_IS_147_EQ_147(...) \, +#define Z_IS_148_EQ_148(...) \, +#define Z_IS_149_EQ_149(...) \, +#define Z_IS_150_EQ_150(...) \, +#define Z_IS_151_EQ_151(...) \, +#define Z_IS_152_EQ_152(...) \, +#define Z_IS_153_EQ_153(...) \, +#define Z_IS_154_EQ_154(...) \, +#define Z_IS_155_EQ_155(...) \, +#define Z_IS_156_EQ_156(...) \, +#define Z_IS_157_EQ_157(...) \, +#define Z_IS_158_EQ_158(...) \, +#define Z_IS_159_EQ_159(...) \, +#define Z_IS_160_EQ_160(...) \, +#define Z_IS_161_EQ_161(...) \, +#define Z_IS_162_EQ_162(...) \, +#define Z_IS_163_EQ_163(...) \, +#define Z_IS_164_EQ_164(...) \, +#define Z_IS_165_EQ_165(...) \, +#define Z_IS_166_EQ_166(...) \, +#define Z_IS_167_EQ_167(...) \, +#define Z_IS_168_EQ_168(...) \, +#define Z_IS_169_EQ_169(...) \, +#define Z_IS_170_EQ_170(...) \, +#define Z_IS_171_EQ_171(...) \, +#define Z_IS_172_EQ_172(...) \, +#define Z_IS_173_EQ_173(...) \, +#define Z_IS_174_EQ_174(...) \, +#define Z_IS_175_EQ_175(...) \, +#define Z_IS_176_EQ_176(...) \, +#define Z_IS_177_EQ_177(...) \, +#define Z_IS_178_EQ_178(...) \, +#define Z_IS_179_EQ_179(...) \, +#define Z_IS_180_EQ_180(...) \, +#define Z_IS_181_EQ_181(...) \, +#define Z_IS_182_EQ_182(...) \, +#define Z_IS_183_EQ_183(...) \, +#define Z_IS_184_EQ_184(...) \, +#define Z_IS_185_EQ_185(...) \, +#define Z_IS_186_EQ_186(...) \, +#define Z_IS_187_EQ_187(...) \, +#define Z_IS_188_EQ_188(...) \, +#define Z_IS_189_EQ_189(...) \, +#define Z_IS_190_EQ_190(...) \, +#define Z_IS_191_EQ_191(...) \, +#define Z_IS_192_EQ_192(...) \, +#define Z_IS_193_EQ_193(...) \, +#define Z_IS_194_EQ_194(...) \, +#define Z_IS_195_EQ_195(...) \, +#define Z_IS_196_EQ_196(...) \, +#define Z_IS_197_EQ_197(...) \, +#define Z_IS_198_EQ_198(...) \, +#define Z_IS_199_EQ_199(...) \, +#define Z_IS_200_EQ_200(...) \, +#define Z_IS_201_EQ_201(...) \, +#define Z_IS_202_EQ_202(...) \, +#define Z_IS_203_EQ_203(...) \, +#define Z_IS_204_EQ_204(...) \, +#define Z_IS_205_EQ_205(...) \, +#define Z_IS_206_EQ_206(...) \, +#define Z_IS_207_EQ_207(...) \, +#define Z_IS_208_EQ_208(...) \, +#define Z_IS_209_EQ_209(...) \, +#define Z_IS_210_EQ_210(...) \, +#define Z_IS_211_EQ_211(...) \, +#define Z_IS_212_EQ_212(...) \, +#define Z_IS_213_EQ_213(...) \, +#define Z_IS_214_EQ_214(...) \, +#define Z_IS_215_EQ_215(...) \, +#define Z_IS_216_EQ_216(...) \, +#define Z_IS_217_EQ_217(...) \, +#define Z_IS_218_EQ_218(...) \, +#define Z_IS_219_EQ_219(...) \, +#define Z_IS_220_EQ_220(...) \, +#define Z_IS_221_EQ_221(...) \, +#define Z_IS_222_EQ_222(...) \, +#define Z_IS_223_EQ_223(...) \, +#define Z_IS_224_EQ_224(...) \, +#define Z_IS_225_EQ_225(...) \, +#define Z_IS_226_EQ_226(...) \, +#define Z_IS_227_EQ_227(...) \, +#define Z_IS_228_EQ_228(...) \, +#define Z_IS_229_EQ_229(...) \, +#define Z_IS_230_EQ_230(...) \, +#define Z_IS_231_EQ_231(...) \, +#define Z_IS_232_EQ_232(...) \, +#define Z_IS_233_EQ_233(...) \, +#define Z_IS_234_EQ_234(...) \, +#define Z_IS_235_EQ_235(...) \, +#define Z_IS_236_EQ_236(...) \, +#define Z_IS_237_EQ_237(...) \, +#define Z_IS_238_EQ_238(...) \, +#define Z_IS_239_EQ_239(...) \, +#define Z_IS_240_EQ_240(...) \, +#define Z_IS_241_EQ_241(...) \, +#define Z_IS_242_EQ_242(...) \, +#define Z_IS_243_EQ_243(...) \, +#define Z_IS_244_EQ_244(...) \, +#define Z_IS_245_EQ_245(...) \, +#define Z_IS_246_EQ_246(...) \, +#define Z_IS_247_EQ_247(...) \, +#define Z_IS_248_EQ_248(...) \, +#define Z_IS_249_EQ_249(...) \, +#define Z_IS_250_EQ_250(...) \, +#define Z_IS_251_EQ_251(...) \, +#define Z_IS_252_EQ_252(...) \, +#define Z_IS_253_EQ_253(...) \, +#define Z_IS_254_EQ_254(...) \, +#define Z_IS_255_EQ_255(...) \, +#define Z_IS_256_EQ_256(...) \, +#define Z_IS_257_EQ_257(...) \, +#define Z_IS_258_EQ_258(...) \, +#define Z_IS_259_EQ_259(...) \, +#define Z_IS_260_EQ_260(...) \, +#define Z_IS_261_EQ_261(...) \, +#define Z_IS_262_EQ_262(...) \, +#define Z_IS_263_EQ_263(...) \, +#define Z_IS_264_EQ_264(...) \, +#define Z_IS_265_EQ_265(...) \, +#define Z_IS_266_EQ_266(...) \, +#define Z_IS_267_EQ_267(...) \, +#define Z_IS_268_EQ_268(...) \, +#define Z_IS_269_EQ_269(...) \, +#define Z_IS_270_EQ_270(...) \, +#define Z_IS_271_EQ_271(...) \, +#define Z_IS_272_EQ_272(...) \, +#define Z_IS_273_EQ_273(...) \, +#define Z_IS_274_EQ_274(...) \, +#define Z_IS_275_EQ_275(...) \, +#define Z_IS_276_EQ_276(...) \, +#define Z_IS_277_EQ_277(...) \, +#define Z_IS_278_EQ_278(...) \, +#define Z_IS_279_EQ_279(...) \, +#define Z_IS_280_EQ_280(...) \, +#define Z_IS_281_EQ_281(...) \, +#define Z_IS_282_EQ_282(...) \, +#define Z_IS_283_EQ_283(...) \, +#define Z_IS_284_EQ_284(...) \, +#define Z_IS_285_EQ_285(...) \, +#define Z_IS_286_EQ_286(...) \, +#define Z_IS_287_EQ_287(...) \, +#define Z_IS_288_EQ_288(...) \, +#define Z_IS_289_EQ_289(...) \, +#define Z_IS_290_EQ_290(...) \, +#define Z_IS_291_EQ_291(...) \, +#define Z_IS_292_EQ_292(...) \, +#define Z_IS_293_EQ_293(...) \, +#define Z_IS_294_EQ_294(...) \, +#define Z_IS_295_EQ_295(...) \, +#define Z_IS_296_EQ_296(...) \, +#define Z_IS_297_EQ_297(...) \, +#define Z_IS_298_EQ_298(...) \, +#define Z_IS_299_EQ_299(...) \, +#define Z_IS_300_EQ_300(...) \, +#define Z_IS_301_EQ_301(...) \, +#define Z_IS_302_EQ_302(...) \, +#define Z_IS_303_EQ_303(...) \, +#define Z_IS_304_EQ_304(...) \, +#define Z_IS_305_EQ_305(...) \, +#define Z_IS_306_EQ_306(...) \, +#define Z_IS_307_EQ_307(...) \, +#define Z_IS_308_EQ_308(...) \, +#define Z_IS_309_EQ_309(...) \, +#define Z_IS_310_EQ_310(...) \, +#define Z_IS_311_EQ_311(...) \, +#define Z_IS_312_EQ_312(...) \, +#define Z_IS_313_EQ_313(...) \, +#define Z_IS_314_EQ_314(...) \, +#define Z_IS_315_EQ_315(...) \, +#define Z_IS_316_EQ_316(...) \, +#define Z_IS_317_EQ_317(...) \, +#define Z_IS_318_EQ_318(...) \, +#define Z_IS_319_EQ_319(...) \, +#define Z_IS_320_EQ_320(...) \, +#define Z_IS_321_EQ_321(...) \, +#define Z_IS_322_EQ_322(...) \, +#define Z_IS_323_EQ_323(...) \, +#define Z_IS_324_EQ_324(...) \, +#define Z_IS_325_EQ_325(...) \, +#define Z_IS_326_EQ_326(...) \, +#define Z_IS_327_EQ_327(...) \, +#define Z_IS_328_EQ_328(...) \, +#define Z_IS_329_EQ_329(...) \, +#define Z_IS_330_EQ_330(...) \, +#define Z_IS_331_EQ_331(...) \, +#define Z_IS_332_EQ_332(...) \, +#define Z_IS_333_EQ_333(...) \, +#define Z_IS_334_EQ_334(...) \, +#define Z_IS_335_EQ_335(...) \, +#define Z_IS_336_EQ_336(...) \, +#define Z_IS_337_EQ_337(...) \, +#define Z_IS_338_EQ_338(...) \, +#define Z_IS_339_EQ_339(...) \, +#define Z_IS_340_EQ_340(...) \, +#define Z_IS_341_EQ_341(...) \, +#define Z_IS_342_EQ_342(...) \, +#define Z_IS_343_EQ_343(...) \, +#define Z_IS_344_EQ_344(...) \, +#define Z_IS_345_EQ_345(...) \, +#define Z_IS_346_EQ_346(...) \, +#define Z_IS_347_EQ_347(...) \, +#define Z_IS_348_EQ_348(...) \, +#define Z_IS_349_EQ_349(...) \, +#define Z_IS_350_EQ_350(...) \, +#define Z_IS_351_EQ_351(...) \, +#define Z_IS_352_EQ_352(...) \, +#define Z_IS_353_EQ_353(...) \, +#define Z_IS_354_EQ_354(...) \, +#define Z_IS_355_EQ_355(...) \, +#define Z_IS_356_EQ_356(...) \, +#define Z_IS_357_EQ_357(...) \, +#define Z_IS_358_EQ_358(...) \, +#define Z_IS_359_EQ_359(...) \, +#define Z_IS_360_EQ_360(...) \, +#define Z_IS_361_EQ_361(...) \, +#define Z_IS_362_EQ_362(...) \, +#define Z_IS_363_EQ_363(...) \, +#define Z_IS_364_EQ_364(...) \, +#define Z_IS_365_EQ_365(...) \, +#define Z_IS_366_EQ_366(...) \, +#define Z_IS_367_EQ_367(...) \, +#define Z_IS_368_EQ_368(...) \, +#define Z_IS_369_EQ_369(...) \, +#define Z_IS_370_EQ_370(...) \, +#define Z_IS_371_EQ_371(...) \, +#define Z_IS_372_EQ_372(...) \, +#define Z_IS_373_EQ_373(...) \, +#define Z_IS_374_EQ_374(...) \, +#define Z_IS_375_EQ_375(...) \, +#define Z_IS_376_EQ_376(...) \, +#define Z_IS_377_EQ_377(...) \, +#define Z_IS_378_EQ_378(...) \, +#define Z_IS_379_EQ_379(...) \, +#define Z_IS_380_EQ_380(...) \, +#define Z_IS_381_EQ_381(...) \, +#define Z_IS_382_EQ_382(...) \, +#define Z_IS_383_EQ_383(...) \, +#define Z_IS_384_EQ_384(...) \, +#define Z_IS_385_EQ_385(...) \, +#define Z_IS_386_EQ_386(...) \, +#define Z_IS_387_EQ_387(...) \, +#define Z_IS_388_EQ_388(...) \, +#define Z_IS_389_EQ_389(...) \, +#define Z_IS_390_EQ_390(...) \, +#define Z_IS_391_EQ_391(...) \, +#define Z_IS_392_EQ_392(...) \, +#define Z_IS_393_EQ_393(...) \, +#define Z_IS_394_EQ_394(...) \, +#define Z_IS_395_EQ_395(...) \, +#define Z_IS_396_EQ_396(...) \, +#define Z_IS_397_EQ_397(...) \, +#define Z_IS_398_EQ_398(...) \, +#define Z_IS_399_EQ_399(...) \, +#define Z_IS_400_EQ_400(...) \, +#define Z_IS_401_EQ_401(...) \, +#define Z_IS_402_EQ_402(...) \, +#define Z_IS_403_EQ_403(...) \, +#define Z_IS_404_EQ_404(...) \, +#define Z_IS_405_EQ_405(...) \, +#define Z_IS_406_EQ_406(...) \, +#define Z_IS_407_EQ_407(...) \, +#define Z_IS_408_EQ_408(...) \, +#define Z_IS_409_EQ_409(...) \, +#define Z_IS_410_EQ_410(...) \, +#define Z_IS_411_EQ_411(...) \, +#define Z_IS_412_EQ_412(...) \, +#define Z_IS_413_EQ_413(...) \, +#define Z_IS_414_EQ_414(...) \, +#define Z_IS_415_EQ_415(...) \, +#define Z_IS_416_EQ_416(...) \, +#define Z_IS_417_EQ_417(...) \, +#define Z_IS_418_EQ_418(...) \, +#define Z_IS_419_EQ_419(...) \, +#define Z_IS_420_EQ_420(...) \, +#define Z_IS_421_EQ_421(...) \, +#define Z_IS_422_EQ_422(...) \, +#define Z_IS_423_EQ_423(...) \, +#define Z_IS_424_EQ_424(...) \, +#define Z_IS_425_EQ_425(...) \, +#define Z_IS_426_EQ_426(...) \, +#define Z_IS_427_EQ_427(...) \, +#define Z_IS_428_EQ_428(...) \, +#define Z_IS_429_EQ_429(...) \, +#define Z_IS_430_EQ_430(...) \, +#define Z_IS_431_EQ_431(...) \, +#define Z_IS_432_EQ_432(...) \, +#define Z_IS_433_EQ_433(...) \, +#define Z_IS_434_EQ_434(...) \, +#define Z_IS_435_EQ_435(...) \, +#define Z_IS_436_EQ_436(...) \, +#define Z_IS_437_EQ_437(...) \, +#define Z_IS_438_EQ_438(...) \, +#define Z_IS_439_EQ_439(...) \, +#define Z_IS_440_EQ_440(...) \, +#define Z_IS_441_EQ_441(...) \, +#define Z_IS_442_EQ_442(...) \, +#define Z_IS_443_EQ_443(...) \, +#define Z_IS_444_EQ_444(...) \, +#define Z_IS_445_EQ_445(...) \, +#define Z_IS_446_EQ_446(...) \, +#define Z_IS_447_EQ_447(...) \, +#define Z_IS_448_EQ_448(...) \, +#define Z_IS_449_EQ_449(...) \, +#define Z_IS_450_EQ_450(...) \, +#define Z_IS_451_EQ_451(...) \, +#define Z_IS_452_EQ_452(...) \, +#define Z_IS_453_EQ_453(...) \, +#define Z_IS_454_EQ_454(...) \, +#define Z_IS_455_EQ_455(...) \, +#define Z_IS_456_EQ_456(...) \, +#define Z_IS_457_EQ_457(...) \, +#define Z_IS_458_EQ_458(...) \, +#define Z_IS_459_EQ_459(...) \, +#define Z_IS_460_EQ_460(...) \, +#define Z_IS_461_EQ_461(...) \, +#define Z_IS_462_EQ_462(...) \, +#define Z_IS_463_EQ_463(...) \, +#define Z_IS_464_EQ_464(...) \, +#define Z_IS_465_EQ_465(...) \, +#define Z_IS_466_EQ_466(...) \, +#define Z_IS_467_EQ_467(...) \, +#define Z_IS_468_EQ_468(...) \, +#define Z_IS_469_EQ_469(...) \, +#define Z_IS_470_EQ_470(...) \, +#define Z_IS_471_EQ_471(...) \, +#define Z_IS_472_EQ_472(...) \, +#define Z_IS_473_EQ_473(...) \, +#define Z_IS_474_EQ_474(...) \, +#define Z_IS_475_EQ_475(...) \, +#define Z_IS_476_EQ_476(...) \, +#define Z_IS_477_EQ_477(...) \, +#define Z_IS_478_EQ_478(...) \, +#define Z_IS_479_EQ_479(...) \, +#define Z_IS_480_EQ_480(...) \, +#define Z_IS_481_EQ_481(...) \, +#define Z_IS_482_EQ_482(...) \, +#define Z_IS_483_EQ_483(...) \, +#define Z_IS_484_EQ_484(...) \, +#define Z_IS_485_EQ_485(...) \, +#define Z_IS_486_EQ_486(...) \, +#define Z_IS_487_EQ_487(...) \, +#define Z_IS_488_EQ_488(...) \, +#define Z_IS_489_EQ_489(...) \, +#define Z_IS_490_EQ_490(...) \, +#define Z_IS_491_EQ_491(...) \, +#define Z_IS_492_EQ_492(...) \, +#define Z_IS_493_EQ_493(...) \, +#define Z_IS_494_EQ_494(...) \, +#define Z_IS_495_EQ_495(...) \, +#define Z_IS_496_EQ_496(...) \, +#define Z_IS_497_EQ_497(...) \, +#define Z_IS_498_EQ_498(...) \, +#define Z_IS_499_EQ_499(...) \, +#define Z_IS_500_EQ_500(...) \, +#define Z_IS_501_EQ_501(...) \, +#define Z_IS_502_EQ_502(...) \, +#define Z_IS_503_EQ_503(...) \, +#define Z_IS_504_EQ_504(...) \, +#define Z_IS_505_EQ_505(...) \, +#define Z_IS_506_EQ_506(...) \, +#define Z_IS_507_EQ_507(...) \, +#define Z_IS_508_EQ_508(...) \, +#define Z_IS_509_EQ_509(...) \, +#define Z_IS_510_EQ_510(...) \, +#define Z_IS_511_EQ_511(...) \, +#define Z_IS_512_EQ_512(...) \, +#define Z_IS_513_EQ_513(...) \, +#define Z_IS_514_EQ_514(...) \, +#define Z_IS_515_EQ_515(...) \, +#define Z_IS_516_EQ_516(...) \, +#define Z_IS_517_EQ_517(...) \, +#define Z_IS_518_EQ_518(...) \, +#define Z_IS_519_EQ_519(...) \, +#define Z_IS_520_EQ_520(...) \, +#define Z_IS_521_EQ_521(...) \, +#define Z_IS_522_EQ_522(...) \, +#define Z_IS_523_EQ_523(...) \, +#define Z_IS_524_EQ_524(...) \, +#define Z_IS_525_EQ_525(...) \, +#define Z_IS_526_EQ_526(...) \, +#define Z_IS_527_EQ_527(...) \, +#define Z_IS_528_EQ_528(...) \, +#define Z_IS_529_EQ_529(...) \, +#define Z_IS_530_EQ_530(...) \, +#define Z_IS_531_EQ_531(...) \, +#define Z_IS_532_EQ_532(...) \, +#define Z_IS_533_EQ_533(...) \, +#define Z_IS_534_EQ_534(...) \, +#define Z_IS_535_EQ_535(...) \, +#define Z_IS_536_EQ_536(...) \, +#define Z_IS_537_EQ_537(...) \, +#define Z_IS_538_EQ_538(...) \, +#define Z_IS_539_EQ_539(...) \, +#define Z_IS_540_EQ_540(...) \, +#define Z_IS_541_EQ_541(...) \, +#define Z_IS_542_EQ_542(...) \, +#define Z_IS_543_EQ_543(...) \, +#define Z_IS_544_EQ_544(...) \, +#define Z_IS_545_EQ_545(...) \, +#define Z_IS_546_EQ_546(...) \, +#define Z_IS_547_EQ_547(...) \, +#define Z_IS_548_EQ_548(...) \, +#define Z_IS_549_EQ_549(...) \, +#define Z_IS_550_EQ_550(...) \, +#define Z_IS_551_EQ_551(...) \, +#define Z_IS_552_EQ_552(...) \, +#define Z_IS_553_EQ_553(...) \, +#define Z_IS_554_EQ_554(...) \, +#define Z_IS_555_EQ_555(...) \, +#define Z_IS_556_EQ_556(...) \, +#define Z_IS_557_EQ_557(...) \, +#define Z_IS_558_EQ_558(...) \, +#define Z_IS_559_EQ_559(...) \, +#define Z_IS_560_EQ_560(...) \, +#define Z_IS_561_EQ_561(...) \, +#define Z_IS_562_EQ_562(...) \, +#define Z_IS_563_EQ_563(...) \, +#define Z_IS_564_EQ_564(...) \, +#define Z_IS_565_EQ_565(...) \, +#define Z_IS_566_EQ_566(...) \, +#define Z_IS_567_EQ_567(...) \, +#define Z_IS_568_EQ_568(...) \, +#define Z_IS_569_EQ_569(...) \, +#define Z_IS_570_EQ_570(...) \, +#define Z_IS_571_EQ_571(...) \, +#define Z_IS_572_EQ_572(...) \, +#define Z_IS_573_EQ_573(...) \, +#define Z_IS_574_EQ_574(...) \, +#define Z_IS_575_EQ_575(...) \, +#define Z_IS_576_EQ_576(...) \, +#define Z_IS_577_EQ_577(...) \, +#define Z_IS_578_EQ_578(...) \, +#define Z_IS_579_EQ_579(...) \, +#define Z_IS_580_EQ_580(...) \, +#define Z_IS_581_EQ_581(...) \, +#define Z_IS_582_EQ_582(...) \, +#define Z_IS_583_EQ_583(...) \, +#define Z_IS_584_EQ_584(...) \, +#define Z_IS_585_EQ_585(...) \, +#define Z_IS_586_EQ_586(...) \, +#define Z_IS_587_EQ_587(...) \, +#define Z_IS_588_EQ_588(...) \, +#define Z_IS_589_EQ_589(...) \, +#define Z_IS_590_EQ_590(...) \, +#define Z_IS_591_EQ_591(...) \, +#define Z_IS_592_EQ_592(...) \, +#define Z_IS_593_EQ_593(...) \, +#define Z_IS_594_EQ_594(...) \, +#define Z_IS_595_EQ_595(...) \, +#define Z_IS_596_EQ_596(...) \, +#define Z_IS_597_EQ_597(...) \, +#define Z_IS_598_EQ_598(...) \, +#define Z_IS_599_EQ_599(...) \, +#define Z_IS_600_EQ_600(...) \, +#define Z_IS_601_EQ_601(...) \, +#define Z_IS_602_EQ_602(...) \, +#define Z_IS_603_EQ_603(...) \, +#define Z_IS_604_EQ_604(...) \, +#define Z_IS_605_EQ_605(...) \, +#define Z_IS_606_EQ_606(...) \, +#define Z_IS_607_EQ_607(...) \, +#define Z_IS_608_EQ_608(...) \, +#define Z_IS_609_EQ_609(...) \, +#define Z_IS_610_EQ_610(...) \, +#define Z_IS_611_EQ_611(...) \, +#define Z_IS_612_EQ_612(...) \, +#define Z_IS_613_EQ_613(...) \, +#define Z_IS_614_EQ_614(...) \, +#define Z_IS_615_EQ_615(...) \, +#define Z_IS_616_EQ_616(...) \, +#define Z_IS_617_EQ_617(...) \, +#define Z_IS_618_EQ_618(...) \, +#define Z_IS_619_EQ_619(...) \, +#define Z_IS_620_EQ_620(...) \, +#define Z_IS_621_EQ_621(...) \, +#define Z_IS_622_EQ_622(...) \, +#define Z_IS_623_EQ_623(...) \, +#define Z_IS_624_EQ_624(...) \, +#define Z_IS_625_EQ_625(...) \, +#define Z_IS_626_EQ_626(...) \, +#define Z_IS_627_EQ_627(...) \, +#define Z_IS_628_EQ_628(...) \, +#define Z_IS_629_EQ_629(...) \, +#define Z_IS_630_EQ_630(...) \, +#define Z_IS_631_EQ_631(...) \, +#define Z_IS_632_EQ_632(...) \, +#define Z_IS_633_EQ_633(...) \, +#define Z_IS_634_EQ_634(...) \, +#define Z_IS_635_EQ_635(...) \, +#define Z_IS_636_EQ_636(...) \, +#define Z_IS_637_EQ_637(...) \, +#define Z_IS_638_EQ_638(...) \, +#define Z_IS_639_EQ_639(...) \, +#define Z_IS_640_EQ_640(...) \, +#define Z_IS_641_EQ_641(...) \, +#define Z_IS_642_EQ_642(...) \, +#define Z_IS_643_EQ_643(...) \, +#define Z_IS_644_EQ_644(...) \, +#define Z_IS_645_EQ_645(...) \, +#define Z_IS_646_EQ_646(...) \, +#define Z_IS_647_EQ_647(...) \, +#define Z_IS_648_EQ_648(...) \, +#define Z_IS_649_EQ_649(...) \, +#define Z_IS_650_EQ_650(...) \, +#define Z_IS_651_EQ_651(...) \, +#define Z_IS_652_EQ_652(...) \, +#define Z_IS_653_EQ_653(...) \, +#define Z_IS_654_EQ_654(...) \, +#define Z_IS_655_EQ_655(...) \, +#define Z_IS_656_EQ_656(...) \, +#define Z_IS_657_EQ_657(...) \, +#define Z_IS_658_EQ_658(...) \, +#define Z_IS_659_EQ_659(...) \, +#define Z_IS_660_EQ_660(...) \, +#define Z_IS_661_EQ_661(...) \, +#define Z_IS_662_EQ_662(...) \, +#define Z_IS_663_EQ_663(...) \, +#define Z_IS_664_EQ_664(...) \, +#define Z_IS_665_EQ_665(...) \, +#define Z_IS_666_EQ_666(...) \, +#define Z_IS_667_EQ_667(...) \, +#define Z_IS_668_EQ_668(...) \, +#define Z_IS_669_EQ_669(...) \, +#define Z_IS_670_EQ_670(...) \, +#define Z_IS_671_EQ_671(...) \, +#define Z_IS_672_EQ_672(...) \, +#define Z_IS_673_EQ_673(...) \, +#define Z_IS_674_EQ_674(...) \, +#define Z_IS_675_EQ_675(...) \, +#define Z_IS_676_EQ_676(...) \, +#define Z_IS_677_EQ_677(...) \, +#define Z_IS_678_EQ_678(...) \, +#define Z_IS_679_EQ_679(...) \, +#define Z_IS_680_EQ_680(...) \, +#define Z_IS_681_EQ_681(...) \, +#define Z_IS_682_EQ_682(...) \, +#define Z_IS_683_EQ_683(...) \, +#define Z_IS_684_EQ_684(...) \, +#define Z_IS_685_EQ_685(...) \, +#define Z_IS_686_EQ_686(...) \, +#define Z_IS_687_EQ_687(...) \, +#define Z_IS_688_EQ_688(...) \, +#define Z_IS_689_EQ_689(...) \, +#define Z_IS_690_EQ_690(...) \, +#define Z_IS_691_EQ_691(...) \, +#define Z_IS_692_EQ_692(...) \, +#define Z_IS_693_EQ_693(...) \, +#define Z_IS_694_EQ_694(...) \, +#define Z_IS_695_EQ_695(...) \, +#define Z_IS_696_EQ_696(...) \, +#define Z_IS_697_EQ_697(...) \, +#define Z_IS_698_EQ_698(...) \, +#define Z_IS_699_EQ_699(...) \, +#define Z_IS_700_EQ_700(...) \, +#define Z_IS_701_EQ_701(...) \, +#define Z_IS_702_EQ_702(...) \, +#define Z_IS_703_EQ_703(...) \, +#define Z_IS_704_EQ_704(...) \, +#define Z_IS_705_EQ_705(...) \, +#define Z_IS_706_EQ_706(...) \, +#define Z_IS_707_EQ_707(...) \, +#define Z_IS_708_EQ_708(...) \, +#define Z_IS_709_EQ_709(...) \, +#define Z_IS_710_EQ_710(...) \, +#define Z_IS_711_EQ_711(...) \, +#define Z_IS_712_EQ_712(...) \, +#define Z_IS_713_EQ_713(...) \, +#define Z_IS_714_EQ_714(...) \, +#define Z_IS_715_EQ_715(...) \, +#define Z_IS_716_EQ_716(...) \, +#define Z_IS_717_EQ_717(...) \, +#define Z_IS_718_EQ_718(...) \, +#define Z_IS_719_EQ_719(...) \, +#define Z_IS_720_EQ_720(...) \, +#define Z_IS_721_EQ_721(...) \, +#define Z_IS_722_EQ_722(...) \, +#define Z_IS_723_EQ_723(...) \, +#define Z_IS_724_EQ_724(...) \, +#define Z_IS_725_EQ_725(...) \, +#define Z_IS_726_EQ_726(...) \, +#define Z_IS_727_EQ_727(...) \, +#define Z_IS_728_EQ_728(...) \, +#define Z_IS_729_EQ_729(...) \, +#define Z_IS_730_EQ_730(...) \, +#define Z_IS_731_EQ_731(...) \, +#define Z_IS_732_EQ_732(...) \, +#define Z_IS_733_EQ_733(...) \, +#define Z_IS_734_EQ_734(...) \, +#define Z_IS_735_EQ_735(...) \, +#define Z_IS_736_EQ_736(...) \, +#define Z_IS_737_EQ_737(...) \, +#define Z_IS_738_EQ_738(...) \, +#define Z_IS_739_EQ_739(...) \, +#define Z_IS_740_EQ_740(...) \, +#define Z_IS_741_EQ_741(...) \, +#define Z_IS_742_EQ_742(...) \, +#define Z_IS_743_EQ_743(...) \, +#define Z_IS_744_EQ_744(...) \, +#define Z_IS_745_EQ_745(...) \, +#define Z_IS_746_EQ_746(...) \, +#define Z_IS_747_EQ_747(...) \, +#define Z_IS_748_EQ_748(...) \, +#define Z_IS_749_EQ_749(...) \, +#define Z_IS_750_EQ_750(...) \, +#define Z_IS_751_EQ_751(...) \, +#define Z_IS_752_EQ_752(...) \, +#define Z_IS_753_EQ_753(...) \, +#define Z_IS_754_EQ_754(...) \, +#define Z_IS_755_EQ_755(...) \, +#define Z_IS_756_EQ_756(...) \, +#define Z_IS_757_EQ_757(...) \, +#define Z_IS_758_EQ_758(...) \, +#define Z_IS_759_EQ_759(...) \, +#define Z_IS_760_EQ_760(...) \, +#define Z_IS_761_EQ_761(...) \, +#define Z_IS_762_EQ_762(...) \, +#define Z_IS_763_EQ_763(...) \, +#define Z_IS_764_EQ_764(...) \, +#define Z_IS_765_EQ_765(...) \, +#define Z_IS_766_EQ_766(...) \, +#define Z_IS_767_EQ_767(...) \, +#define Z_IS_768_EQ_768(...) \, +#define Z_IS_769_EQ_769(...) \, +#define Z_IS_770_EQ_770(...) \, +#define Z_IS_771_EQ_771(...) \, +#define Z_IS_772_EQ_772(...) \, +#define Z_IS_773_EQ_773(...) \, +#define Z_IS_774_EQ_774(...) \, +#define Z_IS_775_EQ_775(...) \, +#define Z_IS_776_EQ_776(...) \, +#define Z_IS_777_EQ_777(...) \, +#define Z_IS_778_EQ_778(...) \, +#define Z_IS_779_EQ_779(...) \, +#define Z_IS_780_EQ_780(...) \, +#define Z_IS_781_EQ_781(...) \, +#define Z_IS_782_EQ_782(...) \, +#define Z_IS_783_EQ_783(...) \, +#define Z_IS_784_EQ_784(...) \, +#define Z_IS_785_EQ_785(...) \, +#define Z_IS_786_EQ_786(...) \, +#define Z_IS_787_EQ_787(...) \, +#define Z_IS_788_EQ_788(...) \, +#define Z_IS_789_EQ_789(...) \, +#define Z_IS_790_EQ_790(...) \, +#define Z_IS_791_EQ_791(...) \, +#define Z_IS_792_EQ_792(...) \, +#define Z_IS_793_EQ_793(...) \, +#define Z_IS_794_EQ_794(...) \, +#define Z_IS_795_EQ_795(...) \, +#define Z_IS_796_EQ_796(...) \, +#define Z_IS_797_EQ_797(...) \, +#define Z_IS_798_EQ_798(...) \, +#define Z_IS_799_EQ_799(...) \, +#define Z_IS_800_EQ_800(...) \, +#define Z_IS_801_EQ_801(...) \, +#define Z_IS_802_EQ_802(...) \, +#define Z_IS_803_EQ_803(...) \, +#define Z_IS_804_EQ_804(...) \, +#define Z_IS_805_EQ_805(...) \, +#define Z_IS_806_EQ_806(...) \, +#define Z_IS_807_EQ_807(...) \, +#define Z_IS_808_EQ_808(...) \, +#define Z_IS_809_EQ_809(...) \, +#define Z_IS_810_EQ_810(...) \, +#define Z_IS_811_EQ_811(...) \, +#define Z_IS_812_EQ_812(...) \, +#define Z_IS_813_EQ_813(...) \, +#define Z_IS_814_EQ_814(...) \, +#define Z_IS_815_EQ_815(...) \, +#define Z_IS_816_EQ_816(...) \, +#define Z_IS_817_EQ_817(...) \, +#define Z_IS_818_EQ_818(...) \, +#define Z_IS_819_EQ_819(...) \, +#define Z_IS_820_EQ_820(...) \, +#define Z_IS_821_EQ_821(...) \, +#define Z_IS_822_EQ_822(...) \, +#define Z_IS_823_EQ_823(...) \, +#define Z_IS_824_EQ_824(...) \, +#define Z_IS_825_EQ_825(...) \, +#define Z_IS_826_EQ_826(...) \, +#define Z_IS_827_EQ_827(...) \, +#define Z_IS_828_EQ_828(...) \, +#define Z_IS_829_EQ_829(...) \, +#define Z_IS_830_EQ_830(...) \, +#define Z_IS_831_EQ_831(...) \, +#define Z_IS_832_EQ_832(...) \, +#define Z_IS_833_EQ_833(...) \, +#define Z_IS_834_EQ_834(...) \, +#define Z_IS_835_EQ_835(...) \, +#define Z_IS_836_EQ_836(...) \, +#define Z_IS_837_EQ_837(...) \, +#define Z_IS_838_EQ_838(...) \, +#define Z_IS_839_EQ_839(...) \, +#define Z_IS_840_EQ_840(...) \, +#define Z_IS_841_EQ_841(...) \, +#define Z_IS_842_EQ_842(...) \, +#define Z_IS_843_EQ_843(...) \, +#define Z_IS_844_EQ_844(...) \, +#define Z_IS_845_EQ_845(...) \, +#define Z_IS_846_EQ_846(...) \, +#define Z_IS_847_EQ_847(...) \, +#define Z_IS_848_EQ_848(...) \, +#define Z_IS_849_EQ_849(...) \, +#define Z_IS_850_EQ_850(...) \, +#define Z_IS_851_EQ_851(...) \, +#define Z_IS_852_EQ_852(...) \, +#define Z_IS_853_EQ_853(...) \, +#define Z_IS_854_EQ_854(...) \, +#define Z_IS_855_EQ_855(...) \, +#define Z_IS_856_EQ_856(...) \, +#define Z_IS_857_EQ_857(...) \, +#define Z_IS_858_EQ_858(...) \, +#define Z_IS_859_EQ_859(...) \, +#define Z_IS_860_EQ_860(...) \, +#define Z_IS_861_EQ_861(...) \, +#define Z_IS_862_EQ_862(...) \, +#define Z_IS_863_EQ_863(...) \, +#define Z_IS_864_EQ_864(...) \, +#define Z_IS_865_EQ_865(...) \, +#define Z_IS_866_EQ_866(...) \, +#define Z_IS_867_EQ_867(...) \, +#define Z_IS_868_EQ_868(...) \, +#define Z_IS_869_EQ_869(...) \, +#define Z_IS_870_EQ_870(...) \, +#define Z_IS_871_EQ_871(...) \, +#define Z_IS_872_EQ_872(...) \, +#define Z_IS_873_EQ_873(...) \, +#define Z_IS_874_EQ_874(...) \, +#define Z_IS_875_EQ_875(...) \, +#define Z_IS_876_EQ_876(...) \, +#define Z_IS_877_EQ_877(...) \, +#define Z_IS_878_EQ_878(...) \, +#define Z_IS_879_EQ_879(...) \, +#define Z_IS_880_EQ_880(...) \, +#define Z_IS_881_EQ_881(...) \, +#define Z_IS_882_EQ_882(...) \, +#define Z_IS_883_EQ_883(...) \, +#define Z_IS_884_EQ_884(...) \, +#define Z_IS_885_EQ_885(...) \, +#define Z_IS_886_EQ_886(...) \, +#define Z_IS_887_EQ_887(...) \, +#define Z_IS_888_EQ_888(...) \, +#define Z_IS_889_EQ_889(...) \, +#define Z_IS_890_EQ_890(...) \, +#define Z_IS_891_EQ_891(...) \, +#define Z_IS_892_EQ_892(...) \, +#define Z_IS_893_EQ_893(...) \, +#define Z_IS_894_EQ_894(...) \, +#define Z_IS_895_EQ_895(...) \, +#define Z_IS_896_EQ_896(...) \, +#define Z_IS_897_EQ_897(...) \, +#define Z_IS_898_EQ_898(...) \, +#define Z_IS_899_EQ_899(...) \, +#define Z_IS_900_EQ_900(...) \, +#define Z_IS_901_EQ_901(...) \, +#define Z_IS_902_EQ_902(...) \, +#define Z_IS_903_EQ_903(...) \, +#define Z_IS_904_EQ_904(...) \, +#define Z_IS_905_EQ_905(...) \, +#define Z_IS_906_EQ_906(...) \, +#define Z_IS_907_EQ_907(...) \, +#define Z_IS_908_EQ_908(...) \, +#define Z_IS_909_EQ_909(...) \, +#define Z_IS_910_EQ_910(...) \, +#define Z_IS_911_EQ_911(...) \, +#define Z_IS_912_EQ_912(...) \, +#define Z_IS_913_EQ_913(...) \, +#define Z_IS_914_EQ_914(...) \, +#define Z_IS_915_EQ_915(...) \, +#define Z_IS_916_EQ_916(...) \, +#define Z_IS_917_EQ_917(...) \, +#define Z_IS_918_EQ_918(...) \, +#define Z_IS_919_EQ_919(...) \, +#define Z_IS_920_EQ_920(...) \, +#define Z_IS_921_EQ_921(...) \, +#define Z_IS_922_EQ_922(...) \, +#define Z_IS_923_EQ_923(...) \, +#define Z_IS_924_EQ_924(...) \, +#define Z_IS_925_EQ_925(...) \, +#define Z_IS_926_EQ_926(...) \, +#define Z_IS_927_EQ_927(...) \, +#define Z_IS_928_EQ_928(...) \, +#define Z_IS_929_EQ_929(...) \, +#define Z_IS_930_EQ_930(...) \, +#define Z_IS_931_EQ_931(...) \, +#define Z_IS_932_EQ_932(...) \, +#define Z_IS_933_EQ_933(...) \, +#define Z_IS_934_EQ_934(...) \, +#define Z_IS_935_EQ_935(...) \, +#define Z_IS_936_EQ_936(...) \, +#define Z_IS_937_EQ_937(...) \, +#define Z_IS_938_EQ_938(...) \, +#define Z_IS_939_EQ_939(...) \, +#define Z_IS_940_EQ_940(...) \, +#define Z_IS_941_EQ_941(...) \, +#define Z_IS_942_EQ_942(...) \, +#define Z_IS_943_EQ_943(...) \, +#define Z_IS_944_EQ_944(...) \, +#define Z_IS_945_EQ_945(...) \, +#define Z_IS_946_EQ_946(...) \, +#define Z_IS_947_EQ_947(...) \, +#define Z_IS_948_EQ_948(...) \, +#define Z_IS_949_EQ_949(...) \, +#define Z_IS_950_EQ_950(...) \, +#define Z_IS_951_EQ_951(...) \, +#define Z_IS_952_EQ_952(...) \, +#define Z_IS_953_EQ_953(...) \, +#define Z_IS_954_EQ_954(...) \, +#define Z_IS_955_EQ_955(...) \, +#define Z_IS_956_EQ_956(...) \, +#define Z_IS_957_EQ_957(...) \, +#define Z_IS_958_EQ_958(...) \, +#define Z_IS_959_EQ_959(...) \, +#define Z_IS_960_EQ_960(...) \, +#define Z_IS_961_EQ_961(...) \, +#define Z_IS_962_EQ_962(...) \, +#define Z_IS_963_EQ_963(...) \, +#define Z_IS_964_EQ_964(...) \, +#define Z_IS_965_EQ_965(...) \, +#define Z_IS_966_EQ_966(...) \, +#define Z_IS_967_EQ_967(...) \, +#define Z_IS_968_EQ_968(...) \, +#define Z_IS_969_EQ_969(...) \, +#define Z_IS_970_EQ_970(...) \, +#define Z_IS_971_EQ_971(...) \, +#define Z_IS_972_EQ_972(...) \, +#define Z_IS_973_EQ_973(...) \, +#define Z_IS_974_EQ_974(...) \, +#define Z_IS_975_EQ_975(...) \, +#define Z_IS_976_EQ_976(...) \, +#define Z_IS_977_EQ_977(...) \, +#define Z_IS_978_EQ_978(...) \, +#define Z_IS_979_EQ_979(...) \, +#define Z_IS_980_EQ_980(...) \, +#define Z_IS_981_EQ_981(...) \, +#define Z_IS_982_EQ_982(...) \, +#define Z_IS_983_EQ_983(...) \, +#define Z_IS_984_EQ_984(...) \, +#define Z_IS_985_EQ_985(...) \, +#define Z_IS_986_EQ_986(...) \, +#define Z_IS_987_EQ_987(...) \, +#define Z_IS_988_EQ_988(...) \, +#define Z_IS_989_EQ_989(...) \, +#define Z_IS_990_EQ_990(...) \, +#define Z_IS_991_EQ_991(...) \, +#define Z_IS_992_EQ_992(...) \, +#define Z_IS_993_EQ_993(...) \, +#define Z_IS_994_EQ_994(...) \, +#define Z_IS_995_EQ_995(...) \, +#define Z_IS_996_EQ_996(...) \, +#define Z_IS_997_EQ_997(...) \, +#define Z_IS_998_EQ_998(...) \, +#define Z_IS_999_EQ_999(...) \, +#define Z_IS_1000_EQ_1000(...) \, +#define Z_IS_1001_EQ_1001(...) \, +#define Z_IS_1002_EQ_1002(...) \, +#define Z_IS_1003_EQ_1003(...) \, +#define Z_IS_1004_EQ_1004(...) \, +#define Z_IS_1005_EQ_1005(...) \, +#define Z_IS_1006_EQ_1006(...) \, +#define Z_IS_1007_EQ_1007(...) \, +#define Z_IS_1008_EQ_1008(...) \, +#define Z_IS_1009_EQ_1009(...) \, +#define Z_IS_1010_EQ_1010(...) \, +#define Z_IS_1011_EQ_1011(...) \, +#define Z_IS_1012_EQ_1012(...) \, +#define Z_IS_1013_EQ_1013(...) \, +#define Z_IS_1014_EQ_1014(...) \, +#define Z_IS_1015_EQ_1015(...) \, +#define Z_IS_1016_EQ_1016(...) \, +#define Z_IS_1017_EQ_1017(...) \, +#define Z_IS_1018_EQ_1018(...) \, +#define Z_IS_1019_EQ_1019(...) \, +#define Z_IS_1020_EQ_1020(...) \, +#define Z_IS_1021_EQ_1021(...) \, +#define Z_IS_1022_EQ_1022(...) \, +#define Z_IS_1023_EQ_1023(...) \, +#define Z_IS_1024_EQ_1024(...) \, +#define Z_IS_1025_EQ_1025(...) \, +#define Z_IS_1026_EQ_1026(...) \, +#define Z_IS_1027_EQ_1027(...) \, +#define Z_IS_1028_EQ_1028(...) \, +#define Z_IS_1029_EQ_1029(...) \, +#define Z_IS_1030_EQ_1030(...) \, +#define Z_IS_1031_EQ_1031(...) \, +#define Z_IS_1032_EQ_1032(...) \, +#define Z_IS_1033_EQ_1033(...) \, +#define Z_IS_1034_EQ_1034(...) \, +#define Z_IS_1035_EQ_1035(...) \, +#define Z_IS_1036_EQ_1036(...) \, +#define Z_IS_1037_EQ_1037(...) \, +#define Z_IS_1038_EQ_1038(...) \, +#define Z_IS_1039_EQ_1039(...) \, +#define Z_IS_1040_EQ_1040(...) \, +#define Z_IS_1041_EQ_1041(...) \, +#define Z_IS_1042_EQ_1042(...) \, +#define Z_IS_1043_EQ_1043(...) \, +#define Z_IS_1044_EQ_1044(...) \, +#define Z_IS_1045_EQ_1045(...) \, +#define Z_IS_1046_EQ_1046(...) \, +#define Z_IS_1047_EQ_1047(...) \, +#define Z_IS_1048_EQ_1048(...) \, +#define Z_IS_1049_EQ_1049(...) \, +#define Z_IS_1050_EQ_1050(...) \, +#define Z_IS_1051_EQ_1051(...) \, +#define Z_IS_1052_EQ_1052(...) \, +#define Z_IS_1053_EQ_1053(...) \, +#define Z_IS_1054_EQ_1054(...) \, +#define Z_IS_1055_EQ_1055(...) \, +#define Z_IS_1056_EQ_1056(...) \, +#define Z_IS_1057_EQ_1057(...) \, +#define Z_IS_1058_EQ_1058(...) \, +#define Z_IS_1059_EQ_1059(...) \, +#define Z_IS_1060_EQ_1060(...) \, +#define Z_IS_1061_EQ_1061(...) \, +#define Z_IS_1062_EQ_1062(...) \, +#define Z_IS_1063_EQ_1063(...) \, +#define Z_IS_1064_EQ_1064(...) \, +#define Z_IS_1065_EQ_1065(...) \, +#define Z_IS_1066_EQ_1066(...) \, +#define Z_IS_1067_EQ_1067(...) \, +#define Z_IS_1068_EQ_1068(...) \, +#define Z_IS_1069_EQ_1069(...) \, +#define Z_IS_1070_EQ_1070(...) \, +#define Z_IS_1071_EQ_1071(...) \, +#define Z_IS_1072_EQ_1072(...) \, +#define Z_IS_1073_EQ_1073(...) \, +#define Z_IS_1074_EQ_1074(...) \, +#define Z_IS_1075_EQ_1075(...) \, +#define Z_IS_1076_EQ_1076(...) \, +#define Z_IS_1077_EQ_1077(...) \, +#define Z_IS_1078_EQ_1078(...) \, +#define Z_IS_1079_EQ_1079(...) \, +#define Z_IS_1080_EQ_1080(...) \, +#define Z_IS_1081_EQ_1081(...) \, +#define Z_IS_1082_EQ_1082(...) \, +#define Z_IS_1083_EQ_1083(...) \, +#define Z_IS_1084_EQ_1084(...) \, +#define Z_IS_1085_EQ_1085(...) \, +#define Z_IS_1086_EQ_1086(...) \, +#define Z_IS_1087_EQ_1087(...) \, +#define Z_IS_1088_EQ_1088(...) \, +#define Z_IS_1089_EQ_1089(...) \, +#define Z_IS_1090_EQ_1090(...) \, +#define Z_IS_1091_EQ_1091(...) \, +#define Z_IS_1092_EQ_1092(...) \, +#define Z_IS_1093_EQ_1093(...) \, +#define Z_IS_1094_EQ_1094(...) \, +#define Z_IS_1095_EQ_1095(...) \, +#define Z_IS_1096_EQ_1096(...) \, +#define Z_IS_1097_EQ_1097(...) \, +#define Z_IS_1098_EQ_1098(...) \, +#define Z_IS_1099_EQ_1099(...) \, +#define Z_IS_1100_EQ_1100(...) \, +#define Z_IS_1101_EQ_1101(...) \, +#define Z_IS_1102_EQ_1102(...) \, +#define Z_IS_1103_EQ_1103(...) \, +#define Z_IS_1104_EQ_1104(...) \, +#define Z_IS_1105_EQ_1105(...) \, +#define Z_IS_1106_EQ_1106(...) \, +#define Z_IS_1107_EQ_1107(...) \, +#define Z_IS_1108_EQ_1108(...) \, +#define Z_IS_1109_EQ_1109(...) \, +#define Z_IS_1110_EQ_1110(...) \, +#define Z_IS_1111_EQ_1111(...) \, +#define Z_IS_1112_EQ_1112(...) \, +#define Z_IS_1113_EQ_1113(...) \, +#define Z_IS_1114_EQ_1114(...) \, +#define Z_IS_1115_EQ_1115(...) \, +#define Z_IS_1116_EQ_1116(...) \, +#define Z_IS_1117_EQ_1117(...) \, +#define Z_IS_1118_EQ_1118(...) \, +#define Z_IS_1119_EQ_1119(...) \, +#define Z_IS_1120_EQ_1120(...) \, +#define Z_IS_1121_EQ_1121(...) \, +#define Z_IS_1122_EQ_1122(...) \, +#define Z_IS_1123_EQ_1123(...) \, +#define Z_IS_1124_EQ_1124(...) \, +#define Z_IS_1125_EQ_1125(...) \, +#define Z_IS_1126_EQ_1126(...) \, +#define Z_IS_1127_EQ_1127(...) \, +#define Z_IS_1128_EQ_1128(...) \, +#define Z_IS_1129_EQ_1129(...) \, +#define Z_IS_1130_EQ_1130(...) \, +#define Z_IS_1131_EQ_1131(...) \, +#define Z_IS_1132_EQ_1132(...) \, +#define Z_IS_1133_EQ_1133(...) \, +#define Z_IS_1134_EQ_1134(...) \, +#define Z_IS_1135_EQ_1135(...) \, +#define Z_IS_1136_EQ_1136(...) \, +#define Z_IS_1137_EQ_1137(...) \, +#define Z_IS_1138_EQ_1138(...) \, +#define Z_IS_1139_EQ_1139(...) \, +#define Z_IS_1140_EQ_1140(...) \, +#define Z_IS_1141_EQ_1141(...) \, +#define Z_IS_1142_EQ_1142(...) \, +#define Z_IS_1143_EQ_1143(...) \, +#define Z_IS_1144_EQ_1144(...) \, +#define Z_IS_1145_EQ_1145(...) \, +#define Z_IS_1146_EQ_1146(...) \, +#define Z_IS_1147_EQ_1147(...) \, +#define Z_IS_1148_EQ_1148(...) \, +#define Z_IS_1149_EQ_1149(...) \, +#define Z_IS_1150_EQ_1150(...) \, +#define Z_IS_1151_EQ_1151(...) \, +#define Z_IS_1152_EQ_1152(...) \, +#define Z_IS_1153_EQ_1153(...) \, +#define Z_IS_1154_EQ_1154(...) \, +#define Z_IS_1155_EQ_1155(...) \, +#define Z_IS_1156_EQ_1156(...) \, +#define Z_IS_1157_EQ_1157(...) \, +#define Z_IS_1158_EQ_1158(...) \, +#define Z_IS_1159_EQ_1159(...) \, +#define Z_IS_1160_EQ_1160(...) \, +#define Z_IS_1161_EQ_1161(...) \, +#define Z_IS_1162_EQ_1162(...) \, +#define Z_IS_1163_EQ_1163(...) \, +#define Z_IS_1164_EQ_1164(...) \, +#define Z_IS_1165_EQ_1165(...) \, +#define Z_IS_1166_EQ_1166(...) \, +#define Z_IS_1167_EQ_1167(...) \, +#define Z_IS_1168_EQ_1168(...) \, +#define Z_IS_1169_EQ_1169(...) \, +#define Z_IS_1170_EQ_1170(...) \, +#define Z_IS_1171_EQ_1171(...) \, +#define Z_IS_1172_EQ_1172(...) \, +#define Z_IS_1173_EQ_1173(...) \, +#define Z_IS_1174_EQ_1174(...) \, +#define Z_IS_1175_EQ_1175(...) \, +#define Z_IS_1176_EQ_1176(...) \, +#define Z_IS_1177_EQ_1177(...) \, +#define Z_IS_1178_EQ_1178(...) \, +#define Z_IS_1179_EQ_1179(...) \, +#define Z_IS_1180_EQ_1180(...) \, +#define Z_IS_1181_EQ_1181(...) \, +#define Z_IS_1182_EQ_1182(...) \, +#define Z_IS_1183_EQ_1183(...) \, +#define Z_IS_1184_EQ_1184(...) \, +#define Z_IS_1185_EQ_1185(...) \, +#define Z_IS_1186_EQ_1186(...) \, +#define Z_IS_1187_EQ_1187(...) \, +#define Z_IS_1188_EQ_1188(...) \, +#define Z_IS_1189_EQ_1189(...) \, +#define Z_IS_1190_EQ_1190(...) \, +#define Z_IS_1191_EQ_1191(...) \, +#define Z_IS_1192_EQ_1192(...) \, +#define Z_IS_1193_EQ_1193(...) \, +#define Z_IS_1194_EQ_1194(...) \, +#define Z_IS_1195_EQ_1195(...) \, +#define Z_IS_1196_EQ_1196(...) \, +#define Z_IS_1197_EQ_1197(...) \, +#define Z_IS_1198_EQ_1198(...) \, +#define Z_IS_1199_EQ_1199(...) \, +#define Z_IS_1200_EQ_1200(...) \, +#define Z_IS_1201_EQ_1201(...) \, +#define Z_IS_1202_EQ_1202(...) \, +#define Z_IS_1203_EQ_1203(...) \, +#define Z_IS_1204_EQ_1204(...) \, +#define Z_IS_1205_EQ_1205(...) \, +#define Z_IS_1206_EQ_1206(...) \, +#define Z_IS_1207_EQ_1207(...) \, +#define Z_IS_1208_EQ_1208(...) \, +#define Z_IS_1209_EQ_1209(...) \, +#define Z_IS_1210_EQ_1210(...) \, +#define Z_IS_1211_EQ_1211(...) \, +#define Z_IS_1212_EQ_1212(...) \, +#define Z_IS_1213_EQ_1213(...) \, +#define Z_IS_1214_EQ_1214(...) \, +#define Z_IS_1215_EQ_1215(...) \, +#define Z_IS_1216_EQ_1216(...) \, +#define Z_IS_1217_EQ_1217(...) \, +#define Z_IS_1218_EQ_1218(...) \, +#define Z_IS_1219_EQ_1219(...) \, +#define Z_IS_1220_EQ_1220(...) \, +#define Z_IS_1221_EQ_1221(...) \, +#define Z_IS_1222_EQ_1222(...) \, +#define Z_IS_1223_EQ_1223(...) \, +#define Z_IS_1224_EQ_1224(...) \, +#define Z_IS_1225_EQ_1225(...) \, +#define Z_IS_1226_EQ_1226(...) \, +#define Z_IS_1227_EQ_1227(...) \, +#define Z_IS_1228_EQ_1228(...) \, +#define Z_IS_1229_EQ_1229(...) \, +#define Z_IS_1230_EQ_1230(...) \, +#define Z_IS_1231_EQ_1231(...) \, +#define Z_IS_1232_EQ_1232(...) \, +#define Z_IS_1233_EQ_1233(...) \, +#define Z_IS_1234_EQ_1234(...) \, +#define Z_IS_1235_EQ_1235(...) \, +#define Z_IS_1236_EQ_1236(...) \, +#define Z_IS_1237_EQ_1237(...) \, +#define Z_IS_1238_EQ_1238(...) \, +#define Z_IS_1239_EQ_1239(...) \, +#define Z_IS_1240_EQ_1240(...) \, +#define Z_IS_1241_EQ_1241(...) \, +#define Z_IS_1242_EQ_1242(...) \, +#define Z_IS_1243_EQ_1243(...) \, +#define Z_IS_1244_EQ_1244(...) \, +#define Z_IS_1245_EQ_1245(...) \, +#define Z_IS_1246_EQ_1246(...) \, +#define Z_IS_1247_EQ_1247(...) \, +#define Z_IS_1248_EQ_1248(...) \, +#define Z_IS_1249_EQ_1249(...) \, +#define Z_IS_1250_EQ_1250(...) \, +#define Z_IS_1251_EQ_1251(...) \, +#define Z_IS_1252_EQ_1252(...) \, +#define Z_IS_1253_EQ_1253(...) \, +#define Z_IS_1254_EQ_1254(...) \, +#define Z_IS_1255_EQ_1255(...) \, +#define Z_IS_1256_EQ_1256(...) \, +#define Z_IS_1257_EQ_1257(...) \, +#define Z_IS_1258_EQ_1258(...) \, +#define Z_IS_1259_EQ_1259(...) \, +#define Z_IS_1260_EQ_1260(...) \, +#define Z_IS_1261_EQ_1261(...) \, +#define Z_IS_1262_EQ_1262(...) \, +#define Z_IS_1263_EQ_1263(...) \, +#define Z_IS_1264_EQ_1264(...) \, +#define Z_IS_1265_EQ_1265(...) \, +#define Z_IS_1266_EQ_1266(...) \, +#define Z_IS_1267_EQ_1267(...) \, +#define Z_IS_1268_EQ_1268(...) \, +#define Z_IS_1269_EQ_1269(...) \, +#define Z_IS_1270_EQ_1270(...) \, +#define Z_IS_1271_EQ_1271(...) \, +#define Z_IS_1272_EQ_1272(...) \, +#define Z_IS_1273_EQ_1273(...) \, +#define Z_IS_1274_EQ_1274(...) \, +#define Z_IS_1275_EQ_1275(...) \, +#define Z_IS_1276_EQ_1276(...) \, +#define Z_IS_1277_EQ_1277(...) \, +#define Z_IS_1278_EQ_1278(...) \, +#define Z_IS_1279_EQ_1279(...) \, +#define Z_IS_1280_EQ_1280(...) \, +#define Z_IS_1281_EQ_1281(...) \, +#define Z_IS_1282_EQ_1282(...) \, +#define Z_IS_1283_EQ_1283(...) \, +#define Z_IS_1284_EQ_1284(...) \, +#define Z_IS_1285_EQ_1285(...) \, +#define Z_IS_1286_EQ_1286(...) \, +#define Z_IS_1287_EQ_1287(...) \, +#define Z_IS_1288_EQ_1288(...) \, +#define Z_IS_1289_EQ_1289(...) \, +#define Z_IS_1290_EQ_1290(...) \, +#define Z_IS_1291_EQ_1291(...) \, +#define Z_IS_1292_EQ_1292(...) \, +#define Z_IS_1293_EQ_1293(...) \, +#define Z_IS_1294_EQ_1294(...) \, +#define Z_IS_1295_EQ_1295(...) \, +#define Z_IS_1296_EQ_1296(...) \, +#define Z_IS_1297_EQ_1297(...) \, +#define Z_IS_1298_EQ_1298(...) \, +#define Z_IS_1299_EQ_1299(...) \, +#define Z_IS_1300_EQ_1300(...) \, +#define Z_IS_1301_EQ_1301(...) \, +#define Z_IS_1302_EQ_1302(...) \, +#define Z_IS_1303_EQ_1303(...) \, +#define Z_IS_1304_EQ_1304(...) \, +#define Z_IS_1305_EQ_1305(...) \, +#define Z_IS_1306_EQ_1306(...) \, +#define Z_IS_1307_EQ_1307(...) \, +#define Z_IS_1308_EQ_1308(...) \, +#define Z_IS_1309_EQ_1309(...) \, +#define Z_IS_1310_EQ_1310(...) \, +#define Z_IS_1311_EQ_1311(...) \, +#define Z_IS_1312_EQ_1312(...) \, +#define Z_IS_1313_EQ_1313(...) \, +#define Z_IS_1314_EQ_1314(...) \, +#define Z_IS_1315_EQ_1315(...) \, +#define Z_IS_1316_EQ_1316(...) \, +#define Z_IS_1317_EQ_1317(...) \, +#define Z_IS_1318_EQ_1318(...) \, +#define Z_IS_1319_EQ_1319(...) \, +#define Z_IS_1320_EQ_1320(...) \, +#define Z_IS_1321_EQ_1321(...) \, +#define Z_IS_1322_EQ_1322(...) \, +#define Z_IS_1323_EQ_1323(...) \, +#define Z_IS_1324_EQ_1324(...) \, +#define Z_IS_1325_EQ_1325(...) \, +#define Z_IS_1326_EQ_1326(...) \, +#define Z_IS_1327_EQ_1327(...) \, +#define Z_IS_1328_EQ_1328(...) \, +#define Z_IS_1329_EQ_1329(...) \, +#define Z_IS_1330_EQ_1330(...) \, +#define Z_IS_1331_EQ_1331(...) \, +#define Z_IS_1332_EQ_1332(...) \, +#define Z_IS_1333_EQ_1333(...) \, +#define Z_IS_1334_EQ_1334(...) \, +#define Z_IS_1335_EQ_1335(...) \, +#define Z_IS_1336_EQ_1336(...) \, +#define Z_IS_1337_EQ_1337(...) \, +#define Z_IS_1338_EQ_1338(...) \, +#define Z_IS_1339_EQ_1339(...) \, +#define Z_IS_1340_EQ_1340(...) \, +#define Z_IS_1341_EQ_1341(...) \, +#define Z_IS_1342_EQ_1342(...) \, +#define Z_IS_1343_EQ_1343(...) \, +#define Z_IS_1344_EQ_1344(...) \, +#define Z_IS_1345_EQ_1345(...) \, +#define Z_IS_1346_EQ_1346(...) \, +#define Z_IS_1347_EQ_1347(...) \, +#define Z_IS_1348_EQ_1348(...) \, +#define Z_IS_1349_EQ_1349(...) \, +#define Z_IS_1350_EQ_1350(...) \, +#define Z_IS_1351_EQ_1351(...) \, +#define Z_IS_1352_EQ_1352(...) \, +#define Z_IS_1353_EQ_1353(...) \, +#define Z_IS_1354_EQ_1354(...) \, +#define Z_IS_1355_EQ_1355(...) \, +#define Z_IS_1356_EQ_1356(...) \, +#define Z_IS_1357_EQ_1357(...) \, +#define Z_IS_1358_EQ_1358(...) \, +#define Z_IS_1359_EQ_1359(...) \, +#define Z_IS_1360_EQ_1360(...) \, +#define Z_IS_1361_EQ_1361(...) \, +#define Z_IS_1362_EQ_1362(...) \, +#define Z_IS_1363_EQ_1363(...) \, +#define Z_IS_1364_EQ_1364(...) \, +#define Z_IS_1365_EQ_1365(...) \, +#define Z_IS_1366_EQ_1366(...) \, +#define Z_IS_1367_EQ_1367(...) \, +#define Z_IS_1368_EQ_1368(...) \, +#define Z_IS_1369_EQ_1369(...) \, +#define Z_IS_1370_EQ_1370(...) \, +#define Z_IS_1371_EQ_1371(...) \, +#define Z_IS_1372_EQ_1372(...) \, +#define Z_IS_1373_EQ_1373(...) \, +#define Z_IS_1374_EQ_1374(...) \, +#define Z_IS_1375_EQ_1375(...) \, +#define Z_IS_1376_EQ_1376(...) \, +#define Z_IS_1377_EQ_1377(...) \, +#define Z_IS_1378_EQ_1378(...) \, +#define Z_IS_1379_EQ_1379(...) \, +#define Z_IS_1380_EQ_1380(...) \, +#define Z_IS_1381_EQ_1381(...) \, +#define Z_IS_1382_EQ_1382(...) \, +#define Z_IS_1383_EQ_1383(...) \, +#define Z_IS_1384_EQ_1384(...) \, +#define Z_IS_1385_EQ_1385(...) \, +#define Z_IS_1386_EQ_1386(...) \, +#define Z_IS_1387_EQ_1387(...) \, +#define Z_IS_1388_EQ_1388(...) \, +#define Z_IS_1389_EQ_1389(...) \, +#define Z_IS_1390_EQ_1390(...) \, +#define Z_IS_1391_EQ_1391(...) \, +#define Z_IS_1392_EQ_1392(...) \, +#define Z_IS_1393_EQ_1393(...) \, +#define Z_IS_1394_EQ_1394(...) \, +#define Z_IS_1395_EQ_1395(...) \, +#define Z_IS_1396_EQ_1396(...) \, +#define Z_IS_1397_EQ_1397(...) \, +#define Z_IS_1398_EQ_1398(...) \, +#define Z_IS_1399_EQ_1399(...) \, +#define Z_IS_1400_EQ_1400(...) \, +#define Z_IS_1401_EQ_1401(...) \, +#define Z_IS_1402_EQ_1402(...) \, +#define Z_IS_1403_EQ_1403(...) \, +#define Z_IS_1404_EQ_1404(...) \, +#define Z_IS_1405_EQ_1405(...) \, +#define Z_IS_1406_EQ_1406(...) \, +#define Z_IS_1407_EQ_1407(...) \, +#define Z_IS_1408_EQ_1408(...) \, +#define Z_IS_1409_EQ_1409(...) \, +#define Z_IS_1410_EQ_1410(...) \, +#define Z_IS_1411_EQ_1411(...) \, +#define Z_IS_1412_EQ_1412(...) \, +#define Z_IS_1413_EQ_1413(...) \, +#define Z_IS_1414_EQ_1414(...) \, +#define Z_IS_1415_EQ_1415(...) \, +#define Z_IS_1416_EQ_1416(...) \, +#define Z_IS_1417_EQ_1417(...) \, +#define Z_IS_1418_EQ_1418(...) \, +#define Z_IS_1419_EQ_1419(...) \, +#define Z_IS_1420_EQ_1420(...) \, +#define Z_IS_1421_EQ_1421(...) \, +#define Z_IS_1422_EQ_1422(...) \, +#define Z_IS_1423_EQ_1423(...) \, +#define Z_IS_1424_EQ_1424(...) \, +#define Z_IS_1425_EQ_1425(...) \, +#define Z_IS_1426_EQ_1426(...) \, +#define Z_IS_1427_EQ_1427(...) \, +#define Z_IS_1428_EQ_1428(...) \, +#define Z_IS_1429_EQ_1429(...) \, +#define Z_IS_1430_EQ_1430(...) \, +#define Z_IS_1431_EQ_1431(...) \, +#define Z_IS_1432_EQ_1432(...) \, +#define Z_IS_1433_EQ_1433(...) \, +#define Z_IS_1434_EQ_1434(...) \, +#define Z_IS_1435_EQ_1435(...) \, +#define Z_IS_1436_EQ_1436(...) \, +#define Z_IS_1437_EQ_1437(...) \, +#define Z_IS_1438_EQ_1438(...) \, +#define Z_IS_1439_EQ_1439(...) \, +#define Z_IS_1440_EQ_1440(...) \, +#define Z_IS_1441_EQ_1441(...) \, +#define Z_IS_1442_EQ_1442(...) \, +#define Z_IS_1443_EQ_1443(...) \, +#define Z_IS_1444_EQ_1444(...) \, +#define Z_IS_1445_EQ_1445(...) \, +#define Z_IS_1446_EQ_1446(...) \, +#define Z_IS_1447_EQ_1447(...) \, +#define Z_IS_1448_EQ_1448(...) \, +#define Z_IS_1449_EQ_1449(...) \, +#define Z_IS_1450_EQ_1450(...) \, +#define Z_IS_1451_EQ_1451(...) \, +#define Z_IS_1452_EQ_1452(...) \, +#define Z_IS_1453_EQ_1453(...) \, +#define Z_IS_1454_EQ_1454(...) \, +#define Z_IS_1455_EQ_1455(...) \, +#define Z_IS_1456_EQ_1456(...) \, +#define Z_IS_1457_EQ_1457(...) \, +#define Z_IS_1458_EQ_1458(...) \, +#define Z_IS_1459_EQ_1459(...) \, +#define Z_IS_1460_EQ_1460(...) \, +#define Z_IS_1461_EQ_1461(...) \, +#define Z_IS_1462_EQ_1462(...) \, +#define Z_IS_1463_EQ_1463(...) \, +#define Z_IS_1464_EQ_1464(...) \, +#define Z_IS_1465_EQ_1465(...) \, +#define Z_IS_1466_EQ_1466(...) \, +#define Z_IS_1467_EQ_1467(...) \, +#define Z_IS_1468_EQ_1468(...) \, +#define Z_IS_1469_EQ_1469(...) \, +#define Z_IS_1470_EQ_1470(...) \, +#define Z_IS_1471_EQ_1471(...) \, +#define Z_IS_1472_EQ_1472(...) \, +#define Z_IS_1473_EQ_1473(...) \, +#define Z_IS_1474_EQ_1474(...) \, +#define Z_IS_1475_EQ_1475(...) \, +#define Z_IS_1476_EQ_1476(...) \, +#define Z_IS_1477_EQ_1477(...) \, +#define Z_IS_1478_EQ_1478(...) \, +#define Z_IS_1479_EQ_1479(...) \, +#define Z_IS_1480_EQ_1480(...) \, +#define Z_IS_1481_EQ_1481(...) \, +#define Z_IS_1482_EQ_1482(...) \, +#define Z_IS_1483_EQ_1483(...) \, +#define Z_IS_1484_EQ_1484(...) \, +#define Z_IS_1485_EQ_1485(...) \, +#define Z_IS_1486_EQ_1486(...) \, +#define Z_IS_1487_EQ_1487(...) \, +#define Z_IS_1488_EQ_1488(...) \, +#define Z_IS_1489_EQ_1489(...) \, +#define Z_IS_1490_EQ_1490(...) \, +#define Z_IS_1491_EQ_1491(...) \, +#define Z_IS_1492_EQ_1492(...) \, +#define Z_IS_1493_EQ_1493(...) \, +#define Z_IS_1494_EQ_1494(...) \, +#define Z_IS_1495_EQ_1495(...) \, +#define Z_IS_1496_EQ_1496(...) \, +#define Z_IS_1497_EQ_1497(...) \, +#define Z_IS_1498_EQ_1498(...) \, +#define Z_IS_1499_EQ_1499(...) \, +#define Z_IS_1500_EQ_1500(...) \, +#define Z_IS_1501_EQ_1501(...) \, +#define Z_IS_1502_EQ_1502(...) \, +#define Z_IS_1503_EQ_1503(...) \, +#define Z_IS_1504_EQ_1504(...) \, +#define Z_IS_1505_EQ_1505(...) \, +#define Z_IS_1506_EQ_1506(...) \, +#define Z_IS_1507_EQ_1507(...) \, +#define Z_IS_1508_EQ_1508(...) \, +#define Z_IS_1509_EQ_1509(...) \, +#define Z_IS_1510_EQ_1510(...) \, +#define Z_IS_1511_EQ_1511(...) \, +#define Z_IS_1512_EQ_1512(...) \, +#define Z_IS_1513_EQ_1513(...) \, +#define Z_IS_1514_EQ_1514(...) \, +#define Z_IS_1515_EQ_1515(...) \, +#define Z_IS_1516_EQ_1516(...) \, +#define Z_IS_1517_EQ_1517(...) \, +#define Z_IS_1518_EQ_1518(...) \, +#define Z_IS_1519_EQ_1519(...) \, +#define Z_IS_1520_EQ_1520(...) \, +#define Z_IS_1521_EQ_1521(...) \, +#define Z_IS_1522_EQ_1522(...) \, +#define Z_IS_1523_EQ_1523(...) \, +#define Z_IS_1524_EQ_1524(...) \, +#define Z_IS_1525_EQ_1525(...) \, +#define Z_IS_1526_EQ_1526(...) \, +#define Z_IS_1527_EQ_1527(...) \, +#define Z_IS_1528_EQ_1528(...) \, +#define Z_IS_1529_EQ_1529(...) \, +#define Z_IS_1530_EQ_1530(...) \, +#define Z_IS_1531_EQ_1531(...) \, +#define Z_IS_1532_EQ_1532(...) \, +#define Z_IS_1533_EQ_1533(...) \, +#define Z_IS_1534_EQ_1534(...) \, +#define Z_IS_1535_EQ_1535(...) \, +#define Z_IS_1536_EQ_1536(...) \, +#define Z_IS_1537_EQ_1537(...) \, +#define Z_IS_1538_EQ_1538(...) \, +#define Z_IS_1539_EQ_1539(...) \, +#define Z_IS_1540_EQ_1540(...) \, +#define Z_IS_1541_EQ_1541(...) \, +#define Z_IS_1542_EQ_1542(...) \, +#define Z_IS_1543_EQ_1543(...) \, +#define Z_IS_1544_EQ_1544(...) \, +#define Z_IS_1545_EQ_1545(...) \, +#define Z_IS_1546_EQ_1546(...) \, +#define Z_IS_1547_EQ_1547(...) \, +#define Z_IS_1548_EQ_1548(...) \, +#define Z_IS_1549_EQ_1549(...) \, +#define Z_IS_1550_EQ_1550(...) \, +#define Z_IS_1551_EQ_1551(...) \, +#define Z_IS_1552_EQ_1552(...) \, +#define Z_IS_1553_EQ_1553(...) \, +#define Z_IS_1554_EQ_1554(...) \, +#define Z_IS_1555_EQ_1555(...) \, +#define Z_IS_1556_EQ_1556(...) \, +#define Z_IS_1557_EQ_1557(...) \, +#define Z_IS_1558_EQ_1558(...) \, +#define Z_IS_1559_EQ_1559(...) \, +#define Z_IS_1560_EQ_1560(...) \, +#define Z_IS_1561_EQ_1561(...) \, +#define Z_IS_1562_EQ_1562(...) \, +#define Z_IS_1563_EQ_1563(...) \, +#define Z_IS_1564_EQ_1564(...) \, +#define Z_IS_1565_EQ_1565(...) \, +#define Z_IS_1566_EQ_1566(...) \, +#define Z_IS_1567_EQ_1567(...) \, +#define Z_IS_1568_EQ_1568(...) \, +#define Z_IS_1569_EQ_1569(...) \, +#define Z_IS_1570_EQ_1570(...) \, +#define Z_IS_1571_EQ_1571(...) \, +#define Z_IS_1572_EQ_1572(...) \, +#define Z_IS_1573_EQ_1573(...) \, +#define Z_IS_1574_EQ_1574(...) \, +#define Z_IS_1575_EQ_1575(...) \, +#define Z_IS_1576_EQ_1576(...) \, +#define Z_IS_1577_EQ_1577(...) \, +#define Z_IS_1578_EQ_1578(...) \, +#define Z_IS_1579_EQ_1579(...) \, +#define Z_IS_1580_EQ_1580(...) \, +#define Z_IS_1581_EQ_1581(...) \, +#define Z_IS_1582_EQ_1582(...) \, +#define Z_IS_1583_EQ_1583(...) \, +#define Z_IS_1584_EQ_1584(...) \, +#define Z_IS_1585_EQ_1585(...) \, +#define Z_IS_1586_EQ_1586(...) \, +#define Z_IS_1587_EQ_1587(...) \, +#define Z_IS_1588_EQ_1588(...) \, +#define Z_IS_1589_EQ_1589(...) \, +#define Z_IS_1590_EQ_1590(...) \, +#define Z_IS_1591_EQ_1591(...) \, +#define Z_IS_1592_EQ_1592(...) \, +#define Z_IS_1593_EQ_1593(...) \, +#define Z_IS_1594_EQ_1594(...) \, +#define Z_IS_1595_EQ_1595(...) \, +#define Z_IS_1596_EQ_1596(...) \, +#define Z_IS_1597_EQ_1597(...) \, +#define Z_IS_1598_EQ_1598(...) \, +#define Z_IS_1599_EQ_1599(...) \, +#define Z_IS_1600_EQ_1600(...) \, +#define Z_IS_1601_EQ_1601(...) \, +#define Z_IS_1602_EQ_1602(...) \, +#define Z_IS_1603_EQ_1603(...) \, +#define Z_IS_1604_EQ_1604(...) \, +#define Z_IS_1605_EQ_1605(...) \, +#define Z_IS_1606_EQ_1606(...) \, +#define Z_IS_1607_EQ_1607(...) \, +#define Z_IS_1608_EQ_1608(...) \, +#define Z_IS_1609_EQ_1609(...) \, +#define Z_IS_1610_EQ_1610(...) \, +#define Z_IS_1611_EQ_1611(...) \, +#define Z_IS_1612_EQ_1612(...) \, +#define Z_IS_1613_EQ_1613(...) \, +#define Z_IS_1614_EQ_1614(...) \, +#define Z_IS_1615_EQ_1615(...) \, +#define Z_IS_1616_EQ_1616(...) \, +#define Z_IS_1617_EQ_1617(...) \, +#define Z_IS_1618_EQ_1618(...) \, +#define Z_IS_1619_EQ_1619(...) \, +#define Z_IS_1620_EQ_1620(...) \, +#define Z_IS_1621_EQ_1621(...) \, +#define Z_IS_1622_EQ_1622(...) \, +#define Z_IS_1623_EQ_1623(...) \, +#define Z_IS_1624_EQ_1624(...) \, +#define Z_IS_1625_EQ_1625(...) \, +#define Z_IS_1626_EQ_1626(...) \, +#define Z_IS_1627_EQ_1627(...) \, +#define Z_IS_1628_EQ_1628(...) \, +#define Z_IS_1629_EQ_1629(...) \, +#define Z_IS_1630_EQ_1630(...) \, +#define Z_IS_1631_EQ_1631(...) \, +#define Z_IS_1632_EQ_1632(...) \, +#define Z_IS_1633_EQ_1633(...) \, +#define Z_IS_1634_EQ_1634(...) \, +#define Z_IS_1635_EQ_1635(...) \, +#define Z_IS_1636_EQ_1636(...) \, +#define Z_IS_1637_EQ_1637(...) \, +#define Z_IS_1638_EQ_1638(...) \, +#define Z_IS_1639_EQ_1639(...) \, +#define Z_IS_1640_EQ_1640(...) \, +#define Z_IS_1641_EQ_1641(...) \, +#define Z_IS_1642_EQ_1642(...) \, +#define Z_IS_1643_EQ_1643(...) \, +#define Z_IS_1644_EQ_1644(...) \, +#define Z_IS_1645_EQ_1645(...) \, +#define Z_IS_1646_EQ_1646(...) \, +#define Z_IS_1647_EQ_1647(...) \, +#define Z_IS_1648_EQ_1648(...) \, +#define Z_IS_1649_EQ_1649(...) \, +#define Z_IS_1650_EQ_1650(...) \, +#define Z_IS_1651_EQ_1651(...) \, +#define Z_IS_1652_EQ_1652(...) \, +#define Z_IS_1653_EQ_1653(...) \, +#define Z_IS_1654_EQ_1654(...) \, +#define Z_IS_1655_EQ_1655(...) \, +#define Z_IS_1656_EQ_1656(...) \, +#define Z_IS_1657_EQ_1657(...) \, +#define Z_IS_1658_EQ_1658(...) \, +#define Z_IS_1659_EQ_1659(...) \, +#define Z_IS_1660_EQ_1660(...) \, +#define Z_IS_1661_EQ_1661(...) \, +#define Z_IS_1662_EQ_1662(...) \, +#define Z_IS_1663_EQ_1663(...) \, +#define Z_IS_1664_EQ_1664(...) \, +#define Z_IS_1665_EQ_1665(...) \, +#define Z_IS_1666_EQ_1666(...) \, +#define Z_IS_1667_EQ_1667(...) \, +#define Z_IS_1668_EQ_1668(...) \, +#define Z_IS_1669_EQ_1669(...) \, +#define Z_IS_1670_EQ_1670(...) \, +#define Z_IS_1671_EQ_1671(...) \, +#define Z_IS_1672_EQ_1672(...) \, +#define Z_IS_1673_EQ_1673(...) \, +#define Z_IS_1674_EQ_1674(...) \, +#define Z_IS_1675_EQ_1675(...) \, +#define Z_IS_1676_EQ_1676(...) \, +#define Z_IS_1677_EQ_1677(...) \, +#define Z_IS_1678_EQ_1678(...) \, +#define Z_IS_1679_EQ_1679(...) \, +#define Z_IS_1680_EQ_1680(...) \, +#define Z_IS_1681_EQ_1681(...) \, +#define Z_IS_1682_EQ_1682(...) \, +#define Z_IS_1683_EQ_1683(...) \, +#define Z_IS_1684_EQ_1684(...) \, +#define Z_IS_1685_EQ_1685(...) \, +#define Z_IS_1686_EQ_1686(...) \, +#define Z_IS_1687_EQ_1687(...) \, +#define Z_IS_1688_EQ_1688(...) \, +#define Z_IS_1689_EQ_1689(...) \, +#define Z_IS_1690_EQ_1690(...) \, +#define Z_IS_1691_EQ_1691(...) \, +#define Z_IS_1692_EQ_1692(...) \, +#define Z_IS_1693_EQ_1693(...) \, +#define Z_IS_1694_EQ_1694(...) \, +#define Z_IS_1695_EQ_1695(...) \, +#define Z_IS_1696_EQ_1696(...) \, +#define Z_IS_1697_EQ_1697(...) \, +#define Z_IS_1698_EQ_1698(...) \, +#define Z_IS_1699_EQ_1699(...) \, +#define Z_IS_1700_EQ_1700(...) \, +#define Z_IS_1701_EQ_1701(...) \, +#define Z_IS_1702_EQ_1702(...) \, +#define Z_IS_1703_EQ_1703(...) \, +#define Z_IS_1704_EQ_1704(...) \, +#define Z_IS_1705_EQ_1705(...) \, +#define Z_IS_1706_EQ_1706(...) \, +#define Z_IS_1707_EQ_1707(...) \, +#define Z_IS_1708_EQ_1708(...) \, +#define Z_IS_1709_EQ_1709(...) \, +#define Z_IS_1710_EQ_1710(...) \, +#define Z_IS_1711_EQ_1711(...) \, +#define Z_IS_1712_EQ_1712(...) \, +#define Z_IS_1713_EQ_1713(...) \, +#define Z_IS_1714_EQ_1714(...) \, +#define Z_IS_1715_EQ_1715(...) \, +#define Z_IS_1716_EQ_1716(...) \, +#define Z_IS_1717_EQ_1717(...) \, +#define Z_IS_1718_EQ_1718(...) \, +#define Z_IS_1719_EQ_1719(...) \, +#define Z_IS_1720_EQ_1720(...) \, +#define Z_IS_1721_EQ_1721(...) \, +#define Z_IS_1722_EQ_1722(...) \, +#define Z_IS_1723_EQ_1723(...) \, +#define Z_IS_1724_EQ_1724(...) \, +#define Z_IS_1725_EQ_1725(...) \, +#define Z_IS_1726_EQ_1726(...) \, +#define Z_IS_1727_EQ_1727(...) \, +#define Z_IS_1728_EQ_1728(...) \, +#define Z_IS_1729_EQ_1729(...) \, +#define Z_IS_1730_EQ_1730(...) \, +#define Z_IS_1731_EQ_1731(...) \, +#define Z_IS_1732_EQ_1732(...) \, +#define Z_IS_1733_EQ_1733(...) \, +#define Z_IS_1734_EQ_1734(...) \, +#define Z_IS_1735_EQ_1735(...) \, +#define Z_IS_1736_EQ_1736(...) \, +#define Z_IS_1737_EQ_1737(...) \, +#define Z_IS_1738_EQ_1738(...) \, +#define Z_IS_1739_EQ_1739(...) \, +#define Z_IS_1740_EQ_1740(...) \, +#define Z_IS_1741_EQ_1741(...) \, +#define Z_IS_1742_EQ_1742(...) \, +#define Z_IS_1743_EQ_1743(...) \, +#define Z_IS_1744_EQ_1744(...) \, +#define Z_IS_1745_EQ_1745(...) \, +#define Z_IS_1746_EQ_1746(...) \, +#define Z_IS_1747_EQ_1747(...) \, +#define Z_IS_1748_EQ_1748(...) \, +#define Z_IS_1749_EQ_1749(...) \, +#define Z_IS_1750_EQ_1750(...) \, +#define Z_IS_1751_EQ_1751(...) \, +#define Z_IS_1752_EQ_1752(...) \, +#define Z_IS_1753_EQ_1753(...) \, +#define Z_IS_1754_EQ_1754(...) \, +#define Z_IS_1755_EQ_1755(...) \, +#define Z_IS_1756_EQ_1756(...) \, +#define Z_IS_1757_EQ_1757(...) \, +#define Z_IS_1758_EQ_1758(...) \, +#define Z_IS_1759_EQ_1759(...) \, +#define Z_IS_1760_EQ_1760(...) \, +#define Z_IS_1761_EQ_1761(...) \, +#define Z_IS_1762_EQ_1762(...) \, +#define Z_IS_1763_EQ_1763(...) \, +#define Z_IS_1764_EQ_1764(...) \, +#define Z_IS_1765_EQ_1765(...) \, +#define Z_IS_1766_EQ_1766(...) \, +#define Z_IS_1767_EQ_1767(...) \, +#define Z_IS_1768_EQ_1768(...) \, +#define Z_IS_1769_EQ_1769(...) \, +#define Z_IS_1770_EQ_1770(...) \, +#define Z_IS_1771_EQ_1771(...) \, +#define Z_IS_1772_EQ_1772(...) \, +#define Z_IS_1773_EQ_1773(...) \, +#define Z_IS_1774_EQ_1774(...) \, +#define Z_IS_1775_EQ_1775(...) \, +#define Z_IS_1776_EQ_1776(...) \, +#define Z_IS_1777_EQ_1777(...) \, +#define Z_IS_1778_EQ_1778(...) \, +#define Z_IS_1779_EQ_1779(...) \, +#define Z_IS_1780_EQ_1780(...) \, +#define Z_IS_1781_EQ_1781(...) \, +#define Z_IS_1782_EQ_1782(...) \, +#define Z_IS_1783_EQ_1783(...) \, +#define Z_IS_1784_EQ_1784(...) \, +#define Z_IS_1785_EQ_1785(...) \, +#define Z_IS_1786_EQ_1786(...) \, +#define Z_IS_1787_EQ_1787(...) \, +#define Z_IS_1788_EQ_1788(...) \, +#define Z_IS_1789_EQ_1789(...) \, +#define Z_IS_1790_EQ_1790(...) \, +#define Z_IS_1791_EQ_1791(...) \, +#define Z_IS_1792_EQ_1792(...) \, +#define Z_IS_1793_EQ_1793(...) \, +#define Z_IS_1794_EQ_1794(...) \, +#define Z_IS_1795_EQ_1795(...) \, +#define Z_IS_1796_EQ_1796(...) \, +#define Z_IS_1797_EQ_1797(...) \, +#define Z_IS_1798_EQ_1798(...) \, +#define Z_IS_1799_EQ_1799(...) \, +#define Z_IS_1800_EQ_1800(...) \, +#define Z_IS_1801_EQ_1801(...) \, +#define Z_IS_1802_EQ_1802(...) \, +#define Z_IS_1803_EQ_1803(...) \, +#define Z_IS_1804_EQ_1804(...) \, +#define Z_IS_1805_EQ_1805(...) \, +#define Z_IS_1806_EQ_1806(...) \, +#define Z_IS_1807_EQ_1807(...) \, +#define Z_IS_1808_EQ_1808(...) \, +#define Z_IS_1809_EQ_1809(...) \, +#define Z_IS_1810_EQ_1810(...) \, +#define Z_IS_1811_EQ_1811(...) \, +#define Z_IS_1812_EQ_1812(...) \, +#define Z_IS_1813_EQ_1813(...) \, +#define Z_IS_1814_EQ_1814(...) \, +#define Z_IS_1815_EQ_1815(...) \, +#define Z_IS_1816_EQ_1816(...) \, +#define Z_IS_1817_EQ_1817(...) \, +#define Z_IS_1818_EQ_1818(...) \, +#define Z_IS_1819_EQ_1819(...) \, +#define Z_IS_1820_EQ_1820(...) \, +#define Z_IS_1821_EQ_1821(...) \, +#define Z_IS_1822_EQ_1822(...) \, +#define Z_IS_1823_EQ_1823(...) \, +#define Z_IS_1824_EQ_1824(...) \, +#define Z_IS_1825_EQ_1825(...) \, +#define Z_IS_1826_EQ_1826(...) \, +#define Z_IS_1827_EQ_1827(...) \, +#define Z_IS_1828_EQ_1828(...) \, +#define Z_IS_1829_EQ_1829(...) \, +#define Z_IS_1830_EQ_1830(...) \, +#define Z_IS_1831_EQ_1831(...) \, +#define Z_IS_1832_EQ_1832(...) \, +#define Z_IS_1833_EQ_1833(...) \, +#define Z_IS_1834_EQ_1834(...) \, +#define Z_IS_1835_EQ_1835(...) \, +#define Z_IS_1836_EQ_1836(...) \, +#define Z_IS_1837_EQ_1837(...) \, +#define Z_IS_1838_EQ_1838(...) \, +#define Z_IS_1839_EQ_1839(...) \, +#define Z_IS_1840_EQ_1840(...) \, +#define Z_IS_1841_EQ_1841(...) \, +#define Z_IS_1842_EQ_1842(...) \, +#define Z_IS_1843_EQ_1843(...) \, +#define Z_IS_1844_EQ_1844(...) \, +#define Z_IS_1845_EQ_1845(...) \, +#define Z_IS_1846_EQ_1846(...) \, +#define Z_IS_1847_EQ_1847(...) \, +#define Z_IS_1848_EQ_1848(...) \, +#define Z_IS_1849_EQ_1849(...) \, +#define Z_IS_1850_EQ_1850(...) \, +#define Z_IS_1851_EQ_1851(...) \, +#define Z_IS_1852_EQ_1852(...) \, +#define Z_IS_1853_EQ_1853(...) \, +#define Z_IS_1854_EQ_1854(...) \, +#define Z_IS_1855_EQ_1855(...) \, +#define Z_IS_1856_EQ_1856(...) \, +#define Z_IS_1857_EQ_1857(...) \, +#define Z_IS_1858_EQ_1858(...) \, +#define Z_IS_1859_EQ_1859(...) \, +#define Z_IS_1860_EQ_1860(...) \, +#define Z_IS_1861_EQ_1861(...) \, +#define Z_IS_1862_EQ_1862(...) \, +#define Z_IS_1863_EQ_1863(...) \, +#define Z_IS_1864_EQ_1864(...) \, +#define Z_IS_1865_EQ_1865(...) \, +#define Z_IS_1866_EQ_1866(...) \, +#define Z_IS_1867_EQ_1867(...) \, +#define Z_IS_1868_EQ_1868(...) \, +#define Z_IS_1869_EQ_1869(...) \, +#define Z_IS_1870_EQ_1870(...) \, +#define Z_IS_1871_EQ_1871(...) \, +#define Z_IS_1872_EQ_1872(...) \, +#define Z_IS_1873_EQ_1873(...) \, +#define Z_IS_1874_EQ_1874(...) \, +#define Z_IS_1875_EQ_1875(...) \, +#define Z_IS_1876_EQ_1876(...) \, +#define Z_IS_1877_EQ_1877(...) \, +#define Z_IS_1878_EQ_1878(...) \, +#define Z_IS_1879_EQ_1879(...) \, +#define Z_IS_1880_EQ_1880(...) \, +#define Z_IS_1881_EQ_1881(...) \, +#define Z_IS_1882_EQ_1882(...) \, +#define Z_IS_1883_EQ_1883(...) \, +#define Z_IS_1884_EQ_1884(...) \, +#define Z_IS_1885_EQ_1885(...) \, +#define Z_IS_1886_EQ_1886(...) \, +#define Z_IS_1887_EQ_1887(...) \, +#define Z_IS_1888_EQ_1888(...) \, +#define Z_IS_1889_EQ_1889(...) \, +#define Z_IS_1890_EQ_1890(...) \, +#define Z_IS_1891_EQ_1891(...) \, +#define Z_IS_1892_EQ_1892(...) \, +#define Z_IS_1893_EQ_1893(...) \, +#define Z_IS_1894_EQ_1894(...) \, +#define Z_IS_1895_EQ_1895(...) \, +#define Z_IS_1896_EQ_1896(...) \, +#define Z_IS_1897_EQ_1897(...) \, +#define Z_IS_1898_EQ_1898(...) \, +#define Z_IS_1899_EQ_1899(...) \, +#define Z_IS_1900_EQ_1900(...) \, +#define Z_IS_1901_EQ_1901(...) \, +#define Z_IS_1902_EQ_1902(...) \, +#define Z_IS_1903_EQ_1903(...) \, +#define Z_IS_1904_EQ_1904(...) \, +#define Z_IS_1905_EQ_1905(...) \, +#define Z_IS_1906_EQ_1906(...) \, +#define Z_IS_1907_EQ_1907(...) \, +#define Z_IS_1908_EQ_1908(...) \, +#define Z_IS_1909_EQ_1909(...) \, +#define Z_IS_1910_EQ_1910(...) \, +#define Z_IS_1911_EQ_1911(...) \, +#define Z_IS_1912_EQ_1912(...) \, +#define Z_IS_1913_EQ_1913(...) \, +#define Z_IS_1914_EQ_1914(...) \, +#define Z_IS_1915_EQ_1915(...) \, +#define Z_IS_1916_EQ_1916(...) \, +#define Z_IS_1917_EQ_1917(...) \, +#define Z_IS_1918_EQ_1918(...) \, +#define Z_IS_1919_EQ_1919(...) \, +#define Z_IS_1920_EQ_1920(...) \, +#define Z_IS_1921_EQ_1921(...) \, +#define Z_IS_1922_EQ_1922(...) \, +#define Z_IS_1923_EQ_1923(...) \, +#define Z_IS_1924_EQ_1924(...) \, +#define Z_IS_1925_EQ_1925(...) \, +#define Z_IS_1926_EQ_1926(...) \, +#define Z_IS_1927_EQ_1927(...) \, +#define Z_IS_1928_EQ_1928(...) \, +#define Z_IS_1929_EQ_1929(...) \, +#define Z_IS_1930_EQ_1930(...) \, +#define Z_IS_1931_EQ_1931(...) \, +#define Z_IS_1932_EQ_1932(...) \, +#define Z_IS_1933_EQ_1933(...) \, +#define Z_IS_1934_EQ_1934(...) \, +#define Z_IS_1935_EQ_1935(...) \, +#define Z_IS_1936_EQ_1936(...) \, +#define Z_IS_1937_EQ_1937(...) \, +#define Z_IS_1938_EQ_1938(...) \, +#define Z_IS_1939_EQ_1939(...) \, +#define Z_IS_1940_EQ_1940(...) \, +#define Z_IS_1941_EQ_1941(...) \, +#define Z_IS_1942_EQ_1942(...) \, +#define Z_IS_1943_EQ_1943(...) \, +#define Z_IS_1944_EQ_1944(...) \, +#define Z_IS_1945_EQ_1945(...) \, +#define Z_IS_1946_EQ_1946(...) \, +#define Z_IS_1947_EQ_1947(...) \, +#define Z_IS_1948_EQ_1948(...) \, +#define Z_IS_1949_EQ_1949(...) \, +#define Z_IS_1950_EQ_1950(...) \, +#define Z_IS_1951_EQ_1951(...) \, +#define Z_IS_1952_EQ_1952(...) \, +#define Z_IS_1953_EQ_1953(...) \, +#define Z_IS_1954_EQ_1954(...) \, +#define Z_IS_1955_EQ_1955(...) \, +#define Z_IS_1956_EQ_1956(...) \, +#define Z_IS_1957_EQ_1957(...) \, +#define Z_IS_1958_EQ_1958(...) \, +#define Z_IS_1959_EQ_1959(...) \, +#define Z_IS_1960_EQ_1960(...) \, +#define Z_IS_1961_EQ_1961(...) \, +#define Z_IS_1962_EQ_1962(...) \, +#define Z_IS_1963_EQ_1963(...) \, +#define Z_IS_1964_EQ_1964(...) \, +#define Z_IS_1965_EQ_1965(...) \, +#define Z_IS_1966_EQ_1966(...) \, +#define Z_IS_1967_EQ_1967(...) \, +#define Z_IS_1968_EQ_1968(...) \, +#define Z_IS_1969_EQ_1969(...) \, +#define Z_IS_1970_EQ_1970(...) \, +#define Z_IS_1971_EQ_1971(...) \, +#define Z_IS_1972_EQ_1972(...) \, +#define Z_IS_1973_EQ_1973(...) \, +#define Z_IS_1974_EQ_1974(...) \, +#define Z_IS_1975_EQ_1975(...) \, +#define Z_IS_1976_EQ_1976(...) \, +#define Z_IS_1977_EQ_1977(...) \, +#define Z_IS_1978_EQ_1978(...) \, +#define Z_IS_1979_EQ_1979(...) \, +#define Z_IS_1980_EQ_1980(...) \, +#define Z_IS_1981_EQ_1981(...) \, +#define Z_IS_1982_EQ_1982(...) \, +#define Z_IS_1983_EQ_1983(...) \, +#define Z_IS_1984_EQ_1984(...) \, +#define Z_IS_1985_EQ_1985(...) \, +#define Z_IS_1986_EQ_1986(...) \, +#define Z_IS_1987_EQ_1987(...) \, +#define Z_IS_1988_EQ_1988(...) \, +#define Z_IS_1989_EQ_1989(...) \, +#define Z_IS_1990_EQ_1990(...) \, +#define Z_IS_1991_EQ_1991(...) \, +#define Z_IS_1992_EQ_1992(...) \, +#define Z_IS_1993_EQ_1993(...) \, +#define Z_IS_1994_EQ_1994(...) \, +#define Z_IS_1995_EQ_1995(...) \, +#define Z_IS_1996_EQ_1996(...) \, +#define Z_IS_1997_EQ_1997(...) \, +#define Z_IS_1998_EQ_1998(...) \, +#define Z_IS_1999_EQ_1999(...) \, +#define Z_IS_2000_EQ_2000(...) \, +#define Z_IS_2001_EQ_2001(...) \, +#define Z_IS_2002_EQ_2002(...) \, +#define Z_IS_2003_EQ_2003(...) \, +#define Z_IS_2004_EQ_2004(...) \, +#define Z_IS_2005_EQ_2005(...) \, +#define Z_IS_2006_EQ_2006(...) \, +#define Z_IS_2007_EQ_2007(...) \, +#define Z_IS_2008_EQ_2008(...) \, +#define Z_IS_2009_EQ_2009(...) \, +#define Z_IS_2010_EQ_2010(...) \, +#define Z_IS_2011_EQ_2011(...) \, +#define Z_IS_2012_EQ_2012(...) \, +#define Z_IS_2013_EQ_2013(...) \, +#define Z_IS_2014_EQ_2014(...) \, +#define Z_IS_2015_EQ_2015(...) \, +#define Z_IS_2016_EQ_2016(...) \, +#define Z_IS_2017_EQ_2017(...) \, +#define Z_IS_2018_EQ_2018(...) \, +#define Z_IS_2019_EQ_2019(...) \, +#define Z_IS_2020_EQ_2020(...) \, +#define Z_IS_2021_EQ_2021(...) \, +#define Z_IS_2022_EQ_2022(...) \, +#define Z_IS_2023_EQ_2023(...) \, +#define Z_IS_2024_EQ_2024(...) \, +#define Z_IS_2025_EQ_2025(...) \, +#define Z_IS_2026_EQ_2026(...) \, +#define Z_IS_2027_EQ_2027(...) \, +#define Z_IS_2028_EQ_2028(...) \, +#define Z_IS_2029_EQ_2029(...) \, +#define Z_IS_2030_EQ_2030(...) \, +#define Z_IS_2031_EQ_2031(...) \, +#define Z_IS_2032_EQ_2032(...) \, +#define Z_IS_2033_EQ_2033(...) \, +#define Z_IS_2034_EQ_2034(...) \, +#define Z_IS_2035_EQ_2035(...) \, +#define Z_IS_2036_EQ_2036(...) \, +#define Z_IS_2037_EQ_2037(...) \, +#define Z_IS_2038_EQ_2038(...) \, +#define Z_IS_2039_EQ_2039(...) \, +#define Z_IS_2040_EQ_2040(...) \, +#define Z_IS_2041_EQ_2041(...) \, +#define Z_IS_2042_EQ_2042(...) \, +#define Z_IS_2043_EQ_2043(...) \, +#define Z_IS_2044_EQ_2044(...) \, +#define Z_IS_2045_EQ_2045(...) \, +#define Z_IS_2046_EQ_2046(...) \, +#define Z_IS_2047_EQ_2047(...) \, +#define Z_IS_2048_EQ_2048(...) \, +#define Z_IS_2049_EQ_2049(...) \, +#define Z_IS_2050_EQ_2050(...) \, +#define Z_IS_2051_EQ_2051(...) \, +#define Z_IS_2052_EQ_2052(...) \, +#define Z_IS_2053_EQ_2053(...) \, +#define Z_IS_2054_EQ_2054(...) \, +#define Z_IS_2055_EQ_2055(...) \, +#define Z_IS_2056_EQ_2056(...) \, +#define Z_IS_2057_EQ_2057(...) \, +#define Z_IS_2058_EQ_2058(...) \, +#define Z_IS_2059_EQ_2059(...) \, +#define Z_IS_2060_EQ_2060(...) \, +#define Z_IS_2061_EQ_2061(...) \, +#define Z_IS_2062_EQ_2062(...) \, +#define Z_IS_2063_EQ_2063(...) \, +#define Z_IS_2064_EQ_2064(...) \, +#define Z_IS_2065_EQ_2065(...) \, +#define Z_IS_2066_EQ_2066(...) \, +#define Z_IS_2067_EQ_2067(...) \, +#define Z_IS_2068_EQ_2068(...) \, +#define Z_IS_2069_EQ_2069(...) \, +#define Z_IS_2070_EQ_2070(...) \, +#define Z_IS_2071_EQ_2071(...) \, +#define Z_IS_2072_EQ_2072(...) \, +#define Z_IS_2073_EQ_2073(...) \, +#define Z_IS_2074_EQ_2074(...) \, +#define Z_IS_2075_EQ_2075(...) \, +#define Z_IS_2076_EQ_2076(...) \, +#define Z_IS_2077_EQ_2077(...) \, +#define Z_IS_2078_EQ_2078(...) \, +#define Z_IS_2079_EQ_2079(...) \, +#define Z_IS_2080_EQ_2080(...) \, +#define Z_IS_2081_EQ_2081(...) \, +#define Z_IS_2082_EQ_2082(...) \, +#define Z_IS_2083_EQ_2083(...) \, +#define Z_IS_2084_EQ_2084(...) \, +#define Z_IS_2085_EQ_2085(...) \, +#define Z_IS_2086_EQ_2086(...) \, +#define Z_IS_2087_EQ_2087(...) \, +#define Z_IS_2088_EQ_2088(...) \, +#define Z_IS_2089_EQ_2089(...) \, +#define Z_IS_2090_EQ_2090(...) \, +#define Z_IS_2091_EQ_2091(...) \, +#define Z_IS_2092_EQ_2092(...) \, +#define Z_IS_2093_EQ_2093(...) \, +#define Z_IS_2094_EQ_2094(...) \, +#define Z_IS_2095_EQ_2095(...) \, +#define Z_IS_2096_EQ_2096(...) \, +#define Z_IS_2097_EQ_2097(...) \, +#define Z_IS_2098_EQ_2098(...) \, +#define Z_IS_2099_EQ_2099(...) \, +#define Z_IS_2100_EQ_2100(...) \, +#define Z_IS_2101_EQ_2101(...) \, +#define Z_IS_2102_EQ_2102(...) \, +#define Z_IS_2103_EQ_2103(...) \, +#define Z_IS_2104_EQ_2104(...) \, +#define Z_IS_2105_EQ_2105(...) \, +#define Z_IS_2106_EQ_2106(...) \, +#define Z_IS_2107_EQ_2107(...) \, +#define Z_IS_2108_EQ_2108(...) \, +#define Z_IS_2109_EQ_2109(...) \, +#define Z_IS_2110_EQ_2110(...) \, +#define Z_IS_2111_EQ_2111(...) \, +#define Z_IS_2112_EQ_2112(...) \, +#define Z_IS_2113_EQ_2113(...) \, +#define Z_IS_2114_EQ_2114(...) \, +#define Z_IS_2115_EQ_2115(...) \, +#define Z_IS_2116_EQ_2116(...) \, +#define Z_IS_2117_EQ_2117(...) \, +#define Z_IS_2118_EQ_2118(...) \, +#define Z_IS_2119_EQ_2119(...) \, +#define Z_IS_2120_EQ_2120(...) \, +#define Z_IS_2121_EQ_2121(...) \, +#define Z_IS_2122_EQ_2122(...) \, +#define Z_IS_2123_EQ_2123(...) \, +#define Z_IS_2124_EQ_2124(...) \, +#define Z_IS_2125_EQ_2125(...) \, +#define Z_IS_2126_EQ_2126(...) \, +#define Z_IS_2127_EQ_2127(...) \, +#define Z_IS_2128_EQ_2128(...) \, +#define Z_IS_2129_EQ_2129(...) \, +#define Z_IS_2130_EQ_2130(...) \, +#define Z_IS_2131_EQ_2131(...) \, +#define Z_IS_2132_EQ_2132(...) \, +#define Z_IS_2133_EQ_2133(...) \, +#define Z_IS_2134_EQ_2134(...) \, +#define Z_IS_2135_EQ_2135(...) \, +#define Z_IS_2136_EQ_2136(...) \, +#define Z_IS_2137_EQ_2137(...) \, +#define Z_IS_2138_EQ_2138(...) \, +#define Z_IS_2139_EQ_2139(...) \, +#define Z_IS_2140_EQ_2140(...) \, +#define Z_IS_2141_EQ_2141(...) \, +#define Z_IS_2142_EQ_2142(...) \, +#define Z_IS_2143_EQ_2143(...) \, +#define Z_IS_2144_EQ_2144(...) \, +#define Z_IS_2145_EQ_2145(...) \, +#define Z_IS_2146_EQ_2146(...) \, +#define Z_IS_2147_EQ_2147(...) \, +#define Z_IS_2148_EQ_2148(...) \, +#define Z_IS_2149_EQ_2149(...) \, +#define Z_IS_2150_EQ_2150(...) \, +#define Z_IS_2151_EQ_2151(...) \, +#define Z_IS_2152_EQ_2152(...) \, +#define Z_IS_2153_EQ_2153(...) \, +#define Z_IS_2154_EQ_2154(...) \, +#define Z_IS_2155_EQ_2155(...) \, +#define Z_IS_2156_EQ_2156(...) \, +#define Z_IS_2157_EQ_2157(...) \, +#define Z_IS_2158_EQ_2158(...) \, +#define Z_IS_2159_EQ_2159(...) \, +#define Z_IS_2160_EQ_2160(...) \, +#define Z_IS_2161_EQ_2161(...) \, +#define Z_IS_2162_EQ_2162(...) \, +#define Z_IS_2163_EQ_2163(...) \, +#define Z_IS_2164_EQ_2164(...) \, +#define Z_IS_2165_EQ_2165(...) \, +#define Z_IS_2166_EQ_2166(...) \, +#define Z_IS_2167_EQ_2167(...) \, +#define Z_IS_2168_EQ_2168(...) \, +#define Z_IS_2169_EQ_2169(...) \, +#define Z_IS_2170_EQ_2170(...) \, +#define Z_IS_2171_EQ_2171(...) \, +#define Z_IS_2172_EQ_2172(...) \, +#define Z_IS_2173_EQ_2173(...) \, +#define Z_IS_2174_EQ_2174(...) \, +#define Z_IS_2175_EQ_2175(...) \, +#define Z_IS_2176_EQ_2176(...) \, +#define Z_IS_2177_EQ_2177(...) \, +#define Z_IS_2178_EQ_2178(...) \, +#define Z_IS_2179_EQ_2179(...) \, +#define Z_IS_2180_EQ_2180(...) \, +#define Z_IS_2181_EQ_2181(...) \, +#define Z_IS_2182_EQ_2182(...) \, +#define Z_IS_2183_EQ_2183(...) \, +#define Z_IS_2184_EQ_2184(...) \, +#define Z_IS_2185_EQ_2185(...) \, +#define Z_IS_2186_EQ_2186(...) \, +#define Z_IS_2187_EQ_2187(...) \, +#define Z_IS_2188_EQ_2188(...) \, +#define Z_IS_2189_EQ_2189(...) \, +#define Z_IS_2190_EQ_2190(...) \, +#define Z_IS_2191_EQ_2191(...) \, +#define Z_IS_2192_EQ_2192(...) \, +#define Z_IS_2193_EQ_2193(...) \, +#define Z_IS_2194_EQ_2194(...) \, +#define Z_IS_2195_EQ_2195(...) \, +#define Z_IS_2196_EQ_2196(...) \, +#define Z_IS_2197_EQ_2197(...) \, +#define Z_IS_2198_EQ_2198(...) \, +#define Z_IS_2199_EQ_2199(...) \, +#define Z_IS_2200_EQ_2200(...) \, +#define Z_IS_2201_EQ_2201(...) \, +#define Z_IS_2202_EQ_2202(...) \, +#define Z_IS_2203_EQ_2203(...) \, +#define Z_IS_2204_EQ_2204(...) \, +#define Z_IS_2205_EQ_2205(...) \, +#define Z_IS_2206_EQ_2206(...) \, +#define Z_IS_2207_EQ_2207(...) \, +#define Z_IS_2208_EQ_2208(...) \, +#define Z_IS_2209_EQ_2209(...) \, +#define Z_IS_2210_EQ_2210(...) \, +#define Z_IS_2211_EQ_2211(...) \, +#define Z_IS_2212_EQ_2212(...) \, +#define Z_IS_2213_EQ_2213(...) \, +#define Z_IS_2214_EQ_2214(...) \, +#define Z_IS_2215_EQ_2215(...) \, +#define Z_IS_2216_EQ_2216(...) \, +#define Z_IS_2217_EQ_2217(...) \, +#define Z_IS_2218_EQ_2218(...) \, +#define Z_IS_2219_EQ_2219(...) \, +#define Z_IS_2220_EQ_2220(...) \, +#define Z_IS_2221_EQ_2221(...) \, +#define Z_IS_2222_EQ_2222(...) \, +#define Z_IS_2223_EQ_2223(...) \, +#define Z_IS_2224_EQ_2224(...) \, +#define Z_IS_2225_EQ_2225(...) \, +#define Z_IS_2226_EQ_2226(...) \, +#define Z_IS_2227_EQ_2227(...) \, +#define Z_IS_2228_EQ_2228(...) \, +#define Z_IS_2229_EQ_2229(...) \, +#define Z_IS_2230_EQ_2230(...) \, +#define Z_IS_2231_EQ_2231(...) \, +#define Z_IS_2232_EQ_2232(...) \, +#define Z_IS_2233_EQ_2233(...) \, +#define Z_IS_2234_EQ_2234(...) \, +#define Z_IS_2235_EQ_2235(...) \, +#define Z_IS_2236_EQ_2236(...) \, +#define Z_IS_2237_EQ_2237(...) \, +#define Z_IS_2238_EQ_2238(...) \, +#define Z_IS_2239_EQ_2239(...) \, +#define Z_IS_2240_EQ_2240(...) \, +#define Z_IS_2241_EQ_2241(...) \, +#define Z_IS_2242_EQ_2242(...) \, +#define Z_IS_2243_EQ_2243(...) \, +#define Z_IS_2244_EQ_2244(...) \, +#define Z_IS_2245_EQ_2245(...) \, +#define Z_IS_2246_EQ_2246(...) \, +#define Z_IS_2247_EQ_2247(...) \, +#define Z_IS_2248_EQ_2248(...) \, +#define Z_IS_2249_EQ_2249(...) \, +#define Z_IS_2250_EQ_2250(...) \, +#define Z_IS_2251_EQ_2251(...) \, +#define Z_IS_2252_EQ_2252(...) \, +#define Z_IS_2253_EQ_2253(...) \, +#define Z_IS_2254_EQ_2254(...) \, +#define Z_IS_2255_EQ_2255(...) \, +#define Z_IS_2256_EQ_2256(...) \, +#define Z_IS_2257_EQ_2257(...) \, +#define Z_IS_2258_EQ_2258(...) \, +#define Z_IS_2259_EQ_2259(...) \, +#define Z_IS_2260_EQ_2260(...) \, +#define Z_IS_2261_EQ_2261(...) \, +#define Z_IS_2262_EQ_2262(...) \, +#define Z_IS_2263_EQ_2263(...) \, +#define Z_IS_2264_EQ_2264(...) \, +#define Z_IS_2265_EQ_2265(...) \, +#define Z_IS_2266_EQ_2266(...) \, +#define Z_IS_2267_EQ_2267(...) \, +#define Z_IS_2268_EQ_2268(...) \, +#define Z_IS_2269_EQ_2269(...) \, +#define Z_IS_2270_EQ_2270(...) \, +#define Z_IS_2271_EQ_2271(...) \, +#define Z_IS_2272_EQ_2272(...) \, +#define Z_IS_2273_EQ_2273(...) \, +#define Z_IS_2274_EQ_2274(...) \, +#define Z_IS_2275_EQ_2275(...) \, +#define Z_IS_2276_EQ_2276(...) \, +#define Z_IS_2277_EQ_2277(...) \, +#define Z_IS_2278_EQ_2278(...) \, +#define Z_IS_2279_EQ_2279(...) \, +#define Z_IS_2280_EQ_2280(...) \, +#define Z_IS_2281_EQ_2281(...) \, +#define Z_IS_2282_EQ_2282(...) \, +#define Z_IS_2283_EQ_2283(...) \, +#define Z_IS_2284_EQ_2284(...) \, +#define Z_IS_2285_EQ_2285(...) \, +#define Z_IS_2286_EQ_2286(...) \, +#define Z_IS_2287_EQ_2287(...) \, +#define Z_IS_2288_EQ_2288(...) \, +#define Z_IS_2289_EQ_2289(...) \, +#define Z_IS_2290_EQ_2290(...) \, +#define Z_IS_2291_EQ_2291(...) \, +#define Z_IS_2292_EQ_2292(...) \, +#define Z_IS_2293_EQ_2293(...) \, +#define Z_IS_2294_EQ_2294(...) \, +#define Z_IS_2295_EQ_2295(...) \, +#define Z_IS_2296_EQ_2296(...) \, +#define Z_IS_2297_EQ_2297(...) \, +#define Z_IS_2298_EQ_2298(...) \, +#define Z_IS_2299_EQ_2299(...) \, +#define Z_IS_2300_EQ_2300(...) \, +#define Z_IS_2301_EQ_2301(...) \, +#define Z_IS_2302_EQ_2302(...) \, +#define Z_IS_2303_EQ_2303(...) \, +#define Z_IS_2304_EQ_2304(...) \, +#define Z_IS_2305_EQ_2305(...) \, +#define Z_IS_2306_EQ_2306(...) \, +#define Z_IS_2307_EQ_2307(...) \, +#define Z_IS_2308_EQ_2308(...) \, +#define Z_IS_2309_EQ_2309(...) \, +#define Z_IS_2310_EQ_2310(...) \, +#define Z_IS_2311_EQ_2311(...) \, +#define Z_IS_2312_EQ_2312(...) \, +#define Z_IS_2313_EQ_2313(...) \, +#define Z_IS_2314_EQ_2314(...) \, +#define Z_IS_2315_EQ_2315(...) \, +#define Z_IS_2316_EQ_2316(...) \, +#define Z_IS_2317_EQ_2317(...) \, +#define Z_IS_2318_EQ_2318(...) \, +#define Z_IS_2319_EQ_2319(...) \, +#define Z_IS_2320_EQ_2320(...) \, +#define Z_IS_2321_EQ_2321(...) \, +#define Z_IS_2322_EQ_2322(...) \, +#define Z_IS_2323_EQ_2323(...) \, +#define Z_IS_2324_EQ_2324(...) \, +#define Z_IS_2325_EQ_2325(...) \, +#define Z_IS_2326_EQ_2326(...) \, +#define Z_IS_2327_EQ_2327(...) \, +#define Z_IS_2328_EQ_2328(...) \, +#define Z_IS_2329_EQ_2329(...) \, +#define Z_IS_2330_EQ_2330(...) \, +#define Z_IS_2331_EQ_2331(...) \, +#define Z_IS_2332_EQ_2332(...) \, +#define Z_IS_2333_EQ_2333(...) \, +#define Z_IS_2334_EQ_2334(...) \, +#define Z_IS_2335_EQ_2335(...) \, +#define Z_IS_2336_EQ_2336(...) \, +#define Z_IS_2337_EQ_2337(...) \, +#define Z_IS_2338_EQ_2338(...) \, +#define Z_IS_2339_EQ_2339(...) \, +#define Z_IS_2340_EQ_2340(...) \, +#define Z_IS_2341_EQ_2341(...) \, +#define Z_IS_2342_EQ_2342(...) \, +#define Z_IS_2343_EQ_2343(...) \, +#define Z_IS_2344_EQ_2344(...) \, +#define Z_IS_2345_EQ_2345(...) \, +#define Z_IS_2346_EQ_2346(...) \, +#define Z_IS_2347_EQ_2347(...) \, +#define Z_IS_2348_EQ_2348(...) \, +#define Z_IS_2349_EQ_2349(...) \, +#define Z_IS_2350_EQ_2350(...) \, +#define Z_IS_2351_EQ_2351(...) \, +#define Z_IS_2352_EQ_2352(...) \, +#define Z_IS_2353_EQ_2353(...) \, +#define Z_IS_2354_EQ_2354(...) \, +#define Z_IS_2355_EQ_2355(...) \, +#define Z_IS_2356_EQ_2356(...) \, +#define Z_IS_2357_EQ_2357(...) \, +#define Z_IS_2358_EQ_2358(...) \, +#define Z_IS_2359_EQ_2359(...) \, +#define Z_IS_2360_EQ_2360(...) \, +#define Z_IS_2361_EQ_2361(...) \, +#define Z_IS_2362_EQ_2362(...) \, +#define Z_IS_2363_EQ_2363(...) \, +#define Z_IS_2364_EQ_2364(...) \, +#define Z_IS_2365_EQ_2365(...) \, +#define Z_IS_2366_EQ_2366(...) \, +#define Z_IS_2367_EQ_2367(...) \, +#define Z_IS_2368_EQ_2368(...) \, +#define Z_IS_2369_EQ_2369(...) \, +#define Z_IS_2370_EQ_2370(...) \, +#define Z_IS_2371_EQ_2371(...) \, +#define Z_IS_2372_EQ_2372(...) \, +#define Z_IS_2373_EQ_2373(...) \, +#define Z_IS_2374_EQ_2374(...) \, +#define Z_IS_2375_EQ_2375(...) \, +#define Z_IS_2376_EQ_2376(...) \, +#define Z_IS_2377_EQ_2377(...) \, +#define Z_IS_2378_EQ_2378(...) \, +#define Z_IS_2379_EQ_2379(...) \, +#define Z_IS_2380_EQ_2380(...) \, +#define Z_IS_2381_EQ_2381(...) \, +#define Z_IS_2382_EQ_2382(...) \, +#define Z_IS_2383_EQ_2383(...) \, +#define Z_IS_2384_EQ_2384(...) \, +#define Z_IS_2385_EQ_2385(...) \, +#define Z_IS_2386_EQ_2386(...) \, +#define Z_IS_2387_EQ_2387(...) \, +#define Z_IS_2388_EQ_2388(...) \, +#define Z_IS_2389_EQ_2389(...) \, +#define Z_IS_2390_EQ_2390(...) \, +#define Z_IS_2391_EQ_2391(...) \, +#define Z_IS_2392_EQ_2392(...) \, +#define Z_IS_2393_EQ_2393(...) \, +#define Z_IS_2394_EQ_2394(...) \, +#define Z_IS_2395_EQ_2395(...) \, +#define Z_IS_2396_EQ_2396(...) \, +#define Z_IS_2397_EQ_2397(...) \, +#define Z_IS_2398_EQ_2398(...) \, +#define Z_IS_2399_EQ_2399(...) \, +#define Z_IS_2400_EQ_2400(...) \, +#define Z_IS_2401_EQ_2401(...) \, +#define Z_IS_2402_EQ_2402(...) \, +#define Z_IS_2403_EQ_2403(...) \, +#define Z_IS_2404_EQ_2404(...) \, +#define Z_IS_2405_EQ_2405(...) \, +#define Z_IS_2406_EQ_2406(...) \, +#define Z_IS_2407_EQ_2407(...) \, +#define Z_IS_2408_EQ_2408(...) \, +#define Z_IS_2409_EQ_2409(...) \, +#define Z_IS_2410_EQ_2410(...) \, +#define Z_IS_2411_EQ_2411(...) \, +#define Z_IS_2412_EQ_2412(...) \, +#define Z_IS_2413_EQ_2413(...) \, +#define Z_IS_2414_EQ_2414(...) \, +#define Z_IS_2415_EQ_2415(...) \, +#define Z_IS_2416_EQ_2416(...) \, +#define Z_IS_2417_EQ_2417(...) \, +#define Z_IS_2418_EQ_2418(...) \, +#define Z_IS_2419_EQ_2419(...) \, +#define Z_IS_2420_EQ_2420(...) \, +#define Z_IS_2421_EQ_2421(...) \, +#define Z_IS_2422_EQ_2422(...) \, +#define Z_IS_2423_EQ_2423(...) \, +#define Z_IS_2424_EQ_2424(...) \, +#define Z_IS_2425_EQ_2425(...) \, +#define Z_IS_2426_EQ_2426(...) \, +#define Z_IS_2427_EQ_2427(...) \, +#define Z_IS_2428_EQ_2428(...) \, +#define Z_IS_2429_EQ_2429(...) \, +#define Z_IS_2430_EQ_2430(...) \, +#define Z_IS_2431_EQ_2431(...) \, +#define Z_IS_2432_EQ_2432(...) \, +#define Z_IS_2433_EQ_2433(...) \, +#define Z_IS_2434_EQ_2434(...) \, +#define Z_IS_2435_EQ_2435(...) \, +#define Z_IS_2436_EQ_2436(...) \, +#define Z_IS_2437_EQ_2437(...) \, +#define Z_IS_2438_EQ_2438(...) \, +#define Z_IS_2439_EQ_2439(...) \, +#define Z_IS_2440_EQ_2440(...) \, +#define Z_IS_2441_EQ_2441(...) \, +#define Z_IS_2442_EQ_2442(...) \, +#define Z_IS_2443_EQ_2443(...) \, +#define Z_IS_2444_EQ_2444(...) \, +#define Z_IS_2445_EQ_2445(...) \, +#define Z_IS_2446_EQ_2446(...) \, +#define Z_IS_2447_EQ_2447(...) \, +#define Z_IS_2448_EQ_2448(...) \, +#define Z_IS_2449_EQ_2449(...) \, +#define Z_IS_2450_EQ_2450(...) \, +#define Z_IS_2451_EQ_2451(...) \, +#define Z_IS_2452_EQ_2452(...) \, +#define Z_IS_2453_EQ_2453(...) \, +#define Z_IS_2454_EQ_2454(...) \, +#define Z_IS_2455_EQ_2455(...) \, +#define Z_IS_2456_EQ_2456(...) \, +#define Z_IS_2457_EQ_2457(...) \, +#define Z_IS_2458_EQ_2458(...) \, +#define Z_IS_2459_EQ_2459(...) \, +#define Z_IS_2460_EQ_2460(...) \, +#define Z_IS_2461_EQ_2461(...) \, +#define Z_IS_2462_EQ_2462(...) \, +#define Z_IS_2463_EQ_2463(...) \, +#define Z_IS_2464_EQ_2464(...) \, +#define Z_IS_2465_EQ_2465(...) \, +#define Z_IS_2466_EQ_2466(...) \, +#define Z_IS_2467_EQ_2467(...) \, +#define Z_IS_2468_EQ_2468(...) \, +#define Z_IS_2469_EQ_2469(...) \, +#define Z_IS_2470_EQ_2470(...) \, +#define Z_IS_2471_EQ_2471(...) \, +#define Z_IS_2472_EQ_2472(...) \, +#define Z_IS_2473_EQ_2473(...) \, +#define Z_IS_2474_EQ_2474(...) \, +#define Z_IS_2475_EQ_2475(...) \, +#define Z_IS_2476_EQ_2476(...) \, +#define Z_IS_2477_EQ_2477(...) \, +#define Z_IS_2478_EQ_2478(...) \, +#define Z_IS_2479_EQ_2479(...) \, +#define Z_IS_2480_EQ_2480(...) \, +#define Z_IS_2481_EQ_2481(...) \, +#define Z_IS_2482_EQ_2482(...) \, +#define Z_IS_2483_EQ_2483(...) \, +#define Z_IS_2484_EQ_2484(...) \, +#define Z_IS_2485_EQ_2485(...) \, +#define Z_IS_2486_EQ_2486(...) \, +#define Z_IS_2487_EQ_2487(...) \, +#define Z_IS_2488_EQ_2488(...) \, +#define Z_IS_2489_EQ_2489(...) \, +#define Z_IS_2490_EQ_2490(...) \, +#define Z_IS_2491_EQ_2491(...) \, +#define Z_IS_2492_EQ_2492(...) \, +#define Z_IS_2493_EQ_2493(...) \, +#define Z_IS_2494_EQ_2494(...) \, +#define Z_IS_2495_EQ_2495(...) \, +#define Z_IS_2496_EQ_2496(...) \, +#define Z_IS_2497_EQ_2497(...) \, +#define Z_IS_2498_EQ_2498(...) \, +#define Z_IS_2499_EQ_2499(...) \, +#define Z_IS_2500_EQ_2500(...) \, +#define Z_IS_2501_EQ_2501(...) \, +#define Z_IS_2502_EQ_2502(...) \, +#define Z_IS_2503_EQ_2503(...) \, +#define Z_IS_2504_EQ_2504(...) \, +#define Z_IS_2505_EQ_2505(...) \, +#define Z_IS_2506_EQ_2506(...) \, +#define Z_IS_2507_EQ_2507(...) \, +#define Z_IS_2508_EQ_2508(...) \, +#define Z_IS_2509_EQ_2509(...) \, +#define Z_IS_2510_EQ_2510(...) \, +#define Z_IS_2511_EQ_2511(...) \, +#define Z_IS_2512_EQ_2512(...) \, +#define Z_IS_2513_EQ_2513(...) \, +#define Z_IS_2514_EQ_2514(...) \, +#define Z_IS_2515_EQ_2515(...) \, +#define Z_IS_2516_EQ_2516(...) \, +#define Z_IS_2517_EQ_2517(...) \, +#define Z_IS_2518_EQ_2518(...) \, +#define Z_IS_2519_EQ_2519(...) \, +#define Z_IS_2520_EQ_2520(...) \, +#define Z_IS_2521_EQ_2521(...) \, +#define Z_IS_2522_EQ_2522(...) \, +#define Z_IS_2523_EQ_2523(...) \, +#define Z_IS_2524_EQ_2524(...) \, +#define Z_IS_2525_EQ_2525(...) \, +#define Z_IS_2526_EQ_2526(...) \, +#define Z_IS_2527_EQ_2527(...) \, +#define Z_IS_2528_EQ_2528(...) \, +#define Z_IS_2529_EQ_2529(...) \, +#define Z_IS_2530_EQ_2530(...) \, +#define Z_IS_2531_EQ_2531(...) \, +#define Z_IS_2532_EQ_2532(...) \, +#define Z_IS_2533_EQ_2533(...) \, +#define Z_IS_2534_EQ_2534(...) \, +#define Z_IS_2535_EQ_2535(...) \, +#define Z_IS_2536_EQ_2536(...) \, +#define Z_IS_2537_EQ_2537(...) \, +#define Z_IS_2538_EQ_2538(...) \, +#define Z_IS_2539_EQ_2539(...) \, +#define Z_IS_2540_EQ_2540(...) \, +#define Z_IS_2541_EQ_2541(...) \, +#define Z_IS_2542_EQ_2542(...) \, +#define Z_IS_2543_EQ_2543(...) \, +#define Z_IS_2544_EQ_2544(...) \, +#define Z_IS_2545_EQ_2545(...) \, +#define Z_IS_2546_EQ_2546(...) \, +#define Z_IS_2547_EQ_2547(...) \, +#define Z_IS_2548_EQ_2548(...) \, +#define Z_IS_2549_EQ_2549(...) \, +#define Z_IS_2550_EQ_2550(...) \, +#define Z_IS_2551_EQ_2551(...) \, +#define Z_IS_2552_EQ_2552(...) \, +#define Z_IS_2553_EQ_2553(...) \, +#define Z_IS_2554_EQ_2554(...) \, +#define Z_IS_2555_EQ_2555(...) \, +#define Z_IS_2556_EQ_2556(...) \, +#define Z_IS_2557_EQ_2557(...) \, +#define Z_IS_2558_EQ_2558(...) \, +#define Z_IS_2559_EQ_2559(...) \, +#define Z_IS_2560_EQ_2560(...) \, +#define Z_IS_2561_EQ_2561(...) \, +#define Z_IS_2562_EQ_2562(...) \, +#define Z_IS_2563_EQ_2563(...) \, +#define Z_IS_2564_EQ_2564(...) \, +#define Z_IS_2565_EQ_2565(...) \, +#define Z_IS_2566_EQ_2566(...) \, +#define Z_IS_2567_EQ_2567(...) \, +#define Z_IS_2568_EQ_2568(...) \, +#define Z_IS_2569_EQ_2569(...) \, +#define Z_IS_2570_EQ_2570(...) \, +#define Z_IS_2571_EQ_2571(...) \, +#define Z_IS_2572_EQ_2572(...) \, +#define Z_IS_2573_EQ_2573(...) \, +#define Z_IS_2574_EQ_2574(...) \, +#define Z_IS_2575_EQ_2575(...) \, +#define Z_IS_2576_EQ_2576(...) \, +#define Z_IS_2577_EQ_2577(...) \, +#define Z_IS_2578_EQ_2578(...) \, +#define Z_IS_2579_EQ_2579(...) \, +#define Z_IS_2580_EQ_2580(...) \, +#define Z_IS_2581_EQ_2581(...) \, +#define Z_IS_2582_EQ_2582(...) \, +#define Z_IS_2583_EQ_2583(...) \, +#define Z_IS_2584_EQ_2584(...) \, +#define Z_IS_2585_EQ_2585(...) \, +#define Z_IS_2586_EQ_2586(...) \, +#define Z_IS_2587_EQ_2587(...) \, +#define Z_IS_2588_EQ_2588(...) \, +#define Z_IS_2589_EQ_2589(...) \, +#define Z_IS_2590_EQ_2590(...) \, +#define Z_IS_2591_EQ_2591(...) \, +#define Z_IS_2592_EQ_2592(...) \, +#define Z_IS_2593_EQ_2593(...) \, +#define Z_IS_2594_EQ_2594(...) \, +#define Z_IS_2595_EQ_2595(...) \, +#define Z_IS_2596_EQ_2596(...) \, +#define Z_IS_2597_EQ_2597(...) \, +#define Z_IS_2598_EQ_2598(...) \, +#define Z_IS_2599_EQ_2599(...) \, +#define Z_IS_2600_EQ_2600(...) \, +#define Z_IS_2601_EQ_2601(...) \, +#define Z_IS_2602_EQ_2602(...) \, +#define Z_IS_2603_EQ_2603(...) \, +#define Z_IS_2604_EQ_2604(...) \, +#define Z_IS_2605_EQ_2605(...) \, +#define Z_IS_2606_EQ_2606(...) \, +#define Z_IS_2607_EQ_2607(...) \, +#define Z_IS_2608_EQ_2608(...) \, +#define Z_IS_2609_EQ_2609(...) \, +#define Z_IS_2610_EQ_2610(...) \, +#define Z_IS_2611_EQ_2611(...) \, +#define Z_IS_2612_EQ_2612(...) \, +#define Z_IS_2613_EQ_2613(...) \, +#define Z_IS_2614_EQ_2614(...) \, +#define Z_IS_2615_EQ_2615(...) \, +#define Z_IS_2616_EQ_2616(...) \, +#define Z_IS_2617_EQ_2617(...) \, +#define Z_IS_2618_EQ_2618(...) \, +#define Z_IS_2619_EQ_2619(...) \, +#define Z_IS_2620_EQ_2620(...) \, +#define Z_IS_2621_EQ_2621(...) \, +#define Z_IS_2622_EQ_2622(...) \, +#define Z_IS_2623_EQ_2623(...) \, +#define Z_IS_2624_EQ_2624(...) \, +#define Z_IS_2625_EQ_2625(...) \, +#define Z_IS_2626_EQ_2626(...) \, +#define Z_IS_2627_EQ_2627(...) \, +#define Z_IS_2628_EQ_2628(...) \, +#define Z_IS_2629_EQ_2629(...) \, +#define Z_IS_2630_EQ_2630(...) \, +#define Z_IS_2631_EQ_2631(...) \, +#define Z_IS_2632_EQ_2632(...) \, +#define Z_IS_2633_EQ_2633(...) \, +#define Z_IS_2634_EQ_2634(...) \, +#define Z_IS_2635_EQ_2635(...) \, +#define Z_IS_2636_EQ_2636(...) \, +#define Z_IS_2637_EQ_2637(...) \, +#define Z_IS_2638_EQ_2638(...) \, +#define Z_IS_2639_EQ_2639(...) \, +#define Z_IS_2640_EQ_2640(...) \, +#define Z_IS_2641_EQ_2641(...) \, +#define Z_IS_2642_EQ_2642(...) \, +#define Z_IS_2643_EQ_2643(...) \, +#define Z_IS_2644_EQ_2644(...) \, +#define Z_IS_2645_EQ_2645(...) \, +#define Z_IS_2646_EQ_2646(...) \, +#define Z_IS_2647_EQ_2647(...) \, +#define Z_IS_2648_EQ_2648(...) \, +#define Z_IS_2649_EQ_2649(...) \, +#define Z_IS_2650_EQ_2650(...) \, +#define Z_IS_2651_EQ_2651(...) \, +#define Z_IS_2652_EQ_2652(...) \, +#define Z_IS_2653_EQ_2653(...) \, +#define Z_IS_2654_EQ_2654(...) \, +#define Z_IS_2655_EQ_2655(...) \, +#define Z_IS_2656_EQ_2656(...) \, +#define Z_IS_2657_EQ_2657(...) \, +#define Z_IS_2658_EQ_2658(...) \, +#define Z_IS_2659_EQ_2659(...) \, +#define Z_IS_2660_EQ_2660(...) \, +#define Z_IS_2661_EQ_2661(...) \, +#define Z_IS_2662_EQ_2662(...) \, +#define Z_IS_2663_EQ_2663(...) \, +#define Z_IS_2664_EQ_2664(...) \, +#define Z_IS_2665_EQ_2665(...) \, +#define Z_IS_2666_EQ_2666(...) \, +#define Z_IS_2667_EQ_2667(...) \, +#define Z_IS_2668_EQ_2668(...) \, +#define Z_IS_2669_EQ_2669(...) \, +#define Z_IS_2670_EQ_2670(...) \, +#define Z_IS_2671_EQ_2671(...) \, +#define Z_IS_2672_EQ_2672(...) \, +#define Z_IS_2673_EQ_2673(...) \, +#define Z_IS_2674_EQ_2674(...) \, +#define Z_IS_2675_EQ_2675(...) \, +#define Z_IS_2676_EQ_2676(...) \, +#define Z_IS_2677_EQ_2677(...) \, +#define Z_IS_2678_EQ_2678(...) \, +#define Z_IS_2679_EQ_2679(...) \, +#define Z_IS_2680_EQ_2680(...) \, +#define Z_IS_2681_EQ_2681(...) \, +#define Z_IS_2682_EQ_2682(...) \, +#define Z_IS_2683_EQ_2683(...) \, +#define Z_IS_2684_EQ_2684(...) \, +#define Z_IS_2685_EQ_2685(...) \, +#define Z_IS_2686_EQ_2686(...) \, +#define Z_IS_2687_EQ_2687(...) \, +#define Z_IS_2688_EQ_2688(...) \, +#define Z_IS_2689_EQ_2689(...) \, +#define Z_IS_2690_EQ_2690(...) \, +#define Z_IS_2691_EQ_2691(...) \, +#define Z_IS_2692_EQ_2692(...) \, +#define Z_IS_2693_EQ_2693(...) \, +#define Z_IS_2694_EQ_2694(...) \, +#define Z_IS_2695_EQ_2695(...) \, +#define Z_IS_2696_EQ_2696(...) \, +#define Z_IS_2697_EQ_2697(...) \, +#define Z_IS_2698_EQ_2698(...) \, +#define Z_IS_2699_EQ_2699(...) \, +#define Z_IS_2700_EQ_2700(...) \, +#define Z_IS_2701_EQ_2701(...) \, +#define Z_IS_2702_EQ_2702(...) \, +#define Z_IS_2703_EQ_2703(...) \, +#define Z_IS_2704_EQ_2704(...) \, +#define Z_IS_2705_EQ_2705(...) \, +#define Z_IS_2706_EQ_2706(...) \, +#define Z_IS_2707_EQ_2707(...) \, +#define Z_IS_2708_EQ_2708(...) \, +#define Z_IS_2709_EQ_2709(...) \, +#define Z_IS_2710_EQ_2710(...) \, +#define Z_IS_2711_EQ_2711(...) \, +#define Z_IS_2712_EQ_2712(...) \, +#define Z_IS_2713_EQ_2713(...) \, +#define Z_IS_2714_EQ_2714(...) \, +#define Z_IS_2715_EQ_2715(...) \, +#define Z_IS_2716_EQ_2716(...) \, +#define Z_IS_2717_EQ_2717(...) \, +#define Z_IS_2718_EQ_2718(...) \, +#define Z_IS_2719_EQ_2719(...) \, +#define Z_IS_2720_EQ_2720(...) \, +#define Z_IS_2721_EQ_2721(...) \, +#define Z_IS_2722_EQ_2722(...) \, +#define Z_IS_2723_EQ_2723(...) \, +#define Z_IS_2724_EQ_2724(...) \, +#define Z_IS_2725_EQ_2725(...) \, +#define Z_IS_2726_EQ_2726(...) \, +#define Z_IS_2727_EQ_2727(...) \, +#define Z_IS_2728_EQ_2728(...) \, +#define Z_IS_2729_EQ_2729(...) \, +#define Z_IS_2730_EQ_2730(...) \, +#define Z_IS_2731_EQ_2731(...) \, +#define Z_IS_2732_EQ_2732(...) \, +#define Z_IS_2733_EQ_2733(...) \, +#define Z_IS_2734_EQ_2734(...) \, +#define Z_IS_2735_EQ_2735(...) \, +#define Z_IS_2736_EQ_2736(...) \, +#define Z_IS_2737_EQ_2737(...) \, +#define Z_IS_2738_EQ_2738(...) \, +#define Z_IS_2739_EQ_2739(...) \, +#define Z_IS_2740_EQ_2740(...) \, +#define Z_IS_2741_EQ_2741(...) \, +#define Z_IS_2742_EQ_2742(...) \, +#define Z_IS_2743_EQ_2743(...) \, +#define Z_IS_2744_EQ_2744(...) \, +#define Z_IS_2745_EQ_2745(...) \, +#define Z_IS_2746_EQ_2746(...) \, +#define Z_IS_2747_EQ_2747(...) \, +#define Z_IS_2748_EQ_2748(...) \, +#define Z_IS_2749_EQ_2749(...) \, +#define Z_IS_2750_EQ_2750(...) \, +#define Z_IS_2751_EQ_2751(...) \, +#define Z_IS_2752_EQ_2752(...) \, +#define Z_IS_2753_EQ_2753(...) \, +#define Z_IS_2754_EQ_2754(...) \, +#define Z_IS_2755_EQ_2755(...) \, +#define Z_IS_2756_EQ_2756(...) \, +#define Z_IS_2757_EQ_2757(...) \, +#define Z_IS_2758_EQ_2758(...) \, +#define Z_IS_2759_EQ_2759(...) \, +#define Z_IS_2760_EQ_2760(...) \, +#define Z_IS_2761_EQ_2761(...) \, +#define Z_IS_2762_EQ_2762(...) \, +#define Z_IS_2763_EQ_2763(...) \, +#define Z_IS_2764_EQ_2764(...) \, +#define Z_IS_2765_EQ_2765(...) \, +#define Z_IS_2766_EQ_2766(...) \, +#define Z_IS_2767_EQ_2767(...) \, +#define Z_IS_2768_EQ_2768(...) \, +#define Z_IS_2769_EQ_2769(...) \, +#define Z_IS_2770_EQ_2770(...) \, +#define Z_IS_2771_EQ_2771(...) \, +#define Z_IS_2772_EQ_2772(...) \, +#define Z_IS_2773_EQ_2773(...) \, +#define Z_IS_2774_EQ_2774(...) \, +#define Z_IS_2775_EQ_2775(...) \, +#define Z_IS_2776_EQ_2776(...) \, +#define Z_IS_2777_EQ_2777(...) \, +#define Z_IS_2778_EQ_2778(...) \, +#define Z_IS_2779_EQ_2779(...) \, +#define Z_IS_2780_EQ_2780(...) \, +#define Z_IS_2781_EQ_2781(...) \, +#define Z_IS_2782_EQ_2782(...) \, +#define Z_IS_2783_EQ_2783(...) \, +#define Z_IS_2784_EQ_2784(...) \, +#define Z_IS_2785_EQ_2785(...) \, +#define Z_IS_2786_EQ_2786(...) \, +#define Z_IS_2787_EQ_2787(...) \, +#define Z_IS_2788_EQ_2788(...) \, +#define Z_IS_2789_EQ_2789(...) \, +#define Z_IS_2790_EQ_2790(...) \, +#define Z_IS_2791_EQ_2791(...) \, +#define Z_IS_2792_EQ_2792(...) \, +#define Z_IS_2793_EQ_2793(...) \, +#define Z_IS_2794_EQ_2794(...) \, +#define Z_IS_2795_EQ_2795(...) \, +#define Z_IS_2796_EQ_2796(...) \, +#define Z_IS_2797_EQ_2797(...) \, +#define Z_IS_2798_EQ_2798(...) \, +#define Z_IS_2799_EQ_2799(...) \, +#define Z_IS_2800_EQ_2800(...) \, +#define Z_IS_2801_EQ_2801(...) \, +#define Z_IS_2802_EQ_2802(...) \, +#define Z_IS_2803_EQ_2803(...) \, +#define Z_IS_2804_EQ_2804(...) \, +#define Z_IS_2805_EQ_2805(...) \, +#define Z_IS_2806_EQ_2806(...) \, +#define Z_IS_2807_EQ_2807(...) \, +#define Z_IS_2808_EQ_2808(...) \, +#define Z_IS_2809_EQ_2809(...) \, +#define Z_IS_2810_EQ_2810(...) \, +#define Z_IS_2811_EQ_2811(...) \, +#define Z_IS_2812_EQ_2812(...) \, +#define Z_IS_2813_EQ_2813(...) \, +#define Z_IS_2814_EQ_2814(...) \, +#define Z_IS_2815_EQ_2815(...) \, +#define Z_IS_2816_EQ_2816(...) \, +#define Z_IS_2817_EQ_2817(...) \, +#define Z_IS_2818_EQ_2818(...) \, +#define Z_IS_2819_EQ_2819(...) \, +#define Z_IS_2820_EQ_2820(...) \, +#define Z_IS_2821_EQ_2821(...) \, +#define Z_IS_2822_EQ_2822(...) \, +#define Z_IS_2823_EQ_2823(...) \, +#define Z_IS_2824_EQ_2824(...) \, +#define Z_IS_2825_EQ_2825(...) \, +#define Z_IS_2826_EQ_2826(...) \, +#define Z_IS_2827_EQ_2827(...) \, +#define Z_IS_2828_EQ_2828(...) \, +#define Z_IS_2829_EQ_2829(...) \, +#define Z_IS_2830_EQ_2830(...) \, +#define Z_IS_2831_EQ_2831(...) \, +#define Z_IS_2832_EQ_2832(...) \, +#define Z_IS_2833_EQ_2833(...) \, +#define Z_IS_2834_EQ_2834(...) \, +#define Z_IS_2835_EQ_2835(...) \, +#define Z_IS_2836_EQ_2836(...) \, +#define Z_IS_2837_EQ_2837(...) \, +#define Z_IS_2838_EQ_2838(...) \, +#define Z_IS_2839_EQ_2839(...) \, +#define Z_IS_2840_EQ_2840(...) \, +#define Z_IS_2841_EQ_2841(...) \, +#define Z_IS_2842_EQ_2842(...) \, +#define Z_IS_2843_EQ_2843(...) \, +#define Z_IS_2844_EQ_2844(...) \, +#define Z_IS_2845_EQ_2845(...) \, +#define Z_IS_2846_EQ_2846(...) \, +#define Z_IS_2847_EQ_2847(...) \, +#define Z_IS_2848_EQ_2848(...) \, +#define Z_IS_2849_EQ_2849(...) \, +#define Z_IS_2850_EQ_2850(...) \, +#define Z_IS_2851_EQ_2851(...) \, +#define Z_IS_2852_EQ_2852(...) \, +#define Z_IS_2853_EQ_2853(...) \, +#define Z_IS_2854_EQ_2854(...) \, +#define Z_IS_2855_EQ_2855(...) \, +#define Z_IS_2856_EQ_2856(...) \, +#define Z_IS_2857_EQ_2857(...) \, +#define Z_IS_2858_EQ_2858(...) \, +#define Z_IS_2859_EQ_2859(...) \, +#define Z_IS_2860_EQ_2860(...) \, +#define Z_IS_2861_EQ_2861(...) \, +#define Z_IS_2862_EQ_2862(...) \, +#define Z_IS_2863_EQ_2863(...) \, +#define Z_IS_2864_EQ_2864(...) \, +#define Z_IS_2865_EQ_2865(...) \, +#define Z_IS_2866_EQ_2866(...) \, +#define Z_IS_2867_EQ_2867(...) \, +#define Z_IS_2868_EQ_2868(...) \, +#define Z_IS_2869_EQ_2869(...) \, +#define Z_IS_2870_EQ_2870(...) \, +#define Z_IS_2871_EQ_2871(...) \, +#define Z_IS_2872_EQ_2872(...) \, +#define Z_IS_2873_EQ_2873(...) \, +#define Z_IS_2874_EQ_2874(...) \, +#define Z_IS_2875_EQ_2875(...) \, +#define Z_IS_2876_EQ_2876(...) \, +#define Z_IS_2877_EQ_2877(...) \, +#define Z_IS_2878_EQ_2878(...) \, +#define Z_IS_2879_EQ_2879(...) \, +#define Z_IS_2880_EQ_2880(...) \, +#define Z_IS_2881_EQ_2881(...) \, +#define Z_IS_2882_EQ_2882(...) \, +#define Z_IS_2883_EQ_2883(...) \, +#define Z_IS_2884_EQ_2884(...) \, +#define Z_IS_2885_EQ_2885(...) \, +#define Z_IS_2886_EQ_2886(...) \, +#define Z_IS_2887_EQ_2887(...) \, +#define Z_IS_2888_EQ_2888(...) \, +#define Z_IS_2889_EQ_2889(...) \, +#define Z_IS_2890_EQ_2890(...) \, +#define Z_IS_2891_EQ_2891(...) \, +#define Z_IS_2892_EQ_2892(...) \, +#define Z_IS_2893_EQ_2893(...) \, +#define Z_IS_2894_EQ_2894(...) \, +#define Z_IS_2895_EQ_2895(...) \, +#define Z_IS_2896_EQ_2896(...) \, +#define Z_IS_2897_EQ_2897(...) \, +#define Z_IS_2898_EQ_2898(...) \, +#define Z_IS_2899_EQ_2899(...) \, +#define Z_IS_2900_EQ_2900(...) \, +#define Z_IS_2901_EQ_2901(...) \, +#define Z_IS_2902_EQ_2902(...) \, +#define Z_IS_2903_EQ_2903(...) \, +#define Z_IS_2904_EQ_2904(...) \, +#define Z_IS_2905_EQ_2905(...) \, +#define Z_IS_2906_EQ_2906(...) \, +#define Z_IS_2907_EQ_2907(...) \, +#define Z_IS_2908_EQ_2908(...) \, +#define Z_IS_2909_EQ_2909(...) \, +#define Z_IS_2910_EQ_2910(...) \, +#define Z_IS_2911_EQ_2911(...) \, +#define Z_IS_2912_EQ_2912(...) \, +#define Z_IS_2913_EQ_2913(...) \, +#define Z_IS_2914_EQ_2914(...) \, +#define Z_IS_2915_EQ_2915(...) \, +#define Z_IS_2916_EQ_2916(...) \, +#define Z_IS_2917_EQ_2917(...) \, +#define Z_IS_2918_EQ_2918(...) \, +#define Z_IS_2919_EQ_2919(...) \, +#define Z_IS_2920_EQ_2920(...) \, +#define Z_IS_2921_EQ_2921(...) \, +#define Z_IS_2922_EQ_2922(...) \, +#define Z_IS_2923_EQ_2923(...) \, +#define Z_IS_2924_EQ_2924(...) \, +#define Z_IS_2925_EQ_2925(...) \, +#define Z_IS_2926_EQ_2926(...) \, +#define Z_IS_2927_EQ_2927(...) \, +#define Z_IS_2928_EQ_2928(...) \, +#define Z_IS_2929_EQ_2929(...) \, +#define Z_IS_2930_EQ_2930(...) \, +#define Z_IS_2931_EQ_2931(...) \, +#define Z_IS_2932_EQ_2932(...) \, +#define Z_IS_2933_EQ_2933(...) \, +#define Z_IS_2934_EQ_2934(...) \, +#define Z_IS_2935_EQ_2935(...) \, +#define Z_IS_2936_EQ_2936(...) \, +#define Z_IS_2937_EQ_2937(...) \, +#define Z_IS_2938_EQ_2938(...) \, +#define Z_IS_2939_EQ_2939(...) \, +#define Z_IS_2940_EQ_2940(...) \, +#define Z_IS_2941_EQ_2941(...) \, +#define Z_IS_2942_EQ_2942(...) \, +#define Z_IS_2943_EQ_2943(...) \, +#define Z_IS_2944_EQ_2944(...) \, +#define Z_IS_2945_EQ_2945(...) \, +#define Z_IS_2946_EQ_2946(...) \, +#define Z_IS_2947_EQ_2947(...) \, +#define Z_IS_2948_EQ_2948(...) \, +#define Z_IS_2949_EQ_2949(...) \, +#define Z_IS_2950_EQ_2950(...) \, +#define Z_IS_2951_EQ_2951(...) \, +#define Z_IS_2952_EQ_2952(...) \, +#define Z_IS_2953_EQ_2953(...) \, +#define Z_IS_2954_EQ_2954(...) \, +#define Z_IS_2955_EQ_2955(...) \, +#define Z_IS_2956_EQ_2956(...) \, +#define Z_IS_2957_EQ_2957(...) \, +#define Z_IS_2958_EQ_2958(...) \, +#define Z_IS_2959_EQ_2959(...) \, +#define Z_IS_2960_EQ_2960(...) \, +#define Z_IS_2961_EQ_2961(...) \, +#define Z_IS_2962_EQ_2962(...) \, +#define Z_IS_2963_EQ_2963(...) \, +#define Z_IS_2964_EQ_2964(...) \, +#define Z_IS_2965_EQ_2965(...) \, +#define Z_IS_2966_EQ_2966(...) \, +#define Z_IS_2967_EQ_2967(...) \, +#define Z_IS_2968_EQ_2968(...) \, +#define Z_IS_2969_EQ_2969(...) \, +#define Z_IS_2970_EQ_2970(...) \, +#define Z_IS_2971_EQ_2971(...) \, +#define Z_IS_2972_EQ_2972(...) \, +#define Z_IS_2973_EQ_2973(...) \, +#define Z_IS_2974_EQ_2974(...) \, +#define Z_IS_2975_EQ_2975(...) \, +#define Z_IS_2976_EQ_2976(...) \, +#define Z_IS_2977_EQ_2977(...) \, +#define Z_IS_2978_EQ_2978(...) \, +#define Z_IS_2979_EQ_2979(...) \, +#define Z_IS_2980_EQ_2980(...) \, +#define Z_IS_2981_EQ_2981(...) \, +#define Z_IS_2982_EQ_2982(...) \, +#define Z_IS_2983_EQ_2983(...) \, +#define Z_IS_2984_EQ_2984(...) \, +#define Z_IS_2985_EQ_2985(...) \, +#define Z_IS_2986_EQ_2986(...) \, +#define Z_IS_2987_EQ_2987(...) \, +#define Z_IS_2988_EQ_2988(...) \, +#define Z_IS_2989_EQ_2989(...) \, +#define Z_IS_2990_EQ_2990(...) \, +#define Z_IS_2991_EQ_2991(...) \, +#define Z_IS_2992_EQ_2992(...) \, +#define Z_IS_2993_EQ_2993(...) \, +#define Z_IS_2994_EQ_2994(...) \, +#define Z_IS_2995_EQ_2995(...) \, +#define Z_IS_2996_EQ_2996(...) \, +#define Z_IS_2997_EQ_2997(...) \, +#define Z_IS_2998_EQ_2998(...) \, +#define Z_IS_2999_EQ_2999(...) \, +#define Z_IS_3000_EQ_3000(...) \, +#define Z_IS_3001_EQ_3001(...) \, +#define Z_IS_3002_EQ_3002(...) \, +#define Z_IS_3003_EQ_3003(...) \, +#define Z_IS_3004_EQ_3004(...) \, +#define Z_IS_3005_EQ_3005(...) \, +#define Z_IS_3006_EQ_3006(...) \, +#define Z_IS_3007_EQ_3007(...) \, +#define Z_IS_3008_EQ_3008(...) \, +#define Z_IS_3009_EQ_3009(...) \, +#define Z_IS_3010_EQ_3010(...) \, +#define Z_IS_3011_EQ_3011(...) \, +#define Z_IS_3012_EQ_3012(...) \, +#define Z_IS_3013_EQ_3013(...) \, +#define Z_IS_3014_EQ_3014(...) \, +#define Z_IS_3015_EQ_3015(...) \, +#define Z_IS_3016_EQ_3016(...) \, +#define Z_IS_3017_EQ_3017(...) \, +#define Z_IS_3018_EQ_3018(...) \, +#define Z_IS_3019_EQ_3019(...) \, +#define Z_IS_3020_EQ_3020(...) \, +#define Z_IS_3021_EQ_3021(...) \, +#define Z_IS_3022_EQ_3022(...) \, +#define Z_IS_3023_EQ_3023(...) \, +#define Z_IS_3024_EQ_3024(...) \, +#define Z_IS_3025_EQ_3025(...) \, +#define Z_IS_3026_EQ_3026(...) \, +#define Z_IS_3027_EQ_3027(...) \, +#define Z_IS_3028_EQ_3028(...) \, +#define Z_IS_3029_EQ_3029(...) \, +#define Z_IS_3030_EQ_3030(...) \, +#define Z_IS_3031_EQ_3031(...) \, +#define Z_IS_3032_EQ_3032(...) \, +#define Z_IS_3033_EQ_3033(...) \, +#define Z_IS_3034_EQ_3034(...) \, +#define Z_IS_3035_EQ_3035(...) \, +#define Z_IS_3036_EQ_3036(...) \, +#define Z_IS_3037_EQ_3037(...) \, +#define Z_IS_3038_EQ_3038(...) \, +#define Z_IS_3039_EQ_3039(...) \, +#define Z_IS_3040_EQ_3040(...) \, +#define Z_IS_3041_EQ_3041(...) \, +#define Z_IS_3042_EQ_3042(...) \, +#define Z_IS_3043_EQ_3043(...) \, +#define Z_IS_3044_EQ_3044(...) \, +#define Z_IS_3045_EQ_3045(...) \, +#define Z_IS_3046_EQ_3046(...) \, +#define Z_IS_3047_EQ_3047(...) \, +#define Z_IS_3048_EQ_3048(...) \, +#define Z_IS_3049_EQ_3049(...) \, +#define Z_IS_3050_EQ_3050(...) \, +#define Z_IS_3051_EQ_3051(...) \, +#define Z_IS_3052_EQ_3052(...) \, +#define Z_IS_3053_EQ_3053(...) \, +#define Z_IS_3054_EQ_3054(...) \, +#define Z_IS_3055_EQ_3055(...) \, +#define Z_IS_3056_EQ_3056(...) \, +#define Z_IS_3057_EQ_3057(...) \, +#define Z_IS_3058_EQ_3058(...) \, +#define Z_IS_3059_EQ_3059(...) \, +#define Z_IS_3060_EQ_3060(...) \, +#define Z_IS_3061_EQ_3061(...) \, +#define Z_IS_3062_EQ_3062(...) \, +#define Z_IS_3063_EQ_3063(...) \, +#define Z_IS_3064_EQ_3064(...) \, +#define Z_IS_3065_EQ_3065(...) \, +#define Z_IS_3066_EQ_3066(...) \, +#define Z_IS_3067_EQ_3067(...) \, +#define Z_IS_3068_EQ_3068(...) \, +#define Z_IS_3069_EQ_3069(...) \, +#define Z_IS_3070_EQ_3070(...) \, +#define Z_IS_3071_EQ_3071(...) \, +#define Z_IS_3072_EQ_3072(...) \, +#define Z_IS_3073_EQ_3073(...) \, +#define Z_IS_3074_EQ_3074(...) \, +#define Z_IS_3075_EQ_3075(...) \, +#define Z_IS_3076_EQ_3076(...) \, +#define Z_IS_3077_EQ_3077(...) \, +#define Z_IS_3078_EQ_3078(...) \, +#define Z_IS_3079_EQ_3079(...) \, +#define Z_IS_3080_EQ_3080(...) \, +#define Z_IS_3081_EQ_3081(...) \, +#define Z_IS_3082_EQ_3082(...) \, +#define Z_IS_3083_EQ_3083(...) \, +#define Z_IS_3084_EQ_3084(...) \, +#define Z_IS_3085_EQ_3085(...) \, +#define Z_IS_3086_EQ_3086(...) \, +#define Z_IS_3087_EQ_3087(...) \, +#define Z_IS_3088_EQ_3088(...) \, +#define Z_IS_3089_EQ_3089(...) \, +#define Z_IS_3090_EQ_3090(...) \, +#define Z_IS_3091_EQ_3091(...) \, +#define Z_IS_3092_EQ_3092(...) \, +#define Z_IS_3093_EQ_3093(...) \, +#define Z_IS_3094_EQ_3094(...) \, +#define Z_IS_3095_EQ_3095(...) \, +#define Z_IS_3096_EQ_3096(...) \, +#define Z_IS_3097_EQ_3097(...) \, +#define Z_IS_3098_EQ_3098(...) \, +#define Z_IS_3099_EQ_3099(...) \, +#define Z_IS_3100_EQ_3100(...) \, +#define Z_IS_3101_EQ_3101(...) \, +#define Z_IS_3102_EQ_3102(...) \, +#define Z_IS_3103_EQ_3103(...) \, +#define Z_IS_3104_EQ_3104(...) \, +#define Z_IS_3105_EQ_3105(...) \, +#define Z_IS_3106_EQ_3106(...) \, +#define Z_IS_3107_EQ_3107(...) \, +#define Z_IS_3108_EQ_3108(...) \, +#define Z_IS_3109_EQ_3109(...) \, +#define Z_IS_3110_EQ_3110(...) \, +#define Z_IS_3111_EQ_3111(...) \, +#define Z_IS_3112_EQ_3112(...) \, +#define Z_IS_3113_EQ_3113(...) \, +#define Z_IS_3114_EQ_3114(...) \, +#define Z_IS_3115_EQ_3115(...) \, +#define Z_IS_3116_EQ_3116(...) \, +#define Z_IS_3117_EQ_3117(...) \, +#define Z_IS_3118_EQ_3118(...) \, +#define Z_IS_3119_EQ_3119(...) \, +#define Z_IS_3120_EQ_3120(...) \, +#define Z_IS_3121_EQ_3121(...) \, +#define Z_IS_3122_EQ_3122(...) \, +#define Z_IS_3123_EQ_3123(...) \, +#define Z_IS_3124_EQ_3124(...) \, +#define Z_IS_3125_EQ_3125(...) \, +#define Z_IS_3126_EQ_3126(...) \, +#define Z_IS_3127_EQ_3127(...) \, +#define Z_IS_3128_EQ_3128(...) \, +#define Z_IS_3129_EQ_3129(...) \, +#define Z_IS_3130_EQ_3130(...) \, +#define Z_IS_3131_EQ_3131(...) \, +#define Z_IS_3132_EQ_3132(...) \, +#define Z_IS_3133_EQ_3133(...) \, +#define Z_IS_3134_EQ_3134(...) \, +#define Z_IS_3135_EQ_3135(...) \, +#define Z_IS_3136_EQ_3136(...) \, +#define Z_IS_3137_EQ_3137(...) \, +#define Z_IS_3138_EQ_3138(...) \, +#define Z_IS_3139_EQ_3139(...) \, +#define Z_IS_3140_EQ_3140(...) \, +#define Z_IS_3141_EQ_3141(...) \, +#define Z_IS_3142_EQ_3142(...) \, +#define Z_IS_3143_EQ_3143(...) \, +#define Z_IS_3144_EQ_3144(...) \, +#define Z_IS_3145_EQ_3145(...) \, +#define Z_IS_3146_EQ_3146(...) \, +#define Z_IS_3147_EQ_3147(...) \, +#define Z_IS_3148_EQ_3148(...) \, +#define Z_IS_3149_EQ_3149(...) \, +#define Z_IS_3150_EQ_3150(...) \, +#define Z_IS_3151_EQ_3151(...) \, +#define Z_IS_3152_EQ_3152(...) \, +#define Z_IS_3153_EQ_3153(...) \, +#define Z_IS_3154_EQ_3154(...) \, +#define Z_IS_3155_EQ_3155(...) \, +#define Z_IS_3156_EQ_3156(...) \, +#define Z_IS_3157_EQ_3157(...) \, +#define Z_IS_3158_EQ_3158(...) \, +#define Z_IS_3159_EQ_3159(...) \, +#define Z_IS_3160_EQ_3160(...) \, +#define Z_IS_3161_EQ_3161(...) \, +#define Z_IS_3162_EQ_3162(...) \, +#define Z_IS_3163_EQ_3163(...) \, +#define Z_IS_3164_EQ_3164(...) \, +#define Z_IS_3165_EQ_3165(...) \, +#define Z_IS_3166_EQ_3166(...) \, +#define Z_IS_3167_EQ_3167(...) \, +#define Z_IS_3168_EQ_3168(...) \, +#define Z_IS_3169_EQ_3169(...) \, +#define Z_IS_3170_EQ_3170(...) \, +#define Z_IS_3171_EQ_3171(...) \, +#define Z_IS_3172_EQ_3172(...) \, +#define Z_IS_3173_EQ_3173(...) \, +#define Z_IS_3174_EQ_3174(...) \, +#define Z_IS_3175_EQ_3175(...) \, +#define Z_IS_3176_EQ_3176(...) \, +#define Z_IS_3177_EQ_3177(...) \, +#define Z_IS_3178_EQ_3178(...) \, +#define Z_IS_3179_EQ_3179(...) \, +#define Z_IS_3180_EQ_3180(...) \, +#define Z_IS_3181_EQ_3181(...) \, +#define Z_IS_3182_EQ_3182(...) \, +#define Z_IS_3183_EQ_3183(...) \, +#define Z_IS_3184_EQ_3184(...) \, +#define Z_IS_3185_EQ_3185(...) \, +#define Z_IS_3186_EQ_3186(...) \, +#define Z_IS_3187_EQ_3187(...) \, +#define Z_IS_3188_EQ_3188(...) \, +#define Z_IS_3189_EQ_3189(...) \, +#define Z_IS_3190_EQ_3190(...) \, +#define Z_IS_3191_EQ_3191(...) \, +#define Z_IS_3192_EQ_3192(...) \, +#define Z_IS_3193_EQ_3193(...) \, +#define Z_IS_3194_EQ_3194(...) \, +#define Z_IS_3195_EQ_3195(...) \, +#define Z_IS_3196_EQ_3196(...) \, +#define Z_IS_3197_EQ_3197(...) \, +#define Z_IS_3198_EQ_3198(...) \, +#define Z_IS_3199_EQ_3199(...) \, +#define Z_IS_3200_EQ_3200(...) \, +#define Z_IS_3201_EQ_3201(...) \, +#define Z_IS_3202_EQ_3202(...) \, +#define Z_IS_3203_EQ_3203(...) \, +#define Z_IS_3204_EQ_3204(...) \, +#define Z_IS_3205_EQ_3205(...) \, +#define Z_IS_3206_EQ_3206(...) \, +#define Z_IS_3207_EQ_3207(...) \, +#define Z_IS_3208_EQ_3208(...) \, +#define Z_IS_3209_EQ_3209(...) \, +#define Z_IS_3210_EQ_3210(...) \, +#define Z_IS_3211_EQ_3211(...) \, +#define Z_IS_3212_EQ_3212(...) \, +#define Z_IS_3213_EQ_3213(...) \, +#define Z_IS_3214_EQ_3214(...) \, +#define Z_IS_3215_EQ_3215(...) \, +#define Z_IS_3216_EQ_3216(...) \, +#define Z_IS_3217_EQ_3217(...) \, +#define Z_IS_3218_EQ_3218(...) \, +#define Z_IS_3219_EQ_3219(...) \, +#define Z_IS_3220_EQ_3220(...) \, +#define Z_IS_3221_EQ_3221(...) \, +#define Z_IS_3222_EQ_3222(...) \, +#define Z_IS_3223_EQ_3223(...) \, +#define Z_IS_3224_EQ_3224(...) \, +#define Z_IS_3225_EQ_3225(...) \, +#define Z_IS_3226_EQ_3226(...) \, +#define Z_IS_3227_EQ_3227(...) \, +#define Z_IS_3228_EQ_3228(...) \, +#define Z_IS_3229_EQ_3229(...) \, +#define Z_IS_3230_EQ_3230(...) \, +#define Z_IS_3231_EQ_3231(...) \, +#define Z_IS_3232_EQ_3232(...) \, +#define Z_IS_3233_EQ_3233(...) \, +#define Z_IS_3234_EQ_3234(...) \, +#define Z_IS_3235_EQ_3235(...) \, +#define Z_IS_3236_EQ_3236(...) \, +#define Z_IS_3237_EQ_3237(...) \, +#define Z_IS_3238_EQ_3238(...) \, +#define Z_IS_3239_EQ_3239(...) \, +#define Z_IS_3240_EQ_3240(...) \, +#define Z_IS_3241_EQ_3241(...) \, +#define Z_IS_3242_EQ_3242(...) \, +#define Z_IS_3243_EQ_3243(...) \, +#define Z_IS_3244_EQ_3244(...) \, +#define Z_IS_3245_EQ_3245(...) \, +#define Z_IS_3246_EQ_3246(...) \, +#define Z_IS_3247_EQ_3247(...) \, +#define Z_IS_3248_EQ_3248(...) \, +#define Z_IS_3249_EQ_3249(...) \, +#define Z_IS_3250_EQ_3250(...) \, +#define Z_IS_3251_EQ_3251(...) \, +#define Z_IS_3252_EQ_3252(...) \, +#define Z_IS_3253_EQ_3253(...) \, +#define Z_IS_3254_EQ_3254(...) \, +#define Z_IS_3255_EQ_3255(...) \, +#define Z_IS_3256_EQ_3256(...) \, +#define Z_IS_3257_EQ_3257(...) \, +#define Z_IS_3258_EQ_3258(...) \, +#define Z_IS_3259_EQ_3259(...) \, +#define Z_IS_3260_EQ_3260(...) \, +#define Z_IS_3261_EQ_3261(...) \, +#define Z_IS_3262_EQ_3262(...) \, +#define Z_IS_3263_EQ_3263(...) \, +#define Z_IS_3264_EQ_3264(...) \, +#define Z_IS_3265_EQ_3265(...) \, +#define Z_IS_3266_EQ_3266(...) \, +#define Z_IS_3267_EQ_3267(...) \, +#define Z_IS_3268_EQ_3268(...) \, +#define Z_IS_3269_EQ_3269(...) \, +#define Z_IS_3270_EQ_3270(...) \, +#define Z_IS_3271_EQ_3271(...) \, +#define Z_IS_3272_EQ_3272(...) \, +#define Z_IS_3273_EQ_3273(...) \, +#define Z_IS_3274_EQ_3274(...) \, +#define Z_IS_3275_EQ_3275(...) \, +#define Z_IS_3276_EQ_3276(...) \, +#define Z_IS_3277_EQ_3277(...) \, +#define Z_IS_3278_EQ_3278(...) \, +#define Z_IS_3279_EQ_3279(...) \, +#define Z_IS_3280_EQ_3280(...) \, +#define Z_IS_3281_EQ_3281(...) \, +#define Z_IS_3282_EQ_3282(...) \, +#define Z_IS_3283_EQ_3283(...) \, +#define Z_IS_3284_EQ_3284(...) \, +#define Z_IS_3285_EQ_3285(...) \, +#define Z_IS_3286_EQ_3286(...) \, +#define Z_IS_3287_EQ_3287(...) \, +#define Z_IS_3288_EQ_3288(...) \, +#define Z_IS_3289_EQ_3289(...) \, +#define Z_IS_3290_EQ_3290(...) \, +#define Z_IS_3291_EQ_3291(...) \, +#define Z_IS_3292_EQ_3292(...) \, +#define Z_IS_3293_EQ_3293(...) \, +#define Z_IS_3294_EQ_3294(...) \, +#define Z_IS_3295_EQ_3295(...) \, +#define Z_IS_3296_EQ_3296(...) \, +#define Z_IS_3297_EQ_3297(...) \, +#define Z_IS_3298_EQ_3298(...) \, +#define Z_IS_3299_EQ_3299(...) \, +#define Z_IS_3300_EQ_3300(...) \, +#define Z_IS_3301_EQ_3301(...) \, +#define Z_IS_3302_EQ_3302(...) \, +#define Z_IS_3303_EQ_3303(...) \, +#define Z_IS_3304_EQ_3304(...) \, +#define Z_IS_3305_EQ_3305(...) \, +#define Z_IS_3306_EQ_3306(...) \, +#define Z_IS_3307_EQ_3307(...) \, +#define Z_IS_3308_EQ_3308(...) \, +#define Z_IS_3309_EQ_3309(...) \, +#define Z_IS_3310_EQ_3310(...) \, +#define Z_IS_3311_EQ_3311(...) \, +#define Z_IS_3312_EQ_3312(...) \, +#define Z_IS_3313_EQ_3313(...) \, +#define Z_IS_3314_EQ_3314(...) \, +#define Z_IS_3315_EQ_3315(...) \, +#define Z_IS_3316_EQ_3316(...) \, +#define Z_IS_3317_EQ_3317(...) \, +#define Z_IS_3318_EQ_3318(...) \, +#define Z_IS_3319_EQ_3319(...) \, +#define Z_IS_3320_EQ_3320(...) \, +#define Z_IS_3321_EQ_3321(...) \, +#define Z_IS_3322_EQ_3322(...) \, +#define Z_IS_3323_EQ_3323(...) \, +#define Z_IS_3324_EQ_3324(...) \, +#define Z_IS_3325_EQ_3325(...) \, +#define Z_IS_3326_EQ_3326(...) \, +#define Z_IS_3327_EQ_3327(...) \, +#define Z_IS_3328_EQ_3328(...) \, +#define Z_IS_3329_EQ_3329(...) \, +#define Z_IS_3330_EQ_3330(...) \, +#define Z_IS_3331_EQ_3331(...) \, +#define Z_IS_3332_EQ_3332(...) \, +#define Z_IS_3333_EQ_3333(...) \, +#define Z_IS_3334_EQ_3334(...) \, +#define Z_IS_3335_EQ_3335(...) \, +#define Z_IS_3336_EQ_3336(...) \, +#define Z_IS_3337_EQ_3337(...) \, +#define Z_IS_3338_EQ_3338(...) \, +#define Z_IS_3339_EQ_3339(...) \, +#define Z_IS_3340_EQ_3340(...) \, +#define Z_IS_3341_EQ_3341(...) \, +#define Z_IS_3342_EQ_3342(...) \, +#define Z_IS_3343_EQ_3343(...) \, +#define Z_IS_3344_EQ_3344(...) \, +#define Z_IS_3345_EQ_3345(...) \, +#define Z_IS_3346_EQ_3346(...) \, +#define Z_IS_3347_EQ_3347(...) \, +#define Z_IS_3348_EQ_3348(...) \, +#define Z_IS_3349_EQ_3349(...) \, +#define Z_IS_3350_EQ_3350(...) \, +#define Z_IS_3351_EQ_3351(...) \, +#define Z_IS_3352_EQ_3352(...) \, +#define Z_IS_3353_EQ_3353(...) \, +#define Z_IS_3354_EQ_3354(...) \, +#define Z_IS_3355_EQ_3355(...) \, +#define Z_IS_3356_EQ_3356(...) \, +#define Z_IS_3357_EQ_3357(...) \, +#define Z_IS_3358_EQ_3358(...) \, +#define Z_IS_3359_EQ_3359(...) \, +#define Z_IS_3360_EQ_3360(...) \, +#define Z_IS_3361_EQ_3361(...) \, +#define Z_IS_3362_EQ_3362(...) \, +#define Z_IS_3363_EQ_3363(...) \, +#define Z_IS_3364_EQ_3364(...) \, +#define Z_IS_3365_EQ_3365(...) \, +#define Z_IS_3366_EQ_3366(...) \, +#define Z_IS_3367_EQ_3367(...) \, +#define Z_IS_3368_EQ_3368(...) \, +#define Z_IS_3369_EQ_3369(...) \, +#define Z_IS_3370_EQ_3370(...) \, +#define Z_IS_3371_EQ_3371(...) \, +#define Z_IS_3372_EQ_3372(...) \, +#define Z_IS_3373_EQ_3373(...) \, +#define Z_IS_3374_EQ_3374(...) \, +#define Z_IS_3375_EQ_3375(...) \, +#define Z_IS_3376_EQ_3376(...) \, +#define Z_IS_3377_EQ_3377(...) \, +#define Z_IS_3378_EQ_3378(...) \, +#define Z_IS_3379_EQ_3379(...) \, +#define Z_IS_3380_EQ_3380(...) \, +#define Z_IS_3381_EQ_3381(...) \, +#define Z_IS_3382_EQ_3382(...) \, +#define Z_IS_3383_EQ_3383(...) \, +#define Z_IS_3384_EQ_3384(...) \, +#define Z_IS_3385_EQ_3385(...) \, +#define Z_IS_3386_EQ_3386(...) \, +#define Z_IS_3387_EQ_3387(...) \, +#define Z_IS_3388_EQ_3388(...) \, +#define Z_IS_3389_EQ_3389(...) \, +#define Z_IS_3390_EQ_3390(...) \, +#define Z_IS_3391_EQ_3391(...) \, +#define Z_IS_3392_EQ_3392(...) \, +#define Z_IS_3393_EQ_3393(...) \, +#define Z_IS_3394_EQ_3394(...) \, +#define Z_IS_3395_EQ_3395(...) \, +#define Z_IS_3396_EQ_3396(...) \, +#define Z_IS_3397_EQ_3397(...) \, +#define Z_IS_3398_EQ_3398(...) \, +#define Z_IS_3399_EQ_3399(...) \, +#define Z_IS_3400_EQ_3400(...) \, +#define Z_IS_3401_EQ_3401(...) \, +#define Z_IS_3402_EQ_3402(...) \, +#define Z_IS_3403_EQ_3403(...) \, +#define Z_IS_3404_EQ_3404(...) \, +#define Z_IS_3405_EQ_3405(...) \, +#define Z_IS_3406_EQ_3406(...) \, +#define Z_IS_3407_EQ_3407(...) \, +#define Z_IS_3408_EQ_3408(...) \, +#define Z_IS_3409_EQ_3409(...) \, +#define Z_IS_3410_EQ_3410(...) \, +#define Z_IS_3411_EQ_3411(...) \, +#define Z_IS_3412_EQ_3412(...) \, +#define Z_IS_3413_EQ_3413(...) \, +#define Z_IS_3414_EQ_3414(...) \, +#define Z_IS_3415_EQ_3415(...) \, +#define Z_IS_3416_EQ_3416(...) \, +#define Z_IS_3417_EQ_3417(...) \, +#define Z_IS_3418_EQ_3418(...) \, +#define Z_IS_3419_EQ_3419(...) \, +#define Z_IS_3420_EQ_3420(...) \, +#define Z_IS_3421_EQ_3421(...) \, +#define Z_IS_3422_EQ_3422(...) \, +#define Z_IS_3423_EQ_3423(...) \, +#define Z_IS_3424_EQ_3424(...) \, +#define Z_IS_3425_EQ_3425(...) \, +#define Z_IS_3426_EQ_3426(...) \, +#define Z_IS_3427_EQ_3427(...) \, +#define Z_IS_3428_EQ_3428(...) \, +#define Z_IS_3429_EQ_3429(...) \, +#define Z_IS_3430_EQ_3430(...) \, +#define Z_IS_3431_EQ_3431(...) \, +#define Z_IS_3432_EQ_3432(...) \, +#define Z_IS_3433_EQ_3433(...) \, +#define Z_IS_3434_EQ_3434(...) \, +#define Z_IS_3435_EQ_3435(...) \, +#define Z_IS_3436_EQ_3436(...) \, +#define Z_IS_3437_EQ_3437(...) \, +#define Z_IS_3438_EQ_3438(...) \, +#define Z_IS_3439_EQ_3439(...) \, +#define Z_IS_3440_EQ_3440(...) \, +#define Z_IS_3441_EQ_3441(...) \, +#define Z_IS_3442_EQ_3442(...) \, +#define Z_IS_3443_EQ_3443(...) \, +#define Z_IS_3444_EQ_3444(...) \, +#define Z_IS_3445_EQ_3445(...) \, +#define Z_IS_3446_EQ_3446(...) \, +#define Z_IS_3447_EQ_3447(...) \, +#define Z_IS_3448_EQ_3448(...) \, +#define Z_IS_3449_EQ_3449(...) \, +#define Z_IS_3450_EQ_3450(...) \, +#define Z_IS_3451_EQ_3451(...) \, +#define Z_IS_3452_EQ_3452(...) \, +#define Z_IS_3453_EQ_3453(...) \, +#define Z_IS_3454_EQ_3454(...) \, +#define Z_IS_3455_EQ_3455(...) \, +#define Z_IS_3456_EQ_3456(...) \, +#define Z_IS_3457_EQ_3457(...) \, +#define Z_IS_3458_EQ_3458(...) \, +#define Z_IS_3459_EQ_3459(...) \, +#define Z_IS_3460_EQ_3460(...) \, +#define Z_IS_3461_EQ_3461(...) \, +#define Z_IS_3462_EQ_3462(...) \, +#define Z_IS_3463_EQ_3463(...) \, +#define Z_IS_3464_EQ_3464(...) \, +#define Z_IS_3465_EQ_3465(...) \, +#define Z_IS_3466_EQ_3466(...) \, +#define Z_IS_3467_EQ_3467(...) \, +#define Z_IS_3468_EQ_3468(...) \, +#define Z_IS_3469_EQ_3469(...) \, +#define Z_IS_3470_EQ_3470(...) \, +#define Z_IS_3471_EQ_3471(...) \, +#define Z_IS_3472_EQ_3472(...) \, +#define Z_IS_3473_EQ_3473(...) \, +#define Z_IS_3474_EQ_3474(...) \, +#define Z_IS_3475_EQ_3475(...) \, +#define Z_IS_3476_EQ_3476(...) \, +#define Z_IS_3477_EQ_3477(...) \, +#define Z_IS_3478_EQ_3478(...) \, +#define Z_IS_3479_EQ_3479(...) \, +#define Z_IS_3480_EQ_3480(...) \, +#define Z_IS_3481_EQ_3481(...) \, +#define Z_IS_3482_EQ_3482(...) \, +#define Z_IS_3483_EQ_3483(...) \, +#define Z_IS_3484_EQ_3484(...) \, +#define Z_IS_3485_EQ_3485(...) \, +#define Z_IS_3486_EQ_3486(...) \, +#define Z_IS_3487_EQ_3487(...) \, +#define Z_IS_3488_EQ_3488(...) \, +#define Z_IS_3489_EQ_3489(...) \, +#define Z_IS_3490_EQ_3490(...) \, +#define Z_IS_3491_EQ_3491(...) \, +#define Z_IS_3492_EQ_3492(...) \, +#define Z_IS_3493_EQ_3493(...) \, +#define Z_IS_3494_EQ_3494(...) \, +#define Z_IS_3495_EQ_3495(...) \, +#define Z_IS_3496_EQ_3496(...) \, +#define Z_IS_3497_EQ_3497(...) \, +#define Z_IS_3498_EQ_3498(...) \, +#define Z_IS_3499_EQ_3499(...) \, +#define Z_IS_3500_EQ_3500(...) \, +#define Z_IS_3501_EQ_3501(...) \, +#define Z_IS_3502_EQ_3502(...) \, +#define Z_IS_3503_EQ_3503(...) \, +#define Z_IS_3504_EQ_3504(...) \, +#define Z_IS_3505_EQ_3505(...) \, +#define Z_IS_3506_EQ_3506(...) \, +#define Z_IS_3507_EQ_3507(...) \, +#define Z_IS_3508_EQ_3508(...) \, +#define Z_IS_3509_EQ_3509(...) \, +#define Z_IS_3510_EQ_3510(...) \, +#define Z_IS_3511_EQ_3511(...) \, +#define Z_IS_3512_EQ_3512(...) \, +#define Z_IS_3513_EQ_3513(...) \, +#define Z_IS_3514_EQ_3514(...) \, +#define Z_IS_3515_EQ_3515(...) \, +#define Z_IS_3516_EQ_3516(...) \, +#define Z_IS_3517_EQ_3517(...) \, +#define Z_IS_3518_EQ_3518(...) \, +#define Z_IS_3519_EQ_3519(...) \, +#define Z_IS_3520_EQ_3520(...) \, +#define Z_IS_3521_EQ_3521(...) \, +#define Z_IS_3522_EQ_3522(...) \, +#define Z_IS_3523_EQ_3523(...) \, +#define Z_IS_3524_EQ_3524(...) \, +#define Z_IS_3525_EQ_3525(...) \, +#define Z_IS_3526_EQ_3526(...) \, +#define Z_IS_3527_EQ_3527(...) \, +#define Z_IS_3528_EQ_3528(...) \, +#define Z_IS_3529_EQ_3529(...) \, +#define Z_IS_3530_EQ_3530(...) \, +#define Z_IS_3531_EQ_3531(...) \, +#define Z_IS_3532_EQ_3532(...) \, +#define Z_IS_3533_EQ_3533(...) \, +#define Z_IS_3534_EQ_3534(...) \, +#define Z_IS_3535_EQ_3535(...) \, +#define Z_IS_3536_EQ_3536(...) \, +#define Z_IS_3537_EQ_3537(...) \, +#define Z_IS_3538_EQ_3538(...) \, +#define Z_IS_3539_EQ_3539(...) \, +#define Z_IS_3540_EQ_3540(...) \, +#define Z_IS_3541_EQ_3541(...) \, +#define Z_IS_3542_EQ_3542(...) \, +#define Z_IS_3543_EQ_3543(...) \, +#define Z_IS_3544_EQ_3544(...) \, +#define Z_IS_3545_EQ_3545(...) \, +#define Z_IS_3546_EQ_3546(...) \, +#define Z_IS_3547_EQ_3547(...) \, +#define Z_IS_3548_EQ_3548(...) \, +#define Z_IS_3549_EQ_3549(...) \, +#define Z_IS_3550_EQ_3550(...) \, +#define Z_IS_3551_EQ_3551(...) \, +#define Z_IS_3552_EQ_3552(...) \, +#define Z_IS_3553_EQ_3553(...) \, +#define Z_IS_3554_EQ_3554(...) \, +#define Z_IS_3555_EQ_3555(...) \, +#define Z_IS_3556_EQ_3556(...) \, +#define Z_IS_3557_EQ_3557(...) \, +#define Z_IS_3558_EQ_3558(...) \, +#define Z_IS_3559_EQ_3559(...) \, +#define Z_IS_3560_EQ_3560(...) \, +#define Z_IS_3561_EQ_3561(...) \, +#define Z_IS_3562_EQ_3562(...) \, +#define Z_IS_3563_EQ_3563(...) \, +#define Z_IS_3564_EQ_3564(...) \, +#define Z_IS_3565_EQ_3565(...) \, +#define Z_IS_3566_EQ_3566(...) \, +#define Z_IS_3567_EQ_3567(...) \, +#define Z_IS_3568_EQ_3568(...) \, +#define Z_IS_3569_EQ_3569(...) \, +#define Z_IS_3570_EQ_3570(...) \, +#define Z_IS_3571_EQ_3571(...) \, +#define Z_IS_3572_EQ_3572(...) \, +#define Z_IS_3573_EQ_3573(...) \, +#define Z_IS_3574_EQ_3574(...) \, +#define Z_IS_3575_EQ_3575(...) \, +#define Z_IS_3576_EQ_3576(...) \, +#define Z_IS_3577_EQ_3577(...) \, +#define Z_IS_3578_EQ_3578(...) \, +#define Z_IS_3579_EQ_3579(...) \, +#define Z_IS_3580_EQ_3580(...) \, +#define Z_IS_3581_EQ_3581(...) \, +#define Z_IS_3582_EQ_3582(...) \, +#define Z_IS_3583_EQ_3583(...) \, +#define Z_IS_3584_EQ_3584(...) \, +#define Z_IS_3585_EQ_3585(...) \, +#define Z_IS_3586_EQ_3586(...) \, +#define Z_IS_3587_EQ_3587(...) \, +#define Z_IS_3588_EQ_3588(...) \, +#define Z_IS_3589_EQ_3589(...) \, +#define Z_IS_3590_EQ_3590(...) \, +#define Z_IS_3591_EQ_3591(...) \, +#define Z_IS_3592_EQ_3592(...) \, +#define Z_IS_3593_EQ_3593(...) \, +#define Z_IS_3594_EQ_3594(...) \, +#define Z_IS_3595_EQ_3595(...) \, +#define Z_IS_3596_EQ_3596(...) \, +#define Z_IS_3597_EQ_3597(...) \, +#define Z_IS_3598_EQ_3598(...) \, +#define Z_IS_3599_EQ_3599(...) \, +#define Z_IS_3600_EQ_3600(...) \, +#define Z_IS_3601_EQ_3601(...) \, +#define Z_IS_3602_EQ_3602(...) \, +#define Z_IS_3603_EQ_3603(...) \, +#define Z_IS_3604_EQ_3604(...) \, +#define Z_IS_3605_EQ_3605(...) \, +#define Z_IS_3606_EQ_3606(...) \, +#define Z_IS_3607_EQ_3607(...) \, +#define Z_IS_3608_EQ_3608(...) \, +#define Z_IS_3609_EQ_3609(...) \, +#define Z_IS_3610_EQ_3610(...) \, +#define Z_IS_3611_EQ_3611(...) \, +#define Z_IS_3612_EQ_3612(...) \, +#define Z_IS_3613_EQ_3613(...) \, +#define Z_IS_3614_EQ_3614(...) \, +#define Z_IS_3615_EQ_3615(...) \, +#define Z_IS_3616_EQ_3616(...) \, +#define Z_IS_3617_EQ_3617(...) \, +#define Z_IS_3618_EQ_3618(...) \, +#define Z_IS_3619_EQ_3619(...) \, +#define Z_IS_3620_EQ_3620(...) \, +#define Z_IS_3621_EQ_3621(...) \, +#define Z_IS_3622_EQ_3622(...) \, +#define Z_IS_3623_EQ_3623(...) \, +#define Z_IS_3624_EQ_3624(...) \, +#define Z_IS_3625_EQ_3625(...) \, +#define Z_IS_3626_EQ_3626(...) \, +#define Z_IS_3627_EQ_3627(...) \, +#define Z_IS_3628_EQ_3628(...) \, +#define Z_IS_3629_EQ_3629(...) \, +#define Z_IS_3630_EQ_3630(...) \, +#define Z_IS_3631_EQ_3631(...) \, +#define Z_IS_3632_EQ_3632(...) \, +#define Z_IS_3633_EQ_3633(...) \, +#define Z_IS_3634_EQ_3634(...) \, +#define Z_IS_3635_EQ_3635(...) \, +#define Z_IS_3636_EQ_3636(...) \, +#define Z_IS_3637_EQ_3637(...) \, +#define Z_IS_3638_EQ_3638(...) \, +#define Z_IS_3639_EQ_3639(...) \, +#define Z_IS_3640_EQ_3640(...) \, +#define Z_IS_3641_EQ_3641(...) \, +#define Z_IS_3642_EQ_3642(...) \, +#define Z_IS_3643_EQ_3643(...) \, +#define Z_IS_3644_EQ_3644(...) \, +#define Z_IS_3645_EQ_3645(...) \, +#define Z_IS_3646_EQ_3646(...) \, +#define Z_IS_3647_EQ_3647(...) \, +#define Z_IS_3648_EQ_3648(...) \, +#define Z_IS_3649_EQ_3649(...) \, +#define Z_IS_3650_EQ_3650(...) \, +#define Z_IS_3651_EQ_3651(...) \, +#define Z_IS_3652_EQ_3652(...) \, +#define Z_IS_3653_EQ_3653(...) \, +#define Z_IS_3654_EQ_3654(...) \, +#define Z_IS_3655_EQ_3655(...) \, +#define Z_IS_3656_EQ_3656(...) \, +#define Z_IS_3657_EQ_3657(...) \, +#define Z_IS_3658_EQ_3658(...) \, +#define Z_IS_3659_EQ_3659(...) \, +#define Z_IS_3660_EQ_3660(...) \, +#define Z_IS_3661_EQ_3661(...) \, +#define Z_IS_3662_EQ_3662(...) \, +#define Z_IS_3663_EQ_3663(...) \, +#define Z_IS_3664_EQ_3664(...) \, +#define Z_IS_3665_EQ_3665(...) \, +#define Z_IS_3666_EQ_3666(...) \, +#define Z_IS_3667_EQ_3667(...) \, +#define Z_IS_3668_EQ_3668(...) \, +#define Z_IS_3669_EQ_3669(...) \, +#define Z_IS_3670_EQ_3670(...) \, +#define Z_IS_3671_EQ_3671(...) \, +#define Z_IS_3672_EQ_3672(...) \, +#define Z_IS_3673_EQ_3673(...) \, +#define Z_IS_3674_EQ_3674(...) \, +#define Z_IS_3675_EQ_3675(...) \, +#define Z_IS_3676_EQ_3676(...) \, +#define Z_IS_3677_EQ_3677(...) \, +#define Z_IS_3678_EQ_3678(...) \, +#define Z_IS_3679_EQ_3679(...) \, +#define Z_IS_3680_EQ_3680(...) \, +#define Z_IS_3681_EQ_3681(...) \, +#define Z_IS_3682_EQ_3682(...) \, +#define Z_IS_3683_EQ_3683(...) \, +#define Z_IS_3684_EQ_3684(...) \, +#define Z_IS_3685_EQ_3685(...) \, +#define Z_IS_3686_EQ_3686(...) \, +#define Z_IS_3687_EQ_3687(...) \, +#define Z_IS_3688_EQ_3688(...) \, +#define Z_IS_3689_EQ_3689(...) \, +#define Z_IS_3690_EQ_3690(...) \, +#define Z_IS_3691_EQ_3691(...) \, +#define Z_IS_3692_EQ_3692(...) \, +#define Z_IS_3693_EQ_3693(...) \, +#define Z_IS_3694_EQ_3694(...) \, +#define Z_IS_3695_EQ_3695(...) \, +#define Z_IS_3696_EQ_3696(...) \, +#define Z_IS_3697_EQ_3697(...) \, +#define Z_IS_3698_EQ_3698(...) \, +#define Z_IS_3699_EQ_3699(...) \, +#define Z_IS_3700_EQ_3700(...) \, +#define Z_IS_3701_EQ_3701(...) \, +#define Z_IS_3702_EQ_3702(...) \, +#define Z_IS_3703_EQ_3703(...) \, +#define Z_IS_3704_EQ_3704(...) \, +#define Z_IS_3705_EQ_3705(...) \, +#define Z_IS_3706_EQ_3706(...) \, +#define Z_IS_3707_EQ_3707(...) \, +#define Z_IS_3708_EQ_3708(...) \, +#define Z_IS_3709_EQ_3709(...) \, +#define Z_IS_3710_EQ_3710(...) \, +#define Z_IS_3711_EQ_3711(...) \, +#define Z_IS_3712_EQ_3712(...) \, +#define Z_IS_3713_EQ_3713(...) \, +#define Z_IS_3714_EQ_3714(...) \, +#define Z_IS_3715_EQ_3715(...) \, +#define Z_IS_3716_EQ_3716(...) \, +#define Z_IS_3717_EQ_3717(...) \, +#define Z_IS_3718_EQ_3718(...) \, +#define Z_IS_3719_EQ_3719(...) \, +#define Z_IS_3720_EQ_3720(...) \, +#define Z_IS_3721_EQ_3721(...) \, +#define Z_IS_3722_EQ_3722(...) \, +#define Z_IS_3723_EQ_3723(...) \, +#define Z_IS_3724_EQ_3724(...) \, +#define Z_IS_3725_EQ_3725(...) \, +#define Z_IS_3726_EQ_3726(...) \, +#define Z_IS_3727_EQ_3727(...) \, +#define Z_IS_3728_EQ_3728(...) \, +#define Z_IS_3729_EQ_3729(...) \, +#define Z_IS_3730_EQ_3730(...) \, +#define Z_IS_3731_EQ_3731(...) \, +#define Z_IS_3732_EQ_3732(...) \, +#define Z_IS_3733_EQ_3733(...) \, +#define Z_IS_3734_EQ_3734(...) \, +#define Z_IS_3735_EQ_3735(...) \, +#define Z_IS_3736_EQ_3736(...) \, +#define Z_IS_3737_EQ_3737(...) \, +#define Z_IS_3738_EQ_3738(...) \, +#define Z_IS_3739_EQ_3739(...) \, +#define Z_IS_3740_EQ_3740(...) \, +#define Z_IS_3741_EQ_3741(...) \, +#define Z_IS_3742_EQ_3742(...) \, +#define Z_IS_3743_EQ_3743(...) \, +#define Z_IS_3744_EQ_3744(...) \, +#define Z_IS_3745_EQ_3745(...) \, +#define Z_IS_3746_EQ_3746(...) \, +#define Z_IS_3747_EQ_3747(...) \, +#define Z_IS_3748_EQ_3748(...) \, +#define Z_IS_3749_EQ_3749(...) \, +#define Z_IS_3750_EQ_3750(...) \, +#define Z_IS_3751_EQ_3751(...) \, +#define Z_IS_3752_EQ_3752(...) \, +#define Z_IS_3753_EQ_3753(...) \, +#define Z_IS_3754_EQ_3754(...) \, +#define Z_IS_3755_EQ_3755(...) \, +#define Z_IS_3756_EQ_3756(...) \, +#define Z_IS_3757_EQ_3757(...) \, +#define Z_IS_3758_EQ_3758(...) \, +#define Z_IS_3759_EQ_3759(...) \, +#define Z_IS_3760_EQ_3760(...) \, +#define Z_IS_3761_EQ_3761(...) \, +#define Z_IS_3762_EQ_3762(...) \, +#define Z_IS_3763_EQ_3763(...) \, +#define Z_IS_3764_EQ_3764(...) \, +#define Z_IS_3765_EQ_3765(...) \, +#define Z_IS_3766_EQ_3766(...) \, +#define Z_IS_3767_EQ_3767(...) \, +#define Z_IS_3768_EQ_3768(...) \, +#define Z_IS_3769_EQ_3769(...) \, +#define Z_IS_3770_EQ_3770(...) \, +#define Z_IS_3771_EQ_3771(...) \, +#define Z_IS_3772_EQ_3772(...) \, +#define Z_IS_3773_EQ_3773(...) \, +#define Z_IS_3774_EQ_3774(...) \, +#define Z_IS_3775_EQ_3775(...) \, +#define Z_IS_3776_EQ_3776(...) \, +#define Z_IS_3777_EQ_3777(...) \, +#define Z_IS_3778_EQ_3778(...) \, +#define Z_IS_3779_EQ_3779(...) \, +#define Z_IS_3780_EQ_3780(...) \, +#define Z_IS_3781_EQ_3781(...) \, +#define Z_IS_3782_EQ_3782(...) \, +#define Z_IS_3783_EQ_3783(...) \, +#define Z_IS_3784_EQ_3784(...) \, +#define Z_IS_3785_EQ_3785(...) \, +#define Z_IS_3786_EQ_3786(...) \, +#define Z_IS_3787_EQ_3787(...) \, +#define Z_IS_3788_EQ_3788(...) \, +#define Z_IS_3789_EQ_3789(...) \, +#define Z_IS_3790_EQ_3790(...) \, +#define Z_IS_3791_EQ_3791(...) \, +#define Z_IS_3792_EQ_3792(...) \, +#define Z_IS_3793_EQ_3793(...) \, +#define Z_IS_3794_EQ_3794(...) \, +#define Z_IS_3795_EQ_3795(...) \, +#define Z_IS_3796_EQ_3796(...) \, +#define Z_IS_3797_EQ_3797(...) \, +#define Z_IS_3798_EQ_3798(...) \, +#define Z_IS_3799_EQ_3799(...) \, +#define Z_IS_3800_EQ_3800(...) \, +#define Z_IS_3801_EQ_3801(...) \, +#define Z_IS_3802_EQ_3802(...) \, +#define Z_IS_3803_EQ_3803(...) \, +#define Z_IS_3804_EQ_3804(...) \, +#define Z_IS_3805_EQ_3805(...) \, +#define Z_IS_3806_EQ_3806(...) \, +#define Z_IS_3807_EQ_3807(...) \, +#define Z_IS_3808_EQ_3808(...) \, +#define Z_IS_3809_EQ_3809(...) \, +#define Z_IS_3810_EQ_3810(...) \, +#define Z_IS_3811_EQ_3811(...) \, +#define Z_IS_3812_EQ_3812(...) \, +#define Z_IS_3813_EQ_3813(...) \, +#define Z_IS_3814_EQ_3814(...) \, +#define Z_IS_3815_EQ_3815(...) \, +#define Z_IS_3816_EQ_3816(...) \, +#define Z_IS_3817_EQ_3817(...) \, +#define Z_IS_3818_EQ_3818(...) \, +#define Z_IS_3819_EQ_3819(...) \, +#define Z_IS_3820_EQ_3820(...) \, +#define Z_IS_3821_EQ_3821(...) \, +#define Z_IS_3822_EQ_3822(...) \, +#define Z_IS_3823_EQ_3823(...) \, +#define Z_IS_3824_EQ_3824(...) \, +#define Z_IS_3825_EQ_3825(...) \, +#define Z_IS_3826_EQ_3826(...) \, +#define Z_IS_3827_EQ_3827(...) \, +#define Z_IS_3828_EQ_3828(...) \, +#define Z_IS_3829_EQ_3829(...) \, +#define Z_IS_3830_EQ_3830(...) \, +#define Z_IS_3831_EQ_3831(...) \, +#define Z_IS_3832_EQ_3832(...) \, +#define Z_IS_3833_EQ_3833(...) \, +#define Z_IS_3834_EQ_3834(...) \, +#define Z_IS_3835_EQ_3835(...) \, +#define Z_IS_3836_EQ_3836(...) \, +#define Z_IS_3837_EQ_3837(...) \, +#define Z_IS_3838_EQ_3838(...) \, +#define Z_IS_3839_EQ_3839(...) \, +#define Z_IS_3840_EQ_3840(...) \, +#define Z_IS_3841_EQ_3841(...) \, +#define Z_IS_3842_EQ_3842(...) \, +#define Z_IS_3843_EQ_3843(...) \, +#define Z_IS_3844_EQ_3844(...) \, +#define Z_IS_3845_EQ_3845(...) \, +#define Z_IS_3846_EQ_3846(...) \, +#define Z_IS_3847_EQ_3847(...) \, +#define Z_IS_3848_EQ_3848(...) \, +#define Z_IS_3849_EQ_3849(...) \, +#define Z_IS_3850_EQ_3850(...) \, +#define Z_IS_3851_EQ_3851(...) \, +#define Z_IS_3852_EQ_3852(...) \, +#define Z_IS_3853_EQ_3853(...) \, +#define Z_IS_3854_EQ_3854(...) \, +#define Z_IS_3855_EQ_3855(...) \, +#define Z_IS_3856_EQ_3856(...) \, +#define Z_IS_3857_EQ_3857(...) \, +#define Z_IS_3858_EQ_3858(...) \, +#define Z_IS_3859_EQ_3859(...) \, +#define Z_IS_3860_EQ_3860(...) \, +#define Z_IS_3861_EQ_3861(...) \, +#define Z_IS_3862_EQ_3862(...) \, +#define Z_IS_3863_EQ_3863(...) \, +#define Z_IS_3864_EQ_3864(...) \, +#define Z_IS_3865_EQ_3865(...) \, +#define Z_IS_3866_EQ_3866(...) \, +#define Z_IS_3867_EQ_3867(...) \, +#define Z_IS_3868_EQ_3868(...) \, +#define Z_IS_3869_EQ_3869(...) \, +#define Z_IS_3870_EQ_3870(...) \, +#define Z_IS_3871_EQ_3871(...) \, +#define Z_IS_3872_EQ_3872(...) \, +#define Z_IS_3873_EQ_3873(...) \, +#define Z_IS_3874_EQ_3874(...) \, +#define Z_IS_3875_EQ_3875(...) \, +#define Z_IS_3876_EQ_3876(...) \, +#define Z_IS_3877_EQ_3877(...) \, +#define Z_IS_3878_EQ_3878(...) \, +#define Z_IS_3879_EQ_3879(...) \, +#define Z_IS_3880_EQ_3880(...) \, +#define Z_IS_3881_EQ_3881(...) \, +#define Z_IS_3882_EQ_3882(...) \, +#define Z_IS_3883_EQ_3883(...) \, +#define Z_IS_3884_EQ_3884(...) \, +#define Z_IS_3885_EQ_3885(...) \, +#define Z_IS_3886_EQ_3886(...) \, +#define Z_IS_3887_EQ_3887(...) \, +#define Z_IS_3888_EQ_3888(...) \, +#define Z_IS_3889_EQ_3889(...) \, +#define Z_IS_3890_EQ_3890(...) \, +#define Z_IS_3891_EQ_3891(...) \, +#define Z_IS_3892_EQ_3892(...) \, +#define Z_IS_3893_EQ_3893(...) \, +#define Z_IS_3894_EQ_3894(...) \, +#define Z_IS_3895_EQ_3895(...) \, +#define Z_IS_3896_EQ_3896(...) \, +#define Z_IS_3897_EQ_3897(...) \, +#define Z_IS_3898_EQ_3898(...) \, +#define Z_IS_3899_EQ_3899(...) \, +#define Z_IS_3900_EQ_3900(...) \, +#define Z_IS_3901_EQ_3901(...) \, +#define Z_IS_3902_EQ_3902(...) \, +#define Z_IS_3903_EQ_3903(...) \, +#define Z_IS_3904_EQ_3904(...) \, +#define Z_IS_3905_EQ_3905(...) \, +#define Z_IS_3906_EQ_3906(...) \, +#define Z_IS_3907_EQ_3907(...) \, +#define Z_IS_3908_EQ_3908(...) \, +#define Z_IS_3909_EQ_3909(...) \, +#define Z_IS_3910_EQ_3910(...) \, +#define Z_IS_3911_EQ_3911(...) \, +#define Z_IS_3912_EQ_3912(...) \, +#define Z_IS_3913_EQ_3913(...) \, +#define Z_IS_3914_EQ_3914(...) \, +#define Z_IS_3915_EQ_3915(...) \, +#define Z_IS_3916_EQ_3916(...) \, +#define Z_IS_3917_EQ_3917(...) \, +#define Z_IS_3918_EQ_3918(...) \, +#define Z_IS_3919_EQ_3919(...) \, +#define Z_IS_3920_EQ_3920(...) \, +#define Z_IS_3921_EQ_3921(...) \, +#define Z_IS_3922_EQ_3922(...) \, +#define Z_IS_3923_EQ_3923(...) \, +#define Z_IS_3924_EQ_3924(...) \, +#define Z_IS_3925_EQ_3925(...) \, +#define Z_IS_3926_EQ_3926(...) \, +#define Z_IS_3927_EQ_3927(...) \, +#define Z_IS_3928_EQ_3928(...) \, +#define Z_IS_3929_EQ_3929(...) \, +#define Z_IS_3930_EQ_3930(...) \, +#define Z_IS_3931_EQ_3931(...) \, +#define Z_IS_3932_EQ_3932(...) \, +#define Z_IS_3933_EQ_3933(...) \, +#define Z_IS_3934_EQ_3934(...) \, +#define Z_IS_3935_EQ_3935(...) \, +#define Z_IS_3936_EQ_3936(...) \, +#define Z_IS_3937_EQ_3937(...) \, +#define Z_IS_3938_EQ_3938(...) \, +#define Z_IS_3939_EQ_3939(...) \, +#define Z_IS_3940_EQ_3940(...) \, +#define Z_IS_3941_EQ_3941(...) \, +#define Z_IS_3942_EQ_3942(...) \, +#define Z_IS_3943_EQ_3943(...) \, +#define Z_IS_3944_EQ_3944(...) \, +#define Z_IS_3945_EQ_3945(...) \, +#define Z_IS_3946_EQ_3946(...) \, +#define Z_IS_3947_EQ_3947(...) \, +#define Z_IS_3948_EQ_3948(...) \, +#define Z_IS_3949_EQ_3949(...) \, +#define Z_IS_3950_EQ_3950(...) \, +#define Z_IS_3951_EQ_3951(...) \, +#define Z_IS_3952_EQ_3952(...) \, +#define Z_IS_3953_EQ_3953(...) \, +#define Z_IS_3954_EQ_3954(...) \, +#define Z_IS_3955_EQ_3955(...) \, +#define Z_IS_3956_EQ_3956(...) \, +#define Z_IS_3957_EQ_3957(...) \, +#define Z_IS_3958_EQ_3958(...) \, +#define Z_IS_3959_EQ_3959(...) \, +#define Z_IS_3960_EQ_3960(...) \, +#define Z_IS_3961_EQ_3961(...) \, +#define Z_IS_3962_EQ_3962(...) \, +#define Z_IS_3963_EQ_3963(...) \, +#define Z_IS_3964_EQ_3964(...) \, +#define Z_IS_3965_EQ_3965(...) \, +#define Z_IS_3966_EQ_3966(...) \, +#define Z_IS_3967_EQ_3967(...) \, +#define Z_IS_3968_EQ_3968(...) \, +#define Z_IS_3969_EQ_3969(...) \, +#define Z_IS_3970_EQ_3970(...) \, +#define Z_IS_3971_EQ_3971(...) \, +#define Z_IS_3972_EQ_3972(...) \, +#define Z_IS_3973_EQ_3973(...) \, +#define Z_IS_3974_EQ_3974(...) \, +#define Z_IS_3975_EQ_3975(...) \, +#define Z_IS_3976_EQ_3976(...) \, +#define Z_IS_3977_EQ_3977(...) \, +#define Z_IS_3978_EQ_3978(...) \, +#define Z_IS_3979_EQ_3979(...) \, +#define Z_IS_3980_EQ_3980(...) \, +#define Z_IS_3981_EQ_3981(...) \, +#define Z_IS_3982_EQ_3982(...) \, +#define Z_IS_3983_EQ_3983(...) \, +#define Z_IS_3984_EQ_3984(...) \, +#define Z_IS_3985_EQ_3985(...) \, +#define Z_IS_3986_EQ_3986(...) \, +#define Z_IS_3987_EQ_3987(...) \, +#define Z_IS_3988_EQ_3988(...) \, +#define Z_IS_3989_EQ_3989(...) \, +#define Z_IS_3990_EQ_3990(...) \, +#define Z_IS_3991_EQ_3991(...) \, +#define Z_IS_3992_EQ_3992(...) \, +#define Z_IS_3993_EQ_3993(...) \, +#define Z_IS_3994_EQ_3994(...) \, +#define Z_IS_3995_EQ_3995(...) \, +#define Z_IS_3996_EQ_3996(...) \, +#define Z_IS_3997_EQ_3997(...) \, +#define Z_IS_3998_EQ_3998(...) \, +#define Z_IS_3999_EQ_3999(...) \, +#define Z_IS_4000_EQ_4000(...) \, +#define Z_IS_4001_EQ_4001(...) \, +#define Z_IS_4002_EQ_4002(...) \, +#define Z_IS_4003_EQ_4003(...) \, +#define Z_IS_4004_EQ_4004(...) \, +#define Z_IS_4005_EQ_4005(...) \, +#define Z_IS_4006_EQ_4006(...) \, +#define Z_IS_4007_EQ_4007(...) \, +#define Z_IS_4008_EQ_4008(...) \, +#define Z_IS_4009_EQ_4009(...) \, +#define Z_IS_4010_EQ_4010(...) \, +#define Z_IS_4011_EQ_4011(...) \, +#define Z_IS_4012_EQ_4012(...) \, +#define Z_IS_4013_EQ_4013(...) \, +#define Z_IS_4014_EQ_4014(...) \, +#define Z_IS_4015_EQ_4015(...) \, +#define Z_IS_4016_EQ_4016(...) \, +#define Z_IS_4017_EQ_4017(...) \, +#define Z_IS_4018_EQ_4018(...) \, +#define Z_IS_4019_EQ_4019(...) \, +#define Z_IS_4020_EQ_4020(...) \, +#define Z_IS_4021_EQ_4021(...) \, +#define Z_IS_4022_EQ_4022(...) \, +#define Z_IS_4023_EQ_4023(...) \, +#define Z_IS_4024_EQ_4024(...) \, +#define Z_IS_4025_EQ_4025(...) \, +#define Z_IS_4026_EQ_4026(...) \, +#define Z_IS_4027_EQ_4027(...) \, +#define Z_IS_4028_EQ_4028(...) \, +#define Z_IS_4029_EQ_4029(...) \, +#define Z_IS_4030_EQ_4030(...) \, +#define Z_IS_4031_EQ_4031(...) \, +#define Z_IS_4032_EQ_4032(...) \, +#define Z_IS_4033_EQ_4033(...) \, +#define Z_IS_4034_EQ_4034(...) \, +#define Z_IS_4035_EQ_4035(...) \, +#define Z_IS_4036_EQ_4036(...) \, +#define Z_IS_4037_EQ_4037(...) \, +#define Z_IS_4038_EQ_4038(...) \, +#define Z_IS_4039_EQ_4039(...) \, +#define Z_IS_4040_EQ_4040(...) \, +#define Z_IS_4041_EQ_4041(...) \, +#define Z_IS_4042_EQ_4042(...) \, +#define Z_IS_4043_EQ_4043(...) \, +#define Z_IS_4044_EQ_4044(...) \, +#define Z_IS_4045_EQ_4045(...) \, +#define Z_IS_4046_EQ_4046(...) \, +#define Z_IS_4047_EQ_4047(...) \, +#define Z_IS_4048_EQ_4048(...) \, +#define Z_IS_4049_EQ_4049(...) \, +#define Z_IS_4050_EQ_4050(...) \, +#define Z_IS_4051_EQ_4051(...) \, +#define Z_IS_4052_EQ_4052(...) \, +#define Z_IS_4053_EQ_4053(...) \, +#define Z_IS_4054_EQ_4054(...) \, +#define Z_IS_4055_EQ_4055(...) \, +#define Z_IS_4056_EQ_4056(...) \, +#define Z_IS_4057_EQ_4057(...) \, +#define Z_IS_4058_EQ_4058(...) \, +#define Z_IS_4059_EQ_4059(...) \, +#define Z_IS_4060_EQ_4060(...) \, +#define Z_IS_4061_EQ_4061(...) \, +#define Z_IS_4062_EQ_4062(...) \, +#define Z_IS_4063_EQ_4063(...) \, +#define Z_IS_4064_EQ_4064(...) \, +#define Z_IS_4065_EQ_4065(...) \, +#define Z_IS_4066_EQ_4066(...) \, +#define Z_IS_4067_EQ_4067(...) \, +#define Z_IS_4068_EQ_4068(...) \, +#define Z_IS_4069_EQ_4069(...) \, +#define Z_IS_4070_EQ_4070(...) \, +#define Z_IS_4071_EQ_4071(...) \, +#define Z_IS_4072_EQ_4072(...) \, +#define Z_IS_4073_EQ_4073(...) \, +#define Z_IS_4074_EQ_4074(...) \, +#define Z_IS_4075_EQ_4075(...) \, +#define Z_IS_4076_EQ_4076(...) \, +#define Z_IS_4077_EQ_4077(...) \, +#define Z_IS_4078_EQ_4078(...) \, +#define Z_IS_4079_EQ_4079(...) \, +#define Z_IS_4080_EQ_4080(...) \, +#define Z_IS_4081_EQ_4081(...) \, +#define Z_IS_4082_EQ_4082(...) \, +#define Z_IS_4083_EQ_4083(...) \, +#define Z_IS_4084_EQ_4084(...) \, +#define Z_IS_4085_EQ_4085(...) \, +#define Z_IS_4086_EQ_4086(...) \, +#define Z_IS_4087_EQ_4087(...) \, +#define Z_IS_4088_EQ_4088(...) \, +#define Z_IS_4089_EQ_4089(...) \, +#define Z_IS_4090_EQ_4090(...) \, +#define Z_IS_4091_EQ_4091(...) \, +#define Z_IS_4092_EQ_4092(...) \, +#define Z_IS_4093_EQ_4093(...) \, +#define Z_IS_4094_EQ_4094(...) \, +#define Z_IS_4095_EQ_4095(...) \, +#define Z_IS_4096_EQ_4096(...) \, + +#endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_IS_EQ_H_ */ diff --git a/include/zephyr/sys/util_internal_util_dec.h b/include/zephyr/sys/util_internal_util_dec.h new file mode 100644 index 00000000000..c66718996dd --- /dev/null +++ b/include/zephyr/sys/util_internal_util_dec.h @@ -0,0 +1,4122 @@ +/* + * Copyright (c) 2011-2014, Wind River Systems, Inc. + * Copyright (c) 2020, Nordic Semiconductor ASA + * Copyright (c) 2023, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @cond INTERNAL_HIDDEN + */ + +#ifndef ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_ +#error "This header should not be used directly, please include util_internal.h instead" +#endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_ */ + +#ifndef ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_UTIL_DEC_H_ +#define ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_UTIL_DEC_H_ + +#define Z_UTIL_DEC_0 0 +#define Z_UTIL_DEC_1 0 +#define Z_UTIL_DEC_2 1 +#define Z_UTIL_DEC_3 2 +#define Z_UTIL_DEC_4 3 +#define Z_UTIL_DEC_5 4 +#define Z_UTIL_DEC_6 5 +#define Z_UTIL_DEC_7 6 +#define Z_UTIL_DEC_8 7 +#define Z_UTIL_DEC_9 8 +#define Z_UTIL_DEC_10 9 +#define Z_UTIL_DEC_11 10 +#define Z_UTIL_DEC_12 11 +#define Z_UTIL_DEC_13 12 +#define Z_UTIL_DEC_14 13 +#define Z_UTIL_DEC_15 14 +#define Z_UTIL_DEC_16 15 +#define Z_UTIL_DEC_17 16 +#define Z_UTIL_DEC_18 17 +#define Z_UTIL_DEC_19 18 +#define Z_UTIL_DEC_20 19 +#define Z_UTIL_DEC_21 20 +#define Z_UTIL_DEC_22 21 +#define Z_UTIL_DEC_23 22 +#define Z_UTIL_DEC_24 23 +#define Z_UTIL_DEC_25 24 +#define Z_UTIL_DEC_26 25 +#define Z_UTIL_DEC_27 26 +#define Z_UTIL_DEC_28 27 +#define Z_UTIL_DEC_29 28 +#define Z_UTIL_DEC_30 29 +#define Z_UTIL_DEC_31 30 +#define Z_UTIL_DEC_32 31 +#define Z_UTIL_DEC_33 32 +#define Z_UTIL_DEC_34 33 +#define Z_UTIL_DEC_35 34 +#define Z_UTIL_DEC_36 35 +#define Z_UTIL_DEC_37 36 +#define Z_UTIL_DEC_38 37 +#define Z_UTIL_DEC_39 38 +#define Z_UTIL_DEC_40 39 +#define Z_UTIL_DEC_41 40 +#define Z_UTIL_DEC_42 41 +#define Z_UTIL_DEC_43 42 +#define Z_UTIL_DEC_44 43 +#define Z_UTIL_DEC_45 44 +#define Z_UTIL_DEC_46 45 +#define Z_UTIL_DEC_47 46 +#define Z_UTIL_DEC_48 47 +#define Z_UTIL_DEC_49 48 +#define Z_UTIL_DEC_50 49 +#define Z_UTIL_DEC_51 50 +#define Z_UTIL_DEC_52 51 +#define Z_UTIL_DEC_53 52 +#define Z_UTIL_DEC_54 53 +#define Z_UTIL_DEC_55 54 +#define Z_UTIL_DEC_56 55 +#define Z_UTIL_DEC_57 56 +#define Z_UTIL_DEC_58 57 +#define Z_UTIL_DEC_59 58 +#define Z_UTIL_DEC_60 59 +#define Z_UTIL_DEC_61 60 +#define Z_UTIL_DEC_62 61 +#define Z_UTIL_DEC_63 62 +#define Z_UTIL_DEC_64 63 +#define Z_UTIL_DEC_65 64 +#define Z_UTIL_DEC_66 65 +#define Z_UTIL_DEC_67 66 +#define Z_UTIL_DEC_68 67 +#define Z_UTIL_DEC_69 68 +#define Z_UTIL_DEC_70 69 +#define Z_UTIL_DEC_71 70 +#define Z_UTIL_DEC_72 71 +#define Z_UTIL_DEC_73 72 +#define Z_UTIL_DEC_74 73 +#define Z_UTIL_DEC_75 74 +#define Z_UTIL_DEC_76 75 +#define Z_UTIL_DEC_77 76 +#define Z_UTIL_DEC_78 77 +#define Z_UTIL_DEC_79 78 +#define Z_UTIL_DEC_80 79 +#define Z_UTIL_DEC_81 80 +#define Z_UTIL_DEC_82 81 +#define Z_UTIL_DEC_83 82 +#define Z_UTIL_DEC_84 83 +#define Z_UTIL_DEC_85 84 +#define Z_UTIL_DEC_86 85 +#define Z_UTIL_DEC_87 86 +#define Z_UTIL_DEC_88 87 +#define Z_UTIL_DEC_89 88 +#define Z_UTIL_DEC_90 89 +#define Z_UTIL_DEC_91 90 +#define Z_UTIL_DEC_92 91 +#define Z_UTIL_DEC_93 92 +#define Z_UTIL_DEC_94 93 +#define Z_UTIL_DEC_95 94 +#define Z_UTIL_DEC_96 95 +#define Z_UTIL_DEC_97 96 +#define Z_UTIL_DEC_98 97 +#define Z_UTIL_DEC_99 98 +#define Z_UTIL_DEC_100 99 +#define Z_UTIL_DEC_101 100 +#define Z_UTIL_DEC_102 101 +#define Z_UTIL_DEC_103 102 +#define Z_UTIL_DEC_104 103 +#define Z_UTIL_DEC_105 104 +#define Z_UTIL_DEC_106 105 +#define Z_UTIL_DEC_107 106 +#define Z_UTIL_DEC_108 107 +#define Z_UTIL_DEC_109 108 +#define Z_UTIL_DEC_110 109 +#define Z_UTIL_DEC_111 110 +#define Z_UTIL_DEC_112 111 +#define Z_UTIL_DEC_113 112 +#define Z_UTIL_DEC_114 113 +#define Z_UTIL_DEC_115 114 +#define Z_UTIL_DEC_116 115 +#define Z_UTIL_DEC_117 116 +#define Z_UTIL_DEC_118 117 +#define Z_UTIL_DEC_119 118 +#define Z_UTIL_DEC_120 119 +#define Z_UTIL_DEC_121 120 +#define Z_UTIL_DEC_122 121 +#define Z_UTIL_DEC_123 122 +#define Z_UTIL_DEC_124 123 +#define Z_UTIL_DEC_125 124 +#define Z_UTIL_DEC_126 125 +#define Z_UTIL_DEC_127 126 +#define Z_UTIL_DEC_128 127 +#define Z_UTIL_DEC_129 128 +#define Z_UTIL_DEC_130 129 +#define Z_UTIL_DEC_131 130 +#define Z_UTIL_DEC_132 131 +#define Z_UTIL_DEC_133 132 +#define Z_UTIL_DEC_134 133 +#define Z_UTIL_DEC_135 134 +#define Z_UTIL_DEC_136 135 +#define Z_UTIL_DEC_137 136 +#define Z_UTIL_DEC_138 137 +#define Z_UTIL_DEC_139 138 +#define Z_UTIL_DEC_140 139 +#define Z_UTIL_DEC_141 140 +#define Z_UTIL_DEC_142 141 +#define Z_UTIL_DEC_143 142 +#define Z_UTIL_DEC_144 143 +#define Z_UTIL_DEC_145 144 +#define Z_UTIL_DEC_146 145 +#define Z_UTIL_DEC_147 146 +#define Z_UTIL_DEC_148 147 +#define Z_UTIL_DEC_149 148 +#define Z_UTIL_DEC_150 149 +#define Z_UTIL_DEC_151 150 +#define Z_UTIL_DEC_152 151 +#define Z_UTIL_DEC_153 152 +#define Z_UTIL_DEC_154 153 +#define Z_UTIL_DEC_155 154 +#define Z_UTIL_DEC_156 155 +#define Z_UTIL_DEC_157 156 +#define Z_UTIL_DEC_158 157 +#define Z_UTIL_DEC_159 158 +#define Z_UTIL_DEC_160 159 +#define Z_UTIL_DEC_161 160 +#define Z_UTIL_DEC_162 161 +#define Z_UTIL_DEC_163 162 +#define Z_UTIL_DEC_164 163 +#define Z_UTIL_DEC_165 164 +#define Z_UTIL_DEC_166 165 +#define Z_UTIL_DEC_167 166 +#define Z_UTIL_DEC_168 167 +#define Z_UTIL_DEC_169 168 +#define Z_UTIL_DEC_170 169 +#define Z_UTIL_DEC_171 170 +#define Z_UTIL_DEC_172 171 +#define Z_UTIL_DEC_173 172 +#define Z_UTIL_DEC_174 173 +#define Z_UTIL_DEC_175 174 +#define Z_UTIL_DEC_176 175 +#define Z_UTIL_DEC_177 176 +#define Z_UTIL_DEC_178 177 +#define Z_UTIL_DEC_179 178 +#define Z_UTIL_DEC_180 179 +#define Z_UTIL_DEC_181 180 +#define Z_UTIL_DEC_182 181 +#define Z_UTIL_DEC_183 182 +#define Z_UTIL_DEC_184 183 +#define Z_UTIL_DEC_185 184 +#define Z_UTIL_DEC_186 185 +#define Z_UTIL_DEC_187 186 +#define Z_UTIL_DEC_188 187 +#define Z_UTIL_DEC_189 188 +#define Z_UTIL_DEC_190 189 +#define Z_UTIL_DEC_191 190 +#define Z_UTIL_DEC_192 191 +#define Z_UTIL_DEC_193 192 +#define Z_UTIL_DEC_194 193 +#define Z_UTIL_DEC_195 194 +#define Z_UTIL_DEC_196 195 +#define Z_UTIL_DEC_197 196 +#define Z_UTIL_DEC_198 197 +#define Z_UTIL_DEC_199 198 +#define Z_UTIL_DEC_200 199 +#define Z_UTIL_DEC_201 200 +#define Z_UTIL_DEC_202 201 +#define Z_UTIL_DEC_203 202 +#define Z_UTIL_DEC_204 203 +#define Z_UTIL_DEC_205 204 +#define Z_UTIL_DEC_206 205 +#define Z_UTIL_DEC_207 206 +#define Z_UTIL_DEC_208 207 +#define Z_UTIL_DEC_209 208 +#define Z_UTIL_DEC_210 209 +#define Z_UTIL_DEC_211 210 +#define Z_UTIL_DEC_212 211 +#define Z_UTIL_DEC_213 212 +#define Z_UTIL_DEC_214 213 +#define Z_UTIL_DEC_215 214 +#define Z_UTIL_DEC_216 215 +#define Z_UTIL_DEC_217 216 +#define Z_UTIL_DEC_218 217 +#define Z_UTIL_DEC_219 218 +#define Z_UTIL_DEC_220 219 +#define Z_UTIL_DEC_221 220 +#define Z_UTIL_DEC_222 221 +#define Z_UTIL_DEC_223 222 +#define Z_UTIL_DEC_224 223 +#define Z_UTIL_DEC_225 224 +#define Z_UTIL_DEC_226 225 +#define Z_UTIL_DEC_227 226 +#define Z_UTIL_DEC_228 227 +#define Z_UTIL_DEC_229 228 +#define Z_UTIL_DEC_230 229 +#define Z_UTIL_DEC_231 230 +#define Z_UTIL_DEC_232 231 +#define Z_UTIL_DEC_233 232 +#define Z_UTIL_DEC_234 233 +#define Z_UTIL_DEC_235 234 +#define Z_UTIL_DEC_236 235 +#define Z_UTIL_DEC_237 236 +#define Z_UTIL_DEC_238 237 +#define Z_UTIL_DEC_239 238 +#define Z_UTIL_DEC_240 239 +#define Z_UTIL_DEC_241 240 +#define Z_UTIL_DEC_242 241 +#define Z_UTIL_DEC_243 242 +#define Z_UTIL_DEC_244 243 +#define Z_UTIL_DEC_245 244 +#define Z_UTIL_DEC_246 245 +#define Z_UTIL_DEC_247 246 +#define Z_UTIL_DEC_248 247 +#define Z_UTIL_DEC_249 248 +#define Z_UTIL_DEC_250 249 +#define Z_UTIL_DEC_251 250 +#define Z_UTIL_DEC_252 251 +#define Z_UTIL_DEC_253 252 +#define Z_UTIL_DEC_254 253 +#define Z_UTIL_DEC_255 254 +#define Z_UTIL_DEC_256 255 +#define Z_UTIL_DEC_257 256 +#define Z_UTIL_DEC_258 257 +#define Z_UTIL_DEC_259 258 +#define Z_UTIL_DEC_260 259 +#define Z_UTIL_DEC_261 260 +#define Z_UTIL_DEC_262 261 +#define Z_UTIL_DEC_263 262 +#define Z_UTIL_DEC_264 263 +#define Z_UTIL_DEC_265 264 +#define Z_UTIL_DEC_266 265 +#define Z_UTIL_DEC_267 266 +#define Z_UTIL_DEC_268 267 +#define Z_UTIL_DEC_269 268 +#define Z_UTIL_DEC_270 269 +#define Z_UTIL_DEC_271 270 +#define Z_UTIL_DEC_272 271 +#define Z_UTIL_DEC_273 272 +#define Z_UTIL_DEC_274 273 +#define Z_UTIL_DEC_275 274 +#define Z_UTIL_DEC_276 275 +#define Z_UTIL_DEC_277 276 +#define Z_UTIL_DEC_278 277 +#define Z_UTIL_DEC_279 278 +#define Z_UTIL_DEC_280 279 +#define Z_UTIL_DEC_281 280 +#define Z_UTIL_DEC_282 281 +#define Z_UTIL_DEC_283 282 +#define Z_UTIL_DEC_284 283 +#define Z_UTIL_DEC_285 284 +#define Z_UTIL_DEC_286 285 +#define Z_UTIL_DEC_287 286 +#define Z_UTIL_DEC_288 287 +#define Z_UTIL_DEC_289 288 +#define Z_UTIL_DEC_290 289 +#define Z_UTIL_DEC_291 290 +#define Z_UTIL_DEC_292 291 +#define Z_UTIL_DEC_293 292 +#define Z_UTIL_DEC_294 293 +#define Z_UTIL_DEC_295 294 +#define Z_UTIL_DEC_296 295 +#define Z_UTIL_DEC_297 296 +#define Z_UTIL_DEC_298 297 +#define Z_UTIL_DEC_299 298 +#define Z_UTIL_DEC_300 299 +#define Z_UTIL_DEC_301 300 +#define Z_UTIL_DEC_302 301 +#define Z_UTIL_DEC_303 302 +#define Z_UTIL_DEC_304 303 +#define Z_UTIL_DEC_305 304 +#define Z_UTIL_DEC_306 305 +#define Z_UTIL_DEC_307 306 +#define Z_UTIL_DEC_308 307 +#define Z_UTIL_DEC_309 308 +#define Z_UTIL_DEC_310 309 +#define Z_UTIL_DEC_311 310 +#define Z_UTIL_DEC_312 311 +#define Z_UTIL_DEC_313 312 +#define Z_UTIL_DEC_314 313 +#define Z_UTIL_DEC_315 314 +#define Z_UTIL_DEC_316 315 +#define Z_UTIL_DEC_317 316 +#define Z_UTIL_DEC_318 317 +#define Z_UTIL_DEC_319 318 +#define Z_UTIL_DEC_320 319 +#define Z_UTIL_DEC_321 320 +#define Z_UTIL_DEC_322 321 +#define Z_UTIL_DEC_323 322 +#define Z_UTIL_DEC_324 323 +#define Z_UTIL_DEC_325 324 +#define Z_UTIL_DEC_326 325 +#define Z_UTIL_DEC_327 326 +#define Z_UTIL_DEC_328 327 +#define Z_UTIL_DEC_329 328 +#define Z_UTIL_DEC_330 329 +#define Z_UTIL_DEC_331 330 +#define Z_UTIL_DEC_332 331 +#define Z_UTIL_DEC_333 332 +#define Z_UTIL_DEC_334 333 +#define Z_UTIL_DEC_335 334 +#define Z_UTIL_DEC_336 335 +#define Z_UTIL_DEC_337 336 +#define Z_UTIL_DEC_338 337 +#define Z_UTIL_DEC_339 338 +#define Z_UTIL_DEC_340 339 +#define Z_UTIL_DEC_341 340 +#define Z_UTIL_DEC_342 341 +#define Z_UTIL_DEC_343 342 +#define Z_UTIL_DEC_344 343 +#define Z_UTIL_DEC_345 344 +#define Z_UTIL_DEC_346 345 +#define Z_UTIL_DEC_347 346 +#define Z_UTIL_DEC_348 347 +#define Z_UTIL_DEC_349 348 +#define Z_UTIL_DEC_350 349 +#define Z_UTIL_DEC_351 350 +#define Z_UTIL_DEC_352 351 +#define Z_UTIL_DEC_353 352 +#define Z_UTIL_DEC_354 353 +#define Z_UTIL_DEC_355 354 +#define Z_UTIL_DEC_356 355 +#define Z_UTIL_DEC_357 356 +#define Z_UTIL_DEC_358 357 +#define Z_UTIL_DEC_359 358 +#define Z_UTIL_DEC_360 359 +#define Z_UTIL_DEC_361 360 +#define Z_UTIL_DEC_362 361 +#define Z_UTIL_DEC_363 362 +#define Z_UTIL_DEC_364 363 +#define Z_UTIL_DEC_365 364 +#define Z_UTIL_DEC_366 365 +#define Z_UTIL_DEC_367 366 +#define Z_UTIL_DEC_368 367 +#define Z_UTIL_DEC_369 368 +#define Z_UTIL_DEC_370 369 +#define Z_UTIL_DEC_371 370 +#define Z_UTIL_DEC_372 371 +#define Z_UTIL_DEC_373 372 +#define Z_UTIL_DEC_374 373 +#define Z_UTIL_DEC_375 374 +#define Z_UTIL_DEC_376 375 +#define Z_UTIL_DEC_377 376 +#define Z_UTIL_DEC_378 377 +#define Z_UTIL_DEC_379 378 +#define Z_UTIL_DEC_380 379 +#define Z_UTIL_DEC_381 380 +#define Z_UTIL_DEC_382 381 +#define Z_UTIL_DEC_383 382 +#define Z_UTIL_DEC_384 383 +#define Z_UTIL_DEC_385 384 +#define Z_UTIL_DEC_386 385 +#define Z_UTIL_DEC_387 386 +#define Z_UTIL_DEC_388 387 +#define Z_UTIL_DEC_389 388 +#define Z_UTIL_DEC_390 389 +#define Z_UTIL_DEC_391 390 +#define Z_UTIL_DEC_392 391 +#define Z_UTIL_DEC_393 392 +#define Z_UTIL_DEC_394 393 +#define Z_UTIL_DEC_395 394 +#define Z_UTIL_DEC_396 395 +#define Z_UTIL_DEC_397 396 +#define Z_UTIL_DEC_398 397 +#define Z_UTIL_DEC_399 398 +#define Z_UTIL_DEC_400 399 +#define Z_UTIL_DEC_401 400 +#define Z_UTIL_DEC_402 401 +#define Z_UTIL_DEC_403 402 +#define Z_UTIL_DEC_404 403 +#define Z_UTIL_DEC_405 404 +#define Z_UTIL_DEC_406 405 +#define Z_UTIL_DEC_407 406 +#define Z_UTIL_DEC_408 407 +#define Z_UTIL_DEC_409 408 +#define Z_UTIL_DEC_410 409 +#define Z_UTIL_DEC_411 410 +#define Z_UTIL_DEC_412 411 +#define Z_UTIL_DEC_413 412 +#define Z_UTIL_DEC_414 413 +#define Z_UTIL_DEC_415 414 +#define Z_UTIL_DEC_416 415 +#define Z_UTIL_DEC_417 416 +#define Z_UTIL_DEC_418 417 +#define Z_UTIL_DEC_419 418 +#define Z_UTIL_DEC_420 419 +#define Z_UTIL_DEC_421 420 +#define Z_UTIL_DEC_422 421 +#define Z_UTIL_DEC_423 422 +#define Z_UTIL_DEC_424 423 +#define Z_UTIL_DEC_425 424 +#define Z_UTIL_DEC_426 425 +#define Z_UTIL_DEC_427 426 +#define Z_UTIL_DEC_428 427 +#define Z_UTIL_DEC_429 428 +#define Z_UTIL_DEC_430 429 +#define Z_UTIL_DEC_431 430 +#define Z_UTIL_DEC_432 431 +#define Z_UTIL_DEC_433 432 +#define Z_UTIL_DEC_434 433 +#define Z_UTIL_DEC_435 434 +#define Z_UTIL_DEC_436 435 +#define Z_UTIL_DEC_437 436 +#define Z_UTIL_DEC_438 437 +#define Z_UTIL_DEC_439 438 +#define Z_UTIL_DEC_440 439 +#define Z_UTIL_DEC_441 440 +#define Z_UTIL_DEC_442 441 +#define Z_UTIL_DEC_443 442 +#define Z_UTIL_DEC_444 443 +#define Z_UTIL_DEC_445 444 +#define Z_UTIL_DEC_446 445 +#define Z_UTIL_DEC_447 446 +#define Z_UTIL_DEC_448 447 +#define Z_UTIL_DEC_449 448 +#define Z_UTIL_DEC_450 449 +#define Z_UTIL_DEC_451 450 +#define Z_UTIL_DEC_452 451 +#define Z_UTIL_DEC_453 452 +#define Z_UTIL_DEC_454 453 +#define Z_UTIL_DEC_455 454 +#define Z_UTIL_DEC_456 455 +#define Z_UTIL_DEC_457 456 +#define Z_UTIL_DEC_458 457 +#define Z_UTIL_DEC_459 458 +#define Z_UTIL_DEC_460 459 +#define Z_UTIL_DEC_461 460 +#define Z_UTIL_DEC_462 461 +#define Z_UTIL_DEC_463 462 +#define Z_UTIL_DEC_464 463 +#define Z_UTIL_DEC_465 464 +#define Z_UTIL_DEC_466 465 +#define Z_UTIL_DEC_467 466 +#define Z_UTIL_DEC_468 467 +#define Z_UTIL_DEC_469 468 +#define Z_UTIL_DEC_470 469 +#define Z_UTIL_DEC_471 470 +#define Z_UTIL_DEC_472 471 +#define Z_UTIL_DEC_473 472 +#define Z_UTIL_DEC_474 473 +#define Z_UTIL_DEC_475 474 +#define Z_UTIL_DEC_476 475 +#define Z_UTIL_DEC_477 476 +#define Z_UTIL_DEC_478 477 +#define Z_UTIL_DEC_479 478 +#define Z_UTIL_DEC_480 479 +#define Z_UTIL_DEC_481 480 +#define Z_UTIL_DEC_482 481 +#define Z_UTIL_DEC_483 482 +#define Z_UTIL_DEC_484 483 +#define Z_UTIL_DEC_485 484 +#define Z_UTIL_DEC_486 485 +#define Z_UTIL_DEC_487 486 +#define Z_UTIL_DEC_488 487 +#define Z_UTIL_DEC_489 488 +#define Z_UTIL_DEC_490 489 +#define Z_UTIL_DEC_491 490 +#define Z_UTIL_DEC_492 491 +#define Z_UTIL_DEC_493 492 +#define Z_UTIL_DEC_494 493 +#define Z_UTIL_DEC_495 494 +#define Z_UTIL_DEC_496 495 +#define Z_UTIL_DEC_497 496 +#define Z_UTIL_DEC_498 497 +#define Z_UTIL_DEC_499 498 +#define Z_UTIL_DEC_500 499 +#define Z_UTIL_DEC_501 500 +#define Z_UTIL_DEC_502 501 +#define Z_UTIL_DEC_503 502 +#define Z_UTIL_DEC_504 503 +#define Z_UTIL_DEC_505 504 +#define Z_UTIL_DEC_506 505 +#define Z_UTIL_DEC_507 506 +#define Z_UTIL_DEC_508 507 +#define Z_UTIL_DEC_509 508 +#define Z_UTIL_DEC_510 509 +#define Z_UTIL_DEC_511 510 +#define Z_UTIL_DEC_512 511 +#define Z_UTIL_DEC_513 512 +#define Z_UTIL_DEC_514 513 +#define Z_UTIL_DEC_515 514 +#define Z_UTIL_DEC_516 515 +#define Z_UTIL_DEC_517 516 +#define Z_UTIL_DEC_518 517 +#define Z_UTIL_DEC_519 518 +#define Z_UTIL_DEC_520 519 +#define Z_UTIL_DEC_521 520 +#define Z_UTIL_DEC_522 521 +#define Z_UTIL_DEC_523 522 +#define Z_UTIL_DEC_524 523 +#define Z_UTIL_DEC_525 524 +#define Z_UTIL_DEC_526 525 +#define Z_UTIL_DEC_527 526 +#define Z_UTIL_DEC_528 527 +#define Z_UTIL_DEC_529 528 +#define Z_UTIL_DEC_530 529 +#define Z_UTIL_DEC_531 530 +#define Z_UTIL_DEC_532 531 +#define Z_UTIL_DEC_533 532 +#define Z_UTIL_DEC_534 533 +#define Z_UTIL_DEC_535 534 +#define Z_UTIL_DEC_536 535 +#define Z_UTIL_DEC_537 536 +#define Z_UTIL_DEC_538 537 +#define Z_UTIL_DEC_539 538 +#define Z_UTIL_DEC_540 539 +#define Z_UTIL_DEC_541 540 +#define Z_UTIL_DEC_542 541 +#define Z_UTIL_DEC_543 542 +#define Z_UTIL_DEC_544 543 +#define Z_UTIL_DEC_545 544 +#define Z_UTIL_DEC_546 545 +#define Z_UTIL_DEC_547 546 +#define Z_UTIL_DEC_548 547 +#define Z_UTIL_DEC_549 548 +#define Z_UTIL_DEC_550 549 +#define Z_UTIL_DEC_551 550 +#define Z_UTIL_DEC_552 551 +#define Z_UTIL_DEC_553 552 +#define Z_UTIL_DEC_554 553 +#define Z_UTIL_DEC_555 554 +#define Z_UTIL_DEC_556 555 +#define Z_UTIL_DEC_557 556 +#define Z_UTIL_DEC_558 557 +#define Z_UTIL_DEC_559 558 +#define Z_UTIL_DEC_560 559 +#define Z_UTIL_DEC_561 560 +#define Z_UTIL_DEC_562 561 +#define Z_UTIL_DEC_563 562 +#define Z_UTIL_DEC_564 563 +#define Z_UTIL_DEC_565 564 +#define Z_UTIL_DEC_566 565 +#define Z_UTIL_DEC_567 566 +#define Z_UTIL_DEC_568 567 +#define Z_UTIL_DEC_569 568 +#define Z_UTIL_DEC_570 569 +#define Z_UTIL_DEC_571 570 +#define Z_UTIL_DEC_572 571 +#define Z_UTIL_DEC_573 572 +#define Z_UTIL_DEC_574 573 +#define Z_UTIL_DEC_575 574 +#define Z_UTIL_DEC_576 575 +#define Z_UTIL_DEC_577 576 +#define Z_UTIL_DEC_578 577 +#define Z_UTIL_DEC_579 578 +#define Z_UTIL_DEC_580 579 +#define Z_UTIL_DEC_581 580 +#define Z_UTIL_DEC_582 581 +#define Z_UTIL_DEC_583 582 +#define Z_UTIL_DEC_584 583 +#define Z_UTIL_DEC_585 584 +#define Z_UTIL_DEC_586 585 +#define Z_UTIL_DEC_587 586 +#define Z_UTIL_DEC_588 587 +#define Z_UTIL_DEC_589 588 +#define Z_UTIL_DEC_590 589 +#define Z_UTIL_DEC_591 590 +#define Z_UTIL_DEC_592 591 +#define Z_UTIL_DEC_593 592 +#define Z_UTIL_DEC_594 593 +#define Z_UTIL_DEC_595 594 +#define Z_UTIL_DEC_596 595 +#define Z_UTIL_DEC_597 596 +#define Z_UTIL_DEC_598 597 +#define Z_UTIL_DEC_599 598 +#define Z_UTIL_DEC_600 599 +#define Z_UTIL_DEC_601 600 +#define Z_UTIL_DEC_602 601 +#define Z_UTIL_DEC_603 602 +#define Z_UTIL_DEC_604 603 +#define Z_UTIL_DEC_605 604 +#define Z_UTIL_DEC_606 605 +#define Z_UTIL_DEC_607 606 +#define Z_UTIL_DEC_608 607 +#define Z_UTIL_DEC_609 608 +#define Z_UTIL_DEC_610 609 +#define Z_UTIL_DEC_611 610 +#define Z_UTIL_DEC_612 611 +#define Z_UTIL_DEC_613 612 +#define Z_UTIL_DEC_614 613 +#define Z_UTIL_DEC_615 614 +#define Z_UTIL_DEC_616 615 +#define Z_UTIL_DEC_617 616 +#define Z_UTIL_DEC_618 617 +#define Z_UTIL_DEC_619 618 +#define Z_UTIL_DEC_620 619 +#define Z_UTIL_DEC_621 620 +#define Z_UTIL_DEC_622 621 +#define Z_UTIL_DEC_623 622 +#define Z_UTIL_DEC_624 623 +#define Z_UTIL_DEC_625 624 +#define Z_UTIL_DEC_626 625 +#define Z_UTIL_DEC_627 626 +#define Z_UTIL_DEC_628 627 +#define Z_UTIL_DEC_629 628 +#define Z_UTIL_DEC_630 629 +#define Z_UTIL_DEC_631 630 +#define Z_UTIL_DEC_632 631 +#define Z_UTIL_DEC_633 632 +#define Z_UTIL_DEC_634 633 +#define Z_UTIL_DEC_635 634 +#define Z_UTIL_DEC_636 635 +#define Z_UTIL_DEC_637 636 +#define Z_UTIL_DEC_638 637 +#define Z_UTIL_DEC_639 638 +#define Z_UTIL_DEC_640 639 +#define Z_UTIL_DEC_641 640 +#define Z_UTIL_DEC_642 641 +#define Z_UTIL_DEC_643 642 +#define Z_UTIL_DEC_644 643 +#define Z_UTIL_DEC_645 644 +#define Z_UTIL_DEC_646 645 +#define Z_UTIL_DEC_647 646 +#define Z_UTIL_DEC_648 647 +#define Z_UTIL_DEC_649 648 +#define Z_UTIL_DEC_650 649 +#define Z_UTIL_DEC_651 650 +#define Z_UTIL_DEC_652 651 +#define Z_UTIL_DEC_653 652 +#define Z_UTIL_DEC_654 653 +#define Z_UTIL_DEC_655 654 +#define Z_UTIL_DEC_656 655 +#define Z_UTIL_DEC_657 656 +#define Z_UTIL_DEC_658 657 +#define Z_UTIL_DEC_659 658 +#define Z_UTIL_DEC_660 659 +#define Z_UTIL_DEC_661 660 +#define Z_UTIL_DEC_662 661 +#define Z_UTIL_DEC_663 662 +#define Z_UTIL_DEC_664 663 +#define Z_UTIL_DEC_665 664 +#define Z_UTIL_DEC_666 665 +#define Z_UTIL_DEC_667 666 +#define Z_UTIL_DEC_668 667 +#define Z_UTIL_DEC_669 668 +#define Z_UTIL_DEC_670 669 +#define Z_UTIL_DEC_671 670 +#define Z_UTIL_DEC_672 671 +#define Z_UTIL_DEC_673 672 +#define Z_UTIL_DEC_674 673 +#define Z_UTIL_DEC_675 674 +#define Z_UTIL_DEC_676 675 +#define Z_UTIL_DEC_677 676 +#define Z_UTIL_DEC_678 677 +#define Z_UTIL_DEC_679 678 +#define Z_UTIL_DEC_680 679 +#define Z_UTIL_DEC_681 680 +#define Z_UTIL_DEC_682 681 +#define Z_UTIL_DEC_683 682 +#define Z_UTIL_DEC_684 683 +#define Z_UTIL_DEC_685 684 +#define Z_UTIL_DEC_686 685 +#define Z_UTIL_DEC_687 686 +#define Z_UTIL_DEC_688 687 +#define Z_UTIL_DEC_689 688 +#define Z_UTIL_DEC_690 689 +#define Z_UTIL_DEC_691 690 +#define Z_UTIL_DEC_692 691 +#define Z_UTIL_DEC_693 692 +#define Z_UTIL_DEC_694 693 +#define Z_UTIL_DEC_695 694 +#define Z_UTIL_DEC_696 695 +#define Z_UTIL_DEC_697 696 +#define Z_UTIL_DEC_698 697 +#define Z_UTIL_DEC_699 698 +#define Z_UTIL_DEC_700 699 +#define Z_UTIL_DEC_701 700 +#define Z_UTIL_DEC_702 701 +#define Z_UTIL_DEC_703 702 +#define Z_UTIL_DEC_704 703 +#define Z_UTIL_DEC_705 704 +#define Z_UTIL_DEC_706 705 +#define Z_UTIL_DEC_707 706 +#define Z_UTIL_DEC_708 707 +#define Z_UTIL_DEC_709 708 +#define Z_UTIL_DEC_710 709 +#define Z_UTIL_DEC_711 710 +#define Z_UTIL_DEC_712 711 +#define Z_UTIL_DEC_713 712 +#define Z_UTIL_DEC_714 713 +#define Z_UTIL_DEC_715 714 +#define Z_UTIL_DEC_716 715 +#define Z_UTIL_DEC_717 716 +#define Z_UTIL_DEC_718 717 +#define Z_UTIL_DEC_719 718 +#define Z_UTIL_DEC_720 719 +#define Z_UTIL_DEC_721 720 +#define Z_UTIL_DEC_722 721 +#define Z_UTIL_DEC_723 722 +#define Z_UTIL_DEC_724 723 +#define Z_UTIL_DEC_725 724 +#define Z_UTIL_DEC_726 725 +#define Z_UTIL_DEC_727 726 +#define Z_UTIL_DEC_728 727 +#define Z_UTIL_DEC_729 728 +#define Z_UTIL_DEC_730 729 +#define Z_UTIL_DEC_731 730 +#define Z_UTIL_DEC_732 731 +#define Z_UTIL_DEC_733 732 +#define Z_UTIL_DEC_734 733 +#define Z_UTIL_DEC_735 734 +#define Z_UTIL_DEC_736 735 +#define Z_UTIL_DEC_737 736 +#define Z_UTIL_DEC_738 737 +#define Z_UTIL_DEC_739 738 +#define Z_UTIL_DEC_740 739 +#define Z_UTIL_DEC_741 740 +#define Z_UTIL_DEC_742 741 +#define Z_UTIL_DEC_743 742 +#define Z_UTIL_DEC_744 743 +#define Z_UTIL_DEC_745 744 +#define Z_UTIL_DEC_746 745 +#define Z_UTIL_DEC_747 746 +#define Z_UTIL_DEC_748 747 +#define Z_UTIL_DEC_749 748 +#define Z_UTIL_DEC_750 749 +#define Z_UTIL_DEC_751 750 +#define Z_UTIL_DEC_752 751 +#define Z_UTIL_DEC_753 752 +#define Z_UTIL_DEC_754 753 +#define Z_UTIL_DEC_755 754 +#define Z_UTIL_DEC_756 755 +#define Z_UTIL_DEC_757 756 +#define Z_UTIL_DEC_758 757 +#define Z_UTIL_DEC_759 758 +#define Z_UTIL_DEC_760 759 +#define Z_UTIL_DEC_761 760 +#define Z_UTIL_DEC_762 761 +#define Z_UTIL_DEC_763 762 +#define Z_UTIL_DEC_764 763 +#define Z_UTIL_DEC_765 764 +#define Z_UTIL_DEC_766 765 +#define Z_UTIL_DEC_767 766 +#define Z_UTIL_DEC_768 767 +#define Z_UTIL_DEC_769 768 +#define Z_UTIL_DEC_770 769 +#define Z_UTIL_DEC_771 770 +#define Z_UTIL_DEC_772 771 +#define Z_UTIL_DEC_773 772 +#define Z_UTIL_DEC_774 773 +#define Z_UTIL_DEC_775 774 +#define Z_UTIL_DEC_776 775 +#define Z_UTIL_DEC_777 776 +#define Z_UTIL_DEC_778 777 +#define Z_UTIL_DEC_779 778 +#define Z_UTIL_DEC_780 779 +#define Z_UTIL_DEC_781 780 +#define Z_UTIL_DEC_782 781 +#define Z_UTIL_DEC_783 782 +#define Z_UTIL_DEC_784 783 +#define Z_UTIL_DEC_785 784 +#define Z_UTIL_DEC_786 785 +#define Z_UTIL_DEC_787 786 +#define Z_UTIL_DEC_788 787 +#define Z_UTIL_DEC_789 788 +#define Z_UTIL_DEC_790 789 +#define Z_UTIL_DEC_791 790 +#define Z_UTIL_DEC_792 791 +#define Z_UTIL_DEC_793 792 +#define Z_UTIL_DEC_794 793 +#define Z_UTIL_DEC_795 794 +#define Z_UTIL_DEC_796 795 +#define Z_UTIL_DEC_797 796 +#define Z_UTIL_DEC_798 797 +#define Z_UTIL_DEC_799 798 +#define Z_UTIL_DEC_800 799 +#define Z_UTIL_DEC_801 800 +#define Z_UTIL_DEC_802 801 +#define Z_UTIL_DEC_803 802 +#define Z_UTIL_DEC_804 803 +#define Z_UTIL_DEC_805 804 +#define Z_UTIL_DEC_806 805 +#define Z_UTIL_DEC_807 806 +#define Z_UTIL_DEC_808 807 +#define Z_UTIL_DEC_809 808 +#define Z_UTIL_DEC_810 809 +#define Z_UTIL_DEC_811 810 +#define Z_UTIL_DEC_812 811 +#define Z_UTIL_DEC_813 812 +#define Z_UTIL_DEC_814 813 +#define Z_UTIL_DEC_815 814 +#define Z_UTIL_DEC_816 815 +#define Z_UTIL_DEC_817 816 +#define Z_UTIL_DEC_818 817 +#define Z_UTIL_DEC_819 818 +#define Z_UTIL_DEC_820 819 +#define Z_UTIL_DEC_821 820 +#define Z_UTIL_DEC_822 821 +#define Z_UTIL_DEC_823 822 +#define Z_UTIL_DEC_824 823 +#define Z_UTIL_DEC_825 824 +#define Z_UTIL_DEC_826 825 +#define Z_UTIL_DEC_827 826 +#define Z_UTIL_DEC_828 827 +#define Z_UTIL_DEC_829 828 +#define Z_UTIL_DEC_830 829 +#define Z_UTIL_DEC_831 830 +#define Z_UTIL_DEC_832 831 +#define Z_UTIL_DEC_833 832 +#define Z_UTIL_DEC_834 833 +#define Z_UTIL_DEC_835 834 +#define Z_UTIL_DEC_836 835 +#define Z_UTIL_DEC_837 836 +#define Z_UTIL_DEC_838 837 +#define Z_UTIL_DEC_839 838 +#define Z_UTIL_DEC_840 839 +#define Z_UTIL_DEC_841 840 +#define Z_UTIL_DEC_842 841 +#define Z_UTIL_DEC_843 842 +#define Z_UTIL_DEC_844 843 +#define Z_UTIL_DEC_845 844 +#define Z_UTIL_DEC_846 845 +#define Z_UTIL_DEC_847 846 +#define Z_UTIL_DEC_848 847 +#define Z_UTIL_DEC_849 848 +#define Z_UTIL_DEC_850 849 +#define Z_UTIL_DEC_851 850 +#define Z_UTIL_DEC_852 851 +#define Z_UTIL_DEC_853 852 +#define Z_UTIL_DEC_854 853 +#define Z_UTIL_DEC_855 854 +#define Z_UTIL_DEC_856 855 +#define Z_UTIL_DEC_857 856 +#define Z_UTIL_DEC_858 857 +#define Z_UTIL_DEC_859 858 +#define Z_UTIL_DEC_860 859 +#define Z_UTIL_DEC_861 860 +#define Z_UTIL_DEC_862 861 +#define Z_UTIL_DEC_863 862 +#define Z_UTIL_DEC_864 863 +#define Z_UTIL_DEC_865 864 +#define Z_UTIL_DEC_866 865 +#define Z_UTIL_DEC_867 866 +#define Z_UTIL_DEC_868 867 +#define Z_UTIL_DEC_869 868 +#define Z_UTIL_DEC_870 869 +#define Z_UTIL_DEC_871 870 +#define Z_UTIL_DEC_872 871 +#define Z_UTIL_DEC_873 872 +#define Z_UTIL_DEC_874 873 +#define Z_UTIL_DEC_875 874 +#define Z_UTIL_DEC_876 875 +#define Z_UTIL_DEC_877 876 +#define Z_UTIL_DEC_878 877 +#define Z_UTIL_DEC_879 878 +#define Z_UTIL_DEC_880 879 +#define Z_UTIL_DEC_881 880 +#define Z_UTIL_DEC_882 881 +#define Z_UTIL_DEC_883 882 +#define Z_UTIL_DEC_884 883 +#define Z_UTIL_DEC_885 884 +#define Z_UTIL_DEC_886 885 +#define Z_UTIL_DEC_887 886 +#define Z_UTIL_DEC_888 887 +#define Z_UTIL_DEC_889 888 +#define Z_UTIL_DEC_890 889 +#define Z_UTIL_DEC_891 890 +#define Z_UTIL_DEC_892 891 +#define Z_UTIL_DEC_893 892 +#define Z_UTIL_DEC_894 893 +#define Z_UTIL_DEC_895 894 +#define Z_UTIL_DEC_896 895 +#define Z_UTIL_DEC_897 896 +#define Z_UTIL_DEC_898 897 +#define Z_UTIL_DEC_899 898 +#define Z_UTIL_DEC_900 899 +#define Z_UTIL_DEC_901 900 +#define Z_UTIL_DEC_902 901 +#define Z_UTIL_DEC_903 902 +#define Z_UTIL_DEC_904 903 +#define Z_UTIL_DEC_905 904 +#define Z_UTIL_DEC_906 905 +#define Z_UTIL_DEC_907 906 +#define Z_UTIL_DEC_908 907 +#define Z_UTIL_DEC_909 908 +#define Z_UTIL_DEC_910 909 +#define Z_UTIL_DEC_911 910 +#define Z_UTIL_DEC_912 911 +#define Z_UTIL_DEC_913 912 +#define Z_UTIL_DEC_914 913 +#define Z_UTIL_DEC_915 914 +#define Z_UTIL_DEC_916 915 +#define Z_UTIL_DEC_917 916 +#define Z_UTIL_DEC_918 917 +#define Z_UTIL_DEC_919 918 +#define Z_UTIL_DEC_920 919 +#define Z_UTIL_DEC_921 920 +#define Z_UTIL_DEC_922 921 +#define Z_UTIL_DEC_923 922 +#define Z_UTIL_DEC_924 923 +#define Z_UTIL_DEC_925 924 +#define Z_UTIL_DEC_926 925 +#define Z_UTIL_DEC_927 926 +#define Z_UTIL_DEC_928 927 +#define Z_UTIL_DEC_929 928 +#define Z_UTIL_DEC_930 929 +#define Z_UTIL_DEC_931 930 +#define Z_UTIL_DEC_932 931 +#define Z_UTIL_DEC_933 932 +#define Z_UTIL_DEC_934 933 +#define Z_UTIL_DEC_935 934 +#define Z_UTIL_DEC_936 935 +#define Z_UTIL_DEC_937 936 +#define Z_UTIL_DEC_938 937 +#define Z_UTIL_DEC_939 938 +#define Z_UTIL_DEC_940 939 +#define Z_UTIL_DEC_941 940 +#define Z_UTIL_DEC_942 941 +#define Z_UTIL_DEC_943 942 +#define Z_UTIL_DEC_944 943 +#define Z_UTIL_DEC_945 944 +#define Z_UTIL_DEC_946 945 +#define Z_UTIL_DEC_947 946 +#define Z_UTIL_DEC_948 947 +#define Z_UTIL_DEC_949 948 +#define Z_UTIL_DEC_950 949 +#define Z_UTIL_DEC_951 950 +#define Z_UTIL_DEC_952 951 +#define Z_UTIL_DEC_953 952 +#define Z_UTIL_DEC_954 953 +#define Z_UTIL_DEC_955 954 +#define Z_UTIL_DEC_956 955 +#define Z_UTIL_DEC_957 956 +#define Z_UTIL_DEC_958 957 +#define Z_UTIL_DEC_959 958 +#define Z_UTIL_DEC_960 959 +#define Z_UTIL_DEC_961 960 +#define Z_UTIL_DEC_962 961 +#define Z_UTIL_DEC_963 962 +#define Z_UTIL_DEC_964 963 +#define Z_UTIL_DEC_965 964 +#define Z_UTIL_DEC_966 965 +#define Z_UTIL_DEC_967 966 +#define Z_UTIL_DEC_968 967 +#define Z_UTIL_DEC_969 968 +#define Z_UTIL_DEC_970 969 +#define Z_UTIL_DEC_971 970 +#define Z_UTIL_DEC_972 971 +#define Z_UTIL_DEC_973 972 +#define Z_UTIL_DEC_974 973 +#define Z_UTIL_DEC_975 974 +#define Z_UTIL_DEC_976 975 +#define Z_UTIL_DEC_977 976 +#define Z_UTIL_DEC_978 977 +#define Z_UTIL_DEC_979 978 +#define Z_UTIL_DEC_980 979 +#define Z_UTIL_DEC_981 980 +#define Z_UTIL_DEC_982 981 +#define Z_UTIL_DEC_983 982 +#define Z_UTIL_DEC_984 983 +#define Z_UTIL_DEC_985 984 +#define Z_UTIL_DEC_986 985 +#define Z_UTIL_DEC_987 986 +#define Z_UTIL_DEC_988 987 +#define Z_UTIL_DEC_989 988 +#define Z_UTIL_DEC_990 989 +#define Z_UTIL_DEC_991 990 +#define Z_UTIL_DEC_992 991 +#define Z_UTIL_DEC_993 992 +#define Z_UTIL_DEC_994 993 +#define Z_UTIL_DEC_995 994 +#define Z_UTIL_DEC_996 995 +#define Z_UTIL_DEC_997 996 +#define Z_UTIL_DEC_998 997 +#define Z_UTIL_DEC_999 998 +#define Z_UTIL_DEC_1000 999 +#define Z_UTIL_DEC_1001 1000 +#define Z_UTIL_DEC_1002 1001 +#define Z_UTIL_DEC_1003 1002 +#define Z_UTIL_DEC_1004 1003 +#define Z_UTIL_DEC_1005 1004 +#define Z_UTIL_DEC_1006 1005 +#define Z_UTIL_DEC_1007 1006 +#define Z_UTIL_DEC_1008 1007 +#define Z_UTIL_DEC_1009 1008 +#define Z_UTIL_DEC_1010 1009 +#define Z_UTIL_DEC_1011 1010 +#define Z_UTIL_DEC_1012 1011 +#define Z_UTIL_DEC_1013 1012 +#define Z_UTIL_DEC_1014 1013 +#define Z_UTIL_DEC_1015 1014 +#define Z_UTIL_DEC_1016 1015 +#define Z_UTIL_DEC_1017 1016 +#define Z_UTIL_DEC_1018 1017 +#define Z_UTIL_DEC_1019 1018 +#define Z_UTIL_DEC_1020 1019 +#define Z_UTIL_DEC_1021 1020 +#define Z_UTIL_DEC_1022 1021 +#define Z_UTIL_DEC_1023 1022 +#define Z_UTIL_DEC_1024 1023 +#define Z_UTIL_DEC_1025 1024 +#define Z_UTIL_DEC_1026 1025 +#define Z_UTIL_DEC_1027 1026 +#define Z_UTIL_DEC_1028 1027 +#define Z_UTIL_DEC_1029 1028 +#define Z_UTIL_DEC_1030 1029 +#define Z_UTIL_DEC_1031 1030 +#define Z_UTIL_DEC_1032 1031 +#define Z_UTIL_DEC_1033 1032 +#define Z_UTIL_DEC_1034 1033 +#define Z_UTIL_DEC_1035 1034 +#define Z_UTIL_DEC_1036 1035 +#define Z_UTIL_DEC_1037 1036 +#define Z_UTIL_DEC_1038 1037 +#define Z_UTIL_DEC_1039 1038 +#define Z_UTIL_DEC_1040 1039 +#define Z_UTIL_DEC_1041 1040 +#define Z_UTIL_DEC_1042 1041 +#define Z_UTIL_DEC_1043 1042 +#define Z_UTIL_DEC_1044 1043 +#define Z_UTIL_DEC_1045 1044 +#define Z_UTIL_DEC_1046 1045 +#define Z_UTIL_DEC_1047 1046 +#define Z_UTIL_DEC_1048 1047 +#define Z_UTIL_DEC_1049 1048 +#define Z_UTIL_DEC_1050 1049 +#define Z_UTIL_DEC_1051 1050 +#define Z_UTIL_DEC_1052 1051 +#define Z_UTIL_DEC_1053 1052 +#define Z_UTIL_DEC_1054 1053 +#define Z_UTIL_DEC_1055 1054 +#define Z_UTIL_DEC_1056 1055 +#define Z_UTIL_DEC_1057 1056 +#define Z_UTIL_DEC_1058 1057 +#define Z_UTIL_DEC_1059 1058 +#define Z_UTIL_DEC_1060 1059 +#define Z_UTIL_DEC_1061 1060 +#define Z_UTIL_DEC_1062 1061 +#define Z_UTIL_DEC_1063 1062 +#define Z_UTIL_DEC_1064 1063 +#define Z_UTIL_DEC_1065 1064 +#define Z_UTIL_DEC_1066 1065 +#define Z_UTIL_DEC_1067 1066 +#define Z_UTIL_DEC_1068 1067 +#define Z_UTIL_DEC_1069 1068 +#define Z_UTIL_DEC_1070 1069 +#define Z_UTIL_DEC_1071 1070 +#define Z_UTIL_DEC_1072 1071 +#define Z_UTIL_DEC_1073 1072 +#define Z_UTIL_DEC_1074 1073 +#define Z_UTIL_DEC_1075 1074 +#define Z_UTIL_DEC_1076 1075 +#define Z_UTIL_DEC_1077 1076 +#define Z_UTIL_DEC_1078 1077 +#define Z_UTIL_DEC_1079 1078 +#define Z_UTIL_DEC_1080 1079 +#define Z_UTIL_DEC_1081 1080 +#define Z_UTIL_DEC_1082 1081 +#define Z_UTIL_DEC_1083 1082 +#define Z_UTIL_DEC_1084 1083 +#define Z_UTIL_DEC_1085 1084 +#define Z_UTIL_DEC_1086 1085 +#define Z_UTIL_DEC_1087 1086 +#define Z_UTIL_DEC_1088 1087 +#define Z_UTIL_DEC_1089 1088 +#define Z_UTIL_DEC_1090 1089 +#define Z_UTIL_DEC_1091 1090 +#define Z_UTIL_DEC_1092 1091 +#define Z_UTIL_DEC_1093 1092 +#define Z_UTIL_DEC_1094 1093 +#define Z_UTIL_DEC_1095 1094 +#define Z_UTIL_DEC_1096 1095 +#define Z_UTIL_DEC_1097 1096 +#define Z_UTIL_DEC_1098 1097 +#define Z_UTIL_DEC_1099 1098 +#define Z_UTIL_DEC_1100 1099 +#define Z_UTIL_DEC_1101 1100 +#define Z_UTIL_DEC_1102 1101 +#define Z_UTIL_DEC_1103 1102 +#define Z_UTIL_DEC_1104 1103 +#define Z_UTIL_DEC_1105 1104 +#define Z_UTIL_DEC_1106 1105 +#define Z_UTIL_DEC_1107 1106 +#define Z_UTIL_DEC_1108 1107 +#define Z_UTIL_DEC_1109 1108 +#define Z_UTIL_DEC_1110 1109 +#define Z_UTIL_DEC_1111 1110 +#define Z_UTIL_DEC_1112 1111 +#define Z_UTIL_DEC_1113 1112 +#define Z_UTIL_DEC_1114 1113 +#define Z_UTIL_DEC_1115 1114 +#define Z_UTIL_DEC_1116 1115 +#define Z_UTIL_DEC_1117 1116 +#define Z_UTIL_DEC_1118 1117 +#define Z_UTIL_DEC_1119 1118 +#define Z_UTIL_DEC_1120 1119 +#define Z_UTIL_DEC_1121 1120 +#define Z_UTIL_DEC_1122 1121 +#define Z_UTIL_DEC_1123 1122 +#define Z_UTIL_DEC_1124 1123 +#define Z_UTIL_DEC_1125 1124 +#define Z_UTIL_DEC_1126 1125 +#define Z_UTIL_DEC_1127 1126 +#define Z_UTIL_DEC_1128 1127 +#define Z_UTIL_DEC_1129 1128 +#define Z_UTIL_DEC_1130 1129 +#define Z_UTIL_DEC_1131 1130 +#define Z_UTIL_DEC_1132 1131 +#define Z_UTIL_DEC_1133 1132 +#define Z_UTIL_DEC_1134 1133 +#define Z_UTIL_DEC_1135 1134 +#define Z_UTIL_DEC_1136 1135 +#define Z_UTIL_DEC_1137 1136 +#define Z_UTIL_DEC_1138 1137 +#define Z_UTIL_DEC_1139 1138 +#define Z_UTIL_DEC_1140 1139 +#define Z_UTIL_DEC_1141 1140 +#define Z_UTIL_DEC_1142 1141 +#define Z_UTIL_DEC_1143 1142 +#define Z_UTIL_DEC_1144 1143 +#define Z_UTIL_DEC_1145 1144 +#define Z_UTIL_DEC_1146 1145 +#define Z_UTIL_DEC_1147 1146 +#define Z_UTIL_DEC_1148 1147 +#define Z_UTIL_DEC_1149 1148 +#define Z_UTIL_DEC_1150 1149 +#define Z_UTIL_DEC_1151 1150 +#define Z_UTIL_DEC_1152 1151 +#define Z_UTIL_DEC_1153 1152 +#define Z_UTIL_DEC_1154 1153 +#define Z_UTIL_DEC_1155 1154 +#define Z_UTIL_DEC_1156 1155 +#define Z_UTIL_DEC_1157 1156 +#define Z_UTIL_DEC_1158 1157 +#define Z_UTIL_DEC_1159 1158 +#define Z_UTIL_DEC_1160 1159 +#define Z_UTIL_DEC_1161 1160 +#define Z_UTIL_DEC_1162 1161 +#define Z_UTIL_DEC_1163 1162 +#define Z_UTIL_DEC_1164 1163 +#define Z_UTIL_DEC_1165 1164 +#define Z_UTIL_DEC_1166 1165 +#define Z_UTIL_DEC_1167 1166 +#define Z_UTIL_DEC_1168 1167 +#define Z_UTIL_DEC_1169 1168 +#define Z_UTIL_DEC_1170 1169 +#define Z_UTIL_DEC_1171 1170 +#define Z_UTIL_DEC_1172 1171 +#define Z_UTIL_DEC_1173 1172 +#define Z_UTIL_DEC_1174 1173 +#define Z_UTIL_DEC_1175 1174 +#define Z_UTIL_DEC_1176 1175 +#define Z_UTIL_DEC_1177 1176 +#define Z_UTIL_DEC_1178 1177 +#define Z_UTIL_DEC_1179 1178 +#define Z_UTIL_DEC_1180 1179 +#define Z_UTIL_DEC_1181 1180 +#define Z_UTIL_DEC_1182 1181 +#define Z_UTIL_DEC_1183 1182 +#define Z_UTIL_DEC_1184 1183 +#define Z_UTIL_DEC_1185 1184 +#define Z_UTIL_DEC_1186 1185 +#define Z_UTIL_DEC_1187 1186 +#define Z_UTIL_DEC_1188 1187 +#define Z_UTIL_DEC_1189 1188 +#define Z_UTIL_DEC_1190 1189 +#define Z_UTIL_DEC_1191 1190 +#define Z_UTIL_DEC_1192 1191 +#define Z_UTIL_DEC_1193 1192 +#define Z_UTIL_DEC_1194 1193 +#define Z_UTIL_DEC_1195 1194 +#define Z_UTIL_DEC_1196 1195 +#define Z_UTIL_DEC_1197 1196 +#define Z_UTIL_DEC_1198 1197 +#define Z_UTIL_DEC_1199 1198 +#define Z_UTIL_DEC_1200 1199 +#define Z_UTIL_DEC_1201 1200 +#define Z_UTIL_DEC_1202 1201 +#define Z_UTIL_DEC_1203 1202 +#define Z_UTIL_DEC_1204 1203 +#define Z_UTIL_DEC_1205 1204 +#define Z_UTIL_DEC_1206 1205 +#define Z_UTIL_DEC_1207 1206 +#define Z_UTIL_DEC_1208 1207 +#define Z_UTIL_DEC_1209 1208 +#define Z_UTIL_DEC_1210 1209 +#define Z_UTIL_DEC_1211 1210 +#define Z_UTIL_DEC_1212 1211 +#define Z_UTIL_DEC_1213 1212 +#define Z_UTIL_DEC_1214 1213 +#define Z_UTIL_DEC_1215 1214 +#define Z_UTIL_DEC_1216 1215 +#define Z_UTIL_DEC_1217 1216 +#define Z_UTIL_DEC_1218 1217 +#define Z_UTIL_DEC_1219 1218 +#define Z_UTIL_DEC_1220 1219 +#define Z_UTIL_DEC_1221 1220 +#define Z_UTIL_DEC_1222 1221 +#define Z_UTIL_DEC_1223 1222 +#define Z_UTIL_DEC_1224 1223 +#define Z_UTIL_DEC_1225 1224 +#define Z_UTIL_DEC_1226 1225 +#define Z_UTIL_DEC_1227 1226 +#define Z_UTIL_DEC_1228 1227 +#define Z_UTIL_DEC_1229 1228 +#define Z_UTIL_DEC_1230 1229 +#define Z_UTIL_DEC_1231 1230 +#define Z_UTIL_DEC_1232 1231 +#define Z_UTIL_DEC_1233 1232 +#define Z_UTIL_DEC_1234 1233 +#define Z_UTIL_DEC_1235 1234 +#define Z_UTIL_DEC_1236 1235 +#define Z_UTIL_DEC_1237 1236 +#define Z_UTIL_DEC_1238 1237 +#define Z_UTIL_DEC_1239 1238 +#define Z_UTIL_DEC_1240 1239 +#define Z_UTIL_DEC_1241 1240 +#define Z_UTIL_DEC_1242 1241 +#define Z_UTIL_DEC_1243 1242 +#define Z_UTIL_DEC_1244 1243 +#define Z_UTIL_DEC_1245 1244 +#define Z_UTIL_DEC_1246 1245 +#define Z_UTIL_DEC_1247 1246 +#define Z_UTIL_DEC_1248 1247 +#define Z_UTIL_DEC_1249 1248 +#define Z_UTIL_DEC_1250 1249 +#define Z_UTIL_DEC_1251 1250 +#define Z_UTIL_DEC_1252 1251 +#define Z_UTIL_DEC_1253 1252 +#define Z_UTIL_DEC_1254 1253 +#define Z_UTIL_DEC_1255 1254 +#define Z_UTIL_DEC_1256 1255 +#define Z_UTIL_DEC_1257 1256 +#define Z_UTIL_DEC_1258 1257 +#define Z_UTIL_DEC_1259 1258 +#define Z_UTIL_DEC_1260 1259 +#define Z_UTIL_DEC_1261 1260 +#define Z_UTIL_DEC_1262 1261 +#define Z_UTIL_DEC_1263 1262 +#define Z_UTIL_DEC_1264 1263 +#define Z_UTIL_DEC_1265 1264 +#define Z_UTIL_DEC_1266 1265 +#define Z_UTIL_DEC_1267 1266 +#define Z_UTIL_DEC_1268 1267 +#define Z_UTIL_DEC_1269 1268 +#define Z_UTIL_DEC_1270 1269 +#define Z_UTIL_DEC_1271 1270 +#define Z_UTIL_DEC_1272 1271 +#define Z_UTIL_DEC_1273 1272 +#define Z_UTIL_DEC_1274 1273 +#define Z_UTIL_DEC_1275 1274 +#define Z_UTIL_DEC_1276 1275 +#define Z_UTIL_DEC_1277 1276 +#define Z_UTIL_DEC_1278 1277 +#define Z_UTIL_DEC_1279 1278 +#define Z_UTIL_DEC_1280 1279 +#define Z_UTIL_DEC_1281 1280 +#define Z_UTIL_DEC_1282 1281 +#define Z_UTIL_DEC_1283 1282 +#define Z_UTIL_DEC_1284 1283 +#define Z_UTIL_DEC_1285 1284 +#define Z_UTIL_DEC_1286 1285 +#define Z_UTIL_DEC_1287 1286 +#define Z_UTIL_DEC_1288 1287 +#define Z_UTIL_DEC_1289 1288 +#define Z_UTIL_DEC_1290 1289 +#define Z_UTIL_DEC_1291 1290 +#define Z_UTIL_DEC_1292 1291 +#define Z_UTIL_DEC_1293 1292 +#define Z_UTIL_DEC_1294 1293 +#define Z_UTIL_DEC_1295 1294 +#define Z_UTIL_DEC_1296 1295 +#define Z_UTIL_DEC_1297 1296 +#define Z_UTIL_DEC_1298 1297 +#define Z_UTIL_DEC_1299 1298 +#define Z_UTIL_DEC_1300 1299 +#define Z_UTIL_DEC_1301 1300 +#define Z_UTIL_DEC_1302 1301 +#define Z_UTIL_DEC_1303 1302 +#define Z_UTIL_DEC_1304 1303 +#define Z_UTIL_DEC_1305 1304 +#define Z_UTIL_DEC_1306 1305 +#define Z_UTIL_DEC_1307 1306 +#define Z_UTIL_DEC_1308 1307 +#define Z_UTIL_DEC_1309 1308 +#define Z_UTIL_DEC_1310 1309 +#define Z_UTIL_DEC_1311 1310 +#define Z_UTIL_DEC_1312 1311 +#define Z_UTIL_DEC_1313 1312 +#define Z_UTIL_DEC_1314 1313 +#define Z_UTIL_DEC_1315 1314 +#define Z_UTIL_DEC_1316 1315 +#define Z_UTIL_DEC_1317 1316 +#define Z_UTIL_DEC_1318 1317 +#define Z_UTIL_DEC_1319 1318 +#define Z_UTIL_DEC_1320 1319 +#define Z_UTIL_DEC_1321 1320 +#define Z_UTIL_DEC_1322 1321 +#define Z_UTIL_DEC_1323 1322 +#define Z_UTIL_DEC_1324 1323 +#define Z_UTIL_DEC_1325 1324 +#define Z_UTIL_DEC_1326 1325 +#define Z_UTIL_DEC_1327 1326 +#define Z_UTIL_DEC_1328 1327 +#define Z_UTIL_DEC_1329 1328 +#define Z_UTIL_DEC_1330 1329 +#define Z_UTIL_DEC_1331 1330 +#define Z_UTIL_DEC_1332 1331 +#define Z_UTIL_DEC_1333 1332 +#define Z_UTIL_DEC_1334 1333 +#define Z_UTIL_DEC_1335 1334 +#define Z_UTIL_DEC_1336 1335 +#define Z_UTIL_DEC_1337 1336 +#define Z_UTIL_DEC_1338 1337 +#define Z_UTIL_DEC_1339 1338 +#define Z_UTIL_DEC_1340 1339 +#define Z_UTIL_DEC_1341 1340 +#define Z_UTIL_DEC_1342 1341 +#define Z_UTIL_DEC_1343 1342 +#define Z_UTIL_DEC_1344 1343 +#define Z_UTIL_DEC_1345 1344 +#define Z_UTIL_DEC_1346 1345 +#define Z_UTIL_DEC_1347 1346 +#define Z_UTIL_DEC_1348 1347 +#define Z_UTIL_DEC_1349 1348 +#define Z_UTIL_DEC_1350 1349 +#define Z_UTIL_DEC_1351 1350 +#define Z_UTIL_DEC_1352 1351 +#define Z_UTIL_DEC_1353 1352 +#define Z_UTIL_DEC_1354 1353 +#define Z_UTIL_DEC_1355 1354 +#define Z_UTIL_DEC_1356 1355 +#define Z_UTIL_DEC_1357 1356 +#define Z_UTIL_DEC_1358 1357 +#define Z_UTIL_DEC_1359 1358 +#define Z_UTIL_DEC_1360 1359 +#define Z_UTIL_DEC_1361 1360 +#define Z_UTIL_DEC_1362 1361 +#define Z_UTIL_DEC_1363 1362 +#define Z_UTIL_DEC_1364 1363 +#define Z_UTIL_DEC_1365 1364 +#define Z_UTIL_DEC_1366 1365 +#define Z_UTIL_DEC_1367 1366 +#define Z_UTIL_DEC_1368 1367 +#define Z_UTIL_DEC_1369 1368 +#define Z_UTIL_DEC_1370 1369 +#define Z_UTIL_DEC_1371 1370 +#define Z_UTIL_DEC_1372 1371 +#define Z_UTIL_DEC_1373 1372 +#define Z_UTIL_DEC_1374 1373 +#define Z_UTIL_DEC_1375 1374 +#define Z_UTIL_DEC_1376 1375 +#define Z_UTIL_DEC_1377 1376 +#define Z_UTIL_DEC_1378 1377 +#define Z_UTIL_DEC_1379 1378 +#define Z_UTIL_DEC_1380 1379 +#define Z_UTIL_DEC_1381 1380 +#define Z_UTIL_DEC_1382 1381 +#define Z_UTIL_DEC_1383 1382 +#define Z_UTIL_DEC_1384 1383 +#define Z_UTIL_DEC_1385 1384 +#define Z_UTIL_DEC_1386 1385 +#define Z_UTIL_DEC_1387 1386 +#define Z_UTIL_DEC_1388 1387 +#define Z_UTIL_DEC_1389 1388 +#define Z_UTIL_DEC_1390 1389 +#define Z_UTIL_DEC_1391 1390 +#define Z_UTIL_DEC_1392 1391 +#define Z_UTIL_DEC_1393 1392 +#define Z_UTIL_DEC_1394 1393 +#define Z_UTIL_DEC_1395 1394 +#define Z_UTIL_DEC_1396 1395 +#define Z_UTIL_DEC_1397 1396 +#define Z_UTIL_DEC_1398 1397 +#define Z_UTIL_DEC_1399 1398 +#define Z_UTIL_DEC_1400 1399 +#define Z_UTIL_DEC_1401 1400 +#define Z_UTIL_DEC_1402 1401 +#define Z_UTIL_DEC_1403 1402 +#define Z_UTIL_DEC_1404 1403 +#define Z_UTIL_DEC_1405 1404 +#define Z_UTIL_DEC_1406 1405 +#define Z_UTIL_DEC_1407 1406 +#define Z_UTIL_DEC_1408 1407 +#define Z_UTIL_DEC_1409 1408 +#define Z_UTIL_DEC_1410 1409 +#define Z_UTIL_DEC_1411 1410 +#define Z_UTIL_DEC_1412 1411 +#define Z_UTIL_DEC_1413 1412 +#define Z_UTIL_DEC_1414 1413 +#define Z_UTIL_DEC_1415 1414 +#define Z_UTIL_DEC_1416 1415 +#define Z_UTIL_DEC_1417 1416 +#define Z_UTIL_DEC_1418 1417 +#define Z_UTIL_DEC_1419 1418 +#define Z_UTIL_DEC_1420 1419 +#define Z_UTIL_DEC_1421 1420 +#define Z_UTIL_DEC_1422 1421 +#define Z_UTIL_DEC_1423 1422 +#define Z_UTIL_DEC_1424 1423 +#define Z_UTIL_DEC_1425 1424 +#define Z_UTIL_DEC_1426 1425 +#define Z_UTIL_DEC_1427 1426 +#define Z_UTIL_DEC_1428 1427 +#define Z_UTIL_DEC_1429 1428 +#define Z_UTIL_DEC_1430 1429 +#define Z_UTIL_DEC_1431 1430 +#define Z_UTIL_DEC_1432 1431 +#define Z_UTIL_DEC_1433 1432 +#define Z_UTIL_DEC_1434 1433 +#define Z_UTIL_DEC_1435 1434 +#define Z_UTIL_DEC_1436 1435 +#define Z_UTIL_DEC_1437 1436 +#define Z_UTIL_DEC_1438 1437 +#define Z_UTIL_DEC_1439 1438 +#define Z_UTIL_DEC_1440 1439 +#define Z_UTIL_DEC_1441 1440 +#define Z_UTIL_DEC_1442 1441 +#define Z_UTIL_DEC_1443 1442 +#define Z_UTIL_DEC_1444 1443 +#define Z_UTIL_DEC_1445 1444 +#define Z_UTIL_DEC_1446 1445 +#define Z_UTIL_DEC_1447 1446 +#define Z_UTIL_DEC_1448 1447 +#define Z_UTIL_DEC_1449 1448 +#define Z_UTIL_DEC_1450 1449 +#define Z_UTIL_DEC_1451 1450 +#define Z_UTIL_DEC_1452 1451 +#define Z_UTIL_DEC_1453 1452 +#define Z_UTIL_DEC_1454 1453 +#define Z_UTIL_DEC_1455 1454 +#define Z_UTIL_DEC_1456 1455 +#define Z_UTIL_DEC_1457 1456 +#define Z_UTIL_DEC_1458 1457 +#define Z_UTIL_DEC_1459 1458 +#define Z_UTIL_DEC_1460 1459 +#define Z_UTIL_DEC_1461 1460 +#define Z_UTIL_DEC_1462 1461 +#define Z_UTIL_DEC_1463 1462 +#define Z_UTIL_DEC_1464 1463 +#define Z_UTIL_DEC_1465 1464 +#define Z_UTIL_DEC_1466 1465 +#define Z_UTIL_DEC_1467 1466 +#define Z_UTIL_DEC_1468 1467 +#define Z_UTIL_DEC_1469 1468 +#define Z_UTIL_DEC_1470 1469 +#define Z_UTIL_DEC_1471 1470 +#define Z_UTIL_DEC_1472 1471 +#define Z_UTIL_DEC_1473 1472 +#define Z_UTIL_DEC_1474 1473 +#define Z_UTIL_DEC_1475 1474 +#define Z_UTIL_DEC_1476 1475 +#define Z_UTIL_DEC_1477 1476 +#define Z_UTIL_DEC_1478 1477 +#define Z_UTIL_DEC_1479 1478 +#define Z_UTIL_DEC_1480 1479 +#define Z_UTIL_DEC_1481 1480 +#define Z_UTIL_DEC_1482 1481 +#define Z_UTIL_DEC_1483 1482 +#define Z_UTIL_DEC_1484 1483 +#define Z_UTIL_DEC_1485 1484 +#define Z_UTIL_DEC_1486 1485 +#define Z_UTIL_DEC_1487 1486 +#define Z_UTIL_DEC_1488 1487 +#define Z_UTIL_DEC_1489 1488 +#define Z_UTIL_DEC_1490 1489 +#define Z_UTIL_DEC_1491 1490 +#define Z_UTIL_DEC_1492 1491 +#define Z_UTIL_DEC_1493 1492 +#define Z_UTIL_DEC_1494 1493 +#define Z_UTIL_DEC_1495 1494 +#define Z_UTIL_DEC_1496 1495 +#define Z_UTIL_DEC_1497 1496 +#define Z_UTIL_DEC_1498 1497 +#define Z_UTIL_DEC_1499 1498 +#define Z_UTIL_DEC_1500 1499 +#define Z_UTIL_DEC_1501 1500 +#define Z_UTIL_DEC_1502 1501 +#define Z_UTIL_DEC_1503 1502 +#define Z_UTIL_DEC_1504 1503 +#define Z_UTIL_DEC_1505 1504 +#define Z_UTIL_DEC_1506 1505 +#define Z_UTIL_DEC_1507 1506 +#define Z_UTIL_DEC_1508 1507 +#define Z_UTIL_DEC_1509 1508 +#define Z_UTIL_DEC_1510 1509 +#define Z_UTIL_DEC_1511 1510 +#define Z_UTIL_DEC_1512 1511 +#define Z_UTIL_DEC_1513 1512 +#define Z_UTIL_DEC_1514 1513 +#define Z_UTIL_DEC_1515 1514 +#define Z_UTIL_DEC_1516 1515 +#define Z_UTIL_DEC_1517 1516 +#define Z_UTIL_DEC_1518 1517 +#define Z_UTIL_DEC_1519 1518 +#define Z_UTIL_DEC_1520 1519 +#define Z_UTIL_DEC_1521 1520 +#define Z_UTIL_DEC_1522 1521 +#define Z_UTIL_DEC_1523 1522 +#define Z_UTIL_DEC_1524 1523 +#define Z_UTIL_DEC_1525 1524 +#define Z_UTIL_DEC_1526 1525 +#define Z_UTIL_DEC_1527 1526 +#define Z_UTIL_DEC_1528 1527 +#define Z_UTIL_DEC_1529 1528 +#define Z_UTIL_DEC_1530 1529 +#define Z_UTIL_DEC_1531 1530 +#define Z_UTIL_DEC_1532 1531 +#define Z_UTIL_DEC_1533 1532 +#define Z_UTIL_DEC_1534 1533 +#define Z_UTIL_DEC_1535 1534 +#define Z_UTIL_DEC_1536 1535 +#define Z_UTIL_DEC_1537 1536 +#define Z_UTIL_DEC_1538 1537 +#define Z_UTIL_DEC_1539 1538 +#define Z_UTIL_DEC_1540 1539 +#define Z_UTIL_DEC_1541 1540 +#define Z_UTIL_DEC_1542 1541 +#define Z_UTIL_DEC_1543 1542 +#define Z_UTIL_DEC_1544 1543 +#define Z_UTIL_DEC_1545 1544 +#define Z_UTIL_DEC_1546 1545 +#define Z_UTIL_DEC_1547 1546 +#define Z_UTIL_DEC_1548 1547 +#define Z_UTIL_DEC_1549 1548 +#define Z_UTIL_DEC_1550 1549 +#define Z_UTIL_DEC_1551 1550 +#define Z_UTIL_DEC_1552 1551 +#define Z_UTIL_DEC_1553 1552 +#define Z_UTIL_DEC_1554 1553 +#define Z_UTIL_DEC_1555 1554 +#define Z_UTIL_DEC_1556 1555 +#define Z_UTIL_DEC_1557 1556 +#define Z_UTIL_DEC_1558 1557 +#define Z_UTIL_DEC_1559 1558 +#define Z_UTIL_DEC_1560 1559 +#define Z_UTIL_DEC_1561 1560 +#define Z_UTIL_DEC_1562 1561 +#define Z_UTIL_DEC_1563 1562 +#define Z_UTIL_DEC_1564 1563 +#define Z_UTIL_DEC_1565 1564 +#define Z_UTIL_DEC_1566 1565 +#define Z_UTIL_DEC_1567 1566 +#define Z_UTIL_DEC_1568 1567 +#define Z_UTIL_DEC_1569 1568 +#define Z_UTIL_DEC_1570 1569 +#define Z_UTIL_DEC_1571 1570 +#define Z_UTIL_DEC_1572 1571 +#define Z_UTIL_DEC_1573 1572 +#define Z_UTIL_DEC_1574 1573 +#define Z_UTIL_DEC_1575 1574 +#define Z_UTIL_DEC_1576 1575 +#define Z_UTIL_DEC_1577 1576 +#define Z_UTIL_DEC_1578 1577 +#define Z_UTIL_DEC_1579 1578 +#define Z_UTIL_DEC_1580 1579 +#define Z_UTIL_DEC_1581 1580 +#define Z_UTIL_DEC_1582 1581 +#define Z_UTIL_DEC_1583 1582 +#define Z_UTIL_DEC_1584 1583 +#define Z_UTIL_DEC_1585 1584 +#define Z_UTIL_DEC_1586 1585 +#define Z_UTIL_DEC_1587 1586 +#define Z_UTIL_DEC_1588 1587 +#define Z_UTIL_DEC_1589 1588 +#define Z_UTIL_DEC_1590 1589 +#define Z_UTIL_DEC_1591 1590 +#define Z_UTIL_DEC_1592 1591 +#define Z_UTIL_DEC_1593 1592 +#define Z_UTIL_DEC_1594 1593 +#define Z_UTIL_DEC_1595 1594 +#define Z_UTIL_DEC_1596 1595 +#define Z_UTIL_DEC_1597 1596 +#define Z_UTIL_DEC_1598 1597 +#define Z_UTIL_DEC_1599 1598 +#define Z_UTIL_DEC_1600 1599 +#define Z_UTIL_DEC_1601 1600 +#define Z_UTIL_DEC_1602 1601 +#define Z_UTIL_DEC_1603 1602 +#define Z_UTIL_DEC_1604 1603 +#define Z_UTIL_DEC_1605 1604 +#define Z_UTIL_DEC_1606 1605 +#define Z_UTIL_DEC_1607 1606 +#define Z_UTIL_DEC_1608 1607 +#define Z_UTIL_DEC_1609 1608 +#define Z_UTIL_DEC_1610 1609 +#define Z_UTIL_DEC_1611 1610 +#define Z_UTIL_DEC_1612 1611 +#define Z_UTIL_DEC_1613 1612 +#define Z_UTIL_DEC_1614 1613 +#define Z_UTIL_DEC_1615 1614 +#define Z_UTIL_DEC_1616 1615 +#define Z_UTIL_DEC_1617 1616 +#define Z_UTIL_DEC_1618 1617 +#define Z_UTIL_DEC_1619 1618 +#define Z_UTIL_DEC_1620 1619 +#define Z_UTIL_DEC_1621 1620 +#define Z_UTIL_DEC_1622 1621 +#define Z_UTIL_DEC_1623 1622 +#define Z_UTIL_DEC_1624 1623 +#define Z_UTIL_DEC_1625 1624 +#define Z_UTIL_DEC_1626 1625 +#define Z_UTIL_DEC_1627 1626 +#define Z_UTIL_DEC_1628 1627 +#define Z_UTIL_DEC_1629 1628 +#define Z_UTIL_DEC_1630 1629 +#define Z_UTIL_DEC_1631 1630 +#define Z_UTIL_DEC_1632 1631 +#define Z_UTIL_DEC_1633 1632 +#define Z_UTIL_DEC_1634 1633 +#define Z_UTIL_DEC_1635 1634 +#define Z_UTIL_DEC_1636 1635 +#define Z_UTIL_DEC_1637 1636 +#define Z_UTIL_DEC_1638 1637 +#define Z_UTIL_DEC_1639 1638 +#define Z_UTIL_DEC_1640 1639 +#define Z_UTIL_DEC_1641 1640 +#define Z_UTIL_DEC_1642 1641 +#define Z_UTIL_DEC_1643 1642 +#define Z_UTIL_DEC_1644 1643 +#define Z_UTIL_DEC_1645 1644 +#define Z_UTIL_DEC_1646 1645 +#define Z_UTIL_DEC_1647 1646 +#define Z_UTIL_DEC_1648 1647 +#define Z_UTIL_DEC_1649 1648 +#define Z_UTIL_DEC_1650 1649 +#define Z_UTIL_DEC_1651 1650 +#define Z_UTIL_DEC_1652 1651 +#define Z_UTIL_DEC_1653 1652 +#define Z_UTIL_DEC_1654 1653 +#define Z_UTIL_DEC_1655 1654 +#define Z_UTIL_DEC_1656 1655 +#define Z_UTIL_DEC_1657 1656 +#define Z_UTIL_DEC_1658 1657 +#define Z_UTIL_DEC_1659 1658 +#define Z_UTIL_DEC_1660 1659 +#define Z_UTIL_DEC_1661 1660 +#define Z_UTIL_DEC_1662 1661 +#define Z_UTIL_DEC_1663 1662 +#define Z_UTIL_DEC_1664 1663 +#define Z_UTIL_DEC_1665 1664 +#define Z_UTIL_DEC_1666 1665 +#define Z_UTIL_DEC_1667 1666 +#define Z_UTIL_DEC_1668 1667 +#define Z_UTIL_DEC_1669 1668 +#define Z_UTIL_DEC_1670 1669 +#define Z_UTIL_DEC_1671 1670 +#define Z_UTIL_DEC_1672 1671 +#define Z_UTIL_DEC_1673 1672 +#define Z_UTIL_DEC_1674 1673 +#define Z_UTIL_DEC_1675 1674 +#define Z_UTIL_DEC_1676 1675 +#define Z_UTIL_DEC_1677 1676 +#define Z_UTIL_DEC_1678 1677 +#define Z_UTIL_DEC_1679 1678 +#define Z_UTIL_DEC_1680 1679 +#define Z_UTIL_DEC_1681 1680 +#define Z_UTIL_DEC_1682 1681 +#define Z_UTIL_DEC_1683 1682 +#define Z_UTIL_DEC_1684 1683 +#define Z_UTIL_DEC_1685 1684 +#define Z_UTIL_DEC_1686 1685 +#define Z_UTIL_DEC_1687 1686 +#define Z_UTIL_DEC_1688 1687 +#define Z_UTIL_DEC_1689 1688 +#define Z_UTIL_DEC_1690 1689 +#define Z_UTIL_DEC_1691 1690 +#define Z_UTIL_DEC_1692 1691 +#define Z_UTIL_DEC_1693 1692 +#define Z_UTIL_DEC_1694 1693 +#define Z_UTIL_DEC_1695 1694 +#define Z_UTIL_DEC_1696 1695 +#define Z_UTIL_DEC_1697 1696 +#define Z_UTIL_DEC_1698 1697 +#define Z_UTIL_DEC_1699 1698 +#define Z_UTIL_DEC_1700 1699 +#define Z_UTIL_DEC_1701 1700 +#define Z_UTIL_DEC_1702 1701 +#define Z_UTIL_DEC_1703 1702 +#define Z_UTIL_DEC_1704 1703 +#define Z_UTIL_DEC_1705 1704 +#define Z_UTIL_DEC_1706 1705 +#define Z_UTIL_DEC_1707 1706 +#define Z_UTIL_DEC_1708 1707 +#define Z_UTIL_DEC_1709 1708 +#define Z_UTIL_DEC_1710 1709 +#define Z_UTIL_DEC_1711 1710 +#define Z_UTIL_DEC_1712 1711 +#define Z_UTIL_DEC_1713 1712 +#define Z_UTIL_DEC_1714 1713 +#define Z_UTIL_DEC_1715 1714 +#define Z_UTIL_DEC_1716 1715 +#define Z_UTIL_DEC_1717 1716 +#define Z_UTIL_DEC_1718 1717 +#define Z_UTIL_DEC_1719 1718 +#define Z_UTIL_DEC_1720 1719 +#define Z_UTIL_DEC_1721 1720 +#define Z_UTIL_DEC_1722 1721 +#define Z_UTIL_DEC_1723 1722 +#define Z_UTIL_DEC_1724 1723 +#define Z_UTIL_DEC_1725 1724 +#define Z_UTIL_DEC_1726 1725 +#define Z_UTIL_DEC_1727 1726 +#define Z_UTIL_DEC_1728 1727 +#define Z_UTIL_DEC_1729 1728 +#define Z_UTIL_DEC_1730 1729 +#define Z_UTIL_DEC_1731 1730 +#define Z_UTIL_DEC_1732 1731 +#define Z_UTIL_DEC_1733 1732 +#define Z_UTIL_DEC_1734 1733 +#define Z_UTIL_DEC_1735 1734 +#define Z_UTIL_DEC_1736 1735 +#define Z_UTIL_DEC_1737 1736 +#define Z_UTIL_DEC_1738 1737 +#define Z_UTIL_DEC_1739 1738 +#define Z_UTIL_DEC_1740 1739 +#define Z_UTIL_DEC_1741 1740 +#define Z_UTIL_DEC_1742 1741 +#define Z_UTIL_DEC_1743 1742 +#define Z_UTIL_DEC_1744 1743 +#define Z_UTIL_DEC_1745 1744 +#define Z_UTIL_DEC_1746 1745 +#define Z_UTIL_DEC_1747 1746 +#define Z_UTIL_DEC_1748 1747 +#define Z_UTIL_DEC_1749 1748 +#define Z_UTIL_DEC_1750 1749 +#define Z_UTIL_DEC_1751 1750 +#define Z_UTIL_DEC_1752 1751 +#define Z_UTIL_DEC_1753 1752 +#define Z_UTIL_DEC_1754 1753 +#define Z_UTIL_DEC_1755 1754 +#define Z_UTIL_DEC_1756 1755 +#define Z_UTIL_DEC_1757 1756 +#define Z_UTIL_DEC_1758 1757 +#define Z_UTIL_DEC_1759 1758 +#define Z_UTIL_DEC_1760 1759 +#define Z_UTIL_DEC_1761 1760 +#define Z_UTIL_DEC_1762 1761 +#define Z_UTIL_DEC_1763 1762 +#define Z_UTIL_DEC_1764 1763 +#define Z_UTIL_DEC_1765 1764 +#define Z_UTIL_DEC_1766 1765 +#define Z_UTIL_DEC_1767 1766 +#define Z_UTIL_DEC_1768 1767 +#define Z_UTIL_DEC_1769 1768 +#define Z_UTIL_DEC_1770 1769 +#define Z_UTIL_DEC_1771 1770 +#define Z_UTIL_DEC_1772 1771 +#define Z_UTIL_DEC_1773 1772 +#define Z_UTIL_DEC_1774 1773 +#define Z_UTIL_DEC_1775 1774 +#define Z_UTIL_DEC_1776 1775 +#define Z_UTIL_DEC_1777 1776 +#define Z_UTIL_DEC_1778 1777 +#define Z_UTIL_DEC_1779 1778 +#define Z_UTIL_DEC_1780 1779 +#define Z_UTIL_DEC_1781 1780 +#define Z_UTIL_DEC_1782 1781 +#define Z_UTIL_DEC_1783 1782 +#define Z_UTIL_DEC_1784 1783 +#define Z_UTIL_DEC_1785 1784 +#define Z_UTIL_DEC_1786 1785 +#define Z_UTIL_DEC_1787 1786 +#define Z_UTIL_DEC_1788 1787 +#define Z_UTIL_DEC_1789 1788 +#define Z_UTIL_DEC_1790 1789 +#define Z_UTIL_DEC_1791 1790 +#define Z_UTIL_DEC_1792 1791 +#define Z_UTIL_DEC_1793 1792 +#define Z_UTIL_DEC_1794 1793 +#define Z_UTIL_DEC_1795 1794 +#define Z_UTIL_DEC_1796 1795 +#define Z_UTIL_DEC_1797 1796 +#define Z_UTIL_DEC_1798 1797 +#define Z_UTIL_DEC_1799 1798 +#define Z_UTIL_DEC_1800 1799 +#define Z_UTIL_DEC_1801 1800 +#define Z_UTIL_DEC_1802 1801 +#define Z_UTIL_DEC_1803 1802 +#define Z_UTIL_DEC_1804 1803 +#define Z_UTIL_DEC_1805 1804 +#define Z_UTIL_DEC_1806 1805 +#define Z_UTIL_DEC_1807 1806 +#define Z_UTIL_DEC_1808 1807 +#define Z_UTIL_DEC_1809 1808 +#define Z_UTIL_DEC_1810 1809 +#define Z_UTIL_DEC_1811 1810 +#define Z_UTIL_DEC_1812 1811 +#define Z_UTIL_DEC_1813 1812 +#define Z_UTIL_DEC_1814 1813 +#define Z_UTIL_DEC_1815 1814 +#define Z_UTIL_DEC_1816 1815 +#define Z_UTIL_DEC_1817 1816 +#define Z_UTIL_DEC_1818 1817 +#define Z_UTIL_DEC_1819 1818 +#define Z_UTIL_DEC_1820 1819 +#define Z_UTIL_DEC_1821 1820 +#define Z_UTIL_DEC_1822 1821 +#define Z_UTIL_DEC_1823 1822 +#define Z_UTIL_DEC_1824 1823 +#define Z_UTIL_DEC_1825 1824 +#define Z_UTIL_DEC_1826 1825 +#define Z_UTIL_DEC_1827 1826 +#define Z_UTIL_DEC_1828 1827 +#define Z_UTIL_DEC_1829 1828 +#define Z_UTIL_DEC_1830 1829 +#define Z_UTIL_DEC_1831 1830 +#define Z_UTIL_DEC_1832 1831 +#define Z_UTIL_DEC_1833 1832 +#define Z_UTIL_DEC_1834 1833 +#define Z_UTIL_DEC_1835 1834 +#define Z_UTIL_DEC_1836 1835 +#define Z_UTIL_DEC_1837 1836 +#define Z_UTIL_DEC_1838 1837 +#define Z_UTIL_DEC_1839 1838 +#define Z_UTIL_DEC_1840 1839 +#define Z_UTIL_DEC_1841 1840 +#define Z_UTIL_DEC_1842 1841 +#define Z_UTIL_DEC_1843 1842 +#define Z_UTIL_DEC_1844 1843 +#define Z_UTIL_DEC_1845 1844 +#define Z_UTIL_DEC_1846 1845 +#define Z_UTIL_DEC_1847 1846 +#define Z_UTIL_DEC_1848 1847 +#define Z_UTIL_DEC_1849 1848 +#define Z_UTIL_DEC_1850 1849 +#define Z_UTIL_DEC_1851 1850 +#define Z_UTIL_DEC_1852 1851 +#define Z_UTIL_DEC_1853 1852 +#define Z_UTIL_DEC_1854 1853 +#define Z_UTIL_DEC_1855 1854 +#define Z_UTIL_DEC_1856 1855 +#define Z_UTIL_DEC_1857 1856 +#define Z_UTIL_DEC_1858 1857 +#define Z_UTIL_DEC_1859 1858 +#define Z_UTIL_DEC_1860 1859 +#define Z_UTIL_DEC_1861 1860 +#define Z_UTIL_DEC_1862 1861 +#define Z_UTIL_DEC_1863 1862 +#define Z_UTIL_DEC_1864 1863 +#define Z_UTIL_DEC_1865 1864 +#define Z_UTIL_DEC_1866 1865 +#define Z_UTIL_DEC_1867 1866 +#define Z_UTIL_DEC_1868 1867 +#define Z_UTIL_DEC_1869 1868 +#define Z_UTIL_DEC_1870 1869 +#define Z_UTIL_DEC_1871 1870 +#define Z_UTIL_DEC_1872 1871 +#define Z_UTIL_DEC_1873 1872 +#define Z_UTIL_DEC_1874 1873 +#define Z_UTIL_DEC_1875 1874 +#define Z_UTIL_DEC_1876 1875 +#define Z_UTIL_DEC_1877 1876 +#define Z_UTIL_DEC_1878 1877 +#define Z_UTIL_DEC_1879 1878 +#define Z_UTIL_DEC_1880 1879 +#define Z_UTIL_DEC_1881 1880 +#define Z_UTIL_DEC_1882 1881 +#define Z_UTIL_DEC_1883 1882 +#define Z_UTIL_DEC_1884 1883 +#define Z_UTIL_DEC_1885 1884 +#define Z_UTIL_DEC_1886 1885 +#define Z_UTIL_DEC_1887 1886 +#define Z_UTIL_DEC_1888 1887 +#define Z_UTIL_DEC_1889 1888 +#define Z_UTIL_DEC_1890 1889 +#define Z_UTIL_DEC_1891 1890 +#define Z_UTIL_DEC_1892 1891 +#define Z_UTIL_DEC_1893 1892 +#define Z_UTIL_DEC_1894 1893 +#define Z_UTIL_DEC_1895 1894 +#define Z_UTIL_DEC_1896 1895 +#define Z_UTIL_DEC_1897 1896 +#define Z_UTIL_DEC_1898 1897 +#define Z_UTIL_DEC_1899 1898 +#define Z_UTIL_DEC_1900 1899 +#define Z_UTIL_DEC_1901 1900 +#define Z_UTIL_DEC_1902 1901 +#define Z_UTIL_DEC_1903 1902 +#define Z_UTIL_DEC_1904 1903 +#define Z_UTIL_DEC_1905 1904 +#define Z_UTIL_DEC_1906 1905 +#define Z_UTIL_DEC_1907 1906 +#define Z_UTIL_DEC_1908 1907 +#define Z_UTIL_DEC_1909 1908 +#define Z_UTIL_DEC_1910 1909 +#define Z_UTIL_DEC_1911 1910 +#define Z_UTIL_DEC_1912 1911 +#define Z_UTIL_DEC_1913 1912 +#define Z_UTIL_DEC_1914 1913 +#define Z_UTIL_DEC_1915 1914 +#define Z_UTIL_DEC_1916 1915 +#define Z_UTIL_DEC_1917 1916 +#define Z_UTIL_DEC_1918 1917 +#define Z_UTIL_DEC_1919 1918 +#define Z_UTIL_DEC_1920 1919 +#define Z_UTIL_DEC_1921 1920 +#define Z_UTIL_DEC_1922 1921 +#define Z_UTIL_DEC_1923 1922 +#define Z_UTIL_DEC_1924 1923 +#define Z_UTIL_DEC_1925 1924 +#define Z_UTIL_DEC_1926 1925 +#define Z_UTIL_DEC_1927 1926 +#define Z_UTIL_DEC_1928 1927 +#define Z_UTIL_DEC_1929 1928 +#define Z_UTIL_DEC_1930 1929 +#define Z_UTIL_DEC_1931 1930 +#define Z_UTIL_DEC_1932 1931 +#define Z_UTIL_DEC_1933 1932 +#define Z_UTIL_DEC_1934 1933 +#define Z_UTIL_DEC_1935 1934 +#define Z_UTIL_DEC_1936 1935 +#define Z_UTIL_DEC_1937 1936 +#define Z_UTIL_DEC_1938 1937 +#define Z_UTIL_DEC_1939 1938 +#define Z_UTIL_DEC_1940 1939 +#define Z_UTIL_DEC_1941 1940 +#define Z_UTIL_DEC_1942 1941 +#define Z_UTIL_DEC_1943 1942 +#define Z_UTIL_DEC_1944 1943 +#define Z_UTIL_DEC_1945 1944 +#define Z_UTIL_DEC_1946 1945 +#define Z_UTIL_DEC_1947 1946 +#define Z_UTIL_DEC_1948 1947 +#define Z_UTIL_DEC_1949 1948 +#define Z_UTIL_DEC_1950 1949 +#define Z_UTIL_DEC_1951 1950 +#define Z_UTIL_DEC_1952 1951 +#define Z_UTIL_DEC_1953 1952 +#define Z_UTIL_DEC_1954 1953 +#define Z_UTIL_DEC_1955 1954 +#define Z_UTIL_DEC_1956 1955 +#define Z_UTIL_DEC_1957 1956 +#define Z_UTIL_DEC_1958 1957 +#define Z_UTIL_DEC_1959 1958 +#define Z_UTIL_DEC_1960 1959 +#define Z_UTIL_DEC_1961 1960 +#define Z_UTIL_DEC_1962 1961 +#define Z_UTIL_DEC_1963 1962 +#define Z_UTIL_DEC_1964 1963 +#define Z_UTIL_DEC_1965 1964 +#define Z_UTIL_DEC_1966 1965 +#define Z_UTIL_DEC_1967 1966 +#define Z_UTIL_DEC_1968 1967 +#define Z_UTIL_DEC_1969 1968 +#define Z_UTIL_DEC_1970 1969 +#define Z_UTIL_DEC_1971 1970 +#define Z_UTIL_DEC_1972 1971 +#define Z_UTIL_DEC_1973 1972 +#define Z_UTIL_DEC_1974 1973 +#define Z_UTIL_DEC_1975 1974 +#define Z_UTIL_DEC_1976 1975 +#define Z_UTIL_DEC_1977 1976 +#define Z_UTIL_DEC_1978 1977 +#define Z_UTIL_DEC_1979 1978 +#define Z_UTIL_DEC_1980 1979 +#define Z_UTIL_DEC_1981 1980 +#define Z_UTIL_DEC_1982 1981 +#define Z_UTIL_DEC_1983 1982 +#define Z_UTIL_DEC_1984 1983 +#define Z_UTIL_DEC_1985 1984 +#define Z_UTIL_DEC_1986 1985 +#define Z_UTIL_DEC_1987 1986 +#define Z_UTIL_DEC_1988 1987 +#define Z_UTIL_DEC_1989 1988 +#define Z_UTIL_DEC_1990 1989 +#define Z_UTIL_DEC_1991 1990 +#define Z_UTIL_DEC_1992 1991 +#define Z_UTIL_DEC_1993 1992 +#define Z_UTIL_DEC_1994 1993 +#define Z_UTIL_DEC_1995 1994 +#define Z_UTIL_DEC_1996 1995 +#define Z_UTIL_DEC_1997 1996 +#define Z_UTIL_DEC_1998 1997 +#define Z_UTIL_DEC_1999 1998 +#define Z_UTIL_DEC_2000 1999 +#define Z_UTIL_DEC_2001 2000 +#define Z_UTIL_DEC_2002 2001 +#define Z_UTIL_DEC_2003 2002 +#define Z_UTIL_DEC_2004 2003 +#define Z_UTIL_DEC_2005 2004 +#define Z_UTIL_DEC_2006 2005 +#define Z_UTIL_DEC_2007 2006 +#define Z_UTIL_DEC_2008 2007 +#define Z_UTIL_DEC_2009 2008 +#define Z_UTIL_DEC_2010 2009 +#define Z_UTIL_DEC_2011 2010 +#define Z_UTIL_DEC_2012 2011 +#define Z_UTIL_DEC_2013 2012 +#define Z_UTIL_DEC_2014 2013 +#define Z_UTIL_DEC_2015 2014 +#define Z_UTIL_DEC_2016 2015 +#define Z_UTIL_DEC_2017 2016 +#define Z_UTIL_DEC_2018 2017 +#define Z_UTIL_DEC_2019 2018 +#define Z_UTIL_DEC_2020 2019 +#define Z_UTIL_DEC_2021 2020 +#define Z_UTIL_DEC_2022 2021 +#define Z_UTIL_DEC_2023 2022 +#define Z_UTIL_DEC_2024 2023 +#define Z_UTIL_DEC_2025 2024 +#define Z_UTIL_DEC_2026 2025 +#define Z_UTIL_DEC_2027 2026 +#define Z_UTIL_DEC_2028 2027 +#define Z_UTIL_DEC_2029 2028 +#define Z_UTIL_DEC_2030 2029 +#define Z_UTIL_DEC_2031 2030 +#define Z_UTIL_DEC_2032 2031 +#define Z_UTIL_DEC_2033 2032 +#define Z_UTIL_DEC_2034 2033 +#define Z_UTIL_DEC_2035 2034 +#define Z_UTIL_DEC_2036 2035 +#define Z_UTIL_DEC_2037 2036 +#define Z_UTIL_DEC_2038 2037 +#define Z_UTIL_DEC_2039 2038 +#define Z_UTIL_DEC_2040 2039 +#define Z_UTIL_DEC_2041 2040 +#define Z_UTIL_DEC_2042 2041 +#define Z_UTIL_DEC_2043 2042 +#define Z_UTIL_DEC_2044 2043 +#define Z_UTIL_DEC_2045 2044 +#define Z_UTIL_DEC_2046 2045 +#define Z_UTIL_DEC_2047 2046 +#define Z_UTIL_DEC_2048 2047 +#define Z_UTIL_DEC_2049 2048 +#define Z_UTIL_DEC_2050 2049 +#define Z_UTIL_DEC_2051 2050 +#define Z_UTIL_DEC_2052 2051 +#define Z_UTIL_DEC_2053 2052 +#define Z_UTIL_DEC_2054 2053 +#define Z_UTIL_DEC_2055 2054 +#define Z_UTIL_DEC_2056 2055 +#define Z_UTIL_DEC_2057 2056 +#define Z_UTIL_DEC_2058 2057 +#define Z_UTIL_DEC_2059 2058 +#define Z_UTIL_DEC_2060 2059 +#define Z_UTIL_DEC_2061 2060 +#define Z_UTIL_DEC_2062 2061 +#define Z_UTIL_DEC_2063 2062 +#define Z_UTIL_DEC_2064 2063 +#define Z_UTIL_DEC_2065 2064 +#define Z_UTIL_DEC_2066 2065 +#define Z_UTIL_DEC_2067 2066 +#define Z_UTIL_DEC_2068 2067 +#define Z_UTIL_DEC_2069 2068 +#define Z_UTIL_DEC_2070 2069 +#define Z_UTIL_DEC_2071 2070 +#define Z_UTIL_DEC_2072 2071 +#define Z_UTIL_DEC_2073 2072 +#define Z_UTIL_DEC_2074 2073 +#define Z_UTIL_DEC_2075 2074 +#define Z_UTIL_DEC_2076 2075 +#define Z_UTIL_DEC_2077 2076 +#define Z_UTIL_DEC_2078 2077 +#define Z_UTIL_DEC_2079 2078 +#define Z_UTIL_DEC_2080 2079 +#define Z_UTIL_DEC_2081 2080 +#define Z_UTIL_DEC_2082 2081 +#define Z_UTIL_DEC_2083 2082 +#define Z_UTIL_DEC_2084 2083 +#define Z_UTIL_DEC_2085 2084 +#define Z_UTIL_DEC_2086 2085 +#define Z_UTIL_DEC_2087 2086 +#define Z_UTIL_DEC_2088 2087 +#define Z_UTIL_DEC_2089 2088 +#define Z_UTIL_DEC_2090 2089 +#define Z_UTIL_DEC_2091 2090 +#define Z_UTIL_DEC_2092 2091 +#define Z_UTIL_DEC_2093 2092 +#define Z_UTIL_DEC_2094 2093 +#define Z_UTIL_DEC_2095 2094 +#define Z_UTIL_DEC_2096 2095 +#define Z_UTIL_DEC_2097 2096 +#define Z_UTIL_DEC_2098 2097 +#define Z_UTIL_DEC_2099 2098 +#define Z_UTIL_DEC_2100 2099 +#define Z_UTIL_DEC_2101 2100 +#define Z_UTIL_DEC_2102 2101 +#define Z_UTIL_DEC_2103 2102 +#define Z_UTIL_DEC_2104 2103 +#define Z_UTIL_DEC_2105 2104 +#define Z_UTIL_DEC_2106 2105 +#define Z_UTIL_DEC_2107 2106 +#define Z_UTIL_DEC_2108 2107 +#define Z_UTIL_DEC_2109 2108 +#define Z_UTIL_DEC_2110 2109 +#define Z_UTIL_DEC_2111 2110 +#define Z_UTIL_DEC_2112 2111 +#define Z_UTIL_DEC_2113 2112 +#define Z_UTIL_DEC_2114 2113 +#define Z_UTIL_DEC_2115 2114 +#define Z_UTIL_DEC_2116 2115 +#define Z_UTIL_DEC_2117 2116 +#define Z_UTIL_DEC_2118 2117 +#define Z_UTIL_DEC_2119 2118 +#define Z_UTIL_DEC_2120 2119 +#define Z_UTIL_DEC_2121 2120 +#define Z_UTIL_DEC_2122 2121 +#define Z_UTIL_DEC_2123 2122 +#define Z_UTIL_DEC_2124 2123 +#define Z_UTIL_DEC_2125 2124 +#define Z_UTIL_DEC_2126 2125 +#define Z_UTIL_DEC_2127 2126 +#define Z_UTIL_DEC_2128 2127 +#define Z_UTIL_DEC_2129 2128 +#define Z_UTIL_DEC_2130 2129 +#define Z_UTIL_DEC_2131 2130 +#define Z_UTIL_DEC_2132 2131 +#define Z_UTIL_DEC_2133 2132 +#define Z_UTIL_DEC_2134 2133 +#define Z_UTIL_DEC_2135 2134 +#define Z_UTIL_DEC_2136 2135 +#define Z_UTIL_DEC_2137 2136 +#define Z_UTIL_DEC_2138 2137 +#define Z_UTIL_DEC_2139 2138 +#define Z_UTIL_DEC_2140 2139 +#define Z_UTIL_DEC_2141 2140 +#define Z_UTIL_DEC_2142 2141 +#define Z_UTIL_DEC_2143 2142 +#define Z_UTIL_DEC_2144 2143 +#define Z_UTIL_DEC_2145 2144 +#define Z_UTIL_DEC_2146 2145 +#define Z_UTIL_DEC_2147 2146 +#define Z_UTIL_DEC_2148 2147 +#define Z_UTIL_DEC_2149 2148 +#define Z_UTIL_DEC_2150 2149 +#define Z_UTIL_DEC_2151 2150 +#define Z_UTIL_DEC_2152 2151 +#define Z_UTIL_DEC_2153 2152 +#define Z_UTIL_DEC_2154 2153 +#define Z_UTIL_DEC_2155 2154 +#define Z_UTIL_DEC_2156 2155 +#define Z_UTIL_DEC_2157 2156 +#define Z_UTIL_DEC_2158 2157 +#define Z_UTIL_DEC_2159 2158 +#define Z_UTIL_DEC_2160 2159 +#define Z_UTIL_DEC_2161 2160 +#define Z_UTIL_DEC_2162 2161 +#define Z_UTIL_DEC_2163 2162 +#define Z_UTIL_DEC_2164 2163 +#define Z_UTIL_DEC_2165 2164 +#define Z_UTIL_DEC_2166 2165 +#define Z_UTIL_DEC_2167 2166 +#define Z_UTIL_DEC_2168 2167 +#define Z_UTIL_DEC_2169 2168 +#define Z_UTIL_DEC_2170 2169 +#define Z_UTIL_DEC_2171 2170 +#define Z_UTIL_DEC_2172 2171 +#define Z_UTIL_DEC_2173 2172 +#define Z_UTIL_DEC_2174 2173 +#define Z_UTIL_DEC_2175 2174 +#define Z_UTIL_DEC_2176 2175 +#define Z_UTIL_DEC_2177 2176 +#define Z_UTIL_DEC_2178 2177 +#define Z_UTIL_DEC_2179 2178 +#define Z_UTIL_DEC_2180 2179 +#define Z_UTIL_DEC_2181 2180 +#define Z_UTIL_DEC_2182 2181 +#define Z_UTIL_DEC_2183 2182 +#define Z_UTIL_DEC_2184 2183 +#define Z_UTIL_DEC_2185 2184 +#define Z_UTIL_DEC_2186 2185 +#define Z_UTIL_DEC_2187 2186 +#define Z_UTIL_DEC_2188 2187 +#define Z_UTIL_DEC_2189 2188 +#define Z_UTIL_DEC_2190 2189 +#define Z_UTIL_DEC_2191 2190 +#define Z_UTIL_DEC_2192 2191 +#define Z_UTIL_DEC_2193 2192 +#define Z_UTIL_DEC_2194 2193 +#define Z_UTIL_DEC_2195 2194 +#define Z_UTIL_DEC_2196 2195 +#define Z_UTIL_DEC_2197 2196 +#define Z_UTIL_DEC_2198 2197 +#define Z_UTIL_DEC_2199 2198 +#define Z_UTIL_DEC_2200 2199 +#define Z_UTIL_DEC_2201 2200 +#define Z_UTIL_DEC_2202 2201 +#define Z_UTIL_DEC_2203 2202 +#define Z_UTIL_DEC_2204 2203 +#define Z_UTIL_DEC_2205 2204 +#define Z_UTIL_DEC_2206 2205 +#define Z_UTIL_DEC_2207 2206 +#define Z_UTIL_DEC_2208 2207 +#define Z_UTIL_DEC_2209 2208 +#define Z_UTIL_DEC_2210 2209 +#define Z_UTIL_DEC_2211 2210 +#define Z_UTIL_DEC_2212 2211 +#define Z_UTIL_DEC_2213 2212 +#define Z_UTIL_DEC_2214 2213 +#define Z_UTIL_DEC_2215 2214 +#define Z_UTIL_DEC_2216 2215 +#define Z_UTIL_DEC_2217 2216 +#define Z_UTIL_DEC_2218 2217 +#define Z_UTIL_DEC_2219 2218 +#define Z_UTIL_DEC_2220 2219 +#define Z_UTIL_DEC_2221 2220 +#define Z_UTIL_DEC_2222 2221 +#define Z_UTIL_DEC_2223 2222 +#define Z_UTIL_DEC_2224 2223 +#define Z_UTIL_DEC_2225 2224 +#define Z_UTIL_DEC_2226 2225 +#define Z_UTIL_DEC_2227 2226 +#define Z_UTIL_DEC_2228 2227 +#define Z_UTIL_DEC_2229 2228 +#define Z_UTIL_DEC_2230 2229 +#define Z_UTIL_DEC_2231 2230 +#define Z_UTIL_DEC_2232 2231 +#define Z_UTIL_DEC_2233 2232 +#define Z_UTIL_DEC_2234 2233 +#define Z_UTIL_DEC_2235 2234 +#define Z_UTIL_DEC_2236 2235 +#define Z_UTIL_DEC_2237 2236 +#define Z_UTIL_DEC_2238 2237 +#define Z_UTIL_DEC_2239 2238 +#define Z_UTIL_DEC_2240 2239 +#define Z_UTIL_DEC_2241 2240 +#define Z_UTIL_DEC_2242 2241 +#define Z_UTIL_DEC_2243 2242 +#define Z_UTIL_DEC_2244 2243 +#define Z_UTIL_DEC_2245 2244 +#define Z_UTIL_DEC_2246 2245 +#define Z_UTIL_DEC_2247 2246 +#define Z_UTIL_DEC_2248 2247 +#define Z_UTIL_DEC_2249 2248 +#define Z_UTIL_DEC_2250 2249 +#define Z_UTIL_DEC_2251 2250 +#define Z_UTIL_DEC_2252 2251 +#define Z_UTIL_DEC_2253 2252 +#define Z_UTIL_DEC_2254 2253 +#define Z_UTIL_DEC_2255 2254 +#define Z_UTIL_DEC_2256 2255 +#define Z_UTIL_DEC_2257 2256 +#define Z_UTIL_DEC_2258 2257 +#define Z_UTIL_DEC_2259 2258 +#define Z_UTIL_DEC_2260 2259 +#define Z_UTIL_DEC_2261 2260 +#define Z_UTIL_DEC_2262 2261 +#define Z_UTIL_DEC_2263 2262 +#define Z_UTIL_DEC_2264 2263 +#define Z_UTIL_DEC_2265 2264 +#define Z_UTIL_DEC_2266 2265 +#define Z_UTIL_DEC_2267 2266 +#define Z_UTIL_DEC_2268 2267 +#define Z_UTIL_DEC_2269 2268 +#define Z_UTIL_DEC_2270 2269 +#define Z_UTIL_DEC_2271 2270 +#define Z_UTIL_DEC_2272 2271 +#define Z_UTIL_DEC_2273 2272 +#define Z_UTIL_DEC_2274 2273 +#define Z_UTIL_DEC_2275 2274 +#define Z_UTIL_DEC_2276 2275 +#define Z_UTIL_DEC_2277 2276 +#define Z_UTIL_DEC_2278 2277 +#define Z_UTIL_DEC_2279 2278 +#define Z_UTIL_DEC_2280 2279 +#define Z_UTIL_DEC_2281 2280 +#define Z_UTIL_DEC_2282 2281 +#define Z_UTIL_DEC_2283 2282 +#define Z_UTIL_DEC_2284 2283 +#define Z_UTIL_DEC_2285 2284 +#define Z_UTIL_DEC_2286 2285 +#define Z_UTIL_DEC_2287 2286 +#define Z_UTIL_DEC_2288 2287 +#define Z_UTIL_DEC_2289 2288 +#define Z_UTIL_DEC_2290 2289 +#define Z_UTIL_DEC_2291 2290 +#define Z_UTIL_DEC_2292 2291 +#define Z_UTIL_DEC_2293 2292 +#define Z_UTIL_DEC_2294 2293 +#define Z_UTIL_DEC_2295 2294 +#define Z_UTIL_DEC_2296 2295 +#define Z_UTIL_DEC_2297 2296 +#define Z_UTIL_DEC_2298 2297 +#define Z_UTIL_DEC_2299 2298 +#define Z_UTIL_DEC_2300 2299 +#define Z_UTIL_DEC_2301 2300 +#define Z_UTIL_DEC_2302 2301 +#define Z_UTIL_DEC_2303 2302 +#define Z_UTIL_DEC_2304 2303 +#define Z_UTIL_DEC_2305 2304 +#define Z_UTIL_DEC_2306 2305 +#define Z_UTIL_DEC_2307 2306 +#define Z_UTIL_DEC_2308 2307 +#define Z_UTIL_DEC_2309 2308 +#define Z_UTIL_DEC_2310 2309 +#define Z_UTIL_DEC_2311 2310 +#define Z_UTIL_DEC_2312 2311 +#define Z_UTIL_DEC_2313 2312 +#define Z_UTIL_DEC_2314 2313 +#define Z_UTIL_DEC_2315 2314 +#define Z_UTIL_DEC_2316 2315 +#define Z_UTIL_DEC_2317 2316 +#define Z_UTIL_DEC_2318 2317 +#define Z_UTIL_DEC_2319 2318 +#define Z_UTIL_DEC_2320 2319 +#define Z_UTIL_DEC_2321 2320 +#define Z_UTIL_DEC_2322 2321 +#define Z_UTIL_DEC_2323 2322 +#define Z_UTIL_DEC_2324 2323 +#define Z_UTIL_DEC_2325 2324 +#define Z_UTIL_DEC_2326 2325 +#define Z_UTIL_DEC_2327 2326 +#define Z_UTIL_DEC_2328 2327 +#define Z_UTIL_DEC_2329 2328 +#define Z_UTIL_DEC_2330 2329 +#define Z_UTIL_DEC_2331 2330 +#define Z_UTIL_DEC_2332 2331 +#define Z_UTIL_DEC_2333 2332 +#define Z_UTIL_DEC_2334 2333 +#define Z_UTIL_DEC_2335 2334 +#define Z_UTIL_DEC_2336 2335 +#define Z_UTIL_DEC_2337 2336 +#define Z_UTIL_DEC_2338 2337 +#define Z_UTIL_DEC_2339 2338 +#define Z_UTIL_DEC_2340 2339 +#define Z_UTIL_DEC_2341 2340 +#define Z_UTIL_DEC_2342 2341 +#define Z_UTIL_DEC_2343 2342 +#define Z_UTIL_DEC_2344 2343 +#define Z_UTIL_DEC_2345 2344 +#define Z_UTIL_DEC_2346 2345 +#define Z_UTIL_DEC_2347 2346 +#define Z_UTIL_DEC_2348 2347 +#define Z_UTIL_DEC_2349 2348 +#define Z_UTIL_DEC_2350 2349 +#define Z_UTIL_DEC_2351 2350 +#define Z_UTIL_DEC_2352 2351 +#define Z_UTIL_DEC_2353 2352 +#define Z_UTIL_DEC_2354 2353 +#define Z_UTIL_DEC_2355 2354 +#define Z_UTIL_DEC_2356 2355 +#define Z_UTIL_DEC_2357 2356 +#define Z_UTIL_DEC_2358 2357 +#define Z_UTIL_DEC_2359 2358 +#define Z_UTIL_DEC_2360 2359 +#define Z_UTIL_DEC_2361 2360 +#define Z_UTIL_DEC_2362 2361 +#define Z_UTIL_DEC_2363 2362 +#define Z_UTIL_DEC_2364 2363 +#define Z_UTIL_DEC_2365 2364 +#define Z_UTIL_DEC_2366 2365 +#define Z_UTIL_DEC_2367 2366 +#define Z_UTIL_DEC_2368 2367 +#define Z_UTIL_DEC_2369 2368 +#define Z_UTIL_DEC_2370 2369 +#define Z_UTIL_DEC_2371 2370 +#define Z_UTIL_DEC_2372 2371 +#define Z_UTIL_DEC_2373 2372 +#define Z_UTIL_DEC_2374 2373 +#define Z_UTIL_DEC_2375 2374 +#define Z_UTIL_DEC_2376 2375 +#define Z_UTIL_DEC_2377 2376 +#define Z_UTIL_DEC_2378 2377 +#define Z_UTIL_DEC_2379 2378 +#define Z_UTIL_DEC_2380 2379 +#define Z_UTIL_DEC_2381 2380 +#define Z_UTIL_DEC_2382 2381 +#define Z_UTIL_DEC_2383 2382 +#define Z_UTIL_DEC_2384 2383 +#define Z_UTIL_DEC_2385 2384 +#define Z_UTIL_DEC_2386 2385 +#define Z_UTIL_DEC_2387 2386 +#define Z_UTIL_DEC_2388 2387 +#define Z_UTIL_DEC_2389 2388 +#define Z_UTIL_DEC_2390 2389 +#define Z_UTIL_DEC_2391 2390 +#define Z_UTIL_DEC_2392 2391 +#define Z_UTIL_DEC_2393 2392 +#define Z_UTIL_DEC_2394 2393 +#define Z_UTIL_DEC_2395 2394 +#define Z_UTIL_DEC_2396 2395 +#define Z_UTIL_DEC_2397 2396 +#define Z_UTIL_DEC_2398 2397 +#define Z_UTIL_DEC_2399 2398 +#define Z_UTIL_DEC_2400 2399 +#define Z_UTIL_DEC_2401 2400 +#define Z_UTIL_DEC_2402 2401 +#define Z_UTIL_DEC_2403 2402 +#define Z_UTIL_DEC_2404 2403 +#define Z_UTIL_DEC_2405 2404 +#define Z_UTIL_DEC_2406 2405 +#define Z_UTIL_DEC_2407 2406 +#define Z_UTIL_DEC_2408 2407 +#define Z_UTIL_DEC_2409 2408 +#define Z_UTIL_DEC_2410 2409 +#define Z_UTIL_DEC_2411 2410 +#define Z_UTIL_DEC_2412 2411 +#define Z_UTIL_DEC_2413 2412 +#define Z_UTIL_DEC_2414 2413 +#define Z_UTIL_DEC_2415 2414 +#define Z_UTIL_DEC_2416 2415 +#define Z_UTIL_DEC_2417 2416 +#define Z_UTIL_DEC_2418 2417 +#define Z_UTIL_DEC_2419 2418 +#define Z_UTIL_DEC_2420 2419 +#define Z_UTIL_DEC_2421 2420 +#define Z_UTIL_DEC_2422 2421 +#define Z_UTIL_DEC_2423 2422 +#define Z_UTIL_DEC_2424 2423 +#define Z_UTIL_DEC_2425 2424 +#define Z_UTIL_DEC_2426 2425 +#define Z_UTIL_DEC_2427 2426 +#define Z_UTIL_DEC_2428 2427 +#define Z_UTIL_DEC_2429 2428 +#define Z_UTIL_DEC_2430 2429 +#define Z_UTIL_DEC_2431 2430 +#define Z_UTIL_DEC_2432 2431 +#define Z_UTIL_DEC_2433 2432 +#define Z_UTIL_DEC_2434 2433 +#define Z_UTIL_DEC_2435 2434 +#define Z_UTIL_DEC_2436 2435 +#define Z_UTIL_DEC_2437 2436 +#define Z_UTIL_DEC_2438 2437 +#define Z_UTIL_DEC_2439 2438 +#define Z_UTIL_DEC_2440 2439 +#define Z_UTIL_DEC_2441 2440 +#define Z_UTIL_DEC_2442 2441 +#define Z_UTIL_DEC_2443 2442 +#define Z_UTIL_DEC_2444 2443 +#define Z_UTIL_DEC_2445 2444 +#define Z_UTIL_DEC_2446 2445 +#define Z_UTIL_DEC_2447 2446 +#define Z_UTIL_DEC_2448 2447 +#define Z_UTIL_DEC_2449 2448 +#define Z_UTIL_DEC_2450 2449 +#define Z_UTIL_DEC_2451 2450 +#define Z_UTIL_DEC_2452 2451 +#define Z_UTIL_DEC_2453 2452 +#define Z_UTIL_DEC_2454 2453 +#define Z_UTIL_DEC_2455 2454 +#define Z_UTIL_DEC_2456 2455 +#define Z_UTIL_DEC_2457 2456 +#define Z_UTIL_DEC_2458 2457 +#define Z_UTIL_DEC_2459 2458 +#define Z_UTIL_DEC_2460 2459 +#define Z_UTIL_DEC_2461 2460 +#define Z_UTIL_DEC_2462 2461 +#define Z_UTIL_DEC_2463 2462 +#define Z_UTIL_DEC_2464 2463 +#define Z_UTIL_DEC_2465 2464 +#define Z_UTIL_DEC_2466 2465 +#define Z_UTIL_DEC_2467 2466 +#define Z_UTIL_DEC_2468 2467 +#define Z_UTIL_DEC_2469 2468 +#define Z_UTIL_DEC_2470 2469 +#define Z_UTIL_DEC_2471 2470 +#define Z_UTIL_DEC_2472 2471 +#define Z_UTIL_DEC_2473 2472 +#define Z_UTIL_DEC_2474 2473 +#define Z_UTIL_DEC_2475 2474 +#define Z_UTIL_DEC_2476 2475 +#define Z_UTIL_DEC_2477 2476 +#define Z_UTIL_DEC_2478 2477 +#define Z_UTIL_DEC_2479 2478 +#define Z_UTIL_DEC_2480 2479 +#define Z_UTIL_DEC_2481 2480 +#define Z_UTIL_DEC_2482 2481 +#define Z_UTIL_DEC_2483 2482 +#define Z_UTIL_DEC_2484 2483 +#define Z_UTIL_DEC_2485 2484 +#define Z_UTIL_DEC_2486 2485 +#define Z_UTIL_DEC_2487 2486 +#define Z_UTIL_DEC_2488 2487 +#define Z_UTIL_DEC_2489 2488 +#define Z_UTIL_DEC_2490 2489 +#define Z_UTIL_DEC_2491 2490 +#define Z_UTIL_DEC_2492 2491 +#define Z_UTIL_DEC_2493 2492 +#define Z_UTIL_DEC_2494 2493 +#define Z_UTIL_DEC_2495 2494 +#define Z_UTIL_DEC_2496 2495 +#define Z_UTIL_DEC_2497 2496 +#define Z_UTIL_DEC_2498 2497 +#define Z_UTIL_DEC_2499 2498 +#define Z_UTIL_DEC_2500 2499 +#define Z_UTIL_DEC_2501 2500 +#define Z_UTIL_DEC_2502 2501 +#define Z_UTIL_DEC_2503 2502 +#define Z_UTIL_DEC_2504 2503 +#define Z_UTIL_DEC_2505 2504 +#define Z_UTIL_DEC_2506 2505 +#define Z_UTIL_DEC_2507 2506 +#define Z_UTIL_DEC_2508 2507 +#define Z_UTIL_DEC_2509 2508 +#define Z_UTIL_DEC_2510 2509 +#define Z_UTIL_DEC_2511 2510 +#define Z_UTIL_DEC_2512 2511 +#define Z_UTIL_DEC_2513 2512 +#define Z_UTIL_DEC_2514 2513 +#define Z_UTIL_DEC_2515 2514 +#define Z_UTIL_DEC_2516 2515 +#define Z_UTIL_DEC_2517 2516 +#define Z_UTIL_DEC_2518 2517 +#define Z_UTIL_DEC_2519 2518 +#define Z_UTIL_DEC_2520 2519 +#define Z_UTIL_DEC_2521 2520 +#define Z_UTIL_DEC_2522 2521 +#define Z_UTIL_DEC_2523 2522 +#define Z_UTIL_DEC_2524 2523 +#define Z_UTIL_DEC_2525 2524 +#define Z_UTIL_DEC_2526 2525 +#define Z_UTIL_DEC_2527 2526 +#define Z_UTIL_DEC_2528 2527 +#define Z_UTIL_DEC_2529 2528 +#define Z_UTIL_DEC_2530 2529 +#define Z_UTIL_DEC_2531 2530 +#define Z_UTIL_DEC_2532 2531 +#define Z_UTIL_DEC_2533 2532 +#define Z_UTIL_DEC_2534 2533 +#define Z_UTIL_DEC_2535 2534 +#define Z_UTIL_DEC_2536 2535 +#define Z_UTIL_DEC_2537 2536 +#define Z_UTIL_DEC_2538 2537 +#define Z_UTIL_DEC_2539 2538 +#define Z_UTIL_DEC_2540 2539 +#define Z_UTIL_DEC_2541 2540 +#define Z_UTIL_DEC_2542 2541 +#define Z_UTIL_DEC_2543 2542 +#define Z_UTIL_DEC_2544 2543 +#define Z_UTIL_DEC_2545 2544 +#define Z_UTIL_DEC_2546 2545 +#define Z_UTIL_DEC_2547 2546 +#define Z_UTIL_DEC_2548 2547 +#define Z_UTIL_DEC_2549 2548 +#define Z_UTIL_DEC_2550 2549 +#define Z_UTIL_DEC_2551 2550 +#define Z_UTIL_DEC_2552 2551 +#define Z_UTIL_DEC_2553 2552 +#define Z_UTIL_DEC_2554 2553 +#define Z_UTIL_DEC_2555 2554 +#define Z_UTIL_DEC_2556 2555 +#define Z_UTIL_DEC_2557 2556 +#define Z_UTIL_DEC_2558 2557 +#define Z_UTIL_DEC_2559 2558 +#define Z_UTIL_DEC_2560 2559 +#define Z_UTIL_DEC_2561 2560 +#define Z_UTIL_DEC_2562 2561 +#define Z_UTIL_DEC_2563 2562 +#define Z_UTIL_DEC_2564 2563 +#define Z_UTIL_DEC_2565 2564 +#define Z_UTIL_DEC_2566 2565 +#define Z_UTIL_DEC_2567 2566 +#define Z_UTIL_DEC_2568 2567 +#define Z_UTIL_DEC_2569 2568 +#define Z_UTIL_DEC_2570 2569 +#define Z_UTIL_DEC_2571 2570 +#define Z_UTIL_DEC_2572 2571 +#define Z_UTIL_DEC_2573 2572 +#define Z_UTIL_DEC_2574 2573 +#define Z_UTIL_DEC_2575 2574 +#define Z_UTIL_DEC_2576 2575 +#define Z_UTIL_DEC_2577 2576 +#define Z_UTIL_DEC_2578 2577 +#define Z_UTIL_DEC_2579 2578 +#define Z_UTIL_DEC_2580 2579 +#define Z_UTIL_DEC_2581 2580 +#define Z_UTIL_DEC_2582 2581 +#define Z_UTIL_DEC_2583 2582 +#define Z_UTIL_DEC_2584 2583 +#define Z_UTIL_DEC_2585 2584 +#define Z_UTIL_DEC_2586 2585 +#define Z_UTIL_DEC_2587 2586 +#define Z_UTIL_DEC_2588 2587 +#define Z_UTIL_DEC_2589 2588 +#define Z_UTIL_DEC_2590 2589 +#define Z_UTIL_DEC_2591 2590 +#define Z_UTIL_DEC_2592 2591 +#define Z_UTIL_DEC_2593 2592 +#define Z_UTIL_DEC_2594 2593 +#define Z_UTIL_DEC_2595 2594 +#define Z_UTIL_DEC_2596 2595 +#define Z_UTIL_DEC_2597 2596 +#define Z_UTIL_DEC_2598 2597 +#define Z_UTIL_DEC_2599 2598 +#define Z_UTIL_DEC_2600 2599 +#define Z_UTIL_DEC_2601 2600 +#define Z_UTIL_DEC_2602 2601 +#define Z_UTIL_DEC_2603 2602 +#define Z_UTIL_DEC_2604 2603 +#define Z_UTIL_DEC_2605 2604 +#define Z_UTIL_DEC_2606 2605 +#define Z_UTIL_DEC_2607 2606 +#define Z_UTIL_DEC_2608 2607 +#define Z_UTIL_DEC_2609 2608 +#define Z_UTIL_DEC_2610 2609 +#define Z_UTIL_DEC_2611 2610 +#define Z_UTIL_DEC_2612 2611 +#define Z_UTIL_DEC_2613 2612 +#define Z_UTIL_DEC_2614 2613 +#define Z_UTIL_DEC_2615 2614 +#define Z_UTIL_DEC_2616 2615 +#define Z_UTIL_DEC_2617 2616 +#define Z_UTIL_DEC_2618 2617 +#define Z_UTIL_DEC_2619 2618 +#define Z_UTIL_DEC_2620 2619 +#define Z_UTIL_DEC_2621 2620 +#define Z_UTIL_DEC_2622 2621 +#define Z_UTIL_DEC_2623 2622 +#define Z_UTIL_DEC_2624 2623 +#define Z_UTIL_DEC_2625 2624 +#define Z_UTIL_DEC_2626 2625 +#define Z_UTIL_DEC_2627 2626 +#define Z_UTIL_DEC_2628 2627 +#define Z_UTIL_DEC_2629 2628 +#define Z_UTIL_DEC_2630 2629 +#define Z_UTIL_DEC_2631 2630 +#define Z_UTIL_DEC_2632 2631 +#define Z_UTIL_DEC_2633 2632 +#define Z_UTIL_DEC_2634 2633 +#define Z_UTIL_DEC_2635 2634 +#define Z_UTIL_DEC_2636 2635 +#define Z_UTIL_DEC_2637 2636 +#define Z_UTIL_DEC_2638 2637 +#define Z_UTIL_DEC_2639 2638 +#define Z_UTIL_DEC_2640 2639 +#define Z_UTIL_DEC_2641 2640 +#define Z_UTIL_DEC_2642 2641 +#define Z_UTIL_DEC_2643 2642 +#define Z_UTIL_DEC_2644 2643 +#define Z_UTIL_DEC_2645 2644 +#define Z_UTIL_DEC_2646 2645 +#define Z_UTIL_DEC_2647 2646 +#define Z_UTIL_DEC_2648 2647 +#define Z_UTIL_DEC_2649 2648 +#define Z_UTIL_DEC_2650 2649 +#define Z_UTIL_DEC_2651 2650 +#define Z_UTIL_DEC_2652 2651 +#define Z_UTIL_DEC_2653 2652 +#define Z_UTIL_DEC_2654 2653 +#define Z_UTIL_DEC_2655 2654 +#define Z_UTIL_DEC_2656 2655 +#define Z_UTIL_DEC_2657 2656 +#define Z_UTIL_DEC_2658 2657 +#define Z_UTIL_DEC_2659 2658 +#define Z_UTIL_DEC_2660 2659 +#define Z_UTIL_DEC_2661 2660 +#define Z_UTIL_DEC_2662 2661 +#define Z_UTIL_DEC_2663 2662 +#define Z_UTIL_DEC_2664 2663 +#define Z_UTIL_DEC_2665 2664 +#define Z_UTIL_DEC_2666 2665 +#define Z_UTIL_DEC_2667 2666 +#define Z_UTIL_DEC_2668 2667 +#define Z_UTIL_DEC_2669 2668 +#define Z_UTIL_DEC_2670 2669 +#define Z_UTIL_DEC_2671 2670 +#define Z_UTIL_DEC_2672 2671 +#define Z_UTIL_DEC_2673 2672 +#define Z_UTIL_DEC_2674 2673 +#define Z_UTIL_DEC_2675 2674 +#define Z_UTIL_DEC_2676 2675 +#define Z_UTIL_DEC_2677 2676 +#define Z_UTIL_DEC_2678 2677 +#define Z_UTIL_DEC_2679 2678 +#define Z_UTIL_DEC_2680 2679 +#define Z_UTIL_DEC_2681 2680 +#define Z_UTIL_DEC_2682 2681 +#define Z_UTIL_DEC_2683 2682 +#define Z_UTIL_DEC_2684 2683 +#define Z_UTIL_DEC_2685 2684 +#define Z_UTIL_DEC_2686 2685 +#define Z_UTIL_DEC_2687 2686 +#define Z_UTIL_DEC_2688 2687 +#define Z_UTIL_DEC_2689 2688 +#define Z_UTIL_DEC_2690 2689 +#define Z_UTIL_DEC_2691 2690 +#define Z_UTIL_DEC_2692 2691 +#define Z_UTIL_DEC_2693 2692 +#define Z_UTIL_DEC_2694 2693 +#define Z_UTIL_DEC_2695 2694 +#define Z_UTIL_DEC_2696 2695 +#define Z_UTIL_DEC_2697 2696 +#define Z_UTIL_DEC_2698 2697 +#define Z_UTIL_DEC_2699 2698 +#define Z_UTIL_DEC_2700 2699 +#define Z_UTIL_DEC_2701 2700 +#define Z_UTIL_DEC_2702 2701 +#define Z_UTIL_DEC_2703 2702 +#define Z_UTIL_DEC_2704 2703 +#define Z_UTIL_DEC_2705 2704 +#define Z_UTIL_DEC_2706 2705 +#define Z_UTIL_DEC_2707 2706 +#define Z_UTIL_DEC_2708 2707 +#define Z_UTIL_DEC_2709 2708 +#define Z_UTIL_DEC_2710 2709 +#define Z_UTIL_DEC_2711 2710 +#define Z_UTIL_DEC_2712 2711 +#define Z_UTIL_DEC_2713 2712 +#define Z_UTIL_DEC_2714 2713 +#define Z_UTIL_DEC_2715 2714 +#define Z_UTIL_DEC_2716 2715 +#define Z_UTIL_DEC_2717 2716 +#define Z_UTIL_DEC_2718 2717 +#define Z_UTIL_DEC_2719 2718 +#define Z_UTIL_DEC_2720 2719 +#define Z_UTIL_DEC_2721 2720 +#define Z_UTIL_DEC_2722 2721 +#define Z_UTIL_DEC_2723 2722 +#define Z_UTIL_DEC_2724 2723 +#define Z_UTIL_DEC_2725 2724 +#define Z_UTIL_DEC_2726 2725 +#define Z_UTIL_DEC_2727 2726 +#define Z_UTIL_DEC_2728 2727 +#define Z_UTIL_DEC_2729 2728 +#define Z_UTIL_DEC_2730 2729 +#define Z_UTIL_DEC_2731 2730 +#define Z_UTIL_DEC_2732 2731 +#define Z_UTIL_DEC_2733 2732 +#define Z_UTIL_DEC_2734 2733 +#define Z_UTIL_DEC_2735 2734 +#define Z_UTIL_DEC_2736 2735 +#define Z_UTIL_DEC_2737 2736 +#define Z_UTIL_DEC_2738 2737 +#define Z_UTIL_DEC_2739 2738 +#define Z_UTIL_DEC_2740 2739 +#define Z_UTIL_DEC_2741 2740 +#define Z_UTIL_DEC_2742 2741 +#define Z_UTIL_DEC_2743 2742 +#define Z_UTIL_DEC_2744 2743 +#define Z_UTIL_DEC_2745 2744 +#define Z_UTIL_DEC_2746 2745 +#define Z_UTIL_DEC_2747 2746 +#define Z_UTIL_DEC_2748 2747 +#define Z_UTIL_DEC_2749 2748 +#define Z_UTIL_DEC_2750 2749 +#define Z_UTIL_DEC_2751 2750 +#define Z_UTIL_DEC_2752 2751 +#define Z_UTIL_DEC_2753 2752 +#define Z_UTIL_DEC_2754 2753 +#define Z_UTIL_DEC_2755 2754 +#define Z_UTIL_DEC_2756 2755 +#define Z_UTIL_DEC_2757 2756 +#define Z_UTIL_DEC_2758 2757 +#define Z_UTIL_DEC_2759 2758 +#define Z_UTIL_DEC_2760 2759 +#define Z_UTIL_DEC_2761 2760 +#define Z_UTIL_DEC_2762 2761 +#define Z_UTIL_DEC_2763 2762 +#define Z_UTIL_DEC_2764 2763 +#define Z_UTIL_DEC_2765 2764 +#define Z_UTIL_DEC_2766 2765 +#define Z_UTIL_DEC_2767 2766 +#define Z_UTIL_DEC_2768 2767 +#define Z_UTIL_DEC_2769 2768 +#define Z_UTIL_DEC_2770 2769 +#define Z_UTIL_DEC_2771 2770 +#define Z_UTIL_DEC_2772 2771 +#define Z_UTIL_DEC_2773 2772 +#define Z_UTIL_DEC_2774 2773 +#define Z_UTIL_DEC_2775 2774 +#define Z_UTIL_DEC_2776 2775 +#define Z_UTIL_DEC_2777 2776 +#define Z_UTIL_DEC_2778 2777 +#define Z_UTIL_DEC_2779 2778 +#define Z_UTIL_DEC_2780 2779 +#define Z_UTIL_DEC_2781 2780 +#define Z_UTIL_DEC_2782 2781 +#define Z_UTIL_DEC_2783 2782 +#define Z_UTIL_DEC_2784 2783 +#define Z_UTIL_DEC_2785 2784 +#define Z_UTIL_DEC_2786 2785 +#define Z_UTIL_DEC_2787 2786 +#define Z_UTIL_DEC_2788 2787 +#define Z_UTIL_DEC_2789 2788 +#define Z_UTIL_DEC_2790 2789 +#define Z_UTIL_DEC_2791 2790 +#define Z_UTIL_DEC_2792 2791 +#define Z_UTIL_DEC_2793 2792 +#define Z_UTIL_DEC_2794 2793 +#define Z_UTIL_DEC_2795 2794 +#define Z_UTIL_DEC_2796 2795 +#define Z_UTIL_DEC_2797 2796 +#define Z_UTIL_DEC_2798 2797 +#define Z_UTIL_DEC_2799 2798 +#define Z_UTIL_DEC_2800 2799 +#define Z_UTIL_DEC_2801 2800 +#define Z_UTIL_DEC_2802 2801 +#define Z_UTIL_DEC_2803 2802 +#define Z_UTIL_DEC_2804 2803 +#define Z_UTIL_DEC_2805 2804 +#define Z_UTIL_DEC_2806 2805 +#define Z_UTIL_DEC_2807 2806 +#define Z_UTIL_DEC_2808 2807 +#define Z_UTIL_DEC_2809 2808 +#define Z_UTIL_DEC_2810 2809 +#define Z_UTIL_DEC_2811 2810 +#define Z_UTIL_DEC_2812 2811 +#define Z_UTIL_DEC_2813 2812 +#define Z_UTIL_DEC_2814 2813 +#define Z_UTIL_DEC_2815 2814 +#define Z_UTIL_DEC_2816 2815 +#define Z_UTIL_DEC_2817 2816 +#define Z_UTIL_DEC_2818 2817 +#define Z_UTIL_DEC_2819 2818 +#define Z_UTIL_DEC_2820 2819 +#define Z_UTIL_DEC_2821 2820 +#define Z_UTIL_DEC_2822 2821 +#define Z_UTIL_DEC_2823 2822 +#define Z_UTIL_DEC_2824 2823 +#define Z_UTIL_DEC_2825 2824 +#define Z_UTIL_DEC_2826 2825 +#define Z_UTIL_DEC_2827 2826 +#define Z_UTIL_DEC_2828 2827 +#define Z_UTIL_DEC_2829 2828 +#define Z_UTIL_DEC_2830 2829 +#define Z_UTIL_DEC_2831 2830 +#define Z_UTIL_DEC_2832 2831 +#define Z_UTIL_DEC_2833 2832 +#define Z_UTIL_DEC_2834 2833 +#define Z_UTIL_DEC_2835 2834 +#define Z_UTIL_DEC_2836 2835 +#define Z_UTIL_DEC_2837 2836 +#define Z_UTIL_DEC_2838 2837 +#define Z_UTIL_DEC_2839 2838 +#define Z_UTIL_DEC_2840 2839 +#define Z_UTIL_DEC_2841 2840 +#define Z_UTIL_DEC_2842 2841 +#define Z_UTIL_DEC_2843 2842 +#define Z_UTIL_DEC_2844 2843 +#define Z_UTIL_DEC_2845 2844 +#define Z_UTIL_DEC_2846 2845 +#define Z_UTIL_DEC_2847 2846 +#define Z_UTIL_DEC_2848 2847 +#define Z_UTIL_DEC_2849 2848 +#define Z_UTIL_DEC_2850 2849 +#define Z_UTIL_DEC_2851 2850 +#define Z_UTIL_DEC_2852 2851 +#define Z_UTIL_DEC_2853 2852 +#define Z_UTIL_DEC_2854 2853 +#define Z_UTIL_DEC_2855 2854 +#define Z_UTIL_DEC_2856 2855 +#define Z_UTIL_DEC_2857 2856 +#define Z_UTIL_DEC_2858 2857 +#define Z_UTIL_DEC_2859 2858 +#define Z_UTIL_DEC_2860 2859 +#define Z_UTIL_DEC_2861 2860 +#define Z_UTIL_DEC_2862 2861 +#define Z_UTIL_DEC_2863 2862 +#define Z_UTIL_DEC_2864 2863 +#define Z_UTIL_DEC_2865 2864 +#define Z_UTIL_DEC_2866 2865 +#define Z_UTIL_DEC_2867 2866 +#define Z_UTIL_DEC_2868 2867 +#define Z_UTIL_DEC_2869 2868 +#define Z_UTIL_DEC_2870 2869 +#define Z_UTIL_DEC_2871 2870 +#define Z_UTIL_DEC_2872 2871 +#define Z_UTIL_DEC_2873 2872 +#define Z_UTIL_DEC_2874 2873 +#define Z_UTIL_DEC_2875 2874 +#define Z_UTIL_DEC_2876 2875 +#define Z_UTIL_DEC_2877 2876 +#define Z_UTIL_DEC_2878 2877 +#define Z_UTIL_DEC_2879 2878 +#define Z_UTIL_DEC_2880 2879 +#define Z_UTIL_DEC_2881 2880 +#define Z_UTIL_DEC_2882 2881 +#define Z_UTIL_DEC_2883 2882 +#define Z_UTIL_DEC_2884 2883 +#define Z_UTIL_DEC_2885 2884 +#define Z_UTIL_DEC_2886 2885 +#define Z_UTIL_DEC_2887 2886 +#define Z_UTIL_DEC_2888 2887 +#define Z_UTIL_DEC_2889 2888 +#define Z_UTIL_DEC_2890 2889 +#define Z_UTIL_DEC_2891 2890 +#define Z_UTIL_DEC_2892 2891 +#define Z_UTIL_DEC_2893 2892 +#define Z_UTIL_DEC_2894 2893 +#define Z_UTIL_DEC_2895 2894 +#define Z_UTIL_DEC_2896 2895 +#define Z_UTIL_DEC_2897 2896 +#define Z_UTIL_DEC_2898 2897 +#define Z_UTIL_DEC_2899 2898 +#define Z_UTIL_DEC_2900 2899 +#define Z_UTIL_DEC_2901 2900 +#define Z_UTIL_DEC_2902 2901 +#define Z_UTIL_DEC_2903 2902 +#define Z_UTIL_DEC_2904 2903 +#define Z_UTIL_DEC_2905 2904 +#define Z_UTIL_DEC_2906 2905 +#define Z_UTIL_DEC_2907 2906 +#define Z_UTIL_DEC_2908 2907 +#define Z_UTIL_DEC_2909 2908 +#define Z_UTIL_DEC_2910 2909 +#define Z_UTIL_DEC_2911 2910 +#define Z_UTIL_DEC_2912 2911 +#define Z_UTIL_DEC_2913 2912 +#define Z_UTIL_DEC_2914 2913 +#define Z_UTIL_DEC_2915 2914 +#define Z_UTIL_DEC_2916 2915 +#define Z_UTIL_DEC_2917 2916 +#define Z_UTIL_DEC_2918 2917 +#define Z_UTIL_DEC_2919 2918 +#define Z_UTIL_DEC_2920 2919 +#define Z_UTIL_DEC_2921 2920 +#define Z_UTIL_DEC_2922 2921 +#define Z_UTIL_DEC_2923 2922 +#define Z_UTIL_DEC_2924 2923 +#define Z_UTIL_DEC_2925 2924 +#define Z_UTIL_DEC_2926 2925 +#define Z_UTIL_DEC_2927 2926 +#define Z_UTIL_DEC_2928 2927 +#define Z_UTIL_DEC_2929 2928 +#define Z_UTIL_DEC_2930 2929 +#define Z_UTIL_DEC_2931 2930 +#define Z_UTIL_DEC_2932 2931 +#define Z_UTIL_DEC_2933 2932 +#define Z_UTIL_DEC_2934 2933 +#define Z_UTIL_DEC_2935 2934 +#define Z_UTIL_DEC_2936 2935 +#define Z_UTIL_DEC_2937 2936 +#define Z_UTIL_DEC_2938 2937 +#define Z_UTIL_DEC_2939 2938 +#define Z_UTIL_DEC_2940 2939 +#define Z_UTIL_DEC_2941 2940 +#define Z_UTIL_DEC_2942 2941 +#define Z_UTIL_DEC_2943 2942 +#define Z_UTIL_DEC_2944 2943 +#define Z_UTIL_DEC_2945 2944 +#define Z_UTIL_DEC_2946 2945 +#define Z_UTIL_DEC_2947 2946 +#define Z_UTIL_DEC_2948 2947 +#define Z_UTIL_DEC_2949 2948 +#define Z_UTIL_DEC_2950 2949 +#define Z_UTIL_DEC_2951 2950 +#define Z_UTIL_DEC_2952 2951 +#define Z_UTIL_DEC_2953 2952 +#define Z_UTIL_DEC_2954 2953 +#define Z_UTIL_DEC_2955 2954 +#define Z_UTIL_DEC_2956 2955 +#define Z_UTIL_DEC_2957 2956 +#define Z_UTIL_DEC_2958 2957 +#define Z_UTIL_DEC_2959 2958 +#define Z_UTIL_DEC_2960 2959 +#define Z_UTIL_DEC_2961 2960 +#define Z_UTIL_DEC_2962 2961 +#define Z_UTIL_DEC_2963 2962 +#define Z_UTIL_DEC_2964 2963 +#define Z_UTIL_DEC_2965 2964 +#define Z_UTIL_DEC_2966 2965 +#define Z_UTIL_DEC_2967 2966 +#define Z_UTIL_DEC_2968 2967 +#define Z_UTIL_DEC_2969 2968 +#define Z_UTIL_DEC_2970 2969 +#define Z_UTIL_DEC_2971 2970 +#define Z_UTIL_DEC_2972 2971 +#define Z_UTIL_DEC_2973 2972 +#define Z_UTIL_DEC_2974 2973 +#define Z_UTIL_DEC_2975 2974 +#define Z_UTIL_DEC_2976 2975 +#define Z_UTIL_DEC_2977 2976 +#define Z_UTIL_DEC_2978 2977 +#define Z_UTIL_DEC_2979 2978 +#define Z_UTIL_DEC_2980 2979 +#define Z_UTIL_DEC_2981 2980 +#define Z_UTIL_DEC_2982 2981 +#define Z_UTIL_DEC_2983 2982 +#define Z_UTIL_DEC_2984 2983 +#define Z_UTIL_DEC_2985 2984 +#define Z_UTIL_DEC_2986 2985 +#define Z_UTIL_DEC_2987 2986 +#define Z_UTIL_DEC_2988 2987 +#define Z_UTIL_DEC_2989 2988 +#define Z_UTIL_DEC_2990 2989 +#define Z_UTIL_DEC_2991 2990 +#define Z_UTIL_DEC_2992 2991 +#define Z_UTIL_DEC_2993 2992 +#define Z_UTIL_DEC_2994 2993 +#define Z_UTIL_DEC_2995 2994 +#define Z_UTIL_DEC_2996 2995 +#define Z_UTIL_DEC_2997 2996 +#define Z_UTIL_DEC_2998 2997 +#define Z_UTIL_DEC_2999 2998 +#define Z_UTIL_DEC_3000 2999 +#define Z_UTIL_DEC_3001 3000 +#define Z_UTIL_DEC_3002 3001 +#define Z_UTIL_DEC_3003 3002 +#define Z_UTIL_DEC_3004 3003 +#define Z_UTIL_DEC_3005 3004 +#define Z_UTIL_DEC_3006 3005 +#define Z_UTIL_DEC_3007 3006 +#define Z_UTIL_DEC_3008 3007 +#define Z_UTIL_DEC_3009 3008 +#define Z_UTIL_DEC_3010 3009 +#define Z_UTIL_DEC_3011 3010 +#define Z_UTIL_DEC_3012 3011 +#define Z_UTIL_DEC_3013 3012 +#define Z_UTIL_DEC_3014 3013 +#define Z_UTIL_DEC_3015 3014 +#define Z_UTIL_DEC_3016 3015 +#define Z_UTIL_DEC_3017 3016 +#define Z_UTIL_DEC_3018 3017 +#define Z_UTIL_DEC_3019 3018 +#define Z_UTIL_DEC_3020 3019 +#define Z_UTIL_DEC_3021 3020 +#define Z_UTIL_DEC_3022 3021 +#define Z_UTIL_DEC_3023 3022 +#define Z_UTIL_DEC_3024 3023 +#define Z_UTIL_DEC_3025 3024 +#define Z_UTIL_DEC_3026 3025 +#define Z_UTIL_DEC_3027 3026 +#define Z_UTIL_DEC_3028 3027 +#define Z_UTIL_DEC_3029 3028 +#define Z_UTIL_DEC_3030 3029 +#define Z_UTIL_DEC_3031 3030 +#define Z_UTIL_DEC_3032 3031 +#define Z_UTIL_DEC_3033 3032 +#define Z_UTIL_DEC_3034 3033 +#define Z_UTIL_DEC_3035 3034 +#define Z_UTIL_DEC_3036 3035 +#define Z_UTIL_DEC_3037 3036 +#define Z_UTIL_DEC_3038 3037 +#define Z_UTIL_DEC_3039 3038 +#define Z_UTIL_DEC_3040 3039 +#define Z_UTIL_DEC_3041 3040 +#define Z_UTIL_DEC_3042 3041 +#define Z_UTIL_DEC_3043 3042 +#define Z_UTIL_DEC_3044 3043 +#define Z_UTIL_DEC_3045 3044 +#define Z_UTIL_DEC_3046 3045 +#define Z_UTIL_DEC_3047 3046 +#define Z_UTIL_DEC_3048 3047 +#define Z_UTIL_DEC_3049 3048 +#define Z_UTIL_DEC_3050 3049 +#define Z_UTIL_DEC_3051 3050 +#define Z_UTIL_DEC_3052 3051 +#define Z_UTIL_DEC_3053 3052 +#define Z_UTIL_DEC_3054 3053 +#define Z_UTIL_DEC_3055 3054 +#define Z_UTIL_DEC_3056 3055 +#define Z_UTIL_DEC_3057 3056 +#define Z_UTIL_DEC_3058 3057 +#define Z_UTIL_DEC_3059 3058 +#define Z_UTIL_DEC_3060 3059 +#define Z_UTIL_DEC_3061 3060 +#define Z_UTIL_DEC_3062 3061 +#define Z_UTIL_DEC_3063 3062 +#define Z_UTIL_DEC_3064 3063 +#define Z_UTIL_DEC_3065 3064 +#define Z_UTIL_DEC_3066 3065 +#define Z_UTIL_DEC_3067 3066 +#define Z_UTIL_DEC_3068 3067 +#define Z_UTIL_DEC_3069 3068 +#define Z_UTIL_DEC_3070 3069 +#define Z_UTIL_DEC_3071 3070 +#define Z_UTIL_DEC_3072 3071 +#define Z_UTIL_DEC_3073 3072 +#define Z_UTIL_DEC_3074 3073 +#define Z_UTIL_DEC_3075 3074 +#define Z_UTIL_DEC_3076 3075 +#define Z_UTIL_DEC_3077 3076 +#define Z_UTIL_DEC_3078 3077 +#define Z_UTIL_DEC_3079 3078 +#define Z_UTIL_DEC_3080 3079 +#define Z_UTIL_DEC_3081 3080 +#define Z_UTIL_DEC_3082 3081 +#define Z_UTIL_DEC_3083 3082 +#define Z_UTIL_DEC_3084 3083 +#define Z_UTIL_DEC_3085 3084 +#define Z_UTIL_DEC_3086 3085 +#define Z_UTIL_DEC_3087 3086 +#define Z_UTIL_DEC_3088 3087 +#define Z_UTIL_DEC_3089 3088 +#define Z_UTIL_DEC_3090 3089 +#define Z_UTIL_DEC_3091 3090 +#define Z_UTIL_DEC_3092 3091 +#define Z_UTIL_DEC_3093 3092 +#define Z_UTIL_DEC_3094 3093 +#define Z_UTIL_DEC_3095 3094 +#define Z_UTIL_DEC_3096 3095 +#define Z_UTIL_DEC_3097 3096 +#define Z_UTIL_DEC_3098 3097 +#define Z_UTIL_DEC_3099 3098 +#define Z_UTIL_DEC_3100 3099 +#define Z_UTIL_DEC_3101 3100 +#define Z_UTIL_DEC_3102 3101 +#define Z_UTIL_DEC_3103 3102 +#define Z_UTIL_DEC_3104 3103 +#define Z_UTIL_DEC_3105 3104 +#define Z_UTIL_DEC_3106 3105 +#define Z_UTIL_DEC_3107 3106 +#define Z_UTIL_DEC_3108 3107 +#define Z_UTIL_DEC_3109 3108 +#define Z_UTIL_DEC_3110 3109 +#define Z_UTIL_DEC_3111 3110 +#define Z_UTIL_DEC_3112 3111 +#define Z_UTIL_DEC_3113 3112 +#define Z_UTIL_DEC_3114 3113 +#define Z_UTIL_DEC_3115 3114 +#define Z_UTIL_DEC_3116 3115 +#define Z_UTIL_DEC_3117 3116 +#define Z_UTIL_DEC_3118 3117 +#define Z_UTIL_DEC_3119 3118 +#define Z_UTIL_DEC_3120 3119 +#define Z_UTIL_DEC_3121 3120 +#define Z_UTIL_DEC_3122 3121 +#define Z_UTIL_DEC_3123 3122 +#define Z_UTIL_DEC_3124 3123 +#define Z_UTIL_DEC_3125 3124 +#define Z_UTIL_DEC_3126 3125 +#define Z_UTIL_DEC_3127 3126 +#define Z_UTIL_DEC_3128 3127 +#define Z_UTIL_DEC_3129 3128 +#define Z_UTIL_DEC_3130 3129 +#define Z_UTIL_DEC_3131 3130 +#define Z_UTIL_DEC_3132 3131 +#define Z_UTIL_DEC_3133 3132 +#define Z_UTIL_DEC_3134 3133 +#define Z_UTIL_DEC_3135 3134 +#define Z_UTIL_DEC_3136 3135 +#define Z_UTIL_DEC_3137 3136 +#define Z_UTIL_DEC_3138 3137 +#define Z_UTIL_DEC_3139 3138 +#define Z_UTIL_DEC_3140 3139 +#define Z_UTIL_DEC_3141 3140 +#define Z_UTIL_DEC_3142 3141 +#define Z_UTIL_DEC_3143 3142 +#define Z_UTIL_DEC_3144 3143 +#define Z_UTIL_DEC_3145 3144 +#define Z_UTIL_DEC_3146 3145 +#define Z_UTIL_DEC_3147 3146 +#define Z_UTIL_DEC_3148 3147 +#define Z_UTIL_DEC_3149 3148 +#define Z_UTIL_DEC_3150 3149 +#define Z_UTIL_DEC_3151 3150 +#define Z_UTIL_DEC_3152 3151 +#define Z_UTIL_DEC_3153 3152 +#define Z_UTIL_DEC_3154 3153 +#define Z_UTIL_DEC_3155 3154 +#define Z_UTIL_DEC_3156 3155 +#define Z_UTIL_DEC_3157 3156 +#define Z_UTIL_DEC_3158 3157 +#define Z_UTIL_DEC_3159 3158 +#define Z_UTIL_DEC_3160 3159 +#define Z_UTIL_DEC_3161 3160 +#define Z_UTIL_DEC_3162 3161 +#define Z_UTIL_DEC_3163 3162 +#define Z_UTIL_DEC_3164 3163 +#define Z_UTIL_DEC_3165 3164 +#define Z_UTIL_DEC_3166 3165 +#define Z_UTIL_DEC_3167 3166 +#define Z_UTIL_DEC_3168 3167 +#define Z_UTIL_DEC_3169 3168 +#define Z_UTIL_DEC_3170 3169 +#define Z_UTIL_DEC_3171 3170 +#define Z_UTIL_DEC_3172 3171 +#define Z_UTIL_DEC_3173 3172 +#define Z_UTIL_DEC_3174 3173 +#define Z_UTIL_DEC_3175 3174 +#define Z_UTIL_DEC_3176 3175 +#define Z_UTIL_DEC_3177 3176 +#define Z_UTIL_DEC_3178 3177 +#define Z_UTIL_DEC_3179 3178 +#define Z_UTIL_DEC_3180 3179 +#define Z_UTIL_DEC_3181 3180 +#define Z_UTIL_DEC_3182 3181 +#define Z_UTIL_DEC_3183 3182 +#define Z_UTIL_DEC_3184 3183 +#define Z_UTIL_DEC_3185 3184 +#define Z_UTIL_DEC_3186 3185 +#define Z_UTIL_DEC_3187 3186 +#define Z_UTIL_DEC_3188 3187 +#define Z_UTIL_DEC_3189 3188 +#define Z_UTIL_DEC_3190 3189 +#define Z_UTIL_DEC_3191 3190 +#define Z_UTIL_DEC_3192 3191 +#define Z_UTIL_DEC_3193 3192 +#define Z_UTIL_DEC_3194 3193 +#define Z_UTIL_DEC_3195 3194 +#define Z_UTIL_DEC_3196 3195 +#define Z_UTIL_DEC_3197 3196 +#define Z_UTIL_DEC_3198 3197 +#define Z_UTIL_DEC_3199 3198 +#define Z_UTIL_DEC_3200 3199 +#define Z_UTIL_DEC_3201 3200 +#define Z_UTIL_DEC_3202 3201 +#define Z_UTIL_DEC_3203 3202 +#define Z_UTIL_DEC_3204 3203 +#define Z_UTIL_DEC_3205 3204 +#define Z_UTIL_DEC_3206 3205 +#define Z_UTIL_DEC_3207 3206 +#define Z_UTIL_DEC_3208 3207 +#define Z_UTIL_DEC_3209 3208 +#define Z_UTIL_DEC_3210 3209 +#define Z_UTIL_DEC_3211 3210 +#define Z_UTIL_DEC_3212 3211 +#define Z_UTIL_DEC_3213 3212 +#define Z_UTIL_DEC_3214 3213 +#define Z_UTIL_DEC_3215 3214 +#define Z_UTIL_DEC_3216 3215 +#define Z_UTIL_DEC_3217 3216 +#define Z_UTIL_DEC_3218 3217 +#define Z_UTIL_DEC_3219 3218 +#define Z_UTIL_DEC_3220 3219 +#define Z_UTIL_DEC_3221 3220 +#define Z_UTIL_DEC_3222 3221 +#define Z_UTIL_DEC_3223 3222 +#define Z_UTIL_DEC_3224 3223 +#define Z_UTIL_DEC_3225 3224 +#define Z_UTIL_DEC_3226 3225 +#define Z_UTIL_DEC_3227 3226 +#define Z_UTIL_DEC_3228 3227 +#define Z_UTIL_DEC_3229 3228 +#define Z_UTIL_DEC_3230 3229 +#define Z_UTIL_DEC_3231 3230 +#define Z_UTIL_DEC_3232 3231 +#define Z_UTIL_DEC_3233 3232 +#define Z_UTIL_DEC_3234 3233 +#define Z_UTIL_DEC_3235 3234 +#define Z_UTIL_DEC_3236 3235 +#define Z_UTIL_DEC_3237 3236 +#define Z_UTIL_DEC_3238 3237 +#define Z_UTIL_DEC_3239 3238 +#define Z_UTIL_DEC_3240 3239 +#define Z_UTIL_DEC_3241 3240 +#define Z_UTIL_DEC_3242 3241 +#define Z_UTIL_DEC_3243 3242 +#define Z_UTIL_DEC_3244 3243 +#define Z_UTIL_DEC_3245 3244 +#define Z_UTIL_DEC_3246 3245 +#define Z_UTIL_DEC_3247 3246 +#define Z_UTIL_DEC_3248 3247 +#define Z_UTIL_DEC_3249 3248 +#define Z_UTIL_DEC_3250 3249 +#define Z_UTIL_DEC_3251 3250 +#define Z_UTIL_DEC_3252 3251 +#define Z_UTIL_DEC_3253 3252 +#define Z_UTIL_DEC_3254 3253 +#define Z_UTIL_DEC_3255 3254 +#define Z_UTIL_DEC_3256 3255 +#define Z_UTIL_DEC_3257 3256 +#define Z_UTIL_DEC_3258 3257 +#define Z_UTIL_DEC_3259 3258 +#define Z_UTIL_DEC_3260 3259 +#define Z_UTIL_DEC_3261 3260 +#define Z_UTIL_DEC_3262 3261 +#define Z_UTIL_DEC_3263 3262 +#define Z_UTIL_DEC_3264 3263 +#define Z_UTIL_DEC_3265 3264 +#define Z_UTIL_DEC_3266 3265 +#define Z_UTIL_DEC_3267 3266 +#define Z_UTIL_DEC_3268 3267 +#define Z_UTIL_DEC_3269 3268 +#define Z_UTIL_DEC_3270 3269 +#define Z_UTIL_DEC_3271 3270 +#define Z_UTIL_DEC_3272 3271 +#define Z_UTIL_DEC_3273 3272 +#define Z_UTIL_DEC_3274 3273 +#define Z_UTIL_DEC_3275 3274 +#define Z_UTIL_DEC_3276 3275 +#define Z_UTIL_DEC_3277 3276 +#define Z_UTIL_DEC_3278 3277 +#define Z_UTIL_DEC_3279 3278 +#define Z_UTIL_DEC_3280 3279 +#define Z_UTIL_DEC_3281 3280 +#define Z_UTIL_DEC_3282 3281 +#define Z_UTIL_DEC_3283 3282 +#define Z_UTIL_DEC_3284 3283 +#define Z_UTIL_DEC_3285 3284 +#define Z_UTIL_DEC_3286 3285 +#define Z_UTIL_DEC_3287 3286 +#define Z_UTIL_DEC_3288 3287 +#define Z_UTIL_DEC_3289 3288 +#define Z_UTIL_DEC_3290 3289 +#define Z_UTIL_DEC_3291 3290 +#define Z_UTIL_DEC_3292 3291 +#define Z_UTIL_DEC_3293 3292 +#define Z_UTIL_DEC_3294 3293 +#define Z_UTIL_DEC_3295 3294 +#define Z_UTIL_DEC_3296 3295 +#define Z_UTIL_DEC_3297 3296 +#define Z_UTIL_DEC_3298 3297 +#define Z_UTIL_DEC_3299 3298 +#define Z_UTIL_DEC_3300 3299 +#define Z_UTIL_DEC_3301 3300 +#define Z_UTIL_DEC_3302 3301 +#define Z_UTIL_DEC_3303 3302 +#define Z_UTIL_DEC_3304 3303 +#define Z_UTIL_DEC_3305 3304 +#define Z_UTIL_DEC_3306 3305 +#define Z_UTIL_DEC_3307 3306 +#define Z_UTIL_DEC_3308 3307 +#define Z_UTIL_DEC_3309 3308 +#define Z_UTIL_DEC_3310 3309 +#define Z_UTIL_DEC_3311 3310 +#define Z_UTIL_DEC_3312 3311 +#define Z_UTIL_DEC_3313 3312 +#define Z_UTIL_DEC_3314 3313 +#define Z_UTIL_DEC_3315 3314 +#define Z_UTIL_DEC_3316 3315 +#define Z_UTIL_DEC_3317 3316 +#define Z_UTIL_DEC_3318 3317 +#define Z_UTIL_DEC_3319 3318 +#define Z_UTIL_DEC_3320 3319 +#define Z_UTIL_DEC_3321 3320 +#define Z_UTIL_DEC_3322 3321 +#define Z_UTIL_DEC_3323 3322 +#define Z_UTIL_DEC_3324 3323 +#define Z_UTIL_DEC_3325 3324 +#define Z_UTIL_DEC_3326 3325 +#define Z_UTIL_DEC_3327 3326 +#define Z_UTIL_DEC_3328 3327 +#define Z_UTIL_DEC_3329 3328 +#define Z_UTIL_DEC_3330 3329 +#define Z_UTIL_DEC_3331 3330 +#define Z_UTIL_DEC_3332 3331 +#define Z_UTIL_DEC_3333 3332 +#define Z_UTIL_DEC_3334 3333 +#define Z_UTIL_DEC_3335 3334 +#define Z_UTIL_DEC_3336 3335 +#define Z_UTIL_DEC_3337 3336 +#define Z_UTIL_DEC_3338 3337 +#define Z_UTIL_DEC_3339 3338 +#define Z_UTIL_DEC_3340 3339 +#define Z_UTIL_DEC_3341 3340 +#define Z_UTIL_DEC_3342 3341 +#define Z_UTIL_DEC_3343 3342 +#define Z_UTIL_DEC_3344 3343 +#define Z_UTIL_DEC_3345 3344 +#define Z_UTIL_DEC_3346 3345 +#define Z_UTIL_DEC_3347 3346 +#define Z_UTIL_DEC_3348 3347 +#define Z_UTIL_DEC_3349 3348 +#define Z_UTIL_DEC_3350 3349 +#define Z_UTIL_DEC_3351 3350 +#define Z_UTIL_DEC_3352 3351 +#define Z_UTIL_DEC_3353 3352 +#define Z_UTIL_DEC_3354 3353 +#define Z_UTIL_DEC_3355 3354 +#define Z_UTIL_DEC_3356 3355 +#define Z_UTIL_DEC_3357 3356 +#define Z_UTIL_DEC_3358 3357 +#define Z_UTIL_DEC_3359 3358 +#define Z_UTIL_DEC_3360 3359 +#define Z_UTIL_DEC_3361 3360 +#define Z_UTIL_DEC_3362 3361 +#define Z_UTIL_DEC_3363 3362 +#define Z_UTIL_DEC_3364 3363 +#define Z_UTIL_DEC_3365 3364 +#define Z_UTIL_DEC_3366 3365 +#define Z_UTIL_DEC_3367 3366 +#define Z_UTIL_DEC_3368 3367 +#define Z_UTIL_DEC_3369 3368 +#define Z_UTIL_DEC_3370 3369 +#define Z_UTIL_DEC_3371 3370 +#define Z_UTIL_DEC_3372 3371 +#define Z_UTIL_DEC_3373 3372 +#define Z_UTIL_DEC_3374 3373 +#define Z_UTIL_DEC_3375 3374 +#define Z_UTIL_DEC_3376 3375 +#define Z_UTIL_DEC_3377 3376 +#define Z_UTIL_DEC_3378 3377 +#define Z_UTIL_DEC_3379 3378 +#define Z_UTIL_DEC_3380 3379 +#define Z_UTIL_DEC_3381 3380 +#define Z_UTIL_DEC_3382 3381 +#define Z_UTIL_DEC_3383 3382 +#define Z_UTIL_DEC_3384 3383 +#define Z_UTIL_DEC_3385 3384 +#define Z_UTIL_DEC_3386 3385 +#define Z_UTIL_DEC_3387 3386 +#define Z_UTIL_DEC_3388 3387 +#define Z_UTIL_DEC_3389 3388 +#define Z_UTIL_DEC_3390 3389 +#define Z_UTIL_DEC_3391 3390 +#define Z_UTIL_DEC_3392 3391 +#define Z_UTIL_DEC_3393 3392 +#define Z_UTIL_DEC_3394 3393 +#define Z_UTIL_DEC_3395 3394 +#define Z_UTIL_DEC_3396 3395 +#define Z_UTIL_DEC_3397 3396 +#define Z_UTIL_DEC_3398 3397 +#define Z_UTIL_DEC_3399 3398 +#define Z_UTIL_DEC_3400 3399 +#define Z_UTIL_DEC_3401 3400 +#define Z_UTIL_DEC_3402 3401 +#define Z_UTIL_DEC_3403 3402 +#define Z_UTIL_DEC_3404 3403 +#define Z_UTIL_DEC_3405 3404 +#define Z_UTIL_DEC_3406 3405 +#define Z_UTIL_DEC_3407 3406 +#define Z_UTIL_DEC_3408 3407 +#define Z_UTIL_DEC_3409 3408 +#define Z_UTIL_DEC_3410 3409 +#define Z_UTIL_DEC_3411 3410 +#define Z_UTIL_DEC_3412 3411 +#define Z_UTIL_DEC_3413 3412 +#define Z_UTIL_DEC_3414 3413 +#define Z_UTIL_DEC_3415 3414 +#define Z_UTIL_DEC_3416 3415 +#define Z_UTIL_DEC_3417 3416 +#define Z_UTIL_DEC_3418 3417 +#define Z_UTIL_DEC_3419 3418 +#define Z_UTIL_DEC_3420 3419 +#define Z_UTIL_DEC_3421 3420 +#define Z_UTIL_DEC_3422 3421 +#define Z_UTIL_DEC_3423 3422 +#define Z_UTIL_DEC_3424 3423 +#define Z_UTIL_DEC_3425 3424 +#define Z_UTIL_DEC_3426 3425 +#define Z_UTIL_DEC_3427 3426 +#define Z_UTIL_DEC_3428 3427 +#define Z_UTIL_DEC_3429 3428 +#define Z_UTIL_DEC_3430 3429 +#define Z_UTIL_DEC_3431 3430 +#define Z_UTIL_DEC_3432 3431 +#define Z_UTIL_DEC_3433 3432 +#define Z_UTIL_DEC_3434 3433 +#define Z_UTIL_DEC_3435 3434 +#define Z_UTIL_DEC_3436 3435 +#define Z_UTIL_DEC_3437 3436 +#define Z_UTIL_DEC_3438 3437 +#define Z_UTIL_DEC_3439 3438 +#define Z_UTIL_DEC_3440 3439 +#define Z_UTIL_DEC_3441 3440 +#define Z_UTIL_DEC_3442 3441 +#define Z_UTIL_DEC_3443 3442 +#define Z_UTIL_DEC_3444 3443 +#define Z_UTIL_DEC_3445 3444 +#define Z_UTIL_DEC_3446 3445 +#define Z_UTIL_DEC_3447 3446 +#define Z_UTIL_DEC_3448 3447 +#define Z_UTIL_DEC_3449 3448 +#define Z_UTIL_DEC_3450 3449 +#define Z_UTIL_DEC_3451 3450 +#define Z_UTIL_DEC_3452 3451 +#define Z_UTIL_DEC_3453 3452 +#define Z_UTIL_DEC_3454 3453 +#define Z_UTIL_DEC_3455 3454 +#define Z_UTIL_DEC_3456 3455 +#define Z_UTIL_DEC_3457 3456 +#define Z_UTIL_DEC_3458 3457 +#define Z_UTIL_DEC_3459 3458 +#define Z_UTIL_DEC_3460 3459 +#define Z_UTIL_DEC_3461 3460 +#define Z_UTIL_DEC_3462 3461 +#define Z_UTIL_DEC_3463 3462 +#define Z_UTIL_DEC_3464 3463 +#define Z_UTIL_DEC_3465 3464 +#define Z_UTIL_DEC_3466 3465 +#define Z_UTIL_DEC_3467 3466 +#define Z_UTIL_DEC_3468 3467 +#define Z_UTIL_DEC_3469 3468 +#define Z_UTIL_DEC_3470 3469 +#define Z_UTIL_DEC_3471 3470 +#define Z_UTIL_DEC_3472 3471 +#define Z_UTIL_DEC_3473 3472 +#define Z_UTIL_DEC_3474 3473 +#define Z_UTIL_DEC_3475 3474 +#define Z_UTIL_DEC_3476 3475 +#define Z_UTIL_DEC_3477 3476 +#define Z_UTIL_DEC_3478 3477 +#define Z_UTIL_DEC_3479 3478 +#define Z_UTIL_DEC_3480 3479 +#define Z_UTIL_DEC_3481 3480 +#define Z_UTIL_DEC_3482 3481 +#define Z_UTIL_DEC_3483 3482 +#define Z_UTIL_DEC_3484 3483 +#define Z_UTIL_DEC_3485 3484 +#define Z_UTIL_DEC_3486 3485 +#define Z_UTIL_DEC_3487 3486 +#define Z_UTIL_DEC_3488 3487 +#define Z_UTIL_DEC_3489 3488 +#define Z_UTIL_DEC_3490 3489 +#define Z_UTIL_DEC_3491 3490 +#define Z_UTIL_DEC_3492 3491 +#define Z_UTIL_DEC_3493 3492 +#define Z_UTIL_DEC_3494 3493 +#define Z_UTIL_DEC_3495 3494 +#define Z_UTIL_DEC_3496 3495 +#define Z_UTIL_DEC_3497 3496 +#define Z_UTIL_DEC_3498 3497 +#define Z_UTIL_DEC_3499 3498 +#define Z_UTIL_DEC_3500 3499 +#define Z_UTIL_DEC_3501 3500 +#define Z_UTIL_DEC_3502 3501 +#define Z_UTIL_DEC_3503 3502 +#define Z_UTIL_DEC_3504 3503 +#define Z_UTIL_DEC_3505 3504 +#define Z_UTIL_DEC_3506 3505 +#define Z_UTIL_DEC_3507 3506 +#define Z_UTIL_DEC_3508 3507 +#define Z_UTIL_DEC_3509 3508 +#define Z_UTIL_DEC_3510 3509 +#define Z_UTIL_DEC_3511 3510 +#define Z_UTIL_DEC_3512 3511 +#define Z_UTIL_DEC_3513 3512 +#define Z_UTIL_DEC_3514 3513 +#define Z_UTIL_DEC_3515 3514 +#define Z_UTIL_DEC_3516 3515 +#define Z_UTIL_DEC_3517 3516 +#define Z_UTIL_DEC_3518 3517 +#define Z_UTIL_DEC_3519 3518 +#define Z_UTIL_DEC_3520 3519 +#define Z_UTIL_DEC_3521 3520 +#define Z_UTIL_DEC_3522 3521 +#define Z_UTIL_DEC_3523 3522 +#define Z_UTIL_DEC_3524 3523 +#define Z_UTIL_DEC_3525 3524 +#define Z_UTIL_DEC_3526 3525 +#define Z_UTIL_DEC_3527 3526 +#define Z_UTIL_DEC_3528 3527 +#define Z_UTIL_DEC_3529 3528 +#define Z_UTIL_DEC_3530 3529 +#define Z_UTIL_DEC_3531 3530 +#define Z_UTIL_DEC_3532 3531 +#define Z_UTIL_DEC_3533 3532 +#define Z_UTIL_DEC_3534 3533 +#define Z_UTIL_DEC_3535 3534 +#define Z_UTIL_DEC_3536 3535 +#define Z_UTIL_DEC_3537 3536 +#define Z_UTIL_DEC_3538 3537 +#define Z_UTIL_DEC_3539 3538 +#define Z_UTIL_DEC_3540 3539 +#define Z_UTIL_DEC_3541 3540 +#define Z_UTIL_DEC_3542 3541 +#define Z_UTIL_DEC_3543 3542 +#define Z_UTIL_DEC_3544 3543 +#define Z_UTIL_DEC_3545 3544 +#define Z_UTIL_DEC_3546 3545 +#define Z_UTIL_DEC_3547 3546 +#define Z_UTIL_DEC_3548 3547 +#define Z_UTIL_DEC_3549 3548 +#define Z_UTIL_DEC_3550 3549 +#define Z_UTIL_DEC_3551 3550 +#define Z_UTIL_DEC_3552 3551 +#define Z_UTIL_DEC_3553 3552 +#define Z_UTIL_DEC_3554 3553 +#define Z_UTIL_DEC_3555 3554 +#define Z_UTIL_DEC_3556 3555 +#define Z_UTIL_DEC_3557 3556 +#define Z_UTIL_DEC_3558 3557 +#define Z_UTIL_DEC_3559 3558 +#define Z_UTIL_DEC_3560 3559 +#define Z_UTIL_DEC_3561 3560 +#define Z_UTIL_DEC_3562 3561 +#define Z_UTIL_DEC_3563 3562 +#define Z_UTIL_DEC_3564 3563 +#define Z_UTIL_DEC_3565 3564 +#define Z_UTIL_DEC_3566 3565 +#define Z_UTIL_DEC_3567 3566 +#define Z_UTIL_DEC_3568 3567 +#define Z_UTIL_DEC_3569 3568 +#define Z_UTIL_DEC_3570 3569 +#define Z_UTIL_DEC_3571 3570 +#define Z_UTIL_DEC_3572 3571 +#define Z_UTIL_DEC_3573 3572 +#define Z_UTIL_DEC_3574 3573 +#define Z_UTIL_DEC_3575 3574 +#define Z_UTIL_DEC_3576 3575 +#define Z_UTIL_DEC_3577 3576 +#define Z_UTIL_DEC_3578 3577 +#define Z_UTIL_DEC_3579 3578 +#define Z_UTIL_DEC_3580 3579 +#define Z_UTIL_DEC_3581 3580 +#define Z_UTIL_DEC_3582 3581 +#define Z_UTIL_DEC_3583 3582 +#define Z_UTIL_DEC_3584 3583 +#define Z_UTIL_DEC_3585 3584 +#define Z_UTIL_DEC_3586 3585 +#define Z_UTIL_DEC_3587 3586 +#define Z_UTIL_DEC_3588 3587 +#define Z_UTIL_DEC_3589 3588 +#define Z_UTIL_DEC_3590 3589 +#define Z_UTIL_DEC_3591 3590 +#define Z_UTIL_DEC_3592 3591 +#define Z_UTIL_DEC_3593 3592 +#define Z_UTIL_DEC_3594 3593 +#define Z_UTIL_DEC_3595 3594 +#define Z_UTIL_DEC_3596 3595 +#define Z_UTIL_DEC_3597 3596 +#define Z_UTIL_DEC_3598 3597 +#define Z_UTIL_DEC_3599 3598 +#define Z_UTIL_DEC_3600 3599 +#define Z_UTIL_DEC_3601 3600 +#define Z_UTIL_DEC_3602 3601 +#define Z_UTIL_DEC_3603 3602 +#define Z_UTIL_DEC_3604 3603 +#define Z_UTIL_DEC_3605 3604 +#define Z_UTIL_DEC_3606 3605 +#define Z_UTIL_DEC_3607 3606 +#define Z_UTIL_DEC_3608 3607 +#define Z_UTIL_DEC_3609 3608 +#define Z_UTIL_DEC_3610 3609 +#define Z_UTIL_DEC_3611 3610 +#define Z_UTIL_DEC_3612 3611 +#define Z_UTIL_DEC_3613 3612 +#define Z_UTIL_DEC_3614 3613 +#define Z_UTIL_DEC_3615 3614 +#define Z_UTIL_DEC_3616 3615 +#define Z_UTIL_DEC_3617 3616 +#define Z_UTIL_DEC_3618 3617 +#define Z_UTIL_DEC_3619 3618 +#define Z_UTIL_DEC_3620 3619 +#define Z_UTIL_DEC_3621 3620 +#define Z_UTIL_DEC_3622 3621 +#define Z_UTIL_DEC_3623 3622 +#define Z_UTIL_DEC_3624 3623 +#define Z_UTIL_DEC_3625 3624 +#define Z_UTIL_DEC_3626 3625 +#define Z_UTIL_DEC_3627 3626 +#define Z_UTIL_DEC_3628 3627 +#define Z_UTIL_DEC_3629 3628 +#define Z_UTIL_DEC_3630 3629 +#define Z_UTIL_DEC_3631 3630 +#define Z_UTIL_DEC_3632 3631 +#define Z_UTIL_DEC_3633 3632 +#define Z_UTIL_DEC_3634 3633 +#define Z_UTIL_DEC_3635 3634 +#define Z_UTIL_DEC_3636 3635 +#define Z_UTIL_DEC_3637 3636 +#define Z_UTIL_DEC_3638 3637 +#define Z_UTIL_DEC_3639 3638 +#define Z_UTIL_DEC_3640 3639 +#define Z_UTIL_DEC_3641 3640 +#define Z_UTIL_DEC_3642 3641 +#define Z_UTIL_DEC_3643 3642 +#define Z_UTIL_DEC_3644 3643 +#define Z_UTIL_DEC_3645 3644 +#define Z_UTIL_DEC_3646 3645 +#define Z_UTIL_DEC_3647 3646 +#define Z_UTIL_DEC_3648 3647 +#define Z_UTIL_DEC_3649 3648 +#define Z_UTIL_DEC_3650 3649 +#define Z_UTIL_DEC_3651 3650 +#define Z_UTIL_DEC_3652 3651 +#define Z_UTIL_DEC_3653 3652 +#define Z_UTIL_DEC_3654 3653 +#define Z_UTIL_DEC_3655 3654 +#define Z_UTIL_DEC_3656 3655 +#define Z_UTIL_DEC_3657 3656 +#define Z_UTIL_DEC_3658 3657 +#define Z_UTIL_DEC_3659 3658 +#define Z_UTIL_DEC_3660 3659 +#define Z_UTIL_DEC_3661 3660 +#define Z_UTIL_DEC_3662 3661 +#define Z_UTIL_DEC_3663 3662 +#define Z_UTIL_DEC_3664 3663 +#define Z_UTIL_DEC_3665 3664 +#define Z_UTIL_DEC_3666 3665 +#define Z_UTIL_DEC_3667 3666 +#define Z_UTIL_DEC_3668 3667 +#define Z_UTIL_DEC_3669 3668 +#define Z_UTIL_DEC_3670 3669 +#define Z_UTIL_DEC_3671 3670 +#define Z_UTIL_DEC_3672 3671 +#define Z_UTIL_DEC_3673 3672 +#define Z_UTIL_DEC_3674 3673 +#define Z_UTIL_DEC_3675 3674 +#define Z_UTIL_DEC_3676 3675 +#define Z_UTIL_DEC_3677 3676 +#define Z_UTIL_DEC_3678 3677 +#define Z_UTIL_DEC_3679 3678 +#define Z_UTIL_DEC_3680 3679 +#define Z_UTIL_DEC_3681 3680 +#define Z_UTIL_DEC_3682 3681 +#define Z_UTIL_DEC_3683 3682 +#define Z_UTIL_DEC_3684 3683 +#define Z_UTIL_DEC_3685 3684 +#define Z_UTIL_DEC_3686 3685 +#define Z_UTIL_DEC_3687 3686 +#define Z_UTIL_DEC_3688 3687 +#define Z_UTIL_DEC_3689 3688 +#define Z_UTIL_DEC_3690 3689 +#define Z_UTIL_DEC_3691 3690 +#define Z_UTIL_DEC_3692 3691 +#define Z_UTIL_DEC_3693 3692 +#define Z_UTIL_DEC_3694 3693 +#define Z_UTIL_DEC_3695 3694 +#define Z_UTIL_DEC_3696 3695 +#define Z_UTIL_DEC_3697 3696 +#define Z_UTIL_DEC_3698 3697 +#define Z_UTIL_DEC_3699 3698 +#define Z_UTIL_DEC_3700 3699 +#define Z_UTIL_DEC_3701 3700 +#define Z_UTIL_DEC_3702 3701 +#define Z_UTIL_DEC_3703 3702 +#define Z_UTIL_DEC_3704 3703 +#define Z_UTIL_DEC_3705 3704 +#define Z_UTIL_DEC_3706 3705 +#define Z_UTIL_DEC_3707 3706 +#define Z_UTIL_DEC_3708 3707 +#define Z_UTIL_DEC_3709 3708 +#define Z_UTIL_DEC_3710 3709 +#define Z_UTIL_DEC_3711 3710 +#define Z_UTIL_DEC_3712 3711 +#define Z_UTIL_DEC_3713 3712 +#define Z_UTIL_DEC_3714 3713 +#define Z_UTIL_DEC_3715 3714 +#define Z_UTIL_DEC_3716 3715 +#define Z_UTIL_DEC_3717 3716 +#define Z_UTIL_DEC_3718 3717 +#define Z_UTIL_DEC_3719 3718 +#define Z_UTIL_DEC_3720 3719 +#define Z_UTIL_DEC_3721 3720 +#define Z_UTIL_DEC_3722 3721 +#define Z_UTIL_DEC_3723 3722 +#define Z_UTIL_DEC_3724 3723 +#define Z_UTIL_DEC_3725 3724 +#define Z_UTIL_DEC_3726 3725 +#define Z_UTIL_DEC_3727 3726 +#define Z_UTIL_DEC_3728 3727 +#define Z_UTIL_DEC_3729 3728 +#define Z_UTIL_DEC_3730 3729 +#define Z_UTIL_DEC_3731 3730 +#define Z_UTIL_DEC_3732 3731 +#define Z_UTIL_DEC_3733 3732 +#define Z_UTIL_DEC_3734 3733 +#define Z_UTIL_DEC_3735 3734 +#define Z_UTIL_DEC_3736 3735 +#define Z_UTIL_DEC_3737 3736 +#define Z_UTIL_DEC_3738 3737 +#define Z_UTIL_DEC_3739 3738 +#define Z_UTIL_DEC_3740 3739 +#define Z_UTIL_DEC_3741 3740 +#define Z_UTIL_DEC_3742 3741 +#define Z_UTIL_DEC_3743 3742 +#define Z_UTIL_DEC_3744 3743 +#define Z_UTIL_DEC_3745 3744 +#define Z_UTIL_DEC_3746 3745 +#define Z_UTIL_DEC_3747 3746 +#define Z_UTIL_DEC_3748 3747 +#define Z_UTIL_DEC_3749 3748 +#define Z_UTIL_DEC_3750 3749 +#define Z_UTIL_DEC_3751 3750 +#define Z_UTIL_DEC_3752 3751 +#define Z_UTIL_DEC_3753 3752 +#define Z_UTIL_DEC_3754 3753 +#define Z_UTIL_DEC_3755 3754 +#define Z_UTIL_DEC_3756 3755 +#define Z_UTIL_DEC_3757 3756 +#define Z_UTIL_DEC_3758 3757 +#define Z_UTIL_DEC_3759 3758 +#define Z_UTIL_DEC_3760 3759 +#define Z_UTIL_DEC_3761 3760 +#define Z_UTIL_DEC_3762 3761 +#define Z_UTIL_DEC_3763 3762 +#define Z_UTIL_DEC_3764 3763 +#define Z_UTIL_DEC_3765 3764 +#define Z_UTIL_DEC_3766 3765 +#define Z_UTIL_DEC_3767 3766 +#define Z_UTIL_DEC_3768 3767 +#define Z_UTIL_DEC_3769 3768 +#define Z_UTIL_DEC_3770 3769 +#define Z_UTIL_DEC_3771 3770 +#define Z_UTIL_DEC_3772 3771 +#define Z_UTIL_DEC_3773 3772 +#define Z_UTIL_DEC_3774 3773 +#define Z_UTIL_DEC_3775 3774 +#define Z_UTIL_DEC_3776 3775 +#define Z_UTIL_DEC_3777 3776 +#define Z_UTIL_DEC_3778 3777 +#define Z_UTIL_DEC_3779 3778 +#define Z_UTIL_DEC_3780 3779 +#define Z_UTIL_DEC_3781 3780 +#define Z_UTIL_DEC_3782 3781 +#define Z_UTIL_DEC_3783 3782 +#define Z_UTIL_DEC_3784 3783 +#define Z_UTIL_DEC_3785 3784 +#define Z_UTIL_DEC_3786 3785 +#define Z_UTIL_DEC_3787 3786 +#define Z_UTIL_DEC_3788 3787 +#define Z_UTIL_DEC_3789 3788 +#define Z_UTIL_DEC_3790 3789 +#define Z_UTIL_DEC_3791 3790 +#define Z_UTIL_DEC_3792 3791 +#define Z_UTIL_DEC_3793 3792 +#define Z_UTIL_DEC_3794 3793 +#define Z_UTIL_DEC_3795 3794 +#define Z_UTIL_DEC_3796 3795 +#define Z_UTIL_DEC_3797 3796 +#define Z_UTIL_DEC_3798 3797 +#define Z_UTIL_DEC_3799 3798 +#define Z_UTIL_DEC_3800 3799 +#define Z_UTIL_DEC_3801 3800 +#define Z_UTIL_DEC_3802 3801 +#define Z_UTIL_DEC_3803 3802 +#define Z_UTIL_DEC_3804 3803 +#define Z_UTIL_DEC_3805 3804 +#define Z_UTIL_DEC_3806 3805 +#define Z_UTIL_DEC_3807 3806 +#define Z_UTIL_DEC_3808 3807 +#define Z_UTIL_DEC_3809 3808 +#define Z_UTIL_DEC_3810 3809 +#define Z_UTIL_DEC_3811 3810 +#define Z_UTIL_DEC_3812 3811 +#define Z_UTIL_DEC_3813 3812 +#define Z_UTIL_DEC_3814 3813 +#define Z_UTIL_DEC_3815 3814 +#define Z_UTIL_DEC_3816 3815 +#define Z_UTIL_DEC_3817 3816 +#define Z_UTIL_DEC_3818 3817 +#define Z_UTIL_DEC_3819 3818 +#define Z_UTIL_DEC_3820 3819 +#define Z_UTIL_DEC_3821 3820 +#define Z_UTIL_DEC_3822 3821 +#define Z_UTIL_DEC_3823 3822 +#define Z_UTIL_DEC_3824 3823 +#define Z_UTIL_DEC_3825 3824 +#define Z_UTIL_DEC_3826 3825 +#define Z_UTIL_DEC_3827 3826 +#define Z_UTIL_DEC_3828 3827 +#define Z_UTIL_DEC_3829 3828 +#define Z_UTIL_DEC_3830 3829 +#define Z_UTIL_DEC_3831 3830 +#define Z_UTIL_DEC_3832 3831 +#define Z_UTIL_DEC_3833 3832 +#define Z_UTIL_DEC_3834 3833 +#define Z_UTIL_DEC_3835 3834 +#define Z_UTIL_DEC_3836 3835 +#define Z_UTIL_DEC_3837 3836 +#define Z_UTIL_DEC_3838 3837 +#define Z_UTIL_DEC_3839 3838 +#define Z_UTIL_DEC_3840 3839 +#define Z_UTIL_DEC_3841 3840 +#define Z_UTIL_DEC_3842 3841 +#define Z_UTIL_DEC_3843 3842 +#define Z_UTIL_DEC_3844 3843 +#define Z_UTIL_DEC_3845 3844 +#define Z_UTIL_DEC_3846 3845 +#define Z_UTIL_DEC_3847 3846 +#define Z_UTIL_DEC_3848 3847 +#define Z_UTIL_DEC_3849 3848 +#define Z_UTIL_DEC_3850 3849 +#define Z_UTIL_DEC_3851 3850 +#define Z_UTIL_DEC_3852 3851 +#define Z_UTIL_DEC_3853 3852 +#define Z_UTIL_DEC_3854 3853 +#define Z_UTIL_DEC_3855 3854 +#define Z_UTIL_DEC_3856 3855 +#define Z_UTIL_DEC_3857 3856 +#define Z_UTIL_DEC_3858 3857 +#define Z_UTIL_DEC_3859 3858 +#define Z_UTIL_DEC_3860 3859 +#define Z_UTIL_DEC_3861 3860 +#define Z_UTIL_DEC_3862 3861 +#define Z_UTIL_DEC_3863 3862 +#define Z_UTIL_DEC_3864 3863 +#define Z_UTIL_DEC_3865 3864 +#define Z_UTIL_DEC_3866 3865 +#define Z_UTIL_DEC_3867 3866 +#define Z_UTIL_DEC_3868 3867 +#define Z_UTIL_DEC_3869 3868 +#define Z_UTIL_DEC_3870 3869 +#define Z_UTIL_DEC_3871 3870 +#define Z_UTIL_DEC_3872 3871 +#define Z_UTIL_DEC_3873 3872 +#define Z_UTIL_DEC_3874 3873 +#define Z_UTIL_DEC_3875 3874 +#define Z_UTIL_DEC_3876 3875 +#define Z_UTIL_DEC_3877 3876 +#define Z_UTIL_DEC_3878 3877 +#define Z_UTIL_DEC_3879 3878 +#define Z_UTIL_DEC_3880 3879 +#define Z_UTIL_DEC_3881 3880 +#define Z_UTIL_DEC_3882 3881 +#define Z_UTIL_DEC_3883 3882 +#define Z_UTIL_DEC_3884 3883 +#define Z_UTIL_DEC_3885 3884 +#define Z_UTIL_DEC_3886 3885 +#define Z_UTIL_DEC_3887 3886 +#define Z_UTIL_DEC_3888 3887 +#define Z_UTIL_DEC_3889 3888 +#define Z_UTIL_DEC_3890 3889 +#define Z_UTIL_DEC_3891 3890 +#define Z_UTIL_DEC_3892 3891 +#define Z_UTIL_DEC_3893 3892 +#define Z_UTIL_DEC_3894 3893 +#define Z_UTIL_DEC_3895 3894 +#define Z_UTIL_DEC_3896 3895 +#define Z_UTIL_DEC_3897 3896 +#define Z_UTIL_DEC_3898 3897 +#define Z_UTIL_DEC_3899 3898 +#define Z_UTIL_DEC_3900 3899 +#define Z_UTIL_DEC_3901 3900 +#define Z_UTIL_DEC_3902 3901 +#define Z_UTIL_DEC_3903 3902 +#define Z_UTIL_DEC_3904 3903 +#define Z_UTIL_DEC_3905 3904 +#define Z_UTIL_DEC_3906 3905 +#define Z_UTIL_DEC_3907 3906 +#define Z_UTIL_DEC_3908 3907 +#define Z_UTIL_DEC_3909 3908 +#define Z_UTIL_DEC_3910 3909 +#define Z_UTIL_DEC_3911 3910 +#define Z_UTIL_DEC_3912 3911 +#define Z_UTIL_DEC_3913 3912 +#define Z_UTIL_DEC_3914 3913 +#define Z_UTIL_DEC_3915 3914 +#define Z_UTIL_DEC_3916 3915 +#define Z_UTIL_DEC_3917 3916 +#define Z_UTIL_DEC_3918 3917 +#define Z_UTIL_DEC_3919 3918 +#define Z_UTIL_DEC_3920 3919 +#define Z_UTIL_DEC_3921 3920 +#define Z_UTIL_DEC_3922 3921 +#define Z_UTIL_DEC_3923 3922 +#define Z_UTIL_DEC_3924 3923 +#define Z_UTIL_DEC_3925 3924 +#define Z_UTIL_DEC_3926 3925 +#define Z_UTIL_DEC_3927 3926 +#define Z_UTIL_DEC_3928 3927 +#define Z_UTIL_DEC_3929 3928 +#define Z_UTIL_DEC_3930 3929 +#define Z_UTIL_DEC_3931 3930 +#define Z_UTIL_DEC_3932 3931 +#define Z_UTIL_DEC_3933 3932 +#define Z_UTIL_DEC_3934 3933 +#define Z_UTIL_DEC_3935 3934 +#define Z_UTIL_DEC_3936 3935 +#define Z_UTIL_DEC_3937 3936 +#define Z_UTIL_DEC_3938 3937 +#define Z_UTIL_DEC_3939 3938 +#define Z_UTIL_DEC_3940 3939 +#define Z_UTIL_DEC_3941 3940 +#define Z_UTIL_DEC_3942 3941 +#define Z_UTIL_DEC_3943 3942 +#define Z_UTIL_DEC_3944 3943 +#define Z_UTIL_DEC_3945 3944 +#define Z_UTIL_DEC_3946 3945 +#define Z_UTIL_DEC_3947 3946 +#define Z_UTIL_DEC_3948 3947 +#define Z_UTIL_DEC_3949 3948 +#define Z_UTIL_DEC_3950 3949 +#define Z_UTIL_DEC_3951 3950 +#define Z_UTIL_DEC_3952 3951 +#define Z_UTIL_DEC_3953 3952 +#define Z_UTIL_DEC_3954 3953 +#define Z_UTIL_DEC_3955 3954 +#define Z_UTIL_DEC_3956 3955 +#define Z_UTIL_DEC_3957 3956 +#define Z_UTIL_DEC_3958 3957 +#define Z_UTIL_DEC_3959 3958 +#define Z_UTIL_DEC_3960 3959 +#define Z_UTIL_DEC_3961 3960 +#define Z_UTIL_DEC_3962 3961 +#define Z_UTIL_DEC_3963 3962 +#define Z_UTIL_DEC_3964 3963 +#define Z_UTIL_DEC_3965 3964 +#define Z_UTIL_DEC_3966 3965 +#define Z_UTIL_DEC_3967 3966 +#define Z_UTIL_DEC_3968 3967 +#define Z_UTIL_DEC_3969 3968 +#define Z_UTIL_DEC_3970 3969 +#define Z_UTIL_DEC_3971 3970 +#define Z_UTIL_DEC_3972 3971 +#define Z_UTIL_DEC_3973 3972 +#define Z_UTIL_DEC_3974 3973 +#define Z_UTIL_DEC_3975 3974 +#define Z_UTIL_DEC_3976 3975 +#define Z_UTIL_DEC_3977 3976 +#define Z_UTIL_DEC_3978 3977 +#define Z_UTIL_DEC_3979 3978 +#define Z_UTIL_DEC_3980 3979 +#define Z_UTIL_DEC_3981 3980 +#define Z_UTIL_DEC_3982 3981 +#define Z_UTIL_DEC_3983 3982 +#define Z_UTIL_DEC_3984 3983 +#define Z_UTIL_DEC_3985 3984 +#define Z_UTIL_DEC_3986 3985 +#define Z_UTIL_DEC_3987 3986 +#define Z_UTIL_DEC_3988 3987 +#define Z_UTIL_DEC_3989 3988 +#define Z_UTIL_DEC_3990 3989 +#define Z_UTIL_DEC_3991 3990 +#define Z_UTIL_DEC_3992 3991 +#define Z_UTIL_DEC_3993 3992 +#define Z_UTIL_DEC_3994 3993 +#define Z_UTIL_DEC_3995 3994 +#define Z_UTIL_DEC_3996 3995 +#define Z_UTIL_DEC_3997 3996 +#define Z_UTIL_DEC_3998 3997 +#define Z_UTIL_DEC_3999 3998 +#define Z_UTIL_DEC_4000 3999 +#define Z_UTIL_DEC_4001 4000 +#define Z_UTIL_DEC_4002 4001 +#define Z_UTIL_DEC_4003 4002 +#define Z_UTIL_DEC_4004 4003 +#define Z_UTIL_DEC_4005 4004 +#define Z_UTIL_DEC_4006 4005 +#define Z_UTIL_DEC_4007 4006 +#define Z_UTIL_DEC_4008 4007 +#define Z_UTIL_DEC_4009 4008 +#define Z_UTIL_DEC_4010 4009 +#define Z_UTIL_DEC_4011 4010 +#define Z_UTIL_DEC_4012 4011 +#define Z_UTIL_DEC_4013 4012 +#define Z_UTIL_DEC_4014 4013 +#define Z_UTIL_DEC_4015 4014 +#define Z_UTIL_DEC_4016 4015 +#define Z_UTIL_DEC_4017 4016 +#define Z_UTIL_DEC_4018 4017 +#define Z_UTIL_DEC_4019 4018 +#define Z_UTIL_DEC_4020 4019 +#define Z_UTIL_DEC_4021 4020 +#define Z_UTIL_DEC_4022 4021 +#define Z_UTIL_DEC_4023 4022 +#define Z_UTIL_DEC_4024 4023 +#define Z_UTIL_DEC_4025 4024 +#define Z_UTIL_DEC_4026 4025 +#define Z_UTIL_DEC_4027 4026 +#define Z_UTIL_DEC_4028 4027 +#define Z_UTIL_DEC_4029 4028 +#define Z_UTIL_DEC_4030 4029 +#define Z_UTIL_DEC_4031 4030 +#define Z_UTIL_DEC_4032 4031 +#define Z_UTIL_DEC_4033 4032 +#define Z_UTIL_DEC_4034 4033 +#define Z_UTIL_DEC_4035 4034 +#define Z_UTIL_DEC_4036 4035 +#define Z_UTIL_DEC_4037 4036 +#define Z_UTIL_DEC_4038 4037 +#define Z_UTIL_DEC_4039 4038 +#define Z_UTIL_DEC_4040 4039 +#define Z_UTIL_DEC_4041 4040 +#define Z_UTIL_DEC_4042 4041 +#define Z_UTIL_DEC_4043 4042 +#define Z_UTIL_DEC_4044 4043 +#define Z_UTIL_DEC_4045 4044 +#define Z_UTIL_DEC_4046 4045 +#define Z_UTIL_DEC_4047 4046 +#define Z_UTIL_DEC_4048 4047 +#define Z_UTIL_DEC_4049 4048 +#define Z_UTIL_DEC_4050 4049 +#define Z_UTIL_DEC_4051 4050 +#define Z_UTIL_DEC_4052 4051 +#define Z_UTIL_DEC_4053 4052 +#define Z_UTIL_DEC_4054 4053 +#define Z_UTIL_DEC_4055 4054 +#define Z_UTIL_DEC_4056 4055 +#define Z_UTIL_DEC_4057 4056 +#define Z_UTIL_DEC_4058 4057 +#define Z_UTIL_DEC_4059 4058 +#define Z_UTIL_DEC_4060 4059 +#define Z_UTIL_DEC_4061 4060 +#define Z_UTIL_DEC_4062 4061 +#define Z_UTIL_DEC_4063 4062 +#define Z_UTIL_DEC_4064 4063 +#define Z_UTIL_DEC_4065 4064 +#define Z_UTIL_DEC_4066 4065 +#define Z_UTIL_DEC_4067 4066 +#define Z_UTIL_DEC_4068 4067 +#define Z_UTIL_DEC_4069 4068 +#define Z_UTIL_DEC_4070 4069 +#define Z_UTIL_DEC_4071 4070 +#define Z_UTIL_DEC_4072 4071 +#define Z_UTIL_DEC_4073 4072 +#define Z_UTIL_DEC_4074 4073 +#define Z_UTIL_DEC_4075 4074 +#define Z_UTIL_DEC_4076 4075 +#define Z_UTIL_DEC_4077 4076 +#define Z_UTIL_DEC_4078 4077 +#define Z_UTIL_DEC_4079 4078 +#define Z_UTIL_DEC_4080 4079 +#define Z_UTIL_DEC_4081 4080 +#define Z_UTIL_DEC_4082 4081 +#define Z_UTIL_DEC_4083 4082 +#define Z_UTIL_DEC_4084 4083 +#define Z_UTIL_DEC_4085 4084 +#define Z_UTIL_DEC_4086 4085 +#define Z_UTIL_DEC_4087 4086 +#define Z_UTIL_DEC_4088 4087 +#define Z_UTIL_DEC_4089 4088 +#define Z_UTIL_DEC_4090 4089 +#define Z_UTIL_DEC_4091 4090 +#define Z_UTIL_DEC_4092 4091 +#define Z_UTIL_DEC_4093 4092 +#define Z_UTIL_DEC_4094 4093 +#define Z_UTIL_DEC_4095 4094 +#define Z_UTIL_DEC_4096 4095 + +#endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_UTIL_DEC_H_ */ + +/** + * INTERNAL_HIDDEN @endcond + */ diff --git a/include/zephyr/sys/util_internal_util_inc.h b/include/zephyr/sys/util_internal_util_inc.h new file mode 100644 index 00000000000..dbff47383c9 --- /dev/null +++ b/include/zephyr/sys/util_internal_util_inc.h @@ -0,0 +1,4122 @@ +/* + * Copyright (c) 2011-2014, Wind River Systems, Inc. + * Copyright (c) 2020, Nordic Semiconductor ASA + * Copyright (c) 2023, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @cond INTERNAL_HIDDEN + */ + +#ifndef ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_ +#error "This header should not be used directly, please include util_internal.h instead" +#endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_ */ + +#ifndef ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_UTIL_INC_H_ +#define ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_UTIL_INC_H_ + +#define Z_UTIL_INC_0 1 +#define Z_UTIL_INC_1 2 +#define Z_UTIL_INC_2 3 +#define Z_UTIL_INC_3 4 +#define Z_UTIL_INC_4 5 +#define Z_UTIL_INC_5 6 +#define Z_UTIL_INC_6 7 +#define Z_UTIL_INC_7 8 +#define Z_UTIL_INC_8 9 +#define Z_UTIL_INC_9 10 +#define Z_UTIL_INC_10 11 +#define Z_UTIL_INC_11 12 +#define Z_UTIL_INC_12 13 +#define Z_UTIL_INC_13 14 +#define Z_UTIL_INC_14 15 +#define Z_UTIL_INC_15 16 +#define Z_UTIL_INC_16 17 +#define Z_UTIL_INC_17 18 +#define Z_UTIL_INC_18 19 +#define Z_UTIL_INC_19 20 +#define Z_UTIL_INC_20 21 +#define Z_UTIL_INC_21 22 +#define Z_UTIL_INC_22 23 +#define Z_UTIL_INC_23 24 +#define Z_UTIL_INC_24 25 +#define Z_UTIL_INC_25 26 +#define Z_UTIL_INC_26 27 +#define Z_UTIL_INC_27 28 +#define Z_UTIL_INC_28 29 +#define Z_UTIL_INC_29 30 +#define Z_UTIL_INC_30 31 +#define Z_UTIL_INC_31 32 +#define Z_UTIL_INC_32 33 +#define Z_UTIL_INC_33 34 +#define Z_UTIL_INC_34 35 +#define Z_UTIL_INC_35 36 +#define Z_UTIL_INC_36 37 +#define Z_UTIL_INC_37 38 +#define Z_UTIL_INC_38 39 +#define Z_UTIL_INC_39 40 +#define Z_UTIL_INC_40 41 +#define Z_UTIL_INC_41 42 +#define Z_UTIL_INC_42 43 +#define Z_UTIL_INC_43 44 +#define Z_UTIL_INC_44 45 +#define Z_UTIL_INC_45 46 +#define Z_UTIL_INC_46 47 +#define Z_UTIL_INC_47 48 +#define Z_UTIL_INC_48 49 +#define Z_UTIL_INC_49 50 +#define Z_UTIL_INC_50 51 +#define Z_UTIL_INC_51 52 +#define Z_UTIL_INC_52 53 +#define Z_UTIL_INC_53 54 +#define Z_UTIL_INC_54 55 +#define Z_UTIL_INC_55 56 +#define Z_UTIL_INC_56 57 +#define Z_UTIL_INC_57 58 +#define Z_UTIL_INC_58 59 +#define Z_UTIL_INC_59 60 +#define Z_UTIL_INC_60 61 +#define Z_UTIL_INC_61 62 +#define Z_UTIL_INC_62 63 +#define Z_UTIL_INC_63 64 +#define Z_UTIL_INC_64 65 +#define Z_UTIL_INC_65 66 +#define Z_UTIL_INC_66 67 +#define Z_UTIL_INC_67 68 +#define Z_UTIL_INC_68 69 +#define Z_UTIL_INC_69 70 +#define Z_UTIL_INC_70 71 +#define Z_UTIL_INC_71 72 +#define Z_UTIL_INC_72 73 +#define Z_UTIL_INC_73 74 +#define Z_UTIL_INC_74 75 +#define Z_UTIL_INC_75 76 +#define Z_UTIL_INC_76 77 +#define Z_UTIL_INC_77 78 +#define Z_UTIL_INC_78 79 +#define Z_UTIL_INC_79 80 +#define Z_UTIL_INC_80 81 +#define Z_UTIL_INC_81 82 +#define Z_UTIL_INC_82 83 +#define Z_UTIL_INC_83 84 +#define Z_UTIL_INC_84 85 +#define Z_UTIL_INC_85 86 +#define Z_UTIL_INC_86 87 +#define Z_UTIL_INC_87 88 +#define Z_UTIL_INC_88 89 +#define Z_UTIL_INC_89 90 +#define Z_UTIL_INC_90 91 +#define Z_UTIL_INC_91 92 +#define Z_UTIL_INC_92 93 +#define Z_UTIL_INC_93 94 +#define Z_UTIL_INC_94 95 +#define Z_UTIL_INC_95 96 +#define Z_UTIL_INC_96 97 +#define Z_UTIL_INC_97 98 +#define Z_UTIL_INC_98 99 +#define Z_UTIL_INC_99 100 +#define Z_UTIL_INC_100 101 +#define Z_UTIL_INC_101 102 +#define Z_UTIL_INC_102 103 +#define Z_UTIL_INC_103 104 +#define Z_UTIL_INC_104 105 +#define Z_UTIL_INC_105 106 +#define Z_UTIL_INC_106 107 +#define Z_UTIL_INC_107 108 +#define Z_UTIL_INC_108 109 +#define Z_UTIL_INC_109 110 +#define Z_UTIL_INC_110 111 +#define Z_UTIL_INC_111 112 +#define Z_UTIL_INC_112 113 +#define Z_UTIL_INC_113 114 +#define Z_UTIL_INC_114 115 +#define Z_UTIL_INC_115 116 +#define Z_UTIL_INC_116 117 +#define Z_UTIL_INC_117 118 +#define Z_UTIL_INC_118 119 +#define Z_UTIL_INC_119 120 +#define Z_UTIL_INC_120 121 +#define Z_UTIL_INC_121 122 +#define Z_UTIL_INC_122 123 +#define Z_UTIL_INC_123 124 +#define Z_UTIL_INC_124 125 +#define Z_UTIL_INC_125 126 +#define Z_UTIL_INC_126 127 +#define Z_UTIL_INC_127 128 +#define Z_UTIL_INC_128 129 +#define Z_UTIL_INC_129 130 +#define Z_UTIL_INC_130 131 +#define Z_UTIL_INC_131 132 +#define Z_UTIL_INC_132 133 +#define Z_UTIL_INC_133 134 +#define Z_UTIL_INC_134 135 +#define Z_UTIL_INC_135 136 +#define Z_UTIL_INC_136 137 +#define Z_UTIL_INC_137 138 +#define Z_UTIL_INC_138 139 +#define Z_UTIL_INC_139 140 +#define Z_UTIL_INC_140 141 +#define Z_UTIL_INC_141 142 +#define Z_UTIL_INC_142 143 +#define Z_UTIL_INC_143 144 +#define Z_UTIL_INC_144 145 +#define Z_UTIL_INC_145 146 +#define Z_UTIL_INC_146 147 +#define Z_UTIL_INC_147 148 +#define Z_UTIL_INC_148 149 +#define Z_UTIL_INC_149 150 +#define Z_UTIL_INC_150 151 +#define Z_UTIL_INC_151 152 +#define Z_UTIL_INC_152 153 +#define Z_UTIL_INC_153 154 +#define Z_UTIL_INC_154 155 +#define Z_UTIL_INC_155 156 +#define Z_UTIL_INC_156 157 +#define Z_UTIL_INC_157 158 +#define Z_UTIL_INC_158 159 +#define Z_UTIL_INC_159 160 +#define Z_UTIL_INC_160 161 +#define Z_UTIL_INC_161 162 +#define Z_UTIL_INC_162 163 +#define Z_UTIL_INC_163 164 +#define Z_UTIL_INC_164 165 +#define Z_UTIL_INC_165 166 +#define Z_UTIL_INC_166 167 +#define Z_UTIL_INC_167 168 +#define Z_UTIL_INC_168 169 +#define Z_UTIL_INC_169 170 +#define Z_UTIL_INC_170 171 +#define Z_UTIL_INC_171 172 +#define Z_UTIL_INC_172 173 +#define Z_UTIL_INC_173 174 +#define Z_UTIL_INC_174 175 +#define Z_UTIL_INC_175 176 +#define Z_UTIL_INC_176 177 +#define Z_UTIL_INC_177 178 +#define Z_UTIL_INC_178 179 +#define Z_UTIL_INC_179 180 +#define Z_UTIL_INC_180 181 +#define Z_UTIL_INC_181 182 +#define Z_UTIL_INC_182 183 +#define Z_UTIL_INC_183 184 +#define Z_UTIL_INC_184 185 +#define Z_UTIL_INC_185 186 +#define Z_UTIL_INC_186 187 +#define Z_UTIL_INC_187 188 +#define Z_UTIL_INC_188 189 +#define Z_UTIL_INC_189 190 +#define Z_UTIL_INC_190 191 +#define Z_UTIL_INC_191 192 +#define Z_UTIL_INC_192 193 +#define Z_UTIL_INC_193 194 +#define Z_UTIL_INC_194 195 +#define Z_UTIL_INC_195 196 +#define Z_UTIL_INC_196 197 +#define Z_UTIL_INC_197 198 +#define Z_UTIL_INC_198 199 +#define Z_UTIL_INC_199 200 +#define Z_UTIL_INC_200 201 +#define Z_UTIL_INC_201 202 +#define Z_UTIL_INC_202 203 +#define Z_UTIL_INC_203 204 +#define Z_UTIL_INC_204 205 +#define Z_UTIL_INC_205 206 +#define Z_UTIL_INC_206 207 +#define Z_UTIL_INC_207 208 +#define Z_UTIL_INC_208 209 +#define Z_UTIL_INC_209 210 +#define Z_UTIL_INC_210 211 +#define Z_UTIL_INC_211 212 +#define Z_UTIL_INC_212 213 +#define Z_UTIL_INC_213 214 +#define Z_UTIL_INC_214 215 +#define Z_UTIL_INC_215 216 +#define Z_UTIL_INC_216 217 +#define Z_UTIL_INC_217 218 +#define Z_UTIL_INC_218 219 +#define Z_UTIL_INC_219 220 +#define Z_UTIL_INC_220 221 +#define Z_UTIL_INC_221 222 +#define Z_UTIL_INC_222 223 +#define Z_UTIL_INC_223 224 +#define Z_UTIL_INC_224 225 +#define Z_UTIL_INC_225 226 +#define Z_UTIL_INC_226 227 +#define Z_UTIL_INC_227 228 +#define Z_UTIL_INC_228 229 +#define Z_UTIL_INC_229 230 +#define Z_UTIL_INC_230 231 +#define Z_UTIL_INC_231 232 +#define Z_UTIL_INC_232 233 +#define Z_UTIL_INC_233 234 +#define Z_UTIL_INC_234 235 +#define Z_UTIL_INC_235 236 +#define Z_UTIL_INC_236 237 +#define Z_UTIL_INC_237 238 +#define Z_UTIL_INC_238 239 +#define Z_UTIL_INC_239 240 +#define Z_UTIL_INC_240 241 +#define Z_UTIL_INC_241 242 +#define Z_UTIL_INC_242 243 +#define Z_UTIL_INC_243 244 +#define Z_UTIL_INC_244 245 +#define Z_UTIL_INC_245 246 +#define Z_UTIL_INC_246 247 +#define Z_UTIL_INC_247 248 +#define Z_UTIL_INC_248 249 +#define Z_UTIL_INC_249 250 +#define Z_UTIL_INC_250 251 +#define Z_UTIL_INC_251 252 +#define Z_UTIL_INC_252 253 +#define Z_UTIL_INC_253 254 +#define Z_UTIL_INC_254 255 +#define Z_UTIL_INC_255 256 +#define Z_UTIL_INC_256 257 +#define Z_UTIL_INC_257 258 +#define Z_UTIL_INC_258 259 +#define Z_UTIL_INC_259 260 +#define Z_UTIL_INC_260 261 +#define Z_UTIL_INC_261 262 +#define Z_UTIL_INC_262 263 +#define Z_UTIL_INC_263 264 +#define Z_UTIL_INC_264 265 +#define Z_UTIL_INC_265 266 +#define Z_UTIL_INC_266 267 +#define Z_UTIL_INC_267 268 +#define Z_UTIL_INC_268 269 +#define Z_UTIL_INC_269 270 +#define Z_UTIL_INC_270 271 +#define Z_UTIL_INC_271 272 +#define Z_UTIL_INC_272 273 +#define Z_UTIL_INC_273 274 +#define Z_UTIL_INC_274 275 +#define Z_UTIL_INC_275 276 +#define Z_UTIL_INC_276 277 +#define Z_UTIL_INC_277 278 +#define Z_UTIL_INC_278 279 +#define Z_UTIL_INC_279 280 +#define Z_UTIL_INC_280 281 +#define Z_UTIL_INC_281 282 +#define Z_UTIL_INC_282 283 +#define Z_UTIL_INC_283 284 +#define Z_UTIL_INC_284 285 +#define Z_UTIL_INC_285 286 +#define Z_UTIL_INC_286 287 +#define Z_UTIL_INC_287 288 +#define Z_UTIL_INC_288 289 +#define Z_UTIL_INC_289 290 +#define Z_UTIL_INC_290 291 +#define Z_UTIL_INC_291 292 +#define Z_UTIL_INC_292 293 +#define Z_UTIL_INC_293 294 +#define Z_UTIL_INC_294 295 +#define Z_UTIL_INC_295 296 +#define Z_UTIL_INC_296 297 +#define Z_UTIL_INC_297 298 +#define Z_UTIL_INC_298 299 +#define Z_UTIL_INC_299 300 +#define Z_UTIL_INC_300 301 +#define Z_UTIL_INC_301 302 +#define Z_UTIL_INC_302 303 +#define Z_UTIL_INC_303 304 +#define Z_UTIL_INC_304 305 +#define Z_UTIL_INC_305 306 +#define Z_UTIL_INC_306 307 +#define Z_UTIL_INC_307 308 +#define Z_UTIL_INC_308 309 +#define Z_UTIL_INC_309 310 +#define Z_UTIL_INC_310 311 +#define Z_UTIL_INC_311 312 +#define Z_UTIL_INC_312 313 +#define Z_UTIL_INC_313 314 +#define Z_UTIL_INC_314 315 +#define Z_UTIL_INC_315 316 +#define Z_UTIL_INC_316 317 +#define Z_UTIL_INC_317 318 +#define Z_UTIL_INC_318 319 +#define Z_UTIL_INC_319 320 +#define Z_UTIL_INC_320 321 +#define Z_UTIL_INC_321 322 +#define Z_UTIL_INC_322 323 +#define Z_UTIL_INC_323 324 +#define Z_UTIL_INC_324 325 +#define Z_UTIL_INC_325 326 +#define Z_UTIL_INC_326 327 +#define Z_UTIL_INC_327 328 +#define Z_UTIL_INC_328 329 +#define Z_UTIL_INC_329 330 +#define Z_UTIL_INC_330 331 +#define Z_UTIL_INC_331 332 +#define Z_UTIL_INC_332 333 +#define Z_UTIL_INC_333 334 +#define Z_UTIL_INC_334 335 +#define Z_UTIL_INC_335 336 +#define Z_UTIL_INC_336 337 +#define Z_UTIL_INC_337 338 +#define Z_UTIL_INC_338 339 +#define Z_UTIL_INC_339 340 +#define Z_UTIL_INC_340 341 +#define Z_UTIL_INC_341 342 +#define Z_UTIL_INC_342 343 +#define Z_UTIL_INC_343 344 +#define Z_UTIL_INC_344 345 +#define Z_UTIL_INC_345 346 +#define Z_UTIL_INC_346 347 +#define Z_UTIL_INC_347 348 +#define Z_UTIL_INC_348 349 +#define Z_UTIL_INC_349 350 +#define Z_UTIL_INC_350 351 +#define Z_UTIL_INC_351 352 +#define Z_UTIL_INC_352 353 +#define Z_UTIL_INC_353 354 +#define Z_UTIL_INC_354 355 +#define Z_UTIL_INC_355 356 +#define Z_UTIL_INC_356 357 +#define Z_UTIL_INC_357 358 +#define Z_UTIL_INC_358 359 +#define Z_UTIL_INC_359 360 +#define Z_UTIL_INC_360 361 +#define Z_UTIL_INC_361 362 +#define Z_UTIL_INC_362 363 +#define Z_UTIL_INC_363 364 +#define Z_UTIL_INC_364 365 +#define Z_UTIL_INC_365 366 +#define Z_UTIL_INC_366 367 +#define Z_UTIL_INC_367 368 +#define Z_UTIL_INC_368 369 +#define Z_UTIL_INC_369 370 +#define Z_UTIL_INC_370 371 +#define Z_UTIL_INC_371 372 +#define Z_UTIL_INC_372 373 +#define Z_UTIL_INC_373 374 +#define Z_UTIL_INC_374 375 +#define Z_UTIL_INC_375 376 +#define Z_UTIL_INC_376 377 +#define Z_UTIL_INC_377 378 +#define Z_UTIL_INC_378 379 +#define Z_UTIL_INC_379 380 +#define Z_UTIL_INC_380 381 +#define Z_UTIL_INC_381 382 +#define Z_UTIL_INC_382 383 +#define Z_UTIL_INC_383 384 +#define Z_UTIL_INC_384 385 +#define Z_UTIL_INC_385 386 +#define Z_UTIL_INC_386 387 +#define Z_UTIL_INC_387 388 +#define Z_UTIL_INC_388 389 +#define Z_UTIL_INC_389 390 +#define Z_UTIL_INC_390 391 +#define Z_UTIL_INC_391 392 +#define Z_UTIL_INC_392 393 +#define Z_UTIL_INC_393 394 +#define Z_UTIL_INC_394 395 +#define Z_UTIL_INC_395 396 +#define Z_UTIL_INC_396 397 +#define Z_UTIL_INC_397 398 +#define Z_UTIL_INC_398 399 +#define Z_UTIL_INC_399 400 +#define Z_UTIL_INC_400 401 +#define Z_UTIL_INC_401 402 +#define Z_UTIL_INC_402 403 +#define Z_UTIL_INC_403 404 +#define Z_UTIL_INC_404 405 +#define Z_UTIL_INC_405 406 +#define Z_UTIL_INC_406 407 +#define Z_UTIL_INC_407 408 +#define Z_UTIL_INC_408 409 +#define Z_UTIL_INC_409 410 +#define Z_UTIL_INC_410 411 +#define Z_UTIL_INC_411 412 +#define Z_UTIL_INC_412 413 +#define Z_UTIL_INC_413 414 +#define Z_UTIL_INC_414 415 +#define Z_UTIL_INC_415 416 +#define Z_UTIL_INC_416 417 +#define Z_UTIL_INC_417 418 +#define Z_UTIL_INC_418 419 +#define Z_UTIL_INC_419 420 +#define Z_UTIL_INC_420 421 +#define Z_UTIL_INC_421 422 +#define Z_UTIL_INC_422 423 +#define Z_UTIL_INC_423 424 +#define Z_UTIL_INC_424 425 +#define Z_UTIL_INC_425 426 +#define Z_UTIL_INC_426 427 +#define Z_UTIL_INC_427 428 +#define Z_UTIL_INC_428 429 +#define Z_UTIL_INC_429 430 +#define Z_UTIL_INC_430 431 +#define Z_UTIL_INC_431 432 +#define Z_UTIL_INC_432 433 +#define Z_UTIL_INC_433 434 +#define Z_UTIL_INC_434 435 +#define Z_UTIL_INC_435 436 +#define Z_UTIL_INC_436 437 +#define Z_UTIL_INC_437 438 +#define Z_UTIL_INC_438 439 +#define Z_UTIL_INC_439 440 +#define Z_UTIL_INC_440 441 +#define Z_UTIL_INC_441 442 +#define Z_UTIL_INC_442 443 +#define Z_UTIL_INC_443 444 +#define Z_UTIL_INC_444 445 +#define Z_UTIL_INC_445 446 +#define Z_UTIL_INC_446 447 +#define Z_UTIL_INC_447 448 +#define Z_UTIL_INC_448 449 +#define Z_UTIL_INC_449 450 +#define Z_UTIL_INC_450 451 +#define Z_UTIL_INC_451 452 +#define Z_UTIL_INC_452 453 +#define Z_UTIL_INC_453 454 +#define Z_UTIL_INC_454 455 +#define Z_UTIL_INC_455 456 +#define Z_UTIL_INC_456 457 +#define Z_UTIL_INC_457 458 +#define Z_UTIL_INC_458 459 +#define Z_UTIL_INC_459 460 +#define Z_UTIL_INC_460 461 +#define Z_UTIL_INC_461 462 +#define Z_UTIL_INC_462 463 +#define Z_UTIL_INC_463 464 +#define Z_UTIL_INC_464 465 +#define Z_UTIL_INC_465 466 +#define Z_UTIL_INC_466 467 +#define Z_UTIL_INC_467 468 +#define Z_UTIL_INC_468 469 +#define Z_UTIL_INC_469 470 +#define Z_UTIL_INC_470 471 +#define Z_UTIL_INC_471 472 +#define Z_UTIL_INC_472 473 +#define Z_UTIL_INC_473 474 +#define Z_UTIL_INC_474 475 +#define Z_UTIL_INC_475 476 +#define Z_UTIL_INC_476 477 +#define Z_UTIL_INC_477 478 +#define Z_UTIL_INC_478 479 +#define Z_UTIL_INC_479 480 +#define Z_UTIL_INC_480 481 +#define Z_UTIL_INC_481 482 +#define Z_UTIL_INC_482 483 +#define Z_UTIL_INC_483 484 +#define Z_UTIL_INC_484 485 +#define Z_UTIL_INC_485 486 +#define Z_UTIL_INC_486 487 +#define Z_UTIL_INC_487 488 +#define Z_UTIL_INC_488 489 +#define Z_UTIL_INC_489 490 +#define Z_UTIL_INC_490 491 +#define Z_UTIL_INC_491 492 +#define Z_UTIL_INC_492 493 +#define Z_UTIL_INC_493 494 +#define Z_UTIL_INC_494 495 +#define Z_UTIL_INC_495 496 +#define Z_UTIL_INC_496 497 +#define Z_UTIL_INC_497 498 +#define Z_UTIL_INC_498 499 +#define Z_UTIL_INC_499 500 +#define Z_UTIL_INC_500 501 +#define Z_UTIL_INC_501 502 +#define Z_UTIL_INC_502 503 +#define Z_UTIL_INC_503 504 +#define Z_UTIL_INC_504 505 +#define Z_UTIL_INC_505 506 +#define Z_UTIL_INC_506 507 +#define Z_UTIL_INC_507 508 +#define Z_UTIL_INC_508 509 +#define Z_UTIL_INC_509 510 +#define Z_UTIL_INC_510 511 +#define Z_UTIL_INC_511 512 +#define Z_UTIL_INC_512 513 +#define Z_UTIL_INC_513 514 +#define Z_UTIL_INC_514 515 +#define Z_UTIL_INC_515 516 +#define Z_UTIL_INC_516 517 +#define Z_UTIL_INC_517 518 +#define Z_UTIL_INC_518 519 +#define Z_UTIL_INC_519 520 +#define Z_UTIL_INC_520 521 +#define Z_UTIL_INC_521 522 +#define Z_UTIL_INC_522 523 +#define Z_UTIL_INC_523 524 +#define Z_UTIL_INC_524 525 +#define Z_UTIL_INC_525 526 +#define Z_UTIL_INC_526 527 +#define Z_UTIL_INC_527 528 +#define Z_UTIL_INC_528 529 +#define Z_UTIL_INC_529 530 +#define Z_UTIL_INC_530 531 +#define Z_UTIL_INC_531 532 +#define Z_UTIL_INC_532 533 +#define Z_UTIL_INC_533 534 +#define Z_UTIL_INC_534 535 +#define Z_UTIL_INC_535 536 +#define Z_UTIL_INC_536 537 +#define Z_UTIL_INC_537 538 +#define Z_UTIL_INC_538 539 +#define Z_UTIL_INC_539 540 +#define Z_UTIL_INC_540 541 +#define Z_UTIL_INC_541 542 +#define Z_UTIL_INC_542 543 +#define Z_UTIL_INC_543 544 +#define Z_UTIL_INC_544 545 +#define Z_UTIL_INC_545 546 +#define Z_UTIL_INC_546 547 +#define Z_UTIL_INC_547 548 +#define Z_UTIL_INC_548 549 +#define Z_UTIL_INC_549 550 +#define Z_UTIL_INC_550 551 +#define Z_UTIL_INC_551 552 +#define Z_UTIL_INC_552 553 +#define Z_UTIL_INC_553 554 +#define Z_UTIL_INC_554 555 +#define Z_UTIL_INC_555 556 +#define Z_UTIL_INC_556 557 +#define Z_UTIL_INC_557 558 +#define Z_UTIL_INC_558 559 +#define Z_UTIL_INC_559 560 +#define Z_UTIL_INC_560 561 +#define Z_UTIL_INC_561 562 +#define Z_UTIL_INC_562 563 +#define Z_UTIL_INC_563 564 +#define Z_UTIL_INC_564 565 +#define Z_UTIL_INC_565 566 +#define Z_UTIL_INC_566 567 +#define Z_UTIL_INC_567 568 +#define Z_UTIL_INC_568 569 +#define Z_UTIL_INC_569 570 +#define Z_UTIL_INC_570 571 +#define Z_UTIL_INC_571 572 +#define Z_UTIL_INC_572 573 +#define Z_UTIL_INC_573 574 +#define Z_UTIL_INC_574 575 +#define Z_UTIL_INC_575 576 +#define Z_UTIL_INC_576 577 +#define Z_UTIL_INC_577 578 +#define Z_UTIL_INC_578 579 +#define Z_UTIL_INC_579 580 +#define Z_UTIL_INC_580 581 +#define Z_UTIL_INC_581 582 +#define Z_UTIL_INC_582 583 +#define Z_UTIL_INC_583 584 +#define Z_UTIL_INC_584 585 +#define Z_UTIL_INC_585 586 +#define Z_UTIL_INC_586 587 +#define Z_UTIL_INC_587 588 +#define Z_UTIL_INC_588 589 +#define Z_UTIL_INC_589 590 +#define Z_UTIL_INC_590 591 +#define Z_UTIL_INC_591 592 +#define Z_UTIL_INC_592 593 +#define Z_UTIL_INC_593 594 +#define Z_UTIL_INC_594 595 +#define Z_UTIL_INC_595 596 +#define Z_UTIL_INC_596 597 +#define Z_UTIL_INC_597 598 +#define Z_UTIL_INC_598 599 +#define Z_UTIL_INC_599 600 +#define Z_UTIL_INC_600 601 +#define Z_UTIL_INC_601 602 +#define Z_UTIL_INC_602 603 +#define Z_UTIL_INC_603 604 +#define Z_UTIL_INC_604 605 +#define Z_UTIL_INC_605 606 +#define Z_UTIL_INC_606 607 +#define Z_UTIL_INC_607 608 +#define Z_UTIL_INC_608 609 +#define Z_UTIL_INC_609 610 +#define Z_UTIL_INC_610 611 +#define Z_UTIL_INC_611 612 +#define Z_UTIL_INC_612 613 +#define Z_UTIL_INC_613 614 +#define Z_UTIL_INC_614 615 +#define Z_UTIL_INC_615 616 +#define Z_UTIL_INC_616 617 +#define Z_UTIL_INC_617 618 +#define Z_UTIL_INC_618 619 +#define Z_UTIL_INC_619 620 +#define Z_UTIL_INC_620 621 +#define Z_UTIL_INC_621 622 +#define Z_UTIL_INC_622 623 +#define Z_UTIL_INC_623 624 +#define Z_UTIL_INC_624 625 +#define Z_UTIL_INC_625 626 +#define Z_UTIL_INC_626 627 +#define Z_UTIL_INC_627 628 +#define Z_UTIL_INC_628 629 +#define Z_UTIL_INC_629 630 +#define Z_UTIL_INC_630 631 +#define Z_UTIL_INC_631 632 +#define Z_UTIL_INC_632 633 +#define Z_UTIL_INC_633 634 +#define Z_UTIL_INC_634 635 +#define Z_UTIL_INC_635 636 +#define Z_UTIL_INC_636 637 +#define Z_UTIL_INC_637 638 +#define Z_UTIL_INC_638 639 +#define Z_UTIL_INC_639 640 +#define Z_UTIL_INC_640 641 +#define Z_UTIL_INC_641 642 +#define Z_UTIL_INC_642 643 +#define Z_UTIL_INC_643 644 +#define Z_UTIL_INC_644 645 +#define Z_UTIL_INC_645 646 +#define Z_UTIL_INC_646 647 +#define Z_UTIL_INC_647 648 +#define Z_UTIL_INC_648 649 +#define Z_UTIL_INC_649 650 +#define Z_UTIL_INC_650 651 +#define Z_UTIL_INC_651 652 +#define Z_UTIL_INC_652 653 +#define Z_UTIL_INC_653 654 +#define Z_UTIL_INC_654 655 +#define Z_UTIL_INC_655 656 +#define Z_UTIL_INC_656 657 +#define Z_UTIL_INC_657 658 +#define Z_UTIL_INC_658 659 +#define Z_UTIL_INC_659 660 +#define Z_UTIL_INC_660 661 +#define Z_UTIL_INC_661 662 +#define Z_UTIL_INC_662 663 +#define Z_UTIL_INC_663 664 +#define Z_UTIL_INC_664 665 +#define Z_UTIL_INC_665 666 +#define Z_UTIL_INC_666 667 +#define Z_UTIL_INC_667 668 +#define Z_UTIL_INC_668 669 +#define Z_UTIL_INC_669 670 +#define Z_UTIL_INC_670 671 +#define Z_UTIL_INC_671 672 +#define Z_UTIL_INC_672 673 +#define Z_UTIL_INC_673 674 +#define Z_UTIL_INC_674 675 +#define Z_UTIL_INC_675 676 +#define Z_UTIL_INC_676 677 +#define Z_UTIL_INC_677 678 +#define Z_UTIL_INC_678 679 +#define Z_UTIL_INC_679 680 +#define Z_UTIL_INC_680 681 +#define Z_UTIL_INC_681 682 +#define Z_UTIL_INC_682 683 +#define Z_UTIL_INC_683 684 +#define Z_UTIL_INC_684 685 +#define Z_UTIL_INC_685 686 +#define Z_UTIL_INC_686 687 +#define Z_UTIL_INC_687 688 +#define Z_UTIL_INC_688 689 +#define Z_UTIL_INC_689 690 +#define Z_UTIL_INC_690 691 +#define Z_UTIL_INC_691 692 +#define Z_UTIL_INC_692 693 +#define Z_UTIL_INC_693 694 +#define Z_UTIL_INC_694 695 +#define Z_UTIL_INC_695 696 +#define Z_UTIL_INC_696 697 +#define Z_UTIL_INC_697 698 +#define Z_UTIL_INC_698 699 +#define Z_UTIL_INC_699 700 +#define Z_UTIL_INC_700 701 +#define Z_UTIL_INC_701 702 +#define Z_UTIL_INC_702 703 +#define Z_UTIL_INC_703 704 +#define Z_UTIL_INC_704 705 +#define Z_UTIL_INC_705 706 +#define Z_UTIL_INC_706 707 +#define Z_UTIL_INC_707 708 +#define Z_UTIL_INC_708 709 +#define Z_UTIL_INC_709 710 +#define Z_UTIL_INC_710 711 +#define Z_UTIL_INC_711 712 +#define Z_UTIL_INC_712 713 +#define Z_UTIL_INC_713 714 +#define Z_UTIL_INC_714 715 +#define Z_UTIL_INC_715 716 +#define Z_UTIL_INC_716 717 +#define Z_UTIL_INC_717 718 +#define Z_UTIL_INC_718 719 +#define Z_UTIL_INC_719 720 +#define Z_UTIL_INC_720 721 +#define Z_UTIL_INC_721 722 +#define Z_UTIL_INC_722 723 +#define Z_UTIL_INC_723 724 +#define Z_UTIL_INC_724 725 +#define Z_UTIL_INC_725 726 +#define Z_UTIL_INC_726 727 +#define Z_UTIL_INC_727 728 +#define Z_UTIL_INC_728 729 +#define Z_UTIL_INC_729 730 +#define Z_UTIL_INC_730 731 +#define Z_UTIL_INC_731 732 +#define Z_UTIL_INC_732 733 +#define Z_UTIL_INC_733 734 +#define Z_UTIL_INC_734 735 +#define Z_UTIL_INC_735 736 +#define Z_UTIL_INC_736 737 +#define Z_UTIL_INC_737 738 +#define Z_UTIL_INC_738 739 +#define Z_UTIL_INC_739 740 +#define Z_UTIL_INC_740 741 +#define Z_UTIL_INC_741 742 +#define Z_UTIL_INC_742 743 +#define Z_UTIL_INC_743 744 +#define Z_UTIL_INC_744 745 +#define Z_UTIL_INC_745 746 +#define Z_UTIL_INC_746 747 +#define Z_UTIL_INC_747 748 +#define Z_UTIL_INC_748 749 +#define Z_UTIL_INC_749 750 +#define Z_UTIL_INC_750 751 +#define Z_UTIL_INC_751 752 +#define Z_UTIL_INC_752 753 +#define Z_UTIL_INC_753 754 +#define Z_UTIL_INC_754 755 +#define Z_UTIL_INC_755 756 +#define Z_UTIL_INC_756 757 +#define Z_UTIL_INC_757 758 +#define Z_UTIL_INC_758 759 +#define Z_UTIL_INC_759 760 +#define Z_UTIL_INC_760 761 +#define Z_UTIL_INC_761 762 +#define Z_UTIL_INC_762 763 +#define Z_UTIL_INC_763 764 +#define Z_UTIL_INC_764 765 +#define Z_UTIL_INC_765 766 +#define Z_UTIL_INC_766 767 +#define Z_UTIL_INC_767 768 +#define Z_UTIL_INC_768 769 +#define Z_UTIL_INC_769 770 +#define Z_UTIL_INC_770 771 +#define Z_UTIL_INC_771 772 +#define Z_UTIL_INC_772 773 +#define Z_UTIL_INC_773 774 +#define Z_UTIL_INC_774 775 +#define Z_UTIL_INC_775 776 +#define Z_UTIL_INC_776 777 +#define Z_UTIL_INC_777 778 +#define Z_UTIL_INC_778 779 +#define Z_UTIL_INC_779 780 +#define Z_UTIL_INC_780 781 +#define Z_UTIL_INC_781 782 +#define Z_UTIL_INC_782 783 +#define Z_UTIL_INC_783 784 +#define Z_UTIL_INC_784 785 +#define Z_UTIL_INC_785 786 +#define Z_UTIL_INC_786 787 +#define Z_UTIL_INC_787 788 +#define Z_UTIL_INC_788 789 +#define Z_UTIL_INC_789 790 +#define Z_UTIL_INC_790 791 +#define Z_UTIL_INC_791 792 +#define Z_UTIL_INC_792 793 +#define Z_UTIL_INC_793 794 +#define Z_UTIL_INC_794 795 +#define Z_UTIL_INC_795 796 +#define Z_UTIL_INC_796 797 +#define Z_UTIL_INC_797 798 +#define Z_UTIL_INC_798 799 +#define Z_UTIL_INC_799 800 +#define Z_UTIL_INC_800 801 +#define Z_UTIL_INC_801 802 +#define Z_UTIL_INC_802 803 +#define Z_UTIL_INC_803 804 +#define Z_UTIL_INC_804 805 +#define Z_UTIL_INC_805 806 +#define Z_UTIL_INC_806 807 +#define Z_UTIL_INC_807 808 +#define Z_UTIL_INC_808 809 +#define Z_UTIL_INC_809 810 +#define Z_UTIL_INC_810 811 +#define Z_UTIL_INC_811 812 +#define Z_UTIL_INC_812 813 +#define Z_UTIL_INC_813 814 +#define Z_UTIL_INC_814 815 +#define Z_UTIL_INC_815 816 +#define Z_UTIL_INC_816 817 +#define Z_UTIL_INC_817 818 +#define Z_UTIL_INC_818 819 +#define Z_UTIL_INC_819 820 +#define Z_UTIL_INC_820 821 +#define Z_UTIL_INC_821 822 +#define Z_UTIL_INC_822 823 +#define Z_UTIL_INC_823 824 +#define Z_UTIL_INC_824 825 +#define Z_UTIL_INC_825 826 +#define Z_UTIL_INC_826 827 +#define Z_UTIL_INC_827 828 +#define Z_UTIL_INC_828 829 +#define Z_UTIL_INC_829 830 +#define Z_UTIL_INC_830 831 +#define Z_UTIL_INC_831 832 +#define Z_UTIL_INC_832 833 +#define Z_UTIL_INC_833 834 +#define Z_UTIL_INC_834 835 +#define Z_UTIL_INC_835 836 +#define Z_UTIL_INC_836 837 +#define Z_UTIL_INC_837 838 +#define Z_UTIL_INC_838 839 +#define Z_UTIL_INC_839 840 +#define Z_UTIL_INC_840 841 +#define Z_UTIL_INC_841 842 +#define Z_UTIL_INC_842 843 +#define Z_UTIL_INC_843 844 +#define Z_UTIL_INC_844 845 +#define Z_UTIL_INC_845 846 +#define Z_UTIL_INC_846 847 +#define Z_UTIL_INC_847 848 +#define Z_UTIL_INC_848 849 +#define Z_UTIL_INC_849 850 +#define Z_UTIL_INC_850 851 +#define Z_UTIL_INC_851 852 +#define Z_UTIL_INC_852 853 +#define Z_UTIL_INC_853 854 +#define Z_UTIL_INC_854 855 +#define Z_UTIL_INC_855 856 +#define Z_UTIL_INC_856 857 +#define Z_UTIL_INC_857 858 +#define Z_UTIL_INC_858 859 +#define Z_UTIL_INC_859 860 +#define Z_UTIL_INC_860 861 +#define Z_UTIL_INC_861 862 +#define Z_UTIL_INC_862 863 +#define Z_UTIL_INC_863 864 +#define Z_UTIL_INC_864 865 +#define Z_UTIL_INC_865 866 +#define Z_UTIL_INC_866 867 +#define Z_UTIL_INC_867 868 +#define Z_UTIL_INC_868 869 +#define Z_UTIL_INC_869 870 +#define Z_UTIL_INC_870 871 +#define Z_UTIL_INC_871 872 +#define Z_UTIL_INC_872 873 +#define Z_UTIL_INC_873 874 +#define Z_UTIL_INC_874 875 +#define Z_UTIL_INC_875 876 +#define Z_UTIL_INC_876 877 +#define Z_UTIL_INC_877 878 +#define Z_UTIL_INC_878 879 +#define Z_UTIL_INC_879 880 +#define Z_UTIL_INC_880 881 +#define Z_UTIL_INC_881 882 +#define Z_UTIL_INC_882 883 +#define Z_UTIL_INC_883 884 +#define Z_UTIL_INC_884 885 +#define Z_UTIL_INC_885 886 +#define Z_UTIL_INC_886 887 +#define Z_UTIL_INC_887 888 +#define Z_UTIL_INC_888 889 +#define Z_UTIL_INC_889 890 +#define Z_UTIL_INC_890 891 +#define Z_UTIL_INC_891 892 +#define Z_UTIL_INC_892 893 +#define Z_UTIL_INC_893 894 +#define Z_UTIL_INC_894 895 +#define Z_UTIL_INC_895 896 +#define Z_UTIL_INC_896 897 +#define Z_UTIL_INC_897 898 +#define Z_UTIL_INC_898 899 +#define Z_UTIL_INC_899 900 +#define Z_UTIL_INC_900 901 +#define Z_UTIL_INC_901 902 +#define Z_UTIL_INC_902 903 +#define Z_UTIL_INC_903 904 +#define Z_UTIL_INC_904 905 +#define Z_UTIL_INC_905 906 +#define Z_UTIL_INC_906 907 +#define Z_UTIL_INC_907 908 +#define Z_UTIL_INC_908 909 +#define Z_UTIL_INC_909 910 +#define Z_UTIL_INC_910 911 +#define Z_UTIL_INC_911 912 +#define Z_UTIL_INC_912 913 +#define Z_UTIL_INC_913 914 +#define Z_UTIL_INC_914 915 +#define Z_UTIL_INC_915 916 +#define Z_UTIL_INC_916 917 +#define Z_UTIL_INC_917 918 +#define Z_UTIL_INC_918 919 +#define Z_UTIL_INC_919 920 +#define Z_UTIL_INC_920 921 +#define Z_UTIL_INC_921 922 +#define Z_UTIL_INC_922 923 +#define Z_UTIL_INC_923 924 +#define Z_UTIL_INC_924 925 +#define Z_UTIL_INC_925 926 +#define Z_UTIL_INC_926 927 +#define Z_UTIL_INC_927 928 +#define Z_UTIL_INC_928 929 +#define Z_UTIL_INC_929 930 +#define Z_UTIL_INC_930 931 +#define Z_UTIL_INC_931 932 +#define Z_UTIL_INC_932 933 +#define Z_UTIL_INC_933 934 +#define Z_UTIL_INC_934 935 +#define Z_UTIL_INC_935 936 +#define Z_UTIL_INC_936 937 +#define Z_UTIL_INC_937 938 +#define Z_UTIL_INC_938 939 +#define Z_UTIL_INC_939 940 +#define Z_UTIL_INC_940 941 +#define Z_UTIL_INC_941 942 +#define Z_UTIL_INC_942 943 +#define Z_UTIL_INC_943 944 +#define Z_UTIL_INC_944 945 +#define Z_UTIL_INC_945 946 +#define Z_UTIL_INC_946 947 +#define Z_UTIL_INC_947 948 +#define Z_UTIL_INC_948 949 +#define Z_UTIL_INC_949 950 +#define Z_UTIL_INC_950 951 +#define Z_UTIL_INC_951 952 +#define Z_UTIL_INC_952 953 +#define Z_UTIL_INC_953 954 +#define Z_UTIL_INC_954 955 +#define Z_UTIL_INC_955 956 +#define Z_UTIL_INC_956 957 +#define Z_UTIL_INC_957 958 +#define Z_UTIL_INC_958 959 +#define Z_UTIL_INC_959 960 +#define Z_UTIL_INC_960 961 +#define Z_UTIL_INC_961 962 +#define Z_UTIL_INC_962 963 +#define Z_UTIL_INC_963 964 +#define Z_UTIL_INC_964 965 +#define Z_UTIL_INC_965 966 +#define Z_UTIL_INC_966 967 +#define Z_UTIL_INC_967 968 +#define Z_UTIL_INC_968 969 +#define Z_UTIL_INC_969 970 +#define Z_UTIL_INC_970 971 +#define Z_UTIL_INC_971 972 +#define Z_UTIL_INC_972 973 +#define Z_UTIL_INC_973 974 +#define Z_UTIL_INC_974 975 +#define Z_UTIL_INC_975 976 +#define Z_UTIL_INC_976 977 +#define Z_UTIL_INC_977 978 +#define Z_UTIL_INC_978 979 +#define Z_UTIL_INC_979 980 +#define Z_UTIL_INC_980 981 +#define Z_UTIL_INC_981 982 +#define Z_UTIL_INC_982 983 +#define Z_UTIL_INC_983 984 +#define Z_UTIL_INC_984 985 +#define Z_UTIL_INC_985 986 +#define Z_UTIL_INC_986 987 +#define Z_UTIL_INC_987 988 +#define Z_UTIL_INC_988 989 +#define Z_UTIL_INC_989 990 +#define Z_UTIL_INC_990 991 +#define Z_UTIL_INC_991 992 +#define Z_UTIL_INC_992 993 +#define Z_UTIL_INC_993 994 +#define Z_UTIL_INC_994 995 +#define Z_UTIL_INC_995 996 +#define Z_UTIL_INC_996 997 +#define Z_UTIL_INC_997 998 +#define Z_UTIL_INC_998 999 +#define Z_UTIL_INC_999 1000 +#define Z_UTIL_INC_1000 1001 +#define Z_UTIL_INC_1001 1002 +#define Z_UTIL_INC_1002 1003 +#define Z_UTIL_INC_1003 1004 +#define Z_UTIL_INC_1004 1005 +#define Z_UTIL_INC_1005 1006 +#define Z_UTIL_INC_1006 1007 +#define Z_UTIL_INC_1007 1008 +#define Z_UTIL_INC_1008 1009 +#define Z_UTIL_INC_1009 1010 +#define Z_UTIL_INC_1010 1011 +#define Z_UTIL_INC_1011 1012 +#define Z_UTIL_INC_1012 1013 +#define Z_UTIL_INC_1013 1014 +#define Z_UTIL_INC_1014 1015 +#define Z_UTIL_INC_1015 1016 +#define Z_UTIL_INC_1016 1017 +#define Z_UTIL_INC_1017 1018 +#define Z_UTIL_INC_1018 1019 +#define Z_UTIL_INC_1019 1020 +#define Z_UTIL_INC_1020 1021 +#define Z_UTIL_INC_1021 1022 +#define Z_UTIL_INC_1022 1023 +#define Z_UTIL_INC_1023 1024 +#define Z_UTIL_INC_1024 1025 +#define Z_UTIL_INC_1025 1026 +#define Z_UTIL_INC_1026 1027 +#define Z_UTIL_INC_1027 1028 +#define Z_UTIL_INC_1028 1029 +#define Z_UTIL_INC_1029 1030 +#define Z_UTIL_INC_1030 1031 +#define Z_UTIL_INC_1031 1032 +#define Z_UTIL_INC_1032 1033 +#define Z_UTIL_INC_1033 1034 +#define Z_UTIL_INC_1034 1035 +#define Z_UTIL_INC_1035 1036 +#define Z_UTIL_INC_1036 1037 +#define Z_UTIL_INC_1037 1038 +#define Z_UTIL_INC_1038 1039 +#define Z_UTIL_INC_1039 1040 +#define Z_UTIL_INC_1040 1041 +#define Z_UTIL_INC_1041 1042 +#define Z_UTIL_INC_1042 1043 +#define Z_UTIL_INC_1043 1044 +#define Z_UTIL_INC_1044 1045 +#define Z_UTIL_INC_1045 1046 +#define Z_UTIL_INC_1046 1047 +#define Z_UTIL_INC_1047 1048 +#define Z_UTIL_INC_1048 1049 +#define Z_UTIL_INC_1049 1050 +#define Z_UTIL_INC_1050 1051 +#define Z_UTIL_INC_1051 1052 +#define Z_UTIL_INC_1052 1053 +#define Z_UTIL_INC_1053 1054 +#define Z_UTIL_INC_1054 1055 +#define Z_UTIL_INC_1055 1056 +#define Z_UTIL_INC_1056 1057 +#define Z_UTIL_INC_1057 1058 +#define Z_UTIL_INC_1058 1059 +#define Z_UTIL_INC_1059 1060 +#define Z_UTIL_INC_1060 1061 +#define Z_UTIL_INC_1061 1062 +#define Z_UTIL_INC_1062 1063 +#define Z_UTIL_INC_1063 1064 +#define Z_UTIL_INC_1064 1065 +#define Z_UTIL_INC_1065 1066 +#define Z_UTIL_INC_1066 1067 +#define Z_UTIL_INC_1067 1068 +#define Z_UTIL_INC_1068 1069 +#define Z_UTIL_INC_1069 1070 +#define Z_UTIL_INC_1070 1071 +#define Z_UTIL_INC_1071 1072 +#define Z_UTIL_INC_1072 1073 +#define Z_UTIL_INC_1073 1074 +#define Z_UTIL_INC_1074 1075 +#define Z_UTIL_INC_1075 1076 +#define Z_UTIL_INC_1076 1077 +#define Z_UTIL_INC_1077 1078 +#define Z_UTIL_INC_1078 1079 +#define Z_UTIL_INC_1079 1080 +#define Z_UTIL_INC_1080 1081 +#define Z_UTIL_INC_1081 1082 +#define Z_UTIL_INC_1082 1083 +#define Z_UTIL_INC_1083 1084 +#define Z_UTIL_INC_1084 1085 +#define Z_UTIL_INC_1085 1086 +#define Z_UTIL_INC_1086 1087 +#define Z_UTIL_INC_1087 1088 +#define Z_UTIL_INC_1088 1089 +#define Z_UTIL_INC_1089 1090 +#define Z_UTIL_INC_1090 1091 +#define Z_UTIL_INC_1091 1092 +#define Z_UTIL_INC_1092 1093 +#define Z_UTIL_INC_1093 1094 +#define Z_UTIL_INC_1094 1095 +#define Z_UTIL_INC_1095 1096 +#define Z_UTIL_INC_1096 1097 +#define Z_UTIL_INC_1097 1098 +#define Z_UTIL_INC_1098 1099 +#define Z_UTIL_INC_1099 1100 +#define Z_UTIL_INC_1100 1101 +#define Z_UTIL_INC_1101 1102 +#define Z_UTIL_INC_1102 1103 +#define Z_UTIL_INC_1103 1104 +#define Z_UTIL_INC_1104 1105 +#define Z_UTIL_INC_1105 1106 +#define Z_UTIL_INC_1106 1107 +#define Z_UTIL_INC_1107 1108 +#define Z_UTIL_INC_1108 1109 +#define Z_UTIL_INC_1109 1110 +#define Z_UTIL_INC_1110 1111 +#define Z_UTIL_INC_1111 1112 +#define Z_UTIL_INC_1112 1113 +#define Z_UTIL_INC_1113 1114 +#define Z_UTIL_INC_1114 1115 +#define Z_UTIL_INC_1115 1116 +#define Z_UTIL_INC_1116 1117 +#define Z_UTIL_INC_1117 1118 +#define Z_UTIL_INC_1118 1119 +#define Z_UTIL_INC_1119 1120 +#define Z_UTIL_INC_1120 1121 +#define Z_UTIL_INC_1121 1122 +#define Z_UTIL_INC_1122 1123 +#define Z_UTIL_INC_1123 1124 +#define Z_UTIL_INC_1124 1125 +#define Z_UTIL_INC_1125 1126 +#define Z_UTIL_INC_1126 1127 +#define Z_UTIL_INC_1127 1128 +#define Z_UTIL_INC_1128 1129 +#define Z_UTIL_INC_1129 1130 +#define Z_UTIL_INC_1130 1131 +#define Z_UTIL_INC_1131 1132 +#define Z_UTIL_INC_1132 1133 +#define Z_UTIL_INC_1133 1134 +#define Z_UTIL_INC_1134 1135 +#define Z_UTIL_INC_1135 1136 +#define Z_UTIL_INC_1136 1137 +#define Z_UTIL_INC_1137 1138 +#define Z_UTIL_INC_1138 1139 +#define Z_UTIL_INC_1139 1140 +#define Z_UTIL_INC_1140 1141 +#define Z_UTIL_INC_1141 1142 +#define Z_UTIL_INC_1142 1143 +#define Z_UTIL_INC_1143 1144 +#define Z_UTIL_INC_1144 1145 +#define Z_UTIL_INC_1145 1146 +#define Z_UTIL_INC_1146 1147 +#define Z_UTIL_INC_1147 1148 +#define Z_UTIL_INC_1148 1149 +#define Z_UTIL_INC_1149 1150 +#define Z_UTIL_INC_1150 1151 +#define Z_UTIL_INC_1151 1152 +#define Z_UTIL_INC_1152 1153 +#define Z_UTIL_INC_1153 1154 +#define Z_UTIL_INC_1154 1155 +#define Z_UTIL_INC_1155 1156 +#define Z_UTIL_INC_1156 1157 +#define Z_UTIL_INC_1157 1158 +#define Z_UTIL_INC_1158 1159 +#define Z_UTIL_INC_1159 1160 +#define Z_UTIL_INC_1160 1161 +#define Z_UTIL_INC_1161 1162 +#define Z_UTIL_INC_1162 1163 +#define Z_UTIL_INC_1163 1164 +#define Z_UTIL_INC_1164 1165 +#define Z_UTIL_INC_1165 1166 +#define Z_UTIL_INC_1166 1167 +#define Z_UTIL_INC_1167 1168 +#define Z_UTIL_INC_1168 1169 +#define Z_UTIL_INC_1169 1170 +#define Z_UTIL_INC_1170 1171 +#define Z_UTIL_INC_1171 1172 +#define Z_UTIL_INC_1172 1173 +#define Z_UTIL_INC_1173 1174 +#define Z_UTIL_INC_1174 1175 +#define Z_UTIL_INC_1175 1176 +#define Z_UTIL_INC_1176 1177 +#define Z_UTIL_INC_1177 1178 +#define Z_UTIL_INC_1178 1179 +#define Z_UTIL_INC_1179 1180 +#define Z_UTIL_INC_1180 1181 +#define Z_UTIL_INC_1181 1182 +#define Z_UTIL_INC_1182 1183 +#define Z_UTIL_INC_1183 1184 +#define Z_UTIL_INC_1184 1185 +#define Z_UTIL_INC_1185 1186 +#define Z_UTIL_INC_1186 1187 +#define Z_UTIL_INC_1187 1188 +#define Z_UTIL_INC_1188 1189 +#define Z_UTIL_INC_1189 1190 +#define Z_UTIL_INC_1190 1191 +#define Z_UTIL_INC_1191 1192 +#define Z_UTIL_INC_1192 1193 +#define Z_UTIL_INC_1193 1194 +#define Z_UTIL_INC_1194 1195 +#define Z_UTIL_INC_1195 1196 +#define Z_UTIL_INC_1196 1197 +#define Z_UTIL_INC_1197 1198 +#define Z_UTIL_INC_1198 1199 +#define Z_UTIL_INC_1199 1200 +#define Z_UTIL_INC_1200 1201 +#define Z_UTIL_INC_1201 1202 +#define Z_UTIL_INC_1202 1203 +#define Z_UTIL_INC_1203 1204 +#define Z_UTIL_INC_1204 1205 +#define Z_UTIL_INC_1205 1206 +#define Z_UTIL_INC_1206 1207 +#define Z_UTIL_INC_1207 1208 +#define Z_UTIL_INC_1208 1209 +#define Z_UTIL_INC_1209 1210 +#define Z_UTIL_INC_1210 1211 +#define Z_UTIL_INC_1211 1212 +#define Z_UTIL_INC_1212 1213 +#define Z_UTIL_INC_1213 1214 +#define Z_UTIL_INC_1214 1215 +#define Z_UTIL_INC_1215 1216 +#define Z_UTIL_INC_1216 1217 +#define Z_UTIL_INC_1217 1218 +#define Z_UTIL_INC_1218 1219 +#define Z_UTIL_INC_1219 1220 +#define Z_UTIL_INC_1220 1221 +#define Z_UTIL_INC_1221 1222 +#define Z_UTIL_INC_1222 1223 +#define Z_UTIL_INC_1223 1224 +#define Z_UTIL_INC_1224 1225 +#define Z_UTIL_INC_1225 1226 +#define Z_UTIL_INC_1226 1227 +#define Z_UTIL_INC_1227 1228 +#define Z_UTIL_INC_1228 1229 +#define Z_UTIL_INC_1229 1230 +#define Z_UTIL_INC_1230 1231 +#define Z_UTIL_INC_1231 1232 +#define Z_UTIL_INC_1232 1233 +#define Z_UTIL_INC_1233 1234 +#define Z_UTIL_INC_1234 1235 +#define Z_UTIL_INC_1235 1236 +#define Z_UTIL_INC_1236 1237 +#define Z_UTIL_INC_1237 1238 +#define Z_UTIL_INC_1238 1239 +#define Z_UTIL_INC_1239 1240 +#define Z_UTIL_INC_1240 1241 +#define Z_UTIL_INC_1241 1242 +#define Z_UTIL_INC_1242 1243 +#define Z_UTIL_INC_1243 1244 +#define Z_UTIL_INC_1244 1245 +#define Z_UTIL_INC_1245 1246 +#define Z_UTIL_INC_1246 1247 +#define Z_UTIL_INC_1247 1248 +#define Z_UTIL_INC_1248 1249 +#define Z_UTIL_INC_1249 1250 +#define Z_UTIL_INC_1250 1251 +#define Z_UTIL_INC_1251 1252 +#define Z_UTIL_INC_1252 1253 +#define Z_UTIL_INC_1253 1254 +#define Z_UTIL_INC_1254 1255 +#define Z_UTIL_INC_1255 1256 +#define Z_UTIL_INC_1256 1257 +#define Z_UTIL_INC_1257 1258 +#define Z_UTIL_INC_1258 1259 +#define Z_UTIL_INC_1259 1260 +#define Z_UTIL_INC_1260 1261 +#define Z_UTIL_INC_1261 1262 +#define Z_UTIL_INC_1262 1263 +#define Z_UTIL_INC_1263 1264 +#define Z_UTIL_INC_1264 1265 +#define Z_UTIL_INC_1265 1266 +#define Z_UTIL_INC_1266 1267 +#define Z_UTIL_INC_1267 1268 +#define Z_UTIL_INC_1268 1269 +#define Z_UTIL_INC_1269 1270 +#define Z_UTIL_INC_1270 1271 +#define Z_UTIL_INC_1271 1272 +#define Z_UTIL_INC_1272 1273 +#define Z_UTIL_INC_1273 1274 +#define Z_UTIL_INC_1274 1275 +#define Z_UTIL_INC_1275 1276 +#define Z_UTIL_INC_1276 1277 +#define Z_UTIL_INC_1277 1278 +#define Z_UTIL_INC_1278 1279 +#define Z_UTIL_INC_1279 1280 +#define Z_UTIL_INC_1280 1281 +#define Z_UTIL_INC_1281 1282 +#define Z_UTIL_INC_1282 1283 +#define Z_UTIL_INC_1283 1284 +#define Z_UTIL_INC_1284 1285 +#define Z_UTIL_INC_1285 1286 +#define Z_UTIL_INC_1286 1287 +#define Z_UTIL_INC_1287 1288 +#define Z_UTIL_INC_1288 1289 +#define Z_UTIL_INC_1289 1290 +#define Z_UTIL_INC_1290 1291 +#define Z_UTIL_INC_1291 1292 +#define Z_UTIL_INC_1292 1293 +#define Z_UTIL_INC_1293 1294 +#define Z_UTIL_INC_1294 1295 +#define Z_UTIL_INC_1295 1296 +#define Z_UTIL_INC_1296 1297 +#define Z_UTIL_INC_1297 1298 +#define Z_UTIL_INC_1298 1299 +#define Z_UTIL_INC_1299 1300 +#define Z_UTIL_INC_1300 1301 +#define Z_UTIL_INC_1301 1302 +#define Z_UTIL_INC_1302 1303 +#define Z_UTIL_INC_1303 1304 +#define Z_UTIL_INC_1304 1305 +#define Z_UTIL_INC_1305 1306 +#define Z_UTIL_INC_1306 1307 +#define Z_UTIL_INC_1307 1308 +#define Z_UTIL_INC_1308 1309 +#define Z_UTIL_INC_1309 1310 +#define Z_UTIL_INC_1310 1311 +#define Z_UTIL_INC_1311 1312 +#define Z_UTIL_INC_1312 1313 +#define Z_UTIL_INC_1313 1314 +#define Z_UTIL_INC_1314 1315 +#define Z_UTIL_INC_1315 1316 +#define Z_UTIL_INC_1316 1317 +#define Z_UTIL_INC_1317 1318 +#define Z_UTIL_INC_1318 1319 +#define Z_UTIL_INC_1319 1320 +#define Z_UTIL_INC_1320 1321 +#define Z_UTIL_INC_1321 1322 +#define Z_UTIL_INC_1322 1323 +#define Z_UTIL_INC_1323 1324 +#define Z_UTIL_INC_1324 1325 +#define Z_UTIL_INC_1325 1326 +#define Z_UTIL_INC_1326 1327 +#define Z_UTIL_INC_1327 1328 +#define Z_UTIL_INC_1328 1329 +#define Z_UTIL_INC_1329 1330 +#define Z_UTIL_INC_1330 1331 +#define Z_UTIL_INC_1331 1332 +#define Z_UTIL_INC_1332 1333 +#define Z_UTIL_INC_1333 1334 +#define Z_UTIL_INC_1334 1335 +#define Z_UTIL_INC_1335 1336 +#define Z_UTIL_INC_1336 1337 +#define Z_UTIL_INC_1337 1338 +#define Z_UTIL_INC_1338 1339 +#define Z_UTIL_INC_1339 1340 +#define Z_UTIL_INC_1340 1341 +#define Z_UTIL_INC_1341 1342 +#define Z_UTIL_INC_1342 1343 +#define Z_UTIL_INC_1343 1344 +#define Z_UTIL_INC_1344 1345 +#define Z_UTIL_INC_1345 1346 +#define Z_UTIL_INC_1346 1347 +#define Z_UTIL_INC_1347 1348 +#define Z_UTIL_INC_1348 1349 +#define Z_UTIL_INC_1349 1350 +#define Z_UTIL_INC_1350 1351 +#define Z_UTIL_INC_1351 1352 +#define Z_UTIL_INC_1352 1353 +#define Z_UTIL_INC_1353 1354 +#define Z_UTIL_INC_1354 1355 +#define Z_UTIL_INC_1355 1356 +#define Z_UTIL_INC_1356 1357 +#define Z_UTIL_INC_1357 1358 +#define Z_UTIL_INC_1358 1359 +#define Z_UTIL_INC_1359 1360 +#define Z_UTIL_INC_1360 1361 +#define Z_UTIL_INC_1361 1362 +#define Z_UTIL_INC_1362 1363 +#define Z_UTIL_INC_1363 1364 +#define Z_UTIL_INC_1364 1365 +#define Z_UTIL_INC_1365 1366 +#define Z_UTIL_INC_1366 1367 +#define Z_UTIL_INC_1367 1368 +#define Z_UTIL_INC_1368 1369 +#define Z_UTIL_INC_1369 1370 +#define Z_UTIL_INC_1370 1371 +#define Z_UTIL_INC_1371 1372 +#define Z_UTIL_INC_1372 1373 +#define Z_UTIL_INC_1373 1374 +#define Z_UTIL_INC_1374 1375 +#define Z_UTIL_INC_1375 1376 +#define Z_UTIL_INC_1376 1377 +#define Z_UTIL_INC_1377 1378 +#define Z_UTIL_INC_1378 1379 +#define Z_UTIL_INC_1379 1380 +#define Z_UTIL_INC_1380 1381 +#define Z_UTIL_INC_1381 1382 +#define Z_UTIL_INC_1382 1383 +#define Z_UTIL_INC_1383 1384 +#define Z_UTIL_INC_1384 1385 +#define Z_UTIL_INC_1385 1386 +#define Z_UTIL_INC_1386 1387 +#define Z_UTIL_INC_1387 1388 +#define Z_UTIL_INC_1388 1389 +#define Z_UTIL_INC_1389 1390 +#define Z_UTIL_INC_1390 1391 +#define Z_UTIL_INC_1391 1392 +#define Z_UTIL_INC_1392 1393 +#define Z_UTIL_INC_1393 1394 +#define Z_UTIL_INC_1394 1395 +#define Z_UTIL_INC_1395 1396 +#define Z_UTIL_INC_1396 1397 +#define Z_UTIL_INC_1397 1398 +#define Z_UTIL_INC_1398 1399 +#define Z_UTIL_INC_1399 1400 +#define Z_UTIL_INC_1400 1401 +#define Z_UTIL_INC_1401 1402 +#define Z_UTIL_INC_1402 1403 +#define Z_UTIL_INC_1403 1404 +#define Z_UTIL_INC_1404 1405 +#define Z_UTIL_INC_1405 1406 +#define Z_UTIL_INC_1406 1407 +#define Z_UTIL_INC_1407 1408 +#define Z_UTIL_INC_1408 1409 +#define Z_UTIL_INC_1409 1410 +#define Z_UTIL_INC_1410 1411 +#define Z_UTIL_INC_1411 1412 +#define Z_UTIL_INC_1412 1413 +#define Z_UTIL_INC_1413 1414 +#define Z_UTIL_INC_1414 1415 +#define Z_UTIL_INC_1415 1416 +#define Z_UTIL_INC_1416 1417 +#define Z_UTIL_INC_1417 1418 +#define Z_UTIL_INC_1418 1419 +#define Z_UTIL_INC_1419 1420 +#define Z_UTIL_INC_1420 1421 +#define Z_UTIL_INC_1421 1422 +#define Z_UTIL_INC_1422 1423 +#define Z_UTIL_INC_1423 1424 +#define Z_UTIL_INC_1424 1425 +#define Z_UTIL_INC_1425 1426 +#define Z_UTIL_INC_1426 1427 +#define Z_UTIL_INC_1427 1428 +#define Z_UTIL_INC_1428 1429 +#define Z_UTIL_INC_1429 1430 +#define Z_UTIL_INC_1430 1431 +#define Z_UTIL_INC_1431 1432 +#define Z_UTIL_INC_1432 1433 +#define Z_UTIL_INC_1433 1434 +#define Z_UTIL_INC_1434 1435 +#define Z_UTIL_INC_1435 1436 +#define Z_UTIL_INC_1436 1437 +#define Z_UTIL_INC_1437 1438 +#define Z_UTIL_INC_1438 1439 +#define Z_UTIL_INC_1439 1440 +#define Z_UTIL_INC_1440 1441 +#define Z_UTIL_INC_1441 1442 +#define Z_UTIL_INC_1442 1443 +#define Z_UTIL_INC_1443 1444 +#define Z_UTIL_INC_1444 1445 +#define Z_UTIL_INC_1445 1446 +#define Z_UTIL_INC_1446 1447 +#define Z_UTIL_INC_1447 1448 +#define Z_UTIL_INC_1448 1449 +#define Z_UTIL_INC_1449 1450 +#define Z_UTIL_INC_1450 1451 +#define Z_UTIL_INC_1451 1452 +#define Z_UTIL_INC_1452 1453 +#define Z_UTIL_INC_1453 1454 +#define Z_UTIL_INC_1454 1455 +#define Z_UTIL_INC_1455 1456 +#define Z_UTIL_INC_1456 1457 +#define Z_UTIL_INC_1457 1458 +#define Z_UTIL_INC_1458 1459 +#define Z_UTIL_INC_1459 1460 +#define Z_UTIL_INC_1460 1461 +#define Z_UTIL_INC_1461 1462 +#define Z_UTIL_INC_1462 1463 +#define Z_UTIL_INC_1463 1464 +#define Z_UTIL_INC_1464 1465 +#define Z_UTIL_INC_1465 1466 +#define Z_UTIL_INC_1466 1467 +#define Z_UTIL_INC_1467 1468 +#define Z_UTIL_INC_1468 1469 +#define Z_UTIL_INC_1469 1470 +#define Z_UTIL_INC_1470 1471 +#define Z_UTIL_INC_1471 1472 +#define Z_UTIL_INC_1472 1473 +#define Z_UTIL_INC_1473 1474 +#define Z_UTIL_INC_1474 1475 +#define Z_UTIL_INC_1475 1476 +#define Z_UTIL_INC_1476 1477 +#define Z_UTIL_INC_1477 1478 +#define Z_UTIL_INC_1478 1479 +#define Z_UTIL_INC_1479 1480 +#define Z_UTIL_INC_1480 1481 +#define Z_UTIL_INC_1481 1482 +#define Z_UTIL_INC_1482 1483 +#define Z_UTIL_INC_1483 1484 +#define Z_UTIL_INC_1484 1485 +#define Z_UTIL_INC_1485 1486 +#define Z_UTIL_INC_1486 1487 +#define Z_UTIL_INC_1487 1488 +#define Z_UTIL_INC_1488 1489 +#define Z_UTIL_INC_1489 1490 +#define Z_UTIL_INC_1490 1491 +#define Z_UTIL_INC_1491 1492 +#define Z_UTIL_INC_1492 1493 +#define Z_UTIL_INC_1493 1494 +#define Z_UTIL_INC_1494 1495 +#define Z_UTIL_INC_1495 1496 +#define Z_UTIL_INC_1496 1497 +#define Z_UTIL_INC_1497 1498 +#define Z_UTIL_INC_1498 1499 +#define Z_UTIL_INC_1499 1500 +#define Z_UTIL_INC_1500 1501 +#define Z_UTIL_INC_1501 1502 +#define Z_UTIL_INC_1502 1503 +#define Z_UTIL_INC_1503 1504 +#define Z_UTIL_INC_1504 1505 +#define Z_UTIL_INC_1505 1506 +#define Z_UTIL_INC_1506 1507 +#define Z_UTIL_INC_1507 1508 +#define Z_UTIL_INC_1508 1509 +#define Z_UTIL_INC_1509 1510 +#define Z_UTIL_INC_1510 1511 +#define Z_UTIL_INC_1511 1512 +#define Z_UTIL_INC_1512 1513 +#define Z_UTIL_INC_1513 1514 +#define Z_UTIL_INC_1514 1515 +#define Z_UTIL_INC_1515 1516 +#define Z_UTIL_INC_1516 1517 +#define Z_UTIL_INC_1517 1518 +#define Z_UTIL_INC_1518 1519 +#define Z_UTIL_INC_1519 1520 +#define Z_UTIL_INC_1520 1521 +#define Z_UTIL_INC_1521 1522 +#define Z_UTIL_INC_1522 1523 +#define Z_UTIL_INC_1523 1524 +#define Z_UTIL_INC_1524 1525 +#define Z_UTIL_INC_1525 1526 +#define Z_UTIL_INC_1526 1527 +#define Z_UTIL_INC_1527 1528 +#define Z_UTIL_INC_1528 1529 +#define Z_UTIL_INC_1529 1530 +#define Z_UTIL_INC_1530 1531 +#define Z_UTIL_INC_1531 1532 +#define Z_UTIL_INC_1532 1533 +#define Z_UTIL_INC_1533 1534 +#define Z_UTIL_INC_1534 1535 +#define Z_UTIL_INC_1535 1536 +#define Z_UTIL_INC_1536 1537 +#define Z_UTIL_INC_1537 1538 +#define Z_UTIL_INC_1538 1539 +#define Z_UTIL_INC_1539 1540 +#define Z_UTIL_INC_1540 1541 +#define Z_UTIL_INC_1541 1542 +#define Z_UTIL_INC_1542 1543 +#define Z_UTIL_INC_1543 1544 +#define Z_UTIL_INC_1544 1545 +#define Z_UTIL_INC_1545 1546 +#define Z_UTIL_INC_1546 1547 +#define Z_UTIL_INC_1547 1548 +#define Z_UTIL_INC_1548 1549 +#define Z_UTIL_INC_1549 1550 +#define Z_UTIL_INC_1550 1551 +#define Z_UTIL_INC_1551 1552 +#define Z_UTIL_INC_1552 1553 +#define Z_UTIL_INC_1553 1554 +#define Z_UTIL_INC_1554 1555 +#define Z_UTIL_INC_1555 1556 +#define Z_UTIL_INC_1556 1557 +#define Z_UTIL_INC_1557 1558 +#define Z_UTIL_INC_1558 1559 +#define Z_UTIL_INC_1559 1560 +#define Z_UTIL_INC_1560 1561 +#define Z_UTIL_INC_1561 1562 +#define Z_UTIL_INC_1562 1563 +#define Z_UTIL_INC_1563 1564 +#define Z_UTIL_INC_1564 1565 +#define Z_UTIL_INC_1565 1566 +#define Z_UTIL_INC_1566 1567 +#define Z_UTIL_INC_1567 1568 +#define Z_UTIL_INC_1568 1569 +#define Z_UTIL_INC_1569 1570 +#define Z_UTIL_INC_1570 1571 +#define Z_UTIL_INC_1571 1572 +#define Z_UTIL_INC_1572 1573 +#define Z_UTIL_INC_1573 1574 +#define Z_UTIL_INC_1574 1575 +#define Z_UTIL_INC_1575 1576 +#define Z_UTIL_INC_1576 1577 +#define Z_UTIL_INC_1577 1578 +#define Z_UTIL_INC_1578 1579 +#define Z_UTIL_INC_1579 1580 +#define Z_UTIL_INC_1580 1581 +#define Z_UTIL_INC_1581 1582 +#define Z_UTIL_INC_1582 1583 +#define Z_UTIL_INC_1583 1584 +#define Z_UTIL_INC_1584 1585 +#define Z_UTIL_INC_1585 1586 +#define Z_UTIL_INC_1586 1587 +#define Z_UTIL_INC_1587 1588 +#define Z_UTIL_INC_1588 1589 +#define Z_UTIL_INC_1589 1590 +#define Z_UTIL_INC_1590 1591 +#define Z_UTIL_INC_1591 1592 +#define Z_UTIL_INC_1592 1593 +#define Z_UTIL_INC_1593 1594 +#define Z_UTIL_INC_1594 1595 +#define Z_UTIL_INC_1595 1596 +#define Z_UTIL_INC_1596 1597 +#define Z_UTIL_INC_1597 1598 +#define Z_UTIL_INC_1598 1599 +#define Z_UTIL_INC_1599 1600 +#define Z_UTIL_INC_1600 1601 +#define Z_UTIL_INC_1601 1602 +#define Z_UTIL_INC_1602 1603 +#define Z_UTIL_INC_1603 1604 +#define Z_UTIL_INC_1604 1605 +#define Z_UTIL_INC_1605 1606 +#define Z_UTIL_INC_1606 1607 +#define Z_UTIL_INC_1607 1608 +#define Z_UTIL_INC_1608 1609 +#define Z_UTIL_INC_1609 1610 +#define Z_UTIL_INC_1610 1611 +#define Z_UTIL_INC_1611 1612 +#define Z_UTIL_INC_1612 1613 +#define Z_UTIL_INC_1613 1614 +#define Z_UTIL_INC_1614 1615 +#define Z_UTIL_INC_1615 1616 +#define Z_UTIL_INC_1616 1617 +#define Z_UTIL_INC_1617 1618 +#define Z_UTIL_INC_1618 1619 +#define Z_UTIL_INC_1619 1620 +#define Z_UTIL_INC_1620 1621 +#define Z_UTIL_INC_1621 1622 +#define Z_UTIL_INC_1622 1623 +#define Z_UTIL_INC_1623 1624 +#define Z_UTIL_INC_1624 1625 +#define Z_UTIL_INC_1625 1626 +#define Z_UTIL_INC_1626 1627 +#define Z_UTIL_INC_1627 1628 +#define Z_UTIL_INC_1628 1629 +#define Z_UTIL_INC_1629 1630 +#define Z_UTIL_INC_1630 1631 +#define Z_UTIL_INC_1631 1632 +#define Z_UTIL_INC_1632 1633 +#define Z_UTIL_INC_1633 1634 +#define Z_UTIL_INC_1634 1635 +#define Z_UTIL_INC_1635 1636 +#define Z_UTIL_INC_1636 1637 +#define Z_UTIL_INC_1637 1638 +#define Z_UTIL_INC_1638 1639 +#define Z_UTIL_INC_1639 1640 +#define Z_UTIL_INC_1640 1641 +#define Z_UTIL_INC_1641 1642 +#define Z_UTIL_INC_1642 1643 +#define Z_UTIL_INC_1643 1644 +#define Z_UTIL_INC_1644 1645 +#define Z_UTIL_INC_1645 1646 +#define Z_UTIL_INC_1646 1647 +#define Z_UTIL_INC_1647 1648 +#define Z_UTIL_INC_1648 1649 +#define Z_UTIL_INC_1649 1650 +#define Z_UTIL_INC_1650 1651 +#define Z_UTIL_INC_1651 1652 +#define Z_UTIL_INC_1652 1653 +#define Z_UTIL_INC_1653 1654 +#define Z_UTIL_INC_1654 1655 +#define Z_UTIL_INC_1655 1656 +#define Z_UTIL_INC_1656 1657 +#define Z_UTIL_INC_1657 1658 +#define Z_UTIL_INC_1658 1659 +#define Z_UTIL_INC_1659 1660 +#define Z_UTIL_INC_1660 1661 +#define Z_UTIL_INC_1661 1662 +#define Z_UTIL_INC_1662 1663 +#define Z_UTIL_INC_1663 1664 +#define Z_UTIL_INC_1664 1665 +#define Z_UTIL_INC_1665 1666 +#define Z_UTIL_INC_1666 1667 +#define Z_UTIL_INC_1667 1668 +#define Z_UTIL_INC_1668 1669 +#define Z_UTIL_INC_1669 1670 +#define Z_UTIL_INC_1670 1671 +#define Z_UTIL_INC_1671 1672 +#define Z_UTIL_INC_1672 1673 +#define Z_UTIL_INC_1673 1674 +#define Z_UTIL_INC_1674 1675 +#define Z_UTIL_INC_1675 1676 +#define Z_UTIL_INC_1676 1677 +#define Z_UTIL_INC_1677 1678 +#define Z_UTIL_INC_1678 1679 +#define Z_UTIL_INC_1679 1680 +#define Z_UTIL_INC_1680 1681 +#define Z_UTIL_INC_1681 1682 +#define Z_UTIL_INC_1682 1683 +#define Z_UTIL_INC_1683 1684 +#define Z_UTIL_INC_1684 1685 +#define Z_UTIL_INC_1685 1686 +#define Z_UTIL_INC_1686 1687 +#define Z_UTIL_INC_1687 1688 +#define Z_UTIL_INC_1688 1689 +#define Z_UTIL_INC_1689 1690 +#define Z_UTIL_INC_1690 1691 +#define Z_UTIL_INC_1691 1692 +#define Z_UTIL_INC_1692 1693 +#define Z_UTIL_INC_1693 1694 +#define Z_UTIL_INC_1694 1695 +#define Z_UTIL_INC_1695 1696 +#define Z_UTIL_INC_1696 1697 +#define Z_UTIL_INC_1697 1698 +#define Z_UTIL_INC_1698 1699 +#define Z_UTIL_INC_1699 1700 +#define Z_UTIL_INC_1700 1701 +#define Z_UTIL_INC_1701 1702 +#define Z_UTIL_INC_1702 1703 +#define Z_UTIL_INC_1703 1704 +#define Z_UTIL_INC_1704 1705 +#define Z_UTIL_INC_1705 1706 +#define Z_UTIL_INC_1706 1707 +#define Z_UTIL_INC_1707 1708 +#define Z_UTIL_INC_1708 1709 +#define Z_UTIL_INC_1709 1710 +#define Z_UTIL_INC_1710 1711 +#define Z_UTIL_INC_1711 1712 +#define Z_UTIL_INC_1712 1713 +#define Z_UTIL_INC_1713 1714 +#define Z_UTIL_INC_1714 1715 +#define Z_UTIL_INC_1715 1716 +#define Z_UTIL_INC_1716 1717 +#define Z_UTIL_INC_1717 1718 +#define Z_UTIL_INC_1718 1719 +#define Z_UTIL_INC_1719 1720 +#define Z_UTIL_INC_1720 1721 +#define Z_UTIL_INC_1721 1722 +#define Z_UTIL_INC_1722 1723 +#define Z_UTIL_INC_1723 1724 +#define Z_UTIL_INC_1724 1725 +#define Z_UTIL_INC_1725 1726 +#define Z_UTIL_INC_1726 1727 +#define Z_UTIL_INC_1727 1728 +#define Z_UTIL_INC_1728 1729 +#define Z_UTIL_INC_1729 1730 +#define Z_UTIL_INC_1730 1731 +#define Z_UTIL_INC_1731 1732 +#define Z_UTIL_INC_1732 1733 +#define Z_UTIL_INC_1733 1734 +#define Z_UTIL_INC_1734 1735 +#define Z_UTIL_INC_1735 1736 +#define Z_UTIL_INC_1736 1737 +#define Z_UTIL_INC_1737 1738 +#define Z_UTIL_INC_1738 1739 +#define Z_UTIL_INC_1739 1740 +#define Z_UTIL_INC_1740 1741 +#define Z_UTIL_INC_1741 1742 +#define Z_UTIL_INC_1742 1743 +#define Z_UTIL_INC_1743 1744 +#define Z_UTIL_INC_1744 1745 +#define Z_UTIL_INC_1745 1746 +#define Z_UTIL_INC_1746 1747 +#define Z_UTIL_INC_1747 1748 +#define Z_UTIL_INC_1748 1749 +#define Z_UTIL_INC_1749 1750 +#define Z_UTIL_INC_1750 1751 +#define Z_UTIL_INC_1751 1752 +#define Z_UTIL_INC_1752 1753 +#define Z_UTIL_INC_1753 1754 +#define Z_UTIL_INC_1754 1755 +#define Z_UTIL_INC_1755 1756 +#define Z_UTIL_INC_1756 1757 +#define Z_UTIL_INC_1757 1758 +#define Z_UTIL_INC_1758 1759 +#define Z_UTIL_INC_1759 1760 +#define Z_UTIL_INC_1760 1761 +#define Z_UTIL_INC_1761 1762 +#define Z_UTIL_INC_1762 1763 +#define Z_UTIL_INC_1763 1764 +#define Z_UTIL_INC_1764 1765 +#define Z_UTIL_INC_1765 1766 +#define Z_UTIL_INC_1766 1767 +#define Z_UTIL_INC_1767 1768 +#define Z_UTIL_INC_1768 1769 +#define Z_UTIL_INC_1769 1770 +#define Z_UTIL_INC_1770 1771 +#define Z_UTIL_INC_1771 1772 +#define Z_UTIL_INC_1772 1773 +#define Z_UTIL_INC_1773 1774 +#define Z_UTIL_INC_1774 1775 +#define Z_UTIL_INC_1775 1776 +#define Z_UTIL_INC_1776 1777 +#define Z_UTIL_INC_1777 1778 +#define Z_UTIL_INC_1778 1779 +#define Z_UTIL_INC_1779 1780 +#define Z_UTIL_INC_1780 1781 +#define Z_UTIL_INC_1781 1782 +#define Z_UTIL_INC_1782 1783 +#define Z_UTIL_INC_1783 1784 +#define Z_UTIL_INC_1784 1785 +#define Z_UTIL_INC_1785 1786 +#define Z_UTIL_INC_1786 1787 +#define Z_UTIL_INC_1787 1788 +#define Z_UTIL_INC_1788 1789 +#define Z_UTIL_INC_1789 1790 +#define Z_UTIL_INC_1790 1791 +#define Z_UTIL_INC_1791 1792 +#define Z_UTIL_INC_1792 1793 +#define Z_UTIL_INC_1793 1794 +#define Z_UTIL_INC_1794 1795 +#define Z_UTIL_INC_1795 1796 +#define Z_UTIL_INC_1796 1797 +#define Z_UTIL_INC_1797 1798 +#define Z_UTIL_INC_1798 1799 +#define Z_UTIL_INC_1799 1800 +#define Z_UTIL_INC_1800 1801 +#define Z_UTIL_INC_1801 1802 +#define Z_UTIL_INC_1802 1803 +#define Z_UTIL_INC_1803 1804 +#define Z_UTIL_INC_1804 1805 +#define Z_UTIL_INC_1805 1806 +#define Z_UTIL_INC_1806 1807 +#define Z_UTIL_INC_1807 1808 +#define Z_UTIL_INC_1808 1809 +#define Z_UTIL_INC_1809 1810 +#define Z_UTIL_INC_1810 1811 +#define Z_UTIL_INC_1811 1812 +#define Z_UTIL_INC_1812 1813 +#define Z_UTIL_INC_1813 1814 +#define Z_UTIL_INC_1814 1815 +#define Z_UTIL_INC_1815 1816 +#define Z_UTIL_INC_1816 1817 +#define Z_UTIL_INC_1817 1818 +#define Z_UTIL_INC_1818 1819 +#define Z_UTIL_INC_1819 1820 +#define Z_UTIL_INC_1820 1821 +#define Z_UTIL_INC_1821 1822 +#define Z_UTIL_INC_1822 1823 +#define Z_UTIL_INC_1823 1824 +#define Z_UTIL_INC_1824 1825 +#define Z_UTIL_INC_1825 1826 +#define Z_UTIL_INC_1826 1827 +#define Z_UTIL_INC_1827 1828 +#define Z_UTIL_INC_1828 1829 +#define Z_UTIL_INC_1829 1830 +#define Z_UTIL_INC_1830 1831 +#define Z_UTIL_INC_1831 1832 +#define Z_UTIL_INC_1832 1833 +#define Z_UTIL_INC_1833 1834 +#define Z_UTIL_INC_1834 1835 +#define Z_UTIL_INC_1835 1836 +#define Z_UTIL_INC_1836 1837 +#define Z_UTIL_INC_1837 1838 +#define Z_UTIL_INC_1838 1839 +#define Z_UTIL_INC_1839 1840 +#define Z_UTIL_INC_1840 1841 +#define Z_UTIL_INC_1841 1842 +#define Z_UTIL_INC_1842 1843 +#define Z_UTIL_INC_1843 1844 +#define Z_UTIL_INC_1844 1845 +#define Z_UTIL_INC_1845 1846 +#define Z_UTIL_INC_1846 1847 +#define Z_UTIL_INC_1847 1848 +#define Z_UTIL_INC_1848 1849 +#define Z_UTIL_INC_1849 1850 +#define Z_UTIL_INC_1850 1851 +#define Z_UTIL_INC_1851 1852 +#define Z_UTIL_INC_1852 1853 +#define Z_UTIL_INC_1853 1854 +#define Z_UTIL_INC_1854 1855 +#define Z_UTIL_INC_1855 1856 +#define Z_UTIL_INC_1856 1857 +#define Z_UTIL_INC_1857 1858 +#define Z_UTIL_INC_1858 1859 +#define Z_UTIL_INC_1859 1860 +#define Z_UTIL_INC_1860 1861 +#define Z_UTIL_INC_1861 1862 +#define Z_UTIL_INC_1862 1863 +#define Z_UTIL_INC_1863 1864 +#define Z_UTIL_INC_1864 1865 +#define Z_UTIL_INC_1865 1866 +#define Z_UTIL_INC_1866 1867 +#define Z_UTIL_INC_1867 1868 +#define Z_UTIL_INC_1868 1869 +#define Z_UTIL_INC_1869 1870 +#define Z_UTIL_INC_1870 1871 +#define Z_UTIL_INC_1871 1872 +#define Z_UTIL_INC_1872 1873 +#define Z_UTIL_INC_1873 1874 +#define Z_UTIL_INC_1874 1875 +#define Z_UTIL_INC_1875 1876 +#define Z_UTIL_INC_1876 1877 +#define Z_UTIL_INC_1877 1878 +#define Z_UTIL_INC_1878 1879 +#define Z_UTIL_INC_1879 1880 +#define Z_UTIL_INC_1880 1881 +#define Z_UTIL_INC_1881 1882 +#define Z_UTIL_INC_1882 1883 +#define Z_UTIL_INC_1883 1884 +#define Z_UTIL_INC_1884 1885 +#define Z_UTIL_INC_1885 1886 +#define Z_UTIL_INC_1886 1887 +#define Z_UTIL_INC_1887 1888 +#define Z_UTIL_INC_1888 1889 +#define Z_UTIL_INC_1889 1890 +#define Z_UTIL_INC_1890 1891 +#define Z_UTIL_INC_1891 1892 +#define Z_UTIL_INC_1892 1893 +#define Z_UTIL_INC_1893 1894 +#define Z_UTIL_INC_1894 1895 +#define Z_UTIL_INC_1895 1896 +#define Z_UTIL_INC_1896 1897 +#define Z_UTIL_INC_1897 1898 +#define Z_UTIL_INC_1898 1899 +#define Z_UTIL_INC_1899 1900 +#define Z_UTIL_INC_1900 1901 +#define Z_UTIL_INC_1901 1902 +#define Z_UTIL_INC_1902 1903 +#define Z_UTIL_INC_1903 1904 +#define Z_UTIL_INC_1904 1905 +#define Z_UTIL_INC_1905 1906 +#define Z_UTIL_INC_1906 1907 +#define Z_UTIL_INC_1907 1908 +#define Z_UTIL_INC_1908 1909 +#define Z_UTIL_INC_1909 1910 +#define Z_UTIL_INC_1910 1911 +#define Z_UTIL_INC_1911 1912 +#define Z_UTIL_INC_1912 1913 +#define Z_UTIL_INC_1913 1914 +#define Z_UTIL_INC_1914 1915 +#define Z_UTIL_INC_1915 1916 +#define Z_UTIL_INC_1916 1917 +#define Z_UTIL_INC_1917 1918 +#define Z_UTIL_INC_1918 1919 +#define Z_UTIL_INC_1919 1920 +#define Z_UTIL_INC_1920 1921 +#define Z_UTIL_INC_1921 1922 +#define Z_UTIL_INC_1922 1923 +#define Z_UTIL_INC_1923 1924 +#define Z_UTIL_INC_1924 1925 +#define Z_UTIL_INC_1925 1926 +#define Z_UTIL_INC_1926 1927 +#define Z_UTIL_INC_1927 1928 +#define Z_UTIL_INC_1928 1929 +#define Z_UTIL_INC_1929 1930 +#define Z_UTIL_INC_1930 1931 +#define Z_UTIL_INC_1931 1932 +#define Z_UTIL_INC_1932 1933 +#define Z_UTIL_INC_1933 1934 +#define Z_UTIL_INC_1934 1935 +#define Z_UTIL_INC_1935 1936 +#define Z_UTIL_INC_1936 1937 +#define Z_UTIL_INC_1937 1938 +#define Z_UTIL_INC_1938 1939 +#define Z_UTIL_INC_1939 1940 +#define Z_UTIL_INC_1940 1941 +#define Z_UTIL_INC_1941 1942 +#define Z_UTIL_INC_1942 1943 +#define Z_UTIL_INC_1943 1944 +#define Z_UTIL_INC_1944 1945 +#define Z_UTIL_INC_1945 1946 +#define Z_UTIL_INC_1946 1947 +#define Z_UTIL_INC_1947 1948 +#define Z_UTIL_INC_1948 1949 +#define Z_UTIL_INC_1949 1950 +#define Z_UTIL_INC_1950 1951 +#define Z_UTIL_INC_1951 1952 +#define Z_UTIL_INC_1952 1953 +#define Z_UTIL_INC_1953 1954 +#define Z_UTIL_INC_1954 1955 +#define Z_UTIL_INC_1955 1956 +#define Z_UTIL_INC_1956 1957 +#define Z_UTIL_INC_1957 1958 +#define Z_UTIL_INC_1958 1959 +#define Z_UTIL_INC_1959 1960 +#define Z_UTIL_INC_1960 1961 +#define Z_UTIL_INC_1961 1962 +#define Z_UTIL_INC_1962 1963 +#define Z_UTIL_INC_1963 1964 +#define Z_UTIL_INC_1964 1965 +#define Z_UTIL_INC_1965 1966 +#define Z_UTIL_INC_1966 1967 +#define Z_UTIL_INC_1967 1968 +#define Z_UTIL_INC_1968 1969 +#define Z_UTIL_INC_1969 1970 +#define Z_UTIL_INC_1970 1971 +#define Z_UTIL_INC_1971 1972 +#define Z_UTIL_INC_1972 1973 +#define Z_UTIL_INC_1973 1974 +#define Z_UTIL_INC_1974 1975 +#define Z_UTIL_INC_1975 1976 +#define Z_UTIL_INC_1976 1977 +#define Z_UTIL_INC_1977 1978 +#define Z_UTIL_INC_1978 1979 +#define Z_UTIL_INC_1979 1980 +#define Z_UTIL_INC_1980 1981 +#define Z_UTIL_INC_1981 1982 +#define Z_UTIL_INC_1982 1983 +#define Z_UTIL_INC_1983 1984 +#define Z_UTIL_INC_1984 1985 +#define Z_UTIL_INC_1985 1986 +#define Z_UTIL_INC_1986 1987 +#define Z_UTIL_INC_1987 1988 +#define Z_UTIL_INC_1988 1989 +#define Z_UTIL_INC_1989 1990 +#define Z_UTIL_INC_1990 1991 +#define Z_UTIL_INC_1991 1992 +#define Z_UTIL_INC_1992 1993 +#define Z_UTIL_INC_1993 1994 +#define Z_UTIL_INC_1994 1995 +#define Z_UTIL_INC_1995 1996 +#define Z_UTIL_INC_1996 1997 +#define Z_UTIL_INC_1997 1998 +#define Z_UTIL_INC_1998 1999 +#define Z_UTIL_INC_1999 2000 +#define Z_UTIL_INC_2000 2001 +#define Z_UTIL_INC_2001 2002 +#define Z_UTIL_INC_2002 2003 +#define Z_UTIL_INC_2003 2004 +#define Z_UTIL_INC_2004 2005 +#define Z_UTIL_INC_2005 2006 +#define Z_UTIL_INC_2006 2007 +#define Z_UTIL_INC_2007 2008 +#define Z_UTIL_INC_2008 2009 +#define Z_UTIL_INC_2009 2010 +#define Z_UTIL_INC_2010 2011 +#define Z_UTIL_INC_2011 2012 +#define Z_UTIL_INC_2012 2013 +#define Z_UTIL_INC_2013 2014 +#define Z_UTIL_INC_2014 2015 +#define Z_UTIL_INC_2015 2016 +#define Z_UTIL_INC_2016 2017 +#define Z_UTIL_INC_2017 2018 +#define Z_UTIL_INC_2018 2019 +#define Z_UTIL_INC_2019 2020 +#define Z_UTIL_INC_2020 2021 +#define Z_UTIL_INC_2021 2022 +#define Z_UTIL_INC_2022 2023 +#define Z_UTIL_INC_2023 2024 +#define Z_UTIL_INC_2024 2025 +#define Z_UTIL_INC_2025 2026 +#define Z_UTIL_INC_2026 2027 +#define Z_UTIL_INC_2027 2028 +#define Z_UTIL_INC_2028 2029 +#define Z_UTIL_INC_2029 2030 +#define Z_UTIL_INC_2030 2031 +#define Z_UTIL_INC_2031 2032 +#define Z_UTIL_INC_2032 2033 +#define Z_UTIL_INC_2033 2034 +#define Z_UTIL_INC_2034 2035 +#define Z_UTIL_INC_2035 2036 +#define Z_UTIL_INC_2036 2037 +#define Z_UTIL_INC_2037 2038 +#define Z_UTIL_INC_2038 2039 +#define Z_UTIL_INC_2039 2040 +#define Z_UTIL_INC_2040 2041 +#define Z_UTIL_INC_2041 2042 +#define Z_UTIL_INC_2042 2043 +#define Z_UTIL_INC_2043 2044 +#define Z_UTIL_INC_2044 2045 +#define Z_UTIL_INC_2045 2046 +#define Z_UTIL_INC_2046 2047 +#define Z_UTIL_INC_2047 2048 +#define Z_UTIL_INC_2048 2049 +#define Z_UTIL_INC_2049 2050 +#define Z_UTIL_INC_2050 2051 +#define Z_UTIL_INC_2051 2052 +#define Z_UTIL_INC_2052 2053 +#define Z_UTIL_INC_2053 2054 +#define Z_UTIL_INC_2054 2055 +#define Z_UTIL_INC_2055 2056 +#define Z_UTIL_INC_2056 2057 +#define Z_UTIL_INC_2057 2058 +#define Z_UTIL_INC_2058 2059 +#define Z_UTIL_INC_2059 2060 +#define Z_UTIL_INC_2060 2061 +#define Z_UTIL_INC_2061 2062 +#define Z_UTIL_INC_2062 2063 +#define Z_UTIL_INC_2063 2064 +#define Z_UTIL_INC_2064 2065 +#define Z_UTIL_INC_2065 2066 +#define Z_UTIL_INC_2066 2067 +#define Z_UTIL_INC_2067 2068 +#define Z_UTIL_INC_2068 2069 +#define Z_UTIL_INC_2069 2070 +#define Z_UTIL_INC_2070 2071 +#define Z_UTIL_INC_2071 2072 +#define Z_UTIL_INC_2072 2073 +#define Z_UTIL_INC_2073 2074 +#define Z_UTIL_INC_2074 2075 +#define Z_UTIL_INC_2075 2076 +#define Z_UTIL_INC_2076 2077 +#define Z_UTIL_INC_2077 2078 +#define Z_UTIL_INC_2078 2079 +#define Z_UTIL_INC_2079 2080 +#define Z_UTIL_INC_2080 2081 +#define Z_UTIL_INC_2081 2082 +#define Z_UTIL_INC_2082 2083 +#define Z_UTIL_INC_2083 2084 +#define Z_UTIL_INC_2084 2085 +#define Z_UTIL_INC_2085 2086 +#define Z_UTIL_INC_2086 2087 +#define Z_UTIL_INC_2087 2088 +#define Z_UTIL_INC_2088 2089 +#define Z_UTIL_INC_2089 2090 +#define Z_UTIL_INC_2090 2091 +#define Z_UTIL_INC_2091 2092 +#define Z_UTIL_INC_2092 2093 +#define Z_UTIL_INC_2093 2094 +#define Z_UTIL_INC_2094 2095 +#define Z_UTIL_INC_2095 2096 +#define Z_UTIL_INC_2096 2097 +#define Z_UTIL_INC_2097 2098 +#define Z_UTIL_INC_2098 2099 +#define Z_UTIL_INC_2099 2100 +#define Z_UTIL_INC_2100 2101 +#define Z_UTIL_INC_2101 2102 +#define Z_UTIL_INC_2102 2103 +#define Z_UTIL_INC_2103 2104 +#define Z_UTIL_INC_2104 2105 +#define Z_UTIL_INC_2105 2106 +#define Z_UTIL_INC_2106 2107 +#define Z_UTIL_INC_2107 2108 +#define Z_UTIL_INC_2108 2109 +#define Z_UTIL_INC_2109 2110 +#define Z_UTIL_INC_2110 2111 +#define Z_UTIL_INC_2111 2112 +#define Z_UTIL_INC_2112 2113 +#define Z_UTIL_INC_2113 2114 +#define Z_UTIL_INC_2114 2115 +#define Z_UTIL_INC_2115 2116 +#define Z_UTIL_INC_2116 2117 +#define Z_UTIL_INC_2117 2118 +#define Z_UTIL_INC_2118 2119 +#define Z_UTIL_INC_2119 2120 +#define Z_UTIL_INC_2120 2121 +#define Z_UTIL_INC_2121 2122 +#define Z_UTIL_INC_2122 2123 +#define Z_UTIL_INC_2123 2124 +#define Z_UTIL_INC_2124 2125 +#define Z_UTIL_INC_2125 2126 +#define Z_UTIL_INC_2126 2127 +#define Z_UTIL_INC_2127 2128 +#define Z_UTIL_INC_2128 2129 +#define Z_UTIL_INC_2129 2130 +#define Z_UTIL_INC_2130 2131 +#define Z_UTIL_INC_2131 2132 +#define Z_UTIL_INC_2132 2133 +#define Z_UTIL_INC_2133 2134 +#define Z_UTIL_INC_2134 2135 +#define Z_UTIL_INC_2135 2136 +#define Z_UTIL_INC_2136 2137 +#define Z_UTIL_INC_2137 2138 +#define Z_UTIL_INC_2138 2139 +#define Z_UTIL_INC_2139 2140 +#define Z_UTIL_INC_2140 2141 +#define Z_UTIL_INC_2141 2142 +#define Z_UTIL_INC_2142 2143 +#define Z_UTIL_INC_2143 2144 +#define Z_UTIL_INC_2144 2145 +#define Z_UTIL_INC_2145 2146 +#define Z_UTIL_INC_2146 2147 +#define Z_UTIL_INC_2147 2148 +#define Z_UTIL_INC_2148 2149 +#define Z_UTIL_INC_2149 2150 +#define Z_UTIL_INC_2150 2151 +#define Z_UTIL_INC_2151 2152 +#define Z_UTIL_INC_2152 2153 +#define Z_UTIL_INC_2153 2154 +#define Z_UTIL_INC_2154 2155 +#define Z_UTIL_INC_2155 2156 +#define Z_UTIL_INC_2156 2157 +#define Z_UTIL_INC_2157 2158 +#define Z_UTIL_INC_2158 2159 +#define Z_UTIL_INC_2159 2160 +#define Z_UTIL_INC_2160 2161 +#define Z_UTIL_INC_2161 2162 +#define Z_UTIL_INC_2162 2163 +#define Z_UTIL_INC_2163 2164 +#define Z_UTIL_INC_2164 2165 +#define Z_UTIL_INC_2165 2166 +#define Z_UTIL_INC_2166 2167 +#define Z_UTIL_INC_2167 2168 +#define Z_UTIL_INC_2168 2169 +#define Z_UTIL_INC_2169 2170 +#define Z_UTIL_INC_2170 2171 +#define Z_UTIL_INC_2171 2172 +#define Z_UTIL_INC_2172 2173 +#define Z_UTIL_INC_2173 2174 +#define Z_UTIL_INC_2174 2175 +#define Z_UTIL_INC_2175 2176 +#define Z_UTIL_INC_2176 2177 +#define Z_UTIL_INC_2177 2178 +#define Z_UTIL_INC_2178 2179 +#define Z_UTIL_INC_2179 2180 +#define Z_UTIL_INC_2180 2181 +#define Z_UTIL_INC_2181 2182 +#define Z_UTIL_INC_2182 2183 +#define Z_UTIL_INC_2183 2184 +#define Z_UTIL_INC_2184 2185 +#define Z_UTIL_INC_2185 2186 +#define Z_UTIL_INC_2186 2187 +#define Z_UTIL_INC_2187 2188 +#define Z_UTIL_INC_2188 2189 +#define Z_UTIL_INC_2189 2190 +#define Z_UTIL_INC_2190 2191 +#define Z_UTIL_INC_2191 2192 +#define Z_UTIL_INC_2192 2193 +#define Z_UTIL_INC_2193 2194 +#define Z_UTIL_INC_2194 2195 +#define Z_UTIL_INC_2195 2196 +#define Z_UTIL_INC_2196 2197 +#define Z_UTIL_INC_2197 2198 +#define Z_UTIL_INC_2198 2199 +#define Z_UTIL_INC_2199 2200 +#define Z_UTIL_INC_2200 2201 +#define Z_UTIL_INC_2201 2202 +#define Z_UTIL_INC_2202 2203 +#define Z_UTIL_INC_2203 2204 +#define Z_UTIL_INC_2204 2205 +#define Z_UTIL_INC_2205 2206 +#define Z_UTIL_INC_2206 2207 +#define Z_UTIL_INC_2207 2208 +#define Z_UTIL_INC_2208 2209 +#define Z_UTIL_INC_2209 2210 +#define Z_UTIL_INC_2210 2211 +#define Z_UTIL_INC_2211 2212 +#define Z_UTIL_INC_2212 2213 +#define Z_UTIL_INC_2213 2214 +#define Z_UTIL_INC_2214 2215 +#define Z_UTIL_INC_2215 2216 +#define Z_UTIL_INC_2216 2217 +#define Z_UTIL_INC_2217 2218 +#define Z_UTIL_INC_2218 2219 +#define Z_UTIL_INC_2219 2220 +#define Z_UTIL_INC_2220 2221 +#define Z_UTIL_INC_2221 2222 +#define Z_UTIL_INC_2222 2223 +#define Z_UTIL_INC_2223 2224 +#define Z_UTIL_INC_2224 2225 +#define Z_UTIL_INC_2225 2226 +#define Z_UTIL_INC_2226 2227 +#define Z_UTIL_INC_2227 2228 +#define Z_UTIL_INC_2228 2229 +#define Z_UTIL_INC_2229 2230 +#define Z_UTIL_INC_2230 2231 +#define Z_UTIL_INC_2231 2232 +#define Z_UTIL_INC_2232 2233 +#define Z_UTIL_INC_2233 2234 +#define Z_UTIL_INC_2234 2235 +#define Z_UTIL_INC_2235 2236 +#define Z_UTIL_INC_2236 2237 +#define Z_UTIL_INC_2237 2238 +#define Z_UTIL_INC_2238 2239 +#define Z_UTIL_INC_2239 2240 +#define Z_UTIL_INC_2240 2241 +#define Z_UTIL_INC_2241 2242 +#define Z_UTIL_INC_2242 2243 +#define Z_UTIL_INC_2243 2244 +#define Z_UTIL_INC_2244 2245 +#define Z_UTIL_INC_2245 2246 +#define Z_UTIL_INC_2246 2247 +#define Z_UTIL_INC_2247 2248 +#define Z_UTIL_INC_2248 2249 +#define Z_UTIL_INC_2249 2250 +#define Z_UTIL_INC_2250 2251 +#define Z_UTIL_INC_2251 2252 +#define Z_UTIL_INC_2252 2253 +#define Z_UTIL_INC_2253 2254 +#define Z_UTIL_INC_2254 2255 +#define Z_UTIL_INC_2255 2256 +#define Z_UTIL_INC_2256 2257 +#define Z_UTIL_INC_2257 2258 +#define Z_UTIL_INC_2258 2259 +#define Z_UTIL_INC_2259 2260 +#define Z_UTIL_INC_2260 2261 +#define Z_UTIL_INC_2261 2262 +#define Z_UTIL_INC_2262 2263 +#define Z_UTIL_INC_2263 2264 +#define Z_UTIL_INC_2264 2265 +#define Z_UTIL_INC_2265 2266 +#define Z_UTIL_INC_2266 2267 +#define Z_UTIL_INC_2267 2268 +#define Z_UTIL_INC_2268 2269 +#define Z_UTIL_INC_2269 2270 +#define Z_UTIL_INC_2270 2271 +#define Z_UTIL_INC_2271 2272 +#define Z_UTIL_INC_2272 2273 +#define Z_UTIL_INC_2273 2274 +#define Z_UTIL_INC_2274 2275 +#define Z_UTIL_INC_2275 2276 +#define Z_UTIL_INC_2276 2277 +#define Z_UTIL_INC_2277 2278 +#define Z_UTIL_INC_2278 2279 +#define Z_UTIL_INC_2279 2280 +#define Z_UTIL_INC_2280 2281 +#define Z_UTIL_INC_2281 2282 +#define Z_UTIL_INC_2282 2283 +#define Z_UTIL_INC_2283 2284 +#define Z_UTIL_INC_2284 2285 +#define Z_UTIL_INC_2285 2286 +#define Z_UTIL_INC_2286 2287 +#define Z_UTIL_INC_2287 2288 +#define Z_UTIL_INC_2288 2289 +#define Z_UTIL_INC_2289 2290 +#define Z_UTIL_INC_2290 2291 +#define Z_UTIL_INC_2291 2292 +#define Z_UTIL_INC_2292 2293 +#define Z_UTIL_INC_2293 2294 +#define Z_UTIL_INC_2294 2295 +#define Z_UTIL_INC_2295 2296 +#define Z_UTIL_INC_2296 2297 +#define Z_UTIL_INC_2297 2298 +#define Z_UTIL_INC_2298 2299 +#define Z_UTIL_INC_2299 2300 +#define Z_UTIL_INC_2300 2301 +#define Z_UTIL_INC_2301 2302 +#define Z_UTIL_INC_2302 2303 +#define Z_UTIL_INC_2303 2304 +#define Z_UTIL_INC_2304 2305 +#define Z_UTIL_INC_2305 2306 +#define Z_UTIL_INC_2306 2307 +#define Z_UTIL_INC_2307 2308 +#define Z_UTIL_INC_2308 2309 +#define Z_UTIL_INC_2309 2310 +#define Z_UTIL_INC_2310 2311 +#define Z_UTIL_INC_2311 2312 +#define Z_UTIL_INC_2312 2313 +#define Z_UTIL_INC_2313 2314 +#define Z_UTIL_INC_2314 2315 +#define Z_UTIL_INC_2315 2316 +#define Z_UTIL_INC_2316 2317 +#define Z_UTIL_INC_2317 2318 +#define Z_UTIL_INC_2318 2319 +#define Z_UTIL_INC_2319 2320 +#define Z_UTIL_INC_2320 2321 +#define Z_UTIL_INC_2321 2322 +#define Z_UTIL_INC_2322 2323 +#define Z_UTIL_INC_2323 2324 +#define Z_UTIL_INC_2324 2325 +#define Z_UTIL_INC_2325 2326 +#define Z_UTIL_INC_2326 2327 +#define Z_UTIL_INC_2327 2328 +#define Z_UTIL_INC_2328 2329 +#define Z_UTIL_INC_2329 2330 +#define Z_UTIL_INC_2330 2331 +#define Z_UTIL_INC_2331 2332 +#define Z_UTIL_INC_2332 2333 +#define Z_UTIL_INC_2333 2334 +#define Z_UTIL_INC_2334 2335 +#define Z_UTIL_INC_2335 2336 +#define Z_UTIL_INC_2336 2337 +#define Z_UTIL_INC_2337 2338 +#define Z_UTIL_INC_2338 2339 +#define Z_UTIL_INC_2339 2340 +#define Z_UTIL_INC_2340 2341 +#define Z_UTIL_INC_2341 2342 +#define Z_UTIL_INC_2342 2343 +#define Z_UTIL_INC_2343 2344 +#define Z_UTIL_INC_2344 2345 +#define Z_UTIL_INC_2345 2346 +#define Z_UTIL_INC_2346 2347 +#define Z_UTIL_INC_2347 2348 +#define Z_UTIL_INC_2348 2349 +#define Z_UTIL_INC_2349 2350 +#define Z_UTIL_INC_2350 2351 +#define Z_UTIL_INC_2351 2352 +#define Z_UTIL_INC_2352 2353 +#define Z_UTIL_INC_2353 2354 +#define Z_UTIL_INC_2354 2355 +#define Z_UTIL_INC_2355 2356 +#define Z_UTIL_INC_2356 2357 +#define Z_UTIL_INC_2357 2358 +#define Z_UTIL_INC_2358 2359 +#define Z_UTIL_INC_2359 2360 +#define Z_UTIL_INC_2360 2361 +#define Z_UTIL_INC_2361 2362 +#define Z_UTIL_INC_2362 2363 +#define Z_UTIL_INC_2363 2364 +#define Z_UTIL_INC_2364 2365 +#define Z_UTIL_INC_2365 2366 +#define Z_UTIL_INC_2366 2367 +#define Z_UTIL_INC_2367 2368 +#define Z_UTIL_INC_2368 2369 +#define Z_UTIL_INC_2369 2370 +#define Z_UTIL_INC_2370 2371 +#define Z_UTIL_INC_2371 2372 +#define Z_UTIL_INC_2372 2373 +#define Z_UTIL_INC_2373 2374 +#define Z_UTIL_INC_2374 2375 +#define Z_UTIL_INC_2375 2376 +#define Z_UTIL_INC_2376 2377 +#define Z_UTIL_INC_2377 2378 +#define Z_UTIL_INC_2378 2379 +#define Z_UTIL_INC_2379 2380 +#define Z_UTIL_INC_2380 2381 +#define Z_UTIL_INC_2381 2382 +#define Z_UTIL_INC_2382 2383 +#define Z_UTIL_INC_2383 2384 +#define Z_UTIL_INC_2384 2385 +#define Z_UTIL_INC_2385 2386 +#define Z_UTIL_INC_2386 2387 +#define Z_UTIL_INC_2387 2388 +#define Z_UTIL_INC_2388 2389 +#define Z_UTIL_INC_2389 2390 +#define Z_UTIL_INC_2390 2391 +#define Z_UTIL_INC_2391 2392 +#define Z_UTIL_INC_2392 2393 +#define Z_UTIL_INC_2393 2394 +#define Z_UTIL_INC_2394 2395 +#define Z_UTIL_INC_2395 2396 +#define Z_UTIL_INC_2396 2397 +#define Z_UTIL_INC_2397 2398 +#define Z_UTIL_INC_2398 2399 +#define Z_UTIL_INC_2399 2400 +#define Z_UTIL_INC_2400 2401 +#define Z_UTIL_INC_2401 2402 +#define Z_UTIL_INC_2402 2403 +#define Z_UTIL_INC_2403 2404 +#define Z_UTIL_INC_2404 2405 +#define Z_UTIL_INC_2405 2406 +#define Z_UTIL_INC_2406 2407 +#define Z_UTIL_INC_2407 2408 +#define Z_UTIL_INC_2408 2409 +#define Z_UTIL_INC_2409 2410 +#define Z_UTIL_INC_2410 2411 +#define Z_UTIL_INC_2411 2412 +#define Z_UTIL_INC_2412 2413 +#define Z_UTIL_INC_2413 2414 +#define Z_UTIL_INC_2414 2415 +#define Z_UTIL_INC_2415 2416 +#define Z_UTIL_INC_2416 2417 +#define Z_UTIL_INC_2417 2418 +#define Z_UTIL_INC_2418 2419 +#define Z_UTIL_INC_2419 2420 +#define Z_UTIL_INC_2420 2421 +#define Z_UTIL_INC_2421 2422 +#define Z_UTIL_INC_2422 2423 +#define Z_UTIL_INC_2423 2424 +#define Z_UTIL_INC_2424 2425 +#define Z_UTIL_INC_2425 2426 +#define Z_UTIL_INC_2426 2427 +#define Z_UTIL_INC_2427 2428 +#define Z_UTIL_INC_2428 2429 +#define Z_UTIL_INC_2429 2430 +#define Z_UTIL_INC_2430 2431 +#define Z_UTIL_INC_2431 2432 +#define Z_UTIL_INC_2432 2433 +#define Z_UTIL_INC_2433 2434 +#define Z_UTIL_INC_2434 2435 +#define Z_UTIL_INC_2435 2436 +#define Z_UTIL_INC_2436 2437 +#define Z_UTIL_INC_2437 2438 +#define Z_UTIL_INC_2438 2439 +#define Z_UTIL_INC_2439 2440 +#define Z_UTIL_INC_2440 2441 +#define Z_UTIL_INC_2441 2442 +#define Z_UTIL_INC_2442 2443 +#define Z_UTIL_INC_2443 2444 +#define Z_UTIL_INC_2444 2445 +#define Z_UTIL_INC_2445 2446 +#define Z_UTIL_INC_2446 2447 +#define Z_UTIL_INC_2447 2448 +#define Z_UTIL_INC_2448 2449 +#define Z_UTIL_INC_2449 2450 +#define Z_UTIL_INC_2450 2451 +#define Z_UTIL_INC_2451 2452 +#define Z_UTIL_INC_2452 2453 +#define Z_UTIL_INC_2453 2454 +#define Z_UTIL_INC_2454 2455 +#define Z_UTIL_INC_2455 2456 +#define Z_UTIL_INC_2456 2457 +#define Z_UTIL_INC_2457 2458 +#define Z_UTIL_INC_2458 2459 +#define Z_UTIL_INC_2459 2460 +#define Z_UTIL_INC_2460 2461 +#define Z_UTIL_INC_2461 2462 +#define Z_UTIL_INC_2462 2463 +#define Z_UTIL_INC_2463 2464 +#define Z_UTIL_INC_2464 2465 +#define Z_UTIL_INC_2465 2466 +#define Z_UTIL_INC_2466 2467 +#define Z_UTIL_INC_2467 2468 +#define Z_UTIL_INC_2468 2469 +#define Z_UTIL_INC_2469 2470 +#define Z_UTIL_INC_2470 2471 +#define Z_UTIL_INC_2471 2472 +#define Z_UTIL_INC_2472 2473 +#define Z_UTIL_INC_2473 2474 +#define Z_UTIL_INC_2474 2475 +#define Z_UTIL_INC_2475 2476 +#define Z_UTIL_INC_2476 2477 +#define Z_UTIL_INC_2477 2478 +#define Z_UTIL_INC_2478 2479 +#define Z_UTIL_INC_2479 2480 +#define Z_UTIL_INC_2480 2481 +#define Z_UTIL_INC_2481 2482 +#define Z_UTIL_INC_2482 2483 +#define Z_UTIL_INC_2483 2484 +#define Z_UTIL_INC_2484 2485 +#define Z_UTIL_INC_2485 2486 +#define Z_UTIL_INC_2486 2487 +#define Z_UTIL_INC_2487 2488 +#define Z_UTIL_INC_2488 2489 +#define Z_UTIL_INC_2489 2490 +#define Z_UTIL_INC_2490 2491 +#define Z_UTIL_INC_2491 2492 +#define Z_UTIL_INC_2492 2493 +#define Z_UTIL_INC_2493 2494 +#define Z_UTIL_INC_2494 2495 +#define Z_UTIL_INC_2495 2496 +#define Z_UTIL_INC_2496 2497 +#define Z_UTIL_INC_2497 2498 +#define Z_UTIL_INC_2498 2499 +#define Z_UTIL_INC_2499 2500 +#define Z_UTIL_INC_2500 2501 +#define Z_UTIL_INC_2501 2502 +#define Z_UTIL_INC_2502 2503 +#define Z_UTIL_INC_2503 2504 +#define Z_UTIL_INC_2504 2505 +#define Z_UTIL_INC_2505 2506 +#define Z_UTIL_INC_2506 2507 +#define Z_UTIL_INC_2507 2508 +#define Z_UTIL_INC_2508 2509 +#define Z_UTIL_INC_2509 2510 +#define Z_UTIL_INC_2510 2511 +#define Z_UTIL_INC_2511 2512 +#define Z_UTIL_INC_2512 2513 +#define Z_UTIL_INC_2513 2514 +#define Z_UTIL_INC_2514 2515 +#define Z_UTIL_INC_2515 2516 +#define Z_UTIL_INC_2516 2517 +#define Z_UTIL_INC_2517 2518 +#define Z_UTIL_INC_2518 2519 +#define Z_UTIL_INC_2519 2520 +#define Z_UTIL_INC_2520 2521 +#define Z_UTIL_INC_2521 2522 +#define Z_UTIL_INC_2522 2523 +#define Z_UTIL_INC_2523 2524 +#define Z_UTIL_INC_2524 2525 +#define Z_UTIL_INC_2525 2526 +#define Z_UTIL_INC_2526 2527 +#define Z_UTIL_INC_2527 2528 +#define Z_UTIL_INC_2528 2529 +#define Z_UTIL_INC_2529 2530 +#define Z_UTIL_INC_2530 2531 +#define Z_UTIL_INC_2531 2532 +#define Z_UTIL_INC_2532 2533 +#define Z_UTIL_INC_2533 2534 +#define Z_UTIL_INC_2534 2535 +#define Z_UTIL_INC_2535 2536 +#define Z_UTIL_INC_2536 2537 +#define Z_UTIL_INC_2537 2538 +#define Z_UTIL_INC_2538 2539 +#define Z_UTIL_INC_2539 2540 +#define Z_UTIL_INC_2540 2541 +#define Z_UTIL_INC_2541 2542 +#define Z_UTIL_INC_2542 2543 +#define Z_UTIL_INC_2543 2544 +#define Z_UTIL_INC_2544 2545 +#define Z_UTIL_INC_2545 2546 +#define Z_UTIL_INC_2546 2547 +#define Z_UTIL_INC_2547 2548 +#define Z_UTIL_INC_2548 2549 +#define Z_UTIL_INC_2549 2550 +#define Z_UTIL_INC_2550 2551 +#define Z_UTIL_INC_2551 2552 +#define Z_UTIL_INC_2552 2553 +#define Z_UTIL_INC_2553 2554 +#define Z_UTIL_INC_2554 2555 +#define Z_UTIL_INC_2555 2556 +#define Z_UTIL_INC_2556 2557 +#define Z_UTIL_INC_2557 2558 +#define Z_UTIL_INC_2558 2559 +#define Z_UTIL_INC_2559 2560 +#define Z_UTIL_INC_2560 2561 +#define Z_UTIL_INC_2561 2562 +#define Z_UTIL_INC_2562 2563 +#define Z_UTIL_INC_2563 2564 +#define Z_UTIL_INC_2564 2565 +#define Z_UTIL_INC_2565 2566 +#define Z_UTIL_INC_2566 2567 +#define Z_UTIL_INC_2567 2568 +#define Z_UTIL_INC_2568 2569 +#define Z_UTIL_INC_2569 2570 +#define Z_UTIL_INC_2570 2571 +#define Z_UTIL_INC_2571 2572 +#define Z_UTIL_INC_2572 2573 +#define Z_UTIL_INC_2573 2574 +#define Z_UTIL_INC_2574 2575 +#define Z_UTIL_INC_2575 2576 +#define Z_UTIL_INC_2576 2577 +#define Z_UTIL_INC_2577 2578 +#define Z_UTIL_INC_2578 2579 +#define Z_UTIL_INC_2579 2580 +#define Z_UTIL_INC_2580 2581 +#define Z_UTIL_INC_2581 2582 +#define Z_UTIL_INC_2582 2583 +#define Z_UTIL_INC_2583 2584 +#define Z_UTIL_INC_2584 2585 +#define Z_UTIL_INC_2585 2586 +#define Z_UTIL_INC_2586 2587 +#define Z_UTIL_INC_2587 2588 +#define Z_UTIL_INC_2588 2589 +#define Z_UTIL_INC_2589 2590 +#define Z_UTIL_INC_2590 2591 +#define Z_UTIL_INC_2591 2592 +#define Z_UTIL_INC_2592 2593 +#define Z_UTIL_INC_2593 2594 +#define Z_UTIL_INC_2594 2595 +#define Z_UTIL_INC_2595 2596 +#define Z_UTIL_INC_2596 2597 +#define Z_UTIL_INC_2597 2598 +#define Z_UTIL_INC_2598 2599 +#define Z_UTIL_INC_2599 2600 +#define Z_UTIL_INC_2600 2601 +#define Z_UTIL_INC_2601 2602 +#define Z_UTIL_INC_2602 2603 +#define Z_UTIL_INC_2603 2604 +#define Z_UTIL_INC_2604 2605 +#define Z_UTIL_INC_2605 2606 +#define Z_UTIL_INC_2606 2607 +#define Z_UTIL_INC_2607 2608 +#define Z_UTIL_INC_2608 2609 +#define Z_UTIL_INC_2609 2610 +#define Z_UTIL_INC_2610 2611 +#define Z_UTIL_INC_2611 2612 +#define Z_UTIL_INC_2612 2613 +#define Z_UTIL_INC_2613 2614 +#define Z_UTIL_INC_2614 2615 +#define Z_UTIL_INC_2615 2616 +#define Z_UTIL_INC_2616 2617 +#define Z_UTIL_INC_2617 2618 +#define Z_UTIL_INC_2618 2619 +#define Z_UTIL_INC_2619 2620 +#define Z_UTIL_INC_2620 2621 +#define Z_UTIL_INC_2621 2622 +#define Z_UTIL_INC_2622 2623 +#define Z_UTIL_INC_2623 2624 +#define Z_UTIL_INC_2624 2625 +#define Z_UTIL_INC_2625 2626 +#define Z_UTIL_INC_2626 2627 +#define Z_UTIL_INC_2627 2628 +#define Z_UTIL_INC_2628 2629 +#define Z_UTIL_INC_2629 2630 +#define Z_UTIL_INC_2630 2631 +#define Z_UTIL_INC_2631 2632 +#define Z_UTIL_INC_2632 2633 +#define Z_UTIL_INC_2633 2634 +#define Z_UTIL_INC_2634 2635 +#define Z_UTIL_INC_2635 2636 +#define Z_UTIL_INC_2636 2637 +#define Z_UTIL_INC_2637 2638 +#define Z_UTIL_INC_2638 2639 +#define Z_UTIL_INC_2639 2640 +#define Z_UTIL_INC_2640 2641 +#define Z_UTIL_INC_2641 2642 +#define Z_UTIL_INC_2642 2643 +#define Z_UTIL_INC_2643 2644 +#define Z_UTIL_INC_2644 2645 +#define Z_UTIL_INC_2645 2646 +#define Z_UTIL_INC_2646 2647 +#define Z_UTIL_INC_2647 2648 +#define Z_UTIL_INC_2648 2649 +#define Z_UTIL_INC_2649 2650 +#define Z_UTIL_INC_2650 2651 +#define Z_UTIL_INC_2651 2652 +#define Z_UTIL_INC_2652 2653 +#define Z_UTIL_INC_2653 2654 +#define Z_UTIL_INC_2654 2655 +#define Z_UTIL_INC_2655 2656 +#define Z_UTIL_INC_2656 2657 +#define Z_UTIL_INC_2657 2658 +#define Z_UTIL_INC_2658 2659 +#define Z_UTIL_INC_2659 2660 +#define Z_UTIL_INC_2660 2661 +#define Z_UTIL_INC_2661 2662 +#define Z_UTIL_INC_2662 2663 +#define Z_UTIL_INC_2663 2664 +#define Z_UTIL_INC_2664 2665 +#define Z_UTIL_INC_2665 2666 +#define Z_UTIL_INC_2666 2667 +#define Z_UTIL_INC_2667 2668 +#define Z_UTIL_INC_2668 2669 +#define Z_UTIL_INC_2669 2670 +#define Z_UTIL_INC_2670 2671 +#define Z_UTIL_INC_2671 2672 +#define Z_UTIL_INC_2672 2673 +#define Z_UTIL_INC_2673 2674 +#define Z_UTIL_INC_2674 2675 +#define Z_UTIL_INC_2675 2676 +#define Z_UTIL_INC_2676 2677 +#define Z_UTIL_INC_2677 2678 +#define Z_UTIL_INC_2678 2679 +#define Z_UTIL_INC_2679 2680 +#define Z_UTIL_INC_2680 2681 +#define Z_UTIL_INC_2681 2682 +#define Z_UTIL_INC_2682 2683 +#define Z_UTIL_INC_2683 2684 +#define Z_UTIL_INC_2684 2685 +#define Z_UTIL_INC_2685 2686 +#define Z_UTIL_INC_2686 2687 +#define Z_UTIL_INC_2687 2688 +#define Z_UTIL_INC_2688 2689 +#define Z_UTIL_INC_2689 2690 +#define Z_UTIL_INC_2690 2691 +#define Z_UTIL_INC_2691 2692 +#define Z_UTIL_INC_2692 2693 +#define Z_UTIL_INC_2693 2694 +#define Z_UTIL_INC_2694 2695 +#define Z_UTIL_INC_2695 2696 +#define Z_UTIL_INC_2696 2697 +#define Z_UTIL_INC_2697 2698 +#define Z_UTIL_INC_2698 2699 +#define Z_UTIL_INC_2699 2700 +#define Z_UTIL_INC_2700 2701 +#define Z_UTIL_INC_2701 2702 +#define Z_UTIL_INC_2702 2703 +#define Z_UTIL_INC_2703 2704 +#define Z_UTIL_INC_2704 2705 +#define Z_UTIL_INC_2705 2706 +#define Z_UTIL_INC_2706 2707 +#define Z_UTIL_INC_2707 2708 +#define Z_UTIL_INC_2708 2709 +#define Z_UTIL_INC_2709 2710 +#define Z_UTIL_INC_2710 2711 +#define Z_UTIL_INC_2711 2712 +#define Z_UTIL_INC_2712 2713 +#define Z_UTIL_INC_2713 2714 +#define Z_UTIL_INC_2714 2715 +#define Z_UTIL_INC_2715 2716 +#define Z_UTIL_INC_2716 2717 +#define Z_UTIL_INC_2717 2718 +#define Z_UTIL_INC_2718 2719 +#define Z_UTIL_INC_2719 2720 +#define Z_UTIL_INC_2720 2721 +#define Z_UTIL_INC_2721 2722 +#define Z_UTIL_INC_2722 2723 +#define Z_UTIL_INC_2723 2724 +#define Z_UTIL_INC_2724 2725 +#define Z_UTIL_INC_2725 2726 +#define Z_UTIL_INC_2726 2727 +#define Z_UTIL_INC_2727 2728 +#define Z_UTIL_INC_2728 2729 +#define Z_UTIL_INC_2729 2730 +#define Z_UTIL_INC_2730 2731 +#define Z_UTIL_INC_2731 2732 +#define Z_UTIL_INC_2732 2733 +#define Z_UTIL_INC_2733 2734 +#define Z_UTIL_INC_2734 2735 +#define Z_UTIL_INC_2735 2736 +#define Z_UTIL_INC_2736 2737 +#define Z_UTIL_INC_2737 2738 +#define Z_UTIL_INC_2738 2739 +#define Z_UTIL_INC_2739 2740 +#define Z_UTIL_INC_2740 2741 +#define Z_UTIL_INC_2741 2742 +#define Z_UTIL_INC_2742 2743 +#define Z_UTIL_INC_2743 2744 +#define Z_UTIL_INC_2744 2745 +#define Z_UTIL_INC_2745 2746 +#define Z_UTIL_INC_2746 2747 +#define Z_UTIL_INC_2747 2748 +#define Z_UTIL_INC_2748 2749 +#define Z_UTIL_INC_2749 2750 +#define Z_UTIL_INC_2750 2751 +#define Z_UTIL_INC_2751 2752 +#define Z_UTIL_INC_2752 2753 +#define Z_UTIL_INC_2753 2754 +#define Z_UTIL_INC_2754 2755 +#define Z_UTIL_INC_2755 2756 +#define Z_UTIL_INC_2756 2757 +#define Z_UTIL_INC_2757 2758 +#define Z_UTIL_INC_2758 2759 +#define Z_UTIL_INC_2759 2760 +#define Z_UTIL_INC_2760 2761 +#define Z_UTIL_INC_2761 2762 +#define Z_UTIL_INC_2762 2763 +#define Z_UTIL_INC_2763 2764 +#define Z_UTIL_INC_2764 2765 +#define Z_UTIL_INC_2765 2766 +#define Z_UTIL_INC_2766 2767 +#define Z_UTIL_INC_2767 2768 +#define Z_UTIL_INC_2768 2769 +#define Z_UTIL_INC_2769 2770 +#define Z_UTIL_INC_2770 2771 +#define Z_UTIL_INC_2771 2772 +#define Z_UTIL_INC_2772 2773 +#define Z_UTIL_INC_2773 2774 +#define Z_UTIL_INC_2774 2775 +#define Z_UTIL_INC_2775 2776 +#define Z_UTIL_INC_2776 2777 +#define Z_UTIL_INC_2777 2778 +#define Z_UTIL_INC_2778 2779 +#define Z_UTIL_INC_2779 2780 +#define Z_UTIL_INC_2780 2781 +#define Z_UTIL_INC_2781 2782 +#define Z_UTIL_INC_2782 2783 +#define Z_UTIL_INC_2783 2784 +#define Z_UTIL_INC_2784 2785 +#define Z_UTIL_INC_2785 2786 +#define Z_UTIL_INC_2786 2787 +#define Z_UTIL_INC_2787 2788 +#define Z_UTIL_INC_2788 2789 +#define Z_UTIL_INC_2789 2790 +#define Z_UTIL_INC_2790 2791 +#define Z_UTIL_INC_2791 2792 +#define Z_UTIL_INC_2792 2793 +#define Z_UTIL_INC_2793 2794 +#define Z_UTIL_INC_2794 2795 +#define Z_UTIL_INC_2795 2796 +#define Z_UTIL_INC_2796 2797 +#define Z_UTIL_INC_2797 2798 +#define Z_UTIL_INC_2798 2799 +#define Z_UTIL_INC_2799 2800 +#define Z_UTIL_INC_2800 2801 +#define Z_UTIL_INC_2801 2802 +#define Z_UTIL_INC_2802 2803 +#define Z_UTIL_INC_2803 2804 +#define Z_UTIL_INC_2804 2805 +#define Z_UTIL_INC_2805 2806 +#define Z_UTIL_INC_2806 2807 +#define Z_UTIL_INC_2807 2808 +#define Z_UTIL_INC_2808 2809 +#define Z_UTIL_INC_2809 2810 +#define Z_UTIL_INC_2810 2811 +#define Z_UTIL_INC_2811 2812 +#define Z_UTIL_INC_2812 2813 +#define Z_UTIL_INC_2813 2814 +#define Z_UTIL_INC_2814 2815 +#define Z_UTIL_INC_2815 2816 +#define Z_UTIL_INC_2816 2817 +#define Z_UTIL_INC_2817 2818 +#define Z_UTIL_INC_2818 2819 +#define Z_UTIL_INC_2819 2820 +#define Z_UTIL_INC_2820 2821 +#define Z_UTIL_INC_2821 2822 +#define Z_UTIL_INC_2822 2823 +#define Z_UTIL_INC_2823 2824 +#define Z_UTIL_INC_2824 2825 +#define Z_UTIL_INC_2825 2826 +#define Z_UTIL_INC_2826 2827 +#define Z_UTIL_INC_2827 2828 +#define Z_UTIL_INC_2828 2829 +#define Z_UTIL_INC_2829 2830 +#define Z_UTIL_INC_2830 2831 +#define Z_UTIL_INC_2831 2832 +#define Z_UTIL_INC_2832 2833 +#define Z_UTIL_INC_2833 2834 +#define Z_UTIL_INC_2834 2835 +#define Z_UTIL_INC_2835 2836 +#define Z_UTIL_INC_2836 2837 +#define Z_UTIL_INC_2837 2838 +#define Z_UTIL_INC_2838 2839 +#define Z_UTIL_INC_2839 2840 +#define Z_UTIL_INC_2840 2841 +#define Z_UTIL_INC_2841 2842 +#define Z_UTIL_INC_2842 2843 +#define Z_UTIL_INC_2843 2844 +#define Z_UTIL_INC_2844 2845 +#define Z_UTIL_INC_2845 2846 +#define Z_UTIL_INC_2846 2847 +#define Z_UTIL_INC_2847 2848 +#define Z_UTIL_INC_2848 2849 +#define Z_UTIL_INC_2849 2850 +#define Z_UTIL_INC_2850 2851 +#define Z_UTIL_INC_2851 2852 +#define Z_UTIL_INC_2852 2853 +#define Z_UTIL_INC_2853 2854 +#define Z_UTIL_INC_2854 2855 +#define Z_UTIL_INC_2855 2856 +#define Z_UTIL_INC_2856 2857 +#define Z_UTIL_INC_2857 2858 +#define Z_UTIL_INC_2858 2859 +#define Z_UTIL_INC_2859 2860 +#define Z_UTIL_INC_2860 2861 +#define Z_UTIL_INC_2861 2862 +#define Z_UTIL_INC_2862 2863 +#define Z_UTIL_INC_2863 2864 +#define Z_UTIL_INC_2864 2865 +#define Z_UTIL_INC_2865 2866 +#define Z_UTIL_INC_2866 2867 +#define Z_UTIL_INC_2867 2868 +#define Z_UTIL_INC_2868 2869 +#define Z_UTIL_INC_2869 2870 +#define Z_UTIL_INC_2870 2871 +#define Z_UTIL_INC_2871 2872 +#define Z_UTIL_INC_2872 2873 +#define Z_UTIL_INC_2873 2874 +#define Z_UTIL_INC_2874 2875 +#define Z_UTIL_INC_2875 2876 +#define Z_UTIL_INC_2876 2877 +#define Z_UTIL_INC_2877 2878 +#define Z_UTIL_INC_2878 2879 +#define Z_UTIL_INC_2879 2880 +#define Z_UTIL_INC_2880 2881 +#define Z_UTIL_INC_2881 2882 +#define Z_UTIL_INC_2882 2883 +#define Z_UTIL_INC_2883 2884 +#define Z_UTIL_INC_2884 2885 +#define Z_UTIL_INC_2885 2886 +#define Z_UTIL_INC_2886 2887 +#define Z_UTIL_INC_2887 2888 +#define Z_UTIL_INC_2888 2889 +#define Z_UTIL_INC_2889 2890 +#define Z_UTIL_INC_2890 2891 +#define Z_UTIL_INC_2891 2892 +#define Z_UTIL_INC_2892 2893 +#define Z_UTIL_INC_2893 2894 +#define Z_UTIL_INC_2894 2895 +#define Z_UTIL_INC_2895 2896 +#define Z_UTIL_INC_2896 2897 +#define Z_UTIL_INC_2897 2898 +#define Z_UTIL_INC_2898 2899 +#define Z_UTIL_INC_2899 2900 +#define Z_UTIL_INC_2900 2901 +#define Z_UTIL_INC_2901 2902 +#define Z_UTIL_INC_2902 2903 +#define Z_UTIL_INC_2903 2904 +#define Z_UTIL_INC_2904 2905 +#define Z_UTIL_INC_2905 2906 +#define Z_UTIL_INC_2906 2907 +#define Z_UTIL_INC_2907 2908 +#define Z_UTIL_INC_2908 2909 +#define Z_UTIL_INC_2909 2910 +#define Z_UTIL_INC_2910 2911 +#define Z_UTIL_INC_2911 2912 +#define Z_UTIL_INC_2912 2913 +#define Z_UTIL_INC_2913 2914 +#define Z_UTIL_INC_2914 2915 +#define Z_UTIL_INC_2915 2916 +#define Z_UTIL_INC_2916 2917 +#define Z_UTIL_INC_2917 2918 +#define Z_UTIL_INC_2918 2919 +#define Z_UTIL_INC_2919 2920 +#define Z_UTIL_INC_2920 2921 +#define Z_UTIL_INC_2921 2922 +#define Z_UTIL_INC_2922 2923 +#define Z_UTIL_INC_2923 2924 +#define Z_UTIL_INC_2924 2925 +#define Z_UTIL_INC_2925 2926 +#define Z_UTIL_INC_2926 2927 +#define Z_UTIL_INC_2927 2928 +#define Z_UTIL_INC_2928 2929 +#define Z_UTIL_INC_2929 2930 +#define Z_UTIL_INC_2930 2931 +#define Z_UTIL_INC_2931 2932 +#define Z_UTIL_INC_2932 2933 +#define Z_UTIL_INC_2933 2934 +#define Z_UTIL_INC_2934 2935 +#define Z_UTIL_INC_2935 2936 +#define Z_UTIL_INC_2936 2937 +#define Z_UTIL_INC_2937 2938 +#define Z_UTIL_INC_2938 2939 +#define Z_UTIL_INC_2939 2940 +#define Z_UTIL_INC_2940 2941 +#define Z_UTIL_INC_2941 2942 +#define Z_UTIL_INC_2942 2943 +#define Z_UTIL_INC_2943 2944 +#define Z_UTIL_INC_2944 2945 +#define Z_UTIL_INC_2945 2946 +#define Z_UTIL_INC_2946 2947 +#define Z_UTIL_INC_2947 2948 +#define Z_UTIL_INC_2948 2949 +#define Z_UTIL_INC_2949 2950 +#define Z_UTIL_INC_2950 2951 +#define Z_UTIL_INC_2951 2952 +#define Z_UTIL_INC_2952 2953 +#define Z_UTIL_INC_2953 2954 +#define Z_UTIL_INC_2954 2955 +#define Z_UTIL_INC_2955 2956 +#define Z_UTIL_INC_2956 2957 +#define Z_UTIL_INC_2957 2958 +#define Z_UTIL_INC_2958 2959 +#define Z_UTIL_INC_2959 2960 +#define Z_UTIL_INC_2960 2961 +#define Z_UTIL_INC_2961 2962 +#define Z_UTIL_INC_2962 2963 +#define Z_UTIL_INC_2963 2964 +#define Z_UTIL_INC_2964 2965 +#define Z_UTIL_INC_2965 2966 +#define Z_UTIL_INC_2966 2967 +#define Z_UTIL_INC_2967 2968 +#define Z_UTIL_INC_2968 2969 +#define Z_UTIL_INC_2969 2970 +#define Z_UTIL_INC_2970 2971 +#define Z_UTIL_INC_2971 2972 +#define Z_UTIL_INC_2972 2973 +#define Z_UTIL_INC_2973 2974 +#define Z_UTIL_INC_2974 2975 +#define Z_UTIL_INC_2975 2976 +#define Z_UTIL_INC_2976 2977 +#define Z_UTIL_INC_2977 2978 +#define Z_UTIL_INC_2978 2979 +#define Z_UTIL_INC_2979 2980 +#define Z_UTIL_INC_2980 2981 +#define Z_UTIL_INC_2981 2982 +#define Z_UTIL_INC_2982 2983 +#define Z_UTIL_INC_2983 2984 +#define Z_UTIL_INC_2984 2985 +#define Z_UTIL_INC_2985 2986 +#define Z_UTIL_INC_2986 2987 +#define Z_UTIL_INC_2987 2988 +#define Z_UTIL_INC_2988 2989 +#define Z_UTIL_INC_2989 2990 +#define Z_UTIL_INC_2990 2991 +#define Z_UTIL_INC_2991 2992 +#define Z_UTIL_INC_2992 2993 +#define Z_UTIL_INC_2993 2994 +#define Z_UTIL_INC_2994 2995 +#define Z_UTIL_INC_2995 2996 +#define Z_UTIL_INC_2996 2997 +#define Z_UTIL_INC_2997 2998 +#define Z_UTIL_INC_2998 2999 +#define Z_UTIL_INC_2999 3000 +#define Z_UTIL_INC_3000 3001 +#define Z_UTIL_INC_3001 3002 +#define Z_UTIL_INC_3002 3003 +#define Z_UTIL_INC_3003 3004 +#define Z_UTIL_INC_3004 3005 +#define Z_UTIL_INC_3005 3006 +#define Z_UTIL_INC_3006 3007 +#define Z_UTIL_INC_3007 3008 +#define Z_UTIL_INC_3008 3009 +#define Z_UTIL_INC_3009 3010 +#define Z_UTIL_INC_3010 3011 +#define Z_UTIL_INC_3011 3012 +#define Z_UTIL_INC_3012 3013 +#define Z_UTIL_INC_3013 3014 +#define Z_UTIL_INC_3014 3015 +#define Z_UTIL_INC_3015 3016 +#define Z_UTIL_INC_3016 3017 +#define Z_UTIL_INC_3017 3018 +#define Z_UTIL_INC_3018 3019 +#define Z_UTIL_INC_3019 3020 +#define Z_UTIL_INC_3020 3021 +#define Z_UTIL_INC_3021 3022 +#define Z_UTIL_INC_3022 3023 +#define Z_UTIL_INC_3023 3024 +#define Z_UTIL_INC_3024 3025 +#define Z_UTIL_INC_3025 3026 +#define Z_UTIL_INC_3026 3027 +#define Z_UTIL_INC_3027 3028 +#define Z_UTIL_INC_3028 3029 +#define Z_UTIL_INC_3029 3030 +#define Z_UTIL_INC_3030 3031 +#define Z_UTIL_INC_3031 3032 +#define Z_UTIL_INC_3032 3033 +#define Z_UTIL_INC_3033 3034 +#define Z_UTIL_INC_3034 3035 +#define Z_UTIL_INC_3035 3036 +#define Z_UTIL_INC_3036 3037 +#define Z_UTIL_INC_3037 3038 +#define Z_UTIL_INC_3038 3039 +#define Z_UTIL_INC_3039 3040 +#define Z_UTIL_INC_3040 3041 +#define Z_UTIL_INC_3041 3042 +#define Z_UTIL_INC_3042 3043 +#define Z_UTIL_INC_3043 3044 +#define Z_UTIL_INC_3044 3045 +#define Z_UTIL_INC_3045 3046 +#define Z_UTIL_INC_3046 3047 +#define Z_UTIL_INC_3047 3048 +#define Z_UTIL_INC_3048 3049 +#define Z_UTIL_INC_3049 3050 +#define Z_UTIL_INC_3050 3051 +#define Z_UTIL_INC_3051 3052 +#define Z_UTIL_INC_3052 3053 +#define Z_UTIL_INC_3053 3054 +#define Z_UTIL_INC_3054 3055 +#define Z_UTIL_INC_3055 3056 +#define Z_UTIL_INC_3056 3057 +#define Z_UTIL_INC_3057 3058 +#define Z_UTIL_INC_3058 3059 +#define Z_UTIL_INC_3059 3060 +#define Z_UTIL_INC_3060 3061 +#define Z_UTIL_INC_3061 3062 +#define Z_UTIL_INC_3062 3063 +#define Z_UTIL_INC_3063 3064 +#define Z_UTIL_INC_3064 3065 +#define Z_UTIL_INC_3065 3066 +#define Z_UTIL_INC_3066 3067 +#define Z_UTIL_INC_3067 3068 +#define Z_UTIL_INC_3068 3069 +#define Z_UTIL_INC_3069 3070 +#define Z_UTIL_INC_3070 3071 +#define Z_UTIL_INC_3071 3072 +#define Z_UTIL_INC_3072 3073 +#define Z_UTIL_INC_3073 3074 +#define Z_UTIL_INC_3074 3075 +#define Z_UTIL_INC_3075 3076 +#define Z_UTIL_INC_3076 3077 +#define Z_UTIL_INC_3077 3078 +#define Z_UTIL_INC_3078 3079 +#define Z_UTIL_INC_3079 3080 +#define Z_UTIL_INC_3080 3081 +#define Z_UTIL_INC_3081 3082 +#define Z_UTIL_INC_3082 3083 +#define Z_UTIL_INC_3083 3084 +#define Z_UTIL_INC_3084 3085 +#define Z_UTIL_INC_3085 3086 +#define Z_UTIL_INC_3086 3087 +#define Z_UTIL_INC_3087 3088 +#define Z_UTIL_INC_3088 3089 +#define Z_UTIL_INC_3089 3090 +#define Z_UTIL_INC_3090 3091 +#define Z_UTIL_INC_3091 3092 +#define Z_UTIL_INC_3092 3093 +#define Z_UTIL_INC_3093 3094 +#define Z_UTIL_INC_3094 3095 +#define Z_UTIL_INC_3095 3096 +#define Z_UTIL_INC_3096 3097 +#define Z_UTIL_INC_3097 3098 +#define Z_UTIL_INC_3098 3099 +#define Z_UTIL_INC_3099 3100 +#define Z_UTIL_INC_3100 3101 +#define Z_UTIL_INC_3101 3102 +#define Z_UTIL_INC_3102 3103 +#define Z_UTIL_INC_3103 3104 +#define Z_UTIL_INC_3104 3105 +#define Z_UTIL_INC_3105 3106 +#define Z_UTIL_INC_3106 3107 +#define Z_UTIL_INC_3107 3108 +#define Z_UTIL_INC_3108 3109 +#define Z_UTIL_INC_3109 3110 +#define Z_UTIL_INC_3110 3111 +#define Z_UTIL_INC_3111 3112 +#define Z_UTIL_INC_3112 3113 +#define Z_UTIL_INC_3113 3114 +#define Z_UTIL_INC_3114 3115 +#define Z_UTIL_INC_3115 3116 +#define Z_UTIL_INC_3116 3117 +#define Z_UTIL_INC_3117 3118 +#define Z_UTIL_INC_3118 3119 +#define Z_UTIL_INC_3119 3120 +#define Z_UTIL_INC_3120 3121 +#define Z_UTIL_INC_3121 3122 +#define Z_UTIL_INC_3122 3123 +#define Z_UTIL_INC_3123 3124 +#define Z_UTIL_INC_3124 3125 +#define Z_UTIL_INC_3125 3126 +#define Z_UTIL_INC_3126 3127 +#define Z_UTIL_INC_3127 3128 +#define Z_UTIL_INC_3128 3129 +#define Z_UTIL_INC_3129 3130 +#define Z_UTIL_INC_3130 3131 +#define Z_UTIL_INC_3131 3132 +#define Z_UTIL_INC_3132 3133 +#define Z_UTIL_INC_3133 3134 +#define Z_UTIL_INC_3134 3135 +#define Z_UTIL_INC_3135 3136 +#define Z_UTIL_INC_3136 3137 +#define Z_UTIL_INC_3137 3138 +#define Z_UTIL_INC_3138 3139 +#define Z_UTIL_INC_3139 3140 +#define Z_UTIL_INC_3140 3141 +#define Z_UTIL_INC_3141 3142 +#define Z_UTIL_INC_3142 3143 +#define Z_UTIL_INC_3143 3144 +#define Z_UTIL_INC_3144 3145 +#define Z_UTIL_INC_3145 3146 +#define Z_UTIL_INC_3146 3147 +#define Z_UTIL_INC_3147 3148 +#define Z_UTIL_INC_3148 3149 +#define Z_UTIL_INC_3149 3150 +#define Z_UTIL_INC_3150 3151 +#define Z_UTIL_INC_3151 3152 +#define Z_UTIL_INC_3152 3153 +#define Z_UTIL_INC_3153 3154 +#define Z_UTIL_INC_3154 3155 +#define Z_UTIL_INC_3155 3156 +#define Z_UTIL_INC_3156 3157 +#define Z_UTIL_INC_3157 3158 +#define Z_UTIL_INC_3158 3159 +#define Z_UTIL_INC_3159 3160 +#define Z_UTIL_INC_3160 3161 +#define Z_UTIL_INC_3161 3162 +#define Z_UTIL_INC_3162 3163 +#define Z_UTIL_INC_3163 3164 +#define Z_UTIL_INC_3164 3165 +#define Z_UTIL_INC_3165 3166 +#define Z_UTIL_INC_3166 3167 +#define Z_UTIL_INC_3167 3168 +#define Z_UTIL_INC_3168 3169 +#define Z_UTIL_INC_3169 3170 +#define Z_UTIL_INC_3170 3171 +#define Z_UTIL_INC_3171 3172 +#define Z_UTIL_INC_3172 3173 +#define Z_UTIL_INC_3173 3174 +#define Z_UTIL_INC_3174 3175 +#define Z_UTIL_INC_3175 3176 +#define Z_UTIL_INC_3176 3177 +#define Z_UTIL_INC_3177 3178 +#define Z_UTIL_INC_3178 3179 +#define Z_UTIL_INC_3179 3180 +#define Z_UTIL_INC_3180 3181 +#define Z_UTIL_INC_3181 3182 +#define Z_UTIL_INC_3182 3183 +#define Z_UTIL_INC_3183 3184 +#define Z_UTIL_INC_3184 3185 +#define Z_UTIL_INC_3185 3186 +#define Z_UTIL_INC_3186 3187 +#define Z_UTIL_INC_3187 3188 +#define Z_UTIL_INC_3188 3189 +#define Z_UTIL_INC_3189 3190 +#define Z_UTIL_INC_3190 3191 +#define Z_UTIL_INC_3191 3192 +#define Z_UTIL_INC_3192 3193 +#define Z_UTIL_INC_3193 3194 +#define Z_UTIL_INC_3194 3195 +#define Z_UTIL_INC_3195 3196 +#define Z_UTIL_INC_3196 3197 +#define Z_UTIL_INC_3197 3198 +#define Z_UTIL_INC_3198 3199 +#define Z_UTIL_INC_3199 3200 +#define Z_UTIL_INC_3200 3201 +#define Z_UTIL_INC_3201 3202 +#define Z_UTIL_INC_3202 3203 +#define Z_UTIL_INC_3203 3204 +#define Z_UTIL_INC_3204 3205 +#define Z_UTIL_INC_3205 3206 +#define Z_UTIL_INC_3206 3207 +#define Z_UTIL_INC_3207 3208 +#define Z_UTIL_INC_3208 3209 +#define Z_UTIL_INC_3209 3210 +#define Z_UTIL_INC_3210 3211 +#define Z_UTIL_INC_3211 3212 +#define Z_UTIL_INC_3212 3213 +#define Z_UTIL_INC_3213 3214 +#define Z_UTIL_INC_3214 3215 +#define Z_UTIL_INC_3215 3216 +#define Z_UTIL_INC_3216 3217 +#define Z_UTIL_INC_3217 3218 +#define Z_UTIL_INC_3218 3219 +#define Z_UTIL_INC_3219 3220 +#define Z_UTIL_INC_3220 3221 +#define Z_UTIL_INC_3221 3222 +#define Z_UTIL_INC_3222 3223 +#define Z_UTIL_INC_3223 3224 +#define Z_UTIL_INC_3224 3225 +#define Z_UTIL_INC_3225 3226 +#define Z_UTIL_INC_3226 3227 +#define Z_UTIL_INC_3227 3228 +#define Z_UTIL_INC_3228 3229 +#define Z_UTIL_INC_3229 3230 +#define Z_UTIL_INC_3230 3231 +#define Z_UTIL_INC_3231 3232 +#define Z_UTIL_INC_3232 3233 +#define Z_UTIL_INC_3233 3234 +#define Z_UTIL_INC_3234 3235 +#define Z_UTIL_INC_3235 3236 +#define Z_UTIL_INC_3236 3237 +#define Z_UTIL_INC_3237 3238 +#define Z_UTIL_INC_3238 3239 +#define Z_UTIL_INC_3239 3240 +#define Z_UTIL_INC_3240 3241 +#define Z_UTIL_INC_3241 3242 +#define Z_UTIL_INC_3242 3243 +#define Z_UTIL_INC_3243 3244 +#define Z_UTIL_INC_3244 3245 +#define Z_UTIL_INC_3245 3246 +#define Z_UTIL_INC_3246 3247 +#define Z_UTIL_INC_3247 3248 +#define Z_UTIL_INC_3248 3249 +#define Z_UTIL_INC_3249 3250 +#define Z_UTIL_INC_3250 3251 +#define Z_UTIL_INC_3251 3252 +#define Z_UTIL_INC_3252 3253 +#define Z_UTIL_INC_3253 3254 +#define Z_UTIL_INC_3254 3255 +#define Z_UTIL_INC_3255 3256 +#define Z_UTIL_INC_3256 3257 +#define Z_UTIL_INC_3257 3258 +#define Z_UTIL_INC_3258 3259 +#define Z_UTIL_INC_3259 3260 +#define Z_UTIL_INC_3260 3261 +#define Z_UTIL_INC_3261 3262 +#define Z_UTIL_INC_3262 3263 +#define Z_UTIL_INC_3263 3264 +#define Z_UTIL_INC_3264 3265 +#define Z_UTIL_INC_3265 3266 +#define Z_UTIL_INC_3266 3267 +#define Z_UTIL_INC_3267 3268 +#define Z_UTIL_INC_3268 3269 +#define Z_UTIL_INC_3269 3270 +#define Z_UTIL_INC_3270 3271 +#define Z_UTIL_INC_3271 3272 +#define Z_UTIL_INC_3272 3273 +#define Z_UTIL_INC_3273 3274 +#define Z_UTIL_INC_3274 3275 +#define Z_UTIL_INC_3275 3276 +#define Z_UTIL_INC_3276 3277 +#define Z_UTIL_INC_3277 3278 +#define Z_UTIL_INC_3278 3279 +#define Z_UTIL_INC_3279 3280 +#define Z_UTIL_INC_3280 3281 +#define Z_UTIL_INC_3281 3282 +#define Z_UTIL_INC_3282 3283 +#define Z_UTIL_INC_3283 3284 +#define Z_UTIL_INC_3284 3285 +#define Z_UTIL_INC_3285 3286 +#define Z_UTIL_INC_3286 3287 +#define Z_UTIL_INC_3287 3288 +#define Z_UTIL_INC_3288 3289 +#define Z_UTIL_INC_3289 3290 +#define Z_UTIL_INC_3290 3291 +#define Z_UTIL_INC_3291 3292 +#define Z_UTIL_INC_3292 3293 +#define Z_UTIL_INC_3293 3294 +#define Z_UTIL_INC_3294 3295 +#define Z_UTIL_INC_3295 3296 +#define Z_UTIL_INC_3296 3297 +#define Z_UTIL_INC_3297 3298 +#define Z_UTIL_INC_3298 3299 +#define Z_UTIL_INC_3299 3300 +#define Z_UTIL_INC_3300 3301 +#define Z_UTIL_INC_3301 3302 +#define Z_UTIL_INC_3302 3303 +#define Z_UTIL_INC_3303 3304 +#define Z_UTIL_INC_3304 3305 +#define Z_UTIL_INC_3305 3306 +#define Z_UTIL_INC_3306 3307 +#define Z_UTIL_INC_3307 3308 +#define Z_UTIL_INC_3308 3309 +#define Z_UTIL_INC_3309 3310 +#define Z_UTIL_INC_3310 3311 +#define Z_UTIL_INC_3311 3312 +#define Z_UTIL_INC_3312 3313 +#define Z_UTIL_INC_3313 3314 +#define Z_UTIL_INC_3314 3315 +#define Z_UTIL_INC_3315 3316 +#define Z_UTIL_INC_3316 3317 +#define Z_UTIL_INC_3317 3318 +#define Z_UTIL_INC_3318 3319 +#define Z_UTIL_INC_3319 3320 +#define Z_UTIL_INC_3320 3321 +#define Z_UTIL_INC_3321 3322 +#define Z_UTIL_INC_3322 3323 +#define Z_UTIL_INC_3323 3324 +#define Z_UTIL_INC_3324 3325 +#define Z_UTIL_INC_3325 3326 +#define Z_UTIL_INC_3326 3327 +#define Z_UTIL_INC_3327 3328 +#define Z_UTIL_INC_3328 3329 +#define Z_UTIL_INC_3329 3330 +#define Z_UTIL_INC_3330 3331 +#define Z_UTIL_INC_3331 3332 +#define Z_UTIL_INC_3332 3333 +#define Z_UTIL_INC_3333 3334 +#define Z_UTIL_INC_3334 3335 +#define Z_UTIL_INC_3335 3336 +#define Z_UTIL_INC_3336 3337 +#define Z_UTIL_INC_3337 3338 +#define Z_UTIL_INC_3338 3339 +#define Z_UTIL_INC_3339 3340 +#define Z_UTIL_INC_3340 3341 +#define Z_UTIL_INC_3341 3342 +#define Z_UTIL_INC_3342 3343 +#define Z_UTIL_INC_3343 3344 +#define Z_UTIL_INC_3344 3345 +#define Z_UTIL_INC_3345 3346 +#define Z_UTIL_INC_3346 3347 +#define Z_UTIL_INC_3347 3348 +#define Z_UTIL_INC_3348 3349 +#define Z_UTIL_INC_3349 3350 +#define Z_UTIL_INC_3350 3351 +#define Z_UTIL_INC_3351 3352 +#define Z_UTIL_INC_3352 3353 +#define Z_UTIL_INC_3353 3354 +#define Z_UTIL_INC_3354 3355 +#define Z_UTIL_INC_3355 3356 +#define Z_UTIL_INC_3356 3357 +#define Z_UTIL_INC_3357 3358 +#define Z_UTIL_INC_3358 3359 +#define Z_UTIL_INC_3359 3360 +#define Z_UTIL_INC_3360 3361 +#define Z_UTIL_INC_3361 3362 +#define Z_UTIL_INC_3362 3363 +#define Z_UTIL_INC_3363 3364 +#define Z_UTIL_INC_3364 3365 +#define Z_UTIL_INC_3365 3366 +#define Z_UTIL_INC_3366 3367 +#define Z_UTIL_INC_3367 3368 +#define Z_UTIL_INC_3368 3369 +#define Z_UTIL_INC_3369 3370 +#define Z_UTIL_INC_3370 3371 +#define Z_UTIL_INC_3371 3372 +#define Z_UTIL_INC_3372 3373 +#define Z_UTIL_INC_3373 3374 +#define Z_UTIL_INC_3374 3375 +#define Z_UTIL_INC_3375 3376 +#define Z_UTIL_INC_3376 3377 +#define Z_UTIL_INC_3377 3378 +#define Z_UTIL_INC_3378 3379 +#define Z_UTIL_INC_3379 3380 +#define Z_UTIL_INC_3380 3381 +#define Z_UTIL_INC_3381 3382 +#define Z_UTIL_INC_3382 3383 +#define Z_UTIL_INC_3383 3384 +#define Z_UTIL_INC_3384 3385 +#define Z_UTIL_INC_3385 3386 +#define Z_UTIL_INC_3386 3387 +#define Z_UTIL_INC_3387 3388 +#define Z_UTIL_INC_3388 3389 +#define Z_UTIL_INC_3389 3390 +#define Z_UTIL_INC_3390 3391 +#define Z_UTIL_INC_3391 3392 +#define Z_UTIL_INC_3392 3393 +#define Z_UTIL_INC_3393 3394 +#define Z_UTIL_INC_3394 3395 +#define Z_UTIL_INC_3395 3396 +#define Z_UTIL_INC_3396 3397 +#define Z_UTIL_INC_3397 3398 +#define Z_UTIL_INC_3398 3399 +#define Z_UTIL_INC_3399 3400 +#define Z_UTIL_INC_3400 3401 +#define Z_UTIL_INC_3401 3402 +#define Z_UTIL_INC_3402 3403 +#define Z_UTIL_INC_3403 3404 +#define Z_UTIL_INC_3404 3405 +#define Z_UTIL_INC_3405 3406 +#define Z_UTIL_INC_3406 3407 +#define Z_UTIL_INC_3407 3408 +#define Z_UTIL_INC_3408 3409 +#define Z_UTIL_INC_3409 3410 +#define Z_UTIL_INC_3410 3411 +#define Z_UTIL_INC_3411 3412 +#define Z_UTIL_INC_3412 3413 +#define Z_UTIL_INC_3413 3414 +#define Z_UTIL_INC_3414 3415 +#define Z_UTIL_INC_3415 3416 +#define Z_UTIL_INC_3416 3417 +#define Z_UTIL_INC_3417 3418 +#define Z_UTIL_INC_3418 3419 +#define Z_UTIL_INC_3419 3420 +#define Z_UTIL_INC_3420 3421 +#define Z_UTIL_INC_3421 3422 +#define Z_UTIL_INC_3422 3423 +#define Z_UTIL_INC_3423 3424 +#define Z_UTIL_INC_3424 3425 +#define Z_UTIL_INC_3425 3426 +#define Z_UTIL_INC_3426 3427 +#define Z_UTIL_INC_3427 3428 +#define Z_UTIL_INC_3428 3429 +#define Z_UTIL_INC_3429 3430 +#define Z_UTIL_INC_3430 3431 +#define Z_UTIL_INC_3431 3432 +#define Z_UTIL_INC_3432 3433 +#define Z_UTIL_INC_3433 3434 +#define Z_UTIL_INC_3434 3435 +#define Z_UTIL_INC_3435 3436 +#define Z_UTIL_INC_3436 3437 +#define Z_UTIL_INC_3437 3438 +#define Z_UTIL_INC_3438 3439 +#define Z_UTIL_INC_3439 3440 +#define Z_UTIL_INC_3440 3441 +#define Z_UTIL_INC_3441 3442 +#define Z_UTIL_INC_3442 3443 +#define Z_UTIL_INC_3443 3444 +#define Z_UTIL_INC_3444 3445 +#define Z_UTIL_INC_3445 3446 +#define Z_UTIL_INC_3446 3447 +#define Z_UTIL_INC_3447 3448 +#define Z_UTIL_INC_3448 3449 +#define Z_UTIL_INC_3449 3450 +#define Z_UTIL_INC_3450 3451 +#define Z_UTIL_INC_3451 3452 +#define Z_UTIL_INC_3452 3453 +#define Z_UTIL_INC_3453 3454 +#define Z_UTIL_INC_3454 3455 +#define Z_UTIL_INC_3455 3456 +#define Z_UTIL_INC_3456 3457 +#define Z_UTIL_INC_3457 3458 +#define Z_UTIL_INC_3458 3459 +#define Z_UTIL_INC_3459 3460 +#define Z_UTIL_INC_3460 3461 +#define Z_UTIL_INC_3461 3462 +#define Z_UTIL_INC_3462 3463 +#define Z_UTIL_INC_3463 3464 +#define Z_UTIL_INC_3464 3465 +#define Z_UTIL_INC_3465 3466 +#define Z_UTIL_INC_3466 3467 +#define Z_UTIL_INC_3467 3468 +#define Z_UTIL_INC_3468 3469 +#define Z_UTIL_INC_3469 3470 +#define Z_UTIL_INC_3470 3471 +#define Z_UTIL_INC_3471 3472 +#define Z_UTIL_INC_3472 3473 +#define Z_UTIL_INC_3473 3474 +#define Z_UTIL_INC_3474 3475 +#define Z_UTIL_INC_3475 3476 +#define Z_UTIL_INC_3476 3477 +#define Z_UTIL_INC_3477 3478 +#define Z_UTIL_INC_3478 3479 +#define Z_UTIL_INC_3479 3480 +#define Z_UTIL_INC_3480 3481 +#define Z_UTIL_INC_3481 3482 +#define Z_UTIL_INC_3482 3483 +#define Z_UTIL_INC_3483 3484 +#define Z_UTIL_INC_3484 3485 +#define Z_UTIL_INC_3485 3486 +#define Z_UTIL_INC_3486 3487 +#define Z_UTIL_INC_3487 3488 +#define Z_UTIL_INC_3488 3489 +#define Z_UTIL_INC_3489 3490 +#define Z_UTIL_INC_3490 3491 +#define Z_UTIL_INC_3491 3492 +#define Z_UTIL_INC_3492 3493 +#define Z_UTIL_INC_3493 3494 +#define Z_UTIL_INC_3494 3495 +#define Z_UTIL_INC_3495 3496 +#define Z_UTIL_INC_3496 3497 +#define Z_UTIL_INC_3497 3498 +#define Z_UTIL_INC_3498 3499 +#define Z_UTIL_INC_3499 3500 +#define Z_UTIL_INC_3500 3501 +#define Z_UTIL_INC_3501 3502 +#define Z_UTIL_INC_3502 3503 +#define Z_UTIL_INC_3503 3504 +#define Z_UTIL_INC_3504 3505 +#define Z_UTIL_INC_3505 3506 +#define Z_UTIL_INC_3506 3507 +#define Z_UTIL_INC_3507 3508 +#define Z_UTIL_INC_3508 3509 +#define Z_UTIL_INC_3509 3510 +#define Z_UTIL_INC_3510 3511 +#define Z_UTIL_INC_3511 3512 +#define Z_UTIL_INC_3512 3513 +#define Z_UTIL_INC_3513 3514 +#define Z_UTIL_INC_3514 3515 +#define Z_UTIL_INC_3515 3516 +#define Z_UTIL_INC_3516 3517 +#define Z_UTIL_INC_3517 3518 +#define Z_UTIL_INC_3518 3519 +#define Z_UTIL_INC_3519 3520 +#define Z_UTIL_INC_3520 3521 +#define Z_UTIL_INC_3521 3522 +#define Z_UTIL_INC_3522 3523 +#define Z_UTIL_INC_3523 3524 +#define Z_UTIL_INC_3524 3525 +#define Z_UTIL_INC_3525 3526 +#define Z_UTIL_INC_3526 3527 +#define Z_UTIL_INC_3527 3528 +#define Z_UTIL_INC_3528 3529 +#define Z_UTIL_INC_3529 3530 +#define Z_UTIL_INC_3530 3531 +#define Z_UTIL_INC_3531 3532 +#define Z_UTIL_INC_3532 3533 +#define Z_UTIL_INC_3533 3534 +#define Z_UTIL_INC_3534 3535 +#define Z_UTIL_INC_3535 3536 +#define Z_UTIL_INC_3536 3537 +#define Z_UTIL_INC_3537 3538 +#define Z_UTIL_INC_3538 3539 +#define Z_UTIL_INC_3539 3540 +#define Z_UTIL_INC_3540 3541 +#define Z_UTIL_INC_3541 3542 +#define Z_UTIL_INC_3542 3543 +#define Z_UTIL_INC_3543 3544 +#define Z_UTIL_INC_3544 3545 +#define Z_UTIL_INC_3545 3546 +#define Z_UTIL_INC_3546 3547 +#define Z_UTIL_INC_3547 3548 +#define Z_UTIL_INC_3548 3549 +#define Z_UTIL_INC_3549 3550 +#define Z_UTIL_INC_3550 3551 +#define Z_UTIL_INC_3551 3552 +#define Z_UTIL_INC_3552 3553 +#define Z_UTIL_INC_3553 3554 +#define Z_UTIL_INC_3554 3555 +#define Z_UTIL_INC_3555 3556 +#define Z_UTIL_INC_3556 3557 +#define Z_UTIL_INC_3557 3558 +#define Z_UTIL_INC_3558 3559 +#define Z_UTIL_INC_3559 3560 +#define Z_UTIL_INC_3560 3561 +#define Z_UTIL_INC_3561 3562 +#define Z_UTIL_INC_3562 3563 +#define Z_UTIL_INC_3563 3564 +#define Z_UTIL_INC_3564 3565 +#define Z_UTIL_INC_3565 3566 +#define Z_UTIL_INC_3566 3567 +#define Z_UTIL_INC_3567 3568 +#define Z_UTIL_INC_3568 3569 +#define Z_UTIL_INC_3569 3570 +#define Z_UTIL_INC_3570 3571 +#define Z_UTIL_INC_3571 3572 +#define Z_UTIL_INC_3572 3573 +#define Z_UTIL_INC_3573 3574 +#define Z_UTIL_INC_3574 3575 +#define Z_UTIL_INC_3575 3576 +#define Z_UTIL_INC_3576 3577 +#define Z_UTIL_INC_3577 3578 +#define Z_UTIL_INC_3578 3579 +#define Z_UTIL_INC_3579 3580 +#define Z_UTIL_INC_3580 3581 +#define Z_UTIL_INC_3581 3582 +#define Z_UTIL_INC_3582 3583 +#define Z_UTIL_INC_3583 3584 +#define Z_UTIL_INC_3584 3585 +#define Z_UTIL_INC_3585 3586 +#define Z_UTIL_INC_3586 3587 +#define Z_UTIL_INC_3587 3588 +#define Z_UTIL_INC_3588 3589 +#define Z_UTIL_INC_3589 3590 +#define Z_UTIL_INC_3590 3591 +#define Z_UTIL_INC_3591 3592 +#define Z_UTIL_INC_3592 3593 +#define Z_UTIL_INC_3593 3594 +#define Z_UTIL_INC_3594 3595 +#define Z_UTIL_INC_3595 3596 +#define Z_UTIL_INC_3596 3597 +#define Z_UTIL_INC_3597 3598 +#define Z_UTIL_INC_3598 3599 +#define Z_UTIL_INC_3599 3600 +#define Z_UTIL_INC_3600 3601 +#define Z_UTIL_INC_3601 3602 +#define Z_UTIL_INC_3602 3603 +#define Z_UTIL_INC_3603 3604 +#define Z_UTIL_INC_3604 3605 +#define Z_UTIL_INC_3605 3606 +#define Z_UTIL_INC_3606 3607 +#define Z_UTIL_INC_3607 3608 +#define Z_UTIL_INC_3608 3609 +#define Z_UTIL_INC_3609 3610 +#define Z_UTIL_INC_3610 3611 +#define Z_UTIL_INC_3611 3612 +#define Z_UTIL_INC_3612 3613 +#define Z_UTIL_INC_3613 3614 +#define Z_UTIL_INC_3614 3615 +#define Z_UTIL_INC_3615 3616 +#define Z_UTIL_INC_3616 3617 +#define Z_UTIL_INC_3617 3618 +#define Z_UTIL_INC_3618 3619 +#define Z_UTIL_INC_3619 3620 +#define Z_UTIL_INC_3620 3621 +#define Z_UTIL_INC_3621 3622 +#define Z_UTIL_INC_3622 3623 +#define Z_UTIL_INC_3623 3624 +#define Z_UTIL_INC_3624 3625 +#define Z_UTIL_INC_3625 3626 +#define Z_UTIL_INC_3626 3627 +#define Z_UTIL_INC_3627 3628 +#define Z_UTIL_INC_3628 3629 +#define Z_UTIL_INC_3629 3630 +#define Z_UTIL_INC_3630 3631 +#define Z_UTIL_INC_3631 3632 +#define Z_UTIL_INC_3632 3633 +#define Z_UTIL_INC_3633 3634 +#define Z_UTIL_INC_3634 3635 +#define Z_UTIL_INC_3635 3636 +#define Z_UTIL_INC_3636 3637 +#define Z_UTIL_INC_3637 3638 +#define Z_UTIL_INC_3638 3639 +#define Z_UTIL_INC_3639 3640 +#define Z_UTIL_INC_3640 3641 +#define Z_UTIL_INC_3641 3642 +#define Z_UTIL_INC_3642 3643 +#define Z_UTIL_INC_3643 3644 +#define Z_UTIL_INC_3644 3645 +#define Z_UTIL_INC_3645 3646 +#define Z_UTIL_INC_3646 3647 +#define Z_UTIL_INC_3647 3648 +#define Z_UTIL_INC_3648 3649 +#define Z_UTIL_INC_3649 3650 +#define Z_UTIL_INC_3650 3651 +#define Z_UTIL_INC_3651 3652 +#define Z_UTIL_INC_3652 3653 +#define Z_UTIL_INC_3653 3654 +#define Z_UTIL_INC_3654 3655 +#define Z_UTIL_INC_3655 3656 +#define Z_UTIL_INC_3656 3657 +#define Z_UTIL_INC_3657 3658 +#define Z_UTIL_INC_3658 3659 +#define Z_UTIL_INC_3659 3660 +#define Z_UTIL_INC_3660 3661 +#define Z_UTIL_INC_3661 3662 +#define Z_UTIL_INC_3662 3663 +#define Z_UTIL_INC_3663 3664 +#define Z_UTIL_INC_3664 3665 +#define Z_UTIL_INC_3665 3666 +#define Z_UTIL_INC_3666 3667 +#define Z_UTIL_INC_3667 3668 +#define Z_UTIL_INC_3668 3669 +#define Z_UTIL_INC_3669 3670 +#define Z_UTIL_INC_3670 3671 +#define Z_UTIL_INC_3671 3672 +#define Z_UTIL_INC_3672 3673 +#define Z_UTIL_INC_3673 3674 +#define Z_UTIL_INC_3674 3675 +#define Z_UTIL_INC_3675 3676 +#define Z_UTIL_INC_3676 3677 +#define Z_UTIL_INC_3677 3678 +#define Z_UTIL_INC_3678 3679 +#define Z_UTIL_INC_3679 3680 +#define Z_UTIL_INC_3680 3681 +#define Z_UTIL_INC_3681 3682 +#define Z_UTIL_INC_3682 3683 +#define Z_UTIL_INC_3683 3684 +#define Z_UTIL_INC_3684 3685 +#define Z_UTIL_INC_3685 3686 +#define Z_UTIL_INC_3686 3687 +#define Z_UTIL_INC_3687 3688 +#define Z_UTIL_INC_3688 3689 +#define Z_UTIL_INC_3689 3690 +#define Z_UTIL_INC_3690 3691 +#define Z_UTIL_INC_3691 3692 +#define Z_UTIL_INC_3692 3693 +#define Z_UTIL_INC_3693 3694 +#define Z_UTIL_INC_3694 3695 +#define Z_UTIL_INC_3695 3696 +#define Z_UTIL_INC_3696 3697 +#define Z_UTIL_INC_3697 3698 +#define Z_UTIL_INC_3698 3699 +#define Z_UTIL_INC_3699 3700 +#define Z_UTIL_INC_3700 3701 +#define Z_UTIL_INC_3701 3702 +#define Z_UTIL_INC_3702 3703 +#define Z_UTIL_INC_3703 3704 +#define Z_UTIL_INC_3704 3705 +#define Z_UTIL_INC_3705 3706 +#define Z_UTIL_INC_3706 3707 +#define Z_UTIL_INC_3707 3708 +#define Z_UTIL_INC_3708 3709 +#define Z_UTIL_INC_3709 3710 +#define Z_UTIL_INC_3710 3711 +#define Z_UTIL_INC_3711 3712 +#define Z_UTIL_INC_3712 3713 +#define Z_UTIL_INC_3713 3714 +#define Z_UTIL_INC_3714 3715 +#define Z_UTIL_INC_3715 3716 +#define Z_UTIL_INC_3716 3717 +#define Z_UTIL_INC_3717 3718 +#define Z_UTIL_INC_3718 3719 +#define Z_UTIL_INC_3719 3720 +#define Z_UTIL_INC_3720 3721 +#define Z_UTIL_INC_3721 3722 +#define Z_UTIL_INC_3722 3723 +#define Z_UTIL_INC_3723 3724 +#define Z_UTIL_INC_3724 3725 +#define Z_UTIL_INC_3725 3726 +#define Z_UTIL_INC_3726 3727 +#define Z_UTIL_INC_3727 3728 +#define Z_UTIL_INC_3728 3729 +#define Z_UTIL_INC_3729 3730 +#define Z_UTIL_INC_3730 3731 +#define Z_UTIL_INC_3731 3732 +#define Z_UTIL_INC_3732 3733 +#define Z_UTIL_INC_3733 3734 +#define Z_UTIL_INC_3734 3735 +#define Z_UTIL_INC_3735 3736 +#define Z_UTIL_INC_3736 3737 +#define Z_UTIL_INC_3737 3738 +#define Z_UTIL_INC_3738 3739 +#define Z_UTIL_INC_3739 3740 +#define Z_UTIL_INC_3740 3741 +#define Z_UTIL_INC_3741 3742 +#define Z_UTIL_INC_3742 3743 +#define Z_UTIL_INC_3743 3744 +#define Z_UTIL_INC_3744 3745 +#define Z_UTIL_INC_3745 3746 +#define Z_UTIL_INC_3746 3747 +#define Z_UTIL_INC_3747 3748 +#define Z_UTIL_INC_3748 3749 +#define Z_UTIL_INC_3749 3750 +#define Z_UTIL_INC_3750 3751 +#define Z_UTIL_INC_3751 3752 +#define Z_UTIL_INC_3752 3753 +#define Z_UTIL_INC_3753 3754 +#define Z_UTIL_INC_3754 3755 +#define Z_UTIL_INC_3755 3756 +#define Z_UTIL_INC_3756 3757 +#define Z_UTIL_INC_3757 3758 +#define Z_UTIL_INC_3758 3759 +#define Z_UTIL_INC_3759 3760 +#define Z_UTIL_INC_3760 3761 +#define Z_UTIL_INC_3761 3762 +#define Z_UTIL_INC_3762 3763 +#define Z_UTIL_INC_3763 3764 +#define Z_UTIL_INC_3764 3765 +#define Z_UTIL_INC_3765 3766 +#define Z_UTIL_INC_3766 3767 +#define Z_UTIL_INC_3767 3768 +#define Z_UTIL_INC_3768 3769 +#define Z_UTIL_INC_3769 3770 +#define Z_UTIL_INC_3770 3771 +#define Z_UTIL_INC_3771 3772 +#define Z_UTIL_INC_3772 3773 +#define Z_UTIL_INC_3773 3774 +#define Z_UTIL_INC_3774 3775 +#define Z_UTIL_INC_3775 3776 +#define Z_UTIL_INC_3776 3777 +#define Z_UTIL_INC_3777 3778 +#define Z_UTIL_INC_3778 3779 +#define Z_UTIL_INC_3779 3780 +#define Z_UTIL_INC_3780 3781 +#define Z_UTIL_INC_3781 3782 +#define Z_UTIL_INC_3782 3783 +#define Z_UTIL_INC_3783 3784 +#define Z_UTIL_INC_3784 3785 +#define Z_UTIL_INC_3785 3786 +#define Z_UTIL_INC_3786 3787 +#define Z_UTIL_INC_3787 3788 +#define Z_UTIL_INC_3788 3789 +#define Z_UTIL_INC_3789 3790 +#define Z_UTIL_INC_3790 3791 +#define Z_UTIL_INC_3791 3792 +#define Z_UTIL_INC_3792 3793 +#define Z_UTIL_INC_3793 3794 +#define Z_UTIL_INC_3794 3795 +#define Z_UTIL_INC_3795 3796 +#define Z_UTIL_INC_3796 3797 +#define Z_UTIL_INC_3797 3798 +#define Z_UTIL_INC_3798 3799 +#define Z_UTIL_INC_3799 3800 +#define Z_UTIL_INC_3800 3801 +#define Z_UTIL_INC_3801 3802 +#define Z_UTIL_INC_3802 3803 +#define Z_UTIL_INC_3803 3804 +#define Z_UTIL_INC_3804 3805 +#define Z_UTIL_INC_3805 3806 +#define Z_UTIL_INC_3806 3807 +#define Z_UTIL_INC_3807 3808 +#define Z_UTIL_INC_3808 3809 +#define Z_UTIL_INC_3809 3810 +#define Z_UTIL_INC_3810 3811 +#define Z_UTIL_INC_3811 3812 +#define Z_UTIL_INC_3812 3813 +#define Z_UTIL_INC_3813 3814 +#define Z_UTIL_INC_3814 3815 +#define Z_UTIL_INC_3815 3816 +#define Z_UTIL_INC_3816 3817 +#define Z_UTIL_INC_3817 3818 +#define Z_UTIL_INC_3818 3819 +#define Z_UTIL_INC_3819 3820 +#define Z_UTIL_INC_3820 3821 +#define Z_UTIL_INC_3821 3822 +#define Z_UTIL_INC_3822 3823 +#define Z_UTIL_INC_3823 3824 +#define Z_UTIL_INC_3824 3825 +#define Z_UTIL_INC_3825 3826 +#define Z_UTIL_INC_3826 3827 +#define Z_UTIL_INC_3827 3828 +#define Z_UTIL_INC_3828 3829 +#define Z_UTIL_INC_3829 3830 +#define Z_UTIL_INC_3830 3831 +#define Z_UTIL_INC_3831 3832 +#define Z_UTIL_INC_3832 3833 +#define Z_UTIL_INC_3833 3834 +#define Z_UTIL_INC_3834 3835 +#define Z_UTIL_INC_3835 3836 +#define Z_UTIL_INC_3836 3837 +#define Z_UTIL_INC_3837 3838 +#define Z_UTIL_INC_3838 3839 +#define Z_UTIL_INC_3839 3840 +#define Z_UTIL_INC_3840 3841 +#define Z_UTIL_INC_3841 3842 +#define Z_UTIL_INC_3842 3843 +#define Z_UTIL_INC_3843 3844 +#define Z_UTIL_INC_3844 3845 +#define Z_UTIL_INC_3845 3846 +#define Z_UTIL_INC_3846 3847 +#define Z_UTIL_INC_3847 3848 +#define Z_UTIL_INC_3848 3849 +#define Z_UTIL_INC_3849 3850 +#define Z_UTIL_INC_3850 3851 +#define Z_UTIL_INC_3851 3852 +#define Z_UTIL_INC_3852 3853 +#define Z_UTIL_INC_3853 3854 +#define Z_UTIL_INC_3854 3855 +#define Z_UTIL_INC_3855 3856 +#define Z_UTIL_INC_3856 3857 +#define Z_UTIL_INC_3857 3858 +#define Z_UTIL_INC_3858 3859 +#define Z_UTIL_INC_3859 3860 +#define Z_UTIL_INC_3860 3861 +#define Z_UTIL_INC_3861 3862 +#define Z_UTIL_INC_3862 3863 +#define Z_UTIL_INC_3863 3864 +#define Z_UTIL_INC_3864 3865 +#define Z_UTIL_INC_3865 3866 +#define Z_UTIL_INC_3866 3867 +#define Z_UTIL_INC_3867 3868 +#define Z_UTIL_INC_3868 3869 +#define Z_UTIL_INC_3869 3870 +#define Z_UTIL_INC_3870 3871 +#define Z_UTIL_INC_3871 3872 +#define Z_UTIL_INC_3872 3873 +#define Z_UTIL_INC_3873 3874 +#define Z_UTIL_INC_3874 3875 +#define Z_UTIL_INC_3875 3876 +#define Z_UTIL_INC_3876 3877 +#define Z_UTIL_INC_3877 3878 +#define Z_UTIL_INC_3878 3879 +#define Z_UTIL_INC_3879 3880 +#define Z_UTIL_INC_3880 3881 +#define Z_UTIL_INC_3881 3882 +#define Z_UTIL_INC_3882 3883 +#define Z_UTIL_INC_3883 3884 +#define Z_UTIL_INC_3884 3885 +#define Z_UTIL_INC_3885 3886 +#define Z_UTIL_INC_3886 3887 +#define Z_UTIL_INC_3887 3888 +#define Z_UTIL_INC_3888 3889 +#define Z_UTIL_INC_3889 3890 +#define Z_UTIL_INC_3890 3891 +#define Z_UTIL_INC_3891 3892 +#define Z_UTIL_INC_3892 3893 +#define Z_UTIL_INC_3893 3894 +#define Z_UTIL_INC_3894 3895 +#define Z_UTIL_INC_3895 3896 +#define Z_UTIL_INC_3896 3897 +#define Z_UTIL_INC_3897 3898 +#define Z_UTIL_INC_3898 3899 +#define Z_UTIL_INC_3899 3900 +#define Z_UTIL_INC_3900 3901 +#define Z_UTIL_INC_3901 3902 +#define Z_UTIL_INC_3902 3903 +#define Z_UTIL_INC_3903 3904 +#define Z_UTIL_INC_3904 3905 +#define Z_UTIL_INC_3905 3906 +#define Z_UTIL_INC_3906 3907 +#define Z_UTIL_INC_3907 3908 +#define Z_UTIL_INC_3908 3909 +#define Z_UTIL_INC_3909 3910 +#define Z_UTIL_INC_3910 3911 +#define Z_UTIL_INC_3911 3912 +#define Z_UTIL_INC_3912 3913 +#define Z_UTIL_INC_3913 3914 +#define Z_UTIL_INC_3914 3915 +#define Z_UTIL_INC_3915 3916 +#define Z_UTIL_INC_3916 3917 +#define Z_UTIL_INC_3917 3918 +#define Z_UTIL_INC_3918 3919 +#define Z_UTIL_INC_3919 3920 +#define Z_UTIL_INC_3920 3921 +#define Z_UTIL_INC_3921 3922 +#define Z_UTIL_INC_3922 3923 +#define Z_UTIL_INC_3923 3924 +#define Z_UTIL_INC_3924 3925 +#define Z_UTIL_INC_3925 3926 +#define Z_UTIL_INC_3926 3927 +#define Z_UTIL_INC_3927 3928 +#define Z_UTIL_INC_3928 3929 +#define Z_UTIL_INC_3929 3930 +#define Z_UTIL_INC_3930 3931 +#define Z_UTIL_INC_3931 3932 +#define Z_UTIL_INC_3932 3933 +#define Z_UTIL_INC_3933 3934 +#define Z_UTIL_INC_3934 3935 +#define Z_UTIL_INC_3935 3936 +#define Z_UTIL_INC_3936 3937 +#define Z_UTIL_INC_3937 3938 +#define Z_UTIL_INC_3938 3939 +#define Z_UTIL_INC_3939 3940 +#define Z_UTIL_INC_3940 3941 +#define Z_UTIL_INC_3941 3942 +#define Z_UTIL_INC_3942 3943 +#define Z_UTIL_INC_3943 3944 +#define Z_UTIL_INC_3944 3945 +#define Z_UTIL_INC_3945 3946 +#define Z_UTIL_INC_3946 3947 +#define Z_UTIL_INC_3947 3948 +#define Z_UTIL_INC_3948 3949 +#define Z_UTIL_INC_3949 3950 +#define Z_UTIL_INC_3950 3951 +#define Z_UTIL_INC_3951 3952 +#define Z_UTIL_INC_3952 3953 +#define Z_UTIL_INC_3953 3954 +#define Z_UTIL_INC_3954 3955 +#define Z_UTIL_INC_3955 3956 +#define Z_UTIL_INC_3956 3957 +#define Z_UTIL_INC_3957 3958 +#define Z_UTIL_INC_3958 3959 +#define Z_UTIL_INC_3959 3960 +#define Z_UTIL_INC_3960 3961 +#define Z_UTIL_INC_3961 3962 +#define Z_UTIL_INC_3962 3963 +#define Z_UTIL_INC_3963 3964 +#define Z_UTIL_INC_3964 3965 +#define Z_UTIL_INC_3965 3966 +#define Z_UTIL_INC_3966 3967 +#define Z_UTIL_INC_3967 3968 +#define Z_UTIL_INC_3968 3969 +#define Z_UTIL_INC_3969 3970 +#define Z_UTIL_INC_3970 3971 +#define Z_UTIL_INC_3971 3972 +#define Z_UTIL_INC_3972 3973 +#define Z_UTIL_INC_3973 3974 +#define Z_UTIL_INC_3974 3975 +#define Z_UTIL_INC_3975 3976 +#define Z_UTIL_INC_3976 3977 +#define Z_UTIL_INC_3977 3978 +#define Z_UTIL_INC_3978 3979 +#define Z_UTIL_INC_3979 3980 +#define Z_UTIL_INC_3980 3981 +#define Z_UTIL_INC_3981 3982 +#define Z_UTIL_INC_3982 3983 +#define Z_UTIL_INC_3983 3984 +#define Z_UTIL_INC_3984 3985 +#define Z_UTIL_INC_3985 3986 +#define Z_UTIL_INC_3986 3987 +#define Z_UTIL_INC_3987 3988 +#define Z_UTIL_INC_3988 3989 +#define Z_UTIL_INC_3989 3990 +#define Z_UTIL_INC_3990 3991 +#define Z_UTIL_INC_3991 3992 +#define Z_UTIL_INC_3992 3993 +#define Z_UTIL_INC_3993 3994 +#define Z_UTIL_INC_3994 3995 +#define Z_UTIL_INC_3995 3996 +#define Z_UTIL_INC_3996 3997 +#define Z_UTIL_INC_3997 3998 +#define Z_UTIL_INC_3998 3999 +#define Z_UTIL_INC_3999 4000 +#define Z_UTIL_INC_4000 4001 +#define Z_UTIL_INC_4001 4002 +#define Z_UTIL_INC_4002 4003 +#define Z_UTIL_INC_4003 4004 +#define Z_UTIL_INC_4004 4005 +#define Z_UTIL_INC_4005 4006 +#define Z_UTIL_INC_4006 4007 +#define Z_UTIL_INC_4007 4008 +#define Z_UTIL_INC_4008 4009 +#define Z_UTIL_INC_4009 4010 +#define Z_UTIL_INC_4010 4011 +#define Z_UTIL_INC_4011 4012 +#define Z_UTIL_INC_4012 4013 +#define Z_UTIL_INC_4013 4014 +#define Z_UTIL_INC_4014 4015 +#define Z_UTIL_INC_4015 4016 +#define Z_UTIL_INC_4016 4017 +#define Z_UTIL_INC_4017 4018 +#define Z_UTIL_INC_4018 4019 +#define Z_UTIL_INC_4019 4020 +#define Z_UTIL_INC_4020 4021 +#define Z_UTIL_INC_4021 4022 +#define Z_UTIL_INC_4022 4023 +#define Z_UTIL_INC_4023 4024 +#define Z_UTIL_INC_4024 4025 +#define Z_UTIL_INC_4025 4026 +#define Z_UTIL_INC_4026 4027 +#define Z_UTIL_INC_4027 4028 +#define Z_UTIL_INC_4028 4029 +#define Z_UTIL_INC_4029 4030 +#define Z_UTIL_INC_4030 4031 +#define Z_UTIL_INC_4031 4032 +#define Z_UTIL_INC_4032 4033 +#define Z_UTIL_INC_4033 4034 +#define Z_UTIL_INC_4034 4035 +#define Z_UTIL_INC_4035 4036 +#define Z_UTIL_INC_4036 4037 +#define Z_UTIL_INC_4037 4038 +#define Z_UTIL_INC_4038 4039 +#define Z_UTIL_INC_4039 4040 +#define Z_UTIL_INC_4040 4041 +#define Z_UTIL_INC_4041 4042 +#define Z_UTIL_INC_4042 4043 +#define Z_UTIL_INC_4043 4044 +#define Z_UTIL_INC_4044 4045 +#define Z_UTIL_INC_4045 4046 +#define Z_UTIL_INC_4046 4047 +#define Z_UTIL_INC_4047 4048 +#define Z_UTIL_INC_4048 4049 +#define Z_UTIL_INC_4049 4050 +#define Z_UTIL_INC_4050 4051 +#define Z_UTIL_INC_4051 4052 +#define Z_UTIL_INC_4052 4053 +#define Z_UTIL_INC_4053 4054 +#define Z_UTIL_INC_4054 4055 +#define Z_UTIL_INC_4055 4056 +#define Z_UTIL_INC_4056 4057 +#define Z_UTIL_INC_4057 4058 +#define Z_UTIL_INC_4058 4059 +#define Z_UTIL_INC_4059 4060 +#define Z_UTIL_INC_4060 4061 +#define Z_UTIL_INC_4061 4062 +#define Z_UTIL_INC_4062 4063 +#define Z_UTIL_INC_4063 4064 +#define Z_UTIL_INC_4064 4065 +#define Z_UTIL_INC_4065 4066 +#define Z_UTIL_INC_4066 4067 +#define Z_UTIL_INC_4067 4068 +#define Z_UTIL_INC_4068 4069 +#define Z_UTIL_INC_4069 4070 +#define Z_UTIL_INC_4070 4071 +#define Z_UTIL_INC_4071 4072 +#define Z_UTIL_INC_4072 4073 +#define Z_UTIL_INC_4073 4074 +#define Z_UTIL_INC_4074 4075 +#define Z_UTIL_INC_4075 4076 +#define Z_UTIL_INC_4076 4077 +#define Z_UTIL_INC_4077 4078 +#define Z_UTIL_INC_4078 4079 +#define Z_UTIL_INC_4079 4080 +#define Z_UTIL_INC_4080 4081 +#define Z_UTIL_INC_4081 4082 +#define Z_UTIL_INC_4082 4083 +#define Z_UTIL_INC_4083 4084 +#define Z_UTIL_INC_4084 4085 +#define Z_UTIL_INC_4085 4086 +#define Z_UTIL_INC_4086 4087 +#define Z_UTIL_INC_4087 4088 +#define Z_UTIL_INC_4088 4089 +#define Z_UTIL_INC_4089 4090 +#define Z_UTIL_INC_4090 4091 +#define Z_UTIL_INC_4091 4092 +#define Z_UTIL_INC_4092 4093 +#define Z_UTIL_INC_4093 4094 +#define Z_UTIL_INC_4094 4095 +#define Z_UTIL_INC_4095 4096 +#define Z_UTIL_INC_4096 4097 + +#endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_UTIL_INC_H_ */ + +/** + * INTERNAL_HIDDEN @endcond + */ diff --git a/include/zephyr/sys/util_internal_util_x2.h b/include/zephyr/sys/util_internal_util_x2.h new file mode 100644 index 00000000000..f2452822cf8 --- /dev/null +++ b/include/zephyr/sys/util_internal_util_x2.h @@ -0,0 +1,4121 @@ +/* + * Copyright (c) 2011-2014, Wind River Systems, Inc. + * Copyright (c) 2020, Nordic Semiconductor ASA + * Copyright (c) 2023, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @cond INTERNAL_HIDDEN + */ + +#ifndef ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_ +#error "This header should not be used directly, please include util_internal.h instead" +#endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_ */ + +#ifndef ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_UTIL_X2_H_ +#define ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_UTIL_X2_H_ + +#define Z_UTIL_X2_0 0 +#define Z_UTIL_X2_1 2 +#define Z_UTIL_X2_2 4 +#define Z_UTIL_X2_3 6 +#define Z_UTIL_X2_4 8 +#define Z_UTIL_X2_5 10 +#define Z_UTIL_X2_6 12 +#define Z_UTIL_X2_7 14 +#define Z_UTIL_X2_8 16 +#define Z_UTIL_X2_9 18 +#define Z_UTIL_X2_10 20 +#define Z_UTIL_X2_11 22 +#define Z_UTIL_X2_12 24 +#define Z_UTIL_X2_13 26 +#define Z_UTIL_X2_14 28 +#define Z_UTIL_X2_15 30 +#define Z_UTIL_X2_16 32 +#define Z_UTIL_X2_17 34 +#define Z_UTIL_X2_18 36 +#define Z_UTIL_X2_19 38 +#define Z_UTIL_X2_20 40 +#define Z_UTIL_X2_21 42 +#define Z_UTIL_X2_22 44 +#define Z_UTIL_X2_23 46 +#define Z_UTIL_X2_24 48 +#define Z_UTIL_X2_25 50 +#define Z_UTIL_X2_26 52 +#define Z_UTIL_X2_27 54 +#define Z_UTIL_X2_28 56 +#define Z_UTIL_X2_29 58 +#define Z_UTIL_X2_30 60 +#define Z_UTIL_X2_31 62 +#define Z_UTIL_X2_32 64 +#define Z_UTIL_X2_33 66 +#define Z_UTIL_X2_34 68 +#define Z_UTIL_X2_35 70 +#define Z_UTIL_X2_36 72 +#define Z_UTIL_X2_37 74 +#define Z_UTIL_X2_38 76 +#define Z_UTIL_X2_39 78 +#define Z_UTIL_X2_40 80 +#define Z_UTIL_X2_41 82 +#define Z_UTIL_X2_42 84 +#define Z_UTIL_X2_43 86 +#define Z_UTIL_X2_44 88 +#define Z_UTIL_X2_45 90 +#define Z_UTIL_X2_46 92 +#define Z_UTIL_X2_47 94 +#define Z_UTIL_X2_48 96 +#define Z_UTIL_X2_49 98 +#define Z_UTIL_X2_50 100 +#define Z_UTIL_X2_51 102 +#define Z_UTIL_X2_52 104 +#define Z_UTIL_X2_53 106 +#define Z_UTIL_X2_54 108 +#define Z_UTIL_X2_55 110 +#define Z_UTIL_X2_56 112 +#define Z_UTIL_X2_57 114 +#define Z_UTIL_X2_58 116 +#define Z_UTIL_X2_59 118 +#define Z_UTIL_X2_60 120 +#define Z_UTIL_X2_61 122 +#define Z_UTIL_X2_62 124 +#define Z_UTIL_X2_63 126 +#define Z_UTIL_X2_64 128 +#define Z_UTIL_X2_65 130 +#define Z_UTIL_X2_66 132 +#define Z_UTIL_X2_67 134 +#define Z_UTIL_X2_68 136 +#define Z_UTIL_X2_69 138 +#define Z_UTIL_X2_70 140 +#define Z_UTIL_X2_71 142 +#define Z_UTIL_X2_72 144 +#define Z_UTIL_X2_73 146 +#define Z_UTIL_X2_74 148 +#define Z_UTIL_X2_75 150 +#define Z_UTIL_X2_76 152 +#define Z_UTIL_X2_77 154 +#define Z_UTIL_X2_78 156 +#define Z_UTIL_X2_79 158 +#define Z_UTIL_X2_80 160 +#define Z_UTIL_X2_81 162 +#define Z_UTIL_X2_82 164 +#define Z_UTIL_X2_83 166 +#define Z_UTIL_X2_84 168 +#define Z_UTIL_X2_85 170 +#define Z_UTIL_X2_86 172 +#define Z_UTIL_X2_87 174 +#define Z_UTIL_X2_88 176 +#define Z_UTIL_X2_89 178 +#define Z_UTIL_X2_90 180 +#define Z_UTIL_X2_91 182 +#define Z_UTIL_X2_92 184 +#define Z_UTIL_X2_93 186 +#define Z_UTIL_X2_94 188 +#define Z_UTIL_X2_95 190 +#define Z_UTIL_X2_96 192 +#define Z_UTIL_X2_97 194 +#define Z_UTIL_X2_98 196 +#define Z_UTIL_X2_99 198 +#define Z_UTIL_X2_100 200 +#define Z_UTIL_X2_101 202 +#define Z_UTIL_X2_102 204 +#define Z_UTIL_X2_103 206 +#define Z_UTIL_X2_104 208 +#define Z_UTIL_X2_105 210 +#define Z_UTIL_X2_106 212 +#define Z_UTIL_X2_107 214 +#define Z_UTIL_X2_108 216 +#define Z_UTIL_X2_109 218 +#define Z_UTIL_X2_110 220 +#define Z_UTIL_X2_111 222 +#define Z_UTIL_X2_112 224 +#define Z_UTIL_X2_113 226 +#define Z_UTIL_X2_114 228 +#define Z_UTIL_X2_115 230 +#define Z_UTIL_X2_116 232 +#define Z_UTIL_X2_117 234 +#define Z_UTIL_X2_118 236 +#define Z_UTIL_X2_119 238 +#define Z_UTIL_X2_120 240 +#define Z_UTIL_X2_121 242 +#define Z_UTIL_X2_122 244 +#define Z_UTIL_X2_123 246 +#define Z_UTIL_X2_124 248 +#define Z_UTIL_X2_125 250 +#define Z_UTIL_X2_126 252 +#define Z_UTIL_X2_127 254 +#define Z_UTIL_X2_128 256 +#define Z_UTIL_X2_129 258 +#define Z_UTIL_X2_130 260 +#define Z_UTIL_X2_131 262 +#define Z_UTIL_X2_132 264 +#define Z_UTIL_X2_133 266 +#define Z_UTIL_X2_134 268 +#define Z_UTIL_X2_135 270 +#define Z_UTIL_X2_136 272 +#define Z_UTIL_X2_137 274 +#define Z_UTIL_X2_138 276 +#define Z_UTIL_X2_139 278 +#define Z_UTIL_X2_140 280 +#define Z_UTIL_X2_141 282 +#define Z_UTIL_X2_142 284 +#define Z_UTIL_X2_143 286 +#define Z_UTIL_X2_144 288 +#define Z_UTIL_X2_145 290 +#define Z_UTIL_X2_146 292 +#define Z_UTIL_X2_147 294 +#define Z_UTIL_X2_148 296 +#define Z_UTIL_X2_149 298 +#define Z_UTIL_X2_150 300 +#define Z_UTIL_X2_151 302 +#define Z_UTIL_X2_152 304 +#define Z_UTIL_X2_153 306 +#define Z_UTIL_X2_154 308 +#define Z_UTIL_X2_155 310 +#define Z_UTIL_X2_156 312 +#define Z_UTIL_X2_157 314 +#define Z_UTIL_X2_158 316 +#define Z_UTIL_X2_159 318 +#define Z_UTIL_X2_160 320 +#define Z_UTIL_X2_161 322 +#define Z_UTIL_X2_162 324 +#define Z_UTIL_X2_163 326 +#define Z_UTIL_X2_164 328 +#define Z_UTIL_X2_165 330 +#define Z_UTIL_X2_166 332 +#define Z_UTIL_X2_167 334 +#define Z_UTIL_X2_168 336 +#define Z_UTIL_X2_169 338 +#define Z_UTIL_X2_170 340 +#define Z_UTIL_X2_171 342 +#define Z_UTIL_X2_172 344 +#define Z_UTIL_X2_173 346 +#define Z_UTIL_X2_174 348 +#define Z_UTIL_X2_175 350 +#define Z_UTIL_X2_176 352 +#define Z_UTIL_X2_177 354 +#define Z_UTIL_X2_178 356 +#define Z_UTIL_X2_179 358 +#define Z_UTIL_X2_180 360 +#define Z_UTIL_X2_181 362 +#define Z_UTIL_X2_182 364 +#define Z_UTIL_X2_183 366 +#define Z_UTIL_X2_184 368 +#define Z_UTIL_X2_185 370 +#define Z_UTIL_X2_186 372 +#define Z_UTIL_X2_187 374 +#define Z_UTIL_X2_188 376 +#define Z_UTIL_X2_189 378 +#define Z_UTIL_X2_190 380 +#define Z_UTIL_X2_191 382 +#define Z_UTIL_X2_192 384 +#define Z_UTIL_X2_193 386 +#define Z_UTIL_X2_194 388 +#define Z_UTIL_X2_195 390 +#define Z_UTIL_X2_196 392 +#define Z_UTIL_X2_197 394 +#define Z_UTIL_X2_198 396 +#define Z_UTIL_X2_199 398 +#define Z_UTIL_X2_200 400 +#define Z_UTIL_X2_201 402 +#define Z_UTIL_X2_202 404 +#define Z_UTIL_X2_203 406 +#define Z_UTIL_X2_204 408 +#define Z_UTIL_X2_205 410 +#define Z_UTIL_X2_206 412 +#define Z_UTIL_X2_207 414 +#define Z_UTIL_X2_208 416 +#define Z_UTIL_X2_209 418 +#define Z_UTIL_X2_210 420 +#define Z_UTIL_X2_211 422 +#define Z_UTIL_X2_212 424 +#define Z_UTIL_X2_213 426 +#define Z_UTIL_X2_214 428 +#define Z_UTIL_X2_215 430 +#define Z_UTIL_X2_216 432 +#define Z_UTIL_X2_217 434 +#define Z_UTIL_X2_218 436 +#define Z_UTIL_X2_219 438 +#define Z_UTIL_X2_220 440 +#define Z_UTIL_X2_221 442 +#define Z_UTIL_X2_222 444 +#define Z_UTIL_X2_223 446 +#define Z_UTIL_X2_224 448 +#define Z_UTIL_X2_225 450 +#define Z_UTIL_X2_226 452 +#define Z_UTIL_X2_227 454 +#define Z_UTIL_X2_228 456 +#define Z_UTIL_X2_229 458 +#define Z_UTIL_X2_230 460 +#define Z_UTIL_X2_231 462 +#define Z_UTIL_X2_232 464 +#define Z_UTIL_X2_233 466 +#define Z_UTIL_X2_234 468 +#define Z_UTIL_X2_235 470 +#define Z_UTIL_X2_236 472 +#define Z_UTIL_X2_237 474 +#define Z_UTIL_X2_238 476 +#define Z_UTIL_X2_239 478 +#define Z_UTIL_X2_240 480 +#define Z_UTIL_X2_241 482 +#define Z_UTIL_X2_242 484 +#define Z_UTIL_X2_243 486 +#define Z_UTIL_X2_244 488 +#define Z_UTIL_X2_245 490 +#define Z_UTIL_X2_246 492 +#define Z_UTIL_X2_247 494 +#define Z_UTIL_X2_248 496 +#define Z_UTIL_X2_249 498 +#define Z_UTIL_X2_250 500 +#define Z_UTIL_X2_251 502 +#define Z_UTIL_X2_252 504 +#define Z_UTIL_X2_253 506 +#define Z_UTIL_X2_254 508 +#define Z_UTIL_X2_255 510 +#define Z_UTIL_X2_256 512 +#define Z_UTIL_X2_257 514 +#define Z_UTIL_X2_258 516 +#define Z_UTIL_X2_259 518 +#define Z_UTIL_X2_260 520 +#define Z_UTIL_X2_261 522 +#define Z_UTIL_X2_262 524 +#define Z_UTIL_X2_263 526 +#define Z_UTIL_X2_264 528 +#define Z_UTIL_X2_265 530 +#define Z_UTIL_X2_266 532 +#define Z_UTIL_X2_267 534 +#define Z_UTIL_X2_268 536 +#define Z_UTIL_X2_269 538 +#define Z_UTIL_X2_270 540 +#define Z_UTIL_X2_271 542 +#define Z_UTIL_X2_272 544 +#define Z_UTIL_X2_273 546 +#define Z_UTIL_X2_274 548 +#define Z_UTIL_X2_275 550 +#define Z_UTIL_X2_276 552 +#define Z_UTIL_X2_277 554 +#define Z_UTIL_X2_278 556 +#define Z_UTIL_X2_279 558 +#define Z_UTIL_X2_280 560 +#define Z_UTIL_X2_281 562 +#define Z_UTIL_X2_282 564 +#define Z_UTIL_X2_283 566 +#define Z_UTIL_X2_284 568 +#define Z_UTIL_X2_285 570 +#define Z_UTIL_X2_286 572 +#define Z_UTIL_X2_287 574 +#define Z_UTIL_X2_288 576 +#define Z_UTIL_X2_289 578 +#define Z_UTIL_X2_290 580 +#define Z_UTIL_X2_291 582 +#define Z_UTIL_X2_292 584 +#define Z_UTIL_X2_293 586 +#define Z_UTIL_X2_294 588 +#define Z_UTIL_X2_295 590 +#define Z_UTIL_X2_296 592 +#define Z_UTIL_X2_297 594 +#define Z_UTIL_X2_298 596 +#define Z_UTIL_X2_299 598 +#define Z_UTIL_X2_300 600 +#define Z_UTIL_X2_301 602 +#define Z_UTIL_X2_302 604 +#define Z_UTIL_X2_303 606 +#define Z_UTIL_X2_304 608 +#define Z_UTIL_X2_305 610 +#define Z_UTIL_X2_306 612 +#define Z_UTIL_X2_307 614 +#define Z_UTIL_X2_308 616 +#define Z_UTIL_X2_309 618 +#define Z_UTIL_X2_310 620 +#define Z_UTIL_X2_311 622 +#define Z_UTIL_X2_312 624 +#define Z_UTIL_X2_313 626 +#define Z_UTIL_X2_314 628 +#define Z_UTIL_X2_315 630 +#define Z_UTIL_X2_316 632 +#define Z_UTIL_X2_317 634 +#define Z_UTIL_X2_318 636 +#define Z_UTIL_X2_319 638 +#define Z_UTIL_X2_320 640 +#define Z_UTIL_X2_321 642 +#define Z_UTIL_X2_322 644 +#define Z_UTIL_X2_323 646 +#define Z_UTIL_X2_324 648 +#define Z_UTIL_X2_325 650 +#define Z_UTIL_X2_326 652 +#define Z_UTIL_X2_327 654 +#define Z_UTIL_X2_328 656 +#define Z_UTIL_X2_329 658 +#define Z_UTIL_X2_330 660 +#define Z_UTIL_X2_331 662 +#define Z_UTIL_X2_332 664 +#define Z_UTIL_X2_333 666 +#define Z_UTIL_X2_334 668 +#define Z_UTIL_X2_335 670 +#define Z_UTIL_X2_336 672 +#define Z_UTIL_X2_337 674 +#define Z_UTIL_X2_338 676 +#define Z_UTIL_X2_339 678 +#define Z_UTIL_X2_340 680 +#define Z_UTIL_X2_341 682 +#define Z_UTIL_X2_342 684 +#define Z_UTIL_X2_343 686 +#define Z_UTIL_X2_344 688 +#define Z_UTIL_X2_345 690 +#define Z_UTIL_X2_346 692 +#define Z_UTIL_X2_347 694 +#define Z_UTIL_X2_348 696 +#define Z_UTIL_X2_349 698 +#define Z_UTIL_X2_350 700 +#define Z_UTIL_X2_351 702 +#define Z_UTIL_X2_352 704 +#define Z_UTIL_X2_353 706 +#define Z_UTIL_X2_354 708 +#define Z_UTIL_X2_355 710 +#define Z_UTIL_X2_356 712 +#define Z_UTIL_X2_357 714 +#define Z_UTIL_X2_358 716 +#define Z_UTIL_X2_359 718 +#define Z_UTIL_X2_360 720 +#define Z_UTIL_X2_361 722 +#define Z_UTIL_X2_362 724 +#define Z_UTIL_X2_363 726 +#define Z_UTIL_X2_364 728 +#define Z_UTIL_X2_365 730 +#define Z_UTIL_X2_366 732 +#define Z_UTIL_X2_367 734 +#define Z_UTIL_X2_368 736 +#define Z_UTIL_X2_369 738 +#define Z_UTIL_X2_370 740 +#define Z_UTIL_X2_371 742 +#define Z_UTIL_X2_372 744 +#define Z_UTIL_X2_373 746 +#define Z_UTIL_X2_374 748 +#define Z_UTIL_X2_375 750 +#define Z_UTIL_X2_376 752 +#define Z_UTIL_X2_377 754 +#define Z_UTIL_X2_378 756 +#define Z_UTIL_X2_379 758 +#define Z_UTIL_X2_380 760 +#define Z_UTIL_X2_381 762 +#define Z_UTIL_X2_382 764 +#define Z_UTIL_X2_383 766 +#define Z_UTIL_X2_384 768 +#define Z_UTIL_X2_385 770 +#define Z_UTIL_X2_386 772 +#define Z_UTIL_X2_387 774 +#define Z_UTIL_X2_388 776 +#define Z_UTIL_X2_389 778 +#define Z_UTIL_X2_390 780 +#define Z_UTIL_X2_391 782 +#define Z_UTIL_X2_392 784 +#define Z_UTIL_X2_393 786 +#define Z_UTIL_X2_394 788 +#define Z_UTIL_X2_395 790 +#define Z_UTIL_X2_396 792 +#define Z_UTIL_X2_397 794 +#define Z_UTIL_X2_398 796 +#define Z_UTIL_X2_399 798 +#define Z_UTIL_X2_400 800 +#define Z_UTIL_X2_401 802 +#define Z_UTIL_X2_402 804 +#define Z_UTIL_X2_403 806 +#define Z_UTIL_X2_404 808 +#define Z_UTIL_X2_405 810 +#define Z_UTIL_X2_406 812 +#define Z_UTIL_X2_407 814 +#define Z_UTIL_X2_408 816 +#define Z_UTIL_X2_409 818 +#define Z_UTIL_X2_410 820 +#define Z_UTIL_X2_411 822 +#define Z_UTIL_X2_412 824 +#define Z_UTIL_X2_413 826 +#define Z_UTIL_X2_414 828 +#define Z_UTIL_X2_415 830 +#define Z_UTIL_X2_416 832 +#define Z_UTIL_X2_417 834 +#define Z_UTIL_X2_418 836 +#define Z_UTIL_X2_419 838 +#define Z_UTIL_X2_420 840 +#define Z_UTIL_X2_421 842 +#define Z_UTIL_X2_422 844 +#define Z_UTIL_X2_423 846 +#define Z_UTIL_X2_424 848 +#define Z_UTIL_X2_425 850 +#define Z_UTIL_X2_426 852 +#define Z_UTIL_X2_427 854 +#define Z_UTIL_X2_428 856 +#define Z_UTIL_X2_429 858 +#define Z_UTIL_X2_430 860 +#define Z_UTIL_X2_431 862 +#define Z_UTIL_X2_432 864 +#define Z_UTIL_X2_433 866 +#define Z_UTIL_X2_434 868 +#define Z_UTIL_X2_435 870 +#define Z_UTIL_X2_436 872 +#define Z_UTIL_X2_437 874 +#define Z_UTIL_X2_438 876 +#define Z_UTIL_X2_439 878 +#define Z_UTIL_X2_440 880 +#define Z_UTIL_X2_441 882 +#define Z_UTIL_X2_442 884 +#define Z_UTIL_X2_443 886 +#define Z_UTIL_X2_444 888 +#define Z_UTIL_X2_445 890 +#define Z_UTIL_X2_446 892 +#define Z_UTIL_X2_447 894 +#define Z_UTIL_X2_448 896 +#define Z_UTIL_X2_449 898 +#define Z_UTIL_X2_450 900 +#define Z_UTIL_X2_451 902 +#define Z_UTIL_X2_452 904 +#define Z_UTIL_X2_453 906 +#define Z_UTIL_X2_454 908 +#define Z_UTIL_X2_455 910 +#define Z_UTIL_X2_456 912 +#define Z_UTIL_X2_457 914 +#define Z_UTIL_X2_458 916 +#define Z_UTIL_X2_459 918 +#define Z_UTIL_X2_460 920 +#define Z_UTIL_X2_461 922 +#define Z_UTIL_X2_462 924 +#define Z_UTIL_X2_463 926 +#define Z_UTIL_X2_464 928 +#define Z_UTIL_X2_465 930 +#define Z_UTIL_X2_466 932 +#define Z_UTIL_X2_467 934 +#define Z_UTIL_X2_468 936 +#define Z_UTIL_X2_469 938 +#define Z_UTIL_X2_470 940 +#define Z_UTIL_X2_471 942 +#define Z_UTIL_X2_472 944 +#define Z_UTIL_X2_473 946 +#define Z_UTIL_X2_474 948 +#define Z_UTIL_X2_475 950 +#define Z_UTIL_X2_476 952 +#define Z_UTIL_X2_477 954 +#define Z_UTIL_X2_478 956 +#define Z_UTIL_X2_479 958 +#define Z_UTIL_X2_480 960 +#define Z_UTIL_X2_481 962 +#define Z_UTIL_X2_482 964 +#define Z_UTIL_X2_483 966 +#define Z_UTIL_X2_484 968 +#define Z_UTIL_X2_485 970 +#define Z_UTIL_X2_486 972 +#define Z_UTIL_X2_487 974 +#define Z_UTIL_X2_488 976 +#define Z_UTIL_X2_489 978 +#define Z_UTIL_X2_490 980 +#define Z_UTIL_X2_491 982 +#define Z_UTIL_X2_492 984 +#define Z_UTIL_X2_493 986 +#define Z_UTIL_X2_494 988 +#define Z_UTIL_X2_495 990 +#define Z_UTIL_X2_496 992 +#define Z_UTIL_X2_497 994 +#define Z_UTIL_X2_498 996 +#define Z_UTIL_X2_499 998 +#define Z_UTIL_X2_500 1000 +#define Z_UTIL_X2_501 1002 +#define Z_UTIL_X2_502 1004 +#define Z_UTIL_X2_503 1006 +#define Z_UTIL_X2_504 1008 +#define Z_UTIL_X2_505 1010 +#define Z_UTIL_X2_506 1012 +#define Z_UTIL_X2_507 1014 +#define Z_UTIL_X2_508 1016 +#define Z_UTIL_X2_509 1018 +#define Z_UTIL_X2_510 1020 +#define Z_UTIL_X2_511 1022 +#define Z_UTIL_X2_512 1024 +#define Z_UTIL_X2_513 1026 +#define Z_UTIL_X2_514 1028 +#define Z_UTIL_X2_515 1030 +#define Z_UTIL_X2_516 1032 +#define Z_UTIL_X2_517 1034 +#define Z_UTIL_X2_518 1036 +#define Z_UTIL_X2_519 1038 +#define Z_UTIL_X2_520 1040 +#define Z_UTIL_X2_521 1042 +#define Z_UTIL_X2_522 1044 +#define Z_UTIL_X2_523 1046 +#define Z_UTIL_X2_524 1048 +#define Z_UTIL_X2_525 1050 +#define Z_UTIL_X2_526 1052 +#define Z_UTIL_X2_527 1054 +#define Z_UTIL_X2_528 1056 +#define Z_UTIL_X2_529 1058 +#define Z_UTIL_X2_530 1060 +#define Z_UTIL_X2_531 1062 +#define Z_UTIL_X2_532 1064 +#define Z_UTIL_X2_533 1066 +#define Z_UTIL_X2_534 1068 +#define Z_UTIL_X2_535 1070 +#define Z_UTIL_X2_536 1072 +#define Z_UTIL_X2_537 1074 +#define Z_UTIL_X2_538 1076 +#define Z_UTIL_X2_539 1078 +#define Z_UTIL_X2_540 1080 +#define Z_UTIL_X2_541 1082 +#define Z_UTIL_X2_542 1084 +#define Z_UTIL_X2_543 1086 +#define Z_UTIL_X2_544 1088 +#define Z_UTIL_X2_545 1090 +#define Z_UTIL_X2_546 1092 +#define Z_UTIL_X2_547 1094 +#define Z_UTIL_X2_548 1096 +#define Z_UTIL_X2_549 1098 +#define Z_UTIL_X2_550 1100 +#define Z_UTIL_X2_551 1102 +#define Z_UTIL_X2_552 1104 +#define Z_UTIL_X2_553 1106 +#define Z_UTIL_X2_554 1108 +#define Z_UTIL_X2_555 1110 +#define Z_UTIL_X2_556 1112 +#define Z_UTIL_X2_557 1114 +#define Z_UTIL_X2_558 1116 +#define Z_UTIL_X2_559 1118 +#define Z_UTIL_X2_560 1120 +#define Z_UTIL_X2_561 1122 +#define Z_UTIL_X2_562 1124 +#define Z_UTIL_X2_563 1126 +#define Z_UTIL_X2_564 1128 +#define Z_UTIL_X2_565 1130 +#define Z_UTIL_X2_566 1132 +#define Z_UTIL_X2_567 1134 +#define Z_UTIL_X2_568 1136 +#define Z_UTIL_X2_569 1138 +#define Z_UTIL_X2_570 1140 +#define Z_UTIL_X2_571 1142 +#define Z_UTIL_X2_572 1144 +#define Z_UTIL_X2_573 1146 +#define Z_UTIL_X2_574 1148 +#define Z_UTIL_X2_575 1150 +#define Z_UTIL_X2_576 1152 +#define Z_UTIL_X2_577 1154 +#define Z_UTIL_X2_578 1156 +#define Z_UTIL_X2_579 1158 +#define Z_UTIL_X2_580 1160 +#define Z_UTIL_X2_581 1162 +#define Z_UTIL_X2_582 1164 +#define Z_UTIL_X2_583 1166 +#define Z_UTIL_X2_584 1168 +#define Z_UTIL_X2_585 1170 +#define Z_UTIL_X2_586 1172 +#define Z_UTIL_X2_587 1174 +#define Z_UTIL_X2_588 1176 +#define Z_UTIL_X2_589 1178 +#define Z_UTIL_X2_590 1180 +#define Z_UTIL_X2_591 1182 +#define Z_UTIL_X2_592 1184 +#define Z_UTIL_X2_593 1186 +#define Z_UTIL_X2_594 1188 +#define Z_UTIL_X2_595 1190 +#define Z_UTIL_X2_596 1192 +#define Z_UTIL_X2_597 1194 +#define Z_UTIL_X2_598 1196 +#define Z_UTIL_X2_599 1198 +#define Z_UTIL_X2_600 1200 +#define Z_UTIL_X2_601 1202 +#define Z_UTIL_X2_602 1204 +#define Z_UTIL_X2_603 1206 +#define Z_UTIL_X2_604 1208 +#define Z_UTIL_X2_605 1210 +#define Z_UTIL_X2_606 1212 +#define Z_UTIL_X2_607 1214 +#define Z_UTIL_X2_608 1216 +#define Z_UTIL_X2_609 1218 +#define Z_UTIL_X2_610 1220 +#define Z_UTIL_X2_611 1222 +#define Z_UTIL_X2_612 1224 +#define Z_UTIL_X2_613 1226 +#define Z_UTIL_X2_614 1228 +#define Z_UTIL_X2_615 1230 +#define Z_UTIL_X2_616 1232 +#define Z_UTIL_X2_617 1234 +#define Z_UTIL_X2_618 1236 +#define Z_UTIL_X2_619 1238 +#define Z_UTIL_X2_620 1240 +#define Z_UTIL_X2_621 1242 +#define Z_UTIL_X2_622 1244 +#define Z_UTIL_X2_623 1246 +#define Z_UTIL_X2_624 1248 +#define Z_UTIL_X2_625 1250 +#define Z_UTIL_X2_626 1252 +#define Z_UTIL_X2_627 1254 +#define Z_UTIL_X2_628 1256 +#define Z_UTIL_X2_629 1258 +#define Z_UTIL_X2_630 1260 +#define Z_UTIL_X2_631 1262 +#define Z_UTIL_X2_632 1264 +#define Z_UTIL_X2_633 1266 +#define Z_UTIL_X2_634 1268 +#define Z_UTIL_X2_635 1270 +#define Z_UTIL_X2_636 1272 +#define Z_UTIL_X2_637 1274 +#define Z_UTIL_X2_638 1276 +#define Z_UTIL_X2_639 1278 +#define Z_UTIL_X2_640 1280 +#define Z_UTIL_X2_641 1282 +#define Z_UTIL_X2_642 1284 +#define Z_UTIL_X2_643 1286 +#define Z_UTIL_X2_644 1288 +#define Z_UTIL_X2_645 1290 +#define Z_UTIL_X2_646 1292 +#define Z_UTIL_X2_647 1294 +#define Z_UTIL_X2_648 1296 +#define Z_UTIL_X2_649 1298 +#define Z_UTIL_X2_650 1300 +#define Z_UTIL_X2_651 1302 +#define Z_UTIL_X2_652 1304 +#define Z_UTIL_X2_653 1306 +#define Z_UTIL_X2_654 1308 +#define Z_UTIL_X2_655 1310 +#define Z_UTIL_X2_656 1312 +#define Z_UTIL_X2_657 1314 +#define Z_UTIL_X2_658 1316 +#define Z_UTIL_X2_659 1318 +#define Z_UTIL_X2_660 1320 +#define Z_UTIL_X2_661 1322 +#define Z_UTIL_X2_662 1324 +#define Z_UTIL_X2_663 1326 +#define Z_UTIL_X2_664 1328 +#define Z_UTIL_X2_665 1330 +#define Z_UTIL_X2_666 1332 +#define Z_UTIL_X2_667 1334 +#define Z_UTIL_X2_668 1336 +#define Z_UTIL_X2_669 1338 +#define Z_UTIL_X2_670 1340 +#define Z_UTIL_X2_671 1342 +#define Z_UTIL_X2_672 1344 +#define Z_UTIL_X2_673 1346 +#define Z_UTIL_X2_674 1348 +#define Z_UTIL_X2_675 1350 +#define Z_UTIL_X2_676 1352 +#define Z_UTIL_X2_677 1354 +#define Z_UTIL_X2_678 1356 +#define Z_UTIL_X2_679 1358 +#define Z_UTIL_X2_680 1360 +#define Z_UTIL_X2_681 1362 +#define Z_UTIL_X2_682 1364 +#define Z_UTIL_X2_683 1366 +#define Z_UTIL_X2_684 1368 +#define Z_UTIL_X2_685 1370 +#define Z_UTIL_X2_686 1372 +#define Z_UTIL_X2_687 1374 +#define Z_UTIL_X2_688 1376 +#define Z_UTIL_X2_689 1378 +#define Z_UTIL_X2_690 1380 +#define Z_UTIL_X2_691 1382 +#define Z_UTIL_X2_692 1384 +#define Z_UTIL_X2_693 1386 +#define Z_UTIL_X2_694 1388 +#define Z_UTIL_X2_695 1390 +#define Z_UTIL_X2_696 1392 +#define Z_UTIL_X2_697 1394 +#define Z_UTIL_X2_698 1396 +#define Z_UTIL_X2_699 1398 +#define Z_UTIL_X2_700 1400 +#define Z_UTIL_X2_701 1402 +#define Z_UTIL_X2_702 1404 +#define Z_UTIL_X2_703 1406 +#define Z_UTIL_X2_704 1408 +#define Z_UTIL_X2_705 1410 +#define Z_UTIL_X2_706 1412 +#define Z_UTIL_X2_707 1414 +#define Z_UTIL_X2_708 1416 +#define Z_UTIL_X2_709 1418 +#define Z_UTIL_X2_710 1420 +#define Z_UTIL_X2_711 1422 +#define Z_UTIL_X2_712 1424 +#define Z_UTIL_X2_713 1426 +#define Z_UTIL_X2_714 1428 +#define Z_UTIL_X2_715 1430 +#define Z_UTIL_X2_716 1432 +#define Z_UTIL_X2_717 1434 +#define Z_UTIL_X2_718 1436 +#define Z_UTIL_X2_719 1438 +#define Z_UTIL_X2_720 1440 +#define Z_UTIL_X2_721 1442 +#define Z_UTIL_X2_722 1444 +#define Z_UTIL_X2_723 1446 +#define Z_UTIL_X2_724 1448 +#define Z_UTIL_X2_725 1450 +#define Z_UTIL_X2_726 1452 +#define Z_UTIL_X2_727 1454 +#define Z_UTIL_X2_728 1456 +#define Z_UTIL_X2_729 1458 +#define Z_UTIL_X2_730 1460 +#define Z_UTIL_X2_731 1462 +#define Z_UTIL_X2_732 1464 +#define Z_UTIL_X2_733 1466 +#define Z_UTIL_X2_734 1468 +#define Z_UTIL_X2_735 1470 +#define Z_UTIL_X2_736 1472 +#define Z_UTIL_X2_737 1474 +#define Z_UTIL_X2_738 1476 +#define Z_UTIL_X2_739 1478 +#define Z_UTIL_X2_740 1480 +#define Z_UTIL_X2_741 1482 +#define Z_UTIL_X2_742 1484 +#define Z_UTIL_X2_743 1486 +#define Z_UTIL_X2_744 1488 +#define Z_UTIL_X2_745 1490 +#define Z_UTIL_X2_746 1492 +#define Z_UTIL_X2_747 1494 +#define Z_UTIL_X2_748 1496 +#define Z_UTIL_X2_749 1498 +#define Z_UTIL_X2_750 1500 +#define Z_UTIL_X2_751 1502 +#define Z_UTIL_X2_752 1504 +#define Z_UTIL_X2_753 1506 +#define Z_UTIL_X2_754 1508 +#define Z_UTIL_X2_755 1510 +#define Z_UTIL_X2_756 1512 +#define Z_UTIL_X2_757 1514 +#define Z_UTIL_X2_758 1516 +#define Z_UTIL_X2_759 1518 +#define Z_UTIL_X2_760 1520 +#define Z_UTIL_X2_761 1522 +#define Z_UTIL_X2_762 1524 +#define Z_UTIL_X2_763 1526 +#define Z_UTIL_X2_764 1528 +#define Z_UTIL_X2_765 1530 +#define Z_UTIL_X2_766 1532 +#define Z_UTIL_X2_767 1534 +#define Z_UTIL_X2_768 1536 +#define Z_UTIL_X2_769 1538 +#define Z_UTIL_X2_770 1540 +#define Z_UTIL_X2_771 1542 +#define Z_UTIL_X2_772 1544 +#define Z_UTIL_X2_773 1546 +#define Z_UTIL_X2_774 1548 +#define Z_UTIL_X2_775 1550 +#define Z_UTIL_X2_776 1552 +#define Z_UTIL_X2_777 1554 +#define Z_UTIL_X2_778 1556 +#define Z_UTIL_X2_779 1558 +#define Z_UTIL_X2_780 1560 +#define Z_UTIL_X2_781 1562 +#define Z_UTIL_X2_782 1564 +#define Z_UTIL_X2_783 1566 +#define Z_UTIL_X2_784 1568 +#define Z_UTIL_X2_785 1570 +#define Z_UTIL_X2_786 1572 +#define Z_UTIL_X2_787 1574 +#define Z_UTIL_X2_788 1576 +#define Z_UTIL_X2_789 1578 +#define Z_UTIL_X2_790 1580 +#define Z_UTIL_X2_791 1582 +#define Z_UTIL_X2_792 1584 +#define Z_UTIL_X2_793 1586 +#define Z_UTIL_X2_794 1588 +#define Z_UTIL_X2_795 1590 +#define Z_UTIL_X2_796 1592 +#define Z_UTIL_X2_797 1594 +#define Z_UTIL_X2_798 1596 +#define Z_UTIL_X2_799 1598 +#define Z_UTIL_X2_800 1600 +#define Z_UTIL_X2_801 1602 +#define Z_UTIL_X2_802 1604 +#define Z_UTIL_X2_803 1606 +#define Z_UTIL_X2_804 1608 +#define Z_UTIL_X2_805 1610 +#define Z_UTIL_X2_806 1612 +#define Z_UTIL_X2_807 1614 +#define Z_UTIL_X2_808 1616 +#define Z_UTIL_X2_809 1618 +#define Z_UTIL_X2_810 1620 +#define Z_UTIL_X2_811 1622 +#define Z_UTIL_X2_812 1624 +#define Z_UTIL_X2_813 1626 +#define Z_UTIL_X2_814 1628 +#define Z_UTIL_X2_815 1630 +#define Z_UTIL_X2_816 1632 +#define Z_UTIL_X2_817 1634 +#define Z_UTIL_X2_818 1636 +#define Z_UTIL_X2_819 1638 +#define Z_UTIL_X2_820 1640 +#define Z_UTIL_X2_821 1642 +#define Z_UTIL_X2_822 1644 +#define Z_UTIL_X2_823 1646 +#define Z_UTIL_X2_824 1648 +#define Z_UTIL_X2_825 1650 +#define Z_UTIL_X2_826 1652 +#define Z_UTIL_X2_827 1654 +#define Z_UTIL_X2_828 1656 +#define Z_UTIL_X2_829 1658 +#define Z_UTIL_X2_830 1660 +#define Z_UTIL_X2_831 1662 +#define Z_UTIL_X2_832 1664 +#define Z_UTIL_X2_833 1666 +#define Z_UTIL_X2_834 1668 +#define Z_UTIL_X2_835 1670 +#define Z_UTIL_X2_836 1672 +#define Z_UTIL_X2_837 1674 +#define Z_UTIL_X2_838 1676 +#define Z_UTIL_X2_839 1678 +#define Z_UTIL_X2_840 1680 +#define Z_UTIL_X2_841 1682 +#define Z_UTIL_X2_842 1684 +#define Z_UTIL_X2_843 1686 +#define Z_UTIL_X2_844 1688 +#define Z_UTIL_X2_845 1690 +#define Z_UTIL_X2_846 1692 +#define Z_UTIL_X2_847 1694 +#define Z_UTIL_X2_848 1696 +#define Z_UTIL_X2_849 1698 +#define Z_UTIL_X2_850 1700 +#define Z_UTIL_X2_851 1702 +#define Z_UTIL_X2_852 1704 +#define Z_UTIL_X2_853 1706 +#define Z_UTIL_X2_854 1708 +#define Z_UTIL_X2_855 1710 +#define Z_UTIL_X2_856 1712 +#define Z_UTIL_X2_857 1714 +#define Z_UTIL_X2_858 1716 +#define Z_UTIL_X2_859 1718 +#define Z_UTIL_X2_860 1720 +#define Z_UTIL_X2_861 1722 +#define Z_UTIL_X2_862 1724 +#define Z_UTIL_X2_863 1726 +#define Z_UTIL_X2_864 1728 +#define Z_UTIL_X2_865 1730 +#define Z_UTIL_X2_866 1732 +#define Z_UTIL_X2_867 1734 +#define Z_UTIL_X2_868 1736 +#define Z_UTIL_X2_869 1738 +#define Z_UTIL_X2_870 1740 +#define Z_UTIL_X2_871 1742 +#define Z_UTIL_X2_872 1744 +#define Z_UTIL_X2_873 1746 +#define Z_UTIL_X2_874 1748 +#define Z_UTIL_X2_875 1750 +#define Z_UTIL_X2_876 1752 +#define Z_UTIL_X2_877 1754 +#define Z_UTIL_X2_878 1756 +#define Z_UTIL_X2_879 1758 +#define Z_UTIL_X2_880 1760 +#define Z_UTIL_X2_881 1762 +#define Z_UTIL_X2_882 1764 +#define Z_UTIL_X2_883 1766 +#define Z_UTIL_X2_884 1768 +#define Z_UTIL_X2_885 1770 +#define Z_UTIL_X2_886 1772 +#define Z_UTIL_X2_887 1774 +#define Z_UTIL_X2_888 1776 +#define Z_UTIL_X2_889 1778 +#define Z_UTIL_X2_890 1780 +#define Z_UTIL_X2_891 1782 +#define Z_UTIL_X2_892 1784 +#define Z_UTIL_X2_893 1786 +#define Z_UTIL_X2_894 1788 +#define Z_UTIL_X2_895 1790 +#define Z_UTIL_X2_896 1792 +#define Z_UTIL_X2_897 1794 +#define Z_UTIL_X2_898 1796 +#define Z_UTIL_X2_899 1798 +#define Z_UTIL_X2_900 1800 +#define Z_UTIL_X2_901 1802 +#define Z_UTIL_X2_902 1804 +#define Z_UTIL_X2_903 1806 +#define Z_UTIL_X2_904 1808 +#define Z_UTIL_X2_905 1810 +#define Z_UTIL_X2_906 1812 +#define Z_UTIL_X2_907 1814 +#define Z_UTIL_X2_908 1816 +#define Z_UTIL_X2_909 1818 +#define Z_UTIL_X2_910 1820 +#define Z_UTIL_X2_911 1822 +#define Z_UTIL_X2_912 1824 +#define Z_UTIL_X2_913 1826 +#define Z_UTIL_X2_914 1828 +#define Z_UTIL_X2_915 1830 +#define Z_UTIL_X2_916 1832 +#define Z_UTIL_X2_917 1834 +#define Z_UTIL_X2_918 1836 +#define Z_UTIL_X2_919 1838 +#define Z_UTIL_X2_920 1840 +#define Z_UTIL_X2_921 1842 +#define Z_UTIL_X2_922 1844 +#define Z_UTIL_X2_923 1846 +#define Z_UTIL_X2_924 1848 +#define Z_UTIL_X2_925 1850 +#define Z_UTIL_X2_926 1852 +#define Z_UTIL_X2_927 1854 +#define Z_UTIL_X2_928 1856 +#define Z_UTIL_X2_929 1858 +#define Z_UTIL_X2_930 1860 +#define Z_UTIL_X2_931 1862 +#define Z_UTIL_X2_932 1864 +#define Z_UTIL_X2_933 1866 +#define Z_UTIL_X2_934 1868 +#define Z_UTIL_X2_935 1870 +#define Z_UTIL_X2_936 1872 +#define Z_UTIL_X2_937 1874 +#define Z_UTIL_X2_938 1876 +#define Z_UTIL_X2_939 1878 +#define Z_UTIL_X2_940 1880 +#define Z_UTIL_X2_941 1882 +#define Z_UTIL_X2_942 1884 +#define Z_UTIL_X2_943 1886 +#define Z_UTIL_X2_944 1888 +#define Z_UTIL_X2_945 1890 +#define Z_UTIL_X2_946 1892 +#define Z_UTIL_X2_947 1894 +#define Z_UTIL_X2_948 1896 +#define Z_UTIL_X2_949 1898 +#define Z_UTIL_X2_950 1900 +#define Z_UTIL_X2_951 1902 +#define Z_UTIL_X2_952 1904 +#define Z_UTIL_X2_953 1906 +#define Z_UTIL_X2_954 1908 +#define Z_UTIL_X2_955 1910 +#define Z_UTIL_X2_956 1912 +#define Z_UTIL_X2_957 1914 +#define Z_UTIL_X2_958 1916 +#define Z_UTIL_X2_959 1918 +#define Z_UTIL_X2_960 1920 +#define Z_UTIL_X2_961 1922 +#define Z_UTIL_X2_962 1924 +#define Z_UTIL_X2_963 1926 +#define Z_UTIL_X2_964 1928 +#define Z_UTIL_X2_965 1930 +#define Z_UTIL_X2_966 1932 +#define Z_UTIL_X2_967 1934 +#define Z_UTIL_X2_968 1936 +#define Z_UTIL_X2_969 1938 +#define Z_UTIL_X2_970 1940 +#define Z_UTIL_X2_971 1942 +#define Z_UTIL_X2_972 1944 +#define Z_UTIL_X2_973 1946 +#define Z_UTIL_X2_974 1948 +#define Z_UTIL_X2_975 1950 +#define Z_UTIL_X2_976 1952 +#define Z_UTIL_X2_977 1954 +#define Z_UTIL_X2_978 1956 +#define Z_UTIL_X2_979 1958 +#define Z_UTIL_X2_980 1960 +#define Z_UTIL_X2_981 1962 +#define Z_UTIL_X2_982 1964 +#define Z_UTIL_X2_983 1966 +#define Z_UTIL_X2_984 1968 +#define Z_UTIL_X2_985 1970 +#define Z_UTIL_X2_986 1972 +#define Z_UTIL_X2_987 1974 +#define Z_UTIL_X2_988 1976 +#define Z_UTIL_X2_989 1978 +#define Z_UTIL_X2_990 1980 +#define Z_UTIL_X2_991 1982 +#define Z_UTIL_X2_992 1984 +#define Z_UTIL_X2_993 1986 +#define Z_UTIL_X2_994 1988 +#define Z_UTIL_X2_995 1990 +#define Z_UTIL_X2_996 1992 +#define Z_UTIL_X2_997 1994 +#define Z_UTIL_X2_998 1996 +#define Z_UTIL_X2_999 1998 +#define Z_UTIL_X2_1000 2000 +#define Z_UTIL_X2_1001 2002 +#define Z_UTIL_X2_1002 2004 +#define Z_UTIL_X2_1003 2006 +#define Z_UTIL_X2_1004 2008 +#define Z_UTIL_X2_1005 2010 +#define Z_UTIL_X2_1006 2012 +#define Z_UTIL_X2_1007 2014 +#define Z_UTIL_X2_1008 2016 +#define Z_UTIL_X2_1009 2018 +#define Z_UTIL_X2_1010 2020 +#define Z_UTIL_X2_1011 2022 +#define Z_UTIL_X2_1012 2024 +#define Z_UTIL_X2_1013 2026 +#define Z_UTIL_X2_1014 2028 +#define Z_UTIL_X2_1015 2030 +#define Z_UTIL_X2_1016 2032 +#define Z_UTIL_X2_1017 2034 +#define Z_UTIL_X2_1018 2036 +#define Z_UTIL_X2_1019 2038 +#define Z_UTIL_X2_1020 2040 +#define Z_UTIL_X2_1021 2042 +#define Z_UTIL_X2_1022 2044 +#define Z_UTIL_X2_1023 2046 +#define Z_UTIL_X2_1024 2048 +#define Z_UTIL_X2_1025 2050 +#define Z_UTIL_X2_1026 2052 +#define Z_UTIL_X2_1027 2054 +#define Z_UTIL_X2_1028 2056 +#define Z_UTIL_X2_1029 2058 +#define Z_UTIL_X2_1030 2060 +#define Z_UTIL_X2_1031 2062 +#define Z_UTIL_X2_1032 2064 +#define Z_UTIL_X2_1033 2066 +#define Z_UTIL_X2_1034 2068 +#define Z_UTIL_X2_1035 2070 +#define Z_UTIL_X2_1036 2072 +#define Z_UTIL_X2_1037 2074 +#define Z_UTIL_X2_1038 2076 +#define Z_UTIL_X2_1039 2078 +#define Z_UTIL_X2_1040 2080 +#define Z_UTIL_X2_1041 2082 +#define Z_UTIL_X2_1042 2084 +#define Z_UTIL_X2_1043 2086 +#define Z_UTIL_X2_1044 2088 +#define Z_UTIL_X2_1045 2090 +#define Z_UTIL_X2_1046 2092 +#define Z_UTIL_X2_1047 2094 +#define Z_UTIL_X2_1048 2096 +#define Z_UTIL_X2_1049 2098 +#define Z_UTIL_X2_1050 2100 +#define Z_UTIL_X2_1051 2102 +#define Z_UTIL_X2_1052 2104 +#define Z_UTIL_X2_1053 2106 +#define Z_UTIL_X2_1054 2108 +#define Z_UTIL_X2_1055 2110 +#define Z_UTIL_X2_1056 2112 +#define Z_UTIL_X2_1057 2114 +#define Z_UTIL_X2_1058 2116 +#define Z_UTIL_X2_1059 2118 +#define Z_UTIL_X2_1060 2120 +#define Z_UTIL_X2_1061 2122 +#define Z_UTIL_X2_1062 2124 +#define Z_UTIL_X2_1063 2126 +#define Z_UTIL_X2_1064 2128 +#define Z_UTIL_X2_1065 2130 +#define Z_UTIL_X2_1066 2132 +#define Z_UTIL_X2_1067 2134 +#define Z_UTIL_X2_1068 2136 +#define Z_UTIL_X2_1069 2138 +#define Z_UTIL_X2_1070 2140 +#define Z_UTIL_X2_1071 2142 +#define Z_UTIL_X2_1072 2144 +#define Z_UTIL_X2_1073 2146 +#define Z_UTIL_X2_1074 2148 +#define Z_UTIL_X2_1075 2150 +#define Z_UTIL_X2_1076 2152 +#define Z_UTIL_X2_1077 2154 +#define Z_UTIL_X2_1078 2156 +#define Z_UTIL_X2_1079 2158 +#define Z_UTIL_X2_1080 2160 +#define Z_UTIL_X2_1081 2162 +#define Z_UTIL_X2_1082 2164 +#define Z_UTIL_X2_1083 2166 +#define Z_UTIL_X2_1084 2168 +#define Z_UTIL_X2_1085 2170 +#define Z_UTIL_X2_1086 2172 +#define Z_UTIL_X2_1087 2174 +#define Z_UTIL_X2_1088 2176 +#define Z_UTIL_X2_1089 2178 +#define Z_UTIL_X2_1090 2180 +#define Z_UTIL_X2_1091 2182 +#define Z_UTIL_X2_1092 2184 +#define Z_UTIL_X2_1093 2186 +#define Z_UTIL_X2_1094 2188 +#define Z_UTIL_X2_1095 2190 +#define Z_UTIL_X2_1096 2192 +#define Z_UTIL_X2_1097 2194 +#define Z_UTIL_X2_1098 2196 +#define Z_UTIL_X2_1099 2198 +#define Z_UTIL_X2_1100 2200 +#define Z_UTIL_X2_1101 2202 +#define Z_UTIL_X2_1102 2204 +#define Z_UTIL_X2_1103 2206 +#define Z_UTIL_X2_1104 2208 +#define Z_UTIL_X2_1105 2210 +#define Z_UTIL_X2_1106 2212 +#define Z_UTIL_X2_1107 2214 +#define Z_UTIL_X2_1108 2216 +#define Z_UTIL_X2_1109 2218 +#define Z_UTIL_X2_1110 2220 +#define Z_UTIL_X2_1111 2222 +#define Z_UTIL_X2_1112 2224 +#define Z_UTIL_X2_1113 2226 +#define Z_UTIL_X2_1114 2228 +#define Z_UTIL_X2_1115 2230 +#define Z_UTIL_X2_1116 2232 +#define Z_UTIL_X2_1117 2234 +#define Z_UTIL_X2_1118 2236 +#define Z_UTIL_X2_1119 2238 +#define Z_UTIL_X2_1120 2240 +#define Z_UTIL_X2_1121 2242 +#define Z_UTIL_X2_1122 2244 +#define Z_UTIL_X2_1123 2246 +#define Z_UTIL_X2_1124 2248 +#define Z_UTIL_X2_1125 2250 +#define Z_UTIL_X2_1126 2252 +#define Z_UTIL_X2_1127 2254 +#define Z_UTIL_X2_1128 2256 +#define Z_UTIL_X2_1129 2258 +#define Z_UTIL_X2_1130 2260 +#define Z_UTIL_X2_1131 2262 +#define Z_UTIL_X2_1132 2264 +#define Z_UTIL_X2_1133 2266 +#define Z_UTIL_X2_1134 2268 +#define Z_UTIL_X2_1135 2270 +#define Z_UTIL_X2_1136 2272 +#define Z_UTIL_X2_1137 2274 +#define Z_UTIL_X2_1138 2276 +#define Z_UTIL_X2_1139 2278 +#define Z_UTIL_X2_1140 2280 +#define Z_UTIL_X2_1141 2282 +#define Z_UTIL_X2_1142 2284 +#define Z_UTIL_X2_1143 2286 +#define Z_UTIL_X2_1144 2288 +#define Z_UTIL_X2_1145 2290 +#define Z_UTIL_X2_1146 2292 +#define Z_UTIL_X2_1147 2294 +#define Z_UTIL_X2_1148 2296 +#define Z_UTIL_X2_1149 2298 +#define Z_UTIL_X2_1150 2300 +#define Z_UTIL_X2_1151 2302 +#define Z_UTIL_X2_1152 2304 +#define Z_UTIL_X2_1153 2306 +#define Z_UTIL_X2_1154 2308 +#define Z_UTIL_X2_1155 2310 +#define Z_UTIL_X2_1156 2312 +#define Z_UTIL_X2_1157 2314 +#define Z_UTIL_X2_1158 2316 +#define Z_UTIL_X2_1159 2318 +#define Z_UTIL_X2_1160 2320 +#define Z_UTIL_X2_1161 2322 +#define Z_UTIL_X2_1162 2324 +#define Z_UTIL_X2_1163 2326 +#define Z_UTIL_X2_1164 2328 +#define Z_UTIL_X2_1165 2330 +#define Z_UTIL_X2_1166 2332 +#define Z_UTIL_X2_1167 2334 +#define Z_UTIL_X2_1168 2336 +#define Z_UTIL_X2_1169 2338 +#define Z_UTIL_X2_1170 2340 +#define Z_UTIL_X2_1171 2342 +#define Z_UTIL_X2_1172 2344 +#define Z_UTIL_X2_1173 2346 +#define Z_UTIL_X2_1174 2348 +#define Z_UTIL_X2_1175 2350 +#define Z_UTIL_X2_1176 2352 +#define Z_UTIL_X2_1177 2354 +#define Z_UTIL_X2_1178 2356 +#define Z_UTIL_X2_1179 2358 +#define Z_UTIL_X2_1180 2360 +#define Z_UTIL_X2_1181 2362 +#define Z_UTIL_X2_1182 2364 +#define Z_UTIL_X2_1183 2366 +#define Z_UTIL_X2_1184 2368 +#define Z_UTIL_X2_1185 2370 +#define Z_UTIL_X2_1186 2372 +#define Z_UTIL_X2_1187 2374 +#define Z_UTIL_X2_1188 2376 +#define Z_UTIL_X2_1189 2378 +#define Z_UTIL_X2_1190 2380 +#define Z_UTIL_X2_1191 2382 +#define Z_UTIL_X2_1192 2384 +#define Z_UTIL_X2_1193 2386 +#define Z_UTIL_X2_1194 2388 +#define Z_UTIL_X2_1195 2390 +#define Z_UTIL_X2_1196 2392 +#define Z_UTIL_X2_1197 2394 +#define Z_UTIL_X2_1198 2396 +#define Z_UTIL_X2_1199 2398 +#define Z_UTIL_X2_1200 2400 +#define Z_UTIL_X2_1201 2402 +#define Z_UTIL_X2_1202 2404 +#define Z_UTIL_X2_1203 2406 +#define Z_UTIL_X2_1204 2408 +#define Z_UTIL_X2_1205 2410 +#define Z_UTIL_X2_1206 2412 +#define Z_UTIL_X2_1207 2414 +#define Z_UTIL_X2_1208 2416 +#define Z_UTIL_X2_1209 2418 +#define Z_UTIL_X2_1210 2420 +#define Z_UTIL_X2_1211 2422 +#define Z_UTIL_X2_1212 2424 +#define Z_UTIL_X2_1213 2426 +#define Z_UTIL_X2_1214 2428 +#define Z_UTIL_X2_1215 2430 +#define Z_UTIL_X2_1216 2432 +#define Z_UTIL_X2_1217 2434 +#define Z_UTIL_X2_1218 2436 +#define Z_UTIL_X2_1219 2438 +#define Z_UTIL_X2_1220 2440 +#define Z_UTIL_X2_1221 2442 +#define Z_UTIL_X2_1222 2444 +#define Z_UTIL_X2_1223 2446 +#define Z_UTIL_X2_1224 2448 +#define Z_UTIL_X2_1225 2450 +#define Z_UTIL_X2_1226 2452 +#define Z_UTIL_X2_1227 2454 +#define Z_UTIL_X2_1228 2456 +#define Z_UTIL_X2_1229 2458 +#define Z_UTIL_X2_1230 2460 +#define Z_UTIL_X2_1231 2462 +#define Z_UTIL_X2_1232 2464 +#define Z_UTIL_X2_1233 2466 +#define Z_UTIL_X2_1234 2468 +#define Z_UTIL_X2_1235 2470 +#define Z_UTIL_X2_1236 2472 +#define Z_UTIL_X2_1237 2474 +#define Z_UTIL_X2_1238 2476 +#define Z_UTIL_X2_1239 2478 +#define Z_UTIL_X2_1240 2480 +#define Z_UTIL_X2_1241 2482 +#define Z_UTIL_X2_1242 2484 +#define Z_UTIL_X2_1243 2486 +#define Z_UTIL_X2_1244 2488 +#define Z_UTIL_X2_1245 2490 +#define Z_UTIL_X2_1246 2492 +#define Z_UTIL_X2_1247 2494 +#define Z_UTIL_X2_1248 2496 +#define Z_UTIL_X2_1249 2498 +#define Z_UTIL_X2_1250 2500 +#define Z_UTIL_X2_1251 2502 +#define Z_UTIL_X2_1252 2504 +#define Z_UTIL_X2_1253 2506 +#define Z_UTIL_X2_1254 2508 +#define Z_UTIL_X2_1255 2510 +#define Z_UTIL_X2_1256 2512 +#define Z_UTIL_X2_1257 2514 +#define Z_UTIL_X2_1258 2516 +#define Z_UTIL_X2_1259 2518 +#define Z_UTIL_X2_1260 2520 +#define Z_UTIL_X2_1261 2522 +#define Z_UTIL_X2_1262 2524 +#define Z_UTIL_X2_1263 2526 +#define Z_UTIL_X2_1264 2528 +#define Z_UTIL_X2_1265 2530 +#define Z_UTIL_X2_1266 2532 +#define Z_UTIL_X2_1267 2534 +#define Z_UTIL_X2_1268 2536 +#define Z_UTIL_X2_1269 2538 +#define Z_UTIL_X2_1270 2540 +#define Z_UTIL_X2_1271 2542 +#define Z_UTIL_X2_1272 2544 +#define Z_UTIL_X2_1273 2546 +#define Z_UTIL_X2_1274 2548 +#define Z_UTIL_X2_1275 2550 +#define Z_UTIL_X2_1276 2552 +#define Z_UTIL_X2_1277 2554 +#define Z_UTIL_X2_1278 2556 +#define Z_UTIL_X2_1279 2558 +#define Z_UTIL_X2_1280 2560 +#define Z_UTIL_X2_1281 2562 +#define Z_UTIL_X2_1282 2564 +#define Z_UTIL_X2_1283 2566 +#define Z_UTIL_X2_1284 2568 +#define Z_UTIL_X2_1285 2570 +#define Z_UTIL_X2_1286 2572 +#define Z_UTIL_X2_1287 2574 +#define Z_UTIL_X2_1288 2576 +#define Z_UTIL_X2_1289 2578 +#define Z_UTIL_X2_1290 2580 +#define Z_UTIL_X2_1291 2582 +#define Z_UTIL_X2_1292 2584 +#define Z_UTIL_X2_1293 2586 +#define Z_UTIL_X2_1294 2588 +#define Z_UTIL_X2_1295 2590 +#define Z_UTIL_X2_1296 2592 +#define Z_UTIL_X2_1297 2594 +#define Z_UTIL_X2_1298 2596 +#define Z_UTIL_X2_1299 2598 +#define Z_UTIL_X2_1300 2600 +#define Z_UTIL_X2_1301 2602 +#define Z_UTIL_X2_1302 2604 +#define Z_UTIL_X2_1303 2606 +#define Z_UTIL_X2_1304 2608 +#define Z_UTIL_X2_1305 2610 +#define Z_UTIL_X2_1306 2612 +#define Z_UTIL_X2_1307 2614 +#define Z_UTIL_X2_1308 2616 +#define Z_UTIL_X2_1309 2618 +#define Z_UTIL_X2_1310 2620 +#define Z_UTIL_X2_1311 2622 +#define Z_UTIL_X2_1312 2624 +#define Z_UTIL_X2_1313 2626 +#define Z_UTIL_X2_1314 2628 +#define Z_UTIL_X2_1315 2630 +#define Z_UTIL_X2_1316 2632 +#define Z_UTIL_X2_1317 2634 +#define Z_UTIL_X2_1318 2636 +#define Z_UTIL_X2_1319 2638 +#define Z_UTIL_X2_1320 2640 +#define Z_UTIL_X2_1321 2642 +#define Z_UTIL_X2_1322 2644 +#define Z_UTIL_X2_1323 2646 +#define Z_UTIL_X2_1324 2648 +#define Z_UTIL_X2_1325 2650 +#define Z_UTIL_X2_1326 2652 +#define Z_UTIL_X2_1327 2654 +#define Z_UTIL_X2_1328 2656 +#define Z_UTIL_X2_1329 2658 +#define Z_UTIL_X2_1330 2660 +#define Z_UTIL_X2_1331 2662 +#define Z_UTIL_X2_1332 2664 +#define Z_UTIL_X2_1333 2666 +#define Z_UTIL_X2_1334 2668 +#define Z_UTIL_X2_1335 2670 +#define Z_UTIL_X2_1336 2672 +#define Z_UTIL_X2_1337 2674 +#define Z_UTIL_X2_1338 2676 +#define Z_UTIL_X2_1339 2678 +#define Z_UTIL_X2_1340 2680 +#define Z_UTIL_X2_1341 2682 +#define Z_UTIL_X2_1342 2684 +#define Z_UTIL_X2_1343 2686 +#define Z_UTIL_X2_1344 2688 +#define Z_UTIL_X2_1345 2690 +#define Z_UTIL_X2_1346 2692 +#define Z_UTIL_X2_1347 2694 +#define Z_UTIL_X2_1348 2696 +#define Z_UTIL_X2_1349 2698 +#define Z_UTIL_X2_1350 2700 +#define Z_UTIL_X2_1351 2702 +#define Z_UTIL_X2_1352 2704 +#define Z_UTIL_X2_1353 2706 +#define Z_UTIL_X2_1354 2708 +#define Z_UTIL_X2_1355 2710 +#define Z_UTIL_X2_1356 2712 +#define Z_UTIL_X2_1357 2714 +#define Z_UTIL_X2_1358 2716 +#define Z_UTIL_X2_1359 2718 +#define Z_UTIL_X2_1360 2720 +#define Z_UTIL_X2_1361 2722 +#define Z_UTIL_X2_1362 2724 +#define Z_UTIL_X2_1363 2726 +#define Z_UTIL_X2_1364 2728 +#define Z_UTIL_X2_1365 2730 +#define Z_UTIL_X2_1366 2732 +#define Z_UTIL_X2_1367 2734 +#define Z_UTIL_X2_1368 2736 +#define Z_UTIL_X2_1369 2738 +#define Z_UTIL_X2_1370 2740 +#define Z_UTIL_X2_1371 2742 +#define Z_UTIL_X2_1372 2744 +#define Z_UTIL_X2_1373 2746 +#define Z_UTIL_X2_1374 2748 +#define Z_UTIL_X2_1375 2750 +#define Z_UTIL_X2_1376 2752 +#define Z_UTIL_X2_1377 2754 +#define Z_UTIL_X2_1378 2756 +#define Z_UTIL_X2_1379 2758 +#define Z_UTIL_X2_1380 2760 +#define Z_UTIL_X2_1381 2762 +#define Z_UTIL_X2_1382 2764 +#define Z_UTIL_X2_1383 2766 +#define Z_UTIL_X2_1384 2768 +#define Z_UTIL_X2_1385 2770 +#define Z_UTIL_X2_1386 2772 +#define Z_UTIL_X2_1387 2774 +#define Z_UTIL_X2_1388 2776 +#define Z_UTIL_X2_1389 2778 +#define Z_UTIL_X2_1390 2780 +#define Z_UTIL_X2_1391 2782 +#define Z_UTIL_X2_1392 2784 +#define Z_UTIL_X2_1393 2786 +#define Z_UTIL_X2_1394 2788 +#define Z_UTIL_X2_1395 2790 +#define Z_UTIL_X2_1396 2792 +#define Z_UTIL_X2_1397 2794 +#define Z_UTIL_X2_1398 2796 +#define Z_UTIL_X2_1399 2798 +#define Z_UTIL_X2_1400 2800 +#define Z_UTIL_X2_1401 2802 +#define Z_UTIL_X2_1402 2804 +#define Z_UTIL_X2_1403 2806 +#define Z_UTIL_X2_1404 2808 +#define Z_UTIL_X2_1405 2810 +#define Z_UTIL_X2_1406 2812 +#define Z_UTIL_X2_1407 2814 +#define Z_UTIL_X2_1408 2816 +#define Z_UTIL_X2_1409 2818 +#define Z_UTIL_X2_1410 2820 +#define Z_UTIL_X2_1411 2822 +#define Z_UTIL_X2_1412 2824 +#define Z_UTIL_X2_1413 2826 +#define Z_UTIL_X2_1414 2828 +#define Z_UTIL_X2_1415 2830 +#define Z_UTIL_X2_1416 2832 +#define Z_UTIL_X2_1417 2834 +#define Z_UTIL_X2_1418 2836 +#define Z_UTIL_X2_1419 2838 +#define Z_UTIL_X2_1420 2840 +#define Z_UTIL_X2_1421 2842 +#define Z_UTIL_X2_1422 2844 +#define Z_UTIL_X2_1423 2846 +#define Z_UTIL_X2_1424 2848 +#define Z_UTIL_X2_1425 2850 +#define Z_UTIL_X2_1426 2852 +#define Z_UTIL_X2_1427 2854 +#define Z_UTIL_X2_1428 2856 +#define Z_UTIL_X2_1429 2858 +#define Z_UTIL_X2_1430 2860 +#define Z_UTIL_X2_1431 2862 +#define Z_UTIL_X2_1432 2864 +#define Z_UTIL_X2_1433 2866 +#define Z_UTIL_X2_1434 2868 +#define Z_UTIL_X2_1435 2870 +#define Z_UTIL_X2_1436 2872 +#define Z_UTIL_X2_1437 2874 +#define Z_UTIL_X2_1438 2876 +#define Z_UTIL_X2_1439 2878 +#define Z_UTIL_X2_1440 2880 +#define Z_UTIL_X2_1441 2882 +#define Z_UTIL_X2_1442 2884 +#define Z_UTIL_X2_1443 2886 +#define Z_UTIL_X2_1444 2888 +#define Z_UTIL_X2_1445 2890 +#define Z_UTIL_X2_1446 2892 +#define Z_UTIL_X2_1447 2894 +#define Z_UTIL_X2_1448 2896 +#define Z_UTIL_X2_1449 2898 +#define Z_UTIL_X2_1450 2900 +#define Z_UTIL_X2_1451 2902 +#define Z_UTIL_X2_1452 2904 +#define Z_UTIL_X2_1453 2906 +#define Z_UTIL_X2_1454 2908 +#define Z_UTIL_X2_1455 2910 +#define Z_UTIL_X2_1456 2912 +#define Z_UTIL_X2_1457 2914 +#define Z_UTIL_X2_1458 2916 +#define Z_UTIL_X2_1459 2918 +#define Z_UTIL_X2_1460 2920 +#define Z_UTIL_X2_1461 2922 +#define Z_UTIL_X2_1462 2924 +#define Z_UTIL_X2_1463 2926 +#define Z_UTIL_X2_1464 2928 +#define Z_UTIL_X2_1465 2930 +#define Z_UTIL_X2_1466 2932 +#define Z_UTIL_X2_1467 2934 +#define Z_UTIL_X2_1468 2936 +#define Z_UTIL_X2_1469 2938 +#define Z_UTIL_X2_1470 2940 +#define Z_UTIL_X2_1471 2942 +#define Z_UTIL_X2_1472 2944 +#define Z_UTIL_X2_1473 2946 +#define Z_UTIL_X2_1474 2948 +#define Z_UTIL_X2_1475 2950 +#define Z_UTIL_X2_1476 2952 +#define Z_UTIL_X2_1477 2954 +#define Z_UTIL_X2_1478 2956 +#define Z_UTIL_X2_1479 2958 +#define Z_UTIL_X2_1480 2960 +#define Z_UTIL_X2_1481 2962 +#define Z_UTIL_X2_1482 2964 +#define Z_UTIL_X2_1483 2966 +#define Z_UTIL_X2_1484 2968 +#define Z_UTIL_X2_1485 2970 +#define Z_UTIL_X2_1486 2972 +#define Z_UTIL_X2_1487 2974 +#define Z_UTIL_X2_1488 2976 +#define Z_UTIL_X2_1489 2978 +#define Z_UTIL_X2_1490 2980 +#define Z_UTIL_X2_1491 2982 +#define Z_UTIL_X2_1492 2984 +#define Z_UTIL_X2_1493 2986 +#define Z_UTIL_X2_1494 2988 +#define Z_UTIL_X2_1495 2990 +#define Z_UTIL_X2_1496 2992 +#define Z_UTIL_X2_1497 2994 +#define Z_UTIL_X2_1498 2996 +#define Z_UTIL_X2_1499 2998 +#define Z_UTIL_X2_1500 3000 +#define Z_UTIL_X2_1501 3002 +#define Z_UTIL_X2_1502 3004 +#define Z_UTIL_X2_1503 3006 +#define Z_UTIL_X2_1504 3008 +#define Z_UTIL_X2_1505 3010 +#define Z_UTIL_X2_1506 3012 +#define Z_UTIL_X2_1507 3014 +#define Z_UTIL_X2_1508 3016 +#define Z_UTIL_X2_1509 3018 +#define Z_UTIL_X2_1510 3020 +#define Z_UTIL_X2_1511 3022 +#define Z_UTIL_X2_1512 3024 +#define Z_UTIL_X2_1513 3026 +#define Z_UTIL_X2_1514 3028 +#define Z_UTIL_X2_1515 3030 +#define Z_UTIL_X2_1516 3032 +#define Z_UTIL_X2_1517 3034 +#define Z_UTIL_X2_1518 3036 +#define Z_UTIL_X2_1519 3038 +#define Z_UTIL_X2_1520 3040 +#define Z_UTIL_X2_1521 3042 +#define Z_UTIL_X2_1522 3044 +#define Z_UTIL_X2_1523 3046 +#define Z_UTIL_X2_1524 3048 +#define Z_UTIL_X2_1525 3050 +#define Z_UTIL_X2_1526 3052 +#define Z_UTIL_X2_1527 3054 +#define Z_UTIL_X2_1528 3056 +#define Z_UTIL_X2_1529 3058 +#define Z_UTIL_X2_1530 3060 +#define Z_UTIL_X2_1531 3062 +#define Z_UTIL_X2_1532 3064 +#define Z_UTIL_X2_1533 3066 +#define Z_UTIL_X2_1534 3068 +#define Z_UTIL_X2_1535 3070 +#define Z_UTIL_X2_1536 3072 +#define Z_UTIL_X2_1537 3074 +#define Z_UTIL_X2_1538 3076 +#define Z_UTIL_X2_1539 3078 +#define Z_UTIL_X2_1540 3080 +#define Z_UTIL_X2_1541 3082 +#define Z_UTIL_X2_1542 3084 +#define Z_UTIL_X2_1543 3086 +#define Z_UTIL_X2_1544 3088 +#define Z_UTIL_X2_1545 3090 +#define Z_UTIL_X2_1546 3092 +#define Z_UTIL_X2_1547 3094 +#define Z_UTIL_X2_1548 3096 +#define Z_UTIL_X2_1549 3098 +#define Z_UTIL_X2_1550 3100 +#define Z_UTIL_X2_1551 3102 +#define Z_UTIL_X2_1552 3104 +#define Z_UTIL_X2_1553 3106 +#define Z_UTIL_X2_1554 3108 +#define Z_UTIL_X2_1555 3110 +#define Z_UTIL_X2_1556 3112 +#define Z_UTIL_X2_1557 3114 +#define Z_UTIL_X2_1558 3116 +#define Z_UTIL_X2_1559 3118 +#define Z_UTIL_X2_1560 3120 +#define Z_UTIL_X2_1561 3122 +#define Z_UTIL_X2_1562 3124 +#define Z_UTIL_X2_1563 3126 +#define Z_UTIL_X2_1564 3128 +#define Z_UTIL_X2_1565 3130 +#define Z_UTIL_X2_1566 3132 +#define Z_UTIL_X2_1567 3134 +#define Z_UTIL_X2_1568 3136 +#define Z_UTIL_X2_1569 3138 +#define Z_UTIL_X2_1570 3140 +#define Z_UTIL_X2_1571 3142 +#define Z_UTIL_X2_1572 3144 +#define Z_UTIL_X2_1573 3146 +#define Z_UTIL_X2_1574 3148 +#define Z_UTIL_X2_1575 3150 +#define Z_UTIL_X2_1576 3152 +#define Z_UTIL_X2_1577 3154 +#define Z_UTIL_X2_1578 3156 +#define Z_UTIL_X2_1579 3158 +#define Z_UTIL_X2_1580 3160 +#define Z_UTIL_X2_1581 3162 +#define Z_UTIL_X2_1582 3164 +#define Z_UTIL_X2_1583 3166 +#define Z_UTIL_X2_1584 3168 +#define Z_UTIL_X2_1585 3170 +#define Z_UTIL_X2_1586 3172 +#define Z_UTIL_X2_1587 3174 +#define Z_UTIL_X2_1588 3176 +#define Z_UTIL_X2_1589 3178 +#define Z_UTIL_X2_1590 3180 +#define Z_UTIL_X2_1591 3182 +#define Z_UTIL_X2_1592 3184 +#define Z_UTIL_X2_1593 3186 +#define Z_UTIL_X2_1594 3188 +#define Z_UTIL_X2_1595 3190 +#define Z_UTIL_X2_1596 3192 +#define Z_UTIL_X2_1597 3194 +#define Z_UTIL_X2_1598 3196 +#define Z_UTIL_X2_1599 3198 +#define Z_UTIL_X2_1600 3200 +#define Z_UTIL_X2_1601 3202 +#define Z_UTIL_X2_1602 3204 +#define Z_UTIL_X2_1603 3206 +#define Z_UTIL_X2_1604 3208 +#define Z_UTIL_X2_1605 3210 +#define Z_UTIL_X2_1606 3212 +#define Z_UTIL_X2_1607 3214 +#define Z_UTIL_X2_1608 3216 +#define Z_UTIL_X2_1609 3218 +#define Z_UTIL_X2_1610 3220 +#define Z_UTIL_X2_1611 3222 +#define Z_UTIL_X2_1612 3224 +#define Z_UTIL_X2_1613 3226 +#define Z_UTIL_X2_1614 3228 +#define Z_UTIL_X2_1615 3230 +#define Z_UTIL_X2_1616 3232 +#define Z_UTIL_X2_1617 3234 +#define Z_UTIL_X2_1618 3236 +#define Z_UTIL_X2_1619 3238 +#define Z_UTIL_X2_1620 3240 +#define Z_UTIL_X2_1621 3242 +#define Z_UTIL_X2_1622 3244 +#define Z_UTIL_X2_1623 3246 +#define Z_UTIL_X2_1624 3248 +#define Z_UTIL_X2_1625 3250 +#define Z_UTIL_X2_1626 3252 +#define Z_UTIL_X2_1627 3254 +#define Z_UTIL_X2_1628 3256 +#define Z_UTIL_X2_1629 3258 +#define Z_UTIL_X2_1630 3260 +#define Z_UTIL_X2_1631 3262 +#define Z_UTIL_X2_1632 3264 +#define Z_UTIL_X2_1633 3266 +#define Z_UTIL_X2_1634 3268 +#define Z_UTIL_X2_1635 3270 +#define Z_UTIL_X2_1636 3272 +#define Z_UTIL_X2_1637 3274 +#define Z_UTIL_X2_1638 3276 +#define Z_UTIL_X2_1639 3278 +#define Z_UTIL_X2_1640 3280 +#define Z_UTIL_X2_1641 3282 +#define Z_UTIL_X2_1642 3284 +#define Z_UTIL_X2_1643 3286 +#define Z_UTIL_X2_1644 3288 +#define Z_UTIL_X2_1645 3290 +#define Z_UTIL_X2_1646 3292 +#define Z_UTIL_X2_1647 3294 +#define Z_UTIL_X2_1648 3296 +#define Z_UTIL_X2_1649 3298 +#define Z_UTIL_X2_1650 3300 +#define Z_UTIL_X2_1651 3302 +#define Z_UTIL_X2_1652 3304 +#define Z_UTIL_X2_1653 3306 +#define Z_UTIL_X2_1654 3308 +#define Z_UTIL_X2_1655 3310 +#define Z_UTIL_X2_1656 3312 +#define Z_UTIL_X2_1657 3314 +#define Z_UTIL_X2_1658 3316 +#define Z_UTIL_X2_1659 3318 +#define Z_UTIL_X2_1660 3320 +#define Z_UTIL_X2_1661 3322 +#define Z_UTIL_X2_1662 3324 +#define Z_UTIL_X2_1663 3326 +#define Z_UTIL_X2_1664 3328 +#define Z_UTIL_X2_1665 3330 +#define Z_UTIL_X2_1666 3332 +#define Z_UTIL_X2_1667 3334 +#define Z_UTIL_X2_1668 3336 +#define Z_UTIL_X2_1669 3338 +#define Z_UTIL_X2_1670 3340 +#define Z_UTIL_X2_1671 3342 +#define Z_UTIL_X2_1672 3344 +#define Z_UTIL_X2_1673 3346 +#define Z_UTIL_X2_1674 3348 +#define Z_UTIL_X2_1675 3350 +#define Z_UTIL_X2_1676 3352 +#define Z_UTIL_X2_1677 3354 +#define Z_UTIL_X2_1678 3356 +#define Z_UTIL_X2_1679 3358 +#define Z_UTIL_X2_1680 3360 +#define Z_UTIL_X2_1681 3362 +#define Z_UTIL_X2_1682 3364 +#define Z_UTIL_X2_1683 3366 +#define Z_UTIL_X2_1684 3368 +#define Z_UTIL_X2_1685 3370 +#define Z_UTIL_X2_1686 3372 +#define Z_UTIL_X2_1687 3374 +#define Z_UTIL_X2_1688 3376 +#define Z_UTIL_X2_1689 3378 +#define Z_UTIL_X2_1690 3380 +#define Z_UTIL_X2_1691 3382 +#define Z_UTIL_X2_1692 3384 +#define Z_UTIL_X2_1693 3386 +#define Z_UTIL_X2_1694 3388 +#define Z_UTIL_X2_1695 3390 +#define Z_UTIL_X2_1696 3392 +#define Z_UTIL_X2_1697 3394 +#define Z_UTIL_X2_1698 3396 +#define Z_UTIL_X2_1699 3398 +#define Z_UTIL_X2_1700 3400 +#define Z_UTIL_X2_1701 3402 +#define Z_UTIL_X2_1702 3404 +#define Z_UTIL_X2_1703 3406 +#define Z_UTIL_X2_1704 3408 +#define Z_UTIL_X2_1705 3410 +#define Z_UTIL_X2_1706 3412 +#define Z_UTIL_X2_1707 3414 +#define Z_UTIL_X2_1708 3416 +#define Z_UTIL_X2_1709 3418 +#define Z_UTIL_X2_1710 3420 +#define Z_UTIL_X2_1711 3422 +#define Z_UTIL_X2_1712 3424 +#define Z_UTIL_X2_1713 3426 +#define Z_UTIL_X2_1714 3428 +#define Z_UTIL_X2_1715 3430 +#define Z_UTIL_X2_1716 3432 +#define Z_UTIL_X2_1717 3434 +#define Z_UTIL_X2_1718 3436 +#define Z_UTIL_X2_1719 3438 +#define Z_UTIL_X2_1720 3440 +#define Z_UTIL_X2_1721 3442 +#define Z_UTIL_X2_1722 3444 +#define Z_UTIL_X2_1723 3446 +#define Z_UTIL_X2_1724 3448 +#define Z_UTIL_X2_1725 3450 +#define Z_UTIL_X2_1726 3452 +#define Z_UTIL_X2_1727 3454 +#define Z_UTIL_X2_1728 3456 +#define Z_UTIL_X2_1729 3458 +#define Z_UTIL_X2_1730 3460 +#define Z_UTIL_X2_1731 3462 +#define Z_UTIL_X2_1732 3464 +#define Z_UTIL_X2_1733 3466 +#define Z_UTIL_X2_1734 3468 +#define Z_UTIL_X2_1735 3470 +#define Z_UTIL_X2_1736 3472 +#define Z_UTIL_X2_1737 3474 +#define Z_UTIL_X2_1738 3476 +#define Z_UTIL_X2_1739 3478 +#define Z_UTIL_X2_1740 3480 +#define Z_UTIL_X2_1741 3482 +#define Z_UTIL_X2_1742 3484 +#define Z_UTIL_X2_1743 3486 +#define Z_UTIL_X2_1744 3488 +#define Z_UTIL_X2_1745 3490 +#define Z_UTIL_X2_1746 3492 +#define Z_UTIL_X2_1747 3494 +#define Z_UTIL_X2_1748 3496 +#define Z_UTIL_X2_1749 3498 +#define Z_UTIL_X2_1750 3500 +#define Z_UTIL_X2_1751 3502 +#define Z_UTIL_X2_1752 3504 +#define Z_UTIL_X2_1753 3506 +#define Z_UTIL_X2_1754 3508 +#define Z_UTIL_X2_1755 3510 +#define Z_UTIL_X2_1756 3512 +#define Z_UTIL_X2_1757 3514 +#define Z_UTIL_X2_1758 3516 +#define Z_UTIL_X2_1759 3518 +#define Z_UTIL_X2_1760 3520 +#define Z_UTIL_X2_1761 3522 +#define Z_UTIL_X2_1762 3524 +#define Z_UTIL_X2_1763 3526 +#define Z_UTIL_X2_1764 3528 +#define Z_UTIL_X2_1765 3530 +#define Z_UTIL_X2_1766 3532 +#define Z_UTIL_X2_1767 3534 +#define Z_UTIL_X2_1768 3536 +#define Z_UTIL_X2_1769 3538 +#define Z_UTIL_X2_1770 3540 +#define Z_UTIL_X2_1771 3542 +#define Z_UTIL_X2_1772 3544 +#define Z_UTIL_X2_1773 3546 +#define Z_UTIL_X2_1774 3548 +#define Z_UTIL_X2_1775 3550 +#define Z_UTIL_X2_1776 3552 +#define Z_UTIL_X2_1777 3554 +#define Z_UTIL_X2_1778 3556 +#define Z_UTIL_X2_1779 3558 +#define Z_UTIL_X2_1780 3560 +#define Z_UTIL_X2_1781 3562 +#define Z_UTIL_X2_1782 3564 +#define Z_UTIL_X2_1783 3566 +#define Z_UTIL_X2_1784 3568 +#define Z_UTIL_X2_1785 3570 +#define Z_UTIL_X2_1786 3572 +#define Z_UTIL_X2_1787 3574 +#define Z_UTIL_X2_1788 3576 +#define Z_UTIL_X2_1789 3578 +#define Z_UTIL_X2_1790 3580 +#define Z_UTIL_X2_1791 3582 +#define Z_UTIL_X2_1792 3584 +#define Z_UTIL_X2_1793 3586 +#define Z_UTIL_X2_1794 3588 +#define Z_UTIL_X2_1795 3590 +#define Z_UTIL_X2_1796 3592 +#define Z_UTIL_X2_1797 3594 +#define Z_UTIL_X2_1798 3596 +#define Z_UTIL_X2_1799 3598 +#define Z_UTIL_X2_1800 3600 +#define Z_UTIL_X2_1801 3602 +#define Z_UTIL_X2_1802 3604 +#define Z_UTIL_X2_1803 3606 +#define Z_UTIL_X2_1804 3608 +#define Z_UTIL_X2_1805 3610 +#define Z_UTIL_X2_1806 3612 +#define Z_UTIL_X2_1807 3614 +#define Z_UTIL_X2_1808 3616 +#define Z_UTIL_X2_1809 3618 +#define Z_UTIL_X2_1810 3620 +#define Z_UTIL_X2_1811 3622 +#define Z_UTIL_X2_1812 3624 +#define Z_UTIL_X2_1813 3626 +#define Z_UTIL_X2_1814 3628 +#define Z_UTIL_X2_1815 3630 +#define Z_UTIL_X2_1816 3632 +#define Z_UTIL_X2_1817 3634 +#define Z_UTIL_X2_1818 3636 +#define Z_UTIL_X2_1819 3638 +#define Z_UTIL_X2_1820 3640 +#define Z_UTIL_X2_1821 3642 +#define Z_UTIL_X2_1822 3644 +#define Z_UTIL_X2_1823 3646 +#define Z_UTIL_X2_1824 3648 +#define Z_UTIL_X2_1825 3650 +#define Z_UTIL_X2_1826 3652 +#define Z_UTIL_X2_1827 3654 +#define Z_UTIL_X2_1828 3656 +#define Z_UTIL_X2_1829 3658 +#define Z_UTIL_X2_1830 3660 +#define Z_UTIL_X2_1831 3662 +#define Z_UTIL_X2_1832 3664 +#define Z_UTIL_X2_1833 3666 +#define Z_UTIL_X2_1834 3668 +#define Z_UTIL_X2_1835 3670 +#define Z_UTIL_X2_1836 3672 +#define Z_UTIL_X2_1837 3674 +#define Z_UTIL_X2_1838 3676 +#define Z_UTIL_X2_1839 3678 +#define Z_UTIL_X2_1840 3680 +#define Z_UTIL_X2_1841 3682 +#define Z_UTIL_X2_1842 3684 +#define Z_UTIL_X2_1843 3686 +#define Z_UTIL_X2_1844 3688 +#define Z_UTIL_X2_1845 3690 +#define Z_UTIL_X2_1846 3692 +#define Z_UTIL_X2_1847 3694 +#define Z_UTIL_X2_1848 3696 +#define Z_UTIL_X2_1849 3698 +#define Z_UTIL_X2_1850 3700 +#define Z_UTIL_X2_1851 3702 +#define Z_UTIL_X2_1852 3704 +#define Z_UTIL_X2_1853 3706 +#define Z_UTIL_X2_1854 3708 +#define Z_UTIL_X2_1855 3710 +#define Z_UTIL_X2_1856 3712 +#define Z_UTIL_X2_1857 3714 +#define Z_UTIL_X2_1858 3716 +#define Z_UTIL_X2_1859 3718 +#define Z_UTIL_X2_1860 3720 +#define Z_UTIL_X2_1861 3722 +#define Z_UTIL_X2_1862 3724 +#define Z_UTIL_X2_1863 3726 +#define Z_UTIL_X2_1864 3728 +#define Z_UTIL_X2_1865 3730 +#define Z_UTIL_X2_1866 3732 +#define Z_UTIL_X2_1867 3734 +#define Z_UTIL_X2_1868 3736 +#define Z_UTIL_X2_1869 3738 +#define Z_UTIL_X2_1870 3740 +#define Z_UTIL_X2_1871 3742 +#define Z_UTIL_X2_1872 3744 +#define Z_UTIL_X2_1873 3746 +#define Z_UTIL_X2_1874 3748 +#define Z_UTIL_X2_1875 3750 +#define Z_UTIL_X2_1876 3752 +#define Z_UTIL_X2_1877 3754 +#define Z_UTIL_X2_1878 3756 +#define Z_UTIL_X2_1879 3758 +#define Z_UTIL_X2_1880 3760 +#define Z_UTIL_X2_1881 3762 +#define Z_UTIL_X2_1882 3764 +#define Z_UTIL_X2_1883 3766 +#define Z_UTIL_X2_1884 3768 +#define Z_UTIL_X2_1885 3770 +#define Z_UTIL_X2_1886 3772 +#define Z_UTIL_X2_1887 3774 +#define Z_UTIL_X2_1888 3776 +#define Z_UTIL_X2_1889 3778 +#define Z_UTIL_X2_1890 3780 +#define Z_UTIL_X2_1891 3782 +#define Z_UTIL_X2_1892 3784 +#define Z_UTIL_X2_1893 3786 +#define Z_UTIL_X2_1894 3788 +#define Z_UTIL_X2_1895 3790 +#define Z_UTIL_X2_1896 3792 +#define Z_UTIL_X2_1897 3794 +#define Z_UTIL_X2_1898 3796 +#define Z_UTIL_X2_1899 3798 +#define Z_UTIL_X2_1900 3800 +#define Z_UTIL_X2_1901 3802 +#define Z_UTIL_X2_1902 3804 +#define Z_UTIL_X2_1903 3806 +#define Z_UTIL_X2_1904 3808 +#define Z_UTIL_X2_1905 3810 +#define Z_UTIL_X2_1906 3812 +#define Z_UTIL_X2_1907 3814 +#define Z_UTIL_X2_1908 3816 +#define Z_UTIL_X2_1909 3818 +#define Z_UTIL_X2_1910 3820 +#define Z_UTIL_X2_1911 3822 +#define Z_UTIL_X2_1912 3824 +#define Z_UTIL_X2_1913 3826 +#define Z_UTIL_X2_1914 3828 +#define Z_UTIL_X2_1915 3830 +#define Z_UTIL_X2_1916 3832 +#define Z_UTIL_X2_1917 3834 +#define Z_UTIL_X2_1918 3836 +#define Z_UTIL_X2_1919 3838 +#define Z_UTIL_X2_1920 3840 +#define Z_UTIL_X2_1921 3842 +#define Z_UTIL_X2_1922 3844 +#define Z_UTIL_X2_1923 3846 +#define Z_UTIL_X2_1924 3848 +#define Z_UTIL_X2_1925 3850 +#define Z_UTIL_X2_1926 3852 +#define Z_UTIL_X2_1927 3854 +#define Z_UTIL_X2_1928 3856 +#define Z_UTIL_X2_1929 3858 +#define Z_UTIL_X2_1930 3860 +#define Z_UTIL_X2_1931 3862 +#define Z_UTIL_X2_1932 3864 +#define Z_UTIL_X2_1933 3866 +#define Z_UTIL_X2_1934 3868 +#define Z_UTIL_X2_1935 3870 +#define Z_UTIL_X2_1936 3872 +#define Z_UTIL_X2_1937 3874 +#define Z_UTIL_X2_1938 3876 +#define Z_UTIL_X2_1939 3878 +#define Z_UTIL_X2_1940 3880 +#define Z_UTIL_X2_1941 3882 +#define Z_UTIL_X2_1942 3884 +#define Z_UTIL_X2_1943 3886 +#define Z_UTIL_X2_1944 3888 +#define Z_UTIL_X2_1945 3890 +#define Z_UTIL_X2_1946 3892 +#define Z_UTIL_X2_1947 3894 +#define Z_UTIL_X2_1948 3896 +#define Z_UTIL_X2_1949 3898 +#define Z_UTIL_X2_1950 3900 +#define Z_UTIL_X2_1951 3902 +#define Z_UTIL_X2_1952 3904 +#define Z_UTIL_X2_1953 3906 +#define Z_UTIL_X2_1954 3908 +#define Z_UTIL_X2_1955 3910 +#define Z_UTIL_X2_1956 3912 +#define Z_UTIL_X2_1957 3914 +#define Z_UTIL_X2_1958 3916 +#define Z_UTIL_X2_1959 3918 +#define Z_UTIL_X2_1960 3920 +#define Z_UTIL_X2_1961 3922 +#define Z_UTIL_X2_1962 3924 +#define Z_UTIL_X2_1963 3926 +#define Z_UTIL_X2_1964 3928 +#define Z_UTIL_X2_1965 3930 +#define Z_UTIL_X2_1966 3932 +#define Z_UTIL_X2_1967 3934 +#define Z_UTIL_X2_1968 3936 +#define Z_UTIL_X2_1969 3938 +#define Z_UTIL_X2_1970 3940 +#define Z_UTIL_X2_1971 3942 +#define Z_UTIL_X2_1972 3944 +#define Z_UTIL_X2_1973 3946 +#define Z_UTIL_X2_1974 3948 +#define Z_UTIL_X2_1975 3950 +#define Z_UTIL_X2_1976 3952 +#define Z_UTIL_X2_1977 3954 +#define Z_UTIL_X2_1978 3956 +#define Z_UTIL_X2_1979 3958 +#define Z_UTIL_X2_1980 3960 +#define Z_UTIL_X2_1981 3962 +#define Z_UTIL_X2_1982 3964 +#define Z_UTIL_X2_1983 3966 +#define Z_UTIL_X2_1984 3968 +#define Z_UTIL_X2_1985 3970 +#define Z_UTIL_X2_1986 3972 +#define Z_UTIL_X2_1987 3974 +#define Z_UTIL_X2_1988 3976 +#define Z_UTIL_X2_1989 3978 +#define Z_UTIL_X2_1990 3980 +#define Z_UTIL_X2_1991 3982 +#define Z_UTIL_X2_1992 3984 +#define Z_UTIL_X2_1993 3986 +#define Z_UTIL_X2_1994 3988 +#define Z_UTIL_X2_1995 3990 +#define Z_UTIL_X2_1996 3992 +#define Z_UTIL_X2_1997 3994 +#define Z_UTIL_X2_1998 3996 +#define Z_UTIL_X2_1999 3998 +#define Z_UTIL_X2_2000 4000 +#define Z_UTIL_X2_2001 4002 +#define Z_UTIL_X2_2002 4004 +#define Z_UTIL_X2_2003 4006 +#define Z_UTIL_X2_2004 4008 +#define Z_UTIL_X2_2005 4010 +#define Z_UTIL_X2_2006 4012 +#define Z_UTIL_X2_2007 4014 +#define Z_UTIL_X2_2008 4016 +#define Z_UTIL_X2_2009 4018 +#define Z_UTIL_X2_2010 4020 +#define Z_UTIL_X2_2011 4022 +#define Z_UTIL_X2_2012 4024 +#define Z_UTIL_X2_2013 4026 +#define Z_UTIL_X2_2014 4028 +#define Z_UTIL_X2_2015 4030 +#define Z_UTIL_X2_2016 4032 +#define Z_UTIL_X2_2017 4034 +#define Z_UTIL_X2_2018 4036 +#define Z_UTIL_X2_2019 4038 +#define Z_UTIL_X2_2020 4040 +#define Z_UTIL_X2_2021 4042 +#define Z_UTIL_X2_2022 4044 +#define Z_UTIL_X2_2023 4046 +#define Z_UTIL_X2_2024 4048 +#define Z_UTIL_X2_2025 4050 +#define Z_UTIL_X2_2026 4052 +#define Z_UTIL_X2_2027 4054 +#define Z_UTIL_X2_2028 4056 +#define Z_UTIL_X2_2029 4058 +#define Z_UTIL_X2_2030 4060 +#define Z_UTIL_X2_2031 4062 +#define Z_UTIL_X2_2032 4064 +#define Z_UTIL_X2_2033 4066 +#define Z_UTIL_X2_2034 4068 +#define Z_UTIL_X2_2035 4070 +#define Z_UTIL_X2_2036 4072 +#define Z_UTIL_X2_2037 4074 +#define Z_UTIL_X2_2038 4076 +#define Z_UTIL_X2_2039 4078 +#define Z_UTIL_X2_2040 4080 +#define Z_UTIL_X2_2041 4082 +#define Z_UTIL_X2_2042 4084 +#define Z_UTIL_X2_2043 4086 +#define Z_UTIL_X2_2044 4088 +#define Z_UTIL_X2_2045 4090 +#define Z_UTIL_X2_2046 4092 +#define Z_UTIL_X2_2047 4094 +#define Z_UTIL_X2_2048 4096 +#define Z_UTIL_X2_2049 4098 +#define Z_UTIL_X2_2050 4100 +#define Z_UTIL_X2_2051 4102 +#define Z_UTIL_X2_2052 4104 +#define Z_UTIL_X2_2053 4106 +#define Z_UTIL_X2_2054 4108 +#define Z_UTIL_X2_2055 4110 +#define Z_UTIL_X2_2056 4112 +#define Z_UTIL_X2_2057 4114 +#define Z_UTIL_X2_2058 4116 +#define Z_UTIL_X2_2059 4118 +#define Z_UTIL_X2_2060 4120 +#define Z_UTIL_X2_2061 4122 +#define Z_UTIL_X2_2062 4124 +#define Z_UTIL_X2_2063 4126 +#define Z_UTIL_X2_2064 4128 +#define Z_UTIL_X2_2065 4130 +#define Z_UTIL_X2_2066 4132 +#define Z_UTIL_X2_2067 4134 +#define Z_UTIL_X2_2068 4136 +#define Z_UTIL_X2_2069 4138 +#define Z_UTIL_X2_2070 4140 +#define Z_UTIL_X2_2071 4142 +#define Z_UTIL_X2_2072 4144 +#define Z_UTIL_X2_2073 4146 +#define Z_UTIL_X2_2074 4148 +#define Z_UTIL_X2_2075 4150 +#define Z_UTIL_X2_2076 4152 +#define Z_UTIL_X2_2077 4154 +#define Z_UTIL_X2_2078 4156 +#define Z_UTIL_X2_2079 4158 +#define Z_UTIL_X2_2080 4160 +#define Z_UTIL_X2_2081 4162 +#define Z_UTIL_X2_2082 4164 +#define Z_UTIL_X2_2083 4166 +#define Z_UTIL_X2_2084 4168 +#define Z_UTIL_X2_2085 4170 +#define Z_UTIL_X2_2086 4172 +#define Z_UTIL_X2_2087 4174 +#define Z_UTIL_X2_2088 4176 +#define Z_UTIL_X2_2089 4178 +#define Z_UTIL_X2_2090 4180 +#define Z_UTIL_X2_2091 4182 +#define Z_UTIL_X2_2092 4184 +#define Z_UTIL_X2_2093 4186 +#define Z_UTIL_X2_2094 4188 +#define Z_UTIL_X2_2095 4190 +#define Z_UTIL_X2_2096 4192 +#define Z_UTIL_X2_2097 4194 +#define Z_UTIL_X2_2098 4196 +#define Z_UTIL_X2_2099 4198 +#define Z_UTIL_X2_2100 4200 +#define Z_UTIL_X2_2101 4202 +#define Z_UTIL_X2_2102 4204 +#define Z_UTIL_X2_2103 4206 +#define Z_UTIL_X2_2104 4208 +#define Z_UTIL_X2_2105 4210 +#define Z_UTIL_X2_2106 4212 +#define Z_UTIL_X2_2107 4214 +#define Z_UTIL_X2_2108 4216 +#define Z_UTIL_X2_2109 4218 +#define Z_UTIL_X2_2110 4220 +#define Z_UTIL_X2_2111 4222 +#define Z_UTIL_X2_2112 4224 +#define Z_UTIL_X2_2113 4226 +#define Z_UTIL_X2_2114 4228 +#define Z_UTIL_X2_2115 4230 +#define Z_UTIL_X2_2116 4232 +#define Z_UTIL_X2_2117 4234 +#define Z_UTIL_X2_2118 4236 +#define Z_UTIL_X2_2119 4238 +#define Z_UTIL_X2_2120 4240 +#define Z_UTIL_X2_2121 4242 +#define Z_UTIL_X2_2122 4244 +#define Z_UTIL_X2_2123 4246 +#define Z_UTIL_X2_2124 4248 +#define Z_UTIL_X2_2125 4250 +#define Z_UTIL_X2_2126 4252 +#define Z_UTIL_X2_2127 4254 +#define Z_UTIL_X2_2128 4256 +#define Z_UTIL_X2_2129 4258 +#define Z_UTIL_X2_2130 4260 +#define Z_UTIL_X2_2131 4262 +#define Z_UTIL_X2_2132 4264 +#define Z_UTIL_X2_2133 4266 +#define Z_UTIL_X2_2134 4268 +#define Z_UTIL_X2_2135 4270 +#define Z_UTIL_X2_2136 4272 +#define Z_UTIL_X2_2137 4274 +#define Z_UTIL_X2_2138 4276 +#define Z_UTIL_X2_2139 4278 +#define Z_UTIL_X2_2140 4280 +#define Z_UTIL_X2_2141 4282 +#define Z_UTIL_X2_2142 4284 +#define Z_UTIL_X2_2143 4286 +#define Z_UTIL_X2_2144 4288 +#define Z_UTIL_X2_2145 4290 +#define Z_UTIL_X2_2146 4292 +#define Z_UTIL_X2_2147 4294 +#define Z_UTIL_X2_2148 4296 +#define Z_UTIL_X2_2149 4298 +#define Z_UTIL_X2_2150 4300 +#define Z_UTIL_X2_2151 4302 +#define Z_UTIL_X2_2152 4304 +#define Z_UTIL_X2_2153 4306 +#define Z_UTIL_X2_2154 4308 +#define Z_UTIL_X2_2155 4310 +#define Z_UTIL_X2_2156 4312 +#define Z_UTIL_X2_2157 4314 +#define Z_UTIL_X2_2158 4316 +#define Z_UTIL_X2_2159 4318 +#define Z_UTIL_X2_2160 4320 +#define Z_UTIL_X2_2161 4322 +#define Z_UTIL_X2_2162 4324 +#define Z_UTIL_X2_2163 4326 +#define Z_UTIL_X2_2164 4328 +#define Z_UTIL_X2_2165 4330 +#define Z_UTIL_X2_2166 4332 +#define Z_UTIL_X2_2167 4334 +#define Z_UTIL_X2_2168 4336 +#define Z_UTIL_X2_2169 4338 +#define Z_UTIL_X2_2170 4340 +#define Z_UTIL_X2_2171 4342 +#define Z_UTIL_X2_2172 4344 +#define Z_UTIL_X2_2173 4346 +#define Z_UTIL_X2_2174 4348 +#define Z_UTIL_X2_2175 4350 +#define Z_UTIL_X2_2176 4352 +#define Z_UTIL_X2_2177 4354 +#define Z_UTIL_X2_2178 4356 +#define Z_UTIL_X2_2179 4358 +#define Z_UTIL_X2_2180 4360 +#define Z_UTIL_X2_2181 4362 +#define Z_UTIL_X2_2182 4364 +#define Z_UTIL_X2_2183 4366 +#define Z_UTIL_X2_2184 4368 +#define Z_UTIL_X2_2185 4370 +#define Z_UTIL_X2_2186 4372 +#define Z_UTIL_X2_2187 4374 +#define Z_UTIL_X2_2188 4376 +#define Z_UTIL_X2_2189 4378 +#define Z_UTIL_X2_2190 4380 +#define Z_UTIL_X2_2191 4382 +#define Z_UTIL_X2_2192 4384 +#define Z_UTIL_X2_2193 4386 +#define Z_UTIL_X2_2194 4388 +#define Z_UTIL_X2_2195 4390 +#define Z_UTIL_X2_2196 4392 +#define Z_UTIL_X2_2197 4394 +#define Z_UTIL_X2_2198 4396 +#define Z_UTIL_X2_2199 4398 +#define Z_UTIL_X2_2200 4400 +#define Z_UTIL_X2_2201 4402 +#define Z_UTIL_X2_2202 4404 +#define Z_UTIL_X2_2203 4406 +#define Z_UTIL_X2_2204 4408 +#define Z_UTIL_X2_2205 4410 +#define Z_UTIL_X2_2206 4412 +#define Z_UTIL_X2_2207 4414 +#define Z_UTIL_X2_2208 4416 +#define Z_UTIL_X2_2209 4418 +#define Z_UTIL_X2_2210 4420 +#define Z_UTIL_X2_2211 4422 +#define Z_UTIL_X2_2212 4424 +#define Z_UTIL_X2_2213 4426 +#define Z_UTIL_X2_2214 4428 +#define Z_UTIL_X2_2215 4430 +#define Z_UTIL_X2_2216 4432 +#define Z_UTIL_X2_2217 4434 +#define Z_UTIL_X2_2218 4436 +#define Z_UTIL_X2_2219 4438 +#define Z_UTIL_X2_2220 4440 +#define Z_UTIL_X2_2221 4442 +#define Z_UTIL_X2_2222 4444 +#define Z_UTIL_X2_2223 4446 +#define Z_UTIL_X2_2224 4448 +#define Z_UTIL_X2_2225 4450 +#define Z_UTIL_X2_2226 4452 +#define Z_UTIL_X2_2227 4454 +#define Z_UTIL_X2_2228 4456 +#define Z_UTIL_X2_2229 4458 +#define Z_UTIL_X2_2230 4460 +#define Z_UTIL_X2_2231 4462 +#define Z_UTIL_X2_2232 4464 +#define Z_UTIL_X2_2233 4466 +#define Z_UTIL_X2_2234 4468 +#define Z_UTIL_X2_2235 4470 +#define Z_UTIL_X2_2236 4472 +#define Z_UTIL_X2_2237 4474 +#define Z_UTIL_X2_2238 4476 +#define Z_UTIL_X2_2239 4478 +#define Z_UTIL_X2_2240 4480 +#define Z_UTIL_X2_2241 4482 +#define Z_UTIL_X2_2242 4484 +#define Z_UTIL_X2_2243 4486 +#define Z_UTIL_X2_2244 4488 +#define Z_UTIL_X2_2245 4490 +#define Z_UTIL_X2_2246 4492 +#define Z_UTIL_X2_2247 4494 +#define Z_UTIL_X2_2248 4496 +#define Z_UTIL_X2_2249 4498 +#define Z_UTIL_X2_2250 4500 +#define Z_UTIL_X2_2251 4502 +#define Z_UTIL_X2_2252 4504 +#define Z_UTIL_X2_2253 4506 +#define Z_UTIL_X2_2254 4508 +#define Z_UTIL_X2_2255 4510 +#define Z_UTIL_X2_2256 4512 +#define Z_UTIL_X2_2257 4514 +#define Z_UTIL_X2_2258 4516 +#define Z_UTIL_X2_2259 4518 +#define Z_UTIL_X2_2260 4520 +#define Z_UTIL_X2_2261 4522 +#define Z_UTIL_X2_2262 4524 +#define Z_UTIL_X2_2263 4526 +#define Z_UTIL_X2_2264 4528 +#define Z_UTIL_X2_2265 4530 +#define Z_UTIL_X2_2266 4532 +#define Z_UTIL_X2_2267 4534 +#define Z_UTIL_X2_2268 4536 +#define Z_UTIL_X2_2269 4538 +#define Z_UTIL_X2_2270 4540 +#define Z_UTIL_X2_2271 4542 +#define Z_UTIL_X2_2272 4544 +#define Z_UTIL_X2_2273 4546 +#define Z_UTIL_X2_2274 4548 +#define Z_UTIL_X2_2275 4550 +#define Z_UTIL_X2_2276 4552 +#define Z_UTIL_X2_2277 4554 +#define Z_UTIL_X2_2278 4556 +#define Z_UTIL_X2_2279 4558 +#define Z_UTIL_X2_2280 4560 +#define Z_UTIL_X2_2281 4562 +#define Z_UTIL_X2_2282 4564 +#define Z_UTIL_X2_2283 4566 +#define Z_UTIL_X2_2284 4568 +#define Z_UTIL_X2_2285 4570 +#define Z_UTIL_X2_2286 4572 +#define Z_UTIL_X2_2287 4574 +#define Z_UTIL_X2_2288 4576 +#define Z_UTIL_X2_2289 4578 +#define Z_UTIL_X2_2290 4580 +#define Z_UTIL_X2_2291 4582 +#define Z_UTIL_X2_2292 4584 +#define Z_UTIL_X2_2293 4586 +#define Z_UTIL_X2_2294 4588 +#define Z_UTIL_X2_2295 4590 +#define Z_UTIL_X2_2296 4592 +#define Z_UTIL_X2_2297 4594 +#define Z_UTIL_X2_2298 4596 +#define Z_UTIL_X2_2299 4598 +#define Z_UTIL_X2_2300 4600 +#define Z_UTIL_X2_2301 4602 +#define Z_UTIL_X2_2302 4604 +#define Z_UTIL_X2_2303 4606 +#define Z_UTIL_X2_2304 4608 +#define Z_UTIL_X2_2305 4610 +#define Z_UTIL_X2_2306 4612 +#define Z_UTIL_X2_2307 4614 +#define Z_UTIL_X2_2308 4616 +#define Z_UTIL_X2_2309 4618 +#define Z_UTIL_X2_2310 4620 +#define Z_UTIL_X2_2311 4622 +#define Z_UTIL_X2_2312 4624 +#define Z_UTIL_X2_2313 4626 +#define Z_UTIL_X2_2314 4628 +#define Z_UTIL_X2_2315 4630 +#define Z_UTIL_X2_2316 4632 +#define Z_UTIL_X2_2317 4634 +#define Z_UTIL_X2_2318 4636 +#define Z_UTIL_X2_2319 4638 +#define Z_UTIL_X2_2320 4640 +#define Z_UTIL_X2_2321 4642 +#define Z_UTIL_X2_2322 4644 +#define Z_UTIL_X2_2323 4646 +#define Z_UTIL_X2_2324 4648 +#define Z_UTIL_X2_2325 4650 +#define Z_UTIL_X2_2326 4652 +#define Z_UTIL_X2_2327 4654 +#define Z_UTIL_X2_2328 4656 +#define Z_UTIL_X2_2329 4658 +#define Z_UTIL_X2_2330 4660 +#define Z_UTIL_X2_2331 4662 +#define Z_UTIL_X2_2332 4664 +#define Z_UTIL_X2_2333 4666 +#define Z_UTIL_X2_2334 4668 +#define Z_UTIL_X2_2335 4670 +#define Z_UTIL_X2_2336 4672 +#define Z_UTIL_X2_2337 4674 +#define Z_UTIL_X2_2338 4676 +#define Z_UTIL_X2_2339 4678 +#define Z_UTIL_X2_2340 4680 +#define Z_UTIL_X2_2341 4682 +#define Z_UTIL_X2_2342 4684 +#define Z_UTIL_X2_2343 4686 +#define Z_UTIL_X2_2344 4688 +#define Z_UTIL_X2_2345 4690 +#define Z_UTIL_X2_2346 4692 +#define Z_UTIL_X2_2347 4694 +#define Z_UTIL_X2_2348 4696 +#define Z_UTIL_X2_2349 4698 +#define Z_UTIL_X2_2350 4700 +#define Z_UTIL_X2_2351 4702 +#define Z_UTIL_X2_2352 4704 +#define Z_UTIL_X2_2353 4706 +#define Z_UTIL_X2_2354 4708 +#define Z_UTIL_X2_2355 4710 +#define Z_UTIL_X2_2356 4712 +#define Z_UTIL_X2_2357 4714 +#define Z_UTIL_X2_2358 4716 +#define Z_UTIL_X2_2359 4718 +#define Z_UTIL_X2_2360 4720 +#define Z_UTIL_X2_2361 4722 +#define Z_UTIL_X2_2362 4724 +#define Z_UTIL_X2_2363 4726 +#define Z_UTIL_X2_2364 4728 +#define Z_UTIL_X2_2365 4730 +#define Z_UTIL_X2_2366 4732 +#define Z_UTIL_X2_2367 4734 +#define Z_UTIL_X2_2368 4736 +#define Z_UTIL_X2_2369 4738 +#define Z_UTIL_X2_2370 4740 +#define Z_UTIL_X2_2371 4742 +#define Z_UTIL_X2_2372 4744 +#define Z_UTIL_X2_2373 4746 +#define Z_UTIL_X2_2374 4748 +#define Z_UTIL_X2_2375 4750 +#define Z_UTIL_X2_2376 4752 +#define Z_UTIL_X2_2377 4754 +#define Z_UTIL_X2_2378 4756 +#define Z_UTIL_X2_2379 4758 +#define Z_UTIL_X2_2380 4760 +#define Z_UTIL_X2_2381 4762 +#define Z_UTIL_X2_2382 4764 +#define Z_UTIL_X2_2383 4766 +#define Z_UTIL_X2_2384 4768 +#define Z_UTIL_X2_2385 4770 +#define Z_UTIL_X2_2386 4772 +#define Z_UTIL_X2_2387 4774 +#define Z_UTIL_X2_2388 4776 +#define Z_UTIL_X2_2389 4778 +#define Z_UTIL_X2_2390 4780 +#define Z_UTIL_X2_2391 4782 +#define Z_UTIL_X2_2392 4784 +#define Z_UTIL_X2_2393 4786 +#define Z_UTIL_X2_2394 4788 +#define Z_UTIL_X2_2395 4790 +#define Z_UTIL_X2_2396 4792 +#define Z_UTIL_X2_2397 4794 +#define Z_UTIL_X2_2398 4796 +#define Z_UTIL_X2_2399 4798 +#define Z_UTIL_X2_2400 4800 +#define Z_UTIL_X2_2401 4802 +#define Z_UTIL_X2_2402 4804 +#define Z_UTIL_X2_2403 4806 +#define Z_UTIL_X2_2404 4808 +#define Z_UTIL_X2_2405 4810 +#define Z_UTIL_X2_2406 4812 +#define Z_UTIL_X2_2407 4814 +#define Z_UTIL_X2_2408 4816 +#define Z_UTIL_X2_2409 4818 +#define Z_UTIL_X2_2410 4820 +#define Z_UTIL_X2_2411 4822 +#define Z_UTIL_X2_2412 4824 +#define Z_UTIL_X2_2413 4826 +#define Z_UTIL_X2_2414 4828 +#define Z_UTIL_X2_2415 4830 +#define Z_UTIL_X2_2416 4832 +#define Z_UTIL_X2_2417 4834 +#define Z_UTIL_X2_2418 4836 +#define Z_UTIL_X2_2419 4838 +#define Z_UTIL_X2_2420 4840 +#define Z_UTIL_X2_2421 4842 +#define Z_UTIL_X2_2422 4844 +#define Z_UTIL_X2_2423 4846 +#define Z_UTIL_X2_2424 4848 +#define Z_UTIL_X2_2425 4850 +#define Z_UTIL_X2_2426 4852 +#define Z_UTIL_X2_2427 4854 +#define Z_UTIL_X2_2428 4856 +#define Z_UTIL_X2_2429 4858 +#define Z_UTIL_X2_2430 4860 +#define Z_UTIL_X2_2431 4862 +#define Z_UTIL_X2_2432 4864 +#define Z_UTIL_X2_2433 4866 +#define Z_UTIL_X2_2434 4868 +#define Z_UTIL_X2_2435 4870 +#define Z_UTIL_X2_2436 4872 +#define Z_UTIL_X2_2437 4874 +#define Z_UTIL_X2_2438 4876 +#define Z_UTIL_X2_2439 4878 +#define Z_UTIL_X2_2440 4880 +#define Z_UTIL_X2_2441 4882 +#define Z_UTIL_X2_2442 4884 +#define Z_UTIL_X2_2443 4886 +#define Z_UTIL_X2_2444 4888 +#define Z_UTIL_X2_2445 4890 +#define Z_UTIL_X2_2446 4892 +#define Z_UTIL_X2_2447 4894 +#define Z_UTIL_X2_2448 4896 +#define Z_UTIL_X2_2449 4898 +#define Z_UTIL_X2_2450 4900 +#define Z_UTIL_X2_2451 4902 +#define Z_UTIL_X2_2452 4904 +#define Z_UTIL_X2_2453 4906 +#define Z_UTIL_X2_2454 4908 +#define Z_UTIL_X2_2455 4910 +#define Z_UTIL_X2_2456 4912 +#define Z_UTIL_X2_2457 4914 +#define Z_UTIL_X2_2458 4916 +#define Z_UTIL_X2_2459 4918 +#define Z_UTIL_X2_2460 4920 +#define Z_UTIL_X2_2461 4922 +#define Z_UTIL_X2_2462 4924 +#define Z_UTIL_X2_2463 4926 +#define Z_UTIL_X2_2464 4928 +#define Z_UTIL_X2_2465 4930 +#define Z_UTIL_X2_2466 4932 +#define Z_UTIL_X2_2467 4934 +#define Z_UTIL_X2_2468 4936 +#define Z_UTIL_X2_2469 4938 +#define Z_UTIL_X2_2470 4940 +#define Z_UTIL_X2_2471 4942 +#define Z_UTIL_X2_2472 4944 +#define Z_UTIL_X2_2473 4946 +#define Z_UTIL_X2_2474 4948 +#define Z_UTIL_X2_2475 4950 +#define Z_UTIL_X2_2476 4952 +#define Z_UTIL_X2_2477 4954 +#define Z_UTIL_X2_2478 4956 +#define Z_UTIL_X2_2479 4958 +#define Z_UTIL_X2_2480 4960 +#define Z_UTIL_X2_2481 4962 +#define Z_UTIL_X2_2482 4964 +#define Z_UTIL_X2_2483 4966 +#define Z_UTIL_X2_2484 4968 +#define Z_UTIL_X2_2485 4970 +#define Z_UTIL_X2_2486 4972 +#define Z_UTIL_X2_2487 4974 +#define Z_UTIL_X2_2488 4976 +#define Z_UTIL_X2_2489 4978 +#define Z_UTIL_X2_2490 4980 +#define Z_UTIL_X2_2491 4982 +#define Z_UTIL_X2_2492 4984 +#define Z_UTIL_X2_2493 4986 +#define Z_UTIL_X2_2494 4988 +#define Z_UTIL_X2_2495 4990 +#define Z_UTIL_X2_2496 4992 +#define Z_UTIL_X2_2497 4994 +#define Z_UTIL_X2_2498 4996 +#define Z_UTIL_X2_2499 4998 +#define Z_UTIL_X2_2500 5000 +#define Z_UTIL_X2_2501 5002 +#define Z_UTIL_X2_2502 5004 +#define Z_UTIL_X2_2503 5006 +#define Z_UTIL_X2_2504 5008 +#define Z_UTIL_X2_2505 5010 +#define Z_UTIL_X2_2506 5012 +#define Z_UTIL_X2_2507 5014 +#define Z_UTIL_X2_2508 5016 +#define Z_UTIL_X2_2509 5018 +#define Z_UTIL_X2_2510 5020 +#define Z_UTIL_X2_2511 5022 +#define Z_UTIL_X2_2512 5024 +#define Z_UTIL_X2_2513 5026 +#define Z_UTIL_X2_2514 5028 +#define Z_UTIL_X2_2515 5030 +#define Z_UTIL_X2_2516 5032 +#define Z_UTIL_X2_2517 5034 +#define Z_UTIL_X2_2518 5036 +#define Z_UTIL_X2_2519 5038 +#define Z_UTIL_X2_2520 5040 +#define Z_UTIL_X2_2521 5042 +#define Z_UTIL_X2_2522 5044 +#define Z_UTIL_X2_2523 5046 +#define Z_UTIL_X2_2524 5048 +#define Z_UTIL_X2_2525 5050 +#define Z_UTIL_X2_2526 5052 +#define Z_UTIL_X2_2527 5054 +#define Z_UTIL_X2_2528 5056 +#define Z_UTIL_X2_2529 5058 +#define Z_UTIL_X2_2530 5060 +#define Z_UTIL_X2_2531 5062 +#define Z_UTIL_X2_2532 5064 +#define Z_UTIL_X2_2533 5066 +#define Z_UTIL_X2_2534 5068 +#define Z_UTIL_X2_2535 5070 +#define Z_UTIL_X2_2536 5072 +#define Z_UTIL_X2_2537 5074 +#define Z_UTIL_X2_2538 5076 +#define Z_UTIL_X2_2539 5078 +#define Z_UTIL_X2_2540 5080 +#define Z_UTIL_X2_2541 5082 +#define Z_UTIL_X2_2542 5084 +#define Z_UTIL_X2_2543 5086 +#define Z_UTIL_X2_2544 5088 +#define Z_UTIL_X2_2545 5090 +#define Z_UTIL_X2_2546 5092 +#define Z_UTIL_X2_2547 5094 +#define Z_UTIL_X2_2548 5096 +#define Z_UTIL_X2_2549 5098 +#define Z_UTIL_X2_2550 5100 +#define Z_UTIL_X2_2551 5102 +#define Z_UTIL_X2_2552 5104 +#define Z_UTIL_X2_2553 5106 +#define Z_UTIL_X2_2554 5108 +#define Z_UTIL_X2_2555 5110 +#define Z_UTIL_X2_2556 5112 +#define Z_UTIL_X2_2557 5114 +#define Z_UTIL_X2_2558 5116 +#define Z_UTIL_X2_2559 5118 +#define Z_UTIL_X2_2560 5120 +#define Z_UTIL_X2_2561 5122 +#define Z_UTIL_X2_2562 5124 +#define Z_UTIL_X2_2563 5126 +#define Z_UTIL_X2_2564 5128 +#define Z_UTIL_X2_2565 5130 +#define Z_UTIL_X2_2566 5132 +#define Z_UTIL_X2_2567 5134 +#define Z_UTIL_X2_2568 5136 +#define Z_UTIL_X2_2569 5138 +#define Z_UTIL_X2_2570 5140 +#define Z_UTIL_X2_2571 5142 +#define Z_UTIL_X2_2572 5144 +#define Z_UTIL_X2_2573 5146 +#define Z_UTIL_X2_2574 5148 +#define Z_UTIL_X2_2575 5150 +#define Z_UTIL_X2_2576 5152 +#define Z_UTIL_X2_2577 5154 +#define Z_UTIL_X2_2578 5156 +#define Z_UTIL_X2_2579 5158 +#define Z_UTIL_X2_2580 5160 +#define Z_UTIL_X2_2581 5162 +#define Z_UTIL_X2_2582 5164 +#define Z_UTIL_X2_2583 5166 +#define Z_UTIL_X2_2584 5168 +#define Z_UTIL_X2_2585 5170 +#define Z_UTIL_X2_2586 5172 +#define Z_UTIL_X2_2587 5174 +#define Z_UTIL_X2_2588 5176 +#define Z_UTIL_X2_2589 5178 +#define Z_UTIL_X2_2590 5180 +#define Z_UTIL_X2_2591 5182 +#define Z_UTIL_X2_2592 5184 +#define Z_UTIL_X2_2593 5186 +#define Z_UTIL_X2_2594 5188 +#define Z_UTIL_X2_2595 5190 +#define Z_UTIL_X2_2596 5192 +#define Z_UTIL_X2_2597 5194 +#define Z_UTIL_X2_2598 5196 +#define Z_UTIL_X2_2599 5198 +#define Z_UTIL_X2_2600 5200 +#define Z_UTIL_X2_2601 5202 +#define Z_UTIL_X2_2602 5204 +#define Z_UTIL_X2_2603 5206 +#define Z_UTIL_X2_2604 5208 +#define Z_UTIL_X2_2605 5210 +#define Z_UTIL_X2_2606 5212 +#define Z_UTIL_X2_2607 5214 +#define Z_UTIL_X2_2608 5216 +#define Z_UTIL_X2_2609 5218 +#define Z_UTIL_X2_2610 5220 +#define Z_UTIL_X2_2611 5222 +#define Z_UTIL_X2_2612 5224 +#define Z_UTIL_X2_2613 5226 +#define Z_UTIL_X2_2614 5228 +#define Z_UTIL_X2_2615 5230 +#define Z_UTIL_X2_2616 5232 +#define Z_UTIL_X2_2617 5234 +#define Z_UTIL_X2_2618 5236 +#define Z_UTIL_X2_2619 5238 +#define Z_UTIL_X2_2620 5240 +#define Z_UTIL_X2_2621 5242 +#define Z_UTIL_X2_2622 5244 +#define Z_UTIL_X2_2623 5246 +#define Z_UTIL_X2_2624 5248 +#define Z_UTIL_X2_2625 5250 +#define Z_UTIL_X2_2626 5252 +#define Z_UTIL_X2_2627 5254 +#define Z_UTIL_X2_2628 5256 +#define Z_UTIL_X2_2629 5258 +#define Z_UTIL_X2_2630 5260 +#define Z_UTIL_X2_2631 5262 +#define Z_UTIL_X2_2632 5264 +#define Z_UTIL_X2_2633 5266 +#define Z_UTIL_X2_2634 5268 +#define Z_UTIL_X2_2635 5270 +#define Z_UTIL_X2_2636 5272 +#define Z_UTIL_X2_2637 5274 +#define Z_UTIL_X2_2638 5276 +#define Z_UTIL_X2_2639 5278 +#define Z_UTIL_X2_2640 5280 +#define Z_UTIL_X2_2641 5282 +#define Z_UTIL_X2_2642 5284 +#define Z_UTIL_X2_2643 5286 +#define Z_UTIL_X2_2644 5288 +#define Z_UTIL_X2_2645 5290 +#define Z_UTIL_X2_2646 5292 +#define Z_UTIL_X2_2647 5294 +#define Z_UTIL_X2_2648 5296 +#define Z_UTIL_X2_2649 5298 +#define Z_UTIL_X2_2650 5300 +#define Z_UTIL_X2_2651 5302 +#define Z_UTIL_X2_2652 5304 +#define Z_UTIL_X2_2653 5306 +#define Z_UTIL_X2_2654 5308 +#define Z_UTIL_X2_2655 5310 +#define Z_UTIL_X2_2656 5312 +#define Z_UTIL_X2_2657 5314 +#define Z_UTIL_X2_2658 5316 +#define Z_UTIL_X2_2659 5318 +#define Z_UTIL_X2_2660 5320 +#define Z_UTIL_X2_2661 5322 +#define Z_UTIL_X2_2662 5324 +#define Z_UTIL_X2_2663 5326 +#define Z_UTIL_X2_2664 5328 +#define Z_UTIL_X2_2665 5330 +#define Z_UTIL_X2_2666 5332 +#define Z_UTIL_X2_2667 5334 +#define Z_UTIL_X2_2668 5336 +#define Z_UTIL_X2_2669 5338 +#define Z_UTIL_X2_2670 5340 +#define Z_UTIL_X2_2671 5342 +#define Z_UTIL_X2_2672 5344 +#define Z_UTIL_X2_2673 5346 +#define Z_UTIL_X2_2674 5348 +#define Z_UTIL_X2_2675 5350 +#define Z_UTIL_X2_2676 5352 +#define Z_UTIL_X2_2677 5354 +#define Z_UTIL_X2_2678 5356 +#define Z_UTIL_X2_2679 5358 +#define Z_UTIL_X2_2680 5360 +#define Z_UTIL_X2_2681 5362 +#define Z_UTIL_X2_2682 5364 +#define Z_UTIL_X2_2683 5366 +#define Z_UTIL_X2_2684 5368 +#define Z_UTIL_X2_2685 5370 +#define Z_UTIL_X2_2686 5372 +#define Z_UTIL_X2_2687 5374 +#define Z_UTIL_X2_2688 5376 +#define Z_UTIL_X2_2689 5378 +#define Z_UTIL_X2_2690 5380 +#define Z_UTIL_X2_2691 5382 +#define Z_UTIL_X2_2692 5384 +#define Z_UTIL_X2_2693 5386 +#define Z_UTIL_X2_2694 5388 +#define Z_UTIL_X2_2695 5390 +#define Z_UTIL_X2_2696 5392 +#define Z_UTIL_X2_2697 5394 +#define Z_UTIL_X2_2698 5396 +#define Z_UTIL_X2_2699 5398 +#define Z_UTIL_X2_2700 5400 +#define Z_UTIL_X2_2701 5402 +#define Z_UTIL_X2_2702 5404 +#define Z_UTIL_X2_2703 5406 +#define Z_UTIL_X2_2704 5408 +#define Z_UTIL_X2_2705 5410 +#define Z_UTIL_X2_2706 5412 +#define Z_UTIL_X2_2707 5414 +#define Z_UTIL_X2_2708 5416 +#define Z_UTIL_X2_2709 5418 +#define Z_UTIL_X2_2710 5420 +#define Z_UTIL_X2_2711 5422 +#define Z_UTIL_X2_2712 5424 +#define Z_UTIL_X2_2713 5426 +#define Z_UTIL_X2_2714 5428 +#define Z_UTIL_X2_2715 5430 +#define Z_UTIL_X2_2716 5432 +#define Z_UTIL_X2_2717 5434 +#define Z_UTIL_X2_2718 5436 +#define Z_UTIL_X2_2719 5438 +#define Z_UTIL_X2_2720 5440 +#define Z_UTIL_X2_2721 5442 +#define Z_UTIL_X2_2722 5444 +#define Z_UTIL_X2_2723 5446 +#define Z_UTIL_X2_2724 5448 +#define Z_UTIL_X2_2725 5450 +#define Z_UTIL_X2_2726 5452 +#define Z_UTIL_X2_2727 5454 +#define Z_UTIL_X2_2728 5456 +#define Z_UTIL_X2_2729 5458 +#define Z_UTIL_X2_2730 5460 +#define Z_UTIL_X2_2731 5462 +#define Z_UTIL_X2_2732 5464 +#define Z_UTIL_X2_2733 5466 +#define Z_UTIL_X2_2734 5468 +#define Z_UTIL_X2_2735 5470 +#define Z_UTIL_X2_2736 5472 +#define Z_UTIL_X2_2737 5474 +#define Z_UTIL_X2_2738 5476 +#define Z_UTIL_X2_2739 5478 +#define Z_UTIL_X2_2740 5480 +#define Z_UTIL_X2_2741 5482 +#define Z_UTIL_X2_2742 5484 +#define Z_UTIL_X2_2743 5486 +#define Z_UTIL_X2_2744 5488 +#define Z_UTIL_X2_2745 5490 +#define Z_UTIL_X2_2746 5492 +#define Z_UTIL_X2_2747 5494 +#define Z_UTIL_X2_2748 5496 +#define Z_UTIL_X2_2749 5498 +#define Z_UTIL_X2_2750 5500 +#define Z_UTIL_X2_2751 5502 +#define Z_UTIL_X2_2752 5504 +#define Z_UTIL_X2_2753 5506 +#define Z_UTIL_X2_2754 5508 +#define Z_UTIL_X2_2755 5510 +#define Z_UTIL_X2_2756 5512 +#define Z_UTIL_X2_2757 5514 +#define Z_UTIL_X2_2758 5516 +#define Z_UTIL_X2_2759 5518 +#define Z_UTIL_X2_2760 5520 +#define Z_UTIL_X2_2761 5522 +#define Z_UTIL_X2_2762 5524 +#define Z_UTIL_X2_2763 5526 +#define Z_UTIL_X2_2764 5528 +#define Z_UTIL_X2_2765 5530 +#define Z_UTIL_X2_2766 5532 +#define Z_UTIL_X2_2767 5534 +#define Z_UTIL_X2_2768 5536 +#define Z_UTIL_X2_2769 5538 +#define Z_UTIL_X2_2770 5540 +#define Z_UTIL_X2_2771 5542 +#define Z_UTIL_X2_2772 5544 +#define Z_UTIL_X2_2773 5546 +#define Z_UTIL_X2_2774 5548 +#define Z_UTIL_X2_2775 5550 +#define Z_UTIL_X2_2776 5552 +#define Z_UTIL_X2_2777 5554 +#define Z_UTIL_X2_2778 5556 +#define Z_UTIL_X2_2779 5558 +#define Z_UTIL_X2_2780 5560 +#define Z_UTIL_X2_2781 5562 +#define Z_UTIL_X2_2782 5564 +#define Z_UTIL_X2_2783 5566 +#define Z_UTIL_X2_2784 5568 +#define Z_UTIL_X2_2785 5570 +#define Z_UTIL_X2_2786 5572 +#define Z_UTIL_X2_2787 5574 +#define Z_UTIL_X2_2788 5576 +#define Z_UTIL_X2_2789 5578 +#define Z_UTIL_X2_2790 5580 +#define Z_UTIL_X2_2791 5582 +#define Z_UTIL_X2_2792 5584 +#define Z_UTIL_X2_2793 5586 +#define Z_UTIL_X2_2794 5588 +#define Z_UTIL_X2_2795 5590 +#define Z_UTIL_X2_2796 5592 +#define Z_UTIL_X2_2797 5594 +#define Z_UTIL_X2_2798 5596 +#define Z_UTIL_X2_2799 5598 +#define Z_UTIL_X2_2800 5600 +#define Z_UTIL_X2_2801 5602 +#define Z_UTIL_X2_2802 5604 +#define Z_UTIL_X2_2803 5606 +#define Z_UTIL_X2_2804 5608 +#define Z_UTIL_X2_2805 5610 +#define Z_UTIL_X2_2806 5612 +#define Z_UTIL_X2_2807 5614 +#define Z_UTIL_X2_2808 5616 +#define Z_UTIL_X2_2809 5618 +#define Z_UTIL_X2_2810 5620 +#define Z_UTIL_X2_2811 5622 +#define Z_UTIL_X2_2812 5624 +#define Z_UTIL_X2_2813 5626 +#define Z_UTIL_X2_2814 5628 +#define Z_UTIL_X2_2815 5630 +#define Z_UTIL_X2_2816 5632 +#define Z_UTIL_X2_2817 5634 +#define Z_UTIL_X2_2818 5636 +#define Z_UTIL_X2_2819 5638 +#define Z_UTIL_X2_2820 5640 +#define Z_UTIL_X2_2821 5642 +#define Z_UTIL_X2_2822 5644 +#define Z_UTIL_X2_2823 5646 +#define Z_UTIL_X2_2824 5648 +#define Z_UTIL_X2_2825 5650 +#define Z_UTIL_X2_2826 5652 +#define Z_UTIL_X2_2827 5654 +#define Z_UTIL_X2_2828 5656 +#define Z_UTIL_X2_2829 5658 +#define Z_UTIL_X2_2830 5660 +#define Z_UTIL_X2_2831 5662 +#define Z_UTIL_X2_2832 5664 +#define Z_UTIL_X2_2833 5666 +#define Z_UTIL_X2_2834 5668 +#define Z_UTIL_X2_2835 5670 +#define Z_UTIL_X2_2836 5672 +#define Z_UTIL_X2_2837 5674 +#define Z_UTIL_X2_2838 5676 +#define Z_UTIL_X2_2839 5678 +#define Z_UTIL_X2_2840 5680 +#define Z_UTIL_X2_2841 5682 +#define Z_UTIL_X2_2842 5684 +#define Z_UTIL_X2_2843 5686 +#define Z_UTIL_X2_2844 5688 +#define Z_UTIL_X2_2845 5690 +#define Z_UTIL_X2_2846 5692 +#define Z_UTIL_X2_2847 5694 +#define Z_UTIL_X2_2848 5696 +#define Z_UTIL_X2_2849 5698 +#define Z_UTIL_X2_2850 5700 +#define Z_UTIL_X2_2851 5702 +#define Z_UTIL_X2_2852 5704 +#define Z_UTIL_X2_2853 5706 +#define Z_UTIL_X2_2854 5708 +#define Z_UTIL_X2_2855 5710 +#define Z_UTIL_X2_2856 5712 +#define Z_UTIL_X2_2857 5714 +#define Z_UTIL_X2_2858 5716 +#define Z_UTIL_X2_2859 5718 +#define Z_UTIL_X2_2860 5720 +#define Z_UTIL_X2_2861 5722 +#define Z_UTIL_X2_2862 5724 +#define Z_UTIL_X2_2863 5726 +#define Z_UTIL_X2_2864 5728 +#define Z_UTIL_X2_2865 5730 +#define Z_UTIL_X2_2866 5732 +#define Z_UTIL_X2_2867 5734 +#define Z_UTIL_X2_2868 5736 +#define Z_UTIL_X2_2869 5738 +#define Z_UTIL_X2_2870 5740 +#define Z_UTIL_X2_2871 5742 +#define Z_UTIL_X2_2872 5744 +#define Z_UTIL_X2_2873 5746 +#define Z_UTIL_X2_2874 5748 +#define Z_UTIL_X2_2875 5750 +#define Z_UTIL_X2_2876 5752 +#define Z_UTIL_X2_2877 5754 +#define Z_UTIL_X2_2878 5756 +#define Z_UTIL_X2_2879 5758 +#define Z_UTIL_X2_2880 5760 +#define Z_UTIL_X2_2881 5762 +#define Z_UTIL_X2_2882 5764 +#define Z_UTIL_X2_2883 5766 +#define Z_UTIL_X2_2884 5768 +#define Z_UTIL_X2_2885 5770 +#define Z_UTIL_X2_2886 5772 +#define Z_UTIL_X2_2887 5774 +#define Z_UTIL_X2_2888 5776 +#define Z_UTIL_X2_2889 5778 +#define Z_UTIL_X2_2890 5780 +#define Z_UTIL_X2_2891 5782 +#define Z_UTIL_X2_2892 5784 +#define Z_UTIL_X2_2893 5786 +#define Z_UTIL_X2_2894 5788 +#define Z_UTIL_X2_2895 5790 +#define Z_UTIL_X2_2896 5792 +#define Z_UTIL_X2_2897 5794 +#define Z_UTIL_X2_2898 5796 +#define Z_UTIL_X2_2899 5798 +#define Z_UTIL_X2_2900 5800 +#define Z_UTIL_X2_2901 5802 +#define Z_UTIL_X2_2902 5804 +#define Z_UTIL_X2_2903 5806 +#define Z_UTIL_X2_2904 5808 +#define Z_UTIL_X2_2905 5810 +#define Z_UTIL_X2_2906 5812 +#define Z_UTIL_X2_2907 5814 +#define Z_UTIL_X2_2908 5816 +#define Z_UTIL_X2_2909 5818 +#define Z_UTIL_X2_2910 5820 +#define Z_UTIL_X2_2911 5822 +#define Z_UTIL_X2_2912 5824 +#define Z_UTIL_X2_2913 5826 +#define Z_UTIL_X2_2914 5828 +#define Z_UTIL_X2_2915 5830 +#define Z_UTIL_X2_2916 5832 +#define Z_UTIL_X2_2917 5834 +#define Z_UTIL_X2_2918 5836 +#define Z_UTIL_X2_2919 5838 +#define Z_UTIL_X2_2920 5840 +#define Z_UTIL_X2_2921 5842 +#define Z_UTIL_X2_2922 5844 +#define Z_UTIL_X2_2923 5846 +#define Z_UTIL_X2_2924 5848 +#define Z_UTIL_X2_2925 5850 +#define Z_UTIL_X2_2926 5852 +#define Z_UTIL_X2_2927 5854 +#define Z_UTIL_X2_2928 5856 +#define Z_UTIL_X2_2929 5858 +#define Z_UTIL_X2_2930 5860 +#define Z_UTIL_X2_2931 5862 +#define Z_UTIL_X2_2932 5864 +#define Z_UTIL_X2_2933 5866 +#define Z_UTIL_X2_2934 5868 +#define Z_UTIL_X2_2935 5870 +#define Z_UTIL_X2_2936 5872 +#define Z_UTIL_X2_2937 5874 +#define Z_UTIL_X2_2938 5876 +#define Z_UTIL_X2_2939 5878 +#define Z_UTIL_X2_2940 5880 +#define Z_UTIL_X2_2941 5882 +#define Z_UTIL_X2_2942 5884 +#define Z_UTIL_X2_2943 5886 +#define Z_UTIL_X2_2944 5888 +#define Z_UTIL_X2_2945 5890 +#define Z_UTIL_X2_2946 5892 +#define Z_UTIL_X2_2947 5894 +#define Z_UTIL_X2_2948 5896 +#define Z_UTIL_X2_2949 5898 +#define Z_UTIL_X2_2950 5900 +#define Z_UTIL_X2_2951 5902 +#define Z_UTIL_X2_2952 5904 +#define Z_UTIL_X2_2953 5906 +#define Z_UTIL_X2_2954 5908 +#define Z_UTIL_X2_2955 5910 +#define Z_UTIL_X2_2956 5912 +#define Z_UTIL_X2_2957 5914 +#define Z_UTIL_X2_2958 5916 +#define Z_UTIL_X2_2959 5918 +#define Z_UTIL_X2_2960 5920 +#define Z_UTIL_X2_2961 5922 +#define Z_UTIL_X2_2962 5924 +#define Z_UTIL_X2_2963 5926 +#define Z_UTIL_X2_2964 5928 +#define Z_UTIL_X2_2965 5930 +#define Z_UTIL_X2_2966 5932 +#define Z_UTIL_X2_2967 5934 +#define Z_UTIL_X2_2968 5936 +#define Z_UTIL_X2_2969 5938 +#define Z_UTIL_X2_2970 5940 +#define Z_UTIL_X2_2971 5942 +#define Z_UTIL_X2_2972 5944 +#define Z_UTIL_X2_2973 5946 +#define Z_UTIL_X2_2974 5948 +#define Z_UTIL_X2_2975 5950 +#define Z_UTIL_X2_2976 5952 +#define Z_UTIL_X2_2977 5954 +#define Z_UTIL_X2_2978 5956 +#define Z_UTIL_X2_2979 5958 +#define Z_UTIL_X2_2980 5960 +#define Z_UTIL_X2_2981 5962 +#define Z_UTIL_X2_2982 5964 +#define Z_UTIL_X2_2983 5966 +#define Z_UTIL_X2_2984 5968 +#define Z_UTIL_X2_2985 5970 +#define Z_UTIL_X2_2986 5972 +#define Z_UTIL_X2_2987 5974 +#define Z_UTIL_X2_2988 5976 +#define Z_UTIL_X2_2989 5978 +#define Z_UTIL_X2_2990 5980 +#define Z_UTIL_X2_2991 5982 +#define Z_UTIL_X2_2992 5984 +#define Z_UTIL_X2_2993 5986 +#define Z_UTIL_X2_2994 5988 +#define Z_UTIL_X2_2995 5990 +#define Z_UTIL_X2_2996 5992 +#define Z_UTIL_X2_2997 5994 +#define Z_UTIL_X2_2998 5996 +#define Z_UTIL_X2_2999 5998 +#define Z_UTIL_X2_3000 6000 +#define Z_UTIL_X2_3001 6002 +#define Z_UTIL_X2_3002 6004 +#define Z_UTIL_X2_3003 6006 +#define Z_UTIL_X2_3004 6008 +#define Z_UTIL_X2_3005 6010 +#define Z_UTIL_X2_3006 6012 +#define Z_UTIL_X2_3007 6014 +#define Z_UTIL_X2_3008 6016 +#define Z_UTIL_X2_3009 6018 +#define Z_UTIL_X2_3010 6020 +#define Z_UTIL_X2_3011 6022 +#define Z_UTIL_X2_3012 6024 +#define Z_UTIL_X2_3013 6026 +#define Z_UTIL_X2_3014 6028 +#define Z_UTIL_X2_3015 6030 +#define Z_UTIL_X2_3016 6032 +#define Z_UTIL_X2_3017 6034 +#define Z_UTIL_X2_3018 6036 +#define Z_UTIL_X2_3019 6038 +#define Z_UTIL_X2_3020 6040 +#define Z_UTIL_X2_3021 6042 +#define Z_UTIL_X2_3022 6044 +#define Z_UTIL_X2_3023 6046 +#define Z_UTIL_X2_3024 6048 +#define Z_UTIL_X2_3025 6050 +#define Z_UTIL_X2_3026 6052 +#define Z_UTIL_X2_3027 6054 +#define Z_UTIL_X2_3028 6056 +#define Z_UTIL_X2_3029 6058 +#define Z_UTIL_X2_3030 6060 +#define Z_UTIL_X2_3031 6062 +#define Z_UTIL_X2_3032 6064 +#define Z_UTIL_X2_3033 6066 +#define Z_UTIL_X2_3034 6068 +#define Z_UTIL_X2_3035 6070 +#define Z_UTIL_X2_3036 6072 +#define Z_UTIL_X2_3037 6074 +#define Z_UTIL_X2_3038 6076 +#define Z_UTIL_X2_3039 6078 +#define Z_UTIL_X2_3040 6080 +#define Z_UTIL_X2_3041 6082 +#define Z_UTIL_X2_3042 6084 +#define Z_UTIL_X2_3043 6086 +#define Z_UTIL_X2_3044 6088 +#define Z_UTIL_X2_3045 6090 +#define Z_UTIL_X2_3046 6092 +#define Z_UTIL_X2_3047 6094 +#define Z_UTIL_X2_3048 6096 +#define Z_UTIL_X2_3049 6098 +#define Z_UTIL_X2_3050 6100 +#define Z_UTIL_X2_3051 6102 +#define Z_UTIL_X2_3052 6104 +#define Z_UTIL_X2_3053 6106 +#define Z_UTIL_X2_3054 6108 +#define Z_UTIL_X2_3055 6110 +#define Z_UTIL_X2_3056 6112 +#define Z_UTIL_X2_3057 6114 +#define Z_UTIL_X2_3058 6116 +#define Z_UTIL_X2_3059 6118 +#define Z_UTIL_X2_3060 6120 +#define Z_UTIL_X2_3061 6122 +#define Z_UTIL_X2_3062 6124 +#define Z_UTIL_X2_3063 6126 +#define Z_UTIL_X2_3064 6128 +#define Z_UTIL_X2_3065 6130 +#define Z_UTIL_X2_3066 6132 +#define Z_UTIL_X2_3067 6134 +#define Z_UTIL_X2_3068 6136 +#define Z_UTIL_X2_3069 6138 +#define Z_UTIL_X2_3070 6140 +#define Z_UTIL_X2_3071 6142 +#define Z_UTIL_X2_3072 6144 +#define Z_UTIL_X2_3073 6146 +#define Z_UTIL_X2_3074 6148 +#define Z_UTIL_X2_3075 6150 +#define Z_UTIL_X2_3076 6152 +#define Z_UTIL_X2_3077 6154 +#define Z_UTIL_X2_3078 6156 +#define Z_UTIL_X2_3079 6158 +#define Z_UTIL_X2_3080 6160 +#define Z_UTIL_X2_3081 6162 +#define Z_UTIL_X2_3082 6164 +#define Z_UTIL_X2_3083 6166 +#define Z_UTIL_X2_3084 6168 +#define Z_UTIL_X2_3085 6170 +#define Z_UTIL_X2_3086 6172 +#define Z_UTIL_X2_3087 6174 +#define Z_UTIL_X2_3088 6176 +#define Z_UTIL_X2_3089 6178 +#define Z_UTIL_X2_3090 6180 +#define Z_UTIL_X2_3091 6182 +#define Z_UTIL_X2_3092 6184 +#define Z_UTIL_X2_3093 6186 +#define Z_UTIL_X2_3094 6188 +#define Z_UTIL_X2_3095 6190 +#define Z_UTIL_X2_3096 6192 +#define Z_UTIL_X2_3097 6194 +#define Z_UTIL_X2_3098 6196 +#define Z_UTIL_X2_3099 6198 +#define Z_UTIL_X2_3100 6200 +#define Z_UTIL_X2_3101 6202 +#define Z_UTIL_X2_3102 6204 +#define Z_UTIL_X2_3103 6206 +#define Z_UTIL_X2_3104 6208 +#define Z_UTIL_X2_3105 6210 +#define Z_UTIL_X2_3106 6212 +#define Z_UTIL_X2_3107 6214 +#define Z_UTIL_X2_3108 6216 +#define Z_UTIL_X2_3109 6218 +#define Z_UTIL_X2_3110 6220 +#define Z_UTIL_X2_3111 6222 +#define Z_UTIL_X2_3112 6224 +#define Z_UTIL_X2_3113 6226 +#define Z_UTIL_X2_3114 6228 +#define Z_UTIL_X2_3115 6230 +#define Z_UTIL_X2_3116 6232 +#define Z_UTIL_X2_3117 6234 +#define Z_UTIL_X2_3118 6236 +#define Z_UTIL_X2_3119 6238 +#define Z_UTIL_X2_3120 6240 +#define Z_UTIL_X2_3121 6242 +#define Z_UTIL_X2_3122 6244 +#define Z_UTIL_X2_3123 6246 +#define Z_UTIL_X2_3124 6248 +#define Z_UTIL_X2_3125 6250 +#define Z_UTIL_X2_3126 6252 +#define Z_UTIL_X2_3127 6254 +#define Z_UTIL_X2_3128 6256 +#define Z_UTIL_X2_3129 6258 +#define Z_UTIL_X2_3130 6260 +#define Z_UTIL_X2_3131 6262 +#define Z_UTIL_X2_3132 6264 +#define Z_UTIL_X2_3133 6266 +#define Z_UTIL_X2_3134 6268 +#define Z_UTIL_X2_3135 6270 +#define Z_UTIL_X2_3136 6272 +#define Z_UTIL_X2_3137 6274 +#define Z_UTIL_X2_3138 6276 +#define Z_UTIL_X2_3139 6278 +#define Z_UTIL_X2_3140 6280 +#define Z_UTIL_X2_3141 6282 +#define Z_UTIL_X2_3142 6284 +#define Z_UTIL_X2_3143 6286 +#define Z_UTIL_X2_3144 6288 +#define Z_UTIL_X2_3145 6290 +#define Z_UTIL_X2_3146 6292 +#define Z_UTIL_X2_3147 6294 +#define Z_UTIL_X2_3148 6296 +#define Z_UTIL_X2_3149 6298 +#define Z_UTIL_X2_3150 6300 +#define Z_UTIL_X2_3151 6302 +#define Z_UTIL_X2_3152 6304 +#define Z_UTIL_X2_3153 6306 +#define Z_UTIL_X2_3154 6308 +#define Z_UTIL_X2_3155 6310 +#define Z_UTIL_X2_3156 6312 +#define Z_UTIL_X2_3157 6314 +#define Z_UTIL_X2_3158 6316 +#define Z_UTIL_X2_3159 6318 +#define Z_UTIL_X2_3160 6320 +#define Z_UTIL_X2_3161 6322 +#define Z_UTIL_X2_3162 6324 +#define Z_UTIL_X2_3163 6326 +#define Z_UTIL_X2_3164 6328 +#define Z_UTIL_X2_3165 6330 +#define Z_UTIL_X2_3166 6332 +#define Z_UTIL_X2_3167 6334 +#define Z_UTIL_X2_3168 6336 +#define Z_UTIL_X2_3169 6338 +#define Z_UTIL_X2_3170 6340 +#define Z_UTIL_X2_3171 6342 +#define Z_UTIL_X2_3172 6344 +#define Z_UTIL_X2_3173 6346 +#define Z_UTIL_X2_3174 6348 +#define Z_UTIL_X2_3175 6350 +#define Z_UTIL_X2_3176 6352 +#define Z_UTIL_X2_3177 6354 +#define Z_UTIL_X2_3178 6356 +#define Z_UTIL_X2_3179 6358 +#define Z_UTIL_X2_3180 6360 +#define Z_UTIL_X2_3181 6362 +#define Z_UTIL_X2_3182 6364 +#define Z_UTIL_X2_3183 6366 +#define Z_UTIL_X2_3184 6368 +#define Z_UTIL_X2_3185 6370 +#define Z_UTIL_X2_3186 6372 +#define Z_UTIL_X2_3187 6374 +#define Z_UTIL_X2_3188 6376 +#define Z_UTIL_X2_3189 6378 +#define Z_UTIL_X2_3190 6380 +#define Z_UTIL_X2_3191 6382 +#define Z_UTIL_X2_3192 6384 +#define Z_UTIL_X2_3193 6386 +#define Z_UTIL_X2_3194 6388 +#define Z_UTIL_X2_3195 6390 +#define Z_UTIL_X2_3196 6392 +#define Z_UTIL_X2_3197 6394 +#define Z_UTIL_X2_3198 6396 +#define Z_UTIL_X2_3199 6398 +#define Z_UTIL_X2_3200 6400 +#define Z_UTIL_X2_3201 6402 +#define Z_UTIL_X2_3202 6404 +#define Z_UTIL_X2_3203 6406 +#define Z_UTIL_X2_3204 6408 +#define Z_UTIL_X2_3205 6410 +#define Z_UTIL_X2_3206 6412 +#define Z_UTIL_X2_3207 6414 +#define Z_UTIL_X2_3208 6416 +#define Z_UTIL_X2_3209 6418 +#define Z_UTIL_X2_3210 6420 +#define Z_UTIL_X2_3211 6422 +#define Z_UTIL_X2_3212 6424 +#define Z_UTIL_X2_3213 6426 +#define Z_UTIL_X2_3214 6428 +#define Z_UTIL_X2_3215 6430 +#define Z_UTIL_X2_3216 6432 +#define Z_UTIL_X2_3217 6434 +#define Z_UTIL_X2_3218 6436 +#define Z_UTIL_X2_3219 6438 +#define Z_UTIL_X2_3220 6440 +#define Z_UTIL_X2_3221 6442 +#define Z_UTIL_X2_3222 6444 +#define Z_UTIL_X2_3223 6446 +#define Z_UTIL_X2_3224 6448 +#define Z_UTIL_X2_3225 6450 +#define Z_UTIL_X2_3226 6452 +#define Z_UTIL_X2_3227 6454 +#define Z_UTIL_X2_3228 6456 +#define Z_UTIL_X2_3229 6458 +#define Z_UTIL_X2_3230 6460 +#define Z_UTIL_X2_3231 6462 +#define Z_UTIL_X2_3232 6464 +#define Z_UTIL_X2_3233 6466 +#define Z_UTIL_X2_3234 6468 +#define Z_UTIL_X2_3235 6470 +#define Z_UTIL_X2_3236 6472 +#define Z_UTIL_X2_3237 6474 +#define Z_UTIL_X2_3238 6476 +#define Z_UTIL_X2_3239 6478 +#define Z_UTIL_X2_3240 6480 +#define Z_UTIL_X2_3241 6482 +#define Z_UTIL_X2_3242 6484 +#define Z_UTIL_X2_3243 6486 +#define Z_UTIL_X2_3244 6488 +#define Z_UTIL_X2_3245 6490 +#define Z_UTIL_X2_3246 6492 +#define Z_UTIL_X2_3247 6494 +#define Z_UTIL_X2_3248 6496 +#define Z_UTIL_X2_3249 6498 +#define Z_UTIL_X2_3250 6500 +#define Z_UTIL_X2_3251 6502 +#define Z_UTIL_X2_3252 6504 +#define Z_UTIL_X2_3253 6506 +#define Z_UTIL_X2_3254 6508 +#define Z_UTIL_X2_3255 6510 +#define Z_UTIL_X2_3256 6512 +#define Z_UTIL_X2_3257 6514 +#define Z_UTIL_X2_3258 6516 +#define Z_UTIL_X2_3259 6518 +#define Z_UTIL_X2_3260 6520 +#define Z_UTIL_X2_3261 6522 +#define Z_UTIL_X2_3262 6524 +#define Z_UTIL_X2_3263 6526 +#define Z_UTIL_X2_3264 6528 +#define Z_UTIL_X2_3265 6530 +#define Z_UTIL_X2_3266 6532 +#define Z_UTIL_X2_3267 6534 +#define Z_UTIL_X2_3268 6536 +#define Z_UTIL_X2_3269 6538 +#define Z_UTIL_X2_3270 6540 +#define Z_UTIL_X2_3271 6542 +#define Z_UTIL_X2_3272 6544 +#define Z_UTIL_X2_3273 6546 +#define Z_UTIL_X2_3274 6548 +#define Z_UTIL_X2_3275 6550 +#define Z_UTIL_X2_3276 6552 +#define Z_UTIL_X2_3277 6554 +#define Z_UTIL_X2_3278 6556 +#define Z_UTIL_X2_3279 6558 +#define Z_UTIL_X2_3280 6560 +#define Z_UTIL_X2_3281 6562 +#define Z_UTIL_X2_3282 6564 +#define Z_UTIL_X2_3283 6566 +#define Z_UTIL_X2_3284 6568 +#define Z_UTIL_X2_3285 6570 +#define Z_UTIL_X2_3286 6572 +#define Z_UTIL_X2_3287 6574 +#define Z_UTIL_X2_3288 6576 +#define Z_UTIL_X2_3289 6578 +#define Z_UTIL_X2_3290 6580 +#define Z_UTIL_X2_3291 6582 +#define Z_UTIL_X2_3292 6584 +#define Z_UTIL_X2_3293 6586 +#define Z_UTIL_X2_3294 6588 +#define Z_UTIL_X2_3295 6590 +#define Z_UTIL_X2_3296 6592 +#define Z_UTIL_X2_3297 6594 +#define Z_UTIL_X2_3298 6596 +#define Z_UTIL_X2_3299 6598 +#define Z_UTIL_X2_3300 6600 +#define Z_UTIL_X2_3301 6602 +#define Z_UTIL_X2_3302 6604 +#define Z_UTIL_X2_3303 6606 +#define Z_UTIL_X2_3304 6608 +#define Z_UTIL_X2_3305 6610 +#define Z_UTIL_X2_3306 6612 +#define Z_UTIL_X2_3307 6614 +#define Z_UTIL_X2_3308 6616 +#define Z_UTIL_X2_3309 6618 +#define Z_UTIL_X2_3310 6620 +#define Z_UTIL_X2_3311 6622 +#define Z_UTIL_X2_3312 6624 +#define Z_UTIL_X2_3313 6626 +#define Z_UTIL_X2_3314 6628 +#define Z_UTIL_X2_3315 6630 +#define Z_UTIL_X2_3316 6632 +#define Z_UTIL_X2_3317 6634 +#define Z_UTIL_X2_3318 6636 +#define Z_UTIL_X2_3319 6638 +#define Z_UTIL_X2_3320 6640 +#define Z_UTIL_X2_3321 6642 +#define Z_UTIL_X2_3322 6644 +#define Z_UTIL_X2_3323 6646 +#define Z_UTIL_X2_3324 6648 +#define Z_UTIL_X2_3325 6650 +#define Z_UTIL_X2_3326 6652 +#define Z_UTIL_X2_3327 6654 +#define Z_UTIL_X2_3328 6656 +#define Z_UTIL_X2_3329 6658 +#define Z_UTIL_X2_3330 6660 +#define Z_UTIL_X2_3331 6662 +#define Z_UTIL_X2_3332 6664 +#define Z_UTIL_X2_3333 6666 +#define Z_UTIL_X2_3334 6668 +#define Z_UTIL_X2_3335 6670 +#define Z_UTIL_X2_3336 6672 +#define Z_UTIL_X2_3337 6674 +#define Z_UTIL_X2_3338 6676 +#define Z_UTIL_X2_3339 6678 +#define Z_UTIL_X2_3340 6680 +#define Z_UTIL_X2_3341 6682 +#define Z_UTIL_X2_3342 6684 +#define Z_UTIL_X2_3343 6686 +#define Z_UTIL_X2_3344 6688 +#define Z_UTIL_X2_3345 6690 +#define Z_UTIL_X2_3346 6692 +#define Z_UTIL_X2_3347 6694 +#define Z_UTIL_X2_3348 6696 +#define Z_UTIL_X2_3349 6698 +#define Z_UTIL_X2_3350 6700 +#define Z_UTIL_X2_3351 6702 +#define Z_UTIL_X2_3352 6704 +#define Z_UTIL_X2_3353 6706 +#define Z_UTIL_X2_3354 6708 +#define Z_UTIL_X2_3355 6710 +#define Z_UTIL_X2_3356 6712 +#define Z_UTIL_X2_3357 6714 +#define Z_UTIL_X2_3358 6716 +#define Z_UTIL_X2_3359 6718 +#define Z_UTIL_X2_3360 6720 +#define Z_UTIL_X2_3361 6722 +#define Z_UTIL_X2_3362 6724 +#define Z_UTIL_X2_3363 6726 +#define Z_UTIL_X2_3364 6728 +#define Z_UTIL_X2_3365 6730 +#define Z_UTIL_X2_3366 6732 +#define Z_UTIL_X2_3367 6734 +#define Z_UTIL_X2_3368 6736 +#define Z_UTIL_X2_3369 6738 +#define Z_UTIL_X2_3370 6740 +#define Z_UTIL_X2_3371 6742 +#define Z_UTIL_X2_3372 6744 +#define Z_UTIL_X2_3373 6746 +#define Z_UTIL_X2_3374 6748 +#define Z_UTIL_X2_3375 6750 +#define Z_UTIL_X2_3376 6752 +#define Z_UTIL_X2_3377 6754 +#define Z_UTIL_X2_3378 6756 +#define Z_UTIL_X2_3379 6758 +#define Z_UTIL_X2_3380 6760 +#define Z_UTIL_X2_3381 6762 +#define Z_UTIL_X2_3382 6764 +#define Z_UTIL_X2_3383 6766 +#define Z_UTIL_X2_3384 6768 +#define Z_UTIL_X2_3385 6770 +#define Z_UTIL_X2_3386 6772 +#define Z_UTIL_X2_3387 6774 +#define Z_UTIL_X2_3388 6776 +#define Z_UTIL_X2_3389 6778 +#define Z_UTIL_X2_3390 6780 +#define Z_UTIL_X2_3391 6782 +#define Z_UTIL_X2_3392 6784 +#define Z_UTIL_X2_3393 6786 +#define Z_UTIL_X2_3394 6788 +#define Z_UTIL_X2_3395 6790 +#define Z_UTIL_X2_3396 6792 +#define Z_UTIL_X2_3397 6794 +#define Z_UTIL_X2_3398 6796 +#define Z_UTIL_X2_3399 6798 +#define Z_UTIL_X2_3400 6800 +#define Z_UTIL_X2_3401 6802 +#define Z_UTIL_X2_3402 6804 +#define Z_UTIL_X2_3403 6806 +#define Z_UTIL_X2_3404 6808 +#define Z_UTIL_X2_3405 6810 +#define Z_UTIL_X2_3406 6812 +#define Z_UTIL_X2_3407 6814 +#define Z_UTIL_X2_3408 6816 +#define Z_UTIL_X2_3409 6818 +#define Z_UTIL_X2_3410 6820 +#define Z_UTIL_X2_3411 6822 +#define Z_UTIL_X2_3412 6824 +#define Z_UTIL_X2_3413 6826 +#define Z_UTIL_X2_3414 6828 +#define Z_UTIL_X2_3415 6830 +#define Z_UTIL_X2_3416 6832 +#define Z_UTIL_X2_3417 6834 +#define Z_UTIL_X2_3418 6836 +#define Z_UTIL_X2_3419 6838 +#define Z_UTIL_X2_3420 6840 +#define Z_UTIL_X2_3421 6842 +#define Z_UTIL_X2_3422 6844 +#define Z_UTIL_X2_3423 6846 +#define Z_UTIL_X2_3424 6848 +#define Z_UTIL_X2_3425 6850 +#define Z_UTIL_X2_3426 6852 +#define Z_UTIL_X2_3427 6854 +#define Z_UTIL_X2_3428 6856 +#define Z_UTIL_X2_3429 6858 +#define Z_UTIL_X2_3430 6860 +#define Z_UTIL_X2_3431 6862 +#define Z_UTIL_X2_3432 6864 +#define Z_UTIL_X2_3433 6866 +#define Z_UTIL_X2_3434 6868 +#define Z_UTIL_X2_3435 6870 +#define Z_UTIL_X2_3436 6872 +#define Z_UTIL_X2_3437 6874 +#define Z_UTIL_X2_3438 6876 +#define Z_UTIL_X2_3439 6878 +#define Z_UTIL_X2_3440 6880 +#define Z_UTIL_X2_3441 6882 +#define Z_UTIL_X2_3442 6884 +#define Z_UTIL_X2_3443 6886 +#define Z_UTIL_X2_3444 6888 +#define Z_UTIL_X2_3445 6890 +#define Z_UTIL_X2_3446 6892 +#define Z_UTIL_X2_3447 6894 +#define Z_UTIL_X2_3448 6896 +#define Z_UTIL_X2_3449 6898 +#define Z_UTIL_X2_3450 6900 +#define Z_UTIL_X2_3451 6902 +#define Z_UTIL_X2_3452 6904 +#define Z_UTIL_X2_3453 6906 +#define Z_UTIL_X2_3454 6908 +#define Z_UTIL_X2_3455 6910 +#define Z_UTIL_X2_3456 6912 +#define Z_UTIL_X2_3457 6914 +#define Z_UTIL_X2_3458 6916 +#define Z_UTIL_X2_3459 6918 +#define Z_UTIL_X2_3460 6920 +#define Z_UTIL_X2_3461 6922 +#define Z_UTIL_X2_3462 6924 +#define Z_UTIL_X2_3463 6926 +#define Z_UTIL_X2_3464 6928 +#define Z_UTIL_X2_3465 6930 +#define Z_UTIL_X2_3466 6932 +#define Z_UTIL_X2_3467 6934 +#define Z_UTIL_X2_3468 6936 +#define Z_UTIL_X2_3469 6938 +#define Z_UTIL_X2_3470 6940 +#define Z_UTIL_X2_3471 6942 +#define Z_UTIL_X2_3472 6944 +#define Z_UTIL_X2_3473 6946 +#define Z_UTIL_X2_3474 6948 +#define Z_UTIL_X2_3475 6950 +#define Z_UTIL_X2_3476 6952 +#define Z_UTIL_X2_3477 6954 +#define Z_UTIL_X2_3478 6956 +#define Z_UTIL_X2_3479 6958 +#define Z_UTIL_X2_3480 6960 +#define Z_UTIL_X2_3481 6962 +#define Z_UTIL_X2_3482 6964 +#define Z_UTIL_X2_3483 6966 +#define Z_UTIL_X2_3484 6968 +#define Z_UTIL_X2_3485 6970 +#define Z_UTIL_X2_3486 6972 +#define Z_UTIL_X2_3487 6974 +#define Z_UTIL_X2_3488 6976 +#define Z_UTIL_X2_3489 6978 +#define Z_UTIL_X2_3490 6980 +#define Z_UTIL_X2_3491 6982 +#define Z_UTIL_X2_3492 6984 +#define Z_UTIL_X2_3493 6986 +#define Z_UTIL_X2_3494 6988 +#define Z_UTIL_X2_3495 6990 +#define Z_UTIL_X2_3496 6992 +#define Z_UTIL_X2_3497 6994 +#define Z_UTIL_X2_3498 6996 +#define Z_UTIL_X2_3499 6998 +#define Z_UTIL_X2_3500 7000 +#define Z_UTIL_X2_3501 7002 +#define Z_UTIL_X2_3502 7004 +#define Z_UTIL_X2_3503 7006 +#define Z_UTIL_X2_3504 7008 +#define Z_UTIL_X2_3505 7010 +#define Z_UTIL_X2_3506 7012 +#define Z_UTIL_X2_3507 7014 +#define Z_UTIL_X2_3508 7016 +#define Z_UTIL_X2_3509 7018 +#define Z_UTIL_X2_3510 7020 +#define Z_UTIL_X2_3511 7022 +#define Z_UTIL_X2_3512 7024 +#define Z_UTIL_X2_3513 7026 +#define Z_UTIL_X2_3514 7028 +#define Z_UTIL_X2_3515 7030 +#define Z_UTIL_X2_3516 7032 +#define Z_UTIL_X2_3517 7034 +#define Z_UTIL_X2_3518 7036 +#define Z_UTIL_X2_3519 7038 +#define Z_UTIL_X2_3520 7040 +#define Z_UTIL_X2_3521 7042 +#define Z_UTIL_X2_3522 7044 +#define Z_UTIL_X2_3523 7046 +#define Z_UTIL_X2_3524 7048 +#define Z_UTIL_X2_3525 7050 +#define Z_UTIL_X2_3526 7052 +#define Z_UTIL_X2_3527 7054 +#define Z_UTIL_X2_3528 7056 +#define Z_UTIL_X2_3529 7058 +#define Z_UTIL_X2_3530 7060 +#define Z_UTIL_X2_3531 7062 +#define Z_UTIL_X2_3532 7064 +#define Z_UTIL_X2_3533 7066 +#define Z_UTIL_X2_3534 7068 +#define Z_UTIL_X2_3535 7070 +#define Z_UTIL_X2_3536 7072 +#define Z_UTIL_X2_3537 7074 +#define Z_UTIL_X2_3538 7076 +#define Z_UTIL_X2_3539 7078 +#define Z_UTIL_X2_3540 7080 +#define Z_UTIL_X2_3541 7082 +#define Z_UTIL_X2_3542 7084 +#define Z_UTIL_X2_3543 7086 +#define Z_UTIL_X2_3544 7088 +#define Z_UTIL_X2_3545 7090 +#define Z_UTIL_X2_3546 7092 +#define Z_UTIL_X2_3547 7094 +#define Z_UTIL_X2_3548 7096 +#define Z_UTIL_X2_3549 7098 +#define Z_UTIL_X2_3550 7100 +#define Z_UTIL_X2_3551 7102 +#define Z_UTIL_X2_3552 7104 +#define Z_UTIL_X2_3553 7106 +#define Z_UTIL_X2_3554 7108 +#define Z_UTIL_X2_3555 7110 +#define Z_UTIL_X2_3556 7112 +#define Z_UTIL_X2_3557 7114 +#define Z_UTIL_X2_3558 7116 +#define Z_UTIL_X2_3559 7118 +#define Z_UTIL_X2_3560 7120 +#define Z_UTIL_X2_3561 7122 +#define Z_UTIL_X2_3562 7124 +#define Z_UTIL_X2_3563 7126 +#define Z_UTIL_X2_3564 7128 +#define Z_UTIL_X2_3565 7130 +#define Z_UTIL_X2_3566 7132 +#define Z_UTIL_X2_3567 7134 +#define Z_UTIL_X2_3568 7136 +#define Z_UTIL_X2_3569 7138 +#define Z_UTIL_X2_3570 7140 +#define Z_UTIL_X2_3571 7142 +#define Z_UTIL_X2_3572 7144 +#define Z_UTIL_X2_3573 7146 +#define Z_UTIL_X2_3574 7148 +#define Z_UTIL_X2_3575 7150 +#define Z_UTIL_X2_3576 7152 +#define Z_UTIL_X2_3577 7154 +#define Z_UTIL_X2_3578 7156 +#define Z_UTIL_X2_3579 7158 +#define Z_UTIL_X2_3580 7160 +#define Z_UTIL_X2_3581 7162 +#define Z_UTIL_X2_3582 7164 +#define Z_UTIL_X2_3583 7166 +#define Z_UTIL_X2_3584 7168 +#define Z_UTIL_X2_3585 7170 +#define Z_UTIL_X2_3586 7172 +#define Z_UTIL_X2_3587 7174 +#define Z_UTIL_X2_3588 7176 +#define Z_UTIL_X2_3589 7178 +#define Z_UTIL_X2_3590 7180 +#define Z_UTIL_X2_3591 7182 +#define Z_UTIL_X2_3592 7184 +#define Z_UTIL_X2_3593 7186 +#define Z_UTIL_X2_3594 7188 +#define Z_UTIL_X2_3595 7190 +#define Z_UTIL_X2_3596 7192 +#define Z_UTIL_X2_3597 7194 +#define Z_UTIL_X2_3598 7196 +#define Z_UTIL_X2_3599 7198 +#define Z_UTIL_X2_3600 7200 +#define Z_UTIL_X2_3601 7202 +#define Z_UTIL_X2_3602 7204 +#define Z_UTIL_X2_3603 7206 +#define Z_UTIL_X2_3604 7208 +#define Z_UTIL_X2_3605 7210 +#define Z_UTIL_X2_3606 7212 +#define Z_UTIL_X2_3607 7214 +#define Z_UTIL_X2_3608 7216 +#define Z_UTIL_X2_3609 7218 +#define Z_UTIL_X2_3610 7220 +#define Z_UTIL_X2_3611 7222 +#define Z_UTIL_X2_3612 7224 +#define Z_UTIL_X2_3613 7226 +#define Z_UTIL_X2_3614 7228 +#define Z_UTIL_X2_3615 7230 +#define Z_UTIL_X2_3616 7232 +#define Z_UTIL_X2_3617 7234 +#define Z_UTIL_X2_3618 7236 +#define Z_UTIL_X2_3619 7238 +#define Z_UTIL_X2_3620 7240 +#define Z_UTIL_X2_3621 7242 +#define Z_UTIL_X2_3622 7244 +#define Z_UTIL_X2_3623 7246 +#define Z_UTIL_X2_3624 7248 +#define Z_UTIL_X2_3625 7250 +#define Z_UTIL_X2_3626 7252 +#define Z_UTIL_X2_3627 7254 +#define Z_UTIL_X2_3628 7256 +#define Z_UTIL_X2_3629 7258 +#define Z_UTIL_X2_3630 7260 +#define Z_UTIL_X2_3631 7262 +#define Z_UTIL_X2_3632 7264 +#define Z_UTIL_X2_3633 7266 +#define Z_UTIL_X2_3634 7268 +#define Z_UTIL_X2_3635 7270 +#define Z_UTIL_X2_3636 7272 +#define Z_UTIL_X2_3637 7274 +#define Z_UTIL_X2_3638 7276 +#define Z_UTIL_X2_3639 7278 +#define Z_UTIL_X2_3640 7280 +#define Z_UTIL_X2_3641 7282 +#define Z_UTIL_X2_3642 7284 +#define Z_UTIL_X2_3643 7286 +#define Z_UTIL_X2_3644 7288 +#define Z_UTIL_X2_3645 7290 +#define Z_UTIL_X2_3646 7292 +#define Z_UTIL_X2_3647 7294 +#define Z_UTIL_X2_3648 7296 +#define Z_UTIL_X2_3649 7298 +#define Z_UTIL_X2_3650 7300 +#define Z_UTIL_X2_3651 7302 +#define Z_UTIL_X2_3652 7304 +#define Z_UTIL_X2_3653 7306 +#define Z_UTIL_X2_3654 7308 +#define Z_UTIL_X2_3655 7310 +#define Z_UTIL_X2_3656 7312 +#define Z_UTIL_X2_3657 7314 +#define Z_UTIL_X2_3658 7316 +#define Z_UTIL_X2_3659 7318 +#define Z_UTIL_X2_3660 7320 +#define Z_UTIL_X2_3661 7322 +#define Z_UTIL_X2_3662 7324 +#define Z_UTIL_X2_3663 7326 +#define Z_UTIL_X2_3664 7328 +#define Z_UTIL_X2_3665 7330 +#define Z_UTIL_X2_3666 7332 +#define Z_UTIL_X2_3667 7334 +#define Z_UTIL_X2_3668 7336 +#define Z_UTIL_X2_3669 7338 +#define Z_UTIL_X2_3670 7340 +#define Z_UTIL_X2_3671 7342 +#define Z_UTIL_X2_3672 7344 +#define Z_UTIL_X2_3673 7346 +#define Z_UTIL_X2_3674 7348 +#define Z_UTIL_X2_3675 7350 +#define Z_UTIL_X2_3676 7352 +#define Z_UTIL_X2_3677 7354 +#define Z_UTIL_X2_3678 7356 +#define Z_UTIL_X2_3679 7358 +#define Z_UTIL_X2_3680 7360 +#define Z_UTIL_X2_3681 7362 +#define Z_UTIL_X2_3682 7364 +#define Z_UTIL_X2_3683 7366 +#define Z_UTIL_X2_3684 7368 +#define Z_UTIL_X2_3685 7370 +#define Z_UTIL_X2_3686 7372 +#define Z_UTIL_X2_3687 7374 +#define Z_UTIL_X2_3688 7376 +#define Z_UTIL_X2_3689 7378 +#define Z_UTIL_X2_3690 7380 +#define Z_UTIL_X2_3691 7382 +#define Z_UTIL_X2_3692 7384 +#define Z_UTIL_X2_3693 7386 +#define Z_UTIL_X2_3694 7388 +#define Z_UTIL_X2_3695 7390 +#define Z_UTIL_X2_3696 7392 +#define Z_UTIL_X2_3697 7394 +#define Z_UTIL_X2_3698 7396 +#define Z_UTIL_X2_3699 7398 +#define Z_UTIL_X2_3700 7400 +#define Z_UTIL_X2_3701 7402 +#define Z_UTIL_X2_3702 7404 +#define Z_UTIL_X2_3703 7406 +#define Z_UTIL_X2_3704 7408 +#define Z_UTIL_X2_3705 7410 +#define Z_UTIL_X2_3706 7412 +#define Z_UTIL_X2_3707 7414 +#define Z_UTIL_X2_3708 7416 +#define Z_UTIL_X2_3709 7418 +#define Z_UTIL_X2_3710 7420 +#define Z_UTIL_X2_3711 7422 +#define Z_UTIL_X2_3712 7424 +#define Z_UTIL_X2_3713 7426 +#define Z_UTIL_X2_3714 7428 +#define Z_UTIL_X2_3715 7430 +#define Z_UTIL_X2_3716 7432 +#define Z_UTIL_X2_3717 7434 +#define Z_UTIL_X2_3718 7436 +#define Z_UTIL_X2_3719 7438 +#define Z_UTIL_X2_3720 7440 +#define Z_UTIL_X2_3721 7442 +#define Z_UTIL_X2_3722 7444 +#define Z_UTIL_X2_3723 7446 +#define Z_UTIL_X2_3724 7448 +#define Z_UTIL_X2_3725 7450 +#define Z_UTIL_X2_3726 7452 +#define Z_UTIL_X2_3727 7454 +#define Z_UTIL_X2_3728 7456 +#define Z_UTIL_X2_3729 7458 +#define Z_UTIL_X2_3730 7460 +#define Z_UTIL_X2_3731 7462 +#define Z_UTIL_X2_3732 7464 +#define Z_UTIL_X2_3733 7466 +#define Z_UTIL_X2_3734 7468 +#define Z_UTIL_X2_3735 7470 +#define Z_UTIL_X2_3736 7472 +#define Z_UTIL_X2_3737 7474 +#define Z_UTIL_X2_3738 7476 +#define Z_UTIL_X2_3739 7478 +#define Z_UTIL_X2_3740 7480 +#define Z_UTIL_X2_3741 7482 +#define Z_UTIL_X2_3742 7484 +#define Z_UTIL_X2_3743 7486 +#define Z_UTIL_X2_3744 7488 +#define Z_UTIL_X2_3745 7490 +#define Z_UTIL_X2_3746 7492 +#define Z_UTIL_X2_3747 7494 +#define Z_UTIL_X2_3748 7496 +#define Z_UTIL_X2_3749 7498 +#define Z_UTIL_X2_3750 7500 +#define Z_UTIL_X2_3751 7502 +#define Z_UTIL_X2_3752 7504 +#define Z_UTIL_X2_3753 7506 +#define Z_UTIL_X2_3754 7508 +#define Z_UTIL_X2_3755 7510 +#define Z_UTIL_X2_3756 7512 +#define Z_UTIL_X2_3757 7514 +#define Z_UTIL_X2_3758 7516 +#define Z_UTIL_X2_3759 7518 +#define Z_UTIL_X2_3760 7520 +#define Z_UTIL_X2_3761 7522 +#define Z_UTIL_X2_3762 7524 +#define Z_UTIL_X2_3763 7526 +#define Z_UTIL_X2_3764 7528 +#define Z_UTIL_X2_3765 7530 +#define Z_UTIL_X2_3766 7532 +#define Z_UTIL_X2_3767 7534 +#define Z_UTIL_X2_3768 7536 +#define Z_UTIL_X2_3769 7538 +#define Z_UTIL_X2_3770 7540 +#define Z_UTIL_X2_3771 7542 +#define Z_UTIL_X2_3772 7544 +#define Z_UTIL_X2_3773 7546 +#define Z_UTIL_X2_3774 7548 +#define Z_UTIL_X2_3775 7550 +#define Z_UTIL_X2_3776 7552 +#define Z_UTIL_X2_3777 7554 +#define Z_UTIL_X2_3778 7556 +#define Z_UTIL_X2_3779 7558 +#define Z_UTIL_X2_3780 7560 +#define Z_UTIL_X2_3781 7562 +#define Z_UTIL_X2_3782 7564 +#define Z_UTIL_X2_3783 7566 +#define Z_UTIL_X2_3784 7568 +#define Z_UTIL_X2_3785 7570 +#define Z_UTIL_X2_3786 7572 +#define Z_UTIL_X2_3787 7574 +#define Z_UTIL_X2_3788 7576 +#define Z_UTIL_X2_3789 7578 +#define Z_UTIL_X2_3790 7580 +#define Z_UTIL_X2_3791 7582 +#define Z_UTIL_X2_3792 7584 +#define Z_UTIL_X2_3793 7586 +#define Z_UTIL_X2_3794 7588 +#define Z_UTIL_X2_3795 7590 +#define Z_UTIL_X2_3796 7592 +#define Z_UTIL_X2_3797 7594 +#define Z_UTIL_X2_3798 7596 +#define Z_UTIL_X2_3799 7598 +#define Z_UTIL_X2_3800 7600 +#define Z_UTIL_X2_3801 7602 +#define Z_UTIL_X2_3802 7604 +#define Z_UTIL_X2_3803 7606 +#define Z_UTIL_X2_3804 7608 +#define Z_UTIL_X2_3805 7610 +#define Z_UTIL_X2_3806 7612 +#define Z_UTIL_X2_3807 7614 +#define Z_UTIL_X2_3808 7616 +#define Z_UTIL_X2_3809 7618 +#define Z_UTIL_X2_3810 7620 +#define Z_UTIL_X2_3811 7622 +#define Z_UTIL_X2_3812 7624 +#define Z_UTIL_X2_3813 7626 +#define Z_UTIL_X2_3814 7628 +#define Z_UTIL_X2_3815 7630 +#define Z_UTIL_X2_3816 7632 +#define Z_UTIL_X2_3817 7634 +#define Z_UTIL_X2_3818 7636 +#define Z_UTIL_X2_3819 7638 +#define Z_UTIL_X2_3820 7640 +#define Z_UTIL_X2_3821 7642 +#define Z_UTIL_X2_3822 7644 +#define Z_UTIL_X2_3823 7646 +#define Z_UTIL_X2_3824 7648 +#define Z_UTIL_X2_3825 7650 +#define Z_UTIL_X2_3826 7652 +#define Z_UTIL_X2_3827 7654 +#define Z_UTIL_X2_3828 7656 +#define Z_UTIL_X2_3829 7658 +#define Z_UTIL_X2_3830 7660 +#define Z_UTIL_X2_3831 7662 +#define Z_UTIL_X2_3832 7664 +#define Z_UTIL_X2_3833 7666 +#define Z_UTIL_X2_3834 7668 +#define Z_UTIL_X2_3835 7670 +#define Z_UTIL_X2_3836 7672 +#define Z_UTIL_X2_3837 7674 +#define Z_UTIL_X2_3838 7676 +#define Z_UTIL_X2_3839 7678 +#define Z_UTIL_X2_3840 7680 +#define Z_UTIL_X2_3841 7682 +#define Z_UTIL_X2_3842 7684 +#define Z_UTIL_X2_3843 7686 +#define Z_UTIL_X2_3844 7688 +#define Z_UTIL_X2_3845 7690 +#define Z_UTIL_X2_3846 7692 +#define Z_UTIL_X2_3847 7694 +#define Z_UTIL_X2_3848 7696 +#define Z_UTIL_X2_3849 7698 +#define Z_UTIL_X2_3850 7700 +#define Z_UTIL_X2_3851 7702 +#define Z_UTIL_X2_3852 7704 +#define Z_UTIL_X2_3853 7706 +#define Z_UTIL_X2_3854 7708 +#define Z_UTIL_X2_3855 7710 +#define Z_UTIL_X2_3856 7712 +#define Z_UTIL_X2_3857 7714 +#define Z_UTIL_X2_3858 7716 +#define Z_UTIL_X2_3859 7718 +#define Z_UTIL_X2_3860 7720 +#define Z_UTIL_X2_3861 7722 +#define Z_UTIL_X2_3862 7724 +#define Z_UTIL_X2_3863 7726 +#define Z_UTIL_X2_3864 7728 +#define Z_UTIL_X2_3865 7730 +#define Z_UTIL_X2_3866 7732 +#define Z_UTIL_X2_3867 7734 +#define Z_UTIL_X2_3868 7736 +#define Z_UTIL_X2_3869 7738 +#define Z_UTIL_X2_3870 7740 +#define Z_UTIL_X2_3871 7742 +#define Z_UTIL_X2_3872 7744 +#define Z_UTIL_X2_3873 7746 +#define Z_UTIL_X2_3874 7748 +#define Z_UTIL_X2_3875 7750 +#define Z_UTIL_X2_3876 7752 +#define Z_UTIL_X2_3877 7754 +#define Z_UTIL_X2_3878 7756 +#define Z_UTIL_X2_3879 7758 +#define Z_UTIL_X2_3880 7760 +#define Z_UTIL_X2_3881 7762 +#define Z_UTIL_X2_3882 7764 +#define Z_UTIL_X2_3883 7766 +#define Z_UTIL_X2_3884 7768 +#define Z_UTIL_X2_3885 7770 +#define Z_UTIL_X2_3886 7772 +#define Z_UTIL_X2_3887 7774 +#define Z_UTIL_X2_3888 7776 +#define Z_UTIL_X2_3889 7778 +#define Z_UTIL_X2_3890 7780 +#define Z_UTIL_X2_3891 7782 +#define Z_UTIL_X2_3892 7784 +#define Z_UTIL_X2_3893 7786 +#define Z_UTIL_X2_3894 7788 +#define Z_UTIL_X2_3895 7790 +#define Z_UTIL_X2_3896 7792 +#define Z_UTIL_X2_3897 7794 +#define Z_UTIL_X2_3898 7796 +#define Z_UTIL_X2_3899 7798 +#define Z_UTIL_X2_3900 7800 +#define Z_UTIL_X2_3901 7802 +#define Z_UTIL_X2_3902 7804 +#define Z_UTIL_X2_3903 7806 +#define Z_UTIL_X2_3904 7808 +#define Z_UTIL_X2_3905 7810 +#define Z_UTIL_X2_3906 7812 +#define Z_UTIL_X2_3907 7814 +#define Z_UTIL_X2_3908 7816 +#define Z_UTIL_X2_3909 7818 +#define Z_UTIL_X2_3910 7820 +#define Z_UTIL_X2_3911 7822 +#define Z_UTIL_X2_3912 7824 +#define Z_UTIL_X2_3913 7826 +#define Z_UTIL_X2_3914 7828 +#define Z_UTIL_X2_3915 7830 +#define Z_UTIL_X2_3916 7832 +#define Z_UTIL_X2_3917 7834 +#define Z_UTIL_X2_3918 7836 +#define Z_UTIL_X2_3919 7838 +#define Z_UTIL_X2_3920 7840 +#define Z_UTIL_X2_3921 7842 +#define Z_UTIL_X2_3922 7844 +#define Z_UTIL_X2_3923 7846 +#define Z_UTIL_X2_3924 7848 +#define Z_UTIL_X2_3925 7850 +#define Z_UTIL_X2_3926 7852 +#define Z_UTIL_X2_3927 7854 +#define Z_UTIL_X2_3928 7856 +#define Z_UTIL_X2_3929 7858 +#define Z_UTIL_X2_3930 7860 +#define Z_UTIL_X2_3931 7862 +#define Z_UTIL_X2_3932 7864 +#define Z_UTIL_X2_3933 7866 +#define Z_UTIL_X2_3934 7868 +#define Z_UTIL_X2_3935 7870 +#define Z_UTIL_X2_3936 7872 +#define Z_UTIL_X2_3937 7874 +#define Z_UTIL_X2_3938 7876 +#define Z_UTIL_X2_3939 7878 +#define Z_UTIL_X2_3940 7880 +#define Z_UTIL_X2_3941 7882 +#define Z_UTIL_X2_3942 7884 +#define Z_UTIL_X2_3943 7886 +#define Z_UTIL_X2_3944 7888 +#define Z_UTIL_X2_3945 7890 +#define Z_UTIL_X2_3946 7892 +#define Z_UTIL_X2_3947 7894 +#define Z_UTIL_X2_3948 7896 +#define Z_UTIL_X2_3949 7898 +#define Z_UTIL_X2_3950 7900 +#define Z_UTIL_X2_3951 7902 +#define Z_UTIL_X2_3952 7904 +#define Z_UTIL_X2_3953 7906 +#define Z_UTIL_X2_3954 7908 +#define Z_UTIL_X2_3955 7910 +#define Z_UTIL_X2_3956 7912 +#define Z_UTIL_X2_3957 7914 +#define Z_UTIL_X2_3958 7916 +#define Z_UTIL_X2_3959 7918 +#define Z_UTIL_X2_3960 7920 +#define Z_UTIL_X2_3961 7922 +#define Z_UTIL_X2_3962 7924 +#define Z_UTIL_X2_3963 7926 +#define Z_UTIL_X2_3964 7928 +#define Z_UTIL_X2_3965 7930 +#define Z_UTIL_X2_3966 7932 +#define Z_UTIL_X2_3967 7934 +#define Z_UTIL_X2_3968 7936 +#define Z_UTIL_X2_3969 7938 +#define Z_UTIL_X2_3970 7940 +#define Z_UTIL_X2_3971 7942 +#define Z_UTIL_X2_3972 7944 +#define Z_UTIL_X2_3973 7946 +#define Z_UTIL_X2_3974 7948 +#define Z_UTIL_X2_3975 7950 +#define Z_UTIL_X2_3976 7952 +#define Z_UTIL_X2_3977 7954 +#define Z_UTIL_X2_3978 7956 +#define Z_UTIL_X2_3979 7958 +#define Z_UTIL_X2_3980 7960 +#define Z_UTIL_X2_3981 7962 +#define Z_UTIL_X2_3982 7964 +#define Z_UTIL_X2_3983 7966 +#define Z_UTIL_X2_3984 7968 +#define Z_UTIL_X2_3985 7970 +#define Z_UTIL_X2_3986 7972 +#define Z_UTIL_X2_3987 7974 +#define Z_UTIL_X2_3988 7976 +#define Z_UTIL_X2_3989 7978 +#define Z_UTIL_X2_3990 7980 +#define Z_UTIL_X2_3991 7982 +#define Z_UTIL_X2_3992 7984 +#define Z_UTIL_X2_3993 7986 +#define Z_UTIL_X2_3994 7988 +#define Z_UTIL_X2_3995 7990 +#define Z_UTIL_X2_3996 7992 +#define Z_UTIL_X2_3997 7994 +#define Z_UTIL_X2_3998 7996 +#define Z_UTIL_X2_3999 7998 +#define Z_UTIL_X2_4000 8000 +#define Z_UTIL_X2_4001 8002 +#define Z_UTIL_X2_4002 8004 +#define Z_UTIL_X2_4003 8006 +#define Z_UTIL_X2_4004 8008 +#define Z_UTIL_X2_4005 8010 +#define Z_UTIL_X2_4006 8012 +#define Z_UTIL_X2_4007 8014 +#define Z_UTIL_X2_4008 8016 +#define Z_UTIL_X2_4009 8018 +#define Z_UTIL_X2_4010 8020 +#define Z_UTIL_X2_4011 8022 +#define Z_UTIL_X2_4012 8024 +#define Z_UTIL_X2_4013 8026 +#define Z_UTIL_X2_4014 8028 +#define Z_UTIL_X2_4015 8030 +#define Z_UTIL_X2_4016 8032 +#define Z_UTIL_X2_4017 8034 +#define Z_UTIL_X2_4018 8036 +#define Z_UTIL_X2_4019 8038 +#define Z_UTIL_X2_4020 8040 +#define Z_UTIL_X2_4021 8042 +#define Z_UTIL_X2_4022 8044 +#define Z_UTIL_X2_4023 8046 +#define Z_UTIL_X2_4024 8048 +#define Z_UTIL_X2_4025 8050 +#define Z_UTIL_X2_4026 8052 +#define Z_UTIL_X2_4027 8054 +#define Z_UTIL_X2_4028 8056 +#define Z_UTIL_X2_4029 8058 +#define Z_UTIL_X2_4030 8060 +#define Z_UTIL_X2_4031 8062 +#define Z_UTIL_X2_4032 8064 +#define Z_UTIL_X2_4033 8066 +#define Z_UTIL_X2_4034 8068 +#define Z_UTIL_X2_4035 8070 +#define Z_UTIL_X2_4036 8072 +#define Z_UTIL_X2_4037 8074 +#define Z_UTIL_X2_4038 8076 +#define Z_UTIL_X2_4039 8078 +#define Z_UTIL_X2_4040 8080 +#define Z_UTIL_X2_4041 8082 +#define Z_UTIL_X2_4042 8084 +#define Z_UTIL_X2_4043 8086 +#define Z_UTIL_X2_4044 8088 +#define Z_UTIL_X2_4045 8090 +#define Z_UTIL_X2_4046 8092 +#define Z_UTIL_X2_4047 8094 +#define Z_UTIL_X2_4048 8096 +#define Z_UTIL_X2_4049 8098 +#define Z_UTIL_X2_4050 8100 +#define Z_UTIL_X2_4051 8102 +#define Z_UTIL_X2_4052 8104 +#define Z_UTIL_X2_4053 8106 +#define Z_UTIL_X2_4054 8108 +#define Z_UTIL_X2_4055 8110 +#define Z_UTIL_X2_4056 8112 +#define Z_UTIL_X2_4057 8114 +#define Z_UTIL_X2_4058 8116 +#define Z_UTIL_X2_4059 8118 +#define Z_UTIL_X2_4060 8120 +#define Z_UTIL_X2_4061 8122 +#define Z_UTIL_X2_4062 8124 +#define Z_UTIL_X2_4063 8126 +#define Z_UTIL_X2_4064 8128 +#define Z_UTIL_X2_4065 8130 +#define Z_UTIL_X2_4066 8132 +#define Z_UTIL_X2_4067 8134 +#define Z_UTIL_X2_4068 8136 +#define Z_UTIL_X2_4069 8138 +#define Z_UTIL_X2_4070 8140 +#define Z_UTIL_X2_4071 8142 +#define Z_UTIL_X2_4072 8144 +#define Z_UTIL_X2_4073 8146 +#define Z_UTIL_X2_4074 8148 +#define Z_UTIL_X2_4075 8150 +#define Z_UTIL_X2_4076 8152 +#define Z_UTIL_X2_4077 8154 +#define Z_UTIL_X2_4078 8156 +#define Z_UTIL_X2_4079 8158 +#define Z_UTIL_X2_4080 8160 +#define Z_UTIL_X2_4081 8162 +#define Z_UTIL_X2_4082 8164 +#define Z_UTIL_X2_4083 8166 +#define Z_UTIL_X2_4084 8168 +#define Z_UTIL_X2_4085 8170 +#define Z_UTIL_X2_4086 8172 +#define Z_UTIL_X2_4087 8174 +#define Z_UTIL_X2_4088 8176 +#define Z_UTIL_X2_4089 8178 +#define Z_UTIL_X2_4090 8180 +#define Z_UTIL_X2_4091 8182 +#define Z_UTIL_X2_4092 8184 +#define Z_UTIL_X2_4093 8186 +#define Z_UTIL_X2_4094 8188 +#define Z_UTIL_X2_4095 8190 + +#endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_UTIL_X2_H_ */ + +/** + * INTERNAL_HIDDEN @endcond + */ diff --git a/include/zephyr/sys/util_listify.h b/include/zephyr/sys/util_listify.h new file mode 100644 index 00000000000..3b755231290 --- /dev/null +++ b/include/zephyr/sys/util_listify.h @@ -0,0 +1,16400 @@ +/* + * Copyright (c) 2021, Nordic Semiconductor ASA + * Copyright (c) 2023, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_SYS_UTIL_LOOPS_H_ +#error "This header should not be used directly, please include util_loops.h instead" +#endif /* ZEPHYR_INCLUDE_SYS_UTIL_LOOPS_H_ */ + +#ifndef ZEPHYR_INCLUDE_SYS_UTIL_LISTIFY_H_ +#define ZEPHYR_INCLUDE_SYS_UTIL_LISTIFY_H_ + +#define Z_UTIL_LISTIFY_0(F, sep, ...) + +#define Z_UTIL_LISTIFY_1(F, sep, ...) \ + F(0, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2(F, sep, ...) \ + Z_UTIL_LISTIFY_1(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3(F, sep, ...) \ + Z_UTIL_LISTIFY_2(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4(F, sep, ...) \ + Z_UTIL_LISTIFY_3(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_5(F, sep, ...) \ + Z_UTIL_LISTIFY_4(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_6(F, sep, ...) \ + Z_UTIL_LISTIFY_5(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(5, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_7(F, sep, ...) \ + Z_UTIL_LISTIFY_6(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(6, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_8(F, sep, ...) \ + Z_UTIL_LISTIFY_7(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(7, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_9(F, sep, ...) \ + Z_UTIL_LISTIFY_8(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(8, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_10(F, sep, ...) \ + Z_UTIL_LISTIFY_9(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(9, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_11(F, sep, ...) \ + Z_UTIL_LISTIFY_10(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(10, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_12(F, sep, ...) \ + Z_UTIL_LISTIFY_11(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(11, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_13(F, sep, ...) \ + Z_UTIL_LISTIFY_12(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(12, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_14(F, sep, ...) \ + Z_UTIL_LISTIFY_13(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(13, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_15(F, sep, ...) \ + Z_UTIL_LISTIFY_14(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(14, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_16(F, sep, ...) \ + Z_UTIL_LISTIFY_15(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(15, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_17(F, sep, ...) \ + Z_UTIL_LISTIFY_16(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(16, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_18(F, sep, ...) \ + Z_UTIL_LISTIFY_17(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(17, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_19(F, sep, ...) \ + Z_UTIL_LISTIFY_18(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(18, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_20(F, sep, ...) \ + Z_UTIL_LISTIFY_19(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(19, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_21(F, sep, ...) \ + Z_UTIL_LISTIFY_20(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(20, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_22(F, sep, ...) \ + Z_UTIL_LISTIFY_21(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(21, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_23(F, sep, ...) \ + Z_UTIL_LISTIFY_22(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(22, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_24(F, sep, ...) \ + Z_UTIL_LISTIFY_23(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(23, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_25(F, sep, ...) \ + Z_UTIL_LISTIFY_24(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(24, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_26(F, sep, ...) \ + Z_UTIL_LISTIFY_25(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(25, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_27(F, sep, ...) \ + Z_UTIL_LISTIFY_26(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(26, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_28(F, sep, ...) \ + Z_UTIL_LISTIFY_27(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(27, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_29(F, sep, ...) \ + Z_UTIL_LISTIFY_28(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(28, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_30(F, sep, ...) \ + Z_UTIL_LISTIFY_29(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(29, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_31(F, sep, ...) \ + Z_UTIL_LISTIFY_30(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(30, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_32(F, sep, ...) \ + Z_UTIL_LISTIFY_31(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(31, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_33(F, sep, ...) \ + Z_UTIL_LISTIFY_32(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(32, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_34(F, sep, ...) \ + Z_UTIL_LISTIFY_33(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(33, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_35(F, sep, ...) \ + Z_UTIL_LISTIFY_34(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(34, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_36(F, sep, ...) \ + Z_UTIL_LISTIFY_35(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(35, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_37(F, sep, ...) \ + Z_UTIL_LISTIFY_36(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(36, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_38(F, sep, ...) \ + Z_UTIL_LISTIFY_37(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(37, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_39(F, sep, ...) \ + Z_UTIL_LISTIFY_38(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(38, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_40(F, sep, ...) \ + Z_UTIL_LISTIFY_39(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(39, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_41(F, sep, ...) \ + Z_UTIL_LISTIFY_40(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(40, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_42(F, sep, ...) \ + Z_UTIL_LISTIFY_41(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(41, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_43(F, sep, ...) \ + Z_UTIL_LISTIFY_42(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(42, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_44(F, sep, ...) \ + Z_UTIL_LISTIFY_43(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(43, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_45(F, sep, ...) \ + Z_UTIL_LISTIFY_44(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(44, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_46(F, sep, ...) \ + Z_UTIL_LISTIFY_45(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(45, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_47(F, sep, ...) \ + Z_UTIL_LISTIFY_46(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(46, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_48(F, sep, ...) \ + Z_UTIL_LISTIFY_47(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(47, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_49(F, sep, ...) \ + Z_UTIL_LISTIFY_48(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(48, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_50(F, sep, ...) \ + Z_UTIL_LISTIFY_49(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(49, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_51(F, sep, ...) \ + Z_UTIL_LISTIFY_50(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(50, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_52(F, sep, ...) \ + Z_UTIL_LISTIFY_51(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(51, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_53(F, sep, ...) \ + Z_UTIL_LISTIFY_52(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(52, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_54(F, sep, ...) \ + Z_UTIL_LISTIFY_53(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(53, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_55(F, sep, ...) \ + Z_UTIL_LISTIFY_54(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(54, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_56(F, sep, ...) \ + Z_UTIL_LISTIFY_55(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(55, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_57(F, sep, ...) \ + Z_UTIL_LISTIFY_56(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(56, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_58(F, sep, ...) \ + Z_UTIL_LISTIFY_57(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(57, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_59(F, sep, ...) \ + Z_UTIL_LISTIFY_58(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(58, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_60(F, sep, ...) \ + Z_UTIL_LISTIFY_59(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(59, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_61(F, sep, ...) \ + Z_UTIL_LISTIFY_60(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(60, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_62(F, sep, ...) \ + Z_UTIL_LISTIFY_61(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(61, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_63(F, sep, ...) \ + Z_UTIL_LISTIFY_62(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(62, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_64(F, sep, ...) \ + Z_UTIL_LISTIFY_63(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(63, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_65(F, sep, ...) \ + Z_UTIL_LISTIFY_64(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(64, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_66(F, sep, ...) \ + Z_UTIL_LISTIFY_65(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(65, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_67(F, sep, ...) \ + Z_UTIL_LISTIFY_66(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(66, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_68(F, sep, ...) \ + Z_UTIL_LISTIFY_67(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(67, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_69(F, sep, ...) \ + Z_UTIL_LISTIFY_68(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(68, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_70(F, sep, ...) \ + Z_UTIL_LISTIFY_69(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(69, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_71(F, sep, ...) \ + Z_UTIL_LISTIFY_70(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(70, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_72(F, sep, ...) \ + Z_UTIL_LISTIFY_71(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(71, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_73(F, sep, ...) \ + Z_UTIL_LISTIFY_72(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(72, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_74(F, sep, ...) \ + Z_UTIL_LISTIFY_73(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(73, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_75(F, sep, ...) \ + Z_UTIL_LISTIFY_74(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(74, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_76(F, sep, ...) \ + Z_UTIL_LISTIFY_75(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(75, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_77(F, sep, ...) \ + Z_UTIL_LISTIFY_76(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(76, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_78(F, sep, ...) \ + Z_UTIL_LISTIFY_77(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(77, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_79(F, sep, ...) \ + Z_UTIL_LISTIFY_78(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(78, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_80(F, sep, ...) \ + Z_UTIL_LISTIFY_79(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(79, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_81(F, sep, ...) \ + Z_UTIL_LISTIFY_80(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(80, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_82(F, sep, ...) \ + Z_UTIL_LISTIFY_81(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(81, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_83(F, sep, ...) \ + Z_UTIL_LISTIFY_82(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(82, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_84(F, sep, ...) \ + Z_UTIL_LISTIFY_83(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(83, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_85(F, sep, ...) \ + Z_UTIL_LISTIFY_84(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(84, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_86(F, sep, ...) \ + Z_UTIL_LISTIFY_85(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(85, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_87(F, sep, ...) \ + Z_UTIL_LISTIFY_86(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(86, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_88(F, sep, ...) \ + Z_UTIL_LISTIFY_87(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(87, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_89(F, sep, ...) \ + Z_UTIL_LISTIFY_88(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(88, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_90(F, sep, ...) \ + Z_UTIL_LISTIFY_89(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(89, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_91(F, sep, ...) \ + Z_UTIL_LISTIFY_90(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(90, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_92(F, sep, ...) \ + Z_UTIL_LISTIFY_91(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(91, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_93(F, sep, ...) \ + Z_UTIL_LISTIFY_92(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(92, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_94(F, sep, ...) \ + Z_UTIL_LISTIFY_93(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(93, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_95(F, sep, ...) \ + Z_UTIL_LISTIFY_94(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(94, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_96(F, sep, ...) \ + Z_UTIL_LISTIFY_95(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(95, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_97(F, sep, ...) \ + Z_UTIL_LISTIFY_96(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(96, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_98(F, sep, ...) \ + Z_UTIL_LISTIFY_97(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(97, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_99(F, sep, ...) \ + Z_UTIL_LISTIFY_98(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(98, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_100(F, sep, ...) \ + Z_UTIL_LISTIFY_99(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(99, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_101(F, sep, ...) \ + Z_UTIL_LISTIFY_100(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(100, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_102(F, sep, ...) \ + Z_UTIL_LISTIFY_101(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(101, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_103(F, sep, ...) \ + Z_UTIL_LISTIFY_102(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(102, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_104(F, sep, ...) \ + Z_UTIL_LISTIFY_103(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(103, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_105(F, sep, ...) \ + Z_UTIL_LISTIFY_104(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(104, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_106(F, sep, ...) \ + Z_UTIL_LISTIFY_105(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(105, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_107(F, sep, ...) \ + Z_UTIL_LISTIFY_106(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(106, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_108(F, sep, ...) \ + Z_UTIL_LISTIFY_107(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(107, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_109(F, sep, ...) \ + Z_UTIL_LISTIFY_108(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(108, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_110(F, sep, ...) \ + Z_UTIL_LISTIFY_109(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(109, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_111(F, sep, ...) \ + Z_UTIL_LISTIFY_110(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(110, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_112(F, sep, ...) \ + Z_UTIL_LISTIFY_111(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(111, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_113(F, sep, ...) \ + Z_UTIL_LISTIFY_112(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(112, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_114(F, sep, ...) \ + Z_UTIL_LISTIFY_113(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(113, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_115(F, sep, ...) \ + Z_UTIL_LISTIFY_114(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(114, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_116(F, sep, ...) \ + Z_UTIL_LISTIFY_115(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(115, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_117(F, sep, ...) \ + Z_UTIL_LISTIFY_116(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(116, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_118(F, sep, ...) \ + Z_UTIL_LISTIFY_117(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(117, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_119(F, sep, ...) \ + Z_UTIL_LISTIFY_118(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(118, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_120(F, sep, ...) \ + Z_UTIL_LISTIFY_119(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(119, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_121(F, sep, ...) \ + Z_UTIL_LISTIFY_120(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(120, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_122(F, sep, ...) \ + Z_UTIL_LISTIFY_121(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(121, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_123(F, sep, ...) \ + Z_UTIL_LISTIFY_122(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(122, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_124(F, sep, ...) \ + Z_UTIL_LISTIFY_123(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(123, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_125(F, sep, ...) \ + Z_UTIL_LISTIFY_124(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(124, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_126(F, sep, ...) \ + Z_UTIL_LISTIFY_125(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(125, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_127(F, sep, ...) \ + Z_UTIL_LISTIFY_126(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(126, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_128(F, sep, ...) \ + Z_UTIL_LISTIFY_127(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(127, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_129(F, sep, ...) \ + Z_UTIL_LISTIFY_128(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(128, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_130(F, sep, ...) \ + Z_UTIL_LISTIFY_129(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(129, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_131(F, sep, ...) \ + Z_UTIL_LISTIFY_130(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(130, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_132(F, sep, ...) \ + Z_UTIL_LISTIFY_131(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(131, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_133(F, sep, ...) \ + Z_UTIL_LISTIFY_132(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(132, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_134(F, sep, ...) \ + Z_UTIL_LISTIFY_133(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(133, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_135(F, sep, ...) \ + Z_UTIL_LISTIFY_134(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(134, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_136(F, sep, ...) \ + Z_UTIL_LISTIFY_135(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(135, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_137(F, sep, ...) \ + Z_UTIL_LISTIFY_136(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(136, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_138(F, sep, ...) \ + Z_UTIL_LISTIFY_137(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(137, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_139(F, sep, ...) \ + Z_UTIL_LISTIFY_138(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(138, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_140(F, sep, ...) \ + Z_UTIL_LISTIFY_139(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(139, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_141(F, sep, ...) \ + Z_UTIL_LISTIFY_140(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(140, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_142(F, sep, ...) \ + Z_UTIL_LISTIFY_141(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(141, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_143(F, sep, ...) \ + Z_UTIL_LISTIFY_142(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(142, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_144(F, sep, ...) \ + Z_UTIL_LISTIFY_143(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(143, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_145(F, sep, ...) \ + Z_UTIL_LISTIFY_144(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(144, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_146(F, sep, ...) \ + Z_UTIL_LISTIFY_145(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(145, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_147(F, sep, ...) \ + Z_UTIL_LISTIFY_146(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(146, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_148(F, sep, ...) \ + Z_UTIL_LISTIFY_147(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(147, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_149(F, sep, ...) \ + Z_UTIL_LISTIFY_148(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(148, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_150(F, sep, ...) \ + Z_UTIL_LISTIFY_149(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(149, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_151(F, sep, ...) \ + Z_UTIL_LISTIFY_150(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(150, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_152(F, sep, ...) \ + Z_UTIL_LISTIFY_151(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(151, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_153(F, sep, ...) \ + Z_UTIL_LISTIFY_152(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(152, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_154(F, sep, ...) \ + Z_UTIL_LISTIFY_153(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(153, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_155(F, sep, ...) \ + Z_UTIL_LISTIFY_154(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(154, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_156(F, sep, ...) \ + Z_UTIL_LISTIFY_155(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(155, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_157(F, sep, ...) \ + Z_UTIL_LISTIFY_156(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(156, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_158(F, sep, ...) \ + Z_UTIL_LISTIFY_157(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(157, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_159(F, sep, ...) \ + Z_UTIL_LISTIFY_158(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(158, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_160(F, sep, ...) \ + Z_UTIL_LISTIFY_159(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(159, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_161(F, sep, ...) \ + Z_UTIL_LISTIFY_160(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(160, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_162(F, sep, ...) \ + Z_UTIL_LISTIFY_161(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(161, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_163(F, sep, ...) \ + Z_UTIL_LISTIFY_162(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(162, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_164(F, sep, ...) \ + Z_UTIL_LISTIFY_163(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(163, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_165(F, sep, ...) \ + Z_UTIL_LISTIFY_164(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(164, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_166(F, sep, ...) \ + Z_UTIL_LISTIFY_165(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(165, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_167(F, sep, ...) \ + Z_UTIL_LISTIFY_166(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(166, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_168(F, sep, ...) \ + Z_UTIL_LISTIFY_167(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(167, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_169(F, sep, ...) \ + Z_UTIL_LISTIFY_168(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(168, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_170(F, sep, ...) \ + Z_UTIL_LISTIFY_169(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(169, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_171(F, sep, ...) \ + Z_UTIL_LISTIFY_170(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(170, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_172(F, sep, ...) \ + Z_UTIL_LISTIFY_171(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(171, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_173(F, sep, ...) \ + Z_UTIL_LISTIFY_172(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(172, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_174(F, sep, ...) \ + Z_UTIL_LISTIFY_173(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(173, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_175(F, sep, ...) \ + Z_UTIL_LISTIFY_174(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(174, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_176(F, sep, ...) \ + Z_UTIL_LISTIFY_175(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(175, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_177(F, sep, ...) \ + Z_UTIL_LISTIFY_176(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(176, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_178(F, sep, ...) \ + Z_UTIL_LISTIFY_177(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(177, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_179(F, sep, ...) \ + Z_UTIL_LISTIFY_178(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(178, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_180(F, sep, ...) \ + Z_UTIL_LISTIFY_179(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(179, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_181(F, sep, ...) \ + Z_UTIL_LISTIFY_180(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(180, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_182(F, sep, ...) \ + Z_UTIL_LISTIFY_181(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(181, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_183(F, sep, ...) \ + Z_UTIL_LISTIFY_182(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(182, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_184(F, sep, ...) \ + Z_UTIL_LISTIFY_183(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(183, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_185(F, sep, ...) \ + Z_UTIL_LISTIFY_184(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(184, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_186(F, sep, ...) \ + Z_UTIL_LISTIFY_185(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(185, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_187(F, sep, ...) \ + Z_UTIL_LISTIFY_186(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(186, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_188(F, sep, ...) \ + Z_UTIL_LISTIFY_187(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(187, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_189(F, sep, ...) \ + Z_UTIL_LISTIFY_188(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(188, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_190(F, sep, ...) \ + Z_UTIL_LISTIFY_189(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(189, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_191(F, sep, ...) \ + Z_UTIL_LISTIFY_190(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(190, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_192(F, sep, ...) \ + Z_UTIL_LISTIFY_191(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(191, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_193(F, sep, ...) \ + Z_UTIL_LISTIFY_192(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(192, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_194(F, sep, ...) \ + Z_UTIL_LISTIFY_193(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(193, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_195(F, sep, ...) \ + Z_UTIL_LISTIFY_194(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(194, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_196(F, sep, ...) \ + Z_UTIL_LISTIFY_195(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(195, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_197(F, sep, ...) \ + Z_UTIL_LISTIFY_196(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(196, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_198(F, sep, ...) \ + Z_UTIL_LISTIFY_197(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(197, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_199(F, sep, ...) \ + Z_UTIL_LISTIFY_198(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(198, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_200(F, sep, ...) \ + Z_UTIL_LISTIFY_199(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(199, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_201(F, sep, ...) \ + Z_UTIL_LISTIFY_200(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(200, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_202(F, sep, ...) \ + Z_UTIL_LISTIFY_201(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(201, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_203(F, sep, ...) \ + Z_UTIL_LISTIFY_202(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(202, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_204(F, sep, ...) \ + Z_UTIL_LISTIFY_203(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(203, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_205(F, sep, ...) \ + Z_UTIL_LISTIFY_204(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(204, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_206(F, sep, ...) \ + Z_UTIL_LISTIFY_205(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(205, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_207(F, sep, ...) \ + Z_UTIL_LISTIFY_206(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(206, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_208(F, sep, ...) \ + Z_UTIL_LISTIFY_207(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(207, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_209(F, sep, ...) \ + Z_UTIL_LISTIFY_208(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(208, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_210(F, sep, ...) \ + Z_UTIL_LISTIFY_209(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(209, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_211(F, sep, ...) \ + Z_UTIL_LISTIFY_210(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(210, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_212(F, sep, ...) \ + Z_UTIL_LISTIFY_211(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(211, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_213(F, sep, ...) \ + Z_UTIL_LISTIFY_212(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(212, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_214(F, sep, ...) \ + Z_UTIL_LISTIFY_213(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(213, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_215(F, sep, ...) \ + Z_UTIL_LISTIFY_214(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(214, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_216(F, sep, ...) \ + Z_UTIL_LISTIFY_215(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(215, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_217(F, sep, ...) \ + Z_UTIL_LISTIFY_216(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(216, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_218(F, sep, ...) \ + Z_UTIL_LISTIFY_217(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(217, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_219(F, sep, ...) \ + Z_UTIL_LISTIFY_218(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(218, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_220(F, sep, ...) \ + Z_UTIL_LISTIFY_219(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(219, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_221(F, sep, ...) \ + Z_UTIL_LISTIFY_220(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(220, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_222(F, sep, ...) \ + Z_UTIL_LISTIFY_221(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(221, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_223(F, sep, ...) \ + Z_UTIL_LISTIFY_222(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(222, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_224(F, sep, ...) \ + Z_UTIL_LISTIFY_223(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(223, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_225(F, sep, ...) \ + Z_UTIL_LISTIFY_224(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(224, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_226(F, sep, ...) \ + Z_UTIL_LISTIFY_225(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(225, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_227(F, sep, ...) \ + Z_UTIL_LISTIFY_226(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(226, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_228(F, sep, ...) \ + Z_UTIL_LISTIFY_227(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(227, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_229(F, sep, ...) \ + Z_UTIL_LISTIFY_228(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(228, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_230(F, sep, ...) \ + Z_UTIL_LISTIFY_229(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(229, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_231(F, sep, ...) \ + Z_UTIL_LISTIFY_230(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(230, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_232(F, sep, ...) \ + Z_UTIL_LISTIFY_231(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(231, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_233(F, sep, ...) \ + Z_UTIL_LISTIFY_232(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(232, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_234(F, sep, ...) \ + Z_UTIL_LISTIFY_233(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(233, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_235(F, sep, ...) \ + Z_UTIL_LISTIFY_234(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(234, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_236(F, sep, ...) \ + Z_UTIL_LISTIFY_235(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(235, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_237(F, sep, ...) \ + Z_UTIL_LISTIFY_236(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(236, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_238(F, sep, ...) \ + Z_UTIL_LISTIFY_237(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(237, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_239(F, sep, ...) \ + Z_UTIL_LISTIFY_238(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(238, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_240(F, sep, ...) \ + Z_UTIL_LISTIFY_239(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(239, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_241(F, sep, ...) \ + Z_UTIL_LISTIFY_240(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(240, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_242(F, sep, ...) \ + Z_UTIL_LISTIFY_241(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(241, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_243(F, sep, ...) \ + Z_UTIL_LISTIFY_242(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(242, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_244(F, sep, ...) \ + Z_UTIL_LISTIFY_243(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(243, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_245(F, sep, ...) \ + Z_UTIL_LISTIFY_244(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(244, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_246(F, sep, ...) \ + Z_UTIL_LISTIFY_245(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(245, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_247(F, sep, ...) \ + Z_UTIL_LISTIFY_246(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(246, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_248(F, sep, ...) \ + Z_UTIL_LISTIFY_247(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(247, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_249(F, sep, ...) \ + Z_UTIL_LISTIFY_248(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(248, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_250(F, sep, ...) \ + Z_UTIL_LISTIFY_249(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(249, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_251(F, sep, ...) \ + Z_UTIL_LISTIFY_250(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(250, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_252(F, sep, ...) \ + Z_UTIL_LISTIFY_251(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(251, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_253(F, sep, ...) \ + Z_UTIL_LISTIFY_252(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(252, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_254(F, sep, ...) \ + Z_UTIL_LISTIFY_253(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(253, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_255(F, sep, ...) \ + Z_UTIL_LISTIFY_254(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(254, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_256(F, sep, ...) \ + Z_UTIL_LISTIFY_255(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(255, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_257(F, sep, ...) \ + Z_UTIL_LISTIFY_256(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(256, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_258(F, sep, ...) \ + Z_UTIL_LISTIFY_257(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(257, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_259(F, sep, ...) \ + Z_UTIL_LISTIFY_258(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(258, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_260(F, sep, ...) \ + Z_UTIL_LISTIFY_259(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(259, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_261(F, sep, ...) \ + Z_UTIL_LISTIFY_260(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(260, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_262(F, sep, ...) \ + Z_UTIL_LISTIFY_261(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(261, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_263(F, sep, ...) \ + Z_UTIL_LISTIFY_262(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(262, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_264(F, sep, ...) \ + Z_UTIL_LISTIFY_263(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(263, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_265(F, sep, ...) \ + Z_UTIL_LISTIFY_264(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(264, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_266(F, sep, ...) \ + Z_UTIL_LISTIFY_265(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(265, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_267(F, sep, ...) \ + Z_UTIL_LISTIFY_266(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(266, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_268(F, sep, ...) \ + Z_UTIL_LISTIFY_267(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(267, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_269(F, sep, ...) \ + Z_UTIL_LISTIFY_268(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(268, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_270(F, sep, ...) \ + Z_UTIL_LISTIFY_269(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(269, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_271(F, sep, ...) \ + Z_UTIL_LISTIFY_270(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(270, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_272(F, sep, ...) \ + Z_UTIL_LISTIFY_271(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(271, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_273(F, sep, ...) \ + Z_UTIL_LISTIFY_272(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(272, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_274(F, sep, ...) \ + Z_UTIL_LISTIFY_273(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(273, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_275(F, sep, ...) \ + Z_UTIL_LISTIFY_274(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(274, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_276(F, sep, ...) \ + Z_UTIL_LISTIFY_275(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(275, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_277(F, sep, ...) \ + Z_UTIL_LISTIFY_276(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(276, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_278(F, sep, ...) \ + Z_UTIL_LISTIFY_277(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(277, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_279(F, sep, ...) \ + Z_UTIL_LISTIFY_278(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(278, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_280(F, sep, ...) \ + Z_UTIL_LISTIFY_279(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(279, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_281(F, sep, ...) \ + Z_UTIL_LISTIFY_280(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(280, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_282(F, sep, ...) \ + Z_UTIL_LISTIFY_281(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(281, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_283(F, sep, ...) \ + Z_UTIL_LISTIFY_282(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(282, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_284(F, sep, ...) \ + Z_UTIL_LISTIFY_283(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(283, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_285(F, sep, ...) \ + Z_UTIL_LISTIFY_284(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(284, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_286(F, sep, ...) \ + Z_UTIL_LISTIFY_285(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(285, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_287(F, sep, ...) \ + Z_UTIL_LISTIFY_286(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(286, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_288(F, sep, ...) \ + Z_UTIL_LISTIFY_287(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(287, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_289(F, sep, ...) \ + Z_UTIL_LISTIFY_288(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(288, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_290(F, sep, ...) \ + Z_UTIL_LISTIFY_289(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(289, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_291(F, sep, ...) \ + Z_UTIL_LISTIFY_290(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(290, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_292(F, sep, ...) \ + Z_UTIL_LISTIFY_291(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(291, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_293(F, sep, ...) \ + Z_UTIL_LISTIFY_292(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(292, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_294(F, sep, ...) \ + Z_UTIL_LISTIFY_293(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(293, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_295(F, sep, ...) \ + Z_UTIL_LISTIFY_294(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(294, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_296(F, sep, ...) \ + Z_UTIL_LISTIFY_295(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(295, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_297(F, sep, ...) \ + Z_UTIL_LISTIFY_296(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(296, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_298(F, sep, ...) \ + Z_UTIL_LISTIFY_297(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(297, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_299(F, sep, ...) \ + Z_UTIL_LISTIFY_298(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(298, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_300(F, sep, ...) \ + Z_UTIL_LISTIFY_299(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(299, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_301(F, sep, ...) \ + Z_UTIL_LISTIFY_300(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(300, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_302(F, sep, ...) \ + Z_UTIL_LISTIFY_301(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(301, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_303(F, sep, ...) \ + Z_UTIL_LISTIFY_302(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(302, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_304(F, sep, ...) \ + Z_UTIL_LISTIFY_303(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(303, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_305(F, sep, ...) \ + Z_UTIL_LISTIFY_304(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(304, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_306(F, sep, ...) \ + Z_UTIL_LISTIFY_305(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(305, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_307(F, sep, ...) \ + Z_UTIL_LISTIFY_306(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(306, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_308(F, sep, ...) \ + Z_UTIL_LISTIFY_307(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(307, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_309(F, sep, ...) \ + Z_UTIL_LISTIFY_308(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(308, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_310(F, sep, ...) \ + Z_UTIL_LISTIFY_309(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(309, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_311(F, sep, ...) \ + Z_UTIL_LISTIFY_310(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(310, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_312(F, sep, ...) \ + Z_UTIL_LISTIFY_311(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(311, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_313(F, sep, ...) \ + Z_UTIL_LISTIFY_312(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(312, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_314(F, sep, ...) \ + Z_UTIL_LISTIFY_313(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(313, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_315(F, sep, ...) \ + Z_UTIL_LISTIFY_314(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(314, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_316(F, sep, ...) \ + Z_UTIL_LISTIFY_315(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(315, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_317(F, sep, ...) \ + Z_UTIL_LISTIFY_316(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(316, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_318(F, sep, ...) \ + Z_UTIL_LISTIFY_317(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(317, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_319(F, sep, ...) \ + Z_UTIL_LISTIFY_318(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(318, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_320(F, sep, ...) \ + Z_UTIL_LISTIFY_319(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(319, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_321(F, sep, ...) \ + Z_UTIL_LISTIFY_320(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(320, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_322(F, sep, ...) \ + Z_UTIL_LISTIFY_321(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(321, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_323(F, sep, ...) \ + Z_UTIL_LISTIFY_322(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(322, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_324(F, sep, ...) \ + Z_UTIL_LISTIFY_323(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(323, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_325(F, sep, ...) \ + Z_UTIL_LISTIFY_324(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(324, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_326(F, sep, ...) \ + Z_UTIL_LISTIFY_325(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(325, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_327(F, sep, ...) \ + Z_UTIL_LISTIFY_326(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(326, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_328(F, sep, ...) \ + Z_UTIL_LISTIFY_327(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(327, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_329(F, sep, ...) \ + Z_UTIL_LISTIFY_328(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(328, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_330(F, sep, ...) \ + Z_UTIL_LISTIFY_329(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(329, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_331(F, sep, ...) \ + Z_UTIL_LISTIFY_330(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(330, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_332(F, sep, ...) \ + Z_UTIL_LISTIFY_331(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(331, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_333(F, sep, ...) \ + Z_UTIL_LISTIFY_332(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(332, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_334(F, sep, ...) \ + Z_UTIL_LISTIFY_333(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(333, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_335(F, sep, ...) \ + Z_UTIL_LISTIFY_334(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(334, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_336(F, sep, ...) \ + Z_UTIL_LISTIFY_335(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(335, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_337(F, sep, ...) \ + Z_UTIL_LISTIFY_336(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(336, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_338(F, sep, ...) \ + Z_UTIL_LISTIFY_337(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(337, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_339(F, sep, ...) \ + Z_UTIL_LISTIFY_338(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(338, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_340(F, sep, ...) \ + Z_UTIL_LISTIFY_339(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(339, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_341(F, sep, ...) \ + Z_UTIL_LISTIFY_340(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(340, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_342(F, sep, ...) \ + Z_UTIL_LISTIFY_341(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(341, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_343(F, sep, ...) \ + Z_UTIL_LISTIFY_342(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(342, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_344(F, sep, ...) \ + Z_UTIL_LISTIFY_343(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(343, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_345(F, sep, ...) \ + Z_UTIL_LISTIFY_344(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(344, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_346(F, sep, ...) \ + Z_UTIL_LISTIFY_345(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(345, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_347(F, sep, ...) \ + Z_UTIL_LISTIFY_346(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(346, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_348(F, sep, ...) \ + Z_UTIL_LISTIFY_347(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(347, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_349(F, sep, ...) \ + Z_UTIL_LISTIFY_348(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(348, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_350(F, sep, ...) \ + Z_UTIL_LISTIFY_349(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(349, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_351(F, sep, ...) \ + Z_UTIL_LISTIFY_350(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(350, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_352(F, sep, ...) \ + Z_UTIL_LISTIFY_351(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(351, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_353(F, sep, ...) \ + Z_UTIL_LISTIFY_352(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(352, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_354(F, sep, ...) \ + Z_UTIL_LISTIFY_353(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(353, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_355(F, sep, ...) \ + Z_UTIL_LISTIFY_354(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(354, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_356(F, sep, ...) \ + Z_UTIL_LISTIFY_355(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(355, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_357(F, sep, ...) \ + Z_UTIL_LISTIFY_356(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(356, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_358(F, sep, ...) \ + Z_UTIL_LISTIFY_357(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(357, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_359(F, sep, ...) \ + Z_UTIL_LISTIFY_358(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(358, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_360(F, sep, ...) \ + Z_UTIL_LISTIFY_359(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(359, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_361(F, sep, ...) \ + Z_UTIL_LISTIFY_360(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(360, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_362(F, sep, ...) \ + Z_UTIL_LISTIFY_361(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(361, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_363(F, sep, ...) \ + Z_UTIL_LISTIFY_362(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(362, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_364(F, sep, ...) \ + Z_UTIL_LISTIFY_363(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(363, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_365(F, sep, ...) \ + Z_UTIL_LISTIFY_364(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(364, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_366(F, sep, ...) \ + Z_UTIL_LISTIFY_365(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(365, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_367(F, sep, ...) \ + Z_UTIL_LISTIFY_366(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(366, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_368(F, sep, ...) \ + Z_UTIL_LISTIFY_367(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(367, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_369(F, sep, ...) \ + Z_UTIL_LISTIFY_368(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(368, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_370(F, sep, ...) \ + Z_UTIL_LISTIFY_369(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(369, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_371(F, sep, ...) \ + Z_UTIL_LISTIFY_370(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(370, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_372(F, sep, ...) \ + Z_UTIL_LISTIFY_371(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(371, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_373(F, sep, ...) \ + Z_UTIL_LISTIFY_372(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(372, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_374(F, sep, ...) \ + Z_UTIL_LISTIFY_373(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(373, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_375(F, sep, ...) \ + Z_UTIL_LISTIFY_374(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(374, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_376(F, sep, ...) \ + Z_UTIL_LISTIFY_375(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(375, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_377(F, sep, ...) \ + Z_UTIL_LISTIFY_376(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(376, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_378(F, sep, ...) \ + Z_UTIL_LISTIFY_377(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(377, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_379(F, sep, ...) \ + Z_UTIL_LISTIFY_378(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(378, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_380(F, sep, ...) \ + Z_UTIL_LISTIFY_379(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(379, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_381(F, sep, ...) \ + Z_UTIL_LISTIFY_380(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(380, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_382(F, sep, ...) \ + Z_UTIL_LISTIFY_381(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(381, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_383(F, sep, ...) \ + Z_UTIL_LISTIFY_382(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(382, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_384(F, sep, ...) \ + Z_UTIL_LISTIFY_383(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(383, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_385(F, sep, ...) \ + Z_UTIL_LISTIFY_384(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(384, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_386(F, sep, ...) \ + Z_UTIL_LISTIFY_385(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(385, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_387(F, sep, ...) \ + Z_UTIL_LISTIFY_386(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(386, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_388(F, sep, ...) \ + Z_UTIL_LISTIFY_387(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(387, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_389(F, sep, ...) \ + Z_UTIL_LISTIFY_388(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(388, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_390(F, sep, ...) \ + Z_UTIL_LISTIFY_389(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(389, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_391(F, sep, ...) \ + Z_UTIL_LISTIFY_390(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(390, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_392(F, sep, ...) \ + Z_UTIL_LISTIFY_391(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(391, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_393(F, sep, ...) \ + Z_UTIL_LISTIFY_392(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(392, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_394(F, sep, ...) \ + Z_UTIL_LISTIFY_393(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(393, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_395(F, sep, ...) \ + Z_UTIL_LISTIFY_394(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(394, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_396(F, sep, ...) \ + Z_UTIL_LISTIFY_395(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(395, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_397(F, sep, ...) \ + Z_UTIL_LISTIFY_396(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(396, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_398(F, sep, ...) \ + Z_UTIL_LISTIFY_397(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(397, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_399(F, sep, ...) \ + Z_UTIL_LISTIFY_398(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(398, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_400(F, sep, ...) \ + Z_UTIL_LISTIFY_399(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(399, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_401(F, sep, ...) \ + Z_UTIL_LISTIFY_400(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(400, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_402(F, sep, ...) \ + Z_UTIL_LISTIFY_401(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(401, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_403(F, sep, ...) \ + Z_UTIL_LISTIFY_402(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(402, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_404(F, sep, ...) \ + Z_UTIL_LISTIFY_403(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(403, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_405(F, sep, ...) \ + Z_UTIL_LISTIFY_404(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(404, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_406(F, sep, ...) \ + Z_UTIL_LISTIFY_405(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(405, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_407(F, sep, ...) \ + Z_UTIL_LISTIFY_406(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(406, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_408(F, sep, ...) \ + Z_UTIL_LISTIFY_407(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(407, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_409(F, sep, ...) \ + Z_UTIL_LISTIFY_408(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(408, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_410(F, sep, ...) \ + Z_UTIL_LISTIFY_409(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(409, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_411(F, sep, ...) \ + Z_UTIL_LISTIFY_410(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(410, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_412(F, sep, ...) \ + Z_UTIL_LISTIFY_411(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(411, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_413(F, sep, ...) \ + Z_UTIL_LISTIFY_412(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(412, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_414(F, sep, ...) \ + Z_UTIL_LISTIFY_413(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(413, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_415(F, sep, ...) \ + Z_UTIL_LISTIFY_414(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(414, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_416(F, sep, ...) \ + Z_UTIL_LISTIFY_415(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(415, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_417(F, sep, ...) \ + Z_UTIL_LISTIFY_416(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(416, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_418(F, sep, ...) \ + Z_UTIL_LISTIFY_417(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(417, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_419(F, sep, ...) \ + Z_UTIL_LISTIFY_418(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(418, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_420(F, sep, ...) \ + Z_UTIL_LISTIFY_419(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(419, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_421(F, sep, ...) \ + Z_UTIL_LISTIFY_420(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(420, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_422(F, sep, ...) \ + Z_UTIL_LISTIFY_421(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(421, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_423(F, sep, ...) \ + Z_UTIL_LISTIFY_422(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(422, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_424(F, sep, ...) \ + Z_UTIL_LISTIFY_423(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(423, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_425(F, sep, ...) \ + Z_UTIL_LISTIFY_424(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(424, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_426(F, sep, ...) \ + Z_UTIL_LISTIFY_425(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(425, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_427(F, sep, ...) \ + Z_UTIL_LISTIFY_426(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(426, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_428(F, sep, ...) \ + Z_UTIL_LISTIFY_427(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(427, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_429(F, sep, ...) \ + Z_UTIL_LISTIFY_428(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(428, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_430(F, sep, ...) \ + Z_UTIL_LISTIFY_429(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(429, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_431(F, sep, ...) \ + Z_UTIL_LISTIFY_430(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(430, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_432(F, sep, ...) \ + Z_UTIL_LISTIFY_431(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(431, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_433(F, sep, ...) \ + Z_UTIL_LISTIFY_432(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(432, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_434(F, sep, ...) \ + Z_UTIL_LISTIFY_433(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(433, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_435(F, sep, ...) \ + Z_UTIL_LISTIFY_434(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(434, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_436(F, sep, ...) \ + Z_UTIL_LISTIFY_435(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(435, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_437(F, sep, ...) \ + Z_UTIL_LISTIFY_436(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(436, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_438(F, sep, ...) \ + Z_UTIL_LISTIFY_437(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(437, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_439(F, sep, ...) \ + Z_UTIL_LISTIFY_438(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(438, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_440(F, sep, ...) \ + Z_UTIL_LISTIFY_439(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(439, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_441(F, sep, ...) \ + Z_UTIL_LISTIFY_440(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(440, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_442(F, sep, ...) \ + Z_UTIL_LISTIFY_441(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(441, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_443(F, sep, ...) \ + Z_UTIL_LISTIFY_442(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(442, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_444(F, sep, ...) \ + Z_UTIL_LISTIFY_443(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(443, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_445(F, sep, ...) \ + Z_UTIL_LISTIFY_444(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(444, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_446(F, sep, ...) \ + Z_UTIL_LISTIFY_445(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(445, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_447(F, sep, ...) \ + Z_UTIL_LISTIFY_446(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(446, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_448(F, sep, ...) \ + Z_UTIL_LISTIFY_447(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(447, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_449(F, sep, ...) \ + Z_UTIL_LISTIFY_448(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(448, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_450(F, sep, ...) \ + Z_UTIL_LISTIFY_449(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(449, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_451(F, sep, ...) \ + Z_UTIL_LISTIFY_450(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(450, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_452(F, sep, ...) \ + Z_UTIL_LISTIFY_451(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(451, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_453(F, sep, ...) \ + Z_UTIL_LISTIFY_452(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(452, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_454(F, sep, ...) \ + Z_UTIL_LISTIFY_453(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(453, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_455(F, sep, ...) \ + Z_UTIL_LISTIFY_454(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(454, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_456(F, sep, ...) \ + Z_UTIL_LISTIFY_455(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(455, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_457(F, sep, ...) \ + Z_UTIL_LISTIFY_456(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(456, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_458(F, sep, ...) \ + Z_UTIL_LISTIFY_457(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(457, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_459(F, sep, ...) \ + Z_UTIL_LISTIFY_458(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(458, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_460(F, sep, ...) \ + Z_UTIL_LISTIFY_459(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(459, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_461(F, sep, ...) \ + Z_UTIL_LISTIFY_460(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(460, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_462(F, sep, ...) \ + Z_UTIL_LISTIFY_461(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(461, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_463(F, sep, ...) \ + Z_UTIL_LISTIFY_462(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(462, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_464(F, sep, ...) \ + Z_UTIL_LISTIFY_463(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(463, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_465(F, sep, ...) \ + Z_UTIL_LISTIFY_464(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(464, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_466(F, sep, ...) \ + Z_UTIL_LISTIFY_465(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(465, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_467(F, sep, ...) \ + Z_UTIL_LISTIFY_466(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(466, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_468(F, sep, ...) \ + Z_UTIL_LISTIFY_467(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(467, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_469(F, sep, ...) \ + Z_UTIL_LISTIFY_468(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(468, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_470(F, sep, ...) \ + Z_UTIL_LISTIFY_469(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(469, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_471(F, sep, ...) \ + Z_UTIL_LISTIFY_470(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(470, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_472(F, sep, ...) \ + Z_UTIL_LISTIFY_471(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(471, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_473(F, sep, ...) \ + Z_UTIL_LISTIFY_472(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(472, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_474(F, sep, ...) \ + Z_UTIL_LISTIFY_473(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(473, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_475(F, sep, ...) \ + Z_UTIL_LISTIFY_474(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(474, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_476(F, sep, ...) \ + Z_UTIL_LISTIFY_475(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(475, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_477(F, sep, ...) \ + Z_UTIL_LISTIFY_476(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(476, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_478(F, sep, ...) \ + Z_UTIL_LISTIFY_477(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(477, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_479(F, sep, ...) \ + Z_UTIL_LISTIFY_478(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(478, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_480(F, sep, ...) \ + Z_UTIL_LISTIFY_479(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(479, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_481(F, sep, ...) \ + Z_UTIL_LISTIFY_480(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(480, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_482(F, sep, ...) \ + Z_UTIL_LISTIFY_481(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(481, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_483(F, sep, ...) \ + Z_UTIL_LISTIFY_482(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(482, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_484(F, sep, ...) \ + Z_UTIL_LISTIFY_483(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(483, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_485(F, sep, ...) \ + Z_UTIL_LISTIFY_484(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(484, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_486(F, sep, ...) \ + Z_UTIL_LISTIFY_485(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(485, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_487(F, sep, ...) \ + Z_UTIL_LISTIFY_486(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(486, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_488(F, sep, ...) \ + Z_UTIL_LISTIFY_487(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(487, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_489(F, sep, ...) \ + Z_UTIL_LISTIFY_488(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(488, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_490(F, sep, ...) \ + Z_UTIL_LISTIFY_489(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(489, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_491(F, sep, ...) \ + Z_UTIL_LISTIFY_490(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(490, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_492(F, sep, ...) \ + Z_UTIL_LISTIFY_491(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(491, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_493(F, sep, ...) \ + Z_UTIL_LISTIFY_492(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(492, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_494(F, sep, ...) \ + Z_UTIL_LISTIFY_493(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(493, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_495(F, sep, ...) \ + Z_UTIL_LISTIFY_494(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(494, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_496(F, sep, ...) \ + Z_UTIL_LISTIFY_495(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(495, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_497(F, sep, ...) \ + Z_UTIL_LISTIFY_496(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(496, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_498(F, sep, ...) \ + Z_UTIL_LISTIFY_497(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(497, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_499(F, sep, ...) \ + Z_UTIL_LISTIFY_498(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(498, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_500(F, sep, ...) \ + Z_UTIL_LISTIFY_499(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(499, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_501(F, sep, ...) \ + Z_UTIL_LISTIFY_500(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(500, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_502(F, sep, ...) \ + Z_UTIL_LISTIFY_501(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(501, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_503(F, sep, ...) \ + Z_UTIL_LISTIFY_502(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(502, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_504(F, sep, ...) \ + Z_UTIL_LISTIFY_503(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(503, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_505(F, sep, ...) \ + Z_UTIL_LISTIFY_504(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(504, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_506(F, sep, ...) \ + Z_UTIL_LISTIFY_505(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(505, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_507(F, sep, ...) \ + Z_UTIL_LISTIFY_506(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(506, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_508(F, sep, ...) \ + Z_UTIL_LISTIFY_507(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(507, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_509(F, sep, ...) \ + Z_UTIL_LISTIFY_508(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(508, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_510(F, sep, ...) \ + Z_UTIL_LISTIFY_509(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(509, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_511(F, sep, ...) \ + Z_UTIL_LISTIFY_510(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(510, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_512(F, sep, ...) \ + Z_UTIL_LISTIFY_511(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(511, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_513(F, sep, ...) \ + Z_UTIL_LISTIFY_512(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(512, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_514(F, sep, ...) \ + Z_UTIL_LISTIFY_513(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(513, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_515(F, sep, ...) \ + Z_UTIL_LISTIFY_514(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(514, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_516(F, sep, ...) \ + Z_UTIL_LISTIFY_515(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(515, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_517(F, sep, ...) \ + Z_UTIL_LISTIFY_516(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(516, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_518(F, sep, ...) \ + Z_UTIL_LISTIFY_517(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(517, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_519(F, sep, ...) \ + Z_UTIL_LISTIFY_518(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(518, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_520(F, sep, ...) \ + Z_UTIL_LISTIFY_519(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(519, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_521(F, sep, ...) \ + Z_UTIL_LISTIFY_520(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(520, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_522(F, sep, ...) \ + Z_UTIL_LISTIFY_521(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(521, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_523(F, sep, ...) \ + Z_UTIL_LISTIFY_522(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(522, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_524(F, sep, ...) \ + Z_UTIL_LISTIFY_523(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(523, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_525(F, sep, ...) \ + Z_UTIL_LISTIFY_524(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(524, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_526(F, sep, ...) \ + Z_UTIL_LISTIFY_525(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(525, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_527(F, sep, ...) \ + Z_UTIL_LISTIFY_526(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(526, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_528(F, sep, ...) \ + Z_UTIL_LISTIFY_527(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(527, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_529(F, sep, ...) \ + Z_UTIL_LISTIFY_528(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(528, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_530(F, sep, ...) \ + Z_UTIL_LISTIFY_529(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(529, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_531(F, sep, ...) \ + Z_UTIL_LISTIFY_530(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(530, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_532(F, sep, ...) \ + Z_UTIL_LISTIFY_531(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(531, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_533(F, sep, ...) \ + Z_UTIL_LISTIFY_532(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(532, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_534(F, sep, ...) \ + Z_UTIL_LISTIFY_533(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(533, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_535(F, sep, ...) \ + Z_UTIL_LISTIFY_534(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(534, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_536(F, sep, ...) \ + Z_UTIL_LISTIFY_535(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(535, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_537(F, sep, ...) \ + Z_UTIL_LISTIFY_536(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(536, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_538(F, sep, ...) \ + Z_UTIL_LISTIFY_537(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(537, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_539(F, sep, ...) \ + Z_UTIL_LISTIFY_538(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(538, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_540(F, sep, ...) \ + Z_UTIL_LISTIFY_539(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(539, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_541(F, sep, ...) \ + Z_UTIL_LISTIFY_540(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(540, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_542(F, sep, ...) \ + Z_UTIL_LISTIFY_541(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(541, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_543(F, sep, ...) \ + Z_UTIL_LISTIFY_542(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(542, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_544(F, sep, ...) \ + Z_UTIL_LISTIFY_543(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(543, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_545(F, sep, ...) \ + Z_UTIL_LISTIFY_544(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(544, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_546(F, sep, ...) \ + Z_UTIL_LISTIFY_545(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(545, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_547(F, sep, ...) \ + Z_UTIL_LISTIFY_546(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(546, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_548(F, sep, ...) \ + Z_UTIL_LISTIFY_547(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(547, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_549(F, sep, ...) \ + Z_UTIL_LISTIFY_548(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(548, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_550(F, sep, ...) \ + Z_UTIL_LISTIFY_549(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(549, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_551(F, sep, ...) \ + Z_UTIL_LISTIFY_550(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(550, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_552(F, sep, ...) \ + Z_UTIL_LISTIFY_551(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(551, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_553(F, sep, ...) \ + Z_UTIL_LISTIFY_552(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(552, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_554(F, sep, ...) \ + Z_UTIL_LISTIFY_553(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(553, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_555(F, sep, ...) \ + Z_UTIL_LISTIFY_554(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(554, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_556(F, sep, ...) \ + Z_UTIL_LISTIFY_555(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(555, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_557(F, sep, ...) \ + Z_UTIL_LISTIFY_556(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(556, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_558(F, sep, ...) \ + Z_UTIL_LISTIFY_557(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(557, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_559(F, sep, ...) \ + Z_UTIL_LISTIFY_558(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(558, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_560(F, sep, ...) \ + Z_UTIL_LISTIFY_559(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(559, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_561(F, sep, ...) \ + Z_UTIL_LISTIFY_560(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(560, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_562(F, sep, ...) \ + Z_UTIL_LISTIFY_561(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(561, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_563(F, sep, ...) \ + Z_UTIL_LISTIFY_562(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(562, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_564(F, sep, ...) \ + Z_UTIL_LISTIFY_563(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(563, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_565(F, sep, ...) \ + Z_UTIL_LISTIFY_564(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(564, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_566(F, sep, ...) \ + Z_UTIL_LISTIFY_565(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(565, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_567(F, sep, ...) \ + Z_UTIL_LISTIFY_566(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(566, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_568(F, sep, ...) \ + Z_UTIL_LISTIFY_567(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(567, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_569(F, sep, ...) \ + Z_UTIL_LISTIFY_568(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(568, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_570(F, sep, ...) \ + Z_UTIL_LISTIFY_569(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(569, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_571(F, sep, ...) \ + Z_UTIL_LISTIFY_570(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(570, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_572(F, sep, ...) \ + Z_UTIL_LISTIFY_571(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(571, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_573(F, sep, ...) \ + Z_UTIL_LISTIFY_572(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(572, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_574(F, sep, ...) \ + Z_UTIL_LISTIFY_573(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(573, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_575(F, sep, ...) \ + Z_UTIL_LISTIFY_574(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(574, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_576(F, sep, ...) \ + Z_UTIL_LISTIFY_575(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(575, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_577(F, sep, ...) \ + Z_UTIL_LISTIFY_576(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(576, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_578(F, sep, ...) \ + Z_UTIL_LISTIFY_577(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(577, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_579(F, sep, ...) \ + Z_UTIL_LISTIFY_578(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(578, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_580(F, sep, ...) \ + Z_UTIL_LISTIFY_579(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(579, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_581(F, sep, ...) \ + Z_UTIL_LISTIFY_580(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(580, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_582(F, sep, ...) \ + Z_UTIL_LISTIFY_581(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(581, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_583(F, sep, ...) \ + Z_UTIL_LISTIFY_582(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(582, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_584(F, sep, ...) \ + Z_UTIL_LISTIFY_583(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(583, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_585(F, sep, ...) \ + Z_UTIL_LISTIFY_584(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(584, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_586(F, sep, ...) \ + Z_UTIL_LISTIFY_585(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(585, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_587(F, sep, ...) \ + Z_UTIL_LISTIFY_586(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(586, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_588(F, sep, ...) \ + Z_UTIL_LISTIFY_587(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(587, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_589(F, sep, ...) \ + Z_UTIL_LISTIFY_588(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(588, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_590(F, sep, ...) \ + Z_UTIL_LISTIFY_589(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(589, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_591(F, sep, ...) \ + Z_UTIL_LISTIFY_590(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(590, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_592(F, sep, ...) \ + Z_UTIL_LISTIFY_591(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(591, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_593(F, sep, ...) \ + Z_UTIL_LISTIFY_592(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(592, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_594(F, sep, ...) \ + Z_UTIL_LISTIFY_593(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(593, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_595(F, sep, ...) \ + Z_UTIL_LISTIFY_594(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(594, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_596(F, sep, ...) \ + Z_UTIL_LISTIFY_595(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(595, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_597(F, sep, ...) \ + Z_UTIL_LISTIFY_596(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(596, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_598(F, sep, ...) \ + Z_UTIL_LISTIFY_597(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(597, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_599(F, sep, ...) \ + Z_UTIL_LISTIFY_598(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(598, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_600(F, sep, ...) \ + Z_UTIL_LISTIFY_599(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(599, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_601(F, sep, ...) \ + Z_UTIL_LISTIFY_600(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(600, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_602(F, sep, ...) \ + Z_UTIL_LISTIFY_601(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(601, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_603(F, sep, ...) \ + Z_UTIL_LISTIFY_602(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(602, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_604(F, sep, ...) \ + Z_UTIL_LISTIFY_603(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(603, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_605(F, sep, ...) \ + Z_UTIL_LISTIFY_604(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(604, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_606(F, sep, ...) \ + Z_UTIL_LISTIFY_605(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(605, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_607(F, sep, ...) \ + Z_UTIL_LISTIFY_606(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(606, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_608(F, sep, ...) \ + Z_UTIL_LISTIFY_607(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(607, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_609(F, sep, ...) \ + Z_UTIL_LISTIFY_608(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(608, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_610(F, sep, ...) \ + Z_UTIL_LISTIFY_609(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(609, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_611(F, sep, ...) \ + Z_UTIL_LISTIFY_610(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(610, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_612(F, sep, ...) \ + Z_UTIL_LISTIFY_611(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(611, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_613(F, sep, ...) \ + Z_UTIL_LISTIFY_612(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(612, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_614(F, sep, ...) \ + Z_UTIL_LISTIFY_613(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(613, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_615(F, sep, ...) \ + Z_UTIL_LISTIFY_614(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(614, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_616(F, sep, ...) \ + Z_UTIL_LISTIFY_615(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(615, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_617(F, sep, ...) \ + Z_UTIL_LISTIFY_616(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(616, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_618(F, sep, ...) \ + Z_UTIL_LISTIFY_617(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(617, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_619(F, sep, ...) \ + Z_UTIL_LISTIFY_618(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(618, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_620(F, sep, ...) \ + Z_UTIL_LISTIFY_619(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(619, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_621(F, sep, ...) \ + Z_UTIL_LISTIFY_620(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(620, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_622(F, sep, ...) \ + Z_UTIL_LISTIFY_621(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(621, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_623(F, sep, ...) \ + Z_UTIL_LISTIFY_622(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(622, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_624(F, sep, ...) \ + Z_UTIL_LISTIFY_623(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(623, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_625(F, sep, ...) \ + Z_UTIL_LISTIFY_624(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(624, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_626(F, sep, ...) \ + Z_UTIL_LISTIFY_625(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(625, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_627(F, sep, ...) \ + Z_UTIL_LISTIFY_626(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(626, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_628(F, sep, ...) \ + Z_UTIL_LISTIFY_627(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(627, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_629(F, sep, ...) \ + Z_UTIL_LISTIFY_628(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(628, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_630(F, sep, ...) \ + Z_UTIL_LISTIFY_629(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(629, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_631(F, sep, ...) \ + Z_UTIL_LISTIFY_630(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(630, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_632(F, sep, ...) \ + Z_UTIL_LISTIFY_631(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(631, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_633(F, sep, ...) \ + Z_UTIL_LISTIFY_632(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(632, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_634(F, sep, ...) \ + Z_UTIL_LISTIFY_633(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(633, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_635(F, sep, ...) \ + Z_UTIL_LISTIFY_634(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(634, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_636(F, sep, ...) \ + Z_UTIL_LISTIFY_635(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(635, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_637(F, sep, ...) \ + Z_UTIL_LISTIFY_636(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(636, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_638(F, sep, ...) \ + Z_UTIL_LISTIFY_637(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(637, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_639(F, sep, ...) \ + Z_UTIL_LISTIFY_638(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(638, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_640(F, sep, ...) \ + Z_UTIL_LISTIFY_639(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(639, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_641(F, sep, ...) \ + Z_UTIL_LISTIFY_640(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(640, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_642(F, sep, ...) \ + Z_UTIL_LISTIFY_641(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(641, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_643(F, sep, ...) \ + Z_UTIL_LISTIFY_642(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(642, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_644(F, sep, ...) \ + Z_UTIL_LISTIFY_643(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(643, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_645(F, sep, ...) \ + Z_UTIL_LISTIFY_644(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(644, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_646(F, sep, ...) \ + Z_UTIL_LISTIFY_645(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(645, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_647(F, sep, ...) \ + Z_UTIL_LISTIFY_646(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(646, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_648(F, sep, ...) \ + Z_UTIL_LISTIFY_647(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(647, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_649(F, sep, ...) \ + Z_UTIL_LISTIFY_648(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(648, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_650(F, sep, ...) \ + Z_UTIL_LISTIFY_649(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(649, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_651(F, sep, ...) \ + Z_UTIL_LISTIFY_650(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(650, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_652(F, sep, ...) \ + Z_UTIL_LISTIFY_651(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(651, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_653(F, sep, ...) \ + Z_UTIL_LISTIFY_652(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(652, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_654(F, sep, ...) \ + Z_UTIL_LISTIFY_653(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(653, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_655(F, sep, ...) \ + Z_UTIL_LISTIFY_654(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(654, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_656(F, sep, ...) \ + Z_UTIL_LISTIFY_655(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(655, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_657(F, sep, ...) \ + Z_UTIL_LISTIFY_656(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(656, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_658(F, sep, ...) \ + Z_UTIL_LISTIFY_657(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(657, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_659(F, sep, ...) \ + Z_UTIL_LISTIFY_658(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(658, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_660(F, sep, ...) \ + Z_UTIL_LISTIFY_659(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(659, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_661(F, sep, ...) \ + Z_UTIL_LISTIFY_660(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(660, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_662(F, sep, ...) \ + Z_UTIL_LISTIFY_661(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(661, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_663(F, sep, ...) \ + Z_UTIL_LISTIFY_662(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(662, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_664(F, sep, ...) \ + Z_UTIL_LISTIFY_663(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(663, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_665(F, sep, ...) \ + Z_UTIL_LISTIFY_664(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(664, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_666(F, sep, ...) \ + Z_UTIL_LISTIFY_665(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(665, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_667(F, sep, ...) \ + Z_UTIL_LISTIFY_666(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(666, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_668(F, sep, ...) \ + Z_UTIL_LISTIFY_667(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(667, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_669(F, sep, ...) \ + Z_UTIL_LISTIFY_668(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(668, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_670(F, sep, ...) \ + Z_UTIL_LISTIFY_669(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(669, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_671(F, sep, ...) \ + Z_UTIL_LISTIFY_670(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(670, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_672(F, sep, ...) \ + Z_UTIL_LISTIFY_671(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(671, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_673(F, sep, ...) \ + Z_UTIL_LISTIFY_672(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(672, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_674(F, sep, ...) \ + Z_UTIL_LISTIFY_673(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(673, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_675(F, sep, ...) \ + Z_UTIL_LISTIFY_674(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(674, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_676(F, sep, ...) \ + Z_UTIL_LISTIFY_675(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(675, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_677(F, sep, ...) \ + Z_UTIL_LISTIFY_676(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(676, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_678(F, sep, ...) \ + Z_UTIL_LISTIFY_677(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(677, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_679(F, sep, ...) \ + Z_UTIL_LISTIFY_678(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(678, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_680(F, sep, ...) \ + Z_UTIL_LISTIFY_679(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(679, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_681(F, sep, ...) \ + Z_UTIL_LISTIFY_680(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(680, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_682(F, sep, ...) \ + Z_UTIL_LISTIFY_681(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(681, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_683(F, sep, ...) \ + Z_UTIL_LISTIFY_682(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(682, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_684(F, sep, ...) \ + Z_UTIL_LISTIFY_683(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(683, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_685(F, sep, ...) \ + Z_UTIL_LISTIFY_684(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(684, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_686(F, sep, ...) \ + Z_UTIL_LISTIFY_685(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(685, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_687(F, sep, ...) \ + Z_UTIL_LISTIFY_686(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(686, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_688(F, sep, ...) \ + Z_UTIL_LISTIFY_687(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(687, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_689(F, sep, ...) \ + Z_UTIL_LISTIFY_688(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(688, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_690(F, sep, ...) \ + Z_UTIL_LISTIFY_689(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(689, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_691(F, sep, ...) \ + Z_UTIL_LISTIFY_690(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(690, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_692(F, sep, ...) \ + Z_UTIL_LISTIFY_691(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(691, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_693(F, sep, ...) \ + Z_UTIL_LISTIFY_692(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(692, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_694(F, sep, ...) \ + Z_UTIL_LISTIFY_693(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(693, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_695(F, sep, ...) \ + Z_UTIL_LISTIFY_694(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(694, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_696(F, sep, ...) \ + Z_UTIL_LISTIFY_695(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(695, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_697(F, sep, ...) \ + Z_UTIL_LISTIFY_696(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(696, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_698(F, sep, ...) \ + Z_UTIL_LISTIFY_697(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(697, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_699(F, sep, ...) \ + Z_UTIL_LISTIFY_698(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(698, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_700(F, sep, ...) \ + Z_UTIL_LISTIFY_699(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(699, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_701(F, sep, ...) \ + Z_UTIL_LISTIFY_700(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(700, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_702(F, sep, ...) \ + Z_UTIL_LISTIFY_701(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(701, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_703(F, sep, ...) \ + Z_UTIL_LISTIFY_702(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(702, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_704(F, sep, ...) \ + Z_UTIL_LISTIFY_703(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(703, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_705(F, sep, ...) \ + Z_UTIL_LISTIFY_704(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(704, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_706(F, sep, ...) \ + Z_UTIL_LISTIFY_705(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(705, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_707(F, sep, ...) \ + Z_UTIL_LISTIFY_706(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(706, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_708(F, sep, ...) \ + Z_UTIL_LISTIFY_707(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(707, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_709(F, sep, ...) \ + Z_UTIL_LISTIFY_708(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(708, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_710(F, sep, ...) \ + Z_UTIL_LISTIFY_709(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(709, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_711(F, sep, ...) \ + Z_UTIL_LISTIFY_710(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(710, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_712(F, sep, ...) \ + Z_UTIL_LISTIFY_711(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(711, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_713(F, sep, ...) \ + Z_UTIL_LISTIFY_712(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(712, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_714(F, sep, ...) \ + Z_UTIL_LISTIFY_713(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(713, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_715(F, sep, ...) \ + Z_UTIL_LISTIFY_714(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(714, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_716(F, sep, ...) \ + Z_UTIL_LISTIFY_715(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(715, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_717(F, sep, ...) \ + Z_UTIL_LISTIFY_716(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(716, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_718(F, sep, ...) \ + Z_UTIL_LISTIFY_717(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(717, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_719(F, sep, ...) \ + Z_UTIL_LISTIFY_718(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(718, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_720(F, sep, ...) \ + Z_UTIL_LISTIFY_719(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(719, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_721(F, sep, ...) \ + Z_UTIL_LISTIFY_720(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(720, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_722(F, sep, ...) \ + Z_UTIL_LISTIFY_721(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(721, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_723(F, sep, ...) \ + Z_UTIL_LISTIFY_722(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(722, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_724(F, sep, ...) \ + Z_UTIL_LISTIFY_723(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(723, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_725(F, sep, ...) \ + Z_UTIL_LISTIFY_724(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(724, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_726(F, sep, ...) \ + Z_UTIL_LISTIFY_725(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(725, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_727(F, sep, ...) \ + Z_UTIL_LISTIFY_726(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(726, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_728(F, sep, ...) \ + Z_UTIL_LISTIFY_727(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(727, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_729(F, sep, ...) \ + Z_UTIL_LISTIFY_728(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(728, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_730(F, sep, ...) \ + Z_UTIL_LISTIFY_729(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(729, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_731(F, sep, ...) \ + Z_UTIL_LISTIFY_730(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(730, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_732(F, sep, ...) \ + Z_UTIL_LISTIFY_731(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(731, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_733(F, sep, ...) \ + Z_UTIL_LISTIFY_732(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(732, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_734(F, sep, ...) \ + Z_UTIL_LISTIFY_733(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(733, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_735(F, sep, ...) \ + Z_UTIL_LISTIFY_734(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(734, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_736(F, sep, ...) \ + Z_UTIL_LISTIFY_735(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(735, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_737(F, sep, ...) \ + Z_UTIL_LISTIFY_736(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(736, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_738(F, sep, ...) \ + Z_UTIL_LISTIFY_737(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(737, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_739(F, sep, ...) \ + Z_UTIL_LISTIFY_738(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(738, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_740(F, sep, ...) \ + Z_UTIL_LISTIFY_739(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(739, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_741(F, sep, ...) \ + Z_UTIL_LISTIFY_740(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(740, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_742(F, sep, ...) \ + Z_UTIL_LISTIFY_741(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(741, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_743(F, sep, ...) \ + Z_UTIL_LISTIFY_742(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(742, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_744(F, sep, ...) \ + Z_UTIL_LISTIFY_743(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(743, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_745(F, sep, ...) \ + Z_UTIL_LISTIFY_744(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(744, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_746(F, sep, ...) \ + Z_UTIL_LISTIFY_745(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(745, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_747(F, sep, ...) \ + Z_UTIL_LISTIFY_746(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(746, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_748(F, sep, ...) \ + Z_UTIL_LISTIFY_747(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(747, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_749(F, sep, ...) \ + Z_UTIL_LISTIFY_748(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(748, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_750(F, sep, ...) \ + Z_UTIL_LISTIFY_749(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(749, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_751(F, sep, ...) \ + Z_UTIL_LISTIFY_750(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(750, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_752(F, sep, ...) \ + Z_UTIL_LISTIFY_751(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(751, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_753(F, sep, ...) \ + Z_UTIL_LISTIFY_752(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(752, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_754(F, sep, ...) \ + Z_UTIL_LISTIFY_753(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(753, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_755(F, sep, ...) \ + Z_UTIL_LISTIFY_754(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(754, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_756(F, sep, ...) \ + Z_UTIL_LISTIFY_755(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(755, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_757(F, sep, ...) \ + Z_UTIL_LISTIFY_756(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(756, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_758(F, sep, ...) \ + Z_UTIL_LISTIFY_757(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(757, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_759(F, sep, ...) \ + Z_UTIL_LISTIFY_758(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(758, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_760(F, sep, ...) \ + Z_UTIL_LISTIFY_759(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(759, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_761(F, sep, ...) \ + Z_UTIL_LISTIFY_760(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(760, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_762(F, sep, ...) \ + Z_UTIL_LISTIFY_761(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(761, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_763(F, sep, ...) \ + Z_UTIL_LISTIFY_762(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(762, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_764(F, sep, ...) \ + Z_UTIL_LISTIFY_763(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(763, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_765(F, sep, ...) \ + Z_UTIL_LISTIFY_764(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(764, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_766(F, sep, ...) \ + Z_UTIL_LISTIFY_765(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(765, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_767(F, sep, ...) \ + Z_UTIL_LISTIFY_766(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(766, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_768(F, sep, ...) \ + Z_UTIL_LISTIFY_767(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(767, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_769(F, sep, ...) \ + Z_UTIL_LISTIFY_768(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(768, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_770(F, sep, ...) \ + Z_UTIL_LISTIFY_769(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(769, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_771(F, sep, ...) \ + Z_UTIL_LISTIFY_770(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(770, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_772(F, sep, ...) \ + Z_UTIL_LISTIFY_771(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(771, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_773(F, sep, ...) \ + Z_UTIL_LISTIFY_772(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(772, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_774(F, sep, ...) \ + Z_UTIL_LISTIFY_773(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(773, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_775(F, sep, ...) \ + Z_UTIL_LISTIFY_774(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(774, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_776(F, sep, ...) \ + Z_UTIL_LISTIFY_775(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(775, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_777(F, sep, ...) \ + Z_UTIL_LISTIFY_776(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(776, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_778(F, sep, ...) \ + Z_UTIL_LISTIFY_777(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(777, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_779(F, sep, ...) \ + Z_UTIL_LISTIFY_778(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(778, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_780(F, sep, ...) \ + Z_UTIL_LISTIFY_779(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(779, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_781(F, sep, ...) \ + Z_UTIL_LISTIFY_780(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(780, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_782(F, sep, ...) \ + Z_UTIL_LISTIFY_781(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(781, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_783(F, sep, ...) \ + Z_UTIL_LISTIFY_782(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(782, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_784(F, sep, ...) \ + Z_UTIL_LISTIFY_783(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(783, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_785(F, sep, ...) \ + Z_UTIL_LISTIFY_784(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(784, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_786(F, sep, ...) \ + Z_UTIL_LISTIFY_785(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(785, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_787(F, sep, ...) \ + Z_UTIL_LISTIFY_786(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(786, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_788(F, sep, ...) \ + Z_UTIL_LISTIFY_787(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(787, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_789(F, sep, ...) \ + Z_UTIL_LISTIFY_788(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(788, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_790(F, sep, ...) \ + Z_UTIL_LISTIFY_789(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(789, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_791(F, sep, ...) \ + Z_UTIL_LISTIFY_790(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(790, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_792(F, sep, ...) \ + Z_UTIL_LISTIFY_791(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(791, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_793(F, sep, ...) \ + Z_UTIL_LISTIFY_792(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(792, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_794(F, sep, ...) \ + Z_UTIL_LISTIFY_793(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(793, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_795(F, sep, ...) \ + Z_UTIL_LISTIFY_794(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(794, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_796(F, sep, ...) \ + Z_UTIL_LISTIFY_795(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(795, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_797(F, sep, ...) \ + Z_UTIL_LISTIFY_796(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(796, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_798(F, sep, ...) \ + Z_UTIL_LISTIFY_797(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(797, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_799(F, sep, ...) \ + Z_UTIL_LISTIFY_798(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(798, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_800(F, sep, ...) \ + Z_UTIL_LISTIFY_799(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(799, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_801(F, sep, ...) \ + Z_UTIL_LISTIFY_800(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(800, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_802(F, sep, ...) \ + Z_UTIL_LISTIFY_801(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(801, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_803(F, sep, ...) \ + Z_UTIL_LISTIFY_802(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(802, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_804(F, sep, ...) \ + Z_UTIL_LISTIFY_803(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(803, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_805(F, sep, ...) \ + Z_UTIL_LISTIFY_804(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(804, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_806(F, sep, ...) \ + Z_UTIL_LISTIFY_805(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(805, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_807(F, sep, ...) \ + Z_UTIL_LISTIFY_806(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(806, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_808(F, sep, ...) \ + Z_UTIL_LISTIFY_807(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(807, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_809(F, sep, ...) \ + Z_UTIL_LISTIFY_808(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(808, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_810(F, sep, ...) \ + Z_UTIL_LISTIFY_809(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(809, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_811(F, sep, ...) \ + Z_UTIL_LISTIFY_810(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(810, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_812(F, sep, ...) \ + Z_UTIL_LISTIFY_811(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(811, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_813(F, sep, ...) \ + Z_UTIL_LISTIFY_812(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(812, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_814(F, sep, ...) \ + Z_UTIL_LISTIFY_813(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(813, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_815(F, sep, ...) \ + Z_UTIL_LISTIFY_814(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(814, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_816(F, sep, ...) \ + Z_UTIL_LISTIFY_815(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(815, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_817(F, sep, ...) \ + Z_UTIL_LISTIFY_816(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(816, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_818(F, sep, ...) \ + Z_UTIL_LISTIFY_817(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(817, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_819(F, sep, ...) \ + Z_UTIL_LISTIFY_818(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(818, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_820(F, sep, ...) \ + Z_UTIL_LISTIFY_819(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(819, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_821(F, sep, ...) \ + Z_UTIL_LISTIFY_820(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(820, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_822(F, sep, ...) \ + Z_UTIL_LISTIFY_821(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(821, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_823(F, sep, ...) \ + Z_UTIL_LISTIFY_822(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(822, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_824(F, sep, ...) \ + Z_UTIL_LISTIFY_823(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(823, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_825(F, sep, ...) \ + Z_UTIL_LISTIFY_824(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(824, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_826(F, sep, ...) \ + Z_UTIL_LISTIFY_825(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(825, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_827(F, sep, ...) \ + Z_UTIL_LISTIFY_826(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(826, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_828(F, sep, ...) \ + Z_UTIL_LISTIFY_827(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(827, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_829(F, sep, ...) \ + Z_UTIL_LISTIFY_828(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(828, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_830(F, sep, ...) \ + Z_UTIL_LISTIFY_829(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(829, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_831(F, sep, ...) \ + Z_UTIL_LISTIFY_830(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(830, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_832(F, sep, ...) \ + Z_UTIL_LISTIFY_831(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(831, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_833(F, sep, ...) \ + Z_UTIL_LISTIFY_832(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(832, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_834(F, sep, ...) \ + Z_UTIL_LISTIFY_833(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(833, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_835(F, sep, ...) \ + Z_UTIL_LISTIFY_834(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(834, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_836(F, sep, ...) \ + Z_UTIL_LISTIFY_835(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(835, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_837(F, sep, ...) \ + Z_UTIL_LISTIFY_836(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(836, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_838(F, sep, ...) \ + Z_UTIL_LISTIFY_837(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(837, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_839(F, sep, ...) \ + Z_UTIL_LISTIFY_838(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(838, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_840(F, sep, ...) \ + Z_UTIL_LISTIFY_839(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(839, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_841(F, sep, ...) \ + Z_UTIL_LISTIFY_840(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(840, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_842(F, sep, ...) \ + Z_UTIL_LISTIFY_841(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(841, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_843(F, sep, ...) \ + Z_UTIL_LISTIFY_842(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(842, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_844(F, sep, ...) \ + Z_UTIL_LISTIFY_843(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(843, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_845(F, sep, ...) \ + Z_UTIL_LISTIFY_844(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(844, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_846(F, sep, ...) \ + Z_UTIL_LISTIFY_845(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(845, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_847(F, sep, ...) \ + Z_UTIL_LISTIFY_846(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(846, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_848(F, sep, ...) \ + Z_UTIL_LISTIFY_847(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(847, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_849(F, sep, ...) \ + Z_UTIL_LISTIFY_848(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(848, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_850(F, sep, ...) \ + Z_UTIL_LISTIFY_849(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(849, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_851(F, sep, ...) \ + Z_UTIL_LISTIFY_850(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(850, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_852(F, sep, ...) \ + Z_UTIL_LISTIFY_851(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(851, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_853(F, sep, ...) \ + Z_UTIL_LISTIFY_852(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(852, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_854(F, sep, ...) \ + Z_UTIL_LISTIFY_853(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(853, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_855(F, sep, ...) \ + Z_UTIL_LISTIFY_854(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(854, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_856(F, sep, ...) \ + Z_UTIL_LISTIFY_855(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(855, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_857(F, sep, ...) \ + Z_UTIL_LISTIFY_856(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(856, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_858(F, sep, ...) \ + Z_UTIL_LISTIFY_857(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(857, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_859(F, sep, ...) \ + Z_UTIL_LISTIFY_858(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(858, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_860(F, sep, ...) \ + Z_UTIL_LISTIFY_859(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(859, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_861(F, sep, ...) \ + Z_UTIL_LISTIFY_860(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(860, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_862(F, sep, ...) \ + Z_UTIL_LISTIFY_861(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(861, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_863(F, sep, ...) \ + Z_UTIL_LISTIFY_862(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(862, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_864(F, sep, ...) \ + Z_UTIL_LISTIFY_863(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(863, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_865(F, sep, ...) \ + Z_UTIL_LISTIFY_864(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(864, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_866(F, sep, ...) \ + Z_UTIL_LISTIFY_865(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(865, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_867(F, sep, ...) \ + Z_UTIL_LISTIFY_866(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(866, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_868(F, sep, ...) \ + Z_UTIL_LISTIFY_867(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(867, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_869(F, sep, ...) \ + Z_UTIL_LISTIFY_868(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(868, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_870(F, sep, ...) \ + Z_UTIL_LISTIFY_869(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(869, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_871(F, sep, ...) \ + Z_UTIL_LISTIFY_870(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(870, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_872(F, sep, ...) \ + Z_UTIL_LISTIFY_871(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(871, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_873(F, sep, ...) \ + Z_UTIL_LISTIFY_872(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(872, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_874(F, sep, ...) \ + Z_UTIL_LISTIFY_873(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(873, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_875(F, sep, ...) \ + Z_UTIL_LISTIFY_874(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(874, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_876(F, sep, ...) \ + Z_UTIL_LISTIFY_875(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(875, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_877(F, sep, ...) \ + Z_UTIL_LISTIFY_876(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(876, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_878(F, sep, ...) \ + Z_UTIL_LISTIFY_877(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(877, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_879(F, sep, ...) \ + Z_UTIL_LISTIFY_878(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(878, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_880(F, sep, ...) \ + Z_UTIL_LISTIFY_879(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(879, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_881(F, sep, ...) \ + Z_UTIL_LISTIFY_880(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(880, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_882(F, sep, ...) \ + Z_UTIL_LISTIFY_881(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(881, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_883(F, sep, ...) \ + Z_UTIL_LISTIFY_882(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(882, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_884(F, sep, ...) \ + Z_UTIL_LISTIFY_883(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(883, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_885(F, sep, ...) \ + Z_UTIL_LISTIFY_884(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(884, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_886(F, sep, ...) \ + Z_UTIL_LISTIFY_885(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(885, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_887(F, sep, ...) \ + Z_UTIL_LISTIFY_886(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(886, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_888(F, sep, ...) \ + Z_UTIL_LISTIFY_887(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(887, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_889(F, sep, ...) \ + Z_UTIL_LISTIFY_888(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(888, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_890(F, sep, ...) \ + Z_UTIL_LISTIFY_889(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(889, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_891(F, sep, ...) \ + Z_UTIL_LISTIFY_890(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(890, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_892(F, sep, ...) \ + Z_UTIL_LISTIFY_891(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(891, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_893(F, sep, ...) \ + Z_UTIL_LISTIFY_892(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(892, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_894(F, sep, ...) \ + Z_UTIL_LISTIFY_893(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(893, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_895(F, sep, ...) \ + Z_UTIL_LISTIFY_894(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(894, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_896(F, sep, ...) \ + Z_UTIL_LISTIFY_895(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(895, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_897(F, sep, ...) \ + Z_UTIL_LISTIFY_896(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(896, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_898(F, sep, ...) \ + Z_UTIL_LISTIFY_897(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(897, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_899(F, sep, ...) \ + Z_UTIL_LISTIFY_898(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(898, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_900(F, sep, ...) \ + Z_UTIL_LISTIFY_899(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(899, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_901(F, sep, ...) \ + Z_UTIL_LISTIFY_900(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(900, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_902(F, sep, ...) \ + Z_UTIL_LISTIFY_901(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(901, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_903(F, sep, ...) \ + Z_UTIL_LISTIFY_902(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(902, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_904(F, sep, ...) \ + Z_UTIL_LISTIFY_903(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(903, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_905(F, sep, ...) \ + Z_UTIL_LISTIFY_904(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(904, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_906(F, sep, ...) \ + Z_UTIL_LISTIFY_905(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(905, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_907(F, sep, ...) \ + Z_UTIL_LISTIFY_906(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(906, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_908(F, sep, ...) \ + Z_UTIL_LISTIFY_907(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(907, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_909(F, sep, ...) \ + Z_UTIL_LISTIFY_908(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(908, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_910(F, sep, ...) \ + Z_UTIL_LISTIFY_909(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(909, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_911(F, sep, ...) \ + Z_UTIL_LISTIFY_910(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(910, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_912(F, sep, ...) \ + Z_UTIL_LISTIFY_911(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(911, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_913(F, sep, ...) \ + Z_UTIL_LISTIFY_912(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(912, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_914(F, sep, ...) \ + Z_UTIL_LISTIFY_913(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(913, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_915(F, sep, ...) \ + Z_UTIL_LISTIFY_914(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(914, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_916(F, sep, ...) \ + Z_UTIL_LISTIFY_915(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(915, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_917(F, sep, ...) \ + Z_UTIL_LISTIFY_916(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(916, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_918(F, sep, ...) \ + Z_UTIL_LISTIFY_917(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(917, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_919(F, sep, ...) \ + Z_UTIL_LISTIFY_918(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(918, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_920(F, sep, ...) \ + Z_UTIL_LISTIFY_919(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(919, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_921(F, sep, ...) \ + Z_UTIL_LISTIFY_920(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(920, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_922(F, sep, ...) \ + Z_UTIL_LISTIFY_921(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(921, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_923(F, sep, ...) \ + Z_UTIL_LISTIFY_922(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(922, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_924(F, sep, ...) \ + Z_UTIL_LISTIFY_923(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(923, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_925(F, sep, ...) \ + Z_UTIL_LISTIFY_924(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(924, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_926(F, sep, ...) \ + Z_UTIL_LISTIFY_925(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(925, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_927(F, sep, ...) \ + Z_UTIL_LISTIFY_926(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(926, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_928(F, sep, ...) \ + Z_UTIL_LISTIFY_927(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(927, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_929(F, sep, ...) \ + Z_UTIL_LISTIFY_928(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(928, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_930(F, sep, ...) \ + Z_UTIL_LISTIFY_929(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(929, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_931(F, sep, ...) \ + Z_UTIL_LISTIFY_930(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(930, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_932(F, sep, ...) \ + Z_UTIL_LISTIFY_931(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(931, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_933(F, sep, ...) \ + Z_UTIL_LISTIFY_932(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(932, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_934(F, sep, ...) \ + Z_UTIL_LISTIFY_933(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(933, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_935(F, sep, ...) \ + Z_UTIL_LISTIFY_934(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(934, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_936(F, sep, ...) \ + Z_UTIL_LISTIFY_935(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(935, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_937(F, sep, ...) \ + Z_UTIL_LISTIFY_936(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(936, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_938(F, sep, ...) \ + Z_UTIL_LISTIFY_937(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(937, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_939(F, sep, ...) \ + Z_UTIL_LISTIFY_938(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(938, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_940(F, sep, ...) \ + Z_UTIL_LISTIFY_939(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(939, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_941(F, sep, ...) \ + Z_UTIL_LISTIFY_940(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(940, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_942(F, sep, ...) \ + Z_UTIL_LISTIFY_941(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(941, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_943(F, sep, ...) \ + Z_UTIL_LISTIFY_942(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(942, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_944(F, sep, ...) \ + Z_UTIL_LISTIFY_943(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(943, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_945(F, sep, ...) \ + Z_UTIL_LISTIFY_944(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(944, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_946(F, sep, ...) \ + Z_UTIL_LISTIFY_945(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(945, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_947(F, sep, ...) \ + Z_UTIL_LISTIFY_946(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(946, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_948(F, sep, ...) \ + Z_UTIL_LISTIFY_947(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(947, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_949(F, sep, ...) \ + Z_UTIL_LISTIFY_948(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(948, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_950(F, sep, ...) \ + Z_UTIL_LISTIFY_949(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(949, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_951(F, sep, ...) \ + Z_UTIL_LISTIFY_950(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(950, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_952(F, sep, ...) \ + Z_UTIL_LISTIFY_951(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(951, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_953(F, sep, ...) \ + Z_UTIL_LISTIFY_952(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(952, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_954(F, sep, ...) \ + Z_UTIL_LISTIFY_953(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(953, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_955(F, sep, ...) \ + Z_UTIL_LISTIFY_954(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(954, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_956(F, sep, ...) \ + Z_UTIL_LISTIFY_955(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(955, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_957(F, sep, ...) \ + Z_UTIL_LISTIFY_956(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(956, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_958(F, sep, ...) \ + Z_UTIL_LISTIFY_957(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(957, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_959(F, sep, ...) \ + Z_UTIL_LISTIFY_958(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(958, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_960(F, sep, ...) \ + Z_UTIL_LISTIFY_959(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(959, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_961(F, sep, ...) \ + Z_UTIL_LISTIFY_960(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(960, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_962(F, sep, ...) \ + Z_UTIL_LISTIFY_961(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(961, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_963(F, sep, ...) \ + Z_UTIL_LISTIFY_962(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(962, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_964(F, sep, ...) \ + Z_UTIL_LISTIFY_963(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(963, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_965(F, sep, ...) \ + Z_UTIL_LISTIFY_964(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(964, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_966(F, sep, ...) \ + Z_UTIL_LISTIFY_965(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(965, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_967(F, sep, ...) \ + Z_UTIL_LISTIFY_966(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(966, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_968(F, sep, ...) \ + Z_UTIL_LISTIFY_967(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(967, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_969(F, sep, ...) \ + Z_UTIL_LISTIFY_968(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(968, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_970(F, sep, ...) \ + Z_UTIL_LISTIFY_969(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(969, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_971(F, sep, ...) \ + Z_UTIL_LISTIFY_970(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(970, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_972(F, sep, ...) \ + Z_UTIL_LISTIFY_971(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(971, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_973(F, sep, ...) \ + Z_UTIL_LISTIFY_972(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(972, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_974(F, sep, ...) \ + Z_UTIL_LISTIFY_973(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(973, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_975(F, sep, ...) \ + Z_UTIL_LISTIFY_974(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(974, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_976(F, sep, ...) \ + Z_UTIL_LISTIFY_975(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(975, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_977(F, sep, ...) \ + Z_UTIL_LISTIFY_976(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(976, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_978(F, sep, ...) \ + Z_UTIL_LISTIFY_977(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(977, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_979(F, sep, ...) \ + Z_UTIL_LISTIFY_978(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(978, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_980(F, sep, ...) \ + Z_UTIL_LISTIFY_979(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(979, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_981(F, sep, ...) \ + Z_UTIL_LISTIFY_980(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(980, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_982(F, sep, ...) \ + Z_UTIL_LISTIFY_981(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(981, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_983(F, sep, ...) \ + Z_UTIL_LISTIFY_982(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(982, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_984(F, sep, ...) \ + Z_UTIL_LISTIFY_983(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(983, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_985(F, sep, ...) \ + Z_UTIL_LISTIFY_984(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(984, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_986(F, sep, ...) \ + Z_UTIL_LISTIFY_985(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(985, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_987(F, sep, ...) \ + Z_UTIL_LISTIFY_986(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(986, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_988(F, sep, ...) \ + Z_UTIL_LISTIFY_987(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(987, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_989(F, sep, ...) \ + Z_UTIL_LISTIFY_988(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(988, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_990(F, sep, ...) \ + Z_UTIL_LISTIFY_989(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(989, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_991(F, sep, ...) \ + Z_UTIL_LISTIFY_990(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(990, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_992(F, sep, ...) \ + Z_UTIL_LISTIFY_991(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(991, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_993(F, sep, ...) \ + Z_UTIL_LISTIFY_992(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(992, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_994(F, sep, ...) \ + Z_UTIL_LISTIFY_993(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(993, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_995(F, sep, ...) \ + Z_UTIL_LISTIFY_994(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(994, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_996(F, sep, ...) \ + Z_UTIL_LISTIFY_995(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(995, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_997(F, sep, ...) \ + Z_UTIL_LISTIFY_996(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(996, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_998(F, sep, ...) \ + Z_UTIL_LISTIFY_997(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(997, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_999(F, sep, ...) \ + Z_UTIL_LISTIFY_998(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(998, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1000(F, sep, ...) \ + Z_UTIL_LISTIFY_999(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(999, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1001(F, sep, ...) \ + Z_UTIL_LISTIFY_1000(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1000, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1002(F, sep, ...) \ + Z_UTIL_LISTIFY_1001(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1001, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1003(F, sep, ...) \ + Z_UTIL_LISTIFY_1002(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1002, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1004(F, sep, ...) \ + Z_UTIL_LISTIFY_1003(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1003, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1005(F, sep, ...) \ + Z_UTIL_LISTIFY_1004(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1004, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1006(F, sep, ...) \ + Z_UTIL_LISTIFY_1005(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1005, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1007(F, sep, ...) \ + Z_UTIL_LISTIFY_1006(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1006, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1008(F, sep, ...) \ + Z_UTIL_LISTIFY_1007(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1007, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1009(F, sep, ...) \ + Z_UTIL_LISTIFY_1008(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1008, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1010(F, sep, ...) \ + Z_UTIL_LISTIFY_1009(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1009, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1011(F, sep, ...) \ + Z_UTIL_LISTIFY_1010(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1010, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1012(F, sep, ...) \ + Z_UTIL_LISTIFY_1011(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1011, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1013(F, sep, ...) \ + Z_UTIL_LISTIFY_1012(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1012, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1014(F, sep, ...) \ + Z_UTIL_LISTIFY_1013(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1013, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1015(F, sep, ...) \ + Z_UTIL_LISTIFY_1014(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1014, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1016(F, sep, ...) \ + Z_UTIL_LISTIFY_1015(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1015, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1017(F, sep, ...) \ + Z_UTIL_LISTIFY_1016(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1016, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1018(F, sep, ...) \ + Z_UTIL_LISTIFY_1017(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1017, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1019(F, sep, ...) \ + Z_UTIL_LISTIFY_1018(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1018, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1020(F, sep, ...) \ + Z_UTIL_LISTIFY_1019(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1019, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1021(F, sep, ...) \ + Z_UTIL_LISTIFY_1020(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1020, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1022(F, sep, ...) \ + Z_UTIL_LISTIFY_1021(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1021, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1023(F, sep, ...) \ + Z_UTIL_LISTIFY_1022(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1022, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1024(F, sep, ...) \ + Z_UTIL_LISTIFY_1023(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1023, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1025(F, sep, ...) \ + Z_UTIL_LISTIFY_1024(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1024, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1026(F, sep, ...) \ + Z_UTIL_LISTIFY_1025(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1025, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1027(F, sep, ...) \ + Z_UTIL_LISTIFY_1026(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1026, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1028(F, sep, ...) \ + Z_UTIL_LISTIFY_1027(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1027, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1029(F, sep, ...) \ + Z_UTIL_LISTIFY_1028(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1028, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1030(F, sep, ...) \ + Z_UTIL_LISTIFY_1029(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1029, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1031(F, sep, ...) \ + Z_UTIL_LISTIFY_1030(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1030, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1032(F, sep, ...) \ + Z_UTIL_LISTIFY_1031(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1031, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1033(F, sep, ...) \ + Z_UTIL_LISTIFY_1032(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1032, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1034(F, sep, ...) \ + Z_UTIL_LISTIFY_1033(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1033, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1035(F, sep, ...) \ + Z_UTIL_LISTIFY_1034(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1034, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1036(F, sep, ...) \ + Z_UTIL_LISTIFY_1035(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1035, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1037(F, sep, ...) \ + Z_UTIL_LISTIFY_1036(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1036, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1038(F, sep, ...) \ + Z_UTIL_LISTIFY_1037(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1037, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1039(F, sep, ...) \ + Z_UTIL_LISTIFY_1038(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1038, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1040(F, sep, ...) \ + Z_UTIL_LISTIFY_1039(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1039, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1041(F, sep, ...) \ + Z_UTIL_LISTIFY_1040(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1040, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1042(F, sep, ...) \ + Z_UTIL_LISTIFY_1041(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1041, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1043(F, sep, ...) \ + Z_UTIL_LISTIFY_1042(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1042, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1044(F, sep, ...) \ + Z_UTIL_LISTIFY_1043(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1043, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1045(F, sep, ...) \ + Z_UTIL_LISTIFY_1044(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1044, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1046(F, sep, ...) \ + Z_UTIL_LISTIFY_1045(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1045, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1047(F, sep, ...) \ + Z_UTIL_LISTIFY_1046(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1046, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1048(F, sep, ...) \ + Z_UTIL_LISTIFY_1047(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1047, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1049(F, sep, ...) \ + Z_UTIL_LISTIFY_1048(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1048, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1050(F, sep, ...) \ + Z_UTIL_LISTIFY_1049(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1049, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1051(F, sep, ...) \ + Z_UTIL_LISTIFY_1050(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1050, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1052(F, sep, ...) \ + Z_UTIL_LISTIFY_1051(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1051, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1053(F, sep, ...) \ + Z_UTIL_LISTIFY_1052(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1052, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1054(F, sep, ...) \ + Z_UTIL_LISTIFY_1053(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1053, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1055(F, sep, ...) \ + Z_UTIL_LISTIFY_1054(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1054, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1056(F, sep, ...) \ + Z_UTIL_LISTIFY_1055(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1055, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1057(F, sep, ...) \ + Z_UTIL_LISTIFY_1056(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1056, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1058(F, sep, ...) \ + Z_UTIL_LISTIFY_1057(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1057, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1059(F, sep, ...) \ + Z_UTIL_LISTIFY_1058(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1058, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1060(F, sep, ...) \ + Z_UTIL_LISTIFY_1059(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1059, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1061(F, sep, ...) \ + Z_UTIL_LISTIFY_1060(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1060, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1062(F, sep, ...) \ + Z_UTIL_LISTIFY_1061(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1061, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1063(F, sep, ...) \ + Z_UTIL_LISTIFY_1062(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1062, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1064(F, sep, ...) \ + Z_UTIL_LISTIFY_1063(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1063, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1065(F, sep, ...) \ + Z_UTIL_LISTIFY_1064(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1064, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1066(F, sep, ...) \ + Z_UTIL_LISTIFY_1065(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1065, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1067(F, sep, ...) \ + Z_UTIL_LISTIFY_1066(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1066, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1068(F, sep, ...) \ + Z_UTIL_LISTIFY_1067(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1067, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1069(F, sep, ...) \ + Z_UTIL_LISTIFY_1068(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1068, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1070(F, sep, ...) \ + Z_UTIL_LISTIFY_1069(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1069, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1071(F, sep, ...) \ + Z_UTIL_LISTIFY_1070(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1070, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1072(F, sep, ...) \ + Z_UTIL_LISTIFY_1071(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1071, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1073(F, sep, ...) \ + Z_UTIL_LISTIFY_1072(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1072, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1074(F, sep, ...) \ + Z_UTIL_LISTIFY_1073(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1073, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1075(F, sep, ...) \ + Z_UTIL_LISTIFY_1074(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1074, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1076(F, sep, ...) \ + Z_UTIL_LISTIFY_1075(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1075, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1077(F, sep, ...) \ + Z_UTIL_LISTIFY_1076(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1076, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1078(F, sep, ...) \ + Z_UTIL_LISTIFY_1077(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1077, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1079(F, sep, ...) \ + Z_UTIL_LISTIFY_1078(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1078, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1080(F, sep, ...) \ + Z_UTIL_LISTIFY_1079(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1079, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1081(F, sep, ...) \ + Z_UTIL_LISTIFY_1080(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1080, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1082(F, sep, ...) \ + Z_UTIL_LISTIFY_1081(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1081, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1083(F, sep, ...) \ + Z_UTIL_LISTIFY_1082(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1082, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1084(F, sep, ...) \ + Z_UTIL_LISTIFY_1083(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1083, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1085(F, sep, ...) \ + Z_UTIL_LISTIFY_1084(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1084, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1086(F, sep, ...) \ + Z_UTIL_LISTIFY_1085(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1085, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1087(F, sep, ...) \ + Z_UTIL_LISTIFY_1086(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1086, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1088(F, sep, ...) \ + Z_UTIL_LISTIFY_1087(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1087, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1089(F, sep, ...) \ + Z_UTIL_LISTIFY_1088(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1088, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1090(F, sep, ...) \ + Z_UTIL_LISTIFY_1089(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1089, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1091(F, sep, ...) \ + Z_UTIL_LISTIFY_1090(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1090, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1092(F, sep, ...) \ + Z_UTIL_LISTIFY_1091(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1091, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1093(F, sep, ...) \ + Z_UTIL_LISTIFY_1092(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1092, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1094(F, sep, ...) \ + Z_UTIL_LISTIFY_1093(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1093, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1095(F, sep, ...) \ + Z_UTIL_LISTIFY_1094(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1094, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1096(F, sep, ...) \ + Z_UTIL_LISTIFY_1095(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1095, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1097(F, sep, ...) \ + Z_UTIL_LISTIFY_1096(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1096, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1098(F, sep, ...) \ + Z_UTIL_LISTIFY_1097(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1097, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1099(F, sep, ...) \ + Z_UTIL_LISTIFY_1098(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1098, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1100(F, sep, ...) \ + Z_UTIL_LISTIFY_1099(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1099, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1101(F, sep, ...) \ + Z_UTIL_LISTIFY_1100(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1100, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1102(F, sep, ...) \ + Z_UTIL_LISTIFY_1101(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1101, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1103(F, sep, ...) \ + Z_UTIL_LISTIFY_1102(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1102, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1104(F, sep, ...) \ + Z_UTIL_LISTIFY_1103(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1103, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1105(F, sep, ...) \ + Z_UTIL_LISTIFY_1104(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1104, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1106(F, sep, ...) \ + Z_UTIL_LISTIFY_1105(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1105, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1107(F, sep, ...) \ + Z_UTIL_LISTIFY_1106(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1106, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1108(F, sep, ...) \ + Z_UTIL_LISTIFY_1107(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1107, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1109(F, sep, ...) \ + Z_UTIL_LISTIFY_1108(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1108, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1110(F, sep, ...) \ + Z_UTIL_LISTIFY_1109(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1109, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1111(F, sep, ...) \ + Z_UTIL_LISTIFY_1110(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1110, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1112(F, sep, ...) \ + Z_UTIL_LISTIFY_1111(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1111, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1113(F, sep, ...) \ + Z_UTIL_LISTIFY_1112(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1112, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1114(F, sep, ...) \ + Z_UTIL_LISTIFY_1113(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1113, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1115(F, sep, ...) \ + Z_UTIL_LISTIFY_1114(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1114, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1116(F, sep, ...) \ + Z_UTIL_LISTIFY_1115(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1115, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1117(F, sep, ...) \ + Z_UTIL_LISTIFY_1116(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1116, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1118(F, sep, ...) \ + Z_UTIL_LISTIFY_1117(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1117, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1119(F, sep, ...) \ + Z_UTIL_LISTIFY_1118(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1118, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1120(F, sep, ...) \ + Z_UTIL_LISTIFY_1119(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1119, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1121(F, sep, ...) \ + Z_UTIL_LISTIFY_1120(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1120, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1122(F, sep, ...) \ + Z_UTIL_LISTIFY_1121(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1121, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1123(F, sep, ...) \ + Z_UTIL_LISTIFY_1122(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1122, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1124(F, sep, ...) \ + Z_UTIL_LISTIFY_1123(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1123, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1125(F, sep, ...) \ + Z_UTIL_LISTIFY_1124(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1124, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1126(F, sep, ...) \ + Z_UTIL_LISTIFY_1125(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1125, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1127(F, sep, ...) \ + Z_UTIL_LISTIFY_1126(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1126, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1128(F, sep, ...) \ + Z_UTIL_LISTIFY_1127(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1127, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1129(F, sep, ...) \ + Z_UTIL_LISTIFY_1128(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1128, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1130(F, sep, ...) \ + Z_UTIL_LISTIFY_1129(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1129, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1131(F, sep, ...) \ + Z_UTIL_LISTIFY_1130(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1130, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1132(F, sep, ...) \ + Z_UTIL_LISTIFY_1131(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1131, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1133(F, sep, ...) \ + Z_UTIL_LISTIFY_1132(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1132, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1134(F, sep, ...) \ + Z_UTIL_LISTIFY_1133(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1133, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1135(F, sep, ...) \ + Z_UTIL_LISTIFY_1134(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1134, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1136(F, sep, ...) \ + Z_UTIL_LISTIFY_1135(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1135, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1137(F, sep, ...) \ + Z_UTIL_LISTIFY_1136(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1136, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1138(F, sep, ...) \ + Z_UTIL_LISTIFY_1137(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1137, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1139(F, sep, ...) \ + Z_UTIL_LISTIFY_1138(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1138, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1140(F, sep, ...) \ + Z_UTIL_LISTIFY_1139(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1139, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1141(F, sep, ...) \ + Z_UTIL_LISTIFY_1140(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1140, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1142(F, sep, ...) \ + Z_UTIL_LISTIFY_1141(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1141, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1143(F, sep, ...) \ + Z_UTIL_LISTIFY_1142(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1142, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1144(F, sep, ...) \ + Z_UTIL_LISTIFY_1143(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1143, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1145(F, sep, ...) \ + Z_UTIL_LISTIFY_1144(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1144, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1146(F, sep, ...) \ + Z_UTIL_LISTIFY_1145(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1145, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1147(F, sep, ...) \ + Z_UTIL_LISTIFY_1146(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1146, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1148(F, sep, ...) \ + Z_UTIL_LISTIFY_1147(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1147, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1149(F, sep, ...) \ + Z_UTIL_LISTIFY_1148(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1148, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1150(F, sep, ...) \ + Z_UTIL_LISTIFY_1149(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1149, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1151(F, sep, ...) \ + Z_UTIL_LISTIFY_1150(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1150, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1152(F, sep, ...) \ + Z_UTIL_LISTIFY_1151(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1151, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1153(F, sep, ...) \ + Z_UTIL_LISTIFY_1152(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1152, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1154(F, sep, ...) \ + Z_UTIL_LISTIFY_1153(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1153, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1155(F, sep, ...) \ + Z_UTIL_LISTIFY_1154(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1154, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1156(F, sep, ...) \ + Z_UTIL_LISTIFY_1155(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1155, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1157(F, sep, ...) \ + Z_UTIL_LISTIFY_1156(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1156, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1158(F, sep, ...) \ + Z_UTIL_LISTIFY_1157(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1157, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1159(F, sep, ...) \ + Z_UTIL_LISTIFY_1158(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1158, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1160(F, sep, ...) \ + Z_UTIL_LISTIFY_1159(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1159, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1161(F, sep, ...) \ + Z_UTIL_LISTIFY_1160(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1160, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1162(F, sep, ...) \ + Z_UTIL_LISTIFY_1161(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1161, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1163(F, sep, ...) \ + Z_UTIL_LISTIFY_1162(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1162, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1164(F, sep, ...) \ + Z_UTIL_LISTIFY_1163(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1163, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1165(F, sep, ...) \ + Z_UTIL_LISTIFY_1164(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1164, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1166(F, sep, ...) \ + Z_UTIL_LISTIFY_1165(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1165, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1167(F, sep, ...) \ + Z_UTIL_LISTIFY_1166(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1166, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1168(F, sep, ...) \ + Z_UTIL_LISTIFY_1167(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1167, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1169(F, sep, ...) \ + Z_UTIL_LISTIFY_1168(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1168, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1170(F, sep, ...) \ + Z_UTIL_LISTIFY_1169(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1169, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1171(F, sep, ...) \ + Z_UTIL_LISTIFY_1170(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1170, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1172(F, sep, ...) \ + Z_UTIL_LISTIFY_1171(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1171, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1173(F, sep, ...) \ + Z_UTIL_LISTIFY_1172(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1172, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1174(F, sep, ...) \ + Z_UTIL_LISTIFY_1173(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1173, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1175(F, sep, ...) \ + Z_UTIL_LISTIFY_1174(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1174, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1176(F, sep, ...) \ + Z_UTIL_LISTIFY_1175(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1175, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1177(F, sep, ...) \ + Z_UTIL_LISTIFY_1176(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1176, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1178(F, sep, ...) \ + Z_UTIL_LISTIFY_1177(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1177, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1179(F, sep, ...) \ + Z_UTIL_LISTIFY_1178(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1178, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1180(F, sep, ...) \ + Z_UTIL_LISTIFY_1179(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1179, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1181(F, sep, ...) \ + Z_UTIL_LISTIFY_1180(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1180, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1182(F, sep, ...) \ + Z_UTIL_LISTIFY_1181(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1181, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1183(F, sep, ...) \ + Z_UTIL_LISTIFY_1182(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1182, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1184(F, sep, ...) \ + Z_UTIL_LISTIFY_1183(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1183, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1185(F, sep, ...) \ + Z_UTIL_LISTIFY_1184(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1184, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1186(F, sep, ...) \ + Z_UTIL_LISTIFY_1185(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1185, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1187(F, sep, ...) \ + Z_UTIL_LISTIFY_1186(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1186, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1188(F, sep, ...) \ + Z_UTIL_LISTIFY_1187(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1187, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1189(F, sep, ...) \ + Z_UTIL_LISTIFY_1188(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1188, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1190(F, sep, ...) \ + Z_UTIL_LISTIFY_1189(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1189, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1191(F, sep, ...) \ + Z_UTIL_LISTIFY_1190(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1190, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1192(F, sep, ...) \ + Z_UTIL_LISTIFY_1191(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1191, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1193(F, sep, ...) \ + Z_UTIL_LISTIFY_1192(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1192, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1194(F, sep, ...) \ + Z_UTIL_LISTIFY_1193(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1193, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1195(F, sep, ...) \ + Z_UTIL_LISTIFY_1194(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1194, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1196(F, sep, ...) \ + Z_UTIL_LISTIFY_1195(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1195, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1197(F, sep, ...) \ + Z_UTIL_LISTIFY_1196(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1196, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1198(F, sep, ...) \ + Z_UTIL_LISTIFY_1197(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1197, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1199(F, sep, ...) \ + Z_UTIL_LISTIFY_1198(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1198, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1200(F, sep, ...) \ + Z_UTIL_LISTIFY_1199(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1199, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1201(F, sep, ...) \ + Z_UTIL_LISTIFY_1200(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1200, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1202(F, sep, ...) \ + Z_UTIL_LISTIFY_1201(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1201, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1203(F, sep, ...) \ + Z_UTIL_LISTIFY_1202(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1202, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1204(F, sep, ...) \ + Z_UTIL_LISTIFY_1203(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1203, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1205(F, sep, ...) \ + Z_UTIL_LISTIFY_1204(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1204, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1206(F, sep, ...) \ + Z_UTIL_LISTIFY_1205(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1205, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1207(F, sep, ...) \ + Z_UTIL_LISTIFY_1206(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1206, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1208(F, sep, ...) \ + Z_UTIL_LISTIFY_1207(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1207, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1209(F, sep, ...) \ + Z_UTIL_LISTIFY_1208(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1208, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1210(F, sep, ...) \ + Z_UTIL_LISTIFY_1209(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1209, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1211(F, sep, ...) \ + Z_UTIL_LISTIFY_1210(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1210, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1212(F, sep, ...) \ + Z_UTIL_LISTIFY_1211(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1211, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1213(F, sep, ...) \ + Z_UTIL_LISTIFY_1212(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1212, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1214(F, sep, ...) \ + Z_UTIL_LISTIFY_1213(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1213, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1215(F, sep, ...) \ + Z_UTIL_LISTIFY_1214(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1214, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1216(F, sep, ...) \ + Z_UTIL_LISTIFY_1215(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1215, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1217(F, sep, ...) \ + Z_UTIL_LISTIFY_1216(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1216, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1218(F, sep, ...) \ + Z_UTIL_LISTIFY_1217(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1217, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1219(F, sep, ...) \ + Z_UTIL_LISTIFY_1218(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1218, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1220(F, sep, ...) \ + Z_UTIL_LISTIFY_1219(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1219, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1221(F, sep, ...) \ + Z_UTIL_LISTIFY_1220(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1220, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1222(F, sep, ...) \ + Z_UTIL_LISTIFY_1221(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1221, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1223(F, sep, ...) \ + Z_UTIL_LISTIFY_1222(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1222, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1224(F, sep, ...) \ + Z_UTIL_LISTIFY_1223(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1223, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1225(F, sep, ...) \ + Z_UTIL_LISTIFY_1224(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1224, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1226(F, sep, ...) \ + Z_UTIL_LISTIFY_1225(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1225, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1227(F, sep, ...) \ + Z_UTIL_LISTIFY_1226(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1226, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1228(F, sep, ...) \ + Z_UTIL_LISTIFY_1227(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1227, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1229(F, sep, ...) \ + Z_UTIL_LISTIFY_1228(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1228, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1230(F, sep, ...) \ + Z_UTIL_LISTIFY_1229(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1229, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1231(F, sep, ...) \ + Z_UTIL_LISTIFY_1230(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1230, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1232(F, sep, ...) \ + Z_UTIL_LISTIFY_1231(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1231, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1233(F, sep, ...) \ + Z_UTIL_LISTIFY_1232(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1232, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1234(F, sep, ...) \ + Z_UTIL_LISTIFY_1233(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1233, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1235(F, sep, ...) \ + Z_UTIL_LISTIFY_1234(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1234, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1236(F, sep, ...) \ + Z_UTIL_LISTIFY_1235(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1235, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1237(F, sep, ...) \ + Z_UTIL_LISTIFY_1236(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1236, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1238(F, sep, ...) \ + Z_UTIL_LISTIFY_1237(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1237, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1239(F, sep, ...) \ + Z_UTIL_LISTIFY_1238(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1238, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1240(F, sep, ...) \ + Z_UTIL_LISTIFY_1239(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1239, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1241(F, sep, ...) \ + Z_UTIL_LISTIFY_1240(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1240, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1242(F, sep, ...) \ + Z_UTIL_LISTIFY_1241(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1241, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1243(F, sep, ...) \ + Z_UTIL_LISTIFY_1242(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1242, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1244(F, sep, ...) \ + Z_UTIL_LISTIFY_1243(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1243, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1245(F, sep, ...) \ + Z_UTIL_LISTIFY_1244(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1244, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1246(F, sep, ...) \ + Z_UTIL_LISTIFY_1245(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1245, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1247(F, sep, ...) \ + Z_UTIL_LISTIFY_1246(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1246, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1248(F, sep, ...) \ + Z_UTIL_LISTIFY_1247(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1247, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1249(F, sep, ...) \ + Z_UTIL_LISTIFY_1248(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1248, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1250(F, sep, ...) \ + Z_UTIL_LISTIFY_1249(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1249, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1251(F, sep, ...) \ + Z_UTIL_LISTIFY_1250(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1250, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1252(F, sep, ...) \ + Z_UTIL_LISTIFY_1251(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1251, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1253(F, sep, ...) \ + Z_UTIL_LISTIFY_1252(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1252, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1254(F, sep, ...) \ + Z_UTIL_LISTIFY_1253(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1253, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1255(F, sep, ...) \ + Z_UTIL_LISTIFY_1254(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1254, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1256(F, sep, ...) \ + Z_UTIL_LISTIFY_1255(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1255, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1257(F, sep, ...) \ + Z_UTIL_LISTIFY_1256(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1256, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1258(F, sep, ...) \ + Z_UTIL_LISTIFY_1257(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1257, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1259(F, sep, ...) \ + Z_UTIL_LISTIFY_1258(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1258, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1260(F, sep, ...) \ + Z_UTIL_LISTIFY_1259(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1259, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1261(F, sep, ...) \ + Z_UTIL_LISTIFY_1260(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1260, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1262(F, sep, ...) \ + Z_UTIL_LISTIFY_1261(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1261, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1263(F, sep, ...) \ + Z_UTIL_LISTIFY_1262(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1262, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1264(F, sep, ...) \ + Z_UTIL_LISTIFY_1263(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1263, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1265(F, sep, ...) \ + Z_UTIL_LISTIFY_1264(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1264, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1266(F, sep, ...) \ + Z_UTIL_LISTIFY_1265(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1265, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1267(F, sep, ...) \ + Z_UTIL_LISTIFY_1266(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1266, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1268(F, sep, ...) \ + Z_UTIL_LISTIFY_1267(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1267, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1269(F, sep, ...) \ + Z_UTIL_LISTIFY_1268(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1268, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1270(F, sep, ...) \ + Z_UTIL_LISTIFY_1269(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1269, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1271(F, sep, ...) \ + Z_UTIL_LISTIFY_1270(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1270, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1272(F, sep, ...) \ + Z_UTIL_LISTIFY_1271(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1271, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1273(F, sep, ...) \ + Z_UTIL_LISTIFY_1272(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1272, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1274(F, sep, ...) \ + Z_UTIL_LISTIFY_1273(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1273, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1275(F, sep, ...) \ + Z_UTIL_LISTIFY_1274(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1274, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1276(F, sep, ...) \ + Z_UTIL_LISTIFY_1275(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1275, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1277(F, sep, ...) \ + Z_UTIL_LISTIFY_1276(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1276, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1278(F, sep, ...) \ + Z_UTIL_LISTIFY_1277(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1277, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1279(F, sep, ...) \ + Z_UTIL_LISTIFY_1278(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1278, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1280(F, sep, ...) \ + Z_UTIL_LISTIFY_1279(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1279, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1281(F, sep, ...) \ + Z_UTIL_LISTIFY_1280(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1280, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1282(F, sep, ...) \ + Z_UTIL_LISTIFY_1281(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1281, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1283(F, sep, ...) \ + Z_UTIL_LISTIFY_1282(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1282, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1284(F, sep, ...) \ + Z_UTIL_LISTIFY_1283(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1283, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1285(F, sep, ...) \ + Z_UTIL_LISTIFY_1284(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1284, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1286(F, sep, ...) \ + Z_UTIL_LISTIFY_1285(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1285, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1287(F, sep, ...) \ + Z_UTIL_LISTIFY_1286(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1286, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1288(F, sep, ...) \ + Z_UTIL_LISTIFY_1287(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1287, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1289(F, sep, ...) \ + Z_UTIL_LISTIFY_1288(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1288, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1290(F, sep, ...) \ + Z_UTIL_LISTIFY_1289(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1289, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1291(F, sep, ...) \ + Z_UTIL_LISTIFY_1290(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1290, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1292(F, sep, ...) \ + Z_UTIL_LISTIFY_1291(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1291, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1293(F, sep, ...) \ + Z_UTIL_LISTIFY_1292(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1292, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1294(F, sep, ...) \ + Z_UTIL_LISTIFY_1293(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1293, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1295(F, sep, ...) \ + Z_UTIL_LISTIFY_1294(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1294, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1296(F, sep, ...) \ + Z_UTIL_LISTIFY_1295(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1295, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1297(F, sep, ...) \ + Z_UTIL_LISTIFY_1296(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1296, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1298(F, sep, ...) \ + Z_UTIL_LISTIFY_1297(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1297, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1299(F, sep, ...) \ + Z_UTIL_LISTIFY_1298(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1298, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1300(F, sep, ...) \ + Z_UTIL_LISTIFY_1299(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1299, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1301(F, sep, ...) \ + Z_UTIL_LISTIFY_1300(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1300, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1302(F, sep, ...) \ + Z_UTIL_LISTIFY_1301(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1301, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1303(F, sep, ...) \ + Z_UTIL_LISTIFY_1302(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1302, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1304(F, sep, ...) \ + Z_UTIL_LISTIFY_1303(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1303, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1305(F, sep, ...) \ + Z_UTIL_LISTIFY_1304(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1304, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1306(F, sep, ...) \ + Z_UTIL_LISTIFY_1305(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1305, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1307(F, sep, ...) \ + Z_UTIL_LISTIFY_1306(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1306, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1308(F, sep, ...) \ + Z_UTIL_LISTIFY_1307(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1307, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1309(F, sep, ...) \ + Z_UTIL_LISTIFY_1308(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1308, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1310(F, sep, ...) \ + Z_UTIL_LISTIFY_1309(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1309, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1311(F, sep, ...) \ + Z_UTIL_LISTIFY_1310(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1310, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1312(F, sep, ...) \ + Z_UTIL_LISTIFY_1311(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1311, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1313(F, sep, ...) \ + Z_UTIL_LISTIFY_1312(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1312, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1314(F, sep, ...) \ + Z_UTIL_LISTIFY_1313(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1313, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1315(F, sep, ...) \ + Z_UTIL_LISTIFY_1314(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1314, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1316(F, sep, ...) \ + Z_UTIL_LISTIFY_1315(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1315, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1317(F, sep, ...) \ + Z_UTIL_LISTIFY_1316(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1316, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1318(F, sep, ...) \ + Z_UTIL_LISTIFY_1317(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1317, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1319(F, sep, ...) \ + Z_UTIL_LISTIFY_1318(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1318, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1320(F, sep, ...) \ + Z_UTIL_LISTIFY_1319(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1319, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1321(F, sep, ...) \ + Z_UTIL_LISTIFY_1320(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1320, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1322(F, sep, ...) \ + Z_UTIL_LISTIFY_1321(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1321, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1323(F, sep, ...) \ + Z_UTIL_LISTIFY_1322(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1322, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1324(F, sep, ...) \ + Z_UTIL_LISTIFY_1323(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1323, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1325(F, sep, ...) \ + Z_UTIL_LISTIFY_1324(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1324, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1326(F, sep, ...) \ + Z_UTIL_LISTIFY_1325(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1325, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1327(F, sep, ...) \ + Z_UTIL_LISTIFY_1326(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1326, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1328(F, sep, ...) \ + Z_UTIL_LISTIFY_1327(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1327, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1329(F, sep, ...) \ + Z_UTIL_LISTIFY_1328(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1328, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1330(F, sep, ...) \ + Z_UTIL_LISTIFY_1329(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1329, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1331(F, sep, ...) \ + Z_UTIL_LISTIFY_1330(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1330, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1332(F, sep, ...) \ + Z_UTIL_LISTIFY_1331(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1331, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1333(F, sep, ...) \ + Z_UTIL_LISTIFY_1332(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1332, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1334(F, sep, ...) \ + Z_UTIL_LISTIFY_1333(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1333, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1335(F, sep, ...) \ + Z_UTIL_LISTIFY_1334(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1334, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1336(F, sep, ...) \ + Z_UTIL_LISTIFY_1335(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1335, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1337(F, sep, ...) \ + Z_UTIL_LISTIFY_1336(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1336, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1338(F, sep, ...) \ + Z_UTIL_LISTIFY_1337(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1337, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1339(F, sep, ...) \ + Z_UTIL_LISTIFY_1338(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1338, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1340(F, sep, ...) \ + Z_UTIL_LISTIFY_1339(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1339, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1341(F, sep, ...) \ + Z_UTIL_LISTIFY_1340(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1340, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1342(F, sep, ...) \ + Z_UTIL_LISTIFY_1341(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1341, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1343(F, sep, ...) \ + Z_UTIL_LISTIFY_1342(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1342, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1344(F, sep, ...) \ + Z_UTIL_LISTIFY_1343(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1343, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1345(F, sep, ...) \ + Z_UTIL_LISTIFY_1344(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1344, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1346(F, sep, ...) \ + Z_UTIL_LISTIFY_1345(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1345, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1347(F, sep, ...) \ + Z_UTIL_LISTIFY_1346(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1346, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1348(F, sep, ...) \ + Z_UTIL_LISTIFY_1347(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1347, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1349(F, sep, ...) \ + Z_UTIL_LISTIFY_1348(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1348, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1350(F, sep, ...) \ + Z_UTIL_LISTIFY_1349(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1349, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1351(F, sep, ...) \ + Z_UTIL_LISTIFY_1350(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1350, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1352(F, sep, ...) \ + Z_UTIL_LISTIFY_1351(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1351, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1353(F, sep, ...) \ + Z_UTIL_LISTIFY_1352(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1352, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1354(F, sep, ...) \ + Z_UTIL_LISTIFY_1353(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1353, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1355(F, sep, ...) \ + Z_UTIL_LISTIFY_1354(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1354, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1356(F, sep, ...) \ + Z_UTIL_LISTIFY_1355(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1355, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1357(F, sep, ...) \ + Z_UTIL_LISTIFY_1356(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1356, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1358(F, sep, ...) \ + Z_UTIL_LISTIFY_1357(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1357, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1359(F, sep, ...) \ + Z_UTIL_LISTIFY_1358(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1358, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1360(F, sep, ...) \ + Z_UTIL_LISTIFY_1359(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1359, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1361(F, sep, ...) \ + Z_UTIL_LISTIFY_1360(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1360, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1362(F, sep, ...) \ + Z_UTIL_LISTIFY_1361(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1361, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1363(F, sep, ...) \ + Z_UTIL_LISTIFY_1362(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1362, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1364(F, sep, ...) \ + Z_UTIL_LISTIFY_1363(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1363, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1365(F, sep, ...) \ + Z_UTIL_LISTIFY_1364(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1364, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1366(F, sep, ...) \ + Z_UTIL_LISTIFY_1365(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1365, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1367(F, sep, ...) \ + Z_UTIL_LISTIFY_1366(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1366, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1368(F, sep, ...) \ + Z_UTIL_LISTIFY_1367(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1367, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1369(F, sep, ...) \ + Z_UTIL_LISTIFY_1368(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1368, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1370(F, sep, ...) \ + Z_UTIL_LISTIFY_1369(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1369, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1371(F, sep, ...) \ + Z_UTIL_LISTIFY_1370(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1370, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1372(F, sep, ...) \ + Z_UTIL_LISTIFY_1371(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1371, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1373(F, sep, ...) \ + Z_UTIL_LISTIFY_1372(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1372, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1374(F, sep, ...) \ + Z_UTIL_LISTIFY_1373(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1373, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1375(F, sep, ...) \ + Z_UTIL_LISTIFY_1374(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1374, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1376(F, sep, ...) \ + Z_UTIL_LISTIFY_1375(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1375, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1377(F, sep, ...) \ + Z_UTIL_LISTIFY_1376(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1376, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1378(F, sep, ...) \ + Z_UTIL_LISTIFY_1377(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1377, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1379(F, sep, ...) \ + Z_UTIL_LISTIFY_1378(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1378, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1380(F, sep, ...) \ + Z_UTIL_LISTIFY_1379(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1379, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1381(F, sep, ...) \ + Z_UTIL_LISTIFY_1380(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1380, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1382(F, sep, ...) \ + Z_UTIL_LISTIFY_1381(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1381, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1383(F, sep, ...) \ + Z_UTIL_LISTIFY_1382(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1382, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1384(F, sep, ...) \ + Z_UTIL_LISTIFY_1383(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1383, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1385(F, sep, ...) \ + Z_UTIL_LISTIFY_1384(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1384, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1386(F, sep, ...) \ + Z_UTIL_LISTIFY_1385(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1385, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1387(F, sep, ...) \ + Z_UTIL_LISTIFY_1386(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1386, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1388(F, sep, ...) \ + Z_UTIL_LISTIFY_1387(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1387, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1389(F, sep, ...) \ + Z_UTIL_LISTIFY_1388(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1388, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1390(F, sep, ...) \ + Z_UTIL_LISTIFY_1389(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1389, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1391(F, sep, ...) \ + Z_UTIL_LISTIFY_1390(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1390, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1392(F, sep, ...) \ + Z_UTIL_LISTIFY_1391(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1391, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1393(F, sep, ...) \ + Z_UTIL_LISTIFY_1392(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1392, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1394(F, sep, ...) \ + Z_UTIL_LISTIFY_1393(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1393, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1395(F, sep, ...) \ + Z_UTIL_LISTIFY_1394(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1394, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1396(F, sep, ...) \ + Z_UTIL_LISTIFY_1395(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1395, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1397(F, sep, ...) \ + Z_UTIL_LISTIFY_1396(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1396, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1398(F, sep, ...) \ + Z_UTIL_LISTIFY_1397(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1397, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1399(F, sep, ...) \ + Z_UTIL_LISTIFY_1398(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1398, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1400(F, sep, ...) \ + Z_UTIL_LISTIFY_1399(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1399, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1401(F, sep, ...) \ + Z_UTIL_LISTIFY_1400(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1400, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1402(F, sep, ...) \ + Z_UTIL_LISTIFY_1401(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1401, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1403(F, sep, ...) \ + Z_UTIL_LISTIFY_1402(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1402, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1404(F, sep, ...) \ + Z_UTIL_LISTIFY_1403(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1403, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1405(F, sep, ...) \ + Z_UTIL_LISTIFY_1404(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1404, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1406(F, sep, ...) \ + Z_UTIL_LISTIFY_1405(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1405, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1407(F, sep, ...) \ + Z_UTIL_LISTIFY_1406(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1406, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1408(F, sep, ...) \ + Z_UTIL_LISTIFY_1407(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1407, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1409(F, sep, ...) \ + Z_UTIL_LISTIFY_1408(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1408, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1410(F, sep, ...) \ + Z_UTIL_LISTIFY_1409(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1409, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1411(F, sep, ...) \ + Z_UTIL_LISTIFY_1410(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1410, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1412(F, sep, ...) \ + Z_UTIL_LISTIFY_1411(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1411, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1413(F, sep, ...) \ + Z_UTIL_LISTIFY_1412(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1412, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1414(F, sep, ...) \ + Z_UTIL_LISTIFY_1413(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1413, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1415(F, sep, ...) \ + Z_UTIL_LISTIFY_1414(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1414, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1416(F, sep, ...) \ + Z_UTIL_LISTIFY_1415(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1415, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1417(F, sep, ...) \ + Z_UTIL_LISTIFY_1416(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1416, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1418(F, sep, ...) \ + Z_UTIL_LISTIFY_1417(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1417, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1419(F, sep, ...) \ + Z_UTIL_LISTIFY_1418(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1418, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1420(F, sep, ...) \ + Z_UTIL_LISTIFY_1419(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1419, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1421(F, sep, ...) \ + Z_UTIL_LISTIFY_1420(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1420, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1422(F, sep, ...) \ + Z_UTIL_LISTIFY_1421(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1421, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1423(F, sep, ...) \ + Z_UTIL_LISTIFY_1422(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1422, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1424(F, sep, ...) \ + Z_UTIL_LISTIFY_1423(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1423, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1425(F, sep, ...) \ + Z_UTIL_LISTIFY_1424(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1424, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1426(F, sep, ...) \ + Z_UTIL_LISTIFY_1425(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1425, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1427(F, sep, ...) \ + Z_UTIL_LISTIFY_1426(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1426, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1428(F, sep, ...) \ + Z_UTIL_LISTIFY_1427(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1427, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1429(F, sep, ...) \ + Z_UTIL_LISTIFY_1428(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1428, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1430(F, sep, ...) \ + Z_UTIL_LISTIFY_1429(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1429, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1431(F, sep, ...) \ + Z_UTIL_LISTIFY_1430(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1430, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1432(F, sep, ...) \ + Z_UTIL_LISTIFY_1431(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1431, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1433(F, sep, ...) \ + Z_UTIL_LISTIFY_1432(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1432, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1434(F, sep, ...) \ + Z_UTIL_LISTIFY_1433(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1433, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1435(F, sep, ...) \ + Z_UTIL_LISTIFY_1434(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1434, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1436(F, sep, ...) \ + Z_UTIL_LISTIFY_1435(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1435, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1437(F, sep, ...) \ + Z_UTIL_LISTIFY_1436(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1436, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1438(F, sep, ...) \ + Z_UTIL_LISTIFY_1437(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1437, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1439(F, sep, ...) \ + Z_UTIL_LISTIFY_1438(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1438, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1440(F, sep, ...) \ + Z_UTIL_LISTIFY_1439(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1439, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1441(F, sep, ...) \ + Z_UTIL_LISTIFY_1440(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1440, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1442(F, sep, ...) \ + Z_UTIL_LISTIFY_1441(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1441, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1443(F, sep, ...) \ + Z_UTIL_LISTIFY_1442(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1442, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1444(F, sep, ...) \ + Z_UTIL_LISTIFY_1443(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1443, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1445(F, sep, ...) \ + Z_UTIL_LISTIFY_1444(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1444, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1446(F, sep, ...) \ + Z_UTIL_LISTIFY_1445(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1445, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1447(F, sep, ...) \ + Z_UTIL_LISTIFY_1446(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1446, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1448(F, sep, ...) \ + Z_UTIL_LISTIFY_1447(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1447, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1449(F, sep, ...) \ + Z_UTIL_LISTIFY_1448(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1448, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1450(F, sep, ...) \ + Z_UTIL_LISTIFY_1449(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1449, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1451(F, sep, ...) \ + Z_UTIL_LISTIFY_1450(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1450, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1452(F, sep, ...) \ + Z_UTIL_LISTIFY_1451(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1451, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1453(F, sep, ...) \ + Z_UTIL_LISTIFY_1452(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1452, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1454(F, sep, ...) \ + Z_UTIL_LISTIFY_1453(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1453, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1455(F, sep, ...) \ + Z_UTIL_LISTIFY_1454(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1454, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1456(F, sep, ...) \ + Z_UTIL_LISTIFY_1455(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1455, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1457(F, sep, ...) \ + Z_UTIL_LISTIFY_1456(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1456, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1458(F, sep, ...) \ + Z_UTIL_LISTIFY_1457(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1457, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1459(F, sep, ...) \ + Z_UTIL_LISTIFY_1458(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1458, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1460(F, sep, ...) \ + Z_UTIL_LISTIFY_1459(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1459, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1461(F, sep, ...) \ + Z_UTIL_LISTIFY_1460(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1460, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1462(F, sep, ...) \ + Z_UTIL_LISTIFY_1461(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1461, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1463(F, sep, ...) \ + Z_UTIL_LISTIFY_1462(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1462, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1464(F, sep, ...) \ + Z_UTIL_LISTIFY_1463(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1463, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1465(F, sep, ...) \ + Z_UTIL_LISTIFY_1464(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1464, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1466(F, sep, ...) \ + Z_UTIL_LISTIFY_1465(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1465, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1467(F, sep, ...) \ + Z_UTIL_LISTIFY_1466(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1466, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1468(F, sep, ...) \ + Z_UTIL_LISTIFY_1467(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1467, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1469(F, sep, ...) \ + Z_UTIL_LISTIFY_1468(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1468, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1470(F, sep, ...) \ + Z_UTIL_LISTIFY_1469(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1469, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1471(F, sep, ...) \ + Z_UTIL_LISTIFY_1470(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1470, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1472(F, sep, ...) \ + Z_UTIL_LISTIFY_1471(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1471, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1473(F, sep, ...) \ + Z_UTIL_LISTIFY_1472(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1472, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1474(F, sep, ...) \ + Z_UTIL_LISTIFY_1473(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1473, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1475(F, sep, ...) \ + Z_UTIL_LISTIFY_1474(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1474, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1476(F, sep, ...) \ + Z_UTIL_LISTIFY_1475(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1475, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1477(F, sep, ...) \ + Z_UTIL_LISTIFY_1476(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1476, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1478(F, sep, ...) \ + Z_UTIL_LISTIFY_1477(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1477, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1479(F, sep, ...) \ + Z_UTIL_LISTIFY_1478(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1478, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1480(F, sep, ...) \ + Z_UTIL_LISTIFY_1479(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1479, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1481(F, sep, ...) \ + Z_UTIL_LISTIFY_1480(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1480, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1482(F, sep, ...) \ + Z_UTIL_LISTIFY_1481(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1481, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1483(F, sep, ...) \ + Z_UTIL_LISTIFY_1482(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1482, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1484(F, sep, ...) \ + Z_UTIL_LISTIFY_1483(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1483, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1485(F, sep, ...) \ + Z_UTIL_LISTIFY_1484(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1484, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1486(F, sep, ...) \ + Z_UTIL_LISTIFY_1485(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1485, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1487(F, sep, ...) \ + Z_UTIL_LISTIFY_1486(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1486, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1488(F, sep, ...) \ + Z_UTIL_LISTIFY_1487(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1487, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1489(F, sep, ...) \ + Z_UTIL_LISTIFY_1488(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1488, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1490(F, sep, ...) \ + Z_UTIL_LISTIFY_1489(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1489, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1491(F, sep, ...) \ + Z_UTIL_LISTIFY_1490(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1490, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1492(F, sep, ...) \ + Z_UTIL_LISTIFY_1491(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1491, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1493(F, sep, ...) \ + Z_UTIL_LISTIFY_1492(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1492, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1494(F, sep, ...) \ + Z_UTIL_LISTIFY_1493(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1493, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1495(F, sep, ...) \ + Z_UTIL_LISTIFY_1494(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1494, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1496(F, sep, ...) \ + Z_UTIL_LISTIFY_1495(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1495, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1497(F, sep, ...) \ + Z_UTIL_LISTIFY_1496(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1496, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1498(F, sep, ...) \ + Z_UTIL_LISTIFY_1497(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1497, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1499(F, sep, ...) \ + Z_UTIL_LISTIFY_1498(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1498, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1500(F, sep, ...) \ + Z_UTIL_LISTIFY_1499(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1499, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1501(F, sep, ...) \ + Z_UTIL_LISTIFY_1500(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1500, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1502(F, sep, ...) \ + Z_UTIL_LISTIFY_1501(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1501, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1503(F, sep, ...) \ + Z_UTIL_LISTIFY_1502(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1502, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1504(F, sep, ...) \ + Z_UTIL_LISTIFY_1503(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1503, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1505(F, sep, ...) \ + Z_UTIL_LISTIFY_1504(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1504, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1506(F, sep, ...) \ + Z_UTIL_LISTIFY_1505(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1505, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1507(F, sep, ...) \ + Z_UTIL_LISTIFY_1506(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1506, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1508(F, sep, ...) \ + Z_UTIL_LISTIFY_1507(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1507, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1509(F, sep, ...) \ + Z_UTIL_LISTIFY_1508(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1508, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1510(F, sep, ...) \ + Z_UTIL_LISTIFY_1509(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1509, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1511(F, sep, ...) \ + Z_UTIL_LISTIFY_1510(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1510, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1512(F, sep, ...) \ + Z_UTIL_LISTIFY_1511(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1511, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1513(F, sep, ...) \ + Z_UTIL_LISTIFY_1512(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1512, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1514(F, sep, ...) \ + Z_UTIL_LISTIFY_1513(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1513, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1515(F, sep, ...) \ + Z_UTIL_LISTIFY_1514(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1514, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1516(F, sep, ...) \ + Z_UTIL_LISTIFY_1515(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1515, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1517(F, sep, ...) \ + Z_UTIL_LISTIFY_1516(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1516, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1518(F, sep, ...) \ + Z_UTIL_LISTIFY_1517(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1517, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1519(F, sep, ...) \ + Z_UTIL_LISTIFY_1518(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1518, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1520(F, sep, ...) \ + Z_UTIL_LISTIFY_1519(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1519, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1521(F, sep, ...) \ + Z_UTIL_LISTIFY_1520(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1520, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1522(F, sep, ...) \ + Z_UTIL_LISTIFY_1521(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1521, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1523(F, sep, ...) \ + Z_UTIL_LISTIFY_1522(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1522, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1524(F, sep, ...) \ + Z_UTIL_LISTIFY_1523(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1523, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1525(F, sep, ...) \ + Z_UTIL_LISTIFY_1524(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1524, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1526(F, sep, ...) \ + Z_UTIL_LISTIFY_1525(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1525, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1527(F, sep, ...) \ + Z_UTIL_LISTIFY_1526(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1526, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1528(F, sep, ...) \ + Z_UTIL_LISTIFY_1527(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1527, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1529(F, sep, ...) \ + Z_UTIL_LISTIFY_1528(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1528, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1530(F, sep, ...) \ + Z_UTIL_LISTIFY_1529(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1529, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1531(F, sep, ...) \ + Z_UTIL_LISTIFY_1530(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1530, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1532(F, sep, ...) \ + Z_UTIL_LISTIFY_1531(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1531, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1533(F, sep, ...) \ + Z_UTIL_LISTIFY_1532(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1532, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1534(F, sep, ...) \ + Z_UTIL_LISTIFY_1533(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1533, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1535(F, sep, ...) \ + Z_UTIL_LISTIFY_1534(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1534, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1536(F, sep, ...) \ + Z_UTIL_LISTIFY_1535(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1535, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1537(F, sep, ...) \ + Z_UTIL_LISTIFY_1536(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1536, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1538(F, sep, ...) \ + Z_UTIL_LISTIFY_1537(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1537, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1539(F, sep, ...) \ + Z_UTIL_LISTIFY_1538(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1538, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1540(F, sep, ...) \ + Z_UTIL_LISTIFY_1539(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1539, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1541(F, sep, ...) \ + Z_UTIL_LISTIFY_1540(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1540, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1542(F, sep, ...) \ + Z_UTIL_LISTIFY_1541(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1541, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1543(F, sep, ...) \ + Z_UTIL_LISTIFY_1542(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1542, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1544(F, sep, ...) \ + Z_UTIL_LISTIFY_1543(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1543, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1545(F, sep, ...) \ + Z_UTIL_LISTIFY_1544(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1544, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1546(F, sep, ...) \ + Z_UTIL_LISTIFY_1545(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1545, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1547(F, sep, ...) \ + Z_UTIL_LISTIFY_1546(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1546, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1548(F, sep, ...) \ + Z_UTIL_LISTIFY_1547(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1547, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1549(F, sep, ...) \ + Z_UTIL_LISTIFY_1548(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1548, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1550(F, sep, ...) \ + Z_UTIL_LISTIFY_1549(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1549, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1551(F, sep, ...) \ + Z_UTIL_LISTIFY_1550(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1550, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1552(F, sep, ...) \ + Z_UTIL_LISTIFY_1551(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1551, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1553(F, sep, ...) \ + Z_UTIL_LISTIFY_1552(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1552, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1554(F, sep, ...) \ + Z_UTIL_LISTIFY_1553(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1553, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1555(F, sep, ...) \ + Z_UTIL_LISTIFY_1554(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1554, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1556(F, sep, ...) \ + Z_UTIL_LISTIFY_1555(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1555, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1557(F, sep, ...) \ + Z_UTIL_LISTIFY_1556(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1556, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1558(F, sep, ...) \ + Z_UTIL_LISTIFY_1557(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1557, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1559(F, sep, ...) \ + Z_UTIL_LISTIFY_1558(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1558, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1560(F, sep, ...) \ + Z_UTIL_LISTIFY_1559(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1559, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1561(F, sep, ...) \ + Z_UTIL_LISTIFY_1560(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1560, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1562(F, sep, ...) \ + Z_UTIL_LISTIFY_1561(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1561, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1563(F, sep, ...) \ + Z_UTIL_LISTIFY_1562(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1562, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1564(F, sep, ...) \ + Z_UTIL_LISTIFY_1563(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1563, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1565(F, sep, ...) \ + Z_UTIL_LISTIFY_1564(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1564, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1566(F, sep, ...) \ + Z_UTIL_LISTIFY_1565(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1565, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1567(F, sep, ...) \ + Z_UTIL_LISTIFY_1566(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1566, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1568(F, sep, ...) \ + Z_UTIL_LISTIFY_1567(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1567, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1569(F, sep, ...) \ + Z_UTIL_LISTIFY_1568(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1568, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1570(F, sep, ...) \ + Z_UTIL_LISTIFY_1569(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1569, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1571(F, sep, ...) \ + Z_UTIL_LISTIFY_1570(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1570, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1572(F, sep, ...) \ + Z_UTIL_LISTIFY_1571(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1571, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1573(F, sep, ...) \ + Z_UTIL_LISTIFY_1572(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1572, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1574(F, sep, ...) \ + Z_UTIL_LISTIFY_1573(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1573, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1575(F, sep, ...) \ + Z_UTIL_LISTIFY_1574(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1574, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1576(F, sep, ...) \ + Z_UTIL_LISTIFY_1575(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1575, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1577(F, sep, ...) \ + Z_UTIL_LISTIFY_1576(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1576, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1578(F, sep, ...) \ + Z_UTIL_LISTIFY_1577(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1577, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1579(F, sep, ...) \ + Z_UTIL_LISTIFY_1578(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1578, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1580(F, sep, ...) \ + Z_UTIL_LISTIFY_1579(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1579, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1581(F, sep, ...) \ + Z_UTIL_LISTIFY_1580(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1580, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1582(F, sep, ...) \ + Z_UTIL_LISTIFY_1581(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1581, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1583(F, sep, ...) \ + Z_UTIL_LISTIFY_1582(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1582, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1584(F, sep, ...) \ + Z_UTIL_LISTIFY_1583(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1583, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1585(F, sep, ...) \ + Z_UTIL_LISTIFY_1584(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1584, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1586(F, sep, ...) \ + Z_UTIL_LISTIFY_1585(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1585, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1587(F, sep, ...) \ + Z_UTIL_LISTIFY_1586(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1586, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1588(F, sep, ...) \ + Z_UTIL_LISTIFY_1587(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1587, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1589(F, sep, ...) \ + Z_UTIL_LISTIFY_1588(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1588, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1590(F, sep, ...) \ + Z_UTIL_LISTIFY_1589(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1589, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1591(F, sep, ...) \ + Z_UTIL_LISTIFY_1590(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1590, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1592(F, sep, ...) \ + Z_UTIL_LISTIFY_1591(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1591, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1593(F, sep, ...) \ + Z_UTIL_LISTIFY_1592(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1592, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1594(F, sep, ...) \ + Z_UTIL_LISTIFY_1593(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1593, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1595(F, sep, ...) \ + Z_UTIL_LISTIFY_1594(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1594, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1596(F, sep, ...) \ + Z_UTIL_LISTIFY_1595(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1595, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1597(F, sep, ...) \ + Z_UTIL_LISTIFY_1596(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1596, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1598(F, sep, ...) \ + Z_UTIL_LISTIFY_1597(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1597, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1599(F, sep, ...) \ + Z_UTIL_LISTIFY_1598(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1598, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1600(F, sep, ...) \ + Z_UTIL_LISTIFY_1599(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1599, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1601(F, sep, ...) \ + Z_UTIL_LISTIFY_1600(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1600, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1602(F, sep, ...) \ + Z_UTIL_LISTIFY_1601(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1601, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1603(F, sep, ...) \ + Z_UTIL_LISTIFY_1602(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1602, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1604(F, sep, ...) \ + Z_UTIL_LISTIFY_1603(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1603, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1605(F, sep, ...) \ + Z_UTIL_LISTIFY_1604(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1604, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1606(F, sep, ...) \ + Z_UTIL_LISTIFY_1605(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1605, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1607(F, sep, ...) \ + Z_UTIL_LISTIFY_1606(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1606, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1608(F, sep, ...) \ + Z_UTIL_LISTIFY_1607(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1607, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1609(F, sep, ...) \ + Z_UTIL_LISTIFY_1608(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1608, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1610(F, sep, ...) \ + Z_UTIL_LISTIFY_1609(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1609, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1611(F, sep, ...) \ + Z_UTIL_LISTIFY_1610(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1610, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1612(F, sep, ...) \ + Z_UTIL_LISTIFY_1611(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1611, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1613(F, sep, ...) \ + Z_UTIL_LISTIFY_1612(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1612, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1614(F, sep, ...) \ + Z_UTIL_LISTIFY_1613(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1613, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1615(F, sep, ...) \ + Z_UTIL_LISTIFY_1614(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1614, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1616(F, sep, ...) \ + Z_UTIL_LISTIFY_1615(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1615, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1617(F, sep, ...) \ + Z_UTIL_LISTIFY_1616(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1616, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1618(F, sep, ...) \ + Z_UTIL_LISTIFY_1617(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1617, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1619(F, sep, ...) \ + Z_UTIL_LISTIFY_1618(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1618, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1620(F, sep, ...) \ + Z_UTIL_LISTIFY_1619(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1619, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1621(F, sep, ...) \ + Z_UTIL_LISTIFY_1620(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1620, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1622(F, sep, ...) \ + Z_UTIL_LISTIFY_1621(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1621, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1623(F, sep, ...) \ + Z_UTIL_LISTIFY_1622(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1622, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1624(F, sep, ...) \ + Z_UTIL_LISTIFY_1623(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1623, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1625(F, sep, ...) \ + Z_UTIL_LISTIFY_1624(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1624, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1626(F, sep, ...) \ + Z_UTIL_LISTIFY_1625(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1625, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1627(F, sep, ...) \ + Z_UTIL_LISTIFY_1626(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1626, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1628(F, sep, ...) \ + Z_UTIL_LISTIFY_1627(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1627, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1629(F, sep, ...) \ + Z_UTIL_LISTIFY_1628(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1628, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1630(F, sep, ...) \ + Z_UTIL_LISTIFY_1629(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1629, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1631(F, sep, ...) \ + Z_UTIL_LISTIFY_1630(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1630, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1632(F, sep, ...) \ + Z_UTIL_LISTIFY_1631(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1631, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1633(F, sep, ...) \ + Z_UTIL_LISTIFY_1632(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1632, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1634(F, sep, ...) \ + Z_UTIL_LISTIFY_1633(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1633, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1635(F, sep, ...) \ + Z_UTIL_LISTIFY_1634(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1634, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1636(F, sep, ...) \ + Z_UTIL_LISTIFY_1635(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1635, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1637(F, sep, ...) \ + Z_UTIL_LISTIFY_1636(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1636, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1638(F, sep, ...) \ + Z_UTIL_LISTIFY_1637(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1637, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1639(F, sep, ...) \ + Z_UTIL_LISTIFY_1638(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1638, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1640(F, sep, ...) \ + Z_UTIL_LISTIFY_1639(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1639, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1641(F, sep, ...) \ + Z_UTIL_LISTIFY_1640(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1640, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1642(F, sep, ...) \ + Z_UTIL_LISTIFY_1641(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1641, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1643(F, sep, ...) \ + Z_UTIL_LISTIFY_1642(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1642, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1644(F, sep, ...) \ + Z_UTIL_LISTIFY_1643(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1643, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1645(F, sep, ...) \ + Z_UTIL_LISTIFY_1644(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1644, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1646(F, sep, ...) \ + Z_UTIL_LISTIFY_1645(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1645, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1647(F, sep, ...) \ + Z_UTIL_LISTIFY_1646(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1646, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1648(F, sep, ...) \ + Z_UTIL_LISTIFY_1647(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1647, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1649(F, sep, ...) \ + Z_UTIL_LISTIFY_1648(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1648, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1650(F, sep, ...) \ + Z_UTIL_LISTIFY_1649(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1649, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1651(F, sep, ...) \ + Z_UTIL_LISTIFY_1650(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1650, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1652(F, sep, ...) \ + Z_UTIL_LISTIFY_1651(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1651, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1653(F, sep, ...) \ + Z_UTIL_LISTIFY_1652(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1652, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1654(F, sep, ...) \ + Z_UTIL_LISTIFY_1653(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1653, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1655(F, sep, ...) \ + Z_UTIL_LISTIFY_1654(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1654, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1656(F, sep, ...) \ + Z_UTIL_LISTIFY_1655(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1655, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1657(F, sep, ...) \ + Z_UTIL_LISTIFY_1656(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1656, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1658(F, sep, ...) \ + Z_UTIL_LISTIFY_1657(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1657, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1659(F, sep, ...) \ + Z_UTIL_LISTIFY_1658(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1658, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1660(F, sep, ...) \ + Z_UTIL_LISTIFY_1659(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1659, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1661(F, sep, ...) \ + Z_UTIL_LISTIFY_1660(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1660, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1662(F, sep, ...) \ + Z_UTIL_LISTIFY_1661(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1661, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1663(F, sep, ...) \ + Z_UTIL_LISTIFY_1662(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1662, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1664(F, sep, ...) \ + Z_UTIL_LISTIFY_1663(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1663, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1665(F, sep, ...) \ + Z_UTIL_LISTIFY_1664(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1664, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1666(F, sep, ...) \ + Z_UTIL_LISTIFY_1665(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1665, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1667(F, sep, ...) \ + Z_UTIL_LISTIFY_1666(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1666, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1668(F, sep, ...) \ + Z_UTIL_LISTIFY_1667(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1667, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1669(F, sep, ...) \ + Z_UTIL_LISTIFY_1668(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1668, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1670(F, sep, ...) \ + Z_UTIL_LISTIFY_1669(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1669, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1671(F, sep, ...) \ + Z_UTIL_LISTIFY_1670(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1670, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1672(F, sep, ...) \ + Z_UTIL_LISTIFY_1671(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1671, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1673(F, sep, ...) \ + Z_UTIL_LISTIFY_1672(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1672, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1674(F, sep, ...) \ + Z_UTIL_LISTIFY_1673(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1673, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1675(F, sep, ...) \ + Z_UTIL_LISTIFY_1674(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1674, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1676(F, sep, ...) \ + Z_UTIL_LISTIFY_1675(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1675, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1677(F, sep, ...) \ + Z_UTIL_LISTIFY_1676(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1676, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1678(F, sep, ...) \ + Z_UTIL_LISTIFY_1677(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1677, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1679(F, sep, ...) \ + Z_UTIL_LISTIFY_1678(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1678, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1680(F, sep, ...) \ + Z_UTIL_LISTIFY_1679(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1679, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1681(F, sep, ...) \ + Z_UTIL_LISTIFY_1680(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1680, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1682(F, sep, ...) \ + Z_UTIL_LISTIFY_1681(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1681, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1683(F, sep, ...) \ + Z_UTIL_LISTIFY_1682(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1682, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1684(F, sep, ...) \ + Z_UTIL_LISTIFY_1683(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1683, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1685(F, sep, ...) \ + Z_UTIL_LISTIFY_1684(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1684, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1686(F, sep, ...) \ + Z_UTIL_LISTIFY_1685(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1685, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1687(F, sep, ...) \ + Z_UTIL_LISTIFY_1686(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1686, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1688(F, sep, ...) \ + Z_UTIL_LISTIFY_1687(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1687, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1689(F, sep, ...) \ + Z_UTIL_LISTIFY_1688(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1688, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1690(F, sep, ...) \ + Z_UTIL_LISTIFY_1689(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1689, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1691(F, sep, ...) \ + Z_UTIL_LISTIFY_1690(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1690, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1692(F, sep, ...) \ + Z_UTIL_LISTIFY_1691(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1691, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1693(F, sep, ...) \ + Z_UTIL_LISTIFY_1692(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1692, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1694(F, sep, ...) \ + Z_UTIL_LISTIFY_1693(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1693, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1695(F, sep, ...) \ + Z_UTIL_LISTIFY_1694(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1694, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1696(F, sep, ...) \ + Z_UTIL_LISTIFY_1695(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1695, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1697(F, sep, ...) \ + Z_UTIL_LISTIFY_1696(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1696, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1698(F, sep, ...) \ + Z_UTIL_LISTIFY_1697(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1697, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1699(F, sep, ...) \ + Z_UTIL_LISTIFY_1698(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1698, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1700(F, sep, ...) \ + Z_UTIL_LISTIFY_1699(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1699, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1701(F, sep, ...) \ + Z_UTIL_LISTIFY_1700(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1700, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1702(F, sep, ...) \ + Z_UTIL_LISTIFY_1701(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1701, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1703(F, sep, ...) \ + Z_UTIL_LISTIFY_1702(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1702, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1704(F, sep, ...) \ + Z_UTIL_LISTIFY_1703(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1703, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1705(F, sep, ...) \ + Z_UTIL_LISTIFY_1704(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1704, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1706(F, sep, ...) \ + Z_UTIL_LISTIFY_1705(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1705, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1707(F, sep, ...) \ + Z_UTIL_LISTIFY_1706(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1706, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1708(F, sep, ...) \ + Z_UTIL_LISTIFY_1707(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1707, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1709(F, sep, ...) \ + Z_UTIL_LISTIFY_1708(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1708, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1710(F, sep, ...) \ + Z_UTIL_LISTIFY_1709(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1709, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1711(F, sep, ...) \ + Z_UTIL_LISTIFY_1710(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1710, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1712(F, sep, ...) \ + Z_UTIL_LISTIFY_1711(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1711, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1713(F, sep, ...) \ + Z_UTIL_LISTIFY_1712(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1712, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1714(F, sep, ...) \ + Z_UTIL_LISTIFY_1713(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1713, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1715(F, sep, ...) \ + Z_UTIL_LISTIFY_1714(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1714, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1716(F, sep, ...) \ + Z_UTIL_LISTIFY_1715(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1715, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1717(F, sep, ...) \ + Z_UTIL_LISTIFY_1716(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1716, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1718(F, sep, ...) \ + Z_UTIL_LISTIFY_1717(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1717, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1719(F, sep, ...) \ + Z_UTIL_LISTIFY_1718(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1718, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1720(F, sep, ...) \ + Z_UTIL_LISTIFY_1719(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1719, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1721(F, sep, ...) \ + Z_UTIL_LISTIFY_1720(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1720, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1722(F, sep, ...) \ + Z_UTIL_LISTIFY_1721(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1721, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1723(F, sep, ...) \ + Z_UTIL_LISTIFY_1722(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1722, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1724(F, sep, ...) \ + Z_UTIL_LISTIFY_1723(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1723, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1725(F, sep, ...) \ + Z_UTIL_LISTIFY_1724(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1724, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1726(F, sep, ...) \ + Z_UTIL_LISTIFY_1725(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1725, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1727(F, sep, ...) \ + Z_UTIL_LISTIFY_1726(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1726, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1728(F, sep, ...) \ + Z_UTIL_LISTIFY_1727(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1727, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1729(F, sep, ...) \ + Z_UTIL_LISTIFY_1728(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1728, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1730(F, sep, ...) \ + Z_UTIL_LISTIFY_1729(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1729, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1731(F, sep, ...) \ + Z_UTIL_LISTIFY_1730(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1730, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1732(F, sep, ...) \ + Z_UTIL_LISTIFY_1731(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1731, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1733(F, sep, ...) \ + Z_UTIL_LISTIFY_1732(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1732, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1734(F, sep, ...) \ + Z_UTIL_LISTIFY_1733(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1733, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1735(F, sep, ...) \ + Z_UTIL_LISTIFY_1734(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1734, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1736(F, sep, ...) \ + Z_UTIL_LISTIFY_1735(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1735, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1737(F, sep, ...) \ + Z_UTIL_LISTIFY_1736(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1736, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1738(F, sep, ...) \ + Z_UTIL_LISTIFY_1737(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1737, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1739(F, sep, ...) \ + Z_UTIL_LISTIFY_1738(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1738, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1740(F, sep, ...) \ + Z_UTIL_LISTIFY_1739(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1739, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1741(F, sep, ...) \ + Z_UTIL_LISTIFY_1740(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1740, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1742(F, sep, ...) \ + Z_UTIL_LISTIFY_1741(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1741, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1743(F, sep, ...) \ + Z_UTIL_LISTIFY_1742(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1742, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1744(F, sep, ...) \ + Z_UTIL_LISTIFY_1743(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1743, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1745(F, sep, ...) \ + Z_UTIL_LISTIFY_1744(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1744, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1746(F, sep, ...) \ + Z_UTIL_LISTIFY_1745(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1745, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1747(F, sep, ...) \ + Z_UTIL_LISTIFY_1746(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1746, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1748(F, sep, ...) \ + Z_UTIL_LISTIFY_1747(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1747, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1749(F, sep, ...) \ + Z_UTIL_LISTIFY_1748(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1748, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1750(F, sep, ...) \ + Z_UTIL_LISTIFY_1749(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1749, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1751(F, sep, ...) \ + Z_UTIL_LISTIFY_1750(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1750, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1752(F, sep, ...) \ + Z_UTIL_LISTIFY_1751(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1751, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1753(F, sep, ...) \ + Z_UTIL_LISTIFY_1752(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1752, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1754(F, sep, ...) \ + Z_UTIL_LISTIFY_1753(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1753, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1755(F, sep, ...) \ + Z_UTIL_LISTIFY_1754(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1754, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1756(F, sep, ...) \ + Z_UTIL_LISTIFY_1755(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1755, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1757(F, sep, ...) \ + Z_UTIL_LISTIFY_1756(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1756, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1758(F, sep, ...) \ + Z_UTIL_LISTIFY_1757(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1757, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1759(F, sep, ...) \ + Z_UTIL_LISTIFY_1758(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1758, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1760(F, sep, ...) \ + Z_UTIL_LISTIFY_1759(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1759, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1761(F, sep, ...) \ + Z_UTIL_LISTIFY_1760(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1760, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1762(F, sep, ...) \ + Z_UTIL_LISTIFY_1761(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1761, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1763(F, sep, ...) \ + Z_UTIL_LISTIFY_1762(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1762, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1764(F, sep, ...) \ + Z_UTIL_LISTIFY_1763(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1763, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1765(F, sep, ...) \ + Z_UTIL_LISTIFY_1764(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1764, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1766(F, sep, ...) \ + Z_UTIL_LISTIFY_1765(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1765, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1767(F, sep, ...) \ + Z_UTIL_LISTIFY_1766(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1766, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1768(F, sep, ...) \ + Z_UTIL_LISTIFY_1767(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1767, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1769(F, sep, ...) \ + Z_UTIL_LISTIFY_1768(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1768, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1770(F, sep, ...) \ + Z_UTIL_LISTIFY_1769(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1769, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1771(F, sep, ...) \ + Z_UTIL_LISTIFY_1770(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1770, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1772(F, sep, ...) \ + Z_UTIL_LISTIFY_1771(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1771, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1773(F, sep, ...) \ + Z_UTIL_LISTIFY_1772(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1772, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1774(F, sep, ...) \ + Z_UTIL_LISTIFY_1773(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1773, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1775(F, sep, ...) \ + Z_UTIL_LISTIFY_1774(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1774, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1776(F, sep, ...) \ + Z_UTIL_LISTIFY_1775(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1775, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1777(F, sep, ...) \ + Z_UTIL_LISTIFY_1776(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1776, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1778(F, sep, ...) \ + Z_UTIL_LISTIFY_1777(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1777, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1779(F, sep, ...) \ + Z_UTIL_LISTIFY_1778(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1778, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1780(F, sep, ...) \ + Z_UTIL_LISTIFY_1779(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1779, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1781(F, sep, ...) \ + Z_UTIL_LISTIFY_1780(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1780, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1782(F, sep, ...) \ + Z_UTIL_LISTIFY_1781(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1781, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1783(F, sep, ...) \ + Z_UTIL_LISTIFY_1782(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1782, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1784(F, sep, ...) \ + Z_UTIL_LISTIFY_1783(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1783, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1785(F, sep, ...) \ + Z_UTIL_LISTIFY_1784(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1784, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1786(F, sep, ...) \ + Z_UTIL_LISTIFY_1785(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1785, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1787(F, sep, ...) \ + Z_UTIL_LISTIFY_1786(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1786, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1788(F, sep, ...) \ + Z_UTIL_LISTIFY_1787(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1787, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1789(F, sep, ...) \ + Z_UTIL_LISTIFY_1788(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1788, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1790(F, sep, ...) \ + Z_UTIL_LISTIFY_1789(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1789, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1791(F, sep, ...) \ + Z_UTIL_LISTIFY_1790(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1790, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1792(F, sep, ...) \ + Z_UTIL_LISTIFY_1791(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1791, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1793(F, sep, ...) \ + Z_UTIL_LISTIFY_1792(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1792, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1794(F, sep, ...) \ + Z_UTIL_LISTIFY_1793(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1793, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1795(F, sep, ...) \ + Z_UTIL_LISTIFY_1794(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1794, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1796(F, sep, ...) \ + Z_UTIL_LISTIFY_1795(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1795, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1797(F, sep, ...) \ + Z_UTIL_LISTIFY_1796(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1796, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1798(F, sep, ...) \ + Z_UTIL_LISTIFY_1797(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1797, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1799(F, sep, ...) \ + Z_UTIL_LISTIFY_1798(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1798, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1800(F, sep, ...) \ + Z_UTIL_LISTIFY_1799(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1799, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1801(F, sep, ...) \ + Z_UTIL_LISTIFY_1800(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1800, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1802(F, sep, ...) \ + Z_UTIL_LISTIFY_1801(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1801, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1803(F, sep, ...) \ + Z_UTIL_LISTIFY_1802(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1802, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1804(F, sep, ...) \ + Z_UTIL_LISTIFY_1803(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1803, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1805(F, sep, ...) \ + Z_UTIL_LISTIFY_1804(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1804, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1806(F, sep, ...) \ + Z_UTIL_LISTIFY_1805(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1805, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1807(F, sep, ...) \ + Z_UTIL_LISTIFY_1806(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1806, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1808(F, sep, ...) \ + Z_UTIL_LISTIFY_1807(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1807, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1809(F, sep, ...) \ + Z_UTIL_LISTIFY_1808(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1808, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1810(F, sep, ...) \ + Z_UTIL_LISTIFY_1809(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1809, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1811(F, sep, ...) \ + Z_UTIL_LISTIFY_1810(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1810, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1812(F, sep, ...) \ + Z_UTIL_LISTIFY_1811(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1811, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1813(F, sep, ...) \ + Z_UTIL_LISTIFY_1812(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1812, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1814(F, sep, ...) \ + Z_UTIL_LISTIFY_1813(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1813, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1815(F, sep, ...) \ + Z_UTIL_LISTIFY_1814(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1814, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1816(F, sep, ...) \ + Z_UTIL_LISTIFY_1815(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1815, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1817(F, sep, ...) \ + Z_UTIL_LISTIFY_1816(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1816, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1818(F, sep, ...) \ + Z_UTIL_LISTIFY_1817(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1817, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1819(F, sep, ...) \ + Z_UTIL_LISTIFY_1818(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1818, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1820(F, sep, ...) \ + Z_UTIL_LISTIFY_1819(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1819, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1821(F, sep, ...) \ + Z_UTIL_LISTIFY_1820(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1820, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1822(F, sep, ...) \ + Z_UTIL_LISTIFY_1821(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1821, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1823(F, sep, ...) \ + Z_UTIL_LISTIFY_1822(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1822, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1824(F, sep, ...) \ + Z_UTIL_LISTIFY_1823(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1823, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1825(F, sep, ...) \ + Z_UTIL_LISTIFY_1824(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1824, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1826(F, sep, ...) \ + Z_UTIL_LISTIFY_1825(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1825, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1827(F, sep, ...) \ + Z_UTIL_LISTIFY_1826(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1826, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1828(F, sep, ...) \ + Z_UTIL_LISTIFY_1827(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1827, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1829(F, sep, ...) \ + Z_UTIL_LISTIFY_1828(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1828, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1830(F, sep, ...) \ + Z_UTIL_LISTIFY_1829(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1829, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1831(F, sep, ...) \ + Z_UTIL_LISTIFY_1830(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1830, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1832(F, sep, ...) \ + Z_UTIL_LISTIFY_1831(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1831, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1833(F, sep, ...) \ + Z_UTIL_LISTIFY_1832(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1832, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1834(F, sep, ...) \ + Z_UTIL_LISTIFY_1833(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1833, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1835(F, sep, ...) \ + Z_UTIL_LISTIFY_1834(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1834, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1836(F, sep, ...) \ + Z_UTIL_LISTIFY_1835(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1835, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1837(F, sep, ...) \ + Z_UTIL_LISTIFY_1836(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1836, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1838(F, sep, ...) \ + Z_UTIL_LISTIFY_1837(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1837, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1839(F, sep, ...) \ + Z_UTIL_LISTIFY_1838(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1838, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1840(F, sep, ...) \ + Z_UTIL_LISTIFY_1839(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1839, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1841(F, sep, ...) \ + Z_UTIL_LISTIFY_1840(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1840, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1842(F, sep, ...) \ + Z_UTIL_LISTIFY_1841(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1841, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1843(F, sep, ...) \ + Z_UTIL_LISTIFY_1842(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1842, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1844(F, sep, ...) \ + Z_UTIL_LISTIFY_1843(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1843, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1845(F, sep, ...) \ + Z_UTIL_LISTIFY_1844(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1844, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1846(F, sep, ...) \ + Z_UTIL_LISTIFY_1845(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1845, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1847(F, sep, ...) \ + Z_UTIL_LISTIFY_1846(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1846, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1848(F, sep, ...) \ + Z_UTIL_LISTIFY_1847(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1847, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1849(F, sep, ...) \ + Z_UTIL_LISTIFY_1848(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1848, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1850(F, sep, ...) \ + Z_UTIL_LISTIFY_1849(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1849, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1851(F, sep, ...) \ + Z_UTIL_LISTIFY_1850(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1850, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1852(F, sep, ...) \ + Z_UTIL_LISTIFY_1851(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1851, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1853(F, sep, ...) \ + Z_UTIL_LISTIFY_1852(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1852, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1854(F, sep, ...) \ + Z_UTIL_LISTIFY_1853(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1853, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1855(F, sep, ...) \ + Z_UTIL_LISTIFY_1854(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1854, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1856(F, sep, ...) \ + Z_UTIL_LISTIFY_1855(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1855, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1857(F, sep, ...) \ + Z_UTIL_LISTIFY_1856(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1856, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1858(F, sep, ...) \ + Z_UTIL_LISTIFY_1857(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1857, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1859(F, sep, ...) \ + Z_UTIL_LISTIFY_1858(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1858, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1860(F, sep, ...) \ + Z_UTIL_LISTIFY_1859(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1859, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1861(F, sep, ...) \ + Z_UTIL_LISTIFY_1860(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1860, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1862(F, sep, ...) \ + Z_UTIL_LISTIFY_1861(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1861, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1863(F, sep, ...) \ + Z_UTIL_LISTIFY_1862(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1862, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1864(F, sep, ...) \ + Z_UTIL_LISTIFY_1863(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1863, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1865(F, sep, ...) \ + Z_UTIL_LISTIFY_1864(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1864, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1866(F, sep, ...) \ + Z_UTIL_LISTIFY_1865(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1865, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1867(F, sep, ...) \ + Z_UTIL_LISTIFY_1866(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1866, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1868(F, sep, ...) \ + Z_UTIL_LISTIFY_1867(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1867, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1869(F, sep, ...) \ + Z_UTIL_LISTIFY_1868(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1868, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1870(F, sep, ...) \ + Z_UTIL_LISTIFY_1869(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1869, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1871(F, sep, ...) \ + Z_UTIL_LISTIFY_1870(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1870, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1872(F, sep, ...) \ + Z_UTIL_LISTIFY_1871(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1871, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1873(F, sep, ...) \ + Z_UTIL_LISTIFY_1872(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1872, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1874(F, sep, ...) \ + Z_UTIL_LISTIFY_1873(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1873, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1875(F, sep, ...) \ + Z_UTIL_LISTIFY_1874(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1874, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1876(F, sep, ...) \ + Z_UTIL_LISTIFY_1875(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1875, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1877(F, sep, ...) \ + Z_UTIL_LISTIFY_1876(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1876, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1878(F, sep, ...) \ + Z_UTIL_LISTIFY_1877(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1877, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1879(F, sep, ...) \ + Z_UTIL_LISTIFY_1878(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1878, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1880(F, sep, ...) \ + Z_UTIL_LISTIFY_1879(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1879, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1881(F, sep, ...) \ + Z_UTIL_LISTIFY_1880(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1880, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1882(F, sep, ...) \ + Z_UTIL_LISTIFY_1881(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1881, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1883(F, sep, ...) \ + Z_UTIL_LISTIFY_1882(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1882, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1884(F, sep, ...) \ + Z_UTIL_LISTIFY_1883(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1883, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1885(F, sep, ...) \ + Z_UTIL_LISTIFY_1884(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1884, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1886(F, sep, ...) \ + Z_UTIL_LISTIFY_1885(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1885, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1887(F, sep, ...) \ + Z_UTIL_LISTIFY_1886(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1886, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1888(F, sep, ...) \ + Z_UTIL_LISTIFY_1887(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1887, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1889(F, sep, ...) \ + Z_UTIL_LISTIFY_1888(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1888, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1890(F, sep, ...) \ + Z_UTIL_LISTIFY_1889(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1889, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1891(F, sep, ...) \ + Z_UTIL_LISTIFY_1890(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1890, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1892(F, sep, ...) \ + Z_UTIL_LISTIFY_1891(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1891, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1893(F, sep, ...) \ + Z_UTIL_LISTIFY_1892(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1892, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1894(F, sep, ...) \ + Z_UTIL_LISTIFY_1893(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1893, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1895(F, sep, ...) \ + Z_UTIL_LISTIFY_1894(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1894, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1896(F, sep, ...) \ + Z_UTIL_LISTIFY_1895(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1895, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1897(F, sep, ...) \ + Z_UTIL_LISTIFY_1896(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1896, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1898(F, sep, ...) \ + Z_UTIL_LISTIFY_1897(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1897, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1899(F, sep, ...) \ + Z_UTIL_LISTIFY_1898(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1898, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1900(F, sep, ...) \ + Z_UTIL_LISTIFY_1899(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1899, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1901(F, sep, ...) \ + Z_UTIL_LISTIFY_1900(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1900, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1902(F, sep, ...) \ + Z_UTIL_LISTIFY_1901(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1901, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1903(F, sep, ...) \ + Z_UTIL_LISTIFY_1902(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1902, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1904(F, sep, ...) \ + Z_UTIL_LISTIFY_1903(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1903, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1905(F, sep, ...) \ + Z_UTIL_LISTIFY_1904(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1904, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1906(F, sep, ...) \ + Z_UTIL_LISTIFY_1905(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1905, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1907(F, sep, ...) \ + Z_UTIL_LISTIFY_1906(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1906, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1908(F, sep, ...) \ + Z_UTIL_LISTIFY_1907(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1907, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1909(F, sep, ...) \ + Z_UTIL_LISTIFY_1908(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1908, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1910(F, sep, ...) \ + Z_UTIL_LISTIFY_1909(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1909, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1911(F, sep, ...) \ + Z_UTIL_LISTIFY_1910(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1910, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1912(F, sep, ...) \ + Z_UTIL_LISTIFY_1911(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1911, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1913(F, sep, ...) \ + Z_UTIL_LISTIFY_1912(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1912, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1914(F, sep, ...) \ + Z_UTIL_LISTIFY_1913(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1913, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1915(F, sep, ...) \ + Z_UTIL_LISTIFY_1914(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1914, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1916(F, sep, ...) \ + Z_UTIL_LISTIFY_1915(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1915, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1917(F, sep, ...) \ + Z_UTIL_LISTIFY_1916(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1916, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1918(F, sep, ...) \ + Z_UTIL_LISTIFY_1917(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1917, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1919(F, sep, ...) \ + Z_UTIL_LISTIFY_1918(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1918, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1920(F, sep, ...) \ + Z_UTIL_LISTIFY_1919(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1919, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1921(F, sep, ...) \ + Z_UTIL_LISTIFY_1920(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1920, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1922(F, sep, ...) \ + Z_UTIL_LISTIFY_1921(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1921, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1923(F, sep, ...) \ + Z_UTIL_LISTIFY_1922(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1922, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1924(F, sep, ...) \ + Z_UTIL_LISTIFY_1923(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1923, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1925(F, sep, ...) \ + Z_UTIL_LISTIFY_1924(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1924, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1926(F, sep, ...) \ + Z_UTIL_LISTIFY_1925(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1925, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1927(F, sep, ...) \ + Z_UTIL_LISTIFY_1926(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1926, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1928(F, sep, ...) \ + Z_UTIL_LISTIFY_1927(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1927, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1929(F, sep, ...) \ + Z_UTIL_LISTIFY_1928(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1928, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1930(F, sep, ...) \ + Z_UTIL_LISTIFY_1929(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1929, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1931(F, sep, ...) \ + Z_UTIL_LISTIFY_1930(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1930, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1932(F, sep, ...) \ + Z_UTIL_LISTIFY_1931(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1931, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1933(F, sep, ...) \ + Z_UTIL_LISTIFY_1932(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1932, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1934(F, sep, ...) \ + Z_UTIL_LISTIFY_1933(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1933, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1935(F, sep, ...) \ + Z_UTIL_LISTIFY_1934(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1934, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1936(F, sep, ...) \ + Z_UTIL_LISTIFY_1935(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1935, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1937(F, sep, ...) \ + Z_UTIL_LISTIFY_1936(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1936, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1938(F, sep, ...) \ + Z_UTIL_LISTIFY_1937(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1937, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1939(F, sep, ...) \ + Z_UTIL_LISTIFY_1938(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1938, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1940(F, sep, ...) \ + Z_UTIL_LISTIFY_1939(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1939, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1941(F, sep, ...) \ + Z_UTIL_LISTIFY_1940(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1940, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1942(F, sep, ...) \ + Z_UTIL_LISTIFY_1941(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1941, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1943(F, sep, ...) \ + Z_UTIL_LISTIFY_1942(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1942, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1944(F, sep, ...) \ + Z_UTIL_LISTIFY_1943(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1943, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1945(F, sep, ...) \ + Z_UTIL_LISTIFY_1944(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1944, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1946(F, sep, ...) \ + Z_UTIL_LISTIFY_1945(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1945, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1947(F, sep, ...) \ + Z_UTIL_LISTIFY_1946(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1946, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1948(F, sep, ...) \ + Z_UTIL_LISTIFY_1947(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1947, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1949(F, sep, ...) \ + Z_UTIL_LISTIFY_1948(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1948, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1950(F, sep, ...) \ + Z_UTIL_LISTIFY_1949(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1949, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1951(F, sep, ...) \ + Z_UTIL_LISTIFY_1950(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1950, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1952(F, sep, ...) \ + Z_UTIL_LISTIFY_1951(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1951, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1953(F, sep, ...) \ + Z_UTIL_LISTIFY_1952(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1952, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1954(F, sep, ...) \ + Z_UTIL_LISTIFY_1953(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1953, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1955(F, sep, ...) \ + Z_UTIL_LISTIFY_1954(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1954, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1956(F, sep, ...) \ + Z_UTIL_LISTIFY_1955(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1955, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1957(F, sep, ...) \ + Z_UTIL_LISTIFY_1956(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1956, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1958(F, sep, ...) \ + Z_UTIL_LISTIFY_1957(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1957, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1959(F, sep, ...) \ + Z_UTIL_LISTIFY_1958(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1958, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1960(F, sep, ...) \ + Z_UTIL_LISTIFY_1959(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1959, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1961(F, sep, ...) \ + Z_UTIL_LISTIFY_1960(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1960, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1962(F, sep, ...) \ + Z_UTIL_LISTIFY_1961(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1961, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1963(F, sep, ...) \ + Z_UTIL_LISTIFY_1962(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1962, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1964(F, sep, ...) \ + Z_UTIL_LISTIFY_1963(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1963, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1965(F, sep, ...) \ + Z_UTIL_LISTIFY_1964(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1964, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1966(F, sep, ...) \ + Z_UTIL_LISTIFY_1965(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1965, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1967(F, sep, ...) \ + Z_UTIL_LISTIFY_1966(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1966, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1968(F, sep, ...) \ + Z_UTIL_LISTIFY_1967(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1967, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1969(F, sep, ...) \ + Z_UTIL_LISTIFY_1968(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1968, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1970(F, sep, ...) \ + Z_UTIL_LISTIFY_1969(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1969, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1971(F, sep, ...) \ + Z_UTIL_LISTIFY_1970(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1970, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1972(F, sep, ...) \ + Z_UTIL_LISTIFY_1971(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1971, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1973(F, sep, ...) \ + Z_UTIL_LISTIFY_1972(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1972, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1974(F, sep, ...) \ + Z_UTIL_LISTIFY_1973(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1973, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1975(F, sep, ...) \ + Z_UTIL_LISTIFY_1974(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1974, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1976(F, sep, ...) \ + Z_UTIL_LISTIFY_1975(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1975, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1977(F, sep, ...) \ + Z_UTIL_LISTIFY_1976(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1976, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1978(F, sep, ...) \ + Z_UTIL_LISTIFY_1977(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1977, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1979(F, sep, ...) \ + Z_UTIL_LISTIFY_1978(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1978, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1980(F, sep, ...) \ + Z_UTIL_LISTIFY_1979(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1979, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1981(F, sep, ...) \ + Z_UTIL_LISTIFY_1980(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1980, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1982(F, sep, ...) \ + Z_UTIL_LISTIFY_1981(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1981, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1983(F, sep, ...) \ + Z_UTIL_LISTIFY_1982(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1982, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1984(F, sep, ...) \ + Z_UTIL_LISTIFY_1983(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1983, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1985(F, sep, ...) \ + Z_UTIL_LISTIFY_1984(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1984, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1986(F, sep, ...) \ + Z_UTIL_LISTIFY_1985(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1985, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1987(F, sep, ...) \ + Z_UTIL_LISTIFY_1986(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1986, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1988(F, sep, ...) \ + Z_UTIL_LISTIFY_1987(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1987, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1989(F, sep, ...) \ + Z_UTIL_LISTIFY_1988(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1988, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1990(F, sep, ...) \ + Z_UTIL_LISTIFY_1989(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1989, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1991(F, sep, ...) \ + Z_UTIL_LISTIFY_1990(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1990, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1992(F, sep, ...) \ + Z_UTIL_LISTIFY_1991(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1991, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1993(F, sep, ...) \ + Z_UTIL_LISTIFY_1992(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1992, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1994(F, sep, ...) \ + Z_UTIL_LISTIFY_1993(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1993, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1995(F, sep, ...) \ + Z_UTIL_LISTIFY_1994(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1994, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1996(F, sep, ...) \ + Z_UTIL_LISTIFY_1995(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1995, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1997(F, sep, ...) \ + Z_UTIL_LISTIFY_1996(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1996, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1998(F, sep, ...) \ + Z_UTIL_LISTIFY_1997(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1997, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_1999(F, sep, ...) \ + Z_UTIL_LISTIFY_1998(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1998, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2000(F, sep, ...) \ + Z_UTIL_LISTIFY_1999(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1999, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2001(F, sep, ...) \ + Z_UTIL_LISTIFY_2000(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2000, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2002(F, sep, ...) \ + Z_UTIL_LISTIFY_2001(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2001, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2003(F, sep, ...) \ + Z_UTIL_LISTIFY_2002(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2002, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2004(F, sep, ...) \ + Z_UTIL_LISTIFY_2003(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2003, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2005(F, sep, ...) \ + Z_UTIL_LISTIFY_2004(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2004, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2006(F, sep, ...) \ + Z_UTIL_LISTIFY_2005(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2005, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2007(F, sep, ...) \ + Z_UTIL_LISTIFY_2006(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2006, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2008(F, sep, ...) \ + Z_UTIL_LISTIFY_2007(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2007, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2009(F, sep, ...) \ + Z_UTIL_LISTIFY_2008(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2008, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2010(F, sep, ...) \ + Z_UTIL_LISTIFY_2009(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2009, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2011(F, sep, ...) \ + Z_UTIL_LISTIFY_2010(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2010, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2012(F, sep, ...) \ + Z_UTIL_LISTIFY_2011(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2011, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2013(F, sep, ...) \ + Z_UTIL_LISTIFY_2012(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2012, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2014(F, sep, ...) \ + Z_UTIL_LISTIFY_2013(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2013, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2015(F, sep, ...) \ + Z_UTIL_LISTIFY_2014(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2014, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2016(F, sep, ...) \ + Z_UTIL_LISTIFY_2015(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2015, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2017(F, sep, ...) \ + Z_UTIL_LISTIFY_2016(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2016, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2018(F, sep, ...) \ + Z_UTIL_LISTIFY_2017(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2017, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2019(F, sep, ...) \ + Z_UTIL_LISTIFY_2018(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2018, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2020(F, sep, ...) \ + Z_UTIL_LISTIFY_2019(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2019, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2021(F, sep, ...) \ + Z_UTIL_LISTIFY_2020(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2020, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2022(F, sep, ...) \ + Z_UTIL_LISTIFY_2021(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2021, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2023(F, sep, ...) \ + Z_UTIL_LISTIFY_2022(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2022, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2024(F, sep, ...) \ + Z_UTIL_LISTIFY_2023(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2023, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2025(F, sep, ...) \ + Z_UTIL_LISTIFY_2024(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2024, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2026(F, sep, ...) \ + Z_UTIL_LISTIFY_2025(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2025, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2027(F, sep, ...) \ + Z_UTIL_LISTIFY_2026(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2026, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2028(F, sep, ...) \ + Z_UTIL_LISTIFY_2027(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2027, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2029(F, sep, ...) \ + Z_UTIL_LISTIFY_2028(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2028, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2030(F, sep, ...) \ + Z_UTIL_LISTIFY_2029(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2029, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2031(F, sep, ...) \ + Z_UTIL_LISTIFY_2030(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2030, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2032(F, sep, ...) \ + Z_UTIL_LISTIFY_2031(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2031, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2033(F, sep, ...) \ + Z_UTIL_LISTIFY_2032(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2032, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2034(F, sep, ...) \ + Z_UTIL_LISTIFY_2033(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2033, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2035(F, sep, ...) \ + Z_UTIL_LISTIFY_2034(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2034, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2036(F, sep, ...) \ + Z_UTIL_LISTIFY_2035(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2035, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2037(F, sep, ...) \ + Z_UTIL_LISTIFY_2036(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2036, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2038(F, sep, ...) \ + Z_UTIL_LISTIFY_2037(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2037, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2039(F, sep, ...) \ + Z_UTIL_LISTIFY_2038(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2038, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2040(F, sep, ...) \ + Z_UTIL_LISTIFY_2039(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2039, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2041(F, sep, ...) \ + Z_UTIL_LISTIFY_2040(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2040, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2042(F, sep, ...) \ + Z_UTIL_LISTIFY_2041(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2041, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2043(F, sep, ...) \ + Z_UTIL_LISTIFY_2042(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2042, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2044(F, sep, ...) \ + Z_UTIL_LISTIFY_2043(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2043, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2045(F, sep, ...) \ + Z_UTIL_LISTIFY_2044(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2044, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2046(F, sep, ...) \ + Z_UTIL_LISTIFY_2045(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2045, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2047(F, sep, ...) \ + Z_UTIL_LISTIFY_2046(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2046, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2048(F, sep, ...) \ + Z_UTIL_LISTIFY_2047(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2047, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2049(F, sep, ...) \ + Z_UTIL_LISTIFY_2048(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2048, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2050(F, sep, ...) \ + Z_UTIL_LISTIFY_2049(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2049, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2051(F, sep, ...) \ + Z_UTIL_LISTIFY_2050(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2050, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2052(F, sep, ...) \ + Z_UTIL_LISTIFY_2051(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2051, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2053(F, sep, ...) \ + Z_UTIL_LISTIFY_2052(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2052, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2054(F, sep, ...) \ + Z_UTIL_LISTIFY_2053(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2053, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2055(F, sep, ...) \ + Z_UTIL_LISTIFY_2054(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2054, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2056(F, sep, ...) \ + Z_UTIL_LISTIFY_2055(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2055, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2057(F, sep, ...) \ + Z_UTIL_LISTIFY_2056(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2056, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2058(F, sep, ...) \ + Z_UTIL_LISTIFY_2057(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2057, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2059(F, sep, ...) \ + Z_UTIL_LISTIFY_2058(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2058, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2060(F, sep, ...) \ + Z_UTIL_LISTIFY_2059(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2059, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2061(F, sep, ...) \ + Z_UTIL_LISTIFY_2060(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2060, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2062(F, sep, ...) \ + Z_UTIL_LISTIFY_2061(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2061, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2063(F, sep, ...) \ + Z_UTIL_LISTIFY_2062(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2062, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2064(F, sep, ...) \ + Z_UTIL_LISTIFY_2063(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2063, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2065(F, sep, ...) \ + Z_UTIL_LISTIFY_2064(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2064, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2066(F, sep, ...) \ + Z_UTIL_LISTIFY_2065(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2065, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2067(F, sep, ...) \ + Z_UTIL_LISTIFY_2066(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2066, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2068(F, sep, ...) \ + Z_UTIL_LISTIFY_2067(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2067, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2069(F, sep, ...) \ + Z_UTIL_LISTIFY_2068(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2068, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2070(F, sep, ...) \ + Z_UTIL_LISTIFY_2069(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2069, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2071(F, sep, ...) \ + Z_UTIL_LISTIFY_2070(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2070, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2072(F, sep, ...) \ + Z_UTIL_LISTIFY_2071(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2071, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2073(F, sep, ...) \ + Z_UTIL_LISTIFY_2072(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2072, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2074(F, sep, ...) \ + Z_UTIL_LISTIFY_2073(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2073, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2075(F, sep, ...) \ + Z_UTIL_LISTIFY_2074(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2074, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2076(F, sep, ...) \ + Z_UTIL_LISTIFY_2075(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2075, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2077(F, sep, ...) \ + Z_UTIL_LISTIFY_2076(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2076, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2078(F, sep, ...) \ + Z_UTIL_LISTIFY_2077(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2077, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2079(F, sep, ...) \ + Z_UTIL_LISTIFY_2078(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2078, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2080(F, sep, ...) \ + Z_UTIL_LISTIFY_2079(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2079, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2081(F, sep, ...) \ + Z_UTIL_LISTIFY_2080(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2080, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2082(F, sep, ...) \ + Z_UTIL_LISTIFY_2081(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2081, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2083(F, sep, ...) \ + Z_UTIL_LISTIFY_2082(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2082, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2084(F, sep, ...) \ + Z_UTIL_LISTIFY_2083(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2083, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2085(F, sep, ...) \ + Z_UTIL_LISTIFY_2084(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2084, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2086(F, sep, ...) \ + Z_UTIL_LISTIFY_2085(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2085, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2087(F, sep, ...) \ + Z_UTIL_LISTIFY_2086(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2086, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2088(F, sep, ...) \ + Z_UTIL_LISTIFY_2087(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2087, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2089(F, sep, ...) \ + Z_UTIL_LISTIFY_2088(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2088, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2090(F, sep, ...) \ + Z_UTIL_LISTIFY_2089(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2089, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2091(F, sep, ...) \ + Z_UTIL_LISTIFY_2090(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2090, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2092(F, sep, ...) \ + Z_UTIL_LISTIFY_2091(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2091, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2093(F, sep, ...) \ + Z_UTIL_LISTIFY_2092(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2092, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2094(F, sep, ...) \ + Z_UTIL_LISTIFY_2093(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2093, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2095(F, sep, ...) \ + Z_UTIL_LISTIFY_2094(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2094, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2096(F, sep, ...) \ + Z_UTIL_LISTIFY_2095(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2095, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2097(F, sep, ...) \ + Z_UTIL_LISTIFY_2096(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2096, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2098(F, sep, ...) \ + Z_UTIL_LISTIFY_2097(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2097, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2099(F, sep, ...) \ + Z_UTIL_LISTIFY_2098(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2098, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2100(F, sep, ...) \ + Z_UTIL_LISTIFY_2099(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2099, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2101(F, sep, ...) \ + Z_UTIL_LISTIFY_2100(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2100, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2102(F, sep, ...) \ + Z_UTIL_LISTIFY_2101(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2101, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2103(F, sep, ...) \ + Z_UTIL_LISTIFY_2102(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2102, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2104(F, sep, ...) \ + Z_UTIL_LISTIFY_2103(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2103, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2105(F, sep, ...) \ + Z_UTIL_LISTIFY_2104(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2104, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2106(F, sep, ...) \ + Z_UTIL_LISTIFY_2105(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2105, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2107(F, sep, ...) \ + Z_UTIL_LISTIFY_2106(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2106, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2108(F, sep, ...) \ + Z_UTIL_LISTIFY_2107(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2107, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2109(F, sep, ...) \ + Z_UTIL_LISTIFY_2108(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2108, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2110(F, sep, ...) \ + Z_UTIL_LISTIFY_2109(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2109, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2111(F, sep, ...) \ + Z_UTIL_LISTIFY_2110(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2110, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2112(F, sep, ...) \ + Z_UTIL_LISTIFY_2111(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2111, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2113(F, sep, ...) \ + Z_UTIL_LISTIFY_2112(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2112, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2114(F, sep, ...) \ + Z_UTIL_LISTIFY_2113(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2113, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2115(F, sep, ...) \ + Z_UTIL_LISTIFY_2114(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2114, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2116(F, sep, ...) \ + Z_UTIL_LISTIFY_2115(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2115, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2117(F, sep, ...) \ + Z_UTIL_LISTIFY_2116(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2116, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2118(F, sep, ...) \ + Z_UTIL_LISTIFY_2117(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2117, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2119(F, sep, ...) \ + Z_UTIL_LISTIFY_2118(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2118, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2120(F, sep, ...) \ + Z_UTIL_LISTIFY_2119(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2119, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2121(F, sep, ...) \ + Z_UTIL_LISTIFY_2120(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2120, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2122(F, sep, ...) \ + Z_UTIL_LISTIFY_2121(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2121, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2123(F, sep, ...) \ + Z_UTIL_LISTIFY_2122(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2122, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2124(F, sep, ...) \ + Z_UTIL_LISTIFY_2123(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2123, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2125(F, sep, ...) \ + Z_UTIL_LISTIFY_2124(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2124, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2126(F, sep, ...) \ + Z_UTIL_LISTIFY_2125(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2125, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2127(F, sep, ...) \ + Z_UTIL_LISTIFY_2126(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2126, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2128(F, sep, ...) \ + Z_UTIL_LISTIFY_2127(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2127, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2129(F, sep, ...) \ + Z_UTIL_LISTIFY_2128(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2128, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2130(F, sep, ...) \ + Z_UTIL_LISTIFY_2129(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2129, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2131(F, sep, ...) \ + Z_UTIL_LISTIFY_2130(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2130, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2132(F, sep, ...) \ + Z_UTIL_LISTIFY_2131(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2131, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2133(F, sep, ...) \ + Z_UTIL_LISTIFY_2132(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2132, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2134(F, sep, ...) \ + Z_UTIL_LISTIFY_2133(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2133, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2135(F, sep, ...) \ + Z_UTIL_LISTIFY_2134(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2134, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2136(F, sep, ...) \ + Z_UTIL_LISTIFY_2135(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2135, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2137(F, sep, ...) \ + Z_UTIL_LISTIFY_2136(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2136, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2138(F, sep, ...) \ + Z_UTIL_LISTIFY_2137(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2137, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2139(F, sep, ...) \ + Z_UTIL_LISTIFY_2138(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2138, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2140(F, sep, ...) \ + Z_UTIL_LISTIFY_2139(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2139, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2141(F, sep, ...) \ + Z_UTIL_LISTIFY_2140(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2140, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2142(F, sep, ...) \ + Z_UTIL_LISTIFY_2141(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2141, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2143(F, sep, ...) \ + Z_UTIL_LISTIFY_2142(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2142, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2144(F, sep, ...) \ + Z_UTIL_LISTIFY_2143(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2143, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2145(F, sep, ...) \ + Z_UTIL_LISTIFY_2144(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2144, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2146(F, sep, ...) \ + Z_UTIL_LISTIFY_2145(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2145, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2147(F, sep, ...) \ + Z_UTIL_LISTIFY_2146(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2146, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2148(F, sep, ...) \ + Z_UTIL_LISTIFY_2147(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2147, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2149(F, sep, ...) \ + Z_UTIL_LISTIFY_2148(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2148, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2150(F, sep, ...) \ + Z_UTIL_LISTIFY_2149(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2149, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2151(F, sep, ...) \ + Z_UTIL_LISTIFY_2150(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2150, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2152(F, sep, ...) \ + Z_UTIL_LISTIFY_2151(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2151, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2153(F, sep, ...) \ + Z_UTIL_LISTIFY_2152(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2152, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2154(F, sep, ...) \ + Z_UTIL_LISTIFY_2153(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2153, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2155(F, sep, ...) \ + Z_UTIL_LISTIFY_2154(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2154, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2156(F, sep, ...) \ + Z_UTIL_LISTIFY_2155(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2155, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2157(F, sep, ...) \ + Z_UTIL_LISTIFY_2156(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2156, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2158(F, sep, ...) \ + Z_UTIL_LISTIFY_2157(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2157, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2159(F, sep, ...) \ + Z_UTIL_LISTIFY_2158(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2158, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2160(F, sep, ...) \ + Z_UTIL_LISTIFY_2159(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2159, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2161(F, sep, ...) \ + Z_UTIL_LISTIFY_2160(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2160, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2162(F, sep, ...) \ + Z_UTIL_LISTIFY_2161(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2161, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2163(F, sep, ...) \ + Z_UTIL_LISTIFY_2162(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2162, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2164(F, sep, ...) \ + Z_UTIL_LISTIFY_2163(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2163, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2165(F, sep, ...) \ + Z_UTIL_LISTIFY_2164(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2164, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2166(F, sep, ...) \ + Z_UTIL_LISTIFY_2165(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2165, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2167(F, sep, ...) \ + Z_UTIL_LISTIFY_2166(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2166, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2168(F, sep, ...) \ + Z_UTIL_LISTIFY_2167(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2167, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2169(F, sep, ...) \ + Z_UTIL_LISTIFY_2168(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2168, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2170(F, sep, ...) \ + Z_UTIL_LISTIFY_2169(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2169, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2171(F, sep, ...) \ + Z_UTIL_LISTIFY_2170(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2170, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2172(F, sep, ...) \ + Z_UTIL_LISTIFY_2171(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2171, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2173(F, sep, ...) \ + Z_UTIL_LISTIFY_2172(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2172, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2174(F, sep, ...) \ + Z_UTIL_LISTIFY_2173(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2173, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2175(F, sep, ...) \ + Z_UTIL_LISTIFY_2174(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2174, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2176(F, sep, ...) \ + Z_UTIL_LISTIFY_2175(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2175, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2177(F, sep, ...) \ + Z_UTIL_LISTIFY_2176(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2176, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2178(F, sep, ...) \ + Z_UTIL_LISTIFY_2177(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2177, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2179(F, sep, ...) \ + Z_UTIL_LISTIFY_2178(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2178, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2180(F, sep, ...) \ + Z_UTIL_LISTIFY_2179(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2179, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2181(F, sep, ...) \ + Z_UTIL_LISTIFY_2180(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2180, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2182(F, sep, ...) \ + Z_UTIL_LISTIFY_2181(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2181, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2183(F, sep, ...) \ + Z_UTIL_LISTIFY_2182(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2182, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2184(F, sep, ...) \ + Z_UTIL_LISTIFY_2183(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2183, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2185(F, sep, ...) \ + Z_UTIL_LISTIFY_2184(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2184, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2186(F, sep, ...) \ + Z_UTIL_LISTIFY_2185(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2185, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2187(F, sep, ...) \ + Z_UTIL_LISTIFY_2186(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2186, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2188(F, sep, ...) \ + Z_UTIL_LISTIFY_2187(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2187, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2189(F, sep, ...) \ + Z_UTIL_LISTIFY_2188(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2188, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2190(F, sep, ...) \ + Z_UTIL_LISTIFY_2189(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2189, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2191(F, sep, ...) \ + Z_UTIL_LISTIFY_2190(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2190, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2192(F, sep, ...) \ + Z_UTIL_LISTIFY_2191(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2191, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2193(F, sep, ...) \ + Z_UTIL_LISTIFY_2192(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2192, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2194(F, sep, ...) \ + Z_UTIL_LISTIFY_2193(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2193, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2195(F, sep, ...) \ + Z_UTIL_LISTIFY_2194(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2194, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2196(F, sep, ...) \ + Z_UTIL_LISTIFY_2195(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2195, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2197(F, sep, ...) \ + Z_UTIL_LISTIFY_2196(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2196, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2198(F, sep, ...) \ + Z_UTIL_LISTIFY_2197(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2197, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2199(F, sep, ...) \ + Z_UTIL_LISTIFY_2198(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2198, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2200(F, sep, ...) \ + Z_UTIL_LISTIFY_2199(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2199, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2201(F, sep, ...) \ + Z_UTIL_LISTIFY_2200(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2200, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2202(F, sep, ...) \ + Z_UTIL_LISTIFY_2201(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2201, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2203(F, sep, ...) \ + Z_UTIL_LISTIFY_2202(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2202, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2204(F, sep, ...) \ + Z_UTIL_LISTIFY_2203(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2203, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2205(F, sep, ...) \ + Z_UTIL_LISTIFY_2204(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2204, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2206(F, sep, ...) \ + Z_UTIL_LISTIFY_2205(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2205, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2207(F, sep, ...) \ + Z_UTIL_LISTIFY_2206(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2206, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2208(F, sep, ...) \ + Z_UTIL_LISTIFY_2207(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2207, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2209(F, sep, ...) \ + Z_UTIL_LISTIFY_2208(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2208, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2210(F, sep, ...) \ + Z_UTIL_LISTIFY_2209(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2209, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2211(F, sep, ...) \ + Z_UTIL_LISTIFY_2210(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2210, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2212(F, sep, ...) \ + Z_UTIL_LISTIFY_2211(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2211, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2213(F, sep, ...) \ + Z_UTIL_LISTIFY_2212(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2212, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2214(F, sep, ...) \ + Z_UTIL_LISTIFY_2213(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2213, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2215(F, sep, ...) \ + Z_UTIL_LISTIFY_2214(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2214, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2216(F, sep, ...) \ + Z_UTIL_LISTIFY_2215(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2215, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2217(F, sep, ...) \ + Z_UTIL_LISTIFY_2216(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2216, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2218(F, sep, ...) \ + Z_UTIL_LISTIFY_2217(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2217, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2219(F, sep, ...) \ + Z_UTIL_LISTIFY_2218(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2218, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2220(F, sep, ...) \ + Z_UTIL_LISTIFY_2219(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2219, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2221(F, sep, ...) \ + Z_UTIL_LISTIFY_2220(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2220, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2222(F, sep, ...) \ + Z_UTIL_LISTIFY_2221(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2221, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2223(F, sep, ...) \ + Z_UTIL_LISTIFY_2222(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2222, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2224(F, sep, ...) \ + Z_UTIL_LISTIFY_2223(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2223, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2225(F, sep, ...) \ + Z_UTIL_LISTIFY_2224(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2224, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2226(F, sep, ...) \ + Z_UTIL_LISTIFY_2225(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2225, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2227(F, sep, ...) \ + Z_UTIL_LISTIFY_2226(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2226, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2228(F, sep, ...) \ + Z_UTIL_LISTIFY_2227(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2227, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2229(F, sep, ...) \ + Z_UTIL_LISTIFY_2228(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2228, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2230(F, sep, ...) \ + Z_UTIL_LISTIFY_2229(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2229, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2231(F, sep, ...) \ + Z_UTIL_LISTIFY_2230(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2230, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2232(F, sep, ...) \ + Z_UTIL_LISTIFY_2231(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2231, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2233(F, sep, ...) \ + Z_UTIL_LISTIFY_2232(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2232, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2234(F, sep, ...) \ + Z_UTIL_LISTIFY_2233(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2233, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2235(F, sep, ...) \ + Z_UTIL_LISTIFY_2234(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2234, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2236(F, sep, ...) \ + Z_UTIL_LISTIFY_2235(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2235, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2237(F, sep, ...) \ + Z_UTIL_LISTIFY_2236(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2236, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2238(F, sep, ...) \ + Z_UTIL_LISTIFY_2237(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2237, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2239(F, sep, ...) \ + Z_UTIL_LISTIFY_2238(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2238, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2240(F, sep, ...) \ + Z_UTIL_LISTIFY_2239(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2239, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2241(F, sep, ...) \ + Z_UTIL_LISTIFY_2240(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2240, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2242(F, sep, ...) \ + Z_UTIL_LISTIFY_2241(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2241, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2243(F, sep, ...) \ + Z_UTIL_LISTIFY_2242(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2242, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2244(F, sep, ...) \ + Z_UTIL_LISTIFY_2243(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2243, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2245(F, sep, ...) \ + Z_UTIL_LISTIFY_2244(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2244, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2246(F, sep, ...) \ + Z_UTIL_LISTIFY_2245(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2245, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2247(F, sep, ...) \ + Z_UTIL_LISTIFY_2246(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2246, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2248(F, sep, ...) \ + Z_UTIL_LISTIFY_2247(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2247, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2249(F, sep, ...) \ + Z_UTIL_LISTIFY_2248(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2248, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2250(F, sep, ...) \ + Z_UTIL_LISTIFY_2249(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2249, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2251(F, sep, ...) \ + Z_UTIL_LISTIFY_2250(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2250, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2252(F, sep, ...) \ + Z_UTIL_LISTIFY_2251(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2251, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2253(F, sep, ...) \ + Z_UTIL_LISTIFY_2252(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2252, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2254(F, sep, ...) \ + Z_UTIL_LISTIFY_2253(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2253, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2255(F, sep, ...) \ + Z_UTIL_LISTIFY_2254(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2254, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2256(F, sep, ...) \ + Z_UTIL_LISTIFY_2255(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2255, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2257(F, sep, ...) \ + Z_UTIL_LISTIFY_2256(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2256, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2258(F, sep, ...) \ + Z_UTIL_LISTIFY_2257(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2257, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2259(F, sep, ...) \ + Z_UTIL_LISTIFY_2258(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2258, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2260(F, sep, ...) \ + Z_UTIL_LISTIFY_2259(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2259, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2261(F, sep, ...) \ + Z_UTIL_LISTIFY_2260(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2260, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2262(F, sep, ...) \ + Z_UTIL_LISTIFY_2261(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2261, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2263(F, sep, ...) \ + Z_UTIL_LISTIFY_2262(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2262, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2264(F, sep, ...) \ + Z_UTIL_LISTIFY_2263(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2263, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2265(F, sep, ...) \ + Z_UTIL_LISTIFY_2264(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2264, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2266(F, sep, ...) \ + Z_UTIL_LISTIFY_2265(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2265, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2267(F, sep, ...) \ + Z_UTIL_LISTIFY_2266(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2266, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2268(F, sep, ...) \ + Z_UTIL_LISTIFY_2267(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2267, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2269(F, sep, ...) \ + Z_UTIL_LISTIFY_2268(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2268, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2270(F, sep, ...) \ + Z_UTIL_LISTIFY_2269(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2269, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2271(F, sep, ...) \ + Z_UTIL_LISTIFY_2270(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2270, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2272(F, sep, ...) \ + Z_UTIL_LISTIFY_2271(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2271, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2273(F, sep, ...) \ + Z_UTIL_LISTIFY_2272(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2272, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2274(F, sep, ...) \ + Z_UTIL_LISTIFY_2273(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2273, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2275(F, sep, ...) \ + Z_UTIL_LISTIFY_2274(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2274, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2276(F, sep, ...) \ + Z_UTIL_LISTIFY_2275(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2275, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2277(F, sep, ...) \ + Z_UTIL_LISTIFY_2276(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2276, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2278(F, sep, ...) \ + Z_UTIL_LISTIFY_2277(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2277, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2279(F, sep, ...) \ + Z_UTIL_LISTIFY_2278(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2278, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2280(F, sep, ...) \ + Z_UTIL_LISTIFY_2279(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2279, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2281(F, sep, ...) \ + Z_UTIL_LISTIFY_2280(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2280, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2282(F, sep, ...) \ + Z_UTIL_LISTIFY_2281(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2281, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2283(F, sep, ...) \ + Z_UTIL_LISTIFY_2282(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2282, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2284(F, sep, ...) \ + Z_UTIL_LISTIFY_2283(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2283, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2285(F, sep, ...) \ + Z_UTIL_LISTIFY_2284(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2284, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2286(F, sep, ...) \ + Z_UTIL_LISTIFY_2285(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2285, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2287(F, sep, ...) \ + Z_UTIL_LISTIFY_2286(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2286, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2288(F, sep, ...) \ + Z_UTIL_LISTIFY_2287(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2287, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2289(F, sep, ...) \ + Z_UTIL_LISTIFY_2288(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2288, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2290(F, sep, ...) \ + Z_UTIL_LISTIFY_2289(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2289, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2291(F, sep, ...) \ + Z_UTIL_LISTIFY_2290(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2290, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2292(F, sep, ...) \ + Z_UTIL_LISTIFY_2291(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2291, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2293(F, sep, ...) \ + Z_UTIL_LISTIFY_2292(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2292, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2294(F, sep, ...) \ + Z_UTIL_LISTIFY_2293(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2293, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2295(F, sep, ...) \ + Z_UTIL_LISTIFY_2294(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2294, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2296(F, sep, ...) \ + Z_UTIL_LISTIFY_2295(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2295, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2297(F, sep, ...) \ + Z_UTIL_LISTIFY_2296(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2296, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2298(F, sep, ...) \ + Z_UTIL_LISTIFY_2297(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2297, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2299(F, sep, ...) \ + Z_UTIL_LISTIFY_2298(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2298, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2300(F, sep, ...) \ + Z_UTIL_LISTIFY_2299(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2299, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2301(F, sep, ...) \ + Z_UTIL_LISTIFY_2300(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2300, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2302(F, sep, ...) \ + Z_UTIL_LISTIFY_2301(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2301, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2303(F, sep, ...) \ + Z_UTIL_LISTIFY_2302(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2302, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2304(F, sep, ...) \ + Z_UTIL_LISTIFY_2303(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2303, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2305(F, sep, ...) \ + Z_UTIL_LISTIFY_2304(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2304, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2306(F, sep, ...) \ + Z_UTIL_LISTIFY_2305(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2305, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2307(F, sep, ...) \ + Z_UTIL_LISTIFY_2306(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2306, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2308(F, sep, ...) \ + Z_UTIL_LISTIFY_2307(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2307, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2309(F, sep, ...) \ + Z_UTIL_LISTIFY_2308(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2308, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2310(F, sep, ...) \ + Z_UTIL_LISTIFY_2309(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2309, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2311(F, sep, ...) \ + Z_UTIL_LISTIFY_2310(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2310, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2312(F, sep, ...) \ + Z_UTIL_LISTIFY_2311(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2311, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2313(F, sep, ...) \ + Z_UTIL_LISTIFY_2312(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2312, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2314(F, sep, ...) \ + Z_UTIL_LISTIFY_2313(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2313, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2315(F, sep, ...) \ + Z_UTIL_LISTIFY_2314(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2314, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2316(F, sep, ...) \ + Z_UTIL_LISTIFY_2315(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2315, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2317(F, sep, ...) \ + Z_UTIL_LISTIFY_2316(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2316, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2318(F, sep, ...) \ + Z_UTIL_LISTIFY_2317(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2317, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2319(F, sep, ...) \ + Z_UTIL_LISTIFY_2318(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2318, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2320(F, sep, ...) \ + Z_UTIL_LISTIFY_2319(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2319, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2321(F, sep, ...) \ + Z_UTIL_LISTIFY_2320(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2320, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2322(F, sep, ...) \ + Z_UTIL_LISTIFY_2321(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2321, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2323(F, sep, ...) \ + Z_UTIL_LISTIFY_2322(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2322, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2324(F, sep, ...) \ + Z_UTIL_LISTIFY_2323(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2323, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2325(F, sep, ...) \ + Z_UTIL_LISTIFY_2324(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2324, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2326(F, sep, ...) \ + Z_UTIL_LISTIFY_2325(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2325, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2327(F, sep, ...) \ + Z_UTIL_LISTIFY_2326(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2326, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2328(F, sep, ...) \ + Z_UTIL_LISTIFY_2327(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2327, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2329(F, sep, ...) \ + Z_UTIL_LISTIFY_2328(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2328, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2330(F, sep, ...) \ + Z_UTIL_LISTIFY_2329(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2329, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2331(F, sep, ...) \ + Z_UTIL_LISTIFY_2330(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2330, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2332(F, sep, ...) \ + Z_UTIL_LISTIFY_2331(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2331, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2333(F, sep, ...) \ + Z_UTIL_LISTIFY_2332(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2332, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2334(F, sep, ...) \ + Z_UTIL_LISTIFY_2333(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2333, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2335(F, sep, ...) \ + Z_UTIL_LISTIFY_2334(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2334, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2336(F, sep, ...) \ + Z_UTIL_LISTIFY_2335(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2335, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2337(F, sep, ...) \ + Z_UTIL_LISTIFY_2336(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2336, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2338(F, sep, ...) \ + Z_UTIL_LISTIFY_2337(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2337, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2339(F, sep, ...) \ + Z_UTIL_LISTIFY_2338(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2338, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2340(F, sep, ...) \ + Z_UTIL_LISTIFY_2339(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2339, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2341(F, sep, ...) \ + Z_UTIL_LISTIFY_2340(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2340, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2342(F, sep, ...) \ + Z_UTIL_LISTIFY_2341(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2341, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2343(F, sep, ...) \ + Z_UTIL_LISTIFY_2342(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2342, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2344(F, sep, ...) \ + Z_UTIL_LISTIFY_2343(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2343, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2345(F, sep, ...) \ + Z_UTIL_LISTIFY_2344(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2344, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2346(F, sep, ...) \ + Z_UTIL_LISTIFY_2345(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2345, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2347(F, sep, ...) \ + Z_UTIL_LISTIFY_2346(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2346, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2348(F, sep, ...) \ + Z_UTIL_LISTIFY_2347(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2347, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2349(F, sep, ...) \ + Z_UTIL_LISTIFY_2348(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2348, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2350(F, sep, ...) \ + Z_UTIL_LISTIFY_2349(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2349, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2351(F, sep, ...) \ + Z_UTIL_LISTIFY_2350(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2350, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2352(F, sep, ...) \ + Z_UTIL_LISTIFY_2351(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2351, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2353(F, sep, ...) \ + Z_UTIL_LISTIFY_2352(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2352, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2354(F, sep, ...) \ + Z_UTIL_LISTIFY_2353(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2353, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2355(F, sep, ...) \ + Z_UTIL_LISTIFY_2354(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2354, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2356(F, sep, ...) \ + Z_UTIL_LISTIFY_2355(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2355, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2357(F, sep, ...) \ + Z_UTIL_LISTIFY_2356(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2356, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2358(F, sep, ...) \ + Z_UTIL_LISTIFY_2357(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2357, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2359(F, sep, ...) \ + Z_UTIL_LISTIFY_2358(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2358, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2360(F, sep, ...) \ + Z_UTIL_LISTIFY_2359(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2359, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2361(F, sep, ...) \ + Z_UTIL_LISTIFY_2360(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2360, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2362(F, sep, ...) \ + Z_UTIL_LISTIFY_2361(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2361, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2363(F, sep, ...) \ + Z_UTIL_LISTIFY_2362(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2362, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2364(F, sep, ...) \ + Z_UTIL_LISTIFY_2363(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2363, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2365(F, sep, ...) \ + Z_UTIL_LISTIFY_2364(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2364, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2366(F, sep, ...) \ + Z_UTIL_LISTIFY_2365(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2365, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2367(F, sep, ...) \ + Z_UTIL_LISTIFY_2366(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2366, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2368(F, sep, ...) \ + Z_UTIL_LISTIFY_2367(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2367, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2369(F, sep, ...) \ + Z_UTIL_LISTIFY_2368(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2368, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2370(F, sep, ...) \ + Z_UTIL_LISTIFY_2369(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2369, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2371(F, sep, ...) \ + Z_UTIL_LISTIFY_2370(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2370, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2372(F, sep, ...) \ + Z_UTIL_LISTIFY_2371(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2371, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2373(F, sep, ...) \ + Z_UTIL_LISTIFY_2372(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2372, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2374(F, sep, ...) \ + Z_UTIL_LISTIFY_2373(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2373, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2375(F, sep, ...) \ + Z_UTIL_LISTIFY_2374(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2374, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2376(F, sep, ...) \ + Z_UTIL_LISTIFY_2375(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2375, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2377(F, sep, ...) \ + Z_UTIL_LISTIFY_2376(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2376, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2378(F, sep, ...) \ + Z_UTIL_LISTIFY_2377(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2377, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2379(F, sep, ...) \ + Z_UTIL_LISTIFY_2378(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2378, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2380(F, sep, ...) \ + Z_UTIL_LISTIFY_2379(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2379, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2381(F, sep, ...) \ + Z_UTIL_LISTIFY_2380(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2380, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2382(F, sep, ...) \ + Z_UTIL_LISTIFY_2381(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2381, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2383(F, sep, ...) \ + Z_UTIL_LISTIFY_2382(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2382, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2384(F, sep, ...) \ + Z_UTIL_LISTIFY_2383(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2383, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2385(F, sep, ...) \ + Z_UTIL_LISTIFY_2384(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2384, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2386(F, sep, ...) \ + Z_UTIL_LISTIFY_2385(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2385, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2387(F, sep, ...) \ + Z_UTIL_LISTIFY_2386(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2386, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2388(F, sep, ...) \ + Z_UTIL_LISTIFY_2387(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2387, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2389(F, sep, ...) \ + Z_UTIL_LISTIFY_2388(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2388, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2390(F, sep, ...) \ + Z_UTIL_LISTIFY_2389(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2389, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2391(F, sep, ...) \ + Z_UTIL_LISTIFY_2390(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2390, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2392(F, sep, ...) \ + Z_UTIL_LISTIFY_2391(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2391, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2393(F, sep, ...) \ + Z_UTIL_LISTIFY_2392(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2392, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2394(F, sep, ...) \ + Z_UTIL_LISTIFY_2393(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2393, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2395(F, sep, ...) \ + Z_UTIL_LISTIFY_2394(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2394, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2396(F, sep, ...) \ + Z_UTIL_LISTIFY_2395(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2395, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2397(F, sep, ...) \ + Z_UTIL_LISTIFY_2396(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2396, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2398(F, sep, ...) \ + Z_UTIL_LISTIFY_2397(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2397, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2399(F, sep, ...) \ + Z_UTIL_LISTIFY_2398(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2398, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2400(F, sep, ...) \ + Z_UTIL_LISTIFY_2399(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2399, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2401(F, sep, ...) \ + Z_UTIL_LISTIFY_2400(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2400, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2402(F, sep, ...) \ + Z_UTIL_LISTIFY_2401(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2401, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2403(F, sep, ...) \ + Z_UTIL_LISTIFY_2402(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2402, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2404(F, sep, ...) \ + Z_UTIL_LISTIFY_2403(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2403, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2405(F, sep, ...) \ + Z_UTIL_LISTIFY_2404(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2404, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2406(F, sep, ...) \ + Z_UTIL_LISTIFY_2405(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2405, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2407(F, sep, ...) \ + Z_UTIL_LISTIFY_2406(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2406, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2408(F, sep, ...) \ + Z_UTIL_LISTIFY_2407(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2407, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2409(F, sep, ...) \ + Z_UTIL_LISTIFY_2408(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2408, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2410(F, sep, ...) \ + Z_UTIL_LISTIFY_2409(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2409, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2411(F, sep, ...) \ + Z_UTIL_LISTIFY_2410(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2410, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2412(F, sep, ...) \ + Z_UTIL_LISTIFY_2411(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2411, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2413(F, sep, ...) \ + Z_UTIL_LISTIFY_2412(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2412, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2414(F, sep, ...) \ + Z_UTIL_LISTIFY_2413(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2413, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2415(F, sep, ...) \ + Z_UTIL_LISTIFY_2414(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2414, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2416(F, sep, ...) \ + Z_UTIL_LISTIFY_2415(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2415, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2417(F, sep, ...) \ + Z_UTIL_LISTIFY_2416(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2416, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2418(F, sep, ...) \ + Z_UTIL_LISTIFY_2417(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2417, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2419(F, sep, ...) \ + Z_UTIL_LISTIFY_2418(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2418, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2420(F, sep, ...) \ + Z_UTIL_LISTIFY_2419(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2419, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2421(F, sep, ...) \ + Z_UTIL_LISTIFY_2420(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2420, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2422(F, sep, ...) \ + Z_UTIL_LISTIFY_2421(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2421, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2423(F, sep, ...) \ + Z_UTIL_LISTIFY_2422(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2422, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2424(F, sep, ...) \ + Z_UTIL_LISTIFY_2423(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2423, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2425(F, sep, ...) \ + Z_UTIL_LISTIFY_2424(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2424, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2426(F, sep, ...) \ + Z_UTIL_LISTIFY_2425(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2425, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2427(F, sep, ...) \ + Z_UTIL_LISTIFY_2426(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2426, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2428(F, sep, ...) \ + Z_UTIL_LISTIFY_2427(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2427, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2429(F, sep, ...) \ + Z_UTIL_LISTIFY_2428(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2428, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2430(F, sep, ...) \ + Z_UTIL_LISTIFY_2429(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2429, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2431(F, sep, ...) \ + Z_UTIL_LISTIFY_2430(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2430, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2432(F, sep, ...) \ + Z_UTIL_LISTIFY_2431(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2431, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2433(F, sep, ...) \ + Z_UTIL_LISTIFY_2432(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2432, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2434(F, sep, ...) \ + Z_UTIL_LISTIFY_2433(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2433, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2435(F, sep, ...) \ + Z_UTIL_LISTIFY_2434(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2434, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2436(F, sep, ...) \ + Z_UTIL_LISTIFY_2435(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2435, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2437(F, sep, ...) \ + Z_UTIL_LISTIFY_2436(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2436, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2438(F, sep, ...) \ + Z_UTIL_LISTIFY_2437(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2437, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2439(F, sep, ...) \ + Z_UTIL_LISTIFY_2438(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2438, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2440(F, sep, ...) \ + Z_UTIL_LISTIFY_2439(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2439, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2441(F, sep, ...) \ + Z_UTIL_LISTIFY_2440(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2440, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2442(F, sep, ...) \ + Z_UTIL_LISTIFY_2441(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2441, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2443(F, sep, ...) \ + Z_UTIL_LISTIFY_2442(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2442, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2444(F, sep, ...) \ + Z_UTIL_LISTIFY_2443(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2443, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2445(F, sep, ...) \ + Z_UTIL_LISTIFY_2444(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2444, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2446(F, sep, ...) \ + Z_UTIL_LISTIFY_2445(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2445, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2447(F, sep, ...) \ + Z_UTIL_LISTIFY_2446(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2446, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2448(F, sep, ...) \ + Z_UTIL_LISTIFY_2447(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2447, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2449(F, sep, ...) \ + Z_UTIL_LISTIFY_2448(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2448, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2450(F, sep, ...) \ + Z_UTIL_LISTIFY_2449(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2449, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2451(F, sep, ...) \ + Z_UTIL_LISTIFY_2450(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2450, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2452(F, sep, ...) \ + Z_UTIL_LISTIFY_2451(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2451, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2453(F, sep, ...) \ + Z_UTIL_LISTIFY_2452(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2452, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2454(F, sep, ...) \ + Z_UTIL_LISTIFY_2453(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2453, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2455(F, sep, ...) \ + Z_UTIL_LISTIFY_2454(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2454, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2456(F, sep, ...) \ + Z_UTIL_LISTIFY_2455(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2455, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2457(F, sep, ...) \ + Z_UTIL_LISTIFY_2456(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2456, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2458(F, sep, ...) \ + Z_UTIL_LISTIFY_2457(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2457, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2459(F, sep, ...) \ + Z_UTIL_LISTIFY_2458(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2458, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2460(F, sep, ...) \ + Z_UTIL_LISTIFY_2459(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2459, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2461(F, sep, ...) \ + Z_UTIL_LISTIFY_2460(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2460, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2462(F, sep, ...) \ + Z_UTIL_LISTIFY_2461(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2461, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2463(F, sep, ...) \ + Z_UTIL_LISTIFY_2462(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2462, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2464(F, sep, ...) \ + Z_UTIL_LISTIFY_2463(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2463, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2465(F, sep, ...) \ + Z_UTIL_LISTIFY_2464(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2464, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2466(F, sep, ...) \ + Z_UTIL_LISTIFY_2465(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2465, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2467(F, sep, ...) \ + Z_UTIL_LISTIFY_2466(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2466, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2468(F, sep, ...) \ + Z_UTIL_LISTIFY_2467(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2467, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2469(F, sep, ...) \ + Z_UTIL_LISTIFY_2468(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2468, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2470(F, sep, ...) \ + Z_UTIL_LISTIFY_2469(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2469, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2471(F, sep, ...) \ + Z_UTIL_LISTIFY_2470(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2470, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2472(F, sep, ...) \ + Z_UTIL_LISTIFY_2471(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2471, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2473(F, sep, ...) \ + Z_UTIL_LISTIFY_2472(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2472, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2474(F, sep, ...) \ + Z_UTIL_LISTIFY_2473(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2473, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2475(F, sep, ...) \ + Z_UTIL_LISTIFY_2474(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2474, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2476(F, sep, ...) \ + Z_UTIL_LISTIFY_2475(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2475, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2477(F, sep, ...) \ + Z_UTIL_LISTIFY_2476(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2476, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2478(F, sep, ...) \ + Z_UTIL_LISTIFY_2477(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2477, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2479(F, sep, ...) \ + Z_UTIL_LISTIFY_2478(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2478, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2480(F, sep, ...) \ + Z_UTIL_LISTIFY_2479(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2479, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2481(F, sep, ...) \ + Z_UTIL_LISTIFY_2480(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2480, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2482(F, sep, ...) \ + Z_UTIL_LISTIFY_2481(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2481, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2483(F, sep, ...) \ + Z_UTIL_LISTIFY_2482(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2482, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2484(F, sep, ...) \ + Z_UTIL_LISTIFY_2483(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2483, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2485(F, sep, ...) \ + Z_UTIL_LISTIFY_2484(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2484, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2486(F, sep, ...) \ + Z_UTIL_LISTIFY_2485(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2485, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2487(F, sep, ...) \ + Z_UTIL_LISTIFY_2486(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2486, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2488(F, sep, ...) \ + Z_UTIL_LISTIFY_2487(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2487, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2489(F, sep, ...) \ + Z_UTIL_LISTIFY_2488(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2488, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2490(F, sep, ...) \ + Z_UTIL_LISTIFY_2489(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2489, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2491(F, sep, ...) \ + Z_UTIL_LISTIFY_2490(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2490, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2492(F, sep, ...) \ + Z_UTIL_LISTIFY_2491(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2491, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2493(F, sep, ...) \ + Z_UTIL_LISTIFY_2492(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2492, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2494(F, sep, ...) \ + Z_UTIL_LISTIFY_2493(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2493, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2495(F, sep, ...) \ + Z_UTIL_LISTIFY_2494(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2494, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2496(F, sep, ...) \ + Z_UTIL_LISTIFY_2495(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2495, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2497(F, sep, ...) \ + Z_UTIL_LISTIFY_2496(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2496, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2498(F, sep, ...) \ + Z_UTIL_LISTIFY_2497(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2497, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2499(F, sep, ...) \ + Z_UTIL_LISTIFY_2498(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2498, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2500(F, sep, ...) \ + Z_UTIL_LISTIFY_2499(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2499, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2501(F, sep, ...) \ + Z_UTIL_LISTIFY_2500(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2500, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2502(F, sep, ...) \ + Z_UTIL_LISTIFY_2501(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2501, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2503(F, sep, ...) \ + Z_UTIL_LISTIFY_2502(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2502, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2504(F, sep, ...) \ + Z_UTIL_LISTIFY_2503(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2503, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2505(F, sep, ...) \ + Z_UTIL_LISTIFY_2504(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2504, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2506(F, sep, ...) \ + Z_UTIL_LISTIFY_2505(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2505, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2507(F, sep, ...) \ + Z_UTIL_LISTIFY_2506(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2506, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2508(F, sep, ...) \ + Z_UTIL_LISTIFY_2507(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2507, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2509(F, sep, ...) \ + Z_UTIL_LISTIFY_2508(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2508, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2510(F, sep, ...) \ + Z_UTIL_LISTIFY_2509(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2509, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2511(F, sep, ...) \ + Z_UTIL_LISTIFY_2510(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2510, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2512(F, sep, ...) \ + Z_UTIL_LISTIFY_2511(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2511, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2513(F, sep, ...) \ + Z_UTIL_LISTIFY_2512(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2512, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2514(F, sep, ...) \ + Z_UTIL_LISTIFY_2513(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2513, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2515(F, sep, ...) \ + Z_UTIL_LISTIFY_2514(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2514, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2516(F, sep, ...) \ + Z_UTIL_LISTIFY_2515(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2515, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2517(F, sep, ...) \ + Z_UTIL_LISTIFY_2516(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2516, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2518(F, sep, ...) \ + Z_UTIL_LISTIFY_2517(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2517, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2519(F, sep, ...) \ + Z_UTIL_LISTIFY_2518(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2518, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2520(F, sep, ...) \ + Z_UTIL_LISTIFY_2519(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2519, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2521(F, sep, ...) \ + Z_UTIL_LISTIFY_2520(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2520, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2522(F, sep, ...) \ + Z_UTIL_LISTIFY_2521(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2521, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2523(F, sep, ...) \ + Z_UTIL_LISTIFY_2522(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2522, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2524(F, sep, ...) \ + Z_UTIL_LISTIFY_2523(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2523, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2525(F, sep, ...) \ + Z_UTIL_LISTIFY_2524(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2524, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2526(F, sep, ...) \ + Z_UTIL_LISTIFY_2525(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2525, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2527(F, sep, ...) \ + Z_UTIL_LISTIFY_2526(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2526, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2528(F, sep, ...) \ + Z_UTIL_LISTIFY_2527(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2527, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2529(F, sep, ...) \ + Z_UTIL_LISTIFY_2528(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2528, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2530(F, sep, ...) \ + Z_UTIL_LISTIFY_2529(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2529, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2531(F, sep, ...) \ + Z_UTIL_LISTIFY_2530(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2530, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2532(F, sep, ...) \ + Z_UTIL_LISTIFY_2531(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2531, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2533(F, sep, ...) \ + Z_UTIL_LISTIFY_2532(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2532, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2534(F, sep, ...) \ + Z_UTIL_LISTIFY_2533(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2533, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2535(F, sep, ...) \ + Z_UTIL_LISTIFY_2534(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2534, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2536(F, sep, ...) \ + Z_UTIL_LISTIFY_2535(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2535, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2537(F, sep, ...) \ + Z_UTIL_LISTIFY_2536(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2536, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2538(F, sep, ...) \ + Z_UTIL_LISTIFY_2537(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2537, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2539(F, sep, ...) \ + Z_UTIL_LISTIFY_2538(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2538, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2540(F, sep, ...) \ + Z_UTIL_LISTIFY_2539(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2539, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2541(F, sep, ...) \ + Z_UTIL_LISTIFY_2540(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2540, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2542(F, sep, ...) \ + Z_UTIL_LISTIFY_2541(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2541, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2543(F, sep, ...) \ + Z_UTIL_LISTIFY_2542(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2542, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2544(F, sep, ...) \ + Z_UTIL_LISTIFY_2543(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2543, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2545(F, sep, ...) \ + Z_UTIL_LISTIFY_2544(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2544, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2546(F, sep, ...) \ + Z_UTIL_LISTIFY_2545(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2545, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2547(F, sep, ...) \ + Z_UTIL_LISTIFY_2546(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2546, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2548(F, sep, ...) \ + Z_UTIL_LISTIFY_2547(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2547, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2549(F, sep, ...) \ + Z_UTIL_LISTIFY_2548(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2548, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2550(F, sep, ...) \ + Z_UTIL_LISTIFY_2549(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2549, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2551(F, sep, ...) \ + Z_UTIL_LISTIFY_2550(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2550, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2552(F, sep, ...) \ + Z_UTIL_LISTIFY_2551(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2551, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2553(F, sep, ...) \ + Z_UTIL_LISTIFY_2552(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2552, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2554(F, sep, ...) \ + Z_UTIL_LISTIFY_2553(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2553, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2555(F, sep, ...) \ + Z_UTIL_LISTIFY_2554(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2554, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2556(F, sep, ...) \ + Z_UTIL_LISTIFY_2555(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2555, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2557(F, sep, ...) \ + Z_UTIL_LISTIFY_2556(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2556, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2558(F, sep, ...) \ + Z_UTIL_LISTIFY_2557(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2557, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2559(F, sep, ...) \ + Z_UTIL_LISTIFY_2558(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2558, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2560(F, sep, ...) \ + Z_UTIL_LISTIFY_2559(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2559, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2561(F, sep, ...) \ + Z_UTIL_LISTIFY_2560(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2560, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2562(F, sep, ...) \ + Z_UTIL_LISTIFY_2561(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2561, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2563(F, sep, ...) \ + Z_UTIL_LISTIFY_2562(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2562, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2564(F, sep, ...) \ + Z_UTIL_LISTIFY_2563(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2563, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2565(F, sep, ...) \ + Z_UTIL_LISTIFY_2564(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2564, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2566(F, sep, ...) \ + Z_UTIL_LISTIFY_2565(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2565, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2567(F, sep, ...) \ + Z_UTIL_LISTIFY_2566(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2566, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2568(F, sep, ...) \ + Z_UTIL_LISTIFY_2567(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2567, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2569(F, sep, ...) \ + Z_UTIL_LISTIFY_2568(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2568, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2570(F, sep, ...) \ + Z_UTIL_LISTIFY_2569(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2569, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2571(F, sep, ...) \ + Z_UTIL_LISTIFY_2570(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2570, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2572(F, sep, ...) \ + Z_UTIL_LISTIFY_2571(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2571, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2573(F, sep, ...) \ + Z_UTIL_LISTIFY_2572(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2572, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2574(F, sep, ...) \ + Z_UTIL_LISTIFY_2573(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2573, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2575(F, sep, ...) \ + Z_UTIL_LISTIFY_2574(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2574, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2576(F, sep, ...) \ + Z_UTIL_LISTIFY_2575(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2575, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2577(F, sep, ...) \ + Z_UTIL_LISTIFY_2576(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2576, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2578(F, sep, ...) \ + Z_UTIL_LISTIFY_2577(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2577, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2579(F, sep, ...) \ + Z_UTIL_LISTIFY_2578(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2578, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2580(F, sep, ...) \ + Z_UTIL_LISTIFY_2579(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2579, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2581(F, sep, ...) \ + Z_UTIL_LISTIFY_2580(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2580, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2582(F, sep, ...) \ + Z_UTIL_LISTIFY_2581(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2581, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2583(F, sep, ...) \ + Z_UTIL_LISTIFY_2582(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2582, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2584(F, sep, ...) \ + Z_UTIL_LISTIFY_2583(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2583, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2585(F, sep, ...) \ + Z_UTIL_LISTIFY_2584(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2584, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2586(F, sep, ...) \ + Z_UTIL_LISTIFY_2585(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2585, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2587(F, sep, ...) \ + Z_UTIL_LISTIFY_2586(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2586, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2588(F, sep, ...) \ + Z_UTIL_LISTIFY_2587(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2587, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2589(F, sep, ...) \ + Z_UTIL_LISTIFY_2588(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2588, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2590(F, sep, ...) \ + Z_UTIL_LISTIFY_2589(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2589, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2591(F, sep, ...) \ + Z_UTIL_LISTIFY_2590(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2590, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2592(F, sep, ...) \ + Z_UTIL_LISTIFY_2591(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2591, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2593(F, sep, ...) \ + Z_UTIL_LISTIFY_2592(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2592, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2594(F, sep, ...) \ + Z_UTIL_LISTIFY_2593(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2593, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2595(F, sep, ...) \ + Z_UTIL_LISTIFY_2594(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2594, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2596(F, sep, ...) \ + Z_UTIL_LISTIFY_2595(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2595, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2597(F, sep, ...) \ + Z_UTIL_LISTIFY_2596(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2596, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2598(F, sep, ...) \ + Z_UTIL_LISTIFY_2597(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2597, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2599(F, sep, ...) \ + Z_UTIL_LISTIFY_2598(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2598, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2600(F, sep, ...) \ + Z_UTIL_LISTIFY_2599(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2599, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2601(F, sep, ...) \ + Z_UTIL_LISTIFY_2600(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2600, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2602(F, sep, ...) \ + Z_UTIL_LISTIFY_2601(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2601, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2603(F, sep, ...) \ + Z_UTIL_LISTIFY_2602(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2602, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2604(F, sep, ...) \ + Z_UTIL_LISTIFY_2603(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2603, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2605(F, sep, ...) \ + Z_UTIL_LISTIFY_2604(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2604, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2606(F, sep, ...) \ + Z_UTIL_LISTIFY_2605(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2605, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2607(F, sep, ...) \ + Z_UTIL_LISTIFY_2606(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2606, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2608(F, sep, ...) \ + Z_UTIL_LISTIFY_2607(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2607, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2609(F, sep, ...) \ + Z_UTIL_LISTIFY_2608(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2608, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2610(F, sep, ...) \ + Z_UTIL_LISTIFY_2609(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2609, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2611(F, sep, ...) \ + Z_UTIL_LISTIFY_2610(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2610, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2612(F, sep, ...) \ + Z_UTIL_LISTIFY_2611(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2611, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2613(F, sep, ...) \ + Z_UTIL_LISTIFY_2612(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2612, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2614(F, sep, ...) \ + Z_UTIL_LISTIFY_2613(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2613, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2615(F, sep, ...) \ + Z_UTIL_LISTIFY_2614(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2614, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2616(F, sep, ...) \ + Z_UTIL_LISTIFY_2615(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2615, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2617(F, sep, ...) \ + Z_UTIL_LISTIFY_2616(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2616, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2618(F, sep, ...) \ + Z_UTIL_LISTIFY_2617(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2617, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2619(F, sep, ...) \ + Z_UTIL_LISTIFY_2618(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2618, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2620(F, sep, ...) \ + Z_UTIL_LISTIFY_2619(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2619, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2621(F, sep, ...) \ + Z_UTIL_LISTIFY_2620(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2620, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2622(F, sep, ...) \ + Z_UTIL_LISTIFY_2621(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2621, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2623(F, sep, ...) \ + Z_UTIL_LISTIFY_2622(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2622, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2624(F, sep, ...) \ + Z_UTIL_LISTIFY_2623(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2623, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2625(F, sep, ...) \ + Z_UTIL_LISTIFY_2624(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2624, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2626(F, sep, ...) \ + Z_UTIL_LISTIFY_2625(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2625, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2627(F, sep, ...) \ + Z_UTIL_LISTIFY_2626(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2626, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2628(F, sep, ...) \ + Z_UTIL_LISTIFY_2627(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2627, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2629(F, sep, ...) \ + Z_UTIL_LISTIFY_2628(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2628, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2630(F, sep, ...) \ + Z_UTIL_LISTIFY_2629(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2629, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2631(F, sep, ...) \ + Z_UTIL_LISTIFY_2630(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2630, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2632(F, sep, ...) \ + Z_UTIL_LISTIFY_2631(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2631, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2633(F, sep, ...) \ + Z_UTIL_LISTIFY_2632(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2632, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2634(F, sep, ...) \ + Z_UTIL_LISTIFY_2633(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2633, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2635(F, sep, ...) \ + Z_UTIL_LISTIFY_2634(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2634, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2636(F, sep, ...) \ + Z_UTIL_LISTIFY_2635(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2635, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2637(F, sep, ...) \ + Z_UTIL_LISTIFY_2636(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2636, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2638(F, sep, ...) \ + Z_UTIL_LISTIFY_2637(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2637, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2639(F, sep, ...) \ + Z_UTIL_LISTIFY_2638(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2638, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2640(F, sep, ...) \ + Z_UTIL_LISTIFY_2639(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2639, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2641(F, sep, ...) \ + Z_UTIL_LISTIFY_2640(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2640, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2642(F, sep, ...) \ + Z_UTIL_LISTIFY_2641(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2641, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2643(F, sep, ...) \ + Z_UTIL_LISTIFY_2642(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2642, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2644(F, sep, ...) \ + Z_UTIL_LISTIFY_2643(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2643, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2645(F, sep, ...) \ + Z_UTIL_LISTIFY_2644(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2644, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2646(F, sep, ...) \ + Z_UTIL_LISTIFY_2645(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2645, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2647(F, sep, ...) \ + Z_UTIL_LISTIFY_2646(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2646, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2648(F, sep, ...) \ + Z_UTIL_LISTIFY_2647(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2647, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2649(F, sep, ...) \ + Z_UTIL_LISTIFY_2648(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2648, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2650(F, sep, ...) \ + Z_UTIL_LISTIFY_2649(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2649, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2651(F, sep, ...) \ + Z_UTIL_LISTIFY_2650(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2650, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2652(F, sep, ...) \ + Z_UTIL_LISTIFY_2651(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2651, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2653(F, sep, ...) \ + Z_UTIL_LISTIFY_2652(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2652, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2654(F, sep, ...) \ + Z_UTIL_LISTIFY_2653(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2653, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2655(F, sep, ...) \ + Z_UTIL_LISTIFY_2654(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2654, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2656(F, sep, ...) \ + Z_UTIL_LISTIFY_2655(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2655, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2657(F, sep, ...) \ + Z_UTIL_LISTIFY_2656(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2656, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2658(F, sep, ...) \ + Z_UTIL_LISTIFY_2657(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2657, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2659(F, sep, ...) \ + Z_UTIL_LISTIFY_2658(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2658, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2660(F, sep, ...) \ + Z_UTIL_LISTIFY_2659(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2659, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2661(F, sep, ...) \ + Z_UTIL_LISTIFY_2660(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2660, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2662(F, sep, ...) \ + Z_UTIL_LISTIFY_2661(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2661, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2663(F, sep, ...) \ + Z_UTIL_LISTIFY_2662(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2662, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2664(F, sep, ...) \ + Z_UTIL_LISTIFY_2663(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2663, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2665(F, sep, ...) \ + Z_UTIL_LISTIFY_2664(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2664, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2666(F, sep, ...) \ + Z_UTIL_LISTIFY_2665(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2665, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2667(F, sep, ...) \ + Z_UTIL_LISTIFY_2666(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2666, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2668(F, sep, ...) \ + Z_UTIL_LISTIFY_2667(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2667, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2669(F, sep, ...) \ + Z_UTIL_LISTIFY_2668(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2668, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2670(F, sep, ...) \ + Z_UTIL_LISTIFY_2669(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2669, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2671(F, sep, ...) \ + Z_UTIL_LISTIFY_2670(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2670, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2672(F, sep, ...) \ + Z_UTIL_LISTIFY_2671(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2671, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2673(F, sep, ...) \ + Z_UTIL_LISTIFY_2672(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2672, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2674(F, sep, ...) \ + Z_UTIL_LISTIFY_2673(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2673, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2675(F, sep, ...) \ + Z_UTIL_LISTIFY_2674(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2674, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2676(F, sep, ...) \ + Z_UTIL_LISTIFY_2675(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2675, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2677(F, sep, ...) \ + Z_UTIL_LISTIFY_2676(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2676, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2678(F, sep, ...) \ + Z_UTIL_LISTIFY_2677(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2677, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2679(F, sep, ...) \ + Z_UTIL_LISTIFY_2678(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2678, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2680(F, sep, ...) \ + Z_UTIL_LISTIFY_2679(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2679, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2681(F, sep, ...) \ + Z_UTIL_LISTIFY_2680(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2680, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2682(F, sep, ...) \ + Z_UTIL_LISTIFY_2681(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2681, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2683(F, sep, ...) \ + Z_UTIL_LISTIFY_2682(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2682, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2684(F, sep, ...) \ + Z_UTIL_LISTIFY_2683(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2683, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2685(F, sep, ...) \ + Z_UTIL_LISTIFY_2684(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2684, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2686(F, sep, ...) \ + Z_UTIL_LISTIFY_2685(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2685, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2687(F, sep, ...) \ + Z_UTIL_LISTIFY_2686(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2686, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2688(F, sep, ...) \ + Z_UTIL_LISTIFY_2687(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2687, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2689(F, sep, ...) \ + Z_UTIL_LISTIFY_2688(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2688, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2690(F, sep, ...) \ + Z_UTIL_LISTIFY_2689(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2689, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2691(F, sep, ...) \ + Z_UTIL_LISTIFY_2690(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2690, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2692(F, sep, ...) \ + Z_UTIL_LISTIFY_2691(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2691, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2693(F, sep, ...) \ + Z_UTIL_LISTIFY_2692(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2692, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2694(F, sep, ...) \ + Z_UTIL_LISTIFY_2693(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2693, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2695(F, sep, ...) \ + Z_UTIL_LISTIFY_2694(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2694, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2696(F, sep, ...) \ + Z_UTIL_LISTIFY_2695(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2695, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2697(F, sep, ...) \ + Z_UTIL_LISTIFY_2696(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2696, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2698(F, sep, ...) \ + Z_UTIL_LISTIFY_2697(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2697, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2699(F, sep, ...) \ + Z_UTIL_LISTIFY_2698(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2698, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2700(F, sep, ...) \ + Z_UTIL_LISTIFY_2699(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2699, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2701(F, sep, ...) \ + Z_UTIL_LISTIFY_2700(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2700, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2702(F, sep, ...) \ + Z_UTIL_LISTIFY_2701(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2701, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2703(F, sep, ...) \ + Z_UTIL_LISTIFY_2702(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2702, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2704(F, sep, ...) \ + Z_UTIL_LISTIFY_2703(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2703, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2705(F, sep, ...) \ + Z_UTIL_LISTIFY_2704(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2704, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2706(F, sep, ...) \ + Z_UTIL_LISTIFY_2705(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2705, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2707(F, sep, ...) \ + Z_UTIL_LISTIFY_2706(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2706, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2708(F, sep, ...) \ + Z_UTIL_LISTIFY_2707(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2707, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2709(F, sep, ...) \ + Z_UTIL_LISTIFY_2708(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2708, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2710(F, sep, ...) \ + Z_UTIL_LISTIFY_2709(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2709, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2711(F, sep, ...) \ + Z_UTIL_LISTIFY_2710(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2710, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2712(F, sep, ...) \ + Z_UTIL_LISTIFY_2711(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2711, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2713(F, sep, ...) \ + Z_UTIL_LISTIFY_2712(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2712, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2714(F, sep, ...) \ + Z_UTIL_LISTIFY_2713(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2713, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2715(F, sep, ...) \ + Z_UTIL_LISTIFY_2714(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2714, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2716(F, sep, ...) \ + Z_UTIL_LISTIFY_2715(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2715, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2717(F, sep, ...) \ + Z_UTIL_LISTIFY_2716(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2716, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2718(F, sep, ...) \ + Z_UTIL_LISTIFY_2717(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2717, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2719(F, sep, ...) \ + Z_UTIL_LISTIFY_2718(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2718, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2720(F, sep, ...) \ + Z_UTIL_LISTIFY_2719(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2719, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2721(F, sep, ...) \ + Z_UTIL_LISTIFY_2720(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2720, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2722(F, sep, ...) \ + Z_UTIL_LISTIFY_2721(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2721, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2723(F, sep, ...) \ + Z_UTIL_LISTIFY_2722(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2722, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2724(F, sep, ...) \ + Z_UTIL_LISTIFY_2723(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2723, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2725(F, sep, ...) \ + Z_UTIL_LISTIFY_2724(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2724, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2726(F, sep, ...) \ + Z_UTIL_LISTIFY_2725(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2725, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2727(F, sep, ...) \ + Z_UTIL_LISTIFY_2726(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2726, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2728(F, sep, ...) \ + Z_UTIL_LISTIFY_2727(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2727, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2729(F, sep, ...) \ + Z_UTIL_LISTIFY_2728(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2728, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2730(F, sep, ...) \ + Z_UTIL_LISTIFY_2729(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2729, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2731(F, sep, ...) \ + Z_UTIL_LISTIFY_2730(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2730, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2732(F, sep, ...) \ + Z_UTIL_LISTIFY_2731(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2731, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2733(F, sep, ...) \ + Z_UTIL_LISTIFY_2732(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2732, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2734(F, sep, ...) \ + Z_UTIL_LISTIFY_2733(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2733, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2735(F, sep, ...) \ + Z_UTIL_LISTIFY_2734(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2734, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2736(F, sep, ...) \ + Z_UTIL_LISTIFY_2735(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2735, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2737(F, sep, ...) \ + Z_UTIL_LISTIFY_2736(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2736, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2738(F, sep, ...) \ + Z_UTIL_LISTIFY_2737(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2737, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2739(F, sep, ...) \ + Z_UTIL_LISTIFY_2738(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2738, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2740(F, sep, ...) \ + Z_UTIL_LISTIFY_2739(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2739, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2741(F, sep, ...) \ + Z_UTIL_LISTIFY_2740(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2740, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2742(F, sep, ...) \ + Z_UTIL_LISTIFY_2741(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2741, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2743(F, sep, ...) \ + Z_UTIL_LISTIFY_2742(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2742, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2744(F, sep, ...) \ + Z_UTIL_LISTIFY_2743(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2743, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2745(F, sep, ...) \ + Z_UTIL_LISTIFY_2744(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2744, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2746(F, sep, ...) \ + Z_UTIL_LISTIFY_2745(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2745, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2747(F, sep, ...) \ + Z_UTIL_LISTIFY_2746(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2746, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2748(F, sep, ...) \ + Z_UTIL_LISTIFY_2747(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2747, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2749(F, sep, ...) \ + Z_UTIL_LISTIFY_2748(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2748, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2750(F, sep, ...) \ + Z_UTIL_LISTIFY_2749(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2749, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2751(F, sep, ...) \ + Z_UTIL_LISTIFY_2750(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2750, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2752(F, sep, ...) \ + Z_UTIL_LISTIFY_2751(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2751, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2753(F, sep, ...) \ + Z_UTIL_LISTIFY_2752(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2752, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2754(F, sep, ...) \ + Z_UTIL_LISTIFY_2753(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2753, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2755(F, sep, ...) \ + Z_UTIL_LISTIFY_2754(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2754, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2756(F, sep, ...) \ + Z_UTIL_LISTIFY_2755(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2755, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2757(F, sep, ...) \ + Z_UTIL_LISTIFY_2756(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2756, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2758(F, sep, ...) \ + Z_UTIL_LISTIFY_2757(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2757, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2759(F, sep, ...) \ + Z_UTIL_LISTIFY_2758(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2758, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2760(F, sep, ...) \ + Z_UTIL_LISTIFY_2759(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2759, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2761(F, sep, ...) \ + Z_UTIL_LISTIFY_2760(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2760, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2762(F, sep, ...) \ + Z_UTIL_LISTIFY_2761(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2761, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2763(F, sep, ...) \ + Z_UTIL_LISTIFY_2762(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2762, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2764(F, sep, ...) \ + Z_UTIL_LISTIFY_2763(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2763, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2765(F, sep, ...) \ + Z_UTIL_LISTIFY_2764(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2764, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2766(F, sep, ...) \ + Z_UTIL_LISTIFY_2765(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2765, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2767(F, sep, ...) \ + Z_UTIL_LISTIFY_2766(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2766, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2768(F, sep, ...) \ + Z_UTIL_LISTIFY_2767(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2767, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2769(F, sep, ...) \ + Z_UTIL_LISTIFY_2768(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2768, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2770(F, sep, ...) \ + Z_UTIL_LISTIFY_2769(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2769, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2771(F, sep, ...) \ + Z_UTIL_LISTIFY_2770(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2770, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2772(F, sep, ...) \ + Z_UTIL_LISTIFY_2771(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2771, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2773(F, sep, ...) \ + Z_UTIL_LISTIFY_2772(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2772, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2774(F, sep, ...) \ + Z_UTIL_LISTIFY_2773(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2773, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2775(F, sep, ...) \ + Z_UTIL_LISTIFY_2774(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2774, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2776(F, sep, ...) \ + Z_UTIL_LISTIFY_2775(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2775, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2777(F, sep, ...) \ + Z_UTIL_LISTIFY_2776(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2776, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2778(F, sep, ...) \ + Z_UTIL_LISTIFY_2777(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2777, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2779(F, sep, ...) \ + Z_UTIL_LISTIFY_2778(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2778, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2780(F, sep, ...) \ + Z_UTIL_LISTIFY_2779(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2779, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2781(F, sep, ...) \ + Z_UTIL_LISTIFY_2780(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2780, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2782(F, sep, ...) \ + Z_UTIL_LISTIFY_2781(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2781, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2783(F, sep, ...) \ + Z_UTIL_LISTIFY_2782(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2782, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2784(F, sep, ...) \ + Z_UTIL_LISTIFY_2783(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2783, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2785(F, sep, ...) \ + Z_UTIL_LISTIFY_2784(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2784, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2786(F, sep, ...) \ + Z_UTIL_LISTIFY_2785(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2785, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2787(F, sep, ...) \ + Z_UTIL_LISTIFY_2786(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2786, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2788(F, sep, ...) \ + Z_UTIL_LISTIFY_2787(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2787, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2789(F, sep, ...) \ + Z_UTIL_LISTIFY_2788(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2788, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2790(F, sep, ...) \ + Z_UTIL_LISTIFY_2789(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2789, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2791(F, sep, ...) \ + Z_UTIL_LISTIFY_2790(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2790, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2792(F, sep, ...) \ + Z_UTIL_LISTIFY_2791(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2791, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2793(F, sep, ...) \ + Z_UTIL_LISTIFY_2792(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2792, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2794(F, sep, ...) \ + Z_UTIL_LISTIFY_2793(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2793, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2795(F, sep, ...) \ + Z_UTIL_LISTIFY_2794(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2794, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2796(F, sep, ...) \ + Z_UTIL_LISTIFY_2795(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2795, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2797(F, sep, ...) \ + Z_UTIL_LISTIFY_2796(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2796, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2798(F, sep, ...) \ + Z_UTIL_LISTIFY_2797(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2797, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2799(F, sep, ...) \ + Z_UTIL_LISTIFY_2798(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2798, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2800(F, sep, ...) \ + Z_UTIL_LISTIFY_2799(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2799, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2801(F, sep, ...) \ + Z_UTIL_LISTIFY_2800(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2800, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2802(F, sep, ...) \ + Z_UTIL_LISTIFY_2801(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2801, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2803(F, sep, ...) \ + Z_UTIL_LISTIFY_2802(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2802, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2804(F, sep, ...) \ + Z_UTIL_LISTIFY_2803(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2803, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2805(F, sep, ...) \ + Z_UTIL_LISTIFY_2804(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2804, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2806(F, sep, ...) \ + Z_UTIL_LISTIFY_2805(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2805, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2807(F, sep, ...) \ + Z_UTIL_LISTIFY_2806(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2806, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2808(F, sep, ...) \ + Z_UTIL_LISTIFY_2807(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2807, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2809(F, sep, ...) \ + Z_UTIL_LISTIFY_2808(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2808, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2810(F, sep, ...) \ + Z_UTIL_LISTIFY_2809(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2809, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2811(F, sep, ...) \ + Z_UTIL_LISTIFY_2810(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2810, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2812(F, sep, ...) \ + Z_UTIL_LISTIFY_2811(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2811, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2813(F, sep, ...) \ + Z_UTIL_LISTIFY_2812(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2812, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2814(F, sep, ...) \ + Z_UTIL_LISTIFY_2813(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2813, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2815(F, sep, ...) \ + Z_UTIL_LISTIFY_2814(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2814, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2816(F, sep, ...) \ + Z_UTIL_LISTIFY_2815(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2815, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2817(F, sep, ...) \ + Z_UTIL_LISTIFY_2816(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2816, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2818(F, sep, ...) \ + Z_UTIL_LISTIFY_2817(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2817, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2819(F, sep, ...) \ + Z_UTIL_LISTIFY_2818(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2818, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2820(F, sep, ...) \ + Z_UTIL_LISTIFY_2819(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2819, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2821(F, sep, ...) \ + Z_UTIL_LISTIFY_2820(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2820, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2822(F, sep, ...) \ + Z_UTIL_LISTIFY_2821(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2821, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2823(F, sep, ...) \ + Z_UTIL_LISTIFY_2822(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2822, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2824(F, sep, ...) \ + Z_UTIL_LISTIFY_2823(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2823, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2825(F, sep, ...) \ + Z_UTIL_LISTIFY_2824(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2824, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2826(F, sep, ...) \ + Z_UTIL_LISTIFY_2825(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2825, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2827(F, sep, ...) \ + Z_UTIL_LISTIFY_2826(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2826, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2828(F, sep, ...) \ + Z_UTIL_LISTIFY_2827(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2827, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2829(F, sep, ...) \ + Z_UTIL_LISTIFY_2828(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2828, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2830(F, sep, ...) \ + Z_UTIL_LISTIFY_2829(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2829, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2831(F, sep, ...) \ + Z_UTIL_LISTIFY_2830(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2830, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2832(F, sep, ...) \ + Z_UTIL_LISTIFY_2831(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2831, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2833(F, sep, ...) \ + Z_UTIL_LISTIFY_2832(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2832, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2834(F, sep, ...) \ + Z_UTIL_LISTIFY_2833(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2833, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2835(F, sep, ...) \ + Z_UTIL_LISTIFY_2834(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2834, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2836(F, sep, ...) \ + Z_UTIL_LISTIFY_2835(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2835, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2837(F, sep, ...) \ + Z_UTIL_LISTIFY_2836(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2836, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2838(F, sep, ...) \ + Z_UTIL_LISTIFY_2837(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2837, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2839(F, sep, ...) \ + Z_UTIL_LISTIFY_2838(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2838, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2840(F, sep, ...) \ + Z_UTIL_LISTIFY_2839(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2839, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2841(F, sep, ...) \ + Z_UTIL_LISTIFY_2840(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2840, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2842(F, sep, ...) \ + Z_UTIL_LISTIFY_2841(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2841, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2843(F, sep, ...) \ + Z_UTIL_LISTIFY_2842(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2842, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2844(F, sep, ...) \ + Z_UTIL_LISTIFY_2843(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2843, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2845(F, sep, ...) \ + Z_UTIL_LISTIFY_2844(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2844, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2846(F, sep, ...) \ + Z_UTIL_LISTIFY_2845(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2845, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2847(F, sep, ...) \ + Z_UTIL_LISTIFY_2846(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2846, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2848(F, sep, ...) \ + Z_UTIL_LISTIFY_2847(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2847, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2849(F, sep, ...) \ + Z_UTIL_LISTIFY_2848(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2848, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2850(F, sep, ...) \ + Z_UTIL_LISTIFY_2849(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2849, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2851(F, sep, ...) \ + Z_UTIL_LISTIFY_2850(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2850, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2852(F, sep, ...) \ + Z_UTIL_LISTIFY_2851(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2851, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2853(F, sep, ...) \ + Z_UTIL_LISTIFY_2852(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2852, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2854(F, sep, ...) \ + Z_UTIL_LISTIFY_2853(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2853, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2855(F, sep, ...) \ + Z_UTIL_LISTIFY_2854(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2854, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2856(F, sep, ...) \ + Z_UTIL_LISTIFY_2855(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2855, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2857(F, sep, ...) \ + Z_UTIL_LISTIFY_2856(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2856, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2858(F, sep, ...) \ + Z_UTIL_LISTIFY_2857(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2857, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2859(F, sep, ...) \ + Z_UTIL_LISTIFY_2858(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2858, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2860(F, sep, ...) \ + Z_UTIL_LISTIFY_2859(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2859, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2861(F, sep, ...) \ + Z_UTIL_LISTIFY_2860(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2860, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2862(F, sep, ...) \ + Z_UTIL_LISTIFY_2861(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2861, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2863(F, sep, ...) \ + Z_UTIL_LISTIFY_2862(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2862, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2864(F, sep, ...) \ + Z_UTIL_LISTIFY_2863(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2863, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2865(F, sep, ...) \ + Z_UTIL_LISTIFY_2864(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2864, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2866(F, sep, ...) \ + Z_UTIL_LISTIFY_2865(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2865, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2867(F, sep, ...) \ + Z_UTIL_LISTIFY_2866(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2866, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2868(F, sep, ...) \ + Z_UTIL_LISTIFY_2867(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2867, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2869(F, sep, ...) \ + Z_UTIL_LISTIFY_2868(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2868, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2870(F, sep, ...) \ + Z_UTIL_LISTIFY_2869(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2869, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2871(F, sep, ...) \ + Z_UTIL_LISTIFY_2870(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2870, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2872(F, sep, ...) \ + Z_UTIL_LISTIFY_2871(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2871, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2873(F, sep, ...) \ + Z_UTIL_LISTIFY_2872(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2872, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2874(F, sep, ...) \ + Z_UTIL_LISTIFY_2873(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2873, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2875(F, sep, ...) \ + Z_UTIL_LISTIFY_2874(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2874, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2876(F, sep, ...) \ + Z_UTIL_LISTIFY_2875(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2875, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2877(F, sep, ...) \ + Z_UTIL_LISTIFY_2876(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2876, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2878(F, sep, ...) \ + Z_UTIL_LISTIFY_2877(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2877, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2879(F, sep, ...) \ + Z_UTIL_LISTIFY_2878(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2878, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2880(F, sep, ...) \ + Z_UTIL_LISTIFY_2879(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2879, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2881(F, sep, ...) \ + Z_UTIL_LISTIFY_2880(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2880, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2882(F, sep, ...) \ + Z_UTIL_LISTIFY_2881(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2881, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2883(F, sep, ...) \ + Z_UTIL_LISTIFY_2882(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2882, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2884(F, sep, ...) \ + Z_UTIL_LISTIFY_2883(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2883, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2885(F, sep, ...) \ + Z_UTIL_LISTIFY_2884(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2884, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2886(F, sep, ...) \ + Z_UTIL_LISTIFY_2885(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2885, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2887(F, sep, ...) \ + Z_UTIL_LISTIFY_2886(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2886, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2888(F, sep, ...) \ + Z_UTIL_LISTIFY_2887(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2887, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2889(F, sep, ...) \ + Z_UTIL_LISTIFY_2888(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2888, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2890(F, sep, ...) \ + Z_UTIL_LISTIFY_2889(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2889, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2891(F, sep, ...) \ + Z_UTIL_LISTIFY_2890(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2890, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2892(F, sep, ...) \ + Z_UTIL_LISTIFY_2891(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2891, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2893(F, sep, ...) \ + Z_UTIL_LISTIFY_2892(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2892, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2894(F, sep, ...) \ + Z_UTIL_LISTIFY_2893(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2893, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2895(F, sep, ...) \ + Z_UTIL_LISTIFY_2894(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2894, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2896(F, sep, ...) \ + Z_UTIL_LISTIFY_2895(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2895, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2897(F, sep, ...) \ + Z_UTIL_LISTIFY_2896(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2896, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2898(F, sep, ...) \ + Z_UTIL_LISTIFY_2897(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2897, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2899(F, sep, ...) \ + Z_UTIL_LISTIFY_2898(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2898, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2900(F, sep, ...) \ + Z_UTIL_LISTIFY_2899(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2899, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2901(F, sep, ...) \ + Z_UTIL_LISTIFY_2900(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2900, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2902(F, sep, ...) \ + Z_UTIL_LISTIFY_2901(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2901, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2903(F, sep, ...) \ + Z_UTIL_LISTIFY_2902(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2902, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2904(F, sep, ...) \ + Z_UTIL_LISTIFY_2903(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2903, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2905(F, sep, ...) \ + Z_UTIL_LISTIFY_2904(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2904, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2906(F, sep, ...) \ + Z_UTIL_LISTIFY_2905(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2905, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2907(F, sep, ...) \ + Z_UTIL_LISTIFY_2906(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2906, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2908(F, sep, ...) \ + Z_UTIL_LISTIFY_2907(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2907, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2909(F, sep, ...) \ + Z_UTIL_LISTIFY_2908(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2908, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2910(F, sep, ...) \ + Z_UTIL_LISTIFY_2909(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2909, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2911(F, sep, ...) \ + Z_UTIL_LISTIFY_2910(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2910, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2912(F, sep, ...) \ + Z_UTIL_LISTIFY_2911(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2911, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2913(F, sep, ...) \ + Z_UTIL_LISTIFY_2912(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2912, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2914(F, sep, ...) \ + Z_UTIL_LISTIFY_2913(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2913, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2915(F, sep, ...) \ + Z_UTIL_LISTIFY_2914(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2914, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2916(F, sep, ...) \ + Z_UTIL_LISTIFY_2915(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2915, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2917(F, sep, ...) \ + Z_UTIL_LISTIFY_2916(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2916, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2918(F, sep, ...) \ + Z_UTIL_LISTIFY_2917(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2917, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2919(F, sep, ...) \ + Z_UTIL_LISTIFY_2918(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2918, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2920(F, sep, ...) \ + Z_UTIL_LISTIFY_2919(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2919, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2921(F, sep, ...) \ + Z_UTIL_LISTIFY_2920(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2920, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2922(F, sep, ...) \ + Z_UTIL_LISTIFY_2921(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2921, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2923(F, sep, ...) \ + Z_UTIL_LISTIFY_2922(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2922, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2924(F, sep, ...) \ + Z_UTIL_LISTIFY_2923(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2923, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2925(F, sep, ...) \ + Z_UTIL_LISTIFY_2924(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2924, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2926(F, sep, ...) \ + Z_UTIL_LISTIFY_2925(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2925, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2927(F, sep, ...) \ + Z_UTIL_LISTIFY_2926(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2926, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2928(F, sep, ...) \ + Z_UTIL_LISTIFY_2927(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2927, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2929(F, sep, ...) \ + Z_UTIL_LISTIFY_2928(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2928, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2930(F, sep, ...) \ + Z_UTIL_LISTIFY_2929(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2929, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2931(F, sep, ...) \ + Z_UTIL_LISTIFY_2930(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2930, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2932(F, sep, ...) \ + Z_UTIL_LISTIFY_2931(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2931, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2933(F, sep, ...) \ + Z_UTIL_LISTIFY_2932(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2932, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2934(F, sep, ...) \ + Z_UTIL_LISTIFY_2933(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2933, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2935(F, sep, ...) \ + Z_UTIL_LISTIFY_2934(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2934, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2936(F, sep, ...) \ + Z_UTIL_LISTIFY_2935(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2935, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2937(F, sep, ...) \ + Z_UTIL_LISTIFY_2936(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2936, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2938(F, sep, ...) \ + Z_UTIL_LISTIFY_2937(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2937, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2939(F, sep, ...) \ + Z_UTIL_LISTIFY_2938(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2938, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2940(F, sep, ...) \ + Z_UTIL_LISTIFY_2939(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2939, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2941(F, sep, ...) \ + Z_UTIL_LISTIFY_2940(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2940, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2942(F, sep, ...) \ + Z_UTIL_LISTIFY_2941(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2941, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2943(F, sep, ...) \ + Z_UTIL_LISTIFY_2942(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2942, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2944(F, sep, ...) \ + Z_UTIL_LISTIFY_2943(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2943, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2945(F, sep, ...) \ + Z_UTIL_LISTIFY_2944(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2944, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2946(F, sep, ...) \ + Z_UTIL_LISTIFY_2945(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2945, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2947(F, sep, ...) \ + Z_UTIL_LISTIFY_2946(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2946, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2948(F, sep, ...) \ + Z_UTIL_LISTIFY_2947(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2947, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2949(F, sep, ...) \ + Z_UTIL_LISTIFY_2948(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2948, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2950(F, sep, ...) \ + Z_UTIL_LISTIFY_2949(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2949, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2951(F, sep, ...) \ + Z_UTIL_LISTIFY_2950(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2950, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2952(F, sep, ...) \ + Z_UTIL_LISTIFY_2951(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2951, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2953(F, sep, ...) \ + Z_UTIL_LISTIFY_2952(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2952, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2954(F, sep, ...) \ + Z_UTIL_LISTIFY_2953(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2953, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2955(F, sep, ...) \ + Z_UTIL_LISTIFY_2954(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2954, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2956(F, sep, ...) \ + Z_UTIL_LISTIFY_2955(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2955, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2957(F, sep, ...) \ + Z_UTIL_LISTIFY_2956(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2956, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2958(F, sep, ...) \ + Z_UTIL_LISTIFY_2957(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2957, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2959(F, sep, ...) \ + Z_UTIL_LISTIFY_2958(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2958, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2960(F, sep, ...) \ + Z_UTIL_LISTIFY_2959(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2959, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2961(F, sep, ...) \ + Z_UTIL_LISTIFY_2960(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2960, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2962(F, sep, ...) \ + Z_UTIL_LISTIFY_2961(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2961, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2963(F, sep, ...) \ + Z_UTIL_LISTIFY_2962(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2962, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2964(F, sep, ...) \ + Z_UTIL_LISTIFY_2963(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2963, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2965(F, sep, ...) \ + Z_UTIL_LISTIFY_2964(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2964, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2966(F, sep, ...) \ + Z_UTIL_LISTIFY_2965(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2965, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2967(F, sep, ...) \ + Z_UTIL_LISTIFY_2966(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2966, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2968(F, sep, ...) \ + Z_UTIL_LISTIFY_2967(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2967, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2969(F, sep, ...) \ + Z_UTIL_LISTIFY_2968(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2968, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2970(F, sep, ...) \ + Z_UTIL_LISTIFY_2969(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2969, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2971(F, sep, ...) \ + Z_UTIL_LISTIFY_2970(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2970, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2972(F, sep, ...) \ + Z_UTIL_LISTIFY_2971(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2971, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2973(F, sep, ...) \ + Z_UTIL_LISTIFY_2972(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2972, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2974(F, sep, ...) \ + Z_UTIL_LISTIFY_2973(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2973, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2975(F, sep, ...) \ + Z_UTIL_LISTIFY_2974(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2974, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2976(F, sep, ...) \ + Z_UTIL_LISTIFY_2975(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2975, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2977(F, sep, ...) \ + Z_UTIL_LISTIFY_2976(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2976, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2978(F, sep, ...) \ + Z_UTIL_LISTIFY_2977(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2977, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2979(F, sep, ...) \ + Z_UTIL_LISTIFY_2978(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2978, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2980(F, sep, ...) \ + Z_UTIL_LISTIFY_2979(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2979, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2981(F, sep, ...) \ + Z_UTIL_LISTIFY_2980(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2980, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2982(F, sep, ...) \ + Z_UTIL_LISTIFY_2981(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2981, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2983(F, sep, ...) \ + Z_UTIL_LISTIFY_2982(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2982, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2984(F, sep, ...) \ + Z_UTIL_LISTIFY_2983(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2983, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2985(F, sep, ...) \ + Z_UTIL_LISTIFY_2984(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2984, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2986(F, sep, ...) \ + Z_UTIL_LISTIFY_2985(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2985, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2987(F, sep, ...) \ + Z_UTIL_LISTIFY_2986(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2986, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2988(F, sep, ...) \ + Z_UTIL_LISTIFY_2987(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2987, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2989(F, sep, ...) \ + Z_UTIL_LISTIFY_2988(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2988, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2990(F, sep, ...) \ + Z_UTIL_LISTIFY_2989(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2989, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2991(F, sep, ...) \ + Z_UTIL_LISTIFY_2990(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2990, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2992(F, sep, ...) \ + Z_UTIL_LISTIFY_2991(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2991, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2993(F, sep, ...) \ + Z_UTIL_LISTIFY_2992(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2992, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2994(F, sep, ...) \ + Z_UTIL_LISTIFY_2993(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2993, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2995(F, sep, ...) \ + Z_UTIL_LISTIFY_2994(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2994, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2996(F, sep, ...) \ + Z_UTIL_LISTIFY_2995(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2995, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2997(F, sep, ...) \ + Z_UTIL_LISTIFY_2996(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2996, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2998(F, sep, ...) \ + Z_UTIL_LISTIFY_2997(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2997, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2999(F, sep, ...) \ + Z_UTIL_LISTIFY_2998(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2998, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3000(F, sep, ...) \ + Z_UTIL_LISTIFY_2999(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2999, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3001(F, sep, ...) \ + Z_UTIL_LISTIFY_3000(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3000, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3002(F, sep, ...) \ + Z_UTIL_LISTIFY_3001(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3001, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3003(F, sep, ...) \ + Z_UTIL_LISTIFY_3002(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3002, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3004(F, sep, ...) \ + Z_UTIL_LISTIFY_3003(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3003, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3005(F, sep, ...) \ + Z_UTIL_LISTIFY_3004(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3004, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3006(F, sep, ...) \ + Z_UTIL_LISTIFY_3005(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3005, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3007(F, sep, ...) \ + Z_UTIL_LISTIFY_3006(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3006, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3008(F, sep, ...) \ + Z_UTIL_LISTIFY_3007(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3007, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3009(F, sep, ...) \ + Z_UTIL_LISTIFY_3008(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3008, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3010(F, sep, ...) \ + Z_UTIL_LISTIFY_3009(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3009, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3011(F, sep, ...) \ + Z_UTIL_LISTIFY_3010(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3010, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3012(F, sep, ...) \ + Z_UTIL_LISTIFY_3011(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3011, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3013(F, sep, ...) \ + Z_UTIL_LISTIFY_3012(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3012, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3014(F, sep, ...) \ + Z_UTIL_LISTIFY_3013(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3013, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3015(F, sep, ...) \ + Z_UTIL_LISTIFY_3014(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3014, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3016(F, sep, ...) \ + Z_UTIL_LISTIFY_3015(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3015, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3017(F, sep, ...) \ + Z_UTIL_LISTIFY_3016(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3016, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3018(F, sep, ...) \ + Z_UTIL_LISTIFY_3017(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3017, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3019(F, sep, ...) \ + Z_UTIL_LISTIFY_3018(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3018, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3020(F, sep, ...) \ + Z_UTIL_LISTIFY_3019(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3019, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3021(F, sep, ...) \ + Z_UTIL_LISTIFY_3020(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3020, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3022(F, sep, ...) \ + Z_UTIL_LISTIFY_3021(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3021, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3023(F, sep, ...) \ + Z_UTIL_LISTIFY_3022(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3022, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3024(F, sep, ...) \ + Z_UTIL_LISTIFY_3023(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3023, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3025(F, sep, ...) \ + Z_UTIL_LISTIFY_3024(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3024, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3026(F, sep, ...) \ + Z_UTIL_LISTIFY_3025(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3025, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3027(F, sep, ...) \ + Z_UTIL_LISTIFY_3026(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3026, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3028(F, sep, ...) \ + Z_UTIL_LISTIFY_3027(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3027, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3029(F, sep, ...) \ + Z_UTIL_LISTIFY_3028(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3028, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3030(F, sep, ...) \ + Z_UTIL_LISTIFY_3029(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3029, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3031(F, sep, ...) \ + Z_UTIL_LISTIFY_3030(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3030, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3032(F, sep, ...) \ + Z_UTIL_LISTIFY_3031(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3031, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3033(F, sep, ...) \ + Z_UTIL_LISTIFY_3032(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3032, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3034(F, sep, ...) \ + Z_UTIL_LISTIFY_3033(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3033, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3035(F, sep, ...) \ + Z_UTIL_LISTIFY_3034(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3034, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3036(F, sep, ...) \ + Z_UTIL_LISTIFY_3035(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3035, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3037(F, sep, ...) \ + Z_UTIL_LISTIFY_3036(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3036, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3038(F, sep, ...) \ + Z_UTIL_LISTIFY_3037(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3037, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3039(F, sep, ...) \ + Z_UTIL_LISTIFY_3038(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3038, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3040(F, sep, ...) \ + Z_UTIL_LISTIFY_3039(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3039, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3041(F, sep, ...) \ + Z_UTIL_LISTIFY_3040(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3040, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3042(F, sep, ...) \ + Z_UTIL_LISTIFY_3041(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3041, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3043(F, sep, ...) \ + Z_UTIL_LISTIFY_3042(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3042, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3044(F, sep, ...) \ + Z_UTIL_LISTIFY_3043(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3043, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3045(F, sep, ...) \ + Z_UTIL_LISTIFY_3044(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3044, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3046(F, sep, ...) \ + Z_UTIL_LISTIFY_3045(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3045, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3047(F, sep, ...) \ + Z_UTIL_LISTIFY_3046(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3046, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3048(F, sep, ...) \ + Z_UTIL_LISTIFY_3047(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3047, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3049(F, sep, ...) \ + Z_UTIL_LISTIFY_3048(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3048, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3050(F, sep, ...) \ + Z_UTIL_LISTIFY_3049(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3049, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3051(F, sep, ...) \ + Z_UTIL_LISTIFY_3050(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3050, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3052(F, sep, ...) \ + Z_UTIL_LISTIFY_3051(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3051, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3053(F, sep, ...) \ + Z_UTIL_LISTIFY_3052(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3052, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3054(F, sep, ...) \ + Z_UTIL_LISTIFY_3053(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3053, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3055(F, sep, ...) \ + Z_UTIL_LISTIFY_3054(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3054, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3056(F, sep, ...) \ + Z_UTIL_LISTIFY_3055(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3055, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3057(F, sep, ...) \ + Z_UTIL_LISTIFY_3056(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3056, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3058(F, sep, ...) \ + Z_UTIL_LISTIFY_3057(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3057, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3059(F, sep, ...) \ + Z_UTIL_LISTIFY_3058(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3058, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3060(F, sep, ...) \ + Z_UTIL_LISTIFY_3059(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3059, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3061(F, sep, ...) \ + Z_UTIL_LISTIFY_3060(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3060, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3062(F, sep, ...) \ + Z_UTIL_LISTIFY_3061(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3061, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3063(F, sep, ...) \ + Z_UTIL_LISTIFY_3062(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3062, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3064(F, sep, ...) \ + Z_UTIL_LISTIFY_3063(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3063, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3065(F, sep, ...) \ + Z_UTIL_LISTIFY_3064(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3064, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3066(F, sep, ...) \ + Z_UTIL_LISTIFY_3065(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3065, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3067(F, sep, ...) \ + Z_UTIL_LISTIFY_3066(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3066, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3068(F, sep, ...) \ + Z_UTIL_LISTIFY_3067(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3067, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3069(F, sep, ...) \ + Z_UTIL_LISTIFY_3068(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3068, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3070(F, sep, ...) \ + Z_UTIL_LISTIFY_3069(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3069, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3071(F, sep, ...) \ + Z_UTIL_LISTIFY_3070(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3070, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3072(F, sep, ...) \ + Z_UTIL_LISTIFY_3071(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3071, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3073(F, sep, ...) \ + Z_UTIL_LISTIFY_3072(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3072, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3074(F, sep, ...) \ + Z_UTIL_LISTIFY_3073(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3073, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3075(F, sep, ...) \ + Z_UTIL_LISTIFY_3074(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3074, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3076(F, sep, ...) \ + Z_UTIL_LISTIFY_3075(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3075, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3077(F, sep, ...) \ + Z_UTIL_LISTIFY_3076(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3076, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3078(F, sep, ...) \ + Z_UTIL_LISTIFY_3077(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3077, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3079(F, sep, ...) \ + Z_UTIL_LISTIFY_3078(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3078, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3080(F, sep, ...) \ + Z_UTIL_LISTIFY_3079(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3079, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3081(F, sep, ...) \ + Z_UTIL_LISTIFY_3080(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3080, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3082(F, sep, ...) \ + Z_UTIL_LISTIFY_3081(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3081, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3083(F, sep, ...) \ + Z_UTIL_LISTIFY_3082(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3082, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3084(F, sep, ...) \ + Z_UTIL_LISTIFY_3083(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3083, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3085(F, sep, ...) \ + Z_UTIL_LISTIFY_3084(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3084, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3086(F, sep, ...) \ + Z_UTIL_LISTIFY_3085(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3085, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3087(F, sep, ...) \ + Z_UTIL_LISTIFY_3086(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3086, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3088(F, sep, ...) \ + Z_UTIL_LISTIFY_3087(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3087, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3089(F, sep, ...) \ + Z_UTIL_LISTIFY_3088(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3088, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3090(F, sep, ...) \ + Z_UTIL_LISTIFY_3089(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3089, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3091(F, sep, ...) \ + Z_UTIL_LISTIFY_3090(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3090, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3092(F, sep, ...) \ + Z_UTIL_LISTIFY_3091(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3091, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3093(F, sep, ...) \ + Z_UTIL_LISTIFY_3092(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3092, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3094(F, sep, ...) \ + Z_UTIL_LISTIFY_3093(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3093, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3095(F, sep, ...) \ + Z_UTIL_LISTIFY_3094(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3094, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3096(F, sep, ...) \ + Z_UTIL_LISTIFY_3095(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3095, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3097(F, sep, ...) \ + Z_UTIL_LISTIFY_3096(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3096, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3098(F, sep, ...) \ + Z_UTIL_LISTIFY_3097(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3097, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3099(F, sep, ...) \ + Z_UTIL_LISTIFY_3098(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3098, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3100(F, sep, ...) \ + Z_UTIL_LISTIFY_3099(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3099, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3101(F, sep, ...) \ + Z_UTIL_LISTIFY_3100(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3100, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3102(F, sep, ...) \ + Z_UTIL_LISTIFY_3101(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3101, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3103(F, sep, ...) \ + Z_UTIL_LISTIFY_3102(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3102, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3104(F, sep, ...) \ + Z_UTIL_LISTIFY_3103(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3103, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3105(F, sep, ...) \ + Z_UTIL_LISTIFY_3104(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3104, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3106(F, sep, ...) \ + Z_UTIL_LISTIFY_3105(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3105, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3107(F, sep, ...) \ + Z_UTIL_LISTIFY_3106(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3106, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3108(F, sep, ...) \ + Z_UTIL_LISTIFY_3107(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3107, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3109(F, sep, ...) \ + Z_UTIL_LISTIFY_3108(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3108, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3110(F, sep, ...) \ + Z_UTIL_LISTIFY_3109(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3109, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3111(F, sep, ...) \ + Z_UTIL_LISTIFY_3110(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3110, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3112(F, sep, ...) \ + Z_UTIL_LISTIFY_3111(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3111, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3113(F, sep, ...) \ + Z_UTIL_LISTIFY_3112(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3112, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3114(F, sep, ...) \ + Z_UTIL_LISTIFY_3113(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3113, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3115(F, sep, ...) \ + Z_UTIL_LISTIFY_3114(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3114, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3116(F, sep, ...) \ + Z_UTIL_LISTIFY_3115(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3115, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3117(F, sep, ...) \ + Z_UTIL_LISTIFY_3116(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3116, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3118(F, sep, ...) \ + Z_UTIL_LISTIFY_3117(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3117, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3119(F, sep, ...) \ + Z_UTIL_LISTIFY_3118(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3118, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3120(F, sep, ...) \ + Z_UTIL_LISTIFY_3119(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3119, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3121(F, sep, ...) \ + Z_UTIL_LISTIFY_3120(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3120, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3122(F, sep, ...) \ + Z_UTIL_LISTIFY_3121(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3121, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3123(F, sep, ...) \ + Z_UTIL_LISTIFY_3122(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3122, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3124(F, sep, ...) \ + Z_UTIL_LISTIFY_3123(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3123, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3125(F, sep, ...) \ + Z_UTIL_LISTIFY_3124(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3124, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3126(F, sep, ...) \ + Z_UTIL_LISTIFY_3125(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3125, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3127(F, sep, ...) \ + Z_UTIL_LISTIFY_3126(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3126, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3128(F, sep, ...) \ + Z_UTIL_LISTIFY_3127(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3127, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3129(F, sep, ...) \ + Z_UTIL_LISTIFY_3128(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3128, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3130(F, sep, ...) \ + Z_UTIL_LISTIFY_3129(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3129, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3131(F, sep, ...) \ + Z_UTIL_LISTIFY_3130(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3130, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3132(F, sep, ...) \ + Z_UTIL_LISTIFY_3131(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3131, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3133(F, sep, ...) \ + Z_UTIL_LISTIFY_3132(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3132, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3134(F, sep, ...) \ + Z_UTIL_LISTIFY_3133(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3133, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3135(F, sep, ...) \ + Z_UTIL_LISTIFY_3134(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3134, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3136(F, sep, ...) \ + Z_UTIL_LISTIFY_3135(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3135, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3137(F, sep, ...) \ + Z_UTIL_LISTIFY_3136(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3136, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3138(F, sep, ...) \ + Z_UTIL_LISTIFY_3137(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3137, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3139(F, sep, ...) \ + Z_UTIL_LISTIFY_3138(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3138, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3140(F, sep, ...) \ + Z_UTIL_LISTIFY_3139(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3139, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3141(F, sep, ...) \ + Z_UTIL_LISTIFY_3140(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3140, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3142(F, sep, ...) \ + Z_UTIL_LISTIFY_3141(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3141, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3143(F, sep, ...) \ + Z_UTIL_LISTIFY_3142(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3142, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3144(F, sep, ...) \ + Z_UTIL_LISTIFY_3143(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3143, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3145(F, sep, ...) \ + Z_UTIL_LISTIFY_3144(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3144, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3146(F, sep, ...) \ + Z_UTIL_LISTIFY_3145(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3145, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3147(F, sep, ...) \ + Z_UTIL_LISTIFY_3146(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3146, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3148(F, sep, ...) \ + Z_UTIL_LISTIFY_3147(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3147, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3149(F, sep, ...) \ + Z_UTIL_LISTIFY_3148(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3148, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3150(F, sep, ...) \ + Z_UTIL_LISTIFY_3149(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3149, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3151(F, sep, ...) \ + Z_UTIL_LISTIFY_3150(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3150, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3152(F, sep, ...) \ + Z_UTIL_LISTIFY_3151(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3151, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3153(F, sep, ...) \ + Z_UTIL_LISTIFY_3152(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3152, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3154(F, sep, ...) \ + Z_UTIL_LISTIFY_3153(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3153, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3155(F, sep, ...) \ + Z_UTIL_LISTIFY_3154(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3154, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3156(F, sep, ...) \ + Z_UTIL_LISTIFY_3155(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3155, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3157(F, sep, ...) \ + Z_UTIL_LISTIFY_3156(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3156, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3158(F, sep, ...) \ + Z_UTIL_LISTIFY_3157(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3157, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3159(F, sep, ...) \ + Z_UTIL_LISTIFY_3158(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3158, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3160(F, sep, ...) \ + Z_UTIL_LISTIFY_3159(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3159, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3161(F, sep, ...) \ + Z_UTIL_LISTIFY_3160(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3160, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3162(F, sep, ...) \ + Z_UTIL_LISTIFY_3161(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3161, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3163(F, sep, ...) \ + Z_UTIL_LISTIFY_3162(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3162, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3164(F, sep, ...) \ + Z_UTIL_LISTIFY_3163(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3163, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3165(F, sep, ...) \ + Z_UTIL_LISTIFY_3164(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3164, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3166(F, sep, ...) \ + Z_UTIL_LISTIFY_3165(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3165, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3167(F, sep, ...) \ + Z_UTIL_LISTIFY_3166(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3166, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3168(F, sep, ...) \ + Z_UTIL_LISTIFY_3167(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3167, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3169(F, sep, ...) \ + Z_UTIL_LISTIFY_3168(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3168, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3170(F, sep, ...) \ + Z_UTIL_LISTIFY_3169(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3169, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3171(F, sep, ...) \ + Z_UTIL_LISTIFY_3170(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3170, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3172(F, sep, ...) \ + Z_UTIL_LISTIFY_3171(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3171, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3173(F, sep, ...) \ + Z_UTIL_LISTIFY_3172(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3172, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3174(F, sep, ...) \ + Z_UTIL_LISTIFY_3173(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3173, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3175(F, sep, ...) \ + Z_UTIL_LISTIFY_3174(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3174, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3176(F, sep, ...) \ + Z_UTIL_LISTIFY_3175(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3175, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3177(F, sep, ...) \ + Z_UTIL_LISTIFY_3176(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3176, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3178(F, sep, ...) \ + Z_UTIL_LISTIFY_3177(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3177, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3179(F, sep, ...) \ + Z_UTIL_LISTIFY_3178(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3178, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3180(F, sep, ...) \ + Z_UTIL_LISTIFY_3179(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3179, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3181(F, sep, ...) \ + Z_UTIL_LISTIFY_3180(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3180, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3182(F, sep, ...) \ + Z_UTIL_LISTIFY_3181(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3181, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3183(F, sep, ...) \ + Z_UTIL_LISTIFY_3182(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3182, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3184(F, sep, ...) \ + Z_UTIL_LISTIFY_3183(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3183, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3185(F, sep, ...) \ + Z_UTIL_LISTIFY_3184(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3184, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3186(F, sep, ...) \ + Z_UTIL_LISTIFY_3185(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3185, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3187(F, sep, ...) \ + Z_UTIL_LISTIFY_3186(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3186, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3188(F, sep, ...) \ + Z_UTIL_LISTIFY_3187(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3187, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3189(F, sep, ...) \ + Z_UTIL_LISTIFY_3188(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3188, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3190(F, sep, ...) \ + Z_UTIL_LISTIFY_3189(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3189, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3191(F, sep, ...) \ + Z_UTIL_LISTIFY_3190(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3190, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3192(F, sep, ...) \ + Z_UTIL_LISTIFY_3191(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3191, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3193(F, sep, ...) \ + Z_UTIL_LISTIFY_3192(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3192, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3194(F, sep, ...) \ + Z_UTIL_LISTIFY_3193(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3193, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3195(F, sep, ...) \ + Z_UTIL_LISTIFY_3194(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3194, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3196(F, sep, ...) \ + Z_UTIL_LISTIFY_3195(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3195, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3197(F, sep, ...) \ + Z_UTIL_LISTIFY_3196(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3196, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3198(F, sep, ...) \ + Z_UTIL_LISTIFY_3197(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3197, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3199(F, sep, ...) \ + Z_UTIL_LISTIFY_3198(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3198, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3200(F, sep, ...) \ + Z_UTIL_LISTIFY_3199(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3199, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3201(F, sep, ...) \ + Z_UTIL_LISTIFY_3200(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3200, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3202(F, sep, ...) \ + Z_UTIL_LISTIFY_3201(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3201, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3203(F, sep, ...) \ + Z_UTIL_LISTIFY_3202(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3202, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3204(F, sep, ...) \ + Z_UTIL_LISTIFY_3203(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3203, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3205(F, sep, ...) \ + Z_UTIL_LISTIFY_3204(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3204, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3206(F, sep, ...) \ + Z_UTIL_LISTIFY_3205(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3205, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3207(F, sep, ...) \ + Z_UTIL_LISTIFY_3206(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3206, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3208(F, sep, ...) \ + Z_UTIL_LISTIFY_3207(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3207, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3209(F, sep, ...) \ + Z_UTIL_LISTIFY_3208(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3208, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3210(F, sep, ...) \ + Z_UTIL_LISTIFY_3209(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3209, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3211(F, sep, ...) \ + Z_UTIL_LISTIFY_3210(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3210, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3212(F, sep, ...) \ + Z_UTIL_LISTIFY_3211(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3211, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3213(F, sep, ...) \ + Z_UTIL_LISTIFY_3212(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3212, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3214(F, sep, ...) \ + Z_UTIL_LISTIFY_3213(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3213, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3215(F, sep, ...) \ + Z_UTIL_LISTIFY_3214(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3214, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3216(F, sep, ...) \ + Z_UTIL_LISTIFY_3215(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3215, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3217(F, sep, ...) \ + Z_UTIL_LISTIFY_3216(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3216, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3218(F, sep, ...) \ + Z_UTIL_LISTIFY_3217(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3217, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3219(F, sep, ...) \ + Z_UTIL_LISTIFY_3218(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3218, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3220(F, sep, ...) \ + Z_UTIL_LISTIFY_3219(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3219, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3221(F, sep, ...) \ + Z_UTIL_LISTIFY_3220(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3220, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3222(F, sep, ...) \ + Z_UTIL_LISTIFY_3221(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3221, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3223(F, sep, ...) \ + Z_UTIL_LISTIFY_3222(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3222, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3224(F, sep, ...) \ + Z_UTIL_LISTIFY_3223(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3223, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3225(F, sep, ...) \ + Z_UTIL_LISTIFY_3224(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3224, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3226(F, sep, ...) \ + Z_UTIL_LISTIFY_3225(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3225, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3227(F, sep, ...) \ + Z_UTIL_LISTIFY_3226(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3226, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3228(F, sep, ...) \ + Z_UTIL_LISTIFY_3227(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3227, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3229(F, sep, ...) \ + Z_UTIL_LISTIFY_3228(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3228, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3230(F, sep, ...) \ + Z_UTIL_LISTIFY_3229(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3229, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3231(F, sep, ...) \ + Z_UTIL_LISTIFY_3230(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3230, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3232(F, sep, ...) \ + Z_UTIL_LISTIFY_3231(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3231, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3233(F, sep, ...) \ + Z_UTIL_LISTIFY_3232(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3232, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3234(F, sep, ...) \ + Z_UTIL_LISTIFY_3233(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3233, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3235(F, sep, ...) \ + Z_UTIL_LISTIFY_3234(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3234, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3236(F, sep, ...) \ + Z_UTIL_LISTIFY_3235(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3235, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3237(F, sep, ...) \ + Z_UTIL_LISTIFY_3236(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3236, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3238(F, sep, ...) \ + Z_UTIL_LISTIFY_3237(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3237, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3239(F, sep, ...) \ + Z_UTIL_LISTIFY_3238(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3238, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3240(F, sep, ...) \ + Z_UTIL_LISTIFY_3239(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3239, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3241(F, sep, ...) \ + Z_UTIL_LISTIFY_3240(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3240, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3242(F, sep, ...) \ + Z_UTIL_LISTIFY_3241(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3241, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3243(F, sep, ...) \ + Z_UTIL_LISTIFY_3242(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3242, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3244(F, sep, ...) \ + Z_UTIL_LISTIFY_3243(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3243, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3245(F, sep, ...) \ + Z_UTIL_LISTIFY_3244(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3244, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3246(F, sep, ...) \ + Z_UTIL_LISTIFY_3245(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3245, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3247(F, sep, ...) \ + Z_UTIL_LISTIFY_3246(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3246, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3248(F, sep, ...) \ + Z_UTIL_LISTIFY_3247(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3247, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3249(F, sep, ...) \ + Z_UTIL_LISTIFY_3248(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3248, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3250(F, sep, ...) \ + Z_UTIL_LISTIFY_3249(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3249, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3251(F, sep, ...) \ + Z_UTIL_LISTIFY_3250(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3250, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3252(F, sep, ...) \ + Z_UTIL_LISTIFY_3251(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3251, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3253(F, sep, ...) \ + Z_UTIL_LISTIFY_3252(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3252, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3254(F, sep, ...) \ + Z_UTIL_LISTIFY_3253(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3253, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3255(F, sep, ...) \ + Z_UTIL_LISTIFY_3254(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3254, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3256(F, sep, ...) \ + Z_UTIL_LISTIFY_3255(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3255, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3257(F, sep, ...) \ + Z_UTIL_LISTIFY_3256(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3256, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3258(F, sep, ...) \ + Z_UTIL_LISTIFY_3257(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3257, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3259(F, sep, ...) \ + Z_UTIL_LISTIFY_3258(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3258, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3260(F, sep, ...) \ + Z_UTIL_LISTIFY_3259(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3259, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3261(F, sep, ...) \ + Z_UTIL_LISTIFY_3260(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3260, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3262(F, sep, ...) \ + Z_UTIL_LISTIFY_3261(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3261, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3263(F, sep, ...) \ + Z_UTIL_LISTIFY_3262(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3262, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3264(F, sep, ...) \ + Z_UTIL_LISTIFY_3263(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3263, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3265(F, sep, ...) \ + Z_UTIL_LISTIFY_3264(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3264, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3266(F, sep, ...) \ + Z_UTIL_LISTIFY_3265(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3265, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3267(F, sep, ...) \ + Z_UTIL_LISTIFY_3266(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3266, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3268(F, sep, ...) \ + Z_UTIL_LISTIFY_3267(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3267, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3269(F, sep, ...) \ + Z_UTIL_LISTIFY_3268(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3268, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3270(F, sep, ...) \ + Z_UTIL_LISTIFY_3269(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3269, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3271(F, sep, ...) \ + Z_UTIL_LISTIFY_3270(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3270, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3272(F, sep, ...) \ + Z_UTIL_LISTIFY_3271(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3271, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3273(F, sep, ...) \ + Z_UTIL_LISTIFY_3272(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3272, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3274(F, sep, ...) \ + Z_UTIL_LISTIFY_3273(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3273, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3275(F, sep, ...) \ + Z_UTIL_LISTIFY_3274(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3274, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3276(F, sep, ...) \ + Z_UTIL_LISTIFY_3275(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3275, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3277(F, sep, ...) \ + Z_UTIL_LISTIFY_3276(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3276, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3278(F, sep, ...) \ + Z_UTIL_LISTIFY_3277(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3277, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3279(F, sep, ...) \ + Z_UTIL_LISTIFY_3278(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3278, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3280(F, sep, ...) \ + Z_UTIL_LISTIFY_3279(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3279, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3281(F, sep, ...) \ + Z_UTIL_LISTIFY_3280(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3280, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3282(F, sep, ...) \ + Z_UTIL_LISTIFY_3281(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3281, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3283(F, sep, ...) \ + Z_UTIL_LISTIFY_3282(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3282, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3284(F, sep, ...) \ + Z_UTIL_LISTIFY_3283(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3283, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3285(F, sep, ...) \ + Z_UTIL_LISTIFY_3284(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3284, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3286(F, sep, ...) \ + Z_UTIL_LISTIFY_3285(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3285, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3287(F, sep, ...) \ + Z_UTIL_LISTIFY_3286(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3286, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3288(F, sep, ...) \ + Z_UTIL_LISTIFY_3287(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3287, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3289(F, sep, ...) \ + Z_UTIL_LISTIFY_3288(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3288, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3290(F, sep, ...) \ + Z_UTIL_LISTIFY_3289(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3289, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3291(F, sep, ...) \ + Z_UTIL_LISTIFY_3290(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3290, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3292(F, sep, ...) \ + Z_UTIL_LISTIFY_3291(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3291, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3293(F, sep, ...) \ + Z_UTIL_LISTIFY_3292(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3292, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3294(F, sep, ...) \ + Z_UTIL_LISTIFY_3293(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3293, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3295(F, sep, ...) \ + Z_UTIL_LISTIFY_3294(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3294, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3296(F, sep, ...) \ + Z_UTIL_LISTIFY_3295(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3295, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3297(F, sep, ...) \ + Z_UTIL_LISTIFY_3296(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3296, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3298(F, sep, ...) \ + Z_UTIL_LISTIFY_3297(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3297, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3299(F, sep, ...) \ + Z_UTIL_LISTIFY_3298(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3298, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3300(F, sep, ...) \ + Z_UTIL_LISTIFY_3299(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3299, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3301(F, sep, ...) \ + Z_UTIL_LISTIFY_3300(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3300, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3302(F, sep, ...) \ + Z_UTIL_LISTIFY_3301(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3301, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3303(F, sep, ...) \ + Z_UTIL_LISTIFY_3302(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3302, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3304(F, sep, ...) \ + Z_UTIL_LISTIFY_3303(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3303, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3305(F, sep, ...) \ + Z_UTIL_LISTIFY_3304(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3304, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3306(F, sep, ...) \ + Z_UTIL_LISTIFY_3305(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3305, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3307(F, sep, ...) \ + Z_UTIL_LISTIFY_3306(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3306, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3308(F, sep, ...) \ + Z_UTIL_LISTIFY_3307(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3307, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3309(F, sep, ...) \ + Z_UTIL_LISTIFY_3308(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3308, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3310(F, sep, ...) \ + Z_UTIL_LISTIFY_3309(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3309, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3311(F, sep, ...) \ + Z_UTIL_LISTIFY_3310(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3310, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3312(F, sep, ...) \ + Z_UTIL_LISTIFY_3311(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3311, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3313(F, sep, ...) \ + Z_UTIL_LISTIFY_3312(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3312, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3314(F, sep, ...) \ + Z_UTIL_LISTIFY_3313(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3313, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3315(F, sep, ...) \ + Z_UTIL_LISTIFY_3314(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3314, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3316(F, sep, ...) \ + Z_UTIL_LISTIFY_3315(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3315, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3317(F, sep, ...) \ + Z_UTIL_LISTIFY_3316(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3316, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3318(F, sep, ...) \ + Z_UTIL_LISTIFY_3317(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3317, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3319(F, sep, ...) \ + Z_UTIL_LISTIFY_3318(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3318, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3320(F, sep, ...) \ + Z_UTIL_LISTIFY_3319(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3319, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3321(F, sep, ...) \ + Z_UTIL_LISTIFY_3320(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3320, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3322(F, sep, ...) \ + Z_UTIL_LISTIFY_3321(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3321, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3323(F, sep, ...) \ + Z_UTIL_LISTIFY_3322(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3322, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3324(F, sep, ...) \ + Z_UTIL_LISTIFY_3323(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3323, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3325(F, sep, ...) \ + Z_UTIL_LISTIFY_3324(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3324, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3326(F, sep, ...) \ + Z_UTIL_LISTIFY_3325(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3325, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3327(F, sep, ...) \ + Z_UTIL_LISTIFY_3326(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3326, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3328(F, sep, ...) \ + Z_UTIL_LISTIFY_3327(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3327, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3329(F, sep, ...) \ + Z_UTIL_LISTIFY_3328(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3328, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3330(F, sep, ...) \ + Z_UTIL_LISTIFY_3329(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3329, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3331(F, sep, ...) \ + Z_UTIL_LISTIFY_3330(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3330, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3332(F, sep, ...) \ + Z_UTIL_LISTIFY_3331(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3331, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3333(F, sep, ...) \ + Z_UTIL_LISTIFY_3332(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3332, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3334(F, sep, ...) \ + Z_UTIL_LISTIFY_3333(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3333, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3335(F, sep, ...) \ + Z_UTIL_LISTIFY_3334(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3334, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3336(F, sep, ...) \ + Z_UTIL_LISTIFY_3335(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3335, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3337(F, sep, ...) \ + Z_UTIL_LISTIFY_3336(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3336, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3338(F, sep, ...) \ + Z_UTIL_LISTIFY_3337(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3337, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3339(F, sep, ...) \ + Z_UTIL_LISTIFY_3338(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3338, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3340(F, sep, ...) \ + Z_UTIL_LISTIFY_3339(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3339, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3341(F, sep, ...) \ + Z_UTIL_LISTIFY_3340(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3340, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3342(F, sep, ...) \ + Z_UTIL_LISTIFY_3341(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3341, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3343(F, sep, ...) \ + Z_UTIL_LISTIFY_3342(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3342, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3344(F, sep, ...) \ + Z_UTIL_LISTIFY_3343(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3343, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3345(F, sep, ...) \ + Z_UTIL_LISTIFY_3344(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3344, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3346(F, sep, ...) \ + Z_UTIL_LISTIFY_3345(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3345, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3347(F, sep, ...) \ + Z_UTIL_LISTIFY_3346(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3346, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3348(F, sep, ...) \ + Z_UTIL_LISTIFY_3347(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3347, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3349(F, sep, ...) \ + Z_UTIL_LISTIFY_3348(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3348, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3350(F, sep, ...) \ + Z_UTIL_LISTIFY_3349(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3349, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3351(F, sep, ...) \ + Z_UTIL_LISTIFY_3350(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3350, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3352(F, sep, ...) \ + Z_UTIL_LISTIFY_3351(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3351, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3353(F, sep, ...) \ + Z_UTIL_LISTIFY_3352(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3352, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3354(F, sep, ...) \ + Z_UTIL_LISTIFY_3353(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3353, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3355(F, sep, ...) \ + Z_UTIL_LISTIFY_3354(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3354, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3356(F, sep, ...) \ + Z_UTIL_LISTIFY_3355(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3355, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3357(F, sep, ...) \ + Z_UTIL_LISTIFY_3356(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3356, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3358(F, sep, ...) \ + Z_UTIL_LISTIFY_3357(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3357, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3359(F, sep, ...) \ + Z_UTIL_LISTIFY_3358(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3358, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3360(F, sep, ...) \ + Z_UTIL_LISTIFY_3359(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3359, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3361(F, sep, ...) \ + Z_UTIL_LISTIFY_3360(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3360, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3362(F, sep, ...) \ + Z_UTIL_LISTIFY_3361(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3361, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3363(F, sep, ...) \ + Z_UTIL_LISTIFY_3362(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3362, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3364(F, sep, ...) \ + Z_UTIL_LISTIFY_3363(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3363, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3365(F, sep, ...) \ + Z_UTIL_LISTIFY_3364(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3364, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3366(F, sep, ...) \ + Z_UTIL_LISTIFY_3365(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3365, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3367(F, sep, ...) \ + Z_UTIL_LISTIFY_3366(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3366, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3368(F, sep, ...) \ + Z_UTIL_LISTIFY_3367(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3367, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3369(F, sep, ...) \ + Z_UTIL_LISTIFY_3368(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3368, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3370(F, sep, ...) \ + Z_UTIL_LISTIFY_3369(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3369, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3371(F, sep, ...) \ + Z_UTIL_LISTIFY_3370(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3370, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3372(F, sep, ...) \ + Z_UTIL_LISTIFY_3371(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3371, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3373(F, sep, ...) \ + Z_UTIL_LISTIFY_3372(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3372, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3374(F, sep, ...) \ + Z_UTIL_LISTIFY_3373(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3373, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3375(F, sep, ...) \ + Z_UTIL_LISTIFY_3374(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3374, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3376(F, sep, ...) \ + Z_UTIL_LISTIFY_3375(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3375, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3377(F, sep, ...) \ + Z_UTIL_LISTIFY_3376(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3376, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3378(F, sep, ...) \ + Z_UTIL_LISTIFY_3377(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3377, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3379(F, sep, ...) \ + Z_UTIL_LISTIFY_3378(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3378, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3380(F, sep, ...) \ + Z_UTIL_LISTIFY_3379(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3379, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3381(F, sep, ...) \ + Z_UTIL_LISTIFY_3380(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3380, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3382(F, sep, ...) \ + Z_UTIL_LISTIFY_3381(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3381, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3383(F, sep, ...) \ + Z_UTIL_LISTIFY_3382(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3382, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3384(F, sep, ...) \ + Z_UTIL_LISTIFY_3383(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3383, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3385(F, sep, ...) \ + Z_UTIL_LISTIFY_3384(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3384, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3386(F, sep, ...) \ + Z_UTIL_LISTIFY_3385(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3385, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3387(F, sep, ...) \ + Z_UTIL_LISTIFY_3386(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3386, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3388(F, sep, ...) \ + Z_UTIL_LISTIFY_3387(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3387, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3389(F, sep, ...) \ + Z_UTIL_LISTIFY_3388(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3388, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3390(F, sep, ...) \ + Z_UTIL_LISTIFY_3389(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3389, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3391(F, sep, ...) \ + Z_UTIL_LISTIFY_3390(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3390, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3392(F, sep, ...) \ + Z_UTIL_LISTIFY_3391(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3391, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3393(F, sep, ...) \ + Z_UTIL_LISTIFY_3392(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3392, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3394(F, sep, ...) \ + Z_UTIL_LISTIFY_3393(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3393, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3395(F, sep, ...) \ + Z_UTIL_LISTIFY_3394(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3394, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3396(F, sep, ...) \ + Z_UTIL_LISTIFY_3395(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3395, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3397(F, sep, ...) \ + Z_UTIL_LISTIFY_3396(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3396, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3398(F, sep, ...) \ + Z_UTIL_LISTIFY_3397(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3397, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3399(F, sep, ...) \ + Z_UTIL_LISTIFY_3398(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3398, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3400(F, sep, ...) \ + Z_UTIL_LISTIFY_3399(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3399, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3401(F, sep, ...) \ + Z_UTIL_LISTIFY_3400(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3400, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3402(F, sep, ...) \ + Z_UTIL_LISTIFY_3401(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3401, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3403(F, sep, ...) \ + Z_UTIL_LISTIFY_3402(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3402, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3404(F, sep, ...) \ + Z_UTIL_LISTIFY_3403(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3403, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3405(F, sep, ...) \ + Z_UTIL_LISTIFY_3404(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3404, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3406(F, sep, ...) \ + Z_UTIL_LISTIFY_3405(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3405, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3407(F, sep, ...) \ + Z_UTIL_LISTIFY_3406(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3406, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3408(F, sep, ...) \ + Z_UTIL_LISTIFY_3407(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3407, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3409(F, sep, ...) \ + Z_UTIL_LISTIFY_3408(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3408, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3410(F, sep, ...) \ + Z_UTIL_LISTIFY_3409(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3409, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3411(F, sep, ...) \ + Z_UTIL_LISTIFY_3410(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3410, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3412(F, sep, ...) \ + Z_UTIL_LISTIFY_3411(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3411, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3413(F, sep, ...) \ + Z_UTIL_LISTIFY_3412(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3412, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3414(F, sep, ...) \ + Z_UTIL_LISTIFY_3413(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3413, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3415(F, sep, ...) \ + Z_UTIL_LISTIFY_3414(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3414, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3416(F, sep, ...) \ + Z_UTIL_LISTIFY_3415(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3415, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3417(F, sep, ...) \ + Z_UTIL_LISTIFY_3416(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3416, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3418(F, sep, ...) \ + Z_UTIL_LISTIFY_3417(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3417, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3419(F, sep, ...) \ + Z_UTIL_LISTIFY_3418(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3418, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3420(F, sep, ...) \ + Z_UTIL_LISTIFY_3419(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3419, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3421(F, sep, ...) \ + Z_UTIL_LISTIFY_3420(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3420, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3422(F, sep, ...) \ + Z_UTIL_LISTIFY_3421(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3421, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3423(F, sep, ...) \ + Z_UTIL_LISTIFY_3422(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3422, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3424(F, sep, ...) \ + Z_UTIL_LISTIFY_3423(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3423, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3425(F, sep, ...) \ + Z_UTIL_LISTIFY_3424(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3424, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3426(F, sep, ...) \ + Z_UTIL_LISTIFY_3425(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3425, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3427(F, sep, ...) \ + Z_UTIL_LISTIFY_3426(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3426, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3428(F, sep, ...) \ + Z_UTIL_LISTIFY_3427(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3427, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3429(F, sep, ...) \ + Z_UTIL_LISTIFY_3428(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3428, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3430(F, sep, ...) \ + Z_UTIL_LISTIFY_3429(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3429, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3431(F, sep, ...) \ + Z_UTIL_LISTIFY_3430(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3430, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3432(F, sep, ...) \ + Z_UTIL_LISTIFY_3431(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3431, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3433(F, sep, ...) \ + Z_UTIL_LISTIFY_3432(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3432, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3434(F, sep, ...) \ + Z_UTIL_LISTIFY_3433(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3433, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3435(F, sep, ...) \ + Z_UTIL_LISTIFY_3434(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3434, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3436(F, sep, ...) \ + Z_UTIL_LISTIFY_3435(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3435, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3437(F, sep, ...) \ + Z_UTIL_LISTIFY_3436(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3436, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3438(F, sep, ...) \ + Z_UTIL_LISTIFY_3437(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3437, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3439(F, sep, ...) \ + Z_UTIL_LISTIFY_3438(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3438, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3440(F, sep, ...) \ + Z_UTIL_LISTIFY_3439(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3439, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3441(F, sep, ...) \ + Z_UTIL_LISTIFY_3440(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3440, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3442(F, sep, ...) \ + Z_UTIL_LISTIFY_3441(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3441, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3443(F, sep, ...) \ + Z_UTIL_LISTIFY_3442(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3442, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3444(F, sep, ...) \ + Z_UTIL_LISTIFY_3443(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3443, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3445(F, sep, ...) \ + Z_UTIL_LISTIFY_3444(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3444, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3446(F, sep, ...) \ + Z_UTIL_LISTIFY_3445(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3445, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3447(F, sep, ...) \ + Z_UTIL_LISTIFY_3446(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3446, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3448(F, sep, ...) \ + Z_UTIL_LISTIFY_3447(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3447, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3449(F, sep, ...) \ + Z_UTIL_LISTIFY_3448(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3448, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3450(F, sep, ...) \ + Z_UTIL_LISTIFY_3449(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3449, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3451(F, sep, ...) \ + Z_UTIL_LISTIFY_3450(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3450, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3452(F, sep, ...) \ + Z_UTIL_LISTIFY_3451(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3451, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3453(F, sep, ...) \ + Z_UTIL_LISTIFY_3452(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3452, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3454(F, sep, ...) \ + Z_UTIL_LISTIFY_3453(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3453, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3455(F, sep, ...) \ + Z_UTIL_LISTIFY_3454(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3454, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3456(F, sep, ...) \ + Z_UTIL_LISTIFY_3455(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3455, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3457(F, sep, ...) \ + Z_UTIL_LISTIFY_3456(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3456, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3458(F, sep, ...) \ + Z_UTIL_LISTIFY_3457(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3457, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3459(F, sep, ...) \ + Z_UTIL_LISTIFY_3458(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3458, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3460(F, sep, ...) \ + Z_UTIL_LISTIFY_3459(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3459, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3461(F, sep, ...) \ + Z_UTIL_LISTIFY_3460(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3460, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3462(F, sep, ...) \ + Z_UTIL_LISTIFY_3461(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3461, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3463(F, sep, ...) \ + Z_UTIL_LISTIFY_3462(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3462, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3464(F, sep, ...) \ + Z_UTIL_LISTIFY_3463(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3463, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3465(F, sep, ...) \ + Z_UTIL_LISTIFY_3464(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3464, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3466(F, sep, ...) \ + Z_UTIL_LISTIFY_3465(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3465, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3467(F, sep, ...) \ + Z_UTIL_LISTIFY_3466(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3466, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3468(F, sep, ...) \ + Z_UTIL_LISTIFY_3467(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3467, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3469(F, sep, ...) \ + Z_UTIL_LISTIFY_3468(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3468, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3470(F, sep, ...) \ + Z_UTIL_LISTIFY_3469(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3469, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3471(F, sep, ...) \ + Z_UTIL_LISTIFY_3470(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3470, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3472(F, sep, ...) \ + Z_UTIL_LISTIFY_3471(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3471, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3473(F, sep, ...) \ + Z_UTIL_LISTIFY_3472(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3472, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3474(F, sep, ...) \ + Z_UTIL_LISTIFY_3473(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3473, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3475(F, sep, ...) \ + Z_UTIL_LISTIFY_3474(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3474, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3476(F, sep, ...) \ + Z_UTIL_LISTIFY_3475(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3475, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3477(F, sep, ...) \ + Z_UTIL_LISTIFY_3476(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3476, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3478(F, sep, ...) \ + Z_UTIL_LISTIFY_3477(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3477, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3479(F, sep, ...) \ + Z_UTIL_LISTIFY_3478(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3478, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3480(F, sep, ...) \ + Z_UTIL_LISTIFY_3479(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3479, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3481(F, sep, ...) \ + Z_UTIL_LISTIFY_3480(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3480, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3482(F, sep, ...) \ + Z_UTIL_LISTIFY_3481(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3481, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3483(F, sep, ...) \ + Z_UTIL_LISTIFY_3482(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3482, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3484(F, sep, ...) \ + Z_UTIL_LISTIFY_3483(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3483, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3485(F, sep, ...) \ + Z_UTIL_LISTIFY_3484(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3484, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3486(F, sep, ...) \ + Z_UTIL_LISTIFY_3485(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3485, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3487(F, sep, ...) \ + Z_UTIL_LISTIFY_3486(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3486, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3488(F, sep, ...) \ + Z_UTIL_LISTIFY_3487(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3487, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3489(F, sep, ...) \ + Z_UTIL_LISTIFY_3488(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3488, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3490(F, sep, ...) \ + Z_UTIL_LISTIFY_3489(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3489, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3491(F, sep, ...) \ + Z_UTIL_LISTIFY_3490(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3490, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3492(F, sep, ...) \ + Z_UTIL_LISTIFY_3491(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3491, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3493(F, sep, ...) \ + Z_UTIL_LISTIFY_3492(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3492, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3494(F, sep, ...) \ + Z_UTIL_LISTIFY_3493(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3493, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3495(F, sep, ...) \ + Z_UTIL_LISTIFY_3494(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3494, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3496(F, sep, ...) \ + Z_UTIL_LISTIFY_3495(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3495, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3497(F, sep, ...) \ + Z_UTIL_LISTIFY_3496(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3496, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3498(F, sep, ...) \ + Z_UTIL_LISTIFY_3497(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3497, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3499(F, sep, ...) \ + Z_UTIL_LISTIFY_3498(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3498, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3500(F, sep, ...) \ + Z_UTIL_LISTIFY_3499(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3499, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3501(F, sep, ...) \ + Z_UTIL_LISTIFY_3500(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3500, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3502(F, sep, ...) \ + Z_UTIL_LISTIFY_3501(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3501, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3503(F, sep, ...) \ + Z_UTIL_LISTIFY_3502(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3502, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3504(F, sep, ...) \ + Z_UTIL_LISTIFY_3503(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3503, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3505(F, sep, ...) \ + Z_UTIL_LISTIFY_3504(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3504, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3506(F, sep, ...) \ + Z_UTIL_LISTIFY_3505(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3505, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3507(F, sep, ...) \ + Z_UTIL_LISTIFY_3506(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3506, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3508(F, sep, ...) \ + Z_UTIL_LISTIFY_3507(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3507, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3509(F, sep, ...) \ + Z_UTIL_LISTIFY_3508(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3508, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3510(F, sep, ...) \ + Z_UTIL_LISTIFY_3509(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3509, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3511(F, sep, ...) \ + Z_UTIL_LISTIFY_3510(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3510, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3512(F, sep, ...) \ + Z_UTIL_LISTIFY_3511(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3511, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3513(F, sep, ...) \ + Z_UTIL_LISTIFY_3512(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3512, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3514(F, sep, ...) \ + Z_UTIL_LISTIFY_3513(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3513, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3515(F, sep, ...) \ + Z_UTIL_LISTIFY_3514(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3514, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3516(F, sep, ...) \ + Z_UTIL_LISTIFY_3515(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3515, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3517(F, sep, ...) \ + Z_UTIL_LISTIFY_3516(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3516, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3518(F, sep, ...) \ + Z_UTIL_LISTIFY_3517(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3517, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3519(F, sep, ...) \ + Z_UTIL_LISTIFY_3518(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3518, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3520(F, sep, ...) \ + Z_UTIL_LISTIFY_3519(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3519, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3521(F, sep, ...) \ + Z_UTIL_LISTIFY_3520(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3520, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3522(F, sep, ...) \ + Z_UTIL_LISTIFY_3521(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3521, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3523(F, sep, ...) \ + Z_UTIL_LISTIFY_3522(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3522, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3524(F, sep, ...) \ + Z_UTIL_LISTIFY_3523(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3523, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3525(F, sep, ...) \ + Z_UTIL_LISTIFY_3524(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3524, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3526(F, sep, ...) \ + Z_UTIL_LISTIFY_3525(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3525, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3527(F, sep, ...) \ + Z_UTIL_LISTIFY_3526(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3526, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3528(F, sep, ...) \ + Z_UTIL_LISTIFY_3527(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3527, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3529(F, sep, ...) \ + Z_UTIL_LISTIFY_3528(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3528, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3530(F, sep, ...) \ + Z_UTIL_LISTIFY_3529(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3529, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3531(F, sep, ...) \ + Z_UTIL_LISTIFY_3530(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3530, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3532(F, sep, ...) \ + Z_UTIL_LISTIFY_3531(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3531, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3533(F, sep, ...) \ + Z_UTIL_LISTIFY_3532(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3532, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3534(F, sep, ...) \ + Z_UTIL_LISTIFY_3533(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3533, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3535(F, sep, ...) \ + Z_UTIL_LISTIFY_3534(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3534, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3536(F, sep, ...) \ + Z_UTIL_LISTIFY_3535(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3535, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3537(F, sep, ...) \ + Z_UTIL_LISTIFY_3536(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3536, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3538(F, sep, ...) \ + Z_UTIL_LISTIFY_3537(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3537, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3539(F, sep, ...) \ + Z_UTIL_LISTIFY_3538(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3538, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3540(F, sep, ...) \ + Z_UTIL_LISTIFY_3539(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3539, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3541(F, sep, ...) \ + Z_UTIL_LISTIFY_3540(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3540, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3542(F, sep, ...) \ + Z_UTIL_LISTIFY_3541(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3541, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3543(F, sep, ...) \ + Z_UTIL_LISTIFY_3542(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3542, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3544(F, sep, ...) \ + Z_UTIL_LISTIFY_3543(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3543, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3545(F, sep, ...) \ + Z_UTIL_LISTIFY_3544(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3544, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3546(F, sep, ...) \ + Z_UTIL_LISTIFY_3545(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3545, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3547(F, sep, ...) \ + Z_UTIL_LISTIFY_3546(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3546, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3548(F, sep, ...) \ + Z_UTIL_LISTIFY_3547(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3547, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3549(F, sep, ...) \ + Z_UTIL_LISTIFY_3548(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3548, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3550(F, sep, ...) \ + Z_UTIL_LISTIFY_3549(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3549, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3551(F, sep, ...) \ + Z_UTIL_LISTIFY_3550(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3550, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3552(F, sep, ...) \ + Z_UTIL_LISTIFY_3551(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3551, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3553(F, sep, ...) \ + Z_UTIL_LISTIFY_3552(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3552, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3554(F, sep, ...) \ + Z_UTIL_LISTIFY_3553(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3553, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3555(F, sep, ...) \ + Z_UTIL_LISTIFY_3554(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3554, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3556(F, sep, ...) \ + Z_UTIL_LISTIFY_3555(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3555, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3557(F, sep, ...) \ + Z_UTIL_LISTIFY_3556(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3556, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3558(F, sep, ...) \ + Z_UTIL_LISTIFY_3557(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3557, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3559(F, sep, ...) \ + Z_UTIL_LISTIFY_3558(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3558, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3560(F, sep, ...) \ + Z_UTIL_LISTIFY_3559(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3559, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3561(F, sep, ...) \ + Z_UTIL_LISTIFY_3560(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3560, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3562(F, sep, ...) \ + Z_UTIL_LISTIFY_3561(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3561, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3563(F, sep, ...) \ + Z_UTIL_LISTIFY_3562(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3562, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3564(F, sep, ...) \ + Z_UTIL_LISTIFY_3563(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3563, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3565(F, sep, ...) \ + Z_UTIL_LISTIFY_3564(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3564, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3566(F, sep, ...) \ + Z_UTIL_LISTIFY_3565(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3565, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3567(F, sep, ...) \ + Z_UTIL_LISTIFY_3566(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3566, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3568(F, sep, ...) \ + Z_UTIL_LISTIFY_3567(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3567, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3569(F, sep, ...) \ + Z_UTIL_LISTIFY_3568(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3568, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3570(F, sep, ...) \ + Z_UTIL_LISTIFY_3569(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3569, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3571(F, sep, ...) \ + Z_UTIL_LISTIFY_3570(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3570, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3572(F, sep, ...) \ + Z_UTIL_LISTIFY_3571(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3571, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3573(F, sep, ...) \ + Z_UTIL_LISTIFY_3572(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3572, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3574(F, sep, ...) \ + Z_UTIL_LISTIFY_3573(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3573, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3575(F, sep, ...) \ + Z_UTIL_LISTIFY_3574(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3574, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3576(F, sep, ...) \ + Z_UTIL_LISTIFY_3575(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3575, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3577(F, sep, ...) \ + Z_UTIL_LISTIFY_3576(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3576, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3578(F, sep, ...) \ + Z_UTIL_LISTIFY_3577(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3577, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3579(F, sep, ...) \ + Z_UTIL_LISTIFY_3578(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3578, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3580(F, sep, ...) \ + Z_UTIL_LISTIFY_3579(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3579, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3581(F, sep, ...) \ + Z_UTIL_LISTIFY_3580(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3580, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3582(F, sep, ...) \ + Z_UTIL_LISTIFY_3581(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3581, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3583(F, sep, ...) \ + Z_UTIL_LISTIFY_3582(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3582, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3584(F, sep, ...) \ + Z_UTIL_LISTIFY_3583(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3583, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3585(F, sep, ...) \ + Z_UTIL_LISTIFY_3584(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3584, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3586(F, sep, ...) \ + Z_UTIL_LISTIFY_3585(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3585, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3587(F, sep, ...) \ + Z_UTIL_LISTIFY_3586(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3586, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3588(F, sep, ...) \ + Z_UTIL_LISTIFY_3587(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3587, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3589(F, sep, ...) \ + Z_UTIL_LISTIFY_3588(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3588, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3590(F, sep, ...) \ + Z_UTIL_LISTIFY_3589(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3589, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3591(F, sep, ...) \ + Z_UTIL_LISTIFY_3590(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3590, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3592(F, sep, ...) \ + Z_UTIL_LISTIFY_3591(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3591, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3593(F, sep, ...) \ + Z_UTIL_LISTIFY_3592(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3592, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3594(F, sep, ...) \ + Z_UTIL_LISTIFY_3593(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3593, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3595(F, sep, ...) \ + Z_UTIL_LISTIFY_3594(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3594, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3596(F, sep, ...) \ + Z_UTIL_LISTIFY_3595(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3595, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3597(F, sep, ...) \ + Z_UTIL_LISTIFY_3596(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3596, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3598(F, sep, ...) \ + Z_UTIL_LISTIFY_3597(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3597, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3599(F, sep, ...) \ + Z_UTIL_LISTIFY_3598(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3598, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3600(F, sep, ...) \ + Z_UTIL_LISTIFY_3599(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3599, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3601(F, sep, ...) \ + Z_UTIL_LISTIFY_3600(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3600, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3602(F, sep, ...) \ + Z_UTIL_LISTIFY_3601(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3601, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3603(F, sep, ...) \ + Z_UTIL_LISTIFY_3602(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3602, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3604(F, sep, ...) \ + Z_UTIL_LISTIFY_3603(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3603, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3605(F, sep, ...) \ + Z_UTIL_LISTIFY_3604(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3604, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3606(F, sep, ...) \ + Z_UTIL_LISTIFY_3605(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3605, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3607(F, sep, ...) \ + Z_UTIL_LISTIFY_3606(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3606, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3608(F, sep, ...) \ + Z_UTIL_LISTIFY_3607(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3607, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3609(F, sep, ...) \ + Z_UTIL_LISTIFY_3608(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3608, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3610(F, sep, ...) \ + Z_UTIL_LISTIFY_3609(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3609, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3611(F, sep, ...) \ + Z_UTIL_LISTIFY_3610(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3610, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3612(F, sep, ...) \ + Z_UTIL_LISTIFY_3611(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3611, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3613(F, sep, ...) \ + Z_UTIL_LISTIFY_3612(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3612, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3614(F, sep, ...) \ + Z_UTIL_LISTIFY_3613(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3613, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3615(F, sep, ...) \ + Z_UTIL_LISTIFY_3614(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3614, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3616(F, sep, ...) \ + Z_UTIL_LISTIFY_3615(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3615, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3617(F, sep, ...) \ + Z_UTIL_LISTIFY_3616(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3616, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3618(F, sep, ...) \ + Z_UTIL_LISTIFY_3617(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3617, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3619(F, sep, ...) \ + Z_UTIL_LISTIFY_3618(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3618, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3620(F, sep, ...) \ + Z_UTIL_LISTIFY_3619(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3619, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3621(F, sep, ...) \ + Z_UTIL_LISTIFY_3620(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3620, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3622(F, sep, ...) \ + Z_UTIL_LISTIFY_3621(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3621, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3623(F, sep, ...) \ + Z_UTIL_LISTIFY_3622(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3622, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3624(F, sep, ...) \ + Z_UTIL_LISTIFY_3623(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3623, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3625(F, sep, ...) \ + Z_UTIL_LISTIFY_3624(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3624, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3626(F, sep, ...) \ + Z_UTIL_LISTIFY_3625(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3625, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3627(F, sep, ...) \ + Z_UTIL_LISTIFY_3626(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3626, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3628(F, sep, ...) \ + Z_UTIL_LISTIFY_3627(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3627, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3629(F, sep, ...) \ + Z_UTIL_LISTIFY_3628(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3628, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3630(F, sep, ...) \ + Z_UTIL_LISTIFY_3629(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3629, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3631(F, sep, ...) \ + Z_UTIL_LISTIFY_3630(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3630, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3632(F, sep, ...) \ + Z_UTIL_LISTIFY_3631(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3631, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3633(F, sep, ...) \ + Z_UTIL_LISTIFY_3632(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3632, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3634(F, sep, ...) \ + Z_UTIL_LISTIFY_3633(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3633, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3635(F, sep, ...) \ + Z_UTIL_LISTIFY_3634(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3634, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3636(F, sep, ...) \ + Z_UTIL_LISTIFY_3635(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3635, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3637(F, sep, ...) \ + Z_UTIL_LISTIFY_3636(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3636, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3638(F, sep, ...) \ + Z_UTIL_LISTIFY_3637(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3637, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3639(F, sep, ...) \ + Z_UTIL_LISTIFY_3638(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3638, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3640(F, sep, ...) \ + Z_UTIL_LISTIFY_3639(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3639, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3641(F, sep, ...) \ + Z_UTIL_LISTIFY_3640(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3640, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3642(F, sep, ...) \ + Z_UTIL_LISTIFY_3641(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3641, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3643(F, sep, ...) \ + Z_UTIL_LISTIFY_3642(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3642, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3644(F, sep, ...) \ + Z_UTIL_LISTIFY_3643(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3643, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3645(F, sep, ...) \ + Z_UTIL_LISTIFY_3644(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3644, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3646(F, sep, ...) \ + Z_UTIL_LISTIFY_3645(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3645, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3647(F, sep, ...) \ + Z_UTIL_LISTIFY_3646(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3646, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3648(F, sep, ...) \ + Z_UTIL_LISTIFY_3647(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3647, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3649(F, sep, ...) \ + Z_UTIL_LISTIFY_3648(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3648, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3650(F, sep, ...) \ + Z_UTIL_LISTIFY_3649(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3649, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3651(F, sep, ...) \ + Z_UTIL_LISTIFY_3650(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3650, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3652(F, sep, ...) \ + Z_UTIL_LISTIFY_3651(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3651, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3653(F, sep, ...) \ + Z_UTIL_LISTIFY_3652(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3652, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3654(F, sep, ...) \ + Z_UTIL_LISTIFY_3653(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3653, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3655(F, sep, ...) \ + Z_UTIL_LISTIFY_3654(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3654, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3656(F, sep, ...) \ + Z_UTIL_LISTIFY_3655(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3655, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3657(F, sep, ...) \ + Z_UTIL_LISTIFY_3656(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3656, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3658(F, sep, ...) \ + Z_UTIL_LISTIFY_3657(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3657, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3659(F, sep, ...) \ + Z_UTIL_LISTIFY_3658(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3658, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3660(F, sep, ...) \ + Z_UTIL_LISTIFY_3659(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3659, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3661(F, sep, ...) \ + Z_UTIL_LISTIFY_3660(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3660, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3662(F, sep, ...) \ + Z_UTIL_LISTIFY_3661(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3661, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3663(F, sep, ...) \ + Z_UTIL_LISTIFY_3662(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3662, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3664(F, sep, ...) \ + Z_UTIL_LISTIFY_3663(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3663, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3665(F, sep, ...) \ + Z_UTIL_LISTIFY_3664(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3664, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3666(F, sep, ...) \ + Z_UTIL_LISTIFY_3665(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3665, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3667(F, sep, ...) \ + Z_UTIL_LISTIFY_3666(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3666, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3668(F, sep, ...) \ + Z_UTIL_LISTIFY_3667(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3667, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3669(F, sep, ...) \ + Z_UTIL_LISTIFY_3668(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3668, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3670(F, sep, ...) \ + Z_UTIL_LISTIFY_3669(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3669, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3671(F, sep, ...) \ + Z_UTIL_LISTIFY_3670(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3670, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3672(F, sep, ...) \ + Z_UTIL_LISTIFY_3671(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3671, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3673(F, sep, ...) \ + Z_UTIL_LISTIFY_3672(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3672, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3674(F, sep, ...) \ + Z_UTIL_LISTIFY_3673(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3673, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3675(F, sep, ...) \ + Z_UTIL_LISTIFY_3674(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3674, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3676(F, sep, ...) \ + Z_UTIL_LISTIFY_3675(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3675, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3677(F, sep, ...) \ + Z_UTIL_LISTIFY_3676(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3676, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3678(F, sep, ...) \ + Z_UTIL_LISTIFY_3677(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3677, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3679(F, sep, ...) \ + Z_UTIL_LISTIFY_3678(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3678, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3680(F, sep, ...) \ + Z_UTIL_LISTIFY_3679(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3679, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3681(F, sep, ...) \ + Z_UTIL_LISTIFY_3680(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3680, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3682(F, sep, ...) \ + Z_UTIL_LISTIFY_3681(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3681, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3683(F, sep, ...) \ + Z_UTIL_LISTIFY_3682(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3682, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3684(F, sep, ...) \ + Z_UTIL_LISTIFY_3683(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3683, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3685(F, sep, ...) \ + Z_UTIL_LISTIFY_3684(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3684, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3686(F, sep, ...) \ + Z_UTIL_LISTIFY_3685(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3685, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3687(F, sep, ...) \ + Z_UTIL_LISTIFY_3686(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3686, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3688(F, sep, ...) \ + Z_UTIL_LISTIFY_3687(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3687, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3689(F, sep, ...) \ + Z_UTIL_LISTIFY_3688(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3688, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3690(F, sep, ...) \ + Z_UTIL_LISTIFY_3689(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3689, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3691(F, sep, ...) \ + Z_UTIL_LISTIFY_3690(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3690, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3692(F, sep, ...) \ + Z_UTIL_LISTIFY_3691(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3691, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3693(F, sep, ...) \ + Z_UTIL_LISTIFY_3692(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3692, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3694(F, sep, ...) \ + Z_UTIL_LISTIFY_3693(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3693, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3695(F, sep, ...) \ + Z_UTIL_LISTIFY_3694(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3694, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3696(F, sep, ...) \ + Z_UTIL_LISTIFY_3695(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3695, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3697(F, sep, ...) \ + Z_UTIL_LISTIFY_3696(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3696, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3698(F, sep, ...) \ + Z_UTIL_LISTIFY_3697(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3697, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3699(F, sep, ...) \ + Z_UTIL_LISTIFY_3698(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3698, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3700(F, sep, ...) \ + Z_UTIL_LISTIFY_3699(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3699, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3701(F, sep, ...) \ + Z_UTIL_LISTIFY_3700(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3700, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3702(F, sep, ...) \ + Z_UTIL_LISTIFY_3701(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3701, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3703(F, sep, ...) \ + Z_UTIL_LISTIFY_3702(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3702, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3704(F, sep, ...) \ + Z_UTIL_LISTIFY_3703(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3703, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3705(F, sep, ...) \ + Z_UTIL_LISTIFY_3704(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3704, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3706(F, sep, ...) \ + Z_UTIL_LISTIFY_3705(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3705, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3707(F, sep, ...) \ + Z_UTIL_LISTIFY_3706(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3706, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3708(F, sep, ...) \ + Z_UTIL_LISTIFY_3707(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3707, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3709(F, sep, ...) \ + Z_UTIL_LISTIFY_3708(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3708, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3710(F, sep, ...) \ + Z_UTIL_LISTIFY_3709(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3709, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3711(F, sep, ...) \ + Z_UTIL_LISTIFY_3710(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3710, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3712(F, sep, ...) \ + Z_UTIL_LISTIFY_3711(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3711, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3713(F, sep, ...) \ + Z_UTIL_LISTIFY_3712(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3712, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3714(F, sep, ...) \ + Z_UTIL_LISTIFY_3713(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3713, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3715(F, sep, ...) \ + Z_UTIL_LISTIFY_3714(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3714, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3716(F, sep, ...) \ + Z_UTIL_LISTIFY_3715(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3715, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3717(F, sep, ...) \ + Z_UTIL_LISTIFY_3716(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3716, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3718(F, sep, ...) \ + Z_UTIL_LISTIFY_3717(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3717, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3719(F, sep, ...) \ + Z_UTIL_LISTIFY_3718(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3718, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3720(F, sep, ...) \ + Z_UTIL_LISTIFY_3719(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3719, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3721(F, sep, ...) \ + Z_UTIL_LISTIFY_3720(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3720, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3722(F, sep, ...) \ + Z_UTIL_LISTIFY_3721(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3721, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3723(F, sep, ...) \ + Z_UTIL_LISTIFY_3722(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3722, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3724(F, sep, ...) \ + Z_UTIL_LISTIFY_3723(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3723, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3725(F, sep, ...) \ + Z_UTIL_LISTIFY_3724(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3724, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3726(F, sep, ...) \ + Z_UTIL_LISTIFY_3725(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3725, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3727(F, sep, ...) \ + Z_UTIL_LISTIFY_3726(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3726, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3728(F, sep, ...) \ + Z_UTIL_LISTIFY_3727(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3727, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3729(F, sep, ...) \ + Z_UTIL_LISTIFY_3728(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3728, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3730(F, sep, ...) \ + Z_UTIL_LISTIFY_3729(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3729, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3731(F, sep, ...) \ + Z_UTIL_LISTIFY_3730(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3730, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3732(F, sep, ...) \ + Z_UTIL_LISTIFY_3731(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3731, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3733(F, sep, ...) \ + Z_UTIL_LISTIFY_3732(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3732, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3734(F, sep, ...) \ + Z_UTIL_LISTIFY_3733(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3733, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3735(F, sep, ...) \ + Z_UTIL_LISTIFY_3734(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3734, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3736(F, sep, ...) \ + Z_UTIL_LISTIFY_3735(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3735, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3737(F, sep, ...) \ + Z_UTIL_LISTIFY_3736(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3736, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3738(F, sep, ...) \ + Z_UTIL_LISTIFY_3737(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3737, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3739(F, sep, ...) \ + Z_UTIL_LISTIFY_3738(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3738, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3740(F, sep, ...) \ + Z_UTIL_LISTIFY_3739(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3739, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3741(F, sep, ...) \ + Z_UTIL_LISTIFY_3740(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3740, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3742(F, sep, ...) \ + Z_UTIL_LISTIFY_3741(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3741, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3743(F, sep, ...) \ + Z_UTIL_LISTIFY_3742(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3742, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3744(F, sep, ...) \ + Z_UTIL_LISTIFY_3743(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3743, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3745(F, sep, ...) \ + Z_UTIL_LISTIFY_3744(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3744, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3746(F, sep, ...) \ + Z_UTIL_LISTIFY_3745(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3745, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3747(F, sep, ...) \ + Z_UTIL_LISTIFY_3746(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3746, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3748(F, sep, ...) \ + Z_UTIL_LISTIFY_3747(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3747, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3749(F, sep, ...) \ + Z_UTIL_LISTIFY_3748(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3748, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3750(F, sep, ...) \ + Z_UTIL_LISTIFY_3749(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3749, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3751(F, sep, ...) \ + Z_UTIL_LISTIFY_3750(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3750, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3752(F, sep, ...) \ + Z_UTIL_LISTIFY_3751(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3751, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3753(F, sep, ...) \ + Z_UTIL_LISTIFY_3752(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3752, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3754(F, sep, ...) \ + Z_UTIL_LISTIFY_3753(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3753, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3755(F, sep, ...) \ + Z_UTIL_LISTIFY_3754(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3754, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3756(F, sep, ...) \ + Z_UTIL_LISTIFY_3755(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3755, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3757(F, sep, ...) \ + Z_UTIL_LISTIFY_3756(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3756, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3758(F, sep, ...) \ + Z_UTIL_LISTIFY_3757(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3757, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3759(F, sep, ...) \ + Z_UTIL_LISTIFY_3758(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3758, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3760(F, sep, ...) \ + Z_UTIL_LISTIFY_3759(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3759, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3761(F, sep, ...) \ + Z_UTIL_LISTIFY_3760(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3760, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3762(F, sep, ...) \ + Z_UTIL_LISTIFY_3761(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3761, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3763(F, sep, ...) \ + Z_UTIL_LISTIFY_3762(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3762, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3764(F, sep, ...) \ + Z_UTIL_LISTIFY_3763(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3763, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3765(F, sep, ...) \ + Z_UTIL_LISTIFY_3764(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3764, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3766(F, sep, ...) \ + Z_UTIL_LISTIFY_3765(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3765, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3767(F, sep, ...) \ + Z_UTIL_LISTIFY_3766(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3766, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3768(F, sep, ...) \ + Z_UTIL_LISTIFY_3767(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3767, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3769(F, sep, ...) \ + Z_UTIL_LISTIFY_3768(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3768, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3770(F, sep, ...) \ + Z_UTIL_LISTIFY_3769(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3769, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3771(F, sep, ...) \ + Z_UTIL_LISTIFY_3770(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3770, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3772(F, sep, ...) \ + Z_UTIL_LISTIFY_3771(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3771, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3773(F, sep, ...) \ + Z_UTIL_LISTIFY_3772(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3772, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3774(F, sep, ...) \ + Z_UTIL_LISTIFY_3773(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3773, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3775(F, sep, ...) \ + Z_UTIL_LISTIFY_3774(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3774, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3776(F, sep, ...) \ + Z_UTIL_LISTIFY_3775(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3775, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3777(F, sep, ...) \ + Z_UTIL_LISTIFY_3776(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3776, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3778(F, sep, ...) \ + Z_UTIL_LISTIFY_3777(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3777, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3779(F, sep, ...) \ + Z_UTIL_LISTIFY_3778(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3778, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3780(F, sep, ...) \ + Z_UTIL_LISTIFY_3779(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3779, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3781(F, sep, ...) \ + Z_UTIL_LISTIFY_3780(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3780, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3782(F, sep, ...) \ + Z_UTIL_LISTIFY_3781(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3781, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3783(F, sep, ...) \ + Z_UTIL_LISTIFY_3782(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3782, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3784(F, sep, ...) \ + Z_UTIL_LISTIFY_3783(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3783, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3785(F, sep, ...) \ + Z_UTIL_LISTIFY_3784(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3784, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3786(F, sep, ...) \ + Z_UTIL_LISTIFY_3785(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3785, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3787(F, sep, ...) \ + Z_UTIL_LISTIFY_3786(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3786, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3788(F, sep, ...) \ + Z_UTIL_LISTIFY_3787(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3787, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3789(F, sep, ...) \ + Z_UTIL_LISTIFY_3788(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3788, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3790(F, sep, ...) \ + Z_UTIL_LISTIFY_3789(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3789, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3791(F, sep, ...) \ + Z_UTIL_LISTIFY_3790(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3790, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3792(F, sep, ...) \ + Z_UTIL_LISTIFY_3791(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3791, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3793(F, sep, ...) \ + Z_UTIL_LISTIFY_3792(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3792, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3794(F, sep, ...) \ + Z_UTIL_LISTIFY_3793(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3793, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3795(F, sep, ...) \ + Z_UTIL_LISTIFY_3794(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3794, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3796(F, sep, ...) \ + Z_UTIL_LISTIFY_3795(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3795, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3797(F, sep, ...) \ + Z_UTIL_LISTIFY_3796(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3796, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3798(F, sep, ...) \ + Z_UTIL_LISTIFY_3797(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3797, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3799(F, sep, ...) \ + Z_UTIL_LISTIFY_3798(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3798, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3800(F, sep, ...) \ + Z_UTIL_LISTIFY_3799(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3799, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3801(F, sep, ...) \ + Z_UTIL_LISTIFY_3800(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3800, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3802(F, sep, ...) \ + Z_UTIL_LISTIFY_3801(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3801, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3803(F, sep, ...) \ + Z_UTIL_LISTIFY_3802(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3802, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3804(F, sep, ...) \ + Z_UTIL_LISTIFY_3803(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3803, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3805(F, sep, ...) \ + Z_UTIL_LISTIFY_3804(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3804, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3806(F, sep, ...) \ + Z_UTIL_LISTIFY_3805(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3805, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3807(F, sep, ...) \ + Z_UTIL_LISTIFY_3806(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3806, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3808(F, sep, ...) \ + Z_UTIL_LISTIFY_3807(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3807, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3809(F, sep, ...) \ + Z_UTIL_LISTIFY_3808(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3808, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3810(F, sep, ...) \ + Z_UTIL_LISTIFY_3809(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3809, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3811(F, sep, ...) \ + Z_UTIL_LISTIFY_3810(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3810, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3812(F, sep, ...) \ + Z_UTIL_LISTIFY_3811(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3811, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3813(F, sep, ...) \ + Z_UTIL_LISTIFY_3812(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3812, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3814(F, sep, ...) \ + Z_UTIL_LISTIFY_3813(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3813, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3815(F, sep, ...) \ + Z_UTIL_LISTIFY_3814(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3814, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3816(F, sep, ...) \ + Z_UTIL_LISTIFY_3815(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3815, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3817(F, sep, ...) \ + Z_UTIL_LISTIFY_3816(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3816, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3818(F, sep, ...) \ + Z_UTIL_LISTIFY_3817(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3817, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3819(F, sep, ...) \ + Z_UTIL_LISTIFY_3818(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3818, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3820(F, sep, ...) \ + Z_UTIL_LISTIFY_3819(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3819, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3821(F, sep, ...) \ + Z_UTIL_LISTIFY_3820(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3820, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3822(F, sep, ...) \ + Z_UTIL_LISTIFY_3821(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3821, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3823(F, sep, ...) \ + Z_UTIL_LISTIFY_3822(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3822, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3824(F, sep, ...) \ + Z_UTIL_LISTIFY_3823(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3823, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3825(F, sep, ...) \ + Z_UTIL_LISTIFY_3824(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3824, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3826(F, sep, ...) \ + Z_UTIL_LISTIFY_3825(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3825, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3827(F, sep, ...) \ + Z_UTIL_LISTIFY_3826(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3826, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3828(F, sep, ...) \ + Z_UTIL_LISTIFY_3827(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3827, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3829(F, sep, ...) \ + Z_UTIL_LISTIFY_3828(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3828, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3830(F, sep, ...) \ + Z_UTIL_LISTIFY_3829(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3829, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3831(F, sep, ...) \ + Z_UTIL_LISTIFY_3830(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3830, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3832(F, sep, ...) \ + Z_UTIL_LISTIFY_3831(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3831, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3833(F, sep, ...) \ + Z_UTIL_LISTIFY_3832(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3832, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3834(F, sep, ...) \ + Z_UTIL_LISTIFY_3833(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3833, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3835(F, sep, ...) \ + Z_UTIL_LISTIFY_3834(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3834, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3836(F, sep, ...) \ + Z_UTIL_LISTIFY_3835(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3835, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3837(F, sep, ...) \ + Z_UTIL_LISTIFY_3836(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3836, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3838(F, sep, ...) \ + Z_UTIL_LISTIFY_3837(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3837, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3839(F, sep, ...) \ + Z_UTIL_LISTIFY_3838(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3838, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3840(F, sep, ...) \ + Z_UTIL_LISTIFY_3839(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3839, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3841(F, sep, ...) \ + Z_UTIL_LISTIFY_3840(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3840, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3842(F, sep, ...) \ + Z_UTIL_LISTIFY_3841(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3841, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3843(F, sep, ...) \ + Z_UTIL_LISTIFY_3842(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3842, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3844(F, sep, ...) \ + Z_UTIL_LISTIFY_3843(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3843, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3845(F, sep, ...) \ + Z_UTIL_LISTIFY_3844(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3844, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3846(F, sep, ...) \ + Z_UTIL_LISTIFY_3845(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3845, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3847(F, sep, ...) \ + Z_UTIL_LISTIFY_3846(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3846, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3848(F, sep, ...) \ + Z_UTIL_LISTIFY_3847(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3847, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3849(F, sep, ...) \ + Z_UTIL_LISTIFY_3848(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3848, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3850(F, sep, ...) \ + Z_UTIL_LISTIFY_3849(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3849, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3851(F, sep, ...) \ + Z_UTIL_LISTIFY_3850(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3850, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3852(F, sep, ...) \ + Z_UTIL_LISTIFY_3851(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3851, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3853(F, sep, ...) \ + Z_UTIL_LISTIFY_3852(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3852, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3854(F, sep, ...) \ + Z_UTIL_LISTIFY_3853(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3853, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3855(F, sep, ...) \ + Z_UTIL_LISTIFY_3854(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3854, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3856(F, sep, ...) \ + Z_UTIL_LISTIFY_3855(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3855, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3857(F, sep, ...) \ + Z_UTIL_LISTIFY_3856(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3856, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3858(F, sep, ...) \ + Z_UTIL_LISTIFY_3857(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3857, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3859(F, sep, ...) \ + Z_UTIL_LISTIFY_3858(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3858, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3860(F, sep, ...) \ + Z_UTIL_LISTIFY_3859(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3859, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3861(F, sep, ...) \ + Z_UTIL_LISTIFY_3860(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3860, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3862(F, sep, ...) \ + Z_UTIL_LISTIFY_3861(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3861, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3863(F, sep, ...) \ + Z_UTIL_LISTIFY_3862(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3862, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3864(F, sep, ...) \ + Z_UTIL_LISTIFY_3863(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3863, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3865(F, sep, ...) \ + Z_UTIL_LISTIFY_3864(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3864, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3866(F, sep, ...) \ + Z_UTIL_LISTIFY_3865(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3865, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3867(F, sep, ...) \ + Z_UTIL_LISTIFY_3866(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3866, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3868(F, sep, ...) \ + Z_UTIL_LISTIFY_3867(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3867, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3869(F, sep, ...) \ + Z_UTIL_LISTIFY_3868(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3868, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3870(F, sep, ...) \ + Z_UTIL_LISTIFY_3869(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3869, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3871(F, sep, ...) \ + Z_UTIL_LISTIFY_3870(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3870, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3872(F, sep, ...) \ + Z_UTIL_LISTIFY_3871(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3871, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3873(F, sep, ...) \ + Z_UTIL_LISTIFY_3872(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3872, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3874(F, sep, ...) \ + Z_UTIL_LISTIFY_3873(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3873, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3875(F, sep, ...) \ + Z_UTIL_LISTIFY_3874(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3874, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3876(F, sep, ...) \ + Z_UTIL_LISTIFY_3875(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3875, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3877(F, sep, ...) \ + Z_UTIL_LISTIFY_3876(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3876, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3878(F, sep, ...) \ + Z_UTIL_LISTIFY_3877(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3877, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3879(F, sep, ...) \ + Z_UTIL_LISTIFY_3878(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3878, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3880(F, sep, ...) \ + Z_UTIL_LISTIFY_3879(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3879, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3881(F, sep, ...) \ + Z_UTIL_LISTIFY_3880(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3880, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3882(F, sep, ...) \ + Z_UTIL_LISTIFY_3881(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3881, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3883(F, sep, ...) \ + Z_UTIL_LISTIFY_3882(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3882, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3884(F, sep, ...) \ + Z_UTIL_LISTIFY_3883(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3883, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3885(F, sep, ...) \ + Z_UTIL_LISTIFY_3884(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3884, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3886(F, sep, ...) \ + Z_UTIL_LISTIFY_3885(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3885, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3887(F, sep, ...) \ + Z_UTIL_LISTIFY_3886(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3886, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3888(F, sep, ...) \ + Z_UTIL_LISTIFY_3887(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3887, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3889(F, sep, ...) \ + Z_UTIL_LISTIFY_3888(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3888, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3890(F, sep, ...) \ + Z_UTIL_LISTIFY_3889(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3889, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3891(F, sep, ...) \ + Z_UTIL_LISTIFY_3890(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3890, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3892(F, sep, ...) \ + Z_UTIL_LISTIFY_3891(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3891, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3893(F, sep, ...) \ + Z_UTIL_LISTIFY_3892(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3892, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3894(F, sep, ...) \ + Z_UTIL_LISTIFY_3893(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3893, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3895(F, sep, ...) \ + Z_UTIL_LISTIFY_3894(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3894, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3896(F, sep, ...) \ + Z_UTIL_LISTIFY_3895(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3895, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3897(F, sep, ...) \ + Z_UTIL_LISTIFY_3896(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3896, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3898(F, sep, ...) \ + Z_UTIL_LISTIFY_3897(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3897, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3899(F, sep, ...) \ + Z_UTIL_LISTIFY_3898(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3898, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3900(F, sep, ...) \ + Z_UTIL_LISTIFY_3899(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3899, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3901(F, sep, ...) \ + Z_UTIL_LISTIFY_3900(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3900, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3902(F, sep, ...) \ + Z_UTIL_LISTIFY_3901(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3901, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3903(F, sep, ...) \ + Z_UTIL_LISTIFY_3902(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3902, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3904(F, sep, ...) \ + Z_UTIL_LISTIFY_3903(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3903, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3905(F, sep, ...) \ + Z_UTIL_LISTIFY_3904(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3904, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3906(F, sep, ...) \ + Z_UTIL_LISTIFY_3905(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3905, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3907(F, sep, ...) \ + Z_UTIL_LISTIFY_3906(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3906, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3908(F, sep, ...) \ + Z_UTIL_LISTIFY_3907(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3907, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3909(F, sep, ...) \ + Z_UTIL_LISTIFY_3908(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3908, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3910(F, sep, ...) \ + Z_UTIL_LISTIFY_3909(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3909, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3911(F, sep, ...) \ + Z_UTIL_LISTIFY_3910(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3910, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3912(F, sep, ...) \ + Z_UTIL_LISTIFY_3911(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3911, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3913(F, sep, ...) \ + Z_UTIL_LISTIFY_3912(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3912, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3914(F, sep, ...) \ + Z_UTIL_LISTIFY_3913(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3913, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3915(F, sep, ...) \ + Z_UTIL_LISTIFY_3914(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3914, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3916(F, sep, ...) \ + Z_UTIL_LISTIFY_3915(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3915, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3917(F, sep, ...) \ + Z_UTIL_LISTIFY_3916(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3916, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3918(F, sep, ...) \ + Z_UTIL_LISTIFY_3917(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3917, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3919(F, sep, ...) \ + Z_UTIL_LISTIFY_3918(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3918, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3920(F, sep, ...) \ + Z_UTIL_LISTIFY_3919(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3919, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3921(F, sep, ...) \ + Z_UTIL_LISTIFY_3920(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3920, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3922(F, sep, ...) \ + Z_UTIL_LISTIFY_3921(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3921, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3923(F, sep, ...) \ + Z_UTIL_LISTIFY_3922(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3922, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3924(F, sep, ...) \ + Z_UTIL_LISTIFY_3923(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3923, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3925(F, sep, ...) \ + Z_UTIL_LISTIFY_3924(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3924, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3926(F, sep, ...) \ + Z_UTIL_LISTIFY_3925(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3925, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3927(F, sep, ...) \ + Z_UTIL_LISTIFY_3926(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3926, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3928(F, sep, ...) \ + Z_UTIL_LISTIFY_3927(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3927, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3929(F, sep, ...) \ + Z_UTIL_LISTIFY_3928(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3928, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3930(F, sep, ...) \ + Z_UTIL_LISTIFY_3929(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3929, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3931(F, sep, ...) \ + Z_UTIL_LISTIFY_3930(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3930, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3932(F, sep, ...) \ + Z_UTIL_LISTIFY_3931(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3931, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3933(F, sep, ...) \ + Z_UTIL_LISTIFY_3932(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3932, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3934(F, sep, ...) \ + Z_UTIL_LISTIFY_3933(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3933, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3935(F, sep, ...) \ + Z_UTIL_LISTIFY_3934(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3934, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3936(F, sep, ...) \ + Z_UTIL_LISTIFY_3935(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3935, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3937(F, sep, ...) \ + Z_UTIL_LISTIFY_3936(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3936, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3938(F, sep, ...) \ + Z_UTIL_LISTIFY_3937(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3937, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3939(F, sep, ...) \ + Z_UTIL_LISTIFY_3938(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3938, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3940(F, sep, ...) \ + Z_UTIL_LISTIFY_3939(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3939, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3941(F, sep, ...) \ + Z_UTIL_LISTIFY_3940(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3940, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3942(F, sep, ...) \ + Z_UTIL_LISTIFY_3941(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3941, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3943(F, sep, ...) \ + Z_UTIL_LISTIFY_3942(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3942, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3944(F, sep, ...) \ + Z_UTIL_LISTIFY_3943(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3943, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3945(F, sep, ...) \ + Z_UTIL_LISTIFY_3944(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3944, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3946(F, sep, ...) \ + Z_UTIL_LISTIFY_3945(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3945, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3947(F, sep, ...) \ + Z_UTIL_LISTIFY_3946(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3946, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3948(F, sep, ...) \ + Z_UTIL_LISTIFY_3947(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3947, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3949(F, sep, ...) \ + Z_UTIL_LISTIFY_3948(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3948, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3950(F, sep, ...) \ + Z_UTIL_LISTIFY_3949(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3949, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3951(F, sep, ...) \ + Z_UTIL_LISTIFY_3950(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3950, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3952(F, sep, ...) \ + Z_UTIL_LISTIFY_3951(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3951, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3953(F, sep, ...) \ + Z_UTIL_LISTIFY_3952(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3952, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3954(F, sep, ...) \ + Z_UTIL_LISTIFY_3953(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3953, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3955(F, sep, ...) \ + Z_UTIL_LISTIFY_3954(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3954, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3956(F, sep, ...) \ + Z_UTIL_LISTIFY_3955(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3955, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3957(F, sep, ...) \ + Z_UTIL_LISTIFY_3956(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3956, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3958(F, sep, ...) \ + Z_UTIL_LISTIFY_3957(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3957, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3959(F, sep, ...) \ + Z_UTIL_LISTIFY_3958(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3958, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3960(F, sep, ...) \ + Z_UTIL_LISTIFY_3959(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3959, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3961(F, sep, ...) \ + Z_UTIL_LISTIFY_3960(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3960, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3962(F, sep, ...) \ + Z_UTIL_LISTIFY_3961(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3961, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3963(F, sep, ...) \ + Z_UTIL_LISTIFY_3962(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3962, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3964(F, sep, ...) \ + Z_UTIL_LISTIFY_3963(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3963, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3965(F, sep, ...) \ + Z_UTIL_LISTIFY_3964(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3964, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3966(F, sep, ...) \ + Z_UTIL_LISTIFY_3965(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3965, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3967(F, sep, ...) \ + Z_UTIL_LISTIFY_3966(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3966, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3968(F, sep, ...) \ + Z_UTIL_LISTIFY_3967(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3967, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3969(F, sep, ...) \ + Z_UTIL_LISTIFY_3968(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3968, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3970(F, sep, ...) \ + Z_UTIL_LISTIFY_3969(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3969, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3971(F, sep, ...) \ + Z_UTIL_LISTIFY_3970(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3970, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3972(F, sep, ...) \ + Z_UTIL_LISTIFY_3971(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3971, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3973(F, sep, ...) \ + Z_UTIL_LISTIFY_3972(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3972, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3974(F, sep, ...) \ + Z_UTIL_LISTIFY_3973(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3973, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3975(F, sep, ...) \ + Z_UTIL_LISTIFY_3974(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3974, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3976(F, sep, ...) \ + Z_UTIL_LISTIFY_3975(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3975, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3977(F, sep, ...) \ + Z_UTIL_LISTIFY_3976(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3976, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3978(F, sep, ...) \ + Z_UTIL_LISTIFY_3977(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3977, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3979(F, sep, ...) \ + Z_UTIL_LISTIFY_3978(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3978, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3980(F, sep, ...) \ + Z_UTIL_LISTIFY_3979(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3979, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3981(F, sep, ...) \ + Z_UTIL_LISTIFY_3980(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3980, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3982(F, sep, ...) \ + Z_UTIL_LISTIFY_3981(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3981, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3983(F, sep, ...) \ + Z_UTIL_LISTIFY_3982(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3982, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3984(F, sep, ...) \ + Z_UTIL_LISTIFY_3983(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3983, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3985(F, sep, ...) \ + Z_UTIL_LISTIFY_3984(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3984, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3986(F, sep, ...) \ + Z_UTIL_LISTIFY_3985(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3985, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3987(F, sep, ...) \ + Z_UTIL_LISTIFY_3986(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3986, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3988(F, sep, ...) \ + Z_UTIL_LISTIFY_3987(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3987, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3989(F, sep, ...) \ + Z_UTIL_LISTIFY_3988(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3988, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3990(F, sep, ...) \ + Z_UTIL_LISTIFY_3989(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3989, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3991(F, sep, ...) \ + Z_UTIL_LISTIFY_3990(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3990, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3992(F, sep, ...) \ + Z_UTIL_LISTIFY_3991(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3991, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3993(F, sep, ...) \ + Z_UTIL_LISTIFY_3992(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3992, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3994(F, sep, ...) \ + Z_UTIL_LISTIFY_3993(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3993, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3995(F, sep, ...) \ + Z_UTIL_LISTIFY_3994(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3994, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3996(F, sep, ...) \ + Z_UTIL_LISTIFY_3995(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3995, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3997(F, sep, ...) \ + Z_UTIL_LISTIFY_3996(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3996, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3998(F, sep, ...) \ + Z_UTIL_LISTIFY_3997(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3997, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3999(F, sep, ...) \ + Z_UTIL_LISTIFY_3998(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3998, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4000(F, sep, ...) \ + Z_UTIL_LISTIFY_3999(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3999, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4001(F, sep, ...) \ + Z_UTIL_LISTIFY_4000(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4000, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4002(F, sep, ...) \ + Z_UTIL_LISTIFY_4001(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4001, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4003(F, sep, ...) \ + Z_UTIL_LISTIFY_4002(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4002, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4004(F, sep, ...) \ + Z_UTIL_LISTIFY_4003(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4003, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4005(F, sep, ...) \ + Z_UTIL_LISTIFY_4004(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4004, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4006(F, sep, ...) \ + Z_UTIL_LISTIFY_4005(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4005, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4007(F, sep, ...) \ + Z_UTIL_LISTIFY_4006(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4006, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4008(F, sep, ...) \ + Z_UTIL_LISTIFY_4007(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4007, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4009(F, sep, ...) \ + Z_UTIL_LISTIFY_4008(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4008, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4010(F, sep, ...) \ + Z_UTIL_LISTIFY_4009(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4009, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4011(F, sep, ...) \ + Z_UTIL_LISTIFY_4010(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4010, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4012(F, sep, ...) \ + Z_UTIL_LISTIFY_4011(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4011, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4013(F, sep, ...) \ + Z_UTIL_LISTIFY_4012(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4012, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4014(F, sep, ...) \ + Z_UTIL_LISTIFY_4013(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4013, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4015(F, sep, ...) \ + Z_UTIL_LISTIFY_4014(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4014, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4016(F, sep, ...) \ + Z_UTIL_LISTIFY_4015(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4015, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4017(F, sep, ...) \ + Z_UTIL_LISTIFY_4016(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4016, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4018(F, sep, ...) \ + Z_UTIL_LISTIFY_4017(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4017, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4019(F, sep, ...) \ + Z_UTIL_LISTIFY_4018(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4018, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4020(F, sep, ...) \ + Z_UTIL_LISTIFY_4019(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4019, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4021(F, sep, ...) \ + Z_UTIL_LISTIFY_4020(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4020, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4022(F, sep, ...) \ + Z_UTIL_LISTIFY_4021(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4021, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4023(F, sep, ...) \ + Z_UTIL_LISTIFY_4022(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4022, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4024(F, sep, ...) \ + Z_UTIL_LISTIFY_4023(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4023, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4025(F, sep, ...) \ + Z_UTIL_LISTIFY_4024(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4024, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4026(F, sep, ...) \ + Z_UTIL_LISTIFY_4025(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4025, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4027(F, sep, ...) \ + Z_UTIL_LISTIFY_4026(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4026, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4028(F, sep, ...) \ + Z_UTIL_LISTIFY_4027(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4027, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4029(F, sep, ...) \ + Z_UTIL_LISTIFY_4028(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4028, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4030(F, sep, ...) \ + Z_UTIL_LISTIFY_4029(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4029, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4031(F, sep, ...) \ + Z_UTIL_LISTIFY_4030(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4030, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4032(F, sep, ...) \ + Z_UTIL_LISTIFY_4031(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4031, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4033(F, sep, ...) \ + Z_UTIL_LISTIFY_4032(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4032, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4034(F, sep, ...) \ + Z_UTIL_LISTIFY_4033(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4033, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4035(F, sep, ...) \ + Z_UTIL_LISTIFY_4034(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4034, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4036(F, sep, ...) \ + Z_UTIL_LISTIFY_4035(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4035, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4037(F, sep, ...) \ + Z_UTIL_LISTIFY_4036(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4036, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4038(F, sep, ...) \ + Z_UTIL_LISTIFY_4037(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4037, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4039(F, sep, ...) \ + Z_UTIL_LISTIFY_4038(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4038, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4040(F, sep, ...) \ + Z_UTIL_LISTIFY_4039(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4039, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4041(F, sep, ...) \ + Z_UTIL_LISTIFY_4040(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4040, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4042(F, sep, ...) \ + Z_UTIL_LISTIFY_4041(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4041, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4043(F, sep, ...) \ + Z_UTIL_LISTIFY_4042(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4042, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4044(F, sep, ...) \ + Z_UTIL_LISTIFY_4043(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4043, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4045(F, sep, ...) \ + Z_UTIL_LISTIFY_4044(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4044, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4046(F, sep, ...) \ + Z_UTIL_LISTIFY_4045(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4045, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4047(F, sep, ...) \ + Z_UTIL_LISTIFY_4046(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4046, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4048(F, sep, ...) \ + Z_UTIL_LISTIFY_4047(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4047, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4049(F, sep, ...) \ + Z_UTIL_LISTIFY_4048(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4048, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4050(F, sep, ...) \ + Z_UTIL_LISTIFY_4049(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4049, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4051(F, sep, ...) \ + Z_UTIL_LISTIFY_4050(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4050, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4052(F, sep, ...) \ + Z_UTIL_LISTIFY_4051(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4051, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4053(F, sep, ...) \ + Z_UTIL_LISTIFY_4052(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4052, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4054(F, sep, ...) \ + Z_UTIL_LISTIFY_4053(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4053, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4055(F, sep, ...) \ + Z_UTIL_LISTIFY_4054(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4054, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4056(F, sep, ...) \ + Z_UTIL_LISTIFY_4055(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4055, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4057(F, sep, ...) \ + Z_UTIL_LISTIFY_4056(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4056, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4058(F, sep, ...) \ + Z_UTIL_LISTIFY_4057(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4057, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4059(F, sep, ...) \ + Z_UTIL_LISTIFY_4058(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4058, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4060(F, sep, ...) \ + Z_UTIL_LISTIFY_4059(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4059, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4061(F, sep, ...) \ + Z_UTIL_LISTIFY_4060(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4060, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4062(F, sep, ...) \ + Z_UTIL_LISTIFY_4061(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4061, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4063(F, sep, ...) \ + Z_UTIL_LISTIFY_4062(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4062, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4064(F, sep, ...) \ + Z_UTIL_LISTIFY_4063(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4063, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4065(F, sep, ...) \ + Z_UTIL_LISTIFY_4064(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4064, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4066(F, sep, ...) \ + Z_UTIL_LISTIFY_4065(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4065, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4067(F, sep, ...) \ + Z_UTIL_LISTIFY_4066(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4066, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4068(F, sep, ...) \ + Z_UTIL_LISTIFY_4067(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4067, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4069(F, sep, ...) \ + Z_UTIL_LISTIFY_4068(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4068, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4070(F, sep, ...) \ + Z_UTIL_LISTIFY_4069(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4069, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4071(F, sep, ...) \ + Z_UTIL_LISTIFY_4070(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4070, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4072(F, sep, ...) \ + Z_UTIL_LISTIFY_4071(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4071, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4073(F, sep, ...) \ + Z_UTIL_LISTIFY_4072(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4072, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4074(F, sep, ...) \ + Z_UTIL_LISTIFY_4073(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4073, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4075(F, sep, ...) \ + Z_UTIL_LISTIFY_4074(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4074, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4076(F, sep, ...) \ + Z_UTIL_LISTIFY_4075(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4075, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4077(F, sep, ...) \ + Z_UTIL_LISTIFY_4076(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4076, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4078(F, sep, ...) \ + Z_UTIL_LISTIFY_4077(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4077, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4079(F, sep, ...) \ + Z_UTIL_LISTIFY_4078(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4078, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4080(F, sep, ...) \ + Z_UTIL_LISTIFY_4079(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4079, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4081(F, sep, ...) \ + Z_UTIL_LISTIFY_4080(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4080, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4082(F, sep, ...) \ + Z_UTIL_LISTIFY_4081(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4081, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4083(F, sep, ...) \ + Z_UTIL_LISTIFY_4082(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4082, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4084(F, sep, ...) \ + Z_UTIL_LISTIFY_4083(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4083, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4085(F, sep, ...) \ + Z_UTIL_LISTIFY_4084(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4084, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4086(F, sep, ...) \ + Z_UTIL_LISTIFY_4085(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4085, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4087(F, sep, ...) \ + Z_UTIL_LISTIFY_4086(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4086, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4088(F, sep, ...) \ + Z_UTIL_LISTIFY_4087(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4087, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4089(F, sep, ...) \ + Z_UTIL_LISTIFY_4088(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4088, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4090(F, sep, ...) \ + Z_UTIL_LISTIFY_4089(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4089, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4091(F, sep, ...) \ + Z_UTIL_LISTIFY_4090(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4090, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4092(F, sep, ...) \ + Z_UTIL_LISTIFY_4091(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4091, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4093(F, sep, ...) \ + Z_UTIL_LISTIFY_4092(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4092, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4094(F, sep, ...) \ + Z_UTIL_LISTIFY_4093(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4093, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4095(F, sep, ...) \ + Z_UTIL_LISTIFY_4094(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4094, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4096(F, sep, ...) \ + Z_UTIL_LISTIFY_4095(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4095, __VA_ARGS__) + +#endif /* ZEPHYR_INCLUDE_SYS_UTIL_LISTIFY_H_ */ diff --git a/include/zephyr/sys/util_loops.h b/include/zephyr/sys/util_loops.h index 979a508a63c..ff64e7b1ef9 100644 --- a/include/zephyr/sys/util_loops.h +++ b/include/zephyr/sys/util_loops.h @@ -1080,1029 +1080,6 @@ #define Z_BYPASS(x) x /* Set of UTIL_LISTIFY particles */ -#define Z_UTIL_LISTIFY_0(F, sep, ...) - -#define Z_UTIL_LISTIFY_1(F, sep, ...) \ - F(0, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_2(F, sep, ...) \ - Z_UTIL_LISTIFY_1(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(1, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_3(F, sep, ...) \ - Z_UTIL_LISTIFY_2(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(2, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_4(F, sep, ...) \ - Z_UTIL_LISTIFY_3(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(3, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_5(F, sep, ...) \ - Z_UTIL_LISTIFY_4(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(4, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_6(F, sep, ...) \ - Z_UTIL_LISTIFY_5(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(5, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_7(F, sep, ...) \ - Z_UTIL_LISTIFY_6(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(6, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_8(F, sep, ...) \ - Z_UTIL_LISTIFY_7(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(7, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_9(F, sep, ...) \ - Z_UTIL_LISTIFY_8(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(8, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_10(F, sep, ...) \ - Z_UTIL_LISTIFY_9(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(9, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_11(F, sep, ...) \ - Z_UTIL_LISTIFY_10(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(10, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_12(F, sep, ...) \ - Z_UTIL_LISTIFY_11(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(11, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_13(F, sep, ...) \ - Z_UTIL_LISTIFY_12(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(12, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_14(F, sep, ...) \ - Z_UTIL_LISTIFY_13(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(13, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_15(F, sep, ...) \ - Z_UTIL_LISTIFY_14(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(14, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_16(F, sep, ...) \ - Z_UTIL_LISTIFY_15(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(15, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_17(F, sep, ...) \ - Z_UTIL_LISTIFY_16(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(16, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_18(F, sep, ...) \ - Z_UTIL_LISTIFY_17(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(17, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_19(F, sep, ...) \ - Z_UTIL_LISTIFY_18(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(18, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_20(F, sep, ...) \ - Z_UTIL_LISTIFY_19(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(19, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_21(F, sep, ...) \ - Z_UTIL_LISTIFY_20(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(20, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_22(F, sep, ...) \ - Z_UTIL_LISTIFY_21(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(21, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_23(F, sep, ...) \ - Z_UTIL_LISTIFY_22(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(22, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_24(F, sep, ...) \ - Z_UTIL_LISTIFY_23(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(23, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_25(F, sep, ...) \ - Z_UTIL_LISTIFY_24(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(24, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_26(F, sep, ...) \ - Z_UTIL_LISTIFY_25(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(25, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_27(F, sep, ...) \ - Z_UTIL_LISTIFY_26(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(26, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_28(F, sep, ...) \ - Z_UTIL_LISTIFY_27(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(27, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_29(F, sep, ...) \ - Z_UTIL_LISTIFY_28(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(28, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_30(F, sep, ...) \ - Z_UTIL_LISTIFY_29(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(29, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_31(F, sep, ...) \ - Z_UTIL_LISTIFY_30(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(30, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_32(F, sep, ...) \ - Z_UTIL_LISTIFY_31(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(31, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_33(F, sep, ...) \ - Z_UTIL_LISTIFY_32(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(32, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_34(F, sep, ...) \ - Z_UTIL_LISTIFY_33(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(33, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_35(F, sep, ...) \ - Z_UTIL_LISTIFY_34(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(34, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_36(F, sep, ...) \ - Z_UTIL_LISTIFY_35(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(35, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_37(F, sep, ...) \ - Z_UTIL_LISTIFY_36(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(36, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_38(F, sep, ...) \ - Z_UTIL_LISTIFY_37(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(37, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_39(F, sep, ...) \ - Z_UTIL_LISTIFY_38(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(38, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_40(F, sep, ...) \ - Z_UTIL_LISTIFY_39(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(39, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_41(F, sep, ...) \ - Z_UTIL_LISTIFY_40(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(40, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_42(F, sep, ...) \ - Z_UTIL_LISTIFY_41(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(41, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_43(F, sep, ...) \ - Z_UTIL_LISTIFY_42(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(42, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_44(F, sep, ...) \ - Z_UTIL_LISTIFY_43(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(43, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_45(F, sep, ...) \ - Z_UTIL_LISTIFY_44(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(44, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_46(F, sep, ...) \ - Z_UTIL_LISTIFY_45(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(45, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_47(F, sep, ...) \ - Z_UTIL_LISTIFY_46(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(46, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_48(F, sep, ...) \ - Z_UTIL_LISTIFY_47(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(47, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_49(F, sep, ...) \ - Z_UTIL_LISTIFY_48(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(48, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_50(F, sep, ...) \ - Z_UTIL_LISTIFY_49(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(49, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_51(F, sep, ...) \ - Z_UTIL_LISTIFY_50(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(50, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_52(F, sep, ...) \ - Z_UTIL_LISTIFY_51(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(51, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_53(F, sep, ...) \ - Z_UTIL_LISTIFY_52(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(52, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_54(F, sep, ...) \ - Z_UTIL_LISTIFY_53(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(53, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_55(F, sep, ...) \ - Z_UTIL_LISTIFY_54(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(54, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_56(F, sep, ...) \ - Z_UTIL_LISTIFY_55(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(55, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_57(F, sep, ...) \ - Z_UTIL_LISTIFY_56(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(56, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_58(F, sep, ...) \ - Z_UTIL_LISTIFY_57(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(57, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_59(F, sep, ...) \ - Z_UTIL_LISTIFY_58(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(58, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_60(F, sep, ...) \ - Z_UTIL_LISTIFY_59(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(59, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_61(F, sep, ...) \ - Z_UTIL_LISTIFY_60(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(60, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_62(F, sep, ...) \ - Z_UTIL_LISTIFY_61(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(61, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_63(F, sep, ...) \ - Z_UTIL_LISTIFY_62(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(62, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_64(F, sep, ...) \ - Z_UTIL_LISTIFY_63(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(63, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_65(F, sep, ...) \ - Z_UTIL_LISTIFY_64(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(64, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_66(F, sep, ...) \ - Z_UTIL_LISTIFY_65(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(65, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_67(F, sep, ...) \ - Z_UTIL_LISTIFY_66(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(66, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_68(F, sep, ...) \ - Z_UTIL_LISTIFY_67(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(67, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_69(F, sep, ...) \ - Z_UTIL_LISTIFY_68(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(68, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_70(F, sep, ...) \ - Z_UTIL_LISTIFY_69(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(69, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_71(F, sep, ...) \ - Z_UTIL_LISTIFY_70(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(70, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_72(F, sep, ...) \ - Z_UTIL_LISTIFY_71(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(71, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_73(F, sep, ...) \ - Z_UTIL_LISTIFY_72(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(72, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_74(F, sep, ...) \ - Z_UTIL_LISTIFY_73(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(73, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_75(F, sep, ...) \ - Z_UTIL_LISTIFY_74(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(74, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_76(F, sep, ...) \ - Z_UTIL_LISTIFY_75(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(75, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_77(F, sep, ...) \ - Z_UTIL_LISTIFY_76(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(76, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_78(F, sep, ...) \ - Z_UTIL_LISTIFY_77(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(77, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_79(F, sep, ...) \ - Z_UTIL_LISTIFY_78(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(78, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_80(F, sep, ...) \ - Z_UTIL_LISTIFY_79(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(79, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_81(F, sep, ...) \ - Z_UTIL_LISTIFY_80(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(80, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_82(F, sep, ...) \ - Z_UTIL_LISTIFY_81(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(81, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_83(F, sep, ...) \ - Z_UTIL_LISTIFY_82(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(82, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_84(F, sep, ...) \ - Z_UTIL_LISTIFY_83(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(83, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_85(F, sep, ...) \ - Z_UTIL_LISTIFY_84(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(84, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_86(F, sep, ...) \ - Z_UTIL_LISTIFY_85(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(85, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_87(F, sep, ...) \ - Z_UTIL_LISTIFY_86(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(86, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_88(F, sep, ...) \ - Z_UTIL_LISTIFY_87(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(87, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_89(F, sep, ...) \ - Z_UTIL_LISTIFY_88(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(88, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_90(F, sep, ...) \ - Z_UTIL_LISTIFY_89(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(89, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_91(F, sep, ...) \ - Z_UTIL_LISTIFY_90(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(90, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_92(F, sep, ...) \ - Z_UTIL_LISTIFY_91(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(91, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_93(F, sep, ...) \ - Z_UTIL_LISTIFY_92(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(92, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_94(F, sep, ...) \ - Z_UTIL_LISTIFY_93(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(93, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_95(F, sep, ...) \ - Z_UTIL_LISTIFY_94(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(94, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_96(F, sep, ...) \ - Z_UTIL_LISTIFY_95(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(95, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_97(F, sep, ...) \ - Z_UTIL_LISTIFY_96(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(96, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_98(F, sep, ...) \ - Z_UTIL_LISTIFY_97(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(97, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_99(F, sep, ...) \ - Z_UTIL_LISTIFY_98(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(98, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_100(F, sep, ...) \ - Z_UTIL_LISTIFY_99(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(99, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_101(F, sep, ...) \ - Z_UTIL_LISTIFY_100(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(100, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_102(F, sep, ...) \ - Z_UTIL_LISTIFY_101(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(101, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_103(F, sep, ...) \ - Z_UTIL_LISTIFY_102(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(102, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_104(F, sep, ...) \ - Z_UTIL_LISTIFY_103(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(103, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_105(F, sep, ...) \ - Z_UTIL_LISTIFY_104(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(104, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_106(F, sep, ...) \ - Z_UTIL_LISTIFY_105(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(105, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_107(F, sep, ...) \ - Z_UTIL_LISTIFY_106(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(106, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_108(F, sep, ...) \ - Z_UTIL_LISTIFY_107(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(107, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_109(F, sep, ...) \ - Z_UTIL_LISTIFY_108(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(108, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_110(F, sep, ...) \ - Z_UTIL_LISTIFY_109(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(109, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_111(F, sep, ...) \ - Z_UTIL_LISTIFY_110(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(110, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_112(F, sep, ...) \ - Z_UTIL_LISTIFY_111(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(111, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_113(F, sep, ...) \ - Z_UTIL_LISTIFY_112(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(112, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_114(F, sep, ...) \ - Z_UTIL_LISTIFY_113(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(113, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_115(F, sep, ...) \ - Z_UTIL_LISTIFY_114(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(114, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_116(F, sep, ...) \ - Z_UTIL_LISTIFY_115(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(115, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_117(F, sep, ...) \ - Z_UTIL_LISTIFY_116(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(116, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_118(F, sep, ...) \ - Z_UTIL_LISTIFY_117(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(117, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_119(F, sep, ...) \ - Z_UTIL_LISTIFY_118(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(118, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_120(F, sep, ...) \ - Z_UTIL_LISTIFY_119(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(119, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_121(F, sep, ...) \ - Z_UTIL_LISTIFY_120(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(120, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_122(F, sep, ...) \ - Z_UTIL_LISTIFY_121(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(121, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_123(F, sep, ...) \ - Z_UTIL_LISTIFY_122(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(122, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_124(F, sep, ...) \ - Z_UTIL_LISTIFY_123(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(123, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_125(F, sep, ...) \ - Z_UTIL_LISTIFY_124(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(124, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_126(F, sep, ...) \ - Z_UTIL_LISTIFY_125(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(125, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_127(F, sep, ...) \ - Z_UTIL_LISTIFY_126(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(126, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_128(F, sep, ...) \ - Z_UTIL_LISTIFY_127(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(127, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_129(F, sep, ...) \ - Z_UTIL_LISTIFY_128(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(128, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_130(F, sep, ...) \ - Z_UTIL_LISTIFY_129(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(129, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_131(F, sep, ...) \ - Z_UTIL_LISTIFY_130(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(130, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_132(F, sep, ...) \ - Z_UTIL_LISTIFY_131(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(131, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_133(F, sep, ...) \ - Z_UTIL_LISTIFY_132(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(132, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_134(F, sep, ...) \ - Z_UTIL_LISTIFY_133(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(133, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_135(F, sep, ...) \ - Z_UTIL_LISTIFY_134(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(134, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_136(F, sep, ...) \ - Z_UTIL_LISTIFY_135(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(135, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_137(F, sep, ...) \ - Z_UTIL_LISTIFY_136(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(136, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_138(F, sep, ...) \ - Z_UTIL_LISTIFY_137(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(137, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_139(F, sep, ...) \ - Z_UTIL_LISTIFY_138(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(138, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_140(F, sep, ...) \ - Z_UTIL_LISTIFY_139(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(139, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_141(F, sep, ...) \ - Z_UTIL_LISTIFY_140(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(140, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_142(F, sep, ...) \ - Z_UTIL_LISTIFY_141(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(141, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_143(F, sep, ...) \ - Z_UTIL_LISTIFY_142(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(142, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_144(F, sep, ...) \ - Z_UTIL_LISTIFY_143(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(143, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_145(F, sep, ...) \ - Z_UTIL_LISTIFY_144(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(144, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_146(F, sep, ...) \ - Z_UTIL_LISTIFY_145(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(145, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_147(F, sep, ...) \ - Z_UTIL_LISTIFY_146(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(146, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_148(F, sep, ...) \ - Z_UTIL_LISTIFY_147(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(147, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_149(F, sep, ...) \ - Z_UTIL_LISTIFY_148(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(148, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_150(F, sep, ...) \ - Z_UTIL_LISTIFY_149(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(149, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_151(F, sep, ...) \ - Z_UTIL_LISTIFY_150(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(150, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_152(F, sep, ...) \ - Z_UTIL_LISTIFY_151(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(151, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_153(F, sep, ...) \ - Z_UTIL_LISTIFY_152(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(152, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_154(F, sep, ...) \ - Z_UTIL_LISTIFY_153(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(153, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_155(F, sep, ...) \ - Z_UTIL_LISTIFY_154(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(154, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_156(F, sep, ...) \ - Z_UTIL_LISTIFY_155(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(155, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_157(F, sep, ...) \ - Z_UTIL_LISTIFY_156(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(156, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_158(F, sep, ...) \ - Z_UTIL_LISTIFY_157(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(157, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_159(F, sep, ...) \ - Z_UTIL_LISTIFY_158(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(158, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_160(F, sep, ...) \ - Z_UTIL_LISTIFY_159(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(159, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_161(F, sep, ...) \ - Z_UTIL_LISTIFY_160(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(160, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_162(F, sep, ...) \ - Z_UTIL_LISTIFY_161(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(161, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_163(F, sep, ...) \ - Z_UTIL_LISTIFY_162(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(162, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_164(F, sep, ...) \ - Z_UTIL_LISTIFY_163(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(163, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_165(F, sep, ...) \ - Z_UTIL_LISTIFY_164(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(164, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_166(F, sep, ...) \ - Z_UTIL_LISTIFY_165(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(165, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_167(F, sep, ...) \ - Z_UTIL_LISTIFY_166(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(166, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_168(F, sep, ...) \ - Z_UTIL_LISTIFY_167(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(167, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_169(F, sep, ...) \ - Z_UTIL_LISTIFY_168(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(168, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_170(F, sep, ...) \ - Z_UTIL_LISTIFY_169(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(169, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_171(F, sep, ...) \ - Z_UTIL_LISTIFY_170(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(170, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_172(F, sep, ...) \ - Z_UTIL_LISTIFY_171(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(171, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_173(F, sep, ...) \ - Z_UTIL_LISTIFY_172(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(172, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_174(F, sep, ...) \ - Z_UTIL_LISTIFY_173(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(173, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_175(F, sep, ...) \ - Z_UTIL_LISTIFY_174(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(174, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_176(F, sep, ...) \ - Z_UTIL_LISTIFY_175(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(175, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_177(F, sep, ...) \ - Z_UTIL_LISTIFY_176(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(176, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_178(F, sep, ...) \ - Z_UTIL_LISTIFY_177(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(177, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_179(F, sep, ...) \ - Z_UTIL_LISTIFY_178(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(178, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_180(F, sep, ...) \ - Z_UTIL_LISTIFY_179(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(179, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_181(F, sep, ...) \ - Z_UTIL_LISTIFY_180(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(180, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_182(F, sep, ...) \ - Z_UTIL_LISTIFY_181(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(181, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_183(F, sep, ...) \ - Z_UTIL_LISTIFY_182(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(182, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_184(F, sep, ...) \ - Z_UTIL_LISTIFY_183(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(183, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_185(F, sep, ...) \ - Z_UTIL_LISTIFY_184(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(184, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_186(F, sep, ...) \ - Z_UTIL_LISTIFY_185(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(185, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_187(F, sep, ...) \ - Z_UTIL_LISTIFY_186(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(186, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_188(F, sep, ...) \ - Z_UTIL_LISTIFY_187(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(187, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_189(F, sep, ...) \ - Z_UTIL_LISTIFY_188(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(188, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_190(F, sep, ...) \ - Z_UTIL_LISTIFY_189(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(189, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_191(F, sep, ...) \ - Z_UTIL_LISTIFY_190(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(190, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_192(F, sep, ...) \ - Z_UTIL_LISTIFY_191(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(191, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_193(F, sep, ...) \ - Z_UTIL_LISTIFY_192(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(192, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_194(F, sep, ...) \ - Z_UTIL_LISTIFY_193(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(193, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_195(F, sep, ...) \ - Z_UTIL_LISTIFY_194(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(194, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_196(F, sep, ...) \ - Z_UTIL_LISTIFY_195(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(195, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_197(F, sep, ...) \ - Z_UTIL_LISTIFY_196(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(196, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_198(F, sep, ...) \ - Z_UTIL_LISTIFY_197(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(197, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_199(F, sep, ...) \ - Z_UTIL_LISTIFY_198(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(198, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_200(F, sep, ...) \ - Z_UTIL_LISTIFY_199(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(199, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_201(F, sep, ...) \ - Z_UTIL_LISTIFY_200(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(200, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_202(F, sep, ...) \ - Z_UTIL_LISTIFY_201(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(201, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_203(F, sep, ...) \ - Z_UTIL_LISTIFY_202(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(202, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_204(F, sep, ...) \ - Z_UTIL_LISTIFY_203(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(203, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_205(F, sep, ...) \ - Z_UTIL_LISTIFY_204(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(204, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_206(F, sep, ...) \ - Z_UTIL_LISTIFY_205(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(205, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_207(F, sep, ...) \ - Z_UTIL_LISTIFY_206(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(206, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_208(F, sep, ...) \ - Z_UTIL_LISTIFY_207(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(207, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_209(F, sep, ...) \ - Z_UTIL_LISTIFY_208(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(208, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_210(F, sep, ...) \ - Z_UTIL_LISTIFY_209(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(209, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_211(F, sep, ...) \ - Z_UTIL_LISTIFY_210(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(210, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_212(F, sep, ...) \ - Z_UTIL_LISTIFY_211(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(211, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_213(F, sep, ...) \ - Z_UTIL_LISTIFY_212(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(212, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_214(F, sep, ...) \ - Z_UTIL_LISTIFY_213(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(213, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_215(F, sep, ...) \ - Z_UTIL_LISTIFY_214(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(214, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_216(F, sep, ...) \ - Z_UTIL_LISTIFY_215(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(215, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_217(F, sep, ...) \ - Z_UTIL_LISTIFY_216(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(216, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_218(F, sep, ...) \ - Z_UTIL_LISTIFY_217(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(217, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_219(F, sep, ...) \ - Z_UTIL_LISTIFY_218(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(218, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_220(F, sep, ...) \ - Z_UTIL_LISTIFY_219(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(219, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_221(F, sep, ...) \ - Z_UTIL_LISTIFY_220(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(220, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_222(F, sep, ...) \ - Z_UTIL_LISTIFY_221(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(221, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_223(F, sep, ...) \ - Z_UTIL_LISTIFY_222(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(222, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_224(F, sep, ...) \ - Z_UTIL_LISTIFY_223(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(223, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_225(F, sep, ...) \ - Z_UTIL_LISTIFY_224(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(224, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_226(F, sep, ...) \ - Z_UTIL_LISTIFY_225(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(225, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_227(F, sep, ...) \ - Z_UTIL_LISTIFY_226(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(226, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_228(F, sep, ...) \ - Z_UTIL_LISTIFY_227(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(227, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_229(F, sep, ...) \ - Z_UTIL_LISTIFY_228(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(228, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_230(F, sep, ...) \ - Z_UTIL_LISTIFY_229(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(229, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_231(F, sep, ...) \ - Z_UTIL_LISTIFY_230(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(230, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_232(F, sep, ...) \ - Z_UTIL_LISTIFY_231(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(231, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_233(F, sep, ...) \ - Z_UTIL_LISTIFY_232(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(232, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_234(F, sep, ...) \ - Z_UTIL_LISTIFY_233(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(233, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_235(F, sep, ...) \ - Z_UTIL_LISTIFY_234(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(234, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_236(F, sep, ...) \ - Z_UTIL_LISTIFY_235(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(235, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_237(F, sep, ...) \ - Z_UTIL_LISTIFY_236(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(236, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_238(F, sep, ...) \ - Z_UTIL_LISTIFY_237(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(237, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_239(F, sep, ...) \ - Z_UTIL_LISTIFY_238(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(238, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_240(F, sep, ...) \ - Z_UTIL_LISTIFY_239(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(239, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_241(F, sep, ...) \ - Z_UTIL_LISTIFY_240(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(240, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_242(F, sep, ...) \ - Z_UTIL_LISTIFY_241(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(241, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_243(F, sep, ...) \ - Z_UTIL_LISTIFY_242(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(242, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_244(F, sep, ...) \ - Z_UTIL_LISTIFY_243(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(243, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_245(F, sep, ...) \ - Z_UTIL_LISTIFY_244(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(244, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_246(F, sep, ...) \ - Z_UTIL_LISTIFY_245(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(245, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_247(F, sep, ...) \ - Z_UTIL_LISTIFY_246(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(246, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_248(F, sep, ...) \ - Z_UTIL_LISTIFY_247(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(247, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_249(F, sep, ...) \ - Z_UTIL_LISTIFY_248(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(248, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_250(F, sep, ...) \ - Z_UTIL_LISTIFY_249(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(249, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_251(F, sep, ...) \ - Z_UTIL_LISTIFY_250(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(250, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_252(F, sep, ...) \ - Z_UTIL_LISTIFY_251(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(251, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_253(F, sep, ...) \ - Z_UTIL_LISTIFY_252(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(252, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_254(F, sep, ...) \ - Z_UTIL_LISTIFY_253(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(253, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_255(F, sep, ...) \ - Z_UTIL_LISTIFY_254(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(254, __VA_ARGS__) - -#define Z_UTIL_LISTIFY_256(F, sep, ...) \ - Z_UTIL_LISTIFY_255(F, sep, __VA_ARGS__) __DEBRACKET sep \ - F(255, __VA_ARGS__) +#include "util_listify.h" #endif /* ZEPHYR_INCLUDE_SYS_UTIL_LOOPS_H_ */ diff --git a/include/zephyr/sys/util_macro.h b/include/zephyr/sys/util_macro.h index 1fbc3944be8..02d0e9885a6 100644 --- a/include/zephyr/sys/util_macro.h +++ b/include/zephyr/sys/util_macro.h @@ -256,7 +256,7 @@ extern "C" { * @brief Like a == b, but does evaluation and * short-circuiting at C preprocessor time. * - * This however only works for integer literal from 0 to 255. + * This however only works for integer literal from 0 to 4095. * */ #define IS_EQ(a, b) Z_IS_EQ(a, b) @@ -367,26 +367,26 @@ extern "C" { #define UTIL_AND(a, b) COND_CODE_1(UTIL_BOOL(a), (b), (0)) /** - * @brief UTIL_INC(x) for an integer literal x from 0 to 255 expands to an + * @brief UTIL_INC(x) for an integer literal x from 0 to 4095 expands to an * integer literal whose value is x+1. * * @see UTIL_DEC(x) */ -#define UTIL_INC(x) UTIL_PRIMITIVE_CAT(UTIL_INC_, x) +#define UTIL_INC(x) UTIL_PRIMITIVE_CAT(Z_UTIL_INC_, x) /** - * @brief UTIL_DEC(x) for an integer literal x from 0 to 255 expands to an + * @brief UTIL_DEC(x) for an integer literal x from 0 to 4095 expands to an * integer literal whose value is x-1. * * @see UTIL_INC(x) */ -#define UTIL_DEC(x) UTIL_PRIMITIVE_CAT(UTIL_DEC_, x) +#define UTIL_DEC(x) UTIL_PRIMITIVE_CAT(Z_UTIL_DEC_, x) /** - * @brief UTIL_X2(y) for an integer literal y from 0 to 255 expands to an + * @brief UTIL_X2(y) for an integer literal y from 0 to 4095 expands to an * integer literal whose value is 2y. */ -#define UTIL_X2(y) UTIL_PRIMITIVE_CAT(UTIL_X2_, y) +#define UTIL_X2(y) UTIL_PRIMITIVE_CAT(Z_UTIL_X2_, y) /** @@ -402,7 +402,7 @@ extern "C" { * { MY_PWM0 , MY_PWM1 } * * @param LEN The length of the sequence. Must be an integer literal less - * than 255. + * than 4095. * @param F A macro function that accepts at least two arguments: * F(i, ...). @p F is called repeatedly in the expansion. * Its first argument @p i is the index in the sequence, and diff --git a/include/zephyr/sys_clock.h b/include/zephyr/sys_clock.h index 9fd1f564a36..e43b539fb8f 100644 --- a/include/zephyr/sys_clock.h +++ b/include/zephyr/sys_clock.h @@ -79,6 +79,36 @@ typedef struct { */ #define K_TIMEOUT_EQ(a, b) ((a).ticks == (b).ticks) +/** number of nanoseconds per micorsecond */ +#define NSEC_PER_USEC 1000U + +/** number of nanoseconds per millisecond */ +#define NSEC_PER_MSEC 1000000U + +/** number of microseconds per millisecond */ +#define USEC_PER_MSEC 1000U + +/** number of milliseconds per second */ +#define MSEC_PER_SEC 1000U + +/** number of seconds per minute */ +#define SEC_PER_MIN 60U + +/** number of minutes per hour */ +#define MIN_PER_HOUR 60U + +/** number of hours per day */ +#define HOUR_PER_DAY 24U + +/** number of microseconds per second */ +#define USEC_PER_SEC ((USEC_PER_MSEC) * (MSEC_PER_SEC)) + +/** number of nanoseconds per second */ +#define NSEC_PER_SEC ((NSEC_PER_USEC) * (USEC_PER_MSEC) * (MSEC_PER_SEC)) + +/** @} */ + +/** @cond INTERNAL_HIDDEN */ #define Z_TIMEOUT_NO_WAIT ((k_timeout_t) {0}) #if defined(__cplusplus) && ((__cplusplus - 0) < 202002L) #define Z_TIMEOUT_TICKS(t) ((k_timeout_t) { (t) }) @@ -92,11 +122,13 @@ typedef struct { # define Z_TIMEOUT_US(t) Z_TIMEOUT_TICKS((k_ticks_t)k_us_to_ticks_ceil64(MAX(t, 0))) # define Z_TIMEOUT_NS(t) Z_TIMEOUT_TICKS((k_ticks_t)k_ns_to_ticks_ceil64(MAX(t, 0))) # define Z_TIMEOUT_CYC(t) Z_TIMEOUT_TICKS((k_ticks_t)k_cyc_to_ticks_ceil64(MAX(t, 0))) +# define Z_TIMEOUT_MS_TICKS(t) ((k_ticks_t)k_ms_to_ticks_ceil64(MAX(t, 0))) #else # define Z_TIMEOUT_MS(t) Z_TIMEOUT_TICKS((k_ticks_t)k_ms_to_ticks_ceil32(MAX(t, 0))) # define Z_TIMEOUT_US(t) Z_TIMEOUT_TICKS((k_ticks_t)k_us_to_ticks_ceil32(MAX(t, 0))) # define Z_TIMEOUT_NS(t) Z_TIMEOUT_TICKS((k_ticks_t)k_ns_to_ticks_ceil32(MAX(t, 0))) # define Z_TIMEOUT_CYC(t) Z_TIMEOUT_TICKS((k_ticks_t)k_cyc_to_ticks_ceil32(MAX(t, 0))) +# define Z_TIMEOUT_MS_TICKS(t) ((k_ticks_t)k_ms_to_ticks_ceil32(MAX(t, 0))) #endif /* Converts between absolute timeout expiration values (packed into @@ -109,35 +141,16 @@ typedef struct { */ #define Z_TICK_ABS(t) (K_TICKS_FOREVER - 1 - (t)) -/** @} */ +/* added tick needed to account for tick in progress */ +#define _TICK_ALIGN 1 -#ifdef CONFIG_TICKLESS_KERNEL -extern void z_enable_sys_clock(void); -#endif +/** @endcond */ #if defined(CONFIG_SYS_CLOCK_EXISTS) && \ (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 0) #error "SYS_CLOCK_HW_CYCLES_PER_SEC must be non-zero!" #endif -/* number of nsec per usec */ -#define NSEC_PER_USEC 1000U - -/* number of nsec per msec */ -#define NSEC_PER_MSEC 1000000U - -/* number of microseconds per millisecond */ -#define USEC_PER_MSEC 1000U - -/* number of milliseconds per second */ -#define MSEC_PER_SEC 1000U - -/* number of microseconds per second */ -#define USEC_PER_SEC ((USEC_PER_MSEC) * (MSEC_PER_SEC)) - -/* number of nanoseconds per second */ -#define NSEC_PER_SEC ((NSEC_PER_USEC) * (USEC_PER_MSEC) * (MSEC_PER_SEC)) - /* kernel clocks */ @@ -146,6 +159,10 @@ extern void z_enable_sys_clock(void); * but if the HW timer cycles/sec, ticks/sec and ms/sec are all known * to be nicely related, then we can cheat with 32 bits instead. */ +/** + * @addtogroup clock_apis + * @{ + */ #ifdef CONFIG_SYS_CLOCK_EXISTS @@ -157,10 +174,7 @@ extern void z_enable_sys_clock(void); #endif -/* added tick needed to account for tick in progress */ -#define _TICK_ALIGN 1 - -/* +/** * SYS_CLOCK_HW_CYCLES_TO_NS_AVG converts CPU clock cycles to nanoseconds * and calculates the average cycle time */ @@ -315,6 +329,7 @@ static inline bool sys_timepoint_expired(k_timepoint_t timepoint) return K_TIMEOUT_EQ(sys_timepoint_timeout(timepoint), Z_TIMEOUT_NO_WAIT); } +/** @} */ #ifdef __cplusplus } diff --git a/include/zephyr/syscall_handler.h b/include/zephyr/syscall_handler.h deleted file mode 100644 index 7e06c5a7a54..00000000000 --- a/include/zephyr/syscall_handler.h +++ /dev/null @@ -1,552 +0,0 @@ -/* - * Copyright (c) 2017, Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - - -#ifndef ZEPHYR_INCLUDE_SYSCALL_HANDLER_H_ -#define ZEPHYR_INCLUDE_SYSCALL_HANDLER_H_ - -#ifdef CONFIG_USERSPACE - -#ifndef _ASMLANGUAGE -#include -#include -#include -#include -#include - -extern const _k_syscall_handler_t _k_syscall_table[K_SYSCALL_LIMIT]; - -enum _obj_init_check { - _OBJ_INIT_TRUE = 0, - _OBJ_INIT_FALSE = -1, - _OBJ_INIT_ANY = 1 -}; - -/** - * Return true if we are currently handling a system call from user mode - * - * Inside z_vrfy functions, we always know that we are handling - * a system call invoked from user context. - * - * However, some checks that are only relevant to user mode must - * instead be placed deeper within the implementation. This - * API is useful to conditionally make these checks. - * - * For performance reasons, whenever possible, checks should be placed - * in the relevant z_vrfy function since these are completely skipped - * when a syscall is invoked. - * - * This will return true only if we are handling a syscall for a - * user thread. If the system call was invoked from supervisor mode, - * or we are not handling a system call, this will return false. - * - * @return whether the current context is handling a syscall for a user - * mode thread - */ -static inline bool z_is_in_user_syscall(void) -{ - /* This gets set on entry to the syscall's generasted z_mrsh - * function and then cleared on exit. This code path is only - * encountered when a syscall is made from user mode, system - * calls from supervisor mode bypass everything directly to - * the implementation function. - */ - return !k_is_in_isr() && _current->syscall_frame != NULL; -} - -/** - * Ensure a system object is a valid object of the expected type - * - * Searches for the object and ensures that it is indeed an object - * of the expected type, that the caller has the right permissions on it, - * and that the object has been initialized. - * - * This function is intended to be called on the kernel-side system - * call handlers to validate kernel object pointers passed in from - * userspace. - * - * @param ko Kernel object metadata pointer, or NULL - * @param otype Expected type of the kernel object, or K_OBJ_ANY if type - * doesn't matter - * @param init Indicate whether the object needs to already be in initialized - * or uninitialized state, or that we don't care - * @return 0 If the object is valid - * -EBADF if not a valid object of the specified type - * -EPERM If the caller does not have permissions - * -EINVAL Object is not initialized - */ -int z_object_validate(struct z_object *ko, enum k_objects otype, - enum _obj_init_check init); - -/** - * Dump out error information on failed z_object_validate() call - * - * @param retval Return value from z_object_validate() - * @param obj Kernel object we were trying to verify - * @param ko If retval=-EPERM, struct z_object * that was looked up, or NULL - * @param otype Expected type of the kernel object - */ -extern void z_dump_object_error(int retval, const void *obj, - struct z_object *ko, enum k_objects otype); - -/** - * Kernel object validation function - * - * Retrieve metadata for a kernel object. This function is implemented in - * the gperf script footer, see gen_kobject_list.py - * - * @param obj Address of kernel object to get metadata - * @return Kernel object's metadata, or NULL if the parameter wasn't the - * memory address of a kernel object - */ -extern struct z_object *z_object_find(const void *obj); - -typedef void (*_wordlist_cb_func_t)(struct z_object *ko, void *context); - -/** - * Iterate over all the kernel object metadata in the system - * - * @param func function to run on each struct z_object - * @param context Context pointer to pass to each invocation - */ -extern void z_object_wordlist_foreach(_wordlist_cb_func_t func, void *context); - -/** - * Copy all kernel object permissions from the parent to the child - * - * @param parent Parent thread, to get permissions from - * @param child Child thread, to copy permissions to - */ -extern void z_thread_perms_inherit(struct k_thread *parent, - struct k_thread *child); - -/** - * Grant a thread permission to a kernel object - * - * @param ko Kernel object metadata to update - * @param thread The thread to grant permission - */ -extern void z_thread_perms_set(struct z_object *ko, struct k_thread *thread); - -/** - * Revoke a thread's permission to a kernel object - * - * @param ko Kernel object metadata to update - * @param thread The thread to grant permission - */ -extern void z_thread_perms_clear(struct z_object *ko, struct k_thread *thread); - -/* - * Revoke access to all objects for the provided thread - * - * NOTE: Unlike z_thread_perms_clear(), this function will not clear - * permissions on public objects. - * - * @param thread Thread object to revoke access - */ -extern void z_thread_perms_all_clear(struct k_thread *thread); - -/** - * Clear initialization state of a kernel object - * - * Intended for thread objects upon thread exit, or for other kernel objects - * that were released back to an object pool. - * - * @param object Address of the kernel object - */ -void z_object_uninit(const void *obj); - -/** - * Initialize and reset permissions to only access by the caller - * - * Intended for scenarios where objects are fetched from slab pools - * and may have had different permissions set during prior usage. - * - * This is only intended for pools of objects, where such objects are - * acquired and released to the pool. If an object has already been used, - * we do not want stale permission information hanging around, the object - * should only have permissions on the caller. Objects which are not - * managed by a pool-like mechanism should not use this API. - * - * The object will be marked as initialized and the calling thread - * granted access to it. - * - * @param object Address of the kernel object - */ -void z_object_recycle(const void *obj); - -/** - * @brief Obtain the size of a C string passed from user mode - * - * Given a C string pointer and a maximum size, obtain the true - * size of the string (not including the trailing NULL byte) just as - * if calling strnlen() on it, with the same semantics of strnlen() with - * respect to the return value and the maxlen parameter. - * - * Any memory protection faults triggered by the examination of the string - * will be safely handled and an error code returned. - * - * NOTE: Doesn't guarantee that user mode has actual access to this - * string, you will need to still do a Z_SYSCALL_MEMORY_READ() - * with the obtained size value to guarantee this. - * - * @param src String to measure size of - * @param maxlen Maximum number of characters to examine - * @param err Pointer to int, filled in with -1 on memory error, 0 on - * success - * @return undefined on error, or strlen(src) if that is less than maxlen, or - * maxlen if there were no NULL terminating characters within the - * first maxlen bytes. - */ -static inline size_t z_user_string_nlen(const char *src, size_t maxlen, - int *err) -{ - return arch_user_string_nlen(src, maxlen, err); -} - -/** - * @brief Copy data from userspace into a resource pool allocation - * - * Given a pointer and a size, allocate a similarly sized buffer in the - * caller's resource pool and copy all the data within it to the newly - * allocated buffer. This will need to be freed later with k_free(). - * - * Checks are done to ensure that the current thread would have read - * access to the provided buffer. - * - * @param src Source memory address - * @param size Size of the memory buffer - * @return An allocated buffer with the data copied within it, or NULL - * if some error condition occurred - */ -extern void *z_user_alloc_from_copy(const void *src, size_t size); - -/** - * @brief Copy data from user mode - * - * Given a userspace pointer and a size, copies data from it into a provided - * destination buffer, performing checks to ensure that the caller would have - * appropriate access when in user mode. - * - * @param dst Destination memory buffer - * @param src Source memory buffer, in userspace - * @param size Number of bytes to copy - * @retval 0 On success - * @retval EFAULT On memory access error - */ -extern int z_user_from_copy(void *dst, const void *src, size_t size); - -/** - * @brief Copy data to user mode - * - * Given a userspace pointer and a size, copies data to it from a provided - * source buffer, performing checks to ensure that the caller would have - * appropriate access when in user mode. - * - * @param dst Destination memory buffer, in userspace - * @param src Source memory buffer - * @param size Number of bytes to copy - * @retval 0 On success - * @retval EFAULT On memory access error - */ -extern int z_user_to_copy(void *dst, const void *src, size_t size); - -/** - * @brief Copy a C string from userspace into a resource pool allocation - * - * Given a C string and maximum length, duplicate the string using an - * allocation from the calling thread's resource pool. This will need to be - * freed later with k_free(). - * - * Checks are performed to ensure that the string is valid memory and that - * the caller has access to it in user mode. - * - * @param src Source string pointer, in userspace - * @param maxlen Maximum size of the string including trailing NULL - * @return The duplicated string, or NULL if an error occurred. - */ -extern char *z_user_string_alloc_copy(const char *src, size_t maxlen); - -/** - * @brief Copy a C string from userspace into a provided buffer - * - * Given a C string and maximum length, copy the string into a buffer. - * - * Checks are performed to ensure that the string is valid memory and that - * the caller has access to it in user mode. - * - * @param dst Destination buffer - * @param src Source string pointer, in userspace - * @param maxlen Maximum size of the string including trailing NULL - * @retval 0 on success - * @retval EINVAL if the source string is too long with respect - * to maxlen - * @retval EFAULT On memory access error - */ -extern int z_user_string_copy(char *dst, const char *src, size_t maxlen); - -#define Z_OOPS(expr) \ - do { \ - if (expr) { \ - arch_syscall_oops(_current->syscall_frame); \ - } \ - } while (false) - -/** - * @brief Runtime expression check for system call arguments - * - * Used in handler functions to perform various runtime checks on arguments, - * and generate a kernel oops if anything is not expected, printing a custom - * message. - * - * @param expr Boolean expression to verify, a false result will trigger an - * oops - * @param fmt Printf-style format string (followed by appropriate variadic - * arguments) to print on verification failure - * @return False on success, True on failure - */ -#define Z_SYSCALL_VERIFY_MSG(expr, fmt, ...) ({ \ - bool expr_copy = !(expr); \ - if (expr_copy) { \ - TOOLCHAIN_IGNORE_WSHADOW_BEGIN \ - LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); \ - TOOLCHAIN_IGNORE_WSHADOW_END \ - LOG_ERR("syscall %s failed check: " fmt, \ - __func__, ##__VA_ARGS__); \ - } \ - expr_copy; }) - -/** - * @brief Runtime expression check for system call arguments - * - * Used in handler functions to perform various runtime checks on arguments, - * and generate a kernel oops if anything is not expected. - * - * @param expr Boolean expression to verify, a false result will trigger an - * oops. A stringified version of this expression will be printed. - * @return 0 on success, nonzero on failure - */ -#define Z_SYSCALL_VERIFY(expr) Z_SYSCALL_VERIFY_MSG(expr, #expr) - -/** - * @brief Runtime check that a user thread has read and/or write permission to - * a memory area - * - * Checks that the particular memory area is readable and/or writeable by the - * currently running thread if the CPU was in user mode, and generates a kernel - * oops if it wasn't. Prevents userspace from getting the kernel to read and/or - * modify memory the thread does not have access to, or passing in garbage - * pointers that would crash/pagefault the kernel if dereferenced. - * - * @param ptr Memory area to examine - * @param size Size of the memory area - * @param write If the thread should be able to write to this memory, not just - * read it - * @return 0 on success, nonzero on failure - */ -#define Z_SYSCALL_MEMORY(ptr, size, write) \ - Z_SYSCALL_VERIFY_MSG(arch_buffer_validate((void *)ptr, size, write) \ - == 0, \ - "Memory region %p (size %zu) %s access denied", \ - (void *)(ptr), (size_t)(size), \ - write ? "write" : "read") - -/** - * @brief Runtime check that a user thread has read permission to a memory area - * - * Checks that the particular memory area is readable by the currently running - * thread if the CPU was in user mode, and generates a kernel oops if it - * wasn't. Prevents userspace from getting the kernel to read memory the thread - * does not have access to, or passing in garbage pointers that would - * crash/pagefault the kernel if dereferenced. - * - * @param ptr Memory area to examine - * @param size Size of the memory area - * @return 0 on success, nonzero on failure - */ -#define Z_SYSCALL_MEMORY_READ(ptr, size) \ - Z_SYSCALL_MEMORY(ptr, size, 0) - -/** - * @brief Runtime check that a user thread has write permission to a memory area - * - * Checks that the particular memory area is readable and writable by the - * currently running thread if the CPU was in user mode, and generates a kernel - * oops if it wasn't. Prevents userspace from getting the kernel to read or - * modify memory the thread does not have access to, or passing in garbage - * pointers that would crash/pagefault the kernel if dereferenced. - * - * @param ptr Memory area to examine - * @param size Size of the memory area - * @param 0 on success, nonzero on failure - */ -#define Z_SYSCALL_MEMORY_WRITE(ptr, size) \ - Z_SYSCALL_MEMORY(ptr, size, 1) - -#define Z_SYSCALL_MEMORY_ARRAY(ptr, nmemb, size, write) \ - ({ \ - size_t product; \ - Z_SYSCALL_VERIFY_MSG(!size_mul_overflow((size_t)(nmemb), \ - (size_t)(size), \ - &product), \ - "%zux%zu array is too large", \ - (size_t)(nmemb), (size_t)(size)) || \ - Z_SYSCALL_MEMORY(ptr, product, write); \ - }) - -/** - * @brief Validate user thread has read permission for sized array - * - * Used when the memory region is expressed in terms of number of elements and - * each element size, handles any overflow issues with computing the total - * array bounds. Otherwise see _SYSCALL_MEMORY_READ. - * - * @param ptr Memory area to examine - * @param nmemb Number of elements in the array - * @param size Size of each array element - * @return 0 on success, nonzero on failure - */ -#define Z_SYSCALL_MEMORY_ARRAY_READ(ptr, nmemb, size) \ - Z_SYSCALL_MEMORY_ARRAY(ptr, nmemb, size, 0) - -/** - * @brief Validate user thread has read/write permission for sized array - * - * Used when the memory region is expressed in terms of number of elements and - * each element size, handles any overflow issues with computing the total - * array bounds. Otherwise see _SYSCALL_MEMORY_WRITE. - * - * @param ptr Memory area to examine - * @param nmemb Number of elements in the array - * @param size Size of each array element - * @return 0 on success, nonzero on failure - */ -#define Z_SYSCALL_MEMORY_ARRAY_WRITE(ptr, nmemb, size) \ - Z_SYSCALL_MEMORY_ARRAY(ptr, nmemb, size, 1) - -static inline int z_obj_validation_check(struct z_object *ko, - const void *obj, - enum k_objects otype, - enum _obj_init_check init) -{ - int ret; - - ret = z_object_validate(ko, otype, init); - -#ifdef CONFIG_LOG - if (ret != 0) { - z_dump_object_error(ret, obj, ko, otype); - } -#else - ARG_UNUSED(obj); -#endif - - return ret; -} - -#define Z_SYSCALL_IS_OBJ(ptr, type, init) \ - Z_SYSCALL_VERIFY_MSG(z_obj_validation_check( \ - z_object_find((const void *)ptr), \ - (const void *)ptr, \ - type, init) == 0, "access denied") - -/** - * @brief Runtime check driver object pointer for presence of operation - * - * Validates if the driver object is capable of performing a certain operation. - * - * @param ptr Untrusted device instance object pointer - * @param api_struct Name of the driver API struct (e.g. gpio_driver_api) - * @param op Driver operation (e.g. manage_callback) - * @return 0 on success, nonzero on failure - */ -#define Z_SYSCALL_DRIVER_OP(ptr, api_name, op) \ - ({ \ - struct api_name *__device__ = (struct api_name *) \ - ((const struct device *)ptr)->api; \ - Z_SYSCALL_VERIFY_MSG(__device__->op != NULL, \ - "Operation %s not defined for driver " \ - "instance %p", \ - # op, __device__); \ - }) - -/** - * @brief Runtime check that device object is of a specific driver type - * - * Checks that the driver object passed in is initialized, the caller has - * correct permissions, and that it belongs to the specified driver - * subsystems. Additionally, all devices store a structure pointer of the - * driver's API. If this doesn't match the value provided, the check will fail. - * - * This provides an easy way to determine if a device object not only - * belongs to a particular subsystem, but is of a specific device driver - * implementation. Useful for defining out-of-subsystem system calls - * which are implemented for only one driver. - * - * @param _device Untrusted device pointer - * @param _dtype Expected kernel object type for the provided device pointer - * @param _api Expected driver API structure memory address - * @return 0 on success, nonzero on failure - */ -#define Z_SYSCALL_SPECIFIC_DRIVER(_device, _dtype, _api) \ - ({ \ - const struct device *_dev = (const struct device *)_device; \ - Z_SYSCALL_OBJ(_dev, _dtype) || \ - Z_SYSCALL_VERIFY_MSG(_dev->api == _api, \ - "API structure mismatch"); \ - }) - -/** - * @brief Runtime check kernel object pointer for non-init functions - * - * Calls z_object_validate and triggers a kernel oops if the check fails. - * For use in system call handlers which are not init functions; a fatal - * error will occur if the object is not initialized. - * - * @param ptr Untrusted kernel object pointer - * @param type Expected kernel object type - * @return 0 on success, nonzero on failure - */ -#define Z_SYSCALL_OBJ(ptr, type) \ - Z_SYSCALL_IS_OBJ(ptr, type, _OBJ_INIT_TRUE) - -/** - * @brief Runtime check kernel object pointer for non-init functions - * - * See description of _SYSCALL_IS_OBJ. No initialization checks are done. - * Intended for init functions where objects may be re-initialized at will. - * - * @param ptr Untrusted kernel object pointer - * @param type Expected kernel object type - * @return 0 on success, nonzero on failure - */ - -#define Z_SYSCALL_OBJ_INIT(ptr, type) \ - Z_SYSCALL_IS_OBJ(ptr, type, _OBJ_INIT_ANY) - -/** - * @brief Runtime check kernel object pointer for non-init functions - * - * See description of _SYSCALL_IS_OBJ. Triggers a fatal error if the object is - * initialized. Intended for init functions where objects, once initialized, - * can only be re-used when their initialization state expires due to some - * other mechanism. - * - * @param ptr Untrusted kernel object pointer - * @param type Expected kernel object type - * @return 0 on success, nonzero on failure - */ - -#define Z_SYSCALL_OBJ_NEVER_INIT(ptr, type) \ - Z_SYSCALL_IS_OBJ(ptr, type, _OBJ_INIT_FALSE) - -#include - -#endif /* _ASMLANGUAGE */ - -#endif /* CONFIG_USERSPACE */ - -#endif /* ZEPHYR_INCLUDE_SYSCALL_HANDLER_H_ */ diff --git a/include/zephyr/toolchain.h b/include/zephyr/toolchain.h index e46c19689da..27e4a46956c 100644 --- a/include/zephyr/toolchain.h +++ b/include/zephyr/toolchain.h @@ -115,6 +115,14 @@ #define TOOLCHAIN_HAS_C_AUTO_TYPE 0 #endif +/** + * @def TOOLCHAIN_HAS_ZLA + * @brief Indicate if toolchain supports Zero Length Arrays. + */ +#ifndef TOOLCHAIN_HAS_ZLA +#define TOOLCHAIN_HAS_ZLA 0 +#endif + /** * @def TOOLCHAIN_IGNORE_WSHADOW_BEGIN * @brief Begin of block to ignore -Wshadow. diff --git a/include/zephyr/toolchain/armclang.h b/include/zephyr/toolchain/armclang.h index 89081227be0..d8dfa235a16 100644 --- a/include/zephyr/toolchain/armclang.h +++ b/include/zephyr/toolchain/armclang.h @@ -7,6 +7,9 @@ #ifndef ZEPHYR_INCLUDE_TOOLCHAIN_ARMCLANG_H_ #define ZEPHYR_INCLUDE_TOOLCHAIN_ARMCLANG_H_ +#ifndef ZEPHYR_INCLUDE_TOOLCHAIN_H_ +#error Please do not include toolchain-specific headers directly, use instead +#endif #include diff --git a/include/zephyr/toolchain/common.h b/include/zephyr/toolchain/common.h index ea6c0db5f4e..c84328365fd 100644 --- a/include/zephyr/toolchain/common.h +++ b/include/zephyr/toolchain/common.h @@ -6,6 +6,11 @@ #ifndef ZEPHYR_INCLUDE_TOOLCHAIN_COMMON_H_ #define ZEPHYR_INCLUDE_TOOLCHAIN_COMMON_H_ + +#ifndef ZEPHYR_INCLUDE_TOOLCHAIN_H_ +#error Please do not include toolchain-specific headers directly, use instead +#endif + /** * @file * @brief Common toolchain abstraction diff --git a/include/zephyr/toolchain/gcc.h b/include/zephyr/toolchain/gcc.h index 4e30158a341..d3dce3b253f 100644 --- a/include/zephyr/toolchain/gcc.h +++ b/include/zephyr/toolchain/gcc.h @@ -7,6 +7,10 @@ #ifndef ZEPHYR_INCLUDE_TOOLCHAIN_GCC_H_ #define ZEPHYR_INCLUDE_TOOLCHAIN_GCC_H_ +#ifndef ZEPHYR_INCLUDE_TOOLCHAIN_H_ +#error Please do not include toolchain-specific headers directly, use instead +#endif + /** * @file * @brief GCC toolchain abstraction @@ -30,6 +34,8 @@ #define TOOLCHAIN_HAS_C_AUTO_TYPE 1 #endif +#define TOOLCHAIN_HAS_ZLA 1 + /* * Older versions of GCC do not define __BYTE_ORDER__, so it must be manually * detected and defined using arch-specific definitions. @@ -194,8 +200,13 @@ do { \ #if !defined(CONFIG_XIP) #define __ramfunc #elif defined(CONFIG_ARCH_HAS_RAMFUNC_SUPPORT) +#if defined(CONFIG_ARM) #define __ramfunc __attribute__((noinline)) \ __attribute__((long_call, section(".ramfunc"))) +#else +#define __ramfunc __attribute__((noinline)) \ + __attribute__((section(".ramfunc"))) +#endif #endif /* !CONFIG_XIP */ #ifndef __fallthrough @@ -263,6 +274,10 @@ do { \ #define __weak __attribute__((__weak__)) #endif +#ifndef __attribute_nonnull +#define __attribute_nonnull(...) __attribute__((nonnull(__VA_ARGS__))) +#endif + /* Builtins with availability that depend on the compiler version. */ #if __GNUC__ >= 5 #define HAS_BUILTIN___builtin_add_overflow 1 diff --git a/include/zephyr/toolchain/llvm.h b/include/zephyr/toolchain/llvm.h index 990cbe6ada4..8a78d4e8404 100644 --- a/include/zephyr/toolchain/llvm.h +++ b/include/zephyr/toolchain/llvm.h @@ -7,6 +7,9 @@ #ifndef ZEPHYR_INCLUDE_TOOLCHAIN_LLVM_H_ #define ZEPHYR_INCLUDE_TOOLCHAIN_LLVM_H_ +#ifndef ZEPHYR_INCLUDE_TOOLCHAIN_H_ +#error Please do not include toolchain-specific headers directly, use instead +#endif #define __no_optimization __attribute__((optnone)) diff --git a/include/zephyr/toolchain/mwdt.h b/include/zephyr/toolchain/mwdt.h index 60bcc1c4919..0da5e7bbee5 100644 --- a/include/zephyr/toolchain/mwdt.h +++ b/include/zephyr/toolchain/mwdt.h @@ -8,6 +8,10 @@ #ifndef ZEPHYR_INCLUDE_TOOLCHAIN_MWDT_H_ #define ZEPHYR_INCLUDE_TOOLCHAIN_MWDT_H_ +#ifndef ZEPHYR_INCLUDE_TOOLCHAIN_H_ +#error Please do not include toolchain-specific headers directly, use instead +#endif + #ifndef _LINKER #if defined(_ASMLANGUAGE) diff --git a/include/zephyr/toolchain/xcc.h b/include/zephyr/toolchain/xcc.h index 65ddc7ea35e..ae4bb811ec0 100644 --- a/include/zephyr/toolchain/xcc.h +++ b/include/zephyr/toolchain/xcc.h @@ -7,6 +7,10 @@ #ifndef ZEPHYR_INCLUDE_TOOLCHAIN_XCC_H_ #define ZEPHYR_INCLUDE_TOOLCHAIN_XCC_H_ +#ifndef ZEPHYR_INCLUDE_TOOLCHAIN_H_ +#error Please do not include toolchain-specific headers directly, use instead +#endif + /* toolchain/gcc.h errors out if __BYTE_ORDER__ cannot be determined * there. However, __BYTE_ORDER__ is actually being defined later in * this file. So define __BYTE_ORDER__ to skip the check in gcc.h diff --git a/include/zephyr/tracing/tracing.h b/include/zephyr/tracing/tracing.h index a8500e6eda9..baf9632a30d 100644 --- a/include/zephyr/tracing/tracing.h +++ b/include/zephyr/tracing/tracing.h @@ -1633,20 +1633,6 @@ */ #define sys_port_trace_k_pipe_get_exit(pipe, timeout, ret) -/** - * @brief Trace Pipe block put enter - * @param pipe Pipe object - * @param sem Semaphore object - */ -#define sys_port_trace_k_pipe_block_put_enter(pipe, sem) - -/** - * @brief Trace Pipe block put exit - * @param pipe Pipe object - * @param sem Semaphore object - */ -#define sys_port_trace_k_pipe_block_put_exit(pipe, sem) - /** @} */ /* end of subsys_tracing_apis_pipe */ /** diff --git a/include/zephyr/tracing/tracing_macros.h b/include/zephyr/tracing/tracing_macros.h index 5f0f871aac7..7ed990617d5 100644 --- a/include/zephyr/tracing/tracing_macros.h +++ b/include/zephyr/tracing/tracing_macros.h @@ -6,6 +6,8 @@ #ifndef ZEPHYR_INCLUDE_TRACING_TRACING_MACROS_H_ #define ZEPHYR_INCLUDE_TRACING_TRACING_MACROS_H_ +#include + #if !defined(CONFIG_TRACING) && !defined(__DOXYGEN__) #define SYS_PORT_TRACING_FUNC(type, func, ...) do { } while (false) @@ -73,6 +75,7 @@ #define sys_port_trace_type_mask_k_thread(trace_call) trace_call #else #define sys_port_trace_type_mask_k_thread(trace_call) + #define sys_port_trace_k_thread_is_disabled 1 #endif #if defined(CONFIG_TRACING_WORK) @@ -173,6 +176,29 @@ #define sys_port_trace_type_mask_k_event(trace_call) #endif +#ifndef CONFIG_TRACING_POLLING + #define sys_port_trace_k_poll_api_is_disabled 1 + #define sys_port_trace_k_work_poll_is_disabled 1 +#endif + +#ifndef CONFIG_TRACING_PM + #define sys_port_trace_pm_is_disabled 1 +#endif + +/* + * We cannot positively enumerate all traced APIs, as applications may trace + * arbitrary custom APIs we know nothing about. Therefore we demand that tracing + * of an API must be actively disabled. + * + * This contrasts with object tracing/tracking as all traceable objects are well + * known, see the SYS_PORT_TRACING_TYPE_MASK approach below. + */ +#define _SYS_PORT_TRACE_IS_DISABLED(type) sys_port_trace_##type##_is_disabled +#define _SYS_PORT_TRACE_WRAP(func, ...) do { func(__VA_ARGS__); } while (false) +#define _SYS_PORT_TRACE_IF_NOT_DISABLED(type, func, ...) \ + COND_CODE_1(_SYS_PORT_TRACE_IS_DISABLED(type), (), \ + (_SYS_PORT_TRACE_WRAP(func, __VA_ARGS__))) + /** @endcond */ /** @@ -194,10 +220,8 @@ * system calls etc. That is, we can often omit the z_vrfy/z_impl part of the name. * @param ... Additional parameters relevant to the tracing call */ -#define SYS_PORT_TRACING_FUNC(type, func, ...) \ - do { \ - _SYS_PORT_TRACING_FUNC(type, func)(__VA_ARGS__); \ - } while (false) +#define SYS_PORT_TRACING_FUNC(type, func, ...) \ + _SYS_PORT_TRACE_IF_NOT_DISABLED(type, _SYS_PORT_TRACING_FUNC(type, func), __VA_ARGS__) /** * @brief Tracing macro for the entry into a function that might or might not return @@ -209,10 +233,8 @@ * system calls etc. That is, we can often omit the z_vrfy/z_impl part of the name. * @param ... Additional parameters relevant to the tracing call */ -#define SYS_PORT_TRACING_FUNC_ENTER(type, func, ...) \ - do { \ - _SYS_PORT_TRACING_FUNC_ENTER(type, func)(__VA_ARGS__); \ - } while (false) +#define SYS_PORT_TRACING_FUNC_ENTER(type, func, ...) \ + _SYS_PORT_TRACE_IF_NOT_DISABLED(type, _SYS_PORT_TRACING_FUNC_ENTER(type, func), __VA_ARGS__) /** * @brief Tracing macro for when a function blocks during its execution. @@ -223,10 +245,9 @@ * system calls etc. That is, we can often omit the z_vrfy/z_impl part of the name. * @param ... Additional parameters relevant to the tracing call */ -#define SYS_PORT_TRACING_FUNC_BLOCKING(type, func, ...) \ - do { \ - _SYS_PORT_TRACING_FUNC_BLOCKING(type, func)(__VA_ARGS__); \ - } while (false) +#define SYS_PORT_TRACING_FUNC_BLOCKING(type, func, ...) \ + _SYS_PORT_TRACE_IF_NOT_DISABLED(type, _SYS_PORT_TRACING_FUNC_BLOCKING(type, func), \ + __VA_ARGS__) /** * @brief Tracing macro for when a function ends its execution. Potential return values @@ -238,10 +259,8 @@ * system calls etc. That is, we can often omit the z_vrfy/z_impl part of the name. * @param ... Additional parameters relevant to the tracing call */ -#define SYS_PORT_TRACING_FUNC_EXIT(type, func, ...) \ - do { \ - _SYS_PORT_TRACING_FUNC_EXIT(type, func)(__VA_ARGS__); \ - } while (false) +#define SYS_PORT_TRACING_FUNC_EXIT(type, func, ...) \ + _SYS_PORT_TRACE_IF_NOT_DISABLED(type, _SYS_PORT_TRACING_FUNC_EXIT(type, func), __VA_ARGS__) /** * @brief Tracing macro for the initialization of an object. diff --git a/include/zephyr/usb/class/usb_audio.h b/include/zephyr/usb/class/usb_audio.h index 26c58c75086..9062af37206 100644 --- a/include/zephyr/usb/class/usb_audio.h +++ b/include/zephyr/usb/class/usb_audio.h @@ -26,7 +26,7 @@ #include #include -/** Audio Interface Subclass Codes +/** Audio Interface Subclass Codes. * Refer to Table A-2 from audio10.pdf */ enum usb_audio_int_subclass_codes { @@ -36,7 +36,7 @@ enum usb_audio_int_subclass_codes { USB_AUDIO_MIDISTREAMING = 0x03 }; -/** Audio Class-Specific AC Interface Descriptor Subtypes +/** Audio Class-Specific AC Interface Descriptor Subtypes. * Refer to Table A-5 from audio10.pdf */ enum usb_audio_cs_ac_int_desc_subtypes { @@ -100,39 +100,81 @@ enum usb_audio_fucs { * Refer to Table 2-1 - Table 2-4 from termt10.pdf */ enum usb_audio_terminal_types { - /* USB Terminal Types */ + /** + * @name USB Terminal Types + * @{ + */ + /** USB undefined */ USB_AUDIO_USB_UNDEFINED = 0x0100, + /** USB streaming */ USB_AUDIO_USB_STREAMING = 0x0101, + /** USB vendor specific */ USB_AUDIO_USB_VENDOR_SPEC = 0x01FF, + /** @} */ - /* Input Terminal Types */ + /** + * @name Input Terminal Types + * @{ + */ + /** Input undefined */ USB_AUDIO_IN_UNDEFINED = 0x0200, + /** Microphone */ USB_AUDIO_IN_MICROPHONE = 0x0201, + /** Desktop microphone */ USB_AUDIO_IN_DESKTOP_MIC = 0x0202, + /** Personal microphone */ USB_AUDIO_IN_PERSONAL_MIC = 0x0203, + /** Omni directional microphone */ USB_AUDIO_IN_OM_DIR_MIC = 0x0204, + /** Microphone array */ USB_AUDIO_IN_MIC_ARRAY = 0x0205, + /** Processing microphone array */ USB_AUDIO_IN_PROC_MIC_ARRAY = 0x0205, + /** @} */ - /* Output Terminal Types */ + /** + * @name Output Terminal Types + * @{ + */ + /** Output undefined */ USB_AUDIO_OUT_UNDEFINED = 0x0300, + /** Speaker */ USB_AUDIO_OUT_SPEAKER = 0x0301, + /** Headphones */ USB_AUDIO_OUT_HEADPHONES = 0x0302, + /** Head mounted display audio */ USB_AUDIO_OUT_HEAD_AUDIO = 0x0303, + /** Desktop speaker */ USB_AUDIO_OUT_DESKTOP_SPEAKER = 0x0304, + /** Room speaker */ USB_AUDIO_OUT_ROOM_SPEAKER = 0x0305, + /** Communication speaker */ USB_AUDIO_OUT_COMM_SPEAKER = 0x0306, + /** Low frequency effects speaker */ USB_AUDIO_OUT_LOW_FREQ_SPEAKER = 0x0307, + /** @} */ - /* Bi-directional Terminal Types */ + /** + * @name Bi-directional Terminal Types + * @{ + */ + /** Bidirectional undefined */ USB_AUDIO_IO_UNDEFINED = 0x0400, + /** Handset */ USB_AUDIO_IO_HANDSET = 0x0401, + /** Headset */ USB_AUDIO_IO_HEADSET = 0x0402, + /** Speakerphone, no echo reduction */ USB_AUDIO_IO_SPEAKERPHONE_ECHO_NONE = 0x0403, + /** Speakerphone, echo reduction */ USB_AUDIO_IO_SPEAKERPHONE_ECHO_SUP = 0x0404, + /** Speakerphone, echo cancellation */ USB_AUDIO_IO_SPEAKERPHONE_ECHO_CAN = 0x0405, }; +/** + * @brief Audio device direction. + */ enum usb_audio_direction { USB_AUDIO_IN = 0x00, USB_AUDIO_OUT = 0x01 @@ -143,20 +185,23 @@ enum usb_audio_direction { * * The event structure is used by feature_update_cb in order to inform the App * whenever the Host has modified one of the device features. - * - * @param dir The device direction that has been changed. Applicable for - * Headset device only. - * @param cs Control selector, feature that has been changed. - * @param channel Device channel that has been changed. If 0xFF, then - * all channels have been changed. - * @param val_len Length of the val field. - * @param val Value of the feature that has been set. */ struct usb_audio_fu_evt { + /** + * The device direction that has been changed. + * Applicable for Headset device only. + */ enum usb_audio_direction dir; + /** Control selector feature that has been changed. */ enum usb_audio_fucs cs; + /** + * Device channel that has been changed. + * If 0xFF, then all channels have been changed. + */ uint8_t channel; + /** Length of the val field. */ uint8_t val_len; + /** Value of the feature that has been set. */ const void *val; }; @@ -214,22 +259,22 @@ typedef void (*usb_audio_feature_updated_cb_t)(const struct device *dev, * to callback documentation above. */ struct usb_audio_ops { - /* Callback called when data could be send */ + /** Callback called when data could be send */ usb_audio_data_request_cb_t data_request_cb; - /* Callback called when data were successfully written with sending + /** Callback called when data were successfully written with sending * capable device. Applicable for headset and microphone. Unused for * headphones. */ usb_audio_data_completion_cb_t data_written_cb; - /* Callback called when data were successfully received by receive + /** Callback called when data were successfully received by receive * capable device. Applicable for headset and headphones. Unused for * microphone. */ usb_audio_data_completion_cb_t data_received_cb; - /* Callback called when features were modified by the Host */ + /** Callback called when features were modified by the Host */ usb_audio_feature_updated_cb_t feature_update_cb; }; diff --git a/include/zephyr/usb/usbh.h b/include/zephyr/usb/usbh.h index 022a4d64653..66ba43072c4 100644 --- a/include/zephyr/usb/usbh.h +++ b/include/zephyr/usb/usbh.h @@ -54,29 +54,15 @@ struct usbh_contex { } /** - * @brief USB host peripheral structure + * @brief USB Class Code triple */ -struct usbh_peripheral { - /** Peripheral dlist node */ - sys_dnode_t node; - /** Peripheral address */ - uint8_t addr; - /** Detected speed (TBD) */ - uint8_t speed; -}; - -/** - * @brief Class Code - */ -struct usbh_class_code { +struct usbh_code_triple { /** Device Class Code */ uint8_t dclass; /** Class Subclass Code */ uint8_t sub; /** Class Protocol Code */ uint8_t proto; - /** Reserved */ - uint8_t reserved; }; /** @@ -84,7 +70,7 @@ struct usbh_class_code { */ struct usbh_class_data { /** Class code supported by this instance */ - struct usbh_class_code code; + struct usbh_code_triple code; /** Initialization of the class implementation */ /* int (*init)(struct usbh_contex *const uhs_ctx); */ diff --git a/include/zephyr/usb_c/usbc.h b/include/zephyr/usb_c/usbc.h index 0a37b081838..db3045d03c1 100644 --- a/include/zephyr/usb_c/usbc.h +++ b/include/zephyr/usb_c/usbc.h @@ -350,6 +350,15 @@ int usbc_suspend(const struct device *dev); */ int usbc_request(const struct device *dev, const enum usbc_policy_request_t req); +/** + * @internal + * @brief Bypass the next USB-C stack sleep and execute one more iteration of the state machines. + * Used internally to decrease the response time. + * + * @param dev Runtime device structure + */ +void usbc_bypass_next_sleep(const struct device *dev); + /** * @brief Set pointer to Device Policy Manager (DPM) data * diff --git a/include/zephyr/xen/dom0/domctl.h b/include/zephyr/xen/dom0/domctl.h new file mode 100644 index 00000000000..6dfe9053887 --- /dev/null +++ b/include/zephyr/xen/dom0/domctl.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2023 EPAM Systems + * + */ +#ifndef __XEN_DOM0_DOMCTL_H__ +#define __XEN_DOM0_DOMCTL_H__ + +#include +#include +#include + +#include + +int xen_domctl_scheduler_op(int domid, struct xen_domctl_scheduler_op *sched_op); +int xen_domctl_pausedomain(int domid); +int xen_domctl_unpausedomain(int domid); +int xen_domctl_resumedomain(int domid); +int xen_domctl_getvcpucontext(int domid, int vcpu, vcpu_guest_context_t *ctxt); +int xen_domctl_setvcpucontext(int domid, int vcpu, vcpu_guest_context_t *ctxt); +int xen_domctl_getdomaininfo(int domid, xen_domctl_getdomaininfo_t *dom_info); +int xen_domctl_set_paging_mempool_size(int domid, uint64_t size_mb); +int xen_domctl_max_mem(int domid, uint64_t max_memkb); +int xen_domctl_set_address_size(int domid, int addr_size); +int xen_domctl_iomem_permission(int domid, uint64_t first_mfn, + uint64_t nr_mfns, uint8_t allow_access); +int xen_domctl_memory_mapping(int domid, uint64_t first_gfn, uint64_t first_mfn, + uint64_t nr_mfns, uint32_t add_mapping); +int xen_domctl_assign_dt_device(int domid, char *dtdev_path); +int xen_domctl_bind_pt_irq(int domid, uint32_t machine_irq, uint8_t irq_type, uint8_t bus, + uint8_t device, uint8_t intx, uint8_t isa_irq, uint16_t spi); +int xen_domctl_max_vcpus(int domid, int max_vcpus); +int xen_domctl_createdomain(int domid, struct xen_domctl_createdomain *config); +int xen_domctl_cacheflush(int domid, struct xen_domctl_cacheflush *cacheflush); +int xen_domctl_destroydomain(int domid); + +#endif /* __XEN_DOM0_DOMCTL_H__ */ diff --git a/include/zephyr/xen/events.h b/include/zephyr/xen/events.h index d2a936a59ed..cbad8162cbb 100644 --- a/include/zephyr/xen/events.h +++ b/include/zephyr/xen/events.h @@ -36,6 +36,17 @@ void notify_evtchn(evtchn_port_t port); */ int alloc_unbound_event_channel(domid_t remote_dom); +#ifdef CONFIG_XEN_DOM0 +/* + * Allocate event-channel between remote domains. Can be used only from Dom0. + * + * @param dom - first remote domain domid (may be DOMID_SELF) + * @param remote_dom - second remote domain domid + * @return - local event channel port on success, negative on error + */ +int alloc_unbound_event_channel_dom0(domid_t dom, domid_t remote_dom); +#endif /* CONFIG_XEN_DOM0 */ + /* * Allocate local event channel, binded to remote port and attach specified callback * to it diff --git a/include/zephyr/xen/hvm.h b/include/zephyr/xen/hvm.h index 968abf01c1a..1848705975a 100644 --- a/include/zephyr/xen/hvm.h +++ b/include/zephyr/xen/hvm.h @@ -11,7 +11,7 @@ #include -int hvm_set_parameter(int idx, uint64_t value); -int hvm_get_parameter(int idx, uint64_t *value); +int hvm_set_parameter(int idx, int domid, uint64_t value); +int hvm_get_parameter(int idx, int domid, uint64_t *value); #endif /* __XEN_HVM_H__ */ diff --git a/include/zephyr/xen/memory.h b/include/zephyr/xen/memory.h new file mode 100644 index 00000000000..636f0998856 --- /dev/null +++ b/include/zephyr/xen/memory.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2023 EPAM Systems + */ + +#include +#include +#include + +/** + * Add mapping for specified page frame in Xen domain physmap. + * + * @param domid domain id, where mapping will be added. For unprivileged should + * be DOMID_SELF. + * @param idx index into space being mapped. + * @param space XENMAPSPACE_* mapping space identifier. + * @param gpfn page frame where the source mapping page should appear. + * @return zero on success, negative errno on error. + */ +int xendom_add_to_physmap(int domid, unsigned long idx, unsigned int space, + xen_pfn_t gpfn); + +/** + * Add mapping for specified set of page frames to Xen domain physmap. + * + * @param domid domain id, where mapping will be added. For unprivileged + * should be DOMID_SELF. + * @param foreign_domid for gmfn_foreign - domain id, whose pages being mapped, + * 0 for other. + * @param space XENMAPSPACE_* mapping space identifier. + * @param size number of page frames being mapped. + * @param idxs array of indexes into space being mapped. + * @param gpfns array of page frames where the mapping should appear. + * @param errs array of per-index error codes. + * @return zero on success, negative errno on error. + */ +int xendom_add_to_physmap_batch(int domid, int foreign_domid, + unsigned int space, unsigned int size, + xen_ulong_t *idxs, xen_pfn_t *gpfns, int *errs); + +/** + * Removes page frame from Xen domain physmap. + * + * @param domid domain id, whose page is going to be removed. For unprivileged + * should be DOMID_SELF. + * @param gpfn page frame number, that needs to be removed + * @return zero on success, negative errno on error. + */ +int xendom_remove_from_physmap(int domid, xen_pfn_t gpfn); + +/** + * Populate specified Xen domain page frames with memory. + * + * @param domid domain id, where mapping will be added. For unprivileged + * should be DOMID_SELF. + * @param extent_order size/alignment of each extent (size is 2^extent_order), + * e.g. 0 for 4K extents, 9 for 2M etc. + * @param nr_extents number of page frames being populated. + * @param mem_flags N/A, should be 0 for Arm. + * @param extent_start page frame bases of extents to populate with memory. + * @return number of populated frames success, negative errno on + * error. + */ +int xendom_populate_physmap(int domid, unsigned int extent_order, + unsigned int nr_extents, unsigned int mem_flags, + xen_pfn_t *extent_start); diff --git a/include/zephyr/xen/public/arch-arm.h b/include/zephyr/xen/public/arch-arm.h index f2812dc3b9b..c3a8afe9a92 100644 --- a/include/zephyr/xen/public/arch-arm.h +++ b/include/zephyr/xen/public/arch-arm.h @@ -205,15 +205,138 @@ typedef uint64_t xen_pfn_t; #define PRI_xen_pfn PRIx64 #define PRIu_xen_pfn PRIu64 -typedef uint64_t xen_ulong_t; -#define PRI_xen_ulong PRIx64 - /* * Maximum number of virtual CPUs in legacy multi-processor guests. * Only one. All other VCPUS must use VCPUOP_register_vcpu_info. */ #define XEN_LEGACY_MAX_VCPUS 1 +typedef uint64_t xen_ulong_t; +#define PRI_xen_ulong PRIx64 + +#ifdef CONFIG_XEN_DOM0 +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +/* Anonymous union includes both 32- and 64-bit names (e.g., r0/x0). */ +# define __DECL_REG(n64, n32) union { \ + uint64_t n64; \ + uint32_t n32; \ +} +#else +/* Non-gcc sources must always use the proper 64-bit name (e.g., x0). */ +#define __DECL_REG(n64, n32) uint64_t n64 +#endif + +struct vcpu_guest_core_regs { + /* Aarch64 Aarch32 */ + __DECL_REG(x0, r0_usr); + __DECL_REG(x1, r1_usr); + __DECL_REG(x2, r2_usr); + __DECL_REG(x3, r3_usr); + __DECL_REG(x4, r4_usr); + __DECL_REG(x5, r5_usr); + __DECL_REG(x6, r6_usr); + __DECL_REG(x7, r7_usr); + __DECL_REG(x8, r8_usr); + __DECL_REG(x9, r9_usr); + __DECL_REG(x10, r10_usr); + __DECL_REG(x11, r11_usr); + __DECL_REG(x12, r12_usr); + + __DECL_REG(x13, sp_usr); + __DECL_REG(x14, lr_usr); + + __DECL_REG(x15, __unused_sp_hyp); + + __DECL_REG(x16, lr_irq); + __DECL_REG(x17, sp_irq); + + __DECL_REG(x18, lr_svc); + __DECL_REG(x19, sp_svc); + + __DECL_REG(x20, lr_abt); + __DECL_REG(x21, sp_abt); + + __DECL_REG(x22, lr_und); + __DECL_REG(x23, sp_und); + + __DECL_REG(x24, r8_fiq); + __DECL_REG(x25, r9_fiq); + __DECL_REG(x26, r10_fiq); + __DECL_REG(x27, r11_fiq); + __DECL_REG(x28, r12_fiq); + + __DECL_REG(x29, sp_fiq); + __DECL_REG(x30, lr_fiq); + + /* Return address and mode */ + __DECL_REG(pc64, pc32); /* ELR_EL2 */ + uint32_t cpsr; /* SPSR_EL2 */ + + union { + uint32_t spsr_el1; /* AArch64 */ + uint32_t spsr_svc; /* AArch32 */ + }; + + /* AArch32 guests only */ + uint32_t spsr_fiq, spsr_irq, spsr_und, spsr_abt; + + /* AArch64 guests only */ + uint64_t sp_el0; + uint64_t sp_el1, elr_el1; +}; +typedef struct vcpu_guest_core_regs vcpu_guest_core_regs_t; +DEFINE_XEN_GUEST_HANDLE(vcpu_guest_core_regs_t); + +#undef __DECL_REG + +struct vcpu_guest_context { +#define _VGCF_online 0 +#define VGCF_online (1 << _VGCF_online) + uint32_t flags; /* VGCF_* */ + + struct vcpu_guest_core_regs user_regs; /* Core CPU registers */ + + uint64_t sctlr; + uint64_t ttbcr, ttbr0, ttbr1; +}; +typedef struct vcpu_guest_context vcpu_guest_context_t; +DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t); + +/* + * struct xen_arch_domainconfig's ABI is covered by + * XEN_DOMCTL_INTERFACE_VERSION. + */ +#define XEN_DOMCTL_CONFIG_GIC_NATIVE 0 +#define XEN_DOMCTL_CONFIG_GIC_V2 1 +#define XEN_DOMCTL_CONFIG_GIC_V3 2 + +#define XEN_DOMCTL_CONFIG_TEE_NONE 0 +#define XEN_DOMCTL_CONFIG_TEE_OPTEE 1 + +struct xen_arch_domainconfig { + /* IN/OUT */ + uint8_t gic_version; + /* IN */ + uint16_t tee_type; + /* IN */ + uint32_t nr_spis; + /* + * OUT + * Based on the property clock-frequency in the DT timer node. + * The property may be present when the bootloader/firmware doesn't + * set correctly CNTFRQ which hold the timer frequency. + * + * As it's not possible to trap this register, we have to replicate + * the value in the guest DT. + * + * = 0 => property not present + * > 0 => Value of the property + * + */ + uint32_t clock_frequency; +}; +#endif /* CONFIG_XEN_DOM0 */ + struct arch_vcpu_info { }; typedef struct arch_vcpu_info arch_vcpu_info_t; @@ -225,4 +348,129 @@ typedef uint64_t xen_callback_t; #endif /* __ASSEMBLY__ */ +#ifdef CONFIG_XEN_DOM0 + +/* PSR bits (CPSR, SPSR) */ +#define PSR_THUMB (1 << 5) /* Thumb Mode enable */ +#define PSR_FIQ_MASK (1 << 6) /* Fast Interrupt mask */ +#define PSR_IRQ_MASK (1 << 7) /* Interrupt mask */ +#define PSR_ABT_MASK (1 << 8) /* Asynchronous Abort mask */ +#define PSR_BIG_ENDIAN (1 << 9) /* arm32: Big Endian Mode */ +#define PSR_DBG_MASK (1 << 9) /* arm64: Debug Exception mask */ +#define PSR_IT_MASK (0x0600fc00) /* Thumb If-Then Mask */ +#define PSR_JAZELLE (1<<24) /* Jazelle Mode */ + +/* 32 bit modes */ +#define PSR_MODE_USR 0x10 +#define PSR_MODE_FIQ 0x11 +#define PSR_MODE_IRQ 0x12 +#define PSR_MODE_SVC 0x13 +#define PSR_MODE_MON 0x16 +#define PSR_MODE_ABT 0x17 +#define PSR_MODE_HYP 0x1a +#define PSR_MODE_UND 0x1b +#define PSR_MODE_SYS 0x1f + +/* 64 bit modes */ +#define PSR_MODE_BIT 0x10 /* Set iff AArch32 */ +#define PSR_MODE_EL3h 0x0d +#define PSR_MODE_EL3t 0x0c +#define PSR_MODE_EL2h 0x09 +#define PSR_MODE_EL2t 0x08 +#define PSR_MODE_EL1h 0x05 +#define PSR_MODE_EL1t 0x04 +#define PSR_MODE_EL0t 0x00 + +#define PSR_GUEST32_INIT (PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_SVC) +#define PSR_GUEST64_INIT (PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_EL1h) + +#define SCTLR_GUEST_INIT xen_mk_ullong(0x00c50078) + +/* + * Virtual machine platform (memory layout, interrupts) + * + * These are defined for consistency between the tools and the + * hypervisor. Guests must not rely on these hardcoded values but + * should instead use the FDT. + */ + +/* Physical Address Space */ + +/* + * vGIC mappings: Only one set of mapping is used by the guest. + * Therefore they can overlap. + */ + +/* vGIC v2 mappings */ +#define GUEST_GICD_BASE xen_mk_ullong(0x03001000) +#define GUEST_GICD_SIZE xen_mk_ullong(0x00001000) +#define GUEST_GICC_BASE xen_mk_ullong(0x03002000) +#define GUEST_GICC_SIZE xen_mk_ullong(0x00002000) + +/* vGIC v3 mappings */ +#define GUEST_GICV3_GICD_BASE xen_mk_ullong(0x03001000) +#define GUEST_GICV3_GICD_SIZE xen_mk_ullong(0x00010000) + +#define GUEST_GICV3_RDIST_REGIONS 1 + +#define GUEST_GICV3_GICR0_BASE xen_mk_ullong(0x03020000) /* vCPU0..127 */ +#define GUEST_GICV3_GICR0_SIZE xen_mk_ullong(0x01000000) + +/* ACPI tables physical address */ +#define GUEST_ACPI_BASE xen_mk_ullong(0x20000000) +#define GUEST_ACPI_SIZE xen_mk_ullong(0x02000000) + +/* PL011 mappings */ +#define GUEST_PL011_BASE xen_mk_ullong(0x22000000) +#define GUEST_PL011_SIZE xen_mk_ullong(0x00001000) + +/* + * 16MB == 4096 pages reserved for guest to use as a region to map its + * grant table in. + */ +#define GUEST_GNTTAB_BASE xen_mk_ullong(0x38000000) +#define GUEST_GNTTAB_SIZE xen_mk_ullong(0x01000000) + +#define GUEST_MAGIC_BASE xen_mk_ullong(0x39000000) +#define GUEST_MAGIC_SIZE xen_mk_ullong(0x01000000) + +#define GUEST_RAM_BANKS 2 + +#define GUEST_RAM0_BASE xen_mk_ullong(0x40000000) /* 3GB of low RAM @ 1GB */ +#define GUEST_RAM0_SIZE xen_mk_ullong(0xc0000000) + +#define GUEST_RAM1_BASE xen_mk_ullong(0x0200000000) /* 1016GB of RAM @ 8GB */ +#define GUEST_RAM1_SIZE xen_mk_ullong(0xfe00000000) + +#define GUEST_RAM_BASE GUEST_RAM0_BASE /* Lowest RAM address */ +/* Largest amount of actual RAM, not including holes */ +#define GUEST_RAM_MAX (GUEST_RAM0_SIZE + GUEST_RAM1_SIZE) +/* Suitable for e.g. const uint64_t ramfoo[] = GUEST_RAM_BANK_FOOS; */ +#define GUEST_RAM_BANK_BASES { GUEST_RAM0_BASE, GUEST_RAM1_BASE } +#define GUEST_RAM_BANK_SIZES { GUEST_RAM0_SIZE, GUEST_RAM1_SIZE } + +/* Current supported guest VCPUs */ +#define GUEST_MAX_VCPUS 128 + +/* Interrupts */ +#define GUEST_TIMER_VIRT_PPI 27 +#define GUEST_TIMER_PHYS_S_PPI 29 +#define GUEST_TIMER_PHYS_NS_PPI 30 +#define GUEST_EVTCHN_PPI 31 + +#define GUEST_VPL011_SPI 32 + +/* PSCI functions */ +#define PSCI_cpu_suspend 0 +#define PSCI_cpu_off 1 +#define PSCI_cpu_on 2 +#define PSCI_migrate 3 + +#endif /* CONFIG_XEN_DOM0 */ + +#ifndef __ASSEMBLY__ +/* Stub definition of PMU structure */ +typedef struct xen_pmu_arch { uint8_t dummy; } xen_pmu_arch_t; +#endif /* __ASSEMBLY__ */ + #endif /* __XEN_PUBLIC_ARCH_ARM_H__ */ diff --git a/include/zephyr/xen/public/domctl.h b/include/zephyr/xen/public/domctl.h new file mode 100644 index 00000000000..b33cf7966fa --- /dev/null +++ b/include/zephyr/xen/public/domctl.h @@ -0,0 +1,517 @@ +/* SPDX-License-Identifier: MIT */ +/****************************************************************************** + * domctl.h + * + * Domain management operations. For use by node control stack. + * + * Copyright (c) 2002-2003, B Dragovic + * Copyright (c) 2002-2006, K Fraser + */ + +#ifndef __XEN_PUBLIC_DOMCTL_H__ +#define __XEN_PUBLIC_DOMCTL_H__ + +#ifndef CONFIG_XEN_DOM0 +#error "domctl operations are intended for use by node control tools only" +#endif + +#include "xen.h" +#include "event_channel.h" +#include "grant_table.h" +#include "memory.h" + +#define XEN_DOMCTL_INTERFACE_VERSION 0x00000015 + +/* + * NB. xen_domctl.domain is an IN/OUT parameter for this operation. + * If it is specified as an invalid value (0 or >= DOMID_FIRST_RESERVED), + * an id is auto-allocated and returned. + */ +/* XEN_DOMCTL_createdomain */ +struct xen_domctl_createdomain { + /* IN parameters */ + uint32_t ssidref; + xen_domain_handle_t handle; +/* Is this an HVM guest (as opposed to a PV guest)? */ +#define _XEN_DOMCTL_CDF_hvm 0 +#define XEN_DOMCTL_CDF_hvm (1U << _XEN_DOMCTL_CDF_hvm) +/* Use hardware-assisted paging if available? */ +#define _XEN_DOMCTL_CDF_hap 1 +#define XEN_DOMCTL_CDF_hap (1U << _XEN_DOMCTL_CDF_hap) +/* Should domain memory integrity be verifed by tboot during Sx? */ +#define _XEN_DOMCTL_CDF_s3_integrity 2 +#define XEN_DOMCTL_CDF_s3_integrity (1U << _XEN_DOMCTL_CDF_s3_integrity) +/* Disable out-of-sync shadow page tables? */ +#define _XEN_DOMCTL_CDF_oos_off 3 +#define XEN_DOMCTL_CDF_oos_off (1U << _XEN_DOMCTL_CDF_oos_off) +/* Is this a xenstore domain? */ +#define _XEN_DOMCTL_CDF_xs_domain 4 +#define XEN_DOMCTL_CDF_xs_domain (1U << _XEN_DOMCTL_CDF_xs_domain) +/* Should this domain be permitted to use the IOMMU? */ +#define _XEN_DOMCTL_CDF_iommu 5 +#define XEN_DOMCTL_CDF_iommu (1U << _XEN_DOMCTL_CDF_iommu) +#define _XEN_DOMCTL_CDF_nested_virt 6 +#define XEN_DOMCTL_CDF_nested_virt (1U << _XEN_DOMCTL_CDF_nested_virt) +/* Should we expose the vPMU to the guest? */ +#define XEN_DOMCTL_CDF_vpmu (1U << 7) + +/* Max XEN_DOMCTL_CDF_* constant. Used for ABI checking. */ +#define XEN_DOMCTL_CDF_MAX XEN_DOMCTL_CDF_vpmu + + uint32_t flags; + +#define _XEN_DOMCTL_IOMMU_no_sharept 0 +#define XEN_DOMCTL_IOMMU_no_sharep (1U << _XEN_DOMCTL_IOMMU_no_sharept) + +/* Max XEN_DOMCTL_IOMMU_* constant. Used for ABI checking. */ +#define XEN_DOMCTL_IOMMU_MAX XEN_DOMCTL_IOMMU_no_sharept + + uint32_t iommu_opts; + + /* + * Various domain limits, which impact the quantity of resources + * (global mapping space, xenheap, etc) a guest may consume. For + * max_grant_frames and max_maptrack_frames, < 0 means "use the + * default maximum value in the hypervisor". + */ + uint32_t max_vcpus; + uint32_t max_evtchn_port; + int32_t max_grant_frames; + int32_t max_maptrack_frames; + +/* Grant version, use low 4 bits. */ +#define XEN_DOMCTL_GRANT_version_mask 0xf +#define XEN_DOMCTL_GRANT_version(v) ((v) & XEN_DOMCTL_GRANT_version_mask) + + uint32_t grant_opts; + + /* Per-vCPU buffer size in bytes. 0 to disable. */ + uint32_t vmtrace_size; + + /* CPU pool to use; specify 0 or a specific existing pool */ + uint32_t cpupool_id; + + struct xen_arch_domainconfig arch; +}; + +/* XEN_DOMCTL_getdomaininfo */ +struct xen_domctl_getdomaininfo { + /* OUT variables. */ + domid_t domain; /* Also echoed in domctl.domain */ + uint16_t pad1; +/* Domain is scheduled to die. */ +#define _XEN_DOMINF_dying 0 +#define XEN_DOMINF_dying (1U << _XEN_DOMINF_dying) +/* Domain is an HVM guest (as opposed to a PV guest). */ +#define _XEN_DOMINF_hvm_guest 1 +#define XEN_DOMINF_hvm_guest (1U << _XEN_DOMINF_hvm_guest) +/* The guest OS has shut down. */ +#define _XEN_DOMINF_shutdown 2 +#define XEN_DOMINF_shutdown (1U << _XEN_DOMINF_shutdown) +/* Currently paused by control software. */ +#define _XEN_DOMINF_paused 3 +#define XEN_DOMINF_paused (1U << _XEN_DOMINF_paused) +/* Currently blocked pending an event. */ +#define _XEN_DOMINF_blocked 4 +#define XEN_DOMINF_blocked (1U << _XEN_DOMINF_blocked) +/* Domain is currently running. */ +#define _XEN_DOMINF_running 5 +#define XEN_DOMINF_running (1U << _XEN_DOMINF_running) +/* Being debugged. */ +#define _XEN_DOMINF_debugged 6 +#define XEN_DOMINF_debugged (1U << _XEN_DOMINF_debugged) +/* domain is a xenstore domain */ +#define _XEN_DOMINF_xs_domain 7 +#define XEN_DOMINF_xs_domain (1U << _XEN_DOMINF_xs_domain) +/* domain has hardware assisted paging */ +#define _XEN_DOMINF_hap 8 +#define XEN_DOMINF_hap (1U << _XEN_DOMINF_hap) +/* XEN_DOMINF_shutdown guest-supplied code. */ +#define XEN_DOMINF_shutdownmask 255 +#define XEN_DOMINF_shutdownshift 16 + uint32_t flags; /* XEN_DOMINF_* */ + uint64_aligned_t tot_pages; + uint64_aligned_t max_pages; + uint64_aligned_t outstanding_pages; + uint64_aligned_t shr_pages; + uint64_aligned_t paged_pages; + uint64_aligned_t shared_info_frame; /* GMFN of shared_info struct */ + uint64_aligned_t cpu_time; + uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */ +#define XEN_INVALID_MAX_VCPU_ID (~0U) /* Domain has no vcpus? */ + uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */ + uint32_t ssidref; + xen_domain_handle_t handle; + uint32_t cpupool; + uint8_t gpaddr_bits; /* Guest physical address space size. */ + uint8_t pad2[7]; + struct xen_arch_domainconfig arch_config; +}; +typedef struct xen_domctl_getdomaininfo xen_domctl_getdomaininfo_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_getdomaininfo_t); + +/* + * Control shadow pagetables operation + */ +/* XEN_DOMCTL_shadow_op */ + +/* Memory allocation accessors. */ +#define XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION 30 +#define XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION 31 + +struct xen_domctl_shadow_op_stats { + uint32_t fault_count; + uint32_t dirty_count; +}; + +struct xen_domctl_shadow_op { + /* IN variables. */ + uint32_t op; /* XEN_DOMCTL_SHADOW_OP_* */ + + /* OP_ENABLE: XEN_DOMCTL_SHADOW_ENABLE_* */ + /* OP_PEAK / OP_CLEAN: XEN_DOMCTL_SHADOW_LOGDIRTY_* */ + uint32_t mode; + + /* OP_GET_ALLOCATION / OP_SET_ALLOCATION */ + uint32_t mb; /* Shadow memory allocation in MB */ + + /* OP_PEEK / OP_CLEAN */ + XEN_GUEST_HANDLE_64(uint8_t) dirty_bitmap; + uint64_aligned_t pages; /* Size of buffer. Updated with actual size. */ + struct xen_domctl_shadow_op_stats stats; +}; + +/* XEN_DOMCTL_max_mem */ +struct xen_domctl_max_mem { + /* IN variables. */ + uint64_aligned_t max_memkb; +}; + +/* XEN_DOMCTL_setvcpucontext */ +/* XEN_DOMCTL_getvcpucontext */ +struct xen_domctl_vcpucontext { + uint32_t vcpu; /* IN */ + + XEN_GUEST_HANDLE_64(vcpu_guest_context_t) ctxt; /* IN/OUT */ +}; + +/* + * XEN_DOMCTL_max_vcpus: + * + * The parameter passed to XEN_DOMCTL_max_vcpus must match the value passed to + * XEN_DOMCTL_createdomain. This hypercall is in the process of being removed + * (once the failure paths in domain_create() have been improved), but is + * still required in the short term to allocate the vcpus themselves. + */ +struct xen_domctl_max_vcpus { + uint32_t max; /* maximum number of vcpus */ +}; + +/* XEN_DOMCTL_scheduler_op */ +/* Scheduler types. */ +/* #define XEN_SCHEDULER_SEDF 4 (Removed) */ +#define XEN_SCHEDULER_CREDIT 5 +#define XEN_SCHEDULER_CREDIT2 6 +#define XEN_SCHEDULER_ARINC653 7 +#define XEN_SCHEDULER_RTDS 8 +#define XEN_SCHEDULER_NULL 9 + +struct xen_domctl_sched_credit { + uint16_t weight; + uint16_t cap; +}; + +struct xen_domctl_sched_credit2 { + uint16_t weight; + uint16_t cap; +}; + +struct xen_domctl_sched_rtds { + uint32_t period; + uint32_t budget; +/* Can this vCPU execute beyond its reserved amount of time? */ +#define _XEN_DOMCTL_SCHEDRT_extra 0 +#define XEN_DOMCTL_SCHEDRT_extra (1U<<_XEN_DOMCTL_SCHEDRT_extra) + uint32_t flags; +}; + +typedef struct xen_domctl_schedparam_vcpu { + union { + struct xen_domctl_sched_credit credit; + struct xen_domctl_sched_credit2 credit2; + struct xen_domctl_sched_rtds rtds; + } u; + uint32_t vcpuid; +} xen_domctl_schedparam_vcpu_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_schedparam_vcpu_t); + +/* + * Set or get info? + * For schedulers supporting per-vcpu settings (e.g., RTDS): + * XEN_DOMCTL_SCHEDOP_putinfo sets params for all vcpus; + * XEN_DOMCTL_SCHEDOP_getinfo gets default params; + * XEN_DOMCTL_SCHEDOP_put(get)vcpuinfo sets (gets) params of vcpus; + * + * For schedulers not supporting per-vcpu settings: + * XEN_DOMCTL_SCHEDOP_putinfo sets params for all vcpus; + * XEN_DOMCTL_SCHEDOP_getinfo gets domain-wise params; + * XEN_DOMCTL_SCHEDOP_put(get)vcpuinfo returns error; + */ +#define XEN_DOMCTL_SCHEDOP_putinfo 0 +#define XEN_DOMCTL_SCHEDOP_getinfo 1 +#define XEN_DOMCTL_SCHEDOP_putvcpuinfo 2 +#define XEN_DOMCTL_SCHEDOP_getvcpuinfo 3 +struct xen_domctl_scheduler_op { + uint32_t sched_id; /* XEN_SCHEDULER_* */ + uint32_t cmd; /* XEN_DOMCTL_SCHEDOP_* */ + /* IN/OUT */ + union { + struct xen_domctl_sched_credit credit; + struct xen_domctl_sched_credit2 credit2; + struct xen_domctl_sched_rtds rtds; + struct { + XEN_GUEST_HANDLE_64(xen_domctl_schedparam_vcpu_t) vcpus; + /* + * IN: Number of elements in vcpus array. + * OUT: Number of processed elements of vcpus array. + */ + uint32_t nr_vcpus; + uint32_t padding; + } v; + } u; +}; + +/* XEN_DOMCTL_iomem_permission */ +struct xen_domctl_iomem_permission { + uint64_aligned_t first_mfn;/* first page (physical page number) in range */ + uint64_aligned_t nr_mfns; /* number of pages in range (>0) */ + uint8_t allow_access; /* allow (!0) or deny (0) access to range? */ +}; + +/* XEN_DOMCTL_set_address_size */ +/* XEN_DOMCTL_get_address_size */ +struct xen_domctl_address_size { + uint32_t size; +}; + +/* Assign a device to a guest. Sets up IOMMU structures. */ +/* XEN_DOMCTL_assign_device */ +/* + * XEN_DOMCTL_test_assign_device: Pass DOMID_INVALID to find out whether the + * given device is assigned to any DomU at all. Pass a specific domain ID to + * find out whether the given device can be assigned to that domain. + */ +/* + * XEN_DOMCTL_deassign_device: The behavior of this DOMCTL differs + * between the different type of device: + * - PCI device (XEN_DOMCTL_DEV_PCI) will be reassigned to DOM0 + * - DT device (XEN_DOMCTL_DEV_DT) will left unassigned. DOM0 + * will have to call XEN_DOMCTL_assign_device in order to use the + * device. + */ +#define XEN_DOMCTL_DEV_PCI 0 +#define XEN_DOMCTL_DEV_DT 1 +struct xen_domctl_assign_device { + /* IN */ + uint32_t dev; /* XEN_DOMCTL_DEV_* */ + uint32_t flags; +#define XEN_DOMCTL_DEV_RDM_RELAXED 1 /* assign only */ + union { + struct { + uint32_t machine_sbdf; /* machine PCI ID of assigned device */ + } pci; + struct { + uint32_t size; /* Length of the path */ + + XEN_GUEST_HANDLE_64(char) path; /* path to the device tree node */ + } dt; + } u; +}; + +/* Pass-through interrupts: bind real irq -> hvm devfn. */ +/* XEN_DOMCTL_bind_pt_irq */ +/* XEN_DOMCTL_unbind_pt_irq */ +enum pt_irq_type { + PT_IRQ_TYPE_PCI, + PT_IRQ_TYPE_ISA, + PT_IRQ_TYPE_MSI, + PT_IRQ_TYPE_MSI_TRANSLATE, + PT_IRQ_TYPE_SPI, /* ARM: valid range 32-1019 */ +}; +struct xen_domctl_bind_pt_irq { + uint32_t machine_irq; + uint32_t irq_type; /* enum pt_irq_type */ + + union { + struct { + uint8_t isa_irq; + } isa; + struct { + uint8_t bus; + uint8_t device; + uint8_t intx; + } pci; + struct { + uint8_t gvec; + uint32_t gflags; +#define XEN_DOMCTL_VMSI_X86_DEST_ID_MASK 0x0000ff +#define XEN_DOMCTL_VMSI_X86_RH_MASK 0x000100 +#define XEN_DOMCTL_VMSI_X86_DM_MASK 0x000200 +#define XEN_DOMCTL_VMSI_X86_DELIV_MASK 0x007000 +#define XEN_DOMCTL_VMSI_X86_TRIG_MASK 0x008000 +#define XEN_DOMCTL_VMSI_X86_UNMASKED 0x010000 + + uint64_aligned_t gtable; + } msi; + struct { + uint16_t spi; + } spi; + } u; +}; + + +/* Bind machine I/O address range -> HVM address range. */ +/* XEN_DOMCTL_memory_mapping */ +/* Returns + * - zero success, everything done + * - -E2BIG passed in nr_mfns value too large for the implementation + * - positive partial success for the first page frames (with + * less than nr_mfns), requiring re-invocation by the + * caller after updating inputs + * - negative error; other than -E2BIG + */ +#define DPCI_ADD_MAPPING 1 +#define DPCI_REMOVE_MAPPING 0 +struct xen_domctl_memory_mapping { + uint64_aligned_t first_gfn; /* first page (hvm guest phys page) in range */ + uint64_aligned_t first_mfn; /* first page (machine page) in range */ + uint64_aligned_t nr_mfns; /* number of pages in range (>0) */ + uint32_t add_mapping; /* add or remove mapping */ + uint32_t padding; /* padding for 64-bit aligned structure */ +}; + +/* + * ARM: Clean and invalidate caches associated with given region of + * guest memory. + */ +struct xen_domctl_cacheflush { + /* IN: page range to flush. */ + xen_pfn_t start_pfn, nr_pfns; +}; + +/* + * XEN_DOMCTL_get_paging_mempool_size / XEN_DOMCTL_set_paging_mempool_size. + * + * Get or set the paging memory pool size. The size is in bytes. + * + * This is a dedicated pool of memory for Xen to use while managing the guest, + * typically containing pagetables. As such, there is an implementation + * specific minimum granularity. + * + * The set operation can fail mid-way through the request (e.g. Xen running + * out of memory, no free memory to reclaim from the pool, etc.). + */ +struct xen_domctl_paging_mempool { + uint64_aligned_t size; /* Size in bytes. */ +}; + +struct xen_domctl { + uint32_t cmd; +#define XEN_DOMCTL_createdomain 1 +#define XEN_DOMCTL_destroydomain 2 +#define XEN_DOMCTL_pausedomain 3 +#define XEN_DOMCTL_unpausedomain 4 +#define XEN_DOMCTL_getdomaininfo 5 +#define XEN_DOMCTL_setvcpuaffinity 9 +#define XEN_DOMCTL_shadow_op 10 +#define XEN_DOMCTL_max_mem 11 +#define XEN_DOMCTL_setvcpucontext 12 +#define XEN_DOMCTL_getvcpucontext 13 +#define XEN_DOMCTL_getvcpuinfo 14 +#define XEN_DOMCTL_max_vcpus 15 +#define XEN_DOMCTL_scheduler_op 16 +#define XEN_DOMCTL_setdomainhandle 17 +#define XEN_DOMCTL_setdebugging 18 +#define XEN_DOMCTL_irq_permission 19 +#define XEN_DOMCTL_iomem_permission 20 +#define XEN_DOMCTL_ioport_permission 21 +#define XEN_DOMCTL_hypercall_init 22 +#define XEN_DOMCTL_settimeoffset 24 +#define XEN_DOMCTL_getvcpuaffinity 25 +#define XEN_DOMCTL_real_mode_area 26 /* Obsolete PPC only */ +#define XEN_DOMCTL_resumedomain 27 +#define XEN_DOMCTL_sendtrigger 28 +#define XEN_DOMCTL_subscribe 29 +#define XEN_DOMCTL_gethvmcontext 33 +#define XEN_DOMCTL_sethvmcontext 34 +#define XEN_DOMCTL_set_address_size 35 +#define XEN_DOMCTL_get_address_size 36 +#define XEN_DOMCTL_assign_device 37 +#define XEN_DOMCTL_bind_pt_irq 38 +#define XEN_DOMCTL_memory_mapping 39 +#define XEN_DOMCTL_ioport_mapping 40 +#define XEN_DOMCTL_set_ext_vcpucontext 42 +#define XEN_DOMCTL_get_ext_vcpucontext 43 +#define XEN_DOMCTL_set_opt_feature 44 /* Obsolete IA64 only */ +#define XEN_DOMCTL_test_assign_device 45 +#define XEN_DOMCTL_set_target 46 +#define XEN_DOMCTL_deassign_device 47 +#define XEN_DOMCTL_unbind_pt_irq 48 +#define XEN_DOMCTL_get_device_group 50 +#define XEN_DOMCTL_debug_op 54 +#define XEN_DOMCTL_gethvmcontext_partial 55 +#define XEN_DOMCTL_vm_event_op 56 +#define XEN_DOMCTL_mem_sharing_op 57 +#define XEN_DOMCTL_gettscinfo 59 +#define XEN_DOMCTL_settscinfo 60 +#define XEN_DOMCTL_getpageframeinfo3 61 +#define XEN_DOMCTL_setvcpuextstate 62 +#define XEN_DOMCTL_getvcpuextstate 63 +#define XEN_DOMCTL_set_access_required 64 +#define XEN_DOMCTL_audit_p2m 65 +#define XEN_DOMCTL_set_virq_handler 66 +#define XEN_DOMCTL_set_broken_page_p2m 67 +#define XEN_DOMCTL_setnodeaffinity 68 +#define XEN_DOMCTL_getnodeaffinity 69 +#define XEN_DOMCTL_cacheflush 71 +#define XEN_DOMCTL_get_vcpu_msrs 72 +#define XEN_DOMCTL_set_vcpu_msrs 73 +#define XEN_DOMCTL_setvnumainfo 74 +#define XEN_DOMCTL_psr_cmt_op 75 +#define XEN_DOMCTL_monitor_op 77 +#define XEN_DOMCTL_psr_alloc 78 +#define XEN_DOMCTL_soft_reset 79 +#define XEN_DOMCTL_vuart_op 81 +#define XEN_DOMCTL_get_cpu_policy 82 +#define XEN_DOMCTL_set_cpu_policy 83 +#define XEN_DOMCTL_vmtrace_op 84 +#define XEN_DOMCTL_get_paging_mempool_size 85 +#define XEN_DOMCTL_set_paging_mempool_size 86 +#define XEN_DOMCTL_gdbsx_guestmemio 1000 +#define XEN_DOMCTL_gdbsx_pausevcpu 1001 +#define XEN_DOMCTL_gdbsx_unpausevcpu 1002 +#define XEN_DOMCTL_gdbsx_domstatus 1003 + uint32_t interface_version; /* XEN_DOMCTL_INTERFACE_VERSION */ + domid_t domain; + uint16_t _pad[3]; + union { + struct xen_domctl_createdomain createdomain; + struct xen_domctl_getdomaininfo getdomaininfo; + struct xen_domctl_max_mem max_mem; + struct xen_domctl_vcpucontext vcpucontext; + struct xen_domctl_max_vcpus max_vcpus; + struct xen_domctl_scheduler_op scheduler_op; + struct xen_domctl_iomem_permission iomem_permission; + struct xen_domctl_address_size address_size; + struct xen_domctl_assign_device assign_device; + struct xen_domctl_bind_pt_irq bind_pt_irq; + struct xen_domctl_memory_mapping memory_mapping; + struct xen_domctl_cacheflush cacheflush; + struct xen_domctl_paging_mempool paging_mempool; + uint8_t pad[128]; + } u; +}; +typedef struct xen_domctl xen_domctl_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_t); + +#endif /* __XEN_PUBLIC_DOMCTL_H__ */ diff --git a/include/zephyr/xen/public/memory.h b/include/zephyr/xen/public/memory.h index 9496b5f5271..513b32735de 100644 --- a/include/zephyr/xen/public/memory.h +++ b/include/zephyr/xen/public/memory.h @@ -69,6 +69,40 @@ struct xen_memory_reservation { typedef struct xen_memory_reservation xen_memory_reservation_t; DEFINE_XEN_GUEST_HANDLE(xen_memory_reservation_t); +/* A batched version of add_to_physmap. */ +#define XENMEM_add_to_physmap_batch 23 +struct xen_add_to_physmap_batch { + /* IN */ + /* Which domain to change the mapping for. */ + domid_t domid; + uint16_t space; /* => enum phys_map_space */ + + /* Number of pages to go through */ + uint16_t size; + +#if __XEN_INTERFACE_VERSION__ < 0x00040700 + domid_t foreign_domid; /* IFF gmfn_foreign. Should be 0 for other spaces. */ +#else + union xen_add_to_physmap_batch_extra { + domid_t foreign_domid; /* gmfn_foreign */ + uint16_t res0; /* All the other spaces. Should be 0 */ + } u; +#endif + + /* Indexes into space being mapped. */ + XEN_GUEST_HANDLE(xen_ulong_t) idxs; + + /* GPFN in domid where the source mapping page should appear. */ + XEN_GUEST_HANDLE(xen_pfn_t) gpfns; + + /* OUT */ + /* Per index error code. */ + XEN_GUEST_HANDLE(int) errs; +}; +typedef struct xen_add_to_physmap_batch xen_add_to_physmap_batch_t; +DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_batch_t); + + #define XENMAPSPACE_shared_info 0 /* shared info page */ #define XENMAPSPACE_grant_table 1 /* grant table page */ #define XENMAPSPACE_gmfn 2 /* GMFN */ diff --git a/include/zephyr/xen/public/xen.h b/include/zephyr/xen/public/xen.h index 8b7c478656b..f8a5b6eba05 100644 --- a/include/zephyr/xen/public/xen.h +++ b/include/zephyr/xen/public/xen.h @@ -47,6 +47,7 @@ __DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long); #endif DEFINE_XEN_GUEST_HANDLE(void); +DEFINE_XEN_GUEST_HANDLE(uint8_t); DEFINE_XEN_GUEST_HANDLE(uint64_t); DEFINE_XEN_GUEST_HANDLE(xen_pfn_t); DEFINE_XEN_GUEST_HANDLE(xen_ulong_t); @@ -371,6 +372,26 @@ struct shared_info { typedef struct shared_info shared_info_t; #endif +typedef uint8_t xen_domain_handle_t[16]; + +#ifndef int64_aligned_t +#define int64_aligned_t int64_t +#endif +#ifndef uint64_aligned_t +#define uint64_aligned_t uint64_t +#endif +#ifndef XEN_GUEST_HANDLE_64 +#define XEN_GUEST_HANDLE_64(name) XEN_GUEST_HANDLE(name) +#endif + +#ifndef __ASSEMBLY__ +struct xenctl_bitmap { + XEN_GUEST_HANDLE_64(uint8_t) bitmap; + uint32_t nr_bits; +}; +typedef struct xenctl_bitmap xenctl_bitmap_t; +#endif + #endif /* !__ASSEMBLY__ */ #endif /* __XEN_PUBLIC_XEN_H__ */ diff --git a/include/zephyr/zbus/zbus.h b/include/zephyr/zbus/zbus.h index 8a4188aa821..285338d4732 100644 --- a/include/zephyr/zbus/zbus.h +++ b/include/zephyr/zbus/zbus.h @@ -148,6 +148,12 @@ struct zbus_channel_observation { const struct zbus_observer *const obs; }; +#ifdef __cplusplus +#define _ZBUS_CPP_EXTERN extern +#else +#define _ZBUS_CPP_EXTERN +#endif /* __cplusplus */ + #if defined(CONFIG_ZBUS_ASSERT_MOCK) #define _ZBUS_ASSERT(_cond, _fmt, ...) \ do { \ @@ -225,7 +231,6 @@ struct zbus_channel_observation { #define _ZBUS_RUNTIME_OBSERVERS_DECL(_name) #endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS */ -k_timeout_t _zbus_timeout_remainder(uint64_t end_ticks); /** @endcond */ /** @@ -305,7 +310,7 @@ k_timeout_t _zbus_timeout_remainder(uint64_t end_ticks); static struct zbus_channel_data _CONCAT(_zbus_chan_data_, _name) = { \ .observers_start_idx = -1, .observers_end_idx = -1}; \ static K_MUTEX_DEFINE(_CONCAT(_zbus_mutex_, _name)); \ - const STRUCT_SECTION_ITERABLE(zbus_channel, _name) = { \ + _ZBUS_CPP_EXTERN const STRUCT_SECTION_ITERABLE(zbus_channel, _name) = { \ ZBUS_CHANNEL_NAME_INIT(_name) /* Maybe removed */ \ .message = &_CONCAT(_zbus_message_, _name), \ .message_size = sizeof(_type), .user_data = _user_data, .validator = (_validator), \ diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 087e96b0812..bec410968cc 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -21,9 +21,15 @@ zephyr_syscall_header_ifdef( zephyr_syscall_header_ifdef( CONFIG_MMU + ${ZEPHYR_BASE}/include/zephyr/kernel/mm.h ${ZEPHYR_BASE}/include/zephyr/sys/mem_manage.h ) +zephyr_syscall_header_ifdef( + CONFIG_DEMAND_PAGING + ${ZEPHYR_BASE}/include/zephyr/kernel/mm/demand_paging.h +) + # If a pre-built static library containing kernel code exists in # this directory, libkernel.a, link it with the application code # instead of building from source. @@ -107,6 +113,7 @@ target_sources_ifdef(CONFIG_POLL kernel PRIVATE poll.c) target_sources_ifdef(CONFIG_EVENTS kernel PRIVATE events.c) target_sources_ifdef(CONFIG_PIPES kernel PRIVATE pipes.c) target_sources_ifdef(CONFIG_SCHED_THREAD_USAGE kernel PRIVATE usage.c) +target_sources_ifdef(CONFIG_OBJ_CORE kernel PRIVATE obj_core.c) if(${CONFIG_KERNEL_MEM_POOL}) target_sources(kernel PRIVATE mempool.c) diff --git a/kernel/Kconfig b/kernel/Kconfig index fce7598aa18..6280e80a400 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -201,7 +201,7 @@ config THREAD_CUSTOM_DATA config THREAD_USERSPACE_LOCAL_DATA bool depends on USERSPACE - default y if ERRNO && !ERRNO_IN_TLS + default y if ERRNO && !ERRNO_IN_TLS && !LIBC_ERRNO config DYNAMIC_THREAD bool "Support for dynamic threads [EXPERIMENTAL]" @@ -382,6 +382,16 @@ config INIT_STACKS water mark can be easily determined. This applies to the stack areas for threads, as well as to the interrupt stack. +config SKIP_BSS_CLEAR + bool + help + This option disables software .bss section zeroing during Zephyr + initialization. Such boot-time optimization could be used for + platforms where .bss section is zeroed-out externally. + Please pay attention that when this option is enabled + the responsibility for .bss zeroing in all possible scenarios + (mind e.g. SW reset) is delegated to the external SW or HW. + config BOOT_BANNER bool "Boot banner" default y @@ -494,10 +504,164 @@ endif # THREAD_RUNTIME_STATS endmenu +menuconfig OBJ_CORE + bool "Object core framework" + default n + help + This option enables the object core framework. This will link + participating kernel objects and their respective types together + in a way that allows them to both have common information stored + together and for that information to be easily retrieved by + automated means. + +if OBJ_CORE +config OBJ_CORE_CONDVAR + bool "Integrate condition variables into object core framework" + default y + help + When enabled, this option integrates condition variables into the + object core framework. + +config OBJ_CORE_EVENT + bool "Integrate events into object core framework" + default y if EVENTS + help + When enabled, this option integrate kernel events into the object + core framework. + +config OBJ_CORE_FIFO + bool "Integrate FIFOs into object core framework" + default y + help + When enabled, this option integrates FIFOs into the object core + framework. + +config OBJ_CORE_LIFO + bool "Integrate LIFOs into object core framework" + default y + help + When enabled, this option integrates LIFOs into the object core + framework. + +config OBJ_CORE_MAILBOX + bool "Integrate mailboxes into object core framework" + default y + help + When enabled, this option integrates mailboxes into the object core + framework. + +config OBJ_CORE_MEM_SLAB + bool "Integrate memory slabs into object core framework" + default y + help + When enabled, this option integrates memory slabs into the object + core framework. + +config OBJ_CORE_MUTEX + bool "Integrate mutexes into object core framework" + default y + help + When enabled, this option integrates mutexes into the object core + framework. + +config OBJ_CORE_MSGQ + bool "Integrate message queues into object core framework" + default y + help + When enabled, this option integrates message queues into the object + core framework. + +config OBJ_CORE_SEM + bool "Integrate semaphores into object core framework" + default y + help + When enabled, this option integrates semaphores into the object core + framework. + +config OBJ_CORE_PIPE + bool "Integrate pipe into object core framework" + default y if PIPES + help + When enabled, this option integrates pipes into the object core + framework. + +config OBJ_CORE_SEM + bool "Integrate semaphores into object core framework" + default y + help + When enabled, this option integrates semaphores into the object core + framework. + +config OBJ_CORE_STACK + bool "Integrate stacks into object core framework" + default y + help + When enabled, this option integrates stacks into the object core + framework. + +config OBJ_CORE_THREAD + bool "Integrate threads into object core framework" + default y + help + When enabled, this option integrates threads into the object core + framework. + +config OBJ_CORE_TIMER + bool "Integrate timers into object core framework" + default y + help + When enabled, this option integrates timers into the object core + framework. + +config OBJ_CORE_SYSTEM + bool + default y + help + When enabled, this option integrates the internal CPU and kernel + system objects into the object core framework. As these are internal + structures, this option is hidden by default and only available to + advanced users. + +menuconfig OBJ_CORE_STATS + bool "Object core statistics" + default n + help + This option integrates statistics gathering into the object core + framework. + +if OBJ_CORE_STATS +config OBJ_CORE_STATS_MEM_SLAB + bool "Object core statistics for memory slabs" + default y if OBJ_CORE_MEM_SLAB + help + When enabled, this allows memory slab statistics to be integrated + into kernel objects. + +config OBJ_CORE_STATS_THREAD + bool "Object core statistics for threads" + default y if OBJ_CORE_THREAD + select THREAD_RUNTIME_STATS + help + When enabled, this integrates thread runtime statistics into the + object core statistics framework. + +config OBJ_CORE_STATS_SYSTEM + bool "Object core statistics for system level objects" + default y if OBJ_CORE_SYSTEM + select SCHED_THREAD_USAGE_ALL + help + When enabled, this integrates thread runtime statistics at the + CPU and system level into the object core statistics framework. + +endif # OBJ_CORE_STATS + +endif # OBJ_CORE + menu "Work Queue Options" config SYSTEM_WORKQUEUE_STACK_SIZE int "System workqueue stack size" default 4096 if COVERAGE_GCOV + default 2560 if WIFI_NM_WPA_SUPPLICANT default 1024 config SYSTEM_WORKQUEUE_PRIORITY @@ -822,6 +986,7 @@ menu "Security Options" config STACK_CANARIES bool "Compiler stack canaries" depends on ENTROPY_GENERATOR || TEST_RANDOM_GENERATOR + select NEED_LIBC_MEM_PARTITION if !STACK_CANARIES_TLS help This option enables compiler stack canaries. @@ -987,17 +1152,16 @@ config SMP_BOOT_DELAY secondary CPUs at a later time. config MP_NUM_CPUS - int "Number of CPUs/cores" + int "Number of CPUs/cores [DEPRECATED]" default MP_MAX_NUM_CPUS - range 1 5 + range 1 12 help - Number of multiprocessing-capable cores available to the - multicpu API and SMP features. + This is deprecated, please use MP_MAX_NUM_CPUS instead. config MP_MAX_NUM_CPUS int "Maximum number of CPUs/cores" default 1 - range 1 5 + range 1 12 help Maximum number of multiprocessing-capable cores available to the multicpu API and SMP features. @@ -1020,12 +1184,12 @@ config TRACE_SCHED_IPI to check if schedule IPI has called or not, for testing purpose. depends on SCHED_IPI_SUPPORTED - depends on MP_NUM_CPUS>1 + depends on MP_MAX_NUM_CPUS>1 config KERNEL_COHERENCE bool "Place all shared data into coherent memory" depends on ARCH_HAS_COHERENCE - default y if SMP && MP_NUM_CPUS > 1 + default y if SMP && MP_MAX_NUM_CPUS > 1 select THREAD_STACK_INFO help When available and selected, the kernel will build in a mode @@ -1040,6 +1204,19 @@ config KERNEL_COHERENCE may fail strangely. Some assertions exist to catch these mistakes, but not all circumstances can be tested. +config TICKET_SPINLOCKS + bool "Ticket spinlocks for lock acquisition fairness [EXPERIMENTAL]" + select EXPERIMENTAL + help + Basic spinlock implementation is based on single + atomic variable and doesn't guarantee locking fairness + across multiple CPUs. It's even possible that single CPU + will win the contention every time which will result + in a live-lock. + Ticket spinlocks provide a FIFO order of lock acquisition + which resolves such unfairness issue at the cost of slightly + increased memory footprint. + endmenu config TICKLESS_KERNEL diff --git a/kernel/Kconfig.vm b/kernel/Kconfig.vm index 1845c24c16b..97d6c1f424b 100644 --- a/kernel/Kconfig.vm +++ b/kernel/Kconfig.vm @@ -198,4 +198,13 @@ config DEMAND_PAGING_TIMING_HISTOGRAM_NUM_BINS endif # DEMAND_PAGING endif # MMU +config KERNEL_VM_USE_CUSTOM_MEM_RANGE_CHECK + bool + help + Use custom memory range check functions instead of the generic + checks in z_mem_phys_addr() and z_mem_virt_addr(). + + sys_mm_is_phys_addr_in_range() and + sys_mm_is_virt_addr_in_range() must be implemented. + endmenu # Virtual Memory Support diff --git a/kernel/atomic_c.c b/kernel/atomic_c.c index ef6e759a8b5..1790953cb11 100644 --- a/kernel/atomic_c.c +++ b/kernel/atomic_c.c @@ -37,12 +37,12 @@ static struct k_spinlock lock; * forbidden. */ #ifdef CONFIG_USERSPACE -#include +#include #define ATOMIC_SYSCALL_HANDLER_TARGET(name) \ static inline atomic_val_t z_vrfy_##name(atomic_t *target) \ { \ - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(target, sizeof(atomic_t))); \ + K_OOPS(K_SYSCALL_MEMORY_WRITE(target, sizeof(atomic_t))); \ return z_impl_##name((atomic_t *)target); \ } @@ -50,7 +50,7 @@ static struct k_spinlock lock; static inline atomic_val_t z_vrfy_##name(atomic_t *target, \ atomic_val_t value) \ { \ - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(target, sizeof(atomic_t))); \ + K_OOPS(K_SYSCALL_MEMORY_WRITE(target, sizeof(atomic_t))); \ return z_impl_##name((atomic_t *)target, value); \ } #else @@ -108,7 +108,7 @@ bool z_impl_atomic_cas(atomic_t *target, atomic_val_t old_value, bool z_vrfy_atomic_cas(atomic_t *target, atomic_val_t old_value, atomic_val_t new_value) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(target, sizeof(atomic_t))); + K_OOPS(K_SYSCALL_MEMORY_WRITE(target, sizeof(atomic_t))); return z_impl_atomic_cas((atomic_t *)target, old_value, new_value); } @@ -138,7 +138,7 @@ static inline bool z_vrfy_atomic_ptr_cas(atomic_ptr_t *target, atomic_ptr_val_t old_value, atomic_ptr_val_t new_value) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(target, sizeof(atomic_ptr_t))); + K_OOPS(K_SYSCALL_MEMORY_WRITE(target, sizeof(atomic_ptr_t))); return z_impl_atomic_ptr_cas(target, old_value, new_value); } @@ -276,7 +276,7 @@ atomic_ptr_val_t z_impl_atomic_ptr_set(atomic_ptr_t *target, static inline atomic_ptr_val_t z_vrfy_atomic_ptr_set(atomic_ptr_t *target, atomic_ptr_val_t value) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(target, sizeof(atomic_ptr_t))); + K_OOPS(K_SYSCALL_MEMORY_WRITE(target, sizeof(atomic_ptr_t))); return z_impl_atomic_ptr_set(target, value); } diff --git a/kernel/condvar.c b/kernel/condvar.c index 87cb36db316..1aa26e937d3 100644 --- a/kernel/condvar.c +++ b/kernel/condvar.c @@ -8,15 +8,24 @@ #include #include #include -#include -#include +#include +#include +#include + +#ifdef CONFIG_OBJ_CORE_CONDVAR +static struct k_obj_type obj_type_condvar; +#endif static struct k_spinlock lock; int z_impl_k_condvar_init(struct k_condvar *condvar) { z_waitq_init(&condvar->wait_q); - z_object_init(condvar); + k_object_init(condvar); + +#ifdef CONFIG_OBJ_CORE_CONDVAR + k_obj_core_init_and_link(K_OBJ_CORE(condvar), &obj_type_condvar); +#endif SYS_PORT_TRACING_OBJ_INIT(k_condvar, condvar, 0); @@ -26,7 +35,7 @@ int z_impl_k_condvar_init(struct k_condvar *condvar) #ifdef CONFIG_USERSPACE int z_vrfy_k_condvar_init(struct k_condvar *condvar) { - Z_OOPS(Z_SYSCALL_OBJ_INIT(condvar, K_OBJ_CONDVAR)); + K_OOPS(K_SYSCALL_OBJ_INIT(condvar, K_OBJ_CONDVAR)); return z_impl_k_condvar_init(condvar); } #include @@ -58,7 +67,7 @@ int z_impl_k_condvar_signal(struct k_condvar *condvar) #ifdef CONFIG_USERSPACE int z_vrfy_k_condvar_signal(struct k_condvar *condvar) { - Z_OOPS(Z_SYSCALL_OBJ(condvar, K_OBJ_CONDVAR)); + K_OOPS(K_SYSCALL_OBJ(condvar, K_OBJ_CONDVAR)); return z_impl_k_condvar_signal(condvar); } #include @@ -91,7 +100,7 @@ int z_impl_k_condvar_broadcast(struct k_condvar *condvar) #ifdef CONFIG_USERSPACE int z_vrfy_k_condvar_broadcast(struct k_condvar *condvar) { - Z_OOPS(Z_SYSCALL_OBJ(condvar, K_OBJ_CONDVAR)); + K_OOPS(K_SYSCALL_OBJ(condvar, K_OBJ_CONDVAR)); return z_impl_k_condvar_broadcast(condvar); } #include @@ -119,9 +128,31 @@ int z_impl_k_condvar_wait(struct k_condvar *condvar, struct k_mutex *mutex, int z_vrfy_k_condvar_wait(struct k_condvar *condvar, struct k_mutex *mutex, k_timeout_t timeout) { - Z_OOPS(Z_SYSCALL_OBJ(condvar, K_OBJ_CONDVAR)); - Z_OOPS(Z_SYSCALL_OBJ(mutex, K_OBJ_MUTEX)); + K_OOPS(K_SYSCALL_OBJ(condvar, K_OBJ_CONDVAR)); + K_OOPS(K_SYSCALL_OBJ(mutex, K_OBJ_MUTEX)); return z_impl_k_condvar_wait(condvar, mutex, timeout); } #include #endif + +#ifdef CONFIG_OBJ_CORE_CONDVAR +static int init_condvar_obj_core_list(void) +{ + /* Initialize condvar object type */ + + z_obj_type_init(&obj_type_condvar, K_OBJ_TYPE_CONDVAR_ID, + offsetof(struct k_condvar, obj_core)); + + /* Initialize and link statically defined condvars */ + + STRUCT_SECTION_FOREACH(k_condvar, condvar) { + k_obj_core_init_and_link(K_OBJ_CORE(condvar), + &obj_type_condvar); + } + + return 0; +} + +SYS_INIT(init_condvar_obj_core_list, PRE_KERNEL_1, + CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); +#endif diff --git a/kernel/device.c b/kernel/device.c index d5ceb615461..6124ada5140 100644 --- a/kernel/device.c +++ b/kernel/device.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include /** @@ -21,7 +21,7 @@ void z_device_state_init(void) { STRUCT_SECTION_FOREACH(device, dev) { - z_object_init(dev); + k_object_init(dev); } } @@ -59,7 +59,7 @@ static inline const struct device *z_vrfy_device_get_binding(const char *name) { char name_copy[Z_DEVICE_MAX_NAME_LEN]; - if (z_user_string_copy(name_copy, (char *)name, sizeof(name_copy)) + if (k_usermode_string_copy(name_copy, (char *)name, sizeof(name_copy)) != 0) { return NULL; } @@ -70,7 +70,7 @@ static inline const struct device *z_vrfy_device_get_binding(const char *name) static inline bool z_vrfy_device_is_ready(const struct device *dev) { - Z_OOPS(Z_SYSCALL_OBJ_INIT(dev, K_OBJ_ANY)); + K_OOPS(K_SYSCALL_OBJ_INIT(dev, K_OBJ_ANY)); return z_impl_device_is_ready(dev); } diff --git a/kernel/dynamic.c b/kernel/dynamic.c index 23e64e802b5..d30dba8ac02 100644 --- a/kernel/dynamic.c +++ b/kernel/dynamic.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); @@ -112,7 +112,8 @@ static void dyn_cb(const struct k_thread *thread, void *user_data) struct dyn_cb_data *const data = (struct dyn_cb_data *)user_data; if (data->stack == (k_thread_stack_t *)thread->stack_info.start) { - __ASSERT(data->tid == NULL, "stack %p is associated with more than one thread!"); + __ASSERT(data->tid == NULL, "stack %p is associated with more than one thread!", + (void *)thread->stack_info.start); data->tid = (k_tid_t)thread; } } @@ -151,7 +152,7 @@ int z_impl_k_thread_stack_free(k_thread_stack_t *stack) if (IS_ENABLED(CONFIG_DYNAMIC_THREAD_ALLOC)) { #ifdef CONFIG_USERSPACE - if (z_object_find(stack)) { + if (k_object_find(stack)) { k_object_free(stack); } else { k_free(stack); diff --git a/kernel/errno.c b/kernel/errno.c index 37866819bf5..645597f02c7 100644 --- a/kernel/errno.c +++ b/kernel/errno.c @@ -13,7 +13,7 @@ */ #include -#include +#include /* * Define _k_neg_eagain for use in assembly files as errno.h is diff --git a/kernel/events.c b/kernel/events.c index 96cae5bc4a8..8cb90dc6160 100644 --- a/kernel/events.c +++ b/kernel/events.c @@ -25,13 +25,14 @@ #include #include -#include #include -#include #include -#include +#include #include #include +/* private kernel APIs */ +#include +#include #define K_EVENT_WAIT_ANY 0x00 /* Wait for any events */ #define K_EVENT_WAIT_ALL 0x01 /* Wait for all events */ @@ -44,6 +45,10 @@ struct event_walk_data { uint32_t events; }; +#ifdef CONFIG_OBJ_CORE_EVENT +static struct k_obj_type obj_type_event; +#endif + void z_impl_k_event_init(struct k_event *event) { event->events = 0; @@ -53,13 +58,17 @@ void z_impl_k_event_init(struct k_event *event) z_waitq_init(&event->wait_q); - z_object_init(event); + k_object_init(event); + +#ifdef CONFIG_OBJ_CORE_EVENT + k_obj_core_init_and_link(K_OBJ_CORE(event), &obj_type_event); +#endif } #ifdef CONFIG_USERSPACE void z_vrfy_k_event_init(struct k_event *event) { - Z_OOPS(Z_SYSCALL_OBJ_NEVER_INIT(event, K_OBJ_EVENT)); + K_OOPS(K_SYSCALL_OBJ_NEVER_INIT(event, K_OBJ_EVENT)); z_impl_k_event_init(event); } #include @@ -178,7 +187,7 @@ uint32_t z_impl_k_event_post(struct k_event *event, uint32_t events) #ifdef CONFIG_USERSPACE uint32_t z_vrfy_k_event_post(struct k_event *event, uint32_t events) { - Z_OOPS(Z_SYSCALL_OBJ(event, K_OBJ_EVENT)); + K_OOPS(K_SYSCALL_OBJ(event, K_OBJ_EVENT)); return z_impl_k_event_post(event, events); } #include @@ -192,7 +201,7 @@ uint32_t z_impl_k_event_set(struct k_event *event, uint32_t events) #ifdef CONFIG_USERSPACE uint32_t z_vrfy_k_event_set(struct k_event *event, uint32_t events) { - Z_OOPS(Z_SYSCALL_OBJ(event, K_OBJ_EVENT)); + K_OOPS(K_SYSCALL_OBJ(event, K_OBJ_EVENT)); return z_impl_k_event_set(event, events); } #include @@ -208,7 +217,7 @@ uint32_t z_impl_k_event_set_masked(struct k_event *event, uint32_t events, uint32_t z_vrfy_k_event_set_masked(struct k_event *event, uint32_t events, uint32_t events_mask) { - Z_OOPS(Z_SYSCALL_OBJ(event, K_OBJ_EVENT)); + K_OOPS(K_SYSCALL_OBJ(event, K_OBJ_EVENT)); return z_impl_k_event_set_masked(event, events, events_mask); } #include @@ -222,7 +231,7 @@ uint32_t z_impl_k_event_clear(struct k_event *event, uint32_t events) #ifdef CONFIG_USERSPACE uint32_t z_vrfy_k_event_clear(struct k_event *event, uint32_t events) { - Z_OOPS(Z_SYSCALL_OBJ(event, K_OBJ_EVENT)); + K_OOPS(K_SYSCALL_OBJ(event, K_OBJ_EVENT)); return z_impl_k_event_clear(event, events); } #include @@ -247,7 +256,7 @@ static uint32_t k_event_wait_internal(struct k_event *event, uint32_t events, } wait_condition = options & K_EVENT_WAIT_MASK; - thread = z_current_get(); + thread = k_sched_current_thread_query(); k_spinlock_key_t key = k_spin_lock(&event->lock); @@ -308,7 +317,7 @@ uint32_t z_impl_k_event_wait(struct k_event *event, uint32_t events, uint32_t z_vrfy_k_event_wait(struct k_event *event, uint32_t events, bool reset, k_timeout_t timeout) { - Z_OOPS(Z_SYSCALL_OBJ(event, K_OBJ_EVENT)); + K_OOPS(K_SYSCALL_OBJ(event, K_OBJ_EVENT)); return z_impl_k_event_wait(event, events, reset, timeout); } #include @@ -330,8 +339,29 @@ uint32_t z_impl_k_event_wait_all(struct k_event *event, uint32_t events, uint32_t z_vrfy_k_event_wait_all(struct k_event *event, uint32_t events, bool reset, k_timeout_t timeout) { - Z_OOPS(Z_SYSCALL_OBJ(event, K_OBJ_EVENT)); + K_OOPS(K_SYSCALL_OBJ(event, K_OBJ_EVENT)); return z_impl_k_event_wait_all(event, events, reset, timeout); } #include #endif + +#ifdef CONFIG_OBJ_CORE_EVENT +static int init_event_obj_core_list(void) +{ + /* Initialize condvar object type */ + + z_obj_type_init(&obj_type_event, K_OBJ_TYPE_EVENT_ID, + offsetof(struct k_event, obj_core)); + + /* Initialize and link statically defined condvars */ + + STRUCT_SECTION_FOREACH(k_event, event) { + k_obj_core_init_and_link(K_OBJ_CORE(event), &obj_type_event); + } + + return 0; +} + +SYS_INIT(init_event_obj_core_list, PRE_KERNEL_1, + CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); +#endif diff --git a/kernel/fatal.c b/kernel/fatal.c index a94aecd1cca..7a3733cbfef 100644 --- a/kernel/fatal.c +++ b/kernel/fatal.c @@ -84,15 +84,6 @@ FUNC_NORETURN void k_fatal_halt(unsigned int reason) } /* LCOV_EXCL_STOP */ -static inline int get_cpu(void) -{ -#if defined(CONFIG_SMP) - return arch_curr_cpu()->id; -#else - return 0; -#endif -} - void z_fatal_error(unsigned int reason, const z_arch_esf_t *esf) { /* We can't allow this code to be preempted, but don't need to @@ -101,13 +92,13 @@ void z_fatal_error(unsigned int reason, const z_arch_esf_t *esf) */ unsigned int key = arch_irq_lock(); struct k_thread *thread = IS_ENABLED(CONFIG_MULTITHREADING) ? - k_current_get() : NULL; + _current : NULL; /* twister looks for the "ZEPHYR FATAL ERROR" string, don't * change it without also updating twister */ LOG_ERR(">>> ZEPHYR FATAL ERROR %d: %s on CPU %d", reason, - reason_to_str(reason), get_cpu()); + reason_to_str(reason), _current_cpu->id); /* FIXME: This doesn't seem to work as expected on all arches. * Need a reliable way to determine whether the fault happened when diff --git a/kernel/futex.c b/kernel/futex.c index 40362045eab..1354a6314e4 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -8,15 +8,15 @@ #include #include #include -#include +#include #include #include static struct z_futex_data *k_futex_find_data(struct k_futex *futex) { - struct z_object *obj; + struct k_object *obj; - obj = z_object_find(futex); + obj = k_object_find(futex); if (obj == NULL || obj->type != K_OBJ_FUTEX) { return NULL; } @@ -54,7 +54,7 @@ int z_impl_k_futex_wake(struct k_futex *futex, bool wake_all) static inline int z_vrfy_k_futex_wake(struct k_futex *futex, bool wake_all) { - if (Z_SYSCALL_MEMORY_WRITE(futex, sizeof(struct k_futex)) != 0) { + if (K_SYSCALL_MEMORY_WRITE(futex, sizeof(struct k_futex)) != 0) { return -EACCES; } @@ -92,7 +92,7 @@ int z_impl_k_futex_wait(struct k_futex *futex, int expected, static inline int z_vrfy_k_futex_wait(struct k_futex *futex, int expected, k_timeout_t timeout) { - if (Z_SYSCALL_MEMORY_WRITE(futex, sizeof(struct k_futex)) != 0) { + if (K_SYSCALL_MEMORY_WRITE(futex, sizeof(struct k_futex)) != 0) { return -EACCES; } diff --git a/kernel/idle.c b/kernel/idle.c index be3902a5b41..290b45976d9 100644 --- a/kernel/idle.c +++ b/kernel/idle.c @@ -8,12 +8,13 @@ #include #include #include -#include #include #include #include +/* private kernel APIs */ #include #include +#include LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); diff --git a/kernel/include/kernel_arch_interface.h b/kernel/include/kernel_arch_interface.h index 16cfda41f54..0173a4ae398 100644 --- a/kernel/include/kernel_arch_interface.h +++ b/kernel/include/kernel_arch_interface.h @@ -402,9 +402,17 @@ void arch_mem_page_in(void *addr, uintptr_t phys); */ void arch_mem_scratch(uintptr_t phys); +/** + * Status of a particular page location. + */ enum arch_page_location { + /** The page has been evicted to the backing store. */ ARCH_PAGE_LOCATION_PAGED_OUT, + + /** The page is resident in memory. */ ARCH_PAGE_LOCATION_PAGED_IN, + + /** The page is not mapped. */ ARCH_PAGE_LOCATION_BAD }; @@ -554,9 +562,6 @@ int arch_printk_char_out(int c); * * This function is invoked near the top of _Cstart, for additional * architecture-specific setup before the rest of the kernel is brought up. - * - * TODO: Deprecate, most arches are using a prep_c() function to do the same - * thing in a simpler way */ static inline void arch_kernel_init(void); @@ -597,7 +602,7 @@ uint16_t arch_coredump_tgt_code_get(void); * @brief Setup Architecture-specific TLS area in stack * * This sets up the stack area for thread local storage. - * The structure inside in area is architecture specific. + * The structure inside TLS area is architecture specific. * * @param new_thread New thread object * @param stack_ptr Stack pointer diff --git a/kernel/include/kernel_internal.h b/kernel/include/kernel_internal.h index aaee3095d9e..711313b5ce7 100644 --- a/kernel/include/kernel_internal.h +++ b/kernel/include/kernel_internal.h @@ -24,8 +24,11 @@ extern "C" { #endif -/* Early boot functions */ +/* Initialize a thread */ +void z_init_thread_base(struct _thread_base *thread_base, int priority, + uint32_t initial_state, unsigned int options); +/* Early boot functions */ void z_early_memset(void *dst, int c, size_t n); void z_early_memcpy(void *dst, const void *src, size_t n); @@ -146,7 +149,7 @@ extern void smp_timer_init(void); #endif #endif -extern void z_early_boot_rand_get(uint8_t *buf, size_t length); +extern void z_early_rand_get(uint8_t *buf, size_t length); #if CONFIG_STACK_POINTER_RANDOM extern int z_stack_adjust_initialized; @@ -227,6 +230,9 @@ void z_mem_manage_init(void); */ void z_mem_manage_boot_finish(void); + +void z_handle_obj_poll_events(sys_dlist_t *events, uint32_t state); + #ifdef CONFIG_PM /* When the kernel is about to go idle, it calls this function to notify the @@ -286,6 +292,22 @@ void z_paging_histogram_inc(struct k_mem_paging_histogram_t *hist, uint32_t cycles); #endif /* CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM */ +#ifdef CONFIG_OBJ_CORE_STATS_THREAD +int z_thread_stats_raw(struct k_obj_core *obj_core, void *stats); +int z_thread_stats_query(struct k_obj_core *obj_core, void *stats); +int z_thread_stats_reset(struct k_obj_core *obj_core); +int z_thread_stats_disable(struct k_obj_core *obj_core); +int z_thread_stats_enable(struct k_obj_core *obj_core); +#endif + +#ifdef CONFIG_OBJ_CORE_STATS_SYSTEM +int z_cpu_stats_raw(struct k_obj_core *obj_core, void *stats); +int z_cpu_stats_query(struct k_obj_core *obj_core, void *stats); + +int z_kernel_stats_raw(struct k_obj_core *obj_core, void *stats); +int z_kernel_stats_query(struct k_obj_core *obj_core, void *stats); +#endif + #ifdef __cplusplus } #endif diff --git a/kernel/include/ksched.h b/kernel/include/ksched.h index 0ec1897a2f3..a6898a8bdf4 100644 --- a/kernel/include/ksched.h +++ b/kernel/include/ksched.h @@ -9,10 +9,12 @@ #include #include -#include +#include #include #include +bool z_is_thread_essential(void); + BUILD_ASSERT(K_LOWEST_APPLICATION_THREAD_PRIO >= K_HIGHEST_APPLICATION_THREAD_PRIO); @@ -268,15 +270,6 @@ static ALWAYS_INLINE void z_sched_unlock_no_reschedule(void) ++_current->base.sched_locked; } -static ALWAYS_INLINE bool z_is_thread_timeout_expired(struct k_thread *thread) -{ -#ifdef CONFIG_SYS_CLOCK_EXISTS - return thread->base.timeout.dticks == _EXPIRED; -#else - return 0; -#endif -} - /* * APIs for working with the Zephyr kernel scheduler. Intended for use in * management of IPC objects, either in the core kernel or other IPC diff --git a/kernel/include/mmu.h b/kernel/include/mmu.h index f51c0adeda0..cd290100e40 100644 --- a/kernel/include/mmu.h +++ b/kernel/include/mmu.h @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include /* diff --git a/include/zephyr/timeout_q.h b/kernel/include/timeout_q.h similarity index 100% rename from include/zephyr/timeout_q.h rename to kernel/include/timeout_q.h diff --git a/include/zephyr/wait_q.h b/kernel/include/wait_q.h similarity index 94% rename from include/zephyr/wait_q.h rename to kernel/include/wait_q.h index 3edcb77702a..0c44a89eb66 100644 --- a/include/zephyr/wait_q.h +++ b/kernel/include/wait_q.h @@ -12,8 +12,8 @@ #include #include #include -#include -#include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/kernel/init.c b/kernel/init.c index 3d5991f1fbe..e4637d3aff1 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include @@ -37,7 +37,6 @@ #include LOG_MODULE_REGISTER(os, CONFIG_KERNEL_LOG_LEVEL); - BUILD_ASSERT(CONFIG_MP_NUM_CPUS == CONFIG_MP_MAX_NUM_CPUS, "CONFIG_MP_NUM_CPUS and CONFIG_MP_MAX_NUM_CPUS need to be set the same"); @@ -98,6 +97,32 @@ K_KERNEL_PINNED_STACK_ARRAY_DEFINE(z_interrupt_stacks, extern void idle(void *unused1, void *unused2, void *unused3); +#ifdef CONFIG_OBJ_CORE_SYSTEM +static struct k_obj_type obj_type_cpu; +static struct k_obj_type obj_type_kernel; + +#ifdef CONFIG_OBJ_CORE_STATS_SYSTEM +static struct k_obj_core_stats_desc cpu_stats_desc = { + .raw_size = sizeof(struct k_cycle_stats), + .query_size = sizeof(struct k_thread_runtime_stats), + .raw = z_cpu_stats_raw, + .query = z_cpu_stats_query, + .reset = NULL, + .disable = NULL, + .enable = NULL, +}; + +static struct k_obj_core_stats_desc kernel_stats_desc = { + .raw_size = sizeof(struct k_cycle_stats) * CONFIG_MP_MAX_NUM_CPUS, + .query_size = sizeof(struct k_thread_runtime_stats), + .raw = z_kernel_stats_raw, + .query = z_kernel_stats_query, + .reset = NULL, + .disable = NULL, + .enable = NULL, +}; +#endif +#endif /* LCOV_EXCL_START * @@ -140,12 +165,7 @@ void __weak z_early_memcpy(void *dst, const void *src, size_t n) __boot_func void z_bss_zero(void) { - if (IS_ENABLED(CONFIG_ARCH_POSIX)) { - /* native_posix gets its memory cleared on entry by - * the host OS, and in any case the host clang/lld - * doesn't emit the __bss_end symbol this code expects - * to see - */ + if (IS_ENABLED(CONFIG_SKIP_BSS_CLEAR)) { return; } @@ -399,7 +419,8 @@ void z_init_cpu(int id) (Z_KERNEL_STACK_BUFFER(z_interrupt_stacks[id]) + K_KERNEL_STACK_SIZEOF(z_interrupt_stacks[id])); #ifdef CONFIG_SCHED_THREAD_USAGE_ALL - _kernel.cpus[id].usage.track_usage = + _kernel.cpus[id].usage = &_kernel.usage[id]; + _kernel.cpus[id].usage->track_usage = CONFIG_SCHED_THREAD_USAGE_AUTO_ENABLE; #endif @@ -408,6 +429,15 @@ void z_init_cpu(int id) * will keep track of this from here. */ atomic_inc(&_cpus_active); + +#ifdef CONFIG_OBJ_CORE_SYSTEM + k_obj_core_init_and_link(K_OBJ_CORE(&_kernel.cpus[id]), &obj_type_cpu); +#ifdef CONFIG_OBJ_CORE_STATS_SYSTEM + k_obj_core_stats_register(K_OBJ_CORE(&_kernel.cpus[id]), + _kernel.cpus[id].usage, + sizeof(struct k_cycle_stats)); +#endif +#endif } /** @@ -473,46 +503,38 @@ static FUNC_NORETURN void switch_to_main_thread(char *stack_ptr) } #endif /* CONFIG_MULTITHREADING */ -#if defined(CONFIG_ENTROPY_HAS_DRIVER) || defined(CONFIG_TEST_RANDOM_GENERATOR) __boot_func -void z_early_boot_rand_get(uint8_t *buf, size_t length) +void __weak z_early_rand_get(uint8_t *buf, size_t length) { -#ifdef CONFIG_ENTROPY_HAS_DRIVER - const struct device *const entropy = DEVICE_DT_GET_OR_NULL(DT_CHOSEN(zephyr_entropy)); + static uint64_t state = (uint64_t)CONFIG_TIMER_RANDOM_INITIAL_STATE; int rc; - if (!device_is_ready(entropy)) { - goto sys_rand_fallback; - } - - /* Try to see if driver provides an ISR-specific API */ - rc = entropy_get_entropy_isr(entropy, buf, length, ENTROPY_BUSYWAIT); - if (rc == -ENOTSUP) { - /* Driver does not provide an ISR-specific API, assume it can - * be called from ISR context - */ - rc = entropy_get_entropy(entropy, buf, length); - } +#ifdef CONFIG_ENTROPY_HAS_DRIVER + const struct device *const entropy = DEVICE_DT_GET_OR_NULL(DT_CHOSEN(zephyr_entropy)); - if (rc >= 0) { - return; + if ((entropy != NULL) && device_is_ready(entropy)) { + /* Try to see if driver provides an ISR-specific API */ + rc = entropy_get_entropy_isr(entropy, buf, length, ENTROPY_BUSYWAIT); + if (rc > 0) { + length -= rc; + buf += rc; + } } +#endif - /* Fall through to fallback */ + while (length > 0) { + uint32_t val; -sys_rand_fallback: -#endif + state = state + k_cycle_get_32(); + state = state * 2862933555777941757ULL + 3037000493ULL; + val = (uint32_t)(state >> 32); + rc = MIN(length, sizeof(val)); + z_early_memcpy((void *)buf, &val, rc); - /* FIXME: this assumes sys_rand32_get() won't use any synchronization - * primitive, like semaphores or mutexes. It's too early in the boot - * process to use any of them. Ideally, only the path where entropy - * devices are available should be built, this is only a fallback for - * those devices without a HWRNG entropy driver. - */ - sys_rand_get(buf, length); + length -= rc; + buf += rc; + } } -/* defined(CONFIG_ENTROPY_HAS_DRIVER) || defined(CONFIG_TEST_RANDOM_GENERATOR) */ -#endif /** * @@ -557,7 +579,7 @@ FUNC_NORETURN void z_cstart(void) #ifdef CONFIG_STACK_CANARIES uintptr_t stack_guard; - z_early_boot_rand_get((uint8_t *)&stack_guard, sizeof(stack_guard)); + z_early_rand_get((uint8_t *)&stack_guard, sizeof(stack_guard)); __stack_chk_guard = stack_guard; __stack_chk_guard <<= 8; #endif /* CONFIG_STACK_CANARIES */ @@ -597,3 +619,45 @@ FUNC_NORETURN void z_cstart(void) CODE_UNREACHABLE; /* LCOV_EXCL_LINE */ } + +#ifdef CONFIG_OBJ_CORE_SYSTEM +static int init_cpu_obj_core_list(void) +{ + /* Initialize CPU object type */ + + z_obj_type_init(&obj_type_cpu, K_OBJ_TYPE_CPU_ID, + offsetof(struct _cpu, obj_core)); + +#ifdef CONFIG_OBJ_CORE_STATS_SYSTEM + k_obj_type_stats_init(&obj_type_cpu, &cpu_stats_desc); +#endif + + return 0; +} + +static int init_kernel_obj_core_list(void) +{ + /* Initialize kernel object type */ + + z_obj_type_init(&obj_type_kernel, K_OBJ_TYPE_KERNEL_ID, + offsetof(struct z_kernel, obj_core)); + +#ifdef CONFIG_OBJ_CORE_STATS_SYSTEM + k_obj_type_stats_init(&obj_type_kernel, &kernel_stats_desc); +#endif + + k_obj_core_init_and_link(K_OBJ_CORE(&_kernel), &obj_type_kernel); +#ifdef CONFIG_OBJ_CORE_STATS_SYSTEM + k_obj_core_stats_register(K_OBJ_CORE(&_kernel), _kernel.usage, + sizeof(_kernel.usage)); +#endif + + return 0; +} + +SYS_INIT(init_cpu_obj_core_list, PRE_KERNEL_1, + CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); + +SYS_INIT(init_kernel_obj_core_list, PRE_KERNEL_1, + CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); +#endif diff --git a/kernel/kheap.c b/kernel/kheap.c index fc2d3300e78..71a3da596ad 100644 --- a/kernel/kheap.c +++ b/kernel/kheap.c @@ -5,11 +5,12 @@ */ #include -#include -#include #include #include #include +/* private kernel APIs */ +#include +#include void k_heap_init(struct k_heap *h, void *mem, size_t bytes) { diff --git a/kernel/mailbox.c b/kernel/mailbox.c index 3014af57063..2d7d28da03a 100644 --- a/kernel/mailbox.c +++ b/kernel/mailbox.c @@ -14,10 +14,15 @@ #include #include #include -#include -#include #include #include +/* private kernel APIs */ +#include +#include + +#ifdef CONFIG_OBJ_CORE_MAILBOX +static struct k_obj_type obj_type_mailbox; +#endif #if (CONFIG_NUM_MBOX_ASYNC_MSGS > 0) @@ -90,6 +95,10 @@ void k_mbox_init(struct k_mbox *mbox) z_waitq_init(&mbox->rx_msg_queue); mbox->lock = (struct k_spinlock) {}; +#ifdef CONFIG_OBJ_CORE_MAILBOX + k_obj_core_init_and_link(K_OBJ_CORE(mbox), &obj_type_mailbox); +#endif + SYS_PORT_TRACING_OBJ_INIT(k_mbox, mbox); } @@ -131,14 +140,6 @@ static int mbox_message_match(struct k_mbox_msg *tx_msg, /* update data location fields for receiver only */ rx_msg->tx_data = tx_msg->tx_data; - rx_msg->tx_block = tx_msg->tx_block; - if (rx_msg->tx_data != NULL) { - rx_msg->tx_block.data = NULL; - } else if (rx_msg->tx_block.data != NULL) { - rx_msg->tx_data = rx_msg->tx_block.data; - } else { - /* no data */ - } /* update syncing thread field for receiver only */ rx_msg->_syncing_thread = tx_msg->_syncing_thread; @@ -152,8 +153,7 @@ static int mbox_message_match(struct k_mbox_msg *tx_msg, /** * @brief Dispose of received message. * - * Releases any memory pool block still associated with the message, - * then notifies the sender that message processing is complete. + * Notifies the sender that message processing is complete. * * @param rx_msg Pointer to receive message descriptor. */ @@ -167,10 +167,6 @@ static void mbox_message_dispose(struct k_mbox_msg *rx_msg) return; } - if (rx_msg->tx_block.data != NULL) { - rx_msg->tx_block.data = NULL; - } - /* recover sender info */ sending_thread = rx_msg->_syncing_thread; rx_msg->_syncing_thread = NULL; @@ -446,3 +442,25 @@ int k_mbox_get(struct k_mbox *mbox, struct k_mbox_msg *rx_msg, void *buffer, return result; } + +#ifdef CONFIG_OBJ_CORE_MAILBOX + +static int init_mailbox_obj_core_list(void) +{ + /* Initialize mailbox object type */ + + z_obj_type_init(&obj_type_mailbox, K_OBJ_TYPE_MBOX_ID, + offsetof(struct k_mbox, obj_core)); + + /* Initialize and link satically defined mailboxes */ + + STRUCT_SECTION_FOREACH(k_mbox, mbox) { + k_obj_core_init_and_link(K_OBJ_CORE(mbox), &obj_type_mailbox); + } + + return 0; +} + +SYS_INIT(init_mailbox_obj_core_list, PRE_KERNEL_1, + CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); +#endif diff --git a/kernel/mem_slab.c b/kernel/mem_slab.c index b03b731d473..3be1066d2b7 100644 --- a/kernel/mem_slab.c +++ b/kernel/mem_slab.c @@ -9,12 +9,88 @@ #include #include -#include #include -#include #include #include #include +#include +/* private kernel APIs */ +#include +#include + +#ifdef CONFIG_OBJ_CORE_MEM_SLAB +static struct k_obj_type obj_type_mem_slab; + +#ifdef CONFIG_OBJ_CORE_STATS_MEM_SLAB + +static int k_mem_slab_stats_raw(struct k_obj_core *obj_core, void *stats) +{ + __ASSERT((obj_core != NULL) && (stats != NULL), "NULL parameter"); + + struct k_mem_slab *slab; + k_spinlock_key_t key; + + slab = CONTAINER_OF(obj_core, struct k_mem_slab, obj_core); + key = k_spin_lock(&slab->lock); + memcpy(stats, &slab->info, sizeof(slab->info)); + k_spin_unlock(&slab->lock, key); + + return 0; +} + +static int k_mem_slab_stats_query(struct k_obj_core *obj_core, void *stats) +{ + __ASSERT((obj_core != NULL) && (stats != NULL), "NULL parameter"); + + struct k_mem_slab *slab; + k_spinlock_key_t key; + struct sys_memory_stats *ptr = stats; + + slab = CONTAINER_OF(obj_core, struct k_mem_slab, obj_core); + key = k_spin_lock(&slab->lock); + ptr->free_bytes = (slab->info.num_blocks - slab->info.num_used) * + slab->info.block_size; + ptr->allocated_bytes = slab->info.num_used * slab->info.block_size; +#ifdef CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION + ptr->max_allocated_bytes = slab->info.max_used * slab->info.block_size; +#else + ptr->max_allocated_bytes = 0; +#endif + k_spin_unlock(&slab->lock, key); + + return 0; +} + +static int k_mem_slab_stats_reset(struct k_obj_core *obj_core) +{ + __ASSERT(obj_core != NULL, "NULL parameter"); + + struct k_mem_slab *slab; + k_spinlock_key_t key; + + slab = CONTAINER_OF(obj_core, struct k_mem_slab, obj_core); + key = k_spin_lock(&slab->lock); + +#ifdef CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION + slab->info.max_used = slab->info.num_used; +#endif + + k_spin_unlock(&slab->lock, key); + + return 0; +} + +static struct k_obj_core_stats_desc mem_slab_stats_desc = { + .raw_size = sizeof(struct k_mem_slab_info), + .query_size = sizeof(struct sys_memory_stats), + .raw = k_mem_slab_stats_raw, + .query = k_mem_slab_stats_query, + .reset = k_mem_slab_stats_reset, + .disable = NULL, + .enable = NULL, +}; +#endif +#endif /** * @brief Initialize kernel memory slab subsystem. @@ -31,7 +107,7 @@ static int create_free_list(struct k_mem_slab *slab) char *p; /* blocks must be word aligned */ - CHECKIF(((slab->block_size | (uintptr_t)slab->buffer) & + CHECKIF(((slab->info.block_size | (uintptr_t)slab->buffer) & (sizeof(void *) - 1)) != 0U) { return -EINVAL; } @@ -39,10 +115,10 @@ static int create_free_list(struct k_mem_slab *slab) slab->free_list = NULL; p = slab->buffer; - for (j = 0U; j < slab->num_blocks; j++) { + for (j = 0U; j < slab->info.num_blocks; j++) { *(char **)p = slab->free_list; slab->free_list = p; - p += slab->block_size; + p += slab->info.block_size; } return 0; } @@ -54,23 +130,43 @@ static int create_free_list(struct k_mem_slab *slab) * * @return 0 on success, fails otherwise. */ -static int init_mem_slab_module(void) +static int init_mem_slab_obj_core_list(void) { int rc = 0; + /* Initialize mem_slab object type */ + +#ifdef CONFIG_OBJ_CORE_MEM_SLAB + z_obj_type_init(&obj_type_mem_slab, K_OBJ_TYPE_MEM_SLAB_ID, + offsetof(struct k_mem_slab, obj_core)); +#ifdef CONFIG_OBJ_CORE_STATS_MEM_SLAB + k_obj_type_stats_init(&obj_type_mem_slab, &mem_slab_stats_desc); +#endif +#endif + + /* Initialize statically defined mem_slabs */ + STRUCT_SECTION_FOREACH(k_mem_slab, slab) { rc = create_free_list(slab); if (rc < 0) { goto out; } - z_object_init(slab); + k_object_init(slab); + +#ifdef CONFIG_OBJ_CORE_MEM_SLAB + k_obj_core_init_and_link(K_OBJ_CORE(slab), &obj_type_mem_slab); +#ifdef CONFIG_OBJ_CORE_STATS_MEM_SLAB + k_obj_core_stats_register(K_OBJ_CORE(slab), &slab->info, + sizeof(struct k_mem_slab_info)); +#endif +#endif } out: return rc; } -SYS_INIT(init_mem_slab_module, PRE_KERNEL_1, +SYS_INIT(init_mem_slab_obj_core_list, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); int k_mem_slab_init(struct k_mem_slab *slab, void *buffer, @@ -78,14 +174,14 @@ int k_mem_slab_init(struct k_mem_slab *slab, void *buffer, { int rc = 0; - slab->num_blocks = num_blocks; - slab->block_size = block_size; + slab->info.num_blocks = num_blocks; + slab->info.block_size = block_size; slab->buffer = buffer; - slab->num_used = 0U; + slab->info.num_used = 0U; slab->lock = (struct k_spinlock) {}; #ifdef CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION - slab->max_used = 0U; + slab->info.max_used = 0U; #endif rc = create_free_list(slab); @@ -93,8 +189,16 @@ int k_mem_slab_init(struct k_mem_slab *slab, void *buffer, goto out; } +#ifdef CONFIG_OBJ_CORE_MEM_SLAB + k_obj_core_init_and_link(K_OBJ_CORE(slab), &obj_type_mem_slab); +#endif +#ifdef CONFIG_OBJ_CORE_STATS_MEM_SLAB + k_obj_core_stats_register(K_OBJ_CORE(slab), &slab->info, + sizeof(struct k_mem_slab_info)); +#endif + z_waitq_init(&slab->wait_q); - z_object_init(slab); + k_object_init(slab); out: SYS_PORT_TRACING_OBJ_INIT(k_mem_slab, slab, rc); @@ -112,10 +216,11 @@ int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem, k_timeout_t timeout) /* take a free block */ *mem = slab->free_list; slab->free_list = *(char **)(slab->free_list); - slab->num_used++; + slab->info.num_used++; #ifdef CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION - slab->max_used = MAX(slab->num_used, slab->max_used); + slab->info.max_used = MAX(slab->info.num_used, + slab->info.max_used); #endif result = 0; @@ -150,8 +255,9 @@ void k_mem_slab_free(struct k_mem_slab *slab, void *mem) k_spinlock_key_t key = k_spin_lock(&slab->lock); __ASSERT(((char *)mem >= slab->buffer) && - ((((char *)mem - slab->buffer) % slab->block_size) == 0) && - ((char *)mem <= (slab->buffer + (slab->block_size * (slab->num_blocks - 1)))), + ((((char *)mem - slab->buffer) % slab->info.block_size) == 0) && + ((char *)mem <= (slab->buffer + (slab->info.block_size * + (slab->info.num_blocks - 1)))), "Invalid memory pointer provided"); SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_mem_slab, free, slab); @@ -169,7 +275,7 @@ void k_mem_slab_free(struct k_mem_slab *slab, void *mem) } *(char **) mem = slab->free_list; slab->free_list = (char *) mem; - slab->num_used--; + slab->info.num_used--; SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_mem_slab, free, slab); @@ -184,10 +290,12 @@ int k_mem_slab_runtime_stats_get(struct k_mem_slab *slab, struct sys_memory_stat k_spinlock_key_t key = k_spin_lock(&slab->lock); - stats->allocated_bytes = slab->num_used * slab->block_size; - stats->free_bytes = (slab->num_blocks - slab->num_used) * slab->block_size; + stats->allocated_bytes = slab->info.num_used * slab->info.block_size; + stats->free_bytes = (slab->info.num_blocks - slab->info.num_used) * + slab->info.block_size; #ifdef CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION - stats->max_allocated_bytes = slab->max_used * slab->block_size; + stats->max_allocated_bytes = slab->info.max_used * + slab->info.block_size; #else stats->max_allocated_bytes = 0; #endif @@ -206,7 +314,7 @@ int k_mem_slab_runtime_stats_reset_max(struct k_mem_slab *slab) k_spinlock_key_t key = k_spin_lock(&slab->lock); - slab->max_used = slab->num_used; + slab->info.max_used = slab->info.num_used; k_spin_unlock(&slab->lock, key); diff --git a/kernel/mmu.c b/kernel/mmu.c index 8f6a811bc4f..6abd9349dd6 100644 --- a/kernel/mmu.c +++ b/kernel/mmu.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include @@ -469,7 +469,9 @@ static int virt_to_page_frame(void *virt, uintptr_t *phys) if (z_page_frame_is_mapped(pf)) { if (virt == pf->addr) { ret = 0; - *phys = z_page_frame_to_phys(pf); + if (phys != NULL) { + *phys = z_page_frame_to_phys(pf); + } break; } } diff --git a/kernel/msg_q.c b/kernel/msg_q.c index 1179612ce42..e11e9a2527e 100644 --- a/kernel/msg_q.c +++ b/kernel/msg_q.c @@ -17,14 +17,18 @@ #include #include #include -#include +#include #include #include #include -#include +#include #include #include +#ifdef CONFIG_OBJ_CORE_MSGQ +static struct k_obj_type obj_type_msgq; +#endif + #ifdef CONFIG_POLL static inline void handle_poll_events(struct k_msgq *msgq, uint32_t state) { @@ -49,9 +53,13 @@ void k_msgq_init(struct k_msgq *msgq, char *buffer, size_t msg_size, sys_dlist_init(&msgq->poll_events); #endif /* CONFIG_POLL */ +#ifdef CONFIG_OBJ_CORE_MSGQ + k_obj_core_init_and_link(K_OBJ_CORE(msgq), &obj_type_msgq); +#endif + SYS_PORT_TRACING_OBJ_INIT(k_msgq, msgq); - z_object_init(msgq); + k_object_init(msgq); } int z_impl_k_msgq_alloc_init(struct k_msgq *msgq, size_t msg_size, @@ -85,7 +93,7 @@ int z_impl_k_msgq_alloc_init(struct k_msgq *msgq, size_t msg_size, int z_vrfy_k_msgq_alloc_init(struct k_msgq *msgq, size_t msg_size, uint32_t max_msgs) { - Z_OOPS(Z_SYSCALL_OBJ_NEVER_INIT(msgq, K_OBJ_MSGQ)); + K_OOPS(K_SYSCALL_OBJ_NEVER_INIT(msgq, K_OBJ_MSGQ)); return z_impl_k_msgq_alloc_init(msgq, msg_size, max_msgs); } @@ -179,8 +187,8 @@ int z_impl_k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout static inline int z_vrfy_k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout) { - Z_OOPS(Z_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(data, msgq->msg_size)); + K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); + K_OOPS(K_SYSCALL_MEMORY_READ(data, msgq->msg_size)); return z_impl_k_msgq_put(msgq, data, timeout); } @@ -198,8 +206,8 @@ void z_impl_k_msgq_get_attrs(struct k_msgq *msgq, struct k_msgq_attrs *attrs) static inline void z_vrfy_k_msgq_get_attrs(struct k_msgq *msgq, struct k_msgq_attrs *attrs) { - Z_OOPS(Z_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(attrs, sizeof(struct k_msgq_attrs))); + K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(attrs, sizeof(struct k_msgq_attrs))); z_impl_k_msgq_get_attrs(msgq, attrs); } #include @@ -277,8 +285,8 @@ int z_impl_k_msgq_get(struct k_msgq *msgq, void *data, k_timeout_t timeout) static inline int z_vrfy_k_msgq_get(struct k_msgq *msgq, void *data, k_timeout_t timeout) { - Z_OOPS(Z_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(data, msgq->msg_size)); + K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(data, msgq->msg_size)); return z_impl_k_msgq_get(msgq, data, timeout); } @@ -311,8 +319,8 @@ int z_impl_k_msgq_peek(struct k_msgq *msgq, void *data) #ifdef CONFIG_USERSPACE static inline int z_vrfy_k_msgq_peek(struct k_msgq *msgq, void *data) { - Z_OOPS(Z_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(data, msgq->msg_size)); + K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(data, msgq->msg_size)); return z_impl_k_msgq_peek(msgq, data); } @@ -357,8 +365,8 @@ int z_impl_k_msgq_peek_at(struct k_msgq *msgq, void *data, uint32_t idx) #ifdef CONFIG_USERSPACE static inline int z_vrfy_k_msgq_peek_at(struct k_msgq *msgq, void *data, uint32_t idx) { - Z_OOPS(Z_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(data, msgq->msg_size)); + K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(data, msgq->msg_size)); return z_impl_k_msgq_peek_at(msgq, data, idx); } @@ -389,23 +397,45 @@ void z_impl_k_msgq_purge(struct k_msgq *msgq) #ifdef CONFIG_USERSPACE static inline void z_vrfy_k_msgq_purge(struct k_msgq *msgq) { - Z_OOPS(Z_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); + K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); z_impl_k_msgq_purge(msgq); } #include static inline uint32_t z_vrfy_k_msgq_num_free_get(struct k_msgq *msgq) { - Z_OOPS(Z_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); + K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); return z_impl_k_msgq_num_free_get(msgq); } #include static inline uint32_t z_vrfy_k_msgq_num_used_get(struct k_msgq *msgq) { - Z_OOPS(Z_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); + K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); return z_impl_k_msgq_num_used_get(msgq); } #include #endif + +#ifdef CONFIG_OBJ_CORE_MSGQ +static int init_msgq_obj_core_list(void) +{ + /* Initialize msgq object type */ + + z_obj_type_init(&obj_type_msgq, K_OBJ_TYPE_MSGQ_ID, + offsetof(struct k_msgq, obj_core)); + + /* Initialize and link statically defined message queues */ + + STRUCT_SECTION_FOREACH(k_msgq, msgq) { + k_obj_core_init_and_link(K_OBJ_CORE(msgq), &obj_type_msgq); + } + + return 0; +}; + +SYS_INIT(init_msgq_obj_core_list, PRE_KERNEL_1, + CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); + +#endif diff --git a/kernel/mutex.c b/kernel/mutex.c index 32c889bb237..622422aef7b 100644 --- a/kernel/mutex.c +++ b/kernel/mutex.c @@ -30,13 +30,14 @@ #include #include #include -#include +#include #include #include -#include +#include #include #include #include +#include LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); /* We use a global spinlock here because some of the synchronization @@ -46,6 +47,10 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); */ static struct k_spinlock lock; +#ifdef CONFIG_OBJ_CORE_MUTEX +static struct k_obj_type obj_type_mutex; +#endif + int z_impl_k_mutex_init(struct k_mutex *mutex) { mutex->owner = NULL; @@ -53,7 +58,11 @@ int z_impl_k_mutex_init(struct k_mutex *mutex) z_waitq_init(&mutex->wait_q); - z_object_init(mutex); + k_object_init(mutex); + +#ifdef CONFIG_OBJ_CORE_MUTEX + k_obj_core_init_and_link(K_OBJ_CORE(mutex), &obj_type_mutex); +#endif SYS_PORT_TRACING_OBJ_INIT(k_mutex, mutex, 0); @@ -63,7 +72,7 @@ int z_impl_k_mutex_init(struct k_mutex *mutex) #ifdef CONFIG_USERSPACE static inline int z_vrfy_k_mutex_init(struct k_mutex *mutex) { - Z_OOPS(Z_SYSCALL_OBJ_INIT(mutex, K_OBJ_MUTEX)); + K_OOPS(K_SYSCALL_OBJ_INIT(mutex, K_OBJ_MUTEX)); return z_impl_k_mutex_init(mutex); } #include @@ -187,12 +196,13 @@ int z_impl_k_mutex_lock(struct k_mutex *mutex, k_timeout_t timeout) return -EAGAIN; } +EXPORT_SYSCALL(k_mutex_lock); #ifdef CONFIG_USERSPACE static inline int z_vrfy_k_mutex_lock(struct k_mutex *mutex, k_timeout_t timeout) { - Z_OOPS(Z_SYSCALL_OBJ(mutex, K_OBJ_MUTEX)); + K_OOPS(K_SYSCALL_OBJ(mutex, K_OBJ_MUTEX)); return z_impl_k_mutex_lock(mutex, timeout); } #include @@ -272,12 +282,34 @@ int z_impl_k_mutex_unlock(struct k_mutex *mutex) return 0; } +EXPORT_SYSCALL(k_mutex_unlock); #ifdef CONFIG_USERSPACE static inline int z_vrfy_k_mutex_unlock(struct k_mutex *mutex) { - Z_OOPS(Z_SYSCALL_OBJ(mutex, K_OBJ_MUTEX)); + K_OOPS(K_SYSCALL_OBJ(mutex, K_OBJ_MUTEX)); return z_impl_k_mutex_unlock(mutex); } #include #endif + +#ifdef CONFIG_OBJ_CORE_MUTEX +static int init_mutex_obj_core_list(void) +{ + /* Initialize mutex object type */ + + z_obj_type_init(&obj_type_mutex, K_OBJ_TYPE_MUTEX_ID, + offsetof(struct k_mutex, obj_core)); + + /* Initialize and link statically defined mutexs */ + + STRUCT_SECTION_FOREACH(k_mutex, mutex) { + k_obj_core_init_and_link(K_OBJ_CORE(mutex), &obj_type_mutex); + } + + return 0; +} + +SYS_INIT(init_mutex_obj_core_list, PRE_KERNEL_1, + CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); +#endif diff --git a/kernel/obj_core.c b/kernel/obj_core.c new file mode 100644 index 00000000000..8ac4f737d2d --- /dev/null +++ b/kernel/obj_core.c @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2023, Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +static struct k_spinlock lock; + +sys_slist_t z_obj_type_list = SYS_SLIST_STATIC_INIT(&z_obj_type_list); + +struct k_obj_type *z_obj_type_init(struct k_obj_type *type, + uint32_t id, size_t off) +{ + sys_slist_init(&type->list); + sys_slist_append(&z_obj_type_list, &type->node); + type->id = id; + type->obj_core_offset = off; + + return type; +} + +void k_obj_core_init(struct k_obj_core *obj_core, struct k_obj_type *type) +{ + obj_core->node.next = NULL; + obj_core->type = type; +#ifdef CONFIG_OBJ_CORE_STATS + obj_core->stats = NULL; +#endif +} + +void k_obj_core_link(struct k_obj_core *obj_core) +{ + k_spinlock_key_t key = k_spin_lock(&lock); + + sys_slist_append(&obj_core->type->list, &obj_core->node); + + k_spin_unlock(&lock, key); +} + +void k_obj_core_init_and_link(struct k_obj_core *obj_core, + struct k_obj_type *type) +{ + k_obj_core_init(obj_core, type); + k_obj_core_link(obj_core); +} + +void k_obj_core_unlink(struct k_obj_core *obj_core) +{ + k_spinlock_key_t key = k_spin_lock(&lock); + + sys_slist_find_and_remove(&obj_core->type->list, &obj_core->node); + + k_spin_unlock(&lock, key); +} + +struct k_obj_type *k_obj_type_find(uint32_t type_id) +{ + struct k_obj_type *type; + struct k_obj_type *rv = NULL; + sys_snode_t *node; + + k_spinlock_key_t key = k_spin_lock(&lock); + + SYS_SLIST_FOR_EACH_NODE(&z_obj_type_list, node) { + type = CONTAINER_OF(node, struct k_obj_type, node); + if (type->id == type_id) { + rv = type; + break; + } + } + + k_spin_unlock(&lock, key); + + return rv; +} + +int k_obj_type_walk_locked(struct k_obj_type *type, + int (*func)(struct k_obj_core *, void *), + void *data) +{ + k_spinlock_key_t key; + struct k_obj_core *obj_core; + sys_snode_t *node; + int status = 0; + + key = k_spin_lock(&lock); + + SYS_SLIST_FOR_EACH_NODE(&type->list, node) { + obj_core = CONTAINER_OF(node, struct k_obj_core, node); + status = func(obj_core, data); + if (status != 0) { + break; + } + } + + k_spin_unlock(&lock, key); + + return status; +} + +int k_obj_type_walk_unlocked(struct k_obj_type *type, + int (*func)(struct k_obj_core *, void *), + void *data) +{ + struct k_obj_core *obj_core; + sys_snode_t *node; + sys_snode_t *next; + int status = 0; + + SYS_SLIST_FOR_EACH_NODE_SAFE(&type->list, node, next) { + obj_core = CONTAINER_OF(node, struct k_obj_core, node); + status = func(obj_core, data); + if (status != 0) { + break; + } + } + + return status; +} + +#ifdef CONFIG_OBJ_CORE_STATS +int k_obj_core_stats_register(struct k_obj_core *obj_core, void *stats, + size_t stats_len) +{ + k_spinlock_key_t key = k_spin_lock(&lock); + + if (obj_core->type->stats_desc == NULL) { + + /* Object type not configured for statistics. */ + + k_spin_unlock(&lock, key); + return -ENOTSUP; + } + + if (obj_core->type->stats_desc->raw_size != stats_len) { + + /* Buffer size mismatch */ + + k_spin_unlock(&lock, key); + return -EINVAL; + } + + obj_core->stats = stats; + k_spin_unlock(&lock, key); + + return 0; +} + +int k_obj_core_stats_deregister(struct k_obj_core *obj_core) +{ + k_spinlock_key_t key = k_spin_lock(&lock); + + if (obj_core->type->stats_desc == NULL) { + + /* Object type not configured for statistics. */ + + k_spin_unlock(&lock, key); + return -ENOTSUP; + } + + obj_core->stats = NULL; + k_spin_unlock(&lock, key); + + return 0; +} + +int k_obj_core_stats_raw(struct k_obj_core *obj_core, void *stats, + size_t stats_len) +{ + int rv; + struct k_obj_core_stats_desc *desc; + + k_spinlock_key_t key = k_spin_lock(&lock); + + desc = obj_core->type->stats_desc; + if ((desc == NULL) || (desc->raw == NULL)) { + + /* The object type is not configured for this operation */ + + k_spin_unlock(&lock, key); + return -ENOTSUP; + } + + if ((desc->raw_size != stats_len) || (obj_core->stats == NULL)) { + + /* + * Either the size of the stats buffer is wrong or + * the kernel object was not registered for statistics. + */ + + k_spin_unlock(&lock, key); + return -EINVAL; + } + + rv = desc->raw(obj_core, stats); + k_spin_unlock(&lock, key); + + return rv; +} + +int k_obj_core_stats_query(struct k_obj_core *obj_core, void *stats, + size_t stats_len) +{ + int rv; + struct k_obj_core_stats_desc *desc; + + k_spinlock_key_t key = k_spin_lock(&lock); + + desc = obj_core->type->stats_desc; + if ((desc == NULL) || (desc->query == NULL)) { + + /* The object type is not configured for this operation */ + + k_spin_unlock(&lock, key); + return -ENOTSUP; + } + + if ((desc->query_size != stats_len) || (obj_core->stats == NULL)) { + + /* + * Either the size of the stats buffer is wrong or + * the kernel object was not registered for statistics. + */ + + k_spin_unlock(&lock, key); + return -EINVAL; + } + + rv = desc->query(obj_core, stats); + k_spin_unlock(&lock, key); + + return rv; +} + +int k_obj_core_stats_reset(struct k_obj_core *obj_core) +{ + int rv; + struct k_obj_core_stats_desc *desc; + + k_spinlock_key_t key = k_spin_lock(&lock); + + desc = obj_core->type->stats_desc; + if ((desc == NULL) || (desc->reset == NULL)) { + + /* The object type is not configured for this operation */ + + k_spin_unlock(&lock, key); + return -ENOTSUP; + } + + if (obj_core->stats == NULL) { + + /* This kernel object is not configured for statistics */ + + k_spin_unlock(&lock, key); + return -EINVAL; + } + + rv = desc->reset(obj_core); + k_spin_unlock(&lock, key); + + return rv; +} + +int k_obj_core_stats_disable(struct k_obj_core *obj_core) +{ + int rv; + struct k_obj_core_stats_desc *desc; + + k_spinlock_key_t key = k_spin_lock(&lock); + + desc = obj_core->type->stats_desc; + if ((desc == NULL) || (desc->disable == NULL)) { + + /* The object type is not configured for this operation */ + + k_spin_unlock(&lock, key); + return -ENOTSUP; + } + + if (obj_core->stats == NULL) { + + /* This kernel object is not configured for statistics */ + + k_spin_unlock(&lock, key); + return -EINVAL; + } + + rv = desc->disable(obj_core); + k_spin_unlock(&lock, key); + + return rv; +} + +int k_obj_core_stats_enable(struct k_obj_core *obj_core) +{ + int rv; + struct k_obj_core_stats_desc *desc; + + k_spinlock_key_t key = k_spin_lock(&lock); + + desc = obj_core->type->stats_desc; + if ((desc == NULL) || (desc->enable == NULL)) { + + /* The object type is not configured for this operation */ + + k_spin_unlock(&lock, key); + return -ENOTSUP; + } + + if (obj_core->stats == NULL) { + + /* This kernel object is not configured for statistics */ + + k_spin_unlock(&lock, key); + return -EINVAL; + } + + rv = desc->enable(obj_core); + k_spin_unlock(&lock, key); + + return rv; +} +#endif diff --git a/kernel/paging/statistics.c b/kernel/paging/statistics.c index f1017687f3e..e8972738135 100644 --- a/kernel/paging/statistics.c +++ b/kernel/paging/statistics.c @@ -6,9 +6,9 @@ #include #include -#include +#include #include -#include +#include extern struct k_mem_paging_stats_t paging_stats; @@ -102,7 +102,7 @@ void z_impl_k_mem_paging_stats_get(struct k_mem_paging_stats_t *stats) static inline void z_vrfy_k_mem_paging_stats_get(struct k_mem_paging_stats_t *stats) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(stats, sizeof(*stats))); + K_OOPS(K_SYSCALL_MEMORY_WRITE(stats, sizeof(*stats))); z_impl_k_mem_paging_stats_get(stats); } #include @@ -125,8 +125,8 @@ static inline void z_vrfy_k_mem_paging_thread_stats_get(struct k_thread *thread, struct k_mem_paging_stats_t *stats) { - Z_OOPS(Z_SYSCALL_OBJ(thread, K_OBJ_THREAD)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(stats, sizeof(*stats))); + K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(stats, sizeof(*stats))); z_impl_k_mem_paging_thread_stats_get(thread, stats); } #include @@ -224,7 +224,7 @@ static inline void z_vrfy_k_mem_paging_histogram_eviction_get( struct k_mem_paging_histogram_t *hist) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(hist, sizeof(*hist))); + K_OOPS(K_SYSCALL_MEMORY_WRITE(hist, sizeof(*hist))); z_impl_k_mem_paging_histogram_eviction_get(hist); } #include @@ -233,7 +233,7 @@ static inline void z_vrfy_k_mem_paging_histogram_backing_store_page_in_get( struct k_mem_paging_histogram_t *hist) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(hist, sizeof(*hist))); + K_OOPS(K_SYSCALL_MEMORY_WRITE(hist, sizeof(*hist))); z_impl_k_mem_paging_histogram_backing_store_page_in_get(hist); } #include @@ -242,7 +242,7 @@ static inline void z_vrfy_k_mem_paging_histogram_backing_store_page_out_get( struct k_mem_paging_histogram_t *hist) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(hist, sizeof(*hist))); + K_OOPS(K_SYSCALL_MEMORY_WRITE(hist, sizeof(*hist))); z_impl_k_mem_paging_histogram_backing_store_page_out_get(hist); } #include diff --git a/kernel/pipes.c b/kernel/pipes.c index 0a899856c02..3fa1c72036d 100644 --- a/kernel/pipes.c +++ b/kernel/pipes.c @@ -15,9 +15,9 @@ #include #include -#include +#include #include -#include +#include #include #include @@ -31,6 +31,10 @@ static int pipe_get_internal(k_spinlock_key_t key, struct k_pipe *pipe, void *data, size_t bytes_to_read, size_t *bytes_read, size_t min_xfer, k_timeout_t timeout); +#ifdef CONFIG_OBJ_CORE_PIPE +static struct k_obj_type obj_type_pipe; +#endif + void k_pipe_init(struct k_pipe *pipe, unsigned char *buffer, size_t size) { @@ -49,7 +53,11 @@ void k_pipe_init(struct k_pipe *pipe, unsigned char *buffer, size_t size) #if defined(CONFIG_POLL) sys_dlist_init(&pipe->poll_events); #endif - z_object_init(pipe); + k_object_init(pipe); + +#ifdef CONFIG_OBJ_CORE_PIPE + k_obj_core_init_and_link(K_OBJ_CORE(pipe), &obj_type_pipe); +#endif } int z_impl_k_pipe_alloc_init(struct k_pipe *pipe, size_t size) @@ -81,7 +89,7 @@ int z_impl_k_pipe_alloc_init(struct k_pipe *pipe, size_t size) #ifdef CONFIG_USERSPACE static inline int z_vrfy_k_pipe_alloc_init(struct k_pipe *pipe, size_t size) { - Z_OOPS(Z_SYSCALL_OBJ_NEVER_INIT(pipe, K_OBJ_PIPE)); + K_OOPS(K_SYSCALL_OBJ_NEVER_INIT(pipe, K_OBJ_PIPE)); return z_impl_k_pipe_alloc_init(pipe, size); } @@ -114,7 +122,7 @@ void z_impl_k_pipe_flush(struct k_pipe *pipe) #ifdef CONFIG_USERSPACE void z_vrfy_k_pipe_flush(struct k_pipe *pipe) { - Z_OOPS(Z_SYSCALL_OBJ(pipe, K_OBJ_PIPE)); + K_OOPS(K_SYSCALL_OBJ(pipe, K_OBJ_PIPE)); z_impl_k_pipe_flush(pipe); } @@ -142,7 +150,7 @@ void z_impl_k_pipe_buffer_flush(struct k_pipe *pipe) #ifdef CONFIG_USERSPACE void z_vrfy_k_pipe_buffer_flush(struct k_pipe *pipe) { - Z_OOPS(Z_SYSCALL_OBJ(pipe, K_OBJ_PIPE)); + K_OOPS(K_SYSCALL_OBJ(pipe, K_OBJ_PIPE)); z_impl_k_pipe_buffer_flush(pipe); } @@ -509,9 +517,9 @@ int z_vrfy_k_pipe_put(struct k_pipe *pipe, void *data, size_t bytes_to_write, size_t *bytes_written, size_t min_xfer, k_timeout_t timeout) { - Z_OOPS(Z_SYSCALL_OBJ(pipe, K_OBJ_PIPE)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(bytes_written, sizeof(*bytes_written))); - Z_OOPS(Z_SYSCALL_MEMORY_READ((void *)data, bytes_to_write)); + K_OOPS(K_SYSCALL_OBJ(pipe, K_OBJ_PIPE)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(bytes_written, sizeof(*bytes_written))); + K_OOPS(K_SYSCALL_MEMORY_READ((void *)data, bytes_to_write)); return z_impl_k_pipe_put((struct k_pipe *)pipe, (void *)data, bytes_to_write, bytes_written, min_xfer, @@ -717,9 +725,9 @@ int z_impl_k_pipe_get(struct k_pipe *pipe, void *data, size_t bytes_to_read, int z_vrfy_k_pipe_get(struct k_pipe *pipe, void *data, size_t bytes_to_read, size_t *bytes_read, size_t min_xfer, k_timeout_t timeout) { - Z_OOPS(Z_SYSCALL_OBJ(pipe, K_OBJ_PIPE)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(bytes_read, sizeof(*bytes_read))); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE((void *)data, bytes_to_read)); + K_OOPS(K_SYSCALL_OBJ(pipe, K_OBJ_PIPE)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(bytes_read, sizeof(*bytes_read))); + K_OOPS(K_SYSCALL_MEMORY_WRITE((void *)data, bytes_to_read)); return z_impl_k_pipe_get((struct k_pipe *)pipe, (void *)data, bytes_to_read, bytes_read, min_xfer, @@ -758,7 +766,7 @@ size_t z_impl_k_pipe_read_avail(struct k_pipe *pipe) #ifdef CONFIG_USERSPACE size_t z_vrfy_k_pipe_read_avail(struct k_pipe *pipe) { - Z_OOPS(Z_SYSCALL_OBJ(pipe, K_OBJ_PIPE)); + K_OOPS(K_SYSCALL_OBJ(pipe, K_OBJ_PIPE)); return z_impl_k_pipe_read_avail(pipe); } @@ -795,9 +803,30 @@ size_t z_impl_k_pipe_write_avail(struct k_pipe *pipe) #ifdef CONFIG_USERSPACE size_t z_vrfy_k_pipe_write_avail(struct k_pipe *pipe) { - Z_OOPS(Z_SYSCALL_OBJ(pipe, K_OBJ_PIPE)); + K_OOPS(K_SYSCALL_OBJ(pipe, K_OBJ_PIPE)); return z_impl_k_pipe_write_avail(pipe); } #include #endif + +#ifdef CONFIG_OBJ_CORE_PIPE +static int init_pipe_obj_core_list(void) +{ + /* Initialize pipe object type */ + + z_obj_type_init(&obj_type_pipe, K_OBJ_TYPE_PIPE_ID, + offsetof(struct k_pipe, obj_core)); + + /* Initialize and link statically defined pipes */ + + STRUCT_SECTION_FOREACH(k_pipe, pipe) { + k_obj_core_init_and_link(K_OBJ_CORE(pipe), &obj_type_pipe); + } + + return 0; +} + +SYS_INIT(init_pipe_obj_core_list, PRE_KERNEL_1, + CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); +#endif diff --git a/kernel/poll.c b/kernel/poll.c index d3b313f04bd..d983af7e20e 100644 --- a/kernel/poll.c +++ b/kernel/poll.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2017 Wind River Systems, Inc. + * Copyright (c) 2023 Arm Limited (or its affiliates). All rights reserved. * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,9 +18,9 @@ #include #include #include -#include +#include #include -#include +#include #include #include #include @@ -271,10 +272,6 @@ static int signal_poller(struct k_poll_event *event, uint32_t state) return 0; } - if (z_is_thread_timeout_expired(thread)) { - return -EAGAIN; - } - z_unpend_thread(thread); arch_thread_return_value_set(thread, state == K_POLL_STATE_CANCELLED ? -EINTR : 0); @@ -367,11 +364,11 @@ static inline int z_vrfy_k_poll(struct k_poll_event *events, /* Validate the events buffer and make a copy of it in an * allocated kernel-side buffer. */ - if (Z_SYSCALL_VERIFY(num_events >= 0)) { + if (K_SYSCALL_VERIFY(num_events >= 0)) { ret = -EINVAL; goto out; } - if (Z_SYSCALL_VERIFY_MSG(!u32_mul_overflow(num_events, + if (K_SYSCALL_VERIFY_MSG(!u32_mul_overflow(num_events, sizeof(struct k_poll_event), &bounds), "num_events too large")) { @@ -385,7 +382,7 @@ static inline int z_vrfy_k_poll(struct k_poll_event *events, } key = k_spin_lock(&lock); - if (Z_SYSCALL_MEMORY_WRITE(events, bounds)) { + if (K_SYSCALL_MEMORY_WRITE(events, bounds)) { k_spin_unlock(&lock, key); goto oops_free; } @@ -396,7 +393,7 @@ static inline int z_vrfy_k_poll(struct k_poll_event *events, for (int i = 0; i < num_events; i++) { struct k_poll_event *e = &events_copy[i]; - if (Z_SYSCALL_VERIFY(e->mode == K_POLL_MODE_NOTIFY_ONLY)) { + if (K_SYSCALL_VERIFY(e->mode == K_POLL_MODE_NOTIFY_ONLY)) { ret = -EINVAL; goto out_free; } @@ -405,20 +402,20 @@ static inline int z_vrfy_k_poll(struct k_poll_event *events, case K_POLL_TYPE_IGNORE: break; case K_POLL_TYPE_SIGNAL: - Z_OOPS(Z_SYSCALL_OBJ(e->signal, K_OBJ_POLL_SIGNAL)); + K_OOPS(K_SYSCALL_OBJ(e->signal, K_OBJ_POLL_SIGNAL)); break; case K_POLL_TYPE_SEM_AVAILABLE: - Z_OOPS(Z_SYSCALL_OBJ(e->sem, K_OBJ_SEM)); + K_OOPS(K_SYSCALL_OBJ(e->sem, K_OBJ_SEM)); break; case K_POLL_TYPE_DATA_AVAILABLE: - Z_OOPS(Z_SYSCALL_OBJ(e->queue, K_OBJ_QUEUE)); + K_OOPS(K_SYSCALL_OBJ(e->queue, K_OBJ_QUEUE)); break; case K_POLL_TYPE_MSGQ_DATA_AVAILABLE: - Z_OOPS(Z_SYSCALL_OBJ(e->msgq, K_OBJ_MSGQ)); + K_OOPS(K_SYSCALL_OBJ(e->msgq, K_OBJ_MSGQ)); break; #ifdef CONFIG_PIPES case K_POLL_TYPE_PIPE_DATA_AVAILABLE: - Z_OOPS(Z_SYSCALL_OBJ(e->pipe, K_OBJ_PIPE)); + K_OOPS(K_SYSCALL_OBJ(e->pipe, K_OBJ_PIPE)); break; #endif default: @@ -435,7 +432,7 @@ static inline int z_vrfy_k_poll(struct k_poll_event *events, return ret; oops_free: k_free(events_copy); - Z_OOPS(1); + K_OOPS(1); } #include #endif @@ -470,11 +467,14 @@ static int signal_poll_event(struct k_poll_event *event, uint32_t state) void z_handle_obj_poll_events(sys_dlist_t *events, uint32_t state) { struct k_poll_event *poll_event; + k_spinlock_key_t key = k_spin_lock(&lock); poll_event = (struct k_poll_event *)sys_dlist_get(events); if (poll_event != NULL) { (void) signal_poll_event(poll_event, state); } + + k_spin_unlock(&lock, key); } void z_impl_k_poll_signal_init(struct k_poll_signal *sig) @@ -482,7 +482,7 @@ void z_impl_k_poll_signal_init(struct k_poll_signal *sig) sys_dlist_init(&sig->poll_events); sig->signaled = 0U; /* signal->result is left uninitialized */ - z_object_init(sig); + k_object_init(sig); SYS_PORT_TRACING_FUNC(k_poll_api, signal_init, sig); } @@ -490,7 +490,7 @@ void z_impl_k_poll_signal_init(struct k_poll_signal *sig) #ifdef CONFIG_USERSPACE static inline void z_vrfy_k_poll_signal_init(struct k_poll_signal *sig) { - Z_OOPS(Z_SYSCALL_OBJ_INIT(sig, K_OBJ_POLL_SIGNAL)); + K_OOPS(K_SYSCALL_OBJ_INIT(sig, K_OBJ_POLL_SIGNAL)); z_impl_k_poll_signal_init(sig); } #include @@ -516,9 +516,9 @@ void z_impl_k_poll_signal_check(struct k_poll_signal *sig, void z_vrfy_k_poll_signal_check(struct k_poll_signal *sig, unsigned int *signaled, int *result) { - Z_OOPS(Z_SYSCALL_OBJ(sig, K_OBJ_POLL_SIGNAL)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(signaled, sizeof(unsigned int))); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(result, sizeof(int))); + K_OOPS(K_SYSCALL_OBJ(sig, K_OBJ_POLL_SIGNAL)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(signaled, sizeof(unsigned int))); + K_OOPS(K_SYSCALL_MEMORY_WRITE(result, sizeof(int))); z_impl_k_poll_signal_check(sig, signaled, result); } #include @@ -553,14 +553,14 @@ int z_impl_k_poll_signal_raise(struct k_poll_signal *sig, int result) static inline int z_vrfy_k_poll_signal_raise(struct k_poll_signal *sig, int result) { - Z_OOPS(Z_SYSCALL_OBJ(sig, K_OBJ_POLL_SIGNAL)); + K_OOPS(K_SYSCALL_OBJ(sig, K_OBJ_POLL_SIGNAL)); return z_impl_k_poll_signal_raise(sig, result); } #include static inline void z_vrfy_k_poll_signal_reset(struct k_poll_signal *sig) { - Z_OOPS(Z_SYSCALL_OBJ(sig, K_OBJ_POLL_SIGNAL)); + K_OOPS(K_SYSCALL_OBJ(sig, K_OBJ_POLL_SIGNAL)); z_impl_k_poll_signal_reset(sig); } #include diff --git a/kernel/queue.c b/kernel/queue.c index 342ee89566e..04aaa149d97 100644 --- a/kernel/queue.c +++ b/kernel/queue.c @@ -15,10 +15,10 @@ #include #include -#include +#include #include #include -#include +#include #include #include @@ -66,13 +66,13 @@ void z_impl_k_queue_init(struct k_queue *queue) SYS_PORT_TRACING_OBJ_INIT(k_queue, queue); - z_object_init(queue); + k_object_init(queue); } #ifdef CONFIG_USERSPACE static inline void z_vrfy_k_queue_init(struct k_queue *queue) { - Z_OOPS(Z_SYSCALL_OBJ_NEVER_INIT(queue, K_OBJ_QUEUE)); + K_OOPS(K_SYSCALL_OBJ_NEVER_INIT(queue, K_OBJ_QUEUE)); z_impl_k_queue_init(queue); } #include @@ -88,6 +88,9 @@ static inline void handle_poll_events(struct k_queue *queue, uint32_t state) { #ifdef CONFIG_POLL z_handle_obj_poll_events(&queue->poll_events, state); +#else + ARG_UNUSED(queue); + ARG_UNUSED(state); #endif } @@ -111,7 +114,7 @@ void z_impl_k_queue_cancel_wait(struct k_queue *queue) #ifdef CONFIG_USERSPACE static inline void z_vrfy_k_queue_cancel_wait(struct k_queue *queue) { - Z_OOPS(Z_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); + K_OOPS(K_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); z_impl_k_queue_cancel_wait(queue); } #include @@ -214,7 +217,7 @@ int32_t z_impl_k_queue_alloc_append(struct k_queue *queue, void *data) static inline int32_t z_vrfy_k_queue_alloc_append(struct k_queue *queue, void *data) { - Z_OOPS(Z_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); + K_OOPS(K_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); return z_impl_k_queue_alloc_append(queue, data); } #include @@ -235,7 +238,7 @@ int32_t z_impl_k_queue_alloc_prepend(struct k_queue *queue, void *data) static inline int32_t z_vrfy_k_queue_alloc_prepend(struct k_queue *queue, void *data) { - Z_OOPS(Z_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); + K_OOPS(K_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); return z_impl_k_queue_alloc_prepend(queue, data); } #include @@ -402,30 +405,76 @@ void *z_impl_k_queue_peek_tail(struct k_queue *queue) static inline void *z_vrfy_k_queue_get(struct k_queue *queue, k_timeout_t timeout) { - Z_OOPS(Z_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); + K_OOPS(K_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); return z_impl_k_queue_get(queue, timeout); } #include static inline int z_vrfy_k_queue_is_empty(struct k_queue *queue) { - Z_OOPS(Z_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); + K_OOPS(K_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); return z_impl_k_queue_is_empty(queue); } #include static inline void *z_vrfy_k_queue_peek_head(struct k_queue *queue) { - Z_OOPS(Z_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); + K_OOPS(K_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); return z_impl_k_queue_peek_head(queue); } #include static inline void *z_vrfy_k_queue_peek_tail(struct k_queue *queue) { - Z_OOPS(Z_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); + K_OOPS(K_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); return z_impl_k_queue_peek_tail(queue); } #include #endif /* CONFIG_USERSPACE */ + +#ifdef CONFIG_OBJ_CORE_FIFO +struct k_obj_type _obj_type_fifo; + +static int init_fifo_obj_core_list(void) +{ + /* Initialize fifo object type */ + + z_obj_type_init(&_obj_type_fifo, K_OBJ_TYPE_FIFO_ID, + offsetof(struct k_fifo, obj_core)); + + /* Initialize and link statically defined fifos */ + + STRUCT_SECTION_FOREACH(k_fifo, fifo) { + k_obj_core_init_and_link(K_OBJ_CORE(fifo), &_obj_type_fifo); + } + + return 0; +} + +SYS_INIT(init_fifo_obj_core_list, PRE_KERNEL_1, + CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); +#endif + +#ifdef CONFIG_OBJ_CORE_LIFO +struct k_obj_type _obj_type_lifo; + +static int init_lifo_obj_core_list(void) +{ + /* Initialize lifo object type */ + + z_obj_type_init(&_obj_type_lifo, K_OBJ_TYPE_LIFO_ID, + offsetof(struct k_lifo, obj_core)); + + /* Initialize and link statically defined lifo */ + + STRUCT_SECTION_FOREACH(k_lifo, lifo) { + k_obj_core_init_and_link(K_OBJ_CORE(lifo), &_obj_type_lifo); + } + + return 0; +} + +SYS_INIT(init_lifo_obj_core_list, PRE_KERNEL_1, + CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); +#endif diff --git a/kernel/sched.c b/kernel/sched.c index fcd77c69eb7..7dd782c9490 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -6,11 +6,11 @@ #include #include #include -#include -#include +#include +#include #include #include -#include +#include #include #include #include @@ -57,7 +57,8 @@ static ALWAYS_INLINE void z_priq_mq_remove(struct _priq_mq *pq, struct k_spinlock sched_spinlock; static void update_cache(int preempt_ok); -static void end_thread(struct k_thread *thread); +static void halt_thread(struct k_thread *thread, uint8_t new_state); +static void add_to_waitq_locked(struct k_thread *thread, _wait_q_t *wait_q); static inline int is_preempt(struct k_thread *thread) @@ -77,6 +78,7 @@ static inline int is_metairq(struct k_thread *thread) return (thread->base.prio - K_HIGHEST_THREAD_PRIO) < CONFIG_NUM_METAIRQ_PRIORITIES; #else + ARG_UNUSED(thread); return 0; #endif } @@ -219,6 +221,7 @@ static ALWAYS_INLINE void *thread_runq(struct k_thread *thread) return &_kernel.cpus[cpu].ready_q.runq; #else + ARG_UNUSED(thread); return &_kernel.ready_q.runq; #endif } @@ -311,17 +314,32 @@ void z_requeue_current(struct k_thread *curr) signal_pending_ipi(); } +/* Return true if the thread is aborting, else false */ static inline bool is_aborting(struct k_thread *thread) { return (thread->base.thread_state & _THREAD_ABORTING) != 0U; } + +/* Return true if the thread is aborting or suspending, else false */ +static inline bool is_halting(struct k_thread *thread) +{ + return (thread->base.thread_state & + (_THREAD_ABORTING | _THREAD_SUSPENDING)) != 0U; +} #endif +/* Clear the halting bits (_THREAD_ABORTING and _THREAD_SUSPENDING) */ +static inline void clear_halting(struct k_thread *thread) +{ + thread->base.thread_state &= ~(_THREAD_ABORTING | _THREAD_SUSPENDING); +} + static ALWAYS_INLINE struct k_thread *next_up(void) { #ifdef CONFIG_SMP - if (is_aborting(_current)) { - end_thread(_current); + if (is_halting(_current)) { + halt_thread(_current, is_aborting(_current) ? + _THREAD_DEAD : _THREAD_SUSPENDED); } #endif @@ -443,6 +461,8 @@ static inline int slice_time(struct k_thread *thread) if (thread->base.slice_ticks != 0) { ret = thread->base.slice_ticks; } +#else + ARG_UNUSED(thread); #endif return ret; } @@ -558,6 +578,8 @@ static void update_metairq_preempt(struct k_thread *thread) /* Returning from existing preemption */ _current_cpu->metairq_preempted = NULL; } +#else + ARG_UNUSED(thread); #endif } @@ -607,6 +629,7 @@ static bool thread_active_elsewhere(struct k_thread *thread) } } #endif + ARG_UNUSED(thread); return false; } @@ -658,31 +681,109 @@ void z_sched_start(struct k_thread *thread) z_reschedule(&sched_spinlock, key); } +/** + * @brief Halt a thread + * + * If the target thread is running on another CPU, flag it as needing to + * abort and send an IPI (if supported) to force a schedule point and wait + * until the target thread is switched out (ISRs will spin to wait and threads + * will block to wait). If the target thread is not running on another CPU, + * then it is safe to act immediately. + * + * Upon entry to this routine, the scheduler lock is already held. It is + * released before this routine returns. + * + * @param thread Thread to suspend or abort + * @param key Current key for sched_spinlock + * @param terminate True if aborting thread, false if suspending thread + */ +static void z_thread_halt(struct k_thread *thread, k_spinlock_key_t key, + bool terminate) +{ +#ifdef CONFIG_SMP + if (is_halting(_current) && arch_is_in_isr()) { + /* Another CPU (in an ISR) or thread is waiting for the + * current thread to halt. Halt it now to help avoid a + * potential deadlock. + */ + halt_thread(_current, + is_aborting(_current) ? _THREAD_DEAD + : _THREAD_SUSPENDED); + } + + bool active = thread_active_elsewhere(thread); + + if (active) { + /* It's running somewhere else, flag and poke */ + thread->base.thread_state |= (terminate ? _THREAD_ABORTING + : _THREAD_SUSPENDING); + + /* We might spin to wait, so a true synchronous IPI is needed + * here, not deferred! + */ +#ifdef CONFIG_SCHED_IPI_SUPPORTED + arch_sched_ipi(); +#endif + } + + if (is_halting(thread) && (thread != _current)) { + if (arch_is_in_isr()) { + /* ISRs can only spin waiting another CPU */ + k_spin_unlock(&sched_spinlock, key); + while (is_halting(thread)) { + } + + /* Now we know it's halting, but not necessarily + * halted (suspended or aborted). Wait for the switch + * to happen! + */ + key = k_spin_lock(&sched_spinlock); + z_sched_switch_spin(thread); + k_spin_unlock(&sched_spinlock, key); + } else if (active) { + /* Threads can wait on a queue */ + add_to_waitq_locked(_current, terminate ? + &thread->join_queue : + &thread->halt_queue); + z_swap(&sched_spinlock, key); + } + return; /* lock has been released */ + } +#endif + halt_thread(thread, terminate ? _THREAD_DEAD : _THREAD_SUSPENDED); + if ((thread == _current) && !arch_is_in_isr()) { + z_swap(&sched_spinlock, key); + __ASSERT(!terminate, "aborted _current back from dead"); + } else { + k_spin_unlock(&sched_spinlock, key); + } +} + void z_impl_k_thread_suspend(struct k_thread *thread) { SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_thread, suspend, thread); (void)z_abort_thread_timeout(thread); - K_SPINLOCK(&sched_spinlock) { - if (z_is_thread_queued(thread)) { - dequeue_thread(thread); - } - z_mark_thread_as_suspended(thread); - update_cache(thread == _current); - } + k_spinlock_key_t key = k_spin_lock(&sched_spinlock); - if (thread == _current) { - z_reschedule_unlocked(); + if ((thread->base.thread_state & _THREAD_SUSPENDED) != 0U) { + + /* The target thread is already suspended. Nothing to do. */ + + k_spin_unlock(&sched_spinlock, key); + return; } + z_thread_halt(thread, key, false); + SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_thread, suspend, thread); } #ifdef CONFIG_USERSPACE static inline void z_vrfy_k_thread_suspend(struct k_thread *thread) { - Z_OOPS(Z_SYSCALL_OBJ(thread, K_OBJ_THREAD)); + K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); z_impl_k_thread_suspend(thread); } #include @@ -711,7 +812,7 @@ void z_impl_k_thread_resume(struct k_thread *thread) #ifdef CONFIG_USERSPACE static inline void z_vrfy_k_thread_resume(struct k_thread *thread) { - Z_OOPS(Z_SYSCALL_OBJ(thread, K_OBJ_THREAD)); + K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); z_impl_k_thread_resume(thread); } #include @@ -791,8 +892,8 @@ ALWAYS_INLINE void z_unpend_thread_no_timeout(struct k_thread *thread) void z_sched_wake_thread(struct k_thread *thread, bool is_timeout) { K_SPINLOCK(&sched_spinlock) { - bool killed = ((thread->base.thread_state & _THREAD_DEAD) || - (thread->base.thread_state & _THREAD_ABORTING)); + bool killed = (thread->base.thread_state & + (_THREAD_DEAD | _THREAD_ABORTING)); #ifdef CONFIG_EVENTS bool do_nothing = thread->no_wake_on_timeout && is_timeout; @@ -1153,6 +1254,8 @@ void *z_get_next_switch_handle(void *interrupted) void z_priq_dumb_remove(sys_dlist_t *pq, struct k_thread *thread) { + ARG_UNUSED(pq); + __ASSERT_NO_MSG(!z_is_idle_thread_object(thread)); sys_dlist_remove(&thread->base.qnode_dlist); @@ -1326,7 +1429,7 @@ int z_impl_k_thread_priority_get(k_tid_t thread) #ifdef CONFIG_USERSPACE static inline int z_vrfy_k_thread_priority_get(k_tid_t thread) { - Z_OOPS(Z_SYSCALL_OBJ(thread, K_OBJ_THREAD)); + K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); return z_impl_k_thread_priority_get(thread); } #include @@ -1349,10 +1452,10 @@ void z_impl_k_thread_priority_set(k_tid_t thread, int prio) #ifdef CONFIG_USERSPACE static inline void z_vrfy_k_thread_priority_set(k_tid_t thread, int prio) { - Z_OOPS(Z_SYSCALL_OBJ(thread, K_OBJ_THREAD)); - Z_OOPS(Z_SYSCALL_VERIFY_MSG(_is_valid_prio(prio, NULL), + K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); + K_OOPS(K_SYSCALL_VERIFY_MSG(_is_valid_prio(prio, NULL), "invalid thread priority %d", prio)); - Z_OOPS(Z_SYSCALL_VERIFY_MSG((int8_t)prio >= thread->base.prio, + K_OOPS(K_SYSCALL_VERIFY_MSG((int8_t)prio >= thread->base.prio, "thread priority may only be downgraded (%d < %d)", prio, thread->base.prio)); @@ -1380,8 +1483,8 @@ static inline void z_vrfy_k_thread_deadline_set(k_tid_t tid, int deadline) { struct k_thread *thread = tid; - Z_OOPS(Z_SYSCALL_OBJ(thread, K_OBJ_THREAD)); - Z_OOPS(Z_SYSCALL_VERIFY_MSG(deadline > 0, + K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); + K_OOPS(K_SYSCALL_VERIFY_MSG(deadline > 0, "invalid thread deadline %d", (int)deadline)); @@ -1574,13 +1677,13 @@ void z_sched_ipi(void) #ifdef CONFIG_USERSPACE static inline void z_vrfy_k_wakeup(k_tid_t thread) { - Z_OOPS(Z_SYSCALL_OBJ(thread, K_OBJ_THREAD)); + K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); z_impl_k_wakeup(thread); } #include #endif -k_tid_t z_impl_z_current_get(void) +k_tid_t z_impl_k_sched_current_thread_query(void) { #ifdef CONFIG_SMP /* In SMP, _current is a field read from _current_cpu, which @@ -1599,11 +1702,11 @@ k_tid_t z_impl_z_current_get(void) } #ifdef CONFIG_USERSPACE -static inline k_tid_t z_vrfy_z_current_get(void) +static inline k_tid_t z_vrfy_k_sched_current_thread_query(void) { - return z_impl_z_current_get(); + return z_impl_k_sched_current_thread_query(); } -#include +#include #endif int z_impl_k_is_preempt_thread(void) @@ -1621,8 +1724,8 @@ static inline int z_vrfy_k_is_preempt_thread(void) #ifdef CONFIG_SCHED_CPU_MASK # ifdef CONFIG_SMP -/* Right now we use a single byte for this mask */ -BUILD_ASSERT(CONFIG_MP_MAX_NUM_CPUS <= 8, "Too many CPUs for mask word"); +/* Right now we use a two byte for this mask */ +BUILD_ASSERT(CONFIG_MP_MAX_NUM_CPUS <= 16, "Too many CPUs for mask word"); # endif @@ -1703,24 +1806,42 @@ static inline void unpend_all(_wait_q_t *wait_q) extern void z_thread_cmsis_status_mask_clear(struct k_thread *thread); #endif -static void end_thread(struct k_thread *thread) +/** + * @brief Dequeues the specified thread + * + * Dequeues the specified thread and move it into the specified new state. + * + * @param thread Identify the thread to halt + * @param new_state New thread state (_THREAD_DEAD or _THREAD_SUSPENDED) + */ +static void halt_thread(struct k_thread *thread, uint8_t new_state) { /* We hold the lock, and the thread is known not to be running * anywhere. */ - if ((thread->base.thread_state & _THREAD_DEAD) == 0U) { - thread->base.thread_state |= _THREAD_DEAD; - thread->base.thread_state &= ~_THREAD_ABORTING; + if ((thread->base.thread_state & new_state) == 0U) { + thread->base.thread_state |= new_state; + clear_halting(thread); if (z_is_thread_queued(thread)) { dequeue_thread(thread); } - if (thread->base.pended_on != NULL) { - unpend_thread_no_timeout(thread); + + if (new_state == _THREAD_DEAD) { + if (thread->base.pended_on != NULL) { + unpend_thread_no_timeout(thread); + } + (void)z_abort_thread_timeout(thread); + unpend_all(&thread->join_queue); } - (void)z_abort_thread_timeout(thread); - unpend_all(&thread->join_queue); +#ifdef CONFIG_SMP + unpend_all(&thread->halt_queue); +#endif update_cache(1); + if (new_state == _THREAD_SUSPENDED) { + return; + } + #if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) arch_float_disable(thread); #endif @@ -1733,11 +1854,18 @@ static void end_thread(struct k_thread *thread) z_thread_cmsis_status_mask_clear(thread); #endif +#ifdef CONFIG_OBJ_CORE_THREAD +#ifdef CONFIG_OBJ_CORE_STATS_THREAD + k_obj_core_stats_deregister(K_OBJ_CORE(thread)); +#endif + k_obj_core_unlink(K_OBJ_CORE(thread)); +#endif + #ifdef CONFIG_USERSPACE z_mem_domain_exit_thread(thread); - z_thread_perms_all_clear(thread); - z_object_uninit(thread->stack_obj); - z_object_uninit(thread); + k_thread_perms_all_clear(thread); + k_object_uninit(thread->stack_obj); + k_object_uninit(thread); #endif } } @@ -1758,53 +1886,7 @@ void z_thread_abort(struct k_thread *thread) return; } -#ifdef CONFIG_SMP - if (is_aborting(thread) && thread == _current && arch_is_in_isr()) { - /* Another CPU is spinning for us, don't deadlock */ - end_thread(thread); - } - - bool active = thread_active_elsewhere(thread); - - if (active) { - /* It's running somewhere else, flag and poke */ - thread->base.thread_state |= _THREAD_ABORTING; - - /* We're going to spin, so need a true synchronous IPI - * here, not deferred! - */ -#ifdef CONFIG_SCHED_IPI_SUPPORTED - arch_sched_ipi(); -#endif - } - - if (is_aborting(thread) && thread != _current) { - if (arch_is_in_isr()) { - /* ISRs can only spin waiting another CPU */ - k_spin_unlock(&sched_spinlock, key); - while (is_aborting(thread)) { - } - - /* Now we know it's dying, but not necessarily - * dead. Wait for the switch to happen! - */ - key = k_spin_lock(&sched_spinlock); - z_sched_switch_spin(thread); - k_spin_unlock(&sched_spinlock, key); - } else if (active) { - /* Threads can join */ - add_to_waitq_locked(_current, &thread->join_queue); - z_swap(&sched_spinlock, key); - } - return; /* lock has been released */ - } -#endif - end_thread(thread); - if (thread == _current && !arch_is_in_isr()) { - z_swap(&sched_spinlock, key); - __ASSERT(false, "aborted _current back from dead"); - } - k_spin_unlock(&sched_spinlock, key); + z_thread_halt(thread, key, true); } #if !defined(CONFIG_ARCH_HAS_THREAD_ABORT) @@ -1862,8 +1944,8 @@ int z_impl_k_thread_join(struct k_thread *thread, k_timeout_t timeout) */ static bool thread_obj_validate(struct k_thread *thread) { - struct z_object *ko = z_object_find(thread); - int ret = z_object_validate(ko, K_OBJ_THREAD, _OBJ_INIT_TRUE); + struct k_object *ko = k_object_find(thread); + int ret = k_object_validate(ko, K_OBJ_THREAD, _OBJ_INIT_TRUE); switch (ret) { case 0: @@ -1872,9 +1954,9 @@ static bool thread_obj_validate(struct k_thread *thread) return true; default: #ifdef CONFIG_LOG - z_dump_object_error(ret, thread, ko, K_OBJ_THREAD); + k_object_dump_error(ret, thread, ko, K_OBJ_THREAD); #endif - Z_OOPS(Z_SYSCALL_VERIFY_MSG(ret, "access denied")); + K_OOPS(K_SYSCALL_VERIFY_MSG(ret, "access denied")); } CODE_UNREACHABLE; /* LCOV_EXCL_LINE */ } @@ -1896,7 +1978,7 @@ static inline void z_vrfy_k_thread_abort(k_tid_t thread) return; } - Z_OOPS(Z_SYSCALL_VERIFY_MSG(!(thread->base.user_options & K_ESSENTIAL), + K_OOPS(K_SYSCALL_VERIFY_MSG(!(thread->base.user_options & K_ESSENTIAL), "aborting essential thread %p", thread)); z_impl_k_thread_abort((struct k_thread *)thread); diff --git a/kernel/sem.c b/kernel/sem.c index 368c9377a1a..2f8de51ed83 100644 --- a/kernel/sem.c +++ b/kernel/sem.c @@ -21,11 +21,11 @@ #include #include -#include +#include #include #include #include -#include +#include #include #include @@ -38,6 +38,10 @@ */ static struct k_spinlock lock; +#ifdef CONFIG_OBJ_CORE_SEM +static struct k_obj_type obj_type_sem; +#endif + int z_impl_k_sem_init(struct k_sem *sem, unsigned int initial_count, unsigned int limit) { @@ -59,7 +63,11 @@ int z_impl_k_sem_init(struct k_sem *sem, unsigned int initial_count, #if defined(CONFIG_POLL) sys_dlist_init(&sem->poll_events); #endif - z_object_init(sem); + k_object_init(sem); + +#ifdef CONFIG_OBJ_CORE_SEM + k_obj_core_init_and_link(K_OBJ_CORE(sem), &obj_type_sem); +#endif return 0; } @@ -68,7 +76,7 @@ int z_impl_k_sem_init(struct k_sem *sem, unsigned int initial_count, int z_vrfy_k_sem_init(struct k_sem *sem, unsigned int initial_count, unsigned int limit) { - Z_OOPS(Z_SYSCALL_OBJ_INIT(sem, K_OBJ_SEM)); + K_OOPS(K_SYSCALL_OBJ_INIT(sem, K_OBJ_SEM)); return z_impl_k_sem_init(sem, initial_count, limit); } #include @@ -115,7 +123,7 @@ void z_impl_k_sem_give(struct k_sem *sem) #ifdef CONFIG_USERSPACE static inline void z_vrfy_k_sem_give(struct k_sem *sem) { - Z_OOPS(Z_SYSCALL_OBJ(sem, K_OBJ_SEM)); + K_OOPS(K_SYSCALL_OBJ(sem, K_OBJ_SEM)); z_impl_k_sem_give(sem); } #include @@ -180,23 +188,44 @@ void z_impl_k_sem_reset(struct k_sem *sem) #ifdef CONFIG_USERSPACE static inline int z_vrfy_k_sem_take(struct k_sem *sem, k_timeout_t timeout) { - Z_OOPS(Z_SYSCALL_OBJ(sem, K_OBJ_SEM)); + K_OOPS(K_SYSCALL_OBJ(sem, K_OBJ_SEM)); return z_impl_k_sem_take((struct k_sem *)sem, timeout); } #include static inline void z_vrfy_k_sem_reset(struct k_sem *sem) { - Z_OOPS(Z_SYSCALL_OBJ(sem, K_OBJ_SEM)); + K_OOPS(K_SYSCALL_OBJ(sem, K_OBJ_SEM)); z_impl_k_sem_reset(sem); } #include static inline unsigned int z_vrfy_k_sem_count_get(struct k_sem *sem) { - Z_OOPS(Z_SYSCALL_OBJ(sem, K_OBJ_SEM)); + K_OOPS(K_SYSCALL_OBJ(sem, K_OBJ_SEM)); return z_impl_k_sem_count_get(sem); } #include #endif + +#ifdef CONFIG_OBJ_CORE_SEM +static int init_sem_obj_core_list(void) +{ + /* Initialize semaphore object type */ + + z_obj_type_init(&obj_type_sem, K_OBJ_TYPE_SEM_ID, + offsetof(struct k_sem, obj_core)); + + /* Initialize and link statically defined semaphores */ + + STRUCT_SECTION_FOREACH(k_sem, sem) { + k_obj_core_init_and_link(K_OBJ_CORE(sem), &obj_type_sem); + } + + return 0; +} + +SYS_INIT(init_sem_obj_core_list, PRE_KERNEL_1, + CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); +#endif diff --git a/kernel/stack.c b/kernel/stack.c index 38c2ccb90d4..6ada39c9b1e 100644 --- a/kernel/stack.c +++ b/kernel/stack.c @@ -13,12 +13,16 @@ #include #include -#include +#include #include #include -#include +#include #include +#ifdef CONFIG_OBJ_CORE_STACK +static struct k_obj_type obj_type_stack; +#endif + void k_stack_init(struct k_stack *stack, stack_data_t *buffer, uint32_t num_entries) { @@ -28,7 +32,11 @@ void k_stack_init(struct k_stack *stack, stack_data_t *buffer, stack->top = stack->base + num_entries; SYS_PORT_TRACING_OBJ_INIT(k_stack, stack); - z_object_init(stack); + k_object_init(stack); + +#ifdef CONFIG_OBJ_CORE_STACK + k_obj_core_init_and_link(K_OBJ_CORE(stack), &obj_type_stack); +#endif } int32_t z_impl_k_stack_alloc_init(struct k_stack *stack, uint32_t num_entries) @@ -56,8 +64,8 @@ int32_t z_impl_k_stack_alloc_init(struct k_stack *stack, uint32_t num_entries) static inline int32_t z_vrfy_k_stack_alloc_init(struct k_stack *stack, uint32_t num_entries) { - Z_OOPS(Z_SYSCALL_OBJ_NEVER_INIT(stack, K_OBJ_STACK)); - Z_OOPS(Z_SYSCALL_VERIFY(num_entries > 0)); + K_OOPS(K_SYSCALL_OBJ_NEVER_INIT(stack, K_OBJ_STACK)); + K_OOPS(K_SYSCALL_VERIFY(num_entries > 0)); return z_impl_k_stack_alloc_init(stack, num_entries); } #include @@ -124,7 +132,7 @@ int z_impl_k_stack_push(struct k_stack *stack, stack_data_t data) #ifdef CONFIG_USERSPACE static inline int z_vrfy_k_stack_push(struct k_stack *stack, stack_data_t data) { - Z_OOPS(Z_SYSCALL_OBJ(stack, K_OBJ_STACK)); + K_OOPS(K_SYSCALL_OBJ(stack, K_OBJ_STACK)); return z_impl_k_stack_push(stack, data); } @@ -179,9 +187,30 @@ int z_impl_k_stack_pop(struct k_stack *stack, stack_data_t *data, static inline int z_vrfy_k_stack_pop(struct k_stack *stack, stack_data_t *data, k_timeout_t timeout) { - Z_OOPS(Z_SYSCALL_OBJ(stack, K_OBJ_STACK)); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(data, sizeof(stack_data_t))); + K_OOPS(K_SYSCALL_OBJ(stack, K_OBJ_STACK)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(data, sizeof(stack_data_t))); return z_impl_k_stack_pop(stack, data, timeout); } #include #endif + +#ifdef CONFIG_OBJ_CORE_STACK +static int init_stack_obj_core_list(void) +{ + /* Initialize stack object type */ + + z_obj_type_init(&obj_type_stack, K_OBJ_TYPE_STACK_ID, + offsetof(struct k_stack, obj_core)); + + /* Initialize and link statically defined stacks */ + + STRUCT_SECTION_FOREACH(k_stack, stack) { + k_obj_core_init_and_link(K_OBJ_CORE(stack), &obj_type_stack); + } + + return 0; +} + +SYS_INIT(init_stack_obj_core_list, PRE_KERNEL_1, + CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); +#endif diff --git a/kernel/thread.c b/kernel/thread.c index fb578eb48d8..fc31f4b36d8 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -16,8 +16,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include @@ -26,13 +26,49 @@ #include #include #include -#include +#include #include #include +#include #include LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); +#ifdef CONFIG_OBJ_CORE_THREAD +static struct k_obj_type obj_type_thread; + +#ifdef CONFIG_OBJ_CORE_STATS_THREAD +static struct k_obj_core_stats_desc thread_stats_desc = { + .raw_size = sizeof(struct k_cycle_stats), + .query_size = sizeof(struct k_thread_runtime_stats), + .raw = z_thread_stats_raw, + .query = z_thread_stats_query, + .reset = z_thread_stats_reset, + .disable = z_thread_stats_disable, + .enable = z_thread_stats_enable, +}; +#endif + +static int init_thread_obj_core_list(void) +{ + /* Initialize mem_slab object type */ + +#ifdef CONFIG_OBJ_CORE_THREAD + z_obj_type_init(&obj_type_thread, K_OBJ_TYPE_THREAD_ID, + offsetof(struct k_thread, obj_core)); +#endif + +#ifdef CONFIG_OBJ_CORE_STATS_THREAD + k_obj_type_stats_init(&obj_type_thread, &thread_stats_desc); +#endif + + return 0; +} + +SYS_INIT(init_thread_obj_core_list, PRE_KERNEL_1, + CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); +#endif + #ifdef CONFIG_THREAD_MONITOR /* This lock protects the linked list of active threads; i.e. the * initial _kernel.threads pointer and the linked list made up of @@ -69,6 +105,9 @@ void k_thread_foreach(k_thread_user_cb_t user_cb, void *user_data) SYS_PORT_TRACING_FUNC_EXIT(k_thread, foreach); k_spin_unlock(&z_thread_monitor_lock, key); +#else + ARG_UNUSED(user_cb); + ARG_UNUSED(user_data); #endif } @@ -93,6 +132,9 @@ void k_thread_foreach_unlocked(k_thread_user_cb_t user_cb, void *user_data) SYS_PORT_TRACING_FUNC_EXIT(k_thread, foreach_unlocked); k_spin_unlock(&z_thread_monitor_lock, key); +#else + ARG_UNUSED(user_cb); + ARG_UNUSED(user_data); #endif } @@ -100,6 +142,7 @@ bool k_is_in_isr(void) { return arch_is_in_isr(); } +EXPORT_SYMBOL(k_is_in_isr); /* * This function tags the current thread as essential to system operation. @@ -216,7 +259,7 @@ static inline int z_vrfy_k_thread_name_set(struct k_thread *thread, const char * char name[CONFIG_THREAD_MAX_NAME_LEN]; if (thread != NULL) { - if (Z_SYSCALL_OBJ(thread, K_OBJ_THREAD) != 0) { + if (K_SYSCALL_OBJ(thread, K_OBJ_THREAD) != 0) { return -EINVAL; } } @@ -225,7 +268,7 @@ static inline int z_vrfy_k_thread_name_set(struct k_thread *thread, const char * * the current z_vrfy / z_impl split does not provide a * means of doing so. */ - if (z_user_string_copy(name, (char *)str, sizeof(name)) != 0) { + if (k_usermode_string_copy(name, (char *)str, sizeof(name)) != 0) { return -EFAULT; } @@ -237,7 +280,7 @@ static inline int z_vrfy_k_thread_name_set(struct k_thread *thread, const char * #include #endif /* CONFIG_USERSPACE */ -const char *k_thread_name_get(struct k_thread *thread) +const char *k_thread_name_get(k_tid_t thread) { #ifdef CONFIG_THREAD_NAME return (const char *)thread->name; @@ -270,15 +313,33 @@ static size_t copy_bytes(char *dest, size_t dest_size, const char *src, size_t s return bytes_to_copy; } +#define Z_STATE_STR_DUMMY "dummy" +#define Z_STATE_STR_PENDING "pending" +#define Z_STATE_STR_PRESTART "prestart" +#define Z_STATE_STR_DEAD "dead" +#define Z_STATE_STR_SUSPENDED "suspended" +#define Z_STATE_STR_ABORTING "aborting" +#define Z_STATE_STR_SUSPENDING "suspending" +#define Z_STATE_STR_QUEUED "queued" + const char *k_thread_state_str(k_tid_t thread_id, char *buf, size_t buf_size) { size_t off = 0; uint8_t bit; uint8_t thread_state = thread_id->base.thread_state; - static const char *states_str[8] = {"dummy", "pending", "prestart", - "dead", "suspended", "aborting", - "", "queued"}; - static const size_t states_sz[8] = {5, 7, 8, 4, 9, 8, 0, 6}; + static const struct { + const char *str; + size_t len; + } state_string[] = { + { Z_STATE_STR_DUMMY, sizeof(Z_STATE_STR_DUMMY) - 1}, + { Z_STATE_STR_PENDING, sizeof(Z_STATE_STR_PENDING) - 1}, + { Z_STATE_STR_PRESTART, sizeof(Z_STATE_STR_PRESTART) - 1}, + { Z_STATE_STR_DEAD, sizeof(Z_STATE_STR_DEAD) - 1}, + { Z_STATE_STR_SUSPENDED, sizeof(Z_STATE_STR_SUSPENDED) - 1}, + { Z_STATE_STR_ABORTING, sizeof(Z_STATE_STR_ABORTING) - 1}, + { Z_STATE_STR_SUSPENDING, sizeof(Z_STATE_STR_SUSPENDING) - 1}, + { Z_STATE_STR_QUEUED, sizeof(Z_STATE_STR_QUEUED) - 1}, + }; if ((buf == NULL) || (buf_size == 0)) { return ""; @@ -292,14 +353,16 @@ const char *k_thread_state_str(k_tid_t thread_id, char *buf, size_t buf_size) * separate the descriptive strings with a '+'. */ - for (uint8_t index = 0; thread_state != 0; index++) { + + for (unsigned int index = 0; thread_state != 0; index++) { bit = BIT(index); if ((thread_state & bit) == 0) { continue; } off += copy_bytes(buf + off, buf_size - off, - states_str[index], states_sz[index]); + state_string[index].str, + state_string[index].len); thread_state &= ~bit; @@ -319,7 +382,7 @@ static inline int z_vrfy_k_thread_name_copy(k_tid_t thread, { #ifdef CONFIG_THREAD_NAME size_t len; - struct z_object *ko = z_object_find(thread); + struct k_object *ko = k_object_find(thread); /* Special case: we allow reading the names of initialized threads * even if we don't have permission on them @@ -328,7 +391,7 @@ static inline int z_vrfy_k_thread_name_copy(k_tid_t thread, (ko->flags & K_OBJ_FLAG_INITIALIZED) == 0) { return -EINVAL; } - if (Z_SYSCALL_MEMORY_WRITE(buf, size) != 0) { + if (K_SYSCALL_MEMORY_WRITE(buf, size) != 0) { return -EFAULT; } len = strlen(thread->name); @@ -336,7 +399,7 @@ static inline int z_vrfy_k_thread_name_copy(k_tid_t thread, return -ENOSPC; } - return z_user_to_copy((void *)buf, thread->name, len + 1); + return k_usermode_to_copy((void *)buf, thread->name, len + 1); #else ARG_UNUSED(thread); ARG_UNUSED(buf); @@ -392,7 +455,7 @@ void z_impl_k_thread_start(struct k_thread *thread) #ifdef CONFIG_USERSPACE static inline void z_vrfy_k_thread_start(struct k_thread *thread) { - Z_OOPS(Z_SYSCALL_OBJ(thread, K_OBJ_THREAD)); + K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); return z_impl_k_thread_start(thread); } #include @@ -423,7 +486,7 @@ static size_t random_offset(size_t stack_size) size_t random_val; if (!z_stack_adjust_initialized) { - z_early_boot_rand_get((uint8_t *)&random_val, sizeof(random_val)); + z_early_rand_get((uint8_t *)&random_val, sizeof(random_val)); } else { sys_rand_get((uint8_t *)&random_val, sizeof(random_val)); } @@ -537,12 +600,21 @@ char *z_setup_new_thread(struct k_thread *new_thread, Z_ASSERT_VALID_PRIO(prio, entry); +#ifdef CONFIG_OBJ_CORE_THREAD + k_obj_core_init_and_link(K_OBJ_CORE(new_thread), &obj_type_thread); +#ifdef CONFIG_OBJ_CORE_STATS_THREAD + k_obj_core_stats_register(K_OBJ_CORE(new_thread), + &new_thread->base.usage, + sizeof(new_thread->base.usage)); +#endif +#endif + #ifdef CONFIG_USERSPACE __ASSERT((options & K_USER) == 0U || z_stack_is_user_capable(stack), "user thread %p with kernel-only stack %p", new_thread, stack); - z_object_init(new_thread); - z_object_init(stack); + k_object_init(new_thread); + k_object_init(stack); new_thread->stack_obj = stack; new_thread->syscall_frame = NULL; @@ -623,7 +695,7 @@ char *z_setup_new_thread(struct k_thread *new_thread, z_mem_domain_init_thread(new_thread); if ((options & K_INHERIT_PERMS) != 0U) { - z_thread_perms_inherit(_current, new_thread); + k_thread_perms_inherit(_current, new_thread); } #endif #ifdef CONFIG_SCHED_DEADLINE @@ -631,6 +703,10 @@ char *z_setup_new_thread(struct k_thread *new_thread, #endif new_thread->resource_pool = _current->resource_pool; +#ifdef CONFIG_SMP + z_waitq_init(&new_thread->halt_queue); +#endif + #ifdef CONFIG_SCHED_THREAD_USAGE new_thread->base.usage = (struct k_cycle_stats) {}; new_thread->base.usage.track_usage = @@ -665,7 +741,7 @@ k_tid_t z_impl_k_thread_create(struct k_thread *new_thread, #ifdef CONFIG_USERSPACE bool z_stack_is_user_capable(k_thread_stack_t *stack) { - return z_object_find(stack) != NULL; + return k_object_find(stack) != NULL; } k_tid_t z_vrfy_k_thread_create(struct k_thread *new_thread, @@ -675,16 +751,16 @@ k_tid_t z_vrfy_k_thread_create(struct k_thread *new_thread, int prio, uint32_t options, k_timeout_t delay) { size_t total_size, stack_obj_size; - struct z_object *stack_object; + struct k_object *stack_object; /* The thread and stack objects *must* be in an uninitialized state */ - Z_OOPS(Z_SYSCALL_OBJ_NEVER_INIT(new_thread, K_OBJ_THREAD)); + K_OOPS(K_SYSCALL_OBJ_NEVER_INIT(new_thread, K_OBJ_THREAD)); /* No need to check z_stack_is_user_capable(), it won't be in the * object table if it isn't */ - stack_object = z_object_find(stack); - Z_OOPS(Z_SYSCALL_VERIFY_MSG(z_obj_validation_check(stack_object, stack, + stack_object = k_object_find(stack); + K_OOPS(K_SYSCALL_VERIFY_MSG(k_object_validation_check(stack_object, stack, K_OBJ_THREAD_STACK_ELEMENT, _OBJ_INIT_FALSE) == 0, "bad stack object")); @@ -692,7 +768,7 @@ k_tid_t z_vrfy_k_thread_create(struct k_thread *new_thread, /* Verify that the stack size passed in is OK by computing the total * size and comparing it with the size value in the object metadata */ - Z_OOPS(Z_SYSCALL_VERIFY_MSG(!size_add_overflow(K_THREAD_STACK_RESERVED, + K_OOPS(K_SYSCALL_VERIFY_MSG(!size_add_overflow(K_THREAD_STACK_RESERVED, stack_size, &total_size), "stack size overflow (%zu+%zu)", stack_size, @@ -706,21 +782,21 @@ k_tid_t z_vrfy_k_thread_create(struct k_thread *new_thread, #else stack_obj_size = stack_object->data.stack_size; #endif - Z_OOPS(Z_SYSCALL_VERIFY_MSG(total_size <= stack_obj_size, + K_OOPS(K_SYSCALL_VERIFY_MSG(total_size <= stack_obj_size, "stack size %zu is too big, max is %zu", total_size, stack_obj_size)); /* User threads may only create other user threads and they can't * be marked as essential */ - Z_OOPS(Z_SYSCALL_VERIFY(options & K_USER)); - Z_OOPS(Z_SYSCALL_VERIFY(!(options & K_ESSENTIAL))); + K_OOPS(K_SYSCALL_VERIFY(options & K_USER)); + K_OOPS(K_SYSCALL_VERIFY(!(options & K_ESSENTIAL))); /* Check validity of prio argument; must be the same or worse priority * than the caller */ - Z_OOPS(Z_SYSCALL_VERIFY(_is_valid_prio(prio, NULL))); - Z_OOPS(Z_SYSCALL_VERIFY(z_is_prio_lower_or_equal(prio, + K_OOPS(K_SYSCALL_VERIFY(_is_valid_prio(prio, NULL))); + K_OOPS(K_SYSCALL_VERIFY(z_is_prio_lower_or_equal(prio, _current->base.prio))); z_setup_new_thread(new_thread, stack, stack_size, @@ -741,7 +817,7 @@ k_tid_t z_vrfy_k_thread_create(struct k_thread *new_thread, static void grant_static_access(void) { - STRUCT_SECTION_FOREACH(z_object_assignment, pos) { + STRUCT_SECTION_FOREACH(k_object_assignment, pos) { for (int i = 0; pos->objects[i] != NULL; i++) { k_object_access_grant(pos->objects[i], pos->thread); @@ -784,9 +860,11 @@ void z_init_static_threads(void) */ k_sched_lock(); _FOREACH_STATIC_THREAD(thread_data) { - if (thread_data->init_delay != K_TICKS_FOREVER) { + k_timeout_t init_delay = Z_THREAD_INIT_DELAY(thread_data); + + if (!K_TIMEOUT_EQ(init_delay, K_FOREVER)) { schedule_new_thread(thread_data->init_thread, - K_MSEC(thread_data->init_delay)); + init_delay); } } k_sched_unlock(); @@ -895,6 +973,7 @@ int z_impl_k_float_disable(struct k_thread *thread) #if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) return arch_float_disable(thread); #else + ARG_UNUSED(thread); return -ENOTSUP; #endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ } @@ -904,6 +983,8 @@ int z_impl_k_float_enable(struct k_thread *thread, unsigned int options) #if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) return arch_float_enable(thread, options); #else + ARG_UNUSED(thread); + ARG_UNUSED(options); return -ENOTSUP; #endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ } @@ -911,7 +992,7 @@ int z_impl_k_float_enable(struct k_thread *thread, unsigned int options) #ifdef CONFIG_USERSPACE static inline int z_vrfy_k_float_disable(struct k_thread *thread) { - Z_OOPS(Z_SYSCALL_OBJ(thread, K_OBJ_THREAD)); + K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); return z_impl_k_float_disable(thread); } #include @@ -1005,7 +1086,7 @@ int z_vrfy_k_thread_stack_space_get(const struct k_thread *thread, size_t unused; int ret; - ret = Z_SYSCALL_OBJ(thread, K_OBJ_THREAD); + ret = K_SYSCALL_OBJ(thread, K_OBJ_THREAD); CHECKIF(ret != 0) { return ret; } @@ -1015,7 +1096,7 @@ int z_vrfy_k_thread_stack_space_get(const struct k_thread *thread, return ret; } - ret = z_user_to_copy(unused_ptr, &unused, sizeof(size_t)); + ret = k_usermode_to_copy(unused_ptr, &unused, sizeof(size_t)); CHECKIF(ret != 0) { return ret; } @@ -1030,7 +1111,7 @@ int z_vrfy_k_thread_stack_space_get(const struct k_thread *thread, static inline k_ticks_t z_vrfy_k_thread_timeout_remaining_ticks( const struct k_thread *t) { - Z_OOPS(Z_SYSCALL_OBJ(t, K_OBJ_THREAD)); + K_OOPS(K_SYSCALL_OBJ(t, K_OBJ_THREAD)); return z_impl_k_thread_timeout_remaining_ticks(t); } #include @@ -1038,7 +1119,7 @@ static inline k_ticks_t z_vrfy_k_thread_timeout_remaining_ticks( static inline k_ticks_t z_vrfy_k_thread_timeout_expires_ticks( const struct k_thread *t) { - Z_OOPS(Z_SYSCALL_OBJ(t, K_OBJ_THREAD)); + K_OOPS(K_SYSCALL_OBJ(t, K_OBJ_THREAD)); return z_impl_k_thread_timeout_expires_ticks(t); } #include diff --git a/kernel/timeout.c b/kernel/timeout.c index 1d3149b2afe..16429bbba20 100644 --- a/kernel/timeout.c +++ b/kernel/timeout.c @@ -7,8 +7,8 @@ #include #include #include -#include -#include +#include +#include #include #include diff --git a/kernel/timer.c b/kernel/timer.c index 9de9768c361..48cc69baffe 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -7,14 +7,18 @@ #include #include -#include -#include -#include +#include #include #include +#include +#include static struct k_spinlock lock; +#ifdef CONFIG_OBJ_CORE_TIMER +static struct k_obj_type obj_type_timer; +#endif + /** * @brief Handle expiration of a kernel timer object. * @@ -124,7 +128,11 @@ void k_timer_init(struct k_timer *timer, timer->user_data = NULL; - z_object_init(timer); + k_object_init(timer); + +#ifdef CONFIG_OBJ_CORE_TIMER + k_obj_core_init_and_link(K_OBJ_CORE(timer), &obj_type_timer); +#endif } @@ -133,7 +141,15 @@ void z_impl_k_timer_start(struct k_timer *timer, k_timeout_t duration, { SYS_PORT_TRACING_OBJ_FUNC(k_timer, start, timer, duration, period); + /* Acquire spinlock to ensure safety during concurrent calls to + * k_timer_start for scheduling or rescheduling. This is necessary + * since k_timer_start can be preempted, especially for the same + * timer instance. + */ + k_spinlock_key_t key = k_spin_lock(&lock); + if (K_TIMEOUT_EQ(duration, K_FOREVER)) { + k_spin_unlock(&lock, key); return; } @@ -160,6 +176,8 @@ void z_impl_k_timer_start(struct k_timer *timer, k_timeout_t duration, z_add_timeout(&timer->timeout, z_timer_expiration_handler, duration); + + k_spin_unlock(&lock, key); } #ifdef CONFIG_USERSPACE @@ -167,7 +185,7 @@ static inline void z_vrfy_k_timer_start(struct k_timer *timer, k_timeout_t duration, k_timeout_t period) { - Z_OOPS(Z_SYSCALL_OBJ(timer, K_OBJ_TIMER)); + K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); z_impl_k_timer_start(timer, duration, period); } #include @@ -200,7 +218,7 @@ void z_impl_k_timer_stop(struct k_timer *timer) #ifdef CONFIG_USERSPACE static inline void z_vrfy_k_timer_stop(struct k_timer *timer) { - Z_OOPS(Z_SYSCALL_OBJ(timer, K_OBJ_TIMER)); + K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); z_impl_k_timer_stop(timer); } #include @@ -220,7 +238,7 @@ uint32_t z_impl_k_timer_status_get(struct k_timer *timer) #ifdef CONFIG_USERSPACE static inline uint32_t z_vrfy_k_timer_status_get(struct k_timer *timer) { - Z_OOPS(Z_SYSCALL_OBJ(timer, K_OBJ_TIMER)); + K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); return z_impl_k_timer_status_get(timer); } #include @@ -288,7 +306,7 @@ uint32_t z_impl_k_timer_status_sync(struct k_timer *timer) #ifdef CONFIG_USERSPACE static inline uint32_t z_vrfy_k_timer_status_sync(struct k_timer *timer) { - Z_OOPS(Z_SYSCALL_OBJ(timer, K_OBJ_TIMER)); + K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); return z_impl_k_timer_status_sync(timer); } #include @@ -296,7 +314,7 @@ static inline uint32_t z_vrfy_k_timer_status_sync(struct k_timer *timer) static inline k_ticks_t z_vrfy_k_timer_remaining_ticks( const struct k_timer *timer) { - Z_OOPS(Z_SYSCALL_OBJ(timer, K_OBJ_TIMER)); + K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); return z_impl_k_timer_remaining_ticks(timer); } #include @@ -304,14 +322,14 @@ static inline k_ticks_t z_vrfy_k_timer_remaining_ticks( static inline k_ticks_t z_vrfy_k_timer_expires_ticks( const struct k_timer *timer) { - Z_OOPS(Z_SYSCALL_OBJ(timer, K_OBJ_TIMER)); + K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); return z_impl_k_timer_expires_ticks(timer); } #include static inline void *z_vrfy_k_timer_user_data_get(const struct k_timer *timer) { - Z_OOPS(Z_SYSCALL_OBJ(timer, K_OBJ_TIMER)); + K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); return z_impl_k_timer_user_data_get(timer); } #include @@ -319,9 +337,29 @@ static inline void *z_vrfy_k_timer_user_data_get(const struct k_timer *timer) static inline void z_vrfy_k_timer_user_data_set(struct k_timer *timer, void *user_data) { - Z_OOPS(Z_SYSCALL_OBJ(timer, K_OBJ_TIMER)); + K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); z_impl_k_timer_user_data_set(timer, user_data); } #include #endif + +#ifdef CONFIG_OBJ_CORE_TIMER +static int init_timer_obj_core_list(void) +{ + /* Initialize timer object type */ + + z_obj_type_init(&obj_type_timer, K_OBJ_TYPE_TIMER_ID, + offsetof(struct k_timer, obj_core)); + + /* Initialize and link statically defined timers */ + + STRUCT_SECTION_FOREACH(k_timer, timer) { + k_obj_core_init_and_link(K_OBJ_CORE(timer), &obj_type_timer); + } + + return 0; +} +SYS_INIT(init_timer_obj_core_list, PRE_KERNEL_1, + CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); +#endif diff --git a/kernel/usage.c b/kernel/usage.c index a44c7552f5c..de497e2879c 100644 --- a/kernel/usage.c +++ b/kernel/usage.c @@ -35,22 +35,22 @@ static uint32_t usage_now(void) #ifdef CONFIG_SCHED_THREAD_USAGE_ALL static void sched_cpu_update_usage(struct _cpu *cpu, uint32_t cycles) { - if (!cpu->usage.track_usage) { + if (!cpu->usage->track_usage) { return; } if (cpu->current != cpu->idle_thread) { - cpu->usage.total += cycles; + cpu->usage->total += cycles; #ifdef CONFIG_SCHED_THREAD_USAGE_ANALYSIS - cpu->usage.current += cycles; + cpu->usage->current += cycles; - if (cpu->usage.longest < cpu->usage.current) { - cpu->usage.longest = cpu->usage.current; + if (cpu->usage->longest < cpu->usage->current) { + cpu->usage->longest = cpu->usage->current; } } else { - cpu->usage.current = 0; - cpu->usage.num_windows++; + cpu->usage->current = 0; + cpu->usage->num_windows++; #endif } } @@ -148,16 +148,16 @@ void z_sched_cpu_usage(uint8_t cpu_id, struct k_thread_runtime_stats *stats) cpu->usage0 = now; } - stats->total_cycles = cpu->usage.total; + stats->total_cycles = cpu->usage->total; #ifdef CONFIG_SCHED_THREAD_USAGE_ANALYSIS - stats->current_cycles = cpu->usage.current; - stats->peak_cycles = cpu->usage.longest; + stats->current_cycles = cpu->usage->current; + stats->peak_cycles = cpu->usage->longest; - if (cpu->usage.num_windows == 0) { + if (cpu->usage->num_windows == 0) { stats->average_cycles = 0; } else { stats->average_cycles = stats->total_cycles / - cpu->usage.num_windows; + cpu->usage->num_windows; } #endif @@ -282,7 +282,7 @@ void k_sys_runtime_stats_enable(void) key = k_spin_lock(&usage_lock); - if (_current_cpu->usage.track_usage) { + if (_current_cpu->usage->track_usage) { /* * Usage tracking is already enabled on the current CPU @@ -299,10 +299,10 @@ void k_sys_runtime_stats_enable(void) unsigned int num_cpus = arch_num_cpus(); for (uint8_t i = 0; i < num_cpus; i++) { - _kernel.cpus[i].usage.track_usage = true; + _kernel.cpus[i].usage->track_usage = true; #ifdef CONFIG_SCHED_THREAD_USAGE_ANALYSIS - _kernel.cpus[i].usage.num_windows++; - _kernel.cpus[i].usage.current = 0; + _kernel.cpus[i].usage->num_windows++; + _kernel.cpus[i].usage->current = 0; #endif } @@ -316,7 +316,7 @@ void k_sys_runtime_stats_disable(void) key = k_spin_lock(&usage_lock); - if (!_current_cpu->usage.track_usage) { + if (!_current_cpu->usage->track_usage) { /* * Usage tracking is already disabled on the current CPU @@ -337,9 +337,150 @@ void k_sys_runtime_stats_disable(void) if (cpu->usage0 != 0) { sched_cpu_update_usage(cpu, now - cpu->usage0); } - cpu->usage.track_usage = false; + cpu->usage->track_usage = false; } k_spin_unlock(&usage_lock, key); } #endif + +#ifdef CONFIG_OBJ_CORE_STATS_THREAD +int z_thread_stats_raw(struct k_obj_core *obj_core, void *stats) +{ + k_spinlock_key_t key; + + key = k_spin_lock(&usage_lock); + memcpy(stats, obj_core->stats, sizeof(struct k_cycle_stats)); + k_spin_unlock(&usage_lock, key); + + return 0; +} + +int z_thread_stats_query(struct k_obj_core *obj_core, void *stats) +{ + struct k_thread *thread; + + thread = CONTAINER_OF(obj_core, struct k_thread, obj_core); + + z_sched_thread_usage(thread, stats); + + return 0; +} + +int z_thread_stats_reset(struct k_obj_core *obj_core) +{ + k_spinlock_key_t key; + struct k_cycle_stats *stats; + struct k_thread *thread; + + thread = CONTAINER_OF(obj_core, struct k_thread, obj_core); + key = k_spin_lock(&usage_lock); + stats = obj_core->stats; + + stats->total = 0ULL; +#ifdef CONFIG_SCHED_THREAD_USAGE_ANALYSIS + stats->current = 0ULL; + stats->longest = 0ULL; + stats->num_windows = (thread->base.usage.track_usage) ? 1U : 0U; +#endif + + if (thread != _current_cpu->current) { + + /* + * If the thread is not running, there is nothing else to do. + * If the thread is running on another core, then it is not + * safe to do anything else but unlock and return (and pretend + * that its stats were reset at the start of its execution + * window. + */ + + k_spin_unlock(&usage_lock, key); + + return 0; + } + + /* Update the current CPU stats. */ + + uint32_t now = usage_now(); + uint32_t cycles = now - _current_cpu->usage0; + + sched_cpu_update_usage(_current_cpu, cycles); + + _current_cpu->usage0 = now; + + k_spin_unlock(&usage_lock, key); + + return 0; +} + +int z_thread_stats_disable(struct k_obj_core *obj_core) +{ +#ifdef CONFIG_SCHED_THREAD_USAGE_ANALYSIS + struct k_thread *thread; + + thread = CONTAINER_OF(obj_core, struct k_thread, obj_core); + + return k_thread_runtime_stats_disable(thread); +#else + return -ENOTSUP; +#endif +} + +int z_thread_stats_enable(struct k_obj_core *obj_core) +{ +#ifdef CONFIG_SCHED_THREAD_USAGE_ANALYSIS + struct k_thread *thread; + + thread = CONTAINER_OF(obj_core, struct k_thread, obj_core); + + return k_thread_runtime_stats_enable(thread); +#else + return -ENOTSUP; +#endif +} +#endif + +#ifdef CONFIG_OBJ_CORE_STATS_SYSTEM +int z_cpu_stats_raw(struct k_obj_core *obj_core, void *stats) +{ + k_spinlock_key_t key; + + key = k_spin_lock(&usage_lock); + memcpy(stats, obj_core->stats, sizeof(struct k_cycle_stats)); + k_spin_unlock(&usage_lock, key); + + return 0; +} + +int z_cpu_stats_query(struct k_obj_core *obj_core, void *stats) +{ + struct _cpu *cpu; + + cpu = CONTAINER_OF(obj_core, struct _cpu, obj_core); + + z_sched_cpu_usage(cpu->id, stats); + + return 0; +} +#endif + +#ifdef CONFIG_OBJ_CORE_STATS_SYSTEM +int z_kernel_stats_raw(struct k_obj_core *obj_core, void *stats) +{ + k_spinlock_key_t key; + + key = k_spin_lock(&usage_lock); + memcpy(stats, obj_core->stats, + CONFIG_MP_MAX_NUM_CPUS * sizeof(struct k_cycle_stats)); + k_spin_unlock(&usage_lock, key); + + return 0; +} + +int z_kernel_stats_query(struct k_obj_core *obj_core, void *stats) +{ + ARG_UNUSED(obj_core); + + return k_thread_runtime_stats_all_get(stats); +} +#endif diff --git a/kernel/userspace.c b/kernel/userspace.c index 000310c3ab0..a3e6df69120 100644 --- a/kernel/userspace.c +++ b/kernel/userspace.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -51,19 +51,19 @@ static struct k_spinlock lists_lock; /* kobj dlist */ static struct k_spinlock objfree_lock; /* k_object_free */ #ifdef CONFIG_GEN_PRIV_STACKS -/* On ARM MPU we may have two different alignment requirement +/* On ARM & ARC MPU we may have two different alignment requirement * when dynamically allocating thread stacks, one for the privileged * stack and other for the user stack, so we need to account the * worst alignment scenario and reserve space for that. */ -#ifdef CONFIG_ARM_MPU +#if defined(CONFIG_ARM_MPU) || defined(CONFIG_ARC_MPU) #define STACK_ELEMENT_DATA_SIZE(size) \ (sizeof(struct z_stack_data) + CONFIG_PRIVILEGED_STACK_SIZE + \ Z_THREAD_STACK_OBJ_ALIGN(size) + Z_THREAD_STACK_SIZE_ADJUST(size)) #else #define STACK_ELEMENT_DATA_SIZE(size) (sizeof(struct z_stack_data) + \ Z_THREAD_STACK_SIZE_ADJUST(size)) -#endif /* CONFIG_ARM_MPU */ +#endif /* CONFIG_ARM_MPU || CONFIG_ARC_MPU */ #else #define STACK_ELEMENT_DATA_SIZE(size) Z_THREAD_STACK_SIZE_ADJUST(size) #endif /* CONFIG_GEN_PRIV_STACKS */ @@ -77,7 +77,7 @@ static struct k_spinlock obj_lock; /* kobj struct data */ extern uint8_t _thread_idx_map[CONFIG_MAX_THREAD_BYTES]; #endif -static void clear_perms_cb(struct z_object *ko, void *ctx_ptr); +static void clear_perms_cb(struct k_object *ko, void *ctx_ptr); const char *otype_to_str(enum k_objects otype) { @@ -119,7 +119,7 @@ struct perm_ctx { */ uint8_t *z_priv_stack_find(k_thread_stack_t *stack) { - struct z_object *obj = z_object_find(stack); + struct k_object *obj = k_object_find(stack); __ASSERT(obj != NULL, "stack object not found"); __ASSERT(obj->type == K_OBJ_THREAD_STACK_ELEMENT, @@ -166,14 +166,14 @@ uint8_t *z_priv_stack_find(k_thread_stack_t *stack) MAX(DYN_OBJ_DATA_ALIGN_K_THREAD, (sizeof(void *))) struct dyn_obj { - struct z_object kobj; + struct k_object kobj; sys_dnode_t dobj_list; /* The object itself */ void *data; }; -extern struct z_object *z_object_gperf_find(const void *obj); +extern struct k_object *z_object_gperf_find(const void *obj); extern void z_object_gperf_wordlist_foreach(_wordlist_cb_func_t func, void *context); @@ -281,7 +281,7 @@ static bool thread_idx_alloc(uintptr_t *tidx) *tidx); /* Clear permission from all objects */ - z_object_wordlist_foreach(clear_perms_cb, + k_object_wordlist_foreach(clear_perms_cb, (void *)*tidx); return true; @@ -306,12 +306,12 @@ static bool thread_idx_alloc(uintptr_t *tidx) static void thread_idx_free(uintptr_t tidx) { /* To prevent leaked permission when index is recycled */ - z_object_wordlist_foreach(clear_perms_cb, (void *)tidx); + k_object_wordlist_foreach(clear_perms_cb, (void *)tidx); sys_bitfield_set_bit((mem_addr_t)_thread_idx_map, tidx); } -static struct z_object *dynamic_object_create(enum k_objects otype, size_t align, +static struct k_object *dynamic_object_create(enum k_objects otype, size_t align, size_t size) { struct dyn_obj *dyn; @@ -342,7 +342,7 @@ static struct z_object *dynamic_object_create(enum k_objects otype, size_t align ((uint8_t *)dyn->data + adjusted_size - sizeof(*stack_data)); stack_data->priv = (uint8_t *)dyn->data; dyn->kobj.data.stack_data = stack_data; -#ifdef CONFIG_ARM_MPU +#if defined(CONFIG_ARM_MPU) || defined(CONFIG_ARC_MPU) dyn->kobj.name = (void *)ROUND_UP( ((uint8_t *)dyn->data + CONFIG_PRIVILEGED_STACK_SIZE), Z_THREAD_STACK_OBJ_ALIGN(size)); @@ -373,9 +373,9 @@ static struct z_object *dynamic_object_create(enum k_objects otype, size_t align return &dyn->kobj; } -struct z_object *z_dynamic_object_aligned_create(size_t align, size_t size) +struct k_object *k_object_create_dynamic_aligned(size_t align, size_t size) { - struct z_object *obj = dynamic_object_create(K_OBJ_ANY, align, size); + struct k_object *obj = dynamic_object_create(K_OBJ_ANY, align, size); if (obj == NULL) { LOG_ERR("could not allocate kernel object, out of memory"); @@ -386,7 +386,7 @@ struct z_object *z_dynamic_object_aligned_create(size_t align, size_t size) static void *z_object_alloc(enum k_objects otype, size_t size) { - struct z_object *zo; + struct k_object *zo; uintptr_t tidx = 0; if (otype <= K_OBJ_ANY || otype >= K_OBJ_LAST) { @@ -428,7 +428,7 @@ static void *z_object_alloc(enum k_objects otype, size_t size) /* The allocating thread implicitly gets permission on kernel objects * that it allocates */ - z_thread_perms_set(zo, _current); + k_thread_perms_set(zo, _current); /* Activates reference counting logic for automatic disposal when * all permissions have been revoked @@ -475,9 +475,9 @@ void k_object_free(void *obj) } } -struct z_object *z_object_find(const void *obj) +struct k_object *k_object_find(const void *obj) { - struct z_object *ret; + struct k_object *ret; ret = z_object_gperf_find(obj); @@ -497,7 +497,7 @@ struct z_object *z_object_find(const void *obj) return ret; } -void z_object_wordlist_foreach(_wordlist_cb_func_t func, void *context) +void k_object_wordlist_foreach(_wordlist_cb_func_t func, void *context) { struct dyn_obj *obj, *next; @@ -514,9 +514,9 @@ void z_object_wordlist_foreach(_wordlist_cb_func_t func, void *context) static unsigned int thread_index_get(struct k_thread *thread) { - struct z_object *ko; + struct k_object *ko; - ko = z_object_find(thread); + ko = k_object_find(thread); if (ko == NULL) { return -1; @@ -525,7 +525,7 @@ static unsigned int thread_index_get(struct k_thread *thread) return ko->data.thread_id; } -static void unref_check(struct z_object *ko, uintptr_t index) +static void unref_check(struct k_object *ko, uintptr_t index) { k_spinlock_key_t key = k_spin_lock(&obj_lock); @@ -579,7 +579,7 @@ static void unref_check(struct z_object *ko, uintptr_t index) k_spin_unlock(&obj_lock, key); } -static void wordlist_cb(struct z_object *ko, void *ctx_ptr) +static void wordlist_cb(struct k_object *ko, void *ctx_ptr) { struct perm_ctx *ctx = (struct perm_ctx *)ctx_ptr; @@ -589,7 +589,7 @@ static void wordlist_cb(struct z_object *ko, void *ctx_ptr) } } -void z_thread_perms_inherit(struct k_thread *parent, struct k_thread *child) +void k_thread_perms_inherit(struct k_thread *parent, struct k_thread *child) { struct perm_ctx ctx = { thread_index_get(parent), @@ -598,11 +598,11 @@ void z_thread_perms_inherit(struct k_thread *parent, struct k_thread *child) }; if ((ctx.parent_id != -1) && (ctx.child_id != -1)) { - z_object_wordlist_foreach(wordlist_cb, &ctx); + k_object_wordlist_foreach(wordlist_cb, &ctx); } } -void z_thread_perms_set(struct z_object *ko, struct k_thread *thread) +void k_thread_perms_set(struct k_object *ko, struct k_thread *thread) { int index = thread_index_get(thread); @@ -611,7 +611,7 @@ void z_thread_perms_set(struct z_object *ko, struct k_thread *thread) } } -void z_thread_perms_clear(struct z_object *ko, struct k_thread *thread) +void k_thread_perms_clear(struct k_object *ko, struct k_thread *thread) { int index = thread_index_get(thread); @@ -621,23 +621,23 @@ void z_thread_perms_clear(struct z_object *ko, struct k_thread *thread) } } -static void clear_perms_cb(struct z_object *ko, void *ctx_ptr) +static void clear_perms_cb(struct k_object *ko, void *ctx_ptr) { uintptr_t id = (uintptr_t)ctx_ptr; unref_check(ko, id); } -void z_thread_perms_all_clear(struct k_thread *thread) +void k_thread_perms_all_clear(struct k_thread *thread) { uintptr_t index = thread_index_get(thread); if ((int)index != -1) { - z_object_wordlist_foreach(clear_perms_cb, (void *)index); + k_object_wordlist_foreach(clear_perms_cb, (void *)index); } } -static int thread_perms_test(struct z_object *ko) +static int thread_perms_test(struct k_object *ko) { int index; @@ -652,7 +652,7 @@ static int thread_perms_test(struct z_object *ko) return 0; } -static void dump_permission_error(struct z_object *ko) +static void dump_permission_error(struct k_object *ko) { int index = thread_index_get(_current); LOG_ERR("thread %p (%d) does not have permission on %s %p", @@ -661,7 +661,7 @@ static void dump_permission_error(struct z_object *ko) LOG_HEXDUMP_ERR(ko->perms, sizeof(ko->perms), "permission bitmap"); } -void z_dump_object_error(int retval, const void *obj, struct z_object *ko, +void k_object_dump_error(int retval, const void *obj, struct k_object *ko, enum k_objects otype) { switch (retval) { @@ -691,19 +691,19 @@ void z_dump_object_error(int retval, const void *obj, struct z_object *ko, void z_impl_k_object_access_grant(const void *object, struct k_thread *thread) { - struct z_object *ko = z_object_find(object); + struct k_object *ko = k_object_find(object); if (ko != NULL) { - z_thread_perms_set(ko, thread); + k_thread_perms_set(ko, thread); } } void k_object_access_revoke(const void *object, struct k_thread *thread) { - struct z_object *ko = z_object_find(object); + struct k_object *ko = k_object_find(object); if (ko != NULL) { - z_thread_perms_clear(ko, thread); + k_thread_perms_clear(ko, thread); } } @@ -714,14 +714,14 @@ void z_impl_k_object_release(const void *object) void k_object_access_all_grant(const void *object) { - struct z_object *ko = z_object_find(object); + struct k_object *ko = k_object_find(object); if (ko != NULL) { ko->flags |= K_OBJ_FLAG_PUBLIC; } } -int z_object_validate(struct z_object *ko, enum k_objects otype, +int k_object_validate(struct k_object *ko, enum k_objects otype, enum _obj_init_check init) { if (unlikely((ko == NULL) || @@ -754,19 +754,19 @@ int z_object_validate(struct z_object *ko, enum k_objects otype, return 0; } -void z_object_init(const void *obj) +void k_object_init(const void *obj) { - struct z_object *ko; + struct k_object *ko; /* By the time we get here, if the caller was from userspace, all the - * necessary checks have been done in z_object_validate(), which takes + * necessary checks have been done in k_object_validate(), which takes * place before the object is initialized. * * This function runs after the object has been initialized and * finalizes it */ - ko = z_object_find(obj); + ko = k_object_find(obj); if (ko == NULL) { /* Supervisor threads can ignore rules about kernel objects * and may declare them on stacks, etc. Such objects will never @@ -779,23 +779,23 @@ void z_object_init(const void *obj) ko->flags |= K_OBJ_FLAG_INITIALIZED; } -void z_object_recycle(const void *obj) +void k_object_recycle(const void *obj) { - struct z_object *ko = z_object_find(obj); + struct k_object *ko = k_object_find(obj); if (ko != NULL) { (void)memset(ko->perms, 0, sizeof(ko->perms)); - z_thread_perms_set(ko, k_current_get()); + k_thread_perms_set(ko, _current); ko->flags |= K_OBJ_FLAG_INITIALIZED; } } -void z_object_uninit(const void *obj) +void k_object_uninit(const void *obj) { - struct z_object *ko; + struct k_object *ko; - /* See comments in z_object_init() */ - ko = z_object_find(obj); + /* See comments in k_object_init() */ + ko = k_object_find(obj); if (ko == NULL) { return; } @@ -806,12 +806,12 @@ void z_object_uninit(const void *obj) /* * Copy to/from helper functions used in syscall handlers */ -void *z_user_alloc_from_copy(const void *src, size_t size) +void *k_usermode_alloc_from_copy(const void *src, size_t size) { void *dst = NULL; /* Does the caller in user mode have access to read this memory? */ - if (Z_SYSCALL_MEMORY_READ(src, size)) { + if (K_SYSCALL_MEMORY_READ(src, size)) { goto out_err; } @@ -831,8 +831,8 @@ static int user_copy(void *dst, const void *src, size_t size, bool to_user) int ret = EFAULT; /* Does the caller in user mode have access to this memory? */ - if (to_user ? Z_SYSCALL_MEMORY_WRITE(dst, size) : - Z_SYSCALL_MEMORY_READ(src, size)) { + if (to_user ? K_SYSCALL_MEMORY_WRITE(dst, size) : + K_SYSCALL_MEMORY_READ(src, size)) { goto out_err; } @@ -842,23 +842,23 @@ static int user_copy(void *dst, const void *src, size_t size, bool to_user) return ret; } -int z_user_from_copy(void *dst, const void *src, size_t size) +int k_usermode_from_copy(void *dst, const void *src, size_t size) { return user_copy(dst, src, size, false); } -int z_user_to_copy(void *dst, const void *src, size_t size) +int k_usermode_to_copy(void *dst, const void *src, size_t size) { return user_copy(dst, src, size, true); } -char *z_user_string_alloc_copy(const char *src, size_t maxlen) +char *k_usermode_string_alloc_copy(const char *src, size_t maxlen) { size_t actual_len; int err; char *ret = NULL; - actual_len = z_user_string_nlen(src, maxlen, &err); + actual_len = k_usermode_string_nlen(src, maxlen, &err); if (err != 0) { goto out; } @@ -872,7 +872,7 @@ char *z_user_string_alloc_copy(const char *src, size_t maxlen) goto out; } - ret = z_user_alloc_from_copy(src, actual_len); + ret = k_usermode_alloc_from_copy(src, actual_len); /* Someone may have modified the source string during the above * checks. Ensure what we actually copied is still terminated @@ -885,12 +885,12 @@ char *z_user_string_alloc_copy(const char *src, size_t maxlen) return ret; } -int z_user_string_copy(char *dst, const char *src, size_t maxlen) +int k_usermode_string_copy(char *dst, const char *src, size_t maxlen) { size_t actual_len; int ret, err; - actual_len = z_user_string_nlen(src, maxlen, &err); + actual_len = k_usermode_string_nlen(src, maxlen, &err); if (err != 0) { ret = EFAULT; goto out; @@ -907,9 +907,9 @@ int z_user_string_copy(char *dst, const char *src, size_t maxlen) goto out; } - ret = z_user_from_copy(dst, src, actual_len); + ret = k_usermode_from_copy(dst, src, actual_len); - /* See comment above in z_user_string_alloc_copy() */ + /* See comment above in k_usermode_string_alloc_copy() */ dst[actual_len - 1] = '\0'; out: return ret; diff --git a/kernel/userspace_handler.c b/kernel/userspace_handler.c index 80f9325b7de..a1cf9f9d7a3 100644 --- a/kernel/userspace_handler.c +++ b/kernel/userspace_handler.c @@ -5,23 +5,26 @@ */ #include -#include +#include #include +#include -static struct z_object *validate_any_object(const void *obj) +static struct k_object *validate_kernel_object(const void *obj, + enum k_objects otype, + enum _obj_init_check init) { - struct z_object *ko; + struct k_object *ko; int ret; - ko = z_object_find(obj); + ko = k_object_find(obj); /* This can be any kernel object and it doesn't have to be * initialized */ - ret = z_object_validate(ko, K_OBJ_ANY, _OBJ_INIT_ANY); + ret = k_object_validate(ko, K_OBJ_ANY, _OBJ_INIT_ANY); if (ret != 0) { #ifdef CONFIG_LOG - z_dump_object_error(ret, obj, ko, K_OBJ_ANY); + k_object_dump_error(ret, obj, ko, otype); #endif return NULL; } @@ -29,34 +32,48 @@ static struct z_object *validate_any_object(const void *obj) return ko; } +static ALWAYS_INLINE struct k_object *validate_any_object(const void *obj) +{ + return validate_kernel_object(obj, K_OBJ_ANY, _OBJ_INIT_ANY); +} + +bool k_object_is_valid(const void *obj, enum k_objects otype) +{ + struct k_object *ko; + + ko = validate_kernel_object(obj, otype, _OBJ_INIT_TRUE); + + return (ko != NULL); +} + /* Normally these would be included in userspace.c, but the way * syscall_dispatch.c declares weak handlers results in build errors if these * are located in userspace.c. Just put in a separate file. * - * To avoid double z_object_find() lookups, we don't call the implementation + * To avoid double k_object_find() lookups, we don't call the implementation * function, but call a level deeper. */ static inline void z_vrfy_k_object_access_grant(const void *object, struct k_thread *thread) { - struct z_object *ko; + struct k_object *ko; - Z_OOPS(Z_SYSCALL_OBJ_INIT(thread, K_OBJ_THREAD)); + K_OOPS(K_SYSCALL_OBJ_INIT(thread, K_OBJ_THREAD)); ko = validate_any_object(object); - Z_OOPS(Z_SYSCALL_VERIFY_MSG(ko != NULL, "object %p access denied", + K_OOPS(K_SYSCALL_VERIFY_MSG(ko != NULL, "object %p access denied", object)); - z_thread_perms_set(ko, thread); + k_thread_perms_set(ko, thread); } #include static inline void z_vrfy_k_object_release(const void *object) { - struct z_object *ko; + struct k_object *ko; ko = validate_any_object((void *)object); - Z_OOPS(Z_SYSCALL_VERIFY_MSG(ko != NULL, "object %p access denied", + K_OOPS(K_SYSCALL_VERIFY_MSG(ko != NULL, "object %p access denied", (void *)object)); - z_thread_perms_clear(ko, _current); + k_thread_perms_clear(ko, _current); } #include diff --git a/kernel/work.c b/kernel/work.c index 08c9d47176e..c5d7c9b5bb8 100644 --- a/kernel/work.c +++ b/kernel/work.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include #include @@ -370,6 +370,7 @@ int z_work_submit_to_queue(struct k_work_q *queue, struct k_work *work) { __ASSERT_NO_MSG(work != NULL); + __ASSERT_NO_MSG(work->handler != NULL); k_spinlock_key_t key = k_spin_lock(&lock); @@ -598,6 +599,9 @@ bool k_work_cancel_sync(struct k_work *work, */ static void work_queue_main(void *workq_ptr, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct k_work_q *queue = (struct k_work_q *)workq_ptr; while (true) { diff --git a/lib/acpi/Kconfig b/lib/acpi/Kconfig index 366dfa66782..42b35725c70 100644 --- a/lib/acpi/Kconfig +++ b/lib/acpi/Kconfig @@ -14,15 +14,24 @@ module = ACPI module-str = acpi source "subsys/logging/Kconfig.template.log_config" +if PCIE_PRT + +config ACPI_PRT_BUS_NAME + string "ACPI name of PCI bus" + default "_SB.PCI0" + help + ACPI name of PCI bus. + config ACPI_MAX_PRT_ENTRY int "Size of PRT buffer" default 4096 help Size of PRT table buffer. +endif # PCIE_PRT + config ACPI_SHELL bool "ACPI command Shell" - default y depends on SHELL help Enable commands for debugging ACPI using the built-in shell. @@ -33,18 +42,6 @@ config ACPI_DEV_MAX help maximum acpi child devices. -config ACPI_INIT_PRIORITY - int "acpi boot time init level" - default 42 - help - boot time init level for acpi driver. - -config ACPI_MAX_INIT_TABLES - int "acpi table size" - default 16 - help - acpi table size. - endif # ACPI config ACPI_HID_LEN_MAX diff --git a/lib/acpi/acpi.c b/lib/acpi/acpi.c index e8948b51e17..7d84b4e5d29 100644 --- a/lib/acpi/acpi.c +++ b/lib/acpi/acpi.c @@ -14,38 +14,32 @@ #include LOG_MODULE_REGISTER(ACPI, CONFIG_ACPI_LOG_LEVEL); -struct acpi { +static struct { struct acpi_dev child_dev[CONFIG_ACPI_DEV_MAX]; int num_dev; +#ifdef CONFIG_PCIE_PRT ACPI_PCI_ROUTING_TABLE pci_prt_table[CONFIG_ACPI_MAX_PRT_ENTRY]; +#endif bool early_init; - int status; -}; - -static struct acpi bus_ctx = { + ACPI_STATUS status; +} acpi = { .status = AE_NOT_CONFIGURED, }; -static ACPI_TABLE_DESC acpi_tables[CONFIG_ACPI_MAX_INIT_TABLES]; - static int acpi_init(void); static int check_init_status(void) { - int ret; - - if (ACPI_SUCCESS(bus_ctx.status)) { - return 0; + if (acpi.status == AE_NOT_CONFIGURED) { + acpi.status = acpi_init(); } - if (bus_ctx.status == AE_NOT_CONFIGURED) { - LOG_DBG("ACPI init\n"); - ret = acpi_init(); + if (ACPI_SUCCESS(acpi.status)) { + return 0; } else { - LOG_ERR("ACPI init was not success\n"); - ret = -EIO; + LOG_ERR("ACPI init was not success"); + return -EIO; } - return ret; } static void notify_handler(ACPI_HANDLE device, UINT32 value, void *ctx) @@ -53,24 +47,6 @@ static void notify_handler(ACPI_HANDLE device, UINT32 value, void *ctx) ACPI_INFO(("Received a notify 0x%X", value)); } -static ACPI_STATUS region_handler(UINT32 Function, ACPI_PHYSICAL_ADDRESS address, UINT32 bit_width, - UINT64 *value, void *handler_ctx, void *region_ctx) -{ - return AE_OK; -} - -static ACPI_STATUS region_init(ACPI_HANDLE RegionHandle, UINT32 Function, void *handler_ctx, - void **region_ctx) -{ - if (Function == ACPI_REGION_DEACTIVATE) { - *region_ctx = NULL; - } else { - *region_ctx = RegionHandle; - } - - return AE_OK; -} - static ACPI_STATUS install_handlers(void) { ACPI_STATUS status; @@ -83,13 +59,7 @@ static ACPI_STATUS install_handlers(void) goto exit; } - status = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_SYSTEM_MEMORY, - region_handler, region_init, NULL); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "While installing an OpRegion handler")); - } exit: - return status; } @@ -105,21 +75,18 @@ static ACPI_STATUS initialize_acpica(void) } /* Initialize the ACPI Table Manager and get all ACPI tables */ - if (!bus_ctx.early_init) { + if (!acpi.early_init) { status = AcpiInitializeTables(NULL, 16, FALSE); - } else { - /* Copy the root table list to dynamic memory if already initialized */ - status = AcpiReallocateRootTable(); - } - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "While initializing Table Manager")); - goto exit; + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "While initializing Table Manager")); + goto exit; + } } - /* Initialize the ACPI hardware */ - status = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION); + /* Create the ACPI namespace from ACPI tables */ + status = AcpiLoadTables(); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "While enabling ACPI")); + ACPI_EXCEPTION((AE_INFO, status, "While loading ACPI tables")); goto exit; } @@ -130,10 +97,10 @@ static ACPI_STATUS initialize_acpica(void) goto exit; } - /* Create the ACPI namespace from ACPI tables */ - status = AcpiLoadTables(); + /* Initialize the ACPI hardware */ + status = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "While loading ACPI tables")); + ACPI_EXCEPTION((AE_INFO, status, "While enabling ACPI")); goto exit; } @@ -224,61 +191,19 @@ static ACPI_STATUS acpi_enable_pic_mode(void) return status; } -static int acpi_get_irq_table(struct acpi *bus, char *bus_name, - ACPI_PCI_ROUTING_TABLE *rt_table, uint32_t rt_size) -{ - ACPI_BUFFER rt_buffer; - ACPI_NAMESPACE_NODE *node; - int status; - - LOG_DBG("%s", bus_name); - - node = acpi_evaluate_method(bus_name, METHOD_NAME__PRT); - if (!node) { - LOG_ERR("Evaluation failed for given device: %s", bus_name); - return -ENODEV; - } - - rt_buffer.Pointer = rt_table; - rt_buffer.Length = ACPI_DEBUG_BUFFER_SIZE; - - status = AcpiGetIrqRoutingTable(node, &rt_buffer); - if (ACPI_FAILURE(status)) { - LOG_ERR("unable to retrieve IRQ Routing Table: %s", bus_name); - return -EIO; - } - - for (int i = 0; i < CONFIG_ACPI_MAX_PRT_ENTRY; i++) { - if (!bus->pci_prt_table[i].SourceIndex) { - break; - } - /* mark the PRT irq numbers as reserved. */ - arch_irq_set_used(bus->pci_prt_table[i].SourceIndex); - } - - return 0; -} - -static int acpi_retrieve_legacy_irq(struct acpi *bus) -{ - /* TODO: assume platform have only one PCH with single PCI bus (bus 0). */ - return acpi_get_irq_table(bus, "_SB.PC00", bus->pci_prt_table, sizeof(bus->pci_prt_table)); -} - static ACPI_STATUS dev_resource_enum_callback(ACPI_HANDLE obj_handle, UINT32 level, void *ctx, void **ret_value) { ACPI_NAMESPACE_NODE *node; ACPI_BUFFER rt_buffer; - struct acpi *bus = (struct acpi *)ctx; struct acpi_dev *child_dev; node = ACPI_CAST_PTR(ACPI_NAMESPACE_NODE, obj_handle); char *path_name; - int status; + ACPI_STATUS status; ACPI_DEVICE_INFO *dev_info; - LOG_DBG("%s %p\n", __func__, node); + LOG_DBG("%s %p", __func__, node); /* get device info such as HID, Class ID etc. */ status = AcpiGetObjectInfo(obj_handle, &dev_info); @@ -287,20 +212,20 @@ static ACPI_STATUS dev_resource_enum_callback(ACPI_HANDLE obj_handle, UINT32 lev goto exit; } - if (bus->num_dev >= CONFIG_ACPI_DEV_MAX) { + if (acpi.num_dev >= CONFIG_ACPI_DEV_MAX) { return AE_NO_MEMORY; } - child_dev = (struct acpi_dev *)&bus->child_dev[bus->num_dev++]; + child_dev = (struct acpi_dev *)&acpi.child_dev[acpi.num_dev++]; child_dev->handle = obj_handle; child_dev->dev_info = dev_info; path_name = AcpiNsGetNormalizedPathname(node, TRUE); if (!path_name) { - LOG_ERR("No memory for path_name\n"); + LOG_ERR("No memory for path_name"); goto exit; } else { - LOG_DBG("Device path: %s\n", path_name); + LOG_DBG("Device path: %s", path_name); child_dev->path = path_name; } @@ -319,122 +244,55 @@ static ACPI_STATUS dev_resource_enum_callback(ACPI_HANDLE obj_handle, UINT32 lev return status; } -static int acpi_enum_devices(struct acpi *bus) +static int acpi_enum_devices(void) { LOG_DBG(""); AcpiWalkNamespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, - dev_resource_enum_callback, NULL, bus, NULL); + dev_resource_enum_callback, NULL, NULL, NULL); return 0; } -static int acpi_init(void) -{ - int status; - - LOG_DBG(""); - - if (bus_ctx.status != AE_NOT_CONFIGURED) { - LOG_DBG("acpi init already done"); - return bus_ctx.status; - } - - /* For debug version only */ - ACPI_DEBUG_INITIALIZE(); - - status = initialize_acpica(); - if (ACPI_FAILURE(status)) { - LOG_ERR("Error in ACPI init:%d", status); - goto exit; - } - - /* Enable IO APIC mode */ - status = acpi_enable_pic_mode(); - if (ACPI_FAILURE(status)) { - LOG_WRN("Error in enable pic mode acpi method:%d", status); - } - - status = acpi_retrieve_legacy_irq(&bus_ctx); - if (status) { - LOG_ERR("Error in retrieve legacy interrupt info:%d", status); - goto exit; - } - - acpi_enum_devices(&bus_ctx); - -exit: - bus_ctx.status = status; - - return status; -} - static int acpi_early_init(void) { ACPI_STATUS status; LOG_DBG(""); - if (bus_ctx.early_init) { + if (acpi.early_init) { LOG_DBG("acpi early init already done"); return 0; } - status = AcpiInitializeTables(acpi_tables, CONFIG_ACPI_MAX_INIT_TABLES, TRUE); + status = AcpiInitializeTables(NULL, 16, FALSE); if (ACPI_FAILURE(status)) { LOG_ERR("Error in acpi table init:%d", status); return -EIO; } - bus_ctx.early_init = true; + acpi.early_init = true; return 0; } -uint32_t acpi_legacy_irq_get(pcie_bdf_t bdf) -{ - uint32_t slot = PCIE_BDF_TO_DEV(bdf), pin; - - LOG_DBG(""); - - if (check_init_status()) { - return UINT_MAX; - } - - pin = (pcie_conf_read(bdf, PCIE_CONF_INTR) >> 8) & 0x3; - - LOG_DBG("Device irq info: slot:%d pin:%d", slot, pin); - - for (int i = 0; i < CONFIG_ACPI_MAX_PRT_ENTRY; i++) { - if (((bus_ctx.pci_prt_table[i].Address >> 16) & 0xffff) == slot && - bus_ctx.pci_prt_table[i].Pin + 1 == pin) { - LOG_DBG("[%d]Device irq info: slot:%d pin:%d irq:%d", i, slot, pin, - bus_ctx.pci_prt_table[i].SourceIndex); - return bus_ctx.pci_prt_table[i].SourceIndex; - } - } - - return UINT_MAX; -} - int acpi_current_resource_get(char *dev_name, ACPI_RESOURCE **res) { ACPI_BUFFER rt_buffer; ACPI_NAMESPACE_NODE *node; - int status; + ACPI_STATUS status; LOG_DBG("%s", dev_name); status = check_init_status(); if (status) { - return status; + return -EAGAIN; } node = acpi_evaluate_method(dev_name, METHOD_NAME__CRS); if (!node) { LOG_ERR("Evaluation failed for given device: %s", dev_name); - status = -ENOTSUP; - goto exit; + return -ENOTSUP; } rt_buffer.Pointer = NULL; @@ -443,34 +301,31 @@ int acpi_current_resource_get(char *dev_name, ACPI_RESOURCE **res) status = AcpiGetCurrentResources(node, &rt_buffer); if (ACPI_FAILURE(status)) { LOG_ERR("AcpiGetCurrentResources failed: %s", AcpiFormatException(status)); - status = -ENOTSUP; + return -ENOTSUP; } else { *res = rt_buffer.Pointer; } -exit: - - return status; + return 0; } int acpi_possible_resource_get(char *dev_name, ACPI_RESOURCE **res) { ACPI_BUFFER rt_buffer; ACPI_NAMESPACE_NODE *node; - int status; + ACPI_STATUS status; LOG_DBG("%s", dev_name); status = check_init_status(); if (status) { - return status; + return -EAGAIN; } node = acpi_evaluate_method(dev_name, METHOD_NAME__PRS); if (!node) { LOG_ERR("Evaluation failed for given device: %s", dev_name); - status = -ENOTSUP; - goto exit; + return -ENOTSUP; } rt_buffer.Pointer = NULL; @@ -479,9 +334,7 @@ int acpi_possible_resource_get(char *dev_name, ACPI_RESOURCE **res) AcpiGetPossibleResources(node, &rt_buffer); *res = rt_buffer.Pointer; -exit: - - return status; + return 0; } int acpi_current_resource_free(ACPI_RESOURCE *res) @@ -491,6 +344,58 @@ int acpi_current_resource_free(ACPI_RESOURCE *res) return 0; } +#ifdef CONFIG_PCIE_PRT +static int acpi_get_irq_table(char *bus_name, ACPI_PCI_ROUTING_TABLE *rt_table, uint32_t rt_size) +{ + ACPI_BUFFER rt_buffer; + ACPI_NAMESPACE_NODE *node; + ACPI_STATUS status; + + LOG_DBG("%s", bus_name); + + node = acpi_evaluate_method(bus_name, METHOD_NAME__PRT); + if (!node) { + LOG_ERR("Evaluation failed for given device: %s", bus_name); + return -ENODEV; + } + + rt_buffer.Pointer = rt_table; + rt_buffer.Length = rt_size * sizeof(ACPI_PCI_ROUTING_TABLE); + + status = AcpiGetIrqRoutingTable(node, &rt_buffer); + if (ACPI_FAILURE(status)) { + LOG_ERR("unable to retrieve IRQ Routing Table: %s", bus_name); + return -EIO; + } + + return 0; +} + +static int acpi_retrieve_legacy_irq(void) +{ + int ret; + + /* TODO: assume platform have only one PCH with single PCI bus (bus 0). */ + ret = acpi_get_irq_table(CONFIG_ACPI_PRT_BUS_NAME, + acpi.pci_prt_table, ARRAY_SIZE(acpi.pci_prt_table)); + if (ret) { + return ret; + } + + for (size_t i = 0; i < ARRAY_SIZE(acpi.pci_prt_table); i++) { + if (!acpi.pci_prt_table[i].SourceIndex) { + break; + } + if (IS_ENABLED(CONFIG_X86_64)) { + /* mark the PRT irq numbers as reserved. */ + arch_irq_set_used(acpi.pci_prt_table[i].SourceIndex); + } + } + + return 0; + +} + int acpi_get_irq_routing_table(char *bus_name, ACPI_PCI_ROUTING_TABLE *rt_table, size_t rt_size) { @@ -501,14 +406,41 @@ int acpi_get_irq_routing_table(char *bus_name, return ret; } - return acpi_get_irq_table(&bus_ctx, bus_name, rt_table, rt_size); + return acpi_get_irq_table(bus_name, rt_table, rt_size); } +uint32_t acpi_legacy_irq_get(pcie_bdf_t bdf) +{ + uint32_t slot = PCIE_BDF_TO_DEV(bdf), pin; + + LOG_DBG(""); + + if (check_init_status()) { + return UINT_MAX; + } + + pin = (pcie_conf_read(bdf, PCIE_CONF_INTR) >> 8) & 0x3; + + LOG_DBG("Device irq info: slot:%d pin:%d", slot, pin); + + for (int i = 0; i < CONFIG_ACPI_MAX_PRT_ENTRY; i++) { + if (((acpi.pci_prt_table[i].Address >> 16) & 0xffff) == slot && + acpi.pci_prt_table[i].Pin + 1 == pin) { + LOG_DBG("[%d]Device irq info: slot:%d pin:%d irq:%d", i, slot, pin, + acpi.pci_prt_table[i].SourceIndex); + return acpi.pci_prt_table[i].SourceIndex; + } + } + + return UINT_MAX; +} +#endif /* CONFIG_PCIE_PRT */ + ACPI_RESOURCE *acpi_resource_parse(ACPI_RESOURCE *res, int res_type) { do { if (!res->Length) { - LOG_DBG("Error: zero length found!\n"); + LOG_DBG("Error: zero length found!"); break; } else if (res->Type == res_type) { break; @@ -568,7 +500,7 @@ int acpi_device_type_get(ACPI_RESOURCE *res) do { if (!res->Length) { - LOG_ERR("Error: zero length found!\n"); + LOG_ERR("Error: zero length found!"); break; } type = acpi_res_type(res); @@ -593,9 +525,9 @@ struct acpi_dev *acpi_device_get(char *hid, int inst) } do { - child_dev = &bus_ctx.child_dev[i]; + child_dev = &acpi.child_dev[i]; if (!child_dev->path) { - LOG_DBG("NULL device path found\n"); + LOG_DBG("NULL device path found"); continue; } @@ -614,36 +546,242 @@ struct acpi_dev *acpi_device_get(char *hid, int inst) return child_dev; } } - } while (i++ < bus_ctx.num_dev); + } while (i++ < acpi.num_dev); return NULL; } struct acpi_dev *acpi_device_by_index_get(int index) { - return index < bus_ctx.num_dev ? &bus_ctx.child_dev[index] : NULL; + return index < acpi.num_dev ? &acpi.child_dev[index] : NULL; } -int acpi_table_get(char *signature, int inst, void **acpi_table) +void *acpi_table_get(char *signature, int inst) { - int status; + ACPI_STATUS status; ACPI_TABLE_HEADER *table; - if (!bus_ctx.early_init) { + if (!acpi.early_init) { status = acpi_early_init(); if (status) { - LOG_ERR("ACPI early int failed"); - return status; + LOG_ERR("ACPI early init failed"); + return NULL; } } status = AcpiGetTable(signature, inst, &table); if (ACPI_FAILURE(status)) { LOG_ERR("ACPI get table failed: %d", status); + return NULL; + } + + return (void *)table; +} + +static uint32_t acpi_get_subtable_entry_num(int type, ACPI_SUBTABLE_HEADER *subtable, + uintptr_t offset, uintptr_t base, uint32_t madt_len) +{ + uint32_t subtable_cnt = 0; + + while (offset < madt_len) { + if (type == subtable->Type) { + subtable_cnt++; + } + offset += subtable->Length; + subtable = ACPI_ADD_PTR(ACPI_SUBTABLE_HEADER, base, offset); + + if (!subtable->Length) { + break; + } + } + + return subtable_cnt; +} + +int acpi_madt_entry_get(int type, ACPI_SUBTABLE_HEADER **tables, int *num_inst) +{ + ACPI_TABLE_HEADER *madt = acpi_table_get("APIC", 0); + uintptr_t base = POINTER_TO_UINT(madt); + uintptr_t offset = sizeof(ACPI_TABLE_MADT); + ACPI_SUBTABLE_HEADER *subtable; + + if (!madt) { return -EIO; } - *acpi_table = table; + subtable = ACPI_ADD_PTR(ACPI_SUBTABLE_HEADER, base, offset); + while (offset < madt->Length) { + + if (type == subtable->Type) { + *tables = subtable; + *num_inst = acpi_get_subtable_entry_num(type, subtable, offset, base, + madt->Length); + return 0; + } + + offset += subtable->Length; + subtable = ACPI_ADD_PTR(ACPI_SUBTABLE_HEADER, base, offset); + } + + return -ENODEV; +} + +int acpi_dmar_entry_get(enum AcpiDmarType type, ACPI_SUBTABLE_HEADER **tables) +{ + struct acpi_table_dmar *dmar = acpi_table_get("DMAR", 0); + uintptr_t base = POINTER_TO_UINT(dmar); + uintptr_t offset = sizeof(ACPI_TABLE_DMAR); + ACPI_DMAR_HEADER *subtable; + + if (!dmar) { + LOG_ERR("error on get DMAR table"); + return -EIO; + } + + subtable = ACPI_ADD_PTR(ACPI_DMAR_HEADER, base, offset); + while (offset < dmar->Header.Length) { + if (type == subtable->Type) { + *tables = (struct acpi_subtable_header *)subtable; + return 0; + } + offset += subtable->Length; + subtable = ACPI_ADD_PTR(ACPI_DMAR_HEADER, base, offset); + } + + return -ENODEV; +} + +int acpi_drhd_get(enum AcpiDmarScopeType scope, ACPI_DMAR_DEVICE_SCOPE *dev_scope, + union acpi_dmar_id *dmar_id, int *num_inst, int max_inst) +{ + uintptr_t offset = sizeof(ACPI_DMAR_HARDWARE_UNIT); + uint32_t i = 0; + ACPI_DMAR_HEADER *drdh; + ACPI_DMAR_DEVICE_SCOPE *subtable; + ACPI_DMAR_PCI_PATH *dev_path; + int ret; + uintptr_t base; + int scope_size; + + ret = acpi_dmar_entry_get(ACPI_DMAR_TYPE_HARDWARE_UNIT, + (ACPI_SUBTABLE_HEADER **)&drdh); + if (ret) { + LOG_ERR("Error on retrieve DMAR table"); + return ret; + } + + scope_size = drdh->Length - sizeof(ACPI_DMAR_HARDWARE_UNIT); + base = (uintptr_t)((uintptr_t)drdh + offset); + + offset = 0; + + while (scope_size) { + int num_path; + + subtable = ACPI_ADD_PTR(ACPI_DMAR_DEVICE_SCOPE, base, offset); + if (!subtable->Length) { + break; + } + + if (scope == subtable->EntryType) { + num_path = (subtable->Length - 6u) / 2u; + dev_path = ACPI_ADD_PTR(ACPI_DMAR_PCI_PATH, subtable, + sizeof(ACPI_DMAR_DEVICE_SCOPE)); + + while (num_path--) { + if (i >= max_inst) { + LOG_ERR("DHRD not enough buffer size"); + return -ENOBUFS; + } + dmar_id[i].bits.bus = subtable->Bus; + dmar_id[i].bits.device = dev_path[i].Device; + dmar_id[i].bits.function = dev_path[i].Function; + i++; + } + break; + } + + offset += subtable->Length; + + if (scope_size < subtable->Length) { + break; + } + scope_size -= subtable->Length; + } + + *num_inst = i; + if (!i) { + LOG_ERR("Error on retrieve DRHD Info"); + return -ENODEV; + } + + if (dev_scope && subtable) { + memcpy(dev_scope, subtable, sizeof(struct acpi_dmar_device_scope)); + } return 0; } + +#define ACPI_CPU_FLAGS_ENABLED 0x01u + +ACPI_MADT_LOCAL_APIC *acpi_local_apic_get(int cpu_num) +{ + ACPI_MADT_LOCAL_APIC *lapic; + int cpu_cnt; + int idx; + + if (acpi_madt_entry_get(ACPI_MADT_TYPE_LOCAL_APIC, (ACPI_SUBTABLE_HEADER **)&lapic, + &cpu_cnt)) { + /* Error on MAD table. */ + return NULL; + } + + for (idx = 0; cpu_num >= 0 && idx < cpu_cnt; idx++) { + if (lapic[idx].LapicFlags & ACPI_CPU_FLAGS_ENABLED) { + if (cpu_num == 0) { + return &lapic[idx]; + } + + cpu_num--; + } + } + + return NULL; +} + +static int acpi_init(void) +{ + ACPI_STATUS status; + + LOG_DBG(""); + + /* For debug version only */ + ACPI_DEBUG_INITIALIZE(); + + status = initialize_acpica(); + if (ACPI_FAILURE(status)) { + LOG_ERR("Error in ACPI init:%d", status); + goto exit; + } + + /* Enable IO APIC mode */ + status = acpi_enable_pic_mode(); + if (ACPI_FAILURE(status)) { + LOG_WRN("Error in enable pic mode acpi method:%d", status); + } + +#ifdef CONFIG_PCIE_PRT + int ret = acpi_retrieve_legacy_irq(); + + if (ret) { + LOG_ERR("Error in retrieve legacy interrupt info:%d", ret); + status = AE_ERROR; + goto exit; + } +#endif + + acpi_enum_devices(); + +exit: + return status; +} diff --git a/lib/acpi/acpi_shell.c b/lib/acpi/acpi_shell.c index 570bb18d821..e2db3aaa30e 100644 --- a/lib/acpi/acpi_shell.c +++ b/lib/acpi/acpi_shell.c @@ -5,137 +5,136 @@ */ #include +#include #include #include #include #include #include -#define MAX_PR_BUFF (4096) - -static ACPI_PCI_ROUTING_TABLE irq_prt_table[CONFIG_ACPI_MAX_PRT_ENTRY]; -static uint8_t prs_buffer[MAX_PR_BUFF]; - static void dump_dev_res(const struct shell *sh, ACPI_RESOURCE *res_lst) { ACPI_RESOURCE *res = res_lst; - shell_print(sh, "\n**** ACPI Device Resource Info ****\n"); + shell_print(sh, "**** ACPI Device Resource Info ****"); do { if (!res->Length) { - shell_error(sh, "Error: zero length found!\n"); + shell_error(sh, "Error: zero length found!"); break; } switch (res->Type) { case ACPI_RESOURCE_TYPE_IRQ: - shell_print(sh, "\nACPI_RESOURCE_TYPE_IRQ\n\n"); + shell_print(sh, "ACPI_RESOURCE_TYPE_IRQ"); ACPI_RESOURCE_IRQ *irq_res = &res->Data.Irq; - shell_print(sh, - "DescriptorLength: %x, Triggering:%x, Polarity:%x, Shareable:%x,", - irq_res->DescriptorLength, irq_res->Triggering, irq_res->Polarity, - irq_res->Shareable); - shell_print(sh, - "InterruptCount:%d, Interrupts[0]:%x\n", irq_res->InterruptCount, - irq_res->Interrupts[0]); + shell_print(sh, "\tDescriptorLength: %x", irq_res->DescriptorLength); + shell_print(sh, "\tTriggering: %x", irq_res->Triggering); + shell_print(sh, "\tPolarity: %x", irq_res->Polarity); + shell_print(sh, "\tShareable: %x", irq_res->Shareable); + shell_print(sh, "\tInterruptCount: %d", irq_res->InterruptCount); + shell_print(sh, "\tInterrupts[0]: %x", irq_res->Interrupts[0]); break; - case ACPI_RESOURCE_TYPE_IO: - ACPI_RESOURCE_IO * io_res = &res->Data.Io; - - shell_print(sh, "\n ACPI_RESOURCE_TYPE_IO\n"); - shell_print(sh, - "IoDecode: %x, Alignment:%x, AddressLength:%x, Minimum:%x,Maximum:%x\n", - io_res->IoDecode, io_res->Alignment, - io_res->AddressLength, io_res->Minimum, - io_res->Maximum); + case ACPI_RESOURCE_TYPE_IO: { + ACPI_RESOURCE_IO *io_res = &res->Data.Io; + + shell_print(sh, "ACPI_RESOURCE_TYPE_IO"); + shell_print(sh, "\tIoDecode: %x", io_res->IoDecode); + shell_print(sh, "\tAlignment: %x", io_res->Alignment); + shell_print(sh, "\tAddressLength: %x", io_res->AddressLength); + shell_print(sh, "\tMinimum: %x", io_res->Minimum); + shell_print(sh, "\tMaximum: %x", io_res->Maximum); break; + } case ACPI_RESOURCE_TYPE_DMA: - shell_print(sh, "ACPI_RESOURCE_TYPE_DMA\n\n"); + shell_print(sh, "ACPI_RESOURCE_TYPE_DMA"); break; case ACPI_RESOURCE_TYPE_START_DEPENDENT: - shell_print(sh, "ACPI_RESOURCE_TYPE_START_DEPENDENT\n\n"); + shell_print(sh, "ACPI_RESOURCE_TYPE_START_DEPENDENT"); break; case ACPI_RESOURCE_TYPE_END_DEPENDENT: - shell_print(sh, "ACPI_RESOURCE_TYPE_END_DEPENDENT\n\n"); + shell_print(sh, "ACPI_RESOURCE_TYPE_END_DEPENDENT"); break; case ACPI_RESOURCE_TYPE_FIXED_IO: - shell_print(sh, "ACPI_RESOURCE_TYPE_FIXED_IO\n\n"); + shell_print(sh, "ACPI_RESOURCE_TYPE_FIXED_IO"); break; case ACPI_RESOURCE_TYPE_VENDOR: - shell_print(sh, "ACPI_RESOURCE_TYPE_VENDOR\n\n"); + shell_print(sh, "ACPI_RESOURCE_TYPE_VENDOR"); break; case ACPI_RESOURCE_TYPE_MEMORY24: - shell_print(sh, "ACPI_RESOURCE_TYPE_MEMORY24\n\n"); + shell_print(sh, "ACPI_RESOURCE_TYPE_MEMORY24"); break; - case ACPI_RESOURCE_TYPE_MEMORY32: - ACPI_RESOURCE_MEMORY32 * mem_res = &res->Data.Memory32; + case ACPI_RESOURCE_TYPE_MEMORY32: { + ACPI_RESOURCE_MEMORY32 *mem_res = &res->Data.Memory32; - shell_print(sh, "\nACPI_RESOURCE_TYPE_MEMORY32\n\n"); - shell_print(sh, "Minimum:%x, Maximum:%x\n", - mem_res->Minimum, mem_res->Maximum); + shell_print(sh, "ACPI_RESOURCE_TYPE_MEMORY32"); + shell_print(sh, "\tMinimum: %x", mem_res->Minimum); + shell_print(sh, "\tMaximum: %x", mem_res->Maximum); break; - case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: - ACPI_RESOURCE_FIXED_MEMORY32 * fix_mem_res = &res->Data.FixedMemory32; + } + case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: { + ACPI_RESOURCE_FIXED_MEMORY32 *fix_mem_res = &res->Data.FixedMemory32; - shell_print(sh, "\nACPI_RESOURCE_TYPE_FIXED_MEMORY32\n\n"); - shell_print(sh, "Address:%x\n", fix_mem_res->Address); + shell_print(sh, "ACPI_RESOURCE_TYPE_FIXED_MEMORY32"); + shell_print(sh, "\tAddress: %x", fix_mem_res->Address); break; + } case ACPI_RESOURCE_TYPE_ADDRESS16: - shell_print(sh, "ACPI_RESOURCE_TYPE_ADDRESS16\n\n"); + shell_print(sh, "ACPI_RESOURCE_TYPE_ADDRESS16"); break; - case ACPI_RESOURCE_TYPE_ADDRESS32: - ACPI_RESOURCE_ADDRESS32 * add_res = &res->Data.Address32; + case ACPI_RESOURCE_TYPE_ADDRESS32: { + ACPI_RESOURCE_ADDRESS32 *add_res = &res->Data.Address32; - shell_print(sh, "\nACPI_RESOURCE_TYPE_ADDRESS32\n\n"); - shell_print(sh, "Minimum:%x, Maximum:%x\n", add_res->Address.Minimum, - add_res->Address.Maximum); + shell_print(sh, "ACPI_RESOURCE_TYPE_ADDRESS32"); + shell_print(sh, "\tMinimum: %x", add_res->Address.Minimum); + shell_print(sh, "\tMaximum: %x", add_res->Address.Maximum); break; - case ACPI_RESOURCE_TYPE_ADDRESS64: - ACPI_RESOURCE_ADDRESS64 * add_res64 = &res->Data.Address64; + } + case ACPI_RESOURCE_TYPE_ADDRESS64: { + ACPI_RESOURCE_ADDRESS64 *add_res64 = &res->Data.Address64; - shell_print(sh, "\nACPI_RESOURCE_TYPE_ADDRESS64\n\n"); - shell_print(sh, - "Minimum:%llx, Maximum:%llx\n", add_res64->Address.Minimum, - add_res64->Address.Maximum); + shell_print(sh, "ACPI_RESOURCE_TYPE_ADDRESS64"); + shell_print(sh, "\tMinimum: %llx", add_res64->Address.Minimum); + shell_print(sh, "\tMaximum: %llx", add_res64->Address.Maximum); break; + } case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: - shell_print(sh, "ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64\n\n"); + shell_print(sh, "ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64"); break; case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: - shell_print(sh, "ACPI_RESOURCE_TYPE_EXTENDED_IRQ\n\n"); + shell_print(sh, "ACPI_RESOURCE_TYPE_EXTENDED_IRQ"); break; case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: - shell_print(sh, "ACPI_RESOURCE_TYPE_GENERIC_REGISTER\n\n"); + shell_print(sh, "ACPI_RESOURCE_TYPE_GENERIC_REGISTER"); break; case ACPI_RESOURCE_TYPE_GPIO: - shell_print(sh, "ACPI_RESOURCE_TYPE_GPIO\n\n"); + shell_print(sh, "ACPI_RESOURCE_TYPE_GPIO"); break; case ACPI_RESOURCE_TYPE_FIXED_DMA: - shell_print(sh, "ACPI_RESOURCE_TYPE_FIXED_DMA\n\n"); + shell_print(sh, "ACPI_RESOURCE_TYPE_FIXED_DMA"); break; case ACPI_RESOURCE_TYPE_SERIAL_BUS: - shell_print(sh, "ACPI_RESOURCE_TYPE_SERIAL_BUS\n\n"); + shell_print(sh, "ACPI_RESOURCE_TYPE_SERIAL_BUS"); break; case ACPI_RESOURCE_TYPE_PIN_FUNCTION: - shell_print(sh, "ACPI_RESOURCE_TYPE_PIN_FUNCTION\n\n"); + shell_print(sh, "ACPI_RESOURCE_TYPE_PIN_FUNCTION"); break; case ACPI_RESOURCE_TYPE_PIN_CONFIG: - shell_print(sh, "ACPI_RESOURCE_TYPE_PIN_CONFIG\n\n"); + shell_print(sh, "ACPI_RESOURCE_TYPE_PIN_CONFIG"); break; case ACPI_RESOURCE_TYPE_PIN_GROUP: - shell_print(sh, "ACPI_RESOURCE_TYPE_PIN_GROUP\n\n"); + shell_print(sh, "ACPI_RESOURCE_TYPE_PIN_GROUP"); break; case ACPI_RESOURCE_TYPE_PIN_GROUP_FUNCTION: - shell_print(sh, - "ACPI_RESOURCE_TYPE_PIN_GROUP_FUNCTION\n\n"); + shell_print(sh, "ACPI_RESOURCE_TYPE_PIN_GROUP_FUNCTION"); break; case ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG: - shell_print(sh, "ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG\n\n"); + shell_print(sh, "ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG"); break; default: + shell_error(sh, "Unknown resource type %d", res->Type); } res = ACPI_NEXT_RESOURCE(res); @@ -149,13 +148,13 @@ static int dump_dev_crs(const struct shell *sh, size_t argc, char **argv) ACPI_RESOURCE *res_lst; if (argc < 2) { - shell_error(sh, "invalid arugment\n"); + shell_error(sh, "invalid arugment"); return -EINVAL; } status = acpi_current_resource_get(argv[1], &res_lst); if (status) { - shell_error(sh, "Error on ACPI _CRS method: %d\n", status); + shell_error(sh, "Error on ACPI _CRS method: %d", status); return status; } @@ -169,16 +168,16 @@ static int dump_dev_crs(const struct shell *sh, size_t argc, char **argv) static int dump_dev_prs(const struct shell *sh, size_t argc, char **argv) { int status; - ACPI_RESOURCE *res_lst = (ACPI_RESOURCE *)prs_buffer; + ACPI_RESOURCE *res_lst; if (argc < 2) { - shell_error(sh, "invalid arugment\n"); + shell_error(sh, "invalid arugment"); return -EINVAL; } status = acpi_possible_resource_get(argv[1], &res_lst); if (status) { - shell_error(sh, "Error in on ACPI _PRS method: %d\n", status); + shell_error(sh, "Error in on ACPI _PRS method: %d", status); return status; } @@ -189,29 +188,31 @@ static int dump_dev_prs(const struct shell *sh, size_t argc, char **argv) static int dump_prt(const struct shell *sh, size_t argc, char **argv) { - int status, cnt; - ACPI_PCI_ROUTING_TABLE *prt; - - if (argc < 2) { - shell_error(sh, "invalid arugment\n"); - return -EINVAL; - } + IF_ENABLED(CONFIG_PCIE_PRT, ({ + static ACPI_PCI_ROUTING_TABLE irq_prt_table[CONFIG_ACPI_MAX_PRT_ENTRY]; + int status, cnt; + ACPI_PCI_ROUTING_TABLE *prt; + + if (argc < 2) { + shell_error(sh, "invalid arugment"); + return -EINVAL; + } - status = acpi_get_irq_routing_table(argv[1], - irq_prt_table, sizeof(irq_prt_table)); - if (status) { - return status; - } + status = acpi_get_irq_routing_table(argv[1], + irq_prt_table, ARRAY_SIZE(irq_prt_table)); + if (status) { + return status; + } - prt = irq_prt_table; - for (cnt = 0; prt->Length; cnt++) { - shell_print(sh, "[%02X] PCI IRQ Routing Table Package\n", cnt); - shell_print(sh, - "DevNum: %lld Pin:%d IRQ: %d\n", (prt->Address >> 16) & 0xFFFF, prt->Pin, - prt->SourceIndex); + prt = irq_prt_table; + for (cnt = 0; prt->Length; cnt++) { + shell_print(sh, "[%02X] PCI IRQ Routing Table Package", cnt); + shell_print(sh, "\tDevNum: %lld Pin: %d IRQ: %d", + (prt->Address >> 16) & 0xFFFF, prt->Pin, prt->SourceIndex); - prt = ACPI_ADD_PTR(ACPI_PCI_ROUTING_TABLE, prt, prt->Length); - } + prt = ACPI_ADD_PTR(ACPI_PCI_ROUTING_TABLE, prt, prt->Length); + } + })); /* IF_ENABLED(CONFIG_PCIE_PRT) */ return 0; } @@ -226,10 +227,11 @@ static int enum_dev(const struct shell *sh, size_t argc, char **argv) dev = acpi_device_get(argv[1], 0); if (!dev || !dev->res_lst) { - shell_error(sh, "acpi get device failed for HID: %s\n", argv[1]); + shell_error(sh, "acpi get device failed for HID: %s", argv[1]); return -EIO; } - shell_print(sh, "\nName:%s\n", dev->path ? dev->path : "Non"); + + shell_print(sh, "Name: %s", dev->path ? dev->path : "None"); dump_dev_res(sh, dev->res_lst); return 0; @@ -237,24 +239,23 @@ static int enum_dev(const struct shell *sh, size_t argc, char **argv) static int read_table(const struct shell *sh, size_t argc, char **argv) { - int status; ACPI_TABLE_HEADER *table; if (argc < 2) { return -EINVAL; } - shell_print(sh, "ACPI Table Name: %s\n", argv[1]); - - status = acpi_table_get(argv[1], 0, (void **)&table); - if (status) { - shell_error(sh, "ACPI get table failed: %d\n", status); - return status; + table = acpi_table_get(argv[1], 0); + if (!table) { + shell_error(sh, "ACPI get table %s failed", argv[1]); + return -EIO; } - shell_print(sh, "ACPI Table Info:\n"); - shell_print(sh, "Signature: %4s Table Length:%d Revision:%d OemId:%s\n", - table->Signature, table->Length, table->Revision, table->OemId); + shell_print(sh, "ACPI Table %s:", argv[1]); + shell_print(sh, "\tSignature: %.4s", table->Signature); + shell_print(sh, "\tTable Length: %d", table->Length); + shell_print(sh, "\tRevision: %d", table->Revision); + shell_print(sh, "\tOemId: %s", table->OemId); return 0; } @@ -267,8 +268,9 @@ SHELL_STATIC_SUBCMD_SET_CREATE( SHELL_CMD(prs, NULL, "display device possible resource settings (eg:acpi crs _SB.PC00.LPCB.RTC)", dump_dev_prs), - SHELL_CMD(prt, NULL, "display PRT details for a given bus (eg:acpi prt _SB.PC00)", - dump_prt), + SHELL_COND_CMD(CONFIG_PCIE_PRT, prt, NULL, + "display PRT details for a given bus (eg:acpi prt _SB.PC00)", + dump_prt), SHELL_CMD(enum, NULL, "enumerate device using hid (for enum HPET timer device,eg:acpi enum PNP0103)", enum_dev), diff --git a/lib/cpp/Kconfig b/lib/cpp/Kconfig index 52084fbe690..6ac4dae170a 100644 --- a/lib/cpp/Kconfig +++ b/lib/cpp/Kconfig @@ -74,6 +74,7 @@ config FULL_LIBCPP_SUPPORTED choice LIBCPP_IMPLEMENTATION prompt "C++ Standard Library Implementation" default EXTERNAL_LIBCPP if REQUIRES_FULL_LIBCPP && NATIVE_BUILD + default LIBCXX_LIBCPP if REQUIRES_FULL_LIBCPP && "$(ZEPHYR_TOOLCHAIN_VARIANT)" = "llvm" default GLIBCXX_LIBCPP if REQUIRES_FULL_LIBCPP default MINIMAL_LIBCPP @@ -96,6 +97,17 @@ config GLIBCXX_LIBCPP Build with GNU C++ Standard Library (libstdc++) provided by the GNU Compiler Collection (GCC)-based toolchain. +config LIBCXX_LIBCPP + bool "LLVM C++ Standard Library" + depends on !NATIVE_APPLICATION + depends on NEWLIB_LIBC + depends on "$(ZEPHYR_TOOLCHAIN_VARIANT)" = "llvm" + select FULL_LIBCPP_SUPPORTED + help + Build with LLVM C++ Standard Library (libc++) provided by LLVM + toolchain. Information about library can be found at + https://libcxx.llvm.org + config ARCMWDT_LIBCPP bool "ARC MWDT C++ Library" depends on !NATIVE_APPLICATION @@ -107,7 +119,12 @@ config ARCMWDT_LIBCPP config EXTERNAL_LIBCPP bool "External C++ standard library" help - Build with an external/user-provided C++ standard library. + Build and link with an external/user-provided C++ standard library. + +config EXTERNAL_MODULE_LIBCPP + bool "External C++ standard library module" + help + Build an external/user-provided C++ standard library. endchoice # LIBCPP_IMPLEMENTATION diff --git a/lib/crc/CMakeLists.txt b/lib/crc/CMakeLists.txt index bf652ba4fcf..a85cc3b05cc 100644 --- a/lib/crc/CMakeLists.txt +++ b/lib/crc/CMakeLists.txt @@ -6,5 +6,6 @@ zephyr_sources_ifdef(CONFIG_CRC crc16_sw.c crc8_sw.c crc7_sw.c + crc4_sw.c ) zephyr_sources_ifdef(CONFIG_CRC_SHELL crc_shell.c) diff --git a/lib/crc/crc4_sw.c b/lib/crc/crc4_sw.c new file mode 100644 index 00000000000..e636a2c8fae --- /dev/null +++ b/lib/crc/crc4_sw.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023 Michal Morsisko + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +uint8_t crc4(const uint8_t *src, size_t len, uint8_t polynomial, uint8_t initial_value, + bool reversed) +{ + uint8_t crc = initial_value; + size_t i, j, k; + + for (i = 0; i < len; i++) { + for (j = 0; j < 2; j++) { + crc ^= ((src[i] >> (4 * (1 - j))) & 0xf); + + for (k = 0; k < 4; k++) { + if (reversed) { + if (crc & 0x01) { + crc = (crc >> 1) ^ polynomial; + } else { + crc >>= 1; + } + } else { + if (crc & 0x8) { + crc = (crc << 1) ^ polynomial; + } else { + crc <<= 1; + } + } + } + } + } + + return crc & 0xF; +} + +uint8_t crc4_ti(uint8_t seed, const uint8_t *src, size_t len) +{ + static const uint8_t lookup[8] = { 0x03, 0x65, 0xcf, 0xa9, 0xb8, 0xde, 0x74, 0x12 }; + uint8_t index; + + for (size_t i = 0; i < len; i++) { + for (size_t j = 0U; j < 2U; j++) { + index = seed ^ ((src[i] >> (4*(1-j))) & 0xf); + seed = (lookup[index >> 1] >> (1 - (index & 1)) * 4) & 0xf; + } + } + + return seed; +} diff --git a/lib/libc/Kconfig b/lib/libc/Kconfig index 522bd4a57b3..8b71808ff54 100644 --- a/lib/libc/Kconfig +++ b/lib/libc/Kconfig @@ -10,6 +10,14 @@ config REQUIRES_FULL_LIBC Select a C library implementation that provides a complete C library implementation, rather than the subset provided by MINIMAL_LIBC. +config REQUIRES_FLOAT_PRINTF + bool "Requires floating point support in printf" + select CBPRINTF_FP_SUPPORT if MINIMAL_LIBC + select NEWLIB_LIBC_FLOAT_PRINTF if NEWLIB_LIBC + help + Select a printf implementation that provides a complete + implementation including floating point support. + config FULL_LIBC_SUPPORTED bool help @@ -35,8 +43,8 @@ config NEWLIB_LIBC_SUPPORTED config PICOLIBC_SUPPORTED bool depends on !NATIVE_APPLICATION - depends on ("$(ZEPHYR_TOOLCHAIN_VARIANT)" = "zephyr") || (NATIVE_LIBRARY) - depends on !(CPP && "$(ZEPHYR_TOOLCHAIN_VARIANT)" = "zephyr") + depends on ("$(TOOLCHAIN_HAS_PICOLIBC)" = "y") || (NATIVE_LIBRARY) + depends on !REQUIRES_FULL_LIBCPP || ("$(TOOLCHAIN_HAS_PICOLIBC)" = "y") default y select FULL_LIBC_SUPPORTED help @@ -53,7 +61,7 @@ menu "C Library" choice LIBC_IMPLEMENTATION prompt "C Library Implementation" - default EXTERNAL_LIBC if NATIVE_BUILD + default EXTERNAL_LIBC if NATIVE_BUILD && !(NATIVE_LIBRARY && POSIX_API) default PICOLIBC default NEWLIB_LIBC if REQUIRES_FULL_LIBC default MINIMAL_LIBC @@ -72,8 +80,9 @@ config MINIMAL_LIBC config PICOLIBC bool "Picolibc library" select COMMON_LIBC_ABORT - select THREAD_LOCAL_STORAGE if ARCH_HAS_THREAD_LOCAL_STORAGE && TOOLCHAIN_SUPPORTS_THREAD_LOCAL_STORAGE + imply THREAD_LOCAL_STORAGE if ARCH_HAS_THREAD_LOCAL_STORAGE && TOOLCHAIN_SUPPORTS_THREAD_LOCAL_STORAGE select LIBC_ERRNO if THREAD_LOCAL_STORAGE + select NEED_LIBC_MEM_PARTITION imply COMMON_LIBC_MALLOC depends on !NATIVE_APPLICATION depends on PICOLIBC_SUPPORTED @@ -87,6 +96,7 @@ config NEWLIB_LIBC select COMMON_LIBC_ABORT depends on !NATIVE_APPLICATION depends on NEWLIB_LIBC_SUPPORTED + select NEED_LIBC_MEM_PARTITION help Build with newlib library. The newlib library is expected to be part of the SDK in this case. diff --git a/lib/libc/arcmwdt/libc-hooks.c b/lib/libc/arcmwdt/libc-hooks.c index b7ee5f90a81..babf24ebda8 100644 --- a/lib/libc/arcmwdt/libc-hooks.c +++ b/lib/libc/arcmwdt/libc-hooks.c @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include #include @@ -56,7 +56,7 @@ int z_impl_zephyr_write_stdout(const void *buffer, int nbytes) #ifdef CONFIG_USERSPACE static inline int z_vrfy_zephyr_write_stdout(const void *buf, int nbytes) { - Z_OOPS(Z_SYSCALL_MEMORY_READ(buf, nbytes)); + K_OOPS(K_SYSCALL_MEMORY_READ(buf, nbytes)); return z_impl_zephyr_write_stdout(buf, nbytes); } #include diff --git a/lib/libc/armstdc/src/libc-hooks.c b/lib/libc/armstdc/src/libc-hooks.c index 4884c391465..afce534eddf 100644 --- a/lib/libc/armstdc/src/libc-hooks.c +++ b/lib/libc/armstdc/src/libc-hooks.c @@ -25,3 +25,8 @@ volatile int *__aeabi_errno_addr(void) { return &_current->errno_var; } + +int fputc(int c, FILE *f) +{ + return (_stdout_hook)(c); +} diff --git a/lib/libc/armstdc/src/threading_weak.c b/lib/libc/armstdc/src/threading_weak.c index 2f1b31a8745..f94f48766a6 100644 --- a/lib/libc/armstdc/src/threading_weak.c +++ b/lib/libc/armstdc/src/threading_weak.c @@ -49,7 +49,7 @@ int __weak z_impl_k_sem_take(struct k_sem *sem, k_timeout_t timeout) return 0; } -k_tid_t __weak z_impl_z_current_get(void) +k_tid_t __weak z_impl_k_sched_current_thread_query(void) { return 0; } diff --git a/lib/libc/common/CMakeLists.txt b/lib/libc/common/CMakeLists.txt index 48372158ea5..4b101d8b84b 100644 --- a/lib/libc/common/CMakeLists.txt +++ b/lib/libc/common/CMakeLists.txt @@ -1,8 +1,20 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_system_include_directories(include) + zephyr_library() zephyr_library_property(ALLOW_EMPTY TRUE) zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_ABORT source/stdlib/abort.c) zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_TIME source/time/time.c) zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_MALLOC source/stdlib/malloc.c) zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_STRNLEN source/string/strnlen.c) +zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_THRD + source/thrd/cnd.c + source/thrd/mtx.c + source/thrd/once.c + source/thrd/thrd.c + source/thrd/tss.c + ) + +# Prevent compiler from optimizing calloc into an infinite recursive call +zephyr_library_compile_options($) diff --git a/lib/libc/common/Kconfig b/lib/libc/common/Kconfig index e4bcf9a72f2..dc22d0c2108 100644 --- a/lib/libc/common/Kconfig +++ b/lib/libc/common/Kconfig @@ -13,6 +13,7 @@ config COMMON_LIBC_TIME config COMMON_LIBC_MALLOC bool "Common C library malloc implementation" + select NEED_LIBC_MEM_PARTITION if COMMON_LIBC_MALLOC_ARENA_SIZE != 0 help Common implementation of malloc family that uses the kernel heap API. @@ -66,3 +67,13 @@ config COMMON_LIBC_STRNLEN bool help common implementation of strnlen(). + +config COMMON_LIBC_THRD + bool "C11 API support" + depends on DYNAMIC_THREAD + # Note: the POSIX_API dependency is only necessary until common elements + # of C11 threads and POSIX API can be abstracted out to a common library. + depends on POSIX_API + default y + help + Common implementation of C11 API. diff --git a/lib/libc/common/include/machine/_threads.h b/lib/libc/common/include/machine/_threads.h new file mode 100644 index 00000000000..578536ca5c6 --- /dev/null +++ b/lib/libc/common/include/machine/_threads.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_LIB_LIBC_COMMON_INCLUDE_MACHINE__THREADS_H_ +#define ZEPHYR_LIB_LIBC_COMMON_INCLUDE_MACHINE__THREADS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define ONCE_FLAG_INIT \ + { \ + 1, 0 \ + } + +typedef int cnd_t; +typedef int mtx_t; +typedef int thrd_t; +typedef int tss_t; +typedef struct { + int is_initialized; + int init_executed; +} once_flag; + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_LIB_LIBC_COMMON_INCLUDE_MACHINE__THREADS_H_ */ diff --git a/lib/libc/common/include/threads.h b/lib/libc/common/include/threads.h new file mode 100644 index 00000000000..b2a8c738389 --- /dev/null +++ b/lib/libc/common/include/threads.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2023, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_LIB_LIBC_COMMON_INCLUDE_THREADS_H_ +#define ZEPHYR_LIB_LIBC_COMMON_INCLUDE_THREADS_H_ + +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int (*thrd_start_t)(void *arg); + +enum { + thrd_success, +#define thrd_success thrd_success + thrd_nomem, +#define thrd_nomem thrd_nomem + thrd_timedout, +#define thrd_timedout thrd_timedout + thrd_busy, +#define thrd_busy thrd_busy + thrd_error, +#define thrd_error thrd_error +}; + +int thrd_create(thrd_t *thr, thrd_start_t func, void *arg); +int thrd_equal(thrd_t lhs, thrd_t rhs); +thrd_t thrd_current(void); +int thrd_sleep(const struct timespec *duration, struct timespec *remaining); +void thrd_yield(void); +_Noreturn void thrd_exit(int res); +int thrd_detach(thrd_t thr); +int thrd_join(thrd_t thr, int *res); + +enum { + mtx_plain, +#define mtx_plain mtx_plain + mtx_timed, +#define mtx_timed mtx_timed + mtx_recursive, +#define mtx_recursive mtx_recursive +}; + +int mtx_init(mtx_t *mutex, int type); +void mtx_destroy(mtx_t *mutex); +int mtx_lock(mtx_t *mutex); +int mtx_timedlock(mtx_t *ZRESTRICT mutex, const struct timespec *ZRESTRICT time_point); +int mtx_trylock(mtx_t *mutex); +int mtx_unlock(mtx_t *mutex); + +int cnd_init(cnd_t *cond); +int cnd_wait(cnd_t *cond, mtx_t *mtx); +int cnd_timedwait(cnd_t *ZRESTRICT cond, mtx_t *ZRESTRICT mtx, const struct timespec *ZRESTRICT ts); +int cnd_signal(cnd_t *cond); +int cnd_broadcast(cnd_t *cond); +void cnd_destroy(cnd_t *cond); + +#ifndef thread_local +#define thread_local _Thread_local +#endif + +typedef void (*tss_dtor_t)(void *val); + +int tss_create(tss_t *key, tss_dtor_t destructor); +void *tss_get(tss_t key); +int tss_set(tss_t key, void *val); +void tss_delete(tss_t key); + +void call_once(once_flag *flag, void (*func)(void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_LIB_LIBC_COMMON_INCLUDE_THREADS_H_ */ diff --git a/lib/libc/common/source/stdlib/malloc.c b/lib/libc/common/source/stdlib/malloc.c index 47583982838..2f469d673e4 100644 --- a/lib/libc/common/source/stdlib/malloc.c +++ b/lib/libc/common/source/stdlib/malloc.c @@ -11,12 +11,14 @@ #include #include #include +#ifdef CONFIG_MULTITHREADING #include +#endif #include #include #include #ifdef CONFIG_MMU -#include +#include #endif #define LOG_LEVEL CONFIG_KERNEL_LOG_LEVEL @@ -45,10 +47,8 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); # if Z_MALLOC_PARTITION_EXISTS K_APPMEM_PARTITION_DEFINE(z_malloc_partition); # define POOL_SECTION Z_GENERIC_SECTION(K_APP_DMEM_SECTION(z_malloc_partition)) -# define MALLOC_SECTION Z_GENERIC_SECTION(K_APP_DMEM_SECTION(z_malloc_partition)) # else # define POOL_SECTION __noinit -# define MALLOC_SECTION # endif /* CONFIG_USERSPACE */ # if defined(CONFIG_MMU) && CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE < 0 @@ -89,6 +89,8 @@ K_APPMEM_PARTITION_DEFINE(z_malloc_partition); # if CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE > 0 +# define HEAP_STATIC + /* Static allocation of heap in BSS */ # define HEAP_SIZE ROUND_UP(CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE, HEAP_ALIGN) @@ -126,15 +128,32 @@ extern char _heap_sentry[]; # endif /* else ALLOCATE_HEAP_AT_STARTUP */ -POOL_SECTION static struct sys_heap z_malloc_heap; -MALLOC_SECTION SYS_MUTEX_DEFINE(z_malloc_heap_mutex); +Z_LIBC_DATA static struct sys_heap z_malloc_heap; -void *malloc(size_t size) -{ +#ifdef CONFIG_MULTITHREADING +Z_LIBC_DATA SYS_MUTEX_DEFINE(z_malloc_heap_mutex); + +static inline void +malloc_lock(void) { int lock_ret; lock_ret = sys_mutex_lock(&z_malloc_heap_mutex, K_FOREVER); __ASSERT_NO_MSG(lock_ret == 0); +} + +static inline void +malloc_unlock(void) +{ + (void) sys_mutex_unlock(&z_malloc_heap_mutex); +} +#else +#define malloc_lock() +#define malloc_unlock() +#endif + +void *malloc(size_t size) +{ + malloc_lock(); void *ret = sys_heap_aligned_alloc(&z_malloc_heap, __alignof__(z_max_align_t), @@ -143,17 +162,14 @@ void *malloc(size_t size) errno = ENOMEM; } - (void) sys_mutex_unlock(&z_malloc_heap_mutex); + malloc_unlock(); return ret; } void *aligned_alloc(size_t alignment, size_t size) { - int lock_ret; - - lock_ret = sys_mutex_lock(&z_malloc_heap_mutex, K_FOREVER); - __ASSERT_NO_MSG(lock_ret == 0); + malloc_lock(); void *ret = sys_heap_aligned_alloc(&z_malloc_heap, alignment, @@ -162,7 +178,7 @@ void *aligned_alloc(size_t alignment, size_t size) errno = ENOMEM; } - (void) sys_mutex_unlock(&z_malloc_heap_mutex); + malloc_unlock(); return ret; } @@ -223,7 +239,7 @@ static int malloc_prepare(void) heap_size = HEAP_SIZE; #endif -#if Z_MALLOC_PARTITION_EXISTS +#if Z_MALLOC_PARTITION_EXISTS && !defined(HEAP_STATIC) z_malloc_partition.start = POINTER_TO_UINT(heap_base); z_malloc_partition.size = heap_size; z_malloc_partition.attr = K_MEM_PARTITION_P_RW_U_RW; @@ -236,10 +252,7 @@ static int malloc_prepare(void) void *realloc(void *ptr, size_t requested_size) { - int lock_ret; - - lock_ret = sys_mutex_lock(&z_malloc_heap_mutex, K_FOREVER); - __ASSERT_NO_MSG(lock_ret == 0); + malloc_lock(); void *ret = sys_heap_aligned_realloc(&z_malloc_heap, ptr, __alignof__(z_max_align_t), @@ -249,19 +262,16 @@ void *realloc(void *ptr, size_t requested_size) errno = ENOMEM; } - (void) sys_mutex_unlock(&z_malloc_heap_mutex); + malloc_unlock(); return ret; } void free(void *ptr) { - int lock_ret; - - lock_ret = sys_mutex_lock(&z_malloc_heap_mutex, K_FOREVER); - __ASSERT_NO_MSG(lock_ret == 0); + malloc_lock(); sys_heap_free(&z_malloc_heap, ptr); - (void) sys_mutex_unlock(&z_malloc_heap_mutex); + malloc_unlock(); } SYS_INIT(malloc_prepare, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/lib/libc/common/source/thrd/cnd.c b/lib/libc/common/source/thrd/cnd.c new file mode 100644 index 00000000000..aea6f5cb78a --- /dev/null +++ b/lib/libc/common/source/thrd/cnd.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2023, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +int cnd_broadcast(cnd_t *cond) +{ + switch (pthread_cond_broadcast(cond)) { + case 0: + return thrd_success; + default: + return thrd_error; + } +} + +void cnd_destroy(cnd_t *cond) +{ + (void)pthread_cond_destroy(cond); +} + +int cnd_init(cnd_t *cond) +{ + switch (pthread_cond_init(cond, NULL)) { + case 0: + return thrd_success; + case ENOMEM: + return thrd_nomem; + default: + return thrd_error; + } +} + +int cnd_signal(cnd_t *cond) +{ + switch (pthread_cond_signal(cond)) { + case 0: + return thrd_success; + case ENOMEM: + return thrd_nomem; + default: + return thrd_error; + } +} + +int cnd_timedwait(cnd_t *restrict cond, mtx_t *restrict mtx, const struct timespec *restrict ts) +{ + switch (pthread_cond_timedwait(cond, mtx, ts)) { + case 0: + return thrd_success; + case ETIMEDOUT: + return thrd_timedout; + default: + return thrd_error; + } +} + +int cnd_wait(cnd_t *cond, mtx_t *mtx) +{ + switch (pthread_cond_wait(cond, mtx)) { + case 0: + return thrd_success; + default: + return thrd_error; + } +} diff --git a/lib/libc/common/source/thrd/mtx.c b/lib/libc/common/source/thrd/mtx.c new file mode 100644 index 00000000000..9746ea64fe6 --- /dev/null +++ b/lib/libc/common/source/thrd/mtx.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2023, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include + +int mtx_init(mtx_t *mutex, int type) +{ + int ret; + pthread_mutexattr_t attr; + pthread_mutexattr_t *attrp = NULL; + + switch (type) { + case mtx_plain: + case mtx_timed: + break; + case mtx_plain | mtx_recursive: + case mtx_timed | mtx_recursive: + attrp = &attr; + ret = pthread_mutexattr_init(attrp); + __ASSERT_NO_MSG(ret == 0); + + ret = pthread_mutexattr_settype(attrp, PTHREAD_MUTEX_RECURSIVE); + __ASSERT_NO_MSG(ret == 0); + break; + default: + return thrd_error; + } + + switch (pthread_mutex_init(mutex, attrp)) { + case 0: + ret = thrd_success; + break; + default: + ret = thrd_error; + break; + } + + if (attrp != NULL) { + (void)pthread_mutexattr_destroy(attrp); + } + + return ret; +} + +void mtx_destroy(mtx_t *mutex) +{ + (void)pthread_mutex_destroy(mutex); +} + +int mtx_lock(mtx_t *mutex) +{ + switch (pthread_mutex_lock(mutex)) { + case 0: + return thrd_success; + default: + return thrd_error; + } +} + +int mtx_timedlock(mtx_t *restrict mutex, const struct timespec *restrict time_point) +{ + switch (pthread_mutex_timedlock(mutex, time_point)) { + case 0: + return thrd_success; + case ETIMEDOUT: + return thrd_timedout; + default: + return thrd_error; + } +} + +int mtx_trylock(mtx_t *mutex) +{ + switch (pthread_mutex_trylock(mutex)) { + case 0: + return thrd_success; + case EBUSY: + return thrd_busy; + default: + return thrd_error; + } +} + +int mtx_unlock(mtx_t *mutex) +{ + switch (pthread_mutex_unlock(mutex)) { + case 0: + return thrd_success; + default: + return thrd_error; + } +} diff --git a/lib/libc/common/source/thrd/once.c b/lib/libc/common/source/thrd/once.c new file mode 100644 index 00000000000..7cfd9983df8 --- /dev/null +++ b/lib/libc/common/source/thrd/once.c @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2023, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include + +void call_once(once_flag *flag, void (*func)(void)) +{ + (void)pthread_once((pthread_once_t *)flag, func); +} diff --git a/lib/libc/common/source/thrd/thrd.c b/lib/libc/common/source/thrd/thrd.c new file mode 100644 index 00000000000..d811fe31ce6 --- /dev/null +++ b/lib/libc/common/source/thrd/thrd.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2023, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include + +struct thrd_trampoline_arg { + thrd_start_t func; + void *arg; +}; + +int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) +{ + typedef void *(*pthread_func_t)(void *arg); + + pthread_func_t pfunc = (pthread_func_t)func; + + switch (pthread_create(thr, NULL, pfunc, arg)) { + case 0: + return thrd_success; + case EAGAIN: + return thrd_nomem; + default: + return thrd_error; + } +} + +int thrd_equal(thrd_t lhs, thrd_t rhs) +{ + return pthread_equal(lhs, rhs); +} + +thrd_t thrd_current(void) +{ + return pthread_self(); +} + +int thrd_sleep(const struct timespec *duration, struct timespec *remaining) +{ + return nanosleep(duration, remaining); +} + +void thrd_yield(void) +{ + (void)sched_yield(); +} + +FUNC_NORETURN void thrd_exit(int res) +{ + pthread_exit(INT_TO_POINTER(res)); + + CODE_UNREACHABLE; +} + +int thrd_detach(thrd_t thr) +{ + switch (pthread_detach(thr)) { + case 0: + return thrd_success; + default: + return thrd_error; + } +} + +int thrd_join(thrd_t thr, int *res) +{ + void *ret; + + switch (pthread_join(thr, &ret)) { + case 0: + if (res != NULL) { + *res = POINTER_TO_INT(ret); + } + return thrd_success; + default: + return thrd_error; + } +} diff --git a/lib/libc/common/source/thrd/tss.c b/lib/libc/common/source/thrd/tss.c new file mode 100644 index 00000000000..4b110d17170 --- /dev/null +++ b/lib/libc/common/source/thrd/tss.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include + +int tss_create(tss_t *key, tss_dtor_t destructor) +{ + switch (pthread_key_create(key, destructor)) { + case 0: + return thrd_success; + case EAGAIN: + return thrd_busy; + case ENOMEM: + return thrd_nomem; + default: + return thrd_error; + } +} + +void *tss_get(tss_t key) +{ + return pthread_getspecific(key); +} + +int tss_set(tss_t key, void *val) +{ + switch (pthread_setspecific(key, val)) { + case 0: + return thrd_success; + case ENOMEM: + return thrd_nomem; + default: + return thrd_error; + } +} + +void tss_delete(tss_t key) +{ + (void)pthread_key_delete(key); +} diff --git a/lib/libc/minimal/CMakeLists.txt b/lib/libc/minimal/CMakeLists.txt index 71a404e7870..abcab108e52 100644 --- a/lib/libc/minimal/CMakeLists.txt +++ b/lib/libc/minimal/CMakeLists.txt @@ -7,7 +7,7 @@ zephyr_library() set(GEN_DIR ${ZEPHYR_BINARY_DIR}/include/generated) set(STRERROR_TABLE_H ${GEN_DIR}/libc/minimal/strerror_table.h) -zephyr_library_cc_option(-fno-builtin) +zephyr_library_compile_options($) zephyr_library_sources( source/stdlib/atoi.c diff --git a/lib/libc/minimal/source/stdout/stdout_console.c b/lib/libc/minimal/source/stdout/stdout_console.c index 8db7528497e..33ea7ffaa66 100644 --- a/lib/libc/minimal/source/stdout/stdout_console.c +++ b/lib/libc/minimal/source/stdout/stdout_console.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include static int _stdout_hook_default(int c) @@ -101,7 +101,7 @@ static inline size_t z_vrfy_zephyr_fwrite(const void *ZRESTRICT ptr, FILE *ZRESTRICT stream) { - Z_OOPS(Z_SYSCALL_MEMORY_ARRAY_READ(ptr, nitems, size)); + K_OOPS(K_SYSCALL_MEMORY_ARRAY_READ(ptr, nitems, size)); return z_impl_zephyr_fwrite((const void *ZRESTRICT)ptr, size, nitems, (FILE *ZRESTRICT)stream); } diff --git a/lib/libc/newlib/CMakeLists.txt b/lib/libc/newlib/CMakeLists.txt index 856befd3811..6556a3e814c 100644 --- a/lib/libc/newlib/CMakeLists.txt +++ b/lib/libc/newlib/CMakeLists.txt @@ -37,39 +37,41 @@ zephyr_compile_definitions(_ANSI_SOURCE) # used by the network stack zephyr_compile_definitions(__LINUX_ERRNO_EXTENSIONS__) -# We are using -# - ${CMAKE_C_LINKER_WRAPPER_FLAG}${CMAKE_LINK_LIBRARY_FLAG}c -# - ${CMAKE_C_LINKER_WRAPPER_FLAG}${CMAKE_LINK_LIBRARY_FLAG}gcc -# - c -# in code below. -# This is needed because when linking with newlib on aarch64, then libgcc has a -# link dependency to libc (strchr), but libc also has dependencies to libgcc. -# -# CMake is capable of handling circular link dependencies for CMake defined -# static libraries, which can be further controlled using LINK_INTERFACE_MULTIPLICITY. -# However, libc and libgcc are not regular CMake libraries, and is seen as linker -# flags by CMake, and thus symbol de-duplications will be performed. -# CMake link options cannot be used, as that will place those libs first on the -# linker invocation. -Wl,--start-group is problematic as the placement of -lc -# and -lgcc is not guaranteed in case later libraries are also using -# -lc / -libbgcc as interface linker flags. -# -# Thus, we resort to use `${CMAKE_C_LINKER_WRAPPER_FLAG}${CMAKE_LINK_LIBRARY_FLAG}` -# as this ensures the uniqueness and thus avoids symbol de-duplication which means -# libc will be followed by libgcc, which is finally followed by libc again. +if(CMAKE_C_COMPILER_ID STREQUAL "GNU") + # We are using + # - ${CMAKE_C_LINKER_WRAPPER_FLAG}${CMAKE_LINK_LIBRARY_FLAG}c + # - ${CMAKE_C_LINKER_WRAPPER_FLAG}${CMAKE_LINK_LIBRARY_FLAG}gcc + # - c + # in code below. + # This is needed because when linking with newlib on aarch64, then libgcc has a + # link dependency to libc (strchr), but libc also has dependencies to libgcc. + # + # CMake is capable of handling circular link dependencies for CMake defined + # static libraries, which can be further controlled using LINK_INTERFACE_MULTIPLICITY. + # However, libc and libgcc are not regular CMake libraries, and is seen as linker + # flags by CMake, and thus symbol de-duplications will be performed. + # CMake link options cannot be used, as that will place those libs first on the + # linker invocation. -Wl,--start-group is problematic as the placement of -lc + # and -lgcc is not guaranteed in case later libraries are also using + # -lc / -libbgcc as interface linker flags. + # + # Thus, we resort to use `${CMAKE_C_LINKER_WRAPPER_FLAG}${CMAKE_LINK_LIBRARY_FLAG}` + # as this ensures the uniqueness and thus avoids symbol de-duplication which means + # libc will be followed by libgcc, which is finally followed by libc again. -list(JOIN CMAKE_C_LINKER_WRAPPER_FLAG "" linker_wrapper_string) + list(JOIN CMAKE_C_LINKER_WRAPPER_FLAG "" linker_wrapper_string) -zephyr_link_libraries( - m - "${linker_wrapper_string}${CMAKE_LINK_LIBRARY_FLAG}c" - ${LIBC_LIBRARY_DIR_FLAG} # NB: Optional - $<$:-u_printf_float> - $<$:-u_scanf_float> - # Lib C depends on libgcc. e.g. libc.a(lib_a-fvwrite.o) references __aeabi_idiv - "${linker_wrapper_string}${CMAKE_LINK_LIBRARY_FLAG}gcc" - c - ) + zephyr_link_libraries( + m + "${linker_wrapper_string}${CMAKE_LINK_LIBRARY_FLAG}c" + ${LIBC_LIBRARY_DIR_FLAG} # NB: Optional + $<$:-u_printf_float> + $<$:-u_scanf_float> + # Lib C depends on libgcc. e.g. libc.a(lib_a-fvwrite.o) references __aeabi_idiv + "${linker_wrapper_string}${CMAKE_LINK_LIBRARY_FLAG}gcc" + ) +endif() +zephyr_link_libraries(c) if(CONFIG_NEWLIB_LIBC_NANO) zephyr_link_libraries( diff --git a/lib/libc/newlib/libc-hooks.c b/lib/libc/newlib/libc-hooks.c index 1769e32dc14..7e066a2817f 100644 --- a/lib/libc/newlib/libc-hooks.c +++ b/lib/libc/newlib/libc-hooks.c @@ -15,12 +15,12 @@ #include #include #include -#include +#include #include #include #include #include -#include +#include #include #define LIBC_BSS K_APP_BMEM(z_libc_partition) @@ -181,7 +181,7 @@ int z_impl_zephyr_read_stdin(char *buf, int nbytes) #ifdef CONFIG_USERSPACE static inline int z_vrfy_zephyr_read_stdin(char *buf, int nbytes) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(buf, nbytes)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(buf, nbytes)); return z_impl_zephyr_read_stdin((char *)buf, nbytes); } #include @@ -204,7 +204,7 @@ int z_impl_zephyr_write_stdout(const void *buffer, int nbytes) #ifdef CONFIG_USERSPACE static inline int z_vrfy_zephyr_write_stdout(const void *buf, int nbytes) { - Z_OOPS(Z_SYSCALL_MEMORY_READ(buf, nbytes)); + K_OOPS(K_SYSCALL_MEMORY_READ(buf, nbytes)); return z_impl_zephyr_write_stdout((const void *)buf, nbytes); } #include diff --git a/lib/libc/picolibc/CMakeLists.txt b/lib/libc/picolibc/CMakeLists.txt index 3bbe8128a1f..232e4ba8fc1 100644 --- a/lib/libc/picolibc/CMakeLists.txt +++ b/lib/libc/picolibc/CMakeLists.txt @@ -17,6 +17,12 @@ if(NOT CONFIG_PICOLIBC_USE_MODULE) if(CONFIG_PICOLIBC_IO_FLOAT) zephyr_compile_definitions(PICOLIBC_DOUBLE_PRINTF_SCANF) zephyr_link_libraries(-DPICOLIBC_DOUBLE_PRINTF_SCANF) + elseif(CONFIG_PICOLIBC_IO_MINIMAL) + zephyr_compile_definitions(PICOLIBC_MINIMAL_PRINTF_SCANF) + zephyr_link_libraries(-DPICOLIBC_MINIMAL_PRINTF_SCANF) + elseif(CONFIG_PICOLIBC_IO_LONG_LONG) + zephyr_compile_definitions(PICOLIBC_LONG_LONG_PRINTF_SCANF) + zephyr_link_libraries(-DPICOLIBC_LONG_LONG_PRINTF_SCANF) else() zephyr_compile_definitions(PICOLIBC_INTEGER_PRINTF_SCANF) zephyr_link_libraries(-DPICOLIBC_INTEGER_PRINTF_SCANF) diff --git a/lib/libc/picolibc/Kconfig b/lib/libc/picolibc/Kconfig index 659cbf41db6..fa6ae7e6e9b 100644 --- a/lib/libc/picolibc/Kconfig +++ b/lib/libc/picolibc/Kconfig @@ -4,8 +4,8 @@ if PICOLIBC config PICOLIBC_USE_MODULE - bool "Picolibc as module" - default y if "$(ZEPHYR_TOOLCHAIN_VARIANT)" != "zephyr" + bool "Picolibc as module" if "$(TOOLCHAIN_HAS_PICOLIBC)" = "y" + default y if "$(TOOLCHAIN_HAS_PICOLIBC)" != "y" depends on ZEPHYR_PICOLIBC_MODULE depends on !GLIBCXX_LIBCPP help @@ -13,6 +13,12 @@ config PICOLIBC_USE_MODULE This is enabled by default for toolchains other than the Zephyr SDK. +# force TLS when using toolchain with TLS support +config PICOLIBC_USE_TOOLCHAIN + bool + default y if PICOLIBC && !PICOLIBC_USE_MODULE + select THREAD_LOCAL_STORAGE if ARCH_HAS_THREAD_LOCAL_STORAGE && TOOLCHAIN_SUPPORTS_THREAD_LOCAL_STORAGE + config PICOLIBC_HEAP_SIZE int "[DEPRECATED] Picolibc heap size (bytes)" default -2 @@ -25,16 +31,42 @@ config PICOLIBC_HEAP_SIZE If set to -2, then the value of COMMON_LIBC_MALLOC_ARENA_SIZE will be used. -config PICOLIBC_IO_LONG_LONG - bool "support for long long in integer-only printf/scanf" +choice PICOLIBC_IO_LEVEL + prompt "Picolibc printf/scanf level" + default PICOLIBC_IO_MINIMAL if CBPRINTF_NANO + default PICOLIBC_IO_LONG_LONG if CBPRINTF_FULL_INTEGRAL + default PICOLIBC_IO_INTEGER help - Includes support for long long in integer-only printf/scanf. long long - types are always supported in the floating-point versions. + Selects the level of printf and scanf support config PICOLIBC_IO_FLOAT - bool "support for floating point values in printf/scanf" + bool "full support for integer/floating point values in printf/scanf" + help + Include full floating point and integer support in printf/scanf + functions. + +config PICOLIBC_IO_LONG_LONG + bool "full support for integer values, including long long, in printf/scanf" + depends on !REQUIRES_FLOAT_PRINTF && (!CBPRINTF_FP_SUPPORT || CBPRINTF_NANO) + help + Includes full integer with long long, but no floating + point in printf/scanf. + +config PICOLIBC_IO_INTEGER + bool "full support for integer values, other than long long, in printf/scanf" + depends on !REQUIRES_FLOAT_PRINTF && ((!CBPRINTF_FP_SUPPORT && !CBPRINTF_FULL_INTEGRAL) || CBPRINTF_NANO) + help + Include full integer other than long long, but no floating point + in printf/scanf. + +config PICOLIBC_IO_MINIMAL + bool "limited support for integer values in printf/scanf" + depends on !REQUIRES_FLOAT_PRINTF && CBPRINTF_NANO help - Include floating point support in printf/scanf functions. + Include limited integer and no floating point support in + printf/scanf. + +endchoice if PICOLIBC_USE_MODULE @@ -82,21 +114,31 @@ config PICOLIBC_FAST_STRCMP This provides a faster strcmp version even when libc is built in space-optimized mode +config PICOLIBC_ASSERT_VERBOSE + bool "assert provides verbose information" + help + The usual picolibc assert helper, __assert_func, takes file, line, + function and expression information to make the presented message + more helpful. These all require storage in the image. Unselecting + this option eliminates all of that information, making the results + less helpful but also making them consume less memory. + config PICOLIBC_IO_C99_FORMATS bool "support C99 format additions in printf/scanf" default y help - Includes support for hex floats (in floating-point version) and j, z, - t size modifiers. + Includes C99 printf and scanf support for j, z, t size + modifiers. C99 support is always included in the floating-point + variant config PICOLIBC_IO_POS_ARGS bool "Support POSIX positional args (e.g. %$1d) in printf/scanf" default y - depends on !PICOLIBC_IO_FLOAT + depends on !PICOLIBC_IO_MINIMAL help - Includes support for positional args (e.g. $1) in integer-only printf - and scanf. Positional args are always supported in the floating-point - versions. + Includes support for positional args (e.g. $1) in integer-only + printf and scanf. Positional args are always supported in the + floating-point variant. config PICOLIBC_IO_FLOAT_EXACT bool "support for exact float/string conversion" @@ -106,6 +148,21 @@ config PICOLIBC_IO_FLOAT_EXACT This ensures that printf values with enough digits can be fed to scanf and generate exactly the same binary value. +config PICOLIBC_IO_SMALL_ULTOA + bool "avoid soft division in printf" + default y + help + Replaces division and modulus by 10 with shifts and adds when + doing binary to decimal conversion in printf for 64-bit + values on 32-bit targets. + +config PICOLIBC_IO_MINIMAL_LONG_LONG + bool "Include long long support in minimal printf" + depends on PICOLIBC_IO_MINIMAL + default y if CBPRINTF_FULL_INTEGRAL + help + Include long long support in the minimal picolibc printf code + config PICOLIBC_LOCALE_INFO bool "support locales in libc functions" help diff --git a/lib/libc/picolibc/libc-hooks.c b/lib/libc/picolibc/libc-hooks.c index 8df622c492c..e7539bc5dfe 100644 --- a/lib/libc/picolibc/libc-hooks.c +++ b/lib/libc/picolibc/libc-hooks.c @@ -14,13 +14,13 @@ #include #include #include -#include +#include #include #include #include #include #ifdef CONFIG_MMU -#include +#include #endif #define LIBC_BSS K_APP_BMEM(z_libc_partition) @@ -206,6 +206,27 @@ void __retarget_lock_release(_LOCK_T lock) #endif /* CONFIG_MULTITHREADING */ +#ifdef CONFIG_PICOLIBC_ASSERT_VERBOSE + +FUNC_NORETURN void __assert_func(const char *file, int line, + const char *function, const char *expression) +{ + __ASSERT(0, "assertion \"%s\" failed: file \"%s\", line %d%s%s\n", + expression, file, line, + function ? ", function: " : "", function ? function : ""); + CODE_UNREACHABLE; +} + +#else + +FUNC_NORETURN void __assert_no_args(void) +{ + __ASSERT_NO_MSG(0); + CODE_UNREACHABLE; +} + +#endif + /* This function gets called if static buffer overflow detection is enabled on * stdlib side (Picolibc here), in case such an overflow is detected. Picolibc * provides an implementation not suitable for us, so we override it here. diff --git a/lib/os/CMakeLists.txt b/lib/os/CMakeLists.txt index 5ed076b47ab..4f082716c48 100644 --- a/lib/os/CMakeLists.txt +++ b/lib/os/CMakeLists.txt @@ -9,7 +9,6 @@ zephyr_sources_ifdef(CONFIG_BASE64 base64.c) zephyr_sources( cbprintf_packaged.c dec.c - fdtable.c hex.c printk.c rb.c @@ -22,6 +21,7 @@ zephyr_sources( multi_heap.c ) +zephyr_sources_ifdef(CONFIG_FDTABLE fdtable.c) zephyr_sources_ifdef(CONFIG_ONOFF onoff.c) zephyr_sources_ifdef(CONFIG_NOTIFY notify.c) diff --git a/lib/os/Kconfig b/lib/os/Kconfig index 42465b24f60..e6b25ade5a5 100644 --- a/lib/os/Kconfig +++ b/lib/os/Kconfig @@ -3,6 +3,13 @@ menu "OS Support Library" +config FDTABLE + bool "File descriptor table" + help + This file provides generic file descriptor table implementation, suitable + for any I/O object implementing POSIX I/O semantics (i.e. read/write + + aux operations). + config JSON_LIBRARY bool "Build JSON library" help @@ -28,7 +35,7 @@ config BASE64 config PRINTK_SYNC bool "Serialize printk() calls" - default y if SMP && MP_NUM_CPUS > 1 && !(EFI_CONSOLE && LOG) + default y if SMP && MP_MAX_NUM_CPUS > 1 && !(EFI_CONSOLE && LOG) help When true, a spinlock will be taken around the output from a single printk() call, preventing the output data from diff --git a/lib/os/Kconfig.cbprintf b/lib/os/Kconfig.cbprintf index 0e4984b1559..54ba8ccfa50 100644 --- a/lib/os/Kconfig.cbprintf +++ b/lib/os/Kconfig.cbprintf @@ -31,7 +31,7 @@ choice CBPRINTF_INTEGRAL_CONV # 01: 0% / 0 B (01 / 00) config CBPRINTF_FULL_INTEGRAL bool "Convert the full range of integer values" - select PICOLIBC_IO_LONG_LONG if PICOLIBC + select PICOLIBC_IO_MINIMAL_LONG_LONG if PICOLIBC_IO_MINIMAL && PICOLIBC_USE_MODULE help Build cbprintf with buffers sized to support converting the full range of all integral and pointer values. @@ -67,7 +67,6 @@ config CBPRINTF_FP_SUPPORT bool "Floating point formatting in cbprintf" default y if FPU depends on CBPRINTF_COMPLETE - select PICOLIBC_IO_FLOAT if PICOLIBC help Build the cbprintf utility function with support for floating point format specifiers. Selecting this increases stack size @@ -90,6 +89,7 @@ config CBPRINTF_FP_A_SUPPORT config CBPRINTF_FP_ALWAYS_A bool "Select %a format for all floating point specifications" select CBPRINTF_FP_A_SUPPORT + depends on !PICOLIBC help The %a format for floats requires significantly less code than the standard decimal representations (%f, %e, %g). Selecting this @@ -103,10 +103,12 @@ config CBPRINTF_FP_ALWAYS_A config CBPRINTF_N_SPECIFIER bool "Support %n specifications" depends on CBPRINTF_COMPLETE + depends on !PICOLIBC default y help If selected %n can be used to determine the number of characters emitted. If enabled there is a small increase in code size. + Picolibc does not support this feature for security reasons. # 180: 18% / 138 B (180 / 80) [NANO] config CBPRINTF_LIBC_SUBSTS @@ -120,6 +122,9 @@ config CBPRINTF_LIBC_SUBSTS When used with CBPRINTF_NANO this increases the implementation code size by a small amount. + When used with picolibc, this option generates cbprintf-compatible + functions using stdio, effectively inverting the sense above. + module = CBPRINTF_PACKAGE module-str = cbprintf_package source "subsys/logging/Kconfig.template.log_config" @@ -159,3 +164,11 @@ config CBPRINTF_PACKAGE_SUPPORT_TAGGED_ARGUMENTS to determine the types of arguments, but instead, each argument is tagged with a type by preceding it with another argument as type (integer). + +config CBPRINTF_CONVERT_CHECK_PTR + bool + default y if !LOG_FMT_SECTION_STRIP + help + If enabled, cbprintf_package_convert() supports checking if string + candidate is used for %p format specifier. Check cannot be performed + if string is not present in the memory. diff --git a/lib/os/Kconfig.heap b/lib/os/Kconfig.heap index 1fa84ff41db..f6e8d93ae50 100644 --- a/lib/os/Kconfig.heap +++ b/lib/os/Kconfig.heap @@ -133,4 +133,21 @@ config SYS_MEM_BLOCKS_RUNTIME_STATS blocks statistics related to the current and maximum number of allocations in a given memory block. +config OBJ_CORE_SYS_MEM_BLOCKS + bool "Kernel object for memory blocks" + depends on SYS_MEM_BLOCKS && OBJ_CORE + default y if SYS_MEM_BLOCKS && OBJ_CORE + help + This option allows object cores to be integrated into memory block + objects. + +config OBJ_CORE_STATS_SYS_MEM_BLOCKS + bool "Object core statistics for memory blocks" + depends on SYS_MEM_BLOCKS && OBJ_CORE_STATS + default y if SYS_MEM_BLOCKS && OBJ_CORE_STATS + select SYS_MEM_BLOCKS_RUNTIME_STATS + help + This option integrates the object core statistics framework into + the memory blocks. + endmenu diff --git a/lib/os/assert.c b/lib/os/assert.c index b6a33ae7320..1fee487bff6 100644 --- a/lib/os/assert.c +++ b/lib/os/assert.c @@ -7,7 +7,7 @@ #include #include #include - +#include /** * @brief Assert Action Handler @@ -42,6 +42,7 @@ __weak void assert_post_action(const char *file, unsigned int line) k_panic(); } +EXPORT_SYMBOL(assert_post_action); void assert_print(const char *fmt, ...) { @@ -53,3 +54,4 @@ void assert_print(const char *fmt, ...) va_end(ap); } +EXPORT_SYMBOL(assert_print); diff --git a/lib/os/cbprintf_packaged.c b/lib/os/cbprintf_packaged.c index 58076e9320a..3e71034f316 100644 --- a/lib/os/cbprintf_packaged.c +++ b/lib/os/cbprintf_packaged.c @@ -999,7 +999,8 @@ int cbprintf_package_convert(void *in_packaged, bool is_ro = ptr_in_rodata(str); int len; - if (fmt_present && is_ptr(fmt, arg_idx)) { + if (IS_ENABLED(CONFIG_CBPRINTF_CONVERT_CHECK_PTR) && + fmt_present && is_ptr(fmt, arg_idx)) { LOG_WRN("(unsigned) char * used for %%p argument. " "It's recommended to cast it to void * because " "it may cause misbehavior in certain " @@ -1077,7 +1078,8 @@ int cbprintf_package_convert(void *in_packaged, const char *str = *(const char **)&buf32[arg_pos]; bool is_ro = ptr_in_rodata(str); - if (fmt_present && is_ptr(fmt, arg_idx)) { + if (IS_ENABLED(CONFIG_CBPRINTF_CONVERT_CHECK_PTR) && + fmt_present && is_ptr(fmt, arg_idx)) { continue; } diff --git a/lib/os/fdtable.c b/lib/os/fdtable.c index 1d5c340cc19..757ebf4361f 100644 --- a/lib/os/fdtable.c +++ b/lib/os/fdtable.c @@ -14,11 +14,13 @@ */ #include +#include + #include #include #include #include -#include +#include #include struct fd_entry { @@ -41,17 +43,23 @@ static struct fd_entry fdtable[CONFIG_POSIX_MAX_FDS] = { { /* STDIN */ .vtable = &stdinout_fd_op_vtable, - .refcount = ATOMIC_INIT(1) + .refcount = ATOMIC_INIT(1), + .lock = Z_MUTEX_INITIALIZER(fdtable[0].lock), + .cond = Z_CONDVAR_INITIALIZER(fdtable[0].cond), }, { /* STDOUT */ .vtable = &stdinout_fd_op_vtable, - .refcount = ATOMIC_INIT(1) + .refcount = ATOMIC_INIT(1), + .lock = Z_MUTEX_INITIALIZER(fdtable[1].lock), + .cond = Z_CONDVAR_INITIALIZER(fdtable[1].cond), }, { /* STDERR */ .vtable = &stdinout_fd_op_vtable, - .refcount = ATOMIC_INIT(1) + .refcount = ATOMIC_INIT(1), + .lock = Z_MUTEX_INITIALIZER(fdtable[2].lock), + .cond = Z_CONDVAR_INITIALIZER(fdtable[2].cond), }, #else { @@ -124,6 +132,30 @@ static int _check_fd(int fd) return 0; } +#ifdef CONFIG_ZTEST +bool fdtable_fd_is_initialized(int fd) +{ + struct k_mutex ref_lock; + struct k_condvar ref_cond; + + if (fd < 0 || fd >= ARRAY_SIZE(fdtable)) { + return false; + } + + ref_lock = (struct k_mutex)Z_MUTEX_INITIALIZER(fdtable[fd].lock); + if (memcmp(&ref_lock, &fdtable[fd].lock, sizeof(ref_lock)) != 0) { + return false; + } + + ref_cond = (struct k_condvar)Z_CONDVAR_INITIALIZER(fdtable[fd].cond); + if (memcmp(&ref_cond, &fdtable[fd].cond, sizeof(ref_cond)) != 0) { + return false; + } + + return true; +} +#endif /* CONFIG_ZTEST */ + void *z_get_fd_obj(int fd, const struct fd_op_vtable *vtable, int err) { struct fd_entry *entry; @@ -231,7 +263,7 @@ void z_finalize_fd(int fd, void *obj, const struct fd_op_vtable *vtable) * This call is a no-op if obj is invalid or points to something * not a kernel object. */ - z_object_recycle(obj); + k_object_recycle(obj); #endif fdtable[fd].obj = obj; fdtable[fd].vtable = vtable; diff --git a/lib/os/mem_blocks.c b/lib/os/mem_blocks.c index 3517a5705d9..84d3d81638a 100644 --- a/lib/os/mem_blocks.c +++ b/lib/os/mem_blocks.c @@ -10,13 +10,14 @@ #include #include #include +#include +#include static void *alloc_blocks(sys_mem_blocks_t *mem_block, size_t num_blocks) { size_t offset; int r; uint8_t *blk; - void *ret = NULL; #ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS k_spinlock_key_t key = k_spin_lock(&mem_block->lock); @@ -24,29 +25,33 @@ static void *alloc_blocks(sys_mem_blocks_t *mem_block, size_t num_blocks) /* Find an unallocated block */ r = sys_bitarray_alloc(mem_block->bitmap, num_blocks, &offset); - if (r == 0) { - + if (r != 0) { #ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS - mem_block->used_blocks += (uint32_t)num_blocks; - - if (mem_block->max_used_blocks < mem_block->used_blocks) { - mem_block->max_used_blocks = mem_block->used_blocks; - } - k_spin_unlock(&mem_block->lock, key); #endif + return NULL; + } - /* Calculate the start address of the newly allocated block */ - blk = mem_block->buffer + (offset << mem_block->blk_sz_shift); +#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS + mem_block->info.used_blocks += (uint32_t)num_blocks; - ret = blk; + if (mem_block->info.max_used_blocks < mem_block->info.used_blocks) { + mem_block->info.max_used_blocks = mem_block->info.used_blocks; } - return ret; + k_spin_unlock(&mem_block->lock, key); +#endif + + /* Calculate the start address of the newly allocated block */ + + blk = mem_block->buffer + (offset << mem_block->info.blk_sz_shift); + + return blk; } -static int free_blocks(sys_mem_blocks_t *mem_block, void *ptr, size_t num_blocks) +static int free_blocks(sys_mem_blocks_t *mem_block, void *ptr, + size_t num_blocks) { size_t offset; uint8_t *blk = ptr; @@ -58,8 +63,8 @@ static int free_blocks(sys_mem_blocks_t *mem_block, void *ptr, size_t num_blocks goto out; } - offset = (blk - mem_block->buffer) >> mem_block->blk_sz_shift; - if (offset >= mem_block->num_blocks) { + offset = (blk - mem_block->buffer) >> mem_block->info.blk_sz_shift; + if (offset >= mem_block->info.num_blocks) { ret = -EFAULT; goto out; } @@ -71,7 +76,7 @@ static int free_blocks(sys_mem_blocks_t *mem_block, void *ptr, size_t num_blocks #ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS if (ret == 0) { - mem_block->used_blocks -= (uint32_t) num_blocks; + mem_block->info.used_blocks -= (uint32_t)num_blocks; } k_spin_unlock(&mem_block->lock, key); @@ -82,7 +87,7 @@ static int free_blocks(sys_mem_blocks_t *mem_block, void *ptr, size_t num_blocks } int sys_mem_blocks_alloc_contiguous(sys_mem_blocks_t *mem_block, size_t count, - void **out_block) + void **out_block) { int ret = 0; @@ -95,7 +100,7 @@ int sys_mem_blocks_alloc_contiguous(sys_mem_blocks_t *mem_block, size_t count, goto out; } - if (count > mem_block->num_blocks) { + if (count > mem_block->info.num_blocks) { /* Definitely not enough blocks to be allocated */ ret = -ENOMEM; goto out; @@ -111,11 +116,11 @@ int sys_mem_blocks_alloc_contiguous(sys_mem_blocks_t *mem_block, size_t count, *out_block = ptr; #ifdef CONFIG_SYS_MEM_BLOCKS_LISTENER heap_listener_notify_alloc(HEAP_ID_FROM_POINTER(mem_block), - ptr, count << mem_block->blk_sz_shift); + ptr, count << mem_block->info.blk_sz_shift); #endif out: - return ret; + return ret; } int sys_mem_blocks_alloc(sys_mem_blocks_t *mem_block, size_t count, @@ -134,7 +139,7 @@ int sys_mem_blocks_alloc(sys_mem_blocks_t *mem_block, size_t count, goto out; } - if (count > mem_block->num_blocks) { + if (count > mem_block->info.num_blocks) { /* Definitely not enough blocks to be allocated */ ret = -ENOMEM; goto out; @@ -151,7 +156,8 @@ int sys_mem_blocks_alloc(sys_mem_blocks_t *mem_block, size_t count, #ifdef CONFIG_SYS_MEM_BLOCKS_LISTENER heap_listener_notify_alloc(HEAP_ID_FROM_POINTER(mem_block), - ptr, BIT(mem_block->blk_sz_shift)); + ptr, + BIT(mem_block->info.blk_sz_shift)); #endif } @@ -165,7 +171,8 @@ int sys_mem_blocks_alloc(sys_mem_blocks_t *mem_block, size_t count, return ret; } -int sys_mem_blocks_is_region_free(sys_mem_blocks_t *mem_block, void *in_block, size_t count) +int sys_mem_blocks_is_region_free(sys_mem_blocks_t *mem_block, void *in_block, + size_t count) { bool result; size_t offset; @@ -174,11 +181,13 @@ int sys_mem_blocks_is_region_free(sys_mem_blocks_t *mem_block, void *in_block, s __ASSERT_NO_MSG(mem_block->bitmap != NULL); __ASSERT_NO_MSG(mem_block->buffer != NULL); - offset = ((uint8_t *)in_block - mem_block->buffer) >> mem_block->blk_sz_shift; + offset = ((uint8_t *)in_block - mem_block->buffer) >> + mem_block->info.blk_sz_shift; - __ASSERT_NO_MSG(offset + count <= mem_block->num_blocks); + __ASSERT_NO_MSG(offset + count <= mem_block->info.num_blocks); - result = sys_bitarray_is_region_cleared(mem_block->bitmap, count, offset); + result = sys_bitarray_is_region_cleared(mem_block->bitmap, count, + offset); return result; } @@ -196,9 +205,10 @@ int sys_mem_blocks_get(sys_mem_blocks_t *mem_block, void *in_block, size_t count goto out; } - offset = ((uint8_t *)in_block - mem_block->buffer) >> mem_block->blk_sz_shift; + offset = ((uint8_t *)in_block - mem_block->buffer) >> + mem_block->info.blk_sz_shift; - if (offset + count > mem_block->num_blocks) { + if (offset + count > mem_block->info.num_blocks) { /* Definitely not enough blocks to be allocated */ ret = -ENOMEM; goto out; @@ -208,7 +218,8 @@ int sys_mem_blocks_get(sys_mem_blocks_t *mem_block, void *in_block, size_t count k_spinlock_key_t key = k_spin_lock(&mem_block->lock); #endif - ret = sys_bitarray_test_and_set_region(mem_block->bitmap, count, offset, true); + ret = sys_bitarray_test_and_set_region(mem_block->bitmap, count, + offset, true); if (ret != 0) { #ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS @@ -219,10 +230,10 @@ int sys_mem_blocks_get(sys_mem_blocks_t *mem_block, void *in_block, size_t count } #ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS - mem_block->used_blocks += (uint32_t)count; + mem_block->info.used_blocks += (uint32_t)count; - if (mem_block->max_used_blocks < mem_block->used_blocks) { - mem_block->max_used_blocks = mem_block->used_blocks; + if (mem_block->info.max_used_blocks < mem_block->info.used_blocks) { + mem_block->info.max_used_blocks = mem_block->info.used_blocks; } k_spin_unlock(&mem_block->lock, key); @@ -230,7 +241,7 @@ int sys_mem_blocks_get(sys_mem_blocks_t *mem_block, void *in_block, size_t count #ifdef CONFIG_SYS_MEM_BLOCKS_LISTENER heap_listener_notify_alloc(HEAP_ID_FROM_POINTER(mem_block), - in_block, count << mem_block->blk_sz_shift); + in_block, count << mem_block->info.blk_sz_shift); #endif out: @@ -254,7 +265,7 @@ int sys_mem_blocks_free(sys_mem_blocks_t *mem_block, size_t count, goto out; } - if (count > mem_block->num_blocks) { + if (count > mem_block->info.num_blocks) { ret = -EINVAL; goto out; } @@ -275,7 +286,7 @@ int sys_mem_blocks_free(sys_mem_blocks_t *mem_block, size_t count, * notifying at the end of function. */ heap_listener_notify_free(HEAP_ID_FROM_POINTER(mem_block), - ptr, BIT(mem_block->blk_sz_shift)); + ptr, BIT(mem_block->info.blk_sz_shift)); } #endif } @@ -297,7 +308,7 @@ int sys_mem_blocks_free_contiguous(sys_mem_blocks_t *mem_block, void *block, siz goto out; } - if (count > mem_block->num_blocks) { + if (count > mem_block->info.num_blocks) { ret = -EINVAL; goto out; } @@ -309,7 +320,7 @@ int sys_mem_blocks_free_contiguous(sys_mem_blocks_t *mem_block, void *block, siz } #ifdef CONFIG_SYS_MEM_BLOCKS_LISTENER heap_listener_notify_free(HEAP_ID_FROM_POINTER(mem_block), - block, count << mem_block->blk_sz_shift); + block, count << mem_block->info.blk_sz_shift); #endif out: @@ -355,7 +366,7 @@ int sys_multi_mem_blocks_alloc(sys_multi_mem_blocks_t *group, goto out; } - if (count > allocator->num_blocks) { + if (count > allocator->info.num_blocks) { ret = -ENOMEM; goto out; } @@ -363,7 +374,7 @@ int sys_multi_mem_blocks_alloc(sys_multi_mem_blocks_t *group, ret = sys_mem_blocks_alloc(allocator, count, out_blocks); if ((ret == 0) && (blk_size != NULL)) { - *blk_size = BIT(allocator->blk_sz_shift); + *blk_size = BIT(allocator->info.blk_sz_shift); } out: @@ -395,7 +406,8 @@ int sys_multi_mem_blocks_free(sys_multi_mem_blocks_t *group, one_alloc = group->allocators[i]; start = one_alloc->buffer; - end = start + (BIT(one_alloc->blk_sz_shift) * one_alloc->num_blocks); + end = start + (BIT(one_alloc->info.blk_sz_shift) * + one_alloc->info.num_blocks); if (((uint8_t *)in_blocks[0] >= start) && ((uint8_t *)in_blocks[0] < end)) { @@ -422,12 +434,13 @@ int sys_mem_blocks_runtime_stats_get(sys_mem_blocks_t *mem_block, return -EINVAL; } - stats->allocated_bytes = mem_block->used_blocks << - mem_block->blk_sz_shift; - stats->free_bytes = (mem_block->num_blocks << mem_block->blk_sz_shift) - + stats->allocated_bytes = mem_block->info.used_blocks << + mem_block->info.blk_sz_shift; + stats->free_bytes = (mem_block->info.num_blocks << + mem_block->info.blk_sz_shift) - stats->allocated_bytes; - stats->max_allocated_bytes = mem_block->max_used_blocks << - mem_block->blk_sz_shift; + stats->max_allocated_bytes = mem_block->info.max_used_blocks << + mem_block->info.blk_sz_shift; return 0; } @@ -438,8 +451,109 @@ int sys_mem_blocks_runtime_stats_reset_max(sys_mem_blocks_t *mem_block) return -EINVAL; } - mem_block->max_used_blocks = mem_block->used_blocks; + mem_block->info.max_used_blocks = mem_block->info.used_blocks; + + return 0; +} +#endif + +#ifdef CONFIG_OBJ_CORE_STATS_SYS_MEM_BLOCKS +static int sys_mem_blocks_stats_raw(struct k_obj_core *obj_core, void *stats) +{ + struct sys_mem_blocks *block; + k_spinlock_key_t key; + + block = CONTAINER_OF(obj_core, struct sys_mem_blocks, obj_core); + + key = k_spin_lock(&block->lock); + + memcpy(stats, &block->info, sizeof(block->info)); + + k_spin_unlock(&block->lock, key); return 0; } + +static int sys_mem_blocks_stats_query(struct k_obj_core *obj_core, void *stats) +{ + struct sys_mem_blocks *block; + k_spinlock_key_t key; + struct sys_memory_stats *ptr = stats; + + block = CONTAINER_OF(obj_core, struct sys_mem_blocks, obj_core); + + key = k_spin_lock(&block->lock); + + ptr->free_bytes = (block->info.num_blocks - block->info.used_blocks) << + block->info.blk_sz_shift; + ptr->allocated_bytes = block->info.used_blocks << + block->info.blk_sz_shift; + ptr->max_allocated_bytes = block->info.max_used_blocks << + block->info.blk_sz_shift; + + k_spin_unlock(&block->lock, key); + + return 0; +} + +static int sys_mem_blocks_stats_reset(struct k_obj_core *obj_core) +{ + struct sys_mem_blocks *block; + k_spinlock_key_t key; + + block = CONTAINER_OF(obj_core, struct sys_mem_blocks, obj_core); + + key = k_spin_lock(&block->lock); + block->info.max_used_blocks = block->info.used_blocks; + k_spin_unlock(&block->lock, key); + + return 0; +} + +static struct k_obj_type obj_type_sys_mem_blocks; + +static struct k_obj_core_stats_desc sys_mem_blocks_stats_desc = { + .raw_size = sizeof(struct sys_mem_blocks_info), + .query_size = sizeof(struct sys_memory_stats), + .raw = sys_mem_blocks_stats_raw, + .query = sys_mem_blocks_stats_query, + .reset = sys_mem_blocks_stats_reset, + .disable = NULL, + .enable = NULL, +}; +#endif + +#ifdef CONFIG_OBJ_CORE_SYS_MEM_BLOCKS +static struct k_obj_type obj_type_sys_mem_blocks; + +static int init_sys_mem_blocks_obj_core_list(void) +{ + /* Initialize the sys_mem_blocks object type */ + + z_obj_type_init(&obj_type_sys_mem_blocks, K_OBJ_TYPE_MEM_BLOCK_ID, + offsetof(struct sys_mem_blocks, obj_core)); + +#ifdef CONFIG_OBJ_CORE_STATS_SYS_MEM_BLOCKS + k_obj_type_stats_init(&obj_type_sys_mem_blocks, + &sys_mem_blocks_stats_desc); +#endif + + /* Initialize statically defined sys_mem_blocks */ + + STRUCT_SECTION_FOREACH_ALTERNATE(sys_mem_blocks_ptr, + sys_mem_blocks *, block_pp) { + k_obj_core_init_and_link(K_OBJ_CORE(*block_pp), + &obj_type_sys_mem_blocks); +#ifdef CONFIG_OBJ_CORE_STATS_SYS_MEM_BLOCKS + k_obj_core_stats_register(K_OBJ_CORE(*block_pp), + &(*block_pp)->info, + sizeof(struct sys_mem_blocks_info)); +#endif + } + + return 0; +} + +SYS_INIT(init_sys_mem_blocks_obj_core_list, PRE_KERNEL_1, + CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); #endif diff --git a/lib/os/mutex.c b/lib/os/mutex.c index 3cd84612a22..e1c6d7fb48f 100644 --- a/lib/os/mutex.c +++ b/lib/os/mutex.c @@ -6,14 +6,14 @@ #include #include -#include +#include #include static struct k_mutex *get_k_mutex(struct sys_mutex *mutex) { - struct z_object *obj; + struct k_object *obj; - obj = z_object_find(mutex); + obj = k_object_find(mutex); if (obj == NULL || obj->type != K_OBJ_SYS_MUTEX) { return NULL; } @@ -27,7 +27,7 @@ static bool check_sys_mutex_addr(struct sys_mutex *addr) * underlying k_mutex, but we don't want threads using mutexes * that are outside their memory domain */ - return Z_SYSCALL_MEMORY_WRITE(addr, sizeof(struct sys_mutex)); + return K_SYSCALL_MEMORY_WRITE(addr, sizeof(struct sys_mutex)); } int z_impl_z_sys_mutex_kernel_lock(struct sys_mutex *mutex, k_timeout_t timeout) diff --git a/lib/os/p4wq.c b/lib/os/p4wq.c index d5e97476812..22d24da140b 100644 --- a/lib/os/p4wq.c +++ b/lib/os/p4wq.c @@ -5,11 +5,12 @@ */ #include #include -#include #include -#include #include #include +/* private kernel APIs */ +#include +#include LOG_MODULE_REGISTER(p4wq, CONFIG_LOG_DEFAULT_LEVEL); diff --git a/lib/os/printk.c b/lib/os/printk.c index 466e8944b2e..f46b950ffe4 100644 --- a/lib/os/printk.c +++ b/lib/os/printk.c @@ -17,9 +17,10 @@ #include #include #include -#include +#include #include #include +#include #include /* Option present only when CONFIG_USERSPACE enabled. */ @@ -173,7 +174,7 @@ void z_impl_k_str_out(char *c, size_t n) #ifdef CONFIG_USERSPACE static inline void z_vrfy_k_str_out(char *c, size_t n) { - Z_OOPS(Z_SYSCALL_MEMORY_READ(c, n)); + K_OOPS(K_SYSCALL_MEMORY_READ(c, n)); z_impl_k_str_out((char *)c, n); } #include @@ -210,6 +211,7 @@ void printk(const char *fmt, ...) va_end(ap); } +EXPORT_SYMBOL(printk); #endif /* defined(CONFIG_PRINTK) */ #ifndef CONFIG_PICOLIBC diff --git a/lib/os/sem.c b/lib/os/sem.c index 132a0c834a8..b01ead58e50 100644 --- a/lib/os/sem.c +++ b/lib/os/sem.c @@ -5,7 +5,7 @@ */ #include -#include +#include #ifdef CONFIG_USERSPACE #define SYS_SEM_MINIMUM 0 diff --git a/lib/os/thread_entry.c b/lib/os/thread_entry.c index 0add601489c..89eb2fe7b4b 100644 --- a/lib/os/thread_entry.c +++ b/lib/os/thread_entry.c @@ -13,7 +13,7 @@ #include #ifdef CONFIG_THREAD_LOCAL_STORAGE -#include +#include __thread k_tid_t z_tls_current; #endif @@ -36,7 +36,7 @@ FUNC_NORETURN void z_thread_entry(k_thread_entry_t entry, void *p1, void *p2, void *p3) { #ifdef CONFIG_THREAD_LOCAL_STORAGE - z_tls_current = z_current_get(); + z_tls_current = k_sched_current_thread_query(); #endif #ifdef CONFIG_STACK_CANARIES_TLS uintptr_t stack_guard; diff --git a/lib/os/timeutil.c b/lib/os/timeutil.c index 4a3b8428f71..18c173acc8d 100644 --- a/lib/os/timeutil.c +++ b/lib/os/timeutil.c @@ -13,6 +13,7 @@ #include #include #include +#include #include /** Convert a civil (proleptic Gregorian) date to days relative to diff --git a/lib/posix/CMakeLists.txt b/lib/posix/CMakeLists.txt index 48bb598ef2d..c6b3a88aeab 100644 --- a/lib/posix/CMakeLists.txt +++ b/lib/posix/CMakeLists.txt @@ -48,15 +48,15 @@ zephyr_library_sources_ifdef(CONFIG_POSIX_MQUEUE mqueue.c) zephyr_library_sources_ifdef(CONFIG_POSIX_SIGNAL signal.c ${STRSIGNAL_TABLE_H}) zephyr_library_sources_ifdef(CONFIG_POSIX_UNAME uname.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC _common.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC barrier.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC cond.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC key.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC mutex.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC pthread.c) +zephyr_library_sources_ifdef(CONFIG_PTHREAD_BARRIER barrier.c) +zephyr_library_sources_ifdef(CONFIG_PTHREAD_COND cond.c) +zephyr_library_sources_ifdef(CONFIG_PTHREAD_KEY key.c) +zephyr_library_sources_ifdef(CONFIG_PTHREAD_MUTEX mutex.c) +zephyr_library_sources_ifdef(CONFIG_PTHREAD pthread.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC rwlock.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC sched.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC semaphore.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC spinlock.c) +zephyr_library_sources_ifdef(CONFIG_PTHREAD_SPINLOCK spinlock.c) zephyr_library_include_directories( ${ZEPHYR_BASE}/kernel/include diff --git a/lib/posix/Kconfig b/lib/posix/Kconfig index 199ed956af2..3fd01313474 100644 --- a/lib/posix/Kconfig +++ b/lib/posix/Kconfig @@ -5,6 +5,7 @@ config POSIX_MAX_FDS int "Maximum number of open file descriptors" + default 16 if WIFI_NM_WPA_SUPPLICANT default 16 if POSIX_API default 4 help diff --git a/lib/posix/Kconfig.clock b/lib/posix/Kconfig.clock index d9767bb3910..95c88769d73 100644 --- a/lib/posix/Kconfig.clock +++ b/lib/posix/Kconfig.clock @@ -5,6 +5,7 @@ config POSIX_CLOCK bool "POSIX clock, timer, and sleep APIs" default y if POSIX_API + depends on !(ARCH_POSIX && EXTERNAL_LIBC) help This enables POSIX clock\_\*(), timer\_\*(), and \*sleep() functions. diff --git a/lib/posix/Kconfig.eventfd b/lib/posix/Kconfig.eventfd index 52f9b461f55..0b6fa171741 100644 --- a/lib/posix/Kconfig.eventfd +++ b/lib/posix/Kconfig.eventfd @@ -7,6 +7,7 @@ config EVENTFD bool "Support for eventfd" depends on !NATIVE_APPLICATION select POLL + select FDTABLE default y if POSIX_API help Enable support for event file descriptors, eventfd. An eventfd can diff --git a/lib/posix/Kconfig.fs b/lib/posix/Kconfig.fs index 6ad72fbcff5..1d032910539 100644 --- a/lib/posix/Kconfig.fs +++ b/lib/posix/Kconfig.fs @@ -6,6 +6,7 @@ config POSIX_FS bool "POSIX file system API support" default y if POSIX_API depends on FILE_SYSTEM + select FDTABLE help This enables POSIX style file system related APIs. diff --git a/lib/posix/Kconfig.template.pooled_ipc_type b/lib/posix/Kconfig.template.pooled_ipc_type index ad0bf5bc9b0..d28ed345b6a 100644 --- a/lib/posix/Kconfig.template.pooled_ipc_type +++ b/lib/posix/Kconfig.template.pooled_ipc_type @@ -3,12 +3,13 @@ # SPDX-License-Identifier: Apache-2.0 source "lib/posix/Kconfig.template.with_url" +source "lib/posix/Kconfig.template.with_logging" # Not user configurable (i.e. private for now) config $(TYPE) - bool - default y + bool "POSIX $(type) support" depends on PTHREAD_IPC + default y help Support for $(TYPE) For more info, see diff --git a/lib/posix/Kconfig.template.pooled_type b/lib/posix/Kconfig.template.pooled_type index d2699e2f17c..a30686043a1 100644 --- a/lib/posix/Kconfig.template.pooled_type +++ b/lib/posix/Kconfig.template.pooled_type @@ -3,6 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 source "lib/posix/Kconfig.template.with_url" +source "lib/posix/Kconfig.template.with_logging" # This is mainly for TIMER currently. config $(TYPE) diff --git a/lib/posix/Kconfig.template.with_logging b/lib/posix/Kconfig.template.with_logging new file mode 100644 index 00000000000..f1fc5141e7c --- /dev/null +++ b/lib/posix/Kconfig.template.with_logging @@ -0,0 +1,7 @@ +# Copyright (c) 2023 Meta +# +# SPDX-License-Identifier: Apache-2.0 + +module = $(TYPE) +module-str = $(TYPE) logging +source "subsys/logging/Kconfig.template.log_config" diff --git a/lib/posix/_common.c b/lib/posix/_common.c index c22a4c65e23..85a8e7cae66 100644 --- a/lib/posix/_common.c +++ b/lib/posix/_common.c @@ -6,7 +6,6 @@ #include #include -#include #include #ifdef CONFIG_POSIX_CLOCK diff --git a/lib/posix/clock.c b/lib/posix/clock.c index 51812ed53bc..d7ca3969aa8 100644 --- a/lib/posix/clock.c +++ b/lib/posix/clock.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include /* @@ -68,7 +68,7 @@ int z_impl_clock_gettime(clockid_t clock_id, struct timespec *ts) #ifdef CONFIG_USERSPACE int z_vrfy_clock_gettime(clockid_t clock_id, struct timespec *ts) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(ts, sizeof(*ts))); + K_OOPS(K_SYSCALL_MEMORY_WRITE(ts, sizeof(*ts))); return z_impl_clock_gettime(clock_id, ts); } #include diff --git a/lib/posix/cond.c b/lib/posix/cond.c index b40105d1ae7..f4128054e3f 100644 --- a/lib/posix/cond.c +++ b/lib/posix/cond.c @@ -9,9 +9,12 @@ #include #include +#include #include #include +LOG_MODULE_REGISTER(pthread_cond, CONFIG_PTHREAD_COND_LOG_LEVEL); + int64_t timespec_to_timeoutms(const struct timespec *abstime); static struct k_condvar posix_cond_pool[CONFIG_MAX_PTHREAD_COND_COUNT]; @@ -42,16 +45,19 @@ static struct k_condvar *get_posix_cond(pthread_cond_t cond) /* if the provided cond does not claim to be initialized, its invalid */ if (!is_pthread_obj_initialized(cond)) { + LOG_ERR("Cond is uninitialized (%x)", cond); return NULL; } /* Mask off the MSB to get the actual bit index */ if (sys_bitarray_test_bit(&posix_cond_bitarray, bit, &actually_initialized) < 0) { + LOG_ERR("Cond is invalid (%x)", cond); return NULL; } if (actually_initialized == 0) { /* The cond claims to be initialized but is actually not */ + LOG_ERR("Cond claims to be initialized (%x)", cond); return NULL; } @@ -70,6 +76,7 @@ static struct k_condvar *to_posix_cond(pthread_cond_t *cvar) /* Try and automatically associate a posix_cond */ if (sys_bitarray_alloc(&posix_cond_bitarray, 1, &bit) < 0) { /* No conds left to allocate */ + LOG_ERR("Unable to allocate pthread_cond_t"); return NULL; } @@ -92,13 +99,17 @@ static int cond_wait(pthread_cond_t *cond, pthread_mutex_t *mu, k_timeout_t time return EINVAL; } + LOG_DBG("Waiting on cond %p with timeout %llx", cv, timeout.ticks); ret = k_condvar_wait(cv, m, timeout); if (ret == -EAGAIN) { + LOG_ERR("Timeout waiting on cond %p", cv); ret = ETIMEDOUT; } else if (ret < 0) { + LOG_ERR("k_condvar_wait() failed: %d", ret); ret = -ret; } else { __ASSERT_NO_MSG(ret == 0); + LOG_DBG("Cond %p received signal", cv); } return ret; @@ -114,8 +125,10 @@ int pthread_cond_signal(pthread_cond_t *cvar) return EINVAL; } + LOG_DBG("Signaling cond %p", cv); ret = k_condvar_signal(cv); if (ret < 0) { + LOG_ERR("k_condvar_signal() failed: %d", ret); return -ret; } @@ -134,8 +147,10 @@ int pthread_cond_broadcast(pthread_cond_t *cvar) return EINVAL; } + LOG_DBG("Broadcasting on cond %p", cv); ret = k_condvar_broadcast(cv); if (ret < 0) { + LOG_ERR("k_condvar_broadcast() failed: %d", ret); return -ret; } @@ -167,6 +182,8 @@ int pthread_cond_init(pthread_cond_t *cvar, const pthread_condattr_t *att) return ENOMEM; } + LOG_DBG("Initialized cond %p", cv); + return 0; } @@ -187,6 +204,8 @@ int pthread_cond_destroy(pthread_cond_t *cvar) *cvar = -1; + LOG_DBG("Destroyed cond %p", cv); + return 0; } diff --git a/lib/posix/mutex.c b/lib/posix/mutex.c index 7d27cdae53c..5aef2c0bc0e 100644 --- a/lib/posix/mutex.c +++ b/lib/posix/mutex.c @@ -9,9 +9,12 @@ #include #include +#include #include #include +LOG_MODULE_REGISTER(pthread_mutex, CONFIG_PTHREAD_MUTEX_LOG_LEVEL); + static struct k_spinlock pthread_mutex_spinlock; int64_t timespec_to_timeoutms(const struct timespec *abstime); @@ -54,16 +57,19 @@ static struct k_mutex *get_posix_mutex(pthread_mutex_t mu) /* if the provided mutex does not claim to be initialized, its invalid */ if (!is_pthread_obj_initialized(mu)) { + LOG_ERR("Mutex is uninitialized (%x)", mu); return NULL; } /* Mask off the MSB to get the actual bit index */ if (sys_bitarray_test_bit(&posix_mutex_bitarray, bit, &actually_initialized) < 0) { + LOG_ERR("Mutex is invalid (%x)", mu); return NULL; } if (actually_initialized == 0) { /* The mutex claims to be initialized but is actually not */ + LOG_ERR("Mutex claims to be initialized (%x)", mu); return NULL; } @@ -82,7 +88,7 @@ struct k_mutex *to_posix_mutex(pthread_mutex_t *mu) /* Try and automatically associate a posix_mutex */ if (sys_bitarray_alloc(&posix_mutex_bitarray, 1, &bit) < 0) { - /* No mutexes left to allocate */ + LOG_ERR("Unable to allocate pthread_mutex_t"); return NULL; } @@ -106,24 +112,30 @@ static int acquire_mutex(pthread_mutex_t *mu, k_timeout_t timeout) struct k_mutex *m; k_spinlock_key_t key; + key = k_spin_lock(&pthread_mutex_spinlock); + m = to_posix_mutex(mu); if (m == NULL) { + k_spin_unlock(&pthread_mutex_spinlock, key); return EINVAL; } + LOG_DBG("Locking mutex %p with timeout %llx", m, timeout.ticks); + bit = posix_mutex_to_offset(m); type = posix_mutex_type[bit]; - key = k_spin_lock(&pthread_mutex_spinlock); if (m->owner == k_current_get()) { switch (type) { case PTHREAD_MUTEX_NORMAL: if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) { - ret = EBUSY; - break; + k_spin_unlock(&pthread_mutex_spinlock, key); + LOG_ERR("Timeout locking mutex %p", m); + return EBUSY; } /* On most POSIX systems, this usually results in an infinite loop */ k_spin_unlock(&pthread_mutex_spinlock, key); + LOG_ERR("Attempt to relock non-recursive mutex %p", m); do { (void)k_sleep(K_FOREVER); } while (true); @@ -131,10 +143,12 @@ static int acquire_mutex(pthread_mutex_t *mu, k_timeout_t timeout) break; case PTHREAD_MUTEX_RECURSIVE: if (m->lock_count >= MUTEX_MAX_REC_LOCK) { + LOG_ERR("Mutex %p locked recursively too many times", m); ret = EAGAIN; } break; case PTHREAD_MUTEX_ERRORCHECK: + LOG_ERR("Attempt to recursively lock non-recursive mutex %p", m); ret = EDEADLK; break; default: @@ -148,18 +162,24 @@ static int acquire_mutex(pthread_mutex_t *mu, k_timeout_t timeout) if (ret == 0) { ret = k_mutex_lock(m, timeout); if (ret == -EAGAIN) { + LOG_ERR("Timeout locking mutex %p", m); /* * special quirk - k_mutex_lock() returns EAGAIN if a timeout occurs, but * for pthreads, that means something different */ - ret = -ETIMEDOUT; + ret = ETIMEDOUT; } } if (ret < 0) { + LOG_ERR("k_mutex_unlock() failed: %d", ret); ret = -ret; } + if (ret == 0) { + LOG_DBG("Locked mutex %p", m); + } + return ret; } @@ -211,6 +231,8 @@ int pthread_mutex_init(pthread_mutex_t *mu, const pthread_mutexattr_t *_attr) posix_mutex_type[bit] = attr->type; } + LOG_DBG("Initialized mutex %p", m); + return 0; } @@ -242,10 +264,12 @@ int pthread_mutex_unlock(pthread_mutex_t *mu) ret = k_mutex_unlock(m); if (ret < 0) { + LOG_ERR("k_mutex_unlock() failed: %d", ret); return -ret; } __ASSERT_NO_MSG(ret == 0); + LOG_DBG("Unlocked mutex %p", m); return 0; } @@ -270,6 +294,8 @@ int pthread_mutex_destroy(pthread_mutex_t *mu) err = sys_bitarray_free(&posix_mutex_bitarray, 1, bit); __ASSERT_NO_MSG(err == 0); + LOG_DBG("Destroyed mutex %p", m); + return 0; } diff --git a/lib/posix/pthread.c b/lib/posix/pthread.c index 0b5ca186530..f2bbc07ae9a 100644 --- a/lib/posix/pthread.c +++ b/lib/posix/pthread.c @@ -12,10 +12,13 @@ #include #include +#include #include #include #include +LOG_MODULE_REGISTER(pthread, CONFIG_PTHREAD_LOG_LEVEL); + #ifdef CONFIG_DYNAMIC_THREAD_STACK_SIZE #define DYNAMIC_STACK_SIZE CONFIG_DYNAMIC_THREAD_STACK_SIZE #else @@ -91,10 +94,12 @@ struct posix_thread *to_posix_thread(pthread_t pthread) /* if the provided thread does not claim to be initialized, its invalid */ if (!is_pthread_obj_initialized(pthread)) { + LOG_ERR("pthread is not initialized (%x)", pthread); return NULL; } if (bit >= CONFIG_MAX_PTHREAD_COUNT) { + LOG_ERR("Invalid pthread (%x)", pthread); return NULL; } @@ -112,7 +117,7 @@ struct posix_thread *to_posix_thread(pthread_t pthread) k_spin_unlock(&pthread_pool_lock, key); if (!actually_initialized) { - /* The thread claims to be initialized but is actually not */ + LOG_ERR("Pthread claims to be initialized (%x)", pthread); return NULL; } @@ -137,6 +142,8 @@ static bool is_posix_policy_prio_valid(uint32_t priority, int policy) return true; } + LOG_ERR("Invalid piority %d and / or policy %d", priority, policy); + return false; } @@ -185,6 +192,7 @@ int pthread_attr_setschedparam(pthread_attr_t *_attr, const struct sched_param * if ((attr == NULL) || (attr->initialized == 0U) || (is_posix_policy_prio_valid(priority, attr->schedpolicy) == false)) { + LOG_ERR("Invalid pthread_attr_t or sched_param"); return EINVAL; } @@ -202,6 +210,7 @@ int pthread_attr_setstack(pthread_attr_t *_attr, void *stackaddr, size_t stacksi struct pthread_attr *attr = (struct pthread_attr *)_attr; if (stackaddr == NULL) { + LOG_ERR("NULL stack address"); return EACCES; } @@ -219,22 +228,26 @@ static bool pthread_attr_is_valid(const struct pthread_attr *attr) /* caller-provided thread stack */ if (attr->initialized == 0U || attr->stack == NULL || attr->stacksize == 0) { + LOG_ERR("pthread_attr_t is not initialized, has a NULL stack, or is of size 0"); return false; } /* require a valid scheduler policy */ if (!valid_posix_policy(attr->schedpolicy)) { + LOG_ERR("Invalid scheduler policy %d", attr->schedpolicy); return false; } /* require a valid detachstate */ if (!(attr->detachstate == PTHREAD_CREATE_JOINABLE || attr->detachstate == PTHREAD_CREATE_DETACHED)) { + LOG_ERR("Invalid detachstate %d", attr->detachstate); return false; } /* we cannot create an essential thread (i.e. one that may not abort) */ if ((attr->flags & K_ESSENTIAL) != 0) { + LOG_ERR("Cannot create an essential thread"); return false; } @@ -323,9 +336,12 @@ static void posix_thread_recycle(void) return; } + LOG_DBG("Recycling %zu threads", sys_dlist_len(&recyclables)); + if (IS_ENABLED(CONFIG_DYNAMIC_THREAD)) { SYS_DLIST_FOR_EACH_CONTAINER(&recyclables, t, q_node) { if (t->dynamic_stack != NULL) { + LOG_DBG("Freeing thread stack %p", t->dynamic_stack); (void)k_thread_stack_free(t->dynamic_stack); t->dynamic_stack = NULL; } @@ -367,8 +383,10 @@ int pthread_create(pthread_t *th, const pthread_attr_t *_attr, void *(*threadrou attr->stack = k_thread_stack_alloc(attr->stacksize, k_is_user_context() ? K_USER : 0); if (attr->stack == NULL) { + LOG_ERR("Unable to allocate stack of size %u", attr->stacksize); return EAGAIN; } + LOG_DBG("Allocated thread stack %p", attr->stack); } else { __ASSERT_NO_MSG(attr != &attr_storage); } @@ -395,6 +413,7 @@ int pthread_create(pthread_t *th, const pthread_attr_t *_attr, void *(*threadrou if (t == NULL) { /* no threads are ready */ + LOG_ERR("No threads are ready"); return EAGAIN; } @@ -402,6 +421,7 @@ int pthread_create(pthread_t *th, const pthread_attr_t *_attr, void *(*threadrou err = pthread_barrier_init(&barrier, NULL, 2); if (err != 0) { if (t->dynamic_stack != NULL) { + LOG_DBG("freeing thread stack at %p", attr->stack); (void)k_thread_stack_free(attr->stack); } @@ -434,6 +454,8 @@ int pthread_create(pthread_t *th, const pthread_attr_t *_attr, void *(*threadrou /* finally provide the initialized thread to the caller */ *th = mark_pthread_obj_initialized(posix_thread_to_offset(t)); + LOG_DBG("Created pthread %p", &t->thread); + return 0; } @@ -449,6 +471,7 @@ int pthread_setcancelstate(int state, int *oldstate) struct posix_thread *t; if (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE) { + LOG_ERR("Invalid pthread state %d", state); return EINVAL; } @@ -513,6 +536,7 @@ int pthread_setschedparam(pthread_t pthread, int policy, const struct sched_para } if (!valid_posix_policy(policy)) { + LOG_ERR("Invalid scheduler policy %d", policy); return EINVAL; } @@ -535,6 +559,7 @@ int pthread_attr_init(pthread_attr_t *attr) { if (attr == NULL) { + LOG_ERR("Invalid attr pointer"); return ENOMEM; } @@ -601,8 +626,10 @@ void pthread_exit(void *retval) self = to_posix_thread(pthread_self()); if (self == NULL) { /* not a valid posix_thread */ - __ASSERT_NO_MSG(self != NULL); + LOG_DBG("Aborting non-pthread %p", k_current_get()); k_thread_abort(k_current_get()); + + CODE_UNREACHABLE; } /* Make a thread as cancelable before exiting */ @@ -621,11 +648,11 @@ void pthread_exit(void *retval) */ int pthread_join(pthread_t pthread, void **status) { - int err; - int ret; struct posix_thread *t; + int ret; if (pthread == pthread_self()) { + LOG_ERR("Pthread attempted to join itself (%x)", pthread); return EDEADLK; } @@ -634,6 +661,8 @@ int pthread_join(pthread_t pthread, void **status) return ESRCH; } + LOG_DBG("Pthread %p joining..", &t->thread); + ret = 0; K_SPINLOCK(&pthread_pool_lock) { @@ -655,15 +684,25 @@ int pthread_join(pthread_t pthread, void **status) t->detachstate = PTHREAD_CREATE_DETACHED; } - if (ret != 0) { + switch (ret) { + case ESRCH: + LOG_ERR("Pthread %p has already been joined", &t->thread); return ret; + case EINVAL: + LOG_ERR("Pthread %p is not a joinable", &t->thread); + return ret; + case 0: + break; } - err = k_thread_join(&t->thread, K_FOREVER); + ret = k_thread_join(&t->thread, K_FOREVER); /* other possibilities? */ - __ASSERT_NO_MSG(err == 0); + __ASSERT_NO_MSG(ret == 0); + + LOG_DBG("Joined pthread %p", &t->thread); if (status != NULL) { + LOG_DBG("Writing status to %p", status); *status = t->retval; } @@ -692,6 +731,7 @@ int pthread_detach(pthread_t pthread) key = k_spin_lock(&pthread_pool_lock); qid = t->qid; if (qid == POSIX_THREAD_READY_Q || t->detachstate != PTHREAD_CREATE_JOINABLE) { + LOG_ERR("Pthread %p cannot be detached", &t->thread); ret = EINVAL; } else { ret = 0; @@ -699,6 +739,10 @@ int pthread_detach(pthread_t pthread) } k_spin_unlock(&pthread_pool_lock, key); + if (ret == 0) { + LOG_DBG("Pthread %p detached", &t->thread); + } + return ret; } diff --git a/lib/posix/timer.c b/lib/posix/timer.c index 11081f1b4d8..39668a1c402 100644 --- a/lib/posix/timer.c +++ b/lib/posix/timer.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,9 @@ struct timer_obj { struct k_timer ztimer; void (*sigev_notify_function)(union sigval val); union sigval val; + int sigev_notify; + struct k_sem sem_cond; + pthread_t thread; struct timespec interval; /* Reload value */ uint32_t reload; /* Reload value in ms */ uint32_t status; @@ -40,6 +44,31 @@ static void zephyr_timer_wrapper(struct k_timer *ztimer) (timer->sigev_notify_function)(timer->val); } +static void *zephyr_thread_wrapper(void *arg) +{ + struct timer_obj *timer = (struct timer_obj *)arg; + + while (1) { + if (timer->reload == 0U) { + timer->status = NOT_ACTIVE; + } + + k_sem_take(&timer->sem_cond, K_FOREVER); + + (timer->sigev_notify_function)(timer->val); + } + + return NULL; +} + +static void zephyr_timer_interrupt(struct k_timer *ztimer) +{ + struct timer_obj *timer; + + timer = (struct timer_obj *)ztimer; + k_sem_give(&timer->sem_cond); +} + /** * @brief Create a per-process timer. * @@ -55,7 +84,8 @@ int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid) if (clockid != CLOCK_MONOTONIC || evp == NULL || (evp->sigev_notify != SIGEV_NONE && - evp->sigev_notify != SIGEV_SIGNAL)) { + evp->sigev_notify != SIGEV_SIGNAL && + evp->sigev_notify != SIGEV_THREAD)) { errno = EINVAL; return -1; } @@ -76,6 +106,20 @@ int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid) if (evp->sigev_notify == SIGEV_NONE) { k_timer_init(&timer->ztimer, NULL, NULL); + } else if (evp->sigev_notify == SIGEV_THREAD) { + int ret; + + timer->sigev_notify = SIGEV_THREAD; + k_sem_init(&timer->sem_cond, 0, 1); + ret = pthread_create(&timer->thread, evp->sigev_notify_attributes, + zephyr_thread_wrapper, timer); + if (ret != 0) { + k_mem_slab_free(&posix_timer_slab, (void *) &timer); + return ret; + } + + pthread_detach(timer->thread); + k_timer_init(&timer->ztimer, zephyr_timer_interrupt, NULL); } else { k_timer_init(&timer->ztimer, zephyr_timer_wrapper, NULL); } @@ -222,6 +266,9 @@ int timer_delete(timer_t timerid) k_timer_stop(&timer->ztimer); } + if (timer->sigev_notify == SIGEV_THREAD) + pthread_cancel(timer->thread); + k_mem_slab_free(&posix_timer_slab, (void *)timer); return 0; diff --git a/misc/generated/generated_header.template b/misc/generated/generated_header.template deleted file mode 100644 index 2b323cd20e1..00000000000 --- a/misc/generated/generated_header.template +++ /dev/null @@ -1 +0,0 @@ -/* WARNING. THIS FILE IS AUTO-GENERATED. DO NOT MODIFY! */ diff --git a/modules/Kconfig b/modules/Kconfig index a2dad7e9c4a..0c1b240efec 100644 --- a/modules/Kconfig +++ b/modules/Kconfig @@ -12,12 +12,9 @@ comment "Available modules." osource "$(KCONFIG_BINARY_DIR)/Kconfig.modules" -comment "Optional modules. Make sure they're installed, via the project manifest." - source "modules/Kconfig.altera" source "modules/Kconfig.atmel" source "modules/Kconfig.chre" -source "modules/cmsis/Kconfig" source "modules/Kconfig.cypress" source "modules/Kconfig.eos_s3" source "modules/Kconfig.esp32" @@ -46,6 +43,7 @@ source "modules/Kconfig.xtensa" source "modules/zcbor/Kconfig" source "modules/Kconfig.mcuboot" source "modules/Kconfig.intel" +source "modules/hostap/Kconfig" comment "Unavailable modules, please install those via the project manifest." @@ -108,6 +106,15 @@ comment "Segger module not available." comment "LVGL module not available." depends on !ZEPHYR_LVGL_MODULE +comment "cmsis module not available." + depends on !ZEPHYR_CMSIS_MODULE + +comment "cmsis-dsp module not available." + depends on !ZEPHYR_CMSIS_DSP_MODULE + +comment "cmsis-nn module not available." + depends on !ZEPHYR_CMSIS_NN_MODULE + # This ensures that symbols are available in Kconfig for dependency checking # and referencing, while keeping the settings themselves unavailable when the # modules are not present in the workspace diff --git a/modules/Kconfig.infineon b/modules/Kconfig.infineon index 348305ccbf7..4147d138de3 100644 --- a/modules/Kconfig.infineon +++ b/modules/Kconfig.infineon @@ -50,4 +50,9 @@ config HAS_XMCLIB_CCU help Enable XMCLIB CCU4/CCU8 +config HAS_XMCLIB_WDT + bool + help + Enable XMCLIB WDT + endif # HAS_XMCLIB diff --git a/modules/Kconfig.libmetal b/modules/Kconfig.libmetal index dd01125e14e..b1575c82902 100644 --- a/modules/Kconfig.libmetal +++ b/modules/Kconfig.libmetal @@ -1,8 +1,12 @@ # Copyright (c) 2018 Linaro Limited # SPDX-License-Identifier: Apache-2.0 +config ZEPHYR_LIBMETAL_MODULE + bool + menuconfig LIBMETAL bool "libmetal Support" + depends on ZEPHYR_LIBMETAL_MODULE help This option enables the libmetal HAL abstraction layer diff --git a/modules/Kconfig.mcux b/modules/Kconfig.mcux index 67377adcbb3..fb5b18a63d3 100644 --- a/modules/Kconfig.mcux +++ b/modules/Kconfig.mcux @@ -5,7 +5,6 @@ config HAS_MCUX bool - select HAS_CMSIS_CORE depends on SOC_FAMILY_KINETIS || SOC_FAMILY_IMX || SOC_FAMILY_LPC || \ SOC_FAMILY_NXP_ADSP || SOC_FAMILY_NXP_S32 diff --git a/modules/Kconfig.open-amp b/modules/Kconfig.open-amp index 5db32041bca..71d2885e5a7 100644 --- a/modules/Kconfig.open-amp +++ b/modules/Kconfig.open-amp @@ -1,8 +1,12 @@ # Copyright (c) 2018 Linaro Limited # SPDX-License-Identifier: Apache-2.0 +config ZEPHYR_OPEN_AMP_MODULE + bool + config OPENAMP bool "OpenAMP Support" + depends on ZEPHYR_OPEN_AMP_MODULE select LIBMETAL help This option enables the OpenAMP IPC library diff --git a/modules/Kconfig.sof b/modules/Kconfig.sof index 17e40df34b5..4a0b9418660 100644 --- a/modules/Kconfig.sof +++ b/modules/Kconfig.sof @@ -1,7 +1,11 @@ # Copyright (c) 2020 Intel Corporation # SPDX-License-Identifier: Apache-2.0 +config ZEPHYR_SOF_MODULE + bool + config SOF bool "Sound Open Firmware (SOF)" + depends on ZEPHYR_SOF_MODULE help Build Sound Open Firmware (SOF) support. diff --git a/modules/Kconfig.st b/modules/Kconfig.st index 2db03e18f77..fd90aee0b17 100644 --- a/modules/Kconfig.st +++ b/modules/Kconfig.st @@ -115,6 +115,9 @@ config USE_STDC_LIS3DSH config USE_STDC_LIS3MDL bool +config USE_STDC_LPS22DF + bool + config USE_STDC_LPS22HB bool diff --git a/modules/Kconfig.tinycrypt b/modules/Kconfig.tinycrypt index 7f279fbc59a..168e05ed799 100644 --- a/modules/Kconfig.tinycrypt +++ b/modules/Kconfig.tinycrypt @@ -3,8 +3,12 @@ # Copyright (c) 2015 Intel Corporation # SPDX-License-Identifier: Apache-2.0 +config ZEPHYR_TINYCRYPT_MODULE + bool + config TINYCRYPT bool "TinyCrypt Support" + depends on ZEPHYR_TINYCRYPT_MODULE help This option enables the TinyCrypt cryptography library. diff --git a/modules/TraceRecorder/CMakeLists.txt b/modules/TraceRecorder/CMakeLists.txt deleted file mode 100644 index a0b4d6ad671..00000000000 --- a/modules/TraceRecorder/CMakeLists.txt +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright (c) 2021, Intel Corporation -# -# SPDX-License-Identifier: Apache-2.0 - -if(CONFIG_PERCEPIO_TRACERECORDER) - - set(TRACERECORDER_DIR ${ZEPHYR_CURRENT_MODULE_DIR}) - - zephyr_library() - zephyr_library_sources_ifdef( - CONFIG_PERCEPIO_TRACERECORDER - ${TRACERECORDER_DIR}/kernelports/Zephyr/trcKernelPort.c - ${TRACERECORDER_DIR}/trcAssert.c - ${TRACERECORDER_DIR}/trcCounter.c - ${TRACERECORDER_DIR}/trcDiagnostics.c - ${TRACERECORDER_DIR}/trcEntryTable.c - ${TRACERECORDER_DIR}/trcError.c - ${TRACERECORDER_DIR}/trcEvent.c - ${TRACERECORDER_DIR}/trcEventBuffer.c - ${TRACERECORDER_DIR}/trcExtension.c - ${TRACERECORDER_DIR}/trcHardwarePort.c - ${TRACERECORDER_DIR}/trcHeap.c - ${TRACERECORDER_DIR}/trcInternalEventBuffer.c - ${TRACERECORDER_DIR}/trcInterval.c - ${TRACERECORDER_DIR}/trcISR.c - ${TRACERECORDER_DIR}/trcMultiCoreEventBuffer.c - ${TRACERECORDER_DIR}/trcObject.c - ${TRACERECORDER_DIR}/trcPrint.c - ${TRACERECORDER_DIR}/trcStackMonitor.c - ${TRACERECORDER_DIR}/trcStateMachine.c - ${TRACERECORDER_DIR}/trcStaticBuffer.c - ${TRACERECORDER_DIR}/trcStreamingRecorder.c - ${TRACERECORDER_DIR}/trcString.c - ${TRACERECORDER_DIR}/trcTask.c - ${TRACERECORDER_DIR}/trcTimestamp.c - ${TRACERECORDER_DIR}/trcDependency.c - ${TRACERECORDER_DIR}/trcRunnable.c - ) - - if(CONFIG_PERCEPIO_TRC_CFG_STREAM_PORT_RTT) - zephyr_library_sources( - ${TRACERECORDER_DIR}/streamports/Jlink_RTT/trcStreamPort.c - ) - - zephyr_include_directories( - ${TRACERECORDER_DIR}/kernelports/Zephyr/streamports/Jlink_RTT/config/ - ${TRACERECORDER_DIR}/streamports/Jlink_RTT/include/ - ) - endif() - - if(CONFIG_PERCEPIO_TRC_CFG_STREAM_PORT_ITM) - zephyr_library_sources( - ${TRACERECORDER_DIR}/streamports/ARM_ITM/trcStreamPort.c - ) - - zephyr_include_directories( - ${TRACERECORDER_DIR}/kernelports/Zephyr/streamports/ARM_ITM/config/ - ${TRACERECORDER_DIR}/streamports/ARM_ITM/include/ - ) - endif() - - if(CONFIG_PERCEPIO_TRC_CFG_STREAM_PORT_RINGBUFFER) - zephyr_library_sources( - ${TRACERECORDER_DIR}/streamports/RingBuffer/trcStreamPort.c - ) - - zephyr_include_directories( - ${TRACERECORDER_DIR}/kernelports/Zephyr/streamports/RingBuffer/config/ - ${TRACERECORDER_DIR}/streamports/RingBuffer/include/ - ) - endif() - - if (CONFIG_PERCEPIO_TRC_CFG_STREAM_PORT_ZEPHYR_SEMIHOST) - zephyr_library_sources( - ${TRACERECORDER_DIR}/kernelports/Zephyr/streamports/Semihost/trcStreamPort.c - ) - - zephyr_include_directories( - ${TRACERECORDER_DIR}/kernelports/Zephyr/streamports/Semihost/config - ${TRACERECORDER_DIR}/kernelports/Zephyr/streamports/Semihost/include - ) - endif() - - zephyr_include_directories( - ${TRACERECORDER_DIR}/kernelports/Zephyr/include - ${TRACERECORDER_DIR}/kernelports/Zephyr/config - ${TRACERECORDER_DIR}/kernelports/Zephyr/config/core - ${TRACERECORDER_DIR}/include - ) - - set_property(GLOBAL APPEND PROPERTY extra_post_build_commands - COMMAND python3 ${TRACERECORDER_DIR}/kernelports/Zephyr/scripts/tz_parse_syscalls.py ${CMAKE_BINARY_DIR} ${ZEPHYR_BASE} - ) - -endif() diff --git a/modules/TraceRecorder/Kconfig b/modules/TraceRecorder/Kconfig deleted file mode 100644 index 2ab8ebd4e80..00000000000 --- a/modules/TraceRecorder/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -# Zephyr module config for TraceRecorder. -# The real Kconfig for the module is located in the module repository, -# this file is to ensure ZEPHYR_TRACERECORDER_MODULE is defined also when the -# module is unavailable. - -# Copyright (c) 2021 Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -config ZEPHYR_TRACERECORDER_MODULE - bool diff --git a/modules/acpica/CMakeLists.txt b/modules/acpica/CMakeLists.txt index 29f685e0266..ad8a75b0230 100644 --- a/modules/acpica/CMakeLists.txt +++ b/modules/acpica/CMakeLists.txt @@ -1,177 +1,179 @@ # Copyright (c) 2023 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -set(ACPI_DIR ${ZEPHYR_CURRENT_MODULE_DIR}/) -set(INC_DIR ${ACPI_DIR}/source/include/) -set(SRC_DIR ${ACPI_DIR}/source) -set(COMP_DIR ${ACPI_DIR}/source/components) -set(PARENT_SRC_DIR ${ACPI_DIR}../../zephyr) -set(ACPI_PARENT_DIR ${ACPI_DIR}/../) +if(CONFIG_ACPI) + set(ACPI_DIR ${ZEPHYR_CURRENT_MODULE_DIR}/) + set(INC_DIR ${ACPI_DIR}/source/include/) + set(SRC_DIR ${ACPI_DIR}/source) + set(COMP_DIR ${ACPI_DIR}/source/components) + set(PARENT_SRC_DIR ${ACPI_DIR}../../zephyr) + set(ACPI_PARENT_DIR ${ACPI_DIR}/../) -zephyr_include_directories( - ${PARENT_SRC_DIR}/include/ - ${ACPI_PARENT_DIR}/ - ${INC_DIR}/ - ${INC_DIR}/platform/ - ${SRC_DIR}/compiler/ - ${ZEPHYR_CURRENT_MODULE_DIR}/generate/zephyr/ - ${SRC_DIR}/tools/acpiexec/ - ${SRC_DIR}/tools/acpidump/ -) + zephyr_include_directories( + ${PARENT_SRC_DIR}/include/ + ${ACPI_PARENT_DIR}/ + ${INC_DIR}/ + ${INC_DIR}/platform/ + ${SRC_DIR}/compiler/ + ${ZEPHYR_CURRENT_MODULE_DIR}/generate/zephyr/ + ${SRC_DIR}/tools/acpiexec/ + ${SRC_DIR}/tools/acpidump/ + ) -if (CONFIG_ACPI) - zephyr_library() + zephyr_library() - add_compile_definitions(__ZEPHYR__) - add_compile_definitions(ACPI_DEBUG_OUTPUT) - add_compile_definitions(ACPI_EXAMPLE_APP) - add_compile_definitions(CONFIG_EXTERNAL_LIBC) + add_compile_definitions(__ZEPHYR__) + add_compile_definitions(ACPI_DEBUG_OUTPUT) + add_compile_definitions(ACPI_EXAMPLE_APP) + add_compile_definitions(CONFIG_EXTERNAL_LIBC) - get_filename_component(libname "${SRC_DIR}/common/" NAME) + get_filename_component(libname "${SRC_DIR}/common/" NAME) - zephyr_library_sources( - ${COMP_DIR}/dispatcher/dsargs.c - ${COMP_DIR}/dispatcher/dscontrol.c - ${COMP_DIR}/dispatcher/dsdebug.c - ${COMP_DIR}/dispatcher/dsfield.c - ${COMP_DIR}/dispatcher/dsinit.c - ${COMP_DIR}/dispatcher/dsmethod.c - ${COMP_DIR}/dispatcher/dsmthdat.c - ${COMP_DIR}/dispatcher/dsobject.c - ${COMP_DIR}/dispatcher/dsopcode.c - ${COMP_DIR}/dispatcher/dspkginit.c - ${COMP_DIR}/dispatcher/dsutils.c - ${COMP_DIR}/dispatcher/dswexec.c - ${COMP_DIR}/dispatcher/dswload.c - ${COMP_DIR}/dispatcher/dswload2.c - ${COMP_DIR}/dispatcher/dswscope.c - ${COMP_DIR}/dispatcher/dswstate.c - - ${COMP_DIR}/events/evhandler.c - ${COMP_DIR}/events/evmisc.c - ${COMP_DIR}/events/evregion.c - ${COMP_DIR}/events/evrgnini.c - ${COMP_DIR}/events/evxface.c - ${COMP_DIR}/events/evxfregn.c - ${COMP_DIR}/executer/exconcat.c - ${COMP_DIR}/executer/exconfig.c - ${COMP_DIR}/executer/exconvrt.c - ${COMP_DIR}/executer/excreate.c - ${COMP_DIR}/executer/exdebug.c - ${COMP_DIR}/executer/exdump.c - ${COMP_DIR}/executer/exfield.c - ${COMP_DIR}/executer/exfldio.c - ${COMP_DIR}/executer/exmisc.c - ${COMP_DIR}/executer/exmutex.c - ${COMP_DIR}/executer/exnames.c - ${COMP_DIR}/executer/exoparg1.c - ${COMP_DIR}/executer/exoparg2.c - ${COMP_DIR}/executer/exoparg3.c - ${COMP_DIR}/executer/exoparg6.c - ${COMP_DIR}/executer/exprep.c - ${COMP_DIR}/executer/exregion.c - ${COMP_DIR}/executer/exresnte.c - ${COMP_DIR}/executer/exresolv.c - ${COMP_DIR}/executer/exresop.c - ${COMP_DIR}/executer/exserial.c - ${COMP_DIR}/executer/exstore.c - ${COMP_DIR}/executer/exstoren.c - ${COMP_DIR}/executer/exstorob.c - ${COMP_DIR}/executer/exsystem.c - ${COMP_DIR}/executer/extrace.c - ${COMP_DIR}/executer/exutils.c - ${COMP_DIR}/hardware/hwpci.c - ${COMP_DIR}/namespace/nsaccess.c - ${COMP_DIR}/namespace/nsalloc.c - ${COMP_DIR}/namespace/nsarguments.c - ${COMP_DIR}/namespace/nsconvert.c - ${COMP_DIR}/namespace/nsdump.c - ${COMP_DIR}/namespace/nseval.c - ${COMP_DIR}/namespace/nsinit.c - ${COMP_DIR}/namespace/nsload.c - ${COMP_DIR}/namespace/nsnames.c - ${COMP_DIR}/namespace/nsobject.c - ${COMP_DIR}/namespace/nsparse.c - ${COMP_DIR}/namespace/nspredef.c - ${COMP_DIR}/namespace/nsprepkg.c - ${COMP_DIR}/namespace/nsrepair.c - ${COMP_DIR}/namespace/nsrepair2.c - ${COMP_DIR}/namespace/nssearch.c - ${COMP_DIR}/namespace/nsutils.c - ${COMP_DIR}/namespace/nswalk.c - ${COMP_DIR}/namespace/nsxfeval.c - ${COMP_DIR}/namespace/nsxfname.c - ${COMP_DIR}/namespace/nsxfobj.c - ${COMP_DIR}/parser/psargs.c - ${COMP_DIR}/parser/psloop.c - ${COMP_DIR}/parser/psobject.c - ${COMP_DIR}/parser/psopcode.c - ${COMP_DIR}/parser/psopinfo.c - ${COMP_DIR}/parser/psparse.c - ${COMP_DIR}/parser/psscope.c - ${COMP_DIR}/parser/pstree.c - ${COMP_DIR}/parser/psutils.c - ${COMP_DIR}/parser/pswalk.c - ${COMP_DIR}/parser/psxface.c - ${COMP_DIR}/tables/tbdata.c - ${COMP_DIR}/tables/tbfadt.c - ${COMP_DIR}/tables/tbfind.c - ${COMP_DIR}/tables/tbinstal.c - ${COMP_DIR}/tables/tbprint.c - ${COMP_DIR}/tables/tbutils.c - ${COMP_DIR}/tables/tbxface.c - ${COMP_DIR}/tables/tbxfload.c - ${COMP_DIR}/tables/tbxfroot.c - ${COMP_DIR}/utilities/utaddress.c - ${COMP_DIR}/utilities/utalloc.c - ${COMP_DIR}/utilities/utascii.c - ${COMP_DIR}/utilities/utbuffer.c - ${COMP_DIR}/utilities/utcache.c - ${COMP_DIR}/utilities/utcksum.c - ${COMP_DIR}/utilities/utcopy.c - ${COMP_DIR}/utilities/utdebug.c - ${COMP_DIR}/utilities/utdecode.c - ${COMP_DIR}/utilities/utdelete.c - ${COMP_DIR}/utilities/uterror.c - ${COMP_DIR}/utilities/uteval.c - ${COMP_DIR}/utilities/utexcep.c - ${COMP_DIR}/utilities/utglobal.c - ${COMP_DIR}/utilities/uthex.c - ${COMP_DIR}/utilities/utids.c - ${COMP_DIR}/utilities/utinit.c - ${COMP_DIR}/utilities/utlock.c - ${COMP_DIR}/utilities/utmath.c - ${COMP_DIR}/utilities/utmisc.c - ${COMP_DIR}/utilities/utmutex.c - ${COMP_DIR}/utilities/utobject.c - ${COMP_DIR}/utilities/utosi.c - ${COMP_DIR}/utilities/utownerid.c - ${COMP_DIR}/utilities/utnonansi.c - ${COMP_DIR}/utilities/utpredef.c - ${COMP_DIR}/utilities/utresrc.c - ${COMP_DIR}/utilities/utstate.c - ${COMP_DIR}/utilities/utstring.c - ${COMP_DIR}/utilities/utstrsuppt.c - ${COMP_DIR}/utilities/utstrtoul64.c - ${COMP_DIR}/utilities/utxface.c - ${COMP_DIR}/utilities/utxferror.c - ${COMP_DIR}/utilities/utxfinit.c - ${COMP_DIR}/utilities/utresdecode.c - ${COMP_DIR}/hardware/hwvalid.c - ${COMP_DIR}/resources/rsxface.c - ${COMP_DIR}/resources/rsutils.c - ${COMP_DIR}/resources/rsaddr.c - ${COMP_DIR}/resources/rscalc.c - ${COMP_DIR}/resources/rscreate.c - ${COMP_DIR}/resources/rsdumpinfo.c - ${COMP_DIR}/resources/rsinfo.c - ${COMP_DIR}/resources/rsio.c - ${COMP_DIR}/resources/rsirq.c - ${COMP_DIR}/resources/rslist.c - ${COMP_DIR}/resources/rsmemory.c - ${COMP_DIR}/resources/rsmisc.c - ${COMP_DIR}/resources/rsserial.c - - ${SRC_DIR}/os_specific/service_layers/oszephyr.c - ) -endif (CONFIG_ACPI) + if(CONFIG_ACPI_DSDT_SUPPORT) + zephyr_library_sources( + ${COMP_DIR}/dispatcher/dsargs.c + ${COMP_DIR}/dispatcher/dscontrol.c + ${COMP_DIR}/dispatcher/dsdebug.c + ${COMP_DIR}/dispatcher/dsfield.c + ${COMP_DIR}/dispatcher/dsinit.c + ${COMP_DIR}/dispatcher/dsmethod.c + ${COMP_DIR}/dispatcher/dsmthdat.c + ${COMP_DIR}/dispatcher/dsobject.c + ${COMP_DIR}/dispatcher/dsopcode.c + ${COMP_DIR}/dispatcher/dspkginit.c + ${COMP_DIR}/dispatcher/dsutils.c + ${COMP_DIR}/dispatcher/dswexec.c + ${COMP_DIR}/dispatcher/dswload.c + ${COMP_DIR}/dispatcher/dswload2.c + ${COMP_DIR}/dispatcher/dswscope.c + ${COMP_DIR}/dispatcher/dswstate.c + ${COMP_DIR}/events/evhandler.c + ${COMP_DIR}/events/evmisc.c + ${COMP_DIR}/events/evregion.c + ${COMP_DIR}/events/evrgnini.c + ${COMP_DIR}/events/evxface.c + ${COMP_DIR}/events/evxfregn.c + ${COMP_DIR}/executer/exconcat.c + ${COMP_DIR}/executer/exconfig.c + ${COMP_DIR}/executer/exconvrt.c + ${COMP_DIR}/executer/excreate.c + ${COMP_DIR}/executer/exdebug.c + ${COMP_DIR}/executer/exdump.c + ${COMP_DIR}/executer/exfield.c + ${COMP_DIR}/executer/exfldio.c + ${COMP_DIR}/executer/exmisc.c + ${COMP_DIR}/executer/exmutex.c + ${COMP_DIR}/executer/exnames.c + ${COMP_DIR}/executer/exoparg1.c + ${COMP_DIR}/executer/exoparg2.c + ${COMP_DIR}/executer/exoparg3.c + ${COMP_DIR}/executer/exoparg6.c + ${COMP_DIR}/executer/exprep.c + ${COMP_DIR}/executer/exregion.c + ${COMP_DIR}/executer/exresnte.c + ${COMP_DIR}/executer/exresolv.c + ${COMP_DIR}/executer/exresop.c + ${COMP_DIR}/executer/exserial.c + ${COMP_DIR}/executer/exstore.c + ${COMP_DIR}/executer/exstoren.c + ${COMP_DIR}/executer/exstorob.c + ${COMP_DIR}/executer/exsystem.c + ${COMP_DIR}/executer/extrace.c + ${COMP_DIR}/executer/exutils.c + ${COMP_DIR}/hardware/hwpci.c + ${COMP_DIR}/namespace/nsaccess.c + ${COMP_DIR}/namespace/nsalloc.c + ${COMP_DIR}/namespace/nsarguments.c + ${COMP_DIR}/namespace/nsconvert.c + ${COMP_DIR}/namespace/nsdump.c + ${COMP_DIR}/namespace/nseval.c + ${COMP_DIR}/namespace/nsinit.c + ${COMP_DIR}/namespace/nsload.c + ${COMP_DIR}/namespace/nsnames.c + ${COMP_DIR}/namespace/nsobject.c + ${COMP_DIR}/namespace/nsparse.c + ${COMP_DIR}/namespace/nspredef.c + ${COMP_DIR}/namespace/nsprepkg.c + ${COMP_DIR}/namespace/nsrepair.c + ${COMP_DIR}/namespace/nsrepair2.c + ${COMP_DIR}/namespace/nssearch.c + ${COMP_DIR}/namespace/nsutils.c + ${COMP_DIR}/namespace/nswalk.c + ${COMP_DIR}/namespace/nsxfeval.c + ${COMP_DIR}/namespace/nsxfname.c + ${COMP_DIR}/namespace/nsxfobj.c + ${COMP_DIR}/parser/psargs.c + ${COMP_DIR}/parser/psloop.c + ${COMP_DIR}/parser/psobject.c + ${COMP_DIR}/parser/psopcode.c + ${COMP_DIR}/parser/psopinfo.c + ${COMP_DIR}/parser/psparse.c + ${COMP_DIR}/parser/psscope.c + ${COMP_DIR}/parser/pstree.c + ${COMP_DIR}/parser/psutils.c + ${COMP_DIR}/parser/pswalk.c + ${COMP_DIR}/parser/psxface.c + ${COMP_DIR}/resources/rsxface.c + ${COMP_DIR}/resources/rsutils.c + ${COMP_DIR}/resources/rsaddr.c + ${COMP_DIR}/resources/rscalc.c + ${COMP_DIR}/resources/rscreate.c + ${COMP_DIR}/resources/rsdumpinfo.c + ${COMP_DIR}/resources/rsinfo.c + ${COMP_DIR}/resources/rsio.c + ${COMP_DIR}/resources/rsirq.c + ${COMP_DIR}/resources/rslist.c + ${COMP_DIR}/resources/rsmemory.c + ${COMP_DIR}/resources/rsmisc.c + ${COMP_DIR}/resources/rsserial.c + ) + endif() + zephyr_library_sources( + ${COMP_DIR}/tables/tbdata.c + ${COMP_DIR}/tables/tbfadt.c + ${COMP_DIR}/tables/tbfind.c + ${COMP_DIR}/tables/tbinstal.c + ${COMP_DIR}/tables/tbprint.c + ${COMP_DIR}/tables/tbutils.c + ${COMP_DIR}/tables/tbxface.c + ${COMP_DIR}/tables/tbxfload.c + ${COMP_DIR}/tables/tbxfroot.c + ${COMP_DIR}/utilities/utaddress.c + ${COMP_DIR}/utilities/utalloc.c + ${COMP_DIR}/utilities/utascii.c + ${COMP_DIR}/utilities/utbuffer.c + ${COMP_DIR}/utilities/utcache.c + ${COMP_DIR}/utilities/utcksum.c + ${COMP_DIR}/utilities/utcopy.c + ${COMP_DIR}/utilities/utdebug.c + ${COMP_DIR}/utilities/utdecode.c + ${COMP_DIR}/utilities/utdelete.c + ${COMP_DIR}/utilities/uterror.c + ${COMP_DIR}/utilities/uteval.c + ${COMP_DIR}/utilities/utexcep.c + ${COMP_DIR}/utilities/utglobal.c + ${COMP_DIR}/utilities/uthex.c + ${COMP_DIR}/utilities/utids.c + ${COMP_DIR}/utilities/utinit.c + ${COMP_DIR}/utilities/utlock.c + ${COMP_DIR}/utilities/utmath.c + ${COMP_DIR}/utilities/utmisc.c + ${COMP_DIR}/utilities/utmutex.c + ${COMP_DIR}/utilities/utobject.c + ${COMP_DIR}/utilities/utosi.c + ${COMP_DIR}/utilities/utownerid.c + ${COMP_DIR}/utilities/utnonansi.c + ${COMP_DIR}/utilities/utpredef.c + ${COMP_DIR}/utilities/utresrc.c + ${COMP_DIR}/utilities/utstate.c + ${COMP_DIR}/utilities/utstring.c + ${COMP_DIR}/utilities/utstrsuppt.c + ${COMP_DIR}/utilities/utstrtoul64.c + ${COMP_DIR}/utilities/utxface.c + ${COMP_DIR}/utilities/utxferror.c + ${COMP_DIR}/utilities/utxfinit.c + ${COMP_DIR}/utilities/utresdecode.c + ${COMP_DIR}/hardware/hwvalid.c + ${SRC_DIR}/os_specific/service_layers/oszephyr.c + ) +endif() diff --git a/modules/acpica/Kconfig b/modules/acpica/Kconfig index 07d6d24c278..18e7cd1482a 100644 --- a/modules/acpica/Kconfig +++ b/modules/acpica/Kconfig @@ -1,9 +1,19 @@ # Copyright (c) 2023 Intel Corporation. # SPDX-License-Identifier: Apache-2.0 +menu "ACPI driver support" + config ACPI bool -menu "ACPI driver support" +if ACPI + +config ACPI_DSDT_SUPPORT + bool "Build source code for DSDT ACPICA support" + default y if PCIE + help + Build source code for DSDT support + +endif #ACPI endmenu diff --git a/modules/canopennode/CO_driver_target.h b/modules/canopennode/CO_driver_target.h index 3e76b5290b0..27b1f1caa9d 100644 --- a/modules/canopennode/CO_driver_target.h +++ b/modules/canopennode/CO_driver_target.h @@ -22,6 +22,7 @@ extern "C" { #include #include #include +#include /* float32_t, float64_t */ /* Use static variables instead of calloc() */ #define CO_USE_GLOBALS @@ -46,12 +47,13 @@ extern "C" { #endif typedef bool bool_t; -typedef float float32_t; -typedef long double float64_t; typedef char char_t; typedef unsigned char oChar_t; typedef unsigned char domain_t; +BUILD_ASSERT(sizeof(float32_t) >= 4); +BUILD_ASSERT(sizeof(float64_t) >= 8); + typedef struct canopen_rx_msg { uint8_t data[8]; uint16_t ident; diff --git a/modules/cmsis-dsp/CMakeLists.txt b/modules/cmsis-dsp/CMakeLists.txt new file mode 100644 index 00000000000..9afaa32b89d --- /dev/null +++ b/modules/cmsis-dsp/CMakeLists.txt @@ -0,0 +1,931 @@ +# Copyright (c) 2023 Meta Platforms +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_CMSIS_DSP) + + set(CMSIS_DSP_DIR ${ZEPHYR_CURRENT_MODULE_DIR}) + set(cmsis_glue_path ${ZEPHYR_CMSIS_MODULE_DIR}) + + zephyr_library() + + zephyr_library_compile_options(-Ofast) + + zephyr_include_directories( + ${CMSIS_DSP_DIR}/Include + ) + + zephyr_library_include_directories( + ${CMSIS_DSP_DIR}/PrivateInclude + ${cmsis_glue_path}/CMSIS/Core/Include + ) + + # Global Feature Definitions + zephyr_library_compile_definitions_ifdef(CONFIG_CMSIS_DSP_NEON ARM_MATH_NEON) + zephyr_library_compile_definitions_ifdef(CONFIG_CMSIS_DSP_NEON_EXPERIMENTAL ARM_MATH_NEON_EXPERIMENTAL) + zephyr_library_compile_definitions_ifdef(CONFIG_CMSIS_DSP_LOOPUNROLL ARM_MATH_LOOPUNROLL) + zephyr_library_compile_definitions_ifdef(CONFIG_CMSIS_DSP_ROUNDING ARM_MATH_ROUNDING) + zephyr_library_compile_definitions_ifdef(CONFIG_CMSIS_DSP_MATRIXCHECK ARM_MATH_MATRIX_CHECK) + zephyr_library_compile_definitions_ifndef(CONFIG_CMSIS_DSP_FLOAT16 DISABLEFLOAT16) + zephyr_library_compile_definitions_ifdef(CONFIG_CMSIS_DSP_AUTOVECTORIZE ARM_MATH_AUTOVECTORIZE) + + # Helium is automatically enabled by CMSIS-DSP if the processor supports it + zephyr_library_compile_definitions_ifdef(CONFIG_CMSIS_DSP_HELIUM_EXPERIMENTAL ARM_MATH_HELIUM_EXPERIMENTAL) + + zephyr_compile_definitions_ifndef(CONFIG_ARM __GNUC_PYTHON__) + + if (CONFIG_CMSIS_DSP_NEON OR CONFIG_CMSIS_DSP_NEON_EXPERIMENTAL) + zephyr_library_include_directories("${CMSIS_DSP_DIR}/ComputeLibrary/Include") + endif() + + if (CONFIG_ARMV8_1_M_MVEI OR CONFIG_ARMV8_1_M_MVEF) + if (CONFIG_CMSIS_DSP_LAX_VECTOR_CONVERSIONS) + zephyr_library_compile_options($<$:-flax-vector-conversions>) + zephyr_library_compile_options($<$:-flax-vector-conversions=integer>) + else() + zephyr_library_compile_options($<$:-fno-lax-vector-conversions>) + zephyr_library_compile_options($<$:-flax-vector-conversions=none>) + endif() + endif() + + zephyr_library_compile_options(-Ofast) + + zephyr_compile_definitions_ifndef(CONFIG_ARM __GNUC_PYTHON__) + + # BasicMathFunctions + + set(SRCF64 ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_abs_f64.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_add_f64.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_dot_prod_f64.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_mult_f64.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_negate_f64.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_offset_f64.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_scale_f64.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_sub_f64.c + ) + + set(SRCF32 ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_abs_f32.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_add_f32.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_clip_f32.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_dot_prod_f32.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_mult_f32.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_negate_f32.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_offset_f32.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_scale_f32.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_sub_f32.c + ) + + set(SRCF16 ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_abs_f16.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_add_f16.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_clip_f16.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_dot_prod_f16.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_mult_f16.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_negate_f16.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_offset_f16.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_scale_f16.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_sub_f16.c + ) + + set(SRCQ31 ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_abs_q31.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_add_q31.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_clip_q31.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_dot_prod_q31.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_mult_q31.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_negate_q31.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_offset_q31.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_scale_q31.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_shift_q31.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_sub_q31.c + ) + + set(SRCQ15 ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_abs_q15.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_add_q15.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_clip_q15.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_dot_prod_q15.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_mult_q15.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_negate_q15.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_offset_q15.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_scale_q15.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_shift_q15.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_sub_q15.c + ) + + set(SRCQ7 ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_abs_q7.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_add_q7.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_clip_q7.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_dot_prod_q7.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_mult_q7.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_negate_q7.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_offset_q7.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_scale_q7.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_shift_q7.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_sub_q7.c + ) + + set(SRCU32 ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_and_u32.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_not_u32.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_or_u32.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_xor_u32.c + ) + + set(SRCU16 ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_and_u16.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_not_u16.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_or_u16.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_xor_u16.c + ) + + set(SRCU8 ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_and_u8.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_or_u8.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_not_u8.c + ${CMSIS_DSP_DIR}/Source/BasicMathFunctions/arm_xor_u8.c) + + zephyr_library_sources(${SRCF64}) + zephyr_library_sources(${SRCF32}) + + if ((NOT ARMAC5) AND (NOT DISABLEFLOAT16)) + zephyr_library_sources(${SRCF16}) + endif() + + zephyr_library_sources(${SRCQ31}) + zephyr_library_sources(${SRCQ15}) + zephyr_library_sources(${SRCQ7}) + + zephyr_library_sources(${SRCU32}) + zephyr_library_sources(${SRCU16}) + zephyr_library_sources(${SRCU8}) + + # BayesFunctions + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/BayesFunctions/arm_gaussian_naive_bayes_predict_f32.c) + + if ((NOT ARMAC5) AND (NOT DISABLEFLOAT16)) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/BayesFunctions/arm_gaussian_naive_bayes_predict_f16.c) + endif() + + # Common Tables + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/CommonTables/arm_common_tables.c + ${CMSIS_DSP_DIR}/Source/CommonTables/arm_common_tables_f16.c) + + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/CommonTables/arm_const_structs.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/CommonTables/arm_const_structs_f16.c) + + + if (CONFIG_CMSIS_DSP_NEON OR CONFIG_CMSIS_DSP_NEON_EXPERIMENTAL) + zephyr_library_sources("${CMSIS_DSP_DIR}/ComputeLibrary/Source/arm_cl_tables.c") + endif() + + if (CONFIG_ARMV8_1_M_MVEI OR CONFIG_ARMV8_1_M_MVEF) + zephyr_library_sources("${CMSIS_DSP_DIR}/Source/CommonTables/arm_mve_tables.c") + zephyr_library_sources("${CMSIS_DSP_DIR}/Source/CommonTables/arm_mve_tables_f16.c") + endif() + + + if (WRAPPER) + target_compile_definitions(CMSISDSP PUBLIC ARM_TABLE_BITREV_1024) + target_compile_definitions(CMSISDSP PUBLIC ARM_TABLE_TWIDDLECOEF_F32_4096) + target_compile_definitions(CMSISDSP PUBLIC ARM_TABLE_TWIDDLECOEF_Q31_4096) + target_compile_definitions(CMSISDSP PUBLIC ARM_TABLE_TWIDDLECOEF_Q15_4096) + if ((NOT ARMAC5) AND (NOT DISABLEFLOAT16)) + target_compile_definitions(CMSISDSP PUBLIC ARM_TABLE_TWIDDLECOEF_F16_4096) + endif() + endif() + + # ComplexMathFunctions + # MVE code is using a table for computing the fast sqrt arm_cmplx_mag_q31 + # There is the possibility of not compiling this function and not including + # the table. + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_mag_q31.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_mag_q15.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_mag_fast_q15.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_conj_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_conj_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_conj_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_dot_prod_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_dot_prod_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_dot_prod_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_mag_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_mag_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_mag_squared_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_mag_squared_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_mag_squared_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_mag_squared_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_mult_cmplx_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_mult_cmplx_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_mult_cmplx_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_mult_cmplx_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_mult_real_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_mult_real_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_mult_real_q31.c) + + if ((NOT ARMAC5) AND (NOT DISABLEFLOAT16)) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_conj_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_dot_prod_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_mag_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_mag_squared_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_mult_cmplx_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ComplexMathFunctions/arm_cmplx_mult_real_f16.c) + endif() + + # Controller Functions + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ControllerFunctions/arm_pid_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ControllerFunctions/arm_pid_init_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ControllerFunctions/arm_pid_init_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ControllerFunctions/arm_pid_reset_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ControllerFunctions/arm_pid_reset_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ControllerFunctions/arm_pid_reset_q31.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ControllerFunctions/arm_sin_cos_f32.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/ControllerFunctions/arm_sin_cos_q31.c) + + # Distance Functions + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_boolean_distance.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_braycurtis_distance_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_canberra_distance_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_chebyshev_distance_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_chebyshev_distance_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_cityblock_distance_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_cityblock_distance_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_correlation_distance_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_cosine_distance_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_cosine_distance_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_dice_distance.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_euclidean_distance_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_euclidean_distance_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_hamming_distance.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_jaccard_distance.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_jensenshannon_distance_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_kulsinski_distance.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_minkowski_distance_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_rogerstanimoto_distance.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_russellrao_distance.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_sokalmichener_distance.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_sokalsneath_distance.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_yule_distance.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_dtw_distance_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_dtw_path_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_dtw_init_window_q7.c) + + + zephyr_library_include_directories("${CMSIS_DSP_DIR}/Source/DistanceFunctions") + + if ((NOT ARMAC5) AND (NOT DISABLEFLOAT16)) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_braycurtis_distance_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_canberra_distance_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_chebyshev_distance_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_cityblock_distance_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_correlation_distance_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_cosine_distance_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_euclidean_distance_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_jensenshannon_distance_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/DistanceFunctions/arm_minkowski_distance_f16.c) + endif() + + # Fast Math Functions + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_cos_f32.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_cos_q15.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_cos_q31.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_sin_f32.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_sin_q15.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_sin_q31.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_sqrt_q31.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_sqrt_q15.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_vlog_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_vlog_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_vexp_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_vexp_f64.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_vlog_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_vlog_q15.c) + + + if ((NOT ARMAC5) AND (NOT DISABLEFLOAT16)) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_vlog_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_vexp_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_vinverse_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_atan2_f16.c) + endif() + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_divide_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_divide_q31.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_atan2_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_atan2_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FastMathFunctions/arm_atan2_q15.c) + + # Filtering Functions + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_lms_norm_init_q31.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_lms_norm_init_q15.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_df1_32x64_init_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_df1_32x64_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_df1_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_df1_fast_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_df1_fast_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_df1_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_df1_init_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_df1_init_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_df1_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_df1_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_df2T_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_df2T_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_df2T_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_df2T_init_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_stereo_df2T_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_stereo_df2T_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_conv_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_conv_fast_opt_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_conv_fast_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_conv_fast_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_conv_opt_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_conv_opt_q7.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_conv_partial_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_conv_partial_fast_opt_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_conv_partial_fast_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_conv_partial_fast_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_conv_partial_opt_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_conv_partial_opt_q7.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_conv_partial_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_conv_partial_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_conv_partial_q7.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_conv_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_conv_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_conv_q7.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_correlate_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_correlate_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_correlate_fast_opt_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_correlate_fast_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_correlate_fast_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_correlate_opt_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_correlate_opt_q7.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_correlate_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_correlate_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_correlate_q7.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_decimate_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_decimate_fast_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_decimate_fast_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_decimate_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_decimate_init_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_decimate_init_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_decimate_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_decimate_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_fast_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_fast_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_init_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_init_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_init_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_init_q7.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_interpolate_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_interpolate_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_interpolate_init_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_interpolate_init_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_interpolate_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_interpolate_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_lattice_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_lattice_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_lattice_init_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_lattice_init_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_lattice_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_lattice_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_q7.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_sparse_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_sparse_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_sparse_init_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_sparse_init_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_sparse_init_q7.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_sparse_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_sparse_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_sparse_q7.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_iir_lattice_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_iir_lattice_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_iir_lattice_init_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_iir_lattice_init_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_iir_lattice_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_iir_lattice_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_lms_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_lms_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_lms_init_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_lms_init_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_lms_norm_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_lms_norm_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_lms_norm_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_lms_norm_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_lms_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_lms_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_levinson_durbin_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_levinson_durbin_q31.c) + + if ((NOT ARMAC5) AND (NOT DISABLEFLOAT16)) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_fir_init_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_df1_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_df1_init_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_df2T_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_df2T_init_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_stereo_df2T_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_biquad_cascade_stereo_df2T_init_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_correlate_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/FilteringFunctions/arm_levinson_durbin_f16.c) + endif() + + # Interpolation Functions + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/InterpolationFunctions/arm_bilinear_interp_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/InterpolationFunctions/arm_bilinear_interp_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/InterpolationFunctions/arm_bilinear_interp_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/InterpolationFunctions/arm_bilinear_interp_q7.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/InterpolationFunctions/arm_linear_interp_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/InterpolationFunctions/arm_linear_interp_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/InterpolationFunctions/arm_linear_interp_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/InterpolationFunctions/arm_linear_interp_q7.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/InterpolationFunctions/arm_spline_interp_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/InterpolationFunctions/arm_spline_interp_init_f32.c) + + + + if ((NOT ARMAC5) AND (NOT DISABLEFLOAT16)) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/InterpolationFunctions/arm_bilinear_interp_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/InterpolationFunctions/arm_linear_interp_f16.c) + endif() + + # Matrix Functions + set(SRCF64 ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_cholesky_f64.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_inverse_f64.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_ldlt_f64.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_mult_f64.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_solve_lower_triangular_f64.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_solve_upper_triangular_f64.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_sub_f64.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_trans_f64.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_qr_f64.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_householder_f64.c + ) + + set(SRCF32 ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_add_f32.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_cholesky_f32.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_cmplx_mult_f32.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_cmplx_trans_f32.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_init_f32.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_inverse_f32.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_ldlt_f32.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_mult_f32.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_scale_f32.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_solve_lower_triangular_f32.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_solve_upper_triangular_f32.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_sub_f32.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_trans_f32.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_vec_mult_f32.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_qr_f32.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_householder_f32.c + ) + + set(SRCQ31 ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_add_q31.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_cmplx_mult_q31.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_cmplx_trans_q31.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_init_q31.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_mult_fast_q31.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_mult_opt_q31.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_mult_q31.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_scale_q31.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_sub_q31.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_trans_q31.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_vec_mult_q31.c + ) + + set(SRCQ15 ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_add_q15.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_cmplx_mult_q15.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_cmplx_trans_q15.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_init_q15.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_mult_fast_q15.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_mult_q15.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_scale_q15.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_sub_q15.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_trans_q15.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_vec_mult_q15.c + ) + + set(SRCQ7 ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_mult_q7.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_vec_mult_q7.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_trans_q7.c + ) + + + zephyr_library_sources(${SRCF64}) + zephyr_library_sources(${SRCF32}) + + zephyr_library_sources(${SRCQ31}) + zephyr_library_sources(${SRCQ15}) + zephyr_library_sources(${SRCQ7}) + + + if ((NOT ARMAC5) AND (NOT DISABLEFLOAT16)) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_add_f16.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_cholesky_f16.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_cmplx_mult_f16.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_cmplx_trans_f16.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_init_f16.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_inverse_f16.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_mult_f16.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_scale_f16.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_solve_lower_triangular_f16.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_solve_upper_triangular_f16.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_sub_f16.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_trans_f16.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_vec_mult_f16.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_mat_qr_f16.c + ${CMSIS_DSP_DIR}/Source/MatrixFunctions/arm_householder_f16.c + ) + endif() + + # Quaternion Math Functions + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/QuaternionMathFunctions/arm_quaternion_norm_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/QuaternionMathFunctions/arm_quaternion_inverse_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/QuaternionMathFunctions/arm_quaternion_conjugate_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/QuaternionMathFunctions/arm_quaternion_normalize_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/QuaternionMathFunctions/arm_quaternion_product_single_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/QuaternionMathFunctions/arm_quaternion_product_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/QuaternionMathFunctions/arm_quaternion2rotation_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/QuaternionMathFunctions/arm_rotation2quaternion_f32.c) + + # Statistics Functions + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_entropy_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_entropy_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_kullback_leibler_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_kullback_leibler_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_logsumexp_dot_prod_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_logsumexp_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_max_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_max_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_max_no_idx_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_max_no_idx_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_min_no_idx_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_min_no_idx_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_max_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_max_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_max_q7.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_max_no_idx_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_max_no_idx_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_max_no_idx_q7.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_mean_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_mean_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_mean_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_mean_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_mean_q7.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_min_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_min_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_min_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_min_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_min_q7.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_min_no_idx_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_min_no_idx_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_min_no_idx_q7.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_power_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_power_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_power_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_power_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_power_q7.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_rms_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_rms_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_rms_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_std_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_std_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_std_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_std_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_var_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_var_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_var_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_var_q31.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmax_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmax_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmax_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmax_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmax_q7.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmin_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmin_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmin_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmin_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmin_q7.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmax_no_idx_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmax_no_idx_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmax_no_idx_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmax_no_idx_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmax_no_idx_q7.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmin_no_idx_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmin_no_idx_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmin_no_idx_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmin_no_idx_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmin_no_idx_q7.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_mse_q7.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_mse_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_mse_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_mse_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_mse_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_mse_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_accumulate_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_accumulate_f32.c) + + + if ((NOT ARMAC5) AND (NOT DISABLEFLOAT16)) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_max_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_min_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_mean_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_power_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_rms_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_std_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_var_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_entropy_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_kullback_leibler_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_logsumexp_dot_prod_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_logsumexp_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_max_no_idx_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_min_no_idx_f16.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmax_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmin_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmax_no_idx_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_absmin_no_idx_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/StatisticsFunctions/arm_accumulate_f16.c) + endif() + + # Support Functions + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_barycenter_f32.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_bitonic_sort_f32.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_bubble_sort_f32.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_copy_f32.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_copy_f64.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_copy_q15.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_copy_q31.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_copy_q7.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_f16_to_float.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_f16_to_q15.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_fill_f32.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_fill_f64.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_fill_q15.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_fill_q31.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_fill_q7.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_f64_to_float.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_f64_to_q31.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_f64_to_q15.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_f64_to_q7.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_float_to_f64.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_float_to_q15.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_float_to_q31.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_float_to_q7.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_heap_sort_f32.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_insertion_sort_f32.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_merge_sort_f32.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_merge_sort_init_f32.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_q15_to_f64.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_q15_to_float.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_q15_to_q31.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_q15_to_q7.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_q31_to_f64.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_q31_to_float.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_q31_to_q15.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_q31_to_q7.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_q7_to_f64.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_q7_to_float.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_q7_to_q15.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_q7_to_q31.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_quick_sort_f32.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_selection_sort_f32.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_sort_f32.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_sort_init_f32.c + ${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_weighted_sum_f32.c + ) + + if ((NOT ARMAC5) AND (NOT DISABLEFLOAT16)) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_copy_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_fill_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_f16_to_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_q15_to_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_float_to_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_f16_to_float.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_weighted_sum_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_barycenter_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_f16_to_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SupportFunctions/arm_f64_to_f16.c) + endif() + + # SVM Functions + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SVMFunctions/arm_svm_linear_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SVMFunctions/arm_svm_rbf_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SVMFunctions/arm_svm_linear_predict_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SVMFunctions/arm_svm_rbf_predict_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SVMFunctions/arm_svm_polynomial_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SVMFunctions/arm_svm_sigmoid_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SVMFunctions/arm_svm_polynomial_predict_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SVMFunctions/arm_svm_sigmoid_predict_f32.c) + + if ((NOT ARMAC5) AND (NOT DISABLEFLOAT16)) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SVMFunctions/arm_svm_linear_init_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SVMFunctions/arm_svm_rbf_init_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SVMFunctions/arm_svm_linear_predict_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SVMFunctions/arm_svm_rbf_predict_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SVMFunctions/arm_svm_polynomial_init_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SVMFunctions/arm_svm_sigmoid_init_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SVMFunctions/arm_svm_polynomial_predict_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/SVMFunctions/arm_svm_sigmoid_predict_f16.c) + endif() + + # Transform Functions + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_bitreversal.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_bitreversal2.c) + + if ((NOT ARMAC5) AND (NOT DISABLEFLOAT16)) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_bitreversal_f16.c) + endif() + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix2_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix4_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix8_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_init_f32.c) + + if ((NOT ARMAC5) AND (NOT DISABLEFLOAT16)) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix2_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix4_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_init_f16.c) + endif() + + if ((NOT ARMAC5) AND (NOT DISABLEFLOAT16)) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix4_init_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix4_f16.c) + endif() + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_init_f64.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix2_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix4_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_init_q15.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix2_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix4_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_init_q31.c) + + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_dct4_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_dct4_init_f32.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_rfft_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_rfft_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix4_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix4_f32.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_dct4_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_dct4_init_q31.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_rfft_init_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_rfft_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_init_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix4_init_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix4_q31.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_dct4_init_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_dct4_q15.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_rfft_init_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_rfft_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_init_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix4_init_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix4_q15.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_rfft_fast_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_rfft_fast_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix8_f32.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_rfft_fast_f64.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_rfft_fast_init_f64.c) + + if ((NOT ARMAC5) AND (NOT DISABLEFLOAT16)) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_rfft_fast_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_rfft_fast_init_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_init_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix8_f16.c) + endif() + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_rfft_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_rfft_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix4_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix4_f32.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_rfft_init_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_rfft_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_init_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix4_q15.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_rfft_init_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_rfft_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_init_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix4_q31.c) + + if (WRAPPER) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix2_init_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix2_init_q31.c) + endif() + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix4_init_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix4_init_q31.c) + + + # For scipy or wrappers or benchmarks + if (WRAPPER) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix2_init_f32.c) + if ((NOT ARMAC5) AND (NOT DISABLEFLOAT16)) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_cfft_radix2_init_f16.c) + endif() + endif() + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_mfcc_init_f32.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_mfcc_f32.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_mfcc_init_q31.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_mfcc_q31.c) + + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_mfcc_init_q15.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_mfcc_q15.c) + + if ((NOT ARMAC5) AND (NOT DISABLEFLOAT16)) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_mfcc_init_f16.c) + zephyr_library_sources(${CMSIS_DSP_DIR}/Source/TransformFunctions/arm_mfcc_f16.c) + endif() + + # Window Functions + set(SRCF64 ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_welch_f64.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_bartlett_f64.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_hamming_f64.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_hanning_f64.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_nuttall3_f64.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_nuttall4_f64.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_nuttall3a_f64.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_nuttall3b_f64.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_nuttall4a_f64.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_blackman_harris_92db_f64.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_nuttall4b_f64.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_nuttall4c_f64.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_hft90d_f64.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_hft95_f64.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_hft116d_f64.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_hft144d_f64.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_hft169d_f64.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_hft196d_f64.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_hft223d_f64.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_hft248d_f64.c + ) + + set(SRCF32 ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_welch_f32.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_bartlett_f32.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_hamming_f32.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_hanning_f32.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_nuttall3_f32.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_nuttall4_f32.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_nuttall3a_f32.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_nuttall3b_f32.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_nuttall4a_f32.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_blackman_harris_92db_f32.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_nuttall4b_f32.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_nuttall4c_f32.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_hft90d_f32.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_hft95_f32.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_hft116d_f32.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_hft144d_f32.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_hft169d_f32.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_hft196d_f32.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_hft223d_f32.c + ${CMSIS_DSP_DIR}/Source/WindowFunctions/arm_hft248d_f32.c + ) + + zephyr_library_sources(${SRCF64}) + zephyr_library_sources(${SRCF32}) + +endif() diff --git a/modules/cmsis-dsp/Kconfig b/modules/cmsis-dsp/Kconfig new file mode 100644 index 00000000000..2159f1f6c2e --- /dev/null +++ b/modules/cmsis-dsp/Kconfig @@ -0,0 +1,79 @@ +# Copyright (c) 2023 Meta Platforms +# SPDX-License-Identifier: Apache-2.0 + +config ZEPHYR_CMSIS_DSP_MODULE + bool + +menuconfig CMSIS_DSP + bool "CMSIS-DSP Library Support" + help + This option enables the CMSIS-DSP library. + +if CMSIS_DSP + +comment "Instruction Set" +# NOTE: These configurations should eventually be derived from the arch ISA and +# FP support configurations. + +config CMSIS_DSP_NEON + bool "Neon Instruction Set" + default y + depends on CPU_CORTEX_A + help + This option enables the NEON Advanced SIMD instruction set, which is + available on most Cortex-A and some Cortex-R processors. + +config CMSIS_DSP_NEON_EXPERIMENTAL + bool "Neon Instruction Set" + depends on CPU_CORTEX_A + help + This option enables the NEON Advanced SIMD instruction set, which is + available on most Cortex-A and some Cortex-R processors. + +config CMSIS_DSP_HELIUM_EXPERIMENTAL + bool "Helium Instruction Set" + depends on FP_HARDABI && (ARMV8_1_M_MVEI || ARMV8_1_M_MVEF) + help + This option enables the Helium Advanced SIMD instruction set, which is + available on some Cortex-M processors. + +comment "Features" + +config CMSIS_DSP_LOOPUNROLL + bool "Loop Unrolling" + help + This option enables manual loop unrolling in the DSP functions. + +config CMSIS_DSP_ROUNDING + bool "Rounding" + help + This option enables rounding on the support functions. + +config CMSIS_DSP_MATRIXCHECK + bool "Matrix Check" + help + This option enables validation of the input and output sizes of + matrices. + +config CMSIS_DSP_AUTOVECTORIZE + bool "Auto Vectorize" + help + This option prefers autovectorizable code to one using C intrinsics + in the DSP functions. + +config CMSIS_DSP_FLOAT16 + bool "Half-Precision (16-bit Float) Support" + default y + depends on FP16 + help + This option enables the half-precision (16-bit) floating-point + operations support. + +config CMSIS_DSP_LAX_VECTOR_CONVERSIONS + bool "Lax Vector Conversions" + default y + depends on FP_HARDABI && (ARMV8_1_M_MVEI || ARMV8_1_M_MVEF) + help + This option enables lax vector conversions + +endif #CMSIS_DSP diff --git a/modules/cmsis-nn/CMakeLists.txt b/modules/cmsis-nn/CMakeLists.txt new file mode 100644 index 00000000000..9393a5ff21e --- /dev/null +++ b/modules/cmsis-nn/CMakeLists.txt @@ -0,0 +1,85 @@ +# Copyright (c) 2023 Meta Platforms +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_CMSIS_NN) + + set(CMSIS_NN_DIR ${ZEPHYR_CURRENT_MODULE_DIR}) + set(cmsis_glue_path ${ZEPHYR_CMSIS_MODULE_DIR}) + + zephyr_library() + + zephyr_library_compile_options(-Ofast) + + zephyr_include_directories(${CMSIS_NN_DIR}/Include) + + zephyr_library_include_directories(${cmsis_glue_path}/CMSIS/Core/Include) + + if(CONFIG_CMSIS_NN_ACTIVATION) + file(GLOB SRC "${CMSIS_NN_DIR}/Source/ActivationFunctions/*_s8*.c") + file(GLOB SRC_S16 "${CMSIS_NN_DIR}/Source/ActivationFunctions/*_s16*.c") + zephyr_library_sources(${SRC} ${SRC_S16} + ${CMSIS_NN_DIR}/Source/ActivationFunctions/arm_relu_q7.c + ${CMSIS_NN_DIR}/Source/ActivationFunctions/arm_relu_q15.c) + endif() + + if(CONFIG_CMSIS_NN_BASICMATH) + file(GLOB SRC "${CMSIS_NN_DIR}/Source/BasicMathFunctions/*_*.c") + zephyr_library_sources(${SRC}) + endif() + + if(CONFIG_CMSIS_NN_CONCATENATION) + file(GLOB SRC "${CMSIS_NN_DIR}/Source/ConcatenationFunctions/*_*.c") + zephyr_library_sources(${SRC}) + endif() + + if(CONFIG_CMSIS_NN_CONVOLUTION) + file(GLOB SRC "${CMSIS_NN_DIR}/Source/ConvolutionFunctions/*_s8*.c") + file(GLOB SRC_S16 "${CMSIS_NN_DIR}/Source/ConvolutionFunctions/*_s16*.c") + zephyr_library_sources(${SRC} ${SRC_S16}) + endif() + + if(CONFIG_CMSIS_NN_FULLYCONNECTED) + file(GLOB SRC "${CMSIS_NN_DIR}/Source/FullyConnectedFunctions/*_s8.c") + file(GLOB SRC_S16 "${CMSIS_NN_DIR}/Source/FullyConnectedFunctions/*_s16*.c") + zephyr_library_sources(${SRC} ${SRC_S16}) + endif() + + if(CONFIG_CMSIS_NN_NNSUPPORT) + file(GLOB SRC "${CMSIS_NN_DIR}/Source/NNSupportFunctions/*_s8*.c") + file(GLOB SRC_S16 "${CMSIS_NN_DIR}/Source/NNSupportFunctions/*_s16*.c") + zephyr_library_sources(${SRC} ${SRC_S16} + ${CMSIS_NN_DIR}/Source/NNSupportFunctions/arm_nntables.c + ${CMSIS_NN_DIR}/Source/NNSupportFunctions/arm_q7_to_q15_with_offset.c + ${CMSIS_NN_DIR}/Source/NNSupportFunctions/arm_s8_to_s16_unordered_with_offset.c) + endif() + + if(CONFIG_CMSIS_NN_POOLING) + file(GLOB SRC "${CMSIS_NN_DIR}/Source/PoolingFunctions/*_s8.c") + file(GLOB SRC_S16 "${CMSIS_NN_DIR}/Source/PoolingFunctions/*_s16.c") + zephyr_library_sources(${SRC} ${SRC_S16}) + endif() + + if(CONFIG_CMSIS_NN_RESHAPE) + file(GLOB SRC "${CMSIS_NN_DIR}/Source/ReshapeFunctions/*_*.c") + zephyr_library_sources(${SRC}) + endif() + + if(CONFIG_CMSIS_NN_SOFTMAX) + file(GLOB SRC "${CMSIS_NN_DIR}/Source/SoftmaxFunctions/*_s8.c") + zephyr_library_sources(${SRC} + ${CMSIS_NN_DIR}/Source/SoftmaxFunctions/arm_softmax_s8_s16.c + ${CMSIS_NN_DIR}/Source/SoftmaxFunctions/arm_softmax_s16.c + ${CMSIS_NN_DIR}/Source/SoftmaxFunctions/arm_nn_softmax_common_s8.c) + endif() + + if(CONFIG_CMSIS_NN_SVD) + file(GLOB SRC "${CMSIS_NN_DIR}/Source/SVDFunctions/*_s8.c") + zephyr_library_sources(${SRC}) + endif() + + if(CONFIG_CMSIS_NN_LSTM) + file(GLOB SRC "${CMSIS_NN_DIR}/Source/LSTMFunctions/*_s16.c") + zephyr_library_sources(${SRC}) + endif() + +endif() diff --git a/modules/cmsis-nn/Kconfig b/modules/cmsis-nn/Kconfig new file mode 100644 index 00000000000..53c3aa4987d --- /dev/null +++ b/modules/cmsis-nn/Kconfig @@ -0,0 +1,81 @@ +# Copyright (c) 2023 Meta Platforms +# SPDX-License-Identifier: Apache-2.0 + +config ZEPHYR_CMSIS_NN_MODULE + bool + +menuconfig CMSIS_NN + bool "CMSIS-NN Library Support" + depends on CPU_CORTEX_M + select CMSIS_DSP + help + This option enables the CMSIS-NN library. + +if CMSIS_NN + +config CMSIS_NN_ACTIVATION + bool "Activation" + help + This option enables the NN libraries for the activation layers + It can perform activation layers, including ReLU (Rectified + Linear Unit), sigmoid, and tanh. + +config CMSIS_NN_BASICMATH + bool "Basic Math for NN" + help + This option enables the NN libraries for the basic maths operations. + It adds functionality for element-wise add and multiplication functions. + +config CMSIS_NN_CONCATENATION + bool "Concatenation" + help + This option enables the NN libraries for the concatenation layers. + +config CMSIS_NN_CONVOLUTION + bool "Convolution" + imply CMSIS_NN_NNSUPPORT + help + Collection of convolution, depthwise convolution functions and + their variants. The convolution is implemented in 2 steps: im2col + and GEMM. GEMM is performed with CMSIS-DSP arm_mat_mult similar options. + +config CMSIS_NN_FULLYCONNECTED + bool "Fully Connected" + imply CMSIS_NN_NNSUPPORT + help + Collection of fully-connected and matrix multiplication functions. + +config CMSIS_NN_NNSUPPORT + bool "NN Support" + help + When off, its default behavior is all tables are included. + +config CMSIS_NN_POOLING + bool "Pooling" + imply CMSIS_NN_NNSUPPORT + help + This option enables pooling layers, including max pooling, + and average pooling. + +config CMSIS_NN_RESHAPE + bool "Reshape" + help + This option enables the NN libraries for the reshape layers. + +config CMSIS_NN_SOFTMAX + bool "Softmax" + help + This option enables the NN libraries for the softmax layers (exp2 based). + +config CMSIS_NN_SVD + bool "SVD" + imply CMSIS_NN_NNSUPPORT + help + This option enabled the NN libraries for Single Value Decomposition Filter layers. + +config CMSIS_NN_LSTM + bool "Long Short-Term Memory" + help + This option enables the NN libraries for Long Short-Term Memory. + +endif #CMSIS_NN diff --git a/modules/cmsis/Kconfig b/modules/cmsis/Kconfig index 0bbcddd55e7..4b5a8ee2855 100644 --- a/modules/cmsis/Kconfig +++ b/modules/cmsis/Kconfig @@ -1,6 +1,9 @@ # Copyright (c) 2016 Intel Corporation # SPDX-License-Identifier: Apache-2.0 +config ZEPHYR_CMSIS_MODULE + bool + config HAS_CMSIS_CORE bool select HAS_CMSIS_CORE_A if CPU_AARCH32_CORTEX_A @@ -19,20 +22,3 @@ config HAS_CMSIS_CORE_M bool endif - -menuconfig CMSIS_DSP - bool "CMSIS-DSP Library Support" - select REQUIRES_FULL_LIBC if !ARCH_POSIX - -if CMSIS_DSP -source "modules/cmsis/Kconfig.cmsis_dsp" -endif - -menuconfig CMSIS_NN - bool "CMSIS-NN Library Support" - depends on CPU_CORTEX_M - select CMSIS_DSP - -if CMSIS_NN -source "modules/cmsis/Kconfig.cmsis_nn" -endif diff --git a/modules/cmsis/Kconfig.cmsis_dsp b/modules/cmsis/Kconfig.cmsis_dsp deleted file mode 100644 index 6b5f936ccc3..00000000000 --- a/modules/cmsis/Kconfig.cmsis_dsp +++ /dev/null @@ -1,803 +0,0 @@ -# Copyright (c) 2020 Stephanos Ioannidis -# SPDX-License-Identifier: Apache-2.0 - -comment "Components" - -config CMSIS_DSP_BASICMATH - bool "Basic Math Functions" - default y - help - This option enables the Basic Math Functions, which support the - following operations: - - * Elementwise Clipping - * Vector Absolute Value - * Vector Addition - * Vector Subtraction - * Vector Multiplication - * Vector Dot Product - * Vector Absolute Value - * Vector Negate - * Vector Offset - * Vector Scale - * Vector Shift - * Vector Bitwise AND - * Vector Bitwise OR - * Vector Bitwise Exclusive OR - * Vector Bitwise NOT - -config CMSIS_DSP_COMPLEXMATH - bool "Complex Math Functions" - imply CMSIS_DSP_FASTMATH - depends on CPU_CORTEX || ARCH_POSIX - help - This option enables the Complex Math Functions, which support the - following operations: - - * Complex-by-Complex Multiplication - * Complex-by-Real Multiplication - * Complex Dot Product - * Complex Magnitude - * Complex Magnitude Squared - * Complex Conjugate - -config CMSIS_DSP_CONTROLLER - bool "Controller Functions" - depends on CPU_CORTEX || ARCH_POSIX - help - This option enables the Controller Functions, which support the - following operations: - - * PID Control - * Vector Clarke Transform - * Vector Inverse Clarke Transform - * Vector Park Transform - * Vector Inverse Park Transform - * Sine-Cosine - - These functions can be used to implement a generic PID controller, as - well as field oriented motor control using Space Vector Modulation - algorithm. - -config CMSIS_DSP_FASTMATH - bool "Fast Math Functions" - select CMSIS_DSP_TABLES - imply CMSIS_DSP_TABLES_ALL_FAST - depends on CPU_CORTEX || ARCH_POSIX - help - This option enables the Fast Math Functions, which support the - following operations: - - * Fixed-Point Division - * Sine - * Cosine - * Square Root - -config CMSIS_DSP_FILTERING - bool "Filtering Functions" - imply CMSIS_DSP_FASTMATH - imply CMSIS_DSP_SUPPORT - depends on CPU_CORTEX || ARCH_POSIX - help - This option enables the Filtering Functions, which support the - following operations: - - * Convolution - * Partial Convolution - * Correlation - * Levinson-Durbin Algorithm - - The following filter types are supported: - - * FIR (finite impulse response) Filter - * FIR Lattice Filter - * FIR Sparse Filter - * FIR Filter with Decimator - * FIR Filter with Interpolator - * IIR (infinite impulse response) Lattice Filter - * Biquad Cascade IIR Filter, Direct Form I Structure - * Biquad Cascade IIR Filter, Direct Form II Transposed Structure - * High Precision Q31 Biquad Cascade Filter - * LMS (least mean square) Filter - * Normalized LMS Filter - -config CMSIS_DSP_INTERPOLATION - bool "Interpolation Functions" - depends on CPU_CORTEX || ARCH_POSIX - help - This option enables the Interpolation Functions, which support the - following operations: - - * Bilinear Interpolation - * Linear Interpolation - * Cubic Spline Interpolation - -config CMSIS_DSP_MATRIX - bool "Matrix Functions" - depends on CPU_CORTEX || ARCH_POSIX - help - This option enables the Matrix Functions, which support the following - operations: - - * Matrix Initialization - * Matrix Addition - * Matrix Subtraction - * Matrix Multiplication - * Complex Matrix Multiplication - * Matrix Vector Multiplication - * Matrix Inverse - * Matrix Scale - * Matrix Transpose - * Complex Matrix Transpose - * Cholesky and LDLT Decompositions - -config CMSIS_DSP_QUATERNIONMATH - bool "Quaternion Math Functions" - depends on CPU_CORTEX || ARCH_POSIX - help - This option enables the Quaternion Math Functions, which support the - following operations: - - * Quaternion Conversions - * Quaternion Conjugate - * Quaternion Inverse - * Quaternion Norm - * Quaternion Normalization - * Quaternion Product - -config CMSIS_DSP_STATISTICS - bool "Statistics Functions" - imply CMSIS_DSP_BASICMATH - imply CMSIS_DSP_FASTMATH - depends on CPU_CORTEX || ARCH_POSIX - help - This option enables the Statistics Functions, which support the - following operations: - - * Minimum - * Absolute Minimum - * Maximum - * Absolute Maximum - * Mean - * Root Mean Square (RMS) - * Variance - * Standard Deviation - * Power - * Entropy - * Kullback-Leibler Divergence - * LogSumExp (LSE) - -config CMSIS_DSP_SUPPORT - bool "Support Functions" - depends on CPU_CORTEX || ARCH_POSIX - help - This option enables the Support Functions, which support the - following operations: - - * Vector 8-bit Integer Value Conversion - * Vector 16-bit Integer Value Conversion - * Vector 32-bit Integer Value Conversion - * Vector 16-bit Floating-Point Value Conversion - * Vector 32-bit Floating-Point Value Conversion - * Vector Copy - * Vector Fill - * Vector Sorting - * Weighted Sum - * Barycenter - -config CMSIS_DSP_TRANSFORM - bool "Transform Functions" - select CMSIS_DSP_TABLES - imply CMSIS_DSP_TABLES_ALL_FFT - depends on CPU_CORTEX || ARCH_POSIX - help - This option enables the Transform Functions, which support the - following transformations: - - * Real Fast Fourier Transform (RFFT) - * Complex Fast Fourier Transform (CFFT) - * Type IV Discrete Cosine Transform (DCT4) - -config CMSIS_DSP_SVM - bool "Support Vector Machine Functions" - select CMSIS_DSP_TABLES - depends on CPU_CORTEX || ARCH_POSIX - help - This option enables the Support Vector Machine Functions, which - support the following algorithms: - - * Linear - * Polynomial - * Sigmoid - * Radial Basis Function (RBF) - -config CMSIS_DSP_BAYES - bool "Bayesian Estimators" - imply CMSIS_DSP_STATISTICS - depends on CPU_CORTEX || ARCH_POSIX - help - This option enables the Bayesian Estimator Functions, which - implements the naive gaussian Bayes estimator. - -config CMSIS_DSP_DISTANCE - bool "Distance Functions" - imply CMSIS_DSP_STATISTICS - depends on CPU_CORTEX || ARCH_POSIX - help - This option enables the Distance Functions, which support the - following distance computation algorithms: - - * Boolean Vectors - * Hamming - * Jaccard - * Kulsinski - * Rogers-Tanimoto - * Russell-Rao - * Sokal-Michener - * Sokal-Sneath - * Yule - * Dice - - * Floating-Point Vectors - * Canberra - * Chebyshev - * Cityblock - * Correlation - * Cosine - * Euclidean - * Jensen-Shannon - * Minkowski - * Bray-Curtis - -menuconfig CMSIS_DSP_TABLES - bool "Look-up Tables" - depends on CPU_CORTEX || ARCH_POSIX - help - This option enables the static look-up tables used by the DSP - functions to compute results. - -if CMSIS_DSP_TABLES - -config CMSIS_DSP_TABLES_ALL_FAST - bool "Include all fast interpolation tables" - select CMSIS_DSP_TABLES_ARM_COS_F32 - select CMSIS_DSP_TABLES_ARM_COS_Q31 - select CMSIS_DSP_TABLES_ARM_COS_Q15 - select CMSIS_DSP_TABLES_ARM_SIN_F32 - select CMSIS_DSP_TABLES_ARM_SIN_Q31 - select CMSIS_DSP_TABLES_ARM_SIN_Q15 - select CMSIS_DSP_TABLES_ARM_SIN_COS_F32 - select CMSIS_DSP_TABLES_ARM_SIN_COS_Q31 - select CMSIS_DSP_TABLES_ARM_LMS_NORM_Q31 - select CMSIS_DSP_TABLES_ARM_LMS_NORM_Q15 - select CMSIS_DSP_TABLES_ARM_CMPLX_MAG_Q31 - select CMSIS_DSP_TABLES_ARM_CMPLX_MAG_Q15 - -config CMSIS_DSP_TABLES_ALL_FFT - bool "Include all FFT tables" - select CMSIS_DSP_TABLES_CFFT_F64_16 - select CMSIS_DSP_TABLES_CFFT_F64_32 - select CMSIS_DSP_TABLES_CFFT_F64_64 - select CMSIS_DSP_TABLES_CFFT_F64_128 - select CMSIS_DSP_TABLES_CFFT_F64_256 - select CMSIS_DSP_TABLES_CFFT_F64_512 - select CMSIS_DSP_TABLES_CFFT_F64_1024 - select CMSIS_DSP_TABLES_CFFT_F64_2048 - select CMSIS_DSP_TABLES_CFFT_F64_4096 - select CMSIS_DSP_TABLES_CFFT_F32_16 - select CMSIS_DSP_TABLES_CFFT_F32_32 - select CMSIS_DSP_TABLES_CFFT_F32_64 - select CMSIS_DSP_TABLES_CFFT_F32_128 - select CMSIS_DSP_TABLES_CFFT_F32_256 - select CMSIS_DSP_TABLES_CFFT_F32_512 - select CMSIS_DSP_TABLES_CFFT_F32_1024 - select CMSIS_DSP_TABLES_CFFT_F32_2048 - select CMSIS_DSP_TABLES_CFFT_F32_4096 - select CMSIS_DSP_TABLES_CFFT_F16_16 - select CMSIS_DSP_TABLES_CFFT_F16_32 - select CMSIS_DSP_TABLES_CFFT_F16_64 - select CMSIS_DSP_TABLES_CFFT_F16_128 - select CMSIS_DSP_TABLES_CFFT_F16_256 - select CMSIS_DSP_TABLES_CFFT_F16_512 - select CMSIS_DSP_TABLES_CFFT_F16_1024 - select CMSIS_DSP_TABLES_CFFT_F16_2048 - select CMSIS_DSP_TABLES_CFFT_F16_4096 - select CMSIS_DSP_TABLES_CFFT_Q31_16 - select CMSIS_DSP_TABLES_CFFT_Q31_32 - select CMSIS_DSP_TABLES_CFFT_Q31_64 - select CMSIS_DSP_TABLES_CFFT_Q31_128 - select CMSIS_DSP_TABLES_CFFT_Q31_256 - select CMSIS_DSP_TABLES_CFFT_Q31_512 - select CMSIS_DSP_TABLES_CFFT_Q31_1024 - select CMSIS_DSP_TABLES_CFFT_Q31_2048 - select CMSIS_DSP_TABLES_CFFT_Q31_4096 - select CMSIS_DSP_TABLES_CFFT_Q15_16 - select CMSIS_DSP_TABLES_CFFT_Q15_32 - select CMSIS_DSP_TABLES_CFFT_Q15_64 - select CMSIS_DSP_TABLES_CFFT_Q15_128 - select CMSIS_DSP_TABLES_CFFT_Q15_256 - select CMSIS_DSP_TABLES_CFFT_Q15_512 - select CMSIS_DSP_TABLES_CFFT_Q15_1024 - select CMSIS_DSP_TABLES_CFFT_Q15_2048 - select CMSIS_DSP_TABLES_CFFT_Q15_4096 - select CMSIS_DSP_TABLES_RFFT_FAST_F64_32 - select CMSIS_DSP_TABLES_RFFT_FAST_F64_64 - select CMSIS_DSP_TABLES_RFFT_FAST_F64_128 - select CMSIS_DSP_TABLES_RFFT_FAST_F64_256 - select CMSIS_DSP_TABLES_RFFT_FAST_F64_512 - select CMSIS_DSP_TABLES_RFFT_FAST_F64_1024 - select CMSIS_DSP_TABLES_RFFT_FAST_F64_2048 - select CMSIS_DSP_TABLES_RFFT_FAST_F64_4096 - select CMSIS_DSP_TABLES_RFFT_FAST_F32_32 - select CMSIS_DSP_TABLES_RFFT_FAST_F32_64 - select CMSIS_DSP_TABLES_RFFT_FAST_F32_128 - select CMSIS_DSP_TABLES_RFFT_FAST_F32_256 - select CMSIS_DSP_TABLES_RFFT_FAST_F32_512 - select CMSIS_DSP_TABLES_RFFT_FAST_F32_1024 - select CMSIS_DSP_TABLES_RFFT_FAST_F32_2048 - select CMSIS_DSP_TABLES_RFFT_FAST_F32_4096 - select CMSIS_DSP_TABLES_RFFT_FAST_F16_32 - select CMSIS_DSP_TABLES_RFFT_FAST_F16_64 - select CMSIS_DSP_TABLES_RFFT_FAST_F16_128 - select CMSIS_DSP_TABLES_RFFT_FAST_F16_256 - select CMSIS_DSP_TABLES_RFFT_FAST_F16_512 - select CMSIS_DSP_TABLES_RFFT_FAST_F16_1024 - select CMSIS_DSP_TABLES_RFFT_FAST_F16_2048 - select CMSIS_DSP_TABLES_RFFT_FAST_F16_4096 - select CMSIS_DSP_TABLES_RFFT_F32_128 - select CMSIS_DSP_TABLES_RFFT_F32_512 - select CMSIS_DSP_TABLES_RFFT_F32_2048 - select CMSIS_DSP_TABLES_RFFT_F32_8192 - select CMSIS_DSP_TABLES_RFFT_F16_128 - select CMSIS_DSP_TABLES_RFFT_F16_512 - select CMSIS_DSP_TABLES_RFFT_F16_2048 - select CMSIS_DSP_TABLES_RFFT_F16_8192 - select CMSIS_DSP_TABLES_RFFT_Q31_32 - select CMSIS_DSP_TABLES_RFFT_Q31_64 - select CMSIS_DSP_TABLES_RFFT_Q31_128 - select CMSIS_DSP_TABLES_RFFT_Q31_256 - select CMSIS_DSP_TABLES_RFFT_Q31_512 - select CMSIS_DSP_TABLES_RFFT_Q31_1024 - select CMSIS_DSP_TABLES_RFFT_Q31_2048 - select CMSIS_DSP_TABLES_RFFT_Q31_4096 - select CMSIS_DSP_TABLES_RFFT_Q31_8192 - select CMSIS_DSP_TABLES_RFFT_Q15_32 - select CMSIS_DSP_TABLES_RFFT_Q15_64 - select CMSIS_DSP_TABLES_RFFT_Q15_128 - select CMSIS_DSP_TABLES_RFFT_Q15_256 - select CMSIS_DSP_TABLES_RFFT_Q15_512 - select CMSIS_DSP_TABLES_RFFT_Q15_1024 - select CMSIS_DSP_TABLES_RFFT_Q15_2048 - select CMSIS_DSP_TABLES_RFFT_Q15_4096 - select CMSIS_DSP_TABLES_RFFT_Q15_8192 - select CMSIS_DSP_TABLES_DCT4_F32_128 - select CMSIS_DSP_TABLES_DCT4_F32_512 - select CMSIS_DSP_TABLES_DCT4_F32_2048 - select CMSIS_DSP_TABLES_DCT4_F32_8192 - select CMSIS_DSP_TABLES_DCT4_Q31_128 - select CMSIS_DSP_TABLES_DCT4_Q31_512 - select CMSIS_DSP_TABLES_DCT4_Q31_2048 - select CMSIS_DSP_TABLES_DCT4_Q31_8192 - select CMSIS_DSP_TABLES_DCT4_Q15_128 - select CMSIS_DSP_TABLES_DCT4_Q15_512 - select CMSIS_DSP_TABLES_DCT4_Q15_2048 - select CMSIS_DSP_TABLES_DCT4_Q15_8192 - -comment "Interpolation Tables" - -config CMSIS_DSP_TABLES_ARM_COS_F32 - bool "cos f32" - -config CMSIS_DSP_TABLES_ARM_COS_Q31 - bool "cos q31" - -config CMSIS_DSP_TABLES_ARM_COS_Q15 - bool "cos q15" - -config CMSIS_DSP_TABLES_ARM_SIN_F32 - bool "sin f32" - -config CMSIS_DSP_TABLES_ARM_SIN_Q31 - bool "sin q31" - -config CMSIS_DSP_TABLES_ARM_SIN_Q15 - bool "sin q15" - -config CMSIS_DSP_TABLES_ARM_SIN_COS_F32 - bool "sin cos f32" - -config CMSIS_DSP_TABLES_ARM_SIN_COS_Q31 - bool "sin cos q31" - -config CMSIS_DSP_TABLES_ARM_LMS_NORM_Q31 - bool "lms norm q31" - -config CMSIS_DSP_TABLES_ARM_LMS_NORM_Q15 - bool "lms norm q15" - -config CMSIS_DSP_TABLES_ARM_CMPLX_MAG_Q31 - bool "cmplx mag q31" - -config CMSIS_DSP_TABLES_ARM_CMPLX_MAG_Q15 - bool "cmplx mag q15" - -comment "Transformation Tables" - -config CMSIS_DSP_TABLES_CFFT_F64_16 - bool "cfft f64 16" - -config CMSIS_DSP_TABLES_CFFT_F64_32 - bool "cfft f64 32" - -config CMSIS_DSP_TABLES_CFFT_F64_64 - bool "cfft f64 64" - -config CMSIS_DSP_TABLES_CFFT_F64_128 - bool "cfft f64 128" - -config CMSIS_DSP_TABLES_CFFT_F64_256 - bool "cfft f64 256" - -config CMSIS_DSP_TABLES_CFFT_F64_512 - bool "cfft f64 512" - -config CMSIS_DSP_TABLES_CFFT_F64_1024 - bool "cfft f64 1024" - -config CMSIS_DSP_TABLES_CFFT_F64_2048 - bool "cfft f64 2048" - -config CMSIS_DSP_TABLES_CFFT_F64_4096 - bool "cfft f64 4096" - -config CMSIS_DSP_TABLES_CFFT_F32_16 - bool "cfft f32 16" - -config CMSIS_DSP_TABLES_CFFT_F32_32 - bool "cfft f32 32" - -config CMSIS_DSP_TABLES_CFFT_F32_64 - bool "cfft f32 64" - -config CMSIS_DSP_TABLES_CFFT_F32_128 - bool "cfft f32 128" - -config CMSIS_DSP_TABLES_CFFT_F32_256 - bool "cfft f32 256" - -config CMSIS_DSP_TABLES_CFFT_F32_512 - bool "cfft f32 512" - -config CMSIS_DSP_TABLES_CFFT_F32_1024 - bool "cfft f32 1024" - -config CMSIS_DSP_TABLES_CFFT_F32_2048 - bool "cfft f32 2048" - -config CMSIS_DSP_TABLES_CFFT_F32_4096 - bool "cfft f32 4096" - -config CMSIS_DSP_TABLES_CFFT_F16_16 - bool "cfft f16 16" - -config CMSIS_DSP_TABLES_CFFT_F16_32 - bool "cfft f16 32" - -config CMSIS_DSP_TABLES_CFFT_F16_64 - bool "cfft f16 64" - -config CMSIS_DSP_TABLES_CFFT_F16_128 - bool "cfft f16 128" - -config CMSIS_DSP_TABLES_CFFT_F16_256 - bool "cfft f16 256" - -config CMSIS_DSP_TABLES_CFFT_F16_512 - bool "cfft f16 512" - -config CMSIS_DSP_TABLES_CFFT_F16_1024 - bool "cfft f16 1024" - -config CMSIS_DSP_TABLES_CFFT_F16_2048 - bool "cfft f16 2048" - -config CMSIS_DSP_TABLES_CFFT_F16_4096 - bool "cfft f16 4096" - -config CMSIS_DSP_TABLES_CFFT_Q31_16 - bool "cfft q31 16" - -config CMSIS_DSP_TABLES_CFFT_Q31_32 - bool "cfft q31 32" - -config CMSIS_DSP_TABLES_CFFT_Q31_64 - bool "cfft q31 64" - -config CMSIS_DSP_TABLES_CFFT_Q31_128 - bool "cfft q31 128" - -config CMSIS_DSP_TABLES_CFFT_Q31_256 - bool "cfft q31 256" - -config CMSIS_DSP_TABLES_CFFT_Q31_512 - bool "cfft q31 512" - -config CMSIS_DSP_TABLES_CFFT_Q31_1024 - bool "cfft q31 1024" - -config CMSIS_DSP_TABLES_CFFT_Q31_2048 - bool "cfft q31 2048" - -config CMSIS_DSP_TABLES_CFFT_Q31_4096 - bool "cfft q31 4096" - -config CMSIS_DSP_TABLES_CFFT_Q15_16 - bool "cfft q15 16" - -config CMSIS_DSP_TABLES_CFFT_Q15_32 - bool "cfft q15 32" - -config CMSIS_DSP_TABLES_CFFT_Q15_64 - bool "cfft q15 64" - -config CMSIS_DSP_TABLES_CFFT_Q15_128 - bool "cfft q15 128" - -config CMSIS_DSP_TABLES_CFFT_Q15_256 - bool "cfft q15 256" - -config CMSIS_DSP_TABLES_CFFT_Q15_512 - bool "cfft q15 512" - -config CMSIS_DSP_TABLES_CFFT_Q15_1024 - bool "cfft q15 1024" - -config CMSIS_DSP_TABLES_CFFT_Q15_2048 - bool "cfft q15 2048" - -config CMSIS_DSP_TABLES_CFFT_Q15_4096 - bool "cfft q15 4096" - -config CMSIS_DSP_TABLES_CFFT_RADIX4_Q31 - bool "cfft radix4 q31 (deprecated)" - -config CMSIS_DSP_TABLES_CFFT_RADIX4_Q15 - bool "cfft radix4 q15 (deprecated)" - -config CMSIS_DSP_TABLES_CFFT_RADIX2_Q31 - bool "cfft radix2 q31 (deprecated)" - -config CMSIS_DSP_TABLES_CFFT_RADIX2_Q15 - bool "cfft radix2 q15 (deprecated)" - -config CMSIS_DSP_TABLES_RFFT_FAST_F64_32 - bool "rfft fast f64 32" - -config CMSIS_DSP_TABLES_RFFT_FAST_F64_64 - bool "rfft fast f64 64" - -config CMSIS_DSP_TABLES_RFFT_FAST_F64_128 - bool "rfft fast f64 128" - -config CMSIS_DSP_TABLES_RFFT_FAST_F64_256 - bool "rfft fast f64 256" - -config CMSIS_DSP_TABLES_RFFT_FAST_F64_512 - bool "rfft fast f64 512" - -config CMSIS_DSP_TABLES_RFFT_FAST_F64_1024 - bool "rfft fast f64 1024" - -config CMSIS_DSP_TABLES_RFFT_FAST_F64_2048 - bool "rfft fast f64 2048" - -config CMSIS_DSP_TABLES_RFFT_FAST_F64_4096 - bool "rfft fast f64 4096" - -config CMSIS_DSP_TABLES_RFFT_FAST_F32_32 - bool "rfft fast f32 32" - -config CMSIS_DSP_TABLES_RFFT_FAST_F32_64 - bool "rfft fast f32 64" - -config CMSIS_DSP_TABLES_RFFT_FAST_F32_128 - bool "rfft fast f32 128" - -config CMSIS_DSP_TABLES_RFFT_FAST_F32_256 - bool "rfft fast f32 256" - -config CMSIS_DSP_TABLES_RFFT_FAST_F32_512 - bool "rfft fast f32 512" - -config CMSIS_DSP_TABLES_RFFT_FAST_F32_1024 - bool "rfft fast f32 1024" - -config CMSIS_DSP_TABLES_RFFT_FAST_F32_2048 - bool "rfft fast f32 2048" - -config CMSIS_DSP_TABLES_RFFT_FAST_F32_4096 - bool "rfft fast f32 4096" - -config CMSIS_DSP_TABLES_RFFT_FAST_F16_32 - bool "rfft fast f16 32" - -config CMSIS_DSP_TABLES_RFFT_FAST_F16_64 - bool "rfft fast f16 64" - -config CMSIS_DSP_TABLES_RFFT_FAST_F16_128 - bool "rfft fast f16 128" - -config CMSIS_DSP_TABLES_RFFT_FAST_F16_256 - bool "rfft fast f16 256" - -config CMSIS_DSP_TABLES_RFFT_FAST_F16_512 - bool "rfft fast f16 512" - -config CMSIS_DSP_TABLES_RFFT_FAST_F16_1024 - bool "rfft fast f16 1024" - -config CMSIS_DSP_TABLES_RFFT_FAST_F16_2048 - bool "rfft fast f16 2048" - -config CMSIS_DSP_TABLES_RFFT_FAST_F16_4096 - bool "rfft fast f16 4096" - -config CMSIS_DSP_TABLES_RFFT_F32_128 - bool "rfft f32 128" - -config CMSIS_DSP_TABLES_RFFT_F32_512 - bool "rfft f32 512" - -config CMSIS_DSP_TABLES_RFFT_F32_2048 - bool "rfft f32 2048" - -config CMSIS_DSP_TABLES_RFFT_F32_8192 - bool "rfft f32 8192" - -config CMSIS_DSP_TABLES_RFFT_F16_128 - bool "rfft f16 128" - -config CMSIS_DSP_TABLES_RFFT_F16_512 - bool "rfft f16 512" - -config CMSIS_DSP_TABLES_RFFT_F16_2048 - bool "rfft f16 2048" - -config CMSIS_DSP_TABLES_RFFT_F16_8192 - bool "rfft f16 8192" - -config CMSIS_DSP_TABLES_RFFT_Q31_32 - bool "rfft q31 32" - -config CMSIS_DSP_TABLES_RFFT_Q31_64 - bool "rfft q31 64" - -config CMSIS_DSP_TABLES_RFFT_Q31_128 - bool "rfft q31 128" - -config CMSIS_DSP_TABLES_RFFT_Q31_256 - bool "rfft q31 256" - -config CMSIS_DSP_TABLES_RFFT_Q31_512 - bool "rfft q31 512" - -config CMSIS_DSP_TABLES_RFFT_Q31_1024 - bool "rfft q31 1024" - -config CMSIS_DSP_TABLES_RFFT_Q31_2048 - bool "rfft q31 2048" - -config CMSIS_DSP_TABLES_RFFT_Q31_4096 - bool "rfft q31 4096" - -config CMSIS_DSP_TABLES_RFFT_Q31_8192 - bool "rfft q31 8192" - -config CMSIS_DSP_TABLES_RFFT_Q15_32 - bool "rfft q15 32" - -config CMSIS_DSP_TABLES_RFFT_Q15_64 - bool "rfft q15 64" - -config CMSIS_DSP_TABLES_RFFT_Q15_128 - bool "rfft q15 128" - -config CMSIS_DSP_TABLES_RFFT_Q15_256 - bool "rfft q15 256" - -config CMSIS_DSP_TABLES_RFFT_Q15_512 - bool "rfft q15 512" - -config CMSIS_DSP_TABLES_RFFT_Q15_1024 - bool "rfft q15 1024" - -config CMSIS_DSP_TABLES_RFFT_Q15_2048 - bool "rfft q15 2048" - -config CMSIS_DSP_TABLES_RFFT_Q15_4096 - bool "rfft q15 4096" - -config CMSIS_DSP_TABLES_RFFT_Q15_8192 - bool "rfft q15 8192" - -config CMSIS_DSP_TABLES_DCT4_F32_128 - bool "dct4 f32 128" - -config CMSIS_DSP_TABLES_DCT4_F32_512 - bool "dct4 f32 512" - -config CMSIS_DSP_TABLES_DCT4_F32_2048 - bool "dct4 f32 2048" - -config CMSIS_DSP_TABLES_DCT4_F32_8192 - bool "dct4 f32 8192" - -config CMSIS_DSP_TABLES_DCT4_Q31_128 - bool "dct4 q31 128" - -config CMSIS_DSP_TABLES_DCT4_Q31_512 - bool "dct4 q31 512" - -config CMSIS_DSP_TABLES_DCT4_Q31_2048 - bool "dct4 q31 2048" - -config CMSIS_DSP_TABLES_DCT4_Q31_8192 - bool "dct4 q31 8192" - -config CMSIS_DSP_TABLES_DCT4_Q15_128 - bool "dct4 q15 128" - -config CMSIS_DSP_TABLES_DCT4_Q15_512 - bool "dct4 q15 512" - -config CMSIS_DSP_TABLES_DCT4_Q15_2048 - bool "dct4 q15 2048" - -config CMSIS_DSP_TABLES_DCT4_Q15_8192 - bool "dct4 q15 8192" - -endif # CMSIS_DSP_TABLES - -comment "Instruction Set" -# NOTE: These configurations should eventually be derived from the arch ISA and -# FP support configurations. - -config CMSIS_DSP_NEON - bool "Neon Instruction Set" - default y - depends on CPU_CORTEX_A - help - This option enables the NEON Advanced SIMD instruction set, which is - available on most Cortex-A and some Cortex-R processors. - -comment "Features" - -config CMSIS_DSP_LOOPUNROLL - bool "Loop Unrolling" - help - This option enables manual loop unrolling in the DSP functions. - -config CMSIS_DSP_ROUNDING - bool "Rounding" - help - This option enables rounding on the support functions. - -config CMSIS_DSP_MATRIXCHECK - bool "Matrix Check" - help - This option enables validation of the input and output sizes of - matrices. - -config CMSIS_DSP_AUTOVECTORIZE - bool "Auto Vectorize" - help - This option prefers autovectorizable code to one using C intrinsics - in the DSP functions. - -config CMSIS_DSP_FLOAT16 - bool "Half-Precision (16-bit Float) Support" - default y - depends on FP16 - help - This option enables the half-precision (16-bit) floating-point - operations support. diff --git a/modules/cmsis/Kconfig.cmsis_nn b/modules/cmsis/Kconfig.cmsis_nn deleted file mode 100644 index 084fcf3a656..00000000000 --- a/modules/cmsis/Kconfig.cmsis_nn +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright (c) 2021, Commonwealth Scientific and Industrial Research -# Organisation (CSIRO) ABN 41 687 119 230. -# SPDX-License-Identifier: Apache-2.0 - -comment "CMSIS-NN Components" - -config CMSIS_NN_ACTIVATION - bool "Activation" - help - This option enables the NN libraries for the activation layers - It can perform activation layers, including ReLU (Rectified - Linear Unit), sigmoid and tanh. - -config CMSIS_NN_BASICMATH - bool "Basic Math for NN" - help - This option enables the NN libraries for the basic maths operations. - It adds functionality for element-wise add and multiplication functions. - -config CMSIS_NN_CONCATENATION - bool "Concatenation" - help - This option enables the NN libraries for the concatenation layers. - -config CMSIS_NN_CONVOLUTION - bool "Convolution" - imply CMSIS_NN_NNSUPPORT - help - Collection of convolution, depthwise convolution functions and - their variants. The convolution is implemented in 2 steps: im2col - and GEMM. GEMM is performed with CMSIS-DSP arm_mat_mult similar options. - -config CMSIS_NN_FULLYCONNECTED - bool "Fully Connected" - imply CMSIS_NN_NNSUPPORT - help - Collection of fully-connected and matrix multiplication functions. - -config CMSIS_NN_NNSUPPORT - bool "NN Support" - help - When off, its default behavior is all tables are included. - -config CMSIS_NN_POOLING - bool "Pooling" - imply CMSIS_NN_NNSUPPORT - help - This option enables pooling layers, including max pooling - and average pooling. - -config CMSIS_NN_RESHAPE - bool "Reshape" - help - This option enables the NN libraries for the reshape layers. - -config CMSIS_NN_SOFTMAX - bool "Softmax" - help - This option enables the NN libraries for the softmax layers (exp2 based). - -config CMSIS_NN_SVD - bool "SVD" - imply CMSIS_NN_NNSUPPORT - help - This option enabled the NN libraries for Single Value Decomposition Filter layers. diff --git a/modules/cmsis/cmsis_core_m.h b/modules/cmsis/cmsis_core_m.h index 849c496a9bd..880ff614b5b 100644 --- a/modules/cmsis/cmsis_core_m.h +++ b/modules/cmsis/cmsis_core_m.h @@ -14,7 +14,7 @@ #ifndef ZEPHYR_MODULES_CMSIS_CMSIS_M_H_ #define ZEPHYR_MODULES_CMSIS_CMSIS_M_H_ -#include +#include #include diff --git a/modules/fatfs/zfs_ffsystem.c b/modules/fatfs/zfs_ffsystem.c index 6f4d134f798..f4f2c900372 100644 --- a/modules/fatfs/zfs_ffsystem.c +++ b/modules/fatfs/zfs_ffsystem.c @@ -10,6 +10,8 @@ * https://github.com/zephyrproject-rtos/fatfs/blob/master/option/ffsystem.c */ +#include + #include #if FF_USE_LFN == 3 /* Dynamic memory allocation */ diff --git a/modules/hal_ambiq/Kconfig b/modules/hal_ambiq/Kconfig index b6029f0592c..28c19e9a587 100644 --- a/modules/hal_ambiq/Kconfig +++ b/modules/hal_ambiq/Kconfig @@ -40,4 +40,9 @@ config AMBIQ_HAL_USE_SPI help Use the SPI driver from Ambiq HAL +config AMBIQ_HAL_USE_MSPI + bool + help + Use the MSPI driver from Ambiq HAL + endif # AMBIQ_HAL diff --git a/modules/hal_ethos_u/Kconfig b/modules/hal_ethos_u/Kconfig index 4a270cabbdc..bfed9b94d82 100644 --- a/modules/hal_ethos_u/Kconfig +++ b/modules/hal_ethos_u/Kconfig @@ -40,6 +40,32 @@ config ARM_ETHOS_U_NPU_NAME help Name of the used Arm NPU -module = ARM_ETHOS_U -module-str = arm_ethos_u -source "subsys/logging/Kconfig.template.log_config" +choice "ARM_ETHOS_U_LOG_LEVEL_CHOICE" + prompt "Max compiled-in log level for arm_ethos_u" + default ARM_ETHOS_U_LOG_LEVEL_WRN + depends on STDOUT_CONSOLE + +config ARM_ETHOS_U_LOG_LEVEL_ERR + bool "Error" + +config ARM_ETHOS_U_LOG_LEVEL_WRN + bool "Warning" + +config ARM_ETHOS_U_LOG_LEVEL_INF + bool "Info" + +config ARM_ETHOS_U_LOG_LEVEL_DBG + bool "Debug" + +config ARM_ETHOS_U_LOG_LEVEL_DEFAULT + bool "Default" + +endchoice + +config ARM_ETHOS_U_LOG_LEVEL + int + depends on STDOUT_CONSOLE + default 1 if ARM_ETHOS_U_LOG_LEVEL_ERR + default 2 if ARM_ETHOS_U_LOG_LEVEL_WRN + default 3 if ARM_ETHOS_U_LOG_LEVEL_INF + default 4 if ARM_ETHOS_U_LOG_LEVEL_DBG diff --git a/modules/hal_infineon/CMakeLists.txt b/modules/hal_infineon/CMakeLists.txt index aff4d21f0aa..27dbd71897f 100644 --- a/modules/hal_infineon/CMakeLists.txt +++ b/modules/hal_infineon/CMakeLists.txt @@ -36,8 +36,13 @@ if (CONFIG_SOC_FAMILY_INFINEON_CAT1A) add_subdirectory(abstraction-rtos) endif() -## Add btstack-integration for CYW43xx BT devices -if (CONFIG_BT_CYW43XXX) +## Add Wi-Fi assets for AIROC devices +if (CONFIG_WIFI_AIROC) + add_subdirectory(wifi-host-driver) +endif() + +## Add BT assets for AIROC devices +if (CONFIG_BT_AIROC) add_subdirectory(btstack-integration) endif() diff --git a/modules/hal_infineon/Kconfig b/modules/hal_infineon/Kconfig index 0522c96769c..af92b98b3dc 100644 --- a/modules/hal_infineon/Kconfig +++ b/modules/hal_infineon/Kconfig @@ -27,6 +27,12 @@ config USE_INFINEON_SDIO Enable Secure Digital Input/Output interface (SDIO) HAL module for Infineon devices driver +config USE_INFINEON_SDHC + bool + help + Enable SDHC HAL module for Infineon devices + driver + config USE_INFINEON_SPI bool help @@ -66,9 +72,8 @@ config USE_INFINEON_WDT Enable WATCHDOG TIMER (WDT) HAL module driver for Infineon devices -config ABSTRACTION_RTOS_COMPONENT_ZEPHYR +config USE_INFINEON_ABSTRACTION_RTOS bool "Abstraction RTOS component (Zephyr support)" - default n help Enable Abstraction RTOS component with Zephyr support diff --git a/modules/hal_infineon/abstraction-rtos/CMakeLists.txt b/modules/hal_infineon/abstraction-rtos/CMakeLists.txt index cd61908659f..6b2b0e6449f 100644 --- a/modules/hal_infineon/abstraction-rtos/CMakeLists.txt +++ b/modules/hal_infineon/abstraction-rtos/CMakeLists.txt @@ -5,7 +5,7 @@ zephyr_include_directories(${ZEPHYR_HAL_INFINEON_MODULE_DIR}/abstraction-rtos/include) # Enable Zephyr support -zephyr_include_directories_ifdef(CONFIG_ABSTRACTION_RTOS_COMPONENT_ZEPHYR +zephyr_include_directories_ifdef(CONFIG_USE_INFINEON_ABSTRACTION_RTOS include/COMPONENT_ZEPHYR) -zephyr_library_sources_ifdef(CONFIG_ABSTRACTION_RTOS_COMPONENT_ZEPHYR +zephyr_library_sources_ifdef(CONFIG_USE_INFINEON_ABSTRACTION_RTOS source/COMPONENT_ZEPHYR/cyabs_rtos_zephyr.c) diff --git a/modules/hal_infineon/btstack-integration/CMakeLists.txt b/modules/hal_infineon/btstack-integration/CMakeLists.txt index ef6a64cff3d..d82fe10662d 100644 --- a/modules/hal_infineon/btstack-integration/CMakeLists.txt +++ b/modules/hal_infineon/btstack-integration/CMakeLists.txt @@ -30,13 +30,13 @@ if(CONFIG_CYW4373_STERLING_LWB5PLUS) set(blob_hcd_file ${hal_blobs_dir}/COMPONENT_4373/COMPONENT_STERLING-LWB5plus/bt_firmware.hcd) endif() -# use user provided FIRMWARE HCD file (path must be defined in CONFIG_CYW43XX_CUSTOM_FIRMWARE_HCD_BLOB) -if(CONFIG_CYW43XX_CUSTOM_FIRMWARE_HCD_BLOB) +# use user provided FIRMWARE HCD file (path must be defined in CONFIG_AIROC_CUSTOM_FIRMWARE_HCD_BLOB) +if(CONFIG_AIROC_CUSTOM_FIRMWARE_HCD_BLOB) # Allowed to pass absolute path to HCD blob file, or relative path from Application folder. - if(IS_ABSOLUTE ${CONFIG_CYW43XX_CUSTOM_FIRMWARE_HCD_BLOB}) - set(blob_hcd_file ${CONFIG_CYW43XX_CUSTOM_FIRMWARE_HCD_BLOB}) + if(IS_ABSOLUTE ${CONFIG_AIROC_CUSTOM_FIRMWARE_HCD_BLOB}) + set(blob_hcd_file ${CONFIG_AIROC_CUSTOM_FIRMWARE_HCD_BLOB}) else() - set(blob_hcd_file ${APPLICATION_SOURCE_DIR}/${CONFIG_CYW43XX_CUSTOM_FIRMWARE_HCD_BLOB}) + set(blob_hcd_file ${APPLICATION_SOURCE_DIR}/${CONFIG_AIROC_CUSTOM_FIRMWARE_HCD_BLOB}) endif() endif() diff --git a/modules/hal_infineon/wifi-host-driver/CMakeLists.txt b/modules/hal_infineon/wifi-host-driver/CMakeLists.txt new file mode 100644 index 00000000000..afdb147676d --- /dev/null +++ b/modules/hal_infineon/wifi-host-driver/CMakeLists.txt @@ -0,0 +1,216 @@ +# Copyright (c) 2023 Cypress Semiconductor Corporation. +# +# SPDX-License-Identifier: Apache-2.0 + +set(hal_dir ${ZEPHYR_HAL_INFINEON_MODULE_DIR}) +set(hal_wifi_dir ${hal_dir}/wifi-host-driver) +set(hal_wifi_dir_resources ${hal_dir}/wifi-host-driver/WiFi_Host_Driver/resources) + +set(hal_blobs_dir ${hal_dir}/zephyr/blobs/img/whd/resources) +set(blob_gen_dir ${ZEPHYR_BINARY_DIR}/include/generated) + +set(cyw43xx_fw_bin_gen_inc ${blob_gen_dir}/cyw43xx_fw_blob.inc) +set(cyw43xx_clm_bin_gen_inc ${blob_gen_dir}/cyw43xx_clm_blob.inc) + +######################################################################################### +# Wi-Fi Host driver +######################################################################################### +if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) + zephyr_compile_definitions(WLAN_MFG_FIRMWARE) +endif() + +# Add WHD includes +zephyr_include_directories(${hal_wifi_dir}) +zephyr_include_directories(${hal_wifi_dir}/WiFi_Host_Driver/inc) +zephyr_include_directories(${hal_wifi_dir}/WiFi_Host_Driver/src) +zephyr_include_directories(${hal_wifi_dir}/WiFi_Host_Driver/src/include) +zephyr_include_directories(${hal_wifi_dir}/WiFi_Host_Driver/resources/resource_imp) + +# src +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/whd_ap.c) +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/whd_buffer_api.c) +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/whd_cdc_bdc.c) +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/whd_chip.c) +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/whd_chip_constants.c) +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/whd_clm.c) +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/whd_debug.c) +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/whd_events.c) +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/whd_logging.c) +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/whd_management.c) +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/whd_network_if.c) +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/whd_resource_if.c) +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/whd_sdpcm.c) +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/whd_thread.c) +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/whd_utils.c) +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/whd_wifi.c) +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/whd_wifi_api.c) +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/whd_wifi_p2p.c) + +# src/bus_protocols +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/bus_protocols/whd_bus.c) +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/bus_protocols/whd_bus_common.c) +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/bus_protocols/whd_bus_sdio_protocol.c) + +# resources/resource_imp +zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/resources/resource_imp/whd_resources.c) + +# CYW43012 firmware +if(CONFIG_CYW43012 AND NOT CONFIG_AIROC_WIFI_CUSTOM) + zephyr_include_directories(${hal_wifi_dir}/WiFi_Host_Driver/resources/firmware/COMPONENT_43012) + + # firmware + if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) + set(cyw43xx_fw_bin ${hal_blobs_dir}/firmware/COMPONENT_43012/43012C0-mfgtest.bin) + zephyr_library_sources(${hal_wifi_dir_resources}/firmware/COMPONENT_43012/43012C0-mfgtest_bin.c) + else() + set(cyw43xx_fw_bin ${hal_blobs_dir}/firmware/COMPONENT_43012/43012C0.bin) + zephyr_library_sources(${hal_wifi_dir_resources}/firmware/COMPONENT_43012/43012C0_bin.c) + endif() +endif() + +# CYW4343W firmware +if(CONFIG_CYW4343W AND NOT CONFIG_AIROC_WIFI_CUSTOM) + zephyr_include_directories(${hal_wifi_dir_resources}/firmware/COMPONENT_4343W) + + # firmware + if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) + set(cyw43xx_fw_bin ${hal_blobs_dir}/firmware/COMPONENT_4343W/4343WA1-mfgtest.bin) + zephyr_library_sources(${hal_wifi_dir_resources}/firmware/COMPONENT_4343W/4343WA1-mfgtest_bin.c) + else() + set(cyw43xx_fw_bin ${hal_blobs_dir}/firmware/COMPONENT_4343W/4343WA1.bin) + zephyr_library_sources(${hal_wifi_dir_resources}/firmware/COMPONENT_4343W/4343WA1_bin.c) + endif() +endif() + +# CYW43438 firmware/clm +if(CONFIG_CYW43438 AND NOT CONFIG_AIROC_WIFI_CUSTOM) + zephyr_include_directories(${hal_wifi_dir_resources}/firmware/COMPONENT_43438) + zephyr_include_directories(${hal_wifi_dir_resources}/clm/COMPONENT_43438) + + # firmware/clm + if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) + set(cyw43xx_fw_bin ${hal_blobs_dir}/firmware/COMPONENT_43438/43438A1-mfgtest.bin) + set(cyw43xx_clm_bin ${hal_blobs_dir}/clm/COMPONENT_43438/43438A1-mfgtest.clm_blob) + + zephyr_library_sources(${hal_wifi_dir_resources}/firmware/COMPONENT_43438/43438A1-mfgtest_bin.c) + zephyr_library_sources(${hal_wifi_dir_resources}/clm/COMPONENT_43438/43438A1-mfgtest_clm_blob.c) + else() + set(cyw43xx_fw_bin ${hal_blobs_dir}/firmware/COMPONENT_43438/43438A1.bin) + set(cyw43xx_clm_bin ${hal_blobs_dir}/clm/COMPONENT_43438/43438A1.clm_blob) + + zephyr_library_sources(${hal_wifi_dir_resources}/firmware/COMPONENT_43438/43438A1_bin.c) + zephyr_library_sources(${hal_wifi_dir_resources}/clm/COMPONENT_43438/43438A1_clm_blob.c) + endif() + +endif() + +# CYW43439 firmware +if(CONFIG_CYW43439 AND NOT CONFIG_AIROC_WIFI_CUSTOM) + zephyr_include_directories(${hal_wifi_dir_resources}/firmware/COMPONENT_43439) + + # firmware + if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) + set(cyw43xx_fw_bin ${hal_blobs_dir}/firmware/COMPONENT_43439/43439A0-mfgtest.bin) + zephyr_library_sources(${hal_wifi_dir_resources}/firmware/COMPONENT_43439/43439A0-mfgtest_bin.c) + else() + set(cyw43xx_fw_bin ${hal_blobs_dir}/firmware/COMPONENT_43439/43439A0.bin) + zephyr_library_sources(${hal_wifi_dir_resources}/firmware/COMPONENT_43439/43439A0_bin.c) + endif() +endif() + +# CYW4373 firmware +if(CONFIG_CYW4373 AND NOT CONFIG_AIROC_WIFI_CUSTOM) + zephyr_include_directories(${hal_wifi_dir_resources}/firmware/COMPONENT_4373) + + # firmware + if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) + set(cyw43xx_fw_bin ${hal_blobs_dir}/firmware/COMPONENT_4373/4373A0-mfgtest.bin) + zephyr_library_sources(${hal_wifi_dir_resources}/firmware/COMPONENT_4373/4373A0-mfgtest_bin.c) + else() + set(cyw43xx_fw_bin ${hal_blobs_dir}/firmware/COMPONENT_4373/4373A0.bin) + zephyr_library_sources(${hal_wifi_dir_resources}/firmware/COMPONENT_4373/4373A0_bin.c) + endif() +endif() + + +# CYW43012_MURATA_1LV clm/nvram +if(CONFIG_CYW43012_MURATA_1LV AND NOT CONFIG_AIROC_WIFI_CUSTOM) + zephyr_include_directories(${hal_wifi_dir}/WiFi_Host_Driver/resources/clm/COMPONENT_43012) + + # clm + if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) + set(cyw43xx_clm_bin ${hal_blobs_dir}/clm/COMPONENT_43012/43012C0-mfgtest.clm_blob) + + zephyr_library_sources(${hal_wifi_dir_resources}/clm/COMPONENT_43012/43012C0-mfgtest_clm_blob.c) + else() + set(cyw43xx_clm_bin ${hal_blobs_dir}/clm/COMPONENT_43012/43012C0.clm_blob) + + zephyr_library_sources(${hal_wifi_dir_resources}/clm/COMPONENT_43012/43012C0_clm_blob.c) + endif() + + # nvram + zephyr_include_directories(${hal_wifi_dir_resources}/nvram/COMPONENT_43012/COMPONENT_MURATA-1LV) +endif() + +# CYW4343W_MURATA_1DX clm/nvram +if(CONFIG_CYW4343W_MURATA_1DX AND NOT CONFIG_AIROC_WIFI_CUSTOM) + zephyr_include_directories(${hal_wifi_dir_resources}/clm/COMPONENT_4343W) + + # clm + if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) + set(cyw43xx_clm_bin ${hal_blobs_dir}/clm/COMPONENT_4343W/4343WA1-mfgtest.clm_blob) + zephyr_library_sources(${hal_wifi_dir_resources}/clm/COMPONENT_4343W/4343WA1-mfgtest_clm_blob.c) + else() + set(cyw43xx_clm_bin ${hal_blobs_dir}/clm/COMPONENT_4343W/4343WA1.clm_blob) + zephyr_library_sources(${hal_wifi_dir_resources}/clm/COMPONENT_4343W/4343WA1_clm_blob.c) + endif() + + # nvram + zephyr_include_directories(${hal_wifi_dir_resources}/nvram/COMPONENT_4343W/COMPONENT_MURATA-1DX) +endif() + +# CYW43439_MURATA_1YN +if(CONFIG_CYW43439_MURATA_1YN AND NOT CONFIG_AIROC_WIFI_CUSTOM) + zephyr_include_directories(${hal_wifi_dir_resources}/clm/COMPONENT_43439) + + # clm + if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) + set(cyw43xx_clm_bin ${hal_blobs_dir}/clm/COMPONENT_43439/43439A0-mfgtest.clm_blob) + zephyr_library_sources(${hal_wifi_dir_resources}/clm/COMPONENT_43439/43439A0-mfgtest_clm_blob.c) + else() + set(cyw43xx_clm_bin ${hal_blobs_dir}/clm/COMPONENT_43439/43439A0.clm_blob) + zephyr_library_sources(${hal_wifi_dir_resources}/clm/COMPONENT_43439/43439A0_clm_blob.c) + endif() + + # nvram + zephyr_include_directories(${hal_wifi_dir_resources}/nvram/COMPONENT_43439/COMPONENT_MURATA-1YN) +endif() + +# CYW4373_STERLING_LWB5PLUS +if(CONFIG_CYW4373_STERLING_LWB5PLUS AND NOT CONFIG_AIROC_WIFI_CUSTOM) + zephyr_include_directories(${hal_wifi_dir_resources}/clm/COMPONENT_4373/COMPONENT_STERLING-LWB5plus) + + # clm + if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) + set(cyw43xx_clm_bin ${hal_blobs_dir}/clm/COMPONENT_4373/COMPONENT_STERLING-LWB5plus/4373A0-mfgtest.clm_blob) + zephyr_library_sources(${hal_wifi_dir_resources}/clm/COMPONENT_4373/COMPONENT_STERLING-LWB5plus/4373A0-mfgtest_clm_blob.c) + else() + set(cyw43xx_clm_bin ${hal_blobs_dir}/clm/COMPONENT_4373/COMPONENT_STERLING-LWB5plus/4373A0.clm_blob) + zephyr_library_sources(${hal_wifi_dir_resources}/clm/COMPONENT_4373/COMPONENT_STERLING-LWB5plus/4373A0_clm_blob.c) + endif() + + # nvram + zephyr_include_directories_ifdef(${hal_wifi_dir_resources}/nvram/COMPONENT_4373/COMPONENT_STERLING-LWB5plus) +endif() + +# generate FW inc_blob from fw_bin +if(EXISTS ${cyw43xx_fw_bin}) + message(INFO " generate include of blob FW file: ${cyw43xx_fw_bin}") + generate_inc_file_for_target(app ${cyw43xx_fw_bin} ${cyw43xx_fw_bin_gen_inc}) +endif() + +# generate CLM inc_blob from clm_bin +if(EXISTS ${cyw43xx_clm_bin}) + message(INFO " generate include of blob CLM file: ${cyw43xx_clm_bin}") + generate_inc_file_for_target(app ${cyw43xx_clm_bin} ${cyw43xx_clm_bin_gen_inc}) +endif() diff --git a/modules/hal_nordic/nrfx/CMakeLists.txt b/modules/hal_nordic/nrfx/CMakeLists.txt index ca325c31770..69afbcc9c51 100644 --- a/modules/hal_nordic/nrfx/CMakeLists.txt +++ b/modules/hal_nordic/nrfx/CMakeLists.txt @@ -28,7 +28,9 @@ zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF52833 NRF52833_XXAA) zephyr_compile_definitions_ifdef(CONFIG_SOC_COMPATIBLE_NRF52833 NRF52833_XXAA) zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF52840 NRF52840_XXAA) zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF5340_CPUAPP NRF5340_XXAA_APPLICATION) +zephyr_compile_definitions_ifdef(CONFIG_SOC_COMPATIBLE_NRF5340_CPUAPP NRF5340_XXAA_APPLICATION) zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF5340_CPUNET NRF5340_XXAA_NETWORK) +zephyr_compile_definitions_ifdef(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET NRF5340_XXAA_NETWORK) zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF9120 NRF9120_XXAA) zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF9160 NRF9160_XXAA) @@ -102,7 +104,6 @@ zephyr_library_sources_ifdef(CONFIG_NRFX_TWIM ${SRC_DIR}/nrfx_twim.c) zephyr_library_sources_ifdef(CONFIG_NRFX_TWIS ${SRC_DIR}/nrfx_twis.c) zephyr_library_sources_ifdef(CONFIG_NRFX_UART ${SRC_DIR}/nrfx_uart.c) zephyr_library_sources_ifdef(CONFIG_NRFX_UARTE ${SRC_DIR}/nrfx_uarte.c) -zephyr_library_sources_ifdef(CONFIG_NRFX_USBD ${SRC_DIR}/nrfx_usbd.c) zephyr_library_sources_ifdef(CONFIG_NRFX_USBREG ${SRC_DIR}/nrfx_usbreg.c) zephyr_library_sources_ifdef(CONFIG_NRFX_WDT ${SRC_DIR}/nrfx_wdt.c) diff --git a/modules/hal_nordic/nrfx/Kconfig b/modules/hal_nordic/nrfx/Kconfig index 41b9c40c9a9..5dcda73c9be 100644 --- a/modules/hal_nordic/nrfx/Kconfig +++ b/modules/hal_nordic/nrfx/Kconfig @@ -82,6 +82,11 @@ config NRFX_I2S0 depends on $(dt_nodelabel_has_compat,i2s0,$(DT_COMPAT_NORDIC_NRF_I2S)) select NRFX_I2S +config NRFX_I2S20 + bool "I2S20 driver instance" + depends on $(dt_nodelabel_has_compat,i2s20,$(DT_COMPAT_NORDIC_NRF_I2S)) + select NRFX_I2S + config NRFX_IPC bool "IPC driver" depends on $(dt_has_compat,$(DT_COMPAT_NORDIC_NRF_IPC)) @@ -154,6 +159,26 @@ config NRFX_QDEC1 depends on $(dt_nodelabel_has_compat,qdec1,$(DT_COMPAT_NORDIC_NRF_QDEC)) select NRFX_QDEC +config NRFX_QDEC20 + bool "QDEC20 driver instance" + depends on $(dt_nodelabel_has_compat,qdec20,$(DT_COMPAT_NORDIC_NRF_QDEC)) + select NRFX_QDEC + +config NRFX_QDEC21 + bool "QDEC21 driver instance" + depends on $(dt_nodelabel_has_compat,qdec21,$(DT_COMPAT_NORDIC_NRF_QDEC)) + select NRFX_QDEC + +config NRFX_QDEC130 + bool "QDEC130 driver instance" + depends on $(dt_nodelabel_has_compat,qdec130,$(DT_COMPAT_NORDIC_NRF_QDEC)) + select NRFX_QDEC + +config NRFX_QDEC131 + bool "QDEC131 driver instance" + depends on $(dt_nodelabel_has_compat,qdec131,$(DT_COMPAT_NORDIC_NRF_QDEC)) + select NRFX_QDEC + config NRFX_QSPI bool "QSPI driver" depends on $(dt_has_compat,$(DT_COMPAT_NORDIC_NRF_QSPI)) @@ -230,6 +255,81 @@ config NRFX_SPIM4 depends on $(dt_nodelabel_has_compat,spi4,$(DT_COMPAT_NORDIC_NRF_SPIM)) select NRFX_SPIM +config NRFX_SPIM00 + bool "SPIM00 driver instance" + depends on $(dt_nodelabel_has_compat,spi00,$(DT_COMPAT_NORDIC_NRF_SPIM)) + select NRFX_SPIM + +config NRFX_SPIM20 + bool "SPIM20 driver instance" + depends on $(dt_nodelabel_has_compat,spi20,$(DT_COMPAT_NORDIC_NRF_SPIM)) + select NRFX_SPIM + +config NRFX_SPIM21 + bool "SPIM21 driver instance" + depends on $(dt_nodelabel_has_compat,spi21,$(DT_COMPAT_NORDIC_NRF_SPIM)) + select NRFX_SPIM + +config NRFX_SPIM22 + bool "SPIM22 driver instance" + depends on $(dt_nodelabel_has_compat,spi22,$(DT_COMPAT_NORDIC_NRF_SPIM)) + select NRFX_SPIM + +config NRFX_SPIM30 + bool "SPIM30 driver instance" + depends on $(dt_nodelabel_has_compat,spi30,$(DT_COMPAT_NORDIC_NRF_SPIM)) + select NRFX_SPIM + +config NRFX_SPIM120 + bool "SPIM120 driver instance" + depends on $(dt_nodelabel_has_compat,spi120,$(DT_COMPAT_NORDIC_NRF_SPIM)) + select NRFX_SPIM + +config NRFX_SPIM121 + bool "SPIM121 driver instance" + depends on $(dt_nodelabel_has_compat,spi121,$(DT_COMPAT_NORDIC_NRF_SPIM)) + select NRFX_SPIM + +config NRFX_SPIM130 + bool "SPIM130 driver instance" + depends on $(dt_nodelabel_has_compat,spi130,$(DT_COMPAT_NORDIC_NRF_SPIM)) + select NRFX_SPIM + +config NRFX_SPIM131 + bool "SPIM131 driver instance" + depends on $(dt_nodelabel_has_compat,spi131,$(DT_COMPAT_NORDIC_NRF_SPIM)) + select NRFX_SPIM + +config NRFX_SPIM132 + bool "SPIM132 driver instance" + depends on $(dt_nodelabel_has_compat,spi132,$(DT_COMPAT_NORDIC_NRF_SPIM)) + select NRFX_SPIM + +config NRFX_SPIM133 + bool "SPIM133 driver instance" + depends on $(dt_nodelabel_has_compat,spi133,$(DT_COMPAT_NORDIC_NRF_SPIM)) + select NRFX_SPIM + +config NRFX_SPIM134 + bool "SPIM134 driver instance" + depends on $(dt_nodelabel_has_compat,spi134,$(DT_COMPAT_NORDIC_NRF_SPIM)) + select NRFX_SPIM + +config NRFX_SPIM135 + bool "SPIM135 driver instance" + depends on $(dt_nodelabel_has_compat,spi135,$(DT_COMPAT_NORDIC_NRF_SPIM)) + select NRFX_SPIM + +config NRFX_SPIM136 + bool "SPIM136 driver instance" + depends on $(dt_nodelabel_has_compat,spi136,$(DT_COMPAT_NORDIC_NRF_SPIM)) + select NRFX_SPIM + +config NRFX_SPIM137 + bool "SPIM137 driver instance" + depends on $(dt_nodelabel_has_compat,spi137,$(DT_COMPAT_NORDIC_NRF_SPIM)) + select NRFX_SPIM + config NRFX_SPIS bool @@ -325,6 +425,71 @@ config NRFX_TWIM3 depends on $(dt_nodelabel_has_compat,i2c3,$(DT_COMPAT_NORDIC_NRF_TWIM)) select NRFX_TWIM +config NRFX_TWIM20 + bool "TWIM20 driver instance" + depends on $(dt_nodelabel_has_compat,i2c20,$(DT_COMPAT_NORDIC_NRF_TWIM)) + select NRFX_TWIM + +config NRFX_TWIM21 + bool "TWIM21 driver instance" + depends on $(dt_nodelabel_has_compat,i2c21,$(DT_COMPAT_NORDIC_NRF_TWIM)) + select NRFX_TWIM + +config NRFX_TWIM22 + bool "TWIM22 driver instance" + depends on $(dt_nodelabel_has_compat,i2c22,$(DT_COMPAT_NORDIC_NRF_TWIM)) + select NRFX_TWIM + +config NRFX_TWIM30 + bool "TWIM30 driver instance" + depends on $(dt_nodelabel_has_compat,i2c30,$(DT_COMPAT_NORDIC_NRF_TWIM)) + select NRFX_TWIM + +config NRFX_TWIM120 + bool "TWIM120 driver instance" + depends on $(dt_nodelabel_has_compat,i2c120,$(DT_COMPAT_NORDIC_NRF_TWIM)) + select NRFX_TWIM + +config NRFX_TWIM130 + bool "TWIM130 driver instance" + depends on $(dt_nodelabel_has_compat,i2c130,$(DT_COMPAT_NORDIC_NRF_TWIM)) + select NRFX_TWIM + +config NRFX_TWIM131 + bool "TWIM131 driver instance" + depends on $(dt_nodelabel_has_compat,i2c131,$(DT_COMPAT_NORDIC_NRF_TWIM)) + select NRFX_TWIM + +config NRFX_TWIM132 + bool "TWIM132 driver instance" + depends on $(dt_nodelabel_has_compat,i2c132,$(DT_COMPAT_NORDIC_NRF_TWIM)) + select NRFX_TWIM + +config NRFX_TWIM133 + bool "TWIM133 driver instance" + depends on $(dt_nodelabel_has_compat,i2c133,$(DT_COMPAT_NORDIC_NRF_TWIM)) + select NRFX_TWIM + +config NRFX_TWIM134 + bool "TWIM134 driver instance" + depends on $(dt_nodelabel_has_compat,i2c134,$(DT_COMPAT_NORDIC_NRF_TWIM)) + select NRFX_TWIM + +config NRFX_TWIM135 + bool "TWIM135 driver instance" + depends on $(dt_nodelabel_has_compat,i2c135,$(DT_COMPAT_NORDIC_NRF_TWIM)) + select NRFX_TWIM + +config NRFX_TWIM136 + bool "TWIM136 driver instance" + depends on $(dt_nodelabel_has_compat,i2c136,$(DT_COMPAT_NORDIC_NRF_TWIM)) + select NRFX_TWIM + +config NRFX_TWIM137 + bool "TWIM137 driver instance" + depends on $(dt_nodelabel_has_compat,i2c137,$(DT_COMPAT_NORDIC_NRF_TWIM)) + select NRFX_TWIM + config NRFX_TWIS bool @@ -379,19 +544,6 @@ config NRFX_UARTE3 depends on $(dt_nodelabel_has_compat,uart3,$(DT_COMPAT_NORDIC_NRF_UARTE)) select NRFX_UARTE -config NRFX_USBD - bool "USBD driver" - depends on $(dt_has_compat,$(DT_COMPAT_NORDIC_NRF_USBD)) - -config NRFX_USBD_ISO_IN_ZLP - bool "Send ZLP on ISO IN when not ready" - depends on NRFX_USBD - default y - help - Controls the response of the ISO IN endpoint to an IN token when no - data is ready to be sent. When enabled, ZLP is sent when no data is - ready. When disabled, no response is sent (bus timeout occurs). - config NRFX_USBREG bool "USBREG driver" depends on $(dt_has_compat,$(DT_COMPAT_NORDIC_NRF_USBREG)) diff --git a/modules/hal_nordic/nrfx/Kconfig.logging b/modules/hal_nordic/nrfx/Kconfig.logging index 41776380cdb..7f7b785e70c 100644 --- a/modules/hal_nordic/nrfx/Kconfig.logging +++ b/modules/hal_nordic/nrfx/Kconfig.logging @@ -132,10 +132,6 @@ config NRFX_UARTE_LOG bool "UARTE driver logging" depends on NRFX_UARTE -config NRFX_USBD_LOG - bool "USBD driver logging" - depends on NRFX_USBD - config NRFX_USBREG_LOG bool "USBREG driver logging" depends on NRFX_USBREG diff --git a/modules/hal_nordic/nrfx/nrfx_config.h b/modules/hal_nordic/nrfx/nrfx_config.h index 29051ccf754..b5b09b96078 100644 --- a/modules/hal_nordic/nrfx/nrfx_config.h +++ b/modules/hal_nordic/nrfx/nrfx_config.h @@ -141,6 +141,9 @@ #ifdef CONFIG_NRFX_I2S0 #define NRFX_I2S0_ENABLED 1 #endif +#ifdef CONFIG_NRFX_I2S20 +#define NRFX_I2S20_ENABLED 1 +#endif #ifdef CONFIG_NRFX_IPC #define NRFX_IPC_ENABLED 1 @@ -244,6 +247,18 @@ #ifdef CONFIG_NRFX_QDEC1 #define NRFX_QDEC1_ENABLED 1 #endif +#ifdef CONFIG_NRFX_QDEC20 +#define NRFX_QDEC20_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_QDEC21 +#define NRFX_QDEC21_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_QDEC130 +#define NRFX_QDEC130_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_QDEC131 +#define NRFX_QDEC131_ENABLED 1 +#endif #ifdef CONFIG_NRFX_QSPI #define NRFX_QSPI_ENABLED 1 @@ -326,6 +341,51 @@ DT_PROP(DT_NODELABEL(spi4), rx_delay_supported)) #define NRFX_SPIM_EXTENDED_ENABLED 1 #endif +#ifdef CONFIG_NRFX_SPIM00 +#define NRFX_SPIM00_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_SPIM20 +#define NRFX_SPIM20_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_SPIM21 +#define NRFX_SPIM21_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_SPIM22 +#define NRFX_SPIM22_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_SPIM30 +#define NRFX_SPIM30_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_SPIM120 +#define NRFX_SPIM120_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_SPIM121 +#define NRFX_SPIM121_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_SPIM130 +#define NRFX_SPIM130_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_SPIM131 +#define NRFX_SPIM131_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_SPIM132 +#define NRFX_SPIM132_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_SPIM133 +#define NRFX_SPIM133_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_SPIM134 +#define NRFX_SPIM134_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_SPIM135 +#define NRFX_SPIM135_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_SPIM136 +#define NRFX_SPIM136_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_SPIM137 +#define NRFX_SPIM137_ENABLED 1 +#endif #ifdef CONFIG_NRFX_SPIS #define NRFX_SPIS_ENABLED 1 @@ -413,6 +473,45 @@ #ifdef CONFIG_NRFX_TWIM3 #define NRFX_TWIM3_ENABLED 1 #endif +#ifdef CONFIG_NRFX_TWIM20 +#define NRFX_TWIM20_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_TWIM21 +#define NRFX_TWIM21_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_TWIM22 +#define NRFX_TWIM22_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_TWIM30 +#define NRFX_TWIM30_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_TWIM120 +#define NRFX_TWIM120_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_TWIM130 +#define NRFX_TWIM130_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_TWIM131 +#define NRFX_TWIM131_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_TWIM132 +#define NRFX_TWIM132_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_TWIM133 +#define NRFX_TWIM133_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_TWIM134 +#define NRFX_TWIM134_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_TWIM135 +#define NRFX_TWIM135_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_TWIM136 +#define NRFX_TWIM136_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_TWIM137 +#define NRFX_TWIM137_ENABLED 1 +#endif #ifdef CONFIG_NRFX_TWIS #define NRFX_TWIS_ENABLED 1 @@ -462,17 +561,6 @@ #define NRFX_UARTE3_ENABLED 1 #endif -#ifdef CONFIG_NRFX_USBD -#define NRFX_USBD_ENABLED 1 -#endif -#ifdef CONFIG_NRFX_USBD_LOG -#define NRFX_USBD_CONFIG_LOG_ENABLED 1 -#endif - -#ifdef CONFIG_NRFX_USBD_ISO_IN_ZLP -#define NRFX_USBD_CONFIG_ISO_IN_ZLP 1 -#endif - #ifdef CONFIG_NRFX_USBREG #define NRFX_USBREG_ENABLED 1 #endif @@ -493,6 +581,15 @@ #define NRFX_WDT1_ENABLED 1 #endif +#ifdef CONFIG_NRF52_ANOMALY_109_WORKAROUND +#define NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED 1 +#define NRFX_SPIS_NRF52_ANOMALY_109_WORKAROUND_ENABLED 1 +#define NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED 1 +#define NRFX_PWM_NRF52_ANOMALY_109_WORKAROUND_ENABLED 1 +#define NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE \ + CONFIG_NRF52_ANOMALY_109_WORKAROUND_EGU_INSTANCE +#endif + #if defined(CONFIG_SOC_SERIES_BSIM_NRFXX) #include "nrfx_config_bsim.h" #endif diff --git a/modules/hal_nordic/nrfx/nrfx_glue.h b/modules/hal_nordic/nrfx/nrfx_glue.h index 786004c05c3..2257ea879a3 100644 --- a/modules/hal_nordic/nrfx/nrfx_glue.h +++ b/modules/hal_nordic/nrfx/nrfx_glue.h @@ -357,7 +357,7 @@ void nrfx_busy_wait(uint32_t usec_to_wait); #define NRFX_PPI_GROUPS_USED_BY_MPSL 0 #endif -#if NRF_802154_VERIFY_PERIPHS_ALLOC_AGAINST_MPSL +#if defined(NRF_802154_VERIFY_PERIPHS_ALLOC_AGAINST_MPSL) BUILD_ASSERT( (NRFX_PPI_CHANNELS_USED_BY_802154_DRV & NRFX_PPI_CHANNELS_USED_BY_MPSL) == 0, "PPI channels used by the IEEE802.15.4 radio driver overlap with those " diff --git a/modules/hal_nxp/CMakeLists.txt b/modules/hal_nxp/CMakeLists.txt index 17f5cfdd078..01e6d58ccae 100644 --- a/modules/hal_nxp/CMakeLists.txt +++ b/modules/hal_nxp/CMakeLists.txt @@ -12,4 +12,7 @@ if(CONFIG_HAS_MCUX OR CONFIG_HAS_IMX_HAL OR CONFIG_HAS_NXP_S32_HAL) zephyr_include_directories_ifdef(CONFIG_PWM_MCUX_CTIMER ${ZEPHYR_CURRENT_MODULE_DIR}/mcux/mcux-sdk/drivers/ctimer/) zephyr_include_directories(.) + + zephyr_compile_definitions_ifdef(CONFIG_CAN_MCUX_FLEXCAN + FLEXCAN_WAIT_TIMEOUT=${CONFIG_CAN_MCUX_FLEXCAN_WAIT_TIMEOUT}) endif() diff --git a/modules/hal_nxp/usb/usb_device_config.h b/modules/hal_nxp/usb/usb_device_config.h index ca2bc5d9373..31a62ffbfeb 100644 --- a/modules/hal_nxp/usb/usb_device_config.h +++ b/modules/hal_nxp/usb/usb_device_config.h @@ -39,7 +39,15 @@ /* Whether device is self power. 1U supported, 0U not supported */ #define USB_DEVICE_CONFIG_SELF_POWER (1U) -#define DT_DRV_COMPAT nxp_mcux_usbd +#define NUM_INSTS DT_NUM_INST_STATUS_OKAY(nxp_ehci) + DT_NUM_INST_STATUS_OKAY(nxp_lpcip3511) +BUILD_ASSERT(NUM_INSTS <= 1, "Only one USB device supported"); +#if DT_HAS_COMPAT_STATUS_OKAY(nxp_lpcip3511) +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nxp_lpcip3511 +#elif DT_HAS_COMPAT_STATUS_OKAY(nxp_ehci) +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nxp_ehci +#endif /* Number of endpoints supported */ #define USB_DEVICE_CONFIG_ENDPOINTS (DT_INST_PROP(0, num_bidir_endpoints)) diff --git a/modules/hal_rpi_pico/CMakeLists.txt b/modules/hal_rpi_pico/CMakeLists.txt index c085785a093..3281528d73f 100644 --- a/modules/hal_rpi_pico/CMakeLists.txt +++ b/modules/hal_rpi_pico/CMakeLists.txt @@ -42,7 +42,7 @@ if(CONFIG_HAS_RPI_PICO) BUILD_ALWAYS TRUE ) - add_dependencies(${ZEPHYR_CURRENT_LIBRARY} second_stage_bootloader) + zephyr_library_add_dependencies(second_stage_bootloader) zephyr_library_sources(${rp2_bootloader_asm}) endif() @@ -105,6 +105,11 @@ if(CONFIG_HAS_RPI_PICO) zephyr_include_directories_ifdef(CONFIG_PICOSDK_USE_DMA ${rp2_common_dir}/hardware_dma/include) + zephyr_library_sources_ifdef(CONFIG_PICOSDK_USE_TIMER + ${rp2_common_dir}/hardware_timer/timer.c) + zephyr_include_directories_ifdef(CONFIG_PICOSDK_USE_TIMER + ${rp2_common_dir}/hardware_timer/include) + zephyr_library_sources_ifdef(CONFIG_PICOSDK_USE_CLAIM ${rp2_common_dir}/hardware_claim/claim.c) zephyr_include_directories_ifdef(CONFIG_PICOSDK_USE_CLAIM diff --git a/modules/hal_rpi_pico/Kconfig b/modules/hal_rpi_pico/Kconfig index 4baf11dd406..56f92ea427e 100644 --- a/modules/hal_rpi_pico/Kconfig +++ b/modules/hal_rpi_pico/Kconfig @@ -44,3 +44,8 @@ config PICOSDK_USE_CLAIM bool help Use the "claim" driver from pico-sdk + +config PICOSDK_USE_TIMER + bool + help + Use the TIMER driver from pico-sdk diff --git a/modules/hostap/CMakeLists.txt b/modules/hostap/CMakeLists.txt new file mode 100644 index 00000000000..ed6b8185873 --- /dev/null +++ b/modules/hostap/CMakeLists.txt @@ -0,0 +1,84 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +if(CONFIG_WIFI_NM_WPA_SUPPLICANT) + +zephyr_library() + +set(HOSTAP_BASE ${ZEPHYR_HOSTAP_MODULE_DIR}) +set(WIFI_NM_WPA_SUPPLICANT_BASE ${HOSTAP_BASE}/wpa_supplicant) +set(HOSTAP_SRC_BASE ${HOSTAP_BASE}/src) + +set(CMAKE_EXE_LINKER_FLAGS "--specs=nosys.specs -lnosys") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMISSING_SYSCALL_NAMES") + +zephyr_compile_definitions( + CONFIG_ZEPHYR +) + +zephyr_include_directories( + ${HOSTAP_BASE}/ + ${WIFI_NM_WPA_SUPPLICANT_BASE}/ + ${HOSTAP_SRC_BASE}/ +) + +zephyr_library_compile_definitions( + TLS_DEFAULT_CIPHERS=\""DEFAULT:!EXP:!LOW"\" + CONFIG_SME + CONFIG_NO_CONFIG_WRITE + CONFIG_NO_CONFIG_BLOBS + CONFIG_CTRL_IFACE + CONFIG_NO_RANDOM_POOL + CONFIG_NO_WPA + CONFIG_NO_PBKDF2 + ) + +zephyr_library_include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/src + ${HOSTAP_BASE}/ + ${HOSTAP_SRC_BASE}/utils + ${HOSTAP_SRC_BASE}/drivers + ${HOSTAP_BASE}/src + ${ZEPHYR_BASE}/include + ${ZEPHYR_BASE}/include/net +) + +zephyr_library_sources( + ${HOSTAP_SRC_BASE}/common/wpa_common.c + ${HOSTAP_SRC_BASE}/common/ieee802_11_common.c + ${HOSTAP_SRC_BASE}/common/hw_features_common.c + ${HOSTAP_SRC_BASE}/common/wpa_ctrl.c + ${HOSTAP_SRC_BASE}/common/cli.c + + ${HOSTAP_SRC_BASE}/drivers/driver_common.c + ${HOSTAP_SRC_BASE}/drivers/drivers.c + ${HOSTAP_SRC_BASE}/utils/base64.c + ${HOSTAP_SRC_BASE}/utils/common.c + ${HOSTAP_SRC_BASE}/utils/wpabuf.c + ${HOSTAP_SRC_BASE}/utils/bitfield.c + ${HOSTAP_SRC_BASE}/utils/eloop.c + ${HOSTAP_SRC_BASE}/utils/os_zephyr.c + ${HOSTAP_SRC_BASE}/utils/wpa_debug_zephyr.c + ${HOSTAP_SRC_BASE}/crypto/crypto_none.c + ${HOSTAP_SRC_BASE}/crypto/tls_none.c + + ${WIFI_NM_WPA_SUPPLICANT_BASE}/config.c + ${WIFI_NM_WPA_SUPPLICANT_BASE}/notify.c + ${WIFI_NM_WPA_SUPPLICANT_BASE}/eap_register.c + ${WIFI_NM_WPA_SUPPLICANT_BASE}/op_classes.c + ${WIFI_NM_WPA_SUPPLICANT_BASE}/rrm.c + ${WIFI_NM_WPA_SUPPLICANT_BASE}/wmm_ac.c + ${WIFI_NM_WPA_SUPPLICANT_BASE}/config_none.c + ${WIFI_NM_WPA_SUPPLICANT_BASE}/bssid_ignore.c + ${WIFI_NM_WPA_SUPPLICANT_BASE}/wpas_glue.c + ${WIFI_NM_WPA_SUPPLICANT_BASE}/scan.c + ${WIFI_NM_WPA_SUPPLICANT_BASE}/ctrl_iface.c + + # Zephyr specific files (glue code) + # TBD +) + +endif() diff --git a/modules/hostap/Kconfig b/modules/hostap/Kconfig new file mode 100644 index 00000000000..5ff3c13a494 --- /dev/null +++ b/modules/hostap/Kconfig @@ -0,0 +1,90 @@ +# WPA Supplicant configuration options +# +# Copyright (c) 2023 Nordic Semiconductor +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NM_WPA_SUPPLICANT + bool "WPA Suplicant from hostap project [EXPERIMENTAL]" + select POSIX_CLOCK + select NET_SOCKETS + select NET_SOCKETS_PACKET + select NET_SOCKETPAIR + select NET_L2_WIFI_MGMT + select WIFI_NM + select EXPERIMENTAL + help + WPA supplicant as a network management backend for WIFI_NM. + +config WIFI_NM_WPA_SUPPLICANT_THREAD_STACK_SIZE + int "Stack size for wpa_supplicant thread" + default 8192 + +# Currently we default POSIX_MAX_FDS to 16 in lib/posix/Kconfig +# l2_packet - 1 +# ctrl_iface - 2 * socketpairs = 4(local and global) +# z_wpa_event_sock - 1 socketpair = 2 +# Remaining left for the applications running in default configuration + +# Supplicant API is stack heavy (buffers + snprintfs) and control interface +# uses socketpair which pushes the stack usage causing overflow for 2048 bytes. +# So we set SYSTEM_WORKQUEUE_STACK_SIZE default to 2560 in kernel/Kconfig + +module = WIFI_NM_WPA_SUPPLICANT +module-str = WPA supplicant +source "subsys/logging/Kconfig.template.log_config" + +config WIFI_NM_WPA_SUPPLICANT_DEBUG_LEVEL + int "Min compiled-in debug message level for WPA supplicant" + default 0 if WIFI_NM_WPA_SUPPLICANT_LOG_LEVEL_DBG # MSG_EXCESSIVE + default 3 if WIFI_NM_WPA_SUPPLICANT_LOG_LEVEL_INF # MSG_INFO + default 4 if WIFI_NM_WPA_SUPPLICANT_LOG_LEVEL_WRN # MSG_WARNING + default 5 if WIFI_NM_WPA_SUPPLICANT_LOG_LEVEL_ERR # MSG_ERROR + default 6 + help + Minimum priority level of a debug message emitted by WPA supplicant that + is compiled-in the firmware. See wpa_debug.h file of the supplicant for + available levels and functions for emitting the messages. Note that + runtime filtering can also be configured in addition to the compile-time + filtering. + +if WIFI_NM_WPA_SUPPLICANT + +# Create hidden config options that are used in hostap. This way we do not need +# to mark them as allowed for CI checks, and also someone else cannot use the +# same name options. + +config SME + bool + default y + +config NO_CONFIG_WRITE + bool + default y + +config NO_CONFIG_BLOBS + bool + default y + +config CTRL_IFACE + bool + default y + +config NO_RANDOM_POOL + bool + default y + +config NO_WPA + bool + default y + +config NO_PBKDF2 + bool + default y + +config ZEPHYR + bool + default y + +endif # WIFI_NM_WPA_SUPPLICANT diff --git a/modules/liblc3/Kconfig b/modules/liblc3/Kconfig index aaca9d95d7b..11ce2e34a6c 100644 --- a/modules/liblc3/Kconfig +++ b/modules/liblc3/Kconfig @@ -7,5 +7,6 @@ config ZEPHYR_LIBLC3_MODULE config LIBLC3 bool "liblc3 Support" depends on FPU + select REQUIRES_FULL_LIBC help This option enables the Android liblc3 library for Bluetooth LE Audio diff --git a/modules/lvgl/CMakeLists.txt b/modules/lvgl/CMakeLists.txt index e6286f8e205..51eb2bd11da 100644 --- a/modules/lvgl/CMakeLists.txt +++ b/modules/lvgl/CMakeLists.txt @@ -13,10 +13,10 @@ zephyr_interface_library_named(LVGL) zephyr_library() zephyr_include_directories(${LVGL_DIR}/src/) -zephyr_include_directories(.) +zephyr_include_directories(include) zephyr_compile_definitions(LV_CONF_INCLUDE_SIMPLE=1) -zephyr_compile_definitions(LV_CONF_PATH=${CMAKE_CURRENT_SOURCE_DIR}/lv_conf.h) +zephyr_compile_definitions(LV_CONF_PATH=${CMAKE_CURRENT_SOURCE_DIR}/include/lv_conf.h) zephyr_library_sources( ${LVGL_DIR}/src/core/lv_disp.c @@ -227,6 +227,7 @@ zephyr_library_sources(input/lvgl_common_input.c) zephyr_library_sources_ifdef(CONFIG_LV_Z_POINTER_KSCAN input/lvgl_pointer_kscan.c) zephyr_library_sources_ifdef(CONFIG_LV_Z_POINTER_INPUT input/lvgl_pointer_input.c) zephyr_library_sources_ifdef(CONFIG_LV_Z_BUTTON_INPUT input/lvgl_button_input.c) +zephyr_library_sources_ifdef(CONFIG_LV_Z_ENCODER_INPUT input/lvgl_encoder_input.c) zephyr_library_link_libraries(LVGL) target_link_libraries(LVGL INTERFACE zephyr_interface) diff --git a/modules/lvgl/Kconfig b/modules/lvgl/Kconfig index 9b73705ddb0..4bd00b1bc55 100644 --- a/modules/lvgl/Kconfig +++ b/modules/lvgl/Kconfig @@ -22,6 +22,36 @@ config LV_CONF_SKIP bool default n +config LV_USE_LOG + bool + +config LV_LOG_LEVEL_NONE + bool + +config LV_LOG_LEVEL_ERROR + bool + +config LV_LOG_LEVEL_WARN + bool + +config LV_LOG_LEVEL_INFO + bool + +config LV_LOG_LEVEL_USER + bool + +config LV_LOG_LEVEL_TRACE + bool + +config LV_Z_LOG_LEVEL + int + default 0 if LV_LOG_LEVEL_NONE || !LV_USE_LOG + default 1 if LV_LOG_LEVEL_ERROR + default 2 if LV_LOG_LEVEL_WARN + default 3 if LV_LOG_LEVEL_INFO + default 3 if LV_LOG_LEVEL_USER + default 4 if LV_LOG_LEVEL_TRACE + config APP_LINK_WITH_LVGL bool "Link 'app' with LVGL" default y diff --git a/modules/lvgl/Kconfig.input b/modules/lvgl/Kconfig.input index 37b316dc36e..b6cbdad0c28 100644 --- a/modules/lvgl/Kconfig.input +++ b/modules/lvgl/Kconfig.input @@ -4,10 +4,6 @@ menu "Input device settings" -config LV_Z_INPUT_INIT_PRIORITY - int - default 91 - config LV_Z_POINTER_KSCAN bool "Keyboard scan pointer input" depends on KSCAN @@ -68,4 +64,17 @@ config LV_Z_BUTTON_INPUT_MSGQ_COUNT help Size of the button message queue buffering input events. +config LV_Z_ENCODER_INPUT + bool "Input lvgl encoder" + default y + depends on INPUT + depends on DT_HAS_ZEPHYR_LVGL_ENCODER_INPUT_ENABLED + +config LV_Z_ENCODER_INPUT_MSGQ_COUNT + int "Input encoder queue message count" + default 4 + depends on LV_Z_ENCODER_INPUT + help + Size of the encoder message queue buffering input events. + endmenu diff --git a/modules/lvgl/Kconfig.memory b/modules/lvgl/Kconfig.memory index 29ccc8e910a..fc59eccb2e3 100644 --- a/modules/lvgl/Kconfig.memory +++ b/modules/lvgl/Kconfig.memory @@ -31,30 +31,16 @@ choice LV_Z_MEMORY_POOL endchoice -if LV_Z_MEM_POOL_SYS_HEAP - -config LV_Z_MEM_POOL_MIN_SIZE - int "Minimum memory pool block size" - default 16 - help - Size of the smallest block in the memory pool in bytes - -config LV_Z_MEM_POOL_MAX_SIZE - int "Maximum memory pool block size" +config LV_Z_MEM_POOL_SIZE + int "Memory pool size" default 2048 + depends on LV_Z_MEM_POOL_SYS_HEAP help - Size of the largest block in the memory pool in bytes - -config LV_Z_MEM_POOL_NUMBER_BLOCKS - int "Number of max size blocks in memory pool" - default 1 - help - Number of maximum sized blocks in the memory pool. - -endif + Size of the memory pool in bytes config LV_Z_VDB_SIZE int "Rendering buffer size" + default 100 if LV_Z_FULL_REFRESH default 10 range 1 100 help diff --git a/modules/lvgl/lv_conf.h b/modules/lvgl/include/lv_conf.h similarity index 97% rename from modules/lvgl/lv_conf.h rename to modules/lvgl/include/lv_conf.h index 20e60058ae3..9dd7b510f73 100644 --- a/modules/lvgl/lv_conf.h +++ b/modules/lvgl/include/lv_conf.h @@ -11,6 +11,7 @@ /* Memory manager settings */ #define LV_MEMCPY_MEMSET_STD 1 +#define LV_MEM_CUSTOM 1 #if defined(CONFIG_LV_Z_MEM_POOL_HEAP_LIB_C) diff --git a/modules/lvgl/include/lvgl_button_input.h b/modules/lvgl/include/lvgl_button_input.h new file mode 100644 index 00000000000..dd97b5e7c7f --- /dev/null +++ b/modules/lvgl/include/lvgl_button_input.h @@ -0,0 +1,22 @@ +/* + * Copyright 2023 Fabian Blatz + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_MODULES_LVGL_LVGL_BUTTON_INPUT_H_ +#define ZEPHYR_MODULES_LVGL_LVGL_BUTTON_INPUT_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int lvgl_button_input_init(const struct device *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_MODULES_LVGL_LVGL_BUTTON_INPUT_H_ */ diff --git a/modules/lvgl/input/lvgl_common_input.h b/modules/lvgl/include/lvgl_common_input.h similarity index 96% rename from modules/lvgl/input/lvgl_common_input.h rename to modules/lvgl/include/lvgl_common_input.h index e9d0ef34f84..c34dabe1a8a 100644 --- a/modules/lvgl/input/lvgl_common_input.h +++ b/modules/lvgl/include/lvgl_common_input.h @@ -23,9 +23,11 @@ struct lvgl_common_input_data { lv_indev_drv_t indev_drv; lv_indev_t *indev; lv_indev_data_t pending_event; + lv_indev_data_t previous_event; }; int lvgl_input_register_driver(lv_indev_type_t indev_type, const struct device *dev); +int lvgl_init_input_devices(void); #define LVGL_INPUT_EVENT_MSGQ(inst, type) lvgl_input_msgq_##type##_##inst #define LVGL_INPUT_DEVICE(inst) DEVICE_DT_GET_OR_NULL(DT_INST_PHANDLE(inst, input)) diff --git a/modules/lvgl/lvgl_display.h b/modules/lvgl/include/lvgl_display.h similarity index 100% rename from modules/lvgl/lvgl_display.h rename to modules/lvgl/include/lvgl_display.h diff --git a/modules/lvgl/include/lvgl_encoder_input.h b/modules/lvgl/include/lvgl_encoder_input.h new file mode 100644 index 00000000000..1fe9a23c2c4 --- /dev/null +++ b/modules/lvgl/include/lvgl_encoder_input.h @@ -0,0 +1,22 @@ +/* + * Copyright 2023 Fabian Blatz + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_MODULES_LVGL_LVGL_ENCODER_INPUT_H_ +#define ZEPHYR_MODULES_LVGL_LVGL_ENCODER_INPUT_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int lvgl_encoder_input_init(const struct device *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_MODULES_LVGL_LVGL_ENCODER_INPUT_H_ */ diff --git a/modules/lvgl/lvgl_fs.h b/modules/lvgl/include/lvgl_fs.h similarity index 100% rename from modules/lvgl/lvgl_fs.h rename to modules/lvgl/include/lvgl_fs.h diff --git a/modules/lvgl/include/lvgl_input_device.h b/modules/lvgl/include/lvgl_input_device.h new file mode 100644 index 00000000000..2e538c92d35 --- /dev/null +++ b/modules/lvgl/include/lvgl_input_device.h @@ -0,0 +1,23 @@ +/* + * Copyright 2023 Fabian Blatz + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_MODULES_LVGL_INPUT_DEVICE_H_ +#define ZEPHYR_MODULES_LVGL_INPUT_DEVICE_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +lv_indev_t *lvgl_input_get_indev(const struct device *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_MODULES_LVGL_INPUT_DEVICE_H_ */ diff --git a/modules/lvgl/lvgl_mem.h b/modules/lvgl/include/lvgl_mem.h similarity index 94% rename from modules/lvgl/lvgl_mem.h rename to modules/lvgl/include/lvgl_mem.h index 7e66581c0ff..02dea4537a0 100644 --- a/modules/lvgl/lvgl_mem.h +++ b/modules/lvgl/include/lvgl_mem.h @@ -22,6 +22,8 @@ void lvgl_free(void *ptr); void lvgl_print_heap_info(bool dump_chunks); +void lvgl_heap_init(void); + #ifdef __cplusplus } #endif diff --git a/modules/lvgl/include/lvgl_pointer_input.h b/modules/lvgl/include/lvgl_pointer_input.h new file mode 100644 index 00000000000..f168477b982 --- /dev/null +++ b/modules/lvgl/include/lvgl_pointer_input.h @@ -0,0 +1,22 @@ +/* + * Copyright 2023 Fabian Blatz + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_MODULES_LVGL_LVGL_POINTER_INPUT_H_ +#define ZEPHYR_MODULES_LVGL_LVGL_POINTER_INPUT_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int lvgl_pointer_input_init(const struct device *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_MODULES_LVGL_LVGL_POINTER_INPUT_H_ */ diff --git a/modules/lvgl/input/lvgl_button_input.c b/modules/lvgl/input/lvgl_button_input.c index d340721b556..8ac96b7fed5 100644 --- a/modules/lvgl/input/lvgl_button_input.c +++ b/modules/lvgl/input/lvgl_button_input.c @@ -7,10 +7,11 @@ #define DT_DRV_COMPAT zephyr_lvgl_button_input #include "lvgl_common_input.h" +#include "lvgl_button_input.h" #include -LOG_MODULE_DECLARE(lvgl); +LOG_MODULE_DECLARE(lvgl, CONFIG_LV_Z_LOG_LEVEL); struct lvgl_button_input_config { struct lvgl_common_input_config common_config; /* Needs to be first member */ @@ -44,7 +45,7 @@ static void lvgl_button_process_event(const struct device *dev, struct input_eve } } -static int lvgl_button_input_init(const struct device *dev) +int lvgl_button_input_init(const struct device *dev) { struct lvgl_common_input_data *data = dev->data; const struct lvgl_button_input_config *cfg = dev->config; @@ -79,8 +80,8 @@ static int lvgl_button_input_init(const struct device *dev) .coordinates = lvgl_button_coordinates_##inst, \ }; \ static struct lvgl_common_input_data lvgl_common_input_data_##inst; \ - DEVICE_DT_INST_DEFINE(inst, lvgl_button_input_init, NULL, &lvgl_common_input_data_##inst, \ - &lvgl_button_input_config_##inst, APPLICATION, \ - CONFIG_LV_Z_INPUT_INIT_PRIORITY, NULL); + DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &lvgl_common_input_data_##inst, \ + &lvgl_button_input_config_##inst, POST_KERNEL, \ + CONFIG_INPUT_INIT_PRIORITY, NULL); DT_INST_FOREACH_STATUS_OKAY(LVGL_BUTTON_INPUT_DEFINE) diff --git a/modules/lvgl/input/lvgl_common_input.c b/modules/lvgl/input/lvgl_common_input.c index 23b61a230e6..2894538c62b 100644 --- a/modules/lvgl/input/lvgl_common_input.c +++ b/modules/lvgl/input/lvgl_common_input.c @@ -8,15 +8,36 @@ #include #include #include +#include +#include "lvgl_pointer_input.h" +#include "lvgl_button_input.h" +#include "lvgl_encoder_input.h" -LOG_MODULE_DECLARE(lvgl); +LOG_MODULE_DECLARE(lvgl, CONFIG_LV_Z_LOG_LEVEL); + +lv_indev_t *lvgl_input_get_indev(const struct device *dev) +{ + struct lvgl_common_input_data *common_data = dev->data; + + return common_data->indev; +} static void lvgl_input_read_cb(lv_indev_drv_t *drv, lv_indev_data_t *data) { const struct device *dev = drv->user_data; const struct lvgl_common_input_config *cfg = dev->config; + struct lvgl_common_input_data *common_data = dev->data; + + if (k_msgq_get(cfg->event_msgq, data, K_NO_WAIT) != 0) { + memcpy(data, &common_data->previous_event, sizeof(lv_indev_data_t)); + if (drv->type == LV_INDEV_TYPE_ENCODER) { + data->enc_diff = 0; /* For encoders, clear last movement */ + } + data->continue_reading = false; + return; + } - k_msgq_get(cfg->event_msgq, data, K_NO_WAIT); + memcpy(&common_data->previous_event, data, sizeof(lv_indev_data_t)); data->continue_reading = k_msgq_num_used_get(cfg->event_msgq) > 0; } @@ -44,3 +65,30 @@ int lvgl_input_register_driver(lv_indev_type_t indev_type, const struct device * return 0; } + +#define LV_DEV_INIT(node_id, init_fn) \ + do { \ + int ret = init_fn(DEVICE_DT_GET(node_id)); \ + if (ret) { \ + return ret; \ + } \ + } while (0) + +int lvgl_init_input_devices(void) +{ +#ifdef CONFIG_LV_Z_POINTER_INPUT + DT_FOREACH_STATUS_OKAY_VARGS(zephyr_lvgl_pointer_input, LV_DEV_INIT, + lvgl_pointer_input_init); +#endif /* CONFIG_LV_Z_POINTER_INPUT */ + +#ifdef CONFIG_LV_Z_BUTTON_INPUT + DT_FOREACH_STATUS_OKAY_VARGS(zephyr_lvgl_button_input, LV_DEV_INIT, lvgl_button_input_init); +#endif /* CONFIG_LV_Z_BUTTON_INPUT */ + +#ifdef CONFIG_LV_Z_ENCODER_INPUT + DT_FOREACH_STATUS_OKAY_VARGS(zephyr_lvgl_encoder_input, LV_DEV_INIT, + lvgl_encoder_input_init); +#endif /* CONFIG_LV_Z_ENCODER_INPUT */ + + return 0; +} diff --git a/modules/lvgl/input/lvgl_encoder_input.c b/modules/lvgl/input/lvgl_encoder_input.c new file mode 100644 index 00000000000..b68ca67b871 --- /dev/null +++ b/modules/lvgl/input/lvgl_encoder_input.c @@ -0,0 +1,72 @@ +/* + * Copyright 2023 Fabian Blatz + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT zephyr_lvgl_encoder_input + +#include "lvgl_common_input.h" +#include "lvgl_encoder_input.h" + +#include + +LOG_MODULE_DECLARE(lvgl, CONFIG_LV_Z_LOG_LEVEL); + +struct lvgl_encoder_input_config { + struct lvgl_common_input_config common_config; /* Needs to be first member */ + int rotation_input_code; + int button_input_code; +}; + +static void lvgl_encoder_process_event(const struct device *dev, struct input_event *evt) +{ + struct lvgl_common_input_data *data = dev->data; + const struct lvgl_encoder_input_config *cfg = dev->config; + + if (evt->code == cfg->rotation_input_code) { + data->pending_event.enc_diff = evt->value; + } else if (evt->code == cfg->button_input_code) { + data->pending_event.state = evt->value ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL; + } else { + LOG_DBG("Ignored input event: %u", evt->code); + return; + } + + if (k_msgq_put(cfg->common_config.event_msgq, &data->pending_event, K_NO_WAIT) != 0) { + LOG_WRN("Could not put input data into queue"); + } +} + +int lvgl_encoder_input_init(const struct device *dev) +{ + return lvgl_input_register_driver(LV_INDEV_TYPE_ENCODER, dev); +} + +#define BUTTON_CODE(inst) DT_INST_PROP_OR(inst, button_input_code, -1) +#define ROTATION_CODE(inst) DT_INST_PROP(inst, rotation_input_code) + +#define ASSERT_PROPERTIES(inst) \ + BUILD_ASSERT(IN_RANGE(ROTATION_CODE(inst), 0, 65536), \ + "Property rotation-input-code needs to be between 0 and 65536."); \ + BUILD_ASSERT(!DT_INST_NODE_HAS_PROP(inst, button_input_code) || \ + IN_RANGE(BUTTON_CODE(inst), 0, 65536), \ + "Property button-input-code needs to be between 0 and 65536."); \ + BUILD_ASSERT(ROTATION_CODE(inst) != BUTTON_CODE(inst), \ + "Property rotation-input-code and button-input-code should not be equal.") + +#define LVGL_ENCODER_INPUT_DEFINE(inst) \ + ASSERT_PROPERTIES(inst); \ + LVGL_INPUT_DEFINE(inst, encoder, CONFIG_LV_Z_ENCODER_INPUT_MSGQ_COUNT, \ + lvgl_encoder_process_event); \ + static const struct lvgl_encoder_input_config lvgl_encoder_input_config_##inst = { \ + .common_config.event_msgq = &LVGL_INPUT_EVENT_MSGQ(inst, encoder), \ + .rotation_input_code = ROTATION_CODE(inst), \ + .button_input_code = BUTTON_CODE(inst), \ + }; \ + static struct lvgl_common_input_data lvgl_common_input_data_##inst; \ + DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &lvgl_common_input_data_##inst, \ + &lvgl_encoder_input_config_##inst, POST_KERNEL, \ + CONFIG_INPUT_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(LVGL_ENCODER_INPUT_DEFINE) diff --git a/modules/lvgl/input/lvgl_pointer_input.c b/modules/lvgl/input/lvgl_pointer_input.c index 483c36a456b..1abfd69d29a 100644 --- a/modules/lvgl/input/lvgl_pointer_input.c +++ b/modules/lvgl/input/lvgl_pointer_input.c @@ -7,11 +7,12 @@ #define DT_DRV_COMPAT zephyr_lvgl_pointer_input #include "lvgl_common_input.h" +#include "lvgl_pointer_input.h" #include #include -LOG_MODULE_DECLARE(lvgl); +LOG_MODULE_DECLARE(lvgl, CONFIG_LV_Z_LOG_LEVEL); struct lvgl_pointer_input_config { struct lvgl_common_input_config common_config; /* Needs to be first member */ @@ -108,7 +109,7 @@ static void lvgl_pointer_process_event(const struct device *dev, struct input_ev } } -static int lvgl_pointer_input_init(const struct device *dev) +int lvgl_pointer_input_init(const struct device *dev) { return lvgl_input_register_driver(LV_INDEV_TYPE_POINTER, dev); } @@ -123,8 +124,8 @@ static int lvgl_pointer_input_init(const struct device *dev) .invert_y = DT_INST_PROP(inst, invert_y), \ }; \ static struct lvgl_common_input_data lvgl_common_input_data_##inst; \ - DEVICE_DT_INST_DEFINE(inst, lvgl_pointer_input_init, NULL, &lvgl_common_input_data_##inst, \ - &lvgl_pointer_input_config_##inst, APPLICATION, \ - CONFIG_LV_Z_INPUT_INIT_PRIORITY, NULL); + DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &lvgl_common_input_data_##inst, \ + &lvgl_pointer_input_config_##inst, POST_KERNEL, \ + CONFIG_INPUT_INIT_PRIORITY, NULL); DT_INST_FOREACH_STATUS_OKAY(LVGL_POINTER_INPUT_DEFINE) diff --git a/modules/lvgl/input/lvgl_pointer_kscan.c b/modules/lvgl/input/lvgl_pointer_kscan.c index f3115ffa029..43c309349ed 100644 --- a/modules/lvgl/input/lvgl_pointer_kscan.c +++ b/modules/lvgl/input/lvgl_pointer_kscan.c @@ -10,7 +10,7 @@ #include "lvgl_display.h" #include -LOG_MODULE_DECLARE(lvgl); +LOG_MODULE_DECLARE(lvgl, CONFIG_LV_Z_LOG_LEVEL); static lv_indev_drv_t indev_drv; #define KSCAN_NODE DT_CHOSEN(zephyr_keyboard_scan) @@ -146,4 +146,4 @@ static int lvgl_kscan_pointer_init(void) return 0; } -SYS_INIT(lvgl_kscan_pointer_init, APPLICATION, CONFIG_LV_Z_INPUT_INIT_PRIORITY); +SYS_INIT(lvgl_kscan_pointer_init, APPLICATION, CONFIG_INPUT_INIT_PRIORITY); diff --git a/modules/lvgl/lvgl.c b/modules/lvgl/lvgl.c index 46c575e2245..76df359e7fc 100644 --- a/modules/lvgl/lvgl.c +++ b/modules/lvgl/lvgl.c @@ -8,14 +8,17 @@ #include #include #include "lvgl_display.h" +#include "lvgl_common_input.h" #ifdef CONFIG_LV_Z_USE_FILESYSTEM #include "lvgl_fs.h" #endif +#ifdef CONFIG_LV_Z_MEM_POOL_SYS_HEAP +#include "lvgl_mem.h" +#endif #include LV_MEM_CUSTOM_INCLUDE -#define LOG_LEVEL CONFIG_LV_LOG_LEVEL #include -LOG_MODULE_REGISTER(lvgl); +LOG_MODULE_REGISTER(lvgl, CONFIG_LV_Z_LOG_LEVEL); static lv_disp_drv_t disp_drv; struct lvgl_disp_data disp_data = { @@ -57,7 +60,7 @@ static uint8_t buf1[BUFFER_SIZE] #endif /* CONFIG_LV_Z_BUFFER_ALLOC_STATIC */ -#if CONFIG_LV_LOG_LEVEL != 0 +#if CONFIG_LV_Z_LOG_LEVEL != 0 /* * In LVGLv8 the signature of the logging callback has changes and it no longer * takes the log level as an integer argument. Instead, the log level is now @@ -79,7 +82,7 @@ static void lvgl_log(const char *buf) LOG_ERR("%s", buf + strlen("[Error] ")); break; case 'W': - LOG_WRN("%s", buf + strlen("Warn] ")); + LOG_WRN("%s", buf + strlen("[Warn] ")); break; case 'I': LOG_INF("%s", buf + strlen("[Info] ")); @@ -87,6 +90,9 @@ static void lvgl_log(const char *buf) case 'T': LOG_DBG("%s", buf + strlen("[Trace] ")); break; + case 'U': + LOG_INF("%s", buf + strlen("[User] ")); + break; } } #endif @@ -190,7 +196,6 @@ static int lvgl_allocate_rendering_buffers(lv_disp_drv_t *disp_driver) static int lvgl_init(void) { - const struct device *display_dev = DEVICE_DT_GET(DISPLAY_NODE); int err = 0; @@ -200,7 +205,11 @@ static int lvgl_init(void) return -ENODEV; } -#if CONFIG_LV_LOG_LEVEL != 0 +#ifdef CONFIG_LV_Z_MEM_POOL_SYS_HEAP + lvgl_heap_init(); +#endif + +#if CONFIG_LV_Z_LOG_LEVEL != 0 lv_log_register_print_cb(lvgl_log); #endif @@ -235,12 +244,13 @@ static int lvgl_init(void) return -EPERM; } + err = lvgl_init_input_devices(); + if (err < 0) { + LOG_ERR("Failed to initialize input devices."); + return err; + } + return 0; } -BUILD_ASSERT(CONFIG_APPLICATION_INIT_PRIORITY < CONFIG_LV_Z_INPUT_INIT_PRIORITY); -#ifdef CONFIG_INPUT -BUILD_ASSERT(CONFIG_INPUT_INIT_PRIORITY < CONFIG_LV_Z_INPUT_INIT_PRIORITY); -#endif /* CONFIG_INPUT */ - SYS_INIT(lvgl_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); diff --git a/modules/lvgl/lvgl_mem.c b/modules/lvgl/lvgl_mem.c index f41ede520cb..001546a23ad 100644 --- a/modules/lvgl/lvgl_mem.c +++ b/modules/lvgl/lvgl_mem.c @@ -10,9 +10,7 @@ #include #include -#define HEAP_BYTES (CONFIG_LV_Z_MEM_POOL_MAX_SIZE * CONFIG_LV_Z_MEM_POOL_NUMBER_BLOCKS) - -static char lvgl_heap_mem[HEAP_BYTES] __aligned(8); +static char lvgl_heap_mem[CONFIG_LV_Z_MEM_POOL_SIZE] __aligned(8); static struct sys_heap lvgl_heap; static struct k_spinlock lvgl_heap_lock; @@ -58,10 +56,7 @@ void lvgl_print_heap_info(bool dump_chunks) k_spin_unlock(&lvgl_heap_lock, key); } -static int lvgl_heap_init(void) +void lvgl_heap_init(void) { - sys_heap_init(&lvgl_heap, &lvgl_heap_mem[0], HEAP_BYTES); - return 0; + sys_heap_init(&lvgl_heap, &lvgl_heap_mem[0], CONFIG_LV_Z_MEM_POOL_SIZE); } - -SYS_INIT(lvgl_heap_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/modules/mbedtls/configs/config-coap.h b/modules/mbedtls/configs/config-coap.h index 18ed60ef7c7..f610eb20bc6 100644 --- a/modules/mbedtls/configs/config-coap.h +++ b/modules/mbedtls/configs/config-coap.h @@ -35,6 +35,7 @@ #define MBEDTLS_PLATFORM_C #define MBEDTLS_PLATFORM_MEMORY #define MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define MBEDTLS_MEMORY_ALIGN_MULTIPLE (sizeof(void *)) #define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS #define MBEDTLS_PLATFORM_EXIT_ALT #define MBEDTLS_NO_PLATFORM_ENTROPY diff --git a/modules/mbedtls/configs/config-mini-dtls1_2.h b/modules/mbedtls/configs/config-mini-dtls1_2.h index 3a13e0d7ca7..ee0d70b5915 100644 --- a/modules/mbedtls/configs/config-mini-dtls1_2.h +++ b/modules/mbedtls/configs/config-mini-dtls1_2.h @@ -16,6 +16,7 @@ #define MBEDTLS_PLATFORM_C #define MBEDTLS_PLATFORM_MEMORY #define MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define MBEDTLS_MEMORY_ALIGN_MULTIPLE (sizeof(void *)) #define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS #define MBEDTLS_PLATFORM_EXIT_ALT #define MBEDTLS_NO_PLATFORM_ENTROPY diff --git a/modules/mbedtls/configs/config-mini-tls1_2.h b/modules/mbedtls/configs/config-mini-tls1_2.h index f725801a62e..4045fe70478 100644 --- a/modules/mbedtls/configs/config-mini-tls1_2.h +++ b/modules/mbedtls/configs/config-mini-tls1_2.h @@ -15,6 +15,7 @@ #define MBEDTLS_PLATFORM_C #define MBEDTLS_PLATFORM_MEMORY #define MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define MBEDTLS_MEMORY_ALIGN_MULTIPLE (sizeof(void *)) #define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS #define MBEDTLS_PLATFORM_EXIT_ALT #define MBEDTLS_NO_PLATFORM_ENTROPY diff --git a/modules/mbedtls/configs/config-threadnet.h b/modules/mbedtls/configs/config-threadnet.h index 6804c790fbf..c6676f03433 100644 --- a/modules/mbedtls/configs/config-threadnet.h +++ b/modules/mbedtls/configs/config-threadnet.h @@ -38,6 +38,7 @@ #define MBEDTLS_PLATFORM_C #define MBEDTLS_PLATFORM_MEMORY #define MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define MBEDTLS_MEMORY_ALIGN_MULTIPLE (sizeof(void *)) #define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS #define MBEDTLS_PLATFORM_EXIT_ALT #define MBEDTLS_NO_PLATFORM_ENTROPY diff --git a/modules/mbedtls/configs/config-tls-generic.h b/modules/mbedtls/configs/config-tls-generic.h index 7b437c23dcb..ab4a9610732 100644 --- a/modules/mbedtls/configs/config-tls-generic.h +++ b/modules/mbedtls/configs/config-tls-generic.h @@ -15,6 +15,7 @@ #define MBEDTLS_PLATFORM_C #define MBEDTLS_PLATFORM_MEMORY #define MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define MBEDTLS_MEMORY_ALIGN_MULTIPLE (sizeof(void *)) #define MBEDTLS_PLATFORM_EXIT_ALT #define MBEDTLS_NO_PLATFORM_ENTROPY @@ -462,7 +463,7 @@ #define MBEDTLS_PSA_CRYPTO_C #define MBEDTLS_USE_PSA_CRYPTO -#if defined(CONFIG_BOARD_NRF52_BSIM) || defined(CONFIG_BOARD_NATIVE_POSIX) +#if defined(CONFIG_ARCH_POSIX) #define MBEDTLS_PSA_KEY_SLOT_COUNT 64 #define MBEDTLS_PSA_CRYPTO_STORAGE_C #define MBEDTLS_PSA_ITS_FILE_C diff --git a/modules/mbedtls/zephyr_init.c b/modules/mbedtls/zephyr_init.c index eec9d991c9b..3329c3b9c8d 100644 --- a/modules/mbedtls/zephyr_init.c +++ b/modules/mbedtls/zephyr_init.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include diff --git a/modules/nanopb/CMakeLists.txt b/modules/nanopb/CMakeLists.txt index 7696ae9e118..2520595cf94 100644 --- a/modules/nanopb/CMakeLists.txt +++ b/modules/nanopb/CMakeLists.txt @@ -6,25 +6,15 @@ if(CONFIG_NANOPB) set(NANOPB_DIR ${ZEPHYR_CURRENT_MODULE_DIR}) - find_program(PROTOC protoc) - if(NOT PROTOC) - message(FATAL_ERROR "'protoc' not found, please ensure protoc is installed\ - and in path. See https://docs.zephyrproject.org/latest/samples/modules/nanopb/README.html") - endif() - - set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${NANOPB_DIR}/extra) - find_package(Nanopb REQUIRED) - zephyr_library() - - zephyr_include_directories(${NANOPB_DIR}) - zephyr_library_sources( ${NANOPB_DIR}/pb_common.c ${NANOPB_DIR}/pb_encode.c ${NANOPB_DIR}/pb_decode.c ) + zephyr_include_directories(${NANOPB_DIR}) + zephyr_compile_definitions( PB_MAX_REQUIRED_FIELDS=${CONFIG_NANOPB_MAX_REQUIRED_FIELDS}) diff --git a/modules/nanopb/nanopb.cmake b/modules/nanopb/nanopb.cmake new file mode 100644 index 00000000000..ddcdb5f61d1 --- /dev/null +++ b/modules/nanopb/nanopb.cmake @@ -0,0 +1,33 @@ +# Copyright (c) 2023, Basalte bv +# +# SPDX-License-Identifier: Apache-2.0 + +include_guard(GLOBAL) + +list(APPEND CMAKE_MODULE_PATH ${ZEPHYR_NANOPB_MODULE_DIR}/extra) + +find_program(PROTOC protoc) +if(NOT PROTOC) + message(FATAL_ERROR "'protoc' not found, please ensure protoc is installed\ +and in path. See https://docs.zephyrproject.org/latest/samples/modules/nanopb/README.html") +endif() + +find_package(Nanopb REQUIRED) + +# Usage: +# list(APPEND CMAKE_MODULE_PATH ${ZEPHYR_BASE}/modules/nanopb) +# include(nanopb) +# +# zephyr_nanopb_sources( ) +# +# Generate source and header files from provided .proto files and +# add these as sources to the specified target. +function(zephyr_nanopb_sources target) + # Turn off the default nanopb behavior + set(NANOPB_GENERATE_CPP_STANDALONE OFF) + + nanopb_generate_cpp(proto_srcs proto_hdrs RELPATH ${CMAKE_CURRENT_SOURCE_DIR} ${ARGN}) + + target_include_directories(${target} PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) + target_sources(${target} PRIVATE ${proto_srcs} ${proto_hdrs}) +endfunction() diff --git a/modules/openthread/CMakeLists.txt b/modules/openthread/CMakeLists.txt index 3796ec8f177..646b086ef1e 100644 --- a/modules/openthread/CMakeLists.txt +++ b/modules/openthread/CMakeLists.txt @@ -559,7 +559,8 @@ target_compile_definitions(ot-config INTERFACE # libraries do not include this header. So we add the defines to all # OpenThread files through the gcc flag -imacros instead. target_compile_options(ot-config INTERFACE - $ -fno-builtin + $ + $ -imacros ${AUTOCONF_H} ) @@ -612,7 +613,8 @@ endif() if(CONFIG_OPENTHREAD_SETTINGS_RAM) target_compile_options(openthread-platform-utils PRIVATE - $ -fno-builtin) + $ + $) add_dependencies(openthread-platform-utils syscall_list_h_target) list(APPEND ot_libs openthread-platform-utils-static) diff --git a/modules/openthread/Kconfig.thread b/modules/openthread/Kconfig.thread index 57a8de5d324..66e039b7300 100644 --- a/modules/openthread/Kconfig.thread +++ b/modules/openthread/Kconfig.thread @@ -68,7 +68,6 @@ config OPENTHREAD_MAX_IP_ADDR_PER_CHILD int "The maximum number of IPv6 address registrations per child" range 4 255 default 6 - depends on OPENTHREAD_FTD config OPENTHREAD_CONFIG_PLATFORM_INFO string "The platform-specific string to insert into the OpenThread version string" diff --git a/modules/openthread/platform/entropy.c b/modules/openthread/platform/entropy.c index fd5d797a469..a52f885e306 100644 --- a/modules/openthread/platform/entropy.c +++ b/modules/openthread/platform/entropy.c @@ -5,14 +5,14 @@ */ #include -#include +#include #include #include LOG_MODULE_REGISTER(net_otPlat_entropy, CONFIG_OPENTHREAD_L2_LOG_LEVEL); -#if !defined(CONFIG_ENTROPY_HAS_DRIVER) +#if !defined(CONFIG_CSPRNG_ENABLED) #error OpenThread requires an entropy source for a TRNG #endif diff --git a/modules/openthread/platform/openthread-core-zephyr-config.h b/modules/openthread/platform/openthread-core-zephyr-config.h index 8d6b5e54fd0..881585e5578 100644 --- a/modules/openthread/platform/openthread-core-zephyr-config.h +++ b/modules/openthread/platform/openthread-core-zephyr-config.h @@ -60,6 +60,18 @@ CONFIG_OPENTHREAD_TMF_ADDRESS_CACHE_ENTRIES #endif +/** + * @def CONFIG_OPENTHREAD_TMF_ADDRESS_CACHE_MAX_SNOOP_ENTRIES + * + * The maximum number of EID-to-RLOC cache entries that can be used for + * "snoop optimization" where an entry is created by inspecting a received message. + * + */ +#ifdef CONFIG_OPENTHREAD_TMF_ADDRESS_CACHE_MAX_SNOOP_ENTRIES +#define OPENTHREAD_CONFIG_TMF_ADDRESS_CACHE_MAX_SNOOP_ENTRIES \ + CONFIG_OPENTHREAD_TMF_ADDRESS_CACHE_MAX_SNOOP_ENTRIES +#endif + /** * @def OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL * diff --git a/modules/openthread/platform/radio.c b/modules/openthread/platform/radio.c index e64e47a5fa9..a09b7dd3b67 100644 --- a/modules/openthread/platform/radio.c +++ b/modules/openthread/platform/radio.c @@ -58,6 +58,11 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_OPENTHREAD_L2_LOG_LEVEL); #define CHANNEL_COUNT OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX - OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN + 1 +/* PHY header duration in us (i.e. 2 symbol periods @ 62.5k symbol rate), see + * IEEE 802.15.4, sections 12.1.3.1, 12.2.5 and 12.3.3. + */ +#define PHR_DURATION_US 32U + enum pending_events { PENDING_EVENT_FRAME_TO_SEND, /* There is a tx frame to send */ PENDING_EVENT_FRAME_RECEIVED, /* Radio has received new frame */ @@ -184,11 +189,7 @@ enum net_verdict ieee802154_handle_ack(struct net_if *iface, struct net_pkt *pkt ack_frame.mInfo.mRxInfo.mRssi = net_pkt_ieee802154_rssi_dbm(pkt); #if defined(CONFIG_NET_PKT_TIMESTAMP) - struct net_ptp_time *pkt_time = net_pkt_timestamp(pkt); - - /* OpenThread expects the timestamp to point to the end of SFD */ - ack_frame.mInfo.mRxInfo.mTimestamp = pkt_time->second * USEC_PER_SEC + - pkt_time->nanosecond / NSEC_PER_USEC; + ack_frame.mInfo.mRxInfo.mTimestamp = net_pkt_timestamp_ns(pkt) / NSEC_PER_USEC; #endif return NET_OK; @@ -228,7 +229,7 @@ void handle_radio_event(const struct device *dev, enum ieee802154_event evt, set_pending_event(PENDING_EVENT_RX_FAILED); } break; - case IEEE802154_EVENT_SLEEP: + case IEEE802154_EVENT_RX_OFF: set_pending_event(PENDING_EVENT_SLEEP); break; default: @@ -396,9 +397,7 @@ void transmit_message(struct k_work *tx_job) #if defined(CONFIG_NET_PKT_TXTIME) uint32_t tx_at = sTransmitFrame.mInfo.mTxInfo.mTxDelayBaseTime + sTransmitFrame.mInfo.mTxInfo.mTxDelay; - struct net_ptp_time timestamp = - ns_to_net_ptp_time(convert_32bit_us_wrapped_to_64bit_ns(tx_at)); - net_pkt_set_timestamp(tx_pkt, ×tamp); + net_pkt_set_timestamp_ns(tx_pkt, convert_32bit_us_wrapped_to_64bit_ns(tx_at)); #endif tx_err = radio_api->tx(radio_dev, IEEE802154_TX_MODE_TXTIME_CCA, tx_pkt, tx_payload); @@ -476,21 +475,12 @@ static void openthread_handle_received_frame(otInstance *instance, recv_frame.mInfo.mRxInfo.mAckedWithFramePending = net_pkt_ieee802154_ack_fpb(pkt); #if defined(CONFIG_NET_PKT_TIMESTAMP) - struct net_ptp_time *pkt_time = net_pkt_timestamp(pkt); - - /* OpenThread expects the timestamp to point to the end of SFD */ - recv_frame.mInfo.mRxInfo.mTimestamp = - pkt_time->second * USEC_PER_SEC + pkt_time->nanosecond / NSEC_PER_USEC; + recv_frame.mInfo.mRxInfo.mTimestamp = net_pkt_timestamp_ns(pkt) / NSEC_PER_USEC; #endif - if (net_pkt_ieee802154_arb(pkt) && net_pkt_ieee802154_fv2015(pkt)) { - recv_frame.mInfo.mRxInfo.mAckedWithSecEnhAck = - net_pkt_ieee802154_ack_seb(pkt); - recv_frame.mInfo.mRxInfo.mAckFrameCounter = - net_pkt_ieee802154_ack_fc(pkt); - recv_frame.mInfo.mRxInfo.mAckKeyId = - net_pkt_ieee802154_ack_keyid(pkt); - } + recv_frame.mInfo.mRxInfo.mAckedWithSecEnhAck = net_pkt_ieee802154_ack_seb(pkt); + recv_frame.mInfo.mRxInfo.mAckFrameCounter = net_pkt_ieee802154_ack_fc(pkt); + recv_frame.mInfo.mRxInfo.mAckKeyId = net_pkt_ieee802154_ack_keyid(pkt); if (IS_ENABLED(CONFIG_OPENTHREAD_DIAG) && otPlatDiagModeGet()) { otPlatDiagRadioReceiveDone(instance, &recv_frame, OT_ERROR_NONE); @@ -900,9 +890,26 @@ otRadioCaps otPlatRadioGetCaps(otInstance *aInstance) caps |= OT_RADIO_CAPS_RECEIVE_TIMING; } + if (radio_caps & IEEE802154_RX_ON_WHEN_IDLE) { + caps |= OT_RADIO_CAPS_RX_ON_WHEN_IDLE; + } + return caps; } +void otPlatRadioSetRxOnWhenIdle(otInstance *aInstance, bool aRxOnWhenIdle) +{ + struct ieee802154_config config = { + .rx_on_when_idle = aRxOnWhenIdle + }; + + ARG_UNUSED(aInstance); + + LOG_DBG("RxOnWhenIdle=%d", aRxOnWhenIdle ? 1 : 0); + + radio_api->configure(radio_dev, IEEE802154_CONFIG_RX_ON_WHEN_IDLE, &config); +} + bool otPlatRadioGetPromiscuous(otInstance *aInstance) { ARG_UNUSED(aInstance); @@ -1253,29 +1260,42 @@ void otPlatRadioSetMacFrameCounterIfLarger(otInstance *aInstance, uint32_t aMacF otError otPlatRadioEnableCsl(otInstance *aInstance, uint32_t aCslPeriod, otShortAddress aShortAddr, const otExtAddress *aExtAddr) { + struct ieee802154_config config = { + .ack_ie.short_addr = aShortAddr, + .ack_ie.ext_addr = aExtAddr->m8, + }; int result; - uint8_t ie_header[OT_IE_HEADER_SIZE + OT_CSL_IE_SIZE]; - struct ieee802154_config config; ARG_UNUSED(aInstance); - ie_header[0] = CSL_IE_HEADER_BYTES_LO; - ie_header[1] = CSL_IE_HEADER_BYTES_HI; - /* Leave CSL Phase empty intentionally */ - sys_put_le16(aCslPeriod, &ie_header[OT_IE_HEADER_SIZE + 2]); - config.ack_ie.data = ie_header; - config.ack_ie.short_addr = aShortAddr; - config.ack_ie.ext_addr = aExtAddr->m8; + /* Configure the CSL period first to give drivers a chance to validate + * the IE for consistency if they wish to. + */ + config.csl_period = aCslPeriod; + result = radio_api->configure(radio_dev, IEEE802154_CONFIG_CSL_PERIOD, &config); + if (result) { + return OT_ERROR_FAILED; + } + /* Configure the CSL IE. */ if (aCslPeriod > 0) { - config.ack_ie.data_len = OT_IE_HEADER_SIZE + OT_CSL_IE_SIZE; + uint8_t header_ie_buf[OT_IE_HEADER_SIZE + OT_CSL_IE_SIZE] = { + CSL_IE_HEADER_BYTES_LO, + CSL_IE_HEADER_BYTES_HI, + }; + struct ieee802154_header_ie *header_ie = + (struct ieee802154_header_ie *)header_ie_buf; + + /* Write CSL period and leave CSL phase empty as it will be + * injected on-the-fly by the driver. + */ + header_ie->content.csl.reduced.csl_period = sys_cpu_to_le16(aCslPeriod); + config.ack_ie.header_ie = header_ie; } else { - config.ack_ie.data_len = 0; + config.ack_ie.header_ie = NULL; } - result = radio_api->configure(radio_dev, IEEE802154_CONFIG_ENH_ACK_HEADER_IE, &config); - config.csl_period = aCslPeriod; - result += radio_api->configure(radio_dev, IEEE802154_CONFIG_CSL_PERIOD, &config); + result = radio_api->configure(radio_dev, IEEE802154_CONFIG_ENH_ACK_HEADER_IE, &config); return result ? OT_ERROR_FAILED : OT_ERROR_NONE; } @@ -1284,10 +1304,15 @@ void otPlatRadioUpdateCslSampleTime(otInstance *aInstance, uint32_t aCslSampleTi { ARG_UNUSED(aInstance); + /* CSL sample time points to "start of MAC" while the expected RX time + * refers to "end of SFD". + */ struct ieee802154_config config = { - .csl_rx_time = convert_32bit_us_wrapped_to_64bit_ns(aCslSampleTime)}; + .expected_rx_time = + convert_32bit_us_wrapped_to_64bit_ns(aCslSampleTime - PHR_DURATION_US), + }; - (void)radio_api->configure(radio_dev, IEEE802154_CONFIG_CSL_RX_TIME, &config); + (void)radio_api->configure(radio_dev, IEEE802154_CONFIG_EXPECTED_RX_TIME, &config); } #endif /* CONFIG_OPENTHREAD_CSL_RECEIVER */ @@ -1403,20 +1428,19 @@ otError otPlatRadioConfigureEnhAckProbing(otInstance *aInstance, otLinkMetrics a const otShortAddress aShortAddress, const otExtAddress *aExtAddress) { - int result; - uint8_t ie_header[OT_ACK_IE_MAX_SIZE]; - uint16_t ie_header_len; struct ieee802154_config config = { .ack_ie.short_addr = aShortAddress, .ack_ie.ext_addr = aExtAddress->m8, }; + uint8_t header_ie_buf[OT_ACK_IE_MAX_SIZE]; + uint16_t header_ie_len; + int result; ARG_UNUSED(aInstance); - ie_header_len = set_vendor_ie_header_lm(aLinkMetrics.mLqi, aLinkMetrics.mLinkMargin, - aLinkMetrics.mRssi, ie_header); - config.ack_ie.data = ie_header; - config.ack_ie.data_len = ie_header_len; + header_ie_len = set_vendor_ie_header_lm(aLinkMetrics.mLqi, aLinkMetrics.mLinkMargin, + aLinkMetrics.mRssi, header_ie_buf); + config.ack_ie.header_ie = (struct ieee802154_header_ie *)header_ie_buf; result = radio_api->configure(radio_dev, IEEE802154_CONFIG_ENH_ACK_HEADER_IE, &config); return result ? OT_ERROR_FAILED : OT_ERROR_NONE; diff --git a/modules/openthread/platform/settings.c b/modules/openthread/platform/settings.c index f716baa842b..ce5fefde0c8 100644 --- a/modules/openthread/platform/settings.c +++ b/modules/openthread/platform/settings.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include diff --git a/modules/percepio/CMakeLists.txt b/modules/percepio/CMakeLists.txt new file mode 100644 index 00000000000..49de379e7f9 --- /dev/null +++ b/modules/percepio/CMakeLists.txt @@ -0,0 +1,163 @@ +# Copyright (c) 2021, Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +if (CONFIG_PERCEPIO_TRACERECORDER OR CONFIG_PERCEPIO_DFM) + zephyr_library() +endif() + +if(CONFIG_PERCEPIO_TRACERECORDER) + + set(TRACERECORDER_DIR ${ZEPHYR_CURRENT_MODULE_DIR}/TraceRecorder) + + zephyr_library_sources_ifdef( + CONFIG_PERCEPIO_TRACERECORDER + ${TRACERECORDER_DIR}/kernelports/Zephyr/trcKernelPort.c + ${TRACERECORDER_DIR}/trcAssert.c + ${TRACERECORDER_DIR}/trcCounter.c + ${TRACERECORDER_DIR}/trcDiagnostics.c + ${TRACERECORDER_DIR}/trcEntryTable.c + ${TRACERECORDER_DIR}/trcError.c + ${TRACERECORDER_DIR}/trcEvent.c + ${TRACERECORDER_DIR}/trcEventBuffer.c + ${TRACERECORDER_DIR}/trcExtension.c + ${TRACERECORDER_DIR}/trcHardwarePort.c + ${TRACERECORDER_DIR}/trcHeap.c + ${TRACERECORDER_DIR}/trcInternalEventBuffer.c + ${TRACERECORDER_DIR}/trcInterval.c + ${TRACERECORDER_DIR}/trcISR.c + ${TRACERECORDER_DIR}/trcMultiCoreEventBuffer.c + ${TRACERECORDER_DIR}/trcObject.c + ${TRACERECORDER_DIR}/trcPrint.c + ${TRACERECORDER_DIR}/trcStackMonitor.c + ${TRACERECORDER_DIR}/trcStateMachine.c + ${TRACERECORDER_DIR}/trcStaticBuffer.c + ${TRACERECORDER_DIR}/trcStreamingRecorder.c + ${TRACERECORDER_DIR}/trcString.c + ${TRACERECORDER_DIR}/trcTask.c + ${TRACERECORDER_DIR}/trcTimestamp.c + ${TRACERECORDER_DIR}/trcDependency.c + ${TRACERECORDER_DIR}/trcRunnable.c + ) + + if(CONFIG_PERCEPIO_TRC_CFG_STREAM_PORT_RTT) + zephyr_library_sources( + ${TRACERECORDER_DIR}/streamports/Jlink_RTT/trcStreamPort.c + ) + + zephyr_include_directories( + ${TRACERECORDER_DIR}/kernelports/Zephyr/streamports/Jlink_RTT/config/ + ${TRACERECORDER_DIR}/streamports/Jlink_RTT/include/ + ) + endif() + + if(CONFIG_PERCEPIO_TRC_CFG_STREAM_PORT_ITM) + zephyr_library_sources( + ${TRACERECORDER_DIR}/streamports/ARM_ITM/trcStreamPort.c + ) + + zephyr_include_directories( + ${TRACERECORDER_DIR}/kernelports/Zephyr/streamports/ARM_ITM/config/ + ${TRACERECORDER_DIR}/streamports/ARM_ITM/include/ + ) + endif() + + if(CONFIG_PERCEPIO_TRC_CFG_STREAM_PORT_RINGBUFFER) + zephyr_library_sources( + ${TRACERECORDER_DIR}/streamports/RingBuffer/trcStreamPort.c + ) + + zephyr_include_directories( + ${TRACERECORDER_DIR}/kernelports/Zephyr/streamports/RingBuffer/config/ + ${TRACERECORDER_DIR}/streamports/RingBuffer/include/ + ) + endif() + + if (CONFIG_PERCEPIO_TRC_CFG_STREAM_PORT_ZEPHYR_SEMIHOST) + zephyr_library_sources( + ${TRACERECORDER_DIR}/kernelports/Zephyr/streamports/Semihost/trcStreamPort.c + ) + + zephyr_include_directories( + ${TRACERECORDER_DIR}/kernelports/Zephyr/streamports/Semihost/config + ${TRACERECORDER_DIR}/kernelports/Zephyr/streamports/Semihost/include + ) + endif() + + + zephyr_include_directories( + ${TRACERECORDER_DIR}/kernelports/Zephyr/include + ${TRACERECORDER_DIR}/kernelports/Zephyr/config + ${TRACERECORDER_DIR}/kernelports/Zephyr/config/core + ${TRACERECORDER_DIR}/include + ) + + set_property(GLOBAL APPEND PROPERTY extra_post_build_commands + COMMAND python3 ${TRACERECORDER_DIR}/kernelports/Zephyr/scripts/tz_parse_syscalls.py ${CMAKE_BINARY_DIR} ${ZEPHYR_BASE} + ) + +endif() + +if(CONFIG_PERCEPIO_DFM) + + set(DFM_DIR ${ZEPHYR_CURRENT_MODULE_DIR}/DFM) + + zephyr_library_sources_ifdef( + CONFIG_PERCEPIO_DFM + ${DFM_DIR}/dfm.c + ${DFM_DIR}/dfmAlert.c + ${DFM_DIR}/dfmCloud.c + ${DFM_DIR}/dfmEntry.c + ${DFM_DIR}/dfmSession.c + ${DFM_DIR}/dfmStorage.c + ${DFM_DIR}/kernelports/Zephyr/dfmKernelPort.c + ) + + if(CONFIG_PERCEPIO_DFM_CFG_STORAGEPORT_NONE) + zephyr_library_sources( + ${DFM_DIR}/storageports/Dummy/dfmStoragePort.c + ) + + zephyr_include_directories( + ${DFM_DIR}/storageports/Dummy/include/ + ) + endif() + + if(CONFIG_PERCEPIO_DFM_CFG_STORAGEPORT_FLASH) + zephyr_library_sources( + ${DFM_DIR}/kernelports/Zephyr/storageports/Flash/dfmStoragePort.c + ) + + zephyr_include_directories( + ${DFM_DIR}/kernelports/Zephyr/storageports/Flash/include/ + ) + endif() + + if(CONFIG_PERCEPIO_DFM_CFG_CLOUDPORT_NONE) + zephyr_library_sources( + ${DFM_DIR}/cloudports/Dummy/dfmCloudPort.c + ) + + zephyr_include_directories( + ${DFM_DIR}/cloudports/Dummy/include/ + ) + endif() + + if(CONFIG_PERCEPIO_DFM_CFG_CLOUDPORT_SERIAL) + zephyr_library_sources( + ${DFM_DIR}/kernelports/Zephyr/cloudports/Serial/dfmCloudPort.c + ) + + zephyr_include_directories( + ${DFM_DIR}/kernelports/Zephyr/cloudports/Serial/config/ + ${DFM_DIR}/kernelports/Zephyr/cloudports/Serial/include/ + ) + endif() + + zephyr_include_directories( + ${DFM_DIR}/kernelports/Zephyr/config + ${DFM_DIR}/kernelports/Zephyr/include + ${DFM_DIR}/include + ) + +endif() diff --git a/modules/percepio/Kconfig b/modules/percepio/Kconfig new file mode 100644 index 00000000000..7e2546016db --- /dev/null +++ b/modules/percepio/Kconfig @@ -0,0 +1,10 @@ +# Zephyr module config for percepio. +# The real Kconfig for the module is located in the module repository, +# this file is to ensure ZEPHYR_PERCEPIO_MODULE is defined also when the +# module is unavailable. + +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config ZEPHYR_PERCEPIO_MODULE + bool diff --git a/modules/segger/Kconfig b/modules/segger/Kconfig index 1324df8cb81..04a2a813b98 100644 --- a/modules/segger/Kconfig +++ b/modules/segger/Kconfig @@ -12,6 +12,7 @@ config HAS_SEGGER_RTT config USE_SEGGER_RTT bool "SEGGER RTT libraries." depends on HAS_SEGGER_RTT + select STM32_ENABLE_DEBUG_SLEEP_STOP if SOC_FAMILY_STM32 help Enable Segger J-Link RTT libraries for platforms that support it. Selection of this option enables use of RTT for various subsystems. diff --git a/modules/tflite-micro/CMakeLists.txt b/modules/tflite-micro/CMakeLists.txt index b1eb41ca998..ce1cd370c1a 100644 --- a/modules/tflite-micro/CMakeLists.txt +++ b/modules/tflite-micro/CMakeLists.txt @@ -13,11 +13,12 @@ if(CONFIG_TENSORFLOW_LITE_MICRO) ${TENSORFLOW_LITE_MICRO_DIR}/third_party_static/gemmlowp ${TENSORFLOW_LITE_MICRO_DIR}/third_party_static/flatbuffers/include ${TENSORFLOW_LITE_MICRO_DIR}/third_party_static/ruy + ${TENSORFLOW_LITE_MICRO_DIR}/third_party_static/kissfft ) if(CONFIG_TENSORFLOW_LITE_MICRO_CMSIS_NN_KERNELS) set(CMSIS_NN_OPTIMIZED_KERNEL_DIR cmsis_nn) - set(tflm_cmsis_nn_glue_path ${ZEPHYR_CMSIS_MODULE_DIR}) + set(tflm_cmsis_nn_glue_path ${ZEPHYR_CMSIS_NN_MODULE_DIR}) zephyr_library_include_directories(${tflm_cmsis_nn_glue_path}) zephyr_library_compile_definitions(CMSIS_NN) @@ -28,15 +29,28 @@ if(CONFIG_TENSORFLOW_LITE_MICRO) endif() zephyr_library_sources( - ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/simple_memory_allocator.cc + ${TENSORFLOW_LITE_MICRO_DIR}/python/tflite_micro/python_ops_resolver.cc + ${TENSORFLOW_LITE_MICRO_DIR}/signal/micro/kernels/fft_flexbuffers_generated_data.cc + ${TENSORFLOW_LITE_MICRO_DIR}/signal/micro/kernels/rfft.cc + ${TENSORFLOW_LITE_MICRO_DIR}/signal/micro/kernels/window.cc + ${TENSORFLOW_LITE_MICRO_DIR}/signal/micro/kernels/window_flexbuffers_generated_data.cc + ${TENSORFLOW_LITE_MICRO_DIR}/signal/src/rfft_float.cc + ${TENSORFLOW_LITE_MICRO_DIR}/signal/src/rfft_int16.cc + ${TENSORFLOW_LITE_MICRO_DIR}/signal/src/rfft_int32.cc + ${TENSORFLOW_LITE_MICRO_DIR}/signal/src/window.cc + ${TENSORFLOW_LITE_MICRO_DIR}/signal/src/kiss_fft_wrappers/kiss_fft_float.cc + ${TENSORFLOW_LITE_MICRO_DIR}/signal/src/kiss_fft_wrappers/kiss_fft_int16.cc + ${TENSORFLOW_LITE_MICRO_DIR}/signal/src/kiss_fft_wrappers/kiss_fft_int32.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/array.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/core/c/common.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/debug_log.cc - ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/micro_error_reporter.cc - ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/all_ops_resolver.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/fake_micro_context.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/memory_helpers.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/micro_allocation_info.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/test_helpers.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/test_helper_custom_ops.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/recording_micro_allocator.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/micro_time.cc - ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/recording_simple_memory_allocator.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/micro_string.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/micro_profiler.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/micro_utils.cc @@ -45,11 +59,26 @@ if(CONFIG_TENSORFLOW_LITE_MICRO) ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/mock_micro_graph.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/micro_interpreter.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/micro_allocator.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/micro_context.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/micro_log.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/micro_op_resolver.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/micro_resource_variable.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/system_setup.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/arena_allocator/non_persistent_arena_buffer_allocator.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/arena_allocator/persistent_arena_buffer_allocator.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/arena_allocator/recording_single_arena_buffer_allocator.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/arena_allocator/single_arena_buffer_allocator.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/tflite_bridge/flatbuffer_conversions_bridge.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/tflite_bridge/micro_error_reporter.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/memory_planner/linear_memory_planner.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/memory_planner/greedy_memory_planner.cc - ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/c/common.c + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/kernels/internal/common.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/kernels/internal/quantization_util.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/kernels/internal/portable_tensor_utils.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/kernels/internal/tensor_ctypes.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/kernels/internal/tensor_utils.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/kernels/internal/reference/comparisons.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/kernels/kernel_util.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/core/api/flatbuffer_conversions.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/core/api/error_reporter.cc @@ -59,12 +88,18 @@ if(CONFIG_TENSORFLOW_LITE_MICRO) ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/activations.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/activations_common.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/${CMSIS_NN_OPTIMIZED_KERNEL_DIR}/add.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/add_common.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/add_n.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/arg_min_max.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/assign_variable.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/batch_to_space_nd.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/broadcast_args.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/broadcast_to.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/call_once.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/cast.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/ceil.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/circular_buffer.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/circular_buffer_common.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/comparisons.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/concatenation.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/${CMSIS_NN_OPTIMIZED_KERNEL_DIR}/conv.cc @@ -74,9 +109,12 @@ if(CONFIG_TENSORFLOW_LITE_MICRO) ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/${CMSIS_NN_OPTIMIZED_KERNEL_DIR}/depthwise_conv.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/depthwise_conv_common.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/dequantize.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/dequantize_common.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/detection_postprocess.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/div.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/elementwise.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/elu.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/embedding_lookup.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/${ETHOSU_CO_PROCESSOR}/ethosu.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/exp.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/expand_dims.cc @@ -96,42 +134,59 @@ if(CONFIG_TENSORFLOW_LITE_MICRO) ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/l2norm.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/l2_pool_2d.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/leaky_relu.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/leaky_relu_common.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/logical.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/logical_common.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/logistic.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/logistic_common.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/lstm_eval.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/lstm_eval_common.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/log_softmax.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/maximum_minimum.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/micro_tensor_utils.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/mirror_pad.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/${CMSIS_NN_OPTIMIZED_KERNEL_DIR}/mul.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/mul_common.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/neg.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/pack.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/pad.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/${CMSIS_NN_OPTIMIZED_KERNEL_DIR}/pooling.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/pooling_common.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/prelu.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/prelu_common.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/quantize.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/quantize_common.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/read_variable.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/reduce.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/reduce_common.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/reshape.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/reshape_common.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/resize_bilinear.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/resize_nearest_neighbor.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/round.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/select.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/shape.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/slice.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/${CMSIS_NN_OPTIMIZED_KERNEL_DIR}/softmax.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/softmax_common.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/space_to_batch_nd.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/space_to_depth.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/split.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/split_v.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/squared_difference.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/squeeze.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/strided_slice.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/sub.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/sub_common.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/${CMSIS_NN_OPTIMIZED_KERNEL_DIR}/svdf.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/svdf_common.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/tanh.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/transpose.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/transpose_conv.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/${CMSIS_NN_OPTIMIZED_KERNEL_DIR}/unidirectional_sequence_lstm.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/unpack.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/var_handle.cc + ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/while.cc ${TENSORFLOW_LITE_MICRO_DIR}/tensorflow/lite/micro/kernels/zeros_like.cc ) diff --git a/modules/tflite-micro/Kconfig b/modules/tflite-micro/Kconfig index d2c92f6e126..72789bd51de 100644 --- a/modules/tflite-micro/Kconfig +++ b/modules/tflite-micro/Kconfig @@ -27,6 +27,7 @@ config TENSORFLOW_LITE_MICRO_CMSIS_NN_KERNELS select CMSIS_NN_RESHAPE select CMSIS_NN_SOFTMAX select CMSIS_NN_SVD + select CMSIS_NN_LSTM help This option adds support for CMSIS-NN optimized kernels when using TensorFlow Lite Micro. diff --git a/modules/trusted-firmware-m/Kconfig.tfm b/modules/trusted-firmware-m/Kconfig.tfm index dc2ab24b17d..a0d71328540 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm +++ b/modules/trusted-firmware-m/Kconfig.tfm @@ -321,6 +321,7 @@ endif # TFM_BL2 choice TFM_MODEL prompt "TF-M Firmware Framework model" + default TFM_SFN if TFM_PROFILE_TYPE_SMALL default TFM_IPC help The Firmware Framework M (FF-M) provides different programming models @@ -342,6 +343,7 @@ config TFM_IPC config TFM_SFN bool "SFN model" + depends on !FP_HARDABI help Use the SFN Model as the SPM backend for the PSA API. The SFN model supports the SFN Partition model, and isolation level 1. diff --git a/modules/trusted-firmware-m/interface/interface.c b/modules/trusted-firmware-m/interface/interface.c index c89a572a788..ad0ed1abdfe 100644 --- a/modules/trusted-firmware-m/interface/interface.c +++ b/modules/trusted-firmware-m/interface/interface.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include diff --git a/modules/zcbor/Kconfig b/modules/zcbor/Kconfig index 5b71f8f45ae..1b3fd15d5e3 100644 --- a/modules/zcbor/Kconfig +++ b/modules/zcbor/Kconfig @@ -6,6 +6,7 @@ config ZEPHYR_ZCBOR_MODULE config ZCBOR bool "zcbor CBOR library" + depends on ZEPHYR_ZCBOR_MODULE help zcbor CBOR encoder/decoder library diff --git a/samples/application_development/code_relocation_nocopy/CMakeLists.txt b/samples/application_development/code_relocation_nocopy/CMakeLists.txt index 0da6192fa11..426979e7c34 100644 --- a/samples/application_development/code_relocation_nocopy/CMakeLists.txt +++ b/samples/application_development/code_relocation_nocopy/CMakeLists.txt @@ -7,7 +7,6 @@ project(code_relocation_nocopy) FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) -target_sources_ifdef(CONFIG_NRFX_QSPI app PRIVATE boards/nrf5340dk_nrf5340_cpuapp/ext_mem_init.c) # Run ext_code from the external flash (XIP). No need to copy. zephyr_code_relocate(FILES src/ext_code.c LOCATION EXTFLASH_TEXT NOCOPY) diff --git a/samples/application_development/code_relocation_nocopy/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/application_development/code_relocation_nocopy/boards/nrf5340dk_nrf5340_cpuapp.conf index ec92c11f204..ce54de70c69 100644 --- a/samples/application_development/code_relocation_nocopy/boards/nrf5340dk_nrf5340_cpuapp.conf +++ b/samples/application_development/code_relocation_nocopy/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -1,2 +1,3 @@ -CONFIG_NRFX_QSPI=y -CONFIG_NRF_ENABLE_CACHE=n +CONFIG_FLASH=y +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_XIP=y diff --git a/samples/application_development/code_relocation_nocopy/boards/nrf5340dk_nrf5340_cpuapp/ext_mem_init.c b/samples/application_development/code_relocation_nocopy/boards/nrf5340dk_nrf5340_cpuapp/ext_mem_init.c deleted file mode 100644 index 36610748a59..00000000000 --- a/samples/application_development/code_relocation_nocopy/boards/nrf5340dk_nrf5340_cpuapp/ext_mem_init.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2022 Nordic Semiconductor ASA. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include - -#define QSPI_STD_CMD_WRSR 0x01 -#define QSPI_STD_CMD_RSTEN 0x66 -#define QSPI_STD_CMD_RST 0x99 - -#define QSPI_NODE DT_NODELABEL(qspi) - -static int qspi_ext_mem_init(void) -{ - - static const nrfx_qspi_config_t qspi_config = { - .prot_if = { - .readoc = NRF_QSPI_READOC_READ4IO, - .writeoc = NRF_QSPI_WRITEOC_PP4IO, - .addrmode = NRF_QSPI_ADDRMODE_24BIT, - }, - .phy_if = { - /* Frequency = PCLK192M / 2 * (sck_freq + 1) -> 32 MHz. - * 33 MHz is the maximum for WRSR, even in the High - * Performance mode. - */ - .sck_freq = 2, - .sck_delay = 0x05, - .spi_mode = NRF_QSPI_MODE_0, - }, - .skip_gpio_cfg = true, - .skip_psel_cfg = true, - }; - static const nrf_qspi_phy_conf_t qspi_phy_48mhz = { - /* After sending WRSR, use 48 MHz (96 MHz cannot be used, - * as 80 MHz is the maximum for the MX25R6435F chip). - */ - .sck_freq = 1, - .sck_delay = 0x05, - .spi_mode = NRF_QSPI_MODE_0, - }; - nrf_qspi_cinstr_conf_t cinstr_cfg = { - .opcode = QSPI_STD_CMD_RSTEN, - .length = NRF_QSPI_CINSTR_LEN_1B, - .io2_level = true, - .io3_level = true, - .wipwait = true, - }; - static const uint8_t flash_chip_cfg[] = { - /* QE (Quad Enable) bit = 1 */ - BIT(6), - 0x00, - /* L/H Switch bit = 1 -> High Performance mode */ - BIT(1), - }; - nrfx_err_t err; - int ret; - - PINCTRL_DT_DEFINE(QSPI_NODE); - - ret = pinctrl_apply_state(PINCTRL_DT_DEV_CONFIG_GET(QSPI_NODE), - PINCTRL_STATE_DEFAULT); - if (ret < 0) { - return ret; - } - - err = nrfx_qspi_init(&qspi_config, NULL, NULL); - if (err != NRFX_SUCCESS) { - return -EIO; - } - - nrf_clock_hfclk192m_div_set(NRF_CLOCK, NRF_CLOCK_HFCLK_DIV_1); - - /* Send reset enable */ - nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL); - - /* Send reset command */ - cinstr_cfg.opcode = QSPI_STD_CMD_RST; - nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL); - - /* Switch to Quad I/O and High Performance mode */ - cinstr_cfg.opcode = QSPI_STD_CMD_WRSR; - cinstr_cfg.wren = true; - cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_4B; - nrfx_qspi_cinstr_xfer(&cinstr_cfg, &flash_chip_cfg, NULL); - - nrf_qspi_ifconfig1_set(NRF_QSPI, &qspi_phy_48mhz); - - /* Enable XiP */ - nrf_qspi_xip_set(NRF_QSPI, true); - - return 0; -} - -SYS_INIT(qspi_ext_mem_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); diff --git a/samples/application_development/code_relocation_nocopy/linker_arm_nocopy.ld b/samples/application_development/code_relocation_nocopy/linker_arm_nocopy.ld index e28cfefd675..7ead7f6bae4 100644 --- a/samples/application_development/code_relocation_nocopy/linker_arm_nocopy.ld +++ b/samples/application_development/code_relocation_nocopy/linker_arm_nocopy.ld @@ -17,16 +17,14 @@ #include #include -#if CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP +#if defined(CONFIG_NORDIC_QSPI_NOR) && defined(CONFIG_SOC_NRF5340_CPUAPP) -/* - * nRF5340dk is shipping a QSPI external flash mapped at 0x1000_0000 that can - * be used for XIP - */ -MEMORY -{ - EXTFLASH (wx) : ORIGIN = 0x10000000, LENGTH = 0x800000 -} +/* On nRF5340, external flash is mapped in XIP region at 0x1000_0000. */ + +#define EXTFLASH_NODE DT_INST(0, nordic_qspi_nor) +#define EXTFLASH_ADDR 0x10000000 +#define EXTFLASH_SIZE DT_PROP_OR(EXTFLASH_NODE, size_in_bytes, \ + DT_PROP(EXTFLASH_NODE, size) / 8) #else @@ -34,14 +32,14 @@ MEMORY * Add another fake portion of FLASH to simulate a secondary or external FLASH * that we can do XIP from. */ -#define EXTFLASH_ADDR 0x5000 +#define EXTFLASH_ADDR 0x7000 #define EXTFLASH_SIZE (CONFIG_FLASH_SIZE * 1K - EXTFLASH_ADDR) +#endif + MEMORY { - EXTFLASH (wx) : ORIGIN = 0x5000, LENGTH = EXTFLASH_SIZE + EXTFLASH (rx) : ORIGIN = EXTFLASH_ADDR, LENGTH = EXTFLASH_SIZE } -#endif /* CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP */ - -#include +#include diff --git a/samples/application_development/external_lib/sample.yaml b/samples/application_development/external_lib/sample.yaml index dc06cb4c903..69cbd486e23 100644 --- a/samples/application_development/external_lib/sample.yaml +++ b/samples/application_development/external_lib/sample.yaml @@ -3,7 +3,7 @@ sample: tests: sample.app_dev.external_lib: integration_platforms: - - native_posix + - native_sim tags: external harness: console harness_config: diff --git a/samples/arch/smp/pi/src/main.c b/samples/arch/smp/pi/src/main.c index 95937e3b275..f5797c43f79 100644 --- a/samples/arch/smp/pi/src/main.c +++ b/samples/arch/smp/pi/src/main.c @@ -17,7 +17,7 @@ #define DIGITS_NUM 240 #define LENGTH ((DIGITS_NUM / 4) * 14) -#define STACK_SIZE ((LENGTH * sizeof(int) + 1024)) +#define STACK_SIZE ((LENGTH * sizeof(int) + 1280)) #ifdef CONFIG_SMP #define CORES_NUM arch_num_cpus() @@ -90,7 +90,7 @@ int main(void) for (i = 0; i < THREADS_NUM; i++) { k_thread_create(&tthread[i], tstack[i], STACK_SIZE, - (k_thread_entry_t)test_thread, + test_thread, (void *)&th_counter, (void *)th_buffer[i], NULL, K_PRIO_COOP(10), 0, K_NO_WAIT); } diff --git a/samples/arch/smp/pktqueue/src/main.c b/samples/arch/smp/pktqueue/src/main.c index 11d3ea36c73..07363a8d234 100644 --- a/samples/arch/smp/pktqueue/src/main.c +++ b/samples/arch/smp/pktqueue/src/main.c @@ -101,7 +101,6 @@ void test_thread(void *arg1, void *arg2, void *arg3) /* Thread that processes one pair of sender/receiver queue */ void queue_thread(void *arg1, void *arg2, void *arg3) { - ARG_UNUSED(arg1); ARG_UNUSED(arg2); ARG_UNUSED(arg3); @@ -117,7 +116,7 @@ void queue_thread(void *arg1, void *arg2, void *arg3) for (int i = 0; i < THREADS_NUM; i++) k_thread_create(&tthread[i+THREADS_NUM*queue_num], tstack[i+THREADS_NUM*queue_num], STACK_SIZE, - (k_thread_entry_t)test_thread, + test_thread, (void *)&sender[queue_num], (void *)&receiver[queue_num], (void *)&queue_num, K_PRIO_PREEMPT(10), 0, K_NO_WAIT); @@ -156,7 +155,7 @@ int main(void) for (int i = 0; i < QUEUE_NUM; i++) k_thread_create(&qthread[i], qstack[i], STACK_SIZE, - (k_thread_entry_t)queue_thread, + queue_thread, (void *)&sender[i], (void *)&receiver[i], (void *)&i, K_PRIO_PREEMPT(11), 0, K_NO_WAIT); diff --git a/samples/arch/smp/pktqueue/src/main.h b/samples/arch/smp/pktqueue/src/main.h index 0ecac944278..20020563ca1 100644 --- a/samples/arch/smp/pktqueue/src/main.h +++ b/samples/arch/smp/pktqueue/src/main.h @@ -7,7 +7,7 @@ #include #include #include -#include +#include /* Amount of parallel processed sender/receiver queues of packet headers */ diff --git a/samples/arch/smp/pktqueue/src/pktqueue.h b/samples/arch/smp/pktqueue/src/pktqueue.h index e46d7ed194f..d4e683d659a 100644 --- a/samples/arch/smp/pktqueue/src/pktqueue.h +++ b/samples/arch/smp/pktqueue/src/pktqueue.h @@ -7,7 +7,7 @@ #include #include #include -#include +#include struct phdr_desc { struct phdr_desc *next; /* Next pkt descriptor in respective queue */ diff --git a/samples/basic/blinky/README.rst b/samples/basic/blinky/README.rst index 6c30bef1af7..893d00b5103 100644 --- a/samples/basic/blinky/README.rst +++ b/samples/basic/blinky/README.rst @@ -1,7 +1,8 @@ -.. _blinky-sample: +.. zephyr:code-sample:: blinky + :name: Blinky + :relevant-api: gpio_interface -Blinky -###### + Blink an LED forever using the GPIO API. Overview ******** @@ -15,7 +16,7 @@ The source code shows how to: #. Configure the GPIO pin as an output #. Toggle the pin forever -See :ref:`pwm-blinky-sample` for a similar sample that uses the PWM API instead. +See :zephyr:code-sample:`pwm-blinky` for a similar sample that uses the PWM API instead. .. _blinky-sample-requirements: diff --git a/samples/basic/blinky_pwm/README.rst b/samples/basic/blinky_pwm/README.rst index ec59a6b3a97..f31c65982fb 100644 --- a/samples/basic/blinky_pwm/README.rst +++ b/samples/basic/blinky_pwm/README.rst @@ -1,14 +1,14 @@ -.. _blink-led-sample: -.. _pwm-blinky-sample: +.. zephyr:code-sample:: pwm-blinky + :name: PWM Blinky + :relevant-api: pwm_interface -PWM Blinky -########## + Blink an LED using the PWM API. Overview ******** -This application blinks a LED using the :ref:`PWM API `. See -:ref:`blinky-sample` for a GPIO-based sample. +This application blinks an LED using the :ref:`PWM API `. See +:zephyr:code-sample:`blinky` for a GPIO-based sample. The LED starts blinking at a 1 Hz frequency. The frequency doubles every 4 seconds until it reaches 128 Hz. The frequency will then be halved every 4 diff --git a/samples/basic/blinky_pwm/boards/esp32c3_luatos_core.overlay b/samples/basic/blinky_pwm/boards/esp32c3_luatos_core.overlay new file mode 100644 index 00000000000..a438cc5246b --- /dev/null +++ b/samples/basic/blinky_pwm/boards/esp32c3_luatos_core.overlay @@ -0,0 +1,45 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2021 Andrei-Edward Popa + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + */ + +#include +#include + +/ { + aliases { + pwm-0 = &ledc0; + pwm-led0 = &pwm_led_blue; + }; + + pwmleds { + compatible = "pwm-leds"; + pwm_led_blue: pwm_led_gpio0_2 { + label = "PWM LED0"; + pwms = <&ledc0 0 1000 PWM_POLARITY_NORMAL>; + }; + }; +}; + +&pinctrl { + ledc0_default: ledc0_default { + group1 { + pinmux = ; + output-enable; + }; + }; +}; + +&ledc0 { + pinctrl-0 = <&ledc0_default>; + pinctrl-names = "default"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + channel0@0 { + reg = <0x0>; + timer = <0>; + }; +}; diff --git a/samples/basic/blinky_pwm/boards/esp32c3_luatos_core_usb.overlay b/samples/basic/blinky_pwm/boards/esp32c3_luatos_core_usb.overlay new file mode 100644 index 00000000000..a438cc5246b --- /dev/null +++ b/samples/basic/blinky_pwm/boards/esp32c3_luatos_core_usb.overlay @@ -0,0 +1,45 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2021 Andrei-Edward Popa + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + */ + +#include +#include + +/ { + aliases { + pwm-0 = &ledc0; + pwm-led0 = &pwm_led_blue; + }; + + pwmleds { + compatible = "pwm-leds"; + pwm_led_blue: pwm_led_gpio0_2 { + label = "PWM LED0"; + pwms = <&ledc0 0 1000 PWM_POLARITY_NORMAL>; + }; + }; +}; + +&pinctrl { + ledc0_default: ledc0_default { + group1 { + pinmux = ; + output-enable; + }; + }; +}; + +&ledc0 { + pinctrl-0 = <&ledc0_default>; + pinctrl-names = "default"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + channel0@0 { + reg = <0x0>; + timer = <0>; + }; +}; diff --git a/samples/basic/blinky_pwm/boards/esp32s3_luatos_core.overlay b/samples/basic/blinky_pwm/boards/esp32s3_luatos_core.overlay new file mode 100644 index 00000000000..61152f82f94 --- /dev/null +++ b/samples/basic/blinky_pwm/boards/esp32s3_luatos_core.overlay @@ -0,0 +1,44 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 YuLong Yao + */ + +#include +#include + +/ { + aliases { + pwm-0 = &ledc0; + pwm-led0 = &pwm_led_blue; + }; + + pwmleds { + compatible = "pwm-leds"; + pwm_led_blue: pwm_led_gpio0_10 { + label = "PWM LED0"; + pwms = <&ledc0 0 1000 PWM_POLARITY_NORMAL>; + }; + }; +}; + +&pinctrl { + ledc0_default: ledc0_default { + group1 { + pinmux = ; + output-enable; + }; + }; +}; + +&ledc0 { + pinctrl-0 = <&ledc0_default>; + pinctrl-names = "default"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + channel0@0 { + reg = <0x0>; + timer = <0>; + }; +}; diff --git a/samples/basic/blinky_pwm/boards/esp32s3_luatos_core_usb.overlay b/samples/basic/blinky_pwm/boards/esp32s3_luatos_core_usb.overlay new file mode 100644 index 00000000000..61152f82f94 --- /dev/null +++ b/samples/basic/blinky_pwm/boards/esp32s3_luatos_core_usb.overlay @@ -0,0 +1,44 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 YuLong Yao + */ + +#include +#include + +/ { + aliases { + pwm-0 = &ledc0; + pwm-led0 = &pwm_led_blue; + }; + + pwmleds { + compatible = "pwm-leds"; + pwm_led_blue: pwm_led_gpio0_10 { + label = "PWM LED0"; + pwms = <&ledc0 0 1000 PWM_POLARITY_NORMAL>; + }; + }; +}; + +&pinctrl { + ledc0_default: ledc0_default { + group1 { + pinmux = ; + output-enable; + }; + }; +}; + +&ledc0 { + pinctrl-0 = <&ledc0_default>; + pinctrl-names = "default"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + channel0@0 { + reg = <0x0>; + timer = <0>; + }; +}; diff --git a/samples/basic/button/README.rst b/samples/basic/button/README.rst index 5b17ee4eadb..1989ff74c5d 100644 --- a/samples/basic/button/README.rst +++ b/samples/basic/button/README.rst @@ -1,7 +1,8 @@ -.. _button-sample: +.. zephyr:code-sample:: button + :name: Button + :relevant-api: gpio_interface -Button -###### + Handle GPIO inputs with interrupts. Overview ******** @@ -27,7 +28,7 @@ You may see additional build errors if the ``sw0`` alias exists, but is not properly defined. The sample additionally supports an optional ``led0`` devicetree alias. This is -the same alias used by the :ref:`blinky-sample`. If this is provided, the LED +the same alias used by the :zephyr:code-sample:`blinky` sample. If this is provided, the LED will be turned on when the button is pressed, and turned off off when it is released. diff --git a/samples/basic/custom_dts_binding/README.rst b/samples/basic/custom_dts_binding/README.rst index d3edd890264..1a54cb5ef67 100644 --- a/samples/basic/custom_dts_binding/README.rst +++ b/samples/basic/custom_dts_binding/README.rst @@ -1,7 +1,8 @@ -.. _gpio-custom-dts-binding-sample: +.. zephyr:code-sample:: gpio-custom-dts-binding + :name: GPIO with custom Devicetree binding + :relevant-api: gpio_interface devicetree-generic-id devicetree-generic-exist -GPIO with custom devicetree binding -################################### + Use custom Devicetree binding to control a GPIO. Overview ******** diff --git a/samples/basic/fade_led/README.rst b/samples/basic/fade_led/README.rst index d86f0f2edfb..4e855548704 100644 --- a/samples/basic/fade_led/README.rst +++ b/samples/basic/fade_led/README.rst @@ -1,7 +1,8 @@ -.. _fade-led-sample: +.. zephyr:code-sample:: fade-led + :name: Fade LED + :relevant-api: pwm_interface -Fade LED -######## + Fade an LED using the PWM API. Overview ******** @@ -18,7 +19,7 @@ Requirements and Wiring *********************** This sample has the same requirements and wiring considerations as the -:ref:`pwm-blinky-sample`. +:zephyr:code-sample:`pwm-blinky` sample. Building and Running ******************** diff --git a/samples/basic/hash_map/README.rst b/samples/basic/hash_map/README.rst index 5126e826d23..0c5d91a3dae 100644 --- a/samples/basic/hash_map/README.rst +++ b/samples/basic/hash_map/README.rst @@ -1,12 +1,13 @@ -.. _system_hashmap: +.. zephyr:code-sample:: system_hashmap + :name: System hashmap + :relevant-api: hashmap_apis -System Hashmap -############## + Insert, replace, and remove entries in a hashmap. Overview ******** -This is a simple example that repeatedly +This is a simple example that repeatedly: * inserts up to ``CONFIG_TEST_LIB_HASH_MAP_MAX_ENTRIES`` * replaces up to the same number that were previously inserted @@ -15,16 +16,16 @@ This is a simple example that repeatedly Building ******** -This application can be built on native_posix as follows: +This application can be built on :ref:`native_sim ` as follows: .. zephyr-app-commands:: :zephyr-app: samples/basic/hash_map :host-os: unix - :board: native_posix + :board: native_sim :goals: build :compact: -To build for another board, change "native_posix" above to that board's name. +To build for another board, change "native_sim" above to that board's name. Additionally, it is possible to use one of the other Hashmap implementations by specifying diff --git a/samples/basic/hash_map/src/main.c b/samples/basic/hash_map/src/main.c index 803a43b9c75..3c919283963 100644 --- a/samples/basic/hash_map/src/main.c +++ b/samples/basic/hash_map/src/main.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include LOG_MODULE_REGISTER(hashmap_sample); diff --git a/samples/basic/minimal/README.rst b/samples/basic/minimal/README.rst index 1e4a2d7f70e..6021d80a1d7 100644 --- a/samples/basic/minimal/README.rst +++ b/samples/basic/minimal/README.rst @@ -1,7 +1,7 @@ -.. _minimal_sample: +.. zephyr:code-sample:: minimal + :name: Minimal footprint -Minimal footprint -################# + Measure Zephyr's minimal ROM footprint in different configurations. Overview ******** diff --git a/samples/basic/rgb_led/README.rst b/samples/basic/rgb_led/README.rst index 3f6a6b67862..11cc5d6e646 100644 --- a/samples/basic/rgb_led/README.rst +++ b/samples/basic/rgb_led/README.rst @@ -1,12 +1,13 @@ -.. _rgb-led-sample: +.. zephyr:code-sample:: rgb-led + :name: PWM RGB LED + :relevant-api: pwm_interface -PWM: RGB LED -############ + Drive an RGB LED using the PWM API. Overview ******** -This is a sample app which drives an RGB LED using PWM. +This is a sample app which drives an RGB LED using the :ref:`PWM API `. There are three single-color component LEDs in an RGB LED. Each component LED is driven by a PWM port where the pulse width is changed from zero to the period diff --git a/samples/basic/servo_motor/README.rst b/samples/basic/servo_motor/README.rst index dcfc7afabb8..e4f2e494196 100644 --- a/samples/basic/servo_motor/README.rst +++ b/samples/basic/servo_motor/README.rst @@ -1,12 +1,13 @@ -.. _servo-motor-sample: +.. zephyr:code-sample:: servo-motor + :name: Servomotor + :relevant-api: pwm_interface -Servomotor -########## + Drive a servomotor using the PWM API. Overview ******** -This is a sample app which drives a servomotor using PWM. +This is a sample app which drives a servomotor using the :ref:`PWM API `. The sample rotates a servomotor back and forth in the 180 degree range with a PWM control signal. diff --git a/samples/basic/sys_heap/README.rst b/samples/basic/sys_heap/README.rst index 335084a901f..74eb2b9e332 100644 --- a/samples/basic/sys_heap/README.rst +++ b/samples/basic/sys_heap/README.rst @@ -1,7 +1,7 @@ -.. _system_heap: +.. zephyr:code-sample:: sys-heap + :name: System heap -System heap -########### + Print system heap usage to the console. Overview ******** @@ -10,18 +10,18 @@ A simple sample that can be used with any :ref:`supported board ` and prints system heap usage to the console. Building -******************** +******** -This application can be built on native_posix as follows: +This application can be built on :ref:`native_sim ` as follows: .. zephyr-app-commands:: :zephyr-app: samples/basic/sys_heap :host-os: unix - :board: native_posix + :board: native_sim :goals: build :compact: -To build for another board, change "native_posix" above to that board's name. +To build for another board, change "native_sim" above to that board's name. Running ******* diff --git a/samples/basic/sys_heap/sample.yaml b/samples/basic/sys_heap/sample.yaml index 9e9f45c90ca..d6179247991 100644 --- a/samples/basic/sys_heap/sample.yaml +++ b/samples/basic/sys_heap/sample.yaml @@ -3,7 +3,7 @@ sample: name: Basic system heap sample common: integration_platforms: - - native_posix + - native_sim harness: console harness_config: type: multi_line diff --git a/samples/basic/threads/README.rst b/samples/basic/threads/README.rst index fd47afad2f0..1ade8e9d360 100644 --- a/samples/basic/threads/README.rst +++ b/samples/basic/threads/README.rst @@ -1,7 +1,8 @@ -.. _96b_carbon_multi_thread_blinky: +.. zephyr:code-sample:: multi-thread-blinky + :name: Basic thread manipulation + :relevant-api: gpio_interface thread_apis -Basic Thread Example -#################### + Spawn multiple threads that blink LEDs and print information to the console. Overview ******** diff --git a/samples/bluetooth/bluetooth.rst b/samples/bluetooth/bluetooth.rst index e9c44451d36..0b59b9626b4 100644 --- a/samples/bluetooth/bluetooth.rst +++ b/samples/bluetooth/bluetooth.rst @@ -6,13 +6,13 @@ Bluetooth samples To build any of the Bluetooth samples, follow the same steps as building any other Zephyr application. Refer to :ref:`bluetooth-dev` for more information. -Many Bluetooth samples can be run on QEMU or Native POSIX with support for +Many Bluetooth samples can be run on QEMU or :ref:`native_sim ` with support for external Bluetooth Controllers. Refer to the :ref:`bluetooth-hw-setup` section for further details. Several of the bluetooth samples will build a Zephyr-based Controller that can then be used with any external Host (including Zephyr running natively or with -QEMU or Native POSIX), those are named accordingly with an "HCI" prefix in the +QEMU or ``native_sim``), those are named accordingly with an "HCI" prefix in the documentation and are prefixed with :literal:`hci_` in their folder names. .. note:: @@ -20,7 +20,7 @@ documentation and are prefixed with :literal:`hci_` in their folder names. ``-DBOARD=nrf5340dk_nrf5340_cpuapp`` or ``-DBOARD=nrf5340dk_nrf5340_cpuapp_ns``) you must also build and program the corresponding sample for the nRF5340 network core - :ref:`bluetooth-hci-rpmsg-sample` which implements the Bluetooth + :ref:`bluetooth-hci-ipc-sample` which implements the Bluetooth Low Energy controller. .. note:: diff --git a/samples/bluetooth/broadcast_audio_sink/Kconfig b/samples/bluetooth/broadcast_audio_sink/Kconfig index 7a61a7b64fc..b70a42e2d99 100644 --- a/samples/bluetooth/broadcast_audio_sink/Kconfig +++ b/samples/bluetooth/broadcast_audio_sink/Kconfig @@ -28,4 +28,19 @@ config SCAN_DELAY Time to advertise connectable for a Broadcast Assistant to connect before starting scanning for Broadcast Sources. +config TARGET_BROADCAST_NAME + string "Target Broadcast Device Name" + default "" + help + Name of target broadcast device. If not empty string, sink device + will only listen to the specified broadcast source. Not case sensitive. + +config ENABLE_LC3 + bool "Enable the LC3 codec" + # By default let's enable it in the platforms we know are capable of supporting it + default y + depends on (ARCH_POSIX || SOC_NRF5340_CPUAPP) + select LIBLC3 + select FPU + source "Kconfig.zephyr" diff --git a/samples/bluetooth/broadcast_audio_sink/Kconfig.sysbuild b/samples/bluetooth/broadcast_audio_sink/Kconfig.sysbuild new file mode 100644 index 00000000000..f434010f81d --- /dev/null +++ b/samples/bluetooth/broadcast_audio_sink/Kconfig.sysbuild @@ -0,0 +1,15 @@ +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config NET_CORE_BOARD + string + default "nrf5340dk_nrf5340_cpunet" if $(BOARD) = "nrf5340dk_nrf5340_cpuapp" + default "nrf5340_audio_dk_nrf5340_cpunet" if $(BOARD) = "nrf5340_audio_dk_nrf5340_cpuapp" + default "nrf5340bsim_nrf5340_cpunet" if $(BOARD) = "nrf5340bsim_nrf5340_cpuapp" + +config NET_CORE_IMAGE_HCI_IPC + bool "HCI IPC image on network core" + default y + depends on NET_CORE_BOARD != "" diff --git a/samples/bluetooth/broadcast_audio_sink/README.rst b/samples/bluetooth/broadcast_audio_sink/README.rst index cb0aabc970d..aca5d18bb94 100644 --- a/samples/bluetooth/broadcast_audio_sink/README.rst +++ b/samples/bluetooth/broadcast_audio_sink/README.rst @@ -1,7 +1,8 @@ -.. _bluetooth_broadcast_audio_sink: +.. zephyr:code-sample:: bluetooth_broadcast_audio_sink + :name: Bluetooth: Broadcast Audio Sink + :relevant-api: bluetooth -Bluetooth: Broadcast Audio Sink -############################### + Bluetooth: Broadcast Audio Sink Overview ******** @@ -10,6 +11,15 @@ Application demonstrating the LE Audio broadcast sink functionality. Starts by scanning for LE Audio broadcast sources and then synchronizes to the first found and listens to it until the source is (potentially) stopped. +This sample can be found under +:zephyr_file:`samples/bluetooth/broadcast_audio_sink` in the Zephyr tree. + +Check the :ref:`bluetooth samples section ` for general information. + +Use `CONFIG_TARGET_BROADCAST_NAME` Kconfig to specify the name (CONFIG_BT_DEVICE_NAME) +of a broadcast source to listen to. With default value (empty string), sink +device will listen to all available broadcast sources. + Requirements ************ @@ -18,9 +28,53 @@ Requirements Building and Running ******************** -This sample can be found under -:zephyr_file:`samples/bluetooth/broadcast_audio_sink` in the Zephyr tree. -Use `-DEXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf` to enable required ISO -feature support in Zephyr Bluetooth Controller on supported boards. -See :ref:`bluetooth samples section ` for details. +When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, +use `-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf` to enable the required ISO +feature support. + +Building for an nrf5340dk +------------------------- + +You can build both the application core image and an appropriate controller image for the network +core with: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/broadcast_audio_sink/ + :board: nrf5340dk_nrf5340_cpuapp + :goals: build + :west-args: --sysbuild + +If you prefer to only build the application core image, you can do so by doing instead: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/broadcast_audio_sink/ + :board: nrf5340dk_nrf5340_cpuapp + :goals: build + +In that case you can pair this application core image with the +:ref:`hci_ipc sample ` +:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. + +Building for a simulated nrf5340bsim +------------------------------------ + +Similarly to how you would for real HW, you can do: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/broadcast_audio_sink/ + :board: nrf5340bsim_nrf5340_cpuapp + :goals: build + :west-args: --sysbuild + +Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. +For more information, check :ref:`this board documentation `. + +Building for a simulated nrf52_bsim +----------------------------------- + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/broadcast_audio_sink/ + :board: nrf52_bsim + :goals: build + :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf diff --git a/samples/bluetooth/broadcast_audio_sink/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/broadcast_audio_sink/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000..8ab7a163fb6 --- /dev/null +++ b/samples/bluetooth/broadcast_audio_sink/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -0,0 +1,3 @@ +# The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence +# inctease stack size for that thread. +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 diff --git a/samples/bluetooth/broadcast_audio_sink/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/broadcast_audio_sink/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000..8ab7a163fb6 --- /dev/null +++ b/samples/bluetooth/broadcast_audio_sink/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,3 @@ +# The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence +# inctease stack size for that thread. +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 diff --git a/samples/bluetooth/broadcast_audio_sink/overlay-bt_ll_sw_split.conf b/samples/bluetooth/broadcast_audio_sink/overlay-bt_ll_sw_split.conf index bc0ba2c6cdd..e336dae38e1 100644 --- a/samples/bluetooth/broadcast_audio_sink/overlay-bt_ll_sw_split.conf +++ b/samples/bluetooth/broadcast_audio_sink/overlay-bt_ll_sw_split.conf @@ -10,3 +10,7 @@ CONFIG_BT_CTLR_SYNC_ISO_PDU_LEN_MAX=155 # Supports the highest advertising data that is set in a single HCI command in # Zephyr Bluetooth Controller CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=191 + +# Number of supported streams +CONFIG_BT_CTLR_SYNC_ISO_STREAM_MAX=2 +CONFIG_BT_CTLR_ISOAL_SINKS=2 diff --git a/samples/bluetooth/broadcast_audio_sink/prj.conf b/samples/bluetooth/broadcast_audio_sink/prj.conf index 11e0971638a..c8adced28ce 100644 --- a/samples/bluetooth/broadcast_audio_sink/prj.conf +++ b/samples/bluetooth/broadcast_audio_sink/prj.conf @@ -10,5 +10,9 @@ CONFIG_BT_ISO_MAX_CHAN=2 CONFIG_BT_BAP_BROADCAST_SNK_SUBGROUP_COUNT=2 CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT=2 CONFIG_BT_BAP_SCAN_DELEGATOR_MAX_SUBGROUPS=2 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 CONFIG_BT_DEVICE_NAME="Broadcast Audio Sink" + +CONFIG_BT_TINYCRYPT_ECC=y diff --git a/samples/bluetooth/broadcast_audio_sink/sample.yaml b/samples/bluetooth/broadcast_audio_sink/sample.yaml index a423dbcde18..e81b86de3e0 100644 --- a/samples/bluetooth/broadcast_audio_sink/sample.yaml +++ b/samples/bluetooth/broadcast_audio_sink/sample.yaml @@ -8,10 +8,12 @@ tests: - qemu_cortex_m3 - qemu_x86 - nrf5340dk_nrf5340_cpuapp + - nrf5340bsim_nrf5340_cpuapp integration_platforms: - qemu_x86 - nrf5340dk_nrf5340_cpuapp tags: bluetooth + sysbuild: true sample.bluetooth.broadcast_audio_sink.bt_ll_sw_split: harness: bluetooth platform_allow: diff --git a/samples/bluetooth/broadcast_audio_sink/src/main.c b/samples/bluetooth/broadcast_audio_sink/src/main.c index fad1ba7c11b..6b519b715f6 100644 --- a/samples/bluetooth/broadcast_audio_sink/src/main.c +++ b/samples/bluetooth/broadcast_audio_sink/src/main.c @@ -4,6 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include + #include #include #include @@ -25,6 +28,7 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_SCAN_SELF) || IS_ENABLED(CONFIG_SCAN_OFFLOAD), #define INVALID_BROADCAST_ID (BT_AUDIO_BROADCAST_ID_MAX + 1) #define SYNC_RETRY_COUNT 6 /* similar to retries for connections */ #define PA_SYNC_SKIP 5 +#define NAME_LEN sizeof(CONFIG_TARGET_BROADCAST_NAME) + 1 static K_SEM_DEFINE(sem_connected, 0U, 1U); static K_SEM_DEFINE(sem_disconnected, 0U, 1U); @@ -40,13 +44,25 @@ static K_SEM_DEFINE(sem_bis_sync_requested, 0U, 1U); static K_SEM_DEFINE(sem_bis_synced, 0U, CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT); /* Sample assumes that we only have a single Scan Delegator receive state */ -static const struct bt_bap_scan_delegator_recv_state *sink_recv_state; +static const struct bt_bap_scan_delegator_recv_state *req_recv_state; static struct bt_bap_broadcast_sink *broadcast_sink; static struct bt_le_scan_recv_info broadcaster_info; static bt_addr_le_t broadcaster_addr; static struct bt_le_per_adv_sync *pa_sync; static uint32_t broadcaster_broadcast_id; -static struct bt_bap_stream streams[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT]; +static struct broadcast_sink_stream { + struct bt_bap_stream stream; + size_t recv_cnt; + size_t loss_cnt; + size_t error_cnt; + size_t valid_cnt; +#if defined(CONFIG_LIBLC3) + struct net_buf *in_buf; + struct k_work_delayable lc3_decode_work; +/* Internal lock for protecting net_buf from multiple access */ + struct k_mutex lc3_decoder_mutex; +#endif /* defined(CONFIG_LIBLC3) */ +} streams[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT]; static struct bt_bap_stream *streams_p[ARRAY_SIZE(streams)]; static struct bt_conn *broadcast_assistant_conn; static struct bt_le_ext_adv *ext_adv; @@ -65,10 +81,118 @@ static uint32_t requested_bis_sync; static uint32_t bis_index_bitfield; static uint8_t sink_broadcast_code[BT_AUDIO_BROADCAST_CODE_SIZE]; +uint64_t total_rx_iso_packet_count; /* This value is exposed to test code */ + +#if defined(CONFIG_LIBLC3) + +#include "lc3.h" + +#define MAX_SAMPLE_RATE 16000 +#define MAX_FRAME_DURATION_US 10000 +#define MAX_NUM_SAMPLES ((MAX_FRAME_DURATION_US * MAX_SAMPLE_RATE) / USEC_PER_SEC) + +static int16_t audio_buf[MAX_NUM_SAMPLES]; +static lc3_decoder_t lc3_decoder; +static lc3_decoder_mem_16k_t lc3_decoder_mem; +static int frames_per_sdu; + +static int lc3_enable(const struct bt_audio_codec_cfg *codec_cfg) +{ + int ret; + int freq_hz; + int frame_duration_us; + + printk("Enable: stream with codec %p\n", codec_cfg); + + ret = bt_audio_codec_cfg_get_freq(codec_cfg); + if (ret > 0) { + freq_hz = bt_audio_codec_cfg_freq_to_freq_hz(ret); + } else { + printk("Error: Codec frequency not set, cannot start codec."); + return -1; + } + + ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg); + if (ret > 0) { + frame_duration_us = bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret); + } else { + printk("Error: Frame duration not set, cannot start codec."); + return ret; + } + + frames_per_sdu = bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true); + + lc3_decoder = lc3_setup_decoder(frame_duration_us, freq_hz, 0, /* No resampling */ + &lc3_decoder_mem); + + if (lc3_decoder == NULL) { + printk("ERROR: Failed to setup LC3 decoder - wrong parameters?\n"); + return -1; + } + + return 0; +} + +static void lc3_decode_handler(struct k_work *work) +{ + int err = 0; + int offset = 0; + uint8_t *buf_data; + struct net_buf *ptr_net_buf; + int octets_per_frame; + struct broadcast_sink_stream *sink_stream = CONTAINER_OF( + k_work_delayable_from_work(work), struct broadcast_sink_stream, lc3_decode_work); + + k_mutex_lock(&sink_stream->lc3_decoder_mutex, K_FOREVER); + + if (sink_stream->in_buf == NULL) { + printk("buf data is NULL, nothing to be docoded\n"); + k_mutex_unlock(&sink_stream->lc3_decoder_mutex); + return; + } + + ptr_net_buf = net_buf_ref(sink_stream->in_buf); + net_buf_unref(sink_stream->in_buf); + sink_stream->in_buf = NULL; + k_mutex_unlock(&sink_stream->lc3_decoder_mutex); + + buf_data = ptr_net_buf->data; + octets_per_frame = ptr_net_buf->len / frames_per_sdu; + + for (int i = 0; i < frames_per_sdu; i++) { + err = lc3_decode(lc3_decoder, buf_data + offset, octets_per_frame, + LC3_PCM_FORMAT_S16, audio_buf, 1); + + if (err == 1) { + printk(" decoder performed PLC\n"); + } else if (err < 0) { + printk(" decoder failed - wrong parameters?\n"); + } + + offset += octets_per_frame; + } + + net_buf_unref(ptr_net_buf); +} + +#endif /* defined(CONFIG_LIBLC3) */ + static void stream_started_cb(struct bt_bap_stream *stream) { + struct broadcast_sink_stream *sink_stream = + CONTAINER_OF(stream, struct broadcast_sink_stream, stream); + printk("Stream %p started\n", stream); + total_rx_iso_packet_count = 0U; + sink_stream->recv_cnt = 0U; + sink_stream->loss_cnt = 0U; + sink_stream->valid_cnt = 0U; + sink_stream->error_cnt = 0U; + +#if defined(CONFIG_LIBLC3) + k_work_init_delayable(&sink_stream->lc3_decode_work, lc3_decode_handler); +#endif /* defined(CONFIG_LIBLC3) */ k_sem_give(&sem_bis_synced); } @@ -84,22 +208,48 @@ static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) } } -static void stream_recv_cb(struct bt_bap_stream *stream, - const struct bt_iso_recv_info *info, +static void stream_recv_cb(struct bt_bap_stream *stream, const struct bt_iso_recv_info *info, struct net_buf *buf) { - static uint32_t recv_cnt; + struct broadcast_sink_stream *sink_stream = + CONTAINER_OF(stream, struct broadcast_sink_stream, stream); + + if (info->flags & BT_ISO_FLAGS_ERROR) { + sink_stream->error_cnt++; + } + + if (info->flags & BT_ISO_FLAGS_LOST) { + sink_stream->loss_cnt++; + } - recv_cnt++; - if ((recv_cnt % 1000U) == 0U) { - printk("Received %u total ISO packets\n", recv_cnt); + if (info->flags & BT_ISO_FLAGS_VALID) { + sink_stream->valid_cnt++; +#if defined(CONFIG_LIBLC3) + k_mutex_lock(&sink_stream->lc3_decoder_mutex, K_FOREVER); + if (sink_stream->in_buf != NULL) { + net_buf_unref(sink_stream->in_buf); + sink_stream->in_buf = NULL; + } + + sink_stream->in_buf = net_buf_ref(buf); + k_mutex_unlock(&sink_stream->lc3_decoder_mutex); + k_work_schedule(&sink_stream->lc3_decode_work, K_NO_WAIT); +#endif /* defined(CONFIG_LIBLC3) */ + } + + total_rx_iso_packet_count++; + sink_stream->recv_cnt++; + if ((sink_stream->recv_cnt % 1000U) == 0U) { + printk("Stream %p: received %u total ISO packets: Valid %u | Error %u | Loss %u\n", + &sink_stream->stream, sink_stream->recv_cnt, sink_stream->valid_cnt, + sink_stream->error_cnt, sink_stream->loss_cnt); } } static struct bt_bap_stream_ops stream_ops = { .started = stream_started_cb, .stopped = stream_stopped_cb, - .recv = stream_recv_cb + .recv = stream_recv_cb, }; static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap_base *base) @@ -114,11 +264,32 @@ static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap base->subgroup_count, sink); for (size_t i = 0U; i < base->subgroup_count; i++) { - for (size_t j = 0U; j < base->subgroups[i].bis_count; j++) { + const size_t bis_count = base->subgroups[i].bis_count; + + printk("Subgroup[%zu] has %zu streams\n", i, bis_count); + + for (size_t j = 0U; j < bis_count; j++) { const uint8_t index = base->subgroups[i].bis_data[j].index; + printk("\tIndex 0x%02x\n", index); + base_bis_index_bitfield |= BIT(index); } +#if defined(CONFIG_LIBLC3) + int ret; + const struct bt_audio_codec_cfg *codec_cfg = &base->subgroups[i].codec_cfg; + + if (codec_cfg->id != BT_HCI_CODING_FORMAT_LC3) { + printk("unsupported codec 0x%02x", codec_cfg->id); + return; + } + + ret = lc3_enable(codec_cfg); + if (ret < 0) { + printk("Error: cannot enable LC3 codec: %d", ret); + return; + } +#endif /* defined(CONFIG_LIBLC3) */ } bis_index_bitfield = base_bis_index_bitfield & bis_index_mask; @@ -148,20 +319,18 @@ static struct bt_bap_broadcast_sink_cb broadcast_sink_cbs = { .syncable = syncable_cb, }; -const struct bt_bap_scan_delegator_recv_state *broadcast_recv_state; - static void pa_timer_handler(struct k_work *work) { - if (broadcast_recv_state != NULL) { + if (req_recv_state != NULL) { enum bt_bap_pa_state pa_state; - if (broadcast_recv_state->pa_sync_state == BT_BAP_PA_STATE_INFO_REQ) { + if (req_recv_state->pa_sync_state == BT_BAP_PA_STATE_INFO_REQ) { pa_state = BT_BAP_PA_STATE_NO_PAST; } else { pa_state = BT_BAP_PA_STATE_FAILED; } - bt_bap_scan_delegator_set_pa_state(broadcast_recv_state->src_id, + bt_bap_scan_delegator_set_pa_state(req_recv_state->src_id, pa_state); } @@ -218,9 +387,7 @@ static int pa_sync_req_cb(struct bt_conn *conn, { int err; - sink_recv_state = recv_state; - - broadcast_recv_state = recv_state; + req_recv_state = recv_state; if (recv_state->pa_sync_state == BT_BAP_PA_STATE_SYNCED || recv_state->pa_sync_state == BT_BAP_PA_STATE_INFO_REQ) { @@ -247,7 +414,7 @@ static int pa_sync_term_req_cb(struct bt_conn *conn, { int err; - sink_recv_state = recv_state; + req_recv_state = recv_state; err = bt_bap_broadcast_sink_delete(broadcast_sink); if (err != 0) { @@ -265,7 +432,7 @@ static void broadcast_code_cb(struct bt_conn *conn, { printk("Broadcast code received for %p\n", recv_state); - sink_recv_state = recv_state; + req_recv_state = recv_state; (void)memcpy(sink_broadcast_code, broadcast_code, BT_AUDIO_BROADCAST_CODE_SIZE); @@ -398,9 +565,10 @@ static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data) if (broadcast_assistant_conn == NULL) { /* Not requested by Broadcast Assistant */ k_sem_give(&sem_broadcaster_found); - } else if (sink_recv_state != NULL && bt_addr_le_eq(info->addr, &sink_recv_state->addr) && - info->sid == sink_recv_state->adv_sid && - broadcast_id == sink_recv_state->broadcast_id) { + } else if (req_recv_state != NULL && + bt_addr_le_eq(info->addr, &req_recv_state->addr) && + info->sid == req_recv_state->adv_sid && + broadcast_id == req_recv_state->broadcast_id) { k_sem_give(&sem_broadcaster_found); } @@ -413,9 +581,59 @@ static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data) return false; } +static bool is_substring(const char *substr, const char *str) +{ + const size_t str_len = strlen(str); + const size_t sub_str_len = strlen(substr); + + if (sub_str_len > str_len) { + return false; + } + + for (size_t pos = 0; pos < str_len; pos++) { + if (tolower(substr[pos]) == tolower(str[pos])) { + if (pos + sub_str_len > str_len) { + return false; + } + + if (strncasecmp(substr, &str[pos], sub_str_len) == 0) { + return true; + } + } + } + + return false; +} + +static bool data_cb(struct bt_data *data, void *user_data) +{ + char *name = user_data; + + switch (data->type) { + case BT_DATA_NAME_SHORTENED: + case BT_DATA_NAME_COMPLETE: + case BT_DATA_BROADCAST_NAME: + memcpy(name, data->data, MIN(data->data_len, NAME_LEN - 1)); + return false; + default: + return true; + } +} + static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info, struct net_buf_simple *ad) { if (info->interval != 0U) { + /* call to bt_data_parse consumes netbufs so shallow clone for verbose output */ + if (strlen(CONFIG_TARGET_BROADCAST_NAME) > 0U) { + struct net_buf_simple buf_copy; + char name[NAME_LEN] = {0}; + + net_buf_simple_clone(ad, &buf_copy); + bt_data_parse(&buf_copy, data_cb, name); + if (!(is_substring(CONFIG_TARGET_BROADCAST_NAME, name))) { + return; + } + } bt_data_parse(ad, scan_check_and_sync_broadcast, (void *)info); } } @@ -475,7 +693,7 @@ static int init(void) bt_le_scan_cb_register(&bap_scan_cb); for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { - streams[i].ops = &stream_ops; + streams[i].stream.ops = &stream_ops; } return 0; @@ -487,7 +705,7 @@ static int reset(void) bis_index_bitfield = 0U; requested_bis_sync = 0U; - sink_recv_state = NULL; + req_recv_state = NULL; (void)memset(sink_broadcast_code, 0, sizeof(sink_broadcast_code)); (void)memset(&broadcaster_info, 0, sizeof(broadcaster_info)); (void)memset(&broadcaster_addr, 0, sizeof(broadcaster_addr)); @@ -566,7 +784,6 @@ static int reset(void) k_sem_reset(&sem_broadcast_code_received); k_sem_reset(&sem_bis_sync_requested); k_sem_reset(&sem_bis_synced); - return 0; } @@ -652,10 +869,15 @@ int main(void) } for (size_t i = 0U; i < ARRAY_SIZE(streams_p); i++) { - streams_p[i] = &streams[i]; + streams_p[i] = &streams[i].stream; +#if defined(CONFIG_LIBLC3) + k_mutex_init(&streams[i].lc3_decoder_mutex); +#endif /* defined(CONFIG_LIBLC3) */ } while (true) { + uint32_t sync_bitfield; + err = reset(); if (err != 0) { printk("Resetting failed: %d - Aborting\n", err); @@ -702,7 +924,13 @@ int main(void) } } - printk("Scanning for broadcast sources\n"); + if (strlen(CONFIG_TARGET_BROADCAST_NAME) > 0U) { + printk("Scanning for broadcast sources containing`" + CONFIG_TARGET_BROADCAST_NAME "`\n"); + } else { + printk("Scanning for broadcast sources\n"); + } + err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, NULL); if (err != 0 && err != -EALREADY) { printk("Unable to start scan for broadcast sources: %d\n", @@ -778,10 +1006,10 @@ int main(void) continue; } - printk("Syncing to broadcast\n"); - err = bt_bap_broadcast_sink_sync(broadcast_sink, - bis_index_bitfield & requested_bis_sync, - streams_p, sink_broadcast_code); + sync_bitfield = bis_index_bitfield & requested_bis_sync; + printk("Syncing to broadcast with bitfield: 0x%08x\n", sync_bitfield); + err = bt_bap_broadcast_sink_sync(broadcast_sink, sync_bitfield, streams_p, + sink_broadcast_code); if (err != 0) { printk("Unable to sync to broadcast source: %d\n", err); return 0; diff --git a/samples/bluetooth/broadcast_audio_sink/sysbuild.cmake b/samples/bluetooth/broadcast_audio_sink/sysbuild.cmake new file mode 100644 index 00000000000..2523aac8ea7 --- /dev/null +++ b/samples/bluetooth/broadcast_audio_sink/sysbuild.cmake @@ -0,0 +1,24 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) + # For builds in the nrf5340, we build the netcore image with the controller + + set(NET_APP hci_ipc) + set(NET_APP_SRC_DIR ${ZEPHYR_BASE}/samples/bluetooth/${NET_APP}) + + ExternalZephyrProject_Add( + APPLICATION ${NET_APP} + SOURCE_DIR ${NET_APP_SRC_DIR} + BOARD ${SB_CONFIG_NET_CORE_BOARD} + ) + + set(${NET_APP}_CONF_FILE + ${NET_APP_SRC_DIR}/nrf5340_cpunet_iso-bt_ll_sw_split.conf + CACHE INTERNAL "" + ) + + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) +endif() + +native_simulator_set_final_executable(${DEFAULT_IMAGE}) diff --git a/samples/bluetooth/broadcast_audio_source/Kconfig b/samples/bluetooth/broadcast_audio_source/Kconfig new file mode 100644 index 00000000000..d88378d0848 --- /dev/null +++ b/samples/bluetooth/broadcast_audio_source/Kconfig @@ -0,0 +1,40 @@ +# Copyright (c) 2023 Demant A/S +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +mainmenu "Bluetooth: Broadcast Audio Source" + +choice BAP_LC3_PRESET + prompt "The BAP LC3 Preset to be used" + default BAP_BROADCAST_16_2_1 + +config BAP_BROADCAST_16_2_1 + bool "BAP_LC3_BROADCAST_PRESET_16_2_1 preset" + help + Using the BAP_LC3_BROADCAST_PRESET_16_2_1 preset. + +config BAP_BROADCAST_24_2_1 + bool "BAP_LC3_BROADCAST_PRESET_24_2_1 preset" + help + Using the BAP_LC3_BROADCAST_PRESET_24_2_1 preset. + +endchoice + +config ENABLE_LC3 + bool "Enable the LC3 codec" + # By default let's enable it in the platforms we know are capable of supporting it + default y + depends on (ARCH_POSIX || SOC_NRF5340_CPUAPP) + select LIBLC3 + select FPU + +config USE_USB_AUDIO_INPUT + bool "Use USB Audio as input" + # By default, use the USB Audio path is disabled. + default n + depends on ENABLE_LC3 + select USB_DEVICE_STACK + select USB_DEVICE_AUDIO + select RING_BUFFER + +source "Kconfig.zephyr" diff --git a/samples/bluetooth/broadcast_audio_source/Kconfig.sysbuild b/samples/bluetooth/broadcast_audio_source/Kconfig.sysbuild new file mode 100644 index 00000000000..f434010f81d --- /dev/null +++ b/samples/bluetooth/broadcast_audio_source/Kconfig.sysbuild @@ -0,0 +1,15 @@ +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config NET_CORE_BOARD + string + default "nrf5340dk_nrf5340_cpunet" if $(BOARD) = "nrf5340dk_nrf5340_cpuapp" + default "nrf5340_audio_dk_nrf5340_cpunet" if $(BOARD) = "nrf5340_audio_dk_nrf5340_cpuapp" + default "nrf5340bsim_nrf5340_cpunet" if $(BOARD) = "nrf5340bsim_nrf5340_cpuapp" + +config NET_CORE_IMAGE_HCI_IPC + bool "HCI IPC image on network core" + default y + depends on NET_CORE_BOARD != "" diff --git a/samples/bluetooth/broadcast_audio_source/README.rst b/samples/bluetooth/broadcast_audio_source/README.rst index 12fb6c0ca1a..1c36236231b 100644 --- a/samples/bluetooth/broadcast_audio_source/README.rst +++ b/samples/bluetooth/broadcast_audio_source/README.rst @@ -1,7 +1,8 @@ -.. _bluetooth_broadcast_audio_source: +.. zephyr:code-sample:: bluetooth_broadcast_audio_source + :name: Bluetooth: Broadcast Audio Source + :relevant-api: bluetooth -Bluetooth: Broadcast Audio Source -################################# + Bluetooth: Broadcast Audio Source Overview ******** @@ -13,6 +14,11 @@ broadcast audio source endpoint (BASE) and finally the BIGinfo together with The broadcast source will reset every 30 seconds to show the full API. +This sample can be found under +:zephyr_file:`samples/bluetooth/broadcast_audio_source` in the Zephyr tree. + +Check the :ref:`bluetooth samples section ` for general information. + Requirements ************ @@ -21,9 +27,53 @@ Requirements Building and Running ******************** -This sample can be found under -:zephyr_file:`samples/bluetooth/broadcast_audio_source` in the Zephyr tree. -Use `-DEXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf` to enable required ISO -feature support in Zephyr Bluetooth Controller on supported boards. -See :ref:`bluetooth samples section ` for details. +When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, +use `-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf` to enable the required ISO +feature support. + +Building for an nrf5340dk +------------------------- + +You can build both the application core image and an appropriate controller image for the network +core with: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/broadcast_audio_source/ + :board: nrf5340dk_nrf5340_cpuapp + :goals: build + :west-args: --sysbuild + +If you prefer to only build the application core image, you can do so by doing instead: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/broadcast_audio_source/ + :board: nrf5340dk_nrf5340_cpuapp + :goals: build + +In that case you can pair this application core image with the +:ref:`hci_ipc sample ` +:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. + +Building for a simulated nrf5340bsim +------------------------------------ + +Similarly to how you would for real HW, you can do: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/broadcast_audio_source/ + :board: nrf5340bsim_nrf5340_cpuapp + :goals: build + :west-args: --sysbuild + +Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. +For more information, check :ref:`this board documentation `. + +Building for a simulated nrf52_bsim +----------------------------------- + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/broadcast_audio_source/ + :board: nrf52_bsim + :goals: build + :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf diff --git a/samples/bluetooth/broadcast_audio_source/boards/nrf52_bsim.conf b/samples/bluetooth/broadcast_audio_source/boards/nrf52_bsim.conf new file mode 100644 index 00000000000..5df721fba26 --- /dev/null +++ b/samples/bluetooth/broadcast_audio_source/boards/nrf52_bsim.conf @@ -0,0 +1 @@ +CONFIG_MAIN_STACK_SIZE=4096 diff --git a/samples/bluetooth/broadcast_audio_source/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/broadcast_audio_source/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000..ff8004f0dc0 --- /dev/null +++ b/samples/bluetooth/broadcast_audio_source/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -0,0 +1,8 @@ +CONFIG_MAIN_STACK_SIZE=4096 + +# Use USB Audio as input +CONFIG_USE_USB_AUDIO_INPUT=y +CONFIG_USB_DEVICE_PRODUCT="Zephyr Broadcast Source" + +# Two streams in one subgroup (stereo) +CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT=1 diff --git a/samples/bluetooth/broadcast_audio_source/boards/nrf5340bsim_nrf5340_cpuapp.conf b/samples/bluetooth/broadcast_audio_source/boards/nrf5340bsim_nrf5340_cpuapp.conf new file mode 100644 index 00000000000..5df721fba26 --- /dev/null +++ b/samples/bluetooth/broadcast_audio_source/boards/nrf5340bsim_nrf5340_cpuapp.conf @@ -0,0 +1 @@ +CONFIG_MAIN_STACK_SIZE=4096 diff --git a/samples/bluetooth/broadcast_audio_source/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/broadcast_audio_source/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000..5df721fba26 --- /dev/null +++ b/samples/bluetooth/broadcast_audio_source/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1 @@ +CONFIG_MAIN_STACK_SIZE=4096 diff --git a/samples/bluetooth/broadcast_audio_source/prj.conf b/samples/bluetooth/broadcast_audio_source/prj.conf index 89210995535..d74cbbe50ce 100644 --- a/samples/bluetooth/broadcast_audio_source/prj.conf +++ b/samples/bluetooth/broadcast_audio_source/prj.conf @@ -10,4 +10,6 @@ CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT=2 CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT=2 CONFIG_BT_ISO_TX_BUF_COUNT=4 +CONFIG_BT_ISO_TX_MTU=60 + CONFIG_BT_DEVICE_NAME="Broadcast Audio Source" diff --git a/samples/bluetooth/broadcast_audio_source/sample.yaml b/samples/bluetooth/broadcast_audio_source/sample.yaml index 1c3904d8c82..1c27238c35f 100644 --- a/samples/bluetooth/broadcast_audio_source/sample.yaml +++ b/samples/bluetooth/broadcast_audio_source/sample.yaml @@ -8,10 +8,12 @@ tests: - qemu_cortex_m3 - qemu_x86 - nrf5340dk_nrf5340_cpuapp + - nrf5340bsim_nrf5340_cpuapp integration_platforms: - qemu_x86 - nrf5340dk_nrf5340_cpuapp tags: bluetooth + sysbuild: true sample.bluetooth.broadcast_audio_source.bt_ll_sw_split: harness: bluetooth platform_allow: diff --git a/samples/bluetooth/broadcast_audio_source/src/main.c b/samples/bluetooth/broadcast_audio_source/src/main.c index 111bba09bc6..8a129e3f361 100644 --- a/samples/bluetooth/broadcast_audio_source/src/main.c +++ b/samples/bluetooth/broadcast_audio_source/src/main.c @@ -9,26 +9,128 @@ #include #include +/* Zephyr Controller works best while Extended Advertising interval to be a multiple + * of the ISO Interval minus 10 ms (max. advertising random delay). This is + * required to place the AUX_ADV_IND PDUs in a non-overlapping interval with the + * Broadcast ISO radio events. + * + * I.e. for a 7.5 ms ISO interval use 90 ms minus 10 ms ==> 80 ms advertising + * interval. + * And, for 10 ms ISO interval, can use 90 ms minus 10 ms ==> 80 ms advertising + * interval. + */ +#define BT_LE_EXT_ADV_CUSTOM \ + BT_LE_ADV_PARAM(BT_LE_ADV_OPT_EXT_ADV | BT_LE_ADV_OPT_USE_NAME, 0x0080, 0x0080, NULL) + /* When BROADCAST_ENQUEUE_COUNT > 1 we can enqueue enough buffers to ensure that * the controller is never idle */ #define BROADCAST_ENQUEUE_COUNT 2U -#define TOTAL_BUF_NEEDED (BROADCAST_ENQUEUE_COUNT * CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT) +#define TOTAL_BUF_NEEDED (BROADCAST_ENQUEUE_COUNT * CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT) BUILD_ASSERT(CONFIG_BT_ISO_TX_BUF_COUNT >= TOTAL_BUF_NEEDED, "CONFIG_BT_ISO_TX_BUF_COUNT should be at least " "BROADCAST_ENQUEUE_COUNT * CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT"); -static struct bt_bap_lc3_preset preset_16_2_1 = BT_BAP_LC3_BROADCAST_PRESET_16_2_1( - BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); -static struct bt_bap_stream streams[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT]; +#if defined(CONFIG_BAP_BROADCAST_16_2_1) + +static struct bt_bap_lc3_preset preset_active = BT_BAP_LC3_BROADCAST_PRESET_16_2_1( + BT_AUDIO_LOCATION_FRONT_LEFT | BT_AUDIO_LOCATION_FRONT_RIGHT, + BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); + +#define BROADCAST_SAMPLE_RATE 16000 + +#elif defined(CONFIG_BAP_BROADCAST_24_2_1) + +static struct bt_bap_lc3_preset preset_active = BT_BAP_LC3_BROADCAST_PRESET_24_2_1( + BT_AUDIO_LOCATION_FRONT_LEFT | BT_AUDIO_LOCATION_FRONT_RIGHT, + BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); + +#define BROADCAST_SAMPLE_RATE 24000 + +#endif + +#if defined(CONFIG_BAP_BROADCAST_16_2_1) +#define MAX_SAMPLE_RATE 16000 +#elif defined(CONFIG_BAP_BROADCAST_24_2_1) +#define MAX_SAMPLE_RATE 24000 +#endif +#define MAX_FRAME_DURATION_US 10000 +#define MAX_NUM_SAMPLES ((MAX_FRAME_DURATION_US * MAX_SAMPLE_RATE) / USEC_PER_SEC) + +#if defined(CONFIG_LIBLC3) +#include "lc3.h" + +#if defined(CONFIG_USB_DEVICE_AUDIO) +#include +#include +#include + +/* USB Audio Data is downsampled from 48kHz to match broadcast preset when receiving data */ +#define USB_SAMPLE_RATE 48000 +#define USB_DOWNSAMPLE_RATE BROADCAST_SAMPLE_RATE +#define USB_FRAME_DURATION_US 1000 +#define USB_NUM_SAMPLES ((USB_FRAME_DURATION_US * USB_DOWNSAMPLE_RATE) / USEC_PER_SEC) +#define USB_BYTES_PER_SAMPLE 2 +#define USB_CHANNELS 2 + +#define RING_BUF_USB_FRAMES 20 +#define AUDIO_RING_BUF_BYTES USB_NUM_SAMPLES * USB_BYTES_PER_SAMPLE * RING_BUF_USB_FRAMES +#else /* !defined(CONFIG_USB_DEVICE_AUDIO) */ + +#include + +#define AUDIO_VOLUME (INT16_MAX - 3000) /* codec does clipping above INT16_MAX - 3000 */ +#define AUDIO_TONE_FREQUENCY_HZ 400 + +/** + * Use the math lib to generate a sine-wave using 16 bit samples into a buffer. + * + * @param buf Destination buffer + * @param length_us Length of the buffer in microseconds + * @param frequency_hz frequency in Hz + * @param sample_rate_hz sample-rate in Hz. + */ +static void fill_audio_buf_sin(int16_t *buf, int length_us, int frequency_hz, int sample_rate_hz) +{ + const int sine_period_samples = sample_rate_hz / frequency_hz; + const unsigned int num_samples = (length_us * sample_rate_hz) / USEC_PER_SEC; + const float step = 2 * 3.1415f / sine_period_samples; + + for (unsigned int i = 0; i < num_samples; i++) { + const float sample = sin(i * step); + + buf[i] = (int16_t)(AUDIO_VOLUME * sample); + } +} +#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ +#endif /* defined(CONFIG_LIBLC3) */ + +static struct broadcast_source_stream { + struct bt_bap_stream stream; + uint16_t seq_num; + size_t sent_cnt; +#if defined(CONFIG_LIBLC3) + lc3_encoder_t lc3_encoder; +#if defined(CONFIG_BAP_BROADCAST_16_2_1) + lc3_encoder_mem_16k_t lc3_encoder_mem; +#elif defined(CONFIG_BAP_BROADCAST_24_2_1) + lc3_encoder_mem_48k_t lc3_encoder_mem; +#endif +#if defined(CONFIG_USB_DEVICE_AUDIO) + struct ring_buf audio_ring_buf; + uint8_t _ring_buffer_memory[AUDIO_RING_BUF_BYTES]; +#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ +#endif /* defined(CONFIG_LIBLC3) */ +} streams[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT]; static struct bt_bap_broadcast_source *broadcast_source; NET_BUF_POOL_FIXED_DEFINE(tx_pool, TOTAL_BUF_NEEDED, BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); -static uint8_t mock_data[CONFIG_BT_ISO_TX_MTU]; + +static int16_t send_pcm_data[MAX_NUM_SAMPLES]; static uint16_t seq_num; static bool stopping; @@ -37,19 +139,18 @@ static K_SEM_DEFINE(sem_stopped, 0U, ARRAY_SIZE(streams)); #define BROADCAST_SOURCE_LIFETIME 120U /* seconds */ -static void stream_started_cb(struct bt_bap_stream *stream) -{ - k_sem_give(&sem_started); -} +#if defined(CONFIG_LIBLC3) +static int freq_hz; +static int frame_duration_us; +static int frames_per_sdu; +static int octets_per_frame; -static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) -{ - k_sem_give(&sem_stopped); -} +static K_SEM_DEFINE(lc3_encoder_sem, 0U, ARRAY_SIZE(streams)); +#endif -static void stream_sent_cb(struct bt_bap_stream *stream) +static void send_data(struct broadcast_source_stream *source_stream) { - static uint32_t sent_cnt; + struct bt_bap_stream *stream = &source_stream->stream; struct net_buf *buf; int ret; @@ -65,9 +166,39 @@ static void stream_sent_cb(struct bt_bap_stream *stream) } net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); - net_buf_add_mem(buf, mock_data, preset_16_2_1.qos.sdu); - ret = bt_bap_stream_send(stream, buf, seq_num++, - BT_ISO_TIMESTAMP_NONE); +#if defined(CONFIG_LIBLC3) + uint8_t lc3_encoded_buffer[preset_active.qos.sdu]; + + if (source_stream->lc3_encoder == NULL) { + printk("LC3 encoder not setup, cannot encode data.\n"); + return; + } + +#if defined(CONFIG_USB_DEVICE_AUDIO) + uint32_t size = ring_buf_get(&source_stream->audio_ring_buf, + (uint8_t *)send_pcm_data, sizeof(send_pcm_data)); + + if (size < sizeof(send_pcm_data)) { + const size_t padding_size = sizeof(send_pcm_data) - size; + + printk("Not enough bytes ready, padding %d!\n", padding_size); + memset(&((uint8_t *)send_pcm_data)[size], 0, padding_size); + } +#endif + + ret = lc3_encode(source_stream->lc3_encoder, LC3_PCM_FORMAT_S16, + send_pcm_data, 1, octets_per_frame, lc3_encoded_buffer); + if (ret == -1) { + printk("LC3 encoder failed - wrong parameters?: %d", ret); + return; + } + + net_buf_add_mem(buf, lc3_encoded_buffer, preset_active.qos.sdu); +#else + net_buf_add_mem(buf, send_pcm_data, preset_active.qos.sdu); +#endif /* defined(CONFIG_LIBLC3) */ + + ret = bt_bap_stream_send(stream, buf, source_stream->seq_num++, BT_ISO_TIMESTAMP_NONE); if (ret < 0) { /* This will end broadcasting on this stream. */ printk("Unable to broadcast data on %p: %d\n", stream, ret); @@ -75,10 +206,168 @@ static void stream_sent_cb(struct bt_bap_stream *stream) return; } - sent_cnt++; - if ((sent_cnt % 1000U) == 0U) { - printk("Sent %u total ISO packets\n", sent_cnt); + source_stream->sent_cnt++; + if ((source_stream->sent_cnt % 1000U) == 0U) { + printk("Stream %p: Sent %u total ISO packets\n", stream, source_stream->sent_cnt); + } +} + +#if defined(CONFIG_LIBLC3) +static void init_lc3_thread(void *arg1, void *arg2, void *arg3) +{ + const struct bt_audio_codec_cfg *codec_cfg = &preset_active.codec_cfg; + int ret; + + ret = bt_audio_codec_cfg_get_freq(codec_cfg); + if (ret > 0) { + freq_hz = bt_audio_codec_cfg_freq_to_freq_hz(ret); + } else { + return; + } + + ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg); + if (ret > 0) { + frame_duration_us = bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret); + } else { + printk("Error: Frame duration not set, cannot start codec."); + return; + } + + octets_per_frame = bt_audio_codec_cfg_get_octets_per_frame(codec_cfg); + frames_per_sdu = bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true); + + if (freq_hz < 0) { + printk("Error: Codec frequency not set, cannot start codec."); + return; + } + + if (frame_duration_us < 0) { + printk("Error: Frame duration not set, cannot start codec."); + return; + } + + if (octets_per_frame < 0) { + printk("Error: Octets per frame not set, cannot start codec."); + return; + } + +#if !defined(CONFIG_USB_DEVICE_AUDIO) + /* If USB is not used as a sound source, generate a sine wave */ + fill_audio_buf_sin(send_pcm_data, frame_duration_us, AUDIO_TONE_FREQUENCY_HZ, freq_hz); +#endif + + /* Create the encoder instance. This shall complete before stream_started() is called. */ + for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { + printk("Initializing lc3 encoder for stream %zu\n", i); + streams[i].lc3_encoder = lc3_setup_encoder(frame_duration_us, freq_hz, + 0, &streams[i].lc3_encoder_mem); + + if (streams[i].lc3_encoder == NULL) { + printk("ERROR: Failed to setup LC3 encoder - wrong parameters?\n"); + } + } + + while (true) { + for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { + k_sem_take(&lc3_encoder_sem, K_FOREVER); + } + for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { + send_data(&streams[i]); + } + } +} + +#define LC3_ENCODER_STACK_SIZE 4 * 4096 +#define LC3_ENCODER_PRIORITY 5 + +K_THREAD_DEFINE(encoder, LC3_ENCODER_STACK_SIZE, init_lc3_thread, + NULL, NULL, NULL, LC3_ENCODER_PRIORITY, 0, -1); + +#if defined(CONFIG_USB_DEVICE_AUDIO) +static void data_received(const struct device *dev, + struct net_buf *buffer, + size_t size) +{ + static int count; + int16_t *pcm; + int nsamples, ratio; + int16_t usb_pcm_data[USB_CHANNELS][USB_NUM_SAMPLES]; + + if (!buffer) { + return; + } + + if (!size) { + net_buf_unref(buffer); + return; + } + + pcm = (int16_t *)net_buf_pull_mem(buffer, size); + + /* 'size' is in bytes, containing 1ms, 48kHz, stereo, 2 bytes per sample. + * Take left channel and do a simple downsample to 16kHz/24Khz + * matching the broadcast preset. + */ + + ratio = USB_SAMPLE_RATE / USB_DOWNSAMPLE_RATE; + nsamples = size / (sizeof(int16_t) * USB_CHANNELS * ratio); + for (size_t i = 0, j = 0; i < nsamples; i++, j += USB_CHANNELS * ratio) { + usb_pcm_data[0][i] = pcm[j]; + usb_pcm_data[1][i] = pcm[j + 1]; } + + for (size_t i = 0U; i < MIN(ARRAY_SIZE(streams), 2); i++) { + const uint32_t size_put = ring_buf_put(&(streams[i].audio_ring_buf), + (uint8_t *)(usb_pcm_data[i]), nsamples * USB_BYTES_PER_SAMPLE); + if (size_put < nsamples * USB_BYTES_PER_SAMPLE) { + printk("Not enough room for samples in %s buffer: %u < %u, total capacity: %u\n", + i == 0 ? "left" : "right", + size_put, + nsamples * USB_BYTES_PER_SAMPLE, + ring_buf_capacity_get(&(streams[i].audio_ring_buf))); + } + } + + count++; + if ((count % 1000) == 0) { + printk("USB Data received (count = %d)\n", count); + } + + net_buf_unref(buffer); +} + +static const struct usb_audio_ops ops = { + .data_received_cb = data_received +}; +#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ +#endif /* defined(CONFIG_LIBLC3) */ + +static void stream_started_cb(struct bt_bap_stream *stream) +{ + struct broadcast_source_stream *source_stream = + CONTAINER_OF(stream, struct broadcast_source_stream, stream); + + source_stream->seq_num = 0U; + source_stream->sent_cnt = 0U; + k_sem_give(&sem_started); +} + +static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) +{ + k_sem_give(&sem_stopped); +} + +static void stream_sent_cb(struct bt_bap_stream *stream) +{ +#if defined(CONFIG_LIBLC3) + k_sem_give(&lc3_encoder_sem); +#else + /* If no LC3 encoder is used, just send mock data directly */ + struct broadcast_source_stream *source_stream = + CONTAINER_OF(stream, struct broadcast_source_stream, stream); + + send_data(source_stream); +#endif } static struct bt_bap_stream_ops stream_ops = { @@ -93,28 +382,30 @@ static int setup_broadcast_source(struct bt_bap_broadcast_source **source) stream_params[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT]; struct bt_bap_broadcast_source_subgroup_param subgroup_param[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT]; - struct bt_bap_broadcast_source_create_param create_param; + struct bt_bap_broadcast_source_param create_param; const size_t streams_per_subgroup = ARRAY_SIZE(stream_params) / ARRAY_SIZE(subgroup_param); + uint8_t left[] = {BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC, + BT_BYTES_LIST_LE32(BT_AUDIO_LOCATION_FRONT_LEFT))}; + uint8_t right[] = {BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC, + BT_BYTES_LIST_LE32(BT_AUDIO_LOCATION_FRONT_RIGHT))}; int err; - (void)memset(streams, 0, sizeof(streams)); - for (size_t i = 0U; i < ARRAY_SIZE(subgroup_param); i++) { subgroup_param[i].params_count = streams_per_subgroup; subgroup_param[i].params = stream_params + i * streams_per_subgroup; - subgroup_param[i].codec_cfg = &preset_16_2_1.codec_cfg; + subgroup_param[i].codec_cfg = &preset_active.codec_cfg; } for (size_t j = 0U; j < ARRAY_SIZE(stream_params); j++) { - stream_params[j].stream = &streams[j]; - stream_params[j].data = NULL; - stream_params[j].data_len = 0U; + stream_params[j].stream = &streams[j].stream; + stream_params[j].data = j == 0 ? left : right; + stream_params[j].data_len = j == 0 ? sizeof(left) : sizeof(right); bt_bap_stream_cb_register(stream_params[j].stream, &stream_ops); } create_param.params_count = ARRAY_SIZE(subgroup_param); create_param.params = subgroup_param; - create_param.qos = &preset_16_2_1.qos; + create_param.qos = &preset_active.qos; create_param.encryption = false; create_param.packing = BT_ISO_PACKING_SEQUENTIAL; @@ -143,11 +434,45 @@ int main(void) } printk("Bluetooth initialized\n"); - for (size_t i = 0U; i < ARRAY_SIZE(mock_data); i++) { + for (size_t i = 0U; i < ARRAY_SIZE(send_pcm_data); i++) { /* Initialize mock data */ - mock_data[i] = i; + send_pcm_data[i] = i; } +#if defined(CONFIG_LIBLC3) +#if defined(CONFIG_USB_DEVICE_AUDIO) + const struct device *hs_dev; + + hs_dev = DEVICE_DT_GET(DT_NODELABEL(hs_0)); + + if (!device_is_ready(hs_dev)) { + printk("Device USB Headset is not ready\n"); + return 0; + } + + printk("Found USB Headset Device\n"); + + (void)memset(streams, 0, sizeof(streams)); + + for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { + ring_buf_init(&(streams[i].audio_ring_buf), + sizeof(streams[i]._ring_buffer_memory), + streams[i]._ring_buffer_memory); + printk("Initialized ring buf %zu: capacity: %u\n", i, + ring_buf_capacity_get(&(streams[i].audio_ring_buf))); + } + + usb_audio_register(hs_dev, &ops); + + err = usb_enable(NULL); + if (err) { + printk("Failed to enable USB"); + return 0; + } +#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ + k_thread_start(encoder); +#endif /* defined(CONFIG_LIBLC3) */ + while (true) { /* Broadcast Audio Streaming Endpoint advertising data */ NET_BUF_SIMPLE_DEFINE(ad_buf, @@ -158,7 +483,7 @@ int main(void) uint32_t broadcast_id; /* Create a non-connectable non-scannable advertising set */ - err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN_NAME, NULL, &adv); + err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CUSTOM, NULL, &adv); if (err != 0) { printk("Unable to create extended advertising set: %d\n", err); @@ -249,14 +574,17 @@ int main(void) /* Initialize sending */ for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { for (unsigned int j = 0U; j < BROADCAST_ENQUEUE_COUNT; j++) { - stream_sent_cb(&streams[i]); + stream_sent_cb(&streams[i].stream); } } +#if defined(CONFIG_LIBLC3) && defined(CONFIG_USB_DEVICE_AUDIO) + /* Never stop streaming when using USB Audio as input */ + k_sleep(K_FOREVER); +#endif /* defined(CONFIG_LIBLC3) && defined(CONFIG_USB_DEVICE_AUDIO) */ printk("Waiting %u seconds before stopped\n", BROADCAST_SOURCE_LIFETIME); k_sleep(K_SECONDS(BROADCAST_SOURCE_LIFETIME)); - printk("Stopping broadcast source\n"); stopping = true; err = bt_bap_broadcast_source_stop(broadcast_source); diff --git a/samples/bluetooth/broadcast_audio_source/sysbuild.cmake b/samples/bluetooth/broadcast_audio_source/sysbuild.cmake new file mode 100644 index 00000000000..2523aac8ea7 --- /dev/null +++ b/samples/bluetooth/broadcast_audio_source/sysbuild.cmake @@ -0,0 +1,24 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) + # For builds in the nrf5340, we build the netcore image with the controller + + set(NET_APP hci_ipc) + set(NET_APP_SRC_DIR ${ZEPHYR_BASE}/samples/bluetooth/${NET_APP}) + + ExternalZephyrProject_Add( + APPLICATION ${NET_APP} + SOURCE_DIR ${NET_APP_SRC_DIR} + BOARD ${SB_CONFIG_NET_CORE_BOARD} + ) + + set(${NET_APP}_CONF_FILE + ${NET_APP_SRC_DIR}/nrf5340_cpunet_iso-bt_ll_sw_split.conf + CACHE INTERNAL "" + ) + + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) +endif() + +native_simulator_set_final_executable(${DEFAULT_IMAGE}) diff --git a/samples/bluetooth/broadcaster_multiple/src/broadcaster_multiple.c b/samples/bluetooth/broadcaster_multiple/src/broadcaster_multiple.c index 30fe35d3dec..d4ce51c4f25 100644 --- a/samples/bluetooth/broadcaster_multiple/src/broadcaster_multiple.c +++ b/samples/bluetooth/broadcaster_multiple/src/broadcaster_multiple.c @@ -56,7 +56,7 @@ static uint8_t mfg_data[BT_MFG_DATA_LEN] = { 0xFF, 0xFF, }; static const struct bt_data ad[] = { BT_DATA(BT_DATA_MANUFACTURER_DATA, mfg_data, sizeof(mfg_data)), -#if defined(CONFIG_BT_CTLR_ADV_DATA_CHAIN) +#if CONFIG_BT_CTLR_ADV_DATA_LEN_MAX > 255 BT_DATA(BT_DATA_MANUFACTURER_DATA, mfg_data, sizeof(mfg_data)), #endif }; diff --git a/samples/bluetooth/central_iso/src/main.c b/samples/bluetooth/central_iso/src/main.c index c5da26373b1..a0062fcfa73 100644 --- a/samples/bluetooth/central_iso/src/main.c +++ b/samples/bluetooth/central_iso/src/main.c @@ -25,6 +25,7 @@ static struct bt_conn *default_conn; static struct k_work_delayable iso_send_work; static struct bt_iso_chan iso_chan; static uint16_t seq_num; +static uint16_t latency_ms = 10U; /* 10ms */ static uint32_t interval_us = 10U * USEC_PER_MSEC; /* 10 ms */ NET_BUF_POOL_FIXED_DEFINE(tx_pool, 1, BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); @@ -251,8 +252,10 @@ int main(void) param.sca = BT_GAP_SCA_UNKNOWN; param.packing = 0; param.framing = 0; - param.latency = 10; /* ms */ - param.interval = interval_us; /* us */ + param.c_to_p_latency = latency_ms; /* ms */ + param.p_to_c_latency = latency_ms; /* ms */ + param.c_to_p_interval = interval_us; /* us */ + param.p_to_c_interval = interval_us; /* us */ err = bt_iso_cig_create(¶m, &cig); diff --git a/samples/bluetooth/direction_finding_central/README.rst b/samples/bluetooth/direction_finding_central/README.rst index 17cbc599f6b..07a5d1c52be 100644 --- a/samples/bluetooth/direction_finding_central/README.rst +++ b/samples/bluetooth/direction_finding_central/README.rst @@ -37,21 +37,21 @@ changing ``nrf52833dk_nrf52833`` as needed for your board: :compact: To run the application on nRF5340DK, a Bluetooth controller application must -also run on the network core. The :ref:`bluetooth-hci-rpmsg-sample` sample +also run on the network core. The :ref:`bluetooth-hci-ipc-sample` sample application may be used. To build this sample with direction finding support enabled: * Copy :zephyr_file:`samples/bluetooth/direction_finding_central/boards/nrf52833dk_nrf52833.overlay` to a new file, - :file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.overlay`. + :file:`samples/bluetooth/hci_ipc/boards/nrf5340dk_nrf5340_cpunet.overlay`. * Make sure the same GPIO pins are assigned to Direction Finding Extension in file :zephyr_file:`samples/bluetooth/direction_finding_central/boards/nrf5340dk_nrf5340_cpuapp.overlay`. - as those in the created file :file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.overlay`. + as those in the created file :file:`samples/bluetooth/hci_ipc/boards/nrf5340dk_nrf5340_cpunet.overlay`. * Copy :zephyr_file:`samples/bluetooth/direction_finding_central/boards/nrf52833dk_nrf52833.conf` to a new file, - :file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.conf`. + :file:`samples/bluetooth/hci_ipc/boards/nrf5340dk_nrf5340_cpunet.conf`. Antenna matrix configuration **************************** @@ -69,8 +69,8 @@ this overlay. See :ref:`set-devicetree-overlays` for information on setting up and using overlays. Note that antenna matrix configuration for the nRF5340 SoC is part of the -network core application. When :ref:`bluetooth-hci-rpmsg-sample` is used as the +network core application. When :ref:`bluetooth-hci-ipc-sample` is used as the network core application, the antenna matrix configuration should be stored in the file -:file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.overlay` +:file:`samples/bluetooth/hci_ipc/boards/nrf5340dk_nrf5340_cpunet.overlay` instead. diff --git a/samples/bluetooth/direction_finding_connectionless_rx/README.rst b/samples/bluetooth/direction_finding_connectionless_rx/README.rst index b7a970acbc4..ad8416dd537 100644 --- a/samples/bluetooth/direction_finding_connectionless_rx/README.rst +++ b/samples/bluetooth/direction_finding_connectionless_rx/README.rst @@ -37,21 +37,21 @@ changing ``nrf52833dk_nrf52833`` as needed for your board: :compact: To run the application on nRF5340DK, a Bluetooth controller application must -also run on the network core. The :ref:`bluetooth-hci-rpmsg-sample` sample +also run on the network core. The :ref:`bluetooth-hci-ipc-sample` sample application may be used. To build this sample with direction finding support enabled: * Copy :zephyr_file:`samples/bluetooth/direction_finding_connectionless_rx/boards/nrf52833dk_nrf52833.overlay` to a new file, - :file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.overlay`. + :file:`samples/bluetooth/hci_ipc/boards/nrf5340dk_nrf5340_cpunet.overlay`. * Make sure the same GPIO pins are assigned to Direction Finding Extension in file :zephyr_file:`samples/bluetooth/direction_finding_connectionless_rx/boards/nrf5340dk_nrf5340_cpuapp.overlay`. - as those in the created file :file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.overlay`. + as those in the created file :file:`samples/bluetooth/hci_ipc/boards/nrf5340dk_nrf5340_cpunet.overlay`. * Copy :zephyr_file:`samples/bluetooth/direction_finding_connectionless_rx/boards/nrf52833dk_nrf52833.conf` to a new file, - :file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.conf`. Add + :file:`samples/bluetooth/hci_ipc/boards/nrf5340dk_nrf5340_cpunet.conf`. Add the line ``CONFIG_BT_EXT_ADV=y`` to enable extended size of :kconfig:option:`CONFIG_BT_BUF_CMD_TX_SIZE` to support the LE Set Extended Advertising Data command. @@ -72,8 +72,8 @@ this overlay. See :ref:`set-devicetree-overlays` for information on setting up and using overlays. Note that antenna matrix configuration for the nRF5340 SoC is part of the -network core application. When :ref:`bluetooth-hci-rpmsg-sample` is used as the +network core application. When :ref:`bluetooth-hci-ipc-sample` is used as the network core application, the antenna matrix configuration should be stored in the file -:file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.overlay` +:file:`samples/bluetooth/hci_ipc/boards/nrf5340dk_nrf5340_cpunet.overlay` instead. diff --git a/samples/bluetooth/direction_finding_connectionless_tx/README.rst b/samples/bluetooth/direction_finding_connectionless_tx/README.rst index ca27319cbc7..6fe3dd68722 100644 --- a/samples/bluetooth/direction_finding_connectionless_tx/README.rst +++ b/samples/bluetooth/direction_finding_connectionless_tx/README.rst @@ -37,21 +37,21 @@ To use Angle of Arrival mode only, build this application as follows, changing :compact: To run the application on nRF5340DK, a Bluetooth controller application must -also run on the network core. The :zephyr_file:`samples/bluetooth/hci_rpmsg` +also run on the network core. The :zephyr_file:`samples/bluetooth/hci_ipc` sample application may be used. To build this sample with direction finding support enabled: * Copy :zephyr_file:`samples/bluetooth/direction_finding_connectionless_tx/boards/nrf52833dk_nrf52833.overlay` to a new file, - :file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.overlay`. + :file:`samples/bluetooth/hci_ipc/boards/nrf5340dk_nrf5340_cpunet.overlay`. * Make sure the same GPIO pins are assigned to Direction Finding Extension in file :zephyr_file:`samples/bluetooth/direction_finding_connectionless_tx/boards/nrf5340dk_nrf5340_cpuapp.overlay`. - as those in the created file :file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.overlay`. + as those in the created file :file:`samples/bluetooth/hci_ipc/boards/nrf5340dk_nrf5340_cpunet.overlay`. * Copy :zephyr_file:`samples/bluetooth/direction_finding_connectionless_tx/boards/nrf52833dk_nrf52833.conf` to a new file, - :file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.conf`. Add + :file:`samples/bluetooth/hci_ipc/boards/nrf5340dk_nrf5340_cpunet.conf`. Add the line ``CONFIG_BT_EXT_ADV=y`` to enable extended size of :kconfig:option:`CONFIG_BT_BUF_CMD_TX_SIZE` to support the LE Set Extended Advertising Data command. @@ -73,10 +73,10 @@ this overlay. See :ref:`set-devicetree-overlays` for information on setting up and using overlays. Note that antenna matrix configuration for the nRF5340 SoC is part of the -network core application. When :ref:`bluetooth-hci-rpmsg-sample` is used as +network core application. When :ref:`bluetooth-hci-ipc-sample` is used as network core application, the antenna matrix configuration should be stored in the file -:file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.overlay` +:file:`samples/bluetooth/hci_ipc/boards/nrf5340dk_nrf5340_cpunet.overlay` instead. In addition to the devicetree configuration, to successfully use the Direction diff --git a/samples/bluetooth/direction_finding_peripheral/README.rst b/samples/bluetooth/direction_finding_peripheral/README.rst index 36846c84d6f..75cc5b9a917 100644 --- a/samples/bluetooth/direction_finding_peripheral/README.rst +++ b/samples/bluetooth/direction_finding_peripheral/README.rst @@ -36,21 +36,21 @@ changing ``nrf52833dk_nrf52833`` as needed for your board: :compact: To run the application on nRF5340DK, a Bluetooth controller application must -also run on the network core. The :ref:`bluetooth-hci-rpmsg-sample` sample +also run on the network core. The :ref:`bluetooth-hci-ipc-sample` sample application may be used. To build this sample with direction finding support enabled: * Copy :zephyr_file:`samples/bluetooth/direction_finding_peripheral/boards/nrf52833dk_nrf52833.overlay` to a new file, - :file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.overlay`. + :file:`samples/bluetooth/hci_ipc/boards/nrf5340dk_nrf5340_cpunet.overlay`. * Make sure the same GPIO pins are assigned to Direction Finding Extension in file :zephyr_file:`samples/bluetooth/direction_finding_peripheral/boards/nrf5340dk_nrf5340_cpuapp.overlay`. - as those in the created file :file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.overlay`. + as those in the created file :file:`samples/bluetooth/hci_ipc/boards/nrf5340dk_nrf5340_cpunet.overlay`. * Copy :zephyr_file:`samples/bluetooth/direction_finding_peripheral/boards/nrf52833dk_nrf52833.conf` to a new file, - :file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.conf`. + :file:`samples/bluetooth/hci_ipc/boards/nrf5340dk_nrf5340_cpunet.conf`. Antenna matrix configuration **************************** @@ -68,8 +68,8 @@ this overlay. See :ref:`set-devicetree-overlays` for information on setting up and using overlays. Note that antenna matrix configuration for the nRF5340 SoC is part of the -network core application. When :ref:`bluetooth-hci-rpmsg-sample` is used as the +network core application. When :ref:`bluetooth-hci-ipc-sample` is used as the network core application, the antenna matrix configuration should be stored in the file -:file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.overlay` +:file:`samples/bluetooth/hci_ipc/boards/nrf5340dk_nrf5340_cpunet.overlay` instead. diff --git a/samples/bluetooth/encrypted_advertising/README.rst b/samples/bluetooth/encrypted_advertising/README.rst index 170fcbfaab5..5c107d8a634 100644 --- a/samples/bluetooth/encrypted_advertising/README.rst +++ b/samples/bluetooth/encrypted_advertising/README.rst @@ -25,8 +25,8 @@ Requirements ************ * Two boards with Bluetooth Low Energy support -* Two boards with a push button connected via a GPIO pin, see :ref:`Button - sample ` for more details +* Two boards with a push button connected via a GPIO pin, see the :zephyr:code-sample:`button` + sample for more details Building and Running ******************** diff --git a/samples/bluetooth/hap_ha/boards/native_sim.conf b/samples/bluetooth/hap_ha/boards/native_sim.conf new file mode 100644 index 00000000000..abce1c1111e --- /dev/null +++ b/samples/bluetooth/hap_ha/boards/native_sim.conf @@ -0,0 +1,7 @@ +CONFIG_LOG_MODE_IMMEDIATE=y +CONFIG_BT_TINYCRYPT_ECC=y + +# For LE-audio at 10ms intervals we need the tick counter to occur more frequently +# than every 10 ms as each PDU for some reason takes 2 ticks to process. +CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 +CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME=y diff --git a/samples/bluetooth/hap_ha/prj.conf b/samples/bluetooth/hap_ha/prj.conf index 179b5a5f4d7..ca019bbafb4 100644 --- a/samples/bluetooth/hap_ha/prj.conf +++ b/samples/bluetooth/hap_ha/prj.conf @@ -21,11 +21,6 @@ CONFIG_BT_ASCS_ASE_SRC_COUNT=1 # Support an ISO channel per ASE CONFIG_BT_ISO_MAX_CHAN=2 -# Sink Contexts Supported: Unspecified, Conversational, Media, Live -CONFIG_BT_PACS_SNK_CONTEXT=0x0047 -# Source Contexts Supported: Unspecified, Conversational -CONFIG_BT_PACS_SRC_CONTEXT=0x0003 - CONFIG_BT_PAC_SNK_LOC=y CONFIG_BT_PAC_SRC_LOC=y diff --git a/samples/bluetooth/hap_ha/sample.yaml b/samples/bluetooth/hap_ha/sample.yaml index c9fcfda90ca..3b0fcd53a51 100644 --- a/samples/bluetooth/hap_ha/sample.yaml +++ b/samples/bluetooth/hap_ha/sample.yaml @@ -4,25 +4,33 @@ sample: tests: sample.bluetooth.hap_ha.monaural: harness: bluetooth - platform_allow: native_posix + platform_allow: + - native_posix + - native_sim tags: bluetooth build_only: true sample.bluetooth.hap_ha.monaural_no_presets: harness: bluetooth - platform_allow: native_posix + platform_allow: + - native_posix + - native_sim tags: bluetooth build_only: true extra_configs: - CONFIG_BT_HAS_PRESET_COUNT=0 sample.bluetooth.hap_ha.banded: harness: bluetooth - platform_allow: native_posix + platform_allow: + - native_posix + - native_sim tags: bluetooth extra_args: OVERLAY_CONFIG="banded.conf" build_only: true sample.bluetooth.hap_ha.binaural: harness: bluetooth - platform_allow: native_posix + platform_allow: + - native_posix + - native_sim tags: bluetooth extra_args: OVERLAY_CONFIG="binaural.conf" build_only: true diff --git a/samples/bluetooth/hap_ha/src/bap_unicast_sr.c b/samples/bluetooth/hap_ha/src/bap_unicast_sr.c index 8db83b2ef2d..1eca1fd25c2 100644 --- a/samples/bluetooth/hap_ha/src/bap_unicast_sr.c +++ b/samples/bluetooth/hap_ha/src/bap_unicast_sr.c @@ -74,17 +74,26 @@ static void print_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg) printk("codec_cfg 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cfg->id, codec_cfg->cid, codec_cfg->vid, codec_cfg->data_len); - if (codec_cfg->id == BT_AUDIO_CODEC_LC3_ID) { - /* LC3 uses the generic LTV format - other codecs might do as well */ - + if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) { enum bt_audio_location chan_allocation; + int ret; + + /* LC3 uses the generic LTV format - other codecs might do as well */ bt_audio_data_parse(codec_cfg->data, codec_cfg->data_len, print_cb, "data"); - printk(" Frequency: %d Hz\n", bt_audio_codec_cfg_get_freq(codec_cfg)); - printk(" Frame Duration: %d us\n", - bt_audio_codec_cfg_get_frame_duration_us(codec_cfg)); - if (bt_audio_codec_cfg_get_chan_allocation_val(codec_cfg, &chan_allocation) == 0) { + ret = bt_audio_codec_cfg_get_freq(codec_cfg); + if (ret > 0) { + printk(" Frequency: %d Hz\n", bt_audio_codec_cfg_freq_to_freq_hz(ret)); + } + + ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg); + if (ret > 0) { + printk(" Frame Duration: %d us\n", + bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret)); + } + + if (bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &chan_allocation) == 0) { printk(" Channel allocation: 0x%x\n", chan_allocation); } diff --git a/samples/bluetooth/hap_ha/src/main.c b/samples/bluetooth/hap_ha/src/main.c index 1ce47508c36..9c57bbefbcb 100644 --- a/samples/bluetooth/hap_ha/src/main.c +++ b/samples/bluetooth/hap_ha/src/main.c @@ -24,11 +24,8 @@ BT_AUDIO_CONTEXT_TYPE_MEDIA | \ BT_AUDIO_CONTEXT_TYPE_LIVE) -#define AVAILABLE_SINK_CONTEXT CONFIG_BT_PACS_SNK_CONTEXT -#define AVAILABLE_SOURCE_CONTEXT CONFIG_BT_PACS_SRC_CONTEXT - -BUILD_ASSERT((CONFIG_BT_PACS_SNK_CONTEXT & MANDATORY_SINK_CONTEXT) == MANDATORY_SINK_CONTEXT, - "Need to support mandatory Supported_Sink_Contexts"); +#define AVAILABLE_SINK_CONTEXT MANDATORY_SINK_CONTEXT +#define AVAILABLE_SOURCE_CONTEXT MANDATORY_SINK_CONTEXT static uint8_t unicast_server_addata[] = { BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL), /* ASCS UUID */ diff --git a/samples/bluetooth/hci_ipc/CMakeLists.txt b/samples/bluetooth/hci_ipc/CMakeLists.txt new file mode 100644 index 00000000000..02ff09719d7 --- /dev/null +++ b/samples/bluetooth/hci_ipc/CMakeLists.txt @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(hci_ipc) + +target_sources(app PRIVATE src/main.c) + +# Remove after 3.7.0 is released +dt_chosen(chosen_hci_rpmsg PROPERTY "zephyr,bt-hci-rpmsg-ipc") +if(DEFINED chosen_hci_rpmsg) + message(FATAL_ERROR "zephyr,bt-hci-rpmsg-ipc has been renamed to zephyr,bt-hci-ipc") +endif() diff --git a/samples/bluetooth/hci_ipc/README.rst b/samples/bluetooth/hci_ipc/README.rst new file mode 100644 index 00000000000..605898d7220 --- /dev/null +++ b/samples/bluetooth/hci_ipc/README.rst @@ -0,0 +1,39 @@ +.. _bluetooth-hci-ipc-sample: + +Bluetooth: HCI IPC +################## + +Overview +******** + +This sample exposes :ref:`bluetooth_controller` support +to another device or CPU using IPC subsystem. + +Requirements +************ + +* A board with IPC subsystem and Bluetooth LE support + +Building and Running +******************** + +This sample can be found under :zephyr_file:`samples/bluetooth/hci_ipc` +in the Zephyr tree. + +To use this application, you need a board with a Bluetooth controller +and IPC support. +You can then build this application and flash it onto your board in +the usual way. See :ref:`boards` for board-specific building and +programming information. + +To test this sample, you need a separate device/CPU that acts as Bluetooth +HCI IPC peer. +This sample is compatible with the HCI IPC driver provided by +Zephyr's Bluetooth :ref:`bt_hci_drivers` core. See the +:kconfig:option:`CONFIG_BT_HCI_IPC` configuration option for more information. + +You might need to adjust the Kconfig configuration of this sample to make it +compatible with the peer application. For example, :kconfig:option:`CONFIG_BT_MAX_CONN` +must be equal to the maximum number of connections supported by the peer application. + +Refer to :ref:`bluetooth-samples` for general information about Bluetooth samples. diff --git a/samples/bluetooth/hci_rpmsg/debug_overlay.conf b/samples/bluetooth/hci_ipc/debug_overlay.conf similarity index 100% rename from samples/bluetooth/hci_rpmsg/debug_overlay.conf rename to samples/bluetooth/hci_ipc/debug_overlay.conf diff --git a/samples/bluetooth/hci_rpmsg/dts/arm/nordic/override.dtsi b/samples/bluetooth/hci_ipc/dts/arm/nordic/override.dtsi similarity index 100% rename from samples/bluetooth/hci_rpmsg/dts/arm/nordic/override.dtsi rename to samples/bluetooth/hci_ipc/dts/arm/nordic/override.dtsi diff --git a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_bis-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_bis-bt_ll_sw_split.conf similarity index 100% rename from samples/bluetooth/hci_rpmsg/nrf5340_cpunet_bis-bt_ll_sw_split.conf rename to samples/bluetooth/hci_ipc/nrf5340_cpunet_bis-bt_ll_sw_split.conf diff --git a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf similarity index 100% rename from samples/bluetooth/hci_rpmsg/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf rename to samples/bluetooth/hci_ipc/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf diff --git a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_cis-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_cis-bt_ll_sw_split.conf similarity index 100% rename from samples/bluetooth/hci_rpmsg/nrf5340_cpunet_cis-bt_ll_sw_split.conf rename to samples/bluetooth/hci_ipc/nrf5340_cpunet_cis-bt_ll_sw_split.conf diff --git a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_df-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_df-bt_ll_sw_split.conf similarity index 100% rename from samples/bluetooth/hci_rpmsg/nrf5340_cpunet_df-bt_ll_sw_split.conf rename to samples/bluetooth/hci_ipc/nrf5340_cpunet_df-bt_ll_sw_split.conf diff --git a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_df-bt_ll_sw_split.overlay b/samples/bluetooth/hci_ipc/nrf5340_cpunet_df-bt_ll_sw_split.overlay similarity index 100% rename from samples/bluetooth/hci_rpmsg/nrf5340_cpunet_df-bt_ll_sw_split.overlay rename to samples/bluetooth/hci_ipc/nrf5340_cpunet_df-bt_ll_sw_split.overlay diff --git a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf similarity index 100% rename from samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso-bt_ll_sw_split.conf rename to samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf diff --git a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf similarity index 100% rename from samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf rename to samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf diff --git a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf similarity index 100% rename from samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf rename to samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf diff --git a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf similarity index 100% rename from samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf rename to samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf diff --git a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_receive-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_receive-bt_ll_sw_split.conf similarity index 100% rename from samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_receive-bt_ll_sw_split.conf rename to samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_receive-bt_ll_sw_split.conf diff --git a/samples/bluetooth/hci_rpmsg/prj.conf b/samples/bluetooth/hci_ipc/prj.conf similarity index 100% rename from samples/bluetooth/hci_rpmsg/prj.conf rename to samples/bluetooth/hci_ipc/prj.conf diff --git a/samples/bluetooth/hci_ipc/sample.yaml b/samples/bluetooth/hci_ipc/sample.yaml new file mode 100644 index 00000000000..e05a5d384d2 --- /dev/null +++ b/samples/bluetooth/hci_ipc/sample.yaml @@ -0,0 +1,110 @@ +sample: + description: Allows Zephyr to provide Bluetooth connectivity via IPC + name: Bluetooth HCI IPC +tests: + sample.bluetooth.hci_ipc: + harness: bluetooth + tags: bluetooth + platform_allow: + - nrf5340dk_nrf5340_cpunet + - nrf5340_audio_dk_nrf5340_cpunet + - nrf5340bsim_nrf5340_cpunet + integration_platforms: + - nrf5340dk_nrf5340_cpunet + - nrf5340_audio_dk_nrf5340_cpunet + sample.bluetooth.hci_ipc.iso_broadcast.bt_ll_sw_split: + harness: bluetooth + tags: bluetooth + extra_args: CONF_FILE="nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf" + platform_allow: + - nrf5340dk_nrf5340_cpunet + - nrf5340_audio_dk_nrf5340_cpunet + - nrf5340bsim_nrf5340_cpunet + integration_platforms: + - nrf5340dk_nrf5340_cpunet + - nrf5340_audio_dk_nrf5340_cpunet + sample.bluetooth.hci_ipc.iso_receive.bt_ll_sw_split: + harness: bluetooth + tags: bluetooth + extra_args: CONF_FILE="nrf5340_cpunet_iso_receive-bt_ll_sw_split.conf" + platform_allow: + - nrf5340dk_nrf5340_cpunet + - nrf5340_audio_dk_nrf5340_cpunet + - nrf5340bsim_nrf5340_cpunet + integration_platforms: + - nrf5340dk_nrf5340_cpunet + sample.bluetooth.hci_ipc.bis.bt_ll_sw_split: + harness: bluetooth + tags: bluetooth + extra_args: CONF_FILE="nrf5340_cpunet_bis-bt_ll_sw_split.conf" + platform_allow: + - nrf5340dk_nrf5340_cpunet + - nrf5340_audio_dk_nrf5340_cpunet + - nrf5340bsim_nrf5340_cpunet + integration_platforms: + - nrf5340dk_nrf5340_cpunet + sample.bluetooth.hci_ipc.iso_central.bt_ll_sw_split: + harness: bluetooth + tags: bluetooth + extra_args: CONF_FILE="nrf5340_cpunet_iso_central-bt_ll_sw_split.conf" + platform_allow: + - nrf5340dk_nrf5340_cpunet + - nrf5340_audio_dk_nrf5340_cpunet + - nrf5340bsim_nrf5340_cpunet + integration_platforms: + - nrf5340dk_nrf5340_cpunet + sample.bluetooth.hci_ipc.iso_peripheral.bt_ll_sw_split: + harness: bluetooth + tags: bluetooth + extra_args: CONF_FILE="nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf" + platform_allow: + - nrf5340dk_nrf5340_cpunet + - nrf5340_audio_dk_nrf5340_cpunet + - nrf5340bsim_nrf5340_cpunet + integration_platforms: + - nrf5340dk_nrf5340_cpunet + sample.bluetooth.hci_ipc.cis.bt_ll_sw_split: + harness: bluetooth + tags: bluetooth + extra_args: CONF_FILE="nrf5340_cpunet_cis-bt_ll_sw_split.conf" + platform_allow: + - nrf5340dk_nrf5340_cpunet + - nrf5340_audio_dk_nrf5340_cpunet + - nrf5340bsim_nrf5340_cpunet + integration_platforms: + - nrf5340dk_nrf5340_cpunet + sample.bluetooth.hci_ipc.iso.bt_ll_sw_split: + harness: bluetooth + tags: bluetooth + extra_args: CONF_FILE="nrf5340_cpunet_iso-bt_ll_sw_split.conf" + platform_allow: + - nrf5340dk_nrf5340_cpunet + - nrf5340bsim_nrf5340_cpunet + integration_platforms: + - nrf5340dk_nrf5340_cpunet + sample.bluetooth.hci_ipc.df.bt_ll_sw_split: + harness: bluetooth + tags: bluetooth + extra_args: + - CONF_FILE="nrf5340_cpunet_df-bt_ll_sw_split.conf" + - DTC_OVERLAY_FILE="nrf5340_cpunet_df-bt_ll_sw_split.overlay" + platform_allow: nrf5340dk_nrf5340_cpunet + integration_platforms: + - nrf5340dk_nrf5340_cpunet + sample.bluetooth.hci_ipc.df.no_phy_coded.bt_ll_sw_split: + harness: bluetooth + tags: bluetooth + extra_args: + - CONF_FILE="nrf5340_cpunet_df-bt_ll_sw_split.conf" + - DTC_OVERLAY_FILE="nrf5340_cpunet_df-bt_ll_sw_split.overlay" + - CONFIG_BT_CTLR_PHY_CODED=n + platform_allow: nrf5340dk_nrf5340_cpunet + integration_platforms: + - nrf5340dk_nrf5340_cpunet + sample.bluetooth.hci_ipc.mesh.bt_ll_sw_split: + harness: bluetooth + tags: bluetooth + extra_args: CONF_FILE="nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf" + platform_allow: nrf5340dk_nrf5340_cpunet + integration_platforms: + - nrf5340dk_nrf5340_cpunet diff --git a/samples/bluetooth/hci_ipc/src/main.c b/samples/bluetooth/hci_ipc/src/main.c new file mode 100644 index 00000000000..5f0614139be --- /dev/null +++ b/samples/bluetooth/hci_ipc/src/main.c @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2019-2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +LOG_MODULE_REGISTER(hci_ipc, CONFIG_BT_LOG_LEVEL); + +static struct ipc_ept hci_ept; + +static K_THREAD_STACK_DEFINE(tx_thread_stack, CONFIG_BT_HCI_TX_STACK_SIZE); +static struct k_thread tx_thread_data; +static K_FIFO_DEFINE(tx_queue); +static K_SEM_DEFINE(ipc_bound_sem, 0, 1); +#if defined(CONFIG_BT_CTLR_ASSERT_HANDLER) || defined(CONFIG_BT_HCI_VS_FATAL_ERROR) +/* A flag used to store information if the IPC endpoint has already been bound. The end point can't + * be used before that happens. + */ +static bool ipc_ept_ready; +#endif /* CONFIG_BT_CTLR_ASSERT_HANDLER || CONFIG_BT_HCI_VS_FATAL_ERROR */ + +#define HCI_IPC_CMD 0x01 +#define HCI_IPC_ACL 0x02 +#define HCI_IPC_SCO 0x03 +#define HCI_IPC_EVT 0x04 +#define HCI_IPC_ISO 0x05 + +#define HCI_FATAL_ERR_MSG true +#define HCI_REGULAR_MSG false + +static struct net_buf *hci_ipc_cmd_recv(uint8_t *data, size_t remaining) +{ + struct bt_hci_cmd_hdr *hdr = (void *)data; + struct net_buf *buf; + + if (remaining < sizeof(*hdr)) { + LOG_ERR("Not enough data for command header"); + return NULL; + } + + buf = bt_buf_get_tx(BT_BUF_CMD, K_NO_WAIT, hdr, sizeof(*hdr)); + if (buf) { + data += sizeof(*hdr); + remaining -= sizeof(*hdr); + } else { + LOG_ERR("No available command buffers!"); + return NULL; + } + + if (remaining != hdr->param_len) { + LOG_ERR("Command payload length is not correct"); + net_buf_unref(buf); + return NULL; + } + + if (remaining > net_buf_tailroom(buf)) { + LOG_ERR("Not enough space in buffer"); + net_buf_unref(buf); + return NULL; + } + + LOG_DBG("len %u", hdr->param_len); + net_buf_add_mem(buf, data, remaining); + + return buf; +} + +static struct net_buf *hci_ipc_acl_recv(uint8_t *data, size_t remaining) +{ + struct bt_hci_acl_hdr *hdr = (void *)data; + struct net_buf *buf; + + if (remaining < sizeof(*hdr)) { + LOG_ERR("Not enough data for ACL header"); + return NULL; + } + + buf = bt_buf_get_tx(BT_BUF_ACL_OUT, K_NO_WAIT, hdr, sizeof(*hdr)); + if (buf) { + data += sizeof(*hdr); + remaining -= sizeof(*hdr); + } else { + LOG_ERR("No available ACL buffers!"); + return NULL; + } + + if (remaining != sys_le16_to_cpu(hdr->len)) { + LOG_ERR("ACL payload length is not correct"); + net_buf_unref(buf); + return NULL; + } + + if (remaining > net_buf_tailroom(buf)) { + LOG_ERR("Not enough space in buffer"); + net_buf_unref(buf); + return NULL; + } + + LOG_DBG("len %u", remaining); + net_buf_add_mem(buf, data, remaining); + + return buf; +} + +static struct net_buf *hci_ipc_iso_recv(uint8_t *data, size_t remaining) +{ + struct bt_hci_iso_hdr *hdr = (void *)data; + struct net_buf *buf; + + if (remaining < sizeof(*hdr)) { + LOG_ERR("Not enough data for ISO header"); + return NULL; + } + + buf = bt_buf_get_tx(BT_BUF_ISO_OUT, K_NO_WAIT, hdr, sizeof(*hdr)); + if (buf) { + data += sizeof(*hdr); + remaining -= sizeof(*hdr); + } else { + LOG_ERR("No available ISO buffers!"); + return NULL; + } + + if (remaining != bt_iso_hdr_len(sys_le16_to_cpu(hdr->len))) { + LOG_ERR("ISO payload length is not correct"); + net_buf_unref(buf); + return NULL; + } + + if (remaining > net_buf_tailroom(buf)) { + LOG_ERR("Not enough space in buffer"); + net_buf_unref(buf); + return NULL; + } + + LOG_DBG("len %zu", remaining); + net_buf_add_mem(buf, data, remaining); + + return buf; +} + +static void hci_ipc_rx(uint8_t *data, size_t len) +{ + uint8_t pkt_indicator; + struct net_buf *buf = NULL; + size_t remaining = len; + + LOG_HEXDUMP_DBG(data, len, "IPC data:"); + + pkt_indicator = *data++; + remaining -= sizeof(pkt_indicator); + + switch (pkt_indicator) { + case HCI_IPC_CMD: + buf = hci_ipc_cmd_recv(data, remaining); + break; + + case HCI_IPC_ACL: + buf = hci_ipc_acl_recv(data, remaining); + break; + + case HCI_IPC_ISO: + buf = hci_ipc_iso_recv(data, remaining); + break; + + default: + LOG_ERR("Unknown HCI type %u", pkt_indicator); + return; + } + + if (buf) { + net_buf_put(&tx_queue, buf); + + LOG_HEXDUMP_DBG(buf->data, buf->len, "Final net buffer:"); + } +} + +static void tx_thread(void *p1, void *p2, void *p3) +{ + while (1) { + struct net_buf *buf; + int err; + + /* Wait until a buffer is available */ + buf = net_buf_get(&tx_queue, K_FOREVER); + /* Pass buffer to the stack */ + err = bt_send(buf); + if (err) { + LOG_ERR("Unable to send (err %d)", err); + net_buf_unref(buf); + } + + /* Give other threads a chance to run if tx_queue keeps getting + * new data all the time. + */ + k_yield(); + } +} + +static void hci_ipc_send(struct net_buf *buf, bool is_fatal_err) +{ + uint8_t pkt_indicator; + uint8_t retries = 0; + int ret; + + LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len); + + LOG_HEXDUMP_DBG(buf->data, buf->len, "Controller buffer:"); + + switch (bt_buf_get_type(buf)) { + case BT_BUF_ACL_IN: + pkt_indicator = HCI_IPC_ACL; + break; + case BT_BUF_EVT: + pkt_indicator = HCI_IPC_EVT; + break; + case BT_BUF_ISO_IN: + pkt_indicator = HCI_IPC_ISO; + break; + default: + LOG_ERR("Unknown type %u", bt_buf_get_type(buf)); + net_buf_unref(buf); + return; + } + net_buf_push_u8(buf, pkt_indicator); + + LOG_HEXDUMP_DBG(buf->data, buf->len, "Final HCI buffer:"); + + do { + ret = ipc_service_send(&hci_ept, buf->data, buf->len); + if (ret < 0) { + retries++; + if (retries > 10) { + /* Default backend (rpmsg_virtio) has a timeout of 150ms. */ + LOG_WRN("IPC send has been blocked for 1.5 seconds."); + retries = 0; + } + + /* The function can be called by the application main thread, + * bt_ctlr_assert_handle and k_sys_fatal_error_handler. In case of a call by + * Bluetooth Controller assert handler or system fatal error handler the + * call can be from ISR context, hence there is no thread to yield. Besides + * that both handlers implement a policy to provide error information and + * stop the system in an infinite loop. The goal is to prevent any other + * damage to the system if one of such exeptional situations occur, hence + * call to k_yield is against it. + */ + if (is_fatal_err) { + LOG_ERR("IPC service send error: %d", ret); + } else { + k_yield(); + } + } + } while (ret < 0); + + LOG_INF("Sent message of %d bytes.", ret); + + net_buf_unref(buf); +} + +#if defined(CONFIG_BT_CTLR_ASSERT_HANDLER) +void bt_ctlr_assert_handle(char *file, uint32_t line) +{ + /* Disable interrupts, this is unrecoverable */ + (void)irq_lock(); + +#if defined(CONFIG_BT_HCI_VS_FATAL_ERROR) + /* Generate an error event only when IPC service endpoint is already bound. */ + if (ipc_ept_ready) { + /* Prepare vendor specific HCI debug event */ + struct net_buf *buf; + + buf = hci_vs_err_assert(file, line); + if (buf == NULL) { + /* Send the event over ipc */ + hci_ipc_send(buf, HCI_FATAL_ERR_MSG); + } else { + LOG_ERR("Can't create Fatal Error HCI event: %s at %d", __FILE__, __LINE__); + } + } else { + LOG_ERR("IPC endpoint is not ready yet: %s at %d", __FILE__, __LINE__); + } + + LOG_ERR("Halting system"); + +#else /* !CONFIG_BT_HCI_VS_FATAL_ERROR */ + LOG_ERR("Controller assert in: %s at %d", file, line); + +#endif /* !CONFIG_BT_HCI_VS_FATAL_ERROR */ + + /* Flush the logs before locking the CPU */ + LOG_PANIC(); + + while (true) { + }; +} +#endif /* CONFIG_BT_CTLR_ASSERT_HANDLER */ + +#if defined(CONFIG_BT_HCI_VS_FATAL_ERROR) +void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *esf) +{ + /* Disable interrupts, this is unrecoverable */ + (void)irq_lock(); + + /* Generate an error event only when there is a stack frame and IPC service endpoint is + * already bound. + */ + if (esf != NULL && ipc_ept_ready) { + /* Prepare vendor specific HCI debug event */ + struct net_buf *buf; + + buf = hci_vs_err_stack_frame(reason, esf); + if (buf != NULL) { + hci_ipc_send(buf, HCI_FATAL_ERR_MSG); + } else { + LOG_ERR("Can't create Fatal Error HCI event.\n"); + } + } + + LOG_ERR("Halting system"); + + /* Flush the logs before locking the CPU */ + LOG_PANIC(); + + while (true) { + }; + + CODE_UNREACHABLE; +} +#endif /* CONFIG_BT_HCI_VS_FATAL_ERROR */ + +static void hci_ept_bound(void *priv) +{ + k_sem_give(&ipc_bound_sem); +#if defined(CONFIG_BT_CTLR_ASSERT_HANDLER) || defined(CONFIG_BT_HCI_VS_FATAL_ERROR) + ipc_ept_ready = true; +#endif /* CONFIG_BT_CTLR_ASSERT_HANDLER || CONFIG_BT_HCI_VS_FATAL_ERROR */ +} + +static void hci_ept_recv(const void *data, size_t len, void *priv) +{ + LOG_INF("Received message of %u bytes.", len); + hci_ipc_rx((uint8_t *) data, len); +} + +static struct ipc_ept_cfg hci_ept_cfg = { + .name = "nrf_bt_hci", + .cb = { + .bound = hci_ept_bound, + .received = hci_ept_recv, + }, +}; + +int main(void) +{ + int err; + const struct device *hci_ipc_instance = + DEVICE_DT_GET(DT_CHOSEN(zephyr_bt_hci_ipc)); + + /* incoming events and data from the controller */ + static K_FIFO_DEFINE(rx_queue); + + LOG_DBG("Start"); + + /* Enable the raw interface, this will in turn open the HCI driver */ + bt_enable_raw(&rx_queue); + + /* Spawn the TX thread and start feeding commands and data to the + * controller + */ + k_thread_create(&tx_thread_data, tx_thread_stack, + K_THREAD_STACK_SIZEOF(tx_thread_stack), tx_thread, + NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); + k_thread_name_set(&tx_thread_data, "HCI ipc TX"); + + /* Initialize IPC service instance and register endpoint. */ + err = ipc_service_open_instance(hci_ipc_instance); + if (err < 0 && err != -EALREADY) { + LOG_ERR("IPC service instance initialization failed: %d\n", err); + } + + err = ipc_service_register_endpoint(hci_ipc_instance, &hci_ept, &hci_ept_cfg); + if (err) { + LOG_ERR("Registering endpoint failed with %d", err); + } + + k_sem_take(&ipc_bound_sem, K_FOREVER); + + while (1) { + struct net_buf *buf; + + buf = net_buf_get(&rx_queue, K_FOREVER); + hci_ipc_send(buf, HCI_REGULAR_MSG); + } + return 0; +} diff --git a/samples/bluetooth/hci_rpmsg/CMakeLists.txt b/samples/bluetooth/hci_rpmsg/CMakeLists.txt deleted file mode 100644 index 11dd731c285..00000000000 --- a/samples/bluetooth/hci_rpmsg/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) - -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(hci_rpmsg) - -target_sources(app PRIVATE src/main.c) diff --git a/samples/bluetooth/hci_rpmsg/README.rst b/samples/bluetooth/hci_rpmsg/README.rst deleted file mode 100644 index 8d0cc704bfa..00000000000 --- a/samples/bluetooth/hci_rpmsg/README.rst +++ /dev/null @@ -1,40 +0,0 @@ -.. _bluetooth-hci-rpmsg-sample: - -Bluetooth: HCI RPMsg -#################### - -Overview -******** - -This sample exposes :ref:`bluetooth_controller` support -to another device or CPU using RPMsg transport which is -a part of `OpenAMP `__. - -Requirements -************ - -* A board with :ref:`ipm_api` driver and Bluetooth LE support - -Building and Running -******************** - -This sample can be found under :zephyr_file:`samples/bluetooth/hci_rpmsg` -in the Zephyr tree. - -To use this application, you need a board with a Bluetooth controller -and IPM drivers. -You can then build this application and flash it onto your board in -the usual way. See :ref:`boards` for board-specific building and -programming information. - -To test this sample, you need a separate device/CPU that acts as Bluetooth -HCI RPMsg peer. -This sample is compatible with the HCI RPMsg driver provided by -Zephyr's Bluetooth :ref:`bt_hci_drivers` core. See the -:kconfig:option:`CONFIG_BT_RPMSG` configuration option for more information. - -You might need to adjust the Kconfig configuration of this sample to make it -compatible with the peer application. For example, :kconfig:option:`CONFIG_BT_MAX_CONN` -must be equal to the maximum number of connections supported by the peer application. - -Refer to :ref:`bluetooth-samples` for general information about Bluetooth samples. diff --git a/samples/bluetooth/hci_rpmsg/sample.yaml b/samples/bluetooth/hci_rpmsg/sample.yaml deleted file mode 100644 index 7cecb12be67..00000000000 --- a/samples/bluetooth/hci_rpmsg/sample.yaml +++ /dev/null @@ -1,101 +0,0 @@ -sample: - description: Allows Zephyr to provide Bluetooth connectivity via RPMsg. - name: Bluetooth HCI RPMsg -tests: - sample.bluetooth.hci_rpmsg: - harness: bluetooth - tags: bluetooth - platform_allow: - - nrf5340dk_nrf5340_cpunet - - nrf5340_audio_dk_nrf5340_cpunet - integration_platforms: - - nrf5340dk_nrf5340_cpunet - - nrf5340_audio_dk_nrf5340_cpunet - sample.bluetooth.hci_rpmsg.iso_broadcast.bt_ll_sw_split: - harness: bluetooth - tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf" - platform_allow: - - nrf5340dk_nrf5340_cpunet - - nrf5340_audio_dk_nrf5340_cpunet - integration_platforms: - - nrf5340dk_nrf5340_cpunet - - nrf5340_audio_dk_nrf5340_cpunet - sample.bluetooth.hci_rpmsg.iso_receive.bt_ll_sw_split: - harness: bluetooth - tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_iso_receive-bt_ll_sw_split.conf" - platform_allow: - - nrf5340dk_nrf5340_cpunet - - nrf5340_audio_dk_nrf5340_cpunet - integration_platforms: - - nrf5340dk_nrf5340_cpunet - sample.bluetooth.hci_rpmsg.bis.bt_ll_sw_split: - harness: bluetooth - tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_bis-bt_ll_sw_split.conf" - platform_allow: - - nrf5340dk_nrf5340_cpunet - - nrf5340_audio_dk_nrf5340_cpunet - integration_platforms: - - nrf5340dk_nrf5340_cpunet - sample.bluetooth.hci_rpmsg.iso_central.bt_ll_sw_split: - harness: bluetooth - tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_iso_central-bt_ll_sw_split.conf" - platform_allow: - - nrf5340dk_nrf5340_cpunet - - nrf5340_audio_dk_nrf5340_cpunet - integration_platforms: - - nrf5340dk_nrf5340_cpunet - sample.bluetooth.hci_rpmsg.iso_peripheral.bt_ll_sw_split: - harness: bluetooth - tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf" - platform_allow: - - nrf5340dk_nrf5340_cpunet - - nrf5340_audio_dk_nrf5340_cpunet - integration_platforms: - - nrf5340dk_nrf5340_cpunet - sample.bluetooth.hci_rpmsg.cis.bt_ll_sw_split: - harness: bluetooth - tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_cis-bt_ll_sw_split.conf" - platform_allow: - - nrf5340dk_nrf5340_cpunet - - nrf5340_audio_dk_nrf5340_cpunet - integration_platforms: - - nrf5340dk_nrf5340_cpunet - sample.bluetooth.hci_rpmsg.iso.bt_ll_sw_split: - harness: bluetooth - tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_iso-bt_ll_sw_split.conf" - platform_allow: nrf5340dk_nrf5340_cpunet - integration_platforms: - - nrf5340dk_nrf5340_cpunet - sample.bluetooth.hci_rpmsg.df.bt_ll_sw_split: - harness: bluetooth - tags: bluetooth - extra_args: - - CONF_FILE="nrf5340_cpunet_df-bt_ll_sw_split.conf" - - DTC_OVERLAY_FILE="nrf5340_cpunet_df-bt_ll_sw_split.overlay" - platform_allow: nrf5340dk_nrf5340_cpunet - integration_platforms: - - nrf5340dk_nrf5340_cpunet - sample.bluetooth.hci_rpmsg.df.no_phy_coded.bt_ll_sw_split: - harness: bluetooth - tags: bluetooth - extra_args: - - CONF_FILE="nrf5340_cpunet_df-bt_ll_sw_split.conf" - - DTC_OVERLAY_FILE="nrf5340_cpunet_df-bt_ll_sw_split.overlay" - - CONFIG_BT_CTLR_PHY_CODED=n - platform_allow: nrf5340dk_nrf5340_cpunet - integration_platforms: - - nrf5340dk_nrf5340_cpunet - sample.bluetooth.hci_rpmsg.mesh.bt_ll_sw_split: - harness: bluetooth - tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf" - platform_allow: nrf5340dk_nrf5340_cpunet - integration_platforms: - - nrf5340dk_nrf5340_cpunet diff --git a/samples/bluetooth/hci_rpmsg/src/main.c b/samples/bluetooth/hci_rpmsg/src/main.c deleted file mode 100644 index 32c4616cc79..00000000000 --- a/samples/bluetooth/hci_rpmsg/src/main.c +++ /dev/null @@ -1,419 +0,0 @@ -/* - * Copyright (c) 2019-2021 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -LOG_MODULE_REGISTER(hci_rpmsg, CONFIG_BT_LOG_LEVEL); - -static struct ipc_ept hci_ept; - -static K_THREAD_STACK_DEFINE(tx_thread_stack, CONFIG_BT_HCI_TX_STACK_SIZE); -static struct k_thread tx_thread_data; -static K_FIFO_DEFINE(tx_queue); -static K_SEM_DEFINE(ipc_bound_sem, 0, 1); -#if defined(CONFIG_BT_CTLR_ASSERT_HANDLER) || defined(CONFIG_BT_HCI_VS_FATAL_ERROR) -/* A flag used to store information if the IPC endpoint has already been bound. The end point can't - * be used before that happens. - */ -static bool ipc_ept_ready; -#endif /* CONFIG_BT_CTLR_ASSERT_HANDLER || CONFIG_BT_HCI_VS_FATAL_ERROR */ - -#define HCI_RPMSG_CMD 0x01 -#define HCI_RPMSG_ACL 0x02 -#define HCI_RPMSG_SCO 0x03 -#define HCI_RPMSG_EVT 0x04 -#define HCI_RPMSG_ISO 0x05 - -#define HCI_FATAL_ERR_MSG true -#define HCI_REGULAR_MSG false - -static struct net_buf *hci_rpmsg_cmd_recv(uint8_t *data, size_t remaining) -{ - struct bt_hci_cmd_hdr *hdr = (void *)data; - struct net_buf *buf; - - if (remaining < sizeof(*hdr)) { - LOG_ERR("Not enough data for command header"); - return NULL; - } - - buf = bt_buf_get_tx(BT_BUF_CMD, K_NO_WAIT, hdr, sizeof(*hdr)); - if (buf) { - data += sizeof(*hdr); - remaining -= sizeof(*hdr); - } else { - LOG_ERR("No available command buffers!"); - return NULL; - } - - if (remaining != hdr->param_len) { - LOG_ERR("Command payload length is not correct"); - net_buf_unref(buf); - return NULL; - } - - if (remaining > net_buf_tailroom(buf)) { - LOG_ERR("Not enough space in buffer"); - net_buf_unref(buf); - return NULL; - } - - LOG_DBG("len %u", hdr->param_len); - net_buf_add_mem(buf, data, remaining); - - return buf; -} - -static struct net_buf *hci_rpmsg_acl_recv(uint8_t *data, size_t remaining) -{ - struct bt_hci_acl_hdr *hdr = (void *)data; - struct net_buf *buf; - - if (remaining < sizeof(*hdr)) { - LOG_ERR("Not enough data for ACL header"); - return NULL; - } - - buf = bt_buf_get_tx(BT_BUF_ACL_OUT, K_NO_WAIT, hdr, sizeof(*hdr)); - if (buf) { - data += sizeof(*hdr); - remaining -= sizeof(*hdr); - } else { - LOG_ERR("No available ACL buffers!"); - return NULL; - } - - if (remaining != sys_le16_to_cpu(hdr->len)) { - LOG_ERR("ACL payload length is not correct"); - net_buf_unref(buf); - return NULL; - } - - if (remaining > net_buf_tailroom(buf)) { - LOG_ERR("Not enough space in buffer"); - net_buf_unref(buf); - return NULL; - } - - LOG_DBG("len %u", remaining); - net_buf_add_mem(buf, data, remaining); - - return buf; -} - -static struct net_buf *hci_rpmsg_iso_recv(uint8_t *data, size_t remaining) -{ - struct bt_hci_iso_hdr *hdr = (void *)data; - struct net_buf *buf; - - if (remaining < sizeof(*hdr)) { - LOG_ERR("Not enough data for ISO header"); - return NULL; - } - - buf = bt_buf_get_tx(BT_BUF_ISO_OUT, K_NO_WAIT, hdr, sizeof(*hdr)); - if (buf) { - data += sizeof(*hdr); - remaining -= sizeof(*hdr); - } else { - LOG_ERR("No available ISO buffers!"); - return NULL; - } - - if (remaining != bt_iso_hdr_len(sys_le16_to_cpu(hdr->len))) { - LOG_ERR("ISO payload length is not correct"); - net_buf_unref(buf); - return NULL; - } - - if (remaining > net_buf_tailroom(buf)) { - LOG_ERR("Not enough space in buffer"); - net_buf_unref(buf); - return NULL; - } - - LOG_DBG("len %zu", remaining); - net_buf_add_mem(buf, data, remaining); - - return buf; -} - -static void hci_rpmsg_rx(uint8_t *data, size_t len) -{ - uint8_t pkt_indicator; - struct net_buf *buf = NULL; - size_t remaining = len; - - LOG_HEXDUMP_DBG(data, len, "RPMSG data:"); - - pkt_indicator = *data++; - remaining -= sizeof(pkt_indicator); - - switch (pkt_indicator) { - case HCI_RPMSG_CMD: - buf = hci_rpmsg_cmd_recv(data, remaining); - break; - - case HCI_RPMSG_ACL: - buf = hci_rpmsg_acl_recv(data, remaining); - break; - - case HCI_RPMSG_ISO: - buf = hci_rpmsg_iso_recv(data, remaining); - break; - - default: - LOG_ERR("Unknown HCI type %u", pkt_indicator); - return; - } - - if (buf) { - net_buf_put(&tx_queue, buf); - - LOG_HEXDUMP_DBG(buf->data, buf->len, "Final net buffer:"); - } -} - -static void tx_thread(void *p1, void *p2, void *p3) -{ - while (1) { - struct net_buf *buf; - int err; - - /* Wait until a buffer is available */ - buf = net_buf_get(&tx_queue, K_FOREVER); - /* Pass buffer to the stack */ - err = bt_send(buf); - if (err) { - LOG_ERR("Unable to send (err %d)", err); - net_buf_unref(buf); - } - - /* Give other threads a chance to run if tx_queue keeps getting - * new data all the time. - */ - k_yield(); - } -} - -static void hci_rpmsg_send(struct net_buf *buf, bool is_fatal_err) -{ - uint8_t pkt_indicator; - uint8_t retries = 0; - int ret; - - LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len); - - LOG_HEXDUMP_DBG(buf->data, buf->len, "Controller buffer:"); - - switch (bt_buf_get_type(buf)) { - case BT_BUF_ACL_IN: - pkt_indicator = HCI_RPMSG_ACL; - break; - case BT_BUF_EVT: - pkt_indicator = HCI_RPMSG_EVT; - break; - case BT_BUF_ISO_IN: - pkt_indicator = HCI_RPMSG_ISO; - break; - default: - LOG_ERR("Unknown type %u", bt_buf_get_type(buf)); - net_buf_unref(buf); - return; - } - net_buf_push_u8(buf, pkt_indicator); - - LOG_HEXDUMP_DBG(buf->data, buf->len, "Final HCI buffer:"); - - do { - ret = ipc_service_send(&hci_ept, buf->data, buf->len); - if (ret < 0) { - retries++; - if (retries > 10) { - /* Default backend (rpmsg_virtio) has a timeout of 150ms. */ - LOG_WRN("IPC send has been blocked for 1.5 seconds."); - retries = 0; - } - - /* The function can be called by the application main thread, - * bt_ctlr_assert_handle and k_sys_fatal_error_handler. In case of a call by - * Bluetooth Controller assert handler or system fatal error handler the - * call can be from ISR context, hence there is no thread to yield. Besides - * that both handlers implement a policy to provide error information and - * stop the system in an infinite loop. The goal is to prevent any other - * damage to the system if one of such exeptional situations occur, hence - * call to k_yield is against it. - */ - if (is_fatal_err) { - LOG_ERR("IPC service send error: %d", ret); - } else { - k_yield(); - } - } - } while (ret < 0); - - LOG_INF("Sent message of %d bytes.", ret); - - net_buf_unref(buf); -} - -#if defined(CONFIG_BT_CTLR_ASSERT_HANDLER) -void bt_ctlr_assert_handle(char *file, uint32_t line) -{ - /* Disable interrupts, this is unrecoverable */ - (void)irq_lock(); - -#if defined(CONFIG_BT_HCI_VS_FATAL_ERROR) - /* Generate an error event only when IPC service endpoint is already bound. */ - if (ipc_ept_ready) { - /* Prepare vendor specific HCI debug event */ - struct net_buf *buf; - - buf = hci_vs_err_assert(file, line); - if (buf == NULL) { - /* Send the event over rpmsg */ - hci_rpmsg_send(buf, HCI_FATAL_ERR_MSG); - } else { - LOG_ERR("Can't create Fatal Error HCI event: %s at %d", __FILE__, __LINE__); - } - } else { - LOG_ERR("IPC endpoint is not ready yet: %s at %d", __FILE__, __LINE__); - } - - LOG_ERR("Halting system"); - -#else /* !CONFIG_BT_HCI_VS_FATAL_ERROR */ - LOG_ERR("Controller assert in: %s at %d", file, line); - -#endif /* !CONFIG_BT_HCI_VS_FATAL_ERROR */ - - /* Flush the logs before locking the CPU */ - LOG_PANIC(); - - while (true) { - }; -} -#endif /* CONFIG_BT_CTLR_ASSERT_HANDLER */ - -#if defined(CONFIG_BT_HCI_VS_FATAL_ERROR) -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *esf) -{ - /* Disable interrupts, this is unrecoverable */ - (void)irq_lock(); - - /* Generate an error event only when there is a stack frame and IPC service endpoint is - * already bound. - */ - if (esf != NULL && ipc_ept_ready) { - /* Prepare vendor specific HCI debug event */ - struct net_buf *buf; - - buf = hci_vs_err_stack_frame(reason, esf); - if (buf != NULL) { - hci_rpmsg_send(buf, HCI_FATAL_ERR_MSG); - } else { - LOG_ERR("Can't create Fatal Error HCI event.\n"); - } - } - - LOG_ERR("Halting system"); - - /* Flush the logs before locking the CPU */ - LOG_PANIC(); - - while (true) { - }; - - CODE_UNREACHABLE; -} -#endif /* CONFIG_BT_HCI_VS_FATAL_ERROR */ - -static void hci_ept_bound(void *priv) -{ - k_sem_give(&ipc_bound_sem); -#if defined(CONFIG_BT_CTLR_ASSERT_HANDLER) || defined(CONFIG_BT_HCI_VS_FATAL_ERROR) - ipc_ept_ready = true; -#endif /* CONFIG_BT_CTLR_ASSERT_HANDLER || CONFIG_BT_HCI_VS_FATAL_ERROR */ -} - -static void hci_ept_recv(const void *data, size_t len, void *priv) -{ - LOG_INF("Received message of %u bytes.", len); - hci_rpmsg_rx((uint8_t *) data, len); -} - -static struct ipc_ept_cfg hci_ept_cfg = { - .name = "nrf_bt_hci", - .cb = { - .bound = hci_ept_bound, - .received = hci_ept_recv, - }, -}; - -int main(void) -{ - int err; - const struct device *hci_ipc_instance = - DEVICE_DT_GET(DT_CHOSEN(zephyr_bt_hci_rpmsg_ipc)); - - /* incoming events and data from the controller */ - static K_FIFO_DEFINE(rx_queue); - - LOG_DBG("Start"); - - /* Enable the raw interface, this will in turn open the HCI driver */ - bt_enable_raw(&rx_queue); - - /* Spawn the TX thread and start feeding commands and data to the - * controller - */ - k_thread_create(&tx_thread_data, tx_thread_stack, - K_THREAD_STACK_SIZEOF(tx_thread_stack), tx_thread, - NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); - k_thread_name_set(&tx_thread_data, "HCI rpmsg TX"); - - /* Initialize IPC service instance and register endpoint. */ - err = ipc_service_open_instance(hci_ipc_instance); - if (err < 0 && err != -EALREADY) { - LOG_ERR("IPC service instance initialization failed: %d\n", err); - } - - err = ipc_service_register_endpoint(hci_ipc_instance, &hci_ept, &hci_ept_cfg); - if (err) { - LOG_ERR("Registering endpoint failed with %d", err); - } - - k_sem_take(&ipc_bound_sem, K_FOREVER); - - while (1) { - struct net_buf *buf; - - buf = net_buf_get(&rx_queue, K_FOREVER); - hci_rpmsg_send(buf, HCI_REGULAR_MSG); - } - return 0; -} diff --git a/samples/bluetooth/hci_uart/README.rst b/samples/bluetooth/hci_uart/README.rst index 83004cd544f..0beb105035d 100644 --- a/samples/bluetooth/hci_uart/README.rst +++ b/samples/bluetooth/hci_uart/README.rst @@ -55,10 +55,10 @@ For example, to build for the nRF52832 Development Kit: .. _bluetooth-hci-uart-qemu-posix: -Using the controller with QEMU and Native POSIX -=============================================== +Using the controller with QEMU or native_sim +============================================ -In order to use the HCI UART controller with QEMU or Native POSIX you will need +In order to use the HCI UART controller with QEMU or :ref:`native_sim ` you will need to attach it to the Linux Host first. To do so simply build the sample and connect the UART to the Linux machine, and then attach it with this command: @@ -84,7 +84,7 @@ If you are running :file:`btmon` you should see a brief log showing how the Linux kernel identifies the attached controller. Once the controller is attached follow the instructions in the -:ref:`bluetooth_qemu_posix` section to use QEMU with it. +:ref:`bluetooth_qemu_native` section to use QEMU with it. .. _bluetooth-hci-uart-bluez: diff --git a/samples/bluetooth/hci_uart_async/README.rst b/samples/bluetooth/hci_uart_async/README.rst index 75bf586868d..f5caf0f965d 100644 --- a/samples/bluetooth/hci_uart_async/README.rst +++ b/samples/bluetooth/hci_uart_async/README.rst @@ -52,10 +52,10 @@ For example, to build for the nRF52832 Development Kit: .. _bluetooth-hci-uart-async-qemu-posix: -Using the controller with QEMU and Native POSIX -=============================================== +Using the controller with QEMU or native_sim +============================================ -In order to use the HCI UART controller with QEMU or Native POSIX you will need +In order to use the HCI UART controller with QEMU or :ref:`native_sim ` you will need to attach it to the Linux Host first. To do so simply build the sample and connect the UART to the Linux machine, and then attach it with this command: @@ -77,7 +77,7 @@ If you are running :file:`btmon` you should see a brief log showing how the Linux kernel identifies the attached controller. Once the controller is attached follow the instructions in the -:ref:`bluetooth_qemu_posix` section to use QEMU with it. +:ref:`bluetooth_qemu_native` section to use QEMU with it. .. _bluetooth-hci-uart-async-bluez: diff --git a/samples/bluetooth/hci_usb/sample.yaml b/samples/bluetooth/hci_usb/sample.yaml index 4b998f95bb6..9848aed2430 100644 --- a/samples/bluetooth/hci_usb/sample.yaml +++ b/samples/bluetooth/hci_usb/sample.yaml @@ -10,7 +10,7 @@ tests: - usb - bluetooth # FIXME: exclude due to build error - platform_exclude: 96b_carbon + platform_exclude: 96b_carbon stm32l562e_dk sample.bluetooth.hci_usb.device_next: harness: bluetooth depends_on: diff --git a/samples/bluetooth/hci_usb_h4/sample.yaml b/samples/bluetooth/hci_usb_h4/sample.yaml index b09b30185a3..afc6e2429cb 100644 --- a/samples/bluetooth/hci_usb_h4/sample.yaml +++ b/samples/bluetooth/hci_usb_h4/sample.yaml @@ -10,4 +10,4 @@ tests: - usb - bluetooth # FIXME: exclude due to build error - platform_exclude: 96b_carbon + platform_exclude: 96b_carbon stm32l562e_dk diff --git a/samples/bluetooth/ipsp/src/main.c b/samples/bluetooth/ipsp/src/main.c index c4f1f87c169..a8c017140c3 100644 --- a/samples/bluetooth/ipsp/src/main.c +++ b/samples/bluetooth/ipsp/src/main.c @@ -285,8 +285,12 @@ static void setup_tcp_accept(struct net_context *tcp_recv6) } } -static void listen(void) +static void listen(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct net_context *udp_recv6 = { 0 }; struct net_context *tcp_recv6 = { 0 }; @@ -313,7 +317,7 @@ int main(void) init_app(); k_thread_create(&thread_data, thread_stack, STACKSIZE, - (k_thread_entry_t)listen, + listen, NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); return 0; } diff --git a/samples/bluetooth/iso_broadcast_benchmark/src/broadcaster.c b/samples/bluetooth/iso_broadcast_benchmark/src/broadcaster.c index 735ac7a3318..6c52e2aef82 100644 --- a/samples/bluetooth/iso_broadcast_benchmark/src/broadcaster.c +++ b/samples/bluetooth/iso_broadcast_benchmark/src/broadcaster.c @@ -22,14 +22,14 @@ LOG_MODULE_REGISTER(iso_broadcast_broadcaster, LOG_LEVEL_DBG); #define DEFAULT_BIS_PACKING 0 #define DEFAULT_BIS_FRAMING 0 #define DEFAULT_BIS_COUNT CONFIG_BT_ISO_MAX_CHAN -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) #define DEFAULT_BIS_NSE BT_ISO_NSE_MIN #define DEFAULT_BIS_BN BT_ISO_BN_MIN #define DEFAULT_BIS_PDU_SIZE CONFIG_BT_ISO_TX_MTU #define DEFAULT_BIS_IRC BT_ISO_IRC_MIN #define DEFAULT_BIS_PTO BT_ISO_PTO_MIN #define DEFAULT_BIS_ISO_INTERVAL DEFAULT_BIS_INTERVAL_US / 1250U /* N * 10 ms */ -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ NET_BUF_POOL_FIXED_DEFINE(bis_tx_pool, CONFIG_BT_ISO_TX_BUF_COUNT, BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), @@ -53,11 +53,11 @@ static struct bt_iso_big_create_param big_create_param = { .framing = DEFAULT_BIS_FRAMING, /* 0 - unframed, 1 - framed */ .interval = DEFAULT_BIS_INTERVAL_US, /* in microseconds */ .latency = DEFAULT_BIS_LATENCY_MS, /* milliseconds */ -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) .irc = DEFAULT_BIS_IRC, .pto = DEFAULT_BIS_PTO, .iso_interval = DEFAULT_BIS_ISO_INTERVAL, -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ }; static void iso_connected(struct bt_iso_chan *chan) @@ -91,17 +91,17 @@ static struct bt_iso_chan_io_qos iso_tx_qos = { .sdu = DEFAULT_BIS_SDU, /* bytes */ .rtn = DEFAULT_BIS_RTN, .phy = DEFAULT_BIS_PHY, -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) .max_pdu = DEFAULT_BIS_PDU_SIZE, .burst_number = DEFAULT_BIS_BN, -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ }; static struct bt_iso_chan_qos bis_iso_qos = { .tx = &iso_tx_qos, -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) .num_subevents = DEFAULT_BIS_NSE, -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ }; static size_t get_chars(char *buffer, size_t max_size) @@ -241,7 +241,7 @@ static int parse_sdu_arg(void) return (int)sdu; } -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) static int parse_irc_arg(void) { size_t char_count; @@ -385,7 +385,7 @@ static int parse_bn_arg(void) return (int)burst_number; } -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ static int parse_packing_arg(void) { @@ -468,14 +468,14 @@ static int parse_args(void) int packing; int framing; int bis_count; -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) int num_subevents; int iso_interval; int burst_number; int max_pdu; int irc; int pto; -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ printk("Follow the prompts. Press enter to use default values.\n"); @@ -519,7 +519,7 @@ static int parse_args(void) return -EINVAL; } -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) irc = parse_irc_arg(); if (irc < 0) { return -EINVAL; @@ -549,7 +549,7 @@ static int parse_args(void) if (burst_number < 0) { return -EINVAL; } -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ iso_tx_qos.rtn = rtn; iso_tx_qos.phy = phy; @@ -559,14 +559,14 @@ static int parse_args(void) big_create_param.packing = packing; big_create_param.framing = framing; big_create_param.num_bis = bis_count; -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) bis_iso_qos.num_subevents = num_subevents; iso_tx_qos.max_pdu = max_pdu; iso_tx_qos.burst_number = burst_number; big_create_param.irc = irc; big_create_param.pto = pto; big_create_param.iso_interval = iso_interval; -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ return 0; } diff --git a/samples/bluetooth/iso_connected_benchmark/src/main.c b/samples/bluetooth/iso_connected_benchmark/src/main.c index 99b308ccbb2..9d387ed8806 100644 --- a/samples/bluetooth/iso_connected_benchmark/src/main.c +++ b/samples/bluetooth/iso_connected_benchmark/src/main.c @@ -28,6 +28,11 @@ enum benchmark_role { ROLE_QUIT }; +enum sdu_dir { + DIR_C_TO_P, + DIR_P_TO_C +}; + #define DEFAULT_CIS_RTN 2 #define DEFAULT_CIS_INTERVAL_US 7500 #define DEFAULT_CIS_LATENCY_MS 40 @@ -38,13 +43,13 @@ enum benchmark_role { #define DEFAULT_CIS_COUNT 1U #define DEFAULT_CIS_SEC_LEVEL BT_SECURITY_L1 -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) #define DEFAULT_CIS_NSE BT_ISO_NSE_MIN #define DEFAULT_CIS_BN BT_ISO_BN_MIN #define DEFAULT_CIS_PDU_SIZE CONFIG_BT_ISO_TX_MTU #define DEFAULT_CIS_FT BT_ISO_FT_MIN #define DEFAULT_CIS_ISO_INTERVAL DEFAULT_CIS_INTERVAL_US / 1250U /* N * 1.25 ms */ -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ #define BUFFERS_ENQUEUED 2 /* Number of buffers enqueue for each channel */ @@ -91,43 +96,45 @@ static struct bt_iso_chan_io_qos iso_tx_qos = { .sdu = DEFAULT_CIS_SDU_SIZE, /* bytes */ .rtn = DEFAULT_CIS_RTN, .phy = DEFAULT_CIS_PHY, -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) .max_pdu = DEFAULT_CIS_PDU_SIZE, .burst_number = DEFAULT_CIS_BN, -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ }; static struct bt_iso_chan_io_qos iso_rx_qos = { .sdu = DEFAULT_CIS_SDU_SIZE, /* bytes */ .rtn = DEFAULT_CIS_RTN, .phy = DEFAULT_CIS_PHY, -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) .max_pdu = DEFAULT_CIS_PDU_SIZE, .burst_number = DEFAULT_CIS_BN, -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ }; static struct bt_iso_chan_qos iso_qos = { .tx = &iso_tx_qos, .rx = &iso_rx_qos, -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) .num_subevents = DEFAULT_CIS_NSE, -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ }; static struct bt_iso_cig_param cig_create_param = { - .interval = DEFAULT_CIS_INTERVAL_US, /* in microseconds */ - .latency = DEFAULT_CIS_LATENCY_MS, /* milliseconds */ + .c_to_p_interval = DEFAULT_CIS_INTERVAL_US, /* in microseconds */ + .p_to_c_interval = DEFAULT_CIS_INTERVAL_US, /* in microseconds */ + .c_to_p_latency = DEFAULT_CIS_LATENCY_MS, /* milliseconds */ + .p_to_c_latency = DEFAULT_CIS_LATENCY_MS, /* milliseconds */ .sca = BT_GAP_SCA_UNKNOWN, .packing = DEFAULT_CIS_PACKING, .framing = DEFAULT_CIS_FRAMING, .cis_channels = cis, .num_cis = DEFAULT_CIS_COUNT, -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) .c_to_p_ft = DEFAULT_CIS_FT, .p_to_c_ft = DEFAULT_CIS_FT, .iso_interval = DEFAULT_CIS_ISO_INTERVAL, -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ }; static enum benchmark_role device_role_select(void) @@ -179,6 +186,7 @@ static void iso_send(struct bt_iso_chan *chan) int ret; struct net_buf *buf; struct iso_chan_work *chan_work; + uint32_t interval; chan_work = CONTAINER_OF(chan, struct iso_chan_work, chan); @@ -186,10 +194,13 @@ static void iso_send(struct bt_iso_chan *chan) return; } + interval = (role == ROLE_CENTRAL) ? + cig_create_param.c_to_p_interval : cig_create_param.p_to_c_interval; + buf = net_buf_alloc(&tx_pool, K_FOREVER); if (buf == NULL) { LOG_ERR("Could not allocate buffer"); - k_work_reschedule(&chan_work->send_work, K_USEC(cig_create_param.interval)); + k_work_reschedule(&chan_work->send_work, K_USEC(interval)); return; } @@ -201,7 +212,7 @@ static void iso_send(struct bt_iso_chan *chan) if (ret < 0) { LOG_ERR("Unable to send data: %d", ret); net_buf_unref(buf); - k_work_reschedule(&chan_work->send_work, K_USEC(cig_create_param.interval)); + k_work_reschedule(&chan_work->send_work, K_USEC(interval)); return; } @@ -535,14 +546,18 @@ static int parse_rtn_arg(struct bt_iso_chan_io_qos *qos) return (int)rtn; } -static int parse_interval_arg(void) +static int parse_interval_arg(enum sdu_dir direction) { char buffer[9]; size_t char_count; uint64_t interval; - printk("Set interval (us) (current %u, default %u)\n", - cig_create_param.interval, DEFAULT_CIS_INTERVAL_US); + interval = (direction == DIR_C_TO_P) ? + cig_create_param.c_to_p_interval : cig_create_param.p_to_c_interval; + + printk("Set %s interval (us) (current %llu, default %u)\n", + (direction == DIR_C_TO_P) ? "C to P" : "P to C", + interval, DEFAULT_CIS_INTERVAL_US); char_count = get_chars(buffer, sizeof(buffer) - 1); if (char_count == 0) { @@ -550,7 +565,6 @@ static int parse_interval_arg(void) } interval = strtoul(buffer, NULL, 0); - /* TODO: Replace literal ints with a #define once it has been created */ if (interval < BT_ISO_SDU_INTERVAL_MIN || interval > BT_ISO_SDU_INTERVAL_MAX) { printk("Invalid interval %llu", interval); return -EINVAL; @@ -559,14 +573,18 @@ static int parse_interval_arg(void) return (int)interval; } -static int parse_latency_arg(void) +static int parse_latency_arg(enum sdu_dir direction) { char buffer[6]; size_t char_count; uint64_t latency; - printk("Set latency (ms) (current %u, default %u)\n", - cig_create_param.latency, DEFAULT_CIS_LATENCY_MS); + latency = (direction == DIR_C_TO_P) ? + cig_create_param.c_to_p_latency : cig_create_param.p_to_c_latency; + + printk("Set %s latency (ms) (current %llu, default %u)\n", + (direction == DIR_C_TO_P) ? "C to P" : "P to C", + latency, DEFAULT_CIS_LATENCY_MS); char_count = get_chars(buffer, sizeof(buffer) - 1); if (char_count == 0) { @@ -632,7 +650,7 @@ static int parse_sdu_arg(struct bt_iso_chan_io_qos *qos) return (int)sdu; } -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) static int parse_c_to_p_ft_arg(void) { char buffer[4]; @@ -778,7 +796,7 @@ static int parse_bn_arg(const struct bt_iso_chan_io_qos *qos) return (int)bn; } -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ static int parse_cis_count_arg(void) { @@ -805,15 +823,17 @@ static int parse_cis_count_arg(void) static int parse_cig_args(void) { - int interval; - int latency; + int c_to_p_interval; + int p_to_c_interval; + int c_to_p_latency; + int p_to_c_latency; int cis_count; -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) int c_to_p_ft; int p_to_c_ft; int iso_interval; int num_subevents; -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ printk("Follow the prompts. Press enter to use default values.\n"); @@ -822,17 +842,27 @@ static int parse_cig_args(void) return -EINVAL; } - interval = parse_interval_arg(); - if (interval < 0) { + c_to_p_interval = parse_interval_arg(DIR_C_TO_P); + if (c_to_p_interval < 0) { + return -EINVAL; + } + + p_to_c_interval = parse_interval_arg(DIR_P_TO_C); + if (p_to_c_interval < 0) { + return -EINVAL; + } + + c_to_p_latency = parse_latency_arg(DIR_C_TO_P); + if (c_to_p_latency < 0) { return -EINVAL; } - latency = parse_latency_arg(); - if (latency < 0) { + p_to_c_latency = parse_latency_arg(DIR_P_TO_C); + if (p_to_c_latency < 0) { return -EINVAL; } -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) c_to_p_ft = parse_c_to_p_ft_arg(); if (c_to_p_ft < 0) { return -EINVAL; @@ -852,17 +882,19 @@ static int parse_cig_args(void) if (num_subevents < 0) { return -EINVAL; } -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ - cig_create_param.interval = interval; - cig_create_param.latency = latency; + cig_create_param.c_to_p_interval = c_to_p_interval; + cig_create_param.p_to_c_interval = p_to_c_interval; + cig_create_param.c_to_p_latency = c_to_p_latency; + cig_create_param.p_to_c_latency = p_to_c_latency; cig_create_param.num_cis = cis_count; -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) cig_create_param.c_to_p_ft = c_to_p_ft; cig_create_param.p_to_c_ft = p_to_c_ft; cig_create_param.iso_interval = iso_interval; iso_qos.num_subevents = num_subevents; -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ return 0; } @@ -872,10 +904,10 @@ static int parse_cis_args(struct bt_iso_chan_io_qos *qos) int rtn; int phy; int sdu; -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) int max_pdu; int burst_number; -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ printk("Follow the prompts. Press enter to use default values.\n"); @@ -894,7 +926,7 @@ static int parse_cis_args(struct bt_iso_chan_io_qos *qos) return -EINVAL; } -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) max_pdu = parse_pdu_arg(qos); if (max_pdu < 0) { return -EINVAL; @@ -904,15 +936,15 @@ static int parse_cis_args(struct bt_iso_chan_io_qos *qos) if (burst_number < 0) { return -EINVAL; } -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ qos->rtn = rtn; qos->phy = phy; qos->sdu = sdu; -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) qos->max_pdu = max_pdu; qos->burst_number = burst_number; -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ return 0; } @@ -923,9 +955,11 @@ static int change_central_settings(void) int err; printk("Change CIG settings (y/N)? (Current settings: cis_count=%u, " - "interval=%u, latency=%u)\n", - cig_create_param.num_cis, cig_create_param.interval, - cig_create_param.latency); + "C to P interval=%u, P to C interval=%u " + "C to P latency=%u, P to C latency=%u)\n", + cig_create_param.num_cis, cig_create_param.c_to_p_interval, + cig_create_param.p_to_c_interval, cig_create_param.c_to_p_latency, + cig_create_param.p_to_c_latency); c = tolower(console_getchar()); if (c == 'y') { @@ -934,9 +968,12 @@ static int change_central_settings(void) return err; } - printk("New settings: cis_count=%u, inteval=%u, latency=%u\n", - cig_create_param.num_cis, cig_create_param.interval, - cig_create_param.latency); + printk("New settings: cis_count=%u, C to P interval=%u, " + "P TO C interval=%u, C to P latency=%u " + "P TO C latency=%u\n", + cig_create_param.num_cis, cig_create_param.c_to_p_interval, + cig_create_param.p_to_c_interval, cig_create_param.c_to_p_latency, + cig_create_param.p_to_c_latency); } printk("Change TX settings (y/N)? (Current settings: rtn=%u, " diff --git a/samples/bluetooth/iso_receive/src/main.c b/samples/bluetooth/iso_receive/src/main.c index 90fdf767dc5..a746a2f2fd0 100644 --- a/samples/bluetooth/iso_receive/src/main.c +++ b/samples/bluetooth/iso_receive/src/main.c @@ -281,6 +281,16 @@ static struct bt_iso_big_sync_param big_sync_param = { .sync_timeout = 100, /* in 10 ms units */ }; +static void reset_semaphores(void) +{ + k_sem_reset(&sem_per_adv); + k_sem_reset(&sem_per_sync); + k_sem_reset(&sem_per_sync_lost); + k_sem_reset(&sem_per_big_info); + k_sem_reset(&sem_big_sync); + k_sem_reset(&sem_big_sync_lost); +} + int main(void) { struct bt_le_per_adv_sync_param sync_create_param; @@ -328,6 +338,7 @@ int main(void) printk("Success.\n"); do { + reset_semaphores(); per_adv_lost = false; printk("Start scanning..."); diff --git a/samples/bluetooth/mesh/README.rst b/samples/bluetooth/mesh/README.rst index c30bb48adae..e6ee78ba3a7 100644 --- a/samples/bluetooth/mesh/README.rst +++ b/samples/bluetooth/mesh/README.rst @@ -45,9 +45,9 @@ Refer to your :ref:`board's documentation ` for alternative flash instructions if your board doesn't support the ``flash`` target. To run the application on an :ref:`nrf5340dk_nrf5340`, a Bluetooth controller application -must also run on the network core. The :ref:`bluetooth-hci-rpmsg-sample` sample +must also run on the network core. The :ref:`bluetooth-hci-ipc-sample` sample application may be used. Build this sample with configuration -:zephyr_file:`samples/bluetooth/hci_rpmg/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf` +:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf` to enable mesh support. Interacting with the sample diff --git a/samples/bluetooth/mesh/src/main.c b/samples/bluetooth/mesh/src/main.c index 6914c4fc409..b220b354fd5 100644 --- a/samples/bluetooth/mesh/src/main.c +++ b/samples/bluetooth/mesh/src/main.c @@ -25,12 +25,12 @@ #define OP_ONOFF_SET_UNACK BT_MESH_MODEL_OP_2(0x82, 0x03) #define OP_ONOFF_STATUS BT_MESH_MODEL_OP_2(0x82, 0x04) -static void attention_on(struct bt_mesh_model *mod) +static void attention_on(const struct bt_mesh_model *mod) { board_led_set(true); } -static void attention_off(struct bt_mesh_model *mod) +static void attention_off(const struct bt_mesh_model *mod) { board_led_set(false); } @@ -102,7 +102,7 @@ static inline uint8_t model_time_encode(int32_t ms) return 0x3f; } -static int onoff_status_send(struct bt_mesh_model *model, +static int onoff_status_send(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx) { uint32_t remaining; @@ -151,7 +151,7 @@ static void onoff_timeout(struct k_work *work) /* Generic OnOff Server message handlers */ -static int gen_onoff_get(struct bt_mesh_model *model, +static int gen_onoff_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -159,7 +159,7 @@ static int gen_onoff_get(struct bt_mesh_model *model, return 0; } -static int gen_onoff_set_unack(struct bt_mesh_model *model, +static int gen_onoff_set_unack(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -202,7 +202,7 @@ static int gen_onoff_set_unack(struct bt_mesh_model *model, return 0; } -static int gen_onoff_set(struct bt_mesh_model *model, +static int gen_onoff_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -221,7 +221,7 @@ static const struct bt_mesh_model_op gen_onoff_srv_op[] = { /* Generic OnOff Client */ -static int gen_onoff_status(struct bt_mesh_model *model, +static int gen_onoff_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -248,7 +248,7 @@ static const struct bt_mesh_model_op gen_onoff_cli_op[] = { }; /* This application only needs one element to contain its models */ -static struct bt_mesh_model models[] = { +static const struct bt_mesh_model models[] = { BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub), BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_srv_op, NULL, @@ -257,7 +257,7 @@ static struct bt_mesh_model models[] = { NULL), }; -static struct bt_mesh_elem elements[] = { +static const struct bt_mesh_elem elements[] = { BT_MESH_ELEM(0, models, BT_MESH_MODEL_NONE), }; diff --git a/samples/bluetooth/mesh_demo/README.rst b/samples/bluetooth/mesh_demo/README.rst index 52a786c164d..7fe7f0908ce 100644 --- a/samples/bluetooth/mesh_demo/README.rst +++ b/samples/bluetooth/mesh_demo/README.rst @@ -56,7 +56,7 @@ Refer to your :ref:`board's documentation ` for alternative flash instructions if your board doesn't support the ``flash`` target. To run the application on an :ref:`nrf5340dk_nrf5340`, a Bluetooth controller application -must also run on the network core. The :ref:`bluetooth-hci-rpmsg-sample` sample +must also run on the network core. The :ref:`bluetooth-hci-ipc-sample` sample application may be used. Build this sample with configuration -:zephyr_file:`samples/bluetooth/hci_rpmg/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf` +:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf` to enable mesh support. diff --git a/samples/bluetooth/mesh_demo/src/main.c b/samples/bluetooth/mesh_demo/src/main.c index 642cce1d18e..b405fd06216 100644 --- a/samples/bluetooth/mesh_demo/src/main.c +++ b/samples/bluetooth/mesh_demo/src/main.c @@ -50,14 +50,14 @@ static void heartbeat(const struct bt_mesh_hb_sub *sub, uint8_t hops, static struct bt_mesh_cfg_cli cfg_cli = { }; -static void attention_on(struct bt_mesh_model *model) +static void attention_on(const struct bt_mesh_model *model) { printk("attention_on()\n"); board_attention(true); board_play("100H100C100H100C100H100C"); } -static void attention_off(struct bt_mesh_model *model) +static void attention_off(const struct bt_mesh_model *model) { printk("attention_off()\n"); board_attention(false); @@ -74,19 +74,19 @@ static struct bt_mesh_health_srv health_srv = { BT_MESH_HEALTH_PUB_DEFINE(health_pub, 0); -static struct bt_mesh_model root_models[] = { +static const struct bt_mesh_model root_models[] = { BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub), }; -static int vnd_button_pressed(struct bt_mesh_model *model, +static int vnd_button_pressed(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { printk("src 0x%04x\n", ctx->addr); - if (ctx->addr == bt_mesh_model_elem(model)->addr) { + if (ctx->addr == bt_mesh_model_elem(model)->rt->addr) { return 0; } @@ -101,11 +101,11 @@ static const struct bt_mesh_model_op vnd_ops[] = { BT_MESH_MODEL_OP_END, }; -static struct bt_mesh_model vnd_models[] = { +static const struct bt_mesh_model vnd_models[] = { BT_MESH_MODEL_VND(BT_COMP_ID_LF, MOD_LF, vnd_ops, NULL, NULL), }; -static struct bt_mesh_elem elements[] = { +static const struct bt_mesh_elem elements[] = { BT_MESH_ELEM(0, root_models, vnd_models), }; diff --git a/samples/bluetooth/mesh_provisioner/README.rst b/samples/bluetooth/mesh_provisioner/README.rst index 4769ae09f17..6da113afc1b 100644 --- a/samples/bluetooth/mesh_provisioner/README.rst +++ b/samples/bluetooth/mesh_provisioner/README.rst @@ -54,7 +54,7 @@ Refer to your :ref:`board's documentation ` for alternative flash instructions if your board doesn't support the ``flash`` target. To run the application on an :ref:`nrf5340dk_nrf5340`, a Bluetooth controller application -must also run on the network core. The :ref:`bluetooth-hci-rpmsg-sample` sample +must also run on the network core. The :ref:`bluetooth-hci-ipc-sample` sample application may be used. Build this sample with configuration -:zephyr_file:`samples/bluetooth/hci_rpmg/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf` +:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf` to enable mesh support. diff --git a/samples/bluetooth/mesh_provisioner/prj.conf b/samples/bluetooth/mesh_provisioner/prj.conf index 3b40d2c2c7b..bfc6d5a1241 100644 --- a/samples/bluetooth/mesh_provisioner/prj.conf +++ b/samples/bluetooth/mesh_provisioner/prj.conf @@ -1,5 +1,5 @@ #CONFIG_INIT_STACKS=y -CONFIG_MAIN_STACK_SIZE=1408 +CONFIG_MAIN_STACK_SIZE=2048 CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 # The Bluetooth API should not be used from a preemptive thread: CONFIG_MAIN_THREAD_PRIORITY=-2 diff --git a/samples/bluetooth/mesh_provisioner/src/main.c b/samples/bluetooth/mesh_provisioner/src/main.c index 42eaa31207b..472dc020d43 100644 --- a/samples/bluetooth/mesh_provisioner/src/main.c +++ b/samples/bluetooth/mesh_provisioner/src/main.c @@ -53,13 +53,13 @@ static struct bt_mesh_health_cli health_cli = { .current_status = health_current_status, }; -static struct bt_mesh_model root_models[] = { +static const struct bt_mesh_model root_models[] = { BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), BT_MESH_MODEL_HEALTH_CLI(&health_cli), }; -static struct bt_mesh_elem elements[] = { +static const struct bt_mesh_elem elements[] = { BT_MESH_ELEM(0, root_models, BT_MESH_MODEL_NONE), }; diff --git a/samples/bluetooth/peripheral_csc/src/main.c b/samples/bluetooth/peripheral_csc/src/main.c index 2f91e201492..eba60137097 100644 --- a/samples/bluetooth/peripheral_csc/src/main.c +++ b/samples/bluetooth/peripheral_csc/src/main.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/samples/bluetooth/tmap_bmr/boards/native_sim.conf b/samples/bluetooth/tmap_bmr/boards/native_sim.conf new file mode 100644 index 00000000000..e06b2999381 --- /dev/null +++ b/samples/bluetooth/tmap_bmr/boards/native_sim.conf @@ -0,0 +1,10 @@ +CONFIG_LOG_MODE_IMMEDIATE=y +CONFIG_BT_TINYCRYPT_ECC=y + +CONFIG_LIBLC3=y +CONFIG_FPU=y + +# For LE-audio at 10ms intervals we need the tick counter to occur more frequently +# than every 10 ms as each PDU for some reason takes 2 ticks to process. +CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 +CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME=y diff --git a/samples/bluetooth/tmap_bmr/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/tmap_bmr/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf index f7c6bbfd3db..af60fb49fbd 100644 --- a/samples/bluetooth/tmap_bmr/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf +++ b/samples/bluetooth/tmap_bmr/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -4,5 +4,5 @@ CONFIG_LIBLC3=y # The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence # inctease stack size for that thread. CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 -# LC3 lib requires floating point support in the c-lib NEWLIB is one way of getting that. -CONFIG_NEWLIB_LIBC=y +# LC3 lib requires floating point support in the c-lib +CONFIG_REQUIRES_FULL_LIBC=y diff --git a/samples/bluetooth/tmap_bmr/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/tmap_bmr/boards/nrf5340dk_nrf5340_cpuapp.conf index f7c6bbfd3db..8d48d5e1c20 100644 --- a/samples/bluetooth/tmap_bmr/boards/nrf5340dk_nrf5340_cpuapp.conf +++ b/samples/bluetooth/tmap_bmr/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -4,5 +4,3 @@ CONFIG_LIBLC3=y # The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence # inctease stack size for that thread. CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 -# LC3 lib requires floating point support in the c-lib NEWLIB is one way of getting that. -CONFIG_NEWLIB_LIBC=y diff --git a/samples/bluetooth/tmap_bmr/sample.yaml b/samples/bluetooth/tmap_bmr/sample.yaml index 2427ef9ca82..aaaa5296149 100644 --- a/samples/bluetooth/tmap_bmr/sample.yaml +++ b/samples/bluetooth/tmap_bmr/sample.yaml @@ -4,7 +4,10 @@ sample: tests: sample.bluetooth.tmap_bmr: harness: bluetooth - platform_allow: qemu_cortex_m3 qemu_x86 + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + - native_sim tags: bluetooth integration_platforms: - qemu_cortex_m3 diff --git a/samples/bluetooth/tmap_bms/boards/native_sim.conf b/samples/bluetooth/tmap_bms/boards/native_sim.conf new file mode 100644 index 00000000000..e06b2999381 --- /dev/null +++ b/samples/bluetooth/tmap_bms/boards/native_sim.conf @@ -0,0 +1,10 @@ +CONFIG_LOG_MODE_IMMEDIATE=y +CONFIG_BT_TINYCRYPT_ECC=y + +CONFIG_LIBLC3=y +CONFIG_FPU=y + +# For LE-audio at 10ms intervals we need the tick counter to occur more frequently +# than every 10 ms as each PDU for some reason takes 2 ticks to process. +CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 +CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME=y diff --git a/samples/bluetooth/tmap_bms/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/tmap_bms/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf index f7c6bbfd3db..8d48d5e1c20 100644 --- a/samples/bluetooth/tmap_bms/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf +++ b/samples/bluetooth/tmap_bms/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -4,5 +4,3 @@ CONFIG_LIBLC3=y # The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence # inctease stack size for that thread. CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 -# LC3 lib requires floating point support in the c-lib NEWLIB is one way of getting that. -CONFIG_NEWLIB_LIBC=y diff --git a/samples/bluetooth/tmap_bms/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/tmap_bms/boards/nrf5340dk_nrf5340_cpuapp.conf index f7c6bbfd3db..8d48d5e1c20 100644 --- a/samples/bluetooth/tmap_bms/boards/nrf5340dk_nrf5340_cpuapp.conf +++ b/samples/bluetooth/tmap_bms/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -4,5 +4,3 @@ CONFIG_LIBLC3=y # The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence # inctease stack size for that thread. CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 -# LC3 lib requires floating point support in the c-lib NEWLIB is one way of getting that. -CONFIG_NEWLIB_LIBC=y diff --git a/samples/bluetooth/tmap_bms/sample.yaml b/samples/bluetooth/tmap_bms/sample.yaml index 83bdc86a9a2..fc4410eac0e 100644 --- a/samples/bluetooth/tmap_bms/sample.yaml +++ b/samples/bluetooth/tmap_bms/sample.yaml @@ -4,7 +4,10 @@ sample: tests: sample.bluetooth.tmap_bms: harness: bluetooth - platform_allow: qemu_cortex_m3 qemu_x86 + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + - native_sim tags: bluetooth integration_platforms: - qemu_cortex_m3 diff --git a/samples/bluetooth/tmap_central/boards/native_sim.conf b/samples/bluetooth/tmap_central/boards/native_sim.conf new file mode 100644 index 00000000000..e06b2999381 --- /dev/null +++ b/samples/bluetooth/tmap_central/boards/native_sim.conf @@ -0,0 +1,10 @@ +CONFIG_LOG_MODE_IMMEDIATE=y +CONFIG_BT_TINYCRYPT_ECC=y + +CONFIG_LIBLC3=y +CONFIG_FPU=y + +# For LE-audio at 10ms intervals we need the tick counter to occur more frequently +# than every 10 ms as each PDU for some reason takes 2 ticks to process. +CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 +CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME=y diff --git a/samples/bluetooth/tmap_central/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/tmap_central/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf index f7c6bbfd3db..8d48d5e1c20 100644 --- a/samples/bluetooth/tmap_central/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf +++ b/samples/bluetooth/tmap_central/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -4,5 +4,3 @@ CONFIG_LIBLC3=y # The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence # inctease stack size for that thread. CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 -# LC3 lib requires floating point support in the c-lib NEWLIB is one way of getting that. -CONFIG_NEWLIB_LIBC=y diff --git a/samples/bluetooth/tmap_central/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/tmap_central/boards/nrf5340dk_nrf5340_cpuapp.conf index f7c6bbfd3db..8d48d5e1c20 100644 --- a/samples/bluetooth/tmap_central/boards/nrf5340dk_nrf5340_cpuapp.conf +++ b/samples/bluetooth/tmap_central/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -4,5 +4,3 @@ CONFIG_LIBLC3=y # The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence # inctease stack size for that thread. CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 -# LC3 lib requires floating point support in the c-lib NEWLIB is one way of getting that. -CONFIG_NEWLIB_LIBC=y diff --git a/samples/bluetooth/tmap_central/sample.yaml b/samples/bluetooth/tmap_central/sample.yaml index 3d0e1e8a08b..cf4dd362938 100644 --- a/samples/bluetooth/tmap_central/sample.yaml +++ b/samples/bluetooth/tmap_central/sample.yaml @@ -4,7 +4,10 @@ sample: tests: sample.bluetooth.tmap_central: harness: bluetooth - platform_allow: qemu_cortex_m3 qemu_x86 + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + - native_sim tags: bluetooth integration_platforms: - qemu_cortex_m3 diff --git a/samples/bluetooth/tmap_central/src/cap_initiator.c b/samples/bluetooth/tmap_central/src/cap_initiator.c index 2ddeada8037..1b45741e14b 100644 --- a/samples/bluetooth/tmap_central/src/cap_initiator.c +++ b/samples/bluetooth/tmap_central/src/cap_initiator.c @@ -196,7 +196,7 @@ static void print_remote_codec(const struct bt_audio_codec_cap *codec_cap, enum printk("codec id 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cap->id, codec_cap->cid, codec_cap->vid, codec_cap->data_len); - if (codec_cap->id == BT_AUDIO_CODEC_LC3_ID) { + if (codec_cap->id == BT_HCI_CODING_FORMAT_LC3) { bt_audio_data_parse(codec_cap->data, codec_cap->data_len, print_cb, "data"); } else { /* If not LC3, we cannot assume it's LTV */ printk("data: "); diff --git a/samples/bluetooth/tmap_peripheral/boards/native_sim.conf b/samples/bluetooth/tmap_peripheral/boards/native_sim.conf new file mode 100644 index 00000000000..e06b2999381 --- /dev/null +++ b/samples/bluetooth/tmap_peripheral/boards/native_sim.conf @@ -0,0 +1,10 @@ +CONFIG_LOG_MODE_IMMEDIATE=y +CONFIG_BT_TINYCRYPT_ECC=y + +CONFIG_LIBLC3=y +CONFIG_FPU=y + +# For LE-audio at 10ms intervals we need the tick counter to occur more frequently +# than every 10 ms as each PDU for some reason takes 2 ticks to process. +CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 +CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME=y diff --git a/samples/bluetooth/tmap_peripheral/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/tmap_peripheral/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf index f7c6bbfd3db..8d48d5e1c20 100644 --- a/samples/bluetooth/tmap_peripheral/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf +++ b/samples/bluetooth/tmap_peripheral/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -4,5 +4,3 @@ CONFIG_LIBLC3=y # The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence # inctease stack size for that thread. CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 -# LC3 lib requires floating point support in the c-lib NEWLIB is one way of getting that. -CONFIG_NEWLIB_LIBC=y diff --git a/samples/bluetooth/tmap_peripheral/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/tmap_peripheral/boards/nrf5340dk_nrf5340_cpuapp.conf index f7c6bbfd3db..8d48d5e1c20 100644 --- a/samples/bluetooth/tmap_peripheral/boards/nrf5340dk_nrf5340_cpuapp.conf +++ b/samples/bluetooth/tmap_peripheral/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -4,5 +4,3 @@ CONFIG_LIBLC3=y # The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence # inctease stack size for that thread. CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 -# LC3 lib requires floating point support in the c-lib NEWLIB is one way of getting that. -CONFIG_NEWLIB_LIBC=y diff --git a/samples/bluetooth/tmap_peripheral/prj.conf b/samples/bluetooth/tmap_peripheral/prj.conf index 756f86db3ab..6b7d7d390a8 100644 --- a/samples/bluetooth/tmap_peripheral/prj.conf +++ b/samples/bluetooth/tmap_peripheral/prj.conf @@ -32,11 +32,6 @@ CONFIG_BT_ASCS_ASE_SRC_COUNT=1 # Support an ISO channel per ASE CONFIG_BT_ISO_MAX_CHAN=2 -# Sink Contexts Supported: Unspecified, Conversational, Media -CONFIG_BT_PACS_SNK_CONTEXT=0x0007 -# Source Contexts Supported: Unspecified, Conversational, Media -CONFIG_BT_PACS_SRC_CONTEXT=0x0007 - # Sink PAC Location Support CONFIG_BT_PAC_SNK_LOC=y # Source PAC Location Support diff --git a/samples/bluetooth/tmap_peripheral/sample.yaml b/samples/bluetooth/tmap_peripheral/sample.yaml index 69f399c5b23..a2762635968 100644 --- a/samples/bluetooth/tmap_peripheral/sample.yaml +++ b/samples/bluetooth/tmap_peripheral/sample.yaml @@ -4,13 +4,19 @@ sample: tests: sample.bluetooth.tmap_peripheral: harness: bluetooth - platform_allow: qemu_cortex_m3 qemu_x86 + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + - native_sim tags: bluetooth integration_platforms: - qemu_cortex_m3 sample.bluetooth.tmap_peripheral.duo: harness: bluetooth - platform_allow: qemu_cortex_m3 qemu_x86 + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + - native_sim tags: bluetooth extra_args: OVERLAY_CONFIG="duo.conf" extra_configs: diff --git a/samples/bluetooth/tmap_peripheral/src/bap_unicast_sr.c b/samples/bluetooth/tmap_peripheral/src/bap_unicast_sr.c index 16556251c97..bb431ef478a 100644 --- a/samples/bluetooth/tmap_peripheral/src/bap_unicast_sr.c +++ b/samples/bluetooth/tmap_peripheral/src/bap_unicast_sr.c @@ -20,15 +20,14 @@ #include #include -#define AVAILABLE_SINK_CONTEXT CONFIG_BT_PACS_SNK_CONTEXT -#define AVAILABLE_SOURCE_CONTEXT CONFIG_BT_PACS_SRC_CONTEXT +#include "tmap_peripheral.h" static const struct bt_audio_codec_cap lc3_codec_cap = BT_AUDIO_CODEC_CAP_LC3(BT_AUDIO_CODEC_LC3_FREQ_16KHZ | BT_AUDIO_CODEC_LC3_FREQ_32KHZ | BT_AUDIO_CODEC_LC3_FREQ_48KHZ, BT_AUDIO_CODEC_LC3_DURATION_7_5 | BT_AUDIO_CODEC_LC3_DURATION_10, BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(2), 30, 155u, 1u, - (CONFIG_BT_PACS_SNK_CONTEXT | CONFIG_BT_PACS_SRC_CONTEXT)); + (AVAILABLE_SINK_CONTEXT | AVAILABLE_SOURCE_CONTEXT)); static struct bt_conn *default_conn; static struct bt_bap_stream streams[CONFIG_BT_ASCS_ASE_SNK_COUNT + CONFIG_BT_ASCS_ASE_SRC_COUNT]; @@ -64,17 +63,26 @@ static void print_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg) printk("codec_cfg 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cfg->id, codec_cfg->cid, codec_cfg->vid, codec_cfg->data_len); - if (codec_cfg->id == BT_AUDIO_CODEC_LC3_ID) { - /* LC3 uses the generic LTV format - other codecs might do as well */ - + if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) { enum bt_audio_location chan_allocation; + int ret; + + /* LC3 uses the generic LTV format - other codecs might do as well */ bt_audio_data_parse(codec_cfg->data, codec_cfg->data_len, print_cb, "data"); - printk(" Frequency: %d Hz\n", bt_audio_codec_cfg_get_freq(codec_cfg)); - printk(" Frame Duration: %d us\n", - bt_audio_codec_cfg_get_frame_duration_us(codec_cfg)); - if (bt_audio_codec_cfg_get_chan_allocation_val(codec_cfg, &chan_allocation) == 0) { + ret = bt_audio_codec_cfg_get_freq(codec_cfg); + if (ret > 0) { + printk(" Frequency: %d Hz\n", bt_audio_codec_cfg_freq_to_freq_hz(ret)); + } + + ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg); + if (ret > 0) { + printk(" Frame Duration: %d us\n", + bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret)); + } + + if (bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &chan_allocation) == 0) { printk(" Channel allocation: 0x%x\n", chan_allocation); } @@ -331,7 +339,7 @@ int bap_unicast_sr_init(void) { bt_bap_unicast_server_register_cb(&unicast_server_cb); - if (IS_ENABLED(CONFIG_BT_PAC_SNK_LOC)) { + if (IS_ENABLED(CONFIG_BT_PAC_SNK)) { /* Register CT required capabilities */ bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap); @@ -347,7 +355,7 @@ int bap_unicast_sr_init(void) AVAILABLE_SINK_CONTEXT); } - if (IS_ENABLED(CONFIG_BT_ASCS_ASE_SRC)) { + if (IS_ENABLED(CONFIG_BT_PAC_SRC)) { /* Register CT required capabilities */ bt_pacs_cap_register(BT_AUDIO_DIR_SOURCE, &cap); diff --git a/samples/bluetooth/tmap_peripheral/src/main.c b/samples/bluetooth/tmap_peripheral/src/main.c index 2fb2dd54c68..59aa8c70ef0 100644 --- a/samples/bluetooth/tmap_peripheral/src/main.c +++ b/samples/bluetooth/tmap_peripheral/src/main.c @@ -24,20 +24,15 @@ #include "tmap_peripheral.h" -#define AVAILABLE_SINK_CONTEXT (BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | \ - BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | \ - BT_AUDIO_CONTEXT_TYPE_MEDIA | \ - BT_AUDIO_CONTEXT_TYPE_GAME | \ - BT_AUDIO_CONTEXT_TYPE_INSTRUCTIONAL) - static struct bt_conn *default_conn; static struct k_work_delayable call_terminate_set_work; static struct k_work_delayable media_pause_set_work; static uint8_t unicast_server_addata[] = { - BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL), /* ASCS UUID */ + BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL), /* ASCS UUID */ BT_AUDIO_UNICAST_ANNOUNCEMENT_TARGETED, /* Target Announcement */ BT_BYTES_LIST_LE16(AVAILABLE_SINK_CONTEXT), + BT_BYTES_LIST_LE16(AVAILABLE_SOURCE_CONTEXT), 0x00, /* Metadata length */ }; @@ -47,8 +42,8 @@ static const uint8_t cap_addata[] = { }; static uint8_t tmap_addata[] = { - BT_UUID_16_ENCODE(BT_UUID_TMAS_VAL), /* TMAS UUID */ - (BT_TMAP_ROLE_UMR | BT_TMAP_ROLE_CT), 0x00, /* TMAP Role */ + BT_UUID_16_ENCODE(BT_UUID_TMAS_VAL), /* TMAS UUID */ + BT_BYTES_LIST_LE16(BT_TMAP_ROLE_UMR | BT_TMAP_ROLE_CT), /* TMAP Role */ }; static uint8_t csis_rsi_addata[BT_CSIP_RSI_SIZE]; @@ -57,7 +52,8 @@ static bool peer_is_ums; static const struct bt_data ad[] = { BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), - BT_DATA_BYTES(BT_DATA_GAP_APPEARANCE, 0x09, 0x41), /* Appearance - Earbud */ + BT_DATA_BYTES(BT_DATA_GAP_APPEARANCE, + BT_BYTES_LIST_LE16(BT_APPEARANCE_WEARABLE_AUDIO_DEVICE_EARBUD)), BT_DATA_BYTES(BT_DATA_UUID16_SOME, BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL), BT_UUID_16_ENCODE(BT_UUID_CAS_VAL), BT_UUID_16_ENCODE(BT_UUID_TMAS_VAL)), #if defined(CONFIG_BT_CSIP_SET_MEMBER) diff --git a/samples/bluetooth/tmap_peripheral/src/tmap_peripheral.h b/samples/bluetooth/tmap_peripheral/src/tmap_peripheral.h index b23a8adb23b..b01f5c8b0c8 100644 --- a/samples/bluetooth/tmap_peripheral/src/tmap_peripheral.h +++ b/samples/bluetooth/tmap_peripheral/src/tmap_peripheral.h @@ -6,6 +6,23 @@ #include +#if defined(CONFIG_BT_ASCS_ASE_SNK) +#define AVAILABLE_SINK_CONTEXT \ + (BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | \ + BT_AUDIO_CONTEXT_TYPE_MEDIA | BT_AUDIO_CONTEXT_TYPE_GAME | \ + BT_AUDIO_CONTEXT_TYPE_INSTRUCTIONAL) +#else +#define AVAILABLE_SINK_CONTEXT 0x0000 +#endif /* CONFIG_BT_ASCS_ASE_SNK */ + +#if defined(CONFIG_BT_ASCS_ASE_SRC) +#define AVAILABLE_SOURCE_CONTEXT \ + (BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | \ + BT_AUDIO_CONTEXT_TYPE_MEDIA | BT_AUDIO_CONTEXT_TYPE_GAME | \ + BT_AUDIO_CONTEXT_TYPE_INSTRUCTIONAL) +#else +#define AVAILABLE_SOURCE_CONTEXT 0x0000 +#endif /* CONFIG_BT_ASCS_ASE_SRC */ /** * @brief Initialize the VCP Volume Renderer role * diff --git a/samples/bluetooth/unicast_audio_client/Kconfig.sysbuild b/samples/bluetooth/unicast_audio_client/Kconfig.sysbuild new file mode 100644 index 00000000000..f434010f81d --- /dev/null +++ b/samples/bluetooth/unicast_audio_client/Kconfig.sysbuild @@ -0,0 +1,15 @@ +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config NET_CORE_BOARD + string + default "nrf5340dk_nrf5340_cpunet" if $(BOARD) = "nrf5340dk_nrf5340_cpuapp" + default "nrf5340_audio_dk_nrf5340_cpunet" if $(BOARD) = "nrf5340_audio_dk_nrf5340_cpuapp" + default "nrf5340bsim_nrf5340_cpunet" if $(BOARD) = "nrf5340bsim_nrf5340_cpuapp" + +config NET_CORE_IMAGE_HCI_IPC + bool "HCI IPC image on network core" + default y + depends on NET_CORE_BOARD != "" diff --git a/samples/bluetooth/unicast_audio_client/README.rst b/samples/bluetooth/unicast_audio_client/README.rst index dc3b336d9a3..3735aff4ebd 100644 --- a/samples/bluetooth/unicast_audio_client/README.rst +++ b/samples/bluetooth/unicast_audio_client/README.rst @@ -9,6 +9,10 @@ Overview Application demonstrating the LE Audio unicast client functionality. Scans for and connects to a LE Audio unicast server and establishes an audio stream. +This sample can be found under +:zephyr_file:`samples/bluetooth/unicast_audio_client` in the Zephyr tree. + +Check the :ref:`bluetooth samples section ` for general information. Requirements ************ @@ -18,9 +22,62 @@ Requirements Building and Running ******************** -This sample can be found under -:zephyr_file:`samples/bluetooth/unicast_audio_client` in the Zephyr tree. -Use `-DEXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf` to enable required ISO -feature support in Zephyr Bluetooth Controller on supported boards. -See :ref:`bluetooth samples section ` for details. +When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, +use `-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf` to enable the required ISO +feature support. + +Building for an nrf52840dk +-------------------------- + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/unicast_audio_client/ + :board: nrf52840dk_nrf52840 + :goals: build + :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + +Building for an nrf5340dk +------------------------- + +You can build both the application core image and an appropriate controller image for the network +core with: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/unicast_audio_client/ + :board: nrf5340dk_nrf5340_cpuapp + :goals: build + :west-args: --sysbuild + +If you prefer to only build the application core image, you can do so by doing instead: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/unicast_audio_server/ + :board: nrf5340dk_nrf5340_cpuapp + :goals: build + +In that case you can pair this application core image with the +:ref:`hci_ipc sample ` +:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. + +Building for a simulated nrf52_bsim +----------------------------------- + +Similarly to how you would for real HW, you can do: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/unicast_audio_client/ + :board: nrf52_bsim + :goals: build + :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + +Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. +For more information, check :ref:`this board documentation `. + +Building for a simulated nrf5340bsim +------------------------------------ + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/unicast_audio_client/ + :board: nrf5340bsim_nrf5340_cpuapp + :goals: build + :west-args: --sysbuild diff --git a/samples/bluetooth/unicast_audio_client/boards/native_posix.conf b/samples/bluetooth/unicast_audio_client/boards/native_sim.conf similarity index 100% rename from samples/bluetooth/unicast_audio_client/boards/native_posix.conf rename to samples/bluetooth/unicast_audio_client/boards/native_sim.conf diff --git a/samples/bluetooth/unicast_audio_client/boards/nrf52_bsim.conf b/samples/bluetooth/unicast_audio_client/boards/nrf52_bsim.conf new file mode 100644 index 00000000000..8bfd5bc41f9 --- /dev/null +++ b/samples/bluetooth/unicast_audio_client/boards/nrf52_bsim.conf @@ -0,0 +1,3 @@ +# For LC3 the following configs are needed +CONFIG_FPU=y +CONFIG_LIBLC3=y diff --git a/samples/bluetooth/unicast_audio_client/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/unicast_audio_client/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf index f7c6bbfd3db..8d48d5e1c20 100644 --- a/samples/bluetooth/unicast_audio_client/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf +++ b/samples/bluetooth/unicast_audio_client/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -4,5 +4,3 @@ CONFIG_LIBLC3=y # The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence # inctease stack size for that thread. CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 -# LC3 lib requires floating point support in the c-lib NEWLIB is one way of getting that. -CONFIG_NEWLIB_LIBC=y diff --git a/samples/bluetooth/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpuapp.conf b/samples/bluetooth/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpuapp.conf new file mode 100644 index 00000000000..7c6a3aecc26 --- /dev/null +++ b/samples/bluetooth/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpuapp.conf @@ -0,0 +1,10 @@ +# For LC3 the following configs are needed +CONFIG_FPU=y +CONFIG_LIBLC3=y + +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +CONFIG_BT_TINYCRYPT_ECC=y diff --git a/samples/bluetooth/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpunet.conf b/samples/bluetooth/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpunet.conf new file mode 100644 index 00000000000..1572abe6586 --- /dev/null +++ b/samples/bluetooth/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpunet.conf @@ -0,0 +1,6 @@ +# This configuration overlay is used when the controller, host and application are built +# all together in the network core + +# For LC3 the following configs are needed +CONFIG_FPU=y +CONFIG_LIBLC3=y diff --git a/samples/bluetooth/unicast_audio_client/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/unicast_audio_client/boards/nrf5340dk_nrf5340_cpuapp.conf index f7c6bbfd3db..76df8dba27a 100644 --- a/samples/bluetooth/unicast_audio_client/boards/nrf5340dk_nrf5340_cpuapp.conf +++ b/samples/bluetooth/unicast_audio_client/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -4,5 +4,10 @@ CONFIG_LIBLC3=y # The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence # inctease stack size for that thread. CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 -# LC3 lib requires floating point support in the c-lib NEWLIB is one way of getting that. -CONFIG_NEWLIB_LIBC=y + +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +CONFIG_BT_TINYCRYPT_ECC=y diff --git a/samples/bluetooth/unicast_audio_client/sample.yaml b/samples/bluetooth/unicast_audio_client/sample.yaml index 9ca15182f52..76ff71f350b 100644 --- a/samples/bluetooth/unicast_audio_client/sample.yaml +++ b/samples/bluetooth/unicast_audio_client/sample.yaml @@ -7,16 +7,19 @@ tests: platform_allow: - qemu_cortex_m3 - qemu_x86 + - nrf5340bsim_nrf5340_cpuapp + - nrf5340dk_nrf5340_cpuapp + - native_sim tags: bluetooth integration_platforms: - - qemu_cortex_m3 + - nrf5340dk_nrf5340_cpuapp + sysbuild: true sample.bluetooth.audio_unicast_client.bt_ll_sw_split: harness: bluetooth platform_allow: - - qemu_cortex_m3 - - qemu_x86 - nrf52_bsim - nrf52dk_nrf52832 + - nrf52840dk_nrf52840 integration_platforms: - nrf52dk_nrf52832 extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf diff --git a/samples/bluetooth/unicast_audio_client/src/main.c b/samples/bluetooth/unicast_audio_client/src/main.c index ff3c1311c36..3953bee99f0 100644 --- a/samples/bluetooth/unicast_audio_client/src/main.c +++ b/samples/bluetooth/unicast_audio_client/src/main.c @@ -19,6 +19,8 @@ static void start_scan(void); +uint64_t unicast_audio_recv_ctr; /* This value is exposed to test code */ + static struct bt_bap_unicast_client_cb unicast_client_cbs; static struct bt_conn *default_conn; static struct k_work_delayable audio_send_work; @@ -221,30 +223,41 @@ static void lc3_audio_timer_timeout(struct k_work *work) } } -static void init_lc3(void) +static int init_lc3(void) { const struct bt_audio_codec_cfg *codec_cfg = &codec_configuration.codec_cfg; unsigned int num_samples; + int ret; + + ret = bt_audio_codec_cfg_get_freq(codec_cfg); + if (ret > 0) { + freq_hz = bt_audio_codec_cfg_freq_to_freq_hz(ret); + } else { + return ret; + } + + ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg); + if (ret > 0) { + frame_duration_us = bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret); + } - freq_hz = bt_audio_codec_cfg_get_freq(codec_cfg); - frame_duration_us = bt_audio_codec_cfg_get_frame_duration_us(codec_cfg); octets_per_frame = bt_audio_codec_cfg_get_octets_per_frame(codec_cfg); frames_per_sdu = bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true); octets_per_frame = bt_audio_codec_cfg_get_octets_per_frame(codec_cfg); if (freq_hz < 0) { printk("Error: Codec frequency not set, cannot start codec."); - return; + return -1; } if (frame_duration_us < 0) { printk("Error: Frame duration not set, cannot start codec."); - return; + return -1; } if (octets_per_frame < 0) { printk("Error: Octets per frame not set, cannot start codec."); - return; + return -1; } frame_duration_100us = frame_duration_us / 100; @@ -266,12 +279,14 @@ static void init_lc3(void) if (lc3_encoder == NULL) { printk("ERROR: Failed to setup LC3 encoder - wrong parameters?\n"); + return -1; } + return 0; } #else -#define init_lc3(...) +#define init_lc3(...) 0 /** * @brief Send audio data on timeout @@ -369,7 +384,7 @@ static void print_codec_cap(const struct bt_audio_codec_cap *codec_cap) printk("codec id 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cap->id, codec_cap->cid, codec_cap->vid, codec_cap->data_len); - if (codec_cap->id == BT_AUDIO_CODEC_LC3_ID) { + if (codec_cap->id == BT_HCI_CODING_FORMAT_LC3) { bt_audio_data_parse(codec_cap->data, codec_cap->data_len, print_cb, "data"); } else { /* If not LC3, we cannot assume it's LTV */ printk("data: "); @@ -551,7 +566,9 @@ static void stream_recv(struct bt_bap_stream *stream, struct net_buf *buf) { if (info->flags & BT_ISO_FLAGS_VALID) { - printk("Incoming audio on stream %p len %u\n", stream, buf->len); + unicast_audio_recv_ctr++; + printk("Incoming audio on stream %p len %u (%"PRIu64")\n", stream, buf->len, + unicast_audio_recv_ctr); } } @@ -979,7 +996,11 @@ static int set_stream_qos(void) static int enable_streams(void) { if (IS_ENABLED(CONFIG_LIBLC3)) { - init_lc3(); + int err = init_lc3(); + + if (err != 0) { + return err; + } } for (size_t i = 0U; i < configured_stream_count; i++) { diff --git a/samples/bluetooth/unicast_audio_client/sysbuild.cmake b/samples/bluetooth/unicast_audio_client/sysbuild.cmake new file mode 100644 index 00000000000..2523aac8ea7 --- /dev/null +++ b/samples/bluetooth/unicast_audio_client/sysbuild.cmake @@ -0,0 +1,24 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) + # For builds in the nrf5340, we build the netcore image with the controller + + set(NET_APP hci_ipc) + set(NET_APP_SRC_DIR ${ZEPHYR_BASE}/samples/bluetooth/${NET_APP}) + + ExternalZephyrProject_Add( + APPLICATION ${NET_APP} + SOURCE_DIR ${NET_APP_SRC_DIR} + BOARD ${SB_CONFIG_NET_CORE_BOARD} + ) + + set(${NET_APP}_CONF_FILE + ${NET_APP_SRC_DIR}/nrf5340_cpunet_iso-bt_ll_sw_split.conf + CACHE INTERNAL "" + ) + + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) +endif() + +native_simulator_set_final_executable(${DEFAULT_IMAGE}) diff --git a/samples/bluetooth/unicast_audio_server/Kconfig.sysbuild b/samples/bluetooth/unicast_audio_server/Kconfig.sysbuild new file mode 100644 index 00000000000..f434010f81d --- /dev/null +++ b/samples/bluetooth/unicast_audio_server/Kconfig.sysbuild @@ -0,0 +1,15 @@ +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config NET_CORE_BOARD + string + default "nrf5340dk_nrf5340_cpunet" if $(BOARD) = "nrf5340dk_nrf5340_cpuapp" + default "nrf5340_audio_dk_nrf5340_cpunet" if $(BOARD) = "nrf5340_audio_dk_nrf5340_cpuapp" + default "nrf5340bsim_nrf5340_cpunet" if $(BOARD) = "nrf5340bsim_nrf5340_cpuapp" + +config NET_CORE_IMAGE_HCI_IPC + bool "HCI IPC image on network core" + default y + depends on NET_CORE_BOARD != "" diff --git a/samples/bluetooth/unicast_audio_server/README.rst b/samples/bluetooth/unicast_audio_server/README.rst index ce7151e5fb7..79a06244839 100644 --- a/samples/bluetooth/unicast_audio_server/README.rst +++ b/samples/bluetooth/unicast_audio_server/README.rst @@ -9,6 +9,11 @@ Overview Application demonstrating the LE Audio unicast server functionality. Starts advertising and awaits connection from a LE Audio unicast client. +This sample can be found under +:zephyr_file:`samples/bluetooth/unicast_audio_server` in the Zephyr tree. + +Check the :ref:`bluetooth samples section ` for general information. + Requirements ************ @@ -17,9 +22,62 @@ Requirements Building and Running ******************** -This sample can be found under -:zephyr_file:`samples/bluetooth/unicast_audio_server` in the Zephyr tree. -Use `-DEXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf` to enable required ISO -feature support in Zephyr Bluetooth Controller on supported boards. -See :ref:`bluetooth samples section ` for details. +When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, +use `-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf` to enable the required ISO +feature support. + +Building for an nrf52840dk +-------------------------- + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/unicast_audio_server/ + :board: nrf52840dk_nrf52840 + :goals: build + :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + +Building for an nrf5340dk +------------------------- + +You can build both the application core image and an appropriate controller image for the network +core with: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/unicast_audio_server/ + :board: nrf5340dk_nrf5340_cpuapp + :goals: build + :west-args: --sysbuild + +If you prefer to only build the application core image, you can do so by doing instead: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/unicast_audio_server/ + :board: nrf5340dk_nrf5340_cpuapp + :goals: build + +In that case you can pair this application core image with the +:ref:`hci_ipc sample ` +:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. + +Building for a simulated nrf52_bsim +----------------------------------- + +Similarly to how you would for real HW, you can do: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/unicast_audio_server/ + :board: nrf52_bsim + :goals: build + :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + +Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. +For more information, check :ref:`this board documentation `. + +Building for a simulated nrf5340bsim +------------------------------------ + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/unicast_audio_server/ + :board: nrf5340bsim_nrf5340_cpuapp + :goals: build + :west-args: --sysbuild diff --git a/samples/bluetooth/unicast_audio_server/boards/native_posix.conf b/samples/bluetooth/unicast_audio_server/boards/native_sim.conf similarity index 100% rename from samples/bluetooth/unicast_audio_server/boards/native_posix.conf rename to samples/bluetooth/unicast_audio_server/boards/native_sim.conf diff --git a/samples/bluetooth/unicast_audio_server/boards/nrf52_bsim.conf b/samples/bluetooth/unicast_audio_server/boards/nrf52_bsim.conf new file mode 100644 index 00000000000..8bfd5bc41f9 --- /dev/null +++ b/samples/bluetooth/unicast_audio_server/boards/nrf52_bsim.conf @@ -0,0 +1,3 @@ +# For LC3 the following configs are needed +CONFIG_FPU=y +CONFIG_LIBLC3=y diff --git a/samples/bluetooth/unicast_audio_server/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/unicast_audio_server/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf index f7c6bbfd3db..8d48d5e1c20 100644 --- a/samples/bluetooth/unicast_audio_server/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf +++ b/samples/bluetooth/unicast_audio_server/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -4,5 +4,3 @@ CONFIG_LIBLC3=y # The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence # inctease stack size for that thread. CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 -# LC3 lib requires floating point support in the c-lib NEWLIB is one way of getting that. -CONFIG_NEWLIB_LIBC=y diff --git a/samples/bluetooth/unicast_audio_server/boards/nrf5340bsim_nrf5340_cpuapp.conf b/samples/bluetooth/unicast_audio_server/boards/nrf5340bsim_nrf5340_cpuapp.conf new file mode 100644 index 00000000000..7c6a3aecc26 --- /dev/null +++ b/samples/bluetooth/unicast_audio_server/boards/nrf5340bsim_nrf5340_cpuapp.conf @@ -0,0 +1,10 @@ +# For LC3 the following configs are needed +CONFIG_FPU=y +CONFIG_LIBLC3=y + +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +CONFIG_BT_TINYCRYPT_ECC=y diff --git a/samples/bluetooth/unicast_audio_server/boards/nrf5340bsim_nrf5340_cpunet.conf b/samples/bluetooth/unicast_audio_server/boards/nrf5340bsim_nrf5340_cpunet.conf new file mode 100644 index 00000000000..8bfd5bc41f9 --- /dev/null +++ b/samples/bluetooth/unicast_audio_server/boards/nrf5340bsim_nrf5340_cpunet.conf @@ -0,0 +1,3 @@ +# For LC3 the following configs are needed +CONFIG_FPU=y +CONFIG_LIBLC3=y diff --git a/samples/bluetooth/unicast_audio_server/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/unicast_audio_server/boards/nrf5340dk_nrf5340_cpuapp.conf index f7c6bbfd3db..76df8dba27a 100644 --- a/samples/bluetooth/unicast_audio_server/boards/nrf5340dk_nrf5340_cpuapp.conf +++ b/samples/bluetooth/unicast_audio_server/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -4,5 +4,10 @@ CONFIG_LIBLC3=y # The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence # inctease stack size for that thread. CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 -# LC3 lib requires floating point support in the c-lib NEWLIB is one way of getting that. -CONFIG_NEWLIB_LIBC=y + +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +CONFIG_BT_TINYCRYPT_ECC=y diff --git a/samples/bluetooth/unicast_audio_server/sample.yaml b/samples/bluetooth/unicast_audio_server/sample.yaml index afb93362d1e..0c7496e288b 100644 --- a/samples/bluetooth/unicast_audio_server/sample.yaml +++ b/samples/bluetooth/unicast_audio_server/sample.yaml @@ -7,16 +7,19 @@ tests: platform_allow: - qemu_cortex_m3 - qemu_x86 + - nrf5340bsim_nrf5340_cpuapp + - nrf5340dk_nrf5340_cpuapp + - native_sim tags: bluetooth integration_platforms: - - qemu_cortex_m3 + - nrf5340dk_nrf5340_cpuapp + sysbuild: true sample.bluetooth.audio_unicast_server.bt_ll_sw_split: harness: bluetooth platform_allow: - - qemu_cortex_m3 - - qemu_x86 - nrf52_bsim - nrf52dk_nrf52832 + - nrf52840dk_nrf52840 integration_platforms: - nrf52dk_nrf52832 extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf diff --git a/samples/bluetooth/unicast_audio_server/src/main.c b/samples/bluetooth/unicast_audio_server/src/main.c index 05669c5d7e7..700c1a1ef1e 100644 --- a/samples/bluetooth/unicast_audio_server/src/main.c +++ b/samples/bluetooth/unicast_audio_server/src/main.c @@ -134,17 +134,26 @@ static void print_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg) printk("codec_cfg 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cfg->id, codec_cfg->cid, codec_cfg->vid, codec_cfg->data_len); - if (codec_cfg->id == BT_AUDIO_CODEC_LC3_ID) { - /* LC3 uses the generic LTV format - other codecs might do as well */ - + if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) { enum bt_audio_location chan_allocation; + int ret; + + /* LC3 uses the generic LTV format - other codecs might do as well */ bt_audio_data_parse(codec_cfg->data, codec_cfg->data_len, print_cb, "data"); - printk(" Frequency: %d Hz\n", bt_audio_codec_cfg_get_freq(codec_cfg)); - printk(" Frame Duration: %d us\n", - bt_audio_codec_cfg_get_frame_duration_us(codec_cfg)); - if (bt_audio_codec_cfg_get_chan_allocation_val(codec_cfg, &chan_allocation) == 0) { + ret = bt_audio_codec_cfg_get_freq(codec_cfg); + if (ret > 0) { + printk(" Frequency: %d Hz\n", bt_audio_codec_cfg_freq_to_freq_hz(ret)); + } + + ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg); + if (ret > 0) { + printk(" Frame Duration: %d us\n", + bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret)); + } + + if (bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &chan_allocation) == 0) { printk(" Channel allocation: 0x%x\n", chan_allocation); } @@ -349,22 +358,28 @@ static int lc3_enable(struct bt_bap_stream *stream, const uint8_t meta[], size_t #if defined(CONFIG_LIBLC3) { - const int freq = bt_audio_codec_cfg_get_freq(stream->codec_cfg); - const int frame_duration_us = - bt_audio_codec_cfg_get_frame_duration_us(stream->codec_cfg); + int frame_duration_us; + int freq; + int ret; - if (freq < 0) { + ret = bt_audio_codec_cfg_get_freq(stream->codec_cfg); + if (ret > 0) { + freq = bt_audio_codec_cfg_freq_to_freq_hz(ret); + } else { printk("Error: Codec frequency not set, cannot start codec."); *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_CONF_INVALID, BT_BAP_ASCS_REASON_CODEC_DATA); - return -1; + return ret; } - if (frame_duration_us < 0) { + ret = bt_audio_codec_cfg_get_frame_dur(stream->codec_cfg); + if (ret > 0) { + frame_duration_us = bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret); + } else { printk("Error: Frame duration not set, cannot start codec."); *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_CONF_INVALID, BT_BAP_ASCS_REASON_CODEC_DATA); - return -1; + return ret; } frames_per_sdu = diff --git a/samples/bluetooth/unicast_audio_server/sysbuild.cmake b/samples/bluetooth/unicast_audio_server/sysbuild.cmake new file mode 100644 index 00000000000..2523aac8ea7 --- /dev/null +++ b/samples/bluetooth/unicast_audio_server/sysbuild.cmake @@ -0,0 +1,24 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) + # For builds in the nrf5340, we build the netcore image with the controller + + set(NET_APP hci_ipc) + set(NET_APP_SRC_DIR ${ZEPHYR_BASE}/samples/bluetooth/${NET_APP}) + + ExternalZephyrProject_Add( + APPLICATION ${NET_APP} + SOURCE_DIR ${NET_APP_SRC_DIR} + BOARD ${SB_CONFIG_NET_CORE_BOARD} + ) + + set(${NET_APP}_CONF_FILE + ${NET_APP_SRC_DIR}/nrf5340_cpunet_iso-bt_ll_sw_split.conf + CACHE INTERNAL "" + ) + + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) +endif() + +native_simulator_set_final_executable(${DEFAULT_IMAGE}) diff --git a/samples/boards/esp32/deep_sleep/README.rst b/samples/boards/esp32/deep_sleep/README.rst index 97bf2902dcd..a5de4def742 100644 --- a/samples/boards/esp32/deep_sleep/README.rst +++ b/samples/boards/esp32/deep_sleep/README.rst @@ -51,7 +51,7 @@ Building, Flashing and Running .. zephyr-app-commands:: :zephyr-app: samples/boards/esp32/deep_sleep - :board: esp32 + :board: esp32_devkitc_wroom :goals: build flash :compact: diff --git a/samples/boards/esp32/deep_sleep/boards/esp32c3_luatos_core.conf b/samples/boards/esp32/deep_sleep/boards/esp32c3_luatos_core.conf new file mode 100644 index 00000000000..2ce9f6b8f5c --- /dev/null +++ b/samples/boards/esp32/deep_sleep/boards/esp32c3_luatos_core.conf @@ -0,0 +1 @@ +CONFIG_EXAMPLE_GPIO_WAKEUP=y diff --git a/samples/boards/esp32/deep_sleep/boards/esp32c3_luatos_core.overlay b/samples/boards/esp32/deep_sleep/boards/esp32c3_luatos_core.overlay new file mode 100644 index 00000000000..6235a933aec --- /dev/null +++ b/samples/boards/esp32/deep_sleep/boards/esp32c3_luatos_core.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + /* On ESP32-C3, only GPIO0~5 can be used + * as wake-up sources + */ + wakeup-button = &sample_button; + }; + + gpio_keys { + compatible = "gpio-keys"; + sample_button: sample_button { + gpios = <&gpio0 0 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; + }; + }; +}; diff --git a/samples/boards/esp32/deep_sleep/boards/esp32c3_luatos_core_usb.conf b/samples/boards/esp32/deep_sleep/boards/esp32c3_luatos_core_usb.conf new file mode 100644 index 00000000000..2ce9f6b8f5c --- /dev/null +++ b/samples/boards/esp32/deep_sleep/boards/esp32c3_luatos_core_usb.conf @@ -0,0 +1 @@ +CONFIG_EXAMPLE_GPIO_WAKEUP=y diff --git a/samples/boards/esp32/deep_sleep/boards/esp32c3_luatos_core_usb.overlay b/samples/boards/esp32/deep_sleep/boards/esp32c3_luatos_core_usb.overlay new file mode 100644 index 00000000000..6235a933aec --- /dev/null +++ b/samples/boards/esp32/deep_sleep/boards/esp32c3_luatos_core_usb.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + /* On ESP32-C3, only GPIO0~5 can be used + * as wake-up sources + */ + wakeup-button = &sample_button; + }; + + gpio_keys { + compatible = "gpio-keys"; + sample_button: sample_button { + gpios = <&gpio0 0 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; + }; + }; +}; diff --git a/samples/boards/esp32/flash_memory_mapped/CMakeLists.txt b/samples/boards/esp32/flash_memory_mapped/CMakeLists.txt new file mode 100644 index 00000000000..3cdbfb0e0b1 --- /dev/null +++ b/samples/boards/esp32/flash_memory_mapped/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(flash_memory_mapped) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/boards/esp32/flash_memory_mapped/README.rst b/samples/boards/esp32/flash_memory_mapped/README.rst new file mode 100644 index 00000000000..17940504fc0 --- /dev/null +++ b/samples/boards/esp32/flash_memory_mapped/README.rst @@ -0,0 +1,66 @@ +.. _flash_memory_mapped: + +Espressif ESP32 Flash Memory-Mapped +################################### + +Overview +******** + +ESP32 features memory hardware which allows regions of flash memory to be mapped into instruction +and data address spaces. This mapping works only for read operations. It is not possible to modify +contents of flash memory by writing to a mapped memory region. + +Mapping happens in 64 KB pages. Memory mapping hardware can map flash into the data address space +and the instruction address space. See the technical reference manual for more details and +limitations about memory mapping hardware. For more information, check `_ESP32 Flash Memory-Mapping`. + +Supported SoCs +************** + +All ESP32 SoCs support flash memory-mapped feature. + +Building and Running +******************** + +Make sure you have your board connected over USB port. + +.. code-block:: console + + west build -b esp32s3_devkitm samples/boards/esp32/flash_memory_mapped + west flash + +Sample Output +============= + +To check the output of this sample, run ``west espressif monitor`` or any other serial +console program (e.g., minicom, putty, screen, etc). +This example uses ``west espressif monitor``, which automatically detects the serial +port at ``/dev/ttyUSB0``: + +.. code-block:: console + + $ west espressif monitor + +The sample code erases the scratch area defined in DTS file and writes a 32-bytes data buffer in it. +Next, it prints that region content using flash API read and also using memory-mapped pointer. +Both readings should return the same value. Important to notice that writing using memory-mapped pointer +is not allowed. + + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc3-10-g3118724fa268 *** + [00:00:00.255,000] flash_memory_mapped: memory-mapped pointer address: 0x3c040000 + [00:00:01.122,000] flash_memory_mapped: flash read using memory-mapped pointer + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........ + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........ + [00:00:01.122,000] flash_memory_mapped: writing 32-bytes data using flash API + [00:00:01.122,000] flash_memory_mapped: flash read using flash API + 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |........ ........ + 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |........ ........ + [00:00:01.122,000] flash_memory_mapped: flash read using memory-mapped pointer + 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |........ ........ + 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |........ ........ + +.. _ESP32 Flash Memory-Mapping: + https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/spi_flash/index.html#memory-mapping-api diff --git a/samples/boards/esp32/flash_memory_mapped/prj.conf b/samples/boards/esp32/flash_memory_mapped/prj.conf new file mode 100644 index 00000000000..83a00f200cf --- /dev/null +++ b/samples/boards/esp32/flash_memory_mapped/prj.conf @@ -0,0 +1,3 @@ +CONFIG_LOG=y +CONFIG_FLASH=y +CONFIG_FLASH_PAGE_LAYOUT=y diff --git a/samples/boards/esp32/flash_memory_mapped/sample.yaml b/samples/boards/esp32/flash_memory_mapped/sample.yaml new file mode 100644 index 00000000000..c8601961d94 --- /dev/null +++ b/samples/boards/esp32/flash_memory_mapped/sample.yaml @@ -0,0 +1,10 @@ +sample: + description: Sample application to test memory-mapped flash region + name: flash_memory_mapped +tests: + sample.board.esp32.flash_memory_mapped: + platform_allow: + - esp32_devkitc_wroom + - esp32c3_devkitm + - esp32s3_devkitm + tags: esp32 diff --git a/samples/boards/esp32/flash_memory_mapped/src/main.c b/samples/boards/esp32/flash_memory_mapped/src/main.c new file mode 100644 index 00000000000..a29d6db08ec --- /dev/null +++ b/samples/boards/esp32/flash_memory_mapped/src/main.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +LOG_MODULE_REGISTER(flash_memory_mapped, CONFIG_LOG_DEFAULT_LEVEL); + +int main(void) +{ + uint8_t buffer[32]; + const struct device *flash_device; + const void *mem_ptr; + spi_flash_mmap_handle_t handle; + off_t address = FIXED_PARTITION_OFFSET(scratch_partition); + size_t size = FIXED_PARTITION_SIZE(scratch_partition); + + flash_device = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller)); + if (!device_is_ready(flash_device)) { + printk("%s: device not ready.\n", flash_device->name); + return 0; + } + + /* map selected region */ + spi_flash_mmap(address, size, SPI_FLASH_MMAP_DATA, &mem_ptr, &handle); + LOG_INF("memory-mapped pointer address: %p", mem_ptr); + + /* erase and read flash */ + flash_erase(flash_device, address, size); + LOG_HEXDUMP_INF(mem_ptr, 32, "flash read using memory-mapped pointer"); + + LOG_INF("writing 32-bytes data using flash API"); + memset(buffer, 0, sizeof(buffer)); + for (int k = 0; k < 32; k++) { + buffer[k] = k; + } + flash_write(flash_device, address, buffer, 32); + + /* read using flash API */ + memset(buffer, 0, sizeof(buffer)); + flash_read(flash_device, address, buffer, 32); + LOG_HEXDUMP_INF(buffer, 32, "flash read using flash API"); + + LOG_HEXDUMP_INF(mem_ptr, 32, "flash read using memory-mapped pointer"); + + /* unmap mapped region */ + spi_flash_munmap(handle); + + return 0; +} diff --git a/samples/boards/esp32/light_sleep/README.rst b/samples/boards/esp32/light_sleep/README.rst index 3afc3ba82a2..581e9a352b9 100644 --- a/samples/boards/esp32/light_sleep/README.rst +++ b/samples/boards/esp32/light_sleep/README.rst @@ -31,7 +31,7 @@ Building, Flashing and Running .. zephyr-app-commands:: :zephyr-app: samples/boards/esp32/light_sleep - :board: esp32 + :board: esp32_devkitc_wroom :goals: build flash :compact: diff --git a/samples/boards/google_twinkie_v2_pda/src/meas.c b/samples/boards/google_twinkie_v2_pda/src/meas.c index 5d2ba9c793c..15b9b877931 100644 --- a/samples/boards/google_twinkie_v2_pda/src/meas.c +++ b/samples/boards/google_twinkie_v2_pda/src/meas.c @@ -33,7 +33,7 @@ int meas_vbus_v(int32_t *v) }; adc_sequence_init_dt(&adc_vbus_v.port, &sequence); - ret = adc_read(adc_vbus_v.port.dev, &sequence); + ret = adc_read_dt(&adc_vbus_v.port, &sequence); if (ret != 0) { return ret; } diff --git a/samples/boards/mimxrt1170_evk_cm7/magic_addr/CMakeLists.txt b/samples/boards/mimxrt1170_evk_cm7/magic_addr/CMakeLists.txt new file mode 100644 index 00000000000..b8af716702a --- /dev/null +++ b/samples/boards/mimxrt1170_evk_cm7/magic_addr/CMakeLists.txt @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(magic_addr) + +zephyr_library_include_directories(${ZEPHYR_BASE}/drivers/memc) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/boards/mimxrt1170_evk_cm7/magic_addr/README.rst b/samples/boards/mimxrt1170_evk_cm7/magic_addr/README.rst new file mode 100644 index 00000000000..679343d84ff --- /dev/null +++ b/samples/boards/mimxrt1170_evk_cm7/magic_addr/README.rst @@ -0,0 +1,18 @@ +.. _flexram_magic_addr: + +FLEXRAM Magic Addr +################## + +Overview +******** + +A sample that shows how to use RT11XX FLEXRAM Magic Addr functionality + +Magic Addr is a feature of FlexRAM that allows user to configure an interrupt +on an arbitrary RAM/TCM address access. This sample shows how to use the custom +API for the flexram in zephyr to use this unique feature. + +Building and Running +******************** + +see board documentation diff --git a/samples/boards/mimxrt1170_evk_cm7/magic_addr/prj.conf b/samples/boards/mimxrt1170_evk_cm7/magic_addr/prj.conf new file mode 100644 index 00000000000..b58887f4998 --- /dev/null +++ b/samples/boards/mimxrt1170_evk_cm7/magic_addr/prj.conf @@ -0,0 +1,3 @@ +CONFIG_MEMC_NXP_FLEXRAM_MAGIC_ADDR_API=y +CONFIG_CONSOLE_SUBSYS=y +CONFIG_CONSOLE_GETCHAR=y diff --git a/samples/boards/mimxrt1170_evk_cm7/magic_addr/sample.yaml b/samples/boards/mimxrt1170_evk_cm7/magic_addr/sample.yaml new file mode 100644 index 00000000000..10e876847f7 --- /dev/null +++ b/samples/boards/mimxrt1170_evk_cm7/magic_addr/sample.yaml @@ -0,0 +1,12 @@ +sample: + description: RT1170 FLEXRAM Magic Addr example + name: magic addr +common: + integration_platforms: + - mimxrt1170_evk_cm7 + - mimxrt1160_evk_cm7 +tests: + sample.boards.mimxrt1170_evk.magic_addr: + platform_allow: + - mimxrt1170_evk_cm7 + - mimxrt1160_evk_cm7 diff --git a/samples/boards/mimxrt1170_evk_cm7/magic_addr/src/main.c b/samples/boards/mimxrt1170_evk_cm7/magic_addr/src/main.c new file mode 100644 index 00000000000..6856ca8f10f --- /dev/null +++ b/samples/boards/mimxrt1170_evk_cm7/magic_addr/src/main.c @@ -0,0 +1,58 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "memc_nxp_flexram.h" +#include +#include +#include + +K_SEM_DEFINE(dtcm_magic, 0, 1); + +__dtcm_bss_section uint8_t var; +int cnt; + +void flexram_magic_addr_isr_cb(enum memc_flexram_interrupt_cause cause, + void *data) +{ + ARG_UNUSED(data); + + if (cause == flexram_dtcm_magic_addr) { + printf("Magic DTCM address accessed %d times\n", ++cnt); + k_sem_give(&dtcm_magic); + } +} + + +int main(void) +{ + memc_flexram_register_callback(flexram_magic_addr_isr_cb, NULL); + + console_init(); + + printf("%s is opening spellbook...\n", CONFIG_BOARD); + printf("Cast some characters:\n"); + + uint32_t dtcm_addr = (uint32_t)&var; + + memc_flexram_set_dtcm_magic_addr(dtcm_addr); + + uint8_t tmp; + + while (1) { + printf("\n"); + tmp = console_getchar(); + printf("Writing %c to magic addr...\n", tmp); + var = tmp; + k_sem_take(&dtcm_magic, K_FOREVER); + printf("Reading from magic addr...\n"); + printf("Magic variable got: %c\n", var); + k_sem_take(&dtcm_magic, K_FOREVER); + } + + return 0; +} diff --git a/samples/boards/nrf/clock_skew/prj.conf b/samples/boards/nrf/clock_skew/prj.conf index 8ef0d31e37a..957f0d60648 100644 --- a/samples/boards/nrf/clock_skew/prj.conf +++ b/samples/boards/nrf/clock_skew/prj.conf @@ -1,3 +1,3 @@ CONFIG_COUNTER=y -CONFIG_NEWLIB_LIBC=y -CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y +CONFIG_REQUIRES_FULL_LIBC=y +CONFIG_REQUIRES_FLOAT_PRINTF=y diff --git a/samples/boards/nrf/ieee802154/802154_rpmsg/sample.yaml b/samples/boards/nrf/ieee802154/802154_rpmsg/sample.yaml index fe31e48ff84..d99dcceaa32 100644 --- a/samples/boards/nrf/ieee802154/802154_rpmsg/sample.yaml +++ b/samples/boards/nrf/ieee802154/802154_rpmsg/sample.yaml @@ -5,4 +5,6 @@ sample: tests: sample.boards.nrf.802154_rpmsg: build_only: true - platform_allow: nrf5340dk_nrf5340_cpunet + platform_allow: + - nrf5340dk_nrf5340_cpunet + - nrf5340bsim_nrf5340_cpunet diff --git a/samples/boards/nrf/mesh/onoff-app/src/main.c b/samples/boards/nrf/mesh/onoff-app/src/main.c index 9e8788d4642..f0755cb70ab 100644 --- a/samples/boards/nrf/mesh/onoff-app/src/main.c +++ b/samples/boards/nrf/mesh/onoff-app/src/main.c @@ -54,19 +54,19 @@ #define BT_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK BT_MESH_MODEL_OP_2(0x82, 0x03) #define BT_MESH_MODEL_OP_GEN_ONOFF_STATUS BT_MESH_MODEL_OP_2(0x82, 0x04) -static int gen_onoff_set(struct bt_mesh_model *model, +static int gen_onoff_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf); -static int gen_onoff_set_unack(struct bt_mesh_model *model, +static int gen_onoff_set_unack(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf); -static int gen_onoff_get(struct bt_mesh_model *model, +static int gen_onoff_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf); -static int gen_onoff_status(struct bt_mesh_model *model, +static int gen_onoff_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf); @@ -167,7 +167,7 @@ static struct led_onoff_state led_onoff_states[] = { * Element 0 Root Models */ -static struct bt_mesh_model root_models[] = { +static const struct bt_mesh_model root_models[] = { BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub), @@ -181,7 +181,7 @@ static struct bt_mesh_model root_models[] = { * Element 1 Models */ -static struct bt_mesh_model secondary_0_models[] = { +static const struct bt_mesh_model secondary_0_models[] = { BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_srv_op, &gen_onoff_pub_srv_s_0, &led_onoff_states[1]), BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_CLI, gen_onoff_cli_op, @@ -192,7 +192,7 @@ static struct bt_mesh_model secondary_0_models[] = { * Element 2 Models */ -static struct bt_mesh_model secondary_1_models[] = { +static const struct bt_mesh_model secondary_1_models[] = { BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_srv_op, &gen_onoff_pub_srv_s_1, &led_onoff_states[2]), BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_CLI, gen_onoff_cli_op, @@ -203,7 +203,7 @@ static struct bt_mesh_model secondary_1_models[] = { * Element 3 Models */ -static struct bt_mesh_model secondary_2_models[] = { +static const struct bt_mesh_model secondary_2_models[] = { BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_srv_op, &gen_onoff_pub_srv_s_2, &led_onoff_states[3]), BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_CLI, gen_onoff_cli_op, @@ -214,7 +214,7 @@ static struct bt_mesh_model secondary_2_models[] = { * Button to Client Model Assignments */ -struct bt_mesh_model *mod_cli_sw[] = { +const struct bt_mesh_model *mod_cli_sw[] = { &root_models[4], &secondary_0_models[1], &secondary_1_models[1], @@ -225,7 +225,7 @@ struct bt_mesh_model *mod_cli_sw[] = { * LED to Server Model Assignments */ -struct bt_mesh_model *mod_srv_sw[] = { +const struct bt_mesh_model *mod_srv_sw[] = { &root_models[3], &secondary_0_models[0], &secondary_1_models[0], @@ -236,7 +236,7 @@ struct bt_mesh_model *mod_srv_sw[] = { * Root and Secondary Element Declarations */ -static struct bt_mesh_elem elements[] = { +static const struct bt_mesh_elem elements[] = { BT_MESH_ELEM(0, root_models, BT_MESH_MODEL_NONE), BT_MESH_ELEM(0, secondary_0_models, BT_MESH_MODEL_NONE), BT_MESH_ELEM(0, secondary_1_models, BT_MESH_MODEL_NONE), @@ -281,15 +281,15 @@ static uint16_t primary_net_idx; * */ -static int gen_onoff_get(struct bt_mesh_model *model, +static int gen_onoff_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4); - struct led_onoff_state *onoff_state = model->user_data; + struct led_onoff_state *onoff_state = model->rt->user_data; printk("addr 0x%04x onoff 0x%02x\n", - bt_mesh_model_elem(model)->addr, onoff_state->current); + bt_mesh_model_elem(model)->rt->addr, onoff_state->current); bt_mesh_model_msg_init(&msg, BT_MESH_MODEL_OP_GEN_ONOFF_STATUS); net_buf_simple_add_u8(&msg, onoff_state->current); @@ -300,17 +300,17 @@ static int gen_onoff_get(struct bt_mesh_model *model, return 0; } -static int gen_onoff_set_unack(struct bt_mesh_model *model, +static int gen_onoff_set_unack(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { struct net_buf_simple *msg = model->pub->msg; - struct led_onoff_state *onoff_state = model->user_data; + struct led_onoff_state *onoff_state = model->rt->user_data; int err; onoff_state->current = net_buf_simple_pull_u8(buf); printk("addr 0x%02x state 0x%02x\n", - bt_mesh_model_elem(model)->addr, onoff_state->current); + bt_mesh_model_elem(model)->rt->addr, onoff_state->current); gpio_pin_set_dt(&onoff_state->led_device, onoff_state->current); @@ -340,7 +340,7 @@ static int gen_onoff_set_unack(struct bt_mesh_model *model, return 0; } -static int gen_onoff_set(struct bt_mesh_model *model, +static int gen_onoff_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -352,7 +352,7 @@ static int gen_onoff_set(struct bt_mesh_model *model, return 0; } -static int gen_onoff_status(struct bt_mesh_model *model, +static int gen_onoff_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -361,7 +361,7 @@ static int gen_onoff_status(struct bt_mesh_model *model, state = net_buf_simple_pull_u8(buf); printk("Node 0x%04x OnOff status from 0x%04x with state 0x%02x\n", - bt_mesh_model_elem(model)->addr, ctx->addr, state); + bt_mesh_model_elem(model)->rt->addr, ctx->addr, state); return 0; } @@ -465,7 +465,7 @@ static void button_cnt_timer(struct k_timer *work) static void button_pressed_worker(struct k_work *work) { - struct bt_mesh_model *mod_cli, *mod_srv; + const struct bt_mesh_model *mod_cli, *mod_srv; struct bt_mesh_model_pub *pub_cli, *pub_srv; struct switch_data *button_sw = CONTAINER_OF(work, struct switch_data, button_work); int err; diff --git a/samples/boards/nrf/mesh/onoff_level_lighting_vnd_app/src/mesh/device_composition.c b/samples/boards/nrf/mesh/onoff_level_lighting_vnd_app/src/mesh/device_composition.c index 2cf7abc3048..1c59ef8fbd7 100644 --- a/samples/boards/nrf/mesh/onoff_level_lighting_vnd_app/src/mesh/device_composition.c +++ b/samples/boards/nrf/mesh/onoff_level_lighting_vnd_app/src/mesh/device_composition.c @@ -63,12 +63,12 @@ struct vendor_state vnd_user_data; /* Definitions of models user data (End) */ -static struct bt_mesh_elem elements[]; +static const struct bt_mesh_elem elements[]; /* message handlers (Start) */ /* Generic OnOff Server message handlers */ -static int gen_onoff_get(struct bt_mesh_model *model, +static int gen_onoff_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -95,7 +95,7 @@ static int gen_onoff_get(struct bt_mesh_model *model, return 0; } -void gen_onoff_publish(struct bt_mesh_model *model) +void gen_onoff_publish(const struct bt_mesh_model *model) { int err; struct net_buf_simple *msg = model->pub->msg; @@ -119,7 +119,7 @@ void gen_onoff_publish(struct bt_mesh_model *model) } } -static int gen_onoff_set_unack(struct bt_mesh_model *model, +static int gen_onoff_set_unack(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -188,7 +188,7 @@ static int gen_onoff_set_unack(struct bt_mesh_model *model, return 0; } -static int gen_onoff_set(struct bt_mesh_model *model, +static int gen_onoff_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -261,7 +261,7 @@ static int gen_onoff_set(struct bt_mesh_model *model, } /* Generic OnOff Client message handlers */ -static int gen_onoff_status(struct bt_mesh_model *model, +static int gen_onoff_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -277,7 +277,7 @@ static int gen_onoff_status(struct bt_mesh_model *model, } /* Generic Level (LIGHTNESS) Server message handlers */ -static int gen_level_get(struct bt_mesh_model *model, +static int gen_level_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -304,7 +304,7 @@ static int gen_level_get(struct bt_mesh_model *model, return 0; } -void gen_level_publish(struct bt_mesh_model *model) +void gen_level_publish(const struct bt_mesh_model *model) { int err; struct net_buf_simple *msg = model->pub->msg; @@ -328,7 +328,7 @@ void gen_level_publish(struct bt_mesh_model *model) } } -static int gen_level_set_unack(struct bt_mesh_model *model, +static int gen_level_set_unack(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -394,7 +394,7 @@ static int gen_level_set_unack(struct bt_mesh_model *model, return 0; } -static int gen_level_set(struct bt_mesh_model *model, +static int gen_level_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -463,7 +463,7 @@ static int gen_level_set(struct bt_mesh_model *model, return 0; } -static int gen_delta_set_unack(struct bt_mesh_model *model, +static int gen_delta_set_unack(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -545,7 +545,7 @@ static int gen_delta_set_unack(struct bt_mesh_model *model, return 0; } -static int gen_delta_set(struct bt_mesh_model *model, +static int gen_delta_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -630,7 +630,7 @@ static int gen_delta_set(struct bt_mesh_model *model, return 0; } -static int gen_move_set_unack(struct bt_mesh_model *model, +static int gen_move_set_unack(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -705,7 +705,7 @@ static int gen_move_set_unack(struct bt_mesh_model *model, return 0; } -static int gen_move_set(struct bt_mesh_model *model, +static int gen_move_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { uint8_t tid, tt, delay; @@ -783,7 +783,7 @@ static int gen_move_set(struct bt_mesh_model *model, } /* Generic Level Client message handlers */ -static int gen_level_status(struct bt_mesh_model *model, +static int gen_level_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -799,7 +799,7 @@ static int gen_level_status(struct bt_mesh_model *model, } /* Generic Default Transition Time Server message handlers */ -static int gen_def_trans_time_get(struct bt_mesh_model *model, +static int gen_def_trans_time_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -815,7 +815,7 @@ static int gen_def_trans_time_get(struct bt_mesh_model *model, return 0; } -static void gen_def_trans_time_publish(struct bt_mesh_model *model) +static void gen_def_trans_time_publish(const struct bt_mesh_model *model) { int err; struct net_buf_simple *msg = model->pub->msg; @@ -833,7 +833,7 @@ static void gen_def_trans_time_publish(struct bt_mesh_model *model) } } -static int gen_def_trans_time_set_unack(struct bt_mesh_model *model, +static int gen_def_trans_time_set_unack(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -855,7 +855,7 @@ static int gen_def_trans_time_set_unack(struct bt_mesh_model *model, return 0; } -static int gen_def_trans_time_set(struct bt_mesh_model *model, +static int gen_def_trans_time_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -881,7 +881,7 @@ static int gen_def_trans_time_set(struct bt_mesh_model *model, } /* Generic Default Transition Time Client message handlers */ -static int gen_def_trans_time_status(struct bt_mesh_model *model, +static int gen_def_trans_time_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -892,7 +892,7 @@ static int gen_def_trans_time_status(struct bt_mesh_model *model, } /* Generic Power OnOff Server message handlers */ -static int gen_onpowerup_get(struct bt_mesh_model *model, +static int gen_onpowerup_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -909,7 +909,7 @@ static int gen_onpowerup_get(struct bt_mesh_model *model, } /* Generic Power OnOff Client message handlers */ -static int gen_onpowerup_status(struct bt_mesh_model *model, +static int gen_onpowerup_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -921,7 +921,7 @@ static int gen_onpowerup_status(struct bt_mesh_model *model, /* Generic Power OnOff Setup Server message handlers */ -static void gen_onpowerup_publish(struct bt_mesh_model *model) +static void gen_onpowerup_publish(const struct bt_mesh_model *model) { int err; struct net_buf_simple *msg = model->pub->msg; @@ -939,7 +939,7 @@ static void gen_onpowerup_publish(struct bt_mesh_model *model) } } -static int gen_onpowerup_set_unack(struct bt_mesh_model *model, +static int gen_onpowerup_set_unack(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -961,7 +961,7 @@ static int gen_onpowerup_set_unack(struct bt_mesh_model *model, return 0; } -static int gen_onpowerup_set(struct bt_mesh_model *model, +static int gen_onpowerup_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -987,11 +987,11 @@ static int gen_onpowerup_set(struct bt_mesh_model *model, } /* Vendor Model message handlers*/ -static int vnd_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int vnd_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { struct net_buf_simple *msg = NET_BUF_SIMPLE(3 + 6 + 4); - struct vendor_state *state = model->user_data; + struct vendor_state *state = model->rt->user_data; /* This is dummy response for demo purpose */ state->response = 0xA578FEB3; @@ -1007,14 +1007,14 @@ static int vnd_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, return 0; } -static int vnd_set_unack(struct bt_mesh_model *model, +static int vnd_set_unack(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { uint8_t tid; int current; int64_t now; - struct vendor_state *state = model->user_data; + struct vendor_state *state = model->rt->user_data; current = net_buf_simple_pull_le16(buf); tid = net_buf_simple_pull_u8(buf); @@ -1040,7 +1040,7 @@ static int vnd_set_unack(struct bt_mesh_model *model, return 0; } -static int vnd_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int vnd_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { (void)vnd_set_unack(model, ctx, buf); @@ -1049,7 +1049,7 @@ static int vnd_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, return 0; } -static int vnd_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int vnd_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { printk("Acknowledgement from Vendor\n"); @@ -1060,7 +1060,7 @@ static int vnd_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, } /* Light Lightness Server message handlers */ -static int light_lightness_get(struct bt_mesh_model *model, +static int light_lightness_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1087,7 +1087,7 @@ static int light_lightness_get(struct bt_mesh_model *model, return 0; } -void light_lightness_publish(struct bt_mesh_model *model) +void light_lightness_publish(const struct bt_mesh_model *model) { int err; struct net_buf_simple *msg = model->pub->msg; @@ -1111,7 +1111,7 @@ void light_lightness_publish(struct bt_mesh_model *model) } } -static int light_lightness_set_unack(struct bt_mesh_model *model, +static int light_lightness_set_unack(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1177,7 +1177,7 @@ static int light_lightness_set_unack(struct bt_mesh_model *model, return 0; } -static int light_lightness_set(struct bt_mesh_model *model, +static int light_lightness_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1246,7 +1246,7 @@ static int light_lightness_set(struct bt_mesh_model *model, return 0; } -static int light_lightness_linear_get(struct bt_mesh_model *model, +static int light_lightness_linear_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1274,7 +1274,7 @@ static int light_lightness_linear_get(struct bt_mesh_model *model, return 0; } -void light_lightness_linear_publish(struct bt_mesh_model *model) +void light_lightness_linear_publish(const struct bt_mesh_model *model) { int err; struct net_buf_simple *msg = model->pub->msg; @@ -1299,7 +1299,7 @@ void light_lightness_linear_publish(struct bt_mesh_model *model) } } -static int light_lightness_linear_set_unack(struct bt_mesh_model *model, +static int light_lightness_linear_set_unack(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1365,7 +1365,7 @@ static int light_lightness_linear_set_unack(struct bt_mesh_model *model, return 0; } -static int light_lightness_linear_set(struct bt_mesh_model *model, +static int light_lightness_linear_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1434,7 +1434,7 @@ static int light_lightness_linear_set(struct bt_mesh_model *model, return 0; } -static int light_lightness_last_get(struct bt_mesh_model *model, +static int light_lightness_last_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1450,7 +1450,7 @@ static int light_lightness_last_get(struct bt_mesh_model *model, return 0; } -static int light_lightness_default_get(struct bt_mesh_model *model, +static int light_lightness_default_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1467,7 +1467,7 @@ static int light_lightness_default_get(struct bt_mesh_model *model, return 0; } -static int light_lightness_range_get(struct bt_mesh_model *model, +static int light_lightness_range_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1489,7 +1489,7 @@ static int light_lightness_range_get(struct bt_mesh_model *model, /* Light Lightness Setup Server message handlers */ -static void light_lightness_default_publish(struct bt_mesh_model *model) +static void light_lightness_default_publish(const struct bt_mesh_model *model) { int err; struct net_buf_simple *msg = model->pub->msg; @@ -1508,7 +1508,7 @@ static void light_lightness_default_publish(struct bt_mesh_model *model) } } -static int light_lightness_default_set_unack(struct bt_mesh_model *model, +static int light_lightness_default_set_unack(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1527,7 +1527,7 @@ static int light_lightness_default_set_unack(struct bt_mesh_model *model, return 0; } -static int light_lightness_default_set(struct bt_mesh_model *model, +static int light_lightness_default_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1549,7 +1549,7 @@ static int light_lightness_default_set(struct bt_mesh_model *model, return 0; } -static void light_lightness_range_publish(struct bt_mesh_model *model) +static void light_lightness_range_publish(const struct bt_mesh_model *model) { int err; struct net_buf_simple *msg = model->pub->msg; @@ -1569,7 +1569,7 @@ static void light_lightness_range_publish(struct bt_mesh_model *model) } } -static int light_lightness_range_set_unack(struct bt_mesh_model *model, +static int light_lightness_range_set_unack(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1603,7 +1603,7 @@ static int light_lightness_range_set_unack(struct bt_mesh_model *model, return 0; } -static int light_lightness_range_set(struct bt_mesh_model *model, +static int light_lightness_range_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1641,7 +1641,7 @@ static int light_lightness_range_set(struct bt_mesh_model *model, } /* Light Lightness Client message handlers */ -static int light_lightness_status(struct bt_mesh_model *model, +static int light_lightness_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1657,7 +1657,7 @@ static int light_lightness_status(struct bt_mesh_model *model, return 0; } -static int light_lightness_linear_status(struct bt_mesh_model *model, +static int light_lightness_linear_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1673,7 +1673,7 @@ static int light_lightness_linear_status(struct bt_mesh_model *model, return 0; } -static int light_lightness_last_status(struct bt_mesh_model *model, +static int light_lightness_last_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1683,7 +1683,7 @@ static int light_lightness_last_status(struct bt_mesh_model *model, return 0; } -static int light_lightness_default_status(struct bt_mesh_model *model, +static int light_lightness_default_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1693,7 +1693,7 @@ static int light_lightness_default_status(struct bt_mesh_model *model, return 0; } -static int light_lightness_range_status(struct bt_mesh_model *model, +static int light_lightness_range_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1706,7 +1706,7 @@ static int light_lightness_range_status(struct bt_mesh_model *model, } /* Light CTL Server message handlers */ -static int light_ctl_get(struct bt_mesh_model *model, +static int light_ctl_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1736,7 +1736,7 @@ static int light_ctl_get(struct bt_mesh_model *model, return 0; } -void light_ctl_publish(struct bt_mesh_model *model) +void light_ctl_publish(const struct bt_mesh_model *model) { int err; struct net_buf_simple *msg = model->pub->msg; @@ -1766,7 +1766,7 @@ void light_ctl_publish(struct bt_mesh_model *model) } } -static int light_ctl_set_unack(struct bt_mesh_model *model, +static int light_ctl_set_unack(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1845,7 +1845,7 @@ static int light_ctl_set_unack(struct bt_mesh_model *model, return 0; } -static int light_ctl_set(struct bt_mesh_model *model, +static int light_ctl_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1927,7 +1927,7 @@ static int light_ctl_set(struct bt_mesh_model *model, return 0; } -static int light_ctl_temp_range_get(struct bt_mesh_model *model, +static int light_ctl_temp_range_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1947,7 +1947,7 @@ static int light_ctl_temp_range_get(struct bt_mesh_model *model, return 0; } -static int light_ctl_default_get(struct bt_mesh_model *model, +static int light_ctl_default_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1967,7 +1967,7 @@ static int light_ctl_default_get(struct bt_mesh_model *model, /* Light CTL Setup Server message handlers */ -static void light_ctl_default_publish(struct bt_mesh_model *model) +static void light_ctl_default_publish(const struct bt_mesh_model *model) { int err; struct net_buf_simple *msg = model->pub->msg; @@ -1987,7 +1987,7 @@ static void light_ctl_default_publish(struct bt_mesh_model *model) } } -static int light_ctl_default_set_unack(struct bt_mesh_model *model, +static int light_ctl_default_set_unack(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2018,7 +2018,7 @@ static int light_ctl_default_set_unack(struct bt_mesh_model *model, return 0; } -static int light_ctl_default_set(struct bt_mesh_model *model, +static int light_ctl_default_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2052,7 +2052,7 @@ static int light_ctl_default_set(struct bt_mesh_model *model, return 0; } -static void light_ctl_temp_range_publish(struct bt_mesh_model *model) +static void light_ctl_temp_range_publish(const struct bt_mesh_model *model) { int err; struct net_buf_simple *msg = model->pub->msg; @@ -2072,7 +2072,7 @@ static void light_ctl_temp_range_publish(struct bt_mesh_model *model) } } -static int light_ctl_temp_range_set_unack(struct bt_mesh_model *model, +static int light_ctl_temp_range_set_unack(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2108,7 +2108,7 @@ static int light_ctl_temp_range_set_unack(struct bt_mesh_model *model, return 0; } -static int light_ctl_temp_range_set(struct bt_mesh_model *model, +static int light_ctl_temp_range_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2148,7 +2148,7 @@ static int light_ctl_temp_range_set(struct bt_mesh_model *model, } /* Light CTL Client message handlers */ -static int light_ctl_status(struct bt_mesh_model *model, +static int light_ctl_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2168,7 +2168,7 @@ static int light_ctl_status(struct bt_mesh_model *model, return 0; } -static int light_ctl_temp_range_status(struct bt_mesh_model *model, +static int light_ctl_temp_range_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2180,7 +2180,7 @@ static int light_ctl_temp_range_status(struct bt_mesh_model *model, return 0; } -static int light_ctl_temp_status(struct bt_mesh_model *model, +static int light_ctl_temp_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2201,7 +2201,7 @@ static int light_ctl_temp_status(struct bt_mesh_model *model, return 0; } -static int light_ctl_default_status(struct bt_mesh_model *model, +static int light_ctl_default_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2214,7 +2214,7 @@ static int light_ctl_default_status(struct bt_mesh_model *model, } /* Light CTL Temp. Server message handlers */ -static int light_ctl_temp_get(struct bt_mesh_model *model, +static int light_ctl_temp_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2244,7 +2244,7 @@ static int light_ctl_temp_get(struct bt_mesh_model *model, return 0; } -void light_ctl_temp_publish(struct bt_mesh_model *model) +void light_ctl_temp_publish(const struct bt_mesh_model *model) { int err; struct net_buf_simple *msg = model->pub->msg; @@ -2270,7 +2270,7 @@ void light_ctl_temp_publish(struct bt_mesh_model *model) } } -static int light_ctl_temp_set_unack(struct bt_mesh_model *model, +static int light_ctl_temp_set_unack(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2345,7 +2345,7 @@ static int light_ctl_temp_set_unack(struct bt_mesh_model *model, return 0; } -static int light_ctl_temp_set(struct bt_mesh_model *model, +static int light_ctl_temp_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2424,7 +2424,7 @@ static int light_ctl_temp_set(struct bt_mesh_model *model, } /* Generic Level (TEMPERATURE) Server message handlers */ -static int gen_level_get_temp(struct bt_mesh_model *model, +static int gen_level_get_temp(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2451,7 +2451,7 @@ static int gen_level_get_temp(struct bt_mesh_model *model, return 0; } -void gen_level_publish_temp(struct bt_mesh_model *model) +void gen_level_publish_temp(const struct bt_mesh_model *model) { int err; struct net_buf_simple *msg = model->pub->msg; @@ -2475,7 +2475,7 @@ void gen_level_publish_temp(struct bt_mesh_model *model) } } -static int gen_level_set_unack_temp(struct bt_mesh_model *model, +static int gen_level_set_unack_temp(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2541,7 +2541,7 @@ static int gen_level_set_unack_temp(struct bt_mesh_model *model, return 0; } -static int gen_level_set_temp(struct bt_mesh_model *model, +static int gen_level_set_temp(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2610,7 +2610,7 @@ static int gen_level_set_temp(struct bt_mesh_model *model, return 0; } -static int gen_delta_set_unack_temp(struct bt_mesh_model *model, +static int gen_delta_set_unack_temp(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2692,7 +2692,7 @@ static int gen_delta_set_unack_temp(struct bt_mesh_model *model, return 0; } -static int gen_delta_set_temp(struct bt_mesh_model *model, +static int gen_delta_set_temp(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2777,7 +2777,7 @@ static int gen_delta_set_temp(struct bt_mesh_model *model, return 0; } -static int gen_move_set_unack_temp(struct bt_mesh_model *model, +static int gen_move_set_unack_temp(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2852,7 +2852,7 @@ static int gen_move_set_unack_temp(struct bt_mesh_model *model, return 0; } -static int gen_move_set_temp(struct bt_mesh_model *model, +static int gen_move_set_temp(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2931,7 +2931,7 @@ static int gen_move_set_temp(struct bt_mesh_model *model, } /* Generic Level (TEMPERATURE) Client message handlers */ -static int gen_level_status_temp(struct bt_mesh_model *model, +static int gen_level_status_temp(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -3112,7 +3112,7 @@ static const struct bt_mesh_model_op gen_level_cli_op_temp[] = { BT_MESH_MODEL_OP_END, }; -struct bt_mesh_model root_models[] = { +const struct bt_mesh_model root_models[] = { BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub), @@ -3172,12 +3172,12 @@ struct bt_mesh_model root_models[] = { NULL), }; -struct bt_mesh_model vnd_models[] = { +const struct bt_mesh_model vnd_models[] = { BT_MESH_MODEL_VND(CID_ZEPHYR, 0x4321, vnd_ops, &vnd_pub, &vnd_user_data), }; -struct bt_mesh_model s0_models[] = { +const struct bt_mesh_model s0_models[] = { BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_LEVEL_SRV, gen_level_srv_op_temp, &gen_level_srv_pub_s0, NULL), @@ -3190,7 +3190,7 @@ struct bt_mesh_model s0_models[] = { NULL), }; -static struct bt_mesh_elem elements[] = { +static const struct bt_mesh_elem elements[] = { BT_MESH_ELEM(0, root_models, vnd_models), BT_MESH_ELEM(0, s0_models, BT_MESH_MODEL_NONE), }; diff --git a/samples/boards/nrf/mesh/onoff_level_lighting_vnd_app/src/mesh/device_composition.h b/samples/boards/nrf/mesh/onoff_level_lighting_vnd_app/src/mesh/device_composition.h index 2bc4c836926..108075379b0 100644 --- a/samples/boards/nrf/mesh/onoff_level_lighting_vnd_app/src/mesh/device_composition.h +++ b/samples/boards/nrf/mesh/onoff_level_lighting_vnd_app/src/mesh/device_composition.h @@ -93,18 +93,18 @@ struct light_ctl_state { extern struct vendor_state vnd_user_data; extern struct light_ctl_state *const ctl; -extern struct bt_mesh_model root_models[]; -extern struct bt_mesh_model vnd_models[]; -extern struct bt_mesh_model s0_models[]; +extern const struct bt_mesh_model root_models[]; +extern const struct bt_mesh_model vnd_models[]; +extern const struct bt_mesh_model s0_models[]; extern const struct bt_mesh_comp comp; -void gen_onoff_publish(struct bt_mesh_model *model); -void gen_level_publish(struct bt_mesh_model *model); -void light_lightness_publish(struct bt_mesh_model *model); -void light_lightness_linear_publish(struct bt_mesh_model *model); -void light_ctl_publish(struct bt_mesh_model *model); -void light_ctl_temp_publish(struct bt_mesh_model *model); -void gen_level_publish_temp(struct bt_mesh_model *model); +void gen_onoff_publish(const struct bt_mesh_model *model); +void gen_level_publish(const struct bt_mesh_model *model); +void light_lightness_publish(const struct bt_mesh_model *model); +void light_lightness_linear_publish(const struct bt_mesh_model *model); +void light_ctl_publish(const struct bt_mesh_model *model); +void light_ctl_temp_publish(const struct bt_mesh_model *model); +void gen_level_publish_temp(const struct bt_mesh_model *model); #endif diff --git a/samples/boards/nrf/nrf53_sync_rtc/CMakeLists.txt b/samples/boards/nrf/nrf53_sync_rtc/CMakeLists.txt index da1ce866e87..432f5497009 100644 --- a/samples/boards/nrf/nrf53_sync_rtc/CMakeLists.txt +++ b/samples/boards/nrf/nrf53_sync_rtc/CMakeLists.txt @@ -5,33 +5,17 @@ cmake_minimum_required(VERSION 3.20.0) -set(NET_ZEPHYR_DIR ${CMAKE_CURRENT_BINARY_DIR}/sync_rtc_net-prefix/src/sync_rtc_net-build/zephyr) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -if("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpuapp") - set(BOARD_REMOTE "nrf5340dk_nrf5340_cpunet") +if(("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpuapp") OR + ("${BOARD}" STREQUAL "nrf5340bsim_nrf5340_cpuapp")) + message(INFO " ${BOARD} used for Application Core") else() - message(FATAL_ERROR "${BOARD} is not supported for this sample") + message(FATAL_ERROR "${BOARD} is not supported for this sample") endif() -message(INFO " ${BOARD} compile as Master in this sample") - -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(sync_rtc) enable_language(C ASM) target_sources(app PRIVATE src/main.c) - -include(ExternalProject) - -ExternalProject_Add( - sync_rtc_net - SOURCE_DIR ${APPLICATION_SOURCE_DIR}/net - INSTALL_COMMAND "" # This particular build system has no install command - CMAKE_CACHE_ARGS -DBOARD:STRING=${BOARD_REMOTE} - CMAKE_CACHE_ARGS -DDTC_OVERLAY_FILE:STRING=${NET_DTC_OVERLAY_FILE} - CMAKE_CACHE_ARGS -DEXTRA_CONF_FILE:STRING=${NET_OVERLAY_CONF} - BUILD_BYPRODUCTS "${NET_ZEPHYR_DIR}/${KERNEL_BIN_NAME}" - # NB: Do we need to pass on more CMake variables? - BUILD_ALWAYS True -) diff --git a/samples/boards/nrf/nrf53_sync_rtc/Kconfig.sysbuild b/samples/boards/nrf/nrf53_sync_rtc/Kconfig.sysbuild new file mode 100644 index 00000000000..b6dc3d0a6d0 --- /dev/null +++ b/samples/boards/nrf/nrf53_sync_rtc/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config NET_CORE_BOARD +string + default "nrf5340dk_nrf5340_cpunet" if $(BOARD) = "nrf5340dk_nrf5340_cpuapp" + default "nrf5340bsim_nrf5340_cpunet" if $(BOARD) = "nrf5340bsim_nrf5340_cpuapp" diff --git a/samples/boards/nrf/nrf53_sync_rtc/README.rst b/samples/boards/nrf/nrf53_sync_rtc/README.rst index a1224ab9482..0b2fd2a22fa 100644 --- a/samples/boards/nrf/nrf53_sync_rtc/README.rst +++ b/samples/boards/nrf/nrf53_sync_rtc/README.rst @@ -28,7 +28,9 @@ Building the application for nrf5340dk_nrf5340_cpuapp .. zephyr-app-commands:: :zephyr-app: samples/boards/nrf/nrf53_sync_rtc :board: nrf5340dk_nrf5340_cpuapp - :goals: flash "flash --hex-file build/sync_rtc_net-prefix/src/sync_rtc_net-build/zephyr/zephyr.hex" + :goals: flash + :flash-args: --hex-file build/nrf53_sync_rtc/zephyr/zephyr.hex + :west-args: --sysbuild Open a serial terminals (for example Minicom or PuTTY) and connect the board with the following settings: @@ -73,3 +75,24 @@ When you reset the development kit, the following messages (one for master and o Observe that initially logging timestamps for the corresponding events on both cores do not match. Same with local and remote timestamps reported on network core. After RTC synchronization is completed they start to match. + +.. _nrf53_sync_rtc_sample_build_bsim: + +Building the application for the simulated nrf5340bsim +****************************************************** + +.. zephyr-app-commands:: + :zephyr-app: samples/boards/nrf/nrf53_sync_rtc + :host-os: unix + :board: nrf5340bsim_nrf5340_cpuapp + :goals: build + :west-args: --sysbuild + +Then you can execute your application using: + +.. code-block:: console + + $ ./build/zephyr/zephyr.exe -nosim + # Press Ctrl+C to exit + +You can expect a similar output as in the real HW in the invoking console. diff --git a/samples/boards/nrf/nrf53_sync_rtc/net/CMakeLists.txt b/samples/boards/nrf/nrf53_sync_rtc/net/CMakeLists.txt index 7612c9a9cec..feced555bc7 100644 --- a/samples/boards/nrf/nrf53_sync_rtc/net/CMakeLists.txt +++ b/samples/boards/nrf/nrf53_sync_rtc/net/CMakeLists.txt @@ -5,13 +5,15 @@ cmake_minimum_required(VERSION 3.20.0) -if("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpunet") - message(INFO " ${BOARD} compile as slave in this sample") +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +if(("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpunet") OR + ("${BOARD}" STREQUAL "nrf5340bsim_nrf5340_cpunet")) + message(INFO " ${BOARD} used for Network Core") else() message(FATAL_ERROR "${BOARD} is not supported for this sample") endif() -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(sync_rtc_net) target_sources(app PRIVATE src/main.c) diff --git a/samples/boards/nrf/nrf53_sync_rtc/net/boards/nrf5340bsim_nrf5340_cpunet.conf b/samples/boards/nrf/nrf53_sync_rtc/net/boards/nrf5340bsim_nrf5340_cpunet.conf new file mode 100644 index 00000000000..e57e7e2174f --- /dev/null +++ b/samples/boards/nrf/nrf53_sync_rtc/net/boards/nrf5340bsim_nrf5340_cpunet.conf @@ -0,0 +1 @@ +CONFIG_BUILD_OUTPUT_EXE=n diff --git a/samples/boards/nrf/nrf53_sync_rtc/net/sample.yaml b/samples/boards/nrf/nrf53_sync_rtc/net/sample.yaml deleted file mode 100644 index f6b337dac24..00000000000 --- a/samples/boards/nrf/nrf53_sync_rtc/net/sample.yaml +++ /dev/null @@ -1,11 +0,0 @@ -sample: - description: This app shows how RTCs are synchronized - on nrf53 cores. - name: nRF53 Synchronized RTC sample (net) -common: - harness: remote -tests: - sample.boards.nrf.nrf53_sync_rtc.net: - platform_allow: nrf5340dk_nrf5340_cpunet - integration_platforms: - - nrf5340dk_nrf5340_cpunet diff --git a/samples/boards/nrf/nrf53_sync_rtc/net/src/main.c b/samples/boards/nrf/nrf53_sync_rtc/net/src/main.c index 55bbcfd2e88..17cf5cb67ea 100644 --- a/samples/boards/nrf/nrf53_sync_rtc/net/src/main.c +++ b/samples/boards/nrf/nrf53_sync_rtc/net/src/main.c @@ -13,6 +13,13 @@ #include LOG_MODULE_REGISTER(main); +#if (CONFIG_SOC_SERIES_BSIM_NRFXX) +extern uint32_t shared_cell_buffer; +static uint32_t shared_cell = (uintptr_t)&shared_cell_buffer; +#else +static uint32_t shared_cell = 0x20070000; +#endif + static void sync_callback(void) { int32_t offset = z_nrf_rtc_timer_nrf53net_offset_get(); @@ -20,7 +27,6 @@ static void sync_callback(void) __ASSERT(offset >= 0, "Synchronization should be completed"); uint32_t timestamp = sys_clock_tick_get_32() + offset; - uint32_t shared_cell = 0x20070000; uint32_t app_timestamp = *(volatile uint32_t *)shared_cell; LOG_INF("Local timestamp: %u, application core timestamp: %u", diff --git a/samples/boards/nrf/nrf53_sync_rtc/sample.yaml b/samples/boards/nrf/nrf53_sync_rtc/sample.yaml index 54c63eb56e1..d1905e0cc47 100644 --- a/samples/boards/nrf/nrf53_sync_rtc/sample.yaml +++ b/samples/boards/nrf/nrf53_sync_rtc/sample.yaml @@ -3,9 +3,23 @@ sample: on nrf53 cores. name: nRF53 Synchronized RTC sample common: - harness: remote + sysbuild: true tests: - sample.boards.nrf.nrf53_sync_rtc: - platform_allow: nrf5340dk_nrf5340_cpuapp + sample.boards.nrf.nrf53_sync_rtc.real_hw: + platform_allow: + - nrf5340dk_nrf5340_cpuapp integration_platforms: - nrf5340dk_nrf5340_cpuapp + harness: remote + sample.boards.nrf.nrf53_sync_rtc.simu: + platform_allow: + - nrf5340bsim_nrf5340_cpuapp + harness: console + harness_config: + type: multi_line + ordered: false + regex: + - "main: Synchronization using mbox driver" + - "sync_rtc: Updated timestamp to synchronized RTC by .* ticks" + - "main: IPC send at .* ticks" + - "main: Local timestamp: .*, application core timestamp:" diff --git a/samples/boards/nrf/nrf53_sync_rtc/src/main.c b/samples/boards/nrf/nrf53_sync_rtc/src/main.c index 0498fe7b502..9c150fd1d46 100644 --- a/samples/boards/nrf/nrf53_sync_rtc/src/main.c +++ b/samples/boards/nrf/nrf53_sync_rtc/src/main.c @@ -11,11 +11,22 @@ #include LOG_MODULE_REGISTER(main); +#if (CONFIG_SOC_SERIES_BSIM_NRFXX) +#include "nsi_cpu_if.h" + +/* For simulation, we can define shared memory variables linkable from + * other MCUs just by using NATIVE_SIMULATOR_IF + */ +NATIVE_SIMULATOR_IF uint32_t shared_cell_buffer; +static uint32_t shared_cell = (uintptr_t)&shared_cell_buffer; +#else +static uint32_t shared_cell = 0x20070000; +#endif + static void timeout_handler(struct k_timer *timer) { nrf_ipc_task_t task = offsetof(NRF_IPC_Type, TASKS_SEND[2]); uint32_t now = sys_clock_tick_get_32(); - uint32_t shared_cell = 0x20070000; *(volatile uint32_t *)shared_cell = now; nrf_ipc_task_trigger(NRF_IPC, task); diff --git a/samples/boards/nrf/nrf53_sync_rtc/sysbuild.cmake b/samples/boards/nrf/nrf53_sync_rtc/sysbuild.cmake new file mode 100644 index 00000000000..0c97244fd7b --- /dev/null +++ b/samples/boards/nrf/nrf53_sync_rtc/sysbuild.cmake @@ -0,0 +1,20 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if("${SB_CONFIG_NET_CORE_BOARD}" STREQUAL "") + message(FATAL_ERROR + "Target ${BOARD} not supported for this sample. " + "There is no remote board selected in Kconfig.sysbuild") +endif() + +set(REMOTE_APP net) + +ExternalZephyrProject_Add( + APPLICATION ${REMOTE_APP} + SOURCE_DIR ${APP_DIR}/${REMOTE_APP} + BOARD ${SB_CONFIG_NET_CORE_BOARD} +) + +native_simulator_set_child_images(${DEFAULT_IMAGE} ${REMOTE_APP}) + +native_simulator_set_final_executable(${DEFAULT_IMAGE}) diff --git a/samples/boards/nrf/nrf53_sync_rtc/sysbuild.conf b/samples/boards/nrf/nrf53_sync_rtc/sysbuild.conf new file mode 100644 index 00000000000..6408669a847 --- /dev/null +++ b/samples/boards/nrf/nrf53_sync_rtc/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/samples/boards/nrf/system_off/Kconfig b/samples/boards/nrf/system_off/Kconfig index cf7923f59c1..b85b0124de1 100644 --- a/samples/boards/nrf/system_off/Kconfig +++ b/samples/boards/nrf/system_off/Kconfig @@ -5,7 +5,7 @@ mainmenu "Nordic SYSTEM_OFF demo" config APP_RETENTION bool "State retention in system off" - depends on SOC_COMPATIBLE_NRF52X + depends on SOC_COMPATIBLE_NRF52X && CRC help On some Nordic chips this application supports retaining memory while in system off. Select this to enable the diff --git a/samples/boards/nrf/system_off/README.rst b/samples/boards/nrf/system_off/README.rst index 77eb93766dc..8d5636be0f9 100644 --- a/samples/boards/nrf/system_off/README.rst +++ b/samples/boards/nrf/system_off/README.rst @@ -7,20 +7,7 @@ Overview ******** This sample can be used for basic power measurement and as an example of -deep sleep on Nordic platforms. The functional behavior is: - -* Busy-wait for 2 seconds -* Sleep for 2 seconds without device power control -* Sleep for 2 seconds after turning UART off, which reduces current draw - by a couple hundred uA -* Turn the system off after enabling wakeup through a button press - -A power monitor will be able to distinguish among these states. - -This sample also demonstrates the use of a :c:func:`SYS_INIT()` call to -disable the deep sleep functionality before the kernel starts, which -prevents the board from powering down during initialization of drivers -that use unbounded delays to wait for startup. +deep sleep on Nordic platforms. RAM Retention ============= @@ -36,27 +23,9 @@ Requirements This application uses nRF51 DK or nRF52 DK board for the demo. -Building, Flashing and Running -****************************** - -.. zephyr-app-commands:: - :zephyr-app: samples/boards/nrf/system_off - :board: nrf52dk_nrf52832 - :goals: build flash - :compact: - -Running: - -1. Open UART terminal. -2. Power Cycle Device. -3. Device will demonstrate two activity levels which can be measured. -4. Device will demonstrate long sleep at minimal non-off power. -5. Device will turn itself off using deep sleep state 1. Press Button 1 - to wake the device and restart the application as if it had been - powered back on. - Sample Output -================= +============= + nRF52 core output ----------------- @@ -65,8 +34,4 @@ nRF52 core output *** Booting Zephyr OS build v2.3.0-rc1-204-g5f2eb85f728d *** nrf52dk_nrf52832 system off demo - Busy-wait 2 s - Busy-wait 2 s with UART off - Sleep 2 s - Sleep 2 s with UART off - Entering system off; press BUTTON1 to restart + Entering system off; press sw0 to restart diff --git a/samples/boards/nrf/system_off/prj.conf b/samples/boards/nrf/system_off/prj.conf index a57c6919a1e..3849b9c2746 100644 --- a/samples/boards/nrf/system_off/prj.conf +++ b/samples/boards/nrf/system_off/prj.conf @@ -1,7 +1,4 @@ -# Required to disable default behavior of deep sleep on timeout CONFIG_PM_DEVICE=y CONFIG_GPIO=y -# Optional select RAM retention (nRF52 only) -#CONFIG_APP_RETENTION=y CONFIG_CRC=y CONFIG_POWEROFF=y diff --git a/samples/boards/nrf/system_off/src/main.c b/samples/boards/nrf/system_off/src/main.c index 6a2a3491602..83ae6206648 100644 --- a/samples/boards/nrf/system_off/src/main.c +++ b/samples/boards/nrf/system_off/src/main.c @@ -4,17 +4,19 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "retained.h" + +#include #include -#include + #include +#include +#include #include #include -#include -#include "retained.h" -#include +#include -#define BUSY_WAIT_S 2U -#define SLEEP_S 2U +static const struct gpio_dt_spec sw0 = GPIO_DT_SPEC_GET(DT_ALIAS(sw0), gpios); int main(void) { @@ -22,11 +24,11 @@ int main(void) const struct device *const cons = DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); if (!device_is_ready(cons)) { - printk("%s: device not ready.\n", cons->name); + printf("%s: device not ready.\n", cons->name); return 0; } - printk("\n%s system off demo\n", CONFIG_BOARD); + printf("\n%s system off demo\n", CONFIG_BOARD); if (IS_ENABLED(CONFIG_APP_RETENTION)) { bool retained_ok = retained_validate(); @@ -35,37 +37,34 @@ int main(void) retained.boots += 1; retained_update(); - printk("Retained data: %s\n", retained_ok ? "valid" : "INVALID"); - printk("Boot count: %u\n", retained.boots); - printk("Off count: %u\n", retained.off_count); - printk("Active Ticks: %" PRIu64 "\n", retained.uptime_sum); + printf("Retained data: %s\n", retained_ok ? "valid" : "INVALID"); + printf("Boot count: %u\n", retained.boots); + printf("Off count: %u\n", retained.off_count); + printf("Active Ticks: %" PRIu64 "\n", retained.uptime_sum); } else { - printk("Retained data not supported\n"); + printf("Retained data not supported\n"); } - /* Configure to generate PORT event (wakeup) on button 1 press. */ - nrf_gpio_cfg_input(NRF_DT_GPIOS_TO_PSEL(DT_ALIAS(sw0), gpios), - NRF_GPIO_PIN_PULLUP); - nrf_gpio_cfg_sense_set(NRF_DT_GPIOS_TO_PSEL(DT_ALIAS(sw0), gpios), - NRF_GPIO_PIN_SENSE_LOW); - - printk("Busy-wait %u s\n", BUSY_WAIT_S); - k_busy_wait(BUSY_WAIT_S * USEC_PER_SEC); + /* configure sw0 as input, interrupt as level active to allow wake-up */ + rc = gpio_pin_configure_dt(&sw0, GPIO_INPUT); + if (rc < 0) { + printf("Could not configure sw0 GPIO (%d)\n", rc); + return 0; + } - printk("Busy-wait %u s with UART off\n", BUSY_WAIT_S); - rc = pm_device_action_run(cons, PM_DEVICE_ACTION_SUSPEND); - k_busy_wait(BUSY_WAIT_S * USEC_PER_SEC); - rc = pm_device_action_run(cons, PM_DEVICE_ACTION_RESUME); + rc = gpio_pin_interrupt_configure_dt(&sw0, GPIO_INT_LEVEL_ACTIVE); + if (rc < 0) { + printf("Could not configure sw0 GPIO interrupt (%d)\n", rc); + return 0; + } - printk("Sleep %u s\n", SLEEP_S); - k_sleep(K_SECONDS(SLEEP_S)); + printf("Entering system off; press sw0 to restart\n"); - printk("Sleep %u s with UART off\n", SLEEP_S); rc = pm_device_action_run(cons, PM_DEVICE_ACTION_SUSPEND); - k_sleep(K_SECONDS(SLEEP_S)); - rc = pm_device_action_run(cons, PM_DEVICE_ACTION_RESUME); - - printk("Entering system off; press BUTTON1 to restart\n"); + if (rc < 0) { + printf("Could not suspend console (%d)\n", rc); + return 0; + } if (IS_ENABLED(CONFIG_APP_RETENTION)) { /* Update the retained state */ diff --git a/samples/boards/nrf/system_off/src/retained.c b/samples/boards/nrf/system_off/src/retained.c index f389b50cc23..e418780f034 100644 --- a/samples/boards/nrf/system_off/src/retained.c +++ b/samples/boards/nrf/system_off/src/retained.c @@ -4,13 +4,17 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "retained.h" + +#include #include + #include #include #include #include + #include -#include "retained.h" /* nRF52 RAM (really, RAM AHB slaves) are partitioned as: * * Up to 8 blocks of two 4 KiBy byte "small" sections diff --git a/samples/boards/nrf/system_off/src/retained.h b/samples/boards/nrf/system_off/src/retained.h index ebe3b2f2ec2..e79c54ff022 100644 --- a/samples/boards/nrf/system_off/src/retained.h +++ b/samples/boards/nrf/system_off/src/retained.h @@ -7,7 +7,8 @@ #ifndef RETAINED_H_ #define RETAINED_H_ -#include +#include +#include /* Example of validatable retained data. */ struct retained_data { diff --git a/samples/boards/reel_board/mesh_badge/src/mesh.c b/samples/boards/reel_board/mesh_badge/src/mesh.c index d2916d141e6..0b9aff947b0 100644 --- a/samples/boards/reel_board/mesh_badge/src/mesh.c +++ b/samples/boards/reel_board/mesh_badge/src/mesh.c @@ -159,12 +159,12 @@ static struct bt_mesh_cfg_cli cfg_cli = { .cb = &cfg_cli_cb, }; -static void attention_on(struct bt_mesh_model *model) +static void attention_on(const struct bt_mesh_model *model) { board_show_text("Attention!", false, K_SECONDS(2)); } -static void attention_off(struct bt_mesh_model *model) +static void attention_off(const struct bt_mesh_model *model) { board_refresh_display(); } @@ -179,15 +179,15 @@ static struct bt_mesh_health_srv health_srv = { }; /* Generic OnOff Server message handlers */ -static int gen_onoff_get(struct bt_mesh_model *model, +static int gen_onoff_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4); - struct led_onoff_state *state = model->user_data; + struct led_onoff_state *state = model->rt->user_data; printk("addr 0x%04x onoff 0x%02x\n", - bt_mesh_model_elem(model)->addr, state->current); + bt_mesh_model_elem(model)->rt->addr, state->current); bt_mesh_model_msg_init(&msg, BT_MESH_MODEL_OP_GEN_ONOFF_STATUS); net_buf_simple_add_u8(&msg, state->current); @@ -198,12 +198,12 @@ static int gen_onoff_get(struct bt_mesh_model *model, return 0; } -static int gen_onoff_set_unack(struct bt_mesh_model *model, +static int gen_onoff_set_unack(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { struct net_buf_simple *msg = model->pub->msg; - struct led_onoff_state *state = model->user_data; + struct led_onoff_state *state = model->rt->user_data; int err; uint8_t tid, onoff; int64_t now; @@ -229,7 +229,7 @@ static int gen_onoff_set_unack(struct bt_mesh_model *model, state->last_msg_timestamp = now; printk("addr 0x%02x state 0x%02x\n", - bt_mesh_model_elem(model)->addr, state->current); + bt_mesh_model_elem(model)->rt->addr, state->current); if (set_led_state(state->dev_id, onoff)) { printk("Failed to set led state\n"); @@ -263,7 +263,7 @@ static int gen_onoff_set_unack(struct bt_mesh_model *model, return 0; } -static int gen_onoff_set(struct bt_mesh_model *model, +static int gen_onoff_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -273,7 +273,7 @@ static int gen_onoff_set(struct bt_mesh_model *model, return 0; } -static int sensor_desc_get(struct bt_mesh_model *model, +static int sensor_desc_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -333,7 +333,7 @@ static void sensor_create_status(uint16_t id, struct net_buf_simple *msg) } } -static int sensor_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int sensor_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { NET_BUF_SIMPLE_DEFINE(msg, 1 + MAX_SENS_STATUS_LEN + 4); @@ -349,7 +349,7 @@ static int sensor_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, return 0; } -static int sensor_col_get(struct bt_mesh_model *model, +static int sensor_col_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -357,7 +357,7 @@ static int sensor_col_get(struct bt_mesh_model *model, return 0; } -static int sensor_series_get(struct bt_mesh_model *model, +static int sensor_series_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -385,7 +385,7 @@ static const struct bt_mesh_model_op sensor_srv_op[] = { { BT_MESH_MODEL_OP_SENS_SERIES_GET, BT_MESH_LEN_EXACT(2), sensor_series_get }, }; -static struct bt_mesh_model root_models[] = { +static const struct bt_mesh_model root_models[] = { BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub), @@ -396,7 +396,7 @@ static struct bt_mesh_model root_models[] = { sensor_srv_op, NULL, NULL), }; -static int vnd_hello(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int vnd_hello(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { char str[32]; @@ -404,7 +404,7 @@ static int vnd_hello(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, printk("Hello message from 0x%04x\n", ctx->addr); - if (ctx->addr == bt_mesh_model_elem(model)->addr) { + if (ctx->addr == bt_mesh_model_elem(model)->rt->addr) { printk("Ignoring message from self\n"); return 0; } @@ -423,7 +423,7 @@ static int vnd_hello(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, return 0; } -static int vnd_baduser(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int vnd_baduser(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { char str[32]; @@ -431,7 +431,7 @@ static int vnd_baduser(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, printk("\"Bad user\" message from 0x%04x\n", ctx->addr); - if (ctx->addr == bt_mesh_model_elem(model)->addr) { + if (ctx->addr == bt_mesh_model_elem(model)->rt->addr) { printk("Ignoring message from self\n"); return 0; } @@ -448,14 +448,14 @@ static int vnd_baduser(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, return 0; } -static int vnd_heartbeat(struct bt_mesh_model *model, +static int vnd_heartbeat(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { uint8_t init_ttl, hops; /* Ignore messages from self */ - if (ctx->addr == bt_mesh_model_elem(model)->addr) { + if (ctx->addr == bt_mesh_model_elem(model)->rt->addr) { return 0; } @@ -477,7 +477,7 @@ static const struct bt_mesh_model_op vnd_ops[] = { BT_MESH_MODEL_OP_END, }; -static int pub_update(struct bt_mesh_model *mod) +static int pub_update(const struct bt_mesh_model *mod) { struct net_buf_simple *msg = mod->pub->msg; @@ -491,11 +491,11 @@ static int pub_update(struct bt_mesh_model *mod) BT_MESH_MODEL_PUB_DEFINE(vnd_pub, pub_update, 3 + 1); -static struct bt_mesh_model vnd_models[] = { +static const struct bt_mesh_model vnd_models[] = { BT_MESH_MODEL_VND(BT_COMP_ID_LF, MOD_LF, vnd_ops, &vnd_pub, NULL), }; -static struct bt_mesh_elem elements[] = { +static const struct bt_mesh_elem elements[] = { BT_MESH_ELEM(0, root_models, vnd_models), }; @@ -638,12 +638,12 @@ void mesh_start(void) bool mesh_is_initialized(void) { - return elements[0].addr != BT_MESH_ADDR_UNASSIGNED; + return elements[0].rt->addr != BT_MESH_ADDR_UNASSIGNED; } uint16_t mesh_get_addr(void) { - return elements[0].addr; + return elements[0].rt->addr; } int mesh_init(void) diff --git a/samples/boards/sensortile_box_pro/sensors-on-board/CMakeLists.txt b/samples/boards/sensortile_box_pro/sensors-on-board/CMakeLists.txt new file mode 100644 index 00000000000..4904facbcd1 --- /dev/null +++ b/samples/boards/sensortile_box_pro/sensors-on-board/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2023 STMicroelectronics +# +# SPDX-License-Identifier: Apache-2.0 +# +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(sensortile_box_pro) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/boards/sensortile_box_pro/sensors-on-board/README.rst b/samples/boards/sensortile_box_pro/sensors-on-board/README.rst new file mode 100644 index 00000000000..f65294f2aa8 --- /dev/null +++ b/samples/boards/sensortile_box_pro/sensors-on-board/README.rst @@ -0,0 +1,73 @@ +.. _sensortile_box_pro_sample_sensors: + +ST SensorTile.box Pro on-board sensors test +########################################### + +Overview +******** +This sample provides an example of how to read sensors data +from the SensorTile.box Pro board. + +This sample enables all sensors of SensorTile.box Pro board, and then +periodically reads and displays data on the console from the following +sensors: + +- HTS221: ambient temperature and relative humidity +- LPS22DF: ambient temperature and atmospheric pressure +- LSM6DSV16X: 6-Axis acceleration and angular velocity + +Requirements +************ + +The application requires a SensorTile.box Pro board connected to the PC +through USB. The board shows up as a USB CDC class standard device. + +References +********** + +- :ref:`sensortile_box_pro_board` + +Building and Running +******************** + +Build and flash the sample in the following way: + +.. zephyr-app-commands:: + :zephyr-app: samples/boards/sensortile_box_pro/sensors-on-board + :board: sensortile_box_pro + :goals: build flash + +Please note that flashing the board requires a few preliminary steps described +in :ref:`sensortile_box_pro_board`. + +Then, power cycle the board by disconnecting and reconnecting the USB cable. +Run your favorite terminal program to listen for output. + +.. code-block:: console + + $ minicom -D -b 115200 + +Replace :code:`` with the correct device path automatically created on +the host after the SensorTile.box Pro board gets connected to it, +usually :code:`/dev/ttyUSBx` or :code:`/dev/ttyACMx` (with x being 0, 1, 2, ...). +The ``-b`` option sets baud rate ignoring the value from config. + +Sample Output +============= + +The sample code outputs sensors data on the SensorTile.box Pro console. + + .. code-block:: console + + SensorTile.box Pro dashboard + + HTS221: Temperature: 26.4 C + HTS221: Relative Humidity: 60.5% + LPS22DF: Temperature: 28.4 C + LPS22DF: Pressure:99.694 kpa + LSM6DSV16X: Accel (m.s-2): x: -0.158, y: 0.158, z: 9.811 + LSM6DSV16X: GYro (dps): x: 0.003, y: 0.000, z: -0.005 + 1:: lsm6dsv16x acc trig 836 + 1:: lsm6dsv16x gyr trig 836 + + diff --git a/samples/boards/sensortile_box_pro/sensors-on-board/prj.conf b/samples/boards/sensortile_box_pro/sensors-on-board/prj.conf new file mode 100644 index 00000000000..a7c57f2f746 --- /dev/null +++ b/samples/boards/sensortile_box_pro/sensors-on-board/prj.conf @@ -0,0 +1,15 @@ +CONFIG_LOG=y +CONFIG_PRINTK=y +CONFIG_SPI=y +CONFIG_I2C=y +CONFIG_GPIO=y + +# config sensors +CONFIG_SENSOR=y +CONFIG_SENSOR_LOG_LEVEL_DBG=y +CONFIG_HTS221_TRIGGER_NONE=y +CONFIG_LPS22DF_TRIGGER_OWN_THREAD=y +CONFIG_LSM6DSV16X_TRIGGER_OWN_THREAD=y +CONFIG_LIS2MDL_TRIGGER_OWN_THREAD=y + +CONFIG_CBPRINTF_FP_SUPPORT=y diff --git a/samples/boards/sensortile_box_pro/sensors-on-board/sample.yaml b/samples/boards/sensortile_box_pro/sensors-on-board/sample.yaml new file mode 100644 index 00000000000..d723fcdd7c7 --- /dev/null +++ b/samples/boards/sensortile_box_pro/sensors-on-board/sample.yaml @@ -0,0 +1,12 @@ +sample: + description: SensorTile.box Pro board testing + name: SensorTile.box Pro test +tests: + sample.board.sensortile_box_pro.sensors-on-board: + harness: sensor + platform_allow: sensortile_box_pro + tags: sensors + depends_on: + - i2c + - spi + - gpio diff --git a/samples/boards/sensortile_box_pro/sensors-on-board/src/main.c b/samples/boards/sensortile_box_pro/sensors-on-board/src/main.c new file mode 100644 index 00000000000..7aab1f36b13 --- /dev/null +++ b/samples/boards/sensortile_box_pro/sensors-on-board/src/main.c @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#ifdef CONFIG_LPS22DF_TRIGGER +static int lps22df_trig_cnt; + +static void lps22df_trigger_handler(const struct device *dev, + const struct sensor_trigger *trig) +{ + sensor_sample_fetch_chan(dev, SENSOR_CHAN_PRESS); + lps22df_trig_cnt++; +} +#endif + +#ifdef CONFIG_LSM6DSV16X_TRIGGER +static int lsm6dsv16x_acc_trig_cnt; +static int lsm6dsv16x_gyr_trig_cnt; +static int lsm6dsv16x_temp_trig_cnt; + +static void lsm6dsv16x_acc_trig_handler(const struct device *dev, + const struct sensor_trigger *trig) +{ + sensor_sample_fetch_chan(dev, SENSOR_CHAN_ACCEL_XYZ); + lsm6dsv16x_acc_trig_cnt++; +} + +static void lsm6dsv16x_gyr_trig_handler(const struct device *dev, + const struct sensor_trigger *trig) +{ + sensor_sample_fetch_chan(dev, SENSOR_CHAN_GYRO_XYZ); + lsm6dsv16x_gyr_trig_cnt++; +} + +static void lsm6dsv16x_temp_trig_handler(const struct device *dev, + const struct sensor_trigger *trig) +{ + sensor_sample_fetch_chan(dev, SENSOR_CHAN_DIE_TEMP); + lsm6dsv16x_temp_trig_cnt++; +} +#endif + +#ifdef CONFIG_LIS2MDL_TRIGGER +static int lis2mdl_trig_cnt; + +static void lis2mdl_trigger_handler(const struct device *dev, + const struct sensor_trigger *trig) +{ + sensor_sample_fetch_chan(dev, SENSOR_CHAN_ALL); + lis2mdl_trig_cnt++; +} +#endif + +static void lps22df_config(const struct device *lps22df) +{ + struct sensor_value odr_attr; + + /* set LPS22DF sampling frequency to 50 Hz */ + odr_attr.val1 = 50; + odr_attr.val2 = 0; + + if (sensor_attr_set(lps22df, SENSOR_CHAN_ALL, + SENSOR_ATTR_SAMPLING_FREQUENCY, &odr_attr) < 0) { + printk("Cannot set sampling frequency for LPS22DF\n"); + return; + } + +#ifdef CONFIG_LPS22DF_TRIGGER + struct sensor_trigger trig; + + trig.type = SENSOR_TRIG_DATA_READY; + trig.chan = SENSOR_CHAN_ALL; + sensor_trigger_set(lps22df, &trig, lps22df_trigger_handler); +#endif +} + +static void lsm6dsv16x_config(const struct device *lsm6dsv16x) +{ + struct sensor_value odr_attr, fs_attr; + + /* set LSM6DSV16X accel sampling frequency to 208 Hz */ + odr_attr.val1 = 208; + odr_attr.val2 = 0; + + if (sensor_attr_set(lsm6dsv16x, SENSOR_CHAN_ACCEL_XYZ, + SENSOR_ATTR_SAMPLING_FREQUENCY, &odr_attr) < 0) { + printk("Cannot set sampling frequency for LSM6DSV16X accel\n"); + return; + } + + sensor_g_to_ms2(16, &fs_attr); + + if (sensor_attr_set(lsm6dsv16x, SENSOR_CHAN_ACCEL_XYZ, + SENSOR_ATTR_FULL_SCALE, &fs_attr) < 0) { + printk("Cannot set fs for LSM6DSV16X accel\n"); + return; + } + + /* set LSM6DSV16X gyro sampling frequency to 208 Hz */ + odr_attr.val1 = 208; + odr_attr.val2 = 0; + + if (sensor_attr_set(lsm6dsv16x, SENSOR_CHAN_GYRO_XYZ, + SENSOR_ATTR_SAMPLING_FREQUENCY, &odr_attr) < 0) { + printk("Cannot set sampling frequency for LSM6DSV16X gyro\n"); + return; + } + + sensor_degrees_to_rad(250, &fs_attr); + + if (sensor_attr_set(lsm6dsv16x, SENSOR_CHAN_GYRO_XYZ, + SENSOR_ATTR_FULL_SCALE, &fs_attr) < 0) { + printk("Cannot set fs for LSM6DSV16X gyro\n"); + return; + } + +#ifdef CONFIG_LSM6DSV16X_TRIGGER + struct sensor_trigger trig; + + trig.type = SENSOR_TRIG_DATA_READY; + trig.chan = SENSOR_CHAN_ACCEL_XYZ; + sensor_trigger_set(lsm6dsv16x, &trig, lsm6dsv16x_acc_trig_handler); + + trig.type = SENSOR_TRIG_DATA_READY; + trig.chan = SENSOR_CHAN_GYRO_XYZ; + sensor_trigger_set(lsm6dsv16x, &trig, lsm6dsv16x_gyr_trig_handler); + + trig.type = SENSOR_TRIG_DATA_READY; + trig.chan = SENSOR_CHAN_DIE_TEMP; + sensor_trigger_set(lsm6dsv16x, &trig, lsm6dsv16x_temp_trig_handler); +#endif +} + +static void lis2mdl_config(const struct device *lis2mdl) +{ + struct sensor_value odr_attr; + + /* set LIS2MDL sampling frequency to 100 Hz */ + odr_attr.val1 = 100; + odr_attr.val2 = 0; + + if (sensor_attr_set(lis2mdl, SENSOR_CHAN_ALL, + SENSOR_ATTR_SAMPLING_FREQUENCY, &odr_attr) < 0) { + printk("Cannot set sampling frequency for LIS2MDL\n"); + return; + } + +#ifdef CONFIG_LIS2MDL_TRIGGER + struct sensor_trigger trig; + + trig.type = SENSOR_TRIG_DATA_READY; + trig.chan = SENSOR_CHAN_MAGN_XYZ; + sensor_trigger_set(lis2mdl, &trig, lis2mdl_trigger_handler); +#endif +} + +static int led_pattern_out(void) +{ + const struct gpio_dt_spec led0_gpio = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios); + const struct gpio_dt_spec led1_gpio = GPIO_DT_SPEC_GET(DT_ALIAS(led1), gpios); + const struct gpio_dt_spec led2_gpio = GPIO_DT_SPEC_GET(DT_ALIAS(led2), gpios); + const struct gpio_dt_spec led3_gpio = GPIO_DT_SPEC_GET(DT_ALIAS(led3), gpios); + int i; + + /* led 0 */ + if (!gpio_is_ready_dt(&led0_gpio)) { + printk("%s: device not ready.\n", led0_gpio.port->name); + return -1; + } + gpio_pin_configure_dt(&led0_gpio, GPIO_OUTPUT_INACTIVE); + + /* led 1 */ + if (!gpio_is_ready_dt(&led1_gpio)) { + printk("%s: device not ready.\n", led1_gpio.port->name); + return -1; + } + gpio_pin_configure_dt(&led1_gpio, GPIO_OUTPUT_INACTIVE); + + /* led 2 */ + if (!gpio_is_ready_dt(&led2_gpio)) { + printk("%s: device not ready.\n", led2_gpio.port->name); + return -1; + } + gpio_pin_configure_dt(&led2_gpio, GPIO_OUTPUT_INACTIVE); + + /* led 3 */ + if (!gpio_is_ready_dt(&led3_gpio)) { + printk("%s: device not ready.\n", led3_gpio.port->name); + return -1; + } + gpio_pin_configure_dt(&led3_gpio, GPIO_OUTPUT_INACTIVE); + + /* output led pattern */ + for (i = 0; i < 12; i++) { + gpio_pin_set_dt(&led0_gpio, ((i % 4) == 0) ? 1 : 0); + gpio_pin_set_dt(&led1_gpio, ((i % 4) == 1) ? 1 : 0); + gpio_pin_set_dt(&led2_gpio, ((i % 4) == 2) ? 1 : 0); + gpio_pin_set_dt(&led3_gpio, ((i % 4) == 3) ? 1 : 0); + k_sleep(K_MSEC(100)); + } + + /* turn all leds off */ + gpio_pin_set_dt(&led0_gpio, 0); + gpio_pin_set_dt(&led1_gpio, 0); + gpio_pin_set_dt(&led2_gpio, 0); + gpio_pin_set_dt(&led3_gpio, 0); + + return 0; +} + +int main(void) +{ + int cnt = 1; + + /* signal that sample is started */ + if (led_pattern_out() < 0) { + return -1; + } + + printk("SensorTile.box Pro sensor test\n"); + + const struct device *const hts221 = DEVICE_DT_GET_ONE(st_hts221); + const struct device *const lps22df = DEVICE_DT_GET_ONE(st_lps22df); + const struct device *const lsm6dsv16x = DEVICE_DT_GET_ONE(st_lsm6dsv16x); + const struct device *const lis2mdl = DEVICE_DT_GET_ONE(st_lis2mdl); + + if (!device_is_ready(hts221)) { + printk("%s: device not ready.\n", hts221->name); + return 0; + } + if (!device_is_ready(lps22df)) { + printk("%s: device not ready.\n", lps22df->name); + return 0; + } + if (!device_is_ready(lsm6dsv16x)) { + printk("%s: device not ready.\n", lsm6dsv16x->name); + return 0; + } + if (!device_is_ready(lis2mdl)) { + printk("%s: device not ready.\n", lis2mdl->name); + return 0; + } + + lis2mdl_config(lis2mdl); + lps22df_config(lps22df); + lsm6dsv16x_config(lsm6dsv16x); + + while (1) { + struct sensor_value hts221_hum, hts221_temp; + struct sensor_value lps22df_press, lps22df_temp; + struct sensor_value lsm6dsv16x_accel[3], lsm6dsv16x_gyro[3]; + struct sensor_value lis2mdl_magn[3]; + struct sensor_value lis2mdl_temp; + + /* handle HTS221 sensor */ + if (sensor_sample_fetch(hts221) < 0) { + printf("HTS221 Sensor sample update error\n"); + return 0; + } + +#ifndef CONFIG_LSM6DSV16X_TRIGGER + if (sensor_sample_fetch(lsm6dsv16x) < 0) { + printf("LSM6DSV16X Sensor sample update error\n"); + return 0; + } +#endif + +#ifndef CONFIG_LPS22DF_TRIGGER + if (sensor_sample_fetch(lps22df) < 0) { + printf("LPS22DF Sensor sample update error\n"); + return 0; + } +#endif + +#ifndef CONFIG_LIS2MDL_TRIGGER + if (sensor_sample_fetch(lis2mdl) < 0) { + printf("LIS2MDL Magn Sensor sample update error\n"); + return 0; + } +#endif + + sensor_channel_get(hts221, SENSOR_CHAN_HUMIDITY, &hts221_hum); + sensor_channel_get(hts221, SENSOR_CHAN_AMBIENT_TEMP, &hts221_temp); + sensor_channel_get(lps22df, SENSOR_CHAN_AMBIENT_TEMP, &lps22df_temp); + sensor_channel_get(lps22df, SENSOR_CHAN_PRESS, &lps22df_press); + sensor_channel_get(lsm6dsv16x, SENSOR_CHAN_ACCEL_XYZ, lsm6dsv16x_accel); + sensor_channel_get(lsm6dsv16x, SENSOR_CHAN_GYRO_XYZ, lsm6dsv16x_gyro); + sensor_channel_get(lis2mdl, SENSOR_CHAN_MAGN_XYZ, lis2mdl_magn); + sensor_channel_get(lis2mdl, SENSOR_CHAN_DIE_TEMP, &lis2mdl_temp); + + /* Display sensor data */ + + /* Clear terminal (ANSI ESC-C) */ + printf("\0033\014"); + + printf("SensorTile.box dashboard\n\n"); + + /* HTS221 temperature */ + printf("HTS221: Temperature: %.1f C\n", + sensor_value_to_double(&hts221_temp)); + + /* HTS221 humidity */ + printf("HTS221: Relative Humidity: %.1f%%\n", + sensor_value_to_double(&hts221_hum)); + + /* temperature */ + printf("LPS22DF: Temperature: %.1f C\n", + sensor_value_to_double(&lps22df_temp)); + + /* pressure */ + printf("LPS22DF: Pressure: %.3f kpa\n", + sensor_value_to_double(&lps22df_press)); + + printf("LSM6DSV16X: Accel (m.s-2): x: %.3f, y: %.3f, z: %.3f\n", + sensor_value_to_double(&lsm6dsv16x_accel[0]), + sensor_value_to_double(&lsm6dsv16x_accel[1]), + sensor_value_to_double(&lsm6dsv16x_accel[2])); + + printf("LSM6DSV16X: GYro (dps): x: %.3f, y: %.3f, z: %.3f\n", + sensor_value_to_double(&lsm6dsv16x_gyro[0]), + sensor_value_to_double(&lsm6dsv16x_gyro[1]), + sensor_value_to_double(&lsm6dsv16x_gyro[2])); + + /* lis2mdl */ + printf("LIS2MDL: Magn (gauss): x: %.3f, y: %.3f, z: %.3f\n", + sensor_value_to_double(&lis2mdl_magn[0]), + sensor_value_to_double(&lis2mdl_magn[1]), + sensor_value_to_double(&lis2mdl_magn[2])); + + printf("LIS2MDL: Temperature: %.1f C\n", + sensor_value_to_double(&lis2mdl_temp)); + +#ifdef CONFIG_LPS22DF_TRIGGER + printk("%d:: lps22df trig %d\n", cnt, lps22df_trig_cnt); +#endif + +#ifdef CONFIG_LSM6DSV16X_TRIGGER + printk("%d:: lsm6dsv16x acc trig %d\n", cnt, lsm6dsv16x_acc_trig_cnt); + printk("%d:: lsm6dsv16x gyr trig %d\n", cnt, lsm6dsv16x_gyr_trig_cnt); +#endif + +#ifdef CONFIG_LIS2MDL_TRIGGER + printk("%d:: lis2mdl trig %d\n", cnt, lis2mdl_trig_cnt); +#endif + + k_sleep(K_MSEC(2000)); + } +} diff --git a/samples/boards/stm32/power_mgmt/adc/CMakeLists.txt b/samples/boards/stm32/power_mgmt/adc/CMakeLists.txt new file mode 100644 index 00000000000..b0eea852bf5 --- /dev/null +++ b/samples/boards/stm32/power_mgmt/adc/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(stm32_pm_adc) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/boards/stm32/power_mgmt/adc/README.rst b/samples/boards/stm32/power_mgmt/adc/README.rst new file mode 100644 index 00000000000..2ec694884fa --- /dev/null +++ b/samples/boards/stm32/power_mgmt/adc/README.rst @@ -0,0 +1,42 @@ +.. _stm32-pm-adc-sample: + +STM32 PM ADC +############ + +Overview +******** + +This sample is a minimum application to demonstrate basic power management +behavior in a basic ADC set up in low power context. + +.. _stm32-pm-adc-sample-requirements: + +Requirements +************ + +The board should support enabling PM. For a STM32 based target, it means that +it should support a clock source alternative to Cortex Systick that can be used +in core sleep states, as LPTIM (:dtcompatible:`st,stm32-lptim`). + +Building and Running +******************** + +Build and flash as follows, changing ``nucleo_wb55rg`` for your board: + +.. zephyr-app-commands:: + :zephyr-app: samples/boards/stm32/power_mgmt/adc + :board: nucleo_wb55rg + :goals: build flash + :compact: + +After flashing, the console shows the ADC measurement in the form: +``ADC reading[0]:`` +``- adc@50040000, channel 3: 1158 = 932 mV`` + +PM configurations +***************** + +By default, :kconfig:option:`CONFIG_PM_DEVICE` and :kconfig:option:`CONFIG_PM_DEVICE_RUNTIME` are +enabled. +On STM32WB, we can observe a power consumption of about 25µA with both kconfig +enabled, 27.5µA without (each time with :kconfig:option:`CONFIG_PM` enabled). diff --git a/samples/boards/stm32/power_mgmt/adc/boards/nucleo_g474re.overlay b/samples/boards/stm32/power_mgmt/adc/boards/nucleo_g474re.overlay new file mode 100644 index 00000000000..bde07e0f2d6 --- /dev/null +++ b/samples/boards/stm32/power_mgmt/adc/boards/nucleo_g474re.overlay @@ -0,0 +1,27 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 STMicroelectronics + */ + +#include + +/ { + zephyr,user { + /* adjust channel number according to pinmux in board.dts */ + io-channels = <&adc1 1>; + }; +}; + +&adc1 { + #address-cells = <1>; + #size-cells = <0>; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; diff --git a/samples/boards/stm32/power_mgmt/adc/boards/nucleo_wb55rg.overlay b/samples/boards/stm32/power_mgmt/adc/boards/nucleo_wb55rg.overlay new file mode 100644 index 00000000000..6a39f681c45 --- /dev/null +++ b/samples/boards/stm32/power_mgmt/adc/boards/nucleo_wb55rg.overlay @@ -0,0 +1,26 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 STMicroelectronics + */ + +/ { + zephyr,user { + /* adjust channel number according to pinmux in board.dts */ + io-channels = <&adc1 3>; + }; +}; + +&adc1 { + pinctrl-0 = <&adc1_in3_pc2>; + #address-cells = <1>; + #size-cells = <0>; + + channel@3 { + reg = <3>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; diff --git a/samples/boards/stm32/power_mgmt/adc/boards/nucleo_wba52cg.overlay b/samples/boards/stm32/power_mgmt/adc/boards/nucleo_wba52cg.overlay new file mode 100644 index 00000000000..3cd6cb64bf5 --- /dev/null +++ b/samples/boards/stm32/power_mgmt/adc/boards/nucleo_wba52cg.overlay @@ -0,0 +1,12 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 STMicroelectronics + */ + +/ { + zephyr,user { + /* adjust channel number according to pinmux in board.dts */ + io-channels = <&adc4 8>; + }; +}; diff --git a/samples/boards/stm32/power_mgmt/adc/prj.conf b/samples/boards/stm32/power_mgmt/adc/prj.conf new file mode 100644 index 00000000000..c5359fe0238 --- /dev/null +++ b/samples/boards/stm32/power_mgmt/adc/prj.conf @@ -0,0 +1,6 @@ +CONFIG_PM=y +CONFIG_PM_DEVICE=y +CONFIG_PM_DEVICE_RUNTIME=y +CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE=n +CONFIG_ADC=y +#CONFIG_DEBUG=y diff --git a/samples/boards/stm32/power_mgmt/adc/sample.yaml b/samples/boards/stm32/power_mgmt/adc/sample.yaml new file mode 100644 index 00000000000..e3892df7b5c --- /dev/null +++ b/samples/boards/stm32/power_mgmt/adc/sample.yaml @@ -0,0 +1,17 @@ +sample: + name: STM32 ADC Power Management +tests: + sample.boards.stm32.power_mgmt.adc: + tags: + - adc + - power + harness: console + harness_config: + type: one_line + regex: + - "Device ready" + filter: dt_compat_enabled("zephyr,power-state") and + dt_compat_enabled("st,stm32-adc") and + dt_compat_enabled("st,stm32-lptim") + extra_args: "CONFIG_DEBUG=y" + platform_allow: nucleo_wb55rg diff --git a/samples/boards/stm32/power_mgmt/adc/src/main.c b/samples/boards/stm32/power_mgmt/adc/src/main.c new file mode 100644 index 00000000000..b75ab4a9af2 --- /dev/null +++ b/samples/boards/stm32/power_mgmt/adc/src/main.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#define SLEEP_TIME_MS 2000 + +#if !DT_NODE_EXISTS(DT_PATH(zephyr_user)) || \ + !DT_NODE_HAS_PROP(DT_PATH(zephyr_user), io_channels) +#error "No suitable devicetree overlay specified" +#endif + +#define DT_SPEC_AND_COMMA(node_id, prop, idx) \ + ADC_DT_SPEC_GET_BY_IDX(node_id, idx), + +/* Data of ADC io-channels specified in devicetree. */ +static const struct adc_dt_spec adc_channels[] = { + DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channels, + DT_SPEC_AND_COMMA) +}; + +int main(void) +{ + int err; + uint32_t count = 0; + uint16_t buf; + struct adc_sequence sequence = { + .buffer = &buf, + /* buffer size in bytes, not number of samples */ + .buffer_size = sizeof(buf), + }; + + /* Configure channels individually prior to sampling. */ + for (size_t i = 0U; i < ARRAY_SIZE(adc_channels); i++) { + if (!adc_is_ready_dt(&adc_channels[i])) { + printk("ADC controller device %s not ready\n", adc_channels[i].dev->name); + return 0; + } + + err = adc_channel_setup_dt(&adc_channels[i]); + if (err < 0) { + printk("Could not setup channel #%d (%d)\n", i, err); + return 0; + } + } + + printk("Device ready\n"); + + while (true) { + printk("ADC reading[%u]:\n", count++); + for (size_t i = 0U; i < ARRAY_SIZE(adc_channels); i++) { + int32_t val_mv; + + printk("- %s, channel %d: ", + adc_channels[i].dev->name, + adc_channels[i].channel_id); + + (void)adc_sequence_init_dt(&adc_channels[i], &sequence); + + err = adc_read_dt(&adc_channels[i], &sequence); + if (err < 0) { + printk("Could not read (%d)\n", err); + continue; + } + + /* + * If using differential mode, the 16 bit value + * in the ADC sample buffer should be a signed 2's + * complement value. + */ + if (adc_channels[i].channel_cfg.differential) { + val_mv = (int32_t)((int16_t)buf); + } else { + val_mv = (int32_t)buf; + } + printk("%"PRId32, val_mv); + err = adc_raw_to_millivolts_dt(&adc_channels[i], + &val_mv); + /* conversion to mV may not be supported, skip if not */ + if (err < 0) { + printk(" (value in mV not available)\n"); + } else { + printk(" = %"PRId32" mV\n", val_mv); + } + } + + k_msleep(SLEEP_TIME_MS); + } + return 0; +} diff --git a/samples/boards/stm32/power_mgmt/blinky/boards/nucleo_f429zi.conf b/samples/boards/stm32/power_mgmt/blinky/boards/nucleo_f429zi.conf new file mode 100644 index 00000000000..2035eb8c955 --- /dev/null +++ b/samples/boards/stm32/power_mgmt/blinky/boards/nucleo_f429zi.conf @@ -0,0 +1,2 @@ +# Increase IDLE stack for the IDLE timer +CONFIG_IDLE_STACK_SIZE=640 diff --git a/samples/boards/stm32/power_mgmt/blinky/boards/nucleo_f429zi.overlay b/samples/boards/stm32/power_mgmt/blinky/boards/nucleo_f429zi.overlay new file mode 100644 index 00000000000..859c69df414 --- /dev/null +++ b/samples/boards/stm32/power_mgmt/blinky/boards/nucleo_f429zi.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + zephyr,cortex-m-idle-timer = &rtc; + }; +}; diff --git a/samples/boards/stm32/power_mgmt/blinky/prj.conf b/samples/boards/stm32/power_mgmt/blinky/prj.conf index 4921dcc3392..9ac206bd0f3 100644 --- a/samples/boards/stm32/power_mgmt/blinky/prj.conf +++ b/samples/boards/stm32/power_mgmt/blinky/prj.conf @@ -1,3 +1,4 @@ CONFIG_PM=y CONFIG_PM_DEVICE=y CONFIG_PM_DEVICE_RUNTIME=y +CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE=n diff --git a/samples/boards/stm32/power_mgmt/blinky/sample.yaml b/samples/boards/stm32/power_mgmt/blinky/sample.yaml index 103f204a189..04054268228 100644 --- a/samples/boards/stm32/power_mgmt/blinky/sample.yaml +++ b/samples/boards/stm32/power_mgmt/blinky/sample.yaml @@ -12,7 +12,9 @@ tests: - "Device ready" filter: dt_compat_enabled("zephyr,power-state") and dt_enabled_alias_with_parent_compat("led0", "gpio-leds") and - dt_compat_enabled("st,stm32-lptim") + (dt_compat_enabled("st,stm32-lptim") or + dt_chosen_enabled("zephyr,cortex-m-idle-timer")) extra_args: "CONFIG_DEBUG=y" integration_platforms: - nucleo_wb55rg + - nucleo_f429zi diff --git a/samples/boards/stm32/power_mgmt/stm32wb_ble/prj.conf b/samples/boards/stm32/power_mgmt/stm32wb_ble/prj.conf index 583df4e6ee7..1dff53f1da7 100644 --- a/samples/boards/stm32/power_mgmt/stm32wb_ble/prj.conf +++ b/samples/boards/stm32/power_mgmt/stm32wb_ble/prj.conf @@ -1,5 +1,4 @@ CONFIG_BT=y CONFIG_BT_DEVICE_NAME="Test beacon" CONFIG_POWEROFF=y - -#CONFIG_DEBUG=y +CONFIG_PM=y diff --git a/samples/boards/stm32/power_mgmt/stm32wb_ble/sample.yaml b/samples/boards/stm32/power_mgmt/stm32wb_ble/sample.yaml index 3c00f4ef856..0e8e975d19a 100644 --- a/samples/boards/stm32/power_mgmt/stm32wb_ble/sample.yaml +++ b/samples/boards/stm32/power_mgmt/stm32wb_ble/sample.yaml @@ -7,3 +7,4 @@ tests: tags: - bluetooth - pm + extra_args: "CONFIG_DEBUG=y" diff --git a/samples/drivers/uart/stm32/single_wire/CMakeLists.txt b/samples/boards/stm32/uart/single_wire/CMakeLists.txt similarity index 100% rename from samples/drivers/uart/stm32/single_wire/CMakeLists.txt rename to samples/boards/stm32/uart/single_wire/CMakeLists.txt diff --git a/samples/boards/stm32/uart/single_wire/README.rst b/samples/boards/stm32/uart/single_wire/README.rst new file mode 100644 index 00000000000..d5f0e1b592f --- /dev/null +++ b/samples/boards/stm32/uart/single_wire/README.rst @@ -0,0 +1,34 @@ +.. zephyr:code-sample:: uart-stm32-single-wire + :name: STM32 single-wire UART + :relevant-api: uart_interface + + Use single-wire/half-duplex UART functionality of STM32 devices. + +Overview +******** + +A simple application demonstrating how to use the single wire / half-duplex UART +functionality of STM32. Without adaptions this example runs on STM32F3 discovery +board. You need to establish a physical connection between pins PA2 (USART2_TX) and +PC10 (UART4_TX). + +Add a `single_wire_uart_loopback` fixture to your board in the hardware map to allow +twister to verify this sample's output automatically. + +Building and Running +******************** + +Build and flash as follows, replacing ``stm32f3_disco`` with your board: + + .. zephyr-app-commands:: + :zephyr-app: samples/boards/stm32/uart/single_wire + :board: stm32f3_disco + :goals: build flash + :compact: + +After flashing the console output should not show any failure reports, +but the following message repeated every 2s: + +.. code-block:: none + + Received c diff --git a/samples/drivers/uart/stm32/single_wire/boards/stm32f3_disco.overlay b/samples/boards/stm32/uart/single_wire/boards/stm32f3_disco.overlay similarity index 100% rename from samples/drivers/uart/stm32/single_wire/boards/stm32f3_disco.overlay rename to samples/boards/stm32/uart/single_wire/boards/stm32f3_disco.overlay diff --git a/samples/drivers/uart/stm32/single_wire/prj.conf b/samples/boards/stm32/uart/single_wire/prj.conf similarity index 100% rename from samples/drivers/uart/stm32/single_wire/prj.conf rename to samples/boards/stm32/uart/single_wire/prj.conf diff --git a/samples/boards/stm32/uart/single_wire/sample.yaml b/samples/boards/stm32/uart/single_wire/sample.yaml new file mode 100644 index 00000000000..6bf267e50a4 --- /dev/null +++ b/samples/boards/stm32/uart/single_wire/sample.yaml @@ -0,0 +1,14 @@ +sample: + name: STM32 Single Wire UART sample +tests: + sample.boards.stm32.uart.single_wire: + platform_allow: stm32f3_disco + tags: + - drivers + - uart + harness: console + harness_config: + fixture: single_line_uart_loopback + type: one_line + regex: + - "Received c" diff --git a/samples/drivers/uart/stm32/single_wire/src/main.c b/samples/boards/stm32/uart/single_wire/src/main.c similarity index 100% rename from samples/drivers/uart/stm32/single_wire/src/main.c rename to samples/boards/stm32/uart/single_wire/src/main.c diff --git a/samples/charger/CMakeLists.txt b/samples/charger/CMakeLists.txt new file mode 100644 index 00000000000..e0f9e77b374 --- /dev/null +++ b/samples/charger/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(charger) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/charger/prj.conf b/samples/charger/prj.conf new file mode 100644 index 00000000000..922c6f65a09 --- /dev/null +++ b/samples/charger/prj.conf @@ -0,0 +1 @@ +CONFIG_CHARGER=y diff --git a/samples/charger/sample.yaml b/samples/charger/sample.yaml new file mode 100644 index 00000000000..18ab714b99c --- /dev/null +++ b/samples/charger/sample.yaml @@ -0,0 +1,6 @@ +sample: + name: Generic charger +tests: + sample.drivers.charger: + tags: charger + depends_on: charger diff --git a/samples/charger/src/main.c b/samples/charger/src/main.c new file mode 100644 index 00000000000..4f24e1932d9 --- /dev/null +++ b/samples/charger/src/main.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2023 Cirrus Logic, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "zephyr/sys/printk.h" +#include +#include +#include +#include +#include + +static const struct device *chgdev = DEVICE_DT_GET(DT_NODELABEL(charger)); + +int main(void) +{ + union charger_propval val; + int ret; + + if (chgdev == NULL) { + printk("Error: no charger device found.\n"); + return 0; + } + + if (!device_is_ready(chgdev)) { + printk("Error: Device \"%s\" is not ready; " + "check the driver initialization logs for errors.\n", + chgdev->name); + return 0; + } + + printk("Found device \"%s\", getting charger data\n", chgdev->name); + + while (1) { + /* Poll until external power is presented to the charger */ + do { + ret = charger_get_prop(chgdev, CHARGER_PROP_ONLINE, &val); + if (ret < 0) { + return ret; + } + + k_msleep(100); + } while (val.online == CHARGER_ONLINE_OFFLINE); + + val.status = CHARGER_STATUS_CHARGING; + + ret = charger_set_prop(chgdev, CHARGER_PROP_STATUS, &val); + if (ret == -ENOTSUP) { + printk("Enabling charge not supported, assuming auto charge enable\n"); + continue; + } else if (ret < 0) { + return ret; + } + + k_msleep(500); + + ret = charger_get_prop(chgdev, CHARGER_PROP_STATUS, &val); + if (ret < 0) { + return ret; + } + + switch (val.status) { + case CHARGER_STATUS_CHARGING: + printk("Charging in progress...\n"); + + ret = charger_get_prop(chgdev, CHARGER_PROP_CHARGE_TYPE, &val); + if (ret < 0) { + return ret; + } + + printk("Device \"%s\" charge type is %d\n", chgdev->name, val.charge_type); + break; + case CHARGER_STATUS_NOT_CHARGING: + printk("Charging halted...\n"); + + ret = charger_get_prop(chgdev, CHARGER_PROP_HEALTH, &val); + if (ret < 0) { + return ret; + } + + printk("Device \"%s\" health is %d\n", chgdev->name, val.health); + break; + case CHARGER_STATUS_FULL: + printk("Charging complete!"); + return 0; + case CHARGER_STATUS_DISCHARGING: + printk("External power removed, discharging\n"); + + ret = charger_get_prop(chgdev, CHARGER_PROP_ONLINE, &val); + if (ret < 0) { + return ret; + } + break; + default: + return -EIO; + } + + k_msleep(500); + } +} diff --git a/samples/compression/lz4/prj.conf b/samples/compression/lz4/prj.conf index 34e20dad07d..d4f2049eb89 100644 --- a/samples/compression/lz4/prj.conf +++ b/samples/compression/lz4/prj.conf @@ -1,3 +1,4 @@ CONFIG_LZ4=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_HEAP_MEM_POOL_SIZE=16384 +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=24576 diff --git a/samples/compression/lz4/sample.yaml b/samples/compression/lz4/sample.yaml index 442845e199d..f9758f26984 100644 --- a/samples/compression/lz4/sample.yaml +++ b/samples/compression/lz4/sample.yaml @@ -6,12 +6,14 @@ common: - compression - lz4 min_ram: 64 - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED harness: console harness_config: type: one_line regex: - "Validation done. (.*)" + modules: + - lz4 tests: sample.compression.lz4: integration_platforms: diff --git a/samples/drivers/adc/README.rst b/samples/drivers/adc/README.rst index 4b701cc1711..b91867e2ff0 100644 --- a/samples/drivers/adc/README.rst +++ b/samples/drivers/adc/README.rst @@ -1,12 +1,13 @@ -.. _adc-sample: +.. zephyr:code-sample:: adc + :name: Analog-to-Digital Converter (ADC) + :relevant-api: adc_interface -Analog-to-Digital Converter (ADC) -################################# + Read analog inputs from ADC channels. Overview ******** -This sample demonstrates how to use the ADC driver API. +This sample demonstrates how to use the :ref:`ADC driver API `. Depending on the target board, it reads ADC samples from one or more channels and prints the readings on the console. If voltage of the used reference can diff --git a/samples/drivers/adc/boards/cy8cproto_063_ble.overlay b/samples/drivers/adc/boards/cy8cproto_063_ble.overlay index 48b2befb803..c2f70eff7e8 100644 --- a/samples/drivers/adc/boards/cy8cproto_063_ble.overlay +++ b/samples/drivers/adc/boards/cy8cproto_063_ble.overlay @@ -24,7 +24,7 @@ zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; zephyr,resolution = <12>; - zephyr,input-positive = <0>; /* P10.0 */ + zephyr,input-positive = <2>; /* P10.2 */ }; channel@1 { @@ -33,7 +33,7 @@ zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; zephyr,resolution = <12>; - zephyr,input-positive = <1>; /* P10.1 */ + zephyr,input-positive = <3>; /* P10.3 */ }; channel@2 { @@ -42,7 +42,7 @@ zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; zephyr,resolution = <12>; - zephyr,input-positive = <2>; /* P10.2 */ + zephyr,input-positive = <4>; /* P10.4 */ }; channel@3 { @@ -51,6 +51,6 @@ zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; zephyr,resolution = <12>; - zephyr,input-positive = <3>; /* P10.3 */ + zephyr,input-positive = <5>; /* P10.5 */ }; }; diff --git a/samples/drivers/adc/boards/esp32c3_luatos_core.overlay b/samples/drivers/adc/boards/esp32c3_luatos_core.overlay new file mode 100644 index 00000000000..d43209179f7 --- /dev/null +++ b/samples/drivers/adc/boards/esp32c3_luatos_core.overlay @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 Wolter HV + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + zephyr,user { + io-channels = + <&adc0 0>, + <&adc1 0>; + }; +}; + +&adc0 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1_4"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; + +&adc1 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1_4"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; diff --git a/samples/drivers/adc/boards/esp32c3_luatos_core_usb.overlay b/samples/drivers/adc/boards/esp32c3_luatos_core_usb.overlay new file mode 100644 index 00000000000..d43209179f7 --- /dev/null +++ b/samples/drivers/adc/boards/esp32c3_luatos_core_usb.overlay @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 Wolter HV + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + zephyr,user { + io-channels = + <&adc0 0>, + <&adc1 0>; + }; +}; + +&adc0 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1_4"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; + +&adc1 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1_4"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; diff --git a/samples/drivers/adc/boards/esp32s3_luatos_core.overlay b/samples/drivers/adc/boards/esp32s3_luatos_core.overlay new file mode 100644 index 00000000000..d43209179f7 --- /dev/null +++ b/samples/drivers/adc/boards/esp32s3_luatos_core.overlay @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 Wolter HV + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + zephyr,user { + io-channels = + <&adc0 0>, + <&adc1 0>; + }; +}; + +&adc0 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1_4"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; + +&adc1 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1_4"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; diff --git a/samples/drivers/adc/boards/esp32s3_luatos_core_usb.overlay b/samples/drivers/adc/boards/esp32s3_luatos_core_usb.overlay new file mode 100644 index 00000000000..d43209179f7 --- /dev/null +++ b/samples/drivers/adc/boards/esp32s3_luatos_core_usb.overlay @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 Wolter HV + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + zephyr,user { + io-channels = + <&adc0 0>, + <&adc1 0>; + }; +}; + +&adc0 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1_4"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; + +&adc1 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1_4"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; diff --git a/samples/drivers/adc/boards/longan_nano.overlay b/samples/drivers/adc/boards/longan_nano.overlay new file mode 100644 index 00000000000..390534e74ff --- /dev/null +++ b/samples/drivers/adc/boards/longan_nano.overlay @@ -0,0 +1,23 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + zephyr,user { + /* adjust channel number according to pinmux in board.dts */ + io-channels = <&adc0 0>; + }; +}; + +&adc0 { + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; diff --git a/samples/drivers/adc/boards/longan_nano_lite.overlay b/samples/drivers/adc/boards/longan_nano_lite.overlay new file mode 100644 index 00000000000..390534e74ff --- /dev/null +++ b/samples/drivers/adc/boards/longan_nano_lite.overlay @@ -0,0 +1,23 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + zephyr,user { + /* adjust channel number according to pinmux in board.dts */ + io-channels = <&adc0 0>; + }; +}; + +&adc0 { + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; diff --git a/samples/drivers/adc/sample.yaml b/samples/drivers/adc/sample.yaml index fd3807fad99..2ed1681a0e0 100644 --- a/samples/drivers/adc/sample.yaml +++ b/samples/drivers/adc/sample.yaml @@ -2,13 +2,15 @@ sample: name: ADC driver sample tests: sample.drivers.adc: - tags: ADC + tags: + - adc depends_on: adc platform_allow: - nucleo_l073rz - disco_l475_iot1 - cc3220sf_launchxl - cc3235sf_launchxl + - cy8cproto_063_ble - stm32l496g_disco - stm32h735g_disco - nrf51dk_nrf51422 @@ -25,6 +27,8 @@ tests: - gd32l233r_eval - lpcxpresso55s36 - mr_canhubk3 + - longan_nano + - longan_nano_lite integration_platforms: - nucleo_l073rz - nrf52840dk_nrf52840 diff --git a/samples/drivers/adc/src/main.c b/samples/drivers/adc/src/main.c index 50f54455de6..0f781eac700 100644 --- a/samples/drivers/adc/src/main.c +++ b/samples/drivers/adc/src/main.c @@ -65,7 +65,7 @@ int main(void) (void)adc_sequence_init_dt(&adc_channels[i], &sequence); - err = adc_read(adc_channels[i].dev, &sequence); + err = adc_read_dt(&adc_channels[i], &sequence); if (err < 0) { printk("Could not read (%d)\n", err); continue; diff --git a/samples/drivers/audio/dmic/README.rst b/samples/drivers/audio/dmic/README.rst index 70e2b5b8ba1..3e1463795c0 100644 --- a/samples/drivers/audio/dmic/README.rst +++ b/samples/drivers/audio/dmic/README.rst @@ -1,13 +1,14 @@ -.. _dmic_sample: +.. zephyr:code-sample:: dmic + :name: Digital Microphone (DMIC) + :relevant-api: audio_dmic_interface -DMIC Sample -########### + Perform PDM transfers using different configurations. Overview ******** -This is a very simple application intended to show how to use the Audio DMIC -API and also to be an aid in developing drivers to implement this API. +This is a very simple application intended to show how to use the :ref:`Audio DMIC +API ` and also to be an aid in developing drivers to implement this API. It performs two PDM transfers with different configurations (using one channel and two channels) but does not in any way process the received audio data. diff --git a/samples/drivers/auxdisplay/README.rst b/samples/drivers/auxdisplay/README.rst index 1bbe5750d6a..67bfb0e5677 100644 --- a/samples/drivers/auxdisplay/README.rst +++ b/samples/drivers/auxdisplay/README.rst @@ -1,13 +1,14 @@ -.. _auxdisplay-sample: +.. zephyr:code-sample:: auxdisplay + :name: Auxiliary display + :relevant-api: auxdisplay_interface -Auxiliary display sample -######################## + Output "Hello World" to an auxiliary display. Overview ******** -This sample shows how to use the auxiliary display drivers by outputting a -sample "Hello World" text to one. +This sample shows how to use the :ref:`auxiliary display driver ` +by outputting a sample "Hello World" text to one. Building and Running ******************** diff --git a/samples/drivers/can/babbling/Kconfig b/samples/drivers/can/babbling/Kconfig index c98047657a0..0d283081527 100644 --- a/samples/drivers/can/babbling/Kconfig +++ b/samples/drivers/can/babbling/Kconfig @@ -22,10 +22,10 @@ config SAMPLE_CAN_BABBLING_RTR Babbling node sends Remote Transmission Request (RTR) frames. config SAMPLE_CAN_BABBLING_FD_MODE - bool "Send CAN-FD format frames" + bool "Send CAN FD format frames" select CAN_FD_MODE help - Babbling node sends CAN-FD format frames. + Babbling node sends CAN FD format frames. config SAMPLE_CAN_BABBLING_TX_QUEUE_SIZE int "Maximum number of CAN frames to enqueue" diff --git a/samples/drivers/can/babbling/README.rst b/samples/drivers/can/babbling/README.rst index 1f5e7128cc1..f13c80af822 100644 --- a/samples/drivers/can/babbling/README.rst +++ b/samples/drivers/can/babbling/README.rst @@ -1,7 +1,8 @@ -.. _can-babbling-sample: +.. zephyr:code-sample:: can-babbling + :name: Controller Area Network (CAN) babbling node + :relevant-api: can_interface -Controller Area Network (CAN) Babbling Node -########################################### + Simulate a babbling CAN node. Overview ******** @@ -46,5 +47,5 @@ Sample output .. code-block:: console *** Booting Zephyr OS build zephyr-v3.1.0-4606-g8c1efa8b96bb *** - babbling on can@40024000 with standard (11-bit) CAN ID 0x010, RTR 0, CAN-FD 0 + babbling on can@40024000 with standard (11-bit) CAN ID 0x010, RTR 0, CAN FD 0 abort by pressing User SW3 button diff --git a/samples/drivers/can/babbling/sample.yaml b/samples/drivers/can/babbling/sample.yaml index 8a52e4f59cb..2e7a8320dae 100644 --- a/samples/drivers/can/babbling/sample.yaml +++ b/samples/drivers/can/babbling/sample.yaml @@ -6,7 +6,7 @@ tests: depends_on: can filter: dt_chosen_enabled("zephyr,canbus") integration_platforms: - - native_posix + - native_sim harness: console harness_config: type: one_line diff --git a/samples/drivers/can/babbling/src/main.c b/samples/drivers/can/babbling/src/main.c index d43623bd878..ada6852ae8f 100644 --- a/samples/drivers/can/babbling/src/main.c +++ b/samples/drivers/can/babbling/src/main.c @@ -60,7 +60,7 @@ int main(void) if (IS_ENABLED(CONFIG_SAMPLE_CAN_BABBLING_FD_MODE)) { err = can_set_mode(dev, CAN_MODE_FD); if (err != 0) { - printk("Error setting CAN-FD mode (err %d)", err); + printk("Error setting CAN FD mode (err %d)", err); return 0; } } @@ -109,7 +109,7 @@ int main(void) frame.id = CONFIG_SAMPLE_CAN_BABBLING_CAN_ID; - printk("babbling on %s with %s (%d-bit) CAN ID 0x%0*x, RTR %d, CAN-FD %d\n", + printk("babbling on %s with %s (%d-bit) CAN ID 0x%0*x, RTR %d, CAN FD %d\n", dev->name, (frame.flags & CAN_FRAME_IDE) != 0 ? "extended" : "standard", (frame.flags & CAN_FRAME_IDE) != 0 ? 29 : 11, diff --git a/samples/drivers/can/counter/README.rst b/samples/drivers/can/counter/README.rst index 10a35ac480e..6addd47b714 100644 --- a/samples/drivers/can/counter/README.rst +++ b/samples/drivers/can/counter/README.rst @@ -1,7 +1,8 @@ -.. _can-counter-sample: +.. zephyr:code-sample:: can-counter + :name: Controller Area Network (CAN) counter + :relevant-api: can_interface -Controller Area Network (CAN) Counter -##################################### + Send and receive CAN messages. Overview ******** diff --git a/samples/drivers/can/counter/sample.yaml b/samples/drivers/can/counter/sample.yaml index 20f609d0c36..579fc82a069 100644 --- a/samples/drivers/can/counter/sample.yaml +++ b/samples/drivers/can/counter/sample.yaml @@ -5,7 +5,7 @@ tests: tags: can depends_on: can integration_platforms: - - native_posix + - native_sim filter: dt_chosen_enabled("zephyr,canbus") and not dt_compat_enabled("kvaser,pcican") harness: console harness_config: diff --git a/samples/drivers/clock_control_litex/README.rst b/samples/drivers/clock_control_litex/README.rst index a77002a0e2e..c2fa951bd38 100644 --- a/samples/drivers/clock_control_litex/README.rst +++ b/samples/drivers/clock_control_litex/README.rst @@ -1,7 +1,8 @@ -.. _clock_control_litex_sample: +.. zephyr:code-sample:: clock-control-litex + :name: LiteX clock control driver + :relevant-api: clock_control_interface -LiteX Clock Control Driver Sample -################################# + Use LiteX clock control driver to generate multiple clock signals. Introduction ************ diff --git a/samples/drivers/clock_control_litex/sample.yaml b/samples/drivers/clock_control_litex/sample.yaml index 5c9ae55424f..cf5618313c5 100644 --- a/samples/drivers/clock_control_litex/sample.yaml +++ b/samples/drivers/clock_control_litex/sample.yaml @@ -4,7 +4,5 @@ tests: sample.driver.clock_control_litex: platform_allow: litex_vexriscv tags: - - clock - - litex - - vexriscv + - clock_control - mmcm diff --git a/samples/drivers/counter/alarm/README.rst b/samples/drivers/counter/alarm/README.rst index 9efffc81ae7..50ddfed2b13 100644 --- a/samples/drivers/counter/alarm/README.rst +++ b/samples/drivers/counter/alarm/README.rst @@ -1,11 +1,12 @@ -.. _alarm_sample: +.. zephyr:code-sample:: alarm + :name: Counter Alarm + :relevant-api: counter_interface -Counter Alarm Sample -##################### + Implement an alarm application using the counter API. Overview ******** -This sample provides an example of alarm application using counter API. +This sample provides an example of alarm application using :ref:`counter API `. It sets an alarm with an initial delay of 2 seconds. At each alarm expiry, a new alarm is configured with a delay multiplied by 2. diff --git a/samples/drivers/counter/alarm/boards/esp32c3_luatos_core.overlay b/samples/drivers/counter/alarm/boards/esp32c3_luatos_core.overlay new file mode 100644 index 00000000000..241947b0643 --- /dev/null +++ b/samples/drivers/counter/alarm/boards/esp32c3_luatos_core.overlay @@ -0,0 +1,3 @@ +&timer0 { + status = "okay"; +}; diff --git a/samples/drivers/counter/alarm/boards/esp32c3_luatos_core_usb.overlay b/samples/drivers/counter/alarm/boards/esp32c3_luatos_core_usb.overlay new file mode 100644 index 00000000000..241947b0643 --- /dev/null +++ b/samples/drivers/counter/alarm/boards/esp32c3_luatos_core_usb.overlay @@ -0,0 +1,3 @@ +&timer0 { + status = "okay"; +}; diff --git a/samples/drivers/counter/alarm/boards/esp32s3_luatos_core.overlay b/samples/drivers/counter/alarm/boards/esp32s3_luatos_core.overlay new file mode 100644 index 00000000000..241947b0643 --- /dev/null +++ b/samples/drivers/counter/alarm/boards/esp32s3_luatos_core.overlay @@ -0,0 +1,3 @@ +&timer0 { + status = "okay"; +}; diff --git a/samples/drivers/counter/alarm/boards/esp32s3_luatos_core_usb.overlay b/samples/drivers/counter/alarm/boards/esp32s3_luatos_core_usb.overlay new file mode 100644 index 00000000000..241947b0643 --- /dev/null +++ b/samples/drivers/counter/alarm/boards/esp32s3_luatos_core_usb.overlay @@ -0,0 +1,3 @@ +&timer0 { + status = "okay"; +}; diff --git a/samples/drivers/counter/alarm/sample.yaml b/samples/drivers/counter/alarm/sample.yaml index d799d04f5f7..fe81529a45b 100644 --- a/samples/drivers/counter/alarm/sample.yaml +++ b/samples/drivers/counter/alarm/sample.yaml @@ -25,6 +25,7 @@ tests: - gd32f470i_eval - stm32h735g_disco - stm32h573i_dk + - rpi_pico integration_platforms: - nucleo_f746zg harness_config: diff --git a/samples/drivers/counter/alarm/src/main.c b/samples/drivers/counter/alarm/src/main.c index eb19bbdf098..9eee4d3fba2 100644 --- a/samples/drivers/counter/alarm/src/main.c +++ b/samples/drivers/counter/alarm/src/main.c @@ -51,6 +51,8 @@ struct counter_alarm_cfg alarm_cfg; #define TIMER DT_NODELABEL(counter0) #elif defined(CONFIG_COUNTER_SNPS_DW) #define TIMER DT_NODELABEL(timer0) +#elif defined(CONFIG_COUNTER_TIMER_RPI_PICO) +#define TIMER DT_NODELABEL(timer) #endif static void test_counter_interrupt_fn(const struct device *counter_dev, diff --git a/samples/drivers/counter/maxim_ds3231/README.rst b/samples/drivers/counter/maxim_ds3231/README.rst index f8ad28a3f82..dbea079ef21 100644 --- a/samples/drivers/counter/maxim_ds3231/README.rst +++ b/samples/drivers/counter/maxim_ds3231/README.rst @@ -1,7 +1,8 @@ -.. _maxim-ds3231-sample: +.. zephyr:code-sample:: ds3231 + :name: DS3231 TCXO RTC + :relevant-api: counter_interface -Maxim DS3231 TCXO RTC Sample Application -######################################## + Interact with a DS3231 real-time clock using the counter API and dedicated driver API. Overview ******** diff --git a/samples/drivers/counter/maxim_ds3231/prj.conf b/samples/drivers/counter/maxim_ds3231/prj.conf index e858ebb2441..26421607393 100644 --- a/samples/drivers/counter/maxim_ds3231/prj.conf +++ b/samples/drivers/counter/maxim_ds3231/prj.conf @@ -6,7 +6,7 @@ CONFIG_COUNTER_MAXIM_DS3231=y CONFIG_COUNTER_INIT_PRIORITY=65 # Minimal libc doesn't have strftime() -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y # Optional step that syncs RTC and local clock. Don't enable this if # your RTC has already been synchronized and you want to keep its diff --git a/samples/drivers/counter/maxim_ds3231/sample.yaml b/samples/drivers/counter/maxim_ds3231/sample.yaml index 6e244d62da0..4e9c209047c 100644 --- a/samples/drivers/counter/maxim_ds3231/sample.yaml +++ b/samples/drivers/counter/maxim_ds3231/sample.yaml @@ -1,5 +1,5 @@ common: - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED sample: name: Maxim DS3231 RTC tests: diff --git a/samples/drivers/counter/maxim_ds3231/src/main.c b/samples/drivers/counter/maxim_ds3231/src/main.c index 32c37c17188..992283ef343 100644 --- a/samples/drivers/counter/maxim_ds3231/src/main.c +++ b/samples/drivers/counter/maxim_ds3231/src/main.c @@ -105,7 +105,7 @@ static void min_alarm_handler(const struct device *dev, (void)counter_get_value(dev, &time); uint32_t uptime = k_uptime_get_32(); - uint8_t us = uptime % 1000U; + uint16_t ms = uptime % 1000U; uptime /= 1000U; uint8_t se = uptime % 60U; @@ -143,7 +143,7 @@ static void min_alarm_handler(const struct device *dev, printk("%s: adj %d.%09lu, uptime %u:%02u:%02u.%03u, clk err %d ppm\n", format_time(time, -1), (uint32_t)(ts->tv_sec - time), ts->tv_nsec, - hr, mn, se, us, err_ppm); + hr, mn, se, ms, err_ppm); } struct maxim_ds3231_alarm sec_alarm; diff --git a/samples/drivers/crypto/README.rst b/samples/drivers/crypto/README.rst index ee53a917182..02d86b35cec 100644 --- a/samples/drivers/crypto/README.rst +++ b/samples/drivers/crypto/README.rst @@ -1,11 +1,12 @@ -.. _crypto_sample: +.. zephyr:code-sample:: crypto + :name: Crypto + :relevant-api: crypto -Crypto -###### + Use the crypto APIs to perform various encryption/decryption operations. Overview ******** -An example to illustrate the usage of crypto APIs. +An example to illustrate the usage of :ref:`crypto APIs `. Building and Running ******************** diff --git a/samples/drivers/crypto/sample.yaml b/samples/drivers/crypto/sample.yaml index d63e7a4a68a..c969bafa67c 100644 --- a/samples/drivers/crypto/sample.yaml +++ b/samples/drivers/crypto/sample.yaml @@ -12,7 +12,7 @@ tests: harness: console extra_args: EXTRA_CONF_FILE=prj_tinycrypt_shim.conf integration_platforms: - - native_posix + - native_sim harness_config: type: multi_line regex: @@ -26,7 +26,7 @@ tests: harness: console extra_args: EXTRA_CONF_FILE=prj_mtls_shim.conf integration_platforms: - - native_posix + - native_sim harness_config: type: multi_line regex: diff --git a/samples/drivers/current_sensing/CMakeLists.txt b/samples/drivers/current_sensing/CMakeLists.txt deleted file mode 100644 index 280fd63bace..00000000000 --- a/samples/drivers/current_sensing/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(current_sensing) - -FILE(GLOB app_sources src/*.c) -target_sources(app PRIVATE ${app_sources}) diff --git a/samples/drivers/dac/README.rst b/samples/drivers/dac/README.rst index 0075f8f9f67..2803abd8ba7 100644 --- a/samples/drivers/dac/README.rst +++ b/samples/drivers/dac/README.rst @@ -1,12 +1,13 @@ -.. _dac-sample: +.. zephyr:code-sample:: dac + :name: Digital-to-Analog Converter (DAC) + :relevant-api: dac_interface -Digital-to-Analog Converter (DAC) -################################# + Generate an analog sawtooth signal using the DAC driver API. Overview ******** -This sample demonstrates how to use the DAC driver API. +This sample demonstrates how to use the :ref:`DAC driver API `. Building and Running ******************** @@ -209,6 +210,19 @@ also can run for the :goals: build flash :compact: +Building and Running for NXP LPCXpresso55S36 +============================================ +The sample can be built and executed for the :ref:`lpcxpresso55s36` as +follows: + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/dac + :board: lpcxpresso55s36 + :goals: build flash + :compact: + +DAC output is available on connector J12 pin 4. + Sample output ============= diff --git a/samples/drivers/dac/boards/lpcxpresso55s36.overlay b/samples/drivers/dac/boards/lpcxpresso55s36.overlay new file mode 100644 index 00000000000..a3698266744 --- /dev/null +++ b/samples/drivers/dac/boards/lpcxpresso55s36.overlay @@ -0,0 +1,13 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + zephyr,user { + dac = <&dac0>; + dac-channel-id = <0>; + dac-resolution = <12>; + }; +}; diff --git a/samples/drivers/dac/sample.yaml b/samples/drivers/dac/sample.yaml index 7a2c0d0a4e9..8ac2943ecfc 100644 --- a/samples/drivers/dac/sample.yaml +++ b/samples/drivers/dac/sample.yaml @@ -42,6 +42,7 @@ tests: - stm32f3_disco - stm32l562e_dk - twr_ke18f + - lpcxpresso55s36 depends_on: dac integration_platforms: - nucleo_l152re diff --git a/samples/drivers/display/README.rst b/samples/drivers/display/README.rst index de774646789..872a0b5f5d2 100644 --- a/samples/drivers/display/README.rst +++ b/samples/drivers/display/README.rst @@ -1,7 +1,8 @@ -.. _display-sample: +.. zephyr:code-sample:: display + :name: Display + :relevant-api: display_interface -Display Sample -############## + Draw basic rectangles on a display device. Overview ******** @@ -29,12 +30,12 @@ Below is an example on how to build for a :ref:`nrf52840dk_nrf52840` board with :shield: adafruit_2_8_tft_touch_v2 :compact: -For testing purpose without the need of any hardware, the :ref:`native_posix` +For testing purpose without the need of any hardware, the :ref:`native_sim ` board is also supported and can be built as follows; .. zephyr-app-commands:: :zephyr-app: samples/drivers/display - :board: native_posix + :board: native_sim :goals: build :compact: diff --git a/samples/drivers/display/sample.yaml b/samples/drivers/display/sample.yaml index f2cc9d0a89d..ba93efd5c2e 100644 --- a/samples/drivers/display/sample.yaml +++ b/samples/drivers/display/sample.yaml @@ -103,10 +103,14 @@ tests: fixture: fixture_display sample.display.sdl: build_only: true - platform_allow: native_posix_64 + platform_allow: + - native_posix_64 + - native_sim_64 tags: display sample.display.dummy: - platform_allow: native_posix + platform_allow: + - native_posix + - native_sim extra_args: DTC_OVERLAY_FILE="dummy_dc.overlay" extra_configs: - CONFIG_DUMMY_DISPLAY=y @@ -131,3 +135,14 @@ tests: harness: console harness_config: fixture: fixture_display + sample.display.g1120b0mipi: + platform_allow: mimxrt595_evk_cm33 + tags: display + harness: console + extra_args: SHIELD=g1120b0mipi + extra_configs: + - CONFIG_PM=y + - CONFIG_PM_DEVICE=y + - CONFIG_IDLE_STACK_SIZE=400 + harness_config: + fixture: fixture_display diff --git a/samples/drivers/eeprom/README.rst b/samples/drivers/eeprom/README.rst index 98007767a5e..079a3ebb469 100644 --- a/samples/drivers/eeprom/README.rst +++ b/samples/drivers/eeprom/README.rst @@ -1,12 +1,13 @@ -.. _samples_eeprom: +.. zephyr:code-sample:: eeprom + :name: EEPROM + :relevant-api: eeprom_interface -EEPROM Sample -############# + Store a boot count value in EEPROM. Overview ******** -This sample demonstrates the EEPROM driver API in a simple boot counter +This sample demonstrates the :ref:`EEPROM driver API ` in a simple boot counter application. Building and Running @@ -14,12 +15,12 @@ Building and Running In case the target board has defined an EEPROM with alias ``eeprom-0`` the sample can be built without further ado. This applies for example to the -:ref:`native_posix` board: +:ref:`native_sim` board: .. zephyr-app-commands:: :zephyr-app: samples/drivers/eeprom :host-os: unix - :board: native_posix + :board: native_sim :goals: run :compact: diff --git a/samples/drivers/eeprom/sample.yaml b/samples/drivers/eeprom/sample.yaml index b971faf9ba5..c9dfa7dd071 100644 --- a/samples/drivers/eeprom/sample.yaml +++ b/samples/drivers/eeprom/sample.yaml @@ -8,8 +8,10 @@ tests: - gd32f450i_eval - native_posix - native_posix_64 + - native_sim + - native_sim_64 integration_platforms: - - native_posix_64 + - native_sim_64 harness: console harness_config: type: one_line diff --git a/samples/drivers/espi/README.rst b/samples/drivers/espi/README.rst index eef65b6741b..cbb6bb752b6 100644 --- a/samples/drivers/espi/README.rst +++ b/samples/drivers/espi/README.rst @@ -1,13 +1,14 @@ -.. _espi-sample: +.. zephyr:code-sample:: espi + :name: Enhanced Serial Peripheral Interface (eSPI) + :relevant-api: espi_interface spi_interface -Enhanced Serial Peripheral Interface -#################################### + Use eSPI to connect to a slave device and exchange virtual wire packets. Overview ******** -This sample demonstrates how to use the Enhanced Serial Peripheral Interface -(eSPI) API. +This sample demonstrates how to use the :ref:`Enhanced Serial Peripheral Interface +(eSPI) API `. It shows how to configure and select eSPI controller capabilities as part of a simple eSPI handshake that includes exchanging virtual wire packets. diff --git a/samples/drivers/ethernet/eth_ivshmem/README.rst b/samples/drivers/ethernet/eth_ivshmem/README.rst index 5757bbd6c83..03de6cd0e39 100644 --- a/samples/drivers/ethernet/eth_ivshmem/README.rst +++ b/samples/drivers/ethernet/eth_ivshmem/README.rst @@ -1,7 +1,8 @@ -.. _eth_ivshmem_sample: +.. zephyr:code-sample:: eth-ivshmem + :name: Inter-VM Shared Memory (ivshmem) Ethernet + :relevant-api: ivshmem ethernet -Inter-VM Shared Memory (ivshmem) Ethernet Sample Application -############################################################ + Communicate with another "cell" in the Jailhouse hypervisor using IVSHMEM Ethernet. Overview ******** diff --git a/samples/drivers/flash_shell/Kconfig b/samples/drivers/flash_shell/Kconfig deleted file mode 100644 index aa7016fa9ae..00000000000 --- a/samples/drivers/flash_shell/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2020, Linaro Ltd. -# SPDX-License-Identifier: Apache-2.0 - -source "Kconfig.zephyr" - -if ARM_MPU -config MPU_ALLOW_FLASH_WRITE - def_bool y -endif diff --git a/samples/drivers/flash_shell/README.rst b/samples/drivers/flash_shell/README.rst index 60623450a36..f6e1b78a38c 100644 --- a/samples/drivers/flash_shell/README.rst +++ b/samples/drivers/flash_shell/README.rst @@ -1,10 +1,12 @@ -.. _samples_flash_shell: +.. zephyr:code-sample:: flash-shell + :name: Flash shell + :relevant-api: flash_interface -Flash Shell Sample -################## + Explore a flash device using shell commands. Overview ******** + This is a simple shell module that allows arbitrary boards with flash driver support to explore the flash device. @@ -25,19 +27,24 @@ Sample Output .. code-block:: console - uart:~$ flash_sample page_count - Flash device contains 1024 pages. - uart:~$ flash_sample page_erase 1023 - Erasing page 1023 (start offset 0xffc00, size 0x400) - uart:~$ flash_sample page_write 1023 8 17 19 28 39 - Reading back written bytes: - 11 13 1c 27 - uart:~$ flash_sample page_write 1023 4 77 9 1 2 - Reading back written bytes: - 4d 09 01 02 - uart:~$ flash_sample page_read 1023 4 12 - 4d 09 01 02 | 11 13 1c 27 - ff ff ff ff - uart:~$ flash_sample page_read 1023 0 16 - ff ff ff ff | 4d 09 01 02 - 11 13 1c 27 | ff ff ff ff + uart:~$ flash page_info 0 + Page for address 0x0: + start offset: 0x0 + size: 4096 + index: 0 + uart:~$ flash erase 0x1000 + Erase success. + uart:~$ flash write 0x1000 0x12345678 0x9abcdef0 + Write OK. + Verified. + uart:~$ flash write 0x1000 0x11111111 + Write internal ERROR! + uart:~$ flash read 0x1000 0x10 + 00001000: 78 56 34 12 f0 de bc 9a ff ff ff ff ff ff ff ff |xV4..... ........| + + uart:~$ flash write 0x101c 0xabcd1234 + Write OK. + Verified. + uart:~$ flash read 0x1000 0x20 + 00001000: 78 56 34 12 f0 de bc 9a ff ff ff ff ff ff ff ff |xV4..... ........| + 00001010: ff ff ff ff ff ff ff ff ff ff ff ff 34 12 cd ab |........ ....4...| diff --git a/samples/drivers/flash_shell/prj.conf b/samples/drivers/flash_shell/prj.conf index 4e60a63bd0a..657776e96ce 100644 --- a/samples/drivers/flash_shell/prj.conf +++ b/samples/drivers/flash_shell/prj.conf @@ -2,8 +2,5 @@ CONFIG_PRINTK=y CONFIG_SHELL=y CONFIG_LOG=y CONFIG_FLASH=y -# Your flash driver may not enable this, even if it's supported. -# If that's the case and you're interested in the flash layout, enable -# it here. -# CONFIG_FLASH_PAGE_LAYOUT=y -CONFIG_HEAP_MEM_POOL_SIZE=16384 +CONFIG_FLASH_SHELL=y +CONFIG_FLASH_SHELL_TEST_COMMANDS=y diff --git a/samples/drivers/flash_shell/src/main.c b/samples/drivers/flash_shell/src/main.c index e7e1b2d3b4b..2de337414d5 100644 --- a/samples/drivers/flash_shell/src/main.c +++ b/samples/drivers/flash_shell/src/main.c @@ -3,767 +3,12 @@ * * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -LOG_MODULE_REGISTER(app); - -#define PR_SHELL(sh, fmt, ...) \ - shell_fprintf(sh, SHELL_NORMAL, fmt, ##__VA_ARGS__) -#define PR_ERROR(sh, fmt, ...) \ - shell_fprintf(sh, SHELL_ERROR, fmt, ##__VA_ARGS__) -#define PR_INFO(sh, fmt, ...) \ - shell_fprintf(sh, SHELL_INFO, fmt, ##__VA_ARGS__) -#define PR_WARNING(sh, fmt, ...) \ - shell_fprintf(sh, SHELL_WARNING, fmt, ##__VA_ARGS__) - -/* Command usage info. */ -#define WRITE_BLOCK_SIZE_HELP \ - ("Print the device's write block size. This is the smallest amount" \ - " of data which may be written to the device, in bytes.") -#define READ_HELP \ - (" \n" \ - "Read bytes from device offset .") -#define ERASE_HELP \ - (" \n\n" \ - "Erase bytes from device offset , " \ - "subject to hardware page limitations.") -#define WRITE_HELP \ - (" [... byteN]\n\n" \ - "Write given bytes, starting at device offset .\n" \ - "Pages must be erased before they can be written.") -#define WRITE_UNALIGNED_HELP \ - (" [... byteN]\n\n" \ - "Write given bytes, starting at device offset .\n" \ - "Being unaligned, affected memory areas are backed up, erased, protected" \ - " and then overwritten.\n" \ - "This command is designed to test writing to large flash pages.") -#define WRITE_PATTERN_HELP \ - (" \n\n" \ - "Writes a pattern of (0x00 0x01 .. 0xFF 0x00 ..) of length" \ - " at the offset .\n" \ - "Unaligned writing is used, i.e. protection and erasing are automated." \ - "This command is designed to test writing to large flash pages.") -#ifdef CONFIG_FLASH_PAGE_LAYOUT -#define PAGE_COUNT_HELP \ - "\n\nPrint the number of pages on the flash device." -#define PAGE_LAYOUT_HELP \ - ("[start_page] [end_page]\n\n" \ - "Print layout of flash pages in the range [start_page, end_page]," \ - " which is inclusive. By default, all pages are printed.") -#define PAGE_READ_HELP \ - (" OR \n\n" \ - "Read bytes from given page, starting at page offset ," \ - "or offset 0 if not given. No checks are made that bytes read are" \ - " all within the page.") -#define PAGE_ERASE_HELP \ - (" [num]\n\n" \ - "Erase [num] pages (default 1), starting at page .") -#define PAGE_WRITE_HELP \ - (" [... byteN]\n\n" \ - "Write given bytes to given page, starting at page offset ." \ - " No checks are made that the bytes all fall within the page." \ - " Pages must be erased before they can be written.") -#endif -#define SET_DEV_HELP \ - ("\n\n" \ - "Set flash device by name. If a flash device was not found," \ - " this command must be run first to bind a device to this module.") - -#if (CONFIG_SHELL_ARGC_MAX > 4) -#define ARGC_MAX (CONFIG_SHELL_ARGC_MAX - 4) -#else -#error Please increase CONFIG_SHELL_ARGC_MAX parameter. -#endif - -static const struct device *flash_device = - DEVICE_DT_GET_OR_NULL(DT_CHOSEN(zephyr_flash_controller)); - -static int check_flash_device(const struct shell *sh) -{ - if (flash_device == NULL) { - PR_ERROR(sh, "Flash device is unknown." - " Run set_device first.\n"); - return -ENODEV; - } - return 0; -} - -static int dump_buffer(const struct shell *sh, uint8_t *buf, size_t size, - uint8_t *cmp_buf) -{ - int ret = 0; - size_t i; - - for (i = 0; i < size; i++) { - /* Print each byte mismatch as error */ - if (cmp_buf != NULL && buf[i] != cmp_buf[i]) { - PR_ERROR(sh, "%02x ", buf[i]); - ret = -EIO; - } else { - PR_SHELL(sh, "%02x ", buf[i]); - } - - if ((i + 1) % 16 == 0) { - PR_SHELL(sh, "\n"); - } else if ((i + 1) % 4 == 0) { - PR_SHELL(sh, "| "); - } - } - - if (i % 16 != 0) { - PR_SHELL(sh, "\n"); - } - - return ret; -} - -static int parse_ul(const char *str, unsigned long *result) -{ - char *end; - unsigned long val; - - val = strtoul(str, &end, 0); - - if (*str == '\0' || *end != '\0') { - return -EINVAL; - } - - *result = val; - return 0; -} - -static int parse_u8(const char *str, uint8_t *result) -{ - unsigned long val; - - if (parse_ul(str, &val) || val > 0xff) { - return -EINVAL; - } - *result = (uint8_t)val; - return 0; -} - -/* Read bytes, dumping contents to console and printing on error. */ -static int do_read(const struct shell *sh, off_t offset, size_t len, - uint8_t *cmp_buf) -{ - uint8_t buf[64]; - int ret; - size_t read_len; - bool cmp_error = false; - - do { - read_len = len > sizeof(buf) ? sizeof(buf) : len; - ret = flash_read(flash_device, offset, buf, read_len); - if (ret != 0) { - PR_ERROR(sh, "flash_read error: %d\n", ret); - return ret; - } - ret = dump_buffer(sh, buf, read_len, cmp_buf); - if (ret == -EIO) { - cmp_error = true; - } - if (cmp_buf != NULL) { - cmp_buf += read_len; - } - len -= read_len; - offset += read_len; - } while (len > 0); - - if (cmp_error) { - PR_ERROR(sh, "Write verification error, unexpected values " - "marked red\n"); - } - - return 0; -} - -/* Erase area and printing on error. */ -static int do_erase(const struct shell *sh, off_t offset, size_t size) -{ - int ret; - - ret = flash_erase(flash_device, offset, size); - if (ret) { - PR_ERROR(sh, "flash_erase failed (err:%d).\n", ret); - return ret; - } - - return ret; -} - -/* Write bytes and printing on error. */ -static int do_write(const struct shell *sh, off_t offset, uint8_t *buf, - size_t len, bool read_back) -{ - int ret; - - ret = flash_write(flash_device, offset, buf, len); - if (ret) { - PR_ERROR(sh, "flash_write failed (err:%d).\n", ret); - return ret; - } - - if (read_back) { - PR_SHELL(sh, "Reading back written bytes:\n"); - ret = do_read(sh, offset, len, buf); - } - return ret; -} - -static int do_write_unaligned(const struct shell *sh, off_t offset, uint8_t *buf, - size_t len, bool read_back) -{ - int ret = 0; - size_t page_size = flash_get_write_block_size(flash_device); - size_t size_before = offset % page_size; - size_t size_after = page_size - ((size_before + len) % page_size); - size_t aligned_size = size_before + len + size_after; - off_t start_page = offset - size_before; - off_t last_page = start_page + aligned_size - page_size; - bool single_page_write = (size_before + len < page_size); - - char *before_data; - char *after_data; - - if (0 == size_before && 0 == size_after) { - /* Aligned write */ - flash_erase(flash_device, offset, len); - flash_write(flash_device, offset, buf, len); - - return 0; - } - - before_data = k_malloc(page_size); - after_data = k_malloc(page_size); - - if (!before_data || !after_data) { - PR_ERROR(sh, "No heap memory for flash manipulation\n"); - ret = -ENOMEM; - goto free_buffers; - } - - /* Stash useful data from the pages that will be affected. */ - if (single_page_write) { - /* Read old data before new data is written. */ - if (size_before) { - flash_read(flash_device, start_page, before_data, size_before); - } - /* Fill the with new data. */ - memcpy(before_data + size_before, buf, len); - /* Fill the last part of old data. */ - if (size_after) { - flash_read(flash_device, offset + len, - before_data + size_before + len, - size_after); - } - } else { - /* Multipage write, different start and end pages. */ - if (size_before) { - flash_read(flash_device, start_page, before_data, - size_before); - /* Fill the rest with new data. */ - memcpy(before_data + size_before, buf, - page_size - size_before); - } - if (size_after) { - /* Copy ending part of new data. */ - memcpy((void *)after_data, - (void *)(buf + len - - ((len + size_before) % page_size)), - page_size - size_after); - /* Copy ending part of flash page. */ - flash_read(flash_device, offset + len, - after_data + (page_size - size_after), - size_after); - } - } - - /* Erase all the pages that overlap with new data. */ - flash_erase(flash_device, start_page, aligned_size); - - /* Write stashed and new data. */ - if (single_page_write || size_before > 0) { - /* Write first page if available. */ - flash_write(flash_device, start_page, before_data, - page_size); - } - if (!single_page_write) { - size_t middle_data_len = aligned_size; - off_t middle_page_start = start_page; - off_t data_offset = (off_t)buf; - - /* Write the middle bit if available */ - if (size_before > 0) { - middle_page_start += page_size; - middle_data_len -= page_size; - data_offset += (page_size - size_before); - } - if (size_after > 0) { - middle_data_len -= page_size; - } - if (middle_data_len > 0) { - flash_write(flash_device, middle_page_start, - (const void *)data_offset, - middle_data_len); - } - - /* Write the last page if needed. */ - if (size_after > 0) { - flash_write(flash_device, last_page, after_data, - page_size); - } - } - - if (read_back) { - PR_SHELL(sh, "Reading back written bytes:\n"); - ret = do_read(sh, offset, len, buf); - } - -free_buffers: - k_free(before_data); - k_free(after_data); - - return ret; -} - -static int cmd_write_block_size(const struct shell *sh, size_t argc, - char **argv) -{ - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - int err = check_flash_device(sh); - - if (!err) { - PR_SHELL(sh, "%zu\n", - flash_get_write_block_size(flash_device)); - } - - return err; -} - -static int cmd_read(const struct shell *sh, size_t argc, char **argv) -{ - int err = check_flash_device(sh); - unsigned long int offset, len; - - if (err) { - goto exit; - } - - if (parse_ul(argv[1], &offset) || parse_ul(argv[2], &len)) { - PR_ERROR(sh, "Invalid arguments.\n"); - err = -EINVAL; - goto exit; - } - - err = do_read(sh, offset, len, NULL); - -exit: - return err; -} - -static int cmd_erase(const struct shell *sh, size_t argc, char **argv) -{ - int err = check_flash_device(sh); - unsigned long int offset; - unsigned long int size; - - if (err) { - goto exit; - } - - if (parse_ul(argv[1], &offset) || parse_ul(argv[2], &size)) { - PR_ERROR(sh, "Invalid arguments.\n"); - err = -EINVAL; - goto exit; - } - - err = do_erase(sh, (off_t)offset, (size_t)size); -exit: - return err; -} - -static int cmd_write_template(const struct shell *sh, size_t argc, char **argv, bool unaligned) -{ - unsigned long int i, offset; - uint8_t buf[ARGC_MAX]; - - int err = check_flash_device(sh); - - if (err) { - goto exit; - } - - err = parse_ul(argv[1], &offset); - if (err) { - PR_ERROR(sh, "Invalid argument.\n"); - goto exit; - } - - if ((argc - 2) > ARGC_MAX) { - /* Can only happen if Zephyr limit is increased. */ - PR_ERROR(sh, "At most %lu bytes can be written.\n" - "In order to write more bytes please increase" - " parameter: CONFIG_SHELL_ARGC_MAX.\n", - (unsigned long)ARGC_MAX); - err = -EINVAL; - goto exit; - } - - /* skip cmd name and offset */ - argc -= 2; - argv += 2; - for (i = 0; i < argc; i++) { - if (parse_u8(argv[i], &buf[i])) { - PR_ERROR(sh, "Argument %lu (%s) is not a byte.\n" - "Bytes shall be passed in decimal" - " notation.\n", - i + 1, argv[i]); - err = -EINVAL; - goto exit; - } - } - - if (!unaligned) { - err = do_write(sh, offset, buf, i, true); - } else { - err = do_write_unaligned(sh, offset, buf, i, true); - } - -exit: - return err; -} - -static int cmd_write(const struct shell *sh, size_t argc, char **argv) -{ - return cmd_write_template(sh, argc, argv, false); -} - -static int cmd_write_unaligned(const struct shell *sh, size_t argc, char **argv) -{ - return cmd_write_template(sh, argc, argv, true); -} - -static int cmd_write_pattern(const struct shell *sh, size_t argc, char **argv) -{ - int err = check_flash_device(sh); - unsigned long int offset, len, i; - static uint8_t *buf; - - if (err) { - goto exit; - } - - if (parse_ul(argv[1], &offset) || parse_ul(argv[2], &len)) { - PR_ERROR(sh, "Invalid arguments.\n"); - err = -EINVAL; - goto exit; - } - - buf = k_malloc(len); - - if (!buf) { - PR_ERROR(sh, "No heap memory for data pattern\n"); - err = -ENOMEM; - goto exit; - } - - for (i = 0; i < len; i++) { - buf[i] = i & 0xFF; - } - - err = do_write_unaligned(sh, offset, buf, i, true); - - k_free(buf); - -exit: - return err; -} - -#ifdef CONFIG_FLASH_PAGE_LAYOUT -static int cmd_page_count(const struct shell *sh, size_t argc, char **argv) -{ - ARG_UNUSED(argv); - ARG_UNUSED(argc); - - int err = check_flash_device(sh); - size_t page_count; - - if (!err) { - page_count = flash_get_page_count(flash_device); - PR_SHELL(sh, "Flash device contains %lu pages.\n", - (unsigned long int)page_count); - } - - return err; -} - -struct page_layout_data { - unsigned long int start_page; - unsigned long int end_page; - const struct shell *sh; -}; - -static bool page_layout_cb(const struct flash_pages_info *info, void *datav) -{ - struct page_layout_data *data = datav; - unsigned long int sz; - - if (info->index < data->start_page) { - return true; - } else if (info->index > data->end_page) { - return false; - } - - sz = info->size; - PR_SHELL(data->sh, - "\tPage %u: start 0x%08x, length 0x%lx (%lu, %lu KB)\n", - info->index, (uint32_t)info->start_offset, sz, sz, sz / KB(1)); - return true; -} - -static int cmd_page_layout(const struct shell *sh, size_t argc, char **argv) -{ - unsigned long int start_page, end_page; - struct page_layout_data data; - - int err = check_flash_device(sh); - - if (err) { - goto bail; - } - - switch (argc) { - case 1: - start_page = 0; - end_page = flash_get_page_count(flash_device) - 1; - break; - case 2: - if (parse_ul(argv[1], &start_page)) { - err = -EINVAL; - goto bail; - } - end_page = flash_get_page_count(flash_device) - 1; - break; - case 3: - if (parse_ul(argv[1], &start_page) || - parse_ul(argv[2], &end_page)) { - err = -EINVAL; - goto bail; - } - break; - default: - PR_ERROR(sh, "Invalid argument count.\n"); - return -EINVAL; - } - - data.start_page = start_page; - data.end_page = end_page; - data.sh = sh; - flash_page_foreach(flash_device, page_layout_cb, &data); - return 0; - -bail: - PR_ERROR(sh, "Invalid arguments.\n"); - return err; -} - -static int cmd_page_read(const struct shell *sh, size_t argc, char **argv) -{ - unsigned long int page, offset, len; - struct flash_pages_info info; - int ret; - - ret = check_flash_device(sh); - if (ret) { - return ret; - } - - if (argc == 3) { - if (parse_ul(argv[1], &page) || parse_ul(argv[2], &len)) { - ret = -EINVAL; - goto bail; - } - offset = 0; - } else if (parse_ul(argv[1], &page) || parse_ul(argv[2], &offset) || - parse_ul(argv[3], &len)) { - ret = -EINVAL; - goto bail; - } - - ret = flash_get_page_info_by_idx(flash_device, page, &info); - if (ret) { - PR_ERROR(sh, "Function flash_page_info_by_idx returned an" - " error: %d\n", ret); - return ret; - } - offset += info.start_offset; - ret = do_read(sh, offset, len, NULL); - return ret; - - bail: - PR_ERROR(sh, "Invalid arguments.\n"); - return ret; -} - -static int cmd_page_erase(const struct shell *sh, size_t argc, char **argv) -{ - struct flash_pages_info info; - unsigned long int i, page, num; - int ret; - - ret = check_flash_device(sh); - if (ret) { - return ret; - } - - if (parse_ul(argv[1], &page)) { - ret = -EINVAL; - goto bail; - } - if (argc == 2) { - num = 1; - } else if (parse_ul(argv[2], &num)) { - goto bail; - } - - for (i = 0; i < num; i++) { - ret = flash_get_page_info_by_idx(flash_device, page + i, &info); - if (ret) { - PR_ERROR(sh, "flash_get_page_info_by_idx error:" - " %d\n", ret); - return ret; - } - PR_SHELL(sh, "Erasing page %u (start offset 0x%x," - " size 0x%x)\n", - info.index, (uint32_t)info.start_offset, (uint32_t)info.size); - ret = do_erase(sh, info.start_offset, (uint32_t)info.size); - if (ret) { - return ret; - } - } - - return ret; - - bail: - PR_ERROR(sh, "Invalid arguments.\n"); - return ret; -} - -static int cmd_page_write(const struct shell *sh, size_t argc, char **argv) -{ - struct flash_pages_info info; - unsigned long int page, off; - uint8_t buf[ARGC_MAX]; - size_t i; - int ret; - - ret = check_flash_device(sh); - if (ret) { - return ret; - } - - if (parse_ul(argv[1], &page) || parse_ul(argv[2], &off)) { - ret = -EINVAL; - goto bail; - } - - argc -= 3; - argv += 3; - for (i = 0; i < argc; i++) { - if (parse_u8(argv[i], &buf[i])) { - PR_ERROR(sh, "Argument %d (%s) is not a byte.\n", - (int)i + 2, argv[i]); - ret = -EINVAL; - goto bail; - } - } - - ret = flash_get_page_info_by_idx(flash_device, page, &info); - if (ret) { - PR_ERROR(sh, "flash_get_page_info_by_idx: %d\n", ret); - return ret; - } - ret = do_write(sh, info.start_offset + off, buf, i, true); - return ret; - - bail: - PR_ERROR(sh, "Invalid arguments.\n"); - return ret; -} -#endif /* CONFIG_FLASH_PAGE_LAYOUT */ - -static int cmd_set_dev(const struct shell *sh, size_t argc, char **argv) -{ - const struct device *dev; - const char *name; - - name = argv[1]; - - /* Run command. */ - dev = device_get_binding(name); - if (!dev) { - PR_ERROR(sh, "No device named %s.\n", name); - return -ENOEXEC; - } - if (flash_device) { - PR_SHELL(sh, "Leaving behind device %s\n", - flash_device->name); - } - flash_device = dev; - - return 0; -} +#include int main(void) { - if (device_is_ready(flash_device)) { - printk("Found flash controller %s.\n", flash_device->name); - printk("Flash I/O commands can be run.\n"); - } else { - flash_device = NULL; - printk("**Flash controller not ready or not found!**\n"); - printk("Run set_device to specify one " - "before using other commands.\n"); - } + printf("Flash shell sample"); + return 0; } - - -SHELL_STATIC_SUBCMD_SET_CREATE(sub_flash, - /* Alphabetically sorted to ensure correct Tab autocompletion. */ - SHELL_CMD_ARG(erase, NULL, ERASE_HELP, cmd_erase, 3, 0), -#ifdef CONFIG_FLASH_PAGE_LAYOUT - SHELL_CMD_ARG(page_count, NULL, PAGE_COUNT_HELP, cmd_page_count, 1, 0), - SHELL_CMD_ARG(page_erase, NULL, PAGE_ERASE_HELP, cmd_page_erase, 2, 1), - SHELL_CMD_ARG(page_layout, NULL, PAGE_LAYOUT_HELP, - cmd_page_layout, 1, 2), - SHELL_CMD_ARG(page_read, NULL, PAGE_READ_HELP, cmd_page_read, 3, 1), - SHELL_CMD_ARG(page_write, NULL, PAGE_WRITE_HELP, - cmd_page_write, 3, 255), -#endif - SHELL_CMD_ARG(read, NULL, READ_HELP, cmd_read, 3, 0), - SHELL_CMD_ARG(set_device, NULL, SET_DEV_HELP, cmd_set_dev, 2, 0), - SHELL_CMD_ARG(write, NULL, WRITE_HELP, cmd_write, 3, 255), - SHELL_CMD_ARG(write_block_size, NULL, WRITE_BLOCK_SIZE_HELP, - cmd_write_block_size, 1, 0), - SHELL_CMD_ARG(write_unaligned, NULL, WRITE_UNALIGNED_HELP, - cmd_write_unaligned, 3, 255), - SHELL_CMD_ARG(write_pattern, NULL, WRITE_PATTERN_HELP, - cmd_write_pattern, 3, 255), - SHELL_SUBCMD_SET_END /* Array terminated. */ -); - -SHELL_CMD_REGISTER(flash_sample, &sub_flash, "Flash related commands.", NULL); diff --git a/samples/drivers/fpga/fpga_controller/README.rst b/samples/drivers/fpga/fpga_controller/README.rst index 82b4e68abcc..d971c138541 100644 --- a/samples/drivers/fpga/fpga_controller/README.rst +++ b/samples/drivers/fpga/fpga_controller/README.rst @@ -1,7 +1,7 @@ -.. _samples_fpga_controller: +.. zephyr:code-sample:: fpga-controller + :name: FPGA Controller -Zephyr FPGA controller -###################### + Load a bitstream into an FPGA and perform basic operations on it. Overview ******** diff --git a/samples/drivers/gnss/CMakeLists.txt b/samples/drivers/gnss/CMakeLists.txt new file mode 100644 index 00000000000..929f1b4da27 --- /dev/null +++ b/samples/drivers/gnss/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2023 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(gnss_sample) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/drivers/gnss/README.rst b/samples/drivers/gnss/README.rst new file mode 100644 index 00000000000..8d4749cd410 --- /dev/null +++ b/samples/drivers/gnss/README.rst @@ -0,0 +1,29 @@ +.. zephyr:code-sample:: gnss + :name: GNSS + :relevant-api: gnss_interface navigation + + Connect to a GNSS device to obtain time, navigation data, and satellite information. + +Overview +******** +This sample demonstrates how to use a GNSS device implementing the +GNSS device driver API. + +Requirements +************ + +This sample requires a board with a GNSS device present and enabled +in the devicetree. + +Sample Output +************* + +.. code-block:: console + + gnss: gnss_info: {satellites_cnt: 14, hdop: 0.850, fix_status: GNSS_FIX, fix_quality: GNSS_SPS} + gnss: navigation_data: {latitude: 57.162331699, longitude : 9.961104199, bearing 12.530, speed 0.25, altitude: 42.372} + gnss: gnss_time: {hour: 16, minute: 17, millisecond 36000, month_day 3, month: 10, century_year: 23} + gnss has fix! + gnss: gnss_satellite: {prn: 1, snr: 30, elevation 71, azimuth 276, system: GLONASS, is_tracked: 1} + gnss: gnss_satellite: {prn: 11, snr: 31, elevation 62, azimuth 221, system: GLONASS, is_tracked: 1} + gnss reported 2 satellites! diff --git a/samples/drivers/gnss/prj.conf b/samples/drivers/gnss/prj.conf new file mode 100644 index 00000000000..5ed72c140c2 --- /dev/null +++ b/samples/drivers/gnss/prj.conf @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_GNSS=y +CONFIG_GNSS_SATELLITES=y +CONFIG_LOG=y +CONFIG_LOG_BUFFER_SIZE=8192 +CONFIG_GNSS_DUMP_TO_LOG=y +CONFIG_GNSS_LOG_LEVEL_DBG=y diff --git a/samples/drivers/gnss/sample.yaml b/samples/drivers/gnss/sample.yaml new file mode 100644 index 00000000000..385a4ca0b67 --- /dev/null +++ b/samples/drivers/gnss/sample.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2023 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +sample: + name: GNSS sample +tests: + sample.drivers.gnss: + tags: + - drivers + - gnss + filter: dt_alias_exists("gnss") + depends_on: gnss diff --git a/samples/drivers/gnss/src/main.c b/samples/drivers/gnss/src/main.c new file mode 100644 index 00000000000..16b812f3f84 --- /dev/null +++ b/samples/drivers/gnss/src/main.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +static void gnss_data_cb(const struct device *dev, const struct gnss_data *data) +{ + if (data->info.fix_status != GNSS_FIX_STATUS_NO_FIX) { + printf("%s has fix!\r\n", dev->name); + } +} + +GNSS_DATA_CALLBACK_DEFINE(DEVICE_DT_GET(DT_ALIAS(gnss)), gnss_data_cb); + +#if CONFIG_GNSS_SATELLITES +static void gnss_satellites_cb(const struct device *dev, const struct gnss_satellite *satellites, + uint16_t size) +{ + printf("%s reported %u satellites!\r\n", dev->name, size); +} +#endif + +GNSS_SATELLITES_CALLBACK_DEFINE(DEVICE_DT_GET(DT_ALIAS(gnss)), gnss_satellites_cb); + +int main(void) +{ + return 0; +} diff --git a/samples/drivers/ht16k33/README.rst b/samples/drivers/ht16k33/README.rst index 01b899d5ff5..06fcc50a697 100644 --- a/samples/drivers/ht16k33/README.rst +++ b/samples/drivers/ht16k33/README.rst @@ -1,7 +1,8 @@ -.. _ht16k33: +.. zephyr:code-sample:: ht16k33 + :name: HT16K33 LED driver with keyscan + :relevant-api: led_interface kscan_interface -HT16K33 LED driver with keyscan -############################### + Control up to 128 LEDs connected to an HT16K33 LED driver and log keyscan events. Overview ******** @@ -23,7 +24,7 @@ Building and Running ******************** Build the application for the :ref:`nrf52840dk_nrf52840` board, and -connect a HT16K33 LED driver at address 0x70 on the I2C-0 bus. +connect an HT16K33 LED driver at address 0x70 on the I2C-0 bus. .. zephyr-app-commands:: :zephyr-app: samples/drivers/ht16k33 diff --git a/samples/drivers/i2s/echo/README.rst b/samples/drivers/i2s/echo/README.rst index 40dfecca1c4..8f7838d6298 100644 --- a/samples/drivers/i2s/echo/README.rst +++ b/samples/drivers/i2s/echo/README.rst @@ -1,7 +1,8 @@ -.. _i2s_echo_sample: +.. zephyr:code-sample:: i2s-echo + :name: I2S echo + :relevant-api: i2s_interface -I2S Echo Sample -############### + Process an audio stream to add an echo effect. Overview ******** diff --git a/samples/drivers/ipm/ipm_esp32/README.rst b/samples/drivers/ipm/ipm_esp32/README.rst index 6c1e793baf6..3219ee7b307 100644 --- a/samples/drivers/ipm/ipm_esp32/README.rst +++ b/samples/drivers/ipm/ipm_esp32/README.rst @@ -1,7 +1,8 @@ -.. _ipm_esp32: +.. zephyr:code-sample:: ipm-esp32 + :name: IPM on ESP32 + :relevant-api: ipm_interface -ESP32 Soft-IPM example -###################### + Implement inter-processor mailbox (IPM) between ESP32 APP and PRO CPUs. Overview ******** @@ -16,7 +17,7 @@ ESP32 intercore messaging has up two four channels, the 0 and 1 are reserved for BT and WIFI messages, and channels 2 and 3 is free to any application, each channel supports up to 64 bytes of data per message, so high level protocol is responsible to fragment larger -messages in chunks of 64bytes. +messages in chunks of 64 bytes. Building and Running the Zephyr Code ************************************ @@ -25,7 +26,7 @@ Build the ESP32 IPM sample code as follows: .. zephyr-app-commands:: :zephyr-app: samples/drivers/ipm/ipm_esp32 - :board: esp32 + :board: esp32_devkitc_wroom :goals: build :compact: diff --git a/samples/drivers/ipm/ipm_imx/README.rst b/samples/drivers/ipm/ipm_imx/README.rst index 3a356112d31..570f7115362 100644 --- a/samples/drivers/ipm/ipm_imx/README.rst +++ b/samples/drivers/ipm/ipm_imx/README.rst @@ -1,7 +1,8 @@ -.. _ipm_imx: +.. zephyr:code-sample:: ipm-imx + :name: IPM on NXP i.MX + :relevant-api: ipm_interface -i.MX IPM example -################ + Implement inter-processor mailbox (IPM) on i.MX SoCs containing a Messaging Unit peripheral. Overview ******** diff --git a/samples/drivers/ipm/ipm_ivshmem/README.rst b/samples/drivers/ipm/ipm_ivshmem/README.rst index 174fce788e7..80fe914d5da 100644 --- a/samples/drivers/ipm/ipm_ivshmem/README.rst +++ b/samples/drivers/ipm/ipm_ivshmem/README.rst @@ -1,5 +1,8 @@ -IPM over IVSHMEM Driver sample -################################ +.. zephyr:code-sample:: ipm-ivshmem + :name: IPM over IVSHMEM + :relevant-api: ipm_interface + + Implement inter-processor mailbox (IPM) over IVSHMEM (Inter-VM shared memory) Prerequisites ************* diff --git a/samples/drivers/ipm/ipm_mcux/README.rst b/samples/drivers/ipm/ipm_mcux/README.rst index d8dfcc65aea..1fcd1e9818e 100644 --- a/samples/drivers/ipm/ipm_mcux/README.rst +++ b/samples/drivers/ipm/ipm_mcux/README.rst @@ -1,7 +1,8 @@ -.. _ipm-mcux-sample: +.. zephyr:code-sample:: ipm-mcux + :name: IPM on NXP LPC + :relevant-api: ipm_interface -Sample mailbox application -########################## + Implement inter-processor mailbox (IPM) on NXP LPC family. Overview ******** diff --git a/samples/drivers/ipm/ipm_mhu_dual_core/README.rst b/samples/drivers/ipm/ipm_mhu_dual_core/README.rst index b6e212efd25..fc6414d83ff 100644 --- a/samples/drivers/ipm/ipm_mhu_dual_core/README.rst +++ b/samples/drivers/ipm/ipm_mhu_dual_core/README.rst @@ -1,7 +1,8 @@ -.. _ipm_mhu_dual_core: +.. zephyr:code-sample:: ipm-mhu-dual-core + :name: IPM with ARM MHU + :relevant-api: ipm_interface -MHU Dual Core -############# + Implement inter-processor mailbox (IPM) using an MHU (Message Handling Unit) Overview ******** diff --git a/samples/drivers/jesd216/README.rst b/samples/drivers/jesd216/README.rst index 8aaa07a8283..71887480a58 100644 --- a/samples/drivers/jesd216/README.rst +++ b/samples/drivers/jesd216/README.rst @@ -1,7 +1,8 @@ -.. _jesd216-sample: +.. zephyr:code-sample:: jesd216 + :name: JESD216 flash + :relevant-api: flash_interface -JESD216 Sample -############## + Use the JESD216 flash API to extract information from a compatible serial memory device. Overview ******** diff --git a/samples/drivers/jesd216/boards/b_l4s5i_iot01a.conf b/samples/drivers/jesd216/boards/b_l4s5i_iot01a.conf deleted file mode 100644 index 6e3cf258b12..00000000000 --- a/samples/drivers/jesd216/boards/b_l4s5i_iot01a.conf +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright (c) 2022 STMicroelectronics -# -# SPDX-License-Identifier: Apache-2.0 - -CONFIG_FLASH_STM32_OSPI=y -CONFIG_SPI_NOR_SFDP_RUNTIME=y -CONFIG_SPI_NOR=n diff --git a/samples/drivers/jesd216/boards/b_u585i_iot02a.conf b/samples/drivers/jesd216/boards/b_u585i_iot02a.conf deleted file mode 100644 index 6e3cf258b12..00000000000 --- a/samples/drivers/jesd216/boards/b_u585i_iot02a.conf +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright (c) 2022 STMicroelectronics -# -# SPDX-License-Identifier: Apache-2.0 - -CONFIG_FLASH_STM32_OSPI=y -CONFIG_SPI_NOR_SFDP_RUNTIME=y -CONFIG_SPI_NOR=n diff --git a/samples/drivers/jesd216/boards/disco_l475_iot1.conf b/samples/drivers/jesd216/boards/disco_l475_iot1.conf deleted file mode 100644 index dbb7255d188..00000000000 --- a/samples/drivers/jesd216/boards/disco_l475_iot1.conf +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_FLASH_STM32_QSPI=y -CONFIG_SPI_NOR_SFDP_RUNTIME=y -CONFIG_SPI_NOR=n diff --git a/samples/drivers/jesd216/boards/stm32h573i_dk.conf b/samples/drivers/jesd216/boards/stm32h573i_dk.conf deleted file mode 100644 index 4dd3e9965c4..00000000000 --- a/samples/drivers/jesd216/boards/stm32h573i_dk.conf +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright (c) 2023 STMicroelectronics -# -# SPDX-License-Identifier: Apache-2.0 - -CONFIG_FLASH_STM32_OSPI=y -CONFIG_SPI_NOR_SFDP_RUNTIME=y -CONFIG_SPI_NOR=n diff --git a/samples/drivers/jesd216/boards/stm32h735g_disco.conf b/samples/drivers/jesd216/boards/stm32h735g_disco.conf deleted file mode 100644 index 6e3cf258b12..00000000000 --- a/samples/drivers/jesd216/boards/stm32h735g_disco.conf +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright (c) 2022 STMicroelectronics -# -# SPDX-License-Identifier: Apache-2.0 - -CONFIG_FLASH_STM32_OSPI=y -CONFIG_SPI_NOR_SFDP_RUNTIME=y -CONFIG_SPI_NOR=n diff --git a/samples/drivers/jesd216/boards/stm32h747i_disco_m7.conf b/samples/drivers/jesd216/boards/stm32h747i_disco_m7.conf deleted file mode 100644 index dbb7255d188..00000000000 --- a/samples/drivers/jesd216/boards/stm32h747i_disco_m7.conf +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_FLASH_STM32_QSPI=y -CONFIG_SPI_NOR_SFDP_RUNTIME=y -CONFIG_SPI_NOR=n diff --git a/samples/drivers/jesd216/boards/stm32l496g_disco.conf b/samples/drivers/jesd216/boards/stm32l496g_disco.conf deleted file mode 100644 index dbb7255d188..00000000000 --- a/samples/drivers/jesd216/boards/stm32l496g_disco.conf +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_FLASH_STM32_QSPI=y -CONFIG_SPI_NOR_SFDP_RUNTIME=y -CONFIG_SPI_NOR=n diff --git a/samples/drivers/jesd216/boards/stm32l562e_dk.conf b/samples/drivers/jesd216/boards/stm32l562e_dk.conf deleted file mode 100644 index 6e3cf258b12..00000000000 --- a/samples/drivers/jesd216/boards/stm32l562e_dk.conf +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright (c) 2022 STMicroelectronics -# -# SPDX-License-Identifier: Apache-2.0 - -CONFIG_FLASH_STM32_OSPI=y -CONFIG_SPI_NOR_SFDP_RUNTIME=y -CONFIG_SPI_NOR=n diff --git a/samples/drivers/jesd216/sample.yaml b/samples/drivers/jesd216/sample.yaml index af84cbc791e..c50ce41d0f3 100644 --- a/samples/drivers/jesd216/sample.yaml +++ b/samples/drivers/jesd216/sample.yaml @@ -28,3 +28,6 @@ tests: platform_allow: nrf52840dk_nrf52840 integration_platforms: - nrf52840dk_nrf52840 + sample.drivers.stm32.jesd216: + filter: dt_compat_enabled("st,stm32-ospi-nor") or dt_compat_enabled("st,stm32-qspi-nor") + depends_on: spi diff --git a/samples/drivers/kscan/README.rst b/samples/drivers/kscan/README.rst index 2bbf5b04ad5..e2d2d129b6b 100644 --- a/samples/drivers/kscan/README.rst +++ b/samples/drivers/kscan/README.rst @@ -1,7 +1,8 @@ -.. _kscan-sample: +.. zephyr:code-sample:: kscan + :name: KSCAN + :relevant-api: kscan_interface timer_apis -KSCAN Interface -#################################### + Use the KSCAN API to read key presses and releases on a keyboard matrix. Overview ******** diff --git a/samples/drivers/kscan_touch/CMakeLists.txt b/samples/drivers/kscan_touch/CMakeLists.txt deleted file mode 100644 index 1c5812ccffb..00000000000 --- a/samples/drivers/kscan_touch/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(kscan) - -FILE(GLOB app_sources src/*.c) -target_sources(app PRIVATE ${app_sources}) diff --git a/samples/drivers/kscan_touch/README.rst b/samples/drivers/kscan_touch/README.rst deleted file mode 100644 index 80fb2f273cd..00000000000 --- a/samples/drivers/kscan_touch/README.rst +++ /dev/null @@ -1,26 +0,0 @@ -.. _kscan-touch-sample: - -KSCAN touch panel example -#################################### - -Overview -******** - -This sample demonstrates how to interface with a touch panel. When touches are -detected a log message is output on the console. - -Building and Running -******************** - -The sample can be built and executed on boards with a touch panel for example -stm32f746g_disco or mimxrt1060_evk. The boards dts file should contain an alias -to kscan0 - -Sample output -============= - -.. code-block:: console - - KSCAN test for touch panels. - Note: You are expected to see several callbacks - as you touch the screen. diff --git a/samples/drivers/kscan_touch/prj.conf b/samples/drivers/kscan_touch/prj.conf deleted file mode 100644 index b25816644e9..00000000000 --- a/samples/drivers/kscan_touch/prj.conf +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_STDOUT_CONSOLE=y -CONFIG_PRINTK=y -CONFIG_KSCAN=y diff --git a/samples/drivers/kscan_touch/sample.yaml b/samples/drivers/kscan_touch/sample.yaml deleted file mode 100644 index b555e9f9901..00000000000 --- a/samples/drivers/kscan_touch/sample.yaml +++ /dev/null @@ -1,14 +0,0 @@ -sample: - name: KSCAN touch driver api sample -tests: - sample.drivers.kscan_touch: - tags: - - drivers - - kscan_touch - harness: console - harness_config: - type: multi_line - ordered: true - regex: - - "kb data(.*)" - depends_on: kscan:touch diff --git a/samples/drivers/kscan_touch/src/main.c b/samples/drivers/kscan_touch/src/main.c deleted file mode 100644 index cfec920f732..00000000000 --- a/samples/drivers/kscan_touch/src/main.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2020 Mark Olsson - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include - -#define LOG_LEVEL LOG_LEVEL_DBG -#include - -LOG_MODULE_REGISTER(main); - -const struct device *const kscan_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_keyboard_scan)); - -static void k_callback(const struct device *dev, uint32_t row, uint32_t col, - bool pressed) -{ - ARG_UNUSED(dev); - if (pressed) { - printk("row = %u col = %u\n", row, col); - } -} - -int main(void) -{ - printk("Kscan touch panel sample application\n"); - - if (!device_is_ready(kscan_dev)) { - LOG_ERR("kscan device %s not ready", kscan_dev->name); - return 0; - } - - kscan_config(kscan_dev, k_callback); - kscan_enable_callback(kscan_dev); - return 0; -} diff --git a/samples/drivers/lcd_hd44780/README.rst b/samples/drivers/lcd_hd44780/README.rst index 44b27251e9c..c4d729ca6df 100644 --- a/samples/drivers/lcd_hd44780/README.rst +++ b/samples/drivers/lcd_hd44780/README.rst @@ -1,7 +1,8 @@ -.. _samples_lcd_hd44780: +.. zephyr:code-sample:: lcd-hd44780 + :name: HD44780 LCD controller + :relevant-api: gpio_interface -LCD HD44780 driver sample -######################### + Control an HD44780-based LCD display using GPIO pins. Overview ******** diff --git a/samples/drivers/led_apa102/README.rst b/samples/drivers/led_apa102/README.rst index 9def8376dcc..2ea03328238 100644 --- a/samples/drivers/led_apa102/README.rst +++ b/samples/drivers/led_apa102/README.rst @@ -1,7 +1,8 @@ -.. _led_apa102_sample: +.. zephyr:code-sample:: led-apa102 + :name: APA102 LED strip + :relevant-api: led_strip_interface -APA102 Sample Application -######################### + Control an LED strip using an APA102, Adafruit DotStar, or compatible driver chip. Overview ******** diff --git a/samples/drivers/led_is31fl3216a/README.rst b/samples/drivers/led_is31fl3216a/README.rst index fb3c2353dd5..fa527d09579 100644 --- a/samples/drivers/led_is31fl3216a/README.rst +++ b/samples/drivers/led_is31fl3216a/README.rst @@ -1,7 +1,8 @@ -.. _is31fl3216a: +.. zephyr:code-sample:: is31fl3216a + :name: IS31FL3216A LED + :relevant-api: led_interface -is31fl3216a: 16 channels PWD LEDs controller -############################################ + Control up to 16 PWM LEDs connected to an IS31FL3216A driver chip. Overview ******** @@ -12,12 +13,13 @@ Each LED is gradually pulsed until it reach 100% of luminosity and gradually turned off again. Once each LED was pulsed, multiple LEDs are pulse simultaneously using the -``write_channels`` LED API. +:c:func:`led_write_channels` API. Test pattern ============ For each LED: + - Increase the luminosity until 100% is reached - Decrease the luminosity until completely turned off diff --git a/samples/drivers/led_is31fl3733/README.rst b/samples/drivers/led_is31fl3733/README.rst index 0894c7ef9e8..8f0f30e61cf 100644 --- a/samples/drivers/led_is31fl3733/README.rst +++ b/samples/drivers/led_is31fl3733/README.rst @@ -1,7 +1,8 @@ -.. _is31fl3733: +.. zephyr:code-sample:: is31fl3733 + :name: IS31FL3733 LED Matrix + :relevant-api: led_interface -IS31FL3733 LED Matrix Driver Demo Application -############################################# + Control a matrix of up to 192 LEDs connected to an IS31FL3733 driver chip. Overview ******** @@ -9,19 +10,20 @@ Overview This sample controls a matrix of up to 192 LEDs. The sample performs the following test steps in an infinite loop: -- Set all LEDs to full brightness with `led_write_channels` API -- Disable upper quadrant of LED array with `led_write_channels` API -- Dim each LED in sequence using `led_set_brightness` API -- Toggle each LED in sequency using `led_on` and `led_off` APIs -- Toggle between low or high current limit using `is31fl3733_current_limit` +- Set all LEDs to full brightness with :c:func:`led_write_channels` API +- Disable upper quadrant of LED array with :c:func:`led_write_channels` API +- Dim each LED in sequence using :c:func:`led_set_brightness` API +- Toggle each LED in sequency using :c:func:`led_on` and :c:func:`led_of` APIs +- Toggle between low or high current limit using :c:func:`is31fl3733_current_limit` API, and repeat the above tests Sample Configuration ==================== The number of LEDs can be limited using the following sample specific Kconfigs: -- `CONFIG_LED_ROW_COUNT` -- `CONFIG_LED_COLUMN_COUNT` + +- :kconfig:option:`CONFIG_LED_ROW_COUNT` +- :kconfig:option:`CONFIG_LED_COLUMN_COUNT` Building and Running ******************** diff --git a/samples/drivers/led_lp3943/README.rst b/samples/drivers/led_lp3943/README.rst index c092a9dfdf0..cb1905d2c14 100644 --- a/samples/drivers/led_lp3943/README.rst +++ b/samples/drivers/led_lp3943/README.rst @@ -1,7 +1,8 @@ -.. _lp3943: +.. zephyr:code-sample:: lp3943 + :name: LP3943 RGBW LED + :relevant-api: led_interface -LP3943: 16-Channel RGB, White-LED Driver -######################################## + Control up to 16 RGBW LEDs connected to an LP3943 driver chip. Overview ******** diff --git a/samples/drivers/led_lp50xx/README.rst b/samples/drivers/led_lp50xx/README.rst index afad1ee0ea5..23d4fcaa3ff 100644 --- a/samples/drivers/led_lp50xx/README.rst +++ b/samples/drivers/led_lp50xx/README.rst @@ -1,7 +1,8 @@ -.. _lp50xx: +.. zephyr:code-sample:: lp50xx + :name: LP50XX RGB LED + :relevant-api: led_interface -LP50XX: up to 12 RGB channels -############################### + Control up to 12 RGB LEDs connected to an LP50xx driver chip. Overview ******** @@ -11,8 +12,8 @@ This sample controls up to 12 LEDs connected to a LP50xx driver. First, for each LED information is retrieved using the led_get_info syscall and printed in the log messages. Next, from an infinite loop, a test pattern (described below) is applied to all the LEDs simultaneously (using the -led_write_channels syscall) and then to each LED one by one (using the -led_set_{brightness,color} syscalls). +:c:func:`led_write_channels` syscall) and then to each LED one by one (using the +:c:func:`led_set_brightness` and :c:func:`led_set_color` syscalls). Test pattern ============ diff --git a/samples/drivers/led_lp5562/README.rst b/samples/drivers/led_lp5562/README.rst index 9f141507612..4848455ab32 100644 --- a/samples/drivers/led_lp5562/README.rst +++ b/samples/drivers/led_lp5562/README.rst @@ -1,7 +1,8 @@ -.. _lp5562: +.. zephyr:code-sample:: lp5562 + :name: LP5562 RGB LED + :relevant-api: led_interface -LP5562: 4-Channel RGB -###################### + Control 4 RGB LEDs connected to an LP5562 driver chip. Overview ******** diff --git a/samples/drivers/led_lp5569/README.rst b/samples/drivers/led_lp5569/README.rst index c7679972f1d..f9d0f5febd9 100644 --- a/samples/drivers/led_lp5569/README.rst +++ b/samples/drivers/led_lp5569/README.rst @@ -1,7 +1,8 @@ -.. _lp5569: +.. zephyr:code-sample:: lp5569 + :name: LP5569 9-channel LED controller + :relevant-api: led_interface -LP5569: 9-Channel LED Controller -################################ + Control 9 LEDs connected to an LP5569 driver chip. Overview ******** diff --git a/samples/drivers/led_lpd8806/README.rst b/samples/drivers/led_lpd8806/README.rst index 095638c74ad..570f6498fc7 100644 --- a/samples/drivers/led_lpd8806/README.rst +++ b/samples/drivers/led_lpd8806/README.rst @@ -1,7 +1,8 @@ -.. _led_lpd8806_sample: +.. zephyr:code-sample:: led-lpd8806 + :name: LPD880x LED strip + :relevant-api: led_strip_interface -LPD880x Sample Application -########################## + Control an LED strip using an LPD880x-compatible driver chip. Overview ******** diff --git a/samples/drivers/led_pca9633/README.rst b/samples/drivers/led_pca9633/README.rst index 32e5ed14db9..ac461961e03 100644 --- a/samples/drivers/led_pca9633/README.rst +++ b/samples/drivers/led_pca9633/README.rst @@ -1,7 +1,8 @@ -.. _pca9633: +.. zephyr:code-sample:: pca9633 + :name: PCA9633 LED + :relevant-api: led_interface -PCA9633: 4-Channel RGB -###################### + Control 4 LEDs connected to a PCA9633 driver chip. Overview ******** diff --git a/samples/drivers/led_pwm/README.rst b/samples/drivers/led_pwm/README.rst index 54ae34f4d64..62e830fcae1 100644 --- a/samples/drivers/led_pwm/README.rst +++ b/samples/drivers/led_pwm/README.rst @@ -1,7 +1,8 @@ -.. _led_pwm: +.. zephyr:code-sample:: led-pwm + :name: LED PWM + :relevant-api: led_interface -LED PWM sample application -########################## + Control PWM LEDs using the LED API. Overview ******** diff --git a/samples/drivers/led_pwm/boards/mr_canhubk3.conf b/samples/drivers/led_pwm/boards/mr_canhubk3.conf new file mode 100644 index 00000000000..e42e5613d05 --- /dev/null +++ b/samples/drivers/led_pwm/boards/mr_canhubk3.conf @@ -0,0 +1,6 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +# Due to gpio-leds and pwm-leds are the same RGB LEDs so should not be used +# at the same time, need to disable this config when using pwm-leds. +CONFIG_LED_GPIO=n diff --git a/samples/drivers/led_sx1509b_intensity/README.rst b/samples/drivers/led_sx1509b_intensity/README.rst index ce715fab878..2fdeee737ac 100644 --- a/samples/drivers/led_sx1509b_intensity/README.rst +++ b/samples/drivers/led_sx1509b_intensity/README.rst @@ -1,7 +1,8 @@ -.. _sx1509b_intensity: +.. zephyr:code-sample:: sx1509b + :name: SX1509B RGB LED + :relevant-api: led_interface -SX1509B LED Intensity -###################### + Control an RGB LED connected to an SX1509B driver chip. Overview ******** diff --git a/samples/drivers/led_ws2812/Kconfig b/samples/drivers/led_ws2812/Kconfig index f5cfbc2cf73..2b60e294b7a 100644 --- a/samples/drivers/led_ws2812/Kconfig +++ b/samples/drivers/led_ws2812/Kconfig @@ -6,4 +6,14 @@ config SPI default y +menu "WS2812 Sample Configuration" + +config SAMPLE_LED_UPDATE_DELAY + int "Delay between LED updates in ms" + default 50 + help + Delay between LED updates in ms. + +endmenu + source "Kconfig.zephyr" diff --git a/samples/drivers/led_ws2812/README.rst b/samples/drivers/led_ws2812/README.rst index 4d07c825bf3..183875520f2 100644 --- a/samples/drivers/led_ws2812/README.rst +++ b/samples/drivers/led_ws2812/README.rst @@ -1,7 +1,8 @@ -.. _led_ws2812_sample: +.. zephyr:code-sample:: led-ws2812 + :name: WS2812 LED strip + :relevant-api: led_strip_interface -WS2812 Sample Application -######################### + Control an LED strip using a WS2812 (or compatible) driver chip. Overview ******** @@ -73,6 +74,9 @@ For example devicetree configurations for each compatible, see Some boards are already supported out of the box; see the :file:`boards` directory for this sample for details. +The sample updates the LED strip periodically. The update frequency can be +modified by changing the :kconfig:option:`CONFIG_SAMPLE_LED_UPDATE_DELAY`. + Then build and flash the application: .. zephyr-app-commands:: @@ -96,9 +100,13 @@ Supported drivers This sample uses different drivers depending on the selected board: I2S driver: + - thingy52_nrf52832 +- nrf5340dk_nrf5340 (3.3V logic level, a logic level shifter may be required) + - should work for other boards featuring an nRF5340 host processor SPI driver: + - mimxrt1050_evk - mimxrt1050_evk_qspi - nrf52dk_nrf52832 @@ -108,6 +116,7 @@ SPI driver: - nucleo_l476rg GPIO driver (cortex-M0 only): + - bbc_microbit - nrf51dk_nrf51422 diff --git a/samples/drivers/led_ws2812/boards/nrf5340dk_nrf5340.conf b/samples/drivers/led_ws2812/boards/nrf5340dk_nrf5340.conf new file mode 100644 index 00000000000..f5d64aaf5da --- /dev/null +++ b/samples/drivers/led_ws2812/boards/nrf5340dk_nrf5340.conf @@ -0,0 +1,5 @@ +CONFIG_SPI=n + +CONFIG_I2S=y +CONFIG_WS2812_STRIP=y +CONFIG_WS2812_STRIP_I2S=y diff --git a/samples/drivers/led_ws2812/boards/nrf5340dk_nrf5340.overlay b/samples/drivers/led_ws2812/boards/nrf5340dk_nrf5340.overlay new file mode 100644 index 00000000000..738e7911532 --- /dev/null +++ b/samples/drivers/led_ws2812/boards/nrf5340dk_nrf5340.overlay @@ -0,0 +1,36 @@ +#include + +&pinctrl { + i2s0_default_alt: i2s0_default_alt { + group1 { + /* Default I2S config for the nRF5340, P1.13 is the output */ + psels = , + , + , + ; + }; + }; +}; + +i2s_led: &i2s0 { + status = "okay"; + pinctrl-0 = <&i2s0_default_alt>; + pinctrl-names = "default"; +}; + +/ { + led_strip: ws2812 { + compatible = "worldsemi,ws2812-i2s"; + + i2s-dev = <&i2s_led>; + chain-length = <42>; /* arbitrary; change at will */ + color-mapping = ; + reset-delay = <500>; + }; + + aliases { + led-strip = &led_strip; + }; +}; diff --git a/samples/drivers/led_ws2812/src/main.c b/samples/drivers/led_ws2812/src/main.c index ee7672b38c3..d26fe6a7e91 100644 --- a/samples/drivers/led_ws2812/src/main.c +++ b/samples/drivers/led_ws2812/src/main.c @@ -21,7 +21,7 @@ LOG_MODULE_REGISTER(main); #define STRIP_NODE DT_ALIAS(led_strip) #define STRIP_NUM_PIXELS DT_PROP(DT_ALIAS(led_strip), chain_length) -#define DELAY_TIME K_MSEC(50) +#define DELAY_TIME K_MSEC(CONFIG_SAMPLE_LED_UPDATE_DELAY) #define RGB(_r, _g, _b) { .r = (_r), .g = (_g), .b = (_b) } diff --git a/samples/drivers/led_xec/README.rst b/samples/drivers/led_xec/README.rst index 883126640d3..12c951c7ad3 100644 --- a/samples/drivers/led_xec/README.rst +++ b/samples/drivers/led_xec/README.rst @@ -1,7 +1,8 @@ -.. _led: +.. zephyr:code-sample:: led-xec + :name: Breathing-blinking LED (BBLED) + :relevant-api: led_interface -LED sample application -########################## + Control a BBLED (Breathing-Blinking LED) using Microchip XEC driver. Overview ******** @@ -9,12 +10,16 @@ Overview This sample allows to test the Microchip led-xec driver which uses the breathing-blinking LED (BBLED) controllers. The SoC design is fixed allowing each BBLED control over one specific GPIO. + MEC15xx and MEC172x: -BBLED controller 0 uses GPIO 0156. -BBLED controller 1 uses GPIO 0157. -BBLED controller 2 uses GPIO 0153. -MEC172x has a fourth instance of BBLED. -BBLED controller 3 uses GPIO 0035 + +- BBLED controller 0 uses GPIO 0156. +- BBLED controller 1 uses GPIO 0157. +- BBLED controller 2 uses GPIO 0153. + +MEC172x has a fourth instance of BBLED: + +- BBLED controller 3 uses GPIO 0035 Test pattern ============ @@ -27,44 +32,50 @@ For each LEDs (one after the other): - Blinking on: 1 sec, off: 1 sec Board Jumpers -******************** +************* + +mec172xevb_assy6906 evaluation board +==================================== + +- BBLED0: GPIO 0156. + - Connect GPIO 0156 to board LED4 by placing a wire from JP71-11 to J47-3. + - Make sure there are no jumpers on JP54 1-2 and JP21 4-5 + +- BBLED1: GPIO 0157. + - Connect GPIO 0156 to board LED5 by placing a wire from JP71-12 to J48-3. + - Make sure there are no jumpers on JP54 3-4 and JP21 16-17 + +- BBLED2: GPIO 0153. + - Connect GPIO 0153 to board LED7 by placing a wire from JP71-5 to JP146-5. + + JP146-5 is connected to MEC172x VCI_OUT1 without a jumper. Force VCI_OUT1 + high by forcing VCI_IN1 high: install jumper on J55 3-4 which pulls VCI_IN1 + to the VBAT rail via a 100K pull-up. Requires VBAT power rail is connected + to VTR or some other power source. + +- BBLED3: GPIO 0035. + - Connect GPIO 0035 to board LED7 by placing a wire from JP67-19 to JP146-1. + - Make sure there is no jumper on JP79 17-18. + + JP146-1 is connected to MEC172x VCI_OUT2 without a jumper. Force VCI_OUT2 + high by forcing VCI_IN2 high: install a jumper on J55 5-6 which pulls VCI_IN2 + to the VBAT rail via a 100K pull-up. Requires VBAT power rail is connected + to VTR or some other power source. + +mec15xxevb_assy6853 evaluation board +==================================== + +- BBLED0: GPIO 0156. + - Add jumper on JP41 1-2 to connect GPIO 0156 to board LED2 + - Remove jumper on JP31 13-14 + +- BBLED1: GPIO 0157. + - Add jumper on JP41 3-4 to connect GPIO 0157 to board LED3 + - Remove jumper on JP31 15-16 -EVB: mec172xevb_assy6906 -BBLED0 GPIO 0156. -Connect GPIO 0156 to board LED4 by placing a wire from JP71-11 to J47-3. -Make sure there are no jumpers on JP54 1-2 and JP21 4-5 - -BBLED1 GPIO 0157. -Connect GPIO 0156 to board LED5 by placing a wire from JP71-12 to J48-3. -Make sure there are no jumpers on JP54 3-4 and JP21 16-17 - -BBLED2 GPIO 0153. -Connect GPIO 0153 to board LED7 by placing a wire from JP71-5 to JP146-5. -JP146-5 is connected to MEC172x VCI_OUT1 without a jumper. Force VCI_OUT1 -high by forcing VCI_IN1 high: install jumper on J55 3-4 which pulls VCI_IN1 -to the VBAT rail via a 100K pull-up. Requires VBAT power rail is connected -to VTR or some other power source. - -BBLED3 GPIO 0035. -Connect GPIO 0035 to board LED7 by placing a wire from JP67-19 to JP146-1. -Make sure there is no jumper on JP79 17-18. -JP146-1 is connected to MEC172x VCI_OUT2 without a jumper. Force VCI_OUT2 -high by forcing VCI_IN2 high: install a jumper on J55 5-6 which pulls VCI_IN2 -to the VBAT rail via a 100K pull-up. Requires VBAT power rail is connected -to VTR or some other power source. - -EVB: mec15xxevb_assy6853 -BBLED0 GPIO 0156. -Add jumper on JP41 1-2 to connect GPIO 0156 to board LED2 -Remove jumper on JP31 13-14 - -BBLED1 GPIO 0157. -Add jumper on JP41 3-4 to connect GPIO 0157 to board LED3 -Remove jumper on JP31 15-16 - -BBLED2 GPIO 0153. -Add jumper on JP41 3-4 to connect GPIO 0153 to board LED4 -Remove jumper on JP31 17-18 +- BBLED2: GPIO 0153. + - Add jumper on JP41 3-4 to connect GPIO 0153 to board LED4 + - Remove jumper on JP31 17-18 Building and Running ******************** diff --git a/samples/drivers/lora/receive/README.rst b/samples/drivers/lora/receive/README.rst new file mode 100644 index 00000000000..8d08a5445ef --- /dev/null +++ b/samples/drivers/lora/receive/README.rst @@ -0,0 +1,55 @@ +.. zephyr:code-sample:: lora-receive + :name: LoRa receive + :relevant-api: lora_api + + Receive packets in both synchronous and asynchronous mode using the LoRa + radio. + +Overview +******** + +This sample demonstrates how to use the LoRa radio driver to receive packets +both synchronously and asynchronously. + +In order to successfully receive messages, build and flash the accompanying +LoRa send sample :zephyr:code-sample:`lora-send` on another board within range. + +As this sample receives a finite number of packets and then sleeps infinitely, +the user must be ready to inspect the console output immediately after +resetting the device. + +Building and Running +******************** + +Build and flash the sample as follows, changing ``b_l072z_lrwan1`` for +your board, where your board has a ``lora0`` alias in the devicetree. + +.. zephyr-app-commands:: + :zephyr-app: zephyr/samples/drivers/lora/receive + :host-os: unix + :board: b_l072z_lrwan1 + :goals: build flash + :compact: + +Sample Output +============= + +.. code-block:: console + + [00:00:00.235,000] lora_receive: Synchronous reception + [00:00:00.956,000] lora_receive: Received data: helloworld (RSSI:-60dBm, SNR:7dBm) + [00:00:02.249,000] lora_receive: Received data: helloworld (RSSI:-57dBm, SNR:9dBm) + [00:00:03.541,000] lora_receive: Received data: helloworld (RSSI:-57dBm, SNR:9dBm) + [00:00:04.834,000] lora_receive: Received data: helloworld (RSSI:-55dBm, SNR:9dBm) + [00:00:04.834,000] lora_receive: Asynchronous reception + [00:00:06.127,000] lora_receive: Received data: helloworld (RSSI:-55dBm, SNR:9dBm) + [00:00:07.419,000] lora_receive: Received data: helloworld (RSSI:-55dBm, SNR:9dBm) + [00:00:08.712,000] lora_receive: Received data: helloworld (RSSI:-55dBm, SNR:9dBm) + [00:00:10.004,000] lora_receive: Received data: helloworld (RSSI:-55dBm, SNR:9dBm) + [00:00:11.297,000] lora_receive: Received data: helloworld (RSSI:-55dBm, SNR:9dBm) + [00:00:12.590,000] lora_receive: Received data: helloworld (RSSI:-55dBm, SNR:9dBm) + [00:00:13.884,000] lora_receive: Received data: helloworld (RSSI:-55dBm, SNR:9dBm) + [00:00:15.177,000] lora_receive: Received data: helloworld (RSSI:-55dBm, SNR:9dBm) + [00:00:16.470,000] lora_receive: Received data: helloworld (RSSI:-55dBm, SNR:9dBm) + [00:00:17.762,000] lora_receive: Received data: helloworld (RSSI:-55dBm, SNR:9dBm) + [00:00:17.762,000] lora_receive: Stopping packet receptions diff --git a/samples/drivers/lora/send/README.rst b/samples/drivers/lora/send/README.rst new file mode 100644 index 00000000000..f2b46bcc917 --- /dev/null +++ b/samples/drivers/lora/send/README.rst @@ -0,0 +1,37 @@ +.. zephyr:code-sample:: lora-send + :name: LoRa send + :relevant-api: lora_api + + Transmit a preconfigured payload every second using the LoRa radio. + +Overview +******** + +This sample demonstrates how to use the LoRa radio driver to configure +the encoding settings and send data over the radio. + +Transmitted messages can be received by building and flashing the accompanying +LoRa receive sample :zephyr:code-sample:`lora-receive` on another board within +range. + +Building and Running +******************** + +Build and flash the sample as follows, changing ``b_l072z_lrwan1`` for +your board, where your board has a ``lora0`` alias in the devicetree. + +.. zephyr-app-commands:: + :zephyr-app: zephyr/samples/drivers/lora/send + :host-os: unix + :board: b_l072z_lrwan1 + :goals: build flash + :compact: + +Sample Output +============= + +.. code-block:: console + + [00:00:00.531,000] lora_send: Data sent! + [00:00:01.828,000] lora_send: Data sent! + [00:00:03.125,000] lora_send: Data sent! diff --git a/samples/drivers/mbox/CMakeLists.txt b/samples/drivers/mbox/CMakeLists.txt index dd7ab115570..e65d44f0048 100644 --- a/samples/drivers/mbox/CMakeLists.txt +++ b/samples/drivers/mbox/CMakeLists.txt @@ -6,33 +6,19 @@ cmake_minimum_required(VERSION 3.20.0) -set(REMOTE_ZEPHYR_DIR ${CMAKE_CURRENT_BINARY_DIR}/mbox_ipc_remote-prefix/src/mbox_ipc_remote-build/zephyr) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -if("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpuapp") - set(BOARD_REMOTE "nrf5340dk_nrf5340_cpunet") -elseif("${BOARD}" STREQUAL "adp_xc7k_ae350") - set(BOARD_REMOTE "adp_xc7k_ae350") +if(("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpuapp") OR + ("${BOARD}" STREQUAL "nrf5340bsim_nrf5340_cpuapp") OR + ("${BOARD}" STREQUAL "adp_xc7k_ae350") OR + ("${BOARD}" STREQUAL "mimxrt595_evk_cm33")) + message(STATUS "${BOARD} compile as Main in this sample") else() message(FATAL_ERROR "${BOARD} is not supported for this sample") endif() -message(STATUS "${BOARD} compile as Main in this sample") - -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(mbox_ipc) enable_language(C ASM) target_sources(app PRIVATE src/main.c) - -include(ExternalProject) - -ExternalProject_Add( - mbox_ipc_remote - SOURCE_DIR ${APPLICATION_SOURCE_DIR}/remote - INSTALL_COMMAND "" # This particular build system has no install command - CMAKE_CACHE_ARGS -DBOARD:STRING=${BOARD_REMOTE} - BUILD_BYPRODUCTS "${REMOTE_ZEPHYR_DIR}/${KERNEL_BIN_NAME}" - # NB: Do we need to pass on more CMake variables? - BUILD_ALWAYS True -) diff --git a/samples/drivers/mbox/Kconfig.sysbuild b/samples/drivers/mbox/Kconfig.sysbuild new file mode 100644 index 00000000000..46ffe3e12ae --- /dev/null +++ b/samples/drivers/mbox/Kconfig.sysbuild @@ -0,0 +1,12 @@ +# Copyright 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config REMOTE_BOARD +string + default "nrf5340dk_nrf5340_cpunet" if $(BOARD) = "nrf5340dk_nrf5340_cpuapp" + default "nrf5340bsim_nrf5340_cpunet" if $(BOARD) = "nrf5340bsim_nrf5340_cpuapp" + default "adp_xc7k_ae350" if $(BOARD) = "adp_xc7k_ae350" + default "nrf5340dk_nrf5340_cpunet" if $(BOARD) = "mimxrt595_evk_cm33" diff --git a/samples/drivers/mbox/README.rst b/samples/drivers/mbox/README.rst index a05aa24aa00..cee903710f7 100644 --- a/samples/drivers/mbox/README.rst +++ b/samples/drivers/mbox/README.rst @@ -1,7 +1,8 @@ -.. _mbox-sample: +.. zephyr:code-sample:: mbox + :name: MBOX + :relevant-api: mbox_interface -MBOX Interface -############## + Perform inter-processor mailbox communication using the MBOX API. Overview ******** @@ -20,6 +21,7 @@ Building the application for nrf5340dk_nrf5340_cpuapp :zephyr-app: samples/drivers/mbox/ :board: nrf5340dk_nrf5340_cpuapp :goals: debug + :west-args: --sysbuild Open a serial terminal (minicom, putty, etc.) and connect the board with the following settings: @@ -57,3 +59,23 @@ core: Pong (on channel 1) Ping (on channel 0) Pong (on channel 1) + + +Building the application for the simulated nrf5340bsim +****************************************************** + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/mbox/ + :host-os: unix + :board: nrf5340bsim_nrf5340_cpuapp + :goals: build + :west-args: --sysbuild + +Then you can execute your application using: + +.. code-block:: console + + $ ./build/zephyr/zephyr.exe -nosim + # Press Ctrl+C to exit + +You can expect a similar output as in the real HW in the invoking console. diff --git a/samples/drivers/mbox/boards/mimxrt595_evk_cm33.conf b/samples/drivers/mbox/boards/mimxrt595_evk_cm33.conf new file mode 100644 index 00000000000..b01ff58e024 --- /dev/null +++ b/samples/drivers/mbox/boards/mimxrt595_evk_cm33.conf @@ -0,0 +1 @@ +CONFIG_MBOX_NXP_IMX_MU=y diff --git a/samples/drivers/mbox/remote/CMakeLists.txt b/samples/drivers/mbox/remote/CMakeLists.txt index a2efccf2227..3aee2d96482 100644 --- a/samples/drivers/mbox/remote/CMakeLists.txt +++ b/samples/drivers/mbox/remote/CMakeLists.txt @@ -6,15 +6,16 @@ cmake_minimum_required(VERSION 3.20.0) -if("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpunet") - message(STATUS "${BOARD} compile as remote in this sample") -elseif("${BOARD}" STREQUAL "adp_xc7k_ae350") +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +if(("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpunet") OR + ("${BOARD}" STREQUAL "nrf5340bsim_nrf5340_cpunet") OR + ("${BOARD}" STREQUAL "adp_xc7k_ae350")) message(STATUS "${BOARD} compile as remote in this sample") else() message(FATAL_ERROR "${BOARD} is not supported for this sample") endif() -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(mbox_ipc_remote) target_sources(app PRIVATE src/main.c) diff --git a/samples/drivers/mbox/remote/boards/nrf5340bsim_nrf5340_cpunet.conf b/samples/drivers/mbox/remote/boards/nrf5340bsim_nrf5340_cpunet.conf new file mode 100644 index 00000000000..665e456f504 --- /dev/null +++ b/samples/drivers/mbox/remote/boards/nrf5340bsim_nrf5340_cpunet.conf @@ -0,0 +1,2 @@ +CONFIG_MBOX_NRFX_IPC=y +CONFIG_BUILD_OUTPUT_EXE=n diff --git a/samples/drivers/mbox/remote/sample.yaml b/samples/drivers/mbox/remote/sample.yaml deleted file mode 100644 index 014ad53a126..00000000000 --- a/samples/drivers/mbox/remote/sample.yaml +++ /dev/null @@ -1,9 +0,0 @@ -sample: - name: MBOX IPC sample (remote) -tests: - sample.drivers.mbox_remote: - platform_allow: nrf5340dk_nrf5340_cpunet adp_xc7k_ae350 - integration_platforms: - - nrf5340dk_nrf5340_cpunet - tags: mbox - harness: remote diff --git a/samples/drivers/mbox/sample.yaml b/samples/drivers/mbox/sample.yaml index 6d1ee5fd235..f7aa8953ea1 100644 --- a/samples/drivers/mbox/sample.yaml +++ b/samples/drivers/mbox/sample.yaml @@ -1,9 +1,26 @@ sample: name: MBOX IPC sample +common: + sysbuild: true + tags: mbox tests: - sample.drivers.mbox: - platform_allow: nrf5340dk_nrf5340_cpuapp adp_xc7k_ae350 + sample.drivers.mbox.real_hw: + platform_allow: + - nrf5340dk_nrf5340_cpuapp + - adp_xc7k_ae350 + - mimxrt595_evk_cm33 integration_platforms: - nrf5340dk_nrf5340_cpuapp - tags: mbox harness: remote + sample.drivers.mbox.simu: + platform_allow: + - nrf5340bsim_nrf5340_cpuapp + harness: console + harness_config: + type: multi_line + ordered: false + regex: + - "Ping \\(on channel 0\\)" + - "Pong \\(on channel 0\\)" + - "Ping \\(on channel 1\\)" + - "Pong \\(on channel 1\\)" diff --git a/samples/drivers/mbox/sysbuild.cmake b/samples/drivers/mbox/sysbuild.cmake new file mode 100644 index 00000000000..a8dfb8ebdf4 --- /dev/null +++ b/samples/drivers/mbox/sysbuild.cmake @@ -0,0 +1,20 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if("${SB_CONFIG_REMOTE_BOARD}" STREQUAL "") + message(FATAL_ERROR + "Target ${BOARD} not supported for this sample. " + "There is no remote board selected in Kconfig.sysbuild") +endif() + +set(REMOTE_APP remote) + +ExternalZephyrProject_Add( + APPLICATION ${REMOTE_APP} + SOURCE_DIR ${APP_DIR}/${REMOTE_APP} + BOARD ${SB_CONFIG_REMOTE_BOARD} +) + +native_simulator_set_child_images(${DEFAULT_IMAGE} ${REMOTE_APP}) + +native_simulator_set_final_executable(${DEFAULT_IMAGE}) diff --git a/samples/drivers/mbox/sysbuild.conf b/samples/drivers/mbox/sysbuild.conf new file mode 100644 index 00000000000..6408669a847 --- /dev/null +++ b/samples/drivers/mbox/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/samples/drivers/memc/CMakeLists.txt b/samples/drivers/memc/CMakeLists.txt index 1e46e72f25b..04025a6b0fb 100644 --- a/samples/drivers/memc/CMakeLists.txt +++ b/samples/drivers/memc/CMakeLists.txt @@ -5,4 +5,9 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(memc) + +if(CONFIG_MEMC_MCUX_FLEXSPI) + target_include_directories(app PRIVATE ${ZEPHYR_BASE}/drivers/memc) +endif() + target_sources(app PRIVATE src/main.c) diff --git a/samples/drivers/memc/README.rst b/samples/drivers/memc/README.rst index 05da1c094d5..814b7e949fc 100644 --- a/samples/drivers/memc/README.rst +++ b/samples/drivers/memc/README.rst @@ -1,7 +1,7 @@ -.. _memc: +.. zephyr:code-sample:: memc + :name: Memory controller (MEMC) driver -MEMC Driver Sample -################## + Access memory-mapped external RAM Overview ******** diff --git a/samples/drivers/memc/src/main.c b/samples/drivers/memc/src/main.c index 86b7ff86b60..60bc1170761 100644 --- a/samples/drivers/memc/src/main.c +++ b/samples/drivers/memc/src/main.c @@ -7,8 +7,11 @@ #include #if DT_HAS_COMPAT_STATUS_OKAY(nxp_imx_flexspi) -/* FlexSPI memory mapped region is second register property of parent dev */ -#define MEMC_BASE DT_REG_ADDR_BY_IDX(DT_PARENT(DT_ALIAS(sram_ext)), 1) +/* Use memc API to get AHB base address for the device */ +#include "memc_mcux_flexspi.h" +#define FLEXSPI_DEV DEVICE_DT_GET(DT_PARENT(DT_ALIAS(sram_ext))) +#define MEMC_PORT DT_REG_ADDR(DT_ALIAS(sram_ext)) +#define MEMC_BASE memc_flexspi_get_ahb_address(FLEXSPI_DEV, MEMC_PORT, 0) #define MEMC_SIZE (DT_PROP(DT_ALIAS(sram_ext), size) / 8) #endif @@ -49,7 +52,7 @@ int main(void) for (i = 0; i < BUF_SIZE; i++) { memc_write_buffer[i] = (uint8_t)i; } - printk("Writing to memory region with base 0x%0x, size 0x%0x\n\n", + printk("Writing to memory region with base %p, size 0x%0x\n\n", MEMC_BASE, MEMC_SIZE); /* Copy write buffer into memc region */ for (i = 0, j = 0; j < (MEMC_SIZE / BUF_SIZE); i += BUF_SIZE, j++) { diff --git a/samples/drivers/misc/ft800/README.rst b/samples/drivers/misc/ft800/README.rst index 81c4a3ad764..5c72c3641e6 100644 --- a/samples/drivers/misc/ft800/README.rst +++ b/samples/drivers/misc/ft800/README.rst @@ -1,7 +1,8 @@ -.. _display-ft800-sample: +.. zephyr:code-sample:: ft800 + :name: FT800 + :relevant-api: ft8xx_interface -FT800 -##### + Display various shapes and text using FT800 Embedded Video Engine. Overview ******** diff --git a/samples/drivers/misc/grove_display/README.rst b/samples/drivers/misc/grove_display/README.rst index a1838d0ec5c..cd288b5b76f 100644 --- a/samples/drivers/misc/grove_display/README.rst +++ b/samples/drivers/misc/grove_display/README.rst @@ -1,7 +1,8 @@ -.. _grove-lcd-sample: +.. zephyr:code-sample:: grove-lcd + :name: Grove LCD + :relevant-api: grove_display -Grove LCD -######### + Display an incrementing counter and change the backlight color. Overview ******** diff --git a/samples/drivers/misc/timeaware_gpio/CMakeLists.txt b/samples/drivers/misc/timeaware_gpio/CMakeLists.txt new file mode 100644 index 00000000000..2705cd84c08 --- /dev/null +++ b/samples/drivers/misc/timeaware_gpio/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(timeaware_gpio) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/drivers/misc/timeaware_gpio/README.rst b/samples/drivers/misc/timeaware_gpio/README.rst new file mode 100644 index 00000000000..fc242f9dba8 --- /dev/null +++ b/samples/drivers/misc/timeaware_gpio/README.rst @@ -0,0 +1,52 @@ +.. zephyr:code-sample:: timeaware-gpio + :name: Time-aware GPIO + :relevant-api: tgpio_interface + + Synchronize clocks. + +Overview +******** + +A sample application that can be used with any supported boards. eg. RPL. +prints configuration info to the console. Below functionalities are tested: + +1. Periodic pulse generation (an Oscilloscope or loopback may be required) +2. Input pulse timestamping (a pulse generator or loopback may be required) + +Building and Running +******************** + +This application can be built and executed as follows: + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/misc/timeaware_gpio + :board: intel_rpl_crb + :host-os: unix + :goals: build + + +To build for another supported board, change "intel_rpl_crb" to that board's +name (if supported). + +Sample Output +============= + +.. code-block:: console + + *** Booting Zephyr OS build zephyr-v3.4.0-4166-g52b34a310c67 *** + [TGPIO] Bind Success + [TGPIO] Time now: 00000001477ed72f + [TGPIO] Running rate: 19200000 + [TGPIO] Periodic pulses start at: 0000000148a3cf2f + [TGPIO] timestamp: 0000000000000000, event count: 0000000000000000 + [TGPIO] timestamp: 0000000148a3cf31, event count: 0000000000000001 + [TGPIO] timestamp: 0000000149c8c731, event count: 0000000000000002 + [TGPIO] timestamp: 000000014aedbf31, event count: 0000000000000003 + [TGPIO] timestamp: 000000014c12b731, event count: 0000000000000004 + [TGPIO] timestamp: 000000014d37af31, event count: 0000000000000005 + [TGPIO] timestamp: 000000014e5ca731, event count: 0000000000000006 + [TGPIO] timestamp: 000000014f819f31, event count: 0000000000000007 + [TGPIO] timestamp: 0000000150a69731, event count: 0000000000000008 + [TGPIO] timestamp: 0000000151cb8f31, event count: 0000000000000009 + [TGPIO] timestamp: 0000000152f08731, event count: 000000000000000a + [TGPIO] timestamp: 0000000154157f31, event count: 000000000000000b diff --git a/samples/drivers/misc/timeaware_gpio/prj.conf b/samples/drivers/misc/timeaware_gpio/prj.conf new file mode 100644 index 00000000000..5bc0e68bd3c --- /dev/null +++ b/samples/drivers/misc/timeaware_gpio/prj.conf @@ -0,0 +1,2 @@ +# nothing here +CONFIG_TIMEAWARE_GPIO=y diff --git a/samples/drivers/misc/timeaware_gpio/sample.yaml b/samples/drivers/misc/timeaware_gpio/sample.yaml new file mode 100644 index 00000000000..4af9b14640a --- /dev/null +++ b/samples/drivers/misc/timeaware_gpio/sample.yaml @@ -0,0 +1,7 @@ +sample: + name: timeaware_gpio +tests: + sample.drivers.misc.timeaware_gpio: + tags: + - drivers + filter: dt_compat_enabled("intel,timeaware-gpio") diff --git a/samples/drivers/misc/timeaware_gpio/src/main.c b/samples/drivers/misc/timeaware_gpio/src/main.c new file mode 100644 index 00000000000..f205368124a --- /dev/null +++ b/samples/drivers/misc/timeaware_gpio/src/main.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Sample application for timeaware GPIO. + * This example demonstrates the following + * a. How to generate pulses based on ART time on an output pin + * b. How to timestamp a pulse on an input pin + */ + +/* Local Includes */ +#include +#include +#include +#include +#include +#include + +#define TGPIO_LABEL DT_NODELABEL(tgpio) +#define TGPIO_PIN_IN 0 +#define TGPIO_PIN_OUT 1 + +int main(void) +{ + const struct device *tgpio_dev; + uint64_t tm, ts, ec, ret; + uint32_t cycles; + + /* Get the device handle for Timeaware-GPIO instance */ + tgpio_dev = DEVICE_DT_GET(TGPIO_LABEL); + if (!device_is_ready(tgpio_dev)) { + printk("[TGPIO] Bind failed\n"); + return -EINVAL; + } + + printk("[TGPIO] Bind Success\n"); + + tgpio_port_get_time(tgpio_dev, &tm); + printk("[TGPIO] Time now: %016llx\n", tm); + + tgpio_port_get_cycles_per_second(tgpio_dev, &cycles); + printk("[TGPIO] Running rate: %d\n", cycles); + + /* Configure start time of first pulse, time has to be in future */ + tm += cycles; + printk("[TGPIO] Periodic pulses start at: %016llx\n", tm); + + ret = tgpio_pin_periodic_output(tgpio_dev, TGPIO_PIN_OUT, + tm, cycles, true); + if (ret) { + printk("[TGPIO] periodic output configuration failed\n"); + return -EINVAL; + } + + /* Configure external timestamp for input pulses */ + ret = tgpio_pin_config_ext_timestamp(tgpio_dev, TGPIO_PIN_IN, 0); + if (ret) { + printk("[TGPIO] external timestamp configuration failed\n"); + return -EINVAL; + } + + while (1) { + /* Read timestamp and event counter values */ + tgpio_pin_read_ts_ec(tgpio_dev, TGPIO_PIN_IN, &ts, &ec); + printk("[TGPIO] timestamp: %016llx, event count: %016llx\n", ts, ec); + k_sleep(K_MSEC(500)); + } + return 0; +} diff --git a/samples/drivers/peci/README.rst b/samples/drivers/peci/README.rst index aa361dc7611..98c11d43a25 100644 --- a/samples/drivers/peci/README.rst +++ b/samples/drivers/peci/README.rst @@ -1,7 +1,8 @@ -.. _peci-sample: +.. zephyr:code-sample:: peci + :name: PECI interface + :relevant-api: peci_interface -PECI Interface -#################################### + Monitor CPU temperature using PECI. Overview ******** diff --git a/samples/drivers/ps2/README.rst b/samples/drivers/ps2/README.rst index f18e1a5e6f9..d37fbde392e 100644 --- a/samples/drivers/ps2/README.rst +++ b/samples/drivers/ps2/README.rst @@ -1,7 +1,8 @@ -.. _ps2-sample: +.. zephyr:code-sample:: ps2 + :name: PS/2 interface + :relevant-api: ps2_interface -PS/2 Interface -#################################### + Communicate with a PS/2 mouse. Overview ******** diff --git a/samples/drivers/ps2/prj.conf b/samples/drivers/ps2/prj.conf index 743787bd855..182a536650f 100644 --- a/samples/drivers/ps2/prj.conf +++ b/samples/drivers/ps2/prj.conf @@ -2,3 +2,4 @@ CONFIG_STDOUT_CONSOLE=y CONFIG_PRINTK=y CONFIG_PS2=y CONFIG_PM_DEVICE=y +CONFIG_PM=y diff --git a/samples/drivers/smbus/README.rst b/samples/drivers/smbus/README.rst index e1f8fec8db9..28558247706 100644 --- a/samples/drivers/smbus/README.rst +++ b/samples/drivers/smbus/README.rst @@ -1,7 +1,8 @@ -.. _samples_smbus_shell: +.. zephyr:code-sample:: smbus-shell + :name: SMBus shell + :relevant-api: smbus_interface -SMBus Shell Sample -################## + Interact with SMBus peripherals using shell commands. Overview ******** @@ -12,7 +13,9 @@ driver supported exploring the SMBus communication with peripheral devices. Building and Running ******************** -This project can be built and executed on as follows: +This sample can be found under :zephyr_file:`samples/drivers/smbus` in the +Zephyr tree. +The sample can be built and run as follows for the ``qemu_x86_64`` board: .. zephyr-app-commands:: :zephyr-app: zephyr/samples/drivers/smbus @@ -22,15 +25,19 @@ This project can be built and executed on as follows: :compact: Sample Output -============= +************* -Output from console when application started:: +Output from console when application started: + +.. code-block:: console *** Booting Zephyr OS build zephyr-v3.2.0-804-gfedd72615e82 *** Start SMBUS shell sample qemu_x86_64 uart:~$ -List avaibalbe SMBus shell commands with:: +List available SMBus shell commands with: + +.. code-block:: console uart:~$ smbus smbus - smbus commands @@ -56,7 +63,9 @@ List avaibalbe SMBus shell commands with:: block_read :SMBus: Block Read command Usage: block_read -Scan for available SMBus devices with command:: +Scan for available SMBus devices with command: + +.. code-block:: console uart:~$ smbus scan smbus@fb00 0 1 2 3 4 5 6 7 8 9 a b c d e f diff --git a/samples/drivers/smbus/prj.conf b/samples/drivers/smbus/prj.conf index a02baae7ec9..8ed31bb9e29 100644 --- a/samples/drivers/smbus/prj.conf +++ b/samples/drivers/smbus/prj.conf @@ -1,4 +1,5 @@ CONFIG_SMBUS=y +CONFIG_SMBUS_SHELL=y CONFIG_SMBUS_INTEL_PCH=y CONFIG_SMBUS_LOG_LEVEL_DBG=y CONFIG_USERSPACE=y diff --git a/samples/drivers/soc_flash_nrf/README.rst b/samples/drivers/soc_flash_nrf/README.rst index 14c39851f66..2ee87739aad 100644 --- a/samples/drivers/soc_flash_nrf/README.rst +++ b/samples/drivers/soc_flash_nrf/README.rst @@ -1,18 +1,19 @@ -.. _soc-flash-nrf-sample: +.. zephyr:code-sample:: soc-flash-nrf + :name: nRF SoC flash + :relevant-api: flash_interface flash_area_api -nRF SoC flash sample -#################### + Use the flash API to interact with the SoC flash. Overview ******** -This sample demonstrates using the flash API on a SoC internal flash. -The sample uses :ref:`flash_map_api` to obtain device for flash, using -DTS node label, and then directly uses :ref:`flash_api` to perform +This sample demonstrates using the :ref:`Flash API ` on an SoC internal flash. +The sample uses :ref:`Flash map API ` to obtain device for flash, using +DTS node label, and then directly uses :ref:`Flash API ` to perform flash operations. -Within the sample user may observe how read/write/erase operations -are performed on a device and how to first check whether device is +Within the sample, user may observe how read/write/erase operations +are performed on a device, and how to first check whether device is ready for operation. Building and Running diff --git a/samples/drivers/soc_flash_nrf/sample.yaml b/samples/drivers/soc_flash_nrf/sample.yaml index c493c553e1f..d1f635ca93f 100644 --- a/samples/drivers/soc_flash_nrf/sample.yaml +++ b/samples/drivers/soc_flash_nrf/sample.yaml @@ -10,8 +10,7 @@ tests: - nrf52dk_nrf52832 tags: - flash - - nrf52 - - nrf9160 + - drivers harness: console harness_config: fixture: external_flash diff --git a/samples/drivers/spi_bitbang/README.rst b/samples/drivers/spi_bitbang/README.rst index 6b629c99118..a8ff597f002 100644 --- a/samples/drivers/spi_bitbang/README.rst +++ b/samples/drivers/spi_bitbang/README.rst @@ -1,7 +1,8 @@ -.. _spi-bitbang-sample: +.. zephyr:code-sample:: spi-bitbang + :name: SPI bitbang + :relevant-api: spi_interface -SPI-Bitbang Sample -#################### + Use the bitbang SPI driver for communicating with a slave. Overview ******** diff --git a/samples/drivers/spi_flash/README.rst b/samples/drivers/spi_flash/README.rst index e459559a418..70b523a58a4 100644 --- a/samples/drivers/spi_flash/README.rst +++ b/samples/drivers/spi_flash/README.rst @@ -1,12 +1,13 @@ -.. _spi-nor-sample: +.. zephyr:code-sample:: spi-nor + :name: JEDEC SPI-NOR flash + :relevant-api: flash_interface -JEDEC SPI-NOR Sample -#################### + Use the flash API to interact with an SPI NOR serial flash memory device. Overview ******** -This sample demonstrates using the flash API on a SPI NOR serial flash +This sample demonstrates using the :ref:`flash API ` on a SPI NOR serial flash memory device. While trivial it is an example of direct access and allows confirmation that the flash is working and that automatic power savings is correctly implemented. diff --git a/samples/drivers/spi_flash_at45/README.rst b/samples/drivers/spi_flash_at45/README.rst index c8d5b60c91e..467edb2a4d2 100644 --- a/samples/drivers/spi_flash_at45/README.rst +++ b/samples/drivers/spi_flash_at45/README.rst @@ -1,7 +1,8 @@ -.. _spi_flash_at45_sample: +.. zephyr:code-sample:: spi-flash-at45 + :name: AT45 DataFlash driver + :relevant-api: flash_interface -AT45 DataFlash driver sample -############################# + Use the AT45 family DataFlash driver to interact with the flash memory over SPI. Overview ******** @@ -23,7 +24,7 @@ enables the flash page layout API which allow show the flash information. In the default configuration, the AT45 flash driver is configured to use the Read-Modify-Write functionality of DataFlash chips and does not perform page erasing, as it is not needed in this case. This can be modified by -simply disabling the SPI_FLASH_AT45_USE_READ_MODIFY_WRITE option. +simply disabling the :kconfig:option:`CONFIG_SPI_FLASH_AT45_USE_READ_MODIFY_WRITE` option. Requirements ************ diff --git a/samples/drivers/uart/echo_bot/README.rst b/samples/drivers/uart/echo_bot/README.rst index f46f39b99ba..8f08af803d4 100644 --- a/samples/drivers/uart/echo_bot/README.rst +++ b/samples/drivers/uart/echo_bot/README.rst @@ -1,7 +1,8 @@ -.. _uart_sample: +.. zephyr:code-sample:: uart + :name: UART echo + :relevant-api: uart_interface -UART Driver Sample -################## + Read data from the console and echo it back. Overview ******** diff --git a/samples/drivers/uart/native_tty/README.rst b/samples/drivers/uart/native_tty/README.rst index deacfde80d3..78c101dea1f 100644 --- a/samples/drivers/uart/native_tty/README.rst +++ b/samples/drivers/uart/native_tty/README.rst @@ -1,7 +1,8 @@ -.. _sample-uart-native-tty: +.. zephyr:code-sample:: uart-native-tty + :name: Native TTY UART + :relevant-api: uart_interface -Native TTY UART -############### + Use native TTY driver to send and receive data between two UART-to-USB bridge dongles. Overview ******** @@ -14,7 +15,7 @@ The source code for this sample application can be found at: :zephyr_file:`samples/drivers/uart/native-tty`. You can learn more about the Native TTY UART driver in the -:ref:`TTY UART ` section of the Native posix board +:ref:`TTY UART ` section of the native_sim board documentation. Requirements @@ -27,18 +28,18 @@ Requirements ``/dev/ttyUSB0`` and ``/dev/ttyUSB1`` in the system. You can check what they are in your system by running the command ``ls -l /dev/tty*``. If that is not the case on your machine you can either change the ``serial-port`` properties - in the ``boards/native_posix.overlay`` file or using the command line options + in the ``boards/native_sim.overlay`` file or using the command line options ``-uart_port`` and ``-uart_port2``. Building and Running ******************** -This application can be built and executed on Native Posix as follows: +This application can be built and executed on :ref:`native_sim ` as follows: .. zephyr-app-commands:: :zephyr-app: samples/drivers/uart/native_tty :host-os: unix - :board: native_posix + :board: native_sim :goals: run :compact: diff --git a/samples/drivers/uart/native_tty/boards/native_posix.overlay b/samples/drivers/uart/native_tty/boards/native_posix.overlay index 24f1bd95705..6a3daca3241 100644 --- a/samples/drivers/uart/native_tty/boards/native_posix.overlay +++ b/samples/drivers/uart/native_tty/boards/native_posix.overlay @@ -1,15 +1 @@ -/ { - uart0: uart { - status = "okay"; - compatible = "zephyr,native-tty-uart"; - current-speed = <115200>; - serial-port = "/dev/ttyUSB0"; - }; - - uart2: uart2 { - status = "okay"; - compatible = "zephyr,native-tty-uart"; - current-speed = <115200>; - serial-port = "/dev/ttyUSB1"; - }; -}; +#include "native_sim.overlay" diff --git a/samples/drivers/uart/native_tty/boards/native_sim.overlay b/samples/drivers/uart/native_tty/boards/native_sim.overlay new file mode 100644 index 00000000000..24f1bd95705 --- /dev/null +++ b/samples/drivers/uart/native_tty/boards/native_sim.overlay @@ -0,0 +1,15 @@ +/ { + uart0: uart { + status = "okay"; + compatible = "zephyr,native-tty-uart"; + current-speed = <115200>; + serial-port = "/dev/ttyUSB0"; + }; + + uart2: uart2 { + status = "okay"; + compatible = "zephyr,native-tty-uart"; + current-speed = <115200>; + serial-port = "/dev/ttyUSB1"; + }; +}; diff --git a/samples/drivers/uart/native_tty/prj.conf b/samples/drivers/uart/native_tty/prj.conf index ef2861c789f..7958f8c58bf 100644 --- a/samples/drivers/uart/native_tty/prj.conf +++ b/samples/drivers/uart/native_tty/prj.conf @@ -1 +1,2 @@ CONFIG_SERIAL=y +CONFIG_UART_USE_RUNTIME_CONFIGURE=y diff --git a/samples/drivers/uart/native_tty/sample.yaml b/samples/drivers/uart/native_tty/sample.yaml index 92263aa8c42..1e059d9ce3a 100644 --- a/samples/drivers/uart/native_tty/sample.yaml +++ b/samples/drivers/uart/native_tty/sample.yaml @@ -3,7 +3,9 @@ sample: tests: sample.drivers.uart.native_tty: build_only: true - platform_allow: native_posix + platform_allow: + - native_posix + - native_sim tags: - serial - uart diff --git a/samples/drivers/uart/stm32/single_wire/README.rst b/samples/drivers/uart/stm32/single_wire/README.rst deleted file mode 100644 index 8956cca4a31..00000000000 --- a/samples/drivers/uart/stm32/single_wire/README.rst +++ /dev/null @@ -1,33 +0,0 @@ -.. _sample_uart_stm32_single_wire: - -STM32 Single Wire UART -###################### - -Overview -******** - -A simple application demonstrating how to use the single wire / half-duplex UART -functionality of STM32. Without adaptions this example runs on STM32F3 discovery -board. You need to establish a physical connection between pins PA2 (USART2_TX) and -PC10 (UART4_TX). - -Add a `single_wire_uart_loopback` fixture to your board in the hardware map to allow -twister to verify this sample's output automatically. - -Building and Running -******************** - -Build and flash as follows, replacing ``stm32f3_disco`` with your board: - - .. zephyr-app-commands:: - :zephyr-app: samples/drivers/uart/stm32/single_wire - :board: stm32f3_disco - :goals: build flash - :compact: - -After flashing the console output should not show any failure reports, -but the following message repeated every 2s: - -.. code-block:: none - - Received c diff --git a/samples/drivers/uart/stm32/single_wire/sample.yaml b/samples/drivers/uart/stm32/single_wire/sample.yaml deleted file mode 100644 index 006fa8e84f8..00000000000 --- a/samples/drivers/uart/stm32/single_wire/sample.yaml +++ /dev/null @@ -1,14 +0,0 @@ -sample: - name: STM32 Single Wire UART sample -tests: - sample.drivers.uart.stm32.single_wire: - platform_allow: stm32f3_disco - tags: - - drivers - - uart - harness: console - harness_config: - fixture: single_line_uart_loopback - type: one_line - regex: - - "Received c" diff --git a/samples/drivers/virtualization/ivshmem/doorbell/README.rst b/samples/drivers/virtualization/ivshmem/doorbell/README.rst index 001bdf3e545..d5091323b2c 100644 --- a/samples/drivers/virtualization/ivshmem/doorbell/README.rst +++ b/samples/drivers/virtualization/ivshmem/doorbell/README.rst @@ -1,5 +1,9 @@ -IVSHMEM Doorbell Sample Application -################################### +.. zephyr:code-sample:: ivshmem-doorbell + :name: IVSHMEM doorbell + :relevant-api: ivshmem + + Use Inter-VM Shared Memory to exchange messages between two processes running on different + operating systems. Overview ******** @@ -62,7 +66,7 @@ How to .. note:: The ivshmem shared memory can be manipulated to crash QEMU and bring down - Zephyr. Check `ivshmem_doorbell_sample_security`_ for details. + Zephyr. Check :ref:`ivshmem_doorbell_sample_security` section for more details. .. note:: diff --git a/samples/drivers/w1/scanner/README.rst b/samples/drivers/w1/scanner/README.rst index fa8e8563dfa..325b02f528c 100644 --- a/samples/drivers/w1/scanner/README.rst +++ b/samples/drivers/w1/scanner/README.rst @@ -1,7 +1,8 @@ -.. _w1_scanner_sample: +.. zephyr:code-sample:: w1-scanner + :name: 1-Wire scanner + :relevant-api: w1_interface -1-Wire Scanner Sample -##################### + Scan for 1-Wire devices and print their family ID and serial number. Overview ******** diff --git a/samples/drivers/w1/scanner/sample.yaml b/samples/drivers/w1/scanner/sample.yaml index 1ffb7ffc930..c05df2c59e2 100644 --- a/samples/drivers/w1/scanner/sample.yaml +++ b/samples/drivers/w1/scanner/sample.yaml @@ -37,7 +37,8 @@ tests: - "Number of devices found on bus: .*" fixture: w1_scanner_ds2485 samples.drivers.w1.scanner.w1_serial: - depends_on: arduino_serial + depends_on: + - arduino_serial extra_args: DTC_OVERLAY_FILE=w1_serial.overlay platform_allow: - nrf52840dk_nrf52840 diff --git a/samples/drivers/watchdog/README.rst b/samples/drivers/watchdog/README.rst index 54f95cb032b..619ddf78952 100644 --- a/samples/drivers/watchdog/README.rst +++ b/samples/drivers/watchdog/README.rst @@ -1,7 +1,8 @@ -.. _watchdog-sample: +.. zephyr:code-sample:: watchdog + :name: Watchdog + :relevant-api: watchdog_interface -Watchdog Sample -############### + Use the watchdog driver API to reset the board when it gets stuck in an infinite loop. Overview ******** diff --git a/samples/drivers/watchdog/boards/up_squared_pro_7000.overlay b/samples/drivers/watchdog/boards/up_squared_pro_7000.overlay new file mode 100644 index 00000000000..660b55c0512 --- /dev/null +++ b/samples/drivers/watchdog/boards/up_squared_pro_7000.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&tco_wdt { + status = "okay"; +}; diff --git a/samples/drivers/watchdog/boards/xmc45_relax_kit.overlay b/samples/drivers/watchdog/boards/xmc45_relax_kit.overlay new file mode 100644 index 00000000000..44cc7a91cda --- /dev/null +++ b/samples/drivers/watchdog/boards/xmc45_relax_kit.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2023 SLB + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&wdt0 { + status = "okay"; +}; diff --git a/samples/drivers/watchdog/boards/xmc47_relax_kit.overlay b/samples/drivers/watchdog/boards/xmc47_relax_kit.overlay new file mode 100644 index 00000000000..44cc7a91cda --- /dev/null +++ b/samples/drivers/watchdog/boards/xmc47_relax_kit.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2023 SLB + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&wdt0 { + status = "okay"; +}; diff --git a/samples/drivers/watchdog/sample.yaml b/samples/drivers/watchdog/sample.yaml index d9c908d536d..f3e11dda9b5 100644 --- a/samples/drivers/watchdog/sample.yaml +++ b/samples/drivers/watchdog/sample.yaml @@ -20,6 +20,8 @@ tests: platform_exclude: - s32z270dc2_rtu0_r52 - s32z270dc2_rtu1_r52 + - s32z270dc2_rtu0_r52@D + - s32z270dc2_rtu1_r52@D sample.drivers.watchdog.stm32_wwdg: extra_args: DTC_OVERLAY_FILE=boards/stm32_wwdg.overlay filter: dt_compat_enabled("st,stm32-window-watchdog") @@ -106,3 +108,5 @@ tests: platform_allow: - s32z270dc2_rtu0_r52 - s32z270dc2_rtu1_r52 + - s32z270dc2_rtu0_r52@D + - s32z270dc2_rtu1_r52@D diff --git a/samples/fuel_gauge/max17048/src/main.c b/samples/fuel_gauge/max17048/src/main.c index 01428f10aba..26bb94b3852 100644 --- a/samples/fuel_gauge/max17048/src/main.c +++ b/samples/fuel_gauge/max17048/src/main.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "zephyr/sys/util.h" #include #include #include @@ -38,66 +39,27 @@ int main(void) while (1) { - struct fuel_gauge_get_property props[] = { - { - .property_type = FUEL_GAUGE_RUNTIME_TO_EMPTY, - }, - { - .property_type = FUEL_GAUGE_RUNTIME_TO_FULL, - }, - { - .property_type = FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE, - }, - { - .property_type = FUEL_GAUGE_VOLTAGE, - } + fuel_gauge_prop_t props[] = { + FUEL_GAUGE_RUNTIME_TO_EMPTY, + FUEL_GAUGE_RUNTIME_TO_FULL, + FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE, + FUEL_GAUGE_VOLTAGE, }; - ret = fuel_gauge_get_prop(dev, props, ARRAY_SIZE(props)); + union fuel_gauge_prop_val vals[ARRAY_SIZE(props)]; + + ret = fuel_gauge_get_props(dev, props, vals, ARRAY_SIZE(props)); if (ret < 0) { printk("Error: cannot get properties\n"); } else { - if (ret != 0) { - printk("Warning: Some properties failed\n"); - } - - if (props[0].status == 0) { - printk("Time to empty %d\n", props[0].value.runtime_to_empty); - } else { - printk( - "Property FUEL_GAUGE_RUNTIME_TO_EMPTY failed with error %d\n", - props[0].status - ); - } - - if (props[1].status == 0) { - printk("Time to full %d\n", props[1].value.runtime_to_full); - } else { - printk( - "Property FUEL_GAUGE_RUNTIME_TO_FULL failed with error %d\n", - props[1].status - ); - } - - if (props[2].status == 0) { - printk("Charge %d%%\n", props[2].value.relative_state_of_charge); - } else { - printk( - "Property FUEL_GAUGE_STATE_OF_CHARGE failed with error %d\n", - props[2].status - ); - } - - if (props[3].status == 0) { - printk("Voltage %d\n", props[3].value.voltage); - } else { - printk( - "Property FUEL_GAUGE_VOLTAGE failed with error %d\n", - props[3].status - ); - } - } + printk("Time to empty %d\n", vals[0].runtime_to_empty); + + printk("Time to full %d\n", vals[1].runtime_to_full); + printk("Charge %d%%\n", vals[2].relative_state_of_charge); + + printk("Voltage %d\n", vals[3].voltage); + } k_sleep(K_MSEC(5000)); } diff --git a/samples/hello_world/sample.yaml b/samples/hello_world/sample.yaml index 60cbe49360f..1bcb7db62f2 100644 --- a/samples/hello_world/sample.yaml +++ b/samples/hello_world/sample.yaml @@ -5,7 +5,7 @@ sample: common: tags: introduction integration_platforms: - - native_posix + - native_sim harness: console harness_config: type: one_line diff --git a/samples/index.rst b/samples/index.rst index 0ba36eeaebb..8581a330d40 100644 --- a/samples/index.rst +++ b/samples/index.rst @@ -5,6 +5,7 @@ Samples and Demos .. toctree:: + :titlesonly: :maxdepth: 2 :glob: diff --git a/samples/kernel/condition_variables/condvar/README.rst b/samples/kernel/condition_variables/condvar/README.rst index 79a41f870b2..bd84d54854a 100644 --- a/samples/kernel/condition_variables/condvar/README.rst +++ b/samples/kernel/condition_variables/condvar/README.rst @@ -1,12 +1,13 @@ -.. _samples_kernel_condvar: +.. zephyr:code-sample:: kernel-condvar + :name: Condition Variables + :relevant-api: condvar_apis -Condition Variables -################### + Manipulate condition variables in a multithreaded application. Overview ******** -This sample demonstrates the usage of condition variables in a +This sample demonstrates the usage of :ref:`condition variables ` in a multithreaded application. Condition variables are used with a mutex to signal changing states (conditions) from one thread to another thread. A thread uses a condition variable to wait for a condition to @@ -19,16 +20,16 @@ the console. Building and Running ******************** -This application can be built and executed on Native Posix as follows: +This application can be built and executed on :ref:`native_sim ` as follows: .. zephyr-app-commands:: :zephyr-app: samples/kernel/condition_variables/condvar :host-os: unix - :board: native_posix + :board: native_sim :goals: run :compact: -To build for another board, change "native_posix" above to that board's name. +To build for another board, change ``native_sim`` above to that board's name. Sample Output ============= diff --git a/samples/kernel/condition_variables/condvar/sample.yaml b/samples/kernel/condition_variables/condvar/sample.yaml index a6e1515c67b..d2a68fbdce4 100644 --- a/samples/kernel/condition_variables/condvar/sample.yaml +++ b/samples/kernel/condition_variables/condvar/sample.yaml @@ -1,7 +1,7 @@ tests: sample.kernel.cond_var: integration_platforms: - - native_posix + - native_sim tags: - kernel - condition_variables diff --git a/samples/kernel/condition_variables/simple/README.rst b/samples/kernel/condition_variables/simple/README.rst index 42199d31c5b..2977b72cc97 100644 --- a/samples/kernel/condition_variables/simple/README.rst +++ b/samples/kernel/condition_variables/simple/README.rst @@ -19,16 +19,16 @@ the console. Building and Running ******************** -This application can be built and executed on Native Posix as follows: +This application can be built and executed on :ref:`native_sim ` as follows: .. zephyr-app-commands:: :zephyr-app: samples/kernel/condition_variables/simple :host-os: unix - :board: native_posix + :board: native_sim :goals: run :compact: -To build for another board, change "native_posix" above to that board's name. +To build for another board, change ``native_sim`` above to that board's name. Sample Output ============= diff --git a/samples/kernel/condition_variables/simple/sample.yaml b/samples/kernel/condition_variables/simple/sample.yaml index 556fc8e9f03..0b260a8a7e3 100644 --- a/samples/kernel/condition_variables/simple/sample.yaml +++ b/samples/kernel/condition_variables/simple/sample.yaml @@ -1,7 +1,7 @@ tests: sample.kernel.cond_var.simple: integration_platforms: - - native_posix + - native_sim tags: - kernel - condition_variables diff --git a/samples/kernel/metairq_dispatch/CMakeLists.txt b/samples/kernel/metairq_dispatch/CMakeLists.txt index fe39b05df2e..2b16c4b410e 100644 --- a/samples/kernel/metairq_dispatch/CMakeLists.txt +++ b/samples/kernel/metairq_dispatch/CMakeLists.txt @@ -6,3 +6,7 @@ find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(metairq_dispatch) target_sources(app PRIVATE src/main.c src/msgdev.c) + +target_include_directories(app PRIVATE + ${ZEPHYR_BASE}/kernel/include + ) diff --git a/samples/kernel/metairq_dispatch/README.rst b/samples/kernel/metairq_dispatch/README.rst index ef7e96afa17..1e9fda7927c 100644 --- a/samples/kernel/metairq_dispatch/README.rst +++ b/samples/kernel/metairq_dispatch/README.rst @@ -60,7 +60,7 @@ kHz). Note that because the test is fundamentally measuring thread preemption behavior, it does not run without modification on -native_posix platforms. In that emulation environment, threads will +native_sim platforms. In that emulation environment, threads will not be preempted except at specific instrumentation points (e.g. in k_busy_wait()) where they will voluntarily release the CPU. diff --git a/samples/kernel/metairq_dispatch/sample.yaml b/samples/kernel/metairq_dispatch/sample.yaml index 201166f7e78..82090751b33 100644 --- a/samples/kernel/metairq_dispatch/sample.yaml +++ b/samples/kernel/metairq_dispatch/sample.yaml @@ -14,7 +14,7 @@ common: regex: - "MetaIRQ Test Complete" -# Note that native_posix architectures are filtered, they require +# Note that boards based on the POSIX architecture are filtered as they require # instrumentation (e.g. a k_busy_wait()) inside the worker threads # "busy" loops in order for the interrupts to fire on time, and the # sample is designed to demonstrate completely arbitrary CPU work. diff --git a/samples/kernel/metairq_dispatch/src/msgdev.c b/samples/kernel/metairq_dispatch/src/msgdev.c index 142f46d043d..d4ba5d5895f 100644 --- a/samples/kernel/metairq_dispatch/src/msgdev.c +++ b/samples/kernel/metairq_dispatch/src/msgdev.c @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include "msgdev.h" /* This file implements a fake device that creates and enqueues diff --git a/samples/modules/canopennode/README.rst b/samples/modules/canopennode/README.rst index ae6f135ae30..50b53aab99f 100644 --- a/samples/modules/canopennode/README.rst +++ b/samples/modules/canopennode/README.rst @@ -26,6 +26,13 @@ Requirements Building and Running ******************** +First, ensure the optional CANopenNode module is enabled and available: + + .. code-block:: console + + west config manifest.project-filter +canopennode + west update canopennode + Building and Running for TWR-KE18F ================================== The :ref:`twr_ke18f` board is equipped with an onboard CAN diff --git a/samples/modules/chre/README.rst b/samples/modules/chre/README.rst index 54b9244d3dc..22a43a58432 100644 --- a/samples/modules/chre/README.rst +++ b/samples/modules/chre/README.rst @@ -31,7 +31,7 @@ To build the sample use the following west command: .. zephyr-app-commands:: :zephyr-app: samples/modules/chre - :board: native_posix + :board: native_sim :goals: build Once built and run, the sample application should: diff --git a/samples/modules/chre/sample.yaml b/samples/modules/chre/sample.yaml index 65f64e9453d..9442decc83d 100644 --- a/samples/modules/chre/sample.yaml +++ b/samples/modules/chre/sample.yaml @@ -24,5 +24,5 @@ tests: - "EchoApp::nanoappEnd\\(\\)" - "I: Exiting EventLoop.*" integration_platforms: - - native_posix + - native_sim filter: CONFIG_FULL_LIBC_SUPPORTED diff --git a/samples/modules/index.rst b/samples/modules/index.rst index 79828d002a2..5316bb6e244 100644 --- a/samples/modules/index.rst +++ b/samples/modules/index.rst @@ -4,7 +4,8 @@ External Module Samples ####################### .. toctree:: - :maxdepth: 2 + :titlesonly: + :maxdepth: 1 :glob: **/* diff --git a/samples/modules/lvgl/accelerometer_chart/CMakeLists.txt b/samples/modules/lvgl/accelerometer_chart/CMakeLists.txt new file mode 100644 index 00000000000..6c4a568b1e5 --- /dev/null +++ b/samples/modules/lvgl/accelerometer_chart/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(accelerometer_chart) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/modules/lvgl/accelerometer_chart/Kconfig b/samples/modules/lvgl/accelerometer_chart/Kconfig new file mode 100644 index 00000000000..bba256103be --- /dev/null +++ b/samples/modules/lvgl/accelerometer_chart/Kconfig @@ -0,0 +1,17 @@ +# Copyright (c) 2023 Benjamin Cabé +# SPDX-License-Identifier: Apache-2.0 + +config SAMPLE_CHART_POINTS_PER_SERIES + int "Number of points per series" + default 50 + range 10 200 + help + Maximum number of points per series in the accelerometer chart. + Warning: More points means more memory usage, and slower rendering! + +config SAMPLE_ACCEL_SAMPLING_RATE + int "Accelerometer sampling rate (Hz)" + default 50 + range 1 100 + +source "Kconfig.zephyr" diff --git a/samples/modules/lvgl/accelerometer_chart/README.rst b/samples/modules/lvgl/accelerometer_chart/README.rst new file mode 100644 index 00000000000..69f90b4f4de --- /dev/null +++ b/samples/modules/lvgl/accelerometer_chart/README.rst @@ -0,0 +1,51 @@ +.. zephyr:code-sample:: lvgl-accelerometer-chart + :name: LVGL line chart with accelerometer data + :relevant-api: display_interface sensor_interface + + Display acceleration data on a real-time chart using LVGL. + +Overview +******** + +A sample application that demonstrates how to use LVGL and the :ref:`sensor API ` to +display acceleration data on a line chart that is updated in real time. + +This sample creates a line chart with three series, one for each axis of the accelerometer. An LVGL +timer fetches the latest acceleration data from the sensor every 20 ms (default value) and updates +the chart. The update period is configurable, see +:ref:`lvgl_accelerometer_chart_building_and_running` below. + +Requirements +************ + +* A board with a display. +* A sensor that provides acceleration data (:c:enumerator:`SENSOR_CHAN_ACCEL_XYZ`) and available + under the ``&accel0`` Devicetree alias. + +.. note:: + + A Devicetree overlay declaring an emulated BMI160 accelerometer is provided for the + ``native_posix*`` and ``native_sim*`` board variants, making it possible to run this sample on + your local machine. + +.. _lvgl_accelerometer_chart_building_and_running: + +Building and Running +******************** + +The maximum number of points to display for each series and the sampling rate of the +accelerometer can be configured using the :kconfig:option:`CONFIG_SAMPLE_CHART_POINTS_PER_SERIES` +and :kconfig:option:`CONFIG_SAMPLE_ACCEL_SAMPLING_RATE` Kconfig options, respectively. + +The default sampling rate is 50 Hz, and the default maximum number of points per series is 50. + +The demo can be built as follows (note how in this particular case the sampling rate is set to a +custom value of 20 Hz): + +.. zephyr-app-commands:: + :zephyr-app: samples/modules/lvgl/accelerometer_chart + :host-os: unix + :board: native_sim + :gen-args: -DCONFIG_SAMPLE_ACCEL_SAMPLING_RATE=20 + :goals: run + :compact: diff --git a/samples/modules/lvgl/accelerometer_chart/boards/native_posix.conf b/samples/modules/lvgl/accelerometer_chart/boards/native_posix.conf new file mode 100644 index 00000000000..e01c80e9dfa --- /dev/null +++ b/samples/modules/lvgl/accelerometer_chart/boards/native_posix.conf @@ -0,0 +1 @@ +CONFIG_BMI160_TRIGGER_NONE=y diff --git a/samples/modules/lvgl/accelerometer_chart/boards/native_posix.overlay b/samples/modules/lvgl/accelerometer_chart/boards/native_posix.overlay new file mode 100644 index 00000000000..dc4174b58d7 --- /dev/null +++ b/samples/modules/lvgl/accelerometer_chart/boards/native_posix.overlay @@ -0,0 +1,16 @@ +/* Copyright (c) 2023 Benjamin Cabé + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + accel0 = &bmi_i2c; + }; +}; + +&i2c0 { + bmi_i2c: bmi@68 { + compatible = "bosch,bmi160"; + reg = <0x68>; + }; +}; diff --git a/samples/modules/lvgl/accelerometer_chart/boards/native_posix_64.conf b/samples/modules/lvgl/accelerometer_chart/boards/native_posix_64.conf new file mode 100644 index 00000000000..e01c80e9dfa --- /dev/null +++ b/samples/modules/lvgl/accelerometer_chart/boards/native_posix_64.conf @@ -0,0 +1 @@ +CONFIG_BMI160_TRIGGER_NONE=y diff --git a/samples/modules/lvgl/accelerometer_chart/boards/native_posix_64.overlay b/samples/modules/lvgl/accelerometer_chart/boards/native_posix_64.overlay new file mode 100644 index 00000000000..2b055bf3de6 --- /dev/null +++ b/samples/modules/lvgl/accelerometer_chart/boards/native_posix_64.overlay @@ -0,0 +1 @@ +#include "native_posix.overlay" diff --git a/samples/modules/lvgl/accelerometer_chart/boards/native_sim.conf b/samples/modules/lvgl/accelerometer_chart/boards/native_sim.conf new file mode 100644 index 00000000000..e01c80e9dfa --- /dev/null +++ b/samples/modules/lvgl/accelerometer_chart/boards/native_sim.conf @@ -0,0 +1 @@ +CONFIG_BMI160_TRIGGER_NONE=y diff --git a/samples/modules/lvgl/accelerometer_chart/boards/native_sim.overlay b/samples/modules/lvgl/accelerometer_chart/boards/native_sim.overlay new file mode 100644 index 00000000000..2b055bf3de6 --- /dev/null +++ b/samples/modules/lvgl/accelerometer_chart/boards/native_sim.overlay @@ -0,0 +1 @@ +#include "native_posix.overlay" diff --git a/samples/modules/lvgl/accelerometer_chart/boards/native_sim_64.conf b/samples/modules/lvgl/accelerometer_chart/boards/native_sim_64.conf new file mode 100644 index 00000000000..e01c80e9dfa --- /dev/null +++ b/samples/modules/lvgl/accelerometer_chart/boards/native_sim_64.conf @@ -0,0 +1 @@ +CONFIG_BMI160_TRIGGER_NONE=y diff --git a/samples/modules/lvgl/accelerometer_chart/boards/native_sim_64.overlay b/samples/modules/lvgl/accelerometer_chart/boards/native_sim_64.overlay new file mode 100644 index 00000000000..6a3daca3241 --- /dev/null +++ b/samples/modules/lvgl/accelerometer_chart/boards/native_sim_64.overlay @@ -0,0 +1 @@ +#include "native_sim.overlay" diff --git a/samples/modules/lvgl/accelerometer_chart/prj.conf b/samples/modules/lvgl/accelerometer_chart/prj.conf new file mode 100644 index 00000000000..a5d6e2e831e --- /dev/null +++ b/samples/modules/lvgl/accelerometer_chart/prj.conf @@ -0,0 +1,9 @@ +CONFIG_MAIN_STACK_SIZE=4096 +CONFIG_LOG=y + +CONFIG_LVGL=y +CONFIG_LV_Z_MEM_POOL_SIZE=16384 + +CONFIG_DISPLAY=y +CONFIG_INPUT=y +CONFIG_SENSOR=y diff --git a/samples/modules/lvgl/accelerometer_chart/sample.yaml b/samples/modules/lvgl/accelerometer_chart/sample.yaml new file mode 100644 index 00000000000..943a242d00c --- /dev/null +++ b/samples/modules/lvgl/accelerometer_chart/sample.yaml @@ -0,0 +1,18 @@ +sample: + description: Real-time visualization of acceleration data using LVGL chart widget + name: LVGL acceleration chart +tests: + sample.modules.lvgl.accelerometer_chart: + filter: dt_chosen_enabled("zephyr,display") and dt_alias_exists("accel0") + min_flash: 250 + min_ram: 32 + harness: none + tags: + - samples + - display + - gui + - lvgl + modules: + - lvgl + integration_platforms: + - native_sim_64 diff --git a/samples/modules/lvgl/accelerometer_chart/src/main.c b/samples/modules/lvgl/accelerometer_chart/src/main.c new file mode 100644 index 00000000000..2aaee9fad0d --- /dev/null +++ b/samples/modules/lvgl/accelerometer_chart/src/main.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2023 Benjamin Cabé + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(app, CONFIG_LOG_DEFAULT_LEVEL); + +static lv_obj_t *chart1; +static lv_chart_series_t *ser_x; +static lv_chart_series_t *ser_y; +static lv_chart_series_t *ser_z; +static lv_timer_t *sensor_timer; + +const struct device *accel_sensor; + +/* Timer handler: fetches sensor data and appends it to the chart */ +static void sensor_timer_cb(lv_timer_t *timer) +{ + struct sensor_value accel[3]; + int rc = sensor_sample_fetch(accel_sensor); + + if (rc == 0) { + rc = sensor_channel_get(accel_sensor, SENSOR_CHAN_ACCEL_XYZ, accel); + } + if (rc < 0) { + LOG_ERR("ERROR: Update failed: %d\n", rc); + return; + } + lv_chart_set_next_value(chart1, ser_x, sensor_value_to_double(&accel[0])); + lv_chart_set_next_value(chart1, ser_y, sensor_value_to_double(&accel[1])); + lv_chart_set_next_value(chart1, ser_z, sensor_value_to_double(&accel[2])); +} + +static void create_accelerometer_chart(lv_obj_t *parent) +{ + chart1 = lv_chart_create(parent); + lv_obj_set_size(chart1, LV_HOR_RES, LV_VER_RES); + lv_chart_set_type(chart1, LV_CHART_TYPE_LINE); + lv_chart_set_div_line_count(chart1, 5, 8); + lv_chart_set_range(chart1, LV_CHART_AXIS_PRIMARY_Y, -20, 20); /* roughly -/+ 2G */ + lv_chart_set_update_mode(chart1, LV_CHART_UPDATE_MODE_SHIFT); + + ser_x = lv_chart_add_series(chart1, lv_palette_main(LV_PALETTE_RED), + LV_CHART_AXIS_PRIMARY_Y); + ser_y = lv_chart_add_series(chart1, lv_palette_main(LV_PALETTE_BLUE), + LV_CHART_AXIS_PRIMARY_Y); + ser_z = lv_chart_add_series(chart1, lv_palette_main(LV_PALETTE_GREEN), + LV_CHART_AXIS_PRIMARY_Y); + + lv_chart_set_point_count(chart1, CONFIG_SAMPLE_CHART_POINTS_PER_SERIES); + + /* Do not display point markers on the data */ + lv_obj_set_style_size(chart1, 0, LV_PART_INDICATOR); +} + +int main(void) +{ + const struct device *display_dev; + + display_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display)); + if (!device_is_ready(display_dev)) { + LOG_ERR("Device not ready, aborting test"); + return -ENODEV; + } + + accel_sensor = DEVICE_DT_GET(DT_ALIAS(accel0)); + if (!device_is_ready(accel_sensor)) { + LOG_ERR("Device %s is not ready\n", accel_sensor->name); + return -ENODEV; + } + + create_accelerometer_chart(lv_scr_act()); + sensor_timer = lv_timer_create(sensor_timer_cb, + 1000 / CONFIG_SAMPLE_ACCEL_SAMPLING_RATE, + NULL); + lv_task_handler(); + display_blanking_off(display_dev); + + while (1) { + k_msleep(lv_task_handler()); + } + + return 0; +} diff --git a/samples/modules/lvgl/demos/CMakeLists.txt b/samples/modules/lvgl/demos/CMakeLists.txt new file mode 100644 index 00000000000..c80e3b4364b --- /dev/null +++ b/samples/modules/lvgl/demos/CMakeLists.txt @@ -0,0 +1,90 @@ +# Copyright (c) 2023 Fabian Blatz +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(lvgl_sample) + +set(LVGL_DIR ${ZEPHYR_LVGL_MODULE_DIR}) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) + +target_include_directories(app PRIVATE + ${LVGL_DIR}/demos/ +) + +target_sources_ifdef(CONFIG_LV_USE_DEMO_MUSIC app PRIVATE + ${LVGL_DIR}/demos/music/lv_demo_music_list.c + ${LVGL_DIR}/demos/music/lv_demo_music.c + ${LVGL_DIR}/demos/music/lv_demo_music_main.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_btn_next.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_wave_top_large.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_icon_4_large.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_icon_4.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_corner_right.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_cover_1.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_slider_knob_large.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_icon_3.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_btn_pause.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_btn_pause_large.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_wave_bottom_large.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_icon_2_large.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_btn_list_play_large.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_wave_top.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_btn_play_large.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_cover_1_large.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_wave_bottom.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_corner_left_large.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_btn_play.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_list_border.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_icon_2.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_btn_next_large.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_btn_list_play.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_list_border_large.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_btn_rnd.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_cover_3.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_btn_prev_large.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_btn_loop.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_icon_1.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_slider_knob.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_corner_right_large.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_btn_corner_large.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_corner_left.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_cover_2_large.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_icon_3_large.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_icon_1_large.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_cover_2.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_btn_prev.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_btn_rnd_large.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_btn_list_pause_large.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_cover_3_large.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_btn_list_pause.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_logo.c + ${LVGL_DIR}/demos/music/assets/img_lv_demo_music_btn_loop_large.c +) + +target_sources_ifdef(CONFIG_LV_USE_DEMO_BENCHMARK app PRIVATE + ${LVGL_DIR}/demos/benchmark/lv_demo_benchmark.c + ${LVGL_DIR}/demos/benchmark/assets/img_benchmark_cogwheel_indexed16.c + ${LVGL_DIR}/demos/benchmark/assets/lv_font_bechmark_montserrat_28_compr_az.c.c + ${LVGL_DIR}/demos/benchmark/assets/lv_font_bechmark_montserrat_16_compr_az.c.c + ${LVGL_DIR}/demos/benchmark/assets/img_benchmark_cogwheel_argb.c + ${LVGL_DIR}/demos/benchmark/assets/img_benchmark_cogwheel_alpha16.c + ${LVGL_DIR}/demos/benchmark/assets/img_benchmark_cogwheel_rgb.c + ${LVGL_DIR}/demos/benchmark/assets/lv_font_bechmark_montserrat_12_compr_az.c.c + ${LVGL_DIR}/demos/benchmark/assets/img_benchmark_cogwheel_chroma_keyed.c + ${LVGL_DIR}/demos/benchmark/assets/img_benchmark_cogwheel_rgb565a8.c +) + +target_sources_ifdef(CONFIG_LV_USE_DEMO_STRESS app PRIVATE + ${LVGL_DIR}/demos/stress/lv_demo_stress.c +) + +target_sources_ifdef(CONFIG_LV_USE_DEMO_WIDGETS app PRIVATE + ${LVGL_DIR}/demos/widgets/assets/img_clothes.c + ${LVGL_DIR}/demos/widgets/assets/img_demo_widgets_avatar.c + ${LVGL_DIR}/demos/widgets/assets/img_lvgl_logo.c + ${LVGL_DIR}/demos/widgets/lv_demo_widgets.c +) diff --git a/samples/modules/lvgl/demos/Kconfig b/samples/modules/lvgl/demos/Kconfig new file mode 100644 index 00000000000..6f61694f651 --- /dev/null +++ b/samples/modules/lvgl/demos/Kconfig @@ -0,0 +1,36 @@ +# Copyright (c) 2023 Fabian Blatz +# SPDX-License-Identifier: Apache-2.0 + +choice LV_Z_DEMO + prompt "LVGL demo to build" + default LV_Z_DEMO_MUSIC + help + Demo application to build. + +config LV_Z_DEMO_MUSIC + bool "LVGL music demo" + select LV_USE_DEMO_MUSIC + help + Build music player demo application. + +config LV_Z_DEMO_BENCHMARK + bool "LVGL benchmark demo" + select LV_USE_DEMO_BENCHMARK + help + Build benchmarking demo application. + +config LV_Z_DEMO_STRESS + bool "LVGL stress demo" + select LV_USE_DEMO_STRESS + help + Build stress testing demo application. + +config LV_Z_DEMO_WIDGETS + bool "LVGL widgets demo" + select LV_USE_DEMO_WIDGETS + help + Build stress testing demo application. + +endchoice + +source "Kconfig.zephyr" diff --git a/samples/modules/lvgl/demos/README.rst b/samples/modules/lvgl/demos/README.rst new file mode 100644 index 00000000000..cbc97616808 --- /dev/null +++ b/samples/modules/lvgl/demos/README.rst @@ -0,0 +1,61 @@ +.. zephyr:code-sample:: lvgl-demos + :name: LVGL demos + :relevant-api: display_interface + + Run LVGL built-in demos. + +Overview +******** + +A sample showcasing upstream LVGL demos. + +* Music + The music player demo shows what kind of modern, smartphone-like user interfaces can be created on LVGL. +* Benchmark + The benchmark demo tests the performance in various cases. For example rectangle, border, shadow, text, image blending, image transformation, blending modes, etc. +* Stress + A stress test for LVGL. It contains a lot of object creation, deletion, animations, styles usage, and so on. It can be used if there is any memory corruption during heavy usage or any memory leaks. +* Widgets + Shows how the widgets look like out of the box using the built-in material theme. + +Requirements +************ + +* A board with display, ideally with 480x272 resolution or higher. + +Building and Running +******************** + +These demos can be built as follows: + +.. zephyr-app-commands:: + :zephyr-app: samples/modules/lvgl/demos + :host-os: unix + :board: native_sim + :gen-args: -DCONFIG_LV_Z_DEMO_MUSIC=y + :goals: run + :compact: + +.. zephyr-app-commands:: + :zephyr-app: samples/modules/lvgl/demos + :host-os: unix + :board: native_sim + :gen-args: -DCONFIG_LV_Z_DEMO_BENCHMARK=y + :goals: run + :compact: + +.. zephyr-app-commands:: + :zephyr-app: samples/modules/lvgl/demos + :host-os: unix + :board: native_sim + :gen-args: -DCONFIG_LV_Z_DEMO_STRESS=y + :goals: run + :compact: + +.. zephyr-app-commands:: + :zephyr-app: samples/modules/lvgl/demos + :host-os: unix + :board: native_sim + :gen-args: -DCONFIG_LV_Z_DEMO_WIDGETS=y + :goals: run + :compact: diff --git a/samples/modules/lvgl/demos/boards/m5stack_core2.conf b/samples/modules/lvgl/demos/boards/m5stack_core2.conf new file mode 100644 index 00000000000..c1da6a053d2 --- /dev/null +++ b/samples/modules/lvgl/demos/boards/m5stack_core2.conf @@ -0,0 +1,4 @@ +# Copyright 2023 Fabian Blatz +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_MAIN_STACK_SIZE=4096 diff --git a/samples/modules/lvgl/demos/boards/mimxrt1060_evk.conf b/samples/modules/lvgl/demos/boards/mimxrt1060_evk.conf new file mode 100644 index 00000000000..30b4edca858 --- /dev/null +++ b/samples/modules/lvgl/demos/boards/mimxrt1060_evk.conf @@ -0,0 +1,8 @@ +# Copyright 2023 Fabian Blatz +# SPDX-License-Identifier: Apache-2.0 + +# Enable PXP DMA engine and set rotation angle to 0 degrees. +# This allows us to verify the DMA driver functions without altering +# the output image +CONFIG_DMA=y +CONFIG_MCUX_ELCDIF_PXP=y diff --git a/samples/modules/lvgl/demos/boards/mimxrt1170_evk_cm7.conf b/samples/modules/lvgl/demos/boards/mimxrt1170_evk_cm7.conf new file mode 100644 index 00000000000..30b4edca858 --- /dev/null +++ b/samples/modules/lvgl/demos/boards/mimxrt1170_evk_cm7.conf @@ -0,0 +1,8 @@ +# Copyright 2023 Fabian Blatz +# SPDX-License-Identifier: Apache-2.0 + +# Enable PXP DMA engine and set rotation angle to 0 degrees. +# This allows us to verify the DMA driver functions without altering +# the output image +CONFIG_DMA=y +CONFIG_MCUX_ELCDIF_PXP=y diff --git a/samples/modules/lvgl/demos/boards/native_posix.conf b/samples/modules/lvgl/demos/boards/native_posix.conf new file mode 100644 index 00000000000..a99f38b8d84 --- /dev/null +++ b/samples/modules/lvgl/demos/boards/native_posix.conf @@ -0,0 +1,4 @@ +# Copyright 2023 Fabian Blatz +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_LV_COLOR_DEPTH_32=y diff --git a/samples/modules/lvgl/demos/boards/native_posix.overlay b/samples/modules/lvgl/demos/boards/native_posix.overlay new file mode 100644 index 00000000000..eab17f916bd --- /dev/null +++ b/samples/modules/lvgl/demos/boards/native_posix.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2023, Fabian Blatz + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&sdl_dc { + compatible = "zephyr,sdl-dc"; + height = <272>; + width = <480>; +}; diff --git a/samples/modules/lvgl/demos/boards/native_posix_64.conf b/samples/modules/lvgl/demos/boards/native_posix_64.conf new file mode 100644 index 00000000000..a99f38b8d84 --- /dev/null +++ b/samples/modules/lvgl/demos/boards/native_posix_64.conf @@ -0,0 +1,4 @@ +# Copyright 2023 Fabian Blatz +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_LV_COLOR_DEPTH_32=y diff --git a/samples/modules/lvgl/demos/boards/native_posix_64.overlay b/samples/modules/lvgl/demos/boards/native_posix_64.overlay new file mode 100644 index 00000000000..ab50aa66f82 --- /dev/null +++ b/samples/modules/lvgl/demos/boards/native_posix_64.overlay @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2023, Fabian Blatz + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "native_posix.overlay" diff --git a/samples/modules/lvgl/demos/boards/native_sim.conf b/samples/modules/lvgl/demos/boards/native_sim.conf new file mode 100644 index 00000000000..a99f38b8d84 --- /dev/null +++ b/samples/modules/lvgl/demos/boards/native_sim.conf @@ -0,0 +1,4 @@ +# Copyright 2023 Fabian Blatz +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_LV_COLOR_DEPTH_32=y diff --git a/samples/modules/lvgl/demos/boards/native_sim.overlay b/samples/modules/lvgl/demos/boards/native_sim.overlay new file mode 100644 index 00000000000..ab50aa66f82 --- /dev/null +++ b/samples/modules/lvgl/demos/boards/native_sim.overlay @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2023, Fabian Blatz + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "native_posix.overlay" diff --git a/samples/modules/lvgl/demos/boards/native_sim_64.conf b/samples/modules/lvgl/demos/boards/native_sim_64.conf new file mode 100644 index 00000000000..a99f38b8d84 --- /dev/null +++ b/samples/modules/lvgl/demos/boards/native_sim_64.conf @@ -0,0 +1,4 @@ +# Copyright 2023 Fabian Blatz +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_LV_COLOR_DEPTH_32=y diff --git a/samples/modules/lvgl/demos/boards/native_sim_64.overlay b/samples/modules/lvgl/demos/boards/native_sim_64.overlay new file mode 100644 index 00000000000..47fdc4be34c --- /dev/null +++ b/samples/modules/lvgl/demos/boards/native_sim_64.overlay @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2023, Fabian Blatz + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "native_sim.overlay" diff --git a/samples/modules/lvgl/demos/prj.conf b/samples/modules/lvgl/demos/prj.conf new file mode 100644 index 00000000000..3392d5c4fd3 --- /dev/null +++ b/samples/modules/lvgl/demos/prj.conf @@ -0,0 +1,18 @@ +CONFIG_MAIN_STACK_SIZE=4096 +CONFIG_LOG=y +CONFIG_SHELL=y + +CONFIG_LVGL=y +CONFIG_LV_Z_MEM_POOL_SIZE=49152 +CONFIG_LV_Z_SHELL=y +CONFIG_LV_USE_MONKEY=y + +CONFIG_DISPLAY=y +CONFIG_INPUT=y + +CONFIG_LV_FONT_MONTSERRAT_12=y +CONFIG_LV_FONT_MONTSERRAT_14=y +CONFIG_LV_FONT_MONTSERRAT_16=y + +# Benchmark Demo +CONFIG_LV_USE_FONT_COMPRESSED=y diff --git a/samples/modules/lvgl/demos/sample.yaml b/samples/modules/lvgl/demos/sample.yaml new file mode 100644 index 00000000000..b928d9f37f0 --- /dev/null +++ b/samples/modules/lvgl/demos/sample.yaml @@ -0,0 +1,19 @@ +sample: + description: LVGL sample, containing all upstream demos + name: LVGL demos +common: + modules: + - lvgl + harness: none + filter: dt_chosen_enabled("zephyr,display") + tags: samples lvgl display gui +tests: + sample.modules.lvgl.demo_music: + extra_configs: + - CONFIG_LV_Z_DEMO_MUSIC=y + sample.modules.lvgl.demo_benchmark: + extra_configs: + - CONFIG_LV_Z_DEMO_BENCHMARK=y + sample.modules.lvgl.demo_stress: + extra_configs: + - CONFIG_LV_Z_DEMO_STRESS=y diff --git a/samples/modules/lvgl/demos/src/main.c b/samples/modules/lvgl/demos/src/main.c new file mode 100644 index 00000000000..2e3785d8298 --- /dev/null +++ b/samples/modules/lvgl/demos/src/main.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 Fabian Blatz + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL +#include +LOG_MODULE_REGISTER(app); + +int main(void) +{ + const struct device *display_dev; + + display_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display)); + if (!device_is_ready(display_dev)) { + LOG_ERR("Device not ready, aborting test"); + return 0; + } + +#if defined(CONFIG_LV_USE_DEMO_MUSIC) + lv_demo_music(); +#elif defined(CONFIG_LV_USE_DEMO_BENCHMARK) + lv_demo_benchmark(); +#elif defined(CONFIG_LV_USE_DEMO_STRESS) + lv_demo_stress(); +#elif defined(CONFIG_LV_USE_DEMO_WIDGETS) + lv_demo_widgets(); +#else +#error Enable one of the demos CONFIG_LV_USE_DEMO_MUSIC, CONFIG_LV_USE_DEMO_BENCHMARK ,\ + CONFIG_LV_USE_DEMO_STRESS, or CONFIG_LV_USE_DEMO_WIDGETS +#endif + + lv_task_handler(); + display_blanking_off(display_dev); + + while (1) { + k_msleep(lv_task_handler()); + } + + return 0; +} diff --git a/samples/modules/nanopb/CMakeLists.txt b/samples/modules/nanopb/CMakeLists.txt index 67caa89ac80..a3180075d8e 100644 --- a/samples/modules/nanopb/CMakeLists.txt +++ b/samples/modules/nanopb/CMakeLists.txt @@ -5,15 +5,10 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(nanopb_sample) -# Note that here, we're adding CMAKE_SOURCE_DIR to the include path for nanopb. -# This is needed because the below call to nanopb_generate_cpp() is using -# 'RELPATH .' -set(NANOPB_OPTIONS "-I${CMAKE_SOURCE_DIR}") -nanopb_generate_cpp(proto_sources proto_headers RELPATH . - src/simple.proto -) -# we need to be able to include generated header files -zephyr_library_include_directories(${CMAKE_CURRENT_BINARY_DIR}) +list(APPEND CMAKE_MODULE_PATH ${ZEPHYR_BASE}/modules/nanopb) +include(nanopb) + +zephyr_nanopb_sources(app src/simple.proto) FILE(GLOB app_sources src/*.c) -target_sources(app PRIVATE ${proto_sources} ${app_sources}) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/modules/nanopb/README.rst b/samples/modules/nanopb/README.rst index 071498668a4..6e6d567f29c 100644 --- a/samples/modules/nanopb/README.rst +++ b/samples/modules/nanopb/README.rst @@ -22,7 +22,7 @@ make sure the ``protoc`` executable is installed and available. Use ``apt`` to install dependency: - .. code-block:: bash + .. code-block:: shell sudo apt install protobuf-compiler @@ -30,7 +30,7 @@ make sure the ``protoc`` executable is installed and available. Use ``brew`` to install dependency: - .. code-block:: bash + .. code-block:: shell brew install protobuf @@ -38,10 +38,19 @@ make sure the ``protoc`` executable is installed and available. Use ``choco`` to install dependency: - .. code-block:: console + .. code-block:: shell choco install protoc + +Additionally Nanopb is an optional module and needs to be added explicitly to the workspace: + +.. code-block:: shell + + west config manifest.project-filter -- +nanopb + west update + + Building and Running ******************** diff --git a/samples/modules/nanopb/sample.yaml b/samples/modules/nanopb/sample.yaml index 2ea497b0f10..eb990848d18 100644 --- a/samples/modules/nanopb/sample.yaml +++ b/samples/modules/nanopb/sample.yaml @@ -15,5 +15,5 @@ tests: - samples - nanopb integration_platforms: - - native_posix - - native_posix_64 + - native_sim + - native_sim_64 diff --git a/samples/modules/tflite-micro/hello_world/README.rst b/samples/modules/tflite-micro/hello_world/README.rst index 6ab9bcbbc2b..9d6fff4db93 100644 --- a/samples/modules/tflite-micro/hello_world/README.rst +++ b/samples/modules/tflite-micro/hello_world/README.rst @@ -94,7 +94,7 @@ TensorFlow, you must enable the below Kconfig options in your :file:`prj.conf`: .. code-block:: kconfig CONFIG_CPP=y - CONFIG_NEWLIB_LIBC=y + CONFIG_REQUIRES_FULL_LIBC=y CONFIG_TENSORFLOW_LITE_MICRO=y Note that the CMSIS-NN kernel sample demonstrates how to use CMSIS-NN optimized kernels with diff --git a/samples/modules/tflite-micro/hello_world/prj.conf b/samples/modules/tflite-micro/hello_world/prj.conf index 33f91a57e72..c4652d4f7c3 100644 --- a/samples/modules/tflite-micro/hello_world/prj.conf +++ b/samples/modules/tflite-micro/hello_world/prj.conf @@ -13,5 +13,6 @@ # limitations under the License. # ==============================================================================s CONFIG_CPP=y +CONFIG_STD_CPP17=y CONFIG_TENSORFLOW_LITE_MICRO=y CONFIG_MAIN_STACK_SIZE=2048 diff --git a/samples/modules/tflite-micro/hello_world/sample.yaml b/samples/modules/tflite-micro/hello_world/sample.yaml index ed70d085631..bfd142f6702 100644 --- a/samples/modules/tflite-micro/hello_world/sample.yaml +++ b/samples/modules/tflite-micro/hello_world/sample.yaml @@ -20,7 +20,7 @@ tests: integration_platforms: - qemu_x86 tags: tensorflow - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED sample.tensorflow.helloworld.cmsis_nn: tags: tensorflow platform_allow: mps3_an547 diff --git a/samples/modules/tflite-micro/hello_world/src/main_functions.cpp b/samples/modules/tflite-micro/hello_world/src/main_functions.cpp index 7ebfea59c7c..1666e161cf9 100644 --- a/samples/modules/tflite-micro/hello_world/src/main_functions.cpp +++ b/samples/modules/tflite-micro/hello_world/src/main_functions.cpp @@ -16,18 +16,17 @@ #include "main_functions.h" -#include +#include #include "constants.h" #include "model.hpp" #include "output_handler.hpp" -#include +#include #include #include #include /* Globals, used for compatibility with Arduino-style sketches. */ namespace { - tflite::ErrorReporter *error_reporter = nullptr; const tflite::Model *model = nullptr; tflite::MicroInterpreter *interpreter = nullptr; TfLiteTensor *input = nullptr; @@ -41,40 +40,32 @@ namespace { /* The name of this function is important for Arduino compatibility. */ void setup(void) { - /* Set up logging. Google style is to avoid globals or statics because of - * lifetime uncertainty, but since this has a trivial destructor it's okay. - * NOLINTNEXTLINE(runtime-global-variables) - */ - static tflite::MicroErrorReporter micro_error_reporter; - - error_reporter = µ_error_reporter; - /* Map the model into a usable data structure. This doesn't involve any * copying or parsing, it's a very lightweight operation. */ model = tflite::GetModel(g_model); if (model->version() != TFLITE_SCHEMA_VERSION) { - TF_LITE_REPORT_ERROR(error_reporter, - "Model provided is schema version %d not equal " - "to supported version %d.", - model->version(), TFLITE_SCHEMA_VERSION); + MicroPrintf("Model provided is schema version %d not equal " + "to supported version %d.", + model->version(), TFLITE_SCHEMA_VERSION); return; } - /* This pulls in all the operation implementations we need. + /* This pulls in the operation implementations we need. * NOLINTNEXTLINE(runtime-global-variables) */ - static tflite::AllOpsResolver resolver; + static tflite::MicroMutableOpResolver <1> resolver; + resolver.AddFullyConnected(); /* Build an interpreter to run the model with. */ static tflite::MicroInterpreter static_interpreter( - model, resolver, tensor_arena, kTensorArenaSize, error_reporter); + model, resolver, tensor_arena, kTensorArenaSize); interpreter = &static_interpreter; /* Allocate memory from the tensor_arena for the model's tensors. */ TfLiteStatus allocate_status = interpreter->AllocateTensors(); if (allocate_status != kTfLiteOk) { - TF_LITE_REPORT_ERROR(error_reporter, "AllocateTensors() failed"); + MicroPrintf("AllocateTensors() failed"); return; } @@ -106,8 +97,7 @@ void loop(void) /* Run inference, and report any error */ TfLiteStatus invoke_status = interpreter->Invoke(); if (invoke_status != kTfLiteOk) { - TF_LITE_REPORT_ERROR(error_reporter, "Invoke failed on x: %f\n", - static_cast < double > (x)); + MicroPrintf("Invoke failed on x: %f\n", static_cast < double > (x)); return; } @@ -119,7 +109,7 @@ void loop(void) /* Output the results. A custom HandleOutput function can be implemented * for each supported hardware target. */ - HandleOutput(error_reporter, x, y); + HandleOutput(x, y); /* Increment the inference_counter, and reset it if we have reached * the total number per cycle diff --git a/samples/modules/tflite-micro/hello_world/src/output_handler.cpp b/samples/modules/tflite-micro/hello_world/src/output_handler.cpp index c26f6a019fe..ef7e4f0d02e 100644 --- a/samples/modules/tflite-micro/hello_world/src/output_handler.cpp +++ b/samples/modules/tflite-micro/hello_world/src/output_handler.cpp @@ -16,11 +16,10 @@ #include "output_handler.hpp" -void HandleOutput(tflite::ErrorReporter *error_reporter, float x_value, - float y_value) +void HandleOutput(float x_value, float y_value) { /* Log the current X and Y values */ - TF_LITE_REPORT_ERROR(error_reporter, "x_value: %f, y_value: %f\n", - static_cast < double > (x_value), - static_cast < double > (y_value)); + MicroPrintf("x_value: %f, y_value: %f\n", + static_cast < double > (x_value), + static_cast < double > (y_value)); } diff --git a/samples/modules/tflite-micro/hello_world/src/output_handler.hpp b/samples/modules/tflite-micro/hello_world/src/output_handler.hpp index dbf51ebe8fb..0c16c3c18b1 100644 --- a/samples/modules/tflite-micro/hello_world/src/output_handler.hpp +++ b/samples/modules/tflite-micro/hello_world/src/output_handler.hpp @@ -18,10 +18,9 @@ #define TENSORFLOW_LITE_MICRO_EXAMPLES_HELLO_WORLD_OUTPUT_HANDLER_H_ #include -#include +#include /* Called by the main loop to produce some output based on the x and y values */ -void HandleOutput(tflite::ErrorReporter *error_reporter, float x_value, - float y_value); +void HandleOutput(float x_value, float y_value); #endif /* TENSORFLOW_LITE_MICRO_EXAMPLES_HELLO_WORLD_OUTPUT_HANDLER_H_ */ diff --git a/samples/modules/tflite-micro/magic_wand/README.rst b/samples/modules/tflite-micro/magic_wand/README.rst index b020f23d9b1..4a3dadbf7c4 100644 --- a/samples/modules/tflite-micro/magic_wand/README.rst +++ b/samples/modules/tflite-micro/magic_wand/README.rst @@ -107,7 +107,7 @@ TensorFlow, you must enable the below Kconfig options in your :file:`prj.conf`: .. code-block:: kconfig CONFIG_CPP=y - CONFIG_NEWLIB_LIBC=y + CONFIG_REQUIRES_FULL_LIBC=y CONFIG_TENSORFLOW_LITE_MICRO=y Training diff --git a/samples/modules/tflite-micro/magic_wand/prj.conf b/samples/modules/tflite-micro/magic_wand/prj.conf index 5801d104a49..2774abb66e2 100644 --- a/samples/modules/tflite-micro/magic_wand/prj.conf +++ b/samples/modules/tflite-micro/magic_wand/prj.conf @@ -13,7 +13,8 @@ # limitations under the License. # ============================================================================== CONFIG_CPP=y -CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y +CONFIG_STD_CPP17=y +CONFIG_REQUIRES_FLOAT_PRINTF=y CONFIG_SENSOR=y CONFIG_NETWORKING=n CONFIG_MAIN_STACK_SIZE=4096 diff --git a/samples/modules/tflite-micro/magic_wand/src/accelerometer_handler.cpp b/samples/modules/tflite-micro/magic_wand/src/accelerometer_handler.cpp index 894cba004ea..0491f7a7962 100644 --- a/samples/modules/tflite-micro/magic_wand/src/accelerometer_handler.cpp +++ b/samples/modules/tflite-micro/magic_wand/src/accelerometer_handler.cpp @@ -33,7 +33,7 @@ float bufz[BUFLEN] = { 0.0f }; bool initial = true; -TfLiteStatus SetupAccelerometer(tflite::ErrorReporter *error_reporter) +TfLiteStatus SetupAccelerometer() { if (!device_is_ready(sensor)) { printk("%s: device not ready.\n", sensor->name); @@ -41,18 +41,16 @@ TfLiteStatus SetupAccelerometer(tflite::ErrorReporter *error_reporter) } if (sensor == NULL) { - TF_LITE_REPORT_ERROR(error_reporter, - "Failed to get accelerometer, name: %s\n", - sensor->name); + MicroPrintf("Failed to get accelerometer, name: %s\n", + sensor->name); } else { - TF_LITE_REPORT_ERROR(error_reporter, "Got accelerometer, name: %s\n", - sensor->name); + MicroPrintf("Got accelerometer, name: %s\n", + sensor->name); } return kTfLiteOk; } -bool ReadAccelerometer(tflite::ErrorReporter *error_reporter, float *input, - int length) +bool ReadAccelerometer(float *input, int length) { int rc; struct sensor_value accel[3]; @@ -60,7 +58,7 @@ bool ReadAccelerometer(tflite::ErrorReporter *error_reporter, float *input, rc = sensor_sample_fetch(sensor); if (rc < 0) { - TF_LITE_REPORT_ERROR(error_reporter, "Fetch failed\n"); + MicroPrintf("Fetch failed\n"); return false; } /* Skip if there is no data */ @@ -72,7 +70,7 @@ bool ReadAccelerometer(tflite::ErrorReporter *error_reporter, float *input, for (int i = 0; i < samples_count; i++) { rc = sensor_channel_get(sensor, SENSOR_CHAN_ACCEL_XYZ, accel); if (rc < 0) { - TF_LITE_REPORT_ERROR(error_reporter, "ERROR: Update failed: %d\n", rc); + MicroPrintf("ERROR: Update failed: %d\n", rc); return false; } bufx[begin_index] = (float)sensor_value_to_double(&accel[0]); diff --git a/samples/modules/tflite-micro/magic_wand/src/accelerometer_handler.hpp b/samples/modules/tflite-micro/magic_wand/src/accelerometer_handler.hpp index c74382d3cb4..282126e2c1a 100644 --- a/samples/modules/tflite-micro/magic_wand/src/accelerometer_handler.hpp +++ b/samples/modules/tflite-micro/magic_wand/src/accelerometer_handler.hpp @@ -20,11 +20,10 @@ #define kChannelNumber 3 #include -#include +#include extern int begin_index; -extern TfLiteStatus SetupAccelerometer(tflite::ErrorReporter *error_reporter); -extern bool ReadAccelerometer(tflite::ErrorReporter *error_reporter, - float *input, int length); +extern TfLiteStatus SetupAccelerometer(); +extern bool ReadAccelerometer(float *input, int length); #endif /* TENSORFLOW_LITE_MICRO_EXAMPLES_MAGIC_WAND_ACCELEROMETER_HANDLER_H_ */ diff --git a/samples/modules/tflite-micro/magic_wand/src/main_functions.cpp b/samples/modules/tflite-micro/magic_wand/src/main_functions.cpp index 6c8f9e23400..69186d95997 100644 --- a/samples/modules/tflite-micro/magic_wand/src/main_functions.cpp +++ b/samples/modules/tflite-micro/magic_wand/src/main_functions.cpp @@ -21,14 +21,13 @@ #include "gesture_predictor.hpp" #include "magic_wand_model_data.hpp" #include "output_handler.hpp" -#include +#include #include #include #include /* Globals, used for compatibility with Arduino-style sketches. */ namespace { - tflite::ErrorReporter *error_reporter = nullptr; const tflite::Model *model = nullptr; tflite::MicroInterpreter *interpreter = nullptr; TfLiteTensor *model_input = nullptr; @@ -45,22 +44,14 @@ namespace { /* The name of this function is important for Arduino compatibility. */ void setup(void) { - /* Set up logging. Google style is to avoid globals or statics because of - * lifetime uncertainty, but since this has a trivial destructor it's okay. - */ - static tflite::MicroErrorReporter micro_error_reporter; /* NOLINT */ - - error_reporter = µ_error_reporter; - /* Map the model into a usable data structure. This doesn't involve any * copying or parsing, it's a very lightweight operation. */ model = tflite::GetModel(g_magic_wand_model_data); if (model->version() != TFLITE_SCHEMA_VERSION) { - TF_LITE_REPORT_ERROR(error_reporter, - "Model provided is schema version %d not equal " - "to supported version %d.", - model->version(), TFLITE_SCHEMA_VERSION); + MicroPrintf("Model provided is schema version %d not equal " + "to supported version %d.", + model->version(), TFLITE_SCHEMA_VERSION); return; } @@ -79,7 +70,7 @@ void setup(void) /* Build an interpreter to run the model with. */ static tflite::MicroInterpreter static_interpreter( - model, micro_op_resolver, tensor_arena, kTensorArenaSize, error_reporter); + model, micro_op_resolver, tensor_arena, kTensorArenaSize); interpreter = &static_interpreter; /* Allocate memory from the tensor_arena for the model's tensors. */ @@ -91,16 +82,15 @@ void setup(void) (model_input->dims->data[1] != 128) || (model_input->dims->data[2] != kChannelNumber) || (model_input->type != kTfLiteFloat32)) { - TF_LITE_REPORT_ERROR(error_reporter, - "Bad input tensor parameters in model"); + MicroPrintf("Bad input tensor parameters in model"); return; } input_length = model_input->bytes / sizeof(float); - TfLiteStatus setup_status = SetupAccelerometer(error_reporter); + TfLiteStatus setup_status = SetupAccelerometer(); if (setup_status != kTfLiteOk) { - TF_LITE_REPORT_ERROR(error_reporter, "Set up failed\n"); + MicroPrintf("Set up failed\n"); } } @@ -108,7 +98,7 @@ void loop(void) { /* Attempt to read new data from the accelerometer. */ bool got_data = - ReadAccelerometer(error_reporter, model_input->data.f, input_length); + ReadAccelerometer(model_input->data.f, input_length); /* If there was no new data, wait until next time. */ if (!got_data) { @@ -118,13 +108,12 @@ void loop(void) /* Run inference, and report any error */ TfLiteStatus invoke_status = interpreter->Invoke(); if (invoke_status != kTfLiteOk) { - TF_LITE_REPORT_ERROR(error_reporter, "Invoke failed on index: %d\n", - begin_index); + MicroPrintf("Invoke failed on index: %d\n", begin_index); return; } /* Analyze the results to obtain a prediction */ int gesture_index = PredictGesture(interpreter->output(0)->data.f); /* Produce an output */ - HandleOutput(error_reporter, gesture_index); + HandleOutput(gesture_index); } diff --git a/samples/modules/tflite-micro/magic_wand/src/output_handler.cpp b/samples/modules/tflite-micro/magic_wand/src/output_handler.cpp index d00aeaf46c8..373131d632e 100644 --- a/samples/modules/tflite-micro/magic_wand/src/output_handler.cpp +++ b/samples/modules/tflite-micro/magic_wand/src/output_handler.cpp @@ -16,24 +16,21 @@ #include "output_handler.hpp" -void HandleOutput(tflite::ErrorReporter *error_reporter, int kind) +void HandleOutput(int kind) { /* light (red: wing, blue: ring, green: slope) */ if (kind == 0) { - TF_LITE_REPORT_ERROR( - error_reporter, + MicroPrintf( "WING:\n\r* * *\n\r * * * " "*\n\r * * * *\n\r * * * *\n\r * * " "* *\n\r * *\n\r"); } else if (kind == 1) { - TF_LITE_REPORT_ERROR( - error_reporter, + MicroPrintf( "RING:\n\r *\n\r * *\n\r * *\n\r " " * *\n\r * *\n\r * *\n\r " " *\n\r"); } else if (kind == 2) { - TF_LITE_REPORT_ERROR( - error_reporter, + MicroPrintf( "SLOPE:\n\r *\n\r *\n\r *\n\r *\n\r " "*\n\r *\n\r *\n\r * * * * * * * *\n\r"); } diff --git a/samples/modules/tflite-micro/magic_wand/src/output_handler.hpp b/samples/modules/tflite-micro/magic_wand/src/output_handler.hpp index c5f1aebb046..ae041ae72c0 100644 --- a/samples/modules/tflite-micro/magic_wand/src/output_handler.hpp +++ b/samples/modules/tflite-micro/magic_wand/src/output_handler.hpp @@ -18,8 +18,8 @@ #define TENSORFLOW_LITE_MICRO_EXAMPLES_MAGIC_WAND_OUTPUT_HANDLER_H_ #include -#include +#include -void HandleOutput(tflite::ErrorReporter *error_reporter, int kind); +void HandleOutput(int kind); #endif /* TENSORFLOW_LITE_MICRO_EXAMPLES_MAGIC_WAND_OUTPUT_HANDLER_H_ */ diff --git a/samples/modules/tflite-micro/tflm_ethosu/prj.conf b/samples/modules/tflite-micro/tflm_ethosu/prj.conf index 37107d7a78c..e4d4947b298 100644 --- a/samples/modules/tflite-micro/tflm_ethosu/prj.conf +++ b/samples/modules/tflite-micro/tflm_ethosu/prj.conf @@ -1,6 +1,7 @@ #application default configuration # include TFLM based on CMSIS NN optimization and ETHOSU acceleration CONFIG_CPP=y +CONFIG_STD_CPP17=y CONFIG_TENSORFLOW_LITE_MICRO=y CONFIG_ARM_ETHOS_U=y CONFIG_HEAP_MEM_POOL_SIZE=16384 diff --git a/samples/modules/tflite-micro/tflm_ethosu/sample.yaml b/samples/modules/tflite-micro/tflm_ethosu/sample.yaml index d900f9dbe78..e1ff20cbd0f 100644 --- a/samples/modules/tflite-micro/tflm_ethosu/sample.yaml +++ b/samples/modules/tflite-micro/tflm_ethosu/sample.yaml @@ -3,7 +3,10 @@ sample: name: Arm Ethos-U NPU sample tests: sample.drivers.tflm_ethosu: - tags: NPU + tags: + - NPU + modules: + - tflite-micro filter: dt_compat_enabled("arm,ethos-u") build_only: true integration_platforms: diff --git a/samples/modules/tflite-micro/tflm_ethosu/src/inference_process.cpp b/samples/modules/tflite-micro/tflm_ethosu/src/inference_process.cpp index 25adcec70c6..5807588302e 100644 --- a/samples/modules/tflite-micro/tflm_ethosu/src/inference_process.cpp +++ b/samples/modules/tflite-micro/tflm_ethosu/src/inference_process.cpp @@ -6,9 +6,9 @@ #include "inference_process.hpp" -#include +#include #include -#include +#include #include #include #include @@ -118,11 +118,10 @@ bool InferenceProcess::runJob(InferenceJob &job) } /* Create the TFL micro interpreter */ - tflite::AllOpsResolver resolver; - tflite::MicroErrorReporter errorReporter; + tflite::MicroMutableOpResolver <1> resolver; + resolver.AddEthosU(); - tflite::MicroInterpreter interpreter(model, resolver, tensorArena, tensorArenaSize, - &errorReporter); + tflite::MicroInterpreter interpreter(model, resolver, tensorArena, tensorArenaSize); /* Allocate tensors */ TfLiteStatus allocate_status = interpreter.AllocateTensors(); diff --git a/samples/modules/tflite-micro/tflm_ethosu/src/main.cpp b/samples/modules/tflite-micro/tflm_ethosu/src/main.cpp index 19a4afad9c2..5671b0a0718 100644 --- a/samples/modules/tflite-micro/tflm_ethosu/src/main.cpp +++ b/samples/modules/tflite-micro/tflm_ethosu/src/main.cpp @@ -149,6 +149,8 @@ void inferenceProcessTask(void *_name, void *heap, void *_params) } k_thread_abort(k_current_get()); + + CODE_UNREACHABLE; } /* inferenceSenderTask - Creates NUM_INFERENCE_JOBS jobs, queues them, and then diff --git a/samples/net/capture/README.rst b/samples/net/capture/README.rst index 87259408582..c6846e5d552 100644 --- a/samples/net/capture/README.rst +++ b/samples/net/capture/README.rst @@ -1,13 +1,16 @@ -.. _net-capture-sample: +.. zephyr:code-sample:: net-capture + :name: Network packet capture + :relevant-api: net_capture -Network Packet Capture -###################### + Capture network packets and send them to a remote host via IPIP tunnel. Overview ******** This application will setup the device so that net-shell can be used -to enable network packet capture. The captured packets are sent to +to enable network packet capture. + +The captured packets are sent to remote host via IPIP tunnel. The tunnel can be configured to be in the same connection as what we are capturing packets or it can be a separate bearer. For example if you are capturing network traffic for interface 1, diff --git a/samples/net/cellular_modem/README.rst b/samples/net/cellular_modem/README.rst index 7c30a850705..384d8b3bef5 100644 --- a/samples/net/cellular_modem/README.rst +++ b/samples/net/cellular_modem/README.rst @@ -1,7 +1,7 @@ -.. _cellular_modem_sample: +.. zephyr:code-sample:: cellular-modem + :name: Cellular modem -Cellular Modem Sample -######################## + Use a cellular modem to communicate with a UDP server. Overview ******** diff --git a/samples/net/cloud/aws_iot_mqtt/README.rst b/samples/net/cloud/aws_iot_mqtt/README.rst index 0f0d08234d2..8ad0d1f9738 100644 --- a/samples/net/cloud/aws_iot_mqtt/README.rst +++ b/samples/net/cloud/aws_iot_mqtt/README.rst @@ -1,7 +1,8 @@ -.. _aws-iot-mqtt-sample: +.. zephyr:code-sample:: aws-iot-mqtt + :name: AWS IoT Core MQTT + :relevant-api: bsd_sockets mqtt_socket dns_resolve tls_credentials json sntp random_api -AWS IoT Core MQTT Sample -######################## + Connect to AWS IoT Core and publish messages using MQTT. Overview ******** diff --git a/samples/net/cloud/aws_iot_mqtt/prj.conf b/samples/net/cloud/aws_iot_mqtt/prj.conf index 8f6bbb82c6b..6738212e44c 100644 --- a/samples/net/cloud/aws_iot_mqtt/prj.conf +++ b/samples/net/cloud/aws_iot_mqtt/prj.conf @@ -9,7 +9,7 @@ CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_INIT_STACKS=y CONFIG_HW_STACK_PROTECTION=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_SNTP=y CONFIG_JSON_LIBRARY=y CONFIG_POSIX_CLOCK=y diff --git a/samples/net/cloud/aws_iot_mqtt/sample.yaml b/samples/net/cloud/aws_iot_mqtt/sample.yaml index 4dc5c5153ac..314dfc252b6 100644 --- a/samples/net/cloud/aws_iot_mqtt/sample.yaml +++ b/samples/net/cloud/aws_iot_mqtt/sample.yaml @@ -4,7 +4,7 @@ sample: common: tags: net mqtt cloud harness: net - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED and not CONFIG_NATIVE_LIBC extra_args: USE_DUMMY_CREDS=1 tests: sample.net.cloud.aws_iot_mqtt: diff --git a/samples/net/cloud/aws_iot_mqtt/src/main.c b/samples/net/cloud/aws_iot_mqtt/src/main.c index eddca33de29..09999d2e4eb 100644 --- a/samples/net/cloud/aws_iot_mqtt/src/main.c +++ b/samples/net/cloud/aws_iot_mqtt/src/main.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include @@ -58,7 +58,7 @@ static bool do_subscribe; /* Trigger client to subscribe */ #define TLS_TAG_DEVICE_PRIVATE_KEY 1 #define TLS_TAG_AWS_CA_CERTIFICATE 2 -static sec_tag_t sec_tls_tags[] = { +static const sec_tag_t sec_tls_tags[] = { TLS_TAG_DEVICE_CERTIFICATE, TLS_TAG_AWS_CA_CERTIFICATE, }; diff --git a/samples/net/cloud/google_iot_mqtt/CMakeLists.txt b/samples/net/cloud/google_iot_mqtt/CMakeLists.txt deleted file mode 100644 index 6fd930b57ec..00000000000 --- a/samples/net/cloud/google_iot_mqtt/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) - -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(google_iot_mqtt) - -FILE(GLOB app_sources src/*.c) -target_sources(app PRIVATE ${app_sources}) -zephyr_include_directories(${APPLICATION_SOURCE_DIR}/src/tls_config) - -if(USE_DUMMY_KEY) - target_sources(app PRIVATE ${APPLICATION_SOURCE_DIR}/src/private_info/test_key.c) -else() - if(NOT EXISTS ${APPLICATION_SOURCE_DIR}/src/private_info/key.c) - message(FATAL_ERROR "!!!!!! Generate key file before continuing. See README !!!!!") - endif() - - target_sources(app PRIVATE ${APPLICATION_SOURCE_DIR}/src/private_info/key.c) -endif() diff --git a/samples/net/cloud/google_iot_mqtt/Kconfig b/samples/net/cloud/google_iot_mqtt/Kconfig deleted file mode 100644 index 5bcba2e2d19..00000000000 --- a/samples/net/cloud/google_iot_mqtt/Kconfig +++ /dev/null @@ -1,33 +0,0 @@ -# Private config options for Google Cloud IOT application - -# Copyright (c) 2018 Linaro -# SPDX-License-Identifier: Apache-2.0 - -mainmenu "Google IOT MQTT/TLS sample application" - -config CLOUD_CLIENT_ID - string "Client ID string" - default "put client string here" - help - Set required client string that matches Google Cloud project - -config CLOUD_AUDIENCE - string "Audience string" - default "put audience string here" - help - Set required audience string that matches Google Cloud project - -config CLOUD_SUBSCRIBE_CONFIG - string "Subscription string for config" - default "put subscription string here" - help - Set required subscription string that matches Google Cloud project - config item. - -config CLOUD_PUBLISH_TOPIC - string "Publish topic string" - default "put topic string here" - help - Set publish topics string that matches Google Cloud project - -source "Kconfig.zephyr" diff --git a/samples/net/cloud/google_iot_mqtt/README.rst b/samples/net/cloud/google_iot_mqtt/README.rst deleted file mode 100644 index e82736f4c0c..00000000000 --- a/samples/net/cloud/google_iot_mqtt/README.rst +++ /dev/null @@ -1,64 +0,0 @@ -.. _google-iot-mqtt-sample: - -Google IOT MQTT Sample -###################### - -Overview -******** - -This sample application demonstrates a "full stack" application. This -currently is able to - -- Acquire a DHCPv4 lease. -- Connect to an SNTP server and acquire current time -- Establish a TLS connection with the Google IOT Cloud servers -- Publish data to the Google IOT Cloud -- Send/Receive keep alive / pings from cloud server - -The source code for this sample application can be found at: -:zephyr_file:`samples/net/cloud/google_iot_mqtt`. - -Requirements -************ -- Entropy source -- Google IOT Cloud account -- Google IOT Cloud credentials and required information -- Network connectivity - -Building and Running -******************** -This application has been built and tested on the NXP FRDMK64F. RSA or -ECDSA certs/keys are required to authenticate to the Google IOT Cloud. -The application includes a key creation script. - -Run the ``create_keys.py`` script in the -``samples/net/cloud/google_iot_mqtt/src/private_info/`` directory. -Be sure that they key type generated (RSA or ECDSA) matches your -config of either :code:`JWT_SIGN_RSA` or :code:`JWT_SIGN_ECDSA`. - -Users will also be required to configure the following Kconfig options -based on their Google Cloud IOT project. The following values come -from the Google Cloud Platform itself: - -- PROJECT_ID: When you select your project at the top of the UI, it - should have a "name", and there should be an ID field as well. This - seems to be two words and a number, separated by hyphens. -- REGION: The Region shows in the list of registries for your - registry. And example is "us-central1". -- REGISTRY_ID: Each registry has an id. This is a string given when - creating the registry. -- DEVICE_ID: A name given for each device. When viewing the table of - devices, this will be shown. - -From these values, the config values can be set using the following -template: - -.. code-block:: kconfig - - CLOUD_CLIENT_ID="projects/PROJECT_ID/locations/REGION/registries/REGISTRY_ID/devices/DEVICE_ID" - CLOUD_AUDIENCE="PROJECT_ID" - CLOUD_SUBSCRIBE_CONFIG="/devices/DEVICE_ID/config" - CLOUD_PUBLISH_TOPIC="/devices/DEVICE_ID/state" - -See `Google Cloud MQTT Documentation -`_. diff --git a/samples/net/cloud/google_iot_mqtt/prj.conf b/samples/net/cloud/google_iot_mqtt/prj.conf deleted file mode 100644 index 6abb2eb7061..00000000000 --- a/samples/net/cloud/google_iot_mqtt/prj.conf +++ /dev/null @@ -1,64 +0,0 @@ -CONFIG_NETWORKING=y -CONFIG_NET_IPV6=n -CONFIG_NET_IPV4=y -CONFIG_NET_UDP=y -CONFIG_NET_TCP=y -CONFIG_NET_DHCPV4=y -CONFIG_STDOUT_CONSOLE=y - -CONFIG_NET_PKT_RX_COUNT=4 -CONFIG_NET_PKT_TX_COUNT=4 -CONFIG_NET_BUF_RX_COUNT=12 -CONFIG_NET_BUF_TX_COUNT=12 - -CONFIG_INIT_STACKS=y - -CONFIG_JWT=y -CONFIG_JWT_SIGN_ECDSA=y - -CONFIG_NET_MGMT=y -CONFIG_NET_MGMT_EVENT=y - -CONFIG_LOG=y - -# This shouldn't need to be set, but isn't selected properly. -CONFIG_NEWLIB_LIBC=y - -CONFIG_DNS_SERVER_IP_ADDRESSES=y -CONFIG_DNS_SERVER1="8.8.8.8" - -CONFIG_DNS_RESOLVER=y -CONFIG_DNS_RESOLVER_ADDITIONAL_BUF_CTR=2 -CONFIG_SNTP=y - -CONFIG_SLIP_STATISTICS=n - -CONFIG_HW_STACK_PROTECTION=y -CONFIG_MAIN_STACK_SIZE=4096 - -CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 - -CONFIG_PTHREAD_IPC=n -CONFIG_NET_SOCKETS=y -CONFIG_MQTT_LIB=y -CONFIG_MQTT_LIB_TLS=y -CONFIG_NET_SOCKETS_SOCKOPT_TLS=y - - -# Enable MBEDTLS -CONFIG_MBEDTLS=y -CONFIG_MBEDTLS_BUILTIN=y - -CONFIG_NET_SOCKETS_POSIX_NAMES=y - -CONFIG_MBEDTLS_ENABLE_HEAP=y -CONFIG_MBEDTLS_HEAP_SIZE=56240 -CONFIG_MBEDTLS_USER_CONFIG_ENABLE=y -CONFIG_MBEDTLS_USER_CONFIG_FILE="user-tls-conf.h" - -# Please see README.rst in this directory for instructions -# on where to get the values for these config entries. -CONFIG_CLOUD_CLIENT_ID="projects//locations//registries//devices/" -CONFIG_CLOUD_AUDIENCE="" -CONFIG_CLOUD_SUBSCRIBE_CONFIG="/devices//config" -CONFIG_CLOUD_PUBLISH_TOPIC="/devices//state" diff --git a/samples/net/cloud/google_iot_mqtt/sample.yaml b/samples/net/cloud/google_iot_mqtt/sample.yaml deleted file mode 100644 index 25830576aed..00000000000 --- a/samples/net/cloud/google_iot_mqtt/sample.yaml +++ /dev/null @@ -1,19 +0,0 @@ -sample: - description: MQTT sample app to Google IoT cloud - name: google_iot_mqtt -common: - tags: - - net - - mqtt - - cloud - harness: net - filter: TOOLCHAIN_HAS_NEWLIB == 1 - extra_args: USE_DUMMY_KEY=1 -tests: - sample.net.cloud.google_iot_mqtt: - depends_on: netif - platform_allow: - - frdm_k64f - - qemu_x86 - integration_platforms: - - qemu_x86 diff --git a/samples/net/cloud/google_iot_mqtt/src/dhcp.c b/samples/net/cloud/google_iot_mqtt/src/dhcp.c deleted file mode 100644 index bc06cb424b2..00000000000 --- a/samples/net/cloud/google_iot_mqtt/src/dhcp.c +++ /dev/null @@ -1,66 +0,0 @@ -/* DHCPv4 client startup. */ - -/* - * Copyright (c) 2018 Linaro Ltd - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -LOG_MODULE_DECLARE(net_google_iot_mqtt, LOG_LEVEL_DBG); - -#include - -#include -#include -#include -#include - -static struct net_mgmt_event_callback mgmt_cb; - -/* Semaphore to indicate a lease has been acquired. */ -static K_SEM_DEFINE(got_address, 0, 1); - -static void handler(struct net_mgmt_event_callback *cb, - uint32_t mgmt_event, - struct net_if *iface) -{ - int i; - bool notified = false; - - if (mgmt_event != NET_EVENT_IPV4_ADDR_ADD) { - return; - } - - for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) { - - if (iface->config.ip.ipv4->unicast[i].addr_type != - NET_ADDR_DHCP) { - continue; - } - - if (!notified) { - k_sem_give(&got_address); - notified = true; - } - break; - } -} - -/** - * Start a DHCP client, and wait for a lease to be acquired. - */ -void app_dhcpv4_startup(void) -{ - LOG_INF("starting DHCPv4"); - - net_mgmt_init_event_callback(&mgmt_cb, handler, - NET_EVENT_IPV4_ADDR_ADD); - net_mgmt_add_event_callback(&mgmt_cb); - - net_dhcpv4_start(net_if_get_default()); - - /* Wait for a lease. */ - k_sem_take(&got_address, K_FOREVER); -} diff --git a/samples/net/cloud/google_iot_mqtt/src/dhcp.h b/samples/net/cloud/google_iot_mqtt/src/dhcp.h deleted file mode 100644 index 3760d46c5f7..00000000000 --- a/samples/net/cloud/google_iot_mqtt/src/dhcp.h +++ /dev/null @@ -1,14 +0,0 @@ -/* DHCPv4 client startup. */ - -/* - * Copyright (c) 2018 Linaro Ltd - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __DHCP_H__ -#define __DHCP_H__ - -void app_dhcpv4_startup(void); - -#endif /* not __DHCP_H__ */ diff --git a/samples/net/cloud/google_iot_mqtt/src/globalsign.inc b/samples/net/cloud/google_iot_mqtt/src/globalsign.inc deleted file mode 100644 index e1424bc483b..00000000000 --- a/samples/net/cloud/google_iot_mqtt/src/globalsign.inc +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2018 Linaro Ltd - * - * SPDX-License-Identifier: Apache-2.0 - * - * vim: ft=c - * - * Generated from downloading GlobalSign Root Certificate R2 from - * https://aboutssl.org/globalsign-root-certificates-licensing-and-use/ - * and extracting the following information using openssl: - * - * openssl x509 -in GlobalSign_Root_CA_-_R2.pem -inform pem -noout -C - */ -/* subject:/OU=GlobalSign Root CA - R2/O=GlobalSign/CN=GlobalSign */ -/* issuer :/OU=GlobalSign Root CA - R2/O=GlobalSign/CN=GlobalSign */ -/* -unsigned char XXX_subject_name[78]={ -0x30,0x4C,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x0B,0x13,0x17,0x47,0x6C,0x6F, -0x62,0x61,0x6C,0x53,0x69,0x67,0x6E,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x20, -0x2D,0x20,0x52,0x32,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x47, -0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69,0x67,0x6E,0x31,0x13,0x30,0x11,0x06,0x03,0x55, -0x04,0x03,0x13,0x0A,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69,0x67,0x6E, -}; -unsigned char XXX_public_key[294]={ -0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, -0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01, -0x00,0xA6,0xCF,0x24,0x0E,0xBE,0x2E,0x6F,0x28,0x99,0x45,0x42,0xC4,0xAB,0x3E,0x21, -0x54,0x9B,0x0B,0xD3,0x7F,0x84,0x70,0xFA,0x12,0xB3,0xCB,0xBF,0x87,0x5F,0xC6,0x7F, -0x86,0xD3,0xB2,0x30,0x5C,0xD6,0xFD,0xAD,0xF1,0x7B,0xDC,0xE5,0xF8,0x60,0x96,0x09, -0x92,0x10,0xF5,0xD0,0x53,0xDE,0xFB,0x7B,0x7E,0x73,0x88,0xAC,0x52,0x88,0x7B,0x4A, -0xA6,0xCA,0x49,0xA6,0x5E,0xA8,0xA7,0x8C,0x5A,0x11,0xBC,0x7A,0x82,0xEB,0xBE,0x8C, -0xE9,0xB3,0xAC,0x96,0x25,0x07,0x97,0x4A,0x99,0x2A,0x07,0x2F,0xB4,0x1E,0x77,0xBF, -0x8A,0x0F,0xB5,0x02,0x7C,0x1B,0x96,0xB8,0xC5,0xB9,0x3A,0x2C,0xBC,0xD6,0x12,0xB9, -0xEB,0x59,0x7D,0xE2,0xD0,0x06,0x86,0x5F,0x5E,0x49,0x6A,0xB5,0x39,0x5E,0x88,0x34, -0xEC,0xBC,0x78,0x0C,0x08,0x98,0x84,0x6C,0xA8,0xCD,0x4B,0xB4,0xA0,0x7D,0x0C,0x79, -0x4D,0xF0,0xB8,0x2D,0xCB,0x21,0xCA,0xD5,0x6C,0x5B,0x7D,0xE1,0xA0,0x29,0x84,0xA1, -0xF9,0xD3,0x94,0x49,0xCB,0x24,0x62,0x91,0x20,0xBC,0xDD,0x0B,0xD5,0xD9,0xCC,0xF9, -0xEA,0x27,0x0A,0x2B,0x73,0x91,0xC6,0x9D,0x1B,0xAC,0xC8,0xCB,0xE8,0xE0,0xA0,0xF4, -0x2F,0x90,0x8B,0x4D,0xFB,0xB0,0x36,0x1B,0xF6,0x19,0x7A,0x85,0xE0,0x6D,0xF2,0x61, -0x13,0x88,0x5C,0x9F,0xE0,0x93,0x0A,0x51,0x97,0x8A,0x5A,0xCE,0xAF,0xAB,0xD5,0xF7, -0xAA,0x09,0xAA,0x60,0xBD,0xDC,0xD9,0x5F,0xDF,0x72,0xA9,0x60,0x13,0x5E,0x00,0x01, -0xC9,0x4A,0xFA,0x3F,0xA4,0xEA,0x07,0x03,0x21,0x02,0x8E,0x82,0xCA,0x03,0xC2,0x9B, -0x8F,0x02,0x03,0x01,0x00,0x01, -}; -*/ -unsigned char globalsign_certificate[958]={ -0x30,0x82,0x03,0xBA,0x30,0x82,0x02,0xA2,0xA0,0x03,0x02,0x01,0x02,0x02,0x0B,0x04, -0x00,0x00,0x00,0x00,0x01,0x0F,0x86,0x26,0xE6,0x0D,0x30,0x0D,0x06,0x09,0x2A,0x86, -0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x4C,0x31,0x20,0x30,0x1E,0x06, -0x03,0x55,0x04,0x0B,0x13,0x17,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69,0x67,0x6E, -0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x20,0x2D,0x20,0x52,0x32,0x31,0x13,0x30, -0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69, -0x67,0x6E,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0A,0x47,0x6C,0x6F, -0x62,0x61,0x6C,0x53,0x69,0x67,0x6E,0x30,0x1E,0x17,0x0D,0x30,0x36,0x31,0x32,0x31, -0x35,0x30,0x38,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32,0x31,0x31,0x32,0x31,0x35, -0x30,0x38,0x30,0x30,0x30,0x30,0x5A,0x30,0x4C,0x31,0x20,0x30,0x1E,0x06,0x03,0x55, -0x04,0x0B,0x13,0x17,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69,0x67,0x6E,0x20,0x52, -0x6F,0x6F,0x74,0x20,0x43,0x41,0x20,0x2D,0x20,0x52,0x32,0x31,0x13,0x30,0x11,0x06, -0x03,0x55,0x04,0x0A,0x13,0x0A,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69,0x67,0x6E, -0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0A,0x47,0x6C,0x6F,0x62,0x61, -0x6C,0x53,0x69,0x67,0x6E,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, -0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01, -0x0A,0x02,0x82,0x01,0x01,0x00,0xA6,0xCF,0x24,0x0E,0xBE,0x2E,0x6F,0x28,0x99,0x45, -0x42,0xC4,0xAB,0x3E,0x21,0x54,0x9B,0x0B,0xD3,0x7F,0x84,0x70,0xFA,0x12,0xB3,0xCB, -0xBF,0x87,0x5F,0xC6,0x7F,0x86,0xD3,0xB2,0x30,0x5C,0xD6,0xFD,0xAD,0xF1,0x7B,0xDC, -0xE5,0xF8,0x60,0x96,0x09,0x92,0x10,0xF5,0xD0,0x53,0xDE,0xFB,0x7B,0x7E,0x73,0x88, -0xAC,0x52,0x88,0x7B,0x4A,0xA6,0xCA,0x49,0xA6,0x5E,0xA8,0xA7,0x8C,0x5A,0x11,0xBC, -0x7A,0x82,0xEB,0xBE,0x8C,0xE9,0xB3,0xAC,0x96,0x25,0x07,0x97,0x4A,0x99,0x2A,0x07, -0x2F,0xB4,0x1E,0x77,0xBF,0x8A,0x0F,0xB5,0x02,0x7C,0x1B,0x96,0xB8,0xC5,0xB9,0x3A, -0x2C,0xBC,0xD6,0x12,0xB9,0xEB,0x59,0x7D,0xE2,0xD0,0x06,0x86,0x5F,0x5E,0x49,0x6A, -0xB5,0x39,0x5E,0x88,0x34,0xEC,0xBC,0x78,0x0C,0x08,0x98,0x84,0x6C,0xA8,0xCD,0x4B, -0xB4,0xA0,0x7D,0x0C,0x79,0x4D,0xF0,0xB8,0x2D,0xCB,0x21,0xCA,0xD5,0x6C,0x5B,0x7D, -0xE1,0xA0,0x29,0x84,0xA1,0xF9,0xD3,0x94,0x49,0xCB,0x24,0x62,0x91,0x20,0xBC,0xDD, -0x0B,0xD5,0xD9,0xCC,0xF9,0xEA,0x27,0x0A,0x2B,0x73,0x91,0xC6,0x9D,0x1B,0xAC,0xC8, -0xCB,0xE8,0xE0,0xA0,0xF4,0x2F,0x90,0x8B,0x4D,0xFB,0xB0,0x36,0x1B,0xF6,0x19,0x7A, -0x85,0xE0,0x6D,0xF2,0x61,0x13,0x88,0x5C,0x9F,0xE0,0x93,0x0A,0x51,0x97,0x8A,0x5A, -0xCE,0xAF,0xAB,0xD5,0xF7,0xAA,0x09,0xAA,0x60,0xBD,0xDC,0xD9,0x5F,0xDF,0x72,0xA9, -0x60,0x13,0x5E,0x00,0x01,0xC9,0x4A,0xFA,0x3F,0xA4,0xEA,0x07,0x03,0x21,0x02,0x8E, -0x82,0xCA,0x03,0xC2,0x9B,0x8F,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0x9C,0x30,0x81, -0x99,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01, -0x06,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01, -0x01,0xFF,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x9B,0xE2,0x07, -0x57,0x67,0x1C,0x1E,0xC0,0x6A,0x06,0xDE,0x59,0xB4,0x9A,0x2D,0xDF,0xDC,0x19,0x86, -0x2E,0x30,0x36,0x06,0x03,0x55,0x1D,0x1F,0x04,0x2F,0x30,0x2D,0x30,0x2B,0xA0,0x29, -0xA0,0x27,0x86,0x25,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x67, -0x6C,0x6F,0x62,0x61,0x6C,0x73,0x69,0x67,0x6E,0x2E,0x6E,0x65,0x74,0x2F,0x72,0x6F, -0x6F,0x74,0x2D,0x72,0x32,0x2E,0x63,0x72,0x6C,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23, -0x04,0x18,0x30,0x16,0x80,0x14,0x9B,0xE2,0x07,0x57,0x67,0x1C,0x1E,0xC0,0x6A,0x06, -0xDE,0x59,0xB4,0x9A,0x2D,0xDF,0xDC,0x19,0x86,0x2E,0x30,0x0D,0x06,0x09,0x2A,0x86, -0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x99,0x81, -0x53,0x87,0x1C,0x68,0x97,0x86,0x91,0xEC,0xE0,0x4A,0xB8,0x44,0x0B,0xAB,0x81,0xAC, -0x27,0x4F,0xD6,0xC1,0xB8,0x1C,0x43,0x78,0xB3,0x0C,0x9A,0xFC,0xEA,0x2C,0x3C,0x6E, -0x61,0x1B,0x4D,0x4B,0x29,0xF5,0x9F,0x05,0x1D,0x26,0xC1,0xB8,0xE9,0x83,0x00,0x62, -0x45,0xB6,0xA9,0x08,0x93,0xB9,0xA9,0x33,0x4B,0x18,0x9A,0xC2,0xF8,0x87,0x88,0x4E, -0xDB,0xDD,0x71,0x34,0x1A,0xC1,0x54,0xDA,0x46,0x3F,0xE0,0xD3,0x2A,0xAB,0x6D,0x54, -0x22,0xF5,0x3A,0x62,0xCD,0x20,0x6F,0xBA,0x29,0x89,0xD7,0xDD,0x91,0xEE,0xD3,0x5C, -0xA2,0x3E,0xA1,0x5B,0x41,0xF5,0xDF,0xE5,0x64,0x43,0x2D,0xE9,0xD5,0x39,0xAB,0xD2, -0xA2,0xDF,0xB7,0x8B,0xD0,0xC0,0x80,0x19,0x1C,0x45,0xC0,0x2D,0x8C,0xE8,0xF8,0x2D, -0xA4,0x74,0x56,0x49,0xC5,0x05,0xB5,0x4F,0x15,0xDE,0x6E,0x44,0x78,0x39,0x87,0xA8, -0x7E,0xBB,0xF3,0x79,0x18,0x91,0xBB,0xF4,0x6F,0x9D,0xC1,0xF0,0x8C,0x35,0x8C,0x5D, -0x01,0xFB,0xC3,0x6D,0xB9,0xEF,0x44,0x6D,0x79,0x46,0x31,0x7E,0x0A,0xFE,0xA9,0x82, -0xC1,0xFF,0xEF,0xAB,0x6E,0x20,0xC4,0x50,0xC9,0x5F,0x9D,0x4D,0x9B,0x17,0x8C,0x0C, -0xE5,0x01,0xC9,0xA0,0x41,0x6A,0x73,0x53,0xFA,0xA5,0x50,0xB4,0x6E,0x25,0x0F,0xFB, -0x4C,0x18,0xF4,0xFD,0x52,0xD9,0x8E,0x69,0xB1,0xE8,0x11,0x0F,0xDE,0x88,0xD8,0xFB, -0x1D,0x49,0xF7,0xAA,0xDE,0x95,0xCF,0x20,0x78,0xC2,0x60,0x12,0xDB,0x25,0x40,0x8C, -0x6A,0xFC,0x7E,0x42,0x38,0x40,0x64,0x12,0xF7,0x9E,0x81,0xE1,0x93,0x2E, -}; diff --git a/samples/net/cloud/google_iot_mqtt/src/main.c b/samples/net/cloud/google_iot_mqtt/src/main.c deleted file mode 100644 index 1cd93febf1a..00000000000 --- a/samples/net/cloud/google_iot_mqtt/src/main.c +++ /dev/null @@ -1,79 +0,0 @@ -/* Full-stack IoT client example. */ - -/* - * Copyright (c) 2018 Linaro Ltd - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -#include "dhcp.h" -#include "protocol.h" - -#include -#include -#include - -#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL -#include - -LOG_MODULE_REGISTER(net_google_iot_mqtt, LOG_LEVEL_INF); - -/* This comes from newlib. */ -#include -#include - -int64_t time_base; - -int do_sntp(void) -{ - int rc; - struct sntp_time sntp_time; - char time_str[sizeof("1970-01-01T00:00:00")]; - - LOG_INF("Sending NTP request for current time:"); - - rc = sntp_simple("time.google.com", SYS_FOREVER_MS, &sntp_time); - if (rc == 0) { - time_base = sntp_time.seconds * MSEC_PER_SEC - k_uptime_get(); - - /* Convert time to make sure. */ - time_t now = sntp_time.seconds; - struct tm now_tm; - - gmtime_r(&now, &now_tm); - strftime(time_str, sizeof(time_str), "%FT%T", &now_tm); - LOG_INF(" Acquired time: %s", time_str); - - } else { - LOG_ERR(" Failed to acquire SNTP, code %d\n", rc); - } - return rc; -} - -/* - * Things that make sense in a demo app that would need to be more - * robust in a real application: - * - * - DHCP happens once. If it fails, or we change networks, the - * network will just stop working. - * - */ -int main(void) -{ - LOG_INF("Main entered"); - - app_dhcpv4_startup(); - - LOG_INF("Should have DHCPv4 lease at this point."); - - /* early return if we failed to acquire time */ - if (do_sntp() != 0) { - LOG_ERR("Failed to get NTP time"); - return 0; - } - - mqtt_startup("mqtt.googleapis.com", 8883); - return 0; -} diff --git a/samples/net/cloud/google_iot_mqtt/src/private_info/.gitignore b/samples/net/cloud/google_iot_mqtt/src/private_info/.gitignore deleted file mode 100644 index 29bda8c1ec4..00000000000 --- a/samples/net/cloud/google_iot_mqtt/src/private_info/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -*-cert.pem -*-private.pem -*.der -key.c diff --git a/samples/net/cloud/google_iot_mqtt/src/private_info/create_keys.py b/samples/net/cloud/google_iot_mqtt/src/private_info/create_keys.py deleted file mode 100755 index cb0fbeb3bd2..00000000000 --- a/samples/net/cloud/google_iot_mqtt/src/private_info/create_keys.py +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (c) 2018 Linaro -# -# SPDX-License-Identifier: Apache-2.0 - -import sys -import subprocess -import argparse - -def parse_args(): - global args - - parser = argparse.ArgumentParser(description=__doc__, - formatter_class=argparse.RawDescriptionHelpFormatter, allow_abbrev=False) - - parser.add_argument( - "-d", "--device", required=True, - help="Name of device") - - parser.add_argument( - "-e", "--ecdsa", required=False, - action='store_true', - help="Use elliptic curve") - - parser.add_argument( - "-r", "--rsa", required=False, - action='store_true', - help="Use RSA") - - args = parser.parse_args() - -split_string = lambda x, n: [x[i:i+n] for i in range(0, len(x), n)] - -def main(): - parse_args() - - fd = open("key.c", "w") - - pem_file = args.device + "-private.pem" - cert_file = args.device + "-cert.pem" - der_file = args.device + "-private.der" - - if args.ecdsa: - print("Generating ecdsa private key") - try: - subprocess.call(["openssl", "ecparam", "-noout", "-name", "prime256v1", "-genkey", - "-out", pem_file]) - - except subprocess.CalledProcessError as e: - print(e.output) - else: - print("Generating rsa private key") - try: - subprocess.call(["openssl", "genrsa", "-out", pem_file, "2048"]) - - except subprocess.CalledProcessError as e: - print(e.output) - - print("Generating certificate") - - try: - subprocess.check_call(["openssl", "req", "-new", "-x509", "-key", pem_file, "-out", - cert_file, "-days", "1000000", "-subj", "/CN=" + args.device]) - - except subprocess.CalledProcessError as e: - print(e.output) - - - if args.ecdsa: - print("Parsing ECDSA private key") - o = subprocess.Popen(["openssl", "asn1parse", "-in", pem_file, - "-offset", "5", "-length", "34"], stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - - if o.returncode == 0: - sys.exit("failed to parse ECDSA private key") - - tmp = o.communicate()[0].decode('ascii').split(":")[3].lower().strip() - - if o.returncode: - sys.exit("failed to parse ECDSA private key") - - tmp = split_string(tmp, 2) - output = ["0x" + s for s in tmp] - output = ', '.join(output) - - else: - print("Parsing RSA private key and generating DER output") - try: - subprocess.call(["openssl", "pkcs8", "-nocrypt", "-topk8", - "-inform", "pem", "-outform", "der", "-in", pem_file, "-out", - der_file]) - - except subprocess.CalledProcessError as e: - print(e.output) - - der_fd = open(der_file, "r") - o = subprocess.Popen(["xxd", "-i"], stdin=der_fd, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - - output = o.communicate()[0].decode('ascii') - - if o.returncode: - sys.exit("failed to parse RSA private key") - - print("Generating key.c") - fd.write("unsigned char zepfull_private_der[] = {\n") - key_len = len(output.split(',')) - fd.write(output) - fd.write("};\n\n") - - fd.write("unsigned int zepfull_private_der_len = " + str(key_len) + ";\n") - -if __name__ == "__main__": - main() diff --git a/samples/net/cloud/google_iot_mqtt/src/private_info/test_key.c b/samples/net/cloud/google_iot_mqtt/src/private_info/test_key.c deleted file mode 100644 index 14baccb56d2..00000000000 --- a/samples/net/cloud/google_iot_mqtt/src/private_info/test_key.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2021 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -unsigned char zepfull_private_der[] = { - 0x30, 0x82, 0x04, 0xbe, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, - 0x04, 0xa8, 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, - 0x01, 0x00, 0xc7, 0xa1, 0x91, 0x8d, 0x6c, 0xed, 0x88, 0xbe, 0x23, 0x01, - 0x4a, 0x49, 0x64, 0x3f, 0x45, 0xe7, 0x1e, 0xab, 0x3e, 0xf4, 0x60, 0xaf, - 0x64, 0x60, 0xda, 0x5e, 0xf8, 0xfe, 0x5b, 0xd0, 0x49, 0x61, 0xd9, 0x1e, - 0x7d, 0xb1, 0xaf, 0xf4, 0x32, 0xa1, 0x54, 0xf7, 0xce, 0x3f, 0xaa, 0x7d, - 0x93, 0xef, 0x96, 0xa5, 0x84, 0x8b, 0x1c, 0xd5, 0x31, 0x67, 0xc7, 0xcd, - 0xd0, 0x17, 0xa3, 0xbf, 0x75, 0xae, 0x4b, 0x26, 0xc2, 0x82, 0x1f, 0x1f, - 0x40, 0xfd, 0xd0, 0xdd, 0x89, 0x64, 0x6b, 0xed, 0x83, 0xd9, 0x33, 0xfc, - 0x2d, 0xec, 0x7a, 0xfb, 0x9b, 0x12, 0xae, 0x65, 0x8b, 0x8d, 0x9d, 0x85, - 0x2b, 0x34, 0x42, 0xa6, 0x59, 0x74, 0x08, 0x34, 0xaa, 0x66, 0xf2, 0x52, - 0xac, 0xbf, 0xe2, 0x55, 0x2e, 0x64, 0xb0, 0x04, 0x2d, 0xa6, 0x0f, 0xe0, - 0xc1, 0xf2, 0x48, 0x21, 0x9b, 0x5d, 0x96, 0x36, 0x0a, 0xeb, 0xfa, 0xdf, - 0xcb, 0xc7, 0x95, 0x86, 0xec, 0x85, 0xd8, 0xa3, 0xb9, 0xc4, 0x6f, 0x9f, - 0xb3, 0x52, 0xec, 0xc3, 0xae, 0x7b, 0x51, 0x4e, 0x76, 0x6c, 0x59, 0xdc, - 0x05, 0xb1, 0x20, 0xdc, 0x4f, 0x21, 0x57, 0x19, 0x93, 0x42, 0x1b, 0xf2, - 0x38, 0x84, 0x15, 0xf3, 0x5a, 0xe6, 0x9c, 0x5c, 0xff, 0x8b, 0x7a, 0x09, - 0x66, 0x96, 0xa4, 0x53, 0x00, 0xb0, 0x75, 0xac, 0xdb, 0xb2, 0xa4, 0x5d, - 0x18, 0x7d, 0x76, 0xf6, 0xc5, 0x69, 0x37, 0x6b, 0xfd, 0xc4, 0x56, 0x01, - 0x13, 0xf7, 0x7d, 0xcd, 0xf7, 0x3b, 0xa8, 0xec, 0x11, 0x95, 0x53, 0x25, - 0x5e, 0x99, 0xb9, 0x13, 0xf9, 0xa8, 0x68, 0x25, 0x23, 0x2c, 0x36, 0xc7, - 0xb6, 0x39, 0x7f, 0xe9, 0xf9, 0x70, 0x2b, 0x29, 0xbc, 0x70, 0xe9, 0x7a, - 0x00, 0xd2, 0x76, 0xa1, 0xef, 0x3c, 0x98, 0x71, 0x77, 0xbb, 0xcd, 0x83, - 0xf2, 0x3a, 0x7a, 0x5e, 0xc0, 0x27, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, - 0x82, 0x01, 0x01, 0x00, 0xb8, 0xf8, 0x67, 0x99, 0x16, 0xf8, 0xf0, 0xde, - 0xdc, 0x28, 0x71, 0xe0, 0x96, 0xd6, 0x59, 0xba, 0xd0, 0x9b, 0xf3, 0x75, - 0x13, 0xb0, 0xef, 0xdd, 0x1d, 0xf9, 0x29, 0xd4, 0xe4, 0xd5, 0x95, 0x68, - 0xe8, 0x78, 0x6c, 0x16, 0x9b, 0xe6, 0x34, 0x93, 0x6f, 0xdb, 0x3c, 0x6b, - 0x99, 0x59, 0x4a, 0x1d, 0x91, 0x04, 0x44, 0x4f, 0x71, 0xa3, 0xc8, 0x67, - 0x54, 0xa6, 0xca, 0xcd, 0x5c, 0x98, 0x26, 0x3e, 0x1c, 0xbc, 0x09, 0x35, - 0xf0, 0x08, 0x51, 0x7b, 0xdc, 0x6f, 0xa8, 0xc2, 0x37, 0x8e, 0x97, 0xc0, - 0x45, 0x7e, 0xc0, 0x3e, 0x81, 0xa5, 0x68, 0x06, 0x63, 0x39, 0x0b, 0x99, - 0x67, 0xfe, 0xe0, 0x0d, 0x48, 0x44, 0x42, 0x56, 0x54, 0xd4, 0x17, 0x9f, - 0xd3, 0x9f, 0xef, 0x18, 0xcc, 0x6a, 0x08, 0xd6, 0x9a, 0x91, 0x04, 0x8a, - 0xfd, 0xe3, 0x4f, 0x51, 0x62, 0xac, 0x60, 0xfc, 0xd2, 0x15, 0xb8, 0xff, - 0x53, 0x3e, 0xc0, 0x07, 0xe3, 0x75, 0x42, 0xbe, 0x35, 0x1b, 0x7e, 0xf5, - 0x00, 0x1a, 0x26, 0x10, 0x89, 0xb4, 0x8c, 0x21, 0x54, 0xb5, 0x1e, 0x1a, - 0x23, 0x32, 0xaf, 0x80, 0x38, 0x0a, 0xfa, 0xc0, 0x17, 0xb1, 0x49, 0x92, - 0xfa, 0x08, 0x15, 0x02, 0xa6, 0xe3, 0x36, 0x57, 0x03, 0xbd, 0x56, 0xd2, - 0x24, 0xaf, 0xb9, 0x45, 0xd0, 0x43, 0x16, 0xd1, 0x78, 0x86, 0x2e, 0xae, - 0xf6, 0xac, 0x1d, 0x0b, 0x03, 0xac, 0x90, 0x0d, 0x5d, 0xbe, 0xc0, 0xc0, - 0x9e, 0x30, 0x38, 0x9b, 0x61, 0x7b, 0x51, 0x39, 0xc2, 0x3d, 0x30, 0x85, - 0xf2, 0x33, 0x94, 0x53, 0xb0, 0x5a, 0x12, 0x72, 0xeb, 0x30, 0xb2, 0x8c, - 0x66, 0xec, 0xc2, 0x1f, 0x4d, 0xa5, 0x67, 0x20, 0xde, 0x3b, 0x05, 0x72, - 0xe9, 0x0e, 0x77, 0x1f, 0x3f, 0xd8, 0x8a, 0x77, 0x5c, 0x4c, 0xc0, 0x81, - 0xf2, 0xe3, 0x41, 0x96, 0x94, 0xa6, 0xe5, 0xc1, 0x02, 0x81, 0x81, 0x00, - 0xe3, 0xd3, 0x76, 0x49, 0x5f, 0x18, 0x58, 0x74, 0x31, 0x37, 0xca, 0xfa, - 0x42, 0x39, 0x74, 0x61, 0x4b, 0xec, 0x0c, 0x14, 0xc7, 0xfa, 0xff, 0xe5, - 0xa4, 0xb0, 0x33, 0xba, 0x7b, 0x0a, 0x02, 0xf4, 0x07, 0x6e, 0xf3, 0xbe, - 0xde, 0xe6, 0x1b, 0xb3, 0x72, 0xbf, 0x10, 0x82, 0x3b, 0xf5, 0x1d, 0x9f, - 0x43, 0x0d, 0x0a, 0x42, 0xcf, 0x1a, 0xbd, 0x94, 0x65, 0xb9, 0xdc, 0x73, - 0x9b, 0xbe, 0xda, 0xc9, 0xb9, 0xa6, 0x65, 0x99, 0x48, 0xae, 0xa8, 0x62, - 0xe3, 0xc2, 0xe1, 0x53, 0x57, 0x01, 0x06, 0xa3, 0x63, 0xac, 0x3c, 0x7e, - 0x32, 0xa1, 0xf7, 0xbf, 0x73, 0xec, 0x38, 0x0e, 0x4d, 0x9b, 0x88, 0x94, - 0x5f, 0xbc, 0x1d, 0x8d, 0xd1, 0xff, 0x2d, 0x84, 0x73, 0x67, 0x24, 0x91, - 0x34, 0x65, 0xa9, 0xec, 0x70, 0x0d, 0x50, 0x52, 0x0d, 0xee, 0x94, 0x6a, - 0x43, 0xd9, 0x66, 0x57, 0x9e, 0x04, 0x2e, 0xa9, 0x02, 0x81, 0x81, 0x00, - 0xe0, 0x51, 0x82, 0x81, 0xb0, 0x47, 0xcc, 0xf7, 0xb3, 0xc2, 0x1e, 0xc7, - 0xc0, 0xc5, 0x35, 0xcf, 0x3e, 0xc7, 0x40, 0xa3, 0x01, 0x18, 0x4b, 0x8b, - 0x8a, 0xbd, 0x6c, 0x21, 0x9d, 0xf7, 0x73, 0xc6, 0x92, 0x04, 0x6e, 0x5a, - 0xf8, 0x89, 0x42, 0x1f, 0x27, 0x26, 0x9c, 0x00, 0x22, 0x0f, 0xa4, 0xbe, - 0xc9, 0x96, 0x20, 0xb5, 0xaa, 0xa7, 0x3e, 0x1d, 0xa2, 0x23, 0x3a, 0xa6, - 0x80, 0x1d, 0x52, 0xbb, 0xf2, 0xe8, 0x2d, 0x84, 0xa1, 0x81, 0x75, 0x6c, - 0x60, 0xc9, 0x39, 0x15, 0xaa, 0x6c, 0x56, 0x0a, 0x08, 0x24, 0x3f, 0xda, - 0xd4, 0x62, 0xed, 0xf2, 0x59, 0x10, 0x34, 0x14, 0xfa, 0x91, 0x08, 0x80, - 0xb2, 0x90, 0xba, 0x0f, 0x39, 0x45, 0x84, 0x69, 0x4a, 0xce, 0xbc, 0x71, - 0x24, 0x49, 0x4e, 0x53, 0x26, 0xd7, 0x38, 0x79, 0x05, 0xf7, 0x57, 0x7a, - 0x43, 0xd0, 0x55, 0xb6, 0xc1, 0x0b, 0xca, 0x4f, 0x02, 0x81, 0x80, 0x77, - 0x43, 0xc7, 0xf4, 0x78, 0xf7, 0xc1, 0xb6, 0x71, 0xdd, 0x87, 0x40, 0xa3, - 0x52, 0x78, 0x7e, 0x46, 0xc4, 0x77, 0x3e, 0x99, 0xc1, 0xe8, 0x1c, 0x4b, - 0xae, 0x82, 0x25, 0xe9, 0x2b, 0x40, 0x88, 0x87, 0x2b, 0xaa, 0x26, 0x0d, - 0x81, 0xe0, 0x96, 0x7c, 0x47, 0x51, 0x59, 0x1c, 0x12, 0x21, 0x43, 0xb2, - 0x52, 0x2d, 0x40, 0xf4, 0x32, 0x47, 0x74, 0x5c, 0x1c, 0x84, 0x2f, 0x71, - 0x24, 0xe4, 0x5c, 0x1d, 0xf7, 0xe1, 0xcf, 0xf0, 0xa0, 0x9e, 0x3d, 0xc6, - 0x85, 0xca, 0x77, 0x5a, 0x60, 0x8b, 0x1d, 0x15, 0x9c, 0xa0, 0xbe, 0x5f, - 0xbb, 0x32, 0x7a, 0xe3, 0x30, 0x91, 0xd7, 0xcb, 0x00, 0xd4, 0xea, 0xf7, - 0x82, 0xfe, 0xe5, 0xb3, 0x3d, 0x26, 0x92, 0xe3, 0xe6, 0xe6, 0xd9, 0xac, - 0xd8, 0x5b, 0xb0, 0x0e, 0xa8, 0xa9, 0x97, 0x8a, 0xfb, 0x8e, 0x6e, 0x62, - 0xbe, 0x78, 0x38, 0xfd, 0xdb, 0xaa, 0xa1, 0x02, 0x81, 0x81, 0x00, 0x93, - 0x65, 0x1b, 0xc3, 0x09, 0xc8, 0xf4, 0x26, 0xa3, 0x08, 0x5f, 0xdf, 0x53, - 0x8c, 0x82, 0x22, 0x0e, 0x97, 0x30, 0xa2, 0xab, 0x1a, 0x82, 0xb1, 0x4b, - 0x55, 0xd2, 0x52, 0x78, 0x90, 0xdb, 0x93, 0x53, 0xe8, 0xf3, 0x76, 0x75, - 0x2f, 0x03, 0xb2, 0xa2, 0xb0, 0x1c, 0xfb, 0x7d, 0x66, 0x18, 0x13, 0x81, - 0x34, 0x53, 0x83, 0xeb, 0x81, 0x7f, 0x30, 0x4b, 0x94, 0xa8, 0x7a, 0x35, - 0x5e, 0x8f, 0x39, 0x8e, 0x8f, 0xff, 0x30, 0xd2, 0x4a, 0xd5, 0x94, 0x84, - 0x38, 0x54, 0x79, 0x27, 0x05, 0x8e, 0xb7, 0x82, 0xc8, 0x06, 0xe9, 0x4c, - 0x7b, 0x40, 0xec, 0xe8, 0x96, 0xdc, 0x12, 0x18, 0xde, 0xe9, 0xde, 0x5e, - 0xf6, 0xf8, 0x3a, 0xfe, 0x9f, 0xee, 0x34, 0x9d, 0x82, 0x20, 0x92, 0x9b, - 0x8c, 0x4b, 0x9a, 0x19, 0xc0, 0x7b, 0x8c, 0x12, 0x5e, 0x87, 0x2d, 0x80, - 0x97, 0xc9, 0x6a, 0x8f, 0x88, 0xa6, 0xc3, 0x02, 0x81, 0x80, 0x4b, 0x44, - 0xe8, 0xb7, 0x47, 0xb0, 0x59, 0xf1, 0x58, 0x4e, 0x3f, 0x51, 0x37, 0x63, - 0xe0, 0xc5, 0xad, 0xf9, 0x32, 0x8d, 0x8f, 0xa4, 0xa6, 0xd3, 0x8e, 0x01, - 0xf4, 0xc0, 0xbd, 0x8e, 0x2d, 0xd7, 0x99, 0xf7, 0x23, 0x2d, 0x36, 0xd8, - 0xc9, 0x9e, 0xc0, 0x63, 0x00, 0xb1, 0xe7, 0xb6, 0xab, 0x0c, 0x95, 0x17, - 0xe3, 0x7c, 0x86, 0x64, 0x0c, 0x06, 0x00, 0x10, 0x8a, 0x23, 0x14, 0x1b, - 0xa6, 0xdb, 0xc9, 0xcc, 0xcb, 0x96, 0xcd, 0x38, 0x77, 0xa5, 0xb1, 0x02, - 0xf7, 0x49, 0x87, 0x1d, 0x6a, 0x2b, 0xfb, 0x40, 0x6b, 0x03, 0x4d, 0x04, - 0xdf, 0xed, 0x16, 0x1b, 0xbe, 0x3c, 0x03, 0xca, 0x68, 0x3f, 0x4c, 0x28, - 0xfc, 0x99, 0xf0, 0xdd, 0x23, 0x51, 0xc0, 0x87, 0x85, 0x17, 0xa9, 0x1f, - 0x18, 0xe0, 0x10, 0xd6, 0xca, 0xbf, 0xb6, 0x5c, 0x0c, 0xce, 0x4d, 0x2e, - 0x9e, 0x75, 0xf0, 0x71, 0xe0, 0x01 -}; - -unsigned int zepfull_private_der_len = 1218; diff --git a/samples/net/cloud/google_iot_mqtt/src/protocol.c b/samples/net/cloud/google_iot_mqtt/src/protocol.c deleted file mode 100644 index 7e62253583a..00000000000 --- a/samples/net/cloud/google_iot_mqtt/src/protocol.c +++ /dev/null @@ -1,407 +0,0 @@ -/* Protocol implementation. */ -/* - * Copyright (c) 2018-2019 Linaro Ltd - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -LOG_MODULE_DECLARE(net_google_iot_mqtt, LOG_LEVEL_DBG); -#include "protocol.h" - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include - -extern int64_t time_base; - -/* private key information */ -extern unsigned char zepfull_private_der[]; -extern unsigned int zepfull_private_der_len; - -/* - * This is the hard-coded root certificate that we accept. - */ -#include "globalsign.inc" - -static uint8_t client_id[] = CONFIG_CLOUD_CLIENT_ID; -static uint8_t client_username[] = "none"; -static uint8_t pub_topic[] = CONFIG_CLOUD_PUBLISH_TOPIC; - -static struct mqtt_publish_param pub_data; - -static uint8_t token[512]; - -static bool connected; -static uint64_t next_alive; - -/* The mqtt client struct */ -static struct mqtt_client client_ctx; - -/* MQTT Broker details. */ -static struct sockaddr_storage broker; - -/* Buffers for MQTT client. */ -static uint8_t rx_buffer[1024]; -static uint8_t tx_buffer[1024]; - -static sec_tag_t m_sec_tags[] = { -#if defined(MBEDTLS_X509_CRT_PARSE_C) - 1, -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) - APP_PSK_TAG, -#endif -}; - -/* Zephyr implementation of POSIX `time`. Has to be called k_time - * because time is already taken by newlib. The clock will be set by - * the SNTP client when it receives the time. We make no attempt to - * adjust it smoothly, and it should not be used for measuring - * intervals. Use `k_uptime_get()` directly for that. Also the - * time_t defined by newlib is a signed 32-bit value, and will - * overflow in 2037. - */ -time_t my_k_time(time_t *ptr) -{ - int64_t stamp; - time_t now; - - stamp = k_uptime_get(); - now = (time_t)((stamp + time_base) / 1000); - - if (ptr) { - *ptr = now; - } - - return now; -} - -void mqtt_subscribe_config(struct mqtt_client *const client) -{ -#ifdef CONFIG_CLOUD_SUBSCRIBE_CONFIG - /* subscribe to config information */ - struct mqtt_topic subs_topic = { - .topic = { - .utf8 = CONFIG_CLOUD_SUBSCRIBE_CONFIG, - .size = strlen(CONFIG_CLOUD_SUBSCRIBE_CONFIG) - }, - .qos = MQTT_QOS_1_AT_LEAST_ONCE - }; - const struct mqtt_subscription_list subs_list = { - .list = &subs_topic, - .list_count = 1U, - .message_id = 1U - }; - int err; - - err = mqtt_subscribe(client, &subs_list); - if (err) { - LOG_ERR("Failed to subscribe to %s item, error %d", - subs_topic.topic.utf8, err); - } -#endif -} - -void mqtt_evt_handler(struct mqtt_client *const client, - const struct mqtt_evt *evt) -{ - switch (evt->type) { - case MQTT_EVT_SUBACK: - LOG_INF("SUBACK packet id: %u", evt->param.suback.message_id); - break; - - case MQTT_EVT_UNSUBACK: - LOG_INF("UNSUBACK packet id: %u", - evt->param.suback.message_id); - break; - - case MQTT_EVT_CONNACK: - if (evt->result != 0) { - LOG_ERR("MQTT connect failed %d", evt->result); - break; - } - - connected = true; - LOG_INF("MQTT client connected!"); - - mqtt_subscribe_config(client); - - break; - - case MQTT_EVT_DISCONNECT: - LOG_INF("MQTT client disconnected %d", evt->result); - - connected = false; - - break; - -#ifdef CONFIG_CLOUD_SUBSCRIBE_CONFIG - case MQTT_EVT_PUBLISH: { - const struct mqtt_publish_param *pub = &evt->param.publish; - uint8_t d[33]; - int len = pub->message.payload.len; - int bytes_read; - - LOG_INF("MQTT publish received %d, %d bytes", - evt->result, len); - LOG_INF(" id: %d, qos: %d", - pub->message_id, - pub->message.topic.qos); - LOG_INF(" item: %s", - pub->message.topic.topic.utf8); - - /* assuming the config message is textual */ - while (len) { - bytes_read = mqtt_read_publish_payload_blocking( - client, d, - len >= 32 ? 32 : len); - if (bytes_read < 0) { - LOG_ERR("failure to read payload"); - break; - } - - d[bytes_read] = '\0'; - LOG_INF(" payload: %s", d); - len -= bytes_read; - } - - /* for MQTT_QOS_0_AT_MOST_ONCE no acknowledgment needed */ - if (pub->message.topic.qos == MQTT_QOS_1_AT_LEAST_ONCE) { - struct mqtt_puback_param puback = { - .message_id = pub->message_id - }; - - mqtt_publish_qos1_ack(client, &puback); - } - break; - } -#endif - - case MQTT_EVT_PUBACK: - if (evt->result != 0) { - LOG_ERR("MQTT PUBACK error %d", evt->result); - break; - } - - /* increment message id for when we send next message */ - pub_data.message_id += 1U; - LOG_INF("PUBACK packet id: %u", - evt->param.puback.message_id); - break; - - default: - LOG_INF("MQTT event received %d", evt->type); - break; - } -} - -static int wait_for_input(int timeout) -{ - int res; - struct zsock_pollfd fds[1] = { - [0] = {.fd = client_ctx.transport.tls.sock, - .events = ZSOCK_POLLIN, - .revents = 0}, - }; - - res = zsock_poll(fds, 1, timeout); - if (res < 0) { - LOG_ERR("poll read event error"); - return -errno; - } - - return res; -} - -#define ALIVE_TIME (60 * MSEC_PER_SEC) - -static struct mqtt_utf8 password = { - .utf8 = token -}; - -static struct mqtt_utf8 username = { - .utf8 = client_username, - .size = sizeof(client_username) -}; - -void mqtt_startup(char *hostname, int port) -{ - int err, cnt; - char pub_msg[64]; - struct sockaddr_in *broker4 = (struct sockaddr_in *)&broker; - struct mqtt_client *client = &client_ctx; - struct jwt_builder jb; - static struct zsock_addrinfo hints; - struct zsock_addrinfo *haddr; - int res = 0; - int retries = 5; - - mbedtls_platform_set_time(my_k_time); - - err = tls_credential_add(1, TLS_CREDENTIAL_CA_CERTIFICATE, - globalsign_certificate, - sizeof(globalsign_certificate)); - if (err < 0) { - LOG_ERR("Failed to register public certificate: %d", err); - } - - while (retries) { - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - cnt = 0; - while ((err = getaddrinfo("mqtt.googleapis.com", "8883", &hints, - &haddr)) && cnt < 3) { - LOG_ERR("Unable to get address for broker, retrying"); - cnt++; - } - - if (err != 0) { - LOG_ERR("Unable to get address for broker, error %d", - err); - return; - } - LOG_INF("DNS resolved for mqtt.googleapis.com:8883"); - - mqtt_client_init(client); - - time_t now = my_k_time(NULL); - - res = jwt_init_builder(&jb, token, sizeof(token)); - if (res != 0) { - LOG_ERR("Error with JWT token"); - return; - } - - res = jwt_add_payload(&jb, now + 60 * 60, now, - CONFIG_CLOUD_AUDIENCE); - if (res != 0) { - LOG_ERR("Error with JWT token"); - return; - } - - res = jwt_sign(&jb, zepfull_private_der, - zepfull_private_der_len); - - if (res != 0) { - LOG_ERR("Error with JWT token"); - return; - } - - - broker4->sin_family = AF_INET; - broker4->sin_port = htons(port); - net_ipaddr_copy(&broker4->sin_addr, - &net_sin(haddr->ai_addr)->sin_addr); - - /* MQTT client configuration */ - client->broker = &broker; - client->evt_cb = mqtt_evt_handler; - client->client_id.utf8 = client_id; - client->client_id.size = strlen(client_id); - client->password = &password; - password.size = jwt_payload_len(&jb); - client->user_name = &username; - client->protocol_version = MQTT_VERSION_3_1_1; - - /* MQTT buffers configuration */ - client->rx_buf = rx_buffer; - client->rx_buf_size = sizeof(rx_buffer); - client->tx_buf = tx_buffer; - client->tx_buf_size = sizeof(tx_buffer); - - /* MQTT transport configuration */ - client->transport.type = MQTT_TRANSPORT_SECURE; - - struct mqtt_sec_config *tls_config = - &client->transport.tls.config; - - tls_config->peer_verify = TLS_PEER_VERIFY_REQUIRED; - tls_config->cipher_list = NULL; - tls_config->sec_tag_list = m_sec_tags; - tls_config->sec_tag_count = ARRAY_SIZE(m_sec_tags); - tls_config->hostname = hostname; - - LOG_INF("Connecting to host: %s", hostname); - err = mqtt_connect(client); - if (err != 0) { - LOG_ERR("could not connect, error %d", err); - mqtt_disconnect(client); - retries--; - k_msleep(ALIVE_TIME); - continue; - } - - if (wait_for_input(5 * MSEC_PER_SEC) > 0) { - mqtt_input(client); - if (!connected) { - LOG_ERR("failed to connect to mqtt_broker"); - mqtt_disconnect(client); - retries--; - k_msleep(ALIVE_TIME); - continue; - } else { - break; - } - } else { - LOG_ERR("failed to connect to mqtt broker"); - mqtt_disconnect(client); - retries--; - k_msleep(ALIVE_TIME); - continue; - } - } - - if (!connected) { - LOG_ERR("Failed to connect to client, aborting"); - return; - } - - /* initialize publish structure */ - pub_data.message.topic.topic.utf8 = pub_topic; - pub_data.message.topic.topic.size = strlen(pub_topic); - pub_data.message.topic.qos = MQTT_QOS_1_AT_LEAST_ONCE; - pub_data.message.payload.data = (uint8_t *)pub_msg; - pub_data.message_id = 1U; - pub_data.dup_flag = 0U; - pub_data.retain_flag = 1U; - - mqtt_live(client); - - next_alive = k_uptime_get() + ALIVE_TIME; - - while (1) { - LOG_INF("Publishing data"); - sprintf(pub_msg, "%s: %d\n", "payload", pub_data.message_id); - pub_data.message.payload.len = strlen(pub_msg); - err = mqtt_publish(client, &pub_data); - if (err) { - LOG_ERR("could not publish, error %d", err); - break; - } - - /* idle and process messages */ - while (k_uptime_get() < next_alive) { - LOG_INF("... idling ..."); - if (wait_for_input(5 * MSEC_PER_SEC) > 0) { - mqtt_input(client); - } - } - - mqtt_live(client); - next_alive += ALIVE_TIME; - } -} diff --git a/samples/net/cloud/google_iot_mqtt/src/protocol.h b/samples/net/cloud/google_iot_mqtt/src/protocol.h deleted file mode 100644 index 9378688c933..00000000000 --- a/samples/net/cloud/google_iot_mqtt/src/protocol.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2018 Linaro Ltd - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/* - * MQTT-based cloud protocol engine. - */ - -#ifndef PROTOCOL_H__ -#define PROTOCOL_H__ - -#include - -void mqtt_startup(char *hostname, int port); - -#endif diff --git a/samples/net/cloud/google_iot_mqtt/src/tls_config/user-tls-conf.h b/samples/net/cloud/google_iot_mqtt/src/tls_config/user-tls-conf.h deleted file mode 100644 index 035f2b062ec..00000000000 --- a/samples/net/cloud/google_iot_mqtt/src/tls_config/user-tls-conf.h +++ /dev/null @@ -1,5 +0,0 @@ -#define MBEDTLS_AES_ROM_TABLES - -#define MBEDTLS_HAVE_TIME -#define MBEDTLS_HAVE_TIME_DATE -#define MBEDTLS_PLATFORM_TIME_ALT diff --git a/samples/net/cloud/mqtt_azure/README.rst b/samples/net/cloud/mqtt_azure/README.rst index a1414b8df43..1369b83d0e5 100644 --- a/samples/net/cloud/mqtt_azure/README.rst +++ b/samples/net/cloud/mqtt_azure/README.rst @@ -1,7 +1,8 @@ -.. _mqtt-azure-sample: +.. zephyr:code-sample:: mqtt-azure + :name: Microsoft Azure IoT Hub MQTT + :relevant-api: bsd_sockets mqtt_socket tls_credentials random_api -MQTT Azure Sample -################# + Connect to Azure IoT Hub and publish messages using MQTT. Overview ******** diff --git a/samples/net/cloud/mqtt_azure/prj.conf b/samples/net/cloud/mqtt_azure/prj.conf index e3b8ac83edb..27b703bf585 100644 --- a/samples/net/cloud/mqtt_azure/prj.conf +++ b/samples/net/cloud/mqtt_azure/prj.conf @@ -47,7 +47,7 @@ CONFIG_DNS_RESOLVER=y CONFIG_DNS_SERVER_IP_ADDRESSES=y CONFIG_DNS_SERVER1="8.8.8.8" CONFIG_DNS_RESOLVER_ADDITIONAL_BUF_CTR=2 -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_INIT_STACKS=y CONFIG_NET_SHELL=y diff --git a/samples/net/cloud/mqtt_azure/sample.yaml b/samples/net/cloud/mqtt_azure/sample.yaml index 2f234d39481..ffa3e866895 100644 --- a/samples/net/cloud/mqtt_azure/sample.yaml +++ b/samples/net/cloud/mqtt_azure/sample.yaml @@ -1,5 +1,5 @@ common: - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED sample: description: MQTT sample app to Azure cloud name: mqtt-azure diff --git a/samples/net/cloud/mqtt_azure/src/main.c b/samples/net/cloud/mqtt_azure/src/main.c index c3cf2a568fa..420750e416c 100644 --- a/samples/net/cloud/mqtt_azure/src/main.c +++ b/samples/net/cloud/mqtt_azure/src/main.c @@ -12,7 +12,7 @@ LOG_MODULE_REGISTER(mqtt_azure, LOG_LEVEL_DBG); #include #include -#include +#include #include #include @@ -60,7 +60,7 @@ static K_SEM_DEFINE(mqtt_start, 0, 1); #define TLS_SNI_HOSTNAME CONFIG_SAMPLE_CLOUD_AZURE_HOSTNAME #define APP_CA_CERT_TAG 1 -static sec_tag_t m_sec_tags[] = { +static const sec_tag_t m_sec_tags[] = { APP_CA_CERT_TAG, }; diff --git a/samples/net/cloud/tagoio_http_post/README.rst b/samples/net/cloud/tagoio_http_post/README.rst index 235a35265e4..dc0f2b9da6c 100644 --- a/samples/net/cloud/tagoio_http_post/README.rst +++ b/samples/net/cloud/tagoio_http_post/README.rst @@ -1,7 +1,8 @@ -.. _cloud-tagoio-http-post-sample: +.. zephyr:code-sample:: tagoio-http-post + :name: TagoIO HTTP Post + :relevant-api: bsd_sockets http_client dns_resolve tls_credentials -TagoIO IoT Cloud HTTP Sample -############################ + Send random temperature values to TagoIO IoT Cloud Platform using HTTP. Overview ******** diff --git a/samples/net/cloud/tagoio_http_post/src/main.c b/samples/net/cloud/tagoio_http_post/src/main.c index 29edb2c7084..fb97c15c18e 100644 --- a/samples/net/cloud/tagoio_http_post/src/main.c +++ b/samples/net/cloud/tagoio_http_post/src/main.c @@ -10,7 +10,7 @@ LOG_MODULE_REGISTER(tagoio_http_post, CONFIG_TAGOIO_HTTP_POST_LOG_LEVEL); #include #include #include -#include +#include #include #include "wifi.h" diff --git a/samples/net/dhcpv4_client/README.rst b/samples/net/dhcpv4_client/README.rst index 60e985eb0a9..e8c232a7e94 100644 --- a/samples/net/dhcpv4_client/README.rst +++ b/samples/net/dhcpv4_client/README.rst @@ -1,7 +1,8 @@ -.. _dhcpv4-client-sample: +.. zephyr:code-sample:: dhcpv4-client + :name: DHCPv4 client + :relevant-api: dhcpv4 net_mgmt -Sample DHCPv4 client application -################################ + Start a DHCPv4 client to obtain an IPv4 address from a DHCPv4 server. Overview ******** diff --git a/samples/net/dns_resolve/README.rst b/samples/net/dns_resolve/README.rst index 28cfabdf013..ac2ea0f391b 100644 --- a/samples/net/dns_resolve/README.rst +++ b/samples/net/dns_resolve/README.rst @@ -1,7 +1,8 @@ -.. _dns-resolve-sample: +.. zephyr:code-sample:: dns-resolve + :name: DNS resolve + :relevant-api: dns_resolve net_mgmt -DNS Resolve Application -####################### + Resolve an IP address for a given hostname. Overview ******** diff --git a/samples/net/dsa/README.rst b/samples/net/dsa/README.rst index 588adf28db1..729aac7785e 100644 --- a/samples/net/dsa/README.rst +++ b/samples/net/dsa/README.rst @@ -1,7 +1,8 @@ -.. _dsa-sample: +.. zephyr:code-sample:: dsa + :name: DSA (Distributed Switch Architecture) + :relevant-api: DSA -DSA Sample Application -###################### + Test and debug Distributed Switch Architecture Overview ******** diff --git a/samples/net/dsa/prj.conf b/samples/net/dsa/prj.conf index 952aa9d272f..6309976db06 100644 --- a/samples/net/dsa/prj.conf +++ b/samples/net/dsa/prj.conf @@ -49,7 +49,7 @@ CONFIG_NET_TC_TX_COUNT=6 CONFIG_NET_TC_RX_COUNT=4 CONFIG_NET_CONFIG_INIT_TIMEOUT=10 -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_NET_IF_MAX_IPV4_COUNT=4 CONFIG_NET_IF_MAX_IPV6_COUNT=4 diff --git a/samples/net/eth_native_posix/CMakeLists.txt b/samples/net/eth_native_posix/CMakeLists.txt deleted file mode 100644 index 4b116d7f47f..00000000000 --- a/samples/net/eth_native_posix/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(eth_native_posix) - -target_sources(app PRIVATE src/main.c) - -include(${ZEPHYR_BASE}/samples/net/common/common.cmake) diff --git a/samples/net/eth_native_posix/README.rst b/samples/net/eth_native_posix/README.rst deleted file mode 100644 index 2ec9c55c52d..00000000000 --- a/samples/net/eth_native_posix/README.rst +++ /dev/null @@ -1,146 +0,0 @@ -.. _eth-native-posix-sample: - -Native Posix Ethernet -##################### - -Overview -******** - -The eth_native_posix sample application for Zephyr creates a **zeth** network -interface to the host system. One can communicate with Zephyr via this network -interface. - -The source code for this sample application can be found at: -:zephyr_file:`samples/net/eth_native_posix`. - -Building And Running -******************** - -To build the eth_native_posix sample application, follow the steps -below. - -.. zephyr-app-commands:: - :zephyr-app: samples/net/eth_native_posix - :host-os: unix - :board: native_posix - :conf: - :goals: build - :compact: - -Normally one needs extra privileges to create and configure the TAP device in -the host system. If the user has set the -:kconfig:option:`CONFIG_ETH_NATIVE_POSIX_STARTUP_AUTOMATIC` option (this is disabled -by default), then the user needs to use ``sudo`` to execute the Zephyr process -with admin privileges, like this: - -.. code-block:: console - - sudo --preserve-env=ZEPHYR_BASE make -Cbuild run - -If the ``sudo --preserve-env=ZEPHYR_BASE`` gives an error, -just use ``sudo --preserve-env`` instead. - -If the :kconfig:option:`CONFIG_ETH_NATIVE_POSIX_STARTUP_AUTOMATIC` option -is not enabled (this is the default), then the user should -execute the ``net-setup.sh`` script from Zephyr `net-tools`_ repository. -The script should be run before executing the Zephyr process. The script -will create the zeth interface and set up IP addresses and routes. -While running ``net-setup.sh`` requires root access, afterwards Zephyr -process can be run as a non-root user. - -You can run the ``net-setup.sh`` script like this:: - - cd net-tools - sudo ./net-setup.sh - -or:: - - sudo ./net-setup.sh --config ./zeth-vlan.conf - -See also other command line options by typing ``net-setup.sh --help``. - -When the network interface is set up manually, you can leave the wireshark -to monitor the interface, and then start and stop the zephyr process without -stopping the wireshark. - -Setting things manually works the same as working with SLIP connectivity -in QEMU. - -If you want to connect two Zephyr instances together, you can do it like this: - -Create two Zephyr config files prj1.conf and prj2.conf. You can use -:zephyr_file:`samples/net/eth_native_posix/prj.conf` as a base. - -Set prj1.conf IP address configuration like this: - -.. code-block:: console - - CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8:100::1" - CONFIG_NET_CONFIG_PEER_IPV6_ADDR="2001:db8:100::2" - CONFIG_NET_CONFIG_MY_IPV4_ADDR="198.51.100.1" - CONFIG_NET_CONFIG_PEER_IPV4_ADDR="198.51.100.2" - CONFIG_NET_CONFIG_MY_IPV4_GW="203.0.113.1" - CONFIG_ETH_NATIVE_POSIX_RANDOM_MAC=n - CONFIG_ETH_NATIVE_POSIX_MAC_ADDR="00:00:5e:00:53:64" - CONFIG_ETH_NATIVE_POSIX_SETUP_SCRIPT="echo" - CONFIG_ETH_NATIVE_POSIX_DRV_NAME="zeth.1" - -Set prj2.conf IP address configuration like this: - -.. code-block:: console - - CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8:200::1" - CONFIG_NET_CONFIG_PEER_IPV6_ADDR="2001:db8:200::2" - CONFIG_NET_CONFIG_MY_IPV4_ADDR="203.0.113.1" - CONFIG_NET_CONFIG_PEER_IPV4_ADDR="203.0.113.2" - CONFIG_NET_CONFIG_MY_IPV4_GW="198.51.100.1" - CONFIG_ETH_NATIVE_POSIX_RANDOM_MAC=n - CONFIG_ETH_NATIVE_POSIX_MAC_ADDR="00:00:5e:00:53:c8" - CONFIG_ETH_NATIVE_POSIX_SETUP_SCRIPT="echo" - CONFIG_ETH_NATIVE_POSIX_DRV_NAME="zeth.2" - -Then compile and run two Zephyr instances -(if ``sudo --preserve-env=ZEPHYR_BASE`` gives an error, -just use ``sudo --preserve-env`` instead): - -.. code-block:: console - - cmake -DCONF_FILE=prj1.conf -DBOARD=native_posix -Bbuild1/native_posix . - make -s -C build1/native_posix - sudo --preserve-env=ZEPHYR_BASE make -s -C build1/native_posix run - -.. code-block:: console - - cmake -DCONF_FILE=prj2.conf -DBOARD=native_posix -Bbuild2/native_posix . - make -s -C build2/native_posix - sudo --preserve-env=ZEPHYR_BASE make -s -C build2/native_posix run - -Bridge the two Zephyr instances together: - -.. code-block:: console - - sudo brctl addbr zeth-br - sudo brctl addif zeth-br zeth.1 - sudo brctl addif zeth-br zeth.2 - sudo ifconfig zeth-br up - -After this, you are able to ping device 1 from device 2 in net-shell: - -.. code-block:: console - - # In device 1 - net ping 2001:db8:200::1 - net ping 203.0.113.1 - -.. code-block:: console - - # In device 2 - net ping 2001:db8:100::1 - net ping 198.51.100.1 - -Note that in this setup you cannot access these two Zephyr devices from -your host. If you want to do that, then you could create a new network -interface with proper IP addresses and add that interface to the Zephyr -bridge. - -.. _`net-tools`: https://github.com/zephyrproject-rtos/net-tools diff --git a/samples/net/eth_native_posix/net_setup_host b/samples/net/eth_native_posix/net_setup_host deleted file mode 100755 index e1ee7b80c09..00000000000 --- a/samples/net/eth_native_posix/net_setup_host +++ /dev/null @@ -1,81 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2018 Intel Corporation -# -# 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. - -# This script is called by native-posix board when TAP network interface -# is taken up by Zephyr. The script should setup the host system so that -# connectivity will work with Zephyr. - -while [ $# -gt 0 ]; do - case "$1" in - -f|--file) - CONF_FILE="$2" - shift - shift;; - -i|--interface) - # Only first -i option is taken into account. This way - # the driver added -i option is ignored if user has specified - # the -i option to host setup script command. - if [ -z "$IFACE" ]; then - IFACE="$2" - fi - shift - shift;; - *) - shift;; - esac -done - -if [ `id -u` != 0 ]; then - echo "Warning: This script will need admin rights to setup \ -network interface!" -fi - -if [ -z "$IFACE" ]; then - IFACE="zeth" -fi - -if [ -z "$CONF_FILE" ]; then - DIR=`dirname $0` - CONF_FILE="$DIR/net_setup_host.conf" -fi - -if [ -f "$CONF_FILE" ]; then - . $CONF_FILE -else - echo "Warning: config file $CONF_FILE does not exist!" -fi - -ip link set dev $IFACE up - -if [ ! -z "$HWADDR" ]; then - ip link set dev $IFACE address $HWADDR -fi - -if [ ! -z "$IPV6_ADDR_1" ]; then - ip -6 address add $IPV6_ADDR_1 dev $IFACE -fi - -if [ ! -z "$IPV6_ROUTE_1" ]; then - ip -6 route add $IPV6_ROUTE_1 dev $IFACE -fi - -if [ ! -z "$IPV4_ADDR_1" ]; then - ip address add $IPV4_ADDR_1 dev $IFACE -fi - -if [ ! -z "$IPV4_ROUTE_1" ]; then - ip route add $IPV4_ROUTE_1 dev $IFACE -fi diff --git a/samples/net/eth_native_posix/net_setup_host.conf b/samples/net/eth_native_posix/net_setup_host.conf deleted file mode 100644 index 4e6ab7a5574..00000000000 --- a/samples/net/eth_native_posix/net_setup_host.conf +++ /dev/null @@ -1,11 +0,0 @@ -# -# Configuration options for setting up the host network interface -# - -HWADDR="00:00:5e:00:53:ff" - -IPV6_ADDR_1="2001:db8::2" -IPV6_ROUTE_1="2001:db8::/64" - -IPV4_ADDR_1="192.0.2.2" -IPV4_ROUTE_1="192.0.2.0/24" diff --git a/samples/net/eth_native_posix/net_start_wireshark.sh b/samples/net/eth_native_posix/net_start_wireshark.sh deleted file mode 100755 index 2fcdeded9d1..00000000000 --- a/samples/net/eth_native_posix/net_start_wireshark.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2018 Intel Corporation -# -# 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. - -# This script can be called by native-posix board when TAP network interface -# is created. This script will start wireshark so that it is possible to -# monitor the network traffic for the interface. - -if [ ! -z "$1" ]; then - IFACE="$1" -else - IFACE="zeth" -fi - -WIRESHARK="wireshark -k -i $IFACE" - -echo "Starting \"$WIRESHARK\" as \"`id -u -n`\" user." - -$WIRESHARK & - -# The startup of wireshark is slow so sleep here a bit so that everything -# in wireshark is setup properly before continuing with zephyr startup. -sleep 5 diff --git a/samples/net/eth_native_posix/prj.conf b/samples/net/eth_native_posix/prj.conf deleted file mode 100644 index dedd8e86bfc..00000000000 --- a/samples/net/eth_native_posix/prj.conf +++ /dev/null @@ -1,40 +0,0 @@ -CONFIG_NETWORKING=y -CONFIG_NET_UDP=y -CONFIG_NET_TCP=y -CONFIG_NET_IPV6=y -CONFIG_NET_IPV4=y -#CONFIG_NET_DHCPV4=y - -CONFIG_ENTROPY_GENERATOR=y -CONFIG_TEST_RANDOM_GENERATOR=y -CONFIG_INIT_STACKS=y - -CONFIG_NET_LOG=y -CONFIG_LOG=y - -CONFIG_NET_STATISTICS=y - -CONFIG_NET_PKT_RX_COUNT=32 -CONFIG_NET_PKT_TX_COUNT=32 -CONFIG_NET_BUF_RX_COUNT=32 -CONFIG_NET_BUF_TX_COUNT=32 - -CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3 -CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=4 -CONFIG_NET_MAX_CONTEXTS=10 - -CONFIG_NET_SHELL=y - -CONFIG_NET_CONFIG_SETTINGS=y -CONFIG_NET_CONFIG_NEED_IPV6=y -CONFIG_NET_CONFIG_NEED_IPV4=y -CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1" -CONFIG_NET_CONFIG_PEER_IPV6_ADDR="2001:db8::2" -CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1" -CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2" - -CONFIG_NET_L2_ETHERNET=y - -CONFIG_ETH_NATIVE_POSIX=y -CONFIG_ETH_NATIVE_POSIX_RANDOM_MAC=y -#CONFIG_ETH_NATIVE_POSIX_MAC_ADDR="00:00:5e:00:53:2a" diff --git a/samples/net/eth_native_posix/sample.yaml b/samples/net/eth_native_posix/sample.yaml deleted file mode 100644 index d60d6adf68b..00000000000 --- a/samples/net/eth_native_posix/sample.yaml +++ /dev/null @@ -1,13 +0,0 @@ -common: - harness: net - tags: net -sample: - description: Can be used to test native posix connectivity via ethernet. - name: Native posix ethernet demo application -tests: - sample.net.eth_native_posix: - platform_allow: - - native_posix - - native_posix_64 - integration_platforms: - - native_posix diff --git a/samples/net/eth_native_posix/src/main.c b/samples/net/eth_native_posix/src/main.c deleted file mode 100644 index fccb0ddde9d..00000000000 --- a/samples/net/eth_native_posix/src/main.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2018 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -LOG_MODULE_REGISTER(net_native_posix_sample, LOG_LEVEL_DBG); - -#include -#include - -#include - -/* This application itself does nothing as there is net-shell that can be used - * to monitor things. - */ -int main(void) -{ - LOG_INF("Start application"); - return 0; -} diff --git a/samples/net/gptp/README.rst b/samples/net/gptp/README.rst index 4b7f6a100fc..f0c1b39e958 100644 --- a/samples/net/gptp/README.rst +++ b/samples/net/gptp/README.rst @@ -1,7 +1,8 @@ -.. _gptp-sample: +.. zephyr:code-sample:: gptp + :name: gPTP + :relevant-api: gptp ptp_time -gPTP Sample Application -####################### + Enable gPTP support and monitor functionality using net-shell. Overview ******** @@ -18,13 +19,13 @@ Requirements ************ For generic host connectivity, that can be used for debugging purposes, see -:ref:`networking_with_native_posix` for details. +:ref:`networking_with_native_sim` for details. Building and Running ******************** A good way to run this sample is to run this gPTP application inside -native_posix board as described in :ref:`networking_with_native_posix` or with +native_sim board as described in :ref:`networking_with_native_sim` or with embedded device like NXP FRDM-K64F, Nucleo-H743-ZI, Nucleo-H745ZI-Q, Nucleo-F767ZI or Atmel SAM-E70 Xplained. Note that gPTP is only supported for boards that have an Ethernet port and which has support for collecting @@ -50,7 +51,7 @@ Setting up Linux Host If you need VLAN support in your network, then the :zephyr_file:`samples/net/vlan/vlan-setup-linux.sh` provides a script that can be executed on the Linux host. It creates two VLANs on the Linux host and creates -routes to Zephyr. If you are using native_posix board, then +routes to Zephyr. If you are using native_sim board, then the ``net-setup.sh`` will create VLAN setup automatically with this command: .. code-block:: console @@ -60,9 +61,9 @@ the ``net-setup.sh`` will create VLAN setup automatically with this command: The OpenAVNU repository at https://github.com/AVnu contains gPTP daemon that can be run in Linux host and which can act as a grandmaster for the IEEE 801.1AS network. Note that OpenAVNU will not work with -native_posix board as that board only supports software timestamping and +native_sim board as that board only supports software timestamping and OpenAVNU only supports hardware timestamping. See instructions at the end -of this chapter how to run linuxptp daemon with native_posix board. +of this chapter how to run linuxptp daemon with native_sim board. Get OpenAvnu/gPTP project sources @@ -125,7 +126,7 @@ By default gPTP in Zephyr will not print any gPTP debug messages to console. One can enable debug prints by setting :kconfig:option:`CONFIG_NET_GPTP_LOG_LEVEL_DBG` in the config file. -For native_posix board, use ``linuxptp`` project as that supports +For native_sim board, use ``linuxptp`` project as that supports software timestamping. Get linuxptp project sources @@ -149,7 +150,7 @@ Multiport Setup If you set :kconfig:option:`CONFIG_NET_GPTP_NUM_PORTS` larger than 1, then gPTP sample will create multiple TSN ports. This configuration is currently only supported -in native_posix board. +in native_sim board. You need to enable the ports in the net-tools. If the number of ports is set to 2, then give following commands to create the network interfaces in host @@ -162,7 +163,7 @@ side: After that you can start ptp4l daemon for both interfaces. Please use two terminals when starting ptp4l daemon. Note that you must use ptp4l as OpenAVNU -does not work with software clock available in native_posix. +does not work with software clock available in native_sim. .. code-block:: console @@ -174,7 +175,7 @@ Compile Zephyr application. .. zephyr-app-commands:: :zephyr-app: samples/net/gptp - :board: native_posix + :board: native_sim :goals: build :compact: diff --git a/samples/net/gptp/boards/mimxrt1050_evk.conf b/samples/net/gptp/boards/mimxrt1050_evk.conf index eeef6eaba02..2819d3afd66 100644 --- a/samples/net/gptp/boards/mimxrt1050_evk.conf +++ b/samples/net/gptp/boards/mimxrt1050_evk.conf @@ -7,5 +7,5 @@ CONFIG_ETH_MCUX_PTP_CLOCK_SRC_HZ=25000000 CONFIG_ETH_MCUX_RX_BUFFERS=6 CONFIG_ETH_MCUX_TX_BUFFERS=4 CONFIG_NET_GPTP_STATISTICS=y -CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y +CONFIG_REQUIRES_FLOAT_PRINTF=y diff --git a/samples/net/gptp/boards/mimxrt1060_evk.conf b/samples/net/gptp/boards/mimxrt1060_evk.conf index f12f5ebf34d..114cebd8fe8 100644 --- a/samples/net/gptp/boards/mimxrt1060_evk.conf +++ b/samples/net/gptp/boards/mimxrt1060_evk.conf @@ -6,6 +6,6 @@ CONFIG_NET_GPTP_CLOCK_ACCURACY_25MS=y #CONFIG_ETH_MCUX_RX_BUFFERS=6 #CONFIG_ETH_MCUX_TX_BUFFERS=8 CONFIG_NET_GPTP_STATISTICS=y -CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FLOAT_PRINTF=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_NET_GPTP_INIT_LOG_PDELAY_REQ_ITV=-3 diff --git a/samples/net/gptp/boards/native_sim.conf b/samples/net/gptp/boards/native_sim.conf new file mode 100644 index 00000000000..c514520186c --- /dev/null +++ b/samples/net/gptp/boards/native_sim.conf @@ -0,0 +1,8 @@ +# Settings for native_posix ethernet driver +CONFIG_ETH_NATIVE_POSIX_PTP_CLOCK=y + +#CONFIG_ETH_NATIVE_POSIX_RANDOM_MAC=y +CONFIG_ETH_NATIVE_POSIX_MAC_ADDR="00:00:5e:00:53:2a" + +# Assume 1 ms accuracy for native_posix simulated clock +CONFIG_NET_GPTP_CLOCK_ACCURACY_1MS=y diff --git a/samples/net/gptp/boards/native_sim_64.conf b/samples/net/gptp/boards/native_sim_64.conf new file mode 100644 index 00000000000..c514520186c --- /dev/null +++ b/samples/net/gptp/boards/native_sim_64.conf @@ -0,0 +1,8 @@ +# Settings for native_posix ethernet driver +CONFIG_ETH_NATIVE_POSIX_PTP_CLOCK=y + +#CONFIG_ETH_NATIVE_POSIX_RANDOM_MAC=y +CONFIG_ETH_NATIVE_POSIX_MAC_ADDR="00:00:5e:00:53:2a" + +# Assume 1 ms accuracy for native_posix simulated clock +CONFIG_NET_GPTP_CLOCK_ACCURACY_1MS=y diff --git a/samples/net/gptp/docker-test.sh b/samples/net/gptp/docker-test.sh index 03ab0f48aa7..bc791584c0b 100644 --- a/samples/net/gptp/docker-test.sh +++ b/samples/net/gptp/docker-test.sh @@ -14,7 +14,7 @@ start_docker \ "/usr/local/sbin/ptp4l -2 -f /etc/gptp.cfg -m -q -l 6 -S -i eth0" \ || return $? -# For native_posix gPTP run, the delay threshold needs to be huge +# For native_sim gPTP run, the delay threshold needs to be huge start_zephyr "$overlay" "-DCONFIG_NET_SAMPLE_RUN_DURATION=10" \ "-DCONFIG_NET_GPTP_NEIGHBOR_PROP_DELAY_THR=12000000" diff --git a/samples/net/gptp/sample.yaml b/samples/net/gptp/sample.yaml index 0184353569e..a668d6325a5 100644 --- a/samples/net/gptp/sample.yaml +++ b/samples/net/gptp/sample.yaml @@ -13,6 +13,8 @@ tests: - sam_e70_xplained - native_posix - native_posix_64 + - native_sim + - native_sim_64 - nucleo_f767zi - nucleo_h743zi - nucleo_h745zi_q_m7 diff --git a/samples/net/gsm_modem/README.rst b/samples/net/gsm_modem/README.rst index aebfc2ab3a5..2021b0e0554 100644 --- a/samples/net/gsm_modem/README.rst +++ b/samples/net/gsm_modem/README.rst @@ -1,7 +1,7 @@ -.. _gsm-modem-sample: +.. zephyr:code-sample:: gsm-modem + :name: Generic GSM modem -Generic GSM Modem Sample -######################## + Use a GSM modem to connect to a GPRS network. Overview ******** diff --git a/samples/net/ipv4_autoconf/README.rst b/samples/net/ipv4_autoconf/README.rst index 1ee783cbe41..614f2c64047 100644 --- a/samples/net/ipv4_autoconf/README.rst +++ b/samples/net/ipv4_autoconf/README.rst @@ -1,7 +1,8 @@ -.. _ipv4-autoconf-sample: +.. zephyr:code-sample:: ipv4-autoconf + :name: IPv4 autoconf client + :relevant-api: networking net_if net_context net_mgmt -IPv4 autoconf client application -################################ + Perform IPv4 autoconfiguration and self-assign a random IPv4 address Overview ******** diff --git a/samples/net/ipv4_autoconf/sample.yaml b/samples/net/ipv4_autoconf/sample.yaml index bb1f529ef4b..07260fee0ad 100644 --- a/samples/net/ipv4_autoconf/sample.yaml +++ b/samples/net/ipv4_autoconf/sample.yaml @@ -7,8 +7,10 @@ common: - qemu_x86 - native_posix - native_posix_64 + - native_sim + - native_sim_64 integration_platforms: - - native_posix + - native_sim sample: description: Test IPv4 autoconf functionality name: IPv4 autoconf sample app diff --git a/samples/net/lldp/README.rst b/samples/net/lldp/README.rst index 856c4342910..ba392d8be94 100644 --- a/samples/net/lldp/README.rst +++ b/samples/net/lldp/README.rst @@ -1,7 +1,8 @@ -.. _lldp-sample: +.. zephyr:code-sample:: lldp + :name: Link Layer Discovery Protocol (LLDP) + :relevant-api: lldp net_l2 -LLDP Sample Application -####################### + Enable LLDP support and setup VLANs. Overview ******** diff --git a/samples/net/lldp/sample.yaml b/samples/net/lldp/sample.yaml index 78b61768ee6..4daf567dca2 100644 --- a/samples/net/lldp/sample.yaml +++ b/samples/net/lldp/sample.yaml @@ -11,6 +11,8 @@ tests: platform_allow: - native_posix - native_posix_64 + - native_sim + - native_sim_64 integration_platforms: - - native_posix + - native_sim depends_on: netif diff --git a/samples/net/lwm2m_client/README.rst b/samples/net/lwm2m_client/README.rst index c05a1149d31..2225f789c0c 100644 --- a/samples/net/lwm2m_client/README.rst +++ b/samples/net/lwm2m_client/README.rst @@ -1,7 +1,8 @@ -.. _lwm2m-client-sample: +.. zephyr:code-sample:: lwm2m-client + :name: LwM2M client + :relevant-api: lwm2m_api -LwM2M client -############ + Implement a LwM2M client that connects to a LwM2M server. Overview ******** @@ -24,7 +25,7 @@ The source code for this sample application can be found at: Requirements ************ -- :ref:`networking_with_eth_qemu`, :ref:`networking_with_qemu` or :ref:`networking_with_native_posix` +- :ref:`networking_with_eth_qemu`, :ref:`networking_with_qemu` or :ref:`networking_with_native_sim` - Linux machine - Leshan Demo Server (https://eclipse.org/leshan/) @@ -67,8 +68,8 @@ Build the lwm2m-client sample application like this: :compact: The easiest way to setup this sample application is to build and run it -as native POSIX application or as a QEMU target using the default configuration :file:`prj.conf`. -This requires a small amount of setup described in :ref:`networking_with_eth_qemu`, :ref:`networking_with_qemu` and :ref:`networking_with_native_posix`. +as a native_sim application or as a QEMU target using the default configuration :file:`prj.conf`. +This requires a small amount of setup described in :ref:`networking_with_eth_qemu`, :ref:`networking_with_qemu` and :ref:`networking_with_native_sim`. Download and run the latest build of the Leshan Demo Server: diff --git a/samples/net/lwm2m_client/boards/native_sim.conf b/samples/net/lwm2m_client/boards/native_sim.conf new file mode 100644 index 00000000000..3e21f837f7c --- /dev/null +++ b/samples/net/lwm2m_client/boards/native_sim.conf @@ -0,0 +1,5 @@ +CONFIG_DNS_RESOLVER=y +CONFIG_DNS_SERVER_IP_ADDRESSES=y +CONFIG_DNS_SERVER1="192.0.2.2" +CONFIG_LWM2M_DNS_SUPPORT=y +CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2" diff --git a/samples/net/lwm2m_client/boards/qemu_x86.conf b/samples/net/lwm2m_client/boards/qemu_x86.conf index c099c8e81df..5a1dc0925c3 100644 --- a/samples/net/lwm2m_client/boards/qemu_x86.conf +++ b/samples/net/lwm2m_client/boards/qemu_x86.conf @@ -1 +1,5 @@ CONFIG_FPU=y +CONFIG_NET_L2_ETHERNET=y +CONFIG_NET_QEMU_ETHERNET=y + +CONFIG_PCIE=y diff --git a/samples/net/lwm2m_client/docker-test.sh b/samples/net/lwm2m_client/docker-test.sh new file mode 100644 index 00000000000..a7200b21b4b --- /dev/null +++ b/samples/net/lwm2m_client/docker-test.sh @@ -0,0 +1,29 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if [ -z "$RUNNING_FROM_MAIN_SCRIPT" ]; then + echo "Do not run this script directly!" + echo "Run $ZEPHYR_BASE/scripts/net/run-sample-tests.sh instead." + exit 1 +fi + +IP="--ip=192.0.2.2 --ip6=2001:db8::2" +FWD="-p 8080:8080 -p 8081:8081 -p 5683:5683/udp" + +start_configuration "$IP $FWD" || return $? +start_docker "/net-tools/start-leshan.sh" || return $? + +start_zephyr + +sleep 5 +curl -s -X GET 'http://localhost:8080/api/clients/native_posix/3/0/0' | grep Zephyr 2>&1 >/dev/null +result=$? + +stop_zephyr +stop_docker + +if [ $result -eq 0 ]; then + return 0 +else + return 1 +fi diff --git a/samples/net/lwm2m_client/overlay-dtls.conf b/samples/net/lwm2m_client/overlay-dtls.conf index d9cf838ddc5..930230d8ba4 100644 --- a/samples/net/lwm2m_client/overlay-dtls.conf +++ b/samples/net/lwm2m_client/overlay-dtls.conf @@ -1,9 +1,12 @@ +# Enable DTLS with Connection Identifier CONFIG_LWM2M_DTLS_SUPPORT=y +CONFIG_LWM2M_DTLS_CID=y CONFIG_LWM2M_PEER_PORT=5684 # Select Zephyr mbedtls CONFIG_MBEDTLS=y CONFIG_MBEDTLS_TLS_VERSION_1_2=y +CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID=y # Special MbedTLS changes CONFIG_MBEDTLS_ENABLE_HEAP=y diff --git a/samples/net/lwm2m_client/overlay-ot.conf b/samples/net/lwm2m_client/overlay-ot.conf index 38960970f58..0e73d874597 100644 --- a/samples/net/lwm2m_client/overlay-ot.conf +++ b/samples/net/lwm2m_client/overlay-ot.conf @@ -1,7 +1,7 @@ # Main CONFIG_MAIN_STACK_SIZE=2048 -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y # Disable TCP and IPv4 (TCP disabled to avoid heavy traffic) CONFIG_NET_TCP=n diff --git a/samples/net/lwm2m_client/sample.yaml b/samples/net/lwm2m_client/sample.yaml index 8faf0e613e5..9c0cada2c1f 100644 --- a/samples/net/lwm2m_client/sample.yaml +++ b/samples/net/lwm2m_client/sample.yaml @@ -10,6 +10,7 @@ tests: - frdm_k64f - pinnacle_100_dvk - mg100 + - native_sim integration_platforms: - qemu_x86 tags: @@ -18,7 +19,9 @@ tests: sample.net.lwm2m_client.all_objects: harness: net depends_on: netif - platform_allow: qemu_x86 + platform_allow: + - qemu_x86 + - native_sim integration_platforms: - qemu_x86 tags: @@ -43,6 +46,7 @@ tests: - frdm_k64f - pinnacle_100_dvk - mg100 + - native_sim integration_platforms: - qemu_x86 tags: @@ -63,7 +67,9 @@ tests: harness: net depends_on: netif extra_args: OVERLAY_CONFIG=overlay-queue.conf - platform_allow: qemu_x86 + platform_allow: + - qemu_x86 + - native_sim integration_platforms: - qemu_x86 tags: diff --git a/samples/net/lwm2m_client/src/temperature.c b/samples/net/lwm2m_client/src/temperature.c index 8d2c0efefb1..6d251fafbdb 100644 --- a/samples/net/lwm2m_client/src/temperature.c +++ b/samples/net/lwm2m_client/src/temperature.c @@ -14,7 +14,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #include #include #include -#include +#include #include static struct k_work_delayable temp_work; diff --git a/samples/net/mdns_responder/CMakeLists.txt b/samples/net/mdns_responder/CMakeLists.txt index 21efc955050..5c4e88178a9 100644 --- a/samples/net/mdns_responder/CMakeLists.txt +++ b/samples/net/mdns_responder/CMakeLists.txt @@ -4,7 +4,8 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(mdns_responder) -FILE(GLOB app_sources src/*.c) -target_sources(app PRIVATE ${app_sources}) +target_sources(app PRIVATE src/main.c) +target_sources(app PRIVATE src/service.c) +target_sources_ifdef(CONFIG_NET_VLAN app PRIVATE src/vlan.c) include(${ZEPHYR_BASE}/samples/net/common/common.cmake) diff --git a/samples/net/mdns_responder/Kconfig b/samples/net/mdns_responder/Kconfig new file mode 100644 index 00000000000..53cc3d2153d --- /dev/null +++ b/samples/net/mdns_responder/Kconfig @@ -0,0 +1,56 @@ +# Private config options for mDNS responder sample app + +# Copyright (c) 2023 NordicNordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +mainmenu "Networking mDNS responder sample application" + +config NET_SAMPLE_IFACE2_MY_IPV6_ADDR + string "My IPv6 address for second interface" + help + The value depends on your network setup. + +config NET_SAMPLE_IFACE2_MY_IPV4_ADDR + string "My IPv4 address for second interface" + help + The value depends on your network setup. + +config NET_SAMPLE_IFACE2_MY_IPV4_NETMASK + string "My IPv4 netmask for second interface" + help + The value depends on your network setup. + +config NET_SAMPLE_IFACE2_VLAN_TAG + int "VLAN tag for second interface" + default 100 + range 0 4094 + depends on NET_VLAN + help + Set VLAN (virtual LAN) tag (id) that is used in the sample + application. + +config NET_SAMPLE_IFACE3_MY_IPV6_ADDR + string "My IPv6 address for third interface" + help + The value depends on your network setup. + +config NET_SAMPLE_IFACE3_MY_IPV4_ADDR + string "My IPv4 address for third interface" + help + The value depends on your network setup. + +config NET_SAMPLE_IFACE3_MY_IPV4_NETMASK + string "My IPv4 netmask for third interface" + help + The value depends on your network setup. + +config NET_SAMPLE_IFACE3_VLAN_TAG + int "VLAN tag for third interface" + default 200 + range 0 4094 + depends on NET_VLAN + help + Set VLAN (virtual LAN) tag (id) that is used in the sample + application. + +source "Kconfig.zephyr" diff --git a/samples/net/mdns_responder/README.rst b/samples/net/mdns_responder/README.rst index 8b9d93299a4..015f6c8b444 100644 --- a/samples/net/mdns_responder/README.rst +++ b/samples/net/mdns_responder/README.rst @@ -1,7 +1,8 @@ -.. _mdns-responder-sample: +.. zephyr:code-sample:: mdns-responder + :name: mDNS responder + :relevant-api: net_core dns_sd bsd_sockets -mDNS Responder Application -########################## + Listen and respond to mDNS queries. Overview ******** diff --git a/samples/net/mdns_responder/overlay-e1000.conf b/samples/net/mdns_responder/overlay-e1000.conf new file mode 100644 index 00000000000..d2880bd3587 --- /dev/null +++ b/samples/net/mdns_responder/overlay-e1000.conf @@ -0,0 +1,6 @@ +CONFIG_NET_L2_ETHERNET=y +CONFIG_NET_QEMU_ETHERNET=y + +CONFIG_PCIE=y + +#CONFIG_ETHERNET_LOG_LEVEL_DBG=y diff --git a/samples/net/mdns_responder/overlay-vlan.conf b/samples/net/mdns_responder/overlay-vlan.conf new file mode 100644 index 00000000000..5dfe0f9b8f7 --- /dev/null +++ b/samples/net/mdns_responder/overlay-vlan.conf @@ -0,0 +1,34 @@ +CONFIG_NET_VLAN=y + +# We have one non-vlan interface and two VLAN interfaces +CONFIG_NET_VLAN_COUNT=3 + +# There will be three network interfaces. + +# First ethernet interface will use these settings +CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1" +CONFIG_NET_CONFIG_PEER_IPV6_ADDR="2001:db8::2" +CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1" +CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2" + +# Second ethernet interface will have these settings +CONFIG_NET_SAMPLE_IFACE2_MY_IPV6_ADDR="2001:db8:100::1" +# TEST-NET-2 from RFC 5737 +CONFIG_NET_SAMPLE_IFACE2_MY_IPV4_ADDR="198.51.100.1" +CONFIG_NET_SAMPLE_IFACE2_MY_IPV4_NETMASK="255.255.255.0" +# VLAN tag for the second interface +CONFIG_NET_SAMPLE_IFACE2_VLAN_TAG=100 + +# Settings for the third network interface +CONFIG_NET_SAMPLE_IFACE3_MY_IPV6_ADDR="2001:db8:200::1" +# TEST-NET-3 from RFC 5737 +CONFIG_NET_SAMPLE_IFACE3_MY_IPV4_ADDR="203.0.113.1" +CONFIG_NET_SAMPLE_IFACE3_MY_IPV4_NETMASK="255.255.255.0" +# VLAN tag for the second interface +CONFIG_NET_SAMPLE_IFACE3_VLAN_TAG=200 + +# Each interface needs at least 2 context. So if we have three +# interfaces we need minimum 6 context but allocate more so that +# we do not run out of them. +CONFIG_NET_MAX_CONTEXTS=10 +CONFIG_NET_MAX_CONN=10 diff --git a/samples/net/mdns_responder/src/main.c b/samples/net/mdns_responder/src/main.c index 6a4ec48a4ab..112f9e93931 100644 --- a/samples/net/mdns_responder/src/main.c +++ b/samples/net/mdns_responder/src/main.c @@ -14,6 +14,15 @@ LOG_MODULE_REGISTER(net_mdns_responder_sample, LOG_LEVEL_DBG); extern void service(void); +#if defined(CONFIG_NET_VLAN) +int init_vlan(void); +#else +static inline int init_vlan(void) +{ + return 0; +} +#endif /* CONFIG_NET_VLAN */ + /* * Note that mDNS support requires no application interaction with zephyr, * beyond optional runtime hostname configuration calls and setting @@ -26,6 +35,7 @@ extern void service(void); int main(void) { LOG_INF("Waiting mDNS queries..."); + init_vlan(); service(); return 0; } diff --git a/samples/net/mdns_responder/src/vlan.c b/samples/net/mdns_responder/src/vlan.c new file mode 100644 index 00000000000..534662c3c64 --- /dev/null +++ b/samples/net/mdns_responder/src/vlan.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2018 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_mdns_responder_sample, LOG_LEVEL_DBG); + +#include + +#include + +/* User data for the interface callback */ +struct ud { + struct net_if *first; + struct net_if *second; + struct net_if *third; +}; + +static void iface_cb(struct net_if *iface, void *user_data_param) +{ + struct ud *user_data = user_data_param; + + if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) { + return; + } + + if (!user_data->first) { + user_data->first = iface; + return; + } + + if (!user_data->second) { + user_data->second = iface; + return; + } + + if (!user_data->third) { + user_data->third = iface; + return; + } +} + +static int setup_iface(struct net_if *iface, const char *ipv6_addr, + const char *ipv4_addr, const char *netmask, + uint16_t vlan_tag) +{ + struct net_if_addr *ifaddr; + struct in_addr addr4; + struct in6_addr addr6; + int ret; + + ret = net_eth_vlan_enable(iface, vlan_tag); + if (ret < 0) { + LOG_ERR("Cannot enable VLAN for tag %d (%d)", vlan_tag, ret); + } + + if (IS_ENABLED(CONFIG_NET_IPV6)) { + if (net_addr_pton(AF_INET6, ipv6_addr, &addr6)) { + LOG_ERR("Invalid address: %s", ipv6_addr); + return -EINVAL; + } + + ifaddr = net_if_ipv6_addr_add(iface, &addr6, + NET_ADDR_MANUAL, 0); + if (!ifaddr) { + LOG_ERR("Cannot add %s to interface %p", + ipv6_addr, iface); + return -EINVAL; + } + } + + if (IS_ENABLED(CONFIG_NET_IPV4)) { + if (net_addr_pton(AF_INET, ipv4_addr, &addr4)) { + LOG_ERR("Invalid address: %s", ipv4_addr); + return -EINVAL; + } + + ifaddr = net_if_ipv4_addr_add(iface, &addr4, + NET_ADDR_MANUAL, 0); + if (!ifaddr) { + LOG_ERR("Cannot add %s to interface %p", + ipv4_addr, iface); + return -EINVAL; + } + + if (netmask && netmask[0]) { + if (net_addr_pton(AF_INET, netmask, &addr4)) { + LOG_ERR("Invalid netmask: %s", ipv4_addr); + return -EINVAL; + } + + net_if_ipv4_set_netmask(iface, &addr4); + } + } + + LOG_DBG("Interface %p VLAN tag %d setup done.", iface, vlan_tag); + + return 0; +} + +int init_vlan(void) +{ + struct ud user_data; + int ret; + + memset(&user_data, 0, sizeof(user_data)); + + net_if_foreach(iface_cb, &user_data); + + /* This sample has two VLANs. For the second one we need to manually + * create IP address for this test. But first the VLAN needs to be + * added to the interface so that IPv6 DAD can work properly. + */ + ret = setup_iface(user_data.second, + CONFIG_NET_SAMPLE_IFACE2_MY_IPV6_ADDR, + CONFIG_NET_SAMPLE_IFACE2_MY_IPV4_ADDR, + CONFIG_NET_SAMPLE_IFACE2_MY_IPV4_NETMASK, + CONFIG_NET_SAMPLE_IFACE2_VLAN_TAG); + if (ret < 0) { + return ret; + } + + ret = setup_iface(user_data.third, + CONFIG_NET_SAMPLE_IFACE3_MY_IPV6_ADDR, + CONFIG_NET_SAMPLE_IFACE3_MY_IPV4_ADDR, + CONFIG_NET_SAMPLE_IFACE3_MY_IPV4_NETMASK, + CONFIG_NET_SAMPLE_IFACE3_VLAN_TAG); + if (ret < 0) { + return ret; + } + + return 0; +} diff --git a/samples/net/mqtt_publisher/README.rst b/samples/net/mqtt_publisher/README.rst index 04ff4c47bfd..2c22394036b 100644 --- a/samples/net/mqtt_publisher/README.rst +++ b/samples/net/mqtt_publisher/README.rst @@ -1,7 +1,8 @@ -.. _mqtt-publisher-sample: +.. zephyr:code-sample:: mqtt-publisher + :name: MQTT publisher + :relevant-api: mqtt_socket -MQTT Publisher -############## + Send MQTT PUBLISH messages to an MQTT server. Overview ******** diff --git a/samples/net/mqtt_publisher/src/main.c b/samples/net/mqtt_publisher/src/main.c index a4b391d9148..8ff34f271c2 100644 --- a/samples/net/mqtt_publisher/src/main.c +++ b/samples/net/mqtt_publisher/src/main.c @@ -10,7 +10,7 @@ LOG_MODULE_REGISTER(net_mqtt_publisher_sample, LOG_LEVEL_DBG); #include #include #include -#include +#include #include #include diff --git a/samples/net/mqtt_sn_publisher/README.rst b/samples/net/mqtt_sn_publisher/README.rst index 57e82f30594..48b8dab5dec 100644 --- a/samples/net/mqtt_sn_publisher/README.rst +++ b/samples/net/mqtt_sn_publisher/README.rst @@ -1,7 +1,8 @@ -.. _mqtt-sn-publisher-sample: +.. zephyr:code-sample:: mqtt-sn-publisher + :name: MQTT-SN publisher + :relevant-api: mqtt_sn_socket -MQTT-SN Publisher -################# + Send MQTT-SN PUBLISH messages to an MQTT-SN gateway. Overview ******** @@ -16,8 +17,8 @@ requires a reliable TCP/IP transport, MQTT-SN is designed to be usable on any datagram-based transport like UDP, ZigBee or even a plain UART (with an additional framing protocol). -The Zephyr MQTT-SN Publisher sample application is a MQTT-SN v1.2 -client that sends MQTT-SN PUBLISH messages to a MQTT-SN gateway. +The Zephyr MQTT-SN Publisher sample application is an MQTT-SN v1.2 +client that sends MQTT-SN PUBLISH messages to an MQTT-SN gateway. It also SUBSCRIBEs to a topic. See the `MQTT-SN v1.2 spec`_ for more information. @@ -43,7 +44,7 @@ Currently, this sample application only supports static IP addresses. Open the :file:`prj.conf` file and set the IP addresses according to the LAN environment. -You will also need to start a MQTT-SN gateway. With paho, you can either +You will also need to start an MQTT-SN gateway. With Paho, you can either build it from source - see `PAHO MQTT-SN Gateway`_ - or run an unofficial docker image, like `kyberpunk/paho`_. @@ -66,8 +67,8 @@ Then, locate your zephyr directory and type: .. zephyr-app-commands:: :zephyr-app: samples/net/mqtt_sn_publisher - :board: native_posix_64 - :goals: build -t run + :board: native_sim_64 + :goals: run :compact: Optionally, use any MQTT explorer to connect to your broker. diff --git a/samples/net/mqtt_sn_publisher/boards/native_sim.conf b/samples/net/mqtt_sn_publisher/boards/native_sim.conf new file mode 100644 index 00000000000..0843e94acbd --- /dev/null +++ b/samples/net/mqtt_sn_publisher/boards/native_sim.conf @@ -0,0 +1 @@ +CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME=y diff --git a/samples/net/mqtt_sn_publisher/boards/native_sim_64.conf b/samples/net/mqtt_sn_publisher/boards/native_sim_64.conf new file mode 100644 index 00000000000..0843e94acbd --- /dev/null +++ b/samples/net/mqtt_sn_publisher/boards/native_sim_64.conf @@ -0,0 +1 @@ +CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME=y diff --git a/samples/net/mqtt_sn_publisher/sample.yaml b/samples/net/mqtt_sn_publisher/sample.yaml index 5d37a430ba1..ca11e3e96f3 100644 --- a/samples/net/mqtt_sn_publisher/sample.yaml +++ b/samples/net/mqtt_sn_publisher/sample.yaml @@ -13,5 +13,6 @@ tests: - qemu_x86 - pinnacle_100_dvk - mg100 + - native_sim_64 integration_platforms: - qemu_x86 diff --git a/samples/net/mqtt_sn_publisher/src/common.h b/samples/net/mqtt_sn_publisher/src/common.h index 4b0fef32698..1cfbbc10450 100644 --- a/samples/net/mqtt_sn_publisher/src/common.h +++ b/samples/net/mqtt_sn_publisher/src/common.h @@ -23,4 +23,4 @@ extern struct k_mem_domain app_domain; #define THREAD_PRIORITY K_PRIO_PREEMPT(8) #endif -int start_thread(void); +void start_thread(void); diff --git a/samples/net/mqtt_sn_publisher/src/main.c b/samples/net/mqtt_sn_publisher/src/main.c index 665919ef50a..65436daea4d 100644 --- a/samples/net/mqtt_sn_publisher/src/main.c +++ b/samples/net/mqtt_sn_publisher/src/main.c @@ -83,12 +83,16 @@ static void init_app(void) } } -static int start_client(void) +static void start_client(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + /* Wait for connection */ k_sem_take(&run_app, K_FOREVER); - return start_thread(); + start_thread(); } int main(void) @@ -107,9 +111,9 @@ int main(void) k_thread_access_grant(k_current_get(), &run_app); k_mem_domain_add_thread(&app_domain, k_current_get()); - k_thread_user_mode_enter((k_thread_entry_t)start_client, NULL, NULL, NULL); + k_thread_user_mode_enter(start_client, NULL, NULL, NULL); #else - exit(start_client()); + start_client(NULL, NULL, NULL); #endif return 0; } diff --git a/samples/net/mqtt_sn_publisher/src/udp.c b/samples/net/mqtt_sn_publisher/src/udp.c index 32a64fbccbd..70a09bdb89d 100644 --- a/samples/net/mqtt_sn_publisher/src/udp.c +++ b/samples/net/mqtt_sn_publisher/src/udp.c @@ -141,23 +141,28 @@ static void process_thread(void) LOG_ERR("Exiting thread: %d", err); } -int start_thread(void) +void start_thread(void) { int rc; #if defined(CONFIG_USERSPACE) rc = k_mem_domain_add_thread(&app_domain, udp_thread_id); if (rc < 0) { - return rc; + LOG_ERR("Failed: k_mem_domain_add_thread() %d", rc); + return; } #endif rc = k_thread_name_set(udp_thread_id, "udp"); if (rc < 0 && rc != -ENOSYS) { LOG_ERR("Failed: k_thread_name_set() %d", rc); - return rc; + return; } k_thread_start(udp_thread_id); - return k_thread_join(udp_thread_id, K_FOREVER); + rc = k_thread_join(udp_thread_id, K_FOREVER); + + if (rc != 0) { + LOG_ERR("Failed: k_thread_join() %d", rc); + } } diff --git a/samples/net/openthread/coprocessor/README.rst b/samples/net/openthread/coprocessor/README.rst index ee76942c3fc..9ba9fc62f0d 100644 --- a/samples/net/openthread/coprocessor/README.rst +++ b/samples/net/openthread/coprocessor/README.rst @@ -1,7 +1,8 @@ -.. _coprocessor-sample: +.. zephyr:code-sample:: coprocessor + :name: OpenThread co-processor + :relevant-api: openthread -OpenThread Co-Processor -####################### + Build a Thread border-router using OpenThread's co-processor designs. Overview ******** diff --git a/samples/net/promiscuous_mode/README.rst b/samples/net/promiscuous_mode/README.rst index 44e5bdd27c0..3587deb8d9c 100644 --- a/samples/net/promiscuous_mode/README.rst +++ b/samples/net/promiscuous_mode/README.rst @@ -1,7 +1,8 @@ -.. _net-promiscuous-mode-sample: +.. zephyr:code-sample:: net-promiscuous-mode + :name: Promiscuous mode + :relevant-api: promiscuous -Promiscuous Mode Sample Application -################################### + Enable promiscuous mode on all interfaces and print information about incoming packets. Overview ******** diff --git a/samples/net/sockets/big_http_download/Makefile.posix b/samples/net/sockets/big_http_download/Makefile.host similarity index 100% rename from samples/net/sockets/big_http_download/Makefile.posix rename to samples/net/sockets/big_http_download/Makefile.host diff --git a/samples/net/sockets/big_http_download/README.rst b/samples/net/sockets/big_http_download/README.rst index 0cefa732063..b3bf8e7f2e3 100644 --- a/samples/net/sockets/big_http_download/README.rst +++ b/samples/net/sockets/big_http_download/README.rst @@ -1,14 +1,15 @@ -.. _sockets-big-http-download: +.. zephyr:code-sample:: sockets-big-http-download + :name: Large HTTP download + :relevant-api: bsd_sockets tls_credentials -Socket Big HTTP Download Example -################################ + Download a large file from a web server using BSD sockets. Overview ******** The sockets/big_http_download sample application for Zephyr implements a simple HTTP GET client using a BSD Sockets compatible API. Unlike -the :ref:`sockets-http-get` sample application, it downloads a file of +the :zephyr:code-sample:`sockets-http-get` sample application, it downloads a file of several megabytes in size, and verifies its integrity using hashing. It also performs download repeatedly, tracking the total number of bytes transferred. Thus, it can serve as a "load testing" application for @@ -78,11 +79,11 @@ An alternative way is to specify ``-DEXTRA_CONF_FILE=overlay-tls.conf`` when running ``west build`` or ``cmake``. The TLS version of this sample downloads a file from -https://www.7-zip.org/a/7z1805.exe (1.1MB). The certificate -used by the sample is in the sample's ``src`` directory and is configured -to access the default website configured in the sample for TLS -communication (https://www.7-zip.org). To access a different -web page over TLS, you'll need to provide a different certificate +https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/git/1:2.34.1-1ubuntu1/git_2.34.1.orig.tar.xz +(6.6MB). The certificates used by the sample are in the sample's ``src`` +directory and are used to access the default website configured in the sample +for TLS communication (https://launchpad.net) and possible redirects. To access +a different web page over TLS, you'll need to provide a different certificate to authenticate to that server. Note, that TLS support in the sample depends on non-posix, TLS socket @@ -95,11 +96,11 @@ Running application on POSIX Host The same application source code can be built for a POSIX system, e.g. Linux. -To build for a host POSIX OS: +To build: .. code-block:: console - $ make -f Makefile.posix + $ make -f Makefile.host To run: diff --git a/samples/net/sockets/big_http_download/overlay-tls.conf b/samples/net/sockets/big_http_download/overlay-tls.conf index 28ac8d4bc7d..78d1a7cef13 100644 --- a/samples/net/sockets/big_http_download/overlay-tls.conf +++ b/samples/net/sockets/big_http_download/overlay-tls.conf @@ -5,7 +5,7 @@ CONFIG_NET_PKT_TX_COUNT=10 CONFIG_MBEDTLS=y CONFIG_MBEDTLS_BUILTIN=y CONFIG_MBEDTLS_ENABLE_HEAP=y -CONFIG_MBEDTLS_HEAP_SIZE=60000 +CONFIG_MBEDTLS_HEAP_SIZE=65000 CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 CONFIG_MBEDTLS_PEM_CERTIFICATE_FORMAT=y diff --git a/samples/net/sockets/big_http_download/prj.conf b/samples/net/sockets/big_http_download/prj.conf index 02b7e11d39e..324eb765af2 100644 --- a/samples/net/sockets/big_http_download/prj.conf +++ b/samples/net/sockets/big_http_download/prj.conf @@ -1,5 +1,5 @@ # General config -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_MBEDTLS=y CONFIG_MBEDTLS_ENABLE_HEAP=y CONFIG_MAIN_STACK_SIZE=2536 diff --git a/samples/net/sockets/big_http_download/sample.yaml b/samples/net/sockets/big_http_download/sample.yaml index 019f390d298..313d0a135c7 100644 --- a/samples/net/sockets/big_http_download/sample.yaml +++ b/samples/net/sockets/big_http_download/sample.yaml @@ -2,7 +2,7 @@ sample: description: BSD Sockets big HTTP download example name: big_http_download common: - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED and not CONFIG_NATIVE_LIBC harness: net min_ram: 32 min_flash: 128 diff --git a/samples/net/sockets/big_http_download/src/DigiCertGlobalRootG2.crt.pem b/samples/net/sockets/big_http_download/src/DigiCertGlobalRootG2.crt.pem new file mode 100644 index 00000000000..51a0085fa1a --- /dev/null +++ b/samples/net/sockets/big_http_download/src/DigiCertGlobalRootG2.crt.pem @@ -0,0 +1,22 @@ +"-----BEGIN CERTIFICATE-----\n" +"MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh\n" +"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" +"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH\n" +"MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT\n" +"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n" +"b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG\n" +"9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI\n" +"2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx\n" +"1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ\n" +"q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz\n" +"tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ\n" +"vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP\n" +"BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV\n" +"5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY\n" +"1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4\n" +"NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG\n" +"Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91\n" +"8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe\n" +"pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl\n" +"MrY=\n" +"-----END CERTIFICATE-----\n" diff --git a/samples/net/sockets/big_http_download/src/big_http_download.c b/samples/net/sockets/big_http_download/src/big_http_download.c index c28c22b3159..b4e9ccffeda 100644 --- a/samples/net/sockets/big_http_download/src/big_http_download.c +++ b/samples/net/sockets/big_http_download/src/big_http_download.c @@ -274,9 +274,12 @@ bool download(struct addrinfo *ai, bool is_tls, bool *redirect) #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) if (is_tls) { - sec_tag_t sec_tag_opt[] = { - CA_CERTIFICATE_TAG, + sec_tag_t sec_tag_opt[ARRAY_SIZE(ca_certificates)]; + + for (int i = 0; i < ARRAY_SIZE(ca_certificates); i++) { + sec_tag_opt[i] = CA_CERTIFICATE_TAG + i; }; + CHECK(setsockopt(sock, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_opt, sizeof(sec_tag_opt))); @@ -369,8 +372,12 @@ int main(void) bool redirect = false; #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) - tls_credential_add(CA_CERTIFICATE_TAG, TLS_CREDENTIAL_CA_CERTIFICATE, - ca_certificate, sizeof(ca_certificate)); + for (int i = 0; i < ARRAY_SIZE(ca_certificates); i++) { + tls_credential_add(CA_CERTIFICATE_TAG + i, + TLS_CREDENTIAL_CA_CERTIFICATE, + ca_certificates[i], + strlen(ca_certificates[i]) + 1); + } #endif setbuf(stdout, NULL); diff --git a/samples/net/sockets/big_http_download/src/ca_certificate.h b/samples/net/sockets/big_http_download/src/ca_certificate.h index 4f3e2e266b5..462f8f0052b 100644 --- a/samples/net/sockets/big_http_download/src/ca_certificate.h +++ b/samples/net/sockets/big_http_download/src/ca_certificate.h @@ -13,10 +13,14 @@ * certificate in PEM format, you can enable support for it in Kconfig. */ -/* ISRG Root X1 for https://launchpad.net/ubuntu */ -static const unsigned char ca_certificate[] = +/* ISRG Root X1 for https://launchpad.net/ubuntu + * DigiCert Global Root G2 for possible redirects + */ +static const unsigned char *ca_certificates[] = { #include "isrgrootx1.pem" -; +, +#include "DigiCertGlobalRootG2.crt.pem" +}; #endif /* __CA_CERTIFICATE_H__ */ diff --git a/samples/net/sockets/can/README.rst b/samples/net/sockets/can/README.rst index 5239985c260..800665a8523 100644 --- a/samples/net/sockets/can/README.rst +++ b/samples/net/sockets/can/README.rst @@ -1,7 +1,8 @@ -.. _socket-can-sample: +.. zephyr:code-sample:: socket-can + :name: SocketCAN + :relevant-api: bsd_sockets socket_can -Socket CAN -########## + Send and receive raw CAN frames using BSD sockets API. Overview ******** diff --git a/samples/net/sockets/can/src/main.c b/samples/net/sockets/can/src/main.c index 2f86b63eaf1..506157c6afe 100644 --- a/samples/net/sockets/can/src/main.c +++ b/samples/net/sockets/can/src/main.c @@ -39,8 +39,12 @@ static const struct can_filter zfilter = { static struct socketcan_filter sock_filter; -static void tx(int *can_fd) +static void tx(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + int *can_fd = p1; int fd = POINTER_TO_INT(can_fd); struct can_frame zframe = {0}; struct socketcan_frame sframe = {0}; @@ -95,9 +99,11 @@ static int create_socket(const struct socketcan_filter *sfilter) return fd; } -static void rx(int *can_fd, int *do_close_period, - const struct socketcan_filter *sfilter) +static void rx(void *p1, void *p2, void *p3) { + int *can_fd = p1; + int *do_close_period = p2; + const struct socketcan_filter *sfilter = p3; int close_period = POINTER_TO_INT(do_close_period); int fd = POINTER_TO_INT(can_fd); struct sockaddr_can can_addr; @@ -205,7 +211,7 @@ static int setup_socket(void) /* Delay TX startup so that RX is ready to receive */ tx_tid = k_thread_create(&tx_data, tx_stack, K_THREAD_STACK_SIZEOF(tx_stack), - (k_thread_entry_t)tx, INT_TO_POINTER(fd), + tx, INT_TO_POINTER(fd), NULL, NULL, PRIORITY, 0, K_SECONDS(1)); if (!tx_tid) { ret = -ENOENT; @@ -225,7 +231,7 @@ static int setup_socket(void) if (fd >= 0) { rx_tid = k_thread_create(&rx_data, rx_stack, K_THREAD_STACK_SIZEOF(rx_stack), - (k_thread_entry_t)rx, + rx, INT_TO_POINTER(fd), INT_TO_POINTER(CLOSE_PERIOD), &sock_filter, PRIORITY, 0, K_NO_WAIT); diff --git a/samples/net/sockets/coap_client/README.rst b/samples/net/sockets/coap_client/README.rst index fedea647b3c..ffcd81978cc 100644 --- a/samples/net/sockets/coap_client/README.rst +++ b/samples/net/sockets/coap_client/README.rst @@ -1,7 +1,8 @@ -.. _coap-client-sample: +.. zephyr:code-sample:: coap-client + :name: CoAP client + :relevant-api: coap udp -CoAP client -########### + Use the CoAP library to implement a client that fetches a resource. Overview ******** @@ -28,7 +29,7 @@ be obtained by using a tool such as tcpdump or wireshark. See the `net-tools`_ project for more details. -This sample can be built and executed on QEMU or native_posix board as described +This sample can be built and executed on QEMU or native_sim board as described in :ref:`networking_with_host`. Sample output diff --git a/samples/net/sockets/coap_client/prj.conf b/samples/net/sockets/coap_client/prj.conf index 8a513d82a45..b0df3759b22 100644 --- a/samples/net/sockets/coap_client/prj.conf +++ b/samples/net/sockets/coap_client/prj.conf @@ -1,6 +1,6 @@ # Generic networking options CONFIG_NETWORKING=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_NET_IPV6=y CONFIG_NET_UDP=y diff --git a/samples/net/sockets/coap_client/sample.yaml b/samples/net/sockets/coap_client/sample.yaml index a1fc20ff391..8c822c7604e 100644 --- a/samples/net/sockets/coap_client/sample.yaml +++ b/samples/net/sockets/coap_client/sample.yaml @@ -1,5 +1,5 @@ common: - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED and not CONFIG_NATIVE_LIBC sample: description: TBD name: TBD diff --git a/samples/net/sockets/coap_server/CMakeLists.txt b/samples/net/sockets/coap_server/CMakeLists.txt index 97f67d0a358..17d20709825 100644 --- a/samples/net/sockets/coap_server/CMakeLists.txt +++ b/samples/net/sockets/coap_server/CMakeLists.txt @@ -7,3 +7,5 @@ project(coap_server) FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/net/ip) + +zephyr_linker_sources(DATA_SECTIONS sections-ram.ld) diff --git a/samples/net/sockets/coap_server/README.rst b/samples/net/sockets/coap_server/README.rst index 5159c66b989..a2962b941be 100644 --- a/samples/net/sockets/coap_server/README.rst +++ b/samples/net/sockets/coap_server/README.rst @@ -1,12 +1,18 @@ -.. _coap-server-sample: +.. zephyr:code-sample:: coap-server + :name: CoAP service + :relevant-api: coap coap_service udp -CoAP Server -########### + Use the CoAP server subsystem to register CoAP resources. Overview ******** -This sample is a simple CoAP server showing how to expose a simple resource. +This sample shows how to register CoAP resources to a main CoAP service. +The CoAP server implementation expects all services and resources to be +available at compile time, as they are put into dedicated sections. + +The resource is placed into the correct linker section based on the owning +service's name. A linker file is required, see ``sections-ram.ld`` for an example. This demo assumes that the platform of choice has networking support, some adjustments to the configuration may be needed. @@ -38,7 +44,7 @@ or wireshark. See the `net-tools`_ project for more details -This sample can be built and executed on QEMU or native_posix board as +This sample can be built and executed on QEMU or native_sim board as described in :ref:`networking_with_host`. Use this command on the host to run the `libcoap`_ implementation of diff --git a/samples/net/sockets/coap_server/boards/native_posix.conf b/samples/net/sockets/coap_server/boards/native_posix.conf new file mode 100644 index 00000000000..b8f2d57be74 --- /dev/null +++ b/samples/net/sockets/coap_server/boards/native_posix.conf @@ -0,0 +1,3 @@ +CONFIG_NET_L2_ETHERNET=y +CONFIG_NATIVE_POSIX_SLOWDOWN_TO_REAL_TIME=y +CONFIG_NATIVE_UART_0_ON_STDINOUT=y diff --git a/samples/net/sockets/coap_server/boards/native_posix_64.conf b/samples/net/sockets/coap_server/boards/native_posix_64.conf new file mode 100644 index 00000000000..b8f2d57be74 --- /dev/null +++ b/samples/net/sockets/coap_server/boards/native_posix_64.conf @@ -0,0 +1,3 @@ +CONFIG_NET_L2_ETHERNET=y +CONFIG_NATIVE_POSIX_SLOWDOWN_TO_REAL_TIME=y +CONFIG_NATIVE_UART_0_ON_STDINOUT=y diff --git a/samples/net/sockets/coap_server/boards/native_sim.conf b/samples/net/sockets/coap_server/boards/native_sim.conf new file mode 100644 index 00000000000..ac091ebe5db --- /dev/null +++ b/samples/net/sockets/coap_server/boards/native_sim.conf @@ -0,0 +1,4 @@ +CONFIG_NET_L2_ETHERNET=y +CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME=y +CONFIG_NATIVE_UART_0_ON_STDINOUT=y +CONFIG_PICOLIBC=y diff --git a/samples/net/sockets/coap_server/boards/native_sim_64.conf b/samples/net/sockets/coap_server/boards/native_sim_64.conf new file mode 100644 index 00000000000..ac091ebe5db --- /dev/null +++ b/samples/net/sockets/coap_server/boards/native_sim_64.conf @@ -0,0 +1,4 @@ +CONFIG_NET_L2_ETHERNET=y +CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME=y +CONFIG_NATIVE_UART_0_ON_STDINOUT=y +CONFIG_PICOLIBC=y diff --git a/samples/net/sockets/coap_server/boards/qemu_cortex_m3.conf b/samples/net/sockets/coap_server/boards/qemu_cortex_m3.conf new file mode 100644 index 00000000000..dc256b47832 --- /dev/null +++ b/samples/net/sockets/coap_server/boards/qemu_cortex_m3.conf @@ -0,0 +1,4 @@ +CONFIG_NET_L2_ETHERNET=y +CONFIG_ETH_DRIVER=y +CONFIG_ETH_STELLARIS=y +CONFIG_NET_QEMU_ETHERNET=y diff --git a/samples/net/sockets/coap_server/prj.conf b/samples/net/sockets/coap_server/prj.conf index cbe61178b2a..1a26e614786 100644 --- a/samples/net/sockets/coap_server/prj.conf +++ b/samples/net/sockets/coap_server/prj.conf @@ -1,6 +1,6 @@ # Generic networking options CONFIG_NETWORKING=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_NET_UDP=y # Socket @@ -10,7 +10,10 @@ CONFIG_NET_SOCKETS_POLL_MAX=4 # CoAP CONFIG_COAP=y +CONFIG_COAP_SERVER=y +CONFIG_COAP_SERVER_WELL_KNOWN_CORE=y CONFIG_COAP_WELL_KNOWN_BLOCK_WISE=n +CONFIG_COAP_OBSERVER_EVENTS=y # Kernel options CONFIG_ENTROPY_GENERATOR=y @@ -22,9 +25,7 @@ CONFIG_NET_LOG=y # Network Shell CONFIG_NET_SHELL=y - -CONFIG_MAIN_STACK_SIZE=2048 -CONFIG_HEAP_MEM_POOL_SIZE=4096 +CONFIG_COAP_SERVER_SHELL=y # Configuration CONFIG_NET_CONFIG_SETTINGS=y diff --git a/samples/net/sockets/coap_server/sample.yaml b/samples/net/sockets/coap_server/sample.yaml index dacc6e02ab0..2fcf9b63287 100644 --- a/samples/net/sockets/coap_server/sample.yaml +++ b/samples/net/sockets/coap_server/sample.yaml @@ -1,12 +1,14 @@ common: - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED and not CONFIG_NATIVE_LIBC sample: - description: TBD - name: TBD + description: BSD Sockets API CoAP server example + name: socket_coap_server tests: sample.net.sockets.coap_server: harness: net tags: - net - socket - platform_allow: qemu_x86 + platform_allow: + - native_sim + - qemu_x86 diff --git a/samples/net/sockets/coap_server/sections-ram.ld b/samples/net/sockets/coap_server/sections-ram.ld new file mode 100644 index 00000000000..04534264195 --- /dev/null +++ b/samples/net/sockets/coap_server/sections-ram.ld @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include + +ITERABLE_SECTION_RAM(coap_resource_coap_server, 4) diff --git a/samples/net/sockets/coap_server/src/coap-server.c b/samples/net/sockets/coap_server/src/coap-server.c deleted file mode 100644 index ce47e31a245..00000000000 --- a/samples/net/sockets/coap_server/src/coap-server.c +++ /dev/null @@ -1,1466 +0,0 @@ -/* - * Copyright (c) 2018 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -LOG_MODULE_REGISTER(net_coap_server_sample, LOG_LEVEL_DBG); - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "net_private.h" -#if defined(CONFIG_NET_IPV6) -#include "ipv6.h" -#endif - -#define MAX_RETRANSMIT_COUNT 2 - -#define MAX_COAP_MSG_LEN 256 - -#define MY_COAP_PORT 5683 - -#define BLOCK_WISE_TRANSFER_SIZE_GET 2048 - -#if defined(CONFIG_NET_IPV6) -#define ALL_NODES_LOCAL_COAP_MCAST \ - { { { 0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfd } } } - -#define MY_IP6ADDR \ - { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1 } } } -#endif - -#define ADDRLEN(sock) \ - (((struct sockaddr *)sock)->sa_family == AF_INET ? \ - sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)) - -#define NUM_OBSERVERS 3 - -#define NUM_PENDINGS 10 - -/* CoAP socket fd */ -static int sock; - -static struct coap_observer observers[NUM_OBSERVERS]; - -static struct coap_pending pendings[NUM_PENDINGS]; - -static struct k_work_delayable observer_work; - -static int obs_counter; - -static struct coap_resource *resource_to_notify; - -static struct k_work_delayable retransmit_work; - -#if defined(CONFIG_NET_IPV6) -static bool join_coap_multicast_group(void) -{ - static struct in6_addr my_addr = MY_IP6ADDR; - static struct sockaddr_in6 mcast_addr = { - .sin6_family = AF_INET6, - .sin6_addr = ALL_NODES_LOCAL_COAP_MCAST, - .sin6_port = htons(MY_COAP_PORT) }; - struct net_if_addr *ifaddr; - struct net_if *iface; - int ret; - - iface = net_if_get_default(); - if (!iface) { - LOG_ERR("Could not get te default interface\n"); - return false; - } - -#if defined(CONFIG_NET_CONFIG_SETTINGS) - if (net_addr_pton(AF_INET6, - CONFIG_NET_CONFIG_MY_IPV6_ADDR, - &my_addr) < 0) { - LOG_ERR("Invalid IPv6 address %s", - CONFIG_NET_CONFIG_MY_IPV6_ADDR); - } -#endif - - ifaddr = net_if_ipv6_addr_add(iface, &my_addr, NET_ADDR_MANUAL, 0); - if (!ifaddr) { - LOG_ERR("Could not add unicast address to interface"); - return false; - } - - ifaddr->addr_state = NET_ADDR_PREFERRED; - - ret = net_ipv6_mld_join(iface, &mcast_addr.sin6_addr); - if (ret < 0) { - LOG_ERR("Cannot join %s IPv6 multicast group (%d)", - net_sprint_ipv6_addr(&mcast_addr.sin6_addr), ret); - return false; - } - - return true; -} -#endif - -#if defined(CONFIG_NET_IPV6) -static int start_coap_server(void) -{ - struct sockaddr_in6 addr6; - int r; - - memset(&addr6, 0, sizeof(addr6)); - addr6.sin6_family = AF_INET6; - addr6.sin6_port = htons(MY_COAP_PORT); - - sock = socket(addr6.sin6_family, SOCK_DGRAM, IPPROTO_UDP); - if (sock < 0) { - LOG_ERR("Failed to create UDP socket %d", errno); - return -errno; - } - - r = bind(sock, (struct sockaddr *)&addr6, sizeof(addr6)); - if (r < 0) { - LOG_ERR("Failed to bind UDP socket %d", errno); - return -errno; - } - - return 0; -} -#endif - -#if defined(CONFIG_NET_IPV4) -static int start_coap_server(void) -{ - struct sockaddr_in addr; - int r; - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(MY_COAP_PORT); - - sock = socket(addr.sin_family, SOCK_DGRAM, IPPROTO_UDP); - if (sock < 0) { - LOG_ERR("Failed to create UDP socket %d", errno); - return -errno; - } - - r = bind(sock, (struct sockaddr *)&addr, sizeof(addr)); - if (r < 0) { - LOG_ERR("Failed to bind UDP socket %d", errno); - return -errno; - } - - return 0; -} -#endif - -static int send_coap_reply(struct coap_packet *cpkt, - const struct sockaddr *addr, - socklen_t addr_len) -{ - int r; - - net_hexdump("Response", cpkt->data, cpkt->offset); - - r = sendto(sock, cpkt->data, cpkt->offset, 0, addr, addr_len); - if (r < 0) { - LOG_ERR("Failed to send %d", errno); - r = -errno; - } - - return r; -} - -static int well_known_core_get(struct coap_resource *resource, - struct coap_packet *request, - struct sockaddr *addr, socklen_t addr_len) -{ - struct coap_packet response; - uint8_t *data; - int r; - - data = (uint8_t *)k_malloc(MAX_COAP_MSG_LEN); - if (!data) { - return -ENOMEM; - } - - r = coap_well_known_core_get(resource, request, &response, - data, MAX_COAP_MSG_LEN); - if (r < 0) { - goto end; - } - - r = send_coap_reply(&response, addr, addr_len); - -end: - k_free(data); - - return r; -} - -static int piggyback_get(struct coap_resource *resource, - struct coap_packet *request, - struct sockaddr *addr, socklen_t addr_len) -{ - struct coap_packet response; - uint8_t payload[40]; - uint8_t token[COAP_TOKEN_MAX_LEN]; - uint8_t *data; - uint16_t id; - uint8_t code; - uint8_t type; - uint8_t tkl; - int r; - - code = coap_header_get_code(request); - type = coap_header_get_type(request); - id = coap_header_get_id(request); - tkl = coap_header_get_token(request, token); - - LOG_INF("*******"); - LOG_INF("type: %u code %u id %u", type, code, id); - LOG_INF("*******"); - - if (type == COAP_TYPE_CON) { - type = COAP_TYPE_ACK; - } else { - type = COAP_TYPE_NON_CON; - } - - data = (uint8_t *)k_malloc(MAX_COAP_MSG_LEN); - if (!data) { - return -ENOMEM; - } - - r = coap_packet_init(&response, data, MAX_COAP_MSG_LEN, - COAP_VERSION_1, type, tkl, token, - COAP_RESPONSE_CODE_CONTENT, id); - if (r < 0) { - goto end; - } - - r = coap_append_option_int(&response, COAP_OPTION_CONTENT_FORMAT, - COAP_CONTENT_FORMAT_TEXT_PLAIN); - if (r < 0) { - goto end; - } - - r = coap_packet_append_payload_marker(&response); - if (r < 0) { - goto end; - } - - /* The response that coap-client expects */ - r = snprintk((char *) payload, sizeof(payload), - "Type: %u\nCode: %u\nMID: %u\n", type, code, id); - if (r < 0) { - goto end; - } - - r = coap_packet_append_payload(&response, (uint8_t *)payload, - strlen(payload)); - if (r < 0) { - goto end; - } - - r = send_coap_reply(&response, addr, addr_len); - -end: - k_free(data); - - return r; -} - -static int test_del(struct coap_resource *resource, - struct coap_packet *request, - struct sockaddr *addr, socklen_t addr_len) -{ - struct coap_packet response; - uint8_t token[COAP_TOKEN_MAX_LEN]; - uint8_t *data; - uint8_t tkl; - uint8_t code; - uint8_t type; - uint16_t id; - int r; - - code = coap_header_get_code(request); - type = coap_header_get_type(request); - id = coap_header_get_id(request); - tkl = coap_header_get_token(request, token); - - LOG_INF("*******"); - LOG_INF("type: %u code %u id %u", type, code, id); - LOG_INF("*******"); - - if (type == COAP_TYPE_CON) { - type = COAP_TYPE_ACK; - } else { - type = COAP_TYPE_NON_CON; - } - - data = (uint8_t *)k_malloc(MAX_COAP_MSG_LEN); - if (!data) { - return -ENOMEM; - } - - r = coap_packet_init(&response, data, MAX_COAP_MSG_LEN, - COAP_VERSION_1, type, tkl, token, - COAP_RESPONSE_CODE_DELETED, id); - if (r < 0) { - goto end; - } - - r = send_coap_reply(&response, addr, addr_len); - -end: - k_free(data); - - return r; -} - -static int test_put(struct coap_resource *resource, - struct coap_packet *request, - struct sockaddr *addr, socklen_t addr_len) -{ - struct coap_packet response; - uint8_t token[COAP_TOKEN_MAX_LEN]; - const uint8_t *payload; - uint8_t *data; - uint16_t payload_len; - uint8_t code; - uint8_t type; - uint8_t tkl; - uint16_t id; - int r; - - code = coap_header_get_code(request); - type = coap_header_get_type(request); - id = coap_header_get_id(request); - tkl = coap_header_get_token(request, token); - - LOG_INF("*******"); - LOG_INF("type: %u code %u id %u", type, code, id); - LOG_INF("*******"); - - payload = coap_packet_get_payload(request, &payload_len); - if (payload) { - net_hexdump("PUT Payload", payload, payload_len); - } - - if (type == COAP_TYPE_CON) { - type = COAP_TYPE_ACK; - } else { - type = COAP_TYPE_NON_CON; - } - - data = (uint8_t *)k_malloc(MAX_COAP_MSG_LEN); - if (!data) { - return -ENOMEM; - } - - r = coap_packet_init(&response, data, MAX_COAP_MSG_LEN, - COAP_VERSION_1, type, tkl, token, - COAP_RESPONSE_CODE_CHANGED, id); - if (r < 0) { - goto end; - } - - r = send_coap_reply(&response, addr, addr_len); - -end: - k_free(data); - - return r; -} - -static int test_post(struct coap_resource *resource, - struct coap_packet *request, - struct sockaddr *addr, socklen_t addr_len) -{ - static const char * const location_path[] = { "location1", - "location2", - "location3", - NULL }; - const char * const *p; - struct coap_packet response; - uint8_t token[COAP_TOKEN_MAX_LEN]; - const uint8_t *payload; - uint8_t *data; - uint16_t payload_len; - uint8_t code; - uint8_t type; - uint8_t tkl; - uint16_t id; - int r; - - code = coap_header_get_code(request); - type = coap_header_get_type(request); - id = coap_header_get_id(request); - tkl = coap_header_get_token(request, token); - - LOG_INF("*******"); - LOG_INF("type: %u code %u id %u", type, code, id); - LOG_INF("*******"); - - payload = coap_packet_get_payload(request, &payload_len); - if (payload) { - net_hexdump("POST Payload", payload, payload_len); - } - - if (type == COAP_TYPE_CON) { - type = COAP_TYPE_ACK; - } else { - type = COAP_TYPE_NON_CON; - } - - data = (uint8_t *)k_malloc(MAX_COAP_MSG_LEN); - if (!data) { - return -ENOMEM; - } - - r = coap_packet_init(&response, data, MAX_COAP_MSG_LEN, - COAP_VERSION_1, type, tkl, token, - COAP_RESPONSE_CODE_CREATED, id); - if (r < 0) { - goto end; - } - - for (p = location_path; *p; p++) { - r = coap_packet_append_option(&response, - COAP_OPTION_LOCATION_PATH, - *p, strlen(*p)); - if (r < 0) { - goto end; - } - } - - r = send_coap_reply(&response, addr, addr_len); - -end: - k_free(data); - - return r; -} - -static int query_get(struct coap_resource *resource, - struct coap_packet *request, - struct sockaddr *addr, socklen_t addr_len) -{ - struct coap_option options[4]; - struct coap_packet response; - uint8_t payload[40]; - uint8_t token[COAP_TOKEN_MAX_LEN]; - uint8_t *data; - uint16_t id; - uint8_t code; - uint8_t type; - uint8_t tkl; - int i, r; - - code = coap_header_get_code(request); - type = coap_header_get_type(request); - id = coap_header_get_id(request); - tkl = coap_header_get_token(request, token); - - r = coap_find_options(request, COAP_OPTION_URI_QUERY, options, 4); - if (r < 0) { - return -EINVAL; - } - - LOG_INF("*******"); - LOG_INF("type: %u code %u id %u", type, code, id); - LOG_INF("num queries: %d", r); - - for (i = 0; i < r; i++) { - char str[16]; - - if (options[i].len + 1 > sizeof(str)) { - LOG_INF("Unexpected length of query: " - "%d (expected %zu)", - options[i].len, sizeof(str)); - break; - } - - memcpy(str, options[i].value, options[i].len); - str[options[i].len] = '\0'; - - LOG_INF("query[%d]: %s", i + 1, str); - } - - LOG_INF("*******"); - - data = (uint8_t *)k_malloc(MAX_COAP_MSG_LEN); - if (!data) { - return -ENOMEM; - } - - r = coap_packet_init(&response, data, MAX_COAP_MSG_LEN, - COAP_VERSION_1, COAP_TYPE_ACK, tkl, token, - COAP_RESPONSE_CODE_CONTENT, id); - if (r < 0) { - goto end; - } - - r = coap_append_option_int(&response, COAP_OPTION_CONTENT_FORMAT, - COAP_CONTENT_FORMAT_TEXT_PLAIN); - if (r < 0) { - goto end; - } - - r = coap_packet_append_payload_marker(&response); - if (r < 0) { - goto end; - } - - /* The response that coap-client expects */ - r = snprintk((char *) payload, sizeof(payload), - "Type: %u\nCode: %u\nMID: %u\n", type, code, id); - if (r < 0) { - goto end; - } - - r = coap_packet_append_payload(&response, (uint8_t *)payload, - strlen(payload)); - if (r < 0) { - goto end; - } - - r = send_coap_reply(&response, addr, addr_len); - -end: - k_free(data); - - return r; -} - -static int location_query_post(struct coap_resource *resource, - struct coap_packet *request, - struct sockaddr *addr, socklen_t addr_len) -{ - static const char *const location_query[] = { "first=1", - "second=2", - NULL }; - const char * const *p; - struct coap_packet response; - uint8_t *data; - uint8_t token[COAP_TOKEN_MAX_LEN]; - uint16_t id; - uint8_t code; - uint8_t type; - uint8_t tkl; - int r; - - code = coap_header_get_code(request); - type = coap_header_get_type(request); - id = coap_header_get_id(request); - tkl = coap_header_get_token(request, token); - - LOG_INF("*******"); - LOG_INF("type: %u code %u id %u", type, code, id); - LOG_INF("*******"); - - if (type == COAP_TYPE_CON) { - type = COAP_TYPE_ACK; - } else { - type = COAP_TYPE_NON_CON; - } - - data = (uint8_t *)k_malloc(MAX_COAP_MSG_LEN); - if (!data) { - return -ENOMEM; - } - - r = coap_packet_init(&response, data, MAX_COAP_MSG_LEN, - COAP_VERSION_1, type, tkl, token, - COAP_RESPONSE_CODE_CREATED, id); - if (r < 0) { - goto end; - } - - for (p = location_query; *p; p++) { - r = coap_packet_append_option(&response, - COAP_OPTION_LOCATION_QUERY, - *p, strlen(*p)); - if (r < 0) { - goto end; - } - } - - r = send_coap_reply(&response, addr, addr_len); - -end: - k_free(data); - - return r; -} - -static int separate_get(struct coap_resource *resource, - struct coap_packet *request, - struct sockaddr *addr, socklen_t addr_len) -{ - struct coap_packet response; - uint8_t payload[40]; - uint8_t token[COAP_TOKEN_MAX_LEN]; - uint8_t *data; - uint16_t id; - uint8_t code; - uint8_t type; - uint8_t tkl; - int r; - - code = coap_header_get_code(request); - type = coap_header_get_type(request); - id = coap_header_get_id(request); - tkl = coap_header_get_token(request, token); - - LOG_INF("*******"); - LOG_INF("type: %u code %u id %u", type, code, id); - LOG_INF("*******"); - - if (type == COAP_TYPE_ACK) { - return 0; - } - - data = (uint8_t *)k_malloc(MAX_COAP_MSG_LEN); - if (!data) { - return -ENOMEM; - } - - r = coap_packet_init(&response, data, MAX_COAP_MSG_LEN, - COAP_VERSION_1, COAP_TYPE_ACK, tkl, token, 0, id); - if (r < 0) { - goto end; - } - - r = send_coap_reply(&response, addr, addr_len); - if (r < 0) { - goto end; - } - - if (type == COAP_TYPE_CON) { - type = COAP_TYPE_CON; - } else { - type = COAP_TYPE_NON_CON; - } - - /* Do not free and allocate "data" again, re-use the buffer */ - r = coap_packet_init(&response, data, MAX_COAP_MSG_LEN, - COAP_VERSION_1, type, tkl, token, - COAP_RESPONSE_CODE_CONTENT, id); - if (r < 0) { - goto end; - } - - r = coap_append_option_int(&response, COAP_OPTION_CONTENT_FORMAT, - COAP_CONTENT_FORMAT_TEXT_PLAIN); - if (r < 0) { - goto end; - } - - r = coap_packet_append_payload_marker(&response); - if (r < 0) { - goto end; - } - - /* The response that coap-client expects */ - r = snprintk((char *) payload, sizeof(payload), - "Type: %u\nCode: %u\nMID: %u\n", type, code, id); - if (r < 0) { - goto end; - } - - r = coap_packet_append_payload(&response, (uint8_t *)payload, - strlen(payload)); - if (r < 0) { - goto end; - } - - r = send_coap_reply(&response, addr, addr_len); - -end: - k_free(data); - - return r; -} - -static int large_get(struct coap_resource *resource, - struct coap_packet *request, - struct sockaddr *addr, socklen_t addr_len) - -{ - static struct coap_block_context ctx; - struct coap_packet response; - uint8_t payload[64]; - uint8_t token[COAP_TOKEN_MAX_LEN]; - uint8_t *data; - uint16_t size; - uint16_t id; - uint8_t code; - uint8_t type; - uint8_t tkl; - int r; - - if (ctx.total_size == 0) { - coap_block_transfer_init(&ctx, COAP_BLOCK_64, - BLOCK_WISE_TRANSFER_SIZE_GET); - } - - r = coap_update_from_block(request, &ctx); - if (r < 0) { - return -EINVAL; - } - - code = coap_header_get_code(request); - type = coap_header_get_type(request); - id = coap_header_get_id(request); - tkl = coap_header_get_token(request, token); - - LOG_INF("*******"); - LOG_INF("type: %u code %u id %u", type, code, id); - LOG_INF("*******"); - - data = (uint8_t *)k_malloc(MAX_COAP_MSG_LEN); - if (!data) { - return -ENOMEM; - } - - r = coap_packet_init(&response, data, MAX_COAP_MSG_LEN, - COAP_VERSION_1, COAP_TYPE_ACK, tkl, token, - COAP_RESPONSE_CODE_CONTENT, id); - if (r < 0) { - return -EINVAL; - } - - r = coap_append_option_int(&response, COAP_OPTION_CONTENT_FORMAT, - COAP_CONTENT_FORMAT_TEXT_PLAIN); - if (r < 0) { - goto end; - } - - r = coap_append_block2_option(&response, &ctx); - if (r < 0) { - goto end; - } - - r = coap_packet_append_payload_marker(&response); - if (r < 0) { - goto end; - } - - size = MIN(coap_block_size_to_bytes(ctx.block_size), - ctx.total_size - ctx.current); - - memset(payload, 'A', MIN(size, sizeof(payload))); - - r = coap_packet_append_payload(&response, (uint8_t *)payload, size); - if (r < 0) { - goto end; - } - - r = coap_next_block(&response, &ctx); - if (!r) { - /* Will return 0 when it's the last block. */ - memset(&ctx, 0, sizeof(ctx)); - } - - r = send_coap_reply(&response, addr, addr_len); - -end: - k_free(data); - - return r; -} - -static int large_update_put(struct coap_resource *resource, - struct coap_packet *request, - struct sockaddr *addr, socklen_t addr_len) -{ - static struct coap_block_context ctx; - struct coap_packet response; - const uint8_t *payload; - uint8_t token[COAP_TOKEN_MAX_LEN]; - uint8_t *data; - uint16_t id; - uint16_t len; - uint8_t code; - uint8_t type; - uint8_t tkl; - int r; - bool last_block; - - r = coap_get_option_int(request, COAP_OPTION_BLOCK1); - if (r < 0) { - return -EINVAL; - } - - last_block = !GET_MORE(r); - - /* initialize block context upon the arrival of first block */ - if (!GET_BLOCK_NUM(r)) { - coap_block_transfer_init(&ctx, COAP_BLOCK_64, 0); - } - - r = coap_update_from_block(request, &ctx); - if (r < 0) { - LOG_ERR("Invalid block size option from request"); - return -EINVAL; - } - - payload = coap_packet_get_payload(request, &len); - if (!last_block && payload == NULL) { - LOG_ERR("Packet without payload"); - return -EINVAL; - } - - LOG_INF("**************"); - LOG_INF("[ctx] current %zu block_size %u total_size %zu", - ctx.current, coap_block_size_to_bytes(ctx.block_size), - ctx.total_size); - LOG_INF("**************"); - - code = coap_header_get_code(request); - type = coap_header_get_type(request); - id = coap_header_get_id(request); - tkl = coap_header_get_token(request, token); - - LOG_INF("*******"); - LOG_INF("type: %u code %u id %u", type, code, id); - LOG_INF("*******"); - - /* Do something with the payload */ - - if (!last_block) { - code = COAP_RESPONSE_CODE_CONTINUE; - } else { - code = COAP_RESPONSE_CODE_CHANGED; - } - - data = (uint8_t *)k_malloc(MAX_COAP_MSG_LEN); - if (!data) { - return -ENOMEM; - } - - r = coap_packet_init(&response, data, MAX_COAP_MSG_LEN, - COAP_VERSION_1, COAP_TYPE_ACK, tkl, token, - code, id); - if (r < 0) { - goto end; - } - - r = coap_append_block1_option(&response, &ctx); - if (r < 0) { - LOG_ERR("Could not add Block1 option to response"); - goto end; - } - - r = send_coap_reply(&response, addr, addr_len); - -end: - k_free(data); - - return r; -} - -static int large_create_post(struct coap_resource *resource, - struct coap_packet *request, - struct sockaddr *addr, socklen_t addr_len) -{ - static struct coap_block_context ctx; - struct coap_packet response; - const uint8_t *payload; - uint8_t token[COAP_TOKEN_MAX_LEN]; - uint8_t *data; - uint16_t len; - uint16_t id; - uint8_t code; - uint8_t type; - uint8_t tkl; - int r; - bool last_block; - - r = coap_get_option_int(request, COAP_OPTION_BLOCK1); - if (r < 0) { - return -EINVAL; - } - - last_block = !GET_MORE(r); - - /* initialize block context upon the arrival of first block */ - if (!GET_BLOCK_NUM(r)) { - coap_block_transfer_init(&ctx, COAP_BLOCK_32, 0); - } - - r = coap_update_from_block(request, &ctx); - if (r < 0) { - LOG_ERR("Invalid block size option from request"); - return -EINVAL; - } - - payload = coap_packet_get_payload(request, &len); - if (!last_block && payload) { - LOG_ERR("Packet without payload"); - return -EINVAL; - } - - code = coap_header_get_code(request); - type = coap_header_get_type(request); - id = coap_header_get_id(request); - tkl = coap_header_get_token(request, token); - - LOG_INF("*******"); - LOG_INF("type: %u code %u id %u", type, code, id); - LOG_INF("*******"); - - if (!last_block) { - code = COAP_RESPONSE_CODE_CONTINUE; - } else { - code = COAP_RESPONSE_CODE_CREATED; - } - - data = (uint8_t *)k_malloc(MAX_COAP_MSG_LEN); - if (!data) { - return -ENOMEM; - } - - r = coap_packet_init(&response, data, MAX_COAP_MSG_LEN, - COAP_VERSION_1, COAP_TYPE_ACK, tkl, token, - code, id); - if (r < 0) { - goto end; - } - - r = coap_append_block1_option(&response, &ctx); - if (r < 0) { - LOG_ERR("Could not add Block1 option to response"); - goto end; - } - - r = send_coap_reply(&response, addr, addr_len); - -end: - k_free(data); - - return r; -} - -static void schedule_next_retransmission(void) -{ - struct coap_pending *pending; - int64_t remaining; - int64_t now = k_uptime_get(); - - /* Get the first pending retransmission to expire after cycling. */ - pending = coap_pending_next_to_expire(pendings, NUM_PENDINGS); - if (!pending) { - return; - } - - remaining = pending->t0 + pending->timeout - now; - if (remaining < 0) { - remaining = 0; - } - - k_work_reschedule(&retransmit_work, K_MSEC(remaining)); -} - -static void remove_observer(struct sockaddr *addr); - -static void retransmit_request(struct k_work *work) -{ - struct coap_pending *pending; - int r; - - pending = coap_pending_next_to_expire(pendings, NUM_PENDINGS); - if (!pending) { - return; - } - - if (!coap_pending_cycle(pending)) { - remove_observer(&pending->addr); - k_free(pending->data); - coap_pending_clear(pending); - } else { - net_hexdump("Retransmit", pending->data, pending->len); - - r = sendto(sock, pending->data, pending->len, 0, - &pending->addr, ADDRLEN(&pending->addr)); - if (r < 0) { - LOG_ERR("Failed to send %d", errno); - } - } - - schedule_next_retransmission(); -} - -static void update_counter(struct k_work *work) -{ - obs_counter++; - - if (resource_to_notify) { - coap_resource_notify(resource_to_notify); - } - - k_work_reschedule(&observer_work, K_SECONDS(5)); -} - -static int create_pending_request(struct coap_packet *response, - const struct sockaddr *addr) -{ - struct coap_pending *pending; - int r; - - pending = coap_pending_next_unused(pendings, NUM_PENDINGS); - if (!pending) { - return -ENOMEM; - } - - r = coap_pending_init(pending, response, addr, MAX_RETRANSMIT_COUNT); - if (r < 0) { - return -EINVAL; - } - - coap_pending_cycle(pending); - - schedule_next_retransmission(); - - return 0; -} - -static int send_notification_packet(const struct sockaddr *addr, - socklen_t addr_len, - uint16_t age, uint16_t id, - const uint8_t *token, uint8_t tkl, - bool is_response) -{ - struct coap_packet response; - char payload[14]; - uint8_t *data; - uint8_t type; - int r; - - if (is_response) { - type = COAP_TYPE_ACK; - } else { - type = COAP_TYPE_CON; - } - - if (!is_response) { - id = coap_next_id(); - } - - data = (uint8_t *)k_malloc(MAX_COAP_MSG_LEN); - if (!data) { - return -ENOMEM; - } - - r = coap_packet_init(&response, data, MAX_COAP_MSG_LEN, - COAP_VERSION_1, type, tkl, token, - COAP_RESPONSE_CODE_CONTENT, id); - if (r < 0) { - goto end; - } - - if (age >= 2U) { - r = coap_append_option_int(&response, COAP_OPTION_OBSERVE, age); - if (r < 0) { - goto end; - } - } - - r = coap_append_option_int(&response, COAP_OPTION_CONTENT_FORMAT, - COAP_CONTENT_FORMAT_TEXT_PLAIN); - if (r < 0) { - goto end; - } - - r = coap_packet_append_payload_marker(&response); - if (r < 0) { - goto end; - } - - /* The response that coap-client expects */ - r = snprintk((char *) payload, sizeof(payload), - "Counter: %d\n", obs_counter); - if (r < 0) { - goto end; - } - - r = coap_packet_append_payload(&response, (uint8_t *)payload, - strlen(payload)); - if (r < 0) { - goto end; - } - - if (type == COAP_TYPE_CON) { - r = create_pending_request(&response, addr); - if (r < 0) { - goto end; - } - } - - k_work_reschedule(&observer_work, K_SECONDS(5)); - - r = send_coap_reply(&response, addr, addr_len); - - /* On successful creation of pending request, do not free memory */ - if (type == COAP_TYPE_CON) { - return r; - } - -end: - k_free(data); - - return r; -} - -static int obs_get(struct coap_resource *resource, - struct coap_packet *request, - struct sockaddr *addr, socklen_t addr_len) -{ - struct coap_observer *observer; - uint8_t token[COAP_TOKEN_MAX_LEN]; - uint16_t id; - uint8_t code; - uint8_t type; - uint8_t tkl; - bool observe = true; - - if (!coap_request_is_observe(request)) { - if (coap_get_option_int(request, COAP_OPTION_OBSERVE) == 1) { - remove_observer(addr); - } - observe = false; - goto done; - } - - observer = coap_observer_next_unused(observers, NUM_OBSERVERS); - if (!observer) { - LOG_ERR("Not enough observer slots."); - return -ENOMEM; - } - - coap_observer_init(observer, request, addr); - - coap_register_observer(resource, observer); - - resource_to_notify = resource; - -done: - code = coap_header_get_code(request); - type = coap_header_get_type(request); - id = coap_header_get_id(request); - tkl = coap_header_get_token(request, token); - - LOG_INF("*******"); - LOG_INF("type: %u code %u id %u", type, code, id); - LOG_INF("*******"); - - return send_notification_packet(addr, addr_len, - observe ? resource->age : 0, - id, token, tkl, true); -} - -static void obs_notify(struct coap_resource *resource, - struct coap_observer *observer) -{ - send_notification_packet(&observer->addr, - sizeof(observer->addr), - resource->age, 0, - observer->token, observer->tkl, false); -} - -static int core_get(struct coap_resource *resource, - struct coap_packet *request, - struct sockaddr *addr, socklen_t addr_len) -{ - static const char dummy_str[] = "Just a test\n"; - struct coap_packet response; - uint8_t token[COAP_TOKEN_MAX_LEN]; - uint8_t *data; - uint16_t id; - uint8_t tkl; - int r; - - id = coap_header_get_id(request); - tkl = coap_header_get_token(request, token); - - data = (uint8_t *)k_malloc(MAX_COAP_MSG_LEN); - if (!data) { - return -ENOMEM; - } - - r = coap_packet_init(&response, data, MAX_COAP_MSG_LEN, - COAP_VERSION_1, COAP_TYPE_ACK, tkl, token, - COAP_RESPONSE_CODE_CONTENT, id); - if (r < 0) { - r = -EINVAL; - goto end; - } - - r = coap_packet_append_payload_marker(&response); - if (r < 0) { - r = -EINVAL; - goto end; - } - - r = coap_packet_append_payload(&response, (uint8_t *)dummy_str, - sizeof(dummy_str)); - if (r < 0) { - r = -EINVAL; - goto end; - } - - r = send_coap_reply(&response, addr, addr_len); - -end: - k_free(data); - - return r; -} - -static const char * const test_path[] = { "test", NULL }; - -static const char * const segments_path[] = { "seg1", "seg2", "seg3", NULL }; - -#if defined(CONFIG_COAP_URI_WILDCARD) -static const char * const wildcard1_path[] = { "wild1", "+", "wild3", NULL }; - -static const char * const wildcard2_path[] = { "wild2", "#", NULL }; -#endif /* CONFIG_COAP_URI_WILDCARD */ - -static const char * const query_path[] = { "query", NULL }; - -static const char * const separate_path[] = { "separate", NULL }; - -static const char * const location_query_path[] = { "location-query", NULL }; - -static const char * const large_path[] = { "large", NULL }; - -static const char * const large_update_path[] = { "large-update", NULL }; - -static const char * const large_create_path[] = { "large-create", NULL }; - -static const char * const obs_path[] = { "obs", NULL }; - -static const char * const core_1_path[] = { "core1", NULL }; -static const char * const core_1_attributes[] = { - "title=\"Core 1\"", - "rt=core1", - NULL }; - -static const char * const core_2_path[] = { "core2", NULL }; -static const char * const core_2_attributes[] = { - "title=\"Core 1\"", - "rt=core1", - NULL }; - -static struct coap_resource coap_resources[] = { - { .get = well_known_core_get, - .path = COAP_WELL_KNOWN_CORE_PATH, - }, - { .get = piggyback_get, - .post = test_post, - .del = test_del, - .put = test_put, - .path = test_path - }, - { .get = piggyback_get, - .path = segments_path, - }, -#if defined(CONFIG_COAP_URI_WILDCARD) - { .get = piggyback_get, - .path = wildcard1_path, - }, - { .get = piggyback_get, - .path = wildcard2_path, - }, -#endif /* CONFIG_COAP_URI_WILDCARD */ - { .get = query_get, - .path = query_path, - }, - { .get = separate_get, - .path = separate_path, - }, - { .path = location_query_path, - .post = location_query_post, - }, - { .path = large_path, - .get = large_get, - }, - { .path = large_update_path, - .put = large_update_put, - }, - { .path = large_create_path, - .post = large_create_post, - }, - { .path = obs_path, - .get = obs_get, - .notify = obs_notify, - }, - { .get = core_get, - .path = core_1_path, - .user_data = &((struct coap_core_metadata) { - .attributes = core_1_attributes, - }), - }, - { .get = core_get, - .path = core_2_path, - .user_data = &((struct coap_core_metadata) { - .attributes = core_2_attributes, - }), - }, - { }, -}; - -static struct coap_resource *find_resource_by_observer( - struct coap_resource *resources, struct coap_observer *o) -{ - struct coap_resource *r; - - for (r = resources; r && r->path; r++) { - sys_snode_t *node; - - SYS_SLIST_FOR_EACH_NODE(&r->observers, node) { - if (&o->list == node) { - return r; - } - } - } - - return NULL; -} - -static void remove_observer(struct sockaddr *addr) -{ - struct coap_resource *r; - struct coap_observer *o; - - o = coap_find_observer_by_addr(observers, NUM_OBSERVERS, addr); - if (!o) { - return; - } - - r = find_resource_by_observer(coap_resources, o); - if (!r) { - LOG_ERR("Observer found but Resource not found\n"); - return; - } - - LOG_INF("Removing observer %p", o); - - coap_remove_observer(r, o); - memset(o, 0, sizeof(struct coap_observer)); -} - -static void process_coap_request(uint8_t *data, uint16_t data_len, - struct sockaddr *client_addr, - socklen_t client_addr_len) -{ - struct coap_packet request; - struct coap_pending *pending; - struct coap_option options[16] = { 0 }; - uint8_t opt_num = 16U; - uint8_t type; - int r; - - r = coap_packet_parse(&request, data, data_len, options, opt_num); - if (r < 0) { - LOG_ERR("Invalid data received (%d)\n", r); - return; - } - - type = coap_header_get_type(&request); - - pending = coap_pending_received(&request, pendings, NUM_PENDINGS); - if (!pending) { - goto not_found; - } - - /* Clear CoAP pending request */ - if (type == COAP_TYPE_ACK || type == COAP_TYPE_RESET) { - k_free(pending->data); - coap_pending_clear(pending); - - if (type == COAP_TYPE_RESET) { - remove_observer(client_addr); - } - } - - return; - -not_found: - r = coap_handle_request(&request, coap_resources, options, opt_num, - client_addr, client_addr_len); - if (r < 0) { - LOG_WRN("No handler for such request (%d)\n", r); - } -} - -static int process_client_request(void) -{ - int received; - struct sockaddr client_addr; - socklen_t client_addr_len; - uint8_t request[MAX_COAP_MSG_LEN]; - - do { - client_addr_len = sizeof(client_addr); - received = recvfrom(sock, request, sizeof(request), 0, - &client_addr, &client_addr_len); - if (received < 0) { - LOG_ERR("Connection error %d", errno); - return -errno; - } - - process_coap_request(request, received, &client_addr, - client_addr_len); - } while (true); - - return 0; -} - -int main(void) -{ - int r; - - LOG_DBG("Start CoAP-server sample"); - -#if defined(CONFIG_NET_IPV6) - bool res; - - res = join_coap_multicast_group(); - if (!res) { - goto quit; - } -#endif - - r = start_coap_server(); - if (r < 0) { - goto quit; - } - - k_work_init_delayable(&retransmit_work, retransmit_request); - k_work_init_delayable(&observer_work, update_counter); - - while (1) { - r = process_client_request(); - if (r < 0) { - goto quit; - } - } - - LOG_DBG("Done"); - return 0; - -quit: - LOG_ERR("Quit"); - return 0; -} diff --git a/samples/net/sockets/coap_server/src/core.c b/samples/net/sockets/coap_server/src/core.c new file mode 100644 index 00000000000..276ab0d5de1 --- /dev/null +++ b/samples/net/sockets/coap_server/src/core.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2023 Basalte bv + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_coap_service_sample); + +#include +#include +#include + +static int core_get(struct coap_resource *resource, + struct coap_packet *request, + struct sockaddr *addr, socklen_t addr_len) +{ + static const char dummy_str[] = "Just a test\n"; + uint8_t data[CONFIG_COAP_SERVER_MESSAGE_SIZE]; + struct coap_packet response; + uint8_t token[COAP_TOKEN_MAX_LEN]; + uint16_t id; + uint8_t tkl; + int r; + + id = coap_header_get_id(request); + tkl = coap_header_get_token(request, token); + + r = coap_packet_init(&response, data, sizeof(data), + COAP_VERSION_1, COAP_TYPE_ACK, tkl, token, + COAP_RESPONSE_CODE_CONTENT, id); + if (r < 0) { + return r; + } + + r = coap_packet_append_payload_marker(&response); + if (r < 0) { + return r; + } + + r = coap_packet_append_payload(&response, (uint8_t *)dummy_str, + sizeof(dummy_str)); + if (r < 0) { + return r; + } + + r = coap_resource_send(resource, &response, addr, addr_len); + + return r; +} + +static const char * const core_1_path[] = { "core1", NULL }; +static const char * const core_1_attributes[] = { + "title=\"Core 1\"", + "rt=core1", + NULL, +}; +COAP_RESOURCE_DEFINE(core_1, coap_server, +{ + .get = core_get, + .path = core_1_path, + .user_data = &((struct coap_core_metadata) { + .attributes = core_1_attributes, + }), +}); + +static const char * const core_2_path[] = { "core2", NULL }; +static const char * const core_2_attributes[] = { + "title=\"Core 2\"", + "rt=core2", + NULL, +}; +COAP_RESOURCE_DEFINE(core_2, coap_server, +{ + .get = core_get, + .path = core_2_path, + .user_data = &((struct coap_core_metadata) { + .attributes = core_2_attributes, + }), +}); diff --git a/samples/net/sockets/coap_server/src/large.c b/samples/net/sockets/coap_server/src/large.c new file mode 100644 index 00000000000..28a3eebe099 --- /dev/null +++ b/samples/net/sockets/coap_server/src/large.c @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2023 Basalte bv + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_coap_service_sample); + +#include +#include + +#define BLOCK_WISE_TRANSFER_SIZE_GET 2048 + +static int large_get(struct coap_resource *resource, + struct coap_packet *request, + struct sockaddr *addr, socklen_t addr_len) + +{ + uint8_t data[CONFIG_COAP_SERVER_MESSAGE_SIZE]; + static struct coap_block_context ctx; + struct coap_packet response; + uint8_t payload[64]; + uint8_t token[COAP_TOKEN_MAX_LEN]; + uint16_t size; + uint16_t id; + uint8_t code; + uint8_t type; + uint8_t tkl; + int r; + + if (ctx.total_size == 0) { + coap_block_transfer_init(&ctx, COAP_BLOCK_64, BLOCK_WISE_TRANSFER_SIZE_GET); + } + + r = coap_update_from_block(request, &ctx); + if (r < 0) { + return -EINVAL; + } + + code = coap_header_get_code(request); + type = coap_header_get_type(request); + id = coap_header_get_id(request); + tkl = coap_header_get_token(request, token); + + LOG_INF("*******"); + LOG_INF("type: %u code %u id %u", type, code, id); + LOG_INF("*******"); + + r = coap_packet_init(&response, data, sizeof(data), + COAP_VERSION_1, COAP_TYPE_ACK, tkl, token, + COAP_RESPONSE_CODE_CONTENT, id); + if (r < 0) { + return -EINVAL; + } + + r = coap_append_option_int(&response, COAP_OPTION_CONTENT_FORMAT, + COAP_CONTENT_FORMAT_TEXT_PLAIN); + if (r < 0) { + return r; + } + + r = coap_append_block2_option(&response, &ctx); + if (r < 0) { + return r; + } + + r = coap_packet_append_payload_marker(&response); + if (r < 0) { + return r; + } + + size = MIN(coap_block_size_to_bytes(ctx.block_size), + ctx.total_size - ctx.current); + + memset(payload, 'A', MIN(size, sizeof(payload))); + + r = coap_packet_append_payload(&response, (uint8_t *)payload, size); + if (r < 0) { + return r; + } + + r = coap_next_block(&response, &ctx); + if (!r) { + /* Will return 0 when it's the last block. */ + memset(&ctx, 0, sizeof(ctx)); + } + + r = coap_resource_send(resource, &response, addr, addr_len); + + return r; +} + +static int large_update_put(struct coap_resource *resource, + struct coap_packet *request, + struct sockaddr *addr, socklen_t addr_len) +{ + uint8_t data[CONFIG_COAP_SERVER_MESSAGE_SIZE]; + static struct coap_block_context ctx; + struct coap_packet response; + const uint8_t *payload; + uint8_t token[COAP_TOKEN_MAX_LEN]; + uint16_t id; + uint16_t len; + uint8_t code; + uint8_t type; + uint8_t tkl; + int r; + bool last_block; + + r = coap_get_option_int(request, COAP_OPTION_BLOCK1); + if (r < 0) { + return -EINVAL; + } + + last_block = !GET_MORE(r); + + /* initialize block context upon the arrival of first block */ + if (!GET_BLOCK_NUM(r)) { + coap_block_transfer_init(&ctx, COAP_BLOCK_64, 0); + } + + r = coap_update_from_block(request, &ctx); + if (r < 0) { + LOG_ERR("Invalid block size option from request"); + return -EINVAL; + } + + payload = coap_packet_get_payload(request, &len); + if (!last_block && payload == NULL) { + LOG_ERR("Packet without payload"); + return -EINVAL; + } + + LOG_INF("**************"); + LOG_INF("[ctx] current %zu block_size %u total_size %zu", + ctx.current, coap_block_size_to_bytes(ctx.block_size), + ctx.total_size); + LOG_INF("**************"); + + code = coap_header_get_code(request); + type = coap_header_get_type(request); + id = coap_header_get_id(request); + tkl = coap_header_get_token(request, token); + + LOG_INF("*******"); + LOG_INF("type: %u code %u id %u", type, code, id); + LOG_INF("*******"); + + /* Do something with the payload */ + + if (!last_block) { + code = COAP_RESPONSE_CODE_CONTINUE; + } else { + code = COAP_RESPONSE_CODE_CHANGED; + } + + r = coap_ack_init(&response, request, data, sizeof(data), code); + if (r < 0) { + return r; + } + + r = coap_append_block1_option(&response, &ctx); + if (r < 0) { + LOG_ERR("Could not add Block1 option to response"); + return r; + } + + r = coap_resource_send(resource, &response, addr, addr_len); + + return r; +} + +static int large_create_post(struct coap_resource *resource, + struct coap_packet *request, + struct sockaddr *addr, socklen_t addr_len) +{ + uint8_t data[CONFIG_COAP_SERVER_MESSAGE_SIZE]; + static struct coap_block_context ctx; + struct coap_packet response; + const uint8_t *payload; + uint8_t token[COAP_TOKEN_MAX_LEN]; + uint16_t len; + uint16_t id; + uint8_t code; + uint8_t type; + uint8_t tkl; + int r; + bool last_block; + + r = coap_get_option_int(request, COAP_OPTION_BLOCK1); + if (r < 0) { + return -EINVAL; + } + + last_block = !GET_MORE(r); + + /* initialize block context upon the arrival of first block */ + if (!GET_BLOCK_NUM(r)) { + coap_block_transfer_init(&ctx, COAP_BLOCK_32, 0); + } + + r = coap_update_from_block(request, &ctx); + if (r < 0) { + LOG_ERR("Invalid block size option from request"); + return -EINVAL; + } + + payload = coap_packet_get_payload(request, &len); + if (!last_block && payload) { + LOG_ERR("Packet without payload"); + return -EINVAL; + } + + code = coap_header_get_code(request); + type = coap_header_get_type(request); + id = coap_header_get_id(request); + tkl = coap_header_get_token(request, token); + + LOG_INF("*******"); + LOG_INF("type: %u code %u id %u", type, code, id); + LOG_INF("*******"); + + if (!last_block) { + code = COAP_RESPONSE_CODE_CONTINUE; + } else { + code = COAP_RESPONSE_CODE_CREATED; + } + + r = coap_ack_init(&response, request, data, sizeof(data), code); + if (r < 0) { + return r; + } + + r = coap_append_block1_option(&response, &ctx); + if (r < 0) { + LOG_ERR("Could not add Block1 option to response"); + return r; + } + + r = coap_resource_send(resource, &response, addr, addr_len); + + return r; +} + +static const char * const large_path[] = { "large", NULL }; +COAP_RESOURCE_DEFINE(large, coap_server, +{ + .get = large_get, + .path = large_path, +}); + +static const char * const large_update_path[] = { "large-update", NULL }; +COAP_RESOURCE_DEFINE(large_update, coap_server, +{ + .put = large_update_put, + .path = large_update_path, +}); + +static const char * const large_create_path[] = { "large-create", NULL }; +COAP_RESOURCE_DEFINE(large_create, coap_server, +{ + .post = large_create_post, + .path = large_create_path, +}); diff --git a/samples/net/sockets/coap_server/src/location_query.c b/samples/net/sockets/coap_server/src/location_query.c new file mode 100644 index 00000000000..b13079bc456 --- /dev/null +++ b/samples/net/sockets/coap_server/src/location_query.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2023 Basalte bv + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_coap_service_sample); + +#include +#include + +static int location_query_post(struct coap_resource *resource, + struct coap_packet *request, + struct sockaddr *addr, socklen_t addr_len) +{ + static const char *const location_query[] = { "first=1", + "second=2", + NULL }; + uint8_t data[CONFIG_COAP_SERVER_MESSAGE_SIZE]; + const char * const *p; + struct coap_packet response; + uint8_t token[COAP_TOKEN_MAX_LEN]; + uint16_t id; + uint8_t code; + uint8_t type; + uint8_t tkl; + int r; + + code = coap_header_get_code(request); + type = coap_header_get_type(request); + id = coap_header_get_id(request); + tkl = coap_header_get_token(request, token); + + LOG_INF("*******"); + LOG_INF("type: %u code %u id %u", type, code, id); + LOG_INF("*******"); + + if (type == COAP_TYPE_CON) { + type = COAP_TYPE_ACK; + } else { + type = COAP_TYPE_NON_CON; + } + + r = coap_packet_init(&response, data, sizeof(data), + COAP_VERSION_1, type, tkl, token, + COAP_RESPONSE_CODE_CREATED, id); + if (r < 0) { + return r; + } + + for (p = location_query; *p; p++) { + r = coap_packet_append_option(&response, + COAP_OPTION_LOCATION_QUERY, + *p, strlen(*p)); + if (r < 0) { + return r; + } + } + + r = coap_resource_send(resource, &response, addr, addr_len); + + return r; +} + +static const char * const location_query_path[] = { "location-query", NULL }; +COAP_RESOURCE_DEFINE(location_query, coap_server, +{ + .post = location_query_post, + .path = location_query_path, +}); diff --git a/samples/net/sockets/coap_server/src/main.c b/samples/net/sockets/coap_server/src/main.c new file mode 100644 index 00000000000..4f476511b2c --- /dev/null +++ b/samples/net/sockets/coap_server/src/main.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2023 Basalte bv + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_REGISTER(net_coap_service_sample, LOG_LEVEL_DBG); + +#include + +#ifdef CONFIG_NET_IPV6 +#include "net_private.h" +#include "ipv6.h" +#endif + +static const uint16_t coap_port = 5683; + +#ifdef CONFIG_NET_IPV6 + +#define ALL_NODES_LOCAL_COAP_MCAST \ + { { { 0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfd } } } + +#define MY_IP6ADDR \ + { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1 } } } + +static int join_coap_multicast_group(void) +{ + static struct in6_addr my_addr = MY_IP6ADDR; + static struct sockaddr_in6 mcast_addr = { + .sin6_family = AF_INET6, + .sin6_addr = ALL_NODES_LOCAL_COAP_MCAST, + .sin6_port = htons(coap_port) }; + struct net_if_addr *ifaddr; + struct net_if *iface; + int ret; + + iface = net_if_get_default(); + if (!iface) { + LOG_ERR("Could not get the default interface"); + return -ENOENT; + } + +#if defined(CONFIG_NET_CONFIG_SETTINGS) + if (net_addr_pton(AF_INET6, + CONFIG_NET_CONFIG_MY_IPV6_ADDR, + &my_addr) < 0) { + LOG_ERR("Invalid IPv6 address %s", + CONFIG_NET_CONFIG_MY_IPV6_ADDR); + } +#endif + + ifaddr = net_if_ipv6_addr_add(iface, &my_addr, NET_ADDR_MANUAL, 0); + if (!ifaddr) { + LOG_ERR("Could not add unicast address to interface"); + return -EINVAL; + } + + ifaddr->addr_state = NET_ADDR_PREFERRED; + + ret = net_ipv6_mld_join(iface, &mcast_addr.sin6_addr); + if (ret < 0) { + LOG_ERR("Cannot join %s IPv6 multicast group (%d)", + net_sprint_ipv6_addr(&mcast_addr.sin6_addr), ret); + return ret; + } + + return 0; +} + +int main(void) +{ + return join_coap_multicast_group(); +} + +#else /* CONFIG_NET_IPV6 */ + +int main(void) +{ + return 0; +} + +#endif /* CONFIG_NET_IPV6 */ + +COAP_SERVICE_DEFINE(coap_server, NULL, &coap_port, COAP_SERVICE_AUTOSTART); diff --git a/samples/net/sockets/coap_server/src/observer.c b/samples/net/sockets/coap_server/src/observer.c new file mode 100644 index 00000000000..29b7b4ed472 --- /dev/null +++ b/samples/net/sockets/coap_server/src/observer.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2023 Basalte bv + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_coap_service_sample); + +#include +#include +#include + +static int obs_counter; + +static void update_counter(struct k_work *work); +K_WORK_DELAYABLE_DEFINE(obs_work, update_counter); + +#ifdef CONFIG_COAP_OBSERVER_EVENTS + +static void observer_event(struct coap_resource *resource, struct coap_observer *observer, + enum coap_observer_event event) +{ + LOG_INF("Observer %s", event == COAP_OBSERVER_ADDED ? "added" : "removed"); +} + +#endif + +static int send_notification_packet(struct coap_resource *resource, + const struct sockaddr *addr, + socklen_t addr_len, + uint16_t age, uint16_t id, + const uint8_t *token, uint8_t tkl, + bool is_response) +{ + uint8_t data[CONFIG_COAP_SERVER_MESSAGE_SIZE]; + struct coap_packet response; + char payload[14]; + uint8_t type; + int r; + + if (is_response) { + type = COAP_TYPE_ACK; + } else { + type = COAP_TYPE_CON; + } + + if (!is_response) { + id = coap_next_id(); + } + + r = coap_packet_init(&response, data, sizeof(data), + COAP_VERSION_1, type, tkl, token, + COAP_RESPONSE_CODE_CONTENT, id); + if (r < 0) { + return r; + } + + if (age >= 2U) { + r = coap_append_option_int(&response, COAP_OPTION_OBSERVE, age); + if (r < 0) { + return r; + } + } + + r = coap_append_option_int(&response, COAP_OPTION_CONTENT_FORMAT, + COAP_CONTENT_FORMAT_TEXT_PLAIN); + if (r < 0) { + return r; + } + + r = coap_packet_append_payload_marker(&response); + if (r < 0) { + return r; + } + + /* The response that coap-client expects */ + r = snprintk((char *) payload, sizeof(payload), + "Counter: %d\n", obs_counter); + if (r < 0) { + return r; + } + + r = coap_packet_append_payload(&response, (uint8_t *)payload, + strlen(payload)); + if (r < 0) { + return r; + } + + k_work_reschedule(&obs_work, K_SECONDS(5)); + + r = coap_resource_send(resource, &response, addr, addr_len); + + return r; +} + +static int obs_get(struct coap_resource *resource, + struct coap_packet *request, + struct sockaddr *addr, socklen_t addr_len) +{ + uint8_t token[COAP_TOKEN_MAX_LEN]; + uint16_t id; + uint8_t code; + uint8_t type; + uint8_t tkl; + int r; + + r = coap_resource_parse_observe(resource, request, addr); + + code = coap_header_get_code(request); + type = coap_header_get_type(request); + id = coap_header_get_id(request); + tkl = coap_header_get_token(request, token); + + LOG_INF("*******"); + LOG_INF("type: %u code %u id %u", type, code, id); + LOG_INF("*******"); + + return send_notification_packet(resource, addr, addr_len, + r == 0 ? resource->age : 0, + id, token, tkl, true); +} + +static void obs_notify(struct coap_resource *resource, + struct coap_observer *observer) +{ + send_notification_packet(resource, + &observer->addr, + sizeof(observer->addr), + resource->age, 0, + observer->token, observer->tkl, false); +} + +static const char * const obs_path[] = { "obs", NULL }; +COAP_RESOURCE_DEFINE(obs, coap_server, +{ + .get = obs_get, + .path = obs_path, + .notify = obs_notify, +#ifdef CONFIG_COAP_OBSERVER_EVENTS + .observer_event_handler = observer_event, +#endif +}); + +static void update_counter(struct k_work *work) +{ + obs_counter++; + + coap_resource_notify(&obs); + + k_work_reschedule(&obs_work, K_SECONDS(5)); +} diff --git a/samples/net/sockets/coap_server/src/query.c b/samples/net/sockets/coap_server/src/query.c new file mode 100644 index 00000000000..10479b1e6f1 --- /dev/null +++ b/samples/net/sockets/coap_server/src/query.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2023 Basalte bv + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_coap_service_sample); + +#include +#include + +static int query_get(struct coap_resource *resource, + struct coap_packet *request, + struct sockaddr *addr, socklen_t addr_len) +{ + uint8_t data[CONFIG_COAP_SERVER_MESSAGE_SIZE]; + struct coap_option options[4]; + struct coap_packet response; + uint8_t payload[40]; + uint8_t token[COAP_TOKEN_MAX_LEN]; + uint16_t id; + uint8_t code; + uint8_t type; + uint8_t tkl; + int i, r; + + code = coap_header_get_code(request); + type = coap_header_get_type(request); + id = coap_header_get_id(request); + tkl = coap_header_get_token(request, token); + + r = coap_find_options(request, COAP_OPTION_URI_QUERY, options, 4); + if (r < 0) { + return -EINVAL; + } + + LOG_INF("*******"); + LOG_INF("type: %u code %u id %u", type, code, id); + LOG_INF("num queries: %d", r); + + for (i = 0; i < r; i++) { + char str[16]; + + if (options[i].len + 1 > sizeof(str)) { + LOG_INF("Unexpected length of query: " + "%d (expected %zu)", + options[i].len, sizeof(str)); + break; + } + + memcpy(str, options[i].value, options[i].len); + str[options[i].len] = '\0'; + + LOG_INF("query[%d]: %s", i + 1, str); + } + + LOG_INF("*******"); + + r = coap_packet_init(&response, data, sizeof(data), + COAP_VERSION_1, COAP_TYPE_ACK, tkl, token, + COAP_RESPONSE_CODE_CONTENT, id); + if (r < 0) { + return r; + } + + r = coap_append_option_int(&response, COAP_OPTION_CONTENT_FORMAT, + COAP_CONTENT_FORMAT_TEXT_PLAIN); + if (r < 0) { + return r; + } + + r = coap_packet_append_payload_marker(&response); + if (r < 0) { + return r; + } + + /* The response that coap-client expects */ + r = snprintk((char *) payload, sizeof(payload), + "Type: %u\nCode: %u\nMID: %u\n", type, code, id); + if (r < 0) { + return r; + } + + r = coap_packet_append_payload(&response, (uint8_t *)payload, + strlen(payload)); + if (r < 0) { + return r; + } + + r = coap_resource_send(resource, &response, addr, addr_len); + + return r; +} + +static const char * const query_path[] = { "query", NULL }; +COAP_RESOURCE_DEFINE(query, coap_server, +{ + .get = query_get, + .path = query_path, +}); diff --git a/samples/net/sockets/coap_server/src/separate.c b/samples/net/sockets/coap_server/src/separate.c new file mode 100644 index 00000000000..c3f6f6c256e --- /dev/null +++ b/samples/net/sockets/coap_server/src/separate.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2023 Basalte bv + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_coap_service_sample); + +#include +#include + +static int separate_get(struct coap_resource *resource, + struct coap_packet *request, + struct sockaddr *addr, socklen_t addr_len) +{ + uint8_t data[CONFIG_COAP_SERVER_MESSAGE_SIZE]; + struct coap_packet response; + uint8_t payload[40]; + uint8_t token[COAP_TOKEN_MAX_LEN]; + uint16_t id; + uint8_t code; + uint8_t type; + uint8_t tkl; + int r; + + code = coap_header_get_code(request); + type = coap_header_get_type(request); + id = coap_header_get_id(request); + tkl = coap_header_get_token(request, token); + + LOG_INF("*******"); + LOG_INF("type: %u code %u id %u", type, code, id); + LOG_INF("*******"); + + if (type == COAP_TYPE_ACK) { + return 0; + } + + r = coap_ack_init(&response, request, data, sizeof(data), 0); + if (r < 0) { + return r; + } + + r = coap_resource_send(resource, &response, addr, addr_len); + if (r < 0) { + return r; + } + + if (type == COAP_TYPE_CON) { + type = COAP_TYPE_CON; + } else { + type = COAP_TYPE_NON_CON; + } + + /* Re-use the buffer */ + r = coap_packet_init(&response, data, sizeof(data), + COAP_VERSION_1, type, tkl, token, + COAP_RESPONSE_CODE_CONTENT, id); + if (r < 0) { + return r; + } + + r = coap_append_option_int(&response, COAP_OPTION_CONTENT_FORMAT, + COAP_CONTENT_FORMAT_TEXT_PLAIN); + if (r < 0) { + return r; + } + + r = coap_packet_append_payload_marker(&response); + if (r < 0) { + return r; + } + + /* The response that coap-client expects */ + r = snprintk((char *) payload, sizeof(payload), + "Type: %u\nCode: %u\nMID: %u\n", type, code, id); + if (r < 0) { + return r; + } + + r = coap_packet_append_payload(&response, (uint8_t *)payload, + strlen(payload)); + if (r < 0) { + return r; + } + + r = coap_resource_send(resource, &response, addr, addr_len); + + return r; +} + +static const char * const separate_path[] = { "separate", NULL }; +COAP_RESOURCE_DEFINE(separate, coap_server, +{ + .get = separate_get, + .path = separate_path, +}); diff --git a/samples/net/sockets/coap_server/src/test.c b/samples/net/sockets/coap_server/src/test.c new file mode 100644 index 00000000000..aa496a125b1 --- /dev/null +++ b/samples/net/sockets/coap_server/src/test.c @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2023 Basalte bv + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_coap_service_sample); + +#include +#include + +#include "net_private.h" + +static int piggyback_get(struct coap_resource *resource, + struct coap_packet *request, + struct sockaddr *addr, socklen_t addr_len) +{ + uint8_t data[CONFIG_COAP_SERVER_MESSAGE_SIZE]; + struct coap_packet response; + uint8_t payload[40]; + uint8_t token[COAP_TOKEN_MAX_LEN]; + uint16_t id; + uint8_t code; + uint8_t type; + uint8_t tkl; + int r; + + code = coap_header_get_code(request); + type = coap_header_get_type(request); + id = coap_header_get_id(request); + tkl = coap_header_get_token(request, token); + + LOG_INF("*******"); + LOG_INF("type: %u code %u id %u", type, code, id); + LOG_INF("*******"); + + if (type == COAP_TYPE_CON) { + type = COAP_TYPE_ACK; + } else { + type = COAP_TYPE_NON_CON; + } + + r = coap_packet_init(&response, data, sizeof(data), + COAP_VERSION_1, type, tkl, token, + COAP_RESPONSE_CODE_CONTENT, id); + if (r < 0) { + return r; + } + + r = coap_append_option_int(&response, COAP_OPTION_CONTENT_FORMAT, + COAP_CONTENT_FORMAT_TEXT_PLAIN); + if (r < 0) { + return r; + } + + r = coap_packet_append_payload_marker(&response); + if (r < 0) { + return r; + } + + /* The response that coap-client expects */ + r = snprintk((char *) payload, sizeof(payload), + "Type: %u\nCode: %u\nMID: %u\n", type, code, id); + if (r < 0) { + return r; + } + + r = coap_packet_append_payload(&response, (uint8_t *)payload, + strlen(payload)); + if (r < 0) { + return r; + } + + r = coap_resource_send(resource, &response, addr, addr_len); + + return r; +} + +static int test_del(struct coap_resource *resource, + struct coap_packet *request, + struct sockaddr *addr, socklen_t addr_len) +{ + uint8_t data[CONFIG_COAP_SERVER_MESSAGE_SIZE]; + struct coap_packet response; + uint8_t token[COAP_TOKEN_MAX_LEN]; + uint8_t tkl; + uint8_t code; + uint8_t type; + uint16_t id; + int r; + + code = coap_header_get_code(request); + type = coap_header_get_type(request); + id = coap_header_get_id(request); + tkl = coap_header_get_token(request, token); + + LOG_INF("*******"); + LOG_INF("type: %u code %u id %u", type, code, id); + LOG_INF("*******"); + + if (type == COAP_TYPE_CON) { + type = COAP_TYPE_ACK; + } else { + type = COAP_TYPE_NON_CON; + } + + r = coap_packet_init(&response, data, sizeof(data), + COAP_VERSION_1, type, tkl, token, + COAP_RESPONSE_CODE_DELETED, id); + if (r < 0) { + return r; + } + + r = coap_resource_send(resource, &response, addr, addr_len); + + return r; +} + +static int test_put(struct coap_resource *resource, + struct coap_packet *request, + struct sockaddr *addr, socklen_t addr_len) +{ + uint8_t data[CONFIG_COAP_SERVER_MESSAGE_SIZE]; + struct coap_packet response; + uint8_t token[COAP_TOKEN_MAX_LEN]; + const uint8_t *payload; + uint16_t payload_len; + uint8_t code; + uint8_t type; + uint8_t tkl; + uint16_t id; + int r; + + code = coap_header_get_code(request); + type = coap_header_get_type(request); + id = coap_header_get_id(request); + tkl = coap_header_get_token(request, token); + + LOG_INF("*******"); + LOG_INF("type: %u code %u id %u", type, code, id); + LOG_INF("*******"); + + payload = coap_packet_get_payload(request, &payload_len); + if (payload) { + net_hexdump("PUT Payload", payload, payload_len); + } + + if (type == COAP_TYPE_CON) { + type = COAP_TYPE_ACK; + } else { + type = COAP_TYPE_NON_CON; + } + + r = coap_packet_init(&response, data, sizeof(data), + COAP_VERSION_1, type, tkl, token, + COAP_RESPONSE_CODE_CHANGED, id); + if (r < 0) { + return r; + } + + r = coap_resource_send(resource, &response, addr, addr_len); + + return r; +} + +static int test_post(struct coap_resource *resource, + struct coap_packet *request, + struct sockaddr *addr, socklen_t addr_len) +{ + static const char * const location_path[] = { "location1", + "location2", + "location3", + NULL }; + uint8_t data[CONFIG_COAP_SERVER_MESSAGE_SIZE]; + const char * const *p; + struct coap_packet response; + uint8_t token[COAP_TOKEN_MAX_LEN]; + const uint8_t *payload; + uint16_t payload_len; + uint8_t code; + uint8_t type; + uint8_t tkl; + uint16_t id; + int r; + + code = coap_header_get_code(request); + type = coap_header_get_type(request); + id = coap_header_get_id(request); + tkl = coap_header_get_token(request, token); + + LOG_INF("*******"); + LOG_INF("type: %u code %u id %u", type, code, id); + LOG_INF("*******"); + + payload = coap_packet_get_payload(request, &payload_len); + if (payload) { + net_hexdump("POST Payload", payload, payload_len); + } + + if (type == COAP_TYPE_CON) { + type = COAP_TYPE_ACK; + } else { + type = COAP_TYPE_NON_CON; + } + + r = coap_packet_init(&response, data, sizeof(data), + COAP_VERSION_1, type, tkl, token, + COAP_RESPONSE_CODE_CREATED, id); + if (r < 0) { + return r; + } + + for (p = location_path; *p; p++) { + r = coap_packet_append_option(&response, + COAP_OPTION_LOCATION_PATH, + *p, strlen(*p)); + if (r < 0) { + return r; + } + } + + r = coap_resource_send(resource, &response, addr, addr_len); + + return r; +} + +static const char * const test_path[] = { "test", NULL }; +COAP_RESOURCE_DEFINE(test, coap_server, +{ + .get = piggyback_get, + .post = test_post, + .del = test_del, + .put = test_put, + .path = test_path, +}); + +static const char * const segments_path[] = { "seg1", "seg2", "seg3", NULL }; +COAP_RESOURCE_DEFINE(segments, coap_server, +{ + .get = piggyback_get, + .path = segments_path, +}); + +#if defined(CONFIG_COAP_URI_WILDCARD) + +static const char * const wildcard1_path[] = { "wild1", "+", "wild3", NULL }; +COAP_RESOURCE_DEFINE(wildcard1, coap_server, +{ + .get = piggyback_get, + .path = wildcard1_path, +}); + +static const char * const wildcard2_path[] = { "wild2", "#", NULL }; +COAP_RESOURCE_DEFINE(wildcard2, coap_server, +{ + .get = piggyback_get, + .path = wildcard2_path, +}); + +#endif diff --git a/samples/net/sockets/dumb_http_server/Makefile.posix b/samples/net/sockets/dumb_http_server/Makefile.host similarity index 100% rename from samples/net/sockets/dumb_http_server/Makefile.posix rename to samples/net/sockets/dumb_http_server/Makefile.host diff --git a/samples/net/sockets/dumb_http_server/README.rst b/samples/net/sockets/dumb_http_server/README.rst index f578d877bd1..659f94c82cd 100644 --- a/samples/net/sockets/dumb_http_server/README.rst +++ b/samples/net/sockets/dumb_http_server/README.rst @@ -1,7 +1,8 @@ -.. _sockets-dumb-http-server-sample: +.. zephyr:code-sample:: socket-dumb-http-server + :name: Dumb HTTP server + :relevant-api: bsd_sockets net_pkt -Socket Dumb HTTP Server -####################### + Implement a simple, portable, HTTP server using BSD sockets. Overview ******** @@ -63,11 +64,11 @@ The same application source code can be built for a POSIX system, e.g. Linux. (Note: if you look at the source, you will see that the code is the same except the header files are different for Zephyr vs POSIX.) -To build for a host POSIX OS: +To build: .. code-block:: console - $ make -f Makefile.posix + $ make -f Makefile.host To run: diff --git a/samples/net/sockets/dumb_http_server/prj.conf b/samples/net/sockets/dumb_http_server/prj.conf index 62dcbde44b8..1c826c38f9d 100644 --- a/samples/net/sockets/dumb_http_server/prj.conf +++ b/samples/net/sockets/dumb_http_server/prj.conf @@ -1,5 +1,5 @@ # General config -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y # Networking config CONFIG_NETWORKING=y diff --git a/samples/net/sockets/dumb_http_server/sample.yaml b/samples/net/sockets/dumb_http_server/sample.yaml index d586551bdb7..13fd552b8aa 100644 --- a/samples/net/sockets/dumb_http_server/sample.yaml +++ b/samples/net/sockets/dumb_http_server/sample.yaml @@ -2,7 +2,7 @@ sample: description: BSD Sockets API dumb HTTP server example name: socket_dumb_http_server common: - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED and not CONFIG_NATIVE_LIBC harness: net min_ram: 32 min_flash: 96 diff --git a/samples/net/sockets/dumb_http_server_mt/README.rst b/samples/net/sockets/dumb_http_server_mt/README.rst index e999f8229cf..76e55cbbc0f 100644 --- a/samples/net/sockets/dumb_http_server_mt/README.rst +++ b/samples/net/sockets/dumb_http_server_mt/README.rst @@ -1,14 +1,15 @@ -.. _sockets-dumb-http-server-mt-sample: +.. zephyr:code-sample:: socket-dumb-http-server-mt + :name: Dumb HTTP server (multi-threaded) + :relevant-api: bsd_sockets net_pkt thread_apis tls_credentials -Socket Multithreaded Dumb HTTP Server -##################################### + Implement a simple HTTP server supporting simultaneous connections using BSD sockets. Overview ******** The ``sockets/dumb_http_server_mt`` sample application for Zephyr implements a skeleton HTTP server using a BSD Sockets compatible API. -This sample has similar functionality as :ref:`sockets-dumb-http-server-sample` +This sample has similar functionality as :zephyr:code-sample:`socket-dumb-http-server` except it has support for multiple simultaneous connections, TLS and IPv6. Also this sample application has no compatibility with POSIX. This HTTP server example is very minimal and does not really parse an incoming diff --git a/samples/net/sockets/dumb_http_server_mt/src/main.c b/samples/net/sockets/dumb_http_server_mt/src/main.c index 714bbc5a67b..baa295b7f50 100644 --- a/samples/net/sockets/dumb_http_server_mt/src/main.c +++ b/samples/net/sockets/dumb_http_server_mt/src/main.c @@ -287,7 +287,7 @@ static int process_tcp(int *sock, int *accepted) &tcp6_handler_thread[slot], tcp6_handler_stack[slot], K_THREAD_STACK_SIZEOF(tcp6_handler_stack[slot]), - (k_thread_entry_t)client_conn_handler, + client_conn_handler, INT_TO_POINTER(slot), &accepted[slot], &tcp6_handler_tid[slot], @@ -302,7 +302,7 @@ static int process_tcp(int *sock, int *accepted) &tcp4_handler_thread[slot], tcp4_handler_stack[slot], K_THREAD_STACK_SIZEOF(tcp4_handler_stack[slot]), - (k_thread_entry_t)client_conn_handler, + client_conn_handler, INT_TO_POINTER(slot), &accepted[slot], &tcp4_handler_tid[slot], diff --git a/samples/net/sockets/echo/Makefile.posix b/samples/net/sockets/echo/Makefile.host similarity index 100% rename from samples/net/sockets/echo/Makefile.posix rename to samples/net/sockets/echo/Makefile.host diff --git a/samples/net/sockets/echo/README.rst b/samples/net/sockets/echo/README.rst index 0d91e0ac3e7..ca49115fd5d 100644 --- a/samples/net/sockets/echo/README.rst +++ b/samples/net/sockets/echo/README.rst @@ -1,15 +1,17 @@ -.. _sockets-echo-sample: +.. zephyr:code-sample:: sockets-echo + :name: Echo server (simple) + :relevant-api: bsd_sockets -Socket Echo Server -################## + Implements a simple IPv4/IPv6 TCP echo server using BSD sockets. Overview ******** -The sockets/echo sample application for Zephyr implements an IPv4 TCP echo -server using a BSD Sockets compatible API. The purpose of this sample is to -show how it's possible to develop a sockets application portable to both -POSIX and Zephyr. As such, it is kept minimal and supports only IPv4 and TCP. +The sockets/echo sample application for Zephyr implements a TCP echo +server supporting both IPv4 and IPv6 and using a BSD Sockets compatible API. +The purpose of this sample is to show how it's possible to develop a sockets +application portable to both POSIX and Zephyr. As such, it is kept minimal +and supports only IPv4, IPv6 and TCP. The source code for this sample application can be found at: :zephyr_file:`samples/net/sockets/echo`. @@ -50,11 +52,11 @@ The same application source code can be built for a POSIX system, e.g. Linux. (Note: if you look at the source, you will see that the code is the same except the header files are different for Zephyr vs POSIX.) -To build for a host POSIX OS: +To build: .. code-block:: console - $ make -f Makefile.posix + $ make -f Makefile.host To run: diff --git a/samples/net/sockets/echo/prj.conf b/samples/net/sockets/echo/prj.conf index 6526148e0a1..3d25caa2924 100644 --- a/samples/net/sockets/echo/prj.conf +++ b/samples/net/sockets/echo/prj.conf @@ -1,14 +1,14 @@ # General config -CONFIG_NEWLIB_LIBC=y CONFIG_MAIN_STACK_SIZE=1200 # Networking config CONFIG_NETWORKING=y CONFIG_NET_IPV4=y -CONFIG_NET_IPV6=n +CONFIG_NET_IPV6=y CONFIG_NET_TCP=y CONFIG_NET_SOCKETS=y CONFIG_NET_SOCKETS_POSIX_NAMES=y +CONFIG_NET_IPV4_MAPPING_TO_IPV6=y # Network driver config CONFIG_TEST_RANDOM_GENERATOR=y @@ -16,5 +16,8 @@ CONFIG_TEST_RANDOM_GENERATOR=y # Network address config CONFIG_NET_CONFIG_SETTINGS=y CONFIG_NET_CONFIG_NEED_IPV4=y +CONFIG_NET_CONFIG_NEED_IPV6=y CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1" CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2" +CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1" +CONFIG_NET_CONFIG_PEER_IPV6_ADDR="2001:db8::2" diff --git a/samples/net/sockets/echo/sample.yaml b/samples/net/sockets/echo/sample.yaml index 300c13a4a6f..00a8e4e56bd 100644 --- a/samples/net/sockets/echo/sample.yaml +++ b/samples/net/sockets/echo/sample.yaml @@ -4,7 +4,7 @@ sample: common: harness: net depends_on: netif - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED and not CONFIG_NATIVE_LIBC tests: sample.net.sockets.echo: tags: diff --git a/samples/net/sockets/echo/src/socket_echo.c b/samples/net/sockets/echo/src/socket_echo.c index cf4d05f5780..5ebf954ff49 100644 --- a/samples/net/sockets/echo/src/socket_echo.c +++ b/samples/net/sockets/echo/src/socket_echo.c @@ -26,20 +26,36 @@ int main(void) { - int serv; - struct sockaddr_in bind_addr; + int opt, optlen = sizeof(int); + int serv, ret; + struct sockaddr_in6 bind_addr = { + .sin6_family = AF_INET6, + .sin6_addr = IN6ADDR_ANY_INIT, + .sin6_port = htons(BIND_PORT), + }; static int counter; - serv = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - + serv = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); if (serv < 0) { printf("error: socket: %d\n", errno); exit(1); } - bind_addr.sin_family = AF_INET; - bind_addr.sin_addr.s_addr = htonl(INADDR_ANY); - bind_addr.sin_port = htons(BIND_PORT); + ret = getsockopt(serv, IPPROTO_IPV6, IPV6_V6ONLY, &opt, &optlen); + if (ret == 0) { + if (opt) { + printf("IPV6_V6ONLY option is on, turning it off.\n"); + + opt = 0; + ret = setsockopt(serv, IPPROTO_IPV6, IPV6_V6ONLY, + &opt, optlen); + if (ret < 0) { + printf("Cannot turn off IPV6_V6ONLY option\n"); + } else { + printf("Sharing same socket between IPv6 and IPv4\n"); + } + } + } if (bind(serv, (struct sockaddr *)&bind_addr, sizeof(bind_addr)) < 0) { printf("error: bind: %d\n", errno); @@ -55,7 +71,7 @@ int main(void) "port %d...\n", BIND_PORT); while (1) { - struct sockaddr_in client_addr; + struct sockaddr_in6 client_addr; socklen_t client_addr_len = sizeof(client_addr); char addr_str[32]; int client = accept(serv, (struct sockaddr *)&client_addr, @@ -66,7 +82,7 @@ int main(void) continue; } - inet_ntop(client_addr.sin_family, &client_addr.sin_addr, + inet_ntop(client_addr.sin6_family, &client_addr.sin6_addr, addr_str, sizeof(addr_str)); printf("Connection #%d from %s\n", counter++, addr_str); diff --git a/samples/net/sockets/echo_async/Makefile.posix b/samples/net/sockets/echo_async/Makefile.host similarity index 100% rename from samples/net/sockets/echo_async/Makefile.posix rename to samples/net/sockets/echo_async/Makefile.host diff --git a/samples/net/sockets/echo_async/README.rst b/samples/net/sockets/echo_async/README.rst index e17953b506c..826b3ffbda5 100644 --- a/samples/net/sockets/echo_async/README.rst +++ b/samples/net/sockets/echo_async/README.rst @@ -1,7 +1,8 @@ -.. _async-sockets-echo-sample: +.. zephyr:code-sample:: async-sockets-echo + :name: Asynchronous echo server using poll() + :relevant-api: bsd_sockets -Asynchronous Socket Echo Server -############################### + Implement an asynchronous IPv4/IPv6 TCP echo server using BSD sockets and poll() Overview ******** @@ -9,7 +10,7 @@ Overview The sockets/echo-async sample application for Zephyr implements an asynchronous IPv4/IPv6 TCP echo server using a BSD Sockets compatible API with non-blocking sockets and a ``poll()`` call. This is an extension of -the :ref:`sockets-echo-sample` sample. It's a more involved application, +the :zephyr:code-sample:`sockets-echo` sample. It's a more involved application, supporting both IPv4 and IPv6 with concurrent connections, limiting maximum number of simultaneous connections, and basic error handling. @@ -42,7 +43,7 @@ After the sample starts, it expects connections at 192.0.2.1 (IPv4), or $ telnet 2001:db8::1 4242 # or this for IPv6 After a connection is made, the application will echo back any line sent to -it. Unlike the above-mentioned :ref:`sockets-echo-sample`, this application +it. Unlike the above-mentioned :zephyr:code-sample:`sockets-echo` sample, this application supports multiple concurrent client connections. You can open another terminal window and run the same telnet command as above. The sample supports up to three connected clients, but this can be adjusted @@ -56,11 +57,11 @@ Linux. (Note: if you look at the source, you will see that the code is the same except the header files are different for Zephyr vs POSIX, and there's an additional option to set for Linux to make a socket IPv6-only). -To build for a host POSIX OS: +To build: .. code-block:: console - $ make -f Makefile.posix + $ make -f Makefile.host To run: diff --git a/samples/net/sockets/echo_async/prj.conf b/samples/net/sockets/echo_async/prj.conf index 3cfb5a6d4fc..21291009557 100644 --- a/samples/net/sockets/echo_async/prj.conf +++ b/samples/net/sockets/echo_async/prj.conf @@ -1,5 +1,5 @@ # General config -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_MAIN_STACK_SIZE=1200 # Networking config diff --git a/samples/net/sockets/echo_async/sample.yaml b/samples/net/sockets/echo_async/sample.yaml index d3097a30775..9c88a2d5ea5 100644 --- a/samples/net/sockets/echo_async/sample.yaml +++ b/samples/net/sockets/echo_async/sample.yaml @@ -2,7 +2,7 @@ sample: description: BSD Sockets API TCP echo server sample using non-blocking sockets name: socket_echo_async common: - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED and not CONFIG_NATIVE_LIBC harness: net platform_allow: qemu_x86 tags: diff --git a/samples/net/sockets/echo_async_select/Makefile.posix b/samples/net/sockets/echo_async_select/Makefile.host similarity index 100% rename from samples/net/sockets/echo_async_select/Makefile.posix rename to samples/net/sockets/echo_async_select/Makefile.host diff --git a/samples/net/sockets/echo_async_select/README.rst b/samples/net/sockets/echo_async_select/README.rst index af30527727d..963b1005928 100644 --- a/samples/net/sockets/echo_async_select/README.rst +++ b/samples/net/sockets/echo_async_select/README.rst @@ -1,7 +1,8 @@ -.. _async-sockets-echo-select-sample: +.. zephyr:code-sample:: async-sockets-echo-select + :name: Asynchronous echo server using select() + :relevant-api: bsd_sockets -Asynchronous Socket Echo Server Using select() -############################################## + Implement an asynchronous IPv4/IPv6 TCP echo server using BSD sockets and select() Overview ******** @@ -9,7 +10,7 @@ Overview The sockets/echo_async_select sample application for Zephyr implements an asynchronous IPv4/IPv6 TCP echo server using a BSD Sockets compatible API with non-blocking sockets and a ``select()`` call. This is a variant of -the :ref:`async-sockets-echo-sample` sample. +the :zephyr:code-sample:`async-sockets-echo` sample. The source code for this sample application can be found at: :zephyr_file:`samples/net/sockets/echo_async_select`. @@ -40,7 +41,7 @@ After the sample starts, it expects connections at 192.0.2.1 (IPv4), or $ telnet 2001:db8::1 4242 # or this for IPv6 After a connection is made, the application will echo back any line sent to -it. Unlike the :ref:`sockets-echo-sample`, this application +it. Unlike the :zephyr:code-sample:`sockets-echo` sample, this application supports multiple concurrent client connections. You can open another terminal window and run the same telnet command as above. The sample supports up to three connected clients, but this can be adjusted @@ -54,11 +55,11 @@ Linux. (Note: if you look at the source, you will see that the code is the same except the header files are different for Zephyr vs POSIX, and there's an additional option to set for Linux to make a socket IPv6-only). -To build for a host POSIX OS: +To build: .. code-block:: console - $ make -f Makefile.posix + $ make -f Makefile.host To run: diff --git a/samples/net/sockets/echo_async_select/prj.conf b/samples/net/sockets/echo_async_select/prj.conf index 0a6e0c049b6..377b2eef8af 100644 --- a/samples/net/sockets/echo_async_select/prj.conf +++ b/samples/net/sockets/echo_async_select/prj.conf @@ -1,5 +1,5 @@ # General config -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_MAIN_STACK_SIZE=1200 CONFIG_POSIX_API=y diff --git a/samples/net/sockets/echo_async_select/sample.yaml b/samples/net/sockets/echo_async_select/sample.yaml index b052c0d1c9d..3353773ec0b 100644 --- a/samples/net/sockets/echo_async_select/sample.yaml +++ b/samples/net/sockets/echo_async_select/sample.yaml @@ -7,7 +7,7 @@ common: tags: - net - socket - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED and not CONFIG_NATIVE_LIBC tests: sample.net.sockets.echo_async_select: extra_configs: diff --git a/samples/net/sockets/echo_client/README.rst b/samples/net/sockets/echo_client/README.rst index 31d03d18202..ce9ccf2532b 100644 --- a/samples/net/sockets/echo_client/README.rst +++ b/samples/net/sockets/echo_client/README.rst @@ -1,7 +1,8 @@ -.. _sockets-echo-client-sample: +.. zephyr:code-sample:: sockets-echo-client + :name: Echo client (advanced) + :relevant-api: bsd_sockets tls_credentials -Socket Echo Client -################## + Implement a client that sends IP packets, waits for data to be sent back, and verifies it. Overview ******** @@ -105,7 +106,7 @@ running ``west build`` or ``cmake``. The certificate and private key used by the sample can be found in the sample's ``src`` directory. The default certificates used by Socket Echo Client and -:ref:`sockets-echo-server-sample` enable establishing a secure connection +:zephyr:code-sample:`sockets-echo-server` enable establishing a secure connection between the samples. SOCKS5 proxy support @@ -178,6 +179,6 @@ You can verify TLS communication with a Linux host as well. See https://github.com/zephyrproject-rtos/net-tools documentation for information on how to test TLS with Linux host samples. -See the :ref:`sockets-echo-server-sample` documentation for an alternate +See the :zephyr:code-sample:`sockets-echo-server` documentation for an alternate way of running, with the echo-client on the Linux host and the echo-server in QEMU. diff --git a/samples/net/sockets/echo_client/overlay-ot.conf b/samples/net/sockets/echo_client/overlay-ot.conf index 58c70682478..0eb39c24d43 100644 --- a/samples/net/sockets/echo_client/overlay-ot.conf +++ b/samples/net/sockets/echo_client/overlay-ot.conf @@ -1,4 +1,4 @@ -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y # Disable TCP and IPv4 (TCP disabled to avoid heavy traffic) CONFIG_NET_TCP=n diff --git a/samples/net/sockets/echo_client/sample.yaml b/samples/net/sockets/echo_client/sample.yaml index bbc7d3c10e1..7c37257e420 100644 --- a/samples/net/sockets/echo_client/sample.yaml +++ b/samples/net/sockets/echo_client/sample.yaml @@ -81,7 +81,7 @@ tests: - net - openthread platform_allow: nrf52840dk_nrf52840 - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED and not CONFIG_NATIVE_LIBC sample.net.sockets.echo_client.b91_802154: extra_args: OVERLAY_CONFIG="overlay-802154.conf" platform_allow: tlsr9518adk80d @@ -92,7 +92,7 @@ tests: - net - openthread platform_allow: tlsr9518adk80d - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED and not CONFIG_NATIVE_LIBC sample.net.sockets.echo_client.kw41z_openthread: extra_args: OVERLAY_CONFIG="overlay-ot.conf" slow: true @@ -100,7 +100,7 @@ tests: - net - openthread platform_allow: frdm_kw41z - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED and not CONFIG_NATIVE_LIBC sample.net.sockets.echo_client.userspace: extra_args: - CONFIG_USERSPACE=y diff --git a/samples/net/sockets/echo_client/src/echo-client.c b/samples/net/sockets/echo_client/src/echo-client.c index 3738c758b15..3e4aff0f2d0 100644 --- a/samples/net/sockets/echo_client/src/echo-client.c +++ b/samples/net/sockets/echo_client/src/echo-client.c @@ -279,8 +279,12 @@ static void init_app(void) init_udp(); } -static int start_client(void) +static void start_client(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + int iterations = CONFIG_NET_SAMPLE_SEND_ITERATIONS; int i = 0; int ret; @@ -305,8 +309,6 @@ static int start_client(void) stop_udp_and_tcp(); } - - return ret; } int main(void) @@ -318,6 +320,7 @@ int main(void) * app only after we have a connection, then we can start * it right away. */ + connected = true; k_sem_give(&run_app); } @@ -327,10 +330,9 @@ int main(void) k_thread_access_grant(k_current_get(), &run_app); k_mem_domain_add_thread(&app_domain, k_current_get()); - k_thread_user_mode_enter((k_thread_entry_t)start_client, NULL, NULL, - NULL); + k_thread_user_mode_enter(start_client, NULL, NULL, NULL); #else - exit(start_client()); + start_client(NULL, NULL, NULL); #endif return 0; } diff --git a/samples/net/sockets/echo_client/src/tcp.c b/samples/net/sockets/echo_client/src/tcp.c index 5ff80eb25ad..5833d399088 100644 --- a/samples/net/sockets/echo_client/src/tcp.c +++ b/samples/net/sockets/echo_client/src/tcp.c @@ -16,7 +16,7 @@ LOG_MODULE_DECLARE(net_echo_client_sample, LOG_LEVEL_DBG); #include #include -#include +#include #include "common.h" #include "ca_certificate.h" diff --git a/samples/net/sockets/echo_client/src/udp.c b/samples/net/sockets/echo_client/src/udp.c index 6b52615ff28..e5b7ea1dae0 100644 --- a/samples/net/sockets/echo_client/src/udp.c +++ b/samples/net/sockets/echo_client/src/udp.c @@ -16,7 +16,7 @@ LOG_MODULE_DECLARE(net_echo_client_sample, LOG_LEVEL_DBG); #include #include -#include +#include #include "common.h" #include "ca_certificate.h" @@ -40,8 +40,12 @@ static int send_udp_data(struct data *data); static void wait_reply(struct k_timer *timer); static void wait_transmit(struct k_timer *timer); -static void process_udp_tx(void) +static void process_udp_tx(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct k_poll_event events[] = { K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, @@ -317,7 +321,7 @@ int start_udp(void) k_thread_create(&udp_tx_thread, udp_tx_thread_stack, K_THREAD_STACK_SIZEOF(udp_tx_thread_stack), - (k_thread_entry_t)process_udp_tx, + process_udp_tx, NULL, NULL, NULL, THREAD_PRIORITY, IS_ENABLED(CONFIG_USERSPACE) ? K_USER | K_INHERIT_PERMS : 0, diff --git a/samples/net/sockets/echo_server/README.rst b/samples/net/sockets/echo_server/README.rst index fed7ef00a41..20ce37e7991 100644 --- a/samples/net/sockets/echo_server/README.rst +++ b/samples/net/sockets/echo_server/README.rst @@ -1,7 +1,8 @@ -.. _sockets-echo-server-sample: +.. zephyr:code-sample:: sockets-echo-server + :name: Echo server (advanced) + :relevant-api: bsd_sockets tls_credentials -Socket Echo Server -################## + Implement a UDP/TCP server that sends received packets back to the sender. Overview ******** @@ -107,7 +108,7 @@ running ``west build`` or ``cmake``. The certificate used by the sample can be found in the sample's ``src`` directory. The default certificates used by Socket Echo Server and -:ref:`sockets-echo-client-sample` enable establishing a secure connection +:zephyr:code-sample:`sockets-echo-client` enable establishing a secure connection between the samples. Running echo-client in Linux Host @@ -140,6 +141,6 @@ You can verify TLS communication with a Linux host as well. See https://github.com/zephyrproject-rtos/net-tools documentation for information on how to test TLS with Linux host samples. -See the :ref:`sockets-echo-client-sample` documentation for an alternate +See the :zephyr:code-sample:`sockets-echo-client` sample documentation for an alternate way of running, with the echo-server on the Linux host and the echo-client in QEMU. diff --git a/samples/net/sockets/echo_server/overlay-ot.conf b/samples/net/sockets/echo_server/overlay-ot.conf index 2158020d621..5d4563fdfa1 100644 --- a/samples/net/sockets/echo_server/overlay-ot.conf +++ b/samples/net/sockets/echo_server/overlay-ot.conf @@ -1,4 +1,4 @@ -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y # Disable TCP and IPv4 (TCP disabled to avoid heavy traffic) CONFIG_NET_TCP=n diff --git a/samples/net/sockets/echo_server/sample.yaml b/samples/net/sockets/echo_server/sample.yaml index 10255905402..1174797d04a 100644 --- a/samples/net/sockets/echo_server/sample.yaml +++ b/samples/net/sockets/echo_server/sample.yaml @@ -92,7 +92,7 @@ tests: - net - openthread platform_allow: nrf52840dk_nrf52840 - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED and not CONFIG_NATIVE_LIBC sample.net.sockets.echo_server.b91_openthread: extra_args: OVERLAY_CONFIG="overlay-ot.conf" slow: true @@ -100,7 +100,7 @@ tests: - net - openthread platform_allow: tlsr9518adk80d - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED and not CONFIG_NATIVE_LIBC sample.net.sockets.echo_server.kw41z_openthread: extra_args: OVERLAY_CONFIG="overlay-ot.conf" slow: true @@ -108,7 +108,7 @@ tests: - net - openthread platform_allow: frdm_kw41z - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED and not CONFIG_NATIVE_LIBC sample.net.sockets.echo_server.e1000: extra_args: OVERLAY_CONFIG="overlay-e1000.conf" tags: net diff --git a/samples/net/sockets/echo_server/src/tcp.c b/samples/net/sockets/echo_server/src/tcp.c index ffc6d69bc36..1a6555d43c3 100644 --- a/samples/net/sockets/echo_server/src/tcp.c +++ b/samples/net/sockets/echo_server/src/tcp.c @@ -243,7 +243,7 @@ static int process_tcp(struct data *data) &tcp6_handler_thread[slot], tcp6_handler_stack[slot], K_THREAD_STACK_SIZEOF(tcp6_handler_stack[slot]), - (k_thread_entry_t)handle_data, + handle_data, INT_TO_POINTER(slot), data, &tcp6_handler_in_use[slot], THREAD_PRIORITY, IS_ENABLED(CONFIG_USERSPACE) ? K_USER | @@ -267,7 +267,7 @@ static int process_tcp(struct data *data) &tcp4_handler_thread[slot], tcp4_handler_stack[slot], K_THREAD_STACK_SIZEOF(tcp4_handler_stack[slot]), - (k_thread_entry_t)handle_data, + handle_data, INT_TO_POINTER(slot), data, &tcp4_handler_in_use[slot], THREAD_PRIORITY, IS_ENABLED(CONFIG_USERSPACE) ? K_USER | diff --git a/samples/net/sockets/echo_server/src/tunnel.c b/samples/net/sockets/echo_server/src/tunnel.c index 91d1aa7108d..77c85a7cd93 100644 --- a/samples/net/sockets/echo_server/src/tunnel.c +++ b/samples/net/sockets/echo_server/src/tunnel.c @@ -11,6 +11,7 @@ LOG_MODULE_DECLARE(net_echo_server_sample, LOG_LEVEL_DBG); #include #include +#include /* User data for the interface callback */ struct ud { diff --git a/samples/net/sockets/http_client/README.rst b/samples/net/sockets/http_client/README.rst index 1d37121ad56..855c36d068a 100644 --- a/samples/net/sockets/http_client/README.rst +++ b/samples/net/sockets/http_client/README.rst @@ -1,7 +1,8 @@ -.. _sockets-http-client-sample: +.. zephyr:code-sample:: sockets-http-client + :name: HTTP client + :relevant-api: bsd_sockets http_client tls_credentials secure_sockets_options -Socket HTTP Client -################## + Implement an HTTP(S) client that issues a variety of HTTP requests. Overview ******** diff --git a/samples/net/sockets/http_get/Makefile.posix b/samples/net/sockets/http_get/Makefile.host similarity index 100% rename from samples/net/sockets/http_get/Makefile.posix rename to samples/net/sockets/http_get/Makefile.host diff --git a/samples/net/sockets/http_get/README.rst b/samples/net/sockets/http_get/README.rst index bd4a6824d7f..09bfb2050d1 100644 --- a/samples/net/sockets/http_get/README.rst +++ b/samples/net/sockets/http_get/README.rst @@ -1,7 +1,8 @@ -.. _sockets-http-get: +.. zephyr:code-sample:: sockets-http-get + :name: HTTP GET using plain sockets + :relevant-api: bsd_sockets tls_credentials secure_sockets_options -Socket HTTP GET Example -####################### + Implement an HTTP(S) client using plain BSD sockets. Overview ******** @@ -75,11 +76,11 @@ The same application source code can be built for a POSIX system, e.g. Linux. (Note: if you look at the source, you will see that the code is the same except the header files are different for Zephyr vs POSIX.) -To build for a host POSIX OS: +To build: .. code-block:: console - $ make -f Makefile.posix + $ make -f Makefile.host To run: diff --git a/samples/net/sockets/http_get/prj.conf b/samples/net/sockets/http_get/prj.conf index 64bb4bc52f8..57d4d4c55c0 100644 --- a/samples/net/sockets/http_get/prj.conf +++ b/samples/net/sockets/http_get/prj.conf @@ -1,6 +1,6 @@ # General config CONFIG_MAIN_STACK_SIZE=1536 -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y # Networking config CONFIG_NETWORKING=y diff --git a/samples/net/sockets/http_get/sample.yaml b/samples/net/sockets/http_get/sample.yaml index f8fb27104c3..999c7ba97d6 100644 --- a/samples/net/sockets/http_get/sample.yaml +++ b/samples/net/sockets/http_get/sample.yaml @@ -2,7 +2,7 @@ sample: description: BSD Sockets API HTTP GET example name: socket_http_get common: - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED and not CONFIG_NATIVE_LIBC harness: net min_ram: 32 min_flash: 80 diff --git a/samples/net/sockets/net_mgmt/README.rst b/samples/net/sockets/net_mgmt/README.rst index 4fade75c725..c59b8170e31 100644 --- a/samples/net/sockets/net_mgmt/README.rst +++ b/samples/net/sockets/net_mgmt/README.rst @@ -1,7 +1,8 @@ -.. _sockets-net-mgmt-sample: +.. zephyr:code-sample:: sockets-net-mgmt + :name: Network management socket + :relevant-api: bsd_sockets net_if -Network Management Socket -######################### + Listen to network management events using a network management socket. Overview ******** @@ -33,12 +34,12 @@ Build net-mgmt socket sample application like this: :goals: build :compact: -Example building for the native_posix board: +Example building for the native_sim board: .. zephyr-app-commands:: :zephyr-app: samples/net/sockets/net_mgmt :host-os: unix - :board: native_posix + :board: native_sim :conf: prj.conf :goals: run :compact: diff --git a/samples/net/sockets/net_mgmt/src/main.c b/samples/net/sockets/net_mgmt/src/main.c index 2e6813b54cd..877e5e41d5c 100644 --- a/samples/net/sockets/net_mgmt/src/main.c +++ b/samples/net/sockets/net_mgmt/src/main.c @@ -82,8 +82,12 @@ static char *get_ip_addr(char *ipaddr, size_t len, sa_family_t family, return buf; } -static void listener(void) +static void listener(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct sockaddr_nm sockaddr; struct sockaddr_nm event_addr; socklen_t event_addr_len; @@ -163,10 +167,10 @@ int main(void) k_thread_start(trigger_events_thread_id); if (IS_ENABLED(CONFIG_USERSPACE)) { - k_thread_user_mode_enter((k_thread_entry_t)listener, + k_thread_user_mode_enter(listener, NULL, NULL, NULL); } else { - listener(); + listener(NULL, NULL, NULL); } return 0; } diff --git a/samples/net/sockets/packet/README.rst b/samples/net/sockets/packet/README.rst index fe6ce34c7cd..b9429215061 100644 --- a/samples/net/sockets/packet/README.rst +++ b/samples/net/sockets/packet/README.rst @@ -1,7 +1,8 @@ -.. _packet-socket-sample: +.. zephyr:code-sample:: packet-socket + :name: Packet socket + :relevant-api: bsd_sockets ethernet -Packet socket sample -#################### + Use raw packet sockets over Ethernet. Overview ******** @@ -22,7 +23,7 @@ sent and received packets. See the `net-tools`_ project for more details. -This sample can be built and executed on QEMU or native_posix board as +This sample can be built and executed on QEMU or native_sim board as described in :ref:`networking_with_host`. .. _`net-tools`: https://github.com/zephyrproject-rtos/net-tools diff --git a/samples/net/sockets/packet/sample.yaml b/samples/net/sockets/packet/sample.yaml index 66deae9f335..d02c03c7d68 100644 --- a/samples/net/sockets/packet/sample.yaml +++ b/samples/net/sockets/packet/sample.yaml @@ -7,8 +7,10 @@ tests: platform_allow: - native_posix - native_posix_64 + - native_sim + - native_sim_64 integration_platforms: - - native_posix + - native_sim tags: - net - sockets diff --git a/samples/net/sockets/sntp_client/README.rst b/samples/net/sockets/sntp_client/README.rst index 9515ca3158c..f9a1aacd4b8 100644 --- a/samples/net/sockets/sntp_client/README.rst +++ b/samples/net/sockets/sntp_client/README.rst @@ -1,7 +1,8 @@ -.. _sntp-client-sample: +.. zephyr:code-sample:: sntp-client + :name: SNTP client + :relevant-api: bsd_sockets sntp -SNTP client sample -################## + Use SNTP to get the current time from the host. Overview ******** @@ -23,7 +24,7 @@ printed. See the `net-tools`_ project for more details. -This sample can be built and executed on QEMU or native_posix board as +This sample can be built and executed on QEMU or native_sim board as described in :ref:`networking_with_qemu`. .. _`net-tools`: https://github.com/zephyrproject-rtos/net-tools diff --git a/samples/net/sockets/sntp_client/prj.conf b/samples/net/sockets/sntp_client/prj.conf index d641240c25e..bfcd3092ac6 100644 --- a/samples/net/sockets/sntp_client/prj.conf +++ b/samples/net/sockets/sntp_client/prj.conf @@ -1,5 +1,5 @@ # General config -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y # Networking config CONFIG_NETWORKING=y diff --git a/samples/net/sockets/sntp_client/sample.yaml b/samples/net/sockets/sntp_client/sample.yaml index 3a87d5995e2..65d4f2f3b2c 100644 --- a/samples/net/sockets/sntp_client/sample.yaml +++ b/samples/net/sockets/sntp_client/sample.yaml @@ -6,13 +6,19 @@ common: tags: net tests: sample.net.sockets.sntp_client: - platform_allow: qemu_x86 + platform_allow: + - qemu_x86 + - native_sim sample.net.sockets.sntp_client.posix_names: - platform_allow: qemu_x86 + platform_allow: + - qemu_x86 + - native_sim extra_configs: - CONFIG_NET_SOCKETS_POSIX_NAMES=y sample.net.sockets.sntp_client.posix: - platform_allow: qemu_x86 + platform_allow: + - qemu_x86 + - native_sim extra_configs: - CONFIG_NET_SOCKETS_POSIX_NAMES=n - CONFIG_POSIX_API=y diff --git a/samples/net/sockets/socketpair/Makefile.posix b/samples/net/sockets/socketpair/Makefile.host similarity index 100% rename from samples/net/sockets/socketpair/Makefile.posix rename to samples/net/sockets/socketpair/Makefile.host diff --git a/samples/net/sockets/socketpair/README.rst b/samples/net/sockets/socketpair/README.rst index 7372d1293f0..948a2b2d8bf 100644 --- a/samples/net/sockets/socketpair/README.rst +++ b/samples/net/sockets/socketpair/README.rst @@ -1,7 +1,8 @@ -.. _sockets-socketpair-sample: +.. zephyr:code-sample:: sockets-socketpair + :name: Socketpair + :relevant-api: bsd_sockets -Socketpair Example -################## + Implement communication between threads using socket pairs. Overview ******** @@ -61,11 +62,11 @@ Running application on POSIX Host The same application source code can be built for a POSIX system, e.g. Linux. -To build for a host POSIX OS: +To build: .. code-block:: console - $ make -f Makefile.posix + $ make -f Makefile.host To run: diff --git a/samples/net/sockets/socketpair/sample.yaml b/samples/net/sockets/socketpair/sample.yaml index 2366392ed99..605668336d8 100644 --- a/samples/net/sockets/socketpair/sample.yaml +++ b/samples/net/sockets/socketpair/sample.yaml @@ -9,6 +9,6 @@ common: harness: net arch_exclude: posix integration_platforms: - - mps2_an385 + - qemu_x86 tests: sample.net.sockets.socketpair: {} diff --git a/samples/net/sockets/tcp/README.rst b/samples/net/sockets/tcp/README.rst index 5f43d02d41f..c0540cca147 100644 --- a/samples/net/sockets/tcp/README.rst +++ b/samples/net/sockets/tcp/README.rst @@ -1,7 +1,8 @@ -.. _sockets-tcp-sample: +.. zephyr:code-sample:: sockets-tcp-sample + :name: TCP sample for TTCN-3 based sanity check + :relevant-api: bsd_sockets -TCP Sample for TTCN-3 based Sanity Check -######################################## + Use TTCN-3 to validate the functionality of the TCP stack. Overview ******** diff --git a/samples/net/sockets/tcp/prj.conf b/samples/net/sockets/tcp/prj.conf index be1af897fe2..a442918f337 100644 --- a/samples/net/sockets/tcp/prj.conf +++ b/samples/net/sockets/tcp/prj.conf @@ -1,4 +1,4 @@ -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_NETWORKING=y diff --git a/samples/net/sockets/tcp/sample.yaml b/samples/net/sockets/tcp/sample.yaml index b636044bca3..895e519a360 100644 --- a/samples/net/sockets/tcp/sample.yaml +++ b/samples/net/sockets/tcp/sample.yaml @@ -3,7 +3,7 @@ sample: name: tcp tests: sample.net.socket.tcp: - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED and not CONFIG_NATIVE_LIBC harness: net platform_allow: qemu_x86 tags: diff --git a/samples/net/sockets/txtime/README.rst b/samples/net/sockets/txtime/README.rst index 67909d609c8..46979ce68bb 100644 --- a/samples/net/sockets/txtime/README.rst +++ b/samples/net/sockets/txtime/README.rst @@ -1,7 +1,8 @@ -.. _so_txtime-sample: +.. zephyr:code-sample:: so_txtime + :name: UDP sender using SO_TXTIME + :relevant-api: bsd_sockets ethernet -SO_TXTIME sample -################ + Control the transmission time of a packet using SO_TXTIME socket option. Overview ******** @@ -14,9 +15,9 @@ provided for qemu_x86 board. Also frdm_k64f and sam_e70_xplained boards are supported. Other mcux or gmac Ethernet driver based boards should work too. User can control how long the application should wait between packets sent by -setting CONFIG_NET_SAMPLE_PACKET_INTERVAL option. +setting :kconfig:option:`CONFIG_NET_SAMPLE_PACKET_INTERVAL` option. Also the TXTIME value can be specified in the config file by setting the -CONFIG_NET_SAMPLE_PACKET_TXTIME option. In this case the value is +:kconfig:option:`CONFIG_NET_SAMPLE_PACKET_TXTIME` option. In this case the value is used as an offset from the current time. Building and Running @@ -25,8 +26,8 @@ Building and Running When the application is run, it starts to send UDP packets. You can start ``echo-server`` application from `net-tools`_ project to catch these and send the data back to this application. Optionally you can set -CONFIG_NET_SAMPLE_PACKET_SOCKET option, which makes the application -to create an AF_PACKET type socket. In this case, the ``echo-server`` +:kconfig:option:`CONFIG_NET_SAMPLE_PACKET_SOCKET` option, which makes the application +to create an ``AF_PACKET`` type socket. In this case, the ``echo-server`` application cannot be used as a peer. This sample can be built and executed on qemu_x86 board as diff --git a/samples/net/sockets/txtime/sample.yaml b/samples/net/sockets/txtime/sample.yaml index 98488b70e94..189f6901bfc 100644 --- a/samples/net/sockets/txtime/sample.yaml +++ b/samples/net/sockets/txtime/sample.yaml @@ -5,10 +5,12 @@ common: platform_allow: - native_posix - native_posix_64 + - native_sim + - native_sim_64 - qemu_x86 - qemu_x86_64 integration_platforms: - - native_posix + - native_sim sample: description: Socket SO_TXTIME sample name: txtime-socket diff --git a/samples/net/sockets/txtime/src/main.c b/samples/net/sockets/txtime/src/main.c index a4a63732398..481312d1afe 100644 --- a/samples/net/sockets/txtime/src/main.c +++ b/samples/net/sockets/txtime/src/main.c @@ -127,8 +127,12 @@ static void event_handler(struct net_mgmt_event_callback *cb, } } -static void rx(struct app_data *data) +static void rx(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct app_data *data = p1; static uint8_t recv_buf[sizeof(txtime_str)]; struct sockaddr src; socklen_t addr_len = data->peer_addr_len; @@ -143,8 +147,12 @@ static void rx(struct app_data *data) } } -static void tx(struct app_data *data) +static void tx(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct app_data *data = p1; struct net_ptp_time time; struct msghdr msg; struct cmsghdr *cmsg; @@ -620,7 +628,7 @@ int main(void) tx_tid = k_thread_create(&tx_thread, tx_stack, K_THREAD_STACK_SIZEOF(tx_stack), - (k_thread_entry_t)tx, &peer_data, + tx, &peer_data, NULL, NULL, THREAD_PRIORITY, 0, K_FOREVER); if (!tx_tid) { @@ -632,7 +640,7 @@ int main(void) rx_tid = k_thread_create(&rx_thread, rx_stack, K_THREAD_STACK_SIZEOF(rx_stack), - (k_thread_entry_t)rx, &peer_data, + rx, &peer_data, NULL, NULL, THREAD_PRIORITY, 0, K_FOREVER); if (!rx_tid) { diff --git a/samples/net/sockets/websocket_client/README.rst b/samples/net/sockets/websocket_client/README.rst index d6ae83b568f..b8cf079683f 100644 --- a/samples/net/sockets/websocket_client/README.rst +++ b/samples/net/sockets/websocket_client/README.rst @@ -1,7 +1,8 @@ -.. _sockets-websocket-client-sample: +.. zephyr:code-sample:: sockets-websocket-client + :name: WebSocket Client + :relevant-api: bsd_sockets websocket -Socket Websocket Client -####################### + Implement a Websocket client that connects to a Websocket server. Overview ******** diff --git a/samples/net/sockets/websocket_client/src/main.c b/samples/net/sockets/websocket_client/src/main.c index f58e6d47b41..1b55b6b62ea 100644 --- a/samples/net/sockets/websocket_client/src/main.c +++ b/samples/net/sockets/websocket_client/src/main.c @@ -11,7 +11,7 @@ LOG_MODULE_REGISTER(net_websocket_client_sample, LOG_LEVEL_DBG); #include #include #include -#include +#include #include #include "ca_certificate.h" diff --git a/samples/net/stats/README.rst b/samples/net/stats/README.rst index e7d4ac6d911..b8a2016c83f 100644 --- a/samples/net/stats/README.rst +++ b/samples/net/stats/README.rst @@ -1,7 +1,8 @@ -.. _net_stats-sample: +.. zephyr:code-sample:: net-stats + :name: Network statistics + :relevant-api: net_stats -Network Statistics Sample Application -##################################### + Query and display network statistics from a user application. Overview ******** @@ -20,7 +21,7 @@ Requirements Building and Running ******************** -A good way to run this sample application is with QEMU or native_posix board +A good way to run this sample application is with QEMU or native_sim board as described in :ref:`networking_with_host`. Follow these steps to build the network statistics sample application: diff --git a/samples/net/syslog_net/Kconfig b/samples/net/syslog_net/Kconfig index f7d18e9391c..e355e5683ec 100644 --- a/samples/net/syslog_net/Kconfig +++ b/samples/net/syslog_net/Kconfig @@ -12,4 +12,20 @@ config NET_SAMPLE_SEND_ITERATIONS Send sample data this many times before exiting. A value of zero means that the defaults in the application are used. + +config NET_SAMPLE_SERVER_RUNTIME + string "Syslog server IP address set at runtime" + help + Server address for the syslog server. + This server address gets set at rumtime by the sample + app defore the backend is initialized. This can be + either IPv4 or IPv6 address. Server listen UDP port + number can be configured here too. + Following syntax is supported: + 192.0.2.1:514 + 192.0.2.42 + [2001:db8::1]:514 + [2001:db8::2] + 2001:db::42 + source "Kconfig.zephyr" diff --git a/samples/net/syslog_net/README.rst b/samples/net/syslog_net/README.rst index 04440b34f77..6e4247a5828 100644 --- a/samples/net/syslog_net/README.rst +++ b/samples/net/syslog_net/README.rst @@ -1,7 +1,8 @@ -.. _syslog-net-sample: +.. zephyr:code-sample:: syslog-net + :name: Remote syslog + :relevant-api: log_backend log_ctrl -Syslog net Application -###################### + Enable a remote syslog service that sends syslog messages to a remote server Overview ******** diff --git a/samples/net/syslog_net/overlay-runtime-srv-addr.conf b/samples/net/syslog_net/overlay-runtime-srv-addr.conf new file mode 100644 index 00000000000..55bc234183f --- /dev/null +++ b/samples/net/syslog_net/overlay-runtime-srv-addr.conf @@ -0,0 +1,3 @@ +CONFIG_LOG_BACKEND_NET_SERVER="" +CONFIG_LOG_BACKEND_NET_AUTOSTART=n +CONFIG_NET_SAMPLE_SERVER_RUNTIME="192.0.2.2:514" diff --git a/samples/net/syslog_net/prj.conf b/samples/net/syslog_net/prj.conf index d4fb024b448..b0ae6043cef 100644 --- a/samples/net/syslog_net/prj.conf +++ b/samples/net/syslog_net/prj.conf @@ -37,4 +37,4 @@ CONFIG_LOG_BACKEND_NET=y CONFIG_LOG_BACKEND_NET_SERVER="[2001:db8::2]:514" # Get newlib by default as it has proper time function support -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y diff --git a/samples/net/syslog_net/sample.yaml b/samples/net/syslog_net/sample.yaml index 6eb8440e2c6..4fe99e593ff 100644 --- a/samples/net/syslog_net/sample.yaml +++ b/samples/net/syslog_net/sample.yaml @@ -9,11 +9,11 @@ sample: name: syslog_net tests: sample.net.syslog.with_timefuncs: - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED extra_configs: - - CONFIG_NEWLIB_LIBC=y + - CONFIG_REQUIRES_FULL_LIBC=y sample.net.syslog.ipv4_only: - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED extra_configs: - CONFIG_NET_IPV6=n - CONFIG_NET_CONFIG_NEED_IPV6=n @@ -21,13 +21,19 @@ tests: - CONFIG_NET_CONFIG_PEER_IPV6_ADDR="" - CONFIG_LOG_BACKEND_NET_SERVER="192.0.2.1:514" sample.net.syslog.ipv6_only: - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED extra_configs: - CONFIG_NET_IPV4=n - CONFIG_NET_CONFIG_NEED_IPV4=n - CONFIG_NET_CONFIG_MY_IPV4_ADDR="" - CONFIG_NET_CONFIG_PEER_IPV4_ADDR="" sample.net.syslog.no_autostart: - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED extra_configs: - CONFIG_LOG_BACKEND_NET_AUTOSTART=n + sample.net.syslog.runtime_srv_addr: + filter: CONFIG_FULL_LIBC_SUPPORTED + extra_configs: + - CONFIG_LOG_BACKEND_NET_AUTOSTART=n + - CONFIG_LOG_BACKEND_NET_SERVER="" + - CONFIG_NET_SAMPLE_SERVER_RUNTIME="192.0.2.2:514" diff --git a/samples/net/syslog_net/src/main.c b/samples/net/syslog_net/src/main.c index 50bf55668b2..b842e0ec03b 100644 --- a/samples/net/syslog_net/src/main.c +++ b/samples/net/syslog_net/src/main.c @@ -10,6 +10,7 @@ LOG_MODULE_REGISTER(net_syslog, LOG_LEVEL_DBG); #include #include +#include #include #include @@ -36,6 +37,16 @@ int main(void) const struct log_backend *backend = log_backend_net_get(); if (!log_backend_is_active(backend)) { + + /* Specifying an address by calling this function will + * override the value given to LOG_BACKEND_NET_SERVER. + It can also be called at any other time after the backend + is started. The net context will be released and + restarted with the newly specified address. + */ + if (strlen(CONFIG_LOG_BACKEND_NET_SERVER) == 0) { + log_backend_net_set_addr(CONFIG_NET_SAMPLE_SERVER_RUNTIME); + } log_backend_init(backend); log_backend_enable(backend, backend->cb->ctx, CONFIG_LOG_MAX_LEVEL); } diff --git a/samples/net/telnet/README.rst b/samples/net/telnet/README.rst index ee77c9b1402..1c648e2e970 100644 --- a/samples/net/telnet/README.rst +++ b/samples/net/telnet/README.rst @@ -1,7 +1,8 @@ -.. _telnet-console-sample: +.. zephyr:code-sample:: telnet-console + :name: Telnet console + :relevant-api: shell_api net_core net_if net_mgmt -Sample TELNET console application -################################# + Access Zephyr shell over telnet. Overview ******** diff --git a/samples/net/tftp_client/README.rst b/samples/net/tftp_client/README.rst index ac7181f4605..a6c684da5b0 100644 --- a/samples/net/tftp_client/README.rst +++ b/samples/net/tftp_client/README.rst @@ -1,7 +1,8 @@ -.. _tftp-client-sample: +.. zephyr:code-sample:: tftp-client + :name: TFTP client + :relevant-api: tftp_client -TFTP client -############ + Use the TFTP client library to get/put files from/to a TFTP server. Overview ******** @@ -18,7 +19,7 @@ The source code for this sample application can be found at: Requirements ************ -- :ref:`networking_with_eth_qemu`, :ref:`networking_with_qemu` or :ref:`networking_with_native_posix` +- :ref:`networking_with_eth_qemu`, :ref:`networking_with_qemu` or :ref:`networking_with_native_sim` - Linux machine Building and Running @@ -40,15 +41,15 @@ Build the tftp-client sample application like this: :compact: The easiest way to setup this sample application is to build and run it -as native POSIX application or as a QEMU target using the default configuration :file:`prj.conf`. -This requires a small amount of setup described in :ref:`networking_with_eth_qemu`, :ref:`networking_with_qemu` and :ref:`networking_with_native_posix`. +as a native_sim application or as a QEMU target using the default configuration :file:`prj.conf`. +This requires a small amount of setup described in :ref:`networking_with_eth_qemu`, :ref:`networking_with_qemu` and :ref:`networking_with_native_sim`. -Build the tftp-client sample application for native_posix like this: +Build the tftp-client sample application for :ref:`native_sim ` like this: .. zephyr-app-commands:: :zephyr-app: samples/net/tftp_client :host-os: unix - :board: native_posix + :board: native_sim :goals: run :compact: @@ -69,7 +70,7 @@ configurations in ``prj.conf``:: Sample output ================================== -Sample run on native_posix platform with TFTP server on host machine +Sample run on native_sim platform with TFTP server on host machine Launch net-setup.sh in net-tools .. code-block:: console diff --git a/samples/net/tftp_client/boards/native_sim.conf b/samples/net/tftp_client/boards/native_sim.conf new file mode 100644 index 00000000000..1e9e27b074e --- /dev/null +++ b/samples/net/tftp_client/boards/native_sim.conf @@ -0,0 +1,3 @@ +CONFIG_DNS_RESOLVER=y +CONFIG_DNS_SERVER_IP_ADDRESSES=y +CONFIG_DNS_SERVER1="192.0.2.2" diff --git a/samples/net/tftp_client/sample.yaml b/samples/net/tftp_client/sample.yaml index baabc4790b4..3ccedecafe9 100644 --- a/samples/net/tftp_client/sample.yaml +++ b/samples/net/tftp_client/sample.yaml @@ -7,8 +7,9 @@ tests: depends_on: netif platform_allow: - native_posix + - native_sim integration_platforms: - - native_posix + - native_sim tags: - net - tftp diff --git a/samples/net/virtual/README.rst b/samples/net/virtual/README.rst index 6869d21e1a4..8b83fc9e0e7 100644 --- a/samples/net/virtual/README.rst +++ b/samples/net/virtual/README.rst @@ -1,7 +1,8 @@ -.. _virtual_network_interface-sample: +.. zephyr:code-sample:: virtual-network-interface + :name: Virtual network interface + :relevant-api: virtual virtual_mgmt -Virtual Network Interface Application -##################################### + Create a sample virtual network interface. Overview ******** @@ -9,11 +10,14 @@ Overview This sample application creates a sample virtual network interface for demonstrative purposes, it does not do anything useful here. There are total 4 network interfaces. + Ethernet network interface is providing the real network interface and all the virtual interfaces are running on top of it. + On top of Ethernet interface there are two virtual network interfaces, one provides only IPv6 tunnel, and the other only IPv4. These two tunnels are provided by IPIP tunnel. + The sample provides tunnel interface which runs on top of the IPv6 tunnel. The source code for this sample application can be found at: diff --git a/samples/net/vlan/README.rst b/samples/net/vlan/README.rst index 3cd2c812bff..346dc07a6c3 100644 --- a/samples/net/vlan/README.rst +++ b/samples/net/vlan/README.rst @@ -1,7 +1,8 @@ -.. _vlan-sample: +.. zephyr:code-sample:: vlan + :name: Virtual LAN + :relevant-api: vlan_api net_l2 net_if -Virtual LAN Sample Application -############################## + Setup two virtual LAN networks and use net-shell to view the networks' settings. Overview ******** diff --git a/samples/net/wifi/README.rst b/samples/net/wifi/README.rst index 8638e48103e..81aaa61a729 100644 --- a/samples/net/wifi/README.rst +++ b/samples/net/wifi/README.rst @@ -1,7 +1,8 @@ -.. _wifi_sample: +.. zephyr:code-sample:: wifi-shell + :name: Wi-Fi shell + :relevant-api: net_stats -Wi-Fi sample -############ + Test Wi-Fi functionality using the Wi-Fi shell module. Overview ******** diff --git a/samples/net/wifi/boards/cy8cproto_062_4343w.conf b/samples/net/wifi/boards/cy8cproto_062_4343w.conf new file mode 100644 index 00000000000..943db317fad --- /dev/null +++ b/samples/net/wifi/boards/cy8cproto_062_4343w.conf @@ -0,0 +1,3 @@ +CONFIG_NET_IF_MAX_IPV4_COUNT=2 +CONFIG_NET_MGMT_EVENT_QUEUE_TIMEOUT=20 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 diff --git a/samples/net/wifi/boards/esp32c3_luatos_core.conf b/samples/net/wifi/boards/esp32c3_luatos_core.conf new file mode 100644 index 00000000000..5c37cfc402d --- /dev/null +++ b/samples/net/wifi/boards/esp32c3_luatos_core.conf @@ -0,0 +1,12 @@ +CONFIG_WIFI=y +CONFIG_HEAP_MEM_POOL_SIZE=98304 + +CONFIG_NETWORKING=y +CONFIG_NET_L2_ETHERNET=y + +CONFIG_NET_IPV6=n +CONFIG_NET_IPV4=y +CONFIG_NET_DHCPV4=y +CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4=y + +CONFIG_NET_LOG=y diff --git a/samples/net/wifi/boards/esp32c3_luatos_core.overlay b/samples/net/wifi/boards/esp32c3_luatos_core.overlay new file mode 100644 index 00000000000..ea9865cf5f8 --- /dev/null +++ b/samples/net/wifi/boards/esp32c3_luatos_core.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&wifi { + status = "okay"; +}; diff --git a/samples/net/wifi/boards/esp32c3_luatos_core_usb.conf b/samples/net/wifi/boards/esp32c3_luatos_core_usb.conf new file mode 100644 index 00000000000..5c37cfc402d --- /dev/null +++ b/samples/net/wifi/boards/esp32c3_luatos_core_usb.conf @@ -0,0 +1,12 @@ +CONFIG_WIFI=y +CONFIG_HEAP_MEM_POOL_SIZE=98304 + +CONFIG_NETWORKING=y +CONFIG_NET_L2_ETHERNET=y + +CONFIG_NET_IPV6=n +CONFIG_NET_IPV4=y +CONFIG_NET_DHCPV4=y +CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4=y + +CONFIG_NET_LOG=y diff --git a/samples/net/wifi/boards/esp32c3_luatos_core_usb.overlay b/samples/net/wifi/boards/esp32c3_luatos_core_usb.overlay new file mode 100644 index 00000000000..ea9865cf5f8 --- /dev/null +++ b/samples/net/wifi/boards/esp32c3_luatos_core_usb.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&wifi { + status = "okay"; +}; diff --git a/samples/net/wifi/boards/esp32s2_saola.conf b/samples/net/wifi/boards/esp32s2_saola.conf index 713c75ad3ca..e9ce202c42c 100644 --- a/samples/net/wifi/boards/esp32s2_saola.conf +++ b/samples/net/wifi/boards/esp32s2_saola.conf @@ -1,11 +1,12 @@ CONFIG_WIFI=y -CONFIG_HEAP_MEM_POOL_SIZE=32768 +CONFIG_HEAP_MEM_POOL_SIZE=34816 + +# decrease packet count and size to save RAM +CONFIG_NET_PKT_RX_COUNT=7 +CONFIG_NET_PKT_TX_COUNT=7 +CONFIG_NET_BUF_RX_COUNT=7 +CONFIG_NET_BUF_TX_COUNT=7 -# when enabling NET_SHELL, the following -# helps to optimize memory footprint -CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=8 -CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=8 -CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=8 CONFIG_ESP32_WIFI_IRAM_OPT=n CONFIG_ESP32_WIFI_RX_IRAM_OPT=n @@ -15,5 +16,7 @@ CONFIG_NET_L2_ETHERNET=y CONFIG_NET_IPV6=n CONFIG_NET_IPV4=y CONFIG_NET_DHCPV4=y +CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4=y +CONFIG_LOG_MODE_MINIMAL=y CONFIG_NET_LOG=y diff --git a/samples/net/wifi/boards/esp32s3_luatos_core.conf b/samples/net/wifi/boards/esp32s3_luatos_core.conf new file mode 100644 index 00000000000..a72fdf39efa --- /dev/null +++ b/samples/net/wifi/boards/esp32s3_luatos_core.conf @@ -0,0 +1,11 @@ +CONFIG_WIFI=y + +CONFIG_NETWORKING=y +CONFIG_NET_L2_ETHERNET=y + +CONFIG_NET_IPV6=n +CONFIG_NET_IPV4=y +CONFIG_NET_DHCPV4=y +CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4=y + +CONFIG_NET_LOG=y diff --git a/samples/net/wifi/boards/esp32s3_luatos_core.overlay b/samples/net/wifi/boards/esp32s3_luatos_core.overlay new file mode 100644 index 00000000000..4d69fe29493 --- /dev/null +++ b/samples/net/wifi/boards/esp32s3_luatos_core.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&wifi { + status = "okay"; +}; diff --git a/samples/net/wifi/boards/esp32s3_luatos_core_usb.conf b/samples/net/wifi/boards/esp32s3_luatos_core_usb.conf new file mode 100644 index 00000000000..a72fdf39efa --- /dev/null +++ b/samples/net/wifi/boards/esp32s3_luatos_core_usb.conf @@ -0,0 +1,11 @@ +CONFIG_WIFI=y + +CONFIG_NETWORKING=y +CONFIG_NET_L2_ETHERNET=y + +CONFIG_NET_IPV6=n +CONFIG_NET_IPV4=y +CONFIG_NET_DHCPV4=y +CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4=y + +CONFIG_NET_LOG=y diff --git a/samples/net/wifi/boards/esp32s3_luatos_core_usb.overlay b/samples/net/wifi/boards/esp32s3_luatos_core_usb.overlay new file mode 100644 index 00000000000..4d69fe29493 --- /dev/null +++ b/samples/net/wifi/boards/esp32s3_luatos_core_usb.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&wifi { + status = "okay"; +}; diff --git a/samples/net/wpan_serial/README.rst b/samples/net/wpan_serial/README.rst index 669c574117d..3bcf5dbb4d4 100644 --- a/samples/net/wpan_serial/README.rst +++ b/samples/net/wpan_serial/README.rst @@ -1,7 +1,8 @@ -.. _wpan_serial-sample: +.. zephyr:code-sample:: wpan-serial + :name: 802.15.4 "serial-radio" + :relevant-api: ieee802154 uart_interface -802.15.4 "serial-radio" sample -############################## + Implement a slip-radio device for Contiki-based border routers. Overview ******** diff --git a/samples/net/wpan_serial/sample.yaml b/samples/net/wpan_serial/sample.yaml index 31a458d13fc..c9ff33d9a42 100644 --- a/samples/net/wpan_serial/sample.yaml +++ b/samples/net/wpan_serial/sample.yaml @@ -4,15 +4,13 @@ sample: common: depends_on: usb_device harness: net - tags: - - net - - usb - - ieee802154 + tags: usb ieee802154 platform_exclude: pinnacle_100_dvk tests: sample.net.wpan.serial: filter: dt_chosen_enabled("zephyr,ieee802154") - platform_exclude: thingy53_nrf5340_cpuapp_ns - sample.net.wpan.serial.frdm_cr20a: + platform_exclude: thingy53_nrf5340_cpuapp_ns raytac_mdbt53_db_40_nrf5340_cpuapp_ns + raytac_mdbt53_db_40_nrf5340_cpuapp + sample.net.wpan_serial.frdm_cr20a: extra_args: SHIELD=frdm_cr20a platform_allow: frdm_k64f diff --git a/samples/net/wpan_serial/src/main.c b/samples/net/wpan_serial/src/main.c index 33ac597ef91..04b98a449bb 100644 --- a/samples/net/wpan_serial/src/main.c +++ b/samples/net/wpan_serial/src/main.c @@ -18,7 +18,7 @@ LOG_MODULE_REGISTER(wpan_serial, CONFIG_USB_DEVICE_LOG_LEVEL); #include #include #include -#include +#include #include #include @@ -299,8 +299,12 @@ static void process_config(struct net_pkt *pkt) } } -static void rx_thread(void) +static void rx_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + LOG_DBG("RX thread started"); while (true) { @@ -386,8 +390,12 @@ static int try_write(uint8_t *data, uint16_t len) /** * TX - transmit to SLIP interface */ -static void tx_thread(void) +static void tx_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + LOG_DBG("TX thread started"); while (true) { @@ -421,7 +429,7 @@ static void init_rx_queue(void) k_thread_create(&rx_thread_data, rx_stack, K_THREAD_STACK_SIZEOF(rx_stack), - (k_thread_entry_t)rx_thread, + rx_thread, NULL, NULL, NULL, THREAD_PRIORITY, 0, K_NO_WAIT); } @@ -431,7 +439,7 @@ static void init_tx_queue(void) k_thread_create(&tx_thread_data, tx_stack, K_THREAD_STACK_SIZEOF(tx_stack), - (k_thread_entry_t)tx_thread, + tx_thread, NULL, NULL, NULL, THREAD_PRIORITY, 0, K_NO_WAIT); } diff --git a/samples/net/wpanusb/README.rst b/samples/net/wpanusb/README.rst index e6e87502a66..27c6c2bae72 100644 --- a/samples/net/wpanusb/README.rst +++ b/samples/net/wpanusb/README.rst @@ -1,7 +1,8 @@ -.. _wpanusb-sample: +.. zephyr:code-sample:: wpan-usb + :name: 802.15.4 USB + :relevant-api: ieee802154 _usb_device_core_api -wpanusb sample -############## + Implement a device that exposes an IEEE 802.15.4 radio over USB. Overview ******** diff --git a/samples/net/wpanusb/sample.yaml b/samples/net/wpanusb/sample.yaml index 729e8c6ba12..bf16524ea72 100644 --- a/samples/net/wpanusb/sample.yaml +++ b/samples/net/wpanusb/sample.yaml @@ -3,16 +3,14 @@ sample: name: wpanusb common: depends_on: usb_device - tags: - - net - - ieee802154 - - usb + tags: net ieee802154 usb harness: net platform_exclude: pinnacle_100_dvk tests: sample.net.wpanusb: filter: dt_chosen_enabled("zephyr,ieee802154") - platform_exclude: thingy53_nrf5340_cpuapp_ns + platform_exclude: thingy53_nrf5340_cpuapp_ns raytac_mdbt53_db_40_nrf5340_cpuapp_ns + raytac_mdbt53_db_40_nrf5340_cpuapp sample.net.wpanusb_frdm_cr20a: extra_args: SHIELD=frdm_cr20a platform_allow: frdm_k64f diff --git a/samples/net/wpanusb/src/wpanusb.c b/samples/net/wpanusb/src/wpanusb.c index a4e1f88403f..7cee37340c3 100644 --- a/samples/net/wpanusb/src/wpanusb.c +++ b/samples/net/wpanusb/src/wpanusb.c @@ -295,8 +295,12 @@ static int tx(struct net_pkt *pkt) return ret; } -static void tx_thread(void) +static void tx_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + LOG_DBG("Tx thread started"); while (1) { @@ -353,7 +357,7 @@ static void init_tx_queue(void) k_thread_create(&tx_thread_data, tx_stack, K_THREAD_STACK_SIZEOF(tx_stack), - (k_thread_entry_t)tx_thread, + tx_thread, NULL, NULL, NULL, THREAD_PRIORITY, 0, K_NO_WAIT); } diff --git a/samples/net/zperf/README.rst b/samples/net/zperf/README.rst index ded271b9a43..949acba5e76 100644 --- a/samples/net/zperf/README.rst +++ b/samples/net/zperf/README.rst @@ -1,7 +1,8 @@ -.. _zperf-sample: +.. zephyr:code-sample:: zperf + :name: zperf: Network Traffic Generator + :relevant-api: net_config -zperf: Network Traffic Generator -################################ + Use the zperf shell utility to evaluate network bandwidth. Description *********** diff --git a/samples/net/zperf/sample.yaml b/samples/net/zperf/sample.yaml index 82b8b519e79..201940c23a9 100644 --- a/samples/net/zperf/sample.yaml +++ b/samples/net/zperf/sample.yaml @@ -26,6 +26,7 @@ tests: - nucleo_h743zi - nucleo_f429zi - nucleo_f746zg + - stm32h573i_dk sample.net.zperf_no_shell: harness: net extra_configs: diff --git a/samples/philosophers/README.rst b/samples/philosophers/README.rst index fbf3ff96f3e..77c07cba670 100644 --- a/samples/philosophers/README.rst +++ b/samples/philosophers/README.rst @@ -86,23 +86,23 @@ OpenOCD Sample Output Thread 1 received signal SIGINT, Interrupt. [Switching to Thread 537003160] - arch_cpu_idle () at zephyr/mainline/zephyr/arch/arm/core/aarch32/cpu_idle.S:107 + arch_cpu_idle () at zephyr/mainline/zephyr/arch/arm/core/cpu_idle.S:107 107 cpsie i (gdb) i threads Id Target Id Frame - * 1 Thread 537003160 (Name: idle 00, prio:40,useropts:1) arch_cpu_idle () at zephyr/mainline/zephyr/arch/arm/core/aarch32/cpu_idle.S:107 + * 1 Thread 537003160 (Name: idle 00, prio:40,useropts:1) arch_cpu_idle () at zephyr/mainline/zephyr/arch/arm/core/cpu_idle.S:107 Info : Getting thread 537002984 reg list - 2 Thread 537002984 (Name: Philosopher 5, prio:-2,useropts:4) 0x08001404 in arch_irq_unlock (key=0) at zephyr/mainline/zephyr/include/arch/arm/aarch32/asm_inline_gcc.h:95 + 2 Thread 537002984 (Name: Philosopher 5, prio:-2,useropts:4) 0x08001404 in arch_irq_unlock (key=0) at zephyr/mainline/zephyr/include/arch/arm/asm_inline_gcc.h:95 Info : Getting thread 537002808 reg list - 3 Thread 537002808 (Name: Philosopher 4, prio:-1,useropts:4) 0x08001404 in arch_irq_unlock (key=0) at zephyr/mainline/zephyr/include/arch/arm/aarch32/asm_inline_gcc.h:95 + 3 Thread 537002808 (Name: Philosopher 4, prio:-1,useropts:4) 0x08001404 in arch_irq_unlock (key=0) at zephyr/mainline/zephyr/include/arch/arm/asm_inline_gcc.h:95 Info : Getting thread 537002632 reg list - 4 Thread 537002632 (Name: Philosopher 3, prio:0,useropts:4) 0x08001404 in arch_irq_unlock (key=0) at zephyr/mainline/zephyr/include/arch/arm/aarch32/asm_inline_gcc.h:95 + 4 Thread 537002632 (Name: Philosopher 3, prio:0,useropts:4) 0x08001404 in arch_irq_unlock (key=0) at zephyr/mainline/zephyr/include/arch/arm/asm_inline_gcc.h:95 Info : Getting thread 537002456 reg list - 5 Thread 537002456 (Name: Philosopher 2, prio:1,useropts:4) 0x08001404 in arch_irq_unlock (key=0) at zephyr/mainline/zephyr/include/arch/arm/aarch32/asm_inline_gcc.h:95 + 5 Thread 537002456 (Name: Philosopher 2, prio:1,useropts:4) 0x08001404 in arch_irq_unlock (key=0) at zephyr/mainline/zephyr/include/arch/arm/asm_inline_gcc.h:95 Info : Getting thread 537002280 reg list - 6 Thread 537002280 (Name: Philosopher 1, prio:2,useropts:4) 0x08001404 in arch_irq_unlock (key=0) at zephyr/mainline/zephyr/include/arch/arm/aarch32/asm_inline_gcc.h:95 + 6 Thread 537002280 (Name: Philosopher 1, prio:2,useropts:4) 0x08001404 in arch_irq_unlock (key=0) at zephyr/mainline/zephyr/include/arch/arm/asm_inline_gcc.h:95 Info : Getting thread 537002104 reg list - 7 Thread 537002104 (Name: Philosopher 0, prio:3,useropts:4) 0x08001404 in arch_irq_unlock (key=0) at zephyr/mainline/zephyr/include/arch/arm/aarch32/asm_inline_gcc.h:95 + 7 Thread 537002104 (Name: Philosopher 0, prio:3,useropts:4) 0x08001404 in arch_irq_unlock (key=0) at zephyr/mainline/zephyr/include/arch/arm/asm_inline_gcc.h:95 .. code-block:: console @@ -121,17 +121,17 @@ J-Link Sample Output Thread 2 received signal SIGTRAP, Trace/breakpoint trap. [Switching to Thread 537920592] - arch_cpu_idle () at zephyr/mainline/zephyr/arch/arm/core/aarch32/cpu_idle.S:107 + arch_cpu_idle () at zephyr/mainline/zephyr/arch/arm/core/cpu_idle.S:107 107 cpsie i (gdb) i threads Id Target Id Frame - * 2 Thread 537920592 (idle 00 UNKNOWN PRIO 40) arch_cpu_idle () at zephyr/mainline/zephyr/arch/arm/core/aarch32/cpu_idle.S:107 - 3 Thread 537919536 (Philosopher 0 PENDING PRIO 3) arch_swap (key=0) at zephyr/mainline/zephyr/arch/arm/core/aarch32/swap.c:53 - 4 Thread 537919712 (Philosopher 1 SUSPENDED PRIO 2) arch_swap (key=key@entry=0) at zephyr/mainline/zephyr/arch/arm/core/aarch32/swap.c:53 - 5 Thread 537919888 (Philosopher 2 SUSPENDED PRIO 1) arch_swap (key=key@entry=0) at zephyr/mainline/zephyr/arch/arm/core/aarch32/swap.c:53 - 6 Thread 537920064 (Philosopher 3 SUSPENDED PRIO 0) arch_swap (key=key@entry=0) at zephyr/mainline/zephyr/arch/arm/core/aarch32/swap.c:53 - 7 Thread 537920240 (Philosopher 4 PENDING PRIO 255) arch_swap (key=0) at zephyr/mainline/zephyr/arch/arm/core/aarch32/swap.c:53 - 8 Thread 537920416 (Philosopher 5 SUSPENDED PRIO 254) arch_swap (key=key@entry=0) at zephyr/mainline/zephyr/arch/arm/core/aarch32/swap.c:53 + * 2 Thread 537920592 (idle 00 UNKNOWN PRIO 40) arch_cpu_idle () at zephyr/mainline/zephyr/arch/arm/core/cpu_idle.S:107 + 3 Thread 537919536 (Philosopher 0 PENDING PRIO 3) arch_swap (key=0) at zephyr/mainline/zephyr/arch/arm/core/swap.c:53 + 4 Thread 537919712 (Philosopher 1 SUSPENDED PRIO 2) arch_swap (key=key@entry=0) at zephyr/mainline/zephyr/arch/arm/core/swap.c:53 + 5 Thread 537919888 (Philosopher 2 SUSPENDED PRIO 1) arch_swap (key=key@entry=0) at zephyr/mainline/zephyr/arch/arm/core/swap.c:53 + 6 Thread 537920064 (Philosopher 3 SUSPENDED PRIO 0) arch_swap (key=key@entry=0) at zephyr/mainline/zephyr/arch/arm/core/swap.c:53 + 7 Thread 537920240 (Philosopher 4 PENDING PRIO 255) arch_swap (key=0) at zephyr/mainline/zephyr/arch/arm/core/swap.c:53 + 8 Thread 537920416 (Philosopher 5 SUSPENDED PRIO 254) arch_swap (key=key@entry=0) at zephyr/mainline/zephyr/arch/arm/core/swap.c:53 .. code-block:: console diff --git a/samples/philosophers/sample.yaml b/samples/philosophers/sample.yaml index d072f2c6887..2db2c1563f4 100644 --- a/samples/philosophers/sample.yaml +++ b/samples/philosophers/sample.yaml @@ -8,7 +8,7 @@ common: harness: console min_ram: 16 integration_platforms: - - native_posix + - native_sim harness_config: type: multi_line ordered: false diff --git a/samples/philosophers/src/phil_obj_abstract.h b/samples/philosophers/src/phil_obj_abstract.h index 9277ce8a1e7..e749a3f8d49 100644 --- a/samples/philosophers/src/phil_obj_abstract.h +++ b/samples/philosophers/src/phil_obj_abstract.h @@ -87,7 +87,7 @@ #endif #define take(x) do { \ stack_data_t data; k_stack_pop(x, &data, K_FOREVER); \ - __ASSERT(data == MAGIC, "data was %x\n", data); \ + __ASSERT(data == MAGIC, "data was %lx\n", data); \ } while ((0)) #define drop(x) k_stack_push(x, MAGIC) #define fork_type_str "stacks" diff --git a/samples/posix/eventfd/Makefile.posix b/samples/posix/eventfd/Makefile.host similarity index 100% rename from samples/posix/eventfd/Makefile.posix rename to samples/posix/eventfd/Makefile.host diff --git a/samples/posix/eventfd/prj.conf b/samples/posix/eventfd/prj.conf index a0bfcdf747b..4fb4280b874 100644 --- a/samples/posix/eventfd/prj.conf +++ b/samples/posix/eventfd/prj.conf @@ -1,6 +1,5 @@ # General config -CONFIG_NEWLIB_LIBC=y -CONFIG_NEWLIB_LIBC_NANO=n +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_POSIX_API=y CONFIG_EVENTFD=y diff --git a/samples/posix/eventfd/sample.yaml b/samples/posix/eventfd/sample.yaml index d1384095ae8..8e1e16b4eb7 100644 --- a/samples/posix/eventfd/sample.yaml +++ b/samples/posix/eventfd/sample.yaml @@ -2,7 +2,7 @@ sample: description: Extended POSIX (Linux) API eventfd() example name: eventfd common: - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED and not CONFIG_NATIVE_LIBC tags: posix platform_exclude: m2gl025_miv integration_platforms: diff --git a/samples/posix/gettimeofday/Makefile.posix b/samples/posix/gettimeofday/Makefile.host similarity index 100% rename from samples/posix/gettimeofday/Makefile.posix rename to samples/posix/gettimeofday/Makefile.host diff --git a/samples/posix/gettimeofday/README.rst b/samples/posix/gettimeofday/README.rst index c2c5def96d8..c01f1c65e33 100644 --- a/samples/posix/gettimeofday/README.rst +++ b/samples/posix/gettimeofday/README.rst @@ -34,9 +34,8 @@ on QEMU as follows: :goals: run :compact: -For comparison, a version for native POSIX operating systems (e.g. Linux) -can be built using: +For comparison, to build directly for your host OS if it is POSIX compliant (for ex. Linux): .. code-block:: console - make -f Makefile.posix + make -f Makefile.host diff --git a/samples/posix/gettimeofday/prj.conf b/samples/posix/gettimeofday/prj.conf index 033db203f16..ee748221ce5 100644 --- a/samples/posix/gettimeofday/prj.conf +++ b/samples/posix/gettimeofday/prj.conf @@ -1,6 +1,6 @@ # General config CONFIG_MAIN_STACK_SIZE=1088 -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_POSIX_API=y CONFIG_SNTP=y CONFIG_NET_CONFIG_CLOCK_SNTP_INIT=y diff --git a/samples/posix/gettimeofday/sample.yaml b/samples/posix/gettimeofday/sample.yaml index 2e21ce21457..a71d29f09c5 100644 --- a/samples/posix/gettimeofday/sample.yaml +++ b/samples/posix/gettimeofday/sample.yaml @@ -2,7 +2,8 @@ sample: description: POSIX API gettimeofday() example (with SNTP) name: gettimeofday common: - filter: ( TOOLCHAIN_HAS_NEWLIB == 1 and not CONFIG_SOC_FAMILY_INTEL_ADSP ) + filter: ( CONFIG_FULL_LIBC_SUPPORTED and not CONFIG_NATIVE_LIBC + and not CONFIG_SOC_FAMILY_INTEL_ADSP ) harness: net min_ram: 32 min_flash: 96 diff --git a/samples/posix/uname/sample.yaml b/samples/posix/uname/sample.yaml index cfe990eb127..f4b8b82abac 100644 --- a/samples/posix/uname/sample.yaml +++ b/samples/posix/uname/sample.yaml @@ -3,9 +3,11 @@ sample: name: posix uname common: tags: posix - filter: not CONFIG_ARCH_POSIX - integration_platforms: + platform_exclude: + - native_posix - native_posix_64 + integration_platforms: + - native_sim - qemu_riscv64 harness: console harness_config: diff --git a/samples/sample_definition_and_criteria.rst b/samples/sample_definition_and_criteria.rst index 5a75496aff6..8e69fe4a63a 100644 --- a/samples/sample_definition_and_criteria.rst +++ b/samples/sample_definition_and_criteria.rst @@ -19,7 +19,7 @@ Sample Criteria * The primary purpose of a sample is to provide a reference to the user. * Samples must not use Zephyr's testing framework. - * Must not use :kconfig:option:`CONFIG_ZTEST` or :kconfig:option:`CONFIG_ZTEST_NEW_API`. + * Must not use :kconfig:option:`CONFIG_ZTEST` * Must not use zasserts in samples. * If a sample can provide output that can be verified, then output should be evaluated against @@ -38,7 +38,7 @@ Sample Criteria tests: sample.kernel.cond_var: integration_platforms: - - native_posix + - native_sim tags: kernel condition_variables harness: console harness_config: diff --git a/samples/sensor/bme280/README.rst b/samples/sensor/bme280/README.rst index f47512fe341..f6372779154 100644 --- a/samples/sensor/bme280/README.rst +++ b/samples/sensor/bme280/README.rst @@ -73,6 +73,34 @@ The devicetree overlay :zephyr_file:`samples/sensor/bme280/arduino_i2c.overlay` works on any board with a properly configured Arduino pin-compatible I2C peripheral. +BME280 via Raspberry Pi Pico +============================ + +The default assignment of the built-in spi0 device on the :ref:`rpi_pico` is +to GPIO16 through GPIO19. With the sensor wired to those lines, build and +flash with: + +.. zephyr-app-commands:: + :zephyr-app: samples/sensor/bme280 + :goals: build flash + :board: rpi_pico + +An alternative is to use PIO serving as an SPI device. The devicetree +overlay :zephyr_file:`samples/sensor/bme280/rpi_pico_spi_pio.overlay` +demonstrates using PIO SPI with the sensor wired to arbitrary GPIO pins. +Build and flash with: + +.. zephyr-app-commands:: + :zephyr-app: samples/sensor/bme280 + :goals: build flash + :board: rpi_pico + :gen-args: -DDTC_OVERLAY_FILE=rpi_pico_spi_pio.overlay + +Note that miso-gpios, mosi-gpios, and clk-gpios need to be assigned to the +selected PIO device in pinctrl, while cs-gpios should not; chip select is +controlled by the SPI context and must operate as a conventional GPIO pin, +not under control of PIO. + Board-specific overlays ======================= diff --git a/samples/sensor/bme280/boards/rpi_pico.overlay b/samples/sensor/bme280/boards/rpi_pico.overlay new file mode 100644 index 00000000000..61cf67aff5b --- /dev/null +++ b/samples/sensor/bme280/boards/rpi_pico.overlay @@ -0,0 +1,10 @@ +&spi0 { + status = "okay"; + cs-gpios = <&gpio0 17 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&spi0_default>; + bme280@0 { + compatible = "bosch,bme280"; + reg = <0>; + spi-max-frequency = <1000000>; /* conservatively set to 1MHz */ + }; +}; diff --git a/samples/sensor/bme280/rpi_pico_spi_pio.overlay b/samples/sensor/bme280/rpi_pico_spi_pio.overlay new file mode 100644 index 00000000000..473cfae2a0b --- /dev/null +++ b/samples/sensor/bme280/rpi_pico_spi_pio.overlay @@ -0,0 +1,36 @@ +&pinctrl { + pio0_spi0_default: pio0_spi0_default { + /* gpio 13 is used for chip select, not assigned to the PIO */ + group1 { + pinmux = , ; + }; + group2 { + pinmux = ; + input-enable; + }; + }; +}; + +&pio0 { + status = "okay"; + + pio0_spi0: pio0_spi0 { + pinctrl-0 = <&pio0_spi0_default>; + pinctrl-names = "default"; + + compatible = "raspberrypi,pico-spi-pio"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + clocks = < &system_clk >; + miso-gpios = <&gpio0 12 0>; + cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + clk-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; + mosi-gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>; + bme280@0 { + compatible = "bosch,bme280"; + reg = <0>; + spi-max-frequency = <1000000>; /* conservatively set to 1MHz */ + }; + }; +}; diff --git a/samples/sensor/bme280/sample.yaml b/samples/sensor/bme280/sample.yaml index eaa0d13e5bb..2e84cd1af03 100644 --- a/samples/sensor/bme280/sample.yaml +++ b/samples/sensor/bme280/sample.yaml @@ -4,7 +4,9 @@ tests: sample.sensor.bme280: harness: console tags: sensors - platform_allow: adafruit_feather_m0_basic_proto + platform_allow: + - adafruit_feather_m0_basic_proto + - rpi_pico integration_platforms: - adafruit_feather_m0_basic_proto harness_config: @@ -24,3 +26,15 @@ tests: regex: - "temp: (.*); press: (.*); humidity: (.*)" fixture: fixture_spi_bme280 + sample.sensor.bme280.rpi_pico.pio: + harness: console + tags: sensors + platform_allow: rpi_pico + integration_platforms: + - rpi_pico + extra_args: "DTC_OVERLAY_FILE=rpi_pico_spi_pio.overlay" + harness_config: + type: one_line + regex: + - "temp: (.*); press: (.*); humidity: (.*)" + fixture: fixture_rpi_pico_pio_spi_bme280 diff --git a/samples/sensor/co2_polling/CMakeLists.txt b/samples/sensor/co2_polling/CMakeLists.txt new file mode 100644 index 00000000000..ae467b6d2aa --- /dev/null +++ b/samples/sensor/co2_polling/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(co2_polling) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/sensor/co2_polling/README.rst b/samples/sensor/co2_polling/README.rst new file mode 100644 index 00000000000..c0436b363ac --- /dev/null +++ b/samples/sensor/co2_polling/README.rst @@ -0,0 +1,30 @@ +.. co2: + +Generic CO2 polling sample +########################## + +Overview +******** + +A sensor sample that demonstrates how to poll a CO2 sensor. + +Building and Running +******************** + +This sample reads the CO2 sensor and print the values continuously. + +.. zephyr-app-commands:: + :zephyr-app: samples/sensor/co2_polling + :board: + :goals: build flash + :compact: + +Sample Output +============= + +.. code-block:: console + + CO2 940 ppm + CO2 950 ppm + + diff --git a/samples/sensor/co2_polling/boards/nucleo_h563zi.conf b/samples/sensor/co2_polling/boards/nucleo_h563zi.conf new file mode 100644 index 00000000000..86df0aff3e6 --- /dev/null +++ b/samples/sensor/co2_polling/boards/nucleo_h563zi.conf @@ -0,0 +1 @@ +CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/samples/sensor/co2_polling/boards/nucleo_h563zi.overlay b/samples/sensor/co2_polling/boards/nucleo_h563zi.overlay new file mode 100644 index 00000000000..549e3492699 --- /dev/null +++ b/samples/sensor/co2_polling/boards/nucleo_h563zi.overlay @@ -0,0 +1,15 @@ +/ { + aliases { + co2 = &explorir_m; + }; +}; + +&lpuart1 { + status = "okay"; + current-speed = <9600>; + + explorir_m: explorir_m { + compatible = "gss,explorir-m"; + status = "okay"; + }; +}; diff --git a/samples/sensor/co2_polling/prj.conf b/samples/sensor/co2_polling/prj.conf new file mode 100644 index 00000000000..fe480d2b794 --- /dev/null +++ b/samples/sensor/co2_polling/prj.conf @@ -0,0 +1,7 @@ +CONFIG_STDOUT_CONSOLE=y +CONFIG_LOG=y +CONFIG_SHELL=y +CONFIG_SENSOR_SHELL=y +CONFIG_SERIAL=y +CONFIG_SENSOR=y +CONFIG_SENSOR_LOG_LEVEL_DBG=y diff --git a/samples/sensor/co2_polling/sample.yaml b/samples/sensor/co2_polling/sample.yaml new file mode 100644 index 00000000000..13b4ffa6dfb --- /dev/null +++ b/samples/sensor/co2_polling/sample.yaml @@ -0,0 +1,8 @@ +sample: + name: CO2 sensor sample +tests: + sample.sensor.co2: + harness: sensor + tags: sensors + filter: dt_alias_exists("co2") + depends_on: serial uart_interrupt_driven diff --git a/samples/sensor/co2_polling/src/main.c b/samples/sensor/co2_polling/src/main.c new file mode 100644 index 00000000000..4f184527453 --- /dev/null +++ b/samples/sensor/co2_polling/src/main.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023, Vitrolife A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +LOG_MODULE_REGISTER(MAIN); + +int main(void) +{ + struct sensor_value value; + const struct device *const dev = DEVICE_DT_GET(DT_ALIAS(co2)); + + if (!device_is_ready(dev)) { + LOG_ERR("%s is not ready", dev->name); + return 0; + } + + while (1) { + if (sensor_sample_fetch(dev) == 0 && + sensor_channel_get(dev, SENSOR_CHAN_CO2, &value) == 0) { + LOG_INF("CO2 %d ppm", value.val1); + } + + k_msleep(1000); + } + + return 0; +} diff --git a/samples/sensor/dht/boards/longan_nano.overlay b/samples/sensor/dht/boards/longan_nano.overlay new file mode 100644 index 00000000000..a50cd9b9404 --- /dev/null +++ b/samples/sensor/dht/boards/longan_nano.overlay @@ -0,0 +1,11 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + dht22 { + compatible = "aosong,dht"; + status = "okay"; + dio-gpios = <&gpiob 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + }; +}; diff --git a/samples/sensor/dht/prj.conf b/samples/sensor/dht/prj.conf index 9555c352793..33811ecb171 100644 --- a/samples/sensor/dht/prj.conf +++ b/samples/sensor/dht/prj.conf @@ -8,6 +8,6 @@ CONFIG_SENSOR=y CONFIG_GPIO=y # Need float format support -CONFIG_NEWLIB_LIBC=y -CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y +CONFIG_REQUIRES_FULL_LIBC=y +CONFIG_REQUIRES_FLOAT_PRINTF=y CONFIG_CBPRINTF_FP_SUPPORT=y diff --git a/samples/sensor/dht/sample.yaml b/samples/sensor/dht/sample.yaml index 74f346bd31d..ad74cb83d9c 100644 --- a/samples/sensor/dht/sample.yaml +++ b/samples/sensor/dht/sample.yaml @@ -5,7 +5,7 @@ # common: - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED sample: name: DHT Sensor Sample tests: diff --git a/samples/sensor/dht_polling/CMakeLists.txt b/samples/sensor/dht_polling/CMakeLists.txt new file mode 100644 index 00000000000..31b4352da9d --- /dev/null +++ b/samples/sensor/dht_polling/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Ian Morris +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(dht_polling) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/sensor/dht_polling/README.rst b/samples/sensor/dht_polling/README.rst new file mode 100644 index 00000000000..09550b255d0 --- /dev/null +++ b/samples/sensor/dht_polling/README.rst @@ -0,0 +1,49 @@ +.. _dht_polling: + +Generic Digital Humidity Temperature sensor polling sample +########################################################## + +Overview +******** + +This sample application demonstrates how to use digital humidity temperature +sensors. + +Building and Running +******************** + +This sample supports up to 10 humidity/temperature sensors. Each sensor needs to +be aliased as ``dhtN`` where ``N`` goes from ``0`` to ``9``. For example: + +.. code-block:: devicetree + + / { + aliases { + dht0 = &hs300x; + }; + }; + +Make sure the aliases are in devicetree, then build and run with: + +.. zephyr-app-commands:: + :zephyr-app: samples/sensor/dht_polling + :board: + :goals: build flash + :compact: + +Sample Output +============= + +.. code-block:: console + + hs300x@44: temp is 25.31 °C humidity is 30.39 %RH + hs300x@44: temp is 25.51 °C humidity is 30.44 %RH + hs300x@44: temp is 25.51 °C humidity is 30.37 %RH + hs300x@44: temp is 25.51 °C humidity is 30.39 %RH + hs300x@44: temp is 25.31 °C humidity is 30.37 %RH + hs300x@44: temp is 25.31 °C humidity is 30.35 %RH + hs300x@44: temp is 25.51 °C humidity is 30.37 %RH + hs300x@44: temp is 25.51 °C humidity is 30.37 %RH + hs300x@44: temp is 25.51 °C humidity is 30.39 %RH + hs300x@44: temp is 25.51 °C humidity is 30.44 %RH + hs300x@44: temp is 25.51 °C humidity is 30.53 %RH diff --git a/samples/sensor/dht_polling/boards/nucleo_f401re.overlay b/samples/sensor/dht_polling/boards/nucleo_f401re.overlay new file mode 100644 index 00000000000..cb381b5ba3a --- /dev/null +++ b/samples/sensor/dht_polling/boards/nucleo_f401re.overlay @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 Ian Morris + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + dht0 = &hs300x; + }; +}; + + &i2c1 { + status = "okay"; + + hs300x: hs300x@44 { + compatible = "renesas,hs300x"; + reg = <0x44>; + #address-cells = <1>; + #size-cells = <0>; + }; +}; diff --git a/samples/sensor/dht_polling/prj.conf b/samples/sensor/dht_polling/prj.conf new file mode 100644 index 00000000000..7d668be1f0b --- /dev/null +++ b/samples/sensor/dht_polling/prj.conf @@ -0,0 +1,2 @@ +CONFIG_STDOUT_CONSOLE=y +CONFIG_SENSOR=y diff --git a/samples/sensor/dht_polling/sample.yaml b/samples/sensor/dht_polling/sample.yaml new file mode 100644 index 00000000000..8177e636d21 --- /dev/null +++ b/samples/sensor/dht_polling/sample.yaml @@ -0,0 +1,20 @@ +# +# Copyright (c) 2023 Ian Morris +# +# SPDX-License-Identifier: Apache-2.0 +# + +sample: + description: Digital Humidity Temperature polling sample + name: DHT polling sample +tests: + sample.sensor.dht_polling: + tags: sensors + filter: dt_alias_exists("dht0") + integration_platforms: + - nucleo_f401re + harness: console + harness_config: + type: one_line + regex: + - "[0-9A-Za-z_,+-.]*@[0-9A-Fa-f]*: temp is (.*) °C humidity is (.*) %RH" diff --git a/samples/sensor/dht_polling/src/main.c b/samples/sensor/dht_polling/src/main.c new file mode 100644 index 00000000000..8ff26b5ab9b --- /dev/null +++ b/samples/sensor/dht_polling/src/main.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023 Ian Morris + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include +#include + +#define DHT_ALIAS(i) DT_ALIAS(_CONCAT(dht, i)) +#define DHT_DEVICE(i, _) \ + IF_ENABLED(DT_NODE_EXISTS(DHT_ALIAS(i)), (DEVICE_DT_GET(DHT_ALIAS(i)),)) + +/* Support up to 10 temperature/humidity sensors */ +static const struct device *const sensors[] = {LISTIFY(10, DHT_DEVICE, ())}; + +int main(void) +{ + int rc; + + for (size_t i = 0; i < ARRAY_SIZE(sensors); i++) { + if (!device_is_ready(sensors[i])) { + printk("sensor: device %s not ready.\n", sensors[i]->name); + return 0; + } + } + + while (1) { + for (size_t i = 0; i < ARRAY_SIZE(sensors); i++) { + struct device *dev = (struct device *)sensors[i]; + + rc = sensor_sample_fetch(dev); + if (rc < 0) { + printk("%s: sensor_sample_fetch() failed: %d\n", dev->name, rc); + return rc; + } + + struct sensor_value temp; + struct sensor_value hum; + + rc = sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &temp); + if (rc == 0) { + rc = sensor_channel_get(dev, SENSOR_CHAN_HUMIDITY, &hum); + } + if (rc != 0) { + printf("get failed: %d\n", rc); + break; + } + + printk("%16s: temp is %d.%02d °C humidity is %d.%02d %%RH\n", + dev->name, temp.val1, temp.val2 / 10000, + hum.val1, hum.val2 / 10000); + } + k_msleep(1000); + } + return 0; +} diff --git a/samples/sensor/die_temp_polling/boards/esp32c3_devkitm.conf b/samples/sensor/die_temp_polling/boards/esp32c3_devkitm.conf index 13ed95d4291..5ab7306afeb 100644 --- a/samples/sensor/die_temp_polling/boards/esp32c3_devkitm.conf +++ b/samples/sensor/die_temp_polling/boards/esp32c3_devkitm.conf @@ -1 +1 @@ -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y diff --git a/samples/sensor/die_temp_polling/boards/esp32c3_luatos_core.conf b/samples/sensor/die_temp_polling/boards/esp32c3_luatos_core.conf new file mode 100644 index 00000000000..5ab7306afeb --- /dev/null +++ b/samples/sensor/die_temp_polling/boards/esp32c3_luatos_core.conf @@ -0,0 +1 @@ +CONFIG_REQUIRES_FULL_LIBC=y diff --git a/samples/sensor/die_temp_polling/boards/esp32c3_luatos_core.overlay b/samples/sensor/die_temp_polling/boards/esp32c3_luatos_core.overlay new file mode 100644 index 00000000000..55c2a4c86ae --- /dev/null +++ b/samples/sensor/die_temp_polling/boards/esp32c3_luatos_core.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2023, Hiroki Tada + * + * SPDX-License-Identifier: Apache-2.0 + * + * Application overlay for creating temperature sensor device instance + */ + +&coretemp { + status = "okay"; +}; diff --git a/samples/sensor/die_temp_polling/boards/esp32c3_luatos_core_usb.conf b/samples/sensor/die_temp_polling/boards/esp32c3_luatos_core_usb.conf new file mode 100644 index 00000000000..5ab7306afeb --- /dev/null +++ b/samples/sensor/die_temp_polling/boards/esp32c3_luatos_core_usb.conf @@ -0,0 +1 @@ +CONFIG_REQUIRES_FULL_LIBC=y diff --git a/samples/sensor/die_temp_polling/boards/esp32c3_luatos_core_usb.overlay b/samples/sensor/die_temp_polling/boards/esp32c3_luatos_core_usb.overlay new file mode 100644 index 00000000000..55c2a4c86ae --- /dev/null +++ b/samples/sensor/die_temp_polling/boards/esp32c3_luatos_core_usb.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2023, Hiroki Tada + * + * SPDX-License-Identifier: Apache-2.0 + * + * Application overlay for creating temperature sensor device instance + */ + +&coretemp { + status = "okay"; +}; diff --git a/samples/sensor/die_temp_polling/boards/esp32s2_saola.conf b/samples/sensor/die_temp_polling/boards/esp32s2_saola.conf index 13ed95d4291..5ab7306afeb 100644 --- a/samples/sensor/die_temp_polling/boards/esp32s2_saola.conf +++ b/samples/sensor/die_temp_polling/boards/esp32s2_saola.conf @@ -1 +1 @@ -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y diff --git a/samples/sensor/die_temp_polling/boards/mimxrt1050_evk.conf b/samples/sensor/die_temp_polling/boards/mimxrt1050_evk.conf index 13ed95d4291..5ab7306afeb 100644 --- a/samples/sensor/die_temp_polling/boards/mimxrt1050_evk.conf +++ b/samples/sensor/die_temp_polling/boards/mimxrt1050_evk.conf @@ -1 +1 @@ -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y diff --git a/samples/sensor/die_temp_polling/sample.yaml b/samples/sensor/die_temp_polling/sample.yaml index f27b40e34f3..f64b321c2bd 100644 --- a/samples/sensor/die_temp_polling/sample.yaml +++ b/samples/sensor/die_temp_polling/sample.yaml @@ -12,4 +12,4 @@ tests: harness_config: type: one_line regex: - - "CPU Die temperature\\[[A-Za-z0-9_]+\\]: [1-9][0-9].[0-9] °C" + - "CPU Die temperature\\[[A-Za-z0-9_@]+\\]: [1-9][0-9].[0-9] °C" diff --git a/samples/sensor/fdc2x1x/prj.conf b/samples/sensor/fdc2x1x/prj.conf index f0275d2e97e..2b9602b1fc8 100644 --- a/samples/sensor/fdc2x1x/prj.conf +++ b/samples/sensor/fdc2x1x/prj.conf @@ -2,7 +2,7 @@ CONFIG_LOG=y CONFIG_I2C=y CONFIG_SENSOR=y CONFIG_PM_DEVICE=n -CONFIG_NEWLIB_LIBC=y -CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y +CONFIG_REQUIRES_FULL_LIBC=y +CONFIG_REQUIRES_FLOAT_PRINTF=y CONFIG_FDC2X1X_TRIGGER_GLOBAL_THREAD=n diff --git a/samples/sensor/grove_light/prj.conf b/samples/sensor/grove_light/prj.conf index 7aafd383084..dc1d0ec2139 100644 --- a/samples/sensor/grove_light/prj.conf +++ b/samples/sensor/grove_light/prj.conf @@ -1,5 +1,5 @@ CONFIG_ADC=y CONFIG_SENSOR=y -CONFIG_NEWLIB_LIBC=y -CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y +CONFIG_REQUIRES_FULL_LIBC=y +CONFIG_REQUIRES_FLOAT_PRINTF=y CONFIG_CBPRINTF_FP_SUPPORT=y diff --git a/samples/sensor/grove_light/sample.yaml b/samples/sensor/grove_light/sample.yaml index df34be19f7a..3eb1083a883 100644 --- a/samples/sensor/grove_light/sample.yaml +++ b/samples/sensor/grove_light/sample.yaml @@ -1,5 +1,5 @@ common: - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED sample: name: Grove Light Sensor tests: diff --git a/samples/sensor/grove_temperature/prj.conf b/samples/sensor/grove_temperature/prj.conf index 7aafd383084..dc1d0ec2139 100644 --- a/samples/sensor/grove_temperature/prj.conf +++ b/samples/sensor/grove_temperature/prj.conf @@ -1,5 +1,5 @@ CONFIG_ADC=y CONFIG_SENSOR=y -CONFIG_NEWLIB_LIBC=y -CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y +CONFIG_REQUIRES_FULL_LIBC=y +CONFIG_REQUIRES_FLOAT_PRINTF=y CONFIG_CBPRINTF_FP_SUPPORT=y diff --git a/samples/sensor/grove_temperature/sample.yaml b/samples/sensor/grove_temperature/sample.yaml index 0076845543e..83035b9b9fb 100644 --- a/samples/sensor/grove_temperature/sample.yaml +++ b/samples/sensor/grove_temperature/sample.yaml @@ -1,5 +1,5 @@ common: - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED sample: name: Grove Temperature Sensor tests: diff --git a/samples/sensor/grove_temperature/src/main.c b/samples/sensor/grove_temperature/src/main.c index 643ae4707e2..c49137f6018 100644 --- a/samples/sensor/grove_temperature/src/main.c +++ b/samples/sensor/grove_temperature/src/main.c @@ -63,7 +63,7 @@ int main(void) /* display temperature on LCD */ glcd_cursor_pos_set(glcd, 0, 0); -#ifdef CONFIG_NEWLIB_LIBC_FLOAT_PRINTF +#ifdef CONFIG_REQUIRES_FLOAT_PRINTF sprintf(row, "T:%.2f%cC", sensor_value_to_double(&temp), 223 /* degree symbol */); @@ -75,7 +75,7 @@ int main(void) #endif -#ifdef CONFIG_NEWLIB_LIBC_FLOAT_PRINTF +#ifdef CONFIG_REQUIRES_FLOAT_PRINTF printf("Temperature: %.2f C\n", sensor_value_to_double(&temp)); #else printk("Temperature: %d\n", temp.val1); diff --git a/samples/sensor/hts221/README.rst b/samples/sensor/hts221/README.rst index 746bb1fa0a4..56734c08c35 100644 --- a/samples/sensor/hts221/README.rst +++ b/samples/sensor/hts221/README.rst @@ -17,7 +17,7 @@ This sample uses the HTS221 sensor controlled using the I2C interface. References ********** - - HTS211: http://www.st.com/en/mems-and-sensors/hts221.html + - HTS211: https://www.st.com/en/mems-and-sensors/hts221.html Building and Running ******************** diff --git a/samples/sensor/lis2dh/README.rst b/samples/sensor/lis2dh/README.rst index de4bd3d0b91..3e68414abce 100644 --- a/samples/sensor/lis2dh/README.rst +++ b/samples/sensor/lis2dh/README.rst @@ -20,7 +20,7 @@ References ********** For more information about the LIS2DH motion sensor see -http://www.st.com/en/mems-and-sensors/lis2dh.html. +https://www.st.com/en/mems-and-sensors/lis2dh.html. Building and Running ******************** diff --git a/samples/sensor/lps22hb/README.rst b/samples/sensor/lps22hb/README.rst index efbc20ca009..f469f05b6db 100644 --- a/samples/sensor/lps22hb/README.rst +++ b/samples/sensor/lps22hb/README.rst @@ -17,7 +17,7 @@ This sample uses the LPS22HB sensor controlled using the I2C interface. References ********** -- LPS22HB: http://www.st.com/en/mems-and-sensors/lps22hb.html +- LPS22HB: https://www.st.com/en/mems-and-sensors/lps22hb.html Building and Running ******************** diff --git a/samples/sensor/lps22hh/README.rst b/samples/sensor/lps22hh/README.rst index 545a6a59d48..ad0e780a076 100644 --- a/samples/sensor/lps22hh/README.rst +++ b/samples/sensor/lps22hh/README.rst @@ -17,7 +17,7 @@ This sample uses the LPS22HH sensor controlled using the I2C interface. References ********** -- LPS22HH: http://www.st.com/en/mems-and-sensors/lps22hh.html +- LPS22HH: https://www.st.com/en/mems-and-sensors/lps22hh.html Building and Running ******************** diff --git a/samples/sensor/lps22hh_i3c/README.rst b/samples/sensor/lps22hh_i3c/README.rst index 1077524037e..1f4ff486241 100644 --- a/samples/sensor/lps22hh_i3c/README.rst +++ b/samples/sensor/lps22hh_i3c/README.rst @@ -18,7 +18,7 @@ STEVALMKI192-V1 connected to the I3C header on :ref:`mimxrt685_evk`. References ********** -- LPS22HH: http://www.st.com/en/mems-and-sensors/lps22hh.html +- LPS22HH: https://www.st.com/en/mems-and-sensors/lps22hh.html Building and Running ******************** diff --git a/samples/sensor/lsm303dlhc/README.rst b/samples/sensor/lsm303dlhc/README.rst index b2da84cd413..1b8eed7c935 100644 --- a/samples/sensor/lsm303dlhc/README.rst +++ b/samples/sensor/lsm303dlhc/README.rst @@ -20,7 +20,7 @@ References ********** For more information about the LSM303DLHC eCompass module, see -http://www.st.com/en/mems-and-sensors/lsm303dlhc.html +https://www.st.com/en/mems-and-sensors/lsm303dlhc.html Building and Running ******************** diff --git a/samples/sensor/lsm6dsl/README.rst b/samples/sensor/lsm6dsl/README.rst index fb4d4d20bc8..e75cbe773db 100644 --- a/samples/sensor/lsm6dsl/README.rst +++ b/samples/sensor/lsm6dsl/README.rst @@ -20,7 +20,7 @@ It has been tested on both :ref:`96b_argonkey` and disco_l475_iot1 board. References ********** -- LSM6DSL http://www.st.com/en/mems-and-sensors/lsm6dsl.html +- LSM6DSL https://www.st.com/en/mems-and-sensors/lsm6dsl.html Building and Running ******************** diff --git a/samples/sensor/lsm6dso/README.rst b/samples/sensor/lsm6dso/README.rst index d9240d0d811..f0fda1781a4 100644 --- a/samples/sensor/lsm6dso/README.rst +++ b/samples/sensor/lsm6dso/README.rst @@ -18,7 +18,7 @@ It has been tested on the :ref:`stm32l562e_dk_board`. References ********** -- LSM6DSO http://www.st.com/en/mems-and-sensors/lsm6dso.html +- LSM6DSO https://www.st.com/en/mems-and-sensors/lsm6dso.html Building and Running ******************** diff --git a/samples/sensor/lsm6dso_i2c_on_i3c/README.rst b/samples/sensor/lsm6dso_i2c_on_i3c/README.rst index eb449879638..a4e42306d58 100644 --- a/samples/sensor/lsm6dso_i2c_on_i3c/README.rst +++ b/samples/sensor/lsm6dso_i2c_on_i3c/README.rst @@ -20,7 +20,7 @@ on :ref:`mimxrt685_evk`. References ********** -- LSM6DSO http://www.st.com/en/mems-and-sensors/lsm6dso.html +- LSM6DSO https://www.st.com/en/mems-and-sensors/lsm6dso.html Building and Running ******************** diff --git a/samples/sensor/mpu6050/src/main.c b/samples/sensor/mpu6050/src/main.c index c3151ee91ff..531a7cca873 100644 --- a/samples/sensor/mpu6050/src/main.c +++ b/samples/sensor/mpu6050/src/main.c @@ -46,7 +46,7 @@ static int process_mpu6050(const struct device *dev) gyro); } if (rc == 0) { - rc = sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, + rc = sensor_channel_get(dev, SENSOR_CHAN_DIE_TEMP, &temperature); } if (rc == 0) { diff --git a/samples/sensor/qdec/boards/esp32s3_luatos_core.overlay b/samples/sensor/qdec/boards/esp32s3_luatos_core.overlay new file mode 100644 index 00000000000..d347ea85345 --- /dev/null +++ b/samples/sensor/qdec/boards/esp32s3_luatos_core.overlay @@ -0,0 +1,44 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + */ + +#include + +/ { + aliases { + qdec0 = &pcnt; + }; +}; + +&pinctrl { + pcnt_default: pcnt_default { + group1 { + pinmux = , + ; + bias-pull-up; + }; + }; +}; + +&pcnt { + pinctrl-0 = <&pcnt_default>; + pinctrl-names = "default"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + unit0@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + filter = <100>; + channelA@0 { + reg = <0>; + sig-pos-mode = <2>; + sig-neg-mode = <1>; + ctrl-h-mode = <0>; + ctrl-l-mode = <1>; + }; + }; +}; diff --git a/samples/sensor/qdec/boards/esp32s3_luatos_core_usb.overlay b/samples/sensor/qdec/boards/esp32s3_luatos_core_usb.overlay new file mode 100644 index 00000000000..d347ea85345 --- /dev/null +++ b/samples/sensor/qdec/boards/esp32s3_luatos_core_usb.overlay @@ -0,0 +1,44 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + */ + +#include + +/ { + aliases { + qdec0 = &pcnt; + }; +}; + +&pinctrl { + pcnt_default: pcnt_default { + group1 { + pinmux = , + ; + bias-pull-up; + }; + }; +}; + +&pcnt { + pinctrl-0 = <&pcnt_default>; + pinctrl-names = "default"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + unit0@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + filter = <100>; + channelA@0 { + reg = <0>; + sig-pos-mode = <2>; + sig-neg-mode = <1>; + ctrl-h-mode = <0>; + ctrl-l-mode = <1>; + }; + }; +}; diff --git a/samples/sensor/sensor_shell/boards/tdk_robokit1.conf b/samples/sensor/sensor_shell/boards/tdk_robokit1.conf new file mode 100644 index 00000000000..aee20b8b100 --- /dev/null +++ b/samples/sensor/sensor_shell/boards/tdk_robokit1.conf @@ -0,0 +1,3 @@ +# Copyright (c) 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 +CONFIG_SPI_RTIO=y diff --git a/samples/sensor/sensor_shell/sample.yaml b/samples/sensor/sensor_shell/sample.yaml index 7b194f4d622..d89dfebc21a 100644 --- a/samples/sensor/sensor_shell/sample.yaml +++ b/samples/sensor/sensor_shell/sample.yaml @@ -4,6 +4,8 @@ tests: sample.sensor.shell: integration_platforms: - frdm_k64f + # TODO Remove once #63414 is resolved + platform_exclude: gd32l233r_eval filter: ( CONFIG_UART_CONSOLE and CONFIG_SERIAL_SUPPORT_INTERRUPT ) tags: shell harness: keyboard diff --git a/samples/sensor/vl53l0x/README.rst b/samples/sensor/vl53l0x/README.rst index 8f0b6a31984..242ddf455cc 100644 --- a/samples/sensor/vl53l0x/README.rst +++ b/samples/sensor/vl53l0x/README.rst @@ -18,7 +18,7 @@ This sample uses the VL53L0X sensor controlled using the I2C interface. References ********** - - VL53L0X: http://www.st.com/en/imaging-and-photonics-solutions/vl53l0x.html + - VL53L0X: https://www.st.com/en/imaging-and-photonics-solutions/vl53l0x.html Building and Running ******************** diff --git a/samples/shields/npm1300_ek/prj.conf b/samples/shields/npm1300_ek/prj.conf index 7b134995827..c8421d9bf0c 100644 --- a/samples/shields/npm1300_ek/prj.conf +++ b/samples/shields/npm1300_ek/prj.conf @@ -5,5 +5,6 @@ CONFIG_SHELL=y CONFIG_LOG=y CONFIG_GPIO=y CONFIG_REGULATOR=y +CONFIG_REGULATOR_SHELL=y CONFIG_SENSOR=y CONFIG_LED=y diff --git a/samples/shields/npm6001_ek/prj.conf b/samples/shields/npm6001_ek/prj.conf index bfacbe8b14b..94da7cfdaef 100644 --- a/samples/shields/npm6001_ek/prj.conf +++ b/samples/shields/npm6001_ek/prj.conf @@ -7,4 +7,5 @@ CONFIG_GETOPT=y CONFIG_GETOPT_LONG=y CONFIG_GPIO=y CONFIG_REGULATOR=y +CONFIG_REGULATOR_SHELL=y CONFIG_WATCHDOG=y diff --git a/samples/shields/x_nucleo_53l0a1/README.rst b/samples/shields/x_nucleo_53l0a1/README.rst index ddc762ed46c..403c7ebb4f9 100644 --- a/samples/shields/x_nucleo_53l0a1/README.rst +++ b/samples/shields/x_nucleo_53l0a1/README.rst @@ -1,7 +1,8 @@ -.. _x-nucleo-53l0a1-sample: +.. zephyr:code-sample:: x-nucleo-53l0a1 + :name: X-NUCLEO-53L0A1 shield + :relevant-api: sensor_interface gpio_interface -X-NUCLEO-53L0A1 ranging and gesture detection sensor expansion board -##################################################################### + Interact with the 7-segment display and VL53L0X ranging sensor of an X-NUCLEO-53L0A1 shield. Overview ******** diff --git a/samples/shields/x_nucleo_iks01a1/README.rst b/samples/shields/x_nucleo_iks01a1/README.rst index 10c9e3f75cb..58121c1f951 100644 --- a/samples/shields/x_nucleo_iks01a1/README.rst +++ b/samples/shields/x_nucleo_iks01a1/README.rst @@ -1,7 +1,8 @@ -.. _x-nucleo-iks01a1-sample: +.. zephyr:code-sample:: x-nucleo-iks01a1 + :name: X-NUCLEO-IKS01A1 shield + :relevant-api: sensor_interface -X-NUCLEO-IKS01A1: MEMS inertial and environmental multi-sensor shield -##################################################################### + Interact with all the sensors of an X-NUCLEO-IKS01A1 shield. Overview ******** @@ -27,7 +28,7 @@ does not yet support sensors multiple instances. References ********** --X-NUCLEO-IKS01A1: http://www.st.com/en/ecosystems/x-nucleo-iks01a1.html +-X-NUCLEO-IKS01A1: https://www.st.com/en/ecosystems/x-nucleo-iks01a1.html Building and Running ******************** diff --git a/samples/shields/x_nucleo_iks01a2/sensorhub/README.rst b/samples/shields/x_nucleo_iks01a2/sensorhub/README.rst index a1ae62691a9..5b97f057172 100644 --- a/samples/shields/x_nucleo_iks01a2/sensorhub/README.rst +++ b/samples/shields/x_nucleo_iks01a2/sensorhub/README.rst @@ -1,7 +1,8 @@ -.. _x-nucleo-iks01a2-shub-sample: +.. zephyr:code-sample:: x-nucleo-iks01a2-shub + :name: X-NUCLEO-IKS01A2 shield - SensorHub (Mode 2) + :relevant-api: sensor_interface -X-NUCLEO-IKS01A2: shield SensorHub (Mode 2) sample -################################################## + Interact with all the sensors of an X-NUCLEO-IKS01A2 shield using Sensor Hub mode. Overview ******** @@ -35,7 +36,7 @@ does not yet support sensors multiple instances. References ********** --X-NUCLEO-IKS01A2: http://www.st.com/en/ecosystems/x-nucleo-iks01a2.html +-X-NUCLEO-IKS01A2: https://www.st.com/en/ecosystems/x-nucleo-iks01a2.html Building and Running ******************** diff --git a/samples/shields/x_nucleo_iks01a2/standard/README.rst b/samples/shields/x_nucleo_iks01a2/standard/README.rst index a31a7a75b4d..ccfedc1cfcb 100644 --- a/samples/shields/x_nucleo_iks01a2/standard/README.rst +++ b/samples/shields/x_nucleo_iks01a2/standard/README.rst @@ -1,7 +1,8 @@ -.. _x-nucleo-iks01a2-std-sample: +.. zephyr:code-sample:: x-nucleo-iks01a2-std + :name: X-NUCLEO-IKS01A2 shield - Standard (Mode 1) + :relevant-api: sensor_interface -X-NUCLEO-IKS01A2: shield Standard (Mode 1) sample -################################################# + Interact with all the sensors of an X-NUCLEO-IKS01A2 shield using Standard Mode. Overview ******** @@ -31,7 +32,7 @@ does not yet support sensors multiple instances. References ********** --X-NUCLEO-IKS01A2: http://www.st.com/en/ecosystems/x-nucleo-iks01a2.html +-X-NUCLEO-IKS01A2: https://www.st.com/en/ecosystems/x-nucleo-iks01a2.html Building and Running ******************** diff --git a/samples/shields/x_nucleo_iks01a3/sensorhub/README.rst b/samples/shields/x_nucleo_iks01a3/sensorhub/README.rst index 45299badd6b..ddd06b483a1 100644 --- a/samples/shields/x_nucleo_iks01a3/sensorhub/README.rst +++ b/samples/shields/x_nucleo_iks01a3/sensorhub/README.rst @@ -1,7 +1,8 @@ -.. _x-nucleo-iks01a3-shub-sample: +.. zephyr:code-sample:: x-nucleo-iks01a3-shub + :name: X-NUCLEO-IKS01A3 shield - SensorHub (Mode 2) + :relevant-api: sensor_interface -X-NUCLEO-IKS01A3: shield (Mode 2) sample -######################################## + Interact with all the sensors of an X-NUCLEO-IKS01A3 shield using Sensor Hub mode. Overview ******** @@ -45,7 +46,7 @@ as sensors multiple instances are not supported. References ********** -- X-NUCLEO-IKS01A3: http://www.st.com/en/ecosystems/x-nucleo-iks01a3.html +- X-NUCLEO-IKS01A3: https://www.st.com/en/ecosystems/x-nucleo-iks01a3.html Building and Running ******************** diff --git a/samples/shields/x_nucleo_iks01a3/standard/README.rst b/samples/shields/x_nucleo_iks01a3/standard/README.rst index fdca7db1d0b..03213d0006c 100644 --- a/samples/shields/x_nucleo_iks01a3/standard/README.rst +++ b/samples/shields/x_nucleo_iks01a3/standard/README.rst @@ -1,7 +1,8 @@ -.. _x-nucleo-iks01a3-std-sample: +.. zephyr:code-sample:: x-nucleo-iks01a3-std + :name: X-NUCLEO-IKS01A3 shield - Standard (Mode 1) + :relevant-api: sensor_interface -X-NUCLEO-IKS01A3: shield Standard (Mode 1) sample -################################################# + Interact with all the sensors of an X-NUCLEO-IKS01A3 shield using Standard mode. Overview ******** @@ -38,7 +39,7 @@ as sensors multiple instances are not supported. References ********** -- X-NUCLEO-IKS01A3: http://www.st.com/en/ecosystems/x-nucleo-iks01a3.html +- X-NUCLEO-IKS01A3: https://www.st.com/en/ecosystems/x-nucleo-iks01a3.html Building and Running ******************** diff --git a/samples/shields/x_nucleo_iks02a1/microphone/README.rst b/samples/shields/x_nucleo_iks02a1/microphone/README.rst index 7740f521b9b..adc6831c81d 100644 --- a/samples/shields/x_nucleo_iks02a1/microphone/README.rst +++ b/samples/shields/x_nucleo_iks02a1/microphone/README.rst @@ -1,7 +1,8 @@ -.. _x-nucleo-iks02a1-mic-sample: +.. zephyr:code-sample:: x-nucleo-iks02a1-mic + :name: X-NUCLEO-IKS02A1 shield - MEMS microphone + :relevant-api: audio_dmic_interface -X-NUCLEO-IKS02A1 shield: Acquire MEMS microphones data -###################################################### + Acquire audio using the digital MEMS microphone on X-NUCLEO-IKS02A1 shield. Overview ******** @@ -9,7 +10,7 @@ This sample enables the digital MEMS microphone on X-NUCLEO-IKS02A1 shields This sample provides an example of how to acquire audio through -the digital MEMS microphones on X-NUCLEO-IKS02A1 shield. +the digital MEMS microphone on X-NUCLEO-IKS02A1 shield. The microphone generates a PDM stream which is acquired through I2S. The PDM stream is then converted to PCM using the OpenPDM2PCM library available in zephyrproject/modules/hal/st/audio/microphone. diff --git a/samples/shields/x_nucleo_iks02a1/sensorhub/README.rst b/samples/shields/x_nucleo_iks02a1/sensorhub/README.rst index 9032b014321..e8b17efc65c 100644 --- a/samples/shields/x_nucleo_iks02a1/sensorhub/README.rst +++ b/samples/shields/x_nucleo_iks02a1/sensorhub/README.rst @@ -1,7 +1,8 @@ -.. _x-nucleo-iks02a1-shub-sample: +.. zephyr:code-sample:: x-nucleo-iks02a1-shub + :name: X-NUCLEO-IKS02A1 shield - SensorHub (Mode 2) + :relevant-api: sensor_interface -X-NUCLEO-IKS02A1 shield: Sensorhub (Mode 2) sample -################################################## + Interact with all the sensors of an X-NUCLEO-IKS02A1 shield using Sensor Hub mode. Overview ******** @@ -40,7 +41,7 @@ as sensors multiple instances are not supported. References ********** -- X-NUCLEO-IKS02A1: http://www.st.com/en/ecosystems/x-nucleo-iks02a1.html +- X-NUCLEO-IKS02A1: https://www.st.com/en/ecosystems/x-nucleo-iks02a1.html Building and Running ******************** diff --git a/samples/shields/x_nucleo_iks02a1/standard/README.rst b/samples/shields/x_nucleo_iks02a1/standard/README.rst index a9043eeb8e0..faa60e8387a 100644 --- a/samples/shields/x_nucleo_iks02a1/standard/README.rst +++ b/samples/shields/x_nucleo_iks02a1/standard/README.rst @@ -1,7 +1,8 @@ -.. _x-nucleo-iks02a1-std-sample: +.. zephyr:code-sample:: x-nucleo-iks02a1-std + :name: X-NUCLEO-IKS02A1 shield - Standard (Mode 1) + :relevant-api: sensor_interface -X-NUCLEO-IKS02A1 shield: Standard (Mode 1) sample -################################################# + Interact with all the sensors of an X-NUCLEO-IKS02A1 shield using Standard mode. Overview ******** @@ -35,7 +36,7 @@ as sensors multiple instances are not supported. References ********** -- X-NUCLEO-IKS02A1: http://www.st.com/en/ecosystems/x-nucleo-iks02a1.html +- X-NUCLEO-IKS02A1: https://www.st.com/en/ecosystems/x-nucleo-iks02a1.html Building and Running ******************** diff --git a/samples/subsys/bindesc/bindesc.rst b/samples/subsys/bindesc/bindesc.rst new file mode 100644 index 00000000000..105d6f80dc8 --- /dev/null +++ b/samples/subsys/bindesc/bindesc.rst @@ -0,0 +1,10 @@ +.. _bindesc_samples: + +Binary Descriptor Samples +######################### + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* diff --git a/samples/subsys/bindesc/hello_bindesc/CMakeLists.txt b/samples/subsys/bindesc/hello_bindesc/CMakeLists.txt new file mode 100644 index 00000000000..3e70363ba31 --- /dev/null +++ b/samples/subsys/bindesc/hello_bindesc/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(hello_bindesc) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/subsys/bindesc/hello_bindesc/README.rst b/samples/subsys/bindesc/hello_bindesc/README.rst new file mode 100644 index 00000000000..0596639b518 --- /dev/null +++ b/samples/subsys/bindesc/hello_bindesc/README.rst @@ -0,0 +1,32 @@ +.. zephyr:code-sample:: hello-bindesc + :name: Binary descriptors "Hello World" + :relevant-api: bindesc_define + + Set and access binary descriptors for a basic Zephyr application. + +Overview +******** + +A simple sample of :ref:`binary descriptor ` definition and usage. + +Building and Running +******************** + +Follow these steps to build the ``hello_bindesc`` sample application: + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/bindesc/hello_bindesc + :board: + :goals: build + :compact: + +To dump all binary descriptors in the image, run: + +.. code-block:: bash + + west bindesc dump build/zephyr/zephyr.bin + +(Note: you can also dump the contents of ``zephyr.elf``, if your build system +does not produce a ``*.bin`` file, e.g. compiling for ``native_sim``.) + +For more details see :ref:`binary_descriptors` and :ref:`west-bindesc`. diff --git a/samples/subsys/bindesc/hello_bindesc/VERSION b/samples/subsys/bindesc/hello_bindesc/VERSION new file mode 100644 index 00000000000..16a13732e3a --- /dev/null +++ b/samples/subsys/bindesc/hello_bindesc/VERSION @@ -0,0 +1,5 @@ +VERSION_MAJOR = 1 +VERSION_MINOR = 0 +PATCHLEVEL = 0 +VERSION_TWEAK = 0 +EXTRAVERSION = diff --git a/samples/subsys/bindesc/hello_bindesc/prj.conf b/samples/subsys/bindesc/hello_bindesc/prj.conf new file mode 100644 index 00000000000..0b22906d9f5 --- /dev/null +++ b/samples/subsys/bindesc/hello_bindesc/prj.conf @@ -0,0 +1,21 @@ +# Enable binary descriptors +CONFIG_BINDESC=y + +# Enable definition of binary descriptors +CONFIG_BINDESC_DEFINE=y + +# Enable default build time binary descriptors +CONFIG_BINDESC_DEFINE_BUILD_TIME=y +CONFIG_BINDESC_BUILD_DATE_TIME_STRING=y + +# Enable default version binary descriptors +CONFIG_BINDESC_DEFINE_VERSION=y +CONFIG_BINDESC_KERNEL_VERSION_STRING=y +CONFIG_BINDESC_KERNEL_VERSION_MAJOR=y + +CONFIG_BINDESC_APP_VERSION_STRING=y + +# Enable default host info binary descriptors +CONFIG_BINDESC_DEFINE_HOST_INFO=y +CONFIG_BINDESC_C_COMPILER_NAME=y +CONFIG_BINDESC_C_COMPILER_VERSION=y diff --git a/samples/subsys/bindesc/hello_bindesc/sample.yaml b/samples/subsys/bindesc/hello_bindesc/sample.yaml new file mode 100644 index 00000000000..2725b9ab241 --- /dev/null +++ b/samples/subsys/bindesc/hello_bindesc/sample.yaml @@ -0,0 +1,20 @@ +sample: + name: Hello Bindesc +tests: + sample.bindesc: + tags: bindesc + filter: CONFIG_ARCH_SUPPORTS_ROM_START or CONFIG_ARCH_POSIX + integration_platforms: + - native_sim + harness: console + harness_config: + type: multi_line + ordered: true + regex: + - "Zephyr version: " + - "App version: 1.0.0" + - "Build time: " + - "Compiler: " + - "my_string: Hello world!" + - "my_int: 5" + - "my_bytes: 01 02 03 04" diff --git a/samples/subsys/bindesc/hello_bindesc/src/main.c b/samples/subsys/bindesc/hello_bindesc/src/main.c new file mode 100644 index 00000000000..22837247d8d --- /dev/null +++ b/samples/subsys/bindesc/hello_bindesc/src/main.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +BINDESC_STR_DEFINE(my_string, 1, "Hello world!"); +BINDESC_UINT_DEFINE(my_int, 2, 5); +BINDESC_BYTES_DEFINE(my_bytes, 3, ({1, 2, 3, 4})); + +int main(void) +{ + size_t i; + + /* Builtin descriptors */ + printk("Zephyr version: %s\n", BINDESC_GET_STR(kernel_version_string)); + printk("App version: %s\n", BINDESC_GET_STR(app_version_string)); + printk("Build time: %s\n", BINDESC_GET_STR(build_date_time_string)); + printk("Compiler: %s %s\n", BINDESC_GET_STR(c_compiler_name), + BINDESC_GET_STR(c_compiler_version)); + + /* Custom descriptors */ + printk("my_string: %s\n", BINDESC_GET_STR(my_string)); + printk("my_int: %d\n", BINDESC_GET_UINT(my_int)); + printk("my_bytes: "); + for (i = 0; i < BINDESC_GET_SIZE(my_bytes); i++) { + printk("%02x ", BINDESC_GET_BYTES(my_bytes)[i]); + } + printk("\n"); + + return 0; +} diff --git a/samples/subsys/canbus/isotp/Kconfig b/samples/subsys/canbus/isotp/Kconfig index ba9b4bc25d6..9fd282d2282 100644 --- a/samples/subsys/canbus/isotp/Kconfig +++ b/samples/subsys/canbus/isotp/Kconfig @@ -22,4 +22,12 @@ config SAMPLE_RX_THREAD_PRIORITY help Priority used for the RX threads. +config SAMPLE_CAN_FD_MODE + bool "Use CAN FD" + select CAN_FD_MODE + +config ISOTP_RX_BUF_COUNT + default 4 if SAMPLE_CAN_FD_MODE + default 2 + source "Kconfig.zephyr" diff --git a/samples/subsys/canbus/isotp/README.rst b/samples/subsys/canbus/isotp/README.rst index 378ecd03e4e..4a9d2019bc5 100644 --- a/samples/subsys/canbus/isotp/README.rst +++ b/samples/subsys/canbus/isotp/README.rst @@ -1,14 +1,17 @@ -.. _isotp-sample: +.. zephyr:code-sample:: isotp + :name: ISO-TP library + :relevant-api: can_isotp -ISO-TP library -############## + Use ISO-TP library to exchange messages between two boards. Overview ******** -This sample demonstrates how to use the ISO-TP library. +This sample demonstrates how to use the :ref:`ISO-TP library `. + Messages are exchanged between two boards. A long message, that is sent with -a block-size (BS) of eight frames, and a short one that has an minimal +a block-size (BS) of eight frames, and a short one that has a minimal separation-time (STmin) of five milliseconds. + The send function call for the short message is non-blocking, and the send function call for the long message is blocking. diff --git a/samples/subsys/canbus/isotp/prj.conf b/samples/subsys/canbus/isotp/prj.conf index 73c988ad91b..04c9fc95d13 100644 --- a/samples/subsys/canbus/isotp/prj.conf +++ b/samples/subsys/canbus/isotp/prj.conf @@ -4,9 +4,5 @@ CONFIG_CAN=y CONFIG_CAN_MAX_FILTER=8 CONFIG_ISOTP=y -CONFIG_ISOTP_RX_BUF_COUNT=2 -#A frame has 7 bytes payload, we are using a BS of 8 and need one char for the -#string termination (7 * 8 + 1 = 57) -CONFIG_ISOTP_RX_BUF_SIZE=57 -#We have two receiving contexts that are bound to a single address. +# We have two receiving contexts that are bound to a single address. CONFIG_ISOTP_RX_SF_FF_BUF_COUNT=2 diff --git a/samples/subsys/canbus/isotp/sample.yaml b/samples/subsys/canbus/isotp/sample.yaml index dd9fadb0dea..0036552b67b 100644 --- a/samples/subsys/canbus/isotp/sample.yaml +++ b/samples/subsys/canbus/isotp/sample.yaml @@ -14,3 +14,21 @@ tests: type: one_line regex: - "(.*)Got 247 bytes in total" + sample.subsys.canbus.isotp.fd: + tags: + - can + - isotp + depends_on: can + extra_configs: + - CONFIG_SAMPLE_LOOPBACK_MODE=y + - CONFIG_SAMPLE_CAN_FD_MODE=y + platform_allow: + - native_posix + - native_posix_64 + - native_sim + - native_sim_64 + harness: console + harness_config: + type: one_line + regex: + - "(.*)Got 247 bytes in total" diff --git a/samples/subsys/canbus/isotp/src/main.c b/samples/subsys/canbus/isotp/src/main.c index 8fbd43e28ac..8005a68c07d 100644 --- a/samples/subsys/canbus/isotp/src/main.c +++ b/samples/subsys/canbus/isotp/src/main.c @@ -12,23 +12,29 @@ const struct isotp_fc_opts fc_opts_0_5 = {.bs = 0, .stmin = 5}; const struct isotp_msg_id rx_addr_8_0 = { .std_id = 0x80, - .ide = 0, - .use_ext_addr = 0 +#ifdef CONFIG_SAMPLE_CAN_FD_MODE + .flags = ISOTP_MSG_FDF | ISOTP_MSG_BRS, +#endif }; const struct isotp_msg_id tx_addr_8_0 = { .std_id = 0x180, - .ide = 0, - .use_ext_addr = 0 +#ifdef CONFIG_SAMPLE_CAN_FD_MODE + .dl = 64, + .flags = ISOTP_MSG_FDF | ISOTP_MSG_BRS, +#endif }; const struct isotp_msg_id rx_addr_0_5 = { .std_id = 0x01, - .ide = 0, - .use_ext_addr = 0 +#ifdef CONFIG_SAMPLE_CAN_FD_MODE + .flags = ISOTP_MSG_FDF | ISOTP_MSG_BRS, +#endif }; const struct isotp_msg_id tx_addr_0_5 = { .std_id = 0x101, - .ide = 0, - .use_ext_addr = 0 +#ifdef CONFIG_SAMPLE_CAN_FD_MODE + .dl = 64, + .flags = ISOTP_MSG_FDF | ISOTP_MSG_BRS, +#endif }; const struct device *can_dev; @@ -57,8 +63,6 @@ void rx_8_0_thread(void *arg1, void *arg2, void *arg3) ARG_UNUSED(arg3); int ret, rem_len, received_len; struct net_buf *buf; - static uint8_t rx_buffer[7]; - ret = isotp_bind(&recv_ctx_8_0, can_dev, &tx_addr_8_0, &rx_addr_8_0, @@ -79,19 +83,11 @@ void rx_8_0_thread(void *arg1, void *arg2, void *arg3) break; } - received_len += buf->len; - if (net_buf_tailroom(buf) >= 1) { - net_buf_add_u8(buf, '\0'); - printk("%s", buf->data); - } else if (buf->len == 6) { - /* First frame does not have tailroom.*/ - memcpy(rx_buffer, buf->data, 6); - rx_buffer[6] = '\0'; - printk("%s", rx_buffer); - } else { - printk("No tailroom for string termination\n"); + while (buf != NULL) { + received_len += buf->len; + printk("%.*s", buf->len, buf->data); + buf = net_buf_frag_del(NULL, buf); } - net_buf_unref(buf); } while (rem_len); printk("Got %d bytes in total\n", received_len); } @@ -150,13 +146,13 @@ int main(void) return 0; } -#ifdef CONFIG_SAMPLE_LOOPBACK_MODE - ret = can_set_mode(can_dev, CAN_MODE_LOOPBACK); + can_mode_t mode = (IS_ENABLED(CONFIG_SAMPLE_LOOPBACK_MODE) ? CAN_MODE_LOOPBACK : 0) | + (IS_ENABLED(CONFIG_SAMPLE_CAN_FD_MODE) ? CAN_MODE_FD : 0); + ret = can_set_mode(can_dev, mode); if (ret != 0) { - printk("CAN: Failed to set loopback mode [%d]", ret); + printk("CAN: Failed to set mode [%d]", ret); return 0; } -#endif /* CONFIG_SAMPLE_LOOPBACK_MODE */ ret = can_start(can_dev); if (ret != 0) { diff --git a/samples/subsys/console/getchar/README.rst b/samples/subsys/console/getchar/README.rst index eddfb83671f..54dc7e8fc48 100644 --- a/samples/subsys/console/getchar/README.rst +++ b/samples/subsys/console/getchar/README.rst @@ -1,7 +1,7 @@ -.. _console_getchar_sample: +.. zephyr:code-sample:: console_getchar + :name: console_getchar() -console_getchar() Sample Application -#################################### + Use console_getchar() to read an input character from the console. Overview ******** @@ -15,7 +15,7 @@ process console input character by character. The sample also allows to see key/character codes as returned by the function. If you are interested in line by line console input, see -:ref:`console_getline_sample`. +:zephyr:code-sample:`console_getline`. Requirements diff --git a/samples/subsys/console/getline/README.rst b/samples/subsys/console/getline/README.rst index f10cbf791c1..6c7e05f4f8d 100644 --- a/samples/subsys/console/getline/README.rst +++ b/samples/subsys/console/getline/README.rst @@ -1,7 +1,7 @@ -.. _console_getline_sample: +.. zephyr:code-sample:: console_getline + :name: console_getline() -console_getline() Sample Application -#################################### + Use console_getline() to read an input line from the console. Overview ******** @@ -15,7 +15,7 @@ console input line by line. The sample also allows to see details of how a line is returned by the function. If you are interested in character by character console input, see -:ref:`console_getchar_sample`. +:zephyr:code-sample:`console_getchar`. Requirements diff --git a/samples/subsys/debug/debugmon/src/main.c b/samples/subsys/debug/debugmon/src/main.c index a05bb2b4117..9029cc44ae7 100644 --- a/samples/subsys/debug/debugmon/src/main.c +++ b/samples/subsys/debug/debugmon/src/main.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #define LED0_NODE DT_ALIAS(led0) static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios); diff --git a/samples/subsys/debug/gdbstub/CMakeLists.txt b/samples/subsys/debug/gdbstub/CMakeLists.txt deleted file mode 100644 index 9759ca6c7f0..00000000000 --- a/samples/subsys/debug/gdbstub/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) - -if(BOARD MATCHES "qemu_x86") - list(APPEND QEMU_EXTRA_FLAGS -serial tcp:127.0.0.1:5678,server) -endif() - -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(debug) - -target_sources(app PRIVATE src/main.c) diff --git a/samples/subsys/debug/gdbstub/README.rst b/samples/subsys/debug/gdbstub/README.rst deleted file mode 100644 index b2f6af74b96..00000000000 --- a/samples/subsys/debug/gdbstub/README.rst +++ /dev/null @@ -1,31 +0,0 @@ -.. _gdb_debug_sample: - -GDB Debug Sample -################ - -Overview -******** - -A simple sample that can be used with QEMU to show debug using GDB -Remote Serial Protocol (RSP) capabilities. - -Building and Running -******************** - -This application can be built and executed on QEMU as follows: - -.. zephyr-app-commands:: - :zephyr-app: samples/subsys/debug/gdbstub - :host-os: unix - :board: qemu_x86 - :goals: run - :compact: - -Open a new terminal and use gdb to connect to the running qemu as follows: - -.. code-block:: bash - - gdb build/zephyr/zephyr.elf - (gdb) target remote :5678 - -Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`. diff --git a/samples/subsys/debug/gdbstub/boards/qemu_x86_64.overlay b/samples/subsys/debug/gdbstub/boards/qemu_x86_64.overlay deleted file mode 100644 index e6c560fae72..00000000000 --- a/samples/subsys/debug/gdbstub/boards/qemu_x86_64.overlay +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 */ - -/ { - chosen { - zephyr,gdbstub-uart = &uart1; - }; -}; diff --git a/samples/subsys/debug/gdbstub/prj.conf b/samples/subsys/debug/gdbstub/prj.conf deleted file mode 100644 index da68f3823c4..00000000000 --- a/samples/subsys/debug/gdbstub/prj.conf +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG_GDBSTUB=y -CONFIG_NO_OPTIMIZATIONS=y -CONFIG_USERSPACE=y -CONFIG_KOBJECT_TEXT_AREA=4096 diff --git a/samples/subsys/debug/gdbstub/run.gdbinit b/samples/subsys/debug/gdbstub/run.gdbinit deleted file mode 100644 index 49181157ae2..00000000000 --- a/samples/subsys/debug/gdbstub/run.gdbinit +++ /dev/null @@ -1,17 +0,0 @@ -set pagination off -symbol-file zephyr/zephyr.elf -target remote 127.0.0.1:1234 -b test -b main.c:33 -c - -s -set var a = 2 -c -if ret == 6 - printf "PASSED\n" - quit 0 -else - printf "FAILED\n" - quit 1 -end diff --git a/samples/subsys/debug/gdbstub/sample.yaml b/samples/subsys/debug/gdbstub/sample.yaml deleted file mode 100644 index 5f75a801541..00000000000 --- a/samples/subsys/debug/gdbstub/sample.yaml +++ /dev/null @@ -1,15 +0,0 @@ -# -# Copyright (c) 2020 intel Corporation. -# -# SPDX-License-Identifier: Apache-2.0 -# - -sample: - name: gdbstub sample -tests: - sample.debug.gdbstub: - build_only: true - platform_allow: qemu_x86 - tags: - - debug - - gdbstub diff --git a/samples/subsys/debug/gdbstub/src/main.c b/samples/subsys/debug/gdbstub/src/main.c deleted file mode 100644 index 51995db4ab7..00000000000 --- a/samples/subsys/debug/gdbstub/src/main.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2020 Intel Corporation. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -#define STACKSIZE 512 - -static int test(void) -{ - int a; - int b; - - a = 10; - b = a * 2; - - return a + b; -} - -static void thread_entry(void *p1, void *p2, void *p3) -{ - printk("Hello from user thread!\n"); -} - -int main(void) -{ - int ret; - - ret = test(); - printk("%d\n", ret); - return 0; -} - -K_THREAD_DEFINE(thread, STACKSIZE, thread_entry, NULL, NULL, NULL, - 7, K_USER, 0); diff --git a/samples/subsys/display/cfb/README.rst b/samples/subsys/display/cfb/README.rst index 8e9a71de3a4..093fed8f11c 100644 --- a/samples/subsys/display/cfb/README.rst +++ b/samples/subsys/display/cfb/README.rst @@ -1,7 +1,8 @@ -.. _character_frame_buffer_sample: +.. zephyr:code-sample:: character-frame-buffer + :name: Character frame buffer + :relevant-api: monochrome_character_framebuffer -Character frame buffer -###################### + Display character strings using the Character Frame Buffer (CFB). Overview ******** diff --git a/samples/subsys/display/cfb_custom_font/README.rst b/samples/subsys/display/cfb_custom_font/README.rst index 369f22236b1..1e5dea47535 100644 --- a/samples/subsys/display/cfb_custom_font/README.rst +++ b/samples/subsys/display/cfb_custom_font/README.rst @@ -1,7 +1,8 @@ -.. _cfb_custom_fonts: +.. zephyr:code-sample:: cfb-custom-fonts + :name: Custom fonts + :relevant-api: monochrome_character_framebuffer -Custom Fonts -############ + Generate and use a custom font. Overview ******** diff --git a/samples/subsys/display/cfb_shell/README.rst b/samples/subsys/display/cfb_shell/README.rst index e17422015ab..3e118aba9a4 100644 --- a/samples/subsys/display/cfb_shell/README.rst +++ b/samples/subsys/display/cfb_shell/README.rst @@ -1,7 +1,8 @@ -.. _cfb_shell_sample: +.. zephyr:code-sample:: cfb-shell-sample + :name: Character Framebuffer shell module + :relevant-api: monochrome_character_framebuffer -Character Framebuffer Shell Module Sample -######################################### + Use the CFB shell module to interact with a monochrome display. Overview ******** diff --git a/samples/subsys/display/lvgl/README.rst b/samples/subsys/display/lvgl/README.rst index fde1d2780ec..84bb5fdb40b 100644 --- a/samples/subsys/display/lvgl/README.rst +++ b/samples/subsys/display/lvgl/README.rst @@ -1,7 +1,8 @@ -.. _lvgl-sample: +.. zephyr:code-sample:: lvgl + :name: LVGL basic sample + :relevant-api: display_interface -LVGL Basic Sample -################# + Display "Hello World" and a dynamic counter using LVGL. Overview ******** @@ -26,9 +27,9 @@ or a board with an integrated display: - :ref:`esp_wrover_kit` -or a simulated display environment in a native Posix application: +or a simulated display environment in a :ref:`native_sim ` application: -- :ref:`native_posix` +- :ref:`native_sim` - `SDL2`_ or @@ -52,15 +53,15 @@ Example building for :ref:`nrf52840dk_nrf52840`: :shield: adafruit_2_8_tft_touch_v2 :goals: build flash -Example building for :ref:`native_posix`: +Example building for :ref:`native_sim `: .. zephyr-app-commands:: :zephyr-app: samples/subsys/display/lvgl - :board: native_posix + :board: native_sim :goals: build run Alternatively, if building from a 64-bit host machine, the previous target -board argument may also be replaced by ``native_posix_64``. +board argument may also be replaced by ``native_sim_64``. References ********** diff --git a/samples/subsys/display/lvgl/boards/m5stack_core2.conf b/samples/subsys/display/lvgl/boards/m5stack_core2.conf new file mode 100644 index 00000000000..1ac2b1c55c9 --- /dev/null +++ b/samples/subsys/display/lvgl/boards/m5stack_core2.conf @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_MAIN_STACK_SIZE=4096 diff --git a/samples/subsys/display/lvgl/boards/native_posix.overlay b/samples/subsys/display/lvgl/boards/native_posix.overlay index d0cf42da662..43cc9818d5a 100644 --- a/samples/subsys/display/lvgl/boards/native_posix.overlay +++ b/samples/subsys/display/lvgl/boards/native_posix.overlay @@ -11,6 +11,15 @@ sw0 = &button0; }; + qdec { + compatible = "gpio-qdec"; + gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>, <&gpio0 5 GPIO_ACTIVE_HIGH>; + steps-per-period = <4>; + zephyr,axis = ; + sample-time-us = <2000>; + idle-timeout-ms = <200>; + }; + keys: keys { compatible = "gpio-keys"; button0: button0 { @@ -23,6 +32,11 @@ gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>; zephyr,code = ; }; + + encoder_button: encoder_button { + gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>; + zephyr,code = ; + }; }; lvgl_button_input { @@ -31,15 +45,21 @@ input-codes = ; coordinates = <160 120>; }; + + lvgl_encoder_input { + compatible = "zephyr,lvgl-encoder-input"; + rotation-input-code = ; + button-input-code = ; + }; }; &gpio0 { - ngpios = <3>; + ngpios = <6>; sdl_gpio { status = "okay"; compatible = "zephyr,gpio-emul-sdl"; /* Skip pin 0 with the unknown code 0 */ - scancodes = <0 21 5>; + scancodes = <0 21 5 30 31 32>; }; }; diff --git a/samples/subsys/display/lvgl/prj.conf b/samples/subsys/display/lvgl/prj.conf index 87a03f57cc0..41c0eca6e70 100644 --- a/samples/subsys/display/lvgl/prj.conf +++ b/samples/subsys/display/lvgl/prj.conf @@ -1,4 +1,4 @@ -CONFIG_LV_Z_MEM_POOL_NUMBER_BLOCKS=8 +CONFIG_LV_Z_MEM_POOL_SIZE=16384 CONFIG_LV_Z_SHELL=y CONFIG_MAIN_STACK_SIZE=2048 @@ -13,6 +13,7 @@ CONFIG_LV_MEM_CUSTOM=y CONFIG_LV_USE_LOG=y CONFIG_LV_USE_LABEL=y CONFIG_LV_USE_BTN=y +CONFIG_LV_USE_ARC=y CONFIG_LV_USE_IMG=y CONFIG_LV_USE_MONKEY=y CONFIG_LV_FONT_MONTSERRAT_14=y diff --git a/samples/subsys/display/lvgl/sample.yaml b/samples/subsys/display/lvgl/sample.yaml index 5329ba5d90c..c57ab87122b 100644 --- a/samples/subsys/display/lvgl/sample.yaml +++ b/samples/subsys/display/lvgl/sample.yaml @@ -19,4 +19,24 @@ tests: modules: - lvgl integration_platforms: - - native_posix_64 + - native_sim_64 + sample.display.lvgl.rk055hdmipi4m: + # This sample is intended to test the RT1170 and RT595, which require + # a display shield to work with LVGL + min_flash: 250 + # The minimum RAM needed for this display is actually around 8MB, + # but the RT595 uses external PSRAM for the display buffer + min_ram: 32 + harness: none + tags: + - samples + - display + - gui + modules: + - lvgl + extra_args: SHIELD="rk055hdmipi4m" + platform_allow: + - mimxrt1170_evk_cm7 + - mimxrt595_evk_cm33 + integration_platforms: + - mimxrt1170_evk_cm7 diff --git a/samples/subsys/display/lvgl/src/main.c b/samples/subsys/display/lvgl/src/main.c index 2fd3592dbab..d58be550278 100644 --- a/samples/subsys/display/lvgl/src/main.c +++ b/samples/subsys/display/lvgl/src/main.c @@ -12,6 +12,7 @@ #include #include #include +#include #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL #include @@ -34,7 +35,19 @@ static void button_isr_callback(const struct device *port, count = 0; } -#endif +#endif /* CONFIG_GPIO */ + +#ifdef CONFIG_LV_Z_ENCODER_INPUT +static const struct device *lvgl_encoder = + DEVICE_DT_GET(DT_COMPAT_GET_ANY_STATUS_OKAY(zephyr_lvgl_encoder_input)); +#endif /* CONFIG_LV_Z_ENCODER_INPUT */ + +static void lv_btn_click_callback(lv_event_t *e) +{ + ARG_UNUSED(e); + + count = 0; +} int main(void) { @@ -75,13 +88,28 @@ int main(void) return 0; } } -#endif +#endif /* CONFIG_GPIO */ + +#ifdef CONFIG_LV_Z_ENCODER_INPUT + lv_obj_t *arc; + lv_group_t *arc_group; + + arc = lv_arc_create(lv_scr_act()); + lv_obj_align(arc, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_size(arc, 150, 150); + + arc_group = lv_group_create(); + lv_group_add_obj(arc_group, arc); + lv_indev_set_group(lvgl_input_get_indev(lvgl_encoder), arc_group); +#endif /* CONFIG_LV_Z_ENCODER_INPUT */ if (IS_ENABLED(CONFIG_LV_Z_POINTER_KSCAN) || IS_ENABLED(CONFIG_LV_Z_POINTER_INPUT)) { lv_obj_t *hello_world_button; hello_world_button = lv_btn_create(lv_scr_act()); lv_obj_align(hello_world_button, LV_ALIGN_CENTER, 0, 0); + lv_obj_add_event_cb(hello_world_button, lv_btn_click_callback, LV_EVENT_CLICKED, + NULL); hello_world_label = lv_label_create(hello_world_button); } else { hello_world_label = lv_label_create(lv_scr_act()); diff --git a/samples/subsys/edac/README.rst b/samples/subsys/edac/README.rst index c47f93ef804..fb556b1c07b 100644 --- a/samples/subsys/edac/README.rst +++ b/samples/subsys/edac/README.rst @@ -1,26 +1,32 @@ -.. _samples_edac: +.. zephyr:code-sample:: edac + :name: EDAC shell + :relevant-api: edac -EDAC Shell Sample -################# + Test error detection and correction (EDAC) using shell commands. Overview ******** -This sample demonstrates the EDAC driver API in a simple EDAC shell sample. +This sample demonstrates the :ref:`EDAC driver API ` in a simple EDAC shell sample. Building and Running ******************** -This project can be built and executed on as following example for the -:ref:`intel_ehl_crb` board: +This sample can be found under :zephyr_file:`samples/subsys/edac` in the +Zephyr tree. +The sample can be built as follows for the :ref:`intel_ehl_crb` board: .. zephyr-app-commands:: :zephyr-app: samples/subsys/edac :host-os: unix :board: intel_ehl_crb - :goals: run + :goals: build :compact: +The Zephyr image that's created can be run on the :ref:`intel_ehl_crb` board +as per the instructions in the board documentation. Check out the +:ref:`intel_ehl_crb` for details. + Sample output ************* @@ -28,7 +34,9 @@ Getting help ============ After the application has started help can be read with the following -command:: +command: + +.. code-block:: console uart:~$ edac -h edac - EDAC information @@ -38,7 +46,9 @@ command:: inject :Inject ECC error commands edac inject -Help for subcommand info can be read with:: +Help for subcommand info can be read with: + +.. code-block:: console uart:~$ edac info -h info - Show EDAC information @@ -47,7 +57,9 @@ Help for subcommand info can be read with:: ecc_error :ECC Error Show / Clear commands parity_error :Parity Error Show / Clear commands -Injection help can be received with:: +Injection help can be received with: + +.. code-block:: console uart:~$ edac inject -h inject - Inject ECC error commands @@ -64,7 +76,9 @@ Injection help can be received with:: Testing Error Injection ======================= -Set Error Injection parameters with:: +Set Error Injection parameters with: + +.. code-block:: console uart:~$ edac inject addr 0x1000 Set injection address base to: 0x1000 @@ -75,13 +89,17 @@ Set Error Injection parameters with:: uart:~$ edac inject error_type correctable Set injection error type: correctable -Trigger injection with:: +Trigger injection with: + +.. code-block:: console uart:~$ edac inject trigger Triggering injection Now Read / Write to the injection address to trigger Error Injection with -following devmem commands:: +following devmem commands: + +.. code-block:: console uart:~$ devmem 0x1000 32 0xabcd Mapped 0x1000 to 0x2ffcf000 @@ -95,6 +113,8 @@ following devmem commands:: Using data width 32 Read value 0xabcd -We should get the following message on screen indicating an IBECC event:: +We should get the following message on screen indicating an IBECC event: + +.. code-block:: none Got notification about IBECC event diff --git a/samples/subsys/fs/format/README.rst b/samples/subsys/fs/format/README.rst index f42209fc2f2..1801af34306 100644 --- a/samples/subsys/fs/format/README.rst +++ b/samples/subsys/fs/format/README.rst @@ -1,7 +1,8 @@ -.. _fs_format_sample: +.. zephyr:code-sample:: fs-format + :name: Format filesystem + :relevant-api: file_system_api -FS Format Sample -################ + Format different storage devices for different file systems. Overview *********** diff --git a/samples/subsys/fs/format/prj_ram.conf b/samples/subsys/fs/format/prj_ram.conf index 3604ca153db..feecc2eefd4 100644 --- a/samples/subsys/fs/format/prj_ram.conf +++ b/samples/subsys/fs/format/prj_ram.conf @@ -1,7 +1,5 @@ CONFIG_DISK_ACCESS=y CONFIG_DISK_DRIVERS=y -CONFIG_DISK_DRIVER_RAM=y -CONFIG_DISK_RAM_VOLUME_SIZE=64 CONFIG_LOG=y CONFIG_LOG_MODE_MINIMAL=y diff --git a/samples/subsys/fs/format/ramdisk.overlay b/samples/subsys/fs/format/ramdisk.overlay new file mode 100644 index 00000000000..b76a5ef6161 --- /dev/null +++ b/samples/subsys/fs/format/ramdisk.overlay @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + ramdisk0 { + compatible = "zephyr,ram-disk"; + disk-name = "RAM"; + sector-size = <512>; + sector-count = <128>; + }; +}; diff --git a/samples/subsys/fs/format/sample.yaml b/samples/subsys/fs/format/sample.yaml index 0c41105fc63..aafe86f7989 100644 --- a/samples/subsys/fs/format/sample.yaml +++ b/samples/subsys/fs/format/sample.yaml @@ -4,13 +4,17 @@ tests: sample.filesystem.format.littlefs: platform_allow: - native_posix + - native_sim - nrf52dk_nrf52832 build_only: true tags: filesystem sample.filesystem.format.fat_fs: platform_allow: - native_posix + - native_sim - mimxrt1064_evk build_only: true - extra_args: CONF_FILE="prj_ram.conf" + extra_args: + - CONF_FILE="prj_ram.conf" + - EXTRA_DTC_OVERLAY_FILE="ramdisk.overlay" tags: filesystem diff --git a/samples/subsys/fs/fs_sample/README.rst b/samples/subsys/fs/fs_sample/README.rst index 6a441e201cd..e53068b92c7 100644 --- a/samples/subsys/fs/fs_sample/README.rst +++ b/samples/subsys/fs/fs_sample/README.rst @@ -1,7 +1,8 @@ -.. _fs_sample: +.. zephyr:code-sample:: fs + :name: File system manipulation + :relevant-api: file_system_api disk_access_interface -Filesystems Sample Application -################################### + Use file system API with various filesystems and storage devices. Overview ******** diff --git a/samples/subsys/fs/fs_sample/boards/stm32h747i_disco_m7.conf b/samples/subsys/fs/fs_sample/boards/stm32h747i_disco_m7.conf new file mode 100644 index 00000000000..857d2e8ddfd --- /dev/null +++ b/samples/subsys/fs/fs_sample/boards/stm32h747i_disco_m7.conf @@ -0,0 +1 @@ +CONFIG_SDMMC_STM32_HWFC=y diff --git a/samples/subsys/fs/fs_sample/boards/stm32h747i_disco_m7.overlay b/samples/subsys/fs/fs_sample/boards/stm32h747i_disco_m7.overlay new file mode 100644 index 00000000000..d80aa5114fc --- /dev/null +++ b/samples/subsys/fs/fs_sample/boards/stm32h747i_disco_m7.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2023 S&C Electric Company + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&sdmmc1 { + sdmmc { + compatible = "zephyr,sdmmc-disk"; + }; +}; diff --git a/samples/subsys/fs/fs_sample/sample.yaml b/samples/subsys/fs/fs_sample/sample.yaml index e022ca1e4c1..375bacf4f8f 100644 --- a/samples/subsys/fs/fs_sample/sample.yaml +++ b/samples/subsys/fs/fs_sample/sample.yaml @@ -45,3 +45,8 @@ tests: sample.filesystem.ext2: extra_args: CONF_FILE="prj_ext.conf" platform_allow: hifive_unmatched bl5340_dvk_cpuapp + sample.filesystem.fat_fs.stm32h747i_disco_m7_sdmmc: + build_only: true + platform_allow: stm32h747i_disco_m7 + extra_args: + - OVERLAY_CONFIG=boards/stm32h747i_disco_m7.conf diff --git a/samples/subsys/fs/littlefs/README.rst b/samples/subsys/fs/littlefs/README.rst index 948da3f635b..40911001dda 100644 --- a/samples/subsys/fs/littlefs/README.rst +++ b/samples/subsys/fs/littlefs/README.rst @@ -1,7 +1,8 @@ -.. _littlefs-sample: +.. zephyr:code-sample:: littlefs + :name: LittleFS filesystem + :relevant-api: file_system_api flash_area_api -littlefs File System Sample Application -####################################### + Use file system API over LittleFS. Overview ******** diff --git a/samples/subsys/fs/littlefs/boards/nucleo_h743zi_blk.conf b/samples/subsys/fs/littlefs/boards/nucleo_h743zi_blk.conf index eeabf1150b0..a5663cf11a2 100644 --- a/samples/subsys/fs/littlefs/boards/nucleo_h743zi_blk.conf +++ b/samples/subsys/fs/littlefs/boards/nucleo_h743zi_blk.conf @@ -7,3 +7,4 @@ CONFIG_MAIN_STACK_SIZE=2048 CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=8192 CONFIG_FS_LITTLEFS_FC_HEAP_SIZE=8192 +CONFIG_SDMMC_STM32_HWFC=y diff --git a/samples/subsys/fs/littlefs/boards/stm32h747i_disco_m7.conf b/samples/subsys/fs/littlefs/boards/stm32h747i_disco_m7.conf new file mode 100644 index 00000000000..a45f607811f --- /dev/null +++ b/samples/subsys/fs/littlefs/boards/stm32h747i_disco_m7.conf @@ -0,0 +1,3 @@ +CONFIG_SDMMC_STM32_HWFC=y +CONFIG_FS_LITTLEFS_FC_HEAP_SIZE=2048 +CONFIG_MAIN_STACK_SIZE=2048 diff --git a/samples/subsys/fs/littlefs/boards/stm32h747i_disco_m7.overlay b/samples/subsys/fs/littlefs/boards/stm32h747i_disco_m7.overlay new file mode 100644 index 00000000000..cf1c30e2e87 --- /dev/null +++ b/samples/subsys/fs/littlefs/boards/stm32h747i_disco_m7.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2023 S&C Electric Company + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&sdmmc1 { + sdmmc { + compatible = "zephyr,sdmmc-disk"; + }; +}; diff --git a/samples/subsys/fs/littlefs/prj_blk.conf b/samples/subsys/fs/littlefs/prj_blk.conf index 7df323b59f3..011f919a568 100644 --- a/samples/subsys/fs/littlefs/prj_blk.conf +++ b/samples/subsys/fs/littlefs/prj_blk.conf @@ -19,4 +19,3 @@ CONFIG_FS_LITTLEFS_BLK_DEV=y CONFIG_APP_LITTLEFS_STORAGE_BLK_SDMMC=y CONFIG_NOCACHE_MEMORY=y -CONFIG_SDMMC_STM32_HWFC=y diff --git a/samples/subsys/fs/littlefs/sample.yaml b/samples/subsys/fs/littlefs/sample.yaml index d22cfbbd235..cee42827173 100644 --- a/samples/subsys/fs/littlefs/sample.yaml +++ b/samples/subsys/fs/littlefs/sample.yaml @@ -16,6 +16,7 @@ tests: - mimxrt1064_evk - qemu_x86 - native_posix + - native_sim - mimxrt1160_evk_cm7 - lpcxpresso55s69_cpu0 - mr_canhubk3 @@ -33,3 +34,9 @@ tests: extra_args: - OVERLAY_CONFIG=boards/nrf52840dk_nrf52840_qspi.conf - DTC_OVERLAY_FILE=boards/nrf52840dk_nrf52840_qspi.overlay + sample.filesystem.littlefs.stm32h747i_disco_m7_sdmmc: + build_only: true + platform_allow: stm32h747i_disco_m7 + extra_args: + - OVERLAY_CONFIG=boards/stm32h747i_disco_m7.conf + - CONF_FILE=prj_blk.conf diff --git a/samples/subsys/input/input_dump/README.rst b/samples/subsys/input/input_dump/README.rst index 8a02f104ec8..0492f02b831 100644 --- a/samples/subsys/input/input_dump/README.rst +++ b/samples/subsys/input/input_dump/README.rst @@ -1,7 +1,8 @@ -.. _input-dump-sample: +.. zephyr:code-sample:: input-dump + :name: Input dump + :relevant-api: input_events -Input Dump -########## + Print all input events. Overview ******** diff --git a/samples/subsys/input/input_dump/sample.yaml b/samples/subsys/input/input_dump/sample.yaml index 04a867b8a07..1fb4d9d30a9 100644 --- a/samples/subsys/input/input_dump/sample.yaml +++ b/samples/subsys/input/input_dump/sample.yaml @@ -5,4 +5,4 @@ tests: tags: input build_only: true integration_platforms: - - native_posix + - native_sim diff --git a/samples/subsys/ipc/ipc_service/icmsg/CMakeLists.txt b/samples/subsys/ipc/ipc_service/icmsg/CMakeLists.txt index 31bc4418c9d..2d9d62bdf23 100644 --- a/samples/subsys/ipc/ipc_service/icmsg/CMakeLists.txt +++ b/samples/subsys/ipc/ipc_service/icmsg/CMakeLists.txt @@ -6,15 +6,12 @@ cmake_minimum_required(VERSION 3.20.0) -set(REMOTE_ZEPHYR_DIR ${CMAKE_CURRENT_BINARY_DIR}/ipc_service_remote-prefix/src/ipc_service_remote-build/zephyr) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -if("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpuapp") - set(BOARD_REMOTE "nrf5340dk_nrf5340_cpunet") -else() +if(NOT ("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpuapp")) message(FATAL_ERROR "${BOARD} is not supported for this sample") endif() -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(ipc_service_host) target_include_directories(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/common) @@ -22,13 +19,3 @@ target_include_directories(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/common) target_sources(app PRIVATE src/main.c) include(ExternalProject) - -ExternalProject_Add( - ipc_service_remote - SOURCE_DIR ${APPLICATION_SOURCE_DIR}/remote - INSTALL_COMMAND "" # This particular build system has no install command - CMAKE_CACHE_ARGS -DBOARD:STRING=${BOARD_REMOTE} - BUILD_BYPRODUCTS "${REMOTE_ZEPHYR_DIR}/${KERNEL_BIN_NAME}" - # NB: Do we need to pass on more CMake variables? - BUILD_ALWAYS True -) diff --git a/samples/subsys/ipc/ipc_service/icmsg/Kconfig.sysbuild b/samples/subsys/ipc/ipc_service/icmsg/Kconfig.sysbuild new file mode 100644 index 00000000000..47884745130 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/icmsg/Kconfig.sysbuild @@ -0,0 +1,9 @@ +# Copyright 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config NET_CORE_BOARD +string + default "nrf5340dk_nrf5340_cpunet" if $(BOARD) = "nrf5340dk_nrf5340_cpuapp" diff --git a/samples/subsys/ipc/ipc_service/icmsg/README.rst b/samples/subsys/ipc/ipc_service/icmsg/README.rst index ce052214986..c12c4107075 100644 --- a/samples/subsys/ipc/ipc_service/icmsg/README.rst +++ b/samples/subsys/ipc/ipc_service/icmsg/README.rst @@ -1,7 +1,8 @@ -.. _ipc_icmsg_sample: +.. zephyr:code-sample:: ipc-icmsg + :name: IPC service: icmsg backend + :relevant-api: ipc -IPC Service - icmsg - Sample Application -######################################## + Send messages between two cores using the IPC service and icmsg backend. Overview ******** @@ -17,6 +18,7 @@ Building the application for nrf5340dk_nrf5340_cpuapp :zephyr-app: samples/subsys/ipc/ipc_service/icmsg :board: nrf5340dk_nrf5340_cpuapp :goals: debug + :west-args: --sysbuild Open a serial terminal (minicom, putty, etc.) and connect the board with the following settings: diff --git a/samples/subsys/ipc/ipc_service/icmsg/remote/sample.yaml b/samples/subsys/ipc/ipc_service/icmsg/remote/sample.yaml deleted file mode 100644 index 3b927c11f37..00000000000 --- a/samples/subsys/ipc/ipc_service/icmsg/remote/sample.yaml +++ /dev/null @@ -1,9 +0,0 @@ -sample: - name: IPC Service example integration (icmsg backend) (remote) -tests: - sample.ipc.icmsg_remote: - platform_allow: nrf5340dk_nrf5340_cpunet - integration_platforms: - - nrf5340dk_nrf5340_cpunet - tags: ipc - harness: remote diff --git a/samples/subsys/ipc/ipc_service/icmsg/sample.yaml b/samples/subsys/ipc/ipc_service/icmsg/sample.yaml index 582f277ce7a..b54fc7f8962 100644 --- a/samples/subsys/ipc/ipc_service/icmsg/sample.yaml +++ b/samples/subsys/ipc/ipc_service/icmsg/sample.yaml @@ -6,4 +6,5 @@ tests: integration_platforms: - nrf5340dk_nrf5340_cpuapp tags: ipc + sysbuild: true harness: remote diff --git a/samples/subsys/ipc/ipc_service/icmsg/sysbuild.cmake b/samples/subsys/ipc/ipc_service/icmsg/sysbuild.cmake new file mode 100644 index 00000000000..d0d79b8f240 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/icmsg/sysbuild.cmake @@ -0,0 +1,14 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if("${SB_CONFIG_NET_CORE_BOARD}" STREQUAL "") + message(FATAL_ERROR + "Target ${BOARD} not supported for this sample. " + "There is no remote board selected in Kconfig.sysbuild") +endif() + +ExternalZephyrProject_Add( + APPLICATION remote + SOURCE_DIR ${APP_DIR}/remote + BOARD ${SB_CONFIG_NET_CORE_BOARD} +) diff --git a/samples/subsys/ipc/ipc_service/icmsg/sysbuild.conf b/samples/subsys/ipc/ipc_service/icmsg/sysbuild.conf new file mode 100644 index 00000000000..6408669a847 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/icmsg/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/samples/subsys/ipc/ipc_service/icmsg_me/CMakeLists.txt b/samples/subsys/ipc/ipc_service/icmsg_me/CMakeLists.txt deleted file mode 100644 index 5317f899424..00000000000 --- a/samples/subsys/ipc/ipc_service/icmsg_me/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright (c) 2022 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 -# - -cmake_minimum_required(VERSION 3.20.0) - -set(REMOTE_ZEPHYR_DIR ${CMAKE_CURRENT_BINARY_DIR}/ipc_service_remote-prefix/src/ipc_service_remote-build/zephyr) - -if("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpuapp") - set(BOARD_REMOTE "nrf5340dk_nrf5340_cpunet") -else() - message(FATAL_ERROR "${BOARD} is not supported for this sample") -endif() - -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(ipc_service) - -target_sources(app PRIVATE src/main.c) - -include(ExternalProject) - -ExternalProject_Add( - ipc_service_remote - SOURCE_DIR ${APPLICATION_SOURCE_DIR}/remote - INSTALL_COMMAND "" # This particular build system has no install command - CMAKE_CACHE_ARGS -DBOARD:STRING=${BOARD_REMOTE} - BUILD_BYPRODUCTS "${REMOTE_ZEPHYR_DIR}/${KERNEL_BIN_NAME}" - # NB: Do we need to pass on more CMake variables? - BUILD_ALWAYS True -) diff --git a/samples/subsys/ipc/ipc_service/icmsg_me/prj.conf b/samples/subsys/ipc/ipc_service/icmsg_me/prj.conf deleted file mode 100644 index 5feb10b3120..00000000000 --- a/samples/subsys/ipc/ipc_service/icmsg_me/prj.conf +++ /dev/null @@ -1,8 +0,0 @@ -CONFIG_PRINTK=y - -CONFIG_IPC_SERVICE=y -CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_NOCOPY_RX=y -CONFIG_MBOX=y - -CONFIG_LOG=y -CONFIG_IPC_SERVICE_LOG_LEVEL_INF=y diff --git a/samples/subsys/ipc/ipc_service/icmsg_me/remote/prj.conf b/samples/subsys/ipc/ipc_service/icmsg_me/remote/prj.conf deleted file mode 100644 index 5feb10b3120..00000000000 --- a/samples/subsys/ipc/ipc_service/icmsg_me/remote/prj.conf +++ /dev/null @@ -1,8 +0,0 @@ -CONFIG_PRINTK=y - -CONFIG_IPC_SERVICE=y -CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_NOCOPY_RX=y -CONFIG_MBOX=y - -CONFIG_LOG=y -CONFIG_IPC_SERVICE_LOG_LEVEL_INF=y diff --git a/samples/subsys/ipc/ipc_service/icmsg_me/remote/sample.yaml b/samples/subsys/ipc/ipc_service/icmsg_me/remote/sample.yaml deleted file mode 100644 index baf92ccc3da..00000000000 --- a/samples/subsys/ipc/ipc_service/icmsg_me/remote/sample.yaml +++ /dev/null @@ -1,9 +0,0 @@ -sample: - name: IPC Service example integration (icmsg multi endpoint follower backend) (remote) -tests: - sample.ipc.icmsg_me_follower: - platform_allow: nrf5340dk_nrf5340_cpunet - integration_platforms: - - nrf5340dk_nrf5340_cpunet - tags: ipc - harness: remote diff --git a/samples/subsys/ipc/ipc_service/icmsg_me/remote/src/main.c b/samples/subsys/ipc/ipc_service/icmsg_me/remote/src/main.c deleted file mode 100644 index 387f962af95..00000000000 --- a/samples/subsys/ipc/ipc_service/icmsg_me/remote/src/main.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright (c) 2022 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -#include - -#define STACKSIZE (1024) -#define PRIORITY K_PRIO_PREEMPT(2) - -K_THREAD_STACK_DEFINE(ipc0A_stack, STACKSIZE); -K_THREAD_STACK_DEFINE(ipc0B_stack, STACKSIZE); -K_THREAD_STACK_DEFINE(ipc1_stack, STACKSIZE); - -static volatile uint8_t ipc0A_received_data; -static volatile uint8_t ipc0B_received_data; -static const void *ipc1_received_data; - -static K_SEM_DEFINE(ipc0A_bound_sem, 0, 1); -static K_SEM_DEFINE(ipc0B_bound_sem, 0, 1); -static K_SEM_DEFINE(ipc1_bound_sem, 0, 1); - -static K_SEM_DEFINE(ipc0A_data_sem, 0, 1); -static K_SEM_DEFINE(ipc0B_data_sem, 0, 1); -static K_SEM_DEFINE(ipc1_data_sem, 0, 1); - -/* - * ==> THREAD 0A (IPC instance 0 - endpoint A) <== - */ - -static void ipc0A_ept_bound(void *priv) -{ - k_sem_give(&ipc0A_bound_sem); -} - -static void ipc0A_ept_recv(const void *data, size_t len, void *priv) -{ - ipc0A_received_data = *((uint8_t *) data); - - k_sem_give(&ipc0A_data_sem); -} - -static struct ipc_ept_cfg ipc0A_ept_cfg = { - .name = "ipc0A", - .cb = { - .bound = ipc0A_ept_bound, - .received = ipc0A_ept_recv, - }, -}; - -static void ipc0A_entry(void *dummy0, void *dummy1, void *dummy2) -{ - ARG_UNUSED(dummy0); - ARG_UNUSED(dummy1); - ARG_UNUSED(dummy2); - - const struct device *ipc0_instance; - unsigned char message = 0; - struct ipc_ept ipc0A_ept; - int ret; - - printk("IPC-service REMOTE [INST 0 - ENDP A] demo started\n"); - - ipc0_instance = DEVICE_DT_GET(DT_NODELABEL(ipc0)); - - ret = ipc_service_open_instance(ipc0_instance); - if (ret < 0 && ret != -EALREADY) { - printk("ipc_service_open_instance() failure\n"); - return; - } - - ret = ipc_service_register_endpoint(ipc0_instance, &ipc0A_ept, &ipc0A_ept_cfg); - if (ret < 0) { - printf("ipc_service_register_endpoint() failure\n"); - return; - } - - k_sem_take(&ipc0A_bound_sem, K_FOREVER); - - while (message < 99) { - k_sem_take(&ipc0A_data_sem, K_FOREVER); - message = ipc0A_received_data; - - printk("REMOTE [0A]: %d\n", message); - - message++; - - ret = ipc_service_send(&ipc0A_ept, &message, sizeof(message)); - if (ret < 0) { - printk("send_message(%d) failed with ret %d\n", message, ret); - break; - } - } - - printk("IPC-service REMOTE [INST 0 - ENDP A] demo ended.\n"); -} -K_THREAD_DEFINE(ipc0A_thread_id, STACKSIZE, ipc0A_entry, NULL, NULL, NULL, PRIORITY, 0, 0); - -/* - * ==> THREAD 0B (IPC instance 0 - endpoint B) <== - */ - -static void ipc0B_ept_bound(void *priv) -{ - k_sem_give(&ipc0B_bound_sem); -} - -static void ipc0B_ept_recv(const void *data, size_t len, void *priv) -{ - ipc0B_received_data = *((uint8_t *) data); - - k_sem_give(&ipc0B_data_sem); -} - -static struct ipc_ept_cfg ipc0B_ept_cfg = { - .name = "ipc0B", - .cb = { - .bound = ipc0B_ept_bound, - .received = ipc0B_ept_recv, - }, -}; - -static void ipc0B_entry(void *dummy0, void *dummy1, void *dummy2) -{ - ARG_UNUSED(dummy0); - ARG_UNUSED(dummy1); - ARG_UNUSED(dummy2); - - const struct device *ipc0_instance; - unsigned char message = 0; - struct ipc_ept ipc0B_ept; - int ret; - - printk("IPC-service REMOTE [INST 0 - ENDP B] demo started\n"); - - ipc0_instance = DEVICE_DT_GET(DT_NODELABEL(ipc0)); - - ret = ipc_service_open_instance(ipc0_instance); - if (ret < 0 && ret != -EALREADY) { - printk("ipc_service_open_instance() failure\n"); - return; - } - - /* - * Wait 1 sec to give the opportunity to the PRIMARY core to register - * the endpoint first - */ - - k_sleep(K_MSEC(1000)); - - ret = ipc_service_register_endpoint(ipc0_instance, &ipc0B_ept, &ipc0B_ept_cfg); - if (ret < 0) { - printf("ipc_service_register_endpoint() failure\n"); - return; - } - - k_sem_take(&ipc0B_bound_sem, K_FOREVER); - - while (message < 99) { - k_sem_take(&ipc0B_data_sem, K_FOREVER); - message = ipc0B_received_data; - - printk("REMOTE [0B]: %d\n", message); - - message++; - - ret = ipc_service_send(&ipc0B_ept, &message, sizeof(message)); - if (ret < 0) { - printk("send_message(%d) failed with ret %d\n", message, ret); - break; - } - } - - printk("IPC-service REMOTE [INST 0 - ENDP B] demo ended.\n"); -} -K_THREAD_DEFINE(ipc0B_thread_id, STACKSIZE, ipc0B_entry, NULL, NULL, NULL, PRIORITY, 0, 0); - -/* - * ==> THREAD 1 (IPC instance 1) <== - * - * NOTE: This instance is using the NOCOPY copability of the backend. - */ - -static struct ipc_ept ipc1_ept; - -static void ipc1_ept_bound(void *priv) -{ - k_sem_give(&ipc1_bound_sem); -} - -static void ipc1_ept_recv(const void *data, size_t len, void *priv) -{ - ipc_service_hold_rx_buffer(&ipc1_ept, (void *)data); - ipc1_received_data = data; - - k_sem_give(&ipc1_data_sem); -} - -static struct ipc_ept_cfg ipc1_ept_cfg = { - .name = "ipc1", - .cb = { - .bound = ipc1_ept_bound, - .received = ipc1_ept_recv, - }, -}; - -static void ipc1_entry(void *dummy0, void *dummy1, void *dummy2) -{ - ARG_UNUSED(dummy0); - ARG_UNUSED(dummy1); - ARG_UNUSED(dummy2); - - const struct device *ipc1_instance; - unsigned char message = 0; - int ret; - - printk("IPC-service REMOTE [INST 1] demo started\n"); - - ipc1_instance = DEVICE_DT_GET(DT_NODELABEL(ipc1)); - - ret = ipc_service_open_instance(ipc1_instance); - if (ret < 0 && ret != -EALREADY) { - printk("ipc_service_open_instance() failure\n"); - return; - } - - ret = ipc_service_register_endpoint(ipc1_instance, &ipc1_ept, &ipc1_ept_cfg); - if (ret < 0) { - printf("ipc_service_register_endpoint() failure\n"); - return; - } - - k_sem_take(&ipc1_bound_sem, K_FOREVER); - - while (message < 99) { - void *tx_buffer; - uint32_t tx_buffer_size = sizeof(message); - - k_sem_take(&ipc1_data_sem, K_FOREVER); - message = *((uint8_t *) ipc1_received_data); - - ret = ipc_service_release_rx_buffer(&ipc1_ept, (void *) ipc1_received_data); - if (ret < 0) { - printk("release_rx_buffer() failed with ret %d\n", ret); - break; - } - - printk("REMOTE [1]: %d\n", message); - - message++; - - ret = ipc_service_get_tx_buffer(&ipc1_ept, &tx_buffer, &tx_buffer_size, K_NO_WAIT); - if (ret < 0) { - printk("get_tx_buffer(%u) failed with ret %d\n", sizeof(message), ret); - break; - } - if (tx_buffer_size != sizeof(message)) { - printk("get_tx_buffer modified buffer size to unexpected value %u\n", - tx_buffer_size); - break; - } - - *((uint8_t *) tx_buffer) = message; - - ret = ipc_service_send_nocopy(&ipc1_ept, tx_buffer, tx_buffer_size); - if (ret < 0) { - printk("send_message_nocopy(%u) failed with ret %d\n", message, ret); - break; - } - } - - printk("IPC-service REMOTE [INST 1] demo ended.\n"); -} -K_THREAD_DEFINE(ipc1_thread_id, STACKSIZE, ipc1_entry, NULL, NULL, NULL, PRIORITY, 0, 0); diff --git a/samples/subsys/ipc/ipc_service/icmsg_me/sample.yaml b/samples/subsys/ipc/ipc_service/icmsg_me/sample.yaml deleted file mode 100644 index 8a6443de1fa..00000000000 --- a/samples/subsys/ipc/ipc_service/icmsg_me/sample.yaml +++ /dev/null @@ -1,9 +0,0 @@ -sample: - name: IPC Service example integration (icmsg multi endpoint backend) -tests: - sample.ipc.icmsg_me: - platform_allow: nrf5340dk_nrf5340_cpuapp - integration_platforms: - - nrf5340dk_nrf5340_cpuapp - tags: ipc - harness: remote diff --git a/samples/subsys/ipc/ipc_service/icmsg_me/src/main.c b/samples/subsys/ipc/ipc_service/icmsg_me/src/main.c deleted file mode 100644 index 92b3a5569ef..00000000000 --- a/samples/subsys/ipc/ipc_service/icmsg_me/src/main.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (c) 2022 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -#include - -#define STACKSIZE (4096) -#define PRIORITY K_PRIO_PREEMPT(2) - -K_THREAD_STACK_DEFINE(ipc0A_stack, STACKSIZE); -K_THREAD_STACK_DEFINE(ipc0B_stack, STACKSIZE); -K_THREAD_STACK_DEFINE(ipc1_stack, STACKSIZE); - -static volatile uint8_t ipc0A_received_data; -static volatile uint8_t ipc0B_received_data; -static const void *ipc1_received_data; - -static K_SEM_DEFINE(ipc0A_bound_sem, 0, 1); -static K_SEM_DEFINE(ipc0B_bound_sem, 0, 1); -static K_SEM_DEFINE(ipc1_bound_sem, 0, 1); - -static K_SEM_DEFINE(ipc0A_data_sem, 0, 1); -static K_SEM_DEFINE(ipc0B_data_sem, 0, 1); -static K_SEM_DEFINE(ipc1_data_sem, 0, 1); - -/* - * ==> THREAD 0A (IPC instance 0 - endpoint A) <== - */ - -static void ipc0A_ept_bound(void *priv) -{ - k_sem_give(&ipc0A_bound_sem); -} - -static void ipc0A_ept_recv(const void *data, size_t len, void *priv) -{ - ipc0A_received_data = *((uint8_t *) data); - - k_sem_give(&ipc0A_data_sem); -} - -static struct ipc_ept_cfg ipc0A_ept_cfg = { - .name = "ipc0A", - .cb = { - .bound = ipc0A_ept_bound, - .received = ipc0A_ept_recv, - }, -}; - -static void ipc0A_entry(void *dummy0, void *dummy1, void *dummy2) -{ - ARG_UNUSED(dummy0); - ARG_UNUSED(dummy1); - ARG_UNUSED(dummy2); - - const struct device *ipc0_instance; - unsigned char message = 0; - struct ipc_ept ipc0A_ept; - int ret; - - printk("IPC-service HOST [INST 0 - ENDP A] demo started\n"); - - ipc0_instance = DEVICE_DT_GET(DT_NODELABEL(ipc0)); - - ret = ipc_service_open_instance(ipc0_instance); - if (ret < 0 && ret != -EALREADY) { - printk("ipc_service_open_instance() failure\n"); - return; - } - - /* - * Wait 1 sec to give the opportunity to the SECONDARY core to register - * the endpoint first - */ - - k_sleep(K_MSEC(1000)); - - ret = ipc_service_register_endpoint(ipc0_instance, &ipc0A_ept, &ipc0A_ept_cfg); - if (ret < 0) { - printf("ipc_service_register_endpoint() failure\n"); - return; - } - - k_sem_take(&ipc0A_bound_sem, K_FOREVER); - - while (message < 100) { - ret = ipc_service_send(&ipc0A_ept, &message, sizeof(message)); - if (ret < 0) { - printk("send_message(%d) failed with ret %d\n", message, ret); - break; - } - - k_sem_take(&ipc0A_data_sem, K_FOREVER); - message = ipc0A_received_data; - - printk("HOST [0A]: %d\n", message); - message++; - } - - printk("IPC-service HOST [INST 0 - ENDP A] demo ended.\n"); -} -K_THREAD_DEFINE(ipc0A_thread_id, STACKSIZE, ipc0A_entry, NULL, NULL, NULL, PRIORITY, 0, 0); - -/* - * ==> THREAD 0B (IPC instance 0 - endpoint B) <== - */ - -static void ipc0B_ept_bound(void *priv) -{ - k_sem_give(&ipc0B_bound_sem); -} - -static void ipc0B_ept_recv(const void *data, size_t len, void *priv) -{ - ipc0B_received_data = *((uint8_t *) data); - - k_sem_give(&ipc0B_data_sem); -} - -static struct ipc_ept_cfg ipc0B_ept_cfg = { - .name = "ipc0B", - .cb = { - .bound = ipc0B_ept_bound, - .received = ipc0B_ept_recv, - }, -}; - -static void ipc0B_entry(void *dummy0, void *dummy1, void *dummy2) -{ - ARG_UNUSED(dummy0); - ARG_UNUSED(dummy1); - ARG_UNUSED(dummy2); - - const struct device *ipc0_instance; - unsigned char message = 0; - struct ipc_ept ipc0B_ept; - int ret; - - printk("IPC-service HOST [INST 0 - ENDP B] demo started\n"); - - ipc0_instance = DEVICE_DT_GET(DT_NODELABEL(ipc0)); - - ret = ipc_service_open_instance(ipc0_instance); - if (ret < 0 && ret != -EALREADY) { - printk("ipc_service_open_instance() failure\n"); - return; - } - - ret = ipc_service_register_endpoint(ipc0_instance, &ipc0B_ept, &ipc0B_ept_cfg); - if (ret < 0) { - printf("ipc_service_register_endpoint() failure\n"); - return; - } - - k_sem_take(&ipc0B_bound_sem, K_FOREVER); - - while (message < 100) { - ret = ipc_service_send(&ipc0B_ept, &message, sizeof(message)); - if (ret < 0) { - printk("send_message(%d) failed with ret %d\n", message, ret); - break; - } - - k_sem_take(&ipc0B_data_sem, K_FOREVER); - message = ipc0B_received_data; - - printk("HOST [0B]: %d\n", message); - message++; - } - - printk("IPC-service HOST [INST 0 - ENDP B] demo ended.\n"); -} -K_THREAD_DEFINE(ipc0B_thread_id, STACKSIZE, ipc0B_entry, NULL, NULL, NULL, PRIORITY, 0, 0); - -/* - * ==> THREAD 1 (IPC instance 1) <== - * - * NOTE: This instance is using the NOCOPY copability of the backend. - */ - -static struct ipc_ept ipc1_ept; - -static void ipc1_ept_bound(void *priv) -{ - k_sem_give(&ipc1_bound_sem); -} - -static void ipc1_ept_recv(const void *data, size_t len, void *priv) -{ - ipc_service_hold_rx_buffer(&ipc1_ept, (void *)data); - ipc1_received_data = data; - - k_sem_give(&ipc1_data_sem); -} - -static struct ipc_ept_cfg ipc1_ept_cfg = { - .name = "ipc1", - .cb = { - .bound = ipc1_ept_bound, - .received = ipc1_ept_recv, - }, -}; - -static void ipc1_entry(void *dummy0, void *dummy1, void *dummy2) -{ - ARG_UNUSED(dummy0); - ARG_UNUSED(dummy1); - ARG_UNUSED(dummy2); - - const struct device *ipc1_instance; - unsigned char message = 0; - int ret; - - printk("IPC-service HOST [INST 1] demo started\n"); - - ipc1_instance = DEVICE_DT_GET(DT_NODELABEL(ipc1)); - - ret = ipc_service_open_instance(ipc1_instance); - if (ret < 0 && ret != -EALREADY) { - printk("ipc_service_open_instance() failure\n"); - return; - } - - ret = ipc_service_register_endpoint(ipc1_instance, &ipc1_ept, &ipc1_ept_cfg); - if (ret < 0) { - printf("ipc_service_register_endpoint() failure\n"); - return; - } - - k_sem_take(&ipc1_bound_sem, K_FOREVER); - - /* - * Wait 1 sec to start sending simultaneously with other threads - * the endpoint first - */ - - k_sleep(K_MSEC(1000)); - - while (message < 100) { - void *tx_buffer; - uint32_t tx_buffer_size = sizeof(message); - - ret = ipc_service_get_tx_buffer(&ipc1_ept, &tx_buffer, &tx_buffer_size, K_NO_WAIT); - if (ret < 0) { - printk("get_tx_buffer(%u) failed with ret %d\n", sizeof(message), ret); - break; - } - if (tx_buffer_size != sizeof(message)) { - printk("get_tx_buffer modified buffer size to unexpected value %u\n", - tx_buffer_size); - break; - } - - *((uint8_t *) tx_buffer) = message; - - ret = ipc_service_send_nocopy(&ipc1_ept, tx_buffer, tx_buffer_size); - if (ret < 0) { - printk("send_message_nocopy(%u) failed with ret %d\n", message, ret); - break; - } - - k_sem_take(&ipc1_data_sem, K_FOREVER); - message = *((uint8_t *) ipc1_received_data); - - ret = ipc_service_release_rx_buffer(&ipc1_ept, (void *) ipc1_received_data); - if (ret < 0) { - printk("release_rx_buffer() failed with ret %d\n", ret); - break; - } - - printk("HOST [1]: %d\n", message); - message++; - } - - printk("IPC-service HOST [INST 1] demo ended.\n"); -} -K_THREAD_DEFINE(ipc1_thread_id, STACKSIZE, ipc1_entry, NULL, NULL, NULL, PRIORITY, 0, 0); diff --git a/samples/subsys/ipc/ipc_service/multi_endpoint/CMakeLists.txt b/samples/subsys/ipc/ipc_service/multi_endpoint/CMakeLists.txt new file mode 100644 index 00000000000..b342f550616 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/multi_endpoint/CMakeLists.txt @@ -0,0 +1,17 @@ +# +# Copyright (c) 2022 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +if(NOT ("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpuapp")) + message(FATAL_ERROR "${BOARD} is not supported for this sample") +endif() + +project(ipc_service) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/subsys/ipc/ipc_service/multi_endpoint/Kconfig.sysbuild b/samples/subsys/ipc/ipc_service/multi_endpoint/Kconfig.sysbuild new file mode 100644 index 00000000000..47884745130 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/multi_endpoint/Kconfig.sysbuild @@ -0,0 +1,9 @@ +# Copyright 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config NET_CORE_BOARD +string + default "nrf5340dk_nrf5340_cpunet" if $(BOARD) = "nrf5340dk_nrf5340_cpuapp" diff --git a/samples/subsys/ipc/ipc_service/multi_endpoint/README.rst b/samples/subsys/ipc/ipc_service/multi_endpoint/README.rst new file mode 100644 index 00000000000..faff69e007f --- /dev/null +++ b/samples/subsys/ipc/ipc_service/multi_endpoint/README.rst @@ -0,0 +1,73 @@ +.. _ipc_multi_endpoint_sample: + +IPC Service - Multi-endpoint Sample Application +############################################### + +This application demonstrates how to use IPC Service with multiple endpoints. +By default, it uses the ``icmsg_me`` backend. +You can also configure it to use the ``icbmsg`` backend. + +Building the application for nrf5340dk_nrf5340_cpuapp +***************************************************** + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/ipc/ipc_service/multi_endpoint + :board: nrf5340dk_nrf5340_cpuapp + :goals: debug + +Open a serial terminal (for example Minicom or PuTTY) and connect the board with the following settings: + +* Speed: 115200 +* Data: 8 bits +* Parity: None +* Stop bits: 1 + +After resetting the board, the following message will appear on the corresponding +serial port: + +.. code-block:: console + + *** Booting Zephyr OS build v3.4.0-rc1-108-gccfbac8b0721 *** + IPC-service HOST [INST 0 - ENDP A] demo started + IPC-service HOST [INST 0 - ENDP B] demo started + IPC-service HOST [INST 1] demo started + HOST [0A]: 1 + HOST [0A]: 3 + HOST [0B]: 1 + HOST [1]: 1 + ... + HOST [0A]: 99 + IPC-service HOST [INST 0 - ENDP A] demo ended. + HOST [0B]: 99 + IPC-service HOST [INST 0 - ENDP B] demo ended. + HOST [1]: 99 + IPC-service HOST [INST 1] demo ended. + +.. code-block:: console + + *** Booting Zephyr OS build v3.4.0-rc1-108-gccfbac8b0721 *** + IPC-service REMOTE [INST 0 - ENDP A] demo started + IPC-service REMOTE [INST 0 - ENDP B] demo started + IPC-service REMOTE [INST 1] demo started + REMOTE [0A]: 0 + REMOTE [0A]: 2 + ... + REMOTE [0A]: 98 + IPC-service REMOTE [INST 0 - ENDP A] demo ended. + REMOTE [0B]: 98 + IPC-service REMOTE [INST 0 - ENDP B] demo ended. + REMOTE [1]: 98 + IPC-service REMOTE [INST 1] demo ended. + + +Changing the backend +******************** + +To change the backend to ``icbmsg``, switch the devicetree +overlay files as follows: + +.. code-block:: console + + west build -b nrf5340dk_nrf5340_cpuapp --sysbuild -- \ + -DDTC_OVERLAY_FILE=boards/nrf5340dk_nrf5340_cpuapp_icbmsg.overlay \ + -Dremote_DTC_OVERLAY_FILE=boards/nrf5340dk_nrf5340_cpunet_icbmsg.overlay diff --git a/samples/subsys/ipc/ipc_service/icmsg_me/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/subsys/ipc/ipc_service/multi_endpoint/boards/nrf5340dk_nrf5340_cpuapp.conf similarity index 100% rename from samples/subsys/ipc/ipc_service/icmsg_me/boards/nrf5340dk_nrf5340_cpuapp.conf rename to samples/subsys/ipc/ipc_service/multi_endpoint/boards/nrf5340dk_nrf5340_cpuapp.conf diff --git a/samples/subsys/ipc/ipc_service/icmsg_me/boards/nrf5340dk_nrf5340_cpuapp.overlay b/samples/subsys/ipc/ipc_service/multi_endpoint/boards/nrf5340dk_nrf5340_cpuapp.overlay similarity index 100% rename from samples/subsys/ipc/ipc_service/icmsg_me/boards/nrf5340dk_nrf5340_cpuapp.overlay rename to samples/subsys/ipc/ipc_service/multi_endpoint/boards/nrf5340dk_nrf5340_cpuapp.overlay diff --git a/samples/subsys/ipc/ipc_service/multi_endpoint/boards/nrf5340dk_nrf5340_cpuapp_icbmsg.overlay b/samples/subsys/ipc/ipc_service/multi_endpoint/boards/nrf5340dk_nrf5340_cpuapp_icbmsg.overlay new file mode 100644 index 00000000000..3db9db032f4 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/multi_endpoint/boards/nrf5340dk_nrf5340_cpuapp_icbmsg.overlay @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + /delete-property/ zephyr,ipc_shm; + }; + + reserved-memory { + /delete-node/ memory@20070000; + + sram_ipc0_tx: memory@20070000 { + reg = <0x20070000 0x4000>; + }; + + sram_ipc0_rx: memory@20074000 { + reg = <0x20074000 0x4000>; + }; + + sram_ipc1_tx: memory@20078000 { + reg = <0x20078000 0x4000>; + }; + + sram_ipc1_rx: memory@2007C000 { + reg = <0x2007C000 0x4000>; + }; + }; + + ipc { + /delete-node/ ipc0; + + ipc0: ipc0 { + compatible = "zephyr,ipc-icbmsg"; + tx-region = <&sram_ipc0_tx>; + rx-region = <&sram_ipc0_rx>; + tx-blocks = <16>; + rx-blocks = <24>; + mboxes = <&mbox 0>, <&mbox 1>; + mbox-names = "tx", "rx"; + status = "okay"; + }; + + ipc1: ipc1 { + compatible = "zephyr,ipc-icbmsg"; + tx-region = <&sram_ipc1_tx>; + rx-region = <&sram_ipc1_rx>; + tx-blocks = <32>; + rx-blocks = <48>; + mboxes = <&mbox 2>, <&mbox 3>; + mbox-names = "tx", "rx"; + status = "okay"; + }; + }; +}; diff --git a/samples/subsys/ipc/ipc_service/multi_endpoint/prj.conf b/samples/subsys/ipc/ipc_service/multi_endpoint/prj.conf new file mode 100644 index 00000000000..3d2c799c4eb --- /dev/null +++ b/samples/subsys/ipc/ipc_service/multi_endpoint/prj.conf @@ -0,0 +1,8 @@ +CONFIG_PRINTK=y +CONFIG_LOG_PRINTK=n + +CONFIG_IPC_SERVICE=y +CONFIG_MBOX=y + +CONFIG_LOG=y +CONFIG_IPC_SERVICE_LOG_LEVEL_INF=y diff --git a/samples/subsys/ipc/ipc_service/icmsg_me/remote/CMakeLists.txt b/samples/subsys/ipc/ipc_service/multi_endpoint/remote/CMakeLists.txt similarity index 100% rename from samples/subsys/ipc/ipc_service/icmsg_me/remote/CMakeLists.txt rename to samples/subsys/ipc/ipc_service/multi_endpoint/remote/CMakeLists.txt diff --git a/samples/subsys/ipc/ipc_service/icmsg_me/remote/boards/nrf5340dk_nrf5340_cpunet.conf b/samples/subsys/ipc/ipc_service/multi_endpoint/remote/boards/nrf5340dk_nrf5340_cpunet.conf similarity index 100% rename from samples/subsys/ipc/ipc_service/icmsg_me/remote/boards/nrf5340dk_nrf5340_cpunet.conf rename to samples/subsys/ipc/ipc_service/multi_endpoint/remote/boards/nrf5340dk_nrf5340_cpunet.conf diff --git a/samples/subsys/ipc/ipc_service/icmsg_me/remote/boards/nrf5340dk_nrf5340_cpunet.overlay b/samples/subsys/ipc/ipc_service/multi_endpoint/remote/boards/nrf5340dk_nrf5340_cpunet.overlay similarity index 100% rename from samples/subsys/ipc/ipc_service/icmsg_me/remote/boards/nrf5340dk_nrf5340_cpunet.overlay rename to samples/subsys/ipc/ipc_service/multi_endpoint/remote/boards/nrf5340dk_nrf5340_cpunet.overlay diff --git a/samples/subsys/ipc/ipc_service/multi_endpoint/remote/boards/nrf5340dk_nrf5340_cpunet_icbmsg.overlay b/samples/subsys/ipc/ipc_service/multi_endpoint/remote/boards/nrf5340dk_nrf5340_cpunet_icbmsg.overlay new file mode 100644 index 00000000000..6247ed812aa --- /dev/null +++ b/samples/subsys/ipc/ipc_service/multi_endpoint/remote/boards/nrf5340dk_nrf5340_cpunet_icbmsg.overlay @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + /delete-property/ zephyr,ipc_shm; + }; + + reserved-memory { + /delete-node/ memory@20070000; + + sram_ipc0_rx: memory@20070000 { + reg = <0x20070000 0x4000>; + }; + + sram_ipc0_tx: memory@20074000 { + reg = <0x20074000 0x4000>; + }; + + sram_ipc1_rx: memory@20078000 { + reg = <0x20078000 0x4000>; + }; + + sram_ipc1_tx: memory@2007C000 { + reg = <0x2007C000 0x4000>; + }; + }; + + ipc { + /delete-node/ ipc0; + + ipc0: ipc0 { + compatible = "zephyr,ipc-icbmsg"; + tx-region = <&sram_ipc0_tx>; + rx-region = <&sram_ipc0_rx>; + tx-blocks = <24>; + rx-blocks = <16>; + mboxes = <&mbox 0>, <&mbox 1>; + mbox-names = "rx", "tx"; + status = "okay"; + }; + + ipc1: ipc1 { + compatible = "zephyr,ipc-icbmsg"; + tx-region = <&sram_ipc1_tx>; + rx-region = <&sram_ipc1_rx>; + tx-blocks = <48>; + rx-blocks = <32>; + mboxes = <&mbox 2>, <&mbox 3>; + mbox-names = "rx", "tx"; + status = "okay"; + }; + }; +}; diff --git a/samples/subsys/ipc/ipc_service/multi_endpoint/remote/prj.conf b/samples/subsys/ipc/ipc_service/multi_endpoint/remote/prj.conf new file mode 100644 index 00000000000..3d2c799c4eb --- /dev/null +++ b/samples/subsys/ipc/ipc_service/multi_endpoint/remote/prj.conf @@ -0,0 +1,8 @@ +CONFIG_PRINTK=y +CONFIG_LOG_PRINTK=n + +CONFIG_IPC_SERVICE=y +CONFIG_MBOX=y + +CONFIG_LOG=y +CONFIG_IPC_SERVICE_LOG_LEVEL_INF=y diff --git a/samples/subsys/ipc/ipc_service/multi_endpoint/remote/src/main.c b/samples/subsys/ipc/ipc_service/multi_endpoint/remote/src/main.c new file mode 100644 index 00000000000..f285f4b6d23 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/multi_endpoint/remote/src/main.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +#define STACKSIZE (1024) +#define PRIORITY K_PRIO_PREEMPT(2) + +K_THREAD_STACK_DEFINE(ipc0A_stack, STACKSIZE); +K_THREAD_STACK_DEFINE(ipc0B_stack, STACKSIZE); +K_THREAD_STACK_DEFINE(ipc1_stack, STACKSIZE); + +static volatile uint8_t ipc0A_received_data; +static volatile uint8_t ipc0B_received_data; +static volatile uint8_t ipc1_received_data; + +static K_SEM_DEFINE(ipc0A_bound_sem, 0, 1); +static K_SEM_DEFINE(ipc0B_bound_sem, 0, 1); +static K_SEM_DEFINE(ipc1_bound_sem, 0, 1); + +static K_SEM_DEFINE(ipc0A_data_sem, 0, 1); +static K_SEM_DEFINE(ipc0B_data_sem, 0, 1); +static K_SEM_DEFINE(ipc1_data_sem, 0, 1); + +/* + * ==> THREAD 0A (IPC instance 0 - endpoint A) <== + */ + +static void ipc0A_ept_bound(void *priv) +{ + k_sem_give(&ipc0A_bound_sem); +} + +static void ipc0A_ept_recv(const void *data, size_t len, void *priv) +{ + ipc0A_received_data = *((uint8_t *) data); + + k_sem_give(&ipc0A_data_sem); +} + +static struct ipc_ept_cfg ipc0A_ept_cfg = { + .name = "ipc0A", + .cb = { + .bound = ipc0A_ept_bound, + .received = ipc0A_ept_recv, + }, +}; + +static void ipc0A_entry(void *dummy0, void *dummy1, void *dummy2) +{ + ARG_UNUSED(dummy0); + ARG_UNUSED(dummy1); + ARG_UNUSED(dummy2); + + const struct device *ipc0_instance; + unsigned char message = 0; + struct ipc_ept ipc0A_ept; + int ret; + + printk("IPC-service REMOTE [INST 0 - ENDP A] demo started\n"); + + ipc0_instance = DEVICE_DT_GET(DT_NODELABEL(ipc0)); + + ret = ipc_service_open_instance(ipc0_instance); + if (ret < 0 && ret != -EALREADY) { + printk("ipc_service_open_instance() failure\n"); + return; + } + + ret = ipc_service_register_endpoint(ipc0_instance, &ipc0A_ept, &ipc0A_ept_cfg); + if (ret < 0) { + printf("ipc_service_register_endpoint() failure\n"); + return; + } + + k_sem_take(&ipc0A_bound_sem, K_FOREVER); + + while (message < 99) { + k_sem_take(&ipc0A_data_sem, K_FOREVER); + message = ipc0A_received_data; + + printk("REMOTE [0A]: %d\n", message); + + message++; + + ret = ipc_service_send(&ipc0A_ept, &message, sizeof(message)); + if (ret < 0) { + printk("send_message(%d) failed with ret %d\n", message, ret); + break; + } + } + + printk("IPC-service REMOTE [INST 0 - ENDP A] demo ended.\n"); +} +K_THREAD_DEFINE(ipc0A_thread_id, STACKSIZE, ipc0A_entry, NULL, NULL, NULL, PRIORITY, 0, 0); + +/* + * ==> THREAD 0B (IPC instance 0 - endpoint B) <== + */ + +static void ipc0B_ept_bound(void *priv) +{ + k_sem_give(&ipc0B_bound_sem); +} + +static void ipc0B_ept_recv(const void *data, size_t len, void *priv) +{ + ipc0B_received_data = *((uint8_t *) data); + + k_sem_give(&ipc0B_data_sem); +} + +static struct ipc_ept_cfg ipc0B_ept_cfg = { + .name = "ipc0B", + .cb = { + .bound = ipc0B_ept_bound, + .received = ipc0B_ept_recv, + }, +}; + +static void ipc0B_entry(void *dummy0, void *dummy1, void *dummy2) +{ + ARG_UNUSED(dummy0); + ARG_UNUSED(dummy1); + ARG_UNUSED(dummy2); + + const struct device *ipc0_instance; + unsigned char message = 0; + struct ipc_ept ipc0B_ept; + int ret; + + printk("IPC-service REMOTE [INST 0 - ENDP B] demo started\n"); + + ipc0_instance = DEVICE_DT_GET(DT_NODELABEL(ipc0)); + + ret = ipc_service_open_instance(ipc0_instance); + if (ret < 0 && ret != -EALREADY) { + printk("ipc_service_open_instance() failure\n"); + return; + } + + /* + * Wait 1 sec to give the opportunity to the PRIMARY core to register + * the endpoint first + */ + + k_sleep(K_MSEC(1000)); + + ret = ipc_service_register_endpoint(ipc0_instance, &ipc0B_ept, &ipc0B_ept_cfg); + if (ret < 0) { + printf("ipc_service_register_endpoint() failure\n"); + return; + } + + k_sem_take(&ipc0B_bound_sem, K_FOREVER); + + while (message < 99) { + k_sem_take(&ipc0B_data_sem, K_FOREVER); + message = ipc0B_received_data; + + printk("REMOTE [0B]: %d\n", message); + + message++; + + ret = ipc_service_send(&ipc0B_ept, &message, sizeof(message)); + if (ret < 0) { + printk("send_message(%d) failed with ret %d\n", message, ret); + break; + } + } + + printk("IPC-service REMOTE [INST 0 - ENDP B] demo ended.\n"); +} +K_THREAD_DEFINE(ipc0B_thread_id, STACKSIZE, ipc0B_entry, NULL, NULL, NULL, PRIORITY, 0, 0); + +/* + * ==> THREAD 1 (IPC instance 1) <== + * + */ + +static void ipc1_ept_bound(void *priv) +{ + k_sem_give(&ipc1_bound_sem); +} + +static void ipc1_ept_recv(const void *data, size_t len, void *priv) +{ + ipc1_received_data = *((uint8_t *) data); + + k_sem_give(&ipc1_data_sem); +} + +static struct ipc_ept_cfg ipc1_ept_cfg = { + .name = "ipc1", + .cb = { + .bound = ipc1_ept_bound, + .received = ipc1_ept_recv, + }, +}; + +static void ipc1_entry(void *dummy0, void *dummy1, void *dummy2) +{ + ARG_UNUSED(dummy0); + ARG_UNUSED(dummy1); + ARG_UNUSED(dummy2); + + const struct device *ipc1_instance; + unsigned char message = 0; + struct ipc_ept ipc1_ept; + int ret; + + printk("IPC-service REMOTE [INST 1] demo started\n"); + + ipc1_instance = DEVICE_DT_GET(DT_NODELABEL(ipc1)); + + ret = ipc_service_open_instance(ipc1_instance); + if (ret < 0 && ret != -EALREADY) { + printk("ipc_service_open_instance() failure\n"); + return; + } + + ret = ipc_service_register_endpoint(ipc1_instance, &ipc1_ept, &ipc1_ept_cfg); + if (ret < 0) { + printf("ipc_service_register_endpoint() failure\n"); + return; + } + + k_sem_take(&ipc1_bound_sem, K_FOREVER); + + while (message < 99) { + k_sem_take(&ipc1_data_sem, K_FOREVER); + message = ipc1_received_data; + + printk("REMOTE [1]: %d\n", message); + + message++; + + ret = ipc_service_send(&ipc1_ept, &message, sizeof(message)); + if (ret < 0) { + printk("send_message(%d) failed with ret %d\n", message, ret); + break; + } + } + + printk("IPC-service REMOTE [INST 1] demo ended.\n"); +} +K_THREAD_DEFINE(ipc1_thread_id, STACKSIZE, ipc1_entry, NULL, NULL, NULL, PRIORITY, 0, 0); diff --git a/samples/subsys/ipc/ipc_service/multi_endpoint/sample.yaml b/samples/subsys/ipc/ipc_service/multi_endpoint/sample.yaml new file mode 100644 index 00000000000..fdb3c707d8e --- /dev/null +++ b/samples/subsys/ipc/ipc_service/multi_endpoint/sample.yaml @@ -0,0 +1,19 @@ +sample: + name: IPC Service example integration (icmsg multi endpoint backend) +tests: + sample.ipc.multi_endpoint: + platform_allow: nrf5340dk_nrf5340_cpuapp + integration_platforms: + - nrf5340dk_nrf5340_cpuapp + tags: ipc + sysbuild: true + harness: remote + sample.ipc.multi_endpoint.icbmsg: + platform_allow: nrf5340dk_nrf5340_cpuapp + integration_platforms: + - nrf5340dk_nrf5340_cpuapp + tags: ipc + sysbuild: true + extra_args: + DTC_OVERLAY_FILE=boards/nrf5340dk_nrf5340_cpuapp_icbmsg.overlay + remote_DTC_OVERLAY_FILE=boards/nrf5340dk_nrf5340_cpunet_icbmsg.overlay diff --git a/samples/subsys/ipc/ipc_service/multi_endpoint/src/main.c b/samples/subsys/ipc/ipc_service/multi_endpoint/src/main.c new file mode 100644 index 00000000000..4ad5659df38 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/multi_endpoint/src/main.c @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +#define STACKSIZE (4096) +#define PRIORITY K_PRIO_PREEMPT(2) + +K_THREAD_STACK_DEFINE(ipc0A_stack, STACKSIZE); +K_THREAD_STACK_DEFINE(ipc0B_stack, STACKSIZE); +K_THREAD_STACK_DEFINE(ipc1_stack, STACKSIZE); + +static volatile uint8_t ipc0A_received_data; +static volatile uint8_t ipc0B_received_data; +static volatile uint8_t ipc1_received_data; + +static K_SEM_DEFINE(ipc0A_bound_sem, 0, 1); +static K_SEM_DEFINE(ipc0B_bound_sem, 0, 1); +static K_SEM_DEFINE(ipc1_bound_sem, 0, 1); + +static K_SEM_DEFINE(ipc0A_data_sem, 0, 1); +static K_SEM_DEFINE(ipc0B_data_sem, 0, 1); +static K_SEM_DEFINE(ipc1_data_sem, 0, 1); + +/* + * ==> THREAD 0A (IPC instance 0 - endpoint A) <== + */ + +static void ipc0A_ept_bound(void *priv) +{ + k_sem_give(&ipc0A_bound_sem); +} + +static void ipc0A_ept_recv(const void *data, size_t len, void *priv) +{ + ipc0A_received_data = *((uint8_t *) data); + + k_sem_give(&ipc0A_data_sem); +} + +static struct ipc_ept_cfg ipc0A_ept_cfg = { + .name = "ipc0A", + .cb = { + .bound = ipc0A_ept_bound, + .received = ipc0A_ept_recv, + }, +}; + +static void ipc0A_entry(void *dummy0, void *dummy1, void *dummy2) +{ + ARG_UNUSED(dummy0); + ARG_UNUSED(dummy1); + ARG_UNUSED(dummy2); + + const struct device *ipc0_instance; + unsigned char message = 0; + struct ipc_ept ipc0A_ept; + int ret; + + printk("IPC-service HOST [INST 0 - ENDP A] demo started\n"); + + ipc0_instance = DEVICE_DT_GET(DT_NODELABEL(ipc0)); + + ret = ipc_service_open_instance(ipc0_instance); + if (ret < 0 && ret != -EALREADY) { + printk("ipc_service_open_instance() failure\n"); + return; + } + + /* + * Wait 1 sec to give the opportunity to the SECONDARY core to register + * the endpoint first + */ + + k_sleep(K_MSEC(1000)); + + ret = ipc_service_register_endpoint(ipc0_instance, &ipc0A_ept, &ipc0A_ept_cfg); + if (ret < 0) { + printf("ipc_service_register_endpoint() failure\n"); + return; + } + + k_sem_take(&ipc0A_bound_sem, K_FOREVER); + + while (message < 100) { + ret = ipc_service_send(&ipc0A_ept, &message, sizeof(message)); + if (ret < 0) { + printk("send_message(%d) failed with ret %d\n", message, ret); + break; + } + + k_sem_take(&ipc0A_data_sem, K_FOREVER); + message = ipc0A_received_data; + + printk("HOST [0A]: %d\n", message); + message++; + } + + printk("IPC-service HOST [INST 0 - ENDP A] demo ended.\n"); +} +K_THREAD_DEFINE(ipc0A_thread_id, STACKSIZE, ipc0A_entry, NULL, NULL, NULL, PRIORITY, 0, 0); + +/* + * ==> THREAD 0B (IPC instance 0 - endpoint B) <== + */ + +static void ipc0B_ept_bound(void *priv) +{ + k_sem_give(&ipc0B_bound_sem); +} + +static void ipc0B_ept_recv(const void *data, size_t len, void *priv) +{ + ipc0B_received_data = *((uint8_t *) data); + + k_sem_give(&ipc0B_data_sem); +} + +static struct ipc_ept_cfg ipc0B_ept_cfg = { + .name = "ipc0B", + .cb = { + .bound = ipc0B_ept_bound, + .received = ipc0B_ept_recv, + }, +}; + +static void ipc0B_entry(void *dummy0, void *dummy1, void *dummy2) +{ + ARG_UNUSED(dummy0); + ARG_UNUSED(dummy1); + ARG_UNUSED(dummy2); + + const struct device *ipc0_instance; + unsigned char message = 0; + struct ipc_ept ipc0B_ept; + int ret; + + printk("IPC-service HOST [INST 0 - ENDP B] demo started\n"); + + ipc0_instance = DEVICE_DT_GET(DT_NODELABEL(ipc0)); + + ret = ipc_service_open_instance(ipc0_instance); + if (ret < 0 && ret != -EALREADY) { + printk("ipc_service_open_instance() failure\n"); + return; + } + + ret = ipc_service_register_endpoint(ipc0_instance, &ipc0B_ept, &ipc0B_ept_cfg); + if (ret < 0) { + printf("ipc_service_register_endpoint() failure\n"); + return; + } + + k_sem_take(&ipc0B_bound_sem, K_FOREVER); + + while (message < 100) { + ret = ipc_service_send(&ipc0B_ept, &message, sizeof(message)); + if (ret < 0) { + printk("send_message(%d) failed with ret %d\n", message, ret); + break; + } + + k_sem_take(&ipc0B_data_sem, K_FOREVER); + message = ipc0B_received_data; + + printk("HOST [0B]: %d\n", message); + message++; + } + + printk("IPC-service HOST [INST 0 - ENDP B] demo ended.\n"); +} +K_THREAD_DEFINE(ipc0B_thread_id, STACKSIZE, ipc0B_entry, NULL, NULL, NULL, PRIORITY, 0, 0); + +/* + * ==> THREAD 1 (IPC instance 1) <== + */ + +static void ipc1_ept_bound(void *priv) +{ + k_sem_give(&ipc1_bound_sem); +} + +static void ipc1_ept_recv(const void *data, size_t len, void *priv) +{ + ipc1_received_data = *((uint8_t *) data); + + k_sem_give(&ipc1_data_sem); +} + +static struct ipc_ept_cfg ipc1_ept_cfg = { + .name = "ipc1", + .cb = { + .bound = ipc1_ept_bound, + .received = ipc1_ept_recv, + }, +}; + +static void ipc1_entry(void *dummy0, void *dummy1, void *dummy2) +{ + ARG_UNUSED(dummy0); + ARG_UNUSED(dummy1); + ARG_UNUSED(dummy2); + + const struct device *ipc1_instance; + unsigned char message = 0; + struct ipc_ept ipc1_ept; + int ret; + + printk("IPC-service HOST [INST 1] demo started\n"); + + ipc1_instance = DEVICE_DT_GET(DT_NODELABEL(ipc1)); + + ret = ipc_service_open_instance(ipc1_instance); + if (ret < 0 && ret != -EALREADY) { + printk("ipc_service_open_instance() failure\n"); + return; + } + + ret = ipc_service_register_endpoint(ipc1_instance, &ipc1_ept, &ipc1_ept_cfg); + if (ret < 0) { + printf("ipc_service_register_endpoint() failure\n"); + return; + } + + k_sem_take(&ipc1_bound_sem, K_FOREVER); + + /* + * Wait 1 sec to start sending simultaneously with other threads + * the endpoint first + */ + + k_sleep(K_MSEC(1000)); + + while (message < 100) { + ret = ipc_service_send(&ipc1_ept, &message, sizeof(message)); + if (ret < 0) { + printk("send_message(%d) failed with ret %d\n", message, ret); + break; + } + + k_sem_take(&ipc1_data_sem, K_FOREVER); + message = ipc1_received_data; + + printk("HOST [1]: %d\n", message); + message++; + } + + printk("IPC-service HOST [INST 1] demo ended.\n"); +} +K_THREAD_DEFINE(ipc1_thread_id, STACKSIZE, ipc1_entry, NULL, NULL, NULL, PRIORITY, 0, 0); diff --git a/samples/subsys/ipc/ipc_service/multi_endpoint/sysbuild.cmake b/samples/subsys/ipc/ipc_service/multi_endpoint/sysbuild.cmake new file mode 100644 index 00000000000..d0d79b8f240 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/multi_endpoint/sysbuild.cmake @@ -0,0 +1,14 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if("${SB_CONFIG_NET_CORE_BOARD}" STREQUAL "") + message(FATAL_ERROR + "Target ${BOARD} not supported for this sample. " + "There is no remote board selected in Kconfig.sysbuild") +endif() + +ExternalZephyrProject_Add( + APPLICATION remote + SOURCE_DIR ${APP_DIR}/remote + BOARD ${SB_CONFIG_NET_CORE_BOARD} +) diff --git a/samples/subsys/ipc/ipc_service/multi_endpoint/sysbuild.conf b/samples/subsys/ipc/ipc_service/multi_endpoint/sysbuild.conf new file mode 100644 index 00000000000..6408669a847 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/multi_endpoint/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/samples/subsys/ipc/ipc_service/static_vrings/CMakeLists.txt b/samples/subsys/ipc/ipc_service/static_vrings/CMakeLists.txt index c5ae1a2f8d9..6af69691e1e 100644 --- a/samples/subsys/ipc/ipc_service/static_vrings/CMakeLists.txt +++ b/samples/subsys/ipc/ipc_service/static_vrings/CMakeLists.txt @@ -6,27 +6,14 @@ cmake_minimum_required(VERSION 3.20.0) -set(REMOTE_ZEPHYR_DIR ${CMAKE_CURRENT_BINARY_DIR}/ipc_service_remote-prefix/src/ipc_service_remote-build/zephyr) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -if("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpuapp") - set(BOARD_REMOTE "nrf5340dk_nrf5340_cpunet") -else() +if(NOT ("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpuapp")) message(FATAL_ERROR "${BOARD} is not supported for this sample") endif() -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(ipc_service) target_sources(app PRIVATE src/main.c) include(ExternalProject) - -ExternalProject_Add( - ipc_service_remote - SOURCE_DIR ${APPLICATION_SOURCE_DIR}/remote - INSTALL_COMMAND "" # This particular build system has no install command - CMAKE_CACHE_ARGS -DBOARD:STRING=${BOARD_REMOTE} - BUILD_BYPRODUCTS "${REMOTE_ZEPHYR_DIR}/${KERNEL_BIN_NAME}" - # NB: Do we need to pass on more CMake variables? - BUILD_ALWAYS True -) diff --git a/samples/subsys/ipc/ipc_service/static_vrings/Kconfig.sysbuild b/samples/subsys/ipc/ipc_service/static_vrings/Kconfig.sysbuild new file mode 100644 index 00000000000..47884745130 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/static_vrings/Kconfig.sysbuild @@ -0,0 +1,9 @@ +# Copyright 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config NET_CORE_BOARD +string + default "nrf5340dk_nrf5340_cpunet" if $(BOARD) = "nrf5340dk_nrf5340_cpuapp" diff --git a/samples/subsys/ipc/ipc_service/static_vrings/README.rst b/samples/subsys/ipc/ipc_service/static_vrings/README.rst index 59df32c833e..7fbed84cad8 100644 --- a/samples/subsys/ipc/ipc_service/static_vrings/README.rst +++ b/samples/subsys/ipc/ipc_service/static_vrings/README.rst @@ -1,7 +1,8 @@ -.. _static_vrings_sample: +.. zephyr:code-sample:: ipc-static-vrings + :name: IPC service: static vrings backend + :relevant-api: ipc -IPC Service - static vrings - Sample Application -################################################ + Send messages between two cores using the IPC service and static vrings backend. Overview ******** @@ -17,6 +18,7 @@ Building the application for nrf5340dk_nrf5340_cpuapp :zephyr-app: samples/subsys/ipc/ipc_service/static_vrings :board: nrf5340dk_nrf5340_cpuapp :goals: debug + :west-args: --sysbuild Open a serial terminal (minicom, putty, etc.) and connect the board with the following settings: diff --git a/samples/subsys/ipc/ipc_service/static_vrings/remote/sample.yaml b/samples/subsys/ipc/ipc_service/static_vrings/remote/sample.yaml deleted file mode 100644 index ab70e115c9a..00000000000 --- a/samples/subsys/ipc/ipc_service/static_vrings/remote/sample.yaml +++ /dev/null @@ -1,9 +0,0 @@ -sample: - name: IPC Service example integration (OpenAMP static_vrings backend) (remote) -tests: - sample.ipc.static_vrings_remote: - platform_allow: nrf5340dk_nrf5340_cpunet - integration_platforms: - - nrf5340dk_nrf5340_cpunet - tags: ipc - harness: remote diff --git a/samples/subsys/ipc/ipc_service/static_vrings/sample.yaml b/samples/subsys/ipc/ipc_service/static_vrings/sample.yaml index 42e487503ba..3e57abf32eb 100644 --- a/samples/subsys/ipc/ipc_service/static_vrings/sample.yaml +++ b/samples/subsys/ipc/ipc_service/static_vrings/sample.yaml @@ -6,4 +6,5 @@ tests: integration_platforms: - nrf5340dk_nrf5340_cpuapp tags: ipc + sysbuild: true harness: remote diff --git a/samples/subsys/ipc/ipc_service/static_vrings/sysbuild.cmake b/samples/subsys/ipc/ipc_service/static_vrings/sysbuild.cmake new file mode 100644 index 00000000000..d0d79b8f240 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/static_vrings/sysbuild.cmake @@ -0,0 +1,14 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if("${SB_CONFIG_NET_CORE_BOARD}" STREQUAL "") + message(FATAL_ERROR + "Target ${BOARD} not supported for this sample. " + "There is no remote board selected in Kconfig.sysbuild") +endif() + +ExternalZephyrProject_Add( + APPLICATION remote + SOURCE_DIR ${APP_DIR}/remote + BOARD ${SB_CONFIG_NET_CORE_BOARD} +) diff --git a/samples/subsys/ipc/ipc_service/static_vrings/sysbuild.conf b/samples/subsys/ipc/ipc_service/static_vrings/sysbuild.conf new file mode 100644 index 00000000000..6408669a847 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/static_vrings/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/samples/subsys/ipc/openamp/README.rst b/samples/subsys/ipc/openamp/README.rst index fb54261f14f..1ad79dff354 100644 --- a/samples/subsys/ipc/openamp/README.rst +++ b/samples/subsys/ipc/openamp/README.rst @@ -1,7 +1,8 @@ -.. _openAMP_sample: +.. zephyr:code-sample:: openamp + :name: OpenAMP + :relevant-api: ipm_interface -OpenAMP Sample Application -########################## + Send messages between two cores using OpenAMP. Overview ******** diff --git a/samples/subsys/ipc/openamp/boards/mimxrt1160_evk_cm7.overlay b/samples/subsys/ipc/openamp/boards/mimxrt1160_evk_cm7.overlay index 52c68fd5339..7facea692cb 100644 --- a/samples/subsys/ipc/openamp/boards/mimxrt1160_evk_cm7.overlay +++ b/samples/subsys/ipc/openamp/boards/mimxrt1160_evk_cm7.overlay @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + / { chosen { zephyr,ipc_shm = &ocram2_overlay; @@ -17,6 +19,6 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x202c0000 DT_SIZE_K(16)>; zephyr,memory-region="OCRAM2_OVERLAY"; - zephyr,memory-attr = "IO"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; }; }; diff --git a/samples/subsys/ipc/openamp/boards/mimxrt1170_evk_cm7.overlay b/samples/subsys/ipc/openamp/boards/mimxrt1170_evk_cm7.overlay index 52c68fd5339..7facea692cb 100644 --- a/samples/subsys/ipc/openamp/boards/mimxrt1170_evk_cm7.overlay +++ b/samples/subsys/ipc/openamp/boards/mimxrt1170_evk_cm7.overlay @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + / { chosen { zephyr,ipc_shm = &ocram2_overlay; @@ -17,6 +19,6 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x202c0000 DT_SIZE_K(16)>; zephyr,memory-region="OCRAM2_OVERLAY"; - zephyr,memory-attr = "IO"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; }; }; diff --git a/samples/subsys/ipc/openamp/boards/mimxrt1170_evkb_cm7.overlay b/samples/subsys/ipc/openamp/boards/mimxrt1170_evkb_cm7.overlay index a5d921810bb..584538a14f7 100644 --- a/samples/subsys/ipc/openamp/boards/mimxrt1170_evkb_cm7.overlay +++ b/samples/subsys/ipc/openamp/boards/mimxrt1170_evkb_cm7.overlay @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + / { chosen { zephyr,ipc_shm = &ocram2_overlay; @@ -17,6 +19,6 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x202c0000 DT_SIZE_K(16)>; zephyr,memory-region="OCRAM2_OVERLAY"; - zephyr,memory-attr = "IO"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; }; }; diff --git a/samples/subsys/ipc/openamp/remote/boards/mimxrt1160_evk_cm4.overlay b/samples/subsys/ipc/openamp/remote/boards/mimxrt1160_evk_cm4.overlay index fa4d29c3cd1..87159192cf2 100644 --- a/samples/subsys/ipc/openamp/remote/boards/mimxrt1160_evk_cm4.overlay +++ b/samples/subsys/ipc/openamp/remote/boards/mimxrt1160_evk_cm4.overlay @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + / { /* Switch to lpuart2, since primary core uses lpuart1 */ chosen { @@ -33,7 +35,7 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x202c0000 DT_SIZE_K(16)>; zephyr,memory-region="OCRAM2_OVERLAY"; - zephyr,memory-attr = "IO"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; }; }; diff --git a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.overlay b/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.overlay index fa4d29c3cd1..87159192cf2 100644 --- a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.overlay +++ b/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.overlay @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + / { /* Switch to lpuart2, since primary core uses lpuart1 */ chosen { @@ -33,7 +35,7 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x202c0000 DT_SIZE_K(16)>; zephyr,memory-region="OCRAM2_OVERLAY"; - zephyr,memory-attr = "IO"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; }; }; diff --git a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.overlay b/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.overlay index f4ee15de7ed..72510d26166 100644 --- a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.overlay +++ b/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.overlay @@ -33,7 +33,7 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x202c0000 DT_SIZE_K(16)>; zephyr,memory-region="OCRAM2_OVERLAY"; - zephyr,memory-attr = "IO"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; }; }; diff --git a/samples/subsys/ipc/openamp/remote/src/main.c b/samples/subsys/ipc/openamp/remote/src/main.c index 337d0114531..06622d49e44 100644 --- a/samples/subsys/ipc/openamp/remote/src/main.c +++ b/samples/subsys/ipc/openamp/remote/src/main.c @@ -144,6 +144,7 @@ void app_task(void *arg1, void *arg2, void *arg3) ARG_UNUSED(arg1); ARG_UNUSED(arg2); ARG_UNUSED(arg3); + int status = 0; unsigned int message = 0U; struct metal_device *device; @@ -259,7 +260,7 @@ int main(void) { printk("Starting application thread!\n"); k_thread_create(&thread_data, thread_stack, APP_TASK_STACK_SIZE, - (k_thread_entry_t)app_task, + app_task, NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); return 0; } diff --git a/samples/subsys/ipc/openamp/src/main.c b/samples/subsys/ipc/openamp/src/main.c index b2a06ec8a8c..5b2ce5fddbb 100644 --- a/samples/subsys/ipc/openamp/src/main.c +++ b/samples/subsys/ipc/openamp/src/main.c @@ -168,6 +168,7 @@ void app_task(void *arg1, void *arg2, void *arg3) ARG_UNUSED(arg1); ARG_UNUSED(arg2); ARG_UNUSED(arg3); + int status = 0; unsigned int message = 0U; struct metal_device *device; @@ -284,7 +285,7 @@ int main(void) { printk("Starting application thread!\n"); k_thread_create(&thread_data, thread_stack, APP_TASK_STACK_SIZE, - (k_thread_entry_t)app_task, + app_task, NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); #if defined(CONFIG_SOC_MPS2_AN521) || \ diff --git a/samples/subsys/ipc/openamp_rsc_table/README.rst b/samples/subsys/ipc/openamp_rsc_table/README.rst index 313ebb18888..95eaabfae60 100644 --- a/samples/subsys/ipc/openamp_rsc_table/README.rst +++ b/samples/subsys/ipc/openamp_rsc_table/README.rst @@ -1,7 +1,8 @@ -.. _openAMP_rsc_table_sample: +.. zephyr:code-sample:: openamp-rsc-table + :name: OpenAMP using resource table + :relevant-api: ipm_interface -OpenAMP Sample Application using resource table -############################################### + Send messages between two cores using OpenAMP and a resource table. Overview ******** diff --git a/samples/subsys/ipc/openamp_rsc_table/boards/nxp_adsp_imx8m.conf b/samples/subsys/ipc/openamp_rsc_table/boards/nxp_adsp_imx8m.conf index 0f7274227ce..01dd4f8ca3f 100644 --- a/samples/subsys/ipc/openamp_rsc_table/boards/nxp_adsp_imx8m.conf +++ b/samples/subsys/ipc/openamp_rsc_table/boards/nxp_adsp_imx8m.conf @@ -2,3 +2,4 @@ CONFIG_LOG_PRINTK=n CONFIG_IPM_IMX_MAX_DATA_SIZE_16=n CONFIG_IPM_IMX_MAX_DATA_SIZE_4=y CONFIG_OPENAMP_WITH_DCACHE=y +CONFIG_IPM_IMX_FW_READY_REPLY=y diff --git a/samples/subsys/ipc/openamp_rsc_table/src/main_remote.c b/samples/subsys/ipc/openamp_rsc_table/src/main_remote.c index a5bd2e9c76c..ebee382cdf8 100644 --- a/samples/subsys/ipc/openamp_rsc_table/src/main_remote.c +++ b/samples/subsys/ipc/openamp_rsc_table/src/main_remote.c @@ -276,6 +276,7 @@ void app_rpmsg_client_sample(void *arg1, void *arg2, void *arg3) ARG_UNUSED(arg1); ARG_UNUSED(arg2); ARG_UNUSED(arg3); + unsigned int msg_cnt = 0; int ret = 0; @@ -302,6 +303,7 @@ void app_rpmsg_tty(void *arg1, void *arg2, void *arg3) ARG_UNUSED(arg1); ARG_UNUSED(arg2); ARG_UNUSED(arg3); + unsigned char tx_buff[512]; int ret = 0; @@ -335,6 +337,7 @@ void rpmsg_mng_task(void *arg1, void *arg2, void *arg3) ARG_UNUSED(arg1); ARG_UNUSED(arg2); ARG_UNUSED(arg3); + unsigned char *msg; unsigned int len; int ret = 0; @@ -375,13 +378,13 @@ int main(void) { printk("Starting application threads!\n"); k_thread_create(&thread_mng_data, thread_mng_stack, APP_TASK_STACK_SIZE, - (k_thread_entry_t)rpmsg_mng_task, + rpmsg_mng_task, NULL, NULL, NULL, K_PRIO_COOP(8), 0, K_NO_WAIT); k_thread_create(&thread_rp__client_data, thread_rp__client_stack, APP_TASK_STACK_SIZE, - (k_thread_entry_t)app_rpmsg_client_sample, + app_rpmsg_client_sample, NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); k_thread_create(&thread_tty_data, thread_tty_stack, APP_TTY_TASK_STACK_SIZE, - (k_thread_entry_t)app_rpmsg_tty, + app_rpmsg_tty, NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); return 0; } diff --git a/samples/subsys/ipc/rpmsg_service/CMakeLists.txt b/samples/subsys/ipc/rpmsg_service/CMakeLists.txt index 18108f25fa0..7411ab59dae 100644 --- a/samples/subsys/ipc/rpmsg_service/CMakeLists.txt +++ b/samples/subsys/ipc/rpmsg_service/CMakeLists.txt @@ -18,8 +18,10 @@ elseif("${BOARD}" STREQUAL "mps2_an521") set(BOARD_REMOTE "mps2_an521_remote") elseif("${BOARD}" STREQUAL "v2m_musca_b1") set(BOARD_REMOTE "v2m_musca_b1_ns") -elseif("${BOARD}" STREQUAL "esp32") +elseif("${BOARD}" STREQUAL "esp32_devkitc_wrover") set(BOARD_REMOTE "esp32_net") +elseif("${BOARD}" STREQUAL "esp32s3_devkitm") + set(BOARD_REMOTE "esp32s3_devkitm_appcpu") else() message(FATAL_ERROR "${BOARD} was not supported for this sample") endif() @@ -33,7 +35,7 @@ enable_language(C ASM) target_sources(app PRIVATE src/main.c) -if("${BOARD}" STREQUAL "esp32") +if("${BOARD}" STREQUAL "esp32_devkitc_wrover" OR "${BOARD}" STREQUAL "esp32s3_devkitm") set_source_files_properties(${REMOTE_ZEPHYR_DIR}/esp32_net_firmware.c PROPERTIES GENERATED TRUE) target_sources(app PRIVATE src/main.c ${REMOTE_ZEPHYR_DIR}/esp32_net_firmware.c) endif() @@ -52,7 +54,7 @@ ExternalProject_Add( if(("${BOARD}" STREQUAL "lpcxpresso54114_m4")) add_dependencies(core_m0_inc_target rpmsg_service_remote) -elseif("${BOARD}" STREQUAL "esp32") +elseif("${BOARD}" STREQUAL "esp32_devkitc_wrover" OR "${BOARD}" STREQUAL "esp32s3_devkitm") add_dependencies(app rpmsg_service_remote) endif() diff --git a/samples/subsys/ipc/rpmsg_service/README.rst b/samples/subsys/ipc/rpmsg_service/README.rst index bcc35d70e43..ce32b16b61e 100644 --- a/samples/subsys/ipc/rpmsg_service/README.rst +++ b/samples/subsys/ipc/rpmsg_service/README.rst @@ -1,7 +1,8 @@ -.. _RPMsg_Service_sample: +.. zephyr:code-sample:: rpmsg-service + :name: RPMsg service + :relevant-api: rpmsg_service_api -RPMsg Service sample Application -################################ + Send messages between cores using RPMsg service. Overview ******** diff --git a/samples/subsys/ipc/rpmsg_service/boards/esp32_devkitc_wroom.conf b/samples/subsys/ipc/rpmsg_service/boards/esp32_devkitc_wrover.conf similarity index 100% rename from samples/subsys/ipc/rpmsg_service/boards/esp32_devkitc_wroom.conf rename to samples/subsys/ipc/rpmsg_service/boards/esp32_devkitc_wrover.conf diff --git a/samples/subsys/ipc/rpmsg_service/boards/esp32_devkitc_wroom.overlay b/samples/subsys/ipc/rpmsg_service/boards/esp32_devkitc_wrover.overlay similarity index 100% rename from samples/subsys/ipc/rpmsg_service/boards/esp32_devkitc_wroom.overlay rename to samples/subsys/ipc/rpmsg_service/boards/esp32_devkitc_wrover.overlay diff --git a/samples/subsys/ipc/rpmsg_service/boards/esp32s3_devkitm.conf b/samples/subsys/ipc/rpmsg_service/boards/esp32s3_devkitm.conf new file mode 100644 index 00000000000..a8ee714a955 --- /dev/null +++ b/samples/subsys/ipc/rpmsg_service/boards/esp32s3_devkitm.conf @@ -0,0 +1 @@ +CONFIG_SOC_ESP32S3_PROCPU=y diff --git a/samples/subsys/ipc/rpmsg_service/boards/esp32s3_devkitm.overlay b/samples/subsys/ipc/rpmsg_service/boards/esp32s3_devkitm.overlay new file mode 100644 index 00000000000..ad437c16e49 --- /dev/null +++ b/samples/subsys/ipc/rpmsg_service/boards/esp32s3_devkitm.overlay @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Felipe Neves + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + /* + * shared memory reserved for the inter-processor communication + */ + zephyr,ipc_shm = &shm0; + zephyr,ipc = &ipm0; + }; +}; + +&ipm0 { + status = "okay"; +}; diff --git a/samples/subsys/ipc/rpmsg_service/remote/CMakeLists.txt b/samples/subsys/ipc/rpmsg_service/remote/CMakeLists.txt index fa4fe6ebad5..76fc92e6307 100644 --- a/samples/subsys/ipc/rpmsg_service/remote/CMakeLists.txt +++ b/samples/subsys/ipc/rpmsg_service/remote/CMakeLists.txt @@ -10,7 +10,8 @@ if("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpunet" OR "${BOARD}" STREQUAL "lpcxpresso54114_m0" OR "${BOARD}" STREQUAL "mps2_an521_remote" OR "${BOARD}" STREQUAL "v2m_musca_b1_ns" - OR "${BOARD}" STREQUAL "esp32_net") + OR "${BOARD}" STREQUAL "esp32_net" + OR "${BOARD}" STREQUAL "esp32s3_devkitm_appcpu") message(STATUS "${BOARD} compile as slave in this sample") else() message(FATAL_ERROR "${BOARD} was not supported for this sample") diff --git a/samples/subsys/ipc/rpmsg_service/remote/src/main.c b/samples/subsys/ipc/rpmsg_service/remote/src/main.c index 9960a113267..de6de636ff5 100644 --- a/samples/subsys/ipc/rpmsg_service/remote/src/main.c +++ b/samples/subsys/ipc/rpmsg_service/remote/src/main.c @@ -54,6 +54,7 @@ void app_task(void *arg1, void *arg2, void *arg3) ARG_UNUSED(arg1); ARG_UNUSED(arg2); ARG_UNUSED(arg3); + int status = 0; unsigned int message = 0U; @@ -79,7 +80,7 @@ int main(void) { printk("Starting application thread!\n"); k_thread_create(&thread_data, thread_stack, APP_TASK_STACK_SIZE, - (k_thread_entry_t)app_task, + app_task, NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); return 0; } diff --git a/samples/subsys/ipc/rpmsg_service/src/main.c b/samples/subsys/ipc/rpmsg_service/src/main.c index f849bb3ee96..f90df936565 100644 --- a/samples/subsys/ipc/rpmsg_service/src/main.c +++ b/samples/subsys/ipc/rpmsg_service/src/main.c @@ -55,6 +55,7 @@ void app_task(void *arg1, void *arg2, void *arg3) ARG_UNUSED(arg1); ARG_UNUSED(arg2); ARG_UNUSED(arg3); + int status = 0; unsigned int message = 0U; @@ -88,7 +89,7 @@ int main(void) { printk("Starting application thread!\n"); k_thread_create(&thread_data, thread_stack, APP_TASK_STACK_SIZE, - (k_thread_entry_t)app_task, + app_task, NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); #if defined(CONFIG_SOC_MPS2_AN521) || \ diff --git a/samples/subsys/llext/llext.rst b/samples/subsys/llext/llext.rst new file mode 100644 index 00000000000..f9001e2847b --- /dev/null +++ b/samples/subsys/llext/llext.rst @@ -0,0 +1,10 @@ +.. _llext-samples: + +Linkable Loadable Extension Samples +################################### + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* diff --git a/samples/subsys/llext/shell_loader/CMakeLists.txt b/samples/subsys/llext/shell_loader/CMakeLists.txt new file mode 100644 index 00000000000..a9d5d832334 --- /dev/null +++ b/samples/subsys/llext/shell_loader/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(fs_shell) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/subsys/llext/shell_loader/README.rst b/samples/subsys/llext/shell_loader/README.rst new file mode 100644 index 00000000000..583299028be --- /dev/null +++ b/samples/subsys/llext/shell_loader/README.rst @@ -0,0 +1,149 @@ +.. zephyr:code-sample:: llext-shell-loader + :name: Linkable loadable extensions shell module + :relevant-api: llext + + Manage loadable extensions using shell commands. + +Overview +******** + +This example provides shell access to the :ref:`llext` system and provides the +ability to manage loadable code extensions in the shell. + +Requirements +************ + +A board with a supported llext architecture and shell capable console. + +Building +******** + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/llext/shell_loader + :board: tdk_robokit1 + :goals: build + :compact: + +.. note:: You may need to disable memory protection for the sample to work (e.g. CONFIG_ARM_MPU=n). + +Running +******* + +Once the board has booted, you will be presented with a shell prompt. +All the llext system related commands are available as sub-commands of llext +which can be seen with llext help + +.. code-block:: console + + uart:~$ llext help + llext - Loadable extension commands + Subcommands: + list :List loaded extensions and their size in memory + load_hex :Load an elf file encoded in hex directly from the shell input. + Syntax: + + unload :Unload an extension by name. Syntax: + + list_symbols :List extension symbols. Syntax: + + call_fn :Call extension function with prototype void fn(void). Syntax: + + +A hello world C file can be found in tests/subsys/llext/hello_world/hello_world.c + +This can be built into a relocatable elf usable on arm v7 platforms. It can be +inspected with some binutils to see symbols, sections, and relocations. +Then using additional tools converted to a hex string usable by the llext +load_hex shell command. + +On a host machine with the zephyr sdk setup and the arm toolchain in PATH + +.. code-block:: console + + $ arm-zephyr-eabi-gcc -mlong-calls -mthumb -c -o hello_world.elf tests/subsys/llext/hello_world/hello_world.c + $ arm-zephyr-eabi-objdump -r -d -x hello_world.elf + + hello_world.elf: file format elf32-littlearm + hello_world.elf + architecture: armv4t, flags 0x00000011: + HAS_RELOC, HAS_SYMS + start address 0x00000000 + private flags = 0x5000000: [Version5 EABI] + + Sections: + Idx Name Size VMA LMA File off Algn + 0 .text 00000038 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .data 00000000 00000000 00000000 0000006c 2**0 + CONTENTS, ALLOC, LOAD, DATA + 2 .bss 00000000 00000000 00000000 0000006c 2**0 + ALLOC + 3 .rodata 00000025 00000000 00000000 0000006c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 4 .comment 00000021 00000000 00000000 00000091 2**0 + CONTENTS, READONLY + 5 .ARM.attributes 0000002a 00000000 00000000 000000b2 2**0 + CONTENTS, READONLY + SYMBOL TABLE: + 00000000 l df *ABS* 00000000 hello_world.c + 00000000 l d .text 00000000 .text + 00000000 l d .data 00000000 .data + 00000000 l d .bss 00000000 .bss + 00000000 l d .rodata 00000000 .rodata + 00000000 l O .rodata 00000004 number + 00000000 l d .comment 00000000 .comment + 00000000 l d .ARM.attributes 00000000 .ARM.attributes + 00000000 g F .text 00000034 hello_world + 00000000 *UND* 00000000 printk + + + + Disassembly of section .text: + + 00000000 : + 0: b580 push {r7, lr} + 2: af00 add r7, sp, #0 + 4: 4b08 ldr r3, [pc, #32] ; (28 ) + 6: 0018 movs r0, r3 + 8: 4b08 ldr r3, [pc, #32] ; (2c ) + a: f000 f813 bl 34 + e: 222a movs r2, #42 ; 0x2a + 10: 4b07 ldr r3, [pc, #28] ; (30 ) + 12: 0011 movs r1, r2 + 14: 0018 movs r0, r3 + 16: 4b05 ldr r3, [pc, #20] ; (2c ) + 18: f000 f80c bl 34 + 1c: 46c0 nop ; (mov r8, r8) + 1e: 46bd mov sp, r7 + 20: bc80 pop {r7} + 22: bc01 pop {r0} + 24: 4700 bx r0 + 26: 46c0 nop ; (mov r8, r8) + 28: 00000004 .word 0x00000004 + 28: R_ARM_ABS32 .rodata + 2c: 00000000 .word 0x00000000 + 2c: R_ARM_ABS32 printk + 30: 00000014 .word 0x00000014 + 30: R_ARM_ABS32 .rodata + 34: 4718 bx r3 + 36: 46c0 nop ; (mov r8, r8) + + $ xxd -p hello_world.elf | tr -d '\n' + +The resulting hex string can be used to load the extension. + +.. code-block:: console + + uart:~$ llext load_hex hello_world 7f454c4601010100000000000000000001002800010000000000000000000000680200000000000534000000000028000b000a0080b500af084b1800084b00f013f82a22074b11001800054b00f00cf8c046bd4680bc01bc0047c0460400000000000000140000001847c0462a00000068656c6c6f20776f726c640a0000000041206e756d62657220697320256c750a00004743433a20285a65706879722053444b20302e31362e31292031322e322e30004129000000616561626900011f000000053454000602080109011204140115011703180119011a011e06000000000000000000000000000000000100000000000000000000000400f1ff000000000000000000000000030001000000000000000000000000000300030000000000000000000000000003000400000000000000000000000000030005000f00000000000000000000000000050012000000000000000400000001000500190000000000000000000000000001000f0000002800000000000000000001001900000034000000000000000000010000000000000000000000000003000600000000000000000000000000030007001c000000010000003400000012000100280000000000000000000000100000000068656c6c6f5f776f726c642e63002464006e756d6265720024740068656c6c6f5f776f726c64007072696e746b000028000000020500002c000000020e00003000000002050000002e73796d746162002e737472746162002e7368737472746162002e72656c2e74657874002e64617461002e627373002e726f64617461002e636f6d6d656e74002e41524d2e6174747269627574657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f0000000100000006000000000000003400000038000000000000000000000004000000000000001b000000090000004000000000000000fc0100001800000008000000010000000400000008000000250000000100000003000000000000006c00000000000000000000000000000001000000000000002b0000000800000003000000000000006c0000000000000000000000000000000100000000000000300000000100000002000000000000006c00000025000000000000000000000004000000000000003800000001000000300000000000000091000000210000000000000000000000010000000100000041000000030000700000000000000000b20000002a0000000000000000000000010000000000000001000000020000000000000000000000dc000000f0000000090000000d000000040000001000000009000000030000000000000000000000cc0100002f0000000000000000000000010000000000000011000000030000000000000000000000140200005100000000000000000000000100000000000000 + +This extension can then be seen in the list of loaded extensions (`list`), its symbols printed +(`list_symbols`), and the hello_world function which the extension exports can be called and +run (`call_fn`). + +.. code-block:: console + + uart:~$ llext call_fn hello_world hello_world + hello world + A number is 42 + +In this sample there are 3 absolute (R_ARM_ABS32) relocations, 2 of which are meant to hold addresses into the .rodata sections where the strings are located. A third is an address of where the printk function (symbol) can be found. At load time llext replaces the values in the .text section with real memory addresses so that printk works as expected with the strings included in the hello world sample. diff --git a/samples/subsys/llext/shell_loader/prj.conf b/samples/subsys/llext/shell_loader/prj.conf new file mode 100644 index 00000000000..0e0d38fdcf4 --- /dev/null +++ b/samples/subsys/llext/shell_loader/prj.conf @@ -0,0 +1,12 @@ +CONFIG_LOG=y +CONFIG_LOG_MODE_IMMEDIATE=y + +CONFIG_SHELL=y +CONFIG_SHELL_CMD_BUFF_SIZE=8192 +CONFIG_SHELL_LOG_LEVEL_INF=y +CONFIG_SHELL_STACK_SIZE=4096 + +CONFIG_LLEXT=y +CONFIG_LLEXT_LOG_LEVEL_DBG=y +CONFIG_LLEXT_HEAP_SIZE=8 +CONFIG_LLEXT_SHELL=y diff --git a/samples/subsys/llext/shell_loader/sample.yaml b/samples/subsys/llext/shell_loader/sample.yaml new file mode 100644 index 00000000000..acb30def4da --- /dev/null +++ b/samples/subsys/llext/shell_loader/sample.yaml @@ -0,0 +1,14 @@ +sample: + description: Loadable extensions with shell sample + name: Extension loader shell +tests: + sample.llext.shell: + tags: shell llext + harness: keyboard + filter: not CONFIG_CPU_HAS_MMU and not CONFIG_SOC_SERIES_S32ZE_R52 + arch_allow: arm + extra_configs: + - CONFIG_ARM_MPU=n + # Broken platforms + platform_exclude: + - nuvoton_pfm_m487 # See #63167 diff --git a/samples/subsys/llext/shell_loader/src/main.c b/samples/subsys/llext/shell_loader/src/main.c new file mode 100644 index 00000000000..f22be157314 --- /dev/null +++ b/samples/subsys/llext/shell_loader/src/main.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL +#include +LOG_MODULE_REGISTER(app); + +int main(void) +{ + return 0; +} diff --git a/samples/subsys/logging/ble_backend/README.rst b/samples/subsys/logging/ble_backend/README.rst index 2c3726dc0bf..8324bbbd99f 100644 --- a/samples/subsys/logging/ble_backend/README.rst +++ b/samples/subsys/logging/ble_backend/README.rst @@ -1,7 +1,8 @@ -.. _logger_ble_backend: +.. zephyr:code-sample:: logging-ble-backend + :name: BLE logging backend + :relevant-api: log_api log_backend bt_gatt -Logging: BLE Backend -######################## + Send log messages over BLE using the BLE logging backend. Overview ******** diff --git a/samples/subsys/logging/dictionary/README.rst b/samples/subsys/logging/dictionary/README.rst index be7176b9af4..2253ff18320 100644 --- a/samples/subsys/logging/dictionary/README.rst +++ b/samples/subsys/logging/dictionary/README.rst @@ -1,9 +1,13 @@ -.. _logging_dictionary_sample: +.. zephyr:code-sample:: logging-dictionary + :name: Dictionary-based logging + :relevant-api: log_api -Dictionary-based Logging Sample -############################### + Output binary log data using the dictionary-based logging API. -This is a sample app which utilizes dictionary based logging and +Overview +******** + +This is a sample app which utilizes :ref:`dictionary-based logging ` and the UART backend. This is configured to output binary log data in hexadecimal so it could be run in terminal. diff --git a/samples/subsys/logging/logger/README.rst b/samples/subsys/logging/logger/README.rst index e3ed5e04e64..e82247efe94 100644 --- a/samples/subsys/logging/logger/README.rst +++ b/samples/subsys/logging/logger/README.rst @@ -1,7 +1,8 @@ -.. _logger_sample: +.. zephyr:code-sample:: logging + :name: Logging + :relevant-api: log_api log_ctrl -Logging -########### + Output log messages to the console using the logging subsystem. Overview ******** diff --git a/samples/subsys/logging/logger/sample.yaml b/samples/subsys/logging/logger/sample.yaml index 5dca694782a..2364dabd6b4 100644 --- a/samples/subsys/logging/logger/sample.yaml +++ b/samples/subsys/logging/logger/sample.yaml @@ -4,7 +4,7 @@ sample: tests: sample.logger.basic: integration_platforms: - - native_posix + - native_sim tags: logging harness: console harness_config: @@ -22,6 +22,8 @@ tests: - frdm_k64f tags: logging filter: CONFIG_HAS_SEGGER_RTT + arch_exclude: + - posix harness: keyboard extra_configs: - CONFIG_LOG_BACKEND_RTT=y @@ -30,6 +32,8 @@ tests: sample.logger.usermode: integration_platforms: - mps2_an385 + arch_exclude: + - posix tags: - logging - usermode diff --git a/samples/subsys/logging/multidomain/CMakeLists.txt b/samples/subsys/logging/multidomain/CMakeLists.txt index 378ff66c7d8..a0cc842a6a8 100644 --- a/samples/subsys/logging/multidomain/CMakeLists.txt +++ b/samples/subsys/logging/multidomain/CMakeLists.txt @@ -6,15 +6,13 @@ cmake_minimum_required(VERSION 3.20.0) -set(REMOTE_ZEPHYR_DIR ${CMAKE_CURRENT_BINARY_DIR}/log_multidomain_remote-prefix/src/log_multidomain_remote-build/zephyr) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -if("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpuapp") - set(BOARD_REMOTE "nrf5340dk_nrf5340_cpunet") -else() +if(NOT(("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpuapp") + OR ("${BOARD}" STREQUAL "nrf5340bsim_nrf5340_cpuapp"))) message(FATAL_ERROR "${BOARD} is not supported for this sample") endif() -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(log_multidomain) target_sources(app PRIVATE src/main.c) @@ -22,14 +20,3 @@ target_sources(app PRIVATE src/main.c) if (CONFIG_IPC_SERVICE) target_sources(app PRIVATE src/ipc_service.c) endif() - -include(ExternalProject) - -ExternalProject_Add( - log_multidomain_remote - SOURCE_DIR ${APPLICATION_SOURCE_DIR}/remote - INSTALL_COMMAND "" # This particular build system has no install command - CMAKE_CACHE_ARGS -DBOARD:STRING=${BOARD_REMOTE} - BUILD_BYPRODUCTS "${REMOTE_ZEPHYR_DIR}/${KERNEL_BIN_NAME}" - BUILD_ALWAYS True -) diff --git a/samples/subsys/logging/multidomain/Kconfig.sysbuild b/samples/subsys/logging/multidomain/Kconfig.sysbuild new file mode 100644 index 00000000000..b6dc3d0a6d0 --- /dev/null +++ b/samples/subsys/logging/multidomain/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config NET_CORE_BOARD +string + default "nrf5340dk_nrf5340_cpunet" if $(BOARD) = "nrf5340dk_nrf5340_cpuapp" + default "nrf5340bsim_nrf5340_cpunet" if $(BOARD) = "nrf5340bsim_nrf5340_cpuapp" diff --git a/samples/subsys/logging/multidomain/boards/nrf5340bsim_nrf5340_cpuapp.conf b/samples/subsys/logging/multidomain/boards/nrf5340bsim_nrf5340_cpuapp.conf new file mode 100644 index 00000000000..f14ca9ebc20 --- /dev/null +++ b/samples/subsys/logging/multidomain/boards/nrf5340bsim_nrf5340_cpuapp.conf @@ -0,0 +1,4 @@ +CONFIG_MBOX_NRFX_IPC=y +# For the mailbox to be initialized logger initialization is delayed like in real HW +CONFIG_LOG_PROCESS_THREAD=y +CONFIG_LOG_MODE_DEFERRED=y diff --git a/samples/subsys/logging/multidomain/boards/nrf5340bsim_nrf5340_cpuapp.overlay b/samples/subsys/logging/multidomain/boards/nrf5340bsim_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000..fbcced93153 --- /dev/null +++ b/samples/subsys/logging/multidomain/boards/nrf5340bsim_nrf5340_cpuapp.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf5340dk_nrf5340_cpuapp.overlay" diff --git a/samples/subsys/logging/multidomain/remote/boards/nrf5340bsim_nrf5340_cpunet.conf b/samples/subsys/logging/multidomain/remote/boards/nrf5340bsim_nrf5340_cpunet.conf new file mode 100644 index 00000000000..2d6de6e7c7c --- /dev/null +++ b/samples/subsys/logging/multidomain/remote/boards/nrf5340bsim_nrf5340_cpunet.conf @@ -0,0 +1,5 @@ +CONFIG_MBOX_NRFX_IPC=y +CONFIG_BUILD_OUTPUT_EXE=n +# For the mailbox to be initialized logger initialization is delayed like in real HW +CONFIG_LOG_PROCESS_THREAD=y +CONFIG_LOG_MODE_DEFERRED=y diff --git a/samples/subsys/logging/multidomain/remote/boards/nrf5340bsim_nrf5340_cpunet.overlay b/samples/subsys/logging/multidomain/remote/boards/nrf5340bsim_nrf5340_cpunet.overlay new file mode 100644 index 00000000000..ccb145fa34b --- /dev/null +++ b/samples/subsys/logging/multidomain/remote/boards/nrf5340bsim_nrf5340_cpunet.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf5340dk_nrf5340_cpunet.overlay" diff --git a/samples/subsys/logging/multidomain/remote/boards/nrf5340dk_nrf5340_cpunet.conf b/samples/subsys/logging/multidomain/remote/boards/nrf5340dk_nrf5340_cpunet.conf index a1ab15fae14..cb04b37b233 100644 --- a/samples/subsys/logging/multidomain/remote/boards/nrf5340dk_nrf5340_cpunet.conf +++ b/samples/subsys/logging/multidomain/remote/boards/nrf5340dk_nrf5340_cpunet.conf @@ -1 +1,2 @@ CONFIG_MBOX_NRFX_IPC=y +CONFIG_MPU_STACK_GUARD=y diff --git a/samples/subsys/logging/multidomain/remote/prj.conf b/samples/subsys/logging/multidomain/remote/prj.conf index 65d5bc08f58..11cddd823fb 100644 --- a/samples/subsys/logging/multidomain/remote/prj.conf +++ b/samples/subsys/logging/multidomain/remote/prj.conf @@ -15,6 +15,5 @@ CONFIG_LOG_PRINTK=n CONFIG_LOG_BUFFER_SIZE=4096 CONFIG_ASSERT=y -CONFIG_MPU_STACK_GUARD=y CONFIG_LOG_BACKEND_UART=n CONFIG_LOG_BACKEND_RTT=n diff --git a/samples/subsys/logging/multidomain/sample.yaml b/samples/subsys/logging/multidomain/sample.yaml index 737a44ffded..79523c9951a 100644 --- a/samples/subsys/logging/multidomain/sample.yaml +++ b/samples/subsys/logging/multidomain/sample.yaml @@ -1,9 +1,31 @@ sample: name: Logging in multi-domain environment +common: + sysbuild: true + tags: ipc tests: - sample.logging.multidomain.ipc_static_vrings: - platform_allow: nrf5340dk_nrf5340_cpuapp + sample.logging.multidomain.ipc_static_vrings.hw: + platform_allow: + - nrf5340dk_nrf5340_cpuapp integration_platforms: - nrf5340dk_nrf5340_cpuapp - tags: ipc build_only: true + sample.logging.multidomain.ipc_static_vrings.simu: + platform_allow: + - nrf5340bsim_nrf5340_cpuapp + integration_platforms: + - nrf5340bsim_nrf5340_cpuapp + harness: console + harness_config: + type: multi_line + ordered: false + regex: + - "IPC-service REMOTE \\[INST 1\\] demo started" + - "app: loop: 0" + - "app: ipc open" + - "app: wait for bound" + - "app: bounded" + - "app: REMOTE \\[1\\]: 0" + - "app: HOST \\[1\\]: 1" + - "IPC-service REMOTE \\[INST 1\\] demo ended." + - "app: IPC-service HOST \\[INST 1\\] demo ended." diff --git a/samples/subsys/logging/multidomain/sysbuild.cmake b/samples/subsys/logging/multidomain/sysbuild.cmake new file mode 100644 index 00000000000..496a7a03f9d --- /dev/null +++ b/samples/subsys/logging/multidomain/sysbuild.cmake @@ -0,0 +1,20 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if("${SB_CONFIG_NET_CORE_BOARD}" STREQUAL "") + message(FATAL_ERROR + "Target ${BOARD} not supported for this sample. " + "There is no remote board selected in Kconfig.sysbuild") +endif() + +set(NET_APP remote) + +ExternalZephyrProject_Add( + APPLICATION ${NET_APP} + SOURCE_DIR ${APP_DIR}/${NET_APP} + BOARD ${SB_CONFIG_NET_CORE_BOARD} +) + +native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) + +native_simulator_set_final_executable(${DEFAULT_IMAGE}) diff --git a/samples/subsys/logging/multidomain/sysbuild.conf b/samples/subsys/logging/multidomain/sysbuild.conf new file mode 100644 index 00000000000..6408669a847 --- /dev/null +++ b/samples/subsys/logging/multidomain/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/samples/subsys/lorawan/class_a/README.rst b/samples/subsys/lorawan/class_a/README.rst index ba72fe1d4da..3a7a7944997 100644 --- a/samples/subsys/lorawan/class_a/README.rst +++ b/samples/subsys/lorawan/class_a/README.rst @@ -1,12 +1,13 @@ -.. _lorawan_class_a_sample: +.. zephyr:code-sample:: lorawan-class-a + :name: LoRaWAN class A device + :relevant-api: lorawan_api -LoRaWAN Class A Sample -###################### + Join a LoRaWAN network and send a message periodically. Overview ******** -A simple application to demonstrate the LoRaWAN subsystem of Zephyr. +A simple application to demonstrate the :ref:`LoRaWAN subsystem ` of Zephyr. Building and Running ******************** diff --git a/samples/subsys/lorawan/class_a/src/main.c b/samples/subsys/lorawan/class_a/src/main.c index 9209bcaffb6..76ff5529f57 100644 --- a/samples/subsys/lorawan/class_a/src/main.c +++ b/samples/subsys/lorawan/class_a/src/main.c @@ -90,6 +90,7 @@ int main(void) join_cfg.otaa.join_eui = join_eui; join_cfg.otaa.app_key = app_key; join_cfg.otaa.nwk_key = app_key; + join_cfg.otaa.dev_nonce = 0u; LOG_INF("Joining network over OTAA"); ret = lorawan_join(&join_cfg); diff --git a/samples/subsys/mgmt/hawkbit/README.rst b/samples/subsys/mgmt/hawkbit/README.rst index 1a0e095529b..db96c518213 100644 --- a/samples/subsys/mgmt/hawkbit/README.rst +++ b/samples/subsys/mgmt/hawkbit/README.rst @@ -1,12 +1,13 @@ -.. _hawkbit-api-sample: +.. zephyr:code-sample:: hawkbit-api + :name: Eclipse hawkBit Direct Device Integration API + :relevant-api: hawkbit -Hawkbit Direct Device Integration API sample -############################################ + Update a device using Eclipse hawkBit DDI API. Overview ******** -The hawkbit update server provides REST resources which are consumed by the +The Eclipse hawkBit update server provides REST resources which are consumed by the device to retrieve software update tasks. This API is based on HTTP standards and a polling mechanism. diff --git a/samples/subsys/mgmt/hawkbit/prj.conf b/samples/subsys/mgmt/hawkbit/prj.conf index a96c9461a83..e8539c7a120 100644 --- a/samples/subsys/mgmt/hawkbit/prj.conf +++ b/samples/subsys/mgmt/hawkbit/prj.conf @@ -53,7 +53,7 @@ CONFIG_LOG=y CONFIG_HAWKBIT_LOG_LEVEL_INF=n #General Config -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_LOG_BUFFER_SIZE=4096 #Generate HEX output diff --git a/samples/subsys/mgmt/hawkbit/sample.yaml b/samples/subsys/mgmt/hawkbit/sample.yaml index 4df4c6d3f69..6a60360e423 100644 --- a/samples/subsys/mgmt/hawkbit/sample.yaml +++ b/samples/subsys/mgmt/hawkbit/sample.yaml @@ -1,5 +1,5 @@ common: - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED sample: description: Hawkbit Firmware Over-the-Air (FOTA) name: hawkbit diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/README.rst b/samples/subsys/mgmt/mcumgr/smp_svr/README.rst index c988e414564..c24103815af 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/README.rst +++ b/samples/subsys/mgmt/mcumgr/smp_svr/README.rst @@ -1,7 +1,7 @@ -.. _smp_svr_sample: +.. zephyr:code-sample:: smp-svr + :name: SMP server -SMP Server Sample -################# + Implement a Simple Management Protocol (SMP) server. Overview ******** diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/overlay-bt.conf b/samples/subsys/mgmt/mcumgr/smp_svr/overlay-bt.conf index b2db245ddd4..8942068beb4 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/overlay-bt.conf +++ b/samples/subsys/mgmt/mcumgr/smp_svr/overlay-bt.conf @@ -14,6 +14,7 @@ CONFIG_MCUMGR_TRANSPORT_BT_CONN_PARAM_CONTROL=y # Enable the Shell mcumgr transport. CONFIG_BASE64=y +CONFIG_CRC=y CONFIG_SHELL=y CONFIG_SHELL_BACKEND_SERIAL=y CONFIG_MCUMGR_TRANSPORT_SHELL=y diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/overlay-cdc.conf b/samples/subsys/mgmt/mcumgr/smp_svr/overlay-cdc.conf index 6fb996b0e5d..1d98bc9899d 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/overlay-cdc.conf +++ b/samples/subsys/mgmt/mcumgr/smp_svr/overlay-cdc.conf @@ -7,3 +7,4 @@ CONFIG_CONSOLE=y # USB backend is serial device CONFIG_MCUMGR_TRANSPORT_UART=y CONFIG_BASE64=y +CONFIG_CRC=y diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/overlay-serial-console.conf b/samples/subsys/mgmt/mcumgr/smp_svr/overlay-serial-console.conf index 24e15c9d092..ec2fadf3cfe 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/overlay-serial-console.conf +++ b/samples/subsys/mgmt/mcumgr/smp_svr/overlay-serial-console.conf @@ -1,5 +1,6 @@ # Enable console with MCUmgr pass through CONFIG_BASE64=y +CONFIG_CRC=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_UART_CONSOLE_MCUMGR=y diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/overlay-serial.conf b/samples/subsys/mgmt/mcumgr/smp_svr/overlay-serial.conf index cf542238a48..47d4e8d0b85 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/overlay-serial.conf +++ b/samples/subsys/mgmt/mcumgr/smp_svr/overlay-serial.conf @@ -1,4 +1,5 @@ # Enable the serial MCUmgr transport. CONFIG_BASE64=y +CONFIG_CRC=y CONFIG_MCUMGR_TRANSPORT_UART=y CONFIG_CONSOLE=y diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/overlay-shell-mgmt.conf b/samples/subsys/mgmt/mcumgr/smp_svr/overlay-shell-mgmt.conf index 235cd04b32d..01156e341ec 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/overlay-shell-mgmt.conf +++ b/samples/subsys/mgmt/mcumgr/smp_svr/overlay-shell-mgmt.conf @@ -1,5 +1,6 @@ # Enable shell commands. CONFIG_BASE64=y +CONFIG_CRC=y CONFIG_SHELL=y CONFIG_SHELL_BACKEND_SERIAL=n CONFIG_MCUMGR_GRP_SHELL=y diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/overlay-shell.conf b/samples/subsys/mgmt/mcumgr/smp_svr/overlay-shell.conf index 8021768c12d..59c8b18ed9e 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/overlay-shell.conf +++ b/samples/subsys/mgmt/mcumgr/smp_svr/overlay-shell.conf @@ -1,5 +1,6 @@ # Enable the shell MCUmgr transport. CONFIG_BASE64=y +CONFIG_CRC=y CONFIG_SHELL=y CONFIG_SHELL_BACKEND_SERIAL=y CONFIG_MCUMGR_TRANSPORT_SHELL=y diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/src/main.c b/samples/subsys/mgmt/mcumgr/smp_svr/src/main.c index 2e4f206502e..8b0c0b44a88 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/src/main.c +++ b/samples/subsys/mgmt/mcumgr/smp_svr/src/main.c @@ -73,7 +73,9 @@ int main(void) if (IS_ENABLED(CONFIG_USB_DEVICE_STACK)) { rc = usb_enable(NULL); - if (rc) { + + /* Ignore EALREADY error as USB CDC is likely already initialised */ + if (rc != 0 && rc != -EALREADY) { LOG_ERR("Failed to enable USB"); return 0; } diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild.conf b/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild.conf new file mode 100644 index 00000000000..34f887190b3 --- /dev/null +++ b/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild.conf @@ -0,0 +1,2 @@ +# Enable MCUboot bootloader support +SB_CONFIG_BOOTLOADER_MCUBOOT=y diff --git a/samples/subsys/mgmt/updatehub/README.rst b/samples/subsys/mgmt/updatehub/README.rst index 0324ab97025..ad29354146e 100644 --- a/samples/subsys/mgmt/updatehub/README.rst +++ b/samples/subsys/mgmt/updatehub/README.rst @@ -1,7 +1,8 @@ -.. _updatehub_fota_sample: +.. zephyr:code-sample:: updatehub-fota + :name: UpdateHub embedded Firmware Over-The-Air (FOTA) update + :relevant-api: updatehub -UpdateHub embedded Firmware Over-The-Air (FOTA) sample -###################################################### + Perform Firmware Over-The-Air (FOTA) updates using UpdateHub. Overview ******** @@ -203,7 +204,7 @@ Step 4.3: Build for Modem Modem needs add ``overlay-modem.conf``. Now, a DTC overlay file is used to configure the glue between the modem and an arduino headers. The modem config -uses PPP over GSM modem, see :ref:`gsm-modem-sample`. +uses PPP over GSM modem, see :zephyr:code-sample:`gsm-modem` sample application. .. zephyr-app-commands:: :zephyr-app: zephyr/samples/subsys/mgmt/updatehub @@ -220,7 +221,7 @@ Step 4.4: Build for IEEE 802.15.4 [experimental] For IEEE 802.15.4 needs add ``overlay-802154.conf``. This requires two nodes: one will be the host and the second one will be the device under test. The validation needs a Linux kernel >= 4.9 with all 6loWPAN support. The start -point is try reproduce the Zephyr :ref:`wpanusb-sample`. It is out of scope +point is try reproduce the Zephyr :zephyr:code-sample:`wpan-usb`. It is out of scope at this moment provide support since it is experimental. The gateway was tested with both native linux driver and ``atusb`` and with ``wpanusb`` sample. diff --git a/samples/subsys/modbus/rtu_client/README.rst b/samples/subsys/modbus/rtu_client/README.rst index 1159cfa771f..a432a07b83e 100644 --- a/samples/subsys/modbus/rtu_client/README.rst +++ b/samples/subsys/modbus/rtu_client/README.rst @@ -1,7 +1,8 @@ -.. _modbus-rtu-client-sample: +.. zephyr:code-sample:: modbus-rtu-client + :name: Modbus RTU client + :relevant-api: modbus -Modbus RTU Client Sample -######################## + Communicate with a Modbus RTU server. Overview ******** @@ -16,8 +17,7 @@ This sample has been tested with the nRF52840-DK and FRDM-K64F boards, but it should work with any board that has a free UART interface. RTU client example is running on an evaluation board and communicates -with another board that has been prepared according to the description -`modbus-rtu-server-sample`. +with another board running the :zephyr:code-sample:`modbus-rtu-server` sample. In addition to the evaluation board a RS-485 shield may be used. The shield converts UART TX, RX signals to RS-485. diff --git a/samples/subsys/modbus/rtu_server/README.rst b/samples/subsys/modbus/rtu_server/README.rst index 973339e1cb7..289aa73ea7b 100644 --- a/samples/subsys/modbus/rtu_server/README.rst +++ b/samples/subsys/modbus/rtu_server/README.rst @@ -1,7 +1,8 @@ -.. _modbus-rtu-server-sample: +.. zephyr:code-sample:: modbus-rtu-server + :name: Modbus RTU server + :relevant-api: modbus -Modbus RTU Server Sample -######################## + Implement a Modbus RTU server exposing Modbus commands to control LEDs. Overview ******** diff --git a/samples/subsys/modbus/tcp_gateway/README.rst b/samples/subsys/modbus/tcp_gateway/README.rst index eeb13c0c5d9..5fbc02b41ef 100644 --- a/samples/subsys/modbus/tcp_gateway/README.rst +++ b/samples/subsys/modbus/tcp_gateway/README.rst @@ -1,7 +1,8 @@ -.. _modbus-gateway-sample: +.. zephyr:code-sample:: modbus-gateway + :name: Modbus TCP-to-serial gateway + :relevant-api: modbus bsd_sockets -Modbus TCP to serial line gateway sample -######################################## + Implement a gateway between an Ethernet TCP-IP network and a Modbus serial line. Overview ******** @@ -16,8 +17,8 @@ This sample has been tested with FRDM-K64F board, but it should work with any board or shield that has a network interface. Gateway example is running on an evaluation board and communicates -with another board that has been prepared according to the description -`modbus-rtu-server-sample`. Client is running on a PC or laptop. +with another board that has been prepared according to the instructions in +:zephyr:code-sample:`modbus-rtu-server` sample. Client is running on a PC or laptop. The description of this sample uses `PyModbus`_ (Pymodbus REPL). The user can of course try out other client implementations with this sample. diff --git a/samples/subsys/modbus/tcp_server/README.rst b/samples/subsys/modbus/tcp_server/README.rst index d994d1044c8..1b3f777db45 100644 --- a/samples/subsys/modbus/tcp_server/README.rst +++ b/samples/subsys/modbus/tcp_server/README.rst @@ -1,7 +1,8 @@ -.. _modbus-tcp-server-sample: +.. zephyr:code-sample:: modbus-tcp-server + :name: Modbus TCP server + :relevant-api: modbus bsd_sockets -Modbus TCP Server Sample -######################## + Implement a Modbus TCP server exposing Modbus commands to control LEDs. Overview ******** diff --git a/samples/subsys/modbus/tcp_server/src/main.c b/samples/subsys/modbus/tcp_server/src/main.c index 15ca917a175..163fca98fc6 100644 --- a/samples/subsys/modbus/tcp_server/src/main.c +++ b/samples/subsys/modbus/tcp_server/src/main.c @@ -26,6 +26,43 @@ static const struct gpio_dt_spec led_dev[] = { GPIO_DT_SPEC_GET(DT_ALIAS(led2), gpios), }; +static int custom_read_count; + +static bool custom_handler(const int iface, + const struct modbus_adu *rx_adu, + struct modbus_adu *tx_adu, + uint8_t *const excep_code, + void *const user_data) +{ + const uint8_t request_len = 2; + const uint8_t response_len = 6; + int *read_counter = (int *)user_data; + uint8_t subfunc; + uint8_t data_len; + + LOG_INF("Custom Modbus handler called"); + + if (rx_adu->length != request_len) { + LOG_WRN("Custom request length doesn't match"); + *excep_code = MODBUS_EXC_ILLEGAL_DATA_VAL; + return true; + } + + subfunc = rx_adu->data[0]; + data_len = rx_adu->data[1]; + + LOG_INF("Custom function called with subfunc=%u, data_len=%u", subfunc, data_len); + (*read_counter)++; + sys_put_be16(0x5555, tx_adu->data); + sys_put_be16(0xAAAA, &tx_adu->data[2]); + sys_put_be16(*read_counter, &tx_adu->data[4]); + tx_adu->length = response_len; + + return true; +} + +MODBUS_CUSTOM_FC_DEFINE(custom, custom_handler, 101, &custom_read_count); + static int init_leds(void) { int err; @@ -155,6 +192,7 @@ const static struct modbus_iface_param server_param = { static int init_modbus_server(void) { char iface_name[] = "RAW_0"; + int err; server_iface = modbus_iface_get_by_name(iface_name); @@ -164,7 +202,13 @@ static int init_modbus_server(void) return -ENODEV; } - return modbus_init_server(server_iface, server_param); + err = modbus_init_server(server_iface, server_param); + + if (err < 0) { + return err; + } + + return modbus_register_user_fc(server_iface, &modbus_cfg_custom); } static int modbus_tcp_reply(int client, struct modbus_adu *adu) diff --git a/samples/subsys/nvs/README.rst b/samples/subsys/nvs/README.rst index b9a59b0fa75..ac1df6f9cf7 100644 --- a/samples/subsys/nvs/README.rst +++ b/samples/subsys/nvs/README.rst @@ -1,7 +1,8 @@ -.. _nvs-sample: +.. zephyr:code-sample:: nvs + :name: Non-Volatile Storage (NVS) + :relevant-api: nvs_high_level_api -NVS: Non-Volatile Storage -######################### + Store and retrieve data from flash using the NVS API. Overview ******** diff --git a/samples/subsys/nvs/boards/esp32c3_luatos_core.conf b/samples/subsys/nvs/boards/esp32c3_luatos_core.conf new file mode 100644 index 00000000000..26d52701286 --- /dev/null +++ b/samples/subsys/nvs/boards/esp32c3_luatos_core.conf @@ -0,0 +1 @@ +CONFIG_HEAP_MEM_POOL_SIZE=256 diff --git a/samples/subsys/nvs/boards/esp32c3_luatos_core_usb.conf b/samples/subsys/nvs/boards/esp32c3_luatos_core_usb.conf new file mode 100644 index 00000000000..26d52701286 --- /dev/null +++ b/samples/subsys/nvs/boards/esp32c3_luatos_core_usb.conf @@ -0,0 +1 @@ +CONFIG_HEAP_MEM_POOL_SIZE=256 diff --git a/samples/subsys/pm/device_pm/sample.yaml b/samples/subsys/pm/device_pm/sample.yaml index ab22dee2ed2..13a57cd4b2a 100644 --- a/samples/subsys/pm/device_pm/sample.yaml +++ b/samples/subsys/pm/device_pm/sample.yaml @@ -5,8 +5,10 @@ tests: platform_allow: - nrf52840dk_nrf52840 - nrf52dk_nrf52832 + - qemu_x86 + - mps2_an385 integration_platforms: - - nrf52840dk_nrf52840 + - qemu_x86 tags: power harness: console harness_config: diff --git a/samples/subsys/pm/device_pm/src/dummy_driver.c b/samples/subsys/pm/device_pm/src/dummy_driver.c index c0d0f3873be..ffc4decb1eb 100644 --- a/samples/subsys/pm/device_pm/src/dummy_driver.c +++ b/samples/subsys/pm/device_pm/src/dummy_driver.c @@ -115,5 +115,5 @@ int dummy_init(const struct device *dev) PM_DEVICE_DEFINE(dummy_driver, dummy_device_pm_action); DEVICE_DEFINE(dummy_driver, DUMMY_DRIVER_NAME, &dummy_init, - PM_DEVICE_GET(dummy_driver), NULL, NULL, APPLICATION, - CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &funcs); + PM_DEVICE_GET(dummy_driver), NULL, NULL, POST_KERNEL, + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &funcs); diff --git a/samples/subsys/pm/latency/boards/native_posix.overlay b/samples/subsys/pm/latency/boards/native_posix.overlay index c718cbdd1ff..6a3daca3241 100644 --- a/samples/subsys/pm/latency/boards/native_posix.overlay +++ b/samples/subsys/pm/latency/boards/native_posix.overlay @@ -1,31 +1 @@ -/* - * Copyright (c) 2022 Nordic Semiconductor ASA - * SPDX-License-Identifier: Apache-2.0 - */ - -/ { - power-states { - runtime_idle: runtime-idle { - compatible = "zephyr,power-state"; - power-state-name = "runtime-idle"; - min-residency-us = <1000000>; - exit-latency-us = <10000>; - }; - suspend_to_idle: suspend-to-idle { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - min-residency-us = <1100000>; - exit-latency-us = <20000>; - }; - standby: standby { - compatible = "zephyr,power-state"; - power-state-name = "standby"; - min-residency-us = <1200000>; - exit-latency-us = <30000>; - }; - }; -}; - -&cpu0 { - cpu-power-states = <&runtime_idle &suspend_to_idle &standby>; -}; +#include "native_sim.overlay" diff --git a/samples/subsys/pm/latency/boards/native_sim.overlay b/samples/subsys/pm/latency/boards/native_sim.overlay new file mode 100644 index 00000000000..c718cbdd1ff --- /dev/null +++ b/samples/subsys/pm/latency/boards/native_sim.overlay @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + power-states { + runtime_idle: runtime-idle { + compatible = "zephyr,power-state"; + power-state-name = "runtime-idle"; + min-residency-us = <1000000>; + exit-latency-us = <10000>; + }; + suspend_to_idle: suspend-to-idle { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + min-residency-us = <1100000>; + exit-latency-us = <20000>; + }; + standby: standby { + compatible = "zephyr,power-state"; + power-state-name = "standby"; + min-residency-us = <1200000>; + exit-latency-us = <30000>; + }; + }; +}; + +&cpu0 { + cpu-power-states = <&runtime_idle &suspend_to_idle &standby>; +}; diff --git a/samples/subsys/pm/latency/sample.yaml b/samples/subsys/pm/latency/sample.yaml index 4989a63dbe7..2d6f68879c3 100644 --- a/samples/subsys/pm/latency/sample.yaml +++ b/samples/subsys/pm/latency/sample.yaml @@ -2,9 +2,11 @@ sample: name: Demonstrate usage of the PM policy latency APIs tests: sample.pm.latency: - platform_allow: native_posix - integration_platforms: + platform_allow: - native_posix + - native_sim + integration_platforms: + - native_sim tags: pm harness: console harness_config: diff --git a/samples/subsys/pm/latency/src/test.c b/samples/subsys/pm/latency/src/test.c index b9d31f4415c..bf94c9c1bf8 100644 --- a/samples/subsys/pm/latency/src/test.c +++ b/samples/subsys/pm/latency/src/test.c @@ -60,4 +60,4 @@ int dev_test_init(const struct device *dev) static struct dev_test_data data; DEVICE_DEFINE(dev_test, "dev_test", &dev_test_init, NULL, &data, NULL, - APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &dev_test_api); + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &dev_test_api); diff --git a/samples/subsys/portability/cmsis_rtos_v1/philosophers/README.rst b/samples/subsys/portability/cmsis_rtos_v1/philosophers/README.rst index 5e8d70f1a60..6817cae7883 100644 --- a/samples/subsys/portability/cmsis_rtos_v1/philosophers/README.rst +++ b/samples/subsys/portability/cmsis_rtos_v1/philosophers/README.rst @@ -1,7 +1,7 @@ -.. _cmsis_rtos_v1-sample: +.. zephyr:code-sample:: cmsis-rtos-v1 + :name: Dining Philosophers (CMSIS RTOS V1 APIs) -Dining Philosophers (CMSIS RTOS V1 APIs) -######################################## + Implement a solution to the Dining Philosophers problem using CMSIS RTOS V1. Overview ******** diff --git a/samples/subsys/portability/cmsis_rtos_v1/philosophers/sample.yaml b/samples/subsys/portability/cmsis_rtos_v1/philosophers/sample.yaml index 4f4fe6cf366..64fd5053d85 100644 --- a/samples/subsys/portability/cmsis_rtos_v1/philosophers/sample.yaml +++ b/samples/subsys/portability/cmsis_rtos_v1/philosophers/sample.yaml @@ -2,7 +2,7 @@ sample: name: CMSIS_RTOS_V1 Dining Philosophers common: integration_platforms: - - native_posix + - native_sim extra_args: DEBUG_PRINTF=1 tags: cmsis_rtos min_ram: 32 diff --git a/samples/subsys/portability/cmsis_rtos_v1/timer_synchronization/README.rst b/samples/subsys/portability/cmsis_rtos_v1/timer_synchronization/README.rst index 68db8860a75..53b76b3f182 100644 --- a/samples/subsys/portability/cmsis_rtos_v1/timer_synchronization/README.rst +++ b/samples/subsys/portability/cmsis_rtos_v1/timer_synchronization/README.rst @@ -1,7 +1,7 @@ -.. _cmsis_rtos_v1-sync_sample: +.. zephyr:code-sample:: cmsis-rtos-v1-sync + :name: Synchronization using CMSIS RTOS V1 APIs -Synchronization using CMSIS RTOS V1 APIs -######################################## + Use timers and message queues from CMSIS RTOS v1 API to synchronize threads. Overview ******** diff --git a/samples/subsys/portability/cmsis_rtos_v1/timer_synchronization/sample.yaml b/samples/subsys/portability/cmsis_rtos_v1/timer_synchronization/sample.yaml index 2d8df98d770..e87d8449938 100644 --- a/samples/subsys/portability/cmsis_rtos_v1/timer_synchronization/sample.yaml +++ b/samples/subsys/portability/cmsis_rtos_v1/timer_synchronization/sample.yaml @@ -3,7 +3,7 @@ sample: tests: sample.portability.cmsis_rtos_v1.timer_synchronization: integration_platforms: - - native_posix + - native_sim tags: cmsis_rtos min_ram: 32 min_flash: 34 diff --git a/samples/subsys/portability/cmsis_rtos_v2/philosophers/README.rst b/samples/subsys/portability/cmsis_rtos_v2/philosophers/README.rst index a87af61973c..e5889223ceb 100644 --- a/samples/subsys/portability/cmsis_rtos_v2/philosophers/README.rst +++ b/samples/subsys/portability/cmsis_rtos_v2/philosophers/README.rst @@ -1,7 +1,7 @@ -.. _cmsis_rtos_v2-sample: +.. zephyr:code-sample:: cmsis-rtos-v2 + :name: Dining Philosophers (CMSIS RTOS V2 APIs) -Dining Philosophers (CMSIS RTOS V2 APIs) -######################################## + Implement a solution to the Dining Philosophers problem using CMSIS RTOS V2. Overview ******** diff --git a/samples/subsys/portability/cmsis_rtos_v2/philosophers/sample.yaml b/samples/subsys/portability/cmsis_rtos_v2/philosophers/sample.yaml index 5f15a4d1ce0..af5a69f0af7 100644 --- a/samples/subsys/portability/cmsis_rtos_v2/philosophers/sample.yaml +++ b/samples/subsys/portability/cmsis_rtos_v2/philosophers/sample.yaml @@ -2,7 +2,7 @@ sample: name: CMSIS_RTOS_V2 Dining Philosophers common: integration_platforms: - - native_posix + - native_sim extra_args: DEBUG_PRINTF=1 tags: cmsis_rtos min_ram: 32 diff --git a/samples/subsys/portability/cmsis_rtos_v2/timer_synchronization/README.rst b/samples/subsys/portability/cmsis_rtos_v2/timer_synchronization/README.rst index 0acee5e1883..e5c2d1f8ff4 100644 --- a/samples/subsys/portability/cmsis_rtos_v2/timer_synchronization/README.rst +++ b/samples/subsys/portability/cmsis_rtos_v2/timer_synchronization/README.rst @@ -1,7 +1,7 @@ -.. _cmsis_rtos_v2-sync_sample: +.. zephyr:code-sample:: cmsis-rtos-v2-sync + :name: Synchronization using CMSIS RTOS V2 APIs -Synchronization using CMSIS RTOS V2 APIs -######################################## + Use timers and message queues from CMSIS RTOS v2 API to synchronize threads. Overview ******** diff --git a/samples/subsys/portability/cmsis_rtos_v2/timer_synchronization/sample.yaml b/samples/subsys/portability/cmsis_rtos_v2/timer_synchronization/sample.yaml index 61c1a2079fe..f4a8ad690cf 100644 --- a/samples/subsys/portability/cmsis_rtos_v2/timer_synchronization/sample.yaml +++ b/samples/subsys/portability/cmsis_rtos_v2/timer_synchronization/sample.yaml @@ -3,7 +3,9 @@ sample: tests: sample.portability.cmsis_rtos_v2.timer_synchronization: integration_platforms: - - native_posix + - native_sim + platform_exclude: + - qemu_arc_hs5x # See issue #62405 tags: cmsis_rtos min_ram: 32 min_flash: 34 diff --git a/samples/subsys/portability/portability.rst b/samples/subsys/portability/portability.rst index 1be238d794c..b47ee35edc9 100644 --- a/samples/subsys/portability/portability.rst +++ b/samples/subsys/portability/portability.rst @@ -4,7 +4,7 @@ Portability Samples ################### .. toctree:: - :maxdepth: 2 + :maxdepth: 1 :glob: **/* diff --git a/samples/subsys/rtio/sensor_batch_processing/prj.conf b/samples/subsys/rtio/sensor_batch_processing/prj.conf index 68a9ea43ad2..340b3ed9a00 100644 --- a/samples/subsys/rtio/sensor_batch_processing/prj.conf +++ b/samples/subsys/rtio/sensor_batch_processing/prj.conf @@ -1,5 +1,4 @@ CONFIG_LOG=y CONFIG_LOG_MODE_MINIMAL=y -CONFIG_LOG_DEFAULT_LEVEL=4 CONFIG_RTIO=y CONFIG_RTIO_SYS_MEM_BLOCKS=y diff --git a/samples/subsys/rtio/sensor_batch_processing/sample.yaml b/samples/subsys/rtio/sensor_batch_processing/sample.yaml index 956af3a567a..99732a25574 100644 --- a/samples/subsys/rtio/sensor_batch_processing/sample.yaml +++ b/samples/subsys/rtio/sensor_batch_processing/sample.yaml @@ -4,7 +4,7 @@ tests: sample.rtio.sensor_batch_processing: tags: rtio integration_platforms: - - native_posix + - native_sim harness: console harness_config: type: multi_line diff --git a/samples/subsys/rtio/sensor_batch_processing/src/main.c b/samples/subsys/rtio/sensor_batch_processing/src/main.c index c9306c68f01..8fa1a3641ad 100644 --- a/samples/subsys/rtio/sensor_batch_processing/src/main.c +++ b/samples/subsys/rtio/sensor_batch_processing/src/main.c @@ -8,7 +8,7 @@ #include #include -LOG_MODULE_REGISTER(main); +LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG); #define N (8) #define M (N/2) diff --git a/samples/subsys/rtio/sensor_batch_processing/src/vnd_sensor.c b/samples/subsys/rtio/sensor_batch_processing/src/vnd_sensor.c index c00dfd9d421..a8662c04998 100644 --- a/samples/subsys/rtio/sensor_batch_processing/src/vnd_sensor.c +++ b/samples/subsys/rtio/sensor_batch_processing/src/vnd_sensor.c @@ -11,7 +11,7 @@ #include #include -LOG_MODULE_REGISTER(vnd_sensor); +LOG_MODULE_REGISTER(vnd_sensor, LOG_LEVEL_DBG); struct vnd_sensor_config { uint32_t sample_period; diff --git a/samples/subsys/sensing/simple/README.rst b/samples/subsys/sensing/simple/README.rst index 11a72341fcb..f8ff0857b31 100644 --- a/samples/subsys/sensing/simple/README.rst +++ b/samples/subsys/sensing/simple/README.rst @@ -1,7 +1,8 @@ -.. _sensing subsytem-sample: +.. zephyr:code-sample:: sensing + :name: Sensing subsystem + :relevant-api: sensing_api -Sensing subsystem sample -######################## + Get high-level sensor data in defined intervals. Overview ******** @@ -25,14 +26,14 @@ The program runs in the following sequence: Building and Running ******************** -This application can be built and executed on native_posix as follows: +This application can be built and executed on :ref:`native_sim ` as follows: .. zephyr-app-commands:: :zephyr-app: samples/subsys/sensing/simple :host-os: unix - :board: native_posix + :board: native_sim :goals: run :compact: -To build for another board, change "native_posix" above to that board's name. -At the current stage, it only support native posix +To build for another board, change "native_sim" above to that board's name. +At the current stage, it only support native sim. diff --git a/samples/subsys/sensing/simple/boards/native_posix.conf b/samples/subsys/sensing/simple/boards/native_sim.conf similarity index 100% rename from samples/subsys/sensing/simple/boards/native_posix.conf rename to samples/subsys/sensing/simple/boards/native_sim.conf diff --git a/samples/subsys/sensing/simple/boards/native_posix.overlay b/samples/subsys/sensing/simple/boards/native_sim.overlay similarity index 100% rename from samples/subsys/sensing/simple/boards/native_posix.overlay rename to samples/subsys/sensing/simple/boards/native_sim.overlay diff --git a/samples/subsys/sensing/simple/sample.yaml b/samples/subsys/sensing/simple/sample.yaml index b930aff274b..de2508c0d49 100644 --- a/samples/subsys/sensing/simple/sample.yaml +++ b/samples/subsys/sensing/simple/sample.yaml @@ -4,13 +4,14 @@ sample: common: tags: sensing integration_platforms: - - native_posix + - native_sim harness: console harness_config: type: multi_line regex: - "sensing subsystem run successfully" tests: - sample.subsys.sensing.simple: - platform_allow: native_posix + sample.sensing.simple: + platform_allow: + - native_sim tags: sensing diff --git a/samples/subsys/settings/README.rst b/samples/subsys/settings/README.rst index 9a986735bf2..82f8b797e86 100644 --- a/samples/subsys/settings/README.rst +++ b/samples/subsys/settings/README.rst @@ -1,7 +1,8 @@ -.. _settings_subsys_sample: +.. zephyr:code-sample:: settings + :name: Settings API + :relevant-api: settings settings_rt settings_name_proc -Settings sample -############### + Load and save configuration values using the settings API. Overview ******** diff --git a/samples/subsys/settings/boards/esp32c3_luatos_core.conf b/samples/subsys/settings/boards/esp32c3_luatos_core.conf new file mode 100644 index 00000000000..498fb072287 --- /dev/null +++ b/samples/subsys/settings/boards/esp32c3_luatos_core.conf @@ -0,0 +1,4 @@ +CONFIG_HEAP_MEM_POOL_SIZE=256 +CONFIG_NVS=y +CONFIG_SETTINGS_NVS=y +CONFIG_MPU_ALLOW_FLASH_WRITE=y diff --git a/samples/subsys/settings/boards/esp32c3_luatos_core_usb.conf b/samples/subsys/settings/boards/esp32c3_luatos_core_usb.conf new file mode 100644 index 00000000000..498fb072287 --- /dev/null +++ b/samples/subsys/settings/boards/esp32c3_luatos_core_usb.conf @@ -0,0 +1,4 @@ +CONFIG_HEAP_MEM_POOL_SIZE=256 +CONFIG_NVS=y +CONFIG_SETTINGS_NVS=y +CONFIG_MPU_ALLOW_FLASH_WRITE=y diff --git a/samples/subsys/settings/boards/esp32s3_luatos_core.conf b/samples/subsys/settings/boards/esp32s3_luatos_core.conf new file mode 100644 index 00000000000..498fb072287 --- /dev/null +++ b/samples/subsys/settings/boards/esp32s3_luatos_core.conf @@ -0,0 +1,4 @@ +CONFIG_HEAP_MEM_POOL_SIZE=256 +CONFIG_NVS=y +CONFIG_SETTINGS_NVS=y +CONFIG_MPU_ALLOW_FLASH_WRITE=y diff --git a/samples/subsys/settings/boards/esp32s3_luatos_core_usb.conf b/samples/subsys/settings/boards/esp32s3_luatos_core_usb.conf new file mode 100644 index 00000000000..498fb072287 --- /dev/null +++ b/samples/subsys/settings/boards/esp32s3_luatos_core_usb.conf @@ -0,0 +1,4 @@ +CONFIG_HEAP_MEM_POOL_SIZE=256 +CONFIG_NVS=y +CONFIG_SETTINGS_NVS=y +CONFIG_MPU_ALLOW_FLASH_WRITE=y diff --git a/samples/subsys/settings/boards/native_posix.overlay b/samples/subsys/settings/boards/native_posix.overlay index 0e4839ad026..6a3daca3241 100644 --- a/samples/subsys/settings/boards/native_posix.overlay +++ b/samples/subsys/settings/boards/native_posix.overlay @@ -1,22 +1 @@ -/* - * Copyright (c) 2019 Jan Van Winkel - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/delete-node/ &storage_partition; -/delete-node/ &scratch_partition; - -&flash0 { - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - storage_partition: partition@70000 { - label = "storage"; - reg = <0x00070000 0x8000>; - }; - }; -}; +#include "native_sim.overlay" diff --git a/samples/subsys/settings/boards/native_posix_64.overlay b/samples/subsys/settings/boards/native_posix_64.overlay index 0e4839ad026..6a3daca3241 100644 --- a/samples/subsys/settings/boards/native_posix_64.overlay +++ b/samples/subsys/settings/boards/native_posix_64.overlay @@ -1,22 +1 @@ -/* - * Copyright (c) 2019 Jan Van Winkel - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/delete-node/ &storage_partition; -/delete-node/ &scratch_partition; - -&flash0 { - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - storage_partition: partition@70000 { - label = "storage"; - reg = <0x00070000 0x8000>; - }; - }; -}; +#include "native_sim.overlay" diff --git a/samples/subsys/settings/boards/native_sim.conf b/samples/subsys/settings/boards/native_sim.conf new file mode 100644 index 00000000000..21877f886f3 --- /dev/null +++ b/samples/subsys/settings/boards/native_sim.conf @@ -0,0 +1,5 @@ +# Enable the LittleFS file system. +CONFIG_FILE_SYSTEM=y +CONFIG_FILE_SYSTEM_LITTLEFS=y +CONFIG_SETTINGS_FILE=y +CONFIG_SETTINGS_FILE_PATH="/ff/settings/run" diff --git a/samples/subsys/settings/boards/native_sim.overlay b/samples/subsys/settings/boards/native_sim.overlay new file mode 100644 index 00000000000..0e4839ad026 --- /dev/null +++ b/samples/subsys/settings/boards/native_sim.overlay @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2019 Jan Van Winkel + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/delete-node/ &storage_partition; +/delete-node/ &scratch_partition; + +&flash0 { + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + storage_partition: partition@70000 { + label = "storage"; + reg = <0x00070000 0x8000>; + }; + }; +}; diff --git a/samples/subsys/settings/boards/native_sim_64.conf b/samples/subsys/settings/boards/native_sim_64.conf new file mode 100644 index 00000000000..21877f886f3 --- /dev/null +++ b/samples/subsys/settings/boards/native_sim_64.conf @@ -0,0 +1,5 @@ +# Enable the LittleFS file system. +CONFIG_FILE_SYSTEM=y +CONFIG_FILE_SYSTEM_LITTLEFS=y +CONFIG_SETTINGS_FILE=y +CONFIG_SETTINGS_FILE_PATH="/ff/settings/run" diff --git a/samples/subsys/settings/boards/native_sim_64.overlay b/samples/subsys/settings/boards/native_sim_64.overlay new file mode 100644 index 00000000000..6a3daca3241 --- /dev/null +++ b/samples/subsys/settings/boards/native_sim_64.overlay @@ -0,0 +1 @@ +#include "native_sim.overlay" diff --git a/samples/subsys/settings/sample.yaml b/samples/subsys/settings/sample.yaml index 47276f1e697..2cd51d1405d 100644 --- a/samples/subsys/settings/sample.yaml +++ b/samples/subsys/settings/sample.yaml @@ -9,9 +9,11 @@ tests: - qemu_x86 - native_posix - native_posix_64 + - native_sim + - native_sim_64 - mr_canhubk3 integration_platforms: - - native_posix + - native_sim harness: console harness_config: type: multi_line diff --git a/samples/subsys/shell/devmem_load/README.md b/samples/subsys/shell/devmem_load/README.md index e4c457bf6a9..98b4059dcaf 100644 --- a/samples/subsys/shell/devmem_load/README.md +++ b/samples/subsys/shell/devmem_load/README.md @@ -20,7 +20,7 @@ west flash Building for boards without UART interrupt support: ```bash -west build -b native_posix -- -DOVERLAY_CONFIG=prj_poll.conf samples/subsys/shell/devmem_load +west build -b native_sim -- -DOVERLAY_CONFIG=prj_poll.conf samples/subsys/shell/devmem_load ``` ## Running After connecting to the UART console you should see the following output: diff --git a/samples/subsys/shell/devmem_load/sample.yaml b/samples/subsys/shell/devmem_load/sample.yaml index eca1e1f65cd..2d59490a0eb 100644 --- a/samples/subsys/shell/devmem_load/sample.yaml +++ b/samples/subsys/shell/devmem_load/sample.yaml @@ -9,7 +9,7 @@ common: tests: sample.devmem_load.polled: integration_platforms: - - native_posix + - native_sim extra_args: OVERLAY_CONFIG="prj_poll.conf" sample.devmem_load.uart.interrupt: integration_platforms: diff --git a/samples/subsys/shell/fs/README.rst b/samples/subsys/shell/fs/README.rst index 5482b2e050d..f3d86083225 100644 --- a/samples/subsys/shell/fs/README.rst +++ b/samples/subsys/shell/fs/README.rst @@ -1,7 +1,8 @@ -.. _shell-fs-sample: +.. zephyr:code-sample:: shell-fs + :name: File system shell + :relevant-api: file_system_api -File system shell example -######################### + Access a LittleFS file system partition in flash using the file system shell. Overview ******** @@ -16,12 +17,38 @@ A board with LittleFS file system support and UART console Building ******** -Native Posix -============ +native_sim +========== + +You can build this sample for :ref:`native_sim ` with: + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/shell/fs + :board: native_sim + :goals: build + :compact: + +Which by default will use the flash simulator. The flash simulator will use a file, +:file:`flash.bin`, in the current directory to keep the flash content. +You have several options to control this. You can check them with: + +.. code-block:: console + + zephyr/zephyr.exe -help + +Check the :ref:`native_sim UART documentation ` for information on how to connect +to the UART. + +With FUSE access in the host filesystem +--------------------------------------- + +If you enable the :ref:`host FUSE filsystem access ` +you will also have the flash filesystem mounted and accessible from your Linux host filesystem. Before starting a build, make sure that the i386 pkgconfig directory is in your search path and that a 32-bit version of libfuse is installed. For more -background information on this requirement see :ref:`native_posix`. +background information on this requirement check +:ref:`the native_sim documentation `. .. code-block:: console @@ -29,12 +56,11 @@ background information on this requirement see :ref:`native_posix`. .. zephyr-app-commands:: :zephyr-app: samples/subsys/shell/fs - :board: native_posix + :board: native_sim + :gen-args: -DCONFIG_FUSE_FS_ACCESS=y :goals: build :compact: -See :ref:`native_posix` on how to connect to the UART. - Reel Board ========== @@ -48,7 +74,7 @@ Particle Xenon ============== This target is customized to support the same SPI NOR partition table as -the :ref:`littlefs-sample`. +the :zephyr:code-sample:`littlefs` sample. .. zephyr-app-commands:: :zephyr-app: samples/subsys/shell/fs @@ -197,7 +223,7 @@ Remove a file or directory Flash Host Access ================= -For the Native POSIX board the flash partitions can be accessed from the host +For the :ref:`native sim board ` the flash partitions can be accessed from the host Linux system. By default the flash partitions are accessible through the directory *flash* diff --git a/samples/subsys/shell/fs/boards/native_posix.conf b/samples/subsys/shell/fs/boards/native_posix.conf deleted file mode 100644 index 80357cdf245..00000000000 --- a/samples/subsys/shell/fs/boards/native_posix.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_FUSE_FS_ACCESS=y diff --git a/samples/subsys/shell/fs/boards/native_posix_64.conf b/samples/subsys/shell/fs/boards/native_posix_64.conf deleted file mode 100644 index 80357cdf245..00000000000 --- a/samples/subsys/shell/fs/boards/native_posix_64.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_FUSE_FS_ACCESS=y diff --git a/samples/subsys/shell/fs/sample.yaml b/samples/subsys/shell/fs/sample.yaml index e66f984e929..2f30aad68bb 100644 --- a/samples/subsys/shell/fs/sample.yaml +++ b/samples/subsys/shell/fs/sample.yaml @@ -1,25 +1,30 @@ sample: description: FS shell sample name: FS shell +common: + tags: + - shell + - filesystem + harness: keyboard tests: sample.filesystem.shell: - tags: - - shell - - filesystem - harness: keyboard platform_allow: - reel_board - mimxrt1060_evk - mr_canhubk3 + - native_sim integration_platforms: - reel_board - + sample.filesystem.shell.fuse: + platform_allow: + - native_sim + extra_configs: + - CONFIG_FUSE_FS_ACCESS=y + # This test cannot be run in CI as we lack the fuse library + skip: true sample.filesystem.shell.flash_load: tags: - - shell - - filesystem - flash_load - harness: keyboard platform_allow: nrf52dk_nrf52832 extra_args: CONF_FILE=prj_flash_load.conf integration_platforms: diff --git a/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.conf b/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.conf index ad18b0509ce..489e3f9fe16 100644 --- a/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.conf +++ b/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.conf @@ -19,3 +19,11 @@ CONFIG_COUNTER=y # Enable Timer shell commands CONFIG_COUNTER_SHELL=y + +#SiP SVC Service +CONFIG_ARM_SIP_SVC_DRIVER=y +CONFIG_ARM_SIP_SVC_SUBSYS=y +CONFIG_ARM_SIP_SVC_SUBSYS_SINGLY_OPEN=y + +#SiP SVC Service Shell +CONFIG_ARM_SIP_SVC_SUBSYS_SHELL=y diff --git a/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.overlay b/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.overlay index 86a4fdb4843..a35c307aeca 100644 --- a/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.overlay +++ b/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.overlay @@ -26,3 +26,8 @@ &timer3 { status = "okay"; }; + +&sip_smc { + status = "okay"; + zephyr,num-clients = <2>; +}; diff --git a/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex_socdk.conf b/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex_socdk.conf new file mode 100644 index 00000000000..22a3788b1b8 --- /dev/null +++ b/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex_socdk.conf @@ -0,0 +1,23 @@ +# Copyright (c) 2023, Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +# Misc +CONFIG_HEAP_MEM_POOL_SIZE=16384 +CONFIG_SHELL_STACK_SIZE=8192 + +# Setting the Shell prompt +CONFIG_SHELL_PROMPT_UART="agilex$ " + +# Setting the max argc +CONFIG_SHELL_ARGC_MAX=12 + +# Enable the Zephyr boot banner +CONFIG_BOOT_BANNER=y + +#SiP SVC Service +CONFIG_ARM_SIP_SVC_DRIVER=y +CONFIG_ARM_SIP_SVC_SUBSYS=y +CONFIG_ARM_SIP_SVC_SUBSYS_SINGLY_OPEN=y + +#SiP SVC Service Shell +CONFIG_ARM_SIP_SVC_SUBSYS_SHELL=y diff --git a/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex_socdk.overlay b/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex_socdk.overlay new file mode 100644 index 00000000000..7b96b8e2b28 --- /dev/null +++ b/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex_socdk.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2023 Intel Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * The overlay file should be used to enable any + * dts nodes required by this shell application for this + * board. + */ + +&sip_smc { + status = "okay"; + zephyr,num-clients = <2>; +}; diff --git a/samples/subsys/shell/shell_module/sample.yaml b/samples/subsys/shell/shell_module/sample.yaml index 7aac79eac90..95ac36bc6b3 100644 --- a/samples/subsys/shell/shell_module/sample.yaml +++ b/samples/subsys/shell/shell_module/sample.yaml @@ -7,7 +7,7 @@ tests: harness: keyboard min_ram: 40 integration_platforms: - - native_posix + - native_sim - intel_socfpga_agilex5_socdk sample.shell.shell_module.usb: depends_on: usb_device @@ -20,14 +20,14 @@ tests: - OVERLAY_CONFIG="overlay-usb.conf" - DTC_OVERLAY_FILE="usb.overlay" integration_platforms: - - native_posix + - native_sim sample.shell.shell_module.minimal: filter: CONFIG_SERIAL and dt_chosen_enabled("zephyr,shell-uart") tags: shell harness: keyboard extra_args: CONF_FILE="prj_minimal.conf" integration_platforms: - - native_posix + - native_sim sample.shell.shell_module.getopt: integration_platforms: - qemu_x86 @@ -51,7 +51,7 @@ tests: min_ram: 40 extra_args: CONF_FILE="prj_login.conf" integration_platforms: - - native_posix + - native_sim sample.shell.shell_module.robot: harness: robot harness_config: diff --git a/samples/subsys/sip_svc/boards/intel_socfpga_agilex5_socdk.overlay b/samples/subsys/sip_svc/boards/intel_socfpga_agilex5_socdk.overlay new file mode 100644 index 00000000000..4a6c02a6b1e --- /dev/null +++ b/samples/subsys/sip_svc/boards/intel_socfpga_agilex5_socdk.overlay @@ -0,0 +1,11 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (C) 2023, Intel Corporation + * + */ + +&sip_smc { + status = "okay"; + zephyr,num-clients = <1>; +}; diff --git a/samples/subsys/subsys.rst b/samples/subsys/subsys.rst index 0ea09d7a7d3..bf58c7dda63 100644 --- a/samples/subsys/subsys.rst +++ b/samples/subsys/subsys.rst @@ -4,6 +4,7 @@ Various Subsystems Samples ########################## .. toctree:: + :titlesonly: :maxdepth: 2 :glob: diff --git a/samples/subsys/task_wdt/README.rst b/samples/subsys/task_wdt/README.rst index 03cfd7e90c3..21372f87d2d 100644 --- a/samples/subsys/task_wdt/README.rst +++ b/samples/subsys/task_wdt/README.rst @@ -1,12 +1,13 @@ -.. _task_wdt_sample: +.. zephyr:code-sample:: task-wdt + :name: Task watchdog + :relevant-api: task_wdt_api -Task Watchdog Sample -#################### + Monitor a thread using a task watchdog. Overview ******** -This sample allows to test the task watchdog subsystem. +This sample allows to test the :ref:`task watchdog ` subsystem. Building and Running ******************** diff --git a/samples/subsys/task_wdt/sample.yaml b/samples/subsys/task_wdt/sample.yaml index 1c9c300a878..334d6e3a24f 100644 --- a/samples/subsys/task_wdt/sample.yaml +++ b/samples/subsys/task_wdt/sample.yaml @@ -1,8 +1,9 @@ sample: name: Task Watchdog Subsytem Sample common: - tags: subsys harness: console + tags: + - task_wdt harness_config: type: multi_line ordered: true @@ -19,10 +20,10 @@ common: - s32z270dc2_rtu0_r52 - s32z270dc2_rtu1_r52 tests: - sample.subsys.task_wdt: + sample.task_wdt: integration_platforms: - nucleo_g474re - sample.subsys.task_wdt.no_hw_fallback: + sample.task_wdt.no_hw_fallback: extra_args: CONF_FILE="prj_no_hw_fallback.conf" platform_allow: - mr_canhubk3 diff --git a/samples/subsys/testsuite/integration/prj.conf b/samples/subsys/testsuite/integration/prj.conf index 9228251051e..9467c292689 100644 --- a/samples/subsys/testsuite/integration/prj.conf +++ b/samples/subsys/testsuite/integration/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/samples/subsys/testsuite/integration/testcase.yaml b/samples/subsys/testsuite/integration/testcase.yaml index 8a4c9743b75..1cc0ad1c8ee 100644 --- a/samples/subsys/testsuite/integration/testcase.yaml +++ b/samples/subsys/testsuite/integration/testcase.yaml @@ -2,7 +2,9 @@ tests: # section.subsection sample.testing.ztest: build_only: true - platform_allow: native_posix - integration_platforms: + platform_allow: - native_posix + - native_sim + integration_platforms: + - native_sim tags: test_framework diff --git a/samples/subsys/testsuite/pytest/basic/prj.conf b/samples/subsys/testsuite/pytest/basic/prj.conf index 989b0c1b2cf..c3e81438ced 100644 --- a/samples/subsys/testsuite/pytest/basic/prj.conf +++ b/samples/subsys/testsuite/pytest/basic/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_IDLE_STACK_SIZE=4096 diff --git a/samples/subsys/testsuite/pytest/basic/testcase.yaml b/samples/subsys/testsuite/pytest/basic/testcase.yaml index a7c28cafc3b..6dc504cd64c 100644 --- a/samples/subsys/testsuite/pytest/basic/testcase.yaml +++ b/samples/subsys/testsuite/pytest/basic/testcase.yaml @@ -1,6 +1,8 @@ tests: sample.twister.pytest: - platform_allow: native_posix + platform_allow: + - native_posix + - native_sim harness: pytest harness_config: pytest_args: ["--custom-pytest-arg", "foo", "--cmdopt", "."] @@ -8,4 +10,4 @@ tests: - test_framework - pytest integration_platforms: - - native_posix + - native_sim diff --git a/samples/subsys/testsuite/pytest/shell/testcase.yaml b/samples/subsys/testsuite/pytest/shell/testcase.yaml index 02a3bcf9620..86b9314f444 100644 --- a/samples/subsys/testsuite/pytest/shell/testcase.yaml +++ b/samples/subsys/testsuite/pytest/shell/testcase.yaml @@ -6,7 +6,7 @@ tests: extra_configs: - arch:posix:CONFIG_NATIVE_UART_0_ON_STDINOUT=y integration_platforms: - - native_posix + - native_sim - qemu_cortex_m3 tags: - test_framework diff --git a/samples/subsys/tracing/README.rst b/samples/subsys/tracing/README.rst index df736046ced..299ab0a751d 100644 --- a/samples/subsys/tracing/README.rst +++ b/samples/subsys/tracing/README.rst @@ -1,10 +1,7 @@ -.. _tracing_sample: +.. zephyr:code-sample:: tracing + :name: Tracing -Send Tracing Formatted Packet To The Host With Supported Backends -################################################################# - -Overview -******** + Send tracing formatted packet to the host with supported backends. This application can be used to demonstrate the tracing feature. The tracing formatted packet will be sent to the host with the currently supported tracing @@ -86,8 +83,7 @@ Build a POSIX-tracing image with: .. zephyr-app-commands:: :zephyr-app: samples/subsys/tracing - :board: native_posix - :conf: "prj_native_posix.conf" + :board: native_sim :goals: build :compact: @@ -95,8 +91,8 @@ or: .. zephyr-app-commands:: :zephyr-app: samples/subsys/tracing - :board: native_posix - :conf: "prj_native_posix_ctf.conf" + :board: native_sim + :conf: "prj_native_ctf.conf" :goals: build :compact: diff --git a/samples/subsys/tracing/boards/native_sim.conf b/samples/subsys/tracing/boards/native_sim.conf new file mode 100644 index 00000000000..2a60b33a767 --- /dev/null +++ b/samples/subsys/tracing/boards/native_sim.conf @@ -0,0 +1,5 @@ +CONFIG_TRACING=y +CONFIG_TRACING_TEST=y +CONFIG_TRACING_SYNC=y +CONFIG_TRACING_BACKEND_POSIX=y +CONFIG_TRACING_PACKET_MAX_SIZE=64 diff --git a/samples/subsys/tracing/prj_native_posix_ctf.conf b/samples/subsys/tracing/prj_native_ctf.conf similarity index 100% rename from samples/subsys/tracing/prj_native_posix_ctf.conf rename to samples/subsys/tracing/prj_native_ctf.conf diff --git a/samples/subsys/tracing/sample.yaml b/samples/subsys/tracing/sample.yaml index f206a4e9ca4..23db8876cee 100644 --- a/samples/subsys/tracing/sample.yaml +++ b/samples/subsys/tracing/sample.yaml @@ -13,6 +13,8 @@ tests: extra_args: CONF_FILE="prj_user.conf" integration_platforms: - qemu_x86 + platform_exclude: + - mr_canhubk3 harness_config: type: multi_line regex: @@ -58,13 +60,21 @@ tests: platform_allow: sam_e70_xplained depends_on: usb_device extra_args: CONF_FILE="prj_usb_ctf.conf" - sample.tracing.transport.native_posix: - platform_allow: native_posix - sample.tracing.transport.native_posix.ctf: - platform_allow: native_posix - extra_args: CONF_FILE="prj_native_posix_ctf.conf" + sample.tracing.transport.native: + platform_allow: + - native_posix + - native_sim + integration_platforms: + - native_sim + sample.tracing.transport.native.ctf: + platform_allow: + - native_posix + - native_sim + integration_platforms: + - native_sim + extra_args: CONF_FILE="prj_native_ctf.conf" sample.tracing.percepio: platform_allow: frdm_k64f extra_args: CONF_FILE="prj_percepio.conf" modules: - - TraceRecorderSource + - percepio diff --git a/samples/subsys/tracing/src/tracing_user.c b/samples/subsys/tracing/src/tracing_user.c index 1e05957cd83..7f9370c5d2a 100644 --- a/samples/subsys/tracing/src/tracing_user.c +++ b/samples/subsys/tracing/src/tracing_user.c @@ -14,7 +14,7 @@ void sys_trace_thread_switched_in_user(void) __ASSERT_NO_MSG(nested_interrupts[_current_cpu->id] == 0); /* Can't use k_current_get as thread base and z_tls_current might be incorrect */ - printk("%s: %p\n", __func__, z_current_get()); + printk("%s: %p\n", __func__, k_sched_current_thread_query()); irq_unlock(key); } @@ -25,7 +25,7 @@ void sys_trace_thread_switched_out_user(void) __ASSERT_NO_MSG(nested_interrupts[_current_cpu->id] == 0); /* Can't use k_current_get as thread base and z_tls_current might be incorrect */ - printk("%s: %p\n", __func__, z_current_get()); + printk("%s: %p\n", __func__, k_sched_current_thread_query()); irq_unlock(key); } diff --git a/samples/subsys/usb/audio/headphones_microphone/README.rst b/samples/subsys/usb/audio/headphones_microphone/README.rst index c7bb238894a..eedd3891eec 100644 --- a/samples/subsys/usb/audio/headphones_microphone/README.rst +++ b/samples/subsys/usb/audio/headphones_microphone/README.rst @@ -1,7 +1,8 @@ -.. _usb_audio_headphones_microphone: +.. zephyr:code-sample:: usb-audio-headphones-microphone + :name: USB Audio microphone & headphones + :relevant-api: _usb_device_core_api -USB Audio Sample Application -############################ + Implement a USB Audio microphone + headphones device with audio IN/OUT loopback. Overview ******** diff --git a/samples/subsys/usb/audio/headphones_microphone/app.overlay b/samples/subsys/usb/audio/headphones_microphone/app.overlay index 0e68f9a89d2..1c9633b3ec0 100644 --- a/samples/subsys/usb/audio/headphones_microphone/app.overlay +++ b/samples/subsys/usb/audio/headphones_microphone/app.overlay @@ -10,6 +10,11 @@ feature-mute; channel-l; channel-r; + + feature-volume; + volume-max = <0x0500>; + volume-min = <0xBA00>; + volume-res = <0x100>; }; mic_0 { compatible = "usb-audio-mic"; diff --git a/samples/subsys/usb/audio/headphones_microphone/src/main.c b/samples/subsys/usb/audio/headphones_microphone/src/main.c index 57a5bcd62d8..0c680702ed3 100644 --- a/samples/subsys/usb/audio/headphones_microphone/src/main.c +++ b/samples/subsys/usb/audio/headphones_microphone/src/main.c @@ -45,10 +45,17 @@ static void data_received(const struct device *dev, static void feature_update(const struct device *dev, const struct usb_audio_fu_evt *evt) { + int16_t volume = 0; + LOG_DBG("Control selector %d for channel %d updated", evt->cs, evt->channel); switch (evt->cs) { case USB_AUDIO_FU_MUTE_CONTROL: + break; + case USB_AUDIO_FU_VOLUME_CONTROL: + volume = *((int16_t *)(evt->val)); + LOG_INF("set volume: %d", volume); + break; default: break; } diff --git a/samples/subsys/usb/audio/headset/README.rst b/samples/subsys/usb/audio/headset/README.rst index 4a804a1f388..8ab11bbd586 100644 --- a/samples/subsys/usb/audio/headset/README.rst +++ b/samples/subsys/usb/audio/headset/README.rst @@ -1,7 +1,8 @@ -.. _usb_audio_headset: +.. zephyr:code-sample:: usb-audio-headset + :name: USB Audio headset + :relevant-api: _usb_device_core_api -USB Audio Sample Application -############################ + Implement a USB Audio headset device with audio IN/OUT loopback. Overview ******** diff --git a/samples/subsys/usb/audio/headset/app.overlay b/samples/subsys/usb/audio/headset/app.overlay index cdb2aa0aa88..91c153cd13b 100644 --- a/samples/subsys/usb/audio/headset/app.overlay +++ b/samples/subsys/usb/audio/headset/app.overlay @@ -14,5 +14,10 @@ hp-feature-mute; hp-channel-l; hp-channel-r; + + hp-feature-volume; + volume-max = <0x0500>; + volume-min = <0xBA00>; + volume-res = <0x100>; }; }; diff --git a/samples/subsys/usb/audio/headset/src/main.c b/samples/subsys/usb/audio/headset/src/main.c index ddf39735bc5..447ebf03308 100644 --- a/samples/subsys/usb/audio/headset/src/main.c +++ b/samples/subsys/usb/audio/headset/src/main.c @@ -43,10 +43,17 @@ static void data_received(const struct device *dev, static void feature_update(const struct device *dev, const struct usb_audio_fu_evt *evt) { + int16_t volume = 0; + LOG_DBG("Control selector %d for channel %d updated", evt->cs, evt->channel); switch (evt->cs) { case USB_AUDIO_FU_MUTE_CONTROL: + break; + case USB_AUDIO_FU_VOLUME_CONTROL: + volume = *((int16_t *)(evt->val)); + LOG_INF("set volume: %d", volume); + break; default: break; } diff --git a/samples/subsys/usb/cdc_acm/README.rst b/samples/subsys/usb/cdc_acm/README.rst index 50a0e1531e1..15dcb7d574c 100644 --- a/samples/subsys/usb/cdc_acm/README.rst +++ b/samples/subsys/usb/cdc_acm/README.rst @@ -1,7 +1,8 @@ -.. _usb_cdc-acm: +.. zephyr:code-sample:: usb-cdc-acm + :name: USB CDC-ACM + :relevant-api: usbd_api _usb_device_core_api -USB CDC ACM Sample Application -#################################### + Use USB CDC-ACM driver to implement a serial port echo. Overview ******** diff --git a/samples/subsys/usb/cdc_acm/overlay-composite-cdc-msc.conf b/samples/subsys/usb/cdc_acm/overlay-composite-cdc-msc.conf index a272869511e..6618209fa63 100644 --- a/samples/subsys/usb/cdc_acm/overlay-composite-cdc-msc.conf +++ b/samples/subsys/usb/cdc_acm/overlay-composite-cdc-msc.conf @@ -3,6 +3,3 @@ CONFIG_USB_MASS_STORAGE=y CONFIG_USB_MASS_STORAGE_LOG_LEVEL_ERR=y - -#RAM DISK -CONFIG_DISK_DRIVER_RAM=y diff --git a/samples/subsys/usb/cdc_acm/ramdisk.overlay b/samples/subsys/usb/cdc_acm/ramdisk.overlay new file mode 100644 index 00000000000..b76a5ef6161 --- /dev/null +++ b/samples/subsys/usb/cdc_acm/ramdisk.overlay @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + ramdisk0 { + compatible = "zephyr,ram-disk"; + disk-name = "RAM"; + sector-size = <512>; + sector-count = <128>; + }; +}; diff --git a/samples/subsys/usb/cdc_acm/sample.yaml b/samples/subsys/usb/cdc_acm/sample.yaml index 60d6ab46fff..61b72fa41ef 100644 --- a/samples/subsys/usb/cdc_acm/sample.yaml +++ b/samples/subsys/usb/cdc_acm/sample.yaml @@ -27,7 +27,9 @@ tests: depends_on: usb_device tags: usb arch_exclude: posix - extra_args: OVERLAY_CONFIG=overlay-composite-cdc-msc.conf + extra_args: + - OVERLAY_CONFIG=overlay-composite-cdc-msc.conf + - EXTRA_DTC_OVERLAY_FILE="ramdisk.overlay" harness: console harness_config: type: one_line @@ -39,4 +41,4 @@ tests: arch_allow: posix build_only: true integration_platforms: - - native_posix + - native_sim diff --git a/samples/subsys/usb/cdc_acm/src/main.c b/samples/subsys/usb/cdc_acm/src/main.c index 4276bb2a12e..6847ed8d11e 100644 --- a/samples/subsys/usb/cdc_acm/src/main.c +++ b/samples/subsys/usb/cdc_acm/src/main.c @@ -29,6 +29,8 @@ uint8_t ring_buffer[RING_BUF_SIZE]; struct ring_buf ringbuf; +static bool rx_throttled; + #if defined(CONFIG_USB_DEVICE_STACK_NEXT) USBD_CONFIGURATION_DEFINE(config_1, USB_SCD_SELF_POWERED, @@ -106,12 +108,19 @@ static void interrupt_handler(const struct device *dev, void *user_data) ARG_UNUSED(user_data); while (uart_irq_update(dev) && uart_irq_is_pending(dev)) { - if (uart_irq_rx_ready(dev)) { + if (!rx_throttled && uart_irq_rx_ready(dev)) { int recv_len, rb_len; uint8_t buffer[64]; size_t len = MIN(ring_buf_space_get(&ringbuf), sizeof(buffer)); + if (len == 0) { + /* Throttle because ring buffer is full */ + uart_irq_rx_disable(dev); + rx_throttled = true; + continue; + } + recv_len = uart_fifo_read(dev, buffer, len); if (recv_len < 0) { LOG_ERR("Failed to read UART FIFO"); @@ -140,6 +149,11 @@ static void interrupt_handler(const struct device *dev, void *user_data) continue; } + if (rx_throttled) { + uart_irq_rx_enable(dev); + rx_throttled = false; + } + send_len = uart_fifo_fill(dev, buffer, rb_len); if (send_len < rb_len) { LOG_ERR("Drop %d bytes", rb_len - send_len); diff --git a/samples/subsys/usb/cdc_acm_composite/README.rst b/samples/subsys/usb/cdc_acm_composite/README.rst index 97c3333baa5..a138efffb42 100644 --- a/samples/subsys/usb/cdc_acm_composite/README.rst +++ b/samples/subsys/usb/cdc_acm_composite/README.rst @@ -1,7 +1,8 @@ -.. _usb_cdc-acm_composite: +.. zephyr:code-sample:: usb-cdc-acm-composite + :name: USB CDC-ACM composite + :relevant-api: usbd_api -USB CDC ACM Sample Composite Application -######################################## + Implement a composite USB device exposing two serial ports using USB CDC-ACM driver. Overview ******** diff --git a/samples/subsys/usb/console/README.rst b/samples/subsys/usb/console/README.rst index 08f05aca7d2..ac341a9285b 100644 --- a/samples/subsys/usb/console/README.rst +++ b/samples/subsys/usb/console/README.rst @@ -1,7 +1,8 @@ -.. _cdc-acm-console: +.. zephyr:code-sample:: usb-cdc-acm-console + :name: Console over USB CDC ACM + :relevant-api: _usb_device_core_api usbd_api uart_interface -Console over CDC ACM UART Sample -################################ + Output "Hello World!" to the console over USB CDC ACM. Overview ******** diff --git a/samples/subsys/usb/console/sample.yaml b/samples/subsys/usb/console/sample.yaml index f7fc8c03c0e..0a291d23a67 100644 --- a/samples/subsys/usb/console/sample.yaml +++ b/samples/subsys/usb/console/sample.yaml @@ -6,9 +6,6 @@ tests: - usb_device - usb_cdc tags: usb - platform_exclude: - - native_posix - - native_posix_64 harness: console harness_config: fixture: fixture_usb_cdc diff --git a/samples/subsys/usb/dfu/README.rst b/samples/subsys/usb/dfu/README.rst index 1803287754d..0ca87d7a8cf 100644 --- a/samples/subsys/usb/dfu/README.rst +++ b/samples/subsys/usb/dfu/README.rst @@ -1,7 +1,8 @@ -.. _usb_dfu: +.. zephyr:code-sample:: usb-dfu + :name: USB DFU (Device Firmware Upgrade) + :relevant-api: usbd_api _usb_device_core_api -USB DFU Sample Application -########################## + Implement device firmware upgrade using the USB DFU class driver. Overview ******** diff --git a/samples/subsys/usb/hid-cdc/README.rst b/samples/subsys/usb/hid-cdc/README.rst index 9a55e7d76a3..403785ef25e 100644 --- a/samples/subsys/usb/hid-cdc/README.rst +++ b/samples/subsys/usb/hid-cdc/README.rst @@ -1,7 +1,8 @@ -.. _usb_hid-cdc: +.. zephyr:code-sample:: usb-hid-cdc + :name: USB HID and CDC ACM + :relevant-api: _usb_device_core_api usb_hid_class input_interface -USB HID CDC ACM Application -########################### + Expose multiple USB HID and CDC ACM instances. Overview ******** diff --git a/samples/subsys/usb/hid-cdc/src/main.c b/samples/subsys/usb/hid-cdc/src/main.c index 2873ca5b270..7e06a2c5d0b 100644 --- a/samples/subsys/usb/hid-cdc/src/main.c +++ b/samples/subsys/usb/hid-cdc/src/main.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include diff --git a/samples/subsys/usb/hid-mouse/README.rst b/samples/subsys/usb/hid-mouse/README.rst index a7ff90bc2fe..c532141e71e 100644 --- a/samples/subsys/usb/hid-mouse/README.rst +++ b/samples/subsys/usb/hid-mouse/README.rst @@ -1,7 +1,8 @@ -.. _usb_hid-mouse: +.. zephyr:code-sample:: usb-hid-mouse + :name: USB HID mouse + :relevant-api: _usb_device_core_api usb_hid_class input_interface -USB HID mouse Sample Application -################################ + Implement a basic HID mouse device. Overview ******** diff --git a/samples/subsys/usb/hid/README.rst b/samples/subsys/usb/hid/README.rst index 0d95738f751..c29809cdf00 100644 --- a/samples/subsys/usb/hid/README.rst +++ b/samples/subsys/usb/hid/README.rst @@ -1,7 +1,8 @@ -.. _usb_hid: +.. zephyr:code-sample:: usb-hid + :name: USB HID (Human Interface Device) + :relevant-api: usbd_api usb_hid_device_api -USB HID Sample Application -########################## + Use USB HID driver to enumerate as a raw HID device. Overview ******** diff --git a/samples/subsys/usb/hid/sample.yaml b/samples/subsys/usb/hid/sample.yaml index 7f63562bbf7..ba6cf22a2d4 100644 --- a/samples/subsys/usb/hid/sample.yaml +++ b/samples/subsys/usb/hid/sample.yaml @@ -17,6 +17,8 @@ tests: platform_allow: - native_posix - native_posix_64 + - native_sim + - native_sim_64 build_only: true integration_platforms: - - native_posix + - native_sim diff --git a/samples/subsys/usb/mass/Kconfig b/samples/subsys/usb/mass/Kconfig index eb47261d1c4..e031a4545db 100644 --- a/samples/subsys/usb/mass/Kconfig +++ b/samples/subsys/usb/mass/Kconfig @@ -14,11 +14,9 @@ choice config APP_MSC_STORAGE_NONE bool "Use RAM disk as block device" - imply DISK_DRIVER_RAM config APP_MSC_STORAGE_RAM bool "Use RAM disk and FAT file system" - imply DISK_DRIVER_RAM imply FILE_SYSTEM imply FAT_FILESYSTEM_ELM @@ -42,9 +40,6 @@ config APP_MSC_STORAGE_SDCARD endchoice -config DISK_RAM_VOLUME_SIZE - default 32 if APP_MSC_STORAGE_NONE - config MASS_STORAGE_DISK_NAME default "NAND" if DISK_DRIVER_FLASH default "RAM" if DISK_DRIVER_RAM diff --git a/samples/subsys/usb/mass/README.rst b/samples/subsys/usb/mass/README.rst index 82a252061c8..1c2011f363f 100644 --- a/samples/subsys/usb/mass/README.rst +++ b/samples/subsys/usb/mass/README.rst @@ -1,7 +1,8 @@ -.. _usb_mass: +.. zephyr:code-sample:: usb-mass + :name: USB Mass Storage + :relevant-api: usbd_api _usb_device_core_api file_system_api -USB Mass Storage Sample Application -################################### + Expose board's RAM or FLASH as a USB disk using USB Mass Storage driver. Overview ******** @@ -14,8 +15,7 @@ into an USB disk. This sample can be found under Requirements ************ -This project requires a USB device driver, and either 32KiB (96KiB optional) -of RAM or a FLASH device. +This project requires a USB device driver, and either 96KiB of RAM or a FLASH device. Building and Running ******************** @@ -29,12 +29,13 @@ RAM-disk Example without any file system ======================================== The default configurations selects RAM-based disk without any file system. -This example only needs additional 32KiB RAM for the RAM-disk and is intended +This example only needs additional 96KiB RAM for the RAM-disk and is intended for testing USB mass storage class implementation. .. zephyr-app-commands:: :zephyr-app: samples/subsys/usb/mass :board: reel_board + :gen-args: -DEXTRA_DTC_OVERLAY_FILE="ramdisk.overlay" :goals: build :compact: @@ -49,7 +50,7 @@ In this example we will build the sample with a RAM-based disk: .. zephyr-app-commands:: :zephyr-app: samples/subsys/usb/mass :board: reel_board - :gen-args: -DCONFIG_APP_MSC_STORAGE_RAM=y + :gen-args: -DEXTRA_DTC_OVERLAY_FILE="ramdisk.overlay" -DCONFIG_APP_MSC_STORAGE_RAM=y :goals: build :compact: @@ -157,7 +158,7 @@ LittleFS Example This board configures to use the external 64 MiBi QSPI flash chip with a 128 KiBy `littlefs`_ partition compatible with the one produced by the -:ref:`littlefs-sample`. +:zephyr:code-sample:`littlefs` sample. .. zephyr-app-commands:: :zephyr-app: samples/subsys/usb/mass diff --git a/samples/subsys/usb/mass/boards/sensortile_box_pro.conf b/samples/subsys/usb/mass/boards/sensortile_box_pro.conf new file mode 100644 index 00000000000..eca492a4505 --- /dev/null +++ b/samples/subsys/usb/mass/boards/sensortile_box_pro.conf @@ -0,0 +1,16 @@ +# +# Copyright (c) 2022 O.S.Systems +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=8192 + +CONFIG_DISK_ACCESS=y +CONFIG_DISK_DRIVERS=y +CONFIG_DISK_DRIVER_SDMMC=y + +CONFIG_FILE_SYSTEM=y +CONFIG_FAT_FILESYSTEM_ELM=y + +CONFIG_APP_MSC_STORAGE_SDCARD=y diff --git a/samples/subsys/usb/mass/ramdisk.overlay b/samples/subsys/usb/mass/ramdisk.overlay new file mode 100644 index 00000000000..ff09a0f8ca7 --- /dev/null +++ b/samples/subsys/usb/mass/ramdisk.overlay @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + ramdisk0 { + compatible = "zephyr,ram-disk"; + disk-name = "RAM"; + sector-size = <512>; + sector-count = <192>; + }; +}; diff --git a/samples/subsys/usb/mass/sample.yaml b/samples/subsys/usb/mass/sample.yaml index 2e7570a5ae3..9149012a212 100644 --- a/samples/subsys/usb/mass/sample.yaml +++ b/samples/subsys/usb/mass/sample.yaml @@ -2,9 +2,11 @@ sample: name: Mass Storage tests: sample.usb.mass_ram_none: - min_ram: 64 + min_ram: 128 depends_on: usb_device arch_exclude: posix + extra_args: + - EXTRA_DTC_OVERLAY_FILE="ramdisk.overlay" extra_configs: - CONFIG_LOG_DEFAULT_LEVEL=3 tags: @@ -18,12 +20,14 @@ tests: - "No file system selected" - "The device is put in USB mass storage mode." sample.usb_device_next.mass_ram_none: - min_ram: 64 + min_ram: 128 depends_on: usb_device platform_allow: - nrf52840dk_nrf52840 - frdm_k64f - extra_args: CONF_FILE="usbd_next_prj.conf" + extra_args: + - CONF_FILE="usbd_next_prj.conf" + - EXTRA_DTC_OVERLAY_FILE="ramdisk.overlay" extra_configs: - CONFIG_LOG_DEFAULT_LEVEL=3 tags: @@ -40,6 +44,8 @@ tests: min_ram: 128 depends_on: usb_device arch_exclude: posix + extra_args: + - EXTRA_DTC_OVERLAY_FILE="ramdisk.overlay" extra_configs: - CONFIG_LOG_DEFAULT_LEVEL=3 - CONFIG_APP_MSC_STORAGE_RAM=y diff --git a/samples/subsys/usb/shell/README.rst b/samples/subsys/usb/shell/README.rst index 12f7c0ae193..0e368187c79 100644 --- a/samples/subsys/usb/shell/README.rst +++ b/samples/subsys/usb/shell/README.rst @@ -1,13 +1,14 @@ -.. _usb_shell-app: +.. zephyr:code-sample:: usb-shell + :name: USB shell + :relevant-api: usbd_api -USB support shell sample -######################## + Use shell commands to interact with USB device stack. Overview ******** The sample enables new experimental USB device support and the shell function. -It is primarily intended to aid in the development and testing of USB constoller +It is primarily intended to aid in the development and testing of USB controller drivers and new USB support. Building and flashing diff --git a/samples/subsys/usb/testusb/README.rst b/samples/subsys/usb/testusb/README.rst index 74a6585ab48..03e6f6c104a 100644 --- a/samples/subsys/usb/testusb/README.rst +++ b/samples/subsys/usb/testusb/README.rst @@ -1,9 +1,10 @@ -.. _testusb-app: +.. zephyr:code-sample:: testusb-app + :name: USB testing application + :relevant-api: _usb_device_core_api -Testusb application sample -########################## + Test USB device drivers using a loopback function. -The testusb sample implements a loopback function. This function can be used +This sample implements a loopback function that can be used to test USB device drivers and the device stack connected to a Linux host and has a similar interface to "Gadget Zero" of the Linux kernel. The userspace tool ``testusb`` is needed to start the tests. diff --git a/samples/subsys/usb/usb.rst b/samples/subsys/usb/usb.rst index 90b1c783b4c..5da80b0e219 100644 --- a/samples/subsys/usb/usb.rst +++ b/samples/subsys/usb/usb.rst @@ -7,4 +7,4 @@ USB device support samples :maxdepth: 1 :glob: - **/* + **/README diff --git a/samples/subsys/usb/webusb/README.rst b/samples/subsys/usb/webusb/README.rst index f5d5c17e1d7..228bf822d80 100644 --- a/samples/subsys/usb/webusb/README.rst +++ b/samples/subsys/usb/webusb/README.rst @@ -1,7 +1,8 @@ -.. _webusb-sample: +.. zephyr:code-sample:: webusb + :name: WebUSB + :relevant-api: usbd_api -WebUSB sample application -######################### + Receive and echo data from a web page using WebUSB API. For a deeper dive into the WebUSB, refer to https://developers.google.com/web/updates/2016/03/access-usb-devices-on-the-web @@ -9,11 +10,11 @@ https://developers.google.com/web/updates/2016/03/access-usb-devices-on-the-web WebUSB API Specification: https://wicg.github.io/webusb/ -Sample Overview -*************** +Overview +******** This simple echo application demonstrates the WebUSB sample application. -This application receives the data and echoed back to the WebUSB +This application receives the data and echoes back to the WebUSB based web application (web page) running in the browser at host. This application is intended for testing purposes only. For running real usecase, implement applications based on the WebUSB API. @@ -37,15 +38,15 @@ Build and flash webusb sample with: :goals: flash :compact: -Testing with latest Google Chrome on host -***************************************** +Testing with the latest Google Chrome on host +********************************************* -This sample application requires latest Google Chrome, a web page +This sample application requires the latest Google Chrome, a web page based on WebUSB API to connect to the USB device and optionally http server running on localhost to serve the web page. WebUSB is a powerful new feature added to the Web and it is available -only to secure origins. This means the web page/site that used to +only to secure origins. This means the web page/site that is used to connect to the device must be served over a secure connection (HTTPS). Follow these steps to run the demo on your host system: @@ -55,20 +56,25 @@ Follow these steps to run the demo on your host system: #. Implement a web app (web page) using WebUSB API and run it on localhost. - See the sample at https://github.com/finikorg/webusb-sample + The sample can be found in the webusb sample directory: + :zephyr_file:`samples/subsys/usb/webusb/index.html`. - This sample web page demonstrate how to create and use a WebUSB + This sample web page demonstrates how to create and use a WebUSB interface, as well as demonstrate the communication between browser and WebUSB enabled device. - #. To access JS app go to https://finikorg.github.io/webusb-sample/ + There are two ways to access this sample page: - #. To host the demo page locally: Clone the repo and start a web server - in the appropriate directory. + * Using Chrome browser go to :doc:`demo` - .. code-block:: console + * Host the demo page locally: Start a web server + in the webusb sample directory. - $ python -m http.server + .. code-block:: console + + $ python -m http.server + + Using Chrome browser open url http://localhost:8001/ #. Connect the board to your host. @@ -78,7 +84,8 @@ Follow these steps to run the demo on your host system: Note that at the moment WebUSB landing page notification is disabled in Chrome on Windows. See https://github.com/WICG/webusb#implementation-status -#. Click on Connect button to connect to the device. +#. Click on the :guilabel:`Connect` button to connect to the device. -#. Send some text to the device by clicking on the Send button. The demo app - will receive the same text from the device and display it in the textarea. +#. Send some text to the device by clicking on the :guilabel:`Send` button. + The demo app will receive the same text from the device and display it in + the text area. diff --git a/samples/subsys/usb/webusb/demo.rst b/samples/subsys/usb/webusb/demo.rst new file mode 100644 index 00000000000..6925a802580 --- /dev/null +++ b/samples/subsys/usb/webusb/demo.rst @@ -0,0 +1,7 @@ +:orphan: + +WebUSB HTML Demo App +==================== + +.. raw:: html + :file: index.html diff --git a/samples/subsys/usb/webusb/index.html b/samples/subsys/usb/webusb/index.html new file mode 100644 index 00000000000..b6cfc96d447 --- /dev/null +++ b/samples/subsys/usb/webusb/index.html @@ -0,0 +1,126 @@ + + + + WebUSB Serial Sample Application + + + + + +


    + +
    +

    +
    + + + diff --git a/samples/subsys/usb_c/sink/README.rst b/samples/subsys/usb_c/sink/README.rst index 8b8a4657c81..954147965b7 100644 --- a/samples/subsys/usb_c/sink/README.rst +++ b/samples/subsys/usb_c/sink/README.rst @@ -1,7 +1,8 @@ -.. _usb-c-sink-sample: +.. zephyr:code-sample:: usb-c-sink + :name: Basic USB-C Sink + :relevant-api: _usbc_device_api -Basic USB-C SINK -################ + Implement a USB-C Power Delivery application in the form of a USB-C Sink. Overview ******** diff --git a/samples/subsys/usb_c/sink/boards/b_g474e_dpow1.overlay b/samples/subsys/usb_c/sink/boards/b_g474e_dpow1.overlay index 8a68e092b7c..de70e938992 100644 --- a/samples/subsys/usb_c/sink/boards/b_g474e_dpow1.overlay +++ b/samples/subsys/usb_c/sink/boards/b_g474e_dpow1.overlay @@ -8,6 +8,10 @@ #include / { + aliases { + usbc-port0 = &port1; + }; + /* usbc.rst vbus-voltage-divider-adc start */ vbus1: vbus { compatible = "zephyr,usb-c-vbus-adc"; diff --git a/samples/subsys/usb_c/sink/boards/stm32g081b_eval.overlay b/samples/subsys/usb_c/sink/boards/stm32g081b_eval.overlay index 2ff32caba68..ca6e32206c6 100644 --- a/samples/subsys/usb_c/sink/boards/stm32g081b_eval.overlay +++ b/samples/subsys/usb_c/sink/boards/stm32g081b_eval.overlay @@ -8,6 +8,10 @@ #include / { + aliases { + usbc-port0 = &port1; + }; + vbus1: vbus { compatible = "zephyr,usb-c-vbus-adc"; io-channels = <&adc1 9>; diff --git a/samples/subsys/usb_c/sink/boards/weact_stm32g431_core.overlay b/samples/subsys/usb_c/sink/boards/weact_stm32g431_core.overlay new file mode 100644 index 00000000000..1b951a5ef77 --- /dev/null +++ b/samples/subsys/usb_c/sink/boards/weact_stm32g431_core.overlay @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Andreas Sandberg + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#include + +&adc2 { + status = "okay"; +}; + +&vbus1 { + status = "okay"; +}; + +&usbc1 { + status = "okay"; +}; + +&clk_hsi { + /* The HSI is used by ucpd1 */ + status = "okay"; +}; + +&ucpd1 { + status = "okay"; + dead-battery; +}; diff --git a/samples/subsys/usb_c/sink/src/main.c b/samples/subsys/usb_c/sink/src/main.c index 87ed5114838..fb6407a0309 100644 --- a/samples/subsys/usb_c/sink/src/main.c +++ b/samples/subsys/usb_c/sink/src/main.c @@ -13,10 +13,10 @@ #include LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG); -#define PORT1_NODE DT_NODELABEL(port1) -#define PORT1_POWER_ROLE DT_ENUM_IDX(DT_NODELABEL(port1), power_role) +#define USBC_PORT0_NODE DT_ALIAS(usbc_port0) +#define USBC_PORT0_POWER_ROLE DT_ENUM_IDX(USBC_PORT0_NODE, power_role) -#if (PORT1_POWER_ROLE != TC_ROLE_SINK) +#if (USBC_PORT0_POWER_ROLE != TC_ROLE_SINK) #error "Unsupported board: Only Sink device supported" #endif @@ -26,9 +26,9 @@ LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG); /** * @brief A structure that encapsulates Port data. */ -static struct port1_data_t { +static struct port0_data_t { /** Sink Capabilities */ - uint32_t snk_caps[DT_PROP_LEN(DT_NODELABEL(port1), sink_pdos)]; + uint32_t snk_caps[DT_PROP_LEN(USBC_PORT0_NODE, sink_pdos)]; /** Number of Sink Capabilities */ int snk_cap_cnt; /** Source Capabilities */ @@ -37,9 +37,9 @@ static struct port1_data_t { int src_cap_cnt; /* Power Supply Ready flag */ atomic_t ps_ready; -} port1_data = { - .snk_caps = {DT_FOREACH_PROP_ELEM(DT_NODELABEL(port1), sink_pdos, SINK_PDO)}, - .snk_cap_cnt = DT_PROP_LEN(DT_NODELABEL(port1), sink_pdos), +} port0_data = { + .snk_caps = {DT_FOREACH_PROP_ELEM(USBC_PORT0_NODE, sink_pdos, SINK_PDO)}, + .snk_cap_cnt = DT_PROP_LEN(USBC_PORT0_NODE, sink_pdos), .src_caps = {0}, .src_cap_cnt = 0, .ps_ready = 0 @@ -61,7 +61,7 @@ static struct port1_data_t { * @note Generally a sink application would build an RDO from the * Source Capabilities stored in the dpm_data object */ -static uint32_t build_rdo(const struct port1_data_t *dpm_data) +static uint32_t build_rdo(const struct port0_data_t *dpm_data) { union pd_rdo rdo; @@ -161,7 +161,7 @@ static void display_pdo(const int idx, static void display_source_caps(const struct device *dev) { - struct port1_data_t *dpm_data = usbc_get_dpm_data(dev); + struct port0_data_t *dpm_data = usbc_get_dpm_data(dev); LOG_INF("Source Caps:"); for (int i = 0; i < dpm_data->src_cap_cnt; i++) { @@ -171,11 +171,11 @@ static void display_source_caps(const struct device *dev) } /* usbc.rst callbacks start */ -static int port1_policy_cb_get_snk_cap(const struct device *dev, +static int port0_policy_cb_get_snk_cap(const struct device *dev, uint32_t **pdos, int *num_pdos) { - struct port1_data_t *dpm_data = usbc_get_dpm_data(dev); + struct port0_data_t *dpm_data = usbc_get_dpm_data(dev); *pdos = dpm_data->snk_caps; *num_pdos = dpm_data->snk_cap_cnt; @@ -183,11 +183,11 @@ static int port1_policy_cb_get_snk_cap(const struct device *dev, return 0; } -static void port1_policy_cb_set_src_cap(const struct device *dev, +static void port0_policy_cb_set_src_cap(const struct device *dev, const uint32_t *pdos, const int num_pdos) { - struct port1_data_t *dpm_data; + struct port0_data_t *dpm_data; int num; int i; @@ -205,19 +205,19 @@ static void port1_policy_cb_set_src_cap(const struct device *dev, dpm_data->src_cap_cnt = num; } -static uint32_t port1_policy_cb_get_rdo(const struct device *dev) +static uint32_t port0_policy_cb_get_rdo(const struct device *dev) { - struct port1_data_t *dpm_data = usbc_get_dpm_data(dev); + struct port0_data_t *dpm_data = usbc_get_dpm_data(dev); return build_rdo(dpm_data); } /* usbc.rst callbacks end */ /* usbc.rst notify start */ -static void port1_notify(const struct device *dev, +static void port0_notify(const struct device *dev, const enum usbc_policy_notify_t policy_notify) { - struct port1_data_t *dpm_data = usbc_get_dpm_data(dev); + struct port0_data_t *dpm_data = usbc_get_dpm_data(dev); switch (policy_notify) { case PROTOCOL_ERROR: @@ -269,7 +269,7 @@ static void port1_notify(const struct device *dev, /* usbc.rst notify end */ /* usbc.rst check start */ -bool port1_policy_check(const struct device *dev, +bool port0_policy_check(const struct device *dev, const enum usbc_policy_check_t policy_check) { switch (policy_check) { @@ -295,12 +295,12 @@ bool port1_policy_check(const struct device *dev, int main(void) { - const struct device *usbc_port1; + const struct device *usbc_port0; /* Get the device for this port */ - usbc_port1 = DEVICE_DT_GET(PORT1_NODE); - if (!device_is_ready(usbc_port1)) { - LOG_ERR("PORT1 device not ready"); + usbc_port0 = DEVICE_DT_GET(USBC_PORT0_NODE); + if (!device_is_ready(usbc_port0)) { + LOG_ERR("PORT0 device not ready"); return 0; } @@ -308,33 +308,33 @@ int main(void) /* Register USB-C Callbacks */ /* Register Policy Check callback */ - usbc_set_policy_cb_check(usbc_port1, port1_policy_check); + usbc_set_policy_cb_check(usbc_port0, port0_policy_check); /* Register Policy Notify callback */ - usbc_set_policy_cb_notify(usbc_port1, port1_notify); + usbc_set_policy_cb_notify(usbc_port0, port0_notify); /* Register Policy Get Sink Capabilities callback */ - usbc_set_policy_cb_get_snk_cap(usbc_port1, port1_policy_cb_get_snk_cap); + usbc_set_policy_cb_get_snk_cap(usbc_port0, port0_policy_cb_get_snk_cap); /* Register Policy Set Source Capabilities callback */ - usbc_set_policy_cb_set_src_cap(usbc_port1, port1_policy_cb_set_src_cap); + usbc_set_policy_cb_set_src_cap(usbc_port0, port0_policy_cb_set_src_cap); /* Register Policy Get Request Data Object callback */ - usbc_set_policy_cb_get_rdo(usbc_port1, port1_policy_cb_get_rdo); + usbc_set_policy_cb_get_rdo(usbc_port0, port0_policy_cb_get_rdo); /* usbc.rst register end */ /* usbc.rst user data start */ /* Set Application port data object. This object is passed to the policy callbacks */ - port1_data.ps_ready = ATOMIC_INIT(0); - usbc_set_dpm_data(usbc_port1, &port1_data); + port0_data.ps_ready = ATOMIC_INIT(0); + usbc_set_dpm_data(usbc_port0, &port0_data); /* usbc.rst user data end */ /* usbc.rst usbc start */ /* Start the USB-C Subsystem */ - usbc_start(usbc_port1); + usbc_start(usbc_port0); /* usbc.rst usbc end */ while (1) { /* Perform Application Specific functions */ - if (atomic_test_and_clear_bit(&port1_data.ps_ready, 0)) { + if (atomic_test_and_clear_bit(&port0_data.ps_ready, 0)) { /* Display the Source Capabilities */ - display_source_caps(usbc_port1); + display_source_caps(usbc_port0); } /* Arbitrary delay */ diff --git a/samples/subsys/usb_c/source/README.rst b/samples/subsys/usb_c/source/README.rst index 06cb38eab37..1e9b861cc85 100644 --- a/samples/subsys/usb_c/source/README.rst +++ b/samples/subsys/usb_c/source/README.rst @@ -1,7 +1,8 @@ -.. _usb-c-source-sample: +.. zephyr:code-sample:: usb-c-source + :name: Basic USB-C Source + :relevant-api: _usbc_device_api -Basic USB-C SOURCE -################## + Implement a USB-C Power Delivery application in the form of a USB-C Source. Overview ******** diff --git a/samples/subsys/usb_c/source/boards/stm32g081b_eval.overlay b/samples/subsys/usb_c/source/boards/stm32g081b_eval.overlay index 9e56510ee6b..d81b3d9dbee 100644 --- a/samples/subsys/usb_c/source/boards/stm32g081b_eval.overlay +++ b/samples/subsys/usb_c/source/boards/stm32g081b_eval.overlay @@ -8,6 +8,9 @@ #include / { + aliases { + usbc-port0 = &port1; + }; pwmleds { compatible = "pwm-leds"; diff --git a/samples/subsys/usb_c/source/src/main.c b/samples/subsys/usb_c/source/src/main.c index 416c717a3ed..1e7018c2748 100644 --- a/samples/subsys/usb_c/source/src/main.c +++ b/samples/subsys/usb_c/source/src/main.c @@ -15,11 +15,11 @@ LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG); #include "power_ctrl.h" -#define PORT1_NODE DT_NODELABEL(port1) -#define PORT1_POWER_ROLE DT_ENUM_IDX(DT_NODELABEL(port1), power_role) +#define USBC_PORT0_NODE DT_ALIAS(usbc_port0) +#define USBC_PORT0_POWER_ROLE DT_ENUM_IDX(USBC_PORT0_NODE, power_role) /* A Source power role evauates to 1. See usbc_tc.h: TC_ROLE_SOURCE */ -#if (PORT1_POWER_ROLE != 1) +#if (USBC_PORT0_POWER_ROLE != 1) #error "Unsupported board: Only Source device supported" #endif @@ -29,9 +29,9 @@ LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG); /** * @brief A structure that encapsulates Port data. */ -static struct port1_data_t { +static struct port0_data_t { /** Source Capabilities */ - uint32_t src_caps[DT_PROP_LEN(DT_NODELABEL(port1), source_pdos)]; + uint32_t src_caps[DT_PROP_LEN(USBC_PORT0_NODE, source_pdos)]; /** Number of Source Capabilities */ int src_cap_cnt; /** CC Rp value */ @@ -48,10 +48,10 @@ static struct port1_data_t { bool ps_tran_start; /** Log Sink Requested RDO to console */ atomic_t show_sink_request; -} port1_data = { - .rp = DT_ENUM_IDX(DT_NODELABEL(port1), typec_power_opmode), - .src_caps = {DT_FOREACH_PROP_ELEM(DT_NODELABEL(port1), source_pdos, SOURCE_PDO)}, - .src_cap_cnt = DT_PROP_LEN(DT_NODELABEL(port1), source_pdos), +} port0_data = { + .rp = DT_ENUM_IDX(USBC_PORT0_NODE, typec_power_opmode), + .src_caps = {DT_FOREACH_PROP_ELEM(USBC_PORT0_NODE, source_pdos, SOURCE_PDO)}, + .src_cap_cnt = DT_PROP_LEN(USBC_PORT0_NODE, source_pdos), }; /* usbc.rst port data object end */ @@ -84,10 +84,10 @@ static void dump_sink_request_rdo(const uint32_t rdo) /** * @brief PE calls this function when it needs to set the Rp on CC */ -int port1_policy_cb_get_src_rp(const struct device *dev, +int port0_policy_cb_get_src_rp(const struct device *dev, enum tc_rp_value *rp) { - struct port1_data_t *dpm_data = usbc_get_dpm_data(dev); + struct port0_data_t *dpm_data = usbc_get_dpm_data(dev); *rp = dpm_data->rp; @@ -98,7 +98,7 @@ int port1_policy_cb_get_src_rp(const struct device *dev, * @brief PE calls this function to Enable (5V) or Disable (0V) the * Power Supply */ -int port1_policy_cb_src_en(const struct device *dev, bool en) +int port0_policy_cb_src_en(const struct device *dev, bool en) { source_ctrl_set(en ? SOURCE_5V : SOURCE_0V); @@ -108,9 +108,9 @@ int port1_policy_cb_src_en(const struct device *dev, bool en) /** * @brief PE calls this function to Enable or Disable VCONN */ -int port1_policy_cb_vconn_en(const struct device *dev, enum tc_cc_polarity pol, bool en) +int port0_policy_cb_vconn_en(const struct device *dev, enum tc_cc_polarity pol, bool en) { - struct port1_data_t *dpm_data = usbc_get_dpm_data(dev); + struct port0_data_t *dpm_data = usbc_get_dpm_data(dev); dpm_data->vconn_pol = pol; @@ -132,10 +132,10 @@ int port1_policy_cb_vconn_en(const struct device *dev, enum tc_cc_polarity pol, * @brief PE calls this function to get the Source Caps that will be sent * to the Sink */ -int port1_policy_cb_get_src_caps(const struct device *dev, +int port0_policy_cb_get_src_caps(const struct device *dev, const uint32_t **pdos, uint32_t *num_pdos) { - struct port1_data_t *dpm_data = usbc_get_dpm_data(dev); + struct port0_data_t *dpm_data = usbc_get_dpm_data(dev); *pdos = dpm_data->src_caps; *num_pdos = dpm_data->src_cap_cnt; @@ -146,10 +146,10 @@ int port1_policy_cb_get_src_caps(const struct device *dev, /** * @brief PE calls this function to verify that a Sink's request if valid */ -static enum usbc_snk_req_reply_t port1_policy_cb_check_sink_request(const struct device *dev, +static enum usbc_snk_req_reply_t port0_policy_cb_check_sink_request(const struct device *dev, const uint32_t request_msg) { - struct port1_data_t *dpm_data = usbc_get_dpm_data(dev); + struct port0_data_t *dpm_data = usbc_get_dpm_data(dev); union pd_fixed_supply_pdo_source pdo; uint32_t obj_pos; uint32_t op_current; @@ -171,13 +171,13 @@ static enum usbc_snk_req_reply_t port1_policy_cb_check_sink_request(const struct dpm_data->obj_pos = obj_pos; - atomic_set_bit(&port1_data.show_sink_request, 0); + atomic_set_bit(&port0_data.show_sink_request, 0); /* * Clear PS ready. This will be set to true after PS is ready after * it transitions to the new level. */ - port1_data.ps_ready = false; + port0_data.ps_ready = false; return SNK_REQUEST_VALID; } @@ -186,9 +186,9 @@ static enum usbc_snk_req_reply_t port1_policy_cb_check_sink_request(const struct * @brief PE calls this function to check if the Power Supply is at the requested * level */ -static bool port1_policy_cb_is_ps_ready(const struct device *dev) +static bool port0_policy_cb_is_ps_ready(const struct device *dev) { - struct port1_data_t *dpm_data = usbc_get_dpm_data(dev); + struct port0_data_t *dpm_data = usbc_get_dpm_data(dev); /* Return true to inform that the Power Supply is ready */ @@ -199,10 +199,10 @@ static bool port1_policy_cb_is_ps_ready(const struct device *dev) * @brief PE calls this function to check if the Present Contract is still * valid */ -static bool port1_policy_cb_present_contract_is_valid(const struct device *dev, +static bool port0_policy_cb_present_contract_is_valid(const struct device *dev, const uint32_t present_contract) { - struct port1_data_t *dpm_data = usbc_get_dpm_data(dev); + struct port0_data_t *dpm_data = usbc_get_dpm_data(dev); union pd_fixed_supply_pdo_source pdo; union pd_rdo request; uint32_t obj_pos; @@ -228,10 +228,10 @@ static bool port1_policy_cb_present_contract_is_valid(const struct device *dev, /* usbc.rst callbacks end */ /* usbc.rst notify start */ -static void port1_notify(const struct device *dev, +static void port0_notify(const struct device *dev, const enum usbc_policy_notify_t policy_notify) { - struct port1_data_t *dpm_data = usbc_get_dpm_data(dev); + struct port0_data_t *dpm_data = usbc_get_dpm_data(dev); switch (policy_notify) { case PROTOCOL_ERROR: @@ -277,10 +277,10 @@ static void port1_notify(const struct device *dev, /* usbc.rst notify end */ /* usbc.rst check start */ -bool port1_policy_check(const struct device *dev, +bool port0_policy_check(const struct device *dev, const enum usbc_policy_check_t policy_check) { - struct port1_data_t *dpm_data = usbc_get_dpm_data(dev); + struct port0_data_t *dpm_data = usbc_get_dpm_data(dev); switch (policy_check) { case CHECK_POWER_ROLE_SWAP: @@ -315,12 +315,12 @@ bool port1_policy_check(const struct device *dev, int main(void) { - const struct device *usbc_port1; + const struct device *usbc_port0; /* Get the device for this port */ - usbc_port1 = DEVICE_DT_GET(PORT1_NODE); - if (!device_is_ready(usbc_port1)) { - LOG_ERR("PORT1 device not ready"); + usbc_port0 = DEVICE_DT_GET(USBC_PORT0_NODE); + if (!device_is_ready(usbc_port0)) { + LOG_ERR("PORT0 device not ready"); return 0; } @@ -328,63 +328,63 @@ int main(void) /* Register USB-C Callbacks */ /* Register Policy Check callback */ - usbc_set_policy_cb_check(usbc_port1, port1_policy_check); + usbc_set_policy_cb_check(usbc_port0, port0_policy_check); /* Register Policy Notify callback */ - usbc_set_policy_cb_notify(usbc_port1, port1_notify); + usbc_set_policy_cb_notify(usbc_port0, port0_notify); /* Register Policy callback to set the Rp on CC lines */ - usbc_set_policy_cb_get_src_rp(usbc_port1, port1_policy_cb_get_src_rp); + usbc_set_policy_cb_get_src_rp(usbc_port0, port0_policy_cb_get_src_rp); /* Register Policy callback to enable or disable power supply */ - usbc_set_policy_cb_src_en(usbc_port1, port1_policy_cb_src_en); + usbc_set_policy_cb_src_en(usbc_port0, port0_policy_cb_src_en); /* Register Policy callback to enable or disable vconn */ - usbc_set_vconn_control_cb(usbc_port1, port1_policy_cb_vconn_en); + usbc_set_vconn_control_cb(usbc_port0, port0_policy_cb_vconn_en); /* Register Policy callback to send the source caps to the sink */ - usbc_set_policy_cb_get_src_caps(usbc_port1, port1_policy_cb_get_src_caps); + usbc_set_policy_cb_get_src_caps(usbc_port0, port0_policy_cb_get_src_caps); /* Register Policy callback to check if the sink request is valid */ - usbc_set_policy_cb_check_sink_request(usbc_port1, port1_policy_cb_check_sink_request); + usbc_set_policy_cb_check_sink_request(usbc_port0, port0_policy_cb_check_sink_request); /* Register Policy callback to check if the power supply is ready */ - usbc_set_policy_cb_is_ps_ready(usbc_port1, port1_policy_cb_is_ps_ready); + usbc_set_policy_cb_is_ps_ready(usbc_port0, port0_policy_cb_is_ps_ready); /* Register Policy callback to check if Present Contract is still valid */ - usbc_set_policy_cb_present_contract_is_valid(usbc_port1, - port1_policy_cb_present_contract_is_valid); + usbc_set_policy_cb_present_contract_is_valid(usbc_port0, + port0_policy_cb_present_contract_is_valid); /* usbc.rst register end */ /* usbc.rst user data start */ /* Set Application port data object. This object is passed to the policy callbacks */ - usbc_set_dpm_data(usbc_port1, &port1_data); + usbc_set_dpm_data(usbc_port0, &port0_data); /* usbc.rst user data end */ /* Flag to show sink request */ - port1_data.show_sink_request = ATOMIC_INIT(0); + port0_data.show_sink_request = ATOMIC_INIT(0); /* Init power supply transition start */ - port1_data.ps_tran_start = false; + port0_data.ps_tran_start = false; /* Init power supply ready */ - port1_data.ps_ready = false; + port0_data.ps_ready = false; /* usbc.rst usbc start */ /* Start the USB-C Subsystem */ - usbc_start(usbc_port1); + usbc_start(usbc_port0); /* usbc.rst usbc end */ while (1) { /* Perform Application Specific functions */ /* Transition PS to new level */ - if (port1_data.ps_tran_start) { + if (port0_data.ps_tran_start) { /* * Transition Power Supply to new voltage. * Okay if this blocks. */ - source_ctrl_set(port1_data.obj_pos); - port1_data.ps_ready = true; - port1_data.ps_tran_start = false; + source_ctrl_set(port0_data.obj_pos); + port0_data.ps_ready = true; + port0_data.ps_tran_start = false; } /* Display Sink Requests */ - if (atomic_test_and_clear_bit(&port1_data.show_sink_request, 0)) { + if (atomic_test_and_clear_bit(&port0_data.show_sink_request, 0)) { /* Display the Sink request */ - dump_sink_request_rdo(port1_data.sink_request.raw_value); + dump_sink_request_rdo(port0_data.sink_request.raw_value); } /* Arbitrary delay */ k_msleep(10); diff --git a/samples/subsys/video/capture/README.rst b/samples/subsys/video/capture/README.rst index 4609da6a7de..29dedf2bdf4 100644 --- a/samples/subsys/video/capture/README.rst +++ b/samples/subsys/video/capture/README.rst @@ -1,12 +1,13 @@ -.. _video_capture-sample: +.. zephyr:code-sample:: video-capture + :name: Video capture + :relevant-api: video_interface -Video Capture -############# + Use the video API to retrieve video frames from a capture device. Description *********** -This sample application uses the Video API to retrieve video frames from the +This sample application uses the :ref:`Video API ` to retrieve video frames from the video capture device, writes a frame count message to the console, and then discards the video frame data. diff --git a/samples/subsys/video/tcpserversink/README.rst b/samples/subsys/video/tcpserversink/README.rst index df856011091..6c7fc89afde 100644 --- a/samples/subsys/video/tcpserversink/README.rst +++ b/samples/subsys/video/tcpserversink/README.rst @@ -1,12 +1,13 @@ -.. _video_tcpserversink-sample: +.. zephyr:code-sample:: video-tcpserversink + :name: Video TCP server sink + :relevant-api: video_interface bsd_sockets -VIDEO TCP SERVER SINK -##################### + Capture video frames and send them over the network to a TCP client. Description *********** -This sample application gets frames from video capture device and sends +This sample application gets frames from a video capture device and sends them over the network to the connected TCP client. Requirements diff --git a/samples/subsys/zbus/benchmark/README.rst b/samples/subsys/zbus/benchmark/README.rst index f42bf7ca7e5..4dd14607623 100644 --- a/samples/subsys/zbus/benchmark/README.rst +++ b/samples/subsys/zbus/benchmark/README.rst @@ -1,7 +1,8 @@ -.. _zbus-benchmark-sample: +.. zephyr:code-sample:: zbus-benchmark + :name: Benchmarking + :relevant-api: zbus_apis -Benchmark sample -################ + Measure the time for sending 256KB from a producer to X consumers. This sample implements an application to measure the time for sending 256KB from the producer to the consumers. diff --git a/samples/subsys/zbus/benchmark/sample.yaml b/samples/subsys/zbus/benchmark/sample.yaml index cf05106947b..b090cc9d467 100644 --- a/samples/subsys/zbus/benchmark/sample.yaml +++ b/samples/subsys/zbus/benchmark/sample.yaml @@ -4,7 +4,7 @@ tests: sample.zbus.benchmark_async: tags: zbus min_ram: 16 - filter: CONFIG_SYS_CLOCK_EXISTS + filter: CONFIG_SYS_CLOCK_EXISTS and not (CONFIG_ARCH_POSIX and not CONFIG_BOARD_NATIVE_POSIX) harness: console harness_config: type: multi_line @@ -21,13 +21,12 @@ tests: - CONFIG_BM_ASYNC=y - arch:nios2:CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 - CONFIG_IDLE_STACK_SIZE=1024 - platform_exclude: nrf52_bsim integration_platforms: - qemu_x86 sample.zbus.benchmark_sync: tags: zbus min_ram: 16 - filter: CONFIG_SYS_CLOCK_EXISTS + filter: CONFIG_SYS_CLOCK_EXISTS and not (CONFIG_ARCH_POSIX and not CONFIG_BOARD_NATIVE_POSIX) harness: console harness_config: type: multi_line @@ -44,6 +43,5 @@ tests: - CONFIG_BM_ASYNC=n - arch:nios2:CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 - CONFIG_IDLE_STACK_SIZE=1024 - platform_exclude: nrf52_bsim integration_platforms: - qemu_x86 diff --git a/samples/subsys/zbus/confirmed_channel/README.rst b/samples/subsys/zbus/confirmed_channel/README.rst index 64ff87757aa..c37c0d2546e 100644 --- a/samples/subsys/zbus/confirmed_channel/README.rst +++ b/samples/subsys/zbus/confirmed_channel/README.rst @@ -1,7 +1,8 @@ -.. _zbus-confirmed-channel-sample: +.. zephyr:code-sample:: zbus-confirmed-channel + :name: Confirmed channel + :relevant-api: zbus_apis -Confirmed channel sample -######################## + Use confirmed zbus channels to ensure all subscribers consume a message. Overview ******** diff --git a/samples/subsys/zbus/dyn_channel/README.rst b/samples/subsys/zbus/dyn_channel/README.rst index 190c5422cd7..91577d3dc98 100644 --- a/samples/subsys/zbus/dyn_channel/README.rst +++ b/samples/subsys/zbus/dyn_channel/README.rst @@ -1,7 +1,8 @@ -.. _zbus-dyn-channel-sample: +.. zephyr:code-sample:: zbus-dyn-channel + :name: Dynamic channel + :relevant-api: zbus_apis -Dynamic channel sample -###################### + Use zbus channels with dynamically allocated messages. Overview ******** diff --git a/samples/subsys/zbus/hello_world/README.rst b/samples/subsys/zbus/hello_world/README.rst index 09c897e3241..ba86d669488 100644 --- a/samples/subsys/zbus/hello_world/README.rst +++ b/samples/subsys/zbus/hello_world/README.rst @@ -1,7 +1,8 @@ -.. _zbus-hello-world-sample: +.. zephyr:code-sample:: zbus-hello-world + :name: zbus Hello World + :relevant-api: zbus_apis -Hello world sample -################## + Make three threads talk to each other using zbus. Overview ******** diff --git a/samples/subsys/zbus/msg_subscriber/CMakeLists.txt b/samples/subsys/zbus/msg_subscriber/CMakeLists.txt new file mode 100644 index 00000000000..3d8f35c0925 --- /dev/null +++ b/samples/subsys/zbus/msg_subscriber/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(msg_subscriber) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/subsys/zbus/msg_subscriber/Kconfig b/samples/subsys/zbus/msg_subscriber/Kconfig new file mode 100644 index 00000000000..3d9e72ce843 --- /dev/null +++ b/samples/subsys/zbus/msg_subscriber/Kconfig @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Rodrigo Peixoto +# SPDX-License-Identifier: Apache-2.0 + +config ZBUS_MSG_SUBSCRIBER_SAMPLE + bool "Force selection of heap listener configurations" + default y + select SYS_HEAP_LISTENER + select SYS_HEAP_RUNTIME_STATS + +source "Kconfig.zephyr" diff --git a/samples/subsys/zbus/msg_subscriber/README.rst b/samples/subsys/zbus/msg_subscriber/README.rst new file mode 100644 index 00000000000..79d52e006f0 --- /dev/null +++ b/samples/subsys/zbus/msg_subscriber/README.rst @@ -0,0 +1,78 @@ +.. zephyr:code-sample:: zbus-msg-subscriber + :name: Message subscriber + :relevant-api: zbus_apis + + Use zbus message subscribers to listen to messages published to channels. + +Overview +******** +This sample illustrates how to use a message subscriber in different +ways in conjunction with other types of observers. + +Building and Running +******************** + +This project outputs to the console. It can be built and executed +on QEMU as follows: + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/zbus/msg_subscriber + :host-os: unix + :board: qemu_x86 + :goals: run + +Sample Output +============= + +.. code-block:: console + + -- west build: running target run + [0/1] To exit from QEMU enter: 'CTRL+a, x'[QEMU] CPU: qemu32,+nx,+pae + Booting from ROM.. + I: ----> Publishing to acc_data_chan channel + I: AL Memory allocated 28 bytes. Total allocated 28 bytes + I: From listener foo_lis -> Acc x=1, y=10, z=100 + I: From msg subscriber bar_msg_sub1 -> Acc x=1, y=10, z=100 + I: From msg subscriber bar_msg_sub2 -> Acc x=1, y=10, z=100 + I: From msg subscriber bar_msg_sub3 -> Acc x=1, y=10, z=100 + I: From msg subscriber bar_msg_sub4 -> Acc x=1, y=10, z=100 + I: From msg subscriber bar_msg_sub5 -> Acc x=1, y=10, z=100 + I: From msg subscriber bar_msg_sub6 -> Acc x=1, y=10, z=100 + I: From msg subscriber bar_msg_sub7 -> Acc x=1, y=10, z=100 + I: From msg subscriber bar_msg_sub8 -> Acc x=1, y=10, z=100 + I: From msg subscriber bar_msg_sub9 -> Acc x=1, y=10, z=100 + I: From msg subscriber bar_msg_sub10 -> Acc x=1, y=10, z=100 + I: From msg subscriber bar_msg_sub11 -> Acc x=1, y=10, z=100 + I: From msg subscriber bar_msg_sub12 -> Acc x=1, y=10, z=100 + I: From msg subscriber bar_msg_sub13 -> Acc x=1, y=10, z=100 + I: From msg subscriber bar_msg_sub14 -> Acc x=1, y=10, z=100 + I: From msg subscriber bar_msg_sub15 -> Acc x=1, y=10, z=100 + I: FR Memory freed 28 bytes. Total allocated 0 bytes + I: From msg subscriber bar_msg_sub16 -> Acc x=1, y=10, z=100 + I: From subscriber bar_sub1 -> Acc x=1, y=10, z=100 + I: From subscriber bar_sub2 -> Acc x=1, y=10, z=100 + I: ----> Publishing to acc_data_chan channel + I: AL Memory allocated 28 bytes. Total allocated 28 bytes + I: From listener foo_lis -> Acc x=2, y=20, z=200 + I: From msg subscriber bar_msg_sub1 -> Acc x=2, y=20, z=200 + I: From msg subscriber bar_msg_sub2 -> Acc x=2, y=20, z=200 + I: From msg subscriber bar_msg_sub3 -> Acc x=2, y=20, z=200 + I: From msg subscriber bar_msg_sub4 -> Acc x=2, y=20, z=200 + I: From msg subscriber bar_msg_sub5 -> Acc x=2, y=20, z=200 + I: From msg subscriber bar_msg_sub6 -> Acc x=2, y=20, z=200 + I: From msg subscriber bar_msg_sub7 -> Acc x=2, y=20, z=200 + I: From msg subscriber bar_msg_sub8 -> Acc x=2, y=20, z=200 + I: From msg subscriber bar_msg_sub9 -> Acc x=2, y=20, z=200 + I: From msg subscriber bar_msg_sub10 -> Acc x=2, y=20, z=200 + I: From msg subscriber bar_msg_sub11 -> Acc x=2, y=20, z=200 + I: From msg subscriber bar_msg_sub12 -> Acc x=2, y=20, z=200 + I: From msg subscriber bar_msg_sub13 -> Acc x=2, y=20, z=200 + I: From msg subscriber bar_msg_sub14 -> Acc x=2, y=20, z=200 + I: From msg subscriber bar_msg_sub15 -> Acc x=2, y=20, z=200 + I: FR Memory freed 28 bytes. Total allocated 0 bytes + I: From msg subscriber bar_msg_sub16 -> Acc x=2, y=20, z=200 + I: From subscriber bar_sub1 -> Acc x=2, y=20, z=200 + I: From subscriber bar_sub2 -> Acc x=2, y=20, z=200 + + +Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`. diff --git a/samples/subsys/zbus/msg_subscriber/prj.conf b/samples/subsys/zbus/msg_subscriber/prj.conf new file mode 100644 index 00000000000..3e786a6d7ed --- /dev/null +++ b/samples/subsys/zbus/msg_subscriber/prj.conf @@ -0,0 +1,12 @@ +CONFIG_LOG=y +CONFIG_LOG_MODE_MINIMAL=y +CONFIG_ASSERT=y +CONFIG_BOOT_BANNER=n +CONFIG_MAIN_THREAD_PRIORITY=5 +CONFIG_ZBUS=y +CONFIG_ZBUS_LOG_LEVEL_INF=y +CONFIG_ZBUS_CHANNEL_NAME=y +CONFIG_ZBUS_OBSERVER_NAME=y +CONFIG_ZBUS_MSG_SUBSCRIBER=y +CONFIG_HEAP_MEM_POOL_SIZE=1024 +CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_SIZE=32 diff --git a/samples/subsys/zbus/msg_subscriber/sample.yaml b/samples/subsys/zbus/msg_subscriber/sample.yaml new file mode 100644 index 00000000000..a344a9ee087 --- /dev/null +++ b/samples/subsys/zbus/msg_subscriber/sample.yaml @@ -0,0 +1,183 @@ +sample: + name: Message subscriber +tests: + sample.zbus.msg_subscriber_dynamic: + harness: console + extra_configs: + - CONFIG_ZBUS_LOG_LEVEL_DBG=y + harness_config: + type: multi_line + ordered: false + regex: + - "^.*?I: ----> Publishing to acc_data_chan channel" + - "^.*?I: AL Memory allocated \\d{1,3} bytes. Total allocated \\d{1,3} bytes$" + - "^.*?I: FR Memory freed \\d{1,3} bytes. Total allocated 0 bytes$" + - "^.*?D: 0 -> bar_sub1" + - "^.*?D: 1 -> bar_msg_sub1" + - "^.*?D: 2 -> bar_msg_sub2" + - "^.*?D: 3 -> bar_msg_sub3" + - "^.*?D: 4 -> bar_msg_sub4" + - "^.*?D: 5 -> bar_msg_sub5" + - "^.*?D: 6 -> bar_msg_sub6" + - "^.*?D: 7 -> bar_msg_sub7" + - "^.*?D: 8 -> bar_msg_sub8" + - "^.*?D: 9 -> bar_msg_sub9" + - "^.*?D: 10 -> foo_lis" + - "^.*?D: 11 -> bar_msg_sub10" + - "^.*?D: 12 -> bar_msg_sub11" + - "^.*?D: 13 -> bar_msg_sub12" + - "^.*?D: 14 -> bar_msg_sub13" + - "^.*?D: 15 -> bar_msg_sub14" + - "^.*?D: 16 -> bar_msg_sub15" + - "^.*?D: 17 -> bar_msg_sub16" + - "^.*?D: 18 -> bar_sub2" + - "^.*?I: From listener foo_lis -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub1 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub2 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub3 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub4 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub5 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub6 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub7 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub8 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub9 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub10 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub11 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub12 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub13 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub14 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub15 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub16 -> Acc x=1, y=10, z=100" + - "^.*?I: From subscriber bar_sub1 -> Acc x=1, y=10, z=100" + - "^.*?I: From subscriber bar_sub2 -> Acc x=1, y=10, z=100" + - "^.*?I: From listener foo_lis -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub1 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub2 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub3 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub4 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub5 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub6 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub7 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub8 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub9 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub10 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub11 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub12 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub13 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub14 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub15 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub16 -> Acc x=2, y=20, z=200" + - "^.*?I: From subscriber bar_sub1 -> Acc x=2, y=20, z=200" + - "^.*?I: From subscriber bar_sub2 -> Acc x=2, y=20, z=200" + - "^.*?I: From listener foo_lis -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub1 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub2 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub3 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub4 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub5 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub6 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub7 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub8 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub9 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub10 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub11 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub12 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub13 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub14 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub15 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub16 -> Acc x=3, y=30, z=300" + - "^.*?I: From subscriber bar_sub1 -> Acc x=3, y=30, z=300" + - "^.*?I: From subscriber bar_sub2 -> Acc x=3, y=30, z=300" + tags: zbus + integration_platforms: + - qemu_x86 + sample.zbus.msg_subscriber_static: + harness: console + extra_configs: + - CONFIG_ZBUS_LOG_LEVEL_DBG=y + - CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_STATIC=y + - CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_STATIC_DATA_SIZE=16 + harness_config: + type: multi_line + ordered: false + regex: + - "^.*?I: ----> Publishing to acc_data_chan channel" + - "^.*?D: 0 -> bar_sub1" + - "^.*?D: 1 -> bar_msg_sub1" + - "^.*?D: 2 -> bar_msg_sub2" + - "^.*?D: 3 -> bar_msg_sub3" + - "^.*?D: 4 -> bar_msg_sub4" + - "^.*?D: 5 -> bar_msg_sub5" + - "^.*?D: 6 -> bar_msg_sub6" + - "^.*?D: 7 -> bar_msg_sub7" + - "^.*?D: 8 -> bar_msg_sub8" + - "^.*?D: 9 -> bar_msg_sub9" + - "^.*?D: 10 -> foo_lis" + - "^.*?D: 11 -> bar_msg_sub10" + - "^.*?D: 12 -> bar_msg_sub11" + - "^.*?D: 13 -> bar_msg_sub12" + - "^.*?D: 14 -> bar_msg_sub13" + - "^.*?D: 15 -> bar_msg_sub14" + - "^.*?D: 16 -> bar_msg_sub15" + - "^.*?D: 17 -> bar_msg_sub16" + - "^.*?D: 18 -> bar_sub2" + - "^.*?I: From listener foo_lis -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub1 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub2 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub3 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub4 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub5 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub6 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub7 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub8 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub9 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub10 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub11 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub12 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub13 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub14 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub15 -> Acc x=1, y=10, z=100" + - "^.*?I: From msg subscriber bar_msg_sub16 -> Acc x=1, y=10, z=100" + - "^.*?I: From subscriber bar_sub1 -> Acc x=1, y=10, z=100" + - "^.*?I: From subscriber bar_sub2 -> Acc x=1, y=10, z=100" + - "^.*?I: From listener foo_lis -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub1 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub2 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub3 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub4 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub5 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub6 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub7 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub8 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub9 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub10 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub11 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub12 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub13 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub14 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub15 -> Acc x=2, y=20, z=200" + - "^.*?I: From msg subscriber bar_msg_sub16 -> Acc x=2, y=20, z=200" + - "^.*?I: From subscriber bar_sub1 -> Acc x=2, y=20, z=200" + - "^.*?I: From subscriber bar_sub2 -> Acc x=2, y=20, z=200" + - "^.*?I: From listener foo_lis -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub1 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub2 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub3 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub4 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub5 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub6 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub7 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub8 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub9 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub10 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub11 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub12 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub13 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub14 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub15 -> Acc x=3, y=30, z=300" + - "^.*?I: From msg subscriber bar_msg_sub16 -> Acc x=3, y=30, z=300" + - "^.*?I: From subscriber bar_sub1 -> Acc x=3, y=30, z=300" + - "^.*?I: From subscriber bar_sub2 -> Acc x=3, y=30, z=300" + tags: zbus + integration_platforms: + - qemu_x86 diff --git a/samples/subsys/zbus/msg_subscriber/src/main.c b/samples/subsys/zbus/msg_subscriber/src/main.c new file mode 100644 index 00000000000..03f9cead113 --- /dev/null +++ b/samples/subsys/zbus/msg_subscriber/src/main.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2022 Rodrigo Peixoto + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +LOG_MODULE_REGISTER(sample, CONFIG_LOG_MAX_LEVEL); + +extern struct sys_heap _system_heap; +static size_t total_allocated; + +void on_heap_alloc(uintptr_t heap_id, void *mem, size_t bytes) +{ + total_allocated += bytes; + LOG_INF(" AL Memory allocated %u bytes. Total allocated %u bytes", (unsigned int)bytes, + (unsigned int)total_allocated); +} + +void on_heap_free(uintptr_t heap_id, void *mem, size_t bytes) +{ + total_allocated -= bytes; + LOG_INF(" FR Memory freed %u bytes. Total allocated %u bytes", (unsigned int)bytes, + (unsigned int)total_allocated); +} + +#if defined(CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_DYNAMIC) + +HEAP_LISTENER_ALLOC_DEFINE(my_heap_listener_alloc, HEAP_ID_FROM_POINTER(&_system_heap), + on_heap_alloc); + +HEAP_LISTENER_FREE_DEFINE(my_heap_listener_free, HEAP_ID_FROM_POINTER(&_system_heap), on_heap_free); + +#endif /* CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_DYNAMIC */ +struct acc_msg { + int x; + int y; + int z; +}; + +ZBUS_CHAN_DEFINE(acc_data_chan, /* Name */ + struct acc_msg, /* Message type */ + + NULL, /* Validator */ + NULL, /* User data */ + ZBUS_OBSERVERS(bar_sub1, bar_msg_sub1, bar_msg_sub2, bar_msg_sub3, bar_msg_sub4, + bar_msg_sub5, bar_msg_sub6, bar_msg_sub7, bar_msg_sub8, + bar_msg_sub9, foo_lis), /* observers */ + ZBUS_MSG_INIT(.x = 0, .y = 0, .z = 0) /* Initial value */ +); + +static void listener_callback_example(const struct zbus_channel *chan) +{ + const struct acc_msg *acc = zbus_chan_const_msg(chan); + + LOG_INF("From listener foo_lis -> Acc x=%d, y=%d, z=%d", acc->x, acc->y, acc->z); +} + +ZBUS_LISTENER_DEFINE(foo_lis, listener_callback_example); + +ZBUS_MSG_SUBSCRIBER_DEFINE(bar_msg_sub1); +ZBUS_MSG_SUBSCRIBER_DEFINE(bar_msg_sub2); +ZBUS_MSG_SUBSCRIBER_DEFINE(bar_msg_sub3); +ZBUS_MSG_SUBSCRIBER_DEFINE(bar_msg_sub4); +ZBUS_MSG_SUBSCRIBER_DEFINE(bar_msg_sub5); +ZBUS_MSG_SUBSCRIBER_DEFINE(bar_msg_sub6); +ZBUS_MSG_SUBSCRIBER_DEFINE(bar_msg_sub7); +ZBUS_MSG_SUBSCRIBER_DEFINE(bar_msg_sub8); +ZBUS_MSG_SUBSCRIBER_DEFINE(bar_msg_sub9); +ZBUS_MSG_SUBSCRIBER_DEFINE(bar_msg_sub10); +ZBUS_MSG_SUBSCRIBER_DEFINE(bar_msg_sub11); +ZBUS_MSG_SUBSCRIBER_DEFINE(bar_msg_sub12); +ZBUS_MSG_SUBSCRIBER_DEFINE(bar_msg_sub13); +ZBUS_MSG_SUBSCRIBER_DEFINE(bar_msg_sub14); +ZBUS_MSG_SUBSCRIBER_DEFINE(bar_msg_sub15); +ZBUS_MSG_SUBSCRIBER_DEFINE(bar_msg_sub16); + +ZBUS_SUBSCRIBER_DEFINE(bar_sub1, 4); +ZBUS_SUBSCRIBER_DEFINE(bar_sub2, 4); + +static void msg_subscriber_task(void *sub) +{ + const struct zbus_channel *chan; + + struct acc_msg acc; + + const struct zbus_observer *subscriber = sub; + + while (!zbus_sub_wait_msg(subscriber, &chan, &acc, K_FOREVER)) { + if (&acc_data_chan != chan) { + LOG_ERR("Wrong channel %p!", chan); + + continue; + } + LOG_INF("From msg subscriber %s -> Acc x=%d, y=%d, z=%d", zbus_obs_name(subscriber), + acc.x, acc.y, acc.z); + } +} + +K_THREAD_DEFINE(subscriber_task_id1, CONFIG_MAIN_STACK_SIZE, msg_subscriber_task, &bar_msg_sub1, + NULL, NULL, 3, 0, 0); +K_THREAD_DEFINE(subscriber_task_id2, CONFIG_MAIN_STACK_SIZE, msg_subscriber_task, &bar_msg_sub2, + NULL, NULL, 3, 0, 0); +K_THREAD_DEFINE(subscriber_task_id3, CONFIG_MAIN_STACK_SIZE, msg_subscriber_task, &bar_msg_sub3, + NULL, NULL, 3, 0, 0); +K_THREAD_DEFINE(subscriber_task_id4, CONFIG_MAIN_STACK_SIZE, msg_subscriber_task, &bar_msg_sub4, + NULL, NULL, 3, 0, 0); +K_THREAD_DEFINE(subscriber_task_id5, CONFIG_MAIN_STACK_SIZE, msg_subscriber_task, &bar_msg_sub5, + NULL, NULL, 3, 0, 0); +K_THREAD_DEFINE(subscriber_task_id6, CONFIG_MAIN_STACK_SIZE, msg_subscriber_task, &bar_msg_sub6, + NULL, NULL, 3, 0, 0); +K_THREAD_DEFINE(subscriber_task_id7, CONFIG_MAIN_STACK_SIZE, msg_subscriber_task, &bar_msg_sub7, + NULL, NULL, 3, 0, 0); +K_THREAD_DEFINE(subscriber_task_id8, CONFIG_MAIN_STACK_SIZE, msg_subscriber_task, &bar_msg_sub8, + NULL, NULL, 3, 0, 0); +K_THREAD_DEFINE(subscriber_task_id9, CONFIG_MAIN_STACK_SIZE, msg_subscriber_task, &bar_msg_sub9, + NULL, NULL, 3, 0, 0); +K_THREAD_DEFINE(subscriber_task_id10, CONFIG_MAIN_STACK_SIZE, msg_subscriber_task, &bar_msg_sub10, + NULL, NULL, 3, 0, 0); +K_THREAD_DEFINE(subscriber_task_id11, CONFIG_MAIN_STACK_SIZE, msg_subscriber_task, &bar_msg_sub11, + NULL, NULL, 3, 0, 0); +K_THREAD_DEFINE(subscriber_task_id12, CONFIG_MAIN_STACK_SIZE, msg_subscriber_task, &bar_msg_sub12, + NULL, NULL, 3, 0, 0); +K_THREAD_DEFINE(subscriber_task_id13, CONFIG_MAIN_STACK_SIZE, msg_subscriber_task, &bar_msg_sub13, + NULL, NULL, 3, 0, 0); +K_THREAD_DEFINE(subscriber_task_id14, CONFIG_MAIN_STACK_SIZE, msg_subscriber_task, &bar_msg_sub14, + NULL, NULL, 3, 0, 0); +K_THREAD_DEFINE(subscriber_task_id15, CONFIG_MAIN_STACK_SIZE, msg_subscriber_task, &bar_msg_sub15, + NULL, NULL, 3, 0, 0); +K_THREAD_DEFINE(subscriber_task_id16, CONFIG_MAIN_STACK_SIZE, msg_subscriber_task, &bar_msg_sub16, + NULL, NULL, 3, 0, 0); + +static void subscriber_task(void *sub) +{ + const struct zbus_channel *chan; + + struct acc_msg acc; + + const struct zbus_observer *subscriber = sub; + + while (!zbus_sub_wait(subscriber, &chan, K_FOREVER)) { + if (&acc_data_chan != chan) { + LOG_ERR("Wrong channel %p!", chan); + + continue; + } + zbus_chan_read(chan, &acc, K_MSEC(250)); + + LOG_INF("From subscriber %s -> Acc x=%d, y=%d, z=%d", zbus_obs_name(subscriber), + acc.x, acc.y, acc.z); + } +} + +K_THREAD_DEFINE(subscriber_task_id17, CONFIG_MAIN_STACK_SIZE, subscriber_task, &bar_sub1, NULL, + NULL, 3, 0, 0); +K_THREAD_DEFINE(subscriber_task_id18, CONFIG_MAIN_STACK_SIZE, subscriber_task, &bar_sub2, NULL, + NULL, 3, 0, 0); + +ZBUS_CHAN_ADD_OBS(acc_data_chan, bar_sub2, 3); +ZBUS_CHAN_ADD_OBS(acc_data_chan, bar_msg_sub10, 3); +ZBUS_CHAN_ADD_OBS(acc_data_chan, bar_msg_sub11, 3); +ZBUS_CHAN_ADD_OBS(acc_data_chan, bar_msg_sub12, 3); +ZBUS_CHAN_ADD_OBS(acc_data_chan, bar_msg_sub13, 3); +ZBUS_CHAN_ADD_OBS(acc_data_chan, bar_msg_sub14, 3); +ZBUS_CHAN_ADD_OBS(acc_data_chan, bar_msg_sub15, 3); +ZBUS_CHAN_ADD_OBS(acc_data_chan, bar_msg_sub16, 3); + +int main(void) +{ + struct acc_msg acc = {.x = 1, .y = 10, .z = 100}; + + total_allocated = 0; + +#if defined(CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_DYNAMIC) + + heap_listener_register(&my_heap_listener_alloc); + heap_listener_register(&my_heap_listener_free); + +#endif /* CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_DYNAMIC */ + + while (1) { + LOG_INF("----> Publishing to %s channel", zbus_chan_name(&acc_data_chan)); + zbus_chan_pub(&acc_data_chan, &acc, K_SECONDS(1)); + acc.x += 1; + acc.y += 10; + acc.z += 100; + + k_msleep(1000); + } + + return 0; +} diff --git a/samples/subsys/zbus/remote_mock/README.rst b/samples/subsys/zbus/remote_mock/README.rst index 1afba887987..f599783e0fa 100644 --- a/samples/subsys/zbus/remote_mock/README.rst +++ b/samples/subsys/zbus/remote_mock/README.rst @@ -1,7 +1,8 @@ -.. _zbus-remote-mock-sample: +.. zephyr:code-sample:: zbus-remote-mock + :name: Remote mock sample + :relevant-api: zbus_apis -Remote mock sample -################## + Publish to a zbus instance using UART as a bridge. Overview ******** @@ -15,12 +16,12 @@ Building and Running ******************** This project outputs to the console. It can be built and executed -on native_posix as follows: +on :ref:`native_sim ` as follows: .. zephyr-app-commands:: :zephyr-app: samples/subsys/zbus/remote_mock :host-os: unix - :board: native_posix + :board: native_sim :goals: run Sample Output @@ -62,7 +63,11 @@ The :file:`remote_mock.py` script can be executed using the following command: python3.8 samples/subsys/zbus/remote_mock/remote_mock.py /dev/pts/2 -Note the run command above prints the value of pts port because it is running in ``native_posix``. Look at the line indicating ``uart_1 connected to pseudotty: /dev/pts/2``. It can be different in your case. If you are using a board, read the documentation to get the correct port destination (in Linux is something like ``/dev/tty...`` or in Windows ``COM...``). +Note the run command above prints the value of pts port because it is running in +:ref:`native_sim `. +Look at the line indicating ``uart_1 connected to pseudotty: /dev/pts/2``. +It can be different in your case. If you are using a board, read the documentation to get the +correct port destination (in Linux is something like ``/dev/tty...`` or in Windows ``COM...``). From the remote mock (Python script), you would see something like this: diff --git a/samples/subsys/zbus/remote_mock/sample.yaml b/samples/subsys/zbus/remote_mock/sample.yaml index 3e49a6e2b03..1b632901ed2 100644 --- a/samples/subsys/zbus/remote_mock/sample.yaml +++ b/samples/subsys/zbus/remote_mock/sample.yaml @@ -9,4 +9,4 @@ tests: - native_sim - hifive1_revb integration_platforms: - - native_posix + - native_sim diff --git a/samples/subsys/zbus/runtime_obs_registration/README.rst b/samples/subsys/zbus/runtime_obs_registration/README.rst index 9e59d11dad6..a3376e1a232 100644 --- a/samples/subsys/zbus/runtime_obs_registration/README.rst +++ b/samples/subsys/zbus/runtime_obs_registration/README.rst @@ -1,7 +1,8 @@ -.. _zbus-runtime-obs-registration-sample: +.. zephyr:code-sample:: zbus-runtime-obs-registration + :name: Runtime observer registration + :relevant-api: zbus_apis -Runtime observer registration sample -#################################### + Use zbus' runtime observer registration to filter data generated by a producer. Overview ******** diff --git a/samples/subsys/zbus/uart_bridge/README.rst b/samples/subsys/zbus/uart_bridge/README.rst index 6b8ba15bd8a..a0101fa45b2 100644 --- a/samples/subsys/zbus/uart_bridge/README.rst +++ b/samples/subsys/zbus/uart_bridge/README.rst @@ -1,7 +1,8 @@ -.. _zbus-uart-bridge-sample: +.. zephyr:code-sample:: zbus-uart-bridge + :name: UART bridge + :relevant-api: zbus_apis -UART bridge sample -################## + Redirect channel events to the host over UART. Overview ******** @@ -13,12 +14,12 @@ Building and Running ******************** This project outputs to the console. It can be built and executed -on native_posix as follows: +on native_sim as follows: .. zephyr-app-commands:: :zephyr-app: samples/subsys/zbus/uart_bridge :host-os: unix - :board: native_posix + :board: native_sim :goals: run Sample Output @@ -67,7 +68,11 @@ The :file:`decoder.py` script can be executed using the following command: python3.8 samples/subsys/zbus/uart_bridge/decoder.py /dev/pts/2 -Note the run command above prints the value of pts port because it is running in ``native_posix``. Look at the line indicating ``uart_1 connected to pseudotty: /dev/pts/2``. It can be different in your case. If you are using a board, read the documentation to get the correct port destination (in Linux is something like ``/dev/tty...`` or in Windows ``COM...``). +Note the run command above prints the value of pts port because it is running in +:ref:`native_sim `. +Look at the line indicating ``uart_1 connected to pseudotty: /dev/pts/2``. +It can be different in your case. If you are using a board, read the documentation to get the +correct port destination (in Linux is something like ``/dev/tty...`` or in Windows ``COM...``). From the serial decoder (Python script), you would see something like this: diff --git a/samples/subsys/zbus/work_queue/README.rst b/samples/subsys/zbus/work_queue/README.rst index 55a94a45999..d88de6d470d 100644 --- a/samples/subsys/zbus/work_queue/README.rst +++ b/samples/subsys/zbus/work_queue/README.rst @@ -1,7 +1,8 @@ -.. _zbus-work-queue-sample: +.. zephyr:code-sample:: zbus-work-queue + :name: Work queue + :relevant-api: zbus_apis -Workqueue sample -################ + Use a work queue to process zbus messages in various ways. Overview ******** diff --git a/samples/subsys/zbus/zbus.rst b/samples/subsys/zbus/zbus.rst index 569802c632f..052589eed94 100644 --- a/samples/subsys/zbus/zbus.rst +++ b/samples/subsys/zbus/zbus.rst @@ -1,6 +1,6 @@ .. _zbus_samples: -Zbus Samples +zbus Samples ############ .. toctree:: diff --git a/samples/synchronization/README.rst b/samples/synchronization/README.rst index f45d3d42d3e..abb633b69e6 100644 --- a/samples/synchronization/README.rst +++ b/samples/synchronization/README.rst @@ -1,7 +1,8 @@ -.. _synchronization_sample: +.. zephyr:code-sample:: synchronization + :name: Basic Synchronization + :relevant-api: thread_apis semaphore_apis -Synchronization Sample -###################### + Manipulate basic kernel synchronization primitives. Overview ******** diff --git a/samples/synchronization/sample.yaml b/samples/synchronization/sample.yaml index 173bfe22ea7..aa6b442c3fa 100644 --- a/samples/synchronization/sample.yaml +++ b/samples/synchronization/sample.yaml @@ -5,6 +5,7 @@ sample: tests: sample.kernel.synchronization: tags: synchronization + build_on_all: true harness: console harness_config: type: multi_line diff --git a/samples/synchronization/src/main.c b/samples/synchronization/src/main.c index 027abd1ed96..e72eea92f92 100644 --- a/samples/synchronization/src/main.c +++ b/samples/synchronization/src/main.c @@ -1,4 +1,4 @@ -/* main.c - Hello World demo */ +/* main.c - Synchronization demo */ /* * Copyright (c) 2012-2014 Wind River Systems, Inc. @@ -10,7 +10,7 @@ #include /* - * The hello world demo has two threads that utilize semaphores and sleeping + * The synchronization demo has two threads that utilize semaphores and sleeping * to take turns printing a greeting message at a controlled rate. The demo * shows both the static and dynamic approaches for spawning a thread; a real * world application would likely use the static approach for both threads. @@ -33,8 +33,8 @@ * @param my_sem thread's own semaphore * @param other_sem other thread's semaphore */ -void helloLoop(const char *my_name, - struct k_sem *my_sem, struct k_sem *other_sem) +void hello_loop(const char *my_name, + struct k_sem *my_sem, struct k_sem *other_sem) { const char *tname; uint8_t cpu; @@ -68,66 +68,52 @@ void helloLoop(const char *my_name, } /* define semaphores */ +K_SEM_DEFINE(thread_a_sem, 1, 1); /* starts off "available" */ +K_SEM_DEFINE(thread_b_sem, 0, 1); /* starts off "not available" */ -K_SEM_DEFINE(threadA_sem, 1, 1); /* starts off "available" */ -K_SEM_DEFINE(threadB_sem, 0, 1); /* starts off "not available" */ - - -/* threadB is a dynamic thread that is spawned by threadA */ - -void threadB(void *dummy1, void *dummy2, void *dummy3) +/* thread_a is a dynamic thread that is spawned in main */ +void thread_a_entry_point(void *dummy1, void *dummy2, void *dummy3) { ARG_UNUSED(dummy1); ARG_UNUSED(dummy2); ARG_UNUSED(dummy3); - /* invoke routine to ping-pong hello messages with threadA */ - helloLoop(__func__, &threadB_sem, &threadA_sem); + /* invoke routine to ping-pong hello messages with thread_b */ + hello_loop(__func__, &thread_a_sem, &thread_b_sem); } +K_THREAD_STACK_DEFINE(thread_a_stack_area, STACKSIZE); +static struct k_thread thread_a_data; -K_THREAD_STACK_DEFINE(threadA_stack_area, STACKSIZE); -static struct k_thread threadA_data; - -K_THREAD_STACK_DEFINE(threadB_stack_area, STACKSIZE); -static struct k_thread threadB_data; - -/* threadA is a static thread that is spawned automatically */ - -void threadA(void *dummy1, void *dummy2, void *dummy3) +/* thread_b is a static thread spawned immediately */ +void thread_b_entry_point(void *dummy1, void *dummy2, void *dummy3) { ARG_UNUSED(dummy1); ARG_UNUSED(dummy2); ARG_UNUSED(dummy3); - /* invoke routine to ping-pong hello messages with threadB */ - helloLoop(__func__, &threadA_sem, &threadB_sem); + /* invoke routine to ping-pong hello messages with thread_a */ + hello_loop(__func__, &thread_b_sem, &thread_a_sem); } +K_THREAD_DEFINE(thread_b, STACKSIZE, + thread_b_entry_point, NULL, NULL, NULL, + PRIORITY, 0, 0); +extern const k_tid_t thread_b; int main(void) { - k_thread_create(&threadA_data, threadA_stack_area, - K_THREAD_STACK_SIZEOF(threadA_stack_area), - threadA, NULL, NULL, NULL, + k_thread_create(&thread_a_data, thread_a_stack_area, + K_THREAD_STACK_SIZEOF(thread_a_stack_area), + thread_a_entry_point, NULL, NULL, NULL, PRIORITY, 0, K_FOREVER); - k_thread_name_set(&threadA_data, "thread_a"); -#if PIN_THREADS - if (arch_num_cpus() > 1) { - k_thread_cpu_pin(&threadA_data, 0); - } -#endif + k_thread_name_set(&thread_a_data, "thread_a"); - k_thread_create(&threadB_data, threadB_stack_area, - K_THREAD_STACK_SIZEOF(threadB_stack_area), - threadB, NULL, NULL, NULL, - PRIORITY, 0, K_FOREVER); - k_thread_name_set(&threadB_data, "thread_b"); #if PIN_THREADS if (arch_num_cpus() > 1) { - k_thread_cpu_pin(&threadB_data, 1); + k_thread_cpu_pin(&thread_a_data, 0); + k_thread_cpu_pin(thread_b, 1); } #endif - k_thread_start(&threadA_data); - k_thread_start(&threadB_data); + k_thread_start(&thread_a_data); return 0; } diff --git a/samples/tfm_integration/psa_crypto/prj.conf b/samples/tfm_integration/psa_crypto/prj.conf index a5f38632d51..97df0796411 100644 --- a/samples/tfm_integration/psa_crypto/prj.conf +++ b/samples/tfm_integration/psa_crypto/prj.conf @@ -35,4 +35,4 @@ CONFIG_JSON_LIBRARY=y CONFIG_TFM_PARTITION_INITIAL_ATTESTATION=y CONFIG_TFM_QCBOR_PATH="DOWNLOAD" -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y diff --git a/samples/tfm_integration/psa_crypto/sample.yaml b/samples/tfm_integration/psa_crypto/sample.yaml index d76eb6a2378..45c9940b021 100644 --- a/samples/tfm_integration/psa_crypto/sample.yaml +++ b/samples/tfm_integration/psa_crypto/sample.yaml @@ -5,7 +5,12 @@ sample: name: PSA crypto example tests: sample.psa_crypto: - tags: introduction tfm crypto csr + tags: + - introduction + - trusted-firmware-m + - crypto + - csr + - mcuboot platform_allow: mps2_an521_ns v2m_musca_s1_ns nrf5340dk_nrf5340_cpuapp_ns nrf9160dk_nrf9160_ns stm32l562e_dk_ns bl5340_dvk_cpuapp_ns diff --git a/samples/tfm_integration/psa_protected_storage/sample.yaml b/samples/tfm_integration/psa_protected_storage/sample.yaml index 444f75c2a78..83ddde86758 100644 --- a/samples/tfm_integration/psa_protected_storage/sample.yaml +++ b/samples/tfm_integration/psa_protected_storage/sample.yaml @@ -28,4 +28,6 @@ common: tests: sample.tfm.protected_storage: - tags: tfm + tags: + - trusted-firmware-m + - mcuboot diff --git a/samples/tfm_integration/tfm_integration.rst b/samples/tfm_integration/tfm_integration.rst index 2ca5804d595..02cd3e97855 100644 --- a/samples/tfm_integration/tfm_integration.rst +++ b/samples/tfm_integration/tfm_integration.rst @@ -9,9 +9,6 @@ TF-M Integration Samples */* -Trusted Firmware-M (TF-M) -######################### - Overview ******** These TF-M integration examples can be used with a supported Armv8-M board, and diff --git a/samples/tfm_integration/tfm_ipc/sample.yaml b/samples/tfm_integration/tfm_ipc/sample.yaml index 968ad517ebd..4537b5c48dc 100644 --- a/samples/tfm_integration/tfm_ipc/sample.yaml +++ b/samples/tfm_integration/tfm_ipc/sample.yaml @@ -6,7 +6,8 @@ tests: sample.tfm_ipc: tags: - introduction - - tfm + - trusted-firmware-m + - mcuboot platform_allow: - mps2_an521_ns - nrf5340dk_nrf5340_cpuapp_ns @@ -29,7 +30,7 @@ tests: sample.tfm_ipc.no_bl2: tags: - introduction - - tfm + - trusted-firmware-m platform_allow: mps2_an521_ns extra_configs: - CONFIG_TFM_BL2=n diff --git a/samples/tfm_integration/tfm_psa_test/sample.yaml b/samples/tfm_integration/tfm_psa_test/sample.yaml index 43c8c45c735..df8ae92a372 100644 --- a/samples/tfm_integration/tfm_psa_test/sample.yaml +++ b/samples/tfm_integration/tfm_psa_test/sample.yaml @@ -1,11 +1,16 @@ common: - tags: tfm + tags: + - trusted-firmware-m + - mcuboot platform_allow: - mps2_an521_ns - nrf5340dk_nrf5340_cpuapp_ns - nrf9160dk_nrf9160_ns - nrf9161dk_nrf9161_ns - v2m_musca_s1_ns + modules: + - psa-arch-tests + - tf-m-tests integration_platforms: - mps2_an521_ns harness: console diff --git a/samples/tfm_integration/tfm_regression_test/boards/nucleo_l552ze_q_ns.overlay b/samples/tfm_integration/tfm_regression_test/boards/nucleo_l552ze_q_ns.overlay new file mode 100644 index 00000000000..01744d106f4 --- /dev/null +++ b/samples/tfm_integration/tfm_regression_test/boards/nucleo_l552ze_q_ns.overlay @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + + + /* This partition table could be used along with TFM configuration: + * - TEST_S=ON (REGRESSION) + * - TFM_PSA_API=ON (IPC) + * + */ + +/ { + chosen { + zephyr,code-partition = &slot1_partition; + }; +}; + +&flash0 { + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 DT_SIZE_K(80)>; + read-only; + }; + /* Secure image primary slot */ + slot0_partition: partition@14000 { + label = "image-0"; + reg = <0x00014000 DT_SIZE_K(224)>; + }; + /* Non-secure image primary slot */ + slot1_partition: partition@4c000 { + label = "image-1"; + reg = <0x0004c000 DT_SIZE_K(172)>; + }; + /* + * The flash starting at 0x7F000 and ending at + * 0x80000 is reserved for the application. + */ + storage_partition: partition@77000 { + label = "storage"; + reg = <0x0007F000 DT_SIZE_K(40)>; + }; + }; +}; diff --git a/samples/tfm_integration/tfm_regression_test/sample.yaml b/samples/tfm_integration/tfm_regression_test/sample.yaml index c9ebbcf67ec..e5612d909c8 100644 --- a/samples/tfm_integration/tfm_regression_test/sample.yaml +++ b/samples/tfm_integration/tfm_regression_test/sample.yaml @@ -1,7 +1,10 @@ common: - tags: tfm + tags: + - trusted-firmware-m + - mcuboot + modules: + - psa-arch-tests platform_allow: - - nrf5340dk_nrf5340_cpuapp_ns - nrf9160dk_nrf9160_ns - nrf9161dk_nrf9161_ns diff --git a/samples/tfm_integration/tfm_secure_partition/README.rst b/samples/tfm_integration/tfm_secure_partition/README.rst index 2faa4d25419..94158ef06d8 100644 --- a/samples/tfm_integration/tfm_secure_partition/README.rst +++ b/samples/tfm_integration/tfm_secure_partition/README.rst @@ -6,21 +6,29 @@ TF-M Secure Partition Sample Overview ******** -A Secure Partition is an isolated module that resides in TF-M. It exposes a number of functions or "secure services" to other partitions and/or to the non-secure firmware. -TF-M already contains standard partitions such as crypto, protected_storage, or firmware_update, but it's also possible to create your own partitions. +A Secure Partition is an isolated module that resides in TF-M. It exposes a number of functions or +"secure services" to other partitions and/or to the non-secure firmware. TF-M already contains +standard partitions such as crypto, protected_storage, or firmware_update, but it's also possible to +create your own partitions. -This sample creates a dummy secure partition and secure service for TF-M and instructs the TF-M build system to build it into the secure firmware. -The dummy secure service is then called in the main file (in the non-secure firmware). +This sample creates a dummy secure partition and secure service for TF-M and instructs the TF-M +build system to build it into the secure firmware. The dummy secure service is then called in the +main file (in the non-secure firmware). -This dummy partition has a single secure service, which can index one of 5 dummy secrets inside the partition, and retrieve a hash of the secret. +This dummy partition has a single secure service, which can index one of 5 dummy secrets inside the +partition, and retrieve a hash of the secret. -The partition is located in the ``dummy_partition`` directory. It contains the partition sources, build files and build configuration files. -The partition is built by the TF-M build system, refer to :ref:`tfm_build_system` for more details. +The partition is located in the ``dummy_partition`` directory. It contains the partition sources, +build files and build configuration files. The partition is built by the TF-M build system, refer to +:ref:`tfm_build_system` for more details. -For more information on how to add custom secure partitions refer to TF-M's guide: https://tf-m-user-guide.trustedfirmware.org/docs/integration_guide/services/tfm_secure_partition_addition.html +For more information on how to add custom secure partitions refer to TF-M's guide: +https://tf-m-user-guide.trustedfirmware.org/integration_guide/services/tfm_secure_partition_addition.html -When adapting this partition for your own purposes, please change all occurrences of "dummy_partition", "DUMMY_PARTITION", "dp", and "DP" to your own partition name. -Also, look through both the secure and non-secure CMakeLists.txt file and make relevant changes, as well as the yaml files inside "partition". +When adapting this partition for your own purposes, please change all occurrences of +"dummy_partition", "DUMMY_PARTITION", "dp", and "DP" to your own partition name. Also, look through +both the secure and non-secure CMakeLists.txt file and make relevant changes, as well as the yaml +files inside "partition". Building and Running ******************** @@ -32,8 +40,8 @@ On Target Refer to :ref:`tfm_ipc` for detailed instructions. -On QEMU: -======== +On QEMU +======= Refer to :ref:`tfm_ipc` for detailed instructions. diff --git a/samples/tfm_integration/tfm_secure_partition/sample.yaml b/samples/tfm_integration/tfm_secure_partition/sample.yaml index 5c9a1a94f5e..06cb3bc2e96 100644 --- a/samples/tfm_integration/tfm_secure_partition/sample.yaml +++ b/samples/tfm_integration/tfm_secure_partition/sample.yaml @@ -1,5 +1,6 @@ common: - tags: tfm + tags: + - trusted-firmware-m platform_allow: - mps2_an521_ns - v2m_musca_s1_ns @@ -22,4 +23,6 @@ sample: tests: sample.tfm.secure_partition: - tags: tfm + tags: + - trusted-firmware-m + - mcuboot diff --git a/samples/userspace/hello_world_user/prj.conf b/samples/userspace/hello_world_user/prj.conf index 746de64bb6a..7de714c1418 100644 --- a/samples/userspace/hello_world_user/prj.conf +++ b/samples/userspace/hello_world_user/prj.conf @@ -1,6 +1,2 @@ CONFIG_USERSPACE=y -CONFIG_APPLICATION_DEFINED_SYSCALL=y CONFIG_ASSERT=y -CONFIG_LOG=y -CONFIG_LOG_MODE_MINIMAL=y -CONFIG_MAIN_STACK_SIZE=2560 diff --git a/samples/userspace/hello_world_user/sample.yaml b/samples/userspace/hello_world_user/sample.yaml index 1a0a407e893..f782f36cad4 100644 --- a/samples/userspace/hello_world_user/sample.yaml +++ b/samples/userspace/hello_world_user/sample.yaml @@ -14,4 +14,6 @@ common: tests: sample.helloworld: filter: CONFIG_ARCH_HAS_USERSPACE + arch_exclude: + - posix tags: introduction diff --git a/samples/userspace/prod_consumer/sample.yaml b/samples/userspace/prod_consumer/sample.yaml index 791f103b6ef..cc4aaa5d118 100644 --- a/samples/userspace/prod_consumer/sample.yaml +++ b/samples/userspace/prod_consumer/sample.yaml @@ -13,3 +13,5 @@ common: tests: sample.userspace.prod_consumer: filter: CONFIG_ARCH_HAS_USERSPACE + arch_exclude: + - posix diff --git a/samples/userspace/prod_consumer/src/app_syscall.c b/samples/userspace/prod_consumer/src/app_syscall.c index 0f66c54c159..c1b630ba9f2 100644 --- a/samples/userspace/prod_consumer/src/app_syscall.c +++ b/samples/userspace/prod_consumer/src/app_syscall.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include LOG_MODULE_REGISTER(app_syscall); @@ -38,7 +38,7 @@ static int z_vrfy_magic_syscall(unsigned int *cookie) /* Confirm that this user-supplied pointer is valid memory that * can be accessed. If it's OK, copy into cookie_copy. */ - if (z_user_from_copy(&cookie_copy, cookie, sizeof(*cookie)) != 0) { + if (k_usermode_from_copy(&cookie_copy, cookie, sizeof(*cookie)) != 0) { return -EPERM; } @@ -47,7 +47,7 @@ static int z_vrfy_magic_syscall(unsigned int *cookie) ret = z_impl_magic_syscall(&cookie_copy); if (ret == 0 && - z_user_to_copy(cookie, &cookie_copy, sizeof(*cookie)) != 0) { + k_usermode_to_copy(cookie, &cookie_copy, sizeof(*cookie)) != 0) { return -EPERM; } diff --git a/samples/userspace/prod_consumer/src/sample_driver_handlers.c b/samples/userspace/prod_consumer/src/sample_driver_handlers.c index 8531b2b88f3..89a4ff12044 100644 --- a/samples/userspace/prod_consumer/src/sample_driver_handlers.c +++ b/samples/userspace/prod_consumer/src/sample_driver_handlers.c @@ -5,12 +5,12 @@ */ #include -#include +#include #include "sample_driver.h" int z_vrfy_sample_driver_state_set(const struct device *dev, bool active) { - if (Z_SYSCALL_DRIVER_SAMPLE(dev, state_set)) { + if (K_SYSCALL_DRIVER_SAMPLE(dev, state_set)) { return -EINVAL; } @@ -21,11 +21,11 @@ int z_vrfy_sample_driver_state_set(const struct device *dev, bool active) int z_vrfy_sample_driver_write(const struct device *dev, void *buf) { - if (Z_SYSCALL_DRIVER_SAMPLE(dev, write)) { + if (K_SYSCALL_DRIVER_SAMPLE(dev, write)) { return -EINVAL; } - if (Z_SYSCALL_MEMORY_READ(buf, SAMPLE_DRIVER_MSG_SIZE)) { + if (K_SYSCALL_MEMORY_READ(buf, SAMPLE_DRIVER_MSG_SIZE)) { return -EFAULT; } diff --git a/samples/userspace/shared_mem/boards/nucleo_f746zg.overlay b/samples/userspace/shared_mem/boards/nucleo_f746zg.overlay new file mode 100644 index 00000000000..50fa5dcc6e1 --- /dev/null +++ b/samples/userspace/shared_mem/boards/nucleo_f746zg.overlay @@ -0,0 +1,13 @@ +/* + * Copyright 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Disable quadspi MPU region for testing + * on this stm32f7 target + * else one region is missing among 8 MPU regions + */ + +/delete-node/ &quadspi_memory; diff --git a/samples/userspace/shared_mem/sample.yaml b/samples/userspace/shared_mem/sample.yaml index b9d72fbe145..954b6a9d3d6 100644 --- a/samples/userspace/shared_mem/sample.yaml +++ b/samples/userspace/shared_mem/sample.yaml @@ -14,6 +14,11 @@ common: tests: sample.kernel.memory_protection.shared_mem: filter: CONFIG_ARCH_HAS_USERSPACE - platform_exclude: twr_ke18f + arch_exclude: + - posix + platform_exclude: + - twr_ke18f + - cy8cproto_062_4343w + - cy8cproto_063_ble extra_configs: - CONFIG_TEST_HW_STACK_PROTECTION=n diff --git a/samples/userspace/shared_mem/src/main.c b/samples/userspace/shared_mem/src/main.c index 7eaecfc254a..c8b9adbae1b 100644 --- a/samples/userspace/shared_mem/src/main.c +++ b/samples/userspace/shared_mem/src/main.c @@ -133,7 +133,7 @@ int main(void) * then add the thread to the domain. */ tENC = k_thread_create(&enc_thread, enc_stack, STACKSIZE, - (k_thread_entry_t)enc, NULL, NULL, NULL, + enc, NULL, NULL, NULL, -1, K_USER, K_FOREVER); k_thread_access_grant(tENC, &allforone); @@ -150,7 +150,7 @@ int main(void) tPT = k_thread_create(&pt_thread, pt_stack, STACKSIZE, - (k_thread_entry_t)pt, NULL, NULL, NULL, + pt, NULL, NULL, NULL, -1, K_USER, K_FOREVER); k_thread_access_grant(tPT, &allforone); @@ -163,7 +163,7 @@ int main(void) printk("pt_domain Created\n"); tCT = k_thread_create(&ct_thread, ct_stack, STACKSIZE, - (k_thread_entry_t)ct, NULL, NULL, NULL, + ct, NULL, NULL, NULL, -1, K_USER, K_FOREVER); k_thread_access_grant(tCT, &allforone); @@ -204,8 +204,11 @@ int main(void) * Copy memory from pt thread and encrypt to a local buffer * then copy to the ct thread. */ -void enc(void) +void enc(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); int index, index_out; @@ -252,8 +255,11 @@ void enc(void) * It can be extended to receive data from a serial port * and pass the data to enc */ -void pt(void) +void pt(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); k_sleep(K_MSEC(20)); while (1) { @@ -282,8 +288,11 @@ void pt(void) * CT waits for fBUFOUT = 1 then copies * the message clears the flag and prints */ -void ct(void) +void ct(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); char tbuf[60]; diff --git a/samples/userspace/shared_mem/src/main.h b/samples/userspace/shared_mem/src/main.h index 3fa72b5df1f..40c18364c96 100644 --- a/samples/userspace/shared_mem/src/main.h +++ b/samples/userspace/shared_mem/src/main.h @@ -20,9 +20,9 @@ #include #endif -void enc(void); -void pt(void); -void ct(void); +void enc(void *p1, void *p2, void *p3); +void pt(void *p1, void *p2, void *p3); +void ct(void *p1, void *p2, void *p3); #define _app_user_d K_APP_DMEM(user_part) #define _app_user_b K_APP_BMEM(user_part) diff --git a/scripts/build/check_init_priorities.py b/scripts/build/check_init_priorities.py index 4036d8984b5..ba6f476fba5 100755 --- a/scripts/build/check_init_priorities.py +++ b/scripts/build/check_init_priorities.py @@ -6,14 +6,16 @@ """ Checks the initialization priorities -This script parses the object files in the specified build directory, creates a -list of known devices and their effective initialization priorities and -compares that with the device dependencies inferred from the devicetree -hierarchy. +This script parses a Zephyr executable file, creates a list of known devices +and their effective initialization priorities and compares that with the device +dependencies inferred from the devicetree hierarchy. This can be used to detect devices that are initialized in the incorrect order, but also devices that are initialized at the same priority but depends on each other, which can potentially break if the linking order is changed. + +Optionally, it can also produce a human readable list of the initialization +calls for the various init levels. """ import argparse @@ -24,7 +26,6 @@ import sys from elftools.elf.elffile import ELFFile -from elftools.elf.relocation import RelocationSection from elftools.elf.sections import SymbolTableSection # This is needed to load edt.pickle files. @@ -32,24 +33,14 @@ "dts", "python-devicetree", "src")) from devicetree import edtlib # pylint: disable=unused-import -# Prefix used for relocation sections containing initialization data, as in -# sequence of "struct init_entry". -_INIT_SECTION_PREFIX = (".rel.z_init_", ".rela.z_init_") - # Prefix used for "struct device" reference initialized based on devicetree # entries with a known ordinal. _DEVICE_ORD_PREFIX = "__device_dts_ord_" -# File name suffix for object files to be scanned. -_OBJ_FILE_SUFFIX = ".c.obj" - # Defined init level in order of priority. _DEVICE_INIT_LEVELS = ["EARLY", "PRE_KERNEL_1", "PRE_KERNEL_2", "POST_KERNEL", "APPLICATION", "SMP"] -# File name to check for detecting and skiping nested build directories. -_BUILD_DIR_DETECT_FILE = "CMakeCache.txt" - # List of compatibles for node where the initialization priority should be the # opposite of the device tree inferred dependency. _INVERTED_PRIORITY_COMPATIBLES = frozenset() @@ -65,34 +56,28 @@ class Priority: """Parses and holds a device initialization priority. - Parses an ELF section name for the corresponding initialization level and - priority, for example ".rel.z_init_PRE_KERNEL_155_" for "PRE_KERNEL_1 55". - The object can be used for comparing levels with one another. Attributes: name: the section name """ - def __init__(self, name): - for idx, level in enumerate(_DEVICE_INIT_LEVELS): - if level in name: - _, priority_str = name.strip("_").split(level) - priority, sub_priority = priority_str.split("_") + def __init__(self, level, priority): + for idx, level_name in enumerate(_DEVICE_INIT_LEVELS): + if level_name == level: self._level = idx - self._priority = int(priority) - self._sub_priority = int(sub_priority) + self._priority = priority # Tuples compare elementwise in order - self._level_priority = (self._level, self._priority, self._sub_priority) + self._level_priority = (self._level, self._priority) return - raise ValueError("Unknown level in %s" % name) + raise ValueError("Unknown level in %s" % level) def __repr__(self): - return "<%s %s %d %d>" % (self.__class__.__name__, - _DEVICE_INIT_LEVELS[self._level], self._priority, self._sub_priority) + return "<%s %s %d>" % (self.__class__.__name__, + _DEVICE_INIT_LEVELS[self._level], self._priority) def __str__(self): - return "%s %d %d" % (_DEVICE_INIT_LEVELS[self._level], self._priority, self._sub_priority) + return "%s+%d" % (_DEVICE_INIT_LEVELS[self._level], self._priority) def __lt__(self, other): return self._level_priority < other._level_priority @@ -104,15 +89,15 @@ def __hash__(self): return self._level_priority -class ZephyrObjectFile: - """Load an object file and finds the device defined within it. +class ZephyrInitLevels: + """Load an executable file and find the initialization calls and devices. - Load an object file and scans the relocation sections looking for the known - ones containing initialization callbacks. Then finds what device ordinals - are being initialized at which priority and stores the list internally. + Load a Zephyr executable file and scan for the list of initialization calls + and defined devices. - A dictionary of {ordinal: Priority} is available in the defined_devices - class variable. + The list of devices is available in the "devices" class variable in the + {ordinal: Priority} format, the list of initilevels is in the "initlevels" + class variables in the {"level name": ["call", ...]} format. Attributes: file_path: path of the file to be loaded. @@ -120,26 +105,49 @@ class variable. def __init__(self, file_path): self.file_path = file_path self._elf = ELFFile(open(file_path, "rb")) - self._load_symbols() - self._find_defined_devices() + self._load_objects() + self._load_level_addr() + self._process_initlevels() + + def _load_objects(self): + """Initialize the object table.""" + self._objects = {} + + for section in self._elf.iter_sections(): + if not isinstance(section, SymbolTableSection): + continue - def _load_symbols(self): - """Initialize the symbols table.""" - self._symbols = {} + for sym in section.iter_symbols(): + if (sym.name and + sym.entry.st_size > 0 and + sym.entry.st_info.type in ["STT_OBJECT", "STT_FUNC"]): + self._objects[sym.entry.st_value] = ( + sym.name, sym.entry.st_size, sym.entry.st_shndx) + + def _load_level_addr(self): + """Find the address associated with known init levels.""" + self._init_level_addr = {} for section in self._elf.iter_sections(): if not isinstance(section, SymbolTableSection): continue - for num, sym in enumerate(section.iter_symbols()): - if sym.name: - self._symbols[num] = sym.name + for sym in section.iter_symbols(): + for level in _DEVICE_INIT_LEVELS: + name = f"__init_{level}_start" + if sym.name == name: + self._init_level_addr[level] = sym.entry.st_value + elif sym.name == "__init_end": + self._init_level_end = sym.entry.st_value + + if len(self._init_level_addr) != len(_DEVICE_INIT_LEVELS): + raise ValueError(f"Missing init symbols, found: {self._init_level_addr}") - def _device_ord_from_rel(self, rel): - """Find a device ordinal from a device symbol name.""" - sym_id = rel["r_info_sym"] - sym_name = self._symbols.get(sym_id, None) + if not self._init_level_end: + raise ValueError(f"Missing init section end symbol") + def _device_ord_from_name(self, sym_name): + """Find a device ordinal from a symbol name.""" if not sym_name: return None @@ -149,35 +157,67 @@ def _device_ord_from_rel(self, rel): _, device_ord = sym_name.split(_DEVICE_ORD_PREFIX) return int(device_ord) - def _find_defined_devices(self): - """Find the device structures defined in the object file.""" - self.defined_devices = {} + def _object_name(self, addr): + if not addr: + return "NULL" + elif addr in self._objects: + return self._objects[addr][0] + else: + return "unknown" + + def _initlevel_pointer(self, addr, idx, shidx): + elfclass = self._elf.elfclass + if elfclass == 32: + ptrsize = 4 + elif elfclass == 64: + ptrsize = 8 + else: + ValueError(f"Unknown pointer size for ELF class f{elfclass}") - for section in self._elf.iter_sections(): - if not isinstance(section, RelocationSection): - continue + section = self._elf.get_section(shidx) + start = section.header.sh_addr + data = section.data() - if not section.name.startswith(_INIT_SECTION_PREFIX): - continue + offset = addr - start - prio = Priority(section.name) + start = offset + ptrsize * idx + stop = offset + ptrsize * (idx + 1) - for rel in section.iter_relocations(): - device_ord = self._device_ord_from_rel(rel) - if not device_ord: - continue + return int.from_bytes(data[start:stop], byteorder="little") - if device_ord in self.defined_devices: - raise ValueError( - f"Device {device_ord} already defined, stale " - "object files in the build directory? " - "Try running a clean build.") + def _process_initlevels(self): + """Process the init level and find the init functions and devices.""" + self.devices = {} + self.initlevels = {} - self.defined_devices[device_ord] = prio + for i, level in enumerate(_DEVICE_INIT_LEVELS): + start = self._init_level_addr[level] + if i + 1 == len(_DEVICE_INIT_LEVELS): + stop = self._init_level_end + else: + stop = self._init_level_addr[_DEVICE_INIT_LEVELS[i + 1]] - def __repr__(self): - return (f"<{self.__class__.__name__} {self.file_path} " - f"defined_devices: {self.defined_devices}>") + self.initlevels[level] = [] + + priority = 0 + addr = start + while addr < stop: + if addr not in self._objects: + raise ValueError(f"no symbol at addr {addr:08x}") + obj, size, shidx = self._objects[addr] + + arg0_name = self._object_name(self._initlevel_pointer(addr, 0, shidx)) + arg1_name = self._object_name(self._initlevel_pointer(addr, 1, shidx)) + + self.initlevels[level].append(f"{obj}: {arg0_name}({arg1_name})") + + ordinal = self._device_ord_from_name(arg1_name) + if ordinal: + prio = Priority(level, priority) + self.devices[ordinal] = (prio, arg0_name) + + addr += size + priority += 1 class Validator(): """Validates the initialization priorities. @@ -187,51 +227,24 @@ class Validator(): dependency list and log any found priority issue. Attributes: - build_dir: the build directory to scan - edt_pickle_path: path of the EDT pickle file + elf_file_path: path of the ELF file + edt_pickle: name of the EDT pickle file log: a logging.Logger object """ - def __init__(self, build_dir, edt_pickle_path, log): + def __init__(self, elf_file_path, edt_pickle, log): self.log = log - edtser = pathlib.Path(build_dir, edt_pickle_path) - with open(edtser, "rb") as f: + edt_pickle_path = pathlib.Path( + pathlib.Path(elf_file_path).parent, + edt_pickle) + with open(edt_pickle_path, "rb") as f: edt = pickle.load(f) self._ord2node = edt.dep_ord2node - self._objs = [] - for file in self._find_build_objfiles(build_dir, is_root=True): - obj = ZephyrObjectFile(file) - if obj.defined_devices: - self._objs.append(obj) - for dev in obj.defined_devices: - dev_path = self._ord2node[dev].path - self.log.debug(f"{file}: {dev_path}") - - self._dev_priorities = {} - for obj in self._objs: - for dev, prio in obj.defined_devices.items(): - if dev in self._dev_priorities: - dev_path = self._ord2node[dev].path - raise ValueError( - f"ERROR: device {dev} ({dev_path}) already defined") - self._dev_priorities[dev] = prio - - self.warnings = 0 - self.errors = 0 + self._obj = ZephyrInitLevels(elf_file_path) - def _find_build_objfiles(self, build_dir, is_root=False): - """Find all project object files, skip sub-build directories.""" - if not is_root and pathlib.Path(build_dir, _BUILD_DIR_DETECT_FILE).exists(): - return - - for file in pathlib.Path(build_dir).iterdir(): - if file.is_file() and file.name.endswith(_OBJ_FILE_SUFFIX): - yield file - if file.is_dir(): - for file in self._find_build_objfiles(file.resolve()): - yield file + self.errors = 0 def _check_dep(self, dev_ord, dep_ord): """Validate the priority between two devices.""" @@ -254,41 +267,41 @@ def _check_dep(self, dev_ord, dep_ord): self.log.info(f"Swapped priority: {dev_compat}, {dep_compat}") dev_ord, dep_ord = dep_ord, dev_ord - dev_prio = self._dev_priorities.get(dev_ord, None) - dep_prio = self._dev_priorities.get(dep_ord, None) + dev_prio, dev_init = self._obj.devices.get(dev_ord, (None, None)) + dep_prio, dep_init = self._obj.devices.get(dep_ord, (None, None)) if not dev_prio or not dep_prio: return if dev_prio == dep_prio: - self.warnings += 1 - self.log.warning( - f"{dev_node.path} {dev_prio} == {dep_node.path} {dep_prio}") + raise ValueError(f"{dev_node.path} and {dep_node.path} have the " + f"same priority: {dev_prio}") elif dev_prio < dep_prio: + if not self.errors: + self.log.error("Device initialization priority validation failed, " + "the sequence of initialization calls does not match " + "the devicetree dependencies.") self.errors += 1 self.log.error( - f"{dev_node.path} {dev_prio} < {dep_node.path} {dep_prio}") + f"{dev_node.path} <{dev_init}> is initialized before its dependency " + f"{dep_node.path} <{dep_init}> ({dev_prio} < {dep_prio})") else: self.log.info( - f"{dev_node.path} {dev_prio} > {dep_node.path} {dep_prio}") - - def _check_edt_r(self, dev_ord, dev): - """Recursively check for dependencies of a device.""" - for dep in dev.depends_on: - self._check_dep(dev_ord, dep.dep_ordinal) - if dev._binding and dev._binding.child_binding: - for child in dev.children.values(): - if "compatible" in child.props: - continue - if dev._binding.path != child._binding.path: - continue - self._check_edt_r(dev_ord, child) + f"{dev_node.path} <{dev_init}> {dev_prio} > " + f"{dep_node.path} <{dep_init}> {dep_prio}") def check_edt(self): """Scan through all known devices and validate the init priorities.""" - for dev_ord in self._dev_priorities: + for dev_ord in self._obj.devices: dev = self._ord2node[dev_ord] - self._check_edt_r(dev_ord, dev) + for dep in dev.depends_on: + self._check_dep(dev_ord, dep.dep_ordinal) + + def print_initlevels(self): + for level, calls in self._obj.initlevels.items(): + print(level) + for call in calls: + print(f" {call}") def _parse_args(argv): """Parse the command line arguments.""" @@ -297,19 +310,19 @@ def _parse_args(argv): formatter_class=argparse.RawDescriptionHelpFormatter, allow_abbrev=False) - parser.add_argument("-d", "--build-dir", default="build", - help="build directory to use") + parser.add_argument("-f", "--elf-file", default=pathlib.Path("build", "zephyr", "zephyr.elf"), + help="ELF file to use") parser.add_argument("-v", "--verbose", action="count", help=("enable verbose output, can be used multiple times " "to increase verbosity level")) - parser.add_argument("-w", "--fail-on-warning", action="store_true", - help="fail on both warnings and errors") parser.add_argument("--always-succeed", action="store_true", help="always exit with a return code of 0, used for testing") parser.add_argument("-o", "--output", help="write the output to a file in addition to stdout") - parser.add_argument("--edt-pickle", default=pathlib.Path("zephyr", "edt.pickle"), - help="path to read the pickled edtlib.EDT object from", + parser.add_argument("-i", "--initlevels", action="store_true", + help="print the initlevel functions instead of checking the device dependencies") + parser.add_argument("--edt-pickle", default=pathlib.Path("edt.pickle"), + help="name of the the pickled edtlib.EDT file", type=pathlib.Path) return parser.parse_args(argv) @@ -323,7 +336,7 @@ def _init_log(verbose, output): log.addHandler(console) if output: - file = logging.FileHandler(output) + file = logging.FileHandler(output, mode="w") file.setFormatter(logging.Formatter("%(levelname)s: %(message)s")) log.addHandler(file) @@ -341,17 +354,17 @@ def main(argv=None): log = _init_log(args.verbose, args.output) - log.info(f"check_init_priorities build_dir: {args.build_dir}") + log.info(f"check_init_priorities: {args.elf_file}") - validator = Validator(args.build_dir, args.edt_pickle, log) - validator.check_edt() + validator = Validator(args.elf_file, args.edt_pickle, log) + if args.initlevels: + validator.print_initlevels() + else: + validator.check_edt() if args.always_succeed: return 0 - if args.fail_on_warning and validator.warnings: - return 1 - if validator.errors: return 1 diff --git a/scripts/build/check_init_priorities_test.py b/scripts/build/check_init_priorities_test.py index 85185ebc258..c7b2aabb25f 100755 --- a/scripts/build/check_init_priorities_test.py +++ b/scripts/build/check_init_priorities_test.py @@ -10,7 +10,7 @@ import pathlib import unittest -from elftools.elf.relocation import RelocationSection +from elftools.elf.relocation import Section from elftools.elf.sections import SymbolTableSection import check_init_priorities @@ -19,191 +19,245 @@ class TestPriority(unittest.TestCase): """Tests for the Priority class.""" def test_priority_parsing(self): - prio1 = check_init_priorities.Priority(".rel.z_init_POST_KERNEL12_0_") - self.assertEqual(prio1._level_priority, (3, 12, 0)) + prio1 = check_init_priorities.Priority("POST_KERNEL", 12) + self.assertEqual(prio1._level_priority, (3, 12)) - prio2 = check_init_priorities.Priority("noisenoise_POST_KERNEL99_00023_") - self.assertEqual(prio2._level_priority, (3, 99, 23)) - - prio3 = check_init_priorities.Priority("_PRE_KERNEL_10_99999_") - self.assertEqual(prio3._level_priority, (1, 0, 99999)) - - prio4 = check_init_priorities.Priority("_PRE_KERNEL_110_00001_") - self.assertEqual(prio4._level_priority, (1, 10, 1)) + prio1 = check_init_priorities.Priority("APPLICATION", 9999) + self.assertEqual(prio1._level_priority, (4, 9999)) with self.assertRaises(ValueError): - check_init_priorities.Priority("i-am-not-a-priority") - check_init_priorities.Priority("_DOESNOTEXIST0_") - check_init_priorities.Priority(".rel.z_init_POST_KERNEL12_blah") - check_init_priorities.Priority(".rel.z_init_2_") - check_init_priorities.Priority(".rel.z_init_POST_KERNEL1_") + check_init_priorities.Priority("i-am-not-a-priority", 0) + check_init_priorities.Priority("_DOESNOTEXIST0_", 0) def test_priority_levels(self): prios = [ - check_init_priorities.Priority(".rel.z_init_EARLY0_0_"), - check_init_priorities.Priority(".rel.z_init_EARLY1_0_"), - check_init_priorities.Priority(".rel.z_init_EARLY11_0_"), - check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_10_0_"), - check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_11_0_"), - check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_111_0_"), - check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_111_1_"), - check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_111_00002_"), - check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_111_00010_"), - check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_20_0_"), - check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_21_0_"), - check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_211_0_"), - check_init_priorities.Priority(".rel.z_init_POST_KERNEL0_0_"), - check_init_priorities.Priority(".rel.z_init_POST_KERNEL1_0_"), - check_init_priorities.Priority(".rel.z_init_POST_KERNEL11_0_"), - check_init_priorities.Priority(".rel.z_init_APPLICATION0_0_"), - check_init_priorities.Priority(".rel.z_init_APPLICATION1_0_"), - check_init_priorities.Priority(".rel.z_init_APPLICATION11_0_"), - check_init_priorities.Priority(".rel.z_init_SMP0_0_"), - check_init_priorities.Priority(".rel.z_init_SMP1_0_"), - check_init_priorities.Priority(".rel.z_init_SMP11_0_"), + check_init_priorities.Priority("EARLY", 0), + check_init_priorities.Priority("EARLY", 1), + check_init_priorities.Priority("PRE_KERNEL_1", 0), + check_init_priorities.Priority("PRE_KERNEL_1", 1), + check_init_priorities.Priority("PRE_KERNEL_2", 0), + check_init_priorities.Priority("PRE_KERNEL_2", 1), + check_init_priorities.Priority("POST_KERNEL", 0), + check_init_priorities.Priority("POST_KERNEL", 1), + check_init_priorities.Priority("APPLICATION", 0), + check_init_priorities.Priority("APPLICATION", 1), + check_init_priorities.Priority("SMP", 0), + check_init_priorities.Priority("SMP", 1), ] self.assertListEqual(prios, sorted(prios)) def test_priority_strings(self): - prio = check_init_priorities.Priority(".rel.z_init_POST_KERNEL12_00023_") - self.assertEqual(str(prio), "POST_KERNEL 12 23") - self.assertEqual(repr(prio), "") + prio = check_init_priorities.Priority("POST_KERNEL", 12) + self.assertEqual(str(prio), "POST_KERNEL+12") + self.assertEqual(repr(prio), "") -class testZephyrObjectFile(unittest.TestCase): - """Tests for the ZephyrObjectFile class.""" +class testZephyrInitLevels(unittest.TestCase): + """Tests for the ZephyrInitLevels class.""" - @mock.patch("check_init_priorities.ZephyrObjectFile.__init__", return_value=None) - def test_load_symbols(self, mock_zofinit): + @mock.patch("check_init_priorities.ZephyrInitLevels.__init__", return_value=None) + def test_load_objects(self, mock_zilinit): mock_elf = mock.Mock() sts = mock.Mock(spec=SymbolTableSection) - rel = mock.Mock(spec=RelocationSection) + rel = mock.Mock(spec=Section) mock_elf.iter_sections.return_value = [sts, rel] s0 = mock.Mock() s0.name = "a" + s0.entry.st_info.type = "STT_OBJECT" + s0.entry.st_size = 4 + s0.entry.st_value = 0xaa + s0.entry.st_shndx = 1 + s1 = mock.Mock() s1.name = None + s2 = mock.Mock() s2.name = "b" + s2.entry.st_info.type = "STT_FUNC" + s2.entry.st_size = 8 + s2.entry.st_value = 0xbb + s2.entry.st_shndx = 2 + sts.iter_symbols.return_value = [s0, s1, s2] - obj = check_init_priorities.ZephyrObjectFile("") + obj = check_init_priorities.ZephyrInitLevels("") obj._elf = mock_elf - obj._load_symbols() + obj._load_objects() - self.assertDictEqual(obj._symbols, {0: "a", 2: "b"}) + self.assertDictEqual(obj._objects, {0xaa: ("a", 4, 1), 0xbb: ("b", 8, 2)}) - @mock.patch("check_init_priorities.Priority") - @mock.patch("check_init_priorities.ZephyrObjectFile._device_ord_from_rel") - @mock.patch("check_init_priorities.ZephyrObjectFile.__init__", return_value=None) - def test_find_defined_devices(self, mock_zofinit, mock_dofr, mock_prio): + @mock.patch("check_init_priorities.ZephyrInitLevels.__init__", return_value=None) + def test_load_level_addr(self, mock_zilinit): mock_elf = mock.Mock() sts = mock.Mock(spec=SymbolTableSection) - rel1 = mock.Mock(spec=RelocationSection) - rel1.name = ".rel.z_init_SOMETHING" - rel2 = mock.Mock(spec=RelocationSection) - rel2.name = ".rel.something_else" - mock_elf.iter_sections.return_value = [sts, rel1, rel2] + rel = mock.Mock(spec=Section) + mock_elf.iter_sections.return_value = [sts, rel] - r0 = mock.Mock() - rel1.iter_relocations.return_value = [r0] + s0 = mock.Mock() + s0.name = "__init_EARLY_start" + s0.entry.st_value = 0x00 + + s1 = mock.Mock() + s1.name = "__init_PRE_KERNEL_1_start" + s1.entry.st_value = 0x11 - mock_dofr.return_value = 123 + s2 = mock.Mock() + s2.name = "__init_PRE_KERNEL_2_start" + s2.entry.st_value = 0x22 - r0_prio = mock.Mock() - mock_prio.return_value = r0_prio + s3 = mock.Mock() + s3.name = "__init_POST_KERNEL_start" + s3.entry.st_value = 0x33 - obj = check_init_priorities.ZephyrObjectFile("") - obj._elf = mock_elf - obj._find_defined_devices() + s4 = mock.Mock() + s4.name = "__init_APPLICATION_start" + s4.entry.st_value = 0x44 + + s5 = mock.Mock() + s5.name = "__init_SMP_start" + s5.entry.st_value = 0x55 - self.assertDictEqual(obj.defined_devices, {123: r0_prio}) - mock_dofr.assert_called_once_with(r0) - mock_prio.assert_called_once_with(rel1.name) + s6 = mock.Mock() + s6.name = "__init_end" + s6.entry.st_value = 0x66 - @mock.patch("check_init_priorities.ZephyrObjectFile.__init__", return_value=None) - def test_device_ord_from_rel(self, mock_zofinit): - obj = check_init_priorities.ZephyrObjectFile("") + sts.iter_symbols.return_value = [s0, s1, s2, s3, s4, s5, s6] - obj._symbols = { - 1: "blah", - 2: "__device_dts_ord_123", + obj = check_init_priorities.ZephyrInitLevels("") + obj._elf = mock_elf + obj._load_level_addr() + + self.assertDictEqual(obj._init_level_addr, { + "EARLY": 0x00, + "PRE_KERNEL_1": 0x11, + "PRE_KERNEL_2": 0x22, + "POST_KERNEL": 0x33, + "APPLICATION": 0x44, + "SMP": 0x55, + }) + self.assertEqual(obj._init_level_end, 0x66) + + @mock.patch("check_init_priorities.ZephyrInitLevels.__init__", return_value=None) + def test_device_ord_from_name(self, mock_zilinit): + obj = check_init_priorities.ZephyrInitLevels("") + + self.assertEqual(obj._device_ord_from_name(None), None) + self.assertEqual(obj._device_ord_from_name("hey, hi!"), None) + self.assertEqual(obj._device_ord_from_name("__device_dts_ord_123"), 123) + + @mock.patch("check_init_priorities.ZephyrInitLevels.__init__", return_value=None) + def test_object_name(self, mock_zilinit): + obj = check_init_priorities.ZephyrInitLevels("") + obj._objects = {0x123: ("name", 4)} + + self.assertEqual(obj._object_name(0), "NULL") + self.assertEqual(obj._object_name(73), "unknown") + self.assertEqual(obj._object_name(0x123), "name") + + @mock.patch("check_init_priorities.ZephyrInitLevels.__init__", return_value=None) + def test_initlevel_pointer_32(self, mock_zilinit): + obj = check_init_priorities.ZephyrInitLevels("") + obj._elf = mock.Mock() + obj._elf.elfclass = 32 + mock_section = mock.Mock() + obj._elf.get_section.return_value = mock_section + mock_section.header.sh_addr = 0x100 + mock_section.data.return_value = (b"\x01\x00\x00\x00" + b"\x02\x00\x00\x00" + b"\x03\x00\x00\x00") + + self.assertEqual(obj._initlevel_pointer(0x100, 0, 0), 1) + self.assertEqual(obj._initlevel_pointer(0x100, 1, 0), 2) + self.assertEqual(obj._initlevel_pointer(0x104, 0, 0), 2) + self.assertEqual(obj._initlevel_pointer(0x104, 1, 0), 3) + + @mock.patch("check_init_priorities.ZephyrInitLevels.__init__", return_value=None) + def test_initlevel_pointer_64(self, mock_zilinit): + obj = check_init_priorities.ZephyrInitLevels("") + obj._elf = mock.Mock() + obj._elf.elfclass = 64 + mock_section = mock.Mock() + obj._elf.get_section.return_value = mock_section + mock_section.header.sh_addr = 0x100 + mock_section.data.return_value = (b"\x01\x00\x00\x00\x00\x00\x00\x00" + b"\x02\x00\x00\x00\x00\x00\x00\x00" + b"\x03\x00\x00\x00\x00\x00\x00\x00") + + self.assertEqual(obj._initlevel_pointer(0x100, 0, 0), 1) + self.assertEqual(obj._initlevel_pointer(0x100, 1, 0), 2) + self.assertEqual(obj._initlevel_pointer(0x108, 0, 0), 2) + self.assertEqual(obj._initlevel_pointer(0x108, 1, 0), 3) + + @mock.patch("check_init_priorities.ZephyrInitLevels._object_name") + @mock.patch("check_init_priorities.ZephyrInitLevels._initlevel_pointer") + @mock.patch("check_init_priorities.ZephyrInitLevels.__init__", return_value=None) + def test_process_initlevels(self, mock_zilinit, mock_ip, mock_on): + obj = check_init_priorities.ZephyrInitLevels("") + obj._init_level_addr = { + "EARLY": 0x00, + "PRE_KERNEL_1": 0x00, + "PRE_KERNEL_2": 0x00, + "POST_KERNEL": 0x08, + "APPLICATION": 0x0c, + "SMP": 0x0c, + } + obj._init_level_end = 0x0c + obj._objects = { + 0x00: ("a", 4, 0), + 0x04: ("b", 4, 0), + 0x08: ("c", 4, 0), } - self.assertEqual(obj._device_ord_from_rel({"r_info_sym": 0}), None) - self.assertEqual(obj._device_ord_from_rel({"r_info_sym": 1}), None) - self.assertEqual(obj._device_ord_from_rel({"r_info_sym": 2}), 123) + mock_ip.side_effect = lambda *args: args + + def mock_obj_name(*args): + if args[0] == (0, 0, 0): + return "i0" + elif args[0] == (0, 1, 0): + return "__device_dts_ord_11" + elif args[0] == (4, 0, 0): + return "i1" + elif args[0] == (4, 1, 0): + return "__device_dts_ord_22" + return f"name_{args[0][0]}_{args[0][1]}" + mock_on.side_effect = mock_obj_name + + obj._process_initlevels() + + self.assertDictEqual(obj.initlevels, { + "EARLY": [], + "PRE_KERNEL_1": [], + "PRE_KERNEL_2": ["a: i0(__device_dts_ord_11)", "b: i1(__device_dts_ord_22)"], + "POST_KERNEL": ["c: name_8_0(name_8_1)"], + "APPLICATION": [], + "SMP": [], + }) + self.assertDictEqual(obj.devices, { + 11: (check_init_priorities.Priority("PRE_KERNEL_2", 0), "i0"), + 22: (check_init_priorities.Priority("PRE_KERNEL_2", 1), "i1"), + }) class testValidator(unittest.TestCase): """Tests for the Validator class.""" - @mock.patch("check_init_priorities.ZephyrObjectFile") - @mock.patch("check_init_priorities.Validator._find_build_objfiles") + @mock.patch("check_init_priorities.ZephyrInitLevels") @mock.patch("pickle.load") - def test_initialize(self, mock_pl, mock_fbo, mock_zof): - mock_fbo.return_value = ["filepath"] - + def test_initialize(self, mock_pl, mock_zil): mock_log = mock.Mock() mock_prio = mock.Mock() mock_obj = mock.Mock() mock_obj.defined_devices = {123: mock_prio} - mock_zof.return_value = mock_obj + mock_zil.return_value = mock_obj with mock.patch("builtins.open", mock.mock_open()) as mock_open: validator = check_init_priorities.Validator("path", "pickle", mock_log) - self.assertListEqual(validator._objs, [mock_obj]) - self.assertDictEqual(validator._dev_priorities, {123: mock_prio}) - mock_fbo.assert_called_once_with("path", is_root=True) - mock_zof.assert_called_once_with("filepath") - mock_open.assert_called_once_with(pathlib.Path("path/pickle"), "rb") - - @mock.patch("pathlib.Path") - @mock.patch("check_init_priorities.Validator.__init__", return_value=None) - def test_find_build_objfiles(self, mock_vinit, mock_path): - mock_log = mock.Mock() - - validator = check_init_priorities.Validator("", "", mock_log) - - mock_file = mock.Mock() - mock_file.is_file.return_value = True - mock_file.is_dir.return_value = False - mock_file.file.name = "filename.c.obj" - - mock_dir = mock.Mock() - mock_dir.is_file.return_value = False - mock_dir.is_dir.return_value = True - mock_dir.resolve.return_value = "subdir" - mock_dir.iterdir.return_value = [] - - mock_nosettingsfile = mock.Mock() - mock_nosettingsfile.exists.return_value = False - - mock_path_root = mock.Mock() - mock_path_root.iterdir.return_value = [mock_file, mock_dir] - - def mock_path_stubs(*args): - if args == ("root",): - return mock_path_root - elif args == ("subdir",): - return mock_dir - elif args == ("subdir", "CMakeCache.txt"): - return mock_nosettingsfile - raise ValueError - mock_path.side_effect = mock_path_stubs - - ret = list(validator._find_build_objfiles("root", is_root=True)) - self.assertListEqual(ret, [mock_file]) - - mock_nosettingsfile.exists.assert_called_once_with() - self.assertListEqual(mock_path.call_args_list, [ - mock.call("root"), - mock.call("subdir", "CMakeCache.txt"), - mock.call("subdir") - ]) + self.assertEqual(validator._obj, mock_obj) + mock_zil.assert_called_once_with("path") + mock_open.assert_called_once_with(pathlib.Path("pickle"), "rb") @mock.patch("check_init_priorities.Validator.__init__", return_value=None) def test_check_dep_same_node(self, mock_vinit): @@ -220,15 +274,16 @@ def test_check_dep_same_node(self, mock_vinit): def test_check_dep_no_prio(self, mock_vinit): validator = check_init_priorities.Validator("", "", None) validator.log = mock.Mock() + validator._obj = mock.Mock() validator._ord2node = {1: mock.Mock(), 2: mock.Mock()} validator._ord2node[1]._binding = None validator._ord2node[2]._binding = None - validator._dev_priorities = {1: 10} + validator._obj.devices = {1: (10, "i1")} validator._check_dep(1, 2) - validator._dev_priorities = {2: 20} + validator._obj.devices = {2: (20, "i2")} validator._check_dep(1, 2) self.assertFalse(validator.log.info.called) @@ -239,34 +294,49 @@ def test_check_dep_no_prio(self, mock_vinit): def test_check(self, mock_vinit): validator = check_init_priorities.Validator("", "", None) validator.log = mock.Mock() - validator.warnings = 0 + validator._obj = mock.Mock() validator.errors = 0 - validator._ord2node = {1: mock.Mock(), 2: mock.Mock(), 3: mock.Mock()} + validator._ord2node = {1: mock.Mock(), 2: mock.Mock()} validator._ord2node[1]._binding = None validator._ord2node[1].path = "/1" validator._ord2node[2]._binding = None validator._ord2node[2].path = "/2" - validator._ord2node[3]._binding = None - validator._ord2node[3].path = "/3" - validator._dev_priorities = {1: 10, 2: 10, 3: 20} + validator._obj.devices = {1: (10, "i1"), 2: (20, "i2")} - validator._check_dep(3, 1) validator._check_dep(2, 1) - validator._check_dep(1, 3) + validator._check_dep(1, 2) - validator.log.info.assert_called_once_with("/3 20 > /1 10") - validator.log.warning.assert_called_once_with("/2 10 == /1 10") - validator.log.error.assert_called_once_with("/1 10 < /3 20") - self.assertEqual(validator.warnings, 1) + validator.log.info.assert_called_once_with("/2 20 > /1 10") + validator.log.error.assert_has_calls([ + mock.call("/1 is initialized before its dependency /2 (10 < 20)") + ]) self.assertEqual(validator.errors, 1) + @mock.patch("check_init_priorities.Validator.__init__", return_value=None) + def test_check_same_prio_assert(self, mock_vinit): + validator = check_init_priorities.Validator("", "", None) + validator.log = mock.Mock() + validator._obj = mock.Mock() + validator.errors = 0 + + validator._ord2node = {1: mock.Mock(), 2: mock.Mock()} + validator._ord2node[1]._binding = None + validator._ord2node[1].path = "/1" + validator._ord2node[2]._binding = None + validator._ord2node[2].path = "/2" + + validator._obj.devices = {1: (10, "i1"), 2: (10, "i2")} + + with self.assertRaises(ValueError): + validator._check_dep(1, 2) + @mock.patch("check_init_priorities.Validator.__init__", return_value=None) def test_check_swapped(self, mock_vinit): validator = check_init_priorities.Validator("", "", None) validator.log = mock.Mock() - validator.warnings = 0 + validator._obj = mock.Mock() validator.errors = 0 save_inverted_priorities = check_init_priorities._INVERTED_PRIORITY_COMPATIBLES @@ -279,15 +349,14 @@ def test_check_swapped(self, mock_vinit): validator._ord2node[3]._binding.compatible = "compat-3" validator._ord2node[3].path = "/3" - validator._dev_priorities = {1: 20, 3: 10} + validator._obj.devices = {1: (20, "i1"), 3: (10, "i3")} validator._check_dep(3, 1) self.assertListEqual(validator.log.info.call_args_list, [ mock.call("Swapped priority: compat-3, compat-1"), - mock.call("/3 20 > /1 10"), + mock.call("/3 20 > /1 10"), ]) - self.assertEqual(validator.warnings, 0) self.assertEqual(validator.errors, 0) check_init_priorities._INVERTED_PRIORITY_COMPATIBLES = save_inverted_priorities @@ -296,7 +365,7 @@ def test_check_swapped(self, mock_vinit): def test_check_ignored(self, mock_vinit): validator = check_init_priorities.Validator("", "", None) validator.log = mock.Mock() - validator.warnings = 0 + validator._obj = mock.Mock() validator.errors = 0 save_ignore_compatibles = check_init_priorities._IGNORE_COMPATIBLES @@ -309,65 +378,45 @@ def test_check_ignored(self, mock_vinit): validator._ord2node[3]._binding.compatible = "compat-3" validator._ord2node[3].path = "/3" - validator._dev_priorities = {1: 20, 3: 10} + validator._obj.devices = {1: 20, 3: 10} validator._check_dep(3, 1) self.assertListEqual(validator.log.info.call_args_list, [ mock.call("Ignoring priority: compat-3"), ]) - self.assertEqual(validator.warnings, 0) self.assertEqual(validator.errors, 0) check_init_priorities._IGNORE_COMPATIBLES = save_ignore_compatibles @mock.patch("check_init_priorities.Validator._check_dep") @mock.patch("check_init_priorities.Validator.__init__", return_value=None) - def test_check_edt_r(self, mock_vinit, mock_cd): - validator = check_init_priorities.Validator("", "", None) - + def test_check_edt(self, mock_vinit, mock_cd): d0 = mock.Mock() d0.dep_ordinal = 1 d1 = mock.Mock() d1.dep_ordinal = 2 + d2 = mock.Mock() + d2.dep_ordinal = 3 - c0 = mock.Mock() - c0.props = {"compatible": "c"} - c1 = mock.Mock() - c1.props = {} - c1._binding.path = "another-binding-path.yaml" - c2 = mock.Mock() - c2.props = {} - c2._binding.path = "binding-path.yaml" - c2._binding.child_binding = None - c2.depends_on = [d1] - - dev = mock.Mock() - dev.depends_on = [d0] - dev._binding.child_binding = "child-binding" - dev._binding.path = "binding-path.yaml" - dev.children.values.return_value = [c0, c1, c2] - - validator._check_edt_r(0, dev) + dev0 = mock.Mock() + dev0.depends_on = [d0] + dev1 = mock.Mock() + dev1.depends_on = [d1] + dev2 = mock.Mock() + dev2.depends_on = [d2] - self.assertListEqual(mock_cd.call_args_list, [ - mock.call(0, 1), - mock.call(0, 2), - ]) - - @mock.patch("check_init_priorities.Validator._check_edt_r") - @mock.patch("check_init_priorities.Validator.__init__", return_value=None) - def test_check_edt(self, mock_vinit, mock_cer): validator = check_init_priorities.Validator("", "", None) - validator._ord2node = {1: mock.Mock(), 2: mock.Mock(), 3: mock.Mock()} - validator._dev_priorities = {1: 10, 2: 10, 3: 20} + validator._ord2node = {1: dev0, 2: dev1, 3: dev2} + validator._obj = mock.Mock() + validator._obj.devices = {1: 10, 2: 10, 3: 20} validator.check_edt() - self.assertListEqual(mock_cer.call_args_list, [ - mock.call(1, validator._ord2node[1]), - mock.call(2, validator._ord2node[2]), - mock.call(3, validator._ord2node[3]), + self.assertListEqual(mock_cd.call_args_list, [ + mock.call(1, 1), + mock.call(2, 2), + mock.call(3, 3), ]) if __name__ == "__main__": diff --git a/scripts/build/file2hex.py b/scripts/build/file2hex.py index 34857d4159b..2bb967cf29d 100755 --- a/scripts/build/file2hex.py +++ b/scripts/build/file2hex.py @@ -26,6 +26,11 @@ def parse_args(): formatter_class=argparse.RawDescriptionHelpFormatter, allow_abbrev=False) parser.add_argument("-f", "--file", required=True, help="Input file") + parser.add_argument("-o", "--offset", type=lambda x: int(x, 0), default=0, + help="Byte offset in the input file") + parser.add_argument("-l", "--length", type=lambda x: int(x, 0), default=-1, + help="""Length in bytes to read from the input file. + Defaults to reading till the end of the input file.""") parser.add_argument("-g", "--gzip", action="store_true", help="Compress the file using gzip before output") parser.add_argument("-t", "--gzip-mtime", type=int, default=0, @@ -53,18 +58,26 @@ def main(): if args.gzip: with io.BytesIO() as content: with open(args.file, 'rb') as fg: + fg.seek(args.offset) with gzip.GzipFile(fileobj=content, mode='w', mtime=args.gzip_mtime, compresslevel=9) as gz_obj: - gz_obj.write(fg.read()) + gz_obj.write(fg.read(args.length)) content.seek(0) for chunk in iter(lambda: content.read(8), b''): make_hex(chunk) else: with open(args.file, "rb") as fp: - for chunk in iter(lambda: fp.read(8), b''): - make_hex(chunk) + fp.seek(args.offset) + if args.length < 0: + for chunk in iter(lambda: fp.read(8), b''): + make_hex(chunk) + else: + remainder = args.length + for chunk in iter(lambda: fp.read(min(8, remainder)), b''): + make_hex(chunk) + remainder = remainder - len(chunk) if __name__ == "__main__": diff --git a/scripts/build/gen_cfb_font_header.py b/scripts/build/gen_cfb_font_header.py index dacb76c4eef..0bba785bfe7 100755 --- a/scripts/build/gen_cfb_font_header.py +++ b/scripts/build/gen_cfb_font_header.py @@ -76,7 +76,13 @@ def extract_font_glyphs(): fw_max = 0 fh_max = 0 for i in range(args.first, args.last + 1): - fw, fh = font.getsize(chr(i)) + # returns (left, top, right, bottom) bounding box + size = font.getbbox(chr(i)) + + # calculate width + height + fw = size[2] - size[0] # right - left + fh = size[3] - size[1] # bottom - top + if fw > fw_max: fw_max = fw if fh > fh_max: @@ -100,7 +106,12 @@ def extract_font_glyphs(): image = Image.new('1', (width, height), 'white') draw = ImageDraw.Draw(image) - fw, fh = draw.textsize(chr(i), font=font) + # returns (left, top, right, bottom) bounding box + size = draw.textbbox((0, 0), chr(i), font=font) + + # calculate width + height + fw = size[2] - size[0] # right - left + fh = size[3] - size[1] # bottom - top xpos = 0 if args.center_x: diff --git a/scripts/build/gen_isr_tables.py b/scripts/build/gen_isr_tables.py index 1b564e17a3c..cd329f85551 100755 --- a/scripts/build/gen_isr_tables.py +++ b/scripts/build/gen_isr_tables.py @@ -42,7 +42,7 @@ def endian_prefix(): else: return "<" -def read_intlist(intlist_path, syms): +def read_intlist(elfobj, syms, snames): """read a binary file containing the contents of the kernel's .intList section. This is an instance of a header created by include/zephyr/linker/intlist.ld: @@ -66,7 +66,7 @@ def read_intlist(intlist_path, syms): const void *param; }; """ - + intList_sect = None intlist = {} prefix = endian_prefix() @@ -77,8 +77,16 @@ def read_intlist(intlist_path, syms): else: intlist_entry_fmt = prefix + "iiII" - with open(intlist_path, "rb") as fp: - intdata = fp.read() + for sname in snames: + intList_sect = elfobj.get_section_by_name(sname) + if intList_sect is not None: + debug("Found intlist section: \"{}\"".format(sname)) + break + + if intList_sect is None: + error("Cannot find the intlist section!") + + intdata = intList_sect.data() header_sz = struct.calcsize(intlist_header_fmt) header = struct.unpack_from(intlist_header_fmt, intdata, 0) @@ -122,8 +130,9 @@ def parse_args(): help="Generate SW ISR table") parser.add_argument("-V", "--vector-table", action="store_true", help="Generate vector table") - parser.add_argument("-i", "--intlist", required=True, - help="Zephyr intlist binary for intList extraction") + parser.add_argument("-i", "--intlist-section", action="append", required=True, + help="The name of the section to search for the interrupt data. " + "This is accumulative argument. The first section found would be used.") args = parser.parse_args() @@ -177,11 +186,37 @@ def write_address_irq_vector_table(fp, vt, nv): typedef void (* ISR)(const void *); """ -def write_source_file(fp, vt, swt, intlist, syms): +def write_shared_table(fp, shared, nv): + fp.write("struct z_shared_isr_table_entry __shared_sw_isr_table" + " z_shared_sw_isr_table[%d] = {\n" % nv) + + for i in range(nv): + client_num = shared[i][1] + client_list = shared[i][0] + + if not client_num: + fp.write("\t{ },\n") + else: + fp.write(f"\t{{ .client_num = {client_num}, .clients = {{ ") + for j in range(0, client_num): + routine = client_list[j][1] + arg = client_list[j][0] + + fp.write(f"{{ .isr = (ISR){ hex(routine) if isinstance(routine, int) else routine }, " + f".arg = (const void *){hex(arg)} }},") + + fp.write(" },\n},\n") + + fp.write("};\n") + +def write_source_file(fp, vt, swt, intlist, syms, shared): fp.write(source_header) nv = intlist["num_vectors"] + if "CONFIG_SHARED_INTERRUPTS" in syms: + write_shared_table(fp, shared, nv) + if vt: if "CONFIG_IRQ_VECTOR_TABLE_JUMP_BY_ADDRESS" in syms: write_address_irq_vector_table(fp, vt, nv) @@ -200,7 +235,11 @@ def write_source_file(fp, vt, swt, intlist, syms): level3_offset = syms.get("CONFIG_3RD_LVL_ISR_TBL_OFFSET") for i in range(nv): - param, func = swt[i] + param = "{0:#x}".format(swt[i][0]) + func = swt[i][1] + + if isinstance (func, str) and "z_shared_isr" in func: + param = "&z_shared_sw_isr_table[{0}]".format(i) if isinstance(func, int): func_as_string = "{0:#x}".format(func) else: @@ -213,7 +252,7 @@ def write_source_file(fp, vt, swt, intlist, syms): fp.write("\t/* Level 3 interrupts start here (offset: {}) */\n". format(level3_offset)) - fp.write("\t{{(const void *){0:#x}, (ISR){1}}},\n".format(param, func_as_string)) + fp.write("\t{{(const void *){0}, (ISR){1}}},\n".format(param, func_as_string)) fp.write("};\n") def get_symbols(obj): @@ -256,6 +295,7 @@ def main(): with open(args.kernel, "rb") as fp: kernel = ELFFile(fp) syms = get_symbols(kernel) + intlist = read_intlist(kernel, syms, args.intlist_section) if "CONFIG_MULTI_LEVEL_INTERRUPTS" in syms: max_irq_per = syms["CONFIG_MAX_IRQ_PER_AGGREGATOR"] @@ -283,7 +323,6 @@ def main(): debug('3rd level offsets: {}'.format(list_3rd_lvl_offsets)) - intlist = read_intlist(args.intlist, syms) nvec = intlist["num_vectors"] offset = intlist["offset"] @@ -291,6 +330,7 @@ def main(): raise ValueError('nvec is too large, check endianness.') swt_spurious_handler = "((uintptr_t)&z_irq_spurious)" + swt_shared_handler = "((uintptr_t)&z_shared_isr)" vt_spurious_handler = "z_irq_spurious" vt_irq_handler = "_isr_wrapper" @@ -308,6 +348,7 @@ def main(): # Default to spurious interrupt handler. Configured interrupts # will replace these entries. swt = [(0, swt_spurious_handler) for i in range(nvec)] + shared = [([], 0) for i in range(nvec)] else: if args.vector_table: vt = [vt_spurious_handler for i in range(nvec)] @@ -369,16 +410,37 @@ def main(): if not 0 <= table_index < len(swt): error("IRQ %d (offset=%d) exceeds the maximum of %d" % (table_index, offset, len(swt) - 1)) - if swt[table_index] != (0, swt_spurious_handler): - error(f"multiple registrations at table_index {table_index} for irq {irq} (0x{irq:x})" - + f"\nExisting handler 0x{swt[table_index][1]:x}, new handler 0x{func:x}" - + "\nHas IRQ_CONNECT or IRQ_DIRECT_CONNECT accidentally been invoked on the same irq multiple times?" - ) - - swt[table_index] = (param, func) + if "CONFIG_SHARED_INTERRUPTS" in syms: + if swt[table_index] != (0, swt_spurious_handler): + # check client limit + if syms["CONFIG_SHARED_IRQ_MAX_NUM_CLIENTS"] == shared[table_index][1]: + error(f"Reached shared interrupt client limit. Maybe increase" + + f" CONFIG_SHARED_IRQ_MAX_NUM_CLIENTS?") + lst = shared[table_index][0] + delta_size = 1 + if not shared[table_index][1]: + lst.append(swt[table_index]) + # note: the argument will be fixed when writing the ISR table + # to isr_table.c + swt[table_index] = (0, swt_shared_handler) + delta_size += 1 + if (param, func) in lst: + error("Attempting to register the same ISR/arg pair twice.") + lst.append((param, func)) + shared[table_index] = (lst, shared[table_index][1] + delta_size) + else: + swt[table_index] = (param, func) + else: + if swt[table_index] != (0, swt_spurious_handler): + error(f"multiple registrations at table_index {table_index} for irq {irq} (0x{irq:x})" + + f"\nExisting handler 0x{swt[table_index][1]:x}, new handler 0x{func:x}" + + "\nHas IRQ_CONNECT or IRQ_DIRECT_CONNECT accidentally been invoked on the same irq multiple times?" + ) + else: + swt[table_index] = (param, func) with open(args.output_source, "w") as fp: - write_source_file(fp, vt, swt, intlist, syms) + write_source_file(fp, vt, swt, intlist, syms, shared) if __name__ == "__main__": main() diff --git a/scripts/build/gen_kobject_list.py b/scripts/build/gen_kobject_list.py index 64524c67499..6e41adb797d 100755 --- a/scripts/build/gen_kobject_list.py +++ b/scripts/build/gen_kobject_list.py @@ -110,8 +110,8 @@ ("k_event", ("CONFIG_EVENTS", False, True)), ("ztest_suite_node", ("CONFIG_ZTEST", True, False)), ("ztest_suite_stats", ("CONFIG_ZTEST", True, False)), - ("ztest_unit_test", ("CONFIG_ZTEST_NEW_API", True, False)), - ("ztest_test_rule", ("CONFIG_ZTEST_NEW_API", True, False)), + ("ztest_unit_test", ("CONFIG_ZTEST", True, False)), + ("ztest_test_rule", ("CONFIG_ZTEST", True, False)), ("rtio", ("CONFIG_RTIO", False, False)), ("rtio_iodev", ("CONFIG_RTIO", False, False)), ("sensor_decoder_api", ("CONFIG_SENSOR_ASYNC_API", True, False)) @@ -724,10 +724,10 @@ def get_symbols(elf): %{ #include #include -#include +#include #include %} -struct z_object; +struct k_object; """ # Different versions of gperf have different prototypes for the lookup @@ -735,7 +735,7 @@ def get_symbols(elf): # turned into a string, we told gperf to expect binary strings that are not # NULL-terminated. footer = """%% -struct z_object *z_object_gperf_find(const void *obj) +struct k_object *z_object_gperf_find(const void *obj) { return z_object_lookup((const char *)obj, sizeof(void *)); } @@ -752,10 +752,10 @@ def get_symbols(elf): } #ifndef CONFIG_DYNAMIC_OBJECTS -struct z_object *z_object_find(const void *obj) +struct k_object *k_object_find(const void *obj) ALIAS_OF(z_object_gperf_find); -void z_object_wordlist_foreach(_wordlist_cb_func_t func, void *context) +void k_object_wordlist_foreach(_wordlist_cb_func_t func, void *context) ALIAS_OF(z_object_gperf_wordlist_foreach); #endif """ @@ -885,7 +885,7 @@ def write_gperf_table(fp, syms, objs, little_endian, static_begin, static_end): driver_macro_tpl = """ -#define Z_SYSCALL_DRIVER_%(driver_upper)s(ptr, op) Z_SYSCALL_DRIVER_GEN(ptr, op, %(driver_lower)s, %(driver_upper)s) +#define K_SYSCALL_DRIVER_%(driver_upper)s(ptr, op) K_SYSCALL_DRIVER_GEN(ptr, op, %(driver_lower)s, %(driver_upper)s) """ @@ -893,9 +893,9 @@ def write_validation_output(fp): fp.write("#ifndef DRIVER_VALIDATION_GEN_H\n") fp.write("#define DRIVER_VALIDATION_GEN_H\n") - fp.write("""#define Z_SYSCALL_DRIVER_GEN(ptr, op, driver_lower_case, driver_upper_case) \\ - (Z_SYSCALL_OBJ(ptr, K_OBJ_DRIVER_##driver_upper_case) || \\ - Z_SYSCALL_DRIVER_OP(ptr, driver_lower_case##_driver_api, op)) + fp.write("""#define K_SYSCALL_DRIVER_GEN(ptr, op, driver_lower_case, driver_upper_case) \\ + (K_SYSCALL_OBJ(ptr, K_OBJ_DRIVER_##driver_upper_case) || \\ + K_SYSCALL_DRIVER_OP(ptr, driver_lower_case##_driver_api, op)) """) for subsystem in subsystems: diff --git a/scripts/build/gen_syscalls.py b/scripts/build/gen_syscalls.py index 9ee4e323994..68d0f15f48b 100755 --- a/scripts/build/gen_syscalls.py +++ b/scripts/build/gen_syscalls.py @@ -322,7 +322,7 @@ def marshall_defs(func_name, func_type, args): mrsh += "\t(void) arg%d;\t/* unused */\n" % unused_arg if nmrsh > 6: - mrsh += ("\tZ_OOPS(Z_SYSCALL_MEMORY_READ(more, " + mrsh += ("\tK_OOPS(K_SYSCALL_MEMORY_READ(more, " + str(nmrsh - 5) + " * sizeof(uintptr_t)));\n") argnum = 0 @@ -349,7 +349,7 @@ def marshall_defs(func_name, func_type, args): if need_split(func_type): ptr = "((uint64_t *)%s)" % mrsh_rval(nmrsh - 1, nmrsh) - mrsh += "\t" + "Z_OOPS(Z_SYSCALL_MEMORY_WRITE(%s, 8));\n" % ptr + mrsh += "\t" + "K_OOPS(K_SYSCALL_MEMORY_WRITE(%s, 8));\n" % ptr mrsh += "\t" + "*%s = ret;\n" % ptr mrsh += "\t" + "_current->syscall_frame = NULL;\n" mrsh += "\t" + "return 0;\n" diff --git a/scripts/build/process_gperf.py b/scripts/build/process_gperf.py index 002cd9cc1e6..95bbd244dc7 100755 --- a/scripts/build/process_gperf.py +++ b/scripts/build/process_gperf.py @@ -83,7 +83,7 @@ def process_line(line, fp): return # Set the lookup function to static inline so it gets rolled into - # z_object_find(), nothing else will use it + # k_object_find(), nothing else will use it if re.search(args.pattern + " [*]$", line): fp.write("static inline " + line) return diff --git a/scripts/ci/check_compliance.py b/scripts/ci/check_compliance.py index 07d7431dd65..d8b147f8ab0 100755 --- a/scripts/ci/check_compliance.py +++ b/scripts/ci/check_compliance.py @@ -23,6 +23,9 @@ from junitparser import TestCase, TestSuite, JUnitXml, Skipped, Error, Failure import magic +from west.manifest import Manifest +from west.manifest import ManifestProject + sys.path.insert(0, str(Path(__file__).resolve().parents[1])) from get_maintainer import Maintainers, MaintainersError @@ -635,6 +638,7 @@ def check_no_undef_outside_kconfig(self, kconf): # visible to compliance. "BOOT_ENCRYPTION_KEY_FILE", # Used in sysbuild "BOOT_ENCRYPT_IMAGE", # Used in sysbuild + "BINDESC_", # Used in documentation as a prefix "BOOT_UPGRADE_ONLY", # Used in example adjusting MCUboot config, but # symbol is defined in MCUboot itself. "BOOT_SERIAL_BOOT_MODE", # Used in (sysbuild-based) test/ @@ -642,16 +646,21 @@ def check_no_undef_outside_kconfig(self, kconf): "BOOT_SERIAL_CDC_ACM", # Used in (sysbuild-based) test "BOOT_SERIAL_ENTRANCE_GPIO", # Used in (sysbuild-based) test "BOOT_SERIAL_IMG_GRP_HASH", # Used in documentation - "BOOT_SIGNATURE_KEY_FILE", # MCUboot setting used by sysbuild + "BOOT_SHARE_DATA", # Used in Kconfig text + "BOOT_SHARE_DATA_BOOTINFO", # Used in (sysbuild-based) test + "BOOT_SHARE_BACKEND_RETENTION", # Used in Kconfig text + "BOOT_SIGNATURE_KEY_FILE", # MCUboot setting used by sysbuild "BOOT_SIGNATURE_TYPE_ECDSA_P256", # MCUboot setting used by sysbuild - "BOOT_SIGNATURE_TYPE_ED25519", # MCUboot setting used by sysbuild - "BOOT_SIGNATURE_TYPE_NONE", # MCUboot setting used by sysbuild - "BOOT_SIGNATURE_TYPE_RSA", # MCUboot setting used by sysbuild + "BOOT_SIGNATURE_TYPE_ED25519", # MCUboot setting used by sysbuild + "BOOT_SIGNATURE_TYPE_NONE", # MCUboot setting used by sysbuild + "BOOT_SIGNATURE_TYPE_RSA", # MCUboot setting used by sysbuild "BOOT_VALIDATE_SLOT0", # Used in (sysbuild-based) test "BOOT_WATCHDOG_FEED", # Used in (sysbuild-based) test "BTTESTER_LOG_LEVEL", # Used in tests/bluetooth/tester "BTTESTER_LOG_LEVEL_DBG", # Used in tests/bluetooth/tester "CDC_ACM_PORT_NAME_", + "CHRE", # Optional module + "CHRE_LOG_LEVEL_DBG", # Optional module "CLOCK_STM32_SYSCLK_SRC_", "CMU", "COMPILER_RT_RTLIB", @@ -698,6 +707,7 @@ def check_no_undef_outside_kconfig(self, kconf): "PEDO_THS_MIN", "REG1", "REG2", + "RIMAGE_SIGNING_SCHEMA", # Optional module "SAMPLE_MODULE_LOG_LEVEL", # Used as an example in samples/subsys/logging "SAMPLE_MODULE_LOG_LEVEL_DBG", # Used in tests/subsys/logging/log_api "LOG_BACKEND_MOCK_OUTPUT_DEFAULT", #Referenced in tests/subsys/logging/log_syst @@ -1107,6 +1117,40 @@ def run(self): except MaintainersError as ex: self.failure(f"Error parsing {file}: {ex}") +class ModulesMaintainers(ComplianceTest): + """ + Check that all modules have a MAINTAINERS entry. + """ + name = "ModulesMaintainers" + doc = "Check that all modules have a MAINTAINERS entry." + path_hint = "" + + def run(self): + MAINTAINERS_FILES = ["MAINTAINERS.yml", "MAINTAINERS.yaml"] + + manifest = Manifest.from_file() + + maintainers_file = None + for file in MAINTAINERS_FILES: + if os.path.exists(file): + maintainers_file = file + break + if not maintainers_file: + return + + maintainers = Maintainers(maintainers_file) + + for project in manifest.get_projects([]): + if not manifest.is_active(project): + continue + + if isinstance(project, ManifestProject): + continue + + area = f"West project: {project.name}" + if area not in maintainers.areas: + self.failure(f"Missing {maintainers_file} entry for: \"{area}\"") + class YAMLLint(ComplianceTest): """ @@ -1138,6 +1182,64 @@ def run(self): p.line, col=p.column, desc=p.desc) +class KeepSorted(ComplianceTest): + """ + Check for blocks of code or config that should be kept sorted. + """ + name = "KeepSorted" + doc = "Check for blocks of code or config that should be kept sorted." + path_hint = "" + + MARKER = "zephyr-keep-sorted" + + def check_file(self, file, fp): + mime_type = magic.from_file(file, mime=True) + + if not mime_type.startswith("text/"): + return + + lines = [] + in_block = False + + start_marker = f"{self.MARKER}-start" + stop_marker = f"{self.MARKER}-stop" + + for line_num, line in enumerate(fp.readlines(), start=1): + if start_marker in line: + if in_block: + desc = f"nested {start_marker}" + self.fmtd_failure("error", "KeepSorted", file, line_num, + desc=desc) + in_block = True + lines = [] + elif stop_marker in line: + if not in_block: + desc = f"{stop_marker} without {start_marker}" + self.fmtd_failure("error", "KeepSorted", file, line_num, + desc=desc) + in_block = False + + if lines != sorted(lines): + desc = f"sorted block is not sorted" + self.fmtd_failure("error", "KeepSorted", file, line_num, + desc=desc) + elif not line.strip() or line.startswith("#"): + # Ignore comments and blank lines + continue + elif in_block: + if line.startswith((" ", "\t")): + lines[-1] += line + else: + lines.append(line) + + if in_block: + self.failure(f"unterminated {start_marker} in {file}") + + def run(self): + for file in get_files(filter="d"): + with open(file, "r") as fp: + self.check_file(file, fp) + def init_logs(cli_arg): # Initializes logging diff --git a/scripts/ci/tags.yaml b/scripts/ci/tags.yaml index 32088673057..f66745fb208 100644 --- a/scripts/ci/tags.yaml +++ b/scripts/ci/tags.yaml @@ -50,6 +50,11 @@ net: files: - subsys/net/ - include/zephyr/net/ + - drivers/wifi/ + - drivers/net/ + - drivers/ethernet/ + - drivers/ieee802154/ + - drivers/ptp_clock/ test_framework: files: @@ -67,7 +72,7 @@ cmsis_dsp: mcumgr: files: - - subsys/mcumgr/ + - subsys/mgmt/mcumgr/ - tests/subsys/mgmt/mcumgr/ - samples/subsys/mgmt/mcumgr/ - include/zephyr/mgmt/mcumgr/ diff --git a/scripts/ci/test_plan.py b/scripts/ci/test_plan.py index 21cac8e4914..a2ba406d8ce 100755 --- a/scripts/ci/test_plan.py +++ b/scripts/ci/test_plan.py @@ -181,7 +181,7 @@ def find_modules(self): def find_archs(self): - # we match both arch//* and include/arch/ and skip common. + # we match both arch//* and include/zephyr/arch/ and skip common. # Some architectures like riscv require special handling, i.e. riscv # directory covers 2 architectures known to twister: riscv32 and riscv64. archs = set() @@ -189,7 +189,7 @@ def find_archs(self): for f in self.modified_files: p = re.match(r"^arch\/([^/]+)\/", f) if not p: - p = re.match(r"^include\/arch\/([^/]+)\/", f) + p = re.match(r"^include\/zephyr\/arch\/([^/]+)\/", f) if p: if p.group(1) != 'common': if p.group(1) == 'riscv': @@ -212,7 +212,7 @@ def find_archs(self): self.get_plan(_options, True) else: - self.get_plan(_options, False) + self.get_plan(_options, True) def find_boards(self): boards = set() diff --git a/scripts/ci/twister_ignore.txt b/scripts/ci/twister_ignore.txt index fb267ed81f7..acdad51eb46 100644 --- a/scripts/ci/twister_ignore.txt +++ b/scripts/ci/twister_ignore.txt @@ -33,3 +33,4 @@ scripts/checkpatch/* scripts/checkpatch.pl scripts/ci/pylintrc scripts/footprint/* +scripts/set_assignees.py diff --git a/scripts/coredump/gdbstubs/arch/xtensa.py b/scripts/coredump/gdbstubs/arch/xtensa.py index dfc2f48453e..fbe572ac16b 100644 --- a/scripts/coredump/gdbstubs/arch/xtensa.py +++ b/scripts/coredump/gdbstubs/arch/xtensa.py @@ -25,6 +25,7 @@ class XtensaSoc(Enum): INTEL_ADSP_CAVS = 3 ESP32S2 = 4 ESP32S3 = 5 + DC233C = 6 # The previous version of this script didn't need to know @@ -68,6 +69,8 @@ def get_gdb_reg_definition(soc, toolchain): return GdbRegDef_ESP32S2 elif soc == XtensaSoc.ESP32S3: return GdbRegDef_ESP32S3 + elif soc == XtensaSoc.DC233C: + return GdbRegDef_DC233C else: raise NotImplementedError @@ -476,3 +479,38 @@ class RegNum(Enum): LCOUNT = 514 WINDOWBASE = 584 WINDOWSTART = 585 + +# sdk-ng -> overlays/xtensa_dc233c/gdb/gdb/xtensa-config.c +class GdbRegDef_DC233C: + ARCH_DATA_BLK_STRUCT_REGS = ' None: # Allow a few special properties to not be declared in the binding if prop_name.endswith("-controller") or \ prop_name.startswith("#") or \ - prop_name.startswith("pinctrl-") or \ prop_name in { "compatible", "status", "ranges", "phandle", "interrupt-parent", "interrupts-extended", "device_type"}: @@ -2053,6 +2052,56 @@ def scc_order(self) -> List[List[Node]]: except Exception as e: raise EDTError(e) + def _process_properties_r(self, root_node, props_node): + """ + Process props_node properties for dependencies, and add those as + dependencies of root_node. Then walk through all the props_node + children and do the same recursively, maintaining the same root_node. + + This ensures that on a node with child nodes, the parent node includes + the dependencies of all the child nodes as well as its own. + """ + # A Node depends on any Nodes present in 'phandle', + # 'phandles', or 'phandle-array' property values. + for prop in props_node.props.values(): + if prop.type == 'phandle': + self._graph.add_edge(root_node, prop.val) + elif prop.type == 'phandles': + if TYPE_CHECKING: + assert isinstance(prop.val, list) + for phandle_node in prop.val: + self._graph.add_edge(root_node, phandle_node) + elif prop.type == 'phandle-array': + if TYPE_CHECKING: + assert isinstance(prop.val, list) + for cd in prop.val: + if cd is None: + continue + if TYPE_CHECKING: + assert isinstance(cd, ControllerAndData) + self._graph.add_edge(root_node, cd.controller) + + # A Node depends on whatever supports the interrupts it + # generates. + for intr in props_node.interrupts: + self._graph.add_edge(root_node, intr.controller) + + # If the binding defines child bindings, link the child properties to + # the root_node as well. + if props_node._binding and props_node._binding.child_binding: + for child in props_node.children.values(): + if "compatible" in child.props: + # Not a child node, normal node on a different binding. + continue + self._process_properties_r(root_node, child) + + def _process_properties(self, node): + """ + Add node dependencies based on own as well as child node properties, + start from the node itself. + """ + self._process_properties_r(node, node) + def _init_graph(self) -> None: # Constructs a graph of dependencies between Node instances, # which is usable for computing a partial order over the dependencies. @@ -2062,34 +2111,15 @@ def _init_graph(self) -> None: # first time the scc_order property is read. for node in self.nodes: + # Always insert root node + if not node.parent: + self._graph.add_node(node) + # A Node always depends on its parent. for child in node.children.values(): self._graph.add_edge(child, node) - # A Node depends on any Nodes present in 'phandle', - # 'phandles', or 'phandle-array' property values. - for prop in node.props.values(): - if prop.type == 'phandle': - self._graph.add_edge(node, prop.val) - elif prop.type == 'phandles': - if TYPE_CHECKING: - assert isinstance(prop.val, list) - for phandle_node in prop.val: - self._graph.add_edge(node, phandle_node) - elif prop.type == 'phandle-array': - if TYPE_CHECKING: - assert isinstance(prop.val, list) - for cd in prop.val: - if cd is None: - continue - if TYPE_CHECKING: - assert isinstance(cd, ControllerAndData) - self._graph.add_edge(node, cd.controller) - - # A Node depends on whatever supports the interrupts it - # generates. - for intr in node.interrupts: - self._graph.add_edge(node, intr.controller) + self._process_properties(node) def _init_compat2binding(self) -> None: # Creates self._compat2binding, a dictionary that maps diff --git a/scripts/dts/python-devicetree/src/devicetree/grutils.py b/scripts/dts/python-devicetree/src/devicetree/grutils.py index c3ce825b202..452ee4aaaae 100644 --- a/scripts/dts/python-devicetree/src/devicetree/grutils.py +++ b/scripts/dts/python-devicetree/src/devicetree/grutils.py @@ -26,6 +26,12 @@ def __init__(self, root=None): self.__reverse_map = collections.defaultdict(set) self.__nodes = set() + def add_node(self, node): + """ + Add a node without any target to the graph. + """ + self.__nodes.add(node) + def add_edge(self, source, target): """ Add a directed edge from the C{source} to the C{target}. diff --git a/scripts/dts/python-devicetree/tests/test-bindings/child-binding.yaml b/scripts/dts/python-devicetree/tests/test-bindings/child-binding.yaml index e0af091b10e..7b1334954ee 100644 --- a/scripts/dts/python-devicetree/tests/test-bindings/child-binding.yaml +++ b/scripts/dts/python-devicetree/tests/test-bindings/child-binding.yaml @@ -10,6 +10,8 @@ child-binding: child-prop: type: int required: true + child-ref: + type: phandle child-binding: description: grandchild node @@ -17,3 +19,5 @@ child-binding: grandchild-prop: type: int required: true + grandchild-ref: + type: phandle diff --git a/scripts/dts/python-devicetree/tests/test.dts b/scripts/dts/python-devicetree/tests/test.dts index 35f0f253ce7..213d5d45dfe 100644 --- a/scripts/dts/python-devicetree/tests/test.dts +++ b/scripts/dts/python-devicetree/tests/test.dts @@ -470,16 +470,21 @@ // 'child-binding:') // + child-binding-dep { + }; + child-binding { compatible = "top-binding"; child-1 { child-prop = <1>; grandchild { grandchild-prop = <2>; + grandchild-ref = < &{/child-binding-dep} >; }; }; child-2 { child-prop = <3>; + child-ref = < &{/child-binding-dep} >; }; }; diff --git a/scripts/dts/python-devicetree/tests/test_edtlib.py b/scripts/dts/python-devicetree/tests/test_edtlib.py index 9983e1caf01..ca97fbcb9c2 100644 --- a/scripts/dts/python-devicetree/tests/test_edtlib.py +++ b/scripts/dts/python-devicetree/tests/test_edtlib.py @@ -627,6 +627,20 @@ def test_dependencies(): assert edt.get_node("/") in edt.get_node("/in-dir-1").depends_on assert edt.get_node("/in-dir-1") in edt.get_node("/").required_by +def test_child_dependencies(): + '''Test dependencies relashionship with child nodes propagated to parent''' + with from_here(): + edt = edtlib.EDT("test.dts", ["test-bindings"]) + + dep_node = edt.get_node("/child-binding-dep") + + assert dep_node in edt.get_node("/child-binding").depends_on + assert dep_node in edt.get_node("/child-binding/child-1/grandchild").depends_on + assert dep_node in edt.get_node("/child-binding/child-2").depends_on + assert edt.get_node("/child-binding") in dep_node.required_by + assert edt.get_node("/child-binding/child-1/grandchild") in dep_node.required_by + assert edt.get_node("/child-binding/child-2") in dep_node.required_by + def test_slice_errs(tmp_path): '''Test error messages from the internal _slice() helper''' diff --git a/scripts/footprint/plan.txt b/scripts/footprint/plan.txt index a734da017e8..948a430c62e 100644 --- a/scripts/footprint/plan.txt +++ b/scripts/footprint/plan.txt @@ -25,6 +25,6 @@ bt_tmap_central,default,nrf5340dk_nrf5340_cpuapp,samples/bluetooth/tmap_central, bt_tmap_peripheral,default,nrf5340dk_nrf5340_cpuapp,samples/bluetooth/tmap_peripheral, bt_tmap_bms,default,nrf5340dk_nrf5340_cpuapp,samples/bluetooth/tmap_bms, bt_tmap_bmr,default,nrf5340dk_nrf5340_cpuapp,samples/bluetooth/tmap_bmr, -bt_hci_rpmsg,default,nrf5340dk_nrf5340_cpunet,samples/bluetooth/hci_rpmsg, -bt_hci_rpmsg,iso-broadcast,nrf5340dk_nrf5340_cpunet,samples/bluetooth/hci_rpmsg,-DCONF_FILE=nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf -bt_hci_rpmsg,iso-receive,nrf5340dk_nrf5340_cpunet,samples/bluetooth/hci_rpmsg,-DCONF_FILE=nrf5340_cpunet_iso_receive-bt_ll_sw_split.conf +bt_hci_ipc,default,nrf5340dk_nrf5340_cpunet,samples/bluetooth/hci_ipc, +bt_hci_ipc,iso-broadcast,nrf5340dk_nrf5340_cpunet,samples/bluetooth/hci_ipc,-DCONF_FILE=nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf +bt_hci_ipc,iso-receive,nrf5340dk_nrf5340_cpunet,samples/bluetooth/hci_ipc,-DCONF_FILE=nrf5340_cpunet_iso_receive-bt_ll_sw_split.conf diff --git a/scripts/gitlint/zephyr_commit_rules.py b/scripts/gitlint/zephyr_commit_rules.py index 8f9cce21b1d..ea31c6737f3 100644 --- a/scripts/gitlint/zephyr_commit_rules.py +++ b/scripts/gitlint/zephyr_commit_rules.py @@ -24,8 +24,8 @@ class BodyMinLineCount(CommitRule): # A rule MUST have an *unique* id, we recommend starting with UC (for User-defined Commit-rule). id = "UC6" - # A rule MAY have an option_spec if its behavior should be configurable. - options_spec = [IntOption('min-line-count', 2, "Minimum body line count excluding Signed-off-by")] + # A rule MAY have an options_spec if its behavior should be configurable. + options_spec = [IntOption('min-line-count', 1, "Minimum body line count excluding Signed-off-by")] def validate(self, commit): filtered = [x for x in commit.message.body if not x.lower().startswith("signed-off-by") and x != ''] @@ -42,8 +42,8 @@ class BodyMaxLineCount(CommitRule): # A rule MUST have an *unique* id, we recommend starting with UC (for User-defined Commit-rule). id = "UC1" - # A rule MAY have an option_spec if its behavior should be configurable. - options_spec = [IntOption('max-line-count', 3, "Maximum body line count")] + # A rule MAY have an options_spec if its behavior should be configurable. + options_spec = [IntOption('max-line-count', 200, "Maximum body line count")] def validate(self, commit): line_count = len(commit.message.body) @@ -78,7 +78,7 @@ class TitleMaxLengthRevert(LineRule): name = "title-max-length-no-revert" id = "UC5" target = CommitMessageTitle - options_spec = [IntOption('line-length', 72, "Max line length")] + options_spec = [IntOption('line-length', 75, "Max line length")] violation_message = "Commit title exceeds max length ({0}>{1})" def validate(self, line, _commit): @@ -103,13 +103,13 @@ class MaxLineLengthExceptions(LineRule): name = "max-line-length-with-exceptions" id = "UC4" target = CommitMessageBody - options_spec = [IntOption('line-length', 80, "Max line length")] + options_spec = [IntOption('line-length', 75, "Max line length")] violation_message = "Commit message body line exceeds max length ({0}>{1})" def validate(self, line, _commit): max_length = self.options['line-length'].value urls = re.findall(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', line) - if line.startswith('Signed-off-by'): + if line.lower().startswith('signed-off-by') or line.lower().startswith('co-authored-by'): return if urls: diff --git a/scripts/kconfig/hardened.csv b/scripts/kconfig/hardened.csv index 6a2937df65c..6cc978f7e56 100644 --- a/scripts/kconfig/hardened.csv +++ b/scripts/kconfig/hardened.csv @@ -101,7 +101,6 @@ NET_CONNECTION_MANAGER,n,experimental NET_GPTP,n,experimental NET_IPV4_AUTO,n,experimental NET_L2_IEEE802154_SECURITY,n,experimental -NET_L2_PPP,n,experimental NET_PROMISCUOUS_MODE,n,experimental NET_SOCKETS_CAN,n,experimental NET_SOCKETS_ENABLE_DTLS,n,experimental diff --git a/scripts/kconfig/kconfig.py b/scripts/kconfig/kconfig.py index db2e6da8c44..c0de8245cab 100755 --- a/scripts/kconfig/kconfig.py +++ b/scripts/kconfig/kconfig.py @@ -78,10 +78,10 @@ def main(): check_assigned_sym_values(kconf) check_assigned_choice_values(kconf) - if kconf.syms['WARN_DEPRECATED'].tri_value == 2: + if kconf.syms.get('WARN_DEPRECATED', kconf.y).tri_value == 2: check_deprecated(kconf) - if kconf.syms['WARN_EXPERIMENTAL'].tri_value == 2: + if kconf.syms.get('WARN_EXPERIMENTAL', kconf.y).tri_value == 2: check_experimental(kconf) # Hack: Force all symbols to be evaluated, to catch warnings generated @@ -237,8 +237,8 @@ def check_assigned_choice_values(kconf): def check_deprecated(kconf): - deprecated = kconf.syms['DEPRECATED'] - dep_expr = deprecated.rev_dep + deprecated = kconf.syms.get('DEPRECATED') + dep_expr = kconf.n if deprecated is None else deprecated.rev_dep if dep_expr is not kconf.n: selectors = [s for s in split_expr(dep_expr, OR) if expr_value(s) == 2] @@ -248,8 +248,8 @@ def check_deprecated(kconf): def check_experimental(kconf): - experimental = kconf.syms['EXPERIMENTAL'] - dep_expr = experimental.rev_dep + experimental = kconf.syms.get('EXPERIMENTAL') + dep_expr = kconf.n if experimental is None else experimental.rev_dep if dep_expr is not kconf.n: selectors = [s for s in split_expr(dep_expr, OR) if expr_value(s) == 2] diff --git a/scripts/kconfig/kconfiglib.py b/scripts/kconfig/kconfiglib.py index 75ff3c1ee9a..bd541d07b42 100644 --- a/scripts/kconfig/kconfiglib.py +++ b/scripts/kconfig/kconfiglib.py @@ -1096,6 +1096,8 @@ def _init(self, filename, warn, warn_to_stderr, encoding): # Do various menu tree post-processing self._finalize_node(self.top_node, self.y) + for s in self.syms.values(): + self._finalize_sym(s) self.unique_defined_syms = _ordered_unique(self.defined_syms) self.unique_choices = _ordered_unique(self.choices) @@ -2305,6 +2307,7 @@ def _lookup_sym(self, name): sym.kconfig = self sym.name = name sym.is_constant = False + sym.configdefaults = [] sym.rev_dep = sym.weak_rev_dep = sym.direct_dep = self.n if self._parsing_kconfigs: @@ -2324,6 +2327,7 @@ def _lookup_const_sym(self, name): sym.kconfig = self sym.name = name sym.is_constant = True + sym.configdefaults = [] sym.rev_dep = sym.weak_rev_dep = sym.direct_dep = self.n if self._parsing_kconfigs: @@ -2913,7 +2917,7 @@ def _parse_block(self, end_token, parent, prev): while self._next_line(): t0 = self._tokens[0] - if t0 is _T_CONFIG or t0 is _T_MENUCONFIG: + if t0 in [_T_CONFIG, _T_MENUCONFIG, _T_CONFIGDEFAULT]: # The tokenizer allocates Symbol objects for us sym = self._tokens[1] @@ -2928,7 +2932,8 @@ def _parse_block(self, end_token, parent, prev): node = MenuNode() node.kconfig = self node.item = sym - node.is_menuconfig = (t0 is _T_MENUCONFIG) + node.is_menuconfig = t0 is _T_MENUCONFIG + node.is_configdefault = t0 is _T_CONFIGDEFAULT node.prompt = node.help = node.list = None node.parent = parent node.filename = self.filename @@ -2939,6 +2944,14 @@ def _parse_block(self, end_token, parent, prev): self._parse_props(node) + if node.is_configdefault: + if (node.prompt or + node.dep != self.y or + len(node.ranges) > 0 or + len(node.selects) > 0 or + len(node.implies) > 0): + self._parse_error("configdefault can only contain `default`") + if node.is_menuconfig and not node.prompt: self._warn("the menuconfig symbol {} has no prompt" .format(sym.name_and_loc)) @@ -3551,6 +3564,23 @@ def _invalidate_all(self): # Post-parsing menu tree processing, including dependency propagation and # implicit submenu creation # + def _finalize_sym(self, sym): + # Finalizes symbol definitions + # + # - Applies configdefault node defaults to final symbols + # + # sym: + # The symbol to finalize. + + inserted = 0 + for (idx, defaults) in sym.configdefaults: + for d in defaults: + # Add the defaults to the node, with the requirement that + # direct dependencies are respected. The original order + # of the default statements between nodes is preserved. + default = (d[0], self._make_and(sym.direct_dep, d[1])) + sym.defaults.insert(inserted + idx, default) + inserted += 1 def _finalize_node(self, node, visible_if): # Finalizes a menu node and its children: @@ -3697,6 +3727,14 @@ def _add_props_to_sym(self, node): sym = node.item + if node.is_configdefault: + # Store any defaults for later application after the complete tree + # is known. The current length of of the default array is stored so + # the configdefaults can be inserted in the order they originally + # appeared. + sym.configdefaults.append((len(sym.defaults), node.defaults)) + return + # See the Symbol class docstring sym.direct_dep = self._make_or(sym.direct_dep, node.dep) @@ -4249,6 +4287,7 @@ class Symbol(object): "_write_to_conf", "choice", "defaults", + "configdefaults", "direct_dep", "env_var", "implies", @@ -4307,7 +4346,7 @@ def str_value(self): # function call (property magic) vis = self.visibility - self._write_to_conf = (vis != 0) + self._write_to_conf = vis != 0 if self.orig_type in _INT_HEX: # The C implementation checks the user value against the range in a @@ -4445,7 +4484,7 @@ def tri_value(self): # Warning: See Symbol._rec_invalidate(), and note that this is a hidden # function call (property magic) vis = self.visibility - self._write_to_conf = (vis != 0) + self._write_to_conf = vis != 0 val = 0 @@ -5613,6 +5652,7 @@ class MenuNode(object): "help", "include_path", "is_menuconfig", + "is_configdefault", "item", "kconfig", "linenr", @@ -5814,8 +5854,13 @@ def indent_add_cond(s, cond): sc = self.item if sc.__class__ is Symbol: - lines = [("menuconfig " if self.is_menuconfig else "config ") - + sc.name] + if self.is_menuconfig: + t = "menuconfig " + elif self.is_configdefault: + t = "configdefault " + else: + t = "config " + lines = [t + sc.name] else: lines = ["choice " + sc.name if sc.name else "choice"] @@ -6860,6 +6905,7 @@ def _shell_fn(kconf, _, command): _T_CLOSE_PAREN, _T_COMMENT, _T_CONFIG, + _T_CONFIGDEFAULT, _T_DEFAULT, _T_DEFCONFIG_LIST, _T_DEF_BOOL, @@ -6903,7 +6949,7 @@ def _shell_fn(kconf, _, command): _T_TRISTATE, _T_UNEQUAL, _T_VISIBLE, -) = range(1, 51) +) = range(1, 52) # Keyword to token map, with the get() method assigned directly as a small # optimization @@ -6915,6 +6961,7 @@ def _shell_fn(kconf, _, command): "choice": _T_CHOICE, "comment": _T_COMMENT, "config": _T_CONFIG, + "configdefault": _T_CONFIGDEFAULT, "def_bool": _T_DEF_BOOL, "def_hex": _T_DEF_HEX, "def_int": _T_DEF_INT, diff --git a/scripts/logging/dictionary/database_gen.py b/scripts/logging/dictionary/database_gen.py index 1737186793d..663adb3a365 100755 --- a/scripts/logging/dictionary/database_gen.py +++ b/scripts/logging/dictionary/database_gen.py @@ -49,6 +49,11 @@ 'pinned.rodata', ] +# Sections that contains static strings but are not part of the binary (allocable). +REMOVED_STRING_SECTIONS = [ + 'log_strings' +] + # Regulation expression to match DWARF location DT_LOCATION_REGEX = re.compile(r"\(DW_OP_addr: ([0-9a-f]+)") @@ -94,7 +99,7 @@ def parse_args(): return argparser.parse_args() -def extract_elf_code_data_sections(elf): +def extract_elf_code_data_sections(elf, wildcards = None): """Find all sections in ELF file""" sections = {} @@ -103,9 +108,9 @@ def extract_elf_code_data_sections(elf): # since they actually have code/data. # # On contrary, BSS is allocated but NOBITS. - if ( - (sect['sh_flags'] & SH_FLAGS.SHF_ALLOC) == SH_FLAGS.SHF_ALLOC - and sect['sh_type'] == 'SHT_PROGBITS' + if (((wildcards is not None) and (sect.name in wildcards)) or + ((sect['sh_flags'] & SH_FLAGS.SHF_ALLOC) == SH_FLAGS.SHF_ALLOC + and sect['sh_type'] == 'SHT_PROGBITS') ): sections[sect.name] = { 'name' : sect.name, @@ -453,7 +458,7 @@ def extract_static_strings(elf, database, section_extraction=False): """ string_mappings = {} - elf_sections = extract_elf_code_data_sections(elf) + elf_sections = extract_elf_code_data_sections(elf, REMOVED_STRING_SECTIONS) # Extract strings using ELF DWARF information str_vars = extract_string_variables(elf) diff --git a/scripts/logging/dictionary/dictionary_parser/log_parser_v1.py b/scripts/logging/dictionary/dictionary_parser/log_parser_v1.py index 2559b5b39cd..e065837781f 100644 --- a/scripts/logging/dictionary/dictionary_parser/log_parser_v1.py +++ b/scripts/logging/dictionary/dictionary_parser/log_parser_v1.py @@ -79,9 +79,12 @@ def formalize_fmt_string(fmt_str): """Replace unsupported formatter""" new_str = fmt_str - # Python doesn't support %lld or %llu so need to remove extra 'l' - new_str = new_str.replace("%lld", "%ld") - new_str = new_str.replace("%llu", "%lu") + for spec in ['d', 'i', 'o', 'u', 'x', 'X']: + # Python doesn't support %ll for integer specifiers, so remove extra 'l' + new_str = new_str.replace("%ll" + spec, "%l" + spec) + + # Python doesn't support %hh for integer specifiers, so remove extra 'h' + new_str = new_str.replace("%hh" + spec, "%h" + spec) # No %p for pointer either, so use %x new_str = new_str.replace("%p", "0x%x") diff --git a/scripts/native_simulator/Makefile b/scripts/native_simulator/Makefile index 9dbdb66f31a..e74b1c7bc69 100644 --- a/scripts/native_simulator/Makefile +++ b/scripts/native_simulator/Makefile @@ -27,12 +27,15 @@ NSI_BUILD_PATH?=$(abspath _build/) EXE_NAME?=native_simulator.exe # Final executable path/file_name which will be produced NSI_EXE?=${NSI_BUILD_PATH}/${EXE_NAME} -# Path to the embedded SW which will be linked with the final executable +# Number of embedded CPUs/MCUs +NSI_N_CPUS?=1 +# Path to all CPUs embedded SW which will be linked with the final executable NSI_EMBEDDED_CPU_SW?= # Host architecture configuration switch NSI_ARCH?=-m32 # Coverage switch (GCOV coverage is enabled by default) NSI_COVERAGE?=--coverage +NSI_LOCALIZE_OPTIONS?= NSI_BUILD_OPTIONS?=${NSI_ARCH} ${NSI_COVERAGE} NSI_LINK_OPTIONS?=${NSI_ARCH} ${NSI_COVERAGE} # Extra source files to be built in the runner context @@ -61,7 +64,7 @@ NSI_CPPFLAGS?=-D_POSIX_C_SOURCE=200809 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTEN NO_PIE_CO:=-fno-pie -fno-pic DEPENDFLAGS:=-MMD -MP -CFLAGS:=${NSI_DEBUG} ${NSI_WARNINGS} ${NSI_OPT} ${NO_PIE_CO} \ +CFLAGS:=${NSI_DEBUG} ${NSI_WARNINGS} ${NSI_OPT} ${NO_PIE_CO} -DNSI_N_CPUS=${NSI_N_CPUS} \ -ffunction-sections -fdata-sections ${DEPENDFLAGS} -std=c11 ${NSI_BUILD_OPTIONS} FINALLINK_FLAGS:=${NO_PIE_CO} -no-pie ${NSI_WARNINGS} \ -Wl,--gc-sections -ldl -pthread \ @@ -93,6 +96,8 @@ DEPENDFILES:=$(addsuffix .d,$(basename ${OBJS})) -include ${DEPENDFILES} +LOCALIZED_EMBSW:=$(abspath $(addprefix $(NSI_BUILD_PATH)/,$(addsuffix .loc_cpusw.o,${NSI_EMBEDDED_CPU_SW}))) + ${NSI_BUILD_PATH}: @if [ ! -d ${NSI_BUILD_PATH} ]; then mkdir -p ${NSI_BUILD_PATH}; fi @@ -112,16 +117,19 @@ ${NSI_BUILD_PATH}/${RUNNER_LIB}: ${OBJS} if [ -f $@ ]; then rm $@ ; fi ${NSI_AR} -cr $@ ${OBJS} -${NSI_EXE}: ${NSI_BUILD_PATH}/${RUNNER_LIB} ${NSI_EMBEDDED_CPU_SW} ${NSI_EXTRA_LIBS} \ - ${NSI_BUILD_PATH}/linker_script.ld - @if [ -z ${NSI_EMBEDDED_CPU_SW} ] || [ ! -f ${NSI_EMBEDDED_CPU_SW} ]; then \ - echo "Error: Input embedded CPU SW not found (NSI_EMBEDDED_CPU_SW=${NSI_EMBEDDED_CPU_SW} )"; \ +${NSI_BUILD_PATH}/%.loc_cpusw.o: /% ${NSI_CONFIG_FILE} + @if [ -z $< ] || [ ! -f $< ]; then \ + echo "Error: Input embedded CPU SW ($<) not found \ +(NSI_EMBEDDED_CPU_SW=${NSI_EMBEDDED_CPU_SW} )"; \ false; \ fi - ${NSI_OBJCOPY} --localize-hidden ${NSI_EMBEDDED_CPU_SW} ${NSI_BUILD_PATH}/cpu_0.sw.o \ - -w --localize-symbol=_* - ${NSI_CC} -Wl,--whole-archive ${NSI_BUILD_PATH}/cpu_0.sw.o ${NSI_BUILD_PATH}/${RUNNER_LIB} \ - ${NSI_EXTRA_LIBS} -Wl,--no-whole-archive \ + @if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi + ${NSI_OBJCOPY} --localize-hidden $< $@ -w --localize-symbol=_* ${NSI_LOCALIZE_OPTIONS} + +${NSI_EXE}: ${NSI_BUILD_PATH}/${RUNNER_LIB} ${LOCALIZED_EMBSW} ${NSI_EXTRA_LIBS} \ + ${NSI_BUILD_PATH}/linker_script.ld + ${NSI_CC} -Wl,--whole-archive ${LOCALIZED_EMBSW} ${NSI_BUILD_PATH}/${RUNNER_LIB} \ + ${NSI_EXTRA_LIBS} -Wl,--no-whole-archive \ -o $@ ${FINALLINK_FLAGS} -T ${NSI_BUILD_PATH}/linker_script.ld Makefile: ; diff --git a/scripts/native_simulator/common/src/include/nsi_cpu_ctrl.h b/scripts/native_simulator/common/src/include/nsi_cpu_ctrl.h new file mode 100644 index 00000000000..4ea3ba37ddc --- /dev/null +++ b/scripts/native_simulator/common/src/include/nsi_cpu_ctrl.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NSI_COMMON_SRC_INCL_NSI_CPU_CTRL_H +#define NSI_COMMON_SRC_INCL_NSI_CPU_CTRL_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Define if a CPU should automatically start at boot or not + * + * @param[in] cpu_n: Which CPU + * @param[in] auto_start: If true, it will autostart on its own, + * if 0, it won't + */ +void nsi_cpu_set_auto_start(int cpu_n, bool auto_start); + +bool nsi_cpu_get_auto_start(int cpu_n); + +/** + * @brief Boot CPU + * + * Note: This API may only be called if that CPU was not stared before + * + * @param[in] cpu_n: Which CPU + */ +void nsi_cpu_boot(int cpu_n); + +/* + * Internal native simulator runner API. + * Boot all CPUs which are configured to boot automatically + */ +void nsi_cpu_auto_boot(void); + +#ifdef __cplusplus +} +#endif + +#endif /* NSI_COMMON_SRC_INCL_NSI_CPU_CTRL_H */ diff --git a/scripts/native_simulator/common/src/include/nsi_cpu_if.h b/scripts/native_simulator/common/src/include/nsi_cpu_if.h index 47afcf029e7..991b0b29917 100644 --- a/scripts/native_simulator/common/src/include/nsi_cpu_if.h +++ b/scripts/native_simulator/common/src/include/nsi_cpu_if.h @@ -11,6 +11,8 @@ extern "C" { #endif +#include "nsi_cpu_if_internal.h" + /* * Any symbol annotated by this macro will be visible outside of the * embedded SW library, both by the native simulator runner, @@ -93,31 +95,21 @@ NATIVE_SIMULATOR_IF void nsif_cpu0_irq_raised(void); */ NATIVE_SIMULATOR_IF void nsif_cpu0_irq_raised_from_sw(void); -#define NSI_CPU_IF_N(i) \ -NATIVE_SIMULATOR_IF void nsif_cpu##i##_pre_cmdline_hooks(void); \ -NATIVE_SIMULATOR_IF void nsif_cpu##i##_pre_hw_init_hooks(void); \ -NATIVE_SIMULATOR_IF void nsif_cpu##i##_boot(void); \ -NATIVE_SIMULATOR_IF int nsif_cpu##i##_cleanup(void); \ -NATIVE_SIMULATOR_IF void nsif_cpu##i##_irq_raised(void); \ -NATIVE_SIMULATOR_IF void nsif_cpu##i##_irq_raised_from_sw(void); - -NSI_CPU_IF_N(1) -NSI_CPU_IF_N(2) -NSI_CPU_IF_N(3) -NSI_CPU_IF_N(4) -NSI_CPU_IF_N(5) -NSI_CPU_IF_N(6) -NSI_CPU_IF_N(7) -NSI_CPU_IF_N(8) -NSI_CPU_IF_N(9) -NSI_CPU_IF_N(10) -NSI_CPU_IF_N(11) -NSI_CPU_IF_N(12) -NSI_CPU_IF_N(13) -NSI_CPU_IF_N(14) -NSI_CPU_IF_N(15) - -#undef NSI_CPU_IF_N +/* + * Optional hook which may be used for test functionality. + * When the runner HW models use them and for what is up to those + * specific models. + */ +NATIVE_SIMULATOR_IF int nsif_cpu0_test_hook(void *p); + +/* Provide prototypes for all n instances of these hooks */ +F_TRAMP_LIST(NATIVE_SIMULATOR_IF void nsif_cpu, _pre_cmdline_hooks(void)) +F_TRAMP_LIST(NATIVE_SIMULATOR_IF void nsif_cpu, _pre_hw_init_hooks(void)) +F_TRAMP_LIST(NATIVE_SIMULATOR_IF void nsif_cpu, _boot(void)) +F_TRAMP_LIST(NATIVE_SIMULATOR_IF int nsif_cpu, _cleanup(void)) +F_TRAMP_LIST(NATIVE_SIMULATOR_IF void nsif_cpu, _irq_raised(void)) +F_TRAMP_LIST(NATIVE_SIMULATOR_IF void nsif_cpu, _irq_raised_from_sw(void)) +F_TRAMP_LIST(NATIVE_SIMULATOR_IF int nsif_cpu, _test_hook(void *p)) #ifdef __cplusplus } diff --git a/scripts/native_simulator/common/src/include/nsi_cpu_if_internal.h b/scripts/native_simulator/common/src/include/nsi_cpu_if_internal.h new file mode 100644 index 00000000000..d75f64065e2 --- /dev/null +++ b/scripts/native_simulator/common/src/include/nsi_cpu_if_internal.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NSI_COMMON_SRC_INCL_NSI_CPU_IF_INTERNAL_H +#define NSI_COMMON_SRC_INCL_NSI_CPU_IF_INTERNAL_H + +#include "nsi_utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define FUNCT(i, pre, post) \ + pre##i##post + +#define FUNCT_LIST(pre, post, sep) \ + FUNCT(0, pre, post) NSI_DEBRACKET sep \ + FUNCT(1, pre, post) NSI_DEBRACKET sep \ + FUNCT(2, pre, post) NSI_DEBRACKET sep \ + FUNCT(3, pre, post) NSI_DEBRACKET sep \ + FUNCT(4, pre, post) NSI_DEBRACKET sep \ + FUNCT(5, pre, post) NSI_DEBRACKET sep \ + FUNCT(6, pre, post) NSI_DEBRACKET sep \ + FUNCT(7, pre, post) NSI_DEBRACKET sep \ + FUNCT(8, pre, post) NSI_DEBRACKET sep \ + FUNCT(9, pre, post) NSI_DEBRACKET sep \ + FUNCT(10, pre, post) NSI_DEBRACKET sep \ + FUNCT(11, pre, post) NSI_DEBRACKET sep \ + FUNCT(12, pre, post) NSI_DEBRACKET sep \ + FUNCT(13, pre, post) NSI_DEBRACKET sep \ + FUNCT(14, pre, post) NSI_DEBRACKET sep \ + FUNCT(15, pre, post) NSI_DEBRACKET sep \ + +#define F_TRAMP_TABLE(pre, post) FUNCT_LIST(pre, post, (,)) + +#define F_TRAMP_LIST(pre, post) FUNCT_LIST(pre, post, (;)) + +#define F_TRAMP_BODY_LIST(pre, post) FUNCT_LIST(pre, post, ()) + +#define TRAMPOLINES(pre, post) \ + void pre ## n ## post(int n) \ + { \ + void(*fptrs[])(void) = { \ + F_TRAMP_TABLE(pre, post) \ + }; \ + fptrs[n](); \ + } + +#define TRAMPOLINES_i_vp(pre, post) \ + int pre ## n ## post(int n, void *p) \ + { \ + int(*fptrs[])(void *p) = { \ + F_TRAMP_TABLE(pre, post) \ + }; \ + return fptrs[n](p); \ + } + +#define TRAMPOLINES_i_(pre, post) \ + int pre ## n ## post(int n) \ + { \ + int(*fptrs[])(void) = { \ + F_TRAMP_TABLE(pre, post) \ + }; \ + return fptrs[n](); \ + } + +#ifdef __cplusplus +} +#endif + +#endif /* NSI_COMMON_SRC_INCL_NSI_CPU_IF_INTERNAL_H */ diff --git a/scripts/native_simulator/common/src/nsi_utils.h b/scripts/native_simulator/common/src/include/nsi_utils.h similarity index 87% rename from scripts/native_simulator/common/src/nsi_utils.h rename to scripts/native_simulator/common/src/include/nsi_utils.h index 83f2f22943b..f41fdf9ddc8 100644 --- a/scripts/native_simulator/common/src/nsi_utils.h +++ b/scripts/native_simulator/common/src/include/nsi_utils.h @@ -8,6 +8,8 @@ #ifndef NSI_COMMON_SRC_INCL_NSI_UTILS_H #define NSI_COMMON_SRC_INCL_NSI_UTILS_H +/* Remove brackets from around a single argument: */ +#define NSI_DEBRACKET(...) __VA_ARGS__ #define _NSI_STRINGIFY(x) #x #define NSI_STRINGIFY(s) _NSI_STRINGIFY(s) diff --git a/scripts/native_simulator/common/src/main.c b/scripts/native_simulator/common/src/main.c index b97904a43d3..ffe1d3b93d1 100644 --- a/scripts/native_simulator/common/src/main.c +++ b/scripts/native_simulator/common/src/main.c @@ -14,25 +14,29 @@ #include #include #include -#include "nsi_cpu_if.h" +#include "nsi_cpun_if.h" #include "nsi_tasks.h" #include "nsi_cmdline_main_if.h" #include "nsi_utils.h" #include "nsi_hw_scheduler.h" +#include "nsi_config.h" +#include "nsi_cpu_ctrl.h" int nsi_exit_inner(int exit_code) { static int max_exit_code; + int cpu_ret; max_exit_code = NSI_MAX(exit_code, max_exit_code); /* - * nsif_cpu0_cleanup may not return if this is called from a SW thread, + * nsif_cpun_cleanup may not return if this is called from a SW thread, * but instead it would get nsi_exit() recalled again * ASAP from the HW thread */ - int cpu_0_ret = nsif_cpu0_cleanup(); - - max_exit_code = NSI_MAX(cpu_0_ret, max_exit_code); + for (int i = 0; i < NSI_N_CPUS; i++) { + cpu_ret = nsif_cpun_cleanup(i); + max_exit_code = NSI_MAX(cpu_ret, max_exit_code); + } nsi_run_tasks(NSITASK_ON_EXIT_PRE_LEVEL); nsi_hws_cleanup(); @@ -62,19 +66,23 @@ static void nsi_init(int argc, char *argv[]) setvbuf(stderr, NULL, _IOLBF, 512); nsi_run_tasks(NSITASK_PRE_BOOT_1_LEVEL); - nsif_cpu0_pre_cmdline_hooks(); + for (int i = 0; i < NSI_N_CPUS; i++) { + nsif_cpun_pre_cmdline_hooks(i); + } nsi_handle_cmd_line(argc, argv); nsi_run_tasks(NSITASK_PRE_BOOT_2_LEVEL); - nsif_cpu0_pre_hw_init_hooks(); + for (int i = 0; i < NSI_N_CPUS; i++) { + nsif_cpun_pre_hw_init_hooks(i); + } nsi_run_tasks(NSITASK_HW_INIT_LEVEL); nsi_hws_init(); nsi_run_tasks(NSITASK_PRE_BOOT_3_LEVEL); - nsif_cpu0_boot(); + nsi_cpu_auto_boot(); nsi_run_tasks(NSITASK_FIRST_SLEEP_LEVEL); } diff --git a/scripts/native_simulator/common/src/nsi_config.h b/scripts/native_simulator/common/src/nsi_config.h new file mode 100644 index 00000000000..1ca67ddc8b1 --- /dev/null +++ b/scripts/native_simulator/common/src/nsi_config.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NSI_COMMON_SRC_NSI_CONFIG_H +#define NSI_COMMON_SRC_NSI_CONFIG_H + +#ifndef NSI_N_CPUS +#define NSI_N_CPUS 1 +#endif + +#endif /* NSI_COMMON_SRC_NSI_CONFIG_H */ diff --git a/scripts/native_simulator/common/src/nsi_cpu_ctrl.c b/scripts/native_simulator/common/src/nsi_cpu_ctrl.c new file mode 100644 index 00000000000..4b7e5cd1b65 --- /dev/null +++ b/scripts/native_simulator/common/src/nsi_cpu_ctrl.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "nsi_config.h" +#include "nsi_cpun_if.h" +#include "nsi_tracing.h" + +static bool cpu_auto_start[NSI_N_CPUS] = {true}; /* Only the first core starts on its own */ +static bool cpu_booted[NSI_N_CPUS]; + +#define CPU_N_RANGE_CHECK(cpu_n) \ + if (cpu_n >= NSI_N_CPUS) { \ + nsi_print_error_and_exit("%s called with cpu_n(%i) >= NSI_N_CPUS (%i)\n", \ + cpu_n, NSI_N_CPUS); \ + } + +void nsi_cpu_set_auto_start(int cpu_n, bool auto_start) +{ + CPU_N_RANGE_CHECK(cpu_n); + + cpu_auto_start[cpu_n] = auto_start; +} + +bool nsi_cpu_get_auto_start(int cpu_n) +{ + return cpu_auto_start[cpu_n]; +} + +void nsi_cpu_auto_boot(void) +{ + for (int i = 0; i < NSI_N_CPUS; i++) { + if (cpu_auto_start[i] == true) { + cpu_booted[i] = true; + nsif_cpun_boot(i); + } + } +} + +void nsi_cpu_boot(int cpu_n) +{ + CPU_N_RANGE_CHECK(cpu_n); + if (cpu_booted[cpu_n]) { + nsi_print_warning("%s called with cpu_n(%i) which was already booted\n", + cpu_n); + } + cpu_booted[cpu_n] = true; + nsif_cpun_boot(cpu_n); +} diff --git a/scripts/native_simulator/common/src/nsi_cpun_if.c b/scripts/native_simulator/common/src/nsi_cpun_if.c index 174c770a7a4..c30bfd5a587 100644 --- a/scripts/native_simulator/common/src/nsi_cpun_if.c +++ b/scripts/native_simulator/common/src/nsi_cpun_if.c @@ -11,48 +11,10 @@ * for ex., nsif_cpun_boot(4) -> nsif_cpu4_boot() */ -#define FUNCT(i, pre, post) \ - pre##i##post - -#define F_TABLE(pre, post) \ - FUNCT(0, pre, post), \ - FUNCT(1, pre, post), \ - FUNCT(2, pre, post), \ - FUNCT(3, pre, post), \ - FUNCT(4, pre, post), \ - FUNCT(5, pre, post), \ - FUNCT(6, pre, post), \ - FUNCT(7, pre, post), \ - FUNCT(8, pre, post), \ - FUNCT(9, pre, post), \ - FUNCT(10, pre, post), \ - FUNCT(11, pre, post), \ - FUNCT(12, pre, post), \ - FUNCT(13, pre, post), \ - FUNCT(14, pre, post), \ - FUNCT(15, pre, post) - -#define TRAMPOLINES(pre, post) \ - void pre ## n ## post(int n) \ - { \ - void(*fptrs[])(void) = { \ - F_TABLE(pre, post) \ - }; \ - fptrs[n](); \ - } - -#define TRAMPOLINES_i(pre, post) \ - int pre ## n ## post(int n) \ - { \ - int(*fptrs[])(void) = { \ - F_TABLE(pre, post) \ - }; \ - return fptrs[n](); \ - } - TRAMPOLINES(nsif_cpu, _pre_cmdline_hooks) TRAMPOLINES(nsif_cpu, _pre_hw_init_hooks) TRAMPOLINES(nsif_cpu, _boot) -TRAMPOLINES_i(nsif_cpu, _cleanup) +TRAMPOLINES_i_(nsif_cpu, _cleanup) TRAMPOLINES(nsif_cpu, _irq_raised) TRAMPOLINES(nsif_cpu, _irq_raised_from_sw) +TRAMPOLINES_i_vp(nsif_cpu, _test_hook) diff --git a/scripts/native_simulator/common/src/nsi_cpun_if.h b/scripts/native_simulator/common/src/nsi_cpun_if.h index c072e5938ea..d0d546378cc 100644 --- a/scripts/native_simulator/common/src/nsi_cpun_if.h +++ b/scripts/native_simulator/common/src/nsi_cpun_if.h @@ -21,6 +21,7 @@ void nsif_cpun_boot(int n); int nsif_cpun_cleanup(int n); void nsif_cpun_irq_raised(int n); void nsif_cpun_irq_raised_from_sw(int n); +void nsif_cpun_test_hook(int n, void *p); #ifdef __cplusplus } diff --git a/scripts/native_simulator/common/src/nsi_internal.h b/scripts/native_simulator/common/src/nsi_internal.h index 00e63897996..ebe8289b178 100644 --- a/scripts/native_simulator/common/src/nsi_internal.h +++ b/scripts/native_simulator/common/src/nsi_internal.h @@ -14,7 +14,6 @@ extern "C" { #endif /** - * * @brief find least significant bit set in a 32-bit word * * This routine finds the first bit set starting from the least significant bit @@ -30,6 +29,22 @@ static inline unsigned int nsi_find_lsb_set(uint32_t op) return __builtin_ffs(op); } +/** + * @brief find least significant bit set in a 64-bit word + * + * This routine finds the first bit set starting from the least significant bit + * in the argument passed in and returns the index of that bit. Bits are + * numbered starting at 1 from the least significant bit. A return value of + * zero indicates that the value passed is zero. + * + * @return least significant bit set, 0 if @a op is 0 + */ + +static inline unsigned int nsi_find_lsb_set64(uint64_t op) +{ + return __builtin_ffsll(op); +} + #ifdef __cplusplus } #endif diff --git a/scripts/native_simulator/common/src/nsi_weak_stubs.c b/scripts/native_simulator/common/src/nsi_weak_stubs.c index b2e7e2d2ebd..3c4f096684c 100644 --- a/scripts/native_simulator/common/src/nsi_weak_stubs.c +++ b/scripts/native_simulator/common/src/nsi_weak_stubs.c @@ -12,33 +12,25 @@ * The CPU does not boot, and interrupts are just ignored * These are all defined as weak, so if an actual image is present for that CPU, * that will be linked against. + * + * This exists in case the total device image is assembled lacking some of the embedded CPU images */ -#define NSI_CPU_STUBBED_IMAGE(i) \ -__attribute__((weak)) void nsif_cpu##i##_pre_cmdline_hooks(void) { } \ -__attribute__((weak)) void nsif_cpu##i##_pre_hw_init_hooks(void) { } \ -__attribute__((weak)) void nsif_cpu##i##_boot(void) \ - { \ - nsi_print_trace("Attempted boot of CPU %i without image. "\ - "CPU %i shut down permanently\n", i, i); \ - } \ -__attribute__((weak)) int nsif_cpu##i##_cleanup(void) { return 0; } \ -__attribute__((weak)) void nsif_cpu##i##_irq_raised(void) { } \ -__attribute__((weak)) void nsif_cpu##i##_irq_raised_from_sw(void) { } +static void nsi_boot_warning(const char *func) +{ + nsi_print_trace("%s: Attempted boot of CPU without image. " + "CPU shut down permanently\n", func); +} -NSI_CPU_STUBBED_IMAGE(0) -NSI_CPU_STUBBED_IMAGE(1) -NSI_CPU_STUBBED_IMAGE(2) -NSI_CPU_STUBBED_IMAGE(3) -NSI_CPU_STUBBED_IMAGE(4) -NSI_CPU_STUBBED_IMAGE(5) -NSI_CPU_STUBBED_IMAGE(6) -NSI_CPU_STUBBED_IMAGE(7) -NSI_CPU_STUBBED_IMAGE(8) -NSI_CPU_STUBBED_IMAGE(9) -NSI_CPU_STUBBED_IMAGE(10) -NSI_CPU_STUBBED_IMAGE(11) -NSI_CPU_STUBBED_IMAGE(12) -NSI_CPU_STUBBED_IMAGE(13) -NSI_CPU_STUBBED_IMAGE(14) -NSI_CPU_STUBBED_IMAGE(15) +/* + * These will define N functions like + * int nsif_cpu_cleanup(void) { return 0; } + */ +F_TRAMP_BODY_LIST(__attribute__((weak)) void nsif_cpu, _pre_cmdline_hooks(void) { }) +F_TRAMP_BODY_LIST(__attribute__((weak)) void nsif_cpu, _pre_hw_init_hooks(void) { }) +F_TRAMP_BODY_LIST(__attribute__((weak)) void nsif_cpu, + _boot(void) { nsi_boot_warning(__func__); }) +F_TRAMP_BODY_LIST(__attribute__((weak)) int nsif_cpu, _cleanup(void) { return 0; }) +F_TRAMP_BODY_LIST(__attribute__((weak)) void nsif_cpu, _irq_raised(void) { }) +F_TRAMP_BODY_LIST(__attribute__((weak)) void nsif_cpu, _irq_raised_from_sw(void) { }) +F_TRAMP_BODY_LIST(__attribute__((weak)) int nsif_cpu, _test_hook(void *p) { return 0; }) diff --git a/scripts/native_simulator/native/src/hw_counter.c b/scripts/native_simulator/native/src/hw_counter.c index fc0770dc6a2..2429a57f076 100644 --- a/scripts/native_simulator/native/src/hw_counter.c +++ b/scripts/native_simulator/native/src/hw_counter.c @@ -17,6 +17,7 @@ static bool counter_running; static uint64_t counter_value; static uint64_t counter_target; static uint64_t counter_period; +static uint64_t counter_wrap; /** * Initialize the counter with prescaler of HW @@ -28,6 +29,7 @@ static void hw_counter_init(void) counter_value = 0; counter_running = false; counter_period = NSI_NEVER; + counter_wrap = NSI_NEVER; } NSI_TASK(hw_counter_init, HW_INIT, 10); @@ -40,7 +42,7 @@ static void hw_counter_triggered(void) } hw_counter_timer = nsi_hws_get_time() + counter_period; - counter_value = counter_value + 1; + counter_value = (counter_value + 1) % counter_wrap; if (counter_value == counter_target) { hw_irq_ctrl_set_irq(COUNTER_EVENT_IRQ); @@ -58,6 +60,16 @@ void hw_counter_set_period(uint64_t period) counter_period = period; } +/* + * Set the count value at which the counter will wrap + * The counter will count up to (counter_wrap-1), i.e.: + * 0, 1, 2,.., (counter_wrap - 1), 0 + */ +void hw_counter_set_wrap_value(uint64_t wrap_value) +{ + counter_wrap = wrap_value; +} + /** * Starts the counter. It must be previously configured with * hw_counter_set_period() and hw_counter_set_target(). @@ -86,6 +98,11 @@ void hw_counter_stop(void) nsi_hws_find_next_event(); } +bool hw_counter_is_started(void) +{ + return counter_running; +} + /** * Returns the current counter value. */ @@ -94,6 +111,14 @@ uint64_t hw_counter_get_value(void) return counter_value; } +/** + * Resets the counter value. + */ +void hw_counter_reset(void) +{ + counter_value = 0; +} + /** * Configures the counter to generate an interrupt * when its count value reaches target. diff --git a/scripts/native_simulator/native/src/include/hw_counter.h b/scripts/native_simulator/native/src/include/hw_counter.h index 766aa8e27c3..9230f930bdf 100644 --- a/scripts/native_simulator/native/src/include/hw_counter.h +++ b/scripts/native_simulator/native/src/include/hw_counter.h @@ -22,9 +22,12 @@ void hw_counter_triggered(void); void hw_counter_set_period(uint64_t period); void hw_counter_set_target(uint64_t counter_target); +void hw_counter_set_wrap_value(uint64_t wrap_value); void hw_counter_start(void); void hw_counter_stop(void); +bool hw_counter_is_started(void); uint64_t hw_counter_get_value(void); +void hw_counter_reset(void); #ifdef __cplusplus } diff --git a/scripts/native_simulator/native/src/irq_ctrl.c b/scripts/native_simulator/native/src/irq_ctrl.c index 40ee28487f0..2c187f77679 100644 --- a/scripts/native_simulator/native/src/irq_ctrl.c +++ b/scripts/native_simulator/native/src/irq_ctrl.c @@ -95,7 +95,7 @@ int hw_irq_ctrl_get_highest_prio_irq(void) int winner_prio = 256; while (irq_status != 0U) { - int irq_nbr = nsi_find_lsb_set(irq_status) - 1; + int irq_nbr = nsi_find_lsb_set64(irq_status) - 1; irq_status &= ~((uint64_t) 1 << irq_nbr); if ((winner_prio > (int)irq_prio[irq_nbr]) diff --git a/scripts/net/run-sample-tests.sh b/scripts/net/run-sample-tests.sh index f99215685e0..11162b30b5e 100755 --- a/scripts/net/run-sample-tests.sh +++ b/scripts/net/run-sample-tests.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # Copyright (c) 2019 Intel Corporation # SPDX-License-Identifier: Apache-2.0 @@ -36,7 +36,7 @@ check_dirs () do local l - l="$d/net-tools" + l="$d/tools/net-tools" if [ -d "$l" ]; then NET_TOOLS_BASE="$l" break diff --git a/scripts/pylib/build_helpers/domains.py b/scripts/pylib/build_helpers/domains.py index 978569d9547..760217cc282 100644 --- a/scripts/pylib/build_helpers/domains.py +++ b/scripts/pylib/build_helpers/domains.py @@ -78,7 +78,7 @@ def __init__(self, domains_yaml): # Now that self._domains has been initialized, we can leverage # the common checks in self.get_domain to verify this. self._default_domain = self.get_domain(data['default']) - self._flash_order = self.get_domains(data['flash_order'] or []) + self._flash_order = self.get_domains(data.get('flash_order', [])) @staticmethod def from_file(domains_file): diff --git a/scripts/pylib/pytest-twister-harness/README.rst b/scripts/pylib/pytest-twister-harness/README.rst index 814282fc57b..860b7cd645d 100644 --- a/scripts/pylib/pytest-twister-harness/README.rst +++ b/scripts/pylib/pytest-twister-harness/README.rst @@ -20,8 +20,8 @@ Run exemplary test shell application by Twister: cd ${ZEPHYR_BASE} - # native_posix & QEMU - ./scripts/twister -p native_posix -p qemu_x86 -T samples/subsys/testsuite/pytest/shell + # native_sim & QEMU + ./scripts/twister -p native_sim -p qemu_x86 -T samples/subsys/testsuite/pytest/shell # hardware ./scripts/twister -p nrf52840dk_nrf52840 --device-testing --device-serial /dev/ttyACM0 -T samples/subsys/testsuite/pytest/shell @@ -34,8 +34,8 @@ or build shell application by west and call pytest directly: cd ${ZEPHYR_BASE}/samples/subsys/testsuite/pytest/shell - # native_posix - west build -p -b native_posix -- -DCONFIG_NATIVE_UART_0_ON_STDINOUT=y + # native_sim + west build -p -b native_sim -- -DCONFIG_NATIVE_UART_0_ON_STDINOUT=y pytest --twister-harness --device-type=native --build-dir=build -p twister_harness.plugin # QEMU diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/device/device_adapter.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/device/device_adapter.py index 5fdd7ccc2fa..59be6c52af9 100644 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/device/device_adapter.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/device/device_adapter.py @@ -203,7 +203,7 @@ def _handle_device_output(self) -> None: with open(self.handler_log_path, 'a+') as log_file: while self.is_device_running(): if self.is_device_connected(): - output = self._read_device_output().decode().strip() + output = self._read_device_output().decode(errors='replace').strip() if output: self._device_read_queue.put(output) log_file.write(f'{output}\n') diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/device/utils.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/device/utils.py index 5b89d1ad7a8..60ee2537bb8 100644 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/device/utils.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/device/utils.py @@ -44,7 +44,7 @@ def terminate_process(proc: subprocess.Popen) -> None: for child in psutil.Process(proc.pid).children(recursive=True): try: os.kill(child.pid, signal.SIGTERM) - except ProcessLookupError: + except (ProcessLookupError, psutil.NoSuchProcess): pass proc.terminate() # sleep for a while before attempting to kill diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/helpers/shell.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/helpers/shell.py index 37f8ad432cf..f6eb8074451 100644 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/helpers/shell.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/helpers/shell.py @@ -8,6 +8,9 @@ import re import time +from dataclasses import dataclass, field +from inspect import signature + from twister_harness.device.device_adapter import DeviceAdapter from twister_harness.exceptions import TwisterHarnessTimeoutException @@ -66,3 +69,63 @@ def exec_command(self, command: str, timeout: float | None = None, print_output: # wait for device command execution lines.extend(self._device.readlines_until(regex=regex_prompt, timeout=timeout, print_output=print_output)) return lines + + def get_filtered_output(self, command_lines: list[str]) -> list[str]: + regex_filter = re.compile( + '|'.join([ + re.escape(self.prompt), + '', + '', + '', + '' + ]) + ) + return list(filter(lambda l: not regex_filter.search(l), command_lines)) + + +@dataclass +class ShellMCUbootArea: + name: str + version: str + image_size: str + magic: str = 'unset' + swap_type: str = 'none' + copy_done: str = 'unset' + image_ok: str = 'unset' + + @classmethod + def from_kwargs(cls, **kwargs) -> ShellMCUbootArea: + cls_fields = {field for field in signature(cls).parameters} + native_args = {} + for name, val in kwargs.items(): + if name in cls_fields: + native_args[name] = val + return cls(**native_args) + + +@dataclass +class ShellMCUbootCommandParsed: + """ + Helper class to keep data from `mcuboot` shell command. + """ + areas: list[ShellMCUbootArea] = field(default_factory=list) + + @classmethod + def create_from_cmd_output(cls, cmd_output: list[str]) -> ShellMCUbootCommandParsed: + """ + Factory to create class from the output of `mcuboot` shell command. + """ + areas: list[dict] = [] + re_area = re.compile(r'(.+ area.*):\s*$') + re_key = re.compile(r'(?P.+):(?P.+)') + for line in cmd_output: + if m := re_area.search(line): + areas.append({'name': m.group(1)}) + elif areas: + if m := re_key.search(line): + areas[-1][m.group('key').strip().replace(' ', '_')] = m.group('val').strip() + data_areas: list[ShellMCUbootArea] = [] + for area in areas: + data_areas.append(ShellMCUbootArea.from_kwargs(**area)) + + return cls(data_areas) diff --git a/scripts/pylib/pytest-twister-harness/tests/helpers/shell_mcuboot_command_parser_test.py b/scripts/pylib/pytest-twister-harness/tests/helpers/shell_mcuboot_command_parser_test.py new file mode 100644 index 00000000000..c6ebf46c2c2 --- /dev/null +++ b/scripts/pylib/pytest-twister-harness/tests/helpers/shell_mcuboot_command_parser_test.py @@ -0,0 +1,56 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 + +import textwrap + +from twister_harness.helpers.shell import ShellMCUbootCommandParsed, ShellMCUbootArea + + +def test_if_mcuboot_command_output_is_parsed_two_areas() -> None: + cmd_output = textwrap.dedent(""" + \x1b[1;32muart:~$ \x1b[mmcuboot + swap type: revert + confirmed: 0 + primary area (1): + version: 0.0.2+0 + image size: 68240 + magic: good + swap type: test + copy done: set + image ok: unset + secondary area (3): + version: 0.0.0+0 + image size: 68240 + magic: unset + swap type: none + copy done: unset + image ok: unset + \x1b[1;32muart:~$ \x1b[m + """) + mcuboot_parsed = ShellMCUbootCommandParsed.create_from_cmd_output(cmd_output.splitlines()) + assert isinstance(mcuboot_parsed, ShellMCUbootCommandParsed) + assert isinstance(mcuboot_parsed.areas[0], ShellMCUbootArea) + assert len(mcuboot_parsed.areas) == 2 + assert mcuboot_parsed.areas[0].version == '0.0.2+0' + assert mcuboot_parsed.areas[0].swap_type == 'test' + + +def test_if_mcuboot_command_output_is_parsed_with_failed_area() -> None: + cmd_output = textwrap.dedent(""" + \x1b[1;32muart:~$ \x1b[mmcuboot + swap type: revert + confirmed: 0 + primary area (1): + version: 1.1.1+1 + image size: 68240 + magic: good + swap type: test + copy done: set + image ok: unset + failed to read secondary area (1) header: -5 + \x1b[1;32muart:~$ \x1b[m + """) + mcuboot_parsed = ShellMCUbootCommandParsed.create_from_cmd_output(cmd_output.splitlines()) + assert len(mcuboot_parsed.areas) == 1 + assert mcuboot_parsed.areas[0].version == '1.1.1+1' diff --git a/scripts/pylib/twister/scl.py b/scripts/pylib/twister/scl.py index 2518e4b4138..25a3210b141 100644 --- a/scripts/pylib/twister/scl.py +++ b/scripts/pylib/twister/scl.py @@ -21,6 +21,11 @@ log = logging.getLogger("scl") + +class EmptyYamlFileException(Exception): + pass + + # # def yaml_load(filename): @@ -36,7 +41,7 @@ def yaml_load(filename): :return: dictionary representing the YAML document """ try: - with open(filename, 'r') as f: + with open(filename, 'r', encoding='utf-8') as f: return yaml.load(f, Loader=SafeLoader) except yaml.scanner.ScannerError as e: # For errors parsing schema.yaml mark = e.problem_mark @@ -78,5 +83,7 @@ def yaml_load_verify(filename, schema): """ # 'document.yaml' contains a single YAML document. y = yaml_load(filename) + if not y: + raise EmptyYamlFileException('No data in YAML file: %s' % filename) _yaml_validate(y, schema) return y diff --git a/scripts/pylib/twister/twisterlib/config_parser.py b/scripts/pylib/twister/twisterlib/config_parser.py index f431e2d57c2..53732876247 100644 --- a/scripts/pylib/twister/twisterlib/config_parser.py +++ b/scripts/pylib/twister/twisterlib/config_parser.py @@ -3,6 +3,7 @@ # Copyright (c) 2018-2022 Intel Corporation # SPDX-License-Identifier: Apache-2.0 +import copy import scl import warnings from typing import Union @@ -176,7 +177,8 @@ def get_scenario(self, name): {"CONF_FILE", "OVERLAY_CONFIG", "DTC_OVERLAY_FILE"}, v ) else: - d[k] = v + # Copy common value to avoid mutating it with test specific values below + d[k] = copy.copy(v) for k, v in self.scenarios[name].items(): if k == "extra_args": diff --git a/scripts/pylib/twister/twisterlib/coverage.py b/scripts/pylib/twister/twisterlib/coverage.py index 067dcfbcca7..c1c9065d9ad 100644 --- a/scripts/pylib/twister/twisterlib/coverage.py +++ b/scripts/pylib/twister/twisterlib/coverage.py @@ -71,6 +71,7 @@ def retrieve_gcov_data(input_file): @staticmethod def create_gcda_files(extracted_coverage_info): + gcda_created = True logger.debug("Generating gcda files") for filename, hexdump_val in extracted_coverage_info.items(): # if kobject_hash is given for coverage gcovr fails @@ -83,19 +84,33 @@ def create_gcda_files(extracted_coverage_info): pass continue - with open(filename, 'wb') as fp: - fp.write(bytes.fromhex(hexdump_val)) + try: + with open(filename, 'wb') as fp: + fp.write(bytes.fromhex(hexdump_val)) + except ValueError: + logger.exception("Unable to convert hex data for file: {}".format(filename)) + gcda_created = False + except FileNotFoundError: + logger.exception("Unable to create gcda file: {}".format(filename)) + gcda_created = False + return gcda_created def generate(self, outdir): + coverage_completed = True for filename in glob.glob("%s/**/handler.log" % outdir, recursive=True): gcov_data = self.__class__.retrieve_gcov_data(filename) capture_complete = gcov_data['complete'] extracted_coverage_info = gcov_data['data'] if capture_complete: - self.__class__.create_gcda_files(extracted_coverage_info) - logger.debug("Gcov data captured: {}".format(filename)) + gcda_created = self.__class__.create_gcda_files(extracted_coverage_info) + if gcda_created: + logger.debug("Gcov data captured: {}".format(filename)) + else: + logger.error("Gcov data invalid for: {}".format(filename)) + coverage_completed = False else: logger.error("Gcov data capture incomplete: {}".format(filename)) + coverage_completed = False with open(os.path.join(outdir, "coverage.log"), "a") as coveragelog: ret = self._generate(outdir, coveragelog) @@ -111,6 +126,10 @@ def generate(self, outdir): } for r in self.output_formats.split(','): logger.info(report_log[r]) + else: + coverage_completed = False + logger.debug("All coverage data processed: {}".format(coverage_completed)) + return coverage_completed class Lcov(CoverageTool): @@ -202,11 +221,11 @@ def _generate(self, outdir, coveragelog): excludes = Gcovr._interleave_list("-e", self.ignores) # We want to remove tests/* and tests/ztest/test/* but save tests/ztest - cmd = ["gcovr", "-r", self.base_dir, "--gcov-executable", - str(self.gcov_tool), "-e", "tests/*"] + excludes + ["--json", - "-o", - coveragefile, - outdir] + cmd = ["gcovr", "-r", self.base_dir, + "--gcov-ignore-parse-errors=negative_hits.warn_once_per_file", + "--gcov-executable", str(self.gcov_tool), + "-e", "tests/*"] + cmd += excludes + ["--json", "-o", coveragefile, outdir] cmd_str = " ".join(cmd) logger.debug(f"Running {cmd_str}...") subprocess.call(cmd, stdout=coveragelog) @@ -280,4 +299,5 @@ def run_coverage(testplan, options): coverage_tool.add_ignore_file('generated') coverage_tool.add_ignore_directory('tests') coverage_tool.add_ignore_directory('samples') - coverage_tool.generate(options.outdir) + coverage_completed = coverage_tool.generate(options.outdir) + return coverage_completed diff --git a/scripts/pylib/twister/twisterlib/environment.py b/scripts/pylib/twister/twisterlib/environment.py index d1ce56711c2..16e19c85fec 100644 --- a/scripts/pylib/twister/twisterlib/environment.py +++ b/scripts/pylib/twister/twisterlib/environment.py @@ -196,6 +196,11 @@ def add_parse_arguments(parser = None): help="""Only run device tests with current artifacts, do not build the code""") + parser.add_argument("--timeout-multiplier", type=float, default=1, + help="""Globally adjust tests timeouts by specified multiplier. The resulting test + timeout would be multiplication of test timeout value, board-level timeout multiplier + and global timeout multiplier (this parameter)""") + test_xor_subtest.add_argument( "-s", "--test", action="append", help="Run only the specified testsuite scenario. These are named by " @@ -221,7 +226,7 @@ def add_parse_arguments(parser = None): "--enable-valgrind", action="store_true", help="""Run binary through valgrind and check for several memory access errors. Valgrind needs to be installed on the host. This option only - works with host binaries such as those generated for the native_posix + works with host binaries such as those generated for the native_sim configuration and is mutual exclusive with --enable-asan. """) @@ -229,7 +234,7 @@ def add_parse_arguments(parser = None): "--enable-asan", action="store_true", help="""Enable address sanitizer to check for several memory access errors. Libasan needs to be installed on the host. This option only - works with host binaries such as those generated for the native_posix + works with host binaries such as those generated for the native_sim configuration and is mutual exclusive with --enable-valgrind. """) @@ -350,7 +355,7 @@ def add_parse_arguments(parser = None): "--enable-lsan", action="store_true", help="""Enable leak sanitizer to check for heap memory leaks. Libasan needs to be installed on the host. This option only - works with host binaries such as those generated for the native_posix + works with host binaries such as those generated for the native_sim configuration and when --enable-asan is given. """) @@ -359,12 +364,17 @@ def add_parse_arguments(parser = None): help="""Enable undefined behavior sanitizer to check for undefined behaviour during program execution. It uses an optional runtime library to provide better error diagnostics. This option only works with host - binaries such as those generated for the native_posix configuration. + binaries such as those generated for the native_sim configuration. """) parser.add_argument("--enable-size-report", action="store_true", help="Enable expensive computation of RAM/ROM segment sizes.") + parser.add_argument("--create-rom-ram-report", action="store_true", + help="Generate detailed ram/rom json reports for " + "each build, via cmake build calls with the " + "`--target footprint` argument") + parser.add_argument( "--filter", choices=['buildable', 'runnable'], default='buildable', @@ -502,6 +512,10 @@ def add_parse_arguments(parser = None): that support this feature (currently only Linux). """) + parser.add_argument( + "--vendor", action="append", default=[], + help="Vendor filter for testing") + parser.add_argument( "-p", "--platform", action="append", default=[], help="Platform filter for testing. This option may be used multiple " @@ -542,12 +556,6 @@ def add_parse_arguments(parser = None): default=True, help="deprecated, left for compatibility") - parser.add_argument("--report-excluded", - action="store_true", - help="""List all tests that are never run based on current scope and - coverage. If you are looking for accurate results, run this with - --all, but this will take a while...""") - parser.add_argument( "--report-name", help="""Create a report with a custom name. @@ -584,7 +592,7 @@ def add_parse_arguments(parser = None): parser.add_argument( "--seed", type=int, - help="Seed for native posix pseudo-random number generator") + help="Seed for native_sim pseudo-random number generator") parser.add_argument( "--short-build-path", diff --git a/scripts/pylib/twister/twisterlib/handlers.py b/scripts/pylib/twister/twisterlib/handlers.py index d9f1943e1c3..3c6498a6ea4 100755 --- a/scripts/pylib/twister/twisterlib/handlers.py +++ b/scripts/pylib/twister/twisterlib/handlers.py @@ -5,19 +5,20 @@ # Copyright 2022 NXP # SPDX-License-Identifier: Apache-2.0 -import math -import os -import sys import csv -import time -import signal import logging +import math +import os +import psutil +import re +import select import shlex +import signal import subprocess +import sys import threading -import select -import re -import psutil +import time + from twisterlib.environment import ZEPHYR_BASE from twisterlib.error import TwisterException sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/pylib/build_helpers")) @@ -55,7 +56,7 @@ def terminate_process(proc): for child in psutil.Process(proc.pid).children(recursive=True): try: os.kill(child.pid, signal.SIGTERM) - except ProcessLookupError: + except (ProcessLookupError, psutil.NoSuchProcess): pass proc.terminate() # sleep for a while before attempting to kill @@ -80,7 +81,6 @@ def __init__(self, instance, type_str="build"): self.name = instance.name self.instance = instance - self.timeout = math.ceil(instance.testsuite.timeout * instance.platform.timeout_multiplier) self.sourcedir = instance.testsuite.source_dir self.build_dir = instance.build_dir self.log = os.path.join(self.build_dir, "handler.log") @@ -93,6 +93,11 @@ def __init__(self, instance, type_str="build"): self.args = [] self.terminated = False + def get_test_timeout(self): + return math.ceil(self.instance.testsuite.timeout * + self.instance.platform.timeout_multiplier * + self.options.timeout_multiplier) + def record(self, harness): if harness.recording: filename = os.path.join(self.build_dir, "recording.csv") @@ -177,7 +182,7 @@ def try_kill_process_by_pid(self): self.pid_fn = None # clear so we don't try to kill the binary twice try: os.kill(pid, signal.SIGKILL) - except ProcessLookupError: + except (ProcessLookupError, psutil.NoSuchProcess): pass def _output_reader(self, proc): @@ -188,7 +193,7 @@ def _output_handler(self, proc, harness): with open(self.log, "wt") as log_out_fp: timeout_extended = False - timeout_time = time.time() + self.timeout + timeout_time = time.time() + self.get_test_timeout() while True: this_timeout = timeout_time - time.time() if this_timeout < 0: @@ -223,10 +228,7 @@ def _output_handler(self, proc, harness): except subprocess.TimeoutExpired: self.terminate(proc) - def handle(self, harness): - - robot_test = getattr(harness, "is_robot_test", False) - + def _create_command(self, robot_test): if robot_test: command = [self.generator_cmd, "run_renode_test"] elif self.call_make_run: @@ -236,7 +238,6 @@ def handle(self, harness): else: command = [self.binary] - run_valgrind = False if self.options.enable_valgrind: command = ["valgrind", "--error-exitcode=2", "--leak-check=full", @@ -244,20 +245,16 @@ def handle(self, harness): "--log-file=" + self.build_dir + "/valgrind.log", "--track-origins=yes", ] + command - run_valgrind = True - # Only valid for native_posix + # Only valid for native_sim if self.seed is not None: command.append(f"--seed={self.seed}") if self.extra_test_args is not None: command.extend(self.extra_test_args) - logger.debug("Spawning process: " + - " ".join(shlex.quote(word) for word in command) + os.linesep + - "in directory: " + self.build_dir) - - start_time = time.time() + return command + def _create_env(self): env = os.environ.copy() if self.options.enable_asan: env["ASAN_OPTIONS"] = "log_path=stdout:" + \ @@ -269,6 +266,40 @@ def handle(self, harness): env["UBSAN_OPTIONS"] = "log_path=stdout:halt_on_error=1:" + \ env.get("UBSAN_OPTIONS", "") + return env + + def _update_instance_info(self, harness_state, handler_time): + self.instance.execution_time = handler_time + if not self.terminated and self.returncode != 0: + self.instance.status = "failed" + if self.options.enable_valgrind and self.returncode == 2: + self.instance.reason = "Valgrind error" + else: + # When a process is killed, the default handler returns 128 + SIGTERM + # so in that case the return code itself is not meaningful + self.instance.reason = "Failed" + elif harness_state: + self.instance.status = harness_state + if harness_state == "failed": + self.instance.reason = "Failed" + else: + self.instance.status = "failed" + self.instance.reason = "Timeout" + self.instance.add_missing_case_status("blocked", "Timeout") + + def handle(self, harness): + robot_test = getattr(harness, "is_robot_test", False) + + command = self._create_command(robot_test) + + logger.debug("Spawning process: " + + " ".join(shlex.quote(word) for word in command) + os.linesep + + "in directory: " + self.build_dir) + + start_time = time.time() + + env = self._create_env() + if robot_test: harness.run_robot_test(command, self) return @@ -297,23 +328,7 @@ def handle(self, harness): if sys.stdout.isatty(): subprocess.call(["stty", "sane"], stdin=sys.stdout) - self.instance.execution_time = handler_time - if not self.terminated and self.returncode != 0: - self.instance.status = "failed" - if run_valgrind and self.returncode == 2: - self.instance.reason = "Valgrind error" - else: - # When a process is killed, the default handler returns 128 + SIGTERM - # so in that case the return code itself is not meaningful - self.instance.reason = "Failed" - elif harness.state: - self.instance.status = harness.state - if harness.state == "failed": - self.instance.reason = "Failed" - else: - self.instance.status = "failed" - self.instance.reason = "Timeout" - self.instance.add_missing_case_status("blocked", "Timeout") + self._update_instance_info(harness.state, handler_time) self._final_handle_actions(harness, handler_time) @@ -333,6 +348,7 @@ def __init__(self, instance, type_str): self.binary = os.path.join(instance.build_dir, "zephyr", "zephyr.exe") self.ready = True + class DeviceHandler(Handler): def __init__(self, instance, type_str): @@ -342,8 +358,15 @@ def __init__(self, instance, type_str): """ super().__init__(instance, type_str) + def get_test_timeout(self): + timeout = super().get_test_timeout() + if self.options.coverage: + # wait more for gcov data to be dumped on console + timeout += 120 + return timeout + def monitor_serial(self, ser, halt_event, harness): - log_out_fp = open(self.log, "wt") + log_out_fp = open(self.log, "wb") if self.options.coverage: # Set capture_coverage to True to indicate that right after @@ -395,7 +418,7 @@ def monitor_serial(self, ser, halt_event, harness): sl = serial_line.decode('utf-8', 'ignore').lstrip() logger.debug("DEVICE: {0}".format(sl.rstrip())) - log_out_fp.write(sl) + log_out_fp.write(sl.encode('utf-8')) log_out_fp.flush() harness.handle(sl.rstrip()) @@ -451,45 +474,7 @@ def run_custom_script(script, timeout): proc.communicate() logger.error("{} timed out".format(script)) - def get_hardware(self): - hardware = None - try: - hardware = self.device_is_available(self.instance) - while not hardware: - time.sleep(1) - hardware = self.device_is_available(self.instance) - except TwisterException as error: - self.instance.status = "failed" - self.instance.reason = str(error) - logger.error(self.instance.reason) - return hardware - - def handle(self, harness): - runner = None - hardware = self.get_hardware() - if hardware: - self.instance.dut = hardware.id - if not hardware: - return - - runner = hardware.runner or self.options.west_runner - serial_pty = hardware.serial_pty - - ser_pty_process = None - if serial_pty: - master, slave = pty.openpty() - try: - ser_pty_process = subprocess.Popen(re.split(',| ', serial_pty), stdout=master, stdin=master, stderr=master) - except subprocess.CalledProcessError as error: - logger.error("Failed to run subprocess {}, error {}".format(serial_pty, error.output)) - return - - serial_device = os.ttyname(slave) - else: - serial_device = hardware.serial - - logger.debug(f"Using serial device {serial_device} @ {hardware.baud} baud") - + def _create_command(self, runner, hardware): if (self.options.west_flash is not None) or runner: command = ["west", "flash", "--skip-rebuild", "-d", self.build_dir] command_extra_args = [] @@ -516,48 +501,55 @@ def handle(self, harness): command_extra_args.append(board_id) elif runner == "openocd" and product == "STM32 STLink": command_extra_args.append("--cmd-pre-init") - command_extra_args.append("hla_serial %s" % (board_id)) + command_extra_args.append("hla_serial %s" % board_id) elif runner == "openocd" and product == "STLINK-V3": command_extra_args.append("--cmd-pre-init") - command_extra_args.append("hla_serial %s" % (board_id)) + command_extra_args.append("hla_serial %s" % board_id) elif runner == "openocd" and product == "EDBG CMSIS-DAP": command_extra_args.append("--cmd-pre-init") - command_extra_args.append("cmsis_dap_serial %s" % (board_id)) + command_extra_args.append("cmsis_dap_serial %s" % board_id) elif runner == "jlink": - command.append("--tool-opt=-SelectEmuBySN %s" % (board_id)) + command.append("--tool-opt=-SelectEmuBySN %s" % board_id) elif runner == "stm32cubeprogrammer": - command.append("--tool-opt=sn=%s" % (board_id)) + command.append("--tool-opt=sn=%s" % board_id) # Receive parameters from runner_params field. if hardware.runner_params: for param in hardware.runner_params: command.append(param) - if command_extra_args != []: + if command_extra_args: command.append('--') command.extend(command_extra_args) else: command = [self.generator_cmd, "-C", self.build_dir, "flash"] - pre_script = hardware.pre_script - post_flash_script = hardware.post_flash_script - post_script = hardware.post_script + return command - if pre_script: - self.run_custom_script(pre_script, 30) + def _update_instance_info(self, harness_state, handler_time, flash_error): + self.instance.execution_time = handler_time + if harness_state: + self.instance.status = harness_state + if harness_state == "failed": + self.instance.reason = "Failed" + elif not flash_error: + self.instance.status = "failed" + self.instance.reason = "Timeout" - flash_timeout = hardware.flash_timeout - if hardware.flash_with_test: - flash_timeout += self.timeout + if self.instance.status in ["error", "failed"]: + self.instance.add_missing_case_status("blocked", self.instance.reason) + def _create_serial_connection(self, serial_device, hardware_baud, + flash_timeout, serial_pty, ser_pty_process): try: ser = serial.Serial( serial_device, - baudrate=hardware.baud, + baudrate=hardware_baud, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, - timeout=max(flash_timeout, self.timeout) # the worst case of no serial input + # the worst case of no serial input + timeout=max(flash_timeout, self.get_test_timeout()) ) except serial.SerialException as e: self.instance.status = "failed" @@ -574,6 +566,86 @@ def handle(self, harness): self.make_device_available(serial_pty) else: self.make_device_available(serial_device) + raise + + return ser + + def get_hardware(self): + hardware = None + try: + hardware = self.device_is_available(self.instance) + while not hardware: + time.sleep(1) + hardware = self.device_is_available(self.instance) + except TwisterException as error: + self.instance.status = "failed" + self.instance.reason = str(error) + logger.error(self.instance.reason) + return hardware + + def _get_serial_device(self, serial_pty, hardware_serial): + ser_pty_process = None + if serial_pty: + master, slave = pty.openpty() + try: + ser_pty_process = subprocess.Popen( + re.split('[, ]', serial_pty), + stdout=master, + stdin=master, + stderr=master + ) + except subprocess.CalledProcessError as error: + logger.error( + "Failed to run subprocess {}, error {}".format( + serial_pty, + error.output + ) + ) + return + + serial_device = os.ttyname(slave) + else: + serial_device = hardware_serial + + return serial_device, ser_pty_process + + def handle(self, harness): + runner = None + hardware = self.get_hardware() + if hardware: + self.instance.dut = hardware.id + if not hardware: + return + + runner = hardware.runner or self.options.west_runner + serial_pty = hardware.serial_pty + + serial_device, ser_pty_process = self._get_serial_device(serial_pty, hardware.serial) + + logger.debug(f"Using serial device {serial_device} @ {hardware.baud} baud") + + command = self._create_command(runner, hardware) + + pre_script = hardware.pre_script + post_flash_script = hardware.post_flash_script + post_script = hardware.post_script + + if pre_script: + self.run_custom_script(pre_script, 30) + + flash_timeout = hardware.flash_timeout + if hardware.flash_with_test: + flash_timeout += self.get_test_timeout() + + try: + ser = self._create_serial_connection( + serial_device, + hardware.baud, + flash_timeout, + serial_pty, + ser_pty_process + ) + except serial.SerialException: return halt_monitor_evt = threading.Event() @@ -592,7 +664,7 @@ def handle(self, harness): try: (stdout, stderr) = proc.communicate(timeout=flash_timeout) # ignore unencodable unicode chars - logger.debug(stdout.decode(errors = "ignore")) + logger.debug(stdout.decode(errors="ignore")) if proc.returncode != 0: self.instance.status = "error" @@ -623,7 +695,7 @@ def handle(self, harness): if not flash_error: # Always wait at most the test timeout here after flashing. - t.join(self.timeout) + t.join(self.get_test_timeout()) else: # When the flash error is due exceptions, # twister tell the monitor serial thread @@ -645,17 +717,7 @@ def handle(self, harness): handler_time = time.time() - start_time - self.instance.execution_time = handler_time - if harness.state: - self.instance.status = harness.state - if harness.state == "failed": - self.instance.reason = "Failed" - elif not flash_error: - self.instance.status = "failed" - self.instance.reason = "Timeout" - - if self.instance.status in ["error", "failed"]: - self.instance.add_missing_case_status("blocked", self.instance.reason) + self._update_instance_info(harness.state, handler_time, flash_error) self._final_handle_actions(harness, handler_time) @@ -667,6 +729,7 @@ def handle(self, harness): else: self.make_device_available(serial_device) + class QEMUHandler(Handler): """Spawns a thread to monitor QEMU output from pipes @@ -707,11 +770,14 @@ def _get_cpu_time(pid): return cpu_time.user + cpu_time.system @staticmethod - def _thread(handler, timeout, outdir, logfile, fifo_fn, pid_fn, results, harness, - ignore_unexpected_eof=False): + def _thread_get_fifo_names(fifo_fn): fifo_in = fifo_fn + ".in" fifo_out = fifo_fn + ".out" + return fifo_in, fifo_out + + @staticmethod + def _thread_open_files(fifo_in, fifo_out, logfile): # These in/out nodes are named from QEMU's perspective, not ours if os.path.exists(fifo_in): os.unlink(fifo_in) @@ -728,6 +794,51 @@ def _thread(handler, timeout, outdir, logfile, fifo_fn, pid_fn, results, harness in_fp = open(fifo_out, "rb", buffering=0) log_out_fp = open(logfile, "wt") + return out_fp, in_fp, log_out_fp + + @staticmethod + def _thread_close_files(fifo_in, fifo_out, pid, out_fp, in_fp, log_out_fp): + log_out_fp.close() + out_fp.close() + in_fp.close() + if pid: + try: + if pid: + os.kill(pid, signal.SIGTERM) + except (ProcessLookupError, psutil.NoSuchProcess): + # Oh well, as long as it's dead! User probably sent Ctrl-C + pass + + os.unlink(fifo_in) + os.unlink(fifo_out) + + @staticmethod + def _thread_update_instance_info(handler, handler_time, out_state): + handler.instance.execution_time = handler_time + if out_state == "timeout": + handler.instance.status = "failed" + handler.instance.reason = "Timeout" + elif out_state == "failed": + handler.instance.status = "failed" + handler.instance.reason = "Failed" + elif out_state in ['unexpected eof', 'unexpected byte']: + handler.instance.status = "failed" + handler.instance.reason = out_state + else: + handler.instance.status = out_state + handler.instance.reason = "Unknown" + + @staticmethod + def _thread(handler, timeout, outdir, logfile, fifo_fn, pid_fn, results, + harness, ignore_unexpected_eof=False): + fifo_in, fifo_out = QEMUHandler._thread_get_fifo_names(fifo_fn) + + out_fp, in_fp, log_out_fp = QEMUHandler._thread_open_files( + fifo_in, + fifo_out, + logfile + ) + start_time = time.time() timeout_time = start_time + timeout p = select.poll() @@ -746,13 +857,15 @@ def _thread(handler, timeout, outdir, logfile, fifo_fn, pid_fn, results, harness if this_timeout < 0 or not p.poll(this_timeout): try: if pid and this_timeout > 0: - #there's possibility we polled nothing because - #of not enough CPU time scheduled by host for - #QEMU process during p.poll(this_timeout) + # there's possibility we polled nothing because + # of not enough CPU time scheduled by host for + # QEMU process during p.poll(this_timeout) cpu_time = QEMUHandler._get_cpu_time(pid) if cpu_time < timeout and not out_state: timeout_time = time.time() + (timeout - cpu_time) continue + except psutil.NoSuchProcess: + pass except ProcessLookupError: out_state = "failed" break @@ -783,7 +896,7 @@ def _thread(handler, timeout, outdir, logfile, fifo_fn, pid_fn, results, harness # line contains a full line of data output from QEMU log_out_fp.write(line) log_out_fp.flush() - line = line.strip() + line = line.rstrip() logger.debug(f"QEMU ({pid}): {line}") harness.handle(line) @@ -810,64 +923,64 @@ def _thread(handler, timeout, outdir, logfile, fifo_fn, pid_fn, results, harness handler_time = time.time() - start_time logger.debug(f"QEMU ({pid}) complete ({out_state}) after {handler_time} seconds") - handler.instance.execution_time = handler_time - if out_state == "timeout": - handler.instance.status = "failed" - handler.instance.reason = "Timeout" - elif out_state == "failed": - handler.instance.status = "failed" - handler.instance.reason = "Failed" - elif out_state in ['unexpected eof', 'unexpected byte']: - handler.instance.status = "failed" - handler.instance.reason = out_state - else: - handler.instance.status = out_state - handler.instance.reason = "Unknown" - - log_out_fp.close() - out_fp.close() - in_fp.close() - if pid: - try: - if pid: - os.kill(pid, signal.SIGTERM) - except ProcessLookupError: - # Oh well, as long as it's dead! User probably sent Ctrl-C - pass - - os.unlink(fifo_in) - os.unlink(fifo_out) + QEMUHandler._thread_update_instance_info(handler, handler_time, out_state) - def handle(self, harness): - self.results = {} - self.run = True - - # We pass this to QEMU which looks for fifos with .in and .out - # suffixes. + QEMUHandler._thread_close_files(fifo_in, fifo_out, pid, out_fp, in_fp, log_out_fp) + def _get_sysbuild_build_dir(self): if self.instance.testsuite.sysbuild: # Load domain yaml to get default domain build directory # Note: for targets using QEMU, we assume that the target will # have added any additional images to the run target manually domain_path = os.path.join(self.build_dir, "domains.yaml") domains = Domains.from_file(domain_path) - logger.debug("Loaded sysbuild domain data from %s" % (domain_path)) + logger.debug("Loaded sysbuild domain data from %s" % domain_path) build_dir = domains.get_default_domain().build_dir else: build_dir = self.build_dir + return build_dir + + def _set_qemu_filenames(self, sysbuild_build_dir): + # We pass this to QEMU which looks for fifos with .in and .out suffixes. # QEMU fifo will use main build dir self.fifo_fn = os.path.join(self.instance.build_dir, "qemu-fifo") # PID file will be created in the main sysbuild app's build dir - self.pid_fn = os.path.join(build_dir, "qemu.pid") + self.pid_fn = os.path.join(sysbuild_build_dir, "qemu.pid") if os.path.exists(self.pid_fn): os.unlink(self.pid_fn) self.log_fn = self.log + def _create_command(self, sysbuild_build_dir): + command = [self.generator_cmd] + command += ["-C", sysbuild_build_dir, "run"] + + return command + + def _update_instance_info(self, harness_state, is_timeout): + if (self.returncode != 0 and not self.ignore_qemu_crash) or not harness_state: + self.instance.status = "failed" + if is_timeout: + self.instance.reason = "Timeout" + else: + if not self.instance.reason: + self.instance.reason = "Exited with {}".format(self.returncode) + self.instance.add_missing_case_status("blocked") + + def handle(self, harness): + self.results = {} + self.run = True + + sysbuild_build_dir = self._get_sysbuild_build_dir() + + command = self._create_command(sysbuild_build_dir) + + self._set_qemu_filenames(sysbuild_build_dir) + self.thread = threading.Thread(name=self.name, target=QEMUHandler._thread, - args=(self, self.timeout, self.build_dir, + args=(self, self.get_test_timeout(), self.build_dir, self.log_fn, self.fifo_fn, self.pid_fn, self.results, harness, self.ignore_unexpected_eof)) @@ -879,8 +992,6 @@ def handle(self, harness): subprocess.call(["stty", "sane"], stdin=sys.stdout) logger.debug("Running %s (%s)" % (self.name, self.type_str)) - command = [self.generator_cmd] - command += ["-C", build_dir, "run"] is_timeout = False qemu_pid = None @@ -889,7 +1000,7 @@ def handle(self, harness): logger.debug("Spawning QEMUHandler Thread for %s" % self.name) try: - proc.wait(self.timeout) + proc.wait(self.get_test_timeout()) except subprocess.TimeoutExpired: # sometimes QEMU can't handle SIGTERM signal correctly # in that case kill -9 QEMU process directly and leave @@ -919,14 +1030,7 @@ def handle(self, harness): logger.debug(f"return code from QEMU ({qemu_pid}): {self.returncode}") - if (self.returncode != 0 and not self.ignore_qemu_crash) or not harness.state: - self.instance.status = "failed" - if is_timeout: - self.instance.reason = "Timeout" - else: - if not self.instance.reason: - self.instance.reason = "Exited with {}".format(self.returncode) - self.instance.add_missing_case_status("blocked") + self._update_instance_info(harness.state, is_timeout) self._final_handle_actions(harness, 0) diff --git a/scripts/pylib/twister/twisterlib/harness.py b/scripts/pylib/twister/twisterlib/harness.py index edb053232b9..8b8ad92fc51 100644 --- a/scripts/pylib/twister/twisterlib/harness.py +++ b/scripts/pylib/twister/twisterlib/harness.py @@ -13,6 +13,7 @@ import threading import time +from twisterlib.error import ConfigurationError from twisterlib.environment import ZEPHYR_BASE, PYTEST_PLUGIN_INSTALLED from twisterlib.handlers import Handler, terminate_process, SUPPORTED_SIMS_IN_PYTEST from twisterlib.testinstance import TestInstance @@ -143,10 +144,15 @@ def run_robot_test(self, command, handler): if cmake_proc.returncode == 0: self.instance.status = "passed" + # all tests in one Robot file are treated as a single test case, + # so its status should be set accordingly to the instance status + # please note that there should be only one testcase in testcases list + self.instance.testcases[0].status = "passed" else: logger.error("Robot test failure: %s for %s" % (handler.sourcedir, self.instance.platform.name)) self.instance.status = "failed" + self.instance.testcases[0].status = "failed" if out: with open(os.path.join(self.instance.build_dir, handler.log), "wt") as log: @@ -155,22 +161,60 @@ def run_robot_test(self, command, handler): class Console(Harness): + def get_testcase_name(self): + ''' + Get current TestCase name. + + Console Harness id has only TestSuite id without TestCase name suffix. + Only the first TestCase name might be taken if available when a Ztest with + a single test case is configured to use this harness type for simplified + output parsing instead of the Ztest harness as Ztest suite should do. + ''' + if self.instance and len(self.instance.testcases) == 1: + return self.instance.testcases[0].name + return self.id + def configure(self, instance): super(Console, self).configure(instance) + if self.regex is None or len(self.regex) == 0: + self.state = "failed" + tc = self.instance.set_case_status_by_name( + self.get_testcase_name(), + "failed", + f"HARNESS:{self.__class__.__name__}:no regex patterns configured." + ) + raise ConfigurationError(self.instance.name, tc.reason) if self.type == "one_line": self.pattern = re.compile(self.regex[0]) + self.patterns_expected = 1 elif self.type == "multi_line": self.patterns = [] for r in self.regex: self.patterns.append(re.compile(r)) + self.patterns_expected = len(self.patterns) + else: + self.state = "failed" + tc = self.instance.set_case_status_by_name( + self.get_testcase_name(), + "failed", + f"HARNESS:{self.__class__.__name__}:incorrect type={self.type}" + ) + raise ConfigurationError(self.instance.name, tc.reason) + # def handle(self, line): if self.type == "one_line": if self.pattern.search(line): + logger.debug(f"HARNESS:{self.__class__.__name__}:EXPECTED:" + f"'{self.pattern.pattern}'") + self.next_pattern += 1 self.state = "passed" elif self.type == "multi_line" and self.ordered: if (self.next_pattern < len(self.patterns) and self.patterns[self.next_pattern].search(line)): + logger.debug(f"HARNESS:{self.__class__.__name__}:EXPECTED(" + f"{self.next_pattern + 1}/{self.patterns_expected}):" + f"'{self.patterns[self.next_pattern].pattern}'") self.next_pattern += 1 if self.next_pattern >= len(self.patterns): self.state = "passed" @@ -179,6 +223,9 @@ def handle(self, line): r = self.regex[i] if pattern.search(line) and not r in self.matches: self.matches[r] = line + logger.debug(f"HARNESS:{self.__class__.__name__}:EXPECTED(" + f"{len(self.matches)}/{self.patterns_expected}):" + f"'{pattern.pattern}'") if len(self.matches) == len(self.regex): self.state = "passed" else: @@ -208,8 +255,25 @@ def handle(self, line): self.recording.append(csv) self.process_test(line) + # Reset the resulting test state to 'failed' when not all of the patterns were + # found in the output, but just ztest's 'PROJECT EXECUTION SUCCESSFUL'. + # It might happen because of the pattern sequence diverged from the + # test code, the test platform has console issues, or even some other + # test image was executed. + # TODO: Introduce explicit match policy type to reject + # unexpected console output, allow missing patterns, deny duplicates. + if self.state == "passed" and self.ordered and self.next_pattern < self.patterns_expected: + logger.error(f"HARNESS:{self.__class__.__name__}: failed with" + f" {self.next_pattern} of {self.patterns_expected}" + f" expected ordered patterns.") + self.state = "failed" + if self.state == "passed" and not self.ordered and len(self.matches) < self.patterns_expected: + logger.error(f"HARNESS:{self.__class__.__name__}: failed with" + f" {len(self.matches)} of {self.patterns_expected}" + f" expected unordered patterns.") + self.state = "failed" - tc = self.instance.get_case_or_create(self.id) + tc = self.instance.get_case_or_create(self.get_testcase_name()) if self.state == "passed": tc.status = "passed" else: @@ -441,17 +505,23 @@ def _parse_report_file(self, report): class Gtest(Harness): ANSI_ESCAPE = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])') - TEST_START_PATTERN = r"\[ RUN \] (?P.*)\.(?P.*)$" - TEST_PASS_PATTERN = r"\[ OK \] (?P.*)\.(?P.*)$" - TEST_FAIL_PATTERN = r"\[ FAILED \] (?P.*)\.(?P.*)$" - FINISHED_PATTERN = r"\[==========\] Done running all tests\.$" - has_failures = False - tc = None + TEST_START_PATTERN = r".*\[ RUN \] (?P.*)\.(?P.*)$" + TEST_PASS_PATTERN = r".*\[ OK \] (?P.*)\.(?P.*)$" + TEST_FAIL_PATTERN = r".*\[ FAILED \] (?P.*)\.(?P.*)$" + FINISHED_PATTERN = r".*\[==========\] Done running all tests\.$" + + def __init__(self): + super().__init__() + self.tc = None + self.has_failures = False def handle(self, line): # Strip the ANSI characters, they mess up the patterns non_ansi_line = self.ANSI_ESCAPE.sub('', line) + if self.state: + return + # Check if we started running a new test test_start_match = re.search(self.TEST_START_PATTERN, non_ansi_line) if test_start_match: diff --git a/scripts/pylib/twister/twisterlib/platform.py b/scripts/pylib/twister/twisterlib/platform.py index fbbd10523b1..f3773ef4c67 100644 --- a/scripts/pylib/twister/twisterlib/platform.py +++ b/scripts/pylib/twister/twisterlib/platform.py @@ -36,6 +36,8 @@ def __init__(self): self.supported = set() self.arch = "" + self.vendor = "" + self.tier = -1 self.type = "na" self.simulation = "na" self.simulation_exec = None @@ -67,6 +69,8 @@ def load(self, platform_file): self.supported.add(item) self.arch = data['arch'] + self.vendor = data.get('vendor', '') + self.tier = data.get("tier", -1) self.type = data.get('type', "na") self.simulation = data.get('simulation', "na") self.simulation_exec = data.get('simulation_exec') diff --git a/scripts/pylib/twister/twisterlib/quarantine.py b/scripts/pylib/twister/twisterlib/quarantine.py index cb05a920ca6..e4baa52781e 100644 --- a/scripts/pylib/twister/twisterlib/quarantine.py +++ b/scripts/pylib/twister/twisterlib/quarantine.py @@ -41,6 +41,10 @@ class QuarantineElement: architectures: list[str] = field(default_factory=list) simulations: list[str] = field(default_factory=list) comment: str = 'NA' + re_scenarios: list = field(default_factory=list) + re_platforms: list = field(default_factory=list) + re_architectures: list = field(default_factory=list) + re_simulations: list = field(default_factory=list) def __post_init__(self): # If there is no entry in filters then take all possible values. @@ -53,6 +57,12 @@ def __post_init__(self): self.architectures = [] if 'all' in self.simulations: self.simulations = [] + # keep precompiled regexp entiries to speed-up matching + self.re_scenarios = [re.compile(pat) for pat in self.scenarios] + self.re_platforms = [re.compile(pat) for pat in self.platforms] + self.re_architectures = [re.compile(pat) for pat in self.architectures] + self.re_simulations = [re.compile(pat) for pat in self.simulations] + # However, at least one of the filters ('scenarios', platforms' ...) # must be given (there is no sense to put all possible configuration # into quarantine) @@ -101,16 +111,16 @@ def get_matched_quarantine(self, for qelem in self.qlist: matched: bool = False if (qelem.scenarios - and (matched := _is_element_matched(scenario, qelem.scenarios)) is False): + and (matched := _is_element_matched(scenario, qelem.re_scenarios)) is False): continue if (qelem.platforms - and (matched := _is_element_matched(platform, qelem.platforms)) is False): + and (matched := _is_element_matched(platform, qelem.re_platforms)) is False): continue if (qelem.architectures - and (matched := _is_element_matched(architecture, qelem.architectures)) is False): + and (matched := _is_element_matched(architecture, qelem.re_architectures)) is False): continue if (qelem.simulations - and (matched := _is_element_matched(simulation, qelem.simulations)) is False): + and (matched := _is_element_matched(simulation, qelem.re_simulations)) is False): continue if matched: @@ -118,9 +128,9 @@ def get_matched_quarantine(self, return None -def _is_element_matched(element: str, list_of_elements: list) -> bool: +def _is_element_matched(element: str, list_of_elements: list[re.Pattern]) -> bool: """Return True if given element is matching to any of elements from the list""" for pattern in list_of_elements: - if re.fullmatch(pattern, element): + if pattern.fullmatch(element): return True return False diff --git a/scripts/pylib/twister/twisterlib/runner.py b/scripts/pylib/twister/twisterlib/runner.py index 4dbdb21f882..3471f6bf702 100644 --- a/scripts/pylib/twister/twisterlib/runner.py +++ b/scripts/pylib/twister/twisterlib/runner.py @@ -25,7 +25,7 @@ from domains import Domains from twisterlib.cmakecache import CMakeCache from twisterlib.environment import canonical_zephyr_base -from twisterlib.error import BuildError +from twisterlib.error import BuildError, ConfigurationError import elftools from elftools.elf.elffile import ELFFile @@ -1053,10 +1053,13 @@ def run(self): instance = self.instance if instance.handler.ready: + logger.debug(f"Reset instance status from '{instance.status}' to None before run.") + instance.status = None + if instance.handler.type_str == "device": instance.handler.duts = self.duts - if(self.options.seed is not None and instance.platform.name.startswith("native_posix")): + if(self.options.seed is not None and instance.platform.name.startswith("native_")): self.parse_generated() if('CONFIG_FAKE_ENTROPY_NATIVE_POSIX' in self.defconfig and self.defconfig['CONFIG_FAKE_ENTROPY_NATIVE_POSIX'] == 'y'): @@ -1066,15 +1069,24 @@ def run(self): instance.handler.extra_test_args = self.options.extra_test_args harness = HarnessImporter.get_harness(instance.testsuite.harness.capitalize()) - harness.configure(instance) + try: + harness.configure(instance) + except ConfigurationError as error: + instance.status = "error" + instance.reason = str(error) + logger.error(instance.reason) + return + # if isinstance(harness, Pytest): - harness.pytest_run(instance.handler.timeout) + harness.pytest_run(instance.handler.get_test_timeout()) else: instance.handler.handle(harness) sys.stdout.flush() def gather_metrics(self, instance: TestInstance): + if self.options.create_rom_ram_report: + self.run_build(['--build', self.build_dir, "--target", "footprint"]) if self.options.enable_size_report and not self.options.cmake_only: self.calc_size(instance=instance, from_buildlog=self.options.footprint_from_buildlog) else: diff --git a/scripts/pylib/twister/twisterlib/size_calc.py b/scripts/pylib/twister/twisterlib/size_calc.py index 29d8ee2542e..f449d26ac99 100644 --- a/scripts/pylib/twister/twisterlib/size_calc.py +++ b/scripts/pylib/twister/twisterlib/size_calc.py @@ -78,7 +78,7 @@ class SizeCalculator: "ctors", "init_array", "reset", - "z_object_assignment_area", + "k_object_assignment_area", "rodata", "net_l2", "vector", @@ -257,9 +257,9 @@ def _get_info_elf_sections(self) -> None: # If build.log file exists, check errors (unrecognized sections # in ELF file). if self.buildlog_filename: - if name in SizeCalculator.alloc_sections or\ - SizeCalculator.rw_sections or\ - SizeCalculator.ro_sections: + if name in SizeCalculator.alloc_sections or \ + name in SizeCalculator.rw_sections or \ + name in SizeCalculator.ro_sections: continue else: stype = "unknown" diff --git a/scripts/pylib/twister/twisterlib/testinstance.py b/scripts/pylib/twister/twisterlib/testinstance.py index b9e7d411cb5..958019b411a 100644 --- a/scripts/pylib/twister/twisterlib/testinstance.py +++ b/scripts/pylib/twister/twisterlib/testinstance.py @@ -190,7 +190,7 @@ def setup_handler(self, env): self.handler = handler # Global testsuite parameters - def check_runnable(self, enable_slow=False, filter='buildable', fixtures=[]): + def check_runnable(self, enable_slow=False, filter='buildable', fixtures=[], hardware_map=None): # running on simulators is currently not supported on Windows if os.name == 'nt' and self.platform.simulation != 'na': @@ -223,6 +223,13 @@ def check_runnable(self, enable_slow=False, filter='buildable', fixtures=[]): testsuite_runnable = self.testsuite_runnable(self.testsuite, fixtures) + if hardware_map: + for h in hardware_map.duts: + if (h.platform == self.platform.name and + self.testsuite_runnable(self.testsuite, h.fixtures)): + testsuite_runnable = True + break + return testsuite_runnable and target_ready def create_overlay(self, platform, enable_asan=False, enable_ubsan=False, enable_coverage=False, coverage_platform=[]): diff --git a/scripts/pylib/twister/twisterlib/testplan.py b/scripts/pylib/twister/twisterlib/testplan.py index ae122862d1e..930d4573b19 100755 --- a/scripts/pylib/twister/twisterlib/testplan.py +++ b/scripts/pylib/twister/twisterlib/testplan.py @@ -50,6 +50,8 @@ import scl class Filters: + # platform keys + PLATFORM_KEY = 'platform key filter' # filters provided on command line by the user/tester CMD_LINE = 'command line filter' # filters in the testsuite yaml definition @@ -60,6 +62,10 @@ class Filters: QUARENTINE = 'Quarantine filter' # in case a test suite is skipped intentionally . SKIP = 'Skip filter' + # in case of incompatibility between selected and allowed toolchains. + TOOLCHAIN = 'Toolchain filter' + # in case an optional module is not available + MODULE = 'Module filter' class TestLevel: @@ -194,8 +200,11 @@ def discover(self): raise TwisterRuntimeError("No quarantine list given to be verified") if ql: for quarantine_file in ql: - # validate quarantine yaml file against the provided schema - scl.yaml_load_verify(quarantine_file, self.quarantine_schema) + try: + # validate quarantine yaml file against the provided schema + scl.yaml_load_verify(quarantine_file, self.quarantine_schema) + except scl.EmptyYamlFileException: + logger.debug(f'Quarantine file {quarantine_file} is empty') self.quarantine = Quarantine(ql) def load(self): @@ -212,15 +221,14 @@ def load(self): self.load_from_file(self.options.load_tests) self.selected_platforms = set(p.platform.name for p in self.instances.values()) elif self.options.test_only: - # Get list of connected hardware and filter tests to only be run on connected hardware - # in cases where no platform was specified when running the tests. - # If the platform does not exist in the hardware map, just skip it. - connected_list = [] - if not self.options.platform: - for connected in self.hwm.duts: - if connected['connected']: - connected_list.append(connected['platform']) - + # Get list of connected hardware and filter tests to only be run on connected hardware. + # If the platform does not exist in the hardware map or was not specified by --platform, + # just skip it. + connected_list = self.options.platform + if self.options.exclude_platform: + for excluded in self.options.exclude_platform: + if excluded in connected_list: + connected_list.remove(excluded) self.load_from_file(last_run, filter_platform=connected_list) self.selected_platforms = set(p.platform.name for p in self.instances.values()) else: @@ -377,36 +385,6 @@ def report_test_list(self): print("{} total.".format(cnt)) - - def report_excluded_tests(self): - all_tests = self.get_all_tests() - to_be_run = set() - for _, p in self.instances.items(): - to_be_run.update(p.testsuite.cases) - - if all_tests - to_be_run: - print("Tests that never build or run:") - for not_run in all_tests - to_be_run: - print("- {}".format(not_run)) - - def report_platform_tests(self, platforms=[]): - if len(platforms) > 1: - raise TwisterRuntimeError("When exporting tests, only one platform " - "should be specified.") - - for p in platforms: - inst = self.get_platform_instances(p) - count = 0 - for i in inst.values(): - for c in i.testsuite.cases: - print(f"- {c}") - count += 1 - print(f"Tests found: {count}") - - def get_platform_instances(self, platform): - filtered_dict = {k:v for k,v in self.instances.items() if k.startswith(platform + os.sep)} - return filtered_dict - def config(self): logger.info("coverage platform: {}".format(self.coverage_platform)) @@ -449,7 +427,7 @@ def add_configurations(self): # if there is already an existed _.yaml, then use it to # load platform directly, otherwise, iterate the directory to # get all valid board revision based on each _.conf. - if not "@" in platform.name: + if '@' not in platform.name: tmp_dir = os.listdir(os.path.dirname(file)) for item in tmp_dir: # Need to make sure the revision matches @@ -570,7 +548,8 @@ def load_from_file(self, file, filter_platform=[]): instance.run = instance.check_runnable( self.options.enable_slow, tfilter, - self.options.fixture + self.options.fixture, + self.hwm ) instance.metrics['handler_time'] = ts.get('execution_time', 0) @@ -617,6 +596,7 @@ def apply_filters(self, **kwargs): toolchain = self.env.toolchain platform_filter = self.options.platform + vendor_filter = self.options.vendor exclude_platform = self.options.exclude_platform testsuite_filter = self.run_individual_testsuite arch_filter = self.options.arch @@ -631,29 +611,36 @@ def apply_filters(self, **kwargs): emu_filter = self.options.emulation_only logger.debug("platform filter: " + str(platform_filter)) + logger.debug(" vendor filter: " + str(vendor_filter)) logger.debug(" arch_filter: " + str(arch_filter)) logger.debug(" tag_filter: " + str(tag_filter)) logger.debug(" exclude_tag: " + str(exclude_tag)) default_platforms = False + vendor_platforms = False emulation_platforms = False if all_filter: logger.info("Selecting all possible platforms per test case") # When --all used, any --platform arguments ignored platform_filter = [] - elif not platform_filter and not emu_filter: + elif not platform_filter and not emu_filter and not vendor_filter: logger.info("Selecting default platforms per test case") default_platforms = True elif emu_filter: logger.info("Selecting emulation platforms per test case") emulation_platforms = True + elif vendor_filter: + vendor_platforms = True if platform_filter: self.verify_platforms_existence(platform_filter, f"platform_filter") platforms = list(filter(lambda p: p.name in platform_filter, self.platforms)) elif emu_filter: platforms = list(filter(lambda p: p.simulation != 'na', self.platforms)) + elif vendor_filter: + platforms = list(filter(lambda p: p.vendor in vendor_filter, self.platforms)) + logger.info(f"Selecting platforms by vendors: {','.join(vendor_filter)}") elif arch_filter: platforms = list(filter(lambda p: p.arch in arch_filter, self.platforms)) elif default_platforms: @@ -700,8 +687,6 @@ def apply_filters(self, **kwargs): if not c: platform_scope = list(filter(lambda item: item.name in ts.platform_allow, \ self.platforms)) - - # list of instances per testsuite, aka configurations. instance_list = [] for plat in platform_scope: @@ -714,13 +699,9 @@ def apply_filters(self, **kwargs): instance.run = instance.check_runnable( self.options.enable_slow, tfilter, - self.options.fixture + self.options.fixture, + self.hwm ) - if runnable and self.hwm.duts: - for h in self.hwm.duts: - if h.platform == plat.name: - if ts.harness_config.get('fixture') in h.fixtures: - instance.run = True if not force_platform and plat.name in exclude_platform: instance.add_filter("Platform is excluded on command line.", Filters.CMD_LINE) @@ -731,7 +712,7 @@ def apply_filters(self, **kwargs): if ts.modules and self.modules: if not set(ts.modules).issubset(set(self.modules)): - instance.add_filter(f"one or more required modules not available: {','.join(ts.modules)}", Filters.TESTSUITE) + instance.add_filter(f"one or more required modules not available: {','.join(ts.modules)}", Filters.MODULE) if self.options.level: tl = self.get_level(self.options.level) @@ -775,7 +756,7 @@ def apply_filters(self, **kwargs): instance.add_filter("In test case platform exclude", Filters.TESTSUITE) if ts.toolchain_exclude and toolchain in ts.toolchain_exclude: - instance.add_filter("In test case toolchain exclude", Filters.TESTSUITE) + instance.add_filter("In test case toolchain exclude", Filters.TOOLCHAIN) if platform_filter and plat.name not in platform_filter: instance.add_filter("Command line platform filter", Filters.CMD_LINE) @@ -789,7 +770,7 @@ def apply_filters(self, **kwargs): instance.add_filter("Not in testsuite platform type list", Filters.TESTSUITE) if ts.toolchain_allow and toolchain not in ts.toolchain_allow: - instance.add_filter("Not in testsuite toolchain allow list", Filters.TESTSUITE) + instance.add_filter("Not in testsuite toolchain allow list", Filters.TOOLCHAIN) if not plat.env_satisfied: instance.add_filter("Environment ({}) not satisfied".format(", ".join(plat.env)), Filters.PLATFORM) @@ -882,7 +863,7 @@ def apply_filters(self, **kwargs): keyed_test = keyed_tests.get(test_key) if keyed_test is not None: plat_key = {key_field: getattr(keyed_test['plat'], key_field) for key_field in key_fields} - instance.add_filter(f"Excluded test already covered for key {tuple(key)} by platform {keyed_test['plat'].name} having key {plat_key}", Filters.TESTSUITE) + instance.add_filter(f"Excluded test already covered for key {tuple(key)} by platform {keyed_test['plat'].name} having key {plat_key}", Filters.PLATFORM_KEY) else: keyed_tests[test_key] = {'plat': plat, 'ts': ts} else: @@ -928,7 +909,11 @@ def apply_filters(self, **kwargs): elif emulation_platforms: self.add_instances(instance_list) for instance in list(filter(lambda inst: not inst.platform.simulation != 'na', instance_list)): - instance.add_filter("Not an emulated platform", Filters.PLATFORM) + instance.add_filter("Not an emulated platform", Filters.CMD_LINE) + elif vendor_platforms: + self.add_instances(instance_list) + for instance in list(filter(lambda inst: not inst.platform.vendor in vendor_filter, instance_list)): + instance.add_filter("Not a selected vendor platform", Filters.CMD_LINE) else: self.add_instances(instance_list) @@ -1016,12 +1001,14 @@ def _create_build_dir_link(self, links_dir_path, instance): def change_skip_to_error_if_integration(options, instance): - ''' If integration mode is on all skips on integration_platforms are treated as errors.''' - if options.integration and instance.platform.name in instance.testsuite.integration_platforms \ + ''' All skips on integration_platforms are treated as errors.''' + if instance.platform.name in instance.testsuite.integration_platforms \ and "quarantine" not in instance.reason.lower(): # Do not treat this as error if filter type is command line filters = {t['type'] for t in instance.filters} - if Filters.CMD_LINE in filters or Filters.SKIP in filters: + ignore_filters ={Filters.CMD_LINE, Filters.SKIP, Filters.PLATFORM_KEY, + Filters.TOOLCHAIN, Filters.MODULE} + if filters.intersection(ignore_filters): return instance.status = "error" instance.reason += " but is one of the integration platforms" diff --git a/scripts/pylib/twister/twisterlib/testsuite.py b/scripts/pylib/twister/twisterlib/testsuite.py index 39c21098718..419d0f39596 100644 --- a/scripts/pylib/twister/twisterlib/testsuite.py +++ b/scripts/pylib/twister/twisterlib/testsuite.py @@ -256,6 +256,28 @@ def _find_ztest_testcases(search_area, testcase_regex): return testcase_names, warnings +def find_c_files_in(path: str, extensions: list = ['c', 'cpp', 'cxx', 'cc']) -> list: + """ + Find C or C++ sources in the directory specified by "path" + """ + if not os.path.isdir(path): + return [] + + # back up previous CWD + oldpwd = os.getcwd() + os.chdir(path) + + filenames = [] + for ext in extensions: + # glob.glob('**/*.c') does not pick up the base directory + filenames += [os.path.join(path, x) for x in glob.glob(f'*.{ext}')] + # glob matches in subdirectories too + filenames += [os.path.join(path, x) for x in glob.glob(f'**/*.{ext}')] + + # restore previous CWD + os.chdir(oldpwd) + + return filenames def scan_testsuite_path(testsuite_path): subcases = [] @@ -265,7 +287,7 @@ def scan_testsuite_path(testsuite_path): ztest_suite_names = [] src_dir_path = _find_src_dir_path(testsuite_path) - for filename in glob.glob(os.path.join(src_dir_path, "*.c*")): + for filename in find_c_files_in(src_dir_path): if os.stat(filename).st_size == 0: continue try: @@ -288,7 +310,7 @@ def scan_testsuite_path(testsuite_path): except ValueError as e: logger.error("%s: error parsing source file: %s" % (filename, e)) - for filename in glob.glob(os.path.join(testsuite_path, "*.c*")): + for filename in find_c_files_in(testsuite_path): try: result: ScanPathResult = scan_file(filename) if result.warnings: @@ -428,7 +450,7 @@ def get_unique(testsuite_root, workdir, name): relative_ts_root = "" # workdir can be "." - unique = os.path.normpath(os.path.join(relative_ts_root, workdir, name)) + unique = os.path.normpath(os.path.join(relative_ts_root, workdir, name)).replace(os.sep, '/') return unique @staticmethod diff --git a/scripts/pylib/twister/twisterlib/twister_main.py b/scripts/pylib/twister/twisterlib/twister_main.py index 336c95f3609..30656544b94 100644 --- a/scripts/pylib/twister/twisterlib/twister_main.py +++ b/scripts/pylib/twister/twisterlib/twister_main.py @@ -131,10 +131,6 @@ def main(options): logger.error(f"{e}") return 1 - if options.list_tests and options.platform: - tplan.report_platform_tests(options.platform) - return 0 - if VERBOSE > 1: # if we are using command line platform filter, no need to list every # other platform as excluded, we know that already. @@ -155,10 +151,6 @@ def main(options): ) ) - if options.report_excluded: - tplan.report_excluded_tests() - return 0 - report = Reporting(tplan, env) plan_file = os.path.join(options.outdir, "testplan.json") if not os.path.exists(plan_file): @@ -207,9 +199,10 @@ def main(options): report.summary(runner.results, options.disable_unrecognized_section_test, duration) + coverage_completed = True if options.coverage: if not options.build_only: - run_coverage(tplan, options) + coverage_completed = run_coverage(tplan, options) else: logger.info("Skipping coverage report generation due to --build-only.") @@ -235,6 +228,7 @@ def main(options): runner.results.failed or runner.results.error or (tplan.warnings and options.warnings_as_errors) + or (options.coverage and not coverage_completed) ): return 1 diff --git a/scripts/requirements-build-test.txt b/scripts/requirements-build-test.txt index 79309a179cd..c0f808880fb 100644 --- a/scripts/requirements-build-test.txt +++ b/scripts/requirements-build-test.txt @@ -10,7 +10,7 @@ colorama ply>=3.10 # used for code coverage -gcovr>=4.2 +gcovr>=6.0 coverage # used for west-command testing diff --git a/scripts/requirements-extras.txt b/scripts/requirements-extras.txt index 969254e7835..f210f069de9 100644 --- a/scripts/requirements-extras.txt +++ b/scripts/requirements-extras.txt @@ -16,7 +16,7 @@ clang-format>=15.0.0 lpc_checksum # used by scripts/build/gen_cfb_font_header.py - helper script for user -Pillow +Pillow>=10.0 # can be used to sign a Zephyr application binary for consumption by a bootloader imgtool>=1.9 diff --git a/scripts/schemas/twister/platform-schema.yaml b/scripts/schemas/twister/platform-schema.yaml index 6524e5f8769..f1ba2d88748 100644 --- a/scripts/schemas/twister/platform-schema.yaml +++ b/scripts/schemas/twister/platform-schema.yaml @@ -41,6 +41,10 @@ mapping: type: str "arch": type: str + "vendor": + type: str + "tier": + type: int "toolchain": type: seq seq: diff --git a/scripts/set_assignees.py b/scripts/set_assignees.py index 2a4575eb3c4..269bde82f54 100755 --- a/scripts/set_assignees.py +++ b/scripts/set_assignees.py @@ -64,88 +64,98 @@ def process_pr(gh, maintainer_file, number): labels = set() area_counter = defaultdict(int) - maint = defaultdict(int) + found_maintainers = defaultdict(int) num_files = 0 all_areas = set() fn = list(pr.get_files()) + + manifest_change = False + for changed_file in fn: + if changed_file.filename in ['west.yml','submanifests/optional.yaml']: + manifest_change = True + break + + # one liner PRs should be trivial + if pr.commits == 1 and (pr.additions <= 1 and pr.deletions <= 1) and not manifest_change: + labels = {'trivial'} + if len(fn) > 500: log(f"Too many files changed ({len(fn)}), skipping....") return - for f in pr.get_files(): + + for changed_file in fn: num_files += 1 - log(f"file: {f.filename}") - areas = maintainer_file.path2areas(f.filename) - - if areas: - all_areas.update(areas) - for a in areas: - area_counter[a.name] += 1 - labels.update(a.labels) - for p in a.maintainers: - maint[p] += 1 - - ac = dict(sorted(area_counter.items(), key=lambda item: item[1], reverse=True)) - log(f"Area matches: {ac}") + log(f"file: {changed_file.filename}") + areas = maintainer_file.path2areas(changed_file.filename) + + if not areas: + continue + + all_areas.update(areas) + is_instance = False + sorted_areas = sorted(areas, key=lambda x: 'Platform' in x.name, reverse=True) + for area in sorted_areas: + c = 1 if not is_instance else 0 + + area_counter[area] += c + labels.update(area.labels) + # FIXME: Here we count the same file multiple times if it exists in + # multiple areas with same maintainer + for area_maintainer in area.maintainers: + found_maintainers[area_maintainer] += c + + if 'Platform' in area.name: + is_instance = True + + area_counter = dict(sorted(area_counter.items(), key=lambda item: item[1], reverse=True)) + log(f"Area matches: {area_counter}") log(f"labels: {labels}") # Create a list of collaborators ordered by the area match collab = list() - for a in ac: - collab += maintainer_file.areas[a].maintainers - collab += maintainer_file.areas[a].collaborators + for area in area_counter: + collab += maintainer_file.areas[area.name].maintainers + collab += maintainer_file.areas[area.name].collaborators collab = list(dict.fromkeys(collab)) log(f"collab: {collab}") - sm = dict(sorted(maint.items(), key=lambda item: item[1], reverse=True)) + _all_maintainers = dict(sorted(found_maintainers.items(), key=lambda item: item[1], reverse=True)) log(f"Submitted by: {pr.user.login}") - log(f"candidate maintainers: {sm}") - - maintainer = "None" - maintainers = list(sm.keys()) - - prop = 0 - if maintainers: - maintainer = maintainers[0] - - if len(ac) > 1 and list(ac.values())[0] == list(ac.values())[1]: - for aa in ac: - if 'Documentation' in aa: - log("++ With multiple areas of same weight including docs, take something else other than Documentation as the maintainer") - for a in all_areas: - if (a.name == aa and - a.maintainers and a.maintainers[0] == maintainer and - len(maintainers) > 1): - maintainer = maintainers[1] - elif 'Platform' in aa: - log("++ Platform takes precedence over subsystem...") - log(f"Set maintainer of area {aa}") - for a in all_areas: - if a.name == aa: - if a.maintainers: - maintainer = a.maintainers[0] - break - - - # if the submitter is the same as the maintainer, check if we have - # multiple maintainers - if pr.user.login == maintainer: - log("Submitter is same as Assignee, trying to find another assignee...") - aff = list(ac.keys())[0] - for a in all_areas: - if a.name == aff: - if len(a.maintainers) > 1: - maintainer = a.maintainers[1] - else: - log(f"This area has only one maintainer, keeping assignee as {maintainer}") - - prop = (maint[maintainer] / num_files) * 100 - if prop < 20: - maintainer = "None" - - log(f"Picked maintainer: {maintainer} ({prop:.2f}% ownership)") - log("+++++++++++++++++++++++++") + log(f"candidate maintainers: {_all_maintainers}") + + maintainers = list(_all_maintainers.keys()) + assignee = None + + # we start with areas with most files changed and pick the maintainer from the first one. + # if the first area is an implementation, i.e. driver or platform, we + # continue searching for any other areas + for area, count in area_counter.items(): + if count == 0: + continue + if len(area.maintainers) > 0: + assignee = area.maintainers[0] + + if 'Platform' not in area.name: + break + + # if the submitter is the same as the maintainer, check if we have + # multiple maintainers + if len(maintainers) > 1 and pr.user.login == assignee: + log("Submitter is same as Assignee, trying to find another assignee...") + aff = list(area_counter.keys())[0] + for area in all_areas: + if area.name == aff: + if len(area.maintainers) > 1: + assignee = area.maintainers[1] + else: + log(f"This area has only one maintainer, keeping assignee as {assignee}") + + if assignee: + prop = (found_maintainers[assignee] / num_files) * 100 + log(f"Picked assignee: {assignee} ({prop:.2f}% ownership)") + log("+++++++++++++++++++++++++") # Set labels if labels: @@ -197,9 +207,9 @@ def process_pr(gh, maintainer_file, number): ms = [] # assignees - if maintainer != 'None' and not pr.assignee: + if assignee and not pr.assignee: try: - u = gh.get_user(maintainer) + u = gh.get_user(assignee) ms.append(u) except GithubException: log(f"Error: Unknown user") @@ -286,7 +296,10 @@ def process_modules(gh, maintainers_file): log(f"No maintainers for: {area}") continue - log(f"Found {area}, maintainers={maintainers}") + collaborators = maintainers_file.areas[area].collaborators + + log(f"Found {area}, maintainers={maintainers}, collaborators={collaborators}") + repo_name = f"{args.org}/{project.name}" repos[repo_name] = maintainers_file.areas[area] @@ -309,9 +322,15 @@ def process_modules(gh, maintainers_file): area = repos[repo_name] for maintainer in area.maintainers: - log(f"Adding {maintainer} to {pull.html_url}") + log(f"Assigning {maintainer} to {pull.html_url}") if not args.dry_run: pull.add_to_assignees(maintainer) + pull.create_review_request(maintainer) + + for collaborator in area.collaborators: + log(f"Adding {collaborator} to {pull.html_url}") + if not args.dry_run: + pull.create_review_request(collaborator) def main(): diff --git a/scripts/spelling.txt b/scripts/spelling.txt index fd3c5170303..ffa9e7cb8e3 100644 --- a/scripts/spelling.txt +++ b/scripts/spelling.txt @@ -9,7 +9,12 @@ # abandonning||abandoning abigious||ambiguous +abitrary||arbitrary abitrate||arbitrate +abnornally||abnormally +abnrormal||abnormal +abord||abort +aboslute||absolute abov||above abreviated||abbreviated absense||absence @@ -17,6 +22,8 @@ absolut||absolute absoulte||absolute acccess||access acceess||access +accelaration||acceleration +accelearion||acceleration acceleratoin||acceleration accelleration||acceleration accesing||accessing @@ -25,6 +32,7 @@ accessable||accessible accesss||access accidentaly||accidentally accidentually||accidentally +acclerated||accelerated accoding||according accomodate||accommodate accomodates||accommodates @@ -34,8 +42,11 @@ accout||account accquire||acquire accquired||acquired accross||across +accumalate||accumulate +accumalator||accumulator acessable||accessible acess||access +acessing||accessing achitecture||architecture acient||ancient acitions||actions @@ -48,24 +59,36 @@ acording||according activete||activate actived||activated actualy||actually +actvie||active acumulating||accumulating +acumulative||accumulative acumulator||accumulator +acutally||actually adapater||adapter +adderted||asserted addional||additional additionaly||additionally +additonal||additional addres||address +adddress||address addreses||addresses addresss||address +addrress||address aditional||additional aditionally||additionally aditionaly||additionally adminstrative||administrative adress||address adresses||addresses +adrresses||addresses +advertisment||advertisement adviced||advised afecting||affecting againt||against agaist||against +aggreataon||aggregation +aggreation||aggregation +ajust||adjust albumns||albums alegorical||allegorical algined||aligned @@ -73,15 +96,19 @@ algorith||algorithm algorithmical||algorithmically algoritm||algorithm algoritms||algorithms +algorithmn||algorithm algorrithm||algorithm algorritm||algorithm aligment||alignment alignement||alignment allign||align alligned||aligned +alllocate||allocate +alloated||allocated allocatote||allocate allocatrd||allocated allocte||allocate +allocted||allocated allpication||application alocate||allocate alogirhtms||algorithms @@ -89,11 +116,17 @@ alogrithm||algorithm alot||a lot alow||allow alows||allows +alreay||already +alredy||already altough||although alue||value ambigious||ambiguous +ambigous||ambiguous amoung||among +amount of times||number of times amout||amount +amplifer||amplifier +amplifyer||amplifier an union||a union an user||a user an userspace||a userspace @@ -122,35 +155,56 @@ aquired||acquired aquisition||acquisition arbitary||arbitrary architechture||architecture +archtecture||architecture arguement||argument arguements||arguments +arithmatic||arithmetic aritmetic||arithmetic arne't||aren't arraival||arrival artifical||artificial artillary||artillery asign||assign +asser||assert assertation||assertion +assertting||asserting +assgined||assigned assiged||assigned assigment||assignment assigments||assignments assistent||assistant +assocaited||associated +assocating||associating assocation||association associcated||associated assotiated||associated +asssert||assert assum||assume assumtpion||assumption asuming||assuming asycronous||asynchronous +asychronous||asynchronous asynchnous||asynchronous +asynchronus||asynchronous +asynchromous||asynchronous +asymetric||asymmetric +asymmeric||asymmetric +atleast||at least atomatically||automatically atomicly||atomically atempt||attempt +atrributes||attributes attachement||attachment +attatch||attach attched||attached +attemp||attempt attemps||attempts +attemping||attempting +attepmpt||attempt +attnetion||attention attruibutes||attributes authentification||authentication +authenicated||authenticated automaticaly||automatically automaticly||automatically automatize||automate @@ -164,10 +218,12 @@ avaible||available availabe||available availabled||available availablity||availability +availaible||available availale||available availavility||availability availble||available availiable||available +availible||available avalable||available avaliable||available aysnc||async @@ -181,6 +237,7 @@ baloons||balloons bandwith||bandwidth banlance||balance batery||battery +battey||battery beacuse||because becasue||because becomming||becoming @@ -192,30 +249,57 @@ beter||better betweeen||between bianries||binaries bitmast||bitmask +bitwiedh||bitwidth boardcast||broadcast borad||board boundry||boundary brievely||briefly +brigde||bridge +broadcase||broadcast broadcat||broadcast +bufer||buffer +bufferred||buffered +bufufer||buffer cacluated||calculated +caculate||calculate caculation||calculation +cadidate||candidate +cahces||caches calender||calendar +calescing||coalescing calle||called callibration||calibration +callled||called +callser||caller calucate||calculate calulate||calculate cancelation||cancellation +cancle||cancel +cant||can't +cant'||can't +canot||cannot +cann't||can't +cannnot||cannot +capabiity||capability capabilites||capabilities +capabilties||capabilities +capabilty||capability capabitilies||capabilities +capablity||capability capatibilities||capabilities +capapbilities||capabilities +caputure||capture carefuly||carefully cariage||carriage +casued||caused catagory||category cehck||check challange||challenge challanges||challenges +chache||cache chanell||channel changable||changeable +chanined||chained channle||channel channnel||channel charachter||character @@ -226,6 +310,7 @@ charaters||characters charcter||character chcek||check chck||check +checksumed||checksummed checksuming||checksumming childern||children childs||children @@ -233,6 +318,7 @@ chiled||child chked||checked chnage||change chnages||changes +chnange||change chnnel||channel choosen||chosen chouse||chose @@ -241,6 +327,9 @@ claread||cleared clared||cleared closeing||closing clustred||clustered +cnfiguration||configuration +coexistance||coexistence +colescing||coalescing collapsable||collapsible colorfull||colorful comand||command @@ -251,14 +340,18 @@ comminucation||communication commited||committed commiting||committing committ||commit +commnunication||communication commoditiy||commodity comsume||consume comsumer||consumer comsuming||consuming +comaptible||compatible compability||compatibility compaibility||compatibility +comparsion||comparison compatability||compatibility compatable||compatible +compatibililty||compatibility compatibiliy||compatibility compatibilty||compatibility compatiblity||compatibility @@ -269,16 +362,29 @@ completition||completion completly||completely complient||compliant componnents||components +compoment||component +comppatible||compatible compres||compress compresion||compression +compresser||compressor comression||compression +comsumed||consumed +comunicate||communicate comunication||communication conbination||combination concurent||concurrent conditionaly||conditionally +conditon||condition +condtion||condition +condtional||conditional conected||connected connecetd||connected +conector||connector +configration||configuration +configred||configured configuartion||configuration +configuation||configuration +configued||configured configuratoin||configuration configuraton||configuration configuretion||configuration @@ -286,6 +392,7 @@ configutation||configuration conider||consider conjuction||conjunction connectinos||connections +connetor||connector connnection||connection connnections||connections consistancy||consistency @@ -295,10 +402,13 @@ containts||contains contaisn||contains contant||contact contence||contents +contiguos||contiguous +continious||continuous continous||continuous continously||continuously continueing||continuing contraints||constraints +contruct||construct contol||control contoller||controller controled||controlled @@ -316,22 +426,35 @@ correponding||corresponding correponds||corresponds correspoding||corresponding cotrol||control +cound||could couter||counter coutner||counter +creationg||creating cryptocraphic||cryptographic +cummulative||cumulative cunter||counter curent||current curently||currently cylic||cyclic dafault||default +deactive||deactivate deafult||default deamon||daemon +debouce||debounce +decendant||descendant +decendants||descendants decompres||decompress +decsribed||described decription||description +dectected||detected defailt||default +deferal||deferral +deffered||deferred defferred||deferred definate||definite definately||definitely +definiation||definition +definiton||definition defintion||definition defintions||definitions defualt||default @@ -345,25 +468,38 @@ delare||declare delares||declares delaring||declaring delemiter||delimiter +delibrately||deliberately +delievered||delivered +demodualtor||demodulator +demension||dimension dependancies||dependencies dependancy||dependency dependant||dependent +dependend||dependent depreacted||deprecated depreacte||deprecate desactivate||deactivate desciptor||descriptor desciptors||descriptors +descripto||descriptor descripton||description descrition||description descritptor||descriptor desctiptor||descriptor desriptor||descriptor desriptors||descriptors +desination||destination +destionation||destination +destoried||destroyed destory||destroy destoryed||destroyed destorys||destroys destroied||destroyed detabase||database +deteced||detected +detecion||detection +detectt||detect +detroyed||destroyed develope||develop developement||development developped||developed @@ -373,43 +509,77 @@ developpment||development deveolpment||development devided||divided deviece||device +devision||division diable||disable +diabled||disabled +dicline||decline dictionnary||dictionary didnt||didn't diferent||different differrence||difference diffrent||different +differenciate||differentiate +diffreential||differential diffrentiate||differentiate difinition||definition +digial||digital +dimention||dimension +dimesions||dimensions +diconnected||disconnected +disabed||disabled +disasembler||disassembler +disgest||digest +disired||desired +dispalying||displaying +dissable||disable diplay||display +directon||direction +direcly||directly direectly||directly +diregard||disregard disassocation||disassociation disapear||disappear disapeared||disappeared disappared||disappeared +disbale||disable +disbaled||disabled disble||disable disbled||disabled disconnet||disconnect discontinous||discontinuous +disharge||discharge +disnabled||disabled dispertion||dispersion dissapears||disappears +dissconect||disconnect distiction||distinction +divisable||divisible +divsiors||divisors +dsiabled||disabled docuentation||documentation documantation||documentation documentaion||documentation documment||document doesnt||doesn't +donwload||download +donwloading||downloading dorp||drop dosen||doesn downlad||download downlads||downloads +droped||dropped +droput||dropout druing||during +dyanmic||dynamic dynmaic||dynamic +eanable||enable +eanble||enable easilly||easily ecspecially||especially edditable||editable editting||editing efective||effective +effectivness||effectiveness efficently||efficiently ehther||ether eigth||eight @@ -417,14 +587,23 @@ elementry||elementary eletronic||electronic embeded||embedded enabledi||enabled +enbale||enable +enble||enable enchanced||enhanced encorporating||incorporating encrupted||encrypted encrypiton||encryption +encryptio||encryption endianess||endianness +enpoint||endpoint enhaced||enhanced enlightnment||enlightenment +enqueing||enqueuing +entires||entries +entites||entities +entrys||entries enocded||encoded +enought||enough enterily||entirely enviroiment||environment enviroment||environment @@ -435,19 +614,37 @@ equiped||equipped equivelant||equivalent equivilant||equivalent eror||error +errorr||error +errror||error estbalishment||establishment etsablishment||establishment etsbalishment||establishment +evalute||evaluate +evalutes||evaluates +evalution||evaluation excecutable||executable +excceed||exceed exceded||exceeded +exceds||exceeds +exceeed||exceed excellant||excellent +exchnage||exchange +execeeded||exceeded +execeeds||exceeds +exeed||exceed +exeeds||exceeds +exeuction||execution existance||existence existant||existent exixt||exist +exsits||exists exlcude||exclude +exlcuding||excluding exlcusive||exclusive +exlusive||exclusive exmaple||example expecially||especially +experies||expires explicite||explicit explicitely||explicitly explict||explicit @@ -456,47 +653,69 @@ explictly||explicitly expresion||expression exprimental||experimental extened||extended +exteneded||extended extensability||extensibility extention||extension +extenstion||extension extracter||extractor -falied||failed +faied||failed +faield||failed faild||failed +failded||failed +failer||failure faill||fail failied||failed faillure||failure failue||failure failuer||failure +failng||failing faireness||fairness falied||failed faliure||failure +fallbck||fallback familar||familiar fatser||faster feauture||feature feautures||features fetaure||feature fetaures||features +fetcing||fetching fileystem||filesystem +fimrware||firmware fimware||firmware +firmare||firmware +firmaware||firmware +firtly||firstly +firware||firmware +firwmare||firmware finanize||finalize findn||find finilizes||finalizes finsih||finish +fliter||filter flusing||flushing folloing||following followign||following followings||following follwing||following +fonud||found forseeable||foreseeable forse||force fortan||fortran forwardig||forwarding +frambuffer||framebuffer framming||framing framwork||framework +frequence||frequency frequncy||frequency +frequancy||frequency frome||from +fronend||frontend fucntion||function fuction||function fuctions||functions +fullill||fulfill +funcation||function funcion||function functionallity||functionality functionaly||functionally @@ -507,41 +726,64 @@ funtions||functions furthur||further futhermore||furthermore futrue||future +gatable||gateable +gateing||gating +gauage||gauge gaurenteed||guaranteed generiously||generously genereate||generate +genereted||generated genric||generic +gerenal||general +geting||getting globel||global grabing||grabbing grahical||graphical grahpical||graphical +granularty||granularity grapic||graphic +grranted||granted guage||gauge guarenteed||guaranteed guarentee||guarantee halfs||halves hander||handler handfull||handful +hanlde||handle hanled||handled happend||happened +hardare||hardware harware||hardware +hardward||hardware +havind||having heirarchically||hierarchically +heirarchy||hierarchy helpfull||helpful +hearbeat||heartbeat +heterogenous||heterogeneous +hexdecimal||hexadecimal +hybernate||hibernate hierachy||hierarchy hierarchie||hierarchy +homogenous||homogeneous howver||however hsould||should hypervior||hypervisor hypter||hyper +idel||idle identidier||identifier iligal||illegal illigal||illegal +illgal||illegal +iomaped||iomapped imblance||imbalance immeadiately||immediately immedaite||immediate +immedate||immediate immediatelly||immediately immediatly||immediately immidiate||immediate +immutible||immutable impelentation||implementation impementated||implemented implemantation||implementation @@ -549,24 +791,34 @@ implemenation||implementation implementaiton||implementation implementated||implemented implemention||implementation +implementd||implemented implemetation||implementation implemntation||implementation implentation||implementation implmentation||implementation implmenting||implementing +incative||inactive incomming||incoming +incompaitiblity||incompatibility incompatabilities||incompatibilities incompatable||incompatible +incompatble||incompatible inconsistant||inconsistent increas||increase +incremeted||incremented incrment||increment +incuding||including +inculde||include indendation||indentation indended||intended independant||independent independantly||independently independed||independent indiate||indicate +indicat||indicate inexpect||inexpected +inferface||interface +infinit||infinite infomation||information informatiom||information informations||information @@ -581,27 +833,41 @@ initalize||initialize initation||initiation initators||initiators initialiazation||initialization +initializationg||initialization initializiation||initialization +initialze||initialize initialzed||initialized +initialzing||initializing initilization||initialization initilize||initialize +initliaze||initialize +initilized||initialized inofficial||unofficial +inrerface||interface insititute||institute +instace||instance instal||install +instanciate||instantiate instanciated||instantiated +instuments||instruments +insufficent||insufficient inteface||interface integreated||integrated integrety||integrity integrey||integrity intendet||intended intented||intended +interal||internal interanl||internal interchangable||interchangeable interferring||interfering interger||integer +intergrated||integrated intermittant||intermittent internel||internal interoprability||interoperability +interuupt||interrupt +interupts||interrupts interrface||interface interrrupt||interrupt interrup||interrupt @@ -609,6 +875,7 @@ interrups||interrupts interruptted||interrupted interupted||interrupted interupt||interrupt +intiailized||initialized intial||initial intialisation||initialisation intialised||initialised @@ -617,24 +884,35 @@ intialization||initialization intialized||initialized intialize||initialize intregral||integral +intrerrupt||interrupt intrrupt||interrupt intterrupt||interrupt intuative||intuitive +inavlid||invalid invaid||invalid +invaild||invalid +invailid||invalid +invald||invalid invalde||invalid invalide||invalid +invalidiate||invalidate invalud||invalid invididual||individual invokation||invocation invokations||invocations +ireelevant||irrelevant irrelevent||irrelevant isnt||isn't isssue||issue +issus||issues +iteraions||iterations iternations||iterations itertation||iteration itslef||itself +ivalid||invalid jave||java jeffies||jiffies +jumpimng||jumping juse||just jus||just kown||known @@ -644,6 +922,7 @@ langauge||language langugage||language lauch||launch layed||laid +legnth||length leightweight||lightweight lengh||length lenght||length @@ -654,40 +933,66 @@ libary||library librairies||libraries libraris||libraries licenceing||licencing +limted||limited +logaritmic||logarithmic loggging||logging loggin||login logile||logfile +loobpack||loopback loosing||losing losted||lost +maangement||management machinary||machinery +maibox||mailbox maintainance||maintenance maintainence||maintenance maintan||maintain makeing||making +mailformed||malformed malplaced||misplaced malplace||misplace managable||manageable +managament||management managment||management mangement||management +manger||manager manoeuvering||maneuvering +manufaucturing||manufacturing mappping||mapping +maping||mapping +matchs||matches mathimatical||mathematical mathimatic||mathematic mathimatics||mathematics +maxmium||maximum +maximium||maximum maxium||maximum mechamism||mechanism +mechanim||mechanism meetign||meeting +memeory||memory +memmber||member +memoery||memory +memroy||memory ment||meant mergable||mergeable mesage||message +mesages||messages messags||messages messgaes||messages messsage||message messsages||messages +metdata||metadata +micropone||microphone microprocesspr||microprocessor +migrateable||migratable +millenium||millennium milliseonds||milliseconds +minimim||minimum minium||minimum minimam||minimum +minimun||minimum +miniumum||minimum minumum||minimum misalinged||misaligned miscelleneous||miscellaneous @@ -695,21 +1000,35 @@ misformed||malformed mispelled||misspelled mispelt||misspelt mising||missing +mismactch||mismatch +missign||missing +missmanaged||mismanaged +missmatch||mismatch +misssing||missing miximum||maximum mmnemonic||mnemonic mnay||many +modfiy||modify +modifer||modifier +modul||module modulues||modules momery||memory +memomry||memory +monitring||monitoring monochorome||monochrome monochromo||monochrome monocrome||monochrome mopdule||module mroe||more mulitplied||multiplied +muliple||multiple +multipler||multiplier multidimensionnal||multidimensional +multipe||multiple multple||multiple mumber||number muticast||multicast +mutilcast||multicast mutiple||multiple mutli||multi nams||names @@ -726,45 +1045,67 @@ negotation||negotiation nerver||never nescessary||necessary nessessary||necessary +none existent||non-existent noticable||noticeable +notication||notification notications||notifications +notifcations||notifications notifed||notified +notity||notify +nubmer||number numebr||number +numer||number numner||number +nunber||number obtaion||obtain +obusing||abusing occassionally||occasionally occationally||occasionally occurance||occurrence occurances||occurrences -occured||occurred +occurd||occurred occurence||occurrence occure||occurred occured||occurred occuring||occurring +ocurrence||occurrence +offser||offset offet||offset +offlaod||offload +offloded||offloaded +offseting||offsetting +oflload||offload omited||omitted omiting||omitting omitt||omit ommiting||omitting ommitted||omitted onself||oneself +onthe||on the ony||only +openning||opening operatione||operation opertaions||operations +opportunies||opportunities optionnal||optional optmizations||optimizations orientatied||orientated orientied||oriented orignal||original +originial||original otherise||otherwise ouput||output oustanding||outstanding overaall||overall overhread||overhead overlaping||overlapping +oveflow||overflow +overflw||overflow +overlfow||overflow overide||override overrided||overridden overriden||overridden +overrrun||overrun overun||overrun overwritting||overwriting overwriten||overwritten @@ -775,8 +1116,10 @@ packege||package packge||package packtes||packets pakage||package +paket||packet pallette||palette paln||plan +palne||plane paramameters||parameters paramaters||parameters paramater||parameter @@ -784,22 +1127,36 @@ parametes||parameters parametised||parametrised paramter||parameter paramters||parameters +parmaters||parameters particuarly||particularly particularily||particularly +partion||partition +partions||partitions partiton||partition pased||passed passin||passing pathes||paths +pattrns||patterns pecularities||peculiarities peformance||performance +peforming||performing peice||piece pendantic||pedantic peprocessor||preprocessor +perfomance||performance perfoming||performing +perfomring||performing +periperal||peripheral +peripherial||peripheral permissons||permissions +permited||permitted peroid||period persistance||persistence persistant||persistent +phoneticly||phonetically +plaform||platform +plalform||platform +platfoem||platform platfrom||platform plattform||platform pleaes||please @@ -811,7 +1168,12 @@ poiter||pointer posible||possible positon||position possibilites||possibilities +potocol||protocol powerfull||powerful +pramater||parameter +preamle||preamble +preample||preamble +preapre||prepare preceeded||preceded preceeding||preceding preceed||precede @@ -820,17 +1182,28 @@ precission||precision preemptable||preemptible prefered||preferred prefferably||preferably +prefitler||prefilter +preform||perform premption||preemption prepaired||prepared +prepate||prepare +preperation||preparation +preprare||prepare pressre||pressure +presuambly||presumably +previosuly||previously +previsously||previously primative||primitive princliple||principle priorty||priority +priting||printing privilaged||privileged privilage||privilege priviledge||privilege priviledges||privileges +privleges||privileges probaly||probably +probabalistic||probabilistic procceed||proceed proccesors||processors procesed||processed @@ -843,12 +1216,17 @@ processsed||processed processsing||processing procteted||protected prodecure||procedure +progamming||programming progams||programs progess||progress +programable||programmable programers||programmers programm||program programms||programs +progres||progress progresss||progress +prohibitted||prohibited +prohibitting||prohibiting promiscous||promiscuous promps||prompts pronnounced||pronounced @@ -858,34 +1236,45 @@ pronunce||pronounce propery||property propigate||propagate propigation||propagation +propogation||propagation propogate||propagate prosess||process protable||portable protcol||protocol protecion||protection +protedcted||protected protocoll||protocol promixity||proximity psudo||pseudo psuedo||pseudo psychadelic||psychedelic +purgable||purgeable pwoer||power +queing||queuing quering||querying +queus||queues +randomally||randomly raoming||roaming reasearcher||researcher reasearchers||researchers reasearch||research +receieve||receive recepient||recipient +recevied||received receving||receiving +recievd||received recieved||received recieve||receive reciever||receiver recieves||receives +recieving||receiving recogniced||recognised recognizeable||recognizable recommanded||recommended recyle||recycle redircet||redirect redirectrion||redirection +redundacy||redundancy reename||rename refcounf||refcount refence||reference @@ -895,8 +1284,12 @@ refering||referring refernces||references refernnce||reference refrence||reference +regiser||register +registed||registered registerd||registered +registeration||registration registeresd||registered +registerred||registered registes||registers registraration||registration regsiter||register @@ -907,6 +1300,7 @@ regulamentations||regulations reigstration||registration releated||related relevent||relevant +reloade||reload remoote||remote remore||remote removeable||removable @@ -917,29 +1311,45 @@ replys||replies reponse||response representaion||representation reqeust||request +reqister||register +requed||requeued requestied||requested requiere||require requirment||requirement requred||required requried||required requst||request +requsted||requested +reregisteration||reregistration reseting||resetting +reseved||reserved +reseverd||reserved resizeable||resizable +resotre||restore +resouce||resource resouces||resources resoures||resources responce||response +resrouce||resource ressizes||resizes ressource||resource ressources||resources +restesting||retesting +resumbmitting||resubmitting retransmited||retransmitted retreived||retrieved retreive||retrieve +retreiving||retrieving retrive||retrieve +retrived||retrieved +retrun||return +retun||return retuned||returned reudce||reduce reuest||request reuqest||request reutnred||returned +revsion||revision rmeoved||removed rmeove||remove rmeoves||removes @@ -948,20 +1358,29 @@ routins||routines rquest||request runing||running runned||ran +runnnig||running runnning||running runtine||runtime sacrifying||sacrificing safly||safely safty||safety +satify||satisfy +satisifed||satisfied savable||saveable +scaleing||scaling scaned||scanned scaning||scanning scarch||search +schdule||schedule seach||search searchs||searches +secion||section secquence||sequence secund||second segement||segment +seleted||selected +semaphone||semaphore +senario||scenario senarios||scenarios sentivite||sensitive separatly||separately @@ -973,11 +1392,19 @@ seperate||separate seperatly||separately seperator||separator sepperate||separate +seqeunce||sequence +seqeuncer||sequencer +seqeuencer||sequencer sequece||sequence +sequemce||sequence sequencial||sequential +serivce||service serveral||several +servive||service setts||sets settting||setting +shapshot||snapshot +shoft||shift shotdown||shutdown shoud||should shouldnt||shouldn't @@ -985,24 +1412,35 @@ shoule||should shrinked||shrunk siginificantly||significantly signabl||signal +significanly||significantly similary||similarly similiar||similar simlar||similar simliar||similar simpified||simplified +simultaneusly||simultaneously +simultanous||simultaneous singaled||signaled singal||signal singed||signed +slect||select sleeped||slept +sliped||slipped +softwade||software softwares||software +soley||solely +souce||source speach||speech specfic||specific +specfield||specified speciefied||specified specifc||specific specifed||specified specificatin||specification specificaton||specification +specificed||specified specifing||specifying +specifiy||specify specifiying||specifying speficied||specified speicify||specify @@ -1019,8 +1457,12 @@ staion||station standardss||standards standartization||standardization standart||standard +standy||standby +stardard||standard staticly||statically +statuss||status stoped||stopped +stoping||stopping stoppped||stopped straming||streaming struc||struct @@ -1032,12 +1474,18 @@ sturcture||structure subdirectoires||subdirectories suble||subtle substract||subtract +submited||submitted +submition||submission +succeded||succeeded +suceed||succeed +succesfuly||successfully succesfully||successfully succesful||successful successed||succeeded successfull||successful successfuly||successfully sucessfully||successfully +sucessful||successful sucess||success superflous||superfluous superseeded||superseded @@ -1046,14 +1494,18 @@ suported||supported suport||support supportet||supported suppored||supported +supporing||supporting supportin||supporting suppoted||supported suppported||supported suppport||support +supprot||support supress||suppress +surpressed||suppressed surpresses||suppresses susbsystem||subsystem suspeneded||suspended +suspsend||suspend suspicously||suspiciously swaping||swapping switchs||switches @@ -1064,9 +1516,14 @@ swithced||switched swithcing||switching swithed||switched swithing||switching +swtich||switch +syfs||sysfs symetric||symmetric synax||syntax synchonized||synchronized +sychronization||synchronization +sychronously||synchronously +synchronuously||synchronously syncronize||synchronize syncronized||synchronized syncronizing||synchronizing @@ -1075,42 +1532,78 @@ syste||system sytem||system sythesis||synthesis taht||that +tained||tainted +tarffic||traffic +tansmit||transmit targetted||targeted targetting||targeting +taskelt||tasklet teh||the +temeprature||temperature temorary||temporary temproarily||temporarily +temperture||temperature +the the||the +theads||threads therfore||therefore thier||their threds||threads +threee||three threshhold||threshold +thresold||threshold throught||through +tansition||transition +trackling||tracking +troughput||throughput +trys||tries thses||these +tiggers||triggers tiggered||triggered tipically||typically +timeing||timing timout||timeout tmis||this +toogle||toggle torerable||tolerable +torlence||tolerance +traget||target +traking||tracking tramsmitted||transmitted tramsmit||transmit +tranasction||transaction +tranceiver||transceiver tranfer||transfer +tranmission||transmission +transcevier||transceiver transciever||transceiver transferd||transferred transfered||transferred transfering||transferring transision||transition +transistioned||transitioned transmittd||transmitted transormed||transformed +trasfer||transfer trasmission||transmission treshold||threshold +triggerd||triggered +trigerred||triggered trigerring||triggering trun||turn +tunning||tuning ture||true tyep||type udpate||update +updtes||updates uesd||used +unknwon||unknown +uknown||unknown +usccess||success uncommited||uncommitted +uncompatible||incompatible unconditionaly||unconditionally +undeflow||underflow +undelying||underlying underun||underrun unecessary||unnecessary unexecpted||unexpected @@ -1121,31 +1614,52 @@ unexpeted||unexpected unexpexted||unexpected unfortunatelly||unfortunately unifiy||unify +uniterrupted||uninterrupted +uninterruptable||uninterruptible unintialized||uninitialized +unitialized||uninitialized unkmown||unknown unknonw||unknown +unknouwn||unknown unknow||unknown unkown||unknown +unamed||unnamed +uneeded||unneeded unneded||unneeded +unneccecary||unnecessary +unneccesary||unnecessary +unneccessary||unnecessary +unnecesary||unnecessary unneedingly||unnecessarily unnsupported||unsupported +unuspported||unsupported unmached||unmatched +unprecise||imprecise +unpriviledged||unprivileged +unpriviliged||unprivileged unregester||unregister unresgister||unregister unrgesiter||unregister unsinged||unsigned unstabel||unstable +unsolicted||unsolicited unsolicitied||unsolicited unsuccessfull||unsuccessful unsuported||unsupported untill||until +ununsed||unused unuseful||useless +unvalid||invalid upate||update +upsupported||unsupported +upto||up to +useable||usable usefule||useful usefull||useful usege||usage usera||users usualy||usually +usupported||unsupported utilites||utilities utillities||utilities utilties||utilities @@ -1160,8 +1674,12 @@ varible||variable varient||variant vaule||value verbse||verbose +veify||verify +verfication||verification +veriosn||version verisons||versions verison||version +veritical||vertical verson||version vicefersa||vice-versa virtal||virtual @@ -1169,7 +1687,12 @@ virtaul||virtual virtiual||virtual visiters||visitors vitual||virtual +vunerable||vulnerable +wakeus||wakeups +was't||wasn't +wathdog||watchdog wating||waiting +wiat||wait wether||whether whataver||whatever whcih||which @@ -1177,12 +1700,15 @@ whenver||whenever wheter||whether whe||when wierd||weird +wihout||without wiil||will wirte||write withing||within wnat||want +wont||won't workarould||workaround writeing||writing writting||writing +wtih||with zombe||zombie zomebie||zombie diff --git a/scripts/tests/build_helpers/test_domains.py b/scripts/tests/build_helpers/test_domains.py new file mode 100644 index 00000000000..0ebdeaf6cb2 --- /dev/null +++ b/scripts/tests/build_helpers/test_domains.py @@ -0,0 +1,256 @@ +#!/usr/bin/env python3 +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +""" +Tests for domains.py classes +""" + +import mock +import os +import pytest +import sys + +ZEPHYR_BASE = os.getenv("ZEPHYR_BASE") +sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/pylib/build_helpers")) + +import domains + +from contextlib import nullcontext + + +TESTDATA_1 = [ + ('', False, 1, ['domains.yaml file not found: domains.yaml']), + ( +""" +default: None +build_dir: some/dir +domains: [] +""", + True, None, [] + ), +] + +@pytest.mark.parametrize( + 'f_contents, f_exists, exit_code, expected_logs', + TESTDATA_1, + ids=['no file', 'valid'] +) +def test_from_file(caplog, f_contents, f_exists, exit_code, expected_logs): + def mock_open(*args, **kwargs): + if f_exists: + return mock.mock_open(read_data=f_contents)(args, kwargs) + raise FileNotFoundError(f'domains.yaml not found.') + + init_mock = mock.Mock(return_value=None) + + with mock.patch('domains.Domains.__init__', init_mock), \ + mock.patch('builtins.open', mock_open), \ + pytest.raises(SystemExit) if exit_code else nullcontext() as s_exit: + result = domains.Domains.from_file('domains.yaml') + + if exit_code: + assert str(s_exit.value) == str(exit_code) + else: + init_mock.assert_called_once() + assert result is not None + + assert all([log in caplog.text for log in expected_logs]) + + +TESTDATA_2 = [ + ( +""" +default: some default +build_dir: my/dir +domains: +- name: some default + build_dir: dir/2 +- name: another + build_dir: dir/3 +flash_order: I don\'t think this is correct +""", + 1, None, None, None, None + ), + ( +""" +build_dir: build/dir +domains: +- name: a domain + build_dir: dir/1 +- name: default_domain + build_dir: dir/2 +default: default_domain +flash_order: +- default_domain +- a domain +""", + None, + 'build/dir', + [('default_domain', 'dir/2'), ('a domain', 'dir/1')], + ('default_domain', 'dir/2'), + {'a domain': ('a domain', 'dir/1'), + 'default_domain': ('default_domain', 'dir/2')} + ), +] + +@pytest.mark.parametrize( + 'data, exit_code, expected_build_dir, expected_flash_order,' \ + ' expected_default, expected_domains', + TESTDATA_2, + ids=['invalid', 'valid'] +) +def test_from_yaml( + caplog, + data, + exit_code, + expected_build_dir, + expected_flash_order, + expected_default, + expected_domains +): + def mock_domain(name, build_dir, *args, **kwargs): + return name, build_dir + + with mock.patch('domains.Domain', side_effect=mock_domain), \ + pytest.raises(SystemExit) if exit_code else nullcontext() as exit_st: + doms = domains.Domains.from_yaml(data) + + if exit_code: + assert str(exit_st.value) == str(exit_code) + return + + assert doms.get_default_domain() == expected_default + assert doms.get_top_build_dir() == expected_build_dir + + assert doms._domains == expected_domains + + assert all([d in expected_flash_order for d in doms._flash_order]) + assert all([d in doms._flash_order for d in expected_flash_order]) + + +TESTDATA_3 = [ + ( + None, + True, + [('some', os.path.join('dir', '2')), + ('order', os.path.join('dir', '1'))] + ), + ( + None, + False, + [('order', os.path.join('dir', '1')), + ('some', os.path.join('dir', '2'))] + ), + ( + ['some'], + False, + [('some', os.path.join('dir', '2'))] + ), +] + +@pytest.mark.parametrize( + 'names, default_flash_order, expected_result', + TESTDATA_3, + ids=['order only', 'no parameters', 'valid'] +) +def test_get_domains( + caplog, + names, + default_flash_order, + expected_result +): + doms = domains.Domains( +""" +domains: +- name: dummy + build_dir: dummy +default: dummy +build_dir: dummy +""" + ) + doms._flash_order = [ + ('some', os.path.join('dir', '2')), + ('order', os.path.join('dir', '1')) + ] + doms._domains = { + 'order': ('order', os.path.join('dir', '1')), + 'some': ('some', os.path.join('dir', '2')) + } + + result = doms.get_domains(names, default_flash_order) + + assert result == expected_result + + + +TESTDATA_3 = [ + ( + 'other', + 1, + ['domain "other" not found, valid domains are: order, some'], + None + ), + ( + 'some', + None, + [], + ('some', os.path.join('dir', '2')) + ), +] + +@pytest.mark.parametrize( + 'name, exit_code, expected_logs, expected_result', + TESTDATA_3, + ids=['domain not found', 'valid'] +) +def test_get_domain( + caplog, + name, + exit_code, + expected_logs, + expected_result +): + doms = domains.Domains( +""" +domains: +- name: dummy + build_dir: dummy +default: dummy +build_dir: dummy +""" + ) + doms._flash_order = [ + ('some', os.path.join('dir', '2')), + ('order', os.path.join('dir', '1')) + ] + doms._domains = { + 'order': ('order', os.path.join('dir', '1')), + 'some': ('some', os.path.join('dir', '2')) + } + + with pytest.raises(SystemExit) if exit_code else nullcontext() as s_exit: + result = doms.get_domain(name) + + assert all([log in caplog.text for log in expected_logs]) + + if exit_code: + assert str(s_exit.value) == str(exit_code) + else: + assert result == expected_result + + +def test_domain(): + name = 'Domain Name' + build_dir = 'build/dir' + + domain = domains.Domain(name, build_dir) + + assert domain.name == name + assert domain.build_dir == build_dir + + domain.name = 'New Name' + domain.build_dir = 'new/dir' + + assert domain.name == 'New Name' + assert domain.build_dir == 'new/dir' diff --git a/scripts/tests/twister/test_data/mixins/test_to_ignore.py b/scripts/tests/twister/test_data/mixins/test_to_ignore.py new file mode 100644 index 00000000000..49381293a8b --- /dev/null +++ b/scripts/tests/twister/test_data/mixins/test_to_ignore.py @@ -0,0 +1,5 @@ +from twisterlib.mixins import DisablePyTestCollectionMixin + +class TestClassToIgnore(DisablePyTestCollectionMixin): + def test_to_ignore(self): + assert False diff --git a/scripts/tests/twister/test_data/testsuites/tests/test_d/snippets/dummy/dummy.conf b/scripts/tests/twister/test_data/testsuites/tests/test_d/snippets/dummy/dummy.conf new file mode 100644 index 00000000000..72b91bc12be --- /dev/null +++ b/scripts/tests/twister/test_data/testsuites/tests/test_d/snippets/dummy/dummy.conf @@ -0,0 +1 @@ +CONFIG_BOOT_BANNER=n diff --git a/scripts/tests/twister/test_data/testsuites/tests/test_d/snippets/dummy/snippet.yml b/scripts/tests/twister/test_data/testsuites/tests/test_d/snippets/dummy/snippet.yml new file mode 100644 index 00000000000..05c65f733fd --- /dev/null +++ b/scripts/tests/twister/test_data/testsuites/tests/test_d/snippets/dummy/snippet.yml @@ -0,0 +1,5 @@ +name: dummy +boards: + demo_board_2: + append: + EXTRA_CONF_FILE: dummy.conf diff --git a/scripts/tests/twister/test_errors.py b/scripts/tests/twister/test_errors.py new file mode 100644 index 00000000000..426258f4cb8 --- /dev/null +++ b/scripts/tests/twister/test_errors.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +""" +Tests for the error classes +""" + +import os +import pytest + +from pathlib import Path +from twisterlib.error import ConfigurationError + +def test_configurationerror(): + cfile = Path('some') / 'path' + message = 'dummy message' + + expected_err = f'{os.path.join("some", "path")}: dummy message' + + with pytest.raises(ConfigurationError, match=expected_err): + raise ConfigurationError(cfile, message) diff --git a/scripts/tests/twister/test_handlers.py b/scripts/tests/twister/test_handlers.py new file mode 100644 index 00000000000..6675c4ae451 --- /dev/null +++ b/scripts/tests/twister/test_handlers.py @@ -0,0 +1,2073 @@ +#!/usr/bin/env python3 +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +""" +Tests for handlers.py classes' methods +""" + +import itertools +import mock +import os +import pytest +import signal +import subprocess +import sys + +from contextlib import nullcontext +from importlib import reload +from serial import SerialException +from subprocess import CalledProcessError, TimeoutExpired + +import twisterlib.harness + +from conftest import ZEPHYR_BASE +from twisterlib.error import TwisterException +from twisterlib.handlers import ( + Handler, + BinaryHandler, + DeviceHandler, + QEMUHandler, + SimulationHandler +) + + +@pytest.fixture +def mocked_instance(tmp_path): + instance = mock.Mock() + + testsuite = mock.Mock() + type(testsuite).source_dir = mock.PropertyMock(return_value='') + instance.testsuite = testsuite + + build_dir = tmp_path / 'build_dir' + os.makedirs(build_dir) + type(instance).build_dir = mock.PropertyMock(return_value=str(build_dir)) + + platform = mock.Mock() + type(platform).binaries = mock.PropertyMock(return_value=[]) + instance.platform = platform + + type(instance.testsuite).timeout = mock.PropertyMock(return_value=60) + type(instance.platform).timeout_multiplier = mock.PropertyMock( + return_value=2 + ) + + instance.status = None + instance.reason = 'Unknown' + + return instance + + +@pytest.fixture +def faux_timer(): + class Counter: + def __init__(self): + self.t = 0 + + def time(self): + self.t += 1 + return self.t + + return Counter() + + +TESTDATA_1 = [ + (True, False, 'posix', ['Install pyserial python module with pip to use' \ + ' --device-testing option.'], None), + (False, True, 'nt', [], None), + (True, True, 'posix', ['Install pyserial python module with pip to use' \ + ' --device-testing option.'], ImportError), +] + +@pytest.mark.parametrize( + 'fail_serial, fail_pty, os_name, expected_outs, expected_error', + TESTDATA_1, + ids=['import serial', 'import pty nt', 'import serial+pty posix'] +) +def test_imports( + capfd, + fail_serial, + fail_pty, + os_name, + expected_outs, + expected_error +): + class ImportRaiser: + def find_spec(self, fullname, path, target=None): + if fullname == 'serial' and fail_serial: + raise ImportError() + if fullname == 'pty' and fail_pty: + raise ImportError() + + modules_mock = sys.modules.copy() + modules_mock['serial'] = None if fail_serial else modules_mock['serial'] + modules_mock['pty'] = None if fail_pty else modules_mock['pty'] + + meta_path_mock = sys.meta_path[:] + meta_path_mock.insert(0, ImportRaiser()) + + with mock.patch('os.name', os_name), \ + mock.patch.dict('sys.modules', modules_mock, clear=True), \ + mock.patch('sys.meta_path', meta_path_mock), \ + pytest.raises(expected_error) if expected_error else nullcontext(): + reload(twisterlib.handlers) + + out, _ = capfd.readouterr() + assert all([expected_out in out for expected_out in expected_outs]) + + +def test_handler_final_handle_actions(mocked_instance): + instance = mocked_instance + instance.testcases = [mock.Mock()] + + handler = Handler(mocked_instance) + handler.suite_name_check = True + + harness = twisterlib.harness.Test() + harness.state = mock.Mock() + harness.detected_suite_names = mock.Mock() + harness.matched_run_id = False + harness.run_id_exists = True + + handler_time = mock.Mock() + + handler._final_handle_actions(harness, handler_time) + + assert handler.instance.status == 'failed' + assert handler.instance.execution_time == handler_time + assert handler.instance.reason == 'RunID mismatch' + assert all(testcase.status == 'failed' for \ + testcase in handler.instance.testcases) + + handler.instance.reason = 'This reason shan\'t be changed.' + handler._final_handle_actions(harness, handler_time) + + assert handler.instance.reason == 'This reason shan\'t be changed.' + + +TESTDATA_2 = [ + (['dummy_testsuite_name'], False), + ([], True), + (['another_dummy_name', 'yet_another_dummy_name'], True), +] + +@pytest.mark.parametrize( + 'detected_suite_names, should_be_called', + TESTDATA_2, + ids=['detected one expected', 'detected none', 'detected two unexpected'] +) +def test_handler_verify_ztest_suite_name( + mocked_instance, + detected_suite_names, + should_be_called +): + instance = mocked_instance + type(instance.testsuite).ztest_suite_names = ['dummy_testsuite_name'] + + harness_state = 'passed' + + handler_time = mock.Mock() + + with mock.patch.object(Handler, '_missing_suite_name') as _missing_mocked: + handler = Handler(instance) + handler._verify_ztest_suite_name( + harness_state, + detected_suite_names, + handler_time + ) + + if should_be_called: + _missing_mocked.assert_called_once() + else: + _missing_mocked.assert_not_called() + + +def test_handler_missing_suite_name(mocked_instance): + instance = mocked_instance + instance.testcases = [mock.Mock()] + + handler = Handler(mocked_instance) + handler.suite_name_check = True + + expected_suite_names = ['dummy_testsuite_name'] + + handler_time = mock.Mock() + + handler._missing_suite_name(expected_suite_names, handler_time) + + assert handler.instance.status == 'failed' + assert handler.instance.execution_time == handler_time + assert handler.instance.reason == 'Testsuite mismatch' + assert all( + testcase.status == 'failed' for testcase in handler.instance.testcases + ) + + +def test_handler_record(mocked_instance): + instance = mocked_instance + instance.testcases = [mock.Mock()] + + handler = Handler(instance) + handler.suite_name_check = True + + harness = twisterlib.harness.Test() + harness.recording = ['dummy recording'] + type(harness).fieldnames = mock.PropertyMock(return_value=[]) + + mock_writerow = mock.Mock() + mock_writer = mock.Mock(writerow=mock_writerow) + + with mock.patch( + 'builtins.open', + mock.mock_open(read_data='') + ) as mock_file, \ + mock.patch( + 'csv.writer', + mock.Mock(return_value=mock_writer) + ) as mock_writer_constructor: + handler.record(harness) + + mock_file.assert_called_with( + os.path.join(instance.build_dir, 'recording.csv'), + 'at' + ) + + mock_writer_constructor.assert_called_with( + mock_file(), + harness.fieldnames, + lineterminator=os.linesep + ) + + mock_writerow.assert_has_calls( + [mock.call(harness.fieldnames)] + \ + [mock.call(recording) for recording in harness.recording] + ) + + +def test_handler_terminate(mocked_instance): + def mock_kill_function(pid, sig): + if pid < 0: + raise ProcessLookupError + + instance = mocked_instance + + handler = Handler(instance) + + mock_process = mock.Mock() + mock_child1 = mock.Mock(pid=1) + mock_child2 = mock.Mock(pid=2) + mock_process.children = mock.Mock(return_value=[mock_child1, mock_child2]) + + mock_proc = mock.Mock(pid=0) + mock_proc.terminate = mock.Mock(return_value=None) + mock_proc.kill = mock.Mock(return_value=None) + + with mock.patch('psutil.Process', return_value=mock_process), \ + mock.patch( + 'os.kill', + mock.Mock(side_effect=mock_kill_function) + ) as mock_kill: + handler.terminate(mock_proc) + + assert handler.terminated + mock_proc.terminate.assert_called_once() + mock_proc.kill.assert_called_once() + mock_kill.assert_has_calls( + [mock.call(1, signal.SIGTERM), mock.call(2, signal.SIGTERM)] + ) + + mock_child_neg1 = mock.Mock(pid=-1) + mock_process.children = mock.Mock( + return_value=[mock_child_neg1, mock_child2] + ) + handler.terminated = False + mock_kill.reset_mock() + + handler.terminate(mock_proc) + + mock_kill.assert_has_calls( + [mock.call(-1, signal.SIGTERM), mock.call(2, signal.SIGTERM)] + ) + + +def test_binaryhandler_try_kill_process_by_pid(mocked_instance): + def mock_kill_function(pid, sig): + if pid < 0: + raise ProcessLookupError + + instance = mocked_instance + + handler = BinaryHandler(instance, 'build') + handler.pid_fn = os.path.join('dummy', 'path', 'to', 'pid.pid') + + with mock.patch( + 'os.kill', + mock.Mock(side_effect=mock_kill_function) + ) as mock_kill, \ + mock.patch('os.unlink', mock.Mock()) as mock_unlink: + with mock.patch('builtins.open', mock.mock_open(read_data='1')): + handler.try_kill_process_by_pid() + + mock_unlink.assert_called_once_with( + os.path.join('dummy', 'path', 'to', 'pid.pid') + ) + mock_kill.assert_called_once_with(1, signal.SIGKILL) + + mock_unlink.reset_mock() + mock_kill.reset_mock() + handler.pid_fn = os.path.join('dummy', 'path', 'to', 'pid.pid') + + with mock.patch('builtins.open', mock.mock_open(read_data='-1')): + handler.try_kill_process_by_pid() + + mock_unlink.assert_called_once_with( + os.path.join('dummy', 'path', 'to', 'pid.pid') + ) + mock_kill.assert_called_once_with(-1, signal.SIGKILL) + + +TESTDATA_3 = [ + ( + [b'This\\r\\n', b'is\r', b'a short', b'file.'], + mock.Mock(state=False, capture_coverage=False), + [ + mock.call('This\\r\\n'), + mock.call('is\r'), + mock.call('a short'), + mock.call('file.') + ], + [ + mock.call('This'), + mock.call('is'), + mock.call('a short'), + mock.call('file.') + ], + None, + False + ), + ( + [b'Too much.'] * 120, # Should be more than the timeout + mock.Mock(state=False, capture_coverage=False), + None, + None, + True, + False + ), + ( + [b'Too much.'] * 120, # Should be more than the timeout + mock.Mock(state=True, capture_coverage=False), + None, + None, + True, + False + ), + ( + [b'Too much.'] * 120, # Should be more than the timeout + mock.Mock(state=True, capture_coverage=True), + None, + None, + False, + True + ), +] + +@pytest.mark.parametrize( + 'proc_stdout, harness, expected_handler_calls,' + ' expected_harness_calls, should_be_less, timeout_wait', + TESTDATA_3, + ids=[ + 'no timeout', + 'timeout', + 'timeout with harness state', + 'timeout with capture_coverage, wait timeout' + ] +) +def test_binaryhandler_output_handler( + mocked_instance, + faux_timer, + proc_stdout, + harness, + expected_handler_calls, + expected_harness_calls, + should_be_less, + timeout_wait +): + class MockStdout(mock.Mock): + def __init__(self, text): + super().__init__(text) + self.text = text + self.line_index = 0 + + def readline(self): + if self.line_index == len(self.text): + self.line_index = 0 + return b'' + else: + line = self.text[self.line_index] + self.line_index += 1 + return line + + class MockProc(mock.Mock): + def __init__(self, pid, stdout): + super().__init__(pid, stdout) + self.pid = mock.PropertyMock(return_value=pid) + self.stdout = MockStdout(stdout) + + def wait(self, *args, **kwargs): + if timeout_wait: + raise TimeoutExpired('dummy cmd', 'dummyamount') + + handler = BinaryHandler(mocked_instance, 'build') + handler.terminate = mock.Mock() + handler.options = mock.Mock(timeout_multiplier=1) + + proc = MockProc(1, proc_stdout) + + with mock.patch( + 'builtins.open', + mock.mock_open(read_data='') + ) as mock_file, \ + mock.patch('time.time', side_effect=faux_timer.time): + handler._output_handler(proc, harness) + + mock_file.assert_called_with(handler.log, 'wt') + + if expected_handler_calls: + mock_file.return_value.write.assert_has_calls(expected_handler_calls) + if expected_harness_calls: + harness.handle.assert_has_calls(expected_harness_calls) + if should_be_less is not None: + if should_be_less: + assert mock_file.return_value.write.call_count < len(proc_stdout) + else: + assert mock_file.return_value.write.call_count == len(proc_stdout) + if timeout_wait: + handler.terminate.assert_called_once_with(proc) + + +TESTDATA_4 = [ + (True, False, False, True, None, None, + ['valgrind', '--error-exitcode=2', '--leak-check=full', + f'--suppressions={ZEPHYR_BASE}/scripts/valgrind.supp', + '--log-file=build_dir/valgrind.log', '--track-origins=yes', + 'generator', 'run_renode_test']), + (False, True, False, False, 123, None, ['generator', 'run', '--seed=123']), + (False, False, True, False, None, None, + ['west', 'flash', '--skip-rebuild', '-d', 'build_dir']), + (False, False, False, False, None, ['ex1', 'ex2'], ['bin', 'ex1', 'ex2']), +] + +@pytest.mark.parametrize( + 'robot_test, call_make_run, call_west_flash, enable_valgrind, seed,' \ + ' extra_args, expected', + TESTDATA_4, + ids=['robot, valgrind', 'make run, seed', 'west flash', 'binary, extra'] +) +def test_binaryhandler_create_command( + mocked_instance, + robot_test, + call_make_run, + call_west_flash, + enable_valgrind, + seed, + extra_args, + expected +): + handler = BinaryHandler(mocked_instance, 'build') + handler.generator_cmd = 'generator' + handler.binary = 'bin' + handler.call_make_run = call_make_run + handler.call_west_flash = call_west_flash + handler.options = mock.Mock(enable_valgrind=enable_valgrind) + handler.seed = seed + handler.extra_test_args = extra_args + handler.build_dir = 'build_dir' + + command = handler._create_command(robot_test) + + assert command == expected + + +TESTDATA_5 = [ + (False, False, False), + (True, False, False), + (True, True, False), + (False, False, True), +] + +@pytest.mark.parametrize( + 'enable_asan, enable_lsan, enable_ubsan', + TESTDATA_5, + ids=['none', 'asan', 'asan, lsan', 'ubsan'] +) +def test_binaryhandler_create_env( + mocked_instance, + enable_asan, + enable_lsan, + enable_ubsan +): + handler = BinaryHandler(mocked_instance, 'build') + handler.options = mock.Mock( + enable_asan=enable_asan, + enable_lsan=enable_lsan, + enable_ubsan=enable_ubsan + ) + + env = { + 'example_env_var': True, + 'ASAN_OPTIONS': 'dummy=dummy:', + 'UBSAN_OPTIONS': 'dummy=dummy:' + } + + with mock.patch('os.environ', env): + res = handler._create_env() + + assert env['example_env_var'] == res['example_env_var'] + + if enable_ubsan: + assert env['UBSAN_OPTIONS'] in res['UBSAN_OPTIONS'] + assert 'log_path=stdout:' in res['UBSAN_OPTIONS'] + assert 'halt_on_error=1:' in res['UBSAN_OPTIONS'] + + if enable_asan: + assert env['ASAN_OPTIONS'] in res['ASAN_OPTIONS'] + assert 'log_path=stdout:' in res['ASAN_OPTIONS'] + + if not enable_lsan: + assert 'detect_leaks=0' in res['ASAN_OPTIONS'] + + +TESTDATA_6 = [ + (None, False, 2, True, 'failed', 'Valgrind error', False), + (None, False, 1, False, 'failed', 'Failed', False), + ('failed', False, 0, False, 'failed', 'Failed', False), + ('success', False, 0, False, 'success', 'Unknown', False), + (None, True, 1, True, 'failed', 'Timeout', True), +] + +@pytest.mark.parametrize( + 'harness_state, terminated, returncode, enable_valgrind,' \ + ' expected_status, expected_reason, do_add_missing', + TESTDATA_6, + ids=['valgrind error', 'failed', 'harness failed', 'success', 'no state'] +) +def test_binaryhandler_update_instance_info( + mocked_instance, + harness_state, + terminated, + returncode, + enable_valgrind, + expected_status, + expected_reason, + do_add_missing +): + handler = BinaryHandler(mocked_instance, 'build') + handler_time = 59 + handler.terminated = terminated + handler.returncode = returncode + handler.options = mock.Mock(enable_valgrind=enable_valgrind) + missing_mock = mock.Mock() + handler.instance.add_missing_case_status = missing_mock + + handler._update_instance_info(harness_state, handler_time) + + assert handler.instance.execution_time == handler_time + + assert handler.instance.status == expected_status + assert handler.instance.reason == expected_reason + + if do_add_missing: + missing_mock.assert_called_once_with('blocked', expected_reason) + + +TESTDATA_7 = [ + (True, False, False), + (False, True, False), + (False, False, True), +] + +@pytest.mark.parametrize( + 'is_robot_test, coverage, isatty', + TESTDATA_7, + ids=['robot test', 'coverage', 'isatty'] +) +def test_binaryhandler_handle( + mocked_instance, + caplog, + is_robot_test, + coverage, + isatty +): + thread_mock_obj = mock.Mock() + + def mock_popen(command, *args, **kwargs,): + return mock.Mock( + __enter__=mock.Mock(return_value=mock.Mock(pid=0, returncode=0)), + __exit__=mock.Mock(return_value=None) + ) + + def mock_thread(target, *args, **kwargs): + return thread_mock_obj + + handler = BinaryHandler(mocked_instance, 'build') + handler.sourcedir = 'source_dir' + handler.build_dir = 'build_dir' + handler.name= 'Dummy Name' + handler._create_command = mock.Mock(return_value=['dummy' , 'command']) + handler._create_env = mock.Mock(return_value=[]) + handler._update_instance_info = mock.Mock() + handler._final_handle_actions = mock.Mock() + handler.terminate = mock.Mock() + handler.try_kill_process_by_pid = mock.Mock() + handler.options = mock.Mock(coverage=coverage) + + robot_mock = mock.Mock() + harness = mock.Mock(is_robot_test=is_robot_test, run_robot_test=robot_mock) + + popen_mock = mock.Mock(side_effect=mock_popen) + thread_mock = mock.Mock(side_effect=mock_thread) + call_mock = mock.Mock() + + with mock.patch('subprocess.call', call_mock), \ + mock.patch('subprocess.Popen', popen_mock), \ + mock.patch('threading.Thread', thread_mock), \ + mock.patch('sys.stdout.isatty', return_value=isatty): + handler.handle(harness) + + if is_robot_test: + robot_mock.assert_called_once_with(['dummy', 'command'], mock.ANY) + return + + assert 'Spawning BinaryHandler Thread for Dummy Name' in caplog.text + + thread_mock_obj.join.assert_called() + handler._update_instance_info.assert_called_once() + handler._final_handle_actions.assert_called_once() + + if coverage: + call_mock.assert_any_call( + ['GCOV_PREFIX=build_dir', 'gcov', 'source_dir', + '-b', '-s', 'build_dir'], + shell=True + ) + + if isatty: + call_mock.assert_any_call(['stty', 'sane'], stdin=mock.ANY) + + +TESTDATA_8 = [ + ('renode', True, True, False, False), + ('native', False, False, False, True), + ('build', False, True, False, False), +] + +@pytest.mark.parametrize( + 'type_str, is_pid_fn, expected_call_make_run, is_binary, expected_ready', + TESTDATA_8, + ids=[t[0] for t in TESTDATA_8] +) +def test_simulationhandler_init( + mocked_instance, + type_str, + is_pid_fn, + expected_call_make_run, + is_binary, + expected_ready +): + handler = SimulationHandler(mocked_instance, type_str) + + assert handler.call_make_run == expected_call_make_run + assert handler.ready == expected_ready + + if is_pid_fn: + assert handler.pid_fn == os.path.join(mocked_instance.build_dir, + 'renode.pid') + if is_binary: + assert handler.pid_fn == os.path.join(mocked_instance.build_dir, + 'zephyr', 'zephyr.exe') + + +TESTDATA_9 = [ + (3, 2, 0, 0, 3, -1, True, False, False, 1), + (4, 1, 0, 0, -1, -1, False, True, False, 0), + (5, 0, 1, 2, -1, 4, False, False, True, 3) +] + +@pytest.mark.parametrize( + 'success_count, in_waiting_count, oserror_count, readline_error_count,' + ' haltless_count, stateless_count, end_by_halt, end_by_close,' + ' end_by_state, expected_line_count', + TESTDATA_9, + ids=[ + 'halt event', + 'serial closes', + 'harness state with errors' + ] +) +def test_devicehandler_monitor_serial( + mocked_instance, + success_count, + in_waiting_count, + oserror_count, + readline_error_count, + haltless_count, + stateless_count, + end_by_halt, + end_by_close, + end_by_state, + expected_line_count +): + is_open_iter = iter(lambda: True, False) + line_iter = [ + TypeError('dummy TypeError') if x % 2 else \ + SerialException('dummy SerialException') for x in range( + readline_error_count + ) + ] + [ + f'line no {idx}'.encode('utf-8') for idx in range(success_count) + ] + in_waiting_iter = [False] * in_waiting_count + [ + TypeError('dummy TypeError') + ] if end_by_close else ( + [OSError('dummy OSError')] * oserror_count + [False] * in_waiting_count + ) + [True] * (success_count + readline_error_count) + + is_set_iter = [False] * haltless_count + [True] \ + if end_by_halt else iter(lambda: False, True) + + state_iter = [False] * stateless_count + [True] \ + if end_by_state else iter(lambda: False, True) + + halt_event = mock.Mock(is_set=mock.Mock(side_effect=is_set_iter)) + ser = mock.Mock( + isOpen=mock.Mock(side_effect=is_open_iter), + readline=mock.Mock(side_effect=line_iter) + ) + type(ser).in_waiting = mock.PropertyMock( + side_effect=in_waiting_iter, + return_value=False + ) + harness = mock.Mock(capture_coverage=False) + type(harness).state=mock.PropertyMock(side_effect=state_iter) + + handler = DeviceHandler(mocked_instance, 'build') + handler.options = mock.Mock(coverage=not end_by_state) + + with mock.patch('builtins.open', mock.mock_open(read_data='')): + handler.monitor_serial(ser, halt_event, harness) + + if not end_by_close: + ser.close.assert_called_once() + + harness.handle.assert_has_calls( + [mock.call(f'line no {idx}') for idx in range(expected_line_count)] + ) + + +TESTDATA_10 = [ + ( + 'dummy_platform', + 'dummy fixture', + [ + mock.Mock( + fixtures=[], + platform='dummy_platform', + available=1, + counter=0 + ), + mock.Mock( + fixtures=['dummy fixture'], + platform='another_platform', + available=1, + counter=0 + ), + mock.Mock( + fixtures=['dummy fixture'], + platform='dummy_platform', + serial_pty=None, + serial=None, + available=1, + counter=0 + ), + mock.Mock( + fixtures=['dummy fixture'], + platform='dummy_platform', + serial_pty=mock.Mock(), + available=1, + counter=0 + ) + ], + 3 + ), + ( + 'dummy_platform', + 'dummy fixture', + [], + TwisterException + ), + ( + 'dummy_platform', + 'dummy fixture', + [ + mock.Mock( + fixtures=['dummy fixture'], + platform='dummy_platform', + serial_pty=mock.Mock(), + available=0 + ), + mock.Mock( + fixtures=['another fixture'], + platform='dummy_platform', + serial_pty=mock.Mock(), + available=0 + ), + mock.Mock( + fixtures=['dummy fixture'], + platform='dummy_platform', + serial=mock.Mock(), + available=0 + ), + mock.Mock( + fixtures=['another fixture'], + platform='dummy_platform', + serial=mock.Mock(), + available=0 + ) + ], + None + ) +] + +@pytest.mark.parametrize( + 'platform_name, fixture, duts, expected', + TESTDATA_10, + ids=['one good dut', 'exception - no duts', 'no available duts'] +) +def test_devicehandler_device_is_available( + mocked_instance, + platform_name, + fixture, + duts, + expected +): + mocked_instance.platform.name = platform_name + mocked_instance.testsuite.harness_config = {'fixture': fixture} + + handler = DeviceHandler(mocked_instance, 'build') + handler.duts = duts + + if isinstance(expected, int): + device = handler.device_is_available(mocked_instance) + + assert device == duts[expected] + assert device.available == 0 + assert device.counter == 1 + elif expected is None: + device = handler.device_is_available(mocked_instance) + + assert device is None + elif isinstance(expected, type): + with pytest.raises(expected): + device = handler.device_is_available(mocked_instance) + else: + assert False + + +def test_devicehandler_make_device_available(mocked_instance): + serial = mock.Mock(name='dummy_serial') + duts = [ + mock.Mock(available=0, serial=serial, serial_pty=None), + mock.Mock(available=0, serial=None, serial_pty=serial), + mock.Mock( + available=0, + serial=mock.Mock('another_serial'), + serial_pty=None + ) + ] + + handler = DeviceHandler(mocked_instance, 'build') + handler.duts = duts + + handler.make_device_available(serial) + + assert len([None for d in handler.duts if d.available == 1]) == 2 + assert handler.duts[2].available == 0 + + +TESTDATA_11 = [ + (mock.Mock(pid=0, returncode=0), False), + (mock.Mock(pid=0, returncode=1), False), + (mock.Mock(pid=0, returncode=1), True) +] + +@pytest.mark.parametrize( + 'mock_process, raise_timeout', + TESTDATA_11, + ids=['proper script', 'error', 'timeout'] +) +def test_devicehandler_run_custom_script(caplog, mock_process, raise_timeout): + def raise_timeout_fn(timeout=-1): + if raise_timeout and timeout != -1: + raise subprocess.TimeoutExpired(None, timeout) + else: + return mock.Mock(), mock.Mock() + + def assert_popen(command, *args, **kwargs): + return mock.Mock( + __enter__=mock.Mock(return_value=mock_process), + __exit__=mock.Mock(return_value=None) + ) + + mock_process.communicate = mock.Mock(side_effect=raise_timeout_fn) + + script = [os.path.join('test','script', 'path'), 'arg'] + timeout = 60 + + with mock.patch('subprocess.Popen', side_effect=assert_popen): + DeviceHandler.run_custom_script(script, timeout) + + if raise_timeout: + assert all( + t in caplog.text.lower() for t in [str(script), 'timed out'] + ) + mock_process.assert_has_calls( + [ + mock.call.communicate(timeout=timeout), + mock.call.kill(), + mock.call.communicate() + ] + ) + elif mock_process.returncode == 0: + assert not any([r.levelname == 'ERROR' for r in caplog.records]) + else: + assert 'timed out' not in caplog.text.lower() + assert 'custom script failure' in caplog.text.lower() + + +TESTDATA_12 = [ + (0, False), + (4, False), + (0, True) +] + +@pytest.mark.parametrize( + 'num_of_failures, raise_exception', + TESTDATA_12, + ids=['no failures', 'with failures', 'exception'] +) +def test_devicehandler_get_hardware( + mocked_instance, + caplog, + num_of_failures, + raise_exception +): + expected_hardware = mock.Mock() + + def mock_availability(handler, instance, no=num_of_failures): + if raise_exception: + raise TwisterException(f'dummy message') + if handler.no: + handler.no -= 1 + return None + return expected_hardware + + handler = DeviceHandler(mocked_instance, 'build') + handler.no = num_of_failures + + with mock.patch.object( + DeviceHandler, + 'device_is_available', + mock_availability + ): + hardware = handler.get_hardware() + + if raise_exception: + assert 'dummy message' in caplog.text.lower() + assert mocked_instance.status == 'failed' + assert mocked_instance.reason == 'dummy message' + else: + assert hardware == expected_hardware + + +TESTDATA_13 = [ + ( + None, + None, + None, + ['generator_cmd', '-C', '$build_dir', 'flash'] + ), + ( + [], + None, + None, + ['west', 'flash', '--skip-rebuild', '-d', '$build_dir'] + ), + ( + '--dummy', + None, + None, + ['west', 'flash', '--skip-rebuild', '-d', '$build_dir', + '--', '--dummy'] + ), + ( + '--dummy1,--dummy2', + None, + None, + ['west', 'flash', '--skip-rebuild', '-d', '$build_dir', + '--', '--dummy1', '--dummy2'] + ), + + ( + None, + 'runner', + 'product', + ['west', 'flash', '--skip-rebuild', '-d', '$build_dir', + '--runner', 'runner', 'param1', 'param2'] + ), + + ( + None, + 'pyocd', + 'product', + ['west', 'flash', '--skip-rebuild', '-d', '$build_dir', + '--runner', 'pyocd', 'param1', 'param2', '--', '--dev-id', 12345] + ), + ( + None, + 'nrfjprog', + 'product', + ['west', 'flash', '--skip-rebuild', '-d', '$build_dir', + '--runner', 'nrfjprog', 'param1', 'param2', '--', '--dev-id', 12345] + ), + ( + None, + 'openocd', + 'STM32 STLink', + ['west', 'flash', '--skip-rebuild', '-d', '$build_dir', + '--runner', 'openocd', 'param1', 'param2', + '--', '--cmd-pre-init', 'hla_serial 12345'] + ), + ( + None, + 'openocd', + 'STLINK-V3', + ['west', 'flash', '--skip-rebuild', '-d', '$build_dir', + '--runner', 'openocd', 'param1', 'param2', + '--', '--cmd-pre-init', 'hla_serial 12345'] + ), + ( + None, + 'openocd', + 'EDBG CMSIS-DAP', + ['west', 'flash', '--skip-rebuild', '-d', '$build_dir', + '--runner', 'openocd', 'param1', 'param2', + '--', '--cmd-pre-init', 'cmsis_dap_serial 12345'] + ), + ( + None, + 'jlink', + 'product', + ['west', 'flash', '--skip-rebuild', '-d', '$build_dir', + '--runner', 'jlink', '--tool-opt=-SelectEmuBySN 12345', # 2x space + 'param1', 'param2'] + ), + ( + None, + 'stm32cubeprogrammer', + 'product', + ['west', 'flash', '--skip-rebuild', '-d', '$build_dir', + '--runner', 'stm32cubeprogrammer', '--tool-opt=sn=12345', + 'param1', 'param2'] + ), + +] + +TESTDATA_13_2 = [(True), (False)] + +@pytest.mark.parametrize( + 'self_west_flash, runner,' \ + ' hardware_product_name, expected', + TESTDATA_13, + ids=['generator', '--west-flash', 'one west flash value', + 'multiple west flash values', 'generic runner', 'pyocd', + 'nrfjprog', 'openocd, STM32 STLink', 'openocd, STLINK-v3', + 'openocd, EDBG CMSIS-DAP', 'jlink', 'stm32cubeprogrammer'] +) +@pytest.mark.parametrize('hardware_probe', TESTDATA_13_2, ids=['probe', 'id']) +def test_devicehandler_create_command( + mocked_instance, + self_west_flash, + runner, + hardware_probe, + hardware_product_name, + expected +): + handler = DeviceHandler(mocked_instance, 'build') + handler.options = mock.Mock(west_flash=self_west_flash) + handler.generator_cmd = 'generator_cmd' + + expected = [handler.build_dir if val == '$build_dir' else \ + val for val in expected] + + hardware = mock.Mock( + product=hardware_product_name, + probe_id=12345 if hardware_probe else None, + id=12345 if not hardware_probe else None, + runner_params=['param1', 'param2'] + ) + + command = handler._create_command(runner, hardware) + + assert command == expected + + +TESTDATA_14 = [ + ('success', False, 'success', 'Unknown', False), + ('failed', False, 'failed', 'Failed', True), + ('error', False, 'error', 'Unknown', True), + (None, True, None, 'Unknown', False), + (None, False, 'failed', 'Timeout', True), +] + +@pytest.mark.parametrize( + 'harness_state, flash_error,' \ + ' expected_status, expected_reason, do_add_missing', + TESTDATA_14, + ids=['success', 'failed', 'error', 'flash error', 'no status'] +) +def test_devicehandler_update_instance_info( + mocked_instance, + harness_state, + flash_error, + expected_status, + expected_reason, + do_add_missing +): + handler = DeviceHandler(mocked_instance, 'build') + handler_time = 59 + missing_mock = mock.Mock() + handler.instance.add_missing_case_status = missing_mock + + handler._update_instance_info(harness_state, handler_time, flash_error) + + assert handler.instance.execution_time == handler_time + + assert handler.instance.status == expected_status + assert handler.instance.reason == expected_reason + + if do_add_missing: + missing_mock.assert_called_once_with('blocked', expected_reason) + + +TESTDATA_15 = [ + ('dummy device', 'dummy pty', None, None, True, False, False), + ( + 'dummy device', + 'dummy pty', + mock.Mock(communicate=mock.Mock(return_value=('', ''))), + SerialException, + False, + True, + 'dummy pty' + ), + ( + 'dummy device', + None, + None, + SerialException, + False, + False, + 'dummy device' + ) +] + +@pytest.mark.parametrize( + 'serial_device, serial_pty, ser_pty_process, expected_exception,' \ + ' expected_result, terminate_ser_pty_process, make_available', + TESTDATA_15, + ids=['valid', 'serial pty process', 'no serial pty'] +) +def test_devicehandler_create_serial_connection( + mocked_instance, + serial_device, + serial_pty, + ser_pty_process, + expected_exception, + expected_result, + terminate_ser_pty_process, + make_available +): + def mock_serial(*args, **kwargs): + if expected_exception: + raise expected_exception('') + return expected_result + + handler = DeviceHandler(mocked_instance, 'build') + handler.make_device_available = mock.Mock() + missing_mock = mock.Mock() + handler.instance.add_missing_case_status = missing_mock + available_mock = mock.Mock() + handler.make_device_available = available_mock + handler.options = mock.Mock(timeout_multiplier=1) + + hardware_baud = 14400 + flash_timeout = 60 + serial_mock = mock.Mock(side_effect=mock_serial) + + with mock.patch('serial.Serial', serial_mock), \ + pytest.raises(expected_exception) if expected_exception else \ + nullcontext(): + result = handler._create_serial_connection(serial_device, hardware_baud, + flash_timeout, serial_pty, + ser_pty_process) + + if expected_result: + assert result is not None + + if expected_exception: + assert handler.instance.status == 'failed' + assert handler.instance.reason == 'Serial Device Error' + + missing_mock.assert_called_once_with('blocked', 'Serial Device Error') + + if terminate_ser_pty_process: + ser_pty_process.terminate.assert_called_once() + ser_pty_process.communicate.assert_called_once() + + if make_available: + available_mock.assert_called_once_with(make_available) + + +TESTDATA_16 = [ + ('dummy1 dummy2', None, 'slave name'), + ('dummy1,dummy2', CalledProcessError, None), + (None, None, 'dummy hardware serial'), +] + +@pytest.mark.parametrize( + 'serial_pty, popen_exception, expected_device', + TESTDATA_16, + ids=['pty', 'pty process error', 'no pty'] +) +def test_devicehandler_get_serial_device( + mocked_instance, + serial_pty, + popen_exception, + expected_device +): + def mock_popen(command, *args, **kwargs): + assert command == ['dummy1', 'dummy2'] + if popen_exception: + raise popen_exception(command, 'Dummy error') + return mock.Mock() + + handler = DeviceHandler(mocked_instance, 'build') + hardware_serial = 'dummy hardware serial' + + popen_mock = mock.Mock(side_effect=mock_popen) + openpty_mock = mock.Mock(return_value=('master', 'slave')) + ttyname_mock = mock.Mock(side_effect=lambda x: x + ' name') + + with mock.patch('subprocess.Popen', popen_mock), \ + mock.patch('pty.openpty', openpty_mock), \ + mock.patch('os.ttyname', ttyname_mock): + result = handler._get_serial_device(serial_pty, hardware_serial) + + if popen_exception: + assert result is None + else: + assert result[0] == expected_device + +TESTDATA_17 = [ + (False, False, False, False, None, False, False, + None, None, []), + (True, True, False, False, None, False, False, + None, None, []), + (True, False, True, False, None, False, False, + 'error', 'Device issue (Flash error)', []), + (True, False, False, True, None, False, False, + 'error', 'Device issue (Timeout)', ['Flash operation timed out.']), + (True, False, False, False, 1, False, False, + 'error', 'Device issue (Flash error?)', []), + (True, False, False, False, 0, True, False, + None, None, ['Timed out while monitoring serial output on IPName']), + (True, False, False, False, 0, False, True, + None, None, ['Process Serial PTY terminated outs: errs ']), +] + +@pytest.mark.parametrize( + 'has_hardware, raise_create_serial, raise_popen, raise_timeout,' \ + ' returncode, do_timeout_thread, use_pty,' \ + ' expected_status, expected_reason, expected_logs', + TESTDATA_17, + ids=['no hardware', 'create serial failure', 'popen called process error', + 'communicate timeout', 'nonzero returncode', 'valid pty', 'valid dev'] +) +def test_devicehandler_handle( + mocked_instance, + caplog, + has_hardware, + raise_create_serial, + raise_popen, + raise_timeout, + returncode, + do_timeout_thread, + use_pty, + expected_status, + expected_reason, + expected_logs +): + def mock_get_serial(serial_pty, hardware_serial): + if serial_pty: + serial_pty_process = mock.Mock( + name='dummy serial PTY process', + communicate=mock.Mock( + return_value=('', '') + ) + ) + return 'dummy serial PTY device', serial_pty_process + return 'dummy serial device', None + + def mock_create_serial(*args, **kwargs): + if raise_create_serial: + raise SerialException('dummy cmd', 'dummy msg') + return mock.Mock(name='dummy serial') + + def mock_thread(*args, **kwargs): + is_alive_mock = mock.Mock(return_value=bool(do_timeout_thread)) + + return mock.Mock(is_alive=is_alive_mock) + + def mock_terminate(proc, *args, **kwargs): + proc.communicate = mock.Mock(return_value=(mock.Mock(), mock.Mock())) + + def mock_communicate(*args, **kwargs): + if raise_timeout: + raise TimeoutExpired('dummy cmd', 'dummyamount') + return mock.Mock(), mock.Mock() + + def mock_popen(command, *args, **kwargs): + if raise_popen: + raise CalledProcessError('dummy proc', 'dummy msg') + + mock_process = mock.Mock( + pid=1, + returncode=returncode, + communicate=mock.Mock(side_effect=mock_communicate) + ) + + return mock.Mock( + __enter__=mock.Mock(return_value=mock_process), + __exit__=mock.Mock(return_value=None) + ) + + hardware = None if not has_hardware else mock.Mock( + baud=14400, + runner='dummy runner', + serial_pty='Serial PTY' if use_pty else None, + serial='dummy serial', + pre_script='dummy pre script', + post_script='dummy post script', + post_flash_script='dummy post flash script', + flash_timeout=60, + flash_with_test=True + ) + + handler = DeviceHandler(mocked_instance, 'build') + handler.get_hardware = mock.Mock(return_value=hardware) + handler.options = mock.Mock( + timeout_multiplier=1, + west_flash=None, + west_runner=None + ) + handler._get_serial_device = mock.Mock(side_effect=mock_get_serial) + handler._create_command = mock.Mock(return_value=['dummy', 'command']) + handler.run_custom_script = mock.Mock() + handler._create_serial_connection = mock.Mock( + side_effect=mock_create_serial + ) + handler.monitor_serial = mock.Mock() + handler.terminate = mock.Mock(side_effect=mock_terminate) + handler._update_instance_info = mock.Mock() + handler._final_handle_actions = mock.Mock() + handler.make_device_available = mock.Mock() + handler.instance.platform.name = 'IPName' + + harness = mock.Mock() + + with mock.patch('builtins.open', mock.mock_open(read_data='')), \ + mock.patch('subprocess.Popen', side_effect=mock_popen), \ + mock.patch('threading.Event', mock.Mock()), \ + mock.patch('threading.Thread', side_effect=mock_thread): + handler.handle(harness) + + handler.get_hardware.assert_called_once() + + messages = [record.msg for record in caplog.records] + assert all([msg in messages for msg in expected_logs]) + + if not has_hardware: + return + + handler.run_custom_script.assert_has_calls([ + mock.call('dummy pre script', mock.ANY) + ]) + + if raise_create_serial: + return + + handler.run_custom_script.assert_has_calls([ + mock.call('dummy pre script', mock.ANY), + mock.call('dummy post flash script', mock.ANY), + mock.call('dummy post script', mock.ANY) + ]) + + if expected_reason: + assert handler.instance.reason == expected_reason + if expected_status: + assert handler.instance.status == expected_status + + handler.make_device_available.assert_called_once_with( + 'Serial PTY' if use_pty else 'dummy serial device' + ) + + +TESTDATA_18 = [ + (True, True, True), + (False, False, False), +] + +@pytest.mark.parametrize( + 'ignore_qemu_crash, expected_ignore_crash, expected_ignore_unexpected_eof', + TESTDATA_18, + ids=['ignore crash', 'qemu crash'] +) +def test_qemuhandler_init( + mocked_instance, + ignore_qemu_crash, + expected_ignore_crash, + expected_ignore_unexpected_eof +): + mocked_instance.testsuite.ignore_qemu_crash = ignore_qemu_crash + + handler = QEMUHandler(mocked_instance, 'build') + + assert handler.ignore_qemu_crash == expected_ignore_crash + assert handler.ignore_unexpected_eof == expected_ignore_unexpected_eof + + +def test_qemuhandler_get_cpu_time(): + def mock_process(pid): + return mock.Mock( + cpu_times=mock.Mock( + return_value=mock.Mock( + user=20.0, + system=64.0 + ) + ) + ) + + with mock.patch('psutil.Process', mock_process): + res = QEMUHandler._get_cpu_time(0) + + assert res == pytest.approx(84.0) + + +TESTDATA_19 = [ + ( + True, + os.path.join('self', 'dummy_dir', '1'), + mock.PropertyMock(return_value=os.path.join('dummy_dir', '1')), + os.path.join('dummy_dir', '1') + ), + ( + False, + os.path.join('self', 'dummy_dir', '2'), + mock.PropertyMock(return_value=os.path.join('dummy_dir', '2')), + os.path.join('self', 'dummy_dir', '2') + ), +] + +@pytest.mark.parametrize( + 'self_sysbuild, self_build_dir, build_dir, expected', + TESTDATA_19, + ids=['domains build dir', 'self build dir'] +) +def test_qemuhandler_get_sysbuild_build_dir( + mocked_instance, + self_sysbuild, + self_build_dir, + build_dir, + expected +): + get_default_domain_mock = mock.Mock() + type(get_default_domain_mock()).build_dir = build_dir + domains_mock = mock.Mock(get_default_domain=get_default_domain_mock) + from_file_mock = mock.Mock(return_value=domains_mock) + + handler = QEMUHandler(mocked_instance, 'build') + handler.instance.testsuite.sysbuild = self_sysbuild + handler.build_dir = self_build_dir + + with mock.patch('domains.Domains.from_file', from_file_mock): + result = handler._get_sysbuild_build_dir() + + assert result == expected + + +TESTDATA_20 = [ + ( + os.path.join('self', 'dummy_dir', 'log1'), + os.path.join('self', 'dummy_dir', 'pid1'), + os.path.join('sysbuild', 'dummy_dir', 'bd1'), + True + ), + ( + os.path.join('self', 'dummy_dir', 'log2'), + os.path.join('self', 'dummy_dir', 'pid2'), + os.path.join('sysbuild', 'dummy_dir', 'bd2'), + False + ), +] + +@pytest.mark.parametrize( + 'self_log, self_pid_fn, sysbuild_build_dir, exists_pid_fn', + TESTDATA_20, + ids=['pid exists', 'pid missing'] +) +def test_qemuhandler_set_qemu_filenames( + mocked_instance, + self_log, + self_pid_fn, + sysbuild_build_dir, + exists_pid_fn +): + unlink_mock = mock.Mock() + exists_mock = mock.Mock(return_value=exists_pid_fn) + + handler = QEMUHandler(mocked_instance, 'build') + handler.log = self_log + handler.pid_fn = self_pid_fn + + with mock.patch('os.unlink', unlink_mock), \ + mock.patch('os.path.exists', exists_mock): + handler._set_qemu_filenames(sysbuild_build_dir) + + assert handler.fifo_fn == mocked_instance.build_dir + \ + os.path.sep + 'qemu-fifo' + + assert handler.pid_fn == sysbuild_build_dir + os.path.sep + 'qemu.pid' + + assert handler.log_fn == self_log + + if exists_pid_fn: + unlink_mock.assert_called_once_with(sysbuild_build_dir + \ + os.path.sep + 'qemu.pid') + + +def test_qemuhandler_create_command(mocked_instance): + sysbuild_build_dir = os.path.join('sysbuild', 'dummy_dir') + + handler = QEMUHandler(mocked_instance, 'build') + handler.generator_cmd = 'dummy_cmd' + + result = handler._create_command(sysbuild_build_dir) + + assert result == ['dummy_cmd', '-C', 'sysbuild' + os.path.sep + 'dummy_dir', + 'run'] + + +TESTDATA_21 = [ + ( + 0, + False, + None, + 'good dummy state', + False, + None, + None, + False + ), + ( + 1, + True, + None, + 'good dummy state', + False, + None, + None, + False + ), + ( + 0, + False, + None, + None, + True, + 'failed', + 'Timeout', + True + ), + ( + 1, + False, + None, + None, + False, + 'failed', + 'Exited with 1', + True + ), + ( + 1, + False, + 'preexisting reason', + 'good dummy state', + False, + 'failed', + 'preexisting reason', + True + ), +] + +@pytest.mark.parametrize( + 'self_returncode, self_ignore_qemu_crash,' \ + ' self_instance_reason, harness_state, is_timeout,' \ + ' expected_status, expected_reason, expected_called_missing_case', + TESTDATA_21, + ids=['not failed', 'qemu ignore', 'timeout', 'bad returncode', 'other fail'] +) +def test_qemuhandler_update_instance_info( + mocked_instance, + self_returncode, + self_ignore_qemu_crash, + self_instance_reason, + harness_state, + is_timeout, + expected_status, + expected_reason, + expected_called_missing_case +): + mocked_instance.add_missing_case_status = mock.Mock() + mocked_instance.reason = self_instance_reason + + handler = QEMUHandler(mocked_instance, 'build') + handler.returncode = self_returncode + handler.ignore_qemu_crash = self_ignore_qemu_crash + + handler._update_instance_info(harness_state, is_timeout) + + assert handler.instance.status == expected_status + assert handler.instance.reason == expected_reason + + if expected_called_missing_case: + mocked_instance.add_missing_case_status.assert_called_once_with( + 'blocked' + ) + + +def test_qemuhandler_thread_get_fifo_names(): + fifo_fn = 'dummy' + + fifo_in, fifo_out = QEMUHandler._thread_get_fifo_names(fifo_fn) + + assert fifo_in == 'dummy.in' + assert fifo_out == 'dummy.out' + +TESTDATA_22 = [ + (False, False), + (False, True), + (True, False), + (True, True), +] + +@pytest.mark.parametrize( + 'fifo_in_exists, fifo_out_exists', + TESTDATA_22, + ids=['both missing', 'out exists', 'in exists', 'both exist'] +) +def test_qemuhandler_thread_open_files(fifo_in_exists, fifo_out_exists): + def mock_exists(path): + if path == 'fifo.in': + return fifo_in_exists + elif path == 'fifo.out': + return fifo_out_exists + else: + raise ValueError('Unexpected path in mock of os.path.exists') + + unlink_mock = mock.Mock() + exists_mock = mock.Mock(side_effect=mock_exists) + mkfifo_mock = mock.Mock() + + fifo_in = 'fifo.in' + fifo_out = 'fifo.out' + logfile = 'log.file' + + with mock.patch('os.unlink', unlink_mock), \ + mock.patch('os.mkfifo', mkfifo_mock), \ + mock.patch('os.path.exists', exists_mock), \ + mock.patch('builtins.open', mock.mock_open()) as open_mock: + _, _, _ = QEMUHandler._thread_open_files(fifo_in, fifo_out, logfile) + + open_mock.assert_has_calls([ + mock.call('fifo.in', 'wb'), + mock.call('fifo.out', 'rb', buffering=0), + mock.call('log.file', 'wt'), + ]) + + if fifo_in_exists: + unlink_mock.assert_any_call('fifo.in') + + if fifo_out_exists: + unlink_mock.assert_any_call('fifo.out') + + +TESTDATA_23 = [ + (False, False), + (True, True), + (True, False) +] + +@pytest.mark.parametrize( + 'is_pid, is_lookup_error', + TESTDATA_23, + ids=['pid missing', 'pid lookup error', 'pid ok'] +) +def test_qemuhandler_thread_close_files(is_pid, is_lookup_error): + is_process_killed = {} + + def mock_kill(pid, sig): + if is_lookup_error: + raise ProcessLookupError(f'Couldn\'t find pid: {pid}.') + elif sig == signal.SIGTERM: + is_process_killed[pid] = True + + unlink_mock = mock.Mock() + kill_mock = mock.Mock(side_effect=mock_kill) + + fifo_in = 'fifo.in' + fifo_out = 'fifo.out' + pid = 12345 if is_pid else None + out_fp = mock.Mock() + in_fp = mock.Mock() + log_out_fp = mock.Mock() + + with mock.patch('os.unlink', unlink_mock), \ + mock.patch('os.kill', kill_mock): + QEMUHandler._thread_close_files(fifo_in, fifo_out, pid, out_fp, + in_fp, log_out_fp) + + out_fp.close.assert_called_once() + in_fp.close.assert_called_once() + log_out_fp.close.assert_called_once() + + unlink_mock.assert_has_calls([mock.call('fifo.in'), mock.call('fifo.out')]) + + if is_pid and not is_lookup_error: + assert is_process_killed[pid] + + +TESTDATA_24 = [ + ('timeout', 'failed', 'Timeout'), + ('failed', 'failed', 'Failed'), + ('unexpected eof', 'failed', 'unexpected eof'), + ('unexpected byte', 'failed', 'unexpected byte'), + (None, None, 'Unknown'), +] + +@pytest.mark.parametrize( + 'out_state, expected_status, expected_reason', + TESTDATA_24, + ids=['timeout', 'failed', 'unexpected eof', 'unexpected byte', 'unknown'] +) +def test_qemuhandler_thread_update_instance_info( + mocked_instance, + out_state, + expected_status, + expected_reason +): + handler = QEMUHandler(mocked_instance, 'build') + handler_time = 59 + + QEMUHandler._thread_update_instance_info(handler, handler_time, out_state) + + assert handler.instance.execution_time == handler_time + + assert handler.instance.status == expected_status + assert handler.instance.reason == expected_reason + + +TESTDATA_25 = [ + ( + ('1\n' * 60).encode('utf-8'), + 60, + 1, + [None] * 60 + ['success'] * 6, + 1000, + False, + 'timeout', + [mock.call('1\n'), mock.call('1\n')] + ), + ( + ('1\n' * 60).encode('utf-8'), + 60, + -1, + [None] * 60 + ['success'] * 30, + 100, + False, + 'failed', + [mock.call('1\n'), mock.call('1\n')] + ), + ( + b'', + 60, + 1, + ['success'] * 3, + 100, + False, + 'unexpected eof', + [] + ), + ( + b'\x81', + 60, + 1, + ['success'] * 3, + 100, + False, + 'unexpected byte', + [] + ), + ( + '1\n2\n3\n4\n5\n'.encode('utf-8'), + 600, + 1, + [None] * 3 + ['success'] * 7, + 100, + False, + 'success', + [mock.call('1\n'), mock.call('2\n'), mock.call('3\n'), mock.call('4\n')] + ), + ( + '1\n2\n3\n4\n5\n'.encode('utf-8'), + 600, + 0, + [None] * 3 + ['success'] * 7, + 100, + False, + 'timeout', + [mock.call('1\n'), mock.call('2\n')] + ), + ( + '1\n2\n3\n4\n5\n'.encode('utf-8'), + 60, + 1, + [None] * 3 + ['success'] * 7, + (n for n in [100, 100, 10000]), + True, + 'success', + [mock.call('1\n'), mock.call('2\n'), mock.call('3\n'), mock.call('4\n')] + ), +] + +@pytest.mark.parametrize( + 'content, timeout, pid, harness_states, cputime, capture_coverage,' \ + ' expected_out_state, expected_log_calls', + TESTDATA_25, + ids=[ + 'timeout', + 'harness failed', + 'unexpected eof', + 'unexpected byte', + 'harness success', + 'timeout by pid=0', + 'capture_coverage' + ] +) +def test_qemuhandler_thread( + mocked_instance, + faux_timer, + content, + timeout, + pid, + harness_states, + cputime, + capture_coverage, + expected_out_state, + expected_log_calls +): + def mock_cputime(pid): + if pid > 0: + return cputime if isinstance(cputime, int) else next(cputime) + else: + raise ProcessLookupError() + + type(mocked_instance.testsuite).timeout = mock.PropertyMock(return_value=timeout) + handler = QEMUHandler(mocked_instance, 'build') + handler.results = {} + handler.ignore_unexpected_eof = False + handler.pid_fn = 'pid_fn' + handler.fifo_fn = 'fifo_fn' + handler.options = mock.Mock(timeout_multiplier=1) + + def mocked_open(filename, *args, **kwargs): + if filename == handler.pid_fn: + contents = str(pid).encode('utf-8') + elif filename == handler.fifo_fn + '.out': + contents = content + else: + contents = b'' + + file_object = mock.mock_open(read_data=contents).return_value + file_object.__iter__.return_value = contents.splitlines(True) + return file_object + + harness = mock.Mock(capture_coverage=capture_coverage, handle=print) + type(harness).state = mock.PropertyMock(side_effect=harness_states) + + p = mock.Mock() + p.poll = mock.Mock( + side_effect=itertools.cycle([True, True, True, True, False]) + ) + + mock_thread_get_fifo_names = mock.Mock( + return_value=('fifo_fn.in', 'fifo_fn.out') + ) + log_fp_mock = mock.Mock() + in_fp_mock = mocked_open('fifo_fn.out') + out_fp_mock = mock.Mock() + mock_thread_open_files = mock.Mock( + return_value=(out_fp_mock, in_fp_mock, log_fp_mock) + ) + mock_thread_close_files = mock.Mock() + mock_thread_update_instance_info = mock.Mock() + + with mock.patch('time.time', side_effect=faux_timer.time), \ + mock.patch('builtins.open', new=mocked_open), \ + mock.patch('select.poll', return_value=p), \ + mock.patch('os.path.exists', return_value=True), \ + mock.patch('twisterlib.handlers.QEMUHandler._get_cpu_time', + mock_cputime), \ + mock.patch('twisterlib.handlers.QEMUHandler._thread_get_fifo_names', + mock_thread_get_fifo_names), \ + mock.patch('twisterlib.handlers.QEMUHandler._thread_open_files', + mock_thread_open_files), \ + mock.patch('twisterlib.handlers.QEMUHandler._thread_close_files', + mock_thread_close_files), \ + mock.patch('twisterlib.handlers.QEMUHandler.' \ + '_thread_update_instance_info', + mock_thread_update_instance_info): + QEMUHandler._thread( + handler, + handler.get_test_timeout(), + handler.build_dir, + handler.log, + handler.fifo_fn, + handler.pid_fn, + handler.results, + harness, + handler.ignore_unexpected_eof + ) + + mock_thread_update_instance_info.assert_called_once_with( + handler, + mock.ANY, + expected_out_state + ) + + log_fp_mock.write.assert_has_calls(expected_log_calls) + + +TESTDATA_26 = [ + (True, False, None, True, + ['No timeout, return code from QEMU (1): 1', + 'return code from QEMU (1): 1']), + (False, True, 'passed', True, ['return code from QEMU (1): 0']), + (False, True, 'failed', False, ['return code from QEMU (None): 1']), +] + +@pytest.mark.parametrize( + 'isatty, do_timeout, harness_state, exists_pid_fn, expected_logs', + TESTDATA_26, + ids=['no timeout, isatty', 'timeout passed', 'timeout, no pid_fn'] +) +def test_qemuhandler_handle( + mocked_instance, + caplog, + tmp_path, + isatty, + do_timeout, + harness_state, + exists_pid_fn, + expected_logs +): + def mock_wait(*args, **kwargs): + if do_timeout: + raise TimeoutExpired('dummy cmd', 'dummyamount') + + mock_process = mock.Mock(pid=0, returncode=1) + mock_process.communicate = mock.Mock( + return_value=(mock.Mock(), mock.Mock()) + ) + mock_process.wait = mock.Mock(side_effect=mock_wait) + + handler = QEMUHandler(mocked_instance, 'build') + + def mock_path_exists(name, *args, **kwargs): + return exists_pid_fn + + def mock_popen(command, stdout=None, stdin=None, stderr=None, cwd=None): + return mock.Mock( + __enter__=mock.Mock(return_value=mock_process), + __exit__=mock.Mock(return_value=None), + communicate=mock.Mock(return_value=(mock.Mock(), mock.Mock())) + ) + + def mock_thread(name=None, target=None, daemon=None, args=None): + return mock.Mock() + + def mock_filenames(sysbuild_build_dir): + handler.fifo_fn = os.path.join('dummy', 'qemu-fifo') + handler.pid_fn = os.path.join(sysbuild_build_dir, 'qemu.pid') + handler.log_fn = os.path.join('dummy', 'log') + + harness = mock.Mock(state=harness_state) + handler_options_west_flash = [] + + sysbuild_build_dir = os.path.join('sysbuild', 'dummydir') + command = ['generator_cmd', '-C', os.path.join('cmd', 'path'), 'run'] + + handler.options = mock.Mock( + timeout_multiplier=1, + west_flash=handler_options_west_flash, + west_runner=None + ) + handler.run_custom_script = mock.Mock(return_value=None) + handler.make_device_available = mock.Mock(return_value=None) + handler._final_handle_actions = mock.Mock(return_value=None) + handler._create_command = mock.Mock(return_value=command) + handler._set_qemu_filenames = mock.Mock(side_effect=mock_filenames) + handler._get_sysbuild_build_dir = mock.Mock(return_value=sysbuild_build_dir) + handler.terminate = mock.Mock() + + unlink_mock = mock.Mock() + + with mock.patch('subprocess.Popen', side_effect=mock_popen), \ + mock.patch('builtins.open', mock.mock_open(read_data='1')), \ + mock.patch('threading.Thread', side_effect=mock_thread), \ + mock.patch('os.path.exists', side_effect=mock_path_exists), \ + mock.patch('os.unlink', unlink_mock), \ + mock.patch('sys.stdout.isatty', return_value=isatty): + handler.handle(harness) + + assert all([expected_log in caplog.text for expected_log in expected_logs]) + + +def test_qemuhandler_get_fifo(mocked_instance): + handler = QEMUHandler(mocked_instance, 'build') + handler.fifo_fn = 'fifo_fn' + + result = handler.get_fifo() + + assert result == 'fifo_fn' diff --git a/scripts/tests/twister/test_hardwaremap.py b/scripts/tests/twister/test_hardwaremap.py new file mode 100644 index 00000000000..57c028bfea6 --- /dev/null +++ b/scripts/tests/twister/test_hardwaremap.py @@ -0,0 +1,722 @@ +#!/usr/bin/env python3 +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +""" +Tests for hardwaremap.py classes' methods +""" + +import mock +import pytest +import sys + +from pathlib import Path + +from twisterlib.hardwaremap import( + DUT, + HardwareMap +) + + +@pytest.fixture +def mocked_hm(): + duts = [ + DUT(platform='p1', id=1, serial='s1', product='pr1', connected=True), + DUT(platform='p2', id=2, serial='s2', product='pr2', connected=False), + DUT(platform='p3', id=3, serial='s3', product='pr3', connected=True), + DUT(platform='p4', id=4, serial='s4', product='pr4', connected=False), + DUT(platform='p5', id=5, serial='s5', product='pr5', connected=True), + DUT(platform='p6', id=6, serial='s6', product='pr6', connected=False), + DUT(platform='p7', id=7, serial='s7', product='pr7', connected=True), + DUT(platform='p8', id=8, serial='s8', product='pr8', connected=False) + ] + + hm = HardwareMap(env=mock.Mock()) + hm.duts = duts + hm.detected = duts[:5] + + return hm + + +TESTDATA_1 = [ + ( + {}, + {'baud': 115200, 'lock': mock.ANY, 'flash_timeout': 60}, + '' + ), + ( + { + 'id': 'dummy id', + 'serial': 'dummy serial', + 'serial_baud': 4400, + 'platform': 'dummy platform', + 'product': 'dummy product', + 'serial_pty': 'dummy serial pty', + 'connected': True, + 'runner_params': ['dummy', 'runner', 'params'], + 'pre_script': 'dummy pre script', + 'post_script': 'dummy post script', + 'post_flash_script': 'dummy post flash script', + 'runner': 'dummy runner', + 'flash_timeout': 30, + 'flash_with_test': True + }, + { + 'lock': mock.ANY, + 'id': 'dummy id', + 'serial': 'dummy serial', + 'baud': 4400, + 'platform': 'dummy platform', + 'product': 'dummy product', + 'serial_pty': 'dummy serial pty', + 'connected': True, + 'runner_params': ['dummy', 'runner', 'params'], + 'pre_script': 'dummy pre script', + 'post_script': 'dummy post script', + 'post_flash_script': 'dummy post flash script', + 'runner': 'dummy runner', + 'flash_timeout': 30, + 'flash_with_test': True + }, + '' + ), +] + + +@pytest.mark.parametrize( + 'kwargs, expected_dict, expected_repr', + TESTDATA_1, + ids=['no information', 'full information'] +) +def test_dut(kwargs, expected_dict, expected_repr): + d = DUT(**kwargs) + + assert d.available + assert d.counter == 0 + + d.available = False + d.counter = 1 + + assert not d.available + assert d.counter == 1 + + assert d.to_dict() == expected_dict + assert d.__repr__() == expected_repr + + +TESTDATA_2 = [ + ('ghm.yaml', mock.ANY, mock.ANY, [], mock.ANY, mock.ANY, mock.ANY, 0, + True, True, False, False, False, False, []), + (None, False, 'hm.yaml', [], mock.ANY, mock.ANY, mock.ANY, 0, + False, False, True, True, False, False, []), + (None, True, 'hm.yaml', [], mock.ANY, mock.ANY, ['fix'], 1, + False, False, True, False, False, True, ['p1', 'p3', 'p5', 'p7']), + (None, True, 'hm.yaml', ['pX'], mock.ANY, mock.ANY, ['fix'], 1, + False, False, True, False, False, True, ['pX']), + (None, True, None, ['p'], 's', None, ['fix'], 1, + False, False, False, False, True, True, ['p']), + (None, True, None, ['p'], None, 'spty', ['fix'], 1, + False, False, False, False, True, True, ['p']), +] + + +@pytest.mark.parametrize( + 'generate_hardware_map, device_testing, hardware_map, platform,' \ + ' device_serial, device_serial_pty, fixtures,' \ + ' return_code, expect_scan, expect_save, expect_load,' \ + ' expect_dump, expect_add_device, expect_fixtures, expected_platforms', + TESTDATA_2, + ids=['generate hardware map', 'existing hardware map', + 'device testing with hardware map, no platform', + 'device testing with hardware map with platform', + 'device testing with device serial', + 'device testing with device serial pty'] +) +def test_hardwaremap_discover( + caplog, + mocked_hm, + generate_hardware_map, + device_testing, + hardware_map, + platform, + device_serial, + device_serial_pty, + fixtures, + return_code, + expect_scan, + expect_save, + expect_load, + expect_dump, + expect_add_device, + expect_fixtures, + expected_platforms +): + def mock_load(*args): + mocked_hm.platform = platform + + mocked_hm.scan = mock.Mock() + mocked_hm.save = mock.Mock() + mocked_hm.load = mock.Mock(side_effect=mock_load) + mocked_hm.dump = mock.Mock() + mocked_hm.add_device = mock.Mock() + + mocked_hm.options.device_flash_with_test = True + mocked_hm.options.device_flash_timeout = 15 + mocked_hm.options.pre_script = 'dummy pre script' + mocked_hm.options.platform = platform + mocked_hm.options.device_serial = device_serial + mocked_hm.options.device_serial_pty = device_serial_pty + mocked_hm.options.device_testing = device_testing + mocked_hm.options.hardware_map = hardware_map + mocked_hm.options.persistent_hardware_map = mock.Mock() + mocked_hm.options.generate_hardware_map = generate_hardware_map + mocked_hm.options.fixture = fixtures + + returncode = mocked_hm.discover() + + assert returncode == return_code + + if expect_scan: + mocked_hm.scan.assert_called_once_with( + persistent=mocked_hm.options.persistent_hardware_map + ) + if expect_save: + mocked_hm.save.assert_called_once_with( + mocked_hm.options.generate_hardware_map + ) + if expect_load: + mocked_hm.load.assert_called_once_with( + mocked_hm.options.hardware_map + ) + if expect_dump: + mocked_hm.dump.assert_called_once_with( + connected_only=True + ) + if expect_add_device: + mocked_hm.add_device.assert_called_once() + + if expect_fixtures: + assert all( + [all( + [fixture in dut.fixtures for fixture in fixtures] + ) for dut in mocked_hm.duts] + ) + + assert sorted(expected_platforms) == sorted(mocked_hm.options.platform) + + +def test_hardwaremap_summary(capfd, mocked_hm): + selected_platforms = ['p0', 'p1', 'p6', 'p7'] + + mocked_hm.summary(selected_platforms) + + expected = """ +Hardware distribution summary: + +| Board | ID | Counter | +|---------|------|-----------| +| p1 | 1 | 0 | +| p7 | 7 | 0 | +""" + + out, err = capfd.readouterr() + sys.stdout.write(out) + sys.stderr.write(err) + + assert expected in out + + +TESTDATA_3 = [ + (True), + (False) +] + + +@pytest.mark.parametrize( + 'is_pty', + TESTDATA_3, + ids=['pty', 'not pty'] +) +def test_hardwaremap_add_device(is_pty): + hm = HardwareMap(env=mock.Mock()) + + serial = 'dummy' + platform = 'p0' + pre_script = 'dummy pre script' + hm.add_device(serial, platform, pre_script, is_pty) + + assert len(hm.duts) == 1 + if is_pty: + assert hm.duts[0].serial_pty == 'dummy' if is_pty else None + assert hm.duts[0].serial is None + else: + assert hm.duts[0].serial_pty is None + assert hm.duts[0].serial == 'dummy' + + +def test_hardwaremap_load(): + map_file = \ +""" +- id: id0 + platform: p0 + product: pr0 + runner: r0 + flash_with_test: True + flash_timeout: 15 + baud: 14400 + fixtures: + - dummy fixture 1 + - dummy fixture 2 + connected: True + serial: 'dummy' +- id: id1 + platform: p1 + product: pr1 + runner: r1 + connected: True + serial_pty: 'dummy' +- id: id2 + platform: p2 + product: pr2 + runner: r2 + connected: True +""" + map_filename = 'map-file.yaml' + + builtin_open = open + + def mock_open(*args, **kwargs): + if args[0] == map_filename: + return mock.mock_open(read_data=map_file)(*args, **kwargs) + return builtin_open(*args, **kwargs) + + hm = HardwareMap(env=mock.Mock()) + hm.options.device_flash_timeout = 30 + hm.options.device_flash_with_test = False + + with mock.patch('builtins.open', mock_open): + hm.load(map_filename) + + expected = { + 'id0': { + 'platform': 'p0', + 'product': 'pr0', + 'runner': 'r0', + 'flash_timeout': 15, + 'flash_with_test': True, + 'baud': 14400, + 'fixtures': ['dummy fixture 1', 'dummy fixture 2'], + 'connected': True, + 'serial': 'dummy', + 'serial_pty': None, + }, + 'id1': { + 'platform': 'p1', + 'product': 'pr1', + 'runner': 'r1', + 'flash_timeout': 30, + 'flash_with_test': False, + 'baud': 115200, + 'fixtures': [], + 'connected': True, + 'serial': None, + 'serial_pty': 'dummy', + }, + } + + for dut in hm.duts: + assert dut.id in expected + assert all([getattr(dut, k) == v for k, v in expected[dut.id].items()]) + + +TESTDATA_4 = [ + ( + True, + 'Linux', + ['', '', '', + '', '', + '', + '', + ''] + ), + ( + True, + 'nt', + ['', '', '', + '', '', + '', + '', + ''] + ), + ( + False, + 'Linux', + ['', '', '', + '', '', + '', + '', + ''] + ) +] + + +@pytest.mark.parametrize( + 'persistent, system, expected_reprs', + TESTDATA_4, + ids=['linux persistent map', 'no map (not linux)', 'no map (nonpersistent)'] +) +def test_hardwaremap_scan( + caplog, + mocked_hm, + persistent, + system, + expected_reprs +): + def mock_resolve(path): + if str(path).endswith('-link'): + return Path(str(path)[:-5]) + return path + + def mock_iterdir(path): + return [ + Path(path / 'basic-file1'), + Path(path / 'basic-file2-link') + ] + + mocked_hm.manufacturer = ['dummy manufacturer', 'Texas Instruments'] + mocked_hm.runner_mapping = { + 'dummy runner': ['product[0-9]+',], + 'other runner': ['other TI product', 'TI product'] + } + + comports_mock = [ + mock.Mock( + manufacturer='wrong manufacturer', + location='wrong location', + serial_number='wrong number', + product='wrong product', + device='wrong device' + ), + mock.Mock( + manufacturer='dummy manufacturer', + location='dummy location', + serial_number='dummy number', + product=None, + device='/dev/serial/by-id/basic-file2' + ), + mock.Mock( + manufacturer='dummy manufacturer', + location='dummy location', + serial_number='dummy number', + product='product123', + device='dummy device' + ), + mock.Mock( + manufacturer='Texas Instruments', + location='serial1', + serial_number='TI1', + product='TI product', + device='TI device1' + ), + mock.Mock( + manufacturer='Texas Instruments', + location='serial0', + serial_number='TI0', + product='TI product', + device='/dev/serial/by-id/basic-file1' + ), + ] + + with mock.patch('platform.system', return_value=system), \ + mock.patch('serial.tools.list_ports.comports', + return_value=comports_mock), \ + mock.patch('twisterlib.hardwaremap.Path.resolve', + autospec=True, side_effect=mock_resolve), \ + mock.patch('twisterlib.hardwaremap.Path.iterdir', + autospec=True, side_effect=mock_iterdir): + mocked_hm.scan(persistent) + + assert sorted([d.__repr__() for d in mocked_hm.detected]) == \ + sorted(expected_reprs) + + assert 'Scanning connected hardware...' in caplog.text + assert 'Unsupported device (wrong manufacturer): %s' % comports_mock[0] \ + in caplog.text + + +TESTDATA_5 = [ + ( + None, + [{ + 'platform': 'p1', + 'id': 1, + 'runner': mock.ANY, + 'serial': 's1', + 'product': 'pr1', + 'connected': True + }, + { + 'platform': 'p2', + 'id': 2, + 'runner': mock.ANY, + 'serial': 's2', + 'product': 'pr2', + 'connected': False + }, + { + 'platform': 'p3', + 'id': 3, + 'runner': mock.ANY, + 'serial': 's3', + 'product': 'pr3', + 'connected': True + }, + { + 'platform': 'p4', + 'id': 4, + 'runner': mock.ANY, + 'serial': 's4', + 'product': 'pr4', + 'connected': False + }, + { + 'platform': 'p5', + 'id': 5, + 'runner': mock.ANY, + 'serial': 's5', + 'product': 'pr5', + 'connected': True + }] + ), + ( + '', + [{ + 'serial': 's1', + 'baud': 115200, + 'platform': 'p1', + 'connected': True, + 'id': 1, + 'product': 'pr1', + 'lock': mock.ANY, + 'flash_timeout': 60 + }, + { + 'serial': 's2', + 'baud': 115200, + 'platform': 'p2', + 'id': 2, + 'product': 'pr2', + 'lock': mock.ANY, + 'flash_timeout': 60 + }, + { + 'serial': 's3', + 'baud': 115200, + 'platform': 'p3', + 'connected': True, + 'id': 3, + 'product': 'pr3', + 'lock': mock.ANY, + 'flash_timeout': 60 + }, + { + 'serial': 's4', + 'baud': 115200, + 'platform': 'p4', + 'id': 4, + 'product': 'pr4', + 'lock': mock.ANY, + 'flash_timeout': 60 + }, + { + 'serial': 's5', + 'baud': 115200, + 'platform': 'p5', + 'connected': True, + 'id': 5, + 'product': 'pr5', + 'lock': mock.ANY, + 'flash_timeout': 60 + }] + ), + ( +""" +- id: 4 + platform: p4 + product: pr4 + connected: True + serial: s4 +- id: 0 + platform: p0 + product: pr0 + connected: True + serial: s0 +- id: 10 + platform: p10 + product: pr10 + connected: False + serial: s10 +- id: 5 + platform: p5-5 + product: pr5-5 + connected: True + serial: s5-5 +""", + [{ + 'id': 0, + 'platform': 'p0', + 'product': 'pr0', + 'connected': False, + 'serial': None + }, + { + 'id': 4, + 'platform': 'p4', + 'product': 'pr4', + 'connected': True, + 'serial': 's4' + }, + { + 'id': 5, + 'platform': 'p5-5', + 'product': 'pr5-5', + 'connected': False, + 'serial': None + }, + { + 'id': 10, + 'platform': 'p10', + 'product': 'pr10', + 'connected': False, + 'serial': None + }, + { + 'serial': 's1', + 'baud': 115200, + 'platform': 'p1', + 'connected': True, + 'id': 1, + 'product': 'pr1', + 'lock': mock.ANY, + 'flash_timeout': 60 + }, + { + 'serial': 's2', + 'baud': 115200, + 'platform': 'p2', + 'id': 2, + 'product': 'pr2', + 'lock': mock.ANY, + 'flash_timeout': 60 + }, + { + 'serial': 's3', + 'baud': 115200, + 'platform': 'p3', + 'connected': True, + 'id': 3, + 'product': 'pr3', + 'lock': mock.ANY, + 'flash_timeout': 60 + }, + { + 'serial': 's5', + 'baud': 115200, + 'platform': 'p5', + 'connected': True, + 'id': 5, + 'product': 'pr5', + 'lock': mock.ANY, + 'flash_timeout': 60 + }] + ), +] + + +@pytest.mark.parametrize( + 'hwm, expected_dump', + TESTDATA_5, + ids=['no map', 'empty map', 'map exists'] +) +def test_hardwaremap_save(mocked_hm, hwm, expected_dump): + read_mock = mock.mock_open(read_data=hwm) + write_mock = mock.mock_open() + + def mock_open(filename, mode): + if mode == 'r': + return read_mock() + elif mode == 'w': + return write_mock() + + + mocked_hm.load = mock.Mock() + mocked_hm.dump = mock.Mock() + + open_mock = mock.Mock(side_effect=mock_open) + dump_mock = mock.Mock() + + with mock.patch('os.path.exists', return_value=hwm is not None), \ + mock.patch('builtins.open', open_mock), \ + mock.patch('twisterlib.hardwaremap.yaml.dump', dump_mock): + mocked_hm.save('hwm.yaml') + + dump_mock.assert_called_once_with(expected_dump, mock.ANY, Dumper=mock.ANY, + default_flow_style=mock.ANY) + + +TESTDATA_6 = [ + ( + ['p1', 'p3', 'p5', 'p7'], + [], + True, + True, +""" +| Platform | ID | Serial device | +|------------|------|-----------------| +| p1 | 1 | s1 | +| p3 | 3 | s3 | +| p5 | 5 | s5 | +""" + ), + ( + [], + ['?', '??', '???'], + False, + False, +""" +| ? | ?? | ??? | +|-----|------|-------| +| p1 | 1 | s1 | +| p2 | 2 | s2 | +| p3 | 3 | s3 | +| p4 | 4 | s4 | +| p5 | 5 | s5 | +| p6 | 6 | s6 | +| p7 | 7 | s7 | +| p8 | 8 | s8 | +""" + ), +] + + +@pytest.mark.parametrize( + 'filtered, header, connected_only, detected, expected_out', + TESTDATA_6, + ids=['detected no header', 'all with header'] +) +def test_hardwaremap_dump( + capfd, + mocked_hm, + filtered, + header, + connected_only, + detected, + expected_out +): + mocked_hm.dump(filtered, header, connected_only, detected) + + out, err = capfd.readouterr() + sys.stdout.write(out) + sys.stderr.write(err) + + assert out.strip() == expected_out.strip() diff --git a/scripts/tests/twister/test_jobserver.py b/scripts/tests/twister/test_jobserver.py new file mode 100644 index 00000000000..c97e9320447 --- /dev/null +++ b/scripts/tests/twister/test_jobserver.py @@ -0,0 +1,457 @@ +#!/usr/bin/env python3 +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +""" +Tests for jobserver.py classes' methods +""" + +import functools +import mock +import os +import pytest +import sys + +from contextlib import nullcontext +from errno import ENOENT +from fcntl import F_GETFL +from selectors import EVENT_READ + +from twisterlib.jobserver import ( + JobHandle, + JobClient, + GNUMakeJobClient, + GNUMakeJobServer +) + + +def test_jobhandle(capfd): + def f(a, b, c=None, d=None): + print(f'{a}, {b}, {c}, {d}') + + def exiter(): + with JobHandle(f, 1, 2, c='three', d=4): + return + + exiter() + + out, err = capfd.readouterr() + sys.stdout.write(out) + sys.stderr.write(err) + + assert '1, 2, three, 4' in out + + +def test_jobclient_get_job(): + jc = JobClient() + + job = jc.get_job() + + assert isinstance(job, JobHandle) + assert job.release_func is None + + +def test_jobclient_env(): + env = JobClient.env() + + assert env == {} + + +def test_jobclient_pass_fds(): + fds = JobClient.pass_fds() + + assert fds == [] + + +TESTDATA_1 = [ + ({}, {'env': {'k': 'v'}, 'pass_fds': []}), + ({'env': {}, 'pass_fds': ['fd']}, {'env': {}, 'pass_fds': ['fd']}), +] + +@pytest.mark.parametrize( + 'kwargs, expected_kwargs', + TESTDATA_1, + ids=['no values', 'preexisting values'] +) +def test_jobclient_popen(kwargs, expected_kwargs): + jc = JobClient() + + argv = ['cmd', 'and', 'some', 'args'] + proc_mock = mock.Mock() + popen_mock = mock.Mock(return_value=proc_mock) + env_mock = {'k': 'v'} + + with mock.patch('subprocess.Popen', popen_mock), \ + mock.patch('os.environ', env_mock): + proc = jc.popen(argv, **kwargs) + + popen_mock.assert_called_once_with(argv, **expected_kwargs) + assert proc == proc_mock + + +TESTDATA_2 = [ + (False, 0), + (True, 0), + (False, 4), + (True, 16), +] + + +@pytest.mark.parametrize( + 'inheritable, internal_jobs', + TESTDATA_2, + ids=['no inheritable, no internal', 'inheritable, no internal', + 'no inheritable, internal', 'inheritable, internal'] +) +def test_gnumakejobclient_dunders(inheritable, internal_jobs): + inherit_read_fd = mock.Mock() + inherit_write_fd = mock.Mock() + inheritable_pipe = (inherit_read_fd, inherit_write_fd) if inheritable else \ + None + + internal_read_fd = mock.Mock() + internal_write_fd = mock.Mock() + + def mock_pipe(): + return (internal_read_fd, internal_write_fd) + + close_mock = mock.Mock() + write_mock = mock.Mock() + set_blocking_mock = mock.Mock() + selector_mock = mock.Mock() + + def deleter(): + jobs = mock.Mock() + makeflags = mock.Mock() + + gmjc = GNUMakeJobClient( + inheritable_pipe, + jobs, + internal_jobs=internal_jobs, + makeflags=makeflags + ) + + assert gmjc.jobs == jobs + if internal_jobs: + write_mock.assert_called_once_with(internal_write_fd, + b'+' * internal_jobs) + set_blocking_mock.assert_any_call(internal_read_fd, False) + selector_mock().register.assert_any_call(internal_read_fd, + EVENT_READ, + internal_write_fd) + if inheritable: + set_blocking_mock.assert_any_call(inherit_read_fd, False) + selector_mock().register.assert_any_call(inherit_read_fd, + EVENT_READ, + inherit_write_fd) + + with mock.patch('os.close', close_mock), \ + mock.patch('os.write', write_mock), \ + mock.patch('os.set_blocking', set_blocking_mock), \ + mock.patch('os.pipe', mock_pipe), \ + mock.patch('selectors.DefaultSelector', selector_mock): + deleter() + + if internal_jobs: + close_mock.assert_any_call(internal_read_fd) + close_mock.assert_any_call(internal_write_fd) + if inheritable: + close_mock.assert_any_call(inherit_read_fd) + close_mock.assert_any_call(inherit_write_fd) + + +TESTDATA_3 = [ + ( + {'MAKEFLAGS': '-j1'}, + 0, + (False, False), + ['Running in sequential mode (-j1)'], + None, + [None, 1], + {'internal_jobs': 1, 'makeflags': '-j1'} + ), + ( + {'MAKEFLAGS': 'n--jobserver-auth=0,1'}, + 1, + (True, True), + [ + '-jN forced on command line; ignoring GNU make jobserver', + 'MAKEFLAGS contained dry-run flag' + ], + 0, + None, + None + ), + ( + {'MAKEFLAGS': '--jobserver-auth=0,1'}, + 0, + (True, True), + ['using GNU make jobserver'], + None, + [[0, 1], 0], + {'internal_jobs': 1, 'makeflags': '--jobserver-auth=0,1'} + ), + ( + {'MAKEFLAGS': '--jobserver-auth=123,321'}, + 0, + (False, False), + ['No file descriptors; ignoring GNU make jobserver'], + None, + [None, 0], + {'internal_jobs': 1, 'makeflags': '--jobserver-auth=123,321'} + ), + ( + {'MAKEFLAGS': '--jobserver-auth=0,1'}, + 0, + (False, True), + [f'FD 0 is not readable (flags=2); ignoring GNU make jobserver'], + None, + [None, 0], + {'internal_jobs': 1, 'makeflags': '--jobserver-auth=0,1'} + ), + ( + {'MAKEFLAGS': '--jobserver-auth=0,1'}, + 0, + (True, False), + [f'FD 1 is not writable (flags=2); ignoring GNU make jobserver'], + None, + [None, 0], + {'internal_jobs': 1, 'makeflags': '--jobserver-auth=0,1'} + ), + (None, 0, (False, False), [], None, None, None), +] + +@pytest.mark.parametrize( + 'env, jobs, fcntl_ok_per_pipe, expected_logs,' \ + ' exit_code, expected_args, expected_kwargs', + TESTDATA_3, + ids=['env, no jobserver-auth', 'env, jobs, dry run', 'env, no jobs', + 'env, no jobs, oserror', 'env, no jobs, wrong read pipe', + 'env, no jobs, wrong write pipe', 'environ, no makeflags'] +) +def test_gnumakejobclient_from_environ( + caplog, + env, + jobs, + fcntl_ok_per_pipe, + expected_logs, + exit_code, + expected_args, + expected_kwargs +): + def mock_fcntl(fd, flag): + if flag == F_GETFL: + if fd == 0: + if fcntl_ok_per_pipe[0]: + return os.O_RDONLY + else: + return 2 + elif fd == 1: + if fcntl_ok_per_pipe[1]: + return os.O_WRONLY + else: + return 2 + raise OSError(ENOENT, 'dummy error') + + gmjc_init_mock = mock.Mock(return_value=None) + + with mock.patch('fcntl.fcntl', mock_fcntl), \ + mock.patch('os.close', mock.Mock()), \ + mock.patch('twisterlib.jobserver.GNUMakeJobClient.__init__', + gmjc_init_mock), \ + pytest.raises(SystemExit) if exit_code is not None else \ + nullcontext() as se: + gmjc = GNUMakeJobClient.from_environ(env=env, jobs=jobs) + + # As patching __del__ is hard to do, we'll instead + # cover possible exceptions and mock os calls + if gmjc: + gmjc._inheritable_pipe = getattr(gmjc, '_inheritable_pipe', None) + if gmjc: + gmjc._internal_pipe = getattr(gmjc, '_internal_pipe', None) + + assert all([log in caplog.text for log in expected_logs]) + + if se: + assert str(se.value) == str(exit_code) + return + + if expected_args is None and expected_kwargs is None: + assert gmjc is None + else: + gmjc_init_mock.assert_called_once_with(*expected_args, + **expected_kwargs) + + +def test_gnumakejobclient_get_job(): + inherit_read_fd = mock.Mock() + inherit_write_fd = mock.Mock() + inheritable_pipe = (inherit_read_fd, inherit_write_fd) + + internal_read_fd = mock.Mock() + internal_write_fd = mock.Mock() + + def mock_pipe(): + return (internal_read_fd, internal_write_fd) + + selected = [[mock.Mock(fd=0, data=1)], [mock.Mock(fd=1, data=0)]] + + def mock_select(): + nonlocal selected + return selected + + def mock_read(fd, length): + nonlocal selected + if fd == 0: + selected = selected[1:] + raise BlockingIOError + return b'?' * length + + close_mock = mock.Mock() + write_mock = mock.Mock() + set_blocking_mock = mock.Mock() + selector_mock = mock.Mock() + selector_mock().select = mock.Mock(side_effect=mock_select) + + def deleter(): + jobs = mock.Mock() + + gmjc = GNUMakeJobClient( + inheritable_pipe, + jobs + ) + + with mock.patch('os.read', side_effect=mock_read): + job = gmjc.get_job() + with job: + expected_func = functools.partial(os.write, 0, b'?') + + assert job.release_func.func == expected_func.func + assert job.release_func.args == expected_func.args + assert job.release_func.keywords == expected_func.keywords + + with mock.patch('os.close', close_mock), \ + mock.patch('os.write', write_mock), \ + mock.patch('os.set_blocking', set_blocking_mock), \ + mock.patch('os.pipe', mock_pipe), \ + mock.patch('selectors.DefaultSelector', selector_mock): + deleter() + + write_mock.assert_any_call(0, b'?') + + +TESTDATA_4 = [ + ('dummy makeflags', mock.ANY, mock.ANY, {'MAKEFLAGS': 'dummy makeflags'}), + (None, 0, False, {'MAKEFLAGS': ''}), + (None, 1, True, {'MAKEFLAGS': ' -j1'}), + (None, 2, True, {'MAKEFLAGS': ' -j2 --jobserver-auth=0,1'}), + (None, 0, True, {'MAKEFLAGS': ' --jobserver-auth=0,1'}), +] + +@pytest.mark.parametrize( + 'makeflags, jobs, use_inheritable_pipe, expected_makeflags', + TESTDATA_4, + ids=['preexisting makeflags', 'no jobs, no pipe', 'one job', + ' multiple jobs', 'no jobs'] +) +def test_gnumakejobclient_env( + makeflags, + jobs, + use_inheritable_pipe, + expected_makeflags +): + inheritable_pipe = (0, 1) if use_inheritable_pipe else None + + selector_mock = mock.Mock() + + env = None + + def deleter(): + gmjc = GNUMakeJobClient(None, None) + gmjc.jobs = jobs + gmjc._makeflags = makeflags + gmjc._inheritable_pipe = inheritable_pipe + + nonlocal env + env = gmjc.env() + + with mock.patch.object(GNUMakeJobClient, '__del__', mock.Mock()), \ + mock.patch('selectors.DefaultSelector', selector_mock): + deleter() + + assert env == expected_makeflags + + +TESTDATA_5 = [ + (2, False, []), + (1, True, []), + (2, True, (0, 1)), + (0, True, (0, 1)), +] + +@pytest.mark.parametrize( + 'jobs, use_inheritable_pipe, expected_fds', + TESTDATA_5, + ids=['no pipe', 'one job', ' multiple jobs', 'no jobs'] +) +def test_gnumakejobclient_pass_fds(jobs, use_inheritable_pipe, expected_fds): + inheritable_pipe = (0, 1) if use_inheritable_pipe else None + + selector_mock = mock.Mock() + + fds = None + + def deleter(): + gmjc = GNUMakeJobClient(None, None) + gmjc.jobs = jobs + gmjc._inheritable_pipe = inheritable_pipe + + nonlocal fds + fds = gmjc.pass_fds() + + with mock.patch('twisterlib.jobserver.GNUMakeJobClient.__del__', + mock.Mock()), \ + mock.patch('selectors.DefaultSelector', selector_mock): + deleter() + + assert fds == expected_fds + + +TESTDATA_6 = [ + (0, 8), + (32, 16), + (4, 4), +] + +@pytest.mark.parametrize( + 'jobs, expected_jobs', + TESTDATA_6, + ids=['no jobs', 'too many jobs', 'valid jobs'] +) +def test_gnumakejobserver(jobs, expected_jobs): + def mock_init(self, p, j): + self._inheritable_pipe = p + self._internal_pipe = None + self.jobs = j + + pipe = (0, 1) + cpu_count = 8 + pipe_buf = 16 + + selector_mock = mock.Mock() + write_mock = mock.Mock() + del_mock = mock.Mock() + + def deleter(): + GNUMakeJobServer(jobs=jobs) + + with mock.patch.object(GNUMakeJobClient, '__del__', del_mock), \ + mock.patch.object(GNUMakeJobClient, '__init__', mock_init), \ + mock.patch('os.pipe', return_value=pipe), \ + mock.patch('os.write', write_mock), \ + mock.patch('multiprocessing.cpu_count', return_value=cpu_count), \ + mock.patch('select.PIPE_BUF', pipe_buf), \ + mock.patch('selectors.DefaultSelector', selector_mock): + deleter() + + write_mock.assert_called_once_with(pipe[1], b'+' * expected_jobs) diff --git a/scripts/tests/twister/test_log_helper.py b/scripts/tests/twister/test_log_helper.py new file mode 100644 index 00000000000..9373be5da2f --- /dev/null +++ b/scripts/tests/twister/test_log_helper.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +""" +Tests for log_helper.py functions +""" + +import logging +import mock +import pytest + +from importlib import reload + +import twisterlib.log_helper + + +TESTDATA = [ + ('Windows', 'dummy message: [\'dummy\', \'command\', \'-flag\']'), + ('Linux', 'dummy message: dummy command -flag'), +] + +@pytest.mark.parametrize( + 'system, expected_log', + TESTDATA, + ids=['Windows', 'Linux'] +) +def test_log_command(caplog, system, expected_log): + caplog.set_level(logging.DEBUG) + + logger = logging.getLogger('dummy') + message = 'dummy message' + args = ['dummy', 'command', '-flag'] + + with mock.patch('platform.system', return_value=system): + reload(twisterlib.log_helper) + twisterlib.log_helper.log_command(logger, message, args) + + reload(twisterlib.log_helper) + + assert expected_log in caplog.text diff --git a/scripts/tests/twister/test_mixins.py b/scripts/tests/twister/test_mixins.py new file mode 100644 index 00000000000..94e91dcd4ec --- /dev/null +++ b/scripts/tests/twister/test_mixins.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +""" +Tests for the mixins class +""" + +import os +import pytest + + +def test_disable_pytest_test_collection(test_data): + test_path = os.path.join(test_data, 'mixins') + + return_code = pytest.main([test_path]) + + assert return_code == 5 diff --git a/scripts/tests/twister/test_quarantine.py b/scripts/tests/twister/test_quarantine.py index 8988d7978ca..1e4b7d2f405 100644 --- a/scripts/tests/twister/test_quarantine.py +++ b/scripts/tests/twister/test_quarantine.py @@ -104,10 +104,9 @@ def test_quarantinedata_post_init(): quarantine_element = QuarantineElement( platforms=['dummy platform'], - architectures=[] + architectures=[], + simulations=['dummy simulation', 'another simulation'] ) - quarantine_element.scenarios = [] - quarantine_element.simulations = ['dummy simulation', 'another simulation'] quarantine_data_qlist = [quarantine_element, quarantine_element_dict] diff --git a/scripts/tests/twister/test_runner.py b/scripts/tests/twister/test_runner.py index 37c02b6d17b..f0c2cbb50cf 100644 --- a/scripts/tests/twister/test_runner.py +++ b/scripts/tests/twister/test_runner.py @@ -6,19 +6,34 @@ Tests for runner.py classes """ +import errno import mock import os +import pathlib import pytest +import queue +import re +import subprocess import sys import yaml +from contextlib import nullcontext +from elftools.elf.sections import SymbolTableSection from typing import List ZEPHYR_BASE = os.getenv("ZEPHYR_BASE") sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/pylib/twister")) -from twisterlib.runner import ProjectBuilder +from twisterlib.error import BuildError +from twisterlib.harness import Pytest +from twisterlib.runner import ( + CMake, + ExecutionCounter, + FilterBuilder, + ProjectBuilder, + TwisterRunner +) @pytest.fixture def mocked_instance(tmp_path): @@ -78,7 +93,7 @@ def runners(project_builder: ProjectBuilder) -> dict: @mock.patch("os.path.exists") -def test_projectbuilder_cmake_assemble_args(m): +def test_projectbuilder_cmake_assemble_args_single(m): # Causes the additional_overlay_path to be appended m.return_value = True @@ -164,3 +179,2504 @@ def test_if_zephyr_base_is_sanitized_properly(project_builder: ProjectBuilder): with open(cmakecache_file_path, 'r') as file: sanitized_path = file.read() assert sanitized_path == sanitized_path_expected + + +def test_executioncounter(capfd): + ec = ExecutionCounter(total=12) + + ec.cases = 25 + ec.skipped_cases = 6 + ec.error = 2 + ec.iteration = 2 + ec.done = 9 + ec.passed = 6 + ec.skipped_configs = 3 + ec.skipped_runtime = 1 + ec.skipped_filter = 2 + ec.failed = 1 + + ec.summary() + + out, err = capfd.readouterr() + sys.stdout.write(out) + sys.stderr.write(err) + + assert ( + f'--------------------------------\n' + f'Total test suites: 12\n' + f'Total test cases: 25\n' + f'Executed test cases: 19\n' + f'Skipped test cases: 6\n' + f'Completed test suites: 9\n' + f'Passing test suites: 6\n' + f'Failing test suites: 1\n' + f'Skipped test suites: 3\n' + f'Skipped test suites (runtime): 1\n' + f'Skipped test suites (filter): 2\n' + f'Errors: 2\n' + f'--------------------------------' + ) in out + + assert ec.cases == 25 + assert ec.skipped_cases == 6 + assert ec.error == 2 + assert ec.iteration == 2 + assert ec.done == 9 + assert ec.passed == 6 + assert ec.skipped_configs == 3 + assert ec.skipped_runtime == 1 + assert ec.skipped_filter == 2 + assert ec.failed == 1 + + +def test_cmake_parse_generated(mocked_jobserver): + testsuite_mock = mock.Mock() + platform_mock = mock.Mock() + source_dir = os.path.join('source', 'dir') + build_dir = os.path.join('build', 'dir') + + cmake = CMake(testsuite_mock, platform_mock, source_dir, build_dir, + mocked_jobserver) + + result = cmake.parse_generated() + + assert cmake.defconfig == {} + assert result == {} + + +TESTDATA_1_1 = [ + ('linux'), + ('nt') +] +TESTDATA_1_2 = [ + (0, False, 'dummy out', + True, True, True, True, 'passed', None, False, True), + (0, True, '', + False, False, False, False, 'passed', None, False, False), + (1, True, 'ERROR: region `FLASH\' overflowed by 123 MB', + False, True, True, True, 'skipped', 'FLASH overflow', True, False), + (1, True, 'Error: Image size (99 B) + trailer (1 B) exceeds requested size', + False, True, True, True, 'skipped', 'imgtool overflow', True, False), + (1, True, 'mock.ANY', + False, True, True, True, 'error', 'Build failure', False, False) +] + +@pytest.mark.parametrize( + 'return_code, is_instance_run, p_out, expect_msg, expect_returncode,' \ + ' expect_instance, expect_writes, expected_status, expected_reason,' \ + ' expected_change_skip, expected_add_missing', + TESTDATA_1_2, + ids=['no error, no instance run', 'no error, instance run', + 'error - region overflow', 'error - image size exceed', 'error'] +) +@pytest.mark.parametrize('sys_platform', TESTDATA_1_1) +def test_cmake_run_build( + sys_platform, + return_code, + is_instance_run, + p_out, + expect_msg, + expect_returncode, + expect_instance, + expect_writes, + expected_status, + expected_reason, + expected_change_skip, + expected_add_missing +): + process_mock = mock.Mock( + returncode=return_code, + communicate=mock.Mock( + return_value=(p_out.encode(sys.getdefaultencoding()), None) + ) + ) + + def mock_popen(*args, **kwargs): + return process_mock + + testsuite_mock = mock.Mock() + platform_mock = mock.Mock() + platform_mock.name = '' + source_dir = os.path.join('source', 'dir') + build_dir = os.path.join('build', 'dir') + jobserver_mock = mock.Mock( + popen=mock.Mock(side_effect=mock_popen) + ) + instance_mock = mock.Mock(add_missing_case_status=mock.Mock()) + instance_mock.run = is_instance_run + instance_mock.status = None + instance_mock.reason = None + + cmake = CMake(testsuite_mock, platform_mock, source_dir, build_dir, + jobserver_mock) + cmake.cwd = os.path.join('dummy', 'working', 'dir') + cmake.instance = instance_mock + cmake.options = mock.Mock() + cmake.options.overflow_as_errors = False + + cmake_path = os.path.join('dummy', 'cmake') + + popen_mock = mock.Mock(side_effect=mock_popen) + change_mock = mock.Mock() + + with mock.patch('sys.platform', sys_platform), \ + mock.patch('shutil.which', return_value=cmake_path), \ + mock.patch('twisterlib.runner.change_skip_to_error_if_integration', + change_mock), \ + mock.patch('builtins.open', mock.mock_open()), \ + mock.patch('subprocess.Popen', popen_mock): + result = cmake.run_build(args=['arg1', 'arg2']) + + expected_results = {} + if expect_msg: + expected_results['msg'] = 'Finished building %s for %s' % \ + (os.path.join('source', 'dir'), \ + '') + if expect_returncode: + expected_results['returncode'] = return_code + if expect_instance: + expected_results['instance'] = instance_mock + if expected_results == {}: + expected_results = None + + assert expected_results == result + + popen_caller = cmake.jobserver.popen if sys_platform == 'linux' else \ + popen_mock + popen_caller.assert_called_once_with( + [os.path.join('dummy', 'cmake'), 'arg1', 'arg2'], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + cwd=os.path.join('dummy', 'working', 'dir') + ) + + assert cmake.instance.status == expected_status + assert cmake.instance.reason == expected_reason + + if expected_change_skip: + change_mock.assert_called_once() + + if expected_add_missing: + cmake.instance.add_missing_case_status.assert_called_once_with( + 'skipped', 'Test was built only' + ) + + +TESTDATA_2_1 = [ + ('linux'), + ('nt') +] +TESTDATA_2_2 = [ + (True, ['dummy_stage_1', 'ds2'], + 0, False, '', + True, False, True, False, + None, None, + [os.path.join('dummy', 'cmake'), + '-B' + os.path.join('build', 'dir'), '-DTC_RUNID=1', + '-DCONFIG_COMPILER_WARNINGS_AS_ERRORS=y', + '-DEXTRA_GEN_DEFINES_ARGS=--edtlib-Werror', '-Gdummy_generator', + '-S' + os.path.join('source', 'dir'), + 'arg1', 'arg2', + '-DBOARD=', + '-DSNIPPET=dummy snippet 1;ds2', + '-DMODULES=dummy_stage_1,ds2', + '-Pzephyr_base/cmake/package_helper.cmake']), + (False, [], + 1, True, 'ERROR: region `FLASH\' overflowed by 123 MB', + False, True, False, True, + 'error', 'Cmake build failure', + [os.path.join('dummy', 'cmake'), + '-B' + os.path.join('build', 'dir'), '-DTC_RUNID=1', + '-DCONFIG_COMPILER_WARNINGS_AS_ERRORS=n', + '-DEXTRA_GEN_DEFINES_ARGS=', '-Gdummy_generator', + '-Szephyr_base/share/sysbuild', + '-DAPP_DIR=' + os.path.join('source', 'dir'), + 'arg1', 'arg2', + '-DBOARD=', + '-DSNIPPET=dummy snippet 1;ds2']), +] + +@pytest.mark.parametrize( + 'error_warns, f_stages,' \ + ' return_code, is_instance_run, p_out, expect_msg, expect_returncode,' \ + ' expect_filter, expect_writes, expected_status, expected_reason,' \ + ' expected_cmd', + TESTDATA_2_2, + ids=['filter_stages with success', 'no stages with error'] +) +@pytest.mark.parametrize('sys_platform', TESTDATA_2_1) +def test_cmake_run_cmake( + sys_platform, + error_warns, + f_stages, + return_code, + is_instance_run, + p_out, + expect_msg, + expect_returncode, + expect_filter, + expect_writes, + expected_status, + expected_reason, + expected_cmd +): + process_mock = mock.Mock( + returncode=return_code, + communicate=mock.Mock( + return_value=(p_out.encode(sys.getdefaultencoding()), None) + ) + ) + + def mock_popen(*args, **kwargs): + return process_mock + + testsuite_mock = mock.Mock() + testsuite_mock.sysbuild = True + platform_mock = mock.Mock() + platform_mock.name = '' + source_dir = os.path.join('source', 'dir') + build_dir = os.path.join('build', 'dir') + jobserver_mock = mock.Mock( + popen=mock.Mock(side_effect=mock_popen) + ) + instance_mock = mock.Mock(add_missing_case_status=mock.Mock()) + instance_mock.run = is_instance_run + instance_mock.run_id = 1 + instance_mock.status = None + instance_mock.reason = None + instance_mock.testsuite = mock.Mock() + instance_mock.testsuite.required_snippets = ['dummy snippet 1', 'ds2'] + instance_mock.testcases = [mock.Mock(), mock.Mock()] + instance_mock.testcases[0].status = None + instance_mock.testcases[1].status = None + + cmake = CMake(testsuite_mock, platform_mock, source_dir, build_dir, + jobserver_mock) + cmake.cwd = os.path.join('dummy', 'working', 'dir') + cmake.instance = instance_mock + cmake.options = mock.Mock() + cmake.options.disable_warnings_as_errors = not error_warns + cmake.options.overflow_as_errors = False + cmake.env = mock.Mock() + cmake.env.generator = 'dummy_generator' + + cmake_path = os.path.join('dummy', 'cmake') + + popen_mock = mock.Mock(side_effect=mock_popen) + change_mock = mock.Mock() + + with mock.patch('sys.platform', sys_platform), \ + mock.patch('shutil.which', return_value=cmake_path), \ + mock.patch('twisterlib.runner.change_skip_to_error_if_integration', + change_mock), \ + mock.patch('twisterlib.runner.canonical_zephyr_base', + 'zephyr_base'), \ + mock.patch('builtins.open', mock.mock_open()), \ + mock.patch('subprocess.Popen', popen_mock): + result = cmake.run_cmake(args=['arg1', 'arg2'], filter_stages=f_stages) + + expected_results = {} + if expect_msg: + expected_results['msg'] = 'Finished building %s for %s' % \ + (os.path.join('source', 'dir'), \ + '') + if expect_returncode: + expected_results['returncode'] = return_code + if expect_filter: + expected_results['filter'] = {} + if expected_results == {}: + expected_results = None + + assert expected_results == result + + popen_caller = cmake.jobserver.popen if sys_platform == 'linux' else \ + popen_mock + popen_caller.assert_called_once_with( + expected_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + cwd=os.path.join('dummy', 'working', 'dir') + ) + + assert cmake.instance.status == expected_status + assert cmake.instance.reason == expected_reason + + for tc in cmake.instance.testcases: + assert tc.status == cmake.instance.status + + +TESTDATA_3 = [ + ('unit_testing', [], False, True, None, True, None, True, + None, None, {}, {}, None, None, [], {}), + ( + 'other', [], True, + True, ['dummy', 'west', 'options'], True, + None, True, + os.path.join('domain', 'build', 'dir', 'zephyr', '.config'), + os.path.join('domain', 'build', 'dir', 'zephyr', 'edt.pickle'), + {'CONFIG_FOO': 'no'}, + {'dummy cache elem': 1}, + {'ARCH': 'dummy arch', 'PLATFORM': 'other', 'env_dummy': True, + 'CONFIG_FOO': 'no', 'dummy cache elem': 1}, + b'dummy edt pickle contents', + [f'Loaded sysbuild domain data from' \ + f' {os.path.join("build", "dir", "domains.yaml")}'], + {os.path.join('other', 'dummy.testsuite.name'): True} + ), + ( + 'other', ['kconfig'], True, + True, ['dummy', 'west', 'options'], True, + 'Dummy parse results', True, + os.path.join('build', 'dir', 'zephyr', '.config'), + os.path.join('build', 'dir', 'zephyr', 'edt.pickle'), + {'CONFIG_FOO': 'no'}, + {'dummy cache elem': 1}, + {'ARCH': 'dummy arch', 'PLATFORM': 'other', 'env_dummy': True, + 'CONFIG_FOO': 'no', 'dummy cache elem': 1}, + b'dummy edt pickle contents', + [], + {os.path.join('other', 'dummy.testsuite.name'): False} + ), + ( + 'other', ['other'], False, + False, None, True, + 'Dummy parse results', True, + None, + os.path.join('build', 'dir', 'zephyr', 'edt.pickle'), + {}, + {}, + {'ARCH': 'dummy arch', 'PLATFORM': 'other', 'env_dummy': True}, + b'dummy edt pickle contents', + [], + {os.path.join('other', 'dummy.testsuite.name'): False} + ), + ( + 'other', ['other'], True, + False, None, True, + 'Dummy parse results', True, + None, + None, + {}, + {}, + {}, + None, + ['Sysbuild test will be skipped. West must be used for flashing.'], + {os.path.join('other', 'dummy.testsuite.name'): True} + ), + ( + 'other', ['other'], True, + False, ['--erase'], True, + 'Dummy parse results', True, + None, + None, + {}, + {}, + None, + b'dummy edt pickle contents', + ['Sysbuild test will be skipped,' \ + ' --erase is not supported with --west-flash'], + {os.path.join('other', 'dummy.testsuite.name'): True} + ), + ( + 'other', ['other'], False, + True, None, False, + 'Dummy parse results', True, + None, + None, + {}, + {'dummy cache elem': 1}, + {'ARCH': 'dummy arch', 'PLATFORM': 'other', 'env_dummy': True, + 'dummy cache elem': 1}, + None, + [], + {os.path.join('other', 'dummy.testsuite.name'): False} + ), + ( + 'other', ['other'], False, + True, None, True, + 'Dummy parse results', True, + None, + os.path.join('build', 'dir', 'zephyr', 'edt.pickle'), + {}, + {'dummy cache elem': 1}, + {'ARCH': 'dummy arch', 'PLATFORM': 'other', 'env_dummy': True, + 'dummy cache elem': 1}, + b'dummy edt pickle contents', + [], + {os.path.join('other', 'dummy.testsuite.name'): False} + ), + ( + 'other', ['other'], False, + True, None, True, + None, True, + None, + os.path.join('build', 'dir', 'zephyr', 'edt.pickle'), + {}, + {'dummy cache elem': 1}, + {'ARCH': 'dummy arch', 'PLATFORM': 'other', 'env_dummy': True, + 'dummy cache elem': 1}, + b'dummy edt pickle contents', + [], + {os.path.join('other', 'dummy.testsuite.name'): True} + ), + ( + 'other', ['other'], False, + True, None, True, + 'Dummy parse results', False, + None, + os.path.join('build', 'dir', 'zephyr', 'edt.pickle'), + {}, + {'dummy cache elem': 1}, + {'ARCH': 'dummy arch', 'PLATFORM': 'other', 'env_dummy': True, + 'dummy cache elem': 1}, + b'dummy edt pickle contents', + [], + {'ARCH': 'dummy arch', 'PLATFORM': 'other', 'env_dummy': True, + 'dummy cache elem': 1} + ), + ( + 'other', ['other'], False, + True, None, True, + SyntaxError, True, + None, + os.path.join('build', 'dir', 'zephyr', 'edt.pickle'), + {}, + {'dummy cache elem': 1}, + {'ARCH': 'dummy arch', 'PLATFORM': 'other', 'env_dummy': True, + 'dummy cache elem': 1}, + b'dummy edt pickle contents', + ['Failed processing testsuite.yaml'], + SyntaxError + ), +] + +@pytest.mark.parametrize( + 'platform_name, filter_stages, sysbuild,' \ + ' do_find_cache, west_flash_options, edt_exists,' \ + ' parse_results, testsuite_filter,' \ + ' expected_defconfig_path, expected_edt_pickle_path,' \ + ' expected_defconfig, expected_cmakecache, expected_filter_data,' \ + ' expected_edt,' \ + ' expected_logs, expected_return', + TESTDATA_3, + ids=['unit testing', 'domain', 'kconfig', 'no cache', + 'no west options', 'erase west flash option', 'no edt', + 'parse result', 'no parse result', 'no testsuite filter', 'parse err'] +) +def test_filterbuilder_parse_generated( + caplog, + mocked_jobserver, + platform_name, + filter_stages, + sysbuild, + do_find_cache, + west_flash_options, + edt_exists, + parse_results, + testsuite_filter, + expected_defconfig_path, + expected_edt_pickle_path, + expected_defconfig, + expected_cmakecache, + expected_filter_data, + expected_edt, + expected_logs, + expected_return +): + def mock_domains_from_file(*args, **kwargs): + dom = mock.Mock() + dom.build_dir = os.path.join('domain', 'build', 'dir') + res = mock.Mock(get_default_domain=mock.Mock(return_value=dom)) + return res + + def mock_cmakecache_from_file(*args, **kwargs): + if not do_find_cache: + raise FileNotFoundError(errno.ENOENT, 'Cache not found') + cache_elem = mock.Mock() + cache_elem.name = 'dummy cache elem' + cache_elem.value = 1 + cache = [cache_elem] + return cache + + def mock_open(filepath, type, *args, **kwargs): + if filepath == expected_defconfig_path: + rd = 'I am not a proper line\n' \ + 'CONFIG_FOO="no"' + elif filepath == expected_edt_pickle_path: + rd = b'dummy edt pickle contents' + else: + raise FileNotFoundError(errno.ENOENT, + f'File {filepath} not mocked.') + return mock.mock_open(read_data=rd)() + + def mock_parser(filter, filter_data, edt): + assert filter_data == expected_filter_data + if isinstance(parse_results, type) and \ + issubclass(parse_results, Exception): + raise parse_results + return parse_results + + def mock_pickle(datafile): + assert datafile.read() == expected_edt + return mock.Mock() + + testsuite_mock = mock.Mock() + testsuite_mock.sysbuild = 'sysbuild' if sysbuild else None + testsuite_mock.name = 'dummy.testsuite.name' + testsuite_mock.filter = testsuite_filter + platform_mock = mock.Mock() + platform_mock.name = platform_name + platform_mock.arch = 'dummy arch' + source_dir = os.path.join('source', 'dir') + build_dir = os.path.join('build', 'dir') + + fb = FilterBuilder(testsuite_mock, platform_mock, source_dir, build_dir, + mocked_jobserver) + instance_mock = mock.Mock() + fb.instance = instance_mock + fb.env = mock.Mock() + fb.env.options = mock.Mock() + fb.env.options.west_flash = west_flash_options + fb.env.options.device_testing = True + + environ_mock = {'env_dummy': True} + + with mock.patch('twisterlib.runner.Domains.from_file', + mock_domains_from_file), \ + mock.patch('twisterlib.runner.CMakeCache.from_file', + mock_cmakecache_from_file), \ + mock.patch('builtins.open', mock_open), \ + mock.patch('expr_parser.parse', mock_parser), \ + mock.patch('pickle.load', mock_pickle), \ + mock.patch('os.path.exists', return_value=edt_exists), \ + mock.patch('os.environ', environ_mock), \ + pytest.raises(expected_return) if \ + isinstance(parse_results, type) and \ + issubclass(parse_results, Exception) else nullcontext() as err: + result = fb.parse_generated(filter_stages) + + if err: + assert True + return + + assert all([log in caplog.text for log in expected_logs]) + + assert fb.defconfig == expected_defconfig + + assert fb.cmake_cache == expected_cmakecache + + assert result == expected_return + + +TESTDATA_4 = [ + (False, False, [f"see: {os.path.join('dummy', 'path', 'dummy_file.log')}"]), + (True, False, [os.path.join('dummy', 'path', 'dummy_file.log'), + 'file contents', + os.path.join('dummy', 'path', 'dummy_file.log')]), + (True, True, [os.path.join('dummy', 'path', 'dummy_file.log'), + 'Unable to read log data ([Errno 2] ERROR: dummy_file.log)', + os.path.join('dummy', 'path', 'dummy_file.log')]), +] + +@pytest.mark.parametrize( + 'inline_logs, read_exception, expected_logs', + TESTDATA_4, + ids=['basic', 'inline logs', 'inline logs+read_exception'] +) +def test_projectbuilder_log_info( + caplog, + mocked_jobserver, + inline_logs, + read_exception, + expected_logs +): + def mock_open(filename, *args, **kwargs): + if read_exception: + raise OSError(errno.ENOENT, f'ERROR: {os.path.basename(filename)}') + return mock.mock_open(read_data='file contents')() + + def mock_realpath(filename, *args, **kwargs): + return os.path.join('path', filename) + + def mock_abspath(filename, *args, **kwargs): + return os.path.join('dummy', filename) + + filename = 'dummy_file.log' + + env_mock = mock.Mock() + instance_mock = mock.Mock() + + pb = ProjectBuilder(instance_mock, env_mock, mocked_jobserver) + with mock.patch('builtins.open', mock_open), \ + mock.patch('os.path.realpath', mock_realpath), \ + mock.patch('os.path.abspath', mock_abspath): + pb.log_info(filename, inline_logs) + + assert all([log in caplog.text for log in expected_logs]) + + +TESTDATA_5 = [ + (True, False, False, "Valgrind error", 0, 0, 'build_dir/valgrind.log'), + (True, False, False, "Error", 0, 0, 'build_dir/build.log'), + (False, True, False, None, 1024, 0, 'build_dir/handler.log'), + (False, True, False, None, 0, 0, 'build_dir/build.log'), + (False, False, True, None, 0, 1024, 'build_dir/device.log'), + (False, False, True, None, 0, 0, 'build_dir/build.log'), + (False, False, False, None, 0, 0, 'build_dir/build.log'), +] + +@pytest.mark.parametrize( + 'valgrind_log_exists, handler_log_exists, device_log_exists,' \ + ' instance_reason, handler_log_getsize, device_log_getsize, expected_log', + TESTDATA_5, + ids=['valgrind log', 'valgrind log unused', + 'handler log', 'handler log unused', + 'device log', 'device log unused', + 'no logs'] +) +def test_projectbuilder_log_info_file( + caplog, + mocked_jobserver, + valgrind_log_exists, + handler_log_exists, + device_log_exists, + instance_reason, + handler_log_getsize, + device_log_getsize, + expected_log +): + def mock_exists(filename, *args, **kwargs): + if filename == 'build_dir/handler.log': + return handler_log_exists + if filename == 'build_dir/valgrind.log': + return valgrind_log_exists + if filename == 'build_dir/device.log': + return device_log_exists + return False + + def mock_getsize(filename, *args, **kwargs): + if filename == 'build_dir/handler.log': + return handler_log_getsize + if filename == 'build_dir/device.log': + return device_log_getsize + return 0 + + env_mock = mock.Mock() + instance_mock = mock.Mock() + instance_mock.reason = instance_reason + instance_mock.build_dir = 'build_dir' + + pb = ProjectBuilder(instance_mock, env_mock, mocked_jobserver) + + log_info_mock = mock.Mock() + + with mock.patch('os.path.exists', mock_exists), \ + mock.patch('os.path.getsize', mock_getsize), \ + mock.patch('twisterlib.runner.ProjectBuilder.log_info', log_info_mock): + pb.log_info_file(None) + + log_info_mock.assert_called_with(expected_log, mock.ANY) + + +TESTDATA_6 = [ + ( + {'op': 'filter'}, + 'failed', + 'Failed', + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + [], + {'op': 'report', 'test': mock.ANY}, + 'failed', + 'Failed', + 0, + None + ), + ( + {'op': 'filter'}, + 'passed', + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + {'filter': { 'dummy instance name': True }}, + mock.ANY, + mock.ANY, + mock.ANY, + ['filtering dummy instance name'], + {'op': 'report', 'test': mock.ANY}, + 'filtered', + 'runtime filter', + 1, + ('skipped',) + ), + ( + {'op': 'filter'}, + 'passed', + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + {'filter': { 'another dummy instance name': True }}, + mock.ANY, + mock.ANY, + mock.ANY, + [], + {'op': 'cmake', 'test': mock.ANY}, + 'passed', + mock.ANY, + 0, + None + ), + ( + {'op': 'cmake'}, + 'error', + 'dummy error', + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + [], + {'op': 'report', 'test': mock.ANY}, + 'error', + 'dummy error', + 0, + None + ), + ( + {'op': 'cmake'}, + None, + mock.ANY, + mock.ANY, + mock.ANY, + True, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + [], + {'op': 'report', 'test': mock.ANY}, + 'passed', + mock.ANY, + 0, + None + ), + ( + {'op': 'cmake'}, + 'success', + mock.ANY, + mock.ANY, + mock.ANY, + True, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + [], + {'op': 'report', 'test': mock.ANY}, + 'success', + mock.ANY, + 0, + None + ), + ( + {'op': 'cmake'}, + 'success', + mock.ANY, + mock.ANY, + mock.ANY, + False, + mock.ANY, + mock.ANY, + mock.ANY, + {'filter': {'dummy instance name': True}}, + mock.ANY, + mock.ANY, + mock.ANY, + ['filtering dummy instance name'], + {'op': 'report', 'test': mock.ANY}, + 'filtered', + 'runtime filter', + 1, + ('skipped',) + ), + ( + {'op': 'cmake'}, + 'success', + mock.ANY, + mock.ANY, + mock.ANY, + False, + mock.ANY, + mock.ANY, + mock.ANY, + {'filter': {}}, + mock.ANY, + mock.ANY, + mock.ANY, + [], + {'op': 'build', 'test': mock.ANY}, + 'success', + mock.ANY, + 0, + None + ), + ( + {'op': 'build'}, + mock.ANY, + None, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + None, + mock.ANY, + mock.ANY, + ['build test: dummy instance name'], + {'op': 'report', 'test': mock.ANY}, + 'error', + 'Build Failure', + 0, + None + ), + ( + {'op': 'build'}, + 'skipped', + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + {'returncode': 0}, + mock.ANY, + mock.ANY, + ['build test: dummy instance name', + 'Determine test cases for test instance: dummy instance name'], + {'op': 'gather_metrics', 'test': mock.ANY}, + mock.ANY, + mock.ANY, + 1, + ('skipped', mock.ANY) + ), + ( + {'op': 'build'}, + 'passed', + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + {'dummy': 'dummy'}, + mock.ANY, + mock.ANY, + ['build test: dummy instance name'], + {'op': 'report', 'test': mock.ANY}, + 'passed', + mock.ANY, + 0, + ('blocked', mock.ANY) + ), + ( + {'op': 'build'}, + 'success', + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + {'returncode': 0}, + mock.ANY, + mock.ANY, + ['build test: dummy instance name', + 'Determine test cases for test instance: dummy instance name'], + {'op': 'gather_metrics', 'test': mock.ANY}, + mock.ANY, + mock.ANY, + 0, + None + ), + ( + {'op': 'build'}, + 'success', + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + {'returncode': 0}, + mock.ANY, + BuildError, + ['build test: dummy instance name', + 'Determine test cases for test instance: dummy instance name'], + {'op': 'report', 'test': mock.ANY}, + 'error', + 'Determine Testcases Error!', + 0, + None + ), + ( + {'op': 'gather_metrics'}, + mock.ANY, + mock.ANY, + True, + True, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + [], + {'op': 'run', 'test': mock.ANY}, + mock.ANY, + mock.ANY, + 0, + None + ), + ( + {'op': 'gather_metrics'}, + mock.ANY, + mock.ANY, + False, + True, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + [], + {'op': 'report', 'test': mock.ANY}, + mock.ANY, + mock.ANY, + 0, + None + ), + ( + {'op': 'run'}, + 'success', + 'OK', + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + None, + mock.ANY, + ['run test: dummy instance name', + 'run status: dummy instance name success'], + {'op': 'report', 'test': mock.ANY, 'status': 'success', 'reason': 'OK'}, + 'success', + 'OK', + 0, + None + ), + ( + {'op': 'run'}, + 'failed', + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + RuntimeError, + mock.ANY, + ['run test: dummy instance name', + 'run status: dummy instance name failed', + 'RuntimeError: Pipeline Error!'], + None, + 'failed', + mock.ANY, + 0, + None + ), + ( + {'op': 'report'}, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + False, + True, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + [], + {'op': 'cleanup', 'mode': 'device', 'test': mock.ANY}, + mock.ANY, + mock.ANY, + 0, + None + ), + ( + {'op': 'report'}, + 'passed', + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + False, + False, + 'pass', + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + [], + {'op': 'cleanup', 'mode': 'passed', 'test': mock.ANY}, + mock.ANY, + mock.ANY, + 0, + None + ), + ( + {'op': 'report'}, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + False, + False, + 'all', + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + [], + {'op': 'cleanup', 'mode': 'all', 'test': mock.ANY}, + mock.ANY, + mock.ANY, + 0, + None + ), + ( + {'op': 'report'}, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + False, + False, + 'other', + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + [], + None, + mock.ANY, + mock.ANY, + 0, + None + ), + ( + {'op': 'cleanup', 'mode': 'device'}, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + [], + None, + mock.ANY, + mock.ANY, + 0, + None + ), + ( + {'op': 'cleanup', 'mode': 'passed'}, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + [], + None, + mock.ANY, + mock.ANY, + 0, + None + ), + ( + {'op': 'cleanup', 'mode': 'all'}, + mock.ANY, + 'Valgrind error', + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + [], + None, + mock.ANY, + mock.ANY, + 0, + None + ), + ( + {'op': 'cleanup', 'mode': 'all'}, + mock.ANY, + 'Cmake build failure', + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + mock.ANY, + [], + None, + mock.ANY, + mock.ANY, + 0, + None + ), +] + +@pytest.mark.parametrize( + 'message,' \ + ' instance_status, instance_reason, instance_run, instance_handler_ready,' \ + ' options_cmake_only,' \ + ' options_coverage, options_prep_artifacts, options_runtime_artifacts,' \ + ' cmake_res, build_res,' \ + ' pipeline_runtime_error, determine_testcases_build_error,' \ + ' expected_logs, resulting_message,' \ + ' expected_status, expected_reason, expected_skipped, expected_missing', + TESTDATA_6, + ids=[ + 'filter, failed', 'filter, cmake res', 'filter, no cmake res', + 'cmake, failed', 'cmake, cmake_only, no status', 'cmake, cmake_only', + 'cmake, no cmake_only, cmake res', 'cmake, no cmake_only, no cmake res', + 'build, no build res', 'build, skipped', 'build, blocked', + 'build, determine testcases', 'build, determine testcases Error', + 'gather metrics, run and ready handler', 'gather metrics', + 'run', 'run, Pipeline Runtime Error', + 'report, prep artifacts for testing', + 'report, runtime artifact cleanup pass, status passed', + 'report, runtime artifact cleanup all', 'report, no message put', + 'cleanup, device', 'cleanup, mode passed', 'cleanup, mode all', + 'cleanup, mode all, cmake build failure' + ] +) +def test_projectbuilder_process( + caplog, + mocked_jobserver, + message, + instance_status, + instance_reason, + instance_run, + instance_handler_ready, + options_cmake_only, + options_coverage, + options_prep_artifacts, + options_runtime_artifacts, + cmake_res, + build_res, + pipeline_runtime_error, + determine_testcases_build_error, + expected_logs, + resulting_message, + expected_status, + expected_reason, + expected_skipped, + expected_missing +): + def mock_pipeline_put(msg): + if isinstance(pipeline_runtime_error, type) and \ + issubclass(pipeline_runtime_error, Exception): + raise RuntimeError('Pipeline Error!') + + def mock_determine_testcases(res): + if isinstance(determine_testcases_build_error, type) and \ + issubclass(determine_testcases_build_error, Exception): + raise BuildError('Determine Testcases Error!') + + instance_mock = mock.Mock() + instance_mock.name = 'dummy instance name' + instance_mock.status = instance_status + instance_mock.reason = instance_reason + instance_mock.run = instance_run + instance_mock.handler = mock.Mock() + instance_mock.handler.ready = instance_handler_ready + env_mock = mock.Mock() + + pb = ProjectBuilder(instance_mock, env_mock, mocked_jobserver) + pb.options = mock.Mock() + pb.options.coverage = options_coverage + pb.options.prep_artifacts_for_testing = options_prep_artifacts + pb.options.runtime_artifact_cleanup = options_runtime_artifacts + pb.options.cmake_only = options_cmake_only + + pb.cmake = mock.Mock(return_value=cmake_res) + pb.build = mock.Mock(return_value=build_res) + pb.determine_testcases = mock.Mock(side_effect=mock_determine_testcases) + + pb.report_out = mock.Mock() + pb.cleanup_artifacts = mock.Mock() + pb.cleanup_device_testing_artifacts = mock.Mock() + pb.run = mock.Mock() + pb.gather_metrics = mock.Mock() + + pipeline_mock = mock.Mock(put=mock.Mock(side_effect=mock_pipeline_put)) + done_mock = mock.Mock() + lock_mock = mock.Mock( + __enter__=mock.Mock(return_value=(mock.Mock(), mock.Mock())), + __exit__=mock.Mock(return_value=None) + ) + results_mock = mock.Mock() + results_mock.skipped_runtime = 0 + + pb.process(pipeline_mock, done_mock, message, lock_mock, results_mock) + + assert all([log in caplog.text for log in expected_logs]) + + if resulting_message: + pipeline_mock.put.assert_called_with(resulting_message) + + assert pb.instance.status == expected_status + assert pb.instance.reason == expected_reason + assert results_mock.skipped_runtime == expected_skipped + + if expected_missing: + pb.instance.add_missing_case_status.assert_called_with(*expected_missing) + + +TESTDATA_7 = [ + ( + [ + 'z_ztest_unit_test__dummy_suite_name__dummy_test_name', + 'z_ztest_unit_test__dummy_suite_name__test_dummy_name', + 'no match' + ], + ['dummy_id.dummy_name', 'dummy_id.dummy_name'] + ), + ( + ['no match'], + [] + ), +] + +@pytest.mark.parametrize( + 'symbols_names, added_tcs', + TESTDATA_7, + ids=['two hits, one miss', 'nothing'] +) +def test_projectbuilder_determine_testcases( + mocked_jobserver, + symbols_names, + added_tcs +): + symbols_mock = [mock.Mock(n=name) for name in symbols_names] + for m in symbols_mock: + m.configure_mock(name=m.n) + + sections_mock = [mock.Mock(spec=SymbolTableSection)] + sections_mock[0].iter_symbols = mock.Mock(return_value=symbols_mock) + + elf_mock = mock.Mock() + elf_mock().iter_sections = mock.Mock(return_value=sections_mock) + + results_mock = mock.Mock() + + instance_mock = mock.Mock() + instance_mock.testcases = [] + instance_mock.testsuite.id = 'dummy_id' + env_mock = mock.Mock() + + pb = ProjectBuilder(instance_mock, env_mock, mocked_jobserver) + + with mock.patch('twisterlib.runner.ELFFile', elf_mock), \ + mock.patch('builtins.open', mock.mock_open()): + pb.determine_testcases(results_mock) + + pb.instance.add_testcase.assert_has_calls( + [mock.call(name=x) for x in added_tcs] + ) + pb.instance.testsuite.add_testcase.assert_has_calls( + [mock.call(name=x) for x in added_tcs] + ) + + +TESTDATA_8 = [ + ( + ['addition.al'], + 'dummy', + ['addition.al', '.config', 'zephyr'] + ), + ( + [], + 'all', + ['.config', 'zephyr', 'testsuite_extra.conf', 'twister'] + ), +] + +@pytest.mark.parametrize( + 'additional_keep, runtime_artifact_cleanup, expected_files', + TESTDATA_8, + ids=['additional keep', 'all cleanup'] +) +def test_projectbuilder_cleanup_artifacts( + tmpdir, + mocked_jobserver, + additional_keep, + runtime_artifact_cleanup, + expected_files +): + # tmpdir + # ┣ twister + # ┃ ┗ testsuite_extra.conf + # ┣ dummy_dir + # ┃ ┗ dummy.del + # ┣ dummy_link_dir -> zephyr + # ┣ zephyr + # ┃ ┗ .config + # ┗ addition.al + twister_dir = tmpdir.mkdir('twister') + testsuite_extra_conf = twister_dir.join('testsuite_extra.conf') + testsuite_extra_conf.write_text('dummy', 'utf-8') + + dummy_dir = tmpdir.mkdir('dummy_dir') + dummy_del = dummy_dir.join('dummy.del') + dummy_del.write_text('dummy', 'utf-8') + + zephyr = tmpdir.mkdir('zephyr') + config = zephyr.join('.config') + config.write_text('dummy', 'utf-8') + + dummy_link_dir = tmpdir.join('dummy_link_dir') + os.symlink(zephyr, dummy_link_dir) + + addition_al = tmpdir.join('addition.al') + addition_al.write_text('dummy', 'utf-8') + + instance_mock = mock.Mock() + instance_mock.build_dir = tmpdir + env_mock = mock.Mock() + + pb = ProjectBuilder(instance_mock, env_mock, mocked_jobserver) + pb.options = mock.Mock(runtime_artifact_cleanup=runtime_artifact_cleanup) + + pb.cleanup_artifacts(additional_keep) + + files_left = [p.name for p in list(pathlib.Path(tmpdir).glob('**/*'))] + + assert sorted(files_left) == sorted(expected_files) + + +def test_projectbuilder_cleanup_device_testing_artifacts( + caplog, + mocked_jobserver +): + bins = [os.path.join('zephyr', 'file.bin')] + + instance_mock = mock.Mock() + build_dir = os.path.join('build', 'dir') + instance_mock.build_dir = build_dir + env_mock = mock.Mock() + + pb = ProjectBuilder(instance_mock, env_mock, mocked_jobserver) + pb._get_binaries = mock.Mock(return_value=bins) + pb.cleanup_artifacts = mock.Mock() + pb._sanitize_files = mock.Mock() + + pb.cleanup_device_testing_artifacts() + + assert f'Cleaning up for Device Testing {build_dir}' in caplog.text + + pb.cleanup_artifacts.assert_called_once_with( + [os.path.join('zephyr', 'file.bin'), + os.path.join('zephyr', 'runners.yaml')] + ) + pb._sanitize_files.assert_called_once() + + +TESTDATA_9 = [ + ( + None, + [], + [os.path.join('zephyr', 'zephyr.hex'), + os.path.join('zephyr', 'zephyr.bin'), + os.path.join('zephyr', 'zephyr.elf'), + os.path.join('zephyr', 'zephyr.exe')] + ), + ( + [os.path.join('dummy.bin'), os.path.join('dummy.hex')], + [os.path.join('dir2', 'dummy.elf')], + [os.path.join('zephyr', 'dummy.bin'), + os.path.join('zephyr', 'dummy.hex'), + os.path.join('dir2', 'dummy.elf')] + ), +] + +@pytest.mark.parametrize( + 'platform_binaries, runner_binaries, expected_binaries', + TESTDATA_9, + ids=['default', 'valid'] +) +def test_projectbuilder_get_binaries( + mocked_jobserver, + platform_binaries, + runner_binaries, + expected_binaries +): + instance_mock = mock.Mock() + instance_mock.platform = mock.Mock() + instance_mock.platform.binaries = platform_binaries + env_mock = mock.Mock() + + pb = ProjectBuilder(instance_mock, env_mock, mocked_jobserver) + pb._get_binaries_from_runners = mock.Mock(return_value=runner_binaries) + + bins = pb._get_binaries() + + assert all(bin in expected_binaries for bin in bins) + assert all(bin in bins for bin in expected_binaries) + + +TESTDATA_10 = [ + (None, []), + ({'dummy': 'dummy'}, []), + ( + { + 'config': { + 'elf_file': '/absolute/path/dummy.elf', + 'bin_file': 'path/dummy.bin' + } + }, + ['/absolute/path/dummy.elf', os.path.join('zephyr', 'path/dummy.bin')] + ), +] + +@pytest.mark.parametrize( + 'runners_content, expected_binaries', + TESTDATA_10, + ids=['no file', 'no config', 'valid'] +) +def test_projectbuilder_get_binaries_from_runners( + mocked_jobserver, + runners_content, + expected_binaries +): + def mock_exists(fname): + assert fname == os.path.join('build', 'dir', 'zephyr', 'runners.yaml') + return runners_content is not None + + instance_mock = mock.Mock() + instance_mock.build_dir = os.path.join('build', 'dir') + env_mock = mock.Mock() + + pb = ProjectBuilder(instance_mock, env_mock, mocked_jobserver) + + with mock.patch('os.path.exists', mock_exists), \ + mock.patch('builtins.open', mock.mock_open()), \ + mock.patch('yaml.safe_load', return_value=runners_content): + bins = pb._get_binaries_from_runners() + + assert all(bin in expected_binaries for bin in bins) + assert all(bin in bins for bin in expected_binaries) + + +def test_projectbuilder_sanitize_files(mocked_jobserver): + instance_mock = mock.Mock() + env_mock = mock.Mock() + + pb = ProjectBuilder(instance_mock, env_mock, mocked_jobserver) + pb._sanitize_runners_file = mock.Mock() + pb._sanitize_zephyr_base_from_files = mock.Mock() + + pb._sanitize_files() + + pb._sanitize_runners_file.assert_called_once() + pb._sanitize_zephyr_base_from_files.assert_called_once() + + + +TESTDATA_11 = [ + (None, None), + ('dummy: []', None), + ( +""" +config: + elf_file: relative/path/dummy.elf + hex_file: /absolute/path/build_dir/zephyr/dummy.hex +""", +""" +config: + elf_file: relative/path/dummy.elf + hex_file: dummy.hex +""" + ), +] + +@pytest.mark.parametrize( + 'runners_text, expected_write_text', + TESTDATA_11, + ids=['no file', 'no config', 'valid'] +) +def test_projectbuilder_sanitize_runners_file( + mocked_jobserver, + runners_text, + expected_write_text +): + def mock_exists(fname): + return runners_text is not None + + instance_mock = mock.Mock() + instance_mock.build_dir = '/absolute/path/build_dir' + env_mock = mock.Mock() + + pb = ProjectBuilder(instance_mock, env_mock, mocked_jobserver) + + with mock.patch('os.path.exists', mock_exists), \ + mock.patch('builtins.open', + mock.mock_open(read_data=runners_text)) as f: + pb._sanitize_runners_file() + + if expected_write_text is not None: + f().write.assert_called_with(expected_write_text) + else: + f().write.assert_not_called() + + +TESTDATA_12 = [ + ( + { + 'CMakeCache.txt': mock.mock_open( + read_data='canonical/zephyr/base/dummy.file: ERROR' + ) + }, + { + 'CMakeCache.txt': 'dummy.file: ERROR' + } + ), + ( + { + os.path.join('zephyr', 'runners.yaml'): mock.mock_open( + read_data='There was canonical/zephyr/base/dummy.file here' + ) + }, + { + os.path.join('zephyr', 'runners.yaml'): 'There was dummy.file here' + } + ), +] + +@pytest.mark.parametrize( + 'text_mocks, expected_write_texts', + TESTDATA_12, + ids=['CMakeCache file', 'runners.yaml file'] +) +def test_projectbuilder_sanitize_zephyr_base_from_files( + mocked_jobserver, + text_mocks, + expected_write_texts +): + build_dir_path = 'canonical/zephyr/base/build_dir/' + + def mock_exists(fname): + if not fname.startswith(build_dir_path): + return False + return fname[len(build_dir_path):] in text_mocks + + def mock_open(fname, *args, **kwargs): + if not fname.startswith(build_dir_path): + raise FileNotFoundError(errno.ENOENT, f'File {fname} not found.') + return text_mocks[fname[len(build_dir_path):]]() + + instance_mock = mock.Mock() + instance_mock.build_dir = build_dir_path + env_mock = mock.Mock() + + pb = ProjectBuilder(instance_mock, env_mock, mocked_jobserver) + + with mock.patch('os.path.exists', mock_exists), \ + mock.patch('builtins.open', mock_open), \ + mock.patch('twisterlib.runner.canonical_zephyr_base', + 'canonical/zephyr/base'): + pb._sanitize_zephyr_base_from_files() + + for fname, fhandler in text_mocks.items(): + fhandler().write.assert_called_with(expected_write_texts[fname]) + + +TESTDATA_13 = [ + ( + 'error', True, True, False, + ['INFO 20/25 dummy platform' \ + ' dummy.testsuite.name' \ + ' ERROR dummy reason (cmake)'], + None + ), + ( + 'failed', False, False, False, + ['ERROR dummy platform' \ + ' dummy.testsuite.name' \ + ' FAILED : dummy reason'], + 'INFO - Total complete: 20/ 25 80% skipped: 3,' \ + ' failed: 3, error: 1' + ), + ( + 'skipped', True, False, False, + ['INFO 20/25 dummy platform' \ + ' dummy.testsuite.name' \ + ' SKIPPED (dummy reason)'], + None + ), + ( + 'filtered', False, False, False, + [], + 'INFO - Total complete: 20/ 25 80% skipped: 4,' \ + ' failed: 2, error: 1' + ), + ( + 'passed', True, False, True, + ['INFO 20/25 dummy platform' \ + ' dummy.testsuite.name' \ + ' PASSED' \ + ' (dummy handler type: dummy dut, 60.000s)'], + None + ), + ( + 'passed', True, False, False, + ['INFO 20/25 dummy platform' \ + ' dummy.testsuite.name' \ + ' PASSED (build)'], + None + ), + ( + 'unknown status', False, False, False, + ['Unknown status = unknown status'], + 'INFO - Total complete: 20/ 25 80% skipped: 3,' \ + ' failed: 2, error: 1\r' + ), + ( + 'timeout', True, False, True, + ['INFO 20/25 dummy platform' \ + ' dummy.testsuite.name' \ + ' UNKNOWN' \ + ' (dummy handler type: dummy dut, 60.000s/seed: 123)'], + None + ), +] + +@pytest.mark.parametrize( + 'status, verbose, cmake_only, ready_run, expected_logs, expected_out', + TESTDATA_13, + ids=['verbose error cmake only', 'failed', 'verbose skipped', 'filtered', + 'verbose passed ready run', 'verbose passed', 'unknown status', + 'timeout'] +) +def test_projectbuilder_report_out( + capfd, + caplog, + mocked_jobserver, + status, + verbose, + cmake_only, + ready_run, + expected_logs, + expected_out +): + instance_mock = mock.Mock() + instance_mock.handler.type_str = 'dummy handler type' + instance_mock.handler.seed = 123 + instance_mock.handler.ready = ready_run + instance_mock.run = ready_run + instance_mock.dut = 'dummy dut' + instance_mock.execution_time = 60 + instance_mock.platform.name = 'dummy platform' + instance_mock.status = status + instance_mock.reason = 'dummy reason' + instance_mock.testsuite.name = 'dummy.testsuite.name' + instance_mock.testsuite.testcases = [mock.Mock() for _ in range(25)] + instance_mock.testcases = [mock.Mock() for _ in range(24)] + \ + [mock.Mock(status='skipped')] + env_mock = mock.Mock() + + pb = ProjectBuilder(instance_mock, env_mock, mocked_jobserver) + pb.options.verbose = verbose + pb.options.cmake_only = cmake_only + pb.options.seed = 123 + pb.log_info_file = mock.Mock() + + results_mock = mock.Mock() + results_mock.iteration = 1 + results_mock.total = 25 + results_mock.done = 19 + results_mock.passed = 17 + results_mock.skipped_configs = 3 + results_mock.skipped_cases = 4 + results_mock.failed = 2 + results_mock.error = 1 + results_mock.cases = 0 + + pb.report_out(results_mock) + + assert results_mock.cases == 25 + + trim_actual_log = re.sub( + r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])', + '', + caplog.text + ) + trim_actual_log = re.sub(r'twister:runner.py:\d+', '', trim_actual_log) + assert all([log in trim_actual_log for log in expected_logs]) + + if expected_out: + out, err = capfd.readouterr() + sys.stdout.write(out) + sys.stderr.write(err) + + # Remove 7b ANSI C1 escape sequences (colours) + out = re.sub( + r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])', + '', + out + ) + + assert expected_out in out + + +def test_projectbuilder_cmake_assemble_args(): + extra_args = ['CONFIG_FOO=y', 'DUMMY_EXTRA="yes"'] + handler = mock.Mock(ready=True, args=['dummy_handler']) + extra_conf_files = ['extrafile1.conf', 'extrafile2.conf'] + extra_overlay_confs = ['extra_overlay_conf'] + extra_dtc_overlay_files = ['overlay1.dtc', 'overlay2.dtc'] + cmake_extra_args = ['CMAKE1="yes"', 'CMAKE2=n'] + build_dir = os.path.join('build', 'dir') + + with mock.patch('os.path.exists', return_value=True): + results = ProjectBuilder.cmake_assemble_args(extra_args, handler, + extra_conf_files, + extra_overlay_confs, + extra_dtc_overlay_files, + cmake_extra_args, + build_dir) + + expected_results = [ + '-DCONFIG_FOO=y', + '-DCMAKE1=\"yes\"', + '-DCMAKE2=n', + '-DDUMMY_EXTRA=yes', + '-Ddummy_handler', + '-DCONF_FILE=extrafile1.conf;extrafile2.conf', + '-DDTC_OVERLAY_FILE=overlay1.dtc;overlay2.dtc', + f'-DOVERLAY_CONFIG=extra_overlay_conf ' \ + f'{os.path.join("build", "dir", "twister", "testsuite_extra.conf")}' + ] + + assert results == expected_results + + +def test_projectbuilder_cmake(): + instance_mock = mock.Mock() + instance_mock.handler = 'dummy handler' + instance_mock.build_dir = os.path.join('build', 'dir') + env_mock = mock.Mock() + + pb = ProjectBuilder(instance_mock, env_mock, mocked_jobserver) + pb.build_dir = 'build_dir' + pb.testsuite.extra_args = ['some', 'args'] + pb.testsuite.extra_conf_files = ['some', 'files1'] + pb.testsuite.extra_overlay_confs = ['some', 'files2'] + pb.testsuite.extra_dtc_overlay_files = ['some', 'files3'] + pb.options.extra_args = ['other', 'args'] + pb.cmake_assemble_args = mock.Mock(return_value=['dummy']) + cmake_res_mock = mock.Mock() + pb.run_cmake = mock.Mock(return_value=cmake_res_mock) + + res = pb.cmake(['dummy filter']) + + assert res == cmake_res_mock + pb.cmake_assemble_args.assert_called_once_with( + pb.testsuite.extra_args, + pb.instance.handler, + pb.testsuite.extra_conf_files, + pb.testsuite.extra_overlay_confs, + pb.testsuite.extra_dtc_overlay_files, + pb.options.extra_args, + pb.instance.build_dir + ) + pb.run_cmake.assert_called_once_with(['dummy'], ['dummy filter']) + + +def test_projectbuilder_build(mocked_jobserver): + instance_mock = mock.Mock() + env_mock = mock.Mock() + + pb = ProjectBuilder(instance_mock, env_mock, mocked_jobserver) + + pb.build_dir = 'build_dir' + pb.run_build = mock.Mock(return_value={'dummy': 'dummy'}) + + res = pb.build() + + pb.run_build.assert_called_once_with(['--build', 'build_dir']) + assert res == {'dummy': 'dummy'} + + +TESTDATA_14 = [ + ( + True, + 'device', + 234, + 'native_sim', + 'posix', + {'CONFIG_FAKE_ENTROPY_NATIVE_POSIX': 'y'}, + 'pytest', + True, + True, + True, + True, + True, + False + ), + ( + True, + 'not device', + None, + 'native_sim', + 'not posix', + {'CONFIG_FAKE_ENTROPY_NATIVE_POSIX': 'y'}, + 'not pytest', + False, + False, + False, + False, + False, + True + ), + ( + False, + 'device', + 234, + 'native_sim', + 'posix', + {'CONFIG_FAKE_ENTROPY_NATIVE_POSIX': 'y'}, + 'pytest', + False, + False, + False, + False, + False, + False + ), +] + +@pytest.mark.parametrize( + 'ready, type_str, seed, platform_name, platform_arch, defconfig, harness,' \ + ' expect_duts, expect_parse_generated, expect_seed,' \ + ' expect_extra_test_args, expect_pytest, expect_handle', + TESTDATA_14, + ids=['pytest full', 'not pytest minimal', 'not ready'] +) +def test_projectbuilder_run( + mocked_jobserver, + ready, + type_str, + seed, + platform_name, + platform_arch, + defconfig, + harness, + expect_duts, + expect_parse_generated, + expect_seed, + expect_extra_test_args, + expect_pytest, + expect_handle +): + pytest_mock = mock.Mock(spec=Pytest) + harness_mock = mock.Mock() + + def mock_harness(name): + if name == 'Pytest': + return pytest_mock + else: + return harness_mock + + instance_mock = mock.Mock() + instance_mock.handler.get_test_timeout = mock.Mock(return_value=60) + instance_mock.handler.seed = 123 + instance_mock.handler.ready = ready + instance_mock.handler.type_str = type_str + instance_mock.handler.duts = [mock.Mock(name='dummy dut')] + instance_mock.platform.name = platform_name + instance_mock.platform.arch = platform_arch + instance_mock.testsuite.harness = harness + env_mock = mock.Mock() + + pb = ProjectBuilder(instance_mock, env_mock, mocked_jobserver) + pb.options.extra_test_args = ['dummy_arg1', 'dummy_arg2'] + pb.duts = ['another dut'] + pb.options.seed = seed + pb.defconfig = defconfig + pb.parse_generated = mock.Mock() + + with mock.patch('twisterlib.runner.HarnessImporter.get_harness', + mock_harness): + pb.run() + + if expect_duts: + assert pb.instance.handler.duts == ['another dut'] + + if expect_parse_generated: + pb.parse_generated.assert_called_once() + + if expect_seed: + assert pb.instance.handler.seed == seed + + if expect_extra_test_args: + assert pb.instance.handler.extra_test_args == ['dummy_arg1', + 'dummy_arg2'] + + if expect_pytest: + pytest_mock.pytest_run.assert_called_once_with(60) + + if expect_handle: + pb.instance.handler.handle.assert_called_once_with(harness_mock) + + +TESTDATA_15 = [ + (False, False, False, True), + (True, False, True, False), + (False, True, False, True), + (True, True, False, True), +] + +@pytest.mark.parametrize( + 'enable_size_report, cmake_only, expect_calc_size, expect_zeroes', + TESTDATA_15, + ids=['none', 'size_report', 'cmake', 'size_report+cmake'] +) +def test_projectbuilder_gather_metrics( + mocked_jobserver, + enable_size_report, + cmake_only, + expect_calc_size, + expect_zeroes +): + instance_mock = mock.Mock() + instance_mock.metrics = {} + env_mock = mock.Mock() + + pb = ProjectBuilder(instance_mock, env_mock, mocked_jobserver) + pb.options.enable_size_report = enable_size_report + pb.options.create_rom_ram_report = False + pb.options.cmake_only = cmake_only + pb.calc_size = mock.Mock() + + pb.gather_metrics(instance_mock) + + if expect_calc_size: + pb.calc_size.assert_called_once() + + if expect_zeroes: + assert instance_mock.metrics['used_ram'] == 0 + assert instance_mock.metrics['used_rom'] == 0 + assert instance_mock.metrics['available_rom'] == 0 + assert instance_mock.metrics['available_ram'] == 0 + assert instance_mock.metrics['unrecognized'] == [] + + +TESTDATA_16 = [ + ('error', mock.ANY, False, False, False), + ('failed', mock.ANY, False, False, False), + ('skipped', mock.ANY, False, False, False), + ('filtered', 'native', False, False, True), + ('passed', 'qemu', False, False, True), + ('filtered', 'unit', False, False, True), + ('filtered', 'mcu', True, True, False), + ('passed', 'frdm_k64f', False, True, False), +] + +@pytest.mark.parametrize( + 'status, platform_type, expect_warnings, expect_calcs, expect_zeroes', + TESTDATA_16, + ids=[x[0] + (', ' + x[1]) if x[1] != mock.ANY else '' for x in TESTDATA_16] +) +def test_projectbuilder_calc_size( + status, + platform_type, + expect_warnings, + expect_calcs, + expect_zeroes +): + size_calc_mock = mock.Mock() + + instance_mock = mock.Mock() + instance_mock.status = status + instance_mock.platform.type = platform_type + instance_mock.metrics = {} + instance_mock.calculate_sizes = mock.Mock(return_value=size_calc_mock) + + from_buildlog = True + + ProjectBuilder.calc_size(instance_mock, from_buildlog) + + if expect_calcs: + instance_mock.calculate_sizes.assert_called_once_with( + from_buildlog=from_buildlog, + generate_warning=expect_warnings + ) + + assert instance_mock.metrics['used_ram'] == \ + size_calc_mock.get_used_ram() + assert instance_mock.metrics['used_rom'] == \ + size_calc_mock.get_used_rom() + assert instance_mock.metrics['available_rom'] == \ + size_calc_mock.get_available_rom() + assert instance_mock.metrics['available_ram'] == \ + size_calc_mock.get_available_ram() + assert instance_mock.metrics['unrecognized'] == \ + size_calc_mock.unrecognized_sections() + + if expect_zeroes: + assert instance_mock.metrics['used_ram'] == 0 + assert instance_mock.metrics['used_rom'] == 0 + assert instance_mock.metrics['available_rom'] == 0 + assert instance_mock.metrics['available_ram'] == 0 + assert instance_mock.metrics['unrecognized'] == [] + + if expect_calcs or expect_zeroes: + assert instance_mock.metrics['handler_time'] == \ + instance_mock.execution_time + else: + assert instance_mock.metrics == {} + + +TESTDATA_17 = [ + ('linux', 'posix', {'jobs': 4}, True, 32, 'GNUMakeJobClient'), + ('linux', 'posix', {'build_only': True}, False, 16, 'GNUMakeJobServer'), + ('linux', '???', {}, False, 8, 'JobClient'), + ('linux', '???', {'jobs': 4}, False, 4, 'JobClient'), +] + +@pytest.mark.parametrize( + 'platform, os_name, options, jobclient_from_environ, expected_jobs,' \ + ' expected_jobserver', + TESTDATA_17, + ids=['GNUMakeJobClient', 'GNUMakeJobServer', + 'JobClient', 'Jobclient+options'] +) +def test_twisterrunner_run( + caplog, + platform, + os_name, + options, + jobclient_from_environ, + expected_jobs, + expected_jobserver +): + def mock_client_from_environ(jobs): + if jobclient_from_environ: + jobclient_mock = mock.Mock(jobs=32) + jobclient_mock.name = 'GNUMakeJobClient' + return jobclient_mock + return None + + instances = {'dummy instance': mock.Mock(metrics={'k': 'v'})} + suites = [mock.Mock()] + env_mock = mock.Mock() + + tr = TwisterRunner(instances, suites, env=env_mock) + tr.options.retry_failed = 2 + tr.options.retry_interval = 10 + tr.options.retry_build_errors = True + tr.options.jobs = None + tr.options.build_only = None + for k, v in options.items(): + setattr(tr.options, k, v) + tr.update_counting_before_pipeline = mock.Mock() + tr.execute = mock.Mock() + tr.show_brief = mock.Mock() + + gnumakejobserver_mock = mock.Mock() + gnumakejobserver_mock().name='GNUMakeJobServer' + jobclient_mock = mock.Mock() + jobclient_mock().name='JobClient' + + pipeline_q = queue.LifoQueue() + done_q = queue.LifoQueue() + done_instance = mock.Mock( + metrics={'k2': 'v2'}, + execution_time=30 + ) + done_instance.name='dummy instance' + done_q.put(done_instance) + manager_mock = mock.Mock() + manager_mock().LifoQueue = mock.Mock( + side_effect=iter([pipeline_q, done_q]) + ) + + results_mock = mock.Mock() + results_mock().error = 1 + results_mock().iteration = 0 + results_mock().failed = 2 + results_mock().total = 9 + + with mock.patch('twisterlib.runner.ExecutionCounter', results_mock), \ + mock.patch('twisterlib.runner.BaseManager', manager_mock), \ + mock.patch('twisterlib.runner.GNUMakeJobClient.from_environ', + mock_client_from_environ), \ + mock.patch('twisterlib.runner.GNUMakeJobServer', + gnumakejobserver_mock), \ + mock.patch('twisterlib.runner.JobClient', jobclient_mock), \ + mock.patch('multiprocessing.cpu_count', return_value=8), \ + mock.patch('sys.platform', platform), \ + mock.patch('time.sleep', mock.Mock()), \ + mock.patch('os.name', os_name): + tr.run() + + assert f'JOBS: {expected_jobs}' in caplog.text + + assert tr.jobserver.name == expected_jobserver + + assert tr.instances['dummy instance'].metrics == { + 'k': 'v', + 'k2': 'v2', + 'handler_time': 30, + 'unrecognized': [] + } + + assert results_mock().error == 0 + + +def test_twisterrunner_update_counting_before_pipeline(): + instances = { + 'dummy1': mock.Mock( + status='filtered', + reason='runtime filter', + testsuite=mock.Mock( + testcases=[mock.Mock()] + ) + ), + 'dummy2': mock.Mock( + status='filtered', + reason='static filter', + testsuite=mock.Mock( + testcases=[mock.Mock(), mock.Mock(), mock.Mock(), mock.Mock()] + ) + ), + 'dummy3': mock.Mock( + status='error', + reason='error', + testsuite=mock.Mock( + testcases=[mock.Mock()] + ) + ), + 'dummy4': mock.Mock( + status='passed', + reason='OK', + testsuite=mock.Mock( + testcases=[mock.Mock()] + ) + ), + 'dummy5': mock.Mock( + status='skipped', + reason=None, + testsuite=mock.Mock( + testcases=[mock.Mock()] + ) + ) + } + suites = [mock.Mock()] + env_mock = mock.Mock() + + tr = TwisterRunner(instances, suites, env=env_mock) + tr.results = mock.Mock( + skipped_filter = 0, + skipped_configs = 0, + skipped_cases = 0, + cases = 0, + error = 0 + ) + + tr.update_counting_before_pipeline() + + assert tr.results.skipped_filter == 1 + assert tr.results.skipped_configs == 1 + assert tr.results.skipped_cases == 4 + assert tr.results.cases == 4 + assert tr.results.error == 1 + + +def test_twisterrunner_show_brief(caplog): + instances = { + 'dummy1': mock.Mock(), + 'dummy2': mock.Mock(), + 'dummy3': mock.Mock(), + 'dummy4': mock.Mock(), + 'dummy5': mock.Mock() + } + suites = [mock.Mock(), mock.Mock()] + env_mock = mock.Mock() + + tr = TwisterRunner(instances, suites, env=env_mock) + tr.results = mock.Mock( + skipped_filter = 3, + skipped_configs = 4, + skipped_cases = 0, + cases = 0, + error = 0 + ) + + tr.show_brief() + + log = '2 test scenarios (5 test instances) selected,' \ + ' 4 configurations skipped (3 by static filter, 1 at runtime).' + + assert log in caplog.text + + +TESTDATA_18 = [ + (False, False, False, [{'op': 'cmake', 'test': mock.ANY}]), + (False, False, True, [{'op': 'filter', 'test': mock.ANY}, + {'op': 'cmake', 'test': mock.ANY}]), + (False, True, True, [{'op': 'run', 'test': mock.ANY}, + {'op': 'run', 'test': mock.ANY}]), + (False, True, False, [{'op': 'run', 'test': mock.ANY}]), + (True, True, False, [{'op': 'cmake', 'test': mock.ANY}]), + (True, True, True, [{'op': 'filter', 'test': mock.ANY}, + {'op': 'cmake', 'test': mock.ANY}]), + (True, False, True, [{'op': 'filter', 'test': mock.ANY}, + {'op': 'cmake', 'test': mock.ANY}]), + (True, False, False, [{'op': 'cmake', 'test': mock.ANY}]), +] + +@pytest.mark.parametrize( + 'build_only, test_only, retry_build_errors, expected_pipeline_elements', + TESTDATA_18, + ids=['none', 'retry', 'test+retry', 'test', 'build+test', + 'build+test+retry', 'build+retry', 'build'] +) +def test_twisterrunner_add_tasks_to_queue( + build_only, + test_only, + retry_build_errors, + expected_pipeline_elements +): + def mock_get_cmake_filter_stages(filter, keys): + return [filter] + + instances = { + 'dummy1': mock.Mock(run=True, retries=0, status='passed'), + 'dummy2': mock.Mock(run=True, retries=0, status='skipped'), + 'dummy3': mock.Mock(run=True, retries=0, status='filtered'), + 'dummy4': mock.Mock(run=True, retries=0, status='error'), + 'dummy5': mock.Mock(run=True, retries=0, status='failed') + } + instances['dummy4'].testsuite.filter = 'some' + instances['dummy5'].testsuite.filter = 'full' + suites = [mock.Mock(), mock.Mock()] + env_mock = mock.Mock() + + tr = TwisterRunner(instances, suites, env=env_mock) + tr.get_cmake_filter_stages = mock.Mock( + side_effect=mock_get_cmake_filter_stages + ) + + pipeline_mock = mock.Mock() + + tr.add_tasks_to_queue( + pipeline_mock, + build_only, + test_only, + retry_build_errors + ) + + assert all( + [build_only != instance.run for instance in instances.values()] + ) + + tr.get_cmake_filter_stages.assert_any_call('full', mock.ANY) + if retry_build_errors: + tr.get_cmake_filter_stages.assert_any_call('some', mock.ANY) + + print(pipeline_mock.put.call_args_list) + print([mock.call(el) for el in expected_pipeline_elements]) + + assert pipeline_mock.put.call_args_list == \ + [mock.call(el) for el in expected_pipeline_elements] + + +TESTDATA_19 = [ + ('linux'), + ('nt') +] + +@pytest.mark.parametrize( + 'platform', + TESTDATA_19, +) +def test_twisterrunner_pipeline_mgr(mocked_jobserver, platform): + counter = 0 + def mock_get_nowait(): + nonlocal counter + counter += 1 + if counter > 5: + raise queue.Empty() + return {'test': 'dummy'} + + instances = {} + suites = [] + env_mock = mock.Mock() + + tr = TwisterRunner(instances, suites, env=env_mock) + tr.jobserver = mock.Mock( + get_job=mock.Mock( + return_value=nullcontext() + ) + ) + + pipeline_mock = mock.Mock() + pipeline_mock.get_nowait = mock.Mock(side_effect=mock_get_nowait) + done_queue_mock = mock.Mock() + lock_mock = mock.Mock() + results_mock = mock.Mock() + + with mock.patch('sys.platform', platform), \ + mock.patch('twisterlib.runner.ProjectBuilder',\ + return_value=mock.Mock()) as pb: + tr.pipeline_mgr(pipeline_mock, done_queue_mock, lock_mock, results_mock) + + assert len(pb().process.call_args_list) == 5 + + if platform == 'linux': + tr.jobserver.get_job.assert_called_once() + + +def test_twisterrunner_execute(caplog): + counter = 0 + def mock_join(): + nonlocal counter + counter += 1 + if counter > 3: + raise KeyboardInterrupt() + + instances = {} + suites = [] + env_mock = mock.Mock() + + tr = TwisterRunner(instances, suites, env=env_mock) + tr.add_tasks_to_queue = mock.Mock() + tr.jobs = 5 + + process_mock = mock.Mock() + process_mock().join = mock.Mock(side_effect=mock_join) + pipeline_mock = mock.Mock() + done_mock = mock.Mock() + + with mock.patch('twisterlib.runner.Process', process_mock): + tr.execute(pipeline_mock, done_mock) + + assert 'Launch process 0' in caplog.text + assert 'Launch process 1' in caplog.text + assert 'Launch process 2' in caplog.text + assert 'Launch process 3' in caplog.text + assert 'Launch process 4' in caplog.text + assert 'Execution interrupted' in caplog.text + + assert len(process_mock().start.call_args_list) == 5 + assert len(process_mock().join.call_args_list) == 4 + assert len(process_mock().terminate.call_args_list) == 5 + + + +TESTDATA_20 = [ + ('', []), + ('not ARCH in ["x86", "arc"]', ['full']), + ('dt_dummy(x, y)', ['dts']), + ('not CONFIG_FOO', ['kconfig']), + ('dt_dummy and CONFIG_FOO', ['dts', 'kconfig']), +] + +@pytest.mark.parametrize( + 'filter, expected_result', + TESTDATA_20, + ids=['none', 'full', 'dts', 'kconfig', 'dts+kconfig'] +) +def test_twisterrunner_get_cmake_filter_stages(filter, expected_result): + result = TwisterRunner.get_cmake_filter_stages(filter, ['not', 'and']) + + assert sorted(result) == sorted(expected_result) diff --git a/scripts/tests/twister/test_scl.py b/scripts/tests/twister/test_scl.py new file mode 100644 index 00000000000..14a0c447192 --- /dev/null +++ b/scripts/tests/twister/test_scl.py @@ -0,0 +1,256 @@ +#!/usr/bin/env python3 +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +""" +Tests for scl.py functions +""" + +import logging +import mock +import os +import pytest +import sys + +ZEPHYR_BASE = os.getenv("ZEPHYR_BASE") +sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/pylib/twister")) + +import scl + +from contextlib import nullcontext +from importlib import reload +from pykwalify.errors import SchemaError +from yaml.scanner import ScannerError + + +TESTDATA_1 = [ + (False), + (True), +] + +@pytest.mark.parametrize( + 'fail_c', + TESTDATA_1, + ids=['C YAML', 'non-C YAML'] +) +def test_yaml_imports(fail_c): + class ImportRaiser: + def find_spec(self, fullname, path, target=None): + if fullname == 'yaml.CLoader' and fail_c: + raise ImportError() + if fullname == 'yaml.CSafeLoader' and fail_c: + raise ImportError() + if fullname == 'yaml.CDumper' and fail_c: + raise ImportError() + + modules_mock = sys.modules.copy() + + if hasattr(modules_mock['yaml'], 'CLoader'): + del modules_mock['yaml'].CLoader + del modules_mock['yaml'].CSafeLoader + del modules_mock['yaml'].CDumper + + cloader_mock = mock.Mock() + loader_mock = mock.Mock() + csafeloader_mock = mock.Mock() + safeloader_mock = mock.Mock() + cdumper_mock = mock.Mock() + dumper_mock = mock.Mock() + + if not fail_c: + modules_mock['yaml'].CLoader = cloader_mock + modules_mock['yaml'].CSafeLoader = csafeloader_mock + modules_mock['yaml'].CDumper = cdumper_mock + + modules_mock['yaml'].Loader = loader_mock + modules_mock['yaml'].SafeLoader = safeloader_mock + modules_mock['yaml'].Dumper = dumper_mock + + meta_path_mock = sys.meta_path[:] + meta_path_mock.insert(0, ImportRaiser()) + + with mock.patch.dict('sys.modules', modules_mock, clear=True), \ + mock.patch('sys.meta_path', meta_path_mock): + reload(scl) + + assert sys.modules['scl'].Loader == loader_mock if fail_c else \ + cloader_mock + + assert sys.modules['scl'].SafeLoader == safeloader_mock if fail_c else \ + csafeloader_mock + + assert sys.modules['scl'].Dumper == dumper_mock if fail_c else \ + cdumper_mock + + import yaml + reload(yaml) + + +TESTDATA_2 = [ + (False, logging.CRITICAL, []), + (True, None, ['can\'t import pykwalify; won\'t validate YAML']), +] + +@pytest.mark.parametrize( + 'fail_pykwalify, log_level, expected_logs', + TESTDATA_2, + ids=['pykwalify OK', 'no pykwalify'] +) +def test_pykwalify_import(caplog, fail_pykwalify, log_level, expected_logs): + class ImportRaiser: + def find_spec(self, fullname, path, target=None): + if fullname == 'pykwalify.core' and fail_pykwalify: + raise ImportError() + + modules_mock = sys.modules.copy() + modules_mock['pykwalify'] = None if fail_pykwalify else \ + modules_mock['pykwalify'] + + meta_path_mock = sys.meta_path[:] + meta_path_mock.insert(0, ImportRaiser()) + + with mock.patch.dict('sys.modules', modules_mock, clear=True), \ + mock.patch('sys.meta_path', meta_path_mock): + reload(scl) + + if log_level: + assert logging.getLogger('pykwalify.core').level == log_level + + assert all([log in caplog.text for log in expected_logs]) + + if fail_pykwalify: + assert scl._yaml_validate(None, None) is None + assert scl._yaml_validate(mock.Mock(), mock.Mock()) is None + + reload(scl) + + +TESTDATA_3 = [ + (False), + (True), +] + +@pytest.mark.parametrize( + 'fail_parsing', + TESTDATA_3, + ids=['ok', 'parsing error'] +) +def test_yaml_load(caplog, fail_parsing): + result_mock = mock.Mock() + + def mock_load(*args, **kwargs): + if fail_parsing: + context_mark = mock.Mock() + problem_mark = mock.Mock() + type(context_mark).args = mock.PropertyMock(return_value=[]) + type(context_mark).name = 'dummy context mark' + type(context_mark).line = 0 + type(context_mark).column = 0 + type(problem_mark).args = mock.PropertyMock(return_value=[]) + type(problem_mark).name = 'dummy problem mark' + type(problem_mark).line = 0 + type(problem_mark).column = 0 + raise ScannerError(context='dummy context', + context_mark=context_mark, problem='dummy problem', + problem_mark=problem_mark, note='Dummy note') + return result_mock + + filename = 'dummy/file.yaml' + + with mock.patch('yaml.load', side_effect=mock_load), \ + mock.patch('builtins.open', mock.mock_open()) as mock_file: + with pytest.raises(ScannerError) if fail_parsing else nullcontext(): + result = scl.yaml_load(filename) + + mock_file.assert_called_with('dummy/file.yaml', 'r', encoding='utf-8') + + if not fail_parsing: + assert result == result_mock + else: + assert 'dummy problem mark:0:0: error: dummy problem' \ + ' (note Dummy note context @dummy context mark:0:0' \ + ' dummy context)' in caplog.text + + + +TESTDATA_4 = [ + (True, False, None), + (False, False, SchemaError), + (False, True, ScannerError), +] + +@pytest.mark.parametrize( + 'validate, fail_load, expected_error', + TESTDATA_4, + ids=['successful validation', 'failed validation', 'failed load'] +) +def test_yaml_load_verify(validate, fail_load, expected_error): + filename = 'dummy/file.yaml' + schema_mock = mock.Mock() + data_mock = mock.Mock() + + def mock_load(file_name, *args, **kwargs): + assert file_name == filename + if fail_load: + raise ScannerError + return data_mock + + def mock_validate(data, schema, *args, **kwargs): + assert data == data_mock + assert schema == schema_mock + if validate: + return True + raise SchemaError(u'Schema validation failed.') + + with mock.patch('scl.yaml_load', side_effect=mock_load), \ + mock.patch('scl._yaml_validate', side_effect=mock_validate), \ + pytest.raises(expected_error) if expected_error else nullcontext(): + res = scl.yaml_load_verify(filename, schema_mock) + + if validate: + assert res == data_mock + + +TESTDATA_5 = [ + (True, True, None), + (True, False, SchemaError), + (False, None, None), +] + +@pytest.mark.parametrize( + 'schema_exists, validate, expected_error', + TESTDATA_5, + ids=['successful validation', 'failed validation', 'no schema'] +) +def test_yaml_validate(schema_exists, validate, expected_error): + data_mock = mock.Mock() + schema_mock = mock.Mock() if schema_exists else None + + def mock_validate(raise_exception, *args, **kwargs): + assert raise_exception + if validate: + return True + raise SchemaError(u'Schema validation failed.') + + def mock_core(source_data, schema_data, *args, **kwargs): + assert source_data == data_mock + assert schema_data == schema_mock + return mock.Mock(validate=mock_validate) + + core_mock = mock.Mock(side_effect=mock_core) + + with mock.patch('pykwalify.core.Core', core_mock), \ + pytest.raises(expected_error) if expected_error else nullcontext(): + scl._yaml_validate(data_mock, schema_mock) + + if schema_exists: + core_mock.assert_called_once() + else: + core_mock.assert_not_called() + + +def test_yaml_load_empty_file(tmp_path): + quarantine_file = tmp_path / 'empty_quarantine.yml' + quarantine_file.write_text("# yaml file without data") + with pytest.raises(scl.EmptyYamlFileException): + scl.yaml_load_verify(quarantine_file, None) diff --git a/scripts/tests/twister/test_testinstance.py b/scripts/tests/twister/test_testinstance.py index 823eaeb3393..73a3c8f7dfb 100644 --- a/scripts/tests/twister/test_testinstance.py +++ b/scripts/tests/twister/test_testinstance.py @@ -11,6 +11,8 @@ import sys import pytest +from unittest import mock + ZEPHYR_BASE = os.getenv("ZEPHYR_BASE") sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/pylib/twister")) from twisterlib.testinstance import TestInstance @@ -29,7 +31,7 @@ (False, True, "sensor", "native", "", True, [], (True, False)), ] @pytest.mark.parametrize("build_only, slow, harness, platform_type, platform_sim, device_testing,fixture, expected", TESTDATA_1) -def test_check_build_or_run(class_testplan, monkeypatch, all_testsuites_dict, platforms_list, build_only, slow, harness, platform_type, platform_sim, device_testing, fixture, expected): +def test_check_build_or_run(class_testplan, all_testsuites_dict, platforms_list, build_only, slow, harness, platform_type, platform_sim, device_testing, fixture, expected): """" Test to check the conditions for build_only and run scenarios Scenario 1: Test when different parameters are passed, build_only and run are set correctly Scenario 2: Test if build_only is enabled when the OS is Windows""" @@ -51,9 +53,9 @@ def test_check_build_or_run(class_testplan, monkeypatch, all_testsuites_dict, pl _, r = expected assert run == r - monkeypatch.setattr("os.name", "nt") - run = testinstance.check_runnable() - assert not run + with mock.patch('os.name', 'nt'): + run = testinstance.check_runnable() + assert not run TESTDATA_2 = [ (True, True, True, ["demo_board_2"], "native", None, '\nCONFIG_COVERAGE=y\nCONFIG_COVERAGE_DUMP=y\nCONFIG_ASAN=y\nCONFIG_UBSAN=y'), diff --git a/scripts/tests/twister/test_testplan_class.py b/scripts/tests/twister/test_testplan_class.py index 7fdd5f02b4d..f825bc82710 100644 --- a/scripts/tests/twister/test_testplan_class.py +++ b/scripts/tests/twister/test_testplan_class.py @@ -342,3 +342,66 @@ def test_quarantine(class_testplan, platforms_list, test_data, assert instance.reason == "Quarantine: " + expected_val[testname] else: assert not instance.status + +def test_required_snippets_app(class_testplan, all_testsuites_dict, platforms_list): + """ Testing required_snippets function of TestPlan class in Twister + Ensure that app snippets work and are only applied to boards that support the snippet + """ + plan = class_testplan + testsuite = class_testplan.testsuites.get('scripts/tests/twister/test_data/testsuites/tests/test_d/test_d.check_1') + plan.platforms = platforms_list + plan.platform_names = [p.name for p in platforms_list] + plan.testsuites = {'scripts/tests/twister/test_data/testsuites/tests/test_d/test_d.check_1': testsuite} + + for _, testcase in plan.testsuites.items(): + testcase.exclude_platform = [] + testcase.required_snippets = ['dummy'] + testcase.build_on_all = True + + plan.apply_filters() + + filtered_instances = list(filter(lambda item: item.status == "filtered", plan.instances.values())) + for d in filtered_instances: + assert d.reason == "Snippet not supported" + +def test_required_snippets_global(class_testplan, all_testsuites_dict, platforms_list): + """ Testing required_snippets function of TestPlan class in Twister + Ensure that global snippets work and application does not fail + """ + plan = class_testplan + testsuite = class_testplan.testsuites.get('scripts/tests/twister/test_data/testsuites/tests/test_c/test_c.check_1') + plan.platforms = platforms_list + plan.platform_names = [p.name for p in platforms_list] + plan.testsuites = {'scripts/tests/twister/test_data/testsuites/tests/test_c/test_c.check_1': testsuite} + + for _, testcase in plan.testsuites.items(): + testcase.exclude_platform = [] + testcase.required_snippets = ['cdc-acm-console'] + testcase.build_on_all = True + + plan.apply_filters() + + filtered_instances = list(filter(lambda item: item.status == "filtered", plan.instances.values())) + assert len(filtered_instances) == 0 + +def test_required_snippets_multiple(class_testplan, all_testsuites_dict, platforms_list): + """ Testing required_snippets function of TestPlan class in Twister + Ensure that multiple snippets can be used and are applied + """ + plan = class_testplan + testsuite = class_testplan.testsuites.get('scripts/tests/twister/test_data/testsuites/tests/test_d/test_d.check_1') + plan.platforms = platforms_list + plan.platform_names = [p.name for p in platforms_list] + plan.testsuites = {'scripts/tests/twister/test_data/testsuites/tests/test_d/test_d.check_1': testsuite} + + for _, testcase in plan.testsuites.items(): + testcase.exclude_platform = [] + testcase.required_snippets = ['dummy', 'cdc-acm-console'] + testcase.build_on_all = True + + plan.apply_filters() + + filtered_instances = list(filter(lambda item: item.status == "filtered", plan.instances.values())) + assert len(filtered_instances) == 2 + for d in filtered_instances: + assert d.reason == "Snippet not supported" diff --git a/scripts/tests/twister/test_testsuite.py b/scripts/tests/twister/test_testsuite.py index 23e4f8ed034..74402561fc1 100644 --- a/scripts/tests/twister/test_testsuite.py +++ b/scripts/tests/twister/test_testsuite.py @@ -20,6 +20,7 @@ from twisterlib.testsuite import ( _find_src_dir_path, _get_search_area_boundary, + find_c_files_in, scan_file, scan_testsuite_path, ScanPathResult, @@ -426,10 +427,93 @@ def test_get_search_area_boundary( TESTDATA_7 = [ + (True, [os.path.join('', 'home', 'user', 'dummy_path', 'dummy.c'), + os.path.join('', 'home', 'user', 'dummy_path', 'dummy.cpp')]), + (False, []) +] + +@pytest.mark.parametrize( + 'isdir, expected', + TESTDATA_7, + ids=['valid', 'not a directory'] +) +def test_find_c_files_in(isdir, expected): + old_dir = os.path.join('', 'home', 'user', 'dummy_base_dir') + new_path = os.path.join('', 'home', 'user', 'dummy_path') + cur_dir = old_dir + + def mock_chdir(path, *args, **kwargs): + nonlocal cur_dir + cur_dir = path + + # We simulate such a structure: + # + # ┣ dummy.c + # ┣ wrong_dummy.h + # ┗ dummy_dir + # ┣ dummy.cpp + # ┗ wrong_dummy.hpp + # + # ┗ wrong_dummy.c + new_path_base = ['dummy.c', 'wrong_dummy.h'] + new_path_subs = ['dummy.cpp', 'wrong_dummy.hpp'] + old_dir_base = ['wrong_dummy.c'] + + def format_tester(fmt): + formats = [ + {'name': 'subdirs', 'fmt': '**/*.'}, + {'name': 'base', 'fmt': '*.'} + ] + + for format in formats: + if fmt.startswith(format['fmt']): + return format['name'], fmt[len(format['fmt']):] + + raise ValueError('This test wasn\'t designed for those globs.' + ' Please fix the test before PR!') + + def mock_glob(fmt, *args, **kwargs): + from_where, extension = format_tester(fmt) + + if cur_dir == old_dir: + if from_where == 'subdirs': + return [] + elif from_where == 'base': + return list(filter(lambda fn: fn.endswith(extension), + old_dir_base)) + else: + return [] + if cur_dir == new_path: + if from_where == 'subdirs': + return list(filter(lambda fn: fn.endswith(extension), + new_path_subs)) + elif from_where == 'base': + return list(filter(lambda fn: fn.endswith(extension), + new_path_base)) + else: + return [] + + raise ValueError('This test wasn\'t designed for those dirs.' + 'Please fix the test before PR!') + + with mock.patch('os.path.isdir', return_value=isdir), \ + mock.patch('os.getcwd', return_value=cur_dir), \ + mock.patch('glob.glob', mock_glob), \ + mock.patch('os.chdir', side_effect=mock_chdir) as chdir_mock: + filenames = find_c_files_in(new_path) + + assert sorted(filenames) == sorted(expected) + + assert chdir_mock.call_args is None or \ + chdir_mock.call_args == mock.call(old_dir) + + +TESTDATA_8 = [ ( os.path.join('dummy', 'path'), ['testsuite_file_1', 'testsuite_file_2'], - ['src_dir_file_1', 'src_dir_file_2'], + ['src_dir_file_1', 'src_dir_file_2', 'src_dir_file_3'], + {'src_dir_file_1': 1000, 'src_dir_file_2': 2000, 'src_dir_file_3': 0}, { 'testsuite_file_1': ScanPathResult( matches = ['test_a', 'b'], @@ -449,11 +533,12 @@ def test_get_search_area_boundary( ztest_suite_names = ['feature_b'] ), 'src_dir_file_2': ValueError, + 'src_dir_file_3': ValueError, }, [ 'testsuite_file_2: can\'t find: dummy exception', 'testsuite_file_1: dummy warning', - 'src_dir_file_2: can\'t find: dummy exception', + 'src_dir_file_2: error parsing source file: dummy exception', ], None, (['a', 'b', 'test_a', 'test_b'], ['feature_a', 'feature_b']) @@ -462,6 +547,7 @@ def test_get_search_area_boundary( os.path.join('dummy', 'path'), [], ['src_dir_file'], + {'src_dir_file': 1000}, { 'src_dir_file': ScanPathResult( matches = ['test_b', 'a'], @@ -486,6 +572,7 @@ def test_get_search_area_boundary( os.path.join('dummy', 'path'), [], ['src_dir_file'], + {'src_dir_file': 100}, { 'src_dir_file': ScanPathResult( matches = ['test_b', 'a'], @@ -504,13 +591,13 @@ def test_get_search_area_boundary( @pytest.mark.parametrize( - 'testsuite_path, testsuite_glob, src_dir_glob, scanpathresults,' \ + 'testsuite_path, testsuite_glob, src_dir_glob, sizes, scanpathresults,' \ ' expected_logs, expected_exception, expected', - TESTDATA_7, + TESTDATA_8, ids=[ 'valid', 'warning in src dir', - 'register with run error' + 'register with run error', ] ) def test_scan_testsuite_path( @@ -518,18 +605,21 @@ def test_scan_testsuite_path( testsuite_path, testsuite_glob, src_dir_glob, + sizes, scanpathresults, expected_logs, expected_exception, expected ): + src_dir_path = os.path.join(testsuite_path, 'src') + def mock_fsdp(path, *args, **kwargs): - return os.path.join(testsuite_path, 'src') + return src_dir_path - def mock_glob(path, *args, **kwargs): - if path == os.path.join(testsuite_path, 'src', '*.c*'): + def mock_find(path, *args, **kwargs): + if path == src_dir_path: return src_dir_glob - elif path == os.path.join(testsuite_path, '*.c*'): + elif path == testsuite_path: return testsuite_glob else: return [] @@ -540,9 +630,16 @@ def mock_sf(filename, *args, **kwargs): raise scanpathresults[filename]('dummy exception') return scanpathresults[filename] + def mock_stat(filename, *args, **kwargs): + result = mock.Mock() + type(result).st_size = sizes[filename] + + return result + with mock.patch('twisterlib.testsuite._find_src_dir_path', mock_fsdp), \ - mock.patch('glob.glob', mock_glob), \ + mock.patch('twisterlib.testsuite.find_c_files_in', mock_find), \ mock.patch('twisterlib.testsuite.scan_file', mock_sf), \ + mock.patch('os.stat', mock_stat), \ pytest.raises(type(expected_exception)) if \ expected_exception else nullcontext() as exception: result = scan_testsuite_path(testsuite_path) @@ -566,7 +663,7 @@ def mock_sf(filename, *args, **kwargs): ) -TESTDATA_8 = [ +TESTDATA_9 = [ ('dummy/path', 'dummy/path/src', 'dummy/path/src'), ('dummy/path', 'dummy/src', 'dummy/src'), ('dummy/path', 'another/path', '') @@ -575,7 +672,7 @@ def mock_sf(filename, *args, **kwargs): @pytest.mark.parametrize( 'test_dir_path, isdir_path, expected', - TESTDATA_8, + TESTDATA_9, ids=['src here', 'src in parent', 'no path'] ) def test_find_src_dir_path(test_dir_path, isdir_path, expected): @@ -597,7 +694,7 @@ def mock_isdir(path, *args, **kwargs): ) -TESTDATA_9 = [ +TESTDATA_10 = [ ( ZEPHYR_BASE, ZEPHYR_BASE, @@ -641,7 +738,7 @@ def mock_isdir(path, *args, **kwargs): @pytest.mark.parametrize( 'testsuite_root, suite_path, name, data,' \ ' parsed_subcases, suite_names, expected', - TESTDATA_9, + TESTDATA_10, ids=['data', 'subcases', 'empty'] ) def test_testsuite_add_subcases( @@ -673,7 +770,7 @@ def test_testsuite_add_subcases( assert False -TESTDATA_10 = [ +TESTDATA_11 = [ # ( # ZEPHYR_BASE, # ZEPHYR_BASE, @@ -711,7 +808,7 @@ def test_testsuite_add_subcases( @pytest.mark.parametrize( 'testsuite_root, suite_path, name, data, expected', - TESTDATA_10, + TESTDATA_11, ids=[ # 'no harness', 'proper harness', diff --git a/scripts/tests/twister_blackbox/test_data/tests/dummy/agnostic/group1/subgroup1/prj.conf b/scripts/tests/twister_blackbox/test_data/tests/dummy/agnostic/group1/subgroup1/prj.conf index 9228251051e..9467c292689 100644 --- a/scripts/tests/twister_blackbox/test_data/tests/dummy/agnostic/group1/subgroup1/prj.conf +++ b/scripts/tests/twister_blackbox/test_data/tests/dummy/agnostic/group1/subgroup1/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/scripts/tests/twister_blackbox/test_data/tests/dummy/agnostic/group1/subgroup2/prj.conf b/scripts/tests/twister_blackbox/test_data/tests/dummy/agnostic/group1/subgroup2/prj.conf index 9228251051e..9467c292689 100644 --- a/scripts/tests/twister_blackbox/test_data/tests/dummy/agnostic/group1/subgroup2/prj.conf +++ b/scripts/tests/twister_blackbox/test_data/tests/dummy/agnostic/group1/subgroup2/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/scripts/tests/twister_blackbox/test_data/tests/dummy/agnostic/group2/prj.conf b/scripts/tests/twister_blackbox/test_data/tests/dummy/agnostic/group2/prj.conf index 9228251051e..9467c292689 100644 --- a/scripts/tests/twister_blackbox/test_data/tests/dummy/agnostic/group2/prj.conf +++ b/scripts/tests/twister_blackbox/test_data/tests/dummy/agnostic/group2/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/scripts/tests/twister_blackbox/test_data/tests/dummy/device/group/prj.conf b/scripts/tests/twister_blackbox/test_data/tests/dummy/device/group/prj.conf index 9228251051e..9467c292689 100644 --- a/scripts/tests/twister_blackbox/test_data/tests/dummy/device/group/prj.conf +++ b/scripts/tests/twister_blackbox/test_data/tests/dummy/device/group/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/scripts/tests/twister_blackbox/test_hardwaremap.py b/scripts/tests/twister_blackbox/test_hardwaremap.py new file mode 100644 index 00000000000..c5dbd990377 --- /dev/null +++ b/scripts/tests/twister_blackbox/test_hardwaremap.py @@ -0,0 +1,301 @@ +#!/usr/bin/env python3 +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +""" +Blackbox tests for twister's command line functions +""" +import logging +import importlib +import mock +import os +import pytest +import sys + +from conftest import ZEPHYR_BASE, testsuite_filename_mock +from twisterlib.testplan import TestPlan + +sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/pylib/twister/twisterlib")) + +@mock.patch.object(TestPlan, 'TESTSUITE_FILENAME', testsuite_filename_mock) +class TestHardwaremap: + TESTDATA_1 = [ + ( + [ + 'ARM', + 'SEGGER', + 'MBED' + ], + [ + 'DAPLink CMSIS-DAP', + 'MBED CMSIS-DAP' + ], + [1234, 'abcd'], + 'pyocd' + ), + ( + [ + 'STMicroelectronics', + 'Atmel Corp.' + ], + [ + 'J-Link', + 'J-Link OB' + ], + [1234, 'abcd'], + 'jlink' + ), + ( + [ + 'Silicon Labs', + 'NXP Semiconductors', + 'Microchip Technology Inc.' + ], + [ + 'STM32 STLink', + '^XDS110.*', + 'STLINK-V3' + ], + [1234, 'abcd'], + 'openocd' + ), + ( + [ + 'FTDI', + 'Digilent', + 'Microsoft' + ], + [ + 'TTL232R-3V3', + 'MCP2200 USB Serial Port Emulator' + ], + [1234, 'abcd'], + 'dediprog' + ) + ] + TESTDATA_2 = [ + ( + 'FTDI', + 'DAPLink CMSIS-DAP', + 1234, + 'pyocd' + ) + ] + TESTDATA_3 = [ + ( + 'Texas Instruments', + 'DAPLink CMSIS-DAP', + 'abcd', 'las' + ), + ( + 'Texas Instruments', + 'DAPLink CMSIS-DAP', + 'abcd', 'dse0' + ) + ] + + @classmethod + def setup_class(cls): + apath = os.path.join(ZEPHYR_BASE, 'scripts', 'twister') + cls.loader = importlib.machinery.SourceFileLoader('__main__', apath) + cls.spec = importlib.util.spec_from_loader(cls.loader.name, cls.loader) + cls.twister_module = importlib.util.module_from_spec(cls.spec) + + @classmethod + def teardown_class(cls): + pass + + @pytest.mark.usefixtures("clear_log") + @pytest.mark.parametrize( + ('manufacturer', 'product', 'serial', 'runner'), + TESTDATA_1, + ) + def test_generate(self, capfd, manufacturer, product, serial, runner): + file_name = "test-map.yaml" + path = os.path.join(ZEPHYR_BASE, file_name) + args = ['--generate-hardware-map', file_name] + + if os.path.exists(path): + os.remove(path) + + def mocked_comports(): + return [ + mock.Mock(device='/dev/ttyUSB23', + manufacturer=id_man, + product=id_pro, + serial_number=id_serial + ) + ] + + for id_man in manufacturer: + for id_pro in product: + for id_serial in serial: + with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ + mock.patch('serial.tools.list_ports.comports', + side_effect=mocked_comports), \ + pytest.raises(SystemExit) as sys_exit: + self.loader.exec_module(self.twister_module) + + out, err = capfd.readouterr() + sys.stdout.write(out) + sys.stderr.write(err) + + assert os.path.exists(path) + + expected_data = '- connected: true\n' \ + f' id: {id_serial}\n' \ + ' platform: unknown\n' \ + f' product: {id_pro}\n' \ + f' runner: {runner}\n' \ + ' serial: /dev/ttyUSB23\n' + + load_data = open(path).read() + assert load_data == expected_data + + if os.path.exists(path): + os.remove(path) + + assert str(sys_exit.value) == '0' + loggers = [logging.getLogger()] + \ + list(logging.Logger.manager.loggerDict.values()) + \ + [logging.getLogger(name) for \ + name in logging.root.manager.loggerDict] + for logger in loggers: + handlers = getattr(logger, 'handlers', []) + for handler in handlers: + logger.removeHandler(handler) + + @pytest.mark.usefixtures("clear_log") + @pytest.mark.parametrize( + ('manufacturer', 'product', 'serial', 'runner'), + TESTDATA_2, + ) + def test_few_generate(self, capfd, manufacturer, product, serial, runner): + file_name = "test-map.yaml" + path = os.path.join(ZEPHYR_BASE, file_name) + args = ['--generate-hardware-map', file_name] + + if os.path.exists(path): + os.remove(path) + + def mocked_comports(): + return [ + mock.Mock(device='/dev/ttyUSB23', + manufacturer=manufacturer, + product=product, + serial_number=serial + ), + mock.Mock(device='/dev/ttyUSB24', + manufacturer=manufacturer, + product=product, + serial_number=serial + 1 + ), + mock.Mock(device='/dev/ttyUSB24', + manufacturer=manufacturer, + product=product, + serial_number=serial + 2 + ), + mock.Mock(device='/dev/ttyUSB25', + manufacturer=manufacturer, + product=product, + serial_number=serial + 3 + ) + ] + + with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ + mock.patch('serial.tools.list_ports.comports', + side_effect=mocked_comports), \ + pytest.raises(SystemExit) as sys_exit: + self.loader.exec_module(self.twister_module) + + out, err = capfd.readouterr() + sys.stdout.write(out) + sys.stderr.write(err) + + assert os.path.exists(path) + + expected_data = '- connected: true\n' \ + f' id: {serial}\n' \ + ' platform: unknown\n' \ + f' product: {product}\n' \ + f' runner: {runner}\n' \ + ' serial: /dev/ttyUSB23\n' \ + '- connected: true\n' \ + f' id: {serial + 1}\n' \ + ' platform: unknown\n' \ + f' product: {product}\n' \ + f' runner: {runner}\n' \ + ' serial: /dev/ttyUSB24\n' \ + '- connected: true\n' \ + f' id: {serial + 2}\n' \ + ' platform: unknown\n' \ + f' product: {product}\n' \ + f' runner: {runner}\n' \ + ' serial: /dev/ttyUSB24\n' \ + '- connected: true\n' \ + f' id: {serial + 3}\n' \ + ' platform: unknown\n' \ + f' product: {product}\n' \ + f' runner: {runner}\n' \ + ' serial: /dev/ttyUSB25\n' + + load_data = open(path).read() + assert load_data == expected_data + + if os.path.exists(path): + os.remove(path) + + assert str(sys_exit.value) == '0' + + @pytest.mark.usefixtures("clear_log") + @pytest.mark.parametrize( + ('manufacturer', 'product', 'serial', 'location'), + TESTDATA_3, + ) + def test_texas_exeption(self, capfd, manufacturer, product, serial, location): + file_name = "test-map.yaml" + path = os.path.join(ZEPHYR_BASE, file_name) + args = ['--generate-hardware-map', file_name] + + if os.path.exists(path): + os.remove(path) + + def mocked_comports(): + return [ + mock.Mock(device='/dev/ttyUSB23', + manufacturer=manufacturer, + product=product, + serial_number=serial, + location=location + ) + ] + + with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ + mock.patch('serial.tools.list_ports.comports', + side_effect=mocked_comports), \ + pytest.raises(SystemExit) as sys_exit: + self.loader.exec_module(self.twister_module) + + out, err = capfd.readouterr() + sys.stdout.write(out) + sys.stderr.write(err) + + assert os.path.exists(path) + + expected_data = '- connected: true\n' \ + f' id: {serial}\n' \ + ' platform: unknown\n' \ + f' product: {product}\n' \ + ' runner: pyocd\n' \ + ' serial: /dev/ttyUSB23\n' + expected_data2 = '[]\n' + + load_data = open(path).read() + if location.endswith('0'): + assert load_data == expected_data + else: + assert load_data == expected_data2 + if os.path.exists(path): + os.remove(path) + + assert str(sys_exit.value) == '0' diff --git a/scripts/tests/twister_blackbox/test_qemu.py b/scripts/tests/twister_blackbox/test_qemu.py index f8bc54bcc43..a7f7d1c33ef 100644 --- a/scripts/tests/twister_blackbox/test_qemu.py +++ b/scripts/tests/twister_blackbox/test_qemu.py @@ -85,7 +85,7 @@ def teardown_class(cls): ] ) def test_emulation_only(self, capfd, test_path, test_platforms, expected): - args = ['-T', test_path, '--emulation-only'] + \ + args = ['-i', '-T', test_path, '--emulation-only'] + \ [val for pair in zip( ['-p'] * len(test_platforms), test_platforms ) for val in pair] diff --git a/scripts/twister b/scripts/twister index f41349871ed..c66b81d84e1 100755 --- a/scripts/twister +++ b/scripts/twister @@ -142,15 +142,6 @@ pairs: not (right associative) all comparison operators (non-associative) - arch_allow, arch_exclude, platform_allow, platform_exclude - are all syntactic sugar for these expressions. For instance - - arch_exclude = x86 arc - - Is the same as: - - filter = not ARCH in ["x86", "arc"] - The ':' operator compiles the string argument as a regular expression, and then returns a true value only if the symbol's value in the environment matches. For example, if CONFIG_SOC="stm32f107xc" then @@ -159,6 +150,22 @@ pairs: Would match it. + Note that arch_allow, arch_exclude, platform_allow, platform_exclude + are not just syntactic sugar for filter expressions. For instance + + arch_exclude = x86 arc + + Can appear at first glance to have a similar effect to + + filter = not ARCH in ["x86", "arc"] + + but unlike "filter", these cause platforms to be filtered already during the testplan + generation. While "filter" does not exclue platforms at the testplan generation, and instead + relies on the result of running the build configuration stage. That is, to evaluate the filter + expression, cmake is run for that target, and then the filter evaluated as a gate for the + build and run steps. + Therefore filtering by using {platform|arch}_{exclude|allow} is much faster. + The set of test cases that actually run depends on directives in the testsuite files and options passed in on the command line. If there is any confusion, running with -v or examining the test plan report (testplan.json) diff --git a/scripts/utils/convert_guidelines.py b/scripts/utils/convert_guidelines.py new file mode 100755 index 00000000000..a0530b9c7b4 --- /dev/null +++ b/scripts/utils/convert_guidelines.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2023 Baumer (www.baumer.com) +# SPDX-License-Identifier: Apache-2.0 + +"""This script converting the Zephyr coding guideline rst file to a output file, +or print the output to the console. Which than can be used by a tool which +needs to have that information in a specific format (e.g. for cppcheck). +Or simply use the rule list to generate a filter to suppress all other rules +used by default from such a tool. +""" + +import sys +import re +import argparse +from pathlib import Path + +class RuleFormatter: + """ + Base class for the different output formats + """ + def table_start_print(self, outputfile): + pass + def severity_print(self, outputfile, guideline_number, severity): + pass + def description_print(self, outputfile, guideline_number, description): + pass + def closing_print(self, outputfile): + pass + +class CppCheckFormatter(RuleFormatter): + """ + Formatter class to print the rules in a format which can be used by cppcheck + """ + def table_start_print(self, outputfile): + # Start search by cppcheck misra addon + print('Appendix A Summary of guidelines', file=outputfile) + + def severity_print(self, outputfile, guideline_number, severity): + print('Rule ' + guideline_number + ' ' + severity, file=outputfile) + + def description_print(self, outputfile, guideline_number, description): + print(description + '(Misra rule ' + guideline_number + ')', file=outputfile) + + def closing_print(self, outputfile): + # Make cppcheck happy by starting the appendix + print('Appendix B', file=outputfile) + print('', file=outputfile) + +def convert_guidelines(args): + inputfile = args.input + outputfile = sys.stdout + formatter = None + + # If the output is not empty, open the given file for writing + if args.output is not None: + outputfile = open(args.output, "w") + + try: + file_stream = open(inputfile, 'rt', errors='ignore') + except Exception: + print('Error opening ' + inputfile +'.') + sys.exit() + + # Set formatter according to the used format + if args.format == 'cppcheck': + formatter = CppCheckFormatter() + + # Search for table named Main rules + pattern_table_start = re.compile(r'.*list-table:: Main rules') + # Each Rule is a new table column so start with '[tab]* - Rule' + # Ignore directives here + pattern_new_line = re.compile(r'^ \* - Rule ([0-9]+.[0-9]+).*$') + # Each table column start with '[tab]- ' + pattern_new_col = re.compile(r'^ - (.*)$') + + table_start = False + guideline_number = '' + guideline_state = 0 + guideline_list = [] + + for line in file_stream: + + line = line.replace('\r', '').replace('\n', '') + + # Done if we find the Additional rules table start + if line.find('Additional rules') >= 0: + break + + if len(line) == 0: + continue + + if not table_start: + res = pattern_table_start.match(line) + if res: + table_start = True + formatter.table_start_print(outputfile) + continue + + res = pattern_new_line.match(line) + if res: + guideline_state = "severity" + guideline_number = res.group(1) + guideline_list.append(guideline_number) + continue + elif guideline_number == '': + continue + + res = pattern_new_col.match(line) + if res: + if guideline_state == "severity": + # Severity + formatter.severity_print(outputfile, guideline_number, res.group(1)) + guideline_state = "description" + continue + if guideline_state == "description": + # Description + formatter.description_print(outputfile, guideline_number, res.group(1)) + guideline_state = "None" + # We stop here for now, we do not handle the CERT C col + guideline_number = '' + continue + + formatter.closing_print(outputfile) + +if __name__ == "__main__": + supported_formats = ['cppcheck'] + + parser = argparse.ArgumentParser(allow_abbrev=False) + parser.add_argument( + "-i", "--input", metavar="RST_FILE", type=Path, required=True, + help="Path to rst input source file, where the guidelines are written down." + ) + parser.add_argument( + "-f", "--format", metavar="FORMAT", choices=supported_formats, required=True, + help="Format to convert guidlines to. Supported formats are: " + str(supported_formats) + ) + parser.add_argument( + "-o", "--output", metavar="OUTPUT_FILE", type=Path, required=False, + help="Path to output file, where the converted guidelines are written to. If outputfile is not specified, print to stdout." + ) + args = parser.parse_args() + + convert_guidelines(args) diff --git a/scripts/utils/gen_util_macros.py b/scripts/utils/gen_util_macros.py new file mode 100644 index 00000000000..46db3db4e51 --- /dev/null +++ b/scripts/utils/gen_util_macros.py @@ -0,0 +1,163 @@ +""" +Utility script to generate headers for the following macros +- Z_LISTIFY +- Z_UTIL_INC +- Z_UTIL_DEC +- Z_UTIL_X2 +- Z_IS_EQ + +.. note:: + The script will simply create the header files in the current working directory, + they should be copied manually to $ZEPHYR_BASE/include/zephyr/sys/ accordingly. + +Usage:: + + python $ZEPHYR_BASE/scripts/utils/gen_util_macros.py -l 4095 + +Copyright (c) 2023, Meta +SPDX-License-Identifier: Apache-2.0 +""" + +import argparse + +def write_hidden_start(file): + file.write("/**\n") + file.write(" * @cond INTERNAL_HIDDEN\n") + file.write(" */\n") + + +def write_hidden_stop(file): + file.write("/**\n") + file.write(" * INTERNAL_HIDDEN @endcond\n") + file.write(" */\n") + + +def gen_util_listify(limit:int): + with open("util_listify.h", "w") as file: + write_hidden_start(file) + file.write("\n") + file.write("#ifndef ZEPHYR_INCLUDE_SYS_UTIL_LOOPS_H_\n") + file.write("#error \"This header should not be used directly, please include util_loops.h instead\"\n") + file.write("#endif /* ZEPHYR_INCLUDE_SYS_UTIL_LOOPS_H_ */\n") + file.write("\n") + file.write("#ifndef ZEPHYR_INCLUDE_SYS_UTIL_LISTIFY_H_\n") + file.write("#define ZEPHYR_INCLUDE_SYS_UTIL_LISTIFY_H_\n") + file.write("\n") + + file.write("/* Set of UTIL_LISTIFY particles */\n") + file.write("#define Z_UTIL_LISTIFY_0(F, sep, ...)\n\n") + file.write("#define Z_UTIL_LISTIFY_1(F, sep, ...) \\\n") + file.write(" F(0, __VA_ARGS__)\n\n") + + for i in range(2, limit + 3): + file.write(f"#define Z_UTIL_LISTIFY_{i}(F, sep, ...) \\\n") + file.write(f" Z_UTIL_LISTIFY_{i - 1}(F, sep, __VA_ARGS__) __DEBRACKET sep \\\n") + file.write(f" F({i - 1}, __VA_ARGS__)\n") + + file.write("\n") + file.write("#endif /* ZEPHYR_INCLUDE_SYS_UTIL_LISTIFY_H_ */\n") + file.write("\n") + write_hidden_stop(file) + + +def gen_util_internal_is_eq(limit): + with open("util_internal_is_eq.h", "w") as file: + write_hidden_start(file) + file.write("\n") + file.write("#ifndef ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_\n") + file.write("#error \"This header should not be used directly, \ +please include util_internal.h instead\"\n") + file.write("#endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_ */\n") + file.write("\n") + file.write("#ifndef ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_IS_EQ_H_\n") + file.write("#define ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_IS_EQ_H_\n") + file.write("\n") + + for i in range(0, limit + 1): + file.write(f"#define Z_IS_{i}_EQ_{i}(...) \\,\n") + + file.write("\n") + file.write("#endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_IS_EQ_H_ */\n") + file.write("\n") + write_hidden_stop(file) + + +def gen_util_internal_util_inc(limit): + with open("util_internal_util_inc.h", "w") as file: + write_hidden_start(file) + file.write("\n") + file.write("#ifndef ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_\n") + file.write("#error \"This header should not be used directly, \ +please include util_internal.h instead\"\n") + file.write("#endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_ */\n") + file.write("\n") + file.write("#ifndef ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_UTIL_INC_H_\n") + file.write("#define ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_UTIL_INC_H_\n") + file.write("\n") + + for i in range(0, limit + 2): + file.write(f"#define Z_UTIL_INC_{i} {i + 1}\n") + + file.write("\n") + file.write("#endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_UTIL_INC_H_ */\n") + file.write("\n") + write_hidden_stop(file) + + +def gen_util_internal_util_dec(limit): + with open("util_internal_util_dec.h", "w") as file: + write_hidden_start(file) + file.write("\n") + file.write("#ifndef ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_\n") + file.write("#error \"This header should not be used directly, \ +please include util_internal.h instead\"\n") + file.write("#endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_ */\n") + file.write("\n") + file.write("#ifndef ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_UTIL_DEC_H_\n") + file.write("#define ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_UTIL_DEC_H_\n") + file.write("\n") + + file.write(f"#define Z_UTIL_DEC_0 0\n") + for i in range(1, limit + 2): + file.write(f"#define Z_UTIL_DEC_{i} {i - 1}\n") + + file.write("\n") + file.write("#endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_UTIL_DEC_H_ */\n") + file.write("\n") + write_hidden_stop(file) + + +def gen_util_internal_util_x2(limit): + with open("util_internal_util_x2.h", "w") as file: + write_hidden_start(file) + file.write("\n") + file.write("#ifndef ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_\n") + file.write("#error \"This header should not be used directly, \ +please include util_internal.h instead\"\n") + file.write("#endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_ */\n") + file.write("\n") + file.write("#ifndef ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_UTIL_X2_H_\n") + file.write("#define ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_UTIL_X2_H_\n") + file.write("\n") + + for i in range(0, limit + 1): + file.write(f"#define Z_UTIL_X2_{i} {i *2}\n") + + file.write("\n") + file.write("#endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_UTIL_X2_H_ */\n") + file.write("\n") + write_hidden_stop(file) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(allow_abbrev=False) + parser.add_argument( + "-l", "--limit", type=int, required=True, help="Limit of macros" + ) + args = parser.parse_args() + + gen_util_listify(args.limit) + gen_util_internal_is_eq(args.limit) + gen_util_internal_util_inc(args.limit) + gen_util_internal_util_dec(args.limit) + gen_util_internal_util_x2(args.limit) diff --git a/scripts/utils/ntc_thermistor_table.py b/scripts/utils/ntc_thermistor_table.py index 06c282a3c0f..f57d3ca662b 100755 --- a/scripts/utils/ntc_thermistor_table.py +++ b/scripts/utils/ntc_thermistor_table.py @@ -7,8 +7,8 @@ Zephyr's NTC Thermistor DTS Table generator ########################################### -This script can be used to generate a "zephyr,ntc-thermistor-rt-table" compatible -Device Tree node for NTC thermistors. This uses the Beta Parameter Equation +This script can be used to generate an NTC thermistor DTS node with a +"zephyr,compensation-table" property. This uses the Beta Parameter Equation https://devxplained.eu/en/blog/temperature-measurement-with-ntcs#beta-parameter-equation @@ -47,22 +47,17 @@ def main( temps_range = range(temp_init, temp_final + interval - 1, interval) print(f"/* NTC Thermistor Table Generated with {os.path.basename(__file__)} */\n") - print(f"/ {{") print( - f"\tthermistor_R25_{int(r25)}_B_{int(beta)}: thermistor-R25-{int(r25)}-B-{int(beta)} {{" + f"thermistor_R25_{int(r25)}_B_{int(beta)}: thermistor-R25-{int(r25)}-B-{int(beta)} {{" ) - print(f'\t\tstatus = "disabled";') - print(f'\t\tcompatible = "zephyr,ntc-thermistor-rt-table";\n') table = [] for temp in temps_range: resistance = beta_equation_calc_resistance(r25, beta, temp) table.append(f"<({int(temp)}) {int(resistance)}>") - tbl_string = ',\n\t\t\t'.join(table) - print(f"\t\t/* TR Table Format */") - print(f"\t\ttr-table = {tbl_string};") - print(f"\t}};") + tbl_string = ',\n\t\t'.join(table) + print(f"\tzephyr,compensation-table = {tbl_string};") print(f"}};") diff --git a/scripts/west-commands.yml b/scripts/west-commands.yml index 5f63b44225c..803d2b7b2d1 100644 --- a/scripts/west-commands.yml +++ b/scripts/west-commands.yml @@ -56,3 +56,8 @@ west-commands: - name: blobs class: Blobs help: work with binary blobs + - file: scripts/west_commands/bindesc.py + commands: + - name: bindesc + class: Bindesc + help: work with Binary Descriptors diff --git a/scripts/west_commands/bindesc.py b/scripts/west_commands/bindesc.py new file mode 100644 index 00000000000..c56555484e6 --- /dev/null +++ b/scripts/west_commands/bindesc.py @@ -0,0 +1,316 @@ +# Copyright (c) 2023 Yonatan Schachter +# +# SPDX-License-Identifier: Apache-2.0 + +from textwrap import dedent +import struct + +from west.commands import WestCommand +from west import log + + +try: + from elftools.elf.elffile import ELFFile + from intelhex import IntelHex + MISSING_REQUIREMENTS = False +except ImportError: + MISSING_REQUIREMENTS = True + + +# Based on scripts/build/uf2conv.py +def convert_from_uf2(buf): + UF2_MAGIC_START0 = 0x0A324655 # First magic number ('UF2\n') + UF2_MAGIC_START1 = 0x9E5D5157 # Second magic number + numblocks = len(buf) // 512 + curraddr = None + outp = [] + for blockno in range(numblocks): + ptr = blockno * 512 + block = buf[ptr:ptr + 512] + hd = struct.unpack(b' 476: + log.die(f'Invalid UF2 data size at {ptr}') + newaddr = hd[3] + if curraddr is None: + curraddr = newaddr + padding = newaddr - curraddr + if padding < 0: + log.die(f'Block out of order at {ptr}') + if padding > 10*1024*1024: + log.die(f'More than 10M of padding needed at {ptr}') + if padding % 4 != 0: + log.die(f'Non-word padding size at {ptr}') + while padding > 0: + padding -= 4 + outp += b'\x00\x00\x00\x00' + outp.append(block[32 : 32 + datalen]) + curraddr = newaddr + datalen + return b''.join(outp) + + +class Bindesc(WestCommand): + EXTENSIONS = ['bin', 'hex', 'elf', 'uf2'] + + # Corresponds to the definitions in include/zephyr/bindesc.h. + # Do not change without syncing the definitions in both files! + TYPE_UINT = 0 + TYPE_STR = 1 + TYPE_BYTES = 2 + MAGIC = 0xb9863e5a7ea46046 + DESCRIPTORS_END = 0xffff + + def __init__(self): + self.TAG_TO_NAME = { + # Corresponds to the definitions in include/zephyr/bindesc.h. + # Do not change without syncing the definitions in both files! + self.bindesc_gen_tag(self.TYPE_STR, 0x800): 'APP_VERSION_STRING', + self.bindesc_gen_tag(self.TYPE_UINT, 0x801): 'APP_VERSION_MAJOR', + self.bindesc_gen_tag(self.TYPE_UINT, 0x802): 'APP_VERSION_MINOR', + self.bindesc_gen_tag(self.TYPE_UINT, 0x803): 'APP_VERSION_PATCHLEVEL', + self.bindesc_gen_tag(self.TYPE_UINT, 0x804): 'APP_VERSION_NUMBER', + self.bindesc_gen_tag(self.TYPE_STR, 0x900): 'KERNEL_VERSION_STRING', + self.bindesc_gen_tag(self.TYPE_UINT, 0x901): 'KERNEL_VERSION_MAJOR', + self.bindesc_gen_tag(self.TYPE_UINT, 0x902): 'KERNEL_VERSION_MINOR', + self.bindesc_gen_tag(self.TYPE_UINT, 0x903): 'KERNEL_VERSION_PATCHLEVEL', + self.bindesc_gen_tag(self.TYPE_UINT, 0x904): 'KERNEL_VERSION_NUMBER', + self.bindesc_gen_tag(self.TYPE_UINT, 0xa00): 'BUILD_TIME_YEAR', + self.bindesc_gen_tag(self.TYPE_UINT, 0xa01): 'BUILD_TIME_MONTH', + self.bindesc_gen_tag(self.TYPE_UINT, 0xa02): 'BUILD_TIME_DAY', + self.bindesc_gen_tag(self.TYPE_UINT, 0xa03): 'BUILD_TIME_HOUR', + self.bindesc_gen_tag(self.TYPE_UINT, 0xa04): 'BUILD_TIME_MINUTE', + self.bindesc_gen_tag(self.TYPE_UINT, 0xa05): 'BUILD_TIME_SECOND', + self.bindesc_gen_tag(self.TYPE_UINT, 0xa06): 'BUILD_TIME_UNIX', + self.bindesc_gen_tag(self.TYPE_STR, 0xa07): 'BUILD_DATE_TIME_STRING', + self.bindesc_gen_tag(self.TYPE_STR, 0xa08): 'BUILD_DATE_STRING', + self.bindesc_gen_tag(self.TYPE_STR, 0xa09): 'BUILD_TIME_STRING', + self.bindesc_gen_tag(self.TYPE_STR, 0xb00): 'HOST_NAME', + self.bindesc_gen_tag(self.TYPE_STR, 0xb01): 'C_COMPILER_NAME', + self.bindesc_gen_tag(self.TYPE_STR, 0xb02): 'C_COMPILER_VERSION', + self.bindesc_gen_tag(self.TYPE_STR, 0xb03): 'CXX_COMPILER_NAME', + self.bindesc_gen_tag(self.TYPE_STR, 0xb04): 'CXX_COMPILER_VERSION', + } + self.NAME_TO_TAG = {v: k for k, v in self.TAG_TO_NAME.items()} + + super().__init__( + 'bindesc', + 'work with Binary Descriptors', + dedent(''' + Work with Binary Descriptors - constant data objects + describing a binary image + ''')) + + def do_add_parser(self, parser_adder): + parser = parser_adder.add_parser(self.name, + help=self.help, + description=self.description) + + subparsers = parser.add_subparsers(help='sub-command to run', required=True) + + dump_parser = subparsers.add_parser('dump', help='Dump all binary descriptors in the image') + dump_parser.add_argument('file', type=str, help='Executable file') + dump_parser.add_argument('--file-type', type=str, choices=self.EXTENSIONS, help='File type') + dump_parser.add_argument('-b', '--big-endian', action='store_true', + help='Target CPU is big endian') + dump_parser.set_defaults(subcmd='dump', big_endian=False) + + search_parser = subparsers.add_parser('search', help='Search for a specific descriptor') + search_parser.add_argument('descriptor', type=str, help='Descriptor name') + search_parser.add_argument('file', type=str, help='Executable file') + search_parser.add_argument('--file-type', type=str, choices=self.EXTENSIONS, help='File type') + search_parser.add_argument('-b', '--big-endian', action='store_true', + help='Target CPU is big endian') + search_parser.set_defaults(subcmd='search', big_endian=False) + + custom_search_parser = subparsers.add_parser('custom_search', + help='Search for a custom descriptor') + custom_search_parser.add_argument('type', type=str, choices=['UINT', 'STR', 'BYTES'], + help='Descriptor type') + custom_search_parser.add_argument('id', type=str, help='Descriptor ID in hex') + custom_search_parser.add_argument('file', type=str, help='Executable file') + custom_search_parser.add_argument('--file-type', type=str, choices=self.EXTENSIONS, + help='File type') + custom_search_parser.add_argument('-b', '--big-endian', action='store_true', + help='Target CPU is big endian') + custom_search_parser.set_defaults(subcmd='custom_search', big_endian=False) + + list_parser = subparsers.add_parser('list', help='List all known descriptors') + list_parser.set_defaults(subcmd='list', big_endian=False) + + return parser + + def dump(self, args): + image = self.get_image_data(args.file) + + descriptors = self.parse_descriptors(image) + for tag, value in descriptors.items(): + if tag in self.TAG_TO_NAME: + tag = self.TAG_TO_NAME[tag] + log.inf(f'{tag}', self.bindesc_repr(value)) + + def list(self, args): + for tag in self.TAG_TO_NAME.values(): + log.inf(f'{tag}') + + def common_search(self, args, search_term): + image = self.get_image_data(args.file) + + descriptors = self.parse_descriptors(image) + + if search_term in descriptors: + value = descriptors[search_term] + log.inf(self.bindesc_repr(value)) + else: + log.die('Descriptor not found') + + def search(self, args): + try: + search_term = self.NAME_TO_TAG[args.descriptor] + except KeyError: + log.die(f'Descriptor {args.descriptor} is invalid') + + self.common_search(args, search_term) + + def custom_search(self, args): + custom_type = { + 'STR': self.TYPE_STR, + 'UINT': self.TYPE_UINT, + 'BYTES': self.TYPE_BYTES + }[args.type] + custom_tag = self.bindesc_gen_tag(custom_type, int(args.id, 16)) + self.common_search(args, custom_tag) + + def do_run(self, args, _): + if MISSING_REQUIREMENTS: + raise RuntimeError('one or more Python dependencies were missing; ' + 'see the getting started guide for details on ' + 'how to fix') + self.is_big_endian = args.big_endian + self.file_type = self.guess_file_type(args) + subcmd = getattr(self, args.subcmd) + subcmd(args) + + def get_image_data(self, file_name): + if self.file_type == 'bin': + with open(file_name, 'rb') as bin_file: + return bin_file.read() + + if self.file_type == 'hex': + return IntelHex(file_name).tobinstr() + + if self.file_type == 'uf2': + with open(file_name, 'rb') as uf2_file: + return convert_from_uf2(uf2_file.read()) + + if self.file_type == 'elf': + with open(file_name, 'rb') as f: + elffile = ELFFile(f) + + section = elffile.get_section_by_name('rom_start') + if section: + return section.data() + + section = elffile.get_section_by_name('text') + if section: + return section.data() + + log.die('No "rom_start" or "text" section found') + + log.die('Unknown file type') + + def parse_descriptors(self, image): + magic = struct.pack('>Q' if self.is_big_endian else 'Q', self.MAGIC) + index = image.find(magic) + if index == -1: + log.die('Could not find binary descriptor magic') + + descriptors = {} + + index += len(magic) # index points to first descriptor + current_tag = self.bytes_to_short(image[index:index+2]) + while current_tag != self.DESCRIPTORS_END: + index += 2 # index points to length + length = self.bytes_to_short(image[index:index+2]) + index += 2 # index points to data + data = image[index:index+length] + + tag_type = self.bindesc_get_type(current_tag) + if tag_type == self.TYPE_STR: + decoded_data = data[:-1].decode('ascii') + elif tag_type == self.TYPE_UINT: + decoded_data = self.bytes_to_uint(data) + elif tag_type == self.TYPE_BYTES: + decoded_data = data + else: + log.die(f'Unknown type for tag 0x{current_tag:04x}') + + key = f'0x{current_tag:04x}' + descriptors[key] = decoded_data + index += length + index = self.align(index, 4) + current_tag = self.bytes_to_short(image[index:index+2]) + + return descriptors + + def guess_file_type(self, args): + if "file" not in args: + return None + + # If file type is explicitly given, use it + if args.file_type is not None: + return args.file_type + + # If the file has a known extension, use it + for extension in self.EXTENSIONS: + if args.file.endswith(f'.{extension}'): + return extension + + with open(args.file, 'rb') as f: + header = f.read(1024) + + # Try the elf magic + if header.startswith(b'\x7fELF'): + return 'elf' + + # Try the uf2 magic + if header.startswith(b'UF2\n'): + return 'uf2' + + try: + # if the file is textual it's probably hex + header.decode('ascii') + return 'hex' + except UnicodeDecodeError: + # Default to bin + return 'bin' + + def bytes_to_uint(self, b): + return struct.unpack('>I' if self.is_big_endian else 'I', b)[0] + + def bytes_to_short(self, b): + return struct.unpack('>H' if self.is_big_endian else 'H', b)[0] + + @staticmethod + def bindesc_gen_tag(_type, _id): + return f'0x{(_type << 12 | _id):04x}' + + @staticmethod + def bindesc_get_type(tag): + return tag >> 12 + + @staticmethod + def align(x, alignment): + return (x + alignment - 1) & (~(alignment - 1)) + + @staticmethod + def bindesc_repr(value): + if isinstance(value, str): + return f'"{value}"' + if isinstance(value, (int, bytes)): + return f'{value}' diff --git a/scripts/west_commands/completion.py b/scripts/west_commands/completion.py index 708d5500243..470d9a8b5f8 100644 --- a/scripts/west_commands/completion.py +++ b/scripts/west_commands/completion.py @@ -31,6 +31,12 @@ # permanent (might require sudo) west completion zsh > "${fpath[1]}/_west" + fish: + # one-time + west completion fish | source + # permanent + west completion fish > $HOME/.config/fish/completions/west.fish + positional arguments: source_dir application source directory cmake_opt extra options to pass to cmake; implies -c @@ -57,7 +63,7 @@ def do_add_parser(self, parser_adder): # Remember to update west-completion.bash if you add or remove # flags - parser.add_argument('shell', nargs=1, choices=['bash', 'zsh'], + parser.add_argument('shell', nargs=1, choices=['bash', 'zsh', 'fish'], help='''Shell that which the completion script is intended for.''') return parser diff --git a/scripts/west_commands/completion/west-completion.bash b/scripts/west_commands/completion/west-completion.bash index 48375cf486a..ca3f5669d05 100644 --- a/scripts/west_commands/completion/west-completion.bash +++ b/scripts/west_commands/completion/west-completion.bash @@ -644,7 +644,7 @@ __comp_west_completion() *) local counter=$( __west_pos_first_nonflag "$(__west_to_extglob "$global_args_opts")" ) if [ "$cword" -eq "$counter" ]; then - __set_comp "bash zsh" + __set_comp "bash zsh fish" fi ;; esac diff --git a/scripts/west_commands/completion/west-completion.fish b/scripts/west_commands/completion/west-completion.fish new file mode 100644 index 00000000000..92dbc65c800 --- /dev/null +++ b/scripts/west_commands/completion/west-completion.fish @@ -0,0 +1,371 @@ +# check if we are currently in a west workspace +# this is used to filter which command to show +# +# return 0 if in west workspace +# return 1 else +function __zephyr_west_check_if_in_workspace + west topdir &>/dev/null + if test $status = 0 + return 0 + else + return 1 + end +end + +# exclude the caller if one of the arguments is present in the command line +# +# return 1 if one of the arguments is present in the command line +# return 0 else +function __zephyr_west_exclude + set -l tokens (commandline -opc) + + for t in $tokens + for a in $argv + if test $t = $a + return 1 + end + end + end + + return 0 +end + +# function used to have a maximum number of arguments +# +# argv[1] is the maximum number of arguments +# argv[n] are the arguments to count, if not specified will count all arguments after 'west ' on the command line +# +# return 1 if the command line contain more than $argv[1] element from $argv[n...] +# return 0 else +function __zephyr_west_max_args + set -l tokens (commandline -opc) + set -l argc (count $argv) + set -l max $argv[1] + set -l counter 0 + + if test $argc -eq 1 + if test (math (count $tokens) - 2) -ge $max + return 1 + else + return 0 + end + end + + for idx in (seq 2 $argc) + if contains $argv[idx] $tokens + set counter (math $counter + 1) + end + end + + if $counter -ge $max + return 1 + end + + return 0 +end + +# alias of '__fish_complete_directories' but set the arguments to '' +function __zephyr_west_complete_directories + __fish_complete_directories '' '' +end + +# check if a given token is the last one in the command line +# +# return 0 if one of the given argument is the last token +# return 1 else +function __zephyr_west_is_last_token + set -l tokens (commandline -opc) + + for token in $argv + if string match -qr -- "$token*" "$tokens[-1]" + return 0 + end + end + + return 1 +end + +# function similar to '__fish_use_subcommand' but with special cases +function __zephyr_west_use_subcommand + set -l tokens (commandline -opc) + + for idx in (seq 2 (count $tokens)) + switch $tokens[$idx] + case '-*' + continue + case '*' + if test $idx -ge 3 + set -l prv_idx (math $idx - 1) + switch $tokens[$prv_idx] + # this option can be placed before subcommand and require a folder + # if we don't do that the folder will be catched as a subcommand and + # the subcommands will not be completed + case '-z' '--zephyr-base' + continue + end + end + end + return 1 + end + + return 0 +end + +# function similar to '__fish_seen_subcommand_from' but with special cases +function __zephyr_west_seen_subcommand_from + set -l tokens (commandline -opc) + set -e tokens[1] + + # special case: + # we don't want the command completion when doing `west help ` + if contains -- "help" $tokens + return 1 + end + + for token in $tokens + if contains -- $token $argv + return 0 + end + end + + return 1 +end + +# return the list of projects +function __zephyr_west_complete_projects + set -l tokens (commandline -opc) + set -l zephyr_base "" + set -l projects + + for idx in (seq 1 (count $tokens)) + if test \("$tokens[$idx]" = "-z"\) -o \("$tokens[$idx]" = "--zephyr-base"\) + if set -q $tokens[(math $idx + 1)] + set $zephyr_base $tokens (math $idx + 1) + break + end + end + end + + if test $zephyr_base != "" + set projects (west "-z $zephyr_base" list --format="{name}") + else + set projects (west list --format="{name}") + end + + printf "%s\n" $projects +end + +# return the list of available west commands +function __zephyr_west_complete_help + set -l builtin_cmds "init" "create a west repository" \ + "update" "update projects described in west manifest" \ + "list" "print information about projects" \ + "manifest" "manage the west manifest" \ + "diff" '"git diff" for one or more projects' \ + "status" '"git status" for one or more projects' \ + "forall" "run a command in one or more local projects" \ + "config" "get or set config file values" \ + "topdir" "print the top level directory of the workspace" \ + "help" "get help for west or a command" + set -l nb_builtin_cmds (count $builtin_cmds) + + set -l ext_cmds "completion" "display shell completion scripts" \ + "boards" "display information about supported boards" \ + "build" "compile a Zephyr application" \ + "sign" "sign a Zephyr binary for bootloader chain-loading" \ + "flash" "flash and run a binary on a board" \ + "debug" "flash and interactively debug a Zephyr application" \ + "debugserver" "connect to board and launch a debug server" \ + "attach" "interactively debug a board" \ + "zephyr-export" "export Zephyr installation as a CMake config package" \ + "spdx" "create SPDX bill of materials" \ + "blobs" "work with binary blobs" + set -l nb_ext_cmds (count $ext_cmds) + + if __zephyr_west_check_if_in_workspace + for idx in (seq 1 2 $nb_ext_cmds) + set -l desc_idx (math $idx + 1) + printf "%s\n" $ext_cmds[$idx]\t"$ext_cmds[$desc_idx]" + end + end + + for idx in (seq 1 2 $nb_builtin_cmds) + set -l desc_idx (math $idx + 1) + printf "%s\n" $builtin_cmds[$idx]\t"$builtin_cmds[$desc_idx]" + end +end + +function __zephyr_west_complete_board + set -l boards (west 2>/dev/null boards --format="{name} {arch}") + for board in $boards + set -l b (string split " " $board) + printf "%s\n" $b[1]\t"$b[2]" + end +end + +# disable file completion, if an option need it, it should use '--force-files' +complete -c west -f + +# global options +complete -c west -n "__zephyr_west_exclude -h --help" -o h -l help -d "show help" +complete -c west -o v -l verbose -d "enable verbosity" +complete -c west -n "__zephyr_west_exclude -V --version" -o V -l version -d "print version" +complete -c west -n "__zephyr_west_exclude -z --zephyr-base; or __zephyr_west_is_last_token -z --zephyr-base" -o z -l zephyr-base -xa "(__zephyr_west_complete_directories)" -d "zephyr base folder" + +# init +complete -c west -n __zephyr_west_use_subcommand -ra init -d "create a west workspace" +complete -c west -n "__zephyr_west_seen_subcommand_from init" -ra "(__zephyr_west_complete_directories)" +complete -c west -n "__zephyr_west_seen_subcommand_from init; and __zephyr_west_exclude -l --local" -l mr -l manifest-rev -r -d "manifest revision" +complete -c west -n "__zephyr_west_seen_subcommand_from init" -l mf -l manifest-file -r -d "manifest file" +complete -c west -n "__zephyr_west_seen_subcommand_from init; and __zephyr_west_exclude -l --local" -o m -l manifest -ra "(__zephyr_west_complete_directories)" -d "manifest URL" +complete -c west -n "__zephyr_west_seen_subcommand_from init; and __zephyr_west_exclude -m --manifest --mr --manifest-rev" -o l -l local -ra "(__zephyr_west_complete_directories)" -d "use local directory as manifest repository" + +# update +complete -c west -n __zephyr_west_use_subcommand -ra update -d "update projects described in west manifest" +complete -c west -n "__zephyr_west_seen_subcommand_from update" -ra "(__zephyr_west_complete_projects)" +complete -c west -n "__zephyr_west_seen_subcommand_from update" -l stats -d "print performance stats" +complete -c west -n "__zephyr_west_seen_subcommand_from update" -l name-cache -ra "(__zephyr_west_complete_directories)" -d "name-based cache" +complete -c west -n "__zephyr_west_seen_subcommand_from update" -l path-cache -ra "(__zephyr_west_complete_directories)" -d "path-based cache" +complete -c west -n "__zephyr_west_seen_subcommand_from update" -o f -l fetch -ra "always smart" -d "fetch strategy" +complete -c west -n "__zephyr_west_seen_subcommand_from update" -o o -l fetch-opt -d "fetch options" +complete -c west -n "__zephyr_west_seen_subcommand_from update" -o n -l narrow -d "narrow fetch" +complete -c west -n "__zephyr_west_seen_subcommand_from update" -o k -l keep-descendants -d "keep manifest-rev descendants checked out" +complete -c west -n "__zephyr_west_seen_subcommand_from update" -o r -l rebase -d "rebase checked out branch onto the new manifest-rev" + +# list +complete -c west -n __zephyr_west_use_subcommand -ra list -d "print information about projects" +complete -c west -n "__zephyr_west_seen_subcommand_from list; and not __fish_seen_subcommand_from blobs" -ra "(__zephyr_west_complete_projects)" +complete -c west -n "__zephyr_west_seen_subcommand_from list; and not __fish_seen_subcommand_from blobs" -o a -l all -d "include inactive projects" +complete -c west -n "__zephyr_west_seen_subcommand_from list; and not __fish_seen_subcommand_from blobs" -l manifest-path-from-yaml -d "print performance stats" +complete -c west -n "__zephyr_west_seen_subcommand_from list; and not __fish_seen_subcommand_from blobs" -o f -l format -d "format string" + +# manifest +complete -c west -n __zephyr_west_use_subcommand -ra manifest -d "manage the west manifest" +complete -c west -n "__zephyr_west_seen_subcommand_from manifest" -l resolve -d "resolve into single manifest" +complete -c west -n "__zephyr_west_seen_subcommand_from manifest" -l freeze -d "resolve into single manifest, with SHAs" +complete -c west -n "__zephyr_west_seen_subcommand_from manifest" -l validate -d "silently validate manifest" +complete -c west -n "__zephyr_west_seen_subcommand_from manifest" -l path -d "print the path to the top level manifest file" +complete -c west -n "__zephyr_west_seen_subcommand_from manifest" -o o -l output -rF -d "output file" + +# diff +complete -c west -n __zephyr_west_use_subcommand -ra diff -d '"git diff" for one or more projects' +complete -c west -n "__zephyr_west_seen_subcommand_from diff" -ra "(__zephyr_west_complete_projects)" +complete -c west -n "__zephyr_west_seen_subcommand_from diff" -o a -l all -d "include inactive projects" + +# status +complete -c west -n __zephyr_west_use_subcommand -ra status -d '"git status" for one or more projects' +complete -c west -n "__zephyr_west_seen_subcommand_from status" -ra "(__zephyr_west_complete_projects)" +complete -c west -n "__zephyr_west_seen_subcommand_from status" -o a -l all -d "include inactive projects" + +# forall +complete -c west -n __zephyr_west_use_subcommand -ra forall -d "run a command in one or more local projects" +complete -c west -n "__zephyr_west_seen_subcommand_from forall" -ra "(__zephyr_west_complete_projects)" +complete -c west -n "__zephyr_west_seen_subcommand_from forall" -o c -x -d "command to execute" +complete -c west -n "__zephyr_west_seen_subcommand_from forall" -o a -l all -d "include inactive projects" +complete -c west -n "__zephyr_west_seen_subcommand_from forall" -o g -l group -x -d "run command on projects in one of the group" + +# config +complete -c west -n __zephyr_west_use_subcommand -ra config -d "get or set config file values" +complete -c west -n "__zephyr_west_seen_subcommand_from config" -o l -l list -d "list all options and values" +complete -c west -n "__zephyr_west_seen_subcommand_from config" -o d -l delete -d "delete an option in one config file" +complete -c west -n "__zephyr_west_seen_subcommand_from config" -o D -l delete-all -d "delete an option everywhere it's set" +complete -c west -n "__zephyr_west_seen_subcommand_from config" -l system -d "system-wide file" +complete -c west -n "__zephyr_west_seen_subcommand_from config" -l global -d "global user-wide" +complete -c west -n "__zephyr_west_seen_subcommand_from config" -l local -d "this workspace's file" + +# topdir +complete -c west -n __zephyr_west_use_subcommand -a topdir -d "print the top level directory of the workspace" + +# help +complete -c west -n __zephyr_west_use_subcommand -ra help -d "get help for west or a command" +complete -c west -n "__fish_seen_subcommand_from help; and __zephyr_west_max_args 1" -ra "(__zephyr_west_complete_help)" + + + +# completion +complete -c west -n "__zephyr_west_use_subcommand; and __zephyr_west_check_if_in_workspace" -ra completion -d "display shell completion scripts" +complete -c west -n "__zephyr_west_seen_subcommand_from completion; and __zephyr_west_max_args 1" -ra "bash zsh fish" + +# boards +complete -c west -n "__zephyr_west_use_subcommand; and __zephyr_west_check_if_in_workspace" -ra boards -d "display information about supported boards" +complete -c west -n "__zephyr_west_seen_subcommand_from boards" -o f -l format -d "format string" +complete -c west -n "__zephyr_west_seen_subcommand_from boards" -o n -l name -d "name regex" +complete -c west -n "__zephyr_west_seen_subcommand_from boards" -l arch-root -xa "(__zephyr_west_complete_directories)" -d "add an arch root" +complete -c west -n "__zephyr_west_seen_subcommand_from boards" -l board-root -xa "(__zephyr_west_complete_directories)" -d "add a board root" + +# build +complete -c west -n "__zephyr_west_use_subcommand; and __zephyr_west_check_if_in_workspace" -ra build -d "compile a Zephyr application" +complete -c west -n "__zephyr_west_seen_subcommand_from build" -ra "(__zephyr_west_complete_directories)" +complete -c west -n "__zephyr_west_seen_subcommand_from build" -o b -l board -xa "(__zephyr_west_complete_board)" -d "board to build for" +complete -c west -n "__zephyr_west_seen_subcommand_from build" -o d -l build-dir -xa "(__zephyr_west_complete_directories)" -d "build directory to create or use" +complete -c west -n "__zephyr_west_seen_subcommand_from build" -o f -l force -d "ignore errors and continue" +complete -c west -n "__zephyr_west_seen_subcommand_from build" -l sysbuild -d "create multi-domain build system" +complete -c west -n "__zephyr_west_seen_subcommand_from build" -l no-sysbuild -d "do not create multi-domain build system" +complete -c west -n "__zephyr_west_seen_subcommand_from build" -o c -l cmake -d "force a cmake run" +complete -c west -n "__zephyr_west_seen_subcommand_from build" -l domain -d "execute build tool (make or ninja) for a given domain" +complete -c west -n "__zephyr_west_seen_subcommand_from build" -o t -l target -d "run build system target" +complete -c west -n "__zephyr_west_seen_subcommand_from build" -o T -l test-item -d "build based on test data in .yml" +complete -c west -n "__zephyr_west_seen_subcommand_from build" -o o -l build-opt -d "options to pass to build tool (make or ninja)" +complete -c west -n "__zephyr_west_seen_subcommand_from build" -o n -l just-print -l dry-run -l recon -d "just print build commands, don't run them" +complete -c west -n "__zephyr_west_seen_subcommand_from build" -o p -l pristine -ra "auto always never" -d "pristine build setting" + +# sign +complete -c west -n "__zephyr_west_use_subcommand; and __zephyr_west_check_if_in_workspace" -ra sign -d "sign a Zephyr binary for bootloader chain-loading" +complete -c west -n "__zephyr_west_seen_subcommand_from sign" -o d -l build-dir -ra "(__zephyr_west_complete_directories)" -d "build directory to create or use" +complete -c west -n "__zephyr_west_seen_subcommand_from sign" -o q -l quiet -d "suppress non-error output" +complete -c west -n "__zephyr_west_seen_subcommand_from sign" -o f -l force -d "ignore errors and continue" +complete -c west -n "__zephyr_west_seen_subcommand_from sign" -o t -l tool -ra "imgtool rimage" -d "image signing tool name" +complete -c west -n "__zephyr_west_seen_subcommand_from sign" -o p -l tool-path -ra "(__zephyr_west_complete_directories)" -d "path to the tool" +complete -c west -n "__zephyr_west_seen_subcommand_from sign" -o P -l tool-data -ra "(__zephyr_west_complete_directories)" -d "path to tool data" +complete -c west -n "__zephyr_west_seen_subcommand_from sign; and __zephyr_west_exclude --no-bin" -l bin -d "produce a signed bin file" +complete -c west -n "__zephyr_west_seen_subcommand_from sign; and __zephyr_west_exclude --bin" -l no-bin -d "do not produce a signed bin file" +complete -c west -n "__zephyr_west_seen_subcommand_from sign" -o B -l sbin -rF -d "signed .bin filename" +complete -c west -n "__zephyr_west_seen_subcommand_from sign; and __zephyr_west_exclude --no-hex" -l hex -d "produce a signed hex file" +complete -c west -n "__zephyr_west_seen_subcommand_from sign; and __zephyr_west_exclude --hex" -l no-hex -d "do not produce a signed hex file" +complete -c west -n "__zephyr_west_seen_subcommand_from sign" -o H -l shex -rF -d "signed .hex filename" + +# flash +complete -c west -n "__zephyr_west_use_subcommand; and __zephyr_west_check_if_in_workspace" -ra flash -d "flash and run a binary on a board" + +# debug +complete -c west -n "__zephyr_west_use_subcommand; and __zephyr_west_check_if_in_workspace" -ra debug -d "flash and interactively debug a Zephyr application" + +# debugserver +complete -c west -n "__zephyr_west_use_subcommand; and __zephyr_west_check_if_in_workspace" -ra debugserver -d "connect to board and launch a debug server" + +# attach +complete -c west -n "__zephyr_west_use_subcommand; and __zephyr_west_check_if_in_workspace" -ra attach -d "interactively debug a board" + +## flash, debug, debugserver, attach +complete -c west -n "__zephyr_west_seen_subcommand_from flash debug debugserver attach" -o d -l build-dir -ra "(__zephyr_west_complete_directories)" -d "build directory to create or use" +complete -c west -n "__zephyr_west_seen_subcommand_from flash debug debugserver attach" -o r -l runner -r -d "override default runner from build-dir" +complete -c west -n "__zephyr_west_seen_subcommand_from flash debug debugserver attach" -l skip-rebuild -d "do not refresh cmake dependencies first" +complete -c west -n "__zephyr_west_seen_subcommand_from flash debug debugserver attach" -l domain -r -d "execute build tool (make or ninja) for a given domain" +complete -c west -n "__zephyr_west_seen_subcommand_from flash debug debugserver attach" -o H -l context -d "print runner-specific options" +complete -c west -n "__zephyr_west_seen_subcommand_from flash debug debugserver attach" -l board-dir -ra "(__zephyr_west_complete_directories)" -d "board directory" +complete -c west -n "__zephyr_west_seen_subcommand_from flash debug debugserver attach" -o f -l file -Fr -d "path to binary" +complete -c west -n "__zephyr_west_seen_subcommand_from flash debug debugserver attach" -o t -l file-type -ra "hex bin elf" -d "type of binary" +complete -c west -n "__zephyr_west_seen_subcommand_from flash debug debugserver attach" -l elf-file -rka "(__fish_complete_suffix .elf)" -d "path to zephyr.elf" +complete -c west -n "__zephyr_west_seen_subcommand_from flash debug debugserver attach" -l hex-file -rka "(__fish_complete_suffix .hex)" -d "path to zephyr.hex" +complete -c west -n "__zephyr_west_seen_subcommand_from flash debug debugserver attach" -l bin-file -rka "(__fish_complete_suffix .bin)" -d "path to zephyr.bin" +complete -c west -n "__zephyr_west_seen_subcommand_from flash debug debugserver attach" -l gdb -Fr -d "path to GDB" +complete -c west -n "__zephyr_west_seen_subcommand_from flash debug debugserver attach" -l openocd -Fr -d "path to openocd" +complete -c west -n "__zephyr_west_seen_subcommand_from flash debug debugserver attach" -l openocd-search -ra "(__zephyr_west_complete_directories)" -d "path to add to openocd search path" + +# zephyr-export +complete -c west -n "__zephyr_west_use_subcommand; and __zephyr_west_check_if_in_workspace" -ra zephyr-export -d "export Zephyr installation as a CMake config package" + +# spdx +complete -c west -n "__zephyr_west_use_subcommand; and __zephyr_west_check_if_in_workspace" -ra spdx -d "create SPDX bill of materials" +complete -c west -n "__zephyr_west_seen_subcommand_from spdx" -o i -l init -d "initialize CMake file-based API" +complete -c west -n "__zephyr_west_seen_subcommand_from spdx" -o d -l build-dir -ra "(__zephyr_west_complete_directories)" -d "build directory to create or use" +complete -c west -n "__zephyr_west_seen_subcommand_from spdx" -o n -l namespace-prefix -rf -d "namespace prefix" +complete -c west -n "__zephyr_west_seen_subcommand_from spdx" -o s -l spdx-dir -ra "(__zephyr_west_complete_directories)" -d "SPDX output directory" +complete -c west -n "__zephyr_west_seen_subcommand_from spdx" -l analyze-includes -d "also analyze included header files" +complete -c west -n "__zephyr_west_seen_subcommand_from spdx" -l include-sdk -d "also generate SPDX document for SDK" + +# blobs +complete -c west -n "__zephyr_west_use_subcommand; and __zephyr_west_check_if_in_workspace" -ra blobs -d "work with binary blobs" +complete -c west -n "__zephyr_west_seen_subcommand_from blobs; and not __fish_seen_subcommand_from list fetch clean" -ra "list\t'list binary blobs' fetch\t'fetch binary blobs' clean\t'clean working tree of binary blobs'" +complete -c west -n "__zephyr_west_seen_subcommand_from blobs; and __fish_seen_subcommand_from list fetch clean" -ra "(__zephyr_west_complete_projects)" +complete -c west -n "__zephyr_west_seen_subcommand_from blobs; and not __fish_seen_subcommand_from fetch clean" -o f -l format -r -d "format string" diff --git a/scripts/west_commands/completion/west-completion.zsh b/scripts/west_commands/completion/west-completion.zsh index 8cca9b5eee0..b3a881288c0 100644 --- a/scripts/west_commands/completion/west-completion.zsh +++ b/scripts/west_commands/completion/west-completion.zsh @@ -205,7 +205,7 @@ _west_help() { _west_completion() { - _arguments -S "1:shell:(bash zsh)" + _arguments -S "1:shell:(bash zsh fish)" } _west_boards() { @@ -300,7 +300,7 @@ _west_spdx() { '(-i --init)'{-i,--init}'[initialize CMake file-based API]' '(-d --build-dir)'{-d,--build-dir}'[build directory to create or use]:build dir:_directories' '(-n --namespace-prefix)'{-n,--namespace-prefix}'[namespace prefix]:namespace prefix:' - '(-s --spdx-dir)'{-d,--spdx-dir}'[SPDX output directory]:spdx output dir:_directories' + '(-s --spdx-dir)'{-s,--spdx-dir}'[SPDX output directory]:spdx output dir:_directories' '--analyze-includes[also analyze included header files]' '--include-sdk[also generate SPDX document for SDK]' ) diff --git a/scripts/west_commands/run_common.py b/scripts/west_commands/run_common.py index ba62c5c46f7..43d736f2b68 100644 --- a/scripts/west_commands/run_common.py +++ b/scripts/west_commands/run_common.py @@ -411,6 +411,7 @@ def filetype(attr): return RunnerConfig(build_dir, yaml_config['board_dir'], output_file('elf'), + output_file('exe'), output_file('hex'), output_file('bin'), output_file('uf2'), diff --git a/scripts/west_commands/runners/__init__.py b/scripts/west_commands/runners/__init__.py index f4340bc19b0..850efcd5668 100644 --- a/scripts/west_commands/runners/__init__.py +++ b/scripts/west_commands/runners/__init__.py @@ -45,6 +45,7 @@ def _import_runner_module(runner_name): 'nrfjprog', 'nrfutil', 'nsim', + 'nxp_s32dbg', 'openocd', 'pyocd', 'qemu', diff --git a/scripts/west_commands/runners/bossac.py b/scripts/west_commands/runners/bossac.py index ab214210c78..fcbd6fdf92b 100644 --- a/scripts/west_commands/runners/bossac.py +++ b/scripts/west_commands/runners/bossac.py @@ -149,12 +149,19 @@ def get_image_offset(self, supports_offset): return None + def is_gnu_coreutils_stty(self): + try: + result = subprocess.run(['stty', '--version'], capture_output=True, text=True, check=True) + return 'coreutils' in result.stdout + except subprocess.CalledProcessError: + return False + def set_serial_config(self): if platform.system() == 'Linux' or platform.system() == 'Darwin': self.require('stty') # GNU coreutils uses a capital F flag for 'file' - flag = '-F' if platform.system() == 'Linux' else '-f' + flag = '-F' if self.is_gnu_coreutils_stty() else '-f' if self.is_extended_samba_protocol(): self.speed = '1200' diff --git a/scripts/west_commands/runners/core.py b/scripts/west_commands/runners/core.py index b569625e4e6..9b3ca51d900 100644 --- a/scripts/west_commands/runners/core.py +++ b/scripts/west_commands/runners/core.py @@ -22,6 +22,7 @@ import signal import subprocess import re +from dataclasses import dataclass, field from functools import partial from enum import Enum from inspect import isabstract @@ -199,6 +200,9 @@ def __init__(self, program): super().__init__(errno.ENOENT, os.strerror(errno.ENOENT), program) +_RUNNERCAPS_COMMANDS = {'flash', 'debug', 'debugserver', 'attach'} + +@dataclass class RunnerCaps: '''This class represents a runner class's capabilities. @@ -229,34 +233,29 @@ class RunnerCaps: erased by the underlying tool before flashing; UICR on nRF SoCs is one example.) + - reset: whether the runner supports a --reset option, which + resets the device after a flash operation is complete. + - tool_opt: whether the runner supports a --tool-opt (-O) option, which can be given multiple times and is passed on to the underlying tool that the runner wraps. + + - file: whether the runner supports a --file option, which specifies + exactly the file that should be used to flash, overriding any default + discovered in the build directory. ''' - def __init__(self, - commands: Set[str] = {'flash', 'debug', - 'debugserver', 'attach'}, - dev_id: bool = False, - flash_addr: bool = False, - erase: bool = False, - tool_opt: bool = False, - file: bool = False): - self.commands = commands - self.dev_id = dev_id - self.flash_addr = bool(flash_addr) - self.erase = bool(erase) - self.tool_opt = bool(tool_opt) - self.file = bool(file) - - def __str__(self): - return (f'RunnerCaps(commands={self.commands}, ' - f'dev_id={self.dev_id}, ' - f'flash_addr={self.flash_addr}, ' - f'erase={self.erase}, ' - f'tool_opt={self.tool_opt}, ' - f'file={self.file}' - ')') + commands: Set[str] = field(default_factory=lambda: set(_RUNNERCAPS_COMMANDS)) + dev_id: bool = False + flash_addr: bool = False + erase: bool = False + reset: bool = False + tool_opt: bool = False + file: bool = False + + def __post_init__(self): + if not self.commands.issubset(_RUNNERCAPS_COMMANDS): + raise ValueError(f'{self.commands=} contains invalid command') def _missing_cap(cls: Type['ZephyrBinaryRunner'], option: str) -> NoReturn: @@ -284,6 +283,7 @@ class RunnerConfig(NamedTuple): build_dir: str # application build directory board_dir: str # board definition directory elf_file: Optional[str] # zephyr.elf path, or None + exe_file: Optional[str] # zephyr.exe path, or None hex_file: Optional[str] # zephyr.hex path, or None bin_file: Optional[str] # zephyr.bin path, or None uf2_file: Optional[str] # zephyr.uf2 path, or None @@ -521,9 +521,16 @@ def add_parser(cls, parser): parser.add_argument('--erase', '--no-erase', nargs=0, action=_ToggleAction, - help=("mass erase flash before loading, or don't" + help=("mass erase flash before loading, or don't. " + "Default action depends on each specific runner." if caps.erase else argparse.SUPPRESS)) + parser.add_argument('--reset', '--no-reset', nargs=0, + action=_ToggleAction, + help=("reset device after flashing, or don't. " + "Default action depends on each specific runner." + if caps.reset else argparse.SUPPRESS)) + parser.add_argument('-O', '--tool-opt', dest='tool_opt', default=[], action='append', help=(cls.tool_opt_help() if caps.tool_opt @@ -552,6 +559,8 @@ def create(cls, cfg: RunnerConfig, _missing_cap(cls, '--dt-flash') if args.erase and not caps.erase: _missing_cap(cls, '--erase') + if args.reset and not caps.reset: + _missing_cap(cls, '--reset') if args.tool_opt and not caps.tool_opt: _missing_cap(cls, '--tool-opt') if args.file and not caps.file: @@ -564,6 +573,8 @@ def create(cls, cfg: RunnerConfig, ret = cls.do_create(cfg, args) if args.erase: ret.logger.info('mass erase requested') + if args.reset: + ret.logger.info('reset after flashing requested') return ret @classmethod @@ -647,24 +658,26 @@ def tool_opt_help(cls) -> str: in the order they appear on the command line.''' @staticmethod - def require(program: str) -> str: + def require(program: str, path: Optional[str] = None) -> str: '''Require that a program is installed before proceeding. :param program: name of the program that is required, or path to a program binary. + :param path: PATH where to search for the program binary. + By default check on the system PATH. If ``program`` is an absolute path to an existing program binary, this call succeeds. Otherwise, try to find the program - by name on the system PATH. + by name on the system PATH or in the given PATH, if provided. If the program can be found, its path is returned. Otherwise, raises MissingProgram.''' - ret = shutil.which(program) + ret = shutil.which(program, path=path) if ret is None: raise MissingProgram(program) return ret - def run_server_and_client(self, server, client): + def run_server_and_client(self, server, client, **kwargs): '''Run a server that ignores SIGINT, and a client that handles it. This routine portably: @@ -673,20 +686,22 @@ def run_server_and_client(self, server, client): SIGINT - runs ``client`` in a subprocess while temporarily ignoring SIGINT - cleans up the server after the client exits. + - the keyword arguments, if any, will be passed down to both server and + client subprocess calls It's useful to e.g. open a GDB server and client.''' - server_proc = self.popen_ignore_int(server) + server_proc = self.popen_ignore_int(server, **kwargs) try: - self.run_client(client) + self.run_client(client, **kwargs) finally: server_proc.terminate() server_proc.wait() - def run_client(self, client): + def run_client(self, client, **kwargs): '''Run a client that handles SIGINT.''' previous = signal.signal(signal.SIGINT, signal.SIG_IGN) try: - self.check_call(client) + self.check_call(client, **kwargs) finally: signal.signal(signal.SIGINT, previous) diff --git a/scripts/west_commands/runners/esp32.py b/scripts/west_commands/runners/esp32.py index d435014fc38..0ccf0c98d1f 100644 --- a/scripts/west_commands/runners/esp32.py +++ b/scripts/west_commands/runners/esp32.py @@ -16,13 +16,15 @@ class Esp32BinaryRunner(ZephyrBinaryRunner): '''Runner front-end for espidf.''' def __init__(self, cfg, device, boot_address, part_table_address, - app_address, erase=False, baud=921600, flash_size='detect', - flash_freq='40m', flash_mode='dio', espidf='espidf', - bootloader_bin=None, partition_table_bin=None, no_stub=False): + app_address, erase=False, reset=False, baud=921600, + flash_size='detect', flash_freq='40m', flash_mode='dio', + espidf='espidf', bootloader_bin=None, partition_table_bin=None, + no_stub=False): super().__init__(cfg) self.elf = cfg.elf_file self.app_bin = cfg.bin_file self.erase = bool(erase) + self.reset = bool(reset) self.device = device self.boot_address = boot_address self.part_table_address = part_table_address @@ -42,7 +44,7 @@ def name(cls): @classmethod def capabilities(cls): - return RunnerCaps(commands={'flash'}, erase=True) + return RunnerCaps(commands={'flash'}, erase=True, reset=True) @classmethod def do_add_parser(cls, parser): @@ -77,6 +79,8 @@ def do_add_parser(cls, parser): parser.add_argument('--esp-no-stub', default=False, action='store_true', help='Disable launching the flasher stub, only talk to ROM bootloader') + parser.set_defaults(reset=True) + @classmethod def do_create(cls, cfg, args): if args.esp_tool: @@ -88,7 +92,7 @@ def do_create(cls, cfg, args): return Esp32BinaryRunner( cfg, args.esp_device, boot_address=args.esp_boot_address, part_table_address=args.esp_partition_table_address, - app_address=args.esp_app_address, erase=args.erase, + app_address=args.esp_app_address, erase=args.erase, reset=args.reset, baud=args.esp_baud_rate, flash_size=args.esp_flash_size, flash_freq=args.esp_flash_freq, flash_mode=args.esp_flash_mode, espidf=espidf, bootloader_bin=args.esp_flash_bootloader, @@ -111,7 +115,8 @@ def do_run(self, command, **kwargs): cmd_flash.extend(['--port', self.device]) cmd_flash.extend(['--baud', self.baud]) cmd_flash.extend(['--before', 'default_reset']) - cmd_flash.extend(['--after', 'hard_reset', 'write_flash', '-u']) + if self.reset: + cmd_flash.extend(['--after', 'hard_reset', 'write_flash', '-u']) cmd_flash.extend(['--flash_mode', self.flash_mode]) cmd_flash.extend(['--flash_freq', self.flash_freq]) cmd_flash.extend(['--flash_size', self.flash_size]) diff --git a/scripts/west_commands/runners/ezflashcli.py b/scripts/west_commands/runners/ezflashcli.py index 4d9d3d3ae51..a3e1aea3d25 100644 --- a/scripts/west_commands/runners/ezflashcli.py +++ b/scripts/west_commands/runners/ezflashcli.py @@ -10,13 +10,14 @@ class EzFlashCliBinaryRunner(ZephyrBinaryRunner): '''Runner front-end for ezFlashCLI''' - def __init__(self, cfg, tool, sn, erase=False): + def __init__(self, cfg, tool, sn, erase=False, reset=True): super().__init__(cfg) self.bin_ = cfg.bin_file self.tool = tool self.sn_arg = ['-j', f'{sn}'] if sn is not None else [] self.erase = bool(erase) + self.reset = bool(reset) @classmethod def name(cls): @@ -24,7 +25,7 @@ def name(cls): @classmethod def capabilities(cls): - return RunnerCaps(commands={'flash'}, erase=True) + return RunnerCaps(commands={'flash'}, erase=True, reset=True) @classmethod def do_add_parser(cls, parser): @@ -34,6 +35,8 @@ def do_add_parser(cls, parser): parser.add_argument('--sn', default=None, required=False, help='J-Link probe serial number') + parser.set_defaults(reset=True) + @classmethod def do_create(cls, cfg, args): return EzFlashCliBinaryRunner(cfg, tool=args.tool, sn=args.sn, @@ -64,7 +67,7 @@ def program_bin(self): load_offset = self.build_conf['CONFIG_FLASH_LOAD_OFFSET'] self.check_call([self.tool] + self.sn_arg + ["write_flash", f'0x{load_offset:x}', self.bin_]) - def reset(self): + def reset_device(self): self.logger.info("Resetting...") self.check_call([self.tool] + self.sn_arg + ["go"]) @@ -72,4 +75,5 @@ def do_run(self, command, **kwargs): self.require(self.tool) self.ensure_output('bin') self.program_bin() - self.reset() + if self.reset: + self.reset_device() diff --git a/scripts/west_commands/runners/intel_adsp.py b/scripts/west_commands/runners/intel_adsp.py index 4a0c83c2f2c..18b1462ef05 100644 --- a/scripts/west_commands/runners/intel_adsp.py +++ b/scripts/west_commands/runners/intel_adsp.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 -'''Runner for flashing with the Intel ADSP CAVS boards.''' +'''Runner for flashing with the Intel ADSP boards.''' import os import sys @@ -16,7 +16,7 @@ DEFAULT_CAVSTOOL='soc/xtensa/intel_adsp/tools/cavstool_client.py' DEFAULT_SOF_MOD_DIR=os.path.join(ZEPHYR_BASE, '../modules/audio/sof') DEFAULT_RIMAGE_TOOL=shutil.which('rimage') -DEFAULT_CONFIG_DIR=os.path.join(DEFAULT_SOF_MOD_DIR, 'rimage/config') +DEFAULT_CONFIG_DIR=os.path.join(DEFAULT_SOF_MOD_DIR, 'tools/rimage/config') DEFAULT_KEY_DIR=os.path.join(DEFAULT_SOF_MOD_DIR, 'keys') @@ -113,7 +113,7 @@ def do_run(self, command, **kwargs): if self.do_sign: self.sign(**kwargs) - if re.search("intel_adsp_cavs", self.platform): + if re.search("intel_adsp", self.platform): self.require(self.cavstool) self.flash(**kwargs) else: diff --git a/scripts/west_commands/runners/jlink.py b/scripts/west_commands/runners/jlink.py index 80b7de2dffb..4fa71720673 100644 --- a/scripts/west_commands/runners/jlink.py +++ b/scripts/west_commands/runners/jlink.py @@ -35,7 +35,7 @@ class JLinkBinaryRunner(ZephyrBinaryRunner): def __init__(self, cfg, device, dev_id=None, commander=DEFAULT_JLINK_EXE, - dt_flash=True, erase=True, reset_after_load=False, + dt_flash=True, erase=True, reset=False, iface='swd', speed='auto', loader=None, gdbserver='JLinkGDBServer', @@ -54,7 +54,7 @@ def __init__(self, cfg, device, dev_id=None, self.commander = commander self.dt_flash = dt_flash self.erase = erase - self.reset_after_load = reset_after_load + self.reset = reset self.gdbserver = gdbserver self.iface = iface self.speed = speed @@ -74,7 +74,7 @@ def name(cls): @classmethod def capabilities(cls): return RunnerCaps(commands={'flash', 'debug', 'debugserver', 'attach'}, - dev_id=True, flash_addr=True, erase=True, + dev_id=True, flash_addr=True, erase=True, reset=True, tool_opt=True, file=True) @classmethod @@ -114,11 +114,11 @@ def do_add_parser(cls, parser): help=f'''J-Link Commander, default is {DEFAULT_JLINK_EXE}''') parser.add_argument('--reset-after-load', '--no-reset-after-load', - dest='reset_after_load', nargs=0, + dest='reset', nargs=0, action=ToggleAction, - help='reset after loading? (default: no)') + help='obsolete synonym for --reset/--no-reset') - parser.set_defaults(reset_after_load=False) + parser.set_defaults(reset=False) @classmethod def do_create(cls, cfg, args): @@ -127,7 +127,7 @@ def do_create(cls, cfg, args): commander=args.commander, dt_flash=args.dt_flash, erase=args.erase, - reset_after_load=args.reset_after_load, + reset=args.reset, iface=args.iface, speed=args.speed, gdbserver=args.gdbserver, loader=args.loader, @@ -266,7 +266,7 @@ def do_run(self, command, **kwargs): client_cmd += ['-ex', 'monitor halt', '-ex', 'monitor reset', '-ex', 'load'] - if self.reset_after_load: + if self.reset: client_cmd += ['-ex', 'monitor reset'] if not self.gdb_host: self.require(self.gdbserver) @@ -326,7 +326,7 @@ def flash(self, **kwargs): # Flash the selected build artifact lines.append(flash_cmd) - if self.reset_after_load: + if self.reset: lines.append('r') # Reset and halt the target lines.append('g') # Start the CPU diff --git a/scripts/west_commands/runners/linkserver.py b/scripts/west_commands/runners/linkserver.py index 10833618fa1..a4ae5c622d4 100644 --- a/scripts/west_commands/runners/linkserver.py +++ b/scripts/west_commands/runners/linkserver.py @@ -22,7 +22,7 @@ class LinkServerBinaryRunner(ZephyrBinaryRunner): '''Runner front-end for NXP Linkserver''' - def __init__(self, cfg, device, + def __init__(self, cfg, device, core, linkserver=DEFAULT_LINKSERVER_EXE, dt_flash=True, erase=True, probe=1, @@ -39,6 +39,7 @@ def __init__(self, cfg, device, self.elf_name = cfg.elf_file self.gdb_cmd = cfg.gdb if cfg.gdb else None self.device = device + self.core = core self.linkserver = linkserver self.dt_flash = dt_flash self.erase = erase @@ -68,6 +69,8 @@ def capabilities(cls): def do_add_parser(cls, parser): parser.add_argument('--device', required=True, help='device name') + parser.add_argument('--core', required=False, help='core of the device') + parser.add_argument('--probe', default=1, help='interface to use (index, no serial number), default is 1') @@ -92,7 +95,7 @@ def do_add_parser(cls, parser): @classmethod def do_create(cls, cfg, args): - return LinkServerBinaryRunner(cfg, args.device, + return LinkServerBinaryRunner(cfg, args.device, args.core, linkserver=args.linkserver, dt_flash=args.dt_flash, erase=args.erase, @@ -108,7 +111,7 @@ def linkserver_version_str(self): if not hasattr(self, '_linkserver_version'): linkserver_version_cmd=[self.linkserver, "-v"] ls_output=self.check_output(linkserver_version_cmd) - self.linkserver_version = str(ls_output.split()[1].decode()) + self.linkserver_version = str(ls_output.split()[1].decode()).lower() return self.linkserver_version @@ -120,14 +123,22 @@ def do_run(self, command, **kwargs): if command == 'flash': self.flash(**kwargs) else: + if self.core is not None: + _cmd_core = [ "-c", self.core ] + else: + _cmd_core = [] + linkserver_cmd = ([self.linkserver] + ["gdbserver"] + ["--probe", "#"+str(self.probe) ] + ["--gdb-port", str(self.gdb_port )] + ["--semihost-port", str(self.semihost_port) ] + - self.override_cli + + _cmd_core + + self.override_cli + [self.device]) + self.logger.debug(f'LinkServer cmd: + {linkserver_cmd}') + if command in ('debug', 'attach'): if self.elf_name is None or not os.path.isfile(self.elf_name): raise ValueError('Cannot debug; elf file required') @@ -153,8 +164,13 @@ def do_run(self, command, **kwargs): def do_erase(self, **kwargs): + if self.core is not None: + _cmd_core = ":"+self.core + else: + _cmd_core = "" + linkserver_cmd = ([self.linkserver, "flash"] + ["--probe", "#"+str(self.probe)] + - [self.device] + ["erase"]) + [self.device+_cmd_core] + ["erase"]) self.logger.debug("flash erase command = " + str(linkserver_cmd)) self.check_call(linkserver_cmd) @@ -170,7 +186,13 @@ def _build_override_cli(self): def flash(self, **kwargs): - linkserver_cmd = ([self.linkserver, "flash"] + ["--probe", "#"+str(self.probe)] + self.override_cli + [self.device]) + if self.core is not None: + _cmd_core = ":"+self.core + else: + _cmd_core = "" + + linkserver_cmd = ([self.linkserver, "flash"] + ["--probe", "#"+str(self.probe)] + self.override_cli + [self.device+_cmd_core]) + self.logger.debug(f'LinkServer cmd: + {linkserver_cmd}') if self.erase: self.do_erase() @@ -192,5 +214,9 @@ def flash(self, **kwargs): self.logger.debug("flash command = " + str(linkserver_cmd)) kwargs = {} if not self.logger.isEnabledFor(logging.DEBUG): - kwargs['stderr'] = subprocess.DEVNULL + if self.linkserver_version_str < "v1.3.15": + kwargs['stderr'] = subprocess.DEVNULL + else: + kwargs['stdout'] = subprocess.DEVNULL + self.check_call(linkserver_cmd, **kwargs) diff --git a/scripts/west_commands/runners/mdb.py b/scripts/west_commands/runners/mdb.py index 3a7410969af..656d41618a6 100644 --- a/scripts/west_commands/runners/mdb.py +++ b/scripts/west_commands/runners/mdb.py @@ -72,7 +72,7 @@ def mdb_do_run(mdb_runner, command): if mdb_runner.cores == 1: # single core's mdb command is different with multicores mdb_cmd = [commander] + mdb_basic_options + mdb_target + mdb_run + [mdb_runner.elf_name] - elif 1 < mdb_runner.cores <= 4: + elif 1 < mdb_runner.cores <= 12: mdb_multifiles = '-multifiles=' for i in range(mdb_runner.cores): mdb_sub_cmd = [commander] + ['-pset={}'.format(i + 1), '-psetname=core{}'.format(i)] diff --git a/scripts/west_commands/runners/native_gdb.py b/scripts/west_commands/runners/native_gdb.py index 777290cd3e8..163fe01793b 100644 --- a/scripts/west_commands/runners/native_gdb.py +++ b/scripts/west_commands/runners/native_gdb.py @@ -36,11 +36,11 @@ def do_run(self, command: str, **kwargs): if self.cfg.gdb is None: raise ValueError("The provided RunnerConfig is missing the required field 'gdb'.") - if self.cfg.elf_file is None: - raise ValueError("The provided RunnerConfig is missing the required field 'elf_file'.") + if self.cfg.exe_file is None: + raise ValueError("The provided RunnerConfig is missing the required field 'exe_file'.") self.call([ self.cfg.gdb, '--quiet', - self.cfg.elf_file, + self.cfg.exe_file, ]) diff --git a/scripts/west_commands/runners/nrf_common.py b/scripts/west_commands/runners/nrf_common.py index 1a66ed0bded..2ff51d7e85d 100644 --- a/scripts/west_commands/runners/nrf_common.py +++ b/scripts/west_commands/runners/nrf_common.py @@ -28,7 +28,7 @@ class NrfBinaryRunner(ZephyrBinaryRunner): '''Runner front-end base class for nrf tools.''' def __init__(self, cfg, family, softreset, dev_id, erase=False, - tool_opt=[], force=False, recover=False): + reset=True, tool_opt=[], force=False, recover=False): super().__init__(cfg) self.hex_ = cfg.hex_file if family and not family.endswith('_FAMILY'): @@ -37,6 +37,7 @@ def __init__(self, cfg, family, softreset, dev_id, erase=False, self.softreset = softreset self.dev_id = dev_id self.erase = bool(erase) + self.reset = bool(reset) self.force = force self.recover = bool(recover) @@ -47,7 +48,7 @@ def __init__(self, cfg, family, softreset, dev_id, erase=False, @classmethod def capabilities(cls): return RunnerCaps(commands={'flash'}, dev_id=True, erase=True, - tool_opt=True) + reset=True, tool_opt=True) @classmethod def dev_id_help(cls) -> str: @@ -75,6 +76,8 @@ def do_add_parser(cls, parser): memory and disable read back protection before flashing (erases flash for both cores on nRF53)''') + parser.set_defaults(reset=True) + def ensure_snr(self): if not self.dev_id or "*" in self.dev_id: self.dev_id = self.get_board_snr(self.dev_id or "*") @@ -224,6 +227,11 @@ def recover_target(self): else: self.logger.info('Recovering and erasing all flash memory.') + # The network core needs to be recovered first due to the fact that + # recovering it erases the flash of *both* cores. Since a recover + # operation unlocks the core and then flashes a small image that keeps + # the debug access port open, recovering the network core last would + # result in that small image being deleted from the app core. if self.family == 'NRF53_FAMILY': self.exec_op('recover', core='NRFDL_DEVICE_CORE_NETWORK') @@ -398,7 +406,8 @@ def do_run(self, command, **kwargs): if self.recover: self.recover_target() self.program_hex() - self.reset_target() + if self.reset: + self.reset_target() # All done, now flush any outstanding ops self.flush(force=True) diff --git a/scripts/west_commands/runners/nrfjprog.py b/scripts/west_commands/runners/nrfjprog.py index 9671def33c1..8762ce0e740 100644 --- a/scripts/west_commands/runners/nrfjprog.py +++ b/scripts/west_commands/runners/nrfjprog.py @@ -30,6 +30,7 @@ def tool_opt_help(cls) -> str: def do_create(cls, cfg, args): return NrfJprogBinaryRunner(cfg, args.nrf_family, args.softreset, args.dev_id, erase=args.erase, + reset=args.reset, tool_opt=args.tool_opt, force=args.force, recover=args.recover) diff --git a/scripts/west_commands/runners/nrfutil.py b/scripts/west_commands/runners/nrfutil.py index 9c92c07f07d..719e432a23b 100644 --- a/scripts/west_commands/runners/nrfutil.py +++ b/scripts/west_commands/runners/nrfutil.py @@ -16,9 +16,9 @@ class NrfUtilBinaryRunner(NrfBinaryRunner): '''Runner front-end for nrfutil.''' def __init__(self, cfg, family, softreset, dev_id, erase=False, - tool_opt=[], force=False, recover=False): + reset=True, tool_opt=[], force=False, recover=False): - super().__init__(cfg, family, softreset, dev_id, erase, + super().__init__(cfg, family, softreset, dev_id, erase, reset, tool_opt, force, recover) self._ops = [] self._op_id = 1 @@ -35,6 +35,7 @@ def tool_opt_help(cls) -> str: def do_create(cls, cfg, args): return NrfUtilBinaryRunner(cfg, args.nrf_family, args.softreset, args.dev_id, erase=args.erase, + reset=args.reset, tool_opt=args.tool_opt, force=args.force, recover=args.recover) diff --git a/scripts/west_commands/runners/nxp_s32dbg.py b/scripts/west_commands/runners/nxp_s32dbg.py new file mode 100644 index 00000000000..e2065f3980f --- /dev/null +++ b/scripts/west_commands/runners/nxp_s32dbg.py @@ -0,0 +1,334 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 +""" +Runner for NXP S32 Debug Probe. +""" + +import argparse +import os +import platform +import re +import shlex +import subprocess +import sys +import tempfile +from dataclasses import dataclass +from pathlib import Path +from typing import Dict, List, Optional, Union + +from runners.core import (BuildConfiguration, RunnerCaps, RunnerConfig, + ZephyrBinaryRunner) + +NXP_S32DBG_USB_CLASS = 'NXP Probes' +NXP_S32DBG_USB_VID = 0x15a2 +NXP_S32DBG_USB_PID = 0x0067 + + +@dataclass +class NXPS32DebugProbeConfig: + """NXP S32 Debug Probe configuration parameters.""" + conn_str: str = 's32dbg' + server_port: int = 45000 + speed: int = 16000 + remote_timeout: int = 30 + reset_type: Optional[str] = 'default' + reset_delay: int = 0 + + +class NXPS32DebugProbeRunner(ZephyrBinaryRunner): + """Runner front-end for NXP S32 Debug Probe.""" + + def __init__(self, + runner_cfg: RunnerConfig, + probe_cfg: NXPS32DebugProbeConfig, + core_name: str, + soc_name: str, + soc_family_name: str, + start_all_cores: bool, + s32ds_path: Optional[str] = None, + tool_opt: Optional[List[str]] = None) -> None: + super(NXPS32DebugProbeRunner, self).__init__(runner_cfg) + self.elf_file: str = runner_cfg.elf_file or '' + self.probe_cfg: NXPS32DebugProbeConfig = probe_cfg + self.core_name: str = core_name + self.soc_name: str = soc_name + self.soc_family_name: str = soc_family_name + self.start_all_cores: bool = start_all_cores + self.s32ds_path_override: Optional[str] = s32ds_path + + self.tool_opt: List[str] = [] + if tool_opt: + for opt in tool_opt: + self.tool_opt.extend(shlex.split(opt)) + + build_cfg = BuildConfiguration(runner_cfg.build_dir) + self.arch = build_cfg.get('CONFIG_ARCH').replace('"', '') + + @classmethod + def name(cls) -> str: + return 'nxp_s32dbg' + + @classmethod + def capabilities(cls) -> RunnerCaps: + return RunnerCaps(commands={'debug', 'debugserver', 'attach'}, + dev_id=True, tool_opt=True) + + @classmethod + def dev_id_help(cls) -> str: + return '''Debug probe connection string as in "s32dbg[:
    ]" + where
    can be the IP address if TAP is available via Ethernet, + the serial ID of the probe or empty if TAP is available via USB.''' + + @classmethod + def tool_opt_help(cls) -> str: + return '''Additional options for GDB client when used with "debug" or "attach" commands + or for GTA server when used with "debugserver" command.''' + + @classmethod + def do_add_parser(cls, parser: argparse.ArgumentParser) -> None: + parser.add_argument('--core-name', + required=True, + help='Core name as supported by the debug probe (e.g. "R52_0_0")') + parser.add_argument('--soc-name', + required=True, + help='SoC name as supported by the debug probe (e.g. "S32Z270")') + parser.add_argument('--soc-family-name', + required=True, + help='SoC family name as supported by the debug probe (e.g. "s32z2e2")') + parser.add_argument('--start-all-cores', + action='store_true', + help='Start all SoC cores and not just the one being debugged. ' + 'Use together with "debug" command.') + parser.add_argument('--s32ds-path', + help='Override the path to NXP S32 Design Studio installation. ' + 'By default, this runner will try to obtain it from the system ' + 'path, if available.') + parser.add_argument('--server-port', + default=NXPS32DebugProbeConfig.server_port, + type=int, + help='GTA server port') + parser.add_argument('--speed', + default=NXPS32DebugProbeConfig.speed, + type=int, + help='JTAG interface speed') + parser.add_argument('--remote-timeout', + default=NXPS32DebugProbeConfig.remote_timeout, + type=int, + help='Number of seconds to wait for the remote target responses') + + @classmethod + def do_create(cls, cfg: RunnerConfig, args: argparse.Namespace) -> 'NXPS32DebugProbeRunner': + probe_cfg = NXPS32DebugProbeConfig(args.dev_id, + server_port=args.server_port, + speed=args.speed, + remote_timeout=args.remote_timeout) + + return NXPS32DebugProbeRunner(cfg, probe_cfg, args.core_name, args.soc_name, + args.soc_family_name, args.start_all_cores, + s32ds_path=args.s32ds_path, tool_opt=args.tool_opt) + + @staticmethod + def find_usb_probes() -> List[str]: + """Return a list of debug probe serial numbers connected via USB to this host.""" + # use system's native commands to enumerate and retrieve the USB serial ID + # to avoid bloating this runner with third-party dependencies that often + # require priviledged permissions to access the device info + macaddr_pattern = r'(?:[0-9a-f]{2}[:]){5}[0-9a-f]{2}' + if platform.system() == 'Windows': + cmd = f'pnputil /enum-devices /connected /class "{NXP_S32DBG_USB_CLASS}"' + serialid_pattern = f'instance id: +usb\\\\.*\\\\({macaddr_pattern})' + else: + cmd = f'lsusb -v -d {NXP_S32DBG_USB_VID:x}:{NXP_S32DBG_USB_PID:x}' + serialid_pattern = f'iserial +.*({macaddr_pattern})' + + try: + outb = subprocess.check_output(shlex.split(cmd), stderr=subprocess.DEVNULL) + out = outb.decode('utf-8').strip().lower() + except subprocess.CalledProcessError: + raise RuntimeError('error while looking for debug probes connected') + + devices: List[str] = [] + if out and 'no devices were found' not in out: + devices = re.findall(serialid_pattern, out) + + return sorted(devices) + + @classmethod + def select_probe(cls) -> str: + """ + Find debugger probes connected and return the serial number of the one selected. + + If there are multiple debugger probes connected and this runner is being executed + in a interactive prompt, ask the user to select one of the probes. + """ + probes_snr = cls.find_usb_probes() + if not probes_snr: + raise RuntimeError('there are no debug probes connected') + elif len(probes_snr) == 1: + return probes_snr[0] + else: + if not sys.stdin.isatty(): + raise RuntimeError( + f'refusing to guess which of {len(probes_snr)} connected probes to use ' + '(Interactive prompts disabled since standard input is not a terminal). ' + 'Please specify a device ID on the command line.') + + print('There are multiple debug probes connected') + for i, probe in enumerate(probes_snr, 1): + print(f'{i}. {probe}') + + prompt = f'Please select one with desired serial number (1-{len(probes_snr)}): ' + while True: + try: + value: int = int(input(prompt)) + except EOFError: + sys.exit(0) + except ValueError: + continue + if 1 <= value <= len(probes_snr): + break + return probes_snr[value - 1] + + @property + def runtime_environment(self) -> Optional[Dict[str, str]]: + """Execution environment used for the client process.""" + if platform.system() == 'Windows': + python_lib = (self.s32ds_path / 'S32DS' / 'build_tools' / 'msys32' + / 'mingw32' / 'lib' / 'python2.7') + return { + **os.environ, + 'PYTHONPATH': f'{python_lib}{os.pathsep}{python_lib / "site-packages"}' + } + + return None + + @property + def script_globals(self) -> Dict[str, Optional[Union[str, int]]]: + """Global variables required by the debugger scripts.""" + return { + '_PROBE_IP': self.probe_cfg.conn_str, + '_JTAG_SPEED': self.probe_cfg.speed, + '_GDB_SERVER_PORT': self.probe_cfg.server_port, + '_RESET_TYPE': self.probe_cfg.reset_type, + '_RESET_DELAY': self.probe_cfg.reset_delay, + '_REMOTE_TIMEOUT': self.probe_cfg.remote_timeout, + '_CORE_NAME': f'{self.soc_name}_{self.core_name}', + '_SOC_NAME': self.soc_name, + '_IS_LOGGING_ENABLED': False, + '_FLASH_NAME': None, # not supported + '_SECURE_TYPE': None, # not supported + '_SECURE_KEY': None, # not supported + } + + def server_commands(self) -> List[str]: + """Get launch commands to start the GTA server.""" + server_exec = str(self.s32ds_path / 'S32DS' / 'tools' / 'S32Debugger' + / 'Debugger' / 'Server' / 'gta' / 'gta') + cmd = [server_exec, '-p', str(self.probe_cfg.server_port)] + return cmd + + def client_commands(self) -> List[str]: + """Get launch commands to start the GDB client.""" + if self.arch == 'arm': + client_exec_name = 'arm-none-eabi-gdb-py' + elif self.arch == 'arm64': + client_exec_name = 'aarch64-none-elf-gdb-py' + else: + raise RuntimeError(f'architecture {self.arch} not supported') + + client_exec = str(self.s32ds_path / 'S32DS' / 'tools' / 'gdb-arm' + / 'arm32-eabi' / 'bin' / client_exec_name) + cmd = [client_exec] + return cmd + + def get_script(self, name: str) -> Path: + """ + Get the file path of a debugger script with the given name. + + :param name: name of the script, without the SoC family name prefix + :returns: path to the script + :raises RuntimeError: if file does not exist + """ + script = (self.s32ds_path / 'S32DS' / 'tools' / 'S32Debugger' / 'Debugger' / 'scripts' + / self.soc_family_name / f'{self.soc_family_name}_{name}.py') + if not script.exists(): + raise RuntimeError(f'script not found: {script}') + return script + + def do_run(self, command: str, **kwargs) -> None: + """ + Execute the given command. + + :param command: command name to execute + :raises RuntimeError: if target architecture or host OS is not supported + :raises MissingProgram: if required tools are not found in the host + """ + if platform.system() not in ('Windows', 'Linux'): + raise RuntimeError(f'runner not supported on {platform.system()} systems') + + if self.arch not in ('arm', 'arm64'): + raise RuntimeError(f'architecture {self.arch} not supported') + + app_name = 's32ds' if platform.system() == 'Windows' else 's32ds.sh' + self.s32ds_path = Path(self.require(app_name, path=self.s32ds_path_override)).parent + + if not self.probe_cfg.conn_str: + self.probe_cfg.conn_str = f's32dbg:{self.select_probe()}' + self.logger.info(f'using debug probe {self.probe_cfg.conn_str}') + + if command in ('attach', 'debug'): + self.ensure_output('elf') + self.do_attach_debug(command, **kwargs) + else: + self.do_debugserver(**kwargs) + + def do_attach_debug(self, command: str, **kwargs) -> None: + """ + Launch the GTA server and GDB client to start a debugging session. + + :param command: command name to execute + """ + gdb_script: List[str] = [] + + # setup global variables required for the scripts before sourcing them + for name, val in self.script_globals.items(): + gdb_script.append(f'py {name} = {repr(val)}') + + # load platform-specific debugger script + if command == 'debug': + if self.start_all_cores: + startup_script = self.get_script('generic_bareboard_all_cores') + else: + startup_script = self.get_script('generic_bareboard') + else: + startup_script = self.get_script('attach') + gdb_script.append(f'source {startup_script}') + + # executes the SoC and board initialization sequence + if command == 'debug': + gdb_script.append('py board_init()') + + # initializes the debugger connection to the core specified + gdb_script.append('py core_init()') + + gdb_script.append(f'file {Path(self.elf_file).as_posix()}') + if command == 'debug': + gdb_script.append('load') + + with tempfile.TemporaryDirectory(suffix='nxp_s32dbg') as tmpdir: + gdb_cmds = Path(tmpdir) / 'runner.nxp_s32dbg' + gdb_cmds.write_text('\n'.join(gdb_script), encoding='utf-8') + self.logger.debug(gdb_cmds.read_text(encoding='utf-8')) + + server_cmd = self.server_commands() + client_cmd = self.client_commands() + client_cmd.extend(['-x', gdb_cmds.as_posix()]) + client_cmd.extend(self.tool_opt) + + self.run_server_and_client(server_cmd, client_cmd, env=self.runtime_environment) + + def do_debugserver(self, **kwargs) -> None: + """Start the GTA server on a given port with the given extra parameters from cli.""" + server_cmd = self.server_commands() + server_cmd.extend(self.tool_opt) + self.check_call(server_cmd) diff --git a/scripts/west_commands/runners/stm32flash.py b/scripts/west_commands/runners/stm32flash.py index 052c45dbb49..5aa544d4b2a 100644 --- a/scripts/west_commands/runners/stm32flash.py +++ b/scripts/west_commands/runners/stm32flash.py @@ -37,7 +37,7 @@ def name(cls): @classmethod def capabilities(cls): - return RunnerCaps(commands={'flash'}) + return RunnerCaps(commands={'flash'}, reset=True) @classmethod def do_add_parser(cls, parser): @@ -72,12 +72,11 @@ def do_add_parser(cls, parser): parser.add_argument('--serial-mode', default='8e1', required=False, help='serial port mode, default \'8e1\'') - parser.add_argument('--reset', default=False, required=False, action='store_true', - help='reset device at exit, default False') - parser.add_argument('--verify', default=False, required=False, action='store_true', help='verify writes, default False') + parser.set_defaults(reset=False) + @classmethod def do_create(cls, cfg, args): return Stm32flashBinaryRunner(cfg, device=args.device, action=args.action, diff --git a/scripts/west_commands/runners/uf2.py b/scripts/west_commands/runners/uf2.py index 7cb5eced390..87db248c7bf 100644 --- a/scripts/west_commands/runners/uf2.py +++ b/scripts/west_commands/runners/uf2.py @@ -49,7 +49,7 @@ def get_uf2_info_path(part) -> Path: @staticmethod def is_uf2_partition(part): try: - return ((part.fstype in ['vfat', 'FAT']) and + return ((part.fstype in ['vfat', 'FAT', 'msdos']) and UF2BinaryRunner.get_uf2_info_path(part).is_file()) except PermissionError: return False diff --git a/scripts/west_commands/sign.py b/scripts/west_commands/sign.py index 2c2692c55d2..bdf9d353685 100644 --- a/scripts/west_commands/sign.py +++ b/scripts/west_commands/sign.py @@ -502,7 +502,7 @@ def sign(self, command, build_dir, build_conf, formats): elif cache.get('RIMAGE_CONFIG_PATH'): conf_dir = pathlib.Path(cache['RIMAGE_CONFIG_PATH']) else: - conf_dir = sof_src_dir / 'rimage' / 'config' + conf_dir = sof_src_dir / 'tools' / 'rimage' / 'config' conf_path_cmd = ['-c', str(conf_dir / cmake_toml)] if conf_dir else [] @@ -517,6 +517,13 @@ def sign(self, command, build_dir, build_conf, formats): else: no_manifest = False + # Non-SOF build does not have extended manifest data for + # rimage to process, which might result in rimage error. + # So skip it when not doing SOF builds. + is_sof_build = build_conf.getboolean('CONFIG_SOF') + if not is_sof_build: + no_manifest = True + if no_manifest: extra_ri_args = [ ] else: diff --git a/scripts/west_commands/tests/conftest.py b/scripts/west_commands/tests/conftest.py index da89a2df571..0224ad95a64 100644 --- a/scripts/west_commands/tests/conftest.py +++ b/scripts/west_commands/tests/conftest.py @@ -11,6 +11,7 @@ RC_BUILD_DIR = '/test/build-dir' RC_BOARD_DIR = '/test/zephyr/boards/test-arch/test-board' RC_KERNEL_ELF = 'test-zephyr.elf' +RC_KERNEL_EXE = 'test-zephyr.exe' RC_KERNEL_HEX = 'test-zephyr.hex' RC_KERNEL_BIN = 'test-zephyr.bin' RC_GDB = 'test-none-gdb' @@ -21,7 +22,7 @@ @pytest.fixture def runner_config(): '''Fixture which provides a runners.core.RunnerConfig.''' - return RunnerConfig(RC_BUILD_DIR, RC_BOARD_DIR, RC_KERNEL_ELF, + return RunnerConfig(RC_BUILD_DIR, RC_BOARD_DIR, RC_KERNEL_ELF, RC_KERNEL_EXE, RC_KERNEL_HEX, RC_KERNEL_BIN, None, FileType.OTHER, gdb=RC_GDB, openocd=RC_OPENOCD, openocd_search=RC_OPENOCD_SEARCH) diff --git a/scripts/west_commands/tests/test_dfu_util.py b/scripts/west_commands/tests/test_dfu_util.py index 9ae4b1ce99b..a28522cd81b 100644 --- a/scripts/west_commands/tests/test_dfu_util.py +++ b/scripts/west_commands/tests/test_dfu_util.py @@ -86,7 +86,7 @@ def test_dfu_util_init(cc, req, find_device, tc, runner_config): with patch('os.path.isfile', side_effect=os_path_isfile_patch): runner.run('flash') assert find_device.called - assert req.called_with(exe) + assert req.call_args_list == [call(exe)] assert cc.call_args_list == [call(EXPECTED_COMMAND[tc])] def get_flash_address_patch(args, bcfg): @@ -141,5 +141,5 @@ def test_dfu_util_create(cc, req, gfa, find_device, tc, runner_config, tmpdir): cfg = None map_tc = (exe or DFU_UTIL, alt, cfg, img or RC_KERNEL_BIN) assert find_device.called - assert req.called_with(exe) + assert req.call_args_list == [call(exe or DFU_UTIL)] assert cc.call_args_list == [call(EXPECTED_COMMAND[map_tc])] diff --git a/scripts/west_commands/tests/test_imports.py b/scripts/west_commands/tests/test_imports.py index 774d4f7d722..274840f8cbf 100644 --- a/scripts/west_commands/tests/test_imports.py +++ b/scripts/west_commands/tests/test_imports.py @@ -35,6 +35,7 @@ def test_runner_imports(): 'nios2', 'nrfjprog', 'nrfutil', + 'nxp_s32dbg', 'openocd', 'pyocd', 'qemu', diff --git a/scripts/west_commands/tests/test_mdb.py b/scripts/west_commands/tests/test_mdb.py index a6690f4ac5a..ca07b5d1640 100644 --- a/scripts/west_commands/tests/test_mdb.py +++ b/scripts/west_commands/tests/test_mdb.py @@ -92,8 +92,8 @@ 'i': ['--jtag=test_debug', '--cores=1'], 'e': "unsupported jtag adapter test_debug" },{ - 'i': ['--jtag=digilent', '--cores=16'], - 'e': "unsupported cores 16" + 'i': ['--jtag=digilent', '--cores=13'], + 'e': "unsupported cores 13" }] TEST_HW_DEBUG_CASES = [ @@ -116,8 +116,8 @@ 'i': ['--jtag=test_debug', '--cores=1'], 'e': "unsupported jtag adapter test_debug" }, { - 'i': ['--jtag=digilent', '--cores=16'], - 'e': "unsupported cores 16" + 'i': ['--jtag=digilent', '--cores=13'], + 'e': "unsupported cores 13" }] TEST_HW_MULTICORE_CASES = [['--jtag=digilent', '--cores=2']] diff --git a/scripts/west_commands/tests/test_nxp_s32dbg.py b/scripts/west_commands/tests/test_nxp_s32dbg.py new file mode 100644 index 00000000000..a0d982cdfe8 --- /dev/null +++ b/scripts/west_commands/tests/test_nxp_s32dbg.py @@ -0,0 +1,247 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +import argparse +import os +from pathlib import Path +from unittest.mock import patch + +import pytest +from conftest import RC_KERNEL_ELF +from runners.nxp_s32dbg import NXPS32DebugProbeConfig, NXPS32DebugProbeRunner + +TEST_DEVICE = 's32dbg' +TEST_SPEED = 16000 +TEST_SERVER_PORT = 45000 +TEST_REMOTE_TIMEOUT = 30 +TEST_CORE_NAME = 'R52_0_0' +TEST_SOC_NAME = 'S32Z270' +TEST_SOC_FAMILY_NAME = 's32e2z2' +TEST_START_ALL_CORES = True +TEST_S32DS_PATH_OVERRIDE = None +TEST_TOOL_OPT = ['--test-opt-1', '--test-opt-2'] +TEST_RESET_TYPE = 'default' +TEST_RESET_DELAY = 0 + +TEST_S32DS_CMD = 's32ds' +TEST_SERVER_CMD = Path('S32DS') / 'tools' / 'S32Debugger' / 'Debugger' / 'Server' / 'gta' / 'gta' +TEST_ARM_GDB_CMD = Path('S32DS') / 'tools' / 'gdb-arm' / 'arm32-eabi' / 'bin' / 'arm-none-eabi-gdb-py' + +TEST_S32DS_PYTHON_LIB = Path('S32DS') / 'build_tools' / 'msys32' / 'mingw32' / 'lib' / 'python2.7' +TEST_S32DS_RUNTIME_ENV = { + 'PYTHONPATH': f'{TEST_S32DS_PYTHON_LIB}{os.pathsep}{TEST_S32DS_PYTHON_LIB / "site-packages"}' +} + +TEST_ALL_KWARGS = { + 'NXPS32DebugProbeConfig': { + 'conn_str': TEST_DEVICE, + 'server_port': TEST_SERVER_PORT, + 'speed': TEST_SPEED, + 'remote_timeout': TEST_REMOTE_TIMEOUT, + }, + 'NXPS32DebugProbeRunner': { + 'core_name': TEST_CORE_NAME, + 'soc_name': TEST_SOC_NAME, + 'soc_family_name': TEST_SOC_FAMILY_NAME, + 'start_all_cores': TEST_START_ALL_CORES, + 's32ds_path': TEST_S32DS_PATH_OVERRIDE, + 'tool_opt': TEST_TOOL_OPT + } +} + +TEST_ALL_PARAMS = [ + # generic + '--dev-id', TEST_DEVICE, + *[f'--tool-opt={o}' for o in TEST_TOOL_OPT], + # from runner + '--s32ds-path', TEST_S32DS_PATH_OVERRIDE, + '--core-name', TEST_CORE_NAME, + '--soc-name', TEST_SOC_NAME, + '--soc-family-name', TEST_SOC_FAMILY_NAME, + '--server-port', TEST_SERVER_PORT, + '--speed', TEST_SPEED, + '--remote-timeout', TEST_REMOTE_TIMEOUT, + '--start-all-cores', +] + +TEST_ALL_S32DBG_PY_VARS = [ + f'py _PROBE_IP = {repr(TEST_DEVICE)}', + f'py _JTAG_SPEED = {repr(TEST_SPEED)}', + f'py _GDB_SERVER_PORT = {repr(TEST_SERVER_PORT)}', + f"py _RESET_TYPE = {repr(TEST_RESET_TYPE)}", + f'py _RESET_DELAY = {repr(TEST_RESET_DELAY)}', + f'py _REMOTE_TIMEOUT = {repr(TEST_REMOTE_TIMEOUT)}', + f'py _CORE_NAME = {repr(f"{TEST_SOC_NAME}_{TEST_CORE_NAME}")}', + f'py _SOC_NAME = {repr(TEST_SOC_NAME)}', + 'py _IS_LOGGING_ENABLED = False', + 'py _FLASH_NAME = None', + 'py _SECURE_TYPE = None', + 'py _SECURE_KEY = None', +] + +DEBUGSERVER_ALL_EXPECTED_CALL = [ + str(TEST_SERVER_CMD), + '-p', str(TEST_SERVER_PORT), + *TEST_TOOL_OPT, +] + +DEBUG_ALL_EXPECTED_CALL = { + 'client': [ + str(TEST_ARM_GDB_CMD), + '-x', 'TEST_GDB_SCRIPT', + *TEST_TOOL_OPT, + ], + 'server': [ + str(TEST_SERVER_CMD), + '-p', str(TEST_SERVER_PORT), + ], + 'gdb_script': [ + *TEST_ALL_S32DBG_PY_VARS, + f'source generic_bareboard{"_all_cores" if TEST_START_ALL_CORES else ""}.py', + 'py board_init()', + 'py core_init()', + f'file {RC_KERNEL_ELF}', + 'load', + ] +} + +ATTACH_ALL_EXPECTED_CALL = { + **DEBUG_ALL_EXPECTED_CALL, + 'gdb_script': [ + *TEST_ALL_S32DBG_PY_VARS, + f'source attach.py', + 'py core_init()', + f'file {RC_KERNEL_ELF}', + ] +} + + +@pytest.fixture +def s32dbg(runner_config, tmp_path): + '''NXPS32DebugProbeRunner from constructor kwargs or command line parameters''' + def _factory(args): + # create empty files to ensure kernel binaries exist + (tmp_path / RC_KERNEL_ELF).touch() + os.chdir(tmp_path) + + runner_config_patched = fix_up_runner_config(runner_config, tmp_path) + + if isinstance(args, dict): + probe_cfg = NXPS32DebugProbeConfig(**args['NXPS32DebugProbeConfig']) + return NXPS32DebugProbeRunner(runner_config_patched, probe_cfg, + **args['NXPS32DebugProbeRunner']) + elif isinstance(args, list): + parser = argparse.ArgumentParser(allow_abbrev=False) + NXPS32DebugProbeRunner.add_parser(parser) + arg_namespace = parser.parse_args(str(x) for x in args) + return NXPS32DebugProbeRunner.create(runner_config_patched, arg_namespace) + return _factory + + +def fix_up_runner_config(runner_config, tmp_path): + to_replace = {} + + zephyr = tmp_path / 'zephyr' + zephyr.mkdir() + dotconfig = zephyr / '.config' + dotconfig.write_text('CONFIG_ARCH="arm"') + to_replace['build_dir'] = tmp_path + + return runner_config._replace(**to_replace) + + +def require_patch(program, path=None): + assert Path(program).stem == TEST_S32DS_CMD + return program + + +def s32dbg_get_script(name): + return Path(f'{name}.py') + + +@pytest.mark.parametrize('s32dbg_args,expected,osname', [ + (TEST_ALL_KWARGS, DEBUGSERVER_ALL_EXPECTED_CALL, 'Windows'), + (TEST_ALL_PARAMS, DEBUGSERVER_ALL_EXPECTED_CALL, 'Windows'), + (TEST_ALL_KWARGS, DEBUGSERVER_ALL_EXPECTED_CALL, 'Linux'), + (TEST_ALL_PARAMS, DEBUGSERVER_ALL_EXPECTED_CALL, 'Linux'), +]) +@patch('platform.system') +@patch('runners.core.ZephyrBinaryRunner.check_call') +@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch) +def test_debugserver(require, check_call, system, + s32dbg_args, expected, osname, s32dbg): + system.return_value = osname + + runner = s32dbg(s32dbg_args) + runner.run('debugserver') + + assert require.called + check_call.assert_called_once_with(expected) + + +@pytest.mark.parametrize('s32dbg_args,expected,osname', [ + (TEST_ALL_KWARGS, DEBUG_ALL_EXPECTED_CALL, 'Windows'), + (TEST_ALL_PARAMS, DEBUG_ALL_EXPECTED_CALL, 'Windows'), + (TEST_ALL_KWARGS, DEBUG_ALL_EXPECTED_CALL, 'Linux'), + (TEST_ALL_PARAMS, DEBUG_ALL_EXPECTED_CALL, 'Linux'), +]) +@patch.dict(os.environ, TEST_S32DS_RUNTIME_ENV, clear=True) +@patch('platform.system') +@patch('tempfile.TemporaryDirectory') +@patch('runners.nxp_s32dbg.NXPS32DebugProbeRunner.get_script', side_effect=s32dbg_get_script) +@patch('runners.core.ZephyrBinaryRunner.popen_ignore_int') +@patch('runners.core.ZephyrBinaryRunner.check_call') +@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch) +def test_debug(require, check_call, popen_ignore_int, get_script, temporary_dir, system, + s32dbg_args, expected, osname, s32dbg, tmp_path): + + # mock tempfile.TemporaryDirectory to return `tmp_path` and create gdb init script there + temporary_dir.return_value.__enter__.return_value = tmp_path + gdb_script = tmp_path / 'runner.nxp_s32dbg' + expected_client = [e.replace('TEST_GDB_SCRIPT', gdb_script.as_posix()) + for e in expected['client']] + + system.return_value = osname + expected_env = TEST_S32DS_RUNTIME_ENV if osname == 'Windows' else None + + runner = s32dbg(s32dbg_args) + runner.run('debug') + + assert require.called + assert gdb_script.read_text().splitlines() == expected['gdb_script'] + popen_ignore_int.assert_called_once_with(expected['server'], env=expected_env) + check_call.assert_called_once_with(expected_client, env=expected_env) + + +@pytest.mark.parametrize('s32dbg_args,expected,osname', [ + (TEST_ALL_KWARGS, ATTACH_ALL_EXPECTED_CALL, 'Windows'), + (TEST_ALL_PARAMS, ATTACH_ALL_EXPECTED_CALL, 'Windows'), + (TEST_ALL_KWARGS, ATTACH_ALL_EXPECTED_CALL, 'Linux'), + (TEST_ALL_PARAMS, ATTACH_ALL_EXPECTED_CALL, 'Linux'), +]) +@patch.dict(os.environ, TEST_S32DS_RUNTIME_ENV, clear=True) +@patch('platform.system') +@patch('tempfile.TemporaryDirectory') +@patch('runners.nxp_s32dbg.NXPS32DebugProbeRunner.get_script', side_effect=s32dbg_get_script) +@patch('runners.core.ZephyrBinaryRunner.popen_ignore_int') +@patch('runners.core.ZephyrBinaryRunner.check_call') +@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch) +def test_attach(require, check_call, popen_ignore_int, get_script, temporary_dir, system, + s32dbg_args, expected, osname, s32dbg, tmp_path): + + # mock tempfile.TemporaryDirectory to return `tmp_path` and create gdb init script there + temporary_dir.return_value.__enter__.return_value = tmp_path + gdb_script = tmp_path / 'runner.nxp_s32dbg' + expected_client = [e.replace('TEST_GDB_SCRIPT', gdb_script.as_posix()) + for e in expected['client']] + + system.return_value = osname + expected_env = TEST_S32DS_RUNTIME_ENV if osname == 'Windows' else None + + runner = s32dbg(s32dbg_args) + runner.run('attach') + + assert require.called + assert gdb_script.read_text().splitlines() == expected['gdb_script'] + popen_ignore_int.assert_called_once_with(expected['server'], env=expected_env) + check_call.assert_called_once_with(expected_client, env=expected_env) diff --git a/scripts/zephyr_module.py b/scripts/zephyr_module.py index db58bcea23c..ab27eaa5706 100755 --- a/scripts/zephyr_module.py +++ b/scripts/zephyr_module.py @@ -350,7 +350,10 @@ def process_kconfig(module, meta): return kconfig_snippet(meta, module_path, Path(kconfig_file), blobs=taint_blobs) else: - return "" + name_sanitized = meta['name-sanitized'] + return (f'config ZEPHYR_{name_sanitized.upper()}_MODULE\n' + f' bool\n' + f' default y\n') def process_sysbuildkconfig(module, meta): diff --git a/share/sysbuild/CMakeLists.txt b/share/sysbuild/CMakeLists.txt index 7bbfe138760..8a15da9cef5 100644 --- a/share/sysbuild/CMakeLists.txt +++ b/share/sysbuild/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2023 Nordic Semiconductor +# Copyright (c) 2023 Nordic Semiconductor # # SPDX-License-Identifier: Apache-2.0 @@ -18,7 +18,10 @@ set(APP_DIR ${APP_DIR} CACHE PATH "Main Application Source Directory") list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake/modules) # List of Zephyr and sysbuild CMake modules we need for sysbuild. # Note: sysbuild_kconfig will internally load kconfig CMake module. -set(zephyr_modules extensions sysbuild_extensions python west root zephyr_module boards shields sysbuild_kconfig) +set(zephyr_modules extensions + sysbuild_extensions python west root zephyr_module boards shields + sysbuild_kconfig native_simulator_sb_extensions + ) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE} COMPONENTS ${zephyr_modules}) diff --git a/share/sysbuild/cmake/modules/native_simulator_sb_extensions.cmake b/share/sysbuild/cmake/modules/native_simulator_sb_extensions.cmake new file mode 100644 index 00000000000..3d888d1775e --- /dev/null +++ b/share/sysbuild/cmake/modules/native_simulator_sb_extensions.cmake @@ -0,0 +1,62 @@ +# Copyright (c) 2023 Nordic Semiconductor +# +# SPDX-License-Identifier: Apache-2.0 + +# Usage: +# native_simulator_set_final_executable() +# +# When building for a native_simulator based target (including bsim targets), +# this function adds an extra build target which will copy the executable produced by +# `` to the top level, as zephyr/zephyr.exe +# +# This final image is expected to have been set to assemble other dependent images into +# itself if necessary, by calling native_simulator_set_child_images() +# This will allow other tools, like twister, or the bsim test scripts, as well as users to find +# this final executable in the same place as for non-sysbuild builds. +# +function(native_simulator_set_final_executable final_image) + if(("${BOARD}" MATCHES "native") OR ("${BOARD}" MATCHES "bsim")) + add_custom_target(final_executable + ALL + COMMAND + ${CMAKE_COMMAND} -E copy + ${CMAKE_BINARY_DIR}/${final_image}/zephyr/zephyr.exe + ${CMAKE_BINARY_DIR}/zephyr/zephyr.exe + DEPENDS ${final_image} + ) + endif() +endfunction() + +# Usage: +# native_simulator_set_child_images( ) +# +# When building for a native_simulator based target (including bsim targets), +# this function sets a `` as dependencies of `` +# and configures the final image to assemble the child images into its final executable. +# +function(native_simulator_set_child_images final_image child_image) + if(("${BOARD}" MATCHES "native") OR ("${BOARD}" MATCHES "bsim")) + add_dependencies(${final_image} ${child_image}) + + set(CHILD_LIBRARY_PATH ${CMAKE_BINARY_DIR}/${child_image}/zephyr/zephyr.elf) + set_property(TARGET ${final_image} APPEND_STRING PROPERTY CONFIG + "CONFIG_NATIVE_SIMULATOR_EXTRA_IMAGE_PATHS=\"${CHILD_LIBRARY_PATH}\"\n" + ) + endif() +endfunction() + +# Usage: +# native_simulator_set_primary_mcu_index( [ ...]) +# +# Propagate the SB_CONFIG_NATIVE_SIMULATOR_PRIMARY_MCU_INDEX setting, +# if it is set, to each given image CONFIG_NATIVE_SIMULATOR_PRIMARY_MCU_INDEX +# +function(native_simulator_set_primary_mcu_index) + if (NOT ("${SB_CONFIG_NATIVE_SIMULATOR_PRIMARY_MCU_INDEX}" STREQUAL "")) + foreach(arg IN LISTS ARGV) + set_property(TARGET ${arg} APPEND_STRING PROPERTY CONFIG + "CONFIG_NATIVE_SIMULATOR_PRIMARY_MCU_INDEX=${SB_CONFIG_NATIVE_SIMULATOR_PRIMARY_MCU_INDEX}\n" + ) + endforeach() + endif() +endfunction() diff --git a/share/sysbuild/cmake/modules/sysbuild_extensions.cmake b/share/sysbuild/cmake/modules/sysbuild_extensions.cmake index ac8bac25f8c..9250c209c50 100644 --- a/share/sysbuild/cmake/modules/sysbuild_extensions.cmake +++ b/share/sysbuild/cmake/modules/sysbuild_extensions.cmake @@ -174,8 +174,8 @@ function(sysbuild_cache) RESULT_VARIABLE compare_res ) if(NOT compare_res EQUAL 0) - file(COPY_FILE ${${SB_CACHE_APPLICATION}_CACHE_FILE}.tmp - ${${SB_CACHE_APPLICATION}_CACHE_FILE} + zephyr_file_copy(${${SB_CACHE_APPLICATION}_CACHE_FILE}.tmp + ${${SB_CACHE_APPLICATION}_CACHE_FILE} ) ExternalProject_Get_Property(${SB_CACHE_APPLICATION} BINARY_DIR) file(TOUCH_NOCREATE ${BINARY_DIR}/CMakeCache.txt) diff --git a/share/sysbuild/cmake/modules/sysbuild_kconfig.cmake b/share/sysbuild/cmake/modules/sysbuild_kconfig.cmake index 830ad326fd2..12ab32e55c2 100644 --- a/share/sysbuild/cmake/modules/sysbuild_kconfig.cmake +++ b/share/sysbuild/cmake/modules/sysbuild_kconfig.cmake @@ -24,22 +24,23 @@ else() # SYSBuild dedicated configuration file. endif() -if(DEFINED SB_CONF_FILE AND NOT IS_ABSOLUTE SB_CONF_FILE) - cmake_path(ABSOLUTE_PATH SB_CONF_FILE BASE_DIRECTORY ${APP_DIR}) -endif() - -if(DEFINED SB_OVERLAY_CONFIG AND NOT IS_ABSOLUTE SB_OVERLAY_CONFIG) - cmake_path(ABSOLUTE_PATH SB_OVERLAY_CONFIG BASE_DIRECTORY ${APP_DIR}) -endif() - -if(DEFINED SB_EXTRA_CONF_FILE AND NOT IS_ABSOLUTE SB_EXTRA_CONF_FILE) - cmake_path(ABSOLUTE_PATH SB_EXTRA_CONF_FILE BASE_DIRECTORY ${APP_DIR}) -endif() - if(NOT DEFINED SB_EXTRA_CONF_FILE AND DEFINED SB_OVERLAY_CONFIG) set(SB_EXTRA_CONF_FILE ${SB_OVERLAY_CONFIG}) endif() +# Let SB_CONF_FILE and SB_EXTRA_CONF_FILE be relative to APP_DIR. +# Either variable can be a list of paths, so we must make all of them absolute. +foreach(conf_file_var SB_CONF_FILE SB_EXTRA_CONF_FILE) + if(DEFINED ${conf_file_var}) + string(CONFIGURE "${${conf_file_var}}" conf_file_expanded) + set(${conf_file_var} "") + foreach(conf_file ${conf_file_expanded}) + cmake_path(ABSOLUTE_PATH conf_file BASE_DIRECTORY ${APP_DIR}) + list(APPEND ${conf_file_var} ${conf_file}) + endforeach() + endif() +endforeach() + if(DEFINED SB_CONF_FILE AND NOT DEFINED CACHE{SB_CONF_FILE}) # We only want to set this in cache it has been defined and is not already there. set(SB_CONF_FILE ${SB_CONF_FILE} CACHE STRING "If desired, you can build the application with \ diff --git a/snippets/xen_dom0/README.rst b/snippets/xen_dom0/README.rst new file mode 100644 index 00000000000..a871d9f4f51 --- /dev/null +++ b/snippets/xen_dom0/README.rst @@ -0,0 +1,51 @@ +.. _xen_dom0: + +Xen Dom0: universal snippet for XEN control domain +################################################## + +Overview +******** + +This snippet allows user to build Zephyr as a Xen initial domain (Dom0). The feature +is implemented as configuration snippet to allow support for any compatible platform. + +How to add support of a new board +********************************* + +* add board dts overlay to this snippet which deletes/adds memory and deletes UART nodes; +* add correct memory and hypervisor nodes, based on regions Xen picked for Domain-0 on your setup. + +Programming +*********** + +Correct snippet designation for Xen must +be entered when you invoke ``west build``. +For example: + +.. code-block:: console + + west build -b qemu_cortex_a53 -S xen_dom0 samples/synchronization + +QEMU example with Xen +*********************** + +Overlay for qemu_cortex_a53 board, that is present in `board/` directory of this snippet is QEMU +Xen control domain example. To run such setup, you need to: + +* fetch and build Xen (e.g. RELEASE-4.17.0) for arm64 platform +* take and compile sample device tree from `example/` directory +* build your Zephyr sample/application with `xen_dom0` snippet and start it as Xen control domain + +For starting you can use QEMU from Zephyr SDK by following command: + +.. code-block:: console + + /sysroots/x86_64-pokysdk-linux/usr/bin/qemu-system-aarch64 -cpu cortex-a53 \ + -m 6G -nographic -machine virt,gic-version=3,virtualization=true -chardev stdio,id=con,mux=on \ + -serial chardev:con -mon chardev=con,mode=readline -pidfile qemu.pid \ + -device loader,file=/zephyr.bin,addr=0x40600000 \ + -dtb /xen.dtb -kernel /xen + +This will start you a Xen hypervisor with your application as Xen control domain. To make it usable, +you can add `zephyr-xenlib` by Xen-troops library to your project. It'll provide basic domain +management functionalities - domain creation and configuration. diff --git a/snippets/xen_dom0/boards/qemu_cortex_a53.overlay b/snippets/xen_dom0/boards/qemu_cortex_a53.overlay new file mode 100644 index 00000000000..8d841a2be6d --- /dev/null +++ b/snippets/xen_dom0/boards/qemu_cortex_a53.overlay @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/delete-node/ &sram0; + +&uart0 { + /* Xen consoleio will be used */ + status = "disabled"; +}; + +/ { + /* + * This node may differs on different setups, please check + * following line in Xen boot log to set it right: + * (XEN) Grant table range: 0x00000040200000-0x00000040240000 + * + * Xen passes actual values for setup in domain device tree, but Zephyr + * is not capable to parse and handle it in runtime. + */ + hypervisor: hypervisor@40200000 { + compatible = "xen,xen"; + reg = <0x0 0x40200000 0x0 0x40000>; + interrupts = ; + interrupt-parent = <&gic>; + status = "okay"; + }; + + /* + * This node may differs on different setups, because Xen picks + * region for Domain-0 for every specific configuration. You can + * start Xen for your platform and check following log: + * (XEN) Allocating 1:1 mappings for dom0: + * (XEN) BANK[0] 0x00000058000000-0x00000060000000 (128MB) + * + * Xen passes actual values for setup in domain device tree, but Zephyr + * is not capable to parse and handle it in runtime. + */ + soc { + sram0: memory@58000000 { + device_type = "mmio-sram"; + reg = <0x00 0x58000000 0x00 DT_SIZE_M(128)>; + }; + }; +}; diff --git a/snippets/xen_dom0/boards/rcar_h3ulcb_ca57.overlay b/snippets/xen_dom0/boards/rcar_h3ulcb_ca57.overlay new file mode 100644 index 00000000000..9af28690c2c --- /dev/null +++ b/snippets/xen_dom0/boards/rcar_h3ulcb_ca57.overlay @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2023 EPAM Systems. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/delete-node/ &ram; +/delete-node/ &scif2; + +/ { + /* + * This node may differs on different setups, please check + * following line in Xen boot log to set it right: + * (XEN) Grant table range: 0x00000088080000-0x000000880c0000 + * + * Xen passes actual values for setup in domain device tree, but Zephyr + * is not capable to parse and handle it in runtime. + */ + hypervisor: hypervisor@88080000 { + compatible = "xen,xen"; + reg = <0x0 0x88080000 0x0 0x40000>; + interrupts = ; + interrupt-parent = <&gic>; + status = "okay"; + }; + + /* + * This node may differs on different setups, because Xen picks + * region for Domain-0 for every specific configuration. You can + * start Xen for your platform and check following log: + * (XEN) Allocating 1:1 mappings for dom0: + * (XEN) BANK[0] 0x00000060000000-0x00000070000000 (256MB) + * + * Xen passes actual values for setup in domain device tree, but Zephyr + * is not capable to parse and handle it in runtime. + */ + ram: memory@60000000 { + device_type = "mmio-sram"; + reg = <0x00 0x60000000 0x00 DT_SIZE_M(256)>; + }; +}; diff --git a/snippets/xen_dom0/boards/rcar_salvator_xs_m3.overlay b/snippets/xen_dom0/boards/rcar_salvator_xs_m3.overlay new file mode 100644 index 00000000000..9af28690c2c --- /dev/null +++ b/snippets/xen_dom0/boards/rcar_salvator_xs_m3.overlay @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2023 EPAM Systems. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/delete-node/ &ram; +/delete-node/ &scif2; + +/ { + /* + * This node may differs on different setups, please check + * following line in Xen boot log to set it right: + * (XEN) Grant table range: 0x00000088080000-0x000000880c0000 + * + * Xen passes actual values for setup in domain device tree, but Zephyr + * is not capable to parse and handle it in runtime. + */ + hypervisor: hypervisor@88080000 { + compatible = "xen,xen"; + reg = <0x0 0x88080000 0x0 0x40000>; + interrupts = ; + interrupt-parent = <&gic>; + status = "okay"; + }; + + /* + * This node may differs on different setups, because Xen picks + * region for Domain-0 for every specific configuration. You can + * start Xen for your platform and check following log: + * (XEN) Allocating 1:1 mappings for dom0: + * (XEN) BANK[0] 0x00000060000000-0x00000070000000 (256MB) + * + * Xen passes actual values for setup in domain device tree, but Zephyr + * is not capable to parse and handle it in runtime. + */ + ram: memory@60000000 { + device_type = "mmio-sram"; + reg = <0x00 0x60000000 0x00 DT_SIZE_M(256)>; + }; +}; diff --git a/snippets/xen_dom0/snippet.yml b/snippets/xen_dom0/snippet.yml new file mode 100644 index 00000000000..cb6fddeaccd --- /dev/null +++ b/snippets/xen_dom0/snippet.yml @@ -0,0 +1,15 @@ +name: xen_dom0 +append: + EXTRA_DTC_OVERLAY_FILE: xen_dom0.overlay + EXTRA_CONF_FILE: xen_dom0.conf + +boards: + qemu_cortex_a53: + append: + EXTRA_DTC_OVERLAY_FILE: boards/qemu_cortex_a53.overlay + rcar_h3ulcb_ca57: + append: + EXTRA_DTC_OVERLAY_FILE: boards/rcar_h3ulcb_ca57.overlay + rcar_salvator_xs_m3: + append: + EXTRA_DTC_OVERLAY_FILE: boards/rcar_salvator_xs_m3.overlay diff --git a/snippets/xen_dom0/xen_dom0.conf b/snippets/xen_dom0/xen_dom0.conf new file mode 100644 index 00000000000..c5cb5d24aa3 --- /dev/null +++ b/snippets/xen_dom0/xen_dom0.conf @@ -0,0 +1 @@ +CONFIG_XEN_DOM0=y diff --git a/snippets/xen_dom0/xen_dom0.overlay b/snippets/xen_dom0/xen_dom0.overlay new file mode 100644 index 00000000000..98fe1e39d67 --- /dev/null +++ b/snippets/xen_dom0/xen_dom0.overlay @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2023 EPAM Systems. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + chosen { + zephyr,console = &xen_consoleio_hvc; + zephyr,shell-uart = &xen_consoleio_hvc; + }; + + psci { + method = "hvc"; + }; + + xen_consoleio_hvc: hvc { + compatible = "xen,uart_hvc"; + status = "okay"; + }; +}; diff --git a/soc/arc/snps_arc_hsdk/CMakeLists.txt b/soc/arc/snps_arc_hsdk/CMakeLists.txt index 1d6a7c6827f..c20f4167057 100644 --- a/soc/arc/snps_arc_hsdk/CMakeLists.txt +++ b/soc/arc/snps_arc_hsdk/CMakeLists.txt @@ -18,3 +18,5 @@ else() zephyr_ld_options(-Hlib=hs38_full) endif() + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/arc/snps_arc_hsdk4xd/CMakeLists.txt b/soc/arc/snps_arc_hsdk4xd/CMakeLists.txt index 0e6c51029af..0c13259ca2b 100644 --- a/soc/arc/snps_arc_hsdk4xd/CMakeLists.txt +++ b/soc/arc/snps_arc_hsdk4xd/CMakeLists.txt @@ -14,3 +14,5 @@ else() zephyr_ld_options(-Hlib=hs48_slc_full) endif() + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/arc/snps_arc_iot/CMakeLists.txt b/soc/arc/snps_arc_iot/CMakeLists.txt index 4c478bc785c..5a28fe228d8 100644 --- a/soc/arc/snps_arc_iot/CMakeLists.txt +++ b/soc/arc/snps_arc_iot/CMakeLists.txt @@ -6,3 +6,5 @@ zephyr_sources( soc.c sysconf.c ) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/arc/snps_arc_iot/Kconfig.defconfig b/soc/arc/snps_arc_iot/Kconfig.defconfig index 8abaa3382d5..202697a7cf9 100644 --- a/soc/arc/snps_arc_iot/Kconfig.defconfig +++ b/soc/arc/snps_arc_iot/Kconfig.defconfig @@ -34,7 +34,4 @@ config HARVARD config ARC_FIRQ default y -config UART_NS16550_ACCESS_IOPORT - default y - endif # ARC_IOT diff --git a/soc/arc/snps_emsdp/CMakeLists.txt b/soc/arc/snps_emsdp/CMakeLists.txt index 7a4ba9674fd..04466b802c0 100644 --- a/soc/arc/snps_emsdp/CMakeLists.txt +++ b/soc/arc/snps_emsdp/CMakeLists.txt @@ -18,3 +18,5 @@ elseif(CONFIG_SOC_EMSDP_EM11D) zephyr_compile_options(-mmpy-option=6) zephyr_compile_options_ifdef(CONFIG_FPU -mfpu=fpuda_all) endif() + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/arc/snps_emsk/CMakeLists.txt b/soc/arc/snps_emsk/CMakeLists.txt index 53b0f92a9c8..8e8ef5865ca 100644 --- a/soc/arc/snps_emsk/CMakeLists.txt +++ b/soc/arc/snps_emsk/CMakeLists.txt @@ -8,3 +8,5 @@ zephyr_compile_options_ifdef(CONFIG_FPU -mfpu=fpuda_all) endif() zephyr_sources(soc_config.c) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/arc/snps_nsim/CMakeLists.txt b/soc/arc/snps_nsim/CMakeLists.txt index 965bf79968e..094aed08cee 100644 --- a/soc/arc/snps_nsim/CMakeLists.txt +++ b/soc/arc/snps_nsim/CMakeLists.txt @@ -105,3 +105,5 @@ else() zephyr_ld_option_ifdef(CONFIG_SOC_NSIM_HS6X_SMP -Hlib=hs68_full_zephyr) endif() + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/arc/snps_qemu/CMakeLists.txt b/soc/arc/snps_qemu/CMakeLists.txt index c77f0003c4c..a05efdfa22d 100644 --- a/soc/arc/snps_qemu/CMakeLists.txt +++ b/soc/arc/snps_qemu/CMakeLists.txt @@ -19,3 +19,5 @@ else() endif() endif() + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/CMakeLists.txt b/soc/arm/CMakeLists.txt index f854c3b7d1e..b826da926ca 100644 --- a/soc/arm/CMakeLists.txt +++ b/soc/arm/CMakeLists.txt @@ -1,10 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 -add_subdirectory_ifdef(CONFIG_CPU_CORTEX_M common/cortex_m) - if(SOC_FAMILY) add_subdirectory(${SOC_FAMILY}) else() add_subdirectory(${SOC_NAME}) endif() - diff --git a/soc/arm/ambiq/apollo4x/CMakeLists.txt b/soc/arm/ambiq/apollo4x/CMakeLists.txt index 2d96101cb0b..a82fe0a51f3 100644 --- a/soc/arm/ambiq/apollo4x/CMakeLists.txt +++ b/soc/arm/ambiq/apollo4x/CMakeLists.txt @@ -5,3 +5,5 @@ zephyr_sources(soc.c) zephyr_include_directories(${ZEPHYR_BASE}/soc/arm/common/cortex_m) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/ambiq/apollo4x/Kconfig.defconfig.apollo4p_blue b/soc/arm/ambiq/apollo4x/Kconfig.defconfig.apollo4p_blue new file mode 100644 index 00000000000..2d791dd4a46 --- /dev/null +++ b/soc/arm/ambiq/apollo4x/Kconfig.defconfig.apollo4p_blue @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2023 Ambiq Micro Inc. + +if SOC_APOLLO4P_BLUE + +config NUM_IRQS + default 83 + +DT_NODE_SRAM := /memory@0 + +config SRAM_NC_SIZE + default $(dt_node_reg_size_int,$(DT_NODE_SRAM),1,K) + +config SRAM_NC_BASE_ADDRESS + default $(dt_node_reg_addr_hex,$(DT_NODE_SRAM),1) + +endif # SOC_APOLLO4P_BLUE diff --git a/soc/arm/ambiq/apollo4x/Kconfig.soc b/soc/arm/ambiq/apollo4x/Kconfig.soc index 215367c4855..a9b5cf00824 100644 --- a/soc/arm/ambiq/apollo4x/Kconfig.soc +++ b/soc/arm/ambiq/apollo4x/Kconfig.soc @@ -1,6 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 # # Copyright (c) 2023 Antmicro +# Copyright (c) 2023 Ambiq Micro Inc. choice prompt "Ambiq Apollo4X Selection" @@ -9,4 +10,7 @@ choice config SOC_APOLLO4P bool "Apollo4P" +config SOC_APOLLO4P_BLUE + bool "Apollo4 Blue Plus" + endchoice diff --git a/soc/arm/ambiq/apollo4x/linker.ld b/soc/arm/ambiq/apollo4x/linker.ld deleted file mode 100644 index 9c1ab8ff301..00000000000 --- a/soc/arm/ambiq/apollo4x/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2023 Antmicro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/ambiq/apollo4x/soc.c b/soc/arm/ambiq/apollo4x/soc.c index 30288ad12c3..225f5013441 100644 --- a/soc/arm/ambiq/apollo4x/soc.c +++ b/soc/arm/ambiq/apollo4x/soc.c @@ -10,7 +10,14 @@ static int arm_apollo4_init(void) { + + /* Initialize for low power in the power control block */ am_hal_pwrctrl_low_power_init(); + + /* Enable SIMOBUCK for the Apollo4 Family */ + am_hal_pwrctrl_control(AM_HAL_PWRCTRL_CONTROL_SIMOBUCK_INIT, 0); + + /* Disable the RTC. */ am_hal_rtc_osc_disable(); return 0; diff --git a/soc/arm/arm/beetle/CMakeLists.txt b/soc/arm/arm/beetle/CMakeLists.txt index 3fd95157dfc..e911f5faab5 100644 --- a/soc/arm/arm/beetle/CMakeLists.txt +++ b/soc/arm/arm/beetle/CMakeLists.txt @@ -4,3 +4,5 @@ zephyr_sources( soc.c power.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/arm/beetle/linker.ld b/soc/arm/arm/beetle/linker.ld deleted file mode 100644 index 96ec397da78..00000000000 --- a/soc/arm/arm/beetle/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/arm/designstart/CMakeLists.txt b/soc/arm/arm/designstart/CMakeLists.txt index 9881313609a..5d2598e239b 100644 --- a/soc/arm/arm/designstart/CMakeLists.txt +++ b/soc/arm/arm/designstart/CMakeLists.txt @@ -1 +1,3 @@ # SPDX-License-Identifier: Apache-2.0 + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/arm/designstart/linker.ld b/soc/arm/arm/designstart/linker.ld deleted file mode 100644 index 96ec397da78..00000000000 --- a/soc/arm/arm/designstart/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/arm/fvp_aemv8r_aarch32/CMakeLists.txt b/soc/arm/arm/fvp_aemv8r_aarch32/CMakeLists.txt index 01b4ede7dfa..d9264843fae 100644 --- a/soc/arm/arm/fvp_aemv8r_aarch32/CMakeLists.txt +++ b/soc/arm/arm/fvp_aemv8r_aarch32/CMakeLists.txt @@ -3,3 +3,5 @@ zephyr_library_sources_ifdef(CONFIG_ARM_MPU arm_mpu_regions.c) zephyr_library_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/arm/fvp_aemv8r_aarch32/Kconfig.soc b/soc/arm/arm/fvp_aemv8r_aarch32/Kconfig.soc index a7f2131e065..6993cfe715a 100644 --- a/soc/arm/arm/fvp_aemv8r_aarch32/Kconfig.soc +++ b/soc/arm/arm/fvp_aemv8r_aarch32/Kconfig.soc @@ -10,7 +10,7 @@ config SOC_FVP_AEMV8R_AARCH32 select CPU_CORTEX_R52 select CPU_HAS_ARM_MPU select CPU_HAS_MPU - select VFP_DP_D32_FP16_FMAC + select VFP_DP_D32_FP16_FMAC if !USE_SWITCH select GIC_V3 select GIC_SINGLE_SECURITY_STATE select PLATFORM_SPECIFIC_INIT diff --git a/soc/arm/arm/fvp_aemv8r_aarch32/arm_mpu_regions.c b/soc/arm/arm/fvp_aemv8r_aarch32/arm_mpu_regions.c index e756a81bccc..b1c91d15d9a 100644 --- a/soc/arm/arm/fvp_aemv8r_aarch32/arm_mpu_regions.c +++ b/soc/arm/arm/fvp_aemv8r_aarch32/arm_mpu_regions.c @@ -5,7 +5,7 @@ #include #include -#include +#include #define DEVICE_REGION_START 0x80000000UL #define DEVICE_REGION_END 0xFFFFFFFFUL diff --git a/soc/arm/arm/fvp_aemv8r_aarch32/linker.ld b/soc/arm/arm/fvp_aemv8r_aarch32/linker.ld deleted file mode 100644 index 924b5ab62d4..00000000000 --- a/soc/arm/arm/fvp_aemv8r_aarch32/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* - * linker.ld - Linker command/script file - * - * Copyright (c) 2022 IoT.bzh - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/arm/mps2/CMakeLists.txt b/soc/arm/arm/mps2/CMakeLists.txt index 332416ba43b..7424bb9f7b9 100644 --- a/soc/arm/arm/mps2/CMakeLists.txt +++ b/soc/arm/arm/mps2/CMakeLists.txt @@ -3,3 +3,5 @@ zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/arm/mps2/linker.ld b/soc/arm/arm/mps2/linker.ld deleted file mode 100644 index 96ec397da78..00000000000 --- a/soc/arm/arm/mps2/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/arm/mps3/CMakeLists.txt b/soc/arm/arm/mps3/CMakeLists.txt index a2566f7c530..d82e1bc62c5 100644 --- a/soc/arm/arm/mps3/CMakeLists.txt +++ b/soc/arm/arm/mps3/CMakeLists.txt @@ -4,3 +4,5 @@ zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/arm/mps3/linker.ld b/soc/arm/arm/mps3/linker.ld deleted file mode 100644 index 96ec397da78..00000000000 --- a/soc/arm/arm/mps3/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/arm/musca_b1/CMakeLists.txt b/soc/arm/arm/musca_b1/CMakeLists.txt index ae3f7d6c3be..9c8a3b15eb2 100644 --- a/soc/arm/arm/musca_b1/CMakeLists.txt +++ b/soc/arm/arm/musca_b1/CMakeLists.txt @@ -7,3 +7,5 @@ zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/arm/musca_b1/linker.ld b/soc/arm/arm/musca_b1/linker.ld deleted file mode 100644 index 96ec397da78..00000000000 --- a/soc/arm/arm/musca_b1/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/arm/musca_s1/CMakeLists.txt b/soc/arm/arm/musca_s1/CMakeLists.txt index 2ceba388601..51df24c9b73 100644 --- a/soc/arm/arm/musca_s1/CMakeLists.txt +++ b/soc/arm/arm/musca_s1/CMakeLists.txt @@ -3,3 +3,5 @@ # # SPDX-License-Identifier: Apache-2.0 # + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/arm/musca_s1/linker.ld b/soc/arm/arm/musca_s1/linker.ld deleted file mode 100644 index 96ec397da78..00000000000 --- a/soc/arm/arm/musca_s1/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/aspeed/aspeed_util.h b/soc/arm/aspeed/aspeed_util.h index 27a4a504e78..c1b656aeaee 100644 --- a/soc/arm/aspeed/aspeed_util.h +++ b/soc/arm/aspeed/aspeed_util.h @@ -7,7 +7,7 @@ #define ZEPHYR_SOC_ARM_ASPEED_UTIL_H_ #include #include -#include +#include /* gcc.h doesn't define __section but checkpatch.pl will complain for this. so * temporarily add a macro here. diff --git a/soc/arm/aspeed/ast10x0/CMakeLists.txt b/soc/arm/aspeed/ast10x0/CMakeLists.txt index fc5628a425e..0d73ca4ba34 100644 --- a/soc/arm/aspeed/ast10x0/CMakeLists.txt +++ b/soc/arm/aspeed/ast10x0/CMakeLists.txt @@ -13,3 +13,5 @@ set_property(GLOBAL APPEND PROPERTY extra_post_build_commands ${PROJECT_BINARY_DIR}/${CONFIG_KERNEL_BIN_NAME}.bin ${PROJECT_BINARY_DIR}/uart_${CONFIG_KERNEL_BIN_NAME}.bin ) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/aspeed/ast10x0/linker.ld b/soc/arm/aspeed/ast10x0/linker.ld index ef034e1f70e..fec4d373a82 100644 --- a/soc/arm/aspeed/ast10x0/linker.ld +++ b/soc/arm/aspeed/ast10x0/linker.ld @@ -7,4 +7,4 @@ MEMORY { SRAM_NC (wx) : ORIGIN = CONFIG_SRAM_NC_BASE_ADDRESS, LENGTH = CONFIG_SRAM_NC_SIZE * 1024 } -#include +#include diff --git a/soc/arm/atmel_sam/common/CMakeLists.txt b/soc/arm/atmel_sam/common/CMakeLists.txt index 7b57af36217..2d5a6c35a33 100644 --- a/soc/arm/atmel_sam/common/CMakeLists.txt +++ b/soc/arm/atmel_sam/common/CMakeLists.txt @@ -3,6 +3,9 @@ zephyr_include_directories(.) zephyr_library_sources_ifndef(CONFIG_SOC_SERIES_SAM4L soc_pmc.c) zephyr_library_sources_ifndef(CONFIG_SOC_SERIES_SAM4L soc_gpio.c) +zephyr_library_sources_ifndef(CONFIG_SOC_SERIES_SAM4L soc_supc.c) +zephyr_library_sources_ifndef(CONFIG_SOC_SERIES_SAM4L soc_poweroff.c) zephyr_library_sources_ifdef(CONFIG_SOC_SERIES_SAM4L soc_sam4l_pm.c) zephyr_library_sources_ifdef(CONFIG_SOC_SERIES_SAM4L soc_sam4l_gpio.c) +zephyr_library_sources_ifdef(CONFIG_SOC_SERIES_SAM4L soc_sam4l_poweroff.c) diff --git a/soc/arm/atmel_sam/common/soc_poweroff.c b/soc/arm/atmel_sam/common/soc_poweroff.c new file mode 100644 index 00000000000..7cc17f02018 --- /dev/null +++ b/soc/arm/atmel_sam/common/soc_poweroff.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 Bjarki Arge Andreasen + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* + * Poweroff will make the chip enter the backup low-power mode, which + * achieves the lowest possible power consumption. Wakeup from this mode + * requires enabling a wakeup source or input, or power cycling the device. + */ + +static void soc_core_sleepdeep_enable(void) +{ + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; +} + +static void soc_core_sleepdeep_wait(void) +{ + __WFE(); + __WFI(); +} + +void z_sys_poweroff(void) +{ + soc_core_sleepdeep_enable(); + soc_supc_core_voltage_regulator_off(); + soc_core_sleepdeep_wait(); + + CODE_UNREACHABLE; +} diff --git a/soc/arm/atmel_sam/common/soc_sam4l_poweroff.c b/soc/arm/atmel_sam/common/soc_sam4l_poweroff.c new file mode 100644 index 00000000000..ecadfe2d8f0 --- /dev/null +++ b/soc/arm/atmel_sam/common/soc_sam4l_poweroff.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 Bjarki Arge Andreasen + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* + * Poweroff will make the chip enter the backup low-power mode, which + * achieves the lowest possible power consumption. Wakeup from this mode + * requires enabling a wakeup source or input, or power cycling the device. + */ + +static void soc_core_sleepdeep_enable(void) +{ + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; +} + +static void soc_core_sleepdeep_wait(void) +{ + __WFE(); + __WFI(); +} + +void z_sys_poweroff(void) +{ + soc_core_sleepdeep_enable(); + BPM->PMCON |= BPM_PMCON_BKUP; + soc_core_sleepdeep_wait(); + + CODE_UNREACHABLE; +} diff --git a/soc/arm/atmel_sam/common/soc_supc.c b/soc/arm/atmel_sam/common/soc_supc.c new file mode 100644 index 00000000000..cf6ce80ab2c --- /dev/null +++ b/soc/arm/atmel_sam/common/soc_supc.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Bjarki Arge Andreasen + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#define SOC_SUPC_WAKEUP_SOURCE_IDS (3) + +void soc_supc_core_voltage_regulator_off(void) +{ + SUPC->SUPC_CR = SUPC_CR_KEY_PASSWD | SUPC_CR_VROFF_STOP_VREG; +} + +void soc_supc_slow_clock_select_crystal_osc(void) +{ + SUPC->SUPC_CR = SUPC_CR_KEY_PASSWD | SUPC_CR_XTALSEL_CRYSTAL_SEL; + + /* Wait for oscillator to be stabilized. */ + while (!(SUPC->SUPC_SR & SUPC_SR_OSCSEL)) { + } +} + +void soc_supc_enable_wakeup_source(uint32_t wakeup_source_id) +{ + __ASSERT(wakeup_source_id <= SOC_SUPC_WAKEUP_SOURCE_IDS, + "Wakeup source channel is invalid"); + + SUPC->SUPC_WUMR |= 1 << wakeup_source_id; +} diff --git a/soc/arm/atmel_sam/common/soc_supc.h b/soc/arm/atmel_sam/common/soc_supc.h new file mode 100644 index 00000000000..b925eb5f18c --- /dev/null +++ b/soc/arm/atmel_sam/common/soc_supc.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 Bjarki Arge Andreasen + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _ATMEL_SAM_SOC_SUPC_H_ +#define _ATMEL_SAM_SOC_SUPC_H_ + +#include + +/** + * @brief Enable the clock of specified peripheral module. + */ +void soc_supc_core_voltage_regulator_off(void); + +/** + * @brief Switch slow clock source to external crystal oscillator + */ +void soc_supc_slow_clock_select_crystal_osc(void); + +/** + * @brief Enable wakeup source + */ +void soc_supc_enable_wakeup_source(uint32_t wakeup_source_id); + +#endif /* _ATMEL_SAM_SOC_SUPC_H_ */ diff --git a/soc/arm/atmel_sam/sam3x/CMakeLists.txt b/soc/arm/atmel_sam/sam3x/CMakeLists.txt index 332416ba43b..7424bb9f7b9 100644 --- a/soc/arm/atmel_sam/sam3x/CMakeLists.txt +++ b/soc/arm/atmel_sam/sam3x/CMakeLists.txt @@ -3,3 +3,5 @@ zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/atmel_sam/sam3x/Kconfig.series b/soc/arm/atmel_sam/sam3x/Kconfig.series index 911eab6b1cc..08a3781b6d3 100644 --- a/soc/arm/atmel_sam/sam3x/Kconfig.series +++ b/soc/arm/atmel_sam/sam3x/Kconfig.series @@ -15,6 +15,7 @@ config SOC_SERIES_SAM3X select SOC_FAMILY_SAM select PLATFORM_SPECIFIC_INIT select ASF + select HAS_POWEROFF help Enable support for Atmel SAM3X Cortex-M3 microcontrollers. Part No.: SAM3X8E diff --git a/soc/arm/atmel_sam/sam3x/linker.ld b/soc/arm/atmel_sam/sam3x/linker.ld deleted file mode 100644 index 96ec397da78..00000000000 --- a/soc/arm/atmel_sam/sam3x/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/atmel_sam/sam3x/soc.h b/soc/arm/atmel_sam/sam3x/soc.h index 0d7842fac1c..3fe78a7e6ba 100644 --- a/soc/arm/atmel_sam/sam3x/soc.h +++ b/soc/arm/atmel_sam/sam3x/soc.h @@ -38,6 +38,7 @@ #include "../common/soc_pmc.h" #include "../common/soc_gpio.h" +#include "../common/soc_supc.h" #include "../common/atmel_sam_dt.h" /** Processor Clock (HCLK) Frequency */ diff --git a/soc/arm/atmel_sam/sam4e/CMakeLists.txt b/soc/arm/atmel_sam/sam4e/CMakeLists.txt index 332416ba43b..7424bb9f7b9 100644 --- a/soc/arm/atmel_sam/sam4e/CMakeLists.txt +++ b/soc/arm/atmel_sam/sam4e/CMakeLists.txt @@ -3,3 +3,5 @@ zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/atmel_sam/sam4e/Kconfig.series b/soc/arm/atmel_sam/sam4e/Kconfig.series index 612e1d20bd6..93cc0e20a48 100644 --- a/soc/arm/atmel_sam/sam4e/Kconfig.series +++ b/soc/arm/atmel_sam/sam4e/Kconfig.series @@ -15,6 +15,7 @@ config SOC_SERIES_SAM4E select SOC_FAMILY_SAM select PLATFORM_SPECIFIC_INIT select ASF + select HAS_POWEROFF help Enable support for Atmel SAM4E Cortex-M4 microcontrollers. Part No.: SAM4E16E, SAM4E16C, SAM4E8E, SAM4E8C diff --git a/soc/arm/atmel_sam/sam4e/linker.ld b/soc/arm/atmel_sam/sam4e/linker.ld deleted file mode 100644 index 96ec397da78..00000000000 --- a/soc/arm/atmel_sam/sam4e/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/atmel_sam/sam4e/soc.h b/soc/arm/atmel_sam/sam4e/soc.h index 523c5487748..290653e148a 100644 --- a/soc/arm/atmel_sam/sam4e/soc.h +++ b/soc/arm/atmel_sam/sam4e/soc.h @@ -38,6 +38,7 @@ #include "../common/soc_pmc.h" #include "../common/soc_gpio.h" +#include "../common/soc_supc.h" #include "../common/atmel_sam_dt.h" /** Processor Clock (HCLK) Frequency */ diff --git a/soc/arm/atmel_sam/sam4l/CMakeLists.txt b/soc/arm/atmel_sam/sam4l/CMakeLists.txt index 332416ba43b..7424bb9f7b9 100644 --- a/soc/arm/atmel_sam/sam4l/CMakeLists.txt +++ b/soc/arm/atmel_sam/sam4l/CMakeLists.txt @@ -3,3 +3,5 @@ zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/atmel_sam/sam4l/Kconfig.series b/soc/arm/atmel_sam/sam4l/Kconfig.series index 7a41ba2ff24..0a8192f5bd9 100644 --- a/soc/arm/atmel_sam/sam4l/Kconfig.series +++ b/soc/arm/atmel_sam/sam4l/Kconfig.series @@ -10,6 +10,7 @@ config SOC_SERIES_SAM4L select SOC_FAMILY_SAM select PLATFORM_SPECIFIC_INIT select ASF + select HAS_POWEROFF help Enable support for Atmel SAM4L Cortex-M4 microcontrollers. Part No.: SAM4LS8C, SAM4LS8B, SAM4LS8A, SAM4LS4C, SAM4LS4B, diff --git a/soc/arm/atmel_sam/sam4l/linker.ld b/soc/arm/atmel_sam/sam4l/linker.ld deleted file mode 100644 index 96ec397da78..00000000000 --- a/soc/arm/atmel_sam/sam4l/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/atmel_sam/sam4s/CMakeLists.txt b/soc/arm/atmel_sam/sam4s/CMakeLists.txt index 332416ba43b..7424bb9f7b9 100644 --- a/soc/arm/atmel_sam/sam4s/CMakeLists.txt +++ b/soc/arm/atmel_sam/sam4s/CMakeLists.txt @@ -3,3 +3,5 @@ zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/atmel_sam/sam4s/Kconfig.series b/soc/arm/atmel_sam/sam4s/Kconfig.series index 34fe0ce55f2..f591d96ba88 100644 --- a/soc/arm/atmel_sam/sam4s/Kconfig.series +++ b/soc/arm/atmel_sam/sam4s/Kconfig.series @@ -14,6 +14,7 @@ config SOC_SERIES_SAM4S select SOC_FAMILY_SAM select PLATFORM_SPECIFIC_INIT select ASF + select HAS_POWEROFF help Enable support for Atmel SAM4S Cortex-M4 microcontrollers. Part No.: SAM4S16C, SAM4S16B, SAM4S8C, SAM4S8B, diff --git a/soc/arm/atmel_sam/sam4s/linker.ld b/soc/arm/atmel_sam/sam4s/linker.ld deleted file mode 100644 index 96ec397da78..00000000000 --- a/soc/arm/atmel_sam/sam4s/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/atmel_sam/sam4s/soc.h b/soc/arm/atmel_sam/sam4s/soc.h index e469c3ac19a..ec3ab20471e 100644 --- a/soc/arm/atmel_sam/sam4s/soc.h +++ b/soc/arm/atmel_sam/sam4s/soc.h @@ -52,6 +52,7 @@ #include "../common/soc_pmc.h" #include "../common/soc_gpio.h" +#include "../common/soc_supc.h" #include "../common/atmel_sam_dt.h" /** Processor Clock (HCLK) Frequency */ diff --git a/soc/arm/atmel_sam/same70/CMakeLists.txt b/soc/arm/atmel_sam/same70/CMakeLists.txt index 0ad494174dd..8373266d4ec 100644 --- a/soc/arm/atmel_sam/same70/CMakeLists.txt +++ b/soc/arm/atmel_sam/same70/CMakeLists.txt @@ -4,3 +4,5 @@ zephyr_sources( soc.c soc_config.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/atmel_sam/same70/Kconfig.series b/soc/arm/atmel_sam/same70/Kconfig.series index f8955bd4a76..0e19a2197ba 100644 --- a/soc/arm/atmel_sam/same70/Kconfig.series +++ b/soc/arm/atmel_sam/same70/Kconfig.series @@ -16,6 +16,7 @@ config SOC_SERIES_SAME70 select ASF select HAS_SWO select XIP + select HAS_POWEROFF help Enable support for Atmel SAM E70 ARM Cortex-M7 Microcontrollers. Part No.: SAME70J19, SAME70J20, SAME70J21, SAME70N19, SAME70N20, diff --git a/soc/arm/atmel_sam/same70/linker.ld b/soc/arm/atmel_sam/same70/linker.ld deleted file mode 100644 index e9411a5f889..00000000000 --- a/soc/arm/atmel_sam/same70/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/atmel_sam/same70/soc.h b/soc/arm/atmel_sam/same70/soc.h index 37f10e2792a..ad72b4d2ef0 100644 --- a/soc/arm/atmel_sam/same70/soc.h +++ b/soc/arm/atmel_sam/same70/soc.h @@ -64,6 +64,7 @@ #include "../common/soc_pmc.h" #include "../common/soc_gpio.h" +#include "../common/soc_supc.h" #include "../common/atmel_sam_dt.h" /** Processor Clock (HCLK) Frequency */ diff --git a/soc/arm/atmel_sam/samv71/CMakeLists.txt b/soc/arm/atmel_sam/samv71/CMakeLists.txt index 0ad494174dd..8373266d4ec 100644 --- a/soc/arm/atmel_sam/samv71/CMakeLists.txt +++ b/soc/arm/atmel_sam/samv71/CMakeLists.txt @@ -4,3 +4,5 @@ zephyr_sources( soc.c soc_config.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/atmel_sam/samv71/Kconfig.series b/soc/arm/atmel_sam/samv71/Kconfig.series index 75072eec1ee..49de040aff8 100644 --- a/soc/arm/atmel_sam/samv71/Kconfig.series +++ b/soc/arm/atmel_sam/samv71/Kconfig.series @@ -16,6 +16,7 @@ config SOC_SERIES_SAMV71 select ASF select HAS_SWO select XIP + select HAS_POWEROFF help Enable support for Atmel SAM V71 ARM Cortex-M7 Microcontrollers. Part No.: SAMV71J19, SAMV71J20, SAMV71J21, SAMV71N19, SAMV71N20, diff --git a/soc/arm/atmel_sam/samv71/linker.ld b/soc/arm/atmel_sam/samv71/linker.ld deleted file mode 100644 index e9411a5f889..00000000000 --- a/soc/arm/atmel_sam/samv71/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/atmel_sam/samv71/soc.h b/soc/arm/atmel_sam/samv71/soc.h index 264f92c5172..4c85be42136 100644 --- a/soc/arm/atmel_sam/samv71/soc.h +++ b/soc/arm/atmel_sam/samv71/soc.h @@ -65,6 +65,7 @@ #include "../common/soc_pmc.h" #include "../common/soc_gpio.h" +#include "../common/soc_supc.h" #include "../common/atmel_sam_dt.h" /** Processor Clock (HCLK) Frequency */ diff --git a/soc/arm/atmel_sam0/common/CMakeLists.txt b/soc/arm/atmel_sam0/common/CMakeLists.txt index 53f54da8a78..6dd4525f2d2 100644 --- a/soc/arm/atmel_sam0/common/CMakeLists.txt +++ b/soc/arm/atmel_sam0/common/CMakeLists.txt @@ -23,3 +23,5 @@ zephyr_sources_ifdef(CONFIG_SOC_SERIES_SAME53 soc_samd5x.c) zephyr_sources_ifdef(CONFIG_SOC_SERIES_SAME54 soc_samd5x.c) zephyr_include_directories(.) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/atmel_sam0/samc20/linker.ld b/soc/arm/atmel_sam0/samc20/linker.ld deleted file mode 100644 index 3ff98161e11..00000000000 --- a/soc/arm/atmel_sam0/samc20/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2017 Google LLC. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/atmel_sam0/samc21/linker.ld b/soc/arm/atmel_sam0/samc21/linker.ld deleted file mode 100644 index 3ff98161e11..00000000000 --- a/soc/arm/atmel_sam0/samc21/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2017 Google LLC. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/atmel_sam0/samd20/linker.ld b/soc/arm/atmel_sam0/samd20/linker.ld deleted file mode 100644 index 5068c8fa74a..00000000000 --- a/soc/arm/atmel_sam0/samd20/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2018 Sean Nyekjaer - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/atmel_sam0/samd21/linker.ld b/soc/arm/atmel_sam0/samd21/linker.ld deleted file mode 100644 index 3ff98161e11..00000000000 --- a/soc/arm/atmel_sam0/samd21/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2017 Google LLC. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/atmel_sam0/samd51/linker.ld b/soc/arm/atmel_sam0/samd51/linker.ld deleted file mode 100644 index 3ff98161e11..00000000000 --- a/soc/arm/atmel_sam0/samd51/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2017 Google LLC. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/atmel_sam0/same51/linker.ld b/soc/arm/atmel_sam0/same51/linker.ld deleted file mode 100644 index 3ff98161e11..00000000000 --- a/soc/arm/atmel_sam0/same51/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2017 Google LLC. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/atmel_sam0/same53/linker.ld b/soc/arm/atmel_sam0/same53/linker.ld deleted file mode 100644 index 3ff98161e11..00000000000 --- a/soc/arm/atmel_sam0/same53/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2017 Google LLC. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/atmel_sam0/same54/linker.ld b/soc/arm/atmel_sam0/same54/linker.ld deleted file mode 100644 index 3ff98161e11..00000000000 --- a/soc/arm/atmel_sam0/same54/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2017 Google LLC. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/atmel_sam0/saml21/linker.ld b/soc/arm/atmel_sam0/saml21/linker.ld deleted file mode 100644 index 799b8baa700..00000000000 --- a/soc/arm/atmel_sam0/saml21/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2021 Argentum Systems Ltd. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/atmel_sam0/samr21/linker.ld b/soc/arm/atmel_sam0/samr21/linker.ld deleted file mode 100644 index 3ff98161e11..00000000000 --- a/soc/arm/atmel_sam0/samr21/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2017 Google LLC. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/atmel_sam0/samr34/linker.ld b/soc/arm/atmel_sam0/samr34/linker.ld deleted file mode 100644 index 799b8baa700..00000000000 --- a/soc/arm/atmel_sam0/samr34/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2021 Argentum Systems Ltd. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/atmel_sam0/samr35/linker.ld b/soc/arm/atmel_sam0/samr35/linker.ld deleted file mode 100644 index 799b8baa700..00000000000 --- a/soc/arm/atmel_sam0/samr35/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2021 Argentum Systems Ltd. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/bcm_vk/valkyrie/CMakeLists.txt b/soc/arm/bcm_vk/valkyrie/CMakeLists.txt index f75aec6b311..f5ca7d6435e 100644 --- a/soc/arm/bcm_vk/valkyrie/CMakeLists.txt +++ b/soc/arm/bcm_vk/valkyrie/CMakeLists.txt @@ -1,3 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_include_directories(.) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/bcm_vk/valkyrie/linker.ld b/soc/arm/bcm_vk/valkyrie/linker.ld deleted file mode 100644 index 5a1f7793253..00000000000 --- a/soc/arm/bcm_vk/valkyrie/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 */ -/* - * Copyright 2019 Broadcom. - */ - - -#include diff --git a/soc/arm/bcm_vk/viper/CMakeLists.txt b/soc/arm/bcm_vk/viper/CMakeLists.txt index 3b465dc7da8..b81c75442e1 100644 --- a/soc/arm/bcm_vk/viper/CMakeLists.txt +++ b/soc/arm/bcm_vk/viper/CMakeLists.txt @@ -4,3 +4,5 @@ zephyr_include_directories(.) zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/bcm_vk/viper/linker.ld b/soc/arm/bcm_vk/viper/linker.ld deleted file mode 100644 index c3ea22e3564..00000000000 --- a/soc/arm/bcm_vk/viper/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright 2020 Broadcom - * - * SPDX-License-Identifier: Apache-2.0 - */ - - -#include diff --git a/soc/arm/bcm_vk/viper/linker_m7.ld b/soc/arm/bcm_vk/viper/linker_m7.ld deleted file mode 100644 index 3e28ca6c567..00000000000 --- a/soc/arm/bcm_vk/viper/linker_m7.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright 2020 Broadcom - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/common/cortex_m/CMakeLists.txt b/soc/arm/common/cortex_m/CMakeLists.txt deleted file mode 100644 index f6016604726..00000000000 --- a/soc/arm/common/cortex_m/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -if(CONFIG_ARM_MPU AND NOT CONFIG_CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS) - - zephyr_library() - - zephyr_library_sources_ifdef(CONFIG_CPU_HAS_ARM_MPU - arm_mpu_regions.c - ) - zephyr_library_sources_ifdef(CONFIG_CPU_HAS_NXP_MPU - nxp_mpu_regions.c - ) -endif() diff --git a/soc/arm/cypress/psoc6/CMakeLists.txt b/soc/arm/cypress/psoc6/CMakeLists.txt index a88416cda13..e2ea2eb6ae1 100644 --- a/soc/arm/cypress/psoc6/CMakeLists.txt +++ b/soc/arm/cypress/psoc6/CMakeLists.txt @@ -12,3 +12,5 @@ zephyr_sources( zephyr_linker_sources_ifdef(CONFIG_SOC_FAMILY_PSOC6 NOINIT noinit.ld) zephyr_linker_sources_ifdef(CONFIG_SOC_FAMILY_PSOC6 RWDATA rwdata.ld) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/cypress/psoc6/linker.ld b/soc/arm/cypress/psoc6/linker.ld deleted file mode 100644 index bd76ded366c..00000000000 --- a/soc/arm/cypress/psoc6/linker.ld +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2018 Cypress - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images and XIP images. - */ - - -#include diff --git a/soc/arm/gigadevice/gd32a50x/CMakeLists.txt b/soc/arm/gigadevice/gd32a50x/CMakeLists.txt index 6691c489648..033272f3619 100644 --- a/soc/arm/gigadevice/gd32a50x/CMakeLists.txt +++ b/soc/arm/gigadevice/gd32a50x/CMakeLists.txt @@ -3,3 +3,5 @@ zephyr_include_directories(.) zephyr_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/gigadevice/gd32a50x/linker.ld b/soc/arm/gigadevice/gd32a50x/linker.ld deleted file mode 100644 index 32362bbe6e7..00000000000 --- a/soc/arm/gigadevice/gd32a50x/linker.ld +++ /dev/null @@ -1,6 +0,0 @@ -/* - * Copyright (c) 2021 Teslabs Engineering S.L. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/gigadevice/gd32e10x/CMakeLists.txt b/soc/arm/gigadevice/gd32e10x/CMakeLists.txt index 58df401dc74..18c19936f9f 100644 --- a/soc/arm/gigadevice/gd32e10x/CMakeLists.txt +++ b/soc/arm/gigadevice/gd32e10x/CMakeLists.txt @@ -3,3 +3,5 @@ zephyr_include_directories(.) zephyr_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/gigadevice/gd32e10x/linker.ld b/soc/arm/gigadevice/gd32e10x/linker.ld deleted file mode 100644 index 39c3b988037..00000000000 --- a/soc/arm/gigadevice/gd32e10x/linker.ld +++ /dev/null @@ -1,6 +0,0 @@ -/* - * Copyright (c) 2021 YuLong Yao - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/gigadevice/gd32e50x/CMakeLists.txt b/soc/arm/gigadevice/gd32e50x/CMakeLists.txt index d320b8ec86e..bcb019aac62 100644 --- a/soc/arm/gigadevice/gd32e50x/CMakeLists.txt +++ b/soc/arm/gigadevice/gd32e50x/CMakeLists.txt @@ -3,3 +3,5 @@ zephyr_include_directories(.) zephyr_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/gigadevice/gd32e50x/linker.ld b/soc/arm/gigadevice/gd32e50x/linker.ld deleted file mode 100644 index 32362bbe6e7..00000000000 --- a/soc/arm/gigadevice/gd32e50x/linker.ld +++ /dev/null @@ -1,6 +0,0 @@ -/* - * Copyright (c) 2021 Teslabs Engineering S.L. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/gigadevice/gd32f3x0/CMakeLists.txt b/soc/arm/gigadevice/gd32f3x0/CMakeLists.txt index 012b6cddc94..a6856dbe680 100644 --- a/soc/arm/gigadevice/gd32f3x0/CMakeLists.txt +++ b/soc/arm/gigadevice/gd32f3x0/CMakeLists.txt @@ -3,3 +3,5 @@ zephyr_include_directories(.) zephyr_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/gigadevice/gd32f3x0/linker.ld b/soc/arm/gigadevice/gd32f3x0/linker.ld deleted file mode 100644 index d0bc3bd8737..00000000000 --- a/soc/arm/gigadevice/gd32f3x0/linker.ld +++ /dev/null @@ -1,6 +0,0 @@ -/* - * Copyright (c) 2021 BrainCo Inc. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/gigadevice/gd32f403/CMakeLists.txt b/soc/arm/gigadevice/gd32f403/CMakeLists.txt index 0003b5a9de2..af30be8f737 100644 --- a/soc/arm/gigadevice/gd32f403/CMakeLists.txt +++ b/soc/arm/gigadevice/gd32f403/CMakeLists.txt @@ -3,3 +3,5 @@ zephyr_include_directories(.) zephyr_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/gigadevice/gd32f403/linker.ld b/soc/arm/gigadevice/gd32f403/linker.ld deleted file mode 100644 index 96ec397da78..00000000000 --- a/soc/arm/gigadevice/gd32f403/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/gigadevice/gd32f4xx/CMakeLists.txt b/soc/arm/gigadevice/gd32f4xx/CMakeLists.txt index 9d80226466c..dd55a9bcdb1 100644 --- a/soc/arm/gigadevice/gd32f4xx/CMakeLists.txt +++ b/soc/arm/gigadevice/gd32f4xx/CMakeLists.txt @@ -3,3 +3,5 @@ zephyr_include_directories(.) zephyr_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/gigadevice/gd32f4xx/linker.ld b/soc/arm/gigadevice/gd32f4xx/linker.ld deleted file mode 100644 index 32362bbe6e7..00000000000 --- a/soc/arm/gigadevice/gd32f4xx/linker.ld +++ /dev/null @@ -1,6 +0,0 @@ -/* - * Copyright (c) 2021 Teslabs Engineering S.L. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/gigadevice/gd32l23x/CMakeLists.txt b/soc/arm/gigadevice/gd32l23x/CMakeLists.txt index 21581379afa..217e6940926 100644 --- a/soc/arm/gigadevice/gd32l23x/CMakeLists.txt +++ b/soc/arm/gigadevice/gd32l23x/CMakeLists.txt @@ -3,3 +3,5 @@ zephyr_include_directories(.) zephyr_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/gigadevice/gd32l23x/linker.ld b/soc/arm/gigadevice/gd32l23x/linker.ld deleted file mode 100644 index a5bd1ec82a5..00000000000 --- a/soc/arm/gigadevice/gd32l23x/linker.ld +++ /dev/null @@ -1,6 +0,0 @@ -/* - * Copyright (c) 2022 BrainCo Inc. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/infineon_cat1/common/pinctrl_soc.h b/soc/arm/infineon_cat1/common/pinctrl_soc.h index 51c01fcaaa1..7832c1b39de 100644 --- a/soc/arm/infineon_cat1/common/pinctrl_soc.h +++ b/soc/arm/infineon_cat1/common/pinctrl_soc.h @@ -59,6 +59,9 @@ extern "C" { #define SOC_GPIO_INPUTENABLE_POS (5) #define SOC_GPIO_INPUTENABLE (1 << SOC_GPIO_INPUTENABLE_POS) +#define SOC_GPIO_HIGHZ_POS (6) +#define SOC_GPIO_HIGHZ (1 << SOC_GPIO_HIGHZ_POS) + /** Type for CAT1 Soc pin. */ typedef struct { /** @@ -96,7 +99,8 @@ typedef struct { (DT_PROP(node_id, drive_open_drain) << SOC_GPIO_OPENDRAIN_POS) | \ (DT_PROP(node_id, drive_open_source) << SOC_GPIO_OPENSOURCE_POS) | \ (DT_PROP(node_id, drive_push_pull) << SOC_GPIO_PUSHPULL_POS) | \ - (DT_PROP(node_id, input_enable) << SOC_GPIO_INPUTENABLE_POS)) + (DT_PROP(node_id, input_enable) << SOC_GPIO_INPUTENABLE_POS) | \ + (DT_PROP(node_id, bias_high_impedance) << SOC_GPIO_HIGHZ_POS)) /** * @brief Utility macro to initialize each pin. diff --git a/soc/arm/infineon_cat1/psoc6/CMakeLists.txt b/soc/arm/infineon_cat1/psoc6/CMakeLists.txt index e047fc704bb..26c9fb8cd9c 100644 --- a/soc/arm/infineon_cat1/psoc6/CMakeLists.txt +++ b/soc/arm/infineon_cat1/psoc6/CMakeLists.txt @@ -17,3 +17,5 @@ zephyr_linker_sources_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1A RAM_SECTIONS SORT_K zephyr_linker_sources_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1A RAMFUNC_SECTION SORT_KEY 0 ram_func.ld) zephyr_linker_sources_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1 RODATA SORT_KEY 0 rom.ld) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/infineon_cat1/psoc6/linker.ld b/soc/arm/infineon_cat1/psoc6/linker.ld deleted file mode 100644 index d2e0572cbed..00000000000 --- a/soc/arm/infineon_cat1/psoc6/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) 2022 Cypress Semiconductor Corporation (an Infineon company) or - * an affiliate of Cypress Semiconductor Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/infineon_xmc/4xxx/CMakeLists.txt b/soc/arm/infineon_xmc/4xxx/CMakeLists.txt index 124571032e1..8216f9a09ee 100644 --- a/soc/arm/infineon_xmc/4xxx/CMakeLists.txt +++ b/soc/arm/infineon_xmc/4xxx/CMakeLists.txt @@ -5,3 +5,5 @@ zephyr_sources(soc.c) zephyr_linker_sources(NOINIT noinit.ld) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/infineon_xmc/4xxx/Kconfig.series b/soc/arm/infineon_xmc/4xxx/Kconfig.series index 5bfdb994fe4..53312dfaf7b 100644 --- a/soc/arm/infineon_xmc/4xxx/Kconfig.series +++ b/soc/arm/infineon_xmc/4xxx/Kconfig.series @@ -20,5 +20,6 @@ config SOC_SERIES_XMC_4XXX select HAS_XMCLIB_SPI select HAS_XMCLIB_I2C select HAS_XMCLIB_CCU + select HAS_XMCLIB_WDT help Enable support for XMC 4xxx MCU series diff --git a/soc/arm/infineon_xmc/4xxx/linker.ld b/soc/arm/infineon_xmc/4xxx/linker.ld deleted file mode 100644 index 5d6126629f9..00000000000 --- a/soc/arm/infineon_xmc/4xxx/linker.ld +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images and XIP images. - */ - -#include diff --git a/soc/arm/intel_socfpga_std/cyclonev/CMakeLists.txt b/soc/arm/intel_socfpga_std/cyclonev/CMakeLists.txt index 68f5199d81c..4b94d9047e4 100644 --- a/soc/arm/intel_socfpga_std/cyclonev/CMakeLists.txt +++ b/soc/arm/intel_socfpga_std/cyclonev/CMakeLists.txt @@ -5,3 +5,5 @@ zephyr_include_directories(.) zephyr_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/intel_socfpga_std/cyclonev/linker.ld b/soc/arm/intel_socfpga_std/cyclonev/linker.ld deleted file mode 100644 index c4812640739..00000000000 --- a/soc/arm/intel_socfpga_std/cyclonev/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) 2022 Intel Corporation - * SPDX-License-Identifier: Apache-2.0 - * Description: - * Adding support for Cyclone V SoC FPGA, using arm32 linker - */ - -#include diff --git a/soc/arm/intel_socfpga_std/cyclonev/soc.c b/soc/arm/intel_socfpga_std/cyclonev/soc.c index 70e697dd62b..73f7617d792 100644 --- a/soc/arm/intel_socfpga_std/cyclonev/soc.c +++ b/soc/arm/intel_socfpga_std/cyclonev/soc.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include "soc.h" #include diff --git a/soc/arm/microchip_mec/mec1501/CMakeLists.txt b/soc/arm/microchip_mec/mec1501/CMakeLists.txt index 70889bc982b..e92250a6989 100644 --- a/soc/arm/microchip_mec/mec1501/CMakeLists.txt +++ b/soc/arm/microchip_mec/mec1501/CMakeLists.txt @@ -21,3 +21,5 @@ if(CONFIG_SOC_HAS_TIMING_FUNCTIONS AND NOT CONFIG_BOARD_HAS_TIMING_FUNCTIONS) endif() endif() endif() + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/microchip_mec/mec1501/linker.ld b/soc/arm/microchip_mec/mec1501/linker.ld deleted file mode 100644 index 96ec397da78..00000000000 --- a/soc/arm/microchip_mec/mec1501/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/microchip_mec/mec1501/timing.c b/soc/arm/microchip_mec/mec1501/timing.c index 016cfa249f4..a67844f60d2 100644 --- a/soc/arm/microchip_mec/mec1501/timing.c +++ b/soc/arm/microchip_mec/mec1501/timing.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include #include #include diff --git a/soc/arm/microchip_mec/mec172x/CMakeLists.txt b/soc/arm/microchip_mec/mec172x/CMakeLists.txt index 3581ce69b40..59f3b5e4d2b 100644 --- a/soc/arm/microchip_mec/mec172x/CMakeLists.txt +++ b/soc/arm/microchip_mec/mec172x/CMakeLists.txt @@ -21,3 +21,5 @@ if(CONFIG_SOC_HAS_TIMING_FUNCTIONS AND NOT CONFIG_BOARD_HAS_TIMING_FUNCTIONS) endif() endif() endif() + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/microchip_mec/mec172x/Kconfig.defconfig.series b/soc/arm/microchip_mec/mec172x/Kconfig.defconfig.series index afee2b8a59b..d23de11262d 100644 --- a/soc/arm/microchip_mec/mec172x/Kconfig.defconfig.series +++ b/soc/arm/microchip_mec/mec172x/Kconfig.defconfig.series @@ -33,10 +33,4 @@ config PS2_XEC default y depends on PS2 -config PM - default y if SYS_CLOCK_EXISTS - -config PM_DEVICE - default n - endif # SOC_SERIES_MEC172X diff --git a/soc/arm/microchip_mec/mec172x/linker.ld b/soc/arm/microchip_mec/mec172x/linker.ld deleted file mode 100644 index 96ec397da78..00000000000 --- a/soc/arm/microchip_mec/mec172x/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/microchip_mec/mec172x/reg/gpio_pkg_lj.h b/soc/arm/microchip_mec/mec172x/reg/gpio_pkg_lj.h new file mode 100644 index 00000000000..71e1c089f07 --- /dev/null +++ b/soc/arm/microchip_mec/mec172x/reg/gpio_pkg_lj.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2021 Microchip Technology Inc. and its subsidiaries. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _MEC172X_GPIO_LJ_H +#define _MEC172X_GPIO_LJ_H + +#define MCHP_GPIO_PORT_A_BITMAP 0x7FFFFFFFu /* GPIO_0000 - 0036 GIRQ11 */ +#define MCHP_GPIO_PORT_B_BITMAP 0x7FFFFFFFu /* GPIO_0040 - 0076 GIRQ10 */ +#define MCHP_GPIO_PORT_C_BITMAP 0x3FFFFFF7u /* GPIO_0100 - 0136 GIRQ09 */ +#define MCHP_GPIO_PORT_D_BITMAP 0x3F67FFFFu /* GPIO_0140 - 0176 GIRQ08 */ +#define MCHP_GPIO_PORT_E_BITMAP 0x7FFFFFFFu /* GPIO_0200 - 0236 GIRQ12 */ +#define MCHP_GPIO_PORT_F_BITMAP 0x00003F7Fu /* GPIO_0240 - 0276 GIRQ26 */ + +#endif /* #ifndef _MEC172X_GPIO_LJ_H */ diff --git a/soc/arm/microchip_mec/mec172x/reg/gpio_pkg_sz.h b/soc/arm/microchip_mec/mec172x/reg/gpio_pkg_sz.h new file mode 100644 index 00000000000..bfd89788237 --- /dev/null +++ b/soc/arm/microchip_mec/mec172x/reg/gpio_pkg_sz.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2021 Microchip Technology Inc. and its subsidiaries. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _MEC172X_GPIO_SZ_H +#define _MEC172X_GPIO_SZ_H + +#include +#include + +/* MEC172XH-B0-SZ (144-pin) */ +#define MCHP_GPIO_PORT_A_BITMAP 0x7FFFFF9Du /* GPIO_0000 - 0036 GIRQ11 */ +#define MCHP_GPIO_PORT_B_BITMAP 0x7FFFFFFDu /* GPIO_0040 - 0076 GIRQ10 */ +#define MCHP_GPIO_PORT_C_BITMAP 0x07FFFCF7u /* GPIO_0100 - 0136 GIRQ09 */ +#define MCHP_GPIO_PORT_D_BITMAP 0x272EFFFFu /* GPIO_0140 - 0176 GIRQ08 */ +#define MCHP_GPIO_PORT_E_BITMAP 0x00DE00FFu /* GPIO_0200 - 0236 GIRQ12 */ +#define MCHP_GPIO_PORT_F_BITMAP 0x0000397Fu /* GPIO_0240 - 0276 GIRQ26 */ + +#endif /* #ifndef _MEC172X_GPIO_SZ_H */ diff --git a/soc/arm/microchip_mec/mec172x/reg/mec172x_gpio.h b/soc/arm/microchip_mec/mec172x/reg/mec172x_gpio.h index 82b53c4af00..39ed59d279d 100644 --- a/soc/arm/microchip_mec/mec172x/reg/mec172x_gpio.h +++ b/soc/arm/microchip_mec/mec172x/reg/mec172x_gpio.h @@ -10,49 +10,15 @@ #include #include +#if defined(CONFIG_SOC_MEC172X_NSZ) +#include "gpio_pkg_sz.h" +#elif defined(CONFIG_SOC_MEC172X_NLJ) +#include "gpio_pkg_lj.h" +#endif + #define NUM_MCHP_GPIO_PORTS 6u #define MAX_NUM_MCHP_GPIO (NUM_MCHP_GPIO_PORTS * 32u) -#define MCHP_GPIO_CTRL_OFS 0u -#define MCHP_GPIO_PARIN_OFS 0x0300u -#define MCHP_GPIO_PAROUT_OFS 0x0380u -#define MCHP_GPIO_LOCK_OFS 0x03e8u -#define MCHP_GPIO_CTRL2_OFS 0x0500u - -/* MEC172XH-B0-SZ (144-pin) */ -#define MCHP_GPIO_PORT_A_BITMAP 0x7FFFFF9Du /* GPIO_0000 - 0036 GIRQ11 */ -#define MCHP_GPIO_PORT_B_BITMAP 0x7FFFFFFDu /* GPIO_0040 - 0076 GIRQ10 */ -#define MCHP_GPIO_PORT_C_BITMAP 0x07FFFCF7u /* GPIO_0100 - 0136 GIRQ09 */ -#define MCHP_GPIO_PORT_D_BITMAP 0x272EFFFFu /* GPIO_0140 - 0176 GIRQ08 */ -#define MCHP_GPIO_PORT_E_BITMAP 0x00DE00FFu /* GPIO_0200 - 0236 GIRQ12 */ -#define MCHP_GPIO_PORT_F_BITMAP 0x0000397Fu /* GPIO_0240 - 0276 GIRQ26 */ - -#define MCHP_GPIO_PORT_A_DRVSTR_BITMAP 0x7FFFFF9Du -#define MCHP_GPIO_PORT_B_DRVSTR_BITMAP 0x7FFFFFFDu -#define MCHP_GPIO_PORT_C_DRVSTR_BITMAP 0x07FFFCF7u -#define MCHP_GPIO_PORT_D_DRVSTR_BITMAP 0x272EFFFFu -#define MCHP_GPIO_PORT_E_DRVSTR_BITMAP 0x00DE00FFu -#define MCHP_GPIO_PORT_F_DRVSTR_BITMAP 0x0000397Fu - -/* 32-bit Control register */ -#define MCHP_GPIO_CTRL_MASK 0x0101ffffu -/* bits[15:0] of Control register */ -#define MCHP_GPIO_CTRL_CFG_MASK 0xffffu - -/* Disable interrupt detect and pad */ -#define MCHP_GPIO_CTRL_DIS_PIN 0x8040u - -#define MCHP_GPIO_CTRL_DFLT 0x8040u -#define MCHP_GPIO_CTRL_DFLT_MASK 0xffffu - -#define GPIO000_CTRL_DFLT 0x1040u -#define GPIO062_CTRL_DFLT 0x8240u -#define GPIO116_CTRL_DFLT 0x0041u -#define GPIO161_CTRL_DFLT 0x1040u -#define GPIO162_CTRL_DFLT 0x1040u -#define GPIO170_CTRL_DFLT 0x0041u -#define GPIO234_CTRL_DFLT 0x1040u - /* GPIO Control register field definitions. */ /* bits[1:0] internal pull up/down selection */ @@ -156,7 +122,6 @@ * 10b = 8mA * 11b = 12mA */ -#define MCHP_GPIO_CTRL2_OFFSET 0x0500u #define MCHP_GPIO_CTRL2_SLEW_POS 0 #define MCHP_GPIO_CTRL2_SLEW_MASK 0x01u #define MCHP_GPIO_CTRL2_SLEW_SLOW 0 @@ -173,149 +138,8 @@ extern "C" { #endif -/* GPIO pin numbers SZ (144-pin) package */ -enum mec_gpio_idx { - MCHP_GPIO_0000_ID = 0, - MCHP_GPIO_0002_ID = 2, - MCHP_GPIO_0003_ID, - MCHP_GPIO_0004_ID, - MCHP_GPIO_0007_ID = 7, - MCHP_GPIO_0010_ID, - MCHP_GPIO_0011_ID, - MCHP_GPIO_0012_ID, - MCHP_GPIO_0013_ID, - MCHP_GPIO_0014_ID, - MCHP_GPIO_0015_ID, - MCHP_GPIO_0016_ID, - MCHP_GPIO_0017_ID, - MCHP_GPIO_0020_ID, - MCHP_GPIO_0021_ID, - MCHP_GPIO_0022_ID, - MCHP_GPIO_0023_ID, - MCHP_GPIO_0024_ID, - MCHP_GPIO_0025_ID, - MCHP_GPIO_0026_ID, - MCHP_GPIO_0027_ID, - MCHP_GPIO_0030_ID, - MCHP_GPIO_0031_ID, - MCHP_GPIO_0032_ID, - MCHP_GPIO_0033_ID, - MCHP_GPIO_0034_ID, - MCHP_GPIO_0035_ID, - MCHP_GPIO_0036_ID, - MCHP_GPIO_0040_ID = 32, - MCHP_GPIO_0042_ID = 34, - MCHP_GPIO_0043_ID, - MCHP_GPIO_0044_ID, - MCHP_GPIO_0045_ID, - MCHP_GPIO_0046_ID, - MCHP_GPIO_0047_ID, - MCHP_GPIO_0050_ID, - MCHP_GPIO_0051_ID, - MCHP_GPIO_0052_ID, - MCHP_GPIO_0053_ID, - MCHP_GPIO_0054_ID, - MCHP_GPIO_0055_ID, - MCHP_GPIO_0056_ID, - MCHP_GPIO_0057_ID, - MCHP_GPIO_0060_ID, - MCHP_GPIO_0061_ID, - MCHP_GPIO_0062_ID, - MCHP_GPIO_0063_ID, - MCHP_GPIO_0064_ID, - MCHP_GPIO_0065_ID, - MCHP_GPIO_0066_ID, - MCHP_GPIO_0067_ID, - MCHP_GPIO_0070_ID, - MCHP_GPIO_0071_ID, - MCHP_GPIO_0072_ID, - MCHP_GPIO_0073_ID, - MCHP_GPIO_0074_ID, - MCHP_GPIO_0075_ID, - MCHP_GPIO_0076_ID, - MCHP_GPIO_0100_ID = 64, - MCHP_GPIO_0101_ID, - MCHP_GPIO_0102_ID, - MCHP_GPIO_0104_ID = 68, - MCHP_GPIO_0105_ID, - MCHP_GPIO_0106_ID, - MCHP_GPIO_0107_ID, - MCHP_GPIO_0112_ID = 74, - MCHP_GPIO_0113_ID, - MCHP_GPIO_0114_ID, - MCHP_GPIO_0115_ID, - MCHP_GPIO_0116_ID, - MCHP_GPIO_0117_ID, - MCHP_GPIO_0120_ID = 80, - MCHP_GPIO_0121_ID, - MCHP_GPIO_0122_ID, - MCHP_GPIO_0123_ID, - MCHP_GPIO_0124_ID, - MCHP_GPIO_0125_ID, - MCHP_GPIO_0126_ID, - MCHP_GPIO_0127_ID, - MCHP_GPIO_0130_ID, - MCHP_GPIO_0131_ID, - MCHP_GPIO_0132_ID, - MCHP_GPIO_0140_ID = 96, - MCHP_GPIO_0141_ID, - MCHP_GPIO_0142_ID, - MCHP_GPIO_0143_ID, - MCHP_GPIO_0144_ID, - MCHP_GPIO_0145_ID, - MCHP_GPIO_0146_ID, - MCHP_GPIO_0147_ID, - MCHP_GPIO_0150_ID, - MCHP_GPIO_0151_ID, - MCHP_GPIO_0152_ID, - MCHP_GPIO_0153_ID, - MCHP_GPIO_0154_ID, - MCHP_GPIO_0155_ID, - MCHP_GPIO_0156_ID, - MCHP_GPIO_0157_ID, - MCHP_GPIO_0161_ID = 113, - MCHP_GPIO_0162_ID, - MCHP_GPIO_0165_ID = 117, - MCHP_GPIO_0170_ID = 120, - MCHP_GPIO_0171_ID, - MCHP_GPIO_0175_ID = 125, - MCHP_GPIO_0200_ID = 128, - MCHP_GPIO_0201_ID, - MCHP_GPIO_0202_ID, - MCHP_GPIO_0203_ID, - MCHP_GPIO_0204_ID, - MCHP_GPIO_0205_ID, - MCHP_GPIO_0206_ID, - MCHP_GPIO_0207_ID, - MCHP_GPIO_0221_ID = 145, - MCHP_GPIO_0222_ID, - MCHP_GPIO_0223_ID, - MCHP_GPIO_0224_ID, - MCHP_GPIO_0226_ID = 150, - MCHP_GPIO_0227_ID, - MCHP_GPIO_0240_ID = 160, - MCHP_GPIO_0241_ID, - MCHP_GPIO_0242_ID, - MCHP_GPIO_0243_ID, - MCHP_GPIO_0244_ID, - MCHP_GPIO_0245_ID, - MCHP_GPIO_0246_ID, - MCHP_GPIO_0254_ID = 172, - MCHP_GPIO_0255_ID, - MCHP_GPIO_MAX_ID -}; - #define MCHP_GPIO_PIN2PORT(pin_id) ((uint32_t)(pin_id) >> 5) -#define MAX_MCHP_GPIO_BANK 6u -#define MCHP_GPIO_LOCK5_IDX 0u -#define MCHP_GPIO_LOCK4_IDX 1u -#define MCHP_GPIO_LOCK3_IDX 2u -#define MCHP_GPIO_LOCK2_IDX 3u -#define MCHP_GPIO_LOCK1_IDX 4u -#define MCHP_GPIO_LOCK0_IDX 5u -#define MCHP_GPIO_LOCK_MAX_IDX 6u - /* Helper functions */ enum mchp_gpio_pud { MCHP_GPIO_NO_PUD = 0, @@ -393,332 +217,6 @@ enum mchp_gpio_drv_str { MCHP_GPIO_DRV_STR_12MA, }; -/** @brief GPIO control registers by pin name */ -struct gpio_ctrl_regs { - volatile uint32_t CTRL_0000; - uint32_t RSVD1[1]; - volatile uint32_t CTRL_0002; - volatile uint32_t CTRL_0003; - volatile uint32_t CTRL_0004; - uint32_t RSVD2[2]; - volatile uint32_t CTRL_0007; - volatile uint32_t CTRL_0010; - volatile uint32_t CTRL_0011; - volatile uint32_t CTRL_0012; - volatile uint32_t CTRL_0013; - volatile uint32_t CTRL_0014; - volatile uint32_t CTRL_0015; - volatile uint32_t CTRL_0016; - volatile uint32_t CTRL_0017; - volatile uint32_t CTRL_0020; - volatile uint32_t CTRL_0021; - volatile uint32_t CTRL_0022; - volatile uint32_t CTRL_0023; - volatile uint32_t CTRL_0024; - volatile uint32_t CTRL_0025; - volatile uint32_t CTRL_0026; - volatile uint32_t CTRL_0027; - volatile uint32_t CTRL_0030; - volatile uint32_t CTRL_0031; - volatile uint32_t CTRL_0032; - volatile uint32_t CTRL_0033; - volatile uint32_t CTRL_0034; - volatile uint32_t CTRL_0035; - volatile uint32_t CTRL_0036; - uint32_t RSVD3[1]; - volatile uint32_t CTRL_0040; - uint32_t RSVD4[1]; - volatile uint32_t CTRL_0042; - volatile uint32_t CTRL_0043; - volatile uint32_t CTRL_0044; - volatile uint32_t CTRL_0045; - volatile uint32_t CTRL_0046; - volatile uint32_t CTRL_0047; - volatile uint32_t CTRL_0050; - volatile uint32_t CTRL_0051; - volatile uint32_t CTRL_0052; - volatile uint32_t CTRL_0053; - volatile uint32_t CTRL_0054; - volatile uint32_t CTRL_0055; - volatile uint32_t CTRL_0056; - volatile uint32_t CTRL_0057; - volatile uint32_t CTRL_0060; - volatile uint32_t CTRL_0061; - volatile uint32_t CTRL_0062; - volatile uint32_t CTRL_0063; - volatile uint32_t CTRL_0064; - volatile uint32_t CTRL_0065; - volatile uint32_t CTRL_0066; - volatile uint32_t CTRL_0067; - volatile uint32_t CTRL_0070; - volatile uint32_t CTRL_0071; - volatile uint32_t CTRL_0072; - volatile uint32_t CTRL_0073; - volatile uint32_t CTRL_0074; - volatile uint32_t CTRL_0075; - volatile uint32_t CTRL_0076; - uint32_t RSVD5[1]; - volatile uint32_t CTRL_0100; - volatile uint32_t CTRL_0101; - volatile uint32_t CTRL_0102; - uint32_t RSVD6[1]; - volatile uint32_t CTRL_0104; - volatile uint32_t CTRL_0105; - volatile uint32_t CTRL_0106; - volatile uint32_t CTRL_0107; - uint32_t RSVD7[2]; - volatile uint32_t CTRL_0112; - volatile uint32_t CTRL_0113; - volatile uint32_t CTRL_0114; - volatile uint32_t CTRL_0115; - volatile uint32_t CTRL_0116; - volatile uint32_t CTRL_0117; - volatile uint32_t CTRL_0120; - volatile uint32_t CTRL_0121; - volatile uint32_t CTRL_0122; - volatile uint32_t CTRL_0123; - volatile uint32_t CTRL_0124; - volatile uint32_t CTRL_0125; - volatile uint32_t CTRL_0126; - volatile uint32_t CTRL_0127; - volatile uint32_t CTRL_0130; - volatile uint32_t CTRL_0131; - volatile uint32_t CTRL_0132; - uint32_t RSVD9[5]; - volatile uint32_t CTRL_0140; - volatile uint32_t CTRL_0141; - volatile uint32_t CTRL_0142; - volatile uint32_t CTRL_0143; - volatile uint32_t CTRL_0144; - volatile uint32_t CTRL_0145; - volatile uint32_t CTRL_0146; - volatile uint32_t CTRL_0147; - volatile uint32_t CTRL_0150; - volatile uint32_t CTRL_0151; - volatile uint32_t CTRL_0152; - volatile uint32_t CTRL_0153; - volatile uint32_t CTRL_0154; - volatile uint32_t CTRL_0155; - volatile uint32_t CTRL_0156; - volatile uint32_t CTRL_0157; - uint32_t RSVD10[1]; - volatile uint32_t CTRL_0161; - volatile uint32_t CTRL_0162; - uint32_t RSVD11[2]; - volatile uint32_t CTRL_0165; - uint32_t RSVD12[2]; - volatile uint32_t CTRL_0170; - volatile uint32_t CTRL_0171; - uint32_t RSVD13[3]; - volatile uint32_t CTRL_0175; - uint32_t RSVD14[2]; - volatile uint32_t CTRL_0200; - volatile uint32_t CTRL_0201; - volatile uint32_t CTRL_0202; - volatile uint32_t CTRL_0203; - volatile uint32_t CTRL_0204; - volatile uint32_t CTRL_0205; - volatile uint32_t CTRL_0206; - volatile uint32_t CTRL_0207; - uint32_t RSVD15[9]; - volatile uint32_t CTRL_0221; - volatile uint32_t CTRL_0222; - volatile uint32_t CTRL_0223; - volatile uint32_t CTRL_0224; - uint32_t RSVD16[1]; - volatile uint32_t CTRL_0226; - volatile uint32_t CTRL_0227; - uint32_t RSVD17[8]; - volatile uint32_t CTRL_0240; - volatile uint32_t CTRL_0241; - volatile uint32_t CTRL_0242; - volatile uint32_t CTRL_0243; - volatile uint32_t CTRL_0244; - volatile uint32_t CTRL_0245; - volatile uint32_t CTRL_0246; - uint32_t RSVD18[5]; - volatile uint32_t CTRL_0254; - volatile uint32_t CTRL_0255; -}; - -/** @brief GPIO Control 2 registers by pin name */ -struct gpio_ctrl2_regs { - volatile uint32_t CTRL2_0000; - uint32_t RSVD1[1]; - volatile uint32_t CTRL2_0002; - volatile uint32_t CTRL2_0003; - volatile uint32_t CTRL2_0004; - uint32_t RSVD2[2]; - volatile uint32_t CTRL2_0007; - volatile uint32_t CTRL2_0010; - volatile uint32_t CTRL2_0011; - volatile uint32_t CTRL2_0012; - volatile uint32_t CTRL2_0013; - volatile uint32_t CTRL2_0014; - volatile uint32_t CTRL2_0015; - volatile uint32_t CTRL2_0016; - volatile uint32_t CTRL2_0017; - volatile uint32_t CTRL2_0020; - volatile uint32_t CTRL2_0021; - volatile uint32_t CTRL2_0022; - volatile uint32_t CTRL2_0023; - volatile uint32_t CTRL2_0024; - volatile uint32_t CTRL2_0025; - volatile uint32_t CTRL2_0026; - volatile uint32_t CTRL2_0027; - volatile uint32_t CTRL2_0030; - volatile uint32_t CTRL2_0031; - volatile uint32_t CTRL2_0032; - volatile uint32_t CTRL2_0033; - volatile uint32_t CTRL2_0034; - volatile uint32_t CTRL2_0035; - volatile uint32_t CTRL2_0036; - uint32_t RSVD3[1]; - volatile uint32_t CTRL2_0040; - uint32_t RSVD4[1]; - volatile uint32_t CTRL2_0042; - volatile uint32_t CTRL2_0043; - volatile uint32_t CTRL2_0044; - volatile uint32_t CTRL2_0045; - volatile uint32_t CTRL2_0046; - volatile uint32_t CTRL2_0047; - volatile uint32_t CTRL2_0050; - volatile uint32_t CTRL2_0051; - volatile uint32_t CTRL2_0052; - volatile uint32_t CTRL2_0053; - volatile uint32_t CTRL2_0054; - volatile uint32_t CTRL2_0055; - volatile uint32_t CTRL2_0056; - volatile uint32_t CTRL2_0057; - volatile uint32_t CTRL2_0060; - volatile uint32_t CTRL2_0061; - volatile uint32_t CTRL2_0062; - volatile uint32_t CTRL2_0063; - volatile uint32_t CTRL2_0064; - volatile uint32_t CTRL2_0065; - volatile uint32_t CTRL2_0066; - volatile uint32_t CTRL2_0067; - volatile uint32_t CTRL2_0070; - volatile uint32_t CTRL2_0071; - volatile uint32_t CTRL2_0072; - volatile uint32_t CTRL2_0073; - volatile uint32_t CTRL2_0074; - volatile uint32_t CTRL2_0075; - volatile uint32_t CTRL2_0076; - uint32_t RSVD5[1]; - volatile uint32_t CTRL2_0100; - volatile uint32_t CTRL2_0101; - volatile uint32_t CTRL2_0102; - uint32_t RSVD6[1]; - volatile uint32_t CTRL2_0104; - volatile uint32_t CTRL2_0105; - volatile uint32_t CTRL2_0106; - volatile uint32_t CTRL2_0107; - uint32_t RSVD7[2]; - volatile uint32_t CTRL2_0112; - volatile uint32_t CTRL2_0113; - volatile uint32_t CTRL2_0114; - volatile uint32_t CTRL2_0115; - volatile uint32_t CTRL2_0116; - volatile uint32_t CTRL2_0117; - volatile uint32_t CTRL2_0120; - volatile uint32_t CTRL2_0121; - volatile uint32_t CTRL2_0122; - volatile uint32_t CTRL2_0123; - volatile uint32_t CTRL2_0124; - volatile uint32_t CTRL2_0125; - volatile uint32_t CTRL2_0126; - volatile uint32_t CTRL2_0127; - volatile uint32_t CTRL2_0130; - volatile uint32_t CTRL2_0131; - volatile uint32_t CTRL2_0132; - uint32_t RSVD9[5]; - volatile uint32_t CTRL2_0140; - volatile uint32_t CTRL2_0141; - volatile uint32_t CTRL2_0142; - volatile uint32_t CTRL2_0143; - volatile uint32_t CTRL2_0144; - volatile uint32_t CTRL2_0145; - volatile uint32_t CTRL2_0146; - volatile uint32_t CTRL2_0147; - volatile uint32_t CTRL2_0150; - volatile uint32_t CTRL2_0151; - volatile uint32_t CTRL2_0152; - volatile uint32_t CTRL2_0153; - volatile uint32_t CTRL2_0154; - volatile uint32_t CTRL2_0155; - volatile uint32_t CTRL2_0156; - volatile uint32_t CTRL2_0157; - uint32_t RSVD10[1]; - volatile uint32_t CTRL2_0161; - volatile uint32_t CTRL2_0162; - uint32_t RSVD11[2]; - volatile uint32_t CTRL2_0165; - uint32_t RSVD12[2]; - volatile uint32_t CTRL2_0170; - volatile uint32_t CTRL2_0171; - uint32_t RSVD13[3]; - volatile uint32_t CTRL2_0175; - uint32_t RSVD14[2]; - volatile uint32_t CTRL2_0200; - volatile uint32_t CTRL2_0201; - volatile uint32_t CTRL2_0202; - volatile uint32_t CTRL2_0203; - volatile uint32_t CTRL2_0204; - volatile uint32_t CTRL2_0205; - volatile uint32_t CTRL2_0206; - volatile uint32_t CTRL2_0207; - uint32_t RSVD15[9]; - volatile uint32_t CTRL2_0221; - volatile uint32_t CTRL2_0222; - volatile uint32_t CTRL2_0223; - volatile uint32_t CTRL2_0224; - uint32_t RSVD16[1]; - volatile uint32_t CTRL2_0226; - volatile uint32_t CTRL2_0227; - uint32_t RSVD17[8]; - volatile uint32_t CTRL2_0240; - volatile uint32_t CTRL2_0241; - volatile uint32_t CTRL2_0242; - volatile uint32_t CTRL2_0243; - volatile uint32_t CTRL2_0244; - volatile uint32_t CTRL2_0245; - volatile uint32_t CTRL2_0246; - uint32_t RSVD18[5]; - volatile uint32_t CTRL2_0254; - volatile uint32_t CTRL2_0255; -}; - -/** @brief GPIO Parallel Input register. 32 GPIO pins per bank */ -struct gpio_parin_regs { - volatile uint32_t PARIN0; - volatile uint32_t PARIN1; - volatile uint32_t PARIN2; - volatile uint32_t PARIN3; - volatile uint32_t PARIN4; - volatile uint32_t PARIN5; -}; - -/** @brief GPIO Parallel Output register. 32 GPIO pins per bank */ -struct gpio_parout_regs { - volatile uint32_t PAROUT0; - volatile uint32_t PAROUT1; - volatile uint32_t PAROUT2; - volatile uint32_t PAROUT3; - volatile uint32_t PAROUT4; - volatile uint32_t PAROUT5; -}; - -/** @brief GPIO Lock registers. 32 GPIO pins per bank. Write-once bits */ -struct gpio_lock_regs { - volatile uint32_t LOCK5; - volatile uint32_t LOCK4; - volatile uint32_t LOCK3; - volatile uint32_t LOCK2; - volatile uint32_t LOCK1; - volatile uint32_t LOCK0; -}; - #ifdef __cplusplus } #endif diff --git a/soc/arm/microchip_mec/mec172x/timing.c b/soc/arm/microchip_mec/mec172x/timing.c index c415e3223d5..8dafb73544c 100644 --- a/soc/arm/microchip_mec/mec172x/timing.c +++ b/soc/arm/microchip_mec/mec172x/timing.c @@ -5,7 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include #include #include diff --git a/soc/arm/nordic_nrf/Kconfig.peripherals b/soc/arm/nordic_nrf/Kconfig.peripherals index 1645cf34ea0..2b7791bf5e6 100644 --- a/soc/arm/nordic_nrf/Kconfig.peripherals +++ b/soc/arm/nordic_nrf/Kconfig.peripherals @@ -13,11 +13,11 @@ config HAS_HW_NRF_BPROT def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_BPROT)) config HAS_HW_NRF_CC310 - def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_CC310)) || \ + def_bool $(dt_compat_enabled,$(DT_COMPAT_ARM_CRYPTOCELL_310)) || \ ($(dt_nodelabel_enabled,psa_rng) && SOC_SERIES_NRF91X) config HAS_HW_NRF_CC312 - def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_CC312)) || \ + def_bool $(dt_compat_enabled,$(DT_COMPAT_ARM_CRYPTOCELL_312)) || \ ($(dt_nodelabel_enabled,psa_rng) && SOC_NRF5340_CPUAPP) config HAS_HW_NRF_CCM @@ -77,6 +77,9 @@ config HAS_HW_NRF_GPIOTE config HAS_HW_NRF_I2S0 def_bool $(dt_nodelabel_enabled_with_compat,i2s0,$(DT_COMPAT_NORDIC_NRF_I2S)) +config HAS_HW_NRF_I2S20 + def_bool $(dt_nodelabel_enabled_with_compat,i2s20,$(DT_COMPAT_NORDIC_NRF_I2S)) + config HAS_HW_NRF_IPC def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_IPC)) @@ -131,6 +134,18 @@ config HAS_HW_NRF_QDEC0 config HAS_HW_NRF_QDEC1 def_bool $(dt_nodelabel_enabled_with_compat,qdec1,$(DT_COMPAT_NORDIC_NRF_QDEC)) +config HAS_HW_NRF_QDEC20 + def_bool $(dt_nodelabel_enabled_with_compat,qdec20,$(DT_COMPAT_NORDIC_NRF_QDEC)) + +config HAS_HW_NRF_QDEC21 + def_bool $(dt_nodelabel_enabled_with_compat,qdec21,$(DT_COMPAT_NORDIC_NRF_QDEC)) + +config HAS_HW_NRF_QDEC130 + def_bool $(dt_nodelabel_enabled_with_compat,qdec130,$(DT_COMPAT_NORDIC_NRF_QDEC)) + +config HAS_HW_NRF_QDEC131 + def_bool $(dt_nodelabel_enabled_with_compat,qdec131,$(DT_COMPAT_NORDIC_NRF_QDEC)) + config HAS_HW_NRF_QSPI def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_QSPI)) @@ -194,6 +209,51 @@ config HAS_HW_NRF_SPIM3 config HAS_HW_NRF_SPIM4 def_bool $(dt_nodelabel_enabled_with_compat,spi4,$(DT_COMPAT_NORDIC_NRF_SPIM)) +config HAS_HW_NRF_SPIM00 + def_bool $(dt_nodelabel_enabled_with_compat,spi00,$(DT_COMPAT_NORDIC_NRF_SPIM)) + +config HAS_HW_NRF_SPIM20 + def_bool $(dt_nodelabel_enabled_with_compat,spi20,$(DT_COMPAT_NORDIC_NRF_SPIM)) + +config HAS_HW_NRF_SPIM21 + def_bool $(dt_nodelabel_enabled_with_compat,spi21,$(DT_COMPAT_NORDIC_NRF_SPIM)) + +config HAS_HW_NRF_SPIM22 + def_bool $(dt_nodelabel_enabled_with_compat,spi22,$(DT_COMPAT_NORDIC_NRF_SPIM)) + +config HAS_HW_NRF_SPIM30 + def_bool $(dt_nodelabel_enabled_with_compat,spi30,$(DT_COMPAT_NORDIC_NRF_SPIM)) + +config HAS_HW_NRF_SPIM120 + def_bool $(dt_nodelabel_enabled_with_compat,spi120,$(DT_COMPAT_NORDIC_NRF_SPIM)) + +config HAS_HW_NRF_SPIM121 + def_bool $(dt_nodelabel_enabled_with_compat,spi121,$(DT_COMPAT_NORDIC_NRF_SPIM)) + +config HAS_HW_NRF_SPIM130 + def_bool $(dt_nodelabel_enabled_with_compat,spi130,$(DT_COMPAT_NORDIC_NRF_SPIM)) + +config HAS_HW_NRF_SPIM131 + def_bool $(dt_nodelabel_enabled_with_compat,spi131,$(DT_COMPAT_NORDIC_NRF_SPIM)) + +config HAS_HW_NRF_SPIM132 + def_bool $(dt_nodelabel_enabled_with_compat,spi132,$(DT_COMPAT_NORDIC_NRF_SPIM)) + +config HAS_HW_NRF_SPIM133 + def_bool $(dt_nodelabel_enabled_with_compat,spi133,$(DT_COMPAT_NORDIC_NRF_SPIM)) + +config HAS_HW_NRF_SPIM134 + def_bool $(dt_nodelabel_enabled_with_compat,spi134,$(DT_COMPAT_NORDIC_NRF_SPIM)) + +config HAS_HW_NRF_SPIM135 + def_bool $(dt_nodelabel_enabled_with_compat,spi135,$(DT_COMPAT_NORDIC_NRF_SPIM)) + +config HAS_HW_NRF_SPIM136 + def_bool $(dt_nodelabel_enabled_with_compat,spi136,$(DT_COMPAT_NORDIC_NRF_SPIM)) + +config HAS_HW_NRF_SPIM137 + def_bool $(dt_nodelabel_enabled_with_compat,spi137,$(DT_COMPAT_NORDIC_NRF_SPIM)) + config HAS_HW_NRF_SPIS0 def_bool $(dt_nodelabel_enabled_with_compat,spi0,$(DT_COMPAT_NORDIC_NRF_SPIS)) @@ -263,6 +323,45 @@ config HAS_HW_NRF_TWIM2 config HAS_HW_NRF_TWIM3 def_bool $(dt_nodelabel_enabled_with_compat,i2c3,$(DT_COMPAT_NORDIC_NRF_TWIM)) +config HAS_HW_NRF_TWIM20 + def_bool $(dt_nodelabel_enabled_with_compat,i2c20,$(DT_COMPAT_NORDIC_NRF_TWIM)) + +config HAS_HW_NRF_TWIM21 + def_bool $(dt_nodelabel_enabled_with_compat,i2c21,$(DT_COMPAT_NORDIC_NRF_TWIM)) + +config HAS_HW_NRF_TWIM22 + def_bool $(dt_nodelabel_enabled_with_compat,i2c22,$(DT_COMPAT_NORDIC_NRF_TWIM)) + +config HAS_HW_NRF_TWIM30 + def_bool $(dt_nodelabel_enabled_with_compat,i2c30,$(DT_COMPAT_NORDIC_NRF_TWIM)) + +config HAS_HW_NRF_TWIM120 + def_bool $(dt_nodelabel_enabled_with_compat,i2c120,$(DT_COMPAT_NORDIC_NRF_TWIM)) + +config HAS_HW_NRF_TWIM130 + def_bool $(dt_nodelabel_enabled_with_compat,i2c130,$(DT_COMPAT_NORDIC_NRF_TWIM)) + +config HAS_HW_NRF_TWIM131 + def_bool $(dt_nodelabel_enabled_with_compat,i2c131,$(DT_COMPAT_NORDIC_NRF_TWIM)) + +config HAS_HW_NRF_TWIM132 + def_bool $(dt_nodelabel_enabled_with_compat,i2c132,$(DT_COMPAT_NORDIC_NRF_TWIM)) + +config HAS_HW_NRF_TWIM133 + def_bool $(dt_nodelabel_enabled_with_compat,i2c133,$(DT_COMPAT_NORDIC_NRF_TWIM)) + +config HAS_HW_NRF_TWIM134 + def_bool $(dt_nodelabel_enabled_with_compat,i2c134,$(DT_COMPAT_NORDIC_NRF_TWIM)) + +config HAS_HW_NRF_TWIM135 + def_bool $(dt_nodelabel_enabled_with_compat,i2c135,$(DT_COMPAT_NORDIC_NRF_TWIM)) + +config HAS_HW_NRF_TWIM136 + def_bool $(dt_nodelabel_enabled_with_compat,i2c136,$(DT_COMPAT_NORDIC_NRF_TWIM)) + +config HAS_HW_NRF_TWIM137 + def_bool $(dt_nodelabel_enabled_with_compat,i2c137,$(DT_COMPAT_NORDIC_NRF_TWIM)) + config HAS_HW_NRF_TWIS0 def_bool $(dt_nodelabel_enabled_with_compat,i2c0,$(DT_COMPAT_NORDIC_NRF_TWIS)) diff --git a/soc/arm/nordic_nrf/nrf51/CMakeLists.txt b/soc/arm/nordic_nrf/nrf51/CMakeLists.txt index 1a8b943ad5b..44d139e422a 100644 --- a/soc/arm/nordic_nrf/nrf51/CMakeLists.txt +++ b/soc/arm/nordic_nrf/nrf51/CMakeLists.txt @@ -10,3 +10,5 @@ zephyr_library_include_directories( ${ZEPHYR_BASE}/kernel/include ${ZEPHYR_BASE}/arch/arm/include ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nordic_nrf/nrf51/Kconfig.series b/soc/arm/nordic_nrf/nrf51/Kconfig.series index e7028b02190..c484d44fc30 100644 --- a/soc/arm/nordic_nrf/nrf51/Kconfig.series +++ b/soc/arm/nordic_nrf/nrf51/Kconfig.series @@ -9,7 +9,7 @@ config SOC_SERIES_NRF51X select ARM select CPU_CORTEX_M0 select SOC_FAMILY_NRF - select XIP + imply XIP select HAS_NRFX select HAS_SEGGER_RTT if ZEPHYR_SEGGER_MODULE select HAS_POWEROFF diff --git a/soc/arm/nordic_nrf/nrf51/linker.ld b/soc/arm/nordic_nrf/nrf51/linker.ld deleted file mode 100644 index 96ec397da78..00000000000 --- a/soc/arm/nordic_nrf/nrf51/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/nordic_nrf/nrf52/CMakeLists.txt b/soc/arm/nordic_nrf/nrf52/CMakeLists.txt index 06fddff5f06..04e255a3eb1 100644 --- a/soc/arm/nordic_nrf/nrf52/CMakeLists.txt +++ b/soc/arm/nordic_nrf/nrf52/CMakeLists.txt @@ -14,3 +14,13 @@ zephyr_library_include_directories( if(CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58 AND CONFIG_SPI_NRFX_SPIM) message(WARNING "Both SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58 and an NRF SPIM driver are enabled, therefore PAN 58 will apply if RXD.MAXCNT == 1 and TXD.MAXCNT <= 1") endif() + +if(CONFIG_SOC_NRF52832) + if(NOT CONFIG_NRF52_ANOMALY_109_WORKAROUND) + if (CONFIG_NRFX_SPIS OR CONFIG_NRFX_SPIM OR CONFIG_NRFX_TWIM OR CONFIG_NRFX_PWM) + message(WARNING "NRF52_ANOMALY_109_WORKAROUND disabled with SPIS, SPIM, TWIM or PWM enabled. This will occasionally cause the first byte transmitted to be incorrect") + endif() + endif() +endif() + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nordic_nrf/nrf52/Kconfig.series b/soc/arm/nordic_nrf/nrf52/Kconfig.series index f11bd5cd59f..d47089cd595 100644 --- a/soc/arm/nordic_nrf/nrf52/Kconfig.series +++ b/soc/arm/nordic_nrf/nrf52/Kconfig.series @@ -10,7 +10,7 @@ config SOC_SERIES_NRF52X select CPU_CORTEX_M4 select CPU_HAS_ARM_MPU select SOC_FAMILY_NRF - select XIP + imply XIP select HAS_NRFX select HAS_NORDIC_DRIVERS select HAS_SEGGER_RTT if ZEPHYR_SEGGER_MODULE diff --git a/soc/arm/nordic_nrf/nrf52/Kconfig.soc b/soc/arm/nordic_nrf/nrf52/Kconfig.soc index b2a915f168e..de6a16129d3 100644 --- a/soc/arm/nordic_nrf/nrf52/Kconfig.soc +++ b/soc/arm/nordic_nrf/nrf52/Kconfig.soc @@ -136,4 +136,23 @@ config NRF52_ANOMALY_198_WORKAROUND This anomaly applies to IC revisions "Engineering B" up to "3", the most recent one. +config NRF52_ANOMALY_109_WORKAROUND + bool "Anomaly 109 workaround" + default y + depends on SOC_NRF52832 + depends on NRFX_SPIS || NRFX_SPIM || NRFX_TWIM || NRFX_PWM + help + Due to Anomaly 109 the first byte sent out by these peripherals is + sometimes wrong. This occurs when the system enters IDLE and stops the + 64MHz clock at the same time as the peripheral that is using DMA is started. + This anomaly applies to IC revisions up to "3", the most recent one. + +config NRF52_ANOMALY_109_WORKAROUND_EGU_INSTANCE + int "Anomaly 109 workaround EGU instance" + depends on NRF52_ANOMALY_109_WORKAROUND + range 0 5 + default 5 + help + EGU instance used by the nRF52 Anomaly 109 workaround for PWM. + endif # SOC_SERIES_NRF52X diff --git a/soc/arm/nordic_nrf/nrf52/linker.ld b/soc/arm/nordic_nrf/nrf52/linker.ld deleted file mode 100644 index 96ec397da78..00000000000 --- a/soc/arm/nordic_nrf/nrf52/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/nordic_nrf/nrf53/CMakeLists.txt b/soc/arm/nordic_nrf/nrf53/CMakeLists.txt index af4fe549a63..b4e82f52c28 100644 --- a/soc/arm/nordic_nrf/nrf53/CMakeLists.txt +++ b/soc/arm/nordic_nrf/nrf53/CMakeLists.txt @@ -19,3 +19,5 @@ if (CONFIG_SOC_NRF53_ANOMALY_160_WORKAROUND_NEEDED AND At your own risk, you can suppress this warning by setting CONFIG_SOC_NRF53_ANOMALY_160_WORKAROUND_NEEDED=n.") endif() + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nordic_nrf/nrf53/Kconfig.series b/soc/arm/nordic_nrf/nrf53/Kconfig.series index 8ab81ad310b..28d1c10fc1e 100644 --- a/soc/arm/nordic_nrf/nrf53/Kconfig.series +++ b/soc/arm/nordic_nrf/nrf53/Kconfig.series @@ -11,7 +11,7 @@ config SOC_SERIES_NRF53X select CPU_CORTEX_M_HAS_DWT select CPU_HAS_ARM_MPU select SOC_FAMILY_NRF - select XIP + imply XIP select HAS_NRFX select HAS_NORDIC_DRIVERS select HAS_SEGGER_RTT if ZEPHYR_SEGGER_MODULE diff --git a/soc/arm/nordic_nrf/nrf53/Kconfig.soc b/soc/arm/nordic_nrf/nrf53/Kconfig.soc index 1c8527e1716..f72ae5ab004 100644 --- a/soc/arm/nordic_nrf/nrf53/Kconfig.soc +++ b/soc/arm/nordic_nrf/nrf53/Kconfig.soc @@ -214,78 +214,6 @@ config BUILD_WITH_TFM # TF-M nRF53 platform enables the cache unconditionally. select NRF_ENABLE_CACHE if SOC_NRF5340_CPUAPP -config NRF53_SYNC_RTC - bool "RTC clock synchronization" - default y if LOG && !LOG_MODE_MINIMAL - depends on NRF_RTC_TIMER - select NRFX_DPPI - select MBOX if !IPM - -if NRF53_SYNC_RTC - -module = SYNC_RTC -module-str = Synchronized RTC -source "subsys/logging/Kconfig.template.log_config" - -config NRF53_SYNC_RTC_INIT_PRIORITY - int "nRF53 Synchronized RTC init priority" - default APPLICATION_INIT_PRIORITY - help - nRF53 Synchronized RTC initialization priority. - -config NRF_RTC_TIMER_USER_CHAN_COUNT - default 2 if NRF_802154_RADIO_DRIVER && SOC_NRF5340_CPUNET - default 3 if NRF_802154_RADIO_DRIVER - default 1 +rsource "Kconfig.sync_rtc" -config NRF53_SYNC_RTC_LOG_TIMESTAMP - bool "Use Synchronized RTC for logging timestamp" - default y - -config NRF53_SYNC_RTC_IPM_OUT - int "IPM channel from APP to NET" - range 0 15 - default 7 if SOC_NRF5340_CPUAPP - default 8 - -config NRF53_SYNC_RTC_IPM_IN - int "IPM channel from APP to NET" - range 0 15 - default 8 if SOC_NRF5340_CPUAPP - default 7 - -ipm_num = 0 -rsource "Kconfig.sync_rtc_ipm" -ipm_num = 1 -rsource "Kconfig.sync_rtc_ipm" -ipm_num = 2 -rsource "Kconfig.sync_rtc_ipm" -ipm_num = 3 -rsource "Kconfig.sync_rtc_ipm" -ipm_num = 4 -rsource "Kconfig.sync_rtc_ipm" -ipm_num = 5 -rsource "Kconfig.sync_rtc_ipm" -ipm_num = 6 -rsource "Kconfig.sync_rtc_ipm" -ipm_num = 7 -rsource "Kconfig.sync_rtc_ipm" -ipm_num = 8 -rsource "Kconfig.sync_rtc_ipm" -ipm_num = 9 -rsource "Kconfig.sync_rtc_ipm" -ipm_num = 10 -rsource "Kconfig.sync_rtc_ipm" -ipm_num = 11 -rsource "Kconfig.sync_rtc_ipm" -ipm_num = 12 -rsource "Kconfig.sync_rtc_ipm" -ipm_num = 13 -rsource "Kconfig.sync_rtc_ipm" -ipm_num = 14 -rsource "Kconfig.sync_rtc_ipm" -ipm_num = 15 -rsource "Kconfig.sync_rtc_ipm" - -endif # NRF53_SYNC_RTC endif # SOC_SERIES_NRF53X diff --git a/soc/arm/nordic_nrf/nrf53/Kconfig.sync_rtc b/soc/arm/nordic_nrf/nrf53/Kconfig.sync_rtc new file mode 100644 index 00000000000..475db911c67 --- /dev/null +++ b/soc/arm/nordic_nrf/nrf53/Kconfig.sync_rtc @@ -0,0 +1,77 @@ +# Copyright (c) 2019 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config NRF53_SYNC_RTC + bool "RTC clock synchronization" + default y if LOG && !LOG_MODE_MINIMAL + depends on NRF_RTC_TIMER + select NRFX_DPPI + select MBOX if !IPM + +if NRF53_SYNC_RTC + +module = SYNC_RTC +module-str = Synchronized RTC +source "subsys/logging/Kconfig.template.log_config" + +config NRF53_SYNC_RTC_INIT_PRIORITY + int "nRF53 Synchronized RTC init priority" + default APPLICATION_INIT_PRIORITY + help + nRF53 Synchronized RTC initialization priority. + +config NRF_RTC_TIMER_USER_CHAN_COUNT + default 2 if NRF_802154_RADIO_DRIVER && SOC_COMPATIBLE_NRF5340_CPUNET + default 3 if NRF_802154_RADIO_DRIVER + default 1 + +config NRF53_SYNC_RTC_LOG_TIMESTAMP + bool "Use Synchronized RTC for logging timestamp" + default y + +config NRF53_SYNC_RTC_IPM_OUT + int "IPM channel from APP to NET" + range 0 15 + default 7 if SOC_COMPATIBLE_NRF5340_CPUAPP + default 8 + +config NRF53_SYNC_RTC_IPM_IN + int "IPM channel from APP to NET" + range 0 15 + default 8 if SOC_COMPATIBLE_NRF5340_CPUAPP + default 7 + +ipm_num = 0 +rsource "Kconfig.sync_rtc_ipm" +ipm_num = 1 +rsource "Kconfig.sync_rtc_ipm" +ipm_num = 2 +rsource "Kconfig.sync_rtc_ipm" +ipm_num = 3 +rsource "Kconfig.sync_rtc_ipm" +ipm_num = 4 +rsource "Kconfig.sync_rtc_ipm" +ipm_num = 5 +rsource "Kconfig.sync_rtc_ipm" +ipm_num = 6 +rsource "Kconfig.sync_rtc_ipm" +ipm_num = 7 +rsource "Kconfig.sync_rtc_ipm" +ipm_num = 8 +rsource "Kconfig.sync_rtc_ipm" +ipm_num = 9 +rsource "Kconfig.sync_rtc_ipm" +ipm_num = 10 +rsource "Kconfig.sync_rtc_ipm" +ipm_num = 11 +rsource "Kconfig.sync_rtc_ipm" +ipm_num = 12 +rsource "Kconfig.sync_rtc_ipm" +ipm_num = 13 +rsource "Kconfig.sync_rtc_ipm" +ipm_num = 14 +rsource "Kconfig.sync_rtc_ipm" +ipm_num = 15 +rsource "Kconfig.sync_rtc_ipm" + +endif # NRF53_SYNC_RTC diff --git a/soc/arm/nordic_nrf/nrf53/linker.ld b/soc/arm/nordic_nrf/nrf53/linker.ld deleted file mode 100644 index 96ec397da78..00000000000 --- a/soc/arm/nordic_nrf/nrf53/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/nordic_nrf/nrf53/sync_rtc.c b/soc/arm/nordic_nrf/nrf53/sync_rtc.c index 235e9f26001..031f93244f7 100644 --- a/soc/arm/nordic_nrf/nrf53/sync_rtc.c +++ b/soc/arm/nordic_nrf/nrf53/sync_rtc.c @@ -119,7 +119,7 @@ static void free_resources(union rtc_sync_channels channels) int z_nrf_rtc_timer_nrf53net_offset_get(void) { - if (!IS_ENABLED(CONFIG_SOC_NRF5340_CPUNET)) { + if (!IS_ENABLED(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET)) { return -ENOSYS; } @@ -135,7 +135,7 @@ static void rtc_cb(int32_t id, uint64_t cc_value, void *user_data) channels.raw = (uint32_t)user_data; ppi_rtc_to_ipc(channels, false); - if (IS_ENABLED(CONFIG_SOC_NRF5340_CPUAPP)) { + if (IS_ENABLED(CONFIG_SOC_COMPATIBLE_NRF5340_CPUAPP)) { /* APP: Synchronized completed */ free_resources(channels); } else { @@ -165,7 +165,7 @@ static void remote_callback(void *user_data) /* Clear previous task,event */ ppi_ipc_to_rtc(channels, false); - if (IS_ENABLED(CONFIG_SOC_NRF5340_CPUAPP)) { + if (IS_ENABLED(CONFIG_SOC_COMPATIBLE_NRF5340_CPUAPP)) { /* Setup new connection from RTC to IPC and set RTC to a new * interval that contains captured offset. */ @@ -258,7 +258,7 @@ static int sync_rtc_setup(void) nrfx_gppi_channels_enable(BIT(channels.ch.ppi)); - if (IS_ENABLED(CONFIG_SOC_NRF5340_CPUAPP)) { + if (IS_ENABLED(CONFIG_SOC_COMPATIBLE_NRF5340_CPUAPP)) { ppi_ipc_to_rtc(channels, true); } else { ppi_rtc_to_ipc(channels, true); diff --git a/soc/arm/nordic_nrf/nrf91/CMakeLists.txt b/soc/arm/nordic_nrf/nrf91/CMakeLists.txt index 332416ba43b..7424bb9f7b9 100644 --- a/soc/arm/nordic_nrf/nrf91/CMakeLists.txt +++ b/soc/arm/nordic_nrf/nrf91/CMakeLists.txt @@ -3,3 +3,5 @@ zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nordic_nrf/nrf91/Kconfig.series b/soc/arm/nordic_nrf/nrf91/Kconfig.series index 9e0e477e851..08d36e5b48c 100644 --- a/soc/arm/nordic_nrf/nrf91/Kconfig.series +++ b/soc/arm/nordic_nrf/nrf91/Kconfig.series @@ -13,7 +13,7 @@ config SOC_SERIES_NRF91X select CPU_HAS_FPU select ARMV8_M_DSP select SOC_FAMILY_NRF - select XIP + imply XIP select HAS_NRFX select HAS_SEGGER_RTT if ZEPHYR_SEGGER_MODULE select HAS_POWEROFF diff --git a/soc/arm/nordic_nrf/nrf91/linker.ld b/soc/arm/nordic_nrf/nrf91/linker.ld deleted file mode 100644 index 96ec397da78..00000000000 --- a/soc/arm/nordic_nrf/nrf91/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/nordic_nrf/timing.c b/soc/arm/nordic_nrf/timing.c index e75be5f9cdb..402e97f2141 100644 --- a/soc/arm/nordic_nrf/timing.c +++ b/soc/arm/nordic_nrf/timing.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include #include #include diff --git a/soc/arm/nuvoton_npcx/common/reg/reg_def.h b/soc/arm/nuvoton_npcx/common/reg/reg_def.h index afcb0597f1e..e9ef3460e63 100644 --- a/soc/arm/nuvoton_npcx/common/reg/reg_def.h +++ b/soc/arm/nuvoton_npcx/common/reg/reg_def.h @@ -228,49 +228,17 @@ struct scfg_reg { volatile uint8_t LV_GPIO_CTL0[5]; }; -/* SCFG internal inline functions for multi-registers */ -static inline uint32_t npcx_devalt_offset(uint32_t alt_no) -{ - return 0x010 + alt_no; -} - -static inline uint32_t npcx_devalt_lk_offset(uint32_t alt_lk_no) -{ - return 0x210 + alt_lk_no; -} - -static inline uint32_t npcx_pupd_en_offset(uint32_t pupd_en_no) -{ - if (IS_ENABLED(CONFIG_SOC_SERIES_NPCX7) || IS_ENABLED(CONFIG_SOC_SERIES_NPCX9)) { - return 0x28 + pupd_en_no; - } else { /* NPCX4 and later series */ - return 0x2b + pupd_en_no; - } -} - -static inline uint32_t npcx_lv_gpio_ctl_offset(uint32_t ctl_no) -{ - if (IS_ENABLED(CONFIG_SOC_SERIES_NPCX7) || IS_ENABLED(CONFIG_SOC_SERIES_NPCX9)) { - if (ctl_no < 5) { - return 0x02a + ctl_no; - } else { - return 0x026 + ctl_no - 5; - } - } else { /* NPCX4 and later series */ - return 0x150 + ctl_no; - } -} - /* Macro functions for SCFG multi-registers */ -#define NPCX_DEV_CTL(base, n) (*(volatile uint8_t *)(base + n)) -#define NPCX_DEVALT(base, n) (*(volatile uint8_t *)(base + \ - npcx_devalt_offset(n))) -#define NPCX_DEVALT_LK(base, n) (*(volatile uint8_t *)(base + \ - npcx_devalt_lk_offset(n))) -#define NPCX_PUPD_EN(base, n) (*(volatile uint8_t *)(base + \ - npcx_pupd_en_offset(n))) -#define NPCX_LV_GPIO_CTL(base, n) (*(volatile uint8_t *)(base + \ - npcx_lv_gpio_ctl_offset(n))) +#define NPCX_DEV_CTL(base, n) \ + (*(volatile uint8_t *)(base + n)) +#define NPCX_DEVALT(base, n) \ + (*(volatile uint8_t *)(base + NPCX_DEVALT_OFFSET(n))) +#define NPCX_DEVALT_LK(base, n) \ + (*(volatile uint8_t *)(base + NPCX_DEVALT_LK_OFFSET(n))) +#define NPCX_PUPD_EN(base, n) \ + (*(volatile uint8_t *)(base + NPCX_PUPD_EN_OFFSET(n))) +#define NPCX_LV_GPIO_CTL(base, n) \ + (*(volatile uint8_t *)(base + NPCX_LV_GPIO_CTL_OFFSET(n))) /* SCFG register fields */ #define NPCX_DEVCNT_F_SPI_TRIS 6 @@ -413,95 +381,21 @@ struct uart_reg { #define NPCX_UFRCTL_RNEMPTY_EN 6 #define NPCX_UFRCTL_ERR_EN 7 -/* - * Multi-Input Wake-Up Unit (MIWU) device registers - */ - -/* MIWU internal inline functions for multi-registers */ -static inline uint32_t npcx_wkedg_offset(uint32_t group) -{ - if (IS_ENABLED(CONFIG_SOC_SERIES_NPCX7)) { - return 0x000 + (group * 2ul) + (group < 5 ? 0 : 0x1e); - } else { /* NPCX9 and later series */ - return 0x000 + group * 0x10UL; - } -} - -static inline uint32_t npcx_wkaedg_offset(uint32_t group) -{ - if (IS_ENABLED(CONFIG_SOC_SERIES_NPCX7)) { - return 0x001 + (group * 2ul) + (group < 5 ? 0 : 0x1e); - } else { /* NPCX9 and later series */ - return 0x001 + group * 0x10ul; - } -} - -static inline uint32_t npcx_wkmod_offset(uint32_t group) -{ - if (IS_ENABLED(CONFIG_SOC_SERIES_NPCX7)) { - return 0x070 + group; - } else { /* NPCX9 and later series */ - return 0x002 + group * 0x10ul; - } -} - -static inline uint32_t npcx_wkpnd_offset(uint32_t group) -{ - if (IS_ENABLED(CONFIG_SOC_SERIES_NPCX7)) { - return 0x00a + (group * 4ul) + (group < 5 ? 0 : 0x10); - } else { /* NPCX9 and later series */ - return 0x003 + group * 0x10ul; - } -} - -static inline uint32_t npcx_wkpcl_offset(uint32_t group) -{ - if (IS_ENABLED(CONFIG_SOC_SERIES_NPCX7)) { - return 0x00c + (group * 4ul) + (group < 5 ? 0 : 0x10); - } else { /* NPCX9 and later series */ - return 0x004 + group * 0x10ul; - } -} - -static inline uint32_t npcx_wken_offset(uint32_t group) -{ - if (IS_ENABLED(CONFIG_SOC_SERIES_NPCX7)) { - return 0x01e + (group * 2ul) + (group < 5 ? 0 : 0x12); - } else { /* NPCX9 and later series */ - return 0x005 + group * 0x10ul; - } -} - -static inline uint32_t npcx_wkst_offset(uint32_t group) -{ - /* NPCX9 and later series only */ - return 0x006 + group * 0x10ul; -} - -static inline uint32_t npcx_wkinen_offset(uint32_t group) -{ - if (IS_ENABLED(CONFIG_SOC_SERIES_NPCX7)) { - return 0x01f + (group * 2ul) + (group < 5 ? 0 : 0x12); - } else { /* NPCX9 and later series */ - return 0x007 + group * 0x10ul; - } -} - /* Macro functions for MIWU multi-registers */ #define NPCX_WKEDG(base, group) \ - (*(volatile uint8_t *)(base + npcx_wkedg_offset(group))) + (*(volatile uint8_t *)(base + NPCX_WKEDG_OFFSET(group))) #define NPCX_WKAEDG(base, group) \ - (*(volatile uint8_t *)(base + npcx_wkaedg_offset(group))) + (*(volatile uint8_t *)(base + NPCX_WKAEDG_OFFSET(group))) #define NPCX_WKPND(base, group) \ - (*(volatile uint8_t *)(base + npcx_wkpnd_offset(group))) + (*(volatile uint8_t *)(base + NPCX_WKPND_OFFSET(group))) #define NPCX_WKPCL(base, group) \ - (*(volatile uint8_t *)(base + npcx_wkpcl_offset(group))) + (*(volatile uint8_t *)(base + NPCX_WKPCL_OFFSET(group))) #define NPCX_WKEN(base, group) \ - (*(volatile uint8_t *)(base + npcx_wken_offset(group))) + (*(volatile uint8_t *)(base + NPCX_WKEN_OFFSET(group))) #define NPCX_WKINEN(base, group) \ - (*(volatile uint8_t *)(base + npcx_wkinen_offset(group))) + (*(volatile uint8_t *)(base + NPCX_WKINEN_OFFSET(group))) #define NPCX_WKMOD(base, group) \ - (*(volatile uint8_t *)(base + npcx_wkmod_offset(group))) + (*(volatile uint8_t *)(base + NPCX_WKMOD_OFFSET(group))) /* * General-Purpose I/O (GPIO) device registers @@ -566,7 +460,9 @@ struct adc_reg { volatile uint16_t ASCADD; /* 0x008: ADC Scan Channels Select */ volatile uint16_t ADCCS; - volatile uint8_t reserved1[16]; + /* 0x00A: ADC Scan Channels Select 2 */ + volatile uint16_t ADCCS2; + volatile uint8_t reserved1[14]; /* 0x01A: Threshold Status */ volatile uint16_t THRCTS; volatile uint8_t reserved2[4]; @@ -579,12 +475,11 @@ struct adc_reg { volatile uint16_t MEAST; }; -static inline uint32_t npcx_chndat_offset(uint32_t ch) -{ - return 0x40 + ch * 2; -} - -#define CHNDAT(base, ch) (*(volatile uint16_t *)((base) + npcx_chndat_offset(ch))) +/* ADC internal inline functions for multi-registers */ +#define CHNDAT(base, ch) \ + (*(volatile uint16_t *)((base) + NPCX_CHNDAT_OFFSET(ch))) +#define THRCTL(base, ctrl) \ + (*(volatile uint16_t *)(base + NPCX_THRCTL_OFFSET(ctrl))) /* ADC register fields */ #define NPCX_ATCTL_SCLKDIV_FIELD FIELD(0, 6) @@ -604,10 +499,6 @@ static inline uint32_t npcx_chndat_offset(uint32_t ch) #define NPCX_ADCCNF_STOP 11 #define NPCX_CHNDAT_CHDAT_FIELD FIELD(0, 10) #define NPCX_CHNDAT_NEW 15 -#define NPCX_THRCTL_THEN 15 -#define NPCX_THRCTL_L_H 14 -#define NPCX_THRCTL_CHNSEL FIELD(10, 4) -#define NPCX_THRCTL_THRVAL FIELD(0, 10) #define NPCX_THRCTS_ADC_WKEN 15 #define NPCX_THRCTS_THR3_IEN 10 #define NPCX_THRCTS_THR2_IEN 9 @@ -1568,11 +1459,6 @@ struct fiu_reg { #define NPCX_SPI1_DEV_FOUR_BADDR_CS10 6 #define NPCX_SPI1_DEV_FOUR_BADDR_CS11 7 #define NPCX_SPI1_DEV_SPI1_LO_DEV_SIZE FIELD(0, 4) -#if defined(CONFIG_SOC_SERIES_NPCX9) -#define NPCX_FIU_EXT_CFG_SPI1_2DEV 7 -#else -#define NPCX_FIU_EXT_CFG_SPI1_2DEV 6 -#endif #define NPCX_FIU_EXT_CFG_SET_DMM_EN 2 #define NPCX_FIU_EXT_CFG_SET_CMD_EN 1 #define NPCX_SPI_DEV_NADDRB FIELD(5, 3) diff --git a/soc/arm/nuvoton_npcx/common/soc_clock.h b/soc/arm/nuvoton_npcx/common/soc_clock.h index cda024dc0df..d43a70d4529 100644 --- a/soc/arm/nuvoton_npcx/common/soc_clock.h +++ b/soc/arm/nuvoton_npcx/common/soc_clock.h @@ -44,11 +44,11 @@ struct npcx_clk_cfg { #define APB3DIV_VAL (DT_PROP(DT_NODELABEL(pcc), apb3_prescaler) - 1) /* APB4 clock divider if supported */ #if DT_NODE_HAS_PROP(DT_NODELABEL(pcc), apb4_prescaler) -#if !defined(CONFIG_SOC_SERIES_NPCX7) /* Supported in NPCX9 and later series */ +#if defined(CONFIG_CLOCK_CONTROL_NPCX_SUPP_APB4) /* Supported in NPCX9 and later series */ #define APB4DIV_VAL (DT_PROP(DT_NODELABEL(pcc), apb4_prescaler) - 1) #else #error "APB4 clock divider is not supported but defined in pcc node!" -#endif /* !CONFIG_SOC_SERIES_NPCX7 */ +#endif /* CONFIG_CLOCK_CONTROL_NPCX_SUPP_APB4 */ #endif /* Construct a uint8_t array from 'pwdwn-ctl-val' prop for PWDWN_CTL initialization. */ @@ -68,12 +68,6 @@ struct npcx_clk_cfg { * - CORE_CLK > MAX_OFMCLK/2, AHB6DIV should be 1, else 0. * - CORE_CLK > MAX_OFMCLK/2, FIUDIV should be 1, else 0. */ -#if defined(CONFIG_SOC_SERIES_NPCX4) -#define MAX_OFMCLK 120000000 -#else -#define MAX_OFMCLK 100000000 -#endif /* CONFIG_SOC_SERIES_NPCX4 */ - /* Core domain clock */ #define CORE_CLK (OFMCLK / DT_PROP(DT_NODELABEL(pcc), core_prescaler)) /* Low Frequency clock */ @@ -103,13 +97,13 @@ struct npcx_clk_cfg { #define FIUDIV_VAL 0 /* FIU_CLK = CORE_CLK */ #endif -#if defined(CONFIG_SOC_SERIES_NPCX4) +#if defined(CONFIG_CLOCK_CONTROL_NPCX_SUPP_FIU1) #if (CORE_CLK > (MAX_OFMCLK / 2)) #define FIU1DIV_VAL 1 /* FIU1_CLK = CORE_CLK/2 */ #else #define FIU1DIV_VAL 0 /* FIU1_CLK = CORE_CLK */ #endif -#endif /* CONFIG_SOC_SERIES_NPCX4 */ +#endif /* CONFIG_CLOCK_CONTROL_NPCX_SUPP_FIU1 */ /* Get APB clock freq */ #define NPCX_APB_CLOCK(no) (APBSRC_CLK / (APB##no##DIV_VAL + 1)) diff --git a/soc/arm/nuvoton_npcx/npcx4/CMakeLists.txt b/soc/arm/nuvoton_npcx/npcx4/CMakeLists.txt index ee55c1c2a5b..158ae5cbbc7 100644 --- a/soc/arm/nuvoton_npcx/npcx4/CMakeLists.txt +++ b/soc/arm/nuvoton_npcx/npcx4/CMakeLists.txt @@ -5,3 +5,5 @@ zephyr_include_directories(${ZEPHYR_BASE}/drivers) zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nuvoton_npcx/npcx4/Kconfig.series b/soc/arm/nuvoton_npcx/npcx4/Kconfig.series index 2eb4ac5d184..1585ace4e98 100644 --- a/soc/arm/nuvoton_npcx/npcx4/Kconfig.series +++ b/soc/arm/nuvoton_npcx/npcx4/Kconfig.series @@ -11,5 +11,6 @@ config SOC_SERIES_NPCX4 select CPU_HAS_FPU select CPU_HAS_ARM_MPU select SOC_FAMILY_NPCX + select HAS_PM help Enable support for Nuvoton NPCX4 series diff --git a/soc/arm/nuvoton_npcx/npcx4/linker.ld b/soc/arm/nuvoton_npcx/npcx4/linker.ld deleted file mode 100644 index 7b1a0772918..00000000000 --- a/soc/arm/nuvoton_npcx/npcx4/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2023 Nuvoton Technology Corporation. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/nuvoton_npcx/npcx4/soc.h b/soc/arm/nuvoton_npcx/npcx4/soc.h index e61c1e108f0..a9d4e88424b 100644 --- a/soc/arm/nuvoton_npcx/npcx4/soc.h +++ b/soc/arm/nuvoton_npcx/npcx4/soc.h @@ -11,6 +11,45 @@ #define __FPU_PRESENT CONFIG_CPU_HAS_FPU #define __MPU_PRESENT CONFIG_CPU_HAS_ARM_MPU +/* NPCX4 SCFG multi-registers */ +#define NPCX_DEVALT_OFFSET(n) (0x010 + n) +#define NPCX_PUPD_EN_OFFSET(n) (0x02b + n) +#define NPCX_LV_GPIO_CTL_OFFSET(n) (0x150 + n) +#define NPCX_DEVALT_LK_OFFSET(n) (0x210 + n) + +/* NPCX4 MIWU multi-registers */ +#define NPCX_WKEDG_OFFSET(n) (0x000 + (n * 0x010)) +#define NPCX_WKAEDG_OFFSET(n) (0x001 + (n * 0x010)) +#define NPCX_WKMOD_OFFSET(n) (0x002 + (n * 0x010)) +#define NPCX_WKPND_OFFSET(n) (0x003 + (n * 0x010)) +#define NPCX_WKPCL_OFFSET(n) (0x004 + (n * 0x010)) +#define NPCX_WKEN_OFFSET(n) (0x005 + (n * 0x010)) +#define NPCX_WKST_OFFSET(n) (0x006 + (n * 0x010)) +#define NPCX_WKINEN_OFFSET(n) (0x007 + (n * 0x010)) + +/* NPCX4 ADC multi-registers */ +#define NPCX_CHNDAT_OFFSET(n) (0x040 + n * 2) +#define NPCX_THRCTL_OFFSET(n) (0x080 + n * 2) +#define NPCX_THEN_OFFSET 0x090 +#define THEN(base) (*(volatile uint16_t *)(base + NPCX_THEN_OFFSET)) + +/* NPCX4 ADC register fields */ +#define NPCX_THRCTL_L_H 15 +#define NPCX_THRCTL_CHNSEL FIELD(10, 5) +#define NPCX_THRCTL_THRVAL FIELD(0, 10) + +/* NPCX4 FIU register fields */ +#define NPCX_FIU_EXT_CFG_SPI1_2DEV 6 + +/* NPCX4 supported group mask of DEVALT_LK */ +#define NPCX_DEVALT_LK_GROUP_MASK \ + (BIT(0) | BIT(2) | BIT(3) | BIT(4) | \ + BIT(5) | BIT(6) | BIT(11) | BIT(13) | \ + BIT(15) | BIT(16) | BIT(17) | BIT(18) | \ + BIT(19) | BIT(21)) /* DEVALT0_LK - DEVALTN_LK */ + +/* NPCX4 Clock Configuration */ +#define MAX_OFMCLK 120000000 #include #include diff --git a/soc/arm/nuvoton_npcx/npcx7/CMakeLists.txt b/soc/arm/nuvoton_npcx/npcx7/CMakeLists.txt index c4b945e8ad1..01792bf9fce 100644 --- a/soc/arm/nuvoton_npcx/npcx7/CMakeLists.txt +++ b/soc/arm/nuvoton_npcx/npcx7/CMakeLists.txt @@ -10,3 +10,5 @@ zephyr_sources_ifdef( CONFIG_ARM_MPU mpu_regions.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nuvoton_npcx/npcx7/linker.ld b/soc/arm/nuvoton_npcx/npcx7/linker.ld deleted file mode 100644 index 4856bf0a71d..00000000000 --- a/soc/arm/nuvoton_npcx/npcx7/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2020 Nuvoton Technology Corporation. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/nuvoton_npcx/npcx7/mpu_regions.c b/soc/arm/nuvoton_npcx/npcx7/mpu_regions.c index 7592a2e39a2..e9d4c073305 100644 --- a/soc/arm/nuvoton_npcx/npcx7/mpu_regions.c +++ b/soc/arm/nuvoton_npcx/npcx7/mpu_regions.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include static const struct arm_mpu_region mpu_regions[] = { MPU_REGION_ENTRY("FLASH_0_0", diff --git a/soc/arm/nuvoton_npcx/npcx7/soc.h b/soc/arm/nuvoton_npcx/npcx7/soc.h index 9c293e05753..7099552cec3 100644 --- a/soc/arm/nuvoton_npcx/npcx7/soc.h +++ b/soc/arm/nuvoton_npcx/npcx7/soc.h @@ -11,6 +11,38 @@ #define __FPU_PRESENT CONFIG_CPU_HAS_FPU #define __MPU_PRESENT CONFIG_CPU_HAS_ARM_MPU +/* NPCX7 SCFG multi-registers offset */ +#define NPCX_DEVALT_OFFSET(n) (0x010 + n) +#define NPCX_PUPD_EN_OFFSET(n) (0x028 + n) +#define NPCX_LV_GPIO_CTL_OFFSET(n) ((n < 5) ? (0x02a + n) : (0x021 + n)) +#define NPCX_DEVALT_LK_OFFSET(n) (0x210 + n) + +/* NPCX7 MIWU multi-registers offset */ +#define NPCX_WKEDG_OFFSET(n) (0x000 + (n * 2) + ((n < 5) ? 0 : 0x01e)) +#define NPCX_WKAEDG_OFFSET(n) (0x001 + (n * 2) + ((n < 5) ? 0 : 0x01e)) +#define NPCX_WKMOD_OFFSET(n) (0x070 + n) +#define NPCX_WKPND_OFFSET(n) (0x00a + (n * 4) + ((n < 5) ? 0 : 0x010)) +#define NPCX_WKPCL_OFFSET(n) (0x00c + (n * 4) + ((n < 5) ? 0 : 0x010)) +#define NPCX_WKEN_OFFSET(n) (0x01e + (n * 2) + ((n < 5) ? 0 : 0x012)) +#define NPCX_WKINEN_OFFSET(n) (0x01f + (n * 2) + ((n < 5) ? 0 : 0x012)) + +/* NPCX7 ADC multi-registers offset */ +#define NPCX_CHNDAT_OFFSET(n) (0x040 + (n * 2)) +#define NPCX_THRCTL_OFFSET(n) (0x014 + (n * 2)) + +/* NPCX7 ADC register fields */ +#define NPCX_THRCTL_THEN 15 +#define NPCX_THRCTL_L_H 14 +#define NPCX_THRCTL_CHNSEL FIELD(10, 4) +#define NPCX_THRCTL_THRVAL FIELD(0, 10) + +/* NPCX7 supported group mask of DEVALT_LK */ +#define NPCX_DEVALT_LK_GROUP_MASK \ + (BIT(0) | BIT(2) | BIT(3) | BIT(4) | \ + BIT(6) | BIT(11) | BIT(15)) /* DEVALT0_LK - DEVALTF_LK */ + +/* NPCX7 Clock configuration */ +#define MAX_OFMCLK 100000000 #include #include diff --git a/soc/arm/nuvoton_npcx/npcx9/CMakeLists.txt b/soc/arm/nuvoton_npcx/npcx9/CMakeLists.txt index 5b2aad82a5a..56f793d0580 100644 --- a/soc/arm/nuvoton_npcx/npcx9/CMakeLists.txt +++ b/soc/arm/nuvoton_npcx/npcx9/CMakeLists.txt @@ -1,3 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_include_directories(${ZEPHYR_BASE}/drivers) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nuvoton_npcx/npcx9/linker.ld b/soc/arm/nuvoton_npcx/npcx9/linker.ld deleted file mode 100644 index 554ea2c78a7..00000000000 --- a/soc/arm/nuvoton_npcx/npcx9/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2021 Nuvoton Technology Corporation. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/nuvoton_npcx/npcx9/soc.h b/soc/arm/nuvoton_npcx/npcx9/soc.h index a1769e11a00..6b6c3f30a44 100644 --- a/soc/arm/nuvoton_npcx/npcx9/soc.h +++ b/soc/arm/nuvoton_npcx/npcx9/soc.h @@ -11,6 +11,43 @@ #define __FPU_PRESENT CONFIG_CPU_HAS_FPU #define __MPU_PRESENT CONFIG_CPU_HAS_ARM_MPU +/* NPCX9 SCFG multi-registers */ +#define NPCX_DEVALT_OFFSET(n) (0x010 + n) +#define NPCX_PUPD_EN_OFFSET(n) (0x028 + n) +#define NPCX_LV_GPIO_CTL_OFFSET(n) ((n < 5) ? (0x02a + n) : (0x021 + n)) +#define NPCX_DEVALT_LK_OFFSET(n) (0x210 + n) + +/* NPCX9 MIWU multi-registers */ +#define NPCX_WKEDG_OFFSET(n) (0x000 + (n * 0x010)) +#define NPCX_WKAEDG_OFFSET(n) (0x001 + (n * 0x010)) +#define NPCX_WKMOD_OFFSET(n) (0x002 + (n * 0x010)) +#define NPCX_WKPND_OFFSET(n) (0x003 + (n * 0x010)) +#define NPCX_WKPCL_OFFSET(n) (0x004 + (n * 0x010)) +#define NPCX_WKEN_OFFSET(n) (0x005 + (n * 0x010)) +#define NPCX_WKST_OFFSET(n) (0x006 + (n * 0x010)) +#define NPCX_WKINEN_OFFSET(n) (0x007 + (n * 0x010)) + +/* NPCX9 ADC multi-registers */ +#define NPCX_CHNDAT_OFFSET(n) (0x040 + (n * 2)) +#define NPCX_THRCTL_OFFSET(n) (0x060 + (n * 2)) + +/* NPCX9 ADC register fields */ +#define NPCX_THRCTL_THEN 15 +#define NPCX_THRCTL_L_H 14 +#define NPCX_THRCTL_CHNSEL FIELD(10, 4) +#define NPCX_THRCTL_THRVAL FIELD(0, 10) + +/* NPCX9 FIU register fields */ +#define NPCX_FIU_EXT_CFG_SPI1_2DEV 7 + +/* NPCX9 supported group mask of DEVALT_LK */ +#define NPCX_DEVALT_LK_GROUP_MASK \ + (BIT(0) | BIT(2) | BIT(3) | BIT(4) | \ + BIT(5) | BIT(6) | BIT(11) | BIT(13) | \ + BIT(15) | BIT(16) | BIT(17) | BIT(18)) /* DEVALT0_LK - DEVALTJ_LK */ + +/* NPCX9 Clock configuration and limitation */ +#define MAX_OFMCLK 100000000 #include #include diff --git a/soc/arm/nuvoton_numaker/m46x/CMakeLists.txt b/soc/arm/nuvoton_numaker/m46x/CMakeLists.txt index 6b2126d22bd..2fa91b640cf 100644 --- a/soc/arm/nuvoton_numaker/m46x/CMakeLists.txt +++ b/soc/arm/nuvoton_numaker/m46x/CMakeLists.txt @@ -3,3 +3,5 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nuvoton_numaker/m46x/linker.ld b/soc/arm/nuvoton_numaker/m46x/linker.ld deleted file mode 100644 index b9a80770518..00000000000 --- a/soc/arm/nuvoton_numaker/m46x/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2023 Nuvoton Technology Corporation. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/nuvoton_numicro/m48x/CMakeLists.txt b/soc/arm/nuvoton_numicro/m48x/CMakeLists.txt index 5d14a880fef..322465a92ce 100644 --- a/soc/arm/nuvoton_numicro/m48x/CMakeLists.txt +++ b/soc/arm/nuvoton_numicro/m48x/CMakeLists.txt @@ -4,3 +4,5 @@ # Author: Saravanan Sekar zephyr_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nuvoton_numicro/m48x/linker.ld b/soc/arm/nuvoton_numicro/m48x/linker.ld deleted file mode 100644 index 11d1f0f8f32..00000000000 --- a/soc/arm/nuvoton_numicro/m48x/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * Copyright (c) 2020 Linumiz - */ - -#include diff --git a/soc/arm/nxp_imx/mcimx6x_m4/CMakeLists.txt b/soc/arm/nxp_imx/mcimx6x_m4/CMakeLists.txt index a720300fca1..ee28789fe7d 100644 --- a/soc/arm/nxp_imx/mcimx6x_m4/CMakeLists.txt +++ b/soc/arm/nxp_imx/mcimx6x_m4/CMakeLists.txt @@ -8,3 +8,5 @@ zephyr_sources( soc.c soc_clk_freq.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nxp_imx/mcimx6x_m4/linker.ld b/soc/arm/nxp_imx/mcimx6x_m4/linker.ld deleted file mode 100644 index aabc45a6059..00000000000 --- a/soc/arm/nxp_imx/mcimx6x_m4/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/nxp_imx/mcimx7_m4/CMakeLists.txt b/soc/arm/nxp_imx/mcimx7_m4/CMakeLists.txt index f6aa4ef3332..e5c7ae22fd6 100644 --- a/soc/arm/nxp_imx/mcimx7_m4/CMakeLists.txt +++ b/soc/arm/nxp_imx/mcimx7_m4/CMakeLists.txt @@ -8,3 +8,5 @@ zephyr_sources( soc.c soc_clk_freq.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nxp_imx/mcimx7_m4/linker.ld b/soc/arm/nxp_imx/mcimx7_m4/linker.ld deleted file mode 100644 index aabc45a6059..00000000000 --- a/soc/arm/nxp_imx/mcimx7_m4/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/nxp_imx/mimx8ml8_m7/CMakeLists.txt b/soc/arm/nxp_imx/mimx8ml8_m7/CMakeLists.txt index a992a8509b4..3dce744104f 100644 --- a/soc/arm/nxp_imx/mimx8ml8_m7/CMakeLists.txt +++ b/soc/arm/nxp_imx/mimx8ml8_m7/CMakeLists.txt @@ -15,3 +15,5 @@ if(CONFIG_OPENAMP_RSC_TABLE) zephyr_linker_section(NAME .resource_table GROUP ROM_REGION NOINPUT) zephyr_linker_section_configure(SECTION .resource_table KEEP INPUT ".resource_table*") endif() + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nxp_imx/mimx8ml8_m7/Kconfig.defconfig.mimx8ml8_m7 b/soc/arm/nxp_imx/mimx8ml8_m7/Kconfig.defconfig.mimx8ml8_m7 index df80e83fdf2..8b92477601c 100644 --- a/soc/arm/nxp_imx/mimx8ml8_m7/Kconfig.defconfig.mimx8ml8_m7 +++ b/soc/arm/nxp_imx/mimx8ml8_m7/Kconfig.defconfig.mimx8ml8_m7 @@ -16,7 +16,7 @@ config SYS_CLOCK_HW_CYCLES_PER_SEC config GPIO default y -config IPM_IMX_REV2 +config IPM_IMX default y depends on IPM diff --git a/soc/arm/nxp_imx/mimx8ml8_m7/linker.ld b/soc/arm/nxp_imx/mimx8ml8_m7/linker.ld index 26ae2082fa5..0b4006dd732 100644 --- a/soc/arm/nxp_imx/mimx8ml8_m7/linker.ld +++ b/soc/arm/nxp_imx/mimx8ml8_m7/linker.ld @@ -16,7 +16,7 @@ MEMORY #endif } -#include +#include SECTIONS { diff --git a/soc/arm/nxp_imx/mimx8ml8_m7/mpu_regions.c b/soc/arm/nxp_imx/mimx8ml8_m7/mpu_regions.c index 7964712f646..ed7deb8575a 100644 --- a/soc/arm/nxp_imx/mimx8ml8_m7/mpu_regions.c +++ b/soc/arm/nxp_imx/mimx8ml8_m7/mpu_regions.c @@ -5,7 +5,7 @@ */ #include -#include +#include #define REGION_MASK_BASE_ADDRESS 0x00000000U #define REGION_ITCM_BASE_ADDRESS 0x00000000U diff --git a/soc/arm/nxp_imx/mimx8mm6_m4/CMakeLists.txt b/soc/arm/nxp_imx/mimx8mm6_m4/CMakeLists.txt index 468b44a4588..ef0ba73b159 100644 --- a/soc/arm/nxp_imx/mimx8mm6_m4/CMakeLists.txt +++ b/soc/arm/nxp_imx/mimx8mm6_m4/CMakeLists.txt @@ -12,3 +12,5 @@ if(CONFIG_OPENAMP_RSC_TABLE) zephyr_linker_section(NAME .resource_table GROUP ROM_REGION NOINPUT) zephyr_linker_section_configure(SECTION .resource_table KEEP INPUT ".resource_table*") endif() + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nxp_imx/mimx8mm6_m4/Kconfig.defconfig.mimx8mm6_m4 b/soc/arm/nxp_imx/mimx8mm6_m4/Kconfig.defconfig.mimx8mm6_m4 index 1f2fe1b6c0a..70e75a6bfce 100644 --- a/soc/arm/nxp_imx/mimx8mm6_m4/Kconfig.defconfig.mimx8mm6_m4 +++ b/soc/arm/nxp_imx/mimx8mm6_m4/Kconfig.defconfig.mimx8mm6_m4 @@ -13,7 +13,7 @@ config SYS_CLOCK_HW_CYCLES_PER_SEC int default 400000000 -config IPM_IMX_REV2 +config IPM_IMX default y depends on IPM diff --git a/soc/arm/nxp_imx/mimx8mm6_m4/linker.ld b/soc/arm/nxp_imx/mimx8mm6_m4/linker.ld index b6698210b52..b1a954f245a 100644 --- a/soc/arm/nxp_imx/mimx8mm6_m4/linker.ld +++ b/soc/arm/nxp_imx/mimx8mm6_m4/linker.ld @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include SECTIONS { diff --git a/soc/arm/nxp_imx/mimx8mq6_m4/CMakeLists.txt b/soc/arm/nxp_imx/mimx8mq6_m4/CMakeLists.txt index af5db79548a..9555fd57a89 100644 --- a/soc/arm/nxp_imx/mimx8mq6_m4/CMakeLists.txt +++ b/soc/arm/nxp_imx/mimx8mq6_m4/CMakeLists.txt @@ -7,3 +7,5 @@ zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nxp_imx/mimx8mq6_m4/linker.ld b/soc/arm/nxp_imx/mimx8mq6_m4/linker.ld deleted file mode 100644 index ebf224afbaf..00000000000 --- a/soc/arm/nxp_imx/mimx8mq6_m4/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2021, Kwon Tae-young - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/nxp_imx/rt/CMakeLists.txt b/soc/arm/nxp_imx/rt/CMakeLists.txt index 5bfc8d336fc..92ab665a0ef 100644 --- a/soc/arm/nxp_imx/rt/CMakeLists.txt +++ b/soc/arm/nxp_imx/rt/CMakeLists.txt @@ -50,6 +50,9 @@ zephyr_compile_definitions_ifdef(CONFIG_ENTROPY_MCUX_CAAM CACHE_MODE_WRITE_THROU zephyr_compile_definitions_ifdef(CONFIG_USB_DEVICE_DRIVER DATA_SECTION_IS_CACHEABLE=1) +# flexram header +zephyr_library_include_directories(${ZEPHYR_BASE}/drivers/memc) + zephyr_linker_section_configure( SECTION .rom_start INPUT ".boot_hdr.ivt" @@ -59,3 +62,5 @@ zephyr_linker_section_configure( KEEP PRIO 11 ) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nxp_imx/rt/Kconfig.defconfig.series b/soc/arm/nxp_imx/rt/Kconfig.defconfig.series index cc9cc9b5480..b4e8aeb7422 100644 --- a/soc/arm/nxp_imx/rt/Kconfig.defconfig.series +++ b/soc/arm/nxp_imx/rt/Kconfig.defconfig.series @@ -92,6 +92,9 @@ config FLASH_SIZE default $(dt_node_int_prop_int,$(DT_CHOSEN_FLASH_NODE),size,Kb) \ if $(DT_FLASH_HAS_SIZE_PROP) +config MEMC + default y + choice USB_MCUX_CONTROLLER_TYPE default USB_DC_NXP_EHCI endchoice @@ -113,7 +116,7 @@ endchoice # config MBEDTLS #config TINYCRYPT - default y if CSPRING_ENABLED + default y if CSPRNG_ENABLED depends on ENTROPY_GENERATOR if MBEDTLS diff --git a/soc/arm/nxp_imx/rt/Kconfig.soc b/soc/arm/nxp_imx/rt/Kconfig.soc index 23fb53ca344..0058993e825 100644 --- a/soc/arm/nxp_imx/rt/Kconfig.soc +++ b/soc/arm/nxp_imx/rt/Kconfig.soc @@ -1,6 +1,6 @@ # i.MX RT series -# Copyright (c) 2017-2021, NXP +# Copyright 2017-2021,2023 NXP # SPDX-License-Identifier: Apache-2.0 choice @@ -339,7 +339,6 @@ config SOC_MIMXRT1176_CM7 select INIT_VIDEO_PLL select HAS_MCUX_EDMA select CPU_HAS_FPU_DOUBLE_PRECISION - select ADJUST_DCDC select BYPASS_LDO_LPSR select ADJUST_LDO select HAS_MCUX_PWM @@ -408,7 +407,6 @@ config SOC_MIMXRT1166_CM7 select INIT_VIDEO_PLL select HAS_MCUX_EDMA select CPU_HAS_FPU_DOUBLE_PRECISION - select ADJUST_DCDC select BYPASS_LDO_LPSR select ADJUST_LDO select HAS_MCUX_PWM @@ -686,6 +684,7 @@ config DCDC_VALUE config ADJUST_DCDC bool "Adjust internal DCDC output" + default y if SOC_SERIES_IMX_RT11XX config BYPASS_LDO_LPSR bool "Bypass LDO lpsr" @@ -795,6 +794,23 @@ config NXP_IMX_EXTERNAL_SDRAM an MPU region will be defined to disable cached access to the SDRAM memory space. +config NXP_IMX_RT_ROM_RAMLOADER + depends on !FLASH_MCUX_FLEXSPI_XIP && NXP_IMX_RT_BOOT_HEADER + # Required so that debugger will load image to correct offset + select BUILD_OUTPUT_HEX + bool "Create output image that IMX RT ROM can load from FlexSPI to ram" + help + Builds an output image that the IMX RT BootROM can load from the + FlexSPI boot device into RAM region. The image will be loaded + from FLEXSPI into the region specified by `zephyr,flash` node. + +# Setup LMA adjustment if using the RAMLOADER feature of ROM +FLASH_CHOSEN := zephyr,flash +FLASH_BASE := $(dt_chosen_reg_addr_hex,$(FLASH_CHOSEN)) +FLEXSPI_BASE := $(dt_node_reg_addr_hex,/soc/spi@402a8000,1) +config BUILD_OUTPUT_ADJUST_LMA + default "$(FLEXSPI_BASE) - $(FLASH_BASE)" if NXP_IMX_RT_ROM_RAMLOADER + config SECOND_CORE_MCUX bool "Dual core operation on the RT11xx series" depends on SOC_SERIES_IMX_RT11XX diff --git a/soc/arm/nxp_imx/rt/linker.ld b/soc/arm/nxp_imx/rt/linker.ld index b26f1a38aaf..e4d5ad56db0 100644 --- a/soc/arm/nxp_imx/rt/linker.ld +++ b/soc/arm/nxp_imx/rt/linker.ld @@ -15,4 +15,4 @@ MEMORY #endif } -#include +#include diff --git a/soc/arm/nxp_imx/rt/mpu_regions.c b/soc/arm/nxp_imx/rt/mpu_regions.c index 663e448f5dd..51ce490eff1 100644 --- a/soc/arm/nxp_imx/rt/mpu_regions.c +++ b/soc/arm/nxp_imx/rt/mpu_regions.c @@ -7,8 +7,7 @@ #define SDRAM_BASE_ADDR 0x80000000 #include -#include -#include +#include static const struct arm_mpu_region mpu_regions[] = { /* Region 0 */ @@ -28,9 +27,6 @@ static const struct arm_mpu_region mpu_regions[] = { */ MPU_REGION_ENTRY("SDRAM0", SDRAM_BASE_ADDR, REGION_IO_ATTR(REGION_512M)), #endif - - /* DT-defined regions */ - DT_MEMORY_ATTR_APPLY(ARM_MPU_REGION_INIT) }; const struct arm_mpu_config mpu_config = { diff --git a/soc/arm/nxp_imx/rt/soc_rt10xx.c b/soc/arm/nxp_imx/rt/soc_rt10xx.c index ba22a633a50..91ec748a61a 100644 --- a/soc/arm/nxp_imx/rt/soc_rt10xx.c +++ b/soc/arm/nxp_imx/rt/soc_rt10xx.c @@ -21,6 +21,8 @@ #include "usb.h" #endif +#include "memc_nxp_flexram.h" + #include #define CCM_NODE DT_INST(0, nxp_imx_ccm) @@ -345,6 +347,11 @@ void z_arm_platform_init(void) { /* Call CMSIS SystemInit */ SystemInit(); + +#if defined(FLEXRAM_RUNTIME_BANKS_USED) + /* Configure flexram if not running from RAM */ + memc_flexram_dt_partition(); +#endif } #endif diff --git a/soc/arm/nxp_imx/rt/soc_rt11xx.c b/soc/arm/nxp_imx/rt/soc_rt11xx.c index 7340fd0f3ff..f9eb7b7e381 100644 --- a/soc/arm/nxp_imx/rt/soc_rt11xx.c +++ b/soc/arm/nxp_imx/rt/soc_rt11xx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, NXP + * Copyright 2021-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -33,17 +33,18 @@ #include "usb_phy.h" #include "usb.h" #endif +#include "memc_nxp_flexram.h" #include #define DUAL_CORE_MU_ENABLED \ - (CONFIG_SECOND_CORE_MCUX && CONFIG_IPM && CONFIG_IPM_IMX_REV2) + (CONFIG_SECOND_CORE_MCUX && CONFIG_IPM && CONFIG_IPM_IMX) #if DUAL_CORE_MU_ENABLED /* Dual core mode is enabled, and messaging unit is present */ #include #define BOOT_FLAG 0x1U -#define MU_BASE (MU_Type *)DT_REG_ADDR(DT_INST(0, nxp_imx_mu_rev2)) +#define MU_BASE (MU_Type *)DT_REG_ADDR(DT_INST(0, nxp_imx_mu)) #endif #if CONFIG_USB_DC_NXP_EHCI /* USB PHY configuration */ @@ -689,6 +690,11 @@ static int imxrt_init(void) void z_arm_platform_init(void) { SystemInit(); + +#if defined(FLEXRAM_RUNTIME_BANKS_USED) + /* Configure flexram if not running from RAM */ + memc_flexram_dt_partition(); +#endif } #endif diff --git a/soc/arm/nxp_imx/rt5xx/CMakeLists.txt b/soc/arm/nxp_imx/rt5xx/CMakeLists.txt index f3c6404d185..e12f2e9ae18 100644 --- a/soc/arm/nxp_imx/rt5xx/CMakeLists.txt +++ b/soc/arm/nxp_imx/rt5xx/CMakeLists.txt @@ -29,3 +29,5 @@ zephyr_linker_sources_ifdef(CONFIG_USB_DEVICE_DRIVER SECTIONS usb.ld) zephyr_code_relocate(FILES flash_clock_setup.c LOCATION RAM) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nxp_imx/rt5xx/Kconfig.defconfig.series b/soc/arm/nxp_imx/rt5xx/Kconfig.defconfig.series index 9ee952cff78..31b6a2c70db 100644 --- a/soc/arm/nxp_imx/rt5xx/Kconfig.defconfig.series +++ b/soc/arm/nxp_imx/rt5xx/Kconfig.defconfig.series @@ -62,7 +62,7 @@ endif # config MBEDTLS #config TINYCRYPT - default y if CSPRING_ENABLED + default y if CSPRNG_ENABLED depends on ENTROPY_GENERATOR if MBEDTLS diff --git a/soc/arm/nxp_imx/rt5xx/Kconfig.soc b/soc/arm/nxp_imx/rt5xx/Kconfig.soc index f41c63d104b..2c82c533de9 100644 --- a/soc/arm/nxp_imx/rt5xx/Kconfig.soc +++ b/soc/arm/nxp_imx/rt5xx/Kconfig.soc @@ -101,8 +101,27 @@ config IMAGE_VECTOR_TABLE_OFFSET the application entry point and device configuration data. The boot ROM requires a fixed IVT offset for each type of boot device. +config NXP_IMX_RT_ROM_RAMLOADER + depends on !FLASH_MCUX_FLEXSPI_XIP + # Required so that debugger will load image to correct offset + select BUILD_OUTPUT_HEX + bool "Create output image that IMX RT ROM can load from FlexSPI to ram" + help + Builds an output image that the IMX RT BootROM can load from the + FlexSPI boot device into RAM region. The image will be loaded + from FLEXSPI0 into the region specified by `zephyr,flash` node. + +# Setup LMA adjustment if using the RAMLOADER feature of ROM +FLASH_CHOSEN := zephyr,flash +FLASH_BASE := $(dt_chosen_reg_addr_hex,$(FLASH_CHOSEN)) +FLEXSPI_BASE := $(dt_node_reg_addr_hex,/soc/spi@134000,1) +config BUILD_OUTPUT_ADJUST_LMA + default "$(FLEXSPI_BASE) - $(FLASH_BASE)" if NXP_IMX_RT_ROM_RAMLOADER + endif # NXP_IMX_RT5XX_BOOT_HEADER + + config IMXRT5XX_CODE_CACHE bool "Code cache" default y diff --git a/soc/arm/nxp_imx/rt5xx/linker.ld b/soc/arm/nxp_imx/rt5xx/linker.ld index 3b84d02a527..2b6a4d63fba 100644 --- a/soc/arm/nxp_imx/rt5xx/linker.ld +++ b/soc/arm/nxp_imx/rt5xx/linker.ld @@ -21,4 +21,4 @@ FLEXSPI2 (wx) : ORIGIN = DT_REG_ADDR_BY_IDX(DT_NODELABEL(flexspi2), 1), LENGTH = DT_REG_SIZE_BY_IDX(DT_NODELABEL(flexspi2), 1) #endif } -#include +#include diff --git a/soc/arm/nxp_imx/rt5xx/soc.c b/soc/arm/nxp_imx/rt5xx/soc.c index 2fbb7d609b3..d834d3e55bc 100644 --- a/soc/arm/nxp_imx/rt5xx/soc.c +++ b/soc/arm/nxp_imx/rt5xx/soc.c @@ -216,7 +216,8 @@ void z_arm_platform_init(void) SystemInit(); } -static void clock_init(void) +/* Weak so that board can override with their own clock init routine. */ +void __weak rt5xx_clock_init(void) { /* Configure LPOSC 1M */ /* Power on LPOSC (1MHz) */ @@ -364,6 +365,16 @@ static void clock_init(void) RESET_PeripheralReset(kSDIO0_RST_SHIFT_RSTn); #endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(smartdma), okay) && CONFIG_DMA_MCUX_SMARTDMA + /* Power up SMARTDMA ram */ + POWER_DisablePD(kPDRUNCFG_APD_SMARTDMA_SRAM); + POWER_DisablePD(kPDRUNCFG_PPD_SMARTDMA_SRAM); + POWER_ApplyPD(); + + RESET_ClearPeripheralReset(kSMART_DMA_RST_SHIFT_RSTn); + CLOCK_EnableClock(kCLOCK_Smartdma); +#endif + DT_FOREACH_STATUS_OKAY(nxp_lpc_ctimer, CTIMER_CLOCK_SETUP) /* Set up dividers. */ @@ -408,6 +419,10 @@ static void clock_init(void) CLOCK_SetClkDiv(kCLOCK_DivAdcClk, 1); #endif +#if CONFIG_COUNTER_NXP_MRT + RESET_PeripheralReset(kMRT0_RST_SHIFT_RSTn); +#endif + /* Set SystemCoreClock variable. */ SystemCoreClock = CLOCK_INIT_CORE_CLOCK; @@ -416,7 +431,8 @@ static void clock_init(void) } #if CONFIG_MIPI_DSI -void imxrt_pre_init_display_interface(void) +/* Weak so board can override this function */ +void __weak imxrt_pre_init_display_interface(void) { /* Assert MIPI DPHY reset. */ RESET_SetPeripheralReset(kMIPI_DSI_PHY_RST_SHIFT_RSTn); @@ -452,11 +468,22 @@ void imxrt_pre_init_display_interface(void) RESET_ClearPeripheralReset(kMIPI_DSI_CTRL_RST_SHIFT_RSTn); } -void imxrt_post_init_display_interface(void) +void __weak imxrt_post_init_display_interface(void) { /* Deassert MIPI DPHY reset. */ RESET_ClearPeripheralReset(kMIPI_DSI_PHY_RST_SHIFT_RSTn); } + +void __weak imxrt_deinit_display_interface(void) +{ + /* Assert MIPI DPHY and DSI reset */ + RESET_SetPeripheralReset(kMIPI_DSI_PHY_RST_SHIFT_RSTn); + RESET_SetPeripheralReset(kMIPI_DSI_CTRL_RST_SHIFT_RSTn); + /* Remove clock from DPHY */ + CLOCK_AttachClk(kNONE_to_MIPI_DPHY_CLK); +} + + #endif /** @@ -471,7 +498,7 @@ void imxrt_post_init_display_interface(void) static int nxp_rt500_init(void) { /* Initialize clocks with tool generated code */ - clock_init(); + rt5xx_clock_init(); #ifndef CONFIG_IMXRT5XX_CODE_CACHE CACHE64_DisableCache(CACHE64_CTRL0); diff --git a/soc/arm/nxp_imx/rt5xx/soc.h b/soc/arm/nxp_imx/rt5xx/soc.h index c2ebff0369d..eefef70ff82 100644 --- a/soc/arm/nxp_imx/rt5xx/soc.h +++ b/soc/arm/nxp_imx/rt5xx/soc.h @@ -80,6 +80,8 @@ void imxrt_pre_init_display_interface(void); void imxrt_post_init_display_interface(void); + +void imxrt_deinit_display_interface(void); #endif #endif diff --git a/soc/arm/nxp_imx/rt6xx/CMakeLists.txt b/soc/arm/nxp_imx/rt6xx/CMakeLists.txt index a5a853cd853..57d5cb3fd04 100644 --- a/soc/arm/nxp_imx/rt6xx/CMakeLists.txt +++ b/soc/arm/nxp_imx/rt6xx/CMakeLists.txt @@ -32,3 +32,5 @@ zephyr_linker_sources_ifdef(CONFIG_USB_DEVICE_DRIVER if(CONFIG_FLASH_MCUX_FLEXSPI_XIP) zephyr_code_relocate(FILES flash_clock_setup.c LOCATION RAM) endif() + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nxp_imx/rt6xx/Kconfig.defconfig.series b/soc/arm/nxp_imx/rt6xx/Kconfig.defconfig.series index 40bb1ab7b6a..7bcbc4e8e80 100644 --- a/soc/arm/nxp_imx/rt6xx/Kconfig.defconfig.series +++ b/soc/arm/nxp_imx/rt6xx/Kconfig.defconfig.series @@ -63,7 +63,7 @@ endif # config MBEDTLS #config TINYCRYPT - default y if CSPRING_ENABLED + default y if CSPRNG_ENABLED depends on ENTROPY_GENERATOR if MBEDTLS diff --git a/soc/arm/nxp_imx/rt6xx/Kconfig.soc b/soc/arm/nxp_imx/rt6xx/Kconfig.soc index b94e98b7384..e2222ab3214 100644 --- a/soc/arm/nxp_imx/rt6xx/Kconfig.soc +++ b/soc/arm/nxp_imx/rt6xx/Kconfig.soc @@ -107,6 +107,23 @@ config IMAGE_VECTOR_TABLE_OFFSET the application entry point and device configuration data. The boot ROM requires a fixed IVT offset for each type of boot device. +config NXP_IMX_RT_ROM_RAMLOADER + depends on !FLASH_MCUX_FLEXSPI_XIP + # Required so that debugger will load image to correct offset + select BUILD_OUTPUT_HEX + bool "Create output image that IMX RT ROM can load from FlexSPI to ram" + help + Builds an output image that the IMX RT BootROM can load from the + FlexSPI boot device into RAM region. The image will be loaded + from FLEXSPI into the region specified by `zephyr,flash` node. + +# Setup LMA adjustment if using the RAMLOADER feature of ROM +FLASH_CHOSEN := zephyr,flash +FLASH_BASE := $(dt_chosen_reg_addr_hex,$(FLASH_CHOSEN)) +FLEXSPI_BASE := $(dt_node_reg_addr_hex,/soc/spi@134000,1) +config BUILD_OUTPUT_ADJUST_LMA + default "$(FLEXSPI_BASE) - $(FLASH_BASE)" if NXP_IMX_RT_ROM_RAMLOADER + endif # NXP_IMX_RT6XX_BOOT_HEADER config IMXRT6XX_CODE_CACHE diff --git a/soc/arm/nxp_imx/rt6xx/linker.ld b/soc/arm/nxp_imx/rt6xx/linker.ld deleted file mode 100644 index d9eaca7598c..00000000000 --- a/soc/arm/nxp_imx/rt6xx/linker.ld +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2020, NXP - * - * SPDX-License-Identifier: Apache-2.0 - */ -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images and XIP images. - */ - - -#include diff --git a/soc/arm/nxp_imx/rt6xx/soc.c b/soc/arm/nxp_imx/rt6xx/soc.c index 8ba2aa9dcec..2d4eab6854d 100644 --- a/soc/arm/nxp_imx/rt6xx/soc.c +++ b/soc/arm/nxp_imx/rt6xx/soc.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -321,6 +321,10 @@ static ALWAYS_INLINE void clock_init(void) flexspi_setup_clock(FLEXSPI, 1U, 9U); #endif +#if CONFIG_COUNTER_NXP_MRT + RESET_PeripheralReset(kMRT0_RST_SHIFT_RSTn); +#endif + /* Set SystemCoreClock variable. */ SystemCoreClock = CLOCK_INIT_CORE_CLOCK; diff --git a/soc/arm/nxp_kinetis/k2x/CMakeLists.txt b/soc/arm/nxp_kinetis/k2x/CMakeLists.txt index f61746c2610..017787396e4 100644 --- a/soc/arm/nxp_kinetis/k2x/CMakeLists.txt +++ b/soc/arm/nxp_kinetis/k2x/CMakeLists.txt @@ -8,3 +8,5 @@ zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nxp_kinetis/k2x/linker.ld b/soc/arm/nxp_kinetis/k2x/linker.ld deleted file mode 100644 index 5d6126629f9..00000000000 --- a/soc/arm/nxp_kinetis/k2x/linker.ld +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images and XIP images. - */ - -#include diff --git a/soc/arm/nxp_kinetis/k2x/soc.h b/soc/arm/nxp_kinetis/k2x/soc.h index 75789df6531..cb88009a49d 100644 --- a/soc/arm/nxp_kinetis/k2x/soc.h +++ b/soc/arm/nxp_kinetis/k2x/soc.h @@ -35,7 +35,7 @@ extern "C" { #include #include #include -#include +#include #endif /* !_ASMLANGUAGE */ diff --git a/soc/arm/nxp_kinetis/k6x/CMakeLists.txt b/soc/arm/nxp_kinetis/k6x/CMakeLists.txt index d26821f690b..8cf7a11f62e 100644 --- a/soc/arm/nxp_kinetis/k6x/CMakeLists.txt +++ b/soc/arm/nxp_kinetis/k6x/CMakeLists.txt @@ -7,3 +7,5 @@ zephyr_sources_ifdef( CONFIG_ARM_MPU nxp_mpu_regions.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nxp_kinetis/k6x/linker.ld b/soc/arm/nxp_kinetis/k6x/linker.ld deleted file mode 100644 index 5d6126629f9..00000000000 --- a/soc/arm/nxp_kinetis/k6x/linker.ld +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images and XIP images. - */ - -#include diff --git a/soc/arm/nxp_kinetis/k6x/nxp_mpu_regions.c b/soc/arm/nxp_kinetis/k6x/nxp_mpu_regions.c index 8108ca7df88..41d0df3d689 100644 --- a/soc/arm/nxp_kinetis/k6x/nxp_mpu_regions.c +++ b/soc/arm/nxp_kinetis/k6x/nxp_mpu_regions.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ #include -#include +#include static const struct nxp_mpu_region mpu_regions[] = { /* Region 0 */ diff --git a/soc/arm/nxp_kinetis/k8x/CMakeLists.txt b/soc/arm/nxp_kinetis/k8x/CMakeLists.txt index d26821f690b..8cf7a11f62e 100644 --- a/soc/arm/nxp_kinetis/k8x/CMakeLists.txt +++ b/soc/arm/nxp_kinetis/k8x/CMakeLists.txt @@ -7,3 +7,5 @@ zephyr_sources_ifdef( CONFIG_ARM_MPU nxp_mpu_regions.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nxp_kinetis/k8x/linker.ld b/soc/arm/nxp_kinetis/k8x/linker.ld deleted file mode 100644 index 5d6126629f9..00000000000 --- a/soc/arm/nxp_kinetis/k8x/linker.ld +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images and XIP images. - */ - -#include diff --git a/soc/arm/nxp_kinetis/k8x/nxp_mpu_regions.c b/soc/arm/nxp_kinetis/k8x/nxp_mpu_regions.c index d7bcce1cd9b..599f1e149ef 100644 --- a/soc/arm/nxp_kinetis/k8x/nxp_mpu_regions.c +++ b/soc/arm/nxp_kinetis/k8x/nxp_mpu_regions.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ #include -#include +#include static const struct nxp_mpu_region mpu_regions[] = { /* Region 0 */ diff --git a/soc/arm/nxp_kinetis/ke1xf/CMakeLists.txt b/soc/arm/nxp_kinetis/ke1xf/CMakeLists.txt index 0b26284343c..ccbf2208d5a 100644 --- a/soc/arm/nxp_kinetis/ke1xf/CMakeLists.txt +++ b/soc/arm/nxp_kinetis/ke1xf/CMakeLists.txt @@ -11,3 +11,5 @@ zephyr_sources_ifdef( CONFIG_PM power.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nxp_kinetis/ke1xf/linker.ld b/soc/arm/nxp_kinetis/ke1xf/linker.ld deleted file mode 100644 index 5d6126629f9..00000000000 --- a/soc/arm/nxp_kinetis/ke1xf/linker.ld +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images and XIP images. - */ - -#include diff --git a/soc/arm/nxp_kinetis/ke1xf/nxp_mpu_regions.c b/soc/arm/nxp_kinetis/ke1xf/nxp_mpu_regions.c index d7bcce1cd9b..599f1e149ef 100644 --- a/soc/arm/nxp_kinetis/ke1xf/nxp_mpu_regions.c +++ b/soc/arm/nxp_kinetis/ke1xf/nxp_mpu_regions.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ #include -#include +#include static const struct nxp_mpu_region mpu_regions[] = { /* Region 0 */ diff --git a/soc/arm/nxp_kinetis/kl2x/CMakeLists.txt b/soc/arm/nxp_kinetis/kl2x/CMakeLists.txt index 9486f255912..268f065fb12 100644 --- a/soc/arm/nxp_kinetis/kl2x/CMakeLists.txt +++ b/soc/arm/nxp_kinetis/kl2x/CMakeLists.txt @@ -1,3 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nxp_kinetis/kl2x/linker.ld b/soc/arm/nxp_kinetis/kl2x/linker.ld deleted file mode 100644 index 5d6126629f9..00000000000 --- a/soc/arm/nxp_kinetis/kl2x/linker.ld +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images and XIP images. - */ - -#include diff --git a/soc/arm/nxp_kinetis/kv5x/CMakeLists.txt b/soc/arm/nxp_kinetis/kv5x/CMakeLists.txt index 332416ba43b..7424bb9f7b9 100644 --- a/soc/arm/nxp_kinetis/kv5x/CMakeLists.txt +++ b/soc/arm/nxp_kinetis/kv5x/CMakeLists.txt @@ -3,3 +3,5 @@ zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nxp_kinetis/kv5x/linker.ld b/soc/arm/nxp_kinetis/kv5x/linker.ld deleted file mode 100644 index 5d6126629f9..00000000000 --- a/soc/arm/nxp_kinetis/kv5x/linker.ld +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images and XIP images. - */ - -#include diff --git a/soc/arm/nxp_kinetis/kwx/CMakeLists.txt b/soc/arm/nxp_kinetis/kwx/CMakeLists.txt index 9b651c95828..d414d72a63a 100644 --- a/soc/arm/nxp_kinetis/kwx/CMakeLists.txt +++ b/soc/arm/nxp_kinetis/kwx/CMakeLists.txt @@ -4,3 +4,5 @@ zephyr_sources_ifdef(CONFIG_SOC_MKW24D5 soc_kw2xd.c) zephyr_sources_ifdef(CONFIG_SOC_MKW22D5 soc_kw2xd.c) zephyr_sources_ifdef(CONFIG_SOC_MKW41Z4 soc_kw4xz.c) zephyr_sources_ifdef(CONFIG_SOC_MKW40Z4 soc_kw4xz.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nxp_kinetis/kwx/linker.ld b/soc/arm/nxp_kinetis/kwx/linker.ld deleted file mode 100644 index 5d6126629f9..00000000000 --- a/soc/arm/nxp_kinetis/kwx/linker.ld +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images and XIP images. - */ - -#include diff --git a/soc/arm/nxp_lpc/lpc11u6x/CMakeLists.txt b/soc/arm/nxp_lpc/lpc11u6x/CMakeLists.txt index 84686ad59cd..e9a04818a93 100644 --- a/soc/arm/nxp_lpc/lpc11u6x/CMakeLists.txt +++ b/soc/arm/nxp_lpc/lpc11u6x/CMakeLists.txt @@ -3,3 +3,5 @@ # # SPDX-License-Identifier: Apache-2.0 # + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nxp_lpc/lpc11u6x/linker.ld b/soc/arm/nxp_lpc/lpc11u6x/linker.ld deleted file mode 100644 index d729ed4c3a7..00000000000 --- a/soc/arm/nxp_lpc/lpc11u6x/linker.ld +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images and XIP images. - */ - - -#include diff --git a/soc/arm/nxp_lpc/lpc51u68/CMakeLists.txt b/soc/arm/nxp_lpc/lpc51u68/CMakeLists.txt index c2ef013fe62..a0b6a030303 100644 --- a/soc/arm/nxp_lpc/lpc51u68/CMakeLists.txt +++ b/soc/arm/nxp_lpc/lpc51u68/CMakeLists.txt @@ -11,3 +11,5 @@ zephyr_library_include_directories( ${ZEPHYR_BASE}/kernel/include ${ZEPHYR_BASE}/arch/${ARCH}/include ) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nxp_lpc/lpc51u68/linker.ld b/soc/arm/nxp_lpc/lpc51u68/linker.ld index 1023aa66005..8724d8f68dd 100644 --- a/soc/arm/nxp_lpc/lpc51u68/linker.ld +++ b/soc/arm/nxp_lpc/lpc51u68/linker.ld @@ -9,4 +9,4 @@ */ __Vectors = _vector_table; -#include +#include diff --git a/soc/arm/nxp_lpc/lpc54xxx/CMakeLists.txt b/soc/arm/nxp_lpc/lpc54xxx/CMakeLists.txt index 09fdf8ae51a..fda5d9532e8 100644 --- a/soc/arm/nxp_lpc/lpc54xxx/CMakeLists.txt +++ b/soc/arm/nxp_lpc/lpc54xxx/CMakeLists.txt @@ -19,3 +19,5 @@ zephyr_library_include_directories( if(NOT DEFINED CONFIG_LPC54XXX_SRAM2_CLOCK) zephyr_compile_definitions(DONT_ENABLE_DISABLED_RAMBANKS=1) endif() + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nxp_lpc/lpc54xxx/linker.ld b/soc/arm/nxp_lpc/lpc54xxx/linker.ld index 817f1d948d0..b6a1fb0bbcc 100644 --- a/soc/arm/nxp_lpc/lpc54xxx/linker.ld +++ b/soc/arm/nxp_lpc/lpc54xxx/linker.ld @@ -16,4 +16,4 @@ */ __Vectors = _vector_table; -#include +#include diff --git a/soc/arm/nxp_lpc/lpc54xxx/soc.c b/soc/arm/nxp_lpc/lpc54xxx/soc.c index df7e5ac1c06..bbc689dbc68 100644 --- a/soc/arm/nxp_lpc/lpc54xxx/soc.c +++ b/soc/arm/nxp_lpc/lpc54xxx/soc.c @@ -18,7 +18,8 @@ #include #include #include -#include +#include +#include #include #include #include diff --git a/soc/arm/nxp_lpc/lpc55xxx/CMakeLists.txt b/soc/arm/nxp_lpc/lpc55xxx/CMakeLists.txt index 22bb1ed0d55..fb58ca649f2 100644 --- a/soc/arm/nxp_lpc/lpc55xxx/CMakeLists.txt +++ b/soc/arm/nxp_lpc/lpc55xxx/CMakeLists.txt @@ -23,3 +23,5 @@ endif() if(NOT DEFINED CONFIG_LPC55XXX_SRAM_CLOCKS) zephyr_compile_definitions(DONT_ENABLE_DISABLED_RAMBANKS=1) endif() + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nxp_lpc/lpc55xxx/Kconfig.soc b/soc/arm/nxp_lpc/lpc55xxx/Kconfig.soc index a7bae5aafb0..c0341a8e9c5 100644 --- a/soc/arm/nxp_lpc/lpc55xxx/Kconfig.soc +++ b/soc/arm/nxp_lpc/lpc55xxx/Kconfig.soc @@ -123,10 +123,16 @@ config INIT_PLL0 config INIT_PLL1 bool "Initialize PLL1" default "y" - depends on !SOC_LPC55S06 + depends on !(SOC_LPC55S06 || FLASH) help In the LPC55XXX Family, this is currently being used to set the core clock value at it's highest frequency which clocks at 150MHz. + Note that flash programming operations are limited to 100MHz, and + this PLL should not be used as the core clock in those cases. + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 144000000 if INIT_PLL1 + default 96000000 config SECOND_CORE_MCUX bool "LPC55xxx's second core" diff --git a/soc/arm/nxp_lpc/lpc55xxx/linker.ld b/soc/arm/nxp_lpc/lpc55xxx/linker.ld index e7c360409f7..186914f102c 100644 --- a/soc/arm/nxp_lpc/lpc55xxx/linker.ld +++ b/soc/arm/nxp_lpc/lpc55xxx/linker.ld @@ -17,4 +17,4 @@ __Vectors = _vector_table; -#include +#include diff --git a/soc/arm/nxp_lpc/lpc55xxx/soc.c b/soc/arm/nxp_lpc/lpc55xxx/soc.c index cd3995764c6..6730c6cfcff 100644 --- a/soc/arm/nxp_lpc/lpc55xxx/soc.c +++ b/soc/arm/nxp_lpc/lpc55xxx/soc.c @@ -1,5 +1,4 @@ -/* - * Copyright 2017, 2019-2023 NXP +/* Copyright 2017, 2019-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -31,7 +30,8 @@ #include "usb_phy.h" #include "usb.h" #endif -#if defined(CONFIG_SOC_LPC55S36) && defined(CONFIG_ADC_MCUX_LPADC) +#if defined(CONFIG_SOC_LPC55S36) && (defined(CONFIG_ADC_MCUX_LPADC) \ + || defined(CONFIG_DAC_MCUX_LPDAC)) #include #endif @@ -217,7 +217,7 @@ static ALWAYS_INLINE void clock_init(void) #if CONFIG_USB_DC_NXP_LPCIP3511 -#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(usbfs), nxp_mcux_usbd, okay) +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(usbfs), nxp_lpcip3511, okay) /*< Turn on USB Phy */ #if defined(CONFIG_SOC_LPC55S36) POWER_DisablePD(kPDRUNCFG_PD_USBFSPHY); @@ -248,7 +248,7 @@ static ALWAYS_INLINE void clock_init(void) #endif /* USB_DEVICE_TYPE_FS */ -#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(usbhs), nxp_mcux_usbd, okay) +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(usbhs), nxp_lpcip3511, okay) /* enable usb1 host clock */ CLOCK_EnableClock(kCLOCK_Usbh1); /* Put PHY powerdown under software control */ @@ -322,28 +322,35 @@ DT_FOREACH_STATUS_OKAY(nxp_lpc_ctimer, CTIMER_CLOCK_SETUP) #if defined(CONFIG_SOC_LPC55S36) CLOCK_SetClkDiv(kCLOCK_DivAdc0Clk, 2U, true); CLOCK_AttachClk(kFRO_HF_to_ADC0); - -#if defined(CONFIG_ADC_MCUX_LPADC) - /* Vref is required for LPADC reference */ - POWER_DisablePD(kPDRUNCFG_PD_VREF); - - vref_config_t vrefConfig; - - VREF_GetDefaultConfig(&vrefConfig); - vrefConfig.bufferMode = kVREF_ModeHighPowerBuffer; - vrefConfig.enableInternalVoltageRegulator = true; - vrefConfig.enableVrefOut = true; - VREF_Init((VREF_Type *)VREF_BASE, &vrefConfig); -#endif -#else +#else /* not LPC55s36 */ CLOCK_SetClkDiv(kCLOCK_DivAdcAsyncClk, DT_PROP(DT_NODELABEL(adc0), clk_divider), true); CLOCK_AttachClk(MUX_A(CM_ADCASYNCCLKSEL, DT_PROP(DT_NODELABEL(adc0), clk_source))); /* Power up the ADC */ POWER_DisablePD(kPDRUNCFG_PD_LDOGPADC); +#endif /* SOC platform */ +#endif /* ADC */ + +#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(vref0), nxp_vref, okay)) + CLOCK_EnableClock(kCLOCK_Vref); + POWER_DisablePD(kPDRUNCFG_PD_VREF); +#endif /* vref0 */ + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(dac0), nxp_lpdac, okay) +#if defined(CONFIG_SOC_LPC55S36) + CLOCK_SetClkDiv(kCLOCK_DivDac0Clk, 1U, true); + CLOCK_AttachClk(kMAIN_CLK_to_DAC0); + + /* Disable DAC0 power down */ + POWER_DisablePD(kPDRUNCFG_PD_DAC0); +#endif /* SOC platform */ +#endif /* DAC */ + +#ifdef CONFIG_COUNTER_NXP_MRT + RESET_PeripheralReset(kMRT_RST_SHIFT_RSTn); #endif -#endif + } /** diff --git a/soc/arm/nxp_s32/Kconfig b/soc/arm/nxp_s32/Kconfig index 5a33f2065ff..d014315e4d7 100644 --- a/soc/arm/nxp_s32/Kconfig +++ b/soc/arm/nxp_s32/Kconfig @@ -35,8 +35,4 @@ config NXP_S32_DEST_RESET_THRESHOLD source "soc/arm/nxp_s32/*/Kconfig.soc" -config SOC_PART_NUMBER - default SOC_PART_NUMBER_S32ZE_R52 if SOC_SERIES_S32ZE_R52 - default SOC_PART_NUMBER_S32K3 if SOC_SERIES_S32K3_M7 - endif # SOC_FAMILY_NXP_S32 diff --git a/soc/arm/nxp_s32/common/CMakeLists.txt b/soc/arm/nxp_s32/common/CMakeLists.txt index 13ec5b28101..6142be7ab64 100644 --- a/soc/arm/nxp_s32/common/CMakeLists.txt +++ b/soc/arm/nxp_s32/common/CMakeLists.txt @@ -3,4 +3,4 @@ zephyr_include_directories(.) zephyr_sources(osif.c) -zephyr_sources_ifdef(CONFIG_SOC_SERIES_S32K3_M7 power_soc.c) +zephyr_sources_ifdef(CONFIG_SOC_SERIES_S32K3XX power_soc.c) diff --git a/soc/arm/nxp_s32/common/osif.c b/soc/arm/nxp_s32/common/osif.c index 344a1416ee8..970e127fe13 100644 --- a/soc/arm/nxp_s32/common/osif.c +++ b/soc/arm/nxp_s32/common/osif.c @@ -4,15 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include -#if defined(CONFIG_SOC_S32Z27_R52) -#include -#elif defined(CONFIG_SOC_S32K344_M7) -#include -#endif - /* Required by OsIf timer initialization but not used with Zephyr, so no values configured */ static const OsIf_ConfigType osif_config; const OsIf_ConfigType *const OsIf_apxPredefinedConfig[OSIF_MAX_COREIDX_SUPPORTED] = { diff --git a/soc/arm/nxp_s32/common/pinctrl_soc.h b/soc/arm/nxp_s32/common/pinctrl_soc.h index 46c1c77bfd1..60c609497aa 100644 --- a/soc/arm/nxp_s32/common/pinctrl_soc.h +++ b/soc/arm/nxp_s32/common/pinctrl_soc.h @@ -19,6 +19,11 @@ /** @brief Type for NXP S32 pin configuration. */ typedef Siul2_Port_Ip_PinSettingsConfig pinctrl_soc_pin_t; +/* Alias for compatibility with previous RTD versions */ +#if !defined(FEATURE_SIUL2_MAX_NUMBER_OF_INPUT) && defined(FEATURE_SIUL2_MAX_NUMBER_OF_INPUT_U8) +#define FEATURE_SIUL2_MAX_NUMBER_OF_INPUT FEATURE_SIUL2_MAX_NUMBER_OF_INPUT_U8 +#endif + #if defined(SIUL2_PORT_IP_MULTIPLE_SIUL2_INSTANCES) #define NXP_S32_SIUL2_IDX(n) \ n == 0 ? IP_SIUL2_0 : (n == 1 ? IP_SIUL2_1 : ( \ diff --git a/soc/arm/nxp_s32/common/power_soc.c b/soc/arm/nxp_s32/common/power_soc.c index eef489ee8df..3e277155cb8 100644 --- a/soc/arm/nxp_s32/common/power_soc.c +++ b/soc/arm/nxp_s32/common/power_soc.c @@ -71,7 +71,7 @@ static int nxp_s32_power_init(void) }; const Power_Ip_PMC_ConfigType pmc_cfg = { -#ifdef CONFIG_SOC_PART_NUMBER_S32K3 +#ifdef CONFIG_SOC_SERIES_S32K3XX /* PMC Configuration Register (CONFIG) */ .ConfigRegister = PMC_CONFIG_LMEN(IS_ENABLED(CONFIG_NXP_S32_PMC_LMEN)) | PMC_CONFIG_LMBCTLEN(IS_ENABLED(CONFIG_NXP_S32_PMC_LMBCTLEN)), diff --git a/soc/arm/nxp_s32/s32k/CMakeLists.txt b/soc/arm/nxp_s32/s32k/CMakeLists.txt deleted file mode 100644 index f223c351a70..00000000000 --- a/soc/arm/nxp_s32/s32k/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright 2023 NXP -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library() - -zephyr_library_sources(soc.c) -zephyr_library_sources_ifdef(CONFIG_CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS mpu_regions.c) -zephyr_linker_sources(SECTIONS sections.ld) -zephyr_library_sources_ifdef(CONFIG_PLATFORM_SPECIFIC_INIT s32k3xx_startup.S) diff --git a/soc/arm/nxp_s32/s32k/Kconfig.defconfig.s32k344 b/soc/arm/nxp_s32/s32k/Kconfig.defconfig.s32k344 deleted file mode 100644 index 3dfab760337..00000000000 --- a/soc/arm/nxp_s32/s32k/Kconfig.defconfig.s32k344 +++ /dev/null @@ -1,14 +0,0 @@ -# S32K344 - -# Copyright 2023 NXP -# SPDX-License-Identifier: Apache-2.0 - -if SOC_S32K344_M7 - -config SOC - default "s32k344" - -config FPU - default y - -endif # SOC_S32K344_M7 diff --git a/soc/arm/nxp_s32/s32k/Kconfig.defconfig.series b/soc/arm/nxp_s32/s32k/Kconfig.defconfig.series deleted file mode 100644 index 93786720698..00000000000 --- a/soc/arm/nxp_s32/s32k/Kconfig.defconfig.series +++ /dev/null @@ -1,37 +0,0 @@ -# S32 K M7 core series - -# Copyright 2023 NXP -# SPDX-License-Identifier: Apache-2.0 - -if SOC_SERIES_S32K3_M7 - -config SOC_SERIES - default "s32k" - -config SYS_CLOCK_HW_CYCLES_PER_SEC - default 2000000 - -config NUM_IRQS - # must be >= the highest interrupt number used - default 239 - -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - -if NET_L2_ETHERNET - -config NET_TCP_CHECKSUM - default n - -config NET_UDP_CHECKSUM - default n - -endif # NET_L2_ETHERNET - -source "soc/arm/nxp_s32/s32k/Kconfig.defconfig.s32k*" - -endif # SOC_SERIES_S32K_M7 diff --git a/soc/arm/nxp_s32/s32k/Kconfig.series b/soc/arm/nxp_s32/s32k/Kconfig.series deleted file mode 100644 index 566c3608fee..00000000000 --- a/soc/arm/nxp_s32/s32k/Kconfig.series +++ /dev/null @@ -1,23 +0,0 @@ -# NXP S32K3 MCUs family - -# Copyright 2023 NXP -# SPDX-License-Identifier: Apache-2.0 - -config SOC_SERIES_S32K3_M7 - bool "S32K3 M7 Core Series" - select ARM - select CPU_CORTEX_M7 - select SOC_FAMILY_NXP_S32 - select CPU_HAS_FPU - select CPU_HAS_ARM_MPU - select CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS - select PLATFORM_SPECIFIC_INIT if XIP - select USE_DT_CODE_PARTITION if XIP - select CLOCK_CONTROL - select HAS_MCUX - select HAS_MCUX_LPUART - select HAS_MCUX_FLEXCAN - select HAS_MCUX_LPI2C - select HAS_MCUX_LPSPI - help - Enable support for NXP S32K3 MCUs family on Cortex-M7 cores diff --git a/soc/arm/nxp_s32/s32k/Kconfig.soc b/soc/arm/nxp_s32/s32k/Kconfig.soc deleted file mode 100644 index 978c5daf65a..00000000000 --- a/soc/arm/nxp_s32/s32k/Kconfig.soc +++ /dev/null @@ -1,62 +0,0 @@ -# NXP S32K MCUs family - -# Copyright 2023 NXP -# SPDX-License-Identifier: Apache-2.0 - -choice - prompt "NXP S32K MCUs family SoC Selection" - depends on SOC_SERIES_S32K3_M7 - -config SOC_S32K344_M7 - bool "SOC_S32K_M7" - select HAS_NXP_S32_HAL - -endchoice - -if SOC_SERIES_S32K3_M7 - -config SOC_PART_NUMBER_S32K344 - bool - -config SOC_PART_NUMBER_S32K3 - string - default "S32K344" if SOC_PART_NUMBER_S32K344 - help - This string holds the full part number of the SoC. It is a hidden option - that you should not set directly. The part number selection choice defines - the default value for this string. - -config IVT_HEADER_OFFSET - hex - depends on XIP - default $(dt_node_reg_addr_hex,$(dt_nodelabel_path,ivt_header)) - help - The offset address from flash base address for ivt header - -config IVT_HEADER_SIZE - hex - depends on XIP - default $(dt_node_reg_size_hex,$(dt_nodelabel_path,ivt_header)) - help - Size of ivt header region - -config NXP_S32_PMC_LMEN - bool "Last Mile regulator" - default y if CLOCK_CONTROL - help - Enables the Last Mile regulator, which regulates an external 1.5V - voltage on V15 down to the core and logic supply (V11 power domain), - which is typically 1.1V. - When enabling PLL as system clock, the PMC last mile regulator should - be enabled. - -config NXP_S32_PMC_LMBCTLEN - bool "External BCTL regulator for V15" - depends on NXP_S32_PMC_LMEN - help - This option must be selected if an external BJT between VDD_HV_A and - V15 is used on the PCB. The base of this BJT must be connected to the - VRC_CTRL pin and is controlled by the PMC to regulate a voltage of - 1.5V on V15 pin. - -endif diff --git a/soc/arm/nxp_s32/s32k/linker.ld b/soc/arm/nxp_s32/s32k/linker.ld deleted file mode 100644 index dbbca346ba0..00000000000 --- a/soc/arm/nxp_s32/s32k/linker.ld +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2023 NXP - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifdef CONFIG_XIP -MEMORY -{ - IVT_HEADER (r) : ORIGIN = CONFIG_FLASH_BASE_ADDRESS + CONFIG_IVT_HEADER_OFFSET, - LENGTH = CONFIG_IVT_HEADER_SIZE -} -#endif - -#include diff --git a/soc/arm/nxp_s32/s32k/soc.h b/soc/arm/nxp_s32/s32k/soc.h deleted file mode 100644 index fa29a960172..00000000000 --- a/soc/arm/nxp_s32/s32k/soc.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2023 NXP - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef _NXP_S32_S32K_SOC_H_ -#define _NXP_S32_S32K_SOC_H_ - -#include - -#if defined(CONFIG_CMSIS_RTOS_V2) -/* - * The HAL is defining these symbols already. To avoid redefinitions, - * let CMSIS RTOS wrapper define them. - */ -#undef TRUE -#undef FALSE -#endif - -#endif /* _NXP_S32_S32K_SOC_H_ */ diff --git a/soc/arm/nxp_s32/s32k3/CMakeLists.txt b/soc/arm/nxp_s32/s32k3/CMakeLists.txt new file mode 100644 index 00000000000..d65a1a2e73b --- /dev/null +++ b/soc/arm/nxp_s32/s32k3/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(soc.c) +zephyr_library_sources_ifdef(CONFIG_CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS mpu_regions.c) +zephyr_linker_sources(SECTIONS sections.ld) +zephyr_library_sources_ifdef(CONFIG_PLATFORM_SPECIFIC_INIT s32k3xx_startup.S) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nxp_s32/s32k3/Kconfig.defconfig.s32k344 b/soc/arm/nxp_s32/s32k3/Kconfig.defconfig.s32k344 new file mode 100644 index 00000000000..b1b534f6102 --- /dev/null +++ b/soc/arm/nxp_s32/s32k3/Kconfig.defconfig.s32k344 @@ -0,0 +1,14 @@ +# NXP S32K344 + +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +if SOC_S32K344 + +config SOC + default "s32k344" + +config FPU + default y + +endif # SOC_S32K344 diff --git a/soc/arm/nxp_s32/s32k3/Kconfig.defconfig.series b/soc/arm/nxp_s32/s32k3/Kconfig.defconfig.series new file mode 100644 index 00000000000..04d54fdc666 --- /dev/null +++ b/soc/arm/nxp_s32/s32k3/Kconfig.defconfig.series @@ -0,0 +1,37 @@ +# NXP S32K3XX MCU series + +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_S32K3XX + +config SOC_SERIES + default "s32k3" + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 2000000 + +config NUM_IRQS + # must be >= the highest interrupt number used + default 239 + +if !XIP +config FLASH_SIZE + default 0 +config FLASH_BASE_ADDRESS + default 0 +endif + +if NET_L2_ETHERNET + +config NET_TCP_CHECKSUM + default n + +config NET_UDP_CHECKSUM + default n + +endif # NET_L2_ETHERNET + +source "soc/arm/nxp_s32/s32k3/Kconfig.defconfig.s32k*" + +endif # SOC_SERIES_S32K3XX diff --git a/soc/arm/nxp_s32/s32k3/Kconfig.series b/soc/arm/nxp_s32/s32k3/Kconfig.series new file mode 100644 index 00000000000..50be01fe690 --- /dev/null +++ b/soc/arm/nxp_s32/s32k3/Kconfig.series @@ -0,0 +1,25 @@ +# NXP S32K3XX MCU series + +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_S32K3XX + bool "NXP S32K3XX MCU series" + select ARM + select CPU_CORTEX_M7 + select SOC_FAMILY_NXP_S32 + select HAS_NXP_S32_HAL + select CPU_HAS_FPU + select CPU_HAS_ARM_MPU + select CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS + select PLATFORM_SPECIFIC_INIT if XIP + select USE_DT_CODE_PARTITION if XIP + select CLOCK_CONTROL + select HAS_MCUX + select HAS_MCUX_LPUART + select HAS_MCUX_FLEXCAN + select HAS_MCUX_LPI2C + select HAS_MCUX_LPSPI + select HAS_MCUX_CACHE + help + Enable support for NXP S32K3XX MCU series. diff --git a/soc/arm/nxp_s32/s32k3/Kconfig.soc b/soc/arm/nxp_s32/s32k3/Kconfig.soc new file mode 100644 index 00000000000..6b8f4e3a883 --- /dev/null +++ b/soc/arm/nxp_s32/s32k3/Kconfig.soc @@ -0,0 +1,61 @@ +# NXP S32K3XX MCU series + +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +choice + prompt "NXP S32K3XX MCU selection" + depends on SOC_SERIES_S32K3XX + +config SOC_S32K344 + bool "s32k344" + +endchoice + +if SOC_SERIES_S32K3XX + +config SOC_PART_NUMBER_PS32K344EHVPBS + bool + +config SOC_PART_NUMBER + string + default "PS32K344EHVPBS" if SOC_PART_NUMBER_PS32K344EHVPBS + help + This string holds the full part number of the SoC. It is a hidden option + that you should not set directly. The part number selection choice defines + the default value for this string. + +config IVT_HEADER_OFFSET + hex + depends on XIP + default $(dt_node_reg_addr_hex,$(dt_nodelabel_path,ivt_header)) + help + The offset address from flash base address for ivt header + +config IVT_HEADER_SIZE + hex + depends on XIP + default $(dt_node_reg_size_hex,$(dt_nodelabel_path,ivt_header)) + help + Size of ivt header region + +config NXP_S32_PMC_LMEN + bool "Last Mile regulator" + default y if CLOCK_CONTROL + help + Enables the Last Mile regulator, which regulates an external 1.5V + voltage on V15 down to the core and logic supply (V11 power domain), + which is typically 1.1V. + When enabling PLL as system clock, the PMC last mile regulator should + be enabled. + +config NXP_S32_PMC_LMBCTLEN + bool "External BCTL regulator for V15" + depends on NXP_S32_PMC_LMEN + help + This option must be selected if an external BJT between VDD_HV_A and + V15 is used on the PCB. The base of this BJT must be connected to the + VRC_CTRL pin and is controlled by the PMC to regulate a voltage of + 1.5V on V15 pin. + +endif diff --git a/soc/arm/nxp_s32/s32k3/linker.ld b/soc/arm/nxp_s32/s32k3/linker.ld new file mode 100644 index 00000000000..8681f1cd3f3 --- /dev/null +++ b/soc/arm/nxp_s32/s32k3/linker.ld @@ -0,0 +1,15 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifdef CONFIG_XIP +MEMORY +{ + IVT_HEADER (r) : ORIGIN = CONFIG_FLASH_BASE_ADDRESS + CONFIG_IVT_HEADER_OFFSET, + LENGTH = CONFIG_IVT_HEADER_SIZE +} +#endif + +#include diff --git a/soc/arm/nxp_s32/s32k/mpu_regions.c b/soc/arm/nxp_s32/s32k3/mpu_regions.c similarity index 86% rename from soc/arm/nxp_s32/s32k/mpu_regions.c rename to soc/arm/nxp_s32/s32k3/mpu_regions.c index 9c4316d0aa9..acd3ee9d916 100644 --- a/soc/arm/nxp_s32/s32k/mpu_regions.c +++ b/soc/arm/nxp_s32/s32k3/mpu_regions.c @@ -6,7 +6,7 @@ #include #include -#include +#include #if !defined(CONFIG_XIP) extern char _rom_attr[]; @@ -35,9 +35,6 @@ static struct arm_mpu_region mpu_regions[] = { .attr = {(uint32_t)_rom_attr}, }, #endif - - /* DT-defined regions */ - DT_MEMORY_ATTR_APPLY(ARM_MPU_REGION_INIT) }; const struct arm_mpu_config mpu_config = { diff --git a/soc/arm/nxp_s32/s32k/s32k3xx_startup.S b/soc/arm/nxp_s32/s32k3/s32k3xx_startup.S similarity index 100% rename from soc/arm/nxp_s32/s32k/s32k3xx_startup.S rename to soc/arm/nxp_s32/s32k3/s32k3xx_startup.S diff --git a/soc/arm/nxp_s32/s32k/sections.ld b/soc/arm/nxp_s32/s32k3/sections.ld similarity index 100% rename from soc/arm/nxp_s32/s32k/sections.ld rename to soc/arm/nxp_s32/s32k3/sections.ld diff --git a/soc/arm/nxp_s32/s32k/soc.c b/soc/arm/nxp_s32/s32k3/soc.c similarity index 100% rename from soc/arm/nxp_s32/s32k/soc.c rename to soc/arm/nxp_s32/s32k3/soc.c diff --git a/soc/arm/nxp_s32/s32k3/soc.h b/soc/arm/nxp_s32/s32k3/soc.h new file mode 100644 index 00000000000..bbc53e18023 --- /dev/null +++ b/soc/arm/nxp_s32/s32k3/soc.h @@ -0,0 +1,26 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _NXP_S32_S32K_SOC_H_ +#define _NXP_S32_S32K_SOC_H_ + +#include + +#if defined(CONFIG_CMSIS_RTOS_V2) +/* + * The HAL is defining these symbols already. To avoid redefinitions, + * let CMSIS RTOS wrapper define them. + */ +#undef TRUE +#undef FALSE +#endif + +/* Aliases for peripheral base addresses */ + +/* SIUL2 */ +#define IP_SIUL2_0_BASE IP_SIUL2_BASE + +#endif /* _NXP_S32_S32K_SOC_H_ */ diff --git a/soc/arm/nxp_s32/s32ze/CMakeLists.txt b/soc/arm/nxp_s32/s32ze/CMakeLists.txt index 155354816f3..d0eb4cf78b1 100644 --- a/soc/arm/nxp_s32/s32ze/CMakeLists.txt +++ b/soc/arm/nxp_s32/s32ze/CMakeLists.txt @@ -6,3 +6,5 @@ zephyr_library_sources( ) zephyr_library_sources_ifdef(CONFIG_ARM_MPU mpu_regions.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/nxp_s32/s32ze/Kconfig.series b/soc/arm/nxp_s32/s32ze/Kconfig.series index 5414de3546f..c1f2d3606ec 100644 --- a/soc/arm/nxp_s32/s32ze/Kconfig.series +++ b/soc/arm/nxp_s32/s32ze/Kconfig.series @@ -14,5 +14,8 @@ config SOC_SERIES_S32ZE_R52 select VFP_DP_D16 select PLATFORM_SPECIFIC_INIT select SOC_FAMILY_NXP_S32 + select CLOCK_CONTROL + select HAS_MCUX + select HAS_MCUX_PIT help Enable support for NXP S32Z/E MCUs family on Cortex-R52 cores. diff --git a/soc/arm/nxp_s32/s32ze/Kconfig.soc b/soc/arm/nxp_s32/s32ze/Kconfig.soc index c8a1322f531..790751362d3 100644 --- a/soc/arm/nxp_s32/s32ze/Kconfig.soc +++ b/soc/arm/nxp_s32/s32ze/Kconfig.soc @@ -1,6 +1,6 @@ # NXP S32Z/E MCUs family -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # SPDX-License-Identifier: Apache-2.0 choice @@ -18,7 +18,7 @@ if SOC_SERIES_S32ZE_R52 config SOC_PART_NUMBER_S32Z27 bool -config SOC_PART_NUMBER_S32ZE_R52 +config SOC_PART_NUMBER string default "S32Z27" if SOC_PART_NUMBER_S32Z27 help @@ -26,14 +26,6 @@ config SOC_PART_NUMBER_S32ZE_R52 that you should not set directly. The part number selection choice defines the default value for this string. -config INIT_CLOCK_AT_BOOT_TIME - bool "Initialize clocks at boot time" - default y - help - Initialize clocks at boot time with the configuration generated through the - driver's configurator, instead of using the default SoC clock configuration - at reset. - config NXP_S32_RTU_INDEX int range 0 1 diff --git a/soc/arm/nxp_s32/s32ze/linker.ld b/soc/arm/nxp_s32/s32ze/linker.ld deleted file mode 100644 index c8a7570e891..00000000000 --- a/soc/arm/nxp_s32/s32ze/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright 2022 NXP - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/nxp_s32/s32ze/mpu_regions.c b/soc/arm/nxp_s32/s32ze/mpu_regions.c index aa4109f492f..33c41d362b5 100644 --- a/soc/arm/nxp_s32/s32ze/mpu_regions.c +++ b/soc/arm/nxp_s32/s32ze/mpu_regions.c @@ -5,7 +5,7 @@ */ #include -#include +#include #define DEVICE_REGION_START 0x40000000UL #define DEVICE_REGION_END 0x76FFFFFFUL diff --git a/soc/arm/nxp_s32/s32ze/soc.c b/soc/arm/nxp_s32/s32ze/soc.c index 4a1837f9dca..871536a26c6 100644 --- a/soc/arm/nxp_s32/s32ze/soc.c +++ b/soc/arm/nxp_s32/s32ze/soc.c @@ -12,11 +12,6 @@ #include -#ifdef CONFIG_INIT_CLOCK_AT_BOOT_TIME -#include -#include -#endif - void z_arm_platform_init(void) { /* enable peripheral port access at EL1 and EL0 */ @@ -26,6 +21,12 @@ void z_arm_platform_init(void) barrier_dsync_fence_full(); barrier_isync_fence_full(); + /* + * Take exceptions in Arm mode because Zephyr ASM code for Cortex-R Aarch32 + * is written for Arm + */ + __set_SCTLR(__get_SCTLR() & ~SCTLR_TE_Msk); + if (IS_ENABLED(CONFIG_ICACHE)) { if (!(__get_SCTLR() & SCTLR_I_Msk)) { L1C_InvalidateICacheAll(); @@ -47,11 +48,6 @@ static int soc_init(void) { OsIf_Init(NULL); -#ifdef CONFIG_INIT_CLOCK_AT_BOOT_TIME - /* Initialize clocks with tool generated code */ - Clock_Ip_Init(Clock_Ip_aClockConfig); -#endif - return 0; } diff --git a/soc/arm/nxp_s32/s32ze/soc.h b/soc/arm/nxp_s32/s32ze/soc.h index 1bacb430a00..f7c96aa2ed9 100644 --- a/soc/arm/nxp_s32/s32ze/soc.h +++ b/soc/arm/nxp_s32/s32ze/soc.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 NXP + * Copyright 2022-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,4 +10,61 @@ /* Do not let CMSIS to handle GIC */ #define __GIC_PRESENT 0 +#if defined(CONFIG_SOC_S32Z27_R52) +#include +#else +#error "SoC not supported" +#endif + +/* Aliases for peripheral base addresses */ + +/* SIUL2 */ +#define IP_SIUL2_2_BASE 0U /* instance does not exist on this SoC */ + +/* LINFlexD*/ +#define IP_LINFLEX_12_BASE IP_MSC_0_LIN_BASE + +/* SWT */ +#define IP_SWT_0_BASE IP_CE_SWT_0_BASE +#define IP_SWT_1_BASE IP_CE_SWT_1_BASE +#define IP_SWT_2_BASE IP_RTU0__SWT_0_BASE +#define IP_SWT_3_BASE IP_RTU0__SWT_1_BASE +#define IP_SWT_4_BASE IP_RTU0__SWT_2_BASE +#define IP_SWT_5_BASE IP_RTU0__SWT_3_BASE +#define IP_SWT_6_BASE IP_RTU0__SWT_4_BASE +#define IP_SWT_7_BASE IP_RTU1__SWT_0_BASE +#define IP_SWT_8_BASE IP_RTU1__SWT_1_BASE +#define IP_SWT_9_BASE IP_RTU1__SWT_2_BASE +#define IP_SWT_10_BASE IP_RTU1__SWT_3_BASE +#define IP_SWT_11_BASE IP_RTU1__SWT_4_BASE +#define IP_SWT_12_BASE IP_SMU__SWT_BASE + +/* STM */ +#define IP_STM_0_BASE IP_CE_STM_0_BASE +#define IP_STM_1_BASE IP_CE_STM_1_BASE +#define IP_STM_2_BASE IP_CE_STM_2_BASE +#define IP_STM_3_BASE IP_RTU0__STM_0_BASE +#define IP_STM_4_BASE IP_RTU0__STM_1_BASE +#define IP_STM_5_BASE IP_RTU0__STM_2_BASE +#define IP_STM_6_BASE IP_RTU0__STM_3_BASE +#define IP_STM_7_BASE IP_RTU1__STM_0_BASE +#define IP_STM_8_BASE IP_RTU1__STM_1_BASE +#define IP_STM_9_BASE IP_RTU1__STM_2_BASE +#define IP_STM_10_BASE IP_RTU1__STM_3_BASE +#define IP_STM_11_BASE IP_SMU__STM_0_BASE +#define IP_STM_12_BASE IP_SMU__STM_2_BASE + +/* NETC */ +#define IP_NETC_EMDIO_0_BASE IP_NETC__EMDIO_BASE_BASE + +/* MRU */ +#define IP_MRU_0_BASE IP_RTU0__MRU_0_BASE +#define IP_MRU_1_BASE IP_RTU0__MRU_1_BASE +#define IP_MRU_2_BASE IP_RTU0__MRU_2_BASE +#define IP_MRU_3_BASE IP_RTU0__MRU_3_BASE +#define IP_MRU_4_BASE IP_RTU1__MRU_0_BASE +#define IP_MRU_5_BASE IP_RTU1__MRU_1_BASE +#define IP_MRU_6_BASE IP_RTU1__MRU_2_BASE +#define IP_MRU_7_BASE IP_RTU1__MRU_3_BASE + #endif /* _NXP_S32_S32ZE_SOC_H_ */ diff --git a/soc/arm/quicklogic_eos_s3/CMakeLists.txt b/soc/arm/quicklogic_eos_s3/CMakeLists.txt index 5da2746a1bc..224b298c409 100644 --- a/soc/arm/quicklogic_eos_s3/CMakeLists.txt +++ b/soc/arm/quicklogic_eos_s3/CMakeLists.txt @@ -4,3 +4,5 @@ zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/quicklogic_eos_s3/linker.ld b/soc/arm/quicklogic_eos_s3/linker.ld deleted file mode 100644 index 448ac908598..00000000000 --- a/soc/arm/quicklogic_eos_s3/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* -# Copyright (c) 2020 Antmicro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/renesas_ra/CMakeLists.txt b/soc/arm/renesas_ra/CMakeLists.txt new file mode 100644 index 00000000000..b6a22aa757b --- /dev/null +++ b/soc/arm/renesas_ra/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +zephyr_include_directories(common) + +add_subdirectory(${SOC_SERIES}) diff --git a/soc/arm/renesas_ra/Kconfig b/soc/arm/renesas_ra/Kconfig new file mode 100644 index 00000000000..628b75a93de --- /dev/null +++ b/soc/arm/renesas_ra/Kconfig @@ -0,0 +1,18 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FAMILY_RA + bool + +if SOC_FAMILY_RA + +config SOC_FAMILY + string + default "renesas_ra" + +config SERIES_SPECIFIC_SOC_INIT + bool "Use series specific initialize" + +source "soc/arm/renesas_ra/*/Kconfig.soc" + +endif # SOC_FAMILY_RA diff --git a/soc/arm/renesas_ra/Kconfig.defconfig b/soc/arm/renesas_ra/Kconfig.defconfig new file mode 100644 index 00000000000..e5e211a94b3 --- /dev/null +++ b/soc/arm/renesas_ra/Kconfig.defconfig @@ -0,0 +1,4 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +source "soc/arm/renesas_ra/*/Kconfig.defconfig.series" diff --git a/soc/arm/renesas_ra/Kconfig.soc b/soc/arm/renesas_ra/Kconfig.soc new file mode 100644 index 00000000000..2652ee94d2e --- /dev/null +++ b/soc/arm/renesas_ra/Kconfig.soc @@ -0,0 +1,4 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +source "soc/arm/renesas_ra/*/Kconfig.series" diff --git a/soc/arm/renesas_ra/common/pinctrl_ra.h b/soc/arm/renesas_ra/common/pinctrl_ra.h new file mode 100644 index 00000000000..d61f1e418d5 --- /dev/null +++ b/soc/arm/renesas_ra/common/pinctrl_ra.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_ARM_RENESAS_RA_COMMON_RA_PINCTRL_SOC_H_ +#define ZEPHYR_SOC_ARM_RENESAS_RA_COMMON_RA_PINCTRL_SOC_H_ + +enum { + PmnPFS_PODR_POS, + PmnPFS_PIDR_POS, + PmnPFS_PDR_POS, + PmnPFS_RSV3_POS, + PmnPFS_PCR_POS, + PmnPFS_RSV5_POS, + PmnPFS_NCODR_POS, + PmnPFS_RSV7_POS, + PmnPFS_RSV8_POS, + PmnPFS_RSV9_POS, + PmnPFS_DSCR_POS, + PmnPFS_DSCR1_POS, + PmnPFS_EOR_POS, + PmnPFS_EOF_POS, + PmnPFS_ISEL_POS, + PmnPFS_ASEL_POS, + PmnPFS_PMR_POS, +}; + +struct pinctrl_ra_pin { + union { + uint32_t config; + struct { + uint8_t PODR: 1; + uint8_t PIDR: 1; + uint8_t PDR: 1; + uint8_t RESERVED3: 1; + uint8_t PCR: 1; + uint8_t RESERVED5: 1; + uint8_t NCODR: 1; + uint8_t RESERVED7: 1; + uint8_t RESERVED8: 1; + uint8_t RESERVED9: 1; + uint8_t DSCR: 2; + uint8_t EOFR: 2; + uint8_t ISEL: 1; + uint8_t ASEL: 1; + uint8_t PMR: 1; + uint8_t RESERVED17: 7; + uint8_t PSEL: 5; + uint8_t RESERVED29: 3; + }; + /* Using RESERVED fields for store pin and port info. */ + struct { + uint32_t UNUSED0: 17; + uint8_t pin: 4; + uint8_t port: 3; + uint32_t UNUSED24: 5; + uint8_t port4: 3; + }; + }; +}; + +typedef struct pinctrl_ra_pin pinctrl_soc_pin_t; + +extern int pinctrl_ra_query_config(uint32_t port, uint32_t pin, + struct pinctrl_ra_pin *const pincfg); + +/** + * @brief Utility macro to initialize each pin. + * + * @param node_id Node identifier. + * @param prop Property name. + * @param idx Property entry index. + */ +#define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx) \ + { \ + .config = DT_PROP_BY_IDX(node_id, prop, idx), \ + }, + +/** + * @brief Utility macro to initialize state pins contained in a given property. + * + * @param node_id Node identifier. + * @param prop Property name describing state pins. + */ +#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \ + { \ + DT_FOREACH_CHILD_VARGS(DT_PHANDLE(node_id, prop), DT_FOREACH_PROP_ELEM, pinmux, \ + Z_PINCTRL_STATE_PIN_INIT) \ + } + +#endif /* ZEPHYR_SOC_ARM_RENESAS_RA_RA6E1_PINCTRL_SOC_H_ */ diff --git a/soc/arm/renesas_ra/common/ra_common_soc.h b/soc/arm/renesas_ra/common/ra_common_soc.h new file mode 100644 index 00000000000..60559793743 --- /dev/null +++ b/soc/arm/renesas_ra/common/ra_common_soc.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_ARM_RENESAS_RA_COMMON_RA_COMMON_SOC_H_ +#define ZEPHYR_SOC_ARM_RENESAS_RA_COMMON_RA_COMMON_SOC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_SOC_ARM_RENESAS_RA_COMMON_RA_COMMON_SOC_H_ */ diff --git a/soc/arm/renesas_ra/ra4m1/CMakeLists.txt b/soc/arm/renesas_ra/ra4m1/CMakeLists.txt new file mode 100644 index 00000000000..4debbfdbf8a --- /dev/null +++ b/soc/arm/renesas_ra/ra4m1/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/renesas_ra/ra4m1/Kconfig.defconfig.r7fa4m1xxxxxx b/soc/arm/renesas_ra/ra4m1/Kconfig.defconfig.r7fa4m1xxxxxx new file mode 100644 index 00000000000..c138e20d85c --- /dev/null +++ b/soc/arm/renesas_ra/ra4m1/Kconfig.defconfig.r7fa4m1xxxxxx @@ -0,0 +1,9 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +if SOC_R7FA4M1AB3CFM + +config SOC + default "r7fa4m1ab3cfm" + +endif # SOC_R7FA4M1AB3CFM diff --git a/soc/arm/renesas_ra/ra4m1/Kconfig.defconfig.series b/soc/arm/renesas_ra/ra4m1/Kconfig.defconfig.series new file mode 100644 index 00000000000..99e8e3f639d --- /dev/null +++ b/soc/arm/renesas_ra/ra4m1/Kconfig.defconfig.series @@ -0,0 +1,14 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_RA4M1 + +rsource "Kconfig.defconfig.r7fa4*" + +config SOC_SERIES + default "ra4m1" + +config NUM_IRQS + default 32 + +endif # SOC_SERIES_RA4M1 diff --git a/soc/arm/renesas_ra/ra4m1/Kconfig.series b/soc/arm/renesas_ra/ra4m1/Kconfig.series new file mode 100644 index 00000000000..7307a2d26c0 --- /dev/null +++ b/soc/arm/renesas_ra/ra4m1/Kconfig.series @@ -0,0 +1,13 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_RA4M1 + bool "Renesas RA4M1" + select ARM + select CPU_CORTEX_M4 + select CPU_HAS_ARM_MPU + select CPU_CORTEX_M_HAS_SYSTICK + select DYNAMIC_INTERRUPTS + select SOC_FAMILY_RA + select TIMER_READS_ITS_FREQUENCY_AT_RUNTIME + select XIP diff --git a/soc/arm/renesas_ra/ra4m1/Kconfig.soc b/soc/arm/renesas_ra/ra4m1/Kconfig.soc new file mode 100644 index 00000000000..a7b402fd291 --- /dev/null +++ b/soc/arm/renesas_ra/ra4m1/Kconfig.soc @@ -0,0 +1,11 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +choice + prompt "Renesas RA4M1 SoC Selection" + depends on SOC_SERIES_RA4M1 + +config SOC_R7FA4M1AB3CFM + bool "R7FA4M1AB3CFM" + +endchoice diff --git a/soc/arm/renesas_ra/ra4m1/linker.ld b/soc/arm/renesas_ra/ra4m1/linker.ld new file mode 100644 index 00000000000..44d5ee51889 --- /dev/null +++ b/soc/arm/renesas_ra/ra4m1/linker.ld @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#include diff --git a/soc/arm/renesas_ra/ra4m1/pinctrl_soc.h b/soc/arm/renesas_ra/ra4m1/pinctrl_soc.h new file mode 100644 index 00000000000..e149509fab2 --- /dev/null +++ b/soc/arm/renesas_ra/ra4m1/pinctrl_soc.h @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../common/pinctrl_ra.h" diff --git a/soc/arm/renesas_ra/ra4m1/soc.h b/soc/arm/renesas_ra/ra4m1/soc.h new file mode 100644 index 00000000000..127ee9ab444 --- /dev/null +++ b/soc/arm/renesas_ra/ra4m1/soc.h @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../common/ra_common_soc.h" diff --git a/soc/arm/renesas_rcar/gen3/CMakeLists.txt b/soc/arm/renesas_rcar/gen3/CMakeLists.txt index 092b4b2c828..4356fe77d51 100644 --- a/soc/arm/renesas_rcar/gen3/CMakeLists.txt +++ b/soc/arm/renesas_rcar/gen3/CMakeLists.txt @@ -5,3 +5,5 @@ zephyr_sources( soc.c ) zephyr_library_sources_ifdef(CONFIG_SOC_R8A77951 pfc_r8a77951.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/renesas_rcar/gen3/linker.ld b/soc/arm/renesas_rcar/gen3/linker.ld deleted file mode 100644 index 257f496c64d..00000000000 --- a/soc/arm/renesas_rcar/gen3/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2021 IoT.bzh - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/renesas_rzt2m/CMakeLists.txt b/soc/arm/renesas_rzt2m/CMakeLists.txt new file mode 100644 index 00000000000..05fd66ec83c --- /dev/null +++ b/soc/arm/renesas_rzt2m/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +zephyr_sources( + soc.c + ) diff --git a/soc/arm/renesas_rzt2m/Kconfig b/soc/arm/renesas_rzt2m/Kconfig new file mode 100644 index 00000000000..fc2f6e81c4e --- /dev/null +++ b/soc/arm/renesas_rzt2m/Kconfig @@ -0,0 +1,15 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +config SOC_RENESAS_RZT2M + bool + +if SOC_RENESAS_RZT2M + +config SOC_PART_NUMBER_R9A07G075 + bool + +config SOC_PART_NUMBER + default SOC_PART_NUMBER_R9A07G075 + +endif # SOC_RENESAS_RZT2M diff --git a/soc/arm/renesas_rzt2m/Kconfig.defconfig b/soc/arm/renesas_rzt2m/Kconfig.defconfig new file mode 100644 index 00000000000..72f828d4351 --- /dev/null +++ b/soc/arm/renesas_rzt2m/Kconfig.defconfig @@ -0,0 +1,24 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +if SOC_RENESAS_RZT2M + +config SOC + default "renesas_rzt2m" + +config NUM_IRQS + default 994 + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 20000000 + +config FPU + default y + +config FLASH_SIZE + default 0 + +config FLASH_BASE_ADDRESS + default 0 + +endif # SOC_RENESAS_RZT2M diff --git a/soc/arm/renesas_rzt2m/Kconfig.soc b/soc/arm/renesas_rzt2m/Kconfig.soc new file mode 100644 index 00000000000..0275833b792 --- /dev/null +++ b/soc/arm/renesas_rzt2m/Kconfig.soc @@ -0,0 +1,12 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +config SOC_RENESAS_RZT2M + bool "Renesas RZ/T2M MCU" + select ARM + select CPU_CORTEX_R52 + select CPU_HAS_ARM_MPU + select GIC_V3 + select GIC_SINGLE_SECURITY_STATE + select ARM_ARCH_TIMER + select SYSCON diff --git a/soc/arm/renesas_rzt2m/linker.ld b/soc/arm/renesas_rzt2m/linker.ld new file mode 100644 index 00000000000..3a016555ba9 --- /dev/null +++ b/soc/arm/renesas_rzt2m/linker.ld @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include diff --git a/soc/arm/renesas_rzt2m/pinctrl_soc.h b/soc/arm/renesas_rzt2m/pinctrl_soc.h new file mode 100644 index 00000000000..d740d6c115e --- /dev/null +++ b/soc/arm/renesas_rzt2m/pinctrl_soc.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_ARM_RENESAS_RZT2M_PINCTRL_H_ +#define ZEPHYR_SOC_ARM_RENESAS_RZT2M_PINCTRL_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct pinctrl_soc_pin_t { + uint32_t port; + uint32_t pin; + uint32_t func; + uint32_t input_enable: 1; + uint32_t output_enable: 1; + uint32_t pull_up: 1; + uint32_t pull_down: 1; + uint32_t high_impedance: 1; + uint32_t slew_rate: 2; + uint8_t drive_strength; + uint32_t schmitt_enable: 1; +} pinctrl_soc_pin_t; + +#define RZT2M_GET_PORT(pinctrl) ((pinctrl >> 16) & 0xff) +#define RZT2M_GET_PIN(pinctrl) ((pinctrl >> 8) & 0xff) +#define RZT2M_GET_FUNC(pinctrl) (pinctrl & 0xff) + +#define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx) \ + { \ + .port = RZT2M_GET_PORT(DT_PROP_BY_IDX(node_id, prop, idx)), \ + .pin = RZT2M_GET_PIN(DT_PROP_BY_IDX(node_id, prop, idx)), \ + .func = RZT2M_GET_FUNC(DT_PROP_BY_IDX(node_id, prop, idx)), \ + .input_enable = DT_PROP(node_id, input_enable), \ + .pull_up = DT_PROP(node_id, bias_pull_up), \ + .pull_down = DT_PROP(node_id, bias_pull_down), \ + .high_impedance = DT_PROP(node_id, bias_high_impedance), \ + .slew_rate = DT_ENUM_IDX(node_id, slew_rate), \ + .drive_strength = DT_ENUM_IDX(node_id, drive_strength), \ + .schmitt_enable = DT_PROP(node_id, input_schmitt_enable), \ + }, + +#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \ + {DT_FOREACH_CHILD_VARGS(DT_PHANDLE(node_id, prop), \ + DT_FOREACH_PROP_ELEM, pinmux, \ + Z_PINCTRL_STATE_PIN_INIT)} + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_SOC_ARM_RENESAS_RZT2M_PINCTRL_H_ */ diff --git a/soc/arm/renesas_rzt2m/soc.c b/soc/arm/renesas_rzt2m/soc.c new file mode 100644 index 00000000000..5a854090229 --- /dev/null +++ b/soc/arm/renesas_rzt2m/soc.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "soc.h" +#include + +static const struct device *const prcrn_dev = DEVICE_DT_GET(DT_NODELABEL(prcrn)); +static const struct device *const prcrs_dev = DEVICE_DT_GET(DT_NODELABEL(prcrs)); + +void rzt2m_unlock_prcrn(uint32_t mask) +{ + uint32_t prcrn; + + syscon_read_reg(prcrn_dev, 0, &prcrn); + prcrn |= PRC_KEY_CODE | mask; + + syscon_write_reg(prcrn_dev, 0, prcrn); +} + +void rzt2m_lock_prcrn(uint32_t mask) +{ + uint32_t prcrn; + + syscon_read_reg(prcrn_dev, 0, &prcrn); + prcrn &= ~mask; + prcrn |= PRC_KEY_CODE; + + syscon_write_reg(prcrn_dev, 0, prcrn); +} + +void rzt2m_unlock_prcrs(uint32_t mask) +{ + uint32_t prcrs; + + syscon_read_reg(prcrs_dev, 0, &prcrs); + prcrs |= PRC_KEY_CODE | mask; + + syscon_write_reg(prcrs_dev, 0, prcrs); +} + +void rzt2m_lock_prcrs(uint32_t mask) +{ + uint32_t prcrs; + + syscon_read_reg(prcrs_dev, 0, &prcrs); + prcrs &= ~mask; + prcrs |= PRC_KEY_CODE; + + syscon_write_reg(prcrs_dev, 0, prcrs); +} + +void rzt2m_enable_counters(void) +{ + const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(gsc)); + + syscon_write_reg(dev, 0, CNTCR_EN); +} + +static int rzt2m_init(void) +{ + /* Unlock the Protect Registers + * so that device drivers can access configuration registers of peripherals. + */ + /* After the device drivers are done, lock the Protect Registers. */ + + rzt2m_enable_counters(); + return 0; +} + +SYS_INIT(rzt2m_init, PRE_KERNEL_1, 0); diff --git a/soc/arm/renesas_rzt2m/soc.h b/soc/arm/renesas_rzt2m/soc.h new file mode 100644 index 00000000000..02bd03b69a1 --- /dev/null +++ b/soc/arm/renesas_rzt2m/soc.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _SOC__H_ +#define _SOC__H_ + +/* Do not let CMSIS to handle GIC and Timer */ +#include +#define __GIC_PRESENT 0 +#define __TIM_PRESENT 0 + +/* Global system counter */ +#define CNTCR_EN BIT(0) +#define CNTCR_HDBG BIT(1) + +/* Safety area protect register */ +#define PRCRS_CLK BIT(0) +#define PRCRS_LPC_RESET BIT(1) +#define PRCRS_GPIO BIT(2) +#define PRCRS_SYS_CTRL BIT(3) + +/* Non-safety area protect register */ +#define PRCRN_PRC0 BIT(0) +#define PRCRN_PRC1 BIT(1) +#define PRCRN_PRC2 BIT(2) + +/* PRC Key Code - this value is required to allow any write operation + * to the PRCRS / PRCRN registers. + * See section 10.2 of the RZ/T2M User's Manual: Hardware. + */ +#define PRC_KEY_CODE 0xa500 + +void rzt2m_unlock_prcrn(uint32_t mask); +void rzt2m_lock_prcrn(uint32_t mask); +void rzt2m_unlock_prcrs(uint32_t mask); +void rzt2m_lock_prcrs(uint32_t mask); + +#endif /* _SOC__H_ */ diff --git a/soc/arm/renesas_smartbond/da1469x/CMakeLists.txt b/soc/arm/renesas_smartbond/da1469x/CMakeLists.txt index 094293e9f32..115f3a34028 100644 --- a/soc/arm/renesas_smartbond/da1469x/CMakeLists.txt +++ b/soc/arm/renesas_smartbond/da1469x/CMakeLists.txt @@ -7,3 +7,5 @@ zephyr_linker_sources( ) zephyr_library() zephyr_library_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/renesas_smartbond/da1469x/Kconfig.defconfig.da14695 b/soc/arm/renesas_smartbond/da1469x/Kconfig.defconfig.da14695 new file mode 100644 index 00000000000..101e275b79f --- /dev/null +++ b/soc/arm/renesas_smartbond/da1469x/Kconfig.defconfig.da14695 @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Renesas Electronics Corporation and/or its affiliates +# SPDX-License-Identifier: Apache-2.0 + +if SOC_DA14695 + +config SOC + default "da14695" + +endif # SOC_DA14695 diff --git a/soc/arm/renesas_smartbond/da1469x/Kconfig.soc b/soc/arm/renesas_smartbond/da1469x/Kconfig.soc index edce4039867..b1e7eddb850 100644 --- a/soc/arm/renesas_smartbond/da1469x/Kconfig.soc +++ b/soc/arm/renesas_smartbond/da1469x/Kconfig.soc @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Renesas Electronics Corporation +# Copyright (c) 2022-2023 Renesas Electronics Corporation and/or its affiliates # SPDX-License-Identifier: Apache-2.0 choice @@ -8,4 +8,7 @@ choice config SOC_DA14699 bool "DA14699" +config SOC_DA14695 + bool "DA14695" + endchoice diff --git a/soc/arm/renesas_smartbond/da1469x/linker.ld b/soc/arm/renesas_smartbond/da1469x/linker.ld deleted file mode 100644 index f3b675269bb..00000000000 --- a/soc/arm/renesas_smartbond/da1469x/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2022 Renesas Electronics Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/rpi_pico/rp2/CMakeLists.txt b/soc/arm/rpi_pico/rp2/CMakeLists.txt index 210f5623ae9..119517e5e1c 100644 --- a/soc/arm/rpi_pico/rp2/CMakeLists.txt +++ b/soc/arm/rpi_pico/rp2/CMakeLists.txt @@ -4,3 +4,5 @@ zephyr_library() zephyr_library_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/rpi_pico/rp2/linker.ld b/soc/arm/rpi_pico/rp2/linker.ld index bf594a89e98..5e1db9a8175 100644 --- a/soc/arm/rpi_pico/rp2/linker.ld +++ b/soc/arm/rpi_pico/rp2/linker.ld @@ -26,4 +26,4 @@ SECTIONS } #endif /* CONFIG_RP2_REQUIRES_SECOND_STAGE_BOOT */ -#include +#include diff --git a/soc/arm/silabs_exx32/Kconfig b/soc/arm/silabs_exx32/Kconfig index a99c060c68f..d0bbf68c885 100644 --- a/soc/arm/silabs_exx32/Kconfig +++ b/soc/arm/silabs_exx32/Kconfig @@ -8,6 +8,7 @@ config SOC_FAMILY_EXX32 select BUILD_OUTPUT_HEX if SOC_FAMILY_EXX32 + config SOC_FAMILY string default "silabs_exx32" @@ -21,11 +22,11 @@ config SOC_PART_NUMBER that you should not set directly. The part number selection choice defines the default value for this string. -config SOC_GECKO_SERIES2 +config SOC_GECKO_SERIES0 bool help - Set if we're building for Gecko Series 2 SoC. - This is equivalent of _SILICON_LABS_32B_SERIES_2 definition in HAL + Set if we're building for Gecko Series 0 SoC. + This is equivalent of _SILICON_LABS_32B_SERIES_0 definition in HAL code. config SOC_GECKO_SERIES1 @@ -35,6 +36,13 @@ config SOC_GECKO_SERIES1 This is equivalent of _SILICON_LABS_32B_SERIES_1 definition in HAL code. +config SOC_GECKO_SERIES2 + bool + help + Set if we're building for Gecko Series 2 SoC. + This is equivalent of _SILICON_LABS_32B_SERIES_2 definition in HAL + code. + config SOC_GECKO_BURTC bool help @@ -319,8 +327,14 @@ config SOC_GECKO_HAS_HFRCO_FREQRANGE If disabled, indicates that configuration of HFRCO frequency for corresponding SOC is not supported via this field. This is the case for e.g. efm32hg, efm32wg series. +config SOC_GECKO_HAS_RADIO + bool + help + If enabled, indicates that the SoC has a Radio PHY. + config SOC_GECKO_USE_RAIL bool "Use RAIL (Radio Abstraction Interface Layer)" + depends on SOC_GECKO_HAS_RADIO help RAIL (Radio Abstraction Interface Layer) is a library needed to use the EFR radio hardware. This option enable the proper set of features to allow to properly compile diff --git a/soc/arm/silabs_exx32/common/CMakeLists.txt b/soc/arm/silabs_exx32/common/CMakeLists.txt index ac965e28d46..27e11228b97 100644 --- a/soc/arm/silabs_exx32/common/CMakeLists.txt +++ b/soc/arm/silabs_exx32/common/CMakeLists.txt @@ -6,3 +6,5 @@ zephyr_sources_ifdef(CONFIG_SOC_GECKO_PM_BACKEND_EMU soc_power.c) zephyr_sources_ifdef(CONFIG_SOC_GECKO_PM_BACKEND_PMGR soc_power_pmgr.c) zephyr_include_directories(.) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/silabs_exx32/common/sl_device_init_hfxo_config.h b/soc/arm/silabs_exx32/common/sl_device_init_hfxo_config.h new file mode 100644 index 00000000000..533a591fbde --- /dev/null +++ b/soc/arm/silabs_exx32/common/sl_device_init_hfxo_config.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef SL_DEVICE_INIT_HFXO_CONFIG_H +#define SL_DEVICE_INIT_HFXO_CONFIG_H + +#include + +#define SL_DEVICE_INIT_HFXO_MODE cmuHfxoOscMode_Crystal +#define SL_DEVICE_INIT_HFXO_FREQ DT_PROP(DT_NODELABEL(clk_hfxo), clock_frequency) +#define SL_DEVICE_INIT_HFXO_CTUNE DT_PROP(DT_NODELABEL(clk_hfxo), ctune) + +#endif /* SL_DEVICE_INIT_HFXO_CONFIG_H */ diff --git a/soc/arm/silabs_exx32/efm32gg11b/Kconfig.series b/soc/arm/silabs_exx32/efm32gg11b/Kconfig.series index 50d8a7eb0aa..34fa472c23d 100644 --- a/soc/arm/silabs_exx32/efm32gg11b/Kconfig.series +++ b/soc/arm/silabs_exx32/efm32gg11b/Kconfig.series @@ -18,5 +18,6 @@ config SOC_SERIES_EFM32GG11B select SOC_GECKO_EMU select SOC_GECKO_GPIO select SOC_GECKO_TRNG + select SOC_GECKO_SERIES1 help Enable support for EFM32 GiantGecko MCU series diff --git a/soc/arm/silabs_exx32/efm32gg11b/linker.ld b/soc/arm/silabs_exx32/efm32gg11b/linker.ld deleted file mode 100644 index 95b76e19ce0..00000000000 --- a/soc/arm/silabs_exx32/efm32gg11b/linker.ld +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (c) 2019 Interay Solutions B.V. - * Copyright (c) 2019 Oane Kingma - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images. - */ - - -#include diff --git a/soc/arm/silabs_exx32/efm32gg12b/Kconfig.series b/soc/arm/silabs_exx32/efm32gg12b/Kconfig.series index 0f2c18cfbb4..e8dcf52cf17 100644 --- a/soc/arm/silabs_exx32/efm32gg12b/Kconfig.series +++ b/soc/arm/silabs_exx32/efm32gg12b/Kconfig.series @@ -17,5 +17,6 @@ config SOC_SERIES_EFM32GG12B select SOC_GECKO_EMU select SOC_GECKO_GPIO select SOC_GECKO_TRNG + select SOC_GECKO_SERIES1 help Enable support for EFM32 GiantGecko MCU series diff --git a/soc/arm/silabs_exx32/efm32gg12b/linker.ld b/soc/arm/silabs_exx32/efm32gg12b/linker.ld deleted file mode 100644 index c7955ec596c..00000000000 --- a/soc/arm/silabs_exx32/efm32gg12b/linker.ld +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2023 Antmicro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images. - */ - -#include diff --git a/soc/arm/silabs_exx32/efm32hg/Kconfig.series b/soc/arm/silabs_exx32/efm32hg/Kconfig.series index 4acdfa793cc..33793b5386d 100644 --- a/soc/arm/silabs_exx32/efm32hg/Kconfig.series +++ b/soc/arm/silabs_exx32/efm32hg/Kconfig.series @@ -13,5 +13,6 @@ config SOC_SERIES_EFM32HG select SOC_GECKO_CMU select SOC_GECKO_GPIO select HAS_PM + select SOC_GECKO_SERIES0 help Enable support for EFM32 Happy Gecko MCU series diff --git a/soc/arm/silabs_exx32/efm32hg/linker.ld b/soc/arm/silabs_exx32/efm32hg/linker.ld deleted file mode 100644 index ff791e999d2..00000000000 --- a/soc/arm/silabs_exx32/efm32hg/linker.ld +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2018 Marcio Montenegro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images. - */ - - -#include diff --git a/soc/arm/silabs_exx32/efm32jg12b/linker.ld b/soc/arm/silabs_exx32/efm32jg12b/linker.ld deleted file mode 100644 index e93018c0980..00000000000 --- a/soc/arm/silabs_exx32/efm32jg12b/linker.ld +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2018 Christian Taedcke - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images. - */ - - -#include diff --git a/soc/arm/silabs_exx32/efm32pg12b/linker.ld b/soc/arm/silabs_exx32/efm32pg12b/linker.ld deleted file mode 100644 index e93018c0980..00000000000 --- a/soc/arm/silabs_exx32/efm32pg12b/linker.ld +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2018 Christian Taedcke - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images. - */ - - -#include diff --git a/soc/arm/silabs_exx32/efm32pg1b/Kconfig.series b/soc/arm/silabs_exx32/efm32pg1b/Kconfig.series index caeae082a3b..5a22fa29908 100644 --- a/soc/arm/silabs_exx32/efm32pg1b/Kconfig.series +++ b/soc/arm/silabs_exx32/efm32pg1b/Kconfig.series @@ -19,5 +19,6 @@ config SOC_SERIES_EFM32PG1B select SOC_GECKO_EMU select SOC_GECKO_GPIO select HAS_PM + select SOC_GECKO_SERIES1 help Enable support for EFM32 PearlGecko MCU series diff --git a/soc/arm/silabs_exx32/efm32pg1b/linker.ld b/soc/arm/silabs_exx32/efm32pg1b/linker.ld deleted file mode 100644 index e93018c0980..00000000000 --- a/soc/arm/silabs_exx32/efm32pg1b/linker.ld +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2018 Christian Taedcke - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images. - */ - - -#include diff --git a/soc/arm/silabs_exx32/efm32wg/Kconfig.series b/soc/arm/silabs_exx32/efm32wg/Kconfig.series index f339c755e05..99dfba375d1 100644 --- a/soc/arm/silabs_exx32/efm32wg/Kconfig.series +++ b/soc/arm/silabs_exx32/efm32wg/Kconfig.series @@ -15,5 +15,6 @@ config SOC_SERIES_EFM32WG select SOC_GECKO_CMU select SOC_GECKO_GPIO select HAS_PM + select SOC_GECKO_SERIES0 help Enable support for EFM32 WonderGecko MCU series diff --git a/soc/arm/silabs_exx32/efm32wg/linker.ld b/soc/arm/silabs_exx32/efm32wg/linker.ld deleted file mode 100644 index 7c8c33eb937..00000000000 --- a/soc/arm/silabs_exx32/efm32wg/linker.ld +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2017 Christian Taedcke - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images. - */ - - -#include diff --git a/soc/arm/silabs_exx32/efr32bg13p/Kconfig.series b/soc/arm/silabs_exx32/efr32bg13p/Kconfig.series index e7f524a026f..f48d53d861e 100644 --- a/soc/arm/silabs_exx32/efr32bg13p/Kconfig.series +++ b/soc/arm/silabs_exx32/efr32bg13p/Kconfig.series @@ -11,6 +11,7 @@ config SOC_SERIES_EFR32BG13P select CPU_HAS_FPU select CPU_HAS_ARM_MPU select SOC_FAMILY_EXX32 + select SOC_GECKO_HAS_RADIO select HAS_SILABS_GECKO select HAS_SWO select SOC_GECKO_HAS_INDIVIDUAL_PIN_LOCATION @@ -18,5 +19,6 @@ config SOC_SERIES_EFR32BG13P select SOC_GECKO_EMU select SOC_GECKO_GPIO select HAS_PM + select SOC_GECKO_SERIES1 help Enable support for EFR32BG13P Blue Gecko MCU series diff --git a/soc/arm/silabs_exx32/efr32bg13p/linker.ld b/soc/arm/silabs_exx32/efr32bg13p/linker.ld deleted file mode 100644 index b0530df09bd..00000000000 --- a/soc/arm/silabs_exx32/efr32bg13p/linker.ld +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2018 Diego Sueiro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images. - */ - - -#include diff --git a/soc/arm/silabs_exx32/efr32bg22/Kconfig.series b/soc/arm/silabs_exx32/efr32bg22/Kconfig.series index 266d6391725..278f702ebac 100644 --- a/soc/arm/silabs_exx32/efr32bg22/Kconfig.series +++ b/soc/arm/silabs_exx32/efr32bg22/Kconfig.series @@ -15,7 +15,9 @@ config SOC_SERIES_EFR32BG22 select HAS_SILABS_GECKO select HAS_SWO select SOC_FAMILY_EXX32 + select SOC_GECKO_HAS_RADIO select SOC_GECKO_SERIES2 + select SOC_GECKO_GPIO select SOC_GECKO_CMU select SOC_GECKO_CORE select SOC_GECKO_DEV_INIT diff --git a/soc/arm/silabs_exx32/efr32bg22/linker.ld b/soc/arm/silabs_exx32/efr32bg22/linker.ld deleted file mode 100644 index 9fcfb60618d..00000000000 --- a/soc/arm/silabs_exx32/efr32bg22/linker.ld +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2021 Sateesh Kotapati - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images. - */ - -#include diff --git a/soc/arm/silabs_exx32/efr32bg27/Kconfig.series b/soc/arm/silabs_exx32/efr32bg27/Kconfig.series index 572e6107f4e..d826c4d121c 100644 --- a/soc/arm/silabs_exx32/efr32bg27/Kconfig.series +++ b/soc/arm/silabs_exx32/efr32bg27/Kconfig.series @@ -15,6 +15,7 @@ config SOC_SERIES_EFR32BG27 select HAS_SILABS_GECKO select HAS_SWO select SOC_FAMILY_EXX32 + select SOC_GECKO_HAS_RADIO select SOC_GECKO_SERIES2 select SOC_GECKO_CMU select SOC_GECKO_CORE diff --git a/soc/arm/silabs_exx32/efr32bg27/linker.ld b/soc/arm/silabs_exx32/efr32bg27/linker.ld deleted file mode 100644 index 77214fcef49..00000000000 --- a/soc/arm/silabs_exx32/efr32bg27/linker.ld +++ /dev/null @@ -1,5 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/silabs_exx32/efr32fg13p/Kconfig.series b/soc/arm/silabs_exx32/efr32fg13p/Kconfig.series index 6f557377579..11074d6f586 100644 --- a/soc/arm/silabs_exx32/efr32fg13p/Kconfig.series +++ b/soc/arm/silabs_exx32/efr32fg13p/Kconfig.series @@ -13,11 +13,13 @@ config SOC_SERIES_EFR32FG13P select CPU_HAS_FPU select CPU_HAS_ARM_MPU select SOC_FAMILY_EXX32 + select SOC_GECKO_HAS_RADIO select SOC_GECKO_HAS_INDIVIDUAL_PIN_LOCATION select SOC_GECKO_HAS_HFRCO_FREQRANGE select SOC_GECKO_CMU select SOC_GECKO_GPIO select SOC_GECKO_HAS_ERRATA_RTCC_E201 select HAS_PM + select SOC_GECKO_SERIES1 help Enable support for EFR32 FlexGecko MCU series diff --git a/soc/arm/silabs_exx32/efr32fg13p/linker.ld b/soc/arm/silabs_exx32/efr32fg13p/linker.ld deleted file mode 100644 index e93018c0980..00000000000 --- a/soc/arm/silabs_exx32/efr32fg13p/linker.ld +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2018 Christian Taedcke - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images. - */ - - -#include diff --git a/soc/arm/silabs_exx32/efr32fg1p/Kconfig.series b/soc/arm/silabs_exx32/efr32fg1p/Kconfig.series index f8e509faa6d..8d453472de4 100644 --- a/soc/arm/silabs_exx32/efr32fg1p/Kconfig.series +++ b/soc/arm/silabs_exx32/efr32fg1p/Kconfig.series @@ -13,11 +13,13 @@ config SOC_SERIES_EFR32FG1P select CPU_HAS_FPU select CPU_HAS_ARM_MPU select SOC_FAMILY_EXX32 + select SOC_GECKO_HAS_RADIO select SOC_GECKO_HAS_INDIVIDUAL_PIN_LOCATION select SOC_GECKO_HAS_HFRCO_FREQRANGE select SOC_GECKO_CMU select SOC_GECKO_GPIO select SOC_GECKO_HAS_ERRATA_RTCC_E201 select HAS_PM + select SOC_GECKO_SERIES1 help Enable support for EFR32 FlexGecko MCU series diff --git a/soc/arm/silabs_exx32/efr32fg1p/linker.ld b/soc/arm/silabs_exx32/efr32fg1p/linker.ld deleted file mode 100644 index e93018c0980..00000000000 --- a/soc/arm/silabs_exx32/efr32fg1p/linker.ld +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2018 Christian Taedcke - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images. - */ - - -#include diff --git a/soc/arm/silabs_exx32/efr32mg12p/Kconfig.defconfig.series b/soc/arm/silabs_exx32/efr32mg12p/Kconfig.defconfig.series index b2f1e845813..a6881d77861 100644 --- a/soc/arm/silabs_exx32/efr32mg12p/Kconfig.defconfig.series +++ b/soc/arm/silabs_exx32/efr32mg12p/Kconfig.defconfig.series @@ -10,6 +10,7 @@ config SOC_SERIES config SOC_PART_NUMBER default "EFR32MG12P332F1024GL125" if SOC_PART_NUMBER_EFR32MG12P332F1024GL125 + default "EFR32MG12P433F1024GM68" if SOC_PART_NUMBER_EFR32MG12P433F1024GM68 config NUM_IRQS # must be >= the highest interrupt number used diff --git a/soc/arm/silabs_exx32/efr32mg12p/Kconfig.series b/soc/arm/silabs_exx32/efr32mg12p/Kconfig.series index 7c636daec86..23426e8ce20 100644 --- a/soc/arm/silabs_exx32/efr32mg12p/Kconfig.series +++ b/soc/arm/silabs_exx32/efr32mg12p/Kconfig.series @@ -11,6 +11,7 @@ config SOC_SERIES_EFR32MG12P select CPU_HAS_FPU select CPU_HAS_ARM_MPU select SOC_FAMILY_EXX32 + select SOC_GECKO_HAS_RADIO select HAS_SILABS_GECKO select HAS_SWO select SOC_GECKO_HAS_INDIVIDUAL_PIN_LOCATION @@ -20,5 +21,6 @@ config SOC_SERIES_EFR32MG12P select SOC_GECKO_GPIO select SOC_GECKO_TRNG select HAS_PM + select SOC_GECKO_SERIES1 help Enable support for EFR32 Mighty Gecko MCU series diff --git a/soc/arm/silabs_exx32/efr32mg12p/Kconfig.soc b/soc/arm/silabs_exx32/efr32mg12p/Kconfig.soc index 7a42a57a186..8f2f260730d 100644 --- a/soc/arm/silabs_exx32/efr32mg12p/Kconfig.soc +++ b/soc/arm/silabs_exx32/efr32mg12p/Kconfig.soc @@ -6,3 +6,7 @@ config SOC_PART_NUMBER_EFR32MG12P332F1024GL125 bool depends on SOC_SERIES_EFR32MG12P + +config SOC_PART_NUMBER_EFR32MG12P433F1024GM68 + bool + depends on SOC_SERIES_EFR32MG12P diff --git a/soc/arm/silabs_exx32/efr32mg12p/linker.ld b/soc/arm/silabs_exx32/efr32mg12p/linker.ld deleted file mode 100644 index b0530df09bd..00000000000 --- a/soc/arm/silabs_exx32/efr32mg12p/linker.ld +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2018 Diego Sueiro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images. - */ - - -#include diff --git a/soc/arm/silabs_exx32/efr32mg21/Kconfig.series b/soc/arm/silabs_exx32/efr32mg21/Kconfig.series index c22cb8376ee..146493469e8 100644 --- a/soc/arm/silabs_exx32/efr32mg21/Kconfig.series +++ b/soc/arm/silabs_exx32/efr32mg21/Kconfig.series @@ -12,6 +12,7 @@ config SOC_SERIES_EFR32MG21 select CPU_HAS_FPU select CPU_HAS_ARM_MPU select SOC_FAMILY_EXX32 + select SOC_GECKO_HAS_RADIO select SOC_GECKO_SERIES2 select HAS_SILABS_GECKO select HAS_SWO diff --git a/soc/arm/silabs_exx32/efr32mg21/linker.ld b/soc/arm/silabs_exx32/efr32mg21/linker.ld deleted file mode 100644 index d61039d397a..00000000000 --- a/soc/arm/silabs_exx32/efr32mg21/linker.ld +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2020 TriaGnoSys GmbH - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images. - */ - - -#include diff --git a/soc/arm/silabs_exx32/efr32mg24/Kconfig.series b/soc/arm/silabs_exx32/efr32mg24/Kconfig.series index 064db296cd8..a57d2237b3d 100644 --- a/soc/arm/silabs_exx32/efr32mg24/Kconfig.series +++ b/soc/arm/silabs_exx32/efr32mg24/Kconfig.series @@ -14,6 +14,7 @@ config SOC_SERIES_EFR32MG24 select ARMV8_M_DSP select ARM_TRUSTZONE_M select SOC_FAMILY_EXX32 + select SOC_GECKO_HAS_RADIO select SOC_GECKO_SERIES2 select HAS_SILABS_GECKO select HAS_SWO diff --git a/soc/arm/silabs_exx32/efr32mg24/linker.ld b/soc/arm/silabs_exx32/efr32mg24/linker.ld deleted file mode 100644 index d83e2a66530..00000000000 --- a/soc/arm/silabs_exx32/efr32mg24/linker.ld +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (c) 2021 Sateesh Kotapati - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * This is the linker script for both standard images. - */ - -#include - -#include diff --git a/soc/arm/st_stm32/Kconfig b/soc/arm/st_stm32/Kconfig index a75bf6094f6..dcdb22ca26b 100644 --- a/soc/arm/st_stm32/Kconfig +++ b/soc/arm/st_stm32/Kconfig @@ -6,6 +6,7 @@ config SOC_FAMILY_STM32 bool select HAS_SEGGER_RTT if ZEPHYR_SEGGER_MODULE + select STM32_ENABLE_DEBUG_SLEEP_STOP if DEBUG || ZTEST select BUILD_OUTPUT_HEX if SOC_FAMILY_STM32 @@ -14,6 +15,15 @@ config SOC_FAMILY string default "st_stm32" +config STM32_ENABLE_DEBUG_SLEEP_STOP + bool "Allow debugger attach in stop/sleep Mode" + help + Some STM32 parts disable the DBGMCU in sleep/stop modes because + of power consumption. As a side-effects this prevents + debuggers from attaching w/o resetting the target. This + effectivly destroys the use-case of `west attach`. Also + SEGGER RTT and similar technologies need this. + source "soc/arm/st_stm32/*/Kconfig.soc" endif # SOC_FAMILY_STM32 diff --git a/soc/arm/st_stm32/common/Kconfig.defconfig.series b/soc/arm/st_stm32/common/Kconfig.defconfig.series index a632a41ba57..40dda7b6fa0 100644 --- a/soc/arm/st_stm32/common/Kconfig.defconfig.series +++ b/soc/arm/st_stm32/common/Kconfig.defconfig.series @@ -16,6 +16,13 @@ DT_STM32_RCC_CLOCK_FREQ := $(dt_node_int_prop_int,$(DT_STM32_RCC_PATH),clock-fre config SYS_CLOCK_HW_CYCLES_PER_SEC default "$(DT_STM32_RCC_CLOCK_FREQ)" if "$(dt_nodelabel_enabled,rcc)" +if LOG_BACKEND_SWO + +config LOG_BACKEND_SWO_REF_FREQ_HZ + default "$(DT_STM32_RCC_CLOCK_FREQ)" if "$(dt_nodelabel_enabled,rcc)" + +endif # LOG_BACKEND_SWO + # set the tick per sec as a divider of the LPTIM clock source config SYS_CLOCK_TICKS_PER_SEC default 4096 if STM32_LPTIM_TIMER && STM32_LPTIM_CLOCK_LSE diff --git a/soc/arm/st_stm32/common/soc_config.c b/soc/arm/st_stm32/common/soc_config.c index 5027ad0493c..a791f334be4 100644 --- a/soc/arm/st_stm32/common/soc_config.c +++ b/soc/arm/st_stm32/common/soc_config.c @@ -60,13 +60,55 @@ static int st_stm32_common_config(void) LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_DBGMCU); #endif /* LL_APB1_GRP1_PERIPH_DBGMCU */ +#endif /* CONFIG_USE_SEGGER_RTT */ + + +#if defined(CONFIG_STM32_ENABLE_DEBUG_SLEEP_STOP) + #if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32MP1X) - HAL_EnableDBGSleepMode(); -#else + HAL_EnableDBGStopMode(); +#else /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32MP1X */ +#if defined(SOC_SERIES_STM32G0X) || defined(SOC_SERIES_STM32C0X) + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_DBGMCU); + LL_DBGMCU_EnableDBGStopMode(); + LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_DBGMCU); +#elif defined(SOC_SERIES_STM32F0X) + LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_DBGMCU); + LL_DBGMCU_EnableDBGStopMode(); + LL_APB1_GRP2_DisableClock(LL_APB1_GRP2_PERIPH_DBGMCU); +#elif defined(SOC_SERIES_STM32L0X) + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_DBGMCU); + LL_DBGMCU_EnableDBGStopMode(); + LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_DBGMCU); +#else /* all other parts */ LL_DBGMCU_EnableDBGStopMode(); +#endif #endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32MP1X */ -#endif /* CONFIG_USE_SEGGER_RTT */ +#else + +/* keeping in mind that debugging draws a lot of power we explcitly disable when not needed */ +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32MP1X) + HAL_DisableDBGStopMode(); +#else /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32MP1X */ +#if defined(SOC_SERIES_STM32G0X) || defined(SOC_SERIES_STM32C0X) + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_DBGMCU); + LL_DBGMCU_DisableDBGStopMode(); + LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_DBGMCU); +#elif defined(SOC_SERIES_STM32F0X) + LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_DBGMCU); + LL_DBGMCU_DisableDBGStopMode(); + LL_APB1_GRP2_DisableClock(LL_APB1_GRP2_PERIPH_DBGMCU); +#elif defined(SOC_SERIES_STM32L0X) + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_DBGMCU); + LL_DBGMCU_DisableDBGStopMode(); + LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_DBGMCU); +#else /* all other parts */ + LL_DBGMCU_DisableDBGStopMode(); +#endif +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32MP1X */ + +#endif /* CONFIG_STM32_ENABLE_DEBUG_SLEEP_STOP */ return 0; } diff --git a/soc/arm/st_stm32/stm32c0/CMakeLists.txt b/soc/arm/st_stm32/stm32c0/CMakeLists.txt index ac3ba70ace6..e02052e3946 100644 --- a/soc/arm/st_stm32/stm32c0/CMakeLists.txt +++ b/soc/arm/st_stm32/stm32c0/CMakeLists.txt @@ -4,3 +4,5 @@ zephyr_include_directories(${ZEPHYR_BASE}/drivers) zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/st_stm32/stm32c0/linker.ld b/soc/arm/st_stm32/stm32c0/linker.ld deleted file mode 100644 index fda50c307af..00000000000 --- a/soc/arm/st_stm32/stm32c0/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2023 Benjamin Björnsson - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/st_stm32/stm32f0/CMakeLists.txt b/soc/arm/st_stm32/stm32f0/CMakeLists.txt index 56b5d1ffa8e..914e395d27a 100644 --- a/soc/arm/st_stm32/stm32f0/CMakeLists.txt +++ b/soc/arm/st_stm32/stm32f0/CMakeLists.txt @@ -8,3 +8,5 @@ zephyr_linker_sources_ifdef(CONFIG_SRAM_VECTOR_TABLE ) zephyr_include_directories(${ZEPHYR_BASE}/drivers) zephyr_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/st_stm32/stm32f0/Kconfig.defconfig.stm32f072xb b/soc/arm/st_stm32/stm32f0/Kconfig.defconfig.stm32f072xb deleted file mode 100644 index dcb67a92390..00000000000 --- a/soc/arm/st_stm32/stm32f0/Kconfig.defconfig.stm32f072xb +++ /dev/null @@ -1,14 +0,0 @@ -# ST Microelectronics STM32F072XB MCU - -# Copyright (c) 2017 BayLibre, SAS -# SPDX-License-Identifier: Apache-2.0 - -if SOC_STM32F072XB - -config SOC - default "stm32f072xb" - -config NUM_IRQS - default 32 - -endif # SOC_STM32F072XB diff --git a/soc/arm/st_stm32/stm32f0/Kconfig.defconfig.stm32f072xx b/soc/arm/st_stm32/stm32f0/Kconfig.defconfig.stm32f072xx new file mode 100644 index 00000000000..8bfed8c7b10 --- /dev/null +++ b/soc/arm/st_stm32/stm32f0/Kconfig.defconfig.stm32f072xx @@ -0,0 +1,14 @@ +# ST Microelectronics STM32F072XB MCU + +# Copyright (c) 2017 BayLibre, SAS +# SPDX-License-Identifier: Apache-2.0 + +if SOC_STM32F072X8 || SOC_STM32F072XB + +config SOC + default "stm32f072xb" + +config NUM_IRQS + default 32 + +endif # SOC_STM32F072X8 || SOC_STM32F072XB diff --git a/soc/arm/st_stm32/stm32f0/Kconfig.soc b/soc/arm/st_stm32/stm32f0/Kconfig.soc index 728ea4a10c3..eb82615bb09 100644 --- a/soc/arm/st_stm32/stm32f0/Kconfig.soc +++ b/soc/arm/st_stm32/stm32f0/Kconfig.soc @@ -31,6 +31,9 @@ config SOC_STM32F051X8 config SOC_STM32F070XB bool "STM32F070XB" +config SOC_STM32F072X8 + bool "STM32F072X8" + config SOC_STM32F072XB bool "STM32F072XB" diff --git a/soc/arm/st_stm32/stm32f0/linker.ld b/soc/arm/st_stm32/stm32f0/linker.ld deleted file mode 100644 index 876802cb7ee..00000000000 --- a/soc/arm/st_stm32/stm32f0/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014-2016 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/st_stm32/stm32f1/CMakeLists.txt b/soc/arm/st_stm32/stm32f1/CMakeLists.txt index ac3ba70ace6..e02052e3946 100644 --- a/soc/arm/st_stm32/stm32f1/CMakeLists.txt +++ b/soc/arm/st_stm32/stm32f1/CMakeLists.txt @@ -4,3 +4,5 @@ zephyr_include_directories(${ZEPHYR_BASE}/drivers) zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/st_stm32/stm32f1/linker.ld b/soc/arm/st_stm32/stm32f1/linker.ld deleted file mode 100644 index 876802cb7ee..00000000000 --- a/soc/arm/st_stm32/stm32f1/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014-2016 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/st_stm32/stm32f2/CMakeLists.txt b/soc/arm/st_stm32/stm32f2/CMakeLists.txt index ac3ba70ace6..e02052e3946 100644 --- a/soc/arm/st_stm32/stm32f2/CMakeLists.txt +++ b/soc/arm/st_stm32/stm32f2/CMakeLists.txt @@ -4,3 +4,5 @@ zephyr_include_directories(${ZEPHYR_BASE}/drivers) zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/st_stm32/stm32f2/linker.ld b/soc/arm/st_stm32/stm32f2/linker.ld deleted file mode 100644 index 83708c438f6..00000000000 --- a/soc/arm/st_stm32/stm32f2/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2018 qianfan Zhao - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/st_stm32/stm32f3/CMakeLists.txt b/soc/arm/st_stm32/stm32f3/CMakeLists.txt index ac3ba70ace6..e02052e3946 100644 --- a/soc/arm/st_stm32/stm32f3/CMakeLists.txt +++ b/soc/arm/st_stm32/stm32f3/CMakeLists.txt @@ -4,3 +4,5 @@ zephyr_include_directories(${ZEPHYR_BASE}/drivers) zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/st_stm32/stm32f3/linker.ld b/soc/arm/st_stm32/stm32f3/linker.ld deleted file mode 100644 index 876802cb7ee..00000000000 --- a/soc/arm/st_stm32/stm32f3/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014-2016 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/st_stm32/stm32f4/CMakeLists.txt b/soc/arm/st_stm32/stm32f4/CMakeLists.txt index ac3ba70ace6..021708b9d02 100644 --- a/soc/arm/st_stm32/stm32f4/CMakeLists.txt +++ b/soc/arm/st_stm32/stm32f4/CMakeLists.txt @@ -4,3 +4,9 @@ zephyr_include_directories(${ZEPHYR_BASE}/drivers) zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") + +zephyr_sources_ifdef(CONFIG_PM + power.c + ) diff --git a/soc/arm/st_stm32/stm32f4/Kconfig.defconfig.series b/soc/arm/st_stm32/stm32f4/Kconfig.defconfig.series index 14dea5bf4d2..28ed9cc3a55 100644 --- a/soc/arm/st_stm32/stm32f4/Kconfig.defconfig.series +++ b/soc/arm/st_stm32/stm32f4/Kconfig.defconfig.series @@ -17,4 +17,8 @@ config TASK_WDT_HW_FALLBACK_DELAY depends on TASK_WDT_HW_FALLBACK default 200 +config PM + select COUNTER + select COUNTER_RTC_STM32_SUBSECONDS + endif # SOC_SERIES_STM32F4X diff --git a/soc/arm/st_stm32/stm32f4/Kconfig.series b/soc/arm/st_stm32/stm32f4/Kconfig.series index 6b8fdf80c7b..a4e65c97784 100644 --- a/soc/arm/st_stm32/stm32f4/Kconfig.series +++ b/soc/arm/st_stm32/stm32f4/Kconfig.series @@ -13,5 +13,6 @@ config SOC_SERIES_STM32F4X select HAS_STM32CUBE select CPU_HAS_ARM_MPU select HAS_SWO + select HAS_PM help Enable support for STM32F4 MCU series diff --git a/soc/arm/st_stm32/stm32f4/linker.ld b/soc/arm/st_stm32/stm32f4/linker.ld deleted file mode 100644 index 876802cb7ee..00000000000 --- a/soc/arm/st_stm32/stm32f4/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014-2016 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/st_stm32/stm32f4/power.c b/soc/arm/st_stm32/stm32f4/power.c new file mode 100644 index 00000000000..02b645ee9f1 --- /dev/null +++ b/soc/arm/st_stm32/stm32f4/power.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL); + +BUILD_ASSERT(DT_SAME_NODE(DT_CHOSEN(zephyr_cortex_m_idle_timer), DT_NODELABEL(rtc)), + "STM32Fx series needs RTC as an additional IDLE timer for power management"); + +void pm_state_set(enum pm_state state, uint8_t substate_id) +{ + ARG_UNUSED(substate_id); + + switch (state) { + case PM_STATE_SUSPEND_TO_IDLE: + LL_LPM_DisableEventOnPend(); + LL_PWR_ClearFlag_WU(); + /* According to datasheet (DS11139 Rev 8,Table 38.), wakeup with regulator in + * low-power mode takes typically 8us, max 13us more time than with the main + * regulator. We are using RTC as a wakeup source, which has a tick 62,5us. + * It means we have to add significant margin to the exit-latency anyway, + * so it is worth always using the low-power regulator. + */ + LL_PWR_SetPowerMode(LL_PWR_MODE_STOP_LPREGU); + LL_LPM_EnableDeepSleep(); + + k_cpu_idle(); + + break; + default: + LOG_DBG("Unsupported power state %u", state); + break; + } +} + +void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) +{ + ARG_UNUSED(substate_id); + + switch (state) { + case PM_STATE_SUSPEND_TO_IDLE: + LL_LPM_DisableSleepOnExit(); + LL_LPM_EnableSleep(); + + /* Restore the clock setup. */ + stm32_clock_control_init(NULL); + break; + default: + LOG_DBG("Unsupported power substate-id %u", state); + break; + } + + /* + * System is now in active mode. Reenable interrupts which were + * disabled when OS started idling code. + */ + irq_unlock(0); +} + +static int stm32_power_init(void) +{ + /* Enable Power clock. It should by done by default, but make sure to + * enable it for all STM32F4x chips. + */ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); + + /* Enabling debug during STOP mode is done by the common STM32 configuration */ + return 0; +} + +SYS_INIT(stm32_power_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/soc/arm/st_stm32/stm32f7/CMakeLists.txt b/soc/arm/st_stm32/stm32f7/CMakeLists.txt index ac3ba70ace6..e02052e3946 100644 --- a/soc/arm/st_stm32/stm32f7/CMakeLists.txt +++ b/soc/arm/st_stm32/stm32f7/CMakeLists.txt @@ -4,3 +4,5 @@ zephyr_include_directories(${ZEPHYR_BASE}/drivers) zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/st_stm32/stm32f7/linker.ld b/soc/arm/st_stm32/stm32f7/linker.ld deleted file mode 100644 index bf8d6789236..00000000000 --- a/soc/arm/st_stm32/stm32f7/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2018 Yurii Hamann - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/st_stm32/stm32g0/CMakeLists.txt b/soc/arm/st_stm32/stm32g0/CMakeLists.txt index aff2873dc18..85869a31ddf 100644 --- a/soc/arm/st_stm32/stm32g0/CMakeLists.txt +++ b/soc/arm/st_stm32/stm32g0/CMakeLists.txt @@ -9,3 +9,5 @@ zephyr_sources( zephyr_sources_ifdef(CONFIG_PM power.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/st_stm32/stm32g0/linker.ld b/soc/arm/st_stm32/stm32g0/linker.ld deleted file mode 100644 index e5b8916fc1f..00000000000 --- a/soc/arm/st_stm32/stm32g0/linker.ld +++ /dev/null @@ -1,10 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2019 Philippe Retornaz - * Copyright (c) 2019 STMicroelectronics - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/st_stm32/stm32g0/power.c b/soc/arm/st_stm32/stm32g0/power.c index d13ec265679..b2dfd18bb52 100644 --- a/soc/arm/st_stm32/stm32g0/power.c +++ b/soc/arm/st_stm32/stm32g0/power.c @@ -87,13 +87,6 @@ static int stm32_power_init(void) /* enable Power clock */ LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); -#ifdef CONFIG_DEBUG - /* Enable the Debug Module during all and any Low power mode */ - LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_DBGMCU); - LL_DBGMCU_EnableDBGStopMode(); - LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_DBGMCU); -#endif /* CONFIG_DEBUG */ - return 0; } diff --git a/soc/arm/st_stm32/stm32g4/CMakeLists.txt b/soc/arm/st_stm32/stm32g4/CMakeLists.txt index d924a7b2840..04911a6a2e4 100644 --- a/soc/arm/st_stm32/stm32g4/CMakeLists.txt +++ b/soc/arm/st_stm32/stm32g4/CMakeLists.txt @@ -7,3 +7,5 @@ zephyr_sources( zephyr_sources_ifdef(CONFIG_PM power.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/st_stm32/stm32g4/linker.ld b/soc/arm/st_stm32/stm32g4/linker.ld deleted file mode 100644 index 954d9eb7587..00000000000 --- a/soc/arm/st_stm32/stm32g4/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2019 Richard Osterloh - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/st_stm32/stm32g4/power.c b/soc/arm/st_stm32/stm32g4/power.c index dadb0711468..3f2295e9440 100644 --- a/soc/arm/st_stm32/stm32g4/power.c +++ b/soc/arm/st_stm32/stm32g4/power.c @@ -85,13 +85,6 @@ static int stm32_power_init(void) /* enable Power clock */ LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); - /* keep in mind that debugging draws a lot of power */ -#ifdef CONFIG_DEBUG - LL_DBGMCU_EnableDBGStopMode(); -#else - LL_DBGMCU_DisableDBGStopMode(); -#endif - return 0; } diff --git a/soc/arm/st_stm32/stm32h5/CMakeLists.txt b/soc/arm/st_stm32/stm32h5/CMakeLists.txt index 9cb843e9caf..c8d32ef22aa 100644 --- a/soc/arm/st_stm32/stm32h5/CMakeLists.txt +++ b/soc/arm/st_stm32/stm32h5/CMakeLists.txt @@ -5,3 +5,5 @@ zephyr_sources( soc.c ) zephyr_linker_sources(SECTIONS sections.ld) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/st_stm32/stm32h5/linker.ld b/soc/arm/st_stm32/stm32h5/linker.ld deleted file mode 100644 index 8bd989bc732..00000000000 --- a/soc/arm/st_stm32/stm32h5/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2023 STMicroelectronics - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/st_stm32/stm32h7/CMakeLists.txt b/soc/arm/st_stm32/stm32h7/CMakeLists.txt index 24f6f90e6e4..d1ae6c3325d 100644 --- a/soc/arm/st_stm32/stm32h7/CMakeLists.txt +++ b/soc/arm/st_stm32/stm32h7/CMakeLists.txt @@ -7,3 +7,5 @@ zephyr_sources_ifdef(CONFIG_CPU_CORTEX_M4 soc_m4.c) zephyr_sources(mpu_regions.c) zephyr_linker_sources(SECTIONS sections.ld) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/st_stm32/stm32h7/Kconfig.defconfig.stm32h7b0xx b/soc/arm/st_stm32/stm32h7/Kconfig.defconfig.stm32h7b0xx new file mode 100644 index 00000000000..10502135014 --- /dev/null +++ b/soc/arm/st_stm32/stm32h7/Kconfig.defconfig.stm32h7b0xx @@ -0,0 +1,15 @@ +# ST STM32H7B0XX MCU configuration options + +# Copyright (c) 2023 Charles Dias +# SPDX-License-Identifier: Apache-2.0 + +if SOC_STM32H7B0XX || SOC_STM32H7B0XXQ + +config SOC + default "stm32h7b0xxQ" if SOC_STM32H7B0XXQ + default "stm32h7b0xx" if SOC_STM32H7B0XX + +config NUM_IRQS + default 155 + +endif # SOC_STM32H7B0XX || SOC_STM32H7B0XXQ diff --git a/soc/arm/st_stm32/stm32h7/Kconfig.soc b/soc/arm/st_stm32/stm32h7/Kconfig.soc index 46f101f0e14..7856c52652a 100644 --- a/soc/arm/st_stm32/stm32h7/Kconfig.soc +++ b/soc/arm/st_stm32/stm32h7/Kconfig.soc @@ -73,6 +73,16 @@ config SOC_STM32H7A3XXQ select CPU_CORTEX_M7 select CPU_HAS_FPU_DOUBLE_PRECISION +config SOC_STM32H7B0XX + bool "STM32H7B0XX" + select CPU_CORTEX_M7 + select CPU_HAS_FPU_DOUBLE_PRECISION + +config SOC_STM32H7B0XXQ + bool "STM32H7B0XXQ" + select CPU_CORTEX_M7 + select CPU_HAS_FPU_DOUBLE_PRECISION + config SOC_STM32H7B3XX bool "STM32H7B3XX" select CPU_CORTEX_M7 diff --git a/soc/arm/st_stm32/stm32h7/linker.ld b/soc/arm/st_stm32/stm32h7/linker.ld deleted file mode 100644 index 078ef2a807b..00000000000 --- a/soc/arm/st_stm32/stm32h7/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2019 Linaro Limited - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/st_stm32/stm32h7/mpu_regions.c b/soc/arm/st_stm32/stm32h7/mpu_regions.c index f2ba721d2df..29825ad226a 100644 --- a/soc/arm/st_stm32/stm32h7/mpu_regions.c +++ b/soc/arm/st_stm32/stm32h7/mpu_regions.c @@ -5,7 +5,7 @@ */ #include -#include +#include static const struct arm_mpu_region mpu_regions[] = { MPU_REGION_ENTRY("FLASH", CONFIG_FLASH_BASE_ADDRESS, @@ -38,9 +38,6 @@ static const struct arm_mpu_region mpu_regions[] = { REGION_PPB_ATTR(REGION_256B)), #endif #endif - - /* DT-defined regions */ - DT_MEMORY_ATTR_APPLY(ARM_MPU_REGION_INIT) }; const struct arm_mpu_config mpu_config = { diff --git a/soc/arm/st_stm32/stm32l0/CMakeLists.txt b/soc/arm/st_stm32/stm32l0/CMakeLists.txt index 59be7817eab..0fd5073770d 100644 --- a/soc/arm/st_stm32/stm32l0/CMakeLists.txt +++ b/soc/arm/st_stm32/stm32l0/CMakeLists.txt @@ -8,3 +8,5 @@ zephyr_sources( zephyr_sources_ifdef(CONFIG_PM power.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/st_stm32/stm32l0/Kconfig.defconfig.stm32l010x4 b/soc/arm/st_stm32/stm32l0/Kconfig.defconfig.stm32l010x4 new file mode 100644 index 00000000000..779d2624508 --- /dev/null +++ b/soc/arm/st_stm32/stm32l0/Kconfig.defconfig.stm32l010x4 @@ -0,0 +1,14 @@ +# ST Microelectronics STM32L010XX MCU +# +# Copyright (c) 2023 OS Systems +# SPDX-License-Identifier: Apache-2.0 + +if SOC_STM32L010X4 + +config SOC + default "stm32l010x4" + +config NUM_IRQS + default 30 + +endif # SOC_STM32L010X4 diff --git a/soc/arm/st_stm32/stm32l0/Kconfig.defconfig.stm32l010x6 b/soc/arm/st_stm32/stm32l0/Kconfig.defconfig.stm32l010x6 new file mode 100644 index 00000000000..dd86c005ad8 --- /dev/null +++ b/soc/arm/st_stm32/stm32l0/Kconfig.defconfig.stm32l010x6 @@ -0,0 +1,14 @@ +# ST Microelectronics STM32L010XX MCU +# +# Copyright (c) 2023 OS Systems +# SPDX-License-Identifier: Apache-2.0 + +if SOC_STM32L010X6 + +config SOC + default "stm32l010x6" + +config NUM_IRQS + default 30 + +endif # SOC_STM32L010X6 diff --git a/soc/arm/st_stm32/stm32l0/Kconfig.defconfig.stm32l010x8 b/soc/arm/st_stm32/stm32l0/Kconfig.defconfig.stm32l010x8 new file mode 100644 index 00000000000..20dd0b0c09a --- /dev/null +++ b/soc/arm/st_stm32/stm32l0/Kconfig.defconfig.stm32l010x8 @@ -0,0 +1,14 @@ +# ST Microelectronics STM32L010XX MCU +# +# Copyright (c) 2023 OS Systems +# SPDX-License-Identifier: Apache-2.0 + +if SOC_STM32L010X8 + +config SOC + default "stm32l010x8" + +config NUM_IRQS + default 30 + +endif # SOC_STM32L010X8 diff --git a/soc/arm/st_stm32/stm32l0/Kconfig.defconfig.stm32l010xb b/soc/arm/st_stm32/stm32l0/Kconfig.defconfig.stm32l010xb index d447e92f4e0..89e20292fc1 100644 --- a/soc/arm/st_stm32/stm32l0/Kconfig.defconfig.stm32l010xb +++ b/soc/arm/st_stm32/stm32l0/Kconfig.defconfig.stm32l010xb @@ -9,6 +9,6 @@ config SOC default "stm32l010xb" config NUM_IRQS - default 32 + default 30 endif # SOC_STM32L010XB diff --git a/soc/arm/st_stm32/stm32l0/Kconfig.defconfig.stm32l081xx b/soc/arm/st_stm32/stm32l0/Kconfig.defconfig.stm32l081xx new file mode 100644 index 00000000000..f3cc93c38c8 --- /dev/null +++ b/soc/arm/st_stm32/stm32l0/Kconfig.defconfig.stm32l081xx @@ -0,0 +1,14 @@ +# ST Microelectronics STM32L081XX MCU + +# Copyright (c) 2023 Caspar Friedrich +# SPDX-License-Identifier: Apache-2.0 + +if SOC_STM32L081XX + +config SOC + default "stm32l081xx" + +config NUM_IRQS + default 32 + +endif # SOC_STM32L081XX diff --git a/soc/arm/st_stm32/stm32l0/Kconfig.soc b/soc/arm/st_stm32/stm32l0/Kconfig.soc index 42d49fde84e..0baab0cf2b9 100644 --- a/soc/arm/st_stm32/stm32l0/Kconfig.soc +++ b/soc/arm/st_stm32/stm32l0/Kconfig.soc @@ -2,6 +2,7 @@ # Copyright (c) 2018 Endre Karlson # Copyright (c) 2021 Nomono AS +# Copyright (c) 2023 OS Systems # # SPDX-License-Identifier: Apache-2.0 @@ -9,6 +10,15 @@ choice prompt "STM32L0x MCU Selection" depends on SOC_SERIES_STM32L0X +config SOC_STM32L010X4 + bool "STM32L010X4" + +config SOC_STM32L010X6 + bool "STM32L010X6" + +config SOC_STM32L010X8 + bool "STM32L010X8" + config SOC_STM32L010XB bool "STM32L010XB" @@ -38,4 +48,8 @@ config SOC_STM32L073XX bool "STM32L073XX" select CPU_HAS_ARM_MPU +config SOC_STM32L081XX + bool "STM32L081XX" + select CPU_HAS_ARM_MPU + endchoice diff --git a/soc/arm/st_stm32/stm32l0/linker.ld b/soc/arm/st_stm32/stm32l0/linker.ld deleted file mode 100644 index 268542adab1..00000000000 --- a/soc/arm/st_stm32/stm32l0/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2018 Endre Karlson - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/st_stm32/stm32l0/power.c b/soc/arm/st_stm32/stm32l0/power.c index bf7cc7bad11..cfa2281fd6a 100644 --- a/soc/arm/st_stm32/stm32l0/power.c +++ b/soc/arm/st_stm32/stm32l0/power.c @@ -80,13 +80,6 @@ static int stm32_power_init(void) /* Enable Power clock */ LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); -#ifdef CONFIG_DEBUG - /* Enable the Debug Module during STOP mode */ - LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_DBGMCU); - LL_DBGMCU_EnableDBGStopMode(); - LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_DBGMCU); -#endif /* CONFIG_DEBUG */ - return 0; } diff --git a/soc/arm/st_stm32/stm32l1/CMakeLists.txt b/soc/arm/st_stm32/stm32l1/CMakeLists.txt index 844c5252009..68bf00e81c1 100644 --- a/soc/arm/st_stm32/stm32l1/CMakeLists.txt +++ b/soc/arm/st_stm32/stm32l1/CMakeLists.txt @@ -2,3 +2,5 @@ zephyr_include_directories(${ZEPHYR_BASE}/drivers) zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/st_stm32/stm32l1/linker.ld b/soc/arm/st_stm32/stm32l1/linker.ld deleted file mode 100644 index 48056b39708..00000000000 --- a/soc/arm/st_stm32/stm32l1/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2019 Linaro Ltd. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/st_stm32/stm32l4/CMakeLists.txt b/soc/arm/st_stm32/stm32l4/CMakeLists.txt index 8f4b837538d..94edc262274 100644 --- a/soc/arm/st_stm32/stm32l4/CMakeLists.txt +++ b/soc/arm/st_stm32/stm32l4/CMakeLists.txt @@ -10,3 +10,5 @@ zephyr_sources_ifdef(CONFIG_PM ) zephyr_sources_ifdef(CONFIG_POWEROFF poweroff.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/st_stm32/stm32l4/linker.ld b/soc/arm/st_stm32/stm32l4/linker.ld deleted file mode 100644 index 876802cb7ee..00000000000 --- a/soc/arm/st_stm32/stm32l4/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014-2016 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/st_stm32/stm32l4/power.c b/soc/arm/st_stm32/stm32l4/power.c index 94b02f5213f..ff87553836e 100644 --- a/soc/arm/st_stm32/stm32l4/power.c +++ b/soc/arm/st_stm32/stm32l4/power.c @@ -120,11 +120,6 @@ static int stm32_power_init(void) /* enable Power clock */ LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); -#ifdef CONFIG_DEBUG - /* Enable the Debug Module during STOP mode */ - LL_DBGMCU_EnableDBGStopMode(); -#endif /* CONFIG_DEBUG */ - return 0; } diff --git a/soc/arm/st_stm32/stm32l5/CMakeLists.txt b/soc/arm/st_stm32/stm32l5/CMakeLists.txt index 59be7817eab..0fd5073770d 100644 --- a/soc/arm/st_stm32/stm32l5/CMakeLists.txt +++ b/soc/arm/st_stm32/stm32l5/CMakeLists.txt @@ -8,3 +8,5 @@ zephyr_sources( zephyr_sources_ifdef(CONFIG_PM power.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/st_stm32/stm32l5/linker.ld b/soc/arm/st_stm32/stm32l5/linker.ld deleted file mode 100644 index 484e77214be..00000000000 --- a/soc/arm/st_stm32/stm32l5/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2020 Linaro Limited - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/st_stm32/stm32l5/power.c b/soc/arm/st_stm32/stm32l5/power.c index 1d5316c6963..fa8d57c894d 100644 --- a/soc/arm/st_stm32/stm32l5/power.c +++ b/soc/arm/st_stm32/stm32l5/power.c @@ -104,11 +104,6 @@ static int stm32_power_init(void) /* enable Power clock */ LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); -#ifdef CONFIG_DEBUG - /* Enable the Debug Module during all and any Low power mode */ - LL_DBGMCU_EnableDBGStopMode(); -#endif /* CONFIG_DEBUG */ - return 0; } diff --git a/soc/arm/st_stm32/stm32mp1/CMakeLists.txt b/soc/arm/st_stm32/stm32mp1/CMakeLists.txt index 4a1dfd30503..7805c0ffbf2 100644 --- a/soc/arm/st_stm32/stm32mp1/CMakeLists.txt +++ b/soc/arm/st_stm32/stm32mp1/CMakeLists.txt @@ -6,3 +6,5 @@ zephyr_include_directories(${ZEPHYR_BASE}/drivers) zephyr_sources( soc.c ) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/st_stm32/stm32mp1/linker.ld b/soc/arm/st_stm32/stm32mp1/linker.ld index 1ff5da841e5..7f9a84501ef 100644 --- a/soc/arm/st_stm32/stm32mp1/linker.ld +++ b/soc/arm/st_stm32/stm32mp1/linker.ld @@ -7,7 +7,7 @@ */ -#include +#include SECTIONS { diff --git a/soc/arm/st_stm32/stm32u5/CMakeLists.txt b/soc/arm/st_stm32/stm32u5/CMakeLists.txt index 8f4b837538d..94edc262274 100644 --- a/soc/arm/st_stm32/stm32u5/CMakeLists.txt +++ b/soc/arm/st_stm32/stm32u5/CMakeLists.txt @@ -10,3 +10,5 @@ zephyr_sources_ifdef(CONFIG_PM ) zephyr_sources_ifdef(CONFIG_POWEROFF poweroff.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/st_stm32/stm32u5/Kconfig.defconfig.stm32u5a5xx b/soc/arm/st_stm32/stm32u5/Kconfig.defconfig.stm32u5a5xx new file mode 100644 index 00000000000..1759406a580 --- /dev/null +++ b/soc/arm/st_stm32/stm32u5/Kconfig.defconfig.stm32u5a5xx @@ -0,0 +1,14 @@ +# STMicroelectronics STM32U5A5XX MCU + +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if SOC_STM32U5A5XX + +config SOC + default "stm32u5a5xx" + +config NUM_IRQS + default 139 + +endif # SOC_STM32U5A5XX diff --git a/soc/arm/st_stm32/stm32u5/Kconfig.defconfig.stm32u5a9xx b/soc/arm/st_stm32/stm32u5/Kconfig.defconfig.stm32u5a9xx new file mode 100644 index 00000000000..0553382acb1 --- /dev/null +++ b/soc/arm/st_stm32/stm32u5/Kconfig.defconfig.stm32u5a9xx @@ -0,0 +1,14 @@ +# STMicroelectronics STM32U5A9XX MCU + +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if SOC_STM32U5A9XX + +config SOC + default "stm32u5a9xx" + +config NUM_IRQS + default 139 + +endif # SOC_STM32U5A9XX diff --git a/soc/arm/st_stm32/stm32u5/Kconfig.soc b/soc/arm/st_stm32/stm32u5/Kconfig.soc index cceb506f55e..ec8c964ad3e 100644 --- a/soc/arm/st_stm32/stm32u5/Kconfig.soc +++ b/soc/arm/st_stm32/stm32u5/Kconfig.soc @@ -2,6 +2,7 @@ # Copyright (c) 2021 Linaro Limited # Copyright (c) 2023 PSICONTROL nv +# Copyright (c) 2023 STMicroelectronics # SPDX-License-Identifier: Apache-2.0 choice @@ -20,4 +21,10 @@ config SOC_STM32U595XX config SOC_STM32U599XX bool "STM32U599XX" +config SOC_STM32U5A5XX + bool "STM32U5A5XX" + +config SOC_STM32U5A9XX + bool "STM32U5A9XX" + endchoice diff --git a/soc/arm/st_stm32/stm32u5/linker.ld b/soc/arm/st_stm32/stm32u5/linker.ld deleted file mode 100644 index c28ef22f9a0..00000000000 --- a/soc/arm/st_stm32/stm32u5/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2021 Linaro Limited - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/st_stm32/stm32u5/power.c b/soc/arm/st_stm32/stm32u5/power.c index f880ffa1d08..a3214f93d96 100644 --- a/soc/arm/st_stm32/stm32u5/power.c +++ b/soc/arm/st_stm32/stm32u5/power.c @@ -118,11 +118,6 @@ static int stm32_power_init(void) /* enable Power clock */ LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_PWR); -#ifdef CONFIG_DEBUG - /* Enable the Debug Module during all and any Low power mode */ - LL_DBGMCU_EnableDBGStopMode(); -#endif /* CONFIG_DEBUG */ - return 0; } diff --git a/soc/arm/st_stm32/stm32wb/CMakeLists.txt b/soc/arm/st_stm32/stm32wb/CMakeLists.txt index 2b21a72d326..32ce62ee530 100644 --- a/soc/arm/st_stm32/stm32wb/CMakeLists.txt +++ b/soc/arm/st_stm32/stm32wb/CMakeLists.txt @@ -13,3 +13,5 @@ zephyr_sources_ifdef(CONFIG_PM ) zephyr_sources_ifdef(CONFIG_POWEROFF poweroff.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/st_stm32/stm32wb/linker.ld b/soc/arm/st_stm32/stm32wb/linker.ld deleted file mode 100644 index 078ef2a807b..00000000000 --- a/soc/arm/st_stm32/stm32wb/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2019 Linaro Limited - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/st_stm32/stm32wb/power.c b/soc/arm/st_stm32/stm32wb/power.c index e3dcdfa6cab..6836e88c4ed 100644 --- a/soc/arm/st_stm32/stm32wb/power.c +++ b/soc/arm/st_stm32/stm32wb/power.c @@ -141,12 +141,6 @@ void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) /* Initialize STM32 Power */ static int stm32_power_init(void) { - -#ifdef CONFIG_DEBUG - /* Enable the Debug Module during STOP mode */ - LL_DBGMCU_EnableDBGStopMode(); -#endif /* CONFIG_DEBUG */ - return 0; } diff --git a/soc/arm/st_stm32/stm32wba/CMakeLists.txt b/soc/arm/st_stm32/stm32wba/CMakeLists.txt index 59be7817eab..0fd5073770d 100644 --- a/soc/arm/st_stm32/stm32wba/CMakeLists.txt +++ b/soc/arm/st_stm32/stm32wba/CMakeLists.txt @@ -8,3 +8,5 @@ zephyr_sources( zephyr_sources_ifdef(CONFIG_PM power.c ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/st_stm32/stm32wba/linker.ld b/soc/arm/st_stm32/stm32wba/linker.ld deleted file mode 100644 index 8bd989bc732..00000000000 --- a/soc/arm/st_stm32/stm32wba/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2023 STMicroelectronics - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/st_stm32/stm32wba/power.c b/soc/arm/st_stm32/stm32wba/power.c index 691424c2b25..018c27ee0b8 100644 --- a/soc/arm/st_stm32/stm32wba/power.c +++ b/soc/arm/st_stm32/stm32wba/power.c @@ -104,11 +104,6 @@ static int stm32_power_init(void) /* enable Power clock */ LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_PWR); -#ifdef CONFIG_DEBUG - /* Enable the Debug Module during all and any Low power mode */ - LL_DBGMCU_EnableDBGStopMode(); -#endif /* CONFIG_DEBUG */ - return 0; } diff --git a/soc/arm/st_stm32/stm32wl/CMakeLists.txt b/soc/arm/st_stm32/stm32wl/CMakeLists.txt index 40ff85ccbbe..af44cc273e1 100644 --- a/soc/arm/st_stm32/stm32wl/CMakeLists.txt +++ b/soc/arm/st_stm32/stm32wl/CMakeLists.txt @@ -8,3 +8,5 @@ zephyr_sources_ifdef(CONFIG_PM ) zephyr_sources_ifdef(CONFIG_POWEROFF poweroff.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/st_stm32/stm32wl/linker.ld b/soc/arm/st_stm32/stm32wl/linker.ld deleted file mode 100644 index 8050cf9b60c..00000000000 --- a/soc/arm/st_stm32/stm32wl/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2020 STMicroelectronics - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/st_stm32/stm32wl/power.c b/soc/arm/st_stm32/stm32wl/power.c index aaf43db4817..dab500ecb77 100644 --- a/soc/arm/st_stm32/stm32wl/power.c +++ b/soc/arm/st_stm32/stm32wl/power.c @@ -85,12 +85,6 @@ void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) /* Initialize STM32 Power */ static int stm32_power_init(void) { - -#ifdef CONFIG_DEBUG - /* Enable the Debug Module during STOP mode */ - LL_DBGMCU_EnableDBGStopMode(); -#endif /* CONFIG_DEBUG */ - return 0; } diff --git a/soc/arm/ti_k3/am62x_m4/CMakeLists.txt b/soc/arm/ti_k3/am62x_m4/CMakeLists.txt index e8d816988de..bc9b13ea188 100644 --- a/soc/arm/ti_k3/am62x_m4/CMakeLists.txt +++ b/soc/arm/ti_k3/am62x_m4/CMakeLists.txt @@ -9,3 +9,5 @@ if(CONFIG_OPENAMP_RSC_TABLE) zephyr_linker_section(NAME .resource_table GROUP ROM_REGION NOINPUT) zephyr_linker_section_configure(SECTION .resource_table KEEP INPUT ".resource_table*") endif() + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/ti_k3/am62x_m4/linker.ld b/soc/arm/ti_k3/am62x_m4/linker.ld index 793177b7f72..5e478a0541f 100644 --- a/soc/arm/ti_k3/am62x_m4/linker.ld +++ b/soc/arm/ti_k3/am62x_m4/linker.ld @@ -5,7 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include SECTIONS { diff --git a/soc/arm/ti_k3/am62x_m4/soc.c b/soc/arm/ti_k3/am62x_m4/soc.c index 1010e045ea5..9c86eb09a1d 100644 --- a/soc/arm/ti_k3/am62x_m4/soc.c +++ b/soc/arm/ti_k3/am62x_m4/soc.c @@ -70,4 +70,4 @@ static int am62x_m4_init(void) return 0; } -SYS_INIT(am62x_m4_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); +SYS_INIT(am62x_m4_init, EARLY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/soc/arm/ti_k3/am62x_m4/soc.h b/soc/arm/ti_k3/am62x_m4/soc.h index 089479dc6fd..01ff4b07080 100644 --- a/soc/arm/ti_k3/am62x_m4/soc.h +++ b/soc/arm/ti_k3/am62x_m4/soc.h @@ -4,4 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +#ifndef __SOC_H_ +#define __SOC_H_ + #include + +#endif /* __SOC_H */ diff --git a/soc/arm/ti_k3/pinctrl_soc.h b/soc/arm/ti_k3/pinctrl_soc.h index fb9fcfa5a7e..d85797bc2b2 100644 --- a/soc/arm/ti_k3/pinctrl_soc.h +++ b/soc/arm/ti_k3/pinctrl_soc.h @@ -7,6 +7,9 @@ #ifndef ZEPHYR_SOC_ARM_TI_K3_PINCTRL_SOC_H_ #define ZEPHYR_SOC_ARM_TI_K3_PINCTRL_SOC_H_ +#include +#include + #ifdef __cplusplus extern "C" { #endif diff --git a/soc/arm/ti_lm3s6965/CMakeLists.txt b/soc/arm/ti_lm3s6965/CMakeLists.txt index c5f6f41f49a..c76906ff5c3 100644 --- a/soc/arm/ti_lm3s6965/CMakeLists.txt +++ b/soc/arm/ti_lm3s6965/CMakeLists.txt @@ -12,3 +12,5 @@ zephyr_library_include_directories( ${ZEPHYR_BASE}/kernel/include ${ZEPHYR_BASE}/arch/arm/include ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/ti_lm3s6965/linker.ld b/soc/arm/ti_lm3s6965/linker.ld deleted file mode 100644 index 96ec397da78..00000000000 --- a/soc/arm/ti_lm3s6965/linker.ld +++ /dev/null @@ -1,9 +0,0 @@ -/* linker.ld - Linker command/script file */ - -/* - * Copyright (c) 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/ti_simplelink/cc13x2_cc26x2/CMakeLists.txt b/soc/arm/ti_simplelink/cc13x2_cc26x2/CMakeLists.txt index d2a17487383..bf52a055e3b 100644 --- a/soc/arm/ti_simplelink/cc13x2_cc26x2/CMakeLists.txt +++ b/soc/arm/ti_simplelink/cc13x2_cc26x2/CMakeLists.txt @@ -11,3 +11,5 @@ endif() zephyr_library_sources_ifdef(CONFIG_POWEROFF poweroff.c) zephyr_linker_sources_ifdef(CONFIG_HAS_TI_CCFG SECTIONS ccfg.ld) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/ti_simplelink/cc13x2_cc26x2/Kconfig.series b/soc/arm/ti_simplelink/cc13x2_cc26x2/Kconfig.series index d5defae07b0..b7d26a70539 100644 --- a/soc/arm/ti_simplelink/cc13x2_cc26x2/Kconfig.series +++ b/soc/arm/ti_simplelink/cc13x2_cc26x2/Kconfig.series @@ -13,7 +13,7 @@ config SOC_SERIES_CC13X2_CC26X2 select CPU_HAS_FPU select SOC_FAMILY_TISIMPLELINK select HAS_CC13X2_CC26X2_SDK - select HAS_TI_CCFG + select HAS_TI_CCFG if !BOOTLOADER_MCUBOOT select HAS_SEGGER_RTT if ZEPHYR_SEGGER_MODULE select HAS_PM select HAS_POWEROFF diff --git a/soc/arm/ti_simplelink/cc13x2_cc26x2/linker.ld b/soc/arm/ti_simplelink/cc13x2_cc26x2/linker.ld deleted file mode 100644 index 42f44928045..00000000000 --- a/soc/arm/ti_simplelink/cc13x2_cc26x2/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* linker.ld - Linker command/script file - * - * Copyright (c) 2019 Brett Witherspoon - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/ti_simplelink/cc13x2x7_cc26x2x7/CMakeLists.txt b/soc/arm/ti_simplelink/cc13x2x7_cc26x2x7/CMakeLists.txt index 4a2a41c5a5f..4194f426221 100644 --- a/soc/arm/ti_simplelink/cc13x2x7_cc26x2x7/CMakeLists.txt +++ b/soc/arm/ti_simplelink/cc13x2x7_cc26x2x7/CMakeLists.txt @@ -9,3 +9,5 @@ zephyr_library_sources_ifdef(CONFIG_PM power.c) zephyr_library_sources_ifdef(CONFIG_PM_DEVICE power.c) zephyr_linker_sources_ifdef(CONFIG_HAS_TI_CCFG SECTIONS ccfg.ld) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/ti_simplelink/cc13x2x7_cc26x2x7/Kconfig.soc b/soc/arm/ti_simplelink/cc13x2x7_cc26x2x7/Kconfig.soc index 74fae9acafd..96bd6cfce94 100644 --- a/soc/arm/ti_simplelink/cc13x2x7_cc26x2x7/Kconfig.soc +++ b/soc/arm/ti_simplelink/cc13x2x7_cc26x2x7/Kconfig.soc @@ -65,4 +65,11 @@ config CC13X2_CC26X2_BOOTLOADER_BACKDOOR_LEVEL help Set the active level of the pin selected for the bootloader backdoor. +config CC13X2_CC26X2_XOSC_CAPARRAY_DELTA + hex "Cap array tuning delta" + range 0 0xFF + default 0xD5 + help + Enable a specific cap array tunning delta. + endmenu diff --git a/soc/arm/ti_simplelink/cc13x2x7_cc26x2x7/ccfg.c b/soc/arm/ti_simplelink/cc13x2x7_cc26x2x7/ccfg.c index 74f34acac0d..de7b81c32bf 100644 --- a/soc/arm/ti_simplelink/cc13x2x7_cc26x2x7/ccfg.c +++ b/soc/arm/ti_simplelink/cc13x2x7_cc26x2x7/ccfg.c @@ -28,7 +28,7 @@ * https://software-dl.ti.com/simplelink/esd/simplelink_cc13xx_cc26xx_sdk/6.20.00.29/exports/release_notes_simplelink_cc13xx_cc26xx_sdk_6_20_00_29.html#known-issues */ #define SET_CCFG_MODE_CONF_XOSC_CAP_MOD 0x0 -#define SET_CCFG_MODE_CONF_XOSC_CAPARRAY_DELTA 0xD5 +#define SET_CCFG_MODE_CONF_XOSC_CAPARRAY_DELTA CONFIG_CC13X2_CC26X2_XOSC_CAPARRAY_DELTA #endif /* TI recommends setting CCFG values and then including the TI provided ccfg.c */ diff --git a/soc/arm/ti_simplelink/cc13x2x7_cc26x2x7/linker.ld b/soc/arm/ti_simplelink/cc13x2x7_cc26x2x7/linker.ld deleted file mode 100644 index f7ba43c42ca..00000000000 --- a/soc/arm/ti_simplelink/cc13x2x7_cc26x2x7/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* linker.ld - Linker command/script file - * - * Copyright (c) 2022 Vaishnav Achath - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/ti_simplelink/cc32xx/CMakeLists.txt b/soc/arm/ti_simplelink/cc32xx/CMakeLists.txt index cc11ff41954..9d704214718 100644 --- a/soc/arm/ti_simplelink/cc32xx/CMakeLists.txt +++ b/soc/arm/ti_simplelink/cc32xx/CMakeLists.txt @@ -6,3 +6,5 @@ zephyr_include_directories(.) if (DEFINED CONFIG_CC3220SF_DEBUG OR DEFINED CONFIG_CC3235SF_DEBUG) zephyr_linker_sources(ROM_START SORT_KEY 0 cc32xx_debug.ld) endif() + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/ti_simplelink/cc32xx/linker.ld b/soc/arm/ti_simplelink/cc32xx/linker.ld deleted file mode 100644 index e8b364e4dcf..00000000000 --- a/soc/arm/ti_simplelink/cc32xx/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 */ - -/* - * SPDX-License-Identifier: Apache-2.0 - * linker.ld - Linker command/script file - */ - -#include diff --git a/soc/arm/ti_simplelink/msp432p4xx/CMakeLists.txt b/soc/arm/ti_simplelink/msp432p4xx/CMakeLists.txt index 363109a3853..d93f837e79e 100644 --- a/soc/arm/ti_simplelink/msp432p4xx/CMakeLists.txt +++ b/soc/arm/ti_simplelink/msp432p4xx/CMakeLists.txt @@ -2,3 +2,5 @@ zephyr_compile_definitions(-D__MSP432P401R__) zephyr_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/ti_simplelink/msp432p4xx/linker.ld b/soc/arm/ti_simplelink/msp432p4xx/linker.ld deleted file mode 100644 index e8b364e4dcf..00000000000 --- a/soc/arm/ti_simplelink/msp432p4xx/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 */ - -/* - * SPDX-License-Identifier: Apache-2.0 - * linker.ld - Linker command/script file - */ - -#include diff --git a/soc/arm/xilinx_zynq7000/xc7zxxx/CMakeLists.txt b/soc/arm/xilinx_zynq7000/xc7zxxx/CMakeLists.txt index 98057786d37..d47bcfb128f 100644 --- a/soc/arm/xilinx_zynq7000/xc7zxxx/CMakeLists.txt +++ b/soc/arm/xilinx_zynq7000/xc7zxxx/CMakeLists.txt @@ -4,3 +4,5 @@ # zephyr_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/xilinx_zynq7000/xc7zxxx/linker.ld b/soc/arm/xilinx_zynq7000/xc7zxxx/linker.ld deleted file mode 100644 index 38f1212398d..00000000000 --- a/soc/arm/xilinx_zynq7000/xc7zxxx/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2021 Weidmueller Interface GmbH & Co. KG - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/xilinx_zynq7000/xc7zxxx/soc.c b/soc/arm/xilinx_zynq7000/xc7zxxx/soc.c index 5c7317ac3f7..a8d3eab7c73 100644 --- a/soc/arm/xilinx_zynq7000/xc7zxxx/soc.c +++ b/soc/arm/xilinx_zynq7000/xc7zxxx/soc.c @@ -10,7 +10,7 @@ #include #include -#include +#include #include "soc.h" /* System Level Control Registers (SLCR) */ diff --git a/soc/arm/xilinx_zynq7000/xc7zxxxs/CMakeLists.txt b/soc/arm/xilinx_zynq7000/xc7zxxxs/CMakeLists.txt index 98057786d37..d47bcfb128f 100644 --- a/soc/arm/xilinx_zynq7000/xc7zxxxs/CMakeLists.txt +++ b/soc/arm/xilinx_zynq7000/xc7zxxxs/CMakeLists.txt @@ -4,3 +4,5 @@ # zephyr_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/xilinx_zynq7000/xc7zxxxs/linker.ld b/soc/arm/xilinx_zynq7000/xc7zxxxs/linker.ld deleted file mode 100644 index 38f1212398d..00000000000 --- a/soc/arm/xilinx_zynq7000/xc7zxxxs/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2021 Weidmueller Interface GmbH & Co. KG - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm/xilinx_zynq7000/xc7zxxxs/soc.c b/soc/arm/xilinx_zynq7000/xc7zxxxs/soc.c index 7f794c5e9f7..66e17b56bc9 100644 --- a/soc/arm/xilinx_zynq7000/xc7zxxxs/soc.c +++ b/soc/arm/xilinx_zynq7000/xc7zxxxs/soc.c @@ -10,7 +10,7 @@ #include #include -#include +#include #include "soc.h" /* System Level Configuration Registers */ diff --git a/soc/arm/xilinx_zynqmp/CMakeLists.txt b/soc/arm/xilinx_zynqmp/CMakeLists.txt index e6654d03cb7..65bf778779b 100644 --- a/soc/arm/xilinx_zynqmp/CMakeLists.txt +++ b/soc/arm/xilinx_zynqmp/CMakeLists.txt @@ -9,3 +9,7 @@ zephyr_sources_ifdef( CONFIG_ARM_MPU arm_mpu_regions.c ) + +if(CONFIG_SOC_XILINX_ZYNQMP_RPU) + set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld CACHE INTERNAL "") +endif() diff --git a/soc/arm/xilinx_zynqmp/arm_mpu_regions.c b/soc/arm/xilinx_zynqmp/arm_mpu_regions.c index f10ba5d94e0..5a6f8dc6c21 100644 --- a/soc/arm/xilinx_zynqmp/arm_mpu_regions.c +++ b/soc/arm/xilinx_zynqmp/arm_mpu_regions.c @@ -4,7 +4,7 @@ */ #include -#include +#include #define MPUTYPE_READ_ONLY \ { \ diff --git a/soc/arm/xilinx_zynqmp/linker.ld b/soc/arm/xilinx_zynqmp/linker.ld deleted file mode 100644 index 744cd1c5f36..00000000000 --- a/soc/arm/xilinx_zynqmp/linker.ld +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright (c) 2019 Lexmark International, Inc. - * Copyright (c) 2019 Stephanos Ioannidis - * - * SPDX-License-Identifier: Apache-2.0 - */ - - -#if defined(CONFIG_SOC_XILINX_ZYNQMP_RPU) -#include -#endif diff --git a/soc/arm64/arm/fvp_aemv8a/CMakeLists.txt b/soc/arm64/arm/fvp_aemv8a/CMakeLists.txt index fd39809a833..b28d8b24523 100644 --- a/soc/arm64/arm/fvp_aemv8a/CMakeLists.txt +++ b/soc/arm64/arm/fvp_aemv8a/CMakeLists.txt @@ -2,3 +2,5 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_library_sources_ifdef(CONFIG_ARM_MMU mmu_regions.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm64/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm64/arm/fvp_aemv8a/linker.ld b/soc/arm64/arm/fvp_aemv8a/linker.ld deleted file mode 100644 index ab1d76f36ba..00000000000 --- a/soc/arm64/arm/fvp_aemv8a/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* - * linker.ld - Linker command/script file - * - * Copyright (c) 2021 Carlo Caione - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm64/arm/fvp_aemv8r/CMakeLists.txt b/soc/arm64/arm/fvp_aemv8r/CMakeLists.txt index cf23f50c5d0..ce116cb936e 100644 --- a/soc/arm64/arm/fvp_aemv8r/CMakeLists.txt +++ b/soc/arm64/arm/fvp_aemv8r/CMakeLists.txt @@ -5,3 +5,5 @@ zephyr_library_sources( ) zephyr_library_sources_ifdef(CONFIG_ARM_MPU arm_mpu_regions.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm64/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm64/arm/fvp_aemv8r/arm_mpu_regions.c b/soc/arm64/arm/fvp_aemv8r/arm_mpu_regions.c index 65400c67269..a36f53d4193 100644 --- a/soc/arm64/arm/fvp_aemv8r/arm_mpu_regions.c +++ b/soc/arm64/arm/fvp_aemv8r/arm_mpu_regions.c @@ -7,7 +7,6 @@ #include #include -#include #include static const struct arm_mpu_region mpu_regions[] = { @@ -39,9 +38,6 @@ static const struct arm_mpu_region mpu_regions[] = { #endif (uintptr_t)__kernel_ram_end, REGION_RAM_ATTR), - - /* Extra regions defined in device tree */ - DT_MEMORY_ATTR_APPLY(MPU_REGION_ENTRY_FROM_DTS) }; const struct arm_mpu_config mpu_config = { diff --git a/soc/arm64/arm/fvp_aemv8r/linker.ld b/soc/arm64/arm/fvp_aemv8r/linker.ld deleted file mode 100644 index afed4f40d25..00000000000 --- a/soc/arm64/arm/fvp_aemv8r/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* - * linker.ld - Linker command/script file - * - * Copyright (c) 2021 Arm Limited (or its affiliates). All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm64/bcm2711/CMakeLists.txt b/soc/arm64/bcm2711/CMakeLists.txt new file mode 100644 index 00000000000..733abbebd91 --- /dev/null +++ b/soc/arm64/bcm2711/CMakeLists.txt @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 +zephyr_sources_ifdef(CONFIG_ARM_MMU mmu_regions.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm64/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm64/bcm2711/Kconfig.defconfig b/soc/arm64/bcm2711/Kconfig.defconfig new file mode 100644 index 00000000000..0016ca57d03 --- /dev/null +++ b/soc/arm64/bcm2711/Kconfig.defconfig @@ -0,0 +1,17 @@ +# Copyright 2023 honglin leng +# SPDX-License-Identifier: Apache-2.0 + +if SOC_BCM2711 + +config SOC + default "bcm2711" + +config NUM_IRQS + int + default 260 + +config SYS_CLOCK_HW_CYCLES_PER_SEC + int + default 54000000 + +endif diff --git a/soc/arm64/bcm2711/Kconfig.soc b/soc/arm64/bcm2711/Kconfig.soc new file mode 100644 index 00000000000..4e1b69462ea --- /dev/null +++ b/soc/arm64/bcm2711/Kconfig.soc @@ -0,0 +1,8 @@ +# Copyright 2023 honglin leng +# SPDX-License-Identifier: Apache-2.0 + +config SOC_BCM2711 + bool "bcm2711" + select ARM64 + select CPU_CORTEX_A72 + select ARM_ARCH_TIMER if SYS_CLOCK_EXISTS diff --git a/soc/arm64/bcm2711/mmu_regions.c b/soc/arm64/bcm2711/mmu_regions.c new file mode 100644 index 00000000000..41a0bf1f367 --- /dev/null +++ b/soc/arm64/bcm2711/mmu_regions.c @@ -0,0 +1,25 @@ +/* + * Copyright 2023 honglin leng + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include + +static const struct arm_mmu_region mmu_regions[] = { + MMU_REGION_FLAT_ENTRY("GIC", + DT_REG_ADDR_BY_IDX(DT_INST(0, arm_gic), 0), + DT_REG_SIZE_BY_IDX(DT_INST(0, arm_gic), 0), + MT_DEVICE_nGnRnE | MT_P_RW_U_NA | MT_DEFAULT_SECURE_STATE), + + MMU_REGION_FLAT_ENTRY("GIC", + DT_REG_ADDR_BY_IDX(DT_INST(0, arm_gic), 1), + DT_REG_SIZE_BY_IDX(DT_INST(0, arm_gic), 1), + MT_DEVICE_nGnRnE | MT_P_RW_U_NA | MT_DEFAULT_SECURE_STATE), +}; + +const struct arm_mmu_config mmu_config = { + .num_regions = ARRAY_SIZE(mmu_regions), + .mmu_regions = mmu_regions, +}; diff --git a/soc/arm64/bcm_vk/viper/CMakeLists.txt b/soc/arm64/bcm_vk/viper/CMakeLists.txt index 8b59f41d728..93f8b45bc82 100644 --- a/soc/arm64/bcm_vk/viper/CMakeLists.txt +++ b/soc/arm64/bcm_vk/viper/CMakeLists.txt @@ -7,3 +7,5 @@ zephyr_sources( zephyr_sources_ifdef(CONFIG_SOC_BCM58402_A72 plat_core.c) zephyr_sources_ifdef(CONFIG_ARM_MMU mmu_regions.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm64/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm64/bcm_vk/viper/linker.ld b/soc/arm64/bcm_vk/viper/linker.ld deleted file mode 100644 index 223bd37f5c5..00000000000 --- a/soc/arm64/bcm_vk/viper/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright 2020 Broadcom - * - * SPDX-License-Identifier: Apache-2.0 - */ - - -#include diff --git a/soc/arm64/bcm_vk/viper/linker_a72.ld b/soc/arm64/bcm_vk/viper/linker_a72.ld deleted file mode 100644 index a12c2bd066b..00000000000 --- a/soc/arm64/bcm_vk/viper/linker_a72.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright 2020 Broadcom - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm64/intel_socfpga/agilex/CMakeLists.txt b/soc/arm64/intel_socfpga/agilex/CMakeLists.txt index ba3d3c4e034..3cdb01da699 100644 --- a/soc/arm64/intel_socfpga/agilex/CMakeLists.txt +++ b/soc/arm64/intel_socfpga/agilex/CMakeLists.txt @@ -4,3 +4,5 @@ zephyr_include_directories(.) zephyr_library_sources_ifdef(CONFIG_ARM_MMU mmu_regions.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm64/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm64/intel_socfpga/agilex/linker.ld b/soc/arm64/intel_socfpga/agilex/linker.ld deleted file mode 100644 index 2b4cd596a17..00000000000 --- a/soc/arm64/intel_socfpga/agilex/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) 2020 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - * - */ - -#include diff --git a/soc/arm64/intel_socfpga/agilex5/CMakeLists.txt b/soc/arm64/intel_socfpga/agilex5/CMakeLists.txt index f0e79e927d3..a538caf7a33 100644 --- a/soc/arm64/intel_socfpga/agilex5/CMakeLists.txt +++ b/soc/arm64/intel_socfpga/agilex5/CMakeLists.txt @@ -4,3 +4,5 @@ zephyr_include_directories(.) zephyr_library_sources_ifdef(CONFIG_ARM_MMU mmu_regions.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm64/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm64/intel_socfpga/agilex5/linker.ld b/soc/arm64/intel_socfpga/agilex5/linker.ld deleted file mode 100644 index 9f5bc4c4f7e..00000000000 --- a/soc/arm64/intel_socfpga/agilex5/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) 2022 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - * - */ - -#include diff --git a/soc/arm64/nxp_imx/mimx8m/CMakeLists.txt b/soc/arm64/nxp_imx/mimx8m/CMakeLists.txt index ff4a4e0deba..032c4a8642d 100644 --- a/soc/arm64/nxp_imx/mimx8m/CMakeLists.txt +++ b/soc/arm64/nxp_imx/mimx8m/CMakeLists.txt @@ -3,3 +3,5 @@ zephyr_include_directories(.) zephyr_sources_ifdef(CONFIG_ARM_MMU mmu_regions.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm64/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm64/nxp_imx/mimx8m/Kconfig.defconfig.mimx8mm b/soc/arm64/nxp_imx/mimx8m/Kconfig.defconfig.mimx8mm index a35ff4951ef..a77d9f837df 100644 --- a/soc/arm64/nxp_imx/mimx8m/Kconfig.defconfig.mimx8mm +++ b/soc/arm64/nxp_imx/mimx8m/Kconfig.defconfig.mimx8mm @@ -1,10 +1,10 @@ -# Copyright 2020-2022 NXP +# Copyright 2020-2023 NXP # SPDX-License-Identifier: Apache-2.0 if SOC_MIMX8MM_A53 config SOC - default "mimx8mm6" + default "mimx8mm6_ca53" # Workaround for not being able to have commas in macro arguments DT_CHOSEN_Z_FLASH := zephyr,flash diff --git a/soc/arm64/nxp_imx/mimx8m/Kconfig.defconfig.mimx8mn b/soc/arm64/nxp_imx/mimx8m/Kconfig.defconfig.mimx8mn index 9c5e7bfe041..c6c2837d74d 100644 --- a/soc/arm64/nxp_imx/mimx8m/Kconfig.defconfig.mimx8mn +++ b/soc/arm64/nxp_imx/mimx8m/Kconfig.defconfig.mimx8mn @@ -1,10 +1,10 @@ -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # SPDX-License-Identifier: Apache-2.0 if SOC_MIMX8MN_A53 config SOC - default "mimx8mn6" + default "mimx8mn6_ca53" # Workaround for not being able to have commas in macro arguments DT_CHOSEN_Z_FLASH := zephyr,flash diff --git a/soc/arm64/nxp_imx/mimx8m/Kconfig.defconfig.mimx8mp b/soc/arm64/nxp_imx/mimx8m/Kconfig.defconfig.mimx8mp index 5a99f354e5d..ebdfa764a69 100644 --- a/soc/arm64/nxp_imx/mimx8m/Kconfig.defconfig.mimx8mp +++ b/soc/arm64/nxp_imx/mimx8m/Kconfig.defconfig.mimx8mp @@ -1,10 +1,10 @@ -# Copyright 2021-2022 NXP +# Copyright 2021-2023 NXP # SPDX-License-Identifier: Apache-2.0 if SOC_MIMX8MP_A53 config SOC - default "mimx8ml8" + default "mimx8ml8_ca53" # Workaround for not being able to have commas in macro arguments DT_CHOSEN_Z_FLASH := zephyr,flash diff --git a/soc/arm64/nxp_imx/mimx8m/linker.ld b/soc/arm64/nxp_imx/mimx8m/linker.ld deleted file mode 100644 index 65c5d0722aa..00000000000 --- a/soc/arm64/nxp_imx/mimx8m/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright 2020 NXP - * - * SPDX-License-Identifier: Apache-2.0 - */ - - -#include diff --git a/soc/arm64/nxp_imx/mimx9/CMakeLists.txt b/soc/arm64/nxp_imx/mimx9/CMakeLists.txt index ff4a4e0deba..77a9500f5b7 100644 --- a/soc/arm64/nxp_imx/mimx9/CMakeLists.txt +++ b/soc/arm64/nxp_imx/mimx9/CMakeLists.txt @@ -3,3 +3,5 @@ zephyr_include_directories(.) zephyr_sources_ifdef(CONFIG_ARM_MMU mmu_regions.c) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/arm64/nxp_imx/mimx9/Kconfig.defconfig.mimx93 b/soc/arm64/nxp_imx/mimx9/Kconfig.defconfig.mimx93 index 59277175063..45e67de35ed 100644 --- a/soc/arm64/nxp_imx/mimx9/Kconfig.defconfig.mimx93 +++ b/soc/arm64/nxp_imx/mimx9/Kconfig.defconfig.mimx93 @@ -1,10 +1,10 @@ -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # SPDX-License-Identifier: Apache-2.0 if SOC_MIMX93_A55 config SOC - default "mimx9352" + default "mimx9352_ca55" # Workaround for not being able to have commas in macro arguments DT_CHOSEN_Z_FLASH := zephyr,flash diff --git a/soc/arm64/nxp_imx/mimx9/Kconfig.soc b/soc/arm64/nxp_imx/mimx9/Kconfig.soc index 01ba9896874..3f38d40131f 100644 --- a/soc/arm64/nxp_imx/mimx9/Kconfig.soc +++ b/soc/arm64/nxp_imx/mimx9/Kconfig.soc @@ -11,7 +11,7 @@ config SOC_MIMX93_A55 select CPU_CORTEX_A55 select ARM_ARCH_TIMER if SYS_CLOCK_EXISTS select HAS_MCUX if CLOCK_CONTROL - select HAS_MCUX_CCM if CLOCK_CONTROL + select HAS_MCUX_CCM_REV2 if CLOCK_CONTROL select HAS_MCUX_IOMUXC if PINCTRL endchoice diff --git a/soc/arm64/nxp_imx/mimx9/mmu_regions.c b/soc/arm64/nxp_imx/mimx9/mmu_regions.c index fb53c54e7f3..6dd767c2c9c 100644 --- a/soc/arm64/nxp_imx/mimx9/mmu_regions.c +++ b/soc/arm64/nxp_imx/mimx9/mmu_regions.c @@ -30,6 +30,11 @@ static const struct arm_mmu_region mmu_regions[] = { DT_REG_SIZE(DT_NODELABEL(ana_pll)), MT_DEVICE_nGnRnE | MT_P_RW_U_NA | MT_NS), + MMU_REGION_FLAT_ENTRY("UART1", + DT_REG_ADDR(DT_NODELABEL(lpuart1)), + DT_REG_SIZE(DT_NODELABEL(lpuart1)), + MT_DEVICE_nGnRnE | MT_P_RW_U_NA | MT_NS), + MMU_REGION_FLAT_ENTRY("UART2", DT_REG_ADDR(DT_NODELABEL(lpuart2)), DT_REG_SIZE(DT_NODELABEL(lpuart2)), diff --git a/soc/arm64/nxp_layerscape/ls1046a/CMakeLists.txt b/soc/arm64/nxp_layerscape/ls1046a/CMakeLists.txt index 2cf9a407f84..22fc2aa11be 100644 --- a/soc/arm64/nxp_layerscape/ls1046a/CMakeLists.txt +++ b/soc/arm64/nxp_layerscape/ls1046a/CMakeLists.txt @@ -1,3 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_sources_ifdef(CONFIG_ARM_MMU mmu_regions.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm64/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm64/nxp_layerscape/ls1046a/linker.ld b/soc/arm64/nxp_layerscape/ls1046a/linker.ld deleted file mode 100644 index 40dbcd63fca..00000000000 --- a/soc/arm64/nxp_layerscape/ls1046a/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright 2021 NXP - * - * SPDX-License-Identifier: Apache-2.0 - */ - - -#include diff --git a/soc/arm64/qemu_cortex_a53/CMakeLists.txt b/soc/arm64/qemu_cortex_a53/CMakeLists.txt index fd39809a833..b28d8b24523 100644 --- a/soc/arm64/qemu_cortex_a53/CMakeLists.txt +++ b/soc/arm64/qemu_cortex_a53/CMakeLists.txt @@ -2,3 +2,5 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_library_sources_ifdef(CONFIG_ARM_MMU mmu_regions.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm64/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm64/qemu_cortex_a53/linker.ld b/soc/arm64/qemu_cortex_a53/linker.ld deleted file mode 100644 index 9b7be757e17..00000000000 --- a/soc/arm64/qemu_cortex_a53/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) 2019 Carlo Caione - * - * SPDX-License-Identifier: Apache-2.0 - * - */ - -#include diff --git a/soc/arm64/qemu_virt_arm64/CMakeLists.txt b/soc/arm64/qemu_virt_arm64/CMakeLists.txt index 495a3d96b89..7c7a3c4d52c 100644 --- a/soc/arm64/qemu_virt_arm64/CMakeLists.txt +++ b/soc/arm64/qemu_virt_arm64/CMakeLists.txt @@ -2,3 +2,5 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_library_sources_ifdef(CONFIG_ARM_MMU mmu_regions.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm64/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm64/qemu_virt_arm64/linker.ld b/soc/arm64/qemu_virt_arm64/linker.ld deleted file mode 100644 index a7bcbf24cfb..00000000000 --- a/soc/arm64/qemu_virt_arm64/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) 2022 Huawei France Technologies SAS - * - * SPDX-License-Identifier: Apache-2.0 - * - */ - -#include diff --git a/soc/arm64/renesas_rcar/gen3/CMakeLists.txt b/soc/arm64/renesas_rcar/gen3/CMakeLists.txt index 23315289c61..16dcc07b754 100644 --- a/soc/arm64/renesas_rcar/gen3/CMakeLists.txt +++ b/soc/arm64/renesas_rcar/gen3/CMakeLists.txt @@ -4,3 +4,5 @@ zephyr_library_sources_ifdef(CONFIG_SOC_ARM64_R8A77951 pfc_r8a77951.c) zephyr_library_sources_ifdef(CONFIG_SOC_R8A77961 pfc_r8a77961.c) zephyr_library_sources_ifdef(CONFIG_ARM_MMU mmu_regions.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm64/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm64/renesas_rcar/gen3/linker.ld b/soc/arm64/renesas_rcar/gen3/linker.ld deleted file mode 100644 index 0deb8cd2794..00000000000 --- a/soc/arm64/renesas_rcar/gen3/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2023 EPAM Systems - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm64/rockchip/Kconfig b/soc/arm64/rockchip/Kconfig index 668d1e9785a..e0b4b937c79 100644 --- a/soc/arm64/rockchip/Kconfig +++ b/soc/arm64/rockchip/Kconfig @@ -17,5 +17,6 @@ source "soc/arm64/rockchip/*/Kconfig.soc" config SOC_PART_NUMBER default "RK3399" if SOC_SERIES_RK3399 + default "RK3568" if SOC_SERIES_RK3568 endif # SOC_FAMILY_ROCKCHIP diff --git a/soc/arm64/rockchip/rk3399/CMakeLists.txt b/soc/arm64/rockchip/rk3399/CMakeLists.txt index 2cf9a407f84..22fc2aa11be 100644 --- a/soc/arm64/rockchip/rk3399/CMakeLists.txt +++ b/soc/arm64/rockchip/rk3399/CMakeLists.txt @@ -1,3 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_sources_ifdef(CONFIG_ARM_MMU mmu_regions.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm64/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm64/rockchip/rk3399/linker.ld b/soc/arm64/rockchip/rk3399/linker.ld deleted file mode 100644 index 1826843d117..00000000000 --- a/soc/arm64/rockchip/rk3399/linker.ld +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright 2022 Huawei France Technologies SASU - * - * SPDX-License-Identifier: Apache-2.0 - */ - - -#include diff --git a/soc/arm64/rockchip/rk3568/CMakeLists.txt b/soc/arm64/rockchip/rk3568/CMakeLists.txt new file mode 100644 index 00000000000..2cf9a407f84 --- /dev/null +++ b/soc/arm64/rockchip/rk3568/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_sources_ifdef(CONFIG_ARM_MMU mmu_regions.c) diff --git a/soc/arm64/rockchip/rk3568/Kconfig.defconfig.rk3568 b/soc/arm64/rockchip/rk3568/Kconfig.defconfig.rk3568 new file mode 100644 index 00000000000..13dca55c6e9 --- /dev/null +++ b/soc/arm64/rockchip/rk3568/Kconfig.defconfig.rk3568 @@ -0,0 +1,24 @@ +# Copyright 2022 HNU-ESNL +# Copyright 2022 openEuler SIG-Zephyr +# SPDX-License-Identifier: Apache-2.0 + +if SOC_RK3568 + +config SOC + default "rk3568" + +config FLASH_SIZE + default 0 + +config FLASH_BASE_ADDRESS + default 0 + +config NUM_IRQS + int + default 240 + +config SYS_CLOCK_HW_CYCLES_PER_SEC + int + default 24000000 + +endif diff --git a/soc/arm64/rockchip/rk3568/Kconfig.defconfig.series b/soc/arm64/rockchip/rk3568/Kconfig.defconfig.series new file mode 100644 index 00000000000..96279038e4a --- /dev/null +++ b/soc/arm64/rockchip/rk3568/Kconfig.defconfig.series @@ -0,0 +1,12 @@ +# Copyright 2022 HNU-ESNL +# Copyright 2022 openEuler SIG-Zephyr +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_RK3568 + +config SOC_SERIES + default "rk3568" + +source "soc/arm64/rockchip/rk3568/Kconfig.defconfig.rk3568" + +endif # SOC_SERIES_RK3568 diff --git a/soc/arm64/rockchip/rk3568/Kconfig.series b/soc/arm64/rockchip/rk3568/Kconfig.series new file mode 100644 index 00000000000..15909e5bff0 --- /dev/null +++ b/soc/arm64/rockchip/rk3568/Kconfig.series @@ -0,0 +1,10 @@ +# Copyright 2022 HNU-ESNL +# Copyright 2022 openEuler SIG-Zephyrs +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_RK3568 + bool "Rockchip RK3568 Series" + select ARM64 + select SOC_FAMILY_ROCKCHIP + help + Enable support for RK3568 Series. diff --git a/soc/arm64/rockchip/rk3568/Kconfig.soc b/soc/arm64/rockchip/rk3568/Kconfig.soc new file mode 100644 index 00000000000..7bb2be41909 --- /dev/null +++ b/soc/arm64/rockchip/rk3568/Kconfig.soc @@ -0,0 +1,16 @@ +# Copyright 2022 HNU-ESNL +# Copyright 2022 openEuler SIG-Zephyr +# SPDX-License-Identifier: Apache-2.0 + +choice +prompt "Rockchip RK3568 SoC" +depends on SOC_SERIES_RK3568 + +config SOC_RK3568 + bool "Rockchip rk3568" + select ARM64 + select CPU_CORTEX_A55 + select ARM_ARCH_TIMER + select GIC_V3 + +endchoice diff --git a/soc/arm64/rockchip/rk3568/linker.ld b/soc/arm64/rockchip/rk3568/linker.ld new file mode 100644 index 00000000000..f1b07809e1f --- /dev/null +++ b/soc/arm64/rockchip/rk3568/linker.ld @@ -0,0 +1,7 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include diff --git a/soc/arm64/rockchip/rk3568/mmu_regions.c b/soc/arm64/rockchip/rk3568/mmu_regions.c new file mode 100644 index 00000000000..73b615cab80 --- /dev/null +++ b/soc/arm64/rockchip/rk3568/mmu_regions.c @@ -0,0 +1,29 @@ +/* + * Copyright 2020 NXP + * Copyright 2022 HNU-ESNL + * Copyright 2022 openEuler SIG-Zephyr + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include + +static const struct arm_mmu_region mmu_regions[] = { + + MMU_REGION_FLAT_ENTRY("GIC", + DT_REG_ADDR_BY_IDX(DT_NODELABEL(gic), 0), + DT_REG_SIZE_BY_IDX(DT_NODELABEL(gic), 0), + MT_DEVICE_nGnRnE | MT_P_RW_U_RW | MT_NS), + + MMU_REGION_FLAT_ENTRY("GIC", + DT_REG_ADDR_BY_IDX(DT_NODELABEL(gic), 1), + DT_REG_SIZE_BY_IDX(DT_NODELABEL(gic), 1), + MT_DEVICE_nGnRnE | MT_P_RW_U_RW | MT_NS), + +}; + +const struct arm_mmu_config mmu_config = { + .num_regions = ARRAY_SIZE(mmu_regions), + .mmu_regions = mmu_regions, +}; diff --git a/soc/arm64/ti_k3/am6x/CMakeLists.txt b/soc/arm64/ti_k3/am6x/CMakeLists.txt index 6c961dd2801..491cafbec22 100644 --- a/soc/arm64/ti_k3/am6x/CMakeLists.txt +++ b/soc/arm64/ti_k3/am6x/CMakeLists.txt @@ -2,3 +2,5 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_sources_ifdef(CONFIG_ARM_MMU mmu_regions.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm64/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm64/ti_k3/am6x/linker.ld b/soc/arm64/ti_k3/am6x/linker.ld deleted file mode 100644 index 849a1199eb4..00000000000 --- a/soc/arm64/ti_k3/am6x/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2023 Enphase Energy - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm64/ti_k3/pinctrl_soc.h b/soc/arm64/ti_k3/pinctrl_soc.h index 0328f52b390..055215db7f2 100644 --- a/soc/arm64/ti_k3/pinctrl_soc.h +++ b/soc/arm64/ti_k3/pinctrl_soc.h @@ -7,6 +7,9 @@ #ifndef ZEPHYR_SOC_ARM64_TI_K3_PINCTRL_SOC_H_ #define ZEPHYR_SOC_ARM64_TI_K3_PINCTRL_SOC_H_ +#include +#include + #ifdef __cplusplus extern "C" { #endif diff --git a/soc/arm64/xenvm/CMakeLists.txt b/soc/arm64/xenvm/CMakeLists.txt index ac596106c28..7ffbb965792 100644 --- a/soc/arm64/xenvm/CMakeLists.txt +++ b/soc/arm64/xenvm/CMakeLists.txt @@ -1,3 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_library_sources_ifdef(CONFIG_ARM_MMU mmu_regions.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm64/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm64/xenvm/Kconfig.defconfig b/soc/arm64/xenvm/Kconfig.defconfig index 9d8d6847e20..4a88b6bed93 100644 --- a/soc/arm64/xenvm/Kconfig.defconfig +++ b/soc/arm64/xenvm/Kconfig.defconfig @@ -14,4 +14,9 @@ config SYS_CLOCK_HW_CYCLES_PER_SEC int default 8320000 +# We need at least 16M of virtual address space to map memory of Xen node +# 32M should be enough for basic use-cases +config KERNEL_VM_SIZE + default 0x2000000 + endif diff --git a/soc/arm64/xenvm/Kconfig.soc b/soc/arm64/xenvm/Kconfig.soc index 89f90ed5c7c..00f1bf0ca31 100644 --- a/soc/arm64/xenvm/Kconfig.soc +++ b/soc/arm64/xenvm/Kconfig.soc @@ -6,9 +6,3 @@ config SOC_XENVM select ARM64 select ARM_ARCH_TIMER if SYS_CLOCK_EXISTS select CPU_CORTEX_A72 - -config XEN_INITIAL_DOMAIN - bool "Zephyr as Xen Domain 0" - depends on SOC_XENVM - help - Built binary will be used as Xen privileged domain. diff --git a/soc/arm64/xenvm/linker.ld b/soc/arm64/xenvm/linker.ld deleted file mode 100644 index 6f57b480eb8..00000000000 --- a/soc/arm64/xenvm/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright 2020 EPAM Systems - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/arm64/xenvm/mmu_regions.c b/soc/arm64/xenvm/mmu_regions.c index 43e3ada82e9..070bb01474f 100644 --- a/soc/arm64/xenvm/mmu_regions.c +++ b/soc/arm64/xenvm/mmu_regions.c @@ -18,11 +18,6 @@ static const struct arm_mmu_region mmu_regions[] = { DT_REG_ADDR_BY_IDX(DT_INST(0, arm_gic), 1), DT_REG_SIZE_BY_IDX(DT_INST(0, arm_gic), 1), MT_DEVICE_nGnRnE | MT_P_RW_U_NA | MT_NS), - - MMU_REGION_FLAT_ENTRY("HYPERVISOR", - DT_REG_ADDR_BY_IDX(DT_INST(0, xen_xen), 0), - DT_REG_SIZE_BY_IDX(DT_INST(0, xen_xen), 0), - MT_NORMAL | MT_P_RW_U_NA | MT_NS), }; const struct arm_mmu_config mmu_config = { diff --git a/soc/mips/qemu_malta/CMakeLists.txt b/soc/mips/qemu_malta/CMakeLists.txt index 49a74924cdc..351ffebf5b5 100644 --- a/soc/mips/qemu_malta/CMakeLists.txt +++ b/soc/mips/qemu_malta/CMakeLists.txt @@ -15,3 +15,5 @@ zephyr_ld_options( -mips32 ${TOOLCHAIN_LD_FLAGS} ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/mips/linker.ld CACHE INTERNAL "") diff --git a/soc/mips/qemu_malta/linker.ld b/soc/mips/qemu_malta/linker.ld deleted file mode 100644 index f6baabc0aa6..00000000000 --- a/soc/mips/qemu_malta/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2020 Antony Pavlov - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/nios2/nios2-qemu/CMakeLists.txt b/soc/nios2/nios2-qemu/CMakeLists.txt index 1097b991ed2..b6dd454d035 100644 --- a/soc/nios2/nios2-qemu/CMakeLists.txt +++ b/soc/nios2/nios2-qemu/CMakeLists.txt @@ -1,3 +1,4 @@ # SPDX-License-Identifier: Apache-2.0 -# intentionally left empty +zephyr_include_directories(include) +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/nios2/nios2f-zephyr/CMakeLists.txt b/soc/nios2/nios2f-zephyr/CMakeLists.txt index 1097b991ed2..789c4c81fc9 100644 --- a/soc/nios2/nios2f-zephyr/CMakeLists.txt +++ b/soc/nios2/nios2f-zephyr/CMakeLists.txt @@ -1,3 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# intentionally left empty +zephyr_include_directories(include) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/posix/inf_clock/CMakeLists.txt b/soc/posix/inf_clock/CMakeLists.txt index b256d67daa9..5bc6ab3c428 100644 --- a/soc/posix/inf_clock/CMakeLists.txt +++ b/soc/posix/inf_clock/CMakeLists.txt @@ -13,3 +13,5 @@ zephyr_library_include_directories( ${ZEPHYR_BASE}/kernel/include ${ZEPHYR_BASE}/arch/posix/include ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/posix/linker.ld CACHE INTERNAL "") diff --git a/soc/posix/inf_clock/Kconfig b/soc/posix/inf_clock/Kconfig index d66f09f1b92..9e5f5ccc89f 100644 --- a/soc/posix/inf_clock/Kconfig +++ b/soc/posix/inf_clock/Kconfig @@ -1,12 +1,49 @@ # Copyright (c) 2023 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 -config NATIVE_SIMULATOR_CPU_N +config NATIVE_SIMULATOR_MCU_N int "CPU Number this image targets" range 0 15 default 0 depends on NATIVE_LIBRARY help - Which native simulator embedded CPU number is this image targeting. + Which native simulator microcontroller/CPU number is this image targeting. This option is only applicable for targets which use the native simulator as their runner. + +config NATIVE_SIMULATOR_NUMBER_MCUS + int "Total number of MCUs this target has" + range 1 16 + default 1 + depends on NATIVE_LIBRARY + help + How many AMP MCUs does this target have in total. + +config NATIVE_SIMULATOR_PRIMARY_MCU_INDEX + int "Which CPU is the primary/preferred" + default 0 + depends on NATIVE_LIBRARY + help + On a multi MCU device, which MCU is the preferred one. + This MCU will for example have its tests command line parameters presented + without any prefix. Note that an MCU being primary does not imply it will be + the first one to boot, or even that it will boot automatically. + +config NATIVE_SIMULATOR_EXTRA_IMAGE_PATHS + string "Other cores images to include" + depends on NATIVE_LIBRARY + help + This option can be used to provide the native simulator with other MCUs/Cores images which have + been produced by either other Zephyr builds or different OS builds. + So you can, for ex., use this application build produce one core image, and at the same time + have it produce the final link with the native simulator runner and the other MCU images. + +config NATIVE_SIMULATOR_AUTOSTART_MCU + bool "Auto-start this MCU" + depends on NATIVE_LIBRARY + help + Automatically start the MCU this Zephyr image is built for during HW boot, + even if in other circumstances this MCU would not start automatically (for ex. because + another core is meant to release its reset). + If that MCU was, by HW design, going to start at HW boot anyhow, this option does nothing. + This option is meant to facilitate development. diff --git a/soc/posix/inf_clock/linker.ld b/soc/posix/inf_clock/linker.ld deleted file mode 100644 index e33a3520239..00000000000 --- a/soc/posix/inf_clock/linker.ld +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2016 Intel Corporation - * Copyright (c) 2017 Oticon A/S - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @brief Linker script for the POSIX ARCH & INF_CLOCK SOC - */ - -#include diff --git a/soc/posix/inf_clock/posix_board_if.h b/soc/posix/inf_clock/posix_board_if.h index 9fec9915443..1d851fb3935 100644 --- a/soc/posix/inf_clock/posix_board_if.h +++ b/soc/posix/inf_clock/posix_board_if.h @@ -6,7 +6,7 @@ #ifndef _POSIX_CORE_BOARD_PROVIDED_IF_H #define _POSIX_CORE_BOARD_PROVIDED_IF_H -#include "zephyr/types.h" +#include /* * This file lists the functions the posix "inf_clock" soc diff --git a/soc/riscv/espressif_esp32/esp32c3/CMakeLists.txt b/soc/riscv/espressif_esp32/esp32c3/CMakeLists.txt index 4dd457b6801..e97f71751ef 100644 --- a/soc/riscv/espressif_esp32/esp32c3/CMakeLists.txt +++ b/soc/riscv/espressif_esp32/esp32c3/CMakeLists.txt @@ -94,3 +94,9 @@ endif() board_finalize_runner_args(esp32 "--esp-boot-address=${boot_off}") board_finalize_runner_args(esp32 "--esp-app-address=${img_0_off}") + +if(CONFIG_MCUBOOT) + set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/mcuboot.ld CACHE INTERNAL "") +else() + set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/default.ld CACHE INTERNAL "") +endif() diff --git a/soc/riscv/espressif_esp32/esp32c3/Kconfig.soc b/soc/riscv/espressif_esp32/esp32c3/Kconfig.soc index dce91fcc86a..66a6e918f31 100644 --- a/soc/riscv/espressif_esp32/esp32c3/Kconfig.soc +++ b/soc/riscv/espressif_esp32/esp32c3/Kconfig.soc @@ -17,10 +17,10 @@ choice SOC_PART_NUMBER bool "ESP32C3_FX4" config SOC_ESP32C3_MINI_N4 bool "ESP32C3_MINI_N4" - config SOC_ESP32C3_WROOM_H2 - bool "ESP32C3_MINI_N4" - config SOC_ESP32C3_WROOM_H4 - bool "ESP32C3_MINI_N4" + config SOC_ESP32C3_WROOM_02_N4 + bool "ESP32C3_WROOM_02_N4" + config SOC_ESP32C3_WROOM_02_N8 + bool "ESP32C3_WROOM_02_N8" endchoice # SOC_PART_NUMBER diff --git a/soc/riscv/espressif_esp32/esp32c3/default.ld b/soc/riscv/espressif_esp32/esp32c3/default.ld index 01aeb903af2..0884e3d7d3a 100644 --- a/soc/riscv/espressif_esp32/esp32c3/default.ld +++ b/soc/riscv/espressif_esp32/esp32c3/default.ld @@ -49,6 +49,11 @@ #define IROM_SEG_ALIGN 0x10000 #endif +/* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA. + * Executing directly from LMA is not possible. */ +#undef GROUP_ROM_LINK_IN +#define GROUP_ROM_LINK_IN(vregion, lregion) > RODATA_REGION AT > lregion + /* Global symbols required for espressif hal build */ MEMORY { @@ -125,6 +130,7 @@ SECTIONS SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) { + _rodata_reserved_start = ABSOLUTE(.); _rodata_start = ABSOLUTE(.); *(.rodata_desc .rodata_desc.*) @@ -181,15 +187,9 @@ SECTIONS *(.rodata_wlog) *(.rodata_wlog*) _thread_local_end = ABSOLUTE(.); - _rodata_reserved_end = ABSOLUTE(.); . = ALIGN(4); } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) - /* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA. - * Executing directly from LMA is not possible. */ - #pragma push_macro("GROUP_ROM_LINK_IN") - #undef GROUP_ROM_LINK_IN - #define GROUP_ROM_LINK_IN(vregion, lregion) > RODATA_REGION AT > lregion #include #include #include @@ -197,12 +197,13 @@ SECTIONS #include #include #include - #pragma pop_macro("GROUP_ROM_LINK_IN") + #include /* Create an explicit section at the end of all the data that shall be mapped into drom. * This is used to calculate the size of the _image_drom_size variable */ SECTION_PROLOGUE(_RODATA_SECTION_END,,) { + _rodata_reserved_end = ABSOLUTE(.); . = ALIGN(4); _image_rodata_end = ABSOLUTE(.); } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) @@ -312,8 +313,6 @@ SECTIONS . = ALIGN(4); } GROUP_LINK_IN(RAMABLE_REGION) - #include - .dram0.data : { . = ALIGN(4); @@ -404,7 +403,6 @@ SECTIONS { . = SIZEOF(_RODATA_SECTION_NAME); . = ALIGN(0x10000) + 0x20; - _rodata_reserved_start = .; } GROUP_LINK_IN(FLASH_CODE_REGION) .flash.text : ALIGN(IROM_SEG_ALIGN) diff --git a/soc/riscv/espressif_esp32/esp32c3/linker.ld b/soc/riscv/espressif_esp32/esp32c3/linker.ld deleted file mode 100644 index 934088ca728..00000000000 --- a/soc/riscv/espressif_esp32/esp32c3/linker.ld +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - */ - -#if defined(CONFIG_MCUBOOT) - /* Using mcuboot as ESP32C3 2nd stage bootloader */ - #include "mcuboot.ld" - -#else - /* Application default linker script */ - #include "default.ld" - -#endif /* CONFIG_MCUBOOT */ diff --git a/soc/riscv/espressif_esp32/esp32c3/soc.c b/soc/riscv/espressif_esp32/esp32c3/soc.c index be94280a96a..8bb32a5febd 100644 --- a/soc/riscv/espressif_esp32/esp32c3/soc.c +++ b/soc/riscv/espressif_esp32/esp32c3/soc.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #ifdef CONFIG_MCUBOOT diff --git a/soc/riscv/espressif_esp32/esp32c3/soc_irq.c b/soc/riscv/espressif_esp32/esp32c3/soc_irq.c index e1be1d23019..44c8161950c 100644 --- a/soc/riscv/espressif_esp32/esp32c3/soc_irq.c +++ b/soc/riscv/espressif_esp32/esp32c3/soc_irq.c @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include diff --git a/soc/riscv/litex-vexriscv/CMakeLists.txt b/soc/riscv/litex-vexriscv/CMakeLists.txt index 34d6046ab68..9d100ea0e2a 100644 --- a/soc/riscv/litex-vexriscv/CMakeLists.txt +++ b/soc/riscv/litex-vexriscv/CMakeLists.txt @@ -8,3 +8,5 @@ zephyr_sources( ../riscv-privileged/common/soc_irq.S ../riscv-privileged/common/vector.S ) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld CACHE INTERNAL "") diff --git a/soc/riscv/litex-vexriscv/linker.ld b/soc/riscv/litex-vexriscv/linker.ld deleted file mode 100644 index 424ee50014f..00000000000 --- a/soc/riscv/litex-vexriscv/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2018 - 2019 Antmicro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/riscv/openisa_rv32m1/CMakeLists.txt b/soc/riscv/openisa_rv32m1/CMakeLists.txt index 37f4d9c7488..a7a722279c3 100644 --- a/soc/riscv/openisa_rv32m1/CMakeLists.txt +++ b/soc/riscv/openisa_rv32m1/CMakeLists.txt @@ -20,3 +20,5 @@ zephyr_sources( ) zephyr_linker_sources(ROM_START SORT_KEY 0x0vectors vector_table.ld) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/riscv/openisa_rv32m1/linker.ld b/soc/riscv/openisa_rv32m1/linker.ld index 7ade2d4e8dd..784ba791722 100644 --- a/soc/riscv/openisa_rv32m1/linker.ld +++ b/soc/riscv/openisa_rv32m1/linker.ld @@ -5,7 +5,7 @@ * * This file is based on: * - * - include/arch/arm/aarch32/cortex_m/scripts/linker.ld + * - include/arch/arm/cortex_m/scripts/linker.ld * - include/arch/riscv/common/linker.ld * - include/arch/riscv/pulpino/linker.ld * diff --git a/soc/riscv/riscv-ite/common/chip_chipregs.h b/soc/riscv/riscv-ite/common/chip_chipregs.h index 1fccd45853b..b1009e3eee5 100644 --- a/soc/riscv/riscv-ite/common/chip_chipregs.h +++ b/soc/riscv/riscv-ite/common/chip_chipregs.h @@ -1203,11 +1203,11 @@ enum chip_pll_mode { #define IT8XXX2_SMB_MSTFSTS1 ECREG(IT8XXX2_SMB_BASE + 0x0E) #define IT8XXX2_SMB_MSTFCTRL2 ECREG(IT8XXX2_SMB_BASE + 0x0F) #define IT8XXX2_SMB_MSTFSTS2 ECREG(IT8XXX2_SMB_BASE + 0x10) -#define IT8XXX2_SMB_CHSEF ECREG(IT8XXX2_SMB_BASE + 0x11) +#define IT8XXX2_SMB_SMB45CHS ECREG(IT8XXX2_SMB_BASE + 0x11) #define IT8XXX2_SMB_I2CW2RF ECREG(IT8XXX2_SMB_BASE + 0x12) #define IT8XXX2_SMB_IWRFISTA ECREG(IT8XXX2_SMB_BASE + 0x13) -#define IT8XXX2_SMB_CHSAB ECREG(IT8XXX2_SMB_BASE + 0x20) -#define IT8XXX2_SMB_CHSCD ECREG(IT8XXX2_SMB_BASE + 0x21) +#define IT8XXX2_SMB_SMB01CHS ECREG(IT8XXX2_SMB_BASE + 0x20) +#define IT8XXX2_SMB_SMB23CHS ECREG(IT8XXX2_SMB_BASE + 0x21) #define IT8XXX2_SMB_SFFCTL ECREG(IT8XXX2_SMB_BASE + 0x55) #define IT8XXX2_SMB_HOSTA(base) ECREG(base + 0x00) #define IT8XXX2_SMB_HOCTL(base) ECREG(base + 0x01) @@ -1223,7 +1223,7 @@ enum chip_pll_mode { #define IT8XXX2_SMB_SLVISEL ECREG(IT8XXX2_SMB_BASE + 0x08) #define IT8XXX2_SMB_SMB01CHS ECREG(IT8XXX2_SMB_BASE + 0x09) #define IT8XXX2_SMB_SMB23CHS ECREG(IT8XXX2_SMB_BASE + 0x0A) -#define IT8XXX2_SMB_SMB4CHS ECREG(IT8XXX2_SMB_BASE + 0x0B) +#define IT8XXX2_SMB_SMB45CHS ECREG(IT8XXX2_SMB_BASE + 0x0B) #define IT8XXX2_SMB_SCLKTS_BRGS ECREG(IT8XXX2_SMB_BASE + 0x80) #define IT8XXX2_SMB_SCLKTS_BRGM ECREG(IT8XXX2_SMB_BASE + 0x81) #define IT8XXX2_SMB_CHSBRG ECREG(IT8XXX2_SMB_BASE + 0x82) @@ -1321,6 +1321,8 @@ enum chip_pll_mode { /* 0x55: Slave A FIFO Control */ #define IT8XXX2_SMB_HSAPE BIT(1) /* 0x03: Status Register */ +#define IT8XXX2_I2C_BYTE_DONE BIT(7) +#define IT8XXX2_I2C_RW BIT(2) #define IT8XXX2_I2C_INT_PEND BIT(1) /* 0x04: Data Hold Time */ #define IT8XXX2_I2C_SOFT_RST BIT(7) @@ -1347,6 +1349,9 @@ enum chip_pll_mode { /* 0x13: Nack Status */ #define IT8XXX2_I2C_NST_CNS BIT(7) #define IT8XXX2_I2C_NST_ID_NACK BIT(3) +/* 0x18: Timeout and Arbiter Status */ +#define IT8XXX2_I2C_SCL_TIMEOUT_EN BIT(7) +#define IT8XXX2_I2C_SDA_TIMEOUT_EN BIT(6) /* 0x19: Error Status */ #define IT8XXX2_I2C_ERR_ST_DEV1_EIRQ BIT(0) /* 0x1B: Finish Status */ diff --git a/soc/riscv/riscv-ite/it8xxx2/CMakeLists.txt b/soc/riscv/riscv-ite/it8xxx2/CMakeLists.txt index b7eff43b096..df4d9021745 100644 --- a/soc/riscv/riscv-ite/it8xxx2/CMakeLists.txt +++ b/soc/riscv/riscv-ite/it8xxx2/CMakeLists.txt @@ -3,3 +3,7 @@ zephyr_sources( ) zephyr_library_sources_ifndef(CONFIG_RISCV_ISA_EXT_M __arithmetic.S) zephyr_sources_ifdef(CONFIG_SOC_IT8XXX2_USE_ILM ilm.c) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld + CACHE INTERNAL "SoC Linker script ${SOC_NAME}" +) diff --git a/soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.it82002aw b/soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.it82002aw new file mode 100644 index 00000000000..1edba5f674e --- /dev/null +++ b/soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.it82002aw @@ -0,0 +1,12 @@ +# Copyright (c) 2023 ITE Corporation. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_IT82002_AW + +config SOC + default "it82002aw" + +config SOC_IT8XXX2_GPIO_GROUP_K_L_DEFAULT_PULL_DOWN + default y + +endif diff --git a/soc/riscv/riscv-ite/it8xxx2/Kconfig.soc b/soc/riscv/riscv-ite/it8xxx2/Kconfig.soc index c33fe0f376f..38525449f89 100644 --- a/soc/riscv/riscv-ite/it8xxx2/Kconfig.soc +++ b/soc/riscv/riscv-ite/it8xxx2/Kconfig.soc @@ -66,6 +66,10 @@ config SOC_IT82302_AX bool "IT82302 AX version" select SOC_IT8XXX2_REG_SET_V2 +config SOC_IT82002_AW + bool "IT82002 AW version" + select SOC_IT8XXX2_REG_SET_V2 + endchoice config SOC_IT8XXX2_PLL_FLASH_48M diff --git a/soc/riscv/riscv-ite/it8xxx2/linker.ld b/soc/riscv/riscv-ite/it8xxx2/linker.ld index e285147f690..5c13ee2ecce 100644 --- a/soc/riscv/riscv-ite/it8xxx2/linker.ld +++ b/soc/riscv/riscv-ite/it8xxx2/linker.ld @@ -69,6 +69,8 @@ #define SHA256_BLOCK_SIZE 0x200 #endif +#include + MEMORY { #ifdef CONFIG_XIP @@ -76,6 +78,10 @@ MEMORY #endif RAM (rwx) : ORIGIN = RAM_BASE, LENGTH = RAM_SIZE +#if defined(CONFIG_LINKER_DEVNULL_MEMORY) + DEVNULL_ROM (rx) : ORIGIN = DEVNULL_ADDR, LENGTH = DEVNULL_SIZE +#endif + LINKER_DT_REGIONS() /* Used by and documented in include/linker/intlist.ld */ diff --git a/soc/riscv/riscv-privileged/Kconfig b/soc/riscv/riscv-privileged/Kconfig index f94eabd96a7..abbeeac242b 100644 --- a/soc/riscv/riscv-privileged/Kconfig +++ b/soc/riscv/riscv-privileged/Kconfig @@ -10,6 +10,7 @@ config SOC_FAMILY_RISCV_PRIVILEGE config SOC_FAMILY_RISCV_PRIVILEGED bool + select ARCH_HAS_RAMFUNC_SUPPORT if XIP config SOC_FAMILY string diff --git a/soc/riscv/riscv-privileged/andes_v5/CMakeLists.txt b/soc/riscv/riscv-privileged/andes_v5/CMakeLists.txt index 3de7b8c8841..21268312347 100644 --- a/soc/riscv/riscv-privileged/andes_v5/CMakeLists.txt +++ b/soc/riscv/riscv-privileged/andes_v5/CMakeLists.txt @@ -23,3 +23,7 @@ if(CONFIG_SOC_ANDES_V5_EXECIT) zephyr_cc_option(-mexecit) zephyr_ld_options(-Wl,--mexecit) endif() + +if(CONFIG_SOC_RISCV_ANDES_AE350) + set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/ae350/linker.ld CACHE INTERNAL "") +endif() diff --git a/soc/riscv/riscv-privileged/andes_v5/linker.ld b/soc/riscv/riscv-privileged/andes_v5/linker.ld deleted file mode 100644 index 5f92edc75a9..00000000000 --- a/soc/riscv/riscv-privileged/andes_v5/linker.ld +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2021 Andes Technology Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * linker script for andes_v5 SoC Series - */ - - -#if defined(CONFIG_SOC_RISCV_ANDES_AE350) -# include -#endif diff --git a/soc/riscv/riscv-privileged/common/soc_common_irq.c b/soc/riscv/riscv-privileged/common/soc_common_irq.c index c407bc8e20c..24aee37bdaf 100644 --- a/soc/riscv/riscv-privileged/common/soc_common_irq.c +++ b/soc/riscv/riscv-privileged/common/soc_common_irq.c @@ -10,6 +10,7 @@ privileged architecture specification */ #include +#include #include #include @@ -46,7 +47,6 @@ void arch_irq_enable(unsigned int irq) unsigned int level = irq_get_level(irq); if (level == 2) { - irq = irq_from_level_2(irq); riscv_plic_irq_enable(irq); return; } @@ -67,7 +67,6 @@ void arch_irq_disable(unsigned int irq) unsigned int level = irq_get_level(irq); if (level == 2) { - irq = irq_from_level_2(irq); riscv_plic_irq_disable(irq); return; } @@ -88,7 +87,6 @@ int arch_irq_is_enabled(unsigned int irq) unsigned int level = irq_get_level(irq); if (level == 2) { - irq = irq_from_level_2(irq); return riscv_plic_irq_is_enabled(irq); } #endif @@ -104,7 +102,6 @@ void z_riscv_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flag unsigned int level = irq_get_level(irq); if (level == 2) { - irq = irq_from_level_2(irq); riscv_plic_set_priority(irq, prio); } } diff --git a/soc/riscv/riscv-privileged/efinix-sapphire/CMakeLists.txt b/soc/riscv/riscv-privileged/efinix-sapphire/CMakeLists.txt index 9fc80635937..9edb7c3afe5 100644 --- a/soc/riscv/riscv-privileged/efinix-sapphire/CMakeLists.txt +++ b/soc/riscv/riscv-privileged/efinix-sapphire/CMakeLists.txt @@ -2,3 +2,5 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_include_directories(.) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld CACHE INTERNAL "") diff --git a/soc/riscv/riscv-privileged/efinix-sapphire/linker.ld b/soc/riscv/riscv-privileged/efinix-sapphire/linker.ld deleted file mode 100644 index 4cfd67a53f5..00000000000 --- a/soc/riscv/riscv-privileged/efinix-sapphire/linker.ld +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -#include diff --git a/soc/riscv/riscv-privileged/gd32vf103/CMakeLists.txt b/soc/riscv/riscv-privileged/gd32vf103/CMakeLists.txt index a3cabd57ab1..be61e4a64df 100644 --- a/soc/riscv/riscv-privileged/gd32vf103/CMakeLists.txt +++ b/soc/riscv/riscv-privileged/gd32vf103/CMakeLists.txt @@ -3,3 +3,5 @@ zephyr_sources(entry.S) zephyr_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld CACHE INTERNAL "") diff --git a/soc/riscv/riscv-privileged/gd32vf103/linker.ld b/soc/riscv/riscv-privileged/gd32vf103/linker.ld deleted file mode 100644 index 849c94ebe96..00000000000 --- a/soc/riscv/riscv-privileged/gd32vf103/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2021 Tokita, Hiroshi - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/riscv/riscv-privileged/miv/CMakeLists.txt b/soc/riscv/riscv-privileged/miv/CMakeLists.txt index 55fc3999fd7..316f08474ba 100644 --- a/soc/riscv/riscv-privileged/miv/CMakeLists.txt +++ b/soc/riscv/riscv-privileged/miv/CMakeLists.txt @@ -1,3 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_sources() + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld CACHE INTERNAL "") diff --git a/soc/riscv/riscv-privileged/miv/linker.ld b/soc/riscv/riscv-privileged/miv/linker.ld deleted file mode 100644 index 0d220a25c73..00000000000 --- a/soc/riscv/riscv-privileged/miv/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2018 Antmicro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/riscv/riscv-privileged/mpfs/CMakeLists.txt b/soc/riscv/riscv-privileged/mpfs/CMakeLists.txt index 55fc3999fd7..316f08474ba 100644 --- a/soc/riscv/riscv-privileged/mpfs/CMakeLists.txt +++ b/soc/riscv/riscv-privileged/mpfs/CMakeLists.txt @@ -1,3 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_sources() + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld CACHE INTERNAL "") diff --git a/soc/riscv/riscv-privileged/mpfs/linker.ld b/soc/riscv/riscv-privileged/mpfs/linker.ld deleted file mode 100644 index 4e3ca81bfbb..00000000000 --- a/soc/riscv/riscv-privileged/mpfs/linker.ld +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2021-2022 Microchip Technology Inc - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include diff --git a/soc/riscv/riscv-privileged/neorv32/CMakeLists.txt b/soc/riscv/riscv-privileged/neorv32/CMakeLists.txt index 7f7c334fedd..42731316d84 100644 --- a/soc/riscv/riscv-privileged/neorv32/CMakeLists.txt +++ b/soc/riscv/riscv-privileged/neorv32/CMakeLists.txt @@ -6,3 +6,5 @@ zephyr_sources( soc_irq.S soc.c ) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/riscv/riscv-privileged/niosv/CMakeLists.txt b/soc/riscv/riscv-privileged/niosv/CMakeLists.txt index c740850bc77..e7a753a2db3 100644 --- a/soc/riscv/riscv-privileged/niosv/CMakeLists.txt +++ b/soc/riscv/riscv-privileged/niosv/CMakeLists.txt @@ -2,3 +2,5 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_include_directories(.) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/riscv/riscv-privileged/opentitan/CMakeLists.txt b/soc/riscv/riscv-privileged/opentitan/CMakeLists.txt index 05e59ca7071..3502022cbed 100644 --- a/soc/riscv/riscv-privileged/opentitan/CMakeLists.txt +++ b/soc/riscv/riscv-privileged/opentitan/CMakeLists.txt @@ -3,3 +3,5 @@ zephyr_sources(soc.c rom_header.S) zephyr_linker_sources(ROM_START SORT_KEY 000romheader rom_header.ld) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld CACHE INTERNAL "") diff --git a/soc/riscv/riscv-privileged/opentitan/linker.ld b/soc/riscv/riscv-privileged/opentitan/linker.ld deleted file mode 100644 index 8eeb9c50af3..00000000000 --- a/soc/riscv/riscv-privileged/opentitan/linker.ld +++ /dev/null @@ -1,3 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 */ - -#include diff --git a/soc/riscv/riscv-privileged/sifive-freedom/CMakeLists.txt b/soc/riscv/riscv-privileged/sifive-freedom/CMakeLists.txt index f5f6c539efd..ff4cc56d739 100644 --- a/soc/riscv/riscv-privileged/sifive-freedom/CMakeLists.txt +++ b/soc/riscv/riscv-privileged/sifive-freedom/CMakeLists.txt @@ -4,3 +4,5 @@ zephyr_sources() zephyr_sources_ifdef(CONFIG_SOC_RISCV_SIFIVE_FREEDOM fe310_clock.c) zephyr_sources_ifdef(CONFIG_SOC_RISCV_SIFIVE_FU540 fu540_clock.c) zephyr_sources_ifdef(CONFIG_SOC_RISCV_SIFIVE_FU740 fu740_clock.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld CACHE INTERNAL "") diff --git a/soc/riscv/riscv-privileged/sifive-freedom/linker.ld b/soc/riscv/riscv-privileged/sifive-freedom/linker.ld deleted file mode 100644 index 96720f18a2e..00000000000 --- a/soc/riscv/riscv-privileged/sifive-freedom/linker.ld +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright (c) 2017 Jean-Paul Etienne - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @brief Linker script for the SiFive Freedom processor - */ - -#include diff --git a/soc/riscv/riscv-privileged/starfive_jh71xx/CMakeLists.txt b/soc/riscv/riscv-privileged/starfive_jh71xx/CMakeLists.txt index f75aec6b311..f79d0b3255d 100644 --- a/soc/riscv/riscv-privileged/starfive_jh71xx/CMakeLists.txt +++ b/soc/riscv/riscv-privileged/starfive_jh71xx/CMakeLists.txt @@ -1,3 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_include_directories(.) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld CACHE INTERNAL "") diff --git a/soc/riscv/riscv-privileged/starfive_jh71xx/linker.ld b/soc/riscv/riscv-privileged/starfive_jh71xx/linker.ld deleted file mode 100644 index 4e63d62344d..00000000000 --- a/soc/riscv/riscv-privileged/starfive_jh71xx/linker.ld +++ /dev/null @@ -1,6 +0,0 @@ -/* - * Copyright (c) 2020 Cobham Gaisler AB - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include diff --git a/soc/riscv/riscv-privileged/telink_b91/CMakeLists.txt b/soc/riscv/riscv-privileged/telink_b91/CMakeLists.txt index c91adf6a993..8c489ac6dd7 100644 --- a/soc/riscv/riscv-privileged/telink_b91/CMakeLists.txt +++ b/soc/riscv/riscv-privileged/telink_b91/CMakeLists.txt @@ -14,3 +14,5 @@ zephyr_ld_options(-fuse-ld=bfd) zephyr_compile_options_ifdef(CONFIG_TELINK_B91_HWDSP -mext-dsp) zephyr_compile_options_ifndef(CONFIG_RISCV_GP -mno-relax) zephyr_linker_sources(ROM_START SORT_KEY 0x0 init.ld) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/riscv/riscv-privileged/telink_b91/Kconfig.defconfig.series b/soc/riscv/riscv-privileged/telink_b91/Kconfig.defconfig.series index 43eb3a03927..986b6240750 100644 --- a/soc/riscv/riscv-privileged/telink_b91/Kconfig.defconfig.series +++ b/soc/riscv/riscv-privileged/telink_b91/Kconfig.defconfig.series @@ -50,6 +50,9 @@ config TEST_EXTRA_STACK_SIZE int default 1024 +config 2ND_LVL_INTR_00_OFFSET + default 11 + config HAS_FLASH_LOAD_OFFSET default y if BOOTLOADER_MCUBOOT diff --git a/soc/riscv/riscv-privileged/virt/CMakeLists.txt b/soc/riscv/riscv-privileged/virt/CMakeLists.txt index 9486f255912..6a1826b29f9 100644 --- a/soc/riscv/riscv-privileged/virt/CMakeLists.txt +++ b/soc/riscv/riscv-privileged/virt/CMakeLists.txt @@ -1,3 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld CACHE INTERNAL "") diff --git a/soc/riscv/riscv-privileged/virt/Kconfig.defconfig.series b/soc/riscv/riscv-privileged/virt/Kconfig.defconfig.series index 77481104e3b..231d4519d67 100644 --- a/soc/riscv/riscv-privileged/virt/Kconfig.defconfig.series +++ b/soc/riscv/riscv-privileged/virt/Kconfig.defconfig.series @@ -31,7 +31,7 @@ config MAX_IRQ_PER_AGGREGATOR default 52 config NUM_IRQS - default 64 + default 1035 config PMP_SLOTS default 16 diff --git a/soc/riscv/riscv-privileged/virt/linker.ld b/soc/riscv/riscv-privileged/virt/linker.ld deleted file mode 100644 index 4e63d62344d..00000000000 --- a/soc/riscv/riscv-privileged/virt/linker.ld +++ /dev/null @@ -1,6 +0,0 @@ -/* - * Copyright (c) 2020 Cobham Gaisler AB - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include diff --git a/soc/sparc/Kconfig b/soc/sparc/Kconfig index 0d975d46c32..de68a730048 100644 --- a/soc/sparc/Kconfig +++ b/soc/sparc/Kconfig @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 config SPARC_CASA - default y + default y if SPARC config SOC_SPARC_LEON bool diff --git a/soc/sparc/gr716a/CMakeLists.txt b/soc/sparc/gr716a/CMakeLists.txt index 746570b05c7..888e386817e 100644 --- a/soc/sparc/gr716a/CMakeLists.txt +++ b/soc/sparc/gr716a/CMakeLists.txt @@ -1,3 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_sources(../leon3/idle.c) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/sparc/leon3/CMakeLists.txt b/soc/sparc/leon3/CMakeLists.txt index 53b77ee8a37..722526c00cf 100644 --- a/soc/sparc/leon3/CMakeLists.txt +++ b/soc/sparc/leon3/CMakeLists.txt @@ -1,3 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_sources(idle.c) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/x86/alder_lake/CMakeLists.txt b/soc/x86/alder_lake/CMakeLists.txt index 67d93138e14..47325b7a809 100644 --- a/soc/x86/alder_lake/CMakeLists.txt +++ b/soc/x86/alder_lake/CMakeLists.txt @@ -6,3 +6,5 @@ zephyr_library_include_directories(${ZEPHYR_BASE}/drivers) zephyr_cc_option(-march=goldmont) zephyr_library_sources(cpu.c) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/x86/alder_lake/soc.h b/soc/x86/alder_lake/soc.h index dda2272ea61..e1c6a04e834 100644 --- a/soc/x86/alder_lake/soc.h +++ b/soc/x86/alder_lake/soc.h @@ -20,7 +20,7 @@ #ifndef _ASMLANGUAGE #include -#include +#include #endif #ifdef CONFIG_GPIO_INTEL diff --git a/soc/x86/apollo_lake/CMakeLists.txt b/soc/x86/apollo_lake/CMakeLists.txt index 67d93138e14..47325b7a809 100644 --- a/soc/x86/apollo_lake/CMakeLists.txt +++ b/soc/x86/apollo_lake/CMakeLists.txt @@ -6,3 +6,5 @@ zephyr_library_include_directories(${ZEPHYR_BASE}/drivers) zephyr_cc_option(-march=goldmont) zephyr_library_sources(cpu.c) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/x86/apollo_lake/soc.h b/soc/x86/apollo_lake/soc.h index 47e719dac14..8d4dc0f5bf8 100644 --- a/soc/x86/apollo_lake/soc.h +++ b/soc/x86/apollo_lake/soc.h @@ -20,7 +20,7 @@ #ifndef _ASMLANGUAGE #include -#include +#include #endif #ifdef CONFIG_GPIO_INTEL diff --git a/soc/x86/atom/CMakeLists.txt b/soc/x86/atom/CMakeLists.txt index 9881313609a..66d55c6ba96 100644 --- a/soc/x86/atom/CMakeLists.txt +++ b/soc/x86/atom/CMakeLists.txt @@ -1 +1,3 @@ # SPDX-License-Identifier: Apache-2.0 + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/x86/atom/Kconfig.defconfig b/soc/x86/atom/Kconfig.defconfig index 2658fa7220b..743b43465f4 100644 --- a/soc/x86/atom/Kconfig.defconfig +++ b/soc/x86/atom/Kconfig.defconfig @@ -11,7 +11,4 @@ config SOC config SYS_CLOCK_HW_CYCLES_PER_SEC default 25000000 if HPET_TIMER -config UART_NS16550_ACCESS_IOPORT - default y if UART_NS16550 - endif diff --git a/soc/x86/atom/soc.h b/soc/x86/atom/soc.h index 9af32283e53..199820fa7bd 100644 --- a/soc/x86/atom/soc.h +++ b/soc/x86/atom/soc.h @@ -19,7 +19,7 @@ #ifndef _ASMLANGUAGE #include -#include +#include #endif /* PCI definitions */ diff --git a/soc/x86/elkhart_lake/CMakeLists.txt b/soc/x86/elkhart_lake/CMakeLists.txt index 67d93138e14..47325b7a809 100644 --- a/soc/x86/elkhart_lake/CMakeLists.txt +++ b/soc/x86/elkhart_lake/CMakeLists.txt @@ -6,3 +6,5 @@ zephyr_library_include_directories(${ZEPHYR_BASE}/drivers) zephyr_cc_option(-march=goldmont) zephyr_library_sources(cpu.c) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/x86/elkhart_lake/soc.h b/soc/x86/elkhart_lake/soc.h index 1e47a01c38d..0b9c96ea5ad 100644 --- a/soc/x86/elkhart_lake/soc.h +++ b/soc/x86/elkhart_lake/soc.h @@ -20,7 +20,7 @@ #ifndef _ASMLANGUAGE #include -#include +#include #endif #ifdef CONFIG_GPIO_INTEL diff --git a/soc/x86/ia32/CMakeLists.txt b/soc/x86/ia32/CMakeLists.txt index 9881313609a..66d55c6ba96 100644 --- a/soc/x86/ia32/CMakeLists.txt +++ b/soc/x86/ia32/CMakeLists.txt @@ -1 +1,3 @@ # SPDX-License-Identifier: Apache-2.0 + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/x86/ia32/Kconfig.defconfig b/soc/x86/ia32/Kconfig.defconfig index cd6f6f20790..87600183a20 100644 --- a/soc/x86/ia32/Kconfig.defconfig +++ b/soc/x86/ia32/Kconfig.defconfig @@ -11,7 +11,4 @@ config SOC config SYS_CLOCK_HW_CYCLES_PER_SEC default 25000000 if HPET_TIMER -config UART_NS16550_ACCESS_IOPORT - default y if UART_NS16550 - endif diff --git a/soc/x86/ia32/soc.h b/soc/x86/ia32/soc.h index 0fedc9a4d0d..51da1d1cdf4 100644 --- a/soc/x86/ia32/soc.h +++ b/soc/x86/ia32/soc.h @@ -19,7 +19,7 @@ #ifndef _ASMLANGUAGE #include -#include +#include #endif /* PCI definitions */ diff --git a/soc/x86/intel_ish/Kconfig b/soc/x86/intel_ish/Kconfig index 590c26a55fb..b3865915a2a 100644 --- a/soc/x86/intel_ish/Kconfig +++ b/soc/x86/intel_ish/Kconfig @@ -13,3 +13,4 @@ config SOC_FAMILY_INTEL_ISH select CPU_HAS_FPU select INTEL_HAL select HAS_PM + select HAS_COVERAGE_SUPPORT diff --git a/soc/x86/intel_ish/intel_ish5/CMakeLists.txt b/soc/x86/intel_ish/intel_ish5/CMakeLists.txt index 6d4f911744a..3c253ac2648 100644 --- a/soc/x86/intel_ish/intel_ish5/CMakeLists.txt +++ b/soc/x86/intel_ish/intel_ish5/CMakeLists.txt @@ -8,4 +8,6 @@ zephyr_cc_option(-march=pentium -mtune=i486) zephyr_sources(soc.c) add_subdirectory_ifdef(CONFIG_PM pm) +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") + include(../utils/build_ish_firmware.cmake) diff --git a/soc/x86/intel_ish/intel_ish5/pm/Kconfig.pm b/soc/x86/intel_ish/intel_ish5/pm/Kconfig.pm index d4decc82f7d..d50e435c13e 100644 --- a/soc/x86/intel_ish/intel_ish5/pm/Kconfig.pm +++ b/soc/x86/intel_ish/intel_ish5/pm/Kconfig.pm @@ -18,4 +18,7 @@ config GDT_RESERVED_NUM_ENTRIES config REBOOT default y +config PM_NEED_ALL_DEVICES_IDLE + default y + endif diff --git a/soc/x86/intel_ish/intel_ish5/pm/power.c b/soc/x86/intel_ish/intel_ish5/pm/power.c index a2ea8f65ce5..3ad15eee36b 100644 --- a/soc/x86/intel_ish/intel_ish5/pm/power.c +++ b/soc/x86/intel_ish/intel_ish5/pm/power.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include diff --git a/soc/x86/intel_ish/intel_ish5/soc.h b/soc/x86/intel_ish/intel_ish5/soc.h index 69528a74b68..e474a33b3f8 100644 --- a/soc/x86/intel_ish/intel_ish5/soc.h +++ b/soc/x86/intel_ish/intel_ish5/soc.h @@ -11,7 +11,7 @@ #ifndef _ASMLANGUAGE #include -#include +#include #ifdef CONFIG_HPET_TIMER #include "sedi_driver_hpet.h" diff --git a/soc/x86/lakemont/CMakeLists.txt b/soc/x86/lakemont/CMakeLists.txt index 6f44c89f7ad..4527b084519 100644 --- a/soc/x86/lakemont/CMakeLists.txt +++ b/soc/x86/lakemont/CMakeLists.txt @@ -3,3 +3,5 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_cc_option(-march=pentium) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/x86/raptor_lake/CMakeLists.txt b/soc/x86/raptor_lake/CMakeLists.txt index 3be2e750b61..06c46752f81 100644 --- a/soc/x86/raptor_lake/CMakeLists.txt +++ b/soc/x86/raptor_lake/CMakeLists.txt @@ -1,3 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_cc_option(-march=goldmont) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/x86/raptor_lake/Kconfig.defconfig b/soc/x86/raptor_lake/Kconfig.defconfig index 70abc51438b..f9b14da95d0 100644 --- a/soc/x86/raptor_lake/Kconfig.defconfig +++ b/soc/x86/raptor_lake/Kconfig.defconfig @@ -15,7 +15,4 @@ config X86_DYNAMIC_IRQ_STUBS default 16 depends on DYNAMIC_INTERRUPTS -config UART_NS16550_SIMULT_ACCESS - default y if UART_NS16550 - endif # SOC_RAPTOR_LAKE diff --git a/soc/x86/raptor_lake/soc.h b/soc/x86/raptor_lake/soc.h index 6de3f7fa9c0..bb4adb62fa0 100644 --- a/soc/x86/raptor_lake/soc.h +++ b/soc/x86/raptor_lake/soc.h @@ -18,7 +18,7 @@ #ifndef _ASMLANGUAGE #include -#include +#include #endif #ifdef CONFIG_GPIO_INTEL diff --git a/soc/xtensa/dc233c/CMakeLists.txt b/soc/xtensa/dc233c/CMakeLists.txt index 52a6e84baa9..8012661a437 100644 --- a/soc/xtensa/dc233c/CMakeLists.txt +++ b/soc/xtensa/dc233c/CMakeLists.txt @@ -1,3 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_include_directories(include) zephyr_library_sources_ifdef(CONFIG_XTENSA_MMU mmu.c) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/include/xtensa-dc233c.ld CACHE INTERNAL "") diff --git a/soc/xtensa/dc233c/Kconfig.defconfig b/soc/xtensa/dc233c/Kconfig.defconfig index c78c8cd7337..dc5be860b4a 100644 --- a/soc/xtensa/dc233c/Kconfig.defconfig +++ b/soc/xtensa/dc233c/Kconfig.defconfig @@ -22,7 +22,8 @@ config XTENSA_MMU_NUM_L2_TABLES # via TLB way 4 (which covers 1MB). config SRAM_OFFSET hex - default 0x100000 + default 0x100000 if XTENSA_MMU + default 0x2400 config KERNEL_VM_OFFSET hex diff --git a/soc/xtensa/dc233c/Kconfig.soc b/soc/xtensa/dc233c/Kconfig.soc index fee0730da95..89b814da4d2 100644 --- a/soc/xtensa/dc233c/Kconfig.soc +++ b/soc/xtensa/dc233c/Kconfig.soc @@ -6,6 +6,6 @@ config SOC_XTENSA_DC233C bool "Xtensa dc233c core" select XTENSA select XTENSA_HAL + select ARCH_HAS_THREAD_LOCAL_STORAGE select CPU_HAS_MMU - imply XTENSA_MMU select ARCH_HAS_RESERVED_PAGE_FRAMES if XTENSA_MMU diff --git a/soc/xtensa/dc233c/include/backtrace_helpers.h b/soc/xtensa/dc233c/include/backtrace_helpers.h new file mode 100644 index 00000000000..8793ebcd7a1 --- /dev/null +++ b/soc/xtensa/dc233c/include/backtrace_helpers.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2022, 2023 Intel Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + + +#ifndef ZEPHYR_SOC_XTENSA_DC233C_BACKTRACE_HELPERS_H_ +#define ZEPHYR_SOC_XTENSA_DC233C_BACKTRACE_HELPERS_H_ + +#include + +#include + +static inline bool xtensa_dc233c_ptr_executable(const void *p) +{ + bool in_text = ((p >= (void *)__text_region_start) && + (p <= (void *)__text_region_end)); + bool in_vecbase = ((p >= (void *)XCHAL_VECBASE_RESET_VADDR) && + (p < (void *)CONFIG_SRAM_OFFSET)); + + return (in_text || in_vecbase); +} + +static inline bool xtensa_dc233c_stack_ptr_is_sane(uint32_t sp) +{ + return ((char *)sp >= __text_region_start); +} + +#endif /* ZEPHYR_SOC_XTENSA_DC233C_BACKTRACE_HELPERS_H_ */ diff --git a/soc/xtensa/dc233c/include/xtensa-dc233c.ld b/soc/xtensa/dc233c/include/xtensa-dc233c.ld index 07d40aef49e..b165016fa6a 100644 --- a/soc/xtensa/dc233c/include/xtensa-dc233c.ld +++ b/soc/xtensa/dc233c/include/xtensa-dc233c.ld @@ -322,6 +322,12 @@ SECTIONS *(.text.arch_is_in_isr) + /* To support backtracing */ + *libarch__xtensa__core.a:xtensa_backtrace.c.obj(.literal.*) + *libarch__xtensa__core.a:xtensa_backtrace.c.obj(.text.*) + *libarch__xtensa__core.a:debug_helpers_asm.S.obj(.iram1.literal) + *libarch__xtensa__core.a:debug_helpers_asm.S.obj(.iram1) + *libkernel.a:fatal.c.obj(.literal.*) *libkernel.a:fatal.c.obj(.text.*) @@ -340,6 +346,10 @@ SECTIONS } >vec_helpers :vec_helpers_phdr #endif /* CONFIG_XTENSA_MMU */ +#ifdef CONFIG_CODE_DATA_RELOCATION +#include +#endif + .ResetVector.text : ALIGN(4) { __rom_region_start = ABSOLUTE(.); @@ -357,6 +367,7 @@ SECTIONS *(.entry.text) *(.init.literal) *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) + *(.iram1.literal .iram1) KEEP(*(.init)) *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) *(.fini.literal) @@ -397,6 +408,8 @@ SECTIONS #include +#include + #include #include diff --git a/soc/xtensa/dc233c/linker.ld b/soc/xtensa/dc233c/linker.ld deleted file mode 100644 index 1f8e9eadd1a..00000000000 --- a/soc/xtensa/dc233c/linker.ld +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2016 Cadence Design Systems, Inc. - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * Linker script for the Xtensa platform. - */ -#include diff --git a/soc/xtensa/espressif_esp32/esp32/CMakeLists.txt b/soc/xtensa/espressif_esp32/esp32/CMakeLists.txt index 6468d1545dc..f850e56a9b1 100644 --- a/soc/xtensa/espressif_esp32/esp32/CMakeLists.txt +++ b/soc/xtensa/espressif_esp32/esp32/CMakeLists.txt @@ -95,3 +95,9 @@ endif() board_finalize_runner_args(esp32 "--esp-boot-address=${boot_off}") board_finalize_runner_args(esp32 "--esp-app-address=${img_0_off}") + +if(CONFIG_MCUBOOT) + set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/mcuboot.ld CACHE INTERNAL "") +else() + set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/default.ld CACHE INTERNAL "") +endif() diff --git a/soc/xtensa/espressif_esp32/esp32/default.ld b/soc/xtensa/espressif_esp32/esp32/default.ld index b04399a24ac..20dc3c28ef5 100644 --- a/soc/xtensa/espressif_esp32/esp32/default.ld +++ b/soc/xtensa/espressif_esp32/esp32/default.ld @@ -46,6 +46,11 @@ #endif #define IRAM_SEG_LEN 0x20000 +/* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA. + * Executing directly from LMA is not possible. */ +#undef GROUP_ROM_LINK_IN +#define GROUP_ROM_LINK_IN(vregion, lregion) > RODATA_REGION AT > lregion + MEMORY { mcuboot_hdr (RX): org = 0x0, len = 0x20 @@ -209,11 +214,6 @@ SECTIONS . = ALIGN(4); } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) - /* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA. - * Executing directly from LMA is not possible. */ - #pragma push_macro("GROUP_ROM_LINK_IN") - #undef GROUP_ROM_LINK_IN - #define GROUP_ROM_LINK_IN(vregion, lregion) > RODATA_REGION AT > lregion #include #include #include @@ -221,7 +221,7 @@ SECTIONS #include #include #include - #pragma pop_macro("GROUP_ROM_LINK_IN") + #include /* Create an explicit section at the end of all the data that shall be mapped into drom. * This is used to calculate the size of the _image_drom_size variable */ @@ -235,8 +235,6 @@ SECTIONS _image_dram_size = LOADADDR(.dram0.end) + SIZEOF(.dram0.end) - _image_dram_start; _image_dram_vaddr = ADDR(.dram0.data); - #include - .dram0.data : { __data_start = ABSOLUTE(.); diff --git a/soc/xtensa/espressif_esp32/esp32/linker.ld b/soc/xtensa/espressif_esp32/esp32/linker.ld deleted file mode 100644 index 981d25bf18a..00000000000 --- a/soc/xtensa/espressif_esp32/esp32/linker.ld +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - */ - -#if defined(CONFIG_MCUBOOT) - /* Using mcuboot as ESP32 2nd stage bootloader */ - #include "mcuboot.ld" - -#else - /* Application default linker script */ - #include "default.ld" - -#endif /* CONFIG_MCUBOOT */ diff --git a/soc/xtensa/espressif_esp32/esp32/soc.c b/soc/xtensa/espressif_esp32/esp32/soc.c index 953c4797ce9..2abd0f6a88a 100644 --- a/soc/xtensa/espressif_esp32/esp32/soc.c +++ b/soc/xtensa/espressif_esp32/esp32/soc.c @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include diff --git a/soc/xtensa/espressif_esp32/esp32_net/CMakeLists.txt b/soc/xtensa/espressif_esp32/esp32_net/CMakeLists.txt index 9be4cbc549d..2997e2e9990 100644 --- a/soc/xtensa/espressif_esp32/esp32_net/CMakeLists.txt +++ b/soc/xtensa/espressif_esp32/esp32_net/CMakeLists.txt @@ -19,3 +19,5 @@ if(CONFIG_BUILD_OUTPUT_BIN) -o ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.c -a "esp32_net_fw_array") endif() + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/xtensa/espressif_esp32/esp32_net/linker.ld b/soc/xtensa/espressif_esp32/esp32_net/linker.ld index 6c1b69872b1..69a4c48ef78 100644 --- a/soc/xtensa/espressif_esp32/esp32_net/linker.ld +++ b/soc/xtensa/espressif_esp32/esp32_net/linker.ld @@ -26,6 +26,11 @@ #define ROMABLE_DATA_REGION dram0_1_seg #define dram0_0_seg dram0_1_seg +/* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA. + * Executing directly from LMA is not possible. */ +#undef GROUP_ROM_LINK_IN +#define GROUP_ROM_LINK_IN(vregion, lregion) > RODATA_REGION AT > lregion + MEMORY { iram0_0_seg(RX): org = 0x40080000 + 0x08000, len = 0x18000 @@ -200,11 +205,6 @@ SECTIONS . = ALIGN(4); } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_DATA_REGION) - /* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA. - * Executing directly from LMA is not possible. */ - #pragma push_macro("GROUP_ROM_LINK_IN") - #undef GROUP_ROM_LINK_IN - #define GROUP_ROM_LINK_IN(vregion, lregion) > RODATA_REGION AT > lregion #include #include #include @@ -212,7 +212,7 @@ SECTIONS #include #include #include - #pragma pop_macro("GROUP_ROM_LINK_IN") + #include /* Create an explicit section at the end of all the data that shall be mapped into drom. * This is used to calculate the size of the _image_drom_size variable */ @@ -226,8 +226,6 @@ SECTIONS _image_dram_size = LOADADDR(.dram0.end) + SIZEOF(.dram0.end) - _image_dram_start; _image_dram_vaddr = ADDR(.dram0.data); - #include - .dram0.data : { __data_start = ABSOLUTE(.); diff --git a/soc/xtensa/espressif_esp32/esp32_net/soc.c b/soc/xtensa/espressif_esp32/esp32_net/soc.c index bec52472e3e..ac53ccb7e74 100644 --- a/soc/xtensa/espressif_esp32/esp32_net/soc.c +++ b/soc/xtensa/espressif_esp32/esp32_net/soc.c @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include diff --git a/soc/xtensa/espressif_esp32/esp32s2/CMakeLists.txt b/soc/xtensa/espressif_esp32/esp32s2/CMakeLists.txt index 2b023ede856..b9f361d1d5c 100644 --- a/soc/xtensa/espressif_esp32/esp32s2/CMakeLists.txt +++ b/soc/xtensa/espressif_esp32/esp32s2/CMakeLists.txt @@ -93,3 +93,9 @@ endif() board_finalize_runner_args(esp32 "--esp-boot-address=${boot_off}") board_finalize_runner_args(esp32 "--esp-app-address=${img_0_off}") + +if(CONFIG_MCUBOOT) + set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/mcuboot.ld CACHE INTERNAL "") +else() + set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/default.ld CACHE INTERNAL "") +endif() diff --git a/soc/xtensa/espressif_esp32/esp32s2/default.ld b/soc/xtensa/espressif_esp32/esp32s2/default.ld index c6681215e5d..15f654d4b99 100644 --- a/soc/xtensa/espressif_esp32/esp32s2/default.ld +++ b/soc/xtensa/espressif_esp32/esp32s2/default.ld @@ -53,6 +53,11 @@ #define IROM_SEG_ALIGN 0x10000 #endif +/* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA. + * Executing directly from LMA is not possible. */ +#undef GROUP_ROM_LINK_IN +#define GROUP_ROM_LINK_IN(vregion, lregion) > RODATA_REGION AT > lregion + MEMORY { mcuboot_hdr (RX): org = 0x0, len = 0x20 @@ -130,6 +135,7 @@ SECTIONS */ SECTION_PROLOGUE(_RODATA_SECTION_NAME,,ALIGN(4)) { + _rodata_reserved_start = ABSOLUTE(.); __rodata_region_start = ABSOLUTE(.); . = ALIGN(4); @@ -177,27 +183,22 @@ SECTIONS *(.rodata_wlog) *(.rodata_wlog*) _thread_local_end = ABSOLUTE(.); - _rodata_reserved_end = ABSOLUTE(.); . = ALIGN(4); } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) - /* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA. - * Executing directly from LMA is not possible. */ - #pragma push_macro("GROUP_ROM_LINK_IN") - #undef GROUP_ROM_LINK_IN - #define GROUP_ROM_LINK_IN(vregion, lregion) > RODATA_REGION AT > lregion #include #include #include #include #include #include - #pragma pop_macro("GROUP_ROM_LINK_IN") + #include /* Create an explicit section at the end of all the data that shall be mapped into drom. * This is used to calculate the size of the _image_drom_size variable */ SECTION_PROLOGUE(_RODATA_SECTION_END,,ALIGN(0x10)) { + _rodata_reserved_end = ABSOLUTE(.); . = ALIGN(4); _image_rodata_end = ABSOLUTE(.); } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) @@ -364,8 +365,6 @@ SECTIONS . = ALIGN(8); } GROUP_LINK_IN(RAMABLE_REGION) -#include - .dram0.data : { . = ALIGN (8); diff --git a/soc/xtensa/espressif_esp32/esp32s2/linker.ld b/soc/xtensa/espressif_esp32/esp32s2/linker.ld deleted file mode 100644 index dc2d891834e..00000000000 --- a/soc/xtensa/espressif_esp32/esp32s2/linker.ld +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - */ - -#if defined(CONFIG_MCUBOOT) - /* Using mcuboot as ESP32S2 2nd stage bootloader */ - #include "mcuboot.ld" - -#else - /* Application default linker script */ - #include "default.ld" - -#endif /* CONFIG_MCUBOOT */ diff --git a/soc/xtensa/espressif_esp32/esp32s2/soc.c b/soc/xtensa/espressif_esp32/esp32s2/soc.c index 9fc9701db52..45edde47178 100644 --- a/soc/xtensa/espressif_esp32/esp32s2/soc.c +++ b/soc/xtensa/espressif_esp32/esp32s2/soc.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include "esp_private/system_internal.h" diff --git a/soc/xtensa/espressif_esp32/esp32s3/CMakeLists.txt b/soc/xtensa/espressif_esp32/esp32s3/CMakeLists.txt index 87d71798159..cb5291614bc 100644 --- a/soc/xtensa/espressif_esp32/esp32s3/CMakeLists.txt +++ b/soc/xtensa/espressif_esp32/esp32s3/CMakeLists.txt @@ -1,21 +1,18 @@ # SPDX-License-Identifier: Apache-2.0 -zephyr_sources( - soc.c - soc_cache.c - loader.c - ) +if (CONFIG_SOC_ESP32S3_APPCPU) + zephyr_sources(soc_appcpu.c) +else() + zephyr_sources( + soc.c + soc_cache.c + loader.c + esp32s3-mp.c + ) +endif() zephyr_library_sources_ifdef(CONFIG_NEWLIB_LIBC newlib_fix.c) -# get code-partition slot0 address -dt_nodelabel(dts_partition_path NODELABEL "slot0_partition") -dt_reg_addr(img_0_off PATH ${dts_partition_path}) - -# get code-partition boot address -dt_nodelabel(dts_partition_path NODELABEL "boot_partition") -dt_reg_addr(boot_off PATH ${dts_partition_path}) - # get flash size to use in esptool as string math(EXPR esptoolpy_flashsize "${CONFIG_FLASH_SIZE} / 0x100000") @@ -87,8 +84,39 @@ if(CONFIG_MCUBOOT OR CONFIG_BOOTLOADER_ESP_IDF) endif() -set_property(TARGET bintools PROPERTY disassembly_flag_inline_source) +## When building for APPCPU +if (CONFIG_SOC_ESP32S3_APPCPU) -board_finalize_runner_args(esp32 "--esp-boot-address=${boot_off}") + if(CONFIG_BUILD_OUTPUT_BIN) + set_property(GLOBAL APPEND PROPERTY extra_post_build_commands + COMMAND ${PYTHON_EXECUTABLE} ${ESP_IDF_PATH}/tools/esp_bin2c_array.py + ARGS -i ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.bin + -o ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.c + -a "esp32s3_appcpu_fw_array") + endif() -board_finalize_runner_args(esp32 "--esp-app-address=${img_0_off}") +else() + + set_property(TARGET bintools PROPERTY disassembly_flag_inline_source) + + # get code-partition slot0 address + dt_nodelabel(dts_partition_path NODELABEL "slot0_partition") + dt_reg_addr(img_0_off PATH ${dts_partition_path}) + + # get code-partition boot address + dt_nodelabel(dts_partition_path NODELABEL "boot_partition") + dt_reg_addr(boot_off PATH ${dts_partition_path}) + + board_finalize_runner_args(esp32 "--esp-boot-address=${boot_off}") + + board_finalize_runner_args(esp32 "--esp-app-address=${img_0_off}") + +endif() + +if(CONFIG_MCUBOOT) + set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/mcuboot.ld CACHE INTERNAL "") +elseif(CONFIG_SOC_ESP32S3_APPCPU) + set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/default_appcpu.ld CACHE INTERNAL "") +else() + set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/default.ld CACHE INTERNAL "") +endif() diff --git a/soc/xtensa/espressif_esp32/esp32s3/Kconfig.series b/soc/xtensa/espressif_esp32/esp32s3/Kconfig.series index 1265375c12a..6f5fcf88c17 100644 --- a/soc/xtensa/espressif_esp32/esp32s3/Kconfig.series +++ b/soc/xtensa/espressif_esp32/esp32s3/Kconfig.series @@ -12,5 +12,17 @@ config SOC_SERIES_ESP32S3 select XIP if !MCUBOOT select HAS_ESPRESSIF_HAL select CPU_HAS_FPU + +config SOC_ESP32S3_PROCPU + bool "Application runs in ESP32S3 PROCPU (core 0)" + depends on SOC_SERIES_ESP32S3 + help + When this SOC is enabled, it will run application on PROCPU (core 0). It will automatically + enable AMP support by building, flashing and loading APPCPU (core 1) image if exists. + +config SOC_ESP32S3_APPCPU + bool "Application runs in ESP32S3 APPCPU (core 1)" + depends on SOC_SERIES_ESP32S3 help - Enable support for Espressif ESP32-S3 + When this SOC is enabled, it will run application on APPCPU (core 1). It is expected that + there is another image running on PROCPU (core 0) to trigger the AMP support. diff --git a/soc/xtensa/espressif_esp32/esp32s3/Kconfig.soc b/soc/xtensa/espressif_esp32/esp32s3/Kconfig.soc index ac265e5edb0..b8cc95b62cb 100644 --- a/soc/xtensa/espressif_esp32/esp32s3/Kconfig.soc +++ b/soc/xtensa/espressif_esp32/esp32s3/Kconfig.soc @@ -13,11 +13,8 @@ config SOC_TOOLCHAIN_NAME choice SOC_PART_NUMBER prompt "ESP32-S3 SOC Selection" - depends on SOC_SERIES_ESP32S3 # SoC with/without embedded flash - config SOC_ESP32S3 - bool "ESP32S3" config SOC_ESP32S3_R2 bool "ESP32S3_R2" config SOC_ESP32S3_R8 @@ -50,6 +47,20 @@ choice SOC_PART_NUMBER endchoice # SOC_PART_NUMBER +config ESP32S3_APPCPU_IRAM + hex "ESP32S3 APPCPU IRAM size" + depends on SOC_ESP32S3_PROCPU || SOC_ESP32S3_APPCPU + default 0x20000 + help + Defines APPCPU IRAM area in bytes. + +config ESP32S3_APPCPU_DRAM + hex "ESP32S3 APPCPU DRAM size" + depends on SOC_ESP32S3_PROCPU || SOC_ESP32S3_APPCPU + default 0x10000 + help + Defines APPCPU DRAM area in bytes. + choice ESP32S3_RTC_CLK_SRC prompt "RTC clock source" default ESP32S3_RTC_CLK_SRC_INT_RC diff --git a/soc/xtensa/espressif_esp32/esp32s3/default.ld b/soc/xtensa/espressif_esp32/esp32s3/default.ld index b3cbd62c89b..90b6c89ada2 100644 --- a/soc/xtensa/espressif_esp32/esp32s3/default.ld +++ b/soc/xtensa/espressif_esp32/esp32s3/default.ld @@ -57,16 +57,30 @@ #define IROM_SEG_LEN FLASH_SIZE #endif +#ifdef CONFIG_SOC_ESP32S3_PROCPU +#define APPCPU_IRAM_SIZE CONFIG_ESP32S3_APPCPU_IRAM +#define APPCPU_DRAM_SIZE CONFIG_ESP32S3_APPCPU_DRAM +#else +#define APPCPU_IRAM_SIZE 0x0 +#define APPCPU_DRAM_SIZE 0x0 +#endif + #define IROM_SEG_ALIGN 0x10000 +/* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA. + * Executing directly from LMA is not possible. */ +#undef GROUP_ROM_LINK_IN +#define GROUP_ROM_LINK_IN(vregion, lregion) > RODATA_REGION AT > lregion + MEMORY { mcuboot_hdr (RX): org = 0x0, len = 0x20 metadata (RX): org = 0x20, len = 0x20 ROM (RX): org = 0x40, len = FLASH_SIZE - 0x40 - iram0_0_seg(RX): org = SRAM_IRAM_ORG, len = SRAM_IRAM_SIZE + iram0_0_seg(RX): org = SRAM_IRAM_ORG, len = SRAM_IRAM_SIZE - APPCPU_IRAM_SIZE + dram0_0_seg(RW): org = SRAM_DRAM_ORG, len = DRAM0_0_SEG_LEN - APPCPU_DRAM_SIZE + irom0_0_seg(RX): org = IROM_SEG_ORG, len = IROM_SEG_LEN - dram0_0_seg(RW): org = SRAM_DRAM_ORG, len = DRAM0_0_SEG_LEN /* DROM is the first segment placed in generated binary. * MCUboot binary for ESP32 has image header of 0x20 bytes. @@ -81,6 +95,7 @@ MEMORY #if defined(CONFIG_ESP_SPIRAM) ext_ram_seg(RWX): org = EXT_RAM_ORG, len = CONFIG_ESP_SPIRAM_SIZE #endif + /* RTC fast memory (executable). Persists over deep sleep. */ rtc_iram_seg(RWX): org = 0x600fe000, len = 0x2000 @@ -152,6 +167,7 @@ SECTIONS */ SECTION_PROLOGUE(_RODATA_SECTION_NAME,,ALIGN(0x10)) { + _rodata_reserved_start = ABSOLUTE(.); _rodata_start = ABSOLUTE(.); *(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */ @@ -203,15 +219,9 @@ SECTIONS *(.rodata_wlog) *(.rodata_wlog*) _thread_local_end = ABSOLUTE(.); - _rodata_reserved_end = ABSOLUTE(.); . = ALIGN(4); } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) - /* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA. - * Executing directly from LMA is not possible. */ - #pragma push_macro("GROUP_ROM_LINK_IN") - #undef GROUP_ROM_LINK_IN - #define GROUP_ROM_LINK_IN(vregion, lregion) > RODATA_REGION AT > lregion #include #include #include @@ -219,12 +229,13 @@ SECTIONS #include #include #include - #pragma pop_macro("GROUP_ROM_LINK_IN") + #include /* Create an explicit section at the end of all the data that shall be mapped into drom. * This is used to calculate the size of the _image_drom_size variable */ SECTION_PROLOGUE(_RODATA_SECTION_END,,ALIGN(0x10)) { + _rodata_reserved_end = ABSOLUTE(.); . = ALIGN(16); _image_rodata_end = ABSOLUTE(.); } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) @@ -417,8 +428,6 @@ SECTIONS . = ALIGN(8) ; } GROUP_LINK_IN(RAMABLE_REGION) -#include - .dram0.data : { . = ALIGN (8); @@ -486,7 +495,6 @@ SECTIONS { . = SIZEOF(_RODATA_SECTION_NAME); . = ALIGN(IROM_SEG_ALIGN) + 0x20; - _rodata_reserved_start = .; } GROUP_LINK_IN(FLASH_CODE_REGION) .flash.text : ALIGN(IROM_SEG_ALIGN) diff --git a/soc/xtensa/espressif_esp32/esp32s3/default_appcpu.ld b/soc/xtensa/espressif_esp32/esp32s3/default_appcpu.ld new file mode 100644 index 00000000000..d5e0e2fe3e9 --- /dev/null +++ b/soc/xtensa/espressif_esp32/esp32s3/default_appcpu.ld @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#define SRAM_IRAM_START 0x40370000 +#define SRAM_DIRAM_I_START 0x40378000 +#define SRAM_IRAM_END 0x403BA000 +#define I_D_SRAM_OFFSET (SRAM_DIRAM_I_START - SRAM_DRAM_START) + +#define SRAM_DRAM_START 0x3FC88000 +#define SRAM_DRAM_END (SRAM_IRAM_END - I_D_SRAM_OFFSET) + +#define IRAM_REGION iram0_0_seg +#define RAMABLE_REGION dram0_0_seg +#define ROMABLE_REGION iram0_0_seg + +#define IROM_SEG_ALIGN 0x4 + +MEMORY +{ + iram0_0_seg(RX): org = SRAM_IRAM_END - CONFIG_ESP32S3_APPCPU_IRAM, len = CONFIG_ESP32S3_APPCPU_IRAM + dram0_0_seg(RW): org = SRAM_DRAM_END - CONFIG_ESP32S3_APPCPU_DRAM, len = CONFIG_ESP32S3_APPCPU_DRAM +#ifdef CONFIG_GEN_ISR_TABLES + IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 +#endif +} + +/* Default entry point: */ +ENTRY(__app_cpu_start) + +SECTIONS +{ + #include + + /* Send .iram0 code to iram */ + .iram0.vectors : ALIGN(4) + { + /* Vectors go to IRAM */ + _init_start = ABSOLUTE(.); + /* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */ + . = 0x0; + KEEP(*(.WindowVectors.text)); + . = 0x180; + KEEP(*(.Level2InterruptVector.text)); + . = 0x1c0; + KEEP(*(.Level3InterruptVector.text)); + . = 0x200; + KEEP(*(.Level4InterruptVector.text)); + . = 0x240; + KEEP(*(.Level5InterruptVector.text)); + . = 0x280; + KEEP(*(.DebugExceptionVector.text)); + . = 0x2c0; + KEEP(*(.NMIExceptionVector.text)); + . = 0x300; + KEEP(*(.KernelExceptionVector.text)); + . = 0x340; + KEEP(*(.UserExceptionVector.text)); + . = 0x3C0; + KEEP(*(.DoubleExceptionVector.text)); + . = 0x400; + _invalid_pc_placeholder = ABSOLUTE(.); + *(.*Vector.literal) + + *(.UserEnter.literal); + *(.UserEnter.text); + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + . = ALIGN (4); + _init_end = ABSOLUTE(.); + + _iram_start = ABSOLUTE(.); + } GROUP_LINK_IN(IRAM_REGION) + + SECTION_PROLOGUE(_TEXT_SECTION_NAME, , ALIGN(4)) + { + /* Code marked as running out of IRAM */ + _iram_text_start = ABSOLUTE(.); + *(.iram1 .iram1.*) + *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) + *libesp32.a:panic.*(.literal .text .literal.* .text.*) + *librtc.a:(.literal .text .literal.* .text.*) + *libarch__xtensa__core.a:(.literal .text .literal.* .text.*) + *libkernel.a:(.literal .text .literal.* .text.*) + *libsoc.a:rtc_*.*(.literal .text .literal.* .text.*) + *libsoc.a:cpu_util.*(.literal .text .literal.* .text.*) + *libgcc.a:lib2funcs.*(.literal .text .literal.* .text.*) + *libdrivers__flash.a:flash_esp32.*(.literal .text .literal.* .text.*) + *libzephyr.a:windowspill_asm.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_noos.*(.literal .text .literal.* .text.*) + *libdrivers__timer.a:xtensa_sys_timer.*(.literal .text .literal.* .text.*) + *libzephyr.a:systimer_hal.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_core.*(.literal .text .literal.* .text.*) + *libzephyr.a:cbprintf_complete.*(.literal .text .literal.* .text.*) + *libzephyr.a:printk.*(.literal.printk .literal.vprintk .literal.char_out .text.printk .text.vprintk .text.char_out) + *libzephyr.a:log_msg.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_list.*(.literal .text .literal.* .text.*) + *libdrivers__console.a:uart_console.*(.literal.console_out .text.console_out) + *libzephyr.a:log_output.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_backend_uart.*(.literal .text .literal.* .text.*) + *libzephyr.a:loader.*(.literal .text .literal.* .text.*) + *liblib__libc__minimal.a:string.*(.literal .text .literal.* .text.*) + *liblib__libc__newlib.a:string.*(.literal .text .literal.* .text.*) + *libc.a:*(.literal .text .literal.* .text.*) + *libphy.a:(.phyiram .phyiram.*) + *libgcov.a:(.literal .text .literal.* .text.*) + + . = ALIGN(4); + _iram_end = ABSOLUTE(.); + . = ALIGN(4) + 16; + + } GROUP_LINK_IN(IRAM_REGION) + + SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) + { + _rodata_start = ABSOLUTE(.); + + *(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */ + *(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */ + + __rodata_region_start = ABSOLUTE(.); + . = ALIGN(4); + #include + + . = ALIGN(4); + *(EXCLUDE_FILE (*libarch__xtensa__core.a:* *libkernel.a:fatal.* *libkernel.a:init.* *libzephyr.a:cbprintf_complete* *libzephyr.a:log_core.* *libzephyr.a:log_backend_uart.* *libzephyr.a:log_output.* *libzephyr.a:loader.* *libdrivers__serial.a:uart_esp32.*) .rodata) + *(EXCLUDE_FILE (*libarch__xtensa__core.a:* *libkernel.a:fatal.* *libkernel.a:init.* *libzephyr.a:cbprintf_complete* *libzephyr.a:log_core.* *libzephyr.a:log_backend_uart.* *libzephyr.a:log_output.* *libzephyr.a:loader.* *libdrivers__serial.a:uart_esp32.*) .rodata.*) + + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table .gcc_except_table.*) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + . = (. + 3) & ~ 3; + __eh_frame = ABSOLUTE(.); + KEEP(*(.eh_frame)) + . = (. + 7) & ~ 3; + + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + . = ALIGN(4); + __rodata_region_end = ABSOLUTE(.); + /* Literals are also RO data. */ + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + . = ALIGN(4); + _thread_local_start = ABSOLUTE(.); + *(.tdata) + *(.tdata.*) + *(.tbss) + *(.tbss.*) + *(.rodata_wlog) + *(.rodata_wlog*) + _thread_local_end = ABSOLUTE(.); + _rodata_reserved_end = ABSOLUTE(.); + . = ALIGN(4); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, IRAM_REGION) + + /* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA. + * Executing directly from LMA is not possible. */ + #pragma push_macro("GROUP_ROM_LINK_IN") + #undef GROUP_ROM_LINK_IN + #define GROUP_ROM_LINK_IN(vregion, lregion) > RAMABLE_REGION AT > lregion + #include + #include + #include + #include + #include + #include + #include + #pragma pop_macro("GROUP_ROM_LINK_IN") + + /* Create an explicit section at the end of all the data that shall be mapped into drom. + * This is used to calculate the size of the _image_drom_size variable */ + SECTION_PROLOGUE(_RODATA_SECTION_END,,) + { + . = ALIGN(16); + _image_rodata_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, IRAM_REGION) + +#include + + .dram0.data : + { + . = ALIGN (8); + __data_start = ABSOLUTE(.); + + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + /* rodata for panic handler(libarch__xtensa__core.a) and all + * dependent functions should be placed in DRAM to avoid issue + * when flash cache is disabled */ + *libarch__xtensa__core.a:(.rodata .rodata.*) + *libkernel.a:fatal.*(.rodata .rodata.*) + *libkernel.a:init.*(.rodata .rodata.*) + *libzephyr.a:cbprintf_complete*(.rodata .rodata.*) + *libzephyr.a:systimer_hal.*(.rodata .rodata.*) + *libzephyr.a:log_core.*(.rodata .rodata.*) + *libzephyr.a:log_backend_uart.*(.rodata .rodata.*) + *libzephyr.a:log_output.*(.rodata .rodata.*) + *libzephyr.a:loader.*(.rodata .rodata.*) + *libdrivers__serial.a:uart_esp32.*(.rodata .rodata.*) + *libdrivers__flash.a:flash_esp32.*(.rodata .rodata.*) + + KEEP(*(.jcr)) + *(.dram1 .dram1.*) + . = ALIGN(4); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, IRAM_REGION) + + #include + #include + #include + #include + #include + + /* logging sections should be placed in RAM area to avoid flash cache disabled issues */ + #pragma push_macro("GROUP_ROM_LINK_IN") + #undef GROUP_ROM_LINK_IN + #define GROUP_ROM_LINK_IN GROUP_DATA_LINK_IN + #include + #pragma pop_macro("GROUP_ROM_LINK_IN") + + .dram0.end : + { + . = ALIGN(4); + + #include + + . = ALIGN(4); + _end = ABSOLUTE(.); + _heap_sentry = .; + . = ALIGN(4); + __data_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, IRAM_REGION) + + /* Shared RAM */ + SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); /* required by bluetooth library */ + __bss_start = ABSOLUTE(.); + + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.share.mem) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + __bss_end = ABSOLUTE(.); + } GROUP_LINK_IN(RAMABLE_REGION) + + ASSERT(((__bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), "DRAM segment data does not fit.") + + SECTION_DATA_PROLOGUE(_NOINIT_SECTION_NAME, (NOLOAD),) + { + . = ALIGN(8); + *(.noinit) + *(.noinit.*) + . = ALIGN(8) ; + } GROUP_LINK_IN(RAMABLE_REGION) + + .flash.text : ALIGN(IROM_SEG_ALIGN) + { + _stext = .; + _text_start = ABSOLUTE(.); + + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.fini.literal) + *(.fini) + *(.gnu.version) + *(.literal .text .literal.* .text.*) + + /* CPU will try to prefetch up to 16 bytes of + * of instructions. This means that any configuration (e.g. MMU, PMS) must allow + * safe access to up to 16 bytes after the last real instruction, add + * dummy bytes to ensure this + */ + . += 16; + + _text_end = ABSOLUTE(.); + _etext = .; + + /* Similar to _iram_start, this symbol goes here so it is + * resolved by addr2line in preference to the first symbol in + * the flash.text segment. + */ + . = ALIGN(4); + _flash_cache_start = ABSOLUTE(0); + } GROUP_LINK_IN(IRAM_REGION) + +#ifdef CONFIG_GEN_ISR_TABLES +#include +#endif + +#include + + .xtensa.info 0 : { *(.xtensa.info) } + .xt.insn 0 : + { + KEEP (*(.xt.insn)) + KEEP (*(.gnu.linkonce.x.*)) + } + .xt.prop 0 : + { + KEEP (*(.xt.prop)) + KEEP (*(.xt.prop.*)) + KEEP (*(.gnu.linkonce.prop.*)) + } + .xt.lit 0 : + { + KEEP (*(.xt.lit)) + KEEP (*(.xt.lit.*)) + KEEP (*(.gnu.linkonce.p.*)) + } + .xt.profile_range 0 : + { + KEEP (*(.xt.profile_range)) + KEEP (*(.gnu.linkonce.profile_range.*)) + } + .xt.profile_ranges 0 : + { + KEEP (*(.xt.profile_ranges)) + KEEP (*(.gnu.linkonce.xt.profile_ranges.*)) + } + .xt.profile_files 0 : + { + KEEP (*(.xt.profile_files)) + KEEP (*(.gnu.linkonce.xt.profile_files.*)) + } + +} + +ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), + "IRAM0 segment data does not fit.") diff --git a/soc/xtensa/espressif_esp32/esp32s3/esp32s3-mp.c b/soc/xtensa/espressif_esp32/esp32s3/esp32s3-mp.c new file mode 100644 index 00000000000..5f20b64c27a --- /dev/null +++ b/soc/xtensa/espressif_esp32/esp32s3/esp32s3-mp.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +static struct k_spinlock loglock; + +void smp_log(const char *msg) +{ + while (*msg) { + esp_rom_uart_tx_one_char(*msg++); + } + esp_rom_uart_tx_one_char('\r'); + esp_rom_uart_tx_one_char('\n'); +} + +void esp_appcpu_start(void *entry_point) +{ + soc_ll_unstall_core(1); + + if (!REG_GET_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_CLKGATE_EN)) { + REG_SET_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_CLKGATE_EN); + REG_CLR_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RUNSTALL); + REG_SET_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RESETTING); + REG_CLR_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RESETTING); + } + + esp_rom_ets_set_appcpu_boot_addr((void *)entry_point); + + ets_delay_us(50000); + + smp_log("ESP32S3: CPU1 start sequence complete"); +} diff --git a/soc/xtensa/espressif_esp32/esp32s3/linker.ld b/soc/xtensa/espressif_esp32/esp32s3/linker.ld deleted file mode 100644 index 6cfbce9433f..00000000000 --- a/soc/xtensa/espressif_esp32/esp32s3/linker.ld +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - */ - -#if defined(CONFIG_MCUBOOT) - /* Using mcuboot as ESP32S3 2nd stage bootloader */ - #include "mcuboot.ld" - -#else - /* Application default linker script */ - #include "default.ld" - -#endif /* CONFIG_MCUBOOT */ diff --git a/soc/xtensa/espressif_esp32/esp32s3/soc.c b/soc/xtensa/espressif_esp32/esp32s3/soc.c index 4d44fe2f004..ad971b907b2 100644 --- a/soc/xtensa/espressif_esp32/esp32s3/soc.c +++ b/soc/xtensa/espressif_esp32/esp32s3/soc.c @@ -5,7 +5,7 @@ */ /* Include esp-idf headers first to avoid redefining BIT() macro */ -#include "soc.h" +#include #include #include #include @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include @@ -48,6 +48,45 @@ extern int _ext_ram_bss_end; extern void z_cstart(void); +#ifdef CONFIG_SOC_ESP32S3_PROCPU +extern const unsigned char esp32s3_appcpu_fw_array[]; + +void IRAM_ATTR esp_start_appcpu(void) +{ + esp_image_header_t *header = (esp_image_header_t *)&esp32s3_appcpu_fw_array[0]; + esp_image_segment_header_t *segment = + (esp_image_segment_header_t *)&esp32s3_appcpu_fw_array[sizeof(esp_image_header_t)]; + uint8_t *segment_payload; + uint32_t entry_addr = header->entry_addr; + uint32_t idx = sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t); + + for (int i = 0; i < header->segment_count; i++) { + segment_payload = (uint8_t *)&esp32s3_appcpu_fw_array[idx]; + + if (segment->load_addr >= SOC_IRAM_LOW && segment->load_addr < SOC_IRAM_HIGH) { + /* IRAM segment only accepts 4 byte access, avoid memcpy usage here */ + volatile uint32_t *src = (volatile uint32_t *)segment_payload; + volatile uint32_t *dst = (volatile uint32_t *)segment->load_addr; + + for (int i = 0; i < segment->data_len / 4; i++) { + dst[i] = src[i]; + } + + } else if (segment->load_addr >= SOC_DRAM_LOW && + segment->load_addr < SOC_DRAM_HIGH) { + memcpy((void *)segment->load_addr, (const void *)segment_payload, + segment->data_len); + } + + idx += segment->data_len; + segment = (esp_image_segment_header_t *)&esp32s3_appcpu_fw_array[idx]; + idx += sizeof(esp_image_segment_header_t); + } + + esp_appcpu_start((void *)entry_addr); +} +#endif /* CONFIG_SOC_ESP32S3_PROCPU*/ + #ifndef CONFIG_MCUBOOT /* * This function is a container for SoC patches @@ -92,7 +131,7 @@ void IRAM_ATTR __esp_platform_start(void) * initialization code wants a valid _current before * arch_kernel_init() is invoked. */ - __asm__ volatile("wsr.MISC0 %0; rsync" : : "r"(&_kernel.cpus[0])); + __asm__ __volatile__("wsr.MISC0 %0; rsync" : : "r"(&_kernel.cpus[0])); #ifdef CONFIG_MCUBOOT /* MCUboot early initialisation. */ @@ -149,6 +188,11 @@ void IRAM_ATTR __esp_platform_start(void) esp_timer_early_init(); +#if CONFIG_SOC_ESP32S3_PROCPU + /* start the ESP32S3 APP CPU */ + esp_start_appcpu(); +#endif + #if CONFIG_SOC_FLASH_ESP32 spi_flash_guard_set(&g_flash_guard_default_ops); #endif diff --git a/soc/xtensa/espressif_esp32/esp32s3/soc_appcpu.c b/soc/xtensa/espressif_esp32/esp32s3/soc_appcpu.c new file mode 100644 index 00000000000..583f0b8119a --- /dev/null +++ b/soc/xtensa/espressif_esp32/esp32s3/soc_appcpu.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void z_cstart(void); + +static void core_intr_matrix_clear(void) +{ + uint32_t core_id = cpu_hal_get_core_id(); + + for (int i = 0; i < ETS_MAX_INTR_SOURCE; i++) { + intr_matrix_set(core_id, i, ETS_INVALID_INUM); + } +} + +void IRAM_ATTR __app_cpu_start(void) +{ + extern uint32_t _init_start; + extern uint32_t _bss_start; + extern uint32_t _bss_end; + + /* Move the exception vector table to IRAM. */ + __asm__ __volatile__("wsr %0, vecbase" : : "r"(&_init_start)); + + /* Zero out BSS. Clobber _bss_start to avoid memset() elision. */ + z_bss_zero(); + + __asm__ __volatile__("" : : "g"(&__bss_start) : "memory"); + + /* Disable normal interrupts. */ + __asm__ __volatile__("wsr %0, PS" : : "r"(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE)); + + /* Initialize the architecture CPU pointer. Some of the + * initialization code wants a valid _current before + * arch_kernel_init() is invoked. + */ + __asm__ __volatile__("wsr.MISC0 %0; rsync" : : "r"(&_kernel.cpus[1])); + + core_intr_matrix_clear(); + + esp_intr_initialize(); + + /* Start Zephyr */ + z_cstart(); + + CODE_UNREACHABLE; +} + +/* Boot-time static default printk handler, possibly to be overridden later. */ +int IRAM_ATTR arch_printk_char_out(int c) +{ + ARG_UNUSED(c); + return 0; +} + +void sys_arch_reboot(int type) +{ + esp_restart_noos(); +} + +void IRAM_ATTR esp_restart_noos(void) +{ + /* disable interrupts */ + z_xt_ints_off(0xFFFFFFFF); + + /* enable RTC watchdog for 1 second */ + wdt_hal_context_t wdt_ctx; + uint32_t timeout_ticks = (uint32_t)(1000ULL * rtc_clk_slow_freq_get_hz() / 1000ULL); + + wdt_hal_init(&wdt_ctx, WDT_RWDT, 0, false); + wdt_hal_write_protect_disable(&wdt_ctx); + wdt_hal_config_stage(&wdt_ctx, WDT_STAGE0, timeout_ticks, WDT_STAGE_ACTION_RESET_SYSTEM); + wdt_hal_config_stage(&wdt_ctx, WDT_STAGE1, timeout_ticks, WDT_STAGE_ACTION_RESET_RTC); + + /* enable flash boot mode so that flash booting after restart is protected by the RTC WDT */ + wdt_hal_set_flashboot_en(&wdt_ctx, true); + wdt_hal_write_protect_enable(&wdt_ctx); + + /* disable TG0/TG1 watchdogs */ + wdt_hal_context_t wdt0_context = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0}; + + wdt_hal_write_protect_disable(&wdt0_context); + wdt_hal_disable(&wdt0_context); + wdt_hal_write_protect_enable(&wdt0_context); + + wdt_hal_context_t wdt1_context = {.inst = WDT_MWDT1, .mwdt_dev = &TIMERG1}; + + wdt_hal_write_protect_disable(&wdt1_context); + wdt_hal_disable(&wdt1_context); + wdt_hal_write_protect_enable(&wdt1_context); + + /* Flush any data left in UART FIFOs */ + esp_rom_uart_tx_wait_idle(0); + esp_rom_uart_tx_wait_idle(1); + esp_rom_uart_tx_wait_idle(2); + + /* Disable cache */ + Cache_Disable_ICache(); + Cache_Disable_DCache(); + + /* 2nd stage bootloader reconfigures SPI flash signals. */ + /* Reset them to the defaults expected by ROM */ + WRITE_PERI_REG(GPIO_FUNC0_IN_SEL_CFG_REG, 0x30); + WRITE_PERI_REG(GPIO_FUNC1_IN_SEL_CFG_REG, 0x30); + WRITE_PERI_REG(GPIO_FUNC2_IN_SEL_CFG_REG, 0x30); + WRITE_PERI_REG(GPIO_FUNC3_IN_SEL_CFG_REG, 0x30); + WRITE_PERI_REG(GPIO_FUNC4_IN_SEL_CFG_REG, 0x30); + WRITE_PERI_REG(GPIO_FUNC5_IN_SEL_CFG_REG, 0x30); + + /* Reset wifi/bluetooth/ethernet/sdio (bb/mac) */ + SET_PERI_REG_MASK(SYSTEM_CORE_RST_EN_REG, + SYSTEM_BB_RST | SYSTEM_FE_RST | SYSTEM_MAC_RST | SYSTEM_BT_RST | + SYSTEM_BTMAC_RST | SYSTEM_SDIO_RST | SYSTEM_SDIO_HOST_RST | + SYSTEM_EMAC_RST | SYSTEM_MACPWR_RST | SYSTEM_RW_BTMAC_RST | + SYSTEM_RW_BTLP_RST | SYSTEM_BLE_REG_RST | SYSTEM_PWR_REG_RST); + REG_WRITE(SYSTEM_CORE_RST_EN_REG, 0); + + /* Reset timer/spi/uart */ + SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_TIMERS_RST | SYSTEM_SPI01_RST | + SYSTEM_UART_RST | SYSTEM_SYSTIMER_RST); + REG_WRITE(SYSTEM_PERIP_RST_EN0_REG, 0); + + /* Reset DMA */ + SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST); + REG_WRITE(SYSTEM_PERIP_RST_EN1_REG, 0); + + SET_PERI_REG_MASK(SYSTEM_EDMA_CTRL_REG, SYSTEM_EDMA_RESET); + CLEAR_PERI_REG_MASK(SYSTEM_EDMA_CTRL_REG, SYSTEM_EDMA_RESET); + + rtc_clk_cpu_freq_set_xtal(); + + /* Running on APP CPU: need to reset PRO CPU and unstall it, */ + /* then reset APP CPU */ + soc_ll_reset_core(0); + soc_ll_stall_core(0); + soc_ll_reset_core(1); + + while (true) { + ; + } +} diff --git a/soc/xtensa/intel_adsp/CMakeLists.txt b/soc/xtensa/intel_adsp/CMakeLists.txt index 8a3b1f01f25..2cee15bbcf6 100644 --- a/soc/xtensa/intel_adsp/CMakeLists.txt +++ b/soc/xtensa/intel_adsp/CMakeLists.txt @@ -10,3 +10,4 @@ endif() if(CONFIG_INTEL_ADSP_CAVS) add_subdirectory(cavs) endif() +zephyr_include_directories(common/include) diff --git a/soc/xtensa/intel_adsp/Kconfig b/soc/xtensa/intel_adsp/Kconfig index f04286ccae1..a3d93d976ea 100644 --- a/soc/xtensa/intel_adsp/Kconfig +++ b/soc/xtensa/intel_adsp/Kconfig @@ -113,4 +113,16 @@ config ADSP_IMR_CONTEXT_SAVE entering D3 state. Later this context can be used to FW restore when Host power up DSP again. +config XTENSA_CPU_IDLE_SPIN + bool "Use busy loop for k_cpu_idle" + help + Use a spin loop instead of WAITI for the CPU idle state. + +config XTENSA_WAITI_BUG + bool "Workaround sequence for WAITI bug on LX6" + help + SOF traditionally contains this workaround on its ADSP + platforms which prefixes a WAITI entry with 128 NOP + instructions followed by an ISYNC and EXTW. + endif # SOC_FAMILY_INTEL_ADSP diff --git a/soc/xtensa/intel_adsp/ace/CMakeLists.txt b/soc/xtensa/intel_adsp/ace/CMakeLists.txt index 43e812cbabb..a5aa90b59d0 100644 --- a/soc/xtensa/intel_adsp/ace/CMakeLists.txt +++ b/soc/xtensa/intel_adsp/ace/CMakeLists.txt @@ -13,5 +13,9 @@ zephyr_library_sources( boot.c ) +zephyr_include_directories(include) +zephyr_include_directories(include/${SOC_NAME}) zephyr_library_sources_ifdef(CONFIG_SOC_INTEL_COMM_WIDGET comm_widget.c) zephyr_library_sources_ifdef(CONFIG_SOC_INTEL_COMM_WIDGET comm_widget_messages.c) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/xtensa/intel_adsp/ace/ace-link.ld b/soc/xtensa/intel_adsp/ace/ace-link.ld index a4aaf6b8087..454893055e1 100644 --- a/soc/xtensa/intel_adsp/ace/ace-link.ld +++ b/soc/xtensa/intel_adsp/ace/ace-link.ld @@ -403,10 +403,13 @@ SECTIONS { _unused_ram_start_marker = .; *(.unused_ram_start_marker) *(.unused_ram_start_marker.*) - _end = .; z_mapped_end = .; } >ram + /* Heap start and end markers. Used with libc malloc code. */ + . = SEGSTART_UNCACHED; + _end = ALIGN(8); + . = SEGSTART_CACHED; . = L2_SRAM_BASE + L2_SRAM_SIZE; . = SEGSTART_UNCACHED; _heap_end = .; diff --git a/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm/adsp_memory.h b/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm/adsp_memory.h index 7290b1ef6cc..56e78cdca5f 100644 --- a/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm/adsp_memory.h +++ b/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm/adsp_memory.h @@ -147,6 +147,17 @@ struct ace_hpsram_regs { uint8_t HSxPGISTS; uint8_t reserved1[3]; }; + +struct ace_lpsram_regs { + /** @brief power gating control */ + uint8_t USxPGCTL; + /** @brief retention mode control */ + uint8_t USxRMCTL; + uint8_t reserved[2]; + /** @brief power gating status */ + uint8_t USxPGISTS; + uint8_t reserved1[3]; +}; #endif /* These registers are for the L2 HP SRAM bank power management control and status.*/ @@ -156,4 +167,11 @@ struct ace_hpsram_regs { #define HPSRAM_REGS(block_idx) ((volatile struct ace_hpsram_regs *const) \ (L2HSBPM_REG + L2HSBPM_REG_SIZE * (block_idx))) +/* These registers are for the L2 LP SRAM bank power management control and status.*/ +#define L2LSBPM_REG 0x71D80 +#define L2LSBPM_REG_SIZE 0x0008 + +#define LPSRAM_REGS(block_idx) ((volatile struct ace_lpsram_regs *const) \ + (L2LSBPM_REG + L2LSBPM_REG_SIZE * (block_idx))) + #endif /* ZEPHYR_SOC_INTEL_ADSP_MEMORY_H_ */ diff --git a/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm/adsp_shim.h b/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm/adsp_shim.h index a6faa63c3d2..56997ee84d1 100644 --- a/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm/adsp_shim.h +++ b/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm/adsp_shim.h @@ -140,7 +140,7 @@ struct ace_dfpmccu { #endif /* _ASMLANGUAGE */ -#define ACE_CLKCTL_WOVCRO BIT(4) /* Request WOVCRO clock */ +#define ACE_CLKCTL_WOVCRO BIT(21) /* Request WOVCRO clock */ #define SHIM_LDOCTL_HPSRAM_LDO_ON (3 << 0) #define SHIM_LDOCTL_HPSRAM_LDO_BYPASS BIT(0) diff --git a/soc/xtensa/intel_adsp/ace/include/intel_ace20_lnl/adsp_memory.h b/soc/xtensa/intel_adsp/ace/include/intel_ace20_lnl/adsp_memory.h index 165831207f1..a45a8ae590d 100644 --- a/soc/xtensa/intel_adsp/ace/include/intel_ace20_lnl/adsp_memory.h +++ b/soc/xtensa/intel_adsp/ace/include/intel_ace20_lnl/adsp_memory.h @@ -145,6 +145,17 @@ struct ace_hpsram_regs { uint8_t HSxPGISTS; uint8_t reserved1[3]; }; + +struct ace_lpsram_regs { + /** @brief power gating control */ + uint8_t USxPGCTL; + /** @brief retention mode control */ + uint8_t USxRMCTL; + uint8_t reserved[2]; + /** @brief power gating status */ + uint8_t USxPGISTS; + uint8_t reserved1[3]; +}; #endif /* These registers are for the L2 HP SRAM bank power management control and status.*/ @@ -154,4 +165,11 @@ struct ace_hpsram_regs { #define HPSRAM_REGS(block_idx) ((volatile struct ace_hpsram_regs *const) \ (L2HSBPM_REG + L2HSBPM_REG_SIZE * (block_idx))) +/* These registers are for the L2 LP SRAM bank power management control and status.*/ +#define L2LSBPM_REG 0x71D80 +#define L2LSBPM_REG_SIZE 0x0008 + +#define LPSRAM_REGS(block_idx) ((volatile struct ace_lpsram_regs *const) \ + (L2LSBPM_REG + L2LSBPM_REG_SIZE * (block_idx))) + #endif /* ZEPHYR_SOC_INTEL_ADSP_MEMORY_H_ */ diff --git a/soc/xtensa/intel_adsp/ace/sram.c b/soc/xtensa/intel_adsp/ace/sram.c index d2f7bb6c27a..fb3348e0f33 100644 --- a/soc/xtensa/intel_adsp/ace/sram.c +++ b/soc/xtensa/intel_adsp/ace/sram.c @@ -20,15 +20,14 @@ __imr void hp_sram_init(uint32_t memory_size) ARG_UNUSED(memory_size); uint32_t hpsram_ebb_quantity = ace_hpsram_get_bank_count(); - volatile uint32_t *l2hsbpmptr = (volatile uint32_t *)ACE_L2MM->l2hsbpmptr; - volatile uint8_t *status = (volatile uint8_t *)l2hsbpmptr + 4; uint32_t idx; for (idx = 0; idx < hpsram_ebb_quantity; ++idx) { - *(l2hsbpmptr + idx * 2) = 0; + HPSRAM_REGS(idx)->HSxPGCTL = 0; + HPSRAM_REGS(idx)->HSxRMCTL = 1; } for (idx = 0; idx < hpsram_ebb_quantity; ++idx) { - while (*(status + idx * 8) != 0) { + while (HPSRAM_REGS(idx)->HSxPGISTS != 0) { } } @@ -38,15 +37,14 @@ __imr void hp_sram_init(uint32_t memory_size) __imr void lp_sram_init(void) { uint32_t lpsram_ebb_quantity = ace_lpsram_get_bank_count(); - volatile uint32_t *l2usbpmptr = (volatile uint32_t *)ACE_L2MM->l2usbpmptr; - volatile uint8_t *status = (volatile uint8_t *)l2usbpmptr + 4; uint32_t idx; for (idx = 0; idx < lpsram_ebb_quantity; ++idx) { - *(l2usbpmptr + idx * 2) = 0; + LPSRAM_REGS(idx)->USxPGCTL = 0; + LPSRAM_REGS(idx)->USxRMCTL = 1; } for (idx = 0; idx < lpsram_ebb_quantity; ++idx) { - while (*(status + idx * 8) != 0) { + while (LPSRAM_REGS(idx)->USxPGISTS != 0) { } } diff --git a/soc/xtensa/intel_adsp/cavs/CMakeLists.txt b/soc/xtensa/intel_adsp/cavs/CMakeLists.txt index 2a0cbdc463c..5226f1b0535 100644 --- a/soc/xtensa/intel_adsp/cavs/CMakeLists.txt +++ b/soc/xtensa/intel_adsp/cavs/CMakeLists.txt @@ -3,7 +3,8 @@ # Copyright (c) 2022 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -zephyr_library_include_directories(include) +zephyr_include_directories(include) +zephyr_include_directories(include/${SOC_NAME}) zephyr_library_include_directories(${ZEPHYR_BASE}/drivers) zephyr_library_sources( @@ -17,3 +18,5 @@ if(CONFIG_SMP OR CONFIG_MP_MAX_NUM_CPUS GREATER 1) endif() zephyr_library_sources_ifdef(CONFIG_CAVS_ICTL irq.c) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/include/xtensa-cavs-linker.ld CACHE INTERNAL "") diff --git a/soc/xtensa/intel_adsp/cavs/linker.ld b/soc/xtensa/intel_adsp/cavs/linker.ld deleted file mode 100644 index 7c5566067b6..00000000000 --- a/soc/xtensa/intel_adsp/cavs/linker.ld +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2019 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * Linker script for the intel_apl_adsp platform - */ - -#include diff --git a/soc/xtensa/intel_adsp/cavs/multiprocessing.c b/soc/xtensa/intel_adsp/cavs/multiprocessing.c index bc48764515a..85d834065a7 100644 --- a/soc/xtensa/intel_adsp/cavs/multiprocessing.c +++ b/soc/xtensa/intel_adsp/cavs/multiprocessing.c @@ -7,6 +7,7 @@ #include #include #include +#include /* IDC power up message to the ROM firmware. This isn't documented * anywhere, it's basically just a magic number (except the high bit, @@ -71,7 +72,22 @@ void soc_start_core(int cpu_num) }; memcpy(lpsram, tramp, ARRAY_SIZE(tramp)); +#if CONFIG_PM + extern void dsp_restore_vector(void); + + /* We need to find out what type of booting is taking place here. Secondary cores + * can be disabled and enabled multiple times during runtime. During kernel + * initialization, the next pm state is set to ACTIVE. This way we can determine + * whether the core is being turned on again or for the first time. + */ + if (pm_state_next_get(cpu_num)->state == PM_STATE_ACTIVE) + lpsram[1] = z_soc_mp_asm_entry; + else + lpsram[1] = dsp_restore_vector; +#else lpsram[1] = z_soc_mp_asm_entry; +#endif + /* Disable automatic power and clock gating for that CPU, so * it won't just go back to sleep. Note that after startup, @@ -98,7 +114,7 @@ void soc_start_core(int cpu_num) * available, so it's sent shifted). The write to ITC * triggers the interrupt, so that comes last. */ - uint32_t ietc = ((long) z_soc_mp_asm_entry) >> 2; + uint32_t ietc = ((long)lpsram[1]) >> 2; IDC[curr_cpu].core[cpu_num].ietc = ietc; IDC[curr_cpu].core[cpu_num].itc = IDC_MSG_POWER_UP; diff --git a/soc/xtensa/intel_adsp/cavs/power.c b/soc/xtensa/intel_adsp/cavs/power.c index e5b9f73285d..c0a75f5c0ec 100644 --- a/soc/xtensa/intel_adsp/cavs/power.c +++ b/soc/xtensa/intel_adsp/cavs/power.c @@ -54,6 +54,9 @@ LOG_MODULE_REGISTER(soc); extern void rom_entry(void); struct core_state { + uint32_t a0; + uint32_t a1; + uint32_t excsave2; uint32_t intenable; }; @@ -76,6 +79,51 @@ static inline void __sparse_cache *uncache_to_cache(void *address) return (void __sparse_cache *)((uintptr_t)(address) | SRAM_ALIAS_OFFSET); } +static ALWAYS_INLINE void _save_core_context(void) +{ + uint32_t core_id = arch_proc_id(); + + core_desc[core_id].excsave2 = XTENSA_RSR(ZSR_CPU_STR); + __asm__ volatile("mov %0, a0" : "=r"(core_desc[core_id].a0)); + __asm__ volatile("mov %0, a1" : "=r"(core_desc[core_id].a1)); + sys_cache_data_flush_range(&core_desc[core_id], sizeof(struct core_state)); +} + +static ALWAYS_INLINE void _restore_core_context(void) +{ + uint32_t core_id = arch_proc_id(); + + XTENSA_WSR(ZSR_CPU_STR, core_desc[core_id].excsave2); + __asm__ volatile("mov a0, %0" :: "r"(core_desc[core_id].a0)); + __asm__ volatile("mov a1, %0" :: "r"(core_desc[core_id].a1)); + __asm__ volatile("rsync"); +} + +void power_gate_exit(void) +{ + cpu_early_init(); + sys_cache_data_flush_and_invd_all(); + _restore_core_context(); +} + +__asm__(".align 4\n\t" + ".global dsp_restore_vector\n\t" + "dsp_restore_vector:\n\t" + " movi a0, 0\n\t" + " movi a1, 1\n\t" + " movi a2, 0x40020\n\t"/* PS_UM|PS_WOE */ + " wsr a2, PS\n\t" + " wsr a1, WINDOWSTART\n\t" + " wsr a0, WINDOWBASE\n\t" + " rsync\n\t" + " movi a1, z_interrupt_stacks\n\t" + " rsr a2, PRID\n\t" + " movi a3, " STRINGIFY(CONFIG_ISR_STACK_SIZE) "\n\t" + " mull a2, a2, a3\n\t" + " add a2, a2, a3\n\t" + " add a1, a1, a2\n\t" + " call0 power_gate_exit\n\t"); + void pm_state_set(enum pm_state state, uint8_t substate_id) { ARG_UNUSED(substate_id); @@ -84,6 +132,8 @@ void pm_state_set(enum pm_state state, uint8_t substate_id) if (state == PM_STATE_SOFT_OFF) { core_desc[cpu].intenable = XTENSA_RSR("INTENABLE"); z_xt_ints_off(0xffffffff); + xthal_window_spill(); + _save_core_context(); soc_cpus_active[cpu] = false; sys_cache_data_flush_and_invd_all(); if (cpu == 0) { @@ -107,7 +157,6 @@ void pm_state_set(enum pm_state state, uint8_t substate_id) /* do power down - this function won't return */ power_down_cavs(true, uncache_to_cache(&hpsram_mask[0])); } else { - z_xt_ints_on(core_desc[cpu].intenable); k_cpu_idle(); } } else { @@ -131,6 +180,51 @@ void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) } #endif /* CONFIG_PM */ +#ifdef CONFIG_ARCH_CPU_IDLE_CUSTOM +/* xt-clang removes any NOPs more than 8. So we need to set + * no optimization to avoid those NOPs from being removed. + * + * This function is simply enough and full of hand written + * assembly that optimization is not really meaningful + * anyway. So we can skip optimization unconditionally. + * Re-evalulate its use and add #ifdef if this assumption + * is no longer valid. + */ +__no_optimization +void arch_cpu_idle(void) +{ + sys_trace_idle(); + + /* Just spin forever with interrupts unmasked, for platforms + * where WAITI can't be used or where its behavior is + * complicated (Intel DSPs will power gate on idle entry under + * some circumstances) + */ + if (IS_ENABLED(CONFIG_XTENSA_CPU_IDLE_SPIN)) { + __asm__ volatile("rsil a0, 0"); + __asm__ volatile("loop_forever: j loop_forever"); + return; + } + + /* Cribbed from SOF: workaround for a bug in some versions of + * the LX6 IP. Preprocessor ugliness avoids the need to + * figure out how to get the compiler to unroll a loop. + */ + if (IS_ENABLED(CONFIG_XTENSA_WAITI_BUG)) { +#define NOP4 __asm__ volatile("nop; nop; nop; nop"); +#define NOP32 NOP4 NOP4 NOP4 NOP4 NOP4 NOP4 NOP4 NOP4 +#define NOP128() NOP32 NOP32 NOP32 NOP32 + NOP128(); +#undef NOP128 +#undef NOP32 +#undef NOP4 + __asm__ volatile("isync; extw"); + } + +__asm__ volatile ("waiti 0"); +} +#endif + __imr void power_init(void) { /* Request HP ring oscillator and diff --git a/soc/xtensa/intel_adsp/common/CMakeLists.txt b/soc/xtensa/intel_adsp/common/CMakeLists.txt index ff09b1e4ea8..c463e4453fc 100644 --- a/soc/xtensa/intel_adsp/common/CMakeLists.txt +++ b/soc/xtensa/intel_adsp/common/CMakeLists.txt @@ -6,7 +6,7 @@ zephyr_interface_library_named(INTEL_ADSP_COMMON) zephyr_library_named(intel_adsp_common) -zephyr_library_include_directories(include) +zephyr_include_directories(include) zephyr_library_include_directories(${ZEPHYR_BASE}/drivers) zephyr_library_sources_ifdef(CONFIG_INTEL_ADSP_IPC ipc.c) diff --git a/soc/xtensa/intel_adsp/common/boot_complete.c b/soc/xtensa/intel_adsp/common/boot_complete.c index 791590e1273..445fd57b064 100644 --- a/soc/xtensa/intel_adsp/common/boot_complete.c +++ b/soc/xtensa/intel_adsp/common/boot_complete.c @@ -29,4 +29,4 @@ int boot_complete(void) return 0; } -SYS_INIT(boot_complete, EARLY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); +SYS_INIT(boot_complete, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); diff --git a/soc/xtensa/intel_adsp/common/clk.c b/soc/xtensa/intel_adsp/common/clk.c index fada03528bf..0f3f3d32b80 100644 --- a/soc/xtensa/intel_adsp/common/clk.c +++ b/soc/xtensa/intel_adsp/common/clk.c @@ -25,6 +25,15 @@ int adsp_clock_freq_mask[] = ADSP_CPU_CLOCK_FREQ_MASK; static void select_cpu_clock_hw(uint32_t freq_idx) { uint32_t enc = adsp_clock_freq_enc[freq_idx]; + +#ifdef CONFIG_SOC_SERIES_INTEL_ACE + uint32_t clk_ctl = ADSP_CLKCTL; + + clk_ctl &= ~ADSP_CLKCTL_OSC_SOURCE_MASK; + clk_ctl |= (enc & ADSP_CLKCTL_OSC_SOURCE_MASK); + + ADSP_CLKCTL = clk_ctl; +#else uint32_t status_mask = adsp_clock_freq_mask[freq_idx]; /* Request clock */ @@ -42,6 +51,7 @@ static void select_cpu_clock_hw(uint32_t freq_idx) /* Release other clocks */ ADSP_CLKCTL &= ~ADSP_CLKCTL_OSC_REQUEST_MASK | enc; +#endif } int adsp_clock_set_cpu_freq(uint32_t freq_idx) @@ -84,7 +94,7 @@ void adsp_clock_init(void) if (ACE_DfPMCCU.dfclkctl & ACE_CLKCTL_WOVCRO) { ACE_DfPMCCU.dfclkctl = ACE_DfPMCCU.dfclkctl & ~ACE_CLKCTL_WOVCRO; } else { - platform_lowest_freq_idx = ADSP_CPU_CLOCK_FREQ_LPRO; + platform_lowest_freq_idx = ADSP_CPU_CLOCK_FREQ_IPLL; } #else CAVS_SHIM.clkctl |= CAVS_CLKCTL_WOVCRO; diff --git a/soc/xtensa/intel_adsp/common/include/adsp_clk.h b/soc/xtensa/intel_adsp/common/include/adsp_clk.h index 94d2cb07c00..34d7c21822d 100644 --- a/soc/xtensa/intel_adsp/common/include/adsp_clk.h +++ b/soc/xtensa/intel_adsp/common/include/adsp_clk.h @@ -59,6 +59,8 @@ struct adsp_cpu_clock_info *adsp_cpu_clocks_get(void); #define ADSP_CPU_CLOCK_FREQ_WOVCRO ADSP_CPU_CLOCK_FREQ(wovcro) #endif +#define ADSP_CPU_CLOCK_FREQ_IPLL ADSP_CPU_CLOCK_FREQ(ipll) + /* Clock sources used by dai */ #define ADSP_CLOCK_SOURCE_XTAL_OSC 0 diff --git a/soc/xtensa/intel_adsp/common/include/intel_adsp_hda.h b/soc/xtensa/intel_adsp/common/include/intel_adsp_hda.h index 2d166d8950a..2b403eb17a4 100644 --- a/soc/xtensa/intel_adsp/common/include/intel_adsp_hda.h +++ b/soc/xtensa/intel_adsp/common/include/intel_adsp_hda.h @@ -469,4 +469,26 @@ static inline uint32_t intel_adsp_hda_check_buffer_interrupt(uint32_t base, uint return (*DGCS(base, regblock_size, sid) & DGCS_BSC) == DGCS_BSC; } +/** + * @brief Set the Sample Container Size (SCS) + * + * Sample Container Size indicates the container size of the audio samples in local memory + * SCS bit must cleared to 0 for 32bit sample size (HD Audio container size) + * SCS bit must be set to 1 for non 32bit sample sizes + * + * @param base Base address of the IP register block + * @param regblock_size Register block size + * @param sid Stream ID + * @param sample_size + */ +static inline void intel_adsp_hda_set_sample_container_size(uint32_t base, uint32_t regblock_size, + uint32_t sid, uint32_t sample_size) +{ + if (sample_size <= 3) { + *DGCS(base, regblock_size, sid) |= DGCS_SCS; + } else { + *DGCS(base, regblock_size, sid) &= ~DGCS_SCS; + } +} + #endif /* ZEPHYR_INCLUDE_INTEL_ADSP_HDA_H */ diff --git a/soc/xtensa/intel_adsp/common/include/intel_adsp_ipc.h b/soc/xtensa/intel_adsp/common/include/intel_adsp_ipc.h index 2bca8c9c5b8..ca1ddfb573b 100644 --- a/soc/xtensa/intel_adsp/common/include/intel_adsp_ipc.h +++ b/soc/xtensa/intel_adsp/common/include/intel_adsp_ipc.h @@ -7,10 +7,7 @@ #include #include #include -#ifdef CONFIG_PM_DEVICE_RUNTIME #include -#include -#endif struct intel_adsp_ipc_config { volatile struct intel_adsp_ipc *regs; diff --git a/soc/xtensa/intel_adsp/common/mem_window.c b/soc/xtensa/intel_adsp/common/mem_window.c index e101d03ec16..8ca591deb36 100644 --- a/soc/xtensa/intel_adsp/common/mem_window.c +++ b/soc/xtensa/intel_adsp/common/mem_window.c @@ -54,8 +54,9 @@ void mem_window_idle_exit(void) .mem_base = DT_REG_ADDR(DT_PHANDLE(MEM_WINDOW_NODE(n), memory)) + WIN_OFFSET(n), \ .initialize = DT_PROP(MEM_WINDOW_NODE(n), initialize), \ }; \ - DEVICE_DT_DEFINE(MEM_WINDOW_NODE(n), mem_win_init, NULL, NULL, &mem_win_config_##n, EARLY, \ - CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, NULL); + DEVICE_DT_DEFINE(MEM_WINDOW_NODE(n), mem_win_init, NULL, NULL, \ + &mem_win_config_##n, PRE_KERNEL_1, \ + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, NULL); #if DT_NODE_HAS_STATUS(MEM_WINDOW_NODE(0), okay) MEM_WINDOW_DEFINE(0) diff --git a/soc/xtensa/nxp_adsp/CMakeLists.txt b/soc/xtensa/nxp_adsp/CMakeLists.txt index f317b0b7054..a0ab21fb6a8 100644 --- a/soc/xtensa/nxp_adsp/CMakeLists.txt +++ b/soc/xtensa/nxp_adsp/CMakeLists.txt @@ -1,9 +1,14 @@ -# NXP i.MX8 SoC family CMake file +# NXP i.MX8/RT SoC family CMake file # # Copyright (c) 2021 NXP # SPDX-License-Identifier: Apache-2.0 +if(CONFIG_SOC_NXP_RT595) + zephyr_compile_definitions(CPU_MIMXRT595SFFOC_dsp) +endif() + add_subdirectory(common) +zephyr_include_directories(${SOC_SERIES}/include) # west sign @@ -18,3 +23,5 @@ add_custom_command( COMMAND west sign --if-tool-available --tool rimage --build-dir ${CMAKE_BINARY_DIR} ${WEST_SIGN_OPTS} DEPENDS ${CMAKE_BINARY_DIR}/zephyr/${KERNEL_ELF_NAME} ) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/${SOC_SERIES}/linker.ld CACHE INTERNAL "") diff --git a/soc/xtensa/nxp_adsp/Kconfig.defconfig b/soc/xtensa/nxp_adsp/Kconfig.defconfig index 4c8e3f9c83c..cdee20c75f5 100644 --- a/soc/xtensa/nxp_adsp/Kconfig.defconfig +++ b/soc/xtensa/nxp_adsp/Kconfig.defconfig @@ -1,9 +1,33 @@ -# NXP i.MX8 SoC family default configuration options +# NXP i.MX8/RT SoC family default configuration options # # Copyright (c) 2021 NXP # SPDX-License-Identifier: Apache-2.0 +if SOC_FAMILY_NXP_ADSP + source "soc/xtensa/nxp_adsp/*/Kconfig.defconfig.series" config CACHE_MANAGEMENT - def_bool y + default y + +config SMP + default n + +config XTENSA_TIMER + default y + +config KERNEL_ENTRY + default "__start" + +config MULTI_LEVEL_INTERRUPTS + default n + +config 2ND_LEVEL_INTERRUPTS + default n + +# To prevent test uses TEST_LOGGING_MINIMAL +config TEST_LOGGING_DEFAULTS + default n + depends on TEST + +endif diff --git a/soc/xtensa/nxp_adsp/common/CMakeLists.txt b/soc/xtensa/nxp_adsp/common/CMakeLists.txt index 8d6294a6777..02c2ef503e3 100644 --- a/soc/xtensa/nxp_adsp/common/CMakeLists.txt +++ b/soc/xtensa/nxp_adsp/common/CMakeLists.txt @@ -3,10 +3,11 @@ # Copyright (c) 2021 NXP # SPDX-License-Identifier: Apache-2.0 +zephyr_include_directories(include) + zephyr_interface_library_named(NXP_ADSP_COMMON) zephyr_library_named(nxp_adsp_common) -zephyr_library_include_directories(include) zephyr_library_include_directories(${ZEPHYR_BASE}/drivers) zephyr_library_sources(soc.c) diff --git a/soc/xtensa/nxp_adsp/imx8/Kconfig.defconfig.imx8qm b/soc/xtensa/nxp_adsp/imx8/Kconfig.defconfig.imx8qm new file mode 100644 index 00000000000..e678be83592 --- /dev/null +++ b/soc/xtensa/nxp_adsp/imx8/Kconfig.defconfig.imx8qm @@ -0,0 +1,9 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +if SOC_MIMX8QM_ADSP + +config SOC + default "mimx8qm6" + +endif # SOC_MIMX8QM_ADSP diff --git a/soc/xtensa/nxp_adsp/imx8/Kconfig.defconfig.imx8qxp b/soc/xtensa/nxp_adsp/imx8/Kconfig.defconfig.imx8qxp new file mode 100644 index 00000000000..e4fcdd92fd0 --- /dev/null +++ b/soc/xtensa/nxp_adsp/imx8/Kconfig.defconfig.imx8qxp @@ -0,0 +1,9 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +if SOC_MIMX8QXP_ADSP + +config SOC + default "mimx8qx6" + +endif # SOC_MIMX8QXP_ADSP diff --git a/soc/xtensa/nxp_adsp/imx8/Kconfig.defconfig.series b/soc/xtensa/nxp_adsp/imx8/Kconfig.defconfig.series index 7431522e867..a5f4597f069 100644 --- a/soc/xtensa/nxp_adsp/imx8/Kconfig.defconfig.series +++ b/soc/xtensa/nxp_adsp/imx8/Kconfig.defconfig.series @@ -11,40 +11,18 @@ config SOC_TOOLCHAIN_NAME string default "nxp_imx_adsp" -config SOC - string - default "nxp_imx8" - -config SMP - default n - -config XTENSA_TIMER - default y - config SYS_CLOCK_HW_CYCLES_PER_SEC default 666000000 if XTENSA_TIMER config SYS_CLOCK_TICKS_PER_SEC default 50000 -config KERNEL_ENTRY - default "__start" +config DCACHE_LINE_SIZE + default 128 -config MULTI_LEVEL_INTERRUPTS +config GEN_IRQ_VECTOR_TABLE default n -config 2ND_LEVEL_INTERRUPTS - default n - -config DYNAMIC_INTERRUPTS - default y - -config LOG - default y - -# To prevent test uses TEST_LOGGING_MINIMAL -config TEST_LOGGING_DEFAULTS - default n - depends on TEST +source "soc/xtensa/nxp_adsp/imx8/Kconfig.defconfig.imx8q*" endif # SOC_SERIES_NXP_IMX8 diff --git a/soc/xtensa/nxp_adsp/imx8/Kconfig.series b/soc/xtensa/nxp_adsp/imx8/Kconfig.series index 396607a4847..003784e842b 100644 --- a/soc/xtensa/nxp_adsp/imx8/Kconfig.series +++ b/soc/xtensa/nxp_adsp/imx8/Kconfig.series @@ -9,5 +9,7 @@ config SOC_SERIES_NXP_IMX8 select XTENSA_RESET_VECTOR select XTENSA_USE_CORE_CRT1 select ATOMIC_OPERATIONS_BUILTIN + select GEN_ISR_TABLES + select XTENSA_SMALL_VECTOR_TABLE_ENTRY help NXP i.MX8 diff --git a/soc/xtensa/nxp_adsp/imx8/Kconfig.soc b/soc/xtensa/nxp_adsp/imx8/Kconfig.soc index 16c36eb8a6e..33794a85c2b 100644 --- a/soc/xtensa/nxp_adsp/imx8/Kconfig.soc +++ b/soc/xtensa/nxp_adsp/imx8/Kconfig.soc @@ -3,9 +3,26 @@ choice prompt "NXP i.MX SoC Selection" + depends on SOC_SERIES_NXP_IMX8 - config SOC_NXP_IMX8 - bool "i.MX8 SoC" + config SOC_MIMX8QM_ADSP + bool "NXP i.MX8QM Audio DSP" depends on SOC_SERIES_NXP_IMX8 + select HAS_MCUX + config SOC_MIMX8QXP_ADSP + bool "NXP i.MX8QXP Audio DSP" + depends on SOC_SERIES_NXP_IMX8 + select HAS_MCUX endchoice + +if SOC_SERIES_NXP_IMX8 + +config SOC_PART_NUMBER + string + default SOC_PART_NUMBER_MIMX8QM_DSP if SOC_MIMX8QM_ADSP + default SOC_PART_NUMBER_MIMX8QXP_DSP if SOC_MIMX8QXP_ADSP + +source "soc/xtensa/nxp_adsp/imx8/Kconfig.soc.imx8q*" + +endif # SOC_SERIES_NXP_IMX8 diff --git a/soc/xtensa/nxp_adsp/imx8/Kconfig.soc.imx8qm b/soc/xtensa/nxp_adsp/imx8/Kconfig.soc.imx8qm new file mode 100644 index 00000000000..fd5334cfee5 --- /dev/null +++ b/soc/xtensa/nxp_adsp/imx8/Kconfig.soc.imx8qm @@ -0,0 +1,17 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +if SOC_MIMX8QM_ADSP + +config SOC_PART_NUMBER_MIMX8QM6AVUFF + bool + +config SOC_PART_NUMBER_MIMX8QM_DSP + string + default "MIMX8QM6AVUFF_dsp" if SOC_PART_NUMBER_MIMX8QM6AVUFF + help + This string holds the full part number of the SoC. It is a hidden + option that you should not set directly. The part number selection + choice defines the default value for this string. + +endif # SOC_MIMX8QM_ADSP diff --git a/soc/xtensa/nxp_adsp/imx8/Kconfig.soc.imx8qxp b/soc/xtensa/nxp_adsp/imx8/Kconfig.soc.imx8qxp new file mode 100644 index 00000000000..20f0a13e117 --- /dev/null +++ b/soc/xtensa/nxp_adsp/imx8/Kconfig.soc.imx8qxp @@ -0,0 +1,21 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +if SOC_MIMX8QXP_ADSP + +config SOC_PART_NUMBER_MIMX8QX6AVLFZ + bool + +config SOC_PART_NUMBER_MIMX8QX6CVLDZ + bool + +config SOC_PART_NUMBER_MIMX8QXP_DSP + string + default "MIMX8QX6AVLFZ_dsp" if SOC_PART_NUMBER_MIMX8QX6AVLFZ + default "MIMX8QX6CVLDZ_dsp" if SOC_PART_NUMBER_MIMX8QX6CVLDZ + help + This string holds the full part number of the SoC. It is a hidden + option that you should not set directly. The part number selection + choice defines the default value for this string. + +endif # SOC_MIMX8QXP_ADSP diff --git a/soc/xtensa/nxp_adsp/imx8/include/memory.h b/soc/xtensa/nxp_adsp/imx8/include/memory.h new file mode 100644 index 00000000000..56bac21c780 --- /dev/null +++ b/soc/xtensa/nxp_adsp/imx8/include/memory.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2021 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_NXP_ADSP_MEMORY_H_ +#define ZEPHYR_SOC_NXP_ADSP_MEMORY_H_ + +#define IRAM_RESERVE_HEADER_SPACE 0x400 + +#define IRAM_BASE 0x596f8000 +#define IRAM_SIZE 0x800 + +#define SDRAM0_BASE 0x92400000 +#define SDRAM0_SIZE 0x800000 + +#define SDRAM1_BASE 0x92C00000 +#define SDRAM1_SIZE 0x800000 + +/* The reset vector address in SRAM and its size */ +#define MEM_RESET_TEXT_SIZE 0x2e0 +#define MEM_RESET_LIT_SIZE 0x120 + +/* This is the base address of all the vectors defined in IRAM */ +#define XCHAL_VECBASE_RESET_PADDR_IRAM \ + (IRAM_BASE + IRAM_RESERVE_HEADER_SPACE) + +#define MEM_VECBASE_LIT_SIZE 0x178 + +/* + * EXCEPTIONS and VECTORS + */ +#define XCHAL_RESET_VECTOR0_PADDR_IRAM 0x596F8000 + +/* Vector and literal sizes */ +#define MEM_VECT_LIT_SIZE 0x4 +#define MEM_VECT_TEXT_SIZE 0x1C +#define MEM_VECT_SIZE (MEM_VECT_TEXT_SIZE +\ + MEM_VECT_LIT_SIZE) + +/* The addresses of the vectors. + * Only the mem_error vector continues to point to its ROM address. + */ +#define XCHAL_INTLEVEL2_VECTOR_PADDR_IRAM \ + (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x17C) + +#define XCHAL_INTLEVEL3_VECTOR_PADDR_IRAM \ + (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x19C) + +#define XCHAL_INTLEVEL4_VECTOR_PADDR_IRAM \ + (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x1BC) + +#define XCHAL_INTLEVEL5_VECTOR_PADDR_IRAM \ + (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x1DC) + +#define XCHAL_KERNEL_VECTOR_PADDR_IRAM \ + (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x1FC) + +#define XCHAL_USER_VECTOR_PADDR_IRAM \ + (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x21C) + +#define XCHAL_DOUBLEEXC_VECTOR_PADDR_IRAM \ + (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x23C) + +/* Location for the intList section which is later used to construct the + * Interrupt Descriptor Table (IDT). This is a bogus address as this + * section will be stripped off in the final image. + */ +#define IDT_BASE (IRAM_BASE + IRAM_SIZE) + +/* size of the Interrupt Descriptor Table (IDT) */ +#define IDT_SIZE 0x2000 + +/* physical DSP addresses */ +#define IRAM_BASE 0x596f8000 +#define IRAM_SIZE 0x800 + +#define DRAM0_BASE 0x596e8000 +#define DRAM0_SIZE 0x8000 + +#define DRAM1_BASE 0x596f0000 +#define DRAM1_SIZE 0x8000 + +#define SDRAM0_BASE 0x92400000 +#define SDRAM0_SIZE 0x800000 + +#define SDRAM1_BASE 0x92C00000 +#define SDRAM1_SIZE 0x800000 + +#define XSHAL_MU13_SIDEB_BYPASS_PADDR 0x5D310000 +#define MU_BASE XSHAL_MU13_SIDEB_BYPASS_PADDR + +#define EDMA0_BASE 0x59200000 +#define EDMA0_SIZE 0x10000 + +#define ESAI_BASE 0x59010000 +#define ESAI_SIZE 0x00010000 + +#define SAI_1_BASE 0x59050000 +#define SAI_1_SIZE 0x00010000 + +#define UUID_ENTRY_ELF_BASE 0x1FFFA000 +#define UUID_ENTRY_ELF_SIZE 0x6000 + +#define LOG_ENTRY_ELF_BASE 0x20000000 +#define LOG_ENTRY_ELF_SIZE 0x2000000 + +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE 0x2000000 + +/* + * The Heap and Stack on i.MX8 are organized like this :- + * + * +--------------------------------------------------------------------------+ + * | Offset | Region | Size | + * +---------------------+----------------+-----------------------------------+ + * | SDRAM_BASE | RO Data | SOF_DATA_SIZE | + * | | Data | | + * | | BSS | | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_SYSTEM_BASE | System Heap | HEAP_SYSTEM_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_RUNTIME_BASE | Runtime Heap | HEAP_RUNTIME_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_BUFFER_BASE | Module Buffers | HEAP_BUFFER_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SOF_STACK_END | Stack | SOF_STACK_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SOF_STACK_BASE | | | + * +---------------------+----------------+-----------------------------------+ + */ + +#define SRAM_OUTBOX_BASE SDRAM1_BASE +#define SRAM_OUTBOX_SIZE 0x1000 +#define SRAM_OUTBOX_OFFSET 0 + +#define SRAM_INBOX_BASE (SRAM_OUTBOX_BASE + SRAM_OUTBOX_SIZE) +#define SRAM_INBOX_SIZE 0x1000 +#define SRAM_INBOX_OFFSET SRAM_OUTBOX_SIZE + +#define SRAM_DEBUG_BASE (SRAM_INBOX_BASE + SRAM_INBOX_SIZE) +#define SRAM_DEBUG_SIZE 0x800 +#define SRAM_DEBUG_OFFSET (SRAM_INBOX_OFFSET + SRAM_INBOX_SIZE) + +#define SRAM_EXCEPT_BASE (SRAM_DEBUG_BASE + SRAM_DEBUG_SIZE) +#define SRAM_EXCEPT_SIZE 0x800 +#define SRAM_EXCEPT_OFFSET (SRAM_DEBUG_OFFSET + SRAM_DEBUG_SIZE) + +#define SRAM_STREAM_BASE (SRAM_EXCEPT_BASE + SRAM_EXCEPT_SIZE) +#define SRAM_STREAM_SIZE 0x1000 +#define SRAM_STREAM_OFFSET (SRAM_EXCEPT_OFFSET + SRAM_EXCEPT_SIZE) + +#define SRAM_TRACE_BASE (SRAM_STREAM_BASE + SRAM_STREAM_SIZE) +#define SRAM_TRACE_SIZE 0x1000 +#define SRAM_TRACE_OFFSET (SRAM_STREAM_OFFSET + SRAM_STREAM_SIZE) + +#define SOF_MAILBOX_SIZE (SRAM_INBOX_SIZE + SRAM_OUTBOX_SIZE \ + + SRAM_DEBUG_SIZE + SRAM_EXCEPT_SIZE \ + + SRAM_STREAM_SIZE + SRAM_TRACE_SIZE) + +#endif /* ZEPHYR_SOC_NXP_ADSP_MEMORY_H_ */ diff --git a/soc/xtensa/nxp_adsp/imx8/include/soc/memory.h b/soc/xtensa/nxp_adsp/imx8/include/soc/memory.h deleted file mode 100644 index ee4785995a8..00000000000 --- a/soc/xtensa/nxp_adsp/imx8/include/soc/memory.h +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (c) 2021 NXP - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __INC_MEMORY_H -#define __INC_MEMORY_H - -#define PLATFORM_CORE_COUNT 1 - -/** Id of master DSP core */ -#define PLATFORM_PRIMARY_CORE_ID 0 - -#define IRAM_RESERVE_HEADER_SPACE 0x400 - -#define IRAM_BASE 0x596f8000 -#define IRAM_SIZE 0x800 - -#define SDRAM0_BASE 0x92400000 -#define SDRAM0_SIZE 0x800000 - -#define SDRAM1_BASE 0x92C00000 -#define SDRAM1_SIZE 0x800000 - -/* The reset vector address in SRAM and its size */ -#define MEM_RESET_TEXT_SIZE 0x2e0 -#define MEM_RESET_LIT_SIZE 0x120 - -/* This is the base address of all the vectors defined in IRAM */ -#define XCHAL_VECBASE_RESET_PADDR_IRAM \ - (IRAM_BASE + IRAM_RESERVE_HEADER_SPACE) - -#define MEM_VECBASE_LIT_SIZE 0x178 - -/* - * EXCEPTIONS and VECTORS - */ -#define XCHAL_RESET_VECTOR0_PADDR_IRAM 0x596F8000 - -/* Vector and literal sizes */ -#define MEM_VECT_LIT_SIZE 0x4 -#define MEM_VECT_TEXT_SIZE 0x1C -#define MEM_VECT_SIZE (MEM_VECT_TEXT_SIZE +\ - MEM_VECT_LIT_SIZE) - -/* The addresses of the vectors. - * Only the mem_error vector continues to point to its ROM address. - */ -#define XCHAL_INTLEVEL2_VECTOR_PADDR_IRAM \ - (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x17C) - -#define XCHAL_INTLEVEL3_VECTOR_PADDR_IRAM \ - (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x19C) - -#define XCHAL_INTLEVEL4_VECTOR_PADDR_IRAM \ - (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x1BC) - -#define XCHAL_INTLEVEL5_VECTOR_PADDR_IRAM \ - (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x1DC) - -#define XCHAL_KERNEL_VECTOR_PADDR_IRAM \ - (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x1FC) - -#define XCHAL_USER_VECTOR_PADDR_IRAM \ - (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x21C) - -#define XCHAL_DOUBLEEXC_VECTOR_PADDR_IRAM \ - (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x23C) - -/* Location for the intList section which is later used to construct the - * Interrupt Descriptor Table (IDT). This is a bogus address as this - * section will be stripped off in the final image. - */ -#define IDT_BASE (IRAM_BASE + IRAM_SIZE) - -/* size of the Interrupt Descriptor Table (IDT) */ -#define IDT_SIZE 0x2000 - -/* physical DSP addresses */ -#define IRAM_BASE 0x596f8000 -#define IRAM_SIZE 0x800 - -#define DRAM0_BASE 0x596e8000 -#define DRAM0_SIZE 0x8000 - -#define DRAM1_BASE 0x596f0000 -#define DRAM1_SIZE 0x8000 - -#define SDRAM0_BASE 0x92400000 -#define SDRAM0_SIZE 0x800000 - -#define SDRAM1_BASE 0x92C00000 -#define SDRAM1_SIZE 0x800000 - -#define XSHAL_MU13_SIDEB_BYPASS_PADDR 0x5D310000 -#define MU_BASE XSHAL_MU13_SIDEB_BYPASS_PADDR - -#define EDMA0_BASE 0x59200000 -#define EDMA0_SIZE 0x10000 - -#define ESAI_BASE 0x59010000 -#define ESAI_SIZE 0x00010000 - -#define SAI_1_BASE 0x59050000 -#define SAI_1_SIZE 0x00010000 - -#define UUID_ENTRY_ELF_BASE 0x1FFFA000 -#define UUID_ENTRY_ELF_SIZE 0x6000 - -#define LOG_ENTRY_ELF_BASE 0x20000000 -#define LOG_ENTRY_ELF_SIZE 0x2000000 - -#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) -#define EXT_MANIFEST_ELF_SIZE 0x2000000 - -/* - * The Heap and Stack on i.MX8 are organized like this :- - * - * +--------------------------------------------------------------------------+ - * | Offset | Region | Size | - * +---------------------+----------------+-----------------------------------+ - * | SDRAM_BASE | RO Data | SOF_DATA_SIZE | - * | | Data | | - * | | BSS | | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_SYSTEM_BASE | System Heap | HEAP_SYSTEM_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_RUNTIME_BASE | Runtime Heap | HEAP_RUNTIME_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_BUFFER_BASE | Module Buffers | HEAP_BUFFER_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | SOF_STACK_END | Stack | SOF_STACK_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | SOF_STACK_BASE | | | - * +---------------------+----------------+-----------------------------------+ - */ - -#define SRAM_OUTBOX_BASE SDRAM1_BASE -#define SRAM_OUTBOX_SIZE 0x1000 -#define SRAM_OUTBOX_OFFSET 0 - -#define SRAM_INBOX_BASE (SRAM_OUTBOX_BASE + SRAM_OUTBOX_SIZE) -#define SRAM_INBOX_SIZE 0x1000 -#define SRAM_INBOX_OFFSET SRAM_OUTBOX_SIZE - -#define SRAM_DEBUG_BASE (SRAM_INBOX_BASE + SRAM_INBOX_SIZE) -#define SRAM_DEBUG_SIZE 0x800 -#define SRAM_DEBUG_OFFSET (SRAM_INBOX_OFFSET + SRAM_INBOX_SIZE) - -#define SRAM_EXCEPT_BASE (SRAM_DEBUG_BASE + SRAM_DEBUG_SIZE) -#define SRAM_EXCEPT_SIZE 0x800 -#define SRAM_EXCEPT_OFFSET (SRAM_DEBUG_OFFSET + SRAM_DEBUG_SIZE) - -#define SRAM_STREAM_BASE (SRAM_EXCEPT_BASE + SRAM_EXCEPT_SIZE) -#define SRAM_STREAM_SIZE 0x1000 -#define SRAM_STREAM_OFFSET (SRAM_EXCEPT_OFFSET + SRAM_EXCEPT_SIZE) - -#define SRAM_TRACE_BASE (SRAM_STREAM_BASE + SRAM_STREAM_SIZE) -#define SRAM_TRACE_SIZE 0x1000 -#define SRAM_TRACE_OFFSET (SRAM_STREAM_OFFSET + SRAM_STREAM_SIZE) - -#define SOF_MAILBOX_SIZE (SRAM_INBOX_SIZE + SRAM_OUTBOX_SIZE \ - + SRAM_DEBUG_SIZE + SRAM_EXCEPT_SIZE \ - + SRAM_STREAM_SIZE + SRAM_TRACE_SIZE) - -/* Heap section sizes for module pool */ -#define HEAP_RT_COUNT8 0 -#define HEAP_RT_COUNT16 48 -#define HEAP_RT_COUNT32 48 -#define HEAP_RT_COUNT64 32 -#define HEAP_RT_COUNT128 32 -#define HEAP_RT_COUNT256 32 -#define HEAP_RT_COUNT512 4 -#define HEAP_RT_COUNT1024 4 -#define HEAP_RT_COUNT2048 4 - -/* Heap section sizes for system runtime heap */ -#define HEAP_SYS_RT_COUNT64 128 -#define HEAP_SYS_RT_COUNT512 16 -#define HEAP_SYS_RT_COUNT1024 8 - -/* Heap configuration */ -#define HEAP_SYSTEM_BASE SDRAM1_BASE + SOF_MAILBOX_SIZE -#define HEAP_SYSTEM_SIZE 0xe000 - -#define HEAP_SYS_RUNTIME_BASE (HEAP_SYSTEM_BASE + HEAP_SYSTEM_SIZE) -#define HEAP_SYS_RUNTIME_SIZE \ - (HEAP_SYS_RT_COUNT64 * 64 + HEAP_SYS_RT_COUNT512 * 512 + \ - HEAP_SYS_RT_COUNT1024 * 1024) - -#define HEAP_RUNTIME_BASE (HEAP_SYS_RUNTIME_BASE + HEAP_SYS_RUNTIME_SIZE) -#define HEAP_RUNTIME_SIZE \ - (HEAP_RT_COUNT8 * 8 + HEAP_RT_COUNT16 * 16 + \ - HEAP_RT_COUNT32 * 32 + HEAP_RT_COUNT64 * 64 + \ - HEAP_RT_COUNT128 * 128 + HEAP_RT_COUNT256 * 256 + \ - HEAP_RT_COUNT512 * 512 + HEAP_RT_COUNT1024 * 1024 + \ - HEAP_RT_COUNT2048 * 2048) - -#define HEAP_BUFFER_BASE (HEAP_RUNTIME_BASE + HEAP_RUNTIME_SIZE) -#define HEAP_BUFFER_SIZE \ - (SDRAM1_SIZE - SOF_MAILBOX_SIZE - HEAP_RUNTIME_SIZE - SOF_STACK_TOTAL_SIZE -\ - HEAP_SYS_RUNTIME_SIZE - HEAP_SYSTEM_SIZE) - -/* Stack configuration */ -#define SOF_STACK_SIZE 0x1000 -#define SOF_STACK_TOTAL_SIZE SOF_STACK_SIZE -#define SOF_STACK_BASE (SDRAM1_BASE + SDRAM1_SIZE) -#define SOF_STACK_END (SOF_STACK_BASE - SOF_STACK_TOTAL_SIZE) - -/* Host page size */ -#define HOST_PAGE_SIZE 4096 - -#endif /* __INC_MEMORY_H */ diff --git a/soc/xtensa/nxp_adsp/imx8/include/soc/platform.h b/soc/xtensa/nxp_adsp/imx8/include/soc/platform.h deleted file mode 100644 index 44d8f46d1d4..00000000000 --- a/soc/xtensa/nxp_adsp/imx8/include/soc/platform.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2021 NXP - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __PLATFORM_PLATFORM_H__ -#define __PLATFORM_PLATFORM_H__ - -#define PLATFORM_PRIMARY_CORE_ID 0 - -#define MAX_CORE_COUNT 1 - -#if PLATFORM_CORE_COUNT > MAX_CORE_COUNT -#error "Invalid core count - exceeding core limit" -/* IPC Interrupt */ -#define PLATFORM_IPC_INTERRUPT IRQ_NUM_MU -#define PLATFORM_IPC_INTERRUPT_NAME NULL -#endif - -#endif /* __PLATFORM_PLATFORM_H__ */ diff --git a/soc/xtensa/nxp_adsp/imx8/linker.ld b/soc/xtensa/nxp_adsp/imx8/linker.ld index 599ef7339b8..52d3a46b238 100644 --- a/soc/xtensa/nxp_adsp/imx8/linker.ld +++ b/soc/xtensa/nxp_adsp/imx8/linker.ld @@ -15,7 +15,7 @@ OUTPUT_ARCH(xtensa) #include #include -#include +#include #include #include @@ -346,7 +346,7 @@ SECTIONS .text : ALIGN(4) { _stext = .; - _text_start = ABSOLUTE(.); + __text_region_start = ABSOLUTE(.); KEEP (*(.ResetVector.text)) *(.ResetVector.literal) *(.entry.text) @@ -356,7 +356,7 @@ SECTIONS *(.fini.literal) KEEP(*(.fini)) *(.gnu.version) - _text_end = ABSOLUTE(.); + __text_region_end = ABSOLUTE(.); _etext = .; } >sdram0 :sdram0_phdr diff --git a/soc/xtensa/nxp_adsp/imx8/pinctrl_soc.h b/soc/xtensa/nxp_adsp/imx8/pinctrl_soc.h new file mode 100644 index 00000000000..ac748220b56 --- /dev/null +++ b/soc/xtensa/nxp_adsp/imx8/pinctrl_soc.h @@ -0,0 +1,41 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_XTENSA_NXP_ADSP_IMX8_PINCTRL_SOC_H_ +#define ZEPHYR_SOC_XTENSA_NXP_ADSP_IMX8_PINCTRL_SOC_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct pinctrl_soc_pinmux { + uint32_t pad; + uint32_t mux; +}; + +typedef struct pinctrl_soc_pinmux pinctrl_soc_pin_t; + +#define IMX8_PINMUX(n) \ +{ \ + .pad = DT_PROP_BY_IDX(n, pinmux, 0), \ + .mux = DT_PROP_BY_IDX(n, pinmux, 1), \ +}, + +#define Z_PINCTRL_PINMUX(group_id, pin_prop, idx)\ + IMX8_PINMUX(DT_PHANDLE_BY_IDX(group_id, pin_prop, idx)) + +#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \ + { DT_FOREACH_CHILD_VARGS(DT_PHANDLE(node_id, prop), \ + DT_FOREACH_PROP_ELEM, pinmux, Z_PINCTRL_PINMUX) }; + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_SOC_XTENSA_NXP_ADSP_IMX8_PINCTRL_SOC_H_ */ diff --git a/soc/xtensa/nxp_adsp/imx8m/Kconfig.defconfig.series b/soc/xtensa/nxp_adsp/imx8m/Kconfig.defconfig.series index 03967cb74e4..2d00a5e93d9 100644 --- a/soc/xtensa/nxp_adsp/imx8m/Kconfig.defconfig.series +++ b/soc/xtensa/nxp_adsp/imx8m/Kconfig.defconfig.series @@ -11,44 +11,27 @@ config SOC_TOOLCHAIN_NAME string default "nxp_imx8m_adsp" -# if SOC_MIMX8M_ADSP +if SOC_MIMX8M_ADSP config SOC string default "mimx8ml8" -config SMP - default n - -config XTENSA_TIMER - default y - config SYS_CLOCK_HW_CYCLES_PER_SEC default 800000000 if XTENSA_TIMER config SYS_CLOCK_TICKS_PER_SEC default 50000 -config KERNEL_ENTRY - default "__start" - -config MULTI_LEVEL_INTERRUPTS - default n - -config 2ND_LEVEL_INTERRUPTS - default n +config DCACHE_LINE_SIZE + default 128 config DYNAMIC_INTERRUPTS default y -config LOG - default y - -# To prevent test uses TEST_LOGGING_MINIMAL -config TEST_LOGGING_DEFAULTS +config GEN_IRQ_VECTOR_TABLE default n - depends on TEST -# endif # SOC_MIMX8M_ADSP +endif # SOC_MIMX8M_ADSP endif # SOC_SERIES_NXP_IMX8M diff --git a/soc/xtensa/nxp_adsp/imx8m/Kconfig.series b/soc/xtensa/nxp_adsp/imx8m/Kconfig.series index eda7d03ae5e..3847f52d2da 100644 --- a/soc/xtensa/nxp_adsp/imx8m/Kconfig.series +++ b/soc/xtensa/nxp_adsp/imx8m/Kconfig.series @@ -9,5 +9,7 @@ config SOC_SERIES_NXP_IMX8M select XTENSA_RESET_VECTOR select XTENSA_USE_CORE_CRT1 select ATOMIC_OPERATIONS_BUILTIN + select GEN_ISR_TABLES + select XTENSA_SMALL_VECTOR_TABLE_ENTRY help Enable support for NXP i.MX8M Audio DSP diff --git a/soc/xtensa/nxp_adsp/imx8m/include/memory.h b/soc/xtensa/nxp_adsp/imx8m/include/memory.h new file mode 100644 index 00000000000..e882f49a435 --- /dev/null +++ b/soc/xtensa/nxp_adsp/imx8m/include/memory.h @@ -0,0 +1,169 @@ +/* + * Copyright 2021, 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_NXP_ADSP_MEMORY_H_ +#define ZEPHYR_SOC_NXP_ADSP_MEMORY_H_ + +#define PLATFORM_CORE_COUNT 1 + +/** Id of master DSP core */ +#define PLATFORM_PRIMARY_CORE_ID 0 + +#define IRAM_RESERVE_HEADER_SPACE 0x400 + +#define IRAM_BASE 0x3B6F8000 +#define IRAM_SIZE 0x800 + +#define SDRAM0_BASE 0x92400000 +#define SDRAM0_SIZE 0x800000 + +#define SDRAM1_BASE 0x92C00000 +#define SDRAM1_SIZE 0x800000 + +/* The reset vector address in SRAM and its size */ +#define MEM_RESET_TEXT_SIZE 0x2E0 +#define MEM_RESET_LIT_SIZE 0x120 + +/* This is the base address of all the vectors defined in IRAM */ +#define XCHAL_VECBASE_RESET_PADDR_IRAM \ + (IRAM_BASE + IRAM_RESERVE_HEADER_SPACE) + +#define MEM_VECBASE_LIT_SIZE 0x178 + +/* + * EXCEPTIONS and VECTORS + */ +#define XCHAL_RESET_VECTOR0_PADDR_IRAM 0x3B6F8000 + +/* Vector and literal sizes */ +#define MEM_VECT_LIT_SIZE 0x4 +#define MEM_VECT_TEXT_SIZE 0x1C +#define MEM_VECT_SIZE (MEM_VECT_TEXT_SIZE +\ + MEM_VECT_LIT_SIZE) + +/* The addresses of the vectors. + * Only the mem_error vector continues to point to its ROM address. + */ +#define XCHAL_INTLEVEL2_VECTOR_PADDR_IRAM \ + (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x17C) + +#define XCHAL_INTLEVEL3_VECTOR_PADDR_IRAM \ + (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x19C) + +#define XCHAL_INTLEVEL4_VECTOR_PADDR_IRAM \ + (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x1BC) + +#define XCHAL_INTLEVEL5_VECTOR_PADDR_IRAM \ + (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x1DC) + +#define XCHAL_KERNEL_VECTOR_PADDR_IRAM \ + (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x1FC) + +#define XCHAL_USER_VECTOR_PADDR_IRAM \ + (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x21C) + +#define XCHAL_DOUBLEEXC_VECTOR_PADDR_IRAM \ + (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x23C) + +/* Location for the intList section which is later used to construct the + * Interrupt Descriptor Table (IDT). This is a bogus address as this + * section will be stripped off in the final image. + */ +#define IDT_BASE (IRAM_BASE + IRAM_SIZE) + +/* size of the Interrupt Descriptor Table (IDT) */ +#define IDT_SIZE 0x2000 + +/* physical DSP addresses */ +#define IRAM_BASE 0x3B6F8000 +#define IRAM_SIZE 0x800 + +#define DRAM0_BASE 0x3B6E8000 +#define DRAM0_SIZE 0x8000 + +#define DRAM1_BASE 0x3B6F0000 +#define DRAM1_SIZE 0x8000 + +#define SDRAM0_BASE 0x92400000 +#define SDRAM0_SIZE 0x800000 + +#define SDRAM1_BASE 0x92C00000 +#define SDRAM1_SIZE 0x800000 + +#define XSHAL_MU2_SIDEB_BYPASS_PADDR 0x30E70000 +#define MU_BASE XSHAL_MU2_SIDEB_BYPASS_PADDR + +#define SDMA2_BASE 0x30E10000 +#define SDMA2_SIZE 0x10000 + +#define SDMA3_BASE 0x30E00000 +#define SDMA3_SIZE 0x10000 + +#define SAI_1_BASE 0x30C10000 +#define SAI_1_SIZE 0x00010000 + +#define SAI_3_BASE 0x30C30000 +#define SAI_3_SIZE 0x00010000 +#define UUID_ENTRY_ELF_BASE 0x1FFFA000 +#define UUID_ENTRY_ELF_SIZE 0x6000 + +#define LOG_ENTRY_ELF_BASE 0x20000000 +#define LOG_ENTRY_ELF_SIZE 0x2000000 + +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE 0x2000000 + +/* + * The Heap and Stack on i.MX8 are organized like this :- + * + * +--------------------------------------------------------------------------+ + * | Offset | Region | Size | + * +---------------------+----------------+-----------------------------------+ + * | SDRAM_BASE | RO Data | SOF_DATA_SIZE | + * | | Data | | + * | | BSS | | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_SYSTEM_BASE | System Heap | HEAP_SYSTEM_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_RUNTIME_BASE | Runtime Heap | HEAP_RUNTIME_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_BUFFER_BASE | Module Buffers | HEAP_BUFFER_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SOF_STACK_END | Stack | SOF_STACK_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SOF_STACK_BASE | | | + * +---------------------+----------------+-----------------------------------+ + */ + +#define SRAM_OUTBOX_BASE SDRAM1_BASE +#define SRAM_OUTBOX_SIZE 0x1000 +#define SRAM_OUTBOX_OFFSET 0 + +#define SRAM_INBOX_BASE (SRAM_OUTBOX_BASE + SRAM_OUTBOX_SIZE) +#define SRAM_INBOX_SIZE 0x1000 +#define SRAM_INBOX_OFFSET SRAM_OUTBOX_SIZE + +#define SRAM_DEBUG_BASE (SRAM_INBOX_BASE + SRAM_INBOX_SIZE) +#define SRAM_DEBUG_SIZE 0x800 +#define SRAM_DEBUG_OFFSET (SRAM_INBOX_OFFSET + SRAM_INBOX_SIZE) + +#define SRAM_EXCEPT_BASE (SRAM_DEBUG_BASE + SRAM_DEBUG_SIZE) +#define SRAM_EXCEPT_SIZE 0x800 +#define SRAM_EXCEPT_OFFSET (SRAM_DEBUG_OFFSET + SRAM_DEBUG_SIZE) + +#define SRAM_STREAM_BASE (SRAM_EXCEPT_BASE + SRAM_EXCEPT_SIZE) +#define SRAM_STREAM_SIZE 0x1000 +#define SRAM_STREAM_OFFSET (SRAM_EXCEPT_OFFSET + SRAM_EXCEPT_SIZE) + +#define SRAM_TRACE_BASE (SRAM_STREAM_BASE + SRAM_STREAM_SIZE) +#define SRAM_TRACE_SIZE 0x1000 +#define SRAM_TRACE_OFFSET (SRAM_STREAM_OFFSET + SRAM_STREAM_SIZE) + +#define SOF_MAILBOX_SIZE (SRAM_INBOX_SIZE + SRAM_OUTBOX_SIZE \ + + SRAM_DEBUG_SIZE + SRAM_EXCEPT_SIZE \ + + SRAM_STREAM_SIZE + SRAM_TRACE_SIZE) + +#endif /* ZEPHYR_SOC_NXP_ADSP_MEMORY_H_ */ diff --git a/soc/xtensa/nxp_adsp/imx8m/include/soc/memory.h b/soc/xtensa/nxp_adsp/imx8m/include/soc/memory.h deleted file mode 100644 index e93617addb5..00000000000 --- a/soc/xtensa/nxp_adsp/imx8m/include/soc/memory.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2021 NXP - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __INC_MEMORY_H -#define __INC_MEMORY_H - -#define PLATFORM_CORE_COUNT 1 - -/** Id of master DSP core */ -#define PLATFORM_PRIMARY_CORE_ID 0 - -#define IRAM_RESERVE_HEADER_SPACE 0x400 - -#define IRAM_BASE 0x3B6F8000 -#define IRAM_SIZE 0x800 - -#define SDRAM0_BASE 0x92400000 -#define SDRAM0_SIZE 0x800000 - -#define SDRAM1_BASE 0x92C00000 -#define SDRAM1_SIZE 0x800000 - -/* The reset vector address in SRAM and its size */ -#define MEM_RESET_TEXT_SIZE 0x2E0 -#define MEM_RESET_LIT_SIZE 0x120 - -/* This is the base address of all the vectors defined in IRAM */ -#define XCHAL_VECBASE_RESET_PADDR_IRAM \ - (IRAM_BASE + IRAM_RESERVE_HEADER_SPACE) - -#define MEM_VECBASE_LIT_SIZE 0x178 - -/* - * EXCEPTIONS and VECTORS - */ -#define XCHAL_RESET_VECTOR0_PADDR_IRAM 0x3B6F8000 - -/* Vector and literal sizes */ -#define MEM_VECT_LIT_SIZE 0x4 -#define MEM_VECT_TEXT_SIZE 0x1C -#define MEM_VECT_SIZE (MEM_VECT_TEXT_SIZE +\ - MEM_VECT_LIT_SIZE) - -/* The addresses of the vectors. - * Only the mem_error vector continues to point to its ROM address. - */ -#define XCHAL_INTLEVEL2_VECTOR_PADDR_IRAM \ - (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x17C) - -#define XCHAL_INTLEVEL3_VECTOR_PADDR_IRAM \ - (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x19C) - -#define XCHAL_INTLEVEL4_VECTOR_PADDR_IRAM \ - (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x1BC) - -#define XCHAL_INTLEVEL5_VECTOR_PADDR_IRAM \ - (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x1DC) - -#define XCHAL_KERNEL_VECTOR_PADDR_IRAM \ - (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x1FC) - -#define XCHAL_USER_VECTOR_PADDR_IRAM \ - (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x21C) - -#define XCHAL_DOUBLEEXC_VECTOR_PADDR_IRAM \ - (XCHAL_VECBASE_RESET_PADDR_IRAM + 0x23C) - -/* Location for the intList section which is later used to construct the - * Interrupt Descriptor Table (IDT). This is a bogus address as this - * section will be stripped off in the final image. - */ -#define IDT_BASE (IRAM_BASE + IRAM_SIZE) - -/* size of the Interrupt Descriptor Table (IDT) */ -#define IDT_SIZE 0x2000 - -/* physical DSP addresses */ -#define IRAM_BASE 0x3B6F8000 -#define IRAM_SIZE 0x800 - -#define DRAM0_BASE 0x3B6E8000 -#define DRAM0_SIZE 0x8000 - -#define DRAM1_BASE 0x3B6F0000 -#define DRAM1_SIZE 0x8000 - -#define SDRAM0_BASE 0x92400000 -#define SDRAM0_SIZE 0x800000 - -#define SDRAM1_BASE 0x92C00000 -#define SDRAM1_SIZE 0x800000 - -#define XSHAL_MU2_SIDEB_BYPASS_PADDR 0x30E70000 -#define MU_BASE XSHAL_MU2_SIDEB_BYPASS_PADDR - -#define SDMA2_BASE 0x30E10000 -#define SDMA2_SIZE 0x10000 - -#define SDMA3_BASE 0x30E00000 -#define SDMA3_SIZE 0x10000 - -#define SAI_1_BASE 0x30C10000 -#define SAI_1_SIZE 0x00010000 - -#define SAI_3_BASE 0x30C30000 -#define SAI_3_SIZE 0x00010000 -#define UUID_ENTRY_ELF_BASE 0x1FFFA000 -#define UUID_ENTRY_ELF_SIZE 0x6000 - -#define LOG_ENTRY_ELF_BASE 0x20000000 -#define LOG_ENTRY_ELF_SIZE 0x2000000 - -#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) -#define EXT_MANIFEST_ELF_SIZE 0x2000000 - -/* - * The Heap and Stack on i.MX8 are organized like this :- - * - * +--------------------------------------------------------------------------+ - * | Offset | Region | Size | - * +---------------------+----------------+-----------------------------------+ - * | SDRAM_BASE | RO Data | SOF_DATA_SIZE | - * | | Data | | - * | | BSS | | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_SYSTEM_BASE | System Heap | HEAP_SYSTEM_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_RUNTIME_BASE | Runtime Heap | HEAP_RUNTIME_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_BUFFER_BASE | Module Buffers | HEAP_BUFFER_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | SOF_STACK_END | Stack | SOF_STACK_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | SOF_STACK_BASE | | | - * +---------------------+----------------+-----------------------------------+ - */ - -#define SRAM_OUTBOX_BASE SDRAM1_BASE -#define SRAM_OUTBOX_SIZE 0x1000 -#define SRAM_OUTBOX_OFFSET 0 - -#define SRAM_INBOX_BASE (SRAM_OUTBOX_BASE + SRAM_OUTBOX_SIZE) -#define SRAM_INBOX_SIZE 0x1000 -#define SRAM_INBOX_OFFSET SRAM_OUTBOX_SIZE - -#define SRAM_DEBUG_BASE (SRAM_INBOX_BASE + SRAM_INBOX_SIZE) -#define SRAM_DEBUG_SIZE 0x800 -#define SRAM_DEBUG_OFFSET (SRAM_INBOX_OFFSET + SRAM_INBOX_SIZE) - -#define SRAM_EXCEPT_BASE (SRAM_DEBUG_BASE + SRAM_DEBUG_SIZE) -#define SRAM_EXCEPT_SIZE 0x800 -#define SRAM_EXCEPT_OFFSET (SRAM_DEBUG_OFFSET + SRAM_DEBUG_SIZE) - -#define SRAM_STREAM_BASE (SRAM_EXCEPT_BASE + SRAM_EXCEPT_SIZE) -#define SRAM_STREAM_SIZE 0x1000 -#define SRAM_STREAM_OFFSET (SRAM_EXCEPT_OFFSET + SRAM_EXCEPT_SIZE) - -#define SRAM_TRACE_BASE (SRAM_STREAM_BASE + SRAM_STREAM_SIZE) -#define SRAM_TRACE_SIZE 0x1000 -#define SRAM_TRACE_OFFSET (SRAM_STREAM_OFFSET + SRAM_STREAM_SIZE) - -#define SOF_MAILBOX_SIZE (SRAM_INBOX_SIZE + SRAM_OUTBOX_SIZE \ - + SRAM_DEBUG_SIZE + SRAM_EXCEPT_SIZE \ - + SRAM_STREAM_SIZE + SRAM_TRACE_SIZE) - -/* Heap section sizes for module pool */ -#define HEAP_RT_COUNT8 0 -#define HEAP_RT_COUNT16 48 -#define HEAP_RT_COUNT32 48 -#define HEAP_RT_COUNT64 32 -#define HEAP_RT_COUNT128 32 -#define HEAP_RT_COUNT256 32 -#define HEAP_RT_COUNT512 4 -#define HEAP_RT_COUNT1024 4 -#define HEAP_RT_COUNT2048 4 -#define HEAP_RT_COUNT4096 4 - -/* Heap section sizes for system runtime heap */ -#define HEAP_SYS_RT_COUNT64 128 -#define HEAP_SYS_RT_COUNT512 16 -#define HEAP_SYS_RT_COUNT1024 8 - -/* Heap configuration */ -#define HEAP_SYSTEM_BASE SDRAM1_BASE + SOF_MAILBOX_SIZE -#define HEAP_SYSTEM_SIZE 0xe000 -#define HEAP_SYSTEM_0_BASE HEAP_SYSTEM_BASE - -#define HEAP_SYS_RUNTIME_BASE (HEAP_SYSTEM_BASE + HEAP_SYSTEM_SIZE) -#define HEAP_SYS_RUNTIME_SIZE \ - (HEAP_SYS_RT_COUNT64 * 64 + HEAP_SYS_RT_COUNT512 * 512 + \ - HEAP_SYS_RT_COUNT1024 * 1024) - -#define HEAP_RUNTIME_BASE (HEAP_SYS_RUNTIME_BASE + HEAP_SYS_RUNTIME_SIZE) -#define HEAP_RUNTIME_SIZE \ - (HEAP_RT_COUNT8 * 8 + HEAP_RT_COUNT16 * 16 + \ - HEAP_RT_COUNT32 * 32 + HEAP_RT_COUNT64 * 64 + \ - HEAP_RT_COUNT128 * 128 + HEAP_RT_COUNT256 * 256 + \ - HEAP_RT_COUNT512 * 512 + HEAP_RT_COUNT1024 * 1024 + \ - HEAP_RT_COUNT2048 * 2048 + HEAP_RT_COUNT4096 * 4096) - -#define HEAP_BUFFER_BASE (HEAP_RUNTIME_BASE + HEAP_RUNTIME_SIZE) -#define HEAP_BUFFER_SIZE \ - (SDRAM1_SIZE - SOF_MAILBOX_SIZE - HEAP_RUNTIME_SIZE - SOF_STACK_TOTAL_SIZE -\ - HEAP_SYS_RUNTIME_SIZE - HEAP_SYSTEM_SIZE) - -/* Stack configuration */ -#define SOF_STACK_SIZE 0x1000 -#define SOF_STACK_TOTAL_SIZE SOF_STACK_SIZE -#define SOF_STACK_BASE (SDRAM1_BASE + SDRAM1_SIZE) -#define SOF_STACK_END (SOF_STACK_BASE - SOF_STACK_TOTAL_SIZE) - -/* Host page size */ -#define HOST_PAGE_SIZE 4096 - -#endif /* __INC_MEMORY_H */ diff --git a/soc/xtensa/nxp_adsp/imx8m/include/soc/platform.h b/soc/xtensa/nxp_adsp/imx8m/include/soc/platform.h deleted file mode 100644 index 2af652c0cc8..00000000000 --- a/soc/xtensa/nxp_adsp/imx8m/include/soc/platform.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2021 NXP - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __PLATFORM_PLATFORM_H__ -#define __PLATFORM_PLATFORM_H__ - -#define PLATFORM_PRIMARY_CORE_ID 0 - -#define MAX_CORE_COUNT 1 - -#if PLATFORM_CORE_COUNT > MAX_CORE_COUNT -#error "Invalid core count - exceeding core limit" -/* IPC Interrupt */ -#define PLATFORM_IPC_INTERRUPT IRQ_NUM_MU -#define PLATFORM_IPC_INTERRUPT_NAME NULL -#endif - -#endif /* __PLATFORM_PLATFORM_H__ */ diff --git a/soc/xtensa/nxp_adsp/imx8m/linker.ld b/soc/xtensa/nxp_adsp/imx8m/linker.ld index aab0a0b6548..9687b604d6c 100644 --- a/soc/xtensa/nxp_adsp/imx8m/linker.ld +++ b/soc/xtensa/nxp_adsp/imx8m/linker.ld @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 NXP + * Copyright 2021, 2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,7 +15,7 @@ OUTPUT_ARCH(xtensa) #include #include -#include +#include #include #include @@ -352,7 +352,7 @@ SECTIONS .text : ALIGN(4) { _stext = .; - _text_start = ABSOLUTE(.); + __text_region_start = ABSOLUTE(.); KEEP (*(.ResetVector.text)) *(.ResetVector.literal) *(.entry.text) @@ -362,7 +362,7 @@ SECTIONS *(.fini.literal) KEEP(*(.fini)) *(.gnu.version) - _text_end = ABSOLUTE(.); + __text_region_end = ABSOLUTE(.); _etext = .; } >sdram0 :sdram0_phdr @@ -415,6 +415,11 @@ SECTIONS #include + /* Used for C++ build */ + .tm_clone_table : { + *(.tm_clone_table) + } >sdram0 :sdram0_phdr + .bss (NOLOAD) : ALIGN(8) { . = ALIGN (8); @@ -448,6 +453,8 @@ SECTIONS _end = ALIGN (8); PROVIDE(end = ALIGN (8)); + /* Mostly unused, though newlib likes them */ + _heap_sentry = .; __stack = SDRAM1_BASE + SDRAM1_SIZE; .comment 0 : { *(.comment) } .debug 0 : { *(.debug) } @@ -520,4 +527,6 @@ SECTIONS KEEP (*(.fw_metadata)) . = ALIGN(_EXT_MAN_ALIGN_); } >fw_metadata_seg :metadata_entries_phdr + + #include } diff --git a/soc/xtensa/nxp_adsp/rt5xx/Kconfig.defconfig.series b/soc/xtensa/nxp_adsp/rt5xx/Kconfig.defconfig.series new file mode 100644 index 00000000000..b5a56658c7d --- /dev/null +++ b/soc/xtensa/nxp_adsp/rt5xx/Kconfig.defconfig.series @@ -0,0 +1,46 @@ +# Copyright (c) 2023 Google LLC. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_NXP_RT5XX + +config SOC_SERIES + string + default "rt5xx" + +config SOC_TOOLCHAIN_NAME + string + default "nxp_rt500_adsp" + +config SOC + string + default "nxp_rt5xx" + +config SOC_PART_NUMBER + string + default "MIMXRT595SFFOC_dsp" if SOC_NXP_RT595 + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 198000000 + +config XTENSA_CCOUNT_HZ + default SYS_CLOCK_HW_CYCLES_PER_SEC + +config SYS_CLOCK_TICKS_PER_SEC + default 1000 + +config DYNAMIC_INTERRUPTS + default n + +config CACHE + default n + +config DCACHE + default n + +config CACHE_MANAGEMENT + default n + +config LOG + default n + +endif # SOC_SERIES_NXP_RT5XX diff --git a/soc/xtensa/nxp_adsp/rt5xx/Kconfig.series b/soc/xtensa/nxp_adsp/rt5xx/Kconfig.series new file mode 100644 index 00000000000..5135b881638 --- /dev/null +++ b/soc/xtensa/nxp_adsp/rt5xx/Kconfig.series @@ -0,0 +1,12 @@ +# Copyright (c) 2023 Google LLC. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_NXP_RT5XX + bool "NXP RT5xx Series" + select SOC_FAMILY_NXP_ADSP + select XTENSA + select XTENSA_HAL if ("$(ZEPHYR_TOOLCHAIN_VARIANT)" != "xcc" && "$(ZEPHYR_TOOLCHAIN_VARIANT)" != "xt-clang") + select XTENSA_RESET_VECTOR + select XTENSA_USE_CORE_CRT1 + help + NXP RT5xx ADSP Series diff --git a/soc/xtensa/nxp_adsp/rt5xx/Kconfig.soc b/soc/xtensa/nxp_adsp/rt5xx/Kconfig.soc new file mode 100644 index 00000000000..e5b598c4f57 --- /dev/null +++ b/soc/xtensa/nxp_adsp/rt5xx/Kconfig.soc @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Google LLC. +# SPDX-License-Identifier: Apache-2.0 + +choice + prompt "NXP RT5xx ADSP SoC Selection" + + config SOC_NXP_RT595 + bool "NXP RT595" + depends on SOC_SERIES_NXP_RT5XX +endchoice diff --git a/soc/xtensa/nxp_adsp/rt5xx/include/_soc_inthandlers.h b/soc/xtensa/nxp_adsp/rt5xx/include/_soc_inthandlers.h new file mode 100644 index 00000000000..0919a03d9ce --- /dev/null +++ b/soc/xtensa/nxp_adsp/rt5xx/include/_soc_inthandlers.h @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2023 Google LLC. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#if !defined(XCHAL_INT0_LEVEL) || XCHAL_INT0_LEVEL != 5 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT1_LEVEL) || XCHAL_INT1_LEVEL != 2 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT2_LEVEL) || XCHAL_INT2_LEVEL != 2 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT3_LEVEL) || XCHAL_INT3_LEVEL != 3 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT4_LEVEL) || XCHAL_INT4_LEVEL != 3 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT5_LEVEL) || XCHAL_INT5_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT6_LEVEL) || XCHAL_INT6_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT7_LEVEL) || XCHAL_INT7_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT8_LEVEL) || XCHAL_INT8_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT9_LEVEL) || XCHAL_INT9_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT10_LEVEL) || XCHAL_INT10_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT11_LEVEL) || XCHAL_INT11_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT12_LEVEL) || XCHAL_INT12_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT13_LEVEL) || XCHAL_INT13_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT14_LEVEL) || XCHAL_INT14_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT15_LEVEL) || XCHAL_INT15_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT16_LEVEL) || XCHAL_INT16_LEVEL != 2 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT17_LEVEL) || XCHAL_INT17_LEVEL != 2 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT18_LEVEL) || XCHAL_INT18_LEVEL != 2 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT19_LEVEL) || XCHAL_INT19_LEVEL != 2 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT20_LEVEL) || XCHAL_INT20_LEVEL != 2 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT21_LEVEL) || XCHAL_INT21_LEVEL != 2 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT22_LEVEL) || XCHAL_INT22_LEVEL != 2 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT23_LEVEL) || XCHAL_INT23_LEVEL != 2 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT24_LEVEL) || XCHAL_INT24_LEVEL != 3 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT25_LEVEL) || XCHAL_INT25_LEVEL != 3 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT26_LEVEL) || XCHAL_INT26_LEVEL != 3 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT27_LEVEL) || XCHAL_INT27_LEVEL != 3 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT28_LEVEL) || XCHAL_INT28_LEVEL != 3 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT29_LEVEL) || XCHAL_INT29_LEVEL != 3 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT30_LEVEL) || XCHAL_INT30_LEVEL != 3 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT31_LEVEL) || XCHAL_INT31_LEVEL != 3 +#error core-isa.h interrupt level does not match dispatcher! +#endif + +/* + * Interrupt masks for every level (RT595 ADSP): + * XCHAL_INTLEVEL1_MASK: 0x0000FFE0 + * XCHAL_INTLEVEL2_MASK: 0x00FF0006 + * XCHAL_INTLEVEL3_MASK: 0xFF000018 + * XCHAL_INTLEVEL4_MASK: 0x00000000 + * XCHAL_INTLEVEL5_MASK: 0x00000001 + */ + +static inline int _xtensa_handle_one_int1(unsigned int mask) +{ + int irq; + + mask &= XCHAL_INTLEVEL1_MASK; + for (int i = 5; i <= 31; i++) { + if (mask & BIT(i)) { + mask = BIT(i); + irq = i; + goto handle_irq; + } + } + return 0; +handle_irq: + _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); + return mask; +} + +static inline int _xtensa_handle_one_int2(unsigned int mask) +{ + int irq; + + mask &= XCHAL_INTLEVEL2_MASK; + for (int i = 1; i <= 31; i++) { + if (mask & BIT(i)) { + mask = BIT(i); + irq = i; + goto handle_irq; + } + } + return 0; +handle_irq: + _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); + return mask; +} + +static inline int _xtensa_handle_one_int3(unsigned int mask) +{ + int irq; + + mask &= XCHAL_INTLEVEL3_MASK; + for (int i = 3; i <= 31; i++) { + if (mask & BIT(i)) { + mask = BIT(i); + irq = i; + goto handle_irq; + } + } + return 0; +handle_irq: + _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); + return mask; +} + +static inline int _xtensa_handle_one_int4(unsigned int mask) +{ + return 0; +} + +static inline int _xtensa_handle_one_int5(unsigned int mask) +{ + int irq; + + if (mask & BIT(0)) { + mask = BIT(0); + irq = 0; + goto handle_irq; + } + return 0; +handle_irq: + _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); + return mask; +} diff --git a/soc/xtensa/nxp_adsp/rt5xx/include/soc/memory.h b/soc/xtensa/nxp_adsp/rt5xx/include/soc/memory.h new file mode 100644 index 00000000000..af9e1888e1c --- /dev/null +++ b/soc/xtensa/nxp_adsp/rt5xx/include/soc/memory.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 Google LLC. + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +#define IRAM_BASE (CONFIG_RT595_ADSP_TEXT_MEM_ADDR) +#define IRAM_SIZE (CONFIG_RT595_ADSP_TEXT_MEM_SIZE) + +#define SDRAM0_BASE (CONFIG_RT595_ADSP_DATA_MEM_ADDR) +#define SDRAM0_SIZE (CONFIG_RT595_ADSP_DATA_MEM_SIZE - CONFIG_RT595_ADSP_STACK_SIZE) + +/* The reset vector address in SRAM and its size. */ +#define XCHAL_RESET_VECTOR0_PADDR_IRAM (CONFIG_RT595_ADSP_RESET_MEM_ADDR) +#define MEM_RESET_TEXT_SIZE (0x2e0) +#define MEM_RESET_LIT_SIZE (0x120) + +/* Base address of all interrupt vectors in IRAM. */ +#define XCHAL_VECBASE_RESET_PADDR_IRAM (IRAM_BASE) +#define MEM_VECBASE_LIT_SIZE (0x178) + +/* Vector and literal sizes. */ +#define MEM_VECT_LIT_SIZE (0x4) +#define MEM_VECT_TEXT_SIZE (0x1C) + +/* Addresses of the interrupt vectors. */ +#define XCHAL_INT_VECTOR_ADDR(x) (XCHAL_VECBASE_RESET_PADDR_IRAM + (x)) +#define XCHAL_INTLEVEL2_VECTOR_PADDR_IRAM (XCHAL_INT_VECTOR_ADDR(0x17C)) +#define XCHAL_INTLEVEL3_VECTOR_PADDR_IRAM (XCHAL_INT_VECTOR_ADDR(0x19C)) +#define XCHAL_INTLEVEL4_VECTOR_PADDR_IRAM (XCHAL_INT_VECTOR_ADDR(0x1BC)) +#define XCHAL_INTLEVEL5_VECTOR_PADDR_IRAM (XCHAL_INT_VECTOR_ADDR(0x1DC)) +#define XCHAL_KERNEL_VECTOR_PADDR_IRAM (XCHAL_INT_VECTOR_ADDR(0x1FC)) +#define XCHAL_USER_VECTOR_PADDR_IRAM (XCHAL_INT_VECTOR_ADDR(0x21C)) +#define XCHAL_DOUBLEEXC_VECTOR_PADDR_IRAM (XCHAL_INT_VECTOR_ADDR(0x23C)) + +/* Location for the intList section which is later used to construct the + * Interrupt Descriptor Table (IDT). This is a bogus address as this + * section will be stripped off in the final image. + */ +#define IDT_BASE (IRAM_BASE + IRAM_SIZE) + +/* Size of the Interrupt Descriptor Table (IDT). */ +#define IDT_SIZE (0x2000) diff --git a/soc/xtensa/nxp_adsp/rt5xx/linker.ld b/soc/xtensa/nxp_adsp/rt5xx/linker.ld new file mode 100644 index 00000000000..adc8b87fb62 --- /dev/null +++ b/soc/xtensa/nxp_adsp/rt5xx/linker.ld @@ -0,0 +1,464 @@ +/* + * Copyright (c) 2021 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +OUTPUT_ARCH(xtensa) + +#include +#include + +#include +#include +#include + +#define RAMABLE_REGION sdram0 :sdram0_phdr +#define ROMABLE_REGION sdram0 :sdram0_phdr + +MEMORY +{ + vector_reset_text : + org = XCHAL_RESET_VECTOR0_PADDR_IRAM, + len = MEM_RESET_TEXT_SIZE + vector_reset_lit : + org = XCHAL_RESET_VECTOR0_PADDR_IRAM + MEM_RESET_TEXT_SIZE, + len = MEM_RESET_LIT_SIZE + vector_base_text : + org = XCHAL_VECBASE_RESET_PADDR_IRAM, + len = MEM_VECBASE_LIT_SIZE + vector_int2_lit : + org = XCHAL_INTLEVEL2_VECTOR_PADDR_IRAM - MEM_VECT_LIT_SIZE, + len = MEM_VECT_LIT_SIZE + vector_int2_text : + org = XCHAL_INTLEVEL2_VECTOR_PADDR_IRAM, + len = MEM_VECT_TEXT_SIZE + vector_int3_lit : + org = XCHAL_INTLEVEL3_VECTOR_PADDR_IRAM - MEM_VECT_LIT_SIZE, + len = MEM_VECT_LIT_SIZE + vector_int3_text : + org = XCHAL_INTLEVEL3_VECTOR_PADDR_IRAM, + len = MEM_VECT_TEXT_SIZE + vector_int4_lit : + org = XCHAL_INTLEVEL4_VECTOR_PADDR_IRAM - MEM_VECT_LIT_SIZE, + len = MEM_VECT_LIT_SIZE + vector_int4_text : + org = XCHAL_INTLEVEL4_VECTOR_PADDR_IRAM, + len = MEM_VECT_TEXT_SIZE + vector_int5_lit : + org = XCHAL_INTLEVEL5_VECTOR_PADDR_IRAM - MEM_VECT_LIT_SIZE, + len = MEM_VECT_LIT_SIZE + vector_int5_text : + org = XCHAL_INTLEVEL5_VECTOR_PADDR_IRAM, + len = MEM_VECT_TEXT_SIZE + vector_kernel_lit : + org = XCHAL_KERNEL_VECTOR_PADDR_IRAM - MEM_VECT_LIT_SIZE, + len = MEM_VECT_LIT_SIZE + vector_kernel_text : + org = XCHAL_KERNEL_VECTOR_PADDR_IRAM, + len = MEM_VECT_TEXT_SIZE + vector_user_lit : + org = XCHAL_USER_VECTOR_PADDR_IRAM - MEM_VECT_LIT_SIZE, + len = MEM_VECT_LIT_SIZE + vector_user_text : + org = XCHAL_USER_VECTOR_PADDR_IRAM, + len = MEM_VECT_TEXT_SIZE + vector_double_lit : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR_IRAM - MEM_VECT_LIT_SIZE, + len = MEM_VECT_LIT_SIZE + vector_double_text : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR_IRAM, + len = MEM_VECT_TEXT_SIZE + iram_text_start : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR_IRAM + MEM_VECT_TEXT_SIZE, + len = (IRAM_BASE + IRAM_SIZE) - (XCHAL_DOUBLEEXC_VECTOR_PADDR + MEM_VECT_TEXT_SIZE) + sdram0 : + org = SDRAM0_BASE, + len = SDRAM0_SIZE +#ifdef CONFIG_GEN_ISR_TABLES + IDT_LIST : + org = IDT_BASE, + len = IDT_SIZE +#endif +} + +PHDRS +{ + vector_reset_text_phdr PT_LOAD; + vector_reset_lit_phdr PT_LOAD; + vector_base_text_phdr PT_LOAD; + vector_base_lit_phdr PT_LOAD; + vector_int2_text_phdr PT_LOAD; + vector_int2_lit_phdr PT_LOAD; + vector_int3_text_phdr PT_LOAD; + vector_int3_lit_phdr PT_LOAD; + vector_int4_text_phdr PT_LOAD; + vector_int4_lit_phdr PT_LOAD; + vector_int5_text_phdr PT_LOAD; + vector_int5_lit_phdr PT_LOAD; + vector_kernel_text_phdr PT_LOAD; + vector_kernel_lit_phdr PT_LOAD; + vector_user_text_phdr PT_LOAD; + vector_user_lit_phdr PT_LOAD; + vector_double_text_phdr PT_LOAD; + vector_double_lit_phdr PT_LOAD; + iram_text_start_phdr PT_LOAD; + sdram0_phdr PT_LOAD; +} + +PROVIDE(_memmap_reset_vector = XCHAL_RESET_VECTOR0_PADDR_IRAM); +PROVIDE(_memmap_vecbase_reset = XCHAL_VECBASE_RESET_PADDR_IRAM); + +ENTRY(CONFIG_KERNEL_ENTRY) + +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x00000012; +_memmap_cacheattr_wt_base = 0x00000012; +_memmap_cacheattr_bp_base = 0x00000022; +_memmap_cacheattr_unused_mask = 0xFFFFFF00; +_memmap_cacheattr_wb_trapnull = 0x22222212; +_memmap_cacheattr_wba_trapnull = 0x22222212; +_memmap_cacheattr_wbna_trapnull = 0x22222212; +_memmap_cacheattr_wt_trapnull = 0x22222212; +_memmap_cacheattr_bp_trapnull = 0x22222222; +_memmap_cacheattr_wb_strict = 0xFFFFFF12; +_memmap_cacheattr_wt_strict = 0xFFFFFF12; +_memmap_cacheattr_bp_strict = 0xFFFFFF22; +_memmap_cacheattr_wb_allvalid = 0x22222212; +_memmap_cacheattr_wt_allvalid = 0x22222212; +_memmap_cacheattr_bp_allvalid = 0x22222222; +_memmap_region_map = 0x00000003; +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull); + +SECTIONS +{ + +#include + .ResetVector.text : ALIGN(4) + { + _ResetVector_text_start = ABSOLUTE(.); + KEEP (*(.ResetVector.text)) + _ResetVector_text_end = ABSOLUTE(.); + } >vector_reset_text :vector_reset_text_phdr + + .ResetVector.literal : ALIGN(4) + { + _ResetVector_literal_start = ABSOLUTE(.); + *(.ResetVector.literal) + _ResetVector_literal_end = ABSOLUTE(.); + } >vector_reset_lit :vector_reset_lit_phdr + + .WindowVectors.text : ALIGN(4) + { + _WindowVectors_text_start = ABSOLUTE(.); + KEEP (*(.WindowVectors.text)) + _WindowVectors_text_end = ABSOLUTE(.); + } >vector_base_text :vector_base_text_phdr + + .Level2InterruptVector.literal : ALIGN(4) + { + _Level2InterruptVector_literal_start = ABSOLUTE(.); + *(.Level2InterruptVector.literal) + _Level2InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int2_lit :vector_int2_lit_phdr + + .Level2InterruptVector.text : ALIGN(4) + { + _Level2InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level2InterruptVector.text)) + _Level2InterruptVector_text_end = ABSOLUTE(.); + } >vector_int2_text :vector_int2_text_phdr + + .Level3InterruptVector.literal : ALIGN(4) + { + _Level3InterruptVector_literal_start = ABSOLUTE(.); + *(.Level3InterruptVector.literal) + _Level3InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int3_lit :vector_int3_lit_phdr + + .Level3InterruptVector.text : ALIGN(4) + { + _Level3InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level3InterruptVector.text)) + _Level3InterruptVector_text_end = ABSOLUTE(.); + } >vector_int3_text :vector_int3_text_phdr + + .DebugExceptionVector.literal : ALIGN(4) + { + _DebugExceptionVector_literal_start = ABSOLUTE(.); + *(.DebugExceptionVector.literal) + _DebugExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int4_lit :vector_int4_lit_phdr + + .DebugExceptionVector.text : ALIGN(4) + { + _DebugExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DebugExceptionVector.text)) + _DebugExceptionVector_text_end = ABSOLUTE(.); + } >vector_int4_text :vector_int4_text_phdr + + .NMIExceptionVector.literal : ALIGN(4) + { + _NMIExceptionVector_literal_start = ABSOLUTE(.); + *(.NMIExceptionVector.literal) + _NMIExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int5_lit :vector_int5_lit_phdr + + .NMIExceptionVector.text : ALIGN(4) + { + _NMIExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.NMIExceptionVector.text)) + _NMIExceptionVector_text_end = ABSOLUTE(.); + } >vector_int5_text :vector_int5_text_phdr + + .KernelExceptionVector.literal : ALIGN(4) + { + _KernelExceptionVector_literal_start = ABSOLUTE(.); + *(.KernelExceptionVector.literal) + _KernelExceptionVector_literal_end = ABSOLUTE(.); + } >vector_kernel_lit :vector_kernel_lit_phdr + + .KernelExceptionVector.text : ALIGN(4) + { + _KernelExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.KernelExceptionVector.text)) + _KernelExceptionVector_text_end = ABSOLUTE(.); + } >vector_kernel_text :vector_kernel_text_phdr + + .UserExceptionVector.literal : ALIGN(4) + { + _UserExceptionVector_literal_start = ABSOLUTE(.); + *(.UserExceptionVector.literal) + _UserExceptionVector_literal_end = ABSOLUTE(.); + } >vector_user_lit :vector_user_lit_phdr + + .UserExceptionVector.text : ALIGN(4) + { + _UserExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.UserExceptionVector.text)) + _UserExceptionVector_text_end = ABSOLUTE(.); + } >vector_user_text :vector_user_text_phdr + + .DoubleExceptionVector.literal : ALIGN(4) + { + _DoubleExceptionVector_literal_start = ABSOLUTE(.); + *(.DoubleExceptionVector.literal) + _DoubleExceptionVector_literal_end = ABSOLUTE(.); + } >vector_double_lit :vector_double_lit_phdr + + .DoubleExceptionVector.text : ALIGN(4) + { + _DoubleExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DoubleExceptionVector.text)) + _DoubleExceptionVector_text_end = ABSOLUTE(.); + } >vector_double_text :vector_double_text_phdr + + .iram.text : ALIGN(4) + { + _stext = .; + _iram_text_start = ABSOLUTE(.); + *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) + _iram_text_end = ABSOLUTE(.); + } >iram_text_start :iram_text_start_phdr + + .rodata : ALIGN(4) + { + __rodata_region_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE__ = ABSOLUTE(.); + KEEP (*(.xt_except_table)) + KEEP (*(.gcc_except_table .gcc_except_table.*)) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + KEEP (*(.eh_frame)) + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + __XT_EXCEPTION_DESCS__ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + . = ALIGN(4); + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + __rodata_region_end = ABSOLUTE(.); + } >sdram0 :sdram0_phdr + + .module_init : ALIGN(4) + { + _module_init_start = ABSOLUTE(.); + *(*.initcall) + _module_init_end = ABSOLUTE(.); + } >sdram0 :sdram0_phdr + + .text : ALIGN(4) + { + _stext = .; + __text_region_start = ABSOLUTE(.); + KEEP (*(.ResetVector.text)) + *(.ResetVector.literal) + *(.entry.text) + *(.init.literal) + KEEP(*(.init)) + *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.fini.literal) + KEEP(*(.fini)) + *(.gnu.version) + __text_region_end = ABSOLUTE(.); + _etext = .; + } >iram_text_start :iram_text_start_phdr + +#include + + .fw_ready : ALIGN(4) + { + KEEP(*(".fw_ready")); + KEEP (*(.fw_ready_metadata)) + } >sdram0 :sdram0_phdr + + .data : ALIGN(4) + { + __data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + KEEP(*(.gnu.linkonce.d.*personality*)) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + KEEP(*(.jcr)) + _trace_ctx_start = ABSOLUTE(.); + *(.trace_ctx) + _trace_ctx_end = ABSOLUTE(.); + . = ALIGN(4); + *(.gna_model) + __data_end = ABSOLUTE(.); + . = ALIGN(4096); + } >sdram0 :sdram0_phdr + + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >sdram0 :sdram0_phdr + +#include + + .bss (NOLOAD) : ALIGN(8) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + } >sdram0 :sdram0_phdr + + .noinit (NOLOAD) : ALIGN(4) + { + *(.noinit) + *(.noinit.*) + } >sdram0 :sdram0_phdr + + .heap_mem (NOLOAD) : ALIGN(8) + { + . = ALIGN (8); + _heap_mem_start = ABSOLUTE(.); + *(*.heap_mem) + _heap_mem_end = ABSOLUTE(.); + + } >sdram0 :sdram0_phdr + + /* stack */ + _end = ALIGN (8); + + /DISCARD/ : { *(.note.GNU-stack) } + _heap_sentry = SDRAM0_BASE + SDRAM0_SIZE; + __stack = SDRAM0_BASE + SDRAM0_SIZE + CONFIG_RT595_ADSP_STACK_SIZE; + .comment 0 : { *(.comment) } + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + .debug_ranges 0 : { *(.debug_ranges) } + .xtensa.info 0 : { *(.xtensa.info) } + .xt.insn 0 : + { + KEEP (*(.xt.insn)) + KEEP (*(.gnu.linkonce.x.*)) + } + .xt.prop 0 : + { + KEEP (*(.xt.prop)) + KEEP (*(.xt.prop.*)) + KEEP (*(.gnu.linkonce.prop.*)) + } + .xt.lit 0 : + { + KEEP (*(.xt.lit)) + KEEP (*(.xt.lit.*)) + KEEP (*(.gnu.linkonce.p.*)) + } + .xt.profile_range 0 : + { + KEEP (*(.xt.profile_range)) + KEEP (*(.gnu.linkonce.profile_range.*)) + } + .xt.profile_ranges 0 : + { + KEEP (*(.xt.profile_ranges)) + KEEP (*(.gnu.linkonce.xt.profile_ranges.*)) + } + .xt.profile_files 0 : + { + KEEP (*(.xt.profile_files)) + KEEP (*(.gnu.linkonce.xt.profile_files.*)) + } +#ifdef CONFIG_GEN_ISR_TABLES +#include +#endif +} diff --git a/soc/xtensa/sample_controller/CMakeLists.txt b/soc/xtensa/sample_controller/CMakeLists.txt index 1097b991ed2..20e40128eeb 100644 --- a/soc/xtensa/sample_controller/CMakeLists.txt +++ b/soc/xtensa/sample_controller/CMakeLists.txt @@ -1,3 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# intentionally left empty +zephyr_include_directories(include) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/include/xtensa-sample-controller.ld CACHE INTERNAL "") diff --git a/soc/xtensa/sample_controller/linker.ld b/soc/xtensa/sample_controller/linker.ld deleted file mode 100644 index 08639c8908b..00000000000 --- a/soc/xtensa/sample_controller/linker.ld +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2016 Cadence Design Systems, Inc. - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Linker command/script file - * - * Linker script for the Xtensa platform. - */ -#include diff --git a/submanifests/optional.yaml b/submanifests/optional.yaml new file mode 100644 index 00000000000..54b3d77c0cb --- /dev/null +++ b/submanifests/optional.yaml @@ -0,0 +1,66 @@ +manifest: + remotes: + - name: upstream + url-base: https://github.com/zephyrproject-rtos + projects: + - name: canopennode + revision: dec12fa3f0d790cafa8414a4c2930ea71ab72ffd + path: modules/lib/canopennode + remote: upstream + groups: + - optional + - name: chre + revision: 3b32c76efee705af146124fb4190f71be5a4e36e + path: modules/lib/chre + remote: upstream + groups: + - optional + - name: lz4 + revision: 8e303c264fc21c2116dc612658003a22e933124d + path: modules/lib/lz4 + remote: upstream + groups: + - optional + - name: nanopb + revision: 42fa8b211e946b90b9d968523fce7b1cfe27617e + path: modules/lib/nanopb + remote: upstream + groups: + - optional + - name: psa-arch-tests + revision: 6a17330e0dfb5f319730f974d5b05f7b7f04757b + path: modules/tee/tf-m/psa-arch-tests + remote: upstream + groups: + - optional + - name: sof + revision: e7cb489d430dc2181e4a5f7f953ed1eaeec6668d + path: modules/audio/sof + remote: upstream + groups: + - optional + - name: tf-m-tests + revision: a878426da78fbd1486dfc29d6c6b82be4ee79e72 + path: modules/tee/tf-m/tf-m-tests + remote: upstream + groups: + - optional + - name: tflite-micro + revision: 1a34dcab41e7e0e667db72d6a40999c1ec9c510c + path: optional/modules/lib/tflite-micro + repo-path: tflite-micro + remote: upstream + groups: + - optional + - name: thrift + path: optional/modules/lib/thrift + revision: 10023645a0e6cb7ce23fcd7fd3dbac9f18df6234 + remote: upstream + groups: + - optional + - name: zscilib + path: modules/lib/zscilib + revision: 34a94b0995683822fa3626dcd5d838301c94c350 + remote: upstream + groups: + - optional diff --git a/subsys/CMakeLists.txt b/subsys/CMakeLists.txt index e4f155ef0e2..ccd2c8c88bf 100644 --- a/subsys/CMakeLists.txt +++ b/subsys/CMakeLists.txt @@ -11,12 +11,14 @@ add_subdirectory_ifdef(CONFIG_LORAWAN lorawan) # FIXME: SHADOW_VARS: Remove this once we have enabled -Wshadow globally. add_compile_options($) +# zephyr-keep-sorted-start add_subdirectory(canbus) add_subdirectory(debug) add_subdirectory(fb) add_subdirectory(fs) add_subdirectory(ipc) add_subdirectory(logging) +add_subdirectory(mem_mgmt) add_subdirectory(mgmt) add_subdirectory(modbus) add_subdirectory(pm) @@ -31,6 +33,8 @@ add_subdirectory(testsuite) add_subdirectory(tracing) add_subdirectory(usb) +add_subdirectory_ifdef(CONFIG_ARM_SIP_SVC_SUBSYS sip_svc) +add_subdirectory_ifdef(CONFIG_BINDESC bindesc) add_subdirectory_ifdef(CONFIG_BT bluetooth) add_subdirectory_ifdef(CONFIG_CONSOLE_SUBSYS console) add_subdirectory_ifdef(CONFIG_DEMAND_PAGING demand_paging) @@ -40,6 +44,7 @@ add_subdirectory_ifdef(CONFIG_EMUL emul) add_subdirectory_ifdef(CONFIG_IMG_MANAGER dfu) add_subdirectory_ifdef(CONFIG_INPUT input) add_subdirectory_ifdef(CONFIG_JWT jwt) +add_subdirectory_ifdef(CONFIG_LLEXT llext) add_subdirectory_ifdef(CONFIG_MODEM_MODULES modem) add_subdirectory_ifdef(CONFIG_NET_BUF net) add_subdirectory_ifdef(CONFIG_RETENTION retention) @@ -48,4 +53,4 @@ add_subdirectory_ifdef(CONFIG_SETTINGS settings) add_subdirectory_ifdef(CONFIG_SHELL shell) add_subdirectory_ifdef(CONFIG_TIMING_FUNCTIONS timing) add_subdirectory_ifdef(CONFIG_ZBUS zbus) -add_subdirectory_ifdef(CONFIG_ARM_SIP_SVC_SUBSYS sip_svc) +# zephyr-keep-sorted-stop diff --git a/subsys/Kconfig b/subsys/Kconfig index 322ce245729..f0dab7c8c72 100644 --- a/subsys/Kconfig +++ b/subsys/Kconfig @@ -6,6 +6,8 @@ menu "Subsystems and OS Services" +# zephyr-keep-sorted-start +source "subsys/bindesc/Kconfig" source "subsys/bluetooth/Kconfig" source "subsys/canbus/Kconfig" source "subsys/console/Kconfig" @@ -20,8 +22,10 @@ source "subsys/fs/Kconfig" source "subsys/input/Kconfig" source "subsys/ipc/Kconfig" source "subsys/jwt/Kconfig" +source "subsys/llext/Kconfig" source "subsys/logging/Kconfig" source "subsys/lorawan/Kconfig" +source "subsys/mem_mgmt/Kconfig" source "subsys/mgmt/Kconfig" source "subsys/modbus/Kconfig" source "subsys/modem/Kconfig" @@ -35,6 +39,7 @@ source "subsys/sd/Kconfig" source "subsys/sensing/Kconfig" source "subsys/settings/Kconfig" source "subsys/shell/Kconfig" +source "subsys/sip_svc/Kconfig" source "subsys/stats/Kconfig" source "subsys/storage/Kconfig" source "subsys/task_wdt/Kconfig" @@ -46,6 +51,6 @@ source "subsys/usb/device_next/Kconfig" source "subsys/usb/host/Kconfig" source "subsys/usb/usb_c/Kconfig" source "subsys/zbus/Kconfig" -source "subsys/sip_svc/Kconfig" +# zephyr-keep-sorted-stop endmenu diff --git a/subsys/bindesc/CMakeLists.txt b/subsys/bindesc/CMakeLists.txt new file mode 100644 index 00000000000..9dcb467208d --- /dev/null +++ b/subsys/bindesc/CMakeLists.txt @@ -0,0 +1,88 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +if(CONFIG_X86) + zephyr_linker_sources(ROM_START SORT_KEY 0x1bindesc bindesc_no_vt.ld) + zephyr_library_sources(x86/bindesc_skip.S) +else() + zephyr_linker_sources(ROM_START SORT_KEY 0x1bindesc bindesc.ld) +endif() + +# Wrapper macro around string(TIMESTAMP ...), that returns the time +# in either local time or UTC, depending on CONFIG_BINDESC_BUILD_TIME_USE_LOCAL_TIME. +macro(get_time out_var format) + if(CONFIG_BINDESC_BUILD_TIME_USE_LOCAL_TIME) + string(TIMESTAMP ${out_var} ${format}) + else() + string(TIMESTAMP ${out_var} ${format} UTC) + endif() +endmacro() + +macro(gen_build_time_int_definition def_name format) + if(CONFIG_BINDESC_${def_name}) + get_time(${def_name} ${format}) + # remove leading zeros so that the output will not be interpreted as octal + math(EXPR ${def_name} ${${def_name}}) + zephyr_library_compile_definitions(${def_name}=${${def_name}}) + endif() +endmacro() + +macro(gen_build_time_str_definition def_name format) + if(CONFIG_BINDESC_${def_name}) + get_time(${def_name} ${${format}}) + zephyr_library_compile_definitions(${def_name}="${${def_name}}") + endif() +endmacro() + +macro(gen_str_definition def_name value) + if(CONFIG_BINDESC_${def_name}) + zephyr_library_compile_definitions(${def_name}="${value}") + endif() +endmacro() + +if(CONFIG_BINDESC_DEFINE_BUILD_TIME) + zephyr_library_sources(bindesc_build_time.c) + gen_build_time_int_definition(BUILD_TIME_YEAR "%Y") + gen_build_time_int_definition(BUILD_TIME_MONTH "%m") + gen_build_time_int_definition(BUILD_TIME_DAY "%d") + gen_build_time_int_definition(BUILD_TIME_HOUR "%H") + gen_build_time_int_definition(BUILD_TIME_MINUTE "%M") + gen_build_time_int_definition(BUILD_TIME_SECOND "%S") + gen_build_time_int_definition(BUILD_TIME_UNIX "%s") + + gen_build_time_str_definition(BUILD_DATE_TIME_STRING + CONFIG_BINDESC_BUILD_DATE_TIME_STRING_FORMAT) + gen_build_time_str_definition(BUILD_DATE_STRING + CONFIG_BINDESC_BUILD_DATE_STRING_FORMAT) + gen_build_time_str_definition(BUILD_TIME_STRING + CONFIG_BINDESC_BUILD_TIME_STRING_FORMAT) + + if(CONFIG_BINDESC_BUILD_TIME_ALWAYS_REBUILD) + # By adding a custom target that invokes cmake, + # CMake is forced to rebuild this target on every build. This is + # done to ensure that the timestamp is always up to date. + add_custom_target( + bindesc_time_force_rebuild + COMMAND ${CMAKE_COMMAND} ${CMAKE_BINARY_DIR} + ) + zephyr_library_add_dependencies(bindesc_time_force_rebuild) + endif() +endif() + +if(CONFIG_BINDESC_DEFINE_VERSION) + zephyr_library_sources(bindesc_version.c) + if(EXISTS ${APPLICATION_SOURCE_DIR}/VERSION) + zephyr_library_compile_definitions(HAS_APP_VERSION=1) + endif() +endif() + +if(CONFIG_BINDESC_DEFINE_HOST_INFO) + cmake_host_system_information(RESULT hostname QUERY HOSTNAME) + zephyr_library_sources(bindesc_host_info.c) + gen_str_definition(HOST_NAME ${hostname}) + gen_str_definition(C_COMPILER_NAME ${CMAKE_C_COMPILER_ID}) + gen_str_definition(C_COMPILER_VERSION ${CMAKE_C_COMPILER_VERSION}) + gen_str_definition(CXX_COMPILER_NAME ${CMAKE_CXX_COMPILER_ID}) + gen_str_definition(CXX_COMPILER_VERSION ${CMAKE_CXX_COMPILER_VERSION}) +endif() diff --git a/subsys/bindesc/Kconfig b/subsys/bindesc/Kconfig new file mode 100644 index 00000000000..e8c158b8c84 --- /dev/null +++ b/subsys/bindesc/Kconfig @@ -0,0 +1,25 @@ +# Copyright (c) 2023 Yonatan Schachter +# SPDX-License-Identifier: Apache-2.0 + +menuconfig BINDESC + bool "Binary Descriptors" + depends on ARCH_SUPPORTS_ROM_START || ARCH_POSIX + help + Binary Descriptors - constant data accessible outside of the executable image + +if BINDESC + +config BINDESC_DEFINE + bool "Binary Descriptors Define" + help + Enable the app to define its own binary descriptors + +if BINDESC_DEFINE + +source "subsys/bindesc/Kconfig.version" +source "subsys/bindesc/Kconfig.build_time" +source "subsys/bindesc/Kconfig.host_info" + +endif # BINDESC_DEFINE + +endif # BINDESC diff --git a/subsys/bindesc/Kconfig.build_time b/subsys/bindesc/Kconfig.build_time new file mode 100644 index 00000000000..f9917008852 --- /dev/null +++ b/subsys/bindesc/Kconfig.build_time @@ -0,0 +1,117 @@ +# Copyright (c) 2023 Yonatan Schachter +# SPDX-License-Identifier: Apache-2.0 + +menuconfig BINDESC_DEFINE_BUILD_TIME + bool "Build Time binary descriptors" + help + Add the build time binary descriptors + +if BINDESC_DEFINE_BUILD_TIME + +config BINDESC_BUILD_TIME_USE_LOCAL_TIME + bool "Use local time" + help + If enabled, the build time used for the descriptors will express + the local time, rather than UTC. + +config BINDESC_BUILD_TIME_ALWAYS_REBUILD + bool "Always rebuild" + default y + help + If enabled, the file containing the build time definitions will + always be rebuilt. This results in the timestamp always being + accurate, but also in slightly longer build times. + +config BINDESC_BUILD_TIME_YEAR + bool "Year of build" + help + The year the image was compiled, such as 2023 + +config BINDESC_BUILD_TIME_MONTH + bool "Month of build" + help + The month the image was compiled, such as 5 (May) + +config BINDESC_BUILD_TIME_DAY + bool "Day of build" + help + The day of the month the image was compiled, such as 9 + +config BINDESC_BUILD_TIME_HOUR + bool "Hour of build" + help + The hour of the day the image was compiled, such as 13 in 13:34:52 + +config BINDESC_BUILD_TIME_MINUTE + bool "Minute of build" + help + The minute the image was compiled, such as 34 in 13:34:52 + +config BINDESC_BUILD_TIME_SECOND + bool "Second of build" + help + The second the image was compiled, such as 52 in 13:34:52 + +config BINDESC_BUILD_TIME_UNIX + bool "Build time as UNIX time" + help + The UNIX time at which the image was compiled. This is an integer + counting the seconds since midnight of January 1st 1970 + +config BINDESC_BUILD_DATE_TIME_STRING + bool "Build date and time as string" + help + The date and time of compilation as a string, such as "2023-09-29T17:43:14+0000" + +config BINDESC_BUILD_DATE_STRING + bool "Build date as string" + help + The date of compilation as a string, such as "2023-09-29" + +config BINDESC_BUILD_TIME_STRING + bool "Build time as string" + help + The time of compilation as a string, such as "T17:43:14+0000" + +config BINDESC_BUILD_DATE_TIME_STRING_FORMAT + depends on BINDESC_BUILD_DATE_TIME_STRING + string "Date-Time format" + default "%Y-%m-%dT%H:%M:%S%z" + help + Format of the build time string. This value is passed to cmake's string(TIMESTAMP ...) + function, so refer to string's documentation for more info on the different formats. + This can also be used to set a specific time, when trying to reproduce an image. For + example, setting the format to "2023-02-05T00:07:04+0000" will set it as the build time, + regardless of the actual build time. + If BINDESC_BUILD_TIME_USE_LOCAL_TIME is enabled, the time is the local time, else + it is UTC time. + Example of the default format: 2023-09-29T17:43:14+0000. + Note: the default format complies with ISO-8601. + +config BINDESC_BUILD_DATE_STRING_FORMAT + depends on BINDESC_BUILD_DATE_STRING + string "Date format" + default "%Y-%m-%d" + help + Format of the build date string. This value is passed to cmake's string(TIMESTAMP ...) + function, so refer to string's documentation for more info on the different formats. + This can also be used to set a specific time, when trying to reproduce an image. For + example, setting the format to "2023-02-05" will set it as the build time, + regardless of the actual build time. + Example of the default format: 2023-02-05 + Note: the default format complies with ISO-8601. + +config BINDESC_BUILD_TIME_STRING_FORMAT + depends on BINDESC_BUILD_TIME_STRING + string "Time format" + default "T%H:%M:%S%z" + help + Format of the build time string. This value is passed to cmake's string(TIMESTAMP ...) + function, so refer to string's documentation for more info on the different formats. + This can also be used to set a specific time, when trying to reproduce an image. For + example, setting the format to "T00:07:04+0000" will set it as the build time, + regardless of the actual build time. + Example of the default format: T00:07:04+0000. + Note: the default format complies with ISO-8601. + +endif # BINDESC_DEFINE_BUILD_TIME diff --git a/subsys/bindesc/Kconfig.host_info b/subsys/bindesc/Kconfig.host_info new file mode 100644 index 00000000000..8c2c9d24bb4 --- /dev/null +++ b/subsys/bindesc/Kconfig.host_info @@ -0,0 +1,36 @@ +# Copyright (c) 2023 Yonatan Schachter +# SPDX-License-Identifier: Apache-2.0 + +menuconfig BINDESC_DEFINE_HOST_INFO + bool "Host info binary descriptors" + help + Add the host info binary descriptors + +if BINDESC_DEFINE_HOST_INFO + +config BINDESC_HOST_NAME + bool "Host name" + help + The name of the host that the image was compiled on + +config BINDESC_C_COMPILER_NAME + bool "C compiler name" + help + The C compiler name, such as "GNU" + +config BINDESC_C_COMPILER_VERSION + bool "C compiler version" + help + The C compiler version, such as "12.3.0" + +config BINDESC_CXX_COMPILER_NAME + bool "C++ compiler name" + help + The C++ compiler name, such as "GNU" + +config BINDESC_CXX_COMPILER_VERSION + bool "C++ compiler version" + help + The C++ compiler version, such as "12.3.0" + +endif # BINDESC_DEFINE_HOST_INFO diff --git a/subsys/bindesc/Kconfig.version b/subsys/bindesc/Kconfig.version new file mode 100644 index 00000000000..ee7696e8064 --- /dev/null +++ b/subsys/bindesc/Kconfig.version @@ -0,0 +1,65 @@ +# Copyright (c) 2023 Yonatan Schachter +# SPDX-License-Identifier: Apache-2.0 + +menuconfig BINDESC_DEFINE_VERSION + bool "Version binary descriptors" + help + Add the version binary descriptors + +if BINDESC_DEFINE_VERSION + +config BINDESC_KERNEL_VERSION_STRING + bool "Kernel version string" + help + The kernel version string, such as "3.4.0" + +config BINDESC_KERNEL_VERSION_MAJOR + bool "Kernel version major" + help + The major version number, such as 3 in 3.4.0 + +config BINDESC_KERNEL_VERSION_MINOR + bool "Kernel version minor" + help + The minor version number, such as 4 in 3.4.0 + +config BINDESC_KERNEL_VERSION_PATCHLEVEL + bool "Kernel version patchlevel" + help + The patchlevel version number, such as 0 in 3.4.0 + +config BINDESC_KERNEL_VERSION_NUMBER + bool "Kernel version number" + help + The kernel version as binary coded decimal, computed as + (major << 16 | minor << 8 | patchlevel). For example, + 3.4.0 would be represented as 0x30400 + +config BINDESC_APP_VERSION_STRING + bool "App version string" + help + The app version string, such as "1.0.0" + +config BINDESC_APP_VERSION_MAJOR + bool "App version major" + help + The app major version number, such as 1 in 1.0.0 + +config BINDESC_APP_VERSION_MINOR + bool "App version minor" + help + The app minor version number, such as 0 in 1.0.0 + +config BINDESC_APP_VERSION_PATCHLEVEL + bool "App version patchlevel" + help + The app patchlevel version number, such as 0 in 1.0.0 + +config BINDESC_APP_VERSION_NUMBER + bool "App version number" + help + The app version as binary coded decimal, computed as + (major << 16 | minor << 8 | patchlevel). For example, + 1.0.0 would be represented as 0x10000 + +endif # BINDESC_DEFINE_VERSION diff --git a/subsys/bindesc/bindesc.ld b/subsys/bindesc/bindesc.ld new file mode 100644 index 00000000000..e07222d5f10 --- /dev/null +++ b/subsys/bindesc/bindesc.ld @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +SQUAD(BINDESC_MAGIC); +Z_LINK_ITERABLE(bindesc_entry); +. = ALIGN(BINDESC_ALIGNMENT); +LONG(BINDESC_TAG_DESCRIPTORS_END) diff --git a/subsys/bindesc/bindesc_build_time.c b/subsys/bindesc/bindesc_build_time.c new file mode 100644 index 00000000000..c741ce0ffd8 --- /dev/null +++ b/subsys/bindesc/bindesc_build_time.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2023 Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_YEAR) +BINDESC_UINT_DEFINE(build_time_year, BINDESC_ID_BUILD_TIME_YEAR, BUILD_TIME_YEAR); +#endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_YEAR) */ + +#if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_MONTH) +BINDESC_UINT_DEFINE(build_time_month, BINDESC_ID_BUILD_TIME_MONTH, BUILD_TIME_MONTH); +#endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_MONTH) */ + +#if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_DAY) +BINDESC_UINT_DEFINE(build_time_day, BINDESC_ID_BUILD_TIME_DAY, BUILD_TIME_DAY); +#endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_DAY) */ + +#if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_HOUR) +BINDESC_UINT_DEFINE(build_time_hour, BINDESC_ID_BUILD_TIME_HOUR, BUILD_TIME_HOUR); +#endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_HOUR) */ + +#if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_MINUTE) +BINDESC_UINT_DEFINE(build_time_minute, BINDESC_ID_BUILD_TIME_MINUTE, BUILD_TIME_MINUTE); +#endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_MINUTE) */ + +#if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_SECOND) +BINDESC_UINT_DEFINE(build_time_second, BINDESC_ID_BUILD_TIME_SECOND, BUILD_TIME_SECOND); +#endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_SECOND) */ + +#if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_UNIX) +BINDESC_UINT_DEFINE(build_time_unix, BINDESC_ID_BUILD_TIME_UNIX, BUILD_TIME_UNIX); +#endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_UNIX) */ + +#if IS_ENABLED(CONFIG_BINDESC_BUILD_DATE_TIME_STRING) +BINDESC_STR_DEFINE(build_date_time_string, BINDESC_ID_BUILD_DATE_TIME_STRING, + BUILD_DATE_TIME_STRING); +#endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_DATE_TIME_STRING) */ + +#if IS_ENABLED(CONFIG_BINDESC_BUILD_DATE_STRING) +BINDESC_STR_DEFINE(build_date_string, BINDESC_ID_BUILD_DATE_STRING, BUILD_DATE_STRING); +#endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_DATE_STRING) */ + +#if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_STRING) +BINDESC_STR_DEFINE(build_time_string, BINDESC_ID_BUILD_TIME_STRING, BUILD_TIME_STRING); +#endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_STRING) */ diff --git a/subsys/bindesc/bindesc_host_info.c b/subsys/bindesc/bindesc_host_info.c new file mode 100644 index 00000000000..6ecc43495d4 --- /dev/null +++ b/subsys/bindesc/bindesc_host_info.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#if IS_ENABLED(CONFIG_BINDESC_HOST_NAME) +BINDESC_STR_DEFINE(host_name, BINDESC_ID_HOST_NAME, HOST_NAME); +#endif /* IS_ENABLED(CONFIG_BINDESC_HOST_NAME) */ + +#if IS_ENABLED(CONFIG_BINDESC_C_COMPILER_NAME) +BINDESC_STR_DEFINE(c_compiler_name, BINDESC_ID_C_COMPILER_NAME, C_COMPILER_NAME); +#endif /* IS_ENABLED(CONFIG_BINDESC_C_COMPILER_NAME) */ + +#if IS_ENABLED(CONFIG_BINDESC_C_COMPILER_VERSION) +BINDESC_STR_DEFINE(c_compiler_version, BINDESC_ID_C_COMPILER_VERSION, C_COMPILER_VERSION); +#endif /* IS_ENABLED(CONFIG_BINDESC_C_COMPILER_VERSION) */ + +#if IS_ENABLED(CONFIG_BINDESC_CXX_COMPILER_NAME) +BINDESC_STR_DEFINE(cxx_compiler_name, BINDESC_ID_CXX_COMPILER_NAME, CXX_COMPILER_NAME); +#endif /* IS_ENABLED(CONFIG_BINDESC_CXX_COMPILER_NAME) */ + +#if IS_ENABLED(CONFIG_BINDESC_CXX_COMPILER_VERSION) +BINDESC_STR_DEFINE(cxx_compiler_version, BINDESC_ID_CXX_COMPILER_VERSION, + CXX_COMPILER_VERSION); +#endif /* IS_ENABLED(CONFIG_BINDESC_CXX_COMPILER_VERSION) */ diff --git a/subsys/bindesc/bindesc_no_vt.ld b/subsys/bindesc/bindesc_no_vt.ld new file mode 100644 index 00000000000..4362fc721f0 --- /dev/null +++ b/subsys/bindesc/bindesc_no_vt.ld @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2023 Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +KEEP(*(.bindesc_skip)); +. = ALIGN(4); +#include "bindesc.ld" diff --git a/subsys/bindesc/bindesc_version.c b/subsys/bindesc/bindesc_version.c new file mode 100644 index 00000000000..d1c3a905aa0 --- /dev/null +++ b/subsys/bindesc/bindesc_version.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023 Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#if IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_STRING) +BINDESC_STR_DEFINE(kernel_version_string, BINDESC_ID_KERNEL_VERSION_STRING, + KERNEL_VERSION_STRING); +#endif /* IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_STRING) */ + +#if IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_MAJOR) +BINDESC_UINT_DEFINE(kernel_version_major, BINDESC_ID_KERNEL_VERSION_MAJOR, + KERNEL_VERSION_MAJOR); +#endif /* IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_MAJOR) */ + +#if IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_MINOR) +BINDESC_UINT_DEFINE(kernel_version_minor, BINDESC_ID_KERNEL_VERSION_MINOR, + KERNEL_VERSION_MINOR); +#endif /* IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_MINOR) */ + +#if IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_PATCHLEVEL) +BINDESC_UINT_DEFINE(kernel_version_patchlevel, BINDESC_ID_KERNEL_VERSION_PATCHLEVEL, + KERNEL_PATCHLEVEL); +#endif /* IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_PATCHLEVEL) */ + +#if IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_NUMBER) +BINDESC_UINT_DEFINE(kernel_version_number, BINDESC_ID_KERNEL_VERSION_NUMBER, + KERNEL_VERSION_NUMBER); +#endif /* IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_NUMBER) */ + +#if IS_ENABLED(HAS_APP_VERSION) +#include + +#if IS_ENABLED(CONFIG_BINDESC_APP_VERSION_STRING) +BINDESC_STR_DEFINE(app_version_string, BINDESC_ID_APP_VERSION_STRING, + APP_VERSION_STRING); +#endif /* IS_ENABLED(CONFIG_BINDESC_APP_VERSION_STRING) */ + +#if IS_ENABLED(CONFIG_BINDESC_APP_VERSION_MAJOR) +BINDESC_UINT_DEFINE(app_version_major, BINDESC_ID_APP_VERSION_MAJOR, + APP_VERSION_MAJOR); +#endif /* IS_ENABLED(CONFIG_BINDESC_APP_VERSION_MAJOR) */ + +#if IS_ENABLED(CONFIG_BINDESC_APP_VERSION_MINOR) +BINDESC_UINT_DEFINE(app_version_minor, BINDESC_ID_APP_VERSION_MINOR, + APP_VERSION_MINOR); +#endif /* IS_ENABLED(CONFIG_BINDESC_APP_VERSION_MINOR) */ + +#if IS_ENABLED(CONFIG_BINDESC_APP_VERSION_PATCHLEVEL) +BINDESC_UINT_DEFINE(app_version_patchlevel, BINDESC_ID_APP_VERSION_PATCHLEVEL, + APP_PATCHLEVEL); +#endif /* IS_ENABLED(CONFIG_BINDESC_APP_VERSION_PATCHLEVEL) */ + +#if IS_ENABLED(CONFIG_BINDESC_APP_VERSION_NUMBER) +BINDESC_UINT_DEFINE(app_version_number, BINDESC_ID_APP_VERSION_NUMBER, + APP_VERSION_NUMBER); +#endif /* IS_ENABLED(CONFIG_BINDESC_APP_VERSION_NUMBER) */ + +#endif /* IS_ENABLED(HAS_APP_VERSION) */ diff --git a/subsys/bindesc/x86/bindesc_skip.S b/subsys/bindesc/x86/bindesc_skip.S new file mode 100644 index 00000000000..c0a1982f37b --- /dev/null +++ b/subsys/bindesc/x86/bindesc_skip.S @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2023 Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +.section .bindesc_skip +_bindesc_skip: + jmp __start diff --git a/subsys/bluetooth/Kconfig.iso b/subsys/bluetooth/Kconfig.iso index 304c408f42f..0fc4be1401b 100644 --- a/subsys/bluetooth/Kconfig.iso +++ b/subsys/bluetooth/Kconfig.iso @@ -120,8 +120,8 @@ config BT_ISO_RX_MTU This is the actual data payload. It doesn't include the optional HCI ISO Data packet fields (e.g. `struct bt_hci_iso_ts_data_hdr`) -config BT_ISO_ADVANCED - bool "Advanced ISO parameters" +config BT_ISO_TEST_PARAMS + bool "ISO test parameters support" help Enabling advanced ISO parameters will allow the use of the ISO test parameters for creating a CIG or a BIG. These test parameters were diff --git a/subsys/bluetooth/Kconfig.logging b/subsys/bluetooth/Kconfig.logging index addf8eb65fe..ec95ddad10e 100644 --- a/subsys/bluetooth/Kconfig.logging +++ b/subsys/bluetooth/Kconfig.logging @@ -716,6 +716,11 @@ legacy-debug-sym = BT_DEBUG_CAP_INITIATOR module-str = "Common Audio Profile Initiator" source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +parent-module = BT +module = BT_CAP_COMMANDER +module-str = "Common Audio Profile Commander" +source "subsys/logging/Kconfig.template.log_config_inherit" + parent-module = BT module = BT_CAP_STREAM module-str = "Common Audio Profile Stream" diff --git a/subsys/bluetooth/audio/CMakeLists.txt b/subsys/bluetooth/audio/CMakeLists.txt index 8f24c50233b..2ae08c2d7b5 100644 --- a/subsys/bluetooth/audio/CMakeLists.txt +++ b/subsys/bluetooth/audio/CMakeLists.txt @@ -60,4 +60,5 @@ zephyr_library_sources_ifdef(CONFIG_BT_HAS_CLIENT has_client.c) zephyr_library_sources_ifdef(CONFIG_BT_CAP cap_stream.c) zephyr_library_sources_ifdef(CONFIG_BT_CAP_ACCEPTOR cap_acceptor.c) zephyr_library_sources_ifdef(CONFIG_BT_CAP_INITIATOR cap_initiator.c) +zephyr_library_sources_ifdef(CONFIG_BT_CAP_COMMANDER cap_commander.c) zephyr_library_sources_ifdef(CONFIG_BT_TMAP tmap.c) diff --git a/subsys/bluetooth/audio/Kconfig.bap b/subsys/bluetooth/audio/Kconfig.bap index 64c07ca60d7..0b5e1c3e291 100644 --- a/subsys/bluetooth/audio/Kconfig.bap +++ b/subsys/bluetooth/audio/Kconfig.bap @@ -277,5 +277,14 @@ config BT_BAP_STREAM default y if BT_ASCS || BT_BAP_UNICAST_CLIENT || \ BT_BAP_BROADCAST_SOURCE || BT_BAP_BROADCAST_SINK +config BT_BAP_DEBUG_STREAM_SEQ_NUM + bool "Bluetooth Audio Stream sequence number debug" + depends on BT_BAP_STREAM_LOG_LEVEL >= BT_BAP_STREAM_LOG_LEVEL_WRN + default y + help + Use this option to enable Bluetooth Audio Stream sequence number debugging logs for + the Bluetooth Audio functionality. This will provide a warning if the application + provides unexpected sequence numbers. + rsource "Kconfig.pacs" rsource "Kconfig.ascs" diff --git a/subsys/bluetooth/audio/Kconfig.cap b/subsys/bluetooth/audio/Kconfig.cap index 64762a86572..0488b610a08 100644 --- a/subsys/bluetooth/audio/Kconfig.cap +++ b/subsys/bluetooth/audio/Kconfig.cap @@ -11,6 +11,7 @@ config BT_CAP config BT_CAP_ACCEPTOR bool "Common Audio Profile Acceptor Role Support [EXPERIMENTAL]" depends on BT_BAP_UNICAST_SERVER || (BT_BAP_BROADCAST_SINK && BT_BAP_SCAN_DELEGATOR) + depends on BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE >= 4 select EXPERIMENTAL help Enabling this will enable the CAP Acceptor role. This instantiates the @@ -30,6 +31,20 @@ config BT_CAP_ACCEPTOR_SET_MEMBER config BT_CAP_INITIATOR bool "Common Audio Profile Initiator Role Support [EXPERIMENTAL]" depends on (BT_BAP_UNICAST_CLIENT && BT_CSIP_SET_COORDINATOR) || BT_BAP_BROADCAST_SOURCE + depends on BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE >= 4 + select EXPERIMENTAL + help + Enabling this will enable the CAP Initiator role. + + +config BT_CAP_COMMANDER + bool "Common Audio Profile Initiator Role Support [EXPERIMENTAL]" + depends on (BT_BAP_BROADCAST_ASSISTANT && BT_BAP_SCAN_DELEGATOR && BT_CSIP_SET_COORDINATOR) || \ + (BT_BAP_SCAN_DELEGATOR && BT_CSIP_SET_COORDINATOR) || \ + (BT_VCP_VOL_CTLR && BT_CSIP_SET_COORDINATOR) || \ + (BT_MICP_MIC_CTLR && BT_CSIP_SET_COORDINATOR) || \ + BT_TBS_CLIENT || \ + BT_MCC select EXPERIMENTAL help Enabling this will enable the CAP Initiator role. diff --git a/subsys/bluetooth/audio/Kconfig.pacs b/subsys/bluetooth/audio/Kconfig.pacs index 112475ea99c..fba32e709fd 100644 --- a/subsys/bluetooth/audio/Kconfig.pacs +++ b/subsys/bluetooth/audio/Kconfig.pacs @@ -13,24 +13,6 @@ config BT_PAC_SNK This option enables support for Sink Published Audio Capabilities. if BT_PAC_SNK -config BT_PACS_SNK_CONTEXT - hex "Supported Sink Contexts" - default 0x03ff - range 0x0000 0x03ff - help - The Supported Sink Contexts exposes the server’s support for - reception of audio data associated with specific Context Types: - 0x0001: Unspecified - 0x0002: Conversational - 0x0004: Media - 0x0008: Instructional - 0x0010: AttentionSeeking - 0x0020: ImmediateAlert - 0x0040: ManMachine - 0x0080: EmergencyAlert - 0x0100: Ringtone - 0x0200: TV - config BT_PAC_SNK_NOTIFIABLE bool "Sink PAC Notifiable Support" help @@ -65,23 +47,6 @@ config BT_PAC_SRC This option enables support for Source Published Audio Capabilities. if BT_PAC_SRC -config BT_PACS_SRC_CONTEXT - hex "Supported Source Contexts" - default 0x03ff - range 0x0000 0x03ff - help - The Supported Source Contexts exposes the server’s support for - transmission of audio data associated with specific Context Types: - 0x0001: Unspecified - 0x0002: Conversational - 0x0004: Media - 0x0008: Instructional - 0x0010: AttentionSeeking - 0x0020: ImmediateAlert - 0x0040: ManMachine - 0x0080: EmergencyAlert - 0x0100: Ringtone - 0x0200: TV config BT_PAC_SRC_NOTIFIABLE bool "Source PAC Notifiable Support" diff --git a/subsys/bluetooth/audio/ascs.c b/subsys/bluetooth/audio/ascs.c index d85a90ec77a..116071d4c0f 100644 --- a/subsys/bluetooth/audio/ascs.c +++ b/subsys/bluetooth/audio/ascs.c @@ -15,7 +15,7 @@ #include #include #include -#include "zephyr/bluetooth/iso.h" +#include #include #include #include @@ -61,7 +61,7 @@ static struct bt_ascs_ase { struct bt_bap_ep ep; const struct bt_gatt_attr *attr; struct k_work_delayable disconnect_work; - struct k_work state_transition_work; + struct k_work_delayable state_transition_work; enum bt_bap_ep_state state_pending; bool unexpected_iso_link_loss; } ase_pool[CONFIG_BT_ASCS_MAX_ACTIVE_ASES]; @@ -117,58 +117,58 @@ static void ase_free(struct bt_ascs_ase *ase) LOG_DBG("conn %p ase %p id 0x%02x", (void *)ase->conn, ase, ase->ep.status.id); + if (ase->ep.iso != NULL) { + bt_bap_iso_unbind_ep(ase->ep.iso, &ase->ep); + } + bt_conn_unref(ase->conn); ase->conn = NULL; - (void)k_work_cancel(&ase->state_transition_work); + (void)k_work_cancel_delayable(&ase->disconnect_work); + (void)k_work_cancel_delayable(&ase->state_transition_work); } -static void ase_status_changed(struct bt_ascs_ase *ase, uint8_t state) +static int ase_state_notify(struct bt_ascs_ase *ase) { + const uint8_t att_ntf_header_size = 3; /* opcode (1) + handle (2) */ struct bt_conn *conn = ase->conn; + struct bt_conn_info conn_info; + uint16_t max_ntf_size; + uint16_t ntf_size; + int err; - LOG_DBG("ase %p id 0x%02x %s -> %s", ase, ase->ep.status.id, - bt_bap_ep_state_str(ascs_ep_get_state(&ase->ep)), bt_bap_ep_state_str(state)); - - ase->ep.status.state = state; + __ASSERT_NO_MSG(conn != NULL); - if (conn != NULL) { - struct bt_conn_info conn_info; - int err; + err = bt_conn_get_info(conn, &conn_info); + __ASSERT_NO_MSG(err == 0); - err = bt_conn_get_info(conn, &conn_info); - if (err != 0) { - LOG_ERR("Failed to get conn %p info: %d", (void *)conn, err); + if (conn_info.state != BT_CONN_STATE_CONNECTED || + !bt_gatt_is_subscribed(conn, ase->attr, BT_GATT_CCC_NOTIFY)) { + return 0; + } - return; - } + err = k_sem_take(&ase_buf_sem, ASE_BUF_SEM_TIMEOUT); + if (err != 0) { + LOG_WRN("Failed to take ase_buf_sem: %d", err); - if (conn_info.state == BT_CONN_STATE_CONNECTED) { - const uint8_t att_ntf_header_size = 3; /* opcode (1) + handle (2) */ - const uint16_t max_ntf_size = bt_gatt_get_mtu(conn) - att_ntf_header_size; - uint16_t ntf_size; + return err; + } - err = k_sem_take(&ase_buf_sem, ASE_BUF_SEM_TIMEOUT); - if (err != 0) { - LOG_DBG("Failed to take ase_buf_sem: %d", err); + ascs_ep_get_status(&ase->ep, &ase_buf); - return; - } + max_ntf_size = bt_gatt_get_mtu(conn) - att_ntf_header_size; - ascs_ep_get_status(&ase->ep, &ase_buf); + ntf_size = MIN(max_ntf_size, ase_buf.len); + if (ntf_size < ase_buf.len) { + LOG_DBG("Sending truncated notification (%u / %u)", + ntf_size, ase_buf.len); + } - ntf_size = MIN(max_ntf_size, ase_buf.len); - if (ntf_size < ase_buf.len) { - LOG_DBG("Sending truncated notification (%u / %u)", - ntf_size, ase_buf.len); - } + err = bt_gatt_notify(conn, ase->attr, ase_buf.data, ntf_size); - err = bt_gatt_notify(conn, ase->attr, ase_buf.data, ntf_size); - __ASSERT_NO_MSG(err == 0); + k_sem_give(&ase_buf_sem); - k_sem_give(&ase_buf_sem); - } - } + return err; } static void ascs_disconnect_stream_work_handler(struct k_work *work) @@ -238,7 +238,7 @@ static int ascs_disconnect_stream(struct bt_bap_stream *stream) K_MSEC(CONFIG_BT_ASCS_ISO_DISCONNECT_DELAY)); } -static void ase_set_state_idle(struct bt_ascs_ase *ase) +static void ase_enter_state_idle(struct bt_ascs_ase *ase) { struct bt_bap_stream *stream = ase->ep.stream; struct bt_bap_stream_ops *ops; @@ -247,9 +247,10 @@ static void ase_set_state_idle(struct bt_ascs_ase *ase) ase->ep.receiver_ready = false; - ase_status_changed(ase, BT_BAP_EP_STATE_IDLE); - - bt_bap_stream_reset(stream); + if (stream->conn != NULL) { + bt_conn_unref(stream->conn); + stream->conn = NULL; + } ops = stream->ops; if (ops != NULL && ops->released != NULL) { @@ -259,7 +260,7 @@ static void ase_set_state_idle(struct bt_ascs_ase *ase) ase_free(ase); } -static void ase_set_state_codec_configured(struct bt_ascs_ase *ase) +static void ase_enter_state_codec_configured(struct bt_ascs_ase *ase) { struct bt_bap_stream *stream = ase->ep.stream; struct bt_bap_stream_ops *ops; @@ -268,15 +269,13 @@ static void ase_set_state_codec_configured(struct bt_ascs_ase *ase) ase->ep.receiver_ready = false; - ase_status_changed(ase, BT_BAP_EP_STATE_CODEC_CONFIGURED); - ops = stream->ops; if (ops != NULL && ops->configured != NULL) { ops->configured(stream, &ase->ep.qos_pref); } } -static void ase_set_state_qos_configured(struct bt_ascs_ase *ase) +static void ase_enter_state_qos_configured(struct bt_ascs_ase *ase) { struct bt_bap_stream *stream = ase->ep.stream; struct bt_bap_stream_ops *ops; @@ -285,29 +284,22 @@ static void ase_set_state_qos_configured(struct bt_ascs_ase *ase) ase->ep.receiver_ready = false; - ase_status_changed(ase, BT_BAP_EP_STATE_QOS_CONFIGURED); - ops = stream->ops; if (ops != NULL && ops->qos_set != NULL) { ops->qos_set(stream); } } -static void ase_set_state_enabling(struct bt_ascs_ase *ase) +static void ase_enter_state_enabling(struct bt_ascs_ase *ase) { - const bool state_changed = ascs_ep_get_state(&ase->ep) != BT_BAP_EP_STATE_ENABLING; struct bt_bap_stream *stream = ase->ep.stream; struct bt_bap_stream_ops *ops; __ASSERT_NO_MSG(stream != NULL); - ase_status_changed(ase, BT_BAP_EP_STATE_ENABLING); - ops = stream->ops; - if (state_changed && ops != NULL && ops->enabled != NULL) { + if (ops != NULL && ops->enabled != NULL) { ops->enabled(stream); - } else if (!state_changed && ops != NULL && ops->metadata_updated != NULL) { - ops->metadata_updated(stream); } /* SINK ASEs can autonomously go into the streaming state if the CIS is connected */ @@ -317,46 +309,69 @@ static void ase_set_state_enabling(struct bt_ascs_ase *ase) } } -static void ase_set_state_streaming(struct bt_ascs_ase *ase) +static void ase_enter_state_streaming(struct bt_ascs_ase *ase) { - const bool state_changed = ascs_ep_get_state(&ase->ep) != BT_BAP_EP_STATE_STREAMING; struct bt_bap_stream *stream = ase->ep.stream; struct bt_bap_stream_ops *ops; __ASSERT_NO_MSG(stream != NULL); - ase_status_changed(ase, BT_BAP_EP_STATE_STREAMING); - ops = stream->ops; - if (state_changed && ops != NULL && ops->started != NULL) { + if (ops != NULL && ops->started != NULL) { ops->started(stream); - } else if (!state_changed && ops != NULL && ops->metadata_updated != NULL) { + } +} + +static void ase_metadata_updated(struct bt_ascs_ase *ase) +{ + struct bt_bap_stream *stream = ase->ep.stream; + struct bt_bap_stream_ops *ops; + + __ASSERT_NO_MSG(stream != NULL); + + ops = stream->ops; + if (ops != NULL && ops->metadata_updated != NULL) { ops->metadata_updated(stream); } } -static void ase_set_state_disabling(struct bt_ascs_ase *ase) +static void ase_exit_state_streaming(struct bt_ascs_ase *ase) { struct bt_bap_stream *stream = ase->ep.stream; struct bt_bap_stream_ops *ops; + uint8_t reason = ase->ep.reason; __ASSERT_NO_MSG(stream != NULL); - ase->ep.receiver_ready = false; + if (reason == BT_HCI_ERR_SUCCESS) { + /* Default to BT_HCI_ERR_UNSPECIFIED if no other reason is set */ + reason = BT_HCI_ERR_UNSPECIFIED; + } + + ops = stream->ops; + if (ops != NULL && ops->stopped != NULL) { + ops->stopped(stream, reason); + } else { + LOG_WRN("No callback for stopped set"); + } +} + +static void ase_enter_state_disabling(struct bt_ascs_ase *ase) +{ + struct bt_bap_stream *stream = ase->ep.stream; + struct bt_bap_stream_ops *ops; - ase_status_changed(ase, BT_BAP_EP_STATE_DISABLING); + __ASSERT_NO_MSG(stream != NULL); + + ase->ep.receiver_ready = false; ops = stream->ops; if (ops != NULL && ops->disabled != NULL) { ops->disabled(stream); } - - if (ase->unexpected_iso_link_loss) { - ascs_ep_set_state(&ase->ep, BT_BAP_EP_STATE_QOS_CONFIGURED); - } } -static void ase_set_state_releasing(struct bt_ascs_ase *ase) +static void ase_enter_state_releasing(struct bt_ascs_ase *ase) { struct bt_bap_stream *stream = ase->ep.stream; @@ -364,8 +379,6 @@ static void ase_set_state_releasing(struct bt_ascs_ase *ase) ase->ep.receiver_ready = false; - ase_status_changed(ase, BT_BAP_EP_STATE_RELEASING); - /* Either the client or the server may disconnect the CISes when entering the releasing * state. */ @@ -383,52 +396,88 @@ static void ase_set_state_releasing(struct bt_ascs_ase *ase) static void state_transition_work_handler(struct k_work *work) { - struct bt_ascs_ase *ase = CONTAINER_OF(work, struct bt_ascs_ase, state_transition_work); + struct k_work_delayable *d_work = k_work_delayable_from_work(work); + struct bt_ascs_ase *ase = CONTAINER_OF(d_work, struct bt_ascs_ase, state_transition_work); const enum bt_bap_ep_state old_state = ascs_ep_get_state(&ase->ep); const enum bt_bap_ep_state new_state = ase->state_pending; - struct bt_bap_stream *stream = ase->ep.stream; - struct bt_bap_ep *ep = &ase->ep; + int err; - __ASSERT_NO_MSG(stream != NULL); + ase->ep.status.state = new_state; - /* We left the streaming state, let the upper layers know that the stream is stopped */ - if (old_state != new_state && old_state == BT_BAP_EP_STATE_STREAMING) { - struct bt_bap_stream_ops *ops = stream->ops; - uint8_t reason = ep->reason; + /* Notify ASE state */ + if (ase->conn != NULL) { + err = ase_state_notify(ase); + if (err == -ENOMEM) { + struct bt_conn_info info; + uint32_t retry_delay_ms; + + /* Revert back to old state */ + ase->ep.status.state = old_state; + + err = bt_conn_get_info(ase->conn, &info); + __ASSERT_NO_MSG(err == 0); - if (reason == BT_HCI_ERR_SUCCESS) { - /* Default to BT_HCI_ERR_UNSPECIFIED if no other reason is set */ - reason = BT_HCI_ERR_UNSPECIFIED; + retry_delay_ms = BT_CONN_INTERVAL_TO_MS(info.le.interval); + + /* Reschedule the state transition */ + err = k_work_reschedule(d_work, K_MSEC(retry_delay_ms)); + if (err >= 0) { + LOG_WRN("Out of buffers for ase state notification. " + "Will retry in %dms", retry_delay_ms); + return; + } } - if (ops != NULL && ops->stopped != NULL) { - ops->stopped(stream, reason); - } else { - LOG_WRN("No callback for stopped set"); + if (err < 0) { + LOG_ERR("Failed to notify ASE state (err %d)", err); + } + } + + LOG_DBG("ase %p id 0x%02x %s -> %s", ase, ase->ep.status.id, + bt_bap_ep_state_str(old_state), bt_bap_ep_state_str(new_state)); + + if (old_state == new_state) { + switch (new_state) { + case BT_BAP_EP_STATE_ENABLING: + case BT_BAP_EP_STATE_STREAMING: + ase_metadata_updated(ase); + return; + default: + break; } } + /* Actions needed for exiting the old state */ + switch (old_state) { + case BT_BAP_EP_STATE_STREAMING: + ase_exit_state_streaming(ase); + break; + default: + break; + } + + /* Actions needed for entering the new state */ switch (new_state) { case BT_BAP_EP_STATE_IDLE: - ase_set_state_idle(ase); + ase_enter_state_idle(ase); break; case BT_BAP_EP_STATE_CODEC_CONFIGURED: - ase_set_state_codec_configured(ase); + ase_enter_state_codec_configured(ase); break; case BT_BAP_EP_STATE_QOS_CONFIGURED: - ase_set_state_qos_configured(ase); + ase_enter_state_qos_configured(ase); break; case BT_BAP_EP_STATE_ENABLING: - ase_set_state_enabling(ase); + ase_enter_state_enabling(ase); break; case BT_BAP_EP_STATE_STREAMING: - ase_set_state_streaming(ase); + ase_enter_state_streaming(ase); break; case BT_BAP_EP_STATE_DISABLING: - ase_set_state_disabling(ase); + ase_enter_state_disabling(ase); break; case BT_BAP_EP_STATE_RELEASING: - ase_set_state_releasing(ase); + ase_enter_state_releasing(ase); break; default: __ASSERT_PRINT("Invalid state %d", new_state); @@ -468,7 +517,11 @@ int ascs_ep_set_state(struct bt_bap_ep *ep, uint8_t state) break; case BT_BAP_EP_STATE_ENABLING: case BT_BAP_EP_STATE_STREAMING: - valid_state_transition = ase->ep.dir == BT_AUDIO_DIR_SINK; + /* Source ASE transition Streaming->QoS configured is valid on case of CIS + * link-loss. + */ + valid_state_transition = ase->ep.dir == BT_AUDIO_DIR_SINK || + ase->unexpected_iso_link_loss; break; default: break; @@ -525,9 +578,9 @@ int ascs_ep_set_state(struct bt_bap_ep *ep, uint8_t state) ase->state_pending = state; - err = k_work_submit(&ase->state_transition_work); + err = k_work_schedule(&ase->state_transition_work, K_NO_WAIT); if (err < 0) { - LOG_ERR("Failed to submit state transition work err %d", err); + LOG_ERR("Failed to schedule state transition work err %d", err); return err; } @@ -872,20 +925,14 @@ static void ascs_ep_iso_disconnected(struct bt_bap_ep *ep, uint8_t reason) if (ep->status.state == BT_BAP_EP_STATE_RELEASING) { ascs_ep_set_state(ep, BT_BAP_EP_STATE_IDLE); - } else if (ep->status.state == BT_BAP_EP_STATE_STREAMING) { - /* CIS has been unexpectedly disconnected */ - ase->unexpected_iso_link_loss = true; - - /* The ASE state machine goes into different states from this operation - * based on whether it is a source or a sink ASE. + } else if (ep->status.state == BT_BAP_EP_STATE_STREAMING || + ep->status.state == BT_BAP_EP_STATE_DISABLING) { + /* ASCS_v1.0 3.2 ASE state machine transitions + * + * If the server detects link loss of a CIS for an ASE in the Streaming + * state or the Disabling state, the server shall immediately transition + * that ASE to the QoS Configured state. */ - if (ep->dir == BT_AUDIO_DIR_SOURCE) { - ascs_ep_set_state(ep, BT_BAP_EP_STATE_DISABLING); - } else { - ascs_ep_set_state(ep, BT_BAP_EP_STATE_QOS_CONFIGURED); - } - } else if (ep->status.state == BT_BAP_EP_STATE_DISABLING) { - /* CIS has been unexpectedly disconnected */ ase->unexpected_iso_link_loss = true; ascs_ep_set_state(ep, BT_BAP_EP_STATE_QOS_CONFIGURED); @@ -1018,6 +1065,12 @@ static int ase_release(struct bt_ascs_ase *ase, uint8_t reason, struct bt_bap_as int bt_ascs_release_ase(struct bt_bap_ep *ep) { struct bt_ascs_ase *ase = CONTAINER_OF(ep, struct bt_ascs_ase, ep); + const enum bt_bap_ep_state state = ascs_ep_get_state(&ase->ep); + + if (state == BT_BAP_EP_STATE_IDLE) { + ase_free(ase); + return 0; + } return ase_release(ase, BT_HCI_ERR_LOCALHOST_TERM_CONN, BT_BAP_ASCS_RSP_NULL); } @@ -1101,12 +1154,12 @@ static void disconnected(struct bt_conn *conn, uint8_t reason) * should expect there to be only a single reference to the bt_conn pointer * from the stack. * We trigger the work handler directly rather than e.g. calling - * ase_set_state_idle to trigger "regular" state change behavior (such) as + * ase_enter_state_idle to trigger "regular" state change behavior (such) as * calling stream->stopped when leaving the streaming state. */ ase->ep.reason = reason; ase->state_pending = BT_BAP_EP_STATE_IDLE; - state_transition_work_handler(&ase->state_transition_work); + state_transition_work_handler(&ase->state_transition_work.work); /* At this point, `ase` object have been free'd */ } } @@ -1203,9 +1256,8 @@ static void ase_init(struct bt_ascs_ase *ase, struct bt_conn *conn, uint8_t id) __ASSERT(ase->attr, "ASE characteristic not found\n"); - k_work_init_delayable(&ase->disconnect_work, - ascs_disconnect_stream_work_handler); - k_work_init(&ase->state_transition_work, state_transition_work_handler); + k_work_init_delayable(&ase->disconnect_work, ascs_disconnect_stream_work_handler); + k_work_init_delayable(&ase->state_transition_work, state_transition_work_handler); } static struct bt_ascs_ase *ase_new(struct bt_conn *conn, uint8_t id) @@ -1485,6 +1537,19 @@ static int ase_config(struct bt_ascs_ase *ase, const struct bt_ascs_config *cfg) return 0; } +static struct bt_bap_ep *ep_lookup_stream(struct bt_conn *conn, struct bt_bap_stream *stream) +{ + for (size_t i = 0; i < ARRAY_SIZE(ase_pool); i++) { + struct bt_ascs_ase *ase = &ase_pool[i]; + + if (ase->conn == conn && ase->ep.stream == stream) { + return &ase->ep; + } + } + + return NULL; +} + int bt_ascs_config_ase(struct bt_conn *conn, struct bt_bap_stream *stream, struct bt_audio_codec_cfg *codec_cfg, const struct bt_audio_codec_qos_pref *qos_pref) @@ -1499,7 +1564,8 @@ int bt_ascs_config_ase(struct bt_conn *conn, struct bt_bap_stream *stream, return -EINVAL; } - if (stream->ep != NULL) { + ep = ep_lookup_stream(conn, stream); + if (ep != NULL) { LOG_DBG("Stream already configured for conn %p", (void *)stream->conn); return -EALREADY; } diff --git a/subsys/bluetooth/audio/audio.c b/subsys/bluetooth/audio/audio.c index b927b928590..31e8548376e 100644 --- a/subsys/bluetooth/audio/audio.c +++ b/subsys/bluetooth/audio/audio.c @@ -34,15 +34,17 @@ int bt_audio_data_parse(const uint8_t ltv[], size_t size, } for (size_t i = 0; i < size;) { - const uint8_t len = ltv[i++]; + const uint8_t len = ltv[i]; struct bt_data data; if (i + len > size || len < sizeof(data.type)) { - LOG_DBG("Invalid len %u at i = %zu", len, i - 1); + LOG_DBG("Invalid len %u at i = %zu", len, i); return -EINVAL; } + i++; /* Increment as we have parsed the len field */ + data.type = ltv[i++]; data.data_len = len - sizeof(data.type); diff --git a/subsys/bluetooth/audio/bap_broadcast_sink.c b/subsys/bluetooth/audio/bap_broadcast_sink.c index 4fad67ce539..4d2134455b8 100644 --- a/subsys/bluetooth/audio/bap_broadcast_sink.c +++ b/subsys/bluetooth/audio/bap_broadcast_sink.c @@ -109,12 +109,17 @@ static void update_recv_state_big_synced(const struct bt_bap_broadcast_sink *sin struct bt_bap_scan_delegator_subgroup *subgroup_param = &mod_src_param.subgroups[i]; const struct bt_bap_base_subgroup *subgroup = &base->subgroups[i]; - /* Update the BIS sync indexes for the subgroup */ + /* Update the BIS sync indexes for the subgroup based on the BASE*/ for (size_t j = 0U; j < subgroup->bis_count; j++) { const struct bt_bap_base_bis_data *bis_data = &subgroup->bis_data[j]; subgroup_param->bis_sync |= BIT(bis_data->index); } + + /* Update the bis_sync so that the bis_sync value only contains the indexes that we + * are actually synced to + */ + subgroup_param->bis_sync &= sink->indexes_bitfield; } if (recv_state->encrypt_state == BT_BAP_BIG_ENC_STATE_BCODE_REQ) { @@ -146,12 +151,14 @@ static void update_recv_state_big_cleared(const struct bt_bap_broadcast_sink *si recv_state = bt_bap_scan_delegator_find_state(find_recv_state_by_sink_cb, (void *)sink); if (recv_state == NULL) { - LOG_WRN("Failed to find receive state for sink %p", sink); + /* This is likely due to the receive state being removed while we are BIG synced */ + LOG_DBG("Could not find receive state for sink %p", sink); return; } - if (recv_state->encrypt_state == BT_BAP_BIG_ENC_STATE_BCODE_REQ && + if ((recv_state->encrypt_state == BT_BAP_BIG_ENC_STATE_BCODE_REQ || + recv_state->encrypt_state == BT_BAP_BIG_ENC_STATE_DEC) && reason == BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL) { /* Sync failed due to bad broadcast code */ mod_src_param.encrypt_state = BT_BAP_BIG_ENC_STATE_BAD_CODE; @@ -360,25 +367,24 @@ static void broadcast_sink_iso_disconnected(struct bt_iso_chan *chan, broadcast_sink_set_ep_state(ep, BT_BAP_EP_STATE_IDLE); - if (ops != NULL && ops->stopped != NULL) { - ops->stopped(stream, reason); - } else { - LOG_WRN("No callback for stopped set"); - } - sink = broadcast_sink_lookup_iso_chan(chan); if (sink == NULL) { LOG_ERR("Could not lookup sink by iso %p", chan); - return; - } + } else { + if (!sys_slist_find_and_remove(&sink->streams, &stream->_node)) { + LOG_DBG("Could not find and remove stream %p from sink %p", stream, sink); + } - if (!sys_slist_find_and_remove(&sink->streams, &stream->_node)) { - LOG_DBG("Could not find and remove stream %p from sink %p", stream, sink); + /* Clear sink->big if not already cleared */ + if (sys_slist_is_empty(&sink->streams) && sink->big) { + broadcast_sink_clear_big(sink, reason); + } } - /* Clear sink->big if not already cleared */ - if (sys_slist_is_empty(&sink->streams) && sink->big) { - broadcast_sink_clear_big(sink, reason); + if (ops != NULL && ops->stopped != NULL) { + ops->stopped(stream, reason); + } else { + LOG_WRN("No callback for stopped set"); } } @@ -787,6 +793,7 @@ static void broadcast_sink_cleanup_streams(struct bt_bap_broadcast_sink *sink) } sink->stream_count = 0; + sink->indexes_bitfield = 0U; } static void broadcast_sink_cleanup(struct bt_bap_broadcast_sink *sink) @@ -797,8 +804,8 @@ static void broadcast_sink_cleanup(struct bt_bap_broadcast_sink *sink) err = bt_bap_scan_delegator_rem_src(sink->bass_src_id); if (err != 0) { - LOG_WRN("Failed to remove Receive State for sink %p: %d", - sink, err); + /* This is likely due to the receive state been removed */ + LOG_DBG("Could not remove Receive State for sink %p: %d", sink, err); } } @@ -887,6 +894,7 @@ int bt_bap_broadcast_sink_create(struct bt_le_per_adv_sync *pa_sync, uint32_t br } sink->bass_src_id = recv_state->src_id; + atomic_set_bit(sink->flags, BT_BAP_BROADCAST_SINK_FLAG_SRC_ID_VALID); } atomic_set_bit(sink->flags, BT_BAP_BROADCAST_SINK_FLAG_INITIALIZED); @@ -1028,6 +1036,7 @@ int bt_bap_broadcast_sink_sync(struct bt_bap_broadcast_sink *sink, uint32_t inde return err; } + sink->indexes_bitfield = indexes_bitfield; for (size_t i = 0; i < stream_count; i++) { struct bt_bap_ep *ep = streams[i]->ep; diff --git a/subsys/bluetooth/audio/bap_broadcast_source.c b/subsys/bluetooth/audio/bap_broadcast_source.c index 4fa436e8e32..8978e2816cb 100644 --- a/subsys/bluetooth/audio/bap_broadcast_source.c +++ b/subsys/bluetooth/audio/bap_broadcast_source.c @@ -289,6 +289,9 @@ static int broadcast_source_setup_stream(uint8_t index, struct bt_bap_stream *st bt_audio_codec_qos_to_iso_qos(iso->chan.qos->tx, qos); bt_audio_codec_cfg_to_iso_path(iso->chan.qos->tx->path, codec_cfg); +#if defined(CONFIG_BT_ISO_TEST_PARAMS) + iso->chan.qos->num_subevents = qos->num_subevents; +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ bt_bap_iso_unref(iso); @@ -306,7 +309,6 @@ static bool encode_base_subgroup(struct bt_bap_broadcast_subgroup *subgroup, struct bt_bap_stream *stream; const struct bt_audio_codec_cfg *codec_cfg; uint8_t stream_count; - uint8_t bis_index; uint8_t len; stream_count = 0; @@ -350,9 +352,10 @@ static bool encode_base_subgroup(struct bt_bap_broadcast_subgroup *subgroup, #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0 */ /* Create BIS index bitfield */ - bis_index = 0; for (uint8_t i = 0U; i < stream_count; i++) { - bis_index++; + /* Set the bis_index to *streams_encoded plus 1 as the indexes start from 1 */ + const uint8_t bis_index = *streams_encoded + 1; + if ((buf->size - buf->len) < (sizeof(bis_index) + sizeof(uint8_t))) { LOG_DBG("No room for BIS[%d] index", i); @@ -378,7 +381,7 @@ static bool encode_base_subgroup(struct bt_bap_broadcast_subgroup *subgroup, net_buf_simple_add_mem(buf, stream_data[i].data, stream_data[i].data_len); #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 */ - streams_encoded++; + (*streams_encoded)++; } return true; @@ -476,7 +479,8 @@ static void broadcast_source_cleanup(struct bt_bap_broadcast_source *source) (void)memset(source, 0, sizeof(*source)); } -static bool valid_create_param(const struct bt_bap_broadcast_source_create_param *param) +static bool valid_broadcast_source_param(const struct bt_bap_broadcast_source_param *param, + const struct bt_bap_broadcast_source *source) { const struct bt_audio_codec_qos *qos; @@ -555,7 +559,8 @@ static bool valid_create_param(const struct bt_bap_broadcast_source_create_param return false; } - CHECKIF(stream_param->stream->group != NULL) { + CHECKIF(stream_param->stream->group != NULL && + stream_param->stream->group != source) { LOG_DBG("subgroup_params[%zu].stream_params[%zu]->stream is " "already part of group %p", i, j, stream_param->stream->group); @@ -618,7 +623,7 @@ static enum bt_bap_ep_state broadcast_source_get_state(struct bt_bap_broadcast_s return stream->ep->status.state; } -int bt_bap_broadcast_source_create(struct bt_bap_broadcast_source_create_param *param, +int bt_bap_broadcast_source_create(struct bt_bap_broadcast_source_param *param, struct bt_bap_broadcast_source **out_source) { struct bt_bap_broadcast_source *source; @@ -635,7 +640,7 @@ int bt_bap_broadcast_source_create(struct bt_bap_broadcast_source_create_param * /* Set out_source to NULL until the source has actually been created */ *out_source = NULL; - if (!valid_create_param(param)) { + if (!valid_broadcast_source_param(param, NULL)) { LOG_DBG("Invalid parameters"); return -EINVAL; } @@ -723,6 +728,11 @@ int bt_bap_broadcast_source_create(struct bt_bap_broadcast_source_create_param * broadcast_source_set_state(source, BT_BAP_EP_STATE_QOS_CONFIGURED); source->qos = qos; source->packing = param->packing; +#if defined(CONFIG_BT_ISO_TEST_PARAMS) + source->irc = param->irc; + source->pto = param->pto; + source->iso_interval = param->iso_interval; +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ source->encryption = param->encryption; if (source->encryption) { @@ -738,54 +748,149 @@ int bt_bap_broadcast_source_create(struct bt_bap_broadcast_source_create_param * } int bt_bap_broadcast_source_reconfig(struct bt_bap_broadcast_source *source, - struct bt_audio_codec_cfg *codec_cfg, - struct bt_audio_codec_qos *qos) + struct bt_bap_broadcast_source_param *param) { struct bt_bap_broadcast_subgroup *subgroup; enum bt_bap_ep_state broadcast_state; - struct bt_bap_stream *stream; + struct bt_audio_codec_qos *qos; + size_t subgroup_cnt; CHECKIF(source == NULL) { LOG_DBG("source is NULL"); return -EINVAL; } - CHECKIF(!bt_audio_valid_codec_cfg(codec_cfg)) { - LOG_DBG("codec_cfg is invalid"); + if (!valid_broadcast_source_param(param, source)) { + LOG_DBG("Invalid parameters"); return -EINVAL; } - CHECKIF(qos == NULL) { - LOG_DBG("qos is NULL"); - return -EINVAL; + broadcast_state = broadcast_source_get_state(source); + if (broadcast_source_get_state(source) != BT_BAP_EP_STATE_QOS_CONFIGURED) { + LOG_DBG("Broadcast source invalid state: %u", broadcast_state); + return -EBADMSG; } - CHECKIF(bt_audio_verify_qos(qos) != BT_BAP_ASCS_REASON_NONE) { - LOG_DBG("qos is invalid"); - return -EINVAL; + /* Verify that the parameter counts do not exceed existing number of subgroups and streams*/ + subgroup_cnt = 0U; + SYS_SLIST_FOR_EACH_CONTAINER(&source->subgroups, subgroup, _node) { + const struct bt_bap_broadcast_source_subgroup_param *subgroup_param = + ¶m->params[subgroup_cnt]; + const size_t subgroup_stream_param_cnt = subgroup_param->params_count; + struct bt_bap_stream *stream; + size_t subgroup_stream_cnt = 0U; + + SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, stream, _node) { + subgroup_stream_cnt++; + } + + /* Verify that the param stream is in the subgroup */ + for (size_t i = 0U; i < subgroup_param->params_count; i++) { + struct bt_bap_stream *subgroup_stream; + struct bt_bap_stream *param_stream; + bool stream_in_subgroup; + + param_stream = subgroup_param->params[i].stream; + + SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, subgroup_stream, _node) { + if (subgroup_stream == param_stream) { + stream_in_subgroup = true; + break; + } + } + + if (!stream_in_subgroup) { + LOG_DBG("Invalid param->params[%zu]->param[%zu].stream " + "not in subgroup", + subgroup_cnt, i); + return -EINVAL; + } + } + + if (subgroup_stream_cnt < subgroup_stream_param_cnt) { + LOG_DBG("Invalid param->params[%zu]->params_count: %zu " + "(only %zu streams in subgroup)", + subgroup_cnt, subgroup_stream_param_cnt, subgroup_stream_cnt); + return -EINVAL; + } + + subgroup_cnt++; } - CHECKIF(qos->rtn > BT_ISO_BROADCAST_RTN_MAX) { - LOG_DBG("qos->rtn %u invalid", qos->rtn); + if (subgroup_cnt < param->params_count) { + LOG_DBG("Invalid param->params_count: %zu (only %zu subgroups in source)", + param->params_count, subgroup_cnt); return -EINVAL; } - broadcast_state = broadcast_source_get_state(source); - if (broadcast_source_get_state(source) != BT_BAP_EP_STATE_QOS_CONFIGURED) { - LOG_DBG("Broadcast source invalid state: %u", broadcast_state); - return -EBADMSG; - } + qos = param->qos; - SYS_SLIST_FOR_EACH_CONTAINER(&source->subgroups, subgroup, _node) { + /* We update up to the first param->params_count subgroups */ + for (size_t i = 0U; i < param->params_count; i++) { + const struct bt_bap_broadcast_source_subgroup_param *subgroup_param; + struct bt_audio_codec_cfg *codec_cfg; + struct bt_bap_stream *stream; + + if (i == 0) { + subgroup = + SYS_SLIST_PEEK_HEAD_CONTAINER(&source->subgroups, subgroup, _node); + } else { + subgroup = SYS_SLIST_PEEK_NEXT_CONTAINER(subgroup, _node); + } + + subgroup_param = ¶m->params[i]; + codec_cfg = subgroup_param->codec_cfg; + subgroup->codec_cfg = codec_cfg; + + for (size_t j = 0U; j < subgroup_param->params_count; j++) { + const struct bt_bap_broadcast_source_stream_param *stream_param; + struct bt_audio_broadcast_stream_data *stream_data; + struct bt_bap_stream *subgroup_stream; + size_t stream_idx; + + stream_param = &subgroup_param->params[j]; + stream = stream_param->stream; + + stream_idx = 0U; + SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, subgroup_stream, _node) { + if (subgroup_stream == stream) { + break; + } + + stream_idx++; + } + + /* Store the BIS specific codec configuration data in the broadcast source. + * It is stored in the broadcast* source, instead of the stream object, + * as this is only relevant for the broadcast source, and not used + * for unicast or broadcast sink. + */ + stream_data = &source->stream_data[stream_idx]; + (void)memcpy(stream_data->data, stream_param->data, stream_param->data_len); + stream_data->data_len = stream_param->data_len; + } + + /* Apply the codec_cfg to all streams in the subgroup, and not just the ones in the + * params + */ SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, stream, _node) { struct bt_iso_chan_io_qos *iso_qos; iso_qos = stream->ep->iso->chan.qos->tx; - bt_bap_stream_attach(NULL, stream, stream->ep, codec_cfg); + bt_audio_codec_cfg_to_iso_path(iso_qos->path, codec_cfg); + } + } + + /* Finally we apply the new qos and to all streams */ + SYS_SLIST_FOR_EACH_CONTAINER(&source->subgroups, subgroup, _node) { + struct bt_bap_stream *stream; + SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, stream, _node) { + struct bt_iso_chan_io_qos *iso_qos; + + iso_qos = stream->ep->iso->chan.qos->tx; bt_audio_codec_qos_to_iso_qos(iso_qos, qos); - bt_audio_codec_cfg_to_iso_path(iso_qos->path, codec_cfg); stream->qos = qos; } } @@ -883,6 +988,11 @@ int bt_bap_broadcast_source_start(struct bt_bap_broadcast_source *source, struct (void)memcpy(param.bcode, source->broadcast_code, sizeof(param.bcode)); } +#if defined(CONFIG_BT_ISO_TEST_PARAMS) + param.irc = source->irc; + param.pto = source->pto; + param.iso_interval = source->iso_interval; +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ /* Set the enabling state early in case that the BIS is connected before we can manage to * set it afterwards @@ -956,9 +1066,11 @@ int bt_bap_broadcast_source_delete(struct bt_bap_broadcast_source *source) return 0; } -int bt_bap_broadcast_source_get_id(const struct bt_bap_broadcast_source *source, +int bt_bap_broadcast_source_get_id(struct bt_bap_broadcast_source *source, uint32_t *const broadcast_id) { + enum bt_bap_ep_state broadcast_state; + CHECKIF(source == NULL) { LOG_DBG("source is NULL"); return -EINVAL; @@ -969,6 +1081,12 @@ int bt_bap_broadcast_source_get_id(const struct bt_bap_broadcast_source *source, return -EINVAL; } + broadcast_state = broadcast_source_get_state(source); + if (broadcast_state == BT_BAP_EP_STATE_IDLE) { + LOG_DBG("Broadcast source invalid state: %u", broadcast_state); + return -EBADMSG; + } + *broadcast_id = source->broadcast_id; return 0; @@ -977,6 +1095,8 @@ int bt_bap_broadcast_source_get_id(const struct bt_bap_broadcast_source *source, int bt_bap_broadcast_source_get_base(struct bt_bap_broadcast_source *source, struct net_buf_simple *base_buf) { + enum bt_bap_ep_state broadcast_state; + CHECKIF(source == NULL) { LOG_DBG("source is NULL"); return -EINVAL; @@ -987,6 +1107,12 @@ int bt_bap_broadcast_source_get_base(struct bt_bap_broadcast_source *source, return -EINVAL; } + broadcast_state = broadcast_source_get_state(source); + if (broadcast_state == BT_BAP_EP_STATE_IDLE) { + LOG_DBG("Broadcast source invalid state: %u", broadcast_state); + return -EBADMSG; + } + if (!encode_base(source, base_buf)) { LOG_DBG("base_buf %p with size %u not large enough", base_buf, base_buf->size); diff --git a/subsys/bluetooth/audio/bap_endpoint.h b/subsys/bluetooth/audio/bap_endpoint.h index a13a14d54dd..1c5aa3d5fc5 100644 --- a/subsys/bluetooth/audio/bap_endpoint.h +++ b/subsys/bluetooth/audio/bap_endpoint.h @@ -83,6 +83,12 @@ struct bt_bap_broadcast_source { struct bt_iso_big *big; struct bt_audio_codec_qos *qos; +#if defined(CONFIG_BT_ISO_TEST_PARAMS) + /* Stored advanced parameters */ + uint8_t irc; + uint8_t pto; + uint16_t iso_interval; +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 /* The codec specific configured data for each stream in the subgroup */ @@ -125,6 +131,7 @@ struct bt_bap_broadcast_sink { uint16_t iso_interval; uint16_t biginfo_num_bis; uint32_t broadcast_id; /* 24 bit */ + uint32_t indexes_bitfield; struct bt_bap_base base; struct bt_audio_codec_qos codec_qos; struct bt_le_per_adv_sync *pa_sync; diff --git a/subsys/bluetooth/audio/bap_scan_delegator.c b/subsys/bluetooth/audio/bap_scan_delegator.c index c8ddbdcd704..3cef96bd1b8 100644 --- a/subsys/bluetooth/audio/bap_scan_delegator.c +++ b/subsys/bluetooth/audio/bap_scan_delegator.c @@ -12,7 +12,6 @@ #include #include -#include #include #include @@ -460,7 +459,7 @@ static int scan_delegator_add_source(struct bt_conn *conn, /* subtract 1 as the opcode has already been pulled */ if (buf->len < sizeof(struct bt_bap_bass_cp_add_src) - 1) { LOG_DBG("Invalid length %u", buf->size); - return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN); + return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); } internal_state = get_free_recv_state(); @@ -511,7 +510,7 @@ static int scan_delegator_add_source(struct bt_conn *conn, if (buf->len < (sizeof(subgroup->bis_sync) + sizeof(subgroup->metadata_len))) { LOG_DBG("Invalid length %u", buf->size); - return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN); + return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); } internal_state->requested_bis_sync[i] = net_buf_simple_pull_le32(buf); @@ -546,7 +545,7 @@ static int scan_delegator_add_source(struct bt_conn *conn, if (buf->len < subgroup->metadata_len) { LOG_DBG("Invalid length %u", buf->size); - return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN); + return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); } @@ -564,7 +563,7 @@ static int scan_delegator_add_source(struct bt_conn *conn, if (buf->len != 0) { LOG_DBG("Invalid length %u", buf->size); - return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN); + return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); } if (pa_sync != BT_BAP_BASS_PA_REQ_NO_SYNC) { @@ -626,7 +625,7 @@ static int scan_delegator_mod_src(struct bt_conn *conn, if (buf->len < sizeof(struct bt_bap_bass_cp_mod_src) - 1) { LOG_DBG("Invalid length %u", buf->len); - return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN); + return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); } src_id = net_buf_simple_pull_u8(buf); @@ -665,7 +664,7 @@ static int scan_delegator_mod_src(struct bt_conn *conn, if (buf->len < (sizeof(subgroup->bis_sync) + sizeof(subgroup->metadata_len))) { LOG_DBG("Invalid length %u", buf->len); - return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN); + return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); } old_bis_sync_req = internal_state->requested_bis_sync[i]; @@ -700,7 +699,7 @@ static int scan_delegator_mod_src(struct bt_conn *conn, if (buf->len < subgroup->metadata_len) { LOG_DBG("Invalid length %u", buf->len); - return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN); + return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); } if (subgroup->metadata_len > CONFIG_BT_BAP_SCAN_DELEGATOR_MAX_METADATA_LEN) { @@ -718,7 +717,7 @@ static int scan_delegator_mod_src(struct bt_conn *conn, if (buf->len != 0) { LOG_DBG("Invalid length %u", buf->size); - return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN); + return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); } /* All input has been validated; update receive state and check for changes */ @@ -771,6 +770,20 @@ static int scan_delegator_mod_src(struct bt_conn *conn, return err; } + } else if (pa_sync == BT_BAP_BASS_PA_REQ_NO_SYNC && + (state->pa_sync_state == BT_BAP_PA_STATE_INFO_REQ || + state->pa_sync_state == BT_BAP_PA_STATE_SYNCED)) { + /* Terminate PA sync */ + const int err = pa_sync_term_request(conn, &internal_state->state); + + if (err != 0) { + LOG_DBG("PA sync term from %p was reject with reason %d", + conn, err); + + return err; + } + + state_changed = true; } /* Notify if changed */ @@ -798,7 +811,7 @@ static int scan_delegator_broadcast_code(struct bt_conn *conn, /* subtract 1 as the opcode has already been pulled */ if (buf->len != sizeof(struct bt_bap_bass_cp_broadcase_code) - 1) { LOG_DBG("Invalid length %u", buf->size); - return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN); + return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); } src_id = net_buf_simple_pull_u8(buf); @@ -831,12 +844,13 @@ static int scan_delegator_rem_src(struct bt_conn *conn, { struct bass_recv_state_internal *internal_state; struct bt_bap_scan_delegator_recv_state *state; + bool bis_sync_was_requested; uint8_t src_id; /* subtract 1 as the opcode has already been pulled */ if (buf->len != sizeof(struct bt_bap_bass_cp_rem_src) - 1) { LOG_DBG("Invalid length %u", buf->size); - return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN); + return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); } src_id = net_buf_simple_pull_u8(buf); @@ -863,6 +877,14 @@ static int scan_delegator_rem_src(struct bt_conn *conn, } } + bis_sync_was_requested = false; + for (uint8_t i = 0U; i < state->num_subgroups; i++) { + if (internal_state->requested_bis_sync[i] != 0U) { + bis_sync_was_requested = true; + break; + } + } + LOG_DBG("Index %u: Removed source with ID 0x%02x", internal_state->index, src_id); @@ -874,6 +896,9 @@ static int scan_delegator_rem_src(struct bt_conn *conn, (void)memset(internal_state->requested_bis_sync, 0, sizeof(internal_state->requested_bis_sync)); + if (bis_sync_was_requested) { + bis_sync_request_updated(conn, internal_state); + } receive_state_updated(conn, internal_state); return 0; @@ -892,7 +917,7 @@ static ssize_t write_control_point(struct bt_conn *conn, if (offset != 0) { return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET); } else if (len == 0) { - return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN); + return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); } net_buf_simple_init_with_data(&buf, (void *)data, len); @@ -917,7 +942,7 @@ static ssize_t write_control_point(struct bt_conn *conn, if (buf.len != 0) { LOG_DBG("Invalid length %u", buf.size); - return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN); + return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); } bap_broadcast_assistant->scanning = false; @@ -927,7 +952,7 @@ static ssize_t write_control_point(struct bt_conn *conn, if (buf.len != 0) { LOG_DBG("Invalid length %u", buf.size); - return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN); + return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); } bap_broadcast_assistant->scanning = true; break; @@ -1030,7 +1055,7 @@ BT_GATT_SERVICE_DEFINE(bass_svc, #endif /* CONFIG_BT_BAP_SCAN_DELEGATOR_RECV_STATE_COUNT > 1 */ ); -static int bt_bap_scan_delegator_init(const struct device *unused) +static int bt_bap_scan_delegator_init(void) { /* Store the pointer to the first characteristic in each receive state */ scan_delegator.recv_states[0].attr = &bass_svc.attrs[3]; @@ -1049,9 +1074,7 @@ static int bt_bap_scan_delegator_init(const struct device *unused) return 0; } -DEVICE_DEFINE(bt_bap_scan_delegator, "bt_bap_scan_delegator", - &bt_bap_scan_delegator_init, NULL, NULL, NULL, - APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, NULL); +SYS_INIT(bt_bap_scan_delegator_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); /****************************** PUBLIC API ******************************/ void bt_bap_scan_delegator_register_cb(struct bt_bap_scan_delegator_cb *cb) @@ -1301,7 +1324,7 @@ int bt_bap_scan_delegator_mod_src(const struct bt_bap_scan_delegator_mod_src_par { struct bass_recv_state_internal *internal_state = NULL; struct bt_bap_scan_delegator_recv_state *state; - static bool state_changed; + bool state_changed = false; CHECKIF(!valid_bt_bap_scan_delegator_mod_src_param(param)) { return -EINVAL; @@ -1326,6 +1349,11 @@ int bt_bap_scan_delegator_mod_src(const struct bt_bap_scan_delegator_mod_src_par state_changed = true; } + if (state->encrypt_state != param->encrypt_state) { + state->encrypt_state = param->encrypt_state; + state_changed = true; + } + /* Verify that the BIS sync values is acceptable for the receive state */ for (uint8_t i = 0U; i < state->num_subgroups; i++) { const uint32_t bis_sync = param->subgroups[i].bis_sync; @@ -1343,7 +1371,10 @@ int bt_bap_scan_delegator_mod_src(const struct bt_bap_scan_delegator_mod_src_par const struct bt_bap_scan_delegator_subgroup *param_subgroup = ¶m->subgroups[i]; struct bt_bap_scan_delegator_subgroup *subgroup = &state->subgroups[i]; - subgroup->bis_sync = param_subgroup->bis_sync; + if (subgroup->bis_sync != param_subgroup->bis_sync) { + subgroup->bis_sync = param_subgroup->bis_sync; + state_changed = true; + } /* If the metadata len is 0, we shall not overwrite the existing metadata */ if (param_subgroup->metadata_len == 0U) { diff --git a/subsys/bluetooth/audio/bap_stream.c b/subsys/bluetooth/audio/bap_stream.c index 2d315ce227e..23e5bb8564b 100644 --- a/subsys/bluetooth/audio/bap_stream.c +++ b/subsys/bluetooth/audio/bap_stream.c @@ -51,6 +51,10 @@ void bt_audio_codec_qos_to_iso_qos(struct bt_iso_chan_io_qos *io, io->sdu = codec_qos->sdu; io->phy = codec_qos->phy; io->rtn = codec_qos->rtn; +#if defined(CONFIG_BT_ISO_TEST_PARAMS) + io->burst_number = codec_qos->burst_number; + io->max_pdu = codec_qos->max_pdu; +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ } #endif /* CONFIG_BT_BAP_UNICAST_CLIENT || \ * CONFIG_BT_BAP_BROADCAST_SOURCE || \ @@ -195,7 +199,27 @@ bool bt_audio_valid_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg) return false; } + if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) { + if (codec_cfg->cid != 0U) { + LOG_DBG("codec_cfg->cid (%u) is invalid", codec_cfg->cid); + return false; + } + + if (codec_cfg->vid != 0U) { + LOG_DBG("codec_cfg->vid (%u) is invalid", codec_cfg->vid); + return false; + } + } + #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 + /* Verify that codec configuration length is 0 when using + * BT_HCI_CODING_FORMAT_TRANSPARENT as per the core spec, 5.4, Vol 4, Part E, 7.8.109 + */ + if (codec_cfg->id == BT_HCI_CODING_FORMAT_TRANSPARENT && codec_cfg->data_len != 0) { + LOG_DBG("Invalid data_len %zu for codec_id %u", codec_cfg->data_len, codec_cfg->id); + return false; + } + if (codec_cfg->data_len > CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE) { LOG_DBG("codec_cfg->data_len (%zu) is invalid", codec_cfg->data_len); return false; @@ -253,6 +277,16 @@ int bt_bap_stream_send(struct bt_bap_stream *stream, struct net_buf *buf, return -EBADMSG; } +#if defined(CONFIG_BT_BAP_DEBUG_STREAM_SEQ_NUM) + if (stream->_prev_seq_num != 0U && seq_num != 0U && + (stream->_prev_seq_num + 1U) != seq_num) { + LOG_WRN("Unexpected seq_num diff between %u and %u for %p", stream->_prev_seq_num, + seq_num, stream); + } + + stream->_prev_seq_num = seq_num; +#endif /* CONFIG_BT_BAP_DEBUG_STREAM_SEQ_NUM */ + /* TODO: Add checks for broadcast sink */ return bt_iso_chan_send(bt_bap_stream_iso_chan_get(stream), @@ -769,7 +803,7 @@ int bt_bap_stream_release(struct bt_bap_stream *stream) LOG_DBG("stream %p", stream); CHECKIF(stream == NULL || stream->ep == NULL || stream->conn == NULL) { - LOG_DBG("Invalid stream"); + LOG_DBG("Invalid stream (ep %p, conn %p)", stream->ep, (void *)stream->conn); return -EINVAL; } diff --git a/subsys/bluetooth/audio/bap_unicast_client.c b/subsys/bluetooth/audio/bap_unicast_client.c index 4ab7b95232f..933db93ec72 100644 --- a/subsys/bluetooth/audio/bap_unicast_client.c +++ b/subsys/bluetooth/audio/bap_unicast_client.c @@ -1212,7 +1212,7 @@ static int unicast_client_set_codec_cap(uint8_t id, uint16_t cid, uint16_t vid, /* If codec is LC3, then it shall be LTV encoded - We verify this before storing the * data For any non-LC3 codecs, we cannot verify anything */ - if (id == BT_AUDIO_CODEC_LC3_ID) { + if (id == BT_HCI_CODING_FORMAT_LC3) { bt_data_parse(&buf, valid_ltv_cb, NULL); /* Check if all entries could be parsed */ @@ -2085,13 +2085,25 @@ static void unicast_client_ep_reset(struct bt_conn *conn, uint8_t reason) } static void bt_audio_codec_qos_to_cig_param(struct bt_iso_cig_param *cig_param, - const struct bt_audio_codec_qos *qos) + const struct bt_audio_codec_qos *qos, + const struct bt_bap_unicast_group_param *group_param) { cig_param->framing = qos->framing; cig_param->packing = BT_ISO_PACKING_SEQUENTIAL; /* TODO: Add to QoS struct */ - cig_param->interval = qos->interval; - cig_param->latency = qos->latency; + cig_param->c_to_p_interval = qos->interval; + cig_param->p_to_c_interval = qos->interval; + cig_param->c_to_p_latency = qos->latency; + cig_param->p_to_c_latency = qos->latency; cig_param->sca = BT_GAP_SCA_UNKNOWN; + + if (group_param != NULL) { + cig_param->packing = group_param->packing; +#if defined(CONFIG_BT_ISO_TEST_PARAMS) + cig_param->c_to_p_ft = group_param->c_to_p_ft; + cig_param->p_to_c_ft = group_param->p_to_c_ft; + cig_param->iso_interval = group_param->iso_interval; +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ + } } /* FIXME: Remove `qos` parameter. Some of the QoS related CIG can be different @@ -2099,7 +2111,8 @@ static void bt_audio_codec_qos_to_cig_param(struct bt_iso_cig_param *cig_param, * unicast_group instead. */ static int bt_audio_cig_create(struct bt_bap_unicast_group *group, - const struct bt_audio_codec_qos *qos) + const struct bt_audio_codec_qos *qos, + const struct bt_bap_unicast_group_param *group_param) { struct bt_iso_cig_param param; uint8_t cis_count; @@ -2119,7 +2132,7 @@ static int bt_audio_cig_create(struct bt_bap_unicast_group *group, param.num_cis = cis_count; param.cis_channels = group->cis; - bt_audio_codec_qos_to_cig_param(¶m, qos); + bt_audio_codec_qos_to_cig_param(¶m, qos, group_param); err = bt_iso_cig_create(¶m, &group->cig); if (err != 0) { @@ -2153,7 +2166,7 @@ static int bt_audio_cig_reconfigure(struct bt_bap_unicast_group *group, param.num_cis = cis_count; param.cis_channels = group->cis; - bt_audio_codec_qos_to_cig_param(¶m, qos); + bt_audio_codec_qos_to_cig_param(¶m, qos, NULL); err = bt_iso_cig_reconfigure(group->cig, ¶m); if (err != 0) { @@ -2301,6 +2314,9 @@ static void unicast_client_codec_qos_to_iso_qos(struct bt_bap_iso *iso, } bt_audio_codec_qos_to_iso_qos(io_qos, qos); +#if defined(CONFIG_BT_ISO_TEST_PARAMS) + iso->chan.qos->num_subevents = qos->num_subevents; +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ if (other_io_qos != NULL) { /* If the opposing ASE of the CIS is not yet configured, we @@ -2591,7 +2607,7 @@ int bt_bap_unicast_group_create(struct bt_bap_unicast_group_param *param, } } - err = bt_audio_cig_create(unicast_group, group_qos); + err = bt_audio_cig_create(unicast_group, group_qos, param); if (err != 0) { LOG_DBG("bt_audio_cig_create failed: %d", err); unicast_group_free(unicast_group); diff --git a/subsys/bluetooth/audio/cap_acceptor.c b/subsys/bluetooth/audio/cap_acceptor.c index db32d382e2a..56ed5fa2daa 100644 --- a/subsys/bluetooth/audio/cap_acceptor.c +++ b/subsys/bluetooth/audio/cap_acceptor.c @@ -27,6 +27,16 @@ int bt_cap_acceptor_register(const struct bt_csip_set_member_register_param *par static struct bt_gatt_service cas; int err; + CHECKIF(param->set_size == 0U) { + LOG_DBG("param->set_size shall be non-zero"); + return -EINVAL; + } + + CHECKIF(param->rank == 0U) { + LOG_DBG("param->rank shall be non-zero"); + return -EINVAL; + } + err = bt_csip_set_member_register(param, svc_inst); if (err != 0) { LOG_DBG("Failed to register CSIP"); diff --git a/subsys/bluetooth/audio/cap_commander.c b/subsys/bluetooth/audio/cap_commander.c new file mode 100644 index 00000000000..ffe8cd0f89a --- /dev/null +++ b/subsys/bluetooth/audio/cap_commander.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2022-2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include "cap_internal.h" +#include "ccid_internal.h" +#include "csip_internal.h" +#include "bap_endpoint.h" + +#include + +LOG_MODULE_REGISTER(bt_cap_commander, CONFIG_BT_CAP_COMMANDER_LOG_LEVEL); + +#include "common/bt_str.h" + +int bt_cap_commander_unicast_discover(struct bt_conn *conn) +{ + return -ENOSYS; +} + +int bt_cap_commander_broadcast_reception_start( + const struct bt_cap_commander_broadcast_reception_start_param *param) +{ + return -ENOSYS; +} + +int bt_cap_commander_broadcast_reception_stop( + const struct bt_cap_commander_broadcast_reception_stop_param *param) +{ + return -ENOSYS; +} + +int bt_cap_commander_change_volume(const struct bt_cap_commander_change_volume_param *param) +{ + return -ENOSYS; +} + +int bt_cap_commander_change_volume_offset( + const struct bt_cap_commander_change_volume_offset_param *param) +{ + return -ENOSYS; +} + +int bt_cap_commander_change_volume_mute_state( + const struct bt_cap_commander_change_volume_mute_state_param *param) +{ + return -ENOSYS; +} + +int bt_cap_commander_change_microphone_mute_state( + const struct bt_cap_commander_change_microphone_mute_state_param *param) +{ + return -ENOSYS; +} + +int bt_cap_commander_change_microphone_gain_setting( + const struct bt_cap_commander_change_microphone_gain_setting_param *param) +{ + + return -ENOSYS; +} diff --git a/subsys/bluetooth/audio/cap_initiator.c b/subsys/bluetooth/audio/cap_initiator.c index b8ceb017057..46b39afcb41 100644 --- a/subsys/bluetooth/audio/cap_initiator.c +++ b/subsys/bluetooth/audio/cap_initiator.c @@ -10,6 +10,7 @@ #include #include #include "cap_internal.h" +#include "ccid_internal.h" #include "csip_internal.h" #include "bap_endpoint.h" @@ -38,9 +39,14 @@ int bt_cap_initiator_register_cb(const struct bt_cap_initiator_cb *cb) return 0; } +struct valid_metadata_param { + bool stream_context_found; + bool valid; +}; + static bool data_func_cb(struct bt_data *data, void *user_data) { - bool *stream_context_found = (bool *)user_data; + struct valid_metadata_param *metadata_param = (struct valid_metadata_param *)user_data; LOG_DBG("type %u len %u data %s", data->type, data->data_len, bt_hex(data->data, data->data_len)); @@ -50,8 +56,21 @@ static bool data_func_cb(struct bt_data *data, void *user_data) return false; } - *stream_context_found = true; - return false; + metadata_param->stream_context_found = true; + } else if (IS_ENABLED(CONFIG_BT_CCID) && data->type == BT_AUDIO_METADATA_TYPE_CCID_LIST) { + /* If the application supplies a CCID list, we verify that the CCIDs exist on our + * device + */ + for (uint8_t i = 0U; i < data->data_len; i++) { + const uint8_t ccid = data->data[i]; + + if (bt_ccid_find_attr(ccid) == NULL) { + LOG_DBG("Unknown characterstic for CCID 0x%02X", ccid); + metadata_param->valid = false; + + return false; + } + } } return true; @@ -59,21 +78,24 @@ static bool data_func_cb(struct bt_data *data, void *user_data) static bool cap_initiator_valid_metadata(const uint8_t meta[], size_t meta_len) { - bool stream_context_found = false; + struct valid_metadata_param metadata_param = { + .stream_context_found = false, + .valid = true, + }; int err; LOG_DBG("meta %p len %zu", meta, meta_len); - err = bt_audio_data_parse(meta, meta_len, data_func_cb, &stream_context_found); + err = bt_audio_data_parse(meta, meta_len, data_func_cb, &metadata_param); if (err != 0 && err != -ECANCELED) { return false; } - if (!stream_context_found) { + if (!metadata_param.stream_context_found) { LOG_DBG("No streaming context supplied"); } - return stream_context_found; + return metadata_param.stream_context_found && metadata_param.valid; } #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE) @@ -114,7 +136,7 @@ static bool cap_initiator_broadcast_audio_start_valid_param( static void cap_initiator_broadcast_to_bap_broadcast_param( const struct bt_cap_initiator_broadcast_create_param *cap_param, - struct bt_bap_broadcast_source_create_param *bap_param, + struct bt_bap_broadcast_source_param *bap_param, struct bt_bap_broadcast_source_subgroup_param bap_subgroup_params[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT], struct bt_bap_broadcast_source_stream_param @@ -170,7 +192,7 @@ int bt_cap_initiator_broadcast_audio_create( bap_subgroup_params[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT]; struct bt_bap_broadcast_source_stream_param bap_stream_params[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT]; - struct bt_bap_broadcast_source_create_param bap_create_param; + struct bt_bap_broadcast_source_param bap_create_param; CHECKIF(param == NULL) { LOG_DBG("param is NULL"); @@ -314,6 +336,23 @@ enum cap_unicast_subproc_type { CAP_UNICAST_SUBPROC_TYPE_RELEASE, }; +struct cap_unicast_proc_param { + struct bt_cap_stream *stream; + union { + struct { + struct bt_conn *conn; + struct bt_bap_ep *ep; + struct bt_audio_codec_cfg codec_cfg; + } start; + struct { + /** Codec Specific Capabilities Metadata count */ + size_t meta_len; + /** Codec Specific Capabilities Metadata */ + uint8_t meta[CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE]; + } meta_update; + }; +}; + struct cap_unicast_proc { ATOMIC_DEFINE(proc_state_flags, CAP_UNICAST_PROC_STATE_FLAG_NUM); /* Total number of streams in the procedure*/ @@ -326,7 +365,7 @@ struct cap_unicast_proc { enum cap_unicast_subproc_type subproc_type; int err; struct bt_conn *failed_conn; - struct bt_cap_stream *streams[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT]; + struct cap_unicast_proc_param proc_param[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT]; struct bt_bap_unicast_group *unicast_group; }; @@ -388,7 +427,7 @@ static bool cap_conn_in_active_proc(const struct bt_conn *conn) } for (size_t i = 0U; i < active_proc.stream_initiated_cnt; i++) { - if (active_proc.streams[i]->bap_stream.conn == conn) { + if (active_proc.proc_param[i].stream->bap_stream.conn == conn) { return true; } } @@ -619,7 +658,7 @@ static bool cap_stream_in_active_proc(const struct bt_cap_stream *cap_stream) } for (size_t i = 0U; i < active_proc.stream_cnt; i++) { - if (active_proc.streams[i] == cap_stream) { + if (active_proc.proc_param[i].stream == cap_stream) { return true; } } @@ -749,71 +788,6 @@ static bool valid_unicast_audio_start_param(const struct bt_cap_unicast_audio_st return true; } -static int cap_initiator_unicast_audio_configure( - const struct bt_cap_unicast_audio_start_param *param) -{ - /** TODO: If this is a CSIP set, then the order of the procedures may - * not match the order in the parameters, and the CSIP ordered access - * procedure should be used. - */ - - /* Store the information about the active procedure so that we can - * continue the procedure after each step - */ - atomic_set_bit(active_proc.proc_state_flags, CAP_UNICAST_PROC_STATE_ACTIVE); - active_proc.stream_cnt = param->count; - - cap_set_subproc(CAP_UNICAST_SUBPROC_TYPE_CODEC_CONFIG); - - for (size_t i = 0U; i < param->count; i++) { - struct bt_cap_unicast_audio_start_stream_param *stream_param = - ¶m->stream_params[i]; - union bt_cap_set_member *member = &stream_param->member; - struct bt_cap_stream *cap_stream = stream_param->stream; - struct bt_bap_stream *bap_stream = &cap_stream->bap_stream; - struct bt_bap_ep *ep = stream_param->ep; - struct bt_audio_codec_cfg *codec_cfg = stream_param->codec_cfg; - struct bt_conn *conn; - int err; - - if (param->type == BT_CAP_SET_TYPE_AD_HOC) { - conn = member->member; - } else { - struct cap_unicast_client *client; - - /* We have verified that `client` wont be NULL in - * `valid_unicast_audio_start_param`. - */ - client = lookup_unicast_client_by_csis(member->csip); - __ASSERT(client != NULL, "client is NULL"); - conn = client->conn; - } - - /* Ensure that ops are registered before any procedures are started */ - bt_cap_stream_ops_register_bap(cap_stream); - - active_proc.streams[i] = cap_stream; - - err = bt_bap_stream_config(conn, bap_stream, ep, codec_cfg); - if (err != 0) { - LOG_DBG("bt_bap_stream_config failed for param->stream_params[%zu]: %d", - i, err); - - if (i > 0U) { - cap_abort_proc(bap_stream->conn, err); - } else { - (void)memset(&active_proc, 0, sizeof(active_proc)); - } - - return err; - } - - active_proc.stream_initiated_cnt++; - } - - return 0; -} - static void cap_initiator_unicast_audio_proc_complete(void) { struct bt_bap_unicast_group *unicast_group; @@ -853,6 +827,82 @@ static void cap_initiator_unicast_audio_proc_complete(void) } } +static int cap_initiator_unicast_audio_configure( + const struct bt_cap_unicast_audio_start_param *param) +{ + struct cap_unicast_proc_param *proc_param; + struct bt_audio_codec_cfg *codec_cfg; + struct bt_bap_stream *bap_stream; + struct bt_bap_ep *ep; + struct bt_conn *conn; + int err; + /** TODO: If this is a CSIP set, then the order of the procedures may + * not match the order in the parameters, and the CSIP ordered access + * procedure should be used. + */ + + for (size_t i = 0U; i < param->count; i++) { + struct bt_cap_unicast_audio_start_stream_param *stream_param = + ¶m->stream_params[i]; + union bt_cap_set_member *member = &stream_param->member; + struct bt_cap_stream *cap_stream = stream_param->stream; + + if (param->type == BT_CAP_SET_TYPE_AD_HOC) { + conn = member->member; + } else { + struct cap_unicast_client *client; + + /* We have verified that `client` wont be NULL in + * `valid_unicast_audio_start_param`. + */ + client = lookup_unicast_client_by_csis(member->csip); + __ASSERT(client != NULL, "client is NULL"); + conn = client->conn; + } + + /* Ensure that ops are registered before any procedures are started */ + bt_cap_stream_ops_register_bap(cap_stream); + + /* Store the necessary parameters as we cannot assume that the supplied parameters + * are kept valid + */ + active_proc.proc_param[i].stream = cap_stream; + active_proc.proc_param[i].start.ep = stream_param->ep; + active_proc.proc_param[i].start.conn = conn; + memcpy(&active_proc.proc_param[i].start.codec_cfg, stream_param->codec_cfg, + sizeof(*stream_param->codec_cfg)); + } + + /* Store the information about the active procedure so that we can + * continue the procedure after each step + */ + atomic_set_bit(active_proc.proc_state_flags, CAP_UNICAST_PROC_STATE_ACTIVE); + active_proc.stream_cnt = param->count; + + cap_set_subproc(CAP_UNICAST_SUBPROC_TYPE_CODEC_CONFIG); + + proc_param = &active_proc.proc_param[0]; + bap_stream = &proc_param->stream->bap_stream; + codec_cfg = &proc_param->start.codec_cfg; + conn = proc_param->start.conn; + ep = proc_param->start.ep; + + /* Since BAP operations may require a write long or a read long on the notification, + * we cannot assume that we can do multiple streams at once, thus do it one at a time. + * TODO: We should always be able to do one per ACL, so there is room for optimization. + */ + err = bt_bap_stream_config(conn, bap_stream, ep, codec_cfg); + if (err != 0) { + LOG_DBG("Failed to config stream %p: %d", proc_param->stream, err); + + (void)memset(&active_proc, 0, sizeof(active_proc)); + } else { + active_proc.stream_initiated_cnt++; + } + + return err; +} + int bt_cap_initiator_unicast_audio_start(const struct bt_cap_unicast_audio_start_param *param, struct bt_bap_unicast_group *unicast_group) { @@ -879,8 +929,9 @@ int bt_cap_initiator_unicast_audio_start(const struct bt_cap_unicast_audio_start void bt_cap_initiator_codec_configured(struct bt_cap_stream *cap_stream) { - struct bt_conn *conns[MIN(CONFIG_BT_MAX_CONN, - CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT)]; + struct bt_conn + *conns[MIN(CONFIG_BT_MAX_CONN, CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT)]; + struct cap_unicast_proc_param *proc_param; struct bt_bap_unicast_group *unicast_group; if (!cap_stream_in_active_proc(cap_stream)) { @@ -900,14 +951,8 @@ void bt_cap_initiator_codec_configured(struct bt_cap_stream *cap_stream) } else { active_proc.stream_done_cnt++; - LOG_DBG("Stream %p configured (%zu/%zu streams done)", - cap_stream, active_proc.stream_done_cnt, - active_proc.stream_cnt); - - if (!cap_proc_is_done()) { - /* Not yet finished, wait for all */ - return; - } + LOG_DBG("Stream %p configured (%zu/%zu streams done)", cap_stream, + active_proc.stream_done_cnt, active_proc.stream_cnt); } if (cap_proc_is_aborted()) { @@ -918,13 +963,43 @@ void bt_cap_initiator_codec_configured(struct bt_cap_stream *cap_stream) return; } + if (!cap_proc_is_done()) { + struct bt_cap_stream *next_cap_stream = + active_proc.proc_param[active_proc.stream_done_cnt].stream; + struct bt_conn *conn = + active_proc.proc_param[active_proc.stream_done_cnt].start.conn; + struct bt_bap_ep *ep = active_proc.proc_param[active_proc.stream_done_cnt].start.ep; + struct bt_audio_codec_cfg *codec_cfg = + &active_proc.proc_param[active_proc.stream_done_cnt].start.codec_cfg; + struct bt_bap_stream *bap_stream = &next_cap_stream->bap_stream; + int err; + + /* Since BAP operations may require a write long or a read long on the notification, + * we cannot assume that we can do multiple streams at once, thus do it one at a + * time. + * TODO: We should always be able to do one per ACL, so there is room for + * optimization. + */ + err = bt_bap_stream_config(conn, bap_stream, ep, codec_cfg); + if (err != 0) { + LOG_DBG("Failed to config stream %p: %d", next_cap_stream, err); + + cap_abort_proc(conn, err); + cap_initiator_unicast_audio_proc_complete(); + } else { + active_proc.stream_initiated_cnt++; + } + + return; + } + /* The QoS Configure procedure works on a set of connections and a * unicast group, so we generate a list of unique connection pointers * for the procedure */ (void)memset(conns, 0, sizeof(conns)); for (size_t i = 0U; i < active_proc.stream_cnt; i++) { - struct bt_conn *stream_conn = active_proc.streams[i]->bap_stream.conn; + struct bt_conn *stream_conn = active_proc.proc_param[i].stream->bap_stream.conn; struct bt_conn **free_conn = NULL; bool already_added = false; @@ -951,7 +1026,8 @@ void bt_cap_initiator_codec_configured(struct bt_cap_stream *cap_stream) /* All streams in the procedure share the same unicast group, so we just * use the reference from the first stream */ - unicast_group = (struct bt_bap_unicast_group *)active_proc.streams[0]->bap_stream.group; + proc_param = &active_proc.proc_param[0]; + unicast_group = (struct bt_bap_unicast_group *)proc_param->stream->bap_stream.group; cap_set_subproc(CAP_UNICAST_SUBPROC_TYPE_QOS_CONFIG); for (size_t i = 0U; i < ARRAY_SIZE(conns); i++) { @@ -985,6 +1061,11 @@ void bt_cap_initiator_codec_configured(struct bt_cap_stream *cap_stream) void bt_cap_initiator_qos_configured(struct bt_cap_stream *cap_stream) { + struct cap_unicast_proc_param *proc_param; + struct bt_cap_stream *next_cap_stream; + struct bt_bap_stream *bap_stream; + int err; + if (!cap_stream_in_active_proc(cap_stream)) { /* State change happened outside of a procedure; ignore */ return; @@ -996,14 +1077,8 @@ void bt_cap_initiator_qos_configured(struct bt_cap_stream *cap_stream) } else { active_proc.stream_done_cnt++; - LOG_DBG("Stream %p QoS configured (%zu/%zu streams done)", - cap_stream, active_proc.stream_done_cnt, - active_proc.stream_cnt); - - if (!cap_proc_is_done()) { - /* Not yet finished, wait for all */ - return; - } + LOG_DBG("Stream %p QoS configured (%zu/%zu streams done)", cap_stream, + active_proc.stream_done_cnt, active_proc.stream_cnt); } if (cap_proc_is_aborted()) { @@ -1014,36 +1089,35 @@ void bt_cap_initiator_qos_configured(struct bt_cap_stream *cap_stream) return; } - cap_set_subproc(CAP_UNICAST_SUBPROC_TYPE_ENABLE); - - for (size_t i = 0U; i < active_proc.stream_cnt; i++) { - struct bt_cap_stream *cap_stream_active = active_proc.streams[i]; - struct bt_bap_stream *bap_stream = &cap_stream_active->bap_stream; - int err; + if (!cap_proc_is_done()) { + /* Not yet finished, wait for all */ + return; + } - /* TODO: Add metadata */ - err = bt_bap_stream_enable(bap_stream, bap_stream->codec_cfg->meta, - bap_stream->codec_cfg->meta_len); - if (err != 0) { - LOG_DBG("Failed to enable stream %p: %d", - cap_stream_active, err); + cap_set_subproc(CAP_UNICAST_SUBPROC_TYPE_ENABLE); + proc_param = &active_proc.proc_param[0]; + next_cap_stream = proc_param->stream; + bap_stream = &next_cap_stream->bap_stream; - /* End or mark procedure as aborted. - * If we have sent any requests over air, we will abort - * once all sent requests has completed - */ - cap_abort_proc(bap_stream->conn, err); - if (i == 0U) { - cap_initiator_unicast_audio_proc_complete(); - } + /* Since BAP operations may require a write long or a read long on the notification, we + * cannot assume that we can do multiple streams at once, thus do it one at a time. + * TODO: We should always be able to do one per ACL, so there is room for optimization. + */ + err = bt_bap_stream_enable(bap_stream, bap_stream->codec_cfg->meta, + bap_stream->codec_cfg->meta_len); + if (err != 0) { + LOG_DBG("Failed to enable stream %p: %d", next_cap_stream, err); - return; - } + cap_abort_proc(bap_stream->conn, err); + cap_initiator_unicast_audio_proc_complete(); + } else { + active_proc.stream_initiated_cnt++; } } void bt_cap_initiator_enabled(struct bt_cap_stream *cap_stream) { + struct cap_unicast_proc_param *proc_param; struct bt_bap_stream *bap_stream; int err; @@ -1058,14 +1132,8 @@ void bt_cap_initiator_enabled(struct bt_cap_stream *cap_stream) } else { active_proc.stream_done_cnt++; - LOG_DBG("Stream %p enabled (%zu/%zu streams done)", - cap_stream, active_proc.stream_done_cnt, - active_proc.stream_cnt); - - if (!cap_proc_is_done()) { - /* Not yet finished, wait for all */ - return; - } + LOG_DBG("Stream %p enabled (%zu/%zu streams done)", cap_stream, + active_proc.stream_done_cnt, active_proc.stream_cnt); } if (cap_proc_is_aborted()) { @@ -1076,17 +1144,42 @@ void bt_cap_initiator_enabled(struct bt_cap_stream *cap_stream) return; } - cap_set_subproc(CAP_UNICAST_SUBPROC_TYPE_START); + if (!cap_proc_is_done()) { + struct bt_cap_stream *next_cap_stream = + active_proc.proc_param[active_proc.stream_done_cnt].stream; + struct bt_bap_stream *next_bap_stream = &next_cap_stream->bap_stream; + + /* Since BAP operations may require a write long or a read long on the notification, + * we cannot assume that we can do multiple streams at once, thus do it one at a + * time. + * TODO: We should always be able to do one per ACL, so there is room for + * optimization. + */ + err = bt_bap_stream_enable(next_bap_stream, next_bap_stream->codec_cfg->meta, + next_bap_stream->codec_cfg->meta_len); + if (err != 0) { + LOG_DBG("Failed to enable stream %p: %d", next_cap_stream, err); - bap_stream = &active_proc.streams[0]->bap_stream; + cap_abort_proc(next_bap_stream->conn, err); + cap_initiator_unicast_audio_proc_complete(); + } else { + active_proc.stream_initiated_cnt++; + } - /* Since bt_bap_stream_start connects the ISO, we can, at this point, - * only do this one by one due to a restriction in the ISO layer - * (maximum 1 outstanding ISO connection request at any one time). + return; + } + + cap_set_subproc(CAP_UNICAST_SUBPROC_TYPE_START); + proc_param = &active_proc.proc_param[0]; + bap_stream = &proc_param->stream->bap_stream; + + /* Since BAP operations may require a write long or a read long on the notification, we + * cannot assume that we can do multiple streams at once, thus do it one at a time. + * TODO: We should always be able to do one per ACL, so there is room for optimization. */ err = bt_bap_stream_start(bap_stream); if (err != 0) { - LOG_DBG("Failed to start stream %p: %d", active_proc.streams[0], err); + LOG_DBG("Failed to start stream %p: %d", proc_param->stream, err); /* End and mark procedure as aborted. * If we have sent any requests over air, we will abort @@ -1122,14 +1215,15 @@ void bt_cap_initiator_started(struct bt_cap_stream *cap_stream) * (maximum 1 outstanding ISO connection request at any one time). */ if (!cap_proc_is_done()) { - struct bt_cap_stream *next = active_proc.streams[active_proc.stream_done_cnt]; - struct bt_bap_stream *bap_stream = &next->bap_stream; + struct bt_cap_stream *next_cap_stream = + active_proc.proc_param[active_proc.stream_done_cnt].stream; + struct bt_bap_stream *bap_stream = &next_cap_stream->bap_stream; int err; /* Not yet finished, start next */ err = bt_bap_stream_start(bap_stream); if (err != 0) { - LOG_DBG("Failed to start stream %p: %d", next, err); + LOG_DBG("Failed to start stream %p: %d", next_cap_stream, err); /* End and mark procedure as aborted. * If we have sent any requests over air, we will abort @@ -1166,6 +1260,12 @@ static bool can_update_metadata(const struct bt_bap_stream *bap_stream) int bt_cap_initiator_unicast_audio_update(const struct bt_cap_unicast_audio_update_param params[], size_t count) { + struct cap_unicast_proc_param *proc_param; + struct bt_bap_stream *bap_stream; + const uint8_t *meta; + size_t meta_len; + int err; + CHECKIF(params == NULL) { LOG_DBG("params is NULL"); @@ -1185,13 +1285,15 @@ int bt_cap_initiator_unicast_audio_update(const struct bt_cap_unicast_audio_upda } for (size_t i = 0U; i < count; i++) { - CHECKIF(params[i].stream == NULL) { + struct bt_cap_stream *cap_stream = params[i].stream; + + CHECKIF(cap_stream == NULL) { LOG_DBG("params[%zu].stream is NULL", i); return -EINVAL; } - CHECKIF(params[i].stream->bap_stream.conn == NULL) { + CHECKIF(cap_stream->bap_stream.conn == NULL) { LOG_DBG("params[%zu].stream->bap_stream.conn is NULL", i); return -EINVAL; @@ -1205,56 +1307,46 @@ int bt_cap_initiator_unicast_audio_update(const struct bt_cap_unicast_audio_upda } for (size_t j = 0U; j < i; j++) { - if (params[j].stream == params[i].stream) { + if (params[j].stream == cap_stream) { LOG_DBG("param.streams[%zu] is duplicated by param.streams[%zu]", j, i); return -EINVAL; } } - if (!can_update_metadata(¶ms[i].stream->bap_stream)) { + if (!can_update_metadata(&cap_stream->bap_stream)) { LOG_DBG("params[%zu].stream is not in right state to be updated", i); return -EINVAL; } + + active_proc.proc_param[i].stream = cap_stream; + active_proc.proc_param[i].meta_update.meta_len = params[i].meta_len; + memcpy(&active_proc.proc_param[i].meta_update.meta, params[i].meta, + params[i].meta_len); } - atomic_set_bit(active_proc.proc_state_flags, - CAP_UNICAST_PROC_STATE_ACTIVE); + atomic_set_bit(active_proc.proc_state_flags, CAP_UNICAST_PROC_STATE_ACTIVE); active_proc.stream_cnt = count; - active_proc.proc_type = CAP_UNICAST_PROC_TYPE_UPDATE; + active_proc.proc_type = CAP_UNICAST_PROC_TYPE_UPDATE; cap_set_subproc(CAP_UNICAST_SUBPROC_TYPE_META_UPDATE); - /** TODO: If this is a CSIP set, then the order of the procedures may - * not match the order in the parameters, and the CSIP ordered access - * procedure should be used. - */ - for (size_t i = 0U; i < count; i++) { - int err; - - active_proc.streams[i] = params[i].stream; + proc_param = &active_proc.proc_param[0]; + bap_stream = &proc_param->stream->bap_stream; + meta_len = proc_param->meta_update.meta_len; + meta = proc_param->meta_update.meta; - err = bt_bap_stream_metadata(¶ms[i].stream->bap_stream, params[i].meta, - params[i].meta_len); - if (err != 0) { - LOG_DBG("Failed to update metadata for stream %p: %d", - params[i].stream, err); - - if (i > 0U) { - cap_abort_proc(params[i].stream->bap_stream.conn, err); - } else { - (void)memset(&active_proc, 0, - sizeof(active_proc)); - } - - return err; - } + err = bt_bap_stream_metadata(bap_stream, meta, meta_len); + if (err != 0) { + LOG_DBG("Failed to update metadata for stream %p: %d", proc_param->stream, err); + (void)memset(&active_proc, 0, sizeof(active_proc)); + } else { active_proc.stream_initiated_cnt++; } - return 0; + return err; } int bt_cap_initiator_unicast_audio_cancel(void) @@ -1289,10 +1381,7 @@ void bt_cap_initiator_metadata_updated(struct bt_cap_stream *cap_stream) active_proc.stream_cnt); } - if (!cap_proc_is_done()) { - /* Not yet finished, wait for all */ - return; - } else if (cap_proc_is_aborted()) { + if (cap_proc_is_aborted()) { if (cap_proc_all_streams_handled()) { cap_initiator_unicast_audio_proc_complete(); } @@ -1300,6 +1389,37 @@ void bt_cap_initiator_metadata_updated(struct bt_cap_stream *cap_stream) return; } + if (!cap_proc_is_done()) { + const size_t meta_len = + active_proc.proc_param[active_proc.stream_done_cnt].meta_update.meta_len; + const uint8_t *meta = + active_proc.proc_param[active_proc.stream_done_cnt].meta_update.meta; + struct bt_cap_stream *next_cap_stream = + active_proc.proc_param[active_proc.stream_done_cnt].stream; + struct bt_bap_stream *bap_stream = &next_cap_stream->bap_stream; + int err; + + /* Since BAP operations may require a write long or a read long on the notification, + * we cannot assume that we can do multiple streams at once, thus do it one at a + * time. + * TODO: We should always be able to do one per ACL, so there is room for + * optimization. + */ + + err = bt_bap_stream_metadata(bap_stream, meta, meta_len); + if (err != 0) { + LOG_DBG("Failed to update metadata for stream %p: %d", next_cap_stream, + err); + + cap_abort_proc(bap_stream->conn, err); + cap_initiator_unicast_audio_proc_complete(); + } else { + active_proc.stream_initiated_cnt++; + } + + return; + } + cap_initiator_unicast_audio_proc_complete(); } @@ -1324,8 +1444,10 @@ static bool can_release(const struct bt_bap_stream *bap_stream) int bt_cap_initiator_unicast_audio_stop(struct bt_bap_unicast_group *unicast_group) { + struct cap_unicast_proc_param *proc_param; struct bt_bap_stream *bap_stream; size_t stream_cnt; + int err; if (cap_proc_is_active()) { LOG_DBG("A CAP procedure is already in progress"); @@ -1341,6 +1463,9 @@ int bt_cap_initiator_unicast_audio_stop(struct bt_bap_unicast_group *unicast_gro stream_cnt = 0U; SYS_SLIST_FOR_EACH_CONTAINER(&unicast_group->streams, bap_stream, _node) { if (can_release(bap_stream)) { + struct bt_cap_stream *cap_stream = + CONTAINER_OF(bap_stream, struct bt_cap_stream, bap_stream); + active_proc.proc_param[stream_cnt].stream = cap_stream; stream_cnt++; } } @@ -1363,35 +1488,19 @@ int bt_cap_initiator_unicast_audio_stop(struct bt_bap_unicast_group *unicast_gro * not match the order in the parameters, and the CSIP ordered access * procedure should be used. */ - SYS_SLIST_FOR_EACH_CONTAINER(&unicast_group->streams, bap_stream, _node) { - struct bt_cap_stream *cap_stream = - CONTAINER_OF(bap_stream, struct bt_cap_stream, bap_stream); - int err; - - if (!can_release(bap_stream)) { - continue; - } - - active_proc.streams[active_proc.stream_initiated_cnt] = cap_stream; + proc_param = &active_proc.proc_param[0]; + bap_stream = &proc_param->stream->bap_stream; - err = bt_bap_stream_release(bap_stream); - if (err != 0) { - LOG_DBG("Failed to stop bap_stream %p: %d", bap_stream, err); - - if (active_proc.stream_initiated_cnt > 0U) { - cap_abort_proc(bap_stream->conn, err); - } else { - (void)memset(&active_proc, 0, - sizeof(active_proc)); - } - - return err; - } + err = bt_bap_stream_release(bap_stream); + if (err != 0) { + LOG_DBG("Failed to stop bap_stream %p: %d", proc_param->stream, err); + (void)memset(&active_proc, 0, sizeof(active_proc)); + } else { active_proc.stream_initiated_cnt++; } - return 0; + return err; } void bt_cap_initiator_released(struct bt_cap_stream *cap_stream) @@ -1412,10 +1521,7 @@ void bt_cap_initiator_released(struct bt_cap_stream *cap_stream) active_proc.stream_cnt); } - if (!cap_proc_is_done()) { - /* Not yet finished, wait for all */ - return; - } else if (cap_proc_is_aborted()) { + if (cap_proc_is_aborted()) { if (cap_proc_all_streams_handled()) { cap_initiator_unicast_audio_proc_complete(); } @@ -1423,7 +1529,30 @@ void bt_cap_initiator_released(struct bt_cap_stream *cap_stream) return; } - cap_initiator_unicast_audio_proc_complete(); + if (!cap_proc_is_done()) { + struct bt_cap_stream *next_cap_stream = + active_proc.proc_param[active_proc.stream_done_cnt].stream; + struct bt_bap_stream *bap_stream = &next_cap_stream->bap_stream; + int err; + + /* Since BAP operations may require a write long or a read long on the notification, + * we cannot assume that we can do multiple streams at once, thus do it one at a + * time. + * TODO: We should always be able to do one per ACL, so there is room for + * optimization. + */ + err = bt_bap_stream_release(bap_stream); + if (err != 0) { + LOG_DBG("Failed to release stream %p: %d", next_cap_stream, err); + + cap_abort_proc(bap_stream->conn, err); + cap_initiator_unicast_audio_proc_complete(); + } else { + active_proc.stream_initiated_cnt++; + } + } else { + cap_initiator_unicast_audio_proc_complete(); + } } #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */ diff --git a/subsys/bluetooth/audio/ccid.c b/subsys/bluetooth/audio/ccid.c index c7bd56db234..c3a9d6a2b42 100644 --- a/subsys/bluetooth/audio/ccid.c +++ b/subsys/bluetooth/audio/ccid.c @@ -6,6 +6,9 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include #include "ccid_internal.h" @@ -23,3 +26,41 @@ uint8_t bt_ccid_get_value(void) return ccid_value++; } + +struct ccid_search_param { + const struct bt_gatt_attr *attr; + uint8_t ccid; +}; + +static uint8_t ccid_attr_cb(const struct bt_gatt_attr *attr, uint16_t handle, void *user_data) +{ + struct ccid_search_param *search_param = user_data; + + if (attr->read != NULL) { + uint8_t ccid = 0U; + ssize_t res; + + res = attr->read(NULL, attr, &ccid, sizeof(ccid), 0); + + if (res == sizeof(ccid) && search_param->ccid == ccid) { + search_param->attr = attr; + + return BT_GATT_ITER_STOP; + } + } + + return BT_GATT_ITER_CONTINUE; +} + +const struct bt_gatt_attr *bt_ccid_find_attr(uint8_t ccid) +{ + struct ccid_search_param search_param = { + .attr = NULL, + .ccid = ccid, + }; + + bt_gatt_foreach_attr_type(BT_ATT_FIRST_ATTRIBUTE_HANDLE, BT_ATT_LAST_ATTRIBUTE_HANDLE, + BT_UUID_CCID, NULL, 0, ccid_attr_cb, &search_param); + + return search_param.attr; +} diff --git a/subsys/bluetooth/audio/ccid_internal.h b/subsys/bluetooth/audio/ccid_internal.h index e68b7bdb8f8..87cca3d7098 100644 --- a/subsys/bluetooth/audio/ccid_internal.h +++ b/subsys/bluetooth/audio/ccid_internal.h @@ -23,4 +23,16 @@ */ uint8_t bt_ccid_get_value(void); +/** + * @brief Get the GATT attribute of a CCID value + * + * Searches the current GATT database for a CCID characteristic that has the supplied CCID value. + * + * @param ccid The CCID the search for + * + * @retval NULL if none was found + * @retval A pointer to a GATT attribute if found + */ +const struct bt_gatt_attr *bt_ccid_find_attr(uint8_t ccid); + #endif /* ZEPHYR_INCLUDE_BLUETOOTH_CCID_H_ */ diff --git a/subsys/bluetooth/audio/codec.c b/subsys/bluetooth/audio/codec.c index 1b4c9c659c7..38b1ef7d22b 100644 --- a/subsys/bluetooth/audio/codec.c +++ b/subsys/bluetooth/audio/codec.c @@ -10,6 +10,8 @@ * Generic Audio. */ +#include + #include #include #include @@ -18,9 +20,105 @@ LOG_MODULE_REGISTER(bt_audio_codec, CONFIG_BT_AUDIO_CODEC_LOG_LEVEL); -#if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 +int bt_audio_codec_cfg_freq_to_freq_hz(enum bt_audio_codec_config_freq freq) +{ + switch (freq) { + case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_8KHZ: + return 8000; + case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_11KHZ: + return 11025; + case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_16KHZ: + return 16000; + case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_22KHZ: + return 22050; + case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_24KHZ: + return 24000; + case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_32KHZ: + return 32000; + case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_44KHZ: + return 44100; + case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ: + return 48000; + case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_88KHZ: + return 88200; + case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_96KHZ: + return 96000; + case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_176KHZ: + return 176400; + case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_192KHZ: + return 192000; + case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_384KHZ: + return 384000; + default: + return -EINVAL; + } +} + +int bt_audio_codec_cfg_freq_hz_to_freq(uint32_t freq_hz) +{ + switch (freq_hz) { + case 8000U: + return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_8KHZ; + case 11025U: + return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_11KHZ; + case 16000U: + return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_16KHZ; + case 22050U: + return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_22KHZ; + case 24000U: + return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_24KHZ; + case 32000U: + return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_32KHZ; + case 44100U: + return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_44KHZ; + case 48000U: + return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ; + case 88200U: + return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_88KHZ; + case 96000U: + return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_96KHZ; + case 176400U: + return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_176KHZ; + case 192000U: + return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_192KHZ; + case 384000U: + return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_384KHZ; + default: + return -EINVAL; + } +} + +int bt_audio_codec_cfg_frame_dur_to_frame_dur_us(enum bt_audio_codec_config_frame_dur frame_dur) +{ + switch (frame_dur) { + case BT_AUDIO_CODEC_CONFIG_LC3_DURATION_7_5: + return 7500; + case BT_AUDIO_CODEC_CONFIG_LC3_DURATION_10: + return 10000; + default: + return -EINVAL; + } +} + +int bt_audio_codec_cfg_frame_dur_us_to_frame_dur(uint32_t frame_dur_us) +{ + switch (frame_dur_us) { + case 7500U: + return BT_AUDIO_CODEC_CONFIG_LC3_DURATION_7_5; + case 10000U: + return BT_AUDIO_CODEC_CONFIG_LC3_DURATION_10; + default: + return -EINVAL; + } +} + +#if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 || \ + CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0 || \ + CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_SIZE > 0 || \ + CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE > 0 struct search_type_param { + bool found; uint8_t type; uint8_t data_len; const uint8_t **data; @@ -31,6 +129,7 @@ static bool parse_cb(struct bt_data *data, void *user_data) struct search_type_param *param = (struct search_type_param *)user_data; if (param->type == data->type) { + param->found = true; param->data_len = data->data_len; *param->data = data->data; @@ -40,23 +139,128 @@ static bool parse_cb(struct bt_data *data, void *user_data) return true; } -uint8_t bt_audio_codec_cfg_get_val(const struct bt_audio_codec_cfg *codec_cfg, uint8_t type, - const uint8_t **data) +static int ltv_set_val(struct net_buf_simple *buf, uint8_t type, const uint8_t *data, + size_t data_len) +{ + for (uint16_t i = 0U; i < buf->len;) { + uint8_t *len = &buf->data[i++]; + const uint8_t data_type = buf->data[i++]; + const uint8_t value_len = *len - sizeof(data_type); + + if (data_type == type) { + uint8_t *value = &buf->data[i]; + + if (data_len == value_len) { + memcpy(value, data, data_len); + } else { + const int16_t diff = data_len - value_len; + uint8_t *old_next_data_start; + uint8_t *new_next_data_start; + uint8_t data_len_to_move; + + /* Check if this is the last value in the buffer */ + if (value + value_len == buf->data + buf->len) { + data_len_to_move = 0U; + } else { + old_next_data_start = value + value_len + 1; + new_next_data_start = value + data_len + 1; + data_len_to_move = + buf->len - (old_next_data_start - buf->data); + } + + if (diff < 0) { + /* In this case we need to move memory around after the copy + * to fit the new shorter data + */ + + memcpy(value, data, data_len); + if (data_len_to_move > 0U) { + memmove(new_next_data_start, old_next_data_start, + data_len_to_move); + } + } else { + /* In this case we need to move memory around before + * the copy to fit the new longer data + */ + if ((buf->len + diff) > buf->size) { + LOG_DBG("Cannot fit data_len %zu in buf with len " + "%u and size %u", + data_len, buf->len, buf->size); + return -ENOMEM; + } + + if (data_len_to_move > 0) { + memmove(new_next_data_start, old_next_data_start, + data_len_to_move); + } + memcpy(value, data, data_len); + } + + buf->len += diff; + *len += diff; + } + + return buf->len; + } + + i += value_len; + } + + /* If we reach here, we did not find the data in the buffer, so we simply add it */ + if ((buf->len + data_len) <= buf->size) { + net_buf_simple_add_u8(buf, data_len + sizeof(type)); + net_buf_simple_add_u8(buf, type); + if (data_len > 0) { + net_buf_simple_add_mem(buf, data, data_len); + } + } else { + LOG_DBG("Cannot fit data_len %zu in codec_cfg with len %u and size %u", data_len, + buf->len, buf->size); + return -ENOMEM; + } + + return buf->len; +} +#endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 || \ + * CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0 || \ + * CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_SIZE > 0 || \ + * CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE > 0 \ + */ + +#if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 + +static void init_net_buf_simple_from_codec_cfg(struct net_buf_simple *buf, + struct bt_audio_codec_cfg *codec_cfg) +{ + buf->__buf = codec_cfg->data; + buf->data = codec_cfg->data; + buf->size = sizeof(codec_cfg->data); + buf->len = codec_cfg->data_len; +} + +uint8_t bt_audio_codec_cfg_get_val(const struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_codec_config_type type, const uint8_t **data) { struct search_type_param param = { - .type = type, + .found = false, + .type = (uint8_t)type, .data_len = 0, .data = data, }; int err; - *data = NULL; - CHECKIF(codec_cfg == NULL) { LOG_DBG("codec is NULL"); return 0; } + CHECKIF(data == NULL) { + LOG_DBG("data is NULL"); + return 0; + } + + *data = NULL; + err = bt_audio_data_parse(codec_cfg->data, codec_cfg->data_len, parse_cb, ¶m); if (err != 0 && err != -ECANCELED) { LOG_DBG("Could not parse the data: %d", err); @@ -71,88 +275,130 @@ uint8_t bt_audio_codec_cfg_get_val(const struct bt_audio_codec_cfg *codec_cfg, u return param.data_len; } +int bt_audio_codec_cfg_set_val(struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_codec_config_type type, const uint8_t *data, + size_t data_len) +{ + struct net_buf_simple buf; + int ret; + + CHECKIF(codec_cfg == NULL) { + LOG_DBG("codec_cfg is NULL"); + return -EINVAL; + } + + CHECKIF(data == NULL) { + LOG_DBG("data is NULL"); + return -EINVAL; + } + + CHECKIF(data_len == 0U || data_len > UINT8_MAX) { + LOG_DBG("Invalid data_len %zu", data_len); + return -EINVAL; + } + + init_net_buf_simple_from_codec_cfg(&buf, codec_cfg); + + ret = ltv_set_val(&buf, type, data, data_len); + if (ret >= 0) { + codec_cfg->data_len = ret; + } + + return ret; +} + int bt_audio_codec_cfg_get_freq(const struct bt_audio_codec_cfg *codec_cfg) { + enum bt_audio_codec_config_freq freq; const uint8_t *data; uint8_t data_len; CHECKIF(codec_cfg == NULL) { LOG_DBG("codec is NULL"); - return BT_AUDIO_CODEC_PARSE_ERR_INVALID_PARAM; + return -EINVAL; } data_len = bt_audio_codec_cfg_get_val(codec_cfg, BT_AUDIO_CODEC_CONFIG_LC3_FREQ, &data); if (data == NULL) { - return BT_AUDIO_CODEC_PARSE_ERR_TYPE_NOT_FOUND; + return -ENODATA; } if (data_len != sizeof(uint8_t)) { - return BT_AUDIO_CODEC_PARSE_ERR_INVALID_VALUE_FOUND; + return -EBADMSG; } - switch (data[0]) { - case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_8KHZ: - return 8000; - case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_11KHZ: - return 11025; - case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_16KHZ: - return 16000; - case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_22KHZ: - return 22050; - case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_24KHZ: - return 24000; - case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_32KHZ: - return 32000; - case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_44KHZ: - return 44100; - case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ: - return 48000; - case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_88KHZ: - return 88200; - case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_96KHZ: - return 96000; - case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_176KHZ: - return 176400; - case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_192KHZ: - return 192000; - case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_384KHZ: - return 384000; - default: - return BT_AUDIO_CODEC_PARSE_ERR_INVALID_VALUE_FOUND; + freq = data[0]; + if (bt_audio_codec_cfg_freq_to_freq_hz(freq) < 0) { + LOG_DBG("Invalid freq value: 0x%02X", freq); + return -EBADMSG; + } + + return freq; +} + +int bt_audio_codec_cfg_set_freq(struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_codec_config_freq freq) +{ + uint8_t freq_u8; + + if (bt_audio_codec_cfg_freq_to_freq_hz(freq) < 0) { + LOG_DBG("Invalid freq value: %d", freq); + return -EINVAL; } + + freq_u8 = (uint8_t)freq; + + return bt_audio_codec_cfg_set_val(codec_cfg, BT_AUDIO_CODEC_CONFIG_LC3_FREQ, &freq_u8, + sizeof(freq_u8)); } -int bt_audio_codec_cfg_get_frame_duration_us(const struct bt_audio_codec_cfg *codec_cfg) +int bt_audio_codec_cfg_get_frame_dur(const struct bt_audio_codec_cfg *codec_cfg) { + enum bt_audio_codec_config_frame_dur frame_dur; const uint8_t *data; uint8_t data_len; CHECKIF(codec_cfg == NULL) { LOG_DBG("codec is NULL"); - return BT_AUDIO_CODEC_PARSE_ERR_INVALID_PARAM; + return -EINVAL; } data_len = bt_audio_codec_cfg_get_val(codec_cfg, BT_AUDIO_CODEC_CONFIG_LC3_DURATION, &data); if (data == NULL) { - return BT_AUDIO_CODEC_PARSE_ERR_TYPE_NOT_FOUND; + return -ENODATA; } if (data_len != sizeof(uint8_t)) { - return BT_AUDIO_CODEC_PARSE_ERR_INVALID_VALUE_FOUND; + return -EBADMSG; } - switch (data[0]) { - case BT_AUDIO_CODEC_CONFIG_LC3_DURATION_7_5: - return 7500; - case BT_AUDIO_CODEC_CONFIG_LC3_DURATION_10: - return 10000; - default: - return BT_AUDIO_CODEC_PARSE_ERR_INVALID_VALUE_FOUND; + frame_dur = data[0]; + if (bt_audio_codec_cfg_frame_dur_to_frame_dur_us(frame_dur) < 0) { + LOG_DBG("Invalid frame_dur value: 0x%02X", frame_dur); + return -EBADMSG; + } + + return frame_dur; +} + +int bt_audio_codec_cfg_set_frame_dur(struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_codec_config_frame_dur frame_dur) +{ + uint8_t frame_dur_u8; + + if (bt_audio_codec_cfg_frame_dur_to_frame_dur_us(frame_dur) < 0) { + LOG_DBG("Invalid freq value: %d", frame_dur); + return -EINVAL; } + + frame_dur_u8 = (uint8_t)frame_dur; + + return bt_audio_codec_cfg_set_val(codec_cfg, BT_AUDIO_CODEC_CONFIG_LC3_DURATION, + &frame_dur_u8, sizeof(frame_dur_u8)); } -int bt_audio_codec_cfg_get_chan_allocation_val(const struct bt_audio_codec_cfg *codec_cfg, - enum bt_audio_location *chan_allocation) +int bt_audio_codec_cfg_get_chan_allocation(const struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_location *chan_allocation) { const uint8_t *data; uint8_t data_len; @@ -161,21 +407,21 @@ int bt_audio_codec_cfg_get_chan_allocation_val(const struct bt_audio_codec_cfg * CHECKIF(codec_cfg == NULL) { LOG_DBG("codec is NULL"); - return BT_AUDIO_CODEC_PARSE_ERR_INVALID_PARAM; + return -EINVAL; } CHECKIF(chan_allocation == NULL) { - return BT_AUDIO_CODEC_PARSE_ERR_INVALID_PARAM; + return -EINVAL; } - data_len = bt_audio_codec_cfg_get_val(codec_cfg, BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC, - &data); + data_len = + bt_audio_codec_cfg_get_val(codec_cfg, BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC, &data); if (data == NULL) { - return BT_AUDIO_CODEC_PARSE_ERR_TYPE_NOT_FOUND; + return -ENODATA; } if (data_len != sizeof(uint32_t)) { - return BT_AUDIO_CODEC_PARSE_ERR_INVALID_VALUE_FOUND; + return -EBADMSG; } *chan_allocation = sys_get_le32(data); @@ -183,6 +429,23 @@ int bt_audio_codec_cfg_get_chan_allocation_val(const struct bt_audio_codec_cfg * return 0; } +int bt_audio_codec_cfg_set_chan_allocation(struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_location chan_allocation) +{ + uint32_t chan_allocation_u32; + + if ((chan_allocation & BT_AUDIO_LOCATION_ANY) != chan_allocation) { + LOG_DBG("Invalid chan_allocation value: 0x%08X", chan_allocation); + return -EINVAL; + } + + chan_allocation_u32 = sys_cpu_to_le32((uint32_t)chan_allocation); + + return bt_audio_codec_cfg_set_val(codec_cfg, BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC, + (const uint8_t *)&chan_allocation_u32, + sizeof(chan_allocation_u32)); +} + int bt_audio_codec_cfg_get_octets_per_frame(const struct bt_audio_codec_cfg *codec_cfg) { const uint8_t *data; @@ -190,22 +453,34 @@ int bt_audio_codec_cfg_get_octets_per_frame(const struct bt_audio_codec_cfg *cod CHECKIF(codec_cfg == NULL) { LOG_DBG("codec is NULL"); - return BT_AUDIO_CODEC_PARSE_ERR_INVALID_PARAM; + return -EINVAL; } - data_len = bt_audio_codec_cfg_get_val(codec_cfg, BT_AUDIO_CODEC_CONFIG_LC3_FRAME_LEN, - &data); + data_len = + bt_audio_codec_cfg_get_val(codec_cfg, BT_AUDIO_CODEC_CONFIG_LC3_FRAME_LEN, &data); if (data == NULL) { - return BT_AUDIO_CODEC_PARSE_ERR_TYPE_NOT_FOUND; + return -ENODATA; } if (data_len != sizeof(uint16_t)) { - return BT_AUDIO_CODEC_PARSE_ERR_INVALID_VALUE_FOUND; + return -EBADMSG; } return sys_get_le16(data); } +int bt_audio_codec_cfg_set_octets_per_frame(struct bt_audio_codec_cfg *codec_cfg, + uint16_t octets_per_frame) +{ + uint16_t octets_per_frame_le16; + + octets_per_frame_le16 = sys_cpu_to_le16(octets_per_frame); + + return bt_audio_codec_cfg_set_val(codec_cfg, BT_AUDIO_CODEC_CONFIG_LC3_FRAME_LEN, + (uint8_t *)&octets_per_frame_le16, + sizeof(octets_per_frame_le16)); +} + int bt_audio_codec_cfg_get_frame_blocks_per_sdu(const struct bt_audio_codec_cfg *codec_cfg, bool fallback_to_default) { @@ -214,7 +489,7 @@ int bt_audio_codec_cfg_get_frame_blocks_per_sdu(const struct bt_audio_codec_cfg CHECKIF(codec_cfg == NULL) { LOG_DBG("codec is NULL"); - return BT_AUDIO_CODEC_PARSE_ERR_INVALID_PARAM; + return -EINVAL; } data_len = bt_audio_codec_cfg_get_val(codec_cfg, @@ -224,13 +499,1493 @@ int bt_audio_codec_cfg_get_frame_blocks_per_sdu(const struct bt_audio_codec_cfg return 1; } - return BT_AUDIO_CODEC_PARSE_ERR_TYPE_NOT_FOUND; + return -ENODATA; } if (data_len != sizeof(uint8_t)) { - return BT_AUDIO_CODEC_PARSE_ERR_INVALID_VALUE_FOUND; + return -EBADMSG; } return data[0]; } + +int bt_audio_codec_cfg_set_frame_blocks_per_sdu(struct bt_audio_codec_cfg *codec_cfg, + uint8_t frame_blocks) +{ + return bt_audio_codec_cfg_set_val(codec_cfg, BT_AUDIO_CODEC_CONFIG_LC3_FRAME_BLKS_PER_SDU, + &frame_blocks, sizeof(frame_blocks)); +} #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 */ + +#if CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0 || \ + CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE > 0 + +static void init_net_buf_simple_from_meta(struct net_buf_simple *buf, uint8_t meta[], + size_t meta_len, size_t meta_size) +{ + buf->__buf = meta; + buf->data = meta; + buf->size = meta_size; + buf->len = meta_len; +} + +static int codec_meta_get_val(const uint8_t meta[], size_t meta_len, uint8_t type, + const uint8_t **data) +{ + struct search_type_param param = { + .found = false, + .type = type, + .data_len = 0, + .data = data, + }; + int err; + + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + CHECKIF(data == NULL) { + LOG_DBG("data is NULL"); + return -EINVAL; + } + + *data = NULL; + + err = bt_audio_data_parse(meta, meta_len, parse_cb, ¶m); + if (err != 0 && err != -ECANCELED) { + LOG_DBG("Could not parse the meta data: %d", err); + return err; + } + + if (!param.found) { + LOG_DBG("Could not find the type %u", type); + return -ENODATA; + } + + return param.data_len; +} + +static int codec_meta_set_val(uint8_t meta[], size_t meta_len, size_t meta_size, + enum bt_audio_metadata_type type, const uint8_t *data, + size_t data_len) +{ + struct net_buf_simple buf; + + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + CHECKIF(data == NULL && data_len != 0) { + LOG_DBG("data is NULL"); + return -EINVAL; + } + + CHECKIF(data_len > UINT8_MAX) { + LOG_DBG("Invalid data_len %zu", data_len); + return -EINVAL; + } + + init_net_buf_simple_from_meta(&buf, meta, meta_len, meta_size); + + return ltv_set_val(&buf, (uint8_t)type, data, data_len); +} + +static int codec_meta_get_pref_context(const uint8_t meta[], size_t meta_len) +{ + const uint8_t *data; + int ret; + + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_PREF_CONTEXT, &data); + if (data == NULL) { + return -ENODATA; + } + + if (ret != sizeof(uint16_t)) { + return -EBADMSG; + } + + return sys_get_le16(data); +} + +static int codec_meta_set_pref_context(uint8_t meta[], size_t meta_len, size_t meta_size, + enum bt_audio_context ctx) +{ + uint16_t ctx_le16; + + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + if ((ctx & BT_AUDIO_CONTEXT_TYPE_ANY) != ctx) { + LOG_DBG("Invalid ctx value: %d", ctx); + return -EINVAL; + } + + ctx_le16 = sys_cpu_to_le16((uint16_t)ctx); + + return codec_meta_set_val(meta, meta_len, meta_size, BT_AUDIO_METADATA_TYPE_PREF_CONTEXT, + (const uint8_t *)&ctx_le16, sizeof(ctx_le16)); +} + +static int codec_meta_get_stream_context(const uint8_t meta[], size_t meta_len) +{ + const uint8_t *data; + int ret; + + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT, &data); + if (data == NULL) { + return -ENODATA; + } + + if (ret != sizeof(uint16_t)) { + return -EBADMSG; + } + + return sys_get_le16(data); +} + +static int codec_meta_set_stream_context(uint8_t meta[], size_t meta_len, size_t meta_size, + enum bt_audio_context ctx) +{ + uint16_t ctx_le16; + + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + if ((ctx & BT_AUDIO_CONTEXT_TYPE_ANY) != ctx) { + LOG_DBG("Invalid ctx value: %d", ctx); + return -EINVAL; + } + + ctx_le16 = sys_cpu_to_le16((uint16_t)ctx); + + return codec_meta_set_val(meta, meta_len, meta_size, BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT, + (const uint8_t *)&ctx_le16, sizeof(ctx_le16)); +} + +static int codec_meta_get_program_info(const uint8_t meta[], size_t meta_len, + const uint8_t **program_info) +{ + const uint8_t *data; + int ret; + + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + CHECKIF(program_info == NULL) { + LOG_DBG("program_info is NULL"); + return -EINVAL; + } + + ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_PROGRAM_INFO, &data); + if (data == NULL) { + return -ENODATA; + } + + *program_info = data; + + return ret; +} + +static int codec_meta_set_program_info(uint8_t meta[], size_t meta_len, size_t meta_size, + const uint8_t *program_info, size_t program_info_len) +{ + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + CHECKIF(program_info == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + return codec_meta_set_val(meta, meta_len, meta_size, BT_AUDIO_METADATA_TYPE_PROGRAM_INFO, + program_info, program_info_len); +} + +static int codec_meta_get_stream_lang(const uint8_t meta[], size_t meta_len) +{ + const uint8_t *data; + int ret; + + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_STREAM_LANG, &data); + if (data == NULL) { + return -ENODATA; + } + + if (ret != 3) { /* Stream language is 3 octets */ + return -EBADMSG; + } + + return sys_get_le24(data); +} + +static int codec_meta_set_stream_lang(uint8_t meta[], size_t meta_len, size_t meta_size, + uint32_t stream_lang) +{ + uint8_t stream_lang_le[3]; + + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + if ((stream_lang & 0xFFFFFFU) != stream_lang) { + LOG_DBG("Invalid stream_lang value: %d", stream_lang); + return -EINVAL; + } + + sys_put_le24(stream_lang, stream_lang_le); + + return codec_meta_set_val(meta, meta_len, meta_size, BT_AUDIO_METADATA_TYPE_STREAM_LANG, + stream_lang_le, sizeof(stream_lang_le)); +} + +static int codec_meta_get_ccid_list(const uint8_t meta[], size_t meta_len, + const uint8_t **ccid_list) +{ + const uint8_t *data; + int ret; + + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + CHECKIF(ccid_list == NULL) { + LOG_DBG("ccid_list is NULL"); + return -EINVAL; + } + + ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_CCID_LIST, &data); + if (data == NULL) { + return -ENODATA; + } + + *ccid_list = data; + + return ret; +} + +static int codec_meta_set_ccid_list(uint8_t meta[], size_t meta_len, size_t meta_size, + const uint8_t *ccid_list, size_t ccid_list_len) +{ + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + CHECKIF(ccid_list == NULL) { + LOG_DBG("ccid_list is NULL"); + return -EINVAL; + } + + return codec_meta_set_val(meta, meta_len, meta_size, BT_AUDIO_METADATA_TYPE_CCID_LIST, + ccid_list, ccid_list_len); +} + +static int codec_meta_get_parental_rating(const uint8_t meta[], size_t meta_len) +{ + const uint8_t *data; + int ret; + + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_PARENTAL_RATING, &data); + if (data == NULL) { + return -ENODATA; + } + + if (ret != sizeof(uint8_t)) { + return -EBADMSG; + } + + return data[0]; +} + +static int codec_meta_set_parental_rating(uint8_t meta[], size_t meta_len, size_t meta_size, + enum bt_audio_parental_rating parental_rating) +{ + uint8_t parental_rating_u8; + + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + if (parental_rating > BT_AUDIO_PARENTAL_RATING_AGE_18_OR_ABOVE) { + LOG_DBG("Invalid parental_rating value: %d", parental_rating); + return -EINVAL; + } + + parental_rating_u8 = (uint8_t)parental_rating; + + return codec_meta_set_val(meta, meta_len, meta_size, BT_AUDIO_METADATA_TYPE_PARENTAL_RATING, + &parental_rating_u8, sizeof(parental_rating_u8)); +} + +static int codec_meta_get_program_info_uri(const uint8_t meta[], size_t meta_len, + const uint8_t **program_info_uri) +{ + const uint8_t *data; + int ret; + + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + CHECKIF(program_info_uri == NULL) { + LOG_DBG("program_info_uri is NULL"); + return -EINVAL; + } + + ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_PROGRAM_INFO_URI, &data); + if (data == NULL) { + return -ENODATA; + } + + *program_info_uri = data; + + return ret; +} + +static int codec_meta_set_program_info_uri(uint8_t meta[], size_t meta_len, size_t meta_size, + const uint8_t *program_info_uri, + size_t program_info_uri_len) +{ + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + CHECKIF(program_info_uri == NULL) { + LOG_DBG("program_info_uri is NULL"); + return -EINVAL; + } + + return codec_meta_set_val(meta, meta_len, meta_size, + BT_AUDIO_METADATA_TYPE_PROGRAM_INFO_URI, program_info_uri, + program_info_uri_len); +} + +static int codec_meta_get_audio_active_state(const uint8_t meta[], size_t meta_len) +{ + const uint8_t *data; + int ret; + + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_AUDIO_STATE, &data); + if (data == NULL) { + return -ENODATA; + } + + if (ret != sizeof(uint8_t)) { + return -EBADMSG; + } + + return data[0]; +} + +static int codec_meta_set_audio_active_state(uint8_t meta[], size_t meta_len, size_t meta_size, + enum bt_audio_active_state state) +{ + uint8_t state_u8; + + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + if (state != BT_AUDIO_ACTIVE_STATE_DISABLED && state != BT_AUDIO_ACTIVE_STATE_ENABLED) { + LOG_DBG("Invalid state value: %d", state); + return -EINVAL; + } + + state_u8 = (uint8_t)state; + + return codec_meta_set_val(meta, meta_len, meta_size, BT_AUDIO_METADATA_TYPE_AUDIO_STATE, + &state_u8, sizeof(state_u8)); +} + +static int codec_meta_get_bcast_audio_immediate_rend_flag(const uint8_t meta[], size_t meta_len) +{ + const uint8_t *data; + + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + return codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_BROADCAST_IMMEDIATE, + &data); +} + +static int codec_meta_set_bcast_audio_immediate_rend_flag(uint8_t meta[], size_t meta_len, + size_t meta_size) +{ + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + return codec_meta_set_val(meta, meta_len, meta_size, + BT_AUDIO_METADATA_TYPE_BROADCAST_IMMEDIATE, NULL, 0); +} + +static int codec_meta_get_extended(const uint8_t meta[], size_t meta_len, + const uint8_t **extended_meta) +{ + const uint8_t *data; + int ret; + + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + CHECKIF(extended_meta == NULL) { + LOG_DBG("extended_meta is NULL"); + return -EINVAL; + } + + ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_EXTENDED, &data); + if (data == NULL) { + return -ENODATA; + } + + *extended_meta = data; + + return ret; +} + +static int codec_meta_set_extended(uint8_t meta[], size_t meta_len, size_t meta_size, + const uint8_t *extended, size_t extended_len) +{ + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + CHECKIF(extended == NULL) { + LOG_DBG("extended is NULL"); + return -EINVAL; + } + + return codec_meta_set_val(meta, meta_len, meta_size, BT_AUDIO_METADATA_TYPE_EXTENDED, + extended, extended_len); +} + +static int codec_meta_get_vendor(const uint8_t meta[], size_t meta_len, const uint8_t **vendor_meta) +{ + const uint8_t *data; + int ret; + + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + CHECKIF(vendor_meta == NULL) { + LOG_DBG("vendor_meta is NULL"); + return -EINVAL; + } + + ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_VENDOR, &data); + if (data == NULL) { + return -ENODATA; + } + + *vendor_meta = data; + + return ret; +} + +static int codec_meta_set_vendor(uint8_t meta[], size_t meta_len, size_t meta_size, + const uint8_t *vendor, size_t vendor_len) +{ + CHECKIF(meta == NULL) { + LOG_DBG("meta is NULL"); + return -EINVAL; + } + + CHECKIF(vendor == NULL) { + LOG_DBG("vendor is NULL"); + return -EINVAL; + } + + return codec_meta_set_val(meta, meta_len, meta_size, BT_AUDIO_METADATA_TYPE_VENDOR, vendor, + vendor_len); +} + +#if CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0 +int bt_audio_codec_cfg_meta_get_val(const struct bt_audio_codec_cfg *codec_cfg, uint8_t type, + const uint8_t **data) +{ + CHECKIF(codec_cfg == NULL) { + LOG_DBG("codec_cfg is NULL"); + return -EINVAL; + } + + return codec_meta_get_val(codec_cfg->meta, codec_cfg->meta_len, type, data); +} + +int bt_audio_codec_cfg_meta_set_val(struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_metadata_type type, const uint8_t *data, + size_t data_len) +{ + int ret; + + CHECKIF(codec_cfg == NULL) { + LOG_DBG("codec_cfg is NULL"); + return -EINVAL; + } + + ret = codec_meta_set_val(codec_cfg->meta, codec_cfg->meta_len, ARRAY_SIZE(codec_cfg->meta), + type, data, data_len); + if (ret >= 0) { + codec_cfg->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cfg_meta_get_pref_context(const struct bt_audio_codec_cfg *codec_cfg) +{ + CHECKIF(codec_cfg == NULL) { + LOG_DBG("codec_cfg is NULL"); + return -EINVAL; + } + + return codec_meta_get_pref_context(codec_cfg->meta, codec_cfg->meta_len); +} + +int bt_audio_codec_cfg_meta_set_pref_context(struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_context ctx) +{ + int ret; + + ret = codec_meta_set_pref_context(codec_cfg->meta, codec_cfg->meta_len, + ARRAY_SIZE(codec_cfg->meta), ctx); + if (ret >= 0) { + codec_cfg->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cfg_meta_get_stream_context(const struct bt_audio_codec_cfg *codec_cfg) +{ + CHECKIF(codec_cfg == NULL) { + LOG_DBG("codec_cfg is NULL"); + return -EINVAL; + } + + return codec_meta_get_stream_context(codec_cfg->meta, codec_cfg->meta_len); +} + +int bt_audio_codec_cfg_meta_set_stream_context(struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_context ctx) +{ + int ret; + + ret = codec_meta_set_stream_context(codec_cfg->meta, codec_cfg->meta_len, + ARRAY_SIZE(codec_cfg->meta), ctx); + if (ret >= 0) { + codec_cfg->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cfg_meta_get_program_info(const struct bt_audio_codec_cfg *codec_cfg, + const uint8_t **program_info) +{ + CHECKIF(codec_cfg == NULL) { + LOG_DBG("codec_cfg is NULL"); + return -EINVAL; + } + + return codec_meta_get_program_info(codec_cfg->meta, codec_cfg->meta_len, program_info); +} + +int bt_audio_codec_cfg_meta_set_program_info(struct bt_audio_codec_cfg *codec_cfg, + const uint8_t *program_info, size_t program_info_len) +{ + int ret; + + ret = codec_meta_set_program_info(codec_cfg->meta, codec_cfg->meta_len, + ARRAY_SIZE(codec_cfg->meta), program_info, + program_info_len); + if (ret >= 0) { + codec_cfg->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cfg_meta_get_stream_lang(const struct bt_audio_codec_cfg *codec_cfg) +{ + CHECKIF(codec_cfg == NULL) { + LOG_DBG("codec_cfg is NULL"); + return -EINVAL; + } + + return codec_meta_get_stream_lang(codec_cfg->meta, codec_cfg->meta_len); +} + +int bt_audio_codec_cfg_meta_set_stream_lang(struct bt_audio_codec_cfg *codec_cfg, + uint32_t stream_lang) +{ + int ret; + + ret = codec_meta_set_stream_lang(codec_cfg->meta, codec_cfg->meta_len, + ARRAY_SIZE(codec_cfg->meta), stream_lang); + if (ret >= 0) { + codec_cfg->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cfg_meta_get_ccid_list(const struct bt_audio_codec_cfg *codec_cfg, + const uint8_t **ccid_list) +{ + CHECKIF(codec_cfg == NULL) { + LOG_DBG("codec_cfg is NULL"); + return -EINVAL; + } + + return codec_meta_get_ccid_list(codec_cfg->meta, codec_cfg->meta_len, ccid_list); +} + +int bt_audio_codec_cfg_meta_set_ccid_list(struct bt_audio_codec_cfg *codec_cfg, + const uint8_t *ccid_list, size_t ccid_list_len) +{ + int ret; + + ret = codec_meta_set_ccid_list(codec_cfg->meta, codec_cfg->meta_len, + ARRAY_SIZE(codec_cfg->meta), ccid_list, ccid_list_len); + if (ret >= 0) { + codec_cfg->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cfg_meta_get_parental_rating(const struct bt_audio_codec_cfg *codec_cfg) +{ + CHECKIF(codec_cfg == NULL) { + LOG_DBG("codec_cfg is NULL"); + return -EINVAL; + } + + return codec_meta_get_parental_rating(codec_cfg->meta, codec_cfg->meta_len); +} + +int bt_audio_codec_cfg_meta_set_parental_rating(struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_parental_rating parental_rating) +{ + int ret; + + ret = codec_meta_set_parental_rating(codec_cfg->meta, codec_cfg->meta_len, + ARRAY_SIZE(codec_cfg->meta), parental_rating); + if (ret >= 0) { + codec_cfg->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cfg_meta_get_program_info_uri(const struct bt_audio_codec_cfg *codec_cfg, + const uint8_t **program_info_uri) +{ + CHECKIF(codec_cfg == NULL) { + LOG_DBG("codec_cfg is NULL"); + return -EINVAL; + } + + return codec_meta_get_program_info_uri(codec_cfg->meta, codec_cfg->meta_len, + program_info_uri); +} + +int bt_audio_codec_cfg_meta_set_program_info_uri(struct bt_audio_codec_cfg *codec_cfg, + const uint8_t *program_info_uri, + size_t program_info_uri_len) +{ + int ret; + + ret = codec_meta_set_program_info_uri(codec_cfg->meta, codec_cfg->meta_len, + ARRAY_SIZE(codec_cfg->meta), program_info_uri, + program_info_uri_len); + if (ret >= 0) { + codec_cfg->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cfg_meta_get_audio_active_state(const struct bt_audio_codec_cfg *codec_cfg) +{ + CHECKIF(codec_cfg == NULL) { + LOG_DBG("codec_cfg is NULL"); + return -EINVAL; + } + + return codec_meta_get_audio_active_state(codec_cfg->meta, codec_cfg->meta_len); +} + +int bt_audio_codec_cfg_meta_set_audio_active_state(struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_active_state state) +{ + int ret; + + ret = codec_meta_set_audio_active_state(codec_cfg->meta, codec_cfg->meta_len, + ARRAY_SIZE(codec_cfg->meta), state); + if (ret >= 0) { + codec_cfg->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cfg_meta_get_bcast_audio_immediate_rend_flag( + const struct bt_audio_codec_cfg *codec_cfg) +{ + CHECKIF(codec_cfg == NULL) { + LOG_DBG("codec_cfg is NULL"); + return -EINVAL; + } + + return codec_meta_get_bcast_audio_immediate_rend_flag(codec_cfg->meta, codec_cfg->meta_len); +} + +int bt_audio_codec_cfg_meta_set_bcast_audio_immediate_rend_flag( + struct bt_audio_codec_cfg *codec_cfg) +{ + int ret; + + ret = codec_meta_set_bcast_audio_immediate_rend_flag(codec_cfg->meta, codec_cfg->meta_len, + ARRAY_SIZE(codec_cfg->meta)); + if (ret >= 0) { + codec_cfg->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cfg_meta_get_extended(const struct bt_audio_codec_cfg *codec_cfg, + const uint8_t **extended_meta) +{ + CHECKIF(codec_cfg == NULL) { + LOG_DBG("codec_cfg is NULL"); + return -EINVAL; + } + + return codec_meta_get_extended(codec_cfg->meta, codec_cfg->meta_len, extended_meta); +} + +int bt_audio_codec_cfg_meta_set_extended(struct bt_audio_codec_cfg *codec_cfg, + const uint8_t *extended_meta, size_t extended_meta_len) +{ + int ret; + + ret = codec_meta_set_extended(codec_cfg->meta, codec_cfg->meta_len, + ARRAY_SIZE(codec_cfg->meta), extended_meta, + extended_meta_len); + if (ret >= 0) { + codec_cfg->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cfg_meta_get_vendor(const struct bt_audio_codec_cfg *codec_cfg, + const uint8_t **vendor_meta) +{ + CHECKIF(codec_cfg == NULL) { + LOG_DBG("codec_cfg is NULL"); + return -EINVAL; + } + + return codec_meta_get_vendor(codec_cfg->meta, codec_cfg->meta_len, vendor_meta); +} + +int bt_audio_codec_cfg_meta_set_vendor(struct bt_audio_codec_cfg *codec_cfg, + const uint8_t *vendor_meta, size_t vendor_meta_len) +{ + int ret; + + ret = codec_meta_set_vendor(codec_cfg->meta, codec_cfg->meta_len, + ARRAY_SIZE(codec_cfg->meta), vendor_meta, vendor_meta_len); + if (ret >= 0) { + codec_cfg->meta_len = ret; + } + + return ret; +} +#endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0 */ + +#if CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE > 0 +int bt_audio_codec_cap_meta_get_val(const struct bt_audio_codec_cap *codec_cap, uint8_t type, + const uint8_t **data) +{ + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + return codec_meta_get_val(codec_cap->meta, codec_cap->meta_len, type, data); +} + +int bt_audio_codec_cap_meta_set_val(struct bt_audio_codec_cap *codec_cap, + enum bt_audio_metadata_type type, const uint8_t *data, + size_t data_len) +{ + int ret; + + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + ret = codec_meta_set_val(codec_cap->meta, codec_cap->meta_len, ARRAY_SIZE(codec_cap->meta), + type, data, data_len); + if (ret >= 0) { + codec_cap->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cap_meta_get_pref_context(const struct bt_audio_codec_cap *codec_cap) +{ + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + return codec_meta_get_pref_context(codec_cap->meta, codec_cap->meta_len); +} + +int bt_audio_codec_cap_meta_set_pref_context(struct bt_audio_codec_cap *codec_cap, + enum bt_audio_context ctx) +{ + int ret; + + ret = codec_meta_set_pref_context(codec_cap->meta, codec_cap->meta_len, + ARRAY_SIZE(codec_cap->meta), ctx); + if (ret >= 0) { + codec_cap->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cap_meta_get_stream_context(const struct bt_audio_codec_cap *codec_cap) +{ + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + return codec_meta_get_stream_context(codec_cap->meta, codec_cap->meta_len); +} + +int bt_audio_codec_cap_meta_set_stream_context(struct bt_audio_codec_cap *codec_cap, + enum bt_audio_context ctx) +{ + int ret; + + ret = codec_meta_set_stream_context(codec_cap->meta, codec_cap->meta_len, + ARRAY_SIZE(codec_cap->meta), ctx); + if (ret >= 0) { + codec_cap->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cap_meta_get_program_info(const struct bt_audio_codec_cap *codec_cap, + const uint8_t **program_info) +{ + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + return codec_meta_get_program_info(codec_cap->meta, codec_cap->meta_len, program_info); +} + +int bt_audio_codec_cap_meta_set_program_info(struct bt_audio_codec_cap *codec_cap, + const uint8_t *program_info, size_t program_info_len) +{ + int ret; + + ret = codec_meta_set_program_info(codec_cap->meta, codec_cap->meta_len, + ARRAY_SIZE(codec_cap->meta), program_info, + program_info_len); + if (ret >= 0) { + codec_cap->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cap_meta_get_stream_lang(const struct bt_audio_codec_cap *codec_cap) +{ + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + return codec_meta_get_stream_lang(codec_cap->meta, codec_cap->meta_len); +} + +int bt_audio_codec_cap_meta_set_stream_lang(struct bt_audio_codec_cap *codec_cap, + uint32_t stream_lang) +{ + int ret; + + ret = codec_meta_set_stream_lang(codec_cap->meta, codec_cap->meta_len, + ARRAY_SIZE(codec_cap->meta), stream_lang); + if (ret >= 0) { + codec_cap->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cap_meta_get_ccid_list(const struct bt_audio_codec_cap *codec_cap, + const uint8_t **ccid_list) +{ + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + return codec_meta_get_ccid_list(codec_cap->meta, codec_cap->meta_len, ccid_list); +} + +int bt_audio_codec_cap_meta_set_ccid_list(struct bt_audio_codec_cap *codec_cap, + const uint8_t *ccid_list, size_t ccid_list_len) +{ + int ret; + + ret = codec_meta_set_ccid_list(codec_cap->meta, codec_cap->meta_len, + ARRAY_SIZE(codec_cap->meta), ccid_list, ccid_list_len); + if (ret >= 0) { + codec_cap->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cap_meta_get_parental_rating(const struct bt_audio_codec_cap *codec_cap) +{ + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + return codec_meta_get_parental_rating(codec_cap->meta, codec_cap->meta_len); +} + +int bt_audio_codec_cap_meta_set_parental_rating(struct bt_audio_codec_cap *codec_cap, + enum bt_audio_parental_rating parental_rating) +{ + int ret; + + ret = codec_meta_set_parental_rating(codec_cap->meta, codec_cap->meta_len, + ARRAY_SIZE(codec_cap->meta), parental_rating); + if (ret >= 0) { + codec_cap->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cap_meta_get_program_info_uri(const struct bt_audio_codec_cap *codec_cap, + const uint8_t **program_info_uri) +{ + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + return codec_meta_get_program_info_uri(codec_cap->meta, codec_cap->meta_len, + program_info_uri); +} + +int bt_audio_codec_cap_meta_set_program_info_uri(struct bt_audio_codec_cap *codec_cap, + const uint8_t *program_info_uri, + size_t program_info_uri_len) +{ + int ret; + + ret = codec_meta_set_program_info_uri(codec_cap->meta, codec_cap->meta_len, + ARRAY_SIZE(codec_cap->meta), program_info_uri, + program_info_uri_len); + if (ret >= 0) { + codec_cap->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cap_meta_get_audio_active_state(const struct bt_audio_codec_cap *codec_cap) +{ + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + return codec_meta_get_audio_active_state(codec_cap->meta, codec_cap->meta_len); +} + +int bt_audio_codec_cap_meta_set_audio_active_state(struct bt_audio_codec_cap *codec_cap, + enum bt_audio_active_state state) +{ + int ret; + + ret = codec_meta_set_audio_active_state(codec_cap->meta, codec_cap->meta_len, + ARRAY_SIZE(codec_cap->meta), state); + if (ret >= 0) { + codec_cap->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cap_meta_get_bcast_audio_immediate_rend_flag( + const struct bt_audio_codec_cap *codec_cap) +{ + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + return codec_meta_get_bcast_audio_immediate_rend_flag(codec_cap->meta, codec_cap->meta_len); +} + +int bt_audio_codec_cap_meta_set_bcast_audio_immediate_rend_flag( + struct bt_audio_codec_cap *codec_cap) +{ + int ret; + + ret = codec_meta_set_bcast_audio_immediate_rend_flag(codec_cap->meta, codec_cap->meta_len, + ARRAY_SIZE(codec_cap->meta)); + if (ret >= 0) { + codec_cap->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cap_meta_get_extended(const struct bt_audio_codec_cap *codec_cap, + const uint8_t **extended_meta) +{ + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + return codec_meta_get_extended(codec_cap->meta, codec_cap->meta_len, extended_meta); +} + +int bt_audio_codec_cap_meta_set_extended(struct bt_audio_codec_cap *codec_cap, + const uint8_t *extended_meta, size_t extended_meta_len) +{ + int ret; + + ret = codec_meta_set_extended(codec_cap->meta, codec_cap->meta_len, + ARRAY_SIZE(codec_cap->meta), extended_meta, + extended_meta_len); + if (ret >= 0) { + codec_cap->meta_len = ret; + } + + return ret; +} + +int bt_audio_codec_cap_meta_get_vendor(const struct bt_audio_codec_cap *codec_cap, + const uint8_t **vendor_meta) +{ + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + return codec_meta_get_vendor(codec_cap->meta, codec_cap->meta_len, vendor_meta); +} + +int bt_audio_codec_cap_meta_set_vendor(struct bt_audio_codec_cap *codec_cap, + const uint8_t *vendor_meta, size_t vendor_meta_len) +{ + int ret; + + ret = codec_meta_set_vendor(codec_cap->meta, codec_cap->meta_len, + ARRAY_SIZE(codec_cap->meta), vendor_meta, vendor_meta_len); + if (ret >= 0) { + codec_cap->meta_len = ret; + } + + return ret; +} +#endif /* CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE > 0 */ +#endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0 || \ + * CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE > 0 \ + */ + +#if CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_SIZE > 0 + +static void init_net_buf_simple_from_codec_cap(struct net_buf_simple *buf, + struct bt_audio_codec_cap *codec_cap) +{ + buf->__buf = codec_cap->data; + buf->data = codec_cap->data; + buf->size = sizeof(codec_cap->data); + buf->len = codec_cap->data_len; +} + +uint8_t bt_audio_codec_cap_get_val(const struct bt_audio_codec_cap *codec_cap, + enum bt_audio_codec_capability_type type, const uint8_t **data) +{ + struct search_type_param param = { + .found = false, + .type = (uint8_t)type, + .data_len = 0, + .data = data, + }; + int err; + + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return 0; + } + + CHECKIF(data == NULL) { + LOG_DBG("data is NULL"); + return 0; + } + + *data = NULL; + + err = bt_audio_data_parse(codec_cap->data, codec_cap->data_len, parse_cb, ¶m); + if (err != 0 && err != -ECANCELED) { + LOG_DBG("Could not parse the data: %d", err); + return 0; + } + + if (param.data == NULL) { + LOG_DBG("Could not find the type %u", type); + return 0; + } + + return param.data_len; +} + +int bt_audio_codec_cap_set_val(struct bt_audio_codec_cap *codec_cap, + enum bt_audio_codec_capability_type type, const uint8_t *data, + size_t data_len) +{ + struct net_buf_simple buf; + int ret; + + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + CHECKIF(data == NULL) { + LOG_DBG("data is NULL"); + return -EINVAL; + } + + CHECKIF(data_len == 0U || data_len > UINT8_MAX) { + LOG_DBG("Invalid data_len %zu", data_len); + return -EINVAL; + } + + init_net_buf_simple_from_codec_cap(&buf, codec_cap); + + ret = ltv_set_val(&buf, type, data, data_len); + if (ret >= 0) { + codec_cap->data_len = ret; + } + + return ret; +} + +int bt_audio_codec_cap_get_freq(const struct bt_audio_codec_cap *codec_cap) +{ + const uint8_t *data; + uint8_t data_len; + + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + data_len = bt_audio_codec_cap_get_val(codec_cap, BT_AUDIO_CODEC_LC3_FREQ, &data); + if (data == NULL) { + return -ENODATA; + } + + if (data_len != sizeof(uint16_t)) { + return -EBADMSG; + } + + return sys_get_le16(data); +} + +int bt_audio_codec_cap_set_freq(struct bt_audio_codec_cap *codec_cap, + enum bt_audio_codec_cap_freq freq) +{ + uint16_t freq_le16; + + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + if ((freq & BT_AUDIO_CODEC_LC3_FREQ_ANY) != freq) { + LOG_DBG("Invalid freq value: %d", freq); + return -EINVAL; + } + + freq_le16 = sys_cpu_to_le16((uint16_t)freq); + + return bt_audio_codec_cap_set_val(codec_cap, BT_AUDIO_CODEC_LC3_FREQ, (uint8_t *)&freq_le16, + sizeof(freq_le16)); +} + +int bt_audio_codec_cap_get_frame_dur(const struct bt_audio_codec_cap *codec_cap) +{ + const uint8_t *data; + uint8_t data_len; + + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + data_len = bt_audio_codec_cap_get_val(codec_cap, BT_AUDIO_CODEC_LC3_DURATION, &data); + if (data == NULL) { + return -ENODATA; + } + + if (data_len != sizeof(uint8_t)) { + return -EBADMSG; + } + + return data[0]; +} + +int bt_audio_codec_cap_set_frame_dur(struct bt_audio_codec_cap *codec_cap, + enum bt_audio_codec_cap_frame_dur frame_dur) +{ + uint8_t frame_dur_u8; + + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + if ((frame_dur & BT_AUDIO_CODEC_LC3_DURATION_ANY) == 0) { + LOG_DBG("Invalid frame_dur value: %d", frame_dur); + return -EINVAL; + } + + if ((frame_dur & BT_AUDIO_CODEC_LC3_DURATION_PREFER_7_5) != 0) { + if ((frame_dur & BT_AUDIO_CODEC_LC3_DURATION_PREFER_10) != 0) { + LOG_DBG("Cannot prefer both 7.5 and 10ms: %d", frame_dur); + return -EINVAL; + } + + if ((frame_dur & BT_AUDIO_CODEC_LC3_DURATION_7_5) == 0) { + LOG_DBG("Cannot prefer 7.5ms when not supported: %d", frame_dur); + return -EINVAL; + } + } + + if ((frame_dur & BT_AUDIO_CODEC_LC3_DURATION_PREFER_10) != 0 && + (frame_dur & BT_AUDIO_CODEC_LC3_DURATION_10) == 0) { + LOG_DBG("Cannot prefer 10ms when not supported: %d", frame_dur); + return -EINVAL; + } + + frame_dur_u8 = (uint8_t)frame_dur; + + return bt_audio_codec_cap_set_val(codec_cap, BT_AUDIO_CODEC_LC3_DURATION, &frame_dur_u8, + sizeof(frame_dur_u8)); +} + +int bt_audio_codec_cap_get_supported_audio_chan_counts(const struct bt_audio_codec_cap *codec_cap) +{ + const uint8_t *data; + uint8_t data_len; + + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + data_len = bt_audio_codec_cap_get_val(codec_cap, BT_AUDIO_CODEC_LC3_CHAN_COUNT, &data); + if (data == NULL) { + return -ENODATA; + } + + if (data_len != sizeof(uint8_t)) { + return -EBADMSG; + } + + return data[0]; +} + +int bt_audio_codec_cap_set_supported_audio_chan_counts( + struct bt_audio_codec_cap *codec_cap, enum bt_audio_codec_cap_chan_count chan_count) +{ + uint8_t chan_count_u8; + + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + if ((chan_count & BT_AUDIO_CODEC_CAP_CHAN_COUNT_ALL) != chan_count) { + LOG_DBG("Invalid chan_count value: %d", chan_count); + return -EINVAL; + } + + chan_count_u8 = (uint8_t)chan_count; + + return bt_audio_codec_cap_set_val(codec_cap, BT_AUDIO_CODEC_LC3_CHAN_COUNT, &chan_count_u8, + sizeof(chan_count_u8)); +} + +int bt_audio_codec_cap_get_octets_per_frame( + const struct bt_audio_codec_cap *codec_cap, + struct bt_audio_codec_octets_per_codec_frame *codec_frame) +{ + const uint8_t *data; + uint8_t data_len; + + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + CHECKIF(codec_frame == NULL) { + LOG_DBG("codec_frame is NULL"); + return -EINVAL; + } + + data_len = bt_audio_codec_cap_get_val(codec_cap, BT_AUDIO_CODEC_LC3_FRAME_LEN, &data); + if (data == NULL) { + return -ENODATA; + } + + if (data_len != sizeof(uint32_t)) { + return -EBADMSG; + } + + codec_frame->min = sys_get_le16(data); + codec_frame->max = sys_get_le16(data + sizeof(codec_frame->min)); + + return 0; +} + +int bt_audio_codec_cap_set_octets_per_frame( + struct bt_audio_codec_cap *codec_cap, + const struct bt_audio_codec_octets_per_codec_frame *codec_frame) +{ + uint8_t codec_frame_le32[4]; + + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + CHECKIF(codec_frame == NULL) { + LOG_DBG("codec_frame is NULL"); + return -EINVAL; + } + + if (codec_frame->min > codec_frame->max) { + LOG_DBG("Invalid codec_frame values: %u/%u", codec_frame->min, codec_frame->max); + return -EINVAL; + } + + sys_put_le16(codec_frame->min, codec_frame_le32); + sys_put_le16(codec_frame->max, codec_frame_le32 + 2); + + return bt_audio_codec_cap_set_val(codec_cap, BT_AUDIO_CODEC_LC3_FRAME_LEN, codec_frame_le32, + sizeof(codec_frame_le32)); +} + +int bt_audio_codec_cap_get_max_codec_frames_per_sdu(const struct bt_audio_codec_cap *codec_cap) +{ + const uint8_t *data; + uint8_t data_len; + + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + data_len = bt_audio_codec_cap_get_val(codec_cap, BT_AUDIO_CODEC_LC3_FRAME_COUNT, &data); + if (data == NULL) { + return -ENODATA; + } + + if (data_len != sizeof(uint8_t)) { + return -EBADMSG; + } + + return data[0]; +} + +int bt_audio_codec_cap_set_max_codec_frames_per_sdu(struct bt_audio_codec_cap *codec_cap, + uint8_t codec_frames_per_sdu) +{ + CHECKIF(codec_cap == NULL) { + LOG_DBG("codec_cap is NULL"); + return -EINVAL; + } + + return bt_audio_codec_cap_set_val(codec_cap, BT_AUDIO_CODEC_LC3_FRAME_COUNT, + &codec_frames_per_sdu, sizeof(codec_frames_per_sdu)); +} + +#endif /* CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_SIZE > 0 */ diff --git a/subsys/bluetooth/audio/csip_internal.h b/subsys/bluetooth/audio/csip_internal.h index deccab6815d..cfbd1974e68 100644 --- a/subsys/bluetooth/audio/csip_internal.h +++ b/subsys/bluetooth/audio/csip_internal.h @@ -16,20 +16,6 @@ #define BT_CSIP_RELEASE_VALUE 0x01 #define BT_CSIP_LOCK_VALUE 0x02 -struct csip_pending_notifications { - bt_addr_le_t addr; - bool pending; - bool active; - -/* Since there's a 1-to-1 connection between bonded devices, and devices in - * the array containing this struct, if the security manager overwrites - * the oldest keys, we also overwrite the oldest entry - */ -#if defined(CONFIG_BT_KEYS_OVERWRITE_OLDEST) - uint32_t age; -#endif /* CONFIG_BT_KEYS_OVERWRITE_OLDEST */ -}; - struct bt_csip_set_sirk { uint8_t type; uint8_t value[BT_CSIP_SET_SIRK_SIZE]; diff --git a/subsys/bluetooth/audio/csip_set_coordinator.c b/subsys/bluetooth/audio/csip_set_coordinator.c index 7d506e72580..36e5803b45c 100644 --- a/subsys/bluetooth/audio/csip_set_coordinator.c +++ b/subsys/bluetooth/audio/csip_set_coordinator.c @@ -1214,7 +1214,8 @@ static void csip_set_coordinator_lock_state_read_cb(int err, bool locked) if (err || locked) { cur_member = active.members[active.members_handled]; - } else if (!active.oap_cb(info, active.members, active.members_count)) { + } else if (active.oap_cb == NULL || !active.oap_cb(info, active.members, + active.members_count)) { err = -ECANCELED; } @@ -1575,8 +1576,8 @@ static int bt_csip_set_coordinator_get_lock_state( * so we can just initiate the ordered access procedure (oap) callback directly * here. */ - - if (!active.oap_cb(active.info, active.members, active.members_count)) { + if (active.oap_cb == NULL || + !active.oap_cb(active.info, active.members, active.members_count)) { err = -ECANCELED; } diff --git a/subsys/bluetooth/audio/csip_set_member.c b/subsys/bluetooth/audio/csip_set_member.c index 2af43bd4233..b6bd487af82 100644 --- a/subsys/bluetooth/audio/csip_set_member.c +++ b/subsys/bluetooth/audio/csip_set_member.c @@ -39,6 +39,19 @@ LOG_MODULE_REGISTER(bt_csip_set_member, CONFIG_BT_CSIP_SET_MEMBER_LOG_LEVEL); +enum csip_pending_notify_flag { + FLAG_ACTIVE, + FLAG_SET_MEMBER_LOCK, + FLAG_NUM, +}; + +struct csip_client { + bt_addr_le_t addr; + + /* Pending notification flags */ + ATOMIC_DEFINE(flags, FLAG_NUM); +}; + struct bt_csip_set_member_svc_inst { struct bt_csip_set_sirk set_sirk; uint8_t set_size; @@ -48,15 +61,18 @@ struct bt_csip_set_member_svc_inst { struct k_work_delayable set_lock_timer; bt_addr_le_t lock_client_addr; struct bt_gatt_service *service_p; - struct csip_pending_notifications pend_notify[CONFIG_BT_MAX_PAIRED]; -#if defined(CONFIG_BT_KEYS_OVERWRITE_OLDEST) - uint32_t age_counter; -#endif /* CONFIG_BT_KEYS_OVERWRITE_OLDEST */ + struct csip_client clients[CONFIG_BT_MAX_PAIRED]; }; static struct bt_csip_set_member_svc_inst svc_insts[CONFIG_BT_CSIP_SET_MEMBER_MAX_INSTANCE_COUNT]; static bt_addr_le_t server_dummy_addr; /* 0'ed address */ +static atomic_t notify_in_progress; + +static void deferred_nfy_work_handler(struct k_work *work); + +static K_WORK_DEFINE(deferred_nfy_work, deferred_nfy_work_handler); + struct csip_notify_foreach { struct bt_conn *excluded_client; struct bt_csip_set_member_svc_inst *svc_inst; @@ -74,13 +90,63 @@ static bool is_last_client_to_write(const struct bt_csip_set_member_svc_inst *sv } } -static void notify_lock_value(const struct bt_csip_set_member_svc_inst *svc_inst, +static void csip_gatt_notify_complete_cb(struct bt_conn *conn, void *user_data) +{ + /* Notification done, clear bit and reschedule work */ + atomic_clear(¬ify_in_progress); + k_work_submit(&deferred_nfy_work); +} + +static int csip_gatt_notify_set_lock(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + const void *data, + uint16_t len) +{ + int err; + struct bt_gatt_notify_params params; + + memset(¶ms, 0, sizeof(params)); + params.uuid = BT_UUID_CSIS_SET_LOCK; + params.attr = attr; + params.data = data; + params.len = len; + params.func = csip_gatt_notify_complete_cb; + + /* Mark notification in progress */ + atomic_set(¬ify_in_progress, 1); + + err = bt_gatt_notify_cb(conn, ¶ms); + if (err != 0) { + atomic_clear(¬ify_in_progress); + + if (err != -ENOTCONN) { + return err; + } + } + + return 0; +} + +static void csip_set_notify_bit(struct bt_csip_set_member_svc_inst *svc_inst, + enum csip_pending_notify_flag flag) +{ + for (size_t i = 0U; i < ARRAY_SIZE(svc_inst->clients); i++) { + struct csip_client *client; + + client = &svc_inst->clients[i]; + if (atomic_test_bit(client->flags, FLAG_ACTIVE)) { + atomic_set_bit(client->flags, flag); + } + } +} + +static int notify_lock_value(const struct bt_csip_set_member_svc_inst *svc_inst, struct bt_conn *conn) { - bt_gatt_notify_uuid(conn, BT_UUID_CSIS_SET_LOCK, - svc_inst->service_p->attrs, - &svc_inst->set_lock, - sizeof(svc_inst->set_lock)); + LOG_DBG(""); + return csip_gatt_notify_set_lock(conn, svc_inst->service_p->attrs, + &svc_inst->set_lock, + sizeof(svc_inst->set_lock)); } static void notify_client(struct bt_conn *conn, void *data) @@ -93,17 +159,26 @@ static void notify_client(struct bt_conn *conn, void *data) return; } - notify_lock_value(svc_inst, conn); - for (int i = 0; i < ARRAY_SIZE(svc_inst->pend_notify); i++) { - struct csip_pending_notifications *pend_notify; - pend_notify = &svc_inst->pend_notify[i]; + for (size_t i = 0U; i < ARRAY_SIZE(svc_inst->clients); i++) { + struct csip_client *client; - if (pend_notify->pending && - bt_addr_le_eq(bt_conn_get_dst(conn), &pend_notify->addr)) { - pend_notify->pending = false; - break; + client = &svc_inst->clients[i]; + + if (atomic_test_bit(client->flags, FLAG_SET_MEMBER_LOCK) && + bt_addr_le_eq(bt_conn_get_dst(conn), &client->addr)) { + /* First try to send the notification directly, and if it fails add it + * to system workqueue for retry. We do it like this here as the client + * wants the lock notification asap to begin ordered access procedure + */ + if (notify_lock_value(svc_inst, conn) != 0) { + csip_set_notify_bit(svc_inst, FLAG_SET_MEMBER_LOCK); + k_work_submit(&deferred_nfy_work); + } else { + atomic_clear_bit(client->flags, FLAG_SET_MEMBER_LOCK); + break; + } } } } @@ -119,18 +194,18 @@ static void notify_clients(struct bt_csip_set_member_svc_inst *svc_inst, /* Mark all bonded devices as pending notifications, and clear those * that are notified in `notify_client` */ - for (int i = 0; i < ARRAY_SIZE(svc_inst->pend_notify); i++) { - struct csip_pending_notifications *pend_notify; + for (size_t i = 0U; i < ARRAY_SIZE(svc_inst->clients); i++) { + struct csip_client *client; - pend_notify = &svc_inst->pend_notify[i]; + client = &svc_inst->clients[i]; - if (pend_notify->active) { + if (atomic_test_bit(client->flags, FLAG_ACTIVE)) { if (excluded_client != NULL && - bt_addr_le_eq(bt_conn_get_dst(excluded_client), &pend_notify->addr)) { + bt_addr_le_eq(bt_conn_get_dst(excluded_client), &client->addr)) { continue; } - pend_notify->pending = true; + atomic_set_bit(client->flags, FLAG_SET_MEMBER_LOCK); } } @@ -471,18 +546,17 @@ static void csip_security_changed(struct bt_conn *conn, bt_security_t level, return; } - for (int i = 0; i < ARRAY_SIZE(svc_insts); i++) { + for (size_t i = 0U; i < ARRAY_SIZE(svc_insts); i++) { struct bt_csip_set_member_svc_inst *svc_inst = &svc_insts[i]; - for (int j = 0; j < ARRAY_SIZE(svc_inst->pend_notify); j++) { - struct csip_pending_notifications *pend_notify; + for (size_t j = 0U; j < ARRAY_SIZE(svc_inst->clients); j++) { + struct csip_client *client; - pend_notify = &svc_inst->pend_notify[j]; + client = &svc_inst->clients[i]; - if (pend_notify->pending && - bt_addr_le_eq(bt_conn_get_dst(conn), &pend_notify->addr)) { - notify_lock_value(svc_inst, conn); - pend_notify->pending = false; + if (atomic_test_bit(client->flags, FLAG_SET_MEMBER_LOCK) && + bt_addr_le_eq(bt_conn_get_dst(conn), &client->addr)) { + k_work_submit(&deferred_nfy_work); break; } } @@ -509,13 +583,13 @@ static void handle_csip_disconnect(struct bt_csip_set_member_svc_inst *svc_inst, /* Check if the disconnected device once was bonded and stored * here as a bonded device */ - for (int i = 0; i < ARRAY_SIZE(svc_inst->pend_notify); i++) { - struct csip_pending_notifications *pend_notify; + for (size_t i = 0U; i < ARRAY_SIZE(svc_inst->clients); i++) { + struct csip_client *client; - pend_notify = &svc_inst->pend_notify[i]; + client = &svc_inst->clients[i]; - if (bt_addr_le_eq(bt_conn_get_dst(conn), &pend_notify->addr)) { - (void)memset(pend_notify, 0, sizeof(*pend_notify)); + if (bt_addr_le_eq(bt_conn_get_dst(conn), &client->addr)) { + (void)memset(client, 0, sizeof(*client)); break; } } @@ -526,7 +600,7 @@ static void csip_disconnected(struct bt_conn *conn, uint8_t reason) LOG_DBG("Disconnected: %s (reason %u)", bt_addr_le_str(bt_conn_get_dst(conn)), reason); if (!bt_addr_le_is_bonded(conn->id, &conn->le.dst)) { - for (int i = 0; i < ARRAY_SIZE(svc_insts); i++) { + for (size_t i = 0U; i < ARRAY_SIZE(svc_insts); i++) { handle_csip_disconnect(&svc_insts[i], conn); } } @@ -536,59 +610,34 @@ static void handle_csip_auth_complete(struct bt_csip_set_member_svc_inst *svc_in struct bt_conn *conn) { /* Check if already in list, and do nothing if it is */ - for (int i = 0; i < ARRAY_SIZE(svc_inst->pend_notify); i++) { - struct csip_pending_notifications *pend_notify; + for (size_t i = 0U; i < ARRAY_SIZE(svc_inst->clients); i++) { + struct csip_client *client; - pend_notify = &svc_inst->pend_notify[i]; + client = &svc_inst->clients[i]; - if (pend_notify->active && - bt_addr_le_eq(bt_conn_get_dst(conn), &pend_notify->addr)) { -#if defined(CONFIG_BT_KEYS_OVERWRITE_OLDEST) - pend_notify->age = svc_inst->age_counter++; -#endif /* CONFIG_BT_KEYS_OVERWRITE_OLDEST */ + if (atomic_test_bit(client->flags, FLAG_ACTIVE) && + bt_addr_le_eq(bt_conn_get_dst(conn), &client->addr)) { return; } } - /* Copy addr to list over devices to save notifications for */ - for (int i = 0; i < ARRAY_SIZE(svc_inst->pend_notify); i++) { - struct csip_pending_notifications *pend_notify; + /* Else add the device */ + for (size_t i = 0U; i < ARRAY_SIZE(svc_inst->clients); i++) { + struct csip_client *client; - pend_notify = &svc_inst->pend_notify[i]; + client = &svc_inst->clients[i]; - if (!pend_notify->active) { - bt_addr_le_copy(&pend_notify->addr, - bt_conn_get_dst(conn)); - pend_notify->active = true; -#if defined(CONFIG_BT_KEYS_OVERWRITE_OLDEST) - pend_notify->age = svc_inst->age_counter++; -#endif /* CONFIG_BT_KEYS_OVERWRITE_OLDEST */ + if (!atomic_test_bit(client->flags, FLAG_ACTIVE)) { + atomic_set_bit(client->flags, FLAG_ACTIVE); + memcpy(&client->addr, bt_conn_get_dst(conn), sizeof(bt_addr_le_t)); + + /* Send out all pending notifications */ + k_work_submit(&deferred_nfy_work); return; } } -#if defined(CONFIG_BT_KEYS_OVERWRITE_OLDEST) - struct csip_pending_notifications *oldest; - - oldest = &svc_inst->pend_notify[0]; - - for (int i = 1; i < ARRAY_SIZE(svc_inst->pend_notify); i++) { - struct csip_pending_notifications *pend_notify; - - pend_notify = &svc_inst->pend_notify[i]; - - if (pend_notify->age < oldest->age) { - oldest = pend_notify; - } - } - (void)memset(oldest, 0, sizeof(*oldest)); - bt_addr_le_copy(&oldest->addr, &conn->le.dst); - oldest->active = true; - oldest->age = svc_inst->age_counter++; -#else LOG_WRN("Could not add device to pending notification list"); -#endif /* CONFIG_BT_KEYS_OVERWRITE_OLDEST */ - } static void auth_pairing_complete(struct bt_conn *conn, bool bonded) @@ -596,9 +645,9 @@ static void auth_pairing_complete(struct bt_conn *conn, bool bonded) /** * If a pairing is complete for a bonded device, then we * 1) Store the connection pointer to later validate SIRK encryption - * 2) Check if the device is already in the `pend_notify`, and if it is + * 2) Check if the device is already in the `clients`, and if it is * not, then we - * 3) Check if there's room for another device in the `pend_notify` + * 3) Check if there's room for another device in the `clients` * array. If there are no more room for a new device, then * 4) Either we ignore this new device (bad luck), or we overwrite * the oldest entry, following the behavior of the key storage. @@ -611,25 +660,23 @@ static void auth_pairing_complete(struct bt_conn *conn, bool bonded) return; } - for (int i = 0; i < ARRAY_SIZE(svc_insts); i++) { + for (size_t i = 0U; i < ARRAY_SIZE(svc_insts); i++) { handle_csip_auth_complete(&svc_insts[i], conn); } } static void csip_bond_deleted(uint8_t id, const bt_addr_le_t *peer) { - for (int i = 0; i < ARRAY_SIZE(svc_insts); i++) { + for (size_t i = 0U; i < ARRAY_SIZE(svc_insts); i++) { struct bt_csip_set_member_svc_inst *svc_inst = &svc_insts[i]; - for (int j = 0; j < ARRAY_SIZE(svc_inst->pend_notify); j++) { - struct csip_pending_notifications *pend_notify; + for (size_t j = 0U; j < ARRAY_SIZE(svc_inst->clients); j++) { - pend_notify = &svc_inst->pend_notify[j]; - - if (pend_notify->active && - bt_addr_le_eq(peer, &pend_notify->addr)) { - (void)memset(pend_notify, 0, - sizeof(*pend_notify)); + /* Check if match, and if active, if so, reset */ + if (atomic_test_bit(svc_inst->clients[i].flags, FLAG_ACTIVE) && + bt_addr_le_eq(peer, &svc_inst->clients[i].addr)) { + atomic_clear(svc_inst->clients[i].flags); + (void)memset(&svc_inst->clients[i].addr, 0, sizeof(bt_addr_le_t)); break; } } @@ -746,10 +793,72 @@ static void remove_csis_char(const struct bt_uuid *uuid, struct bt_gatt_service __ASSERT(false, "Failed to remove CSIS char %s", bt_uuid_str(uuid)); } +static void notify_cb(struct bt_conn *conn, void *data) +{ + struct bt_conn_info info; + int err = 0; + + err = bt_conn_get_info(conn, &info); + if (err != 0) { + return; + } + + if (info.state != BT_CONN_STATE_CONNECTED) { + /* Not connected */ + LOG_DBG("Not connected"); + return; + } + + for (size_t i = 0U; i < ARRAY_SIZE(svc_insts); i++) { + struct bt_csip_set_member_svc_inst *svc_inst = &svc_insts[i]; + struct csip_client *client = &svc_inst->clients[bt_conn_index(conn)]; + + if (atomic_test_bit(client->flags, FLAG_SET_MEMBER_LOCK)) { + err = notify_lock_value(svc_inst, conn); + if (!err) { + atomic_clear_bit(client->flags, FLAG_SET_MEMBER_LOCK); + } + } + } +} + +static void deferred_nfy_work_handler(struct k_work *work) +{ + /* Check if we have unverified notifications in progress */ + if (atomic_get(¬ify_in_progress)) { + return; + } + + bt_conn_foreach(BT_CONN_TYPE_LE, notify_cb, NULL); +} + +static void add_bonded_addr_to_client_list(const struct bt_bond_info *info, void *data) +{ + + for (size_t i = 0U; i < ARRAY_SIZE(svc_insts); i++) { + struct bt_csip_set_member_svc_inst *svc_inst = &svc_insts[i]; + + for (size_t j = 1U; j < ARRAY_SIZE(svc_inst->clients); i++) { + /* Check if device is registered, it not, add it */ + if (!atomic_test_bit(svc_inst->clients[j].flags, FLAG_ACTIVE)) { + char addr_str[BT_ADDR_LE_STR_LEN]; + + atomic_set_bit(svc_inst->clients[j].flags, FLAG_ACTIVE); + memcpy(&svc_inst->clients[j].addr, &info->addr, + sizeof(bt_addr_le_t)); + bt_addr_le_to_str(&svc_inst->clients[j].addr, addr_str, + sizeof(addr_str)); + LOG_DBG("Added %s to bonded list\n", addr_str); + return; + } + } + } +} + int bt_csip_set_member_register(const struct bt_csip_set_member_register_param *param, struct bt_csip_set_member_svc_inst **svc_inst) { - static bool callbacks_registered; + static bool first_register; static uint8_t instance_cnt; struct bt_csip_set_member_svc_inst *inst; int err; @@ -773,11 +882,14 @@ int bt_csip_set_member_register(const struct bt_csip_set_member_register_param * inst->service_p = &csip_set_member_service_list[instance_cnt]; instance_cnt++; - if (!callbacks_registered) { + if (!first_register) { bt_conn_cb_register(&conn_callbacks); bt_conn_auth_info_cb_register(&auth_callbacks); - callbacks_registered = true; + /* Restore bonding list */ + bt_foreach_bond(BT_ID_DEFAULT, add_bonded_addr_to_client_list, NULL); + + first_register = true; } /* The removal of the optional characteristics should be done in reverse order of the order diff --git a/subsys/bluetooth/audio/has.c b/subsys/bluetooth/audio/has.c index b8e70e4e164..fc1aba7aec2 100644 --- a/subsys/bluetooth/audio/has.c +++ b/subsys/bluetooth/audio/has.c @@ -4,11 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include -#include - -#include #include #include @@ -16,21 +12,22 @@ #include #include #include +#include -#include "../bluetooth/host/conn_internal.h" #include "../bluetooth/host/hci_core.h" #include "audio_internal.h" #include "has_internal.h" +#include "common/bt_str.h" + #include LOG_MODULE_REGISTER(bt_has, CONFIG_BT_HAS_LOG_LEVEL); /* The service allows operations with paired devices only. - * For now, the context is kept for connected devices only, thus the number of contexts is - * equal to maximum number of simultaneous connections to paired devices. + * The number of clients is set to maximum number of simultaneous connections to paired devices. */ -#define BT_HAS_MAX_CONN MIN(CONFIG_BT_MAX_CONN, CONFIG_BT_MAX_PAIRED) +#define MAX_INSTS MIN(CONFIG_BT_MAX_CONN, CONFIG_BT_MAX_PAIRED) #define BITS_CHANGED(_new_value, _old_value) ((_new_value) ^ (_old_value)) #define FEATURE_DEVICE_TYPE_UNCHANGED(_new_value) \ @@ -39,6 +36,8 @@ LOG_MODULE_REGISTER(bt_has, CONFIG_BT_HAS_LOG_LEVEL); !BITS_CHANGED(_new_value, ((has.features & BT_HAS_FEAT_PRESET_SYNC_SUPP) != 0 ? 1 : 0)) #define FEATURE_IND_PRESETS_UNCHANGED(_new_value) \ !BITS_CHANGED(_new_value, ((has.features & BT_HAS_FEAT_INDEPENDENT_PRESETS) != 0 ? 1 : 0)) +#define BONDED_CLIENT_INIT_FLAGS \ + (BIT(FLAG_ACTIVE_INDEX_CHANGED) | BIT(FLAG_NOTIFY_PRESET_LIST) | BIT(FLAG_FEATURES_CHANGED)) static struct bt_has has; @@ -52,12 +51,10 @@ static void active_preset_index_cfg_changed(const struct bt_gatt_attr *attr, uin #if defined(CONFIG_BT_HAS_PRESET_SUPPORT) struct has_client; -/* Active preset notification work */ -static void active_preset_work_process(struct k_work *work); -static K_WORK_DEFINE(active_preset_work, active_preset_work_process); - -static void process_control_point_work(struct k_work *work); -static void read_presets_req_free(struct has_client *client); +static int read_preset_response(struct has_client *client); +static int preset_list_changed(struct has_client *client); +static int preset_list_changed_generic_update_tail(struct has_client *client); +static int preset_list_changed_record_deleted_last(struct has_client *client); static ssize_t write_control_point(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *data, uint16_t len, uint16_t offset, uint8_t flags); @@ -69,14 +66,17 @@ static void preset_cp_cfg_changed(const struct bt_gatt_attr *attr, uint16_t valu static ssize_t read_active_preset_index(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { + uint8_t active_index; + LOG_DBG("conn %p attr %p offset %d", (void *)conn, attr, offset); - if (offset > sizeof(has.active_index)) { + if (offset > sizeof(active_index)) { return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET); } - return bt_gatt_attr_read(conn, attr, buf, len, offset, &has.active_index, - sizeof(has.active_index)); + active_index = bt_has_preset_active_get(); + + return bt_gatt_attr_read(conn, attr, buf, len, offset, &active_index, sizeof(active_index)); } #endif /* CONFIG_BT_HAS_PRESET_SUPPORT */ @@ -115,8 +115,6 @@ static ssize_t read_features(struct bt_conn *conn, const struct bt_gatt_attr *at read_features, NULL, NULL), #endif /* CONFIG_BT_HAS_FEATURES_NOTIFIABLE */ - - #if defined(CONFIG_BT_HAS_PRESET_SUPPORT) #if defined(CONFIG_BT_HAS_PRESET_CONTROL_POINT_NOTIFIABLE) #define BT_HAS_CHR_PRESET_CONTROL_POINT \ @@ -157,32 +155,35 @@ static struct bt_gatt_attr has_attrs[] = { }; static struct bt_gatt_service has_svc; - -#if defined(CONFIG_BT_HAS_FEATURES_NOTIFIABLE) -/* Features notification work */ -static void features_work_process(struct k_work *work); -static K_WORK_DEFINE(features_work, features_work_process); - -#define FEATURES_ATTR &has_attrs[2] -#if defined(CONFIG_BT_HAS_PRESET_SUPPORT) -#define PRESET_CONTROL_POINT_ATTR &has_attrs[5] -#define ACTIVE_PRESET_INDEX_ATTR &has_attrs[8] -#endif /* CONFIG_BT_HAS_PRESET_SUPPORT */ -#else -#if defined(CONFIG_BT_HAS_PRESET_SUPPORT) -#define PRESET_CONTROL_POINT_ATTR &has_attrs[4] -#define ACTIVE_PRESET_INDEX_ATTR &has_attrs[7] -#endif /* CONFIG_BT_HAS_PRESET_SUPPORT */ -#endif /* CONFIG_BT_HAS_FEATURES_NOTIFIABLE */ +static struct bt_gatt_attr *hearing_aid_features_attr; +static struct bt_gatt_attr *preset_control_point_attr; +static struct bt_gatt_attr *active_preset_index_attr; #if defined(CONFIG_BT_HAS_PRESET_SUPPORT) || defined(CONFIG_BT_HAS_FEATURES_NOTIFIABLE) -enum { +static void notify_work_handler(struct k_work *work); + +enum flag_internal { FLAG_ACTIVE_INDEX_CHANGED, - FLAG_CONTROL_POINT_NOTIFY, + FLAG_PENDING_READ_PRESET_RESPONSE, + FLAG_NOTIFY_PRESET_LIST, + FLAG_NOTIFY_PRESET_LIST_GENERIC_UPDATE_TAIL, + FLAG_NOTIFY_PRESET_LIST_RECORD_DELETED_LAST, FLAG_FEATURES_CHANGED, FLAG_NUM, }; +/* Stored client context */ +static struct client_context { + bt_addr_le_t addr; + + /* Pending notification flags */ + ATOMIC_DEFINE(flags, FLAG_NUM); + + /* Last notified preset index */ + uint8_t last_preset_index_known; +} contexts[CONFIG_BT_MAX_PAIRED]; + +/* Connected client clientance */ static struct has_client { struct bt_conn *conn; #if defined(CONFIG_BT_HAS_PRESET_SUPPORT) @@ -195,13 +196,70 @@ static struct has_client { uint8_t preset_changed_index_next; struct bt_has_cp_read_presets_req read_presets_req; - struct k_work control_point_work; #endif /* CONFIG_BT_HAS_PRESET_SUPPORT */ - ATOMIC_DEFINE(flags, FLAG_NUM); -} has_client_list[BT_HAS_MAX_CONN]; + struct k_work_delayable notify_work; + struct client_context *context; +} has_client_list[MAX_INSTS]; + + +static struct client_context *context_find(const bt_addr_le_t *addr) +{ + for (size_t i = 0; i < ARRAY_SIZE(contexts); i++) { + if (bt_addr_le_eq(&contexts[i].addr, addr)) { + return &contexts[i]; + } + } + + return NULL; +} -static struct has_client *client_get_or_new(struct bt_conn *conn) +static struct client_context *context_alloc(const bt_addr_le_t *addr) { + struct client_context *context; + + /* Free contexts has BT_ADDR_LE_ANY as the address */ + context = context_find(BT_ADDR_LE_ANY); + if (context == NULL) { + return NULL; + } + + memset(context, 0, sizeof(*context)); + + bt_addr_le_copy(&context->addr, addr); + + return context; +} + +static void context_free(struct client_context *context) +{ + bt_addr_le_copy(&context->addr, BT_ADDR_LE_ANY); +} + +static void client_free(struct has_client *client) +{ + struct bt_conn_info info = { 0 }; + int err; + +#if defined(CONFIG_BT_HAS_PRESET_SUPPORT) || defined(CONFIG_BT_HAS_FEATURES_NOTIFIABLE) + (void)k_work_cancel_delayable(&client->notify_work); +#endif /* CONFIG_BT_HAS_PRESET_SUPPORT || CONFIG_BT_HAS_FEATURES_NOTIFIABLE */ + + err = bt_conn_get_info(client->conn, &info); + __ASSERT_NO_MSG(err == 0); + + if (client->context != NULL && !bt_addr_le_is_bonded(info.id, info.le.dst)) { + /* Free stored context of non-bonded client */ + context_free(client->context); + client->context = NULL; + } + + bt_conn_unref(client->conn); + client->conn = NULL; +} + +static struct has_client *client_alloc(struct bt_conn *conn) +{ + struct bt_conn_info info = { 0 }; struct has_client *client = NULL; for (size_t i = 0; i < ARRAY_SIZE(has_client_list); i++) { @@ -210,39 +268,44 @@ static struct has_client *client_get_or_new(struct bt_conn *conn) } /* first free slot */ - if (!client && !has_client_list[i].conn) { + if (!client && has_client_list[i].conn == NULL) { client = &has_client_list[i]; } } __ASSERT(client, "failed to get client for conn %p", (void *)conn); + memset(client, 0, sizeof(*client)); + client->conn = bt_conn_ref(conn); -#if defined(CONFIG_BT_HAS_PRESET_SUPPORT) - k_work_init(&client->control_point_work, process_control_point_work); -#endif /* CONFIG_BT_HAS_PRESET_SUPPORT */ +#if defined(CONFIG_BT_HAS_PRESET_SUPPORT) || defined(CONFIG_BT_HAS_FEATURES_NOTIFIABLE) + k_work_init_delayable(&client->notify_work, notify_work_handler); +#endif /* CONFIG_BT_HAS_PRESET_SUPPORT || CONFIG_BT_HAS_FEATURES_NOTIFIABLE */ - return client; -} + bt_conn_get_info(conn, &info); -static void client_free(struct has_client *client) -{ -#if defined(CONFIG_BT_HAS_PRESET_SUPPORT) - (void)k_work_cancel(&client->control_point_work); - read_presets_req_free(client); -#endif /* CONFIG_BT_HAS_PRESET_SUPPORT */ + client->context = context_find(info.le.dst); + if (client->context == NULL) { + client->context = context_alloc(info.le.dst); + if (client->context == NULL) { + LOG_ERR("Failed to allocate client_context for %s", + bt_addr_le_str(info.le.dst)); - atomic_clear_bit(client->flags, FLAG_CONTROL_POINT_NOTIFY); - atomic_clear_bit(client->flags, FLAG_ACTIVE_INDEX_CHANGED); - atomic_clear_bit(client->flags, FLAG_FEATURES_CHANGED); + client_free(client); - bt_conn_unref(client->conn); + return NULL; + } - client->conn = NULL; + LOG_DBG("New client_context for %s", bt_addr_le_str(info.le.dst)); + } else { + LOG_DBG("Restored client_context for %s", bt_addr_le_str(info.le.dst)); + } + + return client; } -static struct has_client *client_get(struct bt_conn *conn) +static struct has_client *client_find_by_conn(struct bt_conn *conn) { for (size_t i = 0; i < ARRAY_SIZE(has_client_list); i++) { if (conn == has_client_list[i].conn) { @@ -253,9 +316,27 @@ static struct has_client *client_get(struct bt_conn *conn) return NULL; } +static void notify_work_reschedule(struct has_client *client, k_timeout_t delay) +{ + int err; + + __ASSERT(client->conn, "Not connected"); + + if (k_work_delayable_remaining_get(&client->notify_work) > 0) { + return; + } + + err = k_work_reschedule(&client->notify_work, delay); + if (err < 0) { + LOG_ERR("Failed to reschedule notification work err %d", err); + } +} + static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) { struct has_client *client; + struct bt_conn_info info; + int ret; LOG_DBG("conn %p level %d err %d", (void *)conn, level, err); @@ -263,74 +344,195 @@ static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_ return; } - client = client_get_or_new(conn); + client = client_alloc(conn); if (unlikely(!client)) { LOG_ERR("Failed to allocate client"); return; } - if (!bt_addr_le_is_bonded(conn->id, &conn->le.dst)) { + ret = bt_conn_get_info(client->conn, &info); + if (ret < 0) { + LOG_ERR("bt_conn_get_info err %d", ret); return; } -#if defined(CONFIG_BT_HAS_PRESET_SUPPORT) - /* Notify after reconnection */ - if (atomic_test_and_clear_bit(client->flags, FLAG_ACTIVE_INDEX_CHANGED)) { - /* Emit active preset notification */ - k_work_submit(&active_preset_work); + if (!bt_addr_le_is_bonded(info.id, info.le.dst)) { + return; } - if (atomic_test_and_clear_bit(client->flags, FLAG_CONTROL_POINT_NOTIFY)) { - /* Emit preset changed notifications */ - k_work_submit(&client->control_point_work); + if (atomic_get(client->context->flags) != 0) { + notify_work_reschedule(client, K_NO_WAIT); } -#endif /* CONFIG_BT_HAS_PRESET_SUPPORT */ +} -#if defined(CONFIG_BT_HAS_FEATURES_NOTIFIABLE) - if (atomic_test_and_clear_bit(client->flags, FLAG_FEATURES_CHANGED)) { - /* Emit preset changed notifications */ - k_work_submit(&features_work); +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + struct has_client *client; + + LOG_DBG("conn %p reason %d", (void *)conn, reason); + + client = client_find_by_conn(conn); + if (client) { + client_free(client); } -#endif /* CONFIG_BT_HAS_FEATURES_NOTIFIABLE */ } -static void connected(struct bt_conn *conn, uint8_t err) +static void identity_resolved(struct bt_conn *conn, const bt_addr_le_t *rpa, + const bt_addr_le_t *identity) { struct has_client *client; - LOG_DBG("conn %p err %d", conn, err); + LOG_DBG("conn %p %s -> %s", (void *)conn, bt_addr_le_str(rpa), bt_addr_le_str(identity)); - if (err != 0 || !bt_addr_le_is_bonded(conn->id, &conn->le.dst)) { + client = client_find_by_conn(conn); + if (client == NULL) { return; } - client = client_get_or_new(conn); - if (unlikely(!client)) { - LOG_ERR("Failed to allocate client"); - return; + bt_addr_le_copy(&client->context->addr, identity); +} + +BT_CONN_CB_DEFINE(conn_cb) = { + .disconnected = disconnected, + .security_changed = security_changed, + .identity_resolved = identity_resolved, +}; + +static void notify_work_handler(struct k_work *work) +{ + struct k_work_delayable *dwork = k_work_delayable_from_work(work); + struct has_client *client = CONTAINER_OF(dwork, struct has_client, notify_work); + int err; + + if (IS_ENABLED(CONFIG_BT_HAS_FEATURES_NOTIFIABLE) && + atomic_test_and_clear_bit(client->context->flags, FLAG_FEATURES_CHANGED) && + bt_gatt_is_subscribed(client->conn, hearing_aid_features_attr, BT_GATT_CCC_NOTIFY)) { + err = bt_gatt_notify(client->conn, hearing_aid_features_attr, &has.features, + sizeof(has.features)); + if (err == -ENOMEM) { + atomic_set_bit(client->context->flags, FLAG_FEATURES_CHANGED); + notify_work_reschedule(client, K_USEC(BT_AUDIO_NOTIFY_RETRY_DELAY_US)); + } else if (err < 0) { + LOG_ERR("Notify features err %d", err); + } + } + +#if defined(CONFIG_BT_HAS_PRESET_SUPPORT) + if (atomic_test_and_clear_bit(client->context->flags, FLAG_PENDING_READ_PRESET_RESPONSE)) { + err = read_preset_response(client); + if (err == -ENOMEM) { + atomic_set_bit(client->context->flags, FLAG_PENDING_READ_PRESET_RESPONSE); + notify_work_reschedule(client, K_USEC(BT_AUDIO_NOTIFY_RETRY_DELAY_US)); + } else if (err < 0) { + LOG_ERR("Notify read preset response err %d", err); + } + } else if (atomic_test_and_clear_bit(client->context->flags, FLAG_NOTIFY_PRESET_LIST)) { + err = preset_list_changed(client); + if (err == -ENOMEM) { + atomic_set_bit(client->context->flags, FLAG_NOTIFY_PRESET_LIST); + notify_work_reschedule(client, K_USEC(BT_AUDIO_NOTIFY_RETRY_DELAY_US)); + } else if (err < 0) { + LOG_ERR("Notify preset list changed err %d", err); + } + } else if (atomic_test_and_clear_bit(client->context->flags, + FLAG_NOTIFY_PRESET_LIST_GENERIC_UPDATE_TAIL)) { + err = preset_list_changed_generic_update_tail(client); + if (err == -ENOMEM) { + atomic_set_bit(client->context->flags, + FLAG_NOTIFY_PRESET_LIST_GENERIC_UPDATE_TAIL); + notify_work_reschedule(client, K_USEC(BT_AUDIO_NOTIFY_RETRY_DELAY_US)); + } else if (err < 0) { + LOG_ERR("Notify preset list changed generic update tail err %d", err); + } + } else if (atomic_test_and_clear_bit(client->context->flags, + FLAG_NOTIFY_PRESET_LIST_RECORD_DELETED_LAST)) { + err = preset_list_changed_record_deleted_last(client); + if (err == -ENOMEM) { + atomic_set_bit(client->context->flags, + FLAG_NOTIFY_PRESET_LIST_RECORD_DELETED_LAST); + notify_work_reschedule(client, K_USEC(BT_AUDIO_NOTIFY_RETRY_DELAY_US)); + } else if (err < 0) { + LOG_ERR("Notify preset list changed recoed deleted last err %d", err); + } + } + +#endif /* CONFIG_BT_HAS_PRESET_SUPPORT */ + + if (IS_ENABLED(CONFIG_BT_HAS_PRESET_SUPPORT) && + atomic_test_and_clear_bit(client->context->flags, FLAG_ACTIVE_INDEX_CHANGED) && + bt_gatt_is_subscribed(client->conn, active_preset_index_attr, BT_GATT_CCC_NOTIFY)) { + uint8_t active_index; + + active_index = bt_has_preset_active_get(); + + err = bt_gatt_notify(client->conn, active_preset_index_attr, + &active_index, sizeof(active_index)); + if (err == -ENOMEM) { + atomic_set_bit(client->context->flags, FLAG_ACTIVE_INDEX_CHANGED); + notify_work_reschedule(client, K_USEC(BT_AUDIO_NOTIFY_RETRY_DELAY_US)); + } else if (err < 0) { + LOG_ERR("Notify active index err %d", err); + } } } -static void disconnected(struct bt_conn *conn, uint8_t reason) +static void notify(struct has_client *client, enum flag_internal flag) { - struct has_client *client; + if (client != NULL) { + atomic_set_bit(client->context->flags, flag); + notify_work_reschedule(client, K_NO_WAIT); + return; + } - LOG_DBG("conn %p reason %d", (void *)conn, reason); + /* Mark notification to be sent to all clients */ + for (size_t i = 0U; i < ARRAY_SIZE(contexts); i++) { + atomic_set_bit(contexts[i].flags, flag); + } - client = client_get(conn); - if (client) { - client_free(client); + for (size_t i = 0U; i < ARRAY_SIZE(has_client_list); i++) { + client = &has_client_list[i]; + + if (client->conn == NULL) { + continue; + } + + notify_work_reschedule(client, K_NO_WAIT); } } -BT_CONN_CB_DEFINE(conn_cb) = { - .connected = connected, - .disconnected = disconnected, - .security_changed = security_changed, +static void bond_deleted_cb(uint8_t id, const bt_addr_le_t *addr) +{ + struct client_context *context; + + context = context_find(addr); + if (context != NULL) { + context_free(context); + } +} + +static struct bt_conn_auth_info_cb auth_info_cb = { + .bond_deleted = bond_deleted_cb, }; + +static void restore_client_context(const struct bt_bond_info *info, void *user_data) +{ + struct client_context *context; + + context = context_alloc(&info->addr); + if (context == NULL) { + LOG_ERR("Failed to allocate client_context for %s", bt_addr_le_str(&info->addr)); + return; + } + + /* Notify all the characteristics values after reboot */ + atomic_set(context->flags, BONDED_CLIENT_INIT_FLAGS); +} + #endif /* CONFIG_BT_HAS_PRESET_SUPPORT || CONFIG_BT_HAS_FEATURES_NOTIFIABLE */ #if defined(CONFIG_BT_HAS_PRESET_SUPPORT) +static struct has_preset *active_preset; + /* HAS internal preset representation */ static struct has_preset { uint8_t index; @@ -341,29 +543,20 @@ static struct has_preset { const char *name; #endif /* CONFIG_BT_HAS_PRESET_NAME_DYNAMIC */ const struct bt_has_preset_ops *ops; -} has_preset_list[CONFIG_BT_HAS_PRESET_COUNT]; - -/* Number of registered presets */ -static uint8_t has_preset_num; + sys_snode_t node; +} preset_pool[CONFIG_BT_HAS_PRESET_COUNT]; -static bool read_presets_req_pending_cp(const struct has_client *client) -{ - return client->read_presets_req.num_presets > 0; -} - -static void read_presets_req_free(struct has_client *client) -{ - client->read_presets_req.num_presets = 0; -} +static sys_slist_t preset_list = SYS_SLIST_STATIC_INIT(&preset_list); +static sys_slist_t preset_free_list = SYS_SLIST_STATIC_INIT(&preset_free_list); typedef uint8_t (*preset_func_t)(const struct has_preset *preset, void *user_data); static void preset_foreach(uint8_t start_index, uint8_t end_index, preset_func_t func, void *user_data) { - for (size_t i = 0; i < ARRAY_SIZE(has_preset_list); i++) { - const struct has_preset *preset = &has_preset_list[i]; + struct has_preset *preset, *tmp; + SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&preset_list, preset, tmp, node) { if (preset->index < start_index) { continue; } @@ -387,70 +580,143 @@ static uint8_t preset_found(const struct has_preset *preset, void *user_data) return BT_HAS_PRESET_ITER_STOP; } -static int preset_index_compare(const void *p1, const void *p2) +static void preset_insert(struct has_preset *preset) { - const struct has_preset *preset_1 = p1; - const struct has_preset *preset_2 = p2; - - if (preset_1->index == BT_HAS_PRESET_INDEX_NONE) { - return 1; - } + struct has_preset *tmp, *prev = NULL; + + SYS_SLIST_FOR_EACH_CONTAINER(&preset_list, tmp, node) { + if (tmp->index > preset->index) { + if (prev) { + sys_slist_insert(&preset_list, &prev->node, &preset->node); + } else { + sys_slist_prepend(&preset_list, &preset->node); + } + return; + } - if (preset_2->index == BT_HAS_PRESET_INDEX_NONE) { - return -1; + prev = tmp; } - return preset_1->index - preset_2->index; + sys_slist_append(&preset_list, &preset->node); } static struct has_preset *preset_alloc(uint8_t index, enum bt_has_properties properties, const char *name, const struct bt_has_preset_ops *ops) { - struct has_preset *preset = NULL; + struct has_preset *preset; + sys_snode_t *node; + + node = sys_slist_get(&preset_free_list); + if (node == NULL) { + return NULL; + } - if (has_preset_num < ARRAY_SIZE(has_preset_list)) { - preset = &has_preset_list[has_preset_num]; - preset->index = index; - preset->properties = properties; + preset = CONTAINER_OF(node, struct has_preset, node); + preset->index = index; + preset->properties = properties; #if defined(CONFIG_BT_HAS_PRESET_NAME_DYNAMIC) - utf8_lcpy(preset->name, name, ARRAY_SIZE(preset->name)); + utf8_lcpy(preset->name, name, ARRAY_SIZE(preset->name)); #else - preset->name = name; + preset->name = name; #endif /* CONFIG_BT_HAS_PRESET_NAME_DYNAMIC */ - preset->ops = ops; - - has_preset_num++; + preset->ops = ops; - /* sort the presets in index ascending order */ - qsort(has_preset_list, has_preset_num, sizeof(*preset), preset_index_compare); - } + preset_insert(preset); return preset; } static void preset_free(struct has_preset *preset) { - preset->index = BT_HAS_PRESET_INDEX_NONE; + bool removed; + + removed = sys_slist_find_and_remove(&preset_list, &preset->node); + if (removed) { + sys_slist_append(&preset_free_list, &preset->node); + } +} + +static struct has_preset *preset_get_head(void) +{ + struct has_preset *next; + + return SYS_SLIST_PEEK_HEAD_CONTAINER(&preset_list, next, node); +} + +static struct has_preset *preset_get_tail(void) +{ + struct has_preset *prev; + + return SYS_SLIST_PEEK_TAIL_CONTAINER(&preset_list, prev, node); +} + +static struct has_preset *preset_get_prev(const struct has_preset *preset) +{ + struct has_preset *prev; + + SYS_SLIST_FOR_EACH_CONTAINER(&preset_list, prev, node) { + if (SYS_SLIST_PEEK_NEXT_CONTAINER(prev, node) == preset) { + return prev; + } + } + + prev = preset_get_tail(); + if (prev == preset) { + return NULL; + } + + return prev; +} + +static struct has_preset *preset_lookup_index(uint8_t index) +{ + struct has_preset *preset; - /* sort the presets in index ascending order */ - if (has_preset_num > 1) { - qsort(has_preset_list, has_preset_num, sizeof(*preset), preset_index_compare); + SYS_SLIST_FOR_EACH_CONTAINER(&preset_list, preset, node) { + if (preset->index == index) { + return preset; + } } - has_preset_num--; + return NULL; +} + +static struct has_preset *preset_get_next(struct has_preset *preset) +{ + struct has_preset *next; + + next = SYS_SLIST_PEEK_NEXT_CONTAINER(preset, node); + if (next == NULL) { + next = preset_get_head(); + if (next == preset) { + return NULL; + } + } + + return next; +} + +static uint8_t preset_get_prev_index(const struct has_preset *preset) +{ + const struct has_preset *prev; + + prev = preset_get_prev(preset); + if (prev == NULL || prev->index >= preset->index) { + return BT_HAS_PRESET_INDEX_NONE; + } + + return prev->index; } static void control_point_ntf_complete(struct bt_conn *conn, void *user_data) { - struct has_client *client = client_get(conn); + struct has_client *client = client_find_by_conn(conn); LOG_DBG("conn %p", (void *)conn); /* Resubmit if needed */ - if (client != NULL && - (read_presets_req_pending_cp(client) || - atomic_test_and_clear_bit(client->flags, FLAG_CONTROL_POINT_NOTIFY))) { - k_work_submit(&client->control_point_work); + if (client != NULL && atomic_get(client->context->flags) != 0) { + notify_work_reschedule(client, K_NO_WAIT); } } @@ -468,10 +734,20 @@ static void control_point_ind_complete(struct bt_conn *conn, static int control_point_send(struct has_client *client, struct net_buf_simple *buf) { + const uint16_t mtu_size = bt_gatt_get_mtu(client->conn); + /* PDU structure is [Opcode (1)] [Handle (2)] [...] */ + const uint16_t pdu_size = 3 + buf->len; + + if (mtu_size < pdu_size) { + LOG_WRN("Sending truncated control point PDU %d < %d", mtu_size, pdu_size); + buf->len -= (pdu_size - mtu_size); + } + #if defined(CONFIG_BT_HAS_PRESET_CONTROL_POINT_NOTIFIABLE) if (bt_eatt_count(client->conn) > 0 && - bt_gatt_is_subscribed(client->conn, PRESET_CONTROL_POINT_ATTR, BT_GATT_CCC_NOTIFY)) { - client->params.ntf.attr = PRESET_CONTROL_POINT_ATTR; + bt_gatt_is_subscribed(client->conn, preset_control_point_attr, BT_GATT_CCC_NOTIFY)) { + memset(&client->params.ntf, 0, sizeof(client->params.ntf)); + client->params.ntf.attr = preset_control_point_attr; client->params.ntf.func = control_point_ntf_complete; client->params.ntf.data = buf->data; client->params.ntf.len = buf->len; @@ -480,8 +756,9 @@ static int control_point_send(struct has_client *client, struct net_buf_simple * } #endif /* CONFIG_BT_HAS_PRESET_CONTROL_POINT_NOTIFIABLE */ - if (bt_gatt_is_subscribed(client->conn, PRESET_CONTROL_POINT_ATTR, BT_GATT_CCC_INDICATE)) { - client->params.ind.attr = PRESET_CONTROL_POINT_ATTR; + if (bt_gatt_is_subscribed(client->conn, preset_control_point_attr, BT_GATT_CCC_INDICATE)) { + memset(&client->params.ind, 0, sizeof(client->params.ind)); + client->params.ind.attr = preset_control_point_attr; client->params.ind.func = control_point_ind_complete; client->params.ind.destroy = NULL; client->params.ind.data = buf->data; @@ -497,22 +774,25 @@ static int control_point_send_all(struct net_buf_simple *buf) { int result = 0; - for (size_t i = 0; i < ARRAY_SIZE(has_client_list); i++) { - struct has_client *client = &has_client_list[i]; + for (size_t i = 0U; i < ARRAY_SIZE(contexts); i++) { + struct client_context *context = &contexts[i]; + struct has_client *client = NULL; int err; - if (!client->conn) { + for (size_t j = 0U; j < ARRAY_SIZE(has_client_list); j++) { + if (has_client_list[j].context == context) { + client = &has_client_list[j]; + break; + } + } + + if (client == NULL || client->conn == NULL) { /* Mark preset changed operation as pending */ - atomic_set_bit(client->flags, FLAG_CONTROL_POINT_NOTIFY); - /* For simplicity we simply start with the first index, - * rather than keeping detailed logs of which clients - * have knowledge of which presets - */ - client->preset_changed_index_next = BT_HAS_PRESET_INDEX_FIRST; + atomic_set_bit(context->flags, FLAG_NOTIFY_PRESET_LIST); continue; } - if (!bt_gatt_is_subscribed(client->conn, PRESET_CONTROL_POINT_ATTR, + if (!bt_gatt_is_subscribed(client->conn, preset_control_point_attr, BT_GATT_CCC_NOTIFY | BT_GATT_CCC_INDICATE)) { continue; } @@ -535,7 +815,8 @@ static int bt_has_cp_read_preset_rsp(struct has_client *client, const struct has NET_BUF_SIMPLE_DEFINE(buf, sizeof(*hdr) + sizeof(*rsp) + BT_HAS_PRESET_NAME_MAX); - LOG_DBG("conn %p preset %p is_last 0x%02x", (void *)client->conn, preset, is_last); + LOG_DBG("conn %p index 0x%02x prop 0x%02x %s is_last 0x%02x", (void *)client->conn, + preset->index, preset->properties, preset->name, is_last); hdr = net_buf_simple_add(&buf, sizeof(*hdr)); hdr->opcode = BT_HAS_OP_READ_PRESET_RSP; @@ -548,23 +829,6 @@ static int bt_has_cp_read_preset_rsp(struct has_client *client, const struct has return control_point_send(client, &buf); } -static uint8_t get_prev_preset_index(const struct has_preset *preset) -{ - const struct has_preset *prev = NULL; - - for (size_t i = 0; i < ARRAY_SIZE(has_preset_list); i++) { - const struct has_preset *tmp = &has_preset_list[i]; - - if (tmp->index == BT_HAS_PRESET_INDEX_NONE || tmp == preset) { - break; - } - - prev = tmp; - } - - return prev ? prev->index : BT_HAS_PRESET_INDEX_NONE; -} - static void preset_changed_prepare(struct net_buf_simple *buf, uint8_t change_id, uint8_t is_last) { struct bt_has_cp_hdr *hdr; @@ -577,8 +841,8 @@ static void preset_changed_prepare(struct net_buf_simple *buf, uint8_t change_id preset_changed->is_last = is_last; } -static int bt_has_cp_generic_update(struct has_client *client, const struct has_preset *preset, - uint8_t is_last) +static int bt_has_cp_generic_update(struct has_client *client, uint8_t prev_index, uint8_t index, + uint8_t properties, const char *name, uint8_t is_last) { struct bt_has_cp_generic_update *generic_update; @@ -586,13 +850,16 @@ static int bt_has_cp_generic_update(struct has_client *client, const struct has_ sizeof(struct bt_has_cp_preset_changed) + sizeof(struct bt_has_cp_generic_update) + BT_HAS_PRESET_NAME_MAX); + LOG_DBG("client %p prev_index 0x%02x index 0x%02x prop 0x%02x %s is_last %d", + client, prev_index, index, properties, name, is_last); + preset_changed_prepare(&buf, BT_HAS_CHANGE_ID_GENERIC_UPDATE, is_last); generic_update = net_buf_simple_add(&buf, sizeof(*generic_update)); - generic_update->prev_index = get_prev_preset_index(preset); - generic_update->index = preset->index; - generic_update->properties = preset->properties; - net_buf_simple_add_mem(&buf, preset->name, strlen(preset->name)); + generic_update->prev_index = prev_index; + generic_update->index = index; + generic_update->properties = properties; + net_buf_simple_add_mem(&buf, name, strlen(name)); if (client) { return control_point_send(client, &buf); @@ -601,77 +868,198 @@ static int bt_has_cp_generic_update(struct has_client *client, const struct has_ } } -static void process_control_point_work(struct k_work *work) +static void update_last_preset_index_known(struct has_client *client, uint8_t index) { - struct has_client *client = CONTAINER_OF(work, struct has_client, control_point_work); + if (client != NULL) { + client->context->last_preset_index_known = index; + return; + } + + for (size_t i = 0; i < ARRAY_SIZE(has_client_list); i++) { + client = &has_client_list[i]; + + /* For each connected client */ + if (client->conn != NULL && client->context != NULL) { + client->context->last_preset_index_known = index; + } + } +} + +static int read_preset_response(struct has_client *client) +{ + const struct has_preset *preset = NULL; + bool is_last = true; int err; - if (!client->conn) { - return; + __ASSERT_NO_MSG(client != NULL); + + preset_foreach(client->read_presets_req.start_index, BT_HAS_PRESET_INDEX_LAST, + preset_found, &preset); + + if (unlikely(preset == NULL)) { + return bt_has_cp_read_preset_rsp(client, NULL, BT_HAS_IS_LAST); } - if (read_presets_req_pending_cp(client)) { - const struct has_preset *preset = NULL; - bool is_last = true; + if (client->read_presets_req.num_presets > 1) { + const struct has_preset *next = NULL; - preset_foreach(client->read_presets_req.start_index, BT_HAS_PRESET_INDEX_LAST, - preset_found, &preset); + preset_foreach(preset->index + 1, BT_HAS_PRESET_INDEX_LAST, preset_found, &next); - if (unlikely(preset == NULL)) { - (void)bt_has_cp_read_preset_rsp(client, NULL, 0x01); + is_last = next == NULL; + } - return; - } + err = bt_has_cp_read_preset_rsp(client, preset, is_last); + if (err != 0) { + return err; + } - if (client->read_presets_req.num_presets > 1) { - const struct has_preset *next = NULL; + if (preset->index > client->context->last_preset_index_known) { + update_last_preset_index_known(client, preset->index); + } - preset_foreach(preset->index + 1, BT_HAS_PRESET_INDEX_LAST, - preset_found, &next); + if (!is_last) { + client->read_presets_req.start_index = preset->index + 1; + client->read_presets_req.num_presets--; - is_last = next == NULL; + atomic_set_bit(client->context->flags, FLAG_PENDING_READ_PRESET_RESPONSE); + notify_work_reschedule(client, K_USEC(BT_AUDIO_NOTIFY_RETRY_DELAY_US)); + } - } + return 0; +} - err = bt_has_cp_read_preset_rsp(client, preset, is_last); - if (err) { - LOG_ERR("bt_has_cp_read_preset_rsp failed (err %d)", err); - } +static int bt_has_cp_preset_record_deleted(struct has_client *client, uint8_t index) +{ + NET_BUF_SIMPLE_DEFINE(buf, sizeof(struct bt_has_cp_hdr) + + sizeof(struct bt_has_cp_preset_changed) + sizeof(uint8_t)); - if (err || is_last) { - read_presets_req_free(client); - } else { - client->read_presets_req.start_index = preset->index + 1; - client->read_presets_req.num_presets--; - } - } else if (atomic_test_and_clear_bit(client->flags, FLAG_CONTROL_POINT_NOTIFY)) { - const struct has_preset *preset = NULL; - const struct has_preset *next = NULL; - bool is_last = true; + preset_changed_prepare(&buf, BT_HAS_CHANGE_ID_PRESET_DELETED, BT_HAS_IS_LAST); + net_buf_simple_add_u8(&buf, index); - preset_foreach(client->preset_changed_index_next, - BT_HAS_PRESET_INDEX_LAST, preset_found, &preset); + if (client != NULL) { + return control_point_send(client, &buf); + } else { + return control_point_send_all(&buf); + } +} - if (preset == NULL) { - return; - } +/* Generic Update the last (already deleted) preset */ +static int preset_list_changed_generic_update_tail(struct has_client *client) +{ + const struct has_preset *prev; + struct has_preset last = { + /* The index value of the last preset the client knew about. */ + .index = client->context->last_preset_index_known, - preset_foreach(preset->index + 1, BT_HAS_PRESET_INDEX_LAST, - preset_found, &next); + /* As the properties of deleted preset is not available anymore, we set this value + * to 0x00 meaning the preset is unavailable and non-writable which is actually true + */ + .properties = BT_HAS_PROP_NONE, - is_last = next == NULL; + /* As the name of deleted preset are not available anymore, we set this value + * to the value what is compliant with specification. + * As per HAS_v1.0 the Name is 1-40 octet value. + */ + .name = "N/A", + }; + int err; - err = bt_has_cp_generic_update(client, preset, is_last); - if (err) { - LOG_ERR("bt_has_cp_read_preset_rsp failed (err %d)", err); - } + prev = preset_get_tail(); - if (err || is_last) { - atomic_clear_bit(client->flags, FLAG_CONTROL_POINT_NOTIFY); - } else { - client->preset_changed_index_next = preset->index + 1; - } + err = bt_has_cp_generic_update(client, prev ? prev->index : BT_HAS_PRESET_INDEX_NONE, + last.index, last.properties, last.name, false); + if (err != 0) { + return err; + } + + return 0; +} + +static int preset_list_changed_record_deleted_last(struct has_client *client) +{ + const struct has_preset *last; + int err; + + err = bt_has_cp_preset_record_deleted(client, client->context->last_preset_index_known); + if (err != 0) { + return err; + } + + last = preset_get_tail(); + + update_last_preset_index_known(client, last ? last->index : BT_HAS_PRESET_INDEX_NONE); + + return 0; +} + +static int preset_list_changed(struct has_client *client) +{ + const struct has_preset *preset = NULL; + const struct has_preset *next = NULL; + bool is_last = true; + int err; + + if (sys_slist_is_empty(&preset_list)) { + /* The preset list is empty. We need to indicate deletion of all presets */ + atomic_set_bit(client->context->flags, + FLAG_NOTIFY_PRESET_LIST_GENERIC_UPDATE_TAIL); + atomic_set_bit(client->context->flags, + FLAG_NOTIFY_PRESET_LIST_RECORD_DELETED_LAST); + notify_work_reschedule(client, K_USEC(BT_AUDIO_NOTIFY_RETRY_DELAY_US)); + + return 0; + } + + preset_foreach(client->preset_changed_index_next, BT_HAS_PRESET_INDEX_LAST, + preset_found, &preset); + + if (preset == NULL) { + return 0; } + + preset_foreach(preset->index + 1, BT_HAS_PRESET_INDEX_LAST, preset_found, &next); + + /* It is last Preset Changed notification if there are no presets left to notify and the + * currently notified preset have the highest index known to the client. + */ + is_last = next == NULL && preset->index >= client->context->last_preset_index_known; + + err = bt_has_cp_generic_update(client, preset_get_prev_index(preset), preset->index, + preset->properties, preset->name, is_last); + if (err != 0) { + return err; + } + + if (is_last) { + client->preset_changed_index_next = 0; + + /* It's the last preset notified, so update the highest index known to the client */ + update_last_preset_index_known(client, preset->index); + + return 0; + } + + if (next == NULL) { + /* If we end up here, the last preset known to the client has been removed. + * As we do not hold the information about the deleted presets, we need to use + * Generic Update procedure to: + * 1. Notify the presets that have been removed in range + * (PrevIndex = current_preset_last, Index=previous_preset_last) + * 2. Notify deletion of preset Index=previous_preset_last. + */ + atomic_set_bit(client->context->flags, + FLAG_NOTIFY_PRESET_LIST_GENERIC_UPDATE_TAIL); + atomic_set_bit(client->context->flags, + FLAG_NOTIFY_PRESET_LIST_RECORD_DELETED_LAST); + } else { + client->preset_changed_index_next = preset->index + 1; + + atomic_set_bit(client->context->flags, FLAG_NOTIFY_PRESET_LIST); + } + + notify_work_reschedule(client, K_USEC(BT_AUDIO_NOTIFY_RETRY_DELAY_US)); + + return 0; } static uint8_t handle_read_preset_req(struct bt_conn *conn, struct net_buf_simple *buf) @@ -688,12 +1076,12 @@ static uint8_t handle_read_preset_req(struct bt_conn *conn, struct net_buf_simpl * shall be returned if client writes Read Presets Request but is not registered for * indications. */ - if (!bt_gatt_is_subscribed(conn, PRESET_CONTROL_POINT_ATTR, BT_GATT_CCC_INDICATE)) { + if (!bt_gatt_is_subscribed(conn, preset_control_point_attr, BT_GATT_CCC_INDICATE)) { return BT_ATT_ERR_CCC_IMPROPER_CONF; } - client = client_get(conn); - if (!client) { + client = client_find_by_conn(conn); + if (client == NULL) { return BT_ATT_ERR_UNLIKELY; } @@ -709,7 +1097,7 @@ static uint8_t handle_read_preset_req(struct bt_conn *conn, struct net_buf_simpl } /* Reject if already in progress */ - if (read_presets_req_pending_cp(client)) { + if (atomic_test_bit(client->context->flags, FLAG_PENDING_READ_PRESET_RESPONSE)) { return BT_HAS_ERR_OPERATION_NOT_POSSIBLE; } @@ -717,7 +1105,7 @@ static uint8_t handle_read_preset_req(struct bt_conn *conn, struct net_buf_simpl client->read_presets_req.start_index = req->start_index; client->read_presets_req.num_presets = req->num_presets; - k_work_submit(&client->control_point_work); + notify(client, FLAG_PENDING_READ_PRESET_RESPONSE); return 0; } @@ -759,7 +1147,8 @@ static int set_preset_name(uint8_t index, const char *name, size_t len) preset->ops->name_changed(index, preset->name); } - return bt_has_cp_generic_update(NULL, preset, BT_HAS_IS_LAST); + return bt_has_cp_generic_update(NULL, preset_get_prev_index(preset), preset->index, + preset->properties, preset->name, BT_HAS_IS_LAST); } static uint8_t handle_write_preset_name(struct bt_conn *conn, struct net_buf_simple *buf) @@ -776,11 +1165,11 @@ static uint8_t handle_write_preset_name(struct bt_conn *conn, struct net_buf_sim * shall be returned if client writes Write Preset Name opcode but is not registered for * indications. */ - if (!bt_gatt_is_subscribed(conn, PRESET_CONTROL_POINT_ATTR, BT_GATT_CCC_INDICATE)) { + if (!bt_gatt_is_subscribed(conn, preset_control_point_attr, BT_GATT_CCC_INDICATE)) { return BT_ATT_ERR_CCC_IMPROPER_CONF; } - client = client_get(conn); + client = client_find_by_conn(conn); if (!client) { return BT_ATT_ERR_UNLIKELY; } @@ -801,46 +1190,16 @@ static uint8_t handle_write_preset_name(struct bt_conn *conn, struct net_buf_sim return BT_ATT_ERR_SUCCESS; } -static void active_preset_work_process(struct k_work *work) +static void preset_set_active(struct has_preset *preset) { - const uint8_t active_index = bt_has_preset_active_get(); + if (active_preset != preset) { + active_preset = preset; - for (size_t i = 0U; i < ARRAY_SIZE(has_client_list); i++) { - struct has_client *client = &has_client_list[i]; - int err; - - if (client->conn == NULL) { - /* mark to notify on reconnect */ - atomic_set_bit(client->flags, FLAG_ACTIVE_INDEX_CHANGED); - continue; - } else if (atomic_test_and_clear_bit(client->flags, FLAG_ACTIVE_INDEX_CHANGED)) { - err = bt_gatt_notify(client->conn, ACTIVE_PRESET_INDEX_ATTR, &active_index, - sizeof(active_index)); - if (err != 0) { - LOG_DBG("failed to notify active_index for %p: %d", client->conn, - err); - } - } - } -} - -static void preset_active_set(uint8_t index) -{ - if (index != has.active_index) { - has.active_index = index; - - for (size_t i = 0U; i < ARRAY_SIZE(has_client_list); i++) { - struct has_client *client = &has_client_list[i]; - /* mark to notify */ - atomic_set_bit(client->flags, FLAG_ACTIVE_INDEX_CHANGED); - } - - /* Emit active preset notification */ - k_work_submit(&active_preset_work); + notify(NULL, FLAG_ACTIVE_INDEX_CHANGED); } } -static uint8_t preset_select(const struct has_preset *preset, bool sync) +static uint8_t preset_select(struct has_preset *preset, bool sync) { const int err = preset->ops->select(preset->index, sync); @@ -859,15 +1218,20 @@ static uint8_t preset_select(const struct has_preset *preset, bool sync) return BT_ATT_ERR_UNLIKELY; } - preset_active_set(preset->index); + preset_set_active(preset); return 0; } +static bool is_preset_available(const struct has_preset *preset) +{ + return (preset->properties & BT_HAS_PROP_AVAILABLE) != 0; +} + static uint8_t handle_set_active_preset(struct net_buf_simple *buf, bool sync) { const struct bt_has_cp_set_active_preset *pdu; - const struct has_preset *preset = NULL; + struct has_preset *preset; if (buf->len < sizeof(*pdu)) { return BT_HAS_ERR_INVALID_PARAM_LEN; @@ -875,12 +1239,12 @@ static uint8_t handle_set_active_preset(struct net_buf_simple *buf, bool sync) pdu = net_buf_simple_pull_mem(buf, sizeof(*pdu)); - preset_foreach(pdu->index, pdu->index, preset_found, &preset); + preset = preset_lookup_index(pdu->index); if (preset == NULL) { return BT_ATT_ERR_OUT_OF_RANGE; } - if (!(preset->properties & BT_HAS_PROP_AVAILABLE)) { + if (!is_preset_available(preset)) { return BT_HAS_ERR_OPERATION_NOT_POSSIBLE; } @@ -889,80 +1253,52 @@ static uint8_t handle_set_active_preset(struct net_buf_simple *buf, bool sync) static uint8_t handle_set_next_preset(bool sync) { - const struct has_preset *next_avail = NULL; - const struct has_preset *first_avail = NULL; + struct has_preset *next, *tmp; - for (size_t i = 0; i < has_preset_num; i++) { - const struct has_preset *tmp = &has_preset_list[i]; + if (active_preset == NULL) { + next = preset_get_head(); + } else { + next = preset_get_next(active_preset); + } - if (tmp->index == BT_HAS_PRESET_INDEX_NONE) { + tmp = next; + do { + if (next == NULL) { break; } - if (!(tmp->properties & BT_HAS_PROP_AVAILABLE)) { - continue; + if (is_preset_available(next)) { + return preset_select(next, sync); } - if (tmp->index < has.active_index && !first_avail) { - first_avail = tmp; - continue; - } - - if (tmp->index > has.active_index) { - next_avail = tmp; - break; - } - } - - if (next_avail) { - return preset_select(next_avail, sync); - } - - if (first_avail) { - return preset_select(first_avail, sync); - } + next = preset_get_next(next); + } while (tmp != next); return BT_HAS_ERR_OPERATION_NOT_POSSIBLE; } static uint8_t handle_set_prev_preset(bool sync) { - const struct has_preset *prev_available = NULL; - const struct has_preset *last_available = NULL; - - for (size_t i = 0; i < ARRAY_SIZE(has_preset_list); i++) { - const struct has_preset *tmp = &has_preset_list[i]; - - if (tmp->index == BT_HAS_PRESET_INDEX_NONE) { - break; - } - - if (!(tmp->properties & BT_HAS_PROP_AVAILABLE)) { - continue; - } + struct has_preset *prev, *tmp; - if (tmp->index < has.active_index) { - prev_available = tmp; - continue; - } + if (active_preset == NULL) { + prev = preset_get_tail(); + } else { + prev = preset_get_prev(active_preset); + } - if (prev_available) { + tmp = prev; + do { + if (prev == NULL) { break; } - if (tmp->index > has.active_index) { - last_available = tmp; - continue; + if (is_preset_available(prev)) { + return preset_select(prev, sync); } - } - if (prev_available) { - return preset_select(prev_available, sync); - } - - if (last_available) { - return preset_select(last_available, sync); - } + prev = preset_get_prev(prev); + } while (tmp != prev); return BT_HAS_ERR_OPERATION_NOT_POSSIBLE; } @@ -1034,7 +1370,7 @@ static ssize_t write_control_point(struct bt_conn *conn, const struct bt_gatt_at err = handle_control_point_op(conn, &buf); if (err) { - LOG_WRN("err 0x%02x", err); + LOG_WRN("handle_control_point_op err 0x%02x", err); return BT_GATT_ERR(err); } @@ -1043,7 +1379,7 @@ static ssize_t write_control_point(struct bt_conn *conn, const struct bt_gatt_at int bt_has_preset_register(const struct bt_has_preset_register_param *param) { - struct has_preset *preset = NULL; + struct has_preset *preset; size_t name_len; CHECKIF(param == NULL) { @@ -1082,7 +1418,7 @@ int bt_has_preset_register(const struct bt_has_preset_register_param *param) return -EINVAL; } - preset_foreach(param->index, param->index, preset_found, &preset); + preset = preset_lookup_index(param->index); if (preset != NULL) { return -EALREADY; } @@ -1092,92 +1428,91 @@ int bt_has_preset_register(const struct bt_has_preset_register_param *param) return -ENOMEM; } - return bt_has_cp_generic_update(NULL, preset, BT_HAS_IS_LAST); + if (preset == preset_get_tail()) { + update_last_preset_index_known(NULL, preset->index); + } + + return bt_has_cp_generic_update(NULL, preset_get_prev_index(preset), preset->index, + preset->properties, preset->name, BT_HAS_IS_LAST); } int bt_has_preset_unregister(uint8_t index) { - struct has_preset *preset = NULL; - - NET_BUF_SIMPLE_DEFINE(buf, sizeof(struct bt_has_cp_hdr) + - sizeof(struct bt_has_cp_preset_changed) + sizeof(uint8_t)); + struct has_preset *preset; + int err; CHECKIF(index == BT_HAS_PRESET_INDEX_NONE) { LOG_ERR("index is invalid"); return -EINVAL; } - preset_foreach(index, index, preset_found, &preset); + preset = preset_lookup_index(index); if (preset == NULL) { return -ENOENT; } - preset_changed_prepare(&buf, BT_HAS_CHANGE_ID_PRESET_DELETED, BT_HAS_IS_LAST); - net_buf_simple_add_u8(&buf, preset->index); - - preset_free(preset); - - return control_point_send_all(&buf); -} - -int bt_has_preset_available(uint8_t index) -{ - struct has_preset *preset = NULL; - - CHECKIF(index == BT_HAS_PRESET_INDEX_NONE) { - LOG_ERR("index is invalid"); - return -EINVAL; + if (preset == active_preset) { + return -EADDRINUSE; } - preset_foreach(index, index, preset_found, &preset); - if (preset == NULL) { - return -ENOENT; + err = bt_has_cp_preset_record_deleted(NULL, preset->index); + if (err != 0) { + return err; } - /* toggle property bit if needed */ - if (!(preset->properties & BT_HAS_PROP_AVAILABLE)) { - NET_BUF_SIMPLE_DEFINE(buf, sizeof(struct bt_has_cp_hdr) + - sizeof(struct bt_has_cp_preset_changed) + sizeof(uint8_t)); - - preset->properties ^= BT_HAS_PROP_AVAILABLE; - - preset_changed_prepare(&buf, BT_HAS_CHANGE_ID_PRESET_AVAILABLE, BT_HAS_IS_LAST); - net_buf_simple_add_u8(&buf, preset->index); - - return control_point_send_all(&buf); + if (preset == preset_get_tail()) { + update_last_preset_index_known(NULL, preset_get_prev_index(preset)); } + preset_free(preset); + return 0; } -int bt_has_preset_unavailable(uint8_t index) +static int set_preset_availability(uint8_t index, bool available) { - struct has_preset *preset = NULL; + NET_BUF_SIMPLE_DEFINE(buf, sizeof(struct bt_has_cp_hdr) + + sizeof(struct bt_has_cp_preset_changed) + sizeof(uint8_t)); + struct has_preset *preset; + uint8_t change_id; CHECKIF(index == BT_HAS_PRESET_INDEX_NONE) { LOG_ERR("index is invalid"); return -EINVAL; } - preset_foreach(index, index, preset_found, &preset); + preset = preset_lookup_index(index); if (preset == NULL) { return -ENOENT; } - /* toggle property bit if needed */ - if (preset->properties & BT_HAS_PROP_AVAILABLE) { - NET_BUF_SIMPLE_DEFINE(buf, sizeof(struct bt_has_cp_hdr) + - sizeof(struct bt_has_cp_preset_changed) + sizeof(uint8_t)); - - preset->properties ^= BT_HAS_PROP_AVAILABLE; + if (is_preset_available(preset) == available) { + /* availability not changed */ + return 0; + } - preset_changed_prepare(&buf, BT_HAS_CHANGE_ID_PRESET_UNAVAILABLE, BT_HAS_IS_LAST); - net_buf_simple_add_u8(&buf, preset->index); + preset->properties ^= BT_HAS_PROP_AVAILABLE; - return control_point_send_all(&buf); + if (is_preset_available(preset)) { + change_id = BT_HAS_CHANGE_ID_PRESET_AVAILABLE; + } else { + change_id = BT_HAS_CHANGE_ID_PRESET_UNAVAILABLE; } - return 0; + preset_changed_prepare(&buf, change_id, BT_HAS_IS_LAST); + net_buf_simple_add_u8(&buf, preset->index); + + return control_point_send_all(&buf); +} + +int bt_has_preset_available(uint8_t index) +{ + return set_preset_availability(index, true); +} + +int bt_has_preset_unavailable(uint8_t index) +{ + return set_preset_availability(index, false); } struct bt_has_preset_foreach_data { @@ -1212,27 +1547,34 @@ void bt_has_preset_foreach(uint8_t index, bt_has_preset_func_t func, void *user_ int bt_has_preset_active_set(uint8_t index) { - if (index != BT_HAS_PRESET_INDEX_NONE) { - struct has_preset *preset = NULL; + struct has_preset *preset; - preset_foreach(index, index, preset_found, &preset); - if (preset == NULL) { - return -ENOENT; - } + if (index == BT_HAS_PRESET_INDEX_NONE) { + preset_set_active(NULL); + return 0; + } - if (!(preset->properties & BT_HAS_PROP_AVAILABLE)) { - return -EINVAL; - } + preset = preset_lookup_index(index); + if (preset == NULL) { + return -ENOENT; + } + + if (!is_preset_available(preset)) { + return -EINVAL; } - preset_active_set(index); + preset_set_active(preset); return 0; } uint8_t bt_has_preset_active_get(void) { - return has.active_index; + if (active_preset == NULL) { + return BT_HAS_PRESET_INDEX_NONE; + } + + return active_preset->index; } int bt_has_preset_name_change(uint8_t index, const char *name) @@ -1286,29 +1628,8 @@ static int has_features_register(const struct bt_has_features_param *features) } #if defined(CONFIG_BT_HAS_FEATURES_NOTIFIABLE) -static void features_work_process(struct k_work *work) -{ - for (size_t i = 0U; i < ARRAY_SIZE(has_client_list); i++) { - struct has_client *client = &has_client_list[i]; - int err; - - if (client->conn == NULL) { - /* mark to notify on reconnect */ - atomic_set_bit(client->flags, FLAG_FEATURES_CHANGED); - continue; - } else if (atomic_test_and_clear_bit(client->flags, FLAG_CONTROL_POINT_NOTIFY)) { - err = bt_gatt_notify(client->conn, FEATURES_ATTR, &has.features, - sizeof(has.features)); - if (err != 0) { - LOG_DBG("failed to notify features for %p: %d", client->conn, err); - } - } - } -} - int bt_has_features_set(const struct bt_has_features_param *features) { - uint8_t tmp_features; int err; if (!has.registered) { @@ -1322,37 +1643,13 @@ int bt_has_features_set(const struct bt_has_features_param *features) return 0; } - tmp_features = has.features; - err = has_features_register(features); if (err != 0) { LOG_DBG("Failed to register features"); return err; } - bool tmp_pending_ntf_features[ARRAY_SIZE(has_client_list)]; - - for (size_t i = 0U; i < ARRAY_SIZE(has_client_list); i++) { - struct has_client *client = &has_client_list[i]; - /* save old state */ - tmp_pending_ntf_features[i] = atomic_test_bit(client->flags, FLAG_FEATURES_CHANGED); - /* mark to notify */ - atomic_set_bit(client->flags, FLAG_FEATURES_CHANGED); - } - - err = k_work_submit(&features_work); - if (err < 0) { - /* restore old values */ - for (size_t i = 0U; i < ARRAY_SIZE(has_client_list); i++) { - struct has_client *client = &has_client_list[i]; - - atomic_set_bit_to(client->flags, FLAG_FEATURES_CHANGED, - tmp_pending_ntf_features[i]); - } - has.features = tmp_features; - - return err; - } + notify(NULL, FLAG_FEATURES_CHANGED); return 0; } @@ -1386,6 +1683,36 @@ int bt_has_register(const struct bt_has_features_param *features) return err; } + if (IS_ENABLED(CONFIG_BT_HAS_FEATURES_NOTIFIABLE)) { + hearing_aid_features_attr = bt_gatt_find_by_uuid(has_svc.attrs, has_svc.attr_count, + BT_UUID_HAS_HEARING_AID_FEATURES); + __ASSERT_NO_MSG(hearing_aid_features_attr != NULL); + } + + if (IS_ENABLED(CONFIG_BT_HAS_PRESET_SUPPORT)) { + preset_control_point_attr = bt_gatt_find_by_uuid(has_svc.attrs, has_svc.attr_count, + BT_UUID_HAS_PRESET_CONTROL_POINT); + __ASSERT_NO_MSG(preset_control_point_attr != NULL); + + active_preset_index_attr = bt_gatt_find_by_uuid(has_svc.attrs, has_svc.attr_count, + BT_UUID_HAS_ACTIVE_PRESET_INDEX); + __ASSERT_NO_MSG(active_preset_index_attr != NULL); + } + +#if defined(CONFIG_BT_HAS_PRESET_SUPPORT) + for (size_t i = 0; i < ARRAY_SIZE(preset_pool); i++) { + struct has_preset *preset = &preset_pool[i]; + + sys_slist_append(&preset_free_list, &preset->node); + } +#endif /* CONFIG_BT_HAS_PRESET_SUPPORT */ + +#if defined(CONFIG_BT_HAS_PRESET_SUPPORT) || defined(CONFIG_BT_HAS_FEATURES_NOTIFIABLE) + bt_conn_auth_info_cb_register(&auth_info_cb); + + bt_foreach_bond(BT_ID_DEFAULT, restore_client_context, NULL); +#endif /* CONFIG_BT_HAS_PRESET_SUPPORT || CONFIG_BT_HAS_FEATURES_NOTIFIABLE */ + has.registered = true; return 0; diff --git a/subsys/bluetooth/audio/has_internal.h b/subsys/bluetooth/audio/has_internal.h index 96fafda9473..c4152eaea1c 100644 --- a/subsys/bluetooth/audio/has_internal.h +++ b/subsys/bluetooth/audio/has_internal.h @@ -77,6 +77,7 @@ struct bt_has_cp_read_preset_rsp { struct bt_has_cp_preset_changed { uint8_t change_id; uint8_t is_last; + uint8_t additional_params[0]; } __packed; struct bt_has_cp_generic_update { diff --git a/subsys/bluetooth/audio/micp_internal.h b/subsys/bluetooth/audio/micp_internal.h new file mode 100644 index 00000000000..a68aaca7cdf --- /dev/null +++ b/subsys/bluetooth/audio/micp_internal.h @@ -0,0 +1,36 @@ +/** @file + * @brief Internal APIs for Bluetooth MICP. + */ + +/* + * Copyright (c) 2020 Bose Corporation + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_MICP_INTERNAL_ +#define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_MICP_INTERNAL_ + +#include +#include + +struct bt_micp_mic_ctlr { + uint16_t start_handle; + uint16_t end_handle; + uint16_t mute_handle; + struct bt_gatt_subscribe_params mute_sub_params; + struct bt_gatt_discover_params mute_sub_disc_params; + + bool busy; + uint8_t mute_val_buf[1]; /* Mute value is a single octet */ + struct bt_gatt_write_params write_params; + struct bt_gatt_read_params read_params; + struct bt_gatt_discover_params discover_params; + struct bt_conn *conn; + + uint8_t aics_inst_cnt; + struct bt_aics *aics[CONFIG_BT_AICS_CLIENT_MAX_INSTANCE_COUNT]; +}; + +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_MICP_INTERNAL_ */ diff --git a/subsys/bluetooth/audio/micp_mic_ctlr.c b/subsys/bluetooth/audio/micp_mic_ctlr.c index 3599287fdd5..55fa6c3c5db 100644 --- a/subsys/bluetooth/audio/micp_mic_ctlr.c +++ b/subsys/bluetooth/audio/micp_mic_ctlr.c @@ -19,9 +19,10 @@ #include #include #include - #include +#include "micp_internal.h" + LOG_MODULE_REGISTER(bt_micp_mic_ctlr, CONFIG_BT_MICP_MIC_CTLR_LOG_LEVEL); #include "common/bt_str.h" @@ -29,24 +30,6 @@ LOG_MODULE_REGISTER(bt_micp_mic_ctlr, CONFIG_BT_MICP_MIC_CTLR_LOG_LEVEL); /* Callback functions */ static struct bt_micp_mic_ctlr_cb *micp_mic_ctlr_cb; -struct bt_micp_mic_ctlr { - uint16_t start_handle; - uint16_t end_handle; - uint16_t mute_handle; - struct bt_gatt_subscribe_params mute_sub_params; - struct bt_gatt_discover_params mute_sub_disc_params; - - bool busy; - uint8_t mute_val_buf[1]; /* Mute value is a single octet */ - struct bt_gatt_write_params write_params; - struct bt_gatt_read_params read_params; - struct bt_gatt_discover_params discover_params; - struct bt_conn *conn; - - uint8_t aics_inst_cnt; - struct bt_aics *aics[CONFIG_BT_MICP_MIC_CTLR_MAX_AICS_INST]; -}; - static struct bt_micp_mic_ctlr mic_ctlrs[CONFIG_BT_MAX_CONN]; static struct bt_uuid *mics_uuid = BT_UUID_MICS; diff --git a/subsys/bluetooth/audio/pacs.c b/subsys/bluetooth/audio/pacs.c index f566645d5b5..2ce6db23a9f 100644 --- a/subsys/bluetooth/audio/pacs.c +++ b/subsys/bluetooth/audio/pacs.c @@ -795,11 +795,11 @@ static int pacs_gatt_notify(struct bt_conn *conn, atomic_clear(¬ify_rdy); } - if (err == -ENOTCONN) { - return 0; - } else { - return 0; + if (err && err != -ENOTCONN) { + return err; } + + return 0; } static void notify_cb(struct bt_conn *conn, void *data) diff --git a/subsys/bluetooth/audio/shell/audio.h b/subsys/bluetooth/audio/shell/audio.h index 7ba7fe52883..8beae301036 100644 --- a/subsys/bluetooth/audio/shell/audio.h +++ b/subsys/bluetooth/audio/shell/audio.h @@ -185,7 +185,7 @@ static inline void print_codec_cap(const struct shell *sh, codec_cap->cid, codec_cap->vid, codec_cap->data_len); #if CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_SIZE > 0 - if (codec_cap->id == BT_AUDIO_CODEC_LC3_ID) { + if (codec_cap->id == BT_HCI_CODING_FORMAT_LC3) { print_ltv_array(sh, "data", codec_cap->data, codec_cap->data_len); } else { /* If not LC3, we cannot assume it's LTV */ shell_hexdump(sh, codec_cap->data, codec_cap->data_len); @@ -204,7 +204,7 @@ static inline void print_codec_cfg(const struct shell *sh, codec_cfg->cid, codec_cfg->vid, codec_cfg->data_len); #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 - if (codec_cfg->id == BT_AUDIO_CODEC_LC3_ID) { + if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) { print_ltv_array(sh, "data", codec_cfg->data, codec_cfg->data_len); } else { /* If not LC3, we cannot assume it's LTV */ shell_hexdump(sh, codec_cfg->data, codec_cfg->data_len); @@ -286,29 +286,6 @@ static inline void copy_broadcast_source_preset(struct broadcast_source *source, memcpy(&source->qos, &named_preset->preset.qos, sizeof(source->qos)); memcpy(&source->codec_cfg, &named_preset->preset.codec_cfg, sizeof(source->codec_cfg)); } - -static inline int codec_set_chan_alloc(struct bt_audio_codec_cfg *codec_cfg, - enum bt_audio_location loc) -{ - for (size_t i = 0U; i < codec_cfg->data_len;) { - const uint8_t len = codec_cfg->data[i++]; - const uint8_t type = codec_cfg->data[i++]; - uint8_t *value = &codec_cfg->data[i]; - const uint8_t value_len = len - sizeof(type); - - if (type == BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC) { - const uint32_t loc_32 = loc; - - sys_put_le32(loc_32, value); - - return 0; - } - i += value_len; - } - - return -ENODATA; -} - #endif /* CONFIG_BT_AUDIO */ #endif /* __AUDIO_H */ diff --git a/subsys/bluetooth/audio/shell/bap.c b/subsys/bluetooth/audio/shell/bap.c index 3e34fe12ec4..bbddb0d3ee6 100644 --- a/subsys/bluetooth/audio/shell/bap.c +++ b/subsys/bluetooth/audio/shell/bap.c @@ -228,34 +228,47 @@ static void fill_audio_buf_sin(int16_t *buf, int length_us, int frequency_hz, in } } -static void init_lc3(const struct bt_bap_stream *stream) +static int init_lc3(const struct bt_bap_stream *stream) { size_t num_samples; + int ret; if (stream == NULL || stream->codec_cfg == NULL) { shell_error(ctx_shell, "invalid stream to init LC3"); - return; + return -EINVAL; + } + + ret = bt_audio_codec_cfg_get_freq(stream->codec_cfg); + if (ret > 0) { + lc3_freq_hz = bt_audio_codec_cfg_freq_to_freq_hz(ret); + } else { + return ret; + } + + ret = bt_audio_codec_cfg_get_frame_dur(stream->codec_cfg); + if (ret > 0) { + lc3_frame_duration_us = bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret); + } else { + return ret; } - lc3_freq_hz = bt_audio_codec_cfg_get_freq(stream->codec_cfg); - lc3_frame_duration_us = bt_audio_codec_cfg_get_frame_duration_us(stream->codec_cfg); lc3_octets_per_frame = bt_audio_codec_cfg_get_octets_per_frame(stream->codec_cfg); lc3_frames_per_sdu = bt_audio_codec_cfg_get_frame_blocks_per_sdu(stream->codec_cfg, true); lc3_octets_per_frame = bt_audio_codec_cfg_get_octets_per_frame(stream->codec_cfg); if (lc3_freq_hz < 0) { printk("Error: Codec frequency not set, cannot start codec."); - return; + return -EINVAL; } if (lc3_frame_duration_us < 0) { printk("Error: Frame duration not set, cannot start codec."); - return; + return -EINVAL; } if (lc3_octets_per_frame < 0) { printk("Error: Octets per frame not set, cannot start codec."); - return; + return -EINVAL; } lc3_frame_duration_100us = lc3_frame_duration_us / 100; @@ -274,7 +287,10 @@ static void init_lc3(const struct bt_bap_stream *stream) if (lc3_encoder == NULL) { printk("ERROR: Failed to setup LC3 encoder - wrong parameters?\n"); + return -EINVAL; } + + return 0; } static void lc3_audio_send_data(struct k_work *work) @@ -1147,7 +1163,7 @@ static int cmd_stream_qos(const struct shell *sh, size_t argc, char *argv[]) { struct bt_audio_codec_qos *qos; unsigned long interval; - int err; + int err = 0; if (default_stream == NULL) { shell_print(sh, "No stream selected"); @@ -1726,7 +1742,7 @@ static void base_recv(struct bt_bap_broadcast_sink *sink, const struct bt_bap_ba shell_print(ctx_shell, "%4sBIS[%d] index 0x%02x", "", i, bis_data->index); bis_indexes[index_count++] = bis_data->index; - if (subgroup->codec_cfg.id == BT_AUDIO_CODEC_LC3_ID) { + if (subgroup->codec_cfg.id == BT_HCI_CODING_FORMAT_LC3) { const int err = bt_audio_data_parse(bis_data->data, bis_data->data_len, print_data_func_cb, NULL); @@ -2052,7 +2068,7 @@ static int cmd_create_broadcast(const struct shell *sh, size_t argc, struct bt_bap_broadcast_source_stream_param stream_params[ARRAY_SIZE(broadcast_source_streams)]; struct bt_bap_broadcast_source_subgroup_param subgroup_param; - struct bt_bap_broadcast_source_create_param create_param = {0}; + struct bt_bap_broadcast_source_param create_param = {0}; const struct named_lc3_preset *named_preset; int err; @@ -2266,7 +2282,7 @@ static int cmd_sync_broadcast(const struct shell *sh, size_t argc, char *argv[]) struct bt_bap_stream *streams[ARRAY_SIZE(broadcast_sink_streams)]; uint32_t bis_bitfield; size_t stream_cnt; - int err; + int err = 0; bis_bitfield = 0; stream_cnt = 0U; @@ -2601,9 +2617,7 @@ static int cmd_send(const struct shell *sh, size_t argc, char *argv[]) #if defined(CONFIG_LIBLC3) static bool stream_start_sine_verify(const struct bt_bap_stream *bap_stream) { - int stream_frame_duration_us; struct bt_bap_ep_info info; - int stream_freq_hz; int err; if (bap_stream == NULL || bap_stream->qos == NULL) { @@ -2619,13 +2633,21 @@ static bool stream_start_sine_verify(const struct bt_bap_stream *bap_stream) return false; } - stream_freq_hz = bt_audio_codec_cfg_get_freq(bap_stream->codec_cfg); - if (stream_freq_hz != lc3_freq_hz) { + err = bt_audio_codec_cfg_get_freq(bap_stream->codec_cfg); + if (err > 0) { + if (bt_audio_codec_cfg_freq_to_freq_hz(err) != lc3_freq_hz) { + return false; + } + } else { return false; } - stream_frame_duration_us = bt_audio_codec_cfg_get_frame_duration_us(bap_stream->codec_cfg); - if (stream_frame_duration_us != lc3_frame_duration_us) { + err = bt_audio_codec_cfg_get_frame_dur(bap_stream->codec_cfg); + if (err > 0) { + if (bt_audio_codec_cfg_frame_dur_to_frame_dur_us(err) != lc3_frame_duration_us) { + return false; + } + } else { return false; } @@ -2671,7 +2693,13 @@ static int cmd_start_sine(const struct shell *sh, size_t argc, char *argv[]) struct bt_bap_stream *bap_stream = &unicast_streams[i].stream.bap_stream; if (!lc3_initialized) { - init_lc3(bap_stream); + err = init_lc3(bap_stream); + if (err != 0) { + shell_error(sh, "Failed to init LC3 %d", err); + + return -ENOEXEC; + } + lc3_initialized = true; } @@ -2694,7 +2722,13 @@ static int cmd_start_sine(const struct shell *sh, size_t argc, char *argv[]) &broadcast_source_streams[i].stream.bap_stream; if (!lc3_initialized) { - init_lc3(bap_stream); + err = init_lc3(bap_stream); + if (err != 0) { + shell_error(sh, "Failed to init LC3 %d", err); + + return -ENOEXEC; + } + lc3_initialized = true; } @@ -2717,7 +2751,12 @@ static int cmd_start_sine(const struct shell *sh, size_t argc, char *argv[]) return -ENOEXEC; } - init_lc3(default_stream); + err = init_lc3(default_stream); + if (err != 0) { + shell_error(sh, "Failed to init LC3 %d", err); + + return -ENOEXEC; + } err = stream_start_sine(default_stream); if (err != 0) { diff --git a/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c b/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c index 76902152dd5..00892ec6187 100644 --- a/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c +++ b/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c @@ -25,6 +25,8 @@ #include "audio.h" #define INVALID_BROADCAST_ID 0xFFFFFFFFU +/* BIS sync is a 32-bit bitfield where BIT(0) is not allowed */ +#define VALID_BIS_SYNC(_bis_sync) ((bis_sync & BIT(0)) == 0U && bis_sync < UINT32_MAX) static struct bt_bap_base received_base; @@ -161,7 +163,7 @@ static void bap_broadcast_assistant_recv_state_cb( } } - if (per_adv_sync) { + if (per_adv_sync && IS_ENABLED(CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER)) { shell_print(ctx_shell, "Sending PAST"); err = bt_le_per_adv_sync_transfer(per_adv_sync, @@ -200,7 +202,8 @@ static void bap_broadcast_assistant_recv_state_cb( } } - if (ext_adv != NULL && IS_ENABLED(CONFIG_BT_PER_ADV)) { + if (ext_adv != NULL && IS_ENABLED(CONFIG_BT_PER_ADV) && + IS_ENABLED(CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER)) { shell_print(ctx_shell, "Sending local PAST"); err = bt_le_per_adv_set_info_transfer(ext_adv, conn, @@ -453,7 +456,7 @@ static int cmd_bap_broadcast_assistant_add_src(const struct shell *sh, return -ENOEXEC; } - if (bis_sync > UINT32_MAX) { + if (!VALID_BIS_SYNC(bis_sync)) { shell_error(sh, "Invalid bis_sync: %lu", bis_sync); return -ENOEXEC; @@ -640,7 +643,7 @@ static int cmd_bap_broadcast_assistant_add_broadcast_id(const struct shell *sh, shell_error(sh, "failed to parse bis_sync: %d", err); return -ENOEXEC; - } else if (bis_sync > UINT32_MAX) { + } else if (!VALID_BIS_SYNC(bis_sync)) { shell_error(sh, "Invalid bis_sync: %lu", bis_sync); return -ENOEXEC; @@ -738,7 +741,7 @@ static int cmd_bap_broadcast_assistant_mod_src(const struct shell *sh, return -ENOEXEC; } - if (bis_sync > UINT32_MAX) { + if (!VALID_BIS_SYNC(bis_sync)) { shell_error(sh, "Invalid bis_sync: %lu", bis_sync); return -ENOEXEC; @@ -779,7 +782,6 @@ static int cmd_bap_broadcast_assistant_mod_src(const struct shell *sh, static int cmd_bap_broadcast_assistant_add_pa_sync(const struct shell *sh, size_t argc, char **argv) { - struct bt_bap_scan_delegator_subgroup subgroup_params[BT_ISO_MAX_GROUP_ISO_COUNT] = { 0 }; struct bt_bap_broadcast_assistant_add_src_param param = { 0 }; /* TODO: Add support to select which PA sync to BIG sync to */ struct bt_le_per_adv_sync *pa_sync = per_adv_syncs[0]; @@ -855,6 +857,9 @@ static int cmd_bap_broadcast_assistant_add_pa_sync(const struct shell *sh, /* The MIN is used to handle `array-bounds` error on some compilers */ param.num_subgroups = MIN(received_base.subgroup_count, BROADCAST_SNK_SUBGROUP_CNT); +#if BROADCAST_SNK_SUBGROUP_CNT > 0 + struct bt_bap_scan_delegator_subgroup subgroup_params[BROADCAST_SNK_SUBGROUP_CNT] = {0}; + param.subgroups = subgroup_params; for (size_t i = 0; i < param.num_subgroups; i++) { struct bt_bap_scan_delegator_subgroup *subgroup_param = &subgroup_params[i]; @@ -873,12 +878,22 @@ static int cmd_bap_broadcast_assistant_add_pa_sync(const struct shell *sh, #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0 metadata_len = subgroup->codec_cfg.meta_len; + if (metadata_len > sizeof(subgroup_param->metadata)) { + shell_error(sh, + "Could not set %zu octets of metadata for subgroup_param of " + "size %zu", + metadata_len, sizeof(subgroup_param->metadata)); + + return -ENOEXEC; + } + memcpy(subgroup_param->metadata, subgroup->codec_cfg.meta, metadata_len); #else metadata_len = 0U; #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0 */ subgroup_param->metadata_len = metadata_len; } +#endif /* BROADCAST_SNK_SUBGROUP_CNT > 0 */ err = bt_bap_broadcast_assistant_add_src(default_conn, ¶m); if (err != 0) { diff --git a/subsys/bluetooth/audio/shell/bap_scan_delegator.c b/subsys/bluetooth/audio/shell/bap_scan_delegator.c index ab4ee9ede0d..9ca494d36ae 100644 --- a/subsys/bluetooth/audio/shell/bap_scan_delegator.c +++ b/subsys/bluetooth/audio/shell/bap_scan_delegator.c @@ -144,6 +144,7 @@ static void pa_timer_handler(struct k_work *work) } } +#if defined(CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER) static int pa_sync_past(struct bt_conn *conn, struct sync_state *state, uint16_t pa_interval) @@ -167,6 +168,7 @@ static int pa_sync_past(struct bt_conn *conn, return err; } +#endif /* CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER */ static int pa_sync_no_past(struct sync_state *state, uint16_t pa_interval) @@ -441,9 +443,11 @@ static int cmd_bap_scan_delegator_sync_pa(const struct shell *sh, size_t argc, return -ENOEXEC; } - if (past_preference && - state->past_avail && - state->conn != NULL) { + if (0) { +#if defined(CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER) + } else if (past_preference && + state->past_avail && + state->conn != NULL) { shell_info(sh, "Syncing with PAST"); err = pa_sync_past(state->conn, state, state->pa_interval); @@ -458,7 +462,7 @@ static int cmd_bap_scan_delegator_sync_pa(const struct shell *sh, size_t argc, return -ENOEXEC; } - +#endif /* CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER */ } else { shell_info(sh, "Syncing without PAST"); err = pa_sync_no_past(state, state->pa_interval); diff --git a/subsys/bluetooth/audio/shell/cap_initiator.c b/subsys/bluetooth/audio/shell/cap_initiator.c index 44c91b7d521..afdd686160c 100644 --- a/subsys/bluetooth/audio/shell/cap_initiator.c +++ b/subsys/bluetooth/audio/shell/cap_initiator.c @@ -573,10 +573,10 @@ static int cap_ac_unicast_start(const struct bap_unicast_ac_param *param, stream_cnt++; if (param->conn_cnt > 1) { - const int err = - codec_set_chan_alloc(stream_param->codec_cfg, BIT(i)); + const int err = bt_audio_codec_cfg_set_chan_allocation( + stream_param->codec_cfg, (enum bt_audio_location)BIT(i)); - if (err != 0) { + if (err < 0) { shell_error(ctx_shell, "Failed to set channel allocation for " "snk[%zu][%zu]: %d", @@ -600,10 +600,10 @@ static int cap_ac_unicast_start(const struct bap_unicast_ac_param *param, stream_cnt++; if (param->conn_cnt > 1) { - const int err = - codec_set_chan_alloc(stream_param->codec_cfg, BIT(i)); + const int err = bt_audio_codec_cfg_set_chan_allocation( + stream_param->codec_cfg, (enum bt_audio_location)BIT(i)); - if (err != 0) { + if (err < 0) { shell_error(ctx_shell, "Failed to set channel allocation for " "src[%zu][%zu]: %d", @@ -1043,7 +1043,7 @@ static int cap_ac_broadcast(const struct shell *sh, size_t argc, char **argv, uint8_t left_data[] = {BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC, BT_AUDIO_LOCATION_FRONT_LEFT)}; struct bt_bap_broadcast_source_subgroup_param subgroup_param = {0}; - struct bt_bap_broadcast_source_create_param create_param = {0}; + struct bt_bap_broadcast_source_param create_param = {0}; const struct named_lc3_preset *named_preset; struct bt_le_ext_adv *adv; int err; diff --git a/subsys/bluetooth/audio/tbs.c b/subsys/bluetooth/audio/tbs.c index d8ef918fcd0..86588c11c71 100644 --- a/subsys/bluetooth/audio/tbs.c +++ b/subsys/bluetooth/audio/tbs.c @@ -9,7 +9,6 @@ #include #include -#include #include #include @@ -308,18 +307,21 @@ static void tbs_set_terminate_reason(struct tbs_service_inst *inst, static uint8_t next_free_call_index(void) { for (int i = 0; i < CONFIG_BT_TBS_MAX_CALLS; i++) { - static uint8_t next_call_index = 1; - const struct bt_tbs_call *call = lookup_call(next_call_index); - - if (call == NULL) { - return next_call_index++; - } + static uint8_t next_call_index; + const struct bt_tbs_call *call; + /* For each new call, the call index should be incremented */ next_call_index++; - if (next_call_index == UINT8_MAX) { + + if (next_call_index == BT_TBS_FREE_CALL_INDEX) { /* call_index = 0 reserved for outgoing calls */ next_call_index = 1; } + + call = lookup_call(next_call_index); + if (call == NULL) { + return next_call_index; + } } LOG_DBG("No more free call spots"); @@ -1753,7 +1755,7 @@ static void signal_interval_timeout(struct k_work *work) } } -static int bt_tbs_init(const struct device *unused) +static int bt_tbs_init(void) { for (size_t i = 0; i < ARRAY_SIZE(svc_insts); i++) { int err; @@ -1798,8 +1800,7 @@ static int bt_tbs_init(const struct device *unused) return 0; } -DEVICE_DEFINE(bt_tbs, "bt_tbs", &bt_tbs_init, NULL, NULL, NULL, - APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, NULL); +SYS_INIT(bt_tbs_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); /***************************** Profile API *****************************/ int bt_tbs_accept(uint8_t call_index) diff --git a/subsys/bluetooth/audio/vcp_internal.h b/subsys/bluetooth/audio/vcp_internal.h index 8a1fec2c0f1..b791b526c1b 100644 --- a/subsys/bluetooth/audio/vcp_internal.h +++ b/subsys/bluetooth/audio/vcp_internal.h @@ -36,4 +36,33 @@ struct vcs_control_vol { uint8_t volume; } __packed; +struct bt_vcp_vol_ctlr { + struct vcs_state state; + uint8_t flags; + + uint16_t start_handle; + uint16_t end_handle; + uint16_t state_handle; + uint16_t control_handle; + uint16_t flag_handle; + struct bt_gatt_subscribe_params state_sub_params; + struct bt_gatt_discover_params state_sub_disc_params; + struct bt_gatt_subscribe_params flag_sub_params; + struct bt_gatt_discover_params flag_sub_disc_params; + bool cp_retried; + + bool busy; + struct vcs_control_vol cp_val; + struct bt_gatt_write_params write_params; + struct bt_gatt_read_params read_params; + struct bt_gatt_discover_params discover_params; + struct bt_uuid_16 uuid; + struct bt_conn *conn; + + uint8_t vocs_inst_cnt; + struct bt_vocs *vocs[CONFIG_BT_VOCS_CLIENT_MAX_INSTANCE_COUNT]; + uint8_t aics_inst_cnt; + struct bt_aics *aics[CONFIG_BT_AICS_CLIENT_MAX_INSTANCE_COUNT]; +}; + #endif /* ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_VCP_INTERNAL_*/ diff --git a/subsys/bluetooth/audio/vcp_vol_ctlr.c b/subsys/bluetooth/audio/vcp_vol_ctlr.c index 825cedff32e..f8033ba99cf 100644 --- a/subsys/bluetooth/audio/vcp_vol_ctlr.c +++ b/subsys/bluetooth/audio/vcp_vol_ctlr.c @@ -28,35 +28,6 @@ LOG_MODULE_REGISTER(bt_vcp_vol_ctlr, CONFIG_BT_VCP_VOL_CTLR_LOG_LEVEL); #include "common/bt_str.h" -struct bt_vcp_vol_ctlr { - struct vcs_state state; - uint8_t flags; - - uint16_t start_handle; - uint16_t end_handle; - uint16_t state_handle; - uint16_t control_handle; - uint16_t flag_handle; - struct bt_gatt_subscribe_params state_sub_params; - struct bt_gatt_discover_params state_sub_disc_params; - struct bt_gatt_subscribe_params flag_sub_params; - struct bt_gatt_discover_params flag_sub_disc_params; - bool cp_retried; - - bool busy; - struct vcs_control_vol cp_val; - struct bt_gatt_write_params write_params; - struct bt_gatt_read_params read_params; - struct bt_gatt_discover_params discover_params; - struct bt_uuid_16 uuid; - struct bt_conn *conn; - - uint8_t vocs_inst_cnt; - struct bt_vocs *vocs[CONFIG_BT_VCP_VOL_CTLR_MAX_VOCS_INST]; - uint8_t aics_inst_cnt; - struct bt_aics *aics[CONFIG_BT_VCP_VOL_CTLR_MAX_AICS_INST]; -}; - /* Callback functions */ static struct bt_vcp_vol_ctlr_cb *vcp_vol_ctlr_cb; diff --git a/subsys/bluetooth/audio/vocs.c b/subsys/bluetooth/audio/vocs.c index 4b9420d36ee..6a03ceb3b70 100644 --- a/subsys/bluetooth/audio/vocs.c +++ b/subsys/bluetooth/audio/vocs.c @@ -19,7 +19,7 @@ #include "audio_internal.h" #include "vocs_internal.h" -#include "zephyr/bluetooth/audio/audio.h" +#include #define LOG_LEVEL CONFIG_BT_VOCS_LOG_LEVEL #include diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 9ba67a05768..077c8e4f6f5 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -210,13 +210,6 @@ config BT_CTLR_ISO_TX_BUFFER_SIZE Size of the Isochronous Tx buffers and the value returned in HCI LE Read Buffer Size V2 command response. -config BT_CTLR_ISOAL_LOG_DBG_VERBOSE - bool "ISO-AL verbose debug logging" - depends on BT_CTLR_ISOAL_LOG_LEVEL = 4 - default n - help - Use this option to enable ISO-AL verbose debug logging. - config BT_CTLR_ISOAL_SOURCES int "Number of Isochronous Adaptation Layer sources" depends on BT_CTLR_ADV_ISO || BT_CTLR_CONN_ISO @@ -248,15 +241,6 @@ config BT_CTLR_ISO_RX_SDU_BUFFERS maximum size of an SDU that can be accurately declared in the HCI ISO Data header. -config BT_CTLR_ISO_TX_SEG_PLAYLOAD_MIN - int "Minimum number of playload data bytes in a new segment" - depends on BT_CTLR_ADV_ISO || BT_CTLR_CONN_ISO - default 1 - range 1 64 - help - Minimum number of payload bytes that would make inserting a new - segment into a PDU worthwhile. - config BT_CTLR_ISO_VENDOR_DATA_PATH bool "Vendor-specific ISO data path" depends on BT_CTLR_SYNC_ISO || BT_CTLR_CONN_ISO @@ -921,17 +905,6 @@ config BT_CTLR_CONN_ISO_STREAMS_MAX_FT help Maximum number of CIS flush timeout events. -config BT_CTLR_CONN_ISO_AVOID_SEGMENTATION - bool "Avoid SDU fragmentation for framed mode" - depends on BT_CTLR_CENTRAL_ISO - help - When creating a CIG, the Max_PDU size is calculated according to BT - Core 5.4 Vol 6, Part G, Section 2.2. However, HAP specifies a need for - avoiding segmentation by forcing the Max_PDU to the appropriate value. - Since there is no way to control the Max_PDU using the non-test - interface, the config provides a way to force the Max_PDU to Max_SDU + - 5 (header + offset). - config BT_CTLR_ISO bool default BT_CTLR_BROADCAST_ISO || BT_CTLR_CONN_ISO diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index e2975107f86..2b9e33ef82d 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -206,6 +206,22 @@ config BT_CTLR_CHECK_SAME_PEER_SYNC endif # BT_CTLR_ADV_EXT +config BT_CTLR_ISOAL_LOG_DBG_VERBOSE + bool "ISO-AL verbose debug logging" + depends on BT_CTLR_ISOAL_LOG_LEVEL = 4 + default n + help + Use this option to enable ISO-AL verbose debug logging. + +config BT_CTLR_ISO_TX_SEG_PLAYLOAD_MIN + int "Minimum number of playload data bytes in a new segment" + depends on BT_CTLR_ADV_ISO || BT_CTLR_CONN_ISO + default 1 + range 1 64 + help + Minimum number of payload bytes that would make inserting a new + segment into a PDU worthwhile. + config BT_CTLR_CONN_ISO_HCI_DATAPATH_SKIP_INVALID_DATA bool "Do not pass invalid SDUs on HCI datapath" depends on BT_CTLR_CONN_ISO @@ -213,6 +229,17 @@ config BT_CTLR_CONN_ISO_HCI_DATAPATH_SKIP_INVALID_DATA This allows for applications to decide whether to forward invalid SDUs through HCI upwards. +config BT_CTLR_CONN_ISO_AVOID_SEGMENTATION + bool "Avoid SDU fragmentation for framed mode" + depends on BT_CTLR_CENTRAL_ISO + help + When creating a CIG, the Max_PDU size is calculated according to BT + Core 5.4 Vol 6, Part G, Section 2.2. However, HAP specifies a need for + avoiding segmentation by forcing the Max_PDU to the appropriate value. + Since there is no way to control the Max_PDU using the non-test + interface, the config provides a way to force the Max_PDU to Max_SDU + + 5 (header + offset). + config BT_CTLR_ADVANCED_FEATURES bool "Show advanced features" help diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index c3dd070720b..fac24c8be4a 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -6959,46 +6959,56 @@ static void le_ext_adv_report(struct pdu_data *pdu_data, ptr = h->data; if (h->adv_addr) { - bt_addr_le_t addr; + /* AdvA is RFU in AUX_CHAIN_IND */ + if (node_rx_curr == node_rx || + node_rx_curr == node_rx->hdr.rx_ftr.extra) { + bt_addr_le_t addr; - adv_addr_type_curr = adv->tx_addr; - adv_addr_curr = ptr; + adv_addr_type_curr = adv->tx_addr; + adv_addr_curr = ptr; - addr.type = adv->tx_addr; - (void)memcpy(addr.a.val, ptr, sizeof(bt_addr_t)); - ptr += BDADDR_SIZE; + addr.type = adv->tx_addr; + (void)memcpy(addr.a.val, ptr, sizeof(bt_addr_t)); + + LOG_DBG(" AdvA: %s", bt_addr_le_str(&addr)); + } - LOG_DBG(" AdvA: %s", bt_addr_le_str(&addr)); + ptr += BDADDR_SIZE; } if (h->tgt_addr) { - struct lll_scan *lll; - bt_addr_le_t addr; + /* TargetA is RFU in AUX_CHAIN_IND */ + if (node_rx_curr == node_rx || + node_rx_curr == node_rx->hdr.rx_ftr.extra) { + struct lll_scan *lll; + bt_addr_le_t addr; - lll = node_rx->hdr.rx_ftr.param; + lll = node_rx->hdr.rx_ftr.param; #if defined(CONFIG_BT_CTLR_EXT_SCAN_FP) - direct_addr_type_curr = - ext_adv_direct_addr_type(lll, - direct_resolved_curr, - direct_report_curr, - adv->rx_addr, ptr); + direct_addr_type_curr = + ext_adv_direct_addr_type(lll, + direct_resolved_curr, + direct_report_curr, + adv->rx_addr, ptr); #else /* !CONFIG_BT_CTLR_EXT_SCAN_FP */ - direct_addr_type_curr = - ext_adv_direct_addr_type(lll, - direct_resolved_curr, - false, adv->rx_addr, - ptr); + direct_addr_type_curr = + ext_adv_direct_addr_type(lll, + direct_resolved_curr, + false, adv->rx_addr, + ptr); #endif /* !CONFIG_BT_CTLR_EXT_SCAN_FP */ - direct_addr_curr = ptr; - ptr += BDADDR_SIZE; + direct_addr_curr = ptr; - addr.type = adv->rx_addr; - (void)memcpy(addr.a.val, direct_addr_curr, - sizeof(bt_addr_t)); + addr.type = adv->rx_addr; + (void)memcpy(addr.a.val, direct_addr_curr, + sizeof(bt_addr_t)); - LOG_DBG(" TgtA: %s", bt_addr_le_str(&addr)); + LOG_DBG(" TgtA: %s", bt_addr_le_str(&addr)); + } + + ptr += BDADDR_SIZE; } if (h->adi) { @@ -7012,34 +7022,42 @@ static void le_ext_adv_report(struct pdu_data *pdu_data, if (h->aux_ptr) { struct pdu_adv_aux_ptr *aux_ptr; - uint8_t aux_phy; - aux_ptr = (void *)ptr; + /* AuxPtr is RFU for connectable or scannable AUX_ADV_IND */ + if (node_rx_curr != node_rx->hdr.rx_ftr.extra || + evt_type_curr == 0U) { + uint8_t aux_phy; - /* Don't report if invalid phy or AUX_ADV_IND was not received - * See BT Core 5.4, Vol 6, Part B, Section 4.4.3.5: - * If the Controller does not listen for or does not receive the - * AUX_ADV_IND PDU, no report shall be generated - */ - if ((node_rx_curr == node_rx && !node_rx_next) || - PDU_ADV_AUX_PTR_PHY_GET(aux_ptr) > EXT_ADV_AUX_PHY_LE_CODED) { - struct node_rx_ftr *ftr; + aux_ptr = (void *)ptr; - ftr = &node_rx->hdr.rx_ftr; - node_rx_extra_list_release(ftr->extra); - return; - } + /* Don't report if invalid phy or AUX_ADV_IND was not received + * See BT Core 5.4, Vol 6, Part B, Section 4.4.3.5: + * If the Controller does not listen for or does not receive the + * AUX_ADV_IND PDU, no report shall be generated + */ + if ((node_rx_curr == node_rx && !node_rx_next) || + PDU_ADV_AUX_PTR_PHY_GET(aux_ptr) > EXT_ADV_AUX_PHY_LE_CODED) { + struct node_rx_ftr *ftr; - ptr += sizeof(*aux_ptr); + ftr = &node_rx->hdr.rx_ftr; + node_rx_extra_list_release(ftr->extra); + return; + } - sec_phy_curr = HCI_AUX_PHY_TO_HCI_PHY(PDU_ADV_AUX_PTR_PHY_GET(aux_ptr)); - aux_phy = BIT(PDU_ADV_AUX_PTR_PHY_GET(aux_ptr)); + sec_phy_curr = HCI_AUX_PHY_TO_HCI_PHY( + PDU_ADV_AUX_PTR_PHY_GET(aux_ptr)); - LOG_DBG(" AuxPtr chan_idx = %u, ca = %u, offs_units " - "= %u offs = 0x%x, phy = 0x%x", - aux_ptr->chan_idx, aux_ptr->ca, - aux_ptr->offs_units, PDU_ADV_AUX_PTR_OFFSET_GET(aux_ptr), aux_phy); + aux_phy = BIT(PDU_ADV_AUX_PTR_PHY_GET(aux_ptr)); + + LOG_DBG(" AuxPtr chan_idx = %u, ca = %u, offs_units " + "= %u offs = 0x%x, phy = 0x%x", + aux_ptr->chan_idx, aux_ptr->ca, + aux_ptr->offs_units, PDU_ADV_AUX_PTR_OFFSET_GET(aux_ptr), + aux_phy); + } + + ptr += sizeof(*aux_ptr); } if (h->sync_info) { @@ -7053,10 +7071,10 @@ static void le_ext_adv_report(struct pdu_data *pdu_data, LOG_DBG(" SyncInfo offs = %u, offs_unit = 0x%x, " "interval = 0x%x, sca = 0x%x, " "chan map = 0x%x 0x%x 0x%x 0x%x 0x%x, " - "AA = 0x%x, CRC = 0x%x 0x%x 0x%x, " + "AA = 0x%x%x%x%x, CRC = 0x%x 0x%x 0x%x, " "evt cntr = 0x%x", - sys_le16_to_cpu(si->offs), - si->offs_units, + PDU_ADV_SYNC_INFO_OFFSET_GET(si), + PDU_ADV_SYNC_INFO_OFFS_UNITS_GET(si), sys_le16_to_cpu(si->interval), ((si->sca_chm[PDU_SYNC_INFO_SCA_CHM_SCA_BYTE_OFFSET] & PDU_SYNC_INFO_SCA_CHM_SCA_BIT_MASK) >> @@ -7065,7 +7083,7 @@ static void le_ext_adv_report(struct pdu_data *pdu_data, si->sca_chm[3], (si->sca_chm[PDU_SYNC_INFO_SCA_CHM_SCA_BYTE_OFFSET] & ~PDU_SYNC_INFO_SCA_CHM_SCA_BIT_MASK), - sys_le32_to_cpu(si->aa), + si->aa[3], si->aa[2], si->aa[1], si->aa[0], si->crc_init[0], si->crc_init[1], si->crc_init[2], sys_le16_to_cpu(si->evt_cntr)); } @@ -7120,9 +7138,10 @@ static void le_ext_adv_report(struct pdu_data *pdu_data, adi = adi_curr; sec_phy = sec_phy_curr; node_rx_data = node_rx_curr; - data_len = data_len_curr; - data_len_total = data_len; - data = data_curr; + /* Adv data in ADV_EXT_IND is RFU */ + data_len = 0U; + data_len_total = 0U; + data = NULL; scan_data_len_total = 0U; tx_pwr = tx_pwr_curr; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c index c6becbe322f..90d75650439 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c @@ -671,9 +671,9 @@ void *radio_pkt_decrypt_get(void) #if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_SYNC_ISO) /* Dedicated Rx PDU Buffer for Control PDU independent of node_rx with BIS Data - * PDU buffer + * PDU buffer. Note this buffer will be used to store whole PDUs, not just the BIG control payload. */ -static uint8_t pkt_big_ctrl[sizeof(struct pdu_big_ctrl)]; +static uint8_t pkt_big_ctrl[offsetof(struct pdu_bis, payload) + sizeof(struct pdu_big_ctrl)]; void *radio_pkt_big_ctrl_get(void) { @@ -1692,20 +1692,25 @@ static void *radio_ccm_ext_rx_pkt_set(struct ccm *cnf, uint8_t phy, uint8_t pdu_ mode |= (CCM_MODE_DATARATE_1Mbit << CCM_MODE_DATARATE_Pos) & CCM_MODE_DATARATE_Msk; + + if (false) { + #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) - /* When direction finding CTE receive feature is enabled then on-the-fly PDU - * parsing for CTEInfo is always done. In such situation, the CCM TASKS_CRYPT - * must be started with short delay. That give the Radio time to store received bits - * in shared memory. - */ - radio_bc_configure(CCM_TASKS_CRYPT_DELAY_BITS); - radio_bc_status_reset(); - hal_trigger_crypt_by_bcmatch_ppi_config(); - hal_radio_nrf_ppi_channels_enable(BIT(HAL_TRIGGER_CRYPT_DELAY_PPI)); -#else - hal_trigger_crypt_ppi_config(); - hal_radio_nrf_ppi_channels_enable(BIT(HAL_TRIGGER_CRYPT_PPI)); + } else if (pdu_type == RADIO_PKT_CONF_PDU_TYPE_DC) { + /* When direction finding CTE receive feature is enabled then on-the-fly + * PDU parsing for CTEInfo is always done. In such situation, the CCM + * TASKS_CRYPT must be started with short delay. That give the Radio time + * to store received bits in shared memory. + */ + radio_bc_configure(CCM_TASKS_CRYPT_DELAY_BITS); + radio_bc_status_reset(); + hal_trigger_crypt_by_bcmatch_ppi_config(); + hal_radio_nrf_ppi_channels_enable(BIT(HAL_TRIGGER_CRYPT_DELAY_PPI)); #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ + } else { + hal_trigger_crypt_ppi_config(); + hal_radio_nrf_ppi_channels_enable(BIT(HAL_TRIGGER_CRYPT_PPI)); + } break; case PHY_2M: diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c index 6fa0204fb56..6b61c3b559f 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c @@ -49,6 +49,9 @@ static int init_reset(void); static int prepare_cb(struct lll_prepare_param *p); +#if !defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO) +static void isr_early_abort(void *param); +#endif /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */ static void isr_done(void *param); #if defined(CONFIG_BT_CTLR_ADV_AUX_PDU_BACK2BACK) static void isr_tx_chain(void *param); @@ -188,7 +191,7 @@ static int prepare_cb(struct lll_prepare_param *p) /* Abort if no aux_ptr filled */ if (unlikely(!pri_hdr->aux_ptr || !PDU_ADV_AUX_PTR_OFFSET_GET(aux_ptr))) { - radio_isr_set(lll_isr_early_abort, lll); + radio_isr_set(isr_early_abort, lll); radio_disable(); return 0; @@ -325,7 +328,7 @@ static int prepare_cb(struct lll_prepare_param *p) if (overhead) { LL_ASSERT_OVERHEAD(overhead); - radio_isr_set(lll_isr_abort, lll); + radio_isr_set(isr_done, lll); radio_disable(); return -ECANCELED; @@ -347,6 +350,33 @@ static int prepare_cb(struct lll_prepare_param *p) return 0; } +#if !defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO) +static void isr_race(void *param) +{ + radio_status_reset(); +} + +static void isr_early_abort(void *param) +{ + struct event_done_extra *extra; + int err; + + /* Generate auxiliary radio event done */ + extra = ull_done_extra_type_set(EVENT_DONE_EXTRA_TYPE_ADV_AUX); + LL_ASSERT(extra); + + radio_isr_set(isr_race, param); + if (!radio_is_idle()) { + radio_disable(); + } + + err = lll_hfclock_off(); + LL_ASSERT(err >= 0); + + lll_done(NULL); +} +#endif /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */ + static void isr_done(void *param) { struct event_done_extra *extra; diff --git a/subsys/bluetooth/controller/ll_sw/pdu.h b/subsys/bluetooth/controller/ll_sw/pdu.h index 93e50e1ebcc..fe6fa8494f5 100644 --- a/subsys/bluetooth/controller/ll_sw/pdu.h +++ b/subsys/bluetooth/controller/ll_sw/pdu.h @@ -225,6 +225,19 @@ (((aux_ptr)->offs_phy_packed[1] & 0x1F) << 8)) #define PDU_ADV_AUX_PTR_PHY_GET(aux_ptr) (((aux_ptr)->offs_phy_packed[1] >> 5) & 0x07) +/* Macros for getting/setting offset/offset_units/offset_adjust from pdu_adv_sync_info */ +#define PDU_ADV_SYNC_INFO_OFFSET_GET(si) ((si)->offs_packed[0] | \ + (((si)->offs_packed[1] & 0x1F) << 8)) +#define PDU_ADV_SYNC_INFO_OFFS_UNITS_GET(si) (((si)->offs_packed[1] >> 5) & 0x01) +#define PDU_ADV_SYNC_INFO_OFFS_ADJUST_GET(si) (((si)->offs_packed[1] >> 6) & 0x01) +#define PDU_ADV_SYNC_INFO_OFFS_SET(si, offs, offs_units, offs_adjust) \ + do { \ + (si)->offs_packed[0] = (offs) & 0xFF; \ + (si)->offs_packed[1] = (((offs) >> 8) & 0x1F) + \ + (((offs_units) << 5) & 0x20) + \ + (((offs_adjust) << 6) & 0x40); \ + } while (0) + /* Advertiser's Sleep Clock Accuracy Value */ #define SCA_500_PPM 500 /* 51 ppm to 500 ppm */ #define SCA_50_PPM 50 /* 0 ppm to 50 ppm */ @@ -488,20 +501,17 @@ enum pdu_adv_aux_phy { }; struct pdu_adv_sync_info { -#ifdef CONFIG_LITTLE_ENDIAN - uint16_t offs:13; - uint16_t offs_units:1; - uint16_t offs_adjust:1; - uint16_t rfu:1; -#else - uint16_t rfu:1; - uint16_t offs_adjust:1; - uint16_t offs_units:1; - uint16_t offs:13; -#endif /* CONFIG_LITTLE_ENDIAN */ + /* offs:13 + * offs_units:1 + * offs_adjust:1 + * rfu:1 + * NOTE: This layout as bitfields is not portable for BE using + * endianness conversion macros. + */ + uint8_t offs_packed[2]; uint16_t interval; uint8_t sca_chm[PDU_CHANNEL_MAP_SIZE]; - uint32_t aa; + uint8_t aa[4]; uint8_t crc_init[3]; uint16_t evt_cntr; } __packed; diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c b/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c index f1f521ca235..5fec8a37534 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c @@ -1348,9 +1348,7 @@ void ull_adv_sync_info_fill(struct ll_adv_sync_set *sync, * If sync_info is part of ADV PDU the offs_adjust field * is always set to 0. */ - si->offs_units = OFFS_UNIT_VALUE_30_US; - si->offs_adjust = 0U; - si->offs = 0U; + PDU_ADV_SYNC_INFO_OFFS_SET(si, 0U, OFFS_UNIT_VALUE_30_US, 0U); /* Fill the interval, access address and CRC init */ si->interval = sys_cpu_to_le16(sync->interval); @@ -2207,18 +2205,19 @@ void ull_adv_sync_lll_syncinfo_fill(struct pdu_adv *pdu, struct lll_adv_aux *lll static void sync_info_offset_fill(struct pdu_adv_sync_info *si, uint32_t offs) { + uint8_t offs_adjust = 0U; + if (offs >= OFFS_ADJUST_US) { offs -= OFFS_ADJUST_US; - si->offs_adjust = 1U; + offs_adjust = 1U; } offs = offs / OFFS_UNIT_30_US; if (!!(offs >> OFFS_UNIT_BITS)) { - si->offs = sys_cpu_to_le16(offs / (OFFS_UNIT_300_US / OFFS_UNIT_30_US)); - si->offs_units = OFFS_UNIT_VALUE_300_US; + PDU_ADV_SYNC_INFO_OFFS_SET(si, offs / (OFFS_UNIT_300_US / OFFS_UNIT_30_US), + OFFS_UNIT_VALUE_300_US, offs_adjust); } else { - si->offs = sys_cpu_to_le16(offs); - si->offs_units = OFFS_UNIT_VALUE_30_US; + PDU_ADV_SYNC_INFO_OFFS_SET(si, offs, OFFS_UNIT_VALUE_30_US, offs_adjust); } } @@ -2328,22 +2327,22 @@ static void sync_info_offset_fill(struct pdu_adv_sync_info *si, uint32_t remainder_us, uint32_t start_us) { + uint8_t offs_adjust = 0U; uint32_t offs; offs = HAL_TICKER_TICKS_TO_US(ticks_offset) + remainder_us - start_us; if (offs >= OFFS_ADJUST_US) { offs -= OFFS_ADJUST_US; - si->offs_adjust = 1U; + offs_adjust = 1U; } offs = offs / OFFS_UNIT_30_US; if (!!(offs >> OFFS_UNIT_BITS)) { - si->offs = sys_cpu_to_le16(offs / (OFFS_UNIT_300_US / OFFS_UNIT_30_US)); - si->offs_units = OFFS_UNIT_VALUE_300_US; + PDU_ADV_SYNC_INFO_OFFS_SET(si, offs / (OFFS_UNIT_300_US / OFFS_UNIT_30_US), + OFFS_UNIT_VALUE_300_US, offs_adjust); } else { - si->offs = sys_cpu_to_le16(offs); - si->offs_units = OFFS_UNIT_VALUE_30_US; + PDU_ADV_SYNC_INFO_OFFS_SET(si, offs, OFFS_UNIT_VALUE_30_US, offs_adjust); } } diff --git a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c index 474b8d0dbe9..b0eac97a80c 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c @@ -147,7 +147,6 @@ uint8_t ll_cis_parameters_set(uint8_t cis_id, } /* TODO: - * - Drop retransmissions to stay within Max_Transmission_Latency instead of asserting * - Calculate ISO_Interval to allow SDU_Interval < ISO_Interval */ uint8_t ll_cig_parameters_commit(uint8_t cig_id, uint16_t *handles) @@ -311,6 +310,8 @@ uint8_t ll_cig_parameters_commit(uint8_t cig_id, uint16_t *handles) } num_cis = cig->lll.num_cis; + +ll_cig_parameters_commit_retry: handle_iter = UINT16_MAX; /* 1) Acquire CIS instances and initialize instance data. @@ -520,8 +521,29 @@ uint8_t ll_cig_parameters_commit(uint8_t cig_id, uint16_t *handles) if (!cig->central.test) { /* Make sure specified Max_Transport_Latency is not exceeded */ - LL_ASSERT(c_latency <= cig->c_latency); - LL_ASSERT(p_latency <= cig->p_latency); + if ((c_latency > cig->c_latency) || (p_latency > cig->p_latency)) { + /* Check if we can reduce RTN to meet requested latency */ + if (!cis->central.c_rtn && !cis->central.p_rtn) { + /* Actual latency exceeds the Max. Transport Latency */ + err = BT_HCI_ERR_INVALID_PARAM; + + /* Release allocated resources and exit */ + goto ll_cig_parameters_commit_cleanup; + } + + /* Reduce the RTN to meet host requested latency. + * NOTE: Both central and peripheral retransmission is reduced for + * simplicity. + */ + if (cis->central.c_rtn) { + cis->central.c_rtn--; + } + if (cis->central.p_rtn) { + cis->central.p_rtn--; + } + + goto ll_cig_parameters_commit_retry; + } } c_max_latency = MAX(c_max_latency, c_latency); diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index 1640c00e87e..193483b6379 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -273,6 +273,9 @@ int ll_tx_mem_enqueue(uint16_t handle, void *tx) pdu = (void *)((struct node_tx *)tx)->pdu; tx_len += pdu->len; + if (delta == 0) { /* Let's avoid a division by 0 if we happen to have a really fast HCI IF*/ + delta = 1; + } tx_rate = ((uint64_t)tx_len << 3) * BT_CTLR_THROUGHPUT_PERIOD / delta; tx_cnt++; #endif /* CONFIG_BT_CTLR_THROUGHPUT */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index ecdfdd60d07..9a86a473b02 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -646,8 +646,8 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) window_widening_us = SCA_DRIFT_500_PPM_US(aux_offset_us); } - lll_aux->window_size_us += (EVENT_TICKER_RES_MARGIN_US + - ((EVENT_JITTER_US + window_widening_us) << 1)); + lll_aux->window_size_us += ((EVENT_TICKER_RES_MARGIN_US + EVENT_JITTER_US + + window_widening_us) << 1); ready_delay_us = lll_radio_rx_ready_delay_get(lll_aux->phy, PHY_FLAGS_S8); diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync.c b/subsys/bluetooth/controller/ll_sw/ull_sync.c index 265475196fd..18ec492621c 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync.c @@ -711,10 +711,10 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux, * CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT */ - memcpy(lll->access_addr, &si->aa, sizeof(lll->access_addr)); + memcpy(lll->access_addr, si->aa, sizeof(lll->access_addr)); lll->data_chan_id = lll_chan_id(lll->access_addr); memcpy(lll->crc_init, si->crc_init, sizeof(lll->crc_init)); - lll->event_counter = si->evt_cntr; + lll->event_counter = sys_le16_to_cpu(si->evt_cntr); lll->phy = aux->lll.phy; interval = sys_le16_to_cpu(si->interval); @@ -762,7 +762,7 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux, lll_clock_ppm_get(sca)) * interval_us), USEC_PER_SEC); lll->window_widening_max_us = (interval_us >> 1) - EVENT_IFS_US; - if (si->offs_units) { + if (PDU_ADV_SYNC_INFO_OFFS_UNITS_GET(si)) { lll->window_size_event_us = OFFS_UNIT_300_US; } else { lll->window_size_event_us = OFFS_UNIT_30_US; @@ -809,10 +809,10 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux, ready_delay_us = lll_radio_rx_ready_delay_get(lll->phy, 1); sync_offset_us = ftr->radio_end_us; - sync_offset_us += (uint32_t)sys_le16_to_cpu(si->offs) * + sync_offset_us += PDU_ADV_SYNC_INFO_OFFSET_GET(si) * lll->window_size_event_us; /* offs_adjust may be 1 only if sync setup by LL_PERIODIC_SYNC_IND */ - sync_offset_us += (si->offs_adjust ? OFFS_ADJUST_US : 0U); + sync_offset_us += (PDU_ADV_SYNC_INFO_OFFS_ADJUST_GET(si) ? OFFS_ADJUST_US : 0U); sync_offset_us -= PDU_AC_US(pdu->len, lll->phy, ftr->phy_flags); sync_offset_us -= EVENT_TICKER_RES_MARGIN_US; sync_offset_us -= EVENT_JITTER_US; diff --git a/subsys/bluetooth/host/CMakeLists.txt b/subsys/bluetooth/host/CMakeLists.txt index a9810c8af32..e5ac8c707e0 100644 --- a/subsys/bluetooth/host/CMakeLists.txt +++ b/subsys/bluetooth/host/CMakeLists.txt @@ -123,3 +123,10 @@ if(CONFIG_BT_CONN_DISABLE_SECURITY) Do not use in production." ) endif() + +# Bluetooth Mesh has test dependencies in the host. +# In order to compile Bsim tests with these test features +# and PSA enabled, the libraries must be linked. +if(CONFIG_BT_MESH AND CONFIG_BT_TESTING) + zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS) +endif() diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index 2e740686b69..c5c73be39a2 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -76,7 +76,7 @@ config BT_HCI_RESERVE int default 0 if BT_H4 default 1 if BT_H5 - default 1 if BT_RPMSG + default 1 if BT_HCI_IPC default 1 if BT_SPI default 1 if BT_STM32_IPM default 1 if BT_USERCHAN @@ -205,6 +205,9 @@ config BT_SETTINGS which case it's more efficient to load all settings in one go, instead of each subsystem doing it independently. + Warning: The Bluetooth host expects a settings backend that loads + settings items in handle order. + if BT_SETTINGS config BT_SETTINGS_CCC_LAZY_LOADING bool "Load CCC values from settings when peer connects" @@ -466,6 +469,18 @@ config BT_RPA_TIMEOUT_DYNAMIC This option allows the user to override the default value of the Resolvable Private Address timeout using dedicated APIs. +config BT_RPA_SHARING + bool "Share the Resolvable Private Address between advertising sets" + depends on BT_PRIVACY && BT_EXT_ADV + help + This option configures the advertising sets linked with the same + Bluetooth identity to use the same Resolvable Private Address in + a given rotation period. After the RPA timeout, the new RPA is + generated and shared between the advertising sets in the subsequent + rotation period. When this option is disabled, the generated RPAs + of the advertising sets differ from each other in a given rotation + period. + config BT_SIGNING bool "Data signing support" help diff --git a/subsys/bluetooth/host/Kconfig.gatt b/subsys/bluetooth/host/Kconfig.gatt index e405a56d147..9209368f943 100644 --- a/subsys/bluetooth/host/Kconfig.gatt +++ b/subsys/bluetooth/host/Kconfig.gatt @@ -7,7 +7,7 @@ menu "ATT and GATT Options" config BT_ATT_ENFORCE_FLOW bool "Enforce strict flow control semantics for incoming PDUs" - default y if !(BOARD_QEMU_CORTEX_M3 || BOARD_QEMU_X86 || ARCH_POSIX) + default y if !(BOARD_QEMU_CORTEX_M3 || BOARD_QEMU_X86 || ARCH_POSIX || BT_SPI_BLUENRG) help Enforce flow control rules on incoming PDUs, preventing a peer from sending new requests until a previous one has been responded diff --git a/subsys/bluetooth/host/att.c b/subsys/bluetooth/host/att.c index f5ae3768cec..130b4ab0853 100644 --- a/subsys/bluetooth/host/att.c +++ b/subsys/bluetooth/host/att.c @@ -83,18 +83,6 @@ enum { ATT_NUM_FLAGS, }; -struct bt_att_tx_meta_data { - struct bt_att_chan *att_chan; - uint16_t attr_count; - bt_gatt_complete_func_t func; - void *user_data; - enum bt_att_chan_opt chan_opt; -}; - -struct bt_att_tx_meta { - struct bt_att_tx_meta_data *data; -}; - /* ATT channel specific data */ struct bt_att_chan { /* Connection this channel is associated with */ @@ -103,8 +91,6 @@ struct bt_att_chan { ATOMIC_DEFINE(flags, ATT_NUM_FLAGS); struct bt_att_req *req; struct k_fifo tx_queue; - struct net_buf *rsp_buf; - struct bt_att_tx_meta_data rsp_meta; struct k_work_delayable timeout_work; sys_snode_t node; }; @@ -173,6 +159,18 @@ static struct bt_att_req cancel; */ static k_tid_t att_handle_rsp_thread; +struct bt_att_tx_meta_data { + struct bt_att_chan *att_chan; + uint16_t attr_count; + bt_gatt_complete_func_t func; + void *user_data; + enum bt_att_chan_opt chan_opt; +}; + +struct bt_att_tx_meta { + struct bt_att_tx_meta_data *data; +}; + #define bt_att_tx_meta_data(buf) (((struct bt_att_tx_meta *)net_buf_user_data(buf))->data) static struct bt_att_tx_meta_data tx_meta_data[CONFIG_BT_CONN_TX_MAX]; @@ -194,22 +192,9 @@ static struct bt_att_tx_meta_data *tx_meta_data_alloc(k_timeout_t timeout) static inline void tx_meta_data_free(struct bt_att_tx_meta_data *data) { __ASSERT_NO_MSG(data); - bool alloc_from_global = PART_OF_ARRAY(tx_meta_data, data); - - if (data == &data->att_chan->rsp_meta) { - /* "Free-ness" is kept by remote: There can only ever be one - * transaction per-bearer. - */ - __ASSERT_NO_MSG(!alloc_from_global); - } else { - __ASSERT_NO_MSG(alloc_from_global); - } (void)memset(data, 0, sizeof(*data)); - - if (alloc_from_global) { - k_fifo_put(&free_att_tx_meta_data, data); - } + k_fifo_put(&free_att_tx_meta_data, data); } static int bt_att_chan_send(struct bt_att_chan *chan, struct net_buf *buf); @@ -447,12 +432,19 @@ static int chan_req_send(struct bt_att_chan *chan, struct bt_att_req *req) buf = req->buf; req->buf = NULL; + /* This lock makes sure the value of `bt_att_mtu(chan)` does not + * change. + */ + k_sched_lock(); err = bt_att_chan_send(chan, buf); if (err) { /* We still have the ownership of the buffer */ req->buf = buf; chan->req = NULL; + } else { + bt_gatt_req_set_mtu(req, bt_att_mtu(chan)); } + k_sched_unlock(); return err; } @@ -660,7 +652,6 @@ static struct net_buf *bt_att_chan_create_pdu(struct bt_att_chan *chan, uint8_t struct net_buf *buf; struct bt_att_tx_meta_data *data; k_timeout_t timeout; - bool re_use = false; if (len + sizeof(op) > bt_att_mtu(chan)) { LOG_WRN("ATT MTU exceeded, max %u, wanted %zu", bt_att_mtu(chan), @@ -670,71 +661,25 @@ static struct net_buf *bt_att_chan_create_pdu(struct bt_att_chan *chan, uint8_t switch (att_op_get_type(op)) { case ATT_RESPONSE: - /* Use a timeout only when responding */ - timeout = BT_ATT_TIMEOUT; - re_use = true; - break; case ATT_CONFIRMATION: + /* Use a timeout only when responding/confirming */ timeout = BT_ATT_TIMEOUT; break; default: timeout = K_FOREVER; } - if (IS_ENABLED(CONFIG_BT_GATT_READ_MULTIPLE) && - (op == BT_ATT_OP_READ_MULT_RSP || - op == BT_ATT_OP_READ_MULT_VL_RSP)) { - /* We can't re-use the REQ buffer (see below) for these two - * opcodes, as the handler will read from it _after_ allocating - * the RSP buffer. - */ - re_use = false; + buf = bt_l2cap_create_pdu_timeout(NULL, 0, timeout); + if (!buf) { + LOG_ERR("Unable to allocate buffer for op 0x%02x", op); + return NULL; } - if (re_use) { - /* There can only ever be one transaction at a time on a - * bearer/channel. Use a dedicated channel meta-data to ensure - * we can always queue an (error) RSP for each REQ. The ATT - * module can then reschedule the RSP if it is not able to send - * it immediately. - */ - if (chan->rsp_meta.att_chan) { - /* Returning a NULL here will trigger an ATT timeout. - * This is better than an assert as an assert would - * allow a peer to DoS us. - */ - LOG_ERR("already processing a REQ/RSP on chan %p", chan); - - return NULL; - } - data = &chan->rsp_meta; - - /* Re-use REQ buf to avoid dropping the REQ and timing out. - * This only works if the bearer used to RX REQs is the same as - * for sending the RSP. That should always be the case - * (per-spec). - */ - __ASSERT_NO_MSG(chan->rsp_buf); - buf = net_buf_ref(chan->rsp_buf); - - net_buf_reset(buf); - net_buf_reserve(buf, BT_L2CAP_BUF_SIZE(0)); - - LOG_DBG("re-using REQ buf %p for RSP", buf); - } else { - LOG_DBG("alloc buf & meta from global pools"); - buf = bt_l2cap_create_pdu_timeout(NULL, 0, timeout); - if (!buf) { - LOG_ERR("Unable to allocate buffer for op 0x%02x", op); - return NULL; - } - - data = tx_meta_data_alloc(timeout); - if (!data) { - LOG_WRN("Unable to allocate ATT TX meta"); - net_buf_unref(buf); - return NULL; - } + data = tx_meta_data_alloc(timeout); + if (!data) { + LOG_WRN("Unable to allocate ATT TX meta"); + net_buf_unref(buf); + return NULL; } if (IS_ENABLED(CONFIG_BT_EATT)) { @@ -812,7 +757,6 @@ static void send_err_rsp(struct bt_att_chan *chan, uint8_t req, uint16_t handle, buf = bt_att_chan_create_pdu(chan, BT_ATT_OP_ERROR_RSP, sizeof(*rsp)); if (!buf) { - LOG_ERR("unable to allocate buf for error response"); return; } @@ -2512,9 +2456,13 @@ static uint8_t att_error_rsp(struct bt_att_chan *chan, struct net_buf *buf) } err = rsp->error; + #if defined(CONFIG_BT_ATT_RETRY_ON_SEC_ERR) + int ret; + /* Check if error can be handled by elevating security. */ - if (!att_change_security(chan->chan.chan.conn, err)) { + ret = att_change_security(chan->chan.chan.conn, err); + if (ret == 0 || ret == -EBUSY) { /* ATT timeout work is normally cancelled in att_handle_rsp. * However retrying is special case, so the timeout shall * be cancelled here. @@ -2867,9 +2815,15 @@ static att_type_t att_op_get_type(uint8_t op) return ATT_UNKNOWN; } +static struct bt_conn *get_conn(struct bt_att_chan *att_chan) +{ + return att_chan->chan.chan.conn; +} + static int bt_att_recv(struct bt_l2cap_chan *chan, struct net_buf *buf) { struct bt_att_chan *att_chan = ATT_CHAN(chan); + struct bt_conn *conn = get_conn(att_chan); struct bt_att_hdr *hdr; const struct att_handler *handler; uint8_t err; @@ -2884,6 +2838,11 @@ static int bt_att_recv(struct bt_l2cap_chan *chan, struct net_buf *buf) LOG_DBG("Received ATT chan %p code 0x%02x len %zu", att_chan, hdr->code, net_buf_frags_len(buf)); + if (conn->state != BT_CONN_CONNECTED) { + LOG_DBG("not connected: conn %p state %u", conn, conn->state); + return 0; + } + if (!att_chan->att) { LOG_DBG("Ignore recv on detached ATT chan"); return 0; @@ -2896,20 +2855,6 @@ static int bt_att_recv(struct bt_l2cap_chan *chan, struct net_buf *buf) } } - /* Thread-local variable, shouldn't be used by anything else */ - __ASSERT_NO_MSG(!att_chan->rsp_buf); - - /* Mark buffer free for re-use by the opcode handler. - * - * This allows ATT to always be able to send a RSP (or err RSP) - * to the peer, regardless of the TX buffer usage by other stack - * users (e.g. GATT notifications, L2CAP using global pool, SMP, - * etc..), avoiding an ATT timeout due to resource usage. - * - * The ref is taken by `bt_att_chan_create_pdu`. - */ - att_chan->rsp_buf = net_buf_ref(buf); - if (!handler) { LOG_WRN("Unhandled ATT code 0x%02x", hdr->code); if (att_op_get_type(hdr->code) != ATT_COMMAND && @@ -2917,19 +2862,19 @@ static int bt_att_recv(struct bt_l2cap_chan *chan, struct net_buf *buf) send_err_rsp(att_chan, hdr->code, 0, BT_ATT_ERR_NOT_SUPPORTED); } - goto exit; + return 0; } if (IS_ENABLED(CONFIG_BT_ATT_ENFORCE_FLOW)) { if (handler->type == ATT_REQUEST && atomic_test_and_set_bit(att_chan->flags, ATT_PENDING_RSP)) { LOG_WRN("Ignoring unexpected request"); - goto exit; + return 0; } else if (handler->type == ATT_INDICATION && atomic_test_and_set_bit(att_chan->flags, ATT_PENDING_CFM)) { LOG_WRN("Ignoring unexpected indication"); - goto exit; + return 0; } } @@ -2945,10 +2890,6 @@ static int bt_att_recv(struct bt_l2cap_chan *chan, struct net_buf *buf) send_err_rsp(att_chan, hdr->code, 0, err); } -exit: - net_buf_unref(att_chan->rsp_buf); - att_chan->rsp_buf = NULL; - return 0; } @@ -3725,7 +3666,8 @@ int bt_eatt_reconfigure(struct bt_conn *conn, uint16_t mtu) #endif /* CONFIG_BT_TESTING */ #endif /* CONFIG_BT_EATT */ -static int bt_eatt_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan) +static int bt_eatt_accept(struct bt_conn *conn, struct bt_l2cap_server *server, + struct bt_l2cap_chan **chan) { struct bt_att_chan *att_chan = att_get_fixed_chan(conn); struct bt_att *att = att_chan->att; diff --git a/subsys/bluetooth/host/att_internal.h b/subsys/bluetooth/host/att_internal.h index 2910c018e85..a45184a59c7 100644 --- a/subsys/bluetooth/host/att_internal.h +++ b/subsys/bluetooth/host/att_internal.h @@ -347,3 +347,5 @@ bool bt_att_tx_meta_data_match(const struct net_buf *buf, bt_gatt_complete_func_ #endif /* CONFIG_BT_EATT */ bool bt_att_chan_opt_valid(struct bt_conn *conn, enum bt_att_chan_opt chan_opt); + +void bt_gatt_req_set_mtu(struct bt_att_req *req, uint16_t mtu); diff --git a/subsys/bluetooth/host/avdtp.c b/subsys/bluetooth/host/avdtp.c index ce4854507be..62409937514 100644 --- a/subsys/bluetooth/host/avdtp.c +++ b/subsys/bluetooth/host/avdtp.c @@ -220,7 +220,8 @@ int bt_avdtp_disconnect(struct bt_avdtp *session) return bt_l2cap_chan_disconnect(&session->br_chan.chan); } -int bt_avdtp_l2cap_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan) +int bt_avdtp_l2cap_accept(struct bt_conn *conn, struct bt_l2cap_server *server, + struct bt_l2cap_chan **chan) { struct bt_avdtp *session = NULL; int result; diff --git a/subsys/bluetooth/host/buf.c b/subsys/bluetooth/host/buf.c index ff9620766fe..50b567d31b7 100644 --- a/subsys/bluetooth/host/buf.c +++ b/subsys/bluetooth/host/buf.c @@ -43,15 +43,14 @@ NET_BUF_POOL_FIXED_DEFINE(discardable_pool, CONFIG_BT_BUF_EVT_DISCARDABLE_COUNT, #if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) NET_BUF_POOL_DEFINE(acl_in_pool, CONFIG_BT_BUF_ACL_RX_COUNT, BT_BUF_ACL_SIZE(CONFIG_BT_BUF_ACL_RX_SIZE), - MAX(sizeof(struct bt_buf_data), CONFIG_BT_CONN_TX_USER_DATA_SIZE), - bt_hci_host_num_completed_packets); + sizeof(struct acl_data), bt_hci_host_num_completed_packets); NET_BUF_POOL_FIXED_DEFINE(evt_pool, CONFIG_BT_BUF_EVT_RX_COUNT, BT_BUF_EVT_RX_SIZE, 8, NULL); #else NET_BUF_POOL_FIXED_DEFINE(hci_rx_pool, BT_BUF_RX_COUNT, - BT_BUF_RX_SIZE, CONFIG_BT_CONN_TX_USER_DATA_SIZE, + BT_BUF_RX_SIZE, 8, NULL); #endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */ diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 0e355c36390..06a3e7553a2 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -28,6 +28,7 @@ #include #include "common/assert.h" +#include "common/bt_str.h" #include "addr_internal.h" #include "hci_core.h" @@ -578,7 +579,7 @@ static inline uint16_t conn_mtu(struct bt_conn *conn) static int do_send_frag(struct bt_conn *conn, struct net_buf *buf, uint8_t flags) { struct bt_conn_tx *tx = tx_data(buf)->tx; - uint32_t *pending_no_cb; + uint32_t *pending_no_cb = NULL; unsigned int key; int err = 0; @@ -2284,12 +2285,16 @@ static int start_security(struct bt_conn *conn) int bt_conn_set_security(struct bt_conn *conn, bt_security_t sec) { + bool force_pair; int err; if (conn->state != BT_CONN_CONNECTED) { return -ENOTCONN; } + force_pair = sec & BT_SECURITY_FORCE_PAIR; + sec &= ~BT_SECURITY_FORCE_PAIR; + if (IS_ENABLED(CONFIG_BT_SMP_SC_ONLY)) { sec = BT_SECURITY_L4; } @@ -2299,13 +2304,12 @@ int bt_conn_set_security(struct bt_conn *conn, bt_security_t sec) } /* nothing to do */ - if (conn->sec_level >= sec || conn->required_sec_level >= sec) { + if (!force_pair && (conn->sec_level >= sec || conn->required_sec_level >= sec)) { return 0; } - atomic_set_bit_to(conn->flags, BT_CONN_FORCE_PAIR, - sec & BT_SECURITY_FORCE_PAIR); - conn->required_sec_level = sec & ~BT_SECURITY_FORCE_PAIR; + atomic_set_bit_to(conn->flags, BT_CONN_FORCE_PAIR, force_pair); + conn->required_sec_level = sec; err = start_security(conn); @@ -2346,7 +2350,8 @@ bool bt_conn_exists_le(uint8_t id, const bt_addr_le_t *peer) * still has valid references. The last reference of the stack * is released after the disconnected callback. */ - LOG_WRN("Found valid connection in %s state", state2str(conn->state)); + LOG_WRN("Found valid connection (%p) with address %s in %s state ", conn, + bt_addr_le_str(peer), state2str(conn->state)); bt_conn_unref(conn); return true; } diff --git a/subsys/bluetooth/host/conn_internal.h b/subsys/bluetooth/host/conn_internal.h index a2d8e28bd4d..a13adff704a 100644 --- a/subsys/bluetooth/host/conn_internal.h +++ b/subsys/bluetooth/host/conn_internal.h @@ -12,15 +12,15 @@ #include typedef enum __packed { - BT_CONN_DISCONNECTED, - BT_CONN_DISCONNECT_COMPLETE, - BT_CONN_CONNECTING_SCAN, - BT_CONN_CONNECTING_AUTO, - BT_CONN_CONNECTING_ADV, - BT_CONN_CONNECTING_DIR_ADV, - BT_CONN_CONNECTING, - BT_CONN_CONNECTED, - BT_CONN_DISCONNECTING, + BT_CONN_DISCONNECTED, /* Disconnected, conn is completely down */ + BT_CONN_DISCONNECT_COMPLETE, /* Received disconn comp event, transition to DISCONNECTED */ + BT_CONN_CONNECTING_SCAN, /* Central passive scanning */ + BT_CONN_CONNECTING_AUTO, /* Central connection establishment w/ filter */ + BT_CONN_CONNECTING_ADV, /* Peripheral connectable advertising */ + BT_CONN_CONNECTING_DIR_ADV, /* Peripheral directed advertising */ + BT_CONN_CONNECTING, /* Central connection establishment */ + BT_CONN_CONNECTED, /* Peripheral or Central connected */ + BT_CONN_DISCONNECTING, /* Peripheral or Central issued disconnection command */ } bt_conn_state_t; /* bt_conn flags: the flags defined here represent connection parameters */ @@ -146,6 +146,17 @@ struct bt_conn_tx { uint32_t pending_no_cb; }; +struct acl_data { + /* Extend the bt_buf user data */ + struct bt_buf_data buf_data; + + /* Index into the bt_conn storage array */ + uint8_t index; + + /** ACL connection handle */ + uint16_t handle; +}; + struct bt_conn { uint16_t handle; enum bt_conn_type type; diff --git a/subsys/bluetooth/host/gatt.c b/subsys/bluetooth/host/gatt.c index 93dfe555580..103229ea245 100644 --- a/subsys/bluetooth/host/gatt.c +++ b/subsys/bluetooth/host/gatt.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2015-2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -79,7 +80,7 @@ struct gatt_sub { * <=> (subscriptions[x].peer == BT_ADDR_LE_ANY). */ static struct gatt_sub subscriptions[SUB_MAX]; -static sys_slist_t callback_list; +static sys_slist_t callback_list = SYS_SLIST_STATIC_INIT(&callback_list); #if defined(CONFIG_BT_GATT_DYNAMIC_DB) static sys_slist_t db; @@ -853,9 +854,7 @@ static void db_hash_gen(void) atomic_set_bit(gatt_sc.flags, DB_HASH_VALID); } -#if defined(CONFIG_BT_SETTINGS) static void sc_indicate(uint16_t start, uint16_t end); -#endif static void do_db_hash(void) { @@ -1463,8 +1462,6 @@ void bt_gatt_init(void) bt_gatt_service_init(); - sys_slist_init(&callback_list); - #if defined(CONFIG_BT_GATT_CACHING) k_work_init_delayable(&db_hash.work, db_hash_process); @@ -1516,10 +1513,10 @@ void bt_gatt_init(void) #endif /* CONFIG_BT_SETTINGS && CONFIG_BT_SMP */ } -#if defined(CONFIG_BT_GATT_DYNAMIC_DB) || \ - (defined(CONFIG_BT_GATT_CACHING) && defined(CONFIG_BT_SETTINGS)) static void sc_indicate(uint16_t start, uint16_t end) { +#if defined(CONFIG_BT_GATT_DYNAMIC_DB) || \ + (defined(CONFIG_BT_GATT_CACHING) && defined(CONFIG_BT_SETTINGS)) LOG_DBG("start 0x%04x end 0x%04x", start, end); if (!atomic_test_and_set_bit(gatt_sc.flags, SC_RANGE_CHANGED)) { @@ -1540,8 +1537,8 @@ static void sc_indicate(uint16_t start, uint16_t end) /* Reschedule since the range has changed */ sc_work_submit(SC_TIMEOUT); -} #endif /* BT_GATT_DYNAMIC_DB || (BT_GATT_CACHING && BT_SETTINGS) */ +} void bt_gatt_cb_register(struct bt_gatt_cb *cb) { @@ -4621,8 +4618,11 @@ static void gatt_read_rsp(struct bt_conn *conn, uint8_t err, const void *pdu, * If the Characteristic Value is greater than (ATT_MTU - 1) octets * in length, the Read Long Characteristic Value procedure may be used * if the rest of the Characteristic Value is required. + * + * Note: Both BT_ATT_OP_READ_RSP and BT_ATT_OP_READ_BLOB_RSP + * have an overhead of one octet. */ - if (length < (bt_att_get_mtu(conn) - 1)) { + if (length < (params->_att_mtu - 1)) { params->func(conn, 0, params, NULL, 0); return; } @@ -5117,18 +5117,21 @@ static void gatt_write_ccc_rsp(struct bt_conn *conn, uint8_t err, /* if write to CCC failed we remove subscription and notify app */ if (err) { struct gatt_sub *sub; - sys_snode_t *node, *tmp; + sys_snode_t *node, *tmp, *prev; sub = gatt_sub_find(conn); if (!sub) { return; } + prev = NULL; + SYS_SLIST_FOR_EACH_NODE_SAFE(&sub->list, node, tmp) { if (node == ¶ms->node) { - gatt_sub_remove(conn, sub, tmp, params); + gatt_sub_remove(conn, sub, prev, params); break; } + prev = node; } } else if (!params->value) { /* Notify with NULL data to complete unsubscribe */ @@ -5752,14 +5755,12 @@ void bt_gatt_encrypt_change(struct bt_conn *conn) bt_gatt_foreach_attr(0x0001, 0xffff, update_ccc, &data); -#if defined(CONFIG_BT_SETTINGS) && defined(CONFIG_BT_GATT_SERVICE_CHANGED) if (!bt_gatt_change_aware(conn, false)) { /* Send a Service Changed indication if the current peer is * marked as change-unaware. */ sc_indicate(0x0001, 0xffff); } -#endif /* CONFIG_BT_SETTINGS && CONFIG_BT_GATT_SERVICE_CHANGED */ } bool bt_gatt_change_aware(struct bt_conn *conn, bool req) @@ -6274,3 +6275,22 @@ void bt_gatt_disconnected(struct bt_conn *conn) remove_cf_cfg(conn); #endif } + +void bt_gatt_req_set_mtu(struct bt_att_req *req, uint16_t mtu) +{ + IF_ENABLED(CONFIG_BT_GATT_CLIENT, ({ + if (req->func == gatt_read_rsp) { + struct bt_gatt_read_params *params = req->user_data; + + __ASSERT_NO_MSG(params); + params->_att_mtu = mtu; + return; + } + })); + + /* Otherwise: This request type does not have an `_att_mtu` + * params field or any other method to get this value, so we can + * just drop it here. Feel free to add this capability to other + * request types if needed. + */ +} diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 7cf699aa8cc..b37cd45e1ae 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -111,16 +111,8 @@ struct cmd_data { static struct cmd_data cmd_data[CONFIG_BT_BUF_CMD_TX_COUNT]; -#if defined(CONFIG_BT_CONN) -struct acl_data { - uint16_t acl_handle; -}; - -static struct acl_data acl_data[CONFIG_BT_BUF_ACL_RX_COUNT]; -#endif - #define cmd(buf) (&cmd_data[net_buf_id(buf)]) -#define acl(buf) (&acl_data[net_buf_id(buf)]) +#define acl(buf) ((struct acl_data *)net_buf_user_data(buf)) void bt_hci_cmd_state_set_init(struct net_buf *buf, struct bt_hci_cmd_state_set *state, @@ -209,9 +201,10 @@ void bt_hci_host_num_completed_packets(struct net_buf *buf) { struct bt_hci_cp_host_num_completed_packets *cp; - uint16_t handle = acl(buf)->acl_handle; + uint16_t handle = acl(buf)->handle; struct bt_hci_handle_count *hc; struct bt_conn *conn; + uint8_t index = acl(buf)->index; net_buf_destroy(buf); @@ -220,9 +213,9 @@ void bt_hci_host_num_completed_packets(struct net_buf *buf) return; } - conn = bt_conn_lookup_handle(handle, BT_CONN_TYPE_ALL); + conn = bt_conn_lookup_index(index); if (!conn) { - LOG_WRN("Unable to look up conn with ACL handle %u", handle); + LOG_WRN("Unable to look up conn with index 0x%02x", index); return; } @@ -508,17 +501,21 @@ static void hci_acl(struct net_buf *buf) uint8_t flags; LOG_DBG("buf %p", buf); - - BT_ASSERT(buf->len >= sizeof(*hdr)); + if (buf->len < sizeof(*hdr)) { + LOG_ERR("Invalid HCI ACL packet size (%u)", buf->len); + net_buf_unref(buf); + return; + } hdr = net_buf_pull_mem(buf, sizeof(*hdr)); len = sys_le16_to_cpu(hdr->len); handle = sys_le16_to_cpu(hdr->handle); flags = bt_acl_flags(handle); - acl(buf)->acl_handle = bt_acl_handle(handle); + acl(buf)->handle = bt_acl_handle(handle); + acl(buf)->index = BT_CONN_INDEX_INVALID; - LOG_DBG("handle %u len %u flags %u", acl(buf)->acl_handle, len, flags); + LOG_DBG("handle %u len %u flags %u", acl(buf)->handle, len, flags); if (buf->len != len) { LOG_ERR("ACL data length mismatch (%u != %u)", buf->len, len); @@ -526,13 +523,15 @@ static void hci_acl(struct net_buf *buf) return; } - conn = bt_conn_lookup_handle(acl(buf)->acl_handle, BT_CONN_TYPE_ALL); + conn = bt_conn_lookup_handle(acl(buf)->handle, BT_CONN_TYPE_ALL); if (!conn) { - LOG_ERR("Unable to find conn for handle %u", acl(buf)->acl_handle); + LOG_ERR("Unable to find conn for handle %u", acl(buf)->handle); net_buf_unref(buf); return; } + acl(buf)->index = bt_conn_index(conn); + bt_conn_recv(conn, buf, flags); bt_conn_unref(conn); } @@ -2334,6 +2333,14 @@ static void hci_cmd_complete(struct net_buf *buf) */ status = buf->data[0]; + /* HOST_NUM_COMPLETED_PACKETS should not generate a response under normal operation. + * The generation of this command ignores `ncmd_sem`, so should not be given here. + */ + if (opcode == BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS) { + LOG_WRN("Unexpected HOST_NUM_COMPLETED_PACKETS (status 0x%02x)", status); + return; + } + hci_cmd_done(opcode, status, buf); /* Allow next command to be sent */ @@ -2681,7 +2688,11 @@ static void hci_event(struct net_buf *buf) { struct bt_hci_evt_hdr *hdr; - BT_ASSERT(buf->len >= sizeof(*hdr)); + if (buf->len < sizeof(*hdr)) { + LOG_ERR("Invalid HCI event size (%u)", buf->len); + net_buf_unref(buf); + return; + } hdr = net_buf_pull_mem(buf, sizeof(*hdr)); LOG_DBG("event 0x%02x", hdr->evt); @@ -3748,7 +3759,11 @@ void hci_event_prio(struct net_buf *buf) net_buf_simple_save(&buf->b, &state); - BT_ASSERT(buf->len >= sizeof(*hdr)); + if (buf->len < sizeof(*hdr)) { + LOG_ERR("Invalid HCI event size (%u)", buf->len); + net_buf_unref(buf); + return; + } hdr = net_buf_pull_mem(buf, sizeof(*hdr)); evt_flags = bt_hci_evt_get_flags(hdr->evt); @@ -3972,6 +3987,13 @@ static void rx_work_handler(struct k_work *work) } #endif /* !CONFIG_BT_RECV_BLOCKING */ +#if defined(CONFIG_BT_TESTING) +k_tid_t bt_testing_tx_tid_get(void) +{ + return &tx_thread_data; +} +#endif + int bt_enable(bt_ready_cb_t cb) { int err; diff --git a/subsys/bluetooth/host/hci_core.h b/subsys/bluetooth/host/hci_core.h index 65466cae740..ce4fc5a9b63 100644 --- a/subsys/bluetooth/host/hci_core.h +++ b/subsys/bluetooth/host/hci_core.h @@ -381,8 +381,10 @@ struct bt_dev { /* Local Identity Resolving Key */ uint8_t irk[CONFIG_BT_ID_MAX][16]; +#if defined(CONFIG_BT_RPA_SHARING) /* Only 1 RPA per identity */ bt_addr_t rpa[CONFIG_BT_ID_MAX]; +#endif /* Work used for RPA rotation */ struct k_work_delayable rpa_update; diff --git a/subsys/bluetooth/host/id.c b/subsys/bluetooth/host/id.c index 4bbc5e23192..6b5fcbd5d17 100644 --- a/subsys/bluetooth/host/id.c +++ b/subsys/bluetooth/host/id.c @@ -207,13 +207,14 @@ static void adv_rpa_expired(struct bt_le_ext_adv *adv) if (atomic_test_bit(adv->flags, BT_ADV_RPA_VALID) && adv->cb && adv->cb->rpa_expired) { rpa_invalid = adv->cb->rpa_expired(adv); - if (rpa_invalid) { - bt_addr_copy(&bt_dev.rpa[adv->id], BT_ADDR_NONE); - } } #endif if (rpa_invalid) { atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID); + +#if defined(CONFIG_BT_RPA_SHARING) + bt_addr_copy(&bt_dev.rpa[adv->id], BT_ADDR_NONE); +#endif } } @@ -321,8 +322,39 @@ int bt_id_set_private_addr(uint8_t id) return 0; } +#if defined(CONFIG_BT_RPA_SHARING) +static int adv_rpa_get(struct bt_le_ext_adv *adv, bt_addr_t *rpa) +{ + int err; + + if (bt_addr_eq(&bt_dev.rpa[adv->id], BT_ADDR_NONE)) { + err = bt_rpa_create(bt_dev.irk[adv->id], &bt_dev.rpa[adv->id]); + if (err) { + return err; + } + } + + bt_addr_copy(rpa, &bt_dev.rpa[adv->id]); + + return 0; +} +#else +static int adv_rpa_get(struct bt_le_ext_adv *adv, bt_addr_t *rpa) +{ + int err; + + err = bt_rpa_create(bt_dev.irk[adv->id], rpa); + if (err) { + return err; + } + + return 0; +} +#endif /* defined(CONFIG_BT_RPA_SHARING) */ + int bt_id_set_adv_private_addr(struct bt_le_ext_adv *adv) { + bt_addr_t rpa; int err; CHECKIF(adv == NULL) { @@ -373,16 +405,12 @@ int bt_id_set_adv_private_addr(struct bt_le_ext_adv *adv) return 0; } - if (bt_addr_eq(&bt_dev.rpa[adv->id], BT_ADDR_NONE)) { - err = bt_rpa_create(bt_dev.irk[adv->id], &bt_dev.rpa[adv->id]); - if (err) { - return err; - } - } - - err = bt_id_set_adv_random_addr(adv, &bt_dev.rpa[adv->id]); + err = adv_rpa_get(adv, &rpa); if (!err) { - atomic_set_bit(adv->flags, BT_ADV_RPA_VALID); + err = bt_id_set_adv_random_addr(adv, &rpa); + if (!err) { + atomic_set_bit(adv->flags, BT_ADV_RPA_VALID); + } } if (!atomic_test_bit(adv->flags, BT_ADV_LIMITED)) { @@ -394,7 +422,7 @@ int bt_id_set_adv_private_addr(struct bt_le_ext_adv *adv) } if (IS_ENABLED(CONFIG_BT_LOG_SNIFFER_INFO)) { - LOG_INF("RPA: %s", bt_addr_str(&bt_dev.rpa[adv->id])); + LOG_INF("RPA: %s", bt_addr_str(&rpa)); } return 0; @@ -1230,7 +1258,10 @@ static int id_create(uint8_t id, bt_addr_le_t *addr, uint8_t *irk) memcpy(irk, &bt_dev.irk[id], 16); } } + +#if defined(CONFIG_BT_RPA_SHARING) bt_addr_copy(&bt_dev.rpa[id], BT_ADDR_NONE); +#endif } #endif /* Only store if stack was already initialized. Before initialization @@ -2064,8 +2095,12 @@ int bt_id_init(void) int err; #if defined(CONFIG_BT_PRIVACY) - bt_addr_copy(&bt_dev.rpa[BT_ID_DEFAULT], BT_ADDR_NONE); k_work_init_delayable(&bt_dev.rpa_update, rpa_timeout); +#if defined(CONFIG_BT_RPA_SHARING) + for (uint8_t id = 0U; id < ARRAY_SIZE(bt_dev.rpa); id++) { + bt_addr_copy(&bt_dev.rpa[id], BT_ADDR_NONE); + } +#endif #endif if (!IS_ENABLED(CONFIG_BT_SETTINGS) && !bt_dev.id_count) { diff --git a/subsys/bluetooth/host/iso.c b/subsys/bluetooth/host/iso.c index f8df05e32d9..42e9c877a9a 100644 --- a/subsys/bluetooth/host/iso.c +++ b/subsys/bluetooth/host/iso.c @@ -105,7 +105,11 @@ void hci_iso(struct net_buf *buf) BT_ISO_DATA_DBG("buf %p", buf); - BT_ASSERT(buf->len >= sizeof(*hdr)); + if (buf->len < sizeof(*hdr)) { + LOG_ERR("Invalid HCI ISO packet size (%u)", buf->len); + net_buf_unref(buf); + return; + } hdr = net_buf_pull_mem(buf, sizeof(*hdr)); len = bt_iso_hdr_len(sys_le16_to_cpu(hdr->len)); @@ -839,7 +843,7 @@ static bool valid_chan_io_qos(const struct bt_iso_chan_io_qos *io_qos, return false; } -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) if (advanced) { if (IS_ENABLED(CONFIG_BT_ISO_BROADCASTER) && is_broadcast) { if (!IN_RANGE(io_qos->max_pdu, @@ -869,7 +873,7 @@ static bool valid_chan_io_qos(const struct bt_iso_chan_io_qos *io_qos, } #else ARG_UNUSED(advanced); -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ return true; } @@ -970,6 +974,14 @@ int bt_iso_chan_disconnect(struct bt_iso_chan *chan) return -EALREADY; } + if (IS_ENABLED(CONFIG_BT_ISO_PERIPHERAL) && chan->iso->role == BT_HCI_ROLE_PERIPHERAL && + chan->state == BT_ISO_STATE_CONNECTING) { + /* A CIS peripheral is not allowed to disconnect a CIS in the connecting state - It + * has to wait for a CIS Established event + */ + return -EAGAIN; + } + err = bt_conn_disconnect(chan->iso, BT_HCI_ERR_REMOTE_USER_TERM_CONN); if (err == 0) { bt_iso_chan_set_state(chan, BT_ISO_STATE_DISCONNECTING); @@ -1027,8 +1039,14 @@ void hci_le_cis_established(struct net_buf *buf) /* ISO connection handles are already assigned at this point */ iso = bt_conn_lookup_handle(handle, BT_CONN_TYPE_ISO); if (!iso) { - LOG_ERR("No connection found for handle %u", handle); - bt_conn_unref(iso); + /* If it is a local disconnect, then we may have received the disconnect complete + * event before this event, and in which case we do not expect to find the CIS + * object + */ + if (evt->status != BT_HCI_ERR_OP_CANCELLED_BY_HOST) { + LOG_ERR("No connection found for handle %u", handle); + } + return; } @@ -1099,10 +1117,11 @@ void hci_le_cis_established(struct net_buf *buf) bt_conn_set_state(iso, BT_CONN_CONNECTED); bt_conn_unref(iso); return; - } + } else if (evt->status != BT_HCI_ERR_OP_CANCELLED_BY_HOST) { + iso->err = evt->status; + bt_iso_disconnected(iso); + } /* else we wait for disconnect event */ - iso->err = evt->status; - bt_iso_disconnected(iso); bt_conn_unref(iso); } @@ -1437,14 +1456,14 @@ static void bt_iso_remove_data_path(struct bt_conn *iso) static bool valid_chan_qos(const struct bt_iso_chan_qos *qos, bool advanced) { -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) if (advanced && !IN_RANGE(qos->num_subevents, BT_ISO_NSE_MIN, BT_ISO_NSE_MAX)) { LOG_DBG("Invalid NSE: %u", qos->num_subevents); return false; } -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ if (qos->rx != NULL) { if (!valid_chan_io_qos(qos->rx, false, false, advanced)) { @@ -1505,18 +1524,22 @@ static struct net_buf *hci_le_set_cig_params(const struct bt_iso_cig *cig, memset(req, 0, sizeof(*req)); req->cig_id = cig->id; - req->c_latency = sys_cpu_to_le16(param->latency); - req->p_latency = sys_cpu_to_le16(param->latency); - sys_put_le24(param->interval, req->c_interval); - sys_put_le24(param->interval, req->p_interval); + req->c_latency = sys_cpu_to_le16(param->c_to_p_latency); + req->p_latency = sys_cpu_to_le16(param->p_to_c_latency); + sys_put_le24(param->c_to_p_interval, req->c_interval); + sys_put_le24(param->p_to_c_interval, req->p_interval); req->sca = param->sca; req->packing = param->packing; req->framing = param->framing; req->num_cis = param->num_cis; - LOG_DBG("id %u, latency %u, interval %u, sca %u, packing %u, framing %u, num_cis %u", - cig->id, param->latency, param->interval, param->sca, param->packing, + LOG_DBG("id %u, latency C to P %u, latency P to C %u, " + "interval C to P %u, interval P to C %u, " + "sca %u, packing %u, framing %u, num_cis %u", + cig->id, param->c_to_p_latency, param->p_to_c_latency, + param->c_to_p_interval, param->p_to_c_interval, + param->sca, param->packing, param->framing, param->num_cis); /* Program the cis parameters */ @@ -1571,7 +1594,7 @@ static struct net_buf *hci_le_set_cig_params(const struct bt_iso_cig *cig, return rsp; } -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) static struct net_buf *hci_le_set_cig_test_params(const struct bt_iso_cig *cig, const struct bt_iso_cig_param *param) { @@ -1592,8 +1615,8 @@ static struct net_buf *hci_le_set_cig_test_params(const struct bt_iso_cig *cig, memset(req, 0, sizeof(*req)); req->cig_id = cig->id; - sys_put_le24(param->interval, req->c_interval); - sys_put_le24(param->interval, req->p_interval); + sys_put_le24(param->c_to_p_interval, req->c_interval); + sys_put_le24(param->p_to_c_interval, req->p_interval); req->c_ft = param->c_to_p_ft; req->p_ft = param->p_to_c_ft; @@ -1603,10 +1626,10 @@ static struct net_buf *hci_le_set_cig_test_params(const struct bt_iso_cig *cig, req->framing = param->framing; req->num_cis = param->num_cis; - LOG_DBG("id %u, SDU interval %u, c_ft %u, p_ft %u, iso_interval %u, " - "sca %u, packing %u, framing %u, num_cis %u", - cig->id, param->interval, param->c_to_p_ft, param->p_to_c_ft, - param->iso_interval, param->sca, param->packing, + LOG_DBG("id %u, SDU interval C to P %u, SDU interval P to C %u, c_ft %u, p_ft %u, " + "iso_interval %u, sca %u, packing %u, framing %u, num_cis %u", + cig->id, param->c_to_p_interval, param->p_to_c_interval, param->c_to_p_ft, + param->p_to_c_ft, param->iso_interval, param->sca, param->packing, param->framing, param->num_cis); /* Program the cis parameters */ @@ -1701,11 +1724,11 @@ static bool is_advanced_cig_param(const struct bt_iso_cig_param *param) return false; } -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ static struct bt_iso_cig *get_cig(const struct bt_iso_chan *iso_chan) { - if (iso_chan->iso == NULL) { + if (iso_chan == NULL || iso_chan->iso == NULL) { return NULL; } @@ -1736,6 +1759,10 @@ static struct bt_iso_cig *get_free_cig(void) static bool cis_is_in_cig(const struct bt_iso_cig *cig, const struct bt_iso_chan *cis) { + if (cig == NULL || cis == NULL || cis->iso == NULL) { + return false; + } + return cig->id == cis->iso->iso.cig_id; } @@ -1784,7 +1811,8 @@ static void cleanup_cig(struct bt_iso_cig *cig) memset(cig, 0, sizeof(*cig)); } -static bool valid_cig_param(const struct bt_iso_cig_param *param, bool advanced) +static bool valid_cig_param(const struct bt_iso_cig_param *param, bool advanced, + const struct bt_iso_cig *cig) { if (param == NULL) { return false; @@ -1798,8 +1826,8 @@ static bool valid_cig_param(const struct bt_iso_cig_param *param, bool advanced) return false; } - if (cis->iso != NULL) { - LOG_DBG("cis_channels[%d]: already allocated", i); + if (cis->iso != NULL && !cis_is_in_cig(cig, cis)) { + LOG_DBG("cis_channels[%d]: already allocated to CIG %p", i, get_cig(cis)); return false; } @@ -1835,20 +1863,28 @@ static bool valid_cig_param(const struct bt_iso_cig_param *param, bool advanced) return false; } - if (param->interval < BT_ISO_SDU_INTERVAL_MIN || - param->interval > BT_ISO_SDU_INTERVAL_MAX) { - LOG_DBG("Invalid interval: %u", param->interval); + if (!IN_RANGE(param->c_to_p_interval, BT_ISO_SDU_INTERVAL_MIN, BT_ISO_SDU_INTERVAL_MAX)) { + LOG_DBG("Invalid C to P interval: %u", param->c_to_p_interval); + return false; + } + + if (!IN_RANGE(param->p_to_c_interval, BT_ISO_SDU_INTERVAL_MIN, BT_ISO_SDU_INTERVAL_MAX)) { + LOG_DBG("Invalid P to C interval: %u", param->p_to_c_interval); return false; } if (!advanced && - (param->latency < BT_ISO_LATENCY_MIN || - param->latency > BT_ISO_LATENCY_MAX)) { - LOG_DBG("Invalid latency: %u", param->latency); + !IN_RANGE(param->c_to_p_latency, BT_ISO_LATENCY_MIN, BT_ISO_LATENCY_MAX)) { + LOG_DBG("Invalid C to P latency: %u", param->c_to_p_latency); + return false; + } + if (!advanced && + !IN_RANGE(param->p_to_c_latency, BT_ISO_LATENCY_MIN, BT_ISO_LATENCY_MAX)) { + LOG_DBG("Invalid P to C latency: %u", param->p_to_c_latency); return false; } -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) if (advanced) { if (!IN_RANGE(param->c_to_p_ft, BT_ISO_FT_MIN, BT_ISO_FT_MAX)) { LOG_DBG("Invalid Central to Peripheral FT %u", @@ -1872,7 +1908,7 @@ static bool valid_cig_param(const struct bt_iso_cig_param *param, bool advanced) return false; } } -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ return true; } @@ -1911,11 +1947,11 @@ int bt_iso_cig_create(const struct bt_iso_cig_param *param, return -EINVAL; } -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) advanced = is_advanced_cig_param(param); -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ - CHECKIF(!valid_cig_param(param, advanced)) { + CHECKIF(!valid_cig_param(param, advanced, NULL)) { LOG_DBG("Invalid CIG params"); return -EINVAL; } @@ -1935,10 +1971,10 @@ int bt_iso_cig_create(const struct bt_iso_cig_param *param, if (!advanced) { rsp = hci_le_set_cig_params(cig, param); -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) } else { rsp = hci_le_set_cig_test_params(cig, param); -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ } if (rsp == NULL) { @@ -2000,11 +2036,9 @@ int bt_iso_cig_reconfigure(struct bt_iso_cig *cig, { struct bt_hci_rp_le_set_cig_params *cig_rsp; uint8_t existing_num_cis; - struct bt_iso_chan *cis; bool advanced = false; struct net_buf *rsp; int err; - int i; CHECKIF(cig == NULL) { LOG_DBG("cig is NULL"); @@ -2016,26 +2050,15 @@ int bt_iso_cig_reconfigure(struct bt_iso_cig *cig, return -EINVAL; } -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) advanced = is_advanced_cig_param(param); -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ - CHECKIF(!valid_cig_param(param, advanced)) { + CHECKIF(!valid_cig_param(param, advanced, cig)) { LOG_DBG("Invalid CIG params"); return -EINVAL; } - for (uint8_t j = 0; j < param->num_cis; j++) { - struct bt_iso_chan *param_cis = param->cis_channels[j]; - - if (param_cis->iso != NULL && !cis_is_in_cig(cig, param_cis)) { - LOG_DBG("Cannot reconfigure other CIG's (id 0x%02X) CIS " - "with this CIG (id 0x%02X)", - param_cis->iso->iso.cig_id, cig->id); - return -EINVAL; - } - } - /* Used to restore CIG in case of error */ existing_num_cis = cig->num_cis; @@ -2048,10 +2071,10 @@ int bt_iso_cig_reconfigure(struct bt_iso_cig *cig, if (!advanced) { rsp = hci_le_set_cig_params(cig, param); -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) } else { rsp = hci_le_set_cig_test_params(cig, param); -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ } if (rsp == NULL) { @@ -2063,18 +2086,27 @@ int bt_iso_cig_reconfigure(struct bt_iso_cig *cig, cig_rsp = (void *)rsp->data; - if (rsp->len < sizeof(cig_rsp) || - cig_rsp->num_handles != param->num_cis) { - LOG_WRN("Unexpected response to hci_le_set_cig_params"); + if (rsp->len < sizeof(*cig_rsp)) { + LOG_WRN("Unexpected response len to hci_le_set_cig_params %u != %zu", rsp->len, + sizeof(*cig_rsp)); err = -EIO; net_buf_unref(rsp); restore_cig(cig, existing_num_cis); return err; } - i = 0; - SYS_SLIST_FOR_EACH_CONTAINER(&cig->cis_channels, cis, node) { - const uint16_t handle = cig_rsp->handle[i++]; + if (cig_rsp->num_handles != param->num_cis) { + LOG_WRN("Unexpected response num_handles to hci_le_set_cig_params %u != %u", + cig_rsp->num_handles, param->num_cis); + err = -EIO; + net_buf_unref(rsp); + restore_cig(cig, existing_num_cis); + return err; + } + + for (uint8_t i = 0u; i < param->num_cis; i++) { + const uint16_t handle = cig_rsp->handle[i]; + struct bt_iso_chan *cis = param->cis_channels[i]; /* Assign the connection handle */ cis->iso->handle = sys_le16_to_cpu(handle); @@ -2563,7 +2595,7 @@ static int hci_le_create_big(struct bt_le_ext_adv *padv, struct bt_iso_big *big, return err; } -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) static int hci_le_create_big_test(const struct bt_le_ext_adv *padv, struct bt_iso_big *big, const struct bt_iso_big_create_param *param) @@ -2655,7 +2687,7 @@ static bool is_advanced_big_param(const struct bt_iso_big_create_param *param) return false; } -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ static bool valid_big_param(const struct bt_iso_big_create_param *param, bool advanced) @@ -2741,7 +2773,7 @@ static bool valid_big_param(const struct bt_iso_big_create_param *param, return false; } -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) if (advanced) { CHECKIF(!IN_RANGE(param->irc, BT_ISO_IRC_MIN, BT_ISO_IRC_MAX)) { LOG_DBG("Invalid IRC %u", param->irc); @@ -2763,7 +2795,7 @@ static bool valid_big_param(const struct bt_iso_big_create_param *param, return false; } } -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ return true; } @@ -2780,9 +2812,9 @@ int bt_iso_big_create(struct bt_le_ext_adv *padv, struct bt_iso_big_create_param return -EINVAL; } -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) advanced = is_advanced_big_param(param); -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ if (!valid_big_param(param, advanced)) { LOG_DBG("Invalid BIG parameters"); @@ -2806,10 +2838,10 @@ int bt_iso_big_create(struct bt_le_ext_adv *padv, struct bt_iso_big_create_param if (!advanced) { err = hci_le_create_big(padv, big, param); -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) } else { err = hci_le_create_big_test(padv, big, param); -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ } if (err) { diff --git a/subsys/bluetooth/host/l2cap.c b/subsys/bluetooth/host/l2cap.c index 7203faf8b2f..e6fbe2144f8 100644 --- a/subsys/bluetooth/host/l2cap.c +++ b/subsys/bluetooth/host/l2cap.c @@ -1048,7 +1048,7 @@ static uint16_t l2cap_chan_accept(struct bt_conn *conn, /* Request server to accept the new connection and allocate the * channel. */ - err = server->accept(conn, chan); + err = server->accept(conn, server, chan); if (err < 0) { return le_err_to_result(err); } @@ -1363,6 +1363,12 @@ static void le_ecred_reconf_req(struct bt_l2cap *l2cap, uint8_t ident, goto response; } + /* The specification only allows up to 5 CIDs in this packet */ + if (buf->len > (L2CAP_ECRED_CHAN_MAX_PER_REQ * sizeof(scid))) { + result = BT_L2CAP_RECONF_OTHER_UNACCEPT; + goto response; + } + while (buf->len >= sizeof(scid)) { struct bt_l2cap_chan *chan; scid = net_buf_pull_le16(buf); diff --git a/subsys/bluetooth/host/l2cap_br.c b/subsys/bluetooth/host/l2cap_br.c index 676fbf0a344..e9a10ff8d72 100644 --- a/subsys/bluetooth/host/l2cap_br.c +++ b/subsys/bluetooth/host/l2cap_br.c @@ -747,7 +747,7 @@ static void l2cap_br_conn_req(struct bt_l2cap_br *l2cap, uint8_t ident, * channel. If no free channels available for PSM server reply with * proper result and quit since chan pointer is uninitialized then. */ - if (server->accept(conn, &chan) < 0) { + if (server->accept(conn, server, &chan) < 0) { result = BT_L2CAP_BR_ERR_NO_RESOURCES; goto no_chan; } diff --git a/subsys/bluetooth/host/rfcomm.c b/subsys/bluetooth/host/rfcomm.c index 8682db1c254..21b0e45e13a 100644 --- a/subsys/bluetooth/host/rfcomm.c +++ b/subsys/bluetooth/host/rfcomm.c @@ -1704,7 +1704,8 @@ int bt_rfcomm_dlc_disconnect(struct bt_rfcomm_dlc *dlc) return rfcomm_dlc_close(dlc); } -static int rfcomm_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan) +static int rfcomm_accept(struct bt_conn *conn, struct bt_l2cap_server *server, + struct bt_l2cap_chan **chan) { struct bt_rfcomm_session *session; diff --git a/subsys/bluetooth/host/sdp.c b/subsys/bluetooth/host/sdp.c index ae20b5dfa79..bd36187d43c 100644 --- a/subsys/bluetooth/host/sdp.c +++ b/subsys/bluetooth/host/sdp.c @@ -1389,7 +1389,8 @@ static int bt_sdp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf) * * @return 0 for success, or relevant error code */ -static int bt_sdp_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan) +static int bt_sdp_accept(struct bt_conn *conn, struct bt_l2cap_server *server, + struct bt_l2cap_chan **chan) { static const struct bt_l2cap_chan_ops ops = { .connected = bt_sdp_connected, diff --git a/subsys/bluetooth/host/smp.c b/subsys/bluetooth/host/smp.c index 9643982c421..2c110dc43a3 100644 --- a/subsys/bluetooth/host/smp.c +++ b/subsys/bluetooth/host/smp.c @@ -1650,11 +1650,11 @@ static void smp_pairing_complete(struct bt_smp *smp, uint8_t status) LOG_DBG("got status 0x%x", status); - if (conn->state != BT_CONN_CONNECTED) { - /* If disconnection has been triggered in between the security update - * and the call to this function we need to abort the pairing. + if (conn->le.keys == NULL) { + /* We can get here if the application calls `bt_unpair` in the + * `security_changed` callback. */ - LOG_WRN("Not connected!"); + LOG_WRN("The in-progress pairing has been deleted!"); status = BT_SMP_ERR_UNSPECIFIED; } @@ -1677,7 +1677,7 @@ static void smp_pairing_complete(struct bt_smp *smp, uint8_t status) bt_keys_show_sniffer_info(conn->le.keys, NULL); } - if (bond_flag) { + if (bond_flag && conn->le.keys) { bt_keys_store(conn->le.keys); } diff --git a/subsys/bluetooth/host/testing.c b/subsys/bluetooth/host/testing.c index 3c118c51e0f..5e2f507bb58 100644 --- a/subsys/bluetooth/host/testing.c +++ b/subsys/bluetooth/host/testing.c @@ -56,7 +56,7 @@ void bt_test_mesh_model_recv(uint16_t src, uint16_t dst, const void *payload, } } -void bt_test_mesh_model_bound(uint16_t addr, struct bt_mesh_model *model, +void bt_test_mesh_model_bound(uint16_t addr, const struct bt_mesh_model *model, uint16_t key_idx) { struct bt_test_cb *cb; @@ -68,7 +68,7 @@ void bt_test_mesh_model_bound(uint16_t addr, struct bt_mesh_model *model, } } -void bt_test_mesh_model_unbound(uint16_t addr, struct bt_mesh_model *model, +void bt_test_mesh_model_unbound(uint16_t addr, const struct bt_mesh_model *model, uint16_t key_idx) { struct bt_test_cb *cb; diff --git a/subsys/bluetooth/host/testing.h b/subsys/bluetooth/host/testing.h index 0e6cfbaf785..8ed1fa61e46 100644 --- a/subsys/bluetooth/host/testing.h +++ b/subsys/bluetooth/host/testing.h @@ -14,9 +14,9 @@ void bt_test_mesh_net_recv(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst, const void *payload, size_t payload_len); void bt_test_mesh_model_recv(uint16_t src, uint16_t dst, const void *payload, size_t payload_len); -void bt_test_mesh_model_bound(uint16_t addr, struct bt_mesh_model *model, +void bt_test_mesh_model_bound(uint16_t addr, const struct bt_mesh_model *model, uint16_t key_idx); -void bt_test_mesh_model_unbound(uint16_t addr, struct bt_mesh_model *model, +void bt_test_mesh_model_unbound(uint16_t addr, const struct bt_mesh_model *model, uint16_t key_idx); void bt_test_mesh_prov_invalid_bearer(uint8_t opcode); void bt_test_mesh_trans_incomp_timer_exp(void); diff --git a/subsys/bluetooth/mesh/Kconfig b/subsys/bluetooth/mesh/Kconfig index 63749a69d56..04366828bbe 100644 --- a/subsys/bluetooth/mesh/Kconfig +++ b/subsys/bluetooth/mesh/Kconfig @@ -1049,13 +1049,10 @@ config BT_MESH_FRIEND_ADV_LATENCY endif # BT_MESH_FRIEND menuconfig BT_MESH_V1d1 - bool "Bluetooth mesh v1.1 support [EXPERIMENTAL]" - select EXPERIMENTAL + bool "Bluetooth mesh v1.1 support" help This option enables Bluetooth mesh v1.1 support. Bluetooth mesh v1.1 - is backward compatible with v1.0.1. The stack cannot be qualified - with this option enabled because the Bluetooth mesh v1.1 specification - is in a draft state. + is backward compatible with v1.0.1. config BT_MESH_ECDH_P256_CMAC_AES128_AES_CCM bool "Support CMAC AES128 for OOB authentication" if BT_MESH_V1d1 @@ -1431,7 +1428,7 @@ config BT_MESH_COMP_PAGE_2 config BT_MESH_MODEL_EXTENSION_LIST_SIZE int "Model extensions list size" depends on BT_MESH_COMP_PAGE_1 - range 1 255 + range 0 255 default 10 help This option specifies how many models relations can be saved. @@ -1442,11 +1439,10 @@ config BT_MESH_SOLICITATION bool config BT_MESH_PROXY_SOLICITATION - bool "Proxy solicitation feature for Proxy Client support" - depends on BT_MESH_PROXY_CLIENT + bool "Proxy solicitation feature" select BT_MESH_SOLICITATION help - This option enables support for sending Solicitation PDUs for Proxy Client. + This option enables support for sending Solicitation PDUs. config BT_MESH_SOL_ADV_XMIT int "Solicitation PDU retransmission count" diff --git a/subsys/bluetooth/mesh/access.c b/subsys/bluetooth/mesh/access.c index 6ca7dbe580b..dcf7f0f783b 100644 --- a/subsys/bluetooth/mesh/access.c +++ b/subsys/bluetooth/mesh/access.c @@ -92,12 +92,12 @@ static struct mod_relation mod_rel_list[MOD_REL_LIST_SIZE]; (idx)++) #define IS_MOD_BASE(mod, idx, offset) \ - (mod_rel_list[(idx)].elem_base == (mod)->elem_idx && \ - mod_rel_list[(idx)].idx_base == (mod)->mod_idx + (offset)) + (mod_rel_list[(idx)].elem_base == mod->rt->elem_idx && \ + mod_rel_list[(idx)].idx_base == mod->rt->mod_idx + (offset)) #define IS_MOD_EXTENSION(mod, idx, offset) \ - (mod_rel_list[(idx)].elem_ext == (mod)->elem_idx && \ - mod_rel_list[(idx)].idx_ext == (mod)->mod_idx + (offset)) + (mod_rel_list[(idx)].elem_ext == mod->rt->elem_idx && \ + mod_rel_list[(idx)].idx_ext == mod->rt->mod_idx + (offset)) #define RELATION_TYPE_EXT 0xFF @@ -114,8 +114,8 @@ static const struct { #endif }; -void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod, - struct bt_mesh_elem *elem, +void bt_mesh_model_foreach(void (*func)(const struct bt_mesh_model *mod, + const struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data), void *user_data) @@ -123,16 +123,16 @@ void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod, int i, j; for (i = 0; i < dev_comp->elem_count; i++) { - struct bt_mesh_elem *elem = &dev_comp->elem[i]; + const struct bt_mesh_elem *elem = &dev_comp->elem[i]; for (j = 0; j < elem->model_count; j++) { - struct bt_mesh_model *model = &elem->models[j]; + const struct bt_mesh_model *model = &elem->models[j]; func(model, elem, false, i == 0, user_data); } for (j = 0; j < elem->vnd_model_count; j++) { - struct bt_mesh_model *model = &elem->vnd_models[j]; + const struct bt_mesh_model *model = &elem->vnd_models[j]; func(model, elem, true, i == 0, user_data); } @@ -181,7 +181,7 @@ static void data_buf_add_mem_offset(struct net_buf_simple *buf, uint8_t *data, s *offset = 0; } -static void comp_add_model(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, +static void comp_add_model(const struct bt_mesh_model *mod, const struct bt_mesh_elem *elem, bool vnd, void *user_data) { struct comp_foreach_model_arg *arg = user_data; @@ -196,8 +196,8 @@ static void comp_add_model(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, #if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV) -static size_t metadata_model_size(struct bt_mesh_model *mod, - struct bt_mesh_elem *elem, bool vnd) +static size_t metadata_model_size(const struct bt_mesh_model *mod, + const struct bt_mesh_elem *elem, bool vnd) { const struct bt_mesh_models_metadata_entry *entry; size_t size = 0; @@ -231,19 +231,19 @@ size_t bt_mesh_metadata_page_0_size(void) comp = bt_mesh_comp_get(); for (i = 0; i < dev_comp->elem_count; i++) { - struct bt_mesh_elem *elem = &dev_comp->elem[i]; + const struct bt_mesh_elem *elem = &dev_comp->elem[i]; size += sizeof(elem->model_count) + sizeof(elem->vnd_model_count); for (j = 0; j < elem->model_count; j++) { - struct bt_mesh_model *model = &elem->models[j]; + const struct bt_mesh_model *model = &elem->models[j]; size += metadata_model_size(model, elem, false); } for (j = 0; j < elem->vnd_model_count; j++) { - struct bt_mesh_model *model = &elem->vnd_models[j]; + const struct bt_mesh_model *model = &elem->vnd_models[j]; size += metadata_model_size(model, elem, true); } @@ -252,8 +252,8 @@ size_t bt_mesh_metadata_page_0_size(void) return size; } -static int metadata_add_model(struct bt_mesh_model *mod, - struct bt_mesh_elem *elem, bool vnd, +static int metadata_add_model(const struct bt_mesh_model *mod, + const struct bt_mesh_elem *elem, bool vnd, void *user_data) { const struct bt_mesh_models_metadata_entry *entry; @@ -310,7 +310,7 @@ int bt_mesh_metadata_get_page_0(struct net_buf_simple *buf, size_t offset) comp = bt_mesh_comp_get(); for (i = 0; i < comp->elem_count; i++) { - struct bt_mesh_elem *elem = &dev_comp->elem[i]; + const struct bt_mesh_elem *elem = &dev_comp->elem[i]; /* Check that the buffer has available tailroom for metadata item counts */ if (net_buf_simple_tailroom(buf) < (((offset == 0) ? 2 : (offset == 1) ? 1 : 0) @@ -322,7 +322,7 @@ int bt_mesh_metadata_get_page_0(struct net_buf_simple *buf, size_t offset) vnd_count_ptr = data_buf_add_u8_offset(buf, 0, &offset); for (j = 0; j < elem->model_count; j++) { - struct bt_mesh_model *model = &elem->models[j]; + const struct bt_mesh_model *model = &elem->models[j]; if (!model->metadata) { continue; @@ -339,7 +339,7 @@ int bt_mesh_metadata_get_page_0(struct net_buf_simple *buf, size_t offset) } for (j = 0; j < elem->vnd_model_count; j++) { - struct bt_mesh_model *model = &elem->vnd_models[j]; + const struct bt_mesh_model *model = &elem->vnd_models[j]; if (!model->metadata) { continue; @@ -360,7 +360,7 @@ int bt_mesh_metadata_get_page_0(struct net_buf_simple *buf, size_t offset) } #endif -static int comp_add_elem(struct net_buf_simple *buf, struct bt_mesh_elem *elem, +static int comp_add_elem(struct net_buf_simple *buf, const struct bt_mesh_elem *elem, size_t *offset) { struct comp_foreach_model_arg arg = { @@ -377,12 +377,12 @@ static int comp_add_elem(struct net_buf_simple *buf, struct bt_mesh_elem *elem, if (net_buf_simple_tailroom(buf) < ((elem_size - *offset) + BT_MESH_MIC_SHORT)) { if (IS_ENABLED(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)) { - /* Mesh Profile 1.1 Section 4.4.1.2.2: + /* MshPRTv1.1: 4.4.1.2.2: * If the complete list of models does not fit in the Data field, * the element shall not be reported. */ LOG_DBG("Element 0x%04x didn't fit in the Data field", - elem->addr); + elem->rt->addr); return 0; } @@ -396,13 +396,13 @@ static int comp_add_elem(struct net_buf_simple *buf, struct bt_mesh_elem *elem, data_buf_add_u8_offset(buf, elem->vnd_model_count, offset); for (i = 0; i < elem->model_count; i++) { - struct bt_mesh_model *model = &elem->models[i]; + const struct bt_mesh_model *model = &elem->models[i]; comp_add_model(model, elem, false, &arg); } for (i = 0; i < elem->vnd_model_count; i++) { - struct bt_mesh_model *model = &elem->vnd_models[i]; + const struct bt_mesh_model *model = &elem->vnd_models[i]; comp_add_model(model, elem, true, &arg); } @@ -452,7 +452,8 @@ int bt_mesh_comp_data_get_page_0(struct net_buf_simple *buf, size_t offset) return 0; } -static uint8_t count_mod_ext(struct bt_mesh_model *mod, uint8_t *max_offset, uint8_t sig_offset) +static uint8_t count_mod_ext(const struct bt_mesh_model *mod, + uint8_t *max_offset, uint8_t sig_offset) { int i; uint8_t extensions = 0; @@ -476,7 +477,7 @@ static uint8_t count_mod_ext(struct bt_mesh_model *mod, uint8_t *max_offset, uin return extensions; } -static bool is_cor_present(struct bt_mesh_model *mod, uint8_t *cor_id, uint8_t sig_offset) +static bool is_cor_present(const struct bt_mesh_model *mod, uint8_t *cor_id, uint8_t sig_offset) { int i; @@ -494,8 +495,9 @@ static bool is_cor_present(struct bt_mesh_model *mod, uint8_t *cor_id, uint8_t s return false; } -static void prep_model_item_header(struct bt_mesh_model *mod, uint8_t *cor_id, uint8_t *mod_cnt, - struct net_buf_simple *buf, size_t *offset, uint8_t sig_offset) +static void prep_model_item_header(const struct bt_mesh_model *mod, uint8_t *cor_id, + uint8_t *mod_cnt, struct net_buf_simple *buf, + size_t *offset, uint8_t sig_offset) { uint8_t ext_mod_cnt; bool cor_present; @@ -522,7 +524,7 @@ static void prep_model_item_header(struct bt_mesh_model *mod, uint8_t *cor_id, u memset(mod_cnt, ext_mod_cnt, sizeof(uint8_t)); } -static void add_items_to_page(struct net_buf_simple *buf, struct bt_mesh_model *mod, +static void add_items_to_page(struct net_buf_simple *buf, const struct bt_mesh_model *mod, uint8_t ext_mod_cnt, size_t *offset, uint8_t sig_offset) { int i, elem_offset; @@ -531,7 +533,7 @@ static void add_items_to_page(struct net_buf_simple *buf, struct bt_mesh_model * MOD_REL_LIST_FOR_EACH(i) { if (IS_MOD_EXTENSION(mod, i, sig_offset) && mod_rel_list[i].type == RELATION_TYPE_EXT) { - elem_offset = mod->elem_idx - mod_rel_list[i].elem_base; + elem_offset = mod->rt->elem_idx - mod_rel_list[i].elem_base; mod_idx = mod_rel_list[i].idx_base; if (ext_mod_cnt < 32 && elem_offset < 4 && @@ -555,7 +557,7 @@ static void add_items_to_page(struct net_buf_simple *buf, struct bt_mesh_model * } } -static size_t mod_items_size(struct bt_mesh_model *mod, uint8_t sig_offset) +static size_t mod_items_size(const struct bt_mesh_model *mod, uint8_t sig_offset) { int i, offset; size_t temp_size = 0; @@ -567,7 +569,7 @@ static size_t mod_items_size(struct bt_mesh_model *mod, uint8_t sig_offset) MOD_REL_LIST_FOR_EACH(i) { if (IS_MOD_EXTENSION(mod, i, sig_offset)) { - offset = mod->elem_idx - mod_rel_list[i].elem_base; + offset = mod->rt->elem_idx - mod_rel_list[i].elem_base; temp_size += (ext_mod_cnt < 32 && offset < 4 && offset > -5) ? 1 : 2; } } @@ -575,7 +577,7 @@ static size_t mod_items_size(struct bt_mesh_model *mod, uint8_t sig_offset) return temp_size; } -static size_t page1_elem_size(struct bt_mesh_elem *elem) +static size_t page1_elem_size(const struct bt_mesh_elem *elem) { size_t temp_size = 2; @@ -611,12 +613,12 @@ static int bt_mesh_comp_data_get_page_1(struct net_buf_simple *buf, size_t offse if (net_buf_simple_tailroom(buf) < ((elem_size - offset) + BT_MESH_MIC_SHORT)) { if (IS_ENABLED(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)) { - /* Mesh Profile 1.1 Section 4.4.1.2.2: + /* MshPRTv1.1: 4.4.1.2.2: * If the complete list of models does not fit in the Data field, * the element shall not be reported. */ LOG_DBG("Element 0x%04x didn't fit in the Data field", - comp->elem[i].addr); + comp->elem[i].rt->addr); return 0; } @@ -669,7 +671,7 @@ static int bt_mesh_comp_data_get_page_2(struct net_buf_simple *buf, size_t offse if (net_buf_simple_tailroom(buf) < ((elem_size - offset) + BT_MESH_MIC_SHORT)) { if (IS_ENABLED(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)) { - /* Mesh Profile 1.1 Section 4.4.1.2.2: + /* MshPRTv1.1: 4.4.1.2.2: * If the complete list of models does not fit in the Data field, * the element shall not be reported. */ @@ -701,7 +703,7 @@ static int bt_mesh_comp_data_get_page_2(struct net_buf_simple *buf, size_t offse return 0; } -int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod) +int32_t bt_mesh_model_pub_period_get(const struct bt_mesh_model *mod) { int32_t period; @@ -741,7 +743,7 @@ int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod) } } -static int32_t next_period(struct bt_mesh_model *mod) +static int32_t next_period(const struct bt_mesh_model *mod) { struct bt_mesh_model_pub *pub = mod->pub; uint32_t period = 0; @@ -782,7 +784,7 @@ static int32_t next_period(struct bt_mesh_model *mod) static void publish_sent(int err, void *user_data) { - struct bt_mesh_model *mod = user_data; + const struct bt_mesh_model *mod = user_data; int32_t delay; LOG_DBG("err %d, time %u", err, k_uptime_get_32()); @@ -812,20 +814,20 @@ static const struct bt_mesh_send_cb pub_sent_cb = { .end = publish_sent, }; -static int publish_transmit(struct bt_mesh_model *mod) +static int publish_transmit(const struct bt_mesh_model *mod) { NET_BUF_SIMPLE_DEFINE(sdu, BT_MESH_TX_SDU_MAX); struct bt_mesh_model_pub *pub = mod->pub; struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_PUB(pub); struct bt_mesh_net_tx tx = { .ctx = &ctx, - .src = bt_mesh_model_elem(mod)->addr, + .src = bt_mesh_model_elem(mod)->rt->addr, .friend_cred = pub->cred, }; net_buf_simple_add_mem(&sdu, pub->msg->data, pub->msg->len); - return bt_mesh_trans_send(&tx, &sdu, &pub_sent_cb, mod); + return bt_mesh_trans_send(&tx, &sdu, &pub_sent_cb, (void *)mod); } static int pub_period_start(struct bt_mesh_model_pub *pub) @@ -846,7 +848,7 @@ static int pub_period_start(struct bt_mesh_model_pub *pub) /* Skip this publish attempt. */ LOG_DBG("Update failed, skipping publish (err: %d)", err); pub->count = 0; - publish_sent(err, pub->mod); + publish_sent(err, (void *)pub->mod); return err; } @@ -878,7 +880,7 @@ static void mod_publish(struct k_work *work) bt_mesh_model_pub_is_retransmission(pub->mod)) { err = pub->update(pub->mod); if (err) { - publish_sent(err, pub->mod); + publish_sent(err, (void *)pub->mod); return; } } @@ -893,18 +895,18 @@ static void mod_publish(struct k_work *work) err = publish_transmit(pub->mod); if (err) { LOG_ERR("Failed to publish (err %d)", err); - publish_sent(err, pub->mod); + publish_sent(err, (void *)pub->mod); } } -struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod) +const struct bt_mesh_elem *bt_mesh_model_elem(const struct bt_mesh_model *mod) { - return &dev_comp->elem[mod->elem_idx]; + return &dev_comp->elem[mod->rt->elem_idx]; } -struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_idx) +const struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_idx) { - struct bt_mesh_elem *elem; + const struct bt_mesh_elem *elem; if (elem_idx >= dev_comp->elem_count) { LOG_ERR("Invalid element index %u", elem_idx); @@ -931,7 +933,7 @@ struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_ } #if defined(CONFIG_BT_MESH_MODEL_VND_MSG_CID_FORCE) -static int bt_mesh_vnd_mod_msg_cid_check(struct bt_mesh_model *mod) +static int bt_mesh_vnd_mod_msg_cid_check(const struct bt_mesh_model *mod) { uint16_t cid; const struct bt_mesh_model_op *op; @@ -954,7 +956,7 @@ static int bt_mesh_vnd_mod_msg_cid_check(struct bt_mesh_model *mod) } #endif -static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, +static void mod_init(const struct bt_mesh_model *mod, const struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data) { int i; @@ -973,9 +975,9 @@ static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, mod->keys[i] = BT_MESH_KEY_UNUSED; } - mod->elem_idx = elem - dev_comp->elem; + mod->rt->elem_idx = elem - dev_comp->elem; if (vnd) { - mod->mod_idx = mod - elem->vnd_models; + mod->rt->mod_idx = mod - elem->vnd_models; if (IS_ENABLED(CONFIG_BT_MESH_MODEL_VND_MSG_CID_FORCE)) { *err = bt_mesh_vnd_mod_msg_cid_check(mod); @@ -985,7 +987,7 @@ static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, } } else { - mod->mod_idx = mod - elem->models; + mod->rt->mod_idx = mod - elem->models; } if (mod->cb && mod->cb->init) { @@ -1055,12 +1057,12 @@ void bt_mesh_comp_provision(uint16_t addr) LOG_DBG("addr 0x%04x elem_count %zu", addr, dev_comp->elem_count); for (i = 0; i < dev_comp->elem_count; i++) { - struct bt_mesh_elem *elem = &dev_comp->elem[i]; + const struct bt_mesh_elem *elem = &dev_comp->elem[i]; - elem->addr = addr++; + elem->rt->addr = addr++; - LOG_DBG("addr 0x%04x mod_count %u vnd_mod_count %u", elem->addr, elem->model_count, - elem->vnd_model_count); + LOG_DBG("addr 0x%04x mod_count %u vnd_mod_count %u", elem->rt->addr, + elem->model_count, elem->vnd_model_count); } } @@ -1071,9 +1073,9 @@ void bt_mesh_comp_unprovision(void) dev_primary_addr = BT_MESH_ADDR_UNASSIGNED; for (int i = 0; i < dev_comp->elem_count; i++) { - struct bt_mesh_elem *elem = &dev_comp->elem[i]; + const struct bt_mesh_elem *elem = &dev_comp->elem[i]; - elem->addr = BT_MESH_ADDR_UNASSIGNED; + elem->rt->addr = BT_MESH_ADDR_UNASSIGNED; } } @@ -1082,7 +1084,7 @@ uint16_t bt_mesh_primary_addr(void) return dev_primary_addr; } -static uint16_t *model_group_get(struct bt_mesh_model *mod, uint16_t addr) +static uint16_t *model_group_get(const struct bt_mesh_model *mod, uint16_t addr) { int i; @@ -1097,15 +1099,15 @@ static uint16_t *model_group_get(struct bt_mesh_model *mod, uint16_t addr) struct find_group_visitor_ctx { uint16_t *entry; - struct bt_mesh_model *mod; + const struct bt_mesh_model *mod; uint16_t addr; }; -static enum bt_mesh_walk find_group_mod_visitor(struct bt_mesh_model *mod, void *user_data) +static enum bt_mesh_walk find_group_mod_visitor(const struct bt_mesh_model *mod, void *user_data) { struct find_group_visitor_ctx *ctx = user_data; - if (mod->elem_idx != ctx->mod->elem_idx) { + if (mod->rt->elem_idx != ctx->mod->rt->elem_idx) { return BT_MESH_WALK_CONTINUE; } @@ -1118,7 +1120,7 @@ static enum bt_mesh_walk find_group_mod_visitor(struct bt_mesh_model *mod, void return BT_MESH_WALK_CONTINUE; } -uint16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, uint16_t addr) +uint16_t *bt_mesh_model_find_group(const struct bt_mesh_model **mod, uint16_t addr) { struct find_group_visitor_ctx ctx = { .mod = *mod, @@ -1133,7 +1135,7 @@ uint16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, uint16_t addr) } #if CONFIG_BT_MESH_LABEL_COUNT > 0 -static const uint8_t **model_uuid_get(struct bt_mesh_model *mod, const uint8_t *uuid) +static const uint8_t **model_uuid_get(const struct bt_mesh_model *mod, const uint8_t *uuid) { int i; @@ -1155,15 +1157,15 @@ static const uint8_t **model_uuid_get(struct bt_mesh_model *mod, const uint8_t * struct find_uuid_visitor_ctx { const uint8_t **entry; - struct bt_mesh_model *mod; + const struct bt_mesh_model *mod; const uint8_t *uuid; }; -static enum bt_mesh_walk find_uuid_mod_visitor(struct bt_mesh_model *mod, void *user_data) +static enum bt_mesh_walk find_uuid_mod_visitor(const struct bt_mesh_model *mod, void *user_data) { struct find_uuid_visitor_ctx *ctx = user_data; - if (mod->elem_idx != ctx->mod->elem_idx) { + if (mod->rt->elem_idx != ctx->mod->rt->elem_idx) { return BT_MESH_WALK_CONTINUE; } @@ -1177,7 +1179,7 @@ static enum bt_mesh_walk find_uuid_mod_visitor(struct bt_mesh_model *mod, void * } #endif /* CONFIG_BT_MESH_LABEL_COUNT > 0 */ -const uint8_t **bt_mesh_model_find_uuid(struct bt_mesh_model **mod, const uint8_t *uuid) +const uint8_t **bt_mesh_model_find_uuid(const struct bt_mesh_model **mod, const uint8_t *uuid) { #if CONFIG_BT_MESH_LABEL_COUNT > 0 struct find_uuid_visitor_ctx ctx = { @@ -1195,10 +1197,10 @@ const uint8_t **bt_mesh_model_find_uuid(struct bt_mesh_model **mod, const uint8_ #endif } -static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem, +static const struct bt_mesh_model *bt_mesh_elem_find_group(const struct bt_mesh_elem *elem, uint16_t group_addr) { - struct bt_mesh_model *model; + const struct bt_mesh_model *model; uint16_t *match; int i; @@ -1223,7 +1225,7 @@ static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem, return NULL; } -struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr) +const struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr) { uint16_t index; @@ -1231,7 +1233,7 @@ struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr) return NULL; } - index = addr - dev_comp->elem[0].addr; + index = addr - dev_comp->elem[0].rt->addr; if (index >= dev_comp->elem_count) { return NULL; } @@ -1252,7 +1254,7 @@ bool bt_mesh_has_addr(uint16_t addr) } for (index = 0; index < dev_comp->elem_count; index++) { - struct bt_mesh_elem *elem = &dev_comp->elem[index]; + const struct bt_mesh_elem *elem = &dev_comp->elem[index]; if (bt_mesh_elem_find_group(elem, addr)) { return true; @@ -1295,7 +1297,7 @@ uint8_t bt_mesh_elem_count(void) return dev_comp->elem_count; } -bool bt_mesh_model_has_key(struct bt_mesh_model *mod, uint16_t key) +bool bt_mesh_model_has_key(const struct bt_mesh_model *mod, uint16_t key) { int i; @@ -1310,14 +1312,14 @@ bool bt_mesh_model_has_key(struct bt_mesh_model *mod, uint16_t key) return false; } -static bool model_has_dst(struct bt_mesh_model *mod, uint16_t dst, const uint8_t *uuid) +static bool model_has_dst(const struct bt_mesh_model *mod, uint16_t dst, const uint8_t *uuid) { if (BT_MESH_ADDR_IS_UNICAST(dst)) { - return (dev_comp->elem[mod->elem_idx].addr == dst); + return (dev_comp->elem[mod->rt->elem_idx].rt->addr == dst); } else if (BT_MESH_ADDR_IS_VIRTUAL(dst)) { return !!bt_mesh_model_find_uuid(&mod, uuid); } else if (BT_MESH_ADDR_IS_GROUP(dst) || - (BT_MESH_ADDR_IS_FIXED_GROUP(dst) && mod->elem_idx != 0)) { + (BT_MESH_ADDR_IS_FIXED_GROUP(dst) && mod->rt->elem_idx != 0)) { return !!bt_mesh_model_find_group(&mod, dst); } @@ -1325,17 +1327,17 @@ static bool model_has_dst(struct bt_mesh_model *mod, uint16_t dst, const uint8_t * the lower layers have already confirmed that we are subscribing to * it. All models on the primary element should receive the message. */ - return mod->elem_idx == 0; + return mod->rt->elem_idx == 0; } -static const struct bt_mesh_model_op *find_op(struct bt_mesh_elem *elem, - uint32_t opcode, struct bt_mesh_model **model) +static const struct bt_mesh_model_op *find_op(const struct bt_mesh_elem *elem, + uint32_t opcode, const struct bt_mesh_model **model) { uint8_t i; uint8_t count; /* This value shall not be used in shipping end products. */ uint32_t cid = UINT32_MAX; - struct bt_mesh_model *models; + const struct bt_mesh_model *models; /* SIG models cannot contain 3-byte (vendor) OpCodes, and * vendor models cannot contain SIG (1- or 2-byte) OpCodes, so @@ -1413,16 +1415,16 @@ static int get_opcode(struct net_buf_simple *buf, uint32_t *opcode) } static int element_model_recv(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf, - struct bt_mesh_elem *elem, uint32_t opcode) + const struct bt_mesh_elem *elem, uint32_t opcode) { const struct bt_mesh_model_op *op; - struct bt_mesh_model *model; + const struct bt_mesh_model *model; struct net_buf_simple_state state; int err; op = find_op(elem, opcode, &model); if (!op) { - LOG_ERR("No OpCode 0x%08x for elem 0x%02x", opcode, elem->addr); + LOG_ERR("No OpCode 0x%08x for elem 0x%02x", opcode, elem->rt->addr); return ACCESS_STATUS_WRONG_OPCODE; } @@ -1477,19 +1479,19 @@ int bt_mesh_model_recv(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) LOG_DBG("OpCode 0x%08x", opcode); if (BT_MESH_ADDR_IS_UNICAST(ctx->recv_dst)) { - index = ctx->recv_dst - dev_comp->elem[0].addr; + index = ctx->recv_dst - dev_comp->elem[0].rt->addr; if (index >= dev_comp->elem_count) { LOG_ERR("Invalid address 0x%02x", ctx->recv_dst); err = ACCESS_STATUS_INVALID_ADDRESS; } else { - struct bt_mesh_elem *elem = &dev_comp->elem[index]; + const struct bt_mesh_elem *elem = &dev_comp->elem[index]; err = element_model_recv(ctx, buf, elem, opcode); } } else { for (index = 0; index < dev_comp->elem_count; index++) { - struct bt_mesh_elem *elem = &dev_comp->elem[index]; + const struct bt_mesh_elem *elem = &dev_comp->elem[index]; (void)element_model_recv(ctx, buf, elem, opcode); } @@ -1502,12 +1504,14 @@ int bt_mesh_model_recv(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) return err; } -int bt_mesh_model_send(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +int bt_mesh_model_send(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *msg, const struct bt_mesh_send_cb *cb, void *cb_data) { - if (IS_ENABLED(CONFIG_BT_MESH_OP_AGG) && bt_mesh_op_agg_accept(ctx)) { - return bt_mesh_op_agg_send(model, ctx, msg, cb); + if (IS_ENABLED(CONFIG_BT_MESH_OP_AGG_SRV) && bt_mesh_op_agg_srv_accept(ctx, msg)) { + return bt_mesh_op_agg_srv_send(model, msg); + } else if (IS_ENABLED(CONFIG_BT_MESH_OP_AGG_CLI) && bt_mesh_op_agg_cli_accept(ctx, msg)) { + return bt_mesh_op_agg_cli_send(model, msg); } if (!bt_mesh_model_has_key(model, ctx->app_idx)) { @@ -1515,10 +1519,10 @@ int bt_mesh_model_send(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, return -EINVAL; } - return bt_mesh_access_send(ctx, msg, bt_mesh_model_elem(model)->addr, cb, cb_data); + return bt_mesh_access_send(ctx, msg, bt_mesh_model_elem(model)->rt->addr, cb, cb_data); } -int bt_mesh_model_publish(struct bt_mesh_model *model) +int bt_mesh_model_publish(const struct bt_mesh_model *model) { struct bt_mesh_model_pub *pub = model->pub; @@ -1558,7 +1562,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model) return 0; } -struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem, +const struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem, uint16_t company, uint16_t id) { uint8_t i; @@ -1573,7 +1577,7 @@ struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem, return NULL; } -struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem, +const struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem, uint16_t id) { uint8_t i; @@ -1592,8 +1596,8 @@ const struct bt_mesh_comp *bt_mesh_comp_get(void) return dev_comp; } -void bt_mesh_model_extensions_walk(struct bt_mesh_model *model, - enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod, +void bt_mesh_model_extensions_walk(const struct bt_mesh_model *model, + enum bt_mesh_walk (*cb)(const struct bt_mesh_model *mod, void *user_data), void *user_data) { @@ -1601,14 +1605,14 @@ void bt_mesh_model_extensions_walk(struct bt_mesh_model *model, (void)cb(model, user_data); return; #else - struct bt_mesh_model *it; + const struct bt_mesh_model *it; - if (cb(model, user_data) == BT_MESH_WALK_STOP || !model->next) { + if (cb(model, user_data) == BT_MESH_WALK_STOP || !model->rt->next) { return; } /* List is circular. Step through all models until we reach the start: */ - for (it = model->next; it != model; it = it->next) { + for (it = model->rt->next; it != model; it = it->rt->next) { if (cb(it, user_data) == BT_MESH_WALK_STOP) { return; } @@ -1620,7 +1624,7 @@ void bt_mesh_model_extensions_walk(struct bt_mesh_model *model, /* For vendor models, determine the offset within the model relation list * by counting the number of standard SIG models in the associated element. */ -static uint8_t get_sig_offset(struct bt_mesh_model *mod) +static uint8_t get_sig_offset(const struct bt_mesh_model *mod) { const struct bt_mesh_elem *elem = bt_mesh_model_elem(mod); uint8_t i; @@ -1633,16 +1637,16 @@ static uint8_t get_sig_offset(struct bt_mesh_model *mod) return 0; } -static int mod_rel_register(struct bt_mesh_model *base, - struct bt_mesh_model *ext, +static int mod_rel_register(const struct bt_mesh_model *base, + const struct bt_mesh_model *ext, uint8_t type) { LOG_DBG(""); struct mod_relation extension = { - base->elem_idx, - base->mod_idx + get_sig_offset(base), - ext->elem_idx, - ext->mod_idx + get_sig_offset(ext), + base->rt->elem_idx, + base->rt->mod_idx + get_sig_offset(base), + ext->rt->elem_idx, + ext->rt->mod_idx + get_sig_offset(ext), type, }; int i; @@ -1661,22 +1665,23 @@ static int mod_rel_register(struct bt_mesh_model *base, return -ENOMEM; } -int bt_mesh_model_extend(struct bt_mesh_model *extending_mod, struct bt_mesh_model *base_mod) +int bt_mesh_model_extend(const struct bt_mesh_model *extending_mod, + const struct bt_mesh_model *base_mod) { - struct bt_mesh_model *a = extending_mod; - struct bt_mesh_model *b = base_mod; - struct bt_mesh_model *a_next = a->next; - struct bt_mesh_model *b_next = b->next; - struct bt_mesh_model *it; + const struct bt_mesh_model *a = extending_mod; + const struct bt_mesh_model *b = base_mod; + const struct bt_mesh_model *a_next = a->rt->next; + const struct bt_mesh_model *b_next = b->rt->next; + const struct bt_mesh_model *it; - base_mod->flags |= BT_MESH_MOD_EXTENDED; + base_mod->rt->flags |= BT_MESH_MOD_EXTENDED; if (a == b) { return 0; } /* Check if a's list contains b */ - for (it = a; (it != NULL) && (it->next != a); it = it->next) { + for (it = a; (it != NULL) && (it->rt->next != a); it = it->rt->next) { if (it == b) { goto register_extension; } @@ -1684,15 +1689,15 @@ int bt_mesh_model_extend(struct bt_mesh_model *extending_mod, struct bt_mesh_mod /* Merge lists */ if (a_next) { - b->next = a_next; + b->rt->next = a_next; } else { - b->next = a; + b->rt->next = a; } if (b_next) { - a->next = b_next; + a->rt->next = b_next; } else { - a->next = b; + a->rt->next = b; } register_extension: @@ -1703,8 +1708,8 @@ int bt_mesh_model_extend(struct bt_mesh_model *extending_mod, struct bt_mesh_mod return 0; } -int bt_mesh_model_correspond(struct bt_mesh_model *corresponding_mod, - struct bt_mesh_model *base_mod) +int bt_mesh_model_correspond(const struct bt_mesh_model *corresponding_mod, + const struct bt_mesh_model *base_mod) { int i, err; uint8_t cor_id = 0; @@ -1738,12 +1743,12 @@ int bt_mesh_model_correspond(struct bt_mesh_model *corresponding_mod, } #endif /* CONFIG_BT_MESH_MODEL_EXTENSIONS */ -bool bt_mesh_model_is_extended(struct bt_mesh_model *model) +bool bt_mesh_model_is_extended(const struct bt_mesh_model *model) { - return model->flags & BT_MESH_MOD_EXTENDED; + return model->rt->flags & BT_MESH_MOD_EXTENDED; } -static int mod_set_bind(struct bt_mesh_model *mod, size_t len_rd, +static int mod_set_bind(const struct bt_mesh_model *mod, size_t len_rd, settings_read_cb read_cb, void *cb_arg) { ssize_t len; @@ -1771,7 +1776,7 @@ static int mod_set_bind(struct bt_mesh_model *mod, size_t len_rd, return 0; } -static int mod_set_sub(struct bt_mesh_model *mod, size_t len_rd, +static int mod_set_sub(const struct bt_mesh_model *mod, size_t len_rd, settings_read_cb read_cb, void *cb_arg) { size_t size = mod->groups_cnt * sizeof(mod->groups[0]); @@ -1818,7 +1823,7 @@ static int mod_set_sub(struct bt_mesh_model *mod, size_t len_rd, return 0; } -static int mod_set_sub_va(struct bt_mesh_model *mod, size_t len_rd, +static int mod_set_sub_va(const struct bt_mesh_model *mod, size_t len_rd, settings_read_cb read_cb, void *cb_arg) { #if CONFIG_BT_MESH_LABEL_COUNT > 0 @@ -1855,7 +1860,7 @@ static int mod_set_sub_va(struct bt_mesh_model *mod, size_t len_rd, return 0; } -static int mod_set_pub(struct bt_mesh_model *mod, size_t len_rd, +static int mod_set_pub(const struct bt_mesh_model *mod, size_t len_rd, settings_read_cb read_cb, void *cb_arg) { struct mod_pub_val pub; @@ -1925,7 +1930,7 @@ static int mod_set_pub(struct bt_mesh_model *mod, size_t len_rd, return 0; } -static int mod_data_set(struct bt_mesh_model *mod, +static int mod_data_set(const struct bt_mesh_model *mod, const char *name, size_t len_rd, settings_read_cb read_cb, void *cb_arg) { @@ -1944,7 +1949,7 @@ static int mod_data_set(struct bt_mesh_model *mod, static int mod_set(bool vnd, const char *name, size_t len_rd, settings_read_cb read_cb, void *cb_arg) { - struct bt_mesh_model *mod; + const struct bt_mesh_model *mod; uint8_t elem_idx, mod_idx; uint16_t mod_key; int len; @@ -2033,10 +2038,10 @@ static int comp_set(const char *name, size_t len_rd, settings_read_cb read_cb, } BT_MESH_SETTINGS_DEFINE(comp, "cmp", comp_set); -static void encode_mod_path(struct bt_mesh_model *mod, bool vnd, +static void encode_mod_path(const struct bt_mesh_model *mod, bool vnd, const char *key, char *path, size_t path_len) { - uint16_t mod_key = (((uint16_t)mod->elem_idx << 8) | mod->mod_idx); + uint16_t mod_key = (((uint16_t)mod->rt->elem_idx << 8) | mod->rt->mod_idx); if (vnd) { snprintk(path, path_len, "bt/mesh/v/%x/%s", mod_key, key); @@ -2045,7 +2050,7 @@ static void encode_mod_path(struct bt_mesh_model *mod, bool vnd, } } -static void store_pending_mod_bind(struct bt_mesh_model *mod, bool vnd) +static void store_pending_mod_bind(const struct bt_mesh_model *mod, bool vnd) { uint16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT]; char path[20]; @@ -2073,7 +2078,7 @@ static void store_pending_mod_bind(struct bt_mesh_model *mod, bool vnd) } } -static void store_pending_mod_sub(struct bt_mesh_model *mod, bool vnd) +static void store_pending_mod_sub(const struct bt_mesh_model *mod, bool vnd) { uint16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT]; char path[20]; @@ -2100,7 +2105,7 @@ static void store_pending_mod_sub(struct bt_mesh_model *mod, bool vnd) } } -static void store_pending_mod_sub_va(struct bt_mesh_model *mod, bool vnd) +static void store_pending_mod_sub_va(const struct bt_mesh_model *mod, bool vnd) { #if CONFIG_BT_MESH_LABEL_COUNT > 0 uint16_t uuidxs[CONFIG_BT_MESH_LABEL_COUNT]; @@ -2132,7 +2137,7 @@ static void store_pending_mod_sub_va(struct bt_mesh_model *mod, bool vnd) #endif /* CONFIG_BT_MESH_LABEL_COUNT > 0 */ } -static void store_pending_mod_pub(struct bt_mesh_model *mod, bool vnd) +static void store_pending_mod_pub(const struct bt_mesh_model *mod, bool vnd) { struct mod_pub_val pub = {0}; char path[20]; @@ -2165,32 +2170,32 @@ static void store_pending_mod_pub(struct bt_mesh_model *mod, bool vnd) } } -static void store_pending_mod(struct bt_mesh_model *mod, - struct bt_mesh_elem *elem, bool vnd, +static void store_pending_mod(const struct bt_mesh_model *mod, + const struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data) { - if (!mod->flags) { + if (!mod->rt->flags) { return; } - if (mod->flags & BT_MESH_MOD_BIND_PENDING) { - mod->flags &= ~BT_MESH_MOD_BIND_PENDING; + if (mod->rt->flags & BT_MESH_MOD_BIND_PENDING) { + mod->rt->flags &= ~BT_MESH_MOD_BIND_PENDING; store_pending_mod_bind(mod, vnd); } - if (mod->flags & BT_MESH_MOD_SUB_PENDING) { - mod->flags &= ~BT_MESH_MOD_SUB_PENDING; + if (mod->rt->flags & BT_MESH_MOD_SUB_PENDING) { + mod->rt->flags &= ~BT_MESH_MOD_SUB_PENDING; store_pending_mod_sub(mod, vnd); store_pending_mod_sub_va(mod, vnd); } - if (mod->flags & BT_MESH_MOD_PUB_PENDING) { - mod->flags &= ~BT_MESH_MOD_PUB_PENDING; + if (mod->rt->flags & BT_MESH_MOD_PUB_PENDING) { + mod->rt->flags &= ~BT_MESH_MOD_PUB_PENDING; store_pending_mod_pub(mod, vnd); } - if (mod->flags & BT_MESH_MOD_DATA_PENDING) { - mod->flags &= ~BT_MESH_MOD_DATA_PENDING; + if (mod->rt->flags & BT_MESH_MOD_DATA_PENDING) { + mod->rt->flags &= ~BT_MESH_MOD_DATA_PENDING; mod->cb->pending_store(mod); } } @@ -2200,21 +2205,21 @@ void bt_mesh_model_pending_store(void) bt_mesh_model_foreach(store_pending_mod, NULL); } -void bt_mesh_model_bind_store(struct bt_mesh_model *mod) +void bt_mesh_model_bind_store(const struct bt_mesh_model *mod) { - mod->flags |= BT_MESH_MOD_BIND_PENDING; + mod->rt->flags |= BT_MESH_MOD_BIND_PENDING; bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_MOD_PENDING); } -void bt_mesh_model_sub_store(struct bt_mesh_model *mod) +void bt_mesh_model_sub_store(const struct bt_mesh_model *mod) { - mod->flags |= BT_MESH_MOD_SUB_PENDING; + mod->rt->flags |= BT_MESH_MOD_SUB_PENDING; bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_MOD_PENDING); } -void bt_mesh_model_pub_store(struct bt_mesh_model *mod) +void bt_mesh_model_pub_store(const struct bt_mesh_model *mod) { - mod->flags |= BT_MESH_MOD_PUB_PENDING; + mod->rt->flags |= BT_MESH_MOD_PUB_PENDING; bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_MOD_PENDING); } @@ -2399,7 +2404,7 @@ int bt_mesh_comp_read(struct net_buf_simple *buf, uint8_t page) return 0; } -int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd, +int bt_mesh_model_data_store(const struct bt_mesh_model *mod, bool vnd, const char *name, const void *data, size_t data_len) { @@ -2548,7 +2553,7 @@ int bt_mesh_models_metadata_change_prepare(void) #endif } -static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, +static void commit_mod(const struct bt_mesh_model *mod, const struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data) { if (mod->pub && mod->pub->update && @@ -2577,9 +2582,9 @@ void bt_mesh_model_settings_commit(void) bt_mesh_model_foreach(commit_mod, NULL); } -void bt_mesh_model_data_store_schedule(struct bt_mesh_model *mod) +void bt_mesh_model_data_store_schedule(const struct bt_mesh_model *mod) { - mod->flags |= BT_MESH_MOD_DATA_PENDING; + mod->rt->flags |= BT_MESH_MOD_DATA_PENDING; bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_MOD_PENDING); } diff --git a/subsys/bluetooth/mesh/access.h b/subsys/bluetooth/mesh/access.h index f58c6f1d449..b7ce1abd0ea 100644 --- a/subsys/bluetooth/mesh/access.h +++ b/subsys/bluetooth/mesh/access.h @@ -20,7 +20,7 @@ enum { BT_MESH_MOD_DATA_PENDING = BIT(5), }; -void bt_mesh_elem_register(struct bt_mesh_elem *elem, uint8_t count); +void bt_mesh_elem_register(const struct bt_mesh_elem *elem, uint8_t count); uint8_t bt_mesh_elem_count(void); size_t bt_mesh_comp_page_size(uint8_t page); @@ -29,26 +29,26 @@ size_t bt_mesh_metadata_page_0_size(void); int bt_mesh_metadata_get_page_0(struct net_buf_simple *buf, size_t offset); /* Find local element based on unicast address */ -struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr); +const struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr); bool bt_mesh_has_addr(uint16_t addr); -bool bt_mesh_model_has_key(struct bt_mesh_model *mod, uint16_t key); +bool bt_mesh_model_has_key(const struct bt_mesh_model *mod, uint16_t key); -void bt_mesh_model_extensions_walk(struct bt_mesh_model *root, - enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod, +void bt_mesh_model_extensions_walk(const struct bt_mesh_model *root, + enum bt_mesh_walk (*cb)(const struct bt_mesh_model *mod, void *user_data), void *user_data); -uint16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, uint16_t addr); -const uint8_t **bt_mesh_model_find_uuid(struct bt_mesh_model **mod, const uint8_t *uuid); +uint16_t *bt_mesh_model_find_group(const struct bt_mesh_model **mod, uint16_t addr); +const uint8_t **bt_mesh_model_find_uuid(const struct bt_mesh_model **mod, const uint8_t *uuid); -void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod, - struct bt_mesh_elem *elem, +void bt_mesh_model_foreach(void (*func)(const struct bt_mesh_model *mod, + const struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data), void *user_data); -int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod); +int32_t bt_mesh_model_pub_period_get(const struct bt_mesh_model *mod); void bt_mesh_comp_provision(uint16_t addr); void bt_mesh_comp_unprovision(void); @@ -57,7 +57,7 @@ uint16_t bt_mesh_primary_addr(void); const struct bt_mesh_comp *bt_mesh_comp_get(void); -struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_idx); +const struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_idx); int bt_mesh_model_recv(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf); @@ -74,9 +74,9 @@ void bt_mesh_comp_data_clear(void); int bt_mesh_comp_data_get_page(struct net_buf_simple *buf, size_t page, size_t offset); void bt_mesh_model_pending_store(void); -void bt_mesh_model_bind_store(struct bt_mesh_model *mod); -void bt_mesh_model_sub_store(struct bt_mesh_model *mod); -void bt_mesh_model_pub_store(struct bt_mesh_model *mod); +void bt_mesh_model_bind_store(const struct bt_mesh_model *mod); +void bt_mesh_model_sub_store(const struct bt_mesh_model *mod); +void bt_mesh_model_pub_store(const struct bt_mesh_model *mod); void bt_mesh_model_settings_commit(void); /** @brief Register a callback function hook for mesh model messages. diff --git a/subsys/bluetooth/mesh/adv.c b/subsys/bluetooth/mesh/adv.c index b24523aacf3..548e7f3fe15 100644 --- a/subsys/bluetooth/mesh/adv.c +++ b/subsys/bluetooth/mesh/adv.c @@ -157,7 +157,6 @@ struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, tag, xmit, timeout); } -#if CONFIG_BT_MESH_RELAY_ADV_SETS || CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE static struct net_buf *process_events(struct k_poll_event *ev, int count) { for (; count; ev++, count--) { @@ -186,12 +185,15 @@ struct net_buf *bt_mesh_adv_buf_get(k_timeout_t timeout) K_POLL_MODE_NOTIFY_ONLY, &bt_mesh_adv_queue, 0), -#if defined(CONFIG_BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET) +#if defined(CONFIG_BT_MESH_RELAY) && \ + (defined(CONFIG_BT_MESH_ADV_LEGACY) || \ + defined(CONFIG_BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET) || \ + !(CONFIG_BT_MESH_RELAY_ADV_SETS)) K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE, K_POLL_MODE_NOTIFY_ONLY, &bt_mesh_relay_queue, 0), -#endif /* CONFIG_BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET */ +#endif }; err = k_poll(events, ARRAY_SIZE(events), timeout); @@ -209,27 +211,13 @@ struct net_buf *bt_mesh_adv_buf_get_by_tag(enum bt_mesh_adv_tag_bit tags, k_time return net_buf_get(&bt_mesh_friend_queue, timeout); } -#if CONFIG_BT_MESH_RELAY_ADV_SETS - if (!(tags & BT_MESH_ADV_TAG_BIT_LOCAL)) { + if (IS_ENABLED(CONFIG_BT_MESH_RELAY) && + !(tags & BT_MESH_ADV_TAG_BIT_LOCAL)) { return net_buf_get(&bt_mesh_relay_queue, timeout); } -#endif return bt_mesh_adv_buf_get(timeout); } -#else /* !(CONFIG_BT_MESH_RELAY_ADV_SETS || CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) */ -struct net_buf *bt_mesh_adv_buf_get(k_timeout_t timeout) -{ - return net_buf_get(&bt_mesh_adv_queue, timeout); -} - -struct net_buf *bt_mesh_adv_buf_get_by_tag(enum bt_mesh_adv_tag_bit tags, k_timeout_t timeout) -{ - ARG_UNUSED(tags); - - return bt_mesh_adv_buf_get(timeout); -} -#endif /* CONFIG_BT_MESH_RELAY_ADV_SETS || CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE */ void bt_mesh_adv_buf_get_cancel(void) { @@ -237,9 +225,9 @@ void bt_mesh_adv_buf_get_cancel(void) k_fifo_cancel_wait(&bt_mesh_adv_queue); -#if CONFIG_BT_MESH_RELAY_ADV_SETS - k_fifo_cancel_wait(&bt_mesh_relay_queue); -#endif /* CONFIG_BT_MESH_RELAY_ADV_SETS */ + if (IS_ENABLED(CONFIG_BT_MESH_RELAY)) { + k_fifo_cancel_wait(&bt_mesh_relay_queue); + } if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE)) { k_fifo_cancel_wait(&bt_mesh_friend_queue); @@ -267,15 +255,14 @@ void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, return; } -#if CONFIG_BT_MESH_RELAY_ADV_SETS - if (BT_MESH_ADV(buf)->tag == BT_MESH_ADV_TAG_RELAY || + if ((IS_ENABLED(CONFIG_BT_MESH_RELAY) && + BT_MESH_ADV(buf)->tag == BT_MESH_ADV_TAG_RELAY) || (IS_ENABLED(CONFIG_BT_MESH_PB_ADV_USE_RELAY_SETS) && BT_MESH_ADV(buf)->tag == BT_MESH_ADV_TAG_PROV)) { net_buf_put(&bt_mesh_relay_queue, net_buf_ref(buf)); bt_mesh_adv_buf_relay_ready(); return; } -#endif net_buf_put(&bt_mesh_adv_queue, net_buf_ref(buf)); bt_mesh_adv_buf_local_ready(); diff --git a/subsys/bluetooth/mesh/app_keys.c b/subsys/bluetooth/mesh/app_keys.c index 64677a3386e..a47d31447c5 100644 --- a/subsys/bluetooth/mesh/app_keys.c +++ b/subsys/bluetooth/mesh/app_keys.c @@ -556,7 +556,7 @@ uint16_t bt_mesh_app_key_find(bool dev_key, uint8_t aid, } } - /** Bluetooth Mesh Specification v1.0.1, section 3.4.3: + /** MshPRTv1.1: 3.4.3: * The Device key is only valid for unicast addresses. */ if (BT_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst)) { @@ -569,7 +569,7 @@ uint16_t bt_mesh_app_key_find(bool dev_key, uint8_t aid, if (atomic_test_bit(bt_mesh.flags, BT_MESH_DEVKEY_CAND)) { err = cb(rx, &bt_mesh.dev_key_cand, cb_data); if (!err) { - /* Bluetooth Mesh Specification v1.1.0, section 3.6.4.2: + /* MshPRTv1.1: 3.6.4.2: * If a message is successfully decrypted using the device * key candidate, the device key candidate should * permanently replace the original devkey. diff --git a/subsys/bluetooth/mesh/blob.h b/subsys/bluetooth/mesh/blob.h index d7552934ecb..2898dcd030c 100644 --- a/subsys/bluetooth/mesh/blob.h +++ b/subsys/bluetooth/mesh/blob.h @@ -33,7 +33,7 @@ * * The macros expand to a series of ternary expressions, effectively * searching through power of twos until a match is found. - * According to the specification, the block size cannot be larger than 2^20, + * According to MshMBTv1.0, the block size cannot be larger than 2^20, * so we'll stop the search at 20. */ #define _BLOB_LOG_2_CEIL(l, x) ((x) <= (1U << l)) ? l : diff --git a/subsys/bluetooth/mesh/blob_cli.c b/subsys/bluetooth/mesh/blob_cli.c index e2b0fc68a70..f96a9af0653 100644 --- a/subsys/bluetooth/mesh/blob_cli.c +++ b/subsys/bluetooth/mesh/blob_cli.c @@ -1204,10 +1204,10 @@ static void rx_block_status(struct bt_mesh_blob_cli *cli, blob_cli_broadcast_rsp(cli, target); } -static int handle_xfer_status(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_xfer_status(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_blob_cli *cli = mod->user_data; + struct bt_mesh_blob_cli *cli = mod->rt->user_data; enum bt_mesh_blob_xfer_phase expected_phase; struct bt_mesh_blob_target *target; struct bt_mesh_blob_xfer_info info = { 0 }; @@ -1276,10 +1276,10 @@ static int handle_xfer_status(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx return 0; } -static int handle_block_report(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_block_report(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_blob_cli *cli = mod->user_data; + struct bt_mesh_blob_cli *cli = mod->rt->user_data; struct block_status status = { .status = BT_MESH_BLOB_SUCCESS, .block.number = cli->block.number, @@ -1330,10 +1330,10 @@ static int handle_block_report(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx return 0; } -static int handle_block_status(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_block_status(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_blob_cli *cli = mod->user_data; + struct bt_mesh_blob_cli *cli = mod->rt->user_data; struct bt_mesh_blob_target *target; struct block_status status = { 0 }; uint8_t status_and_format; @@ -1375,8 +1375,8 @@ static int handle_block_status(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx LOG_DBG("Missing: %s", bt_hex(status.block.missing, len)); break; case BT_MESH_BLOB_CHUNKS_MISSING_ENCODED: - /** An empty Missing Chunks field entails that there are no - * missing chunks for this block (Spec 5.3.8) + /** MshMBTv1.0: 5.3.8: An empty Missing Chunks field entails that there are no + * missing chunks for this block. */ if (!buf->len) { status.missing = BT_MESH_BLOB_CHUNKS_MISSING_NONE; @@ -1401,10 +1401,10 @@ static int handle_block_status(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx return 0; } -static int handle_info_status(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_info_status(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_blob_cli *cli = mod->user_data; + struct bt_mesh_blob_cli *cli = mod->rt->user_data; struct bt_mesh_blob_cli_caps caps; enum bt_mesh_blob_status status; struct bt_mesh_blob_target *target; @@ -1458,9 +1458,9 @@ const struct bt_mesh_model_op _bt_mesh_blob_cli_op[] = { BT_MESH_MODEL_OP_END, }; -static int blob_cli_init(struct bt_mesh_model *mod) +static int blob_cli_init(const struct bt_mesh_model *mod) { - struct bt_mesh_blob_cli *cli = mod->user_data; + struct bt_mesh_blob_cli *cli = mod->rt->user_data; cli->mod = mod; @@ -1471,9 +1471,9 @@ static int blob_cli_init(struct bt_mesh_model *mod) return 0; } -static void blob_cli_reset(struct bt_mesh_model *mod) +static void blob_cli_reset(const struct bt_mesh_model *mod) { - struct bt_mesh_blob_cli *cli = mod->user_data; + struct bt_mesh_blob_cli *cli = mod->rt->user_data; cli_state_reset(cli); } diff --git a/subsys/bluetooth/mesh/blob_srv.c b/subsys/bluetooth/mesh/blob_srv.c index 1e6cb9bc91a..3773a17e9af 100644 --- a/subsys/bluetooth/mesh/blob_srv.c +++ b/subsys/bluetooth/mesh/blob_srv.c @@ -415,10 +415,10 @@ static void block_status_rsp(struct bt_mesh_blob_srv *srv, (void)bt_mesh_model_send(srv->mod, ctx, &buf, NULL, NULL); } -static int handle_xfer_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_xfer_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_blob_srv *srv = mod->user_data; + struct bt_mesh_blob_srv *srv = mod->rt->user_data; LOG_DBG(""); @@ -435,10 +435,10 @@ static int handle_xfer_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ct return 0; } -static int handle_xfer_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_xfer_start(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_blob_srv *srv = mod->user_data; + struct bt_mesh_blob_srv *srv = mod->rt->user_data; enum bt_mesh_blob_status status; enum bt_mesh_blob_xfer_mode mode; uint64_t id; @@ -566,11 +566,11 @@ static int handle_xfer_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx * return 0; } -static int handle_xfer_cancel(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_xfer_cancel(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { enum bt_mesh_blob_status status = BT_MESH_BLOB_SUCCESS; - struct bt_mesh_blob_srv *srv = mod->user_data; + struct bt_mesh_blob_srv *srv = mod->rt->user_data; uint64_t id; id = net_buf_simple_pull_le64(buf); @@ -594,11 +594,11 @@ static int handle_xfer_cancel(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx return 0; } -static int handle_block_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_block_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { enum bt_mesh_blob_status status; - struct bt_mesh_blob_srv *srv = mod->user_data; + struct bt_mesh_blob_srv *srv = mod->rt->user_data; switch (srv->phase) { case BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_BLOCK: @@ -625,10 +625,10 @@ static int handle_block_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *c return 0; } -static int handle_block_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_block_start(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_blob_srv *srv = mod->user_data; + struct bt_mesh_blob_srv *srv = mod->rt->user_data; enum bt_mesh_blob_status status; uint16_t block_number, chunk_size; int err; @@ -720,10 +720,10 @@ static int handle_block_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx return 0; } -static int handle_chunk(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_chunk(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_blob_srv *srv = mod->user_data; + struct bt_mesh_blob_srv *srv = mod->rt->user_data; struct bt_mesh_blob_chunk chunk; size_t expected_size = 0; uint16_t idx; @@ -810,10 +810,10 @@ static int handle_chunk(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, return 0; } -static int handle_info_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_info_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_blob_srv *srv = mod->user_data; + struct bt_mesh_blob_srv *srv = mod->rt->user_data; LOG_DBG(""); @@ -847,9 +847,9 @@ const struct bt_mesh_model_op _bt_mesh_blob_srv_op[] = { BT_MESH_MODEL_OP_END, }; -static int blob_srv_init(struct bt_mesh_model *mod) +static int blob_srv_init(const struct bt_mesh_model *mod) { - struct bt_mesh_blob_srv *srv = mod->user_data; + struct bt_mesh_blob_srv *srv = mod->rt->user_data; srv->mod = mod; srv->state.ttl = BT_MESH_TTL_DEFAULT; @@ -861,11 +861,11 @@ static int blob_srv_init(struct bt_mesh_model *mod) return 0; } -static int blob_srv_settings_set(struct bt_mesh_model *mod, const char *name, +static int blob_srv_settings_set(const struct bt_mesh_model *mod, const char *name, size_t len_rd, settings_read_cb read_cb, void *cb_arg) { - struct bt_mesh_blob_srv *srv = mod->user_data; + struct bt_mesh_blob_srv *srv = mod->rt->user_data; ssize_t len; if (len_rd < offsetof(struct bt_mesh_blob_srv_state, blocks)) { @@ -903,9 +903,9 @@ static int blob_srv_settings_set(struct bt_mesh_model *mod, const char *name, return 0; } -static int blob_srv_start(struct bt_mesh_model *mod) +static int blob_srv_start(const struct bt_mesh_model *mod) { - struct bt_mesh_blob_srv *srv = mod->user_data; + struct bt_mesh_blob_srv *srv = mod->rt->user_data; int err = -ENOTSUP; if (srv->phase == BT_MESH_BLOB_XFER_PHASE_INACTIVE) { @@ -931,9 +931,9 @@ static int blob_srv_start(struct bt_mesh_model *mod) return 0; } -static void blob_srv_reset(struct bt_mesh_model *mod) +static void blob_srv_reset(const struct bt_mesh_model *mod) { - struct bt_mesh_blob_srv *srv = mod->user_data; + struct bt_mesh_blob_srv *srv = mod->rt->user_data; phase_set(srv, BT_MESH_BLOB_XFER_PHASE_INACTIVE); srv->state.xfer.mode = BT_MESH_BLOB_XFER_MODE_NONE; diff --git a/subsys/bluetooth/mesh/cfg_cli.c b/subsys/bluetooth/mesh/cfg_cli.c index c9f4f98f39d..aa762e9b906 100644 --- a/subsys/bluetooth/mesh/cfg_cli.c +++ b/subsys/bluetooth/mesh/cfg_cli.c @@ -48,7 +48,7 @@ static int32_t msg_timeout; static struct bt_mesh_cfg_cli *cli; -static int comp_data_status(struct bt_mesh_model *model, +static int comp_data_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -85,7 +85,7 @@ static int comp_data_status(struct bt_mesh_model *model, return 0; } -static uint8_t state_status_u8(struct bt_mesh_model *model, +static uint8_t state_status_u8(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf, uint32_t expect_status) @@ -111,7 +111,7 @@ static uint8_t state_status_u8(struct bt_mesh_model *model, return status; } -static int beacon_status(struct bt_mesh_model *model, +static int beacon_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -126,7 +126,7 @@ static int beacon_status(struct bt_mesh_model *model, return 0; } -static int ttl_status(struct bt_mesh_model *model, +static int ttl_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -141,7 +141,7 @@ static int ttl_status(struct bt_mesh_model *model, return 0; } -static int friend_status(struct bt_mesh_model *model, +static int friend_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -156,7 +156,7 @@ static int friend_status(struct bt_mesh_model *model, return 0; } -static int gatt_proxy_status(struct bt_mesh_model *model, +static int gatt_proxy_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -178,7 +178,7 @@ struct krp_param { uint8_t *phase; }; -static int krp_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int krp_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { int err = 0; @@ -223,7 +223,7 @@ struct relay_param { uint8_t *transmit; }; -static int relay_status(struct bt_mesh_model *model, +static int relay_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -257,7 +257,7 @@ static int relay_status(struct bt_mesh_model *model, return 0; } -static int net_transmit_status(struct bt_mesh_model *model, +static int net_transmit_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -277,7 +277,7 @@ struct net_key_param { uint16_t net_idx; }; -static int net_key_status(struct bt_mesh_model *model, +static int net_key_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -345,7 +345,7 @@ int bt_mesh_key_idx_unpack_list(struct net_buf_simple *buf, uint16_t *dst_arr, return buf->len > 0 ? -EMSGSIZE : 0; } -static int net_key_list(struct bt_mesh_model *model, +static int net_key_list(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -381,7 +381,7 @@ static int net_key_list(struct bt_mesh_model *model, return err; } -static int node_reset_status(struct bt_mesh_model *model, +static int node_reset_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -412,7 +412,7 @@ struct app_key_param { uint16_t app_idx; }; -static int app_key_status(struct bt_mesh_model *model, +static int app_key_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -461,7 +461,7 @@ struct app_key_list_param { size_t *key_cnt; }; -static int app_key_list(struct bt_mesh_model *model, +static int app_key_list(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -521,7 +521,7 @@ struct mod_app_param { uint16_t cid; }; -static int mod_app_status(struct bt_mesh_model *model, +static int mod_app_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -695,7 +695,7 @@ static int mod_app_list_handle(struct bt_mesh_msg_ctx *ctx, struct net_buf_simpl return err; } -static int mod_app_list(struct bt_mesh_model *model, +static int mod_app_list(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { LOG_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, @@ -704,7 +704,7 @@ static int mod_app_list(struct bt_mesh_model *model, return mod_app_list_handle(ctx, buf, OP_SIG_MOD_APP_LIST, false); } -static int mod_app_list_vnd(struct bt_mesh_model *model, +static int mod_app_list_vnd(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -722,7 +722,7 @@ struct mod_pub_param { struct bt_mesh_cfg_cli_mod_pub *pub; }; -static int mod_pub_status(struct bt_mesh_model *model, +static int mod_pub_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -807,7 +807,7 @@ struct mod_sub_param { uint16_t cid; }; -static int mod_sub_status(struct bt_mesh_model *model, +static int mod_sub_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -866,7 +866,7 @@ static int mod_sub_status(struct bt_mesh_model *model, return err; } -static int mod_sub_list(struct bt_mesh_model *model, +static int mod_sub_list(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { LOG_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, @@ -875,7 +875,7 @@ static int mod_sub_list(struct bt_mesh_model *model, return mod_sub_list_handle(ctx, buf, OP_MOD_SUB_LIST, false); } -static int mod_sub_list_vnd(struct bt_mesh_model *model, +static int mod_sub_list_vnd(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -890,7 +890,7 @@ struct hb_sub_param { struct bt_mesh_cfg_cli_hb_sub *sub; }; -static int hb_sub_status(struct bt_mesh_model *model, +static int hb_sub_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -934,7 +934,7 @@ struct hb_pub_param { struct bt_mesh_cfg_cli_hb_pub *pub; }; -static int hb_pub_status(struct bt_mesh_model *model, +static int hb_pub_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -950,8 +950,8 @@ static int hb_pub_status(struct bt_mesh_model *model, pub.count = net_buf_simple_pull_u8(buf); pub.period = net_buf_simple_pull_u8(buf); pub.ttl = net_buf_simple_pull_u8(buf); - pub.feat = net_buf_simple_pull_u8(buf); - pub.net_idx = net_buf_simple_pull_u8(buf); + pub.feat = net_buf_simple_pull_le16(buf); + pub.net_idx = net_buf_simple_pull_le16(buf) & 0xfff; if (bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_HEARTBEAT_PUB_STATUS, ctx->addr, (void **)¶m)) { @@ -979,7 +979,7 @@ struct node_idt_param { uint8_t *identity; }; -static int node_identity_status(struct bt_mesh_model *model, +static int node_identity_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1020,7 +1020,7 @@ struct lpn_timeout_param { int32_t *polltimeout; }; -static int lpn_timeout_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int lpn_timeout_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { struct lpn_timeout_param *param; @@ -1087,19 +1087,19 @@ const struct bt_mesh_model_op bt_mesh_cfg_cli_op[] = { BT_MESH_MODEL_OP_END, }; -static int cfg_cli_init(struct bt_mesh_model *model) +static int cfg_cli_init(const struct bt_mesh_model *model) { if (!bt_mesh_model_in_primary(model)) { LOG_ERR("Configuration Client only allowed in primary element"); return -EINVAL; } - if (!model->user_data) { + if (!model->rt->user_data) { LOG_ERR("No Configuration Client context provided"); return -EINVAL; } - cli = model->user_data; + cli = model->rt->user_data; cli->model = model; msg_timeout = CONFIG_BT_MESH_CFG_CLI_TIMEOUT; @@ -1108,7 +1108,7 @@ static int cfg_cli_init(struct bt_mesh_model *model) * and remote keys are allowed to access this model. */ model->keys[0] = BT_MESH_KEY_DEV_ANY; - model->flags |= BT_MESH_MOD_DEVKEY_ONLY; + model->rt->flags |= BT_MESH_MOD_DEVKEY_ONLY; bt_mesh_msg_ack_ctx_init(&cli->ack_ctx); diff --git a/subsys/bluetooth/mesh/cfg_srv.c b/subsys/bluetooth/mesh/cfg_srv.c index f65d2cba3c7..fa6bb48703a 100644 --- a/subsys/bluetooth/mesh/cfg_srv.c +++ b/subsys/bluetooth/mesh/cfg_srv.c @@ -48,7 +48,7 @@ static void node_reset_pending_handler(struct k_work *work) static K_WORK_DEFINE(node_reset_pending, node_reset_pending_handler); -static int dev_comp_data_get(struct bt_mesh_model *model, +static int dev_comp_data_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -86,7 +86,7 @@ static int dev_comp_data_get(struct bt_mesh_model *model, return err; } -static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem, +static const struct bt_mesh_model *get_model(const struct bt_mesh_elem *elem, struct net_buf_simple *buf, bool *vnd) { if (buf->len < 4) { @@ -94,7 +94,7 @@ static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem, id = net_buf_simple_pull_le16(buf); - LOG_DBG("ID 0x%04x addr 0x%04x", id, elem->addr); + LOG_DBG("ID 0x%04x addr 0x%04x", id, elem->rt->addr); *vnd = false; @@ -105,7 +105,7 @@ static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem, company = net_buf_simple_pull_le16(buf); id = net_buf_simple_pull_le16(buf); - LOG_DBG("Company 0x%04x ID 0x%04x addr 0x%04x", company, id, elem->addr); + LOG_DBG("Company 0x%04x ID 0x%04x addr 0x%04x", company, id, elem->rt->addr); *vnd = true; @@ -113,9 +113,9 @@ static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem, } } -static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr, const uint8_t *uuid, - uint16_t app_idx, uint8_t cred_flag, uint8_t ttl, uint8_t period, - uint8_t retransmit, bool store) +static uint8_t _mod_pub_set(const struct bt_mesh_model *model, uint16_t pub_addr, + const uint8_t *uuid, uint16_t app_idx, uint8_t cred_flag, + uint8_t ttl, uint8_t period, uint8_t retransmit, bool store) { if (!model->pub) { return STATUS_NVAL_PUB_PARAM; @@ -199,7 +199,7 @@ static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr, cons return STATUS_SUCCESS; } -static uint8_t mod_bind(struct bt_mesh_model *model, uint16_t key_idx) +static uint8_t mod_bind(const struct bt_mesh_model *model, uint16_t key_idx) { int i; @@ -232,7 +232,7 @@ static uint8_t mod_bind(struct bt_mesh_model *model, uint16_t key_idx) return STATUS_INSUFF_RESOURCES; } -static uint8_t mod_unbind(struct bt_mesh_model *model, uint16_t key_idx, bool store) +static uint8_t mod_unbind(const struct bt_mesh_model *model, uint16_t key_idx, bool store) { int i; @@ -284,7 +284,7 @@ static void key_idx_pack_list(struct net_buf_simple *buf, uint16_t *arr, size_t } -static int send_app_key_status(struct bt_mesh_model *model, +static int send_app_key_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, uint8_t status, uint16_t app_idx, uint16_t net_idx) @@ -302,7 +302,7 @@ static int send_app_key_status(struct bt_mesh_model *model, return 0; } -static int app_key_add(struct bt_mesh_model *model, +static int app_key_add(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -318,7 +318,7 @@ static int app_key_add(struct bt_mesh_model *model, return send_app_key_status(model, ctx, status, key_app_idx, key_net_idx); } -static int app_key_update(struct bt_mesh_model *model, +static int app_key_update(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -335,8 +335,8 @@ static int app_key_update(struct bt_mesh_model *model, return send_app_key_status(model, ctx, status, key_app_idx, key_net_idx); } -static void mod_app_key_del(struct bt_mesh_model *mod, - struct bt_mesh_elem *elem, bool vnd, bool primary, +static void mod_app_key_del(const struct bt_mesh_model *mod, + const struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data) { uint16_t *app_idx = user_data; @@ -354,7 +354,7 @@ static void app_key_evt(uint16_t app_idx, uint16_t net_idx, BT_MESH_APP_KEY_CB_DEFINE(app_key_evt); -static int app_key_del(struct bt_mesh_model *model, +static int app_key_del(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -373,7 +373,7 @@ static int app_key_del(struct bt_mesh_model *model, /* Index list length: 3 bytes for every pair and 2 bytes for an odd idx */ #define IDX_LEN(num) (((num) / 2) * 3 + ((num) % 2) * 2) -static int app_key_get(struct bt_mesh_model *model, +static int app_key_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -422,7 +422,7 @@ static int app_key_get(struct bt_mesh_model *model, return 0; } -static int beacon_get(struct bt_mesh_model *model, +static int beacon_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -441,7 +441,7 @@ static int beacon_get(struct bt_mesh_model *model, return 0; } -static int beacon_set(struct bt_mesh_model *model, +static int beacon_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -467,7 +467,7 @@ static int beacon_set(struct bt_mesh_model *model, return 0; } -static int default_ttl_get(struct bt_mesh_model *model, +static int default_ttl_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -486,7 +486,7 @@ static int default_ttl_get(struct bt_mesh_model *model, return 0; } -static int default_ttl_set(struct bt_mesh_model *model, +static int default_ttl_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -512,7 +512,7 @@ static int default_ttl_set(struct bt_mesh_model *model, return 0; } -static int send_gatt_proxy_status(struct bt_mesh_model *model, +static int send_gatt_proxy_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx) { BT_MESH_MODEL_BUF_DEFINE(msg, OP_GATT_PROXY_STATUS, 1); @@ -527,7 +527,7 @@ static int send_gatt_proxy_status(struct bt_mesh_model *model, return 0; } -static int gatt_proxy_get(struct bt_mesh_model *model, +static int gatt_proxy_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -537,7 +537,7 @@ static int gatt_proxy_get(struct bt_mesh_model *model, return send_gatt_proxy_status(model, ctx); } -static int gatt_proxy_set(struct bt_mesh_model *model, +static int gatt_proxy_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -561,7 +561,7 @@ static int gatt_proxy_set(struct bt_mesh_model *model, return send_gatt_proxy_status(model, ctx); } -static int net_transmit_get(struct bt_mesh_model *model, +static int net_transmit_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -580,7 +580,7 @@ static int net_transmit_get(struct bt_mesh_model *model, return 0; } -static int net_transmit_set(struct bt_mesh_model *model, +static int net_transmit_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -604,7 +604,7 @@ static int net_transmit_set(struct bt_mesh_model *model, return 0; } -static int relay_get(struct bt_mesh_model *model, +static int relay_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -624,7 +624,7 @@ static int relay_get(struct bt_mesh_model *model, return 0; } -static int relay_set(struct bt_mesh_model *model, +static int relay_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -651,10 +651,10 @@ static int relay_set(struct bt_mesh_model *model, return 0; } -static int send_mod_pub_status(struct bt_mesh_model *cfg_mod, +static int send_mod_pub_status(const struct bt_mesh_model *cfg_mod, struct bt_mesh_msg_ctx *ctx, uint16_t elem_addr, uint16_t pub_addr, bool vnd, - struct bt_mesh_model *mod, uint8_t status, + const struct bt_mesh_model *mod, uint8_t status, uint8_t *mod_id) { BT_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_PUB_STATUS, 14); @@ -691,12 +691,12 @@ static int send_mod_pub_status(struct bt_mesh_model *cfg_mod, return 0; } -static int mod_pub_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int mod_pub_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { uint16_t elem_addr, pub_addr = 0U; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; + const struct bt_mesh_model *mod; + const struct bt_mesh_elem *elem; uint8_t *mod_id, status; bool vnd; @@ -742,14 +742,14 @@ static int mod_pub_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, status, mod_id); } -static int mod_pub_set(struct bt_mesh_model *model, +static int mod_pub_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { uint8_t retransmit, status, pub_ttl, pub_period, cred_flag; uint16_t elem_addr, pub_addr, pub_app_idx; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; + const struct bt_mesh_model *mod; + const struct bt_mesh_elem *elem; uint8_t *mod_id; bool vnd; @@ -807,7 +807,7 @@ static int mod_pub_set(struct bt_mesh_model *model, status, mod_id); } -static size_t mod_sub_list_clear(struct bt_mesh_model *mod) +static size_t mod_sub_list_clear(const struct bt_mesh_model *mod) { size_t clear_count; int i; @@ -838,7 +838,7 @@ static size_t mod_sub_list_clear(struct bt_mesh_model *mod) return clear_count; } -static int mod_pub_va_set(struct bt_mesh_model *model, +static int mod_pub_va_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -846,8 +846,8 @@ static int mod_pub_va_set(struct bt_mesh_model *model, uint8_t retransmit, status, pub_ttl, pub_period, cred_flag; uint16_t elem_addr, pub_app_idx; uint16_t pub_addr = 0U; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; + const struct bt_mesh_model *mod; + const struct bt_mesh_elem *elem; const uint8_t *uuid; uint8_t *mod_id; bool vnd; @@ -915,7 +915,7 @@ static int mod_pub_va_set(struct bt_mesh_model *model, status, mod_id); } -static int send_mod_sub_status(struct bt_mesh_model *model, +static int send_mod_sub_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, uint8_t status, uint16_t elem_addr, uint16_t sub_addr, uint8_t *mod_id, bool vnd) @@ -943,13 +943,13 @@ static int send_mod_sub_status(struct bt_mesh_model *model, return 0; } -static int mod_sub_add(struct bt_mesh_model *model, +static int mod_sub_add(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { uint16_t elem_addr, sub_addr; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; + const struct bt_mesh_model *mod; + const struct bt_mesh_elem *elem; uint8_t *mod_id; uint8_t status; uint16_t *entry; @@ -1021,13 +1021,13 @@ static int mod_sub_add(struct bt_mesh_model *model, mod_id, vnd); } -static int mod_sub_del(struct bt_mesh_model *model, +static int mod_sub_del(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { uint16_t elem_addr, sub_addr; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; + const struct bt_mesh_model *mod; + const struct bt_mesh_elem *elem; uint8_t *mod_id; uint16_t *match; uint8_t status; @@ -1092,7 +1092,7 @@ static int mod_sub_del(struct bt_mesh_model *model, mod_id, vnd); } -static enum bt_mesh_walk mod_sub_clear_visitor(struct bt_mesh_model *mod, void *user_data) +static enum bt_mesh_walk mod_sub_clear_visitor(const struct bt_mesh_model *mod, void *user_data) { if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) { bt_mesh_lpn_group_del(mod->groups, mod->groups_cnt); @@ -1103,13 +1103,13 @@ static enum bt_mesh_walk mod_sub_clear_visitor(struct bt_mesh_model *mod, void * return BT_MESH_WALK_CONTINUE; } -static int mod_sub_overwrite(struct bt_mesh_model *model, +static int mod_sub_overwrite(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { uint16_t elem_addr, sub_addr; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; + const struct bt_mesh_model *mod; + const struct bt_mesh_elem *elem; uint8_t *mod_id; uint8_t status; bool vnd; @@ -1174,12 +1174,12 @@ static int mod_sub_overwrite(struct bt_mesh_model *model, mod_id, vnd); } -static int mod_sub_del_all(struct bt_mesh_model *model, +static int mod_sub_del_all(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; + const struct bt_mesh_model *mod; + const struct bt_mesh_elem *elem; uint16_t elem_addr; uint8_t *mod_id; uint8_t status; @@ -1232,13 +1232,13 @@ struct mod_sub_list_ctx { struct net_buf_simple *msg; }; -static enum bt_mesh_walk mod_sub_list_visitor(struct bt_mesh_model *mod, void *ctx) +static enum bt_mesh_walk mod_sub_list_visitor(const struct bt_mesh_model *mod, void *ctx) { struct mod_sub_list_ctx *visit = ctx; int count = 0; int i; - if (mod->elem_idx != visit->elem_idx) { + if (mod->rt->elem_idx != visit->elem_idx) { return BT_MESH_WALK_CONTINUE; } @@ -1257,19 +1257,19 @@ static enum bt_mesh_walk mod_sub_list_visitor(struct bt_mesh_model *mod, void *c count++; } - LOG_DBG("sublist: model %u:%x: %u groups", mod->elem_idx, mod->id, count); + LOG_DBG("sublist: model %u:%x: %u groups", mod->rt->elem_idx, mod->id, count); return BT_MESH_WALK_CONTINUE; } -static int mod_sub_get(struct bt_mesh_model *model, +static int mod_sub_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { NET_BUF_SIMPLE_DEFINE(msg, BT_MESH_TX_SDU_MAX); struct mod_sub_list_ctx visit_ctx; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; + const struct bt_mesh_model *mod; + const struct bt_mesh_elem *elem; uint16_t addr, id; addr = net_buf_simple_pull_le16(buf); @@ -1306,7 +1306,7 @@ static int mod_sub_get(struct bt_mesh_model *model, net_buf_simple_add_le16(&msg, id); visit_ctx.msg = &msg; - visit_ctx.elem_idx = mod->elem_idx; + visit_ctx.elem_idx = mod->rt->elem_idx; bt_mesh_model_extensions_walk(mod, mod_sub_list_visitor, &visit_ctx); send_list: @@ -1317,14 +1317,14 @@ static int mod_sub_get(struct bt_mesh_model *model, return 0; } -static int mod_sub_get_vnd(struct bt_mesh_model *model, +static int mod_sub_get_vnd(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { NET_BUF_SIMPLE_DEFINE(msg, BT_MESH_TX_SDU_MAX); struct mod_sub_list_ctx visit_ctx; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; + const struct bt_mesh_model *mod; + const struct bt_mesh_elem *elem; uint16_t company, addr, id; addr = net_buf_simple_pull_le16(buf); @@ -1365,7 +1365,7 @@ static int mod_sub_get_vnd(struct bt_mesh_model *model, net_buf_simple_add_le16(&msg, id); visit_ctx.msg = &msg; - visit_ctx.elem_idx = mod->elem_idx; + visit_ctx.elem_idx = mod->rt->elem_idx; bt_mesh_model_extensions_walk(mod, mod_sub_list_visitor, &visit_ctx); send_list: @@ -1376,14 +1376,14 @@ static int mod_sub_get_vnd(struct bt_mesh_model *model, return 0; } -static int mod_sub_va_add(struct bt_mesh_model *model, +static int mod_sub_va_add(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { const struct bt_mesh_va *va; uint16_t elem_addr, sub_addr = BT_MESH_ADDR_UNASSIGNED; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; + const struct bt_mesh_model *mod; + const struct bt_mesh_elem *elem; const uint8_t *uuid; uint8_t *mod_id; uint16_t *group_entry; @@ -1478,14 +1478,14 @@ static int mod_sub_va_add(struct bt_mesh_model *model, mod_id, vnd); } -static int mod_sub_va_del(struct bt_mesh_model *model, +static int mod_sub_va_del(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { const struct bt_mesh_va *va; uint16_t elem_addr, sub_addr = BT_MESH_ADDR_UNASSIGNED; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; + const struct bt_mesh_model *mod; + const struct bt_mesh_elem *elem; const uint8_t *uuid; uint8_t *mod_id; const uint8_t **label_match; @@ -1562,14 +1562,14 @@ static int mod_sub_va_del(struct bt_mesh_model *model, mod_id, vnd); } -static int mod_sub_va_overwrite(struct bt_mesh_model *model, +static int mod_sub_va_overwrite(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { const struct bt_mesh_va *va; uint16_t elem_addr, sub_addr = BT_MESH_ADDR_UNASSIGNED; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; + const struct bt_mesh_model *mod; + const struct bt_mesh_elem *elem; const uint8_t *uuid; uint8_t *mod_id; uint8_t status; @@ -1638,7 +1638,7 @@ static int mod_sub_va_overwrite(struct bt_mesh_model *model, mod_id, vnd); } -static int send_net_key_status(struct bt_mesh_model *model, +static int send_net_key_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, uint16_t idx, uint8_t status) { @@ -1656,7 +1656,7 @@ static int send_net_key_status(struct bt_mesh_model *model, return 0; } -static int net_key_add(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int net_key_add(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { uint8_t status; @@ -1675,7 +1675,7 @@ static int net_key_add(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, return send_net_key_status(model, ctx, idx, status); } -static int net_key_update(struct bt_mesh_model *model, +static int net_key_update(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1693,7 +1693,7 @@ static int net_key_update(struct bt_mesh_model *model, return send_net_key_status(model, ctx, idx, status); } -static int net_key_del(struct bt_mesh_model *model, +static int net_key_del(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1720,7 +1720,7 @@ static int net_key_del(struct bt_mesh_model *model, return send_net_key_status(model, ctx, del_idx, STATUS_SUCCESS); } -static int net_key_get(struct bt_mesh_model *model, +static int net_key_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1745,7 +1745,7 @@ static int net_key_get(struct bt_mesh_model *model, return 0; } -static int send_node_id_status(struct bt_mesh_model *model, +static int send_node_id_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, uint8_t status, uint16_t net_idx, uint8_t node_id) @@ -1764,7 +1764,7 @@ static int send_node_id_status(struct bt_mesh_model *model, return 0; } -static int node_identity_get(struct bt_mesh_model *model, +static int node_identity_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1786,7 +1786,7 @@ static int node_identity_get(struct bt_mesh_model *model, return send_node_id_status(model, ctx, status, idx, node_id); } -static int node_identity_set(struct bt_mesh_model *model, +static int node_identity_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1824,7 +1824,7 @@ static int node_identity_set(struct bt_mesh_model *model, } static void create_mod_app_status(struct net_buf_simple *msg, - struct bt_mesh_model *mod, bool vnd, + const struct bt_mesh_model *mod, bool vnd, uint16_t elem_addr, uint16_t app_idx, uint8_t status, uint8_t *mod_id) { @@ -1841,14 +1841,14 @@ static void create_mod_app_status(struct net_buf_simple *msg, } } -static int mod_app_bind(struct bt_mesh_model *model, +static int mod_app_bind(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { BT_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_APP_STATUS, 9); uint16_t elem_addr, key_app_idx; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; + const struct bt_mesh_model *mod; + const struct bt_mesh_elem *elem; uint8_t *mod_id, status; bool vnd; @@ -1881,7 +1881,7 @@ static int mod_app_bind(struct bt_mesh_model *model, } /* Some models only allow device key based access */ - if (mod->flags & BT_MESH_MOD_DEVKEY_ONLY) { + if (mod->rt->flags & BT_MESH_MOD_DEVKEY_ONLY) { LOG_ERR("Client tried to bind AppKey to DevKey based model"); status = STATUS_CANNOT_BIND; goto send_status; @@ -1905,14 +1905,14 @@ static int mod_app_bind(struct bt_mesh_model *model, return 0; } -static int mod_app_unbind(struct bt_mesh_model *model, +static int mod_app_unbind(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { BT_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_APP_STATUS, 9); uint16_t elem_addr, key_app_idx; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; + const struct bt_mesh_model *mod; + const struct bt_mesh_elem *elem; uint8_t *mod_id, status; bool vnd; @@ -1964,7 +1964,7 @@ static int mod_app_unbind(struct bt_mesh_model *model, #define KEY_LIST_LEN (CONFIG_BT_MESH_MODEL_KEY_COUNT * 2) -static int mod_app_get(struct bt_mesh_model *model, +static int mod_app_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1973,8 +1973,8 @@ static int mod_app_get(struct bt_mesh_model *model, 9 + KEY_LIST_LEN), BT_MESH_MODEL_BUF_LEN(OP_SIG_MOD_APP_LIST, 9 + KEY_LIST_LEN))); - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; + const struct bt_mesh_model *mod; + const struct bt_mesh_elem *elem; uint8_t *mod_id, status; uint16_t elem_addr; bool vnd; @@ -2050,7 +2050,7 @@ static void reset_send_end(int err, void *cb_data) k_work_submit(&node_reset_pending); } -static int node_reset(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int node_reset(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { static const struct bt_mesh_send_cb reset_cb = { @@ -2072,7 +2072,7 @@ static int node_reset(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, return 0; } -static int send_friend_status(struct bt_mesh_model *model, +static int send_friend_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx) { BT_MESH_MODEL_BUF_DEFINE(msg, OP_FRIEND_STATUS, 1); @@ -2087,7 +2087,7 @@ static int send_friend_status(struct bt_mesh_model *model, return 0; } -static int friend_get(struct bt_mesh_model *model, +static int friend_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2097,7 +2097,7 @@ static int friend_get(struct bt_mesh_model *model, return send_friend_status(model, ctx); } -static int friend_set(struct bt_mesh_model *model, +static int friend_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2114,7 +2114,7 @@ static int friend_set(struct bt_mesh_model *model, return send_friend_status(model, ctx); } -static int lpn_timeout_get(struct bt_mesh_model *model, +static int lpn_timeout_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2160,7 +2160,7 @@ static int lpn_timeout_get(struct bt_mesh_model *model, return 0; } -static int send_krp_status(struct bt_mesh_model *model, +static int send_krp_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, uint16_t idx, uint8_t phase, uint8_t status) { @@ -2179,7 +2179,7 @@ static int send_krp_status(struct bt_mesh_model *model, return 0; } -static int krp_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int krp_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { uint8_t kr_phase, status; @@ -2198,7 +2198,7 @@ static int krp_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, return send_krp_status(model, ctx, idx, kr_phase, status); } -static int krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int krp_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { uint8_t phase, status; @@ -2254,7 +2254,7 @@ struct hb_pub_param { uint16_t net_idx; } __packed; -static int hb_pub_send_status(struct bt_mesh_model *model, +static int hb_pub_send_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, uint8_t status, const struct bt_mesh_hb_pub *pub) { @@ -2267,11 +2267,15 @@ static int hb_pub_send_status(struct bt_mesh_model *model, net_buf_simple_add_u8(&msg, status); net_buf_simple_add_le16(&msg, pub->dst); - net_buf_simple_add_u8(&msg, hb_pub_count_log(pub->count)); - net_buf_simple_add_u8(&msg, bt_mesh_hb_log(pub->period)); - net_buf_simple_add_u8(&msg, pub->ttl); - net_buf_simple_add_le16(&msg, pub->feat); - net_buf_simple_add_le16(&msg, pub->net_idx); + if (pub->dst == BT_MESH_ADDR_UNASSIGNED) { + (void)memset(net_buf_simple_add(&msg, 7), 0, 7); + } else { + net_buf_simple_add_u8(&msg, hb_pub_count_log(pub->count)); + net_buf_simple_add_u8(&msg, bt_mesh_hb_log(pub->period)); + net_buf_simple_add_u8(&msg, pub->ttl); + net_buf_simple_add_le16(&msg, pub->feat); + net_buf_simple_add_le16(&msg, pub->net_idx & 0xfff); + } if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) { LOG_ERR("Unable to send Heartbeat Publication Status"); @@ -2280,7 +2284,7 @@ static int hb_pub_send_status(struct bt_mesh_model *model, return 0; } -static int heartbeat_pub_get(struct bt_mesh_model *model, +static int heartbeat_pub_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2293,7 +2297,7 @@ static int heartbeat_pub_get(struct bt_mesh_model *model, return hb_pub_send_status(model, ctx, STATUS_SUCCESS, &pub); } -static int heartbeat_pub_set(struct bt_mesh_model *model, +static int heartbeat_pub_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2305,7 +2309,7 @@ static int heartbeat_pub_set(struct bt_mesh_model *model, pub.dst = sys_le16_to_cpu(param->dst); if (param->count_log == 0x11) { - /* Special case defined in Mesh Profile Errata 11737 */ + /* Special case defined in MshPRFv1.1 Errata 11737 */ pub.count = 0xfffe; } else { pub.count = bt_mesh_hb_pwr2(param->count_log); @@ -2353,7 +2357,7 @@ static int heartbeat_pub_set(struct bt_mesh_model *model, return hb_pub_send_status(model, ctx, status, &pub); } -static int hb_sub_send_status(struct bt_mesh_model *model, +static int hb_sub_send_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, const struct bt_mesh_hb_sub *sub) { @@ -2378,7 +2382,7 @@ static int hb_sub_send_status(struct bt_mesh_model *model, return 0; } -static int heartbeat_sub_get(struct bt_mesh_model *model, +static int heartbeat_sub_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2391,7 +2395,7 @@ static int heartbeat_sub_get(struct bt_mesh_model *model, return hb_sub_send_status(model, ctx, &sub); } -static int heartbeat_sub_set(struct bt_mesh_model *model, +static int heartbeat_sub_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -2504,7 +2508,7 @@ const struct bt_mesh_model_op bt_mesh_cfg_srv_op[] = { BT_MESH_MODEL_OP_END, }; -static int cfg_srv_init(struct bt_mesh_model *model) +static int cfg_srv_init(const struct bt_mesh_model *model) { if (!bt_mesh_model_in_primary(model)) { LOG_ERR("Configuration Server only allowed in primary element"); @@ -2516,7 +2520,7 @@ static int cfg_srv_init(struct bt_mesh_model *model) * device-key is allowed to access this model. */ model->keys[0] = BT_MESH_KEY_DEV_LOCAL; - model->flags |= BT_MESH_MOD_DEVKEY_ONLY; + model->rt->flags |= BT_MESH_MOD_DEVKEY_ONLY; return 0; } @@ -2525,7 +2529,7 @@ const struct bt_mesh_model_cb bt_mesh_cfg_srv_cb = { .init = cfg_srv_init, }; -static void mod_reset(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, +static void mod_reset(const struct bt_mesh_model *mod, const struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data) { size_t clear_count; diff --git a/subsys/bluetooth/mesh/dfd_srv.c b/subsys/bluetooth/mesh/dfd_srv.c index 0a9ecba6cec..54184acd9b8 100644 --- a/subsys/bluetooth/mesh/dfd_srv.c +++ b/subsys/bluetooth/mesh/dfd_srv.c @@ -112,11 +112,11 @@ static void receivers_status_rsp(struct bt_mesh_dfd_srv *srv, bt_mesh_model_send(srv->mod, ctx, &buf, NULL, NULL); } -static int handle_receivers_add(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_receivers_add(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { enum bt_mesh_dfd_status status = BT_MESH_DFD_SUCCESS; - struct bt_mesh_dfd_srv *srv = mod->user_data; + struct bt_mesh_dfd_srv *srv = mod->rt->user_data; if (buf->len % 3) { return -EINVAL; @@ -143,20 +143,20 @@ static int handle_receivers_add(struct bt_mesh_model *mod, struct bt_mesh_msg_ct return 0; } -static int handle_receivers_delete_all(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_receivers_delete_all(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfd_srv *srv = mod->user_data; + struct bt_mesh_dfd_srv *srv = mod->rt->user_data; receivers_status_rsp(srv, ctx, bt_mesh_dfd_srv_receivers_delete_all(srv)); return 0; } -static int handle_receivers_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_receivers_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfd_srv *srv = mod->user_data; + struct bt_mesh_dfd_srv *srv = mod->rt->user_data; uint16_t first, cnt; uint8_t progress; int i; @@ -206,7 +206,7 @@ static enum bt_mesh_dfu_iter slot_space_cb(const struct bt_mesh_dfu_slot *slot, return BT_MESH_DFU_ITER_CONTINUE; } -static int handle_capabilities_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_capabilities_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { size_t size = 0; @@ -226,7 +226,7 @@ static int handle_capabilities_get(struct bt_mesh_model *mod, struct bt_mesh_msg net_buf_simple_add_le32(&rsp, CONFIG_BT_MESH_DFD_SRV_SLOT_SPACE - size); #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD - struct bt_mesh_dfd_srv *srv = mod->user_data; + struct bt_mesh_dfd_srv *srv = mod->rt->user_data; if (srv->oob_schemes.count > 0) { net_buf_simple_add_u8(&rsp, 1); @@ -268,20 +268,20 @@ static void status_rsp(struct bt_mesh_dfd_srv *srv, struct bt_mesh_msg_ctx *ctx, bt_mesh_model_send(srv->mod, ctx, &rsp, NULL, NULL); } -static int handle_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfd_srv *srv = mod->user_data; + struct bt_mesh_dfd_srv *srv = mod->rt->user_data; status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS); return 0; } -static int handle_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_start(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfd_srv *srv = mod->user_data; + struct bt_mesh_dfd_srv *srv = mod->rt->user_data; struct bt_mesh_dfd_start_params params; uint8_t byte; @@ -310,31 +310,31 @@ static int handle_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, return 0; } -static int handle_suspend(struct bt_mesh_model *mod, +static int handle_suspend(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfd_srv *srv = mod->user_data; + struct bt_mesh_dfd_srv *srv = mod->rt->user_data; status_rsp(srv, ctx, bt_mesh_dfd_srv_suspend(srv)); return 0; } -static int handle_cancel(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_cancel(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfd_srv *srv = mod->user_data; + struct bt_mesh_dfd_srv *srv = mod->rt->user_data; bt_mesh_dfd_srv_cancel(srv, ctx); return 0; } -static int handle_apply(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_apply(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfd_srv *srv = mod->user_data; + struct bt_mesh_dfd_srv *srv = mod->rt->user_data; status_rsp(srv, ctx, bt_mesh_dfd_srv_apply(srv)); @@ -393,10 +393,10 @@ static void upload_status_rsp(struct bt_mesh_dfd_srv *srv, upload_status_rsp_with_progress(srv, ctx, status, progress); } -static int handle_upload_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_upload_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfd_srv *srv = mod->user_data; + struct bt_mesh_dfd_srv *srv = mod->rt->user_data; upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS); @@ -438,10 +438,10 @@ static inline int set_upload_fwid(struct bt_mesh_dfd_srv *srv, struct bt_mesh_ms return err; } -static int handle_upload_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_upload_start(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfd_srv *srv = mod->user_data; + struct bt_mesh_dfd_srv *srv = mod->rt->user_data; size_t meta_len, fwid_len, size; const uint8_t *meta, *fwid; uint16_t timeout_base; @@ -560,10 +560,10 @@ static int handle_upload_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx return 0; } -static int handle_upload_start_oob(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_upload_start_oob(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfd_srv *srv = mod->user_data; + struct bt_mesh_dfd_srv *srv = mod->rt->user_data; uint8_t uri_len; uint8_t *uri; uint16_t fwid_len; @@ -651,10 +651,10 @@ static int handle_upload_start_oob(struct bt_mesh_model *mod, struct bt_mesh_msg return 0; } -static int handle_upload_cancel(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_upload_cancel(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfd_srv *srv = mod->user_data; + struct bt_mesh_dfd_srv *srv = mod->rt->user_data; srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_IDLE; #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD @@ -690,10 +690,10 @@ static void fw_status_rsp(struct bt_mesh_dfd_srv *srv, bt_mesh_model_send(srv->mod, ctx, &rsp, NULL, NULL); } -static int handle_fw_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_fw_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfd_srv *srv = mod->user_data; + struct bt_mesh_dfd_srv *srv = mod->rt->user_data; struct bt_mesh_dfu_slot *slot; const uint8_t *fwid; size_t fwid_len; @@ -714,10 +714,10 @@ static int handle_fw_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, return 0; } -static int handle_fw_get_by_index(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_fw_get_by_index(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfd_srv *srv = mod->user_data; + struct bt_mesh_dfd_srv *srv = mod->rt->user_data; const struct bt_mesh_dfu_slot *slot; uint16_t idx; @@ -735,10 +735,10 @@ static int handle_fw_get_by_index(struct bt_mesh_model *mod, struct bt_mesh_msg_ return 0; } -static int handle_fw_delete(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_fw_delete(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfd_srv *srv = mod->user_data; + struct bt_mesh_dfd_srv *srv = mod->rt->user_data; const uint8_t *fwid; size_t fwid_len; @@ -764,10 +764,10 @@ static enum bt_mesh_dfu_iter slot_del_cb(const struct bt_mesh_dfu_slot *slot, return BT_MESH_DFU_ITER_CONTINUE; } -static int handle_fw_delete_all(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_fw_delete_all(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfd_srv *srv = mod->user_data; + struct bt_mesh_dfd_srv *srv = mod->rt->user_data; fw_status_rsp(srv, ctx, bt_mesh_dfd_srv_fw_delete_all(srv), 0xffff, NULL, 0); @@ -923,9 +923,9 @@ const struct bt_mesh_blob_srv_cb _bt_mesh_dfd_srv_blob_cb = { .suspended = upload_timeout, }; -static int dfd_srv_init(struct bt_mesh_model *mod) +static int dfd_srv_init(const struct bt_mesh_model *mod) { - struct bt_mesh_dfd_srv *srv = mod->user_data; + struct bt_mesh_dfd_srv *srv = mod->rt->user_data; srv->mod = mod; @@ -936,9 +936,9 @@ static int dfd_srv_init(struct bt_mesh_model *mod) return 0; } -static void dfd_srv_reset(struct bt_mesh_model *mod) +static void dfd_srv_reset(const struct bt_mesh_model *mod) { - struct bt_mesh_dfd_srv *srv = mod->user_data; + struct bt_mesh_dfd_srv *srv = mod->rt->user_data; dfd_phase_set(srv, BT_MESH_DFD_PHASE_IDLE); srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_IDLE; diff --git a/subsys/bluetooth/mesh/dfu_cli.c b/subsys/bluetooth/mesh/dfu_cli.c index 4db7779116b..2345ef8e33b 100644 --- a/subsys/bluetooth/mesh/dfu_cli.c +++ b/subsys/bluetooth/mesh/dfu_cli.c @@ -10,7 +10,7 @@ #include "access.h" #include "dfu.h" #include "blob.h" -#include +#include #include #define LOG_LEVEL CONFIG_BT_MESH_DFU_LOG_LEVEL @@ -305,8 +305,9 @@ static void tx_end(int err, void *cb_data) blob_cli_broadcast_tx_complete(&cli->blob); } -static int tx(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf, - const struct bt_mesh_send_cb *cb, struct bt_mesh_dfu_cli *cli) +static int tx(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf, const struct bt_mesh_send_cb *cb, + struct bt_mesh_dfu_cli *cli) { int err; @@ -698,10 +699,10 @@ static void cancelled(struct bt_mesh_blob_cli *b) * Message handlers ******************************************************************************/ -static int handle_status(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_status(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfu_cli *cli = mod->user_data; + struct bt_mesh_dfu_cli *cli = mod->rt->user_data; enum bt_mesh_dfu_status status; enum bt_mesh_dfu_phase phase; struct bt_mesh_dfu_target *target; @@ -824,10 +825,10 @@ static int handle_status(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, return 0; } -static int handle_info_status(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_info_status(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfu_cli *cli = mod->user_data; + struct bt_mesh_dfu_cli *cli = mod->rt->user_data; struct bt_mesh_dfu_target *target; enum bt_mesh_dfu_iter it = BT_MESH_DFU_ITER_CONTINUE; uint8_t img_cnt, idx; @@ -923,10 +924,10 @@ static int handle_info_status(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx return 0; } -static int handle_metadata_status(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_metadata_status(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfu_cli *cli = mod->user_data; + struct bt_mesh_dfu_cli *cli = mod->rt->user_data; struct bt_mesh_dfu_metadata_status *rsp = cli->req.params; uint8_t hdr, idx; @@ -960,11 +961,11 @@ const struct bt_mesh_model_op _bt_mesh_dfu_cli_op[] = { BT_MESH_MODEL_OP_END, }; -static int dfu_cli_init(struct bt_mesh_model *mod) +static int dfu_cli_init(const struct bt_mesh_model *mod) { - struct bt_mesh_dfu_cli *cli = mod->user_data; + struct bt_mesh_dfu_cli *cli = mod->rt->user_data; - if (mod->elem_idx != 0) { + if (mod->rt->elem_idx != 0) { LOG_ERR("DFU update client must be instantiated on first elem"); return -EINVAL; } @@ -980,9 +981,9 @@ static int dfu_cli_init(struct bt_mesh_model *mod) return 0; } -static void dfu_cli_reset(struct bt_mesh_model *mod) +static void dfu_cli_reset(const struct bt_mesh_model *mod) { - struct bt_mesh_dfu_cli *cli = mod->user_data; + struct bt_mesh_dfu_cli *cli = mod->rt->user_data; cli->req.type = REQ_NONE; cli->req.addr = BT_MESH_ADDR_UNASSIGNED; diff --git a/subsys/bluetooth/mesh/dfu_slot.c b/subsys/bluetooth/mesh/dfu_slot.c index 097d5abcc82..c11c16d44fc 100644 --- a/subsys/bluetooth/mesh/dfu_slot.c +++ b/subsys/bluetooth/mesh/dfu_slot.c @@ -95,9 +95,9 @@ static void slot_erase(struct slot *slot_to_erase) uint16_t idx = ARRAY_INDEX(slots, slot_to_erase); char buf[SLOT_ENTRY_BUFLEN]; - settings_delete(slot_entry_encode(idx, buf, PROP_HEADER)); - settings_delete(slot_entry_encode(idx, buf, PROP_FWID)); - settings_delete(slot_entry_encode(idx, buf, PROP_METADATA)); + (void)settings_delete(slot_entry_encode(idx, buf, PROP_HEADER)); + (void)settings_delete(slot_entry_encode(idx, buf, PROP_FWID)); + (void)settings_delete(slot_entry_encode(idx, buf, PROP_METADATA)); } static void slot_index_defrag(void) diff --git a/subsys/bluetooth/mesh/dfu_srv.c b/subsys/bluetooth/mesh/dfu_srv.c index 462a777b46c..f8e87e29da9 100644 --- a/subsys/bluetooth/mesh/dfu_srv.c +++ b/subsys/bluetooth/mesh/dfu_srv.c @@ -125,10 +125,10 @@ static void verify(struct bt_mesh_dfu_srv *srv) } } -static int handle_info_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_info_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfu_srv *srv = mod->user_data; + struct bt_mesh_dfu_srv *srv = mod->rt->user_data; uint8_t idx, limit; if (srv->update.phase == BT_MESH_DFU_PHASE_APPLYING) { @@ -187,10 +187,10 @@ static int handle_info_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ct return 0; } -static int handle_metadata_check(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_metadata_check(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfu_srv *srv = mod->user_data; + struct bt_mesh_dfu_srv *srv = mod->rt->user_data; enum bt_mesh_dfu_status status; enum bt_mesh_dfu_effect effect; uint8_t idx; @@ -239,10 +239,10 @@ static void update_status_rsp(struct bt_mesh_dfu_srv *srv, bt_mesh_model_send(srv->mod, ctx, &buf, send_cb, srv); } -static int handle_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfu_srv *srv = mod->user_data; + struct bt_mesh_dfu_srv *srv = mod->rt->user_data; LOG_DBG(""); @@ -262,10 +262,10 @@ static inline bool is_active_update(struct bt_mesh_dfu_srv *srv, uint8_t idx, srv->update.meta != meta_checksum); } -static int handle_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_start(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfu_srv *srv = mod->user_data; + struct bt_mesh_dfu_srv *srv = mod->rt->user_data; const struct bt_mesh_blob_io *io; uint16_t timeout_base, meta_checksum; enum bt_mesh_dfu_status status; @@ -371,10 +371,10 @@ static int handle_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, return 0; } -static int handle_cancel(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_cancel(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfu_srv *srv = mod->user_data; + struct bt_mesh_dfu_srv *srv = mod->rt->user_data; if (srv->update.idx == UPDATE_IDX_NONE) { goto rsp; @@ -392,10 +392,10 @@ static int handle_cancel(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, return 0; } -static int handle_apply(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_apply(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_dfu_srv *srv = mod->user_data; + struct bt_mesh_dfu_srv *srv = mod->rt->user_data; static const struct bt_mesh_send_cb send_cb = { .start = apply_rsp_sending, .end = apply_rsp_sent, @@ -435,9 +435,9 @@ const struct bt_mesh_model_op _bt_mesh_dfu_srv_op[] = { BT_MESH_MODEL_OP_END, }; -static int dfu_srv_init(struct bt_mesh_model *mod) +static int dfu_srv_init(const struct bt_mesh_model *mod) { - struct bt_mesh_dfu_srv *srv = mod->user_data; + struct bt_mesh_dfu_srv *srv = mod->rt->user_data; srv->mod = mod; srv->update.idx = UPDATE_IDX_NONE; @@ -455,11 +455,11 @@ static int dfu_srv_init(struct bt_mesh_model *mod) return 0; } -static int dfu_srv_settings_set(struct bt_mesh_model *mod, const char *name, +static int dfu_srv_settings_set(const struct bt_mesh_model *mod, const char *name, size_t len_rd, settings_read_cb read_cb, void *cb_arg) { - struct bt_mesh_dfu_srv *srv = mod->user_data; + struct bt_mesh_dfu_srv *srv = mod->rt->user_data; ssize_t len; if (len_rd < sizeof(srv->update)) { @@ -484,9 +484,9 @@ static int dfu_srv_settings_set(struct bt_mesh_model *mod, const char *name, return 0; } -static void dfu_srv_reset(struct bt_mesh_model *mod) +static void dfu_srv_reset(const struct bt_mesh_model *mod) { - struct bt_mesh_dfu_srv *srv = mod->user_data; + struct bt_mesh_dfu_srv *srv = mod->rt->user_data; srv->update.phase = BT_MESH_DFU_PHASE_IDLE; erase_state(srv); diff --git a/subsys/bluetooth/mesh/foundation.h b/subsys/bluetooth/mesh/foundation.h index 01cbf93c39e..8a9beef642e 100644 --- a/subsys/bluetooth/mesh/foundation.h +++ b/subsys/bluetooth/mesh/foundation.h @@ -150,7 +150,7 @@ void bt_mesh_model_reset(void); -void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time); +void bt_mesh_attention(const struct bt_mesh_model *model, uint8_t time); #include diff --git a/subsys/bluetooth/mesh/gatt_cli.c b/subsys/bluetooth/mesh/gatt_cli.c index 59407458de2..bff9b567011 100644 --- a/subsys/bluetooth/mesh/gatt_cli.c +++ b/subsys/bluetooth/mesh/gatt_cli.c @@ -176,8 +176,8 @@ static void gatt_connected(struct bt_conn *conn, uint8_t conn_err) struct bt_conn_info info; int err; - bt_conn_get_info(conn, &info); - if (info.role != BT_CONN_ROLE_CENTRAL || + err = bt_conn_get_info(conn, &info); + if (err || info.role != BT_CONN_ROLE_CENTRAL || !server->gatt) { return; } @@ -214,9 +214,10 @@ static void gatt_disconnected(struct bt_conn *conn, uint8_t reason) { struct bt_conn_info info; struct bt_mesh_gatt_server *server = get_server(conn); + int err; - bt_conn_get_info(conn, &info); - if (info.role != BT_CONN_ROLE_CENTRAL || + err = bt_conn_get_info(conn, &info); + if (err || info.role != BT_CONN_ROLE_CENTRAL || !server->gatt) { return; } diff --git a/subsys/bluetooth/mesh/health_cli.c b/subsys/bluetooth/mesh/health_cli.c index 924005f4882..16d2a79a53a 100644 --- a/subsys/bluetooth/mesh/health_cli.c +++ b/subsys/bluetooth/mesh/health_cli.c @@ -36,11 +36,11 @@ struct health_fault_param { size_t *fault_count; }; -static int health_fault_status(struct bt_mesh_model *model, +static int health_fault_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_health_cli *cli = model->user_data; + struct bt_mesh_health_cli *cli = model->rt->user_data; struct health_fault_param *param; uint8_t test_id; uint16_t cid; @@ -89,11 +89,11 @@ static int health_fault_status(struct bt_mesh_model *model, return 0; } -static int health_current_status(struct bt_mesh_model *model, +static int health_current_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_health_cli *cli = model->user_data; + struct bt_mesh_health_cli *cli = model->rt->user_data; uint8_t test_id; uint16_t cid; @@ -117,11 +117,11 @@ struct health_period_param { uint8_t *divisor; }; -static int health_period_status(struct bt_mesh_model *model, +static int health_period_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_health_cli *cli = model->user_data; + struct bt_mesh_health_cli *cli = model->rt->user_data; struct health_period_param *param; uint8_t divisor; @@ -151,11 +151,11 @@ struct health_attention_param { uint8_t *attention; }; -static int health_attention_status(struct bt_mesh_model *model, +static int health_attention_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_health_cli *cli = model->user_data; + struct bt_mesh_health_cli *cli = model->rt->user_data; struct health_attention_param *param; uint8_t attention; @@ -402,9 +402,9 @@ void bt_mesh_health_cli_timeout_set(int32_t timeout) msg_timeout = timeout; } -static int health_cli_init(struct bt_mesh_model *model) +static int health_cli_init(const struct bt_mesh_model *model) { - struct bt_mesh_health_cli *cli = model->user_data; + struct bt_mesh_health_cli *cli = model->rt->user_data; LOG_DBG("primary %u", bt_mesh_model_in_primary(model)); @@ -423,9 +423,9 @@ static int health_cli_init(struct bt_mesh_model *model) return 0; } -static void health_cli_reset(struct bt_mesh_model *model) +static void health_cli_reset(const struct bt_mesh_model *model) { - struct bt_mesh_health_cli *cli = model->user_data; + struct bt_mesh_health_cli *cli = model->rt->user_data; net_buf_simple_reset(cli->pub.msg); } diff --git a/subsys/bluetooth/mesh/health_srv.c b/subsys/bluetooth/mesh/health_srv.c index bfab40b6ef9..8611e1004f6 100644 --- a/subsys/bluetooth/mesh/health_srv.c +++ b/subsys/bluetooth/mesh/health_srv.c @@ -31,11 +31,11 @@ LOG_MODULE_REGISTER(bt_mesh_health_srv); /* Health Server context of the primary element */ struct bt_mesh_health_srv *health_srv; -static void health_get_registered(struct bt_mesh_model *mod, +static void health_get_registered(const struct bt_mesh_model *mod, uint16_t company_id, struct net_buf_simple *msg) { - struct bt_mesh_health_srv *srv = mod->user_data; + struct bt_mesh_health_srv *srv = mod->rt->user_data; uint8_t *test_id; LOG_DBG("Company ID 0x%04x", company_id); @@ -64,10 +64,10 @@ static void health_get_registered(struct bt_mesh_model *mod, } } -static size_t health_get_current(struct bt_mesh_model *mod, +static size_t health_get_current(const struct bt_mesh_model *mod, struct net_buf_simple *msg) { - struct bt_mesh_health_srv *srv = mod->user_data; + struct bt_mesh_health_srv *srv = mod->rt->user_data; const struct bt_mesh_comp *comp; uint8_t *test_id, *company_ptr; uint16_t company_id; @@ -105,7 +105,7 @@ static size_t health_get_current(struct bt_mesh_model *mod, return fault_count; } -static int health_fault_get(struct bt_mesh_model *model, +static int health_fault_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -125,11 +125,11 @@ static int health_fault_get(struct bt_mesh_model *model, return 0; } -static int health_fault_clear_unrel(struct bt_mesh_model *model, +static int health_fault_clear_unrel(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_health_srv *srv = model->user_data; + struct bt_mesh_health_srv *srv = model->rt->user_data; uint16_t company_id; company_id = net_buf_simple_pull_le16(buf); @@ -143,12 +143,12 @@ static int health_fault_clear_unrel(struct bt_mesh_model *model, return 0; } -static int health_fault_clear(struct bt_mesh_model *model, +static int health_fault_clear(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { NET_BUF_SIMPLE_DEFINE(sdu, BT_MESH_TX_SDU_MAX); - struct bt_mesh_health_srv *srv = model->user_data; + struct bt_mesh_health_srv *srv = model->rt->user_data; uint16_t company_id; company_id = net_buf_simple_pull_le16(buf); @@ -173,11 +173,11 @@ static int health_fault_clear(struct bt_mesh_model *model, return 0; } -static int health_fault_test_unrel(struct bt_mesh_model *model, +static int health_fault_test_unrel(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_health_srv *srv = model->user_data; + struct bt_mesh_health_srv *srv = model->rt->user_data; uint16_t company_id; uint8_t test_id; @@ -193,12 +193,12 @@ static int health_fault_test_unrel(struct bt_mesh_model *model, return 0; } -static int health_fault_test(struct bt_mesh_model *model, +static int health_fault_test(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { NET_BUF_SIMPLE_DEFINE(sdu, BT_MESH_TX_SDU_MAX); - struct bt_mesh_health_srv *srv = model->user_data; + struct bt_mesh_health_srv *srv = model->rt->user_data; uint16_t company_id; uint8_t test_id; @@ -228,12 +228,12 @@ static int health_fault_test(struct bt_mesh_model *model, return 0; } -static int send_attention_status(struct bt_mesh_model *model, +static int send_attention_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx) { /* Needed size: opcode (2 bytes) + msg + MIC */ BT_MESH_MODEL_BUF_DEFINE(msg, OP_ATTENTION_STATUS, 1); - struct bt_mesh_health_srv *srv = model->user_data; + struct bt_mesh_health_srv *srv = model->rt->user_data; uint8_t time; time = k_ticks_to_ms_floor32( @@ -251,7 +251,7 @@ static int send_attention_status(struct bt_mesh_model *model, return 0; } -static int attention_get(struct bt_mesh_model *model, +static int attention_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -260,7 +260,7 @@ static int attention_get(struct bt_mesh_model *model, return send_attention_status(model, ctx); } -static int attention_set_unrel(struct bt_mesh_model *model, +static int attention_set_unrel(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -275,7 +275,7 @@ static int attention_set_unrel(struct bt_mesh_model *model, return 0; } -static int attention_set(struct bt_mesh_model *model, +static int attention_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -291,7 +291,7 @@ static int attention_set(struct bt_mesh_model *model, return send_attention_status(model, ctx); } -static int send_health_period_status(struct bt_mesh_model *model, +static int send_health_period_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx) { /* Needed size: opcode (2 bytes) + msg + MIC */ @@ -308,7 +308,7 @@ static int send_health_period_status(struct bt_mesh_model *model, return 0; } -static int health_period_get(struct bt_mesh_model *model, +static int health_period_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -317,7 +317,7 @@ static int health_period_get(struct bt_mesh_model *model, return send_health_period_status(model, ctx); } -static int health_period_set_unrel(struct bt_mesh_model *model, +static int health_period_set_unrel(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -336,7 +336,7 @@ static int health_period_set_unrel(struct bt_mesh_model *model, return 0; } -static int health_period_set(struct bt_mesh_model *model, +static int health_period_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -367,7 +367,7 @@ const struct bt_mesh_model_op bt_mesh_health_srv_op[] = { BT_MESH_MODEL_OP_END, }; -static int health_pub_update(struct bt_mesh_model *mod) +static int health_pub_update(const struct bt_mesh_model *mod) { struct bt_mesh_model_pub *pub = mod->pub; size_t count; @@ -384,9 +384,9 @@ static int health_pub_update(struct bt_mesh_model *mod) return 0; } -int bt_mesh_health_srv_fault_update(struct bt_mesh_elem *elem) +int bt_mesh_health_srv_fault_update(const struct bt_mesh_elem *elem) { - struct bt_mesh_model *mod; + const struct bt_mesh_model *mod; mod = bt_mesh_model_find(elem, BT_MESH_MODEL_ID_HEALTH_SRV); if (!mod) { @@ -418,9 +418,9 @@ static void attention_off(struct k_work *work) } } -static int health_srv_init(struct bt_mesh_model *model) +static int health_srv_init(const struct bt_mesh_model *model) { - struct bt_mesh_health_srv *srv = model->user_data; + struct bt_mesh_health_srv *srv = model->rt->user_data; if (!srv) { LOG_ERR("No Health Server context provided"); @@ -449,7 +449,7 @@ const struct bt_mesh_model_cb bt_mesh_health_srv_cb = { .init = health_srv_init, }; -void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time) +void bt_mesh_attention(const struct bt_mesh_model *model, uint8_t time) { struct bt_mesh_health_srv *srv; @@ -462,7 +462,7 @@ void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time) model = srv->model; } else { - srv = model->user_data; + srv = model->rt->user_data; } if ((time > 0) && srv->cb && srv->cb->attn_on) { diff --git a/subsys/bluetooth/mesh/large_comp_data_cli.c b/subsys/bluetooth/mesh/large_comp_data_cli.c index 614569d54ae..3aa688523f9 100644 --- a/subsys/bluetooth/mesh/large_comp_data_cli.c +++ b/subsys/bluetooth/mesh/large_comp_data_cli.c @@ -33,7 +33,7 @@ LOG_MODULE_REGISTER(bt_mesh_large_comp_data_cli); static struct bt_mesh_large_comp_data_cli *cli; static int32_t msg_timeout; -static int data_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int data_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf, uint32_t op, void (*cb)(struct bt_mesh_large_comp_data_cli *cli, uint16_t addr, struct bt_mesh_large_comp_data_rsp *rsp)) @@ -78,7 +78,7 @@ static int data_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, return 0; } -static int large_comp_data_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int large_comp_data_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { return data_status(model, ctx, buf, OP_LARGE_COMP_DATA_STATUS, @@ -86,7 +86,7 @@ static int large_comp_data_status(struct bt_mesh_model *model, struct bt_mesh_ms cli->cb->large_comp_data_status : NULL)); } -static int models_metadata_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int models_metadata_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { return data_status(model, ctx, buf, OP_MODELS_METADATA_STATUS, @@ -100,7 +100,7 @@ const struct bt_mesh_model_op _bt_mesh_large_comp_data_cli_op[] = { BT_MESH_MODEL_OP_END, }; -static int large_comp_data_cli_init(struct bt_mesh_model *model) +static int large_comp_data_cli_init(const struct bt_mesh_model *model) { if (!bt_mesh_model_in_primary(model)) { LOG_ERR("Large Comp Data Client only allowed in primary element"); @@ -108,9 +108,9 @@ static int large_comp_data_cli_init(struct bt_mesh_model *model) } model->keys[0] = BT_MESH_KEY_DEV_ANY; - model->flags |= BT_MESH_MOD_DEVKEY_ONLY; + model->rt->flags |= BT_MESH_MOD_DEVKEY_ONLY; - cli = model->user_data; + cli = model->rt->user_data; cli->model = model; msg_timeout = 5000; diff --git a/subsys/bluetooth/mesh/large_comp_data_srv.c b/subsys/bluetooth/mesh/large_comp_data_srv.c index 4ee591d9efd..f47947b9b92 100644 --- a/subsys/bluetooth/mesh/large_comp_data_srv.c +++ b/subsys/bluetooth/mesh/large_comp_data_srv.c @@ -37,10 +37,11 @@ LOG_MODULE_REGISTER(bt_mesh_large_comp_data_srv); /** Mesh Large Composition Data Server Model Context */ static struct bt_mesh_large_comp_data_srv { /** Composition data model entry pointer. */ - struct bt_mesh_model *model; + const struct bt_mesh_model *model; } srv; -static int handle_large_comp_data_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int handle_large_comp_data_get(const struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { BT_MESH_MODEL_BUF_DEFINE(rsp, OP_LARGE_COMP_DATA_STATUS, @@ -101,7 +102,8 @@ static int handle_large_comp_data_get(struct bt_mesh_model *model, struct bt_mes return 0; } -static int handle_models_metadata_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int handle_models_metadata_get(const struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { BT_MESH_MODEL_BUF_DEFINE(rsp, OP_MODELS_METADATA_STATUS, @@ -166,7 +168,7 @@ const struct bt_mesh_model_op _bt_mesh_large_comp_data_srv_op[] = { BT_MESH_MODEL_OP_END, }; -static int large_comp_data_srv_init(struct bt_mesh_model *model) +static int large_comp_data_srv_init(const struct bt_mesh_model *model) { if (!bt_mesh_model_in_primary(model)) { LOG_ERR("Large Composition Data Server only allowed in primary element"); @@ -175,7 +177,7 @@ static int large_comp_data_srv_init(struct bt_mesh_model *model) /* Large Composition Data Server model shall use the device key */ model->keys[0] = BT_MESH_KEY_DEV; - model->flags |= BT_MESH_MOD_DEVKEY_ONLY; + model->rt->flags |= BT_MESH_MOD_DEVKEY_ONLY; srv.model = model; diff --git a/subsys/bluetooth/mesh/main.c b/subsys/bluetooth/mesh/main.c index fb70eef669a..2c78ea227de 100644 --- a/subsys/bluetooth/mesh/main.c +++ b/subsys/bluetooth/mesh/main.c @@ -419,7 +419,7 @@ bool bt_mesh_is_provisioned(void) return atomic_test_bit(bt_mesh.flags, BT_MESH_VALID); } -static void model_suspend(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, +static void model_suspend(const struct bt_mesh_model *mod, const struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data) { if (mod->pub && mod->pub->update) { @@ -463,7 +463,7 @@ int bt_mesh_suspend(void) return 0; } -static void model_resume(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, +static void model_resume(const struct bt_mesh_model *mod, const struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data) { if (mod->pub && mod->pub->update) { @@ -552,7 +552,7 @@ int bt_mesh_init(const struct bt_mesh_prov *prov, return 0; } -static void model_start(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, +static void model_start(const struct bt_mesh_model *mod, const struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data) { if (mod->cb && mod->cb->start) { diff --git a/subsys/bluetooth/mesh/msg.c b/subsys/bluetooth/mesh/msg.c index 458b387539f..6ba497be0c0 100644 --- a/subsys/bluetooth/mesh/msg.c +++ b/subsys/bluetooth/mesh/msg.c @@ -87,7 +87,7 @@ bool bt_mesh_msg_ack_ctx_match(const struct bt_mesh_msg_ack_ctx *ack, return true; } -int bt_mesh_msg_send(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +int bt_mesh_msg_send(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { if (!ctx && !model->pub) { @@ -104,7 +104,7 @@ int bt_mesh_msg_send(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, return bt_mesh_model_publish(model); } -int bt_mesh_msg_ackd_send(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +int bt_mesh_msg_ackd_send(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf, const struct bt_mesh_msg_rsp_ctx *rsp) { int err; diff --git a/subsys/bluetooth/mesh/msg.h b/subsys/bluetooth/mesh/msg.h index a5d75949130..ff52260b626 100644 --- a/subsys/bluetooth/mesh/msg.h +++ b/subsys/bluetooth/mesh/msg.h @@ -18,7 +18,7 @@ * @retval -EADDRNOTAVAIL A message context was not provided and publishing is not configured. * @retval -EAGAIN The device has not been provisioned. */ -int bt_mesh_msg_send(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +int bt_mesh_msg_send(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf); /** @@ -51,5 +51,5 @@ struct bt_mesh_msg_rsp_ctx { * @retval -EAGAIN The device has not been provisioned. * @retval -ETIMEDOUT The request timed out without a response. */ -int bt_mesh_msg_ackd_send(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +int bt_mesh_msg_ackd_send(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf, const struct bt_mesh_msg_rsp_ctx *rsp); diff --git a/subsys/bluetooth/mesh/net.c b/subsys/bluetooth/mesh/net.c index 61efaeb2c81..6a9f29b4064 100644 --- a/subsys/bluetooth/mesh/net.c +++ b/subsys/bluetooth/mesh/net.c @@ -95,9 +95,8 @@ struct bt_mesh_net bt_mesh = { #endif }; -/* Mesh Profile Specification 3.10.6 - * The node shall not execute more than one IV Index Recovery within a period of - * 192 hours. +/* MshPRTv1.1: 3.11.5: + * "A node shall not start an IV Update procedure more often than once every 192 hours." * * Mark that the IV Index Recovery has been done to prevent two recoveries to be * done before a normal IV Index update has been completed within 96h+96h. @@ -293,7 +292,7 @@ bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update) return false; } - /* The Mesh profile specification allows to initiate an + /* MshPRTv1.1 allows to initiate an * IV Index Recovery procedure if previous IV update has * been missed. This allows the node to remain * functional. @@ -560,7 +559,7 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, } } - /* Mesh spec 3.4.5.2: "The output filter of the interface connected to + /* MshPRTv1.1: 3.4.5.2: "The output filter of the interface connected to * advertising or GATT bearers shall drop all messages with TTL value * set to 1." If a TTL=1 packet wasn't for a local interface, it is * invalid. diff --git a/subsys/bluetooth/mesh/od_priv_proxy_cli.c b/subsys/bluetooth/mesh/od_priv_proxy_cli.c index 67f5ac961ad..bd4e796b8e2 100644 --- a/subsys/bluetooth/mesh/od_priv_proxy_cli.c +++ b/subsys/bluetooth/mesh/od_priv_proxy_cli.c @@ -20,7 +20,7 @@ static struct bt_mesh_od_priv_proxy_cli *cli; static int32_t msg_timeout; -static int handle_proxy_status(struct bt_mesh_model *mod, +static int handle_proxy_status(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -93,17 +93,17 @@ void bt_mesh_od_priv_proxy_cli_timeout_set(int32_t timeout) msg_timeout = timeout; } -static int on_demand_proxy_cli_init(struct bt_mesh_model *mod) +static int on_demand_proxy_cli_init(const struct bt_mesh_model *mod) { if (!bt_mesh_model_in_primary(mod)) { LOG_ERR("On-Demand Private Proxy client not in primary element"); return -EINVAL; } - cli = mod->user_data; + cli = mod->rt->user_data; cli->model = mod; mod->keys[0] = BT_MESH_KEY_DEV_ANY; - mod->flags |= BT_MESH_MOD_DEVKEY_ONLY; + mod->rt->flags |= BT_MESH_MOD_DEVKEY_ONLY; msg_timeout = CONFIG_BT_MESH_OD_PRIV_PROXY_CLI_TIMEOUT; bt_mesh_msg_ack_ctx_init(&cli->ack_ctx); diff --git a/subsys/bluetooth/mesh/od_priv_proxy_srv.c b/subsys/bluetooth/mesh/od_priv_proxy_srv.c index b18a8ec7530..e54ed88fa0c 100644 --- a/subsys/bluetooth/mesh/od_priv_proxy_srv.c +++ b/subsys/bluetooth/mesh/od_priv_proxy_srv.c @@ -16,7 +16,7 @@ LOG_MODULE_REGISTER(bt_mesh_od_priv_proxy_srv); -static struct bt_mesh_model *od_priv_proxy_srv; +static const struct bt_mesh_model *od_priv_proxy_srv; static uint8_t on_demand_state; static int od_priv_proxy_store(bool delete) @@ -31,7 +31,7 @@ static int od_priv_proxy_store(bool delete) return bt_mesh_model_data_store(od_priv_proxy_srv, false, "pp", data, len); } -static int proxy_status_rsp(struct bt_mesh_model *mod, +static int proxy_status_rsp(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx) { BT_MESH_MODEL_BUF_DEFINE(buf, OP_OD_PRIV_PROXY_STATUS, 1); @@ -44,7 +44,7 @@ static int proxy_status_rsp(struct bt_mesh_model *mod, return 0; } -static int handle_proxy_get(struct bt_mesh_model *mod, +static int handle_proxy_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -55,7 +55,7 @@ static int handle_proxy_get(struct bt_mesh_model *mod, return 0; } -static int handle_proxy_set(struct bt_mesh_model *mod, +static int handle_proxy_set(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -79,13 +79,13 @@ const struct bt_mesh_model_op _bt_mesh_od_priv_proxy_srv_op[] = { BT_MESH_MODEL_OP_END }; -static int od_priv_proxy_srv_init(struct bt_mesh_model *mod) +static int od_priv_proxy_srv_init(const struct bt_mesh_model *mod) { od_priv_proxy_srv = mod; - struct bt_mesh_model *priv_beacon_srv = bt_mesh_model_find( + const struct bt_mesh_model *priv_beacon_srv = bt_mesh_model_find( bt_mesh_model_elem(mod), BT_MESH_MODEL_ID_PRIV_BEACON_SRV); - struct bt_mesh_model *sol_pdu_rpl_srv = bt_mesh_model_find( + const struct bt_mesh_model *sol_pdu_rpl_srv = bt_mesh_model_find( bt_mesh_model_elem(mod), BT_MESH_MODEL_ID_SOL_PDU_RPL_SRV); if (priv_beacon_srv == NULL) { @@ -98,7 +98,7 @@ static int od_priv_proxy_srv_init(struct bt_mesh_model *mod) } mod->keys[0] = BT_MESH_KEY_DEV_LOCAL; - mod->flags |= BT_MESH_MOD_DEVKEY_ONLY; + mod->rt->flags |= BT_MESH_MOD_DEVKEY_ONLY; if (IS_ENABLED(CONFIG_BT_MESH_MODEL_EXTENSIONS)) { bt_mesh_model_extend(mod, priv_beacon_srv); @@ -108,14 +108,14 @@ static int od_priv_proxy_srv_init(struct bt_mesh_model *mod) return 0; } -static void od_priv_proxy_srv_reset(struct bt_mesh_model *model) +static void od_priv_proxy_srv_reset(const struct bt_mesh_model *model) { on_demand_state = 0; od_priv_proxy_store(true); } #ifdef CONFIG_BT_SETTINGS -static int od_priv_proxy_srv_settings_set(struct bt_mesh_model *model, const char *name, +static int od_priv_proxy_srv_settings_set(const struct bt_mesh_model *model, const char *name, size_t len_rd, settings_read_cb read_cb, void *cb_data) { int err; @@ -135,7 +135,7 @@ static int od_priv_proxy_srv_settings_set(struct bt_mesh_model *model, const cha return 0; } -static void od_priv_proxy_srv_pending_store(struct bt_mesh_model *model) +static void od_priv_proxy_srv_pending_store(const struct bt_mesh_model *model) { on_demand_state = bt_mesh_od_priv_proxy_get(); od_priv_proxy_store(false); diff --git a/subsys/bluetooth/mesh/op_agg.c b/subsys/bluetooth/mesh/op_agg.c index 1580c7f0847..8c4497e4f6f 100644 --- a/subsys/bluetooth/mesh/op_agg.c +++ b/subsys/bluetooth/mesh/op_agg.c @@ -16,83 +16,22 @@ LOG_MODULE_REGISTER(bt_mesh_op_agg); #define IS_LENGTH_LONG(buf) ((buf)->data[0] & 1) #define LENGTH_SHORT_MAX BIT_MASK(7) -NET_BUF_SIMPLE_DEFINE_STATIC(sdu, BT_MESH_TX_SDU_MAX); -NET_BUF_SIMPLE_DEFINE_STATIC(srcs, BT_MESH_TX_SDU_MAX); - -static struct op_agg_ctx agg_ctx = { - .sdu = &sdu, -#if IS_ENABLED(CONFIG_BT_MESH_OP_AGG_CLI) - .srcs = &srcs, -#endif -}; - -struct op_agg_ctx *bt_mesh_op_agg_ctx_get(void) -{ - return &agg_ctx; -} - -static bool ctx_match(struct bt_mesh_msg_ctx *ctx) -{ - return (ctx->net_idx == agg_ctx.net_idx) && (ctx->addr == agg_ctx.addr) && - (ctx->app_idx == agg_ctx.app_idx); -} - -int bt_mesh_op_agg_accept(struct bt_mesh_msg_ctx *msg_ctx) -{ - return agg_ctx.initialized && ctx_match(msg_ctx); -} - -void bt_mesh_op_agg_ctx_reinit(void) -{ - agg_ctx.initialized = true; -} - -int bt_mesh_op_agg_send(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *msg, - const struct bt_mesh_send_cb *cb) -{ - int err; - - /* Model responded so mark this message as acknowledged */ - agg_ctx.ack = true; - - if (IS_ENABLED(CONFIG_BT_MESH_OP_AGG_CLI)) { - /* Store source address so that Opcodes Aggregator Client can - * match response with source model - */ - uint16_t src = bt_mesh_model_elem(model)->addr; - - if (net_buf_simple_tailroom(&srcs) < 2) { - return -ENOMEM; - } - - net_buf_simple_add_le16(&srcs, src); - } - - err = bt_mesh_op_agg_encode_msg(msg); - if (err) { - agg_ctx.rsp_err = ACCESS_STATUS_RESPONSE_OVERFLOW; - } - - return err; -} - -int bt_mesh_op_agg_encode_msg(struct net_buf_simple *msg) +int bt_mesh_op_agg_encode_msg(struct net_buf_simple *msg, struct net_buf_simple *buf) { if (msg->len > LENGTH_SHORT_MAX) { - if (net_buf_simple_tailroom(agg_ctx.sdu) < (msg->len + 2)) { + if (net_buf_simple_tailroom(buf) < (msg->len + 2)) { return -ENOMEM; } - net_buf_simple_add_le16(agg_ctx.sdu, (msg->len << 1) | 1); + net_buf_simple_add_le16(buf, (msg->len << 1) | 1); } else { - if (net_buf_simple_tailroom(agg_ctx.sdu) < (msg->len + 1)) { + if (net_buf_simple_tailroom(buf) < (msg->len + 1)) { return -ENOMEM; } - net_buf_simple_add_u8(agg_ctx.sdu, msg->len << 1); + net_buf_simple_add_u8(buf, msg->len << 1); } - net_buf_simple_add_mem(agg_ctx.sdu, msg->data, msg->len); + net_buf_simple_add_mem(buf, msg->data, msg->len); return 0; } @@ -124,3 +63,21 @@ int bt_mesh_op_agg_decode_msg(struct net_buf_simple *msg, return 0; } + +bool bt_mesh_op_agg_is_op_agg_msg(struct net_buf_simple *buf) +{ + if (buf->len >= 2 && (buf->data[0] >> 6) == 2) { + uint16_t opcode; + struct net_buf_simple_state state; + + net_buf_simple_save(buf, &state); + opcode = net_buf_simple_pull_be16(buf); + net_buf_simple_restore(buf, &state); + + if ((opcode == OP_OPCODES_AGGREGATOR_STATUS) || + (opcode == OP_OPCODES_AGGREGATOR_SEQUENCE)) { + return true; + } + } + return false; +} diff --git a/subsys/bluetooth/mesh/op_agg.h b/subsys/bluetooth/mesh/op_agg.h index a267fc737f7..a56a30ccd31 100644 --- a/subsys/bluetooth/mesh/op_agg.h +++ b/subsys/bluetooth/mesh/op_agg.h @@ -7,45 +7,20 @@ struct op_agg_ctx { /** Context is initialized. */ bool initialized; - /** NetKey Index of the subnet to send the message on. */ uint16_t net_idx; - /** AppKey Index to encrypt the message with. */ uint16_t app_idx; - /** Remote element address. */ uint16_t addr; - - /** List of source element addresses. - * Used by Client to match aggregated responses - * with local source client models. - */ - struct net_buf_simple *srcs; - - /** Response error code. */ - int rsp_err; - /** Aggregated message buffer. */ struct net_buf_simple *sdu; - - /** Used only by the Opcodes Aggregator Server. - * - * Indicates that the received aggregated message - * was acknowledged by local server model. - */ - bool ack; }; -struct op_agg_ctx *bt_mesh_op_agg_ctx_get(void); -void bt_mesh_op_agg_ctx_reinit(void); - -int bt_mesh_op_agg_encode_msg(struct net_buf_simple *msg); -int bt_mesh_op_agg_decode_msg(struct net_buf_simple *msg, - struct net_buf_simple *buf); - -int bt_mesh_op_agg_accept(struct bt_mesh_msg_ctx *ctx); - -int bt_mesh_op_agg_send(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *msg, - const struct bt_mesh_send_cb *cb); +int bt_mesh_op_agg_encode_msg(struct net_buf_simple *msg, struct net_buf_simple *buf); +int bt_mesh_op_agg_decode_msg(struct net_buf_simple *msg, struct net_buf_simple *buf); +int bt_mesh_op_agg_cli_send(const struct bt_mesh_model *model, struct net_buf_simple *msg); +int bt_mesh_op_agg_cli_accept(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf); +int bt_mesh_op_agg_srv_send(const struct bt_mesh_model *model, struct net_buf_simple *msg); +int bt_mesh_op_agg_srv_accept(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf); +bool bt_mesh_op_agg_is_op_agg_msg(struct net_buf_simple *buf); diff --git a/subsys/bluetooth/mesh/op_agg_cli.c b/subsys/bluetooth/mesh/op_agg_cli.c index d3371306a8b..1e44ba36f54 100644 --- a/subsys/bluetooth/mesh/op_agg_cli.c +++ b/subsys/bluetooth/mesh/op_agg_cli.c @@ -18,22 +18,31 @@ #include LOG_MODULE_REGISTER(bt_mesh_op_agg_cli); +NET_BUF_SIMPLE_DEFINE_STATIC(srcs, BT_MESH_TX_SDU_MAX); +NET_BUF_SIMPLE_DEFINE_STATIC(sdu, BT_MESH_TX_SDU_MAX); + /** Mesh Opcodes Aggregator Client Model Context */ static struct bt_mesh_op_agg_cli { /** Composition data model entry pointer. */ - struct bt_mesh_model *model; - - /* Internal parameters for tracking message responses. */ + const struct bt_mesh_model *model; + /** Acknowledge context. */ struct bt_mesh_msg_ack_ctx ack_ctx; -} cli; + /** List of source element addresses. + * Used by Client to match aggregated responses + * with local source client models. + */ + struct net_buf_simple *srcs; + /** Aggregator context. */ + struct op_agg_ctx ctx; + +} cli = {.srcs = &srcs, .ctx.sdu = &sdu}; static int32_t msg_timeout; -static int handle_status(struct bt_mesh_model *model, +static int handle_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct op_agg_ctx *agg = bt_mesh_op_agg_ctx_get(); struct net_buf_simple msg; uint8_t status; uint16_t elem_addr, addr; @@ -57,17 +66,17 @@ static int handle_status(struct bt_mesh_model *model, err = bt_mesh_op_agg_decode_msg(&msg, buf); if (err) { LOG_ERR("Cannot decode aggregated message %d", err); - bt_mesh_op_agg_ctx_reinit(); + cli.ctx.initialized = true; return -EINVAL; } - if (agg->srcs->len < 2) { + if (cli.srcs->len < 2) { LOG_ERR("Mismatch in sources address buffer"); - bt_mesh_op_agg_ctx_reinit(); + cli.ctx.initialized = true; return -ENOENT; } - addr = net_buf_simple_pull_le16(agg->srcs); + addr = net_buf_simple_pull_le16(cli.srcs); /* Empty item means unacked msg. */ if (!msg.len) { @@ -78,7 +87,7 @@ static int handle_status(struct bt_mesh_model *model, err = bt_mesh_model_recv(ctx, &msg); if (err) { LOG_ERR("Opcodes Aggregator receive error %d", err); - bt_mesh_op_agg_ctx_reinit(); + cli.ctx.initialized = true; return err; } } @@ -93,7 +102,7 @@ const struct bt_mesh_model_op _bt_mesh_op_agg_cli_op[] = { BT_MESH_MODEL_OP_END, }; -static int op_agg_cli_init(struct bt_mesh_model *model) +static int op_agg_cli_init(const struct bt_mesh_model *model) { if (!bt_mesh_model_in_primary(model)) { LOG_ERR("Opcodes Aggregator Client only allowed in primary element"); @@ -115,56 +124,51 @@ static int op_agg_cli_init(struct bt_mesh_model *model) int bt_mesh_op_agg_cli_seq_start(uint16_t net_idx, uint16_t app_idx, uint16_t dst, uint16_t elem_addr) { - struct op_agg_ctx *agg = bt_mesh_op_agg_ctx_get(); - if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { LOG_ERR("Element address shall be a unicast address"); return -EINVAL; } - if (agg->initialized) { + if (cli.ctx.initialized) { LOG_ERR("Opcodes Aggregator is already configured"); return -EALREADY; } - agg->net_idx = net_idx; - agg->app_idx = app_idx; - agg->addr = dst; - agg->ack = false; - agg->rsp_err = 0; - agg->initialized = true; + cli.ctx.net_idx = net_idx; + cli.ctx.app_idx = app_idx; + cli.ctx.addr = dst; + cli.ctx.initialized = true; - net_buf_simple_init(agg->srcs, 0); - bt_mesh_model_msg_init(agg->sdu, OP_OPCODES_AGGREGATOR_SEQUENCE); - net_buf_simple_add_le16(agg->sdu, elem_addr); + net_buf_simple_init(cli.srcs, 0); + bt_mesh_model_msg_init(cli.ctx.sdu, OP_OPCODES_AGGREGATOR_SEQUENCE); + net_buf_simple_add_le16(cli.ctx.sdu, elem_addr); return 0; } int bt_mesh_op_agg_cli_seq_send(void) { - struct op_agg_ctx *agg = bt_mesh_op_agg_ctx_get(); struct bt_mesh_msg_ctx ctx = { - .net_idx = agg->net_idx, - .app_idx = agg->app_idx, - .addr = agg->addr, + .net_idx = cli.ctx.net_idx, + .app_idx = cli.ctx.app_idx, + .addr = cli.ctx.addr, }; int err; - if (!agg->initialized) { + if (!cli.ctx.initialized) { LOG_ERR("Opcodes Aggregator not initialized"); return -EINVAL; } - err = bt_mesh_msg_ack_ctx_prepare(&cli.ack_ctx, OP_OPCODES_AGGREGATOR_STATUS, agg->addr, - NULL); + err = bt_mesh_msg_ack_ctx_prepare(&cli.ack_ctx, OP_OPCODES_AGGREGATOR_STATUS, + cli.ctx.addr, NULL); if (err) { return err; } - agg->initialized = false; + cli.ctx.initialized = false; - err = bt_mesh_model_send(cli.model, &ctx, agg->sdu, NULL, NULL); + err = bt_mesh_model_send(cli.model, &ctx, cli.ctx.sdu, NULL, NULL); if (err) { LOG_ERR("model_send() failed (err %d)", err); bt_mesh_msg_ack_ctx_clear(&cli.ack_ctx); @@ -176,23 +180,17 @@ int bt_mesh_op_agg_cli_seq_send(void) void bt_mesh_op_agg_cli_seq_abort(void) { - struct op_agg_ctx *agg = bt_mesh_op_agg_ctx_get(); - - agg->initialized = false; + cli.ctx.initialized = false; } bool bt_mesh_op_agg_cli_seq_is_started(void) { - struct op_agg_ctx *agg = bt_mesh_op_agg_ctx_get(); - - return agg->initialized; + return cli.ctx.initialized; } size_t bt_mesh_op_agg_cli_seq_tailroom(void) { - struct op_agg_ctx *agg = bt_mesh_op_agg_ctx_get(); - - return net_buf_simple_tailroom(agg->sdu); + return net_buf_simple_tailroom(cli.ctx.sdu); } int32_t bt_mesh_op_agg_cli_timeout_get(void) @@ -205,6 +203,26 @@ void bt_mesh_op_agg_cli_timeout_set(int32_t timeout) msg_timeout = timeout; } +int bt_mesh_op_agg_cli_send(const struct bt_mesh_model *model, struct net_buf_simple *msg) +{ + uint16_t src = bt_mesh_model_elem(model)->rt->addr; + + if (net_buf_simple_tailroom(&srcs) < 2) { + return -ENOMEM; + } + + net_buf_simple_add_le16(&srcs, src); + return bt_mesh_op_agg_encode_msg(msg, cli.ctx.sdu); +} + +int bt_mesh_op_agg_cli_accept(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) +{ + + return cli.ctx.initialized && (ctx->net_idx == cli.ctx.net_idx) && + (ctx->addr == cli.ctx.addr) && (ctx->app_idx == cli.ctx.app_idx) && + !bt_mesh_op_agg_is_op_agg_msg(buf); +} + const struct bt_mesh_model_cb _bt_mesh_op_agg_cli_cb = { .init = op_agg_cli_init, }; diff --git a/subsys/bluetooth/mesh/op_agg_srv.c b/subsys/bluetooth/mesh/op_agg_srv.c index bed3b54c946..9bbe01384e2 100644 --- a/subsys/bluetooth/mesh/op_agg_srv.c +++ b/subsys/bluetooth/mesh/op_agg_srv.c @@ -17,17 +17,26 @@ #include LOG_MODULE_REGISTER(bt_mesh_op_agg_srv); +NET_BUF_SIMPLE_DEFINE_STATIC(sdu, BT_MESH_TX_SDU_MAX); + /** Mesh Opcodes Aggragator Server Model Context */ static struct bt_mesh_op_agg_srv { /** Composition data model entry pointer. */ - struct bt_mesh_model *model; -} srv; + const struct bt_mesh_model *model; + /** Response error code. */ + int rsp_err; + /** Indicates that the received aggregated message + * was acknowledged by local server model. + */ + bool ack; + /** Aggregator context. */ + struct op_agg_ctx ctx; +} srv = {.ctx.sdu = &sdu}; -static int handle_sequence(struct bt_mesh_model *model, +static int handle_sequence(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct op_agg_ctx *agg = bt_mesh_op_agg_ctx_get(); struct net_buf_simple_state state; struct net_buf_simple msg; uint16_t elem; @@ -37,14 +46,14 @@ static int handle_sequence(struct bt_mesh_model *model, elem = net_buf_simple_pull_le16(buf); ctx->recv_dst = elem; - bt_mesh_model_msg_init(agg->sdu, OP_OPCODES_AGGREGATOR_STATUS); - status = net_buf_simple_add_u8(agg->sdu, 0); - net_buf_simple_add_le16(agg->sdu, elem); + bt_mesh_model_msg_init(srv.ctx.sdu, OP_OPCODES_AGGREGATOR_STATUS); + status = net_buf_simple_add_u8(srv.ctx.sdu, 0); + net_buf_simple_add_le16(srv.ctx.sdu, elem); - agg->net_idx = ctx->net_idx; - agg->app_idx = ctx->app_idx; - agg->addr = ctx->addr; - agg->initialized = true; + srv.ctx.net_idx = ctx->net_idx; + srv.ctx.app_idx = ctx->app_idx; + srv.ctx.addr = ctx->addr; + srv.ctx.initialized = true; if (!BT_MESH_ADDR_IS_UNICAST(elem)) { LOG_WRN("Address is not unicast, ignoring."); @@ -70,12 +79,12 @@ static int handle_sequence(struct bt_mesh_model *model, while (buf->len > 0) { (void) bt_mesh_op_agg_decode_msg(&msg, buf); - agg->ack = false; - agg->rsp_err = 0; + srv.ack = false; + srv.rsp_err = 0; err = bt_mesh_model_recv(ctx, &msg); - if (agg->rsp_err) { - *status = agg->rsp_err; + if (srv.rsp_err) { + *status = srv.rsp_err; break; } @@ -84,14 +93,14 @@ static int handle_sequence(struct bt_mesh_model *model, break; } - if (!agg->ack) { - net_buf_simple_add_u8(agg->sdu, 0); + if (!srv.ack) { + net_buf_simple_add_u8(srv.ctx.sdu, 0); } } send: - agg->initialized = false; - err = bt_mesh_model_send(model, ctx, agg->sdu, NULL, NULL); + srv.ctx.initialized = false; + err = bt_mesh_model_send(model, ctx, srv.ctx.sdu, NULL, NULL); if (err) { LOG_ERR("Unable to send Opcodes Aggregator Status"); return err; @@ -105,7 +114,7 @@ const struct bt_mesh_model_op _bt_mesh_op_agg_srv_op[] = { BT_MESH_MODEL_OP_END, }; -static int op_agg_srv_init(struct bt_mesh_model *model) +static int op_agg_srv_init(const struct bt_mesh_model *model) { if (!bt_mesh_model_in_primary(model)) { LOG_ERR("Opcodes Aggregator Server only allowed in primary element"); @@ -122,6 +131,29 @@ static int op_agg_srv_init(struct bt_mesh_model *model) return 0; } +int bt_mesh_op_agg_srv_send(const struct bt_mesh_model *model, struct net_buf_simple *msg) +{ + int err; + + /* Model responded so mark this message as acknowledged */ + srv.ack = true; + + err = bt_mesh_op_agg_encode_msg(msg, srv.ctx.sdu); + if (err) { + srv.rsp_err = ACCESS_STATUS_RESPONSE_OVERFLOW; + } + + return err; +} + +int bt_mesh_op_agg_srv_accept(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) +{ + + return srv.ctx.initialized && (ctx->net_idx == srv.ctx.net_idx) && + (ctx->addr == srv.ctx.addr) && (ctx->app_idx == srv.ctx.app_idx) && + !bt_mesh_op_agg_is_op_agg_msg(buf); +} + const struct bt_mesh_model_cb _bt_mesh_op_agg_srv_cb = { .init = op_agg_srv_init, }; diff --git a/subsys/bluetooth/mesh/pb_adv.c b/subsys/bluetooth/mesh/pb_adv.c index cb5f53f32b7..e273739ed72 100644 --- a/subsys/bluetooth/mesh/pb_adv.c +++ b/subsys/bluetooth/mesh/pb_adv.c @@ -929,7 +929,7 @@ static void prov_link_close(enum prov_bearer_link_status status) } /* - * According to mesh profile spec (5.3.1.4.3), the close message should + * According to MshPRTv1.1: 5.3.1.4.3, the close message should * be restransmitted at least three times. Retransmit the LINK_CLOSE * message until CLOSING_TIMEOUT has elapsed. */ diff --git a/subsys/bluetooth/mesh/pb_gatt_srv.c b/subsys/bluetooth/mesh/pb_gatt_srv.c index d5ad2f9711d..f6d9298fc78 100644 --- a/subsys/bluetooth/mesh/pb_gatt_srv.c +++ b/subsys/bluetooth/mesh/pb_gatt_srv.c @@ -94,27 +94,29 @@ static ssize_t gatt_recv(struct bt_conn *conn, return bt_mesh_proxy_msg_recv(conn, buf, len); } -static void gatt_connected(struct bt_conn *conn, uint8_t err) +static void gatt_connected(struct bt_conn *conn, uint8_t conn_err) { struct bt_conn_info info; + int err; - bt_conn_get_info(conn, &info); - if (info.role != BT_CONN_ROLE_PERIPHERAL || !service_registered || + err = bt_conn_get_info(conn, &info); + if (err || info.role != BT_CONN_ROLE_PERIPHERAL || !service_registered || bt_mesh_is_provisioned() || info.id != BT_ID_DEFAULT || cli) { return; } cli = bt_mesh_proxy_role_setup(conn, gatt_send, proxy_msg_recv); - LOG_DBG("conn %p err 0x%02x", (void *)conn, err); + LOG_DBG("conn %p err 0x%02x", (void *)conn, conn_err); } static void gatt_disconnected(struct bt_conn *conn, uint8_t reason) { struct bt_conn_info info; + int err; - bt_conn_get_info(conn, &info); - if (info.role != BT_CONN_ROLE_PERIPHERAL || !service_registered || + err = bt_conn_get_info(conn, &info); + if (err || info.role != BT_CONN_ROLE_PERIPHERAL || !service_registered || info.id != BT_ID_DEFAULT || !cli || cli->conn != conn) { return; } diff --git a/subsys/bluetooth/mesh/priv_beacon_cli.c b/subsys/bluetooth/mesh/priv_beacon_cli.c index d14454c7cf5..7d679f0e322 100644 --- a/subsys/bluetooth/mesh/priv_beacon_cli.c +++ b/subsys/bluetooth/mesh/priv_beacon_cli.c @@ -18,7 +18,7 @@ static struct bt_mesh_priv_beacon_cli *cli; static int32_t msg_timeout; -static int handle_beacon_status(struct bt_mesh_model *model, +static int handle_beacon_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -56,7 +56,7 @@ static int handle_beacon_status(struct bt_mesh_model *model, return 0; } -static int handle_gatt_proxy_status(struct bt_mesh_model *model, +static int handle_gatt_proxy_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -86,7 +86,7 @@ static int handle_gatt_proxy_status(struct bt_mesh_model *model, return 0; } -static int handle_node_id_status(struct bt_mesh_model *model, +static int handle_node_id_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -134,18 +134,18 @@ const struct bt_mesh_model_op bt_mesh_priv_beacon_cli_op[] = { BT_MESH_MODEL_OP_END, }; -static int priv_beacon_cli_init(struct bt_mesh_model *model) +static int priv_beacon_cli_init(const struct bt_mesh_model *model) { if (!bt_mesh_model_in_primary(model)) { LOG_ERR("Private Beacon Client only allowed in primary element"); return -EINVAL; } - cli = model->user_data; + cli = model->rt->user_data; cli->model = model; msg_timeout = 2 * MSEC_PER_SEC; model->keys[0] = BT_MESH_KEY_DEV_ANY; - model->flags |= BT_MESH_MOD_DEVKEY_ONLY; + model->rt->flags |= BT_MESH_MOD_DEVKEY_ONLY; bt_mesh_msg_ack_ctx_init(&cli->ack_ctx); @@ -156,13 +156,14 @@ const struct bt_mesh_model_cb bt_mesh_priv_beacon_cli_cb = { .init = priv_beacon_cli_init, }; -int bt_mesh_priv_beacon_cli_set(uint16_t net_idx, uint16_t addr, struct bt_mesh_priv_beacon *val) +int bt_mesh_priv_beacon_cli_set(uint16_t net_idx, uint16_t addr, struct bt_mesh_priv_beacon *val, + struct bt_mesh_priv_beacon *rsp) { struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_DEV(net_idx, addr); const struct bt_mesh_msg_rsp_ctx rsp_ctx = { .ack = &cli->ack_ctx, .op = OP_PRIV_BEACON_STATUS, - .user_data = val, + .user_data = rsp, .timeout = msg_timeout, }; @@ -174,7 +175,7 @@ int bt_mesh_priv_beacon_cli_set(uint16_t net_idx, uint16_t addr, struct bt_mesh_ net_buf_simple_add_u8(&buf, val->rand_interval); } - return bt_mesh_msg_ackd_send(cli->model, &ctx, &buf, val ? &rsp_ctx : NULL); + return bt_mesh_msg_ackd_send(cli->model, &ctx, &buf, rsp ? &rsp_ctx : NULL); } int bt_mesh_priv_beacon_cli_get(uint16_t net_idx, uint16_t addr, struct bt_mesh_priv_beacon *val) @@ -193,27 +194,28 @@ int bt_mesh_priv_beacon_cli_get(uint16_t net_idx, uint16_t addr, struct bt_mesh_ return bt_mesh_msg_ackd_send(cli->model, &ctx, &buf, val ? &rsp_ctx : NULL); } -int bt_mesh_priv_beacon_cli_gatt_proxy_set(uint16_t net_idx, uint16_t addr, uint8_t *val) +int bt_mesh_priv_beacon_cli_gatt_proxy_set(uint16_t net_idx, uint16_t addr, uint8_t val, + uint8_t *rsp) { struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_DEV(net_idx, addr); const struct bt_mesh_msg_rsp_ctx rsp_ctx = { .ack = &cli->ack_ctx, .op = OP_PRIV_GATT_PROXY_STATUS, - .user_data = val, + .user_data = rsp, .timeout = msg_timeout, }; - if (!val || (*val != BT_MESH_GATT_PROXY_DISABLED && - *val != BT_MESH_GATT_PROXY_ENABLED)) { + if ((val != BT_MESH_GATT_PROXY_DISABLED && + val != BT_MESH_GATT_PROXY_ENABLED)) { return -EINVAL; } BT_MESH_MODEL_BUF_DEFINE(buf, OP_PRIV_GATT_PROXY_SET, 1); bt_mesh_model_msg_init(&buf, OP_PRIV_GATT_PROXY_SET); - net_buf_simple_add_u8(&buf, *val); + net_buf_simple_add_u8(&buf, val); - return bt_mesh_msg_ackd_send(cli->model, &ctx, &buf, val ? &rsp_ctx : NULL); + return bt_mesh_msg_ackd_send(cli->model, &ctx, &buf, rsp ? &rsp_ctx : NULL); } int bt_mesh_priv_beacon_cli_gatt_proxy_get(uint16_t net_idx, uint16_t addr, uint8_t *val) @@ -233,17 +235,18 @@ int bt_mesh_priv_beacon_cli_gatt_proxy_get(uint16_t net_idx, uint16_t addr, uint } int bt_mesh_priv_beacon_cli_node_id_set(uint16_t net_idx, uint16_t addr, - struct bt_mesh_priv_node_id *val) + struct bt_mesh_priv_node_id *val, + struct bt_mesh_priv_node_id *rsp) { struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_DEV(net_idx, addr); const struct bt_mesh_msg_rsp_ctx rsp_ctx = { .ack = &cli->ack_ctx, .op = OP_PRIV_NODE_ID_STATUS, - .user_data = val, + .user_data = rsp, .timeout = msg_timeout, }; - if (!val || val->net_idx > 0xfff || + if (val->net_idx > 0xfff || (val->state != BT_MESH_NODE_IDENTITY_STOPPED && val->state != BT_MESH_NODE_IDENTITY_RUNNING)) { return -EINVAL; @@ -255,7 +258,7 @@ int bt_mesh_priv_beacon_cli_node_id_set(uint16_t net_idx, uint16_t addr, net_buf_simple_add_le16(&buf, val->net_idx); net_buf_simple_add_u8(&buf, val->state); - return bt_mesh_msg_ackd_send(cli->model, &ctx, &buf, val ? &rsp_ctx : NULL); + return bt_mesh_msg_ackd_send(cli->model, &ctx, &buf, rsp ? &rsp_ctx : NULL); } int bt_mesh_priv_beacon_cli_node_id_get(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx, diff --git a/subsys/bluetooth/mesh/priv_beacon_srv.c b/subsys/bluetooth/mesh/priv_beacon_srv.c index 377703e8352..5b5e62f1736 100644 --- a/subsys/bluetooth/mesh/priv_beacon_srv.c +++ b/subsys/bluetooth/mesh/priv_beacon_srv.c @@ -17,7 +17,7 @@ #include LOG_MODULE_REGISTER(bt_mesh_priv_beacon_srv); -static struct bt_mesh_model *priv_beacon_srv; +static const struct bt_mesh_model *priv_beacon_srv; /* Private Beacon configuration server model states */ struct { @@ -38,7 +38,7 @@ static int priv_beacon_store(bool delete) return bt_mesh_model_data_store(priv_beacon_srv, false, "pb", data, len); } -static int beacon_status_rsp(struct bt_mesh_model *mod, +static int beacon_status_rsp(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx) { BT_MESH_MODEL_BUF_DEFINE(buf, OP_PRIV_BEACON_STATUS, 2); @@ -52,7 +52,7 @@ static int beacon_status_rsp(struct bt_mesh_model *mod, return 0; } -static int handle_beacon_get(struct bt_mesh_model *mod, +static int handle_beacon_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -63,7 +63,7 @@ static int handle_beacon_get(struct bt_mesh_model *mod, return 0; } -static int handle_beacon_set(struct bt_mesh_model *mod, +static int handle_beacon_set(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -90,7 +90,7 @@ static int handle_beacon_set(struct bt_mesh_model *mod, return 0; } -static void gatt_proxy_status_rsp(struct bt_mesh_model *mod, +static void gatt_proxy_status_rsp(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx) { BT_MESH_MODEL_BUF_DEFINE(buf, OP_PRIV_GATT_PROXY_STATUS, 1); @@ -101,7 +101,7 @@ static void gatt_proxy_status_rsp(struct bt_mesh_model *mod, bt_mesh_model_send(mod, ctx, &buf, NULL, NULL); } -static int handle_gatt_proxy_get(struct bt_mesh_model *mod, +static int handle_gatt_proxy_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -112,7 +112,7 @@ static int handle_gatt_proxy_get(struct bt_mesh_model *mod, return 0; } -static int handle_gatt_proxy_set(struct bt_mesh_model *mod, +static int handle_gatt_proxy_set(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -134,7 +134,7 @@ static int handle_gatt_proxy_set(struct bt_mesh_model *mod, return 0; } -static void node_id_status_rsp(struct bt_mesh_model *mod, +static void node_id_status_rsp(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, uint8_t status, uint16_t net_idx, uint8_t node_id) { @@ -148,7 +148,7 @@ static void node_id_status_rsp(struct bt_mesh_model *mod, bt_mesh_model_send(mod, ctx, &buf, NULL, NULL); } -static int handle_node_id_get(struct bt_mesh_model *mod, +static int handle_node_id_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -163,7 +163,7 @@ static int handle_node_id_get(struct bt_mesh_model *mod, return 0; } -static int handle_node_id_set(struct bt_mesh_model *mod, +static int handle_node_id_set(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -194,7 +194,7 @@ const struct bt_mesh_model_op bt_mesh_priv_beacon_srv_op[] = { BT_MESH_MODEL_OP_END }; -static int priv_beacon_srv_init(struct bt_mesh_model *mod) +static int priv_beacon_srv_init(const struct bt_mesh_model *mod) { if (!bt_mesh_model_in_primary(mod)) { LOG_ERR("Priv beacon server not in primary element"); @@ -207,14 +207,14 @@ static int priv_beacon_srv_init(struct bt_mesh_model *mod) return 0; } -static void priv_beacon_srv_reset(struct bt_mesh_model *model) +static void priv_beacon_srv_reset(const struct bt_mesh_model *model) { (void)memset(&priv_beacon_state, 0, sizeof(priv_beacon_state)); priv_beacon_store(true); } #ifdef CONFIG_BT_SETTINGS -static int priv_beacon_srv_settings_set(struct bt_mesh_model *model, const char *name, +static int priv_beacon_srv_settings_set(const struct bt_mesh_model *model, const char *name, size_t len_rd, settings_read_cb read_cb, void *cb_data) { int err; @@ -236,7 +236,7 @@ static int priv_beacon_srv_settings_set(struct bt_mesh_model *model, const char return 0; } -static void priv_beacon_srv_pending_store(struct bt_mesh_model *model) +static void priv_beacon_srv_pending_store(const struct bt_mesh_model *model) { priv_beacon_state.state = bt_mesh_priv_beacon_get(); priv_beacon_state.interval = bt_mesh_priv_beacon_update_interval_get(); diff --git a/subsys/bluetooth/mesh/prov.c b/subsys/bluetooth/mesh/prov.c index fbbcde58185..ba177bf1981 100644 --- a/subsys/bluetooth/mesh/prov.c +++ b/subsys/bluetooth/mesh/prov.c @@ -153,15 +153,10 @@ static uint32_t get_auth_number(bt_mesh_output_action_t output, bt_rand(&num, sizeof(num)); - if (output == BT_MESH_BLINK || - output == BT_MESH_BEEP || - output == BT_MESH_VIBRATE || - input == BT_MESH_PUSH || - input == BT_MESH_TWIST) { - /* According to the Bluetooth Mesh Profile - * Specification Section 5.4.2.4, blink, beep - * vibrate, push and twist should be a random integer - * between 0 and 10^size, *exclusive*: + if (output == BT_MESH_BLINK || output == BT_MESH_BEEP || output == BT_MESH_VIBRATE || + input == BT_MESH_PUSH || input == BT_MESH_TWIST) { + /* According to MshPRTv1.1: 5.4.2.4, blink, beep vibrate, push and twist should be + * a random integer between 0 and 10^size, *exclusive*: */ num = (num % (divider[size - 1] - 1)) + 1; } else { diff --git a/subsys/bluetooth/mesh/prov_device.c b/subsys/bluetooth/mesh/prov_device.c index 6e56519eefb..af890396ac7 100644 --- a/subsys/bluetooth/mesh/prov_device.c +++ b/subsys/bluetooth/mesh/prov_device.c @@ -57,9 +57,8 @@ static void prov_send_fail_msg(uint8_t err) static void prov_fail(uint8_t reason) { - /* According to Bluetooth Mesh Specification v1.0.1, Section 5.4.4, the - * provisioner just closes the link when something fails, while the - * provisionee sends the fail message, and waits for the provisioner to + /* According to MshPRTv1.1: 5.4.4, the provisioner just closes the link when something + * fails, while the provisionee sends the fail message, and waits for the provisioner to * close the link. */ prov_send_fail_msg(reason); diff --git a/subsys/bluetooth/mesh/provisioner.c b/subsys/bluetooth/mesh/provisioner.c index a65bd25ab53..aba2449892f 100644 --- a/subsys/bluetooth/mesh/provisioner.c +++ b/subsys/bluetooth/mesh/provisioner.c @@ -72,7 +72,7 @@ static void prov_link_close(enum prov_bearer_link_status status) static void prov_fail(uint8_t reason) { - /* According to Bluetooth Mesh Specification v1.0.1, Section 5.4.4, the + /* According to MshPRTv1.1: 5.4.4, the * provisioner just closes the link when something fails, while the * provisionee sends the fail message, and waits for the provisioner to * close the link. diff --git a/subsys/bluetooth/mesh/proxy.h b/subsys/bluetooth/mesh/proxy.h index 7f06be8f13f..a2f6bb45ff6 100644 --- a/subsys/bluetooth/mesh/proxy.h +++ b/subsys/bluetooth/mesh/proxy.h @@ -36,3 +36,4 @@ void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub); bool bt_mesh_proxy_relay(struct net_buf *buf, uint16_t dst); void bt_mesh_proxy_addr_add(struct net_buf_simple *buf, uint16_t addr); +uint8_t bt_mesh_proxy_srv_connected_cnt(void); diff --git a/subsys/bluetooth/mesh/proxy_cli.c b/subsys/bluetooth/mesh/proxy_cli.c index 54cbf9ab2e9..a0a25751b41 100644 --- a/subsys/bluetooth/mesh/proxy_cli.c +++ b/subsys/bluetooth/mesh/proxy_cli.c @@ -27,6 +27,7 @@ #include "proxy.h" #include "gatt_cli.h" #include "proxy_msg.h" +#include "crypto.h" #define LOG_LEVEL CONFIG_BT_MESH_PROXY_LOG_LEVEL #include @@ -157,14 +158,9 @@ static const struct bt_mesh_gatt_cli proxy = { .disconnected = proxy_disconnected }; -struct find_net_id { - const uint8_t *net_id; - struct bt_mesh_proxy_server *srv; -}; - -static bool has_net_id(struct bt_mesh_subnet *sub, void *user_data) +static bool proxy_srv_check_and_get(struct bt_mesh_subnet *sub, const uint8_t *net_id, + struct bt_mesh_proxy_server **p_srv) { - struct find_net_id *res = user_data; struct bt_mesh_proxy_server *srv; srv = find_proxy_srv(sub->net_idx, true, true); @@ -183,43 +179,125 @@ static bool has_net_id(struct bt_mesh_subnet *sub, void *user_data) } } - if (!memcmp(sub->keys[0].net_id, res->net_id, 8) || - (bt_mesh_subnet_has_new_key(sub) && - !memcmp(sub->keys[1].net_id, res->net_id, 8))) { - res->srv = srv; + /* If net_id is NULL we already know that the networks match */ + if (!net_id || !memcmp(sub->keys[0].net_id, net_id, 8) || + (bt_mesh_subnet_has_new_key(sub) && !memcmp(sub->keys[1].net_id, net_id, 8))) { + + *p_srv = srv; return true; } return false; } -void bt_mesh_proxy_cli_adv_recv(const struct bt_le_scan_recv_info *info, - struct net_buf_simple *buf) -{ +struct find_net_id { uint8_t type; + + union { + const uint8_t *net_id; + struct { + const uint8_t *hash; + const uint8_t *rand; + } priv; + } data; + + struct bt_mesh_proxy_server *srv; +}; + +static bool is_hash_equal(struct bt_mesh_subnet *sub, struct find_net_id *res, uint8_t idx) +{ + int err; + uint8_t in[16], out[16]; + + memcpy(&in[0], sub->keys[idx].net_id, 8); + memcpy(&in[8], res->data.priv.rand, 8); + err = bt_mesh_encrypt(&sub->keys[idx].identity, in, out); + if (err) { + LOG_ERR("Failed to generate hash (err: %d)", err); + return false; + } + + if (memcmp(&out[8], res->data.priv.hash, 8)) { + return false; + } + + return true; +} + +static bool has_net_id(struct bt_mesh_subnet *sub, void *user_data) +{ + struct find_net_id *res = user_data; + uint8_t *net_id = NULL; + + if (res->type == BT_MESH_ID_TYPE_NET) { + net_id = (uint8_t *)res->data.net_id; + goto end; + } + + /* Additional handling for BT_MESH_ID_TYPE_PRIV_NET msg type */ + if (!(is_hash_equal(sub, res, 0) || + (bt_mesh_subnet_has_new_key(sub) && is_hash_equal(sub, res, 1)))) { + return false; + } +end: + return proxy_srv_check_and_get(sub, net_id, &res->srv); +} + +static void handle_net_id(uint8_t type, const struct bt_le_scan_recv_info *info, + struct net_buf_simple *buf) +{ + int err; struct find_net_id res; struct bt_mesh_subnet *sub; - type = net_buf_simple_pull_u8(buf); - switch (type) { - case BT_MESH_ID_TYPE_NET: + res.type = type; + res.srv = NULL; + + if (type == BT_MESH_ID_TYPE_NET) { if (buf->len != 8) { - break; + return; } + res.data.net_id = net_buf_simple_pull_mem(buf, 8); - res.net_id = net_buf_simple_pull_mem(buf, 8); - res.srv = NULL; + } else { + if (buf->len != 16) { + return; + } + + res.data.priv.hash = net_buf_simple_pull_mem(buf, 8); + res.data.priv.rand = net_buf_simple_pull_mem(buf, 8); + } - sub = bt_mesh_subnet_find(has_net_id, (void *)&res); - if (sub && res.srv) { - (void)bt_mesh_gatt_cli_connect(info->addr, &proxy, res.srv); + sub = bt_mesh_subnet_find(has_net_id, (void *)&res); + if (sub && res.srv) { + err = bt_mesh_gatt_cli_connect(info->addr, &proxy, res.srv); + if (err) { + LOG_DBG("Failed to connect over GATT (err:%d)", err); } + } +} + +void bt_mesh_proxy_cli_adv_recv(const struct bt_le_scan_recv_info *info, + struct net_buf_simple *buf) +{ + uint8_t type; + type = net_buf_simple_pull_u8(buf); + switch (type) { + case BT_MESH_ID_TYPE_NET: + /* Fallthrough */ + case BT_MESH_ID_TYPE_PRIV_NET: { + handle_net_id(type, info, buf); break; + } case BT_MESH_ID_TYPE_NODE: { /* TODO */ break; } + case BT_MESH_ID_TYPE_PRIV_NODE: { + /* TODO */ + break; + } default: return; } @@ -313,3 +391,12 @@ static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt) BT_MESH_SUBNET_CB_DEFINE(proxy_cli) = { .evt_handler = subnet_evt, }; + +bool bt_mesh_proxy_cli_is_connected(uint16_t net_idx) +{ + if (find_proxy_srv(net_idx, true, false)) { + return true; + } + + return false; +} diff --git a/subsys/bluetooth/mesh/proxy_cli.h b/subsys/bluetooth/mesh/proxy_cli.h index 9f8ec96458d..8c1fae10e84 100644 --- a/subsys/bluetooth/mesh/proxy_cli.h +++ b/subsys/bluetooth/mesh/proxy_cli.h @@ -9,3 +9,5 @@ void bt_mesh_proxy_cli_adv_recv(const struct bt_le_scan_recv_info *info, struct net_buf_simple *buf); bool bt_mesh_proxy_cli_relay(struct net_buf *buf); + +bool bt_mesh_proxy_cli_is_connected(uint16_t net_idx); diff --git a/subsys/bluetooth/mesh/proxy_msg.c b/subsys/bluetooth/mesh/proxy_msg.c index b9dfb8f7e16..025909e0503 100644 --- a/subsys/bluetooth/mesh/proxy_msg.c +++ b/subsys/bluetooth/mesh/proxy_msg.c @@ -38,7 +38,7 @@ LOG_MODULE_REGISTER(bt_mesh_proxy); #define PDU_SAR(data) (data[0] >> 6) -/* Mesh Profile 1.0 Section 6.6: +/* MshPRTv1.1: 6.3.2.2: * "The timeout for the SAR transfer is 20 seconds. When the timeout * expires, the Proxy Server shall disconnect." */ diff --git a/subsys/bluetooth/mesh/proxy_srv.c b/subsys/bluetooth/mesh/proxy_srv.c index 12775b93651..571144ceaed 100644 --- a/subsys/bluetooth/mesh/proxy_srv.c +++ b/subsys/bluetooth/mesh/proxy_srv.c @@ -518,7 +518,7 @@ static int enc_id_adv(struct bt_mesh_subnet *sub, uint8_t type, return err; } - /* Section 7.2.2.2.4: The AdvA field shall be regenerated whenever the Random field is + /* MshPRTv1.1: 7.2.2.2.4: The AdvA field shall be regenerated whenever the Random field is * regenerated. */ err = randomize_bt_addr(); @@ -697,7 +697,8 @@ static void gatt_proxy_solicited(struct bt_mesh_subnet *sub) int32_t remaining; if (sub->priv_net_id_sent > 0) { - timeout = sub->priv_net_id_sent + MSEC_PER_SEC * bt_mesh_od_priv_proxy_get(); + timeout = sub->priv_net_id_sent + + MSEC_PER_SEC * (int64_t) bt_mesh_od_priv_proxy_get(); remaining = MIN(timeout - now, INT32_MAX); } else { remaining = MSEC_PER_SEC * bt_mesh_od_priv_proxy_get(); @@ -785,14 +786,14 @@ static int gatt_proxy_advertise(struct bt_mesh_subnet *sub) } } - /* Mesh Profile Specification v1.0.1, section 7.2.2.2.1 - * A node that does not support the Proxy feature or - * has the GATT Proxy state disabled shall not advertise with Network ID. + /* MshPRTv1.1: section 7.2.2.2.1: + * "A node that does not support the Proxy feature or + * has the GATT Proxy state disabled shall not advertise with Network ID." */ if (sub->node_id == BT_MESH_NODE_IDENTITY_STOPPED) { if (IS_ENABLED(CONFIG_BT_MESH_PRIV_BEACONS) && (bt_mesh_priv_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED)) { - /* Bluetooth mesh specification v1.1, section 7.2.2.2.4: The Random + /* MshPRTv1.1: 7.2.2.2.4: The Random * field should be updated every 10 minutes. Limit advertising to * 10 minutes to ensure regeneration of a new random value at least * that often. @@ -1057,18 +1058,19 @@ static void solicitation_reset(struct bt_mesh_subnet *sub) #endif } -static void gatt_connected(struct bt_conn *conn, uint8_t err) +static void gatt_connected(struct bt_conn *conn, uint8_t conn_err) { struct bt_mesh_proxy_client *client; struct bt_conn_info info; + int err; - bt_conn_get_info(conn, &info); - if (info.role != BT_CONN_ROLE_PERIPHERAL || !service_registered || + err = bt_conn_get_info(conn, &info); + if (err || info.role != BT_CONN_ROLE_PERIPHERAL || !service_registered || info.id != BT_ID_DEFAULT) { return; } - LOG_DBG("conn %p err 0x%02x", (void *)conn, err); + LOG_DBG("conn %p err 0x%02x", (void *)conn, conn_err); client = find_client(conn); @@ -1078,7 +1080,7 @@ static void gatt_connected(struct bt_conn *conn, uint8_t err) proxy_msg_recv); #if defined(CONFIG_BT_MESH_PRIV_BEACONS) - /* Binding from section 7.2.2.2.6 of MshPRTv1.1. */ + /* Binding from MshPRTv1.1: 7.2.2.2.6. */ enum bt_mesh_subnets_node_id_state cur_node_id = bt_mesh_subnets_node_id_state_get(); if (bt_mesh_gatt_proxy_get() == BT_MESH_FEATURE_ENABLED || @@ -1107,9 +1109,10 @@ static void gatt_disconnected(struct bt_conn *conn, uint8_t reason) { struct bt_conn_info info; struct bt_mesh_proxy_client *client; + int err; - bt_conn_get_info(conn, &info); - if (info.role != BT_CONN_ROLE_PERIPHERAL || info.id != BT_ID_DEFAULT) { + err = bt_conn_get_info(conn, &info); + if (err || info.role != BT_CONN_ROLE_PERIPHERAL || info.id != BT_ID_DEFAULT) { return; } @@ -1157,3 +1160,16 @@ BT_CONN_CB_DEFINE(conn_callbacks) = { .connected = gatt_connected, .disconnected = gatt_disconnected, }; + +uint8_t bt_mesh_proxy_srv_connected_cnt(void) +{ + uint8_t cnt = 0; + + for (int i = 0; i < ARRAY_SIZE(clients); i++) { + if (clients[i].cli) { + cnt++; + } + } + + return cnt; +} diff --git a/subsys/bluetooth/mesh/rpr_cli.c b/subsys/bluetooth/mesh/rpr_cli.c index 3ebd3afcd6a..cbb92e75b40 100644 --- a/subsys/bluetooth/mesh/rpr_cli.c +++ b/subsys/bluetooth/mesh/rpr_cli.c @@ -90,11 +90,11 @@ static void tx_complete(struct bt_mesh_rpr_cli *cli, int err, void *cb_data) } } -static int handle_extended_scan_report(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_extended_scan_report(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { struct bt_mesh_rpr_node srv = RPR_NODE(ctx); - struct bt_mesh_rpr_cli *cli = mod->user_data; + struct bt_mesh_rpr_cli *cli = mod->rt->user_data; struct bt_mesh_rpr_unprov dev = { 0 }; enum bt_mesh_rpr_status status; bool found_dev = false; @@ -123,11 +123,11 @@ static int handle_extended_scan_report(struct bt_mesh_model *mod, struct bt_mesh return 0; } -static int handle_link_report(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_link_report(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { struct bt_mesh_rpr_node srv = RPR_NODE(ctx); - struct bt_mesh_rpr_cli *cli = mod->user_data; + struct bt_mesh_rpr_cli *cli = mod->rt->user_data; struct bt_mesh_rpr_link link; uint8_t reason = PROV_BEARER_LINK_STATUS_SUCCESS; @@ -161,10 +161,10 @@ static int handle_link_report(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx return 0; } -static int handle_link_status(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_link_status(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_rpr_cli *cli = mod->user_data; + struct bt_mesh_rpr_cli *cli = mod->rt->user_data; struct bt_mesh_rpr_node srv = RPR_NODE(ctx); struct bt_mesh_rpr_link *rsp; struct bt_mesh_rpr_link link; @@ -195,10 +195,10 @@ static int handle_link_status(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx return 0; } -static int handle_pdu_outbound_report(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_pdu_outbound_report(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_rpr_cli *cli = mod->user_data; + struct bt_mesh_rpr_cli *cli = mod->rt->user_data; struct bt_mesh_rpr_node srv = RPR_NODE(ctx); void *cb_data; uint8_t num; @@ -226,10 +226,10 @@ static int handle_pdu_outbound_report(struct bt_mesh_model *mod, struct bt_mesh_ return 0; } -static int handle_pdu_report(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_pdu_report(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_rpr_cli *cli = mod->user_data; + struct bt_mesh_rpr_cli *cli = mod->rt->user_data; struct bt_mesh_rpr_node srv = RPR_NODE(ctx); struct pb_remote_ctx cb_ctx = { cli, @@ -257,10 +257,10 @@ static int handle_pdu_report(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx * return 0; } -static int handle_scan_caps_status(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_scan_caps_status(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_rpr_cli *cli = mod->user_data; + struct bt_mesh_rpr_cli *cli = mod->rt->user_data; struct bt_mesh_rpr_node srv = RPR_NODE(ctx); struct bt_mesh_rpr_caps *caps; @@ -281,10 +281,10 @@ static int handle_scan_caps_status(struct bt_mesh_model *mod, struct bt_mesh_msg return 0; } -static int handle_scan_report(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_scan_report(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_rpr_cli *cli = mod->user_data; + struct bt_mesh_rpr_cli *cli = mod->rt->user_data; struct bt_mesh_rpr_node srv = RPR_NODE(ctx); struct bt_mesh_rpr_unprov dev = { 0 }; @@ -313,10 +313,10 @@ static int handle_scan_report(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx return 0; } -static int handle_scan_status(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_scan_status(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - struct bt_mesh_rpr_cli *cli = mod->user_data; + struct bt_mesh_rpr_cli *cli = mod->rt->user_data; struct bt_mesh_rpr_scan_status *status; struct bt_mesh_rpr_node srv = RPR_NODE(ctx); @@ -361,15 +361,15 @@ static void link_timeout(struct k_work *work) } } -static int rpr_cli_init(struct bt_mesh_model *mod) +static int rpr_cli_init(const struct bt_mesh_model *mod) { - if (mod->elem_idx) { + if (mod->rt->elem_idx) { LOG_ERR("Remote provisioning client must be initialized " "on first element"); return -EINVAL; } - struct bt_mesh_rpr_cli *cli = mod->user_data; + struct bt_mesh_rpr_cli *cli = mod->rt->user_data; cli->mod = mod; cli->link.time = LINK_TIMEOUT_SECONDS_DEFAULT; @@ -378,7 +378,7 @@ static int rpr_cli_init(struct bt_mesh_model *mod) bt_mesh_msg_ack_ctx_init(&cli->prov_ack_ctx); k_work_init_delayable(&cli->link.timeout, link_timeout); mod->keys[0] = BT_MESH_KEY_DEV_ANY; - mod->flags |= BT_MESH_MOD_DEVKEY_ONLY; + mod->rt->flags |= BT_MESH_MOD_DEVKEY_ONLY; return 0; } diff --git a/subsys/bluetooth/mesh/rpr_srv.c b/subsys/bluetooth/mesh/rpr_srv.c index 8fb28e56472..9813842a367 100644 --- a/subsys/bluetooth/mesh/rpr_srv.c +++ b/subsys/bluetooth/mesh/rpr_srv.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include #include @@ -47,7 +47,7 @@ enum { /** Remote provisioning server instance. */ static struct { - struct bt_mesh_model *mod; + const struct bt_mesh_model *mod; ATOMIC_DEFINE(flags, RPR_SRV_NUM_FLAGS); @@ -423,7 +423,7 @@ static void subnet_evt_handler(struct bt_mesh_subnet *subnet, link_close(BT_MESH_RPR_ERR_LINK_CLOSED_BY_SERVER, PROV_BEARER_LINK_STATUS_FAIL); /* Skip the link closing stage, as specified in the Bluetooth - * Mesh Profile specification, section 4.4.5.4. + * MshPRTv1.1: 4.4.5.4. */ srv.link.state = BT_MESH_RPR_LINK_IDLE; } else if (atomic_test_bit(srv.flags, SCANNING) && @@ -536,7 +536,7 @@ static const struct prov_bearer_cb prov_bearer_cb = { * Message handlers ******************************************************************************/ -static int handle_scan_caps_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_scan_caps_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { BT_MESH_MODEL_BUF_DEFINE(rsp, RPR_OP_SCAN_CAPS_STATUS, 2); @@ -549,7 +549,7 @@ static int handle_scan_caps_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ct return 0; } -static int handle_scan_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_scan_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { scan_status_send(ctx, BT_MESH_RPR_SUCCESS); @@ -557,7 +557,7 @@ static int handle_scan_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ct return 0; } -static int handle_scan_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_scan_start(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { struct bt_mesh_rpr_node cli = RPR_NODE(ctx); @@ -621,7 +621,7 @@ static int handle_scan_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx * return 0; } -static int handle_extended_scan_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_extended_scan_start(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { BT_MESH_MODEL_BUF_DEFINE(rsp, RPR_OP_EXTENDED_SCAN_REPORT, @@ -634,7 +634,7 @@ static int handle_extended_scan_start(struct bt_mesh_model *mod, struct bt_mesh_ uint8_t timeout; int i; - /* According to the Bluetooth Mesh specification, section 4.4.5.5.1.7, scan reports shall be + /* According to MshPRTv1.1: 4.4.5.5.1.7, scan reports shall be * sent as segmented messages. */ ctx->send_rel = true; @@ -784,7 +784,7 @@ static int handle_extended_scan_start(struct bt_mesh_model *mod, struct bt_mesh_ return 0; } -static int handle_scan_stop(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_scan_stop(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { if (atomic_test_bit(srv.flags, SCANNING)) { @@ -797,7 +797,7 @@ static int handle_scan_stop(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *c return 0; } -static int handle_link_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_link_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { LOG_DBG(""); @@ -807,7 +807,7 @@ static int handle_link_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ct return 0; } -static int handle_link_open(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_link_open(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { bool is_refresh_procedure = (buf->len == 1); @@ -938,7 +938,7 @@ static int handle_link_open(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *c return 0; } -static int handle_link_close(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_link_close(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { struct bt_mesh_rpr_node cli = RPR_NODE(ctx); @@ -975,7 +975,7 @@ static int handle_link_close(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx * return 0; } -static int handle_pdu_send(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int handle_pdu_send(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { struct bt_mesh_rpr_node cli = RPR_NODE(ctx); @@ -1303,9 +1303,9 @@ static struct bt_le_scan_cb scan_cb = { .recv = scan_packet_recv, }; -static int rpr_srv_init(struct bt_mesh_model *mod) +static int rpr_srv_init(const struct bt_mesh_model *mod) { - if (mod->elem_idx || srv.mod) { + if (mod->rt->elem_idx || srv.mod) { LOG_ERR("Remote provisioning server must be initialized " "on first element"); return -EINVAL; @@ -1320,12 +1320,12 @@ static int rpr_srv_init(struct bt_mesh_model *mod) k_work_init(&srv.link.report, link_report_send_and_clear); bt_le_scan_cb_register(&scan_cb); mod->keys[0] = BT_MESH_KEY_DEV_LOCAL; - mod->flags |= BT_MESH_MOD_DEVKEY_ONLY; + mod->rt->flags |= BT_MESH_MOD_DEVKEY_ONLY; return 0; } -static void rpr_srv_reset(struct bt_mesh_model *mod) +static void rpr_srv_reset(const struct bt_mesh_model *mod) { cli_link_clear(); cli_scan_clear(); diff --git a/subsys/bluetooth/mesh/sar_cfg_cli.c b/subsys/bluetooth/mesh/sar_cfg_cli.c index b5a33b975e5..52239c95be4 100644 --- a/subsys/bluetooth/mesh/sar_cfg_cli.c +++ b/subsys/bluetooth/mesh/sar_cfg_cli.c @@ -21,7 +21,7 @@ LOG_MODULE_REGISTER(bt_mesh_sar_cfg_cli); static struct bt_mesh_sar_cfg_cli *cli; -static int transmitter_status(struct bt_mesh_model *model, +static int transmitter_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -45,7 +45,7 @@ static int transmitter_status(struct bt_mesh_model *model, return 0; } -static int receiver_status(struct bt_mesh_model *model, +static int receiver_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -87,35 +87,35 @@ void bt_mesh_sar_cfg_cli_timeout_set(int32_t timeout) cli->timeout = timeout; } -static int bt_mesh_sar_cfg_cli_init(struct bt_mesh_model *model) +static int bt_mesh_sar_cfg_cli_init(const struct bt_mesh_model *model) { if (!bt_mesh_model_in_primary(model)) { LOG_ERR("SAR Configuration Client only allowed in primary element"); return -EINVAL; } - if (!model->user_data) { + if (!model->rt->user_data) { LOG_ERR("No SAR Configuration Client context provided"); return -EINVAL; } - cli = model->user_data; + cli = model->rt->user_data; cli->model = model; cli->timeout = 2 * MSEC_PER_SEC; model->keys[0] = BT_MESH_KEY_DEV_ANY; - model->flags |= BT_MESH_MOD_DEVKEY_ONLY; + model->rt->flags |= BT_MESH_MOD_DEVKEY_ONLY; bt_mesh_msg_ack_ctx_init(&cli->ack_ctx); return 0; } -static void bt_mesh_sar_cfg_cli_reset(struct bt_mesh_model *model) +static void bt_mesh_sar_cfg_cli_reset(const struct bt_mesh_model *model) { struct bt_mesh_sar_cfg_cli *model_cli; - model_cli = model->user_data; + model_cli = model->rt->user_data; bt_mesh_msg_ack_ctx_clear(&model_cli->ack_ctx); } diff --git a/subsys/bluetooth/mesh/sar_cfg_srv.c b/subsys/bluetooth/mesh/sar_cfg_srv.c index e05489ee0cf..2943ce02ddd 100644 --- a/subsys/bluetooth/mesh/sar_cfg_srv.c +++ b/subsys/bluetooth/mesh/sar_cfg_srv.c @@ -27,7 +27,7 @@ #include LOG_MODULE_REGISTER(bt_mesh_sar_cfg_srv); -static int sar_rx_store(struct bt_mesh_model *model, bool delete) +static int sar_rx_store(const struct bt_mesh_model *model, bool delete) { const void *data = delete ? NULL : &bt_mesh.sar_rx; size_t len = delete ? 0 : sizeof(struct bt_mesh_sar_rx); @@ -35,7 +35,7 @@ static int sar_rx_store(struct bt_mesh_model *model, bool delete) return bt_mesh_model_data_store(model, false, "sar_rx", data, len); } -static int sar_tx_store(struct bt_mesh_model *model, bool delete) +static int sar_tx_store(const struct bt_mesh_model *model, bool delete) { const void *data = delete ? NULL : &bt_mesh.sar_tx; size_t len = delete ? 0 : sizeof(struct bt_mesh_sar_tx); @@ -43,7 +43,7 @@ static int sar_tx_store(struct bt_mesh_model *model, bool delete) return bt_mesh_model_data_store(model, false, "sar_tx", data, len); } -static void transmitter_status(struct bt_mesh_model *model, +static void transmitter_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx) { BT_MESH_MODEL_BUF_DEFINE(msg, OP_SAR_CFG_TX_STATUS, BT_MESH_SAR_TX_LEN); @@ -63,7 +63,7 @@ static void transmitter_status(struct bt_mesh_model *model, } } -static void receiver_status(struct bt_mesh_model *model, +static void receiver_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx) { BT_MESH_MODEL_BUF_DEFINE(msg, OP_SAR_CFG_RX_STATUS, BT_MESH_SAR_RX_LEN); @@ -81,7 +81,7 @@ static void receiver_status(struct bt_mesh_model *model, } } -static int transmitter_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int transmitter_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { LOG_DBG("src 0x%04x", ctx->addr); @@ -91,7 +91,7 @@ static int transmitter_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx * return 0; } -static int transmitter_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int transmitter_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { struct bt_mesh_sar_tx *tx = &bt_mesh.sar_tx; @@ -108,7 +108,7 @@ static int transmitter_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx * return 0; } -static int receiver_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int receiver_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { LOG_DBG("src 0x%04x", ctx->addr); @@ -118,7 +118,7 @@ static int receiver_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx return 0; } -static int receiver_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int receiver_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { struct bt_mesh_sar_rx *rx = &bt_mesh.sar_rx; @@ -143,7 +143,7 @@ const struct bt_mesh_model_op bt_mesh_sar_cfg_srv_op[] = { BT_MESH_MODEL_OP_END, }; -static int sar_cfg_srv_init(struct bt_mesh_model *model) +static int sar_cfg_srv_init(const struct bt_mesh_model *model) { if (!bt_mesh_model_in_primary(model)) { LOG_ERR("Configuration Server only allowed in primary element"); @@ -155,12 +155,12 @@ static int sar_cfg_srv_init(struct bt_mesh_model *model) * device-key is allowed to access this model. */ model->keys[0] = BT_MESH_KEY_DEV_LOCAL; - model->flags |= BT_MESH_MOD_DEVKEY_ONLY; + model->rt->flags |= BT_MESH_MOD_DEVKEY_ONLY; return 0; } -static void sar_cfg_srv_reset(struct bt_mesh_model *model) +static void sar_cfg_srv_reset(const struct bt_mesh_model *model) { struct bt_mesh_sar_tx sar_tx = BT_MESH_SAR_TX_INIT; struct bt_mesh_sar_rx sar_rx = BT_MESH_SAR_RX_INIT; @@ -175,8 +175,9 @@ static void sar_cfg_srv_reset(struct bt_mesh_model *model) } #ifdef CONFIG_BT_SETTINGS -static int sar_cfg_srv_settings_set(struct bt_mesh_model *model, const char *name, size_t len_rd, - settings_read_cb read_cb, void *cb_data) +static int sar_cfg_srv_settings_set(const struct bt_mesh_model *model, const char *name, + size_t len_rd, settings_read_cb read_cb, + void *cb_data) { if (!strncmp(name, "sar_rx", 5)) { return bt_mesh_settings_set(read_cb, cb_data, &bt_mesh.sar_rx, diff --git a/subsys/bluetooth/mesh/shell/blob.c b/subsys/bluetooth/mesh/shell/blob.c index a3ecdee241e..a6888da4270 100644 --- a/subsys/bluetooth/mesh/shell/blob.c +++ b/subsys/bluetooth/mesh/shell/blob.c @@ -271,7 +271,7 @@ static int cmd_flash_stream_unset(const struct shell *sh, size_t argc, char *arg #if defined(CONFIG_BT_MESH_SHELL_BLOB_CLI) -static struct bt_mesh_model *mod_cli; +static const struct bt_mesh_model *mod_cli; static void blob_cli_inputs_prepare(uint16_t group) { @@ -351,7 +351,7 @@ static int cmd_tx(const struct shell *sh, size_t argc, char *argv[]) "pull", blob_cli_xfer.xfer.size, group); - err = bt_mesh_blob_cli_send((struct bt_mesh_blob_cli *)mod_cli->user_data, + err = bt_mesh_blob_cli_send((struct bt_mesh_blob_cli *)mod_cli->rt->user_data, &blob_cli_xfer.inputs, &blob_cli_xfer.xfer, bt_mesh_shell_blob_io); if (err) { @@ -421,7 +421,7 @@ static int cmd_caps(const struct shell *sh, size_t argc, char *argv[]) blob_cli_inputs_prepare(group); - err = bt_mesh_blob_cli_caps_get((struct bt_mesh_blob_cli *)mod_cli->user_data, + err = bt_mesh_blob_cli_caps_get((struct bt_mesh_blob_cli *)mod_cli->rt->user_data, &blob_cli_xfer.inputs); if (err) { shell_print(sh, "Boundary check start failed (err: %d)", err); @@ -438,7 +438,7 @@ static int cmd_tx_cancel(const struct shell *sh, size_t argc, } shell_print(sh, "Cancelling transfer"); - bt_mesh_blob_cli_cancel((struct bt_mesh_blob_cli *)mod_cli->user_data); + bt_mesh_blob_cli_cancel((struct bt_mesh_blob_cli *)mod_cli->rt->user_data); return 0; } @@ -465,7 +465,7 @@ static int cmd_tx_get(const struct shell *sh, size_t argc, char *argv[]) blob_cli_inputs_prepare(group); - err = bt_mesh_blob_cli_xfer_progress_get((struct bt_mesh_blob_cli *)mod_cli->user_data, + err = bt_mesh_blob_cli_xfer_progress_get((struct bt_mesh_blob_cli *)mod_cli->rt->user_data, &blob_cli_xfer.inputs); if (err) { shell_print(sh, "ERR %d", err); @@ -482,7 +482,7 @@ static int cmd_tx_suspend(const struct shell *sh, size_t argc, } shell_print(sh, "Suspending transfer"); - bt_mesh_blob_cli_suspend((struct bt_mesh_blob_cli *)mod_cli->user_data); + bt_mesh_blob_cli_suspend((struct bt_mesh_blob_cli *)mod_cli->rt->user_data); return 0; } @@ -494,7 +494,7 @@ static int cmd_tx_resume(const struct shell *sh, size_t argc, char *argv[]) } shell_print(sh, "Resuming transfer"); - bt_mesh_blob_cli_resume((struct bt_mesh_blob_cli *)mod_cli->user_data); + bt_mesh_blob_cli_resume((struct bt_mesh_blob_cli *)mod_cli->rt->user_data); return 0; } @@ -503,7 +503,7 @@ static int cmd_tx_resume(const struct shell *sh, size_t argc, char *argv[]) #if defined(CONFIG_BT_MESH_SHELL_BLOB_SRV) -static struct bt_mesh_model *mod_srv; +static const struct bt_mesh_model *mod_srv; static int cmd_rx(const struct shell *sh, size_t argc, char *argv[]) { @@ -530,7 +530,7 @@ static int cmd_rx(const struct shell *sh, size_t argc, char *argv[]) } shell_print(sh, "Receive BLOB 0x%x", id); - err = bt_mesh_blob_srv_recv((struct bt_mesh_blob_srv *)mod_srv->user_data, + err = bt_mesh_blob_srv_recv((struct bt_mesh_blob_srv *)mod_srv->rt->user_data, id, bt_mesh_shell_blob_io, BT_MESH_TTL_MAX, timeout_base); if (err) { shell_print(sh, "BLOB RX setup failed (%d)", err); @@ -548,7 +548,7 @@ static int cmd_rx_cancel(const struct shell *sh, size_t argc, char *argv[]) } shell_print(sh, "Cancelling BLOB rx"); - err = bt_mesh_blob_srv_cancel((struct bt_mesh_blob_srv *)mod_srv->user_data); + err = bt_mesh_blob_srv_cancel((struct bt_mesh_blob_srv *)mod_srv->rt->user_data); if (err) { shell_print(sh, "BLOB cancel failed (%d)", err); } diff --git a/subsys/bluetooth/mesh/shell/dfd.c b/subsys/bluetooth/mesh/shell/dfd.c index 0415929dfec..4b3d4970282 100644 --- a/subsys/bluetooth/mesh/shell/dfd.c +++ b/subsys/bluetooth/mesh/shell/dfd.c @@ -14,7 +14,7 @@ #include "../dfd_srv_internal.h" #include "../access.h" -static struct bt_mesh_model *mod; +static const struct bt_mesh_model *mod; static void print_receivers_status(const struct shell *sh, struct bt_mesh_dfd_srv *srv, enum bt_mesh_dfd_status status) @@ -70,7 +70,7 @@ static int cmd_dfd_receivers_add(const struct shell *sh, size_t argc, char *argv return -ENODEV; } - struct bt_mesh_dfd_srv *dfd_srv = mod->user_data; + struct bt_mesh_dfd_srv *dfd_srv = mod->rt->user_data; if (bt_mesh_dfu_cli_is_busy(&dfd_srv->dfu)) { print_receivers_status(sh, dfd_srv, @@ -122,7 +122,7 @@ static int cmd_dfd_receivers_delete_all(const struct shell *sh, size_t argc, cha return -ENODEV; } - struct bt_mesh_dfd_srv *dfd_srv = mod->user_data; + struct bt_mesh_dfd_srv *dfd_srv = mod->rt->user_data; enum bt_mesh_dfd_status status = bt_mesh_dfd_srv_receivers_delete_all( dfd_srv); @@ -142,7 +142,7 @@ static int cmd_dfd_receivers_get(const struct shell *sh, size_t argc, char *argv return -ENODEV; } - struct bt_mesh_dfd_srv *dfd_srv = mod->user_data; + struct bt_mesh_dfd_srv *dfd_srv = mod->rt->user_data; int err = 0; uint16_t first = shell_strtoul(argv[1], 0, &err); @@ -197,7 +197,7 @@ static int cmd_dfd_get(const struct shell *sh, size_t argc, char *argv[]) return -ENODEV; } - struct bt_mesh_dfd_srv *dfd_srv = mod->user_data; + struct bt_mesh_dfd_srv *dfd_srv = mod->rt->user_data; print_dfd_status(sh, dfd_srv, BT_MESH_DFD_SUCCESS); @@ -210,7 +210,7 @@ static int cmd_dfd_start(const struct shell *sh, size_t argc, char *argv[]) return -ENODEV; } - struct bt_mesh_dfd_srv *dfd_srv = mod->user_data; + struct bt_mesh_dfd_srv *dfd_srv = mod->rt->user_data; struct bt_mesh_dfd_start_params params; int err = 0; @@ -267,7 +267,7 @@ static int cmd_dfd_suspend(const struct shell *sh, size_t argc, char *argv[]) return -ENODEV; } - struct bt_mesh_dfd_srv *dfd_srv = mod->user_data; + struct bt_mesh_dfd_srv *dfd_srv = mod->rt->user_data; enum bt_mesh_dfd_status status = bt_mesh_dfd_srv_suspend(dfd_srv); @@ -285,7 +285,7 @@ static int cmd_dfd_cancel(const struct shell *sh, size_t argc, char *argv[]) return -ENODEV; } - struct bt_mesh_dfd_srv *dfd_srv = mod->user_data; + struct bt_mesh_dfd_srv *dfd_srv = mod->rt->user_data; enum bt_mesh_dfd_status status = bt_mesh_dfd_srv_cancel(dfd_srv, NULL); @@ -303,7 +303,7 @@ static int cmd_dfd_apply(const struct shell *sh, size_t argc, char *argv[]) return -ENODEV; } - struct bt_mesh_dfd_srv *dfd_srv = mod->user_data; + struct bt_mesh_dfd_srv *dfd_srv = mod->rt->user_data; enum bt_mesh_dfd_status status = bt_mesh_dfd_srv_apply(dfd_srv); @@ -364,7 +364,7 @@ static int cmd_dfd_fw_delete(const struct shell *sh, size_t argc, char *argv[]) return -ENODEV; } - struct bt_mesh_dfd_srv *dfd_srv = mod->user_data; + struct bt_mesh_dfd_srv *dfd_srv = mod->rt->user_data; uint8_t fwid_buf[CONFIG_BT_MESH_DFU_FWID_MAXLEN]; size_t hexlen = strlen(argv[1]); @@ -394,7 +394,7 @@ static int cmd_dfd_fw_delete_all(const struct shell *sh, size_t argc, char *argv return -ENODEV; } - struct bt_mesh_dfd_srv *dfd_srv = mod->user_data; + struct bt_mesh_dfd_srv *dfd_srv = mod->rt->user_data; enum bt_mesh_dfd_status status = bt_mesh_dfd_srv_fw_delete_all(dfd_srv); diff --git a/subsys/bluetooth/mesh/shell/dfu.c b/subsys/bluetooth/mesh/shell/dfu.c index 8d7fc96e014..6b7df4a8bd4 100644 --- a/subsys/bluetooth/mesh/shell/dfu.c +++ b/subsys/bluetooth/mesh/shell/dfu.c @@ -505,7 +505,7 @@ static int cmd_dfu_slot_get(const struct shell *sh, size_t argc, char *argv[]) #if defined(CONFIG_BT_MESH_SHELL_DFU_CLI) -static struct bt_mesh_model *mod_cli; +static const struct bt_mesh_model *mod_cli; static struct { struct bt_mesh_dfu_target targets[32]; @@ -587,7 +587,7 @@ static int cmd_dfu_target_state(const struct shell *sh, size_t argc, char *argv[ return -ENODEV; } - err = bt_mesh_dfu_cli_status_get((struct bt_mesh_dfu_cli *)mod_cli->user_data, + err = bt_mesh_dfu_cli_status_get((struct bt_mesh_dfu_cli *)mod_cli->rt->user_data, &ctx, &rsp); if (err) { shell_print(sh, "Failed getting target status (err: %d)", @@ -654,7 +654,7 @@ static int cmd_dfu_target_imgs(const struct shell *sh, size_t argc, char *argv[] shell_print(sh, "Requesting DFU images in 0x%04x", bt_mesh_shell_target_ctx.dst); - err = bt_mesh_dfu_cli_imgs_get((struct bt_mesh_dfu_cli *)mod_cli->user_data, + err = bt_mesh_dfu_cli_imgs_get((struct bt_mesh_dfu_cli *)mod_cli->rt->user_data, &ctx, dfu_img_cb, NULL, img_cnt); if (err) { shell_print(sh, "Request failed (err: %d)", err); @@ -694,7 +694,7 @@ static int cmd_dfu_target_check(const struct shell *sh, size_t argc, char *argv[ return 0; } - err = bt_mesh_dfu_cli_metadata_check((struct bt_mesh_dfu_cli *)mod_cli->user_data, + err = bt_mesh_dfu_cli_metadata_check((struct bt_mesh_dfu_cli *)mod_cli->rt->user_data, &ctx, img_idx, slot, &rsp); if (err) { shell_print(sh, "Metadata check failed. err: %d", err); @@ -765,7 +765,7 @@ static int cmd_dfu_send(const struct shell *sh, size_t argc, char *argv[]) dfu_tx.inputs.app_idx = bt_mesh_shell_target_ctx.app_idx; dfu_tx.inputs.ttl = BT_MESH_TTL_DEFAULT; - err = bt_mesh_dfu_cli_send((struct bt_mesh_dfu_cli *)mod_cli->user_data, + err = bt_mesh_dfu_cli_send((struct bt_mesh_dfu_cli *)mod_cli->rt->user_data, &dfu_tx.inputs, bt_mesh_shell_blob_io, &xfer); if (err) { shell_print(sh, "Failed (err: %d)", err); @@ -800,7 +800,7 @@ static int cmd_dfu_tx_cancel(const struct shell *sh, size_t argc, char *argv[]) shell_print(sh, "Cancelling DFU"); } - err = bt_mesh_dfu_cli_cancel((struct bt_mesh_dfu_cli *)mod_cli->user_data, + err = bt_mesh_dfu_cli_cancel((struct bt_mesh_dfu_cli *)mod_cli->rt->user_data, (argc == 2) ? &ctx : NULL); if (err) { shell_print(sh, "Failed (err: %d)", err); @@ -819,7 +819,7 @@ static int cmd_dfu_apply(const struct shell *sh, size_t argc, char *argv[]) shell_print(sh, "Applying DFU"); - err = bt_mesh_dfu_cli_apply((struct bt_mesh_dfu_cli *)mod_cli->user_data); + err = bt_mesh_dfu_cli_apply((struct bt_mesh_dfu_cli *)mod_cli->rt->user_data); if (err) { shell_print(sh, "Failed (err: %d)", err); } @@ -837,7 +837,7 @@ static int cmd_dfu_confirm(const struct shell *sh, size_t argc, char *argv[]) shell_print(sh, "Confirming DFU"); - err = bt_mesh_dfu_cli_confirm((struct bt_mesh_dfu_cli *)mod_cli->user_data); + err = bt_mesh_dfu_cli_confirm((struct bt_mesh_dfu_cli *)mod_cli->rt->user_data); if (err) { shell_print(sh, "Failed (err: %d)", err); } @@ -855,7 +855,7 @@ static int cmd_dfu_suspend(const struct shell *sh, size_t argc, char *argv[]) shell_print(sh, "Suspending DFU"); - err = bt_mesh_dfu_cli_suspend((struct bt_mesh_dfu_cli *)mod_cli->user_data); + err = bt_mesh_dfu_cli_suspend((struct bt_mesh_dfu_cli *)mod_cli->rt->user_data); if (err) { shell_print(sh, "Failed (err: %d)", err); } @@ -873,7 +873,7 @@ static int cmd_dfu_resume(const struct shell *sh, size_t argc, char *argv[]) shell_print(sh, "Resuming DFU"); - err = bt_mesh_dfu_cli_resume((struct bt_mesh_dfu_cli *)mod_cli->user_data); + err = bt_mesh_dfu_cli_resume((struct bt_mesh_dfu_cli *)mod_cli->rt->user_data); if (err) { shell_print(sh, "Failed (err: %d)", err); } @@ -888,7 +888,7 @@ static int cmd_dfu_tx_progress(const struct shell *sh, size_t argc, char *argv[] } shell_print(sh, "DFU progress: %u %%", - bt_mesh_dfu_cli_progress((struct bt_mesh_dfu_cli *)mod_cli->user_data)); + bt_mesh_dfu_cli_progress((struct bt_mesh_dfu_cli *)mod_cli->rt->user_data)); return 0; } @@ -896,7 +896,7 @@ static int cmd_dfu_tx_progress(const struct shell *sh, size_t argc, char *argv[] #if defined(CONFIG_BT_MESH_SHELL_DFU_SRV) -static struct bt_mesh_model *mod_srv; +static const struct bt_mesh_model *mod_srv; static int cmd_dfu_applied(const struct shell *sh, size_t argc, char *argv[]) { @@ -904,7 +904,7 @@ static int cmd_dfu_applied(const struct shell *sh, size_t argc, char *argv[]) return -ENODEV; } - bt_mesh_dfu_srv_applied((struct bt_mesh_dfu_srv *)mod_srv->user_data); + bt_mesh_dfu_srv_applied((struct bt_mesh_dfu_srv *)mod_srv->rt->user_data); return 0; } @@ -914,7 +914,7 @@ static int cmd_dfu_rx_cancel(const struct shell *sh, size_t argc, char *argv[]) return -ENODEV; } - bt_mesh_dfu_srv_cancel((struct bt_mesh_dfu_srv *)mod_srv->user_data); + bt_mesh_dfu_srv_cancel((struct bt_mesh_dfu_srv *)mod_srv->rt->user_data); return 0; } @@ -925,7 +925,7 @@ static int cmd_dfu_rx_progress(const struct shell *sh, size_t argc, char *argv[] } shell_print(sh, "DFU progress: %u %%", - bt_mesh_dfu_srv_progress((struct bt_mesh_dfu_srv *)mod_srv->user_data)); + bt_mesh_dfu_srv_progress((struct bt_mesh_dfu_srv *)mod_srv->rt->user_data)); return 0; } diff --git a/subsys/bluetooth/mesh/shell/health.c b/subsys/bluetooth/mesh/shell/health.c index efc7eb84e62..21480c6a66e 100644 --- a/subsys/bluetooth/mesh/shell/health.c +++ b/subsys/bluetooth/mesh/shell/health.c @@ -13,7 +13,7 @@ #include "utils.h" #include -static struct bt_mesh_model *mod; +static const struct bt_mesh_model *mod; static void show_faults(const struct shell *sh, uint8_t test_id, uint16_t cid, uint8_t *faults, size_t fault_count) @@ -40,7 +40,7 @@ static int cmd_fault_get(const struct shell *sh, size_t argc, char *argv[]) return -ENODEV; } - struct bt_mesh_health_cli *cli = mod->user_data; + struct bt_mesh_health_cli *cli = mod->rt->user_data; struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_APP(bt_mesh_shell_target_ctx.app_idx, bt_mesh_shell_target_ctx.dst); uint8_t faults[32]; @@ -74,7 +74,7 @@ static int fault_clear(const struct shell *sh, size_t argc, char *argv[], bool a return -ENODEV; } - struct bt_mesh_health_cli *cli = mod->user_data; + struct bt_mesh_health_cli *cli = mod->rt->user_data; struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_APP(bt_mesh_shell_target_ctx.app_idx, bt_mesh_shell_target_ctx.dst); uint8_t test_id; @@ -126,7 +126,7 @@ static int fault_test(const struct shell *sh, size_t argc, char *argv[], bool ac return -ENODEV; } - struct bt_mesh_health_cli *cli = mod->user_data; + struct bt_mesh_health_cli *cli = mod->rt->user_data; struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_APP(bt_mesh_shell_target_ctx.app_idx, bt_mesh_shell_target_ctx.dst); uint8_t test_id; @@ -179,7 +179,7 @@ static int cmd_period_get(const struct shell *sh, size_t argc, char *argv[]) return -ENODEV; } - struct bt_mesh_health_cli *cli = mod->user_data; + struct bt_mesh_health_cli *cli = mod->rt->user_data; struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_APP(bt_mesh_shell_target_ctx.app_idx, bt_mesh_shell_target_ctx.dst); uint8_t divisor; @@ -201,7 +201,7 @@ static int period_set(const struct shell *sh, size_t argc, char *argv[], bool ac return -ENODEV; } - struct bt_mesh_health_cli *cli = mod->user_data; + struct bt_mesh_health_cli *cli = mod->rt->user_data; struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_APP(bt_mesh_shell_target_ctx.app_idx, bt_mesh_shell_target_ctx.dst); uint8_t divisor; @@ -251,7 +251,7 @@ static int cmd_attention_get(const struct shell *sh, size_t argc, char *argv[]) return -ENODEV; } - struct bt_mesh_health_cli *cli = mod->user_data; + struct bt_mesh_health_cli *cli = mod->rt->user_data; struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_APP(bt_mesh_shell_target_ctx.app_idx, bt_mesh_shell_target_ctx.dst); uint8_t attention; @@ -273,7 +273,7 @@ static int attention_set(const struct shell *sh, size_t argc, char *argv[], bool return -ENODEV; } - struct bt_mesh_health_cli *cli = mod->user_data; + struct bt_mesh_health_cli *cli = mod->rt->user_data; struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_APP(bt_mesh_shell_target_ctx.app_idx, bt_mesh_shell_target_ctx.dst); uint8_t attention; diff --git a/subsys/bluetooth/mesh/shell/od_priv_proxy.c b/subsys/bluetooth/mesh/shell/od_priv_proxy.c index da353b9e95b..517fcfcaea3 100644 --- a/subsys/bluetooth/mesh/shell/od_priv_proxy.c +++ b/subsys/bluetooth/mesh/shell/od_priv_proxy.c @@ -15,13 +15,12 @@ static int cmd_od_priv_gatt_proxy_set(const struct shell *sh, size_t argc, char *argv[]) { uint8_t val, val_rsp; + uint16_t net_idx = bt_mesh_shell_target_ctx.net_idx; + uint16_t addr = bt_mesh_shell_target_ctx.dst; int err = 0; - struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_DEV(bt_mesh_shell_target_ctx.net_idx, - bt_mesh_shell_target_ctx.dst); - if (argc < 2) { - err = bt_mesh_od_priv_proxy_cli_get(&ctx, &val_rsp); + err = bt_mesh_od_priv_proxy_cli_get(net_idx, addr, &val_rsp); } else { val = shell_strtoul(argv[1], 0, &err); @@ -30,7 +29,7 @@ static int cmd_od_priv_gatt_proxy_set(const struct shell *sh, size_t argc, return err; } - err = bt_mesh_od_priv_proxy_cli_set(&ctx, val, &val_rsp); + err = bt_mesh_od_priv_proxy_cli_set(net_idx, addr, val, &val_rsp); } if (err) { diff --git a/subsys/bluetooth/mesh/shell/priv_beacon.c b/subsys/bluetooth/mesh/shell/priv_beacon.c index 296d96b114e..71b0da91e50 100644 --- a/subsys/bluetooth/mesh/shell/priv_beacon.c +++ b/subsys/bluetooth/mesh/shell/priv_beacon.c @@ -48,7 +48,7 @@ static int cmd_priv_beacon_set(const struct shell *sh, size_t argc, char *argv[] err = bt_mesh_priv_beacon_cli_set(bt_mesh_shell_target_ctx.net_idx, bt_mesh_shell_target_ctx.dst, - &val); + &val, &val); if (err) { shell_error(sh, "Failed to send Private Beacon Set (err %d)", err); return 0; @@ -86,7 +86,7 @@ static int cmd_priv_gatt_proxy_set(const struct shell *sh, size_t argc, char *ar } err = bt_mesh_priv_beacon_cli_gatt_proxy_set(bt_mesh_shell_target_ctx.net_idx, - bt_mesh_shell_target_ctx.dst, &state); + bt_mesh_shell_target_ctx.dst, state, &state); if (err) { shell_error(sh, "Failed to send Private GATT Proxy Set (err %d)", err); return 0; @@ -130,7 +130,7 @@ static int cmd_priv_node_id_set(const struct shell *sh, size_t argc, char *argv[ } err = bt_mesh_priv_beacon_cli_node_id_set(bt_mesh_shell_target_ctx.net_idx, - bt_mesh_shell_target_ctx.dst, &val); + bt_mesh_shell_target_ctx.dst, &val, &val); if (err) { shell_error(sh, "Failed to send Private Node Identity Set (err %d)", err); return 0; diff --git a/subsys/bluetooth/mesh/shell/rpr.c b/subsys/bluetooth/mesh/shell/rpr.c index c8f05817104..870fc7c5d37 100644 --- a/subsys/bluetooth/mesh/shell/rpr.c +++ b/subsys/bluetooth/mesh/shell/rpr.c @@ -11,7 +11,7 @@ #include "utils.h" -static struct bt_mesh_model *mod; +static const struct bt_mesh_model *mod; /*************************************************************************************************** * Implementation of the model's instance @@ -108,7 +108,7 @@ static int cmd_scan(const struct shell *sh, size_t argc, char *argv[]) hex2bin(argv[2], strlen(argv[2]), uuid, 16); } - err = bt_mesh_rpr_scan_start((struct bt_mesh_rpr_cli *)mod->user_data, + err = bt_mesh_rpr_scan_start((struct bt_mesh_rpr_cli *)mod->rt->user_data, &srv, argc > 2 ? uuid : NULL, timeout, BT_MESH_RPR_SCAN_MAX_DEVS_ANY, &rsp); if (err) { @@ -153,7 +153,7 @@ static int cmd_scan_ext(const struct shell *sh, size_t argc, char *argv[]) return err; } - err = bt_mesh_rpr_scan_start_ext((struct bt_mesh_rpr_cli *)mod->user_data, + err = bt_mesh_rpr_scan_start_ext((struct bt_mesh_rpr_cli *)mod->rt->user_data, &srv, uuid, timeout, ad_types, (argc - 3)); if (err) { @@ -189,7 +189,7 @@ static int cmd_scan_srv(const struct shell *sh, size_t argc, char *argv[]) return err; } - err = bt_mesh_rpr_scan_start_ext((struct bt_mesh_rpr_cli *)mod->user_data, + err = bt_mesh_rpr_scan_start_ext((struct bt_mesh_rpr_cli *)mod->rt->user_data, &srv, NULL, 0, ad_types, (argc - 1)); if (err) { shell_print(sh, "Scan start failed: %d", err); @@ -213,7 +213,7 @@ static int cmd_scan_caps(const struct shell *sh, size_t argc, char *argv[]) return -ENODEV; } - err = bt_mesh_rpr_scan_caps_get((struct bt_mesh_rpr_cli *)mod->user_data, &srv, &caps); + err = bt_mesh_rpr_scan_caps_get((struct bt_mesh_rpr_cli *)mod->rt->user_data, &srv, &caps); if (err) { shell_print(sh, "Scan capabilities get failed: %d", err); return err; @@ -241,7 +241,7 @@ static int cmd_scan_get(const struct shell *sh, size_t argc, char *argv[]) return -ENODEV; } - err = bt_mesh_rpr_scan_get((struct bt_mesh_rpr_cli *)mod->user_data, &srv, &rsp); + err = bt_mesh_rpr_scan_get((struct bt_mesh_rpr_cli *)mod->rt->user_data, &srv, &rsp); if (err) { shell_print(sh, "Scan get failed: %d", err); return err; @@ -269,7 +269,7 @@ static int cmd_scan_stop(const struct shell *sh, size_t argc, char *argv[]) return -ENODEV; } - err = bt_mesh_rpr_scan_stop((struct bt_mesh_rpr_cli *)mod->user_data, &srv, &rsp); + err = bt_mesh_rpr_scan_stop((struct bt_mesh_rpr_cli *)mod->rt->user_data, &srv, &rsp); if (err || rsp.status) { shell_print(sh, "Scan stop failed: %d %u", err, rsp.status); return err; @@ -294,7 +294,7 @@ static int cmd_link_get(const struct shell *sh, size_t argc, char *argv[]) return -ENODEV; } - err = bt_mesh_rpr_link_get((struct bt_mesh_rpr_cli *)mod->user_data, &srv, &rsp); + err = bt_mesh_rpr_link_get((struct bt_mesh_rpr_cli *)mod->rt->user_data, &srv, &rsp); if (err) { shell_print(sh, "Link get failed: %d %u", err, rsp.status); return err; @@ -316,7 +316,7 @@ static int cmd_link_close(const struct shell *sh, size_t argc, char *argv[]) }; int err; - err = bt_mesh_rpr_link_close((struct bt_mesh_rpr_cli *)mod->user_data, &srv, &rsp); + err = bt_mesh_rpr_link_close((struct bt_mesh_rpr_cli *)mod->rt->user_data, &srv, &rsp); if (err) { shell_print(sh, "Link close failed: %d %u", err, rsp.status); return err; @@ -355,7 +355,7 @@ static int cmd_provision_remote(const struct shell *sh, size_t argc, char *argv[ return err; } - err = bt_mesh_provision_remote((struct bt_mesh_rpr_cli *)mod->user_data, + err = bt_mesh_provision_remote((struct bt_mesh_rpr_cli *)mod->rt->user_data, &srv, uuid, net_idx, addr); if (err) { shell_print(sh, "Prov remote start failed: %d", err); @@ -396,7 +396,7 @@ static int cmd_reprovision_remote(const struct shell *sh, size_t argc, char *arg return err; } - err = bt_mesh_reprovision_remote((struct bt_mesh_rpr_cli *)mod->user_data, + err = bt_mesh_reprovision_remote((struct bt_mesh_rpr_cli *)mod->rt->user_data, &srv, addr, composition_changed); if (err) { shell_print(sh, "Reprovisioning failed: %d", err); diff --git a/subsys/bluetooth/mesh/shell/shell.c b/subsys/bluetooth/mesh/shell/shell.c index c5592db02cf..a169bb16422 100644 --- a/subsys/bluetooth/mesh/shell/shell.c +++ b/subsys/bluetooth/mesh/shell/shell.c @@ -68,7 +68,7 @@ static void get_faults(uint8_t *faults, uint8_t faults_size, uint8_t *dst, uint8 } } -static int fault_get_cur(struct bt_mesh_model *model, uint8_t *test_id, +static int fault_get_cur(const struct bt_mesh_model *model, uint8_t *test_id, uint16_t *company_id, uint8_t *faults, uint8_t *fault_count) { shell_print_ctx("Sending current faults"); @@ -81,7 +81,7 @@ static int fault_get_cur(struct bt_mesh_model *model, uint8_t *test_id, return 0; } -static int fault_get_reg(struct bt_mesh_model *model, uint16_t cid, +static int fault_get_reg(const struct bt_mesh_model *model, uint16_t cid, uint8_t *test_id, uint8_t *faults, uint8_t *fault_count) { if (cid != CONFIG_BT_COMPANY_ID) { @@ -99,7 +99,7 @@ static int fault_get_reg(struct bt_mesh_model *model, uint16_t cid, return 0; } -static int fault_clear(struct bt_mesh_model *model, uint16_t cid) +static int fault_clear(const struct bt_mesh_model *model, uint16_t cid) { if (cid != CONFIG_BT_COMPANY_ID) { return -EINVAL; @@ -110,7 +110,7 @@ static int fault_clear(struct bt_mesh_model *model, uint16_t cid) return 0; } -static int fault_test(struct bt_mesh_model *model, uint8_t test_id, +static int fault_test(const struct bt_mesh_model *model, uint8_t test_id, uint16_t cid) { if (cid != CONFIG_BT_COMPANY_ID) { @@ -124,12 +124,12 @@ static int fault_test(struct bt_mesh_model *model, uint8_t test_id, return 0; } -static void attention_on(struct bt_mesh_model *model) +static void attention_on(const struct bt_mesh_model *model) { shell_print_ctx("Attention On"); } -static void attention_off(struct bt_mesh_model *model) +static void attention_off(const struct bt_mesh_model *model) { shell_print_ctx("Attention Off"); } @@ -387,6 +387,7 @@ static int cmd_proxy_disconnect(const struct shell *sh, size_t argc, return 0; } +#endif /* CONFIG_BT_MESH_PROXY_CLIENT */ #if defined(CONFIG_BT_MESH_PROXY_SOLICITATION) static int cmd_proxy_solicit(const struct shell *sh, size_t argc, @@ -410,7 +411,6 @@ static int cmd_proxy_solicit(const struct shell *sh, size_t argc, return err; } #endif /* CONFIG_BT_MESH_PROXY_SOLICITATION */ -#endif /* CONFIG_BT_MESH_PROXY_CLIENT */ #endif /* CONFIG_BT_MESH_SHELL_GATT_PROXY */ #if defined(CONFIG_BT_MESH_SHELL_PROV) @@ -944,7 +944,7 @@ static int cmd_provision_adv(const struct shell *sh, size_t argc, static int cmd_provision_local(const struct shell *sh, size_t argc, char *argv[]) { - uint8_t *net_key = (uint8_t *)bt_mesh_shell_default_key; + uint8_t net_key[16]; uint16_t net_idx, addr; uint32_t iv_index; int err = 0; @@ -963,6 +963,8 @@ static int cmd_provision_local(const struct shell *sh, size_t argc, char *argv[] return err; } + memcpy(net_key, bt_mesh_shell_default_key, sizeof(net_key)); + if (IS_ENABLED(CONFIG_BT_MESH_CDB)) { struct bt_mesh_cdb_subnet *sub; @@ -1068,7 +1070,7 @@ static int cmd_rpl_clear(const struct shell *sh, size_t argc, char *argv[]) } #if defined(CONFIG_BT_MESH_SHELL_HEALTH_SRV_INSTANCE) -static struct bt_mesh_elem *primary_element(void) +static const struct bt_mesh_elem *primary_element(void) { const struct bt_mesh_comp *comp = bt_mesh_comp_get(); @@ -1083,7 +1085,7 @@ static int cmd_add_fault(const struct shell *sh, size_t argc, char *argv[]) { uint8_t fault_id; uint8_t i; - struct bt_mesh_elem *elem; + const struct bt_mesh_elem *elem; int err = 0; elem = primary_element(); @@ -1136,7 +1138,7 @@ static int cmd_del_fault(const struct shell *sh, size_t argc, char *argv[]) { uint8_t fault_id; uint8_t i; - struct bt_mesh_elem *elem; + const struct bt_mesh_elem *elem; int err = 0; elem = primary_element(); @@ -1739,11 +1741,11 @@ SHELL_STATIC_SUBCMD_SET_CREATE(proxy_cmds, #if defined(CONFIG_BT_MESH_PROXY_CLIENT) SHELL_CMD_ARG(connect, NULL, "", cmd_proxy_connect, 2, 0), SHELL_CMD_ARG(disconnect, NULL, "", cmd_proxy_disconnect, 2, 0), +#endif #if defined(CONFIG_BT_MESH_PROXY_SOLICITATION) SHELL_CMD_ARG(solicit, NULL, "", cmd_proxy_solicit, 2, 0), -#endif #endif SHELL_SUBCMD_SET_END); #endif /* CONFIG_BT_MESH_SHELL_GATT_PROXY */ diff --git a/subsys/bluetooth/mesh/shell/utils.c b/subsys/bluetooth/mesh/shell/utils.c index 8b7ca740663..7ae09f943ca 100644 --- a/subsys/bluetooth/mesh/shell/utils.c +++ b/subsys/bluetooth/mesh/shell/utils.c @@ -13,7 +13,7 @@ #include "mesh/access.h" #include "utils.h" -bool bt_mesh_shell_mdl_first_get(uint16_t id, struct bt_mesh_model **mod) +bool bt_mesh_shell_mdl_first_get(uint16_t id, const struct bt_mesh_model **mod) { const struct bt_mesh_comp *comp = bt_mesh_comp_get(); @@ -27,10 +27,10 @@ bool bt_mesh_shell_mdl_first_get(uint16_t id, struct bt_mesh_model **mod) return false; } -int bt_mesh_shell_mdl_instance_set(const struct shell *sh, struct bt_mesh_model **mod, +int bt_mesh_shell_mdl_instance_set(const struct shell *sh, const struct bt_mesh_model **mod, uint16_t mod_id, uint8_t elem_idx) { - struct bt_mesh_model *mod_temp; + const struct bt_mesh_model *mod_temp; const struct bt_mesh_comp *comp = bt_mesh_comp_get(); if (elem_idx >= comp->elem_count) { @@ -53,14 +53,14 @@ int bt_mesh_shell_mdl_instance_set(const struct shell *sh, struct bt_mesh_model int bt_mesh_shell_mdl_print_all(const struct shell *sh, uint16_t mod_id) { const struct bt_mesh_comp *comp = bt_mesh_comp_get(); - struct bt_mesh_model *mod; + const struct bt_mesh_model *mod; for (int i = 0; i < comp->elem_count; i++) { mod = bt_mesh_model_find(&comp->elem[i], mod_id); if (mod) { shell_print(sh, "Client model instance found at addr 0x%.4X. Element index: %d", - comp->elem[i].addr, mod->elem_idx); + comp->elem[i].rt->addr, mod->rt->elem_idx); } } diff --git a/subsys/bluetooth/mesh/shell/utils.h b/subsys/bluetooth/mesh/shell/utils.h index 222f1f29360..83d025d47ea 100644 --- a/subsys/bluetooth/mesh/shell/utils.h +++ b/subsys/bluetooth/mesh/shell/utils.h @@ -34,9 +34,9 @@ 0), \ SHELL_SUBCMD_SET_END); -bool bt_mesh_shell_mdl_first_get(uint16_t id, struct bt_mesh_model **mod); +bool bt_mesh_shell_mdl_first_get(uint16_t id, const struct bt_mesh_model **mod); -int bt_mesh_shell_mdl_instance_set(const struct shell *sh, struct bt_mesh_model **mod, +int bt_mesh_shell_mdl_instance_set(const struct shell *sh, const struct bt_mesh_model **mod, uint16_t mod_id, uint8_t elem_idx); int bt_mesh_shell_mdl_print_all(const struct shell *sh, uint16_t mod_id); diff --git a/subsys/bluetooth/mesh/sol_pdu_rpl_cli.c b/subsys/bluetooth/mesh/sol_pdu_rpl_cli.c index 3b8f6799b28..dd809b59996 100644 --- a/subsys/bluetooth/mesh/sol_pdu_rpl_cli.c +++ b/subsys/bluetooth/mesh/sol_pdu_rpl_cli.c @@ -22,7 +22,7 @@ struct sol_rpl_param { uint8_t *len; }; -static int handle_status(struct bt_mesh_model *mod, +static int handle_status(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -160,7 +160,7 @@ void bt_mesh_sol_pdu_rpl_cli_timeout_set(int32_t timeout) msg_timeout = timeout; } -static int sol_pdu_rpl_cli_init(struct bt_mesh_model *mod) +static int sol_pdu_rpl_cli_init(const struct bt_mesh_model *mod) { if (!bt_mesh_model_in_primary(mod)) { LOG_ERR("Solicitation PDU RPL Configuration client not in primary element"); @@ -169,7 +169,7 @@ static int sol_pdu_rpl_cli_init(struct bt_mesh_model *mod) msg_timeout = CONFIG_BT_MESH_SOL_PDU_RPL_CLI_TIMEOUT; - cli = mod->user_data; + cli = mod->rt->user_data; cli->model = mod; bt_mesh_msg_ack_ctx_init(&cli->ack_ctx); return 0; diff --git a/subsys/bluetooth/mesh/sol_pdu_rpl_srv.c b/subsys/bluetooth/mesh/sol_pdu_rpl_srv.c index e0fff397640..547494be3be 100644 --- a/subsys/bluetooth/mesh/sol_pdu_rpl_srv.c +++ b/subsys/bluetooth/mesh/sol_pdu_rpl_srv.c @@ -14,7 +14,7 @@ #include LOG_MODULE_REGISTER(bt_mesh_sol_pdu_rpl_srv); -static void sol_rpl_status_rsp(struct bt_mesh_model *mod, +static void sol_rpl_status_rsp(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, uint16_t range, uint8_t len) @@ -32,7 +32,7 @@ static void sol_rpl_status_rsp(struct bt_mesh_model *mod, bt_mesh_model_send(mod, ctx, &buf, NULL, NULL); } -static int item_clear(struct bt_mesh_model *mod, +static int item_clear(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf, bool acked) @@ -78,14 +78,14 @@ static int item_clear(struct bt_mesh_model *mod, return 0; } -static int handle_item_clear(struct bt_mesh_model *mod, +static int handle_item_clear(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { return item_clear(mod, ctx, buf, true); } -static int handle_item_clear_unacked(struct bt_mesh_model *mod, +static int handle_item_clear_unacked(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -99,7 +99,7 @@ const struct bt_mesh_model_op _bt_mesh_sol_pdu_rpl_srv_op[] = { BT_MESH_MODEL_OP_END }; -static int sol_pdu_rpl_srv_init(struct bt_mesh_model *mod) +static int sol_pdu_rpl_srv_init(const struct bt_mesh_model *mod) { if (!bt_mesh_model_in_primary(mod)) { LOG_ERR("Solicitation PDU RPL Configuration server not in primary element"); diff --git a/subsys/bluetooth/mesh/subnet.c b/subsys/bluetooth/mesh/subnet.c index e697d985c24..ef90ff8f725 100644 --- a/subsys/bluetooth/mesh/subnet.c +++ b/subsys/bluetooth/mesh/subnet.c @@ -252,7 +252,7 @@ void bt_mesh_kr_update(struct bt_mesh_subnet *sub, bool kr_flag, bool new_key) } if (sub->kr_phase == BT_MESH_KR_PHASE_1) { - /* Bluetooth Mesh Profile Specification Section 3.10.4.1: + /* MshPRTv1.1: 3.11.4.1: * Can skip phase 2 if we get KR=0 on new key. */ key_refresh(sub, (kr_flag ? BT_MESH_KR_PHASE_2 : @@ -511,7 +511,7 @@ void bt_mesh_friend_cred_destroy(struct bt_mesh_net_cred *cred) uint8_t bt_mesh_subnet_kr_phase_set(uint16_t net_idx, uint8_t *phase) { - /* Table in Bluetooth Mesh Profile Specification Section 4.2.14: */ + /* Table in MshPRTv1.1: 4.2.15: */ const uint8_t valid_transitions[] = { BIT(BT_MESH_KR_PHASE_3), /* Normal phase: KR is started by key update */ BIT(BT_MESH_KR_PHASE_2) | BIT(BT_MESH_KR_PHASE_3), /* Phase 1 */ @@ -582,7 +582,7 @@ uint8_t bt_mesh_subnet_node_id_set(uint16_t net_idx, } #if defined(CONFIG_BT_MESH_PRIV_BEACONS) - /* Implements binding from section 4.2.46.1 of MshPRTv1.1. When enabling non-private node + /* Implements binding from MshPRTv1.1: 4.2.46.1. When enabling non-private node * identity state, disable its private counterpart. */ for (int i = 0; i < ARRAY_SIZE(subnets); i++) { @@ -645,8 +645,8 @@ uint8_t bt_mesh_subnet_priv_node_id_set(uint16_t net_idx, } #if defined(CONFIG_BT_MESH_PRIV_BEACONS) - /* Reverse binding from section 4.2.46.1 doesn't allow to set private state if non-private - * state is enabled. + /* Reverse binding from MshPRTv1.1: 4.2.46.1 doesn't + * allow to set private state if non-private state is enabled. */ for (int i = 0; i < ARRAY_SIZE(subnets); i++) { if (subnets[i].net_idx != BT_MESH_KEY_UNUSED && diff --git a/subsys/bluetooth/mesh/transport.c b/subsys/bluetooth/mesh/transport.c index f4c49aa6856..94c1f698e91 100644 --- a/subsys/bluetooth/mesh/transport.c +++ b/subsys/bluetooth/mesh/transport.c @@ -934,12 +934,10 @@ static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr, uint32_t delta_ms = (uint32_t)(k_uptime_get() - tx->adv_start_timestamp); - /* According to the Bluetooth Mesh Profile specification, - * section 3.5.3.3, we should reset the retransmit timer and - * retransmit immediately when receiving a valid ack message - * while Retransmisison timer is running. However, transport should - * still keep segment transmission interval time between - * transmission of each segment. + /* According to MshPRTv1.1: 3.5.3.3.2, we should reset the retransmit timer + * and retransmit immediately when receiving a valid ack message while + * Retransmisison timer is running. However, transport should still keep + * segment transmission interval time between transmission of each segment. */ if (delta_ms < BT_MESH_SAR_TX_SEG_INT_MS) { timeout = K_MSEC(BT_MESH_SAR_TX_SEG_INT_MS - delta_ms); @@ -1370,7 +1368,7 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx, return -EBADMSG; } - /* According to Mesh 1.0 specification: + /* According to MshPRTv1.1: * "The SeqAuth is composed of the IV Index and the sequence number * (SEQ) of the first segment" * @@ -1466,7 +1464,7 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx, /* Keep track of the received SeqAuth values received from this address * and discard segmented messages that are not newer, as described in - * the Bluetooth Mesh specification section 3.5.3.4. + * MshPRTv1.1: 3.5.3.4. * * The logic on the first segmented receive is a bit special, since the * initial value of rpl->seg is 0, which would normally fail the diff --git a/subsys/bluetooth/mesh/transport_legacy.c b/subsys/bluetooth/mesh/transport_legacy.c index 23e103b4370..da0c1830f73 100644 --- a/subsys/bluetooth/mesh/transport_legacy.c +++ b/subsys/bluetooth/mesh/transport_legacy.c @@ -870,11 +870,9 @@ static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr, } if (tx->nack_count) { - /* According to the Bluetooth Mesh Profile specification, - * section 3.5.3.3, we should reset the retransmit timer and - * retransmit immediately when receiving a valid ack message. - * Don't reset the retransmit timer if we didn't finish sending - * segments. + /* According to MshPRFv1.0.1: 3.5.3.3, we should reset the retransmit timer and + * retransmit immediately when receiving a valid ack message. Don't reset the + * retransmit timer if we didn't finish sending segments. */ if (tx->seg_o == 0) { k_work_reschedule(&tx->retransmit, K_NO_WAIT); @@ -1314,7 +1312,7 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx, return -EINVAL; } - /* According to Mesh 1.0 specification: + /* According to MshPRFv1.0.1: * "The SeqAuth is composed of the IV Index and the sequence number * (SEQ) of the first segment" * @@ -1401,7 +1399,7 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx, /* Keep track of the received SeqAuth values received from this address * and discard segmented messages that are not newer, as described in - * the Bluetooth Mesh specification section 3.5.3.4. + * MshPRFv1.0.1: 3.5.3.4. * * The logic on the first segmented receive is a bit special, since the * initial value of rpl->seg is 0, which would normally fail the diff --git a/subsys/bluetooth/services/ots/ots_client.c b/subsys/bluetooth/services/ots/ots_client.c index 40c6de94b05..e14e83b047a 100644 --- a/subsys/bluetooth/services/ots/ots_client.c +++ b/subsys/bluetooth/services/ots/ots_client.c @@ -230,6 +230,9 @@ static void chan_closed(struct bt_gatt_ots_l2cap *l2cap_ctx, struct bt_conn *conn) { LOG_DBG("L2CAP closed, context: %p, conn: %p", l2cap_ctx, (void *)conn); + if (cur_inst) { + cur_inst = NULL; + } } /* End L2CAP callbacks */ diff --git a/subsys/bluetooth/services/ots/ots_l2cap.c b/subsys/bluetooth/services/ots/ots_l2cap.c index 137829b7d03..923f2c8a593 100644 --- a/subsys/bluetooth/services/ots/ots_l2cap.c +++ b/subsys/bluetooth/services/ots/ots_l2cap.c @@ -187,7 +187,8 @@ static struct bt_gatt_ots_l2cap *find_free_l2cap_ctx(void) return NULL; } -static int l2cap_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan) +static int l2cap_accept(struct bt_conn *conn, struct bt_l2cap_server *server, + struct bt_l2cap_chan **chan) { struct bt_gatt_ots_l2cap *l2cap_ctx; diff --git a/subsys/bluetooth/shell/bredr.c b/subsys/bluetooth/shell/bredr.c index 3e96676a7fe..167aaf91a47 100644 --- a/subsys/bluetooth/shell/bredr.c +++ b/subsys/bluetooth/shell/bredr.c @@ -243,7 +243,8 @@ static struct bt_l2cap_br_chan l2cap_chan = { .rx.mtu = 48, }; -static int l2cap_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan) +static int l2cap_accept(struct bt_conn *conn, struct bt_l2cap_server *server, + struct bt_l2cap_chan **chan) { shell_print(ctx_shell, "Incoming BR/EDR conn %p", conn); diff --git a/subsys/bluetooth/shell/bt.c b/subsys/bluetooth/shell/bt.c index 890eafe2210..4e0111fa757 100644 --- a/subsys/bluetooth/shell/bt.c +++ b/subsys/bluetooth/shell/bt.c @@ -67,6 +67,8 @@ static struct bt_conn_auth_info_cb auth_info_cb; #define ADV_DATA_DELIMITER ", " +#define AD_SIZE 9 + /* * Based on the maximum number of parameters for HCI_LE_Generate_DHKey * See BT Core Spec V5.2 Vol. 4, Part E, section 7.8.37 @@ -232,7 +234,7 @@ static bool is_substring(const char *substr, const char *str) } for (size_t pos = 0; pos < str_len; pos++) { - if (tolower(substr[0]) == tolower(str[pos])) { + if (tolower(substr[pos]) == tolower(str[pos])) { if (pos + sub_str_len > str_len) { return false; } @@ -1983,11 +1985,12 @@ static int cmd_adv_data(const struct shell *sh, size_t argc, char *argv[]) static uint8_t hex_data[1650]; bool appearance = false; struct bt_data *data; - struct bt_data ad[9]; - struct bt_data sd[9]; + struct bt_data ad[AD_SIZE]; + struct bt_data sd[AD_SIZE]; size_t hex_data_len; size_t ad_len = 0; size_t sd_len = 0; + size_t len = 0; bool discoverable = false; size_t *data_len; int err; @@ -2028,8 +2031,6 @@ static int cmd_adv_data(const struct shell *sh, size_t argc, char *argv[]) data = sd; data_len = &sd_len; } else { - size_t len; - len = hex2bin(arg, strlen(arg), &hex_data[hex_data_len], sizeof(hex_data) - hex_data_len); @@ -2051,15 +2052,18 @@ static int cmd_adv_data(const struct shell *sh, size_t argc, char *argv[]) atomic_set_bit_to(adv_set_opt[selected_adv], SHELL_ADV_OPT_APPEARANCE, appearance); - ad_len = ad_init(&ad[*data_len], ARRAY_SIZE(ad) - *data_len, - adv_set_opt[selected_adv]); - if (ad_len < 0) { + len = ad_init(&data[*data_len], AD_SIZE - *data_len, adv_set_opt[selected_adv]); + if (len < 0) { shell_error(sh, "Failed to initialize stack advertising data"); return -ENOEXEC; } - ad_len += *data_len; + if (data == ad) { + ad_len += len; + } else { + sd_len += len; + } err = bt_le_ext_adv_set_data(adv, ad_len > 0 ? ad : NULL, ad_len, sd_len > 0 ? sd : NULL, sd_len); diff --git a/subsys/bluetooth/shell/iso.c b/subsys/bluetooth/shell/iso.c index dcfdcfa9cb7..e11d1d011f6 100644 --- a/subsys/bluetooth/shell/iso.c +++ b/subsys/bluetooth/shell/iso.c @@ -24,6 +24,8 @@ #include "bt.h" +#define TX_BUF_TIMEOUT K_SECONDS(1) + static uint32_t cis_sn_last; static uint32_t bis_sn_last; static int64_t cis_sn_last_updated_ticks; @@ -131,15 +133,65 @@ struct bt_iso_chan iso_chan = { }; NET_BUF_POOL_FIXED_DEFINE(tx_pool, 1, BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), - 8, NULL); + CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); #if defined(CONFIG_BT_ISO_CENTRAL) static struct bt_iso_cig *cig; +static long parse_interval(const struct shell *sh, const char *interval_str) +{ + unsigned long interval; + int err; + + err = 0; + interval = shell_strtoul(interval_str, 0, &err); + if (err != 0) { + shell_error(sh, "Could not parse interval: %d", err); + + return -ENOEXEC; + } + + if (!IN_RANGE(interval, + BT_ISO_SDU_INTERVAL_MIN, + BT_ISO_SDU_INTERVAL_MAX)) { + shell_error(sh, "Invalid interval %lu", interval); + + return -ENOEXEC; + } + + return interval; +} + +static long parse_latency(const struct shell *sh, const char *latency_str) +{ + unsigned long latency; + int err; + + err = 0; + latency = shell_strtoul(latency_str, 0, &err); + if (err != 0) { + shell_error(sh, "Could not parse latency: %d", err); + + return -ENOEXEC; + } + + if (!IN_RANGE(latency, + BT_ISO_LATENCY_MIN, + BT_ISO_LATENCY_MAX)) { + shell_error(sh, "Invalid latency %lu", latency); + + return -ENOEXEC; + } + + return latency; +} + + + static int cmd_cig_create(const struct shell *sh, size_t argc, char *argv[]) { int err; - struct bt_iso_cig_param param; + struct bt_iso_cig_param param = {0}; struct bt_iso_chan *chans[CIS_ISO_CHAN_COUNT]; if (cig != NULL) { @@ -164,33 +216,44 @@ static int cmd_cig_create(const struct shell *sh, size_t argc, char *argv[]) err = 0; if (argc > 2) { - unsigned long interval; + long interval; interval = shell_strtoul(argv[2], 0, &err); - if (err != 0) { - shell_error(sh, "Could not parse interval: %d", err); - - return -ENOEXEC; + interval = parse_interval(sh, argv[2]); + if (interval < 0) { + return interval; } - if (!IN_RANGE(interval, - BT_ISO_SDU_INTERVAL_MIN, - BT_ISO_SDU_INTERVAL_MAX)) { - shell_error(sh, "Invalid interval %lu", interval); + param.c_to_p_interval = interval; + } else { + param.c_to_p_interval = 10000; + } - return -ENOEXEC; + if (argc > 3) { + long interval; + + interval = parse_interval(sh, argv[3]); + if (interval < 0) { + return interval; } - param.interval = interval; + param.p_to_c_interval = interval; } else { - param.interval = 10000; + param.p_to_c_interval = param.c_to_p_interval; } - cis_sdu_interval_us = param.interval; - if (argc > 3) { + /* cis_sdu_interval_us is used to increase the sequence number. + * cig_create can be called before an ACL is created, so the role + * information may not be available. + * Since we are central however we can safely set the cis_sdu_interval + * to the Central to Peer interval + */ + cis_sdu_interval_us = param.c_to_p_interval; + + if (argc > 4) { unsigned long packing; - packing = shell_strtoul(argv[3], 0, &err); + packing = shell_strtoul(argv[4], 0, &err); if (err != 0) { shell_error(sh, "Could not parse packing: %d", err); @@ -208,10 +271,10 @@ static int cmd_cig_create(const struct shell *sh, size_t argc, char *argv[]) param.packing = 0; } - if (argc > 4) { + if (argc > 5) { unsigned long framing; - framing = shell_strtoul(argv[4], 0, &err); + framing = shell_strtoul(argv[5], 0, &err); if (err != 0) { shell_error(sh, "Could not parse framing: %d", err); @@ -229,33 +292,38 @@ static int cmd_cig_create(const struct shell *sh, size_t argc, char *argv[]) param.framing = 0; } - if (argc > 5) { - unsigned long latency; + if (argc > 6) { + long latency; - latency = shell_strtoul(argv[5], 0, &err); - if (err != 0) { - shell_error(sh, "Could not parse latency: %d", err); + latency = parse_latency(sh, argv[6]); - return -ENOEXEC; + if (latency < 0) { + return latency; } - if (!IN_RANGE(latency, - BT_ISO_LATENCY_MIN, - BT_ISO_LATENCY_MAX)) { - shell_error(sh, "Invalid latency %lu", latency); + param.c_to_p_latency = latency; + } else { + param.c_to_p_latency = 10; + } - return -ENOEXEC; + if (argc > 7) { + long latency; + + latency = parse_latency(sh, argv[7]); + + if (latency < 0) { + return latency; } - param.latency = latency; + param.p_to_c_latency = latency; } else { - param.latency = 10; + param.p_to_c_latency = param.c_to_p_latency; } - if (argc > 6) { + if (argc > 7) { unsigned long sdu; - sdu = shell_strtoul(argv[6], 0, &err); + sdu = shell_strtoul(argv[7], 0, &err); if (err != 0) { shell_error(sh, "Could not parse sdu: %d", err); @@ -277,10 +345,10 @@ static int cmd_cig_create(const struct shell *sh, size_t argc, char *argv[]) } } - if (argc > 7) { + if (argc > 8) { unsigned long phy; - phy = shell_strtoul(argv[7], 0, &err); + phy = shell_strtoul(argv[8], 0, &err); if (err != 0) { shell_error(sh, "Could not parse phy: %d", err); @@ -304,10 +372,10 @@ static int cmd_cig_create(const struct shell *sh, size_t argc, char *argv[]) } } - if (argc > 8) { + if (argc > 9) { unsigned long rtn; - rtn = shell_strtoul(argv[8], 0, &err); + rtn = shell_strtoul(argv[9], 0, &err); if (err != 0) { shell_error(sh, "Could not parse rtn: %d", err); @@ -504,11 +572,16 @@ static int cmd_send(const struct shell *sh, size_t argc, char *argv[]) cis_sdu_interval_us); while (count--) { - buf = net_buf_alloc(&tx_pool, K_FOREVER); + buf = net_buf_alloc(&tx_pool, TX_BUF_TIMEOUT); + if (buf == NULL) { + shell_error(sh, "Failed to get buffer..."); + return -ENOEXEC; + } + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); net_buf_add_mem(buf, buf_data, len); - shell_info(sh, "send: %d bytes of data", len); + shell_info(sh, "send: %d bytes of data with PSN %u", len, cis_sn_last); ret = bt_iso_chan_send(&iso_chan, buf, cis_sn_last, BT_ISO_TIMESTAMP_NONE); if (ret < 0) { @@ -612,23 +685,25 @@ static int cmd_broadcast(const struct shell *sh, size_t argc, char *argv[]) } len = MIN(bis_iso_chan.qos->tx->sdu, CONFIG_BT_ISO_TX_MTU); - bis_sn_last = get_next_sn(bis_sn_last, &bis_sn_last_updated_ticks, bis_sdu_interval_us); while (count--) { - for (int i = 0; i < BIS_ISO_CHAN_COUNT; i++) { - buf = net_buf_alloc(&bis_tx_pool, K_FOREVER); - net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); - - net_buf_add_mem(buf, buf_data, len); - ret = bt_iso_chan_send(&bis_iso_chan, buf, bis_sn_last, - BT_ISO_TIMESTAMP_NONE); - if (ret < 0) { - shell_print(sh, "[%i]: Unable to broadcast: %d", i, -ret); - net_buf_unref(buf); - return -ENOEXEC; - } + buf = net_buf_alloc(&bis_tx_pool, TX_BUF_TIMEOUT); + if (buf == NULL) { + shell_error(sh, "Failed to get buffer..."); + return -ENOEXEC; + } + + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); + + net_buf_add_mem(buf, buf_data, len); + shell_info(sh, "send: %d bytes of data with PSN %u", len, bis_sn_last); + ret = bt_iso_chan_send(&bis_iso_chan, buf, bis_sn_last, BT_ISO_TIMESTAMP_NONE); + if (ret < 0) { + shell_print(sh, "Unable to broadcast: %d", -ret); + net_buf_unref(buf); + return -ENOEXEC; } } @@ -640,7 +715,7 @@ static int cmd_broadcast(const struct shell *sh, size_t argc, char *argv[]) static int cmd_big_create(const struct shell *sh, size_t argc, char *argv[]) { int err; - struct bt_iso_big_create_param param; + struct bt_iso_big_create_param param = {0}; struct bt_le_ext_adv *adv = adv_sets[selected_adv]; if (!adv) { @@ -860,8 +935,9 @@ static int cmd_big_term(const struct shell *sh, size_t argc, char *argv[]) SHELL_STATIC_SUBCMD_SET_CREATE(iso_cmds, #if defined(CONFIG_BT_ISO_UNICAST) #if defined(CONFIG_BT_ISO_CENTRAL) - SHELL_CMD_ARG(cig_create, NULL, "[dir=tx,rx,txrx] [interval] [packing] [framing] " - "[latency] [sdu] [phy] [rtn]", cmd_cig_create, 1, 8), + SHELL_CMD_ARG(cig_create, NULL, "[dir=tx,rx,txrx] [C to P interval] [P to C interval] " + "[packing] [framing] [C to P latency] [P to C latency] [sdu] [phy] [rtn]", + cmd_cig_create, 1, 10), SHELL_CMD_ARG(cig_term, NULL, "Terminate the CIG", cmd_cig_term, 1, 0), #if defined(CONFIG_BT_SMP) SHELL_CMD_ARG(connect, NULL, "Connect ISO Channel [security level]", cmd_connect, 1, 1), @@ -900,14 +976,15 @@ SHELL_STATIC_SUBCMD_SET_CREATE(iso_cmds, static int cmd_iso(const struct shell *sh, size_t argc, char **argv) { - if (argc > 1) { - shell_error(sh, "%s unknown parameter: %s", - argv[0], argv[1]); - } else { - shell_error(sh, "%s Missing subcommand", argv[0]); + if (argc == 1) { + shell_help(sh); + + return SHELL_CMD_HELP_PRINTED; } - return -ENOEXEC; + shell_error(sh, "%s unknown parameter: %s", argv[0], argv[1]); + + return -EINVAL; } SHELL_CMD_ARG_REGISTER(iso, &iso_cmds, "Bluetooth ISO shell commands", diff --git a/subsys/bluetooth/shell/l2cap.c b/subsys/bluetooth/shell/l2cap.c index 31bf94ffed2..fe594fb0127 100644 --- a/subsys/bluetooth/shell/l2cap.c +++ b/subsys/bluetooth/shell/l2cap.c @@ -212,7 +212,8 @@ static int l2cap_accept_policy(struct bt_conn *conn) return 0; } -static int l2cap_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan) +static int l2cap_accept(struct bt_conn *conn, struct bt_l2cap_server *server, + struct bt_l2cap_chan **chan) { int err; diff --git a/subsys/canbus/isotp/Kconfig b/subsys/canbus/isotp/Kconfig index b533bf6d1e8..281692cf95e 100644 --- a/subsys/canbus/isotp/Kconfig +++ b/subsys/canbus/isotp/Kconfig @@ -5,6 +5,7 @@ menuconfig ISOTP bool "ISO-TP Transport [EXPERIMENTAL]" + depends on CAN select NET_BUF select POLL select EXPERIMENTAL @@ -74,11 +75,12 @@ config ISOTP_RX_BUF_COUNT config ISOTP_RX_BUF_SIZE int "Size of one buffer data block" + default 63 if CAN_FD_MODE default 56 help This value defines the size of a single block in the pool. The number of blocks is given by ISOTP_RX_BUF_COUNT. To be efficient use a multiple of - CAN_DL - 1 (for classic can : 8 - 1 = 7). + CAN_MAX_DLEN - 1 (for classic CAN : 8 - 1 = 7, for CAN FD : 64 - 1 = 63). config ISOTP_RX_SF_FF_BUF_COUNT int "Number of SF and FF data buffers for receiving data" @@ -87,7 +89,7 @@ config ISOTP_RX_SF_FF_BUF_COUNT This buffer is used for first and single frames. It is extra because the buffer has to be ready for the first reception in isr context and therefor is allocated when binding. - Each buffer will occupy CAN_DL - 1 byte + header (sizeof(struct net_buf)) + Each buffer will occupy CAN_MAX_DLEN - 1 byte + header (sizeof(struct net_buf)) amount of data. config ISOTP_USE_TX_BUF diff --git a/subsys/canbus/isotp/isotp.c b/subsys/canbus/isotp/isotp.c index 85b28ebe1f7..776cdd312a4 100644 --- a/subsys/canbus/isotp/isotp.c +++ b/subsys/canbus/isotp/isotp.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2019 Alexander Wachter + * Copyright (c) 2023 Enphase Energy * * SPDX-License-Identifier: Apache-2.0 */ @@ -26,7 +27,7 @@ NET_BUF_POOL_DEFINE(isotp_rx_pool, CONFIG_ISOTP_RX_BUF_COUNT, receive_pool_free); NET_BUF_POOL_DEFINE(isotp_rx_sf_ff_pool, CONFIG_ISOTP_RX_SF_FF_BUF_COUNT, - ISOTP_CAN_DL, sizeof(uint32_t), receive_ff_sf_pool_free); + CAN_MAX_DLEN, sizeof(uint32_t), receive_ff_sf_pool_free); static struct isotp_global_ctx global_ctx = { .alloc_list = SYS_SLIST_STATIC_INIT(&global_ctx.alloc_list), @@ -38,53 +39,71 @@ NET_BUF_POOL_VAR_DEFINE(isotp_tx_pool, CONFIG_ISOTP_TX_BUF_COUNT, CONFIG_ISOTP_BUF_TX_DATA_POOL_SIZE, 0, NULL); #endif -static void receive_state_machine(struct isotp_recv_ctx *ctx); +static void receive_state_machine(struct isotp_recv_ctx *rctx); + +static inline void prepare_frame(struct can_frame *frame, struct isotp_msg_id *addr) +{ + frame->id = addr->ext_id; + frame->flags = ((addr->flags & ISOTP_MSG_IDE) != 0 ? CAN_FRAME_IDE : 0) | + ((addr->flags & ISOTP_MSG_FDF) != 0 ? CAN_FRAME_FDF : 0) | + ((addr->flags & ISOTP_MSG_BRS) != 0 ? CAN_FRAME_BRS : 0); +} + +static inline void prepare_filter(struct can_filter *filter, struct isotp_msg_id *addr, + uint32_t mask) +{ + filter->id = addr->ext_id; + filter->mask = mask; + filter->flags = CAN_FILTER_DATA | + ((addr->flags & ISOTP_MSG_IDE) != 0 ? CAN_FILTER_IDE : 0) | + ((addr->flags & ISOTP_MSG_FDF) != 0 ? CAN_FILTER_FDF : 0); +} /* * Wake every context that is waiting for a buffer */ static void receive_pool_free(struct net_buf *buf) { - struct isotp_recv_ctx *ctx; - sys_snode_t *ctx_node; + struct isotp_recv_ctx *rctx; + sys_snode_t *rctx_node; net_buf_destroy(buf); - SYS_SLIST_FOR_EACH_NODE(&global_ctx.alloc_list, ctx_node) { - ctx = CONTAINER_OF(ctx_node, struct isotp_recv_ctx, alloc_node); - k_work_submit(&ctx->work); + SYS_SLIST_FOR_EACH_NODE(&global_ctx.alloc_list, rctx_node) { + rctx = CONTAINER_OF(rctx_node, struct isotp_recv_ctx, alloc_node); + k_work_submit(&rctx->work); } } static void receive_ff_sf_pool_free(struct net_buf *buf) { - struct isotp_recv_ctx *ctx; - sys_snode_t *ctx_node; + struct isotp_recv_ctx *rctx; + sys_snode_t *rctx_node; net_buf_destroy(buf); - SYS_SLIST_FOR_EACH_NODE(&global_ctx.ff_sf_alloc_list, ctx_node) { - ctx = CONTAINER_OF(ctx_node, struct isotp_recv_ctx, alloc_node); - k_work_submit(&ctx->work); + SYS_SLIST_FOR_EACH_NODE(&global_ctx.ff_sf_alloc_list, rctx_node) { + rctx = CONTAINER_OF(rctx_node, struct isotp_recv_ctx, alloc_node); + k_work_submit(&rctx->work); } } -static inline void receive_report_error(struct isotp_recv_ctx *ctx, int err) +static inline void receive_report_error(struct isotp_recv_ctx *rctx, int err) { - ctx->state = ISOTP_RX_STATE_ERR; - ctx->error_nr = err; + rctx->state = ISOTP_RX_STATE_ERR; + rctx->error_nr = err; } static void receive_can_tx(const struct device *dev, int error, void *arg) { - struct isotp_recv_ctx *ctx = (struct isotp_recv_ctx *)arg; + struct isotp_recv_ctx *rctx = (struct isotp_recv_ctx *)arg; ARG_UNUSED(dev); if (error != 0) { LOG_ERR("Error sending FC frame (%d)", error); - receive_report_error(ctx, ISOTP_N_ERROR); - k_work_submit(&ctx->work); + receive_report_error(rctx, ISOTP_N_ERROR); + k_work_submit(&rctx->work); } } @@ -103,53 +122,52 @@ static inline uint32_t receive_get_ff_length(struct net_buf *buf) return len; } -static inline uint32_t receive_get_sf_length(struct net_buf *buf) +static inline uint32_t receive_get_sf_length(struct net_buf *buf, bool fdf) { uint8_t len = net_buf_pull_u8(buf) & ISOTP_PCI_SF_DL_MASK; - /* Single frames > 16 bytes (CAN-FD only) */ - if (IS_ENABLED(ISOTP_USE_CAN_FD) && !len) { + /* Single frames > 8 bytes (CAN FD only) */ + if (IS_ENABLED(CONFIG_CAN_FD_MODE) && fdf && !len) { len = net_buf_pull_u8(buf); } return len; } -static void receive_send_fc(struct isotp_recv_ctx *ctx, uint8_t fs) +static void receive_send_fc(struct isotp_recv_ctx *rctx, uint8_t fs) { - struct can_frame frame = { - .flags = ctx->tx_addr.ide != 0 ? CAN_FRAME_IDE : 0, - .id = ctx->tx_addr.ext_id - }; + struct can_frame frame; uint8_t *data = frame.data; uint8_t payload_len; int ret; __ASSERT_NO_MSG(!(fs & ISOTP_PCI_TYPE_MASK)); - if (ctx->tx_addr.use_ext_addr) { - *data++ = ctx->tx_addr.ext_addr; + prepare_frame(&frame, &rctx->tx_addr); + + if ((rctx->tx_addr.flags & ISOTP_MSG_EXT_ADDR) != 0) { + *data++ = rctx->tx_addr.ext_addr; } *data++ = ISOTP_PCI_TYPE_FC | fs; - *data++ = ctx->opts.bs; - *data++ = ctx->opts.stmin; + *data++ = rctx->opts.bs; + *data++ = rctx->opts.stmin; payload_len = data - frame.data; #ifdef CONFIG_ISOTP_ENABLE_TX_PADDING /* AUTOSAR requirement SWS_CanTp_00347 */ - memset(&frame.data[payload_len], 0xCC, ISOTP_CAN_DL - payload_len); - frame.dlc = ISOTP_CAN_DL; + memset(&frame.data[payload_len], ISOTP_PAD_BYTE, + ISOTP_PADDED_FRAME_DL_MIN - payload_len); + frame.dlc = can_bytes_to_dlc(ISOTP_PADDED_FRAME_DL_MIN); #else - frame.dlc = payload_len; + frame.dlc = can_bytes_to_dlc(payload_len); #endif - ret = can_send(ctx->can_dev, &frame, K_MSEC(ISOTP_A), - receive_can_tx, ctx); + ret = can_send(rctx->can_dev, &frame, K_MSEC(ISOTP_A_TIMEOUT_MS), receive_can_tx, rctx); if (ret) { LOG_ERR("Can't send FC, (%d)", ret); - receive_report_error(ctx, ISOTP_N_TIMEOUT_A); - receive_state_machine(ctx); + receive_report_error(rctx, ISOTP_N_TIMEOUT_A); + receive_state_machine(rctx); } } @@ -188,169 +206,163 @@ static inline struct net_buf *receive_alloc_buffer_chain(uint32_t len) static void receive_timeout_handler(struct k_timer *timer) { - struct isotp_recv_ctx *ctx = CONTAINER_OF(timer, struct isotp_recv_ctx, timer); + struct isotp_recv_ctx *rctx = CONTAINER_OF(timer, struct isotp_recv_ctx, timer); - switch (ctx->state) { + switch (rctx->state) { case ISOTP_RX_STATE_WAIT_CF: LOG_ERR("Timeout while waiting for CF"); - receive_report_error(ctx, ISOTP_N_TIMEOUT_CR); + receive_report_error(rctx, ISOTP_N_TIMEOUT_CR); break; case ISOTP_RX_STATE_TRY_ALLOC: - ctx->state = ISOTP_RX_STATE_SEND_WAIT; + rctx->state = ISOTP_RX_STATE_SEND_WAIT; break; } - k_work_submit(&ctx->work); + k_work_submit(&rctx->work); } -static int receive_alloc_buffer(struct isotp_recv_ctx *ctx) +static int receive_alloc_buffer(struct isotp_recv_ctx *rctx) { struct net_buf *buf = NULL; - if (ctx->opts.bs == 0) { + if (rctx->opts.bs == 0) { /* Alloc all buffers because we can't wait during reception */ - buf = receive_alloc_buffer_chain(ctx->length); + buf = receive_alloc_buffer_chain(rctx->length); } else { - buf = receive_alloc_buffer_chain(ctx->opts.bs * - (ISOTP_CAN_DL - 1)); + /* Alloc the minimum of the remaining length and bytes of one block */ + uint32_t len = MIN(rctx->length, rctx->opts.bs * (rctx->rx_addr.dl - 1)); + + buf = receive_alloc_buffer_chain(len); } if (!buf) { - k_timer_start(&ctx->timer, K_MSEC(ISOTP_ALLOC_TIMEOUT), K_NO_WAIT); + k_timer_start(&rctx->timer, K_MSEC(ISOTP_ALLOC_TIMEOUT_MS), K_NO_WAIT); - if (ctx->wft == ISOTP_WFT_FIRST) { + if (rctx->wft == ISOTP_WFT_FIRST) { LOG_DBG("Allocation failed. Append to alloc list"); - ctx->wft = 0; - sys_slist_append(&global_ctx.alloc_list, - &ctx->alloc_node); + rctx->wft = 0; + sys_slist_append(&global_ctx.alloc_list, &rctx->alloc_node); } else { LOG_DBG("Allocation failed. Send WAIT frame"); - ctx->state = ISOTP_RX_STATE_SEND_WAIT; - receive_state_machine(ctx); + rctx->state = ISOTP_RX_STATE_SEND_WAIT; + receive_state_machine(rctx); } return -1; } - if (ctx->state == ISOTP_RX_STATE_TRY_ALLOC) { - k_timer_stop(&ctx->timer); - ctx->wft = ISOTP_WFT_FIRST; - sys_slist_find_and_remove(&global_ctx.alloc_list, - &ctx->alloc_node); + if (rctx->state == ISOTP_RX_STATE_TRY_ALLOC) { + k_timer_stop(&rctx->timer); + rctx->wft = ISOTP_WFT_FIRST; + sys_slist_find_and_remove(&global_ctx.alloc_list, &rctx->alloc_node); } - if (ctx->opts.bs != 0) { - ctx->buf = buf; + if (rctx->opts.bs != 0) { + rctx->buf = buf; } else { - net_buf_frag_insert(ctx->buf, buf); + net_buf_frag_insert(rctx->buf, buf); } - ctx->act_frag = buf; + rctx->act_frag = buf; return 0; } -static void receive_state_machine(struct isotp_recv_ctx *ctx) +static void receive_state_machine(struct isotp_recv_ctx *rctx) { int ret; uint32_t *ud_rem_len; - switch (ctx->state) { + switch (rctx->state) { case ISOTP_RX_STATE_PROCESS_SF: - ctx->length = receive_get_sf_length(ctx->buf); - ud_rem_len = net_buf_user_data(ctx->buf); + rctx->length = receive_get_sf_length(rctx->buf, + (rctx->rx_addr.flags & ISOTP_MSG_FDF) != 0); + ud_rem_len = net_buf_user_data(rctx->buf); *ud_rem_len = 0; - LOG_DBG("SM process SF of length %d", ctx->length); - net_buf_put(&ctx->fifo, ctx->buf); - ctx->state = ISOTP_RX_STATE_RECYCLE; - receive_state_machine(ctx); + LOG_DBG("SM process SF of length %d", rctx->length); + net_buf_put(&rctx->fifo, rctx->buf); + rctx->state = ISOTP_RX_STATE_RECYCLE; + receive_state_machine(rctx); break; case ISOTP_RX_STATE_PROCESS_FF: - ctx->length = receive_get_ff_length(ctx->buf); - LOG_DBG("SM process FF. Length: %d", ctx->length); - ctx->length -= ctx->buf->len; - if (ctx->opts.bs == 0 && - ctx->length > CONFIG_ISOTP_RX_BUF_COUNT * - CONFIG_ISOTP_RX_BUF_SIZE) { - LOG_ERR("Pkt length is %d but buffer has only %d bytes", - ctx->length, - CONFIG_ISOTP_RX_BUF_COUNT * - CONFIG_ISOTP_RX_BUF_SIZE); - receive_report_error(ctx, ISOTP_N_BUFFER_OVERFLW); - receive_state_machine(ctx); + rctx->length = receive_get_ff_length(rctx->buf); + LOG_DBG("SM process FF. Length: %d", rctx->length); + rctx->length -= rctx->buf->len; + if (rctx->opts.bs == 0 && + rctx->length > CONFIG_ISOTP_RX_BUF_COUNT * CONFIG_ISOTP_RX_BUF_SIZE) { + LOG_ERR("Pkt length is %d but buffer has only %d bytes", rctx->length, + CONFIG_ISOTP_RX_BUF_COUNT * CONFIG_ISOTP_RX_BUF_SIZE); + receive_report_error(rctx, ISOTP_N_BUFFER_OVERFLW); + receive_state_machine(rctx); break; } - if (ctx->opts.bs) { - ctx->bs = ctx->opts.bs; - ud_rem_len = net_buf_user_data(ctx->buf); - *ud_rem_len = ctx->length; - net_buf_put(&ctx->fifo, ctx->buf); + if (rctx->opts.bs) { + rctx->bs = rctx->opts.bs; + ud_rem_len = net_buf_user_data(rctx->buf); + *ud_rem_len = rctx->length; + net_buf_put(&rctx->fifo, rctx->buf); } - ctx->wft = ISOTP_WFT_FIRST; - ctx->state = ISOTP_RX_STATE_TRY_ALLOC; + rctx->wft = ISOTP_WFT_FIRST; + rctx->state = ISOTP_RX_STATE_TRY_ALLOC; __fallthrough; case ISOTP_RX_STATE_TRY_ALLOC: LOG_DBG("SM try to allocate"); - k_timer_stop(&ctx->timer); - ret = receive_alloc_buffer(ctx); + k_timer_stop(&rctx->timer); + ret = receive_alloc_buffer(rctx); if (ret) { LOG_DBG("SM allocation failed. Wait for free buffer"); break; } - ctx->state = ISOTP_RX_STATE_SEND_FC; + rctx->state = ISOTP_RX_STATE_SEND_FC; __fallthrough; case ISOTP_RX_STATE_SEND_FC: LOG_DBG("SM send CTS FC frame"); - receive_send_fc(ctx, ISOTP_PCI_FS_CTS); - k_timer_start(&ctx->timer, K_MSEC(ISOTP_CR), K_NO_WAIT); - ctx->state = ISOTP_RX_STATE_WAIT_CF; + receive_send_fc(rctx, ISOTP_PCI_FS_CTS); + k_timer_start(&rctx->timer, K_MSEC(ISOTP_CR_TIMEOUT_MS), K_NO_WAIT); + rctx->state = ISOTP_RX_STATE_WAIT_CF; break; case ISOTP_RX_STATE_SEND_WAIT: - if (++ctx->wft < CONFIG_ISOTP_WFTMAX) { - LOG_DBG("Send wait frame number %d", ctx->wft); - receive_send_fc(ctx, ISOTP_PCI_FS_WAIT); - k_timer_start(&ctx->timer, K_MSEC(ISOTP_ALLOC_TIMEOUT), K_NO_WAIT); - ctx->state = ISOTP_RX_STATE_TRY_ALLOC; + if (++rctx->wft < CONFIG_ISOTP_WFTMAX) { + LOG_DBG("Send wait frame number %d", rctx->wft); + receive_send_fc(rctx, ISOTP_PCI_FS_WAIT); + k_timer_start(&rctx->timer, K_MSEC(ISOTP_ALLOC_TIMEOUT_MS), K_NO_WAIT); + rctx->state = ISOTP_RX_STATE_TRY_ALLOC; break; } - sys_slist_find_and_remove(&global_ctx.alloc_list, - &ctx->alloc_node); - LOG_ERR("Sent %d wait frames. Giving up to alloc now", - ctx->wft); - receive_report_error(ctx, ISOTP_N_BUFFER_OVERFLW); + sys_slist_find_and_remove(&global_ctx.alloc_list, &rctx->alloc_node); + LOG_ERR("Sent %d wait frames. Giving up to alloc now", rctx->wft); + receive_report_error(rctx, ISOTP_N_BUFFER_OVERFLW); __fallthrough; case ISOTP_RX_STATE_ERR: - LOG_DBG("SM ERR state. err nr: %d", ctx->error_nr); - k_timer_stop(&ctx->timer); + LOG_DBG("SM ERR state. err nr: %d", rctx->error_nr); + k_timer_stop(&rctx->timer); - if (ctx->error_nr == ISOTP_N_BUFFER_OVERFLW) { - receive_send_fc(ctx, ISOTP_PCI_FS_OVFLW); + if (rctx->error_nr == ISOTP_N_BUFFER_OVERFLW) { + receive_send_fc(rctx, ISOTP_PCI_FS_OVFLW); } - k_fifo_cancel_wait(&ctx->fifo); - net_buf_unref(ctx->buf); - ctx->buf = NULL; - ctx->state = ISOTP_RX_STATE_RECYCLE; + k_fifo_cancel_wait(&rctx->fifo); + net_buf_unref(rctx->buf); + rctx->buf = NULL; + rctx->state = ISOTP_RX_STATE_RECYCLE; __fallthrough; case ISOTP_RX_STATE_RECYCLE: LOG_DBG("SM recycle context for next message"); - ctx->buf = net_buf_alloc_fixed(&isotp_rx_sf_ff_pool, K_NO_WAIT); - if (!ctx->buf) { + rctx->buf = net_buf_alloc_fixed(&isotp_rx_sf_ff_pool, K_NO_WAIT); + if (!rctx->buf) { LOG_DBG("No free context. Append to waiters list"); - sys_slist_append(&global_ctx.ff_sf_alloc_list, - &ctx->alloc_node); + sys_slist_append(&global_ctx.ff_sf_alloc_list, &rctx->alloc_node); break; } - sys_slist_find_and_remove(&global_ctx.ff_sf_alloc_list, - &ctx->alloc_node); - ctx->state = ISOTP_RX_STATE_WAIT_FF_SF; + sys_slist_find_and_remove(&global_ctx.ff_sf_alloc_list, &rctx->alloc_node); + rctx->state = ISOTP_RX_STATE_WAIT_FF_SF; __fallthrough; case ISOTP_RX_STATE_UNBOUND: break; @@ -362,71 +374,84 @@ static void receive_state_machine(struct isotp_recv_ctx *ctx) static void receive_work_handler(struct k_work *item) { - struct isotp_recv_ctx *ctx = CONTAINER_OF(item, struct isotp_recv_ctx, - work); + struct isotp_recv_ctx *rctx = CONTAINER_OF(item, struct isotp_recv_ctx, work); - receive_state_machine(ctx); + receive_state_machine(rctx); } -static void process_ff_sf(struct isotp_recv_ctx *ctx, struct can_frame *frame) +static void process_ff_sf(struct isotp_recv_ctx *rctx, struct can_frame *frame) { int index = 0; + uint8_t sf_len; uint8_t payload_len; uint32_t rx_sa; /* ISO-TP fixed source address (if used) */ + uint8_t can_dl = can_dlc_to_bytes(frame->dlc); - if (ctx->rx_addr.use_ext_addr) { - if (frame->data[index++] != ctx->rx_addr.ext_addr) { + if ((rctx->rx_addr.flags & ISOTP_MSG_EXT_ADDR) != 0) { + if (frame->data[index++] != rctx->rx_addr.ext_addr) { return; } } - if (ctx->rx_addr.use_fixed_addr) { + if ((rctx->rx_addr.flags & ISOTP_MSG_FIXED_ADDR) != 0) { /* store actual CAN ID used by the sender */ - ctx->rx_addr.ext_id = frame->id; + rctx->rx_addr.ext_id = frame->id; /* replace TX target address with RX source address */ rx_sa = (frame->id & ISOTP_FIXED_ADDR_SA_MASK) >> ISOTP_FIXED_ADDR_SA_POS; - ctx->tx_addr.ext_id &= ~(ISOTP_FIXED_ADDR_TA_MASK); - ctx->tx_addr.ext_id |= rx_sa << ISOTP_FIXED_ADDR_TA_POS; + rctx->tx_addr.ext_id &= ~(ISOTP_FIXED_ADDR_TA_MASK); + rctx->tx_addr.ext_id |= rx_sa << ISOTP_FIXED_ADDR_TA_POS; /* use same priority for TX as in received message */ if (ISOTP_FIXED_ADDR_PRIO_MASK) { - ctx->tx_addr.ext_id &= ~(ISOTP_FIXED_ADDR_PRIO_MASK); - ctx->tx_addr.ext_id |= frame->id & ISOTP_FIXED_ADDR_PRIO_MASK; + rctx->tx_addr.ext_id &= ~(ISOTP_FIXED_ADDR_PRIO_MASK); + rctx->tx_addr.ext_id |= frame->id & ISOTP_FIXED_ADDR_PRIO_MASK; } } switch (frame->data[index] & ISOTP_PCI_TYPE_MASK) { case ISOTP_PCI_TYPE_FF: LOG_DBG("Got FF IRQ"); - if (frame->dlc != ISOTP_CAN_DL) { + if (can_dl < ISOTP_FF_DL_MIN) { LOG_INF("FF DLC invalid. Ignore"); return; } - payload_len = ISOTP_CAN_DL; - ctx->state = ISOTP_RX_STATE_PROCESS_FF; - ctx->sn_expected = 1; + payload_len = can_dl; + rctx->state = ISOTP_RX_STATE_PROCESS_FF; + rctx->rx_addr.dl = can_dl; + rctx->sn_expected = 1; break; case ISOTP_PCI_TYPE_SF: LOG_DBG("Got SF IRQ"); #ifdef CONFIG_ISOTP_REQUIRE_RX_PADDING /* AUTOSAR requirement SWS_CanTp_00345 */ - if (frame->dlc != ISOTP_CAN_DL) { + if (can_dl < ISOTP_PADDED_FRAME_DL_MIN) { LOG_INF("SF DLC invalid. Ignore"); return; } #endif + sf_len = frame->data[index] & ISOTP_PCI_SF_DL_MASK; + + /* Single frames > 8 bytes (CAN FD only) */ + if (IS_ENABLED(CONFIG_CAN_FD_MODE) && (rctx->rx_addr.flags & ISOTP_MSG_FDF) != 0 && + can_dl > ISOTP_4BIT_SF_MAX_CAN_DL) { + if (sf_len != 0) { + LOG_INF("SF DL invalid. Ignore"); + return; + } + sf_len = frame->data[index + 1]; + payload_len = index + 2 + sf_len; + } else { + payload_len = index + 1 + sf_len; + } - payload_len = index + 1 + (frame->data[index] & - ISOTP_PCI_SF_DL_MASK); - - if (payload_len > frame->dlc) { + if (payload_len > can_dl) { LOG_INF("SF DL does not fit. Ignore"); return; } - ctx->state = ISOTP_RX_STATE_PROCESS_SF; + rctx->state = ISOTP_RX_STATE_PROCESS_SF; break; default: @@ -434,39 +459,39 @@ static void process_ff_sf(struct isotp_recv_ctx *ctx, struct can_frame *frame) return; } - net_buf_add_mem(ctx->buf, &frame->data[index], payload_len - index); + net_buf_add_mem(rctx->buf, &frame->data[index], payload_len - index); } -static inline void receive_add_mem(struct isotp_recv_ctx *ctx, uint8_t *data, - size_t len) +static inline void receive_add_mem(struct isotp_recv_ctx *rctx, uint8_t *data, size_t len) { - size_t tailroom = net_buf_tailroom(ctx->act_frag); + size_t tailroom = net_buf_tailroom(rctx->act_frag); if (tailroom >= len) { - net_buf_add_mem(ctx->act_frag, data, len); + net_buf_add_mem(rctx->act_frag, data, len); return; } /* Use next fragment that is already allocated*/ - net_buf_add_mem(ctx->act_frag, data, tailroom); - ctx->act_frag = ctx->act_frag->frags; - if (!ctx->act_frag) { + net_buf_add_mem(rctx->act_frag, data, tailroom); + rctx->act_frag = rctx->act_frag->frags; + if (!rctx->act_frag) { LOG_ERR("No fragment left to append data"); - receive_report_error(ctx, ISOTP_N_BUFFER_OVERFLW); + receive_report_error(rctx, ISOTP_N_BUFFER_OVERFLW); return; } - net_buf_add_mem(ctx->act_frag, data + tailroom, len - tailroom); + net_buf_add_mem(rctx->act_frag, data + tailroom, len - tailroom); } -static void process_cf(struct isotp_recv_ctx *ctx, struct can_frame *frame) +static void process_cf(struct isotp_recv_ctx *rctx, struct can_frame *frame) { - uint32_t *ud_rem_len = (uint32_t *)net_buf_user_data(ctx->buf); + uint32_t *ud_rem_len = (uint32_t *)net_buf_user_data(rctx->buf); int index = 0; uint32_t data_len; + uint8_t can_dl = can_dlc_to_bytes(frame->dlc); - if (ctx->rx_addr.use_ext_addr) { - if (frame->data[index++] != ctx->rx_addr.ext_addr) { + if ((rctx->rx_addr.flags & ISOTP_MSG_EXT_ADDR) != 0) { + if (frame->data[index++] != rctx->rx_addr.ext_addr) { return; } } @@ -474,68 +499,76 @@ static void process_cf(struct isotp_recv_ctx *ctx, struct can_frame *frame) if ((frame->data[index] & ISOTP_PCI_TYPE_MASK) != ISOTP_PCI_TYPE_CF) { LOG_DBG("Waiting for CF but got something else (%d)", frame->data[index] >> ISOTP_PCI_TYPE_POS); - receive_report_error(ctx, ISOTP_N_UNEXP_PDU); - k_work_submit(&ctx->work); + receive_report_error(rctx, ISOTP_N_UNEXP_PDU); + k_work_submit(&rctx->work); return; } - k_timer_start(&ctx->timer, K_MSEC(ISOTP_CR), K_NO_WAIT); + k_timer_start(&rctx->timer, K_MSEC(ISOTP_CR_TIMEOUT_MS), K_NO_WAIT); - if ((frame->data[index++] & ISOTP_PCI_SN_MASK) != ctx->sn_expected++) { + if ((frame->data[index++] & ISOTP_PCI_SN_MASK) != rctx->sn_expected++) { LOG_ERR("Sequence number mismatch"); - receive_report_error(ctx, ISOTP_N_WRONG_SN); - k_work_submit(&ctx->work); + receive_report_error(rctx, ISOTP_N_WRONG_SN); + k_work_submit(&rctx->work); return; } #ifdef CONFIG_ISOTP_REQUIRE_RX_PADDING /* AUTOSAR requirement SWS_CanTp_00346 */ - if (frame->dlc != ISOTP_CAN_DL) { + if (can_dl < ISOTP_PADDED_FRAME_DL_MIN) { LOG_ERR("CF DL invalid"); - receive_report_error(ctx, ISOTP_N_ERROR); + receive_report_error(rctx, ISOTP_N_ERROR); return; } #endif + /* First frame defines the RX data length, consecutive frames + * must have the same length (except the last frame) + */ + if (can_dl != rctx->rx_addr.dl && rctx->length > can_dl - index) { + LOG_ERR("CF DL invalid"); + receive_report_error(rctx, ISOTP_N_ERROR); + return; + } + LOG_DBG("Got CF irq. Appending data"); - data_len = (ctx->length > frame->dlc - index) ? frame->dlc - index : - ctx->length; - receive_add_mem(ctx, &frame->data[index], data_len); - ctx->length -= data_len; - LOG_DBG("%d bytes remaining", ctx->length); - - if (ctx->length == 0) { - ctx->state = ISOTP_RX_STATE_RECYCLE; + data_len = MIN(rctx->length, can_dl - index); + receive_add_mem(rctx, &frame->data[index], data_len); + rctx->length -= data_len; + LOG_DBG("%d bytes remaining", rctx->length); + + if (rctx->length == 0) { + rctx->state = ISOTP_RX_STATE_RECYCLE; *ud_rem_len = 0; - net_buf_put(&ctx->fifo, ctx->buf); + net_buf_put(&rctx->fifo, rctx->buf); return; } - if (ctx->opts.bs && !--ctx->bs) { + if (rctx->opts.bs && !--rctx->bs) { LOG_DBG("Block is complete. Allocate new buffer"); - ctx->bs = ctx->opts.bs; - *ud_rem_len = ctx->length; - net_buf_put(&ctx->fifo, ctx->buf); - ctx->state = ISOTP_RX_STATE_TRY_ALLOC; + rctx->bs = rctx->opts.bs; + *ud_rem_len = rctx->length; + net_buf_put(&rctx->fifo, rctx->buf); + rctx->state = ISOTP_RX_STATE_TRY_ALLOC; } } static void receive_can_rx(const struct device *dev, struct can_frame *frame, void *arg) { - struct isotp_recv_ctx *ctx = (struct isotp_recv_ctx *)arg; + struct isotp_recv_ctx *rctx = (struct isotp_recv_ctx *)arg; ARG_UNUSED(dev); - switch (ctx->state) { + switch (rctx->state) { case ISOTP_RX_STATE_WAIT_FF_SF: - __ASSERT_NO_MSG(ctx->buf); - process_ff_sf(ctx, frame); + __ASSERT_NO_MSG(rctx->buf); + process_ff_sf(rctx, frame); break; case ISOTP_RX_STATE_WAIT_CF: - process_cf(ctx, frame); + process_cf(rctx, frame); /* still waiting for more CF */ - if (ctx->state == ISOTP_RX_STATE_WAIT_CF) { + if (rctx->state == ISOTP_RX_STATE_WAIT_CF) { return; } @@ -543,130 +576,132 @@ static void receive_can_rx(const struct device *dev, struct can_frame *frame, vo case ISOTP_RX_STATE_RECYCLE: LOG_ERR("Got a frame but was not yet ready for a new one"); - receive_report_error(ctx, ISOTP_N_BUFFER_OVERFLW); + receive_report_error(rctx, ISOTP_N_BUFFER_OVERFLW); break; default: LOG_INF("Got a frame in a state where it is unexpected."); } - k_work_submit(&ctx->work); + k_work_submit(&rctx->work); } -static inline int attach_ff_filter(struct isotp_recv_ctx *ctx) +static inline int add_ff_sf_filter(struct isotp_recv_ctx *rctx) { + struct can_filter filter; uint32_t mask; - if (ctx->rx_addr.use_fixed_addr) { + if ((rctx->rx_addr.flags & ISOTP_MSG_FIXED_ADDR) != 0) { mask = ISOTP_FIXED_ADDR_RX_MASK; } else { mask = CAN_EXT_ID_MASK; } - struct can_filter filter = { - .flags = CAN_FILTER_DATA | ((ctx->rx_addr.ide != 0) ? CAN_FILTER_IDE : 0), - .id = ctx->rx_addr.ext_id, - .mask = mask - }; + prepare_filter(&filter, &rctx->rx_addr, mask); - ctx->filter_id = can_add_rx_filter(ctx->can_dev, receive_can_rx, ctx, - &filter); - if (ctx->filter_id < 0) { - LOG_ERR("Error attaching FF filter [%d]", ctx->filter_id); + rctx->filter_id = can_add_rx_filter(rctx->can_dev, receive_can_rx, rctx, &filter); + if (rctx->filter_id < 0) { + LOG_ERR("Error adding FF filter [%d]", rctx->filter_id); return ISOTP_NO_FREE_FILTER; } return 0; } -int isotp_bind(struct isotp_recv_ctx *ctx, const struct device *can_dev, +int isotp_bind(struct isotp_recv_ctx *rctx, const struct device *can_dev, const struct isotp_msg_id *rx_addr, const struct isotp_msg_id *tx_addr, const struct isotp_fc_opts *opts, k_timeout_t timeout) { + can_mode_t cap; int ret; - __ASSERT(ctx, "ctx is NULL"); + __ASSERT(rctx, "rctx is NULL"); __ASSERT(can_dev, "CAN device is NULL"); __ASSERT(rx_addr && tx_addr, "RX or TX addr is NULL"); __ASSERT(opts, "OPTS is NULL"); - ctx->can_dev = can_dev; - ctx->rx_addr = *rx_addr; - ctx->tx_addr = *tx_addr; - k_fifo_init(&ctx->fifo); + rctx->can_dev = can_dev; + rctx->rx_addr = *rx_addr; + rctx->tx_addr = *tx_addr; + k_fifo_init(&rctx->fifo); __ASSERT(opts->stmin < ISOTP_STMIN_MAX, "STmin limit"); __ASSERT(opts->stmin <= ISOTP_STMIN_MS_MAX || opts->stmin >= ISOTP_STMIN_US_BEGIN, "STmin reserved"); - ctx->opts = *opts; - ctx->state = ISOTP_RX_STATE_WAIT_FF_SF; + rctx->opts = *opts; + rctx->state = ISOTP_RX_STATE_WAIT_FF_SF; + + if ((rx_addr->flags & ISOTP_MSG_FDF) != 0 || (tx_addr->flags & ISOTP_MSG_FDF) != 0) { + ret = can_get_capabilities(can_dev, &cap); + if (ret != 0 || (cap & CAN_MODE_FD) == 0) { + LOG_ERR("CAN controller does not support FD mode"); + return ISOTP_N_ERROR; + } + } LOG_DBG("Binding to addr: 0x%x. Responding on 0x%x", - ctx->rx_addr.ext_id, ctx->tx_addr.ext_id); + rctx->rx_addr.ext_id, rctx->tx_addr.ext_id); - ctx->buf = net_buf_alloc_fixed(&isotp_rx_sf_ff_pool, timeout); - if (!ctx->buf) { + rctx->buf = net_buf_alloc_fixed(&isotp_rx_sf_ff_pool, timeout); + if (!rctx->buf) { LOG_ERR("No buffer for FF left"); return ISOTP_NO_NET_BUF_LEFT; } - ret = attach_ff_filter(ctx); + ret = add_ff_sf_filter(rctx); if (ret) { - LOG_ERR("Can't attach filter for binding"); - net_buf_unref(ctx->buf); - ctx->buf = NULL; + LOG_ERR("Can't add filter for binding"); + net_buf_unref(rctx->buf); + rctx->buf = NULL; return ret; } - k_work_init(&ctx->work, receive_work_handler); - k_timer_init(&ctx->timer, receive_timeout_handler, NULL); + k_work_init(&rctx->work, receive_work_handler); + k_timer_init(&rctx->timer, receive_timeout_handler, NULL); return ISOTP_N_OK; } -void isotp_unbind(struct isotp_recv_ctx *ctx) +void isotp_unbind(struct isotp_recv_ctx *rctx) { struct net_buf *buf; - if (ctx->filter_id >= 0 && ctx->can_dev) { - can_remove_rx_filter(ctx->can_dev, ctx->filter_id); + if (rctx->filter_id >= 0 && rctx->can_dev) { + can_remove_rx_filter(rctx->can_dev, rctx->filter_id); } - k_timer_stop(&ctx->timer); + k_timer_stop(&rctx->timer); - sys_slist_find_and_remove(&global_ctx.ff_sf_alloc_list, - &ctx->alloc_node); - sys_slist_find_and_remove(&global_ctx.alloc_list, - &ctx->alloc_node); + sys_slist_find_and_remove(&global_ctx.ff_sf_alloc_list, &rctx->alloc_node); + sys_slist_find_and_remove(&global_ctx.alloc_list, &rctx->alloc_node); - ctx->state = ISOTP_RX_STATE_UNBOUND; + rctx->state = ISOTP_RX_STATE_UNBOUND; - while ((buf = net_buf_get(&ctx->fifo, K_NO_WAIT))) { + while ((buf = net_buf_get(&rctx->fifo, K_NO_WAIT))) { net_buf_unref(buf); } - k_fifo_cancel_wait(&ctx->fifo); + k_fifo_cancel_wait(&rctx->fifo); - if (ctx->buf) { - net_buf_unref(ctx->buf); + if (rctx->buf) { + net_buf_unref(rctx->buf); } LOG_DBG("Unbound"); } -int isotp_recv_net(struct isotp_recv_ctx *ctx, struct net_buf **buffer, - k_timeout_t timeout) +int isotp_recv_net(struct isotp_recv_ctx *rctx, struct net_buf **buffer, k_timeout_t timeout) { struct net_buf *buf; int ret; - buf = net_buf_get(&ctx->fifo, timeout); + buf = net_buf_get(&rctx->fifo, timeout); if (!buf) { - ret = ctx->error_nr ? ctx->error_nr : ISOTP_RECV_TIMEOUT; - ctx->error_nr = 0; + ret = rctx->error_nr ? rctx->error_nr : ISOTP_RECV_TIMEOUT; + rctx->error_nr = 0; return ret; } @@ -676,17 +711,16 @@ int isotp_recv_net(struct isotp_recv_ctx *ctx, struct net_buf **buffer, return *(uint32_t *)net_buf_user_data(buf); } -int isotp_recv(struct isotp_recv_ctx *ctx, uint8_t *data, size_t len, - k_timeout_t timeout) +int isotp_recv(struct isotp_recv_ctx *rctx, uint8_t *data, size_t len, k_timeout_t timeout) { size_t copied, to_copy; int err; - if (!ctx->recv_buf) { - ctx->recv_buf = net_buf_get(&ctx->fifo, timeout); - if (!ctx->recv_buf) { - err = ctx->error_nr ? ctx->error_nr : ISOTP_RECV_TIMEOUT; - ctx->error_nr = 0; + if (!rctx->recv_buf) { + rctx->recv_buf = net_buf_get(&rctx->fifo, timeout); + if (!rctx->recv_buf) { + err = rctx->error_nr ? rctx->error_nr : ISOTP_RECV_TIMEOUT; + rctx->error_nr = 0; return err; } @@ -694,16 +728,16 @@ int isotp_recv(struct isotp_recv_ctx *ctx, uint8_t *data, size_t len, /* traverse fragments and delete them after copying the data */ copied = 0; - while (ctx->recv_buf && copied < len) { - to_copy = MIN(len - copied, ctx->recv_buf->len); - memcpy((uint8_t *)data + copied, ctx->recv_buf->data, to_copy); + while (rctx->recv_buf && copied < len) { + to_copy = MIN(len - copied, rctx->recv_buf->len); + memcpy((uint8_t *)data + copied, rctx->recv_buf->data, to_copy); - if (ctx->recv_buf->len == to_copy) { + if (rctx->recv_buf->len == to_copy) { /* point recv_buf to next frag */ - ctx->recv_buf = net_buf_frag_del(NULL, ctx->recv_buf); + rctx->recv_buf = net_buf_frag_del(NULL, rctx->recv_buf); } else { /* pull received data from remaining frag(s) */ - net_buf_pull(ctx->recv_buf, to_copy); + net_buf_pull(rctx->recv_buf, to_copy); } copied += to_copy; @@ -712,200 +746,209 @@ int isotp_recv(struct isotp_recv_ctx *ctx, uint8_t *data, size_t len, return copied; } -static inline void send_report_error(struct isotp_send_ctx *ctx, uint32_t err) +static inline void send_report_error(struct isotp_send_ctx *sctx, uint32_t err) { - ctx->state = ISOTP_TX_ERR; - ctx->error_nr = err; + sctx->state = ISOTP_TX_ERR; + sctx->error_nr = err; } static void send_can_tx_cb(const struct device *dev, int error, void *arg) { - struct isotp_send_ctx *ctx = (struct isotp_send_ctx *)arg; + struct isotp_send_ctx *sctx = (struct isotp_send_ctx *)arg; ARG_UNUSED(dev); - ctx->tx_backlog--; - k_sem_give(&ctx->tx_sem); + sctx->tx_backlog--; + k_sem_give(&sctx->tx_sem); - if (ctx->state == ISOTP_TX_WAIT_BACKLOG) { - if (ctx->tx_backlog > 0) { + if (sctx->state == ISOTP_TX_WAIT_BACKLOG) { + if (sctx->tx_backlog > 0) { return; } - ctx->state = ISOTP_TX_WAIT_FIN; + sctx->state = ISOTP_TX_WAIT_FIN; } - k_work_submit(&ctx->work); + k_work_submit(&sctx->work); } static void send_timeout_handler(struct k_timer *timer) { - struct isotp_send_ctx *ctx = CONTAINER_OF(timer, struct isotp_send_ctx, timer); + struct isotp_send_ctx *sctx = CONTAINER_OF(timer, struct isotp_send_ctx, timer); - if (ctx->state != ISOTP_TX_SEND_CF) { - send_report_error(ctx, ISOTP_N_TIMEOUT_BS); + if (sctx->state != ISOTP_TX_SEND_CF) { + send_report_error(sctx, ISOTP_N_TIMEOUT_BS); LOG_ERR("Reception of next FC has timed out"); } - k_work_submit(&ctx->work); + k_work_submit(&sctx->work); } -static void send_process_fc(struct isotp_send_ctx *ctx, - struct can_frame *frame) +static void send_process_fc(struct isotp_send_ctx *sctx, struct can_frame *frame) { uint8_t *data = frame->data; - if (ctx->rx_addr.use_ext_addr) { - if (ctx->rx_addr.ext_addr != *data++) { + if ((sctx->rx_addr.flags & ISOTP_MSG_EXT_ADDR) != 0) { + if (sctx->rx_addr.ext_addr != *data++) { return; } } if ((*data & ISOTP_PCI_TYPE_MASK) != ISOTP_PCI_TYPE_FC) { LOG_ERR("Got unexpected PDU expected FC"); - send_report_error(ctx, ISOTP_N_UNEXP_PDU); + send_report_error(sctx, ISOTP_N_UNEXP_PDU); return; } #ifdef CONFIG_ISOTP_REQUIRE_RX_PADDING /* AUTOSAR requirement SWS_CanTp_00349 */ - if (frame->dlc != ISOTP_CAN_DL) { + if (frame->dlc < ISOTP_PADDED_FRAME_DL_MIN) { LOG_ERR("FC DL invalid. Ignore"); - send_report_error(ctx, ISOTP_N_ERROR); + send_report_error(sctx, ISOTP_N_ERROR); return; } #endif switch (*data++ & ISOTP_PCI_FS_MASK) { case ISOTP_PCI_FS_CTS: - ctx->state = ISOTP_TX_SEND_CF; - ctx->wft = 0; - ctx->tx_backlog = 0; - k_sem_reset(&ctx->tx_sem); - ctx->opts.bs = *data++; - ctx->opts.stmin = *data++; - ctx->bs = ctx->opts.bs; - LOG_DBG("Got CTS. BS: %d, STmin: %d", ctx->opts.bs, - ctx->opts.stmin); + sctx->state = ISOTP_TX_SEND_CF; + sctx->wft = 0; + sctx->tx_backlog = 0; + k_sem_reset(&sctx->tx_sem); + sctx->opts.bs = *data++; + sctx->opts.stmin = *data++; + sctx->bs = sctx->opts.bs; + LOG_DBG("Got CTS. BS: %d, STmin: %d", sctx->opts.bs, + sctx->opts.stmin); break; case ISOTP_PCI_FS_WAIT: LOG_DBG("Got WAIT frame"); - k_timer_start(&ctx->timer, K_MSEC(ISOTP_BS), K_NO_WAIT); - if (ctx->wft >= CONFIG_ISOTP_WFTMAX) { + k_timer_start(&sctx->timer, K_MSEC(ISOTP_BS_TIMEOUT_MS), K_NO_WAIT); + if (sctx->wft >= CONFIG_ISOTP_WFTMAX) { LOG_INF("Got to many wait frames"); - send_report_error(ctx, ISOTP_N_WFT_OVRN); + send_report_error(sctx, ISOTP_N_WFT_OVRN); } - ctx->wft++; + sctx->wft++; break; case ISOTP_PCI_FS_OVFLW: LOG_ERR("Got overflow FC frame"); - send_report_error(ctx, ISOTP_N_BUFFER_OVERFLW); + send_report_error(sctx, ISOTP_N_BUFFER_OVERFLW); break; default: - send_report_error(ctx, ISOTP_N_INVALID_FS); + send_report_error(sctx, ISOTP_N_INVALID_FS); } } static void send_can_rx_cb(const struct device *dev, struct can_frame *frame, void *arg) { - struct isotp_send_ctx *ctx = (struct isotp_send_ctx *)arg; + struct isotp_send_ctx *sctx = (struct isotp_send_ctx *)arg; ARG_UNUSED(dev); - if (ctx->state == ISOTP_TX_WAIT_FC) { - k_timer_stop(&ctx->timer); - send_process_fc(ctx, frame); + if (sctx->state == ISOTP_TX_WAIT_FC) { + k_timer_stop(&sctx->timer); + send_process_fc(sctx, frame); } else { LOG_ERR("Got unexpected PDU"); - send_report_error(ctx, ISOTP_N_UNEXP_PDU); + send_report_error(sctx, ISOTP_N_UNEXP_PDU); } - k_work_submit(&ctx->work); + k_work_submit(&sctx->work); } -static size_t get_ctx_data_length(struct isotp_send_ctx *ctx) +static size_t get_send_ctx_data_len(struct isotp_send_ctx *sctx) { - return ctx->is_net_buf ? net_buf_frags_len(ctx->buf) : ctx->len; + return sctx->is_net_buf ? net_buf_frags_len(sctx->buf) : sctx->len; } -static const uint8_t *get_data_ctx(struct isotp_send_ctx *ctx) +static const uint8_t *get_send_ctx_data(struct isotp_send_ctx *sctx) { - if (ctx->is_net_buf) { - return ctx->buf->data; + if (sctx->is_net_buf) { + return sctx->buf->data; } else { - return ctx->data; + return sctx->data; } } -static void pull_data_ctx(struct isotp_send_ctx *ctx, size_t len) +static void pull_send_ctx_data(struct isotp_send_ctx *sctx, size_t len) { - if (ctx->is_net_buf) { - net_buf_pull_mem(ctx->buf, len); + if (sctx->is_net_buf) { + net_buf_pull_mem(sctx->buf, len); } else { - ctx->data += len; - ctx->len -= len; + sctx->data += len; + sctx->len -= len; } } -static inline int send_sf(struct isotp_send_ctx *ctx) +static inline int send_sf(struct isotp_send_ctx *sctx) { - struct can_frame frame = { - .flags = ctx->tx_addr.ide != 0 ? CAN_FRAME_IDE : 0, - .id = ctx->tx_addr.ext_id - }; - size_t len = get_ctx_data_length(ctx); + struct can_frame frame; + size_t len = get_send_ctx_data_len(sctx); int index = 0; int ret; const uint8_t *data; - data = get_data_ctx(ctx); - pull_data_ctx(ctx, len); + prepare_frame(&frame, &sctx->tx_addr); + + data = get_send_ctx_data(sctx); + pull_send_ctx_data(sctx, len); - if (ctx->tx_addr.use_ext_addr) { - frame.data[index++] = ctx->tx_addr.ext_addr; + if ((sctx->tx_addr.flags & ISOTP_MSG_EXT_ADDR) != 0) { + frame.data[index++] = sctx->tx_addr.ext_addr; } - frame.data[index++] = ISOTP_PCI_TYPE_SF | len; + if (IS_ENABLED(CONFIG_CAN_FD_MODE) && (sctx->tx_addr.flags & ISOTP_MSG_FDF) != 0 && + len > ISOTP_4BIT_SF_MAX_CAN_DL - 1 - index) { + frame.data[index++] = ISOTP_PCI_TYPE_SF; + frame.data[index++] = len; + } else { + frame.data[index++] = ISOTP_PCI_TYPE_SF | len; + } - if (len > ISOTP_CAN_DL - index) { + if (len > sctx->tx_addr.dl - index) { LOG_ERR("SF len does not fit DL"); return -ENOSPC; } memcpy(&frame.data[index], data, len); -#ifdef CONFIG_ISOTP_ENABLE_TX_PADDING - /* AUTOSAR requirement SWS_CanTp_00348 */ - memset(&frame.data[index + len], 0xCC, ISOTP_CAN_DL - len - index); - frame.dlc = ISOTP_CAN_DL; -#else - frame.dlc = len + index; -#endif + if (IS_ENABLED(CONFIG_ISOTP_ENABLE_TX_PADDING) || + (IS_ENABLED(CONFIG_CAN_FD_MODE) && (sctx->tx_addr.flags & ISOTP_MSG_FDF) != 0 && + len + index > ISOTP_PADDED_FRAME_DL_MIN)) { + /* AUTOSAR requirements SWS_CanTp_00348 / SWS_CanTp_00351. + * Mandatory for ISO-TP CAN FD frames > 8 bytes. + */ + frame.dlc = can_bytes_to_dlc( + MAX(ISOTP_PADDED_FRAME_DL_MIN, len + index)); + memset(&frame.data[index + len], ISOTP_PAD_BYTE, + can_dlc_to_bytes(frame.dlc) - len - index); + } else { + frame.dlc = can_bytes_to_dlc(len + index); + } - ctx->state = ISOTP_TX_SEND_SF; - ret = can_send(ctx->can_dev, &frame, K_MSEC(ISOTP_A), - send_can_tx_cb, ctx); + sctx->state = ISOTP_TX_SEND_SF; + ret = can_send(sctx->can_dev, &frame, K_MSEC(ISOTP_A_TIMEOUT_MS), send_can_tx_cb, sctx); return ret; } -static inline int send_ff(struct isotp_send_ctx *ctx) +static inline int send_ff(struct isotp_send_ctx *sctx) { - struct can_frame frame = { - .flags = ctx->tx_addr.ide != 0 ? CAN_FRAME_IDE : 0, - .id = ctx->tx_addr.ext_id, - .dlc = ISOTP_CAN_DL - }; + struct can_frame frame; int index = 0; - size_t len = get_ctx_data_length(ctx); + size_t len = get_send_ctx_data_len(sctx); int ret; const uint8_t *data; - if (ctx->tx_addr.use_ext_addr) { - frame.data[index++] = ctx->tx_addr.ext_addr; + prepare_frame(&frame, &sctx->tx_addr); + + frame.dlc = can_bytes_to_dlc(sctx->tx_addr.dl); + + if ((sctx->tx_addr.flags & ISOTP_MSG_EXT_ADDR) != 0) { + frame.data[index++] = sctx->tx_addr.ext_addr; } if (len > 0xFFF) { @@ -923,56 +966,59 @@ static inline int send_ff(struct isotp_send_ctx *ctx) /* According to ISO FF has sn 0 and is incremented to one * although it's not part of the FF frame */ - ctx->sn = 1; - data = get_data_ctx(ctx); - pull_data_ctx(ctx, ISOTP_CAN_DL - index); - memcpy(&frame.data[index], data, ISOTP_CAN_DL - index); + sctx->sn = 1; + data = get_send_ctx_data(sctx); + pull_send_ctx_data(sctx, sctx->tx_addr.dl - index); + memcpy(&frame.data[index], data, sctx->tx_addr.dl - index); - ret = can_send(ctx->can_dev, &frame, K_MSEC(ISOTP_A), - send_can_tx_cb, ctx); + ret = can_send(sctx->can_dev, &frame, K_MSEC(ISOTP_A_TIMEOUT_MS), send_can_tx_cb, sctx); return ret; } -static inline int send_cf(struct isotp_send_ctx *ctx) +static inline int send_cf(struct isotp_send_ctx *sctx) { - struct can_frame frame = { - .flags = ctx->tx_addr.ide != 0 ? CAN_FRAME_IDE : 0, - .id = ctx->tx_addr.ext_id, - }; + struct can_frame frame; int index = 0; int ret; int len; int rem_len; const uint8_t *data; - if (ctx->tx_addr.use_ext_addr) { - frame.data[index++] = ctx->tx_addr.ext_addr; + prepare_frame(&frame, &sctx->tx_addr); + + if ((sctx->tx_addr.flags & ISOTP_MSG_EXT_ADDR) != 0) { + frame.data[index++] = sctx->tx_addr.ext_addr; } /*sn wraps around at 0xF automatically because it has a 4 bit size*/ - frame.data[index++] = ISOTP_PCI_TYPE_CF | ctx->sn; + frame.data[index++] = ISOTP_PCI_TYPE_CF | sctx->sn; - rem_len = get_ctx_data_length(ctx); - len = MIN(rem_len, ISOTP_CAN_DL - index); + rem_len = get_send_ctx_data_len(sctx); + len = MIN(rem_len, sctx->tx_addr.dl - index); rem_len -= len; - data = get_data_ctx(ctx); + data = get_send_ctx_data(sctx); memcpy(&frame.data[index], data, len); -#ifdef CONFIG_ISOTP_ENABLE_TX_PADDING - /* AUTOSAR requirement SWS_CanTp_00348 */ - memset(&frame.data[index + len], 0xCC, ISOTP_CAN_DL - len - index); - frame.dlc = ISOTP_CAN_DL; -#else - frame.dlc = len + index; -#endif + if (IS_ENABLED(CONFIG_ISOTP_ENABLE_TX_PADDING) || + (IS_ENABLED(CONFIG_CAN_FD_MODE) && (sctx->tx_addr.flags & ISOTP_MSG_FDF) != 0 && + len + index > ISOTP_PADDED_FRAME_DL_MIN)) { + /* AUTOSAR requirements SWS_CanTp_00348 / SWS_CanTp_00351. + * Mandatory for ISO-TP CAN FD frames > 8 bytes. + */ + frame.dlc = can_bytes_to_dlc( + MAX(ISOTP_PADDED_FRAME_DL_MIN, len + index)); + memset(&frame.data[index + len], ISOTP_PAD_BYTE, + can_dlc_to_bytes(frame.dlc) - len - index); + } else { + frame.dlc = can_bytes_to_dlc(len + index); + } - ret = can_send(ctx->can_dev, &frame, K_MSEC(ISOTP_A), - send_can_tx_cb, ctx); + ret = can_send(sctx->can_dev, &frame, K_MSEC(ISOTP_A_TIMEOUT_MS), send_can_tx_cb, sctx); if (ret == 0) { - ctx->sn++; - pull_data_ctx(ctx, len); - ctx->bs--; - ctx->tx_backlog++; + sctx->sn++; + pull_send_ctx_data(sctx, len); + sctx->bs--; + sctx->tx_backlog++; } ret = ret ? ret : rem_len; @@ -980,28 +1026,28 @@ static inline int send_cf(struct isotp_send_ctx *ctx) } #ifdef CONFIG_ISOTP_ENABLE_CONTEXT_BUFFERS -static inline void free_send_ctx(struct isotp_send_ctx **ctx) +static inline void free_send_ctx(struct isotp_send_ctx **sctx) { - if ((*ctx)->is_net_buf) { - net_buf_unref((*ctx)->buf); - (*ctx)->buf = NULL; + if ((*sctx)->is_net_buf) { + net_buf_unref((*sctx)->buf); + (*sctx)->buf = NULL; } - if ((*ctx)->is_ctx_slab) { - k_mem_slab_free(&ctx_slab, (void *)*ctx); + if ((*sctx)->is_ctx_slab) { + k_mem_slab_free(&ctx_slab, (void *)*sctx); } } -static int alloc_ctx(struct isotp_send_ctx **ctx, k_timeout_t timeout) +static int alloc_send_ctx(struct isotp_send_ctx **sctx, k_timeout_t timeout) { int ret; - ret = k_mem_slab_alloc(&ctx_slab, (void **)ctx, timeout); + ret = k_mem_slab_alloc(&ctx_slab, (void **)sctx, timeout); if (ret) { return ISOTP_NO_CTX_LEFT; } - (*ctx)->is_ctx_slab = 1; + (*sctx)->is_ctx_slab = 1; return 0; } @@ -1024,56 +1070,56 @@ static k_timeout_t stmin_to_timeout(uint8_t stmin) return K_MSEC(stmin); } -static void send_state_machine(struct isotp_send_ctx *ctx) +static void send_state_machine(struct isotp_send_ctx *sctx) { int ret; - switch (ctx->state) { + switch (sctx->state) { case ISOTP_TX_SEND_FF: - send_ff(ctx); - k_timer_start(&ctx->timer, K_MSEC(ISOTP_BS), K_NO_WAIT); - ctx->state = ISOTP_TX_WAIT_FC; + send_ff(sctx); + k_timer_start(&sctx->timer, K_MSEC(ISOTP_BS_TIMEOUT_MS), K_NO_WAIT); + sctx->state = ISOTP_TX_WAIT_FC; LOG_DBG("SM send FF"); break; case ISOTP_TX_SEND_CF: LOG_DBG("SM send CF"); - k_timer_stop(&ctx->timer); + k_timer_stop(&sctx->timer); do { - ret = send_cf(ctx); + ret = send_cf(sctx); if (!ret) { - ctx->state = ISOTP_TX_WAIT_BACKLOG; + sctx->state = ISOTP_TX_WAIT_BACKLOG; break; } if (ret < 0) { LOG_ERR("Failed to send CF"); - send_report_error(ctx, ret == -EAGAIN ? + send_report_error(sctx, ret == -EAGAIN ? ISOTP_N_TIMEOUT_A : ISOTP_N_ERROR); break; } - if (ctx->opts.bs && !ctx->bs) { - k_timer_start(&ctx->timer, K_MSEC(ISOTP_BS), K_NO_WAIT); - ctx->state = ISOTP_TX_WAIT_FC; + if (sctx->opts.bs && !sctx->bs) { + k_timer_start(&sctx->timer, K_MSEC(ISOTP_BS_TIMEOUT_MS), K_NO_WAIT); + sctx->state = ISOTP_TX_WAIT_FC; LOG_DBG("BS reached. Wait for FC again"); break; - } else if (ctx->opts.stmin) { - ctx->state = ISOTP_TX_WAIT_ST; + } else if (sctx->opts.stmin) { + sctx->state = ISOTP_TX_WAIT_ST; break; } /* Ensure FIFO style transmission of CF */ - k_sem_take(&ctx->tx_sem, K_FOREVER); + k_sem_take(&sctx->tx_sem, K_FOREVER); } while (ret > 0); break; case ISOTP_TX_WAIT_ST: - k_timer_start(&ctx->timer, stmin_to_timeout(ctx->opts.stmin), K_NO_WAIT); - ctx->state = ISOTP_TX_SEND_CF; + k_timer_start(&sctx->timer, stmin_to_timeout(sctx->opts.stmin), K_NO_WAIT); + sctx->state = ISOTP_TX_SEND_CF; LOG_DBG("SM wait ST"); break; @@ -1083,21 +1129,21 @@ static void send_state_machine(struct isotp_send_ctx *ctx) case ISOTP_TX_SEND_SF: __fallthrough; case ISOTP_TX_WAIT_FIN: - if (ctx->filter_id >= 0) { - can_remove_rx_filter(ctx->can_dev, ctx->filter_id); + if (sctx->filter_id >= 0) { + can_remove_rx_filter(sctx->can_dev, sctx->filter_id); } LOG_DBG("SM finish"); - k_timer_stop(&ctx->timer); + k_timer_stop(&sctx->timer); - if (ctx->has_callback) { - ctx->fin_cb.cb(ctx->error_nr, ctx->fin_cb.arg); - free_send_ctx(&ctx); + if (sctx->has_callback) { + sctx->fin_cb.cb(sctx->error_nr, sctx->fin_cb.arg); + free_send_ctx(&sctx); } else { - k_sem_give(&ctx->fin_sem); + k_sem_give(&sctx->fin_sem); } - ctx->state = ISOTP_TX_STATE_RESET; + sctx->state = ISOTP_TX_STATE_RESET; break; default: @@ -1107,107 +1153,142 @@ static void send_state_machine(struct isotp_send_ctx *ctx) static void send_work_handler(struct k_work *item) { - struct isotp_send_ctx *ctx = CONTAINER_OF(item, struct isotp_send_ctx, - work); + struct isotp_send_ctx *sctx = CONTAINER_OF(item, struct isotp_send_ctx, work); - send_state_machine(ctx); + send_state_machine(sctx); } -static inline int attach_fc_filter(struct isotp_send_ctx *ctx) +static inline int add_fc_filter(struct isotp_send_ctx *sctx) { - struct can_filter filter = { - .flags = CAN_FILTER_DATA | ((ctx->rx_addr.ide != 0) ? CAN_FILTER_IDE : 0), - .id = ctx->rx_addr.ext_id, - .mask = CAN_EXT_ID_MASK - }; + struct can_filter filter; + + prepare_filter(&filter, &sctx->rx_addr, CAN_EXT_ID_MASK); - ctx->filter_id = can_add_rx_filter(ctx->can_dev, send_can_rx_cb, ctx, + sctx->filter_id = can_add_rx_filter(sctx->can_dev, send_can_rx_cb, sctx, &filter); - if (ctx->filter_id < 0) { - LOG_ERR("Error attaching FC filter [%d]", ctx->filter_id); + if (sctx->filter_id < 0) { + LOG_ERR("Error adding FC filter [%d]", sctx->filter_id); return ISOTP_NO_FREE_FILTER; } return 0; } -static int send(struct isotp_send_ctx *ctx, const struct device *can_dev, +static int send(struct isotp_send_ctx *sctx, const struct device *can_dev, const struct isotp_msg_id *tx_addr, const struct isotp_msg_id *rx_addr, isotp_tx_callback_t complete_cb, void *cb_arg) { + can_mode_t cap; size_t len; int ret; - __ASSERT_NO_MSG(ctx); + __ASSERT_NO_MSG(sctx); __ASSERT_NO_MSG(can_dev); __ASSERT_NO_MSG(rx_addr && tx_addr); + if ((rx_addr->flags & ISOTP_MSG_FDF) != 0 || (tx_addr->flags & ISOTP_MSG_FDF) != 0) { + ret = can_get_capabilities(can_dev, &cap); + if (ret != 0 || (cap & CAN_MODE_FD) == 0) { + LOG_ERR("CAN controller does not support FD mode"); + return ISOTP_N_ERROR; + } + } + if (complete_cb) { - ctx->fin_cb.cb = complete_cb; - ctx->fin_cb.arg = cb_arg; - ctx->has_callback = 1; + sctx->fin_cb.cb = complete_cb; + sctx->fin_cb.arg = cb_arg; + sctx->has_callback = 1; } else { - k_sem_init(&ctx->fin_sem, 0, 1); - ctx->has_callback = 0; + k_sem_init(&sctx->fin_sem, 0, 1); + sctx->has_callback = 0; + } + + k_sem_init(&sctx->tx_sem, 0, 1); + sctx->can_dev = can_dev; + sctx->tx_addr = *tx_addr; + sctx->rx_addr = *rx_addr; + sctx->error_nr = ISOTP_N_OK; + sctx->wft = 0; + k_work_init(&sctx->work, send_work_handler); + k_timer_init(&sctx->timer, send_timeout_handler, NULL); + + switch (sctx->tx_addr.dl) { + case 0: + if ((sctx->tx_addr.flags & ISOTP_MSG_FDF) == 0) { + sctx->tx_addr.dl = 8; + } else { + sctx->tx_addr.dl = 64; + } + __fallthrough; + case 8: + break; + case 12: + case 16: + case 20: + case 24: + case 32: + case 48: + case 64: + if ((sctx->tx_addr.flags & ISOTP_MSG_FDF) == 0) { + LOG_ERR("TX_DL > 8 only supported with FD mode"); + return ISOTP_N_ERROR; + } + break; + default: + LOG_ERR("Invalid TX_DL: %u", sctx->tx_addr.dl); + return ISOTP_N_ERROR; } - k_sem_init(&ctx->tx_sem, 0, 1); - ctx->can_dev = can_dev; - ctx->tx_addr = *tx_addr; - ctx->rx_addr = *rx_addr; - ctx->error_nr = ISOTP_N_OK; - ctx->wft = 0; - k_work_init(&ctx->work, send_work_handler); - k_timer_init(&ctx->timer, send_timeout_handler, NULL); - - len = get_ctx_data_length(ctx); + len = get_send_ctx_data_len(sctx); LOG_DBG("Send %zu bytes to addr 0x%x and listen on 0x%x", len, - ctx->tx_addr.ext_id, ctx->rx_addr.ext_id); - if (len > ISOTP_CAN_DL - (tx_addr->use_ext_addr ? 2 : 1)) { - ret = attach_fc_filter(ctx); + sctx->tx_addr.ext_id, sctx->rx_addr.ext_id); + /* Single frames > 8 bytes use an additional byte for length (CAN FD only) */ + if (len > sctx->tx_addr.dl - (((tx_addr->flags & ISOTP_MSG_EXT_ADDR) != 0) ? 2 : 1) - + ((sctx->tx_addr.dl > ISOTP_4BIT_SF_MAX_CAN_DL) ? 1 : 0)) { + ret = add_fc_filter(sctx); if (ret) { - LOG_ERR("Can't attach fc filter: %d", ret); - free_send_ctx(&ctx); + LOG_ERR("Can't add fc filter: %d", ret); + free_send_ctx(&sctx); return ret; } LOG_DBG("Starting work to send FF"); - ctx->state = ISOTP_TX_SEND_FF; - k_work_submit(&ctx->work); + sctx->state = ISOTP_TX_SEND_FF; + k_work_submit(&sctx->work); } else { LOG_DBG("Sending single frame"); - ctx->filter_id = -1; - ret = send_sf(ctx); + sctx->filter_id = -1; + ret = send_sf(sctx); if (ret) { - free_send_ctx(&ctx); + free_send_ctx(&sctx); return ret == -EAGAIN ? ISOTP_N_TIMEOUT_A : ISOTP_N_ERROR; } } if (!complete_cb) { - k_sem_take(&ctx->fin_sem, K_FOREVER); - ret = ctx->error_nr; - free_send_ctx(&ctx); + k_sem_take(&sctx->fin_sem, K_FOREVER); + ret = sctx->error_nr; + free_send_ctx(&sctx); return ret; } return ISOTP_N_OK; } -int isotp_send(struct isotp_send_ctx *ctx, const struct device *can_dev, +int isotp_send(struct isotp_send_ctx *sctx, const struct device *can_dev, const uint8_t *data, size_t len, const struct isotp_msg_id *tx_addr, const struct isotp_msg_id *rx_addr, isotp_tx_callback_t complete_cb, void *cb_arg) { - ctx->data = data; - ctx->len = len; - ctx->is_ctx_slab = 0; - ctx->is_net_buf = 0; + sctx->data = data; + sctx->len = len; + sctx->is_ctx_slab = 0; + sctx->is_net_buf = 0; - return send(ctx, can_dev, tx_addr, rx_addr, complete_cb, cb_arg); + return send(sctx, can_dev, tx_addr, rx_addr, complete_cb, cb_arg); } #ifdef CONFIG_ISOTP_ENABLE_CONTEXT_BUFFERS @@ -1219,21 +1300,21 @@ int isotp_send_ctx_buf(const struct device *can_dev, isotp_tx_callback_t complete_cb, void *cb_arg, k_timeout_t timeout) { - struct isotp_send_ctx *ctx; + struct isotp_send_ctx *sctx; int ret; __ASSERT_NO_MSG(data); - ret = alloc_ctx(&ctx, timeout); + ret = alloc_send_ctx(&sctx, timeout); if (ret) { return ret; } - ctx->data = data; - ctx->len = len; - ctx->is_net_buf = 0; + sctx->data = data; + sctx->len = len; + sctx->is_net_buf = 0; - return send(ctx, can_dev, tx_addr, rx_addr, complete_cb, cb_arg); + return send(sctx, can_dev, tx_addr, rx_addr, complete_cb, cb_arg); } int isotp_send_net_ctx_buf(const struct device *can_dev, @@ -1243,20 +1324,20 @@ int isotp_send_net_ctx_buf(const struct device *can_dev, isotp_tx_callback_t complete_cb, void *cb_arg, k_timeout_t timeout) { - struct isotp_send_ctx *ctx; + struct isotp_send_ctx *sctx; int ret; __ASSERT_NO_MSG(data); - ret = alloc_ctx(&ctx, timeout); + ret = alloc_send_ctx(&sctx, timeout); if (ret) { return ret; } - ctx->is_net_buf = 1; - ctx->buf = data; + sctx->is_net_buf = 1; + sctx->buf = data; - return send(ctx, can_dev, tx_addr, rx_addr, complete_cb, cb_arg); + return send(sctx, can_dev, tx_addr, rx_addr, complete_cb, cb_arg); } #ifdef CONFIG_ISOTP_USE_TX_BUF @@ -1267,29 +1348,29 @@ int isotp_send_buf(const struct device *can_dev, isotp_tx_callback_t complete_cb, void *cb_arg, k_timeout_t timeout) { - struct isotp_send_ctx *ctx; + struct isotp_send_ctx *sctx; struct net_buf *buf; int ret; __ASSERT_NO_MSG(data); - ret = alloc_ctx(&ctx, timeout); + ret = alloc_send_ctx(&sctx, timeout); if (ret) { return ret; } buf = net_buf_alloc_len(&isotp_tx_pool, len, timeout); if (!buf) { - k_mem_slab_free(&ctx_slab, (void *)ctx); + k_mem_slab_free(&ctx_slab, (void *)sctx); return ISOTP_NO_BUF_DATA_LEFT; } net_buf_add_mem(buf, data, len); - ctx->is_net_buf = 1; - ctx->buf = buf; + sctx->is_net_buf = 1; + sctx->buf = buf; - return send(ctx, can_dev, tx_addr, rx_addr, complete_cb, cb_arg); + return send(sctx, can_dev, tx_addr, rx_addr, complete_cb, cb_arg); } #endif /*CONFIG_ISOTP_USE_TX_BUF*/ #endif /*CONFIG_ISOTP_ENABLE_CONTEXT_BUFFERS*/ diff --git a/subsys/canbus/isotp/isotp_internal.h b/subsys/canbus/isotp/isotp_internal.h index 24db459a2ec..c5b7dec58e7 100644 --- a/subsys/canbus/isotp/isotp_internal.h +++ b/subsys/canbus/isotp/isotp_internal.h @@ -4,38 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef ZEPHYR_SUBSYS_NET_CAN_ISOTP_INTERNAL_H_ -#define ZEPHYR_SUBSYS_NET_CAN_ISOTP_INTERNAL_H_ - +#ifndef ZEPHYR_SUBSYS_CANBUS_ISOTP_ISOTP_INTERNAL_H_ +#define ZEPHYR_SUBSYS_CANBUS_ISOTP_ISOTP_INTERNAL_H_ #include #include -/* - * Abbreviations - * BS Block Size - * CAN_DL CAN LL data size - * CF Consecutive Frame - * CTS Continue to send - * DLC Data length code - * FC Flow Control - * FF First Frame - * SF Single Frame - * FS Flow Status - * AE Adders Extension - * SN Sequence Number - * ST Separation time - * PCI Process Control Information - */ - -/* This is for future use when we have CAN-FD */ -#ifdef ISOTP_USE_CAN_FD -/* #define ISOTP_CAN_DL CONFIG_ISOTP_TX_DL* */ -#define ISOTP_CAN_DL 8 -#else -#define ISOTP_CAN_DL 8 -#endif/*ISOTP_USE_CAN_FD*/ - /* Protocol control information*/ #define ISOTP_PCI_SF 0x00 /* Single frame*/ #define ISOTP_PCI_FF 0x01 /* First frame */ @@ -67,7 +41,9 @@ #define ISOTP_PCI_SN_MASK 0x0F -#define ISOTP_FF_DL_MIN (ISOTP_CAN_DL) +#define ISOTP_FF_DL_MIN 8 +#define ISOTP_PADDED_FRAME_DL_MIN 8 +#define ISOTP_PAD_BYTE 0xCC #define ISOTP_STMIN_MAX 0xFA #define ISOTP_STMIN_MS_MAX 0x7F @@ -76,12 +52,14 @@ #define ISOTP_WFT_FIRST 0xFF -#define ISOTP_BS (CONFIG_ISOTP_BS_TIMEOUT) -#define ISOTP_A (CONFIG_ISOTP_A_TIMEOUT) -#define ISOTP_CR (CONFIG_ISOTP_CR_TIMEOUT) +#define ISOTP_4BIT_SF_MAX_CAN_DL 8 + +#define ISOTP_BS_TIMEOUT_MS (CONFIG_ISOTP_BS_TIMEOUT) +#define ISOTP_A_TIMEOUT_MS (CONFIG_ISOTP_A_TIMEOUT) +#define ISOTP_CR_TIMEOUT_MS (CONFIG_ISOTP_CR_TIMEOUT) /* Just before the sender would time out*/ -#define ISOTP_ALLOC_TIMEOUT (CONFIG_ISOTP_A_TIMEOUT - 100) +#define ISOTP_ALLOC_TIMEOUT_MS (CONFIG_ISOTP_A_TIMEOUT - 100) #ifdef __cplusplus extern "C" { @@ -121,4 +99,4 @@ struct isotp_global_ctx { } #endif -#endif /* ZEPHYR_SUBSYS_NET_CAN_ISOTP_INTERNAL_H_ */ +#endif /* ZEPHYR_SUBSYS_CANBUS_ISOTP_ISOTP_INTERNAL_H_ */ diff --git a/subsys/debug/Kconfig b/subsys/debug/Kconfig index 47b03f25325..54d83f18ff6 100644 --- a/subsys/debug/Kconfig +++ b/subsys/debug/Kconfig @@ -257,7 +257,7 @@ config ASSERT_LEVEL config SPIN_VALIDATE bool "Spinlock validation" depends on MULTITHREADING - depends on MP_NUM_CPUS <= 4 + depends on MP_MAX_NUM_CPUS <= 4 default y if !FLASH || FLASH_SIZE > 32 help There's a spinlock validation framework available when asserts are @@ -397,6 +397,7 @@ endmenu config GDBSTUB bool "GDB remote serial protocol support [EXPERIMENTAL]" depends on ARCH_HAS_GDBSTUB + select UART_USE_RUNTIME_CONFIGURE select EXPERIMENTAL help This option enable support the target using GDB, or any other diff --git a/subsys/debug/coredump/Kconfig b/subsys/debug/coredump/Kconfig index 5d31913dd7e..63126a28372 100644 --- a/subsys/debug/coredump/Kconfig +++ b/subsys/debug/coredump/Kconfig @@ -9,13 +9,13 @@ menuconfig DEBUG_COREDUMP if DEBUG_COREDUMP -choice +choice DEBUG_COREDUMP_BACKEND prompt "Coredump backend" - default DEBUG_COREDUMP_BACKEND_LOGGING if LOG + default DEBUG_COREDUMP_BACKEND_LOGGING config DEBUG_COREDUMP_BACKEND_LOGGING bool "Use Logging subsystem for coredump" - depends on LOG + select LOG help Core dump is done via logging subsystem. @@ -30,6 +30,7 @@ config DEBUG_COREDUMP_BACKEND_FLASH_PARTITION config DEBUG_COREDUMP_BACKEND_INTEL_ADSP_MEM_WINDOW bool "Use memory window for coredump on Intel ADSP" + depends on DT_HAS_INTEL_ADSP_MEM_WINDOW_ENABLED help Core dump is done via memory window slot[1]. It is Intel ADSP memory region shared with xtensa DSP. @@ -42,7 +43,7 @@ config DEBUG_COREDUMP_BACKEND_OTHER endchoice -choice +choice DEBUG_COREDUMP_MEMORY_DUMP prompt "Memory dump" default DEBUG_COREDUMP_MEMORY_DUMP_LINKER_RAM @@ -70,7 +71,6 @@ endchoice config DEBUG_COREDUMP_SHELL bool "Coredump shell" - default y depends on SHELL help This shell provides access to coredump and its backends. diff --git a/subsys/debug/coredump/coredump_backend_flash_partition.c b/subsys/debug/coredump/coredump_backend_flash_partition.c index d7ce6a02cc2..434cd4774a1 100644 --- a/subsys/debug/coredump/coredump_backend_flash_partition.c +++ b/subsys/debug/coredump/coredump_backend_flash_partition.c @@ -527,6 +527,7 @@ static void coredump_flash_backend_buffer_output(uint8_t *buf, size_t buflen) &backend_ctx.stream_ctx, tmp_buf, copy_sz, false); if (backend_ctx.error != 0) { + LOG_ERR("Flash write error: %d", backend_ctx.error); break; } diff --git a/subsys/debug/thread_info.c b/subsys/debug/thread_info.c index dde7d1d2a20..742cbd59485 100644 --- a/subsys/debug/thread_info.c +++ b/subsys/debug/thread_info.c @@ -40,7 +40,7 @@ enum { * Only version 1 is backward compatible to version 0. */ __attribute__((used, section(".dbg_thread_info"))) -size_t _kernel_thread_info_offsets[] = { +const size_t _kernel_thread_info_offsets[] = { /* Version 0 starts */ [THREAD_INFO_OFFSET_VERSION] = 1, [THREAD_INFO_OFFSET_K_CURR_THREAD] = offsetof(struct _cpu, current), @@ -146,15 +146,15 @@ size_t _kernel_thread_info_offsets[] = { #endif /* CONFIG_ARC */ }; -extern size_t __attribute__((alias("_kernel_thread_info_offsets"))) +extern const size_t __attribute__((alias("_kernel_thread_info_offsets"))) _kernel_openocd_offsets; __attribute__((used, section(".dbg_thread_info"))) -size_t _kernel_thread_info_num_offsets = ARRAY_SIZE(_kernel_thread_info_offsets); -extern size_t __attribute__((alias("_kernel_thread_info_num_offsets"))) +const size_t _kernel_thread_info_num_offsets = ARRAY_SIZE(_kernel_thread_info_offsets); +extern const size_t __attribute__((alias("_kernel_thread_info_num_offsets"))) _kernel_openocd_num_offsets; __attribute__((used, section(".dbg_thread_info"))) -uint8_t _kernel_thread_info_size_t_size = (uint8_t)sizeof(size_t); -extern uint8_t __attribute__((alias("_kernel_thread_info_size_t_size"))) +const uint8_t _kernel_thread_info_size_t_size = (uint8_t)sizeof(size_t); +extern const uint8_t __attribute__((alias("_kernel_thread_info_size_t_size"))) _kernel_openocd_size_t_size; diff --git a/subsys/dfu/Kconfig b/subsys/dfu/Kconfig index 121fa3964f6..e320185dfef 100644 --- a/subsys/dfu/Kconfig +++ b/subsys/dfu/Kconfig @@ -33,7 +33,6 @@ endchoice config MCUBOOT_SHELL bool "MCUboot shell" - default y depends on MCUBOOT_IMG_MANAGER depends on SHELL help diff --git a/subsys/fs/CMakeLists.txt b/subsys/fs/CMakeLists.txt index 0c1bce7425f..e6c66d304ce 100644 --- a/subsys/fs/CMakeLists.txt +++ b/subsys/fs/CMakeLists.txt @@ -31,7 +31,11 @@ if(CONFIG_FUSE_FS_ACCESS) find_package(PkgConfig REQUIRED) pkg_search_module(FUSE REQUIRED fuse) zephyr_include_directories(${FUSE_INCLUDE_DIR}) - zephyr_link_libraries(${FUSE_LIBRARIES}) + if (CONFIG_NATIVE_LIBRARY) + target_link_options(native_simulator INTERFACE "-l${FUSE_LIBRARIES}") + else() + zephyr_link_libraries(${FUSE_LIBRARIES}) + endif() zephyr_library_compile_definitions(_FILE_OFFSET_BITS=64) zephyr_library_sources(fuse_fs_access.c) endif() diff --git a/subsys/fs/ext2/ext2_format.c b/subsys/fs/ext2/ext2_format.c index 6e35555e53f..9fb9792df75 100644 --- a/subsys/fs/ext2/ext2_format.c +++ b/subsys/fs/ext2/ext2_format.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include diff --git a/subsys/fs/fuse_fs_access.c b/subsys/fs/fuse_fs_access.c index 8453c6544e8..e39416f91cf 100644 --- a/subsys/fs/fuse_fs_access.c +++ b/subsys/fs/fuse_fs_access.c @@ -176,9 +176,15 @@ static int fuse_fs_access_readdir(const char *path, void *buf, * directory but FUSE strips the trailing slashes from * directory names so add it back. */ - char mount_path[PATH_MAX]; + char mount_path[PATH_MAX] = {0}; + size_t len = strlen(path); - sprintf(mount_path, "%s/", path); + if (len >= (PATH_MAX - 2)) { + return -ENOMEM; + } + + memcpy(mount_path, path, len); + mount_path[len] = '/'; err = fs_opendir(&dir, mount_path); } else { err = fs_opendir(&dir, path); diff --git a/subsys/input/input_longpress.c b/subsys/input/input_longpress.c index b8510c66a5c..c9acbbf14fe 100644 --- a/subsys/input/input_longpress.c +++ b/subsys/input/input_longpress.c @@ -137,6 +137,6 @@ static int longpress_init(const struct device *dev) }; \ DEVICE_DT_INST_DEFINE(inst, longpress_init, NULL, \ &longpress_data_##inst, &longpress_config_##inst, \ - APPLICATION, CONFIG_INPUT_INIT_PRIORITY, NULL); + POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, NULL); DT_INST_FOREACH_STATUS_OKAY(INPUT_LONGPRESS_DEFINE) diff --git a/subsys/ipc/ipc_service/backends/CMakeLists.txt b/subsys/ipc/ipc_service/backends/CMakeLists.txt index 0f5629a14c5..d6ca8fb76c3 100644 --- a/subsys/ipc/ipc_service/backends/CMakeLists.txt +++ b/subsys/ipc/ipc_service/backends/CMakeLists.txt @@ -3,4 +3,5 @@ zephyr_sources_ifdef(CONFIG_IPC_SERVICE_BACKEND_ICMSG ipc_icmsg.c) zephyr_sources_ifdef(CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_INITIATOR ipc_icmsg_me_initiator.c) zephyr_sources_ifdef(CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_FOLLOWER ipc_icmsg_me_follower.c) +zephyr_sources_ifdef(CONFIG_IPC_SERVICE_BACKEND_ICBMSG ipc_icbmsg.c) zephyr_sources_ifdef(CONFIG_IPC_SERVICE_BACKEND_RPMSG ipc_rpmsg_static_vrings.c) diff --git a/subsys/ipc/ipc_service/backends/Kconfig b/subsys/ipc/ipc_service/backends/Kconfig index 61d113aac3f..8230465e246 100644 --- a/subsys/ipc/ipc_service/backends/Kconfig +++ b/subsys/ipc/ipc_service/backends/Kconfig @@ -49,4 +49,5 @@ config IPC_SERVICE_BACKEND_ICMSG_ME_FOLLOWER role. rsource "Kconfig.icmsg_me" +rsource "Kconfig.icbmsg" rsource "Kconfig.rpmsg" diff --git a/subsys/ipc/ipc_service/backends/Kconfig.icbmsg b/subsys/ipc/ipc_service/backends/Kconfig.icbmsg new file mode 100644 index 00000000000..e31b5cadd77 --- /dev/null +++ b/subsys/ipc/ipc_service/backends/Kconfig.icbmsg @@ -0,0 +1,31 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +menuconfig IPC_SERVICE_BACKEND_ICBMSG + bool "ICMSG backend with dynamically allocated buffers" + default y + depends on MBOX + depends on DT_HAS_ZEPHYR_IPC_ICBMSG_ENABLED + select IPC_SERVICE_ICMSG + help + Choosing this backend results in multi endpoint implementation based + on dynamically allocated buffers. References to them are send over + ICMsg circular buffer. + +if IPC_SERVICE_BACKEND_ICBMSG + +config IPC_SERVICE_BACKEND_ICBMSG_NUM_EP + int "Endpoints count" + range 1 254 + default 4 + help + Number of endpoints supported by the ICBMsg IPC service + backend. The number of endpoints are applied to all the instances, + so this value should be maximum number among all the instances. + +module = IPC_SERVICE_BACKEND_ICBMSG +module-str = ICMSG backend with separate buffers +module-help = Sets log level for ICMsg backend with buffers +source "subsys/logging/Kconfig.template.log_config" + +endif # IPC_SERVICE_BACKEND_ICBMSG diff --git a/subsys/ipc/ipc_service/backends/Kconfig.icmsg_me b/subsys/ipc/ipc_service/backends/Kconfig.icmsg_me index 0513719cc98..e348984fb62 100644 --- a/subsys/ipc/ipc_service/backends/Kconfig.icmsg_me +++ b/subsys/ipc/ipc_service/backends/Kconfig.icmsg_me @@ -28,14 +28,4 @@ config IPC_SERVICE_BACKEND_ICMSG_ME_EP_NAME_LEN Maximal length of a string used to discover endpoints between the initiator and the follower. -config IPC_SERVICE_BACKEND_ICMSG_ME_NOCOPY_RX - bool "Nocopy feature for receive path" - select IPC_SERVICE_ICMSG_ME_NOCOPY_RX - help - Enable nocopy feature for receive path of multiendpoint icmsg - ipc_service backend. This features enables functions to hold and - release rx buffer by the ipc_service API user. It also creates - performance and memory overhead so it is recommended to disable - this feature if unused by the API user. - endif # IPC_SERVICE_BACKEND_ICMSG_ME_INITIATOR || IPC_SERVICE_BACKEND_ICMSG_ME_FOLLOWER diff --git a/subsys/ipc/ipc_service/backends/ipc_icbmsg.c b/subsys/ipc/ipc_service/backends/ipc_icbmsg.c new file mode 100644 index 00000000000..cb4d91d7e8a --- /dev/null +++ b/subsys/ipc/ipc_service/backends/ipc_icbmsg.c @@ -0,0 +1,1303 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * ICBMsg backend. + * + * This is an IPC service backend that dynamically allocates buffers for data storage + * and uses ICMsg to send references to them. + * + * Shared memory organization + * -------------------------- + * + * Single channel (RX or TX) of the shared memory is divided into two areas: ICMsg area + * followed by Blocks area. ICMsg is used to send and receive short 3-byte messages. + * Blocks area is evenly divided into aligned blocks. Blocks are used to allocate + * buffers containing actual data. Data buffers can span multiple blocks. The first block + * starts with the size of the following data. + * + * +------------+-------------+ + * | ICMsg area | Blocks area | + * +------------+-------------+ + * _______/ \_________________________________________ + * / \ + * +-----------+-----------+-----------+-----------+- -+-----------+ + * | Block 0 | Block 1 | Block 2 | Block 3 | ... | Block N-1 | + * +-----------+-----------+-----------+-----------+- -+-----------+ + * _____/ \_____ + * / \ + * +------+--------------------------------+---------+ + * | size | data_buffer[size] ... | padding | + * +------+--------------------------------+---------+ + * + * The sender holds information about reserved blocks using bitarray and it is responsible + * for allocating and releasing the blocks. The receiver just tells the sender that it + * does not need a specific buffer anymore. + * + * Control messages + * ---------------- + * + * ICMsg is used to send and receive small 3-byte control messages. + * + * - Send data + * | MSG_DATA | endpoint address | block index | + * This message is used to send data buffer to specific endpoint. + * + * - Release data + * | MSG_RELEASE_DATA | 0 | block index | + * This message is a response to the "Send data" message and it is used to inform that + * specific buffer is not used anymore and can be released. Endpoint addresses does + * not matter here, so it is zero. + * + * - Bound endpoint + * | MSG_BOUND | endpoint address | block index | + * This message starts the bounding of the endpoint. The buffer contains a + * null-terminated endpoint name. + * + * - Release bound endpoint + * | MSG_RELEASE_BOUND | endpoint address | block index | + * This message is a response to the "Bound endpoint" message and it is used to inform + * that a specific buffer (starting at "block index") is not used anymore and + * a the endpoint is bounded and can now receive a data. + * + * Bounding endpoints + * ------------------ + * + * When ICMsg is bounded and user registers an endpoint on initiator side, the backend + * sends "Bound endpoint". Endpoint address is assigned by the initiator. When follower + * gets the message and user on follower side also registered the same endpoint, + * the backend calls "bound" callback and sends back "Release bound endpoint". + * The follower saves the endpoint address. The follower's endpoint is ready to send + * and receive data. When the initiator gets "Release bound endpoint" message or any + * data messages, it calls bound endpoint and it is ready to send data. + */ + +#include + +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(ipc_icbmsg, + CONFIG_IPC_SERVICE_BACKEND_ICBMSG_LOG_LEVEL); + +#define DT_DRV_COMPAT zephyr_ipc_icbmsg + +/** Allowed number of endpoints. */ +#define NUM_EPT CONFIG_IPC_SERVICE_BACKEND_ICBMSG_NUM_EP + +/** Special endpoint address indicating invalid (or empty) entry. */ +#define EPT_ADDR_INVALID 0xFF + +/** Special value for empty entry in bound message waiting table. */ +#define WAITING_BOUND_MSG_EMPTY 0xFFFF + +/** Size of the header (size field) of the block. */ +#define BLOCK_HEADER_SIZE (sizeof(struct block_header)) + +/** Flag indicating that ICMsg was bounded for this instance. */ +#define CONTROL_BOUNDED BIT(31) + +/** Registered endpoints count mask in flags. */ +#define FLAG_EPT_COUNT_MASK 0xFFFF + +enum msg_type { + MSG_DATA = 0, /* Data message. */ + MSG_RELEASE_DATA, /* Release data buffer message. */ + MSG_BOUND, /* Endpoint bounding message. */ + MSG_RELEASE_BOUND, /* Release endpoint bound message. + * This message is also indicator for the receiving side + * that the endpoint bounding was fully processed on + * the sender side. + */ +}; + +enum ept_bounding_state { + EPT_UNCONFIGURED = 0, /* Endpoint in not configured (initial state). */ + EPT_CONFIGURED, /* Endpoint is configured, waiting for work queue to + * start bounding process. + */ + EPT_BOUNDING, /* Only on initiator. Bound message was send, + * but bound callback was not called yet, because + * we are waiting for any incoming messages. + */ + EPT_READY, /* Bounding is done. Bound callback was called. */ +}; + +struct channel_config { + uint8_t *blocks_ptr; /* Address where the blocks start. */ + size_t block_size; /* Size of one block. */ + size_t block_count; /* Number of blocks. */ +}; + +struct icbmsg_config { + struct icmsg_config_t control_config; /* Configuration of the ICMsg. */ + struct channel_config rx; /* RX channel config. */ + struct channel_config tx; /* TX channel config. */ + sys_bitarray_t *tx_usage_bitmap; /* Bit is set when TX block is in use */ + sys_bitarray_t *rx_hold_bitmap; /* Bit is set, if the buffer starting at + * this block should be kept after exit + * from receive handler. + */ +}; + +struct ept_data { + const struct ipc_ept_cfg *cfg; /* Endpoint configuration. */ + atomic_t state; /* Bounding state. */ + uint8_t addr; /* Endpoint address. */ +}; + +struct backend_data { + const struct icbmsg_config *conf;/* Backend instance config. */ + struct icmsg_data_t control_data;/* ICMsg data. */ + struct k_mutex mutex; /* Mutex to protect: ICMsg send call and + * waiting_bound field. + */ + struct k_work ep_bound_work; /* Work item for bounding processing. */ + struct k_sem block_wait_sem; /* Semaphore for waiting for free blocks. */ + struct ept_data ept[NUM_EPT]; /* Array of registered endpoints. */ + uint8_t ept_map[NUM_EPT]; /* Array that maps endpoint address to index. */ + uint16_t waiting_bound[NUM_EPT];/* The bound messages waiting to be registered. */ + atomic_t flags; /* Flags on higher bits, number of registered + * endpoints on lower. + */ + bool is_initiator; /* This side has an initiator role. */ +}; + +struct block_header { + volatile size_t size; /* Size of the data field. It must be volatile, because + * when this value is read and validated for security + * reasons, compiler cannot generate code that reads + * it again after validation. + */ +}; + +struct block_content { + struct block_header header; + uint8_t data[]; /* Buffer data. */ +}; + +struct control_message { + uint8_t msg_type; /* Message type. */ + uint8_t ept_addr; /* Endpoint address or zero for MSG_RELEASE_DATA. */ + uint8_t block_index; /* Block index to send or release. */ +}; + +BUILD_ASSERT(NUM_EPT <= EPT_ADDR_INVALID, "Too many endpoints"); + +/** + * Calculate pointer to block from its index and channel configuration (RX or TX). + * No validation is performed. + */ +static struct block_content *block_from_index(const struct channel_config *ch_conf, + size_t block_index) +{ + return (struct block_content *)(ch_conf->blocks_ptr + + block_index * ch_conf->block_size); +} + +/** + * Calculate pointer to data buffer from block index and channel configuration (RX or TX). + * Also validate the index and optionally the buffer size allocated on the this block. + * + * @param[in] ch_conf The channel + * @param[in] block_index Block index + * @param[out] size Size of the buffer allocated on the block if not NULL. + * The size is also checked if it fits in the blocks area. + * If it is NULL, no size validation is performed. + * @param[in] invalidate_cache If size is not NULL, invalidates cache for entire buffer + * (all blocks). Otherwise, it is ignored. + * @return Pointer to data buffer or NULL if validation failed. + */ +static uint8_t *buffer_from_index_validate(const struct channel_config *ch_conf, + size_t block_index, size_t *size, + bool invalidate_cache) +{ + size_t allocable_size; + size_t buffer_size; + uint8_t *end_ptr; + struct block_content *block; + + if (block_index >= ch_conf->block_count) { + LOG_ERR("Block index invalid"); + return NULL; + } + + block = block_from_index(ch_conf, block_index); + + if (size != NULL) { + if (invalidate_cache) { + sys_cache_data_invd_range(block, BLOCK_HEADER_SIZE); + __sync_synchronize(); + } + allocable_size = ch_conf->block_count * ch_conf->block_size; + end_ptr = ch_conf->blocks_ptr + allocable_size; + buffer_size = block->header.size; + + if ((buffer_size > allocable_size - BLOCK_HEADER_SIZE) || + (&block->data[buffer_size] > end_ptr)) { + LOG_ERR("Block corrupted"); + return NULL; + } + + *size = buffer_size; + if (invalidate_cache) { + sys_cache_data_invd_range(block->data, buffer_size); + __sync_synchronize(); + } + } + + return block->data; +} + +/** + * Calculate block index based on data buffer pointer and validate it. + * + * @param[in] ch_conf The channel + * @param[in] buffer Pointer to data buffer + * @param[out] size Size of the allocated buffer if not NULL. + * The size is also checked if it fits in the blocks area. + * If it is NULL, no size validation is performed. + * @return Block index or negative error code + * @retval -EINVAL The buffer is not correct + */ +static int buffer_to_index_validate(const struct channel_config *ch_conf, + const uint8_t *buffer, size_t *size) +{ + size_t block_index; + uint8_t *expected; + + block_index = (buffer - ch_conf->blocks_ptr) / ch_conf->block_size; + + expected = buffer_from_index_validate(ch_conf, block_index, size, false); + + if (expected == NULL || expected != buffer) { + LOG_ERR("Pointer invalid"); + return -EINVAL; + } + + return block_index; +} + +/** + * Allocate buffer for transmission + * + * @param[in,out] size Required size of the buffer. If zero, first available block is + * allocated and all subsequent available blocks. Size actually + * allocated which is not less than requested. + * @param[out] buffer Allocated buffer data. + * @param[in] timeout Timeout. + * + * @return Positive index of the first allocated block or negative error. + * @retval -EINVAL If requested size is bigger than entire allocable space. + * @retval -ENOSPC If timeout was K_NO_WAIT and there was not enough space. + * @retval -EAGAIN If timeout occurred. + */ +static int alloc_tx_buffer(struct backend_data *dev_data, uint32_t *size, + uint8_t **buffer, k_timeout_t timeout) +{ + const struct icbmsg_config *conf = dev_data->conf; + size_t total_size = *size + BLOCK_HEADER_SIZE; + size_t num_blocks = DIV_ROUND_UP(total_size, conf->tx.block_size); + struct block_content *block; + bool sem_taken = false; + size_t tx_block_index; + size_t next_bit; + int prev_bit_val; + int r; + + do { + /* Try to allocate specified number of blocks. */ + r = sys_bitarray_alloc(conf->tx_usage_bitmap, num_blocks, + &tx_block_index); + if (r == -ENOSPC && !K_TIMEOUT_EQ(timeout, K_NO_WAIT)) { + /* Wait for releasing if there is no enough space and exit loop + * on timeout. + */ + r = k_sem_take(&dev_data->block_wait_sem, timeout); + if (r < 0) { + break; + } + sem_taken = true; + } else { + /* Exit loop if space was allocated or other error occurred. */ + break; + } + } while (true); + + /* If semaphore was taken, give it back because this thread does not + * necessary took all available space, so other thread may need it. + */ + if (sem_taken) { + k_sem_give(&dev_data->block_wait_sem); + } + + if (r < 0) { + if (r != -ENOSPC && r != -EAGAIN) { + LOG_ERR("Failed to allocate buffer, err: %d", r); + /* Only -EINVAL is allowed in this place. Any other code + * indicates something wrong with the logic. + */ + __ASSERT_NO_MSG(r == -EINVAL); + } + + if (r == -ENOSPC || r == -EINVAL) { + /* IPC service require -ENOMEM error in case of no memory. */ + r = -ENOMEM; + } + return r; + } + + /* If size is 0 try to allocate more blocks after already allocated. */ + if (*size == 0) { + prev_bit_val = 0; + for (next_bit = tx_block_index + 1; next_bit < conf->tx.block_count; + next_bit++) { + r = sys_bitarray_test_and_set_bit(conf->tx_usage_bitmap, next_bit, + &prev_bit_val); + /** Setting bit should always success. */ + __ASSERT_NO_MSG(r == 0); + if (prev_bit_val) { + break; + } + } + num_blocks = next_bit - tx_block_index; + } + + /* Get block pointer and adjust size to actually allocated space. */ + *size = conf->tx.block_size * num_blocks - BLOCK_HEADER_SIZE; + block = block_from_index(&conf->tx, tx_block_index); + block->header.size = *size; + *buffer = block->data; + return tx_block_index; +} + +/** + * Release all or part of the blocks occupied by the buffer. + * + * @param[in] tx_block_index First block index to release, no validation is performed, + * so caller is responsible for passing valid index. + * @param[in] size Size of data buffer, no validation is performed, + * so caller is responsible for passing valid size. + * @param[in] new_size If less than zero, release all blocks, otherwise reduce + * size to this value and update size in block header. + * + * @returns Positive block index where the buffer starts or negative error. + * @retval -EINVAL If invalid buffer was provided or size is greater than already + * allocated size. + */ +static int release_tx_blocks(struct backend_data *dev_data, size_t tx_block_index, + size_t size, int new_size) +{ + const struct icbmsg_config *conf = dev_data->conf; + struct block_content *block; + size_t num_blocks; + size_t total_size; + size_t new_total_size; + size_t new_num_blocks; + size_t release_index; + int r; + + /* Calculate number of blocks. */ + total_size = size + BLOCK_HEADER_SIZE; + num_blocks = DIV_ROUND_UP(total_size, conf->tx.block_size); + + if (new_size >= 0) { + /* Calculate and validate new values. */ + new_total_size = new_size + BLOCK_HEADER_SIZE; + new_num_blocks = DIV_ROUND_UP(new_total_size, conf->tx.block_size); + if (new_num_blocks > num_blocks) { + LOG_ERR("Requested %d blocks, allocated %d", new_num_blocks, + num_blocks); + return -EINVAL; + } + /* Update actual buffer size and number of blocks to release. */ + block = block_from_index(&conf->tx, tx_block_index); + block->header.size = new_size; + release_index = tx_block_index + new_num_blocks; + num_blocks = num_blocks - new_num_blocks; + } else { + /* If size is negative, release all blocks. */ + release_index = tx_block_index; + } + + if (num_blocks > 0) { + /* Free bits in the bitmap. */ + r = sys_bitarray_free(conf->tx_usage_bitmap, num_blocks, + release_index); + if (r < 0) { + LOG_ERR("Cannot free bits, err %d", r); + return r; + } + + /* Wake up all waiting threads. */ + k_sem_give(&dev_data->block_wait_sem); + } + + return tx_block_index; +} + +/** + * Release all or part of the blocks occupied by the buffer. + * + * @param[in] buffer Buffer to release. + * @param[in] new_size If less than zero, release all blocks, otherwise reduce size to + * this value and update size in block header. + * + * @returns Positive block index where the buffer starts or negative error. + * @retval -EINVAL If invalid buffer was provided or size is greater than already + * allocated size. + */ +static int release_tx_buffer(struct backend_data *dev_data, const uint8_t *buffer, + int new_size) +{ + const struct icbmsg_config *conf = dev_data->conf; + size_t size; + int tx_block_index; + + tx_block_index = buffer_to_index_validate(&conf->tx, buffer, &size); + if (tx_block_index < 0) { + return tx_block_index; + } + + return release_tx_blocks(dev_data, tx_block_index, size, new_size); +} + +/** + * Send control message over ICMsg with mutex locked. Mutex must be locked because + * ICMsg may return error on concurrent invocations even when there is enough space + * in queue. + */ +static int send_control_message(struct backend_data *dev_data, enum msg_type msg_type, + uint8_t ept_addr, uint8_t block_index) +{ + const struct icbmsg_config *conf = dev_data->conf; + const struct control_message message = { + .msg_type = (uint8_t)msg_type, + .ept_addr = ept_addr, + .block_index = block_index, + }; + int r; + + k_mutex_lock(&dev_data->mutex, K_FOREVER); + r = icmsg_send(&conf->control_config, &dev_data->control_data, &message, + sizeof(message)); + k_mutex_unlock(&dev_data->mutex); + if (r < 0) { + LOG_ERR("Cannot send over ICMsg, err %d", r); + } + return r; +} + +/** + * Release received buffer. This function will just send release control message. + * + * @param[in] buffer Buffer to release. + * @param[in] msg_type Message type: MSG_RELEASE_BOUND or MSG_RELEASE_DATA. + * @param[in] ept_addr Endpoint address or zero for MSG_RELEASE_DATA. + * + * @return zero or ICMsg send error. + */ +static int send_release(struct backend_data *dev_data, const uint8_t *buffer, + enum msg_type msg_type, uint8_t ept_addr) +{ + const struct icbmsg_config *conf = dev_data->conf; + int rx_block_index; + + rx_block_index = buffer_to_index_validate(&conf->rx, buffer, NULL); + if (rx_block_index < 0) { + return rx_block_index; + } + + return send_control_message(dev_data, msg_type, ept_addr, rx_block_index); +} + +/** + * Send data contained in specified block. It will adjust data size and flush cache + * if necessary. If sending failed, allocated blocks will be released. + * + * @param[in] msg_type Message type: MSG_BOUND or MSG_DATA. + * @param[in] ept_addr Endpoints address. + * @param[in] tx_block_index Index of first block containing data, it is not validated, + * so caller is responsible for passing only valid index. + * @param[in] size Actual size of the data, can be smaller than allocated, + * but it cannot change number of required blocks. + * + * @return O or negative error code. + */ +static int send_block(struct backend_data *dev_data, enum msg_type msg_type, + uint8_t ept_addr, size_t tx_block_index, size_t size) +{ + struct block_content *block; + int r; + + block = block_from_index(&dev_data->conf->tx, tx_block_index); + + block->header.size = size; + __sync_synchronize(); + sys_cache_data_flush_range(block, size + BLOCK_HEADER_SIZE); + + r = send_control_message(dev_data, msg_type, ept_addr, tx_block_index); + if (r < 0) { + release_tx_blocks(dev_data, tx_block_index, size, -1); + } + + return r; +} + +/** + * Find endpoint that was registered with name that matches name + * contained in the endpoint bound message received from remote. + * + * @param[in] name Endpoint name, it must be in a received block. + * + * @return Found endpoint index or -ENOENT if not found. + */ +static int find_ept_by_name(struct backend_data *dev_data, const char *name) +{ + const struct channel_config *rx_conf = &dev_data->conf->rx; + const char *buffer_end = (const char *)rx_conf->blocks_ptr + + rx_conf->block_count * rx_conf->block_size; + struct ept_data *ept; + size_t name_size; + size_t i; + + /* Requested name is in shared memory, so we have to assume that it + * can be corrupted. Extra care must be taken to avoid out of + * bounds reads. + */ + name_size = strnlen(name, buffer_end - name - 1) + 1; + + for (i = 0; i < NUM_EPT; i++) { + ept = &dev_data->ept[i]; + if (atomic_get(&ept->state) == EPT_CONFIGURED && + strncmp(ept->cfg->name, name, name_size) == 0) { + return i; + } + } + + return -ENOENT; +} + +/** + * Find registered endpoint that matches given "bound endpoint" message. When found, + * the "release bound endpoint" message is send. + * + * @param[in] rx_block_index Block containing the "bound endpoint" message. + * @param[in] ept_addr Endpoint address. + * + * @return negative error code or non-negative search result. + * @retval 0 match not found. + * @retval 1 match found and processing was successful. + */ +static int match_bound_msg(struct backend_data *dev_data, size_t rx_block_index, + uint8_t ept_addr) +{ + const struct icbmsg_config *conf = dev_data->conf; + struct block_content *block; + uint8_t *buffer; + int ept_index; + struct ept_data *ept; + int r; + bool valid_state; + + /* Find endpoint that matches requested name. */ + block = block_from_index(&conf->rx, rx_block_index); + buffer = block->data; + ept_index = find_ept_by_name(dev_data, buffer); + if (ept_index < 0) { + return 0; + } + + /* Set endpoint address and mapping. Move it to "ready" state. */ + ept = &dev_data->ept[ept_index]; + ept->addr = ept_addr; + dev_data->ept_map[ept->addr] = ept_index; + valid_state = atomic_cas(&ept->state, EPT_CONFIGURED, EPT_READY); + if (!valid_state) { + LOG_ERR("Unexpected bounding from remote on endpoint %d", ept_addr); + return -EINVAL; + } + + /* Endpoint is ready to send messages, so call bound callback. */ + if (ept->cfg->cb.bound != NULL) { + ept->cfg->cb.bound(ept->cfg->priv); + } + + /* Release the bound message and inform remote that we are ready to receive. */ + r = send_release(dev_data, buffer, MSG_RELEASE_BOUND, ept_addr); + if (r < 0) { + return r; + } + + return 1; +} + +/** + * Send bound message on specified endpoint. + * + * @param[in] ept Endpoint to use. + * + * @return O or negative error code. + */ +static int send_bound_message(struct backend_data *dev_data, struct ept_data *ept) +{ + size_t msg_len; + uint32_t alloc_size; + uint8_t *buffer; + int r; + + msg_len = strlen(ept->cfg->name) + 1; + alloc_size = msg_len; + r = alloc_tx_buffer(dev_data, &alloc_size, &buffer, K_FOREVER); + if (r >= 0) { + strcpy(buffer, ept->cfg->name); + r = send_block(dev_data, MSG_BOUND, ept->addr, r, msg_len); + } + + return r; +} + +/** + * Put endpoint bound processing into system workqueue. + */ +static void schedule_ept_bound_process(struct backend_data *dev_data) +{ + k_work_submit(&dev_data->ep_bound_work); +} + +/** + * Work handler that is responsible to start bounding when ICMsg is bound. + */ +static void ept_bound_process(struct k_work *item) +{ + struct backend_data *dev_data = CONTAINER_OF(item, struct backend_data, + ep_bound_work); + struct ept_data *ept = NULL; + size_t i; + int r = 0; + bool matching_state; + + /* Skip processing if ICMsg was not bounded yet. */ + if (!(atomic_get(&dev_data->flags) & CONTROL_BOUNDED)) { + return; + } + + if (dev_data->is_initiator) { + /* Initiator just sends bound message after endpoint was registered. */ + for (i = 0; i < NUM_EPT; i++) { + ept = &dev_data->ept[i]; + matching_state = atomic_cas(&ept->state, EPT_CONFIGURED, + EPT_BOUNDING); + if (matching_state) { + r = send_bound_message(dev_data, ept); + if (r < 0) { + atomic_set(&ept->state, EPT_UNCONFIGURED); + LOG_ERR("Failed to send bound, err %d", r); + } + } + } + } else { + /* Walk over all waiting bound messages and match to local endpoints. */ + k_mutex_lock(&dev_data->mutex, K_FOREVER); + for (i = 0; i < NUM_EPT; i++) { + if (dev_data->waiting_bound[i] != WAITING_BOUND_MSG_EMPTY) { + k_mutex_unlock(&dev_data->mutex); + r = match_bound_msg(dev_data, + dev_data->waiting_bound[i], i); + k_mutex_lock(&dev_data->mutex, K_FOREVER); + if (r != 0) { + dev_data->waiting_bound[i] = + WAITING_BOUND_MSG_EMPTY; + if (r < 0) { + LOG_ERR("Failed bound, err %d", r); + } + } + } + } + k_mutex_unlock(&dev_data->mutex); + } +} + +/** + * Get endpoint from endpoint address. Also validates if the address is correct and + * endpoint is in correct state for receiving. If bounding callback was not called yet, + * then call it. + */ +static struct ept_data *get_ept_and_rx_validate(struct backend_data *dev_data, + uint8_t ept_addr) +{ + struct ept_data *ept; + enum ept_bounding_state state; + + if (ept_addr >= NUM_EPT || dev_data->ept_map[ept_addr] >= NUM_EPT) { + LOG_ERR("Received invalid endpoint addr %d", ept_addr); + return NULL; + } + + ept = &dev_data->ept[dev_data->ept_map[ept_addr]]; + + state = atomic_get(&ept->state); + + if (state == EPT_READY) { + /* Valid state - nothing to do. */ + } else if (state == EPT_BOUNDING) { + /* Endpoint bound callback was not called yet - call it. */ + atomic_set(&ept->state, EPT_READY); + if (ept->cfg->cb.bound != NULL) { + ept->cfg->cb.bound(ept->cfg->priv); + } + } else { + LOG_ERR("Invalid state %d of receiving endpoint %d", state, ept->addr); + return NULL; + } + + return ept; +} + +/** + * Data message received. + */ +static int received_data(struct backend_data *dev_data, size_t rx_block_index, + uint8_t ept_addr) +{ + const struct icbmsg_config *conf = dev_data->conf; + uint8_t *buffer; + struct ept_data *ept; + size_t size; + int bit_val; + + /* Validate. */ + buffer = buffer_from_index_validate(&conf->rx, rx_block_index, &size, true); + ept = get_ept_and_rx_validate(dev_data, ept_addr); + if (buffer == NULL || ept == NULL) { + LOG_ERR("Received invalid block index %d or addr %d", rx_block_index, + ept_addr); + return -EINVAL; + } + + /* Clear bit. If cleared, specific block will not be hold after the callback. */ + sys_bitarray_clear_bit(conf->rx_hold_bitmap, rx_block_index); + + /* Call the endpoint callback. It can set the hold bit. */ + ept->cfg->cb.received(buffer, size, ept->cfg->priv); + + /* If the bit is still cleared, request release of the buffer. */ + sys_bitarray_test_bit(conf->rx_hold_bitmap, rx_block_index, &bit_val); + if (!bit_val) { + send_release(dev_data, buffer, MSG_RELEASE_DATA, 0); + } + + return 0; +} + +/** + * Release data message received. + */ +static int received_release_data(struct backend_data *dev_data, size_t tx_block_index) +{ + const struct icbmsg_config *conf = dev_data->conf; + uint8_t *buffer; + size_t size; + int r; + + /* Validate. */ + buffer = buffer_from_index_validate(&conf->tx, tx_block_index, &size, false); + if (buffer == NULL) { + LOG_ERR("Received invalid block index %d", tx_block_index); + return -EINVAL; + } + + /* Release. */ + r = release_tx_blocks(dev_data, tx_block_index, size, -1); + if (r < 0) { + return r; + } + + return r; +} + +/** + * Bound endpoint message received. + */ +static int received_bound(struct backend_data *dev_data, size_t rx_block_index, + uint8_t ept_addr) +{ + const struct icbmsg_config *conf = dev_data->conf; + size_t size; + uint8_t *buffer; + + /* Validate */ + buffer = buffer_from_index_validate(&conf->rx, rx_block_index, &size, true); + if (buffer == NULL) { + LOG_ERR("Received invalid block index %d", rx_block_index); + return -EINVAL; + } + + /* Put message to waiting array. */ + k_mutex_lock(&dev_data->mutex, K_FOREVER); + dev_data->waiting_bound[ept_addr] = rx_block_index; + k_mutex_unlock(&dev_data->mutex); + + /* Schedule processing the message. */ + schedule_ept_bound_process(dev_data); + + return 0; +} + +/** + * Callback called by ICMsg that handles message (data or endpoint bound) received + * from the remote. + * + * @param[in] data Message received from the ICMsg. + * @param[in] len Number of bytes of data. + * @param[in] priv Opaque pointer to device instance. + */ +static void control_received(const void *data, size_t len, void *priv) +{ + const struct device *instance = priv; + struct backend_data *dev_data = instance->data; + const struct control_message *message = (const struct control_message *)data; + struct ept_data *ept; + uint8_t ept_addr; + int r = 0; + + /* Allow messages longer than 3 bytes, e.g. for future protocol versions. */ + if (len < sizeof(struct control_message)) { + r = -EINVAL; + goto exit; + } + + ept_addr = message->ept_addr; + if (ept_addr >= NUM_EPT) { + r = -EINVAL; + goto exit; + } + + switch (message->msg_type) { + case MSG_RELEASE_DATA: + r = received_release_data(dev_data, message->block_index); + break; + case MSG_RELEASE_BOUND: + r = received_release_data(dev_data, message->block_index); + if (r >= 0) { + ept = get_ept_and_rx_validate(dev_data, ept_addr); + if (ept == NULL) { + r = -EINVAL; + } + } + break; + case MSG_BOUND: + r = received_bound(dev_data, message->block_index, ept_addr); + break; + case MSG_DATA: + r = received_data(dev_data, message->block_index, ept_addr); + break; + default: + /* Silently ignore other messages types. They can be used in future + * protocol version. + */ + break; + } + +exit: + if (r < 0) { + LOG_ERR("Failed to receive, err %d", r); + } +} + +/** + * Callback called when ICMsg is bound. + */ +static void control_bound(void *priv) +{ + const struct device *instance = priv; + struct backend_data *dev_data = instance->data; + + /* Set flag that ICMsg is bounded and now, endpoint bounding may start. */ + atomic_or(&dev_data->flags, CONTROL_BOUNDED); + schedule_ept_bound_process(dev_data); +} + +/** + * Open the backend instance callback. + */ +static int open(const struct device *instance) +{ + const struct icbmsg_config *conf = instance->config; + struct backend_data *dev_data = instance->data; + + static const struct ipc_service_cb cb = { + .bound = control_bound, + .received = control_received, + .error = NULL, + }; + + LOG_DBG("Open instance 0x%08X, initiator=%d", (uint32_t)instance, + dev_data->is_initiator ? 1 : 0); + LOG_DBG(" TX %d blocks of %d bytes at 0x%08X, max allocable %d bytes", + (uint32_t)conf->tx.block_count, + (uint32_t)conf->tx.block_size, + (uint32_t)conf->tx.blocks_ptr, + (uint32_t)(conf->tx.block_size * conf->tx.block_count - + BLOCK_HEADER_SIZE)); + LOG_DBG(" RX %d blocks of %d bytes at 0x%08X, max allocable %d bytes", + (uint32_t)conf->rx.block_count, + (uint32_t)conf->rx.block_size, + (uint32_t)conf->rx.blocks_ptr, + (uint32_t)(conf->rx.block_size * conf->rx.block_count - + BLOCK_HEADER_SIZE)); + + return icmsg_open(&conf->control_config, &dev_data->control_data, &cb, + (void *)instance); +} + +/** + * Endpoint send callback function (with copy). + */ +static int send(const struct device *instance, void *token, const void *msg, size_t len) +{ + struct backend_data *dev_data = instance->data; + struct ept_data *ept = token; + uint32_t alloc_size; + uint8_t *buffer; + int r; + + /* Allocate the buffer. */ + alloc_size = len; + r = alloc_tx_buffer(dev_data, &alloc_size, &buffer, K_NO_WAIT); + if (r < 0) { + return r; + } + + /* Copy data to allocated buffer. */ + memcpy(buffer, msg, len); + + /* Send data message. */ + return send_block(dev_data, MSG_DATA, ept->addr, r, len); +} + +/** + * Backend endpoint registration callback. + */ +static int register_ept(const struct device *instance, void **token, + const struct ipc_ept_cfg *cfg) +{ + struct backend_data *dev_data = instance->data; + struct ept_data *ept = NULL; + int ept_index; + int r = 0; + + /* Reserve new endpoint index. */ + ept_index = atomic_inc(&dev_data->flags) & FLAG_EPT_COUNT_MASK; + if (ept_index >= NUM_EPT) { + LOG_ERR("Too many endpoints"); + __ASSERT_NO_MSG(false); + return -ENOMEM; + } + + /* Add new endpoint. */ + ept = &dev_data->ept[ept_index]; + ept->cfg = cfg; + if (dev_data->is_initiator) { + ept->addr = ept_index; + dev_data->ept_map[ept->addr] = ept->addr; + } + atomic_set(&ept->state, EPT_CONFIGURED); + + /* Keep endpoint address in token. */ + *token = ept; + + /* Rest of the bounding will be done in the system workqueue. */ + schedule_ept_bound_process(dev_data); + + return r; +} + +/** + * Returns maximum TX buffer size. + */ +static int get_tx_buffer_size(const struct device *instance, void *token) +{ + const struct icbmsg_config *conf = instance->config; + + return conf->tx.block_size * conf->tx.block_count - BLOCK_HEADER_SIZE; +} + +/** + * Endpoint TX buffer allocation callback for nocopy sending. + */ +static int get_tx_buffer(const struct device *instance, void *token, void **data, + uint32_t *user_len, k_timeout_t wait) +{ + struct backend_data *dev_data = instance->data; + int r; + + r = alloc_tx_buffer(dev_data, user_len, (uint8_t **)data, wait); + if (r < 0) { + return r; + } + return 0; +} + +/** + * Endpoint TX buffer release callback for nocopy sending. + */ +static int drop_tx_buffer(const struct device *instance, void *token, const void *data) +{ + struct backend_data *dev_data = instance->data; + int r; + + r = release_tx_buffer(dev_data, data, -1); + if (r < 0) { + return r; + } + + return 0; +} + +/** + * Endpoint nocopy sending. + */ +static int send_nocopy(const struct device *instance, void *token, const void *data, + size_t len) +{ + struct backend_data *dev_data = instance->data; + struct ept_data *ept = token; + int r; + + /* Actual size may be smaller than requested, so shrink if possible. */ + r = release_tx_buffer(dev_data, data, len); + if (r < 0) { + release_tx_buffer(dev_data, data, -1); + return r; + } + + return send_block(dev_data, MSG_DATA, ept->addr, r, len); +} + +/** + * Holding RX buffer for nocopy receiving. + */ +static int hold_rx_buffer(const struct device *instance, void *token, void *data) +{ + const struct icbmsg_config *conf = instance->config; + int rx_block_index; + uint8_t *buffer = data; + + /* Calculate block index and set associated bit. */ + rx_block_index = buffer_to_index_validate(&conf->rx, buffer, NULL); + __ASSERT_NO_MSG(rx_block_index >= 0); + return sys_bitarray_set_bit(conf->rx_hold_bitmap, rx_block_index); +} + +/** + * Release RX buffer that was previously held. + */ +static int release_rx_buffer(const struct device *instance, void *token, void *data) +{ + struct backend_data *dev_data = instance->data; + + return send_release(dev_data, (uint8_t *)data, MSG_RELEASE_DATA, 0); +} + +/** + * Backend device initialization. + */ +static int backend_init(const struct device *instance) +{ + const struct icbmsg_config *conf = instance->config; + struct backend_data *dev_data = instance->data; + + dev_data->conf = conf; + dev_data->is_initiator = (conf->rx.blocks_ptr < conf->tx.blocks_ptr); + k_mutex_init(&dev_data->mutex); + k_work_init(&dev_data->ep_bound_work, ept_bound_process); + k_sem_init(&dev_data->block_wait_sem, 0, 1); + memset(&dev_data->waiting_bound, 0xFF, sizeof(dev_data->waiting_bound)); + memset(&dev_data->ept_map, EPT_ADDR_INVALID, sizeof(dev_data->ept_map)); + return 0; +} + +/** + * IPC service backend callbacks. + */ +const static struct ipc_service_backend backend_ops = { + .open_instance = open, + .close_instance = NULL, /* not implemented */ + .send = send, + .register_endpoint = register_ept, + .deregister_endpoint = NULL, /* not implemented */ + .get_tx_buffer_size = get_tx_buffer_size, + .get_tx_buffer = get_tx_buffer, + .drop_tx_buffer = drop_tx_buffer, + .send_nocopy = send_nocopy, + .hold_rx_buffer = hold_rx_buffer, + .release_rx_buffer = release_rx_buffer, +}; + +/** + * Number of bytes per each ICMsg message. It is used to calculate size of ICMsg area. + */ +#define BYTES_PER_ICMSG_MESSAGE (ROUND_UP(sizeof(struct control_message), \ + sizeof(void *)) + PBUF_PACKET_LEN_SZ) + +/** + * Maximum ICMsg overhead. It is used to calculate size of ICMsg area. + */ +#define ICMSG_BUFFER_OVERHEAD(i) \ + (PBUF_HEADER_OVERHEAD(GET_CACHE_ALIGNMENT(i)) + 2 * BYTES_PER_ICMSG_MESSAGE) + +/** + * Returns required block alignment for instance "i". + */ +#define GET_CACHE_ALIGNMENT(i) \ + MAX(sizeof(uint32_t), DT_INST_PROP_OR(i, dcache_alignment, 0)) + +/** + * Calculates minimum size required for ICMsg region for specific number of local + * and remote blocks. The minimum size ensures that ICMsg queue is will never overflow + * because it can hold data message for each local block and release message + * for each remote block. + */ +#define GET_ICMSG_MIN_SIZE(i, local_blocks, remote_blocks) \ + (ICMSG_BUFFER_OVERHEAD(i) + BYTES_PER_ICMSG_MESSAGE * \ + (local_blocks + remote_blocks)) + +/** + * Calculate aligned block size by evenly dividing remaining space after removing + * the space for ICMsg. + */ +#define GET_BLOCK_SIZE(i, total_size, local_blocks, remote_blocks) ROUND_DOWN( \ + ((total_size) - GET_ICMSG_MIN_SIZE(i, (local_blocks), (remote_blocks))) / \ + (local_blocks), GET_CACHE_ALIGNMENT(i)) + +/** + * Calculate offset where area for blocks starts which is just after the ICMsg. + */ +#define GET_BLOCKS_OFFSET(i, total_size, local_blocks, remote_blocks) \ + ((total_size) - GET_BLOCK_SIZE(i, (total_size), (local_blocks), \ + (remote_blocks)) * (local_blocks)) + +/** + * Return shared memory start address aligned to block alignment and cache line. + */ +#define GET_MEM_ADDR_INST(i, direction) \ + ROUND_UP(DT_REG_ADDR(DT_INST_PHANDLE(i, direction##_region)), \ + GET_CACHE_ALIGNMENT(i)) + +/** + * Return shared memory end address aligned to block alignment and cache line. + */ +#define GET_MEM_END_INST(i, direction) \ + ROUND_DOWN(DT_REG_ADDR(DT_INST_PHANDLE(i, direction##_region)) + \ + DT_REG_SIZE(DT_INST_PHANDLE(i, direction##_region)), \ + GET_CACHE_ALIGNMENT(i)) + +/** + * Return shared memory size aligned to block alignment and cache line. + */ +#define GET_MEM_SIZE_INST(i, direction) \ + (GET_MEM_END_INST(i, direction) - GET_MEM_ADDR_INST(i, direction)) + +/** + * Returns GET_ICMSG_SIZE, but for specific instance and direction. + * 'loc' and 'rem' parameters tells the direction. They can be either "tx, rx" + * or "rx, tx". + */ +#define GET_ICMSG_SIZE_INST(i, loc, rem) \ + GET_BLOCKS_OFFSET( \ + i, \ + GET_MEM_SIZE_INST(i, loc), \ + DT_INST_PROP(i, loc##_blocks), \ + DT_INST_PROP(i, rem##_blocks)) + +/** + * Returns address where area for blocks starts for specific instance and direction. + * 'loc' and 'rem' parameters tells the direction. They can be either "tx, rx" + * or "rx, tx". + */ +#define GET_BLOCKS_ADDR_INST(i, loc, rem) \ + GET_MEM_ADDR_INST(i, loc) + \ + GET_BLOCKS_OFFSET( \ + i, \ + GET_MEM_SIZE_INST(i, loc), \ + DT_INST_PROP(i, loc##_blocks), \ + DT_INST_PROP(i, rem##_blocks)) + +/** + * Returns block size for specific instance and direction. + * 'loc' and 'rem' parameters tells the direction. They can be either "tx, rx" + * or "rx, tx". + */ +#define GET_BLOCK_SIZE_INST(i, loc, rem) \ + GET_BLOCK_SIZE( \ + i, \ + GET_MEM_SIZE_INST(i, loc), \ + DT_INST_PROP(i, loc##_blocks), \ + DT_INST_PROP(i, rem##_blocks)) + +#define DEFINE_BACKEND_DEVICE(i) \ + SYS_BITARRAY_DEFINE_STATIC(tx_usage_bitmap_##i, DT_INST_PROP(i, tx_blocks)); \ + SYS_BITARRAY_DEFINE_STATIC(rx_hold_bitmap_##i, DT_INST_PROP(i, rx_blocks)); \ + PBUF_DEFINE(tx_icbmsg_pb_##i, \ + GET_MEM_ADDR_INST(i, tx), \ + GET_ICMSG_SIZE_INST(i, tx, rx), \ + GET_CACHE_ALIGNMENT(i)); \ + PBUF_DEFINE(rx_icbmsg_pb_##i, \ + GET_MEM_ADDR_INST(i, rx), \ + GET_ICMSG_SIZE_INST(i, rx, tx), \ + GET_CACHE_ALIGNMENT(i)); \ + static struct backend_data backend_data_##i = { \ + .control_data = { \ + .tx_pb = &tx_icbmsg_pb_##i, \ + .rx_pb = &rx_icbmsg_pb_##i, \ + } \ + }; \ + static const struct icbmsg_config backend_config_##i = \ + { \ + .control_config = { \ + .mbox_tx = MBOX_DT_CHANNEL_GET(DT_DRV_INST(i), tx), \ + .mbox_rx = MBOX_DT_CHANNEL_GET(DT_DRV_INST(i), rx), \ + }, \ + .tx = { \ + .blocks_ptr = (uint8_t *)GET_BLOCKS_ADDR_INST(i, tx, rx), \ + .block_count = DT_INST_PROP(i, tx_blocks), \ + .block_size = GET_BLOCK_SIZE_INST(i, tx, rx), \ + }, \ + .rx = { \ + .blocks_ptr = (uint8_t *)GET_BLOCKS_ADDR_INST(i, rx, tx), \ + .block_count = DT_INST_PROP(i, rx_blocks), \ + .block_size = GET_BLOCK_SIZE_INST(i, rx, tx), \ + }, \ + .tx_usage_bitmap = &tx_usage_bitmap_##i, \ + .rx_hold_bitmap = &rx_hold_bitmap_##i, \ + }; \ + BUILD_ASSERT(IS_POWER_OF_TWO(GET_CACHE_ALIGNMENT(i)), \ + "This module supports only power of two cache alignment"); \ + BUILD_ASSERT((GET_BLOCK_SIZE_INST(i, tx, rx) > GET_CACHE_ALIGNMENT(i)) && \ + (GET_BLOCK_SIZE_INST(i, tx, rx) < \ + GET_MEM_SIZE_INST(i, tx)), \ + "TX region is too small for provided number of blocks"); \ + BUILD_ASSERT((GET_BLOCK_SIZE_INST(i, rx, tx) > GET_CACHE_ALIGNMENT(i)) && \ + (GET_BLOCK_SIZE_INST(i, rx, tx) < \ + GET_MEM_SIZE_INST(i, rx)), \ + "RX region is too small for provided number of blocks"); \ + BUILD_ASSERT(DT_INST_PROP(i, rx_blocks) <= 256, "Too many RX blocks"); \ + BUILD_ASSERT(DT_INST_PROP(i, tx_blocks) <= 256, "Too many TX blocks"); \ + DEVICE_DT_INST_DEFINE(i, \ + &backend_init, \ + NULL, \ + &backend_data_##i, \ + &backend_config_##i, \ + POST_KERNEL, \ + CONFIG_IPC_SERVICE_REG_BACKEND_PRIORITY, \ + &backend_ops); + +DT_INST_FOREACH_STATUS_OKAY(DEFINE_BACKEND_DEVICE) diff --git a/subsys/ipc/ipc_service/backends/ipc_icmsg.c b/subsys/ipc/ipc_service/backends/ipc_icmsg.c index eca84f3275c..28b94b861e3 100644 --- a/subsys/ipc/ipc_service/backends/ipc_icmsg.c +++ b/subsys/ipc/ipc_service/backends/ipc_icmsg.c @@ -54,27 +54,33 @@ static int backend_init(const struct device *instance) return 0; } -#define DEFINE_BACKEND_DEVICE(i) \ - static const struct icmsg_config_t backend_config_##i = { \ - .tx_shm_size = DT_REG_SIZE(DT_INST_PHANDLE(i, tx_region)), \ - .tx_shm_addr = DT_REG_ADDR(DT_INST_PHANDLE(i, tx_region)), \ - .rx_shm_size = DT_REG_SIZE(DT_INST_PHANDLE(i, rx_region)), \ - .rx_shm_addr = DT_REG_ADDR(DT_INST_PHANDLE(i, rx_region)), \ - .mbox_tx = MBOX_DT_CHANNEL_GET(DT_DRV_INST(i), tx), \ - .mbox_rx = MBOX_DT_CHANNEL_GET(DT_DRV_INST(i), rx), \ - }; \ - \ - BUILD_ASSERT(DT_REG_SIZE(DT_INST_PHANDLE(i, tx_region)) > \ - sizeof(struct spsc_pbuf)); \ - static struct icmsg_data_t backend_data_##i; \ - \ - DEVICE_DT_INST_DEFINE(i, \ - &backend_init, \ - NULL, \ - &backend_data_##i, \ - &backend_config_##i, \ - POST_KERNEL, \ - CONFIG_IPC_SERVICE_REG_BACKEND_PRIORITY, \ +#define DEFINE_BACKEND_DEVICE(i) \ + static const struct icmsg_config_t backend_config_##i = { \ + .mbox_tx = MBOX_DT_CHANNEL_GET(DT_DRV_INST(i), tx), \ + .mbox_rx = MBOX_DT_CHANNEL_GET(DT_DRV_INST(i), rx), \ + }; \ + \ + PBUF_DEFINE(tx_pb_##i, \ + DT_REG_ADDR(DT_INST_PHANDLE(i, tx_region)), \ + DT_REG_SIZE(DT_INST_PHANDLE(i, tx_region)), \ + DT_INST_PROP_OR(i, dcache_alignment, 0)); \ + PBUF_DEFINE(rx_pb_##i, \ + DT_REG_ADDR(DT_INST_PHANDLE(i, rx_region)), \ + DT_REG_SIZE(DT_INST_PHANDLE(i, rx_region)), \ + DT_INST_PROP_OR(i, dcache_alignment, 0)); \ + \ + static struct icmsg_data_t backend_data_##i = { \ + .tx_pb = &tx_pb_##i, \ + .rx_pb = &rx_pb_##i, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(i, \ + &backend_init, \ + NULL, \ + &backend_data_##i, \ + &backend_config_##i, \ + POST_KERNEL, \ + CONFIG_IPC_SERVICE_REG_BACKEND_PRIORITY, \ &backend_ops); DT_INST_FOREACH_STATUS_OKAY(DEFINE_BACKEND_DEVICE) diff --git a/subsys/ipc/ipc_service/backends/ipc_icmsg_me_follower.c b/subsys/ipc/ipc_service/backends/ipc_icmsg_me_follower.c index df27aaedcbb..5492da0a302 100644 --- a/subsys/ipc/ipc_service/backends/ipc_icmsg_me_follower.c +++ b/subsys/ipc/ipc_service/backends/ipc_icmsg_me_follower.c @@ -260,71 +260,10 @@ static int send(const struct device *instance, void *token, user_len); } -static int get_tx_buffer(const struct device *instance, void *token, - void **data, uint32_t *user_len, k_timeout_t wait) -{ - const struct icmsg_config_t *conf = instance->config; - struct backend_data_t *dev_data = instance->data; - - return icmsg_me_get_tx_buffer(conf, &dev_data->icmsg_me_data, data, - user_len, wait); -} - -static int drop_tx_buffer(const struct device *instance, void *token, - const void *data) -{ - const struct icmsg_config_t *conf = instance->config; - struct backend_data_t *dev_data = instance->data; - - return icmsg_me_drop_tx_buffer(conf, &dev_data->icmsg_me_data, data); -} - -static int send_nocopy(const struct device *instance, void *token, - const void *data, size_t len) -{ - const struct icmsg_config_t *conf = instance->config; - struct backend_data_t *dev_data = instance->data; - icmsg_me_ept_id_t *id = token; - - if (*id == INVALID_EPT_ID) { - return -ENOTCONN; - } - - return icmsg_me_send_nocopy(conf, &dev_data->icmsg_me_data, *id, - data, len); -} - -#ifdef CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_NOCOPY_RX -int hold_rx_buffer(const struct device *instance, void *token, void *data) -{ - const struct icmsg_config_t *conf = instance->config; - struct backend_data_t *dev_data = instance->data; - - return icmsg_me_hold_rx_buffer(conf, &dev_data->icmsg_me_data, data); -} - -int release_rx_buffer(const struct device *instance, void *token, void *data) -{ - const struct icmsg_config_t *conf = instance->config; - struct backend_data_t *dev_data = instance->data; - - return icmsg_me_release_rx_buffer(conf, &dev_data->icmsg_me_data, data); -} -#endif /* CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_NOCOPY_RX */ - const static struct ipc_service_backend backend_ops = { .open_instance = open, .register_endpoint = register_ept, .send = send, - - .get_tx_buffer = get_tx_buffer, - .drop_tx_buffer = drop_tx_buffer, - .send_nocopy = send_nocopy, - -#ifdef CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_NOCOPY_RX - .hold_rx_buffer = hold_rx_buffer, - .release_rx_buffer = release_rx_buffer, -#endif }; static int backend_init(const struct device *instance) @@ -338,16 +277,28 @@ static int backend_init(const struct device *instance) } #define DEFINE_BACKEND_DEVICE(i) \ - static const struct icmsg_config_t backend_config_##i = \ - { \ - .tx_shm_size = DT_REG_SIZE(DT_INST_PHANDLE(i, tx_region)), \ - .tx_shm_addr = DT_REG_ADDR(DT_INST_PHANDLE(i, tx_region)), \ - .rx_shm_size = DT_REG_SIZE(DT_INST_PHANDLE(i, rx_region)), \ - .rx_shm_addr = DT_REG_ADDR(DT_INST_PHANDLE(i, rx_region)), \ + static const struct icmsg_config_t backend_config_##i = { \ .mbox_tx = MBOX_DT_CHANNEL_GET(DT_DRV_INST(i), tx), \ .mbox_rx = MBOX_DT_CHANNEL_GET(DT_DRV_INST(i), rx), \ }; \ - static struct backend_data_t backend_data_##i; \ + \ + PBUF_DEFINE(tx_pb_##i, \ + DT_REG_ADDR(DT_INST_PHANDLE(i, tx_region)), \ + DT_REG_SIZE(DT_INST_PHANDLE(i, tx_region)), \ + DT_INST_PROP_OR(i, dcache_alignment, 0)); \ + PBUF_DEFINE(rx_pb_##i, \ + DT_REG_ADDR(DT_INST_PHANDLE(i, rx_region)), \ + DT_REG_SIZE(DT_INST_PHANDLE(i, rx_region)), \ + DT_INST_PROP_OR(i, dcache_alignment, 0)); \ + \ + static struct backend_data_t backend_data_##i = { \ + .icmsg_me_data = { \ + .icmsg_data = { \ + .tx_pb = &tx_pb_##i, \ + .rx_pb = &rx_pb_##i, \ + } \ + } \ + }; \ \ DEVICE_DT_INST_DEFINE(i, \ &backend_init, \ diff --git a/subsys/ipc/ipc_service/backends/ipc_icmsg_me_initiator.c b/subsys/ipc/ipc_service/backends/ipc_icmsg_me_initiator.c index da6912c8388..2d537dc84a2 100644 --- a/subsys/ipc/ipc_service/backends/ipc_icmsg_me_initiator.c +++ b/subsys/ipc/ipc_service/backends/ipc_icmsg_me_initiator.c @@ -166,67 +166,10 @@ static int send(const struct device *instance, void *token, return icmsg_me_send(conf, &dev_data->icmsg_me_data, *id, msg, len); } -static int get_tx_buffer(const struct device *instance, void *token, - void **data, uint32_t *user_len, k_timeout_t wait) -{ - const struct icmsg_config_t *conf = instance->config; - struct backend_data_t *dev_data = instance->data; - - return icmsg_me_get_tx_buffer(conf, &dev_data->icmsg_me_data, data, - user_len, wait); -} - -static int drop_tx_buffer(const struct device *instance, void *token, - const void *data) -{ - const struct icmsg_config_t *conf = instance->config; - struct backend_data_t *dev_data = instance->data; - - return icmsg_me_drop_tx_buffer(conf, &dev_data->icmsg_me_data, data); -} - -static int send_nocopy(const struct device *instance, void *token, - const void *data, size_t len) -{ - const struct icmsg_config_t *conf = instance->config; - struct backend_data_t *dev_data = instance->data; - icmsg_me_ept_id_t *id = token; - - return icmsg_me_send_nocopy(conf, &dev_data->icmsg_me_data, *id, - data, len); -} - -#ifdef CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_NOCOPY_RX -int hold_rx_buffer(const struct device *instance, void *token, void *data) -{ - const struct icmsg_config_t *conf = instance->config; - struct backend_data_t *dev_data = instance->data; - - return icmsg_me_hold_rx_buffer(conf, &dev_data->icmsg_me_data, data); -} - -int release_rx_buffer(const struct device *instance, void *token, void *data) -{ - const struct icmsg_config_t *conf = instance->config; - struct backend_data_t *dev_data = instance->data; - - return icmsg_me_release_rx_buffer(conf, &dev_data->icmsg_me_data, data); -} -#endif /* CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_NOCOPY_RX */ - const static struct ipc_service_backend backend_ops = { .open_instance = open, .register_endpoint = register_ept, .send = send, - - .get_tx_buffer = get_tx_buffer, - .drop_tx_buffer = drop_tx_buffer, - .send_nocopy = send_nocopy, - -#ifdef CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_NOCOPY_RX - .hold_rx_buffer = hold_rx_buffer, - .release_rx_buffer = release_rx_buffer, -#endif }; static int backend_init(const struct device *instance) @@ -240,16 +183,28 @@ static int backend_init(const struct device *instance) } #define DEFINE_BACKEND_DEVICE(i) \ - static const struct icmsg_config_t backend_config_##i = \ - { \ - .tx_shm_size = DT_REG_SIZE(DT_INST_PHANDLE(i, tx_region)), \ - .tx_shm_addr = DT_REG_ADDR(DT_INST_PHANDLE(i, tx_region)), \ - .rx_shm_size = DT_REG_SIZE(DT_INST_PHANDLE(i, rx_region)), \ - .rx_shm_addr = DT_REG_ADDR(DT_INST_PHANDLE(i, rx_region)), \ + static const struct icmsg_config_t backend_config_##i = { \ .mbox_tx = MBOX_DT_CHANNEL_GET(DT_DRV_INST(i), tx), \ .mbox_rx = MBOX_DT_CHANNEL_GET(DT_DRV_INST(i), rx), \ }; \ - static struct backend_data_t backend_data_##i; \ + \ + PBUF_DEFINE(tx_pb_##i, \ + DT_REG_ADDR(DT_INST_PHANDLE(i, tx_region)), \ + DT_REG_SIZE(DT_INST_PHANDLE(i, tx_region)), \ + DT_INST_PROP_OR(i, dcache_alignment, 0)); \ + PBUF_DEFINE(rx_pb_##i, \ + DT_REG_ADDR(DT_INST_PHANDLE(i, rx_region)), \ + DT_REG_SIZE(DT_INST_PHANDLE(i, rx_region)), \ + DT_INST_PROP_OR(i, dcache_alignment, 0)); \ + \ + static struct backend_data_t backend_data_##i = { \ + .icmsg_me_data = { \ + .icmsg_data = { \ + .tx_pb = &tx_pb_##i, \ + .rx_pb = &rx_pb_##i, \ + } \ + } \ + }; \ \ DEVICE_DT_INST_DEFINE(i, \ &backend_init, \ diff --git a/subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings.c b/subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings.c index 5d04d029e8c..dcbff7b360c 100644 --- a/subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings.c +++ b/subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings.c @@ -774,11 +774,21 @@ static int backend_init(const struct device *instance) return 0; } -#define BACKEND_CONFIG_POPULATE(i) \ - { \ + +#if defined(CONFIG_ARCH_POSIX) +#define BACKEND_PRE(i) extern char IPC##i##_shm_buffer[]; +#define BACKEND_SHM_ADDR(i) (const uintptr_t)IPC##i##_shm_buffer +#else +#define BACKEND_PRE(i) +#define BACKEND_SHM_ADDR(i) DT_REG_ADDR(DT_INST_PHANDLE(i, memory_region)) +#endif /* defined(CONFIG_ARCH_POSIX) */ + +#define DEFINE_BACKEND_DEVICE(i) \ + BACKEND_PRE(i) \ + static struct backend_config_t backend_config_##i = { \ .role = DT_ENUM_IDX_OR(DT_DRV_INST(i), role, ROLE_HOST), \ .shm_size = DT_REG_SIZE(DT_INST_PHANDLE(i, memory_region)), \ - .shm_addr = DT_REG_ADDR(DT_INST_PHANDLE(i, memory_region)), \ + .shm_addr = BACKEND_SHM_ADDR(i), \ .mbox_tx = MBOX_DT_CHANNEL_GET(DT_DRV_INST(i), tx), \ .mbox_rx = MBOX_DT_CHANNEL_GET(DT_DRV_INST(i), rx), \ .wq_prio = COND_CODE_1(DT_INST_NODE_HAS_PROP(i, zephyr_priority), \ @@ -790,10 +800,8 @@ static int backend_init(const struct device *instance) .buffer_size = DT_INST_PROP_OR(i, zephyr_buffer_size, \ RPMSG_BUFFER_SIZE), \ .id = i, \ - } - -#define BACKEND_DEVICE_DEFINE(i) \ - static struct backend_config_t backend_config_##i = BACKEND_CONFIG_POPULATE(i); \ + }; \ + \ static struct backend_data_t backend_data_##i; \ \ DEVICE_DT_INST_DEFINE(i, \ @@ -805,23 +813,20 @@ static int backend_init(const struct device *instance) CONFIG_IPC_SERVICE_REG_BACKEND_PRIORITY, \ &backend_ops); -DT_INST_FOREACH_STATUS_OKAY(BACKEND_DEVICE_DEFINE) +DT_INST_FOREACH_STATUS_OKAY(DEFINE_BACKEND_DEVICE) -#define BACKEND_CONFIG_DEFINE(i) BACKEND_CONFIG_POPULATE(i), +#define BACKEND_CONFIG_INIT(n) &backend_config_##n, #if defined(CONFIG_IPC_SERVICE_BACKEND_RPMSG_SHMEM_RESET) static int shared_memory_prepare(void) { - const struct backend_config_t *backend_config; - const struct backend_config_t backend_configs[] = { - DT_INST_FOREACH_STATUS_OKAY(BACKEND_CONFIG_DEFINE) + static const struct backend_config_t *config[] = { + DT_INST_FOREACH_STATUS_OKAY(BACKEND_CONFIG_INIT) }; - for (backend_config = backend_configs; - backend_config < backend_configs + ARRAY_SIZE(backend_configs); - backend_config++) { - if (backend_config->role == ROLE_HOST) { - memset((void *) backend_config->shm_addr, 0, VDEV_STATUS_SIZE); + for (int i = 0; i < DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT); i++) { + if (config[i]->role == ROLE_HOST) { + memset((void *) config[i]->shm_addr, 0, VDEV_STATUS_SIZE); } } diff --git a/subsys/ipc/ipc_service/lib/CMakeLists.txt b/subsys/ipc/ipc_service/lib/CMakeLists.txt index 97148185954..a560489be72 100644 --- a/subsys/ipc/ipc_service/lib/CMakeLists.txt +++ b/subsys/ipc/ipc_service/lib/CMakeLists.txt @@ -4,3 +4,4 @@ zephyr_sources_ifdef(CONFIG_IPC_SERVICE_ICMSG icmsg.c) zephyr_sources_ifdef(CONFIG_IPC_SERVICE_ICMSG_ME icmsg_me.c) zephyr_sources_ifdef(CONFIG_IPC_SERVICE_RPMSG ipc_rpmsg.c) zephyr_sources_ifdef(CONFIG_IPC_SERVICE_STATIC_VRINGS ipc_static_vrings.c) +zephyr_sources_ifdef(CONFIG_PBUF pbuf.c) diff --git a/subsys/ipc/ipc_service/lib/Kconfig b/subsys/ipc/ipc_service/lib/Kconfig index f2b4d8ae210..0fbc82ddc13 100644 --- a/subsys/ipc/ipc_service/lib/Kconfig +++ b/subsys/ipc/ipc_service/lib/Kconfig @@ -21,8 +21,7 @@ config IPC_SERVICE_STATIC_VRINGS_MEM_ALIGNMENT menuconfig IPC_SERVICE_ICMSG bool "icmsg IPC library" - select SPSC_PBUF - select SPSC_PBUF_USE_CACHE + select PBUF help Icmsg library @@ -36,12 +35,3 @@ config IPC_SERVICE_ICMSG_ME select EVENTS help Multi-endpoint functionality for the icmsg library - -config IPC_SERVICE_ICMSG_ME_NOCOPY_RX - bool - depends on IPC_SERVICE_ICMSG_ME - select IPC_SERVICE_ICMSG_NOCOPY_RX - help - Enable nocopy feature for receiving path of the multi-endpoint - feature of the icmsg library. This features might be used by backends - based on multi-endpoint icmsg. diff --git a/subsys/ipc/ipc_service/lib/Kconfig.icmsg b/subsys/ipc/ipc_service/lib/Kconfig.icmsg index 6847844d67a..39b8c8d0c75 100644 --- a/subsys/ipc/ipc_service/lib/Kconfig.icmsg +++ b/subsys/ipc/ipc_service/lib/Kconfig.icmsg @@ -1,13 +1,6 @@ # Copyright (c) 2022 Nordic Semiconductor (ASA) # SPDX-License-Identifier: Apache-2.0 -config IPC_SERVICE_ICMSG_NOCOPY_RX - bool - depends on IPC_SERVICE_ICMSG - help - Enable nocopy feature for receiving path of the icmsg library that - might be used by backends based on icmsg. - config IPC_SERVICE_ICMSG_SHMEM_ACCESS_SYNC bool "Synchronize access to shared memory" default y @@ -27,11 +20,6 @@ config IPC_SERVICE_ICMSG_SHMEM_ACCESS_TO_MS Maximum time to wait, in milliseconds, for access to send data with backends basing on icmsg library. This time should be relatively low. -# The Icmsg library in its simplicity requires the system workqueue to execute -# at a cooperative priority. -config SYSTEM_WORKQUEUE_PRIORITY - range -256 -1 - config IPC_SERVICE_ICMSG_BOND_NOTIFY_REPEAT_TO_MS int "Bond notification timeout in miliseconds" range 1 100 @@ -39,3 +27,54 @@ config IPC_SERVICE_ICMSG_BOND_NOTIFY_REPEAT_TO_MS help Time to wait for remote bonding notification before the notification is repeated. + +config IPC_SERVICE_BACKEND_ICMSG_WQ_ENABLE + bool "Use dedicated workqueue" + default y + help + Enable dedicated workqueue thread for the ICMsg backend. + Disabling this configuration will cause the ICMsg backend to + process incoming data through the system workqueue context, and + therefore reduces the RAM footprint of the backend. + Disabling this config may result in deadlocks in certain usage + scenarios, such as when synchronous IPC is executed from the system + workqueue context. + The callbacks coming from the backend are executed from the workqueue + context. + When the option is disabled, the user must obey the restrictions + imposed by the system workqueue, such as never performing blocking + operations from within the callback. + +if IPC_SERVICE_BACKEND_ICMSG_WQ_ENABLE + +config IPC_SERVICE_BACKEND_ICMSG_WQ_STACK_SIZE + int "Size of RX work queue stack" + default 1024 + help + Size of stack used by work queue RX thread. This work queue is + created to prevent notifying service users about received data + from the system work queue. The queue is shared among instances. + +config IPC_SERVICE_BACKEND_ICMSG_WQ_PRIORITY + int "Priority of RX work queue thread" + default -1 + range -256 -1 + help + Priority of the ICMSG RX work queue thread. + The ICMSG library in its simplicity requires the workqueue to execute + at a cooperative priority. + +endif + +# The Icmsg library in its simplicity requires the system workqueue to execute +# at a cooperative priority. +config SYSTEM_WORKQUEUE_PRIORITY + range -256 -1 if !IPC_SERVICE_BACKEND_ICMSG_WQ_ENABLE + +config PBUF + bool "Packed buffer support library" + help + The packet buffer implements lightweight unidirectional packet buffer + with read/write semantics on top of a memory region shared by the + reader and writer. It optionally embeds cache and memory barrier + management to ensure correct data access. diff --git a/subsys/ipc/ipc_service/lib/icmsg.c b/subsys/ipc/ipc_service/lib/icmsg.c index b0b9ad11e5b..52e2dd10f1b 100644 --- a/subsys/ipc/ipc_service/lib/icmsg.c +++ b/subsys/ipc/ipc_service/lib/icmsg.c @@ -9,25 +9,24 @@ #include #include #include -#include +#include +#include #define BOND_NOTIFY_REPEAT_TO K_MSEC(CONFIG_IPC_SERVICE_ICMSG_BOND_NOTIFY_REPEAT_TO_MS) #define SHMEM_ACCESS_TO K_MSEC(CONFIG_IPC_SERVICE_ICMSG_SHMEM_ACCESS_TO_MS) -enum rx_buffer_state { - RX_BUFFER_STATE_RELEASED, - RX_BUFFER_STATE_RELEASING, - RX_BUFFER_STATE_HELD -}; - -enum tx_buffer_state { - TX_BUFFER_STATE_UNUSED, - TX_BUFFER_STATE_RESERVED -}; static const uint8_t magic[] = {0x45, 0x6d, 0x31, 0x6c, 0x31, 0x4b, 0x30, 0x72, 0x6e, 0x33, 0x6c, 0x69, 0x34}; +#if IS_ENABLED(CONFIG_IPC_SERVICE_BACKEND_ICMSG_WQ_ENABLE) +static K_THREAD_STACK_DEFINE(icmsg_stack, CONFIG_IPC_SERVICE_BACKEND_ICMSG_WQ_STACK_SIZE); +static struct k_work_q icmsg_workq; +static struct k_work_q *const workq = &icmsg_workq; +#else +static struct k_work_q *const workq = &k_sys_work_q; +#endif + static int mbox_deinit(const struct icmsg_config_t *conf, struct icmsg_data_t *dev_data) { @@ -62,7 +61,7 @@ static void notify_process(struct k_work *item) if (state != ICMSG_STATE_READY) { int ret; - ret = k_work_reschedule(dwork, BOND_NOTIFY_REPEAT_TO); + ret = k_work_reschedule_for_queue(workq, dwork, BOND_NOTIFY_REPEAT_TO); __ASSERT_NO_MSG(ret >= 0); (void)ret; } @@ -73,12 +72,6 @@ static bool is_endpoint_ready(struct icmsg_data_t *dev_data) return atomic_get(&dev_data->state) == ICMSG_STATE_READY; } -static bool is_tx_buffer_reserved(struct icmsg_data_t *dev_data) -{ - return atomic_get(&dev_data->tx_buffer_state) == - TX_BUFFER_STATE_RESERVED; -} - static int reserve_tx_buffer_if_unused(struct icmsg_data_t *dev_data) { #ifdef CONFIG_IPC_SERVICE_ICMSG_SHMEM_ACCESS_SYNC @@ -88,57 +81,25 @@ static int reserve_tx_buffer_if_unused(struct icmsg_data_t *dev_data) return ret; } #endif - - bool was_unused = atomic_cas(&dev_data->tx_buffer_state, - TX_BUFFER_STATE_UNUSED, TX_BUFFER_STATE_RESERVED); - - return was_unused ? 0 : -EALREADY; + return 0; } static int release_tx_buffer(struct icmsg_data_t *dev_data) { - bool was_reserved = atomic_cas(&dev_data->tx_buffer_state, - TX_BUFFER_STATE_RESERVED, TX_BUFFER_STATE_UNUSED); - - if (!was_reserved) { - return -EALREADY; - } - #ifdef CONFIG_IPC_SERVICE_ICMSG_SHMEM_ACCESS_SYNC return k_mutex_unlock(&dev_data->tx_lock); -#else - return 0; -#endif -} - -static bool is_rx_buffer_free(struct icmsg_data_t *dev_data) -{ -#ifdef CONFIG_IPC_SERVICE_ICMSG_NOCOPY_RX - return atomic_get(&dev_data->rx_buffer_state) == RX_BUFFER_STATE_RELEASED; -#else - return true; -#endif -} - -static bool is_rx_buffer_held(struct icmsg_data_t *dev_data) -{ -#ifdef CONFIG_IPC_SERVICE_ICMSG_NOCOPY_RX - return atomic_get(&dev_data->rx_buffer_state) == RX_BUFFER_STATE_HELD; -#else - return false; #endif + return 0; } -static bool is_rx_data_available(struct icmsg_data_t *dev_data) +static uint32_t data_available(struct icmsg_data_t *dev_data) { - int len = spsc_pbuf_read(dev_data->rx_ib, NULL, 0); - - return len > 0; + return pbuf_read(dev_data->rx_pb, NULL, 0); } static void submit_mbox_work(struct icmsg_data_t *dev_data) { - if (k_work_submit(&dev_data->mbox_work) < 0) { + if (k_work_submit_to_queue(workq, &dev_data->mbox_work) < 0) { /* The mbox processing work is never canceled. * The negative error code should never be seen. */ @@ -148,20 +109,13 @@ static void submit_mbox_work(struct icmsg_data_t *dev_data) static void submit_work_if_buffer_free(struct icmsg_data_t *dev_data) { - if (!is_rx_buffer_free(dev_data)) { - return; - } - submit_mbox_work(dev_data); } static void submit_work_if_buffer_free_and_data_available( struct icmsg_data_t *dev_data) { - if (!is_rx_buffer_free(dev_data)) { - return; - } - if (!is_rx_data_available(dev_data)) { + if (!data_available(dev_data)) { return; } @@ -170,46 +124,32 @@ static void submit_work_if_buffer_free_and_data_available( static void mbox_callback_process(struct k_work *item) { - char *rx_buffer; struct icmsg_data_t *dev_data = CONTAINER_OF(item, struct icmsg_data_t, mbox_work); atomic_t state = atomic_get(&dev_data->state); - uint16_t len = spsc_pbuf_claim(dev_data->rx_ib, &rx_buffer); + uint32_t len = data_available(dev_data); if (len == 0) { /* Unlikely, no data in buffer. */ return; } + uint8_t rx_buffer[len]; + + len = pbuf_read(dev_data->rx_pb, rx_buffer, len); + if (state == ICMSG_STATE_READY) { if (dev_data->cb->received) { -#if CONFIG_IPC_SERVICE_ICMSG_NOCOPY_RX - dev_data->rx_buffer = rx_buffer; - dev_data->rx_len = len; -#endif - dev_data->cb->received(rx_buffer, len, dev_data->ctx); - - /* Release Rx buffer here only in case when user did not request - * to hold it. - */ - if (!is_rx_buffer_held(dev_data)) { - spsc_pbuf_free(dev_data->rx_ib, len); - -#if CONFIG_IPC_SERVICE_ICMSG_NOCOPY_RX - dev_data->rx_buffer = NULL; - dev_data->rx_len = 0; -#endif - } } } else { __ASSERT_NO_MSG(state == ICMSG_STATE_BUSY); - bool endpoint_invalid = (len != sizeof(magic) || memcmp(magic, rx_buffer, len)); - - spsc_pbuf_free(dev_data->rx_ib, len); + /* Allow magic number longer than sizeof(magic) for future protocol version. */ + bool endpoint_invalid = (len < sizeof(magic) || + memcmp(magic, rx_buffer, sizeof(magic))); if (endpoint_invalid) { __ASSERT_NO_MSG(false); @@ -253,8 +193,6 @@ int icmsg_open(const struct icmsg_config_t *conf, struct icmsg_data_t *dev_data, const struct ipc_service_cb *cb, void *ctx) { - __ASSERT_NO_MSG(conf->tx_shm_size > sizeof(struct spsc_pbuf)); - if (!atomic_cas(&dev_data->state, ICMSG_STATE_OFF, ICMSG_STATE_BUSY)) { /* Already opened. */ return -EALREADY; @@ -268,12 +206,18 @@ int icmsg_open(const struct icmsg_config_t *conf, k_mutex_init(&dev_data->tx_lock); #endif - dev_data->tx_ib = spsc_pbuf_init((void *)conf->tx_shm_addr, - conf->tx_shm_size, - SPSC_PBUF_CACHE); - dev_data->rx_ib = (void *)conf->rx_shm_addr; + int ret = pbuf_init(dev_data->tx_pb); + + if (ret < 0) { + __ASSERT(false, "Incorrect configuration"); + return ret; + } + + /* Initialize local copies of rx_pb. */ + dev_data->rx_pb->data.wr_idx = 0; + dev_data->rx_pb->data.rd_idx = 0; - int ret = spsc_pbuf_write(dev_data->tx_ib, magic, sizeof(magic)); + ret = pbuf_write(dev_data->tx_pb, magic, sizeof(magic)); if (ret < 0) { __ASSERT_NO_MSG(false); @@ -290,7 +234,7 @@ int icmsg_open(const struct icmsg_config_t *conf, return ret; } - ret = k_work_schedule(&dev_data->notify_work, K_NO_WAIT); + ret = k_work_schedule_for_queue(workq, &dev_data->notify_work, K_NO_WAIT); if (ret < 0) { return ret; } @@ -336,7 +280,7 @@ int icmsg_send(const struct icmsg_config_t *conf, return -ENOBUFS; } - write_ret = spsc_pbuf_write(dev_data->tx_ib, msg, len); + write_ret = pbuf_write(dev_data->tx_pb, msg, len); release_ret = release_tx_buffer(dev_data); __ASSERT_NO_MSG(!release_ret); @@ -357,165 +301,21 @@ int icmsg_send(const struct icmsg_config_t *conf, return sent_bytes; } -int icmsg_get_tx_buffer(const struct icmsg_config_t *conf, - struct icmsg_data_t *dev_data, - void **data, size_t *size) -{ - int ret; - int release_ret; - uint16_t requested_size; - int allocated_len; - char *allocated_buf; - - if (*size == 0) { - /* Requested allocation of maximal size. - * Try to allocate maximal buffer size from spsc, - * potentially after wrapping marker. - */ - requested_size = SPSC_PBUF_MAX_LEN - 1; - } else { - requested_size = *size; - } - - ret = reserve_tx_buffer_if_unused(dev_data); - if (ret < 0) { - return -ENOBUFS; - } - - ret = spsc_pbuf_alloc(dev_data->tx_ib, requested_size, &allocated_buf); - if (ret < 0) { - release_ret = release_tx_buffer(dev_data); - __ASSERT_NO_MSG(!release_ret); - return ret; - } - allocated_len = ret; - - if (*size == 0) { - /* Requested allocation of maximal size. - * Pass the buffer that was allocated. - */ - *size = allocated_len; - *data = allocated_buf; - return 0; - } - - if (*size == allocated_len) { - /* Allocated buffer is of requested size. */ - *data = allocated_buf; - return 0; - } - - /* Allocated smaller buffer than requested. - * Silently stop using the allocated buffer what is allowed by SPSC API - */ - release_tx_buffer(dev_data); - *size = allocated_len; - return -ENOMEM; -} - -int icmsg_drop_tx_buffer(const struct icmsg_config_t *conf, - struct icmsg_data_t *dev_data, - const void *data) -{ - /* Silently stop using the allocated buffer what is allowed by SPSC API - */ - return release_tx_buffer(dev_data); -} +#if IS_ENABLED(CONFIG_IPC_SERVICE_BACKEND_ICMSG_WQ_ENABLE) -int icmsg_send_nocopy(const struct icmsg_config_t *conf, - struct icmsg_data_t *dev_data, - const void *msg, size_t len) +static int work_q_init(void) { - int ret; - int sent_bytes; - - if (!is_endpoint_ready(dev_data)) { - return -EBUSY; - } - - /* Empty message is not allowed */ - if (len == 0) { - return -ENODATA; - } - - if (!is_tx_buffer_reserved(dev_data)) { - return -ENXIO; - } - - spsc_pbuf_commit(dev_data->tx_ib, len); - sent_bytes = len; - - ret = release_tx_buffer(dev_data); - __ASSERT_NO_MSG(!ret); - - __ASSERT_NO_MSG(conf->mbox_tx.dev != NULL); - - ret = mbox_send(&conf->mbox_tx, NULL); - if (ret) { - return ret; - } - - return sent_bytes; -} - -#ifdef CONFIG_IPC_SERVICE_ICMSG_NOCOPY_RX -int icmsg_hold_rx_buffer(const struct icmsg_config_t *conf, - struct icmsg_data_t *dev_data, - const void *data) -{ - bool was_released; - - if (!is_endpoint_ready(dev_data)) { - return -EBUSY; - } - - if (data != dev_data->rx_buffer) { - return -EINVAL; - } - - was_released = atomic_cas(&dev_data->rx_buffer_state, - RX_BUFFER_STATE_RELEASED, RX_BUFFER_STATE_HELD); - if (!was_released) { - return -EALREADY; - } - + struct k_work_queue_config cfg = { + .name = "icmsg_workq", + }; + + k_work_queue_start(&icmsg_workq, + icmsg_stack, + K_KERNEL_STACK_SIZEOF(icmsg_stack), + CONFIG_IPC_SERVICE_BACKEND_ICMSG_WQ_PRIORITY, &cfg); return 0; } -int icmsg_release_rx_buffer(const struct icmsg_config_t *conf, - struct icmsg_data_t *dev_data, - const void *data) -{ - bool was_held; +SYS_INIT(work_q_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); - if (!is_endpoint_ready(dev_data)) { - return -EBUSY; - } - - if (data != dev_data->rx_buffer) { - return -EINVAL; - } - - /* Do not schedule new packet processing until buffer will be released. - * Protect buffer against being freed multiple times. - */ - was_held = atomic_cas(&dev_data->rx_buffer_state, - RX_BUFFER_STATE_HELD, RX_BUFFER_STATE_RELEASING); - if (!was_held) { - return -EALREADY; - } - - spsc_pbuf_free(dev_data->rx_ib, dev_data->rx_len); - -#if CONFIG_IPC_SERVICE_ICMSG_NOCOPY_RX - dev_data->rx_buffer = NULL; - dev_data->rx_len = 0; #endif - - atomic_set(&dev_data->rx_buffer_state, RX_BUFFER_STATE_RELEASED); - - submit_work_if_buffer_free_and_data_available(dev_data); - - return 0; -} -#endif /* CONFIG_IPC_SERVICE_ICMSG_NOCOPY_RX */ diff --git a/subsys/ipc/ipc_service/lib/icmsg_me.c b/subsys/ipc/ipc_service/lib/icmsg_me.c index 870dca0d483..24e3ba6514e 100644 --- a/subsys/ipc/ipc_service/lib/icmsg_me.c +++ b/subsys/ipc/ipc_service/lib/icmsg_me.c @@ -20,11 +20,6 @@ static void *icmsg_buffer_to_user_buffer(const void *icmsg_buffer) return (void *)(((char *)icmsg_buffer) + HEADER_SIZE); } -static void *user_buffer_to_icmsg_buffer(const void *user_buffer) -{ - return (void *)(((char *)user_buffer) - HEADER_SIZE); -} - static size_t icmsg_buffer_len_to_user_buffer_len(size_t icmsg_buffer_len) { return icmsg_buffer_len - HEADER_SIZE; @@ -202,116 +197,3 @@ int icmsg_me_send(const struct icmsg_config_t *conf, return sent_bytes; } - -static size_t get_buffer_length_to_pass(size_t icmsg_buffer_len) -{ - if (icmsg_buffer_len >= HEADER_SIZE) { - return icmsg_buffer_len_to_user_buffer_len(icmsg_buffer_len); - } else { - return 0; - } -} - -int icmsg_me_get_tx_buffer(const struct icmsg_config_t *conf, - struct icmsg_me_data_t *data, - void **buffer, uint32_t *user_len, k_timeout_t wait) -{ - void *icmsg_buffer; - int r; - size_t icmsg_len; - - if (!K_TIMEOUT_EQ(wait, K_NO_WAIT)) { - return -ENOTSUP; - } - - if (*user_len) { - icmsg_len = user_buffer_len_to_icmsg_buffer_len(*user_len); - } else { - icmsg_len = 0; - } - - r = icmsg_get_tx_buffer(conf, &data->icmsg_data, - &icmsg_buffer, &icmsg_len); - if (r == -ENOMEM) { - *user_len = get_buffer_length_to_pass(icmsg_len); - return -ENOMEM; - } - - if (r < 0) { - return r; - } - - /* If requested max buffer length (*len == 0) allocated buffer might be - * shorter than HEADER_SIZE. In such circumstances drop the buffer - * and return error. - */ - *user_len = get_buffer_length_to_pass(icmsg_len); - - if (!(*user_len)) { - r = icmsg_drop_tx_buffer(conf, &data->icmsg_data, icmsg_buffer); - __ASSERT_NO_MSG(!r); - return -ENOBUFS; - } - - *buffer = icmsg_buffer_to_user_buffer(icmsg_buffer); - return 0; - -} - -int icmsg_me_drop_tx_buffer(const struct icmsg_config_t *conf, - struct icmsg_me_data_t *data, - const void *buffer) -{ - const void *buffer_to_drop = user_buffer_to_icmsg_buffer(buffer); - - return icmsg_drop_tx_buffer(conf, &data->icmsg_data, buffer_to_drop); -} - -int icmsg_me_send_nocopy(const struct icmsg_config_t *conf, - struct icmsg_me_data_t *data, icmsg_me_ept_id_t id, - const void *msg, size_t len) -{ - void *buffer_to_send; - size_t len_to_send; - int r; - int sent_bytes; - - buffer_to_send = user_buffer_to_icmsg_buffer(msg); - len_to_send = user_buffer_len_to_icmsg_buffer_len(len); - - set_ept_id_in_send_buffer(buffer_to_send, id); - - r = icmsg_send_nocopy(conf, &data->icmsg_data, - buffer_to_send, len_to_send); - - if (r < 0) { - return r; - } - - __ASSERT_NO_MSG(r >= HEADER_SIZE); - if (r < HEADER_SIZE) { - return 0; - } - - sent_bytes = icmsg_buffer_len_to_user_buffer_len(r); - - return sent_bytes; -} - -#ifdef CONFIG_IPC_SERVICE_ICMSG_ME_NOCOPY_RX -int icmsg_me_hold_rx_buffer(const struct icmsg_config_t *conf, - struct icmsg_me_data_t *data, void *buffer) -{ - void *icmsg_buffer = user_buffer_to_icmsg_buffer(buffer); - - return icmsg_hold_rx_buffer(conf, &data->icmsg_data, icmsg_buffer); -} - -int icmsg_me_release_rx_buffer(const struct icmsg_config_t *conf, - struct icmsg_me_data_t *data, void *buffer) -{ - void *icmsg_buffer = user_buffer_to_icmsg_buffer(buffer); - - return icmsg_release_rx_buffer(conf, &data->icmsg_data, icmsg_buffer); -} -#endif /* CONFIG_IPC_SERVICE_ICMSG_ME_NOCOPY_RX */ diff --git a/subsys/ipc/ipc_service/lib/pbuf.c b/subsys/ipc/ipc_service/lib/pbuf.c new file mode 100644 index 00000000000..1164f814ca0 --- /dev/null +++ b/subsys/ipc/ipc_service/lib/pbuf.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +/* Helper funciton for getting numer of bytes being written to the bufer. */ +static uint32_t idx_occupied(uint32_t len, uint32_t wr_idx, uint32_t rd_idx) +{ + /* It is implicitly assumed wr_idx and rd_idx cannot differ by more then len. */ + return (rd_idx > wr_idx) ? (len - (rd_idx - wr_idx)) : (wr_idx - rd_idx); +} + +/* Helper function for wrapping the index from the begging if above buffer len. */ +static uint32_t idx_wrap(uint32_t len, uint32_t idx) +{ + return (idx >= len) ? (idx % len) : (idx); +} + +static int validate_cfg(const struct pbuf_cfg *cfg) +{ + /* Validate pointers. */ + if (!cfg || !cfg->rd_idx_loc || !cfg->wr_idx_loc || !cfg->data_loc) { + return -EINVAL; + } + + /* Validate pointer alignment. */ + if (!IS_PTR_ALIGNED_BYTES(cfg->rd_idx_loc, MAX(cfg->dcache_alignment, _PBUF_IDX_SIZE)) || + !IS_PTR_ALIGNED_BYTES(cfg->wr_idx_loc, MAX(cfg->dcache_alignment, _PBUF_IDX_SIZE)) || + !IS_PTR_ALIGNED_BYTES(cfg->data_loc, _PBUF_IDX_SIZE)) { + return -EINVAL; + } + + /* Validate len. */ + if (cfg->len < _PBUF_MIN_DATA_LEN || !IS_PTR_ALIGNED_BYTES(cfg->len, _PBUF_IDX_SIZE)) { + return -EINVAL; + } + + /* Validate pointer values. */ + if (!(cfg->rd_idx_loc < cfg->wr_idx_loc) || + !((uint8_t *)cfg->wr_idx_loc < cfg->data_loc) || + !(((uint8_t *)cfg->rd_idx_loc + MAX(_PBUF_IDX_SIZE, cfg->dcache_alignment)) == + (uint8_t *)cfg->wr_idx_loc)) { + return -EINVAL; + } + + return 0; +} + +int pbuf_init(struct pbuf *pb) +{ + if (validate_cfg(pb->cfg) != 0) { + return -EINVAL; + } + + /* Initialize local copy of indexes. */ + pb->data.wr_idx = 0; + pb->data.rd_idx = 0; + + /* Clear shared memory. */ + *(pb->cfg->wr_idx_loc) = pb->data.wr_idx; + *(pb->cfg->rd_idx_loc) = pb->data.rd_idx; + + __sync_synchronize(); + + /* Take care cache. */ + sys_cache_data_flush_range((void *)(pb->cfg->wr_idx_loc), sizeof(*(pb->cfg->wr_idx_loc))); + sys_cache_data_flush_range((void *)(pb->cfg->rd_idx_loc), sizeof(*(pb->cfg->rd_idx_loc))); + + return 0; +} + +int pbuf_write(struct pbuf *pb, const char *data, uint16_t len) +{ + if (pb == NULL || len == 0 || data == NULL) { + /* Incorrect call. */ + return -EINVAL; + } + + /* Invalidate rd_idx only, local wr_idx is used to increase buffer security. */ + sys_cache_data_invd_range((void *)(pb->cfg->rd_idx_loc), sizeof(*(pb->cfg->rd_idx_loc))); + __sync_synchronize(); + + uint8_t *const data_loc = pb->cfg->data_loc; + const uint32_t blen = pb->cfg->len; + uint32_t rd_idx = *(pb->cfg->rd_idx_loc); + uint32_t wr_idx = pb->data.wr_idx; + + /* wr_idx must always be aligned. */ + __ASSERT_NO_MSG(IS_PTR_ALIGNED_BYTES(wr_idx, _PBUF_IDX_SIZE)); + /* rd_idx shall always be aligned, but its value is received from the reader. + * Can not assert. + */ + if (!IS_PTR_ALIGNED_BYTES(rd_idx, _PBUF_IDX_SIZE)) { + return -EINVAL; + } + + uint32_t free_space = blen - idx_occupied(blen, wr_idx, rd_idx) - _PBUF_IDX_SIZE; + + /* Packet length, data + packet length size. */ + uint32_t plen = len + PBUF_PACKET_LEN_SZ; + + /* Check if packet will fit into the buffer. */ + if (free_space < plen) { + return -ENOMEM; + } + + /* Clear packet len with zeros and update. Clearing is done for possible versioning in the + * future. Writing is allowed now, because shared wr_idx value is updated at the very end. + */ + *((uint32_t *)(&data_loc[wr_idx])) = 0; + sys_put_be16(len, &data_loc[wr_idx]); + __sync_synchronize(); + sys_cache_data_flush_range(&data_loc[wr_idx], PBUF_PACKET_LEN_SZ); + + wr_idx = idx_wrap(blen, wr_idx + PBUF_PACKET_LEN_SZ); + + /* Write until end of the buffer, if data will be wrapped. */ + uint32_t tail = MIN(len, blen - wr_idx); + + memcpy(&data_loc[wr_idx], data, tail); + sys_cache_data_flush_range(&data_loc[wr_idx], tail); + + if (len > tail) { + /* Copy remaining data to buffer front. */ + memcpy(&data_loc[0], data + tail, len - tail); + sys_cache_data_flush_range(&data_loc[0], len - tail); + } + + wr_idx = idx_wrap(blen, ROUND_UP(wr_idx + len, _PBUF_IDX_SIZE)); + /* Update wr_idx. */ + pb->data.wr_idx = wr_idx; + *(pb->cfg->wr_idx_loc) = wr_idx; + __sync_synchronize(); + sys_cache_data_flush_range((void *)pb->cfg->wr_idx_loc, sizeof(*(pb->cfg->wr_idx_loc))); + + return len; +} + +int pbuf_read(struct pbuf *pb, char *buf, uint16_t len) +{ + if (pb == NULL) { + /* Incorrect call. */ + return -EINVAL; + } + + /* Invalidate wr_idx only, local rd_idx is used to increase buffer security. */ + sys_cache_data_invd_range((void *)(pb->cfg->wr_idx_loc), sizeof(*(pb->cfg->wr_idx_loc))); + __sync_synchronize(); + + uint8_t *const data_loc = pb->cfg->data_loc; + const uint32_t blen = pb->cfg->len; + uint32_t wr_idx = *(pb->cfg->wr_idx_loc); + uint32_t rd_idx = pb->data.rd_idx; + + /* rd_idx must always be aligned. */ + __ASSERT_NO_MSG(IS_PTR_ALIGNED_BYTES(rd_idx, _PBUF_IDX_SIZE)); + /* wr_idx shall always be aligned, but its value is received from the + * writer. Can not assert. + */ + if (!IS_PTR_ALIGNED_BYTES(wr_idx, _PBUF_IDX_SIZE)) { + return -EINVAL; + } + + if (rd_idx == wr_idx) { + /* Buffer is empty. */ + return 0; + } + + /* Get packet len.*/ + sys_cache_data_invd_range(&data_loc[rd_idx], PBUF_PACKET_LEN_SZ); + uint16_t plen = sys_get_be16(&data_loc[rd_idx]); + + if (!buf) { + return (int)plen; + } + + if (plen > len) { + return -ENOMEM; + } + + uint32_t occupied_space = idx_occupied(blen, wr_idx, rd_idx); + + if (occupied_space < plen + PBUF_PACKET_LEN_SZ) { + /* This should never happen. */ + return -EAGAIN; + } + + rd_idx = idx_wrap(blen, rd_idx + PBUF_PACKET_LEN_SZ); + + /* Packet will fit into provided buffer, truncate len if provided len + * is bigger than necessary. + */ + len = MIN(plen, len); + + /* Read until end of the buffer, if data are wrapped. */ + uint32_t tail = MIN(blen - rd_idx, len); + + sys_cache_data_invd_range(&data_loc[rd_idx], tail); + memcpy(buf, &data_loc[rd_idx], tail); + + if (len > tail) { + sys_cache_data_invd_range(&data_loc[0], len - tail); + memcpy(&buf[tail], &pb->cfg->data_loc[0], len - tail); + } + + /* Update rd_idx. */ + rd_idx = idx_wrap(blen, ROUND_UP(rd_idx + len, _PBUF_IDX_SIZE)); + + pb->data.rd_idx = rd_idx; + *(pb->cfg->rd_idx_loc) = rd_idx; + __sync_synchronize(); + sys_cache_data_flush_range((void *)pb->cfg->rd_idx_loc, sizeof(*(pb->cfg->rd_idx_loc))); + + return len; +} diff --git a/subsys/jwt/Kconfig b/subsys/jwt/Kconfig index dfbdbc3c889..ef4f93238fe 100644 --- a/subsys/jwt/Kconfig +++ b/subsys/jwt/Kconfig @@ -16,7 +16,7 @@ choice config JWT_SIGN_RSA bool "Use RSA signature (RS-256)" - depends on CSPRING_ENABLED + depends on CSPRNG_ENABLED select MBEDTLS config JWT_SIGN_ECDSA diff --git a/subsys/jwt/jwt.c b/subsys/jwt/jwt.c index 11745073796..0db2426195b 100644 --- a/subsys/jwt/jwt.c +++ b/subsys/jwt/jwt.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #endif #ifdef CONFIG_JWT_SIGN_ECDSA @@ -24,7 +24,7 @@ #include #include -#include +#include #endif /* diff --git a/subsys/llext/CMakeLists.txt b/subsys/llext/CMakeLists.txt new file mode 100644 index 00000000000..b129dc7f943 --- /dev/null +++ b/subsys/llext/CMakeLists.txt @@ -0,0 +1,5 @@ +if(CONFIG_LLEXT) + zephyr_library() + zephyr_library_sources(llext.c llext_export.c buf_loader.c) + zephyr_library_sources_ifdef(CONFIG_LLEXT_SHELL shell.c) +endif() diff --git a/subsys/llext/Kconfig b/subsys/llext/Kconfig new file mode 100644 index 00000000000..b1210b8f2e8 --- /dev/null +++ b/subsys/llext/Kconfig @@ -0,0 +1,40 @@ +# Copyright (c) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +menuconfig LLEXT + bool "Linkable loadable extensions" + help + Enable the linkable loadable extension subsystem + +if LLEXT + +config LLEXT_HEAP_SIZE + int "llext heap memory size in kilobytes" + default 8 + help + Heap size in kilobytes available to llext for dynamic allocation + +config LLEXT_SHELL + bool "llext shell commands" + depends on SHELL + help + Manage llext with shell commands for loading, unloading, and introspection + +config LLEXT_SHELL_MAX_SIZE + int "Maximum size of llext in bytes" + depends on LLEXT_SHELL + default 8192 + help + When loading llext with shell it is stored in a temporary buffer of this size + +config LLEXT_STORAGE_WRITABLE + bool "llext storage is writable" + help + Select if LLEXT storage is writable, i.e. if extensions are stored in + RAM and can be modified in place + +module = LLEXT +module-str = llext +source "subsys/logging/Kconfig.template.log_config" + +endif diff --git a/subsys/llext/buf_loader.c b/subsys/llext/buf_loader.c new file mode 100644 index 00000000000..d744a85e473 --- /dev/null +++ b/subsys/llext/buf_loader.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#include +#include +#include + +int llext_buf_read(struct llext_loader *l, void *buf, size_t len) +{ + struct llext_buf_loader *buf_l = CONTAINER_OF(l, struct llext_buf_loader, loader); + size_t end = MIN(buf_l->pos + len, buf_l->len); + size_t read_len = end - buf_l->pos; + + memcpy(buf, buf_l->buf + buf_l->pos, read_len); + buf_l->pos = end; + + return 0; +} + +int llext_buf_seek(struct llext_loader *l, size_t pos) +{ + struct llext_buf_loader *buf_l = CONTAINER_OF(l, struct llext_buf_loader, loader); + + buf_l->pos = MIN(pos, buf_l->len); + + return 0; +} + +void *llext_buf_peek(struct llext_loader *l, size_t pos) +{ + struct llext_buf_loader *buf_l = CONTAINER_OF(l, struct llext_buf_loader, loader); + + return (void *)(buf_l->buf + pos); +} diff --git a/subsys/llext/llext.c b/subsys/llext/llext.c new file mode 100644 index 00000000000..8dd5801bc95 --- /dev/null +++ b/subsys/llext/llext.c @@ -0,0 +1,845 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#include "zephyr/sys/__assert.h" +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(llext, CONFIG_LLEXT_LOG_LEVEL); + +#include + +K_HEAP_DEFINE(llext_heap, CONFIG_LLEXT_HEAP_SIZE * 1024); + +static const char ELF_MAGIC[] = {0x7f, 'E', 'L', 'F'}; + +static sys_slist_t _llext_list = SYS_SLIST_STATIC_INIT(&_llext_list); + +sys_slist_t *llext_list(void) +{ + return &_llext_list; +} + +struct llext *llext_by_name(const char *name) +{ + sys_slist_t *mlist = llext_list(); + sys_snode_t *node = sys_slist_peek_head(mlist); + struct llext *ext = CONTAINER_OF(node, struct llext, _llext_list); + + while (node != NULL) { + if (strncmp(ext->name, name, sizeof(ext->name)) == 0) { + return ext; + } + node = sys_slist_peek_next(node); + ext = CONTAINER_OF(node, struct llext, _llext_list); + } + + return NULL; +} + +const void * const llext_find_sym(const struct llext_symtable *sym_table, const char *sym_name) +{ + if (sym_table == NULL) { + /* Buildin symbol table */ + STRUCT_SECTION_FOREACH(llext_const_symbol, sym) { + if (strcmp(sym->name, sym_name) == 0) { + return sym->addr; + } + } + } else { + /* find symbols in module */ + for (size_t i = 0; i < sym_table->sym_cnt; i++) { + if (strcmp(sym_table->syms[i].name, sym_name) == 0) { + return sym_table->syms[i].addr; + } + } + } + + return NULL; +} + +/* + * Find all relevant string and symbol tables + */ +static int llext_find_tables(struct llext_loader *ldr) +{ + int sect_cnt, i, ret; + size_t pos; + elf_shdr_t shdr; + + ldr->sects[LLEXT_SECT_SHSTRTAB] = + ldr->sects[LLEXT_SECT_STRTAB] = + ldr->sects[LLEXT_SECT_SYMTAB] = (elf_shdr_t){0}; + + /* Find symbol and string tables */ + for (i = 0, sect_cnt = 0, pos = ldr->hdr.e_shoff; + i < ldr->hdr.e_shnum && sect_cnt < 3; + i++, pos += ldr->hdr.e_shentsize) { + ret = llext_seek(ldr, pos); + if (ret != 0) { + LOG_ERR("failed seeking to position %u\n", pos); + return ret; + } + + ret = llext_read(ldr, &shdr, sizeof(elf_shdr_t)); + if (ret != 0) { + LOG_ERR("failed reading section header at position %u\n", pos); + return ret; + } + + LOG_DBG("section %d at %x: name %d, type %d, flags %x, addr %x, size %d", + i, + ldr->hdr.e_shoff + i * ldr->hdr.e_shentsize, + shdr.sh_name, + shdr.sh_type, + shdr.sh_flags, + shdr.sh_addr, + shdr.sh_size); + + switch (shdr.sh_type) { + case SHT_SYMTAB: + case SHT_DYNSYM: + LOG_DBG("symtab at %d", i); + ldr->sects[LLEXT_SECT_SYMTAB] = shdr; + ldr->sect_map[i] = LLEXT_MEM_SYMTAB; + sect_cnt++; + break; + case SHT_STRTAB: + if (ldr->hdr.e_shstrndx == i) { + LOG_DBG("shstrtab at %d", i); + ldr->sects[LLEXT_SECT_SHSTRTAB] = shdr; + ldr->sect_map[i] = LLEXT_MEM_SHSTRTAB; + } else { + LOG_DBG("strtab at %d", i); + ldr->sects[LLEXT_SECT_STRTAB] = shdr; + ldr->sect_map[i] = LLEXT_MEM_STRTAB; + } + sect_cnt++; + break; + default: + break; + } + } + + if (!ldr->sects[LLEXT_SECT_SHSTRTAB].sh_type || + !ldr->sects[LLEXT_SECT_STRTAB].sh_type || + !ldr->sects[LLEXT_SECT_SYMTAB].sh_type) { + LOG_ERR("Some sections are missing or present multiple times!"); + return -ENOENT; + } + + return 0; +} + +static const char *llext_string(struct llext_loader *ldr, struct llext *ext, + enum llext_mem mem_idx, unsigned int idx) +{ + return (char *)ext->mem[mem_idx] + idx; +} + +/* + * Maps the section indexes and copies special section headers for easier use + */ +static int llext_map_sections(struct llext_loader *ldr, struct llext *ext) +{ + int i, ret; + size_t pos; + elf_shdr_t shdr; + const char *name; + + for (i = 0, pos = ldr->hdr.e_shoff; + i < ldr->hdr.e_shnum; + i++, pos += ldr->hdr.e_shentsize) { + ret = llext_seek(ldr, pos); + if (ret != 0) { + return ret; + } + + ret = llext_read(ldr, &shdr, sizeof(elf_shdr_t)); + if (ret != 0) { + return ret; + } + + name = llext_string(ldr, ext, LLEXT_MEM_SHSTRTAB, shdr.sh_name); + + LOG_DBG("section %d name %s", i, name); + + enum llext_section sect_idx; + enum llext_mem mem_idx; + + if (strcmp(name, ".text") == 0) { + sect_idx = LLEXT_SECT_TEXT; + mem_idx = LLEXT_MEM_TEXT; + } else if (strcmp(name, ".data") == 0) { + sect_idx = LLEXT_SECT_DATA; + mem_idx = LLEXT_MEM_DATA; + } else if (strcmp(name, ".rodata") == 0) { + sect_idx = LLEXT_SECT_RODATA; + mem_idx = LLEXT_MEM_RODATA; + } else if (strcmp(name, ".bss") == 0) { + sect_idx = LLEXT_SECT_BSS; + mem_idx = LLEXT_MEM_BSS; + } else { + LOG_DBG("Not copied section %s", name); + continue; + } + + ldr->sects[sect_idx] = shdr; + ldr->sect_map[i] = mem_idx; + } + + return 0; +} + +static enum llext_section llext_sect_from_mem(enum llext_mem m) +{ + enum llext_section s; + + switch (m) { + case LLEXT_MEM_BSS: + s = LLEXT_SECT_BSS; + break; + case LLEXT_MEM_DATA: + s = LLEXT_SECT_DATA; + break; + case LLEXT_MEM_RODATA: + s = LLEXT_SECT_RODATA; + break; + case LLEXT_MEM_TEXT: + s = LLEXT_SECT_TEXT; + break; + case LLEXT_MEM_SYMTAB: + s = LLEXT_SECT_SYMTAB; + break; + case LLEXT_MEM_STRTAB: + s = LLEXT_SECT_STRTAB; + break; + case LLEXT_MEM_SHSTRTAB: + s = LLEXT_SECT_SHSTRTAB; + break; + default: + CODE_UNREACHABLE; + } + + return s; +} + +static int llext_copy_section(struct llext_loader *ldr, struct llext *ext, + enum llext_mem mem_idx) +{ + enum llext_section sect_idx = llext_sect_from_mem(mem_idx); + int ret; + + if (!ldr->sects[sect_idx].sh_size) { + return 0; + } + + if (ldr->sects[sect_idx].sh_type != SHT_NOBITS && + IS_ENABLED(CONFIG_LLEXT_STORAGE_WRITABLE)) { + ext->mem[mem_idx] = llext_peek(ldr, ldr->sects[sect_idx].sh_offset); + if (ext->mem[mem_idx]) { + ext->mem_on_heap[mem_idx] = false; + return 0; + } + } + + ext->mem[mem_idx] = k_heap_aligned_alloc(&llext_heap, sizeof(uintptr_t), + ldr->sects[sect_idx].sh_size, + K_NO_WAIT); + if (!ext->mem[mem_idx]) { + return -ENOMEM; + } + ext->mem_size += ldr->sects[sect_idx].sh_size; + + if (ldr->sects[sect_idx].sh_type == SHT_NOBITS) { + memset(ext->mem[mem_idx], 0, ldr->sects[sect_idx].sh_size); + } else { + ret = llext_seek(ldr, ldr->sects[sect_idx].sh_offset); + if (ret != 0) { + goto err; + } + + ret = llext_read(ldr, ext->mem[mem_idx], ldr->sects[sect_idx].sh_size); + if (ret != 0) { + goto err; + } + } + + ext->mem_on_heap[mem_idx] = true; + + return 0; + +err: + k_heap_free(&llext_heap, ext->mem[mem_idx]); + return ret; +} + +static int llext_copy_strings(struct llext_loader *ldr, struct llext *ext) +{ + int ret = llext_copy_section(ldr, ext, LLEXT_MEM_SHSTRTAB); + + if (!ret) { + ret = llext_copy_section(ldr, ext, LLEXT_MEM_STRTAB); + } + + return ret; +} + +static int llext_copy_sections(struct llext_loader *ldr, struct llext *ext) +{ + for (enum llext_mem mem_idx = 0; mem_idx < LLEXT_MEM_COUNT; mem_idx++) { + /* strings have already been copied */ + if (ext->mem[mem_idx]) { + continue; + } + + int ret = llext_copy_section(ldr, ext, mem_idx); + + if (ret < 0) { + return ret; + } + } + + return 0; +} + +static int llext_count_export_syms(struct llext_loader *ldr, struct llext *ext) +{ + size_t ent_size = ldr->sects[LLEXT_SECT_SYMTAB].sh_entsize; + size_t syms_size = ldr->sects[LLEXT_SECT_SYMTAB].sh_size; + int sym_cnt = syms_size / sizeof(elf_sym_t); + const char *name; + elf_sym_t sym; + int i, ret; + size_t pos; + + LOG_DBG("symbol count %u", sym_cnt); + + for (i = 0, pos = ldr->sects[LLEXT_SECT_SYMTAB].sh_offset; + i < sym_cnt; + i++, pos += ent_size) { + if (!i) { + /* A dummy entry */ + continue; + } + + ret = llext_seek(ldr, pos); + if (ret != 0) { + return ret; + } + + ret = llext_read(ldr, &sym, ent_size); + if (ret != 0) { + return ret; + } + + uint32_t stt = ELF_ST_TYPE(sym.st_info); + uint32_t stb = ELF_ST_BIND(sym.st_info); + uint32_t sect = sym.st_shndx; + + name = llext_string(ldr, ext, LLEXT_MEM_STRTAB, sym.st_name); + + if (stt == STT_FUNC && stb == STB_GLOBAL) { + LOG_DBG("function symbol %d, name %s, type tag %d, bind %d, sect %d", + i, name, stt, stb, sect); + ext->sym_tab.sym_cnt++; + } else { + LOG_DBG("unhandled symbol %d, name %s, type tag %d, bind %d, sect %d", + i, name, stt, stb, sect); + } + } + + return 0; +} + +static int llext_allocate_symtab(struct llext_loader *ldr, struct llext *ext) +{ + struct llext_symtable *sym_tab = &ext->sym_tab; + size_t syms_size = sym_tab->sym_cnt * sizeof(struct llext_symbol); + + sym_tab->syms = k_heap_alloc(&llext_heap, syms_size, K_NO_WAIT); + if (!sym_tab->syms) { + return -ENOMEM; + } + memset(sym_tab->syms, 0, syms_size); + ext->mem_size += syms_size; + + return 0; +} + +static int llext_copy_symbols(struct llext_loader *ldr, struct llext *ext) +{ + size_t ent_size = ldr->sects[LLEXT_SECT_SYMTAB].sh_entsize; + size_t syms_size = ldr->sects[LLEXT_SECT_SYMTAB].sh_size; + int sym_cnt = syms_size / sizeof(elf_sym_t); + struct llext_symtable *sym_tab = &ext->sym_tab; + elf_sym_t sym; + int i, j, ret; + size_t pos; + + for (i = 0, pos = ldr->sects[LLEXT_SECT_SYMTAB].sh_offset, j = 0; + i < sym_cnt; + i++, pos += ent_size) { + if (!i) { + /* A dummy entry */ + continue; + } + + ret = llext_seek(ldr, pos); + if (ret != 0) { + return ret; + } + + ret = llext_read(ldr, &sym, ent_size); + if (ret != 0) { + return ret; + } + + uint32_t stt = ELF_ST_TYPE(sym.st_info); + uint32_t stb = ELF_ST_BIND(sym.st_info); + unsigned int sect = sym.st_shndx; + + if (stt == STT_FUNC && stb == STB_GLOBAL && sect != SHN_UNDEF) { + enum llext_mem mem = ldr->sect_map[sect]; + enum llext_section sect_idx = llext_sect_from_mem(mem); + const char *name = llext_string(ldr, ext, LLEXT_MEM_STRTAB, sym.st_name); + + __ASSERT(j <= sym_tab->sym_cnt, "Miscalculated symbol number %u\n", j); + + sym_tab->syms[j].name = name; + sym_tab->syms[j].addr = (void *)((uintptr_t)ext->mem[mem] + + sym.st_value - + (ldr->hdr.e_type == ET_REL ? 0 : + ldr->sects[sect_idx].sh_addr)); + LOG_DBG("function symbol %d name %s addr %p", + j, name, sym_tab->syms[j].addr); + j++; + } + } + + return 0; +} + +/* + * Find the section, containing the supplied offset and return file offset for + * that value + */ +static size_t llext_file_offset(struct llext_loader *ldr, size_t offset) +{ + unsigned int i; + + for (i = 0; i < LLEXT_SECT_COUNT; i++) + if (ldr->sects[i].sh_addr <= offset && + ldr->sects[i].sh_addr + ldr->sects[i].sh_size > offset) + return offset - ldr->sects[i].sh_addr + ldr->sects[i].sh_offset; + + return offset; +} + +static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, elf_shdr_t *shdr) +{ + unsigned int sh_cnt = shdr->sh_size / shdr->sh_entsize; + /* + * CPU address where the .text section is stored, we use .text just as a + * reference point + */ + uint8_t *text = ext->mem[LLEXT_MEM_TEXT]; + + LOG_DBG("Found %p in PLT %u size %u cnt %u text %p", + (void *)llext_string(ldr, ext, LLEXT_MEM_SHSTRTAB, shdr->sh_name), + shdr->sh_type, shdr->sh_entsize, sh_cnt, (void *)text); + + const elf_shdr_t *sym_shdr = ldr->sects + LLEXT_SECT_SYMTAB; + unsigned int sym_cnt = sym_shdr->sh_size / sym_shdr->sh_entsize; + + for (unsigned int i = 0; i < sh_cnt; i++) { + elf_rela_t rela; + + int ret = llext_seek(ldr, shdr->sh_offset + i * shdr->sh_entsize); + + if (!ret) { + ret = llext_read(ldr, &rela, sizeof(rela)); + } + + if (ret < 0) { + LOG_ERR("PLT: failed to read RELA #%u, trying to continue", i); + continue; + } + + /* Index in the symbol table */ + unsigned int j = ELF32_R_SYM(rela.r_info); + + if (j >= sym_cnt) { + LOG_WRN("PLT: idx %u >= %u", j, sym_cnt); + continue; + } + + elf_sym_t sym_tbl; + + ret = llext_seek(ldr, sym_shdr->sh_offset + j * sizeof(elf_sym_t)); + if (!ret) { + ret = llext_read(ldr, &sym_tbl, sizeof(sym_tbl)); + } + + if (ret < 0) { + LOG_ERR("PLT: failed to read symbol table #%u RELA #%u, trying to continue", + j, i); + continue; + } + + uint32_t stt = ELF_ST_TYPE(sym_tbl.st_info); + const char *name = llext_string(ldr, ext, LLEXT_MEM_STRTAB, sym_tbl.st_name); + /* + * Both r_offset and sh_addr are addresses for which the extension + * has been built. + */ + size_t got_offset = llext_file_offset(ldr, rela.r_offset) - + ldr->sects[LLEXT_SECT_TEXT].sh_offset; + + if (stt == STT_NOTYPE && sym_tbl.st_shndx == SHN_UNDEF && name[0] != '\0') { + const void *link_addr = llext_find_sym(NULL, name); + + if (!link_addr) { + LOG_WRN("PLT: cannot find idx %u name %s", j, name); + continue; + } + + if (!rela.r_offset) { + LOG_WRN("PLT: zero offset idx %u name %s", j, name); + continue; + } + + LOG_DBG("symbol %s offset %#x r-offset %#x .text offset %#x", + name, got_offset, + rela.r_offset, ldr->sects[LLEXT_SECT_TEXT].sh_offset); + + /* Resolve the symbol */ + *(const void **)(text + got_offset) = link_addr; + } + } +} + +__weak void arch_elf_relocate(elf_rela_t *rel, uintptr_t opaddr, uintptr_t opval) +{ +} + +static int llext_link(struct llext_loader *ldr, struct llext *ext) +{ + uintptr_t loc = 0; + elf_shdr_t shdr; + elf_rela_t rel; + elf_sym_t sym; + elf_word rel_cnt = 0; + const char *name; + int i, ret; + size_t pos; + + for (i = 0, pos = ldr->hdr.e_shoff; + i < ldr->hdr.e_shnum - 1; + i++, pos += ldr->hdr.e_shentsize) { + ret = llext_seek(ldr, pos); + if (ret != 0) { + return ret; + } + + ret = llext_read(ldr, &shdr, sizeof(elf_shdr_t)); + if (ret != 0) { + return ret; + } + + /* find relocation sections */ + if (shdr.sh_type != SHT_REL && shdr.sh_type != SHT_RELA) { + continue; + } + + rel_cnt = shdr.sh_size / shdr.sh_entsize; + + name = llext_string(ldr, ext, LLEXT_MEM_SHSTRTAB, shdr.sh_name); + + if (strcmp(name, ".rel.text") == 0 || + strcmp(name, ".rela.text") == 0) { + loc = (uintptr_t)ext->mem[LLEXT_MEM_TEXT]; + } else if (strcmp(name, ".rel.bss") == 0 || + strcmp(name, ".rela.bss") == 0) { + loc = (uintptr_t)ext->mem[LLEXT_MEM_BSS]; + } else if (strcmp(name, ".rel.rodata") == 0 || + strcmp(name, ".rela.rodata") == 0) { + loc = (uintptr_t)ext->mem[LLEXT_MEM_RODATA]; + } else if (strcmp(name, ".rel.data") == 0 || + strcmp(name, ".rela.data") == 0) { + loc = (uintptr_t)ext->mem[LLEXT_MEM_DATA]; + } else if (strcmp(name, ".rela.plt") == 0 || + strcmp(name, ".rela.dyn") == 0) { + llext_link_plt(ldr, ext, &shdr); + continue; + } + + LOG_DBG("relocation section %s (%d) linked to section %d has %d relocations", + name, i, shdr.sh_link, rel_cnt); + + for (int j = 0; j < rel_cnt; j++) { + /* get each relocation entry */ + ret = llext_seek(ldr, shdr.sh_offset + j * shdr.sh_entsize); + if (ret != 0) { + return ret; + } + + ret = llext_read(ldr, &rel, shdr.sh_entsize); + if (ret != 0) { + return ret; + } + + /* get corresponding symbol */ + ret = llext_seek(ldr, ldr->sects[LLEXT_SECT_SYMTAB].sh_offset + + ELF_R_SYM(rel.r_info) * sizeof(elf_sym_t)); + if (ret != 0) { + return ret; + } + + ret = llext_read(ldr, &sym, sizeof(elf_sym_t)); + if (ret != 0) { + return ret; + } + + name = llext_string(ldr, ext, LLEXT_MEM_STRTAB, sym.st_name); + + LOG_DBG("relocation %d:%d info %x (type %d, sym %d) offset %d sym_name " + "%s sym_type %d sym_bind %d sym_ndx %d", + i, j, rel.r_info, ELF_R_TYPE(rel.r_info), ELF_R_SYM(rel.r_info), + rel.r_offset, name, ELF_ST_TYPE(sym.st_info), + ELF_ST_BIND(sym.st_info), sym.st_shndx); + + uintptr_t link_addr, op_loc; + + op_loc = loc + rel.r_offset; + + /* If symbol is undefined, then we need to look it up */ + if (sym.st_shndx == SHN_UNDEF) { + link_addr = (uintptr_t)llext_find_sym(NULL, name); + + if (link_addr == 0) { + LOG_ERR("Undefined symbol with no entry in " + "symbol table %s, offset %d, link section %d", + name, rel.r_offset, shdr.sh_link); + return -ENODATA; + } + } else if (ELF_ST_TYPE(sym.st_info) == STT_SECTION) { + /* Current relocation location holds an offset into the section */ + link_addr = (uintptr_t)ext->mem[ldr->sect_map[sym.st_shndx]] + + sym.st_value + + *((uintptr_t *)op_loc); + + LOG_INF("found section symbol %s addr 0x%lx", name, link_addr); + } else { + /* Nothing to relocate here */ + continue; + } + + LOG_INF("relocating (linking) symbol %s type %d binding %d ndx %d offset " + "%d link section %d", + name, ELF_ST_TYPE(sym.st_info), ELF_ST_BIND(sym.st_info), + sym.st_shndx, rel.r_offset, shdr.sh_link); + + LOG_INF("writing relocation symbol %s type %d sym %d at addr 0x%lx " + "addr 0x%lx", + name, ELF_R_TYPE(rel.r_info), ELF_R_SYM(rel.r_info), + op_loc, link_addr); + + /* relocation */ + arch_elf_relocate(&rel, op_loc, link_addr); + } + } + + return 0; +} + +/* + * Load a valid ELF as an extension + */ +static int do_llext_load(struct llext_loader *ldr, struct llext *ext) +{ + int ret = 0; + + memset(ldr->sects, 0, sizeof(ldr->sects)); + ldr->sect_cnt = 0; + + size_t sect_map_sz = ldr->hdr.e_shnum * sizeof(ldr->sect_map[0]); + + ldr->sect_map = k_heap_alloc(&llext_heap, sect_map_sz, K_NO_WAIT); + if (!ldr->sect_map) { + LOG_ERR("Failed to allocate memory for section map, size %u", sect_map_sz); + ret = -ENOMEM; + goto out; + } + memset(ldr->sect_map, 0, sect_map_sz); + + ldr->sect_cnt = ldr->hdr.e_shnum; + ext->mem_size += sect_map_sz; + + LOG_DBG("Finding ELF tables..."); + ret = llext_find_tables(ldr); + if (ret != 0) { + LOG_ERR("Failed to find important ELF tables, ret %d", ret); + goto out; + } + + LOG_DBG("Allocate and copy strings..."); + ret = llext_copy_strings(ldr, ext); + if (ret != 0) { + LOG_ERR("Failed to copy ELF string sections, ret %d", ret); + goto out; + } + + LOG_DBG("Mapping ELF sections..."); + ret = llext_map_sections(ldr, ext); + if (ret != 0) { + LOG_ERR("Failed to map ELF sections, ret %d", ret); + goto out; + } + + LOG_DBG("Allocate and copy sections..."); + ret = llext_copy_sections(ldr, ext); + if (ret != 0) { + LOG_ERR("Failed to copy ELF sections, ret %d", ret); + goto out; + } + + LOG_DBG("Counting exported symbols..."); + ret = llext_count_export_syms(ldr, ext); + if (ret != 0) { + LOG_ERR("Failed to count exported ELF symbols, ret %d", ret); + goto out; + } + + LOG_DBG("Allocating memory for symbol table..."); + ret = llext_allocate_symtab(ldr, ext); + if (ret != 0) { + LOG_ERR("Failed to allocate extension symbol table, ret %d", ret); + goto out; + } + + LOG_DBG("Copying symbols..."); + ret = llext_copy_symbols(ldr, ext); + if (ret != 0) { + LOG_ERR("Failed to copy symbols, ret %d", ret); + goto out; + } + + LOG_DBG("Linking ELF..."); + ret = llext_link(ldr, ext); + if (ret != 0) { + LOG_ERR("Failed to link, ret %d", ret); + goto out; + } + +out: + k_heap_free(&llext_heap, ldr->sect_map); + + if (ret != 0) { + LOG_DBG("Failed to load extension, freeing memory..."); + for (enum llext_mem mem_idx = 0; mem_idx < LLEXT_MEM_COUNT; mem_idx++) { + if (ext->mem_on_heap[mem_idx]) { + k_heap_free(&llext_heap, ext->mem[mem_idx]); + } + } + k_heap_free(&llext_heap, ext->sym_tab.syms); + } else { + LOG_DBG("loaded module, .text at %p, .rodata at %p", ext->mem[LLEXT_MEM_TEXT], + ext->mem[LLEXT_MEM_RODATA]); + } + + return ret; +} + +int llext_load(struct llext_loader *ldr, const char *name, struct llext **ext) +{ + int ret; + elf_ehdr_t ehdr; + + ret = llext_seek(ldr, 0); + if (ret != 0) { + LOG_ERR("Failed to seek for ELF header"); + return ret; + } + + ret = llext_read(ldr, &ehdr, sizeof(ehdr)); + if (ret != 0) { + LOG_ERR("Failed to read ELF header"); + return ret; + } + + /* check whether this is an valid elf file */ + if (memcmp(ehdr.e_ident, ELF_MAGIC, sizeof(ELF_MAGIC)) != 0) { + LOG_HEXDUMP_ERR(ehdr.e_ident, 16, "Invalid ELF, magic does not match"); + return -EINVAL; + } + + switch (ehdr.e_type) { + case ET_REL: + case ET_DYN: + LOG_DBG("Loading relocatable or shared elf"); + *ext = k_heap_alloc(&llext_heap, sizeof(struct llext), K_NO_WAIT); + if (*ext == NULL) { + LOG_ERR("Not enough memory for extension metadata"); + return -ENOMEM; + } + memset(*ext, 0, sizeof(struct llext)); + + ldr->hdr = ehdr; + ret = do_llext_load(ldr, *ext); + break; + default: + LOG_ERR("Unsupported elf file type %x", ehdr.e_type); + *ext = NULL; + return -EINVAL; + } + + if (ret == 0) { + strncpy((*ext)->name, name, sizeof((*ext)->name)); + (*ext)->name[sizeof((*ext)->name) - 1] = '\0'; + sys_slist_append(&_llext_list, &(*ext)->_llext_list); + LOG_INF("Loaded extension %s", (*ext)->name); + } + + return ret; +} + +void llext_unload(struct llext *ext) +{ + __ASSERT(ext, "Expected non-null extension"); + + sys_slist_find_and_remove(&_llext_list, &ext->_llext_list); + + for (int i = 0; i < LLEXT_MEM_COUNT; i++) { + if (ext->mem_on_heap[i]) { + LOG_DBG("freeing memory region %d", i); + k_heap_free(&llext_heap, ext->mem[i]); + ext->mem[i] = NULL; + } + } + + k_heap_free(&llext_heap, ext->sym_tab.syms); + + k_heap_free(&llext_heap, ext); +} + +int llext_call_fn(struct llext *ext, const char *sym_name) +{ + void (*fn)(void); + + fn = llext_find_sym(&ext->sym_tab, sym_name); + if (fn == NULL) { + return -EINVAL; + } + fn(); + + return 0; +} diff --git a/subsys/llext/llext_export.c b/subsys/llext/llext_export.c new file mode 100644 index 00000000000..0ec7fe4ac0a --- /dev/null +++ b/subsys/llext/llext_export.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +EXPORT_SYMBOL(strcpy); +EXPORT_SYMBOL(strncpy); +EXPORT_SYMBOL(strlen); +EXPORT_SYMBOL(strcmp); +EXPORT_SYMBOL(strncmp); +EXPORT_SYMBOL(memcmp); +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memset); diff --git a/subsys/llext/shell.c b/subsys/llext/shell.c new file mode 100644 index 00000000000..b9a4121acc6 --- /dev/null +++ b/subsys/llext/shell.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(llext_shell, CONFIG_LLEXT_LOG_LEVEL); + +#define LLEXT_LIST_HELP "List loaded extensions and their size in memory" + +#define LLEXT_LOAD_HEX_HELP \ + "Load an elf file encoded in hex directly from the shell input. Syntax:\n" \ + " " + +#define LLEXT_UNLOAD_HELP \ + "Unload an extension by name. Syntax:\n" \ + "" + +#define LLEXT_LIST_SYMBOLS_HELP \ + "List extension symbols. Syntax:\n" \ + "" + +#define LLEXT_CALL_FN_HELP \ + "Call extension function with prototype void fn(void). Syntax:\n" \ + " " + +static int cmd_llext_list_symbols(const struct shell *sh, size_t argc, char *argv[]) +{ + struct llext *m = llext_by_name(argv[1]); + + if (m == NULL) { + shell_print(sh, "No such llext %s", argv[1]); + return -EINVAL; + } + + shell_print(sh, "Extension: %s symbols", m->name); + shell_print(sh, "| Symbol | Address |"); + for (elf_word i = 0; i < m->sym_tab.sym_cnt; i++) { + shell_print(sh, "| %16s | %p |", m->sym_tab.syms[i].name, + m->sym_tab.syms[i].addr); + } + + return 0; +} + +static void llext_name_get(size_t idx, struct shell_static_entry *entry) +{ + sys_slist_t *ext_list = llext_list(); + sys_snode_t *node = sys_slist_peek_head(ext_list); + + entry->syntax = NULL; + + for (int i = 0; i < idx; i++) { + node = sys_slist_peek_next(node); + + if (node == NULL) { + goto out; + } + } + + struct llext *ext = CONTAINER_OF(node, struct llext, _llext_list); + + entry->syntax = ext->name; +out: + entry->syntax = NULL; + entry->help = NULL; + entry->subcmd = NULL; + +} + +SHELL_DYNAMIC_CMD_CREATE(msub_llext_name, llext_name_get); + +static int cmd_llext_list(const struct shell *sh, size_t argc, char *argv[]) +{ + sys_snode_t *node; + struct llext *ext; + + shell_print(sh, "| Name | Size |"); + SYS_SLIST_FOR_EACH_NODE(llext_list(), node) { + ext = CONTAINER_OF(node, struct llext, _llext_list); + shell_print(sh, "| %16s | %12d |", ext->name, ext->mem_size); + } + + return 0; +} + +static uint8_t llext_buf[CONFIG_LLEXT_SHELL_MAX_SIZE]; + +static int cmd_llext_load_hex(const struct shell *sh, size_t argc, char *argv[]) +{ + char name[16]; + size_t hex_len = strnlen(argv[2], CONFIG_LLEXT_SHELL_MAX_SIZE*2+1); + size_t bin_len = hex_len/2; + + if (bin_len > CONFIG_LLEXT_SHELL_MAX_SIZE) { + shell_print(sh, "Extension %d bytes too large to load, max %d bytes\n", hex_len/2, + CONFIG_LLEXT_SHELL_MAX_SIZE); + return -ENOMEM; + } + + strncpy(name, argv[1], sizeof(name)); + + size_t llext_buf_len = hex2bin(argv[2], hex_len, llext_buf, CONFIG_LLEXT_SHELL_MAX_SIZE); + struct llext_buf_loader buf_loader = LLEXT_BUF_LOADER(llext_buf, llext_buf_len); + struct llext_loader *ldr = &buf_loader.loader; + + LOG_DBG("hex2bin hex len %d, llext buf sz %d, read %d", + hex_len, CONFIG_LLEXT_SHELL_MAX_SIZE, llext_buf_len); + LOG_HEXDUMP_DBG(llext_buf, 4, "4 byte MAGIC"); + + struct llext *ext; + int res = llext_load(ldr, name, &ext); + + if (res == 0) { + shell_print(sh, "Successfully loaded extension %s, addr %p\n", ext->name, ext); + } else { + shell_print(sh, "Failed to load extension %s, return code %d\n", name, res); + } + + return 0; +} + +static int cmd_llext_unload(const struct shell *sh, size_t argc, char *argv[]) +{ + struct llext *ext = llext_by_name(argv[1]); + + if (ext == NULL) { + shell_print(sh, "No such extension %s", argv[1]); + return -EINVAL; + } + + llext_unload(ext); + shell_print(sh, "Unloaded extension %s\n", argv[1]); + + return 0; +} + +static int cmd_llext_call_fn(const struct shell *sh, size_t argc, char *argv[]) +{ + struct llext *ext = llext_by_name(argv[1]); + + if (ext == NULL) { + shell_print(sh, "No such extension %s", argv[1]); + return -EINVAL; + } + + llext_call_fn(ext, argv[2]); + + return 0; +} + + +/* clang-format off */ +SHELL_STATIC_SUBCMD_SET_CREATE(sub_llext, + SHELL_CMD(list, NULL, LLEXT_LIST_HELP, cmd_llext_list), + SHELL_CMD_ARG(load_hex, NULL, LLEXT_LOAD_HEX_HELP, cmd_llext_load_hex, + 3, 0), + SHELL_CMD_ARG(unload, &msub_llext_name, LLEXT_UNLOAD_HELP, cmd_llext_unload, 2, 0), + SHELL_CMD_ARG(list_symbols, &msub_llext_name, LLEXT_LIST_SYMBOLS_HELP, + cmd_llext_list_symbols, 2, 0), + SHELL_CMD_ARG(call_fn, &msub_llext_name, LLEXT_CALL_FN_HELP, + cmd_llext_call_fn, 3, 0), + + SHELL_SUBCMD_SET_END + ); +/* clang-format on */ + +SHELL_CMD_REGISTER(llext, &sub_llext, "Loadable extension commands", NULL); diff --git a/subsys/logging/Kconfig.frontends b/subsys/logging/Kconfig.frontends index 1dffe73de59..7a725421fb9 100644 --- a/subsys/logging/Kconfig.frontends +++ b/subsys/logging/Kconfig.frontends @@ -8,6 +8,8 @@ config LOG_FRONTEND_DICT_UART select LOG_DICTIONARY_DB select MPSC_PBUF depends on UART_ASYNC_API || UART_INTERRUPT_DRIVEN + imply LOG_FMT_SECTION + imply LOG_FMT_SECTION_STRIP help Frontend sends data in binary dictionary mode. diff --git a/subsys/logging/Kconfig.misc b/subsys/logging/Kconfig.misc index d425f9b628b..ce34bdae0a0 100644 --- a/subsys/logging/Kconfig.misc +++ b/subsys/logging/Kconfig.misc @@ -15,7 +15,6 @@ config LOG_CMDS bool "Shell commands" depends on SHELL depends on !LOG_FRONTEND_ONLY && !LOG_MODE_MINIMAL - default y if SHELL config LOG_TEST_CLEAR_MESSAGE_SPACE bool "Clear message after allocation" @@ -33,6 +32,16 @@ config LOG_USE_VLA supported. Note that VLA are used for arrays which size is resolved at compile time so at runtime arrays have fixed size. +config LOG_SIMPLE_MSG_OPTIMIZE + bool "Optimize simple messages for size" + depends on !64BIT && !CBPRINTF_PACKAGE_HEADER_STORE_CREATION_FLAGS + default y + help + Dedicated code for handling simple log messages (0-2 32 bit word arguments). + Approximately, 70%-80% log messages in the application fit into that category. + Depending on the architecture code size reduction is from 0-40% (highest seen on + RISCV32) and execution time also up to 40%. + config LOG_ALWAYS_RUNTIME bool "Always use runtime message creation (v2)" default y if NO_OPTIMIZATIONS @@ -55,6 +64,13 @@ config LOG_FMT_SECTION removing strings from final binary and should be used for dictionary logging. +config LOG_FMT_SECTION_STRIP + bool "Strip log strings from binary" + depends on !LOG_OUTPUT + depends on LOG_FMT_SECTION + depends on LINKER_DEVNULL_SUPPORT + imply LINKER_DEVNULL_MEMORY + config LOG_USE_TAGGED_ARGUMENTS bool "Using tagged arguments for packaging" depends on !PICOLIBC diff --git a/subsys/logging/Kconfig.mode b/subsys/logging/Kconfig.mode index 93758b81fb6..61c304ad0b5 100644 --- a/subsys/logging/Kconfig.mode +++ b/subsys/logging/Kconfig.mode @@ -53,6 +53,12 @@ config LOG_FRONTEND_ONLY Option indicates that there are no backends intended to be used. Code asserts if any backend is enabled. +config LOG_FRONTEND_OPT_API + bool "Frontend optimized API" + help + When enabled, frontend implements functions which are optimized versions + used for the most common log messages. + config LOG_CUSTOM_HEADER bool "Include Custom Log Header" help diff --git a/subsys/logging/Kconfig.processing b/subsys/logging/Kconfig.processing index 107dc5033ff..bc553aa239c 100644 --- a/subsys/logging/Kconfig.processing +++ b/subsys/logging/Kconfig.processing @@ -7,9 +7,11 @@ if !LOG_MODE_MINIMAL config LOG_PRINTK bool "Process printk messages" - default y if PRINTK && (!ZTEST || ZTEST_NEW_API) + depends on !USERSPACE + default y if PRINTK help - LOG_PRINTK messages are formatted in place and logged unconditionally. + If enabled, printk messages are redirected to the logging subsystem. + The messages are formatted in place and logged unconditionally. if LOG_MODE_DEFERRED && !LOG_FRONTEND_ONLY diff --git a/subsys/logging/backends/Kconfig.swo b/subsys/logging/backends/Kconfig.swo index 8dcbf3f0285..adfc89b274e 100644 --- a/subsys/logging/backends/Kconfig.swo +++ b/subsys/logging/backends/Kconfig.swo @@ -9,6 +9,16 @@ config LOG_BACKEND_SWO When enabled, backend will use SWO for logging. if LOG_BACKEND_SWO + +config LOG_BACKEND_SWO_REF_FREQ_HZ + int "SWO reference clock frequency" + default $(dt_node_int_prop_int,$(dt_nodelabel_path,itm),swo-ref-frequency) if $(dt_nodelabel_enabled,itm) + default $(dt_node_int_prop_int,/cpus/cpu@0,clock-frequency) if $(dt_node_has_prop,/cpus/cpu@0,clock-frequency) + default 0 + help + Set SWO reference frequency. In most cases it is equal to CPU + frequency. + config LOG_BACKEND_SWO_FREQ_HZ int "Set SWO output frequency" default 0 diff --git a/subsys/logging/backends/log_backend_net.c b/subsys/logging/backends/log_backend_net.c index 7b99a05856f..0681e5901c7 100644 --- a/subsys/logging/backends/log_backend_net.c +++ b/subsys/logging/backends/log_backend_net.c @@ -10,6 +10,7 @@ LOG_MODULE_REGISTER(log_backend_net, CONFIG_LOG_DEFAULT_LEVEL); #include #include #include +#include #include #include @@ -196,19 +197,54 @@ static int format_set(const struct log_backend *const backend, uint32_t log_type return 0; } +bool log_backend_net_set_addr(const char *addr) +{ + bool ret = false; + + if (net_init_done) { + /* Release context so it can be recreated with the specified ip address + * next time process() is called + */ + int released = net_context_put(log_output_net.control_block->ctx); + + if (released < 0) { + LOG_ERR("Cannot release context (%d)", ret); + ret = false; + } else { + /* The context is successfully released so we flag it + * to be recreated with the new ip address + */ + net_init_done = false; + ret = true; + } + + if (!ret) { + return ret; + } + } + + net_sin(&server_addr)->sin_port = htons(514); + + ret = net_ipaddr_parse(addr, strlen(addr), &server_addr); + + if (!ret) { + LOG_ERR("Cannot parse syslog server address"); + return ret; + } + + return ret; +} + static void init_net(struct log_backend const *const backend) { ARG_UNUSED(backend); - int ret; - net_sin(&server_addr)->sin_port = htons(514); + if (strlen(CONFIG_LOG_BACKEND_NET_SERVER) != 0) { + bool ret = log_backend_net_set_addr(CONFIG_LOG_BACKEND_NET_SERVER); - ret = net_ipaddr_parse(CONFIG_LOG_BACKEND_NET_SERVER, - sizeof(CONFIG_LOG_BACKEND_NET_SERVER) - 1, - &server_addr); - if (ret == 0) { - LOG_ERR("Cannot configure syslog server address"); - return; + if (!ret) { + return; + } } log_backend_deactivate(log_backend_net_get()); diff --git a/subsys/logging/backends/log_backend_swo.c b/subsys/logging/backends/log_backend_swo.c index 7c4c89d8b99..2ef29a3e0c6 100644 --- a/subsys/logging/backends/log_backend_swo.c +++ b/subsys/logging/backends/log_backend_swo.c @@ -42,17 +42,12 @@ PINCTRL_DT_DEFINE(DT_NODELABEL(itm)); #define SWO_FREQ_DIV 1 #else -/* Set reference frequency which can be custom or cpu frequency. */ -#if DT_NODE_HAS_PROP(DT_NODELABEL(itm), swo_ref_frequency) -#define SWO_REF_FREQ DT_PROP(DT_NODELABEL(itm), swo_ref_frequency) -#elif DT_NODE_HAS_PROP(DT_PATH(cpus, cpu_0), clock_frequency) -#define SWO_REF_FREQ DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency) -#else -#error "Missing DT 'clock-frequency' property on cpu@0 node" +#if CONFIG_LOG_BACKEND_SWO_REF_FREQ_HZ == 0 +#error "SWO reference frequency is not configured" #endif #define SWO_FREQ_DIV \ - ((SWO_REF_FREQ + (CONFIG_LOG_BACKEND_SWO_FREQ_HZ / 2)) / \ + ((CONFIG_LOG_BACKEND_SWO_REF_FREQ_HZ + (CONFIG_LOG_BACKEND_SWO_FREQ_HZ / 2)) / \ CONFIG_LOG_BACKEND_SWO_FREQ_HZ) #if SWO_FREQ_DIV > 0xFFFF diff --git a/subsys/logging/backends/log_backend_uart.c b/subsys/logging/backends/log_backend_uart.c index 5bfcbdd89b1..46fa12b92e1 100644 --- a/subsys/logging/backends/log_backend_uart.c +++ b/subsys/logging/backends/log_backend_uart.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 Nordic Semiconductor ASA + * Copyright (c) 2023 Meta * * SPDX-License-Identifier: Apache-2.0 */ @@ -18,32 +19,49 @@ #include LOG_MODULE_REGISTER(log_uart); +struct lbu_data { + struct k_sem sem; + uint32_t log_format_current; + volatile bool in_panic; + bool use_async; +}; + +struct lbu_cb_ctx { + const struct log_output *output; +#if DT_HAS_CHOSEN(zephyr_log_uart) + const struct device *uart_dev; +#endif + struct lbu_data *data; +}; + +#define LBU_UART_DEV(ctx) \ + COND_CODE_1(DT_HAS_CHOSEN(zephyr_log_uart), (ctx->uart_dev), \ + (DEVICE_DT_GET(DT_CHOSEN(zephyr_console)))) + /* Fixed size to avoid auto-added trailing '\0'. * Used if CONFIG_LOG_BACKEND_UART_OUTPUT_DICTIONARY_HEX. */ static const char LOG_HEX_SEP[10] = "##ZLOGV1##"; -static const struct device *const uart_dev = - DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); -static struct k_sem sem; -static volatile bool in_panic; -static bool use_async; -static uint32_t log_format_current = CONFIG_LOG_BACKEND_UART_OUTPUT_DEFAULT; - static void uart_callback(const struct device *dev, struct uart_event *evt, void *user_data) { + const struct lbu_cb_ctx *ctx = user_data; + struct lbu_data *data = ctx->data; + + ARG_UNUSED(dev); + switch (evt->type) { case UART_TX_DONE: - k_sem_give(&sem); + k_sem_give(&data->sem); break; default: break; } } -static void dict_char_out_hex(uint8_t *data, size_t length) +static void dict_char_out_hex(const struct device *uart_dev, uint8_t *data, size_t length) { for (size_t i = 0; i < length; i++) { char c; @@ -63,8 +81,10 @@ static void dict_char_out_hex(uint8_t *data, size_t length) static int char_out(uint8_t *data, size_t length, void *ctx) { - ARG_UNUSED(ctx); int err; + const struct lbu_cb_ctx *cb_ctx = ctx; + struct lbu_data *lb_data = cb_ctx->data; + const struct device *uart_dev = LBU_UART_DEV(cb_ctx); if (pm_device_runtime_is_enabled(uart_dev) && !k_is_in_isr()) { if (pm_device_runtime_get(uart_dev) < 0) { @@ -76,11 +96,12 @@ static int char_out(uint8_t *data, size_t length, void *ctx) } if (IS_ENABLED(CONFIG_LOG_BACKEND_UART_OUTPUT_DICTIONARY_HEX)) { - dict_char_out_hex(data, length); + dict_char_out_hex(uart_dev, data, length); goto cleanup; } - if (!IS_ENABLED(CONFIG_LOG_BACKEND_UART_ASYNC) || in_panic || !use_async) { + if (!IS_ENABLED(CONFIG_LOG_BACKEND_UART_ASYNC) || lb_data->in_panic || + !lb_data->use_async) { for (size_t i = 0; i < length; i++) { uart_poll_out(uart_dev, data[i]); } @@ -90,7 +111,7 @@ static int char_out(uint8_t *data, size_t length, void *ctx) err = uart_tx(uart_dev, data, length, SYS_FOREVER_US); __ASSERT_NO_MSG(err == 0); - err = k_sem_take(&sem, K_FOREVER); + err = k_sem_take(&lb_data->sem, K_FOREVER); __ASSERT_NO_MSG(err == 0); (void)err; @@ -103,29 +124,37 @@ static int char_out(uint8_t *data, size_t length, void *ctx) return length; } -static uint8_t uart_output_buf[CONFIG_LOG_BACKEND_UART_BUFFER_SIZE]; -LOG_OUTPUT_DEFINE(log_output_uart, char_out, uart_output_buf, sizeof(uart_output_buf)); - static void process(const struct log_backend *const backend, union log_msg_generic *msg) { + const struct lbu_cb_ctx *ctx = backend->cb->ctx; + struct lbu_data *data = ctx->data; uint32_t flags = log_backend_std_get_flags(); + log_format_func_t log_output_func = log_format_func_t_get(data->log_format_current); - log_format_func_t log_output_func = log_format_func_t_get(log_format_current); - - log_output_func(&log_output_uart, &msg->log, flags); + log_output_func(ctx->output, &msg->log, flags); } static int format_set(const struct log_backend *const backend, uint32_t log_type) { - log_format_current = log_type; + const struct lbu_cb_ctx *ctx = backend->cb->ctx; + struct lbu_data *data = ctx->data; + + data->log_format_current = log_type; + return 0; } static void log_backend_uart_init(struct log_backend const *const backend) { + const struct lbu_cb_ctx *ctx = backend->cb->ctx; + const struct device *uart_dev = LBU_UART_DEV(ctx); + struct lbu_data *data = ctx->data; + __ASSERT_NO_MSG(device_is_ready(uart_dev)); + log_output_ctx_set(ctx->output, (void *)ctx); + if (IS_ENABLED(CONFIG_LOG_BACKEND_UART_OUTPUT_DICTIONARY_HEX)) { /* Print a separator so the output can be fed into * log parser directly. This is useful when capturing @@ -140,20 +169,25 @@ static void log_backend_uart_init(struct log_backend const *const backend) } if (IS_ENABLED(CONFIG_LOG_BACKEND_UART_ASYNC)) { - int err = uart_callback_set(uart_dev, uart_callback, NULL); + int err = uart_callback_set(uart_dev, uart_callback, (void *)ctx); if (err == 0) { - use_async = true; - k_sem_init(&sem, 0, 1); + data->use_async = true; + k_sem_init(&data->sem, 0, 1); } else { LOG_WRN("Failed to initialize asynchronous mode (err:%d). " - "Fallback to polling.", err); + "Fallback to polling.", + err); } } } static void panic(struct log_backend const *const backend) { + const struct lbu_cb_ctx *ctx = backend->cb->ctx; + struct lbu_data *data = ctx->data; + const struct device *uart_dev = LBU_UART_DEV(ctx); + /* Ensure that the UART device is in active mode */ #if defined(CONFIG_PM_DEVICE_RUNTIME) if (pm_device_runtime_is_enabled(uart_dev)) { @@ -172,20 +206,22 @@ static void panic(struct log_backend const *const backend) if ((rc == 0) && (pm_state == PM_DEVICE_STATE_SUSPENDED)) { pm_device_action_run(uart_dev, PM_DEVICE_ACTION_RESUME); } +#else + ARG_UNUSED(uart_dev); #endif /* CONFIG_PM_DEVICE */ - in_panic = true; - log_backend_std_panic(&log_output_uart); + data->in_panic = true; + log_backend_std_panic(ctx->output); } static void dropped(const struct log_backend *const backend, uint32_t cnt) { - ARG_UNUSED(backend); + const struct lbu_cb_ctx *ctx = backend->cb->ctx; if (IS_ENABLED(CONFIG_LOG_BACKEND_UART_OUTPUT_DICTIONARY)) { - log_dict_output_dropped_process(&log_output_uart, cnt); + log_dict_output_dropped_process(ctx->output, cnt); } else { - log_backend_std_dropped(&log_output_uart, cnt); + log_backend_std_dropped(ctx->output, cnt); } } @@ -197,5 +233,29 @@ const struct log_backend_api log_backend_uart_api = { .format_set = format_set, }; -LOG_BACKEND_DEFINE(log_backend_uart, log_backend_uart_api, - IS_ENABLED(CONFIG_LOG_BACKEND_UART_AUTOSTART)); +#define LBU_DEFINE(node_id, ...) \ + static uint8_t lbu_buffer##__VA_ARGS__[CONFIG_LOG_BACKEND_UART_BUFFER_SIZE]; \ + LOG_OUTPUT_DEFINE(lbu_output##__VA_ARGS__, char_out, lbu_buffer##__VA_ARGS__, \ + CONFIG_LOG_BACKEND_UART_BUFFER_SIZE); \ + \ + static struct lbu_data lbu_data##__VA_ARGS__ = { \ + .log_format_current = CONFIG_LOG_BACKEND_UART_OUTPUT_DEFAULT, \ + }; \ + \ + static const struct lbu_cb_ctx lbu_cb_ctx##__VA_ARGS__ = { \ + .output = &lbu_output##__VA_ARGS__, \ + COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__), (), \ + (.uart_dev = DEVICE_DT_GET(node_id),)) \ + .data = &lbu_data##__VA_ARGS__, \ + }; \ + \ + LOG_BACKEND_DEFINE(log_backend_uart##__VA_ARGS__, log_backend_uart_api, \ + IS_ENABLED(CONFIG_LOG_BACKEND_UART_AUTOSTART), \ + (void *)&lbu_cb_ctx##__VA_ARGS__); + +#if DT_HAS_CHOSEN(zephyr_log_uart) +#define LBU_PHA_FN(node_id, prop, idx) LBU_DEFINE(DT_PHANDLE_BY_IDX(node_id, prop, idx), idx) +DT_FOREACH_PROP_ELEM_SEP(DT_CHOSEN(zephyr_log_uart), uarts, LBU_PHA_FN, ()); +#else +LBU_DEFINE(DT_CHOSEN(zephyr_console)); +#endif diff --git a/subsys/logging/log_core.c b/subsys/logging/log_core.c index 8e7f739d0c4..de96cfe2fb3 100644 --- a/subsys/logging/log_core.c +++ b/subsys/logging/log_core.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -163,19 +163,30 @@ static void z_log_msg_post_finalize(void) k_spin_unlock(&process_lock, key); } else if (proc_tid != NULL) { - if (cnt == 0) { - k_timer_start(&log_process_thread_timer, - K_MSEC(CONFIG_LOG_PROCESS_THREAD_SLEEP_MS), - K_NO_WAIT); - } else if (CONFIG_LOG_PROCESS_TRIGGER_THRESHOLD && - (cnt + 1) == CONFIG_LOG_PROCESS_TRIGGER_THRESHOLD) { - k_timer_stop(&log_process_thread_timer); - k_sem_give(&log_process_thread_sem); + /* + * If CONFIG_LOG_PROCESS_TRIGGER_THRESHOLD == 1, + * timer is never needed. We release the processing + * thread after every message is posted. + */ + if (CONFIG_LOG_PROCESS_TRIGGER_THRESHOLD == 1) { + if (cnt == 0) { + k_sem_give(&log_process_thread_sem); + } } else { - /* No action needed. Message processing will be triggered by the - * timeout or when number of upcoming messages exceeds the - * threshold. - */ + if (cnt == 0) { + k_timer_start(&log_process_thread_timer, + K_MSEC(CONFIG_LOG_PROCESS_THREAD_SLEEP_MS), + K_NO_WAIT); + } else if (CONFIG_LOG_PROCESS_TRIGGER_THRESHOLD && + (cnt + 1) == CONFIG_LOG_PROCESS_TRIGGER_THRESHOLD) { + k_timer_stop(&log_process_thread_timer); + k_sem_give(&log_process_thread_sem); + } else { + /* No action needed. Message processing will be triggered by the + * timeout or when number of upcoming messages exceeds the + * threshold. + */ + } } } } @@ -237,8 +248,9 @@ void log_core_init(void) if (sys_clock_hw_cycles_per_sec() > 1000000) { log_set_timestamp_func(default_lf_get_timestamp, 1000U); } else { - log_set_timestamp_func(default_get_timestamp, - sys_clock_hw_cycles_per_sec()); + uint32_t freq = IS_ENABLED(CONFIG_LOG_TIMESTAMP_64BIT) ? + CONFIG_SYS_CLOCK_TICKS_PER_SEC : sys_clock_hw_cycles_per_sec(); + log_set_timestamp_func(default_get_timestamp, freq); } if (IS_ENABLED(CONFIG_LOG_MODE_DEFERRED)) { @@ -596,8 +608,11 @@ static struct log_msg *msg_alloc(struct mpsc_pbuf_buffer *buffer, uint32_t wlen) return NULL; } - return (struct log_msg *)mpsc_pbuf_alloc(buffer, wlen, - K_MSEC(CONFIG_LOG_BLOCK_IN_THREAD_TIMEOUT_MS)); + return (struct log_msg *)mpsc_pbuf_alloc( + buffer, wlen, + (CONFIG_LOG_BLOCK_IN_THREAD_TIMEOUT_MS == -1) + ? K_FOREVER + : K_MSEC(CONFIG_LOG_BLOCK_IN_THREAD_TIMEOUT_MS)); } struct log_msg *z_log_msg_alloc(uint32_t wlen) diff --git a/subsys/logging/log_mgmt.c b/subsys/logging/log_mgmt.c index 1f3e3594760..6336e4a8385 100644 --- a/subsys/logging/log_mgmt.c +++ b/subsys/logging/log_mgmt.c @@ -5,7 +5,7 @@ */ #include #include -#include +#include #include #include #include @@ -417,7 +417,7 @@ uint32_t z_impl_log_filter_set(struct log_backend const *const backend, uint32_t level) { if (!IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING)) { - return level; + return log_compiled_level_get(domain_id, source_id); } __ASSERT_NO_MSG(source_id < log_src_cnt_get(domain_id)); @@ -449,13 +449,13 @@ uint32_t z_vrfy_log_filter_set(struct log_backend const *const backend, int16_t src_id, uint32_t level) { - Z_OOPS(Z_SYSCALL_VERIFY_MSG(backend == NULL, + K_OOPS(K_SYSCALL_VERIFY_MSG(backend == NULL, "Setting per-backend filters from user mode is not supported")); - Z_OOPS(Z_SYSCALL_VERIFY_MSG(domain_id == Z_LOG_LOCAL_DOMAIN_ID, + K_OOPS(K_SYSCALL_VERIFY_MSG(domain_id == Z_LOG_LOCAL_DOMAIN_ID, "Invalid log domain_id")); - Z_OOPS(Z_SYSCALL_VERIFY_MSG(src_id < (int16_t)log_src_cnt_get(domain_id), + K_OOPS(K_SYSCALL_VERIFY_MSG(src_id < (int16_t)log_src_cnt_get(domain_id), "Invalid log source id")); - Z_OOPS(Z_SYSCALL_VERIFY_MSG( + K_OOPS(K_SYSCALL_VERIFY_MSG( (level <= LOG_LEVEL_DBG), "Invalid log level")); diff --git a/subsys/logging/log_msg.c b/subsys/logging/log_msg.c index 3756d52480d..da9dffdc62e 100644 --- a/subsys/logging/log_msg.c +++ b/subsys/logging/log_msg.c @@ -4,12 +4,13 @@ * SPDX-License-Identifier: Apache-2.0 */ #include -#include +#include #include #include #include #include #include +#include LOG_MODULE_DECLARE(log); BUILD_ASSERT(sizeof(struct log_msg_desc) == sizeof(uint32_t), @@ -20,6 +21,13 @@ BUILD_ASSERT(sizeof(struct log_msg_desc) == sizeof(uint32_t), !(IS_ENABLED(CONFIG_LOG_FRONTEND) && \ (IS_ENABLED(CONFIG_LOG_FRONTEND_ONLY) || log_backend_count_get() == 0)) +#define CBPRINTF_DESC_SIZE32 (sizeof(struct cbprintf_package_desc) / sizeof(uint32_t)) + +/* For simplified message handling cprintf package must have only 1 word. */ +BUILD_ASSERT(!IS_ENABLED(CONFIG_LOG_SIMPLE_MSG_OPTIMIZE) || + (IS_ENABLED(CONFIG_LOG_SIMPLE_MSG_OPTIMIZE) && (CBPRINTF_DESC_SIZE32 == 1))); + + void z_log_msg_finalize(struct log_msg *msg, const void *source, const struct log_msg_desc desc, const void *data) { @@ -43,6 +51,174 @@ void z_log_msg_finalize(struct log_msg *msg, const void *source, z_log_msg_commit(msg); } +/** @brief Create a log message using simplified method. + * + * Simple log message has 0-2 32 bit word arguments so creating cbprintf package + * is straightforward as there is no padding or alignment to concern about. + * This function takes input data which is fmt pointer + 0-2 arguments, creates + * package header which is very simple as it only contain non-zero length field. + * Then space is allocated and message is committed. Such simple approach can + * be applied because it is known that input string does not have any arguments + * which complicate things (string pointers, floating numbers). Simple method is + * also limited to 32 bit arch. + * + * @param source Source. + * @param level Severity level. + * @param data Package content (without header). + * @param len Package content length in words. + */ +static void z_log_msg_simple_create(const void *source, uint32_t level, uint32_t *data, size_t len) +{ + /* Package length (in words) is increased by the header. */ + size_t plen32 = len + CBPRINTF_DESC_SIZE32; + /* Package length in bytes. */ + size_t plen8 = sizeof(uint32_t) * plen32; + struct log_msg *msg = z_log_msg_alloc(Z_LOG_MSG_ALIGNED_WLEN(plen8, 0)); + union cbprintf_package_hdr package_hdr = { + .desc = { + .len = plen32 + } + }; + + if (msg) { + uint32_t *package = (uint32_t *)msg->data; + + *package++ = (uint32_t)(uintptr_t)package_hdr.raw; + for (size_t i = 0; i < len; i++) { + *package++ = data[i]; + } + } + + struct log_msg_desc desc = { + .level = level, + .package_len = plen8, + .data_len = 0, + }; + + z_log_msg_finalize(msg, source, desc, NULL); + +} + +void z_impl_z_log_msg_simple_create_0(const void *source, uint32_t level, const char *fmt) +{ + + if (IS_ENABLED(CONFIG_LOG_FRONTEND)) { + if (IS_ENABLED(CONFIG_LOG_FRONTEND_OPT_API)) { + log_frontend_simple_0(source, level, fmt); + } else { + /* If frontend does not support optimized API prepare data for + * the generic call. + */ + uint32_t plen32 = CBPRINTF_DESC_SIZE32 + 1; + union cbprintf_package_hdr hdr = { + .desc = { + .len = plen32 + } + }; + uint32_t package[] = { + (uint32_t)(uintptr_t)hdr.raw, + (uint32_t)(uintptr_t)fmt, + }; + struct log_msg_desc desc = { + .level = level, + .package_len = plen32 * sizeof(uint32_t), + .data_len = 0, + }; + + log_frontend_msg(source, desc, (uint8_t *)package, NULL); + } + } + + if (!BACKENDS_IN_USE()) { + return; + } + + uint32_t data[] = {(uint32_t)(uintptr_t)fmt}; + + z_log_msg_simple_create(source, level, data, ARRAY_SIZE(data)); +} + +void z_impl_z_log_msg_simple_create_1(const void *source, uint32_t level, + const char *fmt, uint32_t arg) +{ + if (IS_ENABLED(CONFIG_LOG_FRONTEND)) { + if (IS_ENABLED(CONFIG_LOG_FRONTEND_OPT_API)) { + log_frontend_simple_1(source, level, fmt, arg); + } else { + /* If frontend does not support optimized API prepare data for + * the generic call. + */ + uint32_t plen32 = CBPRINTF_DESC_SIZE32 + 2; + union cbprintf_package_hdr hdr = { + .desc = { + .len = plen32 + } + }; + uint32_t package[] = { + (uint32_t)(uintptr_t)hdr.raw, + (uint32_t)(uintptr_t)fmt, + arg + }; + struct log_msg_desc desc = { + .level = level, + .package_len = plen32 * sizeof(uint32_t), + .data_len = 0, + }; + + log_frontend_msg(source, desc, (uint8_t *)package, NULL); + } + } + + if (!BACKENDS_IN_USE()) { + return; + } + + uint32_t data[] = {(uint32_t)(uintptr_t)fmt, arg}; + + z_log_msg_simple_create(source, level, data, ARRAY_SIZE(data)); +} + +void z_impl_z_log_msg_simple_create_2(const void *source, uint32_t level, + const char *fmt, uint32_t arg0, uint32_t arg1) +{ + if (IS_ENABLED(CONFIG_LOG_FRONTEND)) { + if (IS_ENABLED(CONFIG_LOG_FRONTEND_OPT_API)) { + log_frontend_simple_2(source, level, fmt, arg0, arg1); + } else { + /* If frontend does not support optimized API prepare data for + * the generic call. + */ + uint32_t plen32 = CBPRINTF_DESC_SIZE32 + 3; + union cbprintf_package_hdr hdr = { + .desc = { + .len = plen32 + } + }; + uint32_t package[] = { + [0](uint32_t)(uintptr_t)hdr.raw, + (uint32_t)(uintptr_t)fmt, + arg0, + arg1 + }; + struct log_msg_desc desc = { + .level = level, + .package_len = plen32 * sizeof(uint32_t), + .data_len = 0, + }; + + log_frontend_msg(source, desc, (uint8_t *)package, NULL); + } + } + + if (!BACKENDS_IN_USE()) { + return; + } + + uint32_t data[] = {(uint32_t)(uintptr_t)fmt, arg0, arg1}; + + z_log_msg_simple_create(source, level, data, ARRAY_SIZE(data)); +} + void z_impl_z_log_msg_static_create(const void *source, const struct log_msg_desc desc, uint8_t *package, const void *data) @@ -61,7 +237,8 @@ void z_impl_z_log_msg_static_create(const void *source, if (inlen > 0) { uint32_t flags = CBPRINTF_PACKAGE_CONVERT_RW_STR | - CBPRINTF_PACKAGE_CONVERT_PTR_CHECK; + (IS_ENABLED(CONFIG_LOG_FMT_SECTION_STRIP) ? + 0 : CBPRINTF_PACKAGE_CONVERT_PTR_CHECK); uint16_t strl[4]; int len; @@ -94,6 +271,7 @@ void z_impl_z_log_msg_static_create(const void *source, z_log_msg_finalize(msg, source, out_desc, data); } +EXPORT_SYSCALL(z_log_msg_static_create); #ifdef CONFIG_USERSPACE static inline void z_vrfy_z_log_msg_static_create(const void *source, @@ -105,7 +283,7 @@ static inline void z_vrfy_z_log_msg_static_create(const void *source, #include #endif -void z_impl_z_log_msg_runtime_vcreate(uint8_t domain_id, const void *source, +void z_log_msg_runtime_vcreate(uint8_t domain_id, const void *source, uint8_t level, const void *data, size_t dlen, uint32_t package_flags, const char *fmt, va_list ap) { @@ -154,15 +332,3 @@ void z_impl_z_log_msg_runtime_vcreate(uint8_t domain_id, const void *source, z_log_msg_finalize(msg, source, desc, data); } } - -#ifdef CONFIG_USERSPACE -static inline void z_vrfy_z_log_msg_runtime_vcreate(uint8_t domain_id, - const void *source, - uint8_t level, const void *data, size_t dlen, - uint32_t package_flags, const char *fmt, va_list ap) -{ - return z_impl_z_log_msg_runtime_vcreate(domain_id, source, level, data, - dlen, package_flags, fmt, ap); -} -#include -#endif diff --git a/subsys/logging/log_output.c b/subsys/logging/log_output.c index ecfab72cac2..b93f3439961 100644 --- a/subsys/logging/log_output.c +++ b/subsys/logging/log_output.c @@ -23,10 +23,10 @@ #define HEXDUMP_BYTES_IN_LINE 16 #define DROPPED_COLOR_PREFIX \ - Z_LOG_EVAL(CONFIG_LOG_BACKEND_SHOW_COLOR, (LOG_COLOR_CODE_RED), ()) + COND_CODE_1(CONFIG_LOG_BACKEND_SHOW_COLOR, (LOG_COLOR_CODE_RED), ()) #define DROPPED_COLOR_POSTFIX \ - Z_LOG_EVAL(CONFIG_LOG_BACKEND_SHOW_COLOR, (LOG_COLOR_CODE_DEFAULT), ()) + COND_CODE_1(CONFIG_LOG_BACKEND_SHOW_COLOR, (LOG_COLOR_CODE_DEFAULT), ()) static const char *const severity[] = { NULL, @@ -328,7 +328,7 @@ static int ids_print(const struct log_output *output, bool thread_on, const char *domain, const char *source, - const k_tid_t tid, + k_tid_t tid, uint32_t level) { int total = 0; @@ -441,7 +441,7 @@ static uint32_t prefix_print(const struct log_output *output, log_timestamp_t timestamp, const char *domain, const char *source, - const k_tid_t tid, + k_tid_t tid, uint8_t level) { __ASSERT_NO_MSG(level <= LOG_LEVEL_DBG); @@ -506,7 +506,7 @@ void log_output_process(const struct log_output *output, log_timestamp_t timestamp, const char *domain, const char *source, - const k_tid_t tid, + k_tid_t tid, uint8_t level, const uint8_t *package, const uint8_t *data, diff --git a/subsys/lorawan/Kconfig b/subsys/lorawan/Kconfig index 691b3a19eb2..229e075b5c5 100644 --- a/subsys/lorawan/Kconfig +++ b/subsys/lorawan/Kconfig @@ -27,6 +27,13 @@ config LORAWAN_SYSTEM_MAX_RX_ERROR System Max Rx timing error value in ms to be used by LoRaWAN stack for calculating the RX1/RX2 window timing. +config LORAWAN_PUBLIC_NETWORK + bool "LoRaWAN Public Network" + default y + help + Enable this option to use a public LoRaWAN network. + Disable for private LoRaWAN networks. + config LORAMAC_REGION_AS923 bool "Asia 923MHz Frequency band" diff --git a/subsys/lorawan/lorawan.c b/subsys/lorawan/lorawan.c index 70bcc67a4d3..56731dfc454 100644 --- a/subsys/lorawan/lorawan.c +++ b/subsys/lorawan/lorawan.c @@ -72,8 +72,8 @@ static LoRaMacEventInfoStatus_t last_mlme_indication_status; static LoRaMacRegion_t selected_region = DEFAULT_LORAWAN_REGION; -static uint8_t (*get_battery_level_user)(void); -static void (*dr_change_cb)(enum lorawan_datarate dr); +static lorawan_battery_level_cb_t battery_level_cb; +static lorawan_dr_changed_cb_t dr_changed_cb; /* implementation required by the soft-se (software secure element) */ void BoardGetUniqueId(uint8_t *id) @@ -83,11 +83,11 @@ void BoardGetUniqueId(uint8_t *id) static uint8_t get_battery_level(void) { - if (get_battery_level_user != NULL) { - return get_battery_level_user(); + if (battery_level_cb != NULL) { + return battery_level_cb(); + } else { + return 255; } - - return 255; } static void mac_process_notify(void) @@ -105,8 +105,8 @@ static void datarate_observe(bool force_notification) if ((mib_req.Param.ChannelsDatarate != current_datarate) || (force_notification)) { current_datarate = mib_req.Param.ChannelsDatarate; - if (dr_change_cb) { - dr_change_cb(current_datarate); + if (dr_changed_cb != NULL) { + dr_changed_cb(current_datarate); } LOG_INF("Datarate changed: DR_%d", current_datarate); } @@ -369,7 +369,7 @@ int lorawan_join(const struct lorawan_join_config *join_cfg) /* MIB_PUBLIC_NETWORK powers on the radio and does not turn it off */ mib_req.Type = MIB_PUBLIC_NETWORK; - mib_req.Param.EnablePublicNetwork = true; + mib_req.Param.EnablePublicNetwork = IS_ENABLED(CONFIG_LORAWAN_PUBLIC_NETWORK); LoRaMacMibSetRequestConfirm(&mib_req); if (join_cfg->mode == LORAWAN_ACT_OTAA) { @@ -621,15 +621,9 @@ int lorawan_send(uint8_t port, uint8_t *data, uint8_t len, return ret; } -int lorawan_set_battery_level_callback(uint8_t (*battery_lvl_cb)(void)) +void lorawan_register_battery_level_callback(lorawan_battery_level_cb_t cb) { - if (battery_lvl_cb == NULL) { - return -EINVAL; - } - - get_battery_level_user = battery_lvl_cb; - - return 0; + battery_level_cb = cb; } void lorawan_register_downlink_callback(struct lorawan_downlink_cb *cb) @@ -637,9 +631,9 @@ void lorawan_register_downlink_callback(struct lorawan_downlink_cb *cb) sys_slist_append(&dl_callbacks, &cb->node); } -void lorawan_register_dr_changed_callback(void (*cb)(enum lorawan_datarate)) +void lorawan_register_dr_changed_callback(lorawan_dr_changed_cb_t cb) { - dr_change_cb = cb; + dr_changed_cb = cb; } int lorawan_start(void) diff --git a/subsys/lorawan/services/clock_sync.c b/subsys/lorawan/services/clock_sync.c index 2f627d30dea..9e4bbe447a0 100644 --- a/subsys/lorawan/services/clock_sync.c +++ b/subsys/lorawan/services/clock_sync.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include LOG_MODULE_REGISTER(lorawan_clock_sync, CONFIG_LORAWAN_SERVICES_LOG_LEVEL); diff --git a/subsys/mem_mgmt/CMakeLists.txt b/subsys/mem_mgmt/CMakeLists.txt new file mode 100644 index 00000000000..62e61fb4d1f --- /dev/null +++ b/subsys/mem_mgmt/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_sources_ifdef(CONFIG_MEM_ATTR mem_attr.c) diff --git a/subsys/mem_mgmt/Kconfig b/subsys/mem_mgmt/Kconfig new file mode 100644 index 00000000000..dda1a404167 --- /dev/null +++ b/subsys/mem_mgmt/Kconfig @@ -0,0 +1,12 @@ +# Copyright (c) 2023 Carlo Caione +# SPDX-License-Identifier: Apache-2.0 + +config MEM_ATTR + bool "Memory Attributes management library" + default y if ARM_MPU + help + Enable a small library to manage the memory regions defined in the DT + with a `zephyr,memory-attr` property. This library builds at build + time an array of the memory regions defined in the DT that can be + probed at run-time using several helper functions. Set to `N` if + unsure to save RODATA space. diff --git a/subsys/mem_mgmt/mem_attr.c b/subsys/mem_mgmt/mem_attr.c new file mode 100644 index 00000000000..c70a515dd81 --- /dev/null +++ b/subsys/mem_mgmt/mem_attr.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023 Carlo Caione, + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#define _BUILD_MEM_ATTR_REGION(node_id) \ + { \ + .dt_name = DT_NODE_FULL_NAME(node_id), \ + .dt_addr = DT_REG_ADDR(node_id), \ + .dt_size = DT_REG_SIZE(node_id), \ + .dt_attr = DT_PROP(node_id, zephyr_memory_attr), \ + }, + +static const struct mem_attr_region_t mem_attr_region[] = { + DT_MEMORY_ATTR_FOREACH_STATUS_OKAY_NODE(_BUILD_MEM_ATTR_REGION) +}; + +size_t mem_attr_get_regions(const struct mem_attr_region_t **region) +{ + *region = mem_attr_region; + + return ARRAY_SIZE(mem_attr_region); +} + +int mem_attr_check_buf(void *v_addr, size_t size, uint32_t attr) +{ + uintptr_t addr = (uintptr_t) v_addr; + + /* + * If MMU is enabled the address of the buffer is a virtual address + * while the addresses in the DT are physical addresses. Given that we + * have no way of knowing whether a mapping exists, we simply bail out. + */ + if (IS_ENABLED(CONFIG_MMU)) { + return -ENOSYS; + } + + if (size == 0) { + return -ENOTSUP; + } + + for (size_t idx = 0; idx < ARRAY_SIZE(mem_attr_region); idx++) { + const struct mem_attr_region_t *region = &mem_attr_region[idx]; + size_t region_end = region->dt_addr + region->dt_size; + + /* Check if the buffer is in the region */ + if ((addr >= region->dt_addr) && (addr < region_end)) { + /* Check if the buffer is entirely contained in the region */ + if ((addr + size) <= region_end) { + /* check if the attribute is correct */ + return (region->dt_attr & attr) == attr ? 0 : -EINVAL; + } + return -ENOSPC; + } + } + return -ENOBUFS; +} diff --git a/subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_espi.c b/subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_espi.c index dd7dfa9099c..09224ffdac2 100644 --- a/subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_espi.c +++ b/subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_espi.c @@ -114,6 +114,10 @@ static int ec_host_cmd_espi_init(const struct ec_host_cmd_backend *backend, espi_read_lpc_request(hc_espi->espi_dev, ECUSTOM_HOST_CMD_GET_PARAM_MEMORY_SIZE, &tx->len_max); + /* Set the max len for RX as the min of buffer to store data and shared memory. */ + hc_espi->rx_ctx->len_max = + MIN(CONFIG_EC_HOST_CMD_HANDLER_RX_BUFFER_SIZE, hc_espi->tx->len_max); + hc_espi->state = ESPI_STATE_READY_TO_RECV; return 0; diff --git a/subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_shi_ite.c b/subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_shi_ite.c index e84b7d351e3..8c11765ee82 100644 --- a/subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_shi_ite.c +++ b/subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_shi_ite.c @@ -455,8 +455,9 @@ static int shi_ite_backend_init(const struct ec_host_cmd_backend *backend, data->tx = tx; rx_ctx->buf = data->in_msg; + rx_ctx->len_max = CONFIG_EC_HOST_CMD_BACKEND_SHI_MAX_REQUEST; tx->buf = data->out_msg + sizeof(out_preamble); - data->tx->len_max = sizeof(data->out_msg) - EC_SHI_PREAMBLE_LENGTH - EC_SHI_PAST_END_LENGTH; + data->tx->len_max = CONFIG_EC_HOST_CMD_BACKEND_SHI_MAX_RESPONSE; return 0; } diff --git a/subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_shi_npcx.c b/subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_shi_npcx.c index 9e4c6b08dd2..f98f3bf7584 100644 --- a/subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_shi_npcx.c +++ b/subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_shi_npcx.c @@ -882,6 +882,7 @@ static int shi_npcx_backend_init(const struct ec_host_cmd_backend *backend, data->tx = tx; rx_ctx->buf = data->in_msg; + rx_ctx->len_max = CONFIG_EC_HOST_CMD_BACKEND_SHI_MAX_REQUEST; tx->buf = data->out_msg_padded + SHI_OUT_START_PAD; tx->len_max = CONFIG_EC_HOST_CMD_BACKEND_SHI_MAX_RESPONSE; diff --git a/subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_spi_stm32.c b/subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_spi_stm32.c index c022150aa3b..52ee12ea0fd 100644 --- a/subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_spi_stm32.c +++ b/subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_spi_stm32.c @@ -96,6 +96,14 @@ BUILD_ASSERT(DT_NODE_HAS_COMPAT_STATUS(DT_CHOSEN(zephyr_host_cmd_spi_backend), #define EC_HOST_CMD_ST_STM32_FIFO #endif /* st_stm32_spi_fifo */ +/* + * Max data size for a version 3 request/response packet. This is big enough + * to handle a request/response header, flash write offset/size, and 512 bytes + * of flash data. + */ +#define SPI_MAX_REQ_SIZE 0x220 +#define SPI_MAX_RESP_SIZE 0x220 + /* Enumeration to maintain different states of incoming request from * host */ @@ -136,8 +144,8 @@ struct dma_stream { struct ec_host_cmd_spi_cfg { SPI_TypeDef *spi; const struct pinctrl_dev_config *pcfg; - size_t pclk_len; const struct stm32_pclken *pclken; + size_t pclk_len; }; struct ec_host_cmd_spi_ctx { @@ -189,9 +197,9 @@ static int prepare_rx(struct ec_host_cmd_spi_ctx *hc_spi); \ static struct ec_host_cmd_spi_cfg ec_host_cmd_spi_cfg = { \ .spi = (SPI_TypeDef *)DT_REG_ADDR(id), \ + .pcfg = PINCTRL_DT_DEV_CONFIG_GET(id), \ .pclken = pclken, \ .pclk_len = DT_NUM_CLOCKS(id), \ - .pcfg = PINCTRL_DT_DEV_CONFIG_GET(id), \ }; \ \ static struct dma_stream dma_rx = {SPI_DMA_CHANNEL_INIT(id, rx, RX, PERIPHERAL, MEMORY)}; \ @@ -667,6 +675,14 @@ static int ec_host_cmd_spi_init(const struct ec_host_cmd_backend *backend, hc_spi->tx->buf = (uint8_t *)hc_spi->tx->buf + sizeof(out_preamble); hc_spi->tx->len_max = hc_spi->tx->len_max - sizeof(out_preamble) - EC_SPI_PAST_END_LENGTH; + /* Limit the requset/response max sizes */ + if (hc_spi->rx_ctx->len_max > SPI_MAX_REQ_SIZE) { + hc_spi->rx_ctx->len_max = SPI_MAX_REQ_SIZE; + } + if (hc_spi->tx->len_max > SPI_MAX_RESP_SIZE) { + hc_spi->tx->len_max = SPI_MAX_RESP_SIZE; + } + ret = spi_init(hc_spi); if (ret) { return ret; diff --git a/subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_uart.c b/subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_uart.c index a15eecfc4e7..2e77d3f0ccd 100644 --- a/subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_uart.c +++ b/subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_uart.c @@ -100,10 +100,16 @@ static int request_expected_size(const struct ec_host_cmd_request_header *r) .ctx = &_name##_hc_uart, \ } -/* Waiting time in microseconds to detect overrun */ -#define UART_OVERRUN_TIMEOUT_US 300 /* Timeout after receiving first byte */ -#define UART_REQ_RX_TIMEOUT K_MSEC(150) +#define UART_REQ_RX_TIMEOUT K_MSEC(150) + +/* + * Max data size for a version 3 request/response packet. This is big enough + * to handle a request/response header, flash write offset/size and 512 bytes + * of request payload or 224 bytes of response payload. + */ +#define UART_MAX_REQ_SIZE 0x220 +#define UART_MAX_RESP_SIZE 0x100 static void rx_timeout(struct k_work *work) { @@ -135,8 +141,7 @@ static void rx_timeout(struct k_work *work) } res = uart_rx_disable(hc_uart->uart_dev); - res = uart_rx_enable(hc_uart->uart_dev, hc_uart->rx_ctx->buf, hc_uart->rx_buf_size, - UART_OVERRUN_TIMEOUT_US); + res = uart_rx_enable(hc_uart->uart_dev, hc_uart->rx_ctx->buf, hc_uart->rx_buf_size, 0); hc_uart->state = UART_HOST_CMD_READY_TO_RX; } @@ -245,10 +250,17 @@ static int ec_host_cmd_uart_init(const struct ec_host_cmd_backend *backend, hc_uart->rx_ctx = rx_ctx; hc_uart->tx_buf = tx; + /* Limit the requset/response max sizes */ + if (hc_uart->rx_ctx->len_max > UART_MAX_REQ_SIZE) { + hc_uart->rx_ctx->len_max = UART_MAX_REQ_SIZE; + } + if (hc_uart->tx_buf->len_max > UART_MAX_RESP_SIZE) { + hc_uart->tx_buf->len_max = UART_MAX_RESP_SIZE; + } + k_work_init_delayable(&hc_uart->timeout_work, rx_timeout); uart_callback_set(hc_uart->uart_dev, uart_callback, hc_uart); - ret = uart_rx_enable(hc_uart->uart_dev, hc_uart->rx_ctx->buf, hc_uart->rx_buf_size, - UART_OVERRUN_TIMEOUT_US); + ret = uart_rx_enable(hc_uart->uart_dev, hc_uart->rx_ctx->buf, hc_uart->rx_buf_size, 0); hc_uart->state = UART_HOST_CMD_READY_TO_RX; @@ -270,8 +282,7 @@ static int ec_host_cmd_uart_send(const struct ec_host_cmd_backend *backend) /* The rx buffer is no longer in use by command handler. * Enable receiving to be ready to get a new command right after sending the response. */ - uart_rx_enable(hc_uart->uart_dev, hc_uart->rx_ctx->buf, hc_uart->rx_buf_size, - UART_OVERRUN_TIMEOUT_US); + uart_rx_enable(hc_uart->uart_dev, hc_uart->rx_ctx->buf, hc_uart->rx_buf_size, 0); /* uart_tx is non-blocking asynchronous function. * The state is changed to UART_HOST_CMD_READY_TO_RX in the UART_TX_DONE event. diff --git a/subsys/mgmt/ec_host_cmd/ec_host_cmd_handler.c b/subsys/mgmt/ec_host_cmd/ec_host_cmd_handler.c index 23a90a64094..b8bf8cfbe6a 100644 --- a/subsys/mgmt/ec_host_cmd/ec_host_cmd_handler.c +++ b/subsys/mgmt/ec_host_cmd/ec_host_cmd_handler.c @@ -15,6 +15,7 @@ LOG_MODULE_REGISTER(host_cmd_handler, CONFIG_EC_HC_LOG_LEVEL); +#ifdef CONFIG_EC_HOST_CMD_INITIALIZE_AT_BOOT #define EC_HOST_CMD_CHOSEN_BACKEND_LIST \ zephyr_host_cmd_espi_backend, zephyr_host_cmd_shi_backend, zephyr_host_cmd_uart_backend, \ zephyr_host_cmd_spi_backend @@ -26,14 +27,17 @@ LOG_MODULE_REGISTER(host_cmd_handler, CONFIG_EC_HC_LOG_LEVEL); +0 BUILD_ASSERT(NUMBER_OF_CHOSEN_BACKENDS < 2, "Number of chosen backends > 1"); +#endif #define RX_HEADER_SIZE (sizeof(struct ec_host_cmd_request_header)) #define TX_HEADER_SIZE (sizeof(struct ec_host_cmd_response_header)) COND_CODE_1(CONFIG_EC_HOST_CMD_HANDLER_RX_BUFFER_DEF, - (static uint8_t hc_rx_buffer[CONFIG_EC_HOST_CMD_HANDLER_RX_BUFFER_SIZE];), ()) + (static uint8_t hc_rx_buffer[CONFIG_EC_HOST_CMD_HANDLER_RX_BUFFER_SIZE] __aligned(4);), + ()) COND_CODE_1(CONFIG_EC_HOST_CMD_HANDLER_TX_BUFFER_DEF, - (static uint8_t hc_tx_buffer[CONFIG_EC_HOST_CMD_HANDLER_TX_BUFFER_SIZE];), ()) + (static uint8_t hc_tx_buffer[CONFIG_EC_HOST_CMD_HANDLER_TX_BUFFER_SIZE] __aligned(4);), + ()) #ifdef CONFIG_EC_HOST_CMD_DEDICATED_THREAD static K_KERNEL_STACK_DEFINE(hc_stack, CONFIG_EC_HOST_CMD_HANDLER_STACK_SIZE); @@ -43,6 +47,8 @@ static struct ec_host_cmd ec_host_cmd = { .rx_ctx = { .buf = COND_CODE_1(CONFIG_EC_HOST_CMD_HANDLER_RX_BUFFER_DEF, (hc_rx_buffer), (NULL)), + .len_max = COND_CODE_1(CONFIG_EC_HOST_CMD_HANDLER_RX_BUFFER_DEF, + (CONFIG_EC_HOST_CMD_HANDLER_RX_BUFFER_SIZE), (0)), }, .tx = { .buf = COND_CODE_1(CONFIG_EC_HOST_CMD_HANDLER_TX_BUFFER_DEF, (hc_tx_buffer), diff --git a/subsys/mgmt/mcumgr/Kconfig b/subsys/mgmt/mcumgr/Kconfig index a25ee0dc625..1c6a3a2a516 100644 --- a/subsys/mgmt/mcumgr/Kconfig +++ b/subsys/mgmt/mcumgr/Kconfig @@ -6,7 +6,6 @@ menuconfig MCUMGR bool "mcumgr Support" depends on NET_BUF depends on ZCBOR - imply CRC imply BOOT_IMAGE_ACCESS_HOOKS if (SOC_NRF5340_CPUAPP_QKAA && MCUMGR_GRP_IMG) help This option enables the mcumgr management library. diff --git a/subsys/mgmt/mcumgr/grp/fs_mgmt/Kconfig b/subsys/mgmt/mcumgr/grp/fs_mgmt/Kconfig index 063aadbf61b..95e8a1c2658 100644 --- a/subsys/mgmt/mcumgr/grp/fs_mgmt/Kconfig +++ b/subsys/mgmt/mcumgr/grp/fs_mgmt/Kconfig @@ -118,6 +118,7 @@ config MCUMGR_GRP_FS_CHECKSUM_HASH_CHUNK_SIZE config MCUMGR_GRP_FS_CHECKSUM_IEEE_CRC32 bool "IEEE CRC32 checksum support" + select CRC default y help Enable IEEE CRC32 checksum support for MCUmgr. diff --git a/subsys/mgmt/mcumgr/grp/fs_mgmt/src/fs_mgmt.c b/subsys/mgmt/mcumgr/grp/fs_mgmt/src/fs_mgmt.c index 571d4c01515..3458c3d6f8b 100644 --- a/subsys/mgmt/mcumgr/grp/fs_mgmt/src/fs_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/fs_mgmt/src/fs_mgmt.c @@ -425,7 +425,9 @@ static int fs_mgmt_file_upload(struct smp_streamer *ctxt) if (rc == -EINVAL) { rc = FS_MGMT_ERR_FILE_INVALID_NAME; } else if (rc == -ENOENT) { - rc = FS_MGMT_ERR_FILE_NOT_FOUND; + rc = FS_MGMT_ERR_MOUNT_POINT_NOT_FOUND; + } else if (rc == -EROFS) { + rc = FS_MGMT_ERR_READ_ONLY_FILESYSTEM; } else { rc = FS_MGMT_ERR_UNKNOWN; } @@ -730,9 +732,12 @@ static int fs_mgmt_file_hash_checksum(struct smp_streamer *ctxt) } if (file_len <= off) { - /* Requested offset is larger than target file size */ + /* Requested offset is larger than target file size or file length is 0, which + * means no hash/checksum can be performed + */ ok = smp_add_cmd_err(zse, MGMT_GROUP_ID_FS, - FS_MGMT_ERR_FILE_OFFSET_LARGER_THAN_FILE); + (file_len == 0 ? FS_MGMT_ERR_FILE_EMPTY : + FS_MGMT_ERR_FILE_OFFSET_LARGER_THAN_FILE)); goto end; } @@ -909,7 +914,18 @@ static int fs_mgmt_translate_error_code(uint16_t err) int rc; switch (err) { + case FS_MGMT_ERR_FILE_INVALID_NAME: + case FS_MGMT_ERR_CHECKSUM_HASH_NOT_FOUND: + rc = MGMT_ERR_EINVAL; + break; + + case FS_MGMT_ERR_FILE_NOT_FOUND: + case FS_MGMT_ERR_MOUNT_POINT_NOT_FOUND: + rc = MGMT_ERR_ENOENT; + break; + case FS_MGMT_ERR_UNKNOWN: + case FS_MGMT_ERR_FILE_IS_DIRECTORY: case FS_MGMT_ERR_FILE_OPEN_FAILED: case FS_MGMT_ERR_FILE_SEEK_FAILED: case FS_MGMT_ERR_FILE_READ_FAILED: @@ -918,6 +934,7 @@ static int fs_mgmt_translate_error_code(uint16_t err) case FS_MGMT_ERR_FILE_WRITE_FAILED: case FS_MGMT_ERR_FILE_OFFSET_NOT_VALID: case FS_MGMT_ERR_FILE_OFFSET_LARGER_THAN_FILE: + case FS_MGMT_ERR_READ_ONLY_FILESYSTEM: default: rc = MGMT_ERR_EUNKNOWN; } diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c b/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c index addde1e9a2c..0af1f19ba88 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c @@ -298,6 +298,11 @@ int img_mgmt_erase_slot(int slot) LOG_ERR("Failed to erase flash area: %d", rc); rc = IMG_MGMT_ERR_FLASH_ERASE_FAILED; } + } else if (rc == 1) { + /* A return value of 1 indicates that the slot is already erased, thus + * return a success code to the client + */ + rc = 0; } flash_area_close(fa); diff --git a/subsys/mgmt/mcumgr/grp/os_mgmt/Kconfig b/subsys/mgmt/mcumgr/grp/os_mgmt/Kconfig index fa743b53caf..62245760a47 100644 --- a/subsys/mgmt/mcumgr/grp/os_mgmt/Kconfig +++ b/subsys/mgmt/mcumgr/grp/os_mgmt/Kconfig @@ -135,6 +135,27 @@ config MCUMGR_GRP_OS_ECHO default y select MCUMGR_SMP_CBOR_MIN_DECODING_LEVEL_2 +config MCUMGR_GRP_OS_DATETIME + bool "Support for datetime command" + depends on RTC + depends on $(dt_alias_enabled,rtc) + select MCUMGR_SMP_CBOR_MIN_DECODING_LEVEL_2 + help + Enables support for the datetime get and set functions, this allows for using the + `rtc` alias device as a timesource from which the current time can be written or read. + +config MCUMGR_GRP_OS_DATETIME_MS + bool "Support millisecond field in datetime commands" + depends on MCUMGR_GRP_OS_DATETIME + +config MCUMGR_GRP_OS_DATETIME_HOOK + bool "Datetime hook" + depends on MCUMGR_GRP_OS_DATETIME + depends on MCUMGR_MGMT_NOTIFICATION_HOOKS + help + Allows applications to control and get notifications of when a datetime set/get + command has been issued via an MCUmgr command. + config MCUMGR_GRP_OS_MCUMGR_PARAMS bool "MCUMGR Parameters retrieval command" diff --git a/subsys/mgmt/mcumgr/grp/os_mgmt/include/os_mgmt_processor.h b/subsys/mgmt/mcumgr/grp/os_mgmt/include/os_mgmt_processor.h index ccb384f6e9d..9e6fa763790 100644 --- a/subsys/mgmt/mcumgr/grp/os_mgmt/include/os_mgmt_processor.h +++ b/subsys/mgmt/mcumgr/grp/os_mgmt/include/os_mgmt_processor.h @@ -132,6 +132,8 @@ extern "C" { #define PROCESSOR_NAME "riscv" #elif defined(CONFIG_XTENSA) #define PROCESSOR_NAME "xtensa" +#elif defined(CONFIG_SPARC) +#define PROCESSOR_NAME "sparc" #endif #ifndef PROCESSOR_NAME diff --git a/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c b/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c index a42e2f4022f..13de45f02a9 100644 --- a/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c @@ -33,6 +33,11 @@ #include #endif +#ifdef CONFIG_MCUMGR_GRP_OS_DATETIME +#include +#include +#endif + #if defined(CONFIG_MCUMGR_GRP_OS_INFO) || defined(CONFIG_MCUMGR_GRP_OS_BOOTLOADER_INFO) #include #include @@ -78,6 +83,52 @@ struct thread_iterator_info { }; #endif +#ifdef CONFIG_MCUMGR_GRP_OS_DATETIME +/* Iterator for extracting values from the provided datetime string, min and max values are + * checked against the provided value, then the offset is added after. If the value is not + * within the min and max values, the set operation will be aborted. + */ +struct datetime_parser { + int *value; + int min_value; + int max_value; + int offset; +}; + +/* RTC device alias to use for datetime functions, "rtc" */ +#define RTC_DEVICE DEVICE_DT_GET(DT_ALIAS(rtc)) + +#define RTC_DATETIME_YEAR_OFFSET 1900 +#define RTC_DATETIME_MONTH_OFFSET 1 +#define RTC_DATETIME_NUMERIC_BASE 10 +#define RTC_DATETIME_MS_TO_NS 1000000 +#define RTC_DATETIME_YEAR_MIN 1900 +#define RTC_DATETIME_YEAR_MAX 11899 +#define RTC_DATETIME_MONTH_MIN 1 +#define RTC_DATETIME_MONTH_MAX 12 +#define RTC_DATETIME_DAY_MIN 1 +#define RTC_DATETIME_DAY_MAX 31 +#define RTC_DATETIME_HOUR_MIN 0 +#define RTC_DATETIME_HOUR_MAX 23 +#define RTC_DATETIME_MINUTE_MIN 0 +#define RTC_DATETIME_MINUTE_MAX 59 +#define RTC_DATETIME_SECOND_MIN 0 +#define RTC_DATETIME_SECOND_MAX 59 +#define RTC_DATETIME_MILLISECOND_MIN 0 +#define RTC_DATETIME_MILLISECOND_MAX 999 + +/* Size used for datetime creation buffer */ +#ifdef CONFIG_MCUMGR_GRP_OS_DATETIME_MS +#define RTC_DATETIME_STRING_SIZE 32 +#else +#define RTC_DATETIME_STRING_SIZE 26 +#endif + +/* Minimum/maximum size of a datetime string that a client can provide */ +#define RTC_DATETIME_MIN_STRING_SIZE 19 +#define RTC_DATETIME_MAX_STRING_SIZE 26 +#endif + /* Specifies what the "all" ('a') of info parameter shows */ #define OS_MGMT_INFO_FORMAT_ALL \ OS_MGMT_INFO_FORMAT_KERNEL_NAME | OS_MGMT_INFO_FORMAT_NODE_NAME | \ @@ -744,6 +795,210 @@ static int os_mgmt_info(struct smp_streamer *ctxt) } #endif +#ifdef CONFIG_MCUMGR_GRP_OS_DATETIME +/** + * Command handler: os datetime get + */ +static int os_mgmt_datetime_read(struct smp_streamer *ctxt) +{ + zcbor_state_t *zse = ctxt->writer->zs; + struct rtc_time current_time; + char date_string[RTC_DATETIME_STRING_SIZE]; + int rc; + bool ok; + +#if defined(CONFIG_MCUMGR_GRP_OS_DATETIME_HOOK) + enum mgmt_cb_return status; + int32_t err_rc; + uint16_t err_group; + + status = mgmt_callback_notify(MGMT_EVT_OP_OS_MGMT_DATETIME_GET, NULL, 0, &err_rc, + &err_group); + + if (status != MGMT_CB_OK) { + if (status == MGMT_CB_ERROR_RC) { + return err_rc; + } + + ok = smp_add_cmd_err(zse, err_group, (uint16_t)err_rc); + return ok ? MGMT_ERR_EOK : MGMT_ERR_EMSGSIZE; + } +#endif + + rc = rtc_get_time(RTC_DEVICE, ¤t_time); + + if (rc == -ENODATA) { + /* RTC not set */ + ok = smp_add_cmd_err(zse, MGMT_GROUP_ID_OS, OS_MGMT_ERR_RTC_NOT_SET); + goto finished; + } else if (rc != 0) { + /* Other RTC error */ + ok = smp_add_cmd_err(zse, MGMT_GROUP_ID_OS, OS_MGMT_ERR_RTC_COMMAND_FAILED); + goto finished; + } + + sprintf(date_string, "%4d-%02d-%02dT%02d:%02d:%02d" +#ifdef CONFIG_MCUMGR_GRP_OS_DATETIME_MS + ".%d" +#endif + , (uint16_t)(current_time.tm_year + RTC_DATETIME_YEAR_OFFSET), + (uint8_t)(current_time.tm_mon + RTC_DATETIME_MONTH_OFFSET), + (uint8_t)current_time.tm_mday, (uint8_t)current_time.tm_hour, + (uint8_t)current_time.tm_min, (uint8_t)current_time.tm_sec +#ifdef CONFIG_MCUMGR_GRP_OS_DATETIME_MS + , (uint16_t)(current_time.tm_nsec / RTC_DATETIME_MS_TO_NS) +#endif + ); + + ok = zcbor_tstr_put_lit(zse, "datetime") && + zcbor_tstr_encode_ptr(zse, date_string, strlen(date_string)); + +finished: + return ok ? MGMT_ERR_EOK : MGMT_ERR_EMSGSIZE; +} + +/** + * Command handler: os datetime set + */ +static int os_mgmt_datetime_write(struct smp_streamer *ctxt) +{ + zcbor_state_t *zsd = ctxt->reader->zs; + zcbor_state_t *zse = ctxt->writer->zs; + size_t decoded; + struct zcbor_string datetime = { 0 }; + int rc; + uint8_t i = 0; + bool ok = true; + char *pos; + char *new_pos; + char date_string[RTC_DATETIME_MAX_STRING_SIZE]; + struct rtc_time new_time = { + .tm_wday = -1, + .tm_yday = -1, + .tm_isdst = -1, + .tm_nsec = 0, + }; + struct datetime_parser parser[] = { + { + .value = &new_time.tm_year, + .min_value = RTC_DATETIME_YEAR_MIN, + .max_value = RTC_DATETIME_YEAR_MAX, + .offset = -RTC_DATETIME_YEAR_OFFSET, + }, + { + .value = &new_time.tm_mon, + .min_value = RTC_DATETIME_MONTH_MIN, + .max_value = RTC_DATETIME_MONTH_MAX, + .offset = -RTC_DATETIME_MONTH_OFFSET, + }, + { + .value = &new_time.tm_mday, + .min_value = RTC_DATETIME_DAY_MIN, + .max_value = RTC_DATETIME_DAY_MAX, + }, + { + .value = &new_time.tm_hour, + .min_value = RTC_DATETIME_HOUR_MIN, + .max_value = RTC_DATETIME_HOUR_MAX, + }, + { + .value = &new_time.tm_min, + .min_value = RTC_DATETIME_MINUTE_MIN, + .max_value = RTC_DATETIME_MINUTE_MAX, + }, + { + .value = &new_time.tm_sec, + .min_value = RTC_DATETIME_SECOND_MIN, + .max_value = RTC_DATETIME_SECOND_MAX, + }, + }; + +#if defined(CONFIG_MCUMGR_GRP_OS_DATETIME_HOOK) + enum mgmt_cb_return status; + int32_t err_rc; + uint16_t err_group; +#endif + + struct zcbor_map_decode_key_val datetime_decode[] = { + ZCBOR_MAP_DECODE_KEY_DECODER("datetime", zcbor_tstr_decode, &datetime), + }; + + if (zcbor_map_decode_bulk(zsd, datetime_decode, ARRAY_SIZE(datetime_decode), &decoded)) { + return MGMT_ERR_EINVAL; + } else if (datetime.len < RTC_DATETIME_MIN_STRING_SIZE || + datetime.len >= RTC_DATETIME_MAX_STRING_SIZE) { + return MGMT_ERR_EINVAL; + } + + memcpy(date_string, datetime.value, datetime.len); + date_string[datetime.len] = '\0'; + + pos = date_string; + + while (i < ARRAY_SIZE(parser)) { + if (pos == (date_string + datetime.len)) { + /* Encountered end of string early, this is invalid */ + return MGMT_ERR_EINVAL; + } + + *parser[i].value = strtol(pos, &new_pos, RTC_DATETIME_NUMERIC_BASE); + + if (pos == new_pos) { + /* Missing or unable to convert field */ + return MGMT_ERR_EINVAL; + } + + if (*parser[i].value < parser[i].min_value || + *parser[i].value > parser[i].max_value) { + /* Value is not within the allowed bounds of this field */ + return MGMT_ERR_EINVAL; + } + + *parser[i].value += parser[i].offset; + + /* Skip a character as there is always a delimiter between the fields */ + ++i; + pos = new_pos + 1; + } + +#ifdef CONFIG_MCUMGR_GRP_OS_DATETIME_MS + if (*(pos - 1) == '.' && *pos != '\0') { + /* Provided value has a ms value, extract it */ + new_time.tm_nsec = strtol(pos, &new_pos, RTC_DATETIME_NUMERIC_BASE); + + if (new_time.tm_nsec < RTC_DATETIME_MILLISECOND_MIN || + new_time.tm_nsec > RTC_DATETIME_MILLISECOND_MAX) { + return MGMT_ERR_EINVAL; + } + + new_time.tm_nsec *= RTC_DATETIME_MS_TO_NS; + } +#endif + +#if defined(CONFIG_MCUMGR_GRP_OS_DATETIME_HOOK) + status = mgmt_callback_notify(MGMT_EVT_OP_OS_MGMT_DATETIME_SET, &new_time, + sizeof(new_time), &err_rc, &err_group); + + if (status != MGMT_CB_OK) { + if (status == MGMT_CB_ERROR_RC) { + return err_rc; + } + + ok = smp_add_cmd_err(zse, err_group, (uint16_t)err_rc); + return ok ? MGMT_ERR_EOK : MGMT_ERR_EMSGSIZE; + } +#endif + + rc = rtc_set_time(RTC_DEVICE, &new_time); + + if (rc != 0) { + ok = smp_add_cmd_err(zse, MGMT_GROUP_ID_OS, OS_MGMT_ERR_RTC_COMMAND_FAILED); + } + + return ok ? MGMT_ERR_EOK : MGMT_ERR_EMSGSIZE; +} +#endif + #ifdef CONFIG_MCUMGR_SMP_SUPPORT_ORIGINAL_PROTOCOL /* * @brief Translate OS mgmt group error code into MCUmgr error code @@ -761,7 +1016,13 @@ static int os_mgmt_translate_error_code(uint16_t err) rc = MGMT_ERR_EINVAL; break; + case OS_MGMT_ERR_QUERY_YIELDS_NO_ANSWER: + case OS_MGMT_ERR_RTC_NOT_SET: + rc = MGMT_ERR_ENOENT; + break; + case OS_MGMT_ERR_UNKNOWN: + case OS_MGMT_ERR_RTC_COMMAND_FAILED: default: rc = MGMT_ERR_EUNKNOWN; } @@ -781,6 +1042,13 @@ static const struct mgmt_handler os_mgmt_group_handlers[] = { os_mgmt_taskstat_read, NULL }, #endif + +#ifdef CONFIG_MCUMGR_GRP_OS_DATETIME + [OS_MGMT_ID_DATETIME_STR] = { + os_mgmt_datetime_read, os_mgmt_datetime_write + }, +#endif + #ifdef CONFIG_REBOOT [OS_MGMT_ID_RESET] = { NULL, os_mgmt_reset diff --git a/subsys/mgmt/mcumgr/grp/settings_mgmt/src/settings_mgmt.c b/subsys/mgmt/mcumgr/grp/settings_mgmt/src/settings_mgmt.c index e5fdcf00d41..bafab97db7c 100644 --- a/subsys/mgmt/mcumgr/grp/settings_mgmt/src/settings_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/settings_mgmt/src/settings_mgmt.c @@ -120,6 +120,8 @@ static int settings_mgmt_read(struct smp_streamer *ctxt) if (rc < 0) { if (rc == -EINVAL) { + rc = SETTINGS_MGMT_ERR_ROOT_KEY_NOT_FOUND; + } else if (rc == -ENOENT) { rc = SETTINGS_MGMT_ERR_KEY_NOT_FOUND; } else if (rc == -ENOTSUP) { rc = SETTINGS_MGMT_ERR_READ_NOT_SUPPORTED; @@ -231,7 +233,11 @@ static int settings_mgmt_write(struct smp_streamer *ctxt) if (rc < 0) { if (rc == -EINVAL) { + rc = SETTINGS_MGMT_ERR_ROOT_KEY_NOT_FOUND; + } else if (rc == -ENOENT) { rc = SETTINGS_MGMT_ERR_KEY_NOT_FOUND; + } else if (rc == -ENOTSUP) { + rc = SETTINGS_MGMT_ERR_WRITE_NOT_SUPPORTED; } else { rc = SETTINGS_MGMT_ERR_UNKNOWN; } @@ -329,8 +335,12 @@ static int settings_mgmt_delete(struct smp_streamer *ctxt) #endif if (rc < 0) { - if (rc == -ENOENT) { + if (rc == -EINVAL) { + rc = SETTINGS_MGMT_ERR_ROOT_KEY_NOT_FOUND; + } else if (rc == -ENOENT) { rc = SETTINGS_MGMT_ERR_KEY_NOT_FOUND; + } else if (rc == -ENOTSUP) { + rc = SETTINGS_MGMT_ERR_DELETE_NOT_SUPPORTED; } else { rc = SETTINGS_MGMT_ERR_UNKNOWN; } diff --git a/subsys/mgmt/mcumgr/mgmt/Kconfig b/subsys/mgmt/mcumgr/mgmt/Kconfig index d1701627860..a0c889f0c5e 100644 --- a/subsys/mgmt/mcumgr/mgmt/Kconfig +++ b/subsys/mgmt/mcumgr/mgmt/Kconfig @@ -25,3 +25,9 @@ config MCUMGR_MGMT_NOTIFICATION_HOOKS or decline the current operation, by returning false this will signal to the calling function that the request should be denied, for informal-only notifications or acceptable, true must be returned by all the registered notification handlers. + +config MCUMGR_MGMT_HANDLER_USER_DATA + bool "MCUmgr mgmt handler user data support" + help + This will add an extra field to the struct mgmt_handler that will allow a user + to pass user_data when the defined handler is called. diff --git a/subsys/mgmt/mcumgr/mgmt/src/mgmt.c b/subsys/mgmt/mcumgr/mgmt/src/mgmt.c index 4121a6f9262..56dcbb0254d 100644 --- a/subsys/mgmt/mcumgr/mgmt/src/mgmt.c +++ b/subsys/mgmt/mcumgr/mgmt/src/mgmt.c @@ -69,6 +69,29 @@ mgmt_find_handler(uint16_t group_id, uint16_t command_id) return &group->mg_handlers[command_id]; } +const struct mgmt_group * +mgmt_find_group(uint16_t group_id) +{ + struct mgmt_group *group = NULL; + sys_snode_t *snp, *sns; + + /* + * Find the group with the specified group id + * from the registered group list, if one exists + * return the matching mgmt group pointer, otherwise return NULL + */ + SYS_SLIST_FOR_EACH_NODE_SAFE(&mgmt_group_list, snp, sns) { + struct mgmt_group *loop_group = + CONTAINER_OF(snp, struct mgmt_group, node); + if (loop_group->mg_group_id == group_id) { + group = loop_group; + break; + } + } + + return group; +} + #if IS_ENABLED(CONFIG_MCUMGR_SMP_SUPPORT_ORIGINAL_PROTOCOL) smp_translate_error_fn mgmt_find_error_translation_function(uint16_t group_id) { diff --git a/subsys/mgmt/mcumgr/transport/Kconfig b/subsys/mgmt/mcumgr/transport/Kconfig index a966b943a9c..3d99fb33ccf 100644 --- a/subsys/mgmt/mcumgr/transport/Kconfig +++ b/subsys/mgmt/mcumgr/transport/Kconfig @@ -48,19 +48,26 @@ config MCUMGR_TRANSPORT_NETBUF_SIZE In case when MCUMGR_TRANSPORT_SHELL is enabled this value should be set to at least MCUMGR_GRP_SHELL_BACKEND_DUMMY_BUF_SIZE + 32. -config MCUMGR_TRANSPORT_NETBUF_USER_DATA_SIZE - int "Size of mcumgr buffer user data" - default 24 if MCUMGR_TRANSPORT_UDP && MCUMGR_TRANSPORT_UDP_IPV6 +config MCUMGR_TRANSPORT_NETBUF_MIN_USER_DATA_SIZE + int + default 24 if MCUMGR_TRANSPORT_UDP && NET_IPV6 default 8 if MCUMGR_TRANSPORT_UDP && MCUMGR_TRANSPORT_UDP_IPV4 default 8 if MCUMGR_TRANSPORT_BT default 4 + help + Hidden option to determine minimum user data size. + +config MCUMGR_TRANSPORT_NETBUF_USER_DATA_SIZE + int "Size of mcumgr buffer user data" + range MCUMGR_TRANSPORT_NETBUF_MIN_USER_DATA_SIZE 128 + default MCUMGR_TRANSPORT_NETBUF_MIN_USER_DATA_SIZE help The size, in bytes, of user data to allocate for each mcumgr buffer. Different mcumgr transports impose different requirements for this setting. A value of 4 is sufficient for UART and shell, a value of 8 is sufficient for Bluetooth. For UDP, the userdata must be large - enough to hold a IPv4/IPv6 address. + enough to hold IPv4/IPv6 addresses. module = MCUMGR_TRANSPORT module-str = mcumgr_transport diff --git a/subsys/mgmt/mcumgr/transport/Kconfig.shell b/subsys/mgmt/mcumgr/transport/Kconfig.shell index 1dea00d4156..8198b0ebda6 100644 --- a/subsys/mgmt/mcumgr/transport/Kconfig.shell +++ b/subsys/mgmt/mcumgr/transport/Kconfig.shell @@ -13,6 +13,7 @@ menuconfig MCUMGR_TRANSPORT_SHELL bool "Shell mcumgr SMP transport" depends on SHELL depends on BASE64 + depends on CRC help Enables handling of SMP commands received over shell. This allows the shell to be use for both mcumgr commands and shell commands. diff --git a/subsys/mgmt/mcumgr/transport/Kconfig.uart b/subsys/mgmt/mcumgr/transport/Kconfig.uart index 4421edce4ce..e5d2bd697cc 100644 --- a/subsys/mgmt/mcumgr/transport/Kconfig.uart +++ b/subsys/mgmt/mcumgr/transport/Kconfig.uart @@ -13,6 +13,7 @@ menuconfig MCUMGR_TRANSPORT_UART bool "UART mcumgr SMP transport" depends on CONSOLE depends on BASE64 + depends on CRC select UART_MCUMGR help Enables handling of SMP commands received over UART. This is a diff --git a/subsys/mgmt/mcumgr/transport/src/smp_bt.c b/subsys/mgmt/mcumgr/transport/src/smp_bt.c index f2aa3eaf542..85377a12e2a 100644 --- a/subsys/mgmt/mcumgr/transport/src/smp_bt.c +++ b/subsys/mgmt/mcumgr/transport/src/smp_bt.c @@ -675,7 +675,7 @@ static void smp_bt_setup(void) if (rc == 0) { smp_client_transport.smpt = &smp_bt_transport; smp_client_transport.smpt_type = SMP_BLUETOOTH_TRANSPORT; - rc = smp_client_transport_register(&smp_client_transport); + smp_client_transport_register(&smp_client_transport); } #endif diff --git a/subsys/mgmt/mcumgr/transport/src/smp_dummy.c b/subsys/mgmt/mcumgr/transport/src/smp_dummy.c index fc34fb05939..e0033cc0d2c 100644 --- a/subsys/mgmt/mcumgr/transport/src/smp_dummy.c +++ b/subsys/mgmt/mcumgr/transport/src/smp_dummy.c @@ -65,7 +65,7 @@ static struct net_buf *mcumgr_dummy_process_frag( static struct net_buf *mcumgr_dummy_process_frag_outgoing( struct mcumgr_serial_rx_ctxt *tx_ctxt, - const uint8_t *frag, int frag_len); + const uint8_t *frag, uint16_t frag_len); static int mcumgr_dummy_tx_pkt(const uint8_t *data, int len, mcumgr_serial_tx_cb cb); @@ -113,7 +113,7 @@ static void smp_dummy_process_frag(struct uart_mcumgr_rx_buf *rx_buf) * used in tests */ static struct net_buf *smp_dummy_process_frag_outgoing(uint8_t *buffer, - uint8_t buffer_size) + uint16_t buffer_size) { struct net_buf *nb; @@ -441,7 +441,7 @@ static struct net_buf *mcumgr_dummy_process_frag( */ static struct net_buf *mcumgr_dummy_process_frag_outgoing( struct mcumgr_serial_rx_ctxt *tx_ctxt, - const uint8_t *frag, int frag_len) + const uint8_t *frag, uint16_t frag_len) { struct net_buf *nb; uint16_t crc; diff --git a/subsys/mgmt/mcumgr/transport/src/smp_shell.c b/subsys/mgmt/mcumgr/transport/src/smp_shell.c index c30874070ba..527ab2e47fa 100644 --- a/subsys/mgmt/mcumgr/transport/src/smp_shell.c +++ b/subsys/mgmt/mcumgr/transport/src/smp_shell.c @@ -59,13 +59,10 @@ enum smp_shell_mcumgr_state { }; #ifdef CONFIG_MCUMGR_TRANSPORT_SHELL_INPUT_TIMEOUT -extern struct shell_transport shell_transport_uart; - static void smp_shell_input_timeout_handler(struct k_timer *timer) { ARG_UNUSED(timer); - struct shell_uart *sh_uart = (struct shell_uart *)shell_transport_uart.ctx; - struct smp_shell_data *const data = &sh_uart->ctrl_blk->smp; + struct smp_shell_data *const data = shell_uart_smp_shell_data_get_ptr(); atomic_clear_bit(&data->esc_state, ESC_MCUMGR_PKT_1); atomic_clear_bit(&data->esc_state, ESC_MCUMGR_PKT_2); @@ -213,13 +210,11 @@ static uint16_t smp_shell_get_mtu(const struct net_buf *nb) static int smp_shell_tx_raw(const void *data, int len) { - const struct shell *const sh = shell_backend_uart_get_ptr(); - const struct shell_uart *const su = sh->iface->ctx; - const struct shell_uart_ctrl_blk *const scb = su->ctrl_blk; + static const struct device *const sh_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_shell_uart)); const uint8_t *out = data; while ((out != NULL) && (len != 0)) { - uart_poll_out(scb->dev, *out); + uart_poll_out(sh_dev, *out); ++out; --len; } diff --git a/subsys/mgmt/mcumgr/transport/src/smp_udp.c b/subsys/mgmt/mcumgr/transport/src/smp_udp.c index 2da48563672..f103ba91249 100644 --- a/subsys/mgmt/mcumgr/transport/src/smp_udp.c +++ b/subsys/mgmt/mcumgr/transport/src/smp_udp.c @@ -42,6 +42,9 @@ BUILD_ASSERT(0, "Either IPv4 or IPv6 SMP must be enabled for the MCUmgr UDP SMP "CONFIG_MCUMGR_TRANSPORT_UDP_IPV4 or CONFIG_MCUMGR_TRANSPORT_UDP_IPV6"); #endif +BUILD_ASSERT(sizeof(struct sockaddr) <= CONFIG_MCUMGR_TRANSPORT_NETBUF_USER_DATA_SIZE, + "CONFIG_MCUMGR_TRANSPORT_NETBUF_USER_DATA_SIZE must be >= sizeof(struct sockaddr)"); + #define IS_THREAD_RUNNING(thread) \ (thread.base.thread_state & (_THREAD_PENDING | \ _THREAD_PRESTART | \ @@ -78,20 +81,7 @@ struct configs { #endif }; -static struct configs configs = { -#ifdef CONFIG_MCUMGR_TRANSPORT_UDP_IPV4 - .ipv4 = { - .proto = PROTOCOL_IPV4, - .sock = -1, - }, -#endif -#ifdef CONFIG_MCUMGR_TRANSPORT_UDP_IPV6 - .ipv6 = { - .proto = PROTOCOL_IPV6, - .sock = -1, - }, -#endif -}; +static struct configs smp_udp_configs; static struct net_mgmt_event_callback smp_udp_mgmt_cb; @@ -118,7 +108,7 @@ static int smp_udp4_tx(struct net_buf *nb) int ret; struct sockaddr *addr = net_buf_user_data(nb); - ret = sendto(configs.ipv4.sock, nb->data, nb->len, 0, addr, sizeof(*addr)); + ret = sendto(smp_udp_configs.ipv4.sock, nb->data, nb->len, 0, addr, sizeof(*addr)); if (ret < 0) { ret = MGMT_ERR_EINVAL; @@ -138,7 +128,7 @@ static int smp_udp6_tx(struct net_buf *nb) int ret; struct sockaddr *addr = net_buf_user_data(nb); - ret = sendto(configs.ipv6.sock, nb->data, nb->len, 0, addr, sizeof(*addr)); + ret = sendto(smp_udp_configs.ipv6.sock, nb->data, nb->len, 0, addr, sizeof(*addr)); if (ret < 0) { ret = MGMT_ERR_EINVAL; @@ -285,14 +275,14 @@ static void smp_udp_net_event_handler(struct net_mgmt_event_callback *cb, uint32 if (mgmt_event == NET_EVENT_L4_CONNECTED) { LOG_INF("Network connected"); #ifdef CONFIG_MCUMGR_TRANSPORT_UDP_IPV4 - if (IS_THREAD_RUNNING(configs.ipv4.thread)) { - k_sem_give(&configs.ipv4.network_ready_sem); + if (IS_THREAD_RUNNING(smp_udp_configs.ipv4.thread)) { + k_sem_give(&smp_udp_configs.ipv4.network_ready_sem); } #endif #ifdef CONFIG_MCUMGR_TRANSPORT_UDP_IPV6 - if (IS_THREAD_RUNNING(configs.ipv6.thread)) { - k_sem_give(&configs.ipv6.network_ready_sem); + if (IS_THREAD_RUNNING(smp_udp_configs.ipv6.thread)) { + k_sem_give(&smp_udp_configs.ipv6.network_ready_sem); } #endif } else if (mgmt_event == NET_EVENT_L4_DISCONNECTED) { @@ -316,9 +306,9 @@ int smp_udp_open(void) bool started = false; #ifdef CONFIG_MCUMGR_TRANSPORT_UDP_IPV4 - if (!IS_THREAD_RUNNING(configs.ipv4.thread)) { - (void)k_sem_reset(&configs.ipv4.network_ready_sem); - create_thread(&configs.ipv4, "smp_udp4"); + if (!IS_THREAD_RUNNING(smp_udp_configs.ipv4.thread)) { + (void)k_sem_reset(&smp_udp_configs.ipv4.network_ready_sem); + create_thread(&smp_udp_configs.ipv4, "smp_udp4"); started = true; } else { LOG_ERR("IPv4 UDP MCUmgr thread is already running"); @@ -326,9 +316,9 @@ int smp_udp_open(void) #endif #ifdef CONFIG_MCUMGR_TRANSPORT_UDP_IPV6 - if (!IS_THREAD_RUNNING(configs.ipv6.thread)) { - (void)k_sem_reset(&configs.ipv6.network_ready_sem); - create_thread(&configs.ipv6, "smp_udp6"); + if (!IS_THREAD_RUNNING(smp_udp_configs.ipv6.thread)) { + (void)k_sem_reset(&smp_udp_configs.ipv6.network_ready_sem); + create_thread(&smp_udp_configs.ipv6, "smp_udp6"); started = true; } else { LOG_ERR("IPv6 UDP MCUmgr thread is already running"); @@ -346,12 +336,12 @@ int smp_udp_open(void) int smp_udp_close(void) { #ifdef CONFIG_MCUMGR_TRANSPORT_UDP_IPV4 - if (IS_THREAD_RUNNING(configs.ipv4.thread)) { - k_thread_abort(&(configs.ipv4.thread)); + if (IS_THREAD_RUNNING(smp_udp_configs.ipv4.thread)) { + k_thread_abort(&(smp_udp_configs.ipv4.thread)); - if (configs.ipv4.sock >= 0) { - close(configs.ipv4.sock); - configs.ipv4.sock = -1; + if (smp_udp_configs.ipv4.sock >= 0) { + close(smp_udp_configs.ipv4.sock); + smp_udp_configs.ipv4.sock = -1; } } else { LOG_ERR("IPv4 UDP MCUmgr thread is not running"); @@ -359,12 +349,12 @@ int smp_udp_close(void) #endif #ifdef CONFIG_MCUMGR_TRANSPORT_UDP_IPV6 - if (IS_THREAD_RUNNING(configs.ipv6.thread)) { - k_thread_abort(&(configs.ipv6.thread)); + if (IS_THREAD_RUNNING(smp_udp_configs.ipv6.thread)) { + k_thread_abort(&(smp_udp_configs.ipv6.thread)); - if (configs.ipv6.sock >= 0) { - close(configs.ipv6.sock); - configs.ipv6.sock = -1; + if (smp_udp_configs.ipv6.sock >= 0) { + close(smp_udp_configs.ipv6.sock); + smp_udp_configs.ipv6.sock = -1; } } else { LOG_ERR("IPv6 UDP MCUmgr thread is not running"); @@ -379,17 +369,20 @@ static void smp_udp_start(void) int rc; #ifdef CONFIG_MCUMGR_TRANSPORT_UDP_IPV4 - k_sem_init(&configs.ipv4.network_ready_sem, 0, 1); - configs.ipv4.smp_transport.functions.output = smp_udp4_tx; - configs.ipv4.smp_transport.functions.get_mtu = smp_udp_get_mtu; - configs.ipv4.smp_transport.functions.ud_copy = smp_udp_ud_copy; + smp_udp_configs.ipv4.proto = PROTOCOL_IPV4; + smp_udp_configs.ipv4.sock = -1; - rc = smp_transport_init(&configs.ipv4.smp_transport); + k_sem_init(&smp_udp_configs.ipv4.network_ready_sem, 0, 1); + smp_udp_configs.ipv4.smp_transport.functions.output = smp_udp4_tx; + smp_udp_configs.ipv4.smp_transport.functions.get_mtu = smp_udp_get_mtu; + smp_udp_configs.ipv4.smp_transport.functions.ud_copy = smp_udp_ud_copy; + + rc = smp_transport_init(&smp_udp_configs.ipv4.smp_transport); #ifdef CONFIG_SMP_CLIENT if (rc == 0) { - configs.ipv4_transport.smpt = &configs.ipv4.smp_transport; - configs.ipv4_transport.smpt_type = SMP_UDP_IPV4_TRANSPORT; - smp_client_transport_register(&configs.ipv4_transport); + smp_udp_configs.ipv4_transport.smpt = &smp_udp_configs.ipv4.smp_transport; + smp_udp_configs.ipv4_transport.smpt_type = SMP_UDP_IPV4_TRANSPORT; + smp_client_transport_register(&smp_udp_configs.ipv4_transport); } #endif if (rc) { @@ -398,17 +391,20 @@ static void smp_udp_start(void) #endif #ifdef CONFIG_MCUMGR_TRANSPORT_UDP_IPV6 - k_sem_init(&configs.ipv6.network_ready_sem, 0, 1); - configs.ipv6.smp_transport.functions.output = smp_udp6_tx; - configs.ipv6.smp_transport.functions.get_mtu = smp_udp_get_mtu; - configs.ipv6.smp_transport.functions.ud_copy = smp_udp_ud_copy; + smp_udp_configs.ipv6.proto = PROTOCOL_IPV6; + smp_udp_configs.ipv6.sock = -1; + + k_sem_init(&smp_udp_configs.ipv6.network_ready_sem, 0, 1); + smp_udp_configs.ipv6.smp_transport.functions.output = smp_udp6_tx; + smp_udp_configs.ipv6.smp_transport.functions.get_mtu = smp_udp_get_mtu; + smp_udp_configs.ipv6.smp_transport.functions.ud_copy = smp_udp_ud_copy; - rc = smp_transport_init(&configs.ipv6.smp_transport); + rc = smp_transport_init(&smp_udp_configs.ipv6.smp_transport); #ifdef CONFIG_SMP_CLIENT if (rc == 0) { - configs.ipv6_transport.smpt = &configs.ipv6.smp_transport; - configs.ipv6_transport.smpt_type = SMP_UDP_IPV6_TRANSPORT; - smp_client_transport_register(&configs.ipv6_transport); + smp_udp_configs.ipv6_transport.smpt = &smp_udp_configs.ipv6.smp_transport; + smp_udp_configs.ipv6_transport.smpt_type = SMP_UDP_IPV6_TRANSPORT; + smp_client_transport_register(&smp_udp_configs.ipv6_transport); } #endif diff --git a/subsys/mgmt/osdp/Kconfig b/subsys/mgmt/osdp/Kconfig index 8fee4185189..c04abbc6df6 100644 --- a/subsys/mgmt/osdp/Kconfig +++ b/subsys/mgmt/osdp/Kconfig @@ -9,6 +9,7 @@ menuconfig OSDP select RING_BUFFER imply SERIAL_SUPPORT_INTERRUPT imply UART_INTERRUPT_DRIVEN + imply UART_USE_RUNTIME_CONFIGURE select CRC help Add support for Open Supervised Device Protocol (OSDP) @@ -70,7 +71,7 @@ config OSDP_SKIP_MARK_BYTE config OSDP_SC_ENABLED bool "OSDP Secure Channel" - depends on CSPRING_ENABLED + depends on CSPRNG_ENABLED default y select CRYPTO select CRYPTO_MBEDTLS_SHIM diff --git a/subsys/mgmt/osdp/src/osdp_common.c b/subsys/mgmt/osdp/src/osdp_common.c index 2898659bd09..2b0fcaf81c9 100644 --- a/subsys/mgmt/osdp/src/osdp_common.c +++ b/subsys/mgmt/osdp/src/osdp_common.c @@ -12,7 +12,7 @@ #ifdef CONFIG_OSDP_SC_ENABLED #include -#include +#include #endif #include "osdp_common.h" diff --git a/subsys/mgmt/updatehub/CMakeLists.txt b/subsys/mgmt/updatehub/CMakeLists.txt index b71f17fab1b..067e6168d97 100644 --- a/subsys/mgmt/updatehub/CMakeLists.txt +++ b/subsys/mgmt/updatehub/CMakeLists.txt @@ -23,3 +23,5 @@ zephyr_library_sources_ifdef(CONFIG_USERSPACE updatehub_handlers.c) zephyr_include_directories( ${ZEPHYR_BASE}/subsys/mgmt/updatehub/include ) + +zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS) diff --git a/subsys/mgmt/updatehub/updatehub_handlers.c b/subsys/mgmt/updatehub/updatehub_handlers.c index 33a0d4acac6..4d889731758 100644 --- a/subsys/mgmt/updatehub/updatehub_handlers.c +++ b/subsys/mgmt/updatehub/updatehub_handlers.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include diff --git a/subsys/modbus/Kconfig b/subsys/modbus/Kconfig index 614afdd8341..38c7d761c07 100644 --- a/subsys/modbus/Kconfig +++ b/subsys/modbus/Kconfig @@ -44,6 +44,7 @@ config MODBUS_SERIAL default y depends on SERIAL && SERIAL_HAS_DRIVER depends on DT_HAS_ZEPHYR_MODBUS_SERIAL_ENABLED + select UART_USE_RUNTIME_CONFIGURE help Enable Modbus over serial line support. diff --git a/subsys/modbus/modbus_core.c b/subsys/modbus/modbus_core.c index 617f5833a40..777887f2275 100644 --- a/subsys/modbus/modbus_core.c +++ b/subsys/modbus/modbus_core.c @@ -211,6 +211,14 @@ static struct modbus_context *modbus_init_iface(const uint8_t iface) return ctx; } +static int modbus_user_fc_init(struct modbus_context *ctx, struct modbus_iface_param param) +{ + sys_slist_init(&ctx->user_defined_cbs); + LOG_DBG("Initializing user-defined function code support."); + + return 0; +} + int modbus_init_server(const int iface, struct modbus_iface_param param) { struct modbus_context *ctx = NULL; @@ -236,6 +244,12 @@ int modbus_init_server(const int iface, struct modbus_iface_param param) ctx->client = false; + if (modbus_user_fc_init(ctx, param) != 0) { + LOG_ERR("Failed to init MODBUS user defined function codes"); + rc = -EINVAL; + goto init_server_error; + } + switch (param.mode) { case MODBUS_MODE_RTU: case MODBUS_MODE_ASCII: @@ -278,6 +292,28 @@ int modbus_init_server(const int iface, struct modbus_iface_param param) return rc; } +int modbus_register_user_fc(const int iface, struct modbus_custom_fc *custom_fc) +{ + struct modbus_context *ctx = modbus_get_context(iface); + + if (!custom_fc) { + LOG_ERR("Provided function code handler was NULL"); + return -EINVAL; + } + + if (custom_fc->fc & BIT(7)) { + LOG_ERR("Function codes must have MSB of 0"); + return -EINVAL; + } + + custom_fc->excep_code = MODBUS_EXC_NONE; + + LOG_DBG("Registered new custom function code %d", custom_fc->fc); + sys_slist_append(&ctx->user_defined_cbs, &custom_fc->node); + + return 0; +} + int modbus_init_client(const int iface, struct modbus_iface_param param) { struct modbus_context *ctx = NULL; diff --git a/subsys/modbus/modbus_internal.h b/subsys/modbus/modbus_internal.h index f271e08941c..080da58ea09 100644 --- a/subsys/modbus/modbus_internal.h +++ b/subsys/modbus/modbus_internal.h @@ -55,18 +55,6 @@ #define MODBUS_FC08_SUBF_SERVER_MSG_CTR 14 #define MODBUS_FC08_SUBF_SERVER_NO_RESP_CTR 15 -/* Modbus exception codes */ -#define MODBUS_EXC_NONE 0 -#define MODBUS_EXC_ILLEGAL_FC 1 -#define MODBUS_EXC_ILLEGAL_DATA_ADDR 2 -#define MODBUS_EXC_ILLEGAL_DATA_VAL 3 -#define MODBUS_EXC_SERVER_DEVICE_FAILURE 4 -#define MODBUS_EXC_ACK 5 -#define MODBUS_EXC_SERVER_DEVICE_BUSY 6 -#define MODBUS_EXC_MEM_PARITY_ERROR 8 -#define MODBUS_EXC_GW_PATH_UNAVAILABLE 10 -#define MODBUS_EXC_GW_TARGET_FAILED_TO_RESP 11 - /* Modbus RTU (ASCII) constants */ #define MODBUS_COIL_OFF_CODE 0x0000 #define MODBUS_COIL_ON_CODE 0xFF00 @@ -142,6 +130,8 @@ struct modbus_context { uint16_t mbs_server_msg_ctr; uint16_t mbs_noresp_ctr; #endif + /* A linked list of function code, handler pairs */ + sys_slist_t user_defined_cbs; /* Unit ID */ uint8_t unit_id; diff --git a/subsys/modbus/modbus_server.c b/subsys/modbus/modbus_server.c index 58a783864c6..4805526b2d6 100644 --- a/subsys/modbus/modbus_server.c +++ b/subsys/modbus/modbus_server.c @@ -926,6 +926,38 @@ static bool mbs_fc16_hregs_write(struct modbus_context *ctx) return true; } +static bool mbs_try_user_fc(struct modbus_context *ctx, uint8_t fc) +{ + struct modbus_custom_fc *p; + + LOG_DBG("Searching for custom Modbus handlers for code %u", fc); + + SYS_SLIST_FOR_EACH_CONTAINER(&ctx->user_defined_cbs, p, node) { + if (p->fc == fc) { + int iface = modbus_iface_get_by_ctx(ctx); + bool rval; + + LOG_DBG("Found custom handler"); + + p->excep_code = MODBUS_EXC_NONE; + rval = p->cb(iface, &ctx->rx_adu, &ctx->tx_adu, &p->excep_code, + p->user_data); + + if (p->excep_code != MODBUS_EXC_NONE) { + LOG_INF("Custom handler failed with code %d", p->excep_code); + mbs_exception_rsp(ctx, p->excep_code); + } + + return rval; + } + } + + LOG_ERR("Function code 0x%02x not implemented", fc); + mbs_exception_rsp(ctx, MODBUS_EXC_ILLEGAL_FC); + + return true; +} + bool modbus_server_handler(struct modbus_context *ctx) { bool send_reply = false; @@ -945,6 +977,7 @@ bool modbus_server_handler(struct modbus_context *ctx) } if (addr != 0 && addr != ctx->unit_id) { + LOG_DBG("Unit ID doesn't match %u != %u", addr, ctx->unit_id); update_noresp_ctr(ctx); return false; } @@ -995,10 +1028,7 @@ bool modbus_server_handler(struct modbus_context *ctx) break; default: - LOG_ERR("Function code 0x%02x not implemented", fc); - mbs_exception_rsp(ctx, MODBUS_EXC_ILLEGAL_FC); - send_reply = true; - break; + send_reply = mbs_try_user_fc(ctx, fc); } if (addr == 0) { diff --git a/subsys/modem/Kconfig b/subsys/modem/Kconfig index 7ad98d2b718..69c102a07ad 100644 --- a/subsys/modem/Kconfig +++ b/subsys/modem/Kconfig @@ -3,6 +3,7 @@ menuconfig MODEM_MODULES bool "Modem modules" + select EXPERIMENTAL if MODEM_MODULES @@ -26,6 +27,14 @@ config MODEM_CMUX select EVENTS select CRC +if MODEM_CMUX + +module = MODEM_CMUX +module-str = modem_cmux +source "subsys/logging/Kconfig.template.log_config" + +endif + config MODEM_PIPE bool "Modem pipe module" diff --git a/subsys/modem/backends/Kconfig b/subsys/modem/backends/Kconfig index f2b45d9285c..317f9d26aa8 100644 --- a/subsys/modem/backends/Kconfig +++ b/subsys/modem/backends/Kconfig @@ -9,6 +9,7 @@ config MODEM_BACKEND_TTY config MODEM_BACKEND_UART bool "Modem UART backend module" select MODEM_PIPE + select RING_BUFFER depends on UART_INTERRUPT_DRIVEN || UART_ASYNC_API if MODEM_BACKEND_UART @@ -21,4 +22,16 @@ config MODEM_BACKEND_UART_ASYNC bool "Modem UART backend module async implementation" default y if UART_ASYNC_API +if MODEM_BACKEND_UART_ASYNC + +config MODEM_BACKEND_UART_ASYNC_TRANSMIT_TIMEOUT_MS + int "Modem UART async transmit timeout in milliseconds" + default 100 + +config MODEM_BACKEND_UART_ASYNC_RECEIVE_IDLE_TIMEOUT_MS + int "Modem UART async receive idle timeout in milliseconds" + default 30 + +endif + endif # MODEM_BACKEND_UART diff --git a/subsys/modem/backends/modem_backend_uart.c b/subsys/modem/backends/modem_backend_uart.c index 91e062b8717..b4b0b81c291 100644 --- a/subsys/modem/backends/modem_backend_uart.c +++ b/subsys/modem/backends/modem_backend_uart.c @@ -36,18 +36,18 @@ struct modem_pipe *modem_backend_uart_init(struct modem_backend_uart *backend, backend->uart = config->uart; k_work_init(&backend->receive_ready_work, modem_backend_uart_receive_ready_handler); -#ifdef CONFIG_UART_ASYNC_API +#ifdef CONFIG_MODEM_BACKEND_UART_ASYNC if (modem_backend_uart_async_is_supported(backend)) { modem_backend_uart_async_init(backend, config); return &backend->pipe; } -#endif /* CONFIG_UART_ASYNC_API */ +#endif /* CONFIG_MODEM_BACKEND_UART_ASYNC */ -#ifdef CONFIG_UART_INTERRUPT_DRIVEN +#ifdef CONFIG_MODEM_BACKEND_UART_ISR modem_backend_uart_isr_init(backend, config); return &backend->pipe; -#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +#endif /* CONFIG_MODEM_BACKEND_UART_ISR */ __ASSERT(0, "No supported UART API"); diff --git a/subsys/modem/backends/modem_backend_uart_async.c b/subsys/modem/backends/modem_backend_uart_async.c index a10822a6ae5..bd18edbd2f5 100644 --- a/subsys/modem/backends/modem_backend_uart_async.c +++ b/subsys/modem/backends/modem_backend_uart_async.c @@ -13,46 +13,31 @@ LOG_MODULE_DECLARE(modem_backend_uart); #include #define MODEM_BACKEND_UART_ASYNC_STATE_TRANSMITTING_BIT (0) -#define MODEM_BACKEND_UART_ASYNC_STATE_RX_BUF0_USED_BIT (1) -#define MODEM_BACKEND_UART_ASYNC_STATE_RX_BUF1_USED_BIT (2) -#define MODEM_BACKEND_UART_ASYNC_STATE_RX_RBUF_USED_INDEX_BIT (3) +#define MODEM_BACKEND_UART_ASYNC_STATE_RECEIVING_BIT (1) +#define MODEM_BACKEND_UART_ASYNC_STATE_RX_BUF0_USED_BIT (2) +#define MODEM_BACKEND_UART_ASYNC_STATE_RX_BUF1_USED_BIT (3) -#define MODEM_BACKEND_UART_ASYNC_BLOCK_MIN_SIZE (8) - -static void modem_backend_uart_async_flush(struct modem_backend_uart *backend) +static bool modem_backend_uart_async_is_closed(struct modem_backend_uart *backend) { - uint8_t c; - - while (uart_fifo_read(backend->uart, &c, 1) > 0) { - continue; + if (!atomic_test_bit(&backend->async.state, + MODEM_BACKEND_UART_ASYNC_STATE_TRANSMITTING_BIT) && + !atomic_test_bit(&backend->async.state, + MODEM_BACKEND_UART_ASYNC_STATE_RECEIVING_BIT) && + !atomic_test_bit(&backend->async.state, + MODEM_BACKEND_UART_ASYNC_STATE_RX_BUF0_USED_BIT) && + !atomic_test_bit(&backend->async.state, + MODEM_BACKEND_UART_ASYNC_STATE_RX_BUF1_USED_BIT)) { + return true; } -} -static uint8_t modem_backend_uart_async_rx_rbuf_used_index(struct modem_backend_uart *backend) -{ - return atomic_test_bit(&backend->async.state, - MODEM_BACKEND_UART_ASYNC_STATE_RX_RBUF_USED_INDEX_BIT); -} - -static void modem_backend_uart_async_rx_rbuf_used_swap(struct modem_backend_uart *backend) -{ - uint8_t rx_rbuf_index = modem_backend_uart_async_rx_rbuf_used_index(backend); - - if (rx_rbuf_index) { - atomic_clear_bit(&backend->async.state, - MODEM_BACKEND_UART_ASYNC_STATE_RX_RBUF_USED_INDEX_BIT); - } else { - atomic_set_bit(&backend->async.state, - MODEM_BACKEND_UART_ASYNC_STATE_RX_RBUF_USED_INDEX_BIT); - } + return false; } static void modem_backend_uart_async_event_handler(const struct device *dev, struct uart_event *evt, void *user_data) { struct modem_backend_uart *backend = (struct modem_backend_uart *) user_data; - - uint8_t receive_rb_used_index; + k_spinlock_key_t key; uint32_t received; switch (evt->type) { @@ -62,6 +47,13 @@ static void modem_backend_uart_async_event_handler(const struct device *dev, break; + case UART_TX_ABORTED: + LOG_WRN("Transmit aborted"); + atomic_clear_bit(&backend->async.state, + MODEM_BACKEND_UART_ASYNC_STATE_TRANSMITTING_BIT); + + break; + case UART_RX_BUF_REQUEST: if (!atomic_test_and_set_bit(&backend->async.state, MODEM_BACKEND_UART_ASYNC_STATE_RX_BUF0_USED_BIT)) { @@ -101,27 +93,38 @@ static void modem_backend_uart_async_event_handler(const struct device *dev, break; case UART_RX_RDY: - receive_rb_used_index = modem_backend_uart_async_rx_rbuf_used_index(backend); - - received = ring_buf_put(&backend->async.receive_rdb[receive_rb_used_index], - &evt->data.rx.buf[evt->data.rx.offset], - evt->data.rx.len); + key = k_spin_lock(&backend->async.receive_rb_lock); + received = ring_buf_put(&backend->async.receive_rb, + &evt->data.rx.buf[evt->data.rx.offset], + evt->data.rx.len); if (received < evt->data.rx.len) { - ring_buf_reset(&backend->async.receive_rdb[receive_rb_used_index]); + ring_buf_reset(&backend->async.receive_rb); + k_spin_unlock(&backend->async.receive_rb_lock, key); LOG_WRN("Receive buffer overrun"); break; } + k_spin_unlock(&backend->async.receive_rb_lock, key); k_work_submit(&backend->receive_ready_work); break; - case UART_TX_ABORTED: - LOG_WRN("Transmit aborted"); + case UART_RX_DISABLED: + atomic_clear_bit(&backend->async.state, + MODEM_BACKEND_UART_ASYNC_STATE_RECEIVING_BIT); + break; + + case UART_RX_STOPPED: + LOG_WRN("Receive stopped for reasons: %u", (uint8_t)evt->data.rx_stop.reason); + break; default: break; } + + if (modem_backend_uart_async_is_closed(backend)) { + k_work_submit(&backend->async.rx_disabled_work); + } } static int modem_backend_uart_async_open(void *data) @@ -130,9 +133,7 @@ static int modem_backend_uart_async_open(void *data) int ret; atomic_set(&backend->async.state, 0); - modem_backend_uart_async_flush(backend); - ring_buf_reset(&backend->async.receive_rdb[0]); - ring_buf_reset(&backend->async.receive_rdb[1]); + ring_buf_reset(&backend->async.receive_rb); /* Reserve receive buffer 0 */ atomic_set_bit(&backend->async.state, @@ -143,12 +144,16 @@ static int modem_backend_uart_async_open(void *data) * used to store received data. */ ret = uart_rx_enable(backend->uart, backend->async.receive_bufs[0], - backend->async.receive_buf_size, 3000); + backend->async.receive_buf_size, + CONFIG_MODEM_BACKEND_UART_ASYNC_RECEIVE_IDLE_TIMEOUT_MS * 1000L); if (ret < 0) { return ret; } + atomic_set_bit(&backend->async.state, + MODEM_BACKEND_UART_ASYNC_STATE_RECEIVING_BIT); + modem_pipe_notify_opened(&backend->pipe); return 0; } @@ -176,7 +181,7 @@ static int modem_backend_uart_async_transmit(void *data, const uint8_t *buf, siz memcpy(backend->async.transmit_buf, buf, bytes_to_transmit); ret = uart_tx(backend->uart, backend->async.transmit_buf, bytes_to_transmit, - SYS_FOREVER_US); + CONFIG_MODEM_BACKEND_UART_ASYNC_TRANSMIT_TIMEOUT_MS * 1000L); if (ret < 0) { LOG_WRN("Failed to start async transmit"); @@ -189,29 +194,19 @@ static int modem_backend_uart_async_transmit(void *data, const uint8_t *buf, siz static int modem_backend_uart_async_receive(void *data, uint8_t *buf, size_t size) { struct modem_backend_uart *backend = (struct modem_backend_uart *)data; - + k_spinlock_key_t key; uint32_t received; - uint8_t receive_rdb_unused; - - received = 0; - receive_rdb_unused = modem_backend_uart_async_rx_rbuf_used_index(backend) ? 0 : 1; + bool empty; - /* Read data from unused ring double buffer first */ - received += ring_buf_get(&backend->async.receive_rdb[receive_rdb_unused], buf, size); + key = k_spin_lock(&backend->async.receive_rb_lock); + received = ring_buf_get(&backend->async.receive_rb, buf, size); + empty = ring_buf_is_empty(&backend->async.receive_rb); + k_spin_unlock(&backend->async.receive_rb_lock, key); - if (ring_buf_is_empty(&backend->async.receive_rdb[receive_rdb_unused]) == false) { - return (int)received; + if (!empty) { + k_work_submit(&backend->receive_ready_work); } - /* Swap receive ring double buffer */ - modem_backend_uart_async_rx_rbuf_used_swap(backend); - - /* Read data from previously used buffer */ - receive_rdb_unused = modem_backend_uart_async_rx_rbuf_used_index(backend) ? 0 : 1; - - received += ring_buf_get(&backend->async.receive_rdb[receive_rdb_unused], - &buf[received], (size - received)); - return (int)received; } @@ -219,8 +214,8 @@ static int modem_backend_uart_async_close(void *data) { struct modem_backend_uart *backend = (struct modem_backend_uart *)data; + uart_tx_abort(backend->uart); uart_rx_disable(backend->uart); - modem_pipe_notify_closed(&backend->pipe); return 0; } @@ -237,24 +232,33 @@ bool modem_backend_uart_async_is_supported(struct modem_backend_uart *backend) backend) == 0; } +static void modem_backend_uart_async_notify_closed(struct k_work *item) +{ + struct modem_backend_uart_async *async = + CONTAINER_OF(item, struct modem_backend_uart_async, rx_disabled_work); + + struct modem_backend_uart *backend = + CONTAINER_OF(async, struct modem_backend_uart, async); + + modem_pipe_notify_closed(&backend->pipe); +} + void modem_backend_uart_async_init(struct modem_backend_uart *backend, const struct modem_backend_uart_config *config) { uint32_t receive_buf_size_quarter = config->receive_buf_size / 4; - /* Split receive buffer into 4 buffers, use 2 parts for UART receive double buffer */ + /* Use half the receive buffer for UART receive buffers */ backend->async.receive_buf_size = receive_buf_size_quarter; backend->async.receive_bufs[0] = &config->receive_buf[0]; backend->async.receive_bufs[1] = &config->receive_buf[receive_buf_size_quarter]; - /* Use remaining 2 parts for receive double ring buffer */ - ring_buf_init(&backend->async.receive_rdb[0], receive_buf_size_quarter, + /* Use half the receive buffer for the received data ring buffer */ + ring_buf_init(&backend->async.receive_rb, (receive_buf_size_quarter * 2), &config->receive_buf[receive_buf_size_quarter * 2]); - ring_buf_init(&backend->async.receive_rdb[1], receive_buf_size_quarter, - &config->receive_buf[receive_buf_size_quarter * 3]); - backend->async.transmit_buf = config->transmit_buf; backend->async.transmit_buf_size = config->transmit_buf_size; + k_work_init(&backend->async.rx_disabled_work, modem_backend_uart_async_notify_closed); modem_pipe_init(&backend->pipe, backend, &modem_backend_uart_async_api); } diff --git a/subsys/modem/modem_chat.c b/subsys/modem/modem_chat.c index 27f958dc7b5..0ab1175f980 100644 --- a/subsys/modem/modem_chat.c +++ b/subsys/modem/modem_chat.c @@ -60,6 +60,10 @@ static void modem_chat_log_received_command(struct modem_chat *chat) static void modem_chat_script_stop(struct modem_chat *chat, enum modem_chat_script_result result) { + if (!chat || !chat->script) { + return; + } + /* Handle result */ if (result == MODEM_CHAT_SCRIPT_RESULT_SUCCESS) { LOG_DBG("%s: complete", chat->script->name); @@ -69,9 +73,6 @@ static void modem_chat_script_stop(struct modem_chat *chat, enum modem_chat_scri LOG_WRN("%s: timed out", chat->script->name); } - /* Clear script running state */ - atomic_clear_bit(&chat->script_state, MODEM_CHAT_SCRIPT_STATE_RUNNING_BIT); - /* Call back with result */ if (chat->script->callback != NULL) { chat->script->callback(chat, result, chat->user_data); @@ -88,6 +89,15 @@ static void modem_chat_script_stop(struct modem_chat *chat, enum modem_chat_scri /* Cancel timeout work */ k_work_cancel_delayable(&chat->script_timeout_work); + + /* Clear script running state */ + atomic_clear_bit(&chat->script_state, MODEM_CHAT_SCRIPT_STATE_RUNNING_BIT); + + /* Store result of script for script stoppted indication */ + chat->script_result = result; + + /* Indicate script stopped */ + k_sem_give(&chat->script_stopped_sem); } static void modem_chat_script_send(struct modem_chat *chat) @@ -129,8 +139,8 @@ static void modem_chat_script_next(struct modem_chat *chat, bool initial) chat->matches_size[MODEM_CHAT_MATCHES_INDEX_RESPONSE] = script_chat->response_matches_size; /* Check if work must be sent */ - if (strlen(script_chat->request) > 0) { - LOG_DBG("sending: %s", script_chat->request); + if (script_chat->request_size > 0) { + LOG_DBG("sending: %.*s", script_chat->request_size, script_chat->request); modem_chat_script_send(chat); } } @@ -190,18 +200,17 @@ static bool modem_chat_script_send_request(struct modem_chat *chat) const struct modem_chat_script_chat *script_chat = &chat->script->script_chats[chat->script_chat_it]; - uint16_t script_chat_request_size = strlen(script_chat->request); uint8_t *script_chat_request_start; uint16_t script_chat_request_remaining; int ret; /* Validate data to send */ - if (script_chat_request_size == chat->script_send_request_pos) { + if (script_chat->request_size == chat->script_send_request_pos) { return true; } script_chat_request_start = (uint8_t *)&script_chat->request[chat->script_send_request_pos]; - script_chat_request_remaining = script_chat_request_size - chat->script_send_request_pos; + script_chat_request_remaining = script_chat->request_size - chat->script_send_request_pos; /* Send data through pipe */ ret = modem_pipe_transmit(chat->pipe, script_chat_request_start, @@ -216,7 +225,7 @@ static bool modem_chat_script_send_request(struct modem_chat *chat) chat->script_send_request_pos += (uint16_t)ret; /* Check if data remains */ - if (chat->script_send_request_pos < script_chat_request_size) { + if (chat->script_send_request_pos < script_chat->request_size) { return false; } @@ -459,6 +468,11 @@ static void modem_chat_on_command_received_resp(struct modem_chat *chat) chat->parse_match->callback(chat, (char **)chat->argv, chat->argc, chat->user_data); } + /* Validate response command is not partial */ + if (chat->parse_match->partial) { + return; + } + /* Advance script */ modem_chat_script_next(chat, false); } @@ -675,9 +689,6 @@ static void modem_chat_pipe_callback(struct modem_pipe *pipe, enum modem_pipe_ev } } -/********************************************************* - * GLOBAL FUNCTIONS - *********************************************************/ int modem_chat_init(struct modem_chat *chat, const struct modem_chat_config *config) { __ASSERT_NO_MSG(chat != NULL); @@ -706,6 +717,7 @@ int modem_chat_init(struct modem_chat *chat, const struct modem_chat_config *con chat->matches_size[MODEM_CHAT_MATCHES_INDEX_UNSOL] = config->unsol_matches_size; chat->process_timeout = config->process_timeout; atomic_set(&chat->script_state, 0); + k_sem_init(&chat->script_stopped_sem, 0, 1); k_work_init_delayable(&chat->process_work, modem_chat_process_handler); k_work_init(&chat->script_run_work, modem_chat_script_run_handler); k_work_init_delayable(&chat->script_timeout_work, modem_chat_script_timeout_handler); @@ -725,7 +737,7 @@ int modem_chat_attach(struct modem_chat *chat, struct modem_pipe *pipe) return 0; } -int modem_chat_script_run(struct modem_chat *chat, const struct modem_chat_script *script) +int modem_chat_run_script_async(struct modem_chat *chat, const struct modem_chat_script *script) { bool script_is_running; @@ -741,7 +753,7 @@ int modem_chat_script_run(struct modem_chat *chat, const struct modem_chat_scrip /* Validate script commands */ for (uint16_t i = 0; i < script->script_chats_size; i++) { - if ((strlen(script->script_chats[i].request) == 0) && + if ((script->script_chats[i].request_size == 0) && (script->script_chats[i].response_matches_size == 0)) { return -EINVAL; } @@ -759,6 +771,25 @@ int modem_chat_script_run(struct modem_chat *chat, const struct modem_chat_scrip return 0; } +int modem_chat_run_script(struct modem_chat *chat, const struct modem_chat_script *script) +{ + int ret; + + k_sem_reset(&chat->script_stopped_sem); + + ret = modem_chat_run_script_async(chat, script); + if (ret < 0) { + return ret; + } + + ret = k_sem_take(&chat->script_stopped_sem, K_FOREVER); + if (ret < 0) { + return ret; + } + + return chat->script_result == MODEM_CHAT_SCRIPT_RESULT_SUCCESS ? 0 : -EAGAIN; +} + void modem_chat_script_abort(struct modem_chat *chat) { k_work_submit(&chat->script_abort_work); @@ -784,6 +815,8 @@ void modem_chat_release(struct modem_chat *chat) chat->script = NULL; chat->script_chat_it = 0; atomic_set(&chat->script_state, 0); + chat->script_result = MODEM_CHAT_SCRIPT_RESULT_ABORT; + k_sem_reset(&chat->script_stopped_sem); chat->script_send_request_pos = 0; chat->script_send_delimiter_pos = 0; chat->parse_match = NULL; diff --git a/subsys/modem/modem_cmux.c b/subsys/modem/modem_cmux.c index d91514d6178..9c95e124fc2 100644 --- a/subsys/modem/modem_cmux.c +++ b/subsys/modem/modem_cmux.c @@ -5,7 +5,7 @@ */ #include -LOG_MODULE_REGISTER(modem_cmux, CONFIG_MODEM_MODULES_LOG_LEVEL); +LOG_MODULE_REGISTER(modem_cmux, CONFIG_MODEM_CMUX_LOG_LEVEL); #include #include @@ -23,7 +23,7 @@ LOG_MODULE_REGISTER(modem_cmux, CONFIG_MODEM_MODULES_LOG_LEVEL); #define MODEM_CMUX_DATA_FRAME_SIZE_MIN (MODEM_CMUX_FRAME_SIZE_MAX + \ MODEM_CMUX_DATA_SIZE_MIN) -#define MODEM_CMUX_CMD_DATA_SIZE_MAX (0x04) +#define MODEM_CMUX_CMD_DATA_SIZE_MAX (0x08) #define MODEM_CMUX_CMD_FRAME_SIZE_MAX (MODEM_CMUX_FRAME_SIZE_MAX + \ MODEM_CMUX_CMD_DATA_SIZE_MAX) @@ -96,26 +96,91 @@ static int modem_cmux_wrap_command(struct modem_cmux_command **command, const ui return 0; } -static struct modem_cmux_command *modem_cmux_command_wrap(uint8_t *data) +static struct modem_cmux_command *modem_cmux_command_wrap(const uint8_t *data) { return (struct modem_cmux_command *)data; } -static void modem_cmux_log_unknown_frame(struct modem_cmux *cmux) +static const char *modem_cmux_frame_type_to_str(enum modem_cmux_frame_types frame_type) { - char data[24]; - uint8_t data_cnt = (cmux->frame.data_len < 8) ? cmux->frame.data_len : 8; - - for (uint8_t i = 0; i < data_cnt; i++) { - snprintk(&data[i * 3], sizeof(data) - (i * 3), "%02X,", cmux->frame.data[i]); + switch (frame_type) { + case MODEM_CMUX_FRAME_TYPE_RR: + return "RR"; + case MODEM_CMUX_FRAME_TYPE_UI: + return "UI"; + case MODEM_CMUX_FRAME_TYPE_RNR: + return "RNR"; + case MODEM_CMUX_FRAME_TYPE_REJ: + return "REJ"; + case MODEM_CMUX_FRAME_TYPE_DM: + return "DM"; + case MODEM_CMUX_FRAME_TYPE_SABM: + return "SABM"; + case MODEM_CMUX_FRAME_TYPE_DISC: + return "DISC"; + case MODEM_CMUX_FRAME_TYPE_UA: + return "UA"; + case MODEM_CMUX_FRAME_TYPE_UIH: + return "UIH"; } + return ""; +} - /* Remove trailing */ - if (data_cnt > 0) { - data[(data_cnt * 3) - 1] = '\0'; +static void modem_cmux_log_transmit_frame(const struct modem_cmux_frame *frame) +{ + LOG_DBG("ch:%u,cr:%u,pf:%u,type:%s", frame->dlci_address, frame->cr, frame->pf, + modem_cmux_frame_type_to_str(frame->type)); + LOG_HEXDUMP_DBG(frame->data, frame->data_len, "data:"); +} + +static void modem_cmux_log_received_frame(const struct modem_cmux_frame *frame) +{ + LOG_DBG("ch:%u,cr:%u,pf:%u,type:%s", frame->dlci_address, frame->cr, frame->pf, + modem_cmux_frame_type_to_str(frame->type)); + LOG_HEXDUMP_DBG(frame->data, frame->data_len, "data:"); +} + +static const char *modem_cmux_command_type_to_str(enum modem_cmux_command_types command_type) +{ + switch (command_type) { + case MODEM_CMUX_COMMAND_NSC: + return "NSC"; + case MODEM_CMUX_COMMAND_TEST: + return "TEST"; + case MODEM_CMUX_COMMAND_PSC: + return "PSC"; + case MODEM_CMUX_COMMAND_RLS: + return "RLS"; + case MODEM_CMUX_COMMAND_FCOFF: + return "FCOFF"; + case MODEM_CMUX_COMMAND_PN: + return "PN"; + case MODEM_CMUX_COMMAND_RPN: + return "RPN"; + case MODEM_CMUX_COMMAND_FCON: + return "FCON"; + case MODEM_CMUX_COMMAND_CLD: + return "CLD"; + case MODEM_CMUX_COMMAND_SNC: + return "SNC"; + case MODEM_CMUX_COMMAND_MSC: + return "MSC"; } + return ""; +} + +static void modem_cmux_log_transmit_command(const struct modem_cmux_command *command) +{ + LOG_DBG("ea:%u,cr:%u,type:%s", command->type.ea, command->type.cr, + modem_cmux_command_type_to_str(command->type.value)); + LOG_HEXDUMP_DBG(command->value, command->length.value, "data:"); +} - LOG_DBG("ch:%u, type:%u, data:%s", cmux->frame.dlci_address, cmux->frame.type, data); +static void modem_cmux_log_received_command(const struct modem_cmux_command *command) +{ + LOG_DBG("ea:%u,cr:%u,type:%s", command->type.ea, command->type.cr, + modem_cmux_command_type_to_str(command->type.value)); + LOG_HEXDUMP_DBG(command->value, command->length.value, "data:"); } static void modem_cmux_raise_event(struct modem_cmux *cmux, enum modem_cmux_event event) @@ -199,6 +264,7 @@ static bool modem_cmux_transmit_cmd_frame(struct modem_cmux *cmux, const struct modem_cmux_frame *frame) { uint16_t space; + struct modem_cmux_command *command; k_mutex_lock(&cmux->transmit_rb_lock, K_FOREVER); space = ring_buf_space_get(&cmux->transmit_rb); @@ -208,6 +274,11 @@ static bool modem_cmux_transmit_cmd_frame(struct modem_cmux *cmux, return false; } + modem_cmux_log_transmit_frame(frame); + if (modem_cmux_wrap_command(&command, frame->data, frame->data_len) == 0) { + modem_cmux_log_transmit_command(command); + } + modem_cmux_transmit_frame(cmux, frame); k_mutex_unlock(&cmux->transmit_rb_lock); return true; @@ -240,6 +311,7 @@ static int16_t modem_cmux_transmit_data_frame(struct modem_cmux *cmux, return -ENOMEM; } + modem_cmux_log_transmit_frame(frame); ret = modem_cmux_transmit_frame(cmux, frame); k_mutex_unlock(&cmux->transmit_rb_lock); return ret; @@ -338,6 +410,8 @@ static void modem_cmux_on_control_frame_uih(struct modem_cmux *cmux) return; } + modem_cmux_log_received_command(command); + switch (command->type.value) { case MODEM_CMUX_COMMAND_CLD: modem_cmux_on_cld_command(cmux); @@ -356,13 +430,15 @@ static void modem_cmux_on_control_frame_uih(struct modem_cmux *cmux) break; default: - LOG_DBG("Unknown command"); + LOG_DBG("Unknown control command"); break; } } static void modem_cmux_on_control_frame(struct modem_cmux *cmux) { + modem_cmux_log_received_frame(&cmux->frame); + switch (cmux->frame.type) { case MODEM_CMUX_FRAME_TYPE_UA: modem_cmux_on_control_frame_ua(cmux); @@ -373,7 +449,7 @@ static void modem_cmux_on_control_frame(struct modem_cmux *cmux) break; default: - modem_cmux_log_unknown_frame(cmux); + LOG_WRN("Unknown %s frame type", "control"); break; } } @@ -401,6 +477,9 @@ static void modem_cmux_on_dlci_frame_ua(struct modem_cmux_dlci *dlci) dlci->state = MODEM_CMUX_DLCI_STATE_OPEN; modem_pipe_notify_opened(&dlci->pipe); k_work_cancel_delayable(&dlci->open_work); + k_mutex_lock(&dlci->receive_rb_lock, K_FOREVER); + ring_buf_reset(&dlci->receive_rb); + k_mutex_unlock(&dlci->receive_rb_lock); break; case MODEM_CMUX_DLCI_STATE_CLOSING: @@ -442,6 +521,8 @@ static void modem_cmux_on_dlci_frame(struct modem_cmux *cmux) return; } + modem_cmux_log_received_frame(&cmux->frame); + switch (cmux->frame.type) { case MODEM_CMUX_FRAME_TYPE_UA: modem_cmux_on_dlci_frame_ua(dlci); @@ -452,7 +533,7 @@ static void modem_cmux_on_dlci_frame(struct modem_cmux *cmux) break; default: - modem_cmux_log_unknown_frame(cmux); + LOG_WRN("Unknown %s frame type", "DLCI"); break; } } @@ -602,7 +683,7 @@ static void modem_cmux_process_received_byte(struct modem_cmux *cmux, uint8_t by /* Check if receive buffer overrun */ if (cmux->receive_buf_len == cmux->receive_buf_size) { - LOG_DBG("Receive buf overrun"); + LOG_WRN("Receive buf overrun"); /* Drop frame */ cmux->receive_state = MODEM_CMUX_RECEIVE_STATE_EOF; @@ -650,8 +731,6 @@ static void modem_cmux_process_received_byte(struct modem_cmux *cmux, uint8_t by break; } - LOG_DBG("Received frame"); - /* Process frame */ cmux->frame.data = cmux->receive_buf; modem_cmux_on_frame(cmux); @@ -726,6 +805,10 @@ static void modem_cmux_connect_handler(struct k_work *item) struct k_work_delayable *dwork = k_work_delayable_from_work(item); struct modem_cmux *cmux = CONTAINER_OF(dwork, struct modem_cmux, connect_work); + if (cmux == NULL) { + return; + } + cmux->state = MODEM_CMUX_STATE_CONNECTING; struct modem_cmux_frame frame = { @@ -790,7 +873,7 @@ static int modem_cmux_dlci_pipe_api_transmit(void *data, const uint8_t *buf, siz struct modem_cmux_frame frame = { .dlci_address = dlci->dlci_address, - .cr = false, + .cr = true, .pf = false, .type = MODEM_CMUX_FRAME_TYPE_UIH, .data = buf, @@ -835,6 +918,10 @@ static void modem_cmux_dlci_open_handler(struct k_work *item) struct k_work_delayable *dwork = k_work_delayable_from_work(item); struct modem_cmux_dlci *dlci = CONTAINER_OF(dwork, struct modem_cmux_dlci, open_work); + if (dlci == NULL) { + return; + } + dlci->state = MODEM_CMUX_DLCI_STATE_OPENING; struct modem_cmux_frame frame = { @@ -856,6 +943,10 @@ static void modem_cmux_dlci_close_handler(struct k_work *item) struct modem_cmux_dlci *dlci = CONTAINER_OF(dwork, struct modem_cmux_dlci, close_work); struct modem_cmux *cmux = dlci->cmux; + if (cmux == NULL) { + return; + } + dlci->state = MODEM_CMUX_DLCI_STATE_CLOSING; struct modem_cmux_frame frame = { @@ -935,20 +1026,18 @@ int modem_cmux_attach(struct modem_cmux *cmux, struct modem_pipe *pipe) { cmux->pipe = pipe; ring_buf_reset(&cmux->transmit_rb); + cmux->receive_state = MODEM_CMUX_RECEIVE_STATE_SOF; modem_pipe_attach(cmux->pipe, modem_cmux_bus_callback, cmux); return 0; } int modem_cmux_connect(struct modem_cmux *cmux) { - __ASSERT_NO_MSG(cmux->pipe != NULL); + int ret; - if (k_event_wait(&cmux->event, MODEM_CMUX_EVENT_CONNECTED_BIT, false, K_NO_WAIT)) { - return -EALREADY; - } - - if (k_work_delayable_is_pending(&cmux->connect_work) == false) { - k_work_schedule(&cmux->connect_work, K_NO_WAIT); + ret = modem_cmux_connect_async(cmux); + if (ret < 0) { + return ret; } if (k_event_wait(&cmux->event, MODEM_CMUX_EVENT_CONNECTED_BIT, false, @@ -963,22 +1052,24 @@ int modem_cmux_connect_async(struct modem_cmux *cmux) { __ASSERT_NO_MSG(cmux->pipe != NULL); - if (k_work_delayable_is_pending(&cmux->connect_work) == true) { - return -EBUSY; + if (k_event_test(&cmux->event, MODEM_CMUX_EVENT_CONNECTED_BIT)) { + return -EALREADY; + } + + if (k_work_delayable_is_pending(&cmux->connect_work) == false) { + k_work_schedule(&cmux->connect_work, K_NO_WAIT); } - k_work_schedule(&cmux->connect_work, K_NO_WAIT); return 0; } int modem_cmux_disconnect(struct modem_cmux *cmux) { - if (k_event_wait(&cmux->event, MODEM_CMUX_EVENT_DISCONNECTED_BIT, false, K_NO_WAIT)) { - return -EALREADY; - } + int ret; - if (k_work_delayable_is_pending(&cmux->disconnect_work) == false) { - k_work_schedule(&cmux->disconnect_work, K_NO_WAIT); + ret = modem_cmux_disconnect_async(cmux); + if (ret < 0) { + return ret; } if (k_event_wait(&cmux->event, MODEM_CMUX_EVENT_DISCONNECTED_BIT, false, @@ -991,11 +1082,16 @@ int modem_cmux_disconnect(struct modem_cmux *cmux) int modem_cmux_disconnect_async(struct modem_cmux *cmux) { - if (k_work_delayable_is_pending(&cmux->disconnect_work) == true) { - return -EBUSY; + __ASSERT_NO_MSG(cmux->pipe != NULL); + + if (k_event_test(&cmux->event, MODEM_CMUX_EVENT_DISCONNECTED_BIT)) { + return -EALREADY; + } + + if (k_work_delayable_is_pending(&cmux->disconnect_work) == false) { + k_work_schedule(&cmux->disconnect_work, K_NO_WAIT); } - k_work_schedule(&cmux->disconnect_work, K_NO_WAIT); return 0; } @@ -1019,4 +1115,8 @@ void modem_cmux_release(struct modem_cmux *cmux) /* Unreference pipe */ cmux->pipe = NULL; + + /* Reset events */ + k_event_clear(&cmux->event, MODEM_CMUX_EVENT_CONNECTED_BIT); + k_event_post(&cmux->event, MODEM_CMUX_EVENT_DISCONNECTED_BIT); } diff --git a/subsys/modem/modem_pipe.c b/subsys/modem/modem_pipe.c index ca2a26020be..01bdac50d3a 100644 --- a/subsys/modem/modem_pipe.c +++ b/subsys/modem/modem_pipe.c @@ -20,6 +20,7 @@ void modem_pipe_init(struct modem_pipe *pipe, void *data, struct modem_pipe_api pipe->callback = NULL; pipe->user_data = NULL; pipe->state = MODEM_PIPE_STATE_CLOSED; + pipe->receive_ready_pending = false; k_mutex_init(&pipe->lock); k_condvar_init(&pipe->condvar); @@ -30,8 +31,12 @@ int modem_pipe_open(struct modem_pipe *pipe) int ret; k_mutex_lock(&pipe->lock, K_FOREVER); - ret = pipe->api->open(pipe->data); + if (pipe->state == MODEM_PIPE_STATE_OPEN) { + k_mutex_unlock(&pipe->lock); + return 0; + } + ret = pipe->api->open(pipe->data); if (ret < 0) { k_mutex_unlock(&pipe->lock); return ret; @@ -53,6 +58,15 @@ int modem_pipe_open_async(struct modem_pipe *pipe) int ret; k_mutex_lock(&pipe->lock, K_FOREVER); + if (pipe->state == MODEM_PIPE_STATE_OPEN) { + if (pipe->callback != NULL) { + pipe->callback(pipe, MODEM_PIPE_EVENT_OPENED, pipe->user_data); + } + + k_mutex_unlock(&pipe->lock); + return 0; + } + ret = pipe->api->open(pipe->data); k_mutex_unlock(&pipe->lock); return ret; @@ -63,6 +77,11 @@ void modem_pipe_attach(struct modem_pipe *pipe, modem_pipe_api_callback callback k_mutex_lock(&pipe->lock, K_FOREVER); pipe->callback = callback; pipe->user_data = user_data; + + if (pipe->receive_ready_pending && (pipe->callback != NULL)) { + pipe->callback(pipe, MODEM_PIPE_EVENT_RECEIVE_READY, pipe->user_data); + } + k_mutex_unlock(&pipe->lock); } @@ -94,6 +113,7 @@ int modem_pipe_receive(struct modem_pipe *pipe, uint8_t *buf, size_t size) } ret = pipe->api->receive(pipe->data, buf, size); + pipe->receive_ready_pending = false; k_mutex_unlock(&pipe->lock); return ret; } @@ -111,6 +131,11 @@ int modem_pipe_close(struct modem_pipe *pipe) int ret; k_mutex_lock(&pipe->lock, K_FOREVER); + if (pipe->state == MODEM_PIPE_STATE_CLOSED) { + k_mutex_unlock(&pipe->lock); + return 0; + } + ret = pipe->api->close(pipe->data); if (ret < 0) { k_mutex_unlock(&pipe->lock); @@ -133,6 +158,15 @@ int modem_pipe_close_async(struct modem_pipe *pipe) int ret; k_mutex_lock(&pipe->lock, K_FOREVER); + if (pipe->state == MODEM_PIPE_STATE_CLOSED) { + if (pipe->callback != NULL) { + pipe->callback(pipe, MODEM_PIPE_EVENT_CLOSED, pipe->user_data); + } + + k_mutex_unlock(&pipe->lock); + return 0; + } + ret = pipe->api->close(pipe->data); k_mutex_unlock(&pipe->lock); return ret; @@ -155,6 +189,7 @@ void modem_pipe_notify_closed(struct modem_pipe *pipe) { k_mutex_lock(&pipe->lock, K_FOREVER); pipe->state = MODEM_PIPE_STATE_CLOSED; + pipe->receive_ready_pending = false; if (pipe->callback != NULL) { pipe->callback(pipe, MODEM_PIPE_EVENT_CLOSED, pipe->user_data); @@ -168,6 +203,8 @@ void modem_pipe_notify_receive_ready(struct modem_pipe *pipe) { k_mutex_lock(&pipe->lock, K_FOREVER); + pipe->receive_ready_pending = true; + if (pipe->callback != NULL) { pipe->callback(pipe, MODEM_PIPE_EVENT_RECEIVE_READY, pipe->user_data); } diff --git a/subsys/modem/modem_ppp.c b/subsys/modem/modem_ppp.c index 48a550d4d1f..476926f4db3 100644 --- a/subsys/modem/modem_ppp.c +++ b/subsys/modem/modem_ppp.c @@ -285,6 +285,9 @@ static void modem_ppp_process_received_byte(struct modem_ppp *ppp, uint8_t byte) net_pkt_unref(ppp->rx_pkt); ppp->rx_pkt = NULL; ppp->receive_state = MODEM_PPP_RECEIVE_STATE_HDR_SOF; +#if defined(CONFIG_NET_STATISTICS_PPP) + ppp->stats.drop++; +#endif } break; @@ -295,6 +298,9 @@ static void modem_ppp_process_received_byte(struct modem_ppp *ppp, uint8_t byte) net_pkt_unref(ppp->rx_pkt); ppp->rx_pkt = NULL; ppp->receive_state = MODEM_PPP_RECEIVE_STATE_HDR_SOF; +#if defined(CONFIG_NET_STATISTICS_PPP) + ppp->stats.drop++; +#endif break; } @@ -433,11 +439,23 @@ static int modem_ppp_ppp_api_send(const struct device *dev, struct net_pkt *pkt) return 0; } +#if defined(CONFIG_NET_STATISTICS_PPP) +static struct net_stats_ppp *modem_ppp_ppp_get_stats(const struct device *dev) +{ + struct modem_ppp *ppp = (struct modem_ppp *)dev->data; + + return &ppp->stats; +} +#endif + const struct ppp_api modem_ppp_ppp_api = { .iface_api.init = modem_ppp_ppp_api_init, .start = modem_ppp_ppp_api_start, .stop = modem_ppp_ppp_api_stop, .send = modem_ppp_ppp_api_send, +#if defined(CONFIG_NET_STATISTICS_PPP) + .get_stats = modem_ppp_ppp_get_stats, +#endif }; int modem_ppp_attach(struct modem_ppp *ppp, struct modem_pipe *pipe) diff --git a/subsys/net/CMakeLists.txt b/subsys/net/CMakeLists.txt index f9cf4940a43..d8ef4ab0f36 100644 --- a/subsys/net/CMakeLists.txt +++ b/subsys/net/CMakeLists.txt @@ -20,4 +20,7 @@ if(CONFIG_NETWORKING) endif() add_subdirectory(lib) -add_subdirectory_ifdef(CONFIG_NET_CONNECTION_MANAGER conn_mgr) + +if(CONFIG_NET_CONNECTION_MANAGER) + add_subdirectory(conn_mgr) +endif() diff --git a/subsys/net/buf.c b/subsys/net/buf.c index da8c75f32f2..09f937da59d 100644 --- a/subsys/net/buf.c +++ b/subsys/net/buf.c @@ -221,17 +221,6 @@ static uint8_t *data_ref(struct net_buf *buf, uint8_t *data) return pool->alloc->cb->ref(buf, data); } -static void data_unref(struct net_buf *buf, uint8_t *data) -{ - struct net_buf_pool *pool = net_buf_pool_get(buf->pool_id); - - if (buf->flags & NET_BUF_EXTERNAL_DATA) { - return; - } - - pool->alloc->cb->unref(buf, data); -} - #if defined(CONFIG_NET_BUF_LOG) struct net_buf *net_buf_alloc_len_debug(struct net_buf_pool *pool, size_t size, k_timeout_t timeout, const char *func, @@ -484,11 +473,6 @@ void net_buf_unref(struct net_buf *buf) return; } - if (buf->__buf) { - data_unref(buf, buf->__buf); - buf->__buf = NULL; - } - buf->data = NULL; buf->frags = NULL; diff --git a/subsys/net/conn_mgr/conn_mgr_monitor.c b/subsys/net/conn_mgr/conn_mgr_monitor.c index 7396b06dc54..69c21f75b2c 100644 --- a/subsys/net/conn_mgr/conn_mgr_monitor.c +++ b/subsys/net/conn_mgr/conn_mgr_monitor.c @@ -193,8 +193,12 @@ static void conn_mgr_mon_init_cb(struct net_if *iface, void *user_data) conn_mgr_mon_initial_state(iface); } -static void conn_mgr_mon_thread_fn(void) +static void conn_mgr_mon_thread_fn(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + k_mutex_lock(&conn_mgr_mon_lock, K_FOREVER); conn_mgr_conn_init(); @@ -332,7 +336,7 @@ static int conn_mgr_mon_init(void) k_thread_create(&conn_mgr_mon_thread, conn_mgr_mon_stack, CONFIG_NET_CONNECTION_MANAGER_MONITOR_STACK_SIZE, - (k_thread_entry_t)conn_mgr_mon_thread_fn, + conn_mgr_mon_thread_fn, NULL, NULL, NULL, THREAD_PRIORITY, 0, K_NO_WAIT); return 0; diff --git a/subsys/net/conn_mgr/conn_mgr_private.h b/subsys/net/conn_mgr/conn_mgr_private.h index cf86e4ddc77..99aa98567a3 100644 --- a/subsys/net/conn_mgr/conn_mgr_private.h +++ b/subsys/net/conn_mgr/conn_mgr_private.h @@ -56,4 +56,7 @@ extern struct k_mutex conn_mgr_mon_lock; void conn_mgr_init_events_handler(void); +/* Cause conn_mgr_connectivity to Initialize all connectivity implementation bindings */ +void conn_mgr_conn_init(void); + #endif /* __CONN_MGR_PRV_H__ */ diff --git a/subsys/net/ip/CMakeLists.txt b/subsys/net/ip/CMakeLists.txt index 7dc54935c5c..b9493b894a7 100644 --- a/subsys/net/ip/CMakeLists.txt +++ b/subsys/net/ip/CMakeLists.txt @@ -28,6 +28,7 @@ if(CONFIG_NET_NATIVE) zephyr_library_sources(net_context.c) zephyr_library_sources(net_pkt.c) zephyr_library_sources(net_tc.c) +zephyr_library_sources(icmp.c) zephyr_library_sources_ifdef(CONFIG_NET_IP connection.c) zephyr_library_sources_ifdef(CONFIG_NET_6LO 6lo.c) zephyr_library_sources_ifdef(CONFIG_NET_DHCPV4 dhcpv4.c) @@ -58,14 +59,10 @@ if(CONFIG_NET_TCP_ISN_RFC6528) endif() endif() +# To get private includes like net_shell.h +zephyr_library_include_directories(. ${ZEPHYR_BASE}/subsys/net/lib) + zephyr_library_include_directories( ${ZEPHYR_BASE}/kernel/include ${ARCH_DIR}/${ARCH}/include ) - -if(CONFIG_NET_SHELL) -zephyr_library_sources(net_shell.c) -zephyr_library_include_directories(. ${ZEPHYR_BASE}/subsys/net/l2) -zephyr_library_include_directories(. ${ZEPHYR_BASE}/subsys/net/lib) -zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS) -endif() diff --git a/subsys/net/ip/Kconfig b/subsys/net/ip/Kconfig index d2ca36b845c..fffa028b628 100644 --- a/subsys/net/ip/Kconfig +++ b/subsys/net/ip/Kconfig @@ -12,6 +12,11 @@ config NET_IP bool default y if NET_IPV6 || NET_IPV4 +# Hidden option enabled whenever an IP fragmentation is enabled. +config NET_IP_FRAGMENT + bool + default y if NET_IPV6_FRAGMENT || NET_IPV4_FRAGMENT + # Hidden option selected by net connection based socket implementations # to draw in all code required for connection infrastructure. config NET_CONNECTION_SOCKETS @@ -53,6 +58,14 @@ config NET_OFFLOAD help Enables TCP/IP stack to be offload to a co-processor. +config NET_OFFLOADING_SUPPORT + bool + default y if NET_OFFLOAD || NET_SOCKETS_OFFLOAD + help + Hidden option that is set if either NET_OFFLOAD or + NET_SOCKETS_OFFLOAD is set. This allows us to check + only one option instead of two. + if NET_OFFLOAD module = NET_OFFLOAD module-dep = NET_LOG @@ -135,9 +148,23 @@ source "subsys/net/ip/Kconfig.ipv6" source "subsys/net/ip/Kconfig.ipv4" +config NET_IPV4_MAPPING_TO_IPV6 + bool "Support IPv4 mapped on IPv6 addresses" + depends on NET_NATIVE_IPV6 + help + Support v4-mapped-on-v6 address type. This allows IPv4 and IPv6 + to share a local port space. When the application gets an IPv4 + connection or packet to an IPv6 socket, its source address will + be mapped to IPv6. This is turned off by default which means + that IPV6_V6ONLY socket option is always on. If you enable this + option, then you can still control the behaviour of the socket + via the IPV6_V6ONLY option at runtime. + config NET_SHELL bool "Network shell utilities" select SHELL + select NET_IPV4_IGMP if NET_IPV4 + select NET_IPV6_MLD if NET_IPV6 help Activate shell module that provides network commands like ping to the console. @@ -211,8 +238,8 @@ config NET_TC_RX_COUNT config NET_TC_SKIP_FOR_HIGH_PRIO bool "Push high priority packets directly to network driver" help - If this is set, then high priority (NET_PRIORITY_CA) net_pkt will be - pushed directly to network driver and will skip the traffic class + If this is set, then high priority (>= NET_PRIORITY_CA) net_pkt will + be pushed directly to network driver and will skip the traffic class queues. This is currently not enabled by default. choice NET_TC_THREAD_TYPE @@ -556,6 +583,13 @@ config NET_TCP_WORKER_PRIO execution to the lower layer network stack, with a high risk of running out of net_bufs. +config NET_TCP_REJECT_CONN_WITH_RST + bool "Reject connection attempts on unbound TCP ports with RST" + default y + help + If enabled, TCP stack will reject connection attempts on unbound ports + with TCP RST packet. + config NET_TEST_PROTOCOL bool "JSON based test protocol (UDP)" help @@ -689,6 +723,20 @@ config NET_CONTEXT_DSCP_ECN Notification values on net_context. Those values are then used in IPv4/IPv6 header when sending packets over net_context. +config NET_CONTEXT_REUSEADDR + bool "Add REUSEADDR support to net_context" + default y if NET_TCP || NET_UDP + help + Allow to set the SO_REUSEADDR flag on a socket. This enables multiple + sockets to bind to the same local IP address. + +config NET_CONTEXT_REUSEPORT + bool "Add REUSEPORT support to net_context" + default y if NET_TCP || NET_UDP + help + Allow to set the SO_REUSEPORT flag on a socket. This enables multiple + sockets to bind to the same local IP address and port combination. + config NET_TEST bool "Network Testing" help @@ -817,8 +865,12 @@ config NET_HEADERS_ALWAYS_CONTIGUOUS NET_BUF_FIXED_DATA_SIZE enabled and NET_BUF_DATA_SIZE of 128 for instance. -choice +# If we are running network tests found in tests/net, then the NET_TEST is +# set and in that case we default to Dummy L2 layer as typically the tests +# use that by default. +choice NET_DEFAULT_IF prompt "Default Network Interface" + default NET_DEFAULT_IF_DUMMY if NET_TEST default NET_DEFAULT_IF_FIRST help If system has multiple interfaces enabled, then user shall be able diff --git a/subsys/net/ip/Kconfig.mgmt b/subsys/net/ip/Kconfig.mgmt index 2ecfc9d028c..cc5c514afde 100644 --- a/subsys/net/ip/Kconfig.mgmt +++ b/subsys/net/ip/Kconfig.mgmt @@ -21,6 +21,7 @@ if NET_MGMT_EVENT config NET_MGMT_EVENT_STACK_SIZE int "Stack size for the inner thread handling event callbacks" + default 4096 if WIFI_NM_WPA_SUPPLICANT default 2048 if COVERAGE_GCOV default 840 if X86 default 800 if THREAD_LOCAL_STORAGE diff --git a/subsys/net/ip/Kconfig.stats b/subsys/net/ip/Kconfig.stats index 147b002d603..53105e0d70c 100644 --- a/subsys/net/ip/Kconfig.stats +++ b/subsys/net/ip/Kconfig.stats @@ -95,7 +95,7 @@ config NET_STATISTICS_IGMP config NET_STATISTICS_PPP bool "Point-to-point (PPP) statistics" - depends on NET_PPP + depends on NET_L2_PPP default y help Keep track of PPP related statistics diff --git a/subsys/net/ip/connection.c b/subsys/net/ip/connection.c index 225a3fdbaad..e32747bc38f 100644 --- a/subsys/net/ip/connection.c +++ b/subsys/net/ip/connection.c @@ -154,11 +154,13 @@ static void conn_set_unused(struct net_conn *conn) } /* Check if we already have identical connection handler installed. */ -static struct net_conn *conn_find_handler(uint16_t proto, uint8_t family, +static struct net_conn *conn_find_handler(struct net_if *iface, + uint16_t proto, uint8_t family, const struct sockaddr *remote_addr, const struct sockaddr *local_addr, uint16_t remote_port, - uint16_t local_port) + uint16_t local_port, + bool reuseport_set) { struct net_conn *conn; struct net_conn *tmp; @@ -174,67 +176,75 @@ static struct net_conn *conn_find_handler(uint16_t proto, uint8_t family, continue; } - if (remote_addr) { - if (!(conn->flags & NET_CONN_REMOTE_ADDR_SET)) { + if (local_addr) { + if (!(conn->flags & NET_CONN_LOCAL_ADDR_SET)) { continue; } if (IS_ENABLED(CONFIG_NET_IPV6) && - remote_addr->sa_family == AF_INET6 && - remote_addr->sa_family == - conn->remote_addr.sa_family) { + local_addr->sa_family == AF_INET6 && + local_addr->sa_family == + conn->local_addr.sa_family) { if (!net_ipv6_addr_cmp( - &net_sin6(remote_addr)->sin6_addr, - &net_sin6(&conn->remote_addr)-> + &net_sin6(local_addr)->sin6_addr, + &net_sin6(&conn->local_addr)-> sin6_addr)) { continue; } } else if (IS_ENABLED(CONFIG_NET_IPV4) && - remote_addr->sa_family == AF_INET && - remote_addr->sa_family == - conn->remote_addr.sa_family) { + local_addr->sa_family == AF_INET && + local_addr->sa_family == + conn->local_addr.sa_family) { if (!net_ipv4_addr_cmp( - &net_sin(remote_addr)->sin_addr, - &net_sin(&conn->remote_addr)-> + &net_sin(local_addr)->sin_addr, + &net_sin(&conn->local_addr)-> sin_addr)) { continue; } } else { continue; } - } else if (conn->flags & NET_CONN_REMOTE_ADDR_SET) { + } else if (conn->flags & NET_CONN_LOCAL_ADDR_SET) { continue; } - if (local_addr) { - if (!(conn->flags & NET_CONN_LOCAL_ADDR_SET)) { + if (net_sin(&conn->local_addr)->sin_port != + htons(local_port)) { + continue; + } + + if (remote_addr) { + if (!(conn->flags & NET_CONN_REMOTE_ADDR_SET)) { continue; } if (IS_ENABLED(CONFIG_NET_IPV6) && - local_addr->sa_family == AF_INET6 && - local_addr->sa_family == - conn->local_addr.sa_family) { + remote_addr->sa_family == AF_INET6 && + remote_addr->sa_family == + conn->remote_addr.sa_family) { if (!net_ipv6_addr_cmp( - &net_sin6(local_addr)->sin6_addr, - &net_sin6(&conn->local_addr)-> + &net_sin6(remote_addr)->sin6_addr, + &net_sin6(&conn->remote_addr)-> sin6_addr)) { continue; } } else if (IS_ENABLED(CONFIG_NET_IPV4) && - local_addr->sa_family == AF_INET && - local_addr->sa_family == - conn->local_addr.sa_family) { + remote_addr->sa_family == AF_INET && + remote_addr->sa_family == + conn->remote_addr.sa_family) { if (!net_ipv4_addr_cmp( - &net_sin(local_addr)->sin_addr, - &net_sin(&conn->local_addr)-> + &net_sin(remote_addr)->sin_addr, + &net_sin(&conn->remote_addr)-> sin_addr)) { continue; } } else { continue; } - } else if (conn->flags & NET_CONN_LOCAL_ADDR_SET) { + } else if (conn->flags & NET_CONN_REMOTE_ADDR_SET) { + continue; + } else if (reuseport_set && conn->context != NULL && + net_context_is_reuseport_set(conn->context)) { continue; } @@ -243,9 +253,11 @@ static struct net_conn *conn_find_handler(uint16_t proto, uint8_t family, continue; } - if (net_sin(&conn->local_addr)->sin_port != - htons(local_port)) { - continue; + if (conn->context != NULL && iface != NULL && + net_context_is_bound_to_iface(conn->context)) { + if (iface != net_context_get_iface(conn->context)) { + continue; + } } k_mutex_unlock(&conn_lock); @@ -269,11 +281,15 @@ int net_conn_register(uint16_t proto, uint8_t family, struct net_conn *conn; uint8_t flags = 0U; - conn = conn_find_handler(proto, family, remote_addr, local_addr, - remote_port, local_port); + conn = conn_find_handler(context != NULL ? net_context_get_iface(context) : NULL, + proto, family, remote_addr, local_addr, + remote_port, local_port, + context != NULL ? + net_context_is_reuseport_set(context) : + false); if (conn) { NET_ERR("Identical connection handler %p already found.", conn); - return -EALREADY; + return -EADDRINUSE; } conn = conn_get_unused(); @@ -373,6 +389,8 @@ int net_conn_register(uint16_t proto, uint8_t family, conn_set_used(conn); + conn->v6only = net_context_is_v6only_set(context); + conn_register_debug(conn, remote_port, local_port); return 0; @@ -661,7 +679,17 @@ enum net_verdict net_conn_input(struct net_pkt *pkt, raw_pkt_continue = true; } } - continue; /* wrong protocol family */ + + if (IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6)) { + if (!(conn->family == AF_INET6 && pkt_family == AF_INET && + !conn->v6only)) { + continue; + } + } else { + continue; /* wrong protocol family */ + } + + /* We might have a match for v4-to-v6 mapping, check more */ } /* Is the candidate connection matching the packet's protocol wihin the family? */ @@ -733,15 +761,26 @@ enum net_verdict net_conn_input(struct net_pkt *pkt, if ((conn->flags & NET_CONN_LOCAL_ADDR_SET) && !conn_addr_cmp(pkt, ip_hdr, &conn->local_addr, false)) { - continue; /* wrong local address */ - } - /* If we have an existing best_match, and that one - * specifies a remote port, then we've matched to a - * LISTENING connection that we should not override. - */ - if (best_match != NULL && best_match->flags & NET_CONN_REMOTE_PORT_SPEC) { - continue; /* do not override listening connection */ + /* Check if we could do a v4-mapping-to-v6 and the IPv6 socket + * has no IPV6_V6ONLY option set and if the local IPV6 address + * is unspecified, then we could accept a connection from IPv4 + * address by mapping it to IPv6 address. + */ + if (IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6)) { + if (!(conn->family == AF_INET6 && pkt_family == AF_INET && + !conn->v6only && + net_ipv6_is_addr_unspecified( + &net_sin6(&conn->local_addr)->sin6_addr))) { + continue; /* wrong local address */ + } + } else { + continue; /* wrong local address */ + } + + /* We might have a match for v4-to-v6 mapping, + * continue with rank checking. + */ } if (best_rank < NET_CONN_RANK(conn->flags)) { @@ -813,7 +852,7 @@ enum net_verdict net_conn_input(struct net_pkt *pkt, if (best_match) { NET_DBG("[%p] match found cb %p ud %p rank 0x%02x", best_match, best_match->cb, - best_match->user_data, best_match->flags); + best_match->user_data, NET_CONN_RANK(best_match->flags)); if (best_match->cb(best_match, pkt, ip_hdr, proto_hdr, best_match->user_data) == NET_DROP) { @@ -829,10 +868,12 @@ enum net_verdict net_conn_input(struct net_pkt *pkt, if (IS_ENABLED(CONFIG_NET_IP) && (pkt_family == AF_INET || pkt_family == AF_INET6) && !(is_mcast_pkt || is_bcast_pkt)) { - conn_send_icmp_error(pkt); - - if (IS_ENABLED(CONFIG_NET_TCP) && proto == IPPROTO_TCP) { + if (IS_ENABLED(CONFIG_NET_TCP) && proto == IPPROTO_TCP && + IS_ENABLED(CONFIG_NET_TCP_REJECT_CONN_WITH_RST)) { + net_tcp_reply_rst(pkt); net_stats_update_tcp_seg_connrst(pkt_iface); + } else { + conn_send_icmp_error(pkt); } } diff --git a/subsys/net/ip/connection.h b/subsys/net/ip/connection.h index 8269feb91a1..ee7ee0efc7d 100644 --- a/subsys/net/ip/connection.h +++ b/subsys/net/ip/connection.h @@ -79,6 +79,9 @@ struct net_conn { /** Flags for the connection */ uint8_t flags; + + /** Is v4-mapping-to-v6 enabled for this connection */ + uint8_t v6only : 1; }; /** diff --git a/subsys/net/ip/dhcpv4.c b/subsys/net/ip/dhcpv4.c index d5aefb3ba90..918b71d1d6b 100644 --- a/subsys/net/ip/dhcpv4.c +++ b/subsys/net/ip/dhcpv4.c @@ -16,7 +16,7 @@ LOG_MODULE_REGISTER(net_dhcpv4, CONFIG_NET_DHCPV4_LOG_LEVEL); #include #include #include -#include +#include #include #include #include diff --git a/subsys/net/ip/dhcpv6.c b/subsys/net/ip/dhcpv6.c index fdfef3c5147..5e596a95e5b 100644 --- a/subsys/net/ip/dhcpv6.c +++ b/subsys/net/ip/dhcpv6.c @@ -13,7 +13,7 @@ LOG_MODULE_REGISTER(net_dhcpv6, CONFIG_NET_DHCPV6_LOG_LEVEL); #include #include -#include +#include #include #include "dhcpv6_internal.h" @@ -892,8 +892,13 @@ static int dhcpv6_parse_option_iaaddr(struct net_pkt *pkt, uint16_t length, break; default: - net_pkt_skip(pkt, sublen); NET_DBG("Unexpected option %d length %d", code, sublen); + + ret = net_pkt_skip(pkt, sublen); + if (ret < 0) { + return ret; + } + break; } @@ -980,8 +985,13 @@ static int dhcpv6_parse_option_ia_na(struct net_pkt *pkt, uint16_t length, break; default: - net_pkt_skip(pkt, sublen); NET_DBG("Unexpected option %d length %d", code, sublen); + + ret = net_pkt_skip(pkt, sublen); + if (ret < 0) { + return ret; + } + break; } @@ -1058,8 +1068,13 @@ static int dhcpv6_parse_option_iaprefix(struct net_pkt *pkt, uint16_t length, break; default: - net_pkt_skip(pkt, sublen); NET_DBG("Unexpected option %d length %d", code, sublen); + + ret = net_pkt_skip(pkt, sublen); + if (ret < 0) { + return ret; + } + break; } @@ -1145,8 +1160,13 @@ static int dhcpv6_parse_option_ia_pd(struct net_pkt *pkt, uint16_t length, break; default: - net_pkt_skip(pkt, sublen); NET_DBG("Unexpected option %d length %d", code, sublen); + + ret = net_pkt_skip(pkt, sublen); + if (ret < 0) { + return ret; + } + break; } @@ -1161,6 +1181,7 @@ static int dhcpv6_find_option(struct net_pkt *pkt, enum dhcpv6_option_code opt_c { uint16_t length; uint16_t code; + int ret; while (net_pkt_read_be16(pkt, &code) == 0) { if (net_pkt_read_be16(pkt, &length) < 0) { @@ -1172,7 +1193,10 @@ static int dhcpv6_find_option(struct net_pkt *pkt, enum dhcpv6_option_code opt_c return 0; } - net_pkt_skip(pkt, length); + ret = net_pkt_skip(pkt, length); + if (ret < 0) { + return ret; + } } return -ENOENT; diff --git a/subsys/net/ip/icmp.c b/subsys/net/ip/icmp.c new file mode 100644 index 00000000000..97902c1e4f5 --- /dev/null +++ b/subsys/net/ip/icmp.c @@ -0,0 +1,593 @@ +/** @file + * @brief ICMP related functions + */ + +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Use highest log level if both IPv4 and IPv6 are defined */ +#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_IPV6) + +#if CONFIG_NET_ICMPV4_LOG_LEVEL > CONFIG_NET_ICMPV6_LOG_LEVEL +#define ICMP_LOG_LEVEL CONFIG_NET_ICMPV4_LOG_LEVEL +#else +#define ICMP_LOG_LEVEL CONFIG_NET_ICMPV6_LOG_LEVEL +#endif + +#elif defined(CONFIG_NET_IPV4) +#define ICMP_LOG_LEVEL CONFIG_NET_ICMPV4_LOG_LEVEL +#elif defined(CONFIG_NET_IPV6) +#define ICMP_LOG_LEVEL CONFIG_NET_ICMPV6_LOG_LEVEL +#else +#define ICMP_LOG_LEVEL LOG_LEVEL_INF +#endif + +#include +LOG_MODULE_REGISTER(net_icmp, ICMP_LOG_LEVEL); + +#include +#include +#include +#include +#include + +#include "net_private.h" +#include "icmpv6.h" +#include "icmpv4.h" +#include "ipv4.h" +#include "ipv6.h" +#include "net_stats.h" + +static K_MUTEX_DEFINE(lock); +static sys_slist_t handlers = SYS_SLIST_STATIC_INIT(&handlers); + +#if defined(CONFIG_NET_OFFLOADING_SUPPORT) +static sys_slist_t offload_handlers = SYS_SLIST_STATIC_INIT(&offload_handlers); +#endif + +#define PKT_WAIT_TIME K_SECONDS(1) + +int net_icmp_init_ctx(struct net_icmp_ctx *ctx, uint8_t type, uint8_t code, + net_icmp_handler_t handler) +{ + if (ctx == NULL || handler == NULL) { + return -EINVAL; + } + + memset(ctx, 0, sizeof(struct net_icmp_ctx)); + + ctx->handler = handler; + ctx->type = type; + ctx->code = code; + + k_mutex_lock(&lock, K_FOREVER); + + sys_slist_prepend(&handlers, &ctx->node); + + k_mutex_unlock(&lock); + + return 0; +} + +static void set_offload_handler(struct net_if *iface, + net_icmp_handler_t handler) +{ + struct net_icmp_offload *offload; + + if (!IS_ENABLED(CONFIG_NET_OFFLOADING_SUPPORT)) { + return; + } + + k_mutex_lock(&lock, K_FOREVER); + +#if defined(CONFIG_NET_OFFLOADING_SUPPORT) + SYS_SLIST_FOR_EACH_CONTAINER(&offload_handlers, offload, node) { + if (offload->iface == iface) { + offload->handler = handler; + break; + } + } +#else + ARG_UNUSED(offload); +#endif + + k_mutex_unlock(&lock); +} + +int net_icmp_cleanup_ctx(struct net_icmp_ctx *ctx) +{ + if (ctx == NULL) { + return -EINVAL; + } + + k_mutex_lock(&lock, K_FOREVER); + + sys_slist_find_and_remove(&handlers, &ctx->node); + + k_mutex_unlock(&lock); + + set_offload_handler(ctx->iface, NULL); + + memset(ctx, 0, sizeof(struct net_icmp_ctx)); + + return 0; +} + +#if defined(CONFIG_NET_IPV4) +static int send_icmpv4_echo_request(struct net_icmp_ctx *ctx, + struct net_if *iface, + struct in_addr *dst, + struct net_icmp_ping_params *params, + void *user_data) +{ + NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmpv4_access, + struct net_icmpv4_echo_req); + int ret = -ENOBUFS; + struct net_icmpv4_echo_req *echo_req; + const struct in_addr *src; + struct net_pkt *pkt; + + if (!iface->config.ip.ipv4) { + return -ENETUNREACH; + } + + src = net_if_ipv4_select_src_addr(iface, dst); + + pkt = net_pkt_alloc_with_buffer(iface, + sizeof(struct net_icmpv4_echo_req) + + params->data_size, + AF_INET, IPPROTO_ICMP, + PKT_WAIT_TIME); + if (!pkt) { + return -ENOMEM; + } + + if (!IS_ENABLED(CONFIG_NET_ALLOW_ANY_PRIORITY) && + params->priority >= NET_MAX_PRIORITIES) { + NET_ERR("Priority %d is too large, maximum allowed is %d", + params->priority, NET_MAX_PRIORITIES - 1); + return -EINVAL; + } + + if (params->priority < 0) { + net_pkt_set_ip_dscp(pkt, net_ipv4_get_dscp(params->tc_tos)); + net_pkt_set_ip_ecn(pkt, net_ipv4_get_ecn(params->tc_tos)); + } else { + net_pkt_set_priority(pkt, params->priority); + } + + if (net_ipv4_create(pkt, src, dst) || + net_icmpv4_create(pkt, NET_ICMPV4_ECHO_REQUEST, 0)) { + goto drop; + } + + echo_req = (struct net_icmpv4_echo_req *)net_pkt_get_data( + pkt, &icmpv4_access); + if (!echo_req) { + goto drop; + } + + echo_req->identifier = htons(params->identifier); + echo_req->sequence = htons(params->sequence); + + net_pkt_set_data(pkt, &icmpv4_access); + + if (params->data != NULL && params->data_size > 0) { + net_pkt_write(pkt, params->data, params->data_size); + } else if (params->data == NULL && params->data_size > 0) { + /* Generate payload. */ + if (params->data_size >= sizeof(uint32_t)) { + uint32_t time_stamp = htonl(k_cycle_get_32()); + + net_pkt_write(pkt, &time_stamp, sizeof(time_stamp)); + params->data_size -= sizeof(time_stamp); + } + + for (size_t i = 0; i < params->data_size; i++) { + net_pkt_write_u8(pkt, (uint8_t)i); + } + } else { + /* No payload. */ + } + + net_pkt_cursor_init(pkt); + + net_ipv4_finalize(pkt, IPPROTO_ICMP); + + NET_DBG("Sending ICMPv4 Echo Request type %d from %s to %s", + NET_ICMPV4_ECHO_REQUEST, + net_sprint_ipv4_addr(src), + net_sprint_ipv4_addr(dst)); + + ctx->user_data = user_data; + ctx->iface = iface; + + if (net_send_data(pkt) >= 0) { + net_stats_update_icmp_sent(iface); + return 0; + } + + net_stats_update_icmp_drop(iface); + + ret = -EIO; + +drop: + net_pkt_unref(pkt); + + return ret; + +} +#else +static int send_icmpv4_echo_request(struct net_icmp_ctx *ctx, + struct net_if *iface, + struct in_addr *dst, + struct net_icmp_ping_params *params, + void *user_data) +{ + ARG_UNUSED(ctx); + ARG_UNUSED(iface); + ARG_UNUSED(dst); + ARG_UNUSED(params); + + return -ENOTSUP; +} +#endif + +#if defined(CONFIG_NET_IPV6) +static int send_icmpv6_echo_request(struct net_icmp_ctx *ctx, + struct net_if *iface, + struct in6_addr *dst, + struct net_icmp_ping_params *params, + void *user_data) +{ + NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmpv6_access, + struct net_icmpv6_echo_req); + int ret = -ENOBUFS; + struct net_icmpv6_echo_req *echo_req; + const struct in6_addr *src; + struct net_pkt *pkt; + + if (!iface->config.ip.ipv6) { + return -ENETUNREACH; + } + + src = net_if_ipv6_select_src_addr(iface, dst); + + pkt = net_pkt_alloc_with_buffer(iface, + sizeof(struct net_icmpv6_echo_req) + + params->data_size, + AF_INET6, IPPROTO_ICMPV6, + PKT_WAIT_TIME); + if (!pkt) { + return -ENOMEM; + } + + if (!IS_ENABLED(CONFIG_NET_ALLOW_ANY_PRIORITY) && + params->priority >= NET_MAX_PRIORITIES) { + NET_ERR("Priority %d is too large, maximum allowed is %d", + params->priority, NET_MAX_PRIORITIES - 1); + return -EINVAL; + } + + if (params->priority < 0) { + net_pkt_set_ip_dscp(pkt, net_ipv6_get_dscp(params->tc_tos)); + net_pkt_set_ip_ecn(pkt, net_ipv6_get_ecn(params->tc_tos)); + } else { + net_pkt_set_priority(pkt, params->priority); + } + + if (net_ipv6_create(pkt, src, dst) || + net_icmpv6_create(pkt, NET_ICMPV6_ECHO_REQUEST, 0)) { + goto drop; + } + + echo_req = (struct net_icmpv6_echo_req *)net_pkt_get_data( + pkt, &icmpv6_access); + if (!echo_req) { + goto drop; + } + + echo_req->identifier = htons(params->identifier); + echo_req->sequence = htons(params->sequence); + + net_pkt_set_data(pkt, &icmpv6_access); + + if (params->data != NULL && params->data_size > 0) { + net_pkt_write(pkt, params->data, params->data_size); + } else if (params->data == NULL && params->data_size > 0) { + /* Generate payload. */ + if (params->data_size >= sizeof(uint32_t)) { + uint32_t time_stamp = htonl(k_cycle_get_32()); + + net_pkt_write(pkt, &time_stamp, sizeof(time_stamp)); + params->data_size -= sizeof(time_stamp); + } + + for (size_t i = 0; i < params->data_size; i++) { + net_pkt_write_u8(pkt, (uint8_t)i); + } + } else { + /* No payload. */ + } + + net_pkt_cursor_init(pkt); + net_ipv6_finalize(pkt, IPPROTO_ICMPV6); + + NET_DBG("Sending ICMPv6 Echo Request type %d from %s to %s", + NET_ICMPV6_ECHO_REQUEST, + net_sprint_ipv6_addr(src), + net_sprint_ipv6_addr(dst)); + + ctx->user_data = user_data; + ctx->iface = iface; + + if (net_send_data(pkt) >= 0) { + net_stats_update_icmp_sent(iface); + return 0; + } + + net_stats_update_icmp_drop(iface); + + ret = -EIO; + +drop: + net_pkt_unref(pkt); + + return ret; +} +#else +static int send_icmpv6_echo_request(struct net_icmp_ctx *ctx, + struct net_if *iface, + struct in6_addr *dst, + struct net_icmp_ping_params *params, + void *user_data) +{ + ARG_UNUSED(ctx); + ARG_UNUSED(iface); + ARG_UNUSED(dst); + ARG_UNUSED(params); + + return -ENOTSUP; +} +#endif + +static struct net_icmp_ping_params *get_default_params(void) +{ + static struct net_icmp_ping_params params = { 0 }; + + params.identifier = sys_rand32_get(); + + return ¶ms; +} + +static int get_offloaded_ping_handler(struct net_if *iface, + net_icmp_offload_ping_handler_t *ping_handler) +{ + struct net_icmp_offload *offload; + int ret; + + if (!IS_ENABLED(CONFIG_NET_OFFLOADING_SUPPORT)) { + return -ENOTSUP; + } + + if (iface == NULL) { + return -EINVAL; + } + + if (!net_if_is_offloaded(iface)) { + return -ENOENT; + } + + ret = -ENOENT; + + k_mutex_lock(&lock, K_FOREVER); + +#if defined(CONFIG_NET_OFFLOADING_SUPPORT) + SYS_SLIST_FOR_EACH_CONTAINER(&offload_handlers, offload, node) { + if (offload->iface == iface) { + *ping_handler = offload->ping_handler; + ret = 0; + break; + } + } +#else + ARG_UNUSED(offload); +#endif + + k_mutex_unlock(&lock); + + return ret; +} + +int net_icmp_send_echo_request(struct net_icmp_ctx *ctx, + struct net_if *iface, + struct sockaddr *dst, + struct net_icmp_ping_params *params, + void *user_data) +{ + if (ctx == NULL || dst == NULL) { + return -EINVAL; + } + + if (iface == NULL) { + if (IS_ENABLED(CONFIG_NET_IPV4) && dst->sa_family == AF_INET) { + iface = net_if_ipv4_select_src_iface(&net_sin(dst)->sin_addr); + } else if (IS_ENABLED(CONFIG_NET_IPV6) && dst->sa_family == AF_INET6) { + iface = net_if_ipv6_select_src_iface(&net_sin6(dst)->sin6_addr); + } + + if (iface == NULL) { + return -ENOENT; + } + } + + if (IS_ENABLED(CONFIG_NET_OFFLOADING_SUPPORT) && net_if_is_offloaded(iface)) { + net_icmp_offload_ping_handler_t ping_handler = NULL; + int ret; + + ret = get_offloaded_ping_handler(iface, &ping_handler); + if (ret < 0) { + return ret; + } + + if (ping_handler == NULL) { + NET_ERR("No ping handler set"); + return -ENOENT; + } + + set_offload_handler(iface, ctx->handler); + + return ping_handler(ctx, iface, dst, params, user_data); + } + + if (IS_ENABLED(CONFIG_NET_IPV4) && dst->sa_family == AF_INET) { + if (params == NULL) { + params = get_default_params(); + } + + return send_icmpv4_echo_request(ctx, iface, &net_sin(dst)->sin_addr, + params, user_data); + } + + if (IS_ENABLED(CONFIG_NET_IPV6) && dst->sa_family == AF_INET6) { + if (params == NULL) { + params = get_default_params(); + } + + return send_icmpv6_echo_request(ctx, iface, &net_sin6(dst)->sin6_addr, + params, user_data); + } + + return -ENOENT; +} + +static int icmp_call_handlers(struct net_pkt *pkt, + struct net_icmp_ip_hdr *ip_hdr, + struct net_icmp_hdr *icmp_hdr) +{ + struct net_icmp_ctx *ctx; + int ret = -ENOENT; + + k_mutex_lock(&lock, K_FOREVER); + + SYS_SLIST_FOR_EACH_CONTAINER(&handlers, ctx, node) { + if (ctx->type == icmp_hdr->type && + (ctx->code == icmp_hdr->code || ctx->code == 0U)) { + /* Do not use a handler that is expecting data from different + * network interface we sent the request. + */ + if (ctx->iface != NULL && ctx->iface != net_pkt_iface(pkt)) { + continue; + } + + ret = ctx->handler(ctx, pkt, ip_hdr, icmp_hdr, ctx->user_data); + if (ret < 0) { + goto out; + } + } + } + +out: + k_mutex_unlock(&lock); + + return ret; +} + + +int net_icmp_call_ipv4_handlers(struct net_pkt *pkt, + struct net_ipv4_hdr *ipv4_hdr, + struct net_icmp_hdr *icmp_hdr) +{ + struct net_icmp_ip_hdr ip_hdr; + + ip_hdr.ipv4 = ipv4_hdr; + ip_hdr.family = AF_INET; + + return icmp_call_handlers(pkt, &ip_hdr, icmp_hdr); +} + +int net_icmp_call_ipv6_handlers(struct net_pkt *pkt, + struct net_ipv6_hdr *ipv6_hdr, + struct net_icmp_hdr *icmp_hdr) +{ + struct net_icmp_ip_hdr ip_hdr; + + ip_hdr.ipv6 = ipv6_hdr; + ip_hdr.family = AF_INET6; + + return icmp_call_handlers(pkt, &ip_hdr, icmp_hdr); +} + +int net_icmp_register_offload_ping(struct net_icmp_offload *ctx, + struct net_if *iface, + net_icmp_offload_ping_handler_t ping_handler) +{ + if (!IS_ENABLED(CONFIG_NET_OFFLOADING_SUPPORT)) { + return -ENOTSUP; + } + + if (iface == NULL) { + return -EINVAL; + } + + if (!net_if_is_offloaded(iface)) { + return -ENOENT; + } + + memset(ctx, 0, sizeof(struct net_icmp_offload)); + + ctx->ping_handler = ping_handler; + ctx->iface = iface; + + k_mutex_lock(&lock, K_FOREVER); + +#if defined(CONFIG_NET_OFFLOADING_SUPPORT) + sys_slist_prepend(&offload_handlers, &ctx->node); +#endif + + k_mutex_unlock(&lock); + + return 0; +} + +int net_icmp_unregister_offload_ping(struct net_icmp_offload *ctx) +{ + if (!IS_ENABLED(CONFIG_NET_OFFLOADING_SUPPORT)) { + return -ENOTSUP; + } + + if (ctx == NULL) { + return -EINVAL; + } + + k_mutex_lock(&lock, K_FOREVER); + +#if defined(CONFIG_NET_OFFLOADING_SUPPORT) + sys_slist_find_and_remove(&offload_handlers, &ctx->node); +#endif + + k_mutex_unlock(&lock); + + memset(ctx, 0, sizeof(struct net_icmp_offload)); + + return 0; +} + +int net_icmp_get_offload_rsp_handler(struct net_icmp_offload *ctx, + net_icmp_handler_t *resp_handler) +{ + if (!IS_ENABLED(CONFIG_NET_OFFLOADING_SUPPORT)) { + return -ENOTSUP; + } + + if (ctx == NULL) { + return -EINVAL; + } + + *resp_handler = ctx->handler; + + return 0; +} diff --git a/subsys/net/ip/icmpv4.c b/subsys/net/ip/icmpv4.c index ed69903bd8e..0ea8d40ba46 100644 --- a/subsys/net/ip/icmpv4.c +++ b/subsys/net/ip/icmpv4.c @@ -16,6 +16,7 @@ LOG_MODULE_REGISTER(net_icmpv4, CONFIG_NET_ICMPV4_LOG_LEVEL); #include #include #include +#include #include "net_private.h" #include "ipv4.h" #include "icmpv4.h" @@ -23,14 +24,12 @@ LOG_MODULE_REGISTER(net_icmpv4, CONFIG_NET_ICMPV4_LOG_LEVEL); #define PKT_WAIT_TIME K_SECONDS(1) -static sys_slist_t handlers; - struct net_icmpv4_hdr_opts_data { struct net_pkt *reply; const struct in_addr *src; }; -static int icmpv4_create(struct net_pkt *pkt, uint8_t icmp_type, uint8_t icmp_code) +int net_icmpv4_create(struct net_pkt *pkt, uint8_t icmp_type, uint8_t icmp_code) { NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmpv4_access, struct net_icmp_hdr); @@ -48,7 +47,7 @@ static int icmpv4_create(struct net_pkt *pkt, uint8_t icmp_type, uint8_t icmp_co return net_pkt_set_data(pkt, &icmpv4_access); } -int net_icmpv4_finalize(struct net_pkt *pkt) +int net_icmpv4_finalize(struct net_pkt *pkt, bool force_chksum) { NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmpv4_access, struct net_icmp_hdr); @@ -66,8 +65,9 @@ int net_icmpv4_finalize(struct net_pkt *pkt) } icmp_hdr->chksum = 0U; - if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt))) { + if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt)) || force_chksum) { icmp_hdr->chksum = net_calc_chksum_icmpv4(pkt); + net_pkt_set_chksum_done(pkt, true); } return net_pkt_set_data(pkt, &icmpv4_access); @@ -410,11 +410,14 @@ static int icmpv4_handle_header_options(struct net_pkt *pkt, } #endif -static enum net_verdict icmpv4_handle_echo_request(struct net_pkt *pkt, - struct net_ipv4_hdr *ip_hdr, - struct net_icmp_hdr *icmp_hdr) +static int icmpv4_handle_echo_request(struct net_icmp_ctx *ctx, + struct net_pkt *pkt, + struct net_icmp_ip_hdr *hdr, + struct net_icmp_hdr *icmp_hdr, + void *user_data) { struct net_pkt *reply = NULL; + struct net_ipv4_hdr *ip_hdr = hdr->ipv4; const struct in_addr *src; int16_t payload_len; @@ -471,7 +474,7 @@ static enum net_verdict icmpv4_handle_echo_request(struct net_pkt *pkt, } } - if (icmpv4_create(reply, NET_ICMPV4_ECHO_REPLY, 0) || + if (net_icmpv4_create(reply, NET_ICMPV4_ECHO_REPLY, 0) || net_pkt_copy(reply, pkt, payload_len)) { goto drop; } @@ -489,9 +492,7 @@ static enum net_verdict icmpv4_handle_echo_request(struct net_pkt *pkt, net_stats_update_icmp_sent(net_pkt_iface(reply)); - net_pkt_unref(pkt); - - return NET_OK; + return 0; drop: if (reply) { net_pkt_unref(reply); @@ -499,115 +500,7 @@ static enum net_verdict icmpv4_handle_echo_request(struct net_pkt *pkt, net_stats_update_icmp_drop(net_pkt_iface(pkt)); - return NET_DROP; -} - -int net_icmpv4_send_echo_request(struct net_if *iface, - struct in_addr *dst, - uint16_t identifier, - uint16_t sequence, - uint8_t tos, - int priority, - const void *data, - size_t data_size) -{ - NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmpv4_access, - struct net_icmpv4_echo_req); - int ret = -ENOBUFS; - struct net_icmpv4_echo_req *echo_req; - const struct in_addr *src; - struct net_pkt *pkt; - - if (IS_ENABLED(CONFIG_NET_OFFLOAD) && net_if_is_ip_offloaded(iface)) { - return -ENOTSUP; - } - - if (!iface->config.ip.ipv4) { - return -ENETUNREACH; - } - - /* Take the first address of the network interface */ - src = &iface->config.ip.ipv4->unicast[0].address.in_addr; - - pkt = net_pkt_alloc_with_buffer(iface, - sizeof(struct net_icmpv4_echo_req) - + data_size, - AF_INET, IPPROTO_ICMP, - PKT_WAIT_TIME); - if (!pkt) { - return -ENOMEM; - } - -#if !defined(CONFIG_NET_ALLOW_ANY_PRIORITY) - if (priority > NET_MAX_PRIORITIES) { - NET_ERR("Priority %d is too large, maximum is %d", - priority, NET_MAX_PRIORITIES); - return -EINVAL; - } -#endif /* !CONFIG_NET_ALLOW_ANY_PRIORITY */ - if (priority < 0) { - net_pkt_set_ip_dscp(pkt, net_ipv4_get_dscp(tos)); - net_pkt_set_ip_ecn(pkt, net_ipv4_get_ecn(tos)); - } else { - net_pkt_set_priority(pkt, priority); - } - - if (net_ipv4_create(pkt, src, dst) || - icmpv4_create(pkt, NET_ICMPV4_ECHO_REQUEST, 0)) { - goto drop; - } - - echo_req = (struct net_icmpv4_echo_req *)net_pkt_get_data( - pkt, &icmpv4_access); - if (!echo_req) { - goto drop; - } - - echo_req->identifier = htons(identifier); - echo_req->sequence = htons(sequence); - - net_pkt_set_data(pkt, &icmpv4_access); - - if (data != NULL && data_size > 0) { - net_pkt_write(pkt, data, data_size); - } else if (data == NULL && data_size > 0) { - /* Generate payload. */ - if (data_size >= sizeof(uint32_t)) { - uint32_t time_stamp = htonl(k_cycle_get_32()); - - net_pkt_write(pkt, &time_stamp, sizeof(time_stamp)); - data_size -= sizeof(time_stamp); - } - - for (size_t i = 0; i < data_size; i++) { - net_pkt_write_u8(pkt, (uint8_t)i); - } - } else { - /* No payload. */ - } - - net_pkt_cursor_init(pkt); - - net_ipv4_finalize(pkt, IPPROTO_ICMP); - - NET_DBG("Sending ICMPv4 Echo Request type %d from %s to %s", - NET_ICMPV4_ECHO_REQUEST, - net_sprint_ipv4_addr(src), - net_sprint_ipv4_addr(dst)); - - if (net_send_data(pkt) >= 0) { - net_stats_update_icmp_sent(iface); - return 0; - } - - net_stats_update_icmp_drop(iface); - - ret = -EIO; - -drop: - net_pkt_unref(pkt); - - return ret; + return -EIO; } int net_icmpv4_send_error(struct net_pkt *orig, uint8_t type, uint8_t code) @@ -671,7 +564,7 @@ int net_icmpv4_send_error(struct net_pkt *orig, uint8_t type, uint8_t code) if (net_ipv4_create(pkt, (struct in_addr *)ip_hdr->dst, (struct in_addr *)ip_hdr->src) || - icmpv4_create(pkt, type, code) || + net_icmpv4_create(pkt, type, code) || net_pkt_memset(pkt, 0, NET_ICMPV4_UNUSED_LEN) || net_pkt_copy(pkt, orig, copy_len)) { goto drop; @@ -703,23 +596,13 @@ int net_icmpv4_send_error(struct net_pkt *orig, uint8_t type, uint8_t code) } -void net_icmpv4_register_handler(struct net_icmpv4_handler *handler) -{ - sys_slist_prepend(&handlers, &handler->node); -} - -void net_icmpv4_unregister_handler(struct net_icmpv4_handler *handler) -{ - sys_slist_find_and_remove(&handlers, &handler->node); -} - enum net_verdict net_icmpv4_input(struct net_pkt *pkt, struct net_ipv4_hdr *ip_hdr) { NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_access, struct net_icmp_hdr); struct net_icmp_hdr *icmp_hdr; - struct net_icmpv4_handler *cb; + int ret; icmp_hdr = (struct net_icmp_hdr *)net_pkt_get_data(pkt, &icmp_access); if (!icmp_hdr) { @@ -727,7 +610,8 @@ enum net_verdict net_icmpv4_input(struct net_pkt *pkt, return NET_DROP; } - if (net_if_need_calc_rx_checksum(net_pkt_iface(pkt))) { + if (net_if_need_calc_rx_checksum(net_pkt_iface(pkt)) || + net_pkt_is_ip_reassembled(pkt)) { if (net_calc_chksum_icmpv4(pkt) != 0U) { NET_DBG("DROP: Invalid checksum"); goto drop; @@ -749,26 +633,29 @@ enum net_verdict net_icmpv4_input(struct net_pkt *pkt, net_stats_update_icmp_recv(net_pkt_iface(pkt)); - SYS_SLIST_FOR_EACH_CONTAINER(&handlers, cb, node) { - if (cb->type == icmp_hdr->type && - (cb->code == icmp_hdr->code || cb->code == 0U)) { - return cb->handler(pkt, ip_hdr, icmp_hdr); - } + ret = net_icmp_call_ipv4_handlers(pkt, ip_hdr, icmp_hdr); + if (ret < 0) { + NET_ERR("ICMPv4 handling failure (%d)", ret); } + net_pkt_unref(pkt); + + return NET_OK; + drop: net_stats_update_icmp_drop(net_pkt_iface(pkt)); return NET_DROP; } -static struct net_icmpv4_handler echo_request_handler = { - .type = NET_ICMPV4_ECHO_REQUEST, - .code = 0, - .handler = icmpv4_handle_echo_request, -}; - void net_icmpv4_init(void) { - net_icmpv4_register_handler(&echo_request_handler); + static struct net_icmp_ctx ctx; + int ret; + + ret = net_icmp_init_ctx(&ctx, NET_ICMPV4_ECHO_REQUEST, 0, icmpv4_handle_echo_request); + if (ret < 0) { + NET_ERR("Cannot register %s handler (%d)", STRINGIFY(NET_ICMPV4_ECHO_REQUEST), + ret); + } } diff --git a/subsys/net/ip/icmpv4.h b/subsys/net/ip/icmpv4.h index 492fc6e84a0..ae848c9d964 100644 --- a/subsys/net/ip/icmpv4.h +++ b/subsys/net/ip/icmpv4.h @@ -19,8 +19,6 @@ #include #define NET_ICMPV4_DST_UNREACH 3 /* Destination unreachable */ -#define NET_ICMPV4_ECHO_REQUEST 8 -#define NET_ICMPV4_ECHO_REPLY 0 #define NET_ICMPV4_TIME_EXCEEDED 11 /* Time exceeded */ #define NET_ICMPV4_BAD_IP_HEADER 12 /* Bad IP header */ @@ -36,18 +34,6 @@ struct net_icmpv4_echo_req { uint16_t sequence; } __packed; -typedef enum net_verdict (*icmpv4_callback_handler_t)( - struct net_pkt *pkt, - struct net_ipv4_hdr *ip_hdr, - struct net_icmp_hdr *icmp_hdr); - -struct net_icmpv4_handler { - sys_snode_t node; - icmpv4_callback_handler_t handler; - uint8_t type; - uint8_t code; -}; - /** * @brief Send ICMPv4 error message. * @param pkt Network packet that this error is related to. @@ -57,72 +43,16 @@ struct net_icmpv4_handler { */ int net_icmpv4_send_error(struct net_pkt *pkt, uint8_t type, uint8_t code); -/** - * @brief Send ICMPv4 echo request message. - * - * @param iface Network interface. - * @param dst IPv4 address of the target host. - * @param identifier An identifier to aid in matching Echo Replies - * to this Echo Request. May be zero. - * @param sequence A sequence number to aid in matching Echo Replies - * to this Echo Request. May be zero. - * @param tos IPv4 Type-of-service field value. Represents combined DSCP and ECN - * values. - * @param data Arbitrary payload data that will be included in the - * Echo Reply verbatim. May be NULL. - * @param data_size Size of the Payload Data in bytes. May be zero. In case data - * pointer is NULL, the function will generate the payload up to the requested - * size. - * - * @return Return 0 if the sending succeed, <0 otherwise. - */ -#if defined(CONFIG_NET_NATIVE_IPV4) -int net_icmpv4_send_echo_request(struct net_if *iface, - struct in_addr *dst, - uint16_t identifier, - uint16_t sequence, - uint8_t tos, - int priority, - const void *data, - size_t data_size); -#else -static inline int net_icmpv4_send_echo_request(struct net_if *iface, - struct in_addr *dst, - uint16_t identifier, - uint16_t sequence, - uint8_t tos, - int priority, - const void *data, - size_t data_size) -{ - ARG_UNUSED(iface); - ARG_UNUSED(dst); - ARG_UNUSED(identifier); - ARG_UNUSED(sequence); - ARG_UNUSED(tos); - ARG_UNUSED(priority); - ARG_UNUSED(data); - ARG_UNUSED(data_size); - - return -ENOTSUP; -} -#endif - #if defined(CONFIG_NET_NATIVE_IPV4) -void net_icmpv4_register_handler(struct net_icmpv4_handler *handler); - -void net_icmpv4_unregister_handler(struct net_icmpv4_handler *handler); - enum net_verdict net_icmpv4_input(struct net_pkt *pkt, struct net_ipv4_hdr *ip_hdr); -int net_icmpv4_finalize(struct net_pkt *pkt); +int net_icmpv4_create(struct net_pkt *pkt, uint8_t icmp_type, uint8_t icmp_code); +int net_icmpv4_finalize(struct net_pkt *pkt, bool force_chksum); void net_icmpv4_init(void); #else #define net_icmpv4_init(...) -#define net_icmpv4_register_handler(...) -#define net_icmpv4_unregister_handler(...) #endif #endif /* __ICMPV4_H */ diff --git a/subsys/net/ip/icmpv6.c b/subsys/net/ip/icmpv6.c index 9abc034e1fb..65c01a510c7 100644 --- a/subsys/net/ip/icmpv6.c +++ b/subsys/net/ip/icmpv6.c @@ -17,6 +17,7 @@ LOG_MODULE_REGISTER(net_icmpv6, CONFIG_NET_ICMPV6_LOG_LEVEL); #include #include #include +#include #include "net_private.h" #include "icmpv6.h" #include "ipv6.h" @@ -24,8 +25,6 @@ LOG_MODULE_REGISTER(net_icmpv6, CONFIG_NET_ICMPV6_LOG_LEVEL); #define PKT_WAIT_TIME K_SECONDS(1) -static sys_slist_t handlers; - const char *net_icmpv6_type2str(int icmpv6_type) { switch (icmpv6_type) { @@ -58,17 +57,7 @@ const char *net_icmpv6_type2str(int icmpv6_type) return "?"; } -void net_icmpv6_register_handler(struct net_icmpv6_handler *handler) -{ - sys_slist_prepend(&handlers, &handler->node); -} - -void net_icmpv6_unregister_handler(struct net_icmpv6_handler *handler) -{ - sys_slist_find_and_remove(&handlers, &handler->node); -} - -int net_icmpv6_finalize(struct net_pkt *pkt) +int net_icmpv6_finalize(struct net_pkt *pkt, bool force_chksum) { NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_access, struct net_icmp_hdr); @@ -80,8 +69,9 @@ int net_icmpv6_finalize(struct net_pkt *pkt) } icmp_hdr->chksum = 0U; - if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt))) { + if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt)) || force_chksum) { icmp_hdr->chksum = net_calc_chksum_icmpv6(pkt); + net_pkt_set_chksum_done(pkt, true); } return net_pkt_set_data(pkt, &icmp_access); @@ -105,15 +95,18 @@ int net_icmpv6_create(struct net_pkt *pkt, uint8_t icmp_type, uint8_t icmp_code) return net_pkt_set_data(pkt, &icmp_access); } -static -enum net_verdict icmpv6_handle_echo_request(struct net_pkt *pkt, - struct net_ipv6_hdr *ip_hdr, - struct net_icmp_hdr *icmp_hdr) +static int icmpv6_handle_echo_request(struct net_icmp_ctx *ctx, + struct net_pkt *pkt, + struct net_icmp_ip_hdr *hdr, + struct net_icmp_hdr *icmp_hdr, + void *user_data) { struct net_pkt *reply = NULL; + struct net_ipv6_hdr *ip_hdr = hdr->ipv6; const struct in6_addr *src; int16_t payload_len; + ARG_UNUSED(user_data); ARG_UNUSED(icmp_hdr); NET_DBG("Received Echo Request from %s to %s", @@ -176,9 +169,7 @@ enum net_verdict icmpv6_handle_echo_request(struct net_pkt *pkt, net_stats_update_icmp_sent(net_pkt_iface(reply)); - net_pkt_unref(pkt); - - return NET_OK; + return 0; drop: if (reply) { @@ -187,7 +178,7 @@ enum net_verdict icmpv6_handle_echo_request(struct net_pkt *pkt, net_stats_update_icmp_drop(net_pkt_iface(pkt)); - return NET_DROP; + return -EIO; } int net_icmpv6_send_error(struct net_pkt *orig, uint8_t type, uint8_t code, @@ -336,113 +327,13 @@ int net_icmpv6_send_error(struct net_pkt *orig, uint8_t type, uint8_t code, return err; } -int net_icmpv6_send_echo_request(struct net_if *iface, - struct in6_addr *dst, - uint16_t identifier, - uint16_t sequence, - uint8_t tc, - int priority, - const void *data, - size_t data_size) -{ - NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmpv6_access, - struct net_icmpv6_echo_req); - int ret = -ENOBUFS; - struct net_icmpv6_echo_req *echo_req; - const struct in6_addr *src; - struct net_pkt *pkt; - - src = net_if_ipv6_select_src_addr(iface, dst); - - pkt = net_pkt_alloc_with_buffer(iface, - sizeof(struct net_icmpv6_echo_req) - + data_size, - AF_INET6, IPPROTO_ICMPV6, - PKT_WAIT_TIME); - if (!pkt) { - return -ENOMEM; - } - -#if !defined(CONFIG_NET_ALLOW_ANY_PRIORITY) - if (priority > NET_MAX_PRIORITIES) { - NET_ERR("Priority %d is too large, maximum is %d", - priority, NET_MAX_PRIORITIES); - return -EINVAL; - } -#endif /* !CONFIG_NET_ALLOW_ANY_PRIORITY */ - - if (priority < 0) { - net_pkt_set_ip_dscp(pkt, net_ipv6_get_dscp(tc)); - net_pkt_set_ip_ecn(pkt, net_ipv6_get_ecn(tc)); - } else { - net_pkt_set_priority(pkt, priority); - } - - if (net_ipv6_create(pkt, src, dst) || - net_icmpv6_create(pkt, NET_ICMPV6_ECHO_REQUEST, 0)) { - goto drop; - } - - echo_req = (struct net_icmpv6_echo_req *)net_pkt_get_data( - pkt, &icmpv6_access); - if (!echo_req) { - goto drop; - } - - echo_req->identifier = htons(identifier); - echo_req->sequence = htons(sequence); - - net_pkt_set_data(pkt, &icmpv6_access); - - if (data != NULL && data_size > 0) { - net_pkt_write(pkt, data, data_size); - } else if (data == NULL && data_size > 0) { - /* Generate payload. */ - if (data_size >= sizeof(uint32_t)) { - uint32_t time_stamp = htonl(k_cycle_get_32()); - - net_pkt_write(pkt, &time_stamp, sizeof(time_stamp)); - data_size -= sizeof(time_stamp); - } - - for (size_t i = 0; i < data_size; i++) { - net_pkt_write_u8(pkt, (uint8_t)i); - } - } else { - /* No payload. */ - } - - net_pkt_cursor_init(pkt); - net_ipv6_finalize(pkt, IPPROTO_ICMPV6); - - NET_DBG("Sending ICMPv6 Echo Request type %d from %s to %s", - NET_ICMPV6_ECHO_REQUEST, - net_sprint_ipv6_addr(src), - net_sprint_ipv6_addr(dst)); - - if (net_send_data(pkt) >= 0) { - net_stats_update_icmp_sent(iface); - return 0; - } - - net_stats_update_icmp_drop(iface); - - ret = -EIO; - -drop: - net_pkt_unref(pkt); - - return ret; -} - enum net_verdict net_icmpv6_input(struct net_pkt *pkt, struct net_ipv6_hdr *ip_hdr) { NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_access, struct net_icmp_hdr); struct net_icmp_hdr *icmp_hdr; - struct net_icmpv6_handler *cb; - enum net_verdict res; + int ret; icmp_hdr = (struct net_icmp_hdr *)net_pkt_get_data(pkt, &icmp_access); if (!icmp_hdr) { @@ -451,7 +342,8 @@ enum net_verdict net_icmpv6_input(struct net_pkt *pkt, } - if (net_if_need_calc_rx_checksum(net_pkt_iface(pkt))) { + if (net_if_need_calc_rx_checksum(net_pkt_iface(pkt)) || + net_pkt_is_ip_reassembled(pkt)) { if (net_calc_chksum_icmpv6(pkt) != 0U) { NET_DBG("DROP: invalid checksum"); goto drop; @@ -466,30 +358,29 @@ enum net_verdict net_icmpv6_input(struct net_pkt *pkt, net_stats_update_icmp_recv(net_pkt_iface(pkt)); - SYS_SLIST_FOR_EACH_CONTAINER(&handlers, cb, node) { - if (cb->type == icmp_hdr->type && - (cb->code == icmp_hdr->code || cb->code == 0U)) { - res = cb->handler(pkt, ip_hdr, icmp_hdr); - if (res == NET_CONTINUE) { - continue; - } else { - return res; - } - } + ret = net_icmp_call_ipv6_handlers(pkt, ip_hdr, icmp_hdr); + if (ret < 0) { + NET_ERR("ICMPv6 handling failure (%d)", ret); } + + net_pkt_unref(pkt); + + return NET_OK; + drop: net_stats_update_icmp_drop(net_pkt_iface(pkt)); return NET_DROP; } -static struct net_icmpv6_handler echo_request_handler = { - .type = NET_ICMPV6_ECHO_REQUEST, - .code = 0, - .handler = icmpv6_handle_echo_request, -}; - void net_icmpv6_init(void) { - net_icmpv6_register_handler(&echo_request_handler); + static struct net_icmp_ctx ctx; + int ret; + + ret = net_icmp_init_ctx(&ctx, NET_ICMPV6_ECHO_REQUEST, 0, icmpv6_handle_echo_request); + if (ret < 0) { + NET_ERR("Cannot register %s handler (%d)", STRINGIFY(NET_ICMPV6_ECHO_REQUEST), + ret); + } } diff --git a/subsys/net/ip/icmpv6.h b/subsys/net/ip/icmpv6.h index d71d9959c14..64ee1dfaa7b 100644 --- a/subsys/net/ip/icmpv6.h +++ b/subsys/net/ip/icmpv6.h @@ -144,8 +144,6 @@ struct net_icmpv6_mld_mcast_record { #define NET_ICMPV6_PACKET_TOO_BIG 2 /* Packet too big */ #define NET_ICMPV6_TIME_EXCEEDED 3 /* Time exceeded */ #define NET_ICMPV6_PARAM_PROBLEM 4 /* IPv6 header is bad */ -#define NET_ICMPV6_ECHO_REQUEST 128 -#define NET_ICMPV6_ECHO_REPLY 129 #define NET_ICMPV6_MLD_QUERY 130 /* Multicast Listener Query */ #define NET_ICMPV6_RS 133 /* Router Solicitation */ #define NET_ICMPV6_RA 134 /* Router Advertisement */ @@ -170,20 +168,8 @@ struct net_icmpv6_mld_mcast_record { /* ICMPv6 header has 4 unused bytes that must be zero, RFC 4443 ch 3.1 */ #define NET_ICMPV6_UNUSED_LEN 4 -typedef enum net_verdict (*icmpv6_callback_handler_t)( - struct net_pkt *pkt, - struct net_ipv6_hdr *ip_hdr, - struct net_icmp_hdr *icmp_hdr); - const char *net_icmpv6_type2str(int icmpv6_type); -struct net_icmpv6_handler { - sys_snode_t node; - icmpv6_callback_handler_t handler; - uint8_t type; - uint8_t code; -}; - /** * @brief Send ICMPv6 error message. * @param pkt Network packet that this error is related to. @@ -197,71 +183,16 @@ struct net_icmpv6_handler { int net_icmpv6_send_error(struct net_pkt *pkt, uint8_t type, uint8_t code, uint32_t param); -/** - * @brief Send ICMPv6 echo request message. - * - * @param iface Network interface. - * @param dst IPv6 address of the target host. - * @param identifier An identifier to aid in matching Echo Replies - * to this Echo Request. May be zero. - * @param sequence A sequence number to aid in matching Echo Replies - * to this Echo Request. May be zero. - * @param tc IPv6 Traffic Class field value. Represents combined DSCP and - * ECN values. - * @param data Arbitrary payload data that will be included in the - * Echo Reply verbatim. May be NULL. - * @param data_size Size of the Payload Data in bytes. May be zero. In case data - * pointer is NULL, the function will generate the payload up to the requested - * size. - * - * @return Return 0 if the sending succeed, <0 otherwise. - */ -#if defined(CONFIG_NET_NATIVE_IPV6) -int net_icmpv6_send_echo_request(struct net_if *iface, - struct in6_addr *dst, - uint16_t identifier, - uint16_t sequence, - uint8_t tc, - int priority, - const void *data, - size_t data_size); -#else -static inline int net_icmpv6_send_echo_request(struct net_if *iface, - struct in6_addr *dst, - uint16_t identifier, - uint16_t sequence, - uint8_t tc, - int priority, - const void *data, - size_t data_size) -{ - ARG_UNUSED(iface); - ARG_UNUSED(dst); - ARG_UNUSED(identifier); - ARG_UNUSED(sequence); - ARG_UNUSED(tc); - ARG_UNUSED(priority); - ARG_UNUSED(data); - ARG_UNUSED(data_size); - - return -ENOTSUP; -} -#endif - #if defined(CONFIG_NET_NATIVE_IPV6) -void net_icmpv6_register_handler(struct net_icmpv6_handler *handler); -void net_icmpv6_unregister_handler(struct net_icmpv6_handler *handler); enum net_verdict net_icmpv6_input(struct net_pkt *pkt, struct net_ipv6_hdr *ip_hdr); int net_icmpv6_create(struct net_pkt *pkt, uint8_t icmp_type, uint8_t icmp_code); -int net_icmpv6_finalize(struct net_pkt *pkt); +int net_icmpv6_finalize(struct net_pkt *pkt, bool force_chksum); void net_icmpv6_init(void); #else #define net_icmpv6_init(...) -#define net_icmpv6_register_handler(...) -#define net_icmpv6_unregister_handler(...) #endif #endif /* __ICMPV6_H */ diff --git a/subsys/net/ip/ipv4.c b/subsys/net/ip/ipv4.c index 922068274f7..ce5c1e9986c 100644 --- a/subsys/net/ip/ipv4.c +++ b/subsys/net/ip/ipv4.c @@ -118,12 +118,12 @@ int net_ipv4_finalize(struct net_pkt *pkt, uint8_t next_header_proto) if (IS_ENABLED(CONFIG_NET_UDP) && next_header_proto == IPPROTO_UDP) { - return net_udp_finalize(pkt); + return net_udp_finalize(pkt, false); } else if (IS_ENABLED(CONFIG_NET_TCP) && next_header_proto == IPPROTO_TCP) { - return net_tcp_finalize(pkt); + return net_tcp_finalize(pkt, false); } else if (next_header_proto == IPPROTO_ICMP) { - return net_icmpv4_finalize(pkt); + return net_icmpv4_finalize(pkt, false); } return 0; diff --git a/subsys/net/ip/ipv4_autoconf.c b/subsys/net/ip/ipv4_autoconf.c index eed61e3f2d0..aa18a27ef63 100644 --- a/subsys/net/ip/ipv4_autoconf.c +++ b/subsys/net/ip/ipv4_autoconf.c @@ -18,7 +18,7 @@ LOG_MODULE_REGISTER(net_ipv4_autoconf, CONFIG_NET_IPV4_AUTO_LOG_LEVEL); #include #include #include -#include +#include #include "ipv4_autoconf_internal.h" diff --git a/subsys/net/ip/ipv4_fragment.c b/subsys/net/ip/ipv4_fragment.c index 99297ae5e20..ee6e43c83d3 100644 --- a/subsys/net/ip/ipv4_fragment.c +++ b/subsys/net/ip/ipv4_fragment.c @@ -14,7 +14,7 @@ LOG_MODULE_DECLARE(net_ipv4, CONFIG_NET_IPV4_LOG_LEVEL); #include #include #include -#include +#include #include "net_private.h" #include "connection.h" #include "icmpv4.h" @@ -203,6 +203,7 @@ static void reassemble_packet(struct net_ipv4_reassembly *reass) ipv4_hdr->chksum = net_calc_chksum_ipv4(pkt); net_pkt_set_data(pkt, &ipv4_access); + net_pkt_set_ip_reassembled(pkt, true); LOG_DBG("New pkt %p IPv4 len is %d bytes", pkt, net_pkt_get_len(pkt)); @@ -480,15 +481,19 @@ static int send_ipv4_fragment(struct net_pkt *pkt, uint16_t rand_id, uint16_t fi ipv4_hdr->len = htons((fit_len + net_pkt_ip_hdr_len(pkt))); ipv4_hdr->chksum = 0; - if (net_if_need_calc_tx_checksum(net_pkt_iface(frag_pkt))) { - ipv4_hdr->chksum = net_calc_chksum_ipv4(frag_pkt); - } + ipv4_hdr->chksum = net_calc_chksum_ipv4(frag_pkt); + + net_pkt_set_chksum_done(frag_pkt, true); net_pkt_set_data(frag_pkt, &ipv4_access); net_pkt_set_overwrite(frag_pkt, false); net_pkt_cursor_restore(frag_pkt, &cur); + if (final) { + net_pkt_set_context(frag_pkt, net_pkt_context(pkt)); + } + /* If everything has been ok so far, we can send the packet. */ ret = net_send_data(frag_pkt); if (ret < 0) { @@ -554,6 +559,35 @@ int net_ipv4_send_fragmented_pkt(struct net_if *iface, struct net_pkt *pkt, pkt_len -= net_pkt_ip_hdr_len(pkt); + /* Calculate the L4 checksum (if not done already) before the fragmentation. */ + if (!net_pkt_is_chksum_done(pkt)) { + struct net_pkt_cursor backup; + + net_pkt_cursor_backup(pkt, &backup); + net_pkt_acknowledge_data(pkt, &frag_access); + + switch (frag_hdr->proto) { + case IPPROTO_ICMP: + ret = net_icmpv4_finalize(pkt, true); + break; + case IPPROTO_TCP: + ret = net_tcp_finalize(pkt, true); + break; + case IPPROTO_UDP: + ret = net_udp_finalize(pkt, true); + break; + default: + ret = 0; + break; + } + + if (ret < 0) { + return ret; + } + + net_pkt_cursor_restore(pkt, &backup); + } + while (frag_offset < pkt_len) { bool final = false; @@ -613,15 +647,6 @@ enum net_verdict net_ipv4_prepare_for_send(struct net_pkt *pkt) } } - /* We "fake" the sending of the packet here so that - * tcp.c:tcp_retry_expired() will increase the ref count when re-sending - * the packet. This is crucial to do here and will cause free memory - * access if not done. - */ - if (IS_ENABLED(CONFIG_NET_TCP)) { - net_pkt_set_sent(pkt, true); - } - /* We need to unref here because we simulate the packet being sent. */ net_pkt_unref(pkt); diff --git a/subsys/net/ip/ipv6.c b/subsys/net/ip/ipv6.c index 7ef75831406..4957f1cb557 100644 --- a/subsys/net/ip/ipv6.c +++ b/subsys/net/ip/ipv6.c @@ -120,12 +120,12 @@ int net_ipv6_finalize(struct net_pkt *pkt, uint8_t next_header_proto) if (IS_ENABLED(CONFIG_NET_UDP) && next_header_proto == IPPROTO_UDP) { - return net_udp_finalize(pkt); + return net_udp_finalize(pkt, false); } else if (IS_ENABLED(CONFIG_NET_TCP) && next_header_proto == IPPROTO_TCP) { - return net_tcp_finalize(pkt); + return net_tcp_finalize(pkt, false); } else if (next_header_proto == IPPROTO_ICMPV6) { - return net_icmpv6_finalize(pkt); + return net_icmpv6_finalize(pkt, false); } return 0; diff --git a/subsys/net/ip/ipv6_fragment.c b/subsys/net/ip/ipv6_fragment.c index 959aaef0b16..fda00c59f03 100644 --- a/subsys/net/ip/ipv6_fragment.c +++ b/subsys/net/ip/ipv6_fragment.c @@ -17,7 +17,7 @@ LOG_MODULE_DECLARE(net_ipv6, CONFIG_NET_IPV6_LOG_LEVEL); #include #include #include -#include +#include #include "net_private.h" #include "connection.h" #include "icmpv6.h" @@ -338,6 +338,7 @@ static void reassemble_packet(struct net_ipv6_reassembly *reass) ipv6.hdr->len = htons(len); net_pkt_set_data(pkt, &ipv6_access); + net_pkt_set_ip_reassembled(pkt, true); NET_DBG("New pkt %p IPv6 len is %d bytes", pkt, len + NET_IPV6H_LEN); @@ -635,10 +636,13 @@ static int send_ipv6_fragment(struct net_pkt *pkt, frag_hdr->id = net_pkt_ipv6_fragment_id(pkt); frag_hdr->offset = htons(((frag_offset / 8U) << 3) | !final); + net_pkt_set_chksum_done(frag_pkt, true); + if (net_pkt_set_data(frag_pkt, &frag_access)) { goto fail; } + net_pkt_set_ip_hdr_len(frag_pkt, net_pkt_ip_hdr_len(pkt)); net_pkt_set_ipv6_ext_len(frag_pkt, net_pkt_ipv6_ext_len(pkt) + sizeof(struct net_ipv6_frag_hdr)); @@ -657,6 +661,10 @@ static int send_ipv6_fragment(struct net_pkt *pkt, goto fail; } + if (final) { + net_pkt_set_context(frag_pkt, net_pkt_context(pkt)); + } + /* If everything has been ok so far, we can send the packet. */ ret = net_send_data(frag_pkt); if (ret < 0) { @@ -685,7 +693,6 @@ int net_ipv6_send_fragmented_pkt(struct net_if *iface, struct net_pkt *pkt, uint16_t frag_offset; size_t length; uint8_t next_hdr; - uint8_t last_hdr; int fit_len; int ret; @@ -699,9 +706,7 @@ int net_ipv6_send_fragmented_pkt(struct net_if *iface, struct net_pkt *pkt, net_pkt_cursor_init(pkt); if (net_pkt_skip(pkt, next_hdr_off) || - net_pkt_read_u8(pkt, &next_hdr) || - net_pkt_skip(pkt, last_hdr_off) || - net_pkt_read_u8(pkt, &last_hdr)) { + net_pkt_read_u8(pkt, &next_hdr)) { return -ENOBUFS; } @@ -720,6 +725,31 @@ int net_ipv6_send_fragmented_pkt(struct net_if *iface, struct net_pkt *pkt, frag_offset = 0U; + /* Calculate the L4 checksum (if not done already) before the fragmentation. */ + if (!net_pkt_is_chksum_done(pkt)) { + net_pkt_cursor_init(pkt); + net_pkt_skip(pkt, last_hdr_off); + + switch (next_hdr) { + case IPPROTO_ICMPV6: + ret = net_icmpv6_finalize(pkt, true); + break; + case IPPROTO_TCP: + ret = net_tcp_finalize(pkt, true); + break; + case IPPROTO_UDP: + ret = net_udp_finalize(pkt, true); + break; + default: + ret = 0; + break; + } + + if (ret < 0) { + return ret; + } + } + length = net_pkt_get_len(pkt) - (net_pkt_ip_hdr_len(pkt) + net_pkt_ipv6_ext_len(pkt)); while (length) { diff --git a/subsys/net/ip/ipv6_mld.c b/subsys/net/ip/ipv6_mld.c index 90eb1343f08..e9eb82984f2 100644 --- a/subsys/net/ip/ipv6_mld.c +++ b/subsys/net/ip/ipv6_mld.c @@ -17,6 +17,7 @@ LOG_MODULE_DECLARE(net_ipv6, CONFIG_NET_IPV6_LOG_LEVEL); #include #include #include +#include #include "net_private.h" #include "connection.h" #include "icmpv6.h" @@ -308,12 +309,15 @@ static void send_mld_report(struct net_if *iface) #define dbg_addr_recv(pkt_str, src, dst) \ dbg_addr("Received", pkt_str, src, dst) -static enum net_verdict handle_mld_query(struct net_pkt *pkt, - struct net_ipv6_hdr *ip_hdr, - struct net_icmp_hdr *icmp_hdr) +static int handle_mld_query(struct net_icmp_ctx *ctx, + struct net_pkt *pkt, + struct net_icmp_ip_hdr *hdr, + struct net_icmp_hdr *icmp_hdr, + void *user_data) { NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(mld_access, struct net_icmpv6_mld_query); + struct net_ipv6_hdr *ip_hdr = hdr->ipv6; uint16_t length = net_pkt_get_len(pkt); struct net_icmpv6_mld_query *mld_query; uint16_t pkt_len; @@ -352,23 +356,22 @@ static enum net_verdict handle_mld_query(struct net_pkt *pkt, send_mld_report(net_pkt_iface(pkt)); - net_pkt_unref(pkt); - - return NET_OK; + return 0; drop: net_stats_update_ipv6_mld_drop(net_pkt_iface(pkt)); - return NET_DROP; + return -EIO; } -static struct net_icmpv6_handler mld_query_input_handler = { - .type = NET_ICMPV6_MLD_QUERY, - .code = 0, - .handler = handle_mld_query, -}; - void net_ipv6_mld_init(void) { - net_icmpv6_register_handler(&mld_query_input_handler); + static struct net_icmp_ctx ctx; + int ret; + + ret = net_icmp_init_ctx(&ctx, NET_ICMPV6_MLD_QUERY, 0, handle_mld_query); + if (ret < 0) { + NET_ERR("Cannot register %s handler (%d)", STRINGIFY(NET_ICMPV6_MLD_QUERY), + ret); + } } diff --git a/subsys/net/ip/ipv6_nbr.c b/subsys/net/ip/ipv6_nbr.c index cba36f41d50..ebf8a6bc5b7 100644 --- a/subsys/net/ip/ipv6_nbr.c +++ b/subsys/net/ip/ipv6_nbr.c @@ -24,6 +24,7 @@ LOG_MODULE_DECLARE(net_ipv6, CONFIG_NET_IPV6_LOG_LEVEL); #include #include #include +#include #include "net_private.h" #include "connection.h" #include "icmpv6.h" @@ -807,16 +808,6 @@ enum net_verdict net_ipv6_prepare_for_send(struct net_pkt *pkt) } } - /* We "fake" the sending of the packet here so that - * tcp.c:tcp_retry_expired() will increase the ref - * count when re-sending the packet. This is crucial - * thing to do here and will cause free memory access - * if not done. - */ - if (IS_ENABLED(CONFIG_NET_TCP)) { - net_pkt_set_sent(pkt, true); - } - /* We need to unref here because we simulate the packet * sending. */ @@ -1141,13 +1132,16 @@ static void ns_routing_info(struct net_pkt *pkt, } } -static enum net_verdict handle_ns_input(struct net_pkt *pkt, - struct net_ipv6_hdr *ip_hdr, - struct net_icmp_hdr *icmp_hdr) +static int handle_ns_input(struct net_icmp_ctx *ctx, + struct net_pkt *pkt, + struct net_icmp_ip_hdr *hdr, + struct net_icmp_hdr *icmp_hdr, + void *user_data) { NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ns_access, struct net_icmpv6_ns_hdr); NET_PKT_DATA_ACCESS_DEFINE(nd_access, struct net_icmpv6_nd_opt_hdr); + struct net_ipv6_hdr *ip_hdr = hdr->ipv6; uint16_t length = net_pkt_get_len(pkt); uint8_t flags = 0U; bool routing = false; @@ -1389,18 +1383,17 @@ static enum net_verdict handle_ns_input(struct net_pkt *pkt, if (!net_ipv6_send_na(net_pkt_iface(pkt), na_src, na_dst, tgt, flags)) { - net_pkt_unref(pkt); - return NET_OK; + return 0; } NET_DBG("DROP: Cannot send NA"); - return NET_DROP; + return -EIO; drop: net_stats_update_ipv6_nd_drop(net_pkt_iface(pkt)); - return NET_DROP; + return -EIO; } #endif /* CONFIG_NET_IPV6_NBR_CACHE */ @@ -1722,13 +1715,16 @@ static inline bool handle_na_neighbor(struct net_pkt *pkt, return true; } -static enum net_verdict handle_na_input(struct net_pkt *pkt, - struct net_ipv6_hdr *ip_hdr, - struct net_icmp_hdr *icmp_hdr) +static int handle_na_input(struct net_icmp_ctx *ctx, + struct net_pkt *pkt, + struct net_icmp_ip_hdr *hdr, + struct net_icmp_hdr *icmp_hdr, + void *user_data) { NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(na_access, struct net_icmpv6_na_hdr); NET_PKT_DATA_ACCESS_DEFINE(nd_access, struct net_icmpv6_nd_opt_hdr); + struct net_ipv6_hdr *ip_hdr = hdr->ipv6; uint16_t length = net_pkt_get_len(pkt); uint16_t tllao_offset = 0U; struct net_icmpv6_nd_opt_hdr *nd_opt_hdr; @@ -1825,14 +1821,12 @@ static enum net_verdict handle_na_input(struct net_pkt *pkt, goto drop; } - net_pkt_unref(pkt); - - return NET_OK; + return 0; drop: net_stats_update_ipv6_nd_drop(net_pkt_iface(pkt)); - return NET_DROP; + return -EIO; } int net_ipv6_send_ns(struct net_if *iface, @@ -2393,13 +2387,16 @@ static inline bool handle_ra_rdnss(struct net_pkt *pkt, uint8_t len) } #endif -static enum net_verdict handle_ra_input(struct net_pkt *pkt, - struct net_ipv6_hdr *ip_hdr, - struct net_icmp_hdr *icmp_hdr) +static int handle_ra_input(struct net_icmp_ctx *ctx, + struct net_pkt *pkt, + struct net_icmp_ip_hdr *hdr, + struct net_icmp_hdr *icmp_hdr, + void *user_data) { NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ra_access, struct net_icmpv6_ra_hdr); NET_PKT_DATA_ACCESS_DEFINE(nd_access, struct net_icmpv6_nd_opt_hdr); + struct net_ipv6_hdr *ip_hdr = hdr->ipv6; uint16_t length = net_pkt_get_len(pkt); struct net_nbr *nbr = NULL; struct net_icmpv6_nd_opt_hdr *nd_opt_hdr; @@ -2408,6 +2405,8 @@ static enum net_verdict handle_ra_input(struct net_pkt *pkt, uint32_t mtu, reachable_time, retrans_timer; uint16_t router_lifetime; + ARG_UNUSED(user_data); + if (net_if_flag_is_set(net_pkt_iface(pkt), NET_IF_IPV6_NO_ND)) { goto drop; } @@ -2608,50 +2607,54 @@ static enum net_verdict handle_ra_input(struct net_pkt *pkt, /* Cancel the RS timer on iface */ net_if_stop_rs(net_pkt_iface(pkt)); - net_pkt_unref(pkt); - - return NET_OK; + return 0; drop: net_stats_update_ipv6_nd_drop(net_pkt_iface(pkt)); - return NET_DROP; + return -EIO; } #endif /* CONFIG_NET_IPV6_ND */ #if defined(CONFIG_NET_IPV6_NBR_CACHE) -static struct net_icmpv6_handler ns_input_handler = { - .type = NET_ICMPV6_NS, - .code = 0, - .handler = handle_ns_input, -}; - -static struct net_icmpv6_handler na_input_handler = { - .type = NET_ICMPV6_NA, - .code = 0, - .handler = handle_na_input, -}; +static struct net_icmp_ctx ns_ctx; +static struct net_icmp_ctx na_ctx; #endif /* CONFIG_NET_IPV6_NBR_CACHE */ #if defined(CONFIG_NET_IPV6_ND) -static struct net_icmpv6_handler ra_input_handler = { - .type = NET_ICMPV6_RA, - .code = 0, - .handler = handle_ra_input, -}; +static struct net_icmp_ctx ra_ctx; #endif /* CONFIG_NET_IPV6_ND */ void net_ipv6_nbr_init(void) { + int ret; + #if defined(CONFIG_NET_IPV6_NBR_CACHE) - net_icmpv6_register_handler(&ns_input_handler); - net_icmpv6_register_handler(&na_input_handler); + ret = net_icmp_init_ctx(&ns_ctx, NET_ICMPV6_NS, 0, handle_ns_input); + if (ret < 0) { + NET_ERR("Cannot register %s handler (%d)", STRINGIFY(NET_ICMPV6_NS), + ret); + } + + ret = net_icmp_init_ctx(&na_ctx, NET_ICMPV6_NA, 0, handle_na_input); + if (ret < 0) { + NET_ERR("Cannot register %s handler (%d)", STRINGIFY(NET_ICMPV6_NA), + ret); + } + k_work_init_delayable(&ipv6_ns_reply_timer, ipv6_ns_reply_timeout); k_sem_init(&nbr_lock, 1, K_SEM_MAX_LIMIT); #endif #if defined(CONFIG_NET_IPV6_ND) - net_icmpv6_register_handler(&ra_input_handler); + ret = net_icmp_init_ctx(&ra_ctx, NET_ICMPV6_RA, 0, handle_ra_input); + if (ret < 0) { + NET_ERR("Cannot register %s handler (%d)", STRINGIFY(NET_ICMPV6_RA), + ret); + } + k_work_init_delayable(&ipv6_nd_reachable_timer, ipv6_nd_reachable_timeout); #endif + + ARG_UNUSED(ret); } diff --git a/subsys/net/ip/net_context.c b/subsys/net/ip/net_context.c index 6af67103721..a628297f650 100644 --- a/subsys/net/ip/net_context.c +++ b/subsys/net/ip/net_context.c @@ -15,7 +15,7 @@ LOG_MODULE_REGISTER(net_ctx, CONFIG_NET_CONTEXT_LOG_LEVEL); #include -#include +#include #include #include #include @@ -60,11 +60,73 @@ static struct net_context contexts[NET_MAX_CONTEXT]; */ static struct k_sem contexts_lock; +bool net_context_is_reuseaddr_set(struct net_context *context) +{ +#if defined(CONFIG_NET_CONTEXT_REUSEADDR) + return context->options.reuseaddr; +#else + return false; +#endif +} + +bool net_context_is_reuseport_set(struct net_context *context) +{ +#if defined(CONFIG_NET_CONTEXT_REUSEPORT) + return context->options.reuseport; +#else + return false; +#endif +} + +bool net_context_is_v6only_set(struct net_context *context) +{ +#if defined(CONFIG_NET_IPV4_MAPPING_TO_IPV6) + return context->options.ipv6_v6only; +#else + ARG_UNUSED(context); + + return true; +#endif +} + #if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP) -static int check_used_port(enum net_ip_protocol proto, - uint16_t local_port, - const struct sockaddr *local_addr) +static inline bool is_in_tcp_listen_state(struct net_context *context) +{ +#if defined(CONFIG_NET_TCP) + if (net_context_get_type(context) == SOCK_STREAM && + net_context_get_state(context) == NET_CONTEXT_LISTENING) { + return true; + } + + return false; +#else + return false; +#endif +} + +static inline bool is_in_tcp_time_wait_state(struct net_context *context) +{ +#if defined(CONFIG_NET_TCP) + if (net_context_get_type(context) == SOCK_STREAM) { + const struct tcp *tcp_conn = context->tcp; + if (net_tcp_get_state(tcp_conn) == TCP_TIME_WAIT) { + return true; + } + } + + return false; +#else + return false; +#endif +} + +static int check_used_port(struct net_if *iface, + enum net_ip_protocol proto, + uint16_t local_port, + const struct sockaddr *local_addr, + bool reuseaddr_set, + bool reuseport_set) { int i; @@ -79,31 +141,129 @@ static int check_used_port(enum net_ip_protocol proto, continue; } + if (net_context_is_bound_to_iface(&contexts[i])) { + if (iface != NULL && iface != net_context_get_iface(&contexts[i])) { + continue; + } + } + if (IS_ENABLED(CONFIG_NET_IPV6) && local_addr->sa_family == AF_INET6) { - if (net_sin6_ptr(&contexts[i].local)->sin6_addr == NULL) { + if (net_sin6_ptr(&contexts[i].local)->sin6_addr == NULL || + net_sin6_ptr(&contexts[i].local)->sin6_family != AF_INET6) { continue; } + if ((net_ipv6_is_addr_unspecified( + net_sin6_ptr(&contexts[i].local)->sin6_addr) || + net_ipv6_is_addr_unspecified( + &net_sin6(local_addr)->sin6_addr))) { + if (reuseport_set && + net_context_is_reuseport_set(&contexts[i])) { + /* When both context have the REUSEPORT set, both + * may be unspecified. + */ + continue; + } else if (reuseaddr_set && + !is_in_tcp_listen_state(&contexts[i]) && + !(net_ipv6_is_addr_unspecified( + net_sin6_ptr(&contexts[i].local)->sin6_addr) && + net_ipv6_is_addr_unspecified( + &net_sin6(local_addr)->sin6_addr))) { + /* In case of REUSEADDR, only one context may be + * bound to the unspecified address, but not both. + * Furthermore, in case the existing context is in + * TCP LISTEN state, we ignore the REUSEADDR option + * (Linux behavior). + */ + continue; + } else { + return -EEXIST; + } + } + if (net_ipv6_addr_cmp( net_sin6_ptr(&contexts[i].local)-> sin6_addr, &((struct sockaddr_in6 *) local_addr)->sin6_addr)) { - return -EEXIST; + if (reuseport_set && + net_context_is_reuseport_set(&contexts[i])) { + /* When both context have the REUSEPORT set, both + * may be bound to exactly the same address. + */ + continue; + } else if (reuseaddr_set && + is_in_tcp_time_wait_state(&contexts[i])) { + /* With REUSEADDR, the existing context must be + * in the TCP TIME_WAIT state. + */ + continue; + } else { + return -EEXIST; + } } } else if (IS_ENABLED(CONFIG_NET_IPV4) && local_addr->sa_family == AF_INET) { - if (net_sin_ptr(&contexts[i].local)->sin_addr == NULL) { + /* If there is an IPv6 socket already bound and + * if v6only option is enabled, then it is possible to + * bind IPv4 address to it. + */ + if (net_sin_ptr(&contexts[i].local)->sin_addr == NULL || + ((IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6) ? + net_context_is_v6only_set(&contexts[i]) : true) && + net_sin_ptr(&contexts[i].local)->sin_family != AF_INET)) { continue; } + if ((net_ipv4_is_addr_unspecified( + net_sin_ptr(&contexts[i].local)->sin_addr) || + net_ipv4_is_addr_unspecified( + &net_sin(local_addr)->sin_addr))) { + if (reuseport_set && + net_context_is_reuseport_set(&contexts[i])) { + /* When both context have the REUSEPORT set, both + * may be unspecified. + */ + continue; + } else if (reuseaddr_set && + !is_in_tcp_listen_state(&contexts[i]) && + !(net_ipv4_is_addr_unspecified( + net_sin_ptr(&contexts[i].local)->sin_addr) && + net_ipv4_is_addr_unspecified( + &net_sin(local_addr)->sin_addr))) { + /* In case of REUSEADDR, only one context may be + * bound to the unspecified address, but not both. + * Furthermore, in case the existing context is in + * TCP LISTEN state, we ignore the REUSEADDR option + * (Linux behavior). + */ + continue; + } else { + return -EEXIST; + } + } + if (net_ipv4_addr_cmp( net_sin_ptr(&contexts[i].local)-> sin_addr, &((struct sockaddr_in *) local_addr)->sin_addr)) { - return -EEXIST; + if (reuseport_set && + net_context_is_reuseport_set(&contexts[i])) { + /* When both context have the REUSEPORT set, both + * may be bound to exactly the same address. + */ + continue; + } else if (reuseaddr_set && + is_in_tcp_time_wait_state(&contexts[i])) { + /* With REUSEADDR, the existing context must be + * in the TCP TIME_WAIT state. + */ + continue; + } else { + return -EEXIST; + } } } } @@ -118,8 +278,8 @@ static uint16_t find_available_port(struct net_context *context, do { local_port = sys_rand32_get() | 0x8000; - } while (check_used_port(net_context_get_proto(context), - htons(local_port), addr) == -EEXIST); + } while (check_used_port(NULL, net_context_get_proto(context), + htons(local_port), addr, false, false) == -EEXIST); return htons(local_port); } @@ -132,7 +292,7 @@ bool net_context_port_in_use(enum net_ip_protocol proto, uint16_t local_port, const struct sockaddr *local_addr) { - return check_used_port(proto, htons(local_port), local_addr) != 0; + return check_used_port(NULL, proto, htons(local_port), local_addr, false, false) != 0; } #if defined(CONFIG_NET_CONTEXT_CHECK) @@ -279,7 +439,10 @@ int net_context_get(sa_family_t family, enum net_sock_type type, uint16_t proto, #if defined(CONFIG_NET_CONTEXT_SNDTIMEO) contexts[i].options.sndtimeo = K_FOREVER; #endif - +#if defined(CONFIG_NET_IPV4_MAPPING_TO_IPV6) + /* By default IPv4 and IPv6 are in different port spaces */ + contexts[i].options.ipv6_v6only = true; +#endif if (IS_ENABLED(CONFIG_NET_IP)) { (void)memset(&contexts[i].remote, 0, sizeof(struct sockaddr)); (void)memset(&contexts[i].local, 0, sizeof(struct sockaddr_ptr)); @@ -572,34 +735,36 @@ int net_context_bind(struct net_context *context, const struct sockaddr *addr, return -EADDRNOTAVAIL; } - if (IS_ENABLED(CONFIG_NET_OFFLOAD) && - net_if_is_ip_offloaded(iface)) { - net_context_set_iface(context, iface); - - return net_offload_bind(iface, - context, - addr, - addrlen); - } - k_mutex_lock(&context->lock, K_FOREVER); - ret = 0; - net_context_set_iface(context, iface); net_sin6_ptr(&context->local)->sin6_family = AF_INET6; net_sin6_ptr(&context->local)->sin6_addr = ptr; + + if (IS_ENABLED(CONFIG_NET_OFFLOAD) && net_if_is_ip_offloaded(iface)) { + k_mutex_unlock(&context->lock); + return net_offload_bind(iface, context, addr, addrlen); + } + + ret = 0; if (addr6->sin6_port) { - ret = check_used_port(AF_INET6, addr6->sin6_port, - addr); - if (!ret) { - net_sin6_ptr(&context->local)->sin6_port = - addr6->sin6_port; - } else { + ret = check_used_port(iface, + context->proto, + addr6->sin6_port, + addr, + net_context_is_reuseaddr_set(context), + net_context_is_reuseport_set(context)); + if (ret != 0) { NET_ERR("Port %d is in use!", ntohs(addr6->sin6_port)); + NET_DBG("Interface %d (%p)", + iface ? net_if_get_by_iface(iface) : 0, iface); + ret = -EADDRINUSE; goto unlock_ipv6; + } else { + net_sin6_ptr(&context->local)->sin6_port = + addr6->sin6_port; } } else { addr6->sin6_port = @@ -670,34 +835,36 @@ int net_context_bind(struct net_context *context, const struct sockaddr *addr, return -EADDRNOTAVAIL; } - if (IS_ENABLED(CONFIG_NET_OFFLOAD) && - net_if_is_ip_offloaded(iface)) { - net_context_set_iface(context, iface); - - return net_offload_bind(iface, - context, - addr, - addrlen); - } - k_mutex_lock(&context->lock, K_FOREVER); - ret = 0; - net_context_set_iface(context, iface); net_sin_ptr(&context->local)->sin_family = AF_INET; net_sin_ptr(&context->local)->sin_addr = ptr; + + if (IS_ENABLED(CONFIG_NET_OFFLOAD) && net_if_is_ip_offloaded(iface)) { + k_mutex_unlock(&context->lock); + return net_offload_bind(iface, context, addr, addrlen); + } + + ret = 0; if (addr4->sin_port) { - ret = check_used_port(AF_INET, addr4->sin_port, - addr); - if (!ret) { - net_sin_ptr(&context->local)->sin_port = - addr4->sin_port; - } else { + ret = check_used_port(iface, + context->proto, + addr4->sin_port, + addr, + net_context_is_reuseaddr_set(context), + net_context_is_reuseport_set(context)); + if (ret != 0) { NET_ERR("Port %d is in use!", ntohs(addr4->sin_port)); + ret = -EADDRINUSE; + NET_DBG("Interface %d (%p)", + iface ? net_if_get_by_iface(iface) : 0, iface); goto unlock_ipv4; + } else { + net_sin_ptr(&context->local)->sin_port = + addr4->sin_port; } } else { addr4->sin_port = @@ -1309,6 +1476,88 @@ static int get_context_dscp_ecn(struct net_context *context, #endif } +static int get_context_reuseaddr(struct net_context *context, + void *value, size_t *len) +{ +#if defined(CONFIG_NET_CONTEXT_REUSEADDR) + if (!value || !len) { + return -EINVAL; + } + + if (*len != sizeof(int)) { + return -EINVAL; + } + + if (context->options.reuseaddr == true) { + *((int *)value) = (int) true; + } else { + *((int *)value) = (int) false; + } + + *len = sizeof(int); + + return 0; +#else + return -ENOTSUP; +#endif +} + +static int get_context_reuseport(struct net_context *context, + void *value, size_t *len) +{ +#if defined(CONFIG_NET_CONTEXT_REUSEPORT) + if (!value || !len) { + return -EINVAL; + } + + if (*len != sizeof(int)) { + return -EINVAL; + } + + if (context->options.reuseport == true) { + *((int *)value) = (int) true; + } else { + *((int *)value) = (int) false; + } + + *len = sizeof(int); + + return 0; +#else + return -ENOTSUP; +#endif +} + +static int get_context_ipv6_v6only(struct net_context *context, + void *value, size_t *len) +{ +#if defined(CONFIG_NET_IPV4_MAPPING_TO_IPV6) + if (!value || !len) { + return -EINVAL; + } + + if (*len != sizeof(int)) { + return -EINVAL; + } + + if (context->options.ipv6_v6only == true) { + *((int *)value) = (int) true; + } else { + *((int *)value) = (int) false; + } + + *len = sizeof(int); + + return 0; +#else + ARG_UNUSED(context); + ARG_UNUSED(value); + ARG_UNUSED(len); + + return -ENOTSUP; +#endif +} + /* If buf is not NULL, then use it. Otherwise read the data to be written * to net_pkt from msghdr. */ @@ -1459,10 +1708,7 @@ static void set_pkt_txtime(struct net_pkt *pkt, const struct msghdr *msghdr) if (cmsg->cmsg_len == CMSG_LEN(sizeof(uint64_t)) && cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TXTIME) { - struct net_ptp_time txtime = - ns_to_net_ptp_time(*(net_time_t *)CMSG_DATA(cmsg)); - - net_pkt_set_timestamp(pkt, &txtime); + net_pkt_set_timestamp_ns(pkt, *(net_time_t *)CMSG_DATA(cmsg)); break; } } @@ -1542,8 +1788,21 @@ static int context_sendto(struct net_context *context, } else if (IS_ENABLED(CONFIG_NET_IPV4) && net_context_get_family(context) == AF_INET) { - const struct sockaddr_in *addr4 = - (const struct sockaddr_in *)dst_addr; + const struct sockaddr_in *addr4 = (const struct sockaddr_in *)dst_addr; + struct sockaddr_in mapped; + + /* Get the destination address from the mapped IPv6 address */ + if (IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6) && + addr4->sin_family == AF_INET6 && + net_ipv6_addr_is_v4_mapped(&net_sin6(dst_addr)->sin6_addr)) { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)dst_addr; + + mapped.sin_port = addr6->sin6_port; + mapped.sin_family = AF_INET; + net_ipaddr_copy(&mapped.sin_addr, + (struct in_addr *)(&addr6->sin6_addr.s6_addr32[3])); + addr4 = &mapped; + } if (msghdr) { addr4 = msghdr->msg_name; @@ -2368,6 +2627,76 @@ static int set_context_dscp_ecn(struct net_context *context, #endif } +static int set_context_reuseaddr(struct net_context *context, + const void *value, size_t len) +{ +#if defined(CONFIG_NET_CONTEXT_REUSEADDR) + bool reuseaddr = false; + + if (len != sizeof(int)) { + return -EINVAL; + } + + if (*((int *) value) != 0) { + reuseaddr = true; + } + + context->options.reuseaddr = reuseaddr; + + return 0; +#else + return -ENOTSUP; +#endif +} + +static int set_context_reuseport(struct net_context *context, + const void *value, size_t len) +{ +#if defined(CONFIG_NET_CONTEXT_REUSEPORT) + bool reuseport = false; + + if (len != sizeof(int)) { + return -EINVAL; + } + + if (*((int *) value) != 0) { + reuseport = true; + } + + context->options.reuseport = reuseport; + + return 0; +#else + return -ENOTSUP; +#endif +} + +static int set_context_ipv6_v6only(struct net_context *context, + const void *value, size_t len) +{ +#if defined(CONFIG_NET_IPV4_MAPPING_TO_IPV6) + bool v6only = false; + + if (len != sizeof(int)) { + return -EINVAL; + } + + if (*((int *) value) != 0) { + v6only = true; + } + + context->options.ipv6_v6only = v6only; + + return 0; +#else + ARG_UNUSED(context); + ARG_UNUSED(value); + ARG_UNUSED(len); + + return -ENOTSUP; +#endif +} + int net_context_set_option(struct net_context *context, enum net_context_option option, const void *value, size_t len) @@ -2407,6 +2736,15 @@ int net_context_set_option(struct net_context *context, case NET_OPT_DSCP_ECN: ret = set_context_dscp_ecn(context, value, len); break; + case NET_OPT_REUSEADDR: + ret = set_context_reuseaddr(context, value, len); + break; + case NET_OPT_REUSEPORT: + ret = set_context_reuseport(context, value, len); + break; + case NET_OPT_IPV6_V6ONLY: + ret = set_context_ipv6_v6only(context, value, len); + break; } k_mutex_unlock(&context->lock); @@ -2453,6 +2791,15 @@ int net_context_get_option(struct net_context *context, case NET_OPT_DSCP_ECN: ret = get_context_dscp_ecn(context, value, len); break; + case NET_OPT_REUSEADDR: + ret = get_context_reuseaddr(context, value, len); + break; + case NET_OPT_REUSEPORT: + ret = get_context_reuseport(context, value, len); + break; + case NET_OPT_IPV6_V6ONLY: + ret = get_context_ipv6_v6only(context, value, len); + break; } k_mutex_unlock(&context->lock); diff --git a/subsys/net/ip/net_core.c b/subsys/net/ip/net_core.c index 1f6dac720af..baa8cd695c5 100644 --- a/subsys/net/ip/net_core.c +++ b/subsys/net/ip/net_core.c @@ -36,7 +36,7 @@ LOG_MODULE_REGISTER(net_core, CONFIG_NET_CORE_LOG_LEVEL); #endif #include "net_private.h" -#include "net_shell.h" +#include "shell/net_shell.h" #include "icmpv6.h" #include "ipv6.h" @@ -76,8 +76,7 @@ static inline enum net_verdict process_data(struct net_pkt *pkt, /* If the packet is routed back to us when we have reassembled an IPv4 or IPv6 packet, * then do not pass it to L2 as the packet does not have link layer headers in it. */ - if ((IS_ENABLED(CONFIG_NET_IPV4_FRAGMENT) && net_pkt_ipv4_fragment_more(pkt)) || - (IS_ENABLED(CONFIG_NET_IPV6_FRAGMENT) && net_pkt_ipv6_fragment_start(pkt))) { + if (net_pkt_is_ip_reassembled(pkt)) { locally_routed = true; } diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index 026eaa88b48..00c9c74495d 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -11,8 +11,8 @@ LOG_MODULE_REGISTER(net_if, CONFIG_NET_IF_LOG_LEVEL); #include #include #include -#include -#include +#include +#include #include #include #include @@ -152,19 +152,13 @@ struct net_if *z_impl_net_if_get_by_index(int index) struct net_if *z_vrfy_net_if_get_by_index(int index) { struct net_if *iface; - struct z_object *zo; - int ret; iface = net_if_get_by_index(index); if (!iface) { return NULL; } - zo = z_object_find(iface); - - ret = z_object_validate(zo, K_OBJ_NET_IF, _OBJ_INIT_TRUE); - if (ret != 0) { - z_dump_object_error(ret, iface, zo, K_OBJ_NET_IF); + if (!k_object_is_valid(iface, K_OBJ_NET_IF)) { return NULL; } @@ -249,11 +243,6 @@ static bool net_if_tx(struct net_if *iface, struct net_pkt *pkt) context = net_pkt_context(pkt); if (net_if_flag_is_set(iface, NET_IF_LOWER_UP)) { - if (IS_ENABLED(CONFIG_NET_TCP) && - net_pkt_family(pkt) != AF_UNSPEC) { - net_pkt_set_queued(pkt, false); - } - if (IS_ENABLED(CONFIG_NET_PKT_TXTIME_STATS)) { pkt_priority = net_pkt_priority(pkt); @@ -361,7 +350,7 @@ void net_if_queue_tx(struct net_if *iface, struct net_pkt *pkt) * directly to the driver. */ if ((IS_ENABLED(CONFIG_NET_TC_SKIP_FOR_HIGH_PRIO) && - prio == NET_PRIORITY_CA) || NET_TC_TX_COUNT == 0) { + prio >= NET_PRIORITY_CA) || NET_TC_TX_COUNT == 0) { net_pkt_set_tx_stats_tick(pkt, k_cycle_get_32()); net_if_tx(net_pkt_iface(pkt), pkt); @@ -435,7 +424,7 @@ static inline void init_iface(struct net_if *iface) NET_DBG("On iface %p", iface); #ifdef CONFIG_USERSPACE - z_object_init(iface); + k_object_init(iface); #endif k_mutex_init(&iface->lock); @@ -1599,7 +1588,7 @@ static inline int z_vrfy_net_if_ipv6_addr_lookup_by_index( { struct in6_addr addr_v6; - Z_OOPS(z_user_from_copy(&addr_v6, (void *)addr, sizeof(addr_v6))); + K_OOPS(k_usermode_from_copy(&addr_v6, (void *)addr, sizeof(addr_v6))); return z_impl_net_if_ipv6_addr_lookup_by_index(&addr_v6); } @@ -1939,7 +1928,7 @@ bool z_vrfy_net_if_ipv6_addr_add_by_index(int index, return false; } - Z_OOPS(z_user_from_copy(&addr_v6, (void *)addr, sizeof(addr_v6))); + K_OOPS(k_usermode_from_copy(&addr_v6, (void *)addr, sizeof(addr_v6))); return z_impl_net_if_ipv6_addr_add_by_index(index, &addr_v6, @@ -1975,7 +1964,7 @@ bool z_vrfy_net_if_ipv6_addr_rm_by_index(int index, return false; } - Z_OOPS(z_user_from_copy(&addr_v6, (void *)addr, sizeof(addr_v6))); + K_OOPS(k_usermode_from_copy(&addr_v6, (void *)addr, sizeof(addr_v6))); return z_impl_net_if_ipv6_addr_rm_by_index(index, &addr_v6); } @@ -2868,6 +2857,8 @@ const struct in6_addr *net_if_ipv6_select_src_addr(struct net_if *dst_iface, const struct in6_addr *src = NULL; uint8_t best_match = 0U; + NET_ASSERT(dst); + if (!net_ipv6_is_ll_addr(dst) && !net_ipv6_is_addr_mcast_link(dst)) { /* If caller has supplied interface, then use that */ if (dst_iface) { @@ -2889,9 +2880,15 @@ const struct in6_addr *net_if_ipv6_select_src_addr(struct net_if *dst_iface, if (dst_iface) { src = net_if_ipv6_get_ll(dst_iface, NET_ADDR_PREFERRED); } else { - STRUCT_SECTION_FOREACH(net_if, iface) { - struct in6_addr *addr; + struct in6_addr *addr; + + addr = net_if_ipv6_get_ll(net_if_get_default(), NET_ADDR_PREFERRED); + if (addr) { + src = addr; + goto out; + } + STRUCT_SECTION_FOREACH(net_if, iface) { addr = net_if_ipv6_get_ll(iface, NET_ADDR_PREFERRED); if (addr) { @@ -2904,7 +2901,6 @@ const struct in6_addr *net_if_ipv6_select_src_addr(struct net_if *dst_iface, if (!src) { src = net_ipv6_unspecified_address(); - goto out; } out: @@ -3404,6 +3400,8 @@ const struct in_addr *net_if_ipv4_select_src_addr(struct net_if *dst_iface, const struct in_addr *src = NULL; uint8_t best_match = 0U; + NET_ASSERT(dst); + if (!net_ipv4_is_ll_addr(dst)) { /* If caller has supplied interface, then use that */ @@ -3426,9 +3424,15 @@ const struct in_addr *net_if_ipv4_select_src_addr(struct net_if *dst_iface, if (dst_iface) { src = net_if_ipv4_get_ll(dst_iface, NET_ADDR_PREFERRED); } else { - STRUCT_SECTION_FOREACH(net_if, iface) { - struct in_addr *addr; + struct in_addr *addr; + + addr = net_if_ipv4_get_ll(net_if_get_default(), NET_ADDR_PREFERRED); + if (addr) { + src = addr; + goto out; + } + STRUCT_SECTION_FOREACH(net_if, iface) { addr = net_if_ipv4_get_ll(iface, NET_ADDR_PREFERRED); if (addr) { @@ -3453,8 +3457,6 @@ const struct in_addr *net_if_ipv4_select_src_addr(struct net_if *dst_iface, if (!src) { src = net_ipv4_unspecified_address(); } - - goto out; } out: @@ -3523,7 +3525,7 @@ static inline int z_vrfy_net_if_ipv4_addr_lookup_by_index( { struct in_addr addr_v4; - Z_OOPS(z_user_from_copy(&addr_v4, (void *)addr, sizeof(addr_v4))); + K_OOPS(k_usermode_from_copy(&addr_v4, (void *)addr, sizeof(addr_v4))); return z_impl_net_if_ipv4_addr_lookup_by_index(&addr_v4); } @@ -3575,7 +3577,7 @@ bool z_vrfy_net_if_ipv4_set_netmask_by_index(int index, return false; } - Z_OOPS(z_user_from_copy(&netmask_addr, (void *)netmask, + K_OOPS(k_usermode_from_copy(&netmask_addr, (void *)netmask, sizeof(netmask_addr))); return z_impl_net_if_ipv4_set_netmask_by_index(index, &netmask_addr); @@ -3628,7 +3630,7 @@ bool z_vrfy_net_if_ipv4_set_gw_by_index(int index, return false; } - Z_OOPS(z_user_from_copy(&gw_addr, (void *)gw, sizeof(gw_addr))); + K_OOPS(k_usermode_from_copy(&gw_addr, (void *)gw, sizeof(gw_addr))); return z_impl_net_if_ipv4_set_gw_by_index(index, &gw_addr); } @@ -3802,7 +3804,7 @@ bool z_vrfy_net_if_ipv4_addr_add_by_index(int index, return false; } - Z_OOPS(z_user_from_copy(&addr_v4, (void *)addr, sizeof(addr_v4))); + K_OOPS(k_usermode_from_copy(&addr_v4, (void *)addr, sizeof(addr_v4))); return z_impl_net_if_ipv4_addr_add_by_index(index, &addr_v4, @@ -3838,7 +3840,7 @@ bool z_vrfy_net_if_ipv4_addr_rm_by_index(int index, return false; } - Z_OOPS(z_user_from_copy(&addr_v4, (void *)addr, sizeof(addr_v4))); + K_OOPS(k_usermode_from_copy(&addr_v4, (void *)addr, sizeof(addr_v4))); return (uint32_t)z_impl_net_if_ipv4_addr_rm_by_index(index, &addr_v4); } @@ -4117,42 +4119,13 @@ enum net_verdict net_if_recv_data(struct net_if *iface, struct net_pkt *pkt) { if (IS_ENABLED(CONFIG_NET_PROMISCUOUS_MODE) && net_if_is_promisc(iface)) { - /* If the packet is not for us and the promiscuous - * mode is enabled, then increase the ref count so - * that net_core.c:processing_data() will not free it. - * The promiscuous mode handler must free the packet - * after it has finished working with it. - * - * If packet is for us, then NET_CONTINUE is returned. - * In this case we must clone the packet, as the packet - * could be manipulated by other part of the stack. - */ - enum net_verdict verdict; struct net_pkt *new_pkt; - /* This protects pkt so that it will not be freed by L2 recv() - */ - net_pkt_ref(pkt); - - verdict = net_if_l2(iface)->recv(iface, pkt); - if (verdict == NET_CONTINUE) { - new_pkt = net_pkt_clone(pkt, K_NO_WAIT); - } else { - new_pkt = net_pkt_ref(pkt); - } - - /* L2 has modified the buffer starting point, it is easier - * to re-initialize the cursor rather than updating it. - */ - net_pkt_cursor_init(new_pkt); + new_pkt = net_pkt_clone(pkt, K_NO_WAIT); if (net_promisc_mode_input(new_pkt) == NET_DROP) { net_pkt_unref(new_pkt); } - - net_pkt_unref(pkt); - - return verdict; } return net_if_l2(iface)->recv(iface, pkt); @@ -4236,7 +4209,7 @@ void net_if_foreach(net_if_cb_t cb, void *user_data) } } -static inline bool is_iface_offloaded(struct net_if *iface) +bool net_if_is_offloaded(struct net_if *iface) { return (IS_ENABLED(CONFIG_NET_OFFLOAD) && net_if_is_ip_offloaded(iface)) || @@ -4256,7 +4229,7 @@ static void notify_iface_up(struct net_if *iface) } else #endif /* CONFIG_NET_L2_CANBUS_RAW */ { - if (!is_iface_offloaded(iface)) { + if (!net_if_is_offloaded(iface)) { NET_ASSERT(net_if_get_link_addr(iface)->addr != NULL); } } @@ -4268,7 +4241,7 @@ static void notify_iface_up(struct net_if *iface) /* If the interface is only having point-to-point traffic then we do * not need to run DAD etc for it. */ - if (!is_iface_offloaded(iface) && + if (!net_if_is_offloaded(iface) && !(l2_flags_get(iface) & NET_L2_POINT_TO_POINT)) { iface_ipv6_start(iface); net_ipv4_autoconf_start(iface); @@ -4281,7 +4254,7 @@ static void notify_iface_down(struct net_if *iface) net_mgmt_event_notify(NET_EVENT_IF_DOWN, iface); net_virtual_disable(iface); - if (!is_iface_offloaded(iface) && + if (!net_if_is_offloaded(iface) && !(l2_flags_get(iface) & NET_L2_POINT_TO_POINT)) { net_ipv4_autoconf_reset(iface); } @@ -4644,8 +4617,12 @@ bool net_if_is_suspended(struct net_if *iface) #endif /* CONFIG_NET_POWER_MANAGEMENT */ #if defined(CONFIG_NET_PKT_TIMESTAMP_THREAD) -static void net_tx_ts_thread(void) +static void net_tx_ts_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct net_pkt *pkt; NET_DBG("Starting TX timestamp callback thread"); @@ -4712,7 +4689,7 @@ void net_if_add_tx_timestamp(struct net_pkt *pkt) bool net_if_is_wifi(struct net_if *iface) { - if (is_iface_offloaded(iface)) { + if (net_if_is_offloaded(iface)) { return net_off_is_wifi_offloaded(iface); } #if defined(CONFIG_NET_L2_ETHERNET) @@ -4899,6 +4876,16 @@ void net_if_init(void) goto out; } +#if defined(CONFIG_ASSERT) + /* Do extra check that verifies that interface count is properly + * done. + */ + int count_if; + + NET_IFACE_COUNT(&count_if); + NET_ASSERT(count_if == if_count); +#endif + iface_ipv6_init(if_count); iface_ipv4_init(if_count); iface_router_init(); @@ -4906,7 +4893,7 @@ void net_if_init(void) #if defined(CONFIG_NET_PKT_TIMESTAMP_THREAD) k_thread_create(&tx_thread_ts, tx_ts_stack, K_KERNEL_STACK_SIZEOF(tx_ts_stack), - (k_thread_entry_t)net_tx_ts_thread, + net_tx_ts_thread, NULL, NULL, NULL, K_PRIO_COOP(1), 0, K_NO_WAIT); k_thread_name_set(&tx_thread_ts, "tx_tstamp"); #endif /* CONFIG_NET_PKT_TIMESTAMP_THREAD */ diff --git a/subsys/net/ip/net_mgmt.c b/subsys/net/ip/net_mgmt.c index 94dac5ef6ef..d26503b2858 100644 --- a/subsys/net/ip/net_mgmt.c +++ b/subsys/net/ip/net_mgmt.c @@ -189,8 +189,12 @@ static inline void mgmt_run_callbacks(const struct mgmt_event_entry * const mgmt #endif } -static void mgmt_thread(void) +static void mgmt_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct mgmt_event_entry mgmt_event; while (1) { @@ -236,29 +240,32 @@ static int mgmt_event_wait_call(struct net_if *iface, net_mgmt_add_event_callback(&sync); ret = k_sem_take(sync.sync_call, timeout); - if (ret == -EAGAIN) { - ret = -ETIMEDOUT; - } else { - if (!ret) { - if (raised_event) { - *raised_event = sync.raised_event; - } + if (ret < 0) { + if (ret == -EAGAIN) { + ret = -ETIMEDOUT; + } - if (event_iface) { - *event_iface = sync_data.iface; - } + net_mgmt_del_event_callback(&sync); + return ret; + } + + if (raised_event) { + *raised_event = sync.raised_event; + } + + if (event_iface) { + *event_iface = sync_data.iface; + } #ifdef CONFIG_NET_MGMT_EVENT_INFO - if (info) { - *info = sync.info; + if (info) { + *info = sync.info; - if (info_length) { - *info_length = sync.info_length; - } - } -#endif /* CONFIG_NET_MGMT_EVENT_INFO */ + if (info_length) { + *info_length = sync.info_length; } } +#endif /* CONFIG_NET_MGMT_EVENT_INFO */ return ret; } @@ -340,7 +347,7 @@ void net_mgmt_event_init(void) k_thread_create(&mgmt_thread_data, mgmt_stack, K_KERNEL_STACK_SIZEOF(mgmt_stack), - (k_thread_entry_t)mgmt_thread, NULL, NULL, NULL, + mgmt_thread, NULL, NULL, NULL, THREAD_PRIORITY, 0, K_NO_WAIT); k_thread_name_set(&mgmt_thread_data, "net_mgmt"); diff --git a/subsys/net/ip/net_pkt.c b/subsys/net/ip/net_pkt.c index fb44490dd2b..38fc288d8f5 100644 --- a/subsys/net/ip/net_pkt.c +++ b/subsys/net/ip/net_pkt.c @@ -1870,6 +1870,11 @@ static void clone_pkt_attributes(struct net_pkt *pkt, struct net_pkt *clone_pkt) net_pkt_set_priority(clone_pkt, net_pkt_priority(pkt)); net_pkt_set_orig_iface(clone_pkt, net_pkt_orig_iface(pkt)); net_pkt_set_captured(clone_pkt, net_pkt_is_captured(pkt)); + net_pkt_set_eof(clone_pkt, net_pkt_eof(pkt)); + net_pkt_set_ptp(clone_pkt, net_pkt_is_ptp(pkt)); + net_pkt_set_forwarding(clone_pkt, net_pkt_forwarding(pkt)); + net_pkt_set_chksum_done(clone_pkt, net_pkt_is_chksum_done(pkt)); + net_pkt_set_ip_reassembled(pkt, net_pkt_is_ip_reassembled(pkt)); net_pkt_set_l2_bridged(clone_pkt, net_pkt_is_l2_bridged(pkt)); net_pkt_set_l2_processed(clone_pkt, net_pkt_is_l2_processed(pkt)); diff --git a/subsys/net/ip/net_private.h b/subsys/net/ip/net_private.h index c2b80aa4f05..0906a7a28b1 100644 --- a/subsys/net/ip/net_private.h +++ b/subsys/net/ip/net_private.h @@ -14,6 +14,7 @@ #include #include #include +#include #ifdef CONFIG_NET_MGMT_EVENT_INFO @@ -58,9 +59,19 @@ extern void net_if_stats_reset_all(void); extern void net_process_rx_packet(struct net_pkt *pkt); extern void net_process_tx_packet(struct net_pkt *pkt); +extern int net_icmp_call_ipv4_handlers(struct net_pkt *pkt, + struct net_ipv4_hdr *ipv4_hdr, + struct net_icmp_hdr *icmp_hdr); +extern int net_icmp_call_ipv6_handlers(struct net_pkt *pkt, + struct net_ipv6_hdr *ipv6_hdr, + struct net_icmp_hdr *icmp_hdr); + #if defined(CONFIG_NET_NATIVE) || defined(CONFIG_NET_OFFLOAD) extern void net_context_init(void); extern const char *net_context_state(struct net_context *context); +extern bool net_context_is_reuseaddr_set(struct net_context *context); +extern bool net_context_is_reuseport_set(struct net_context *context); +extern bool net_context_is_v6only_set(struct net_context *context); extern void net_pkt_init(void); extern void net_tc_tx_init(void); extern void net_tc_rx_init(void); @@ -74,6 +85,16 @@ static inline const char *net_context_state(struct net_context *context) ARG_UNUSED(context); return NULL; } +static inline bool net_context_is_reuseaddr_set(struct net_context *context) +{ + ARG_UNUSED(context); + return false; +} +static inline bool net_context_is_reuseport_set(struct net_context *context) +{ + ARG_UNUSED(context); + return false; +} #endif #if defined(CONFIG_NET_NATIVE) @@ -120,7 +141,25 @@ static inline void net_coap_init(void) } #endif +#if defined(CONFIG_NET_SOCKETS_OBJ_CORE) +struct sock_obj_type_raw_stats { + uint64_t sent; + uint64_t received; +}; +struct sock_obj { + struct net_socket_register *reg; + uint64_t create_time; /* in ticks */ + k_tid_t creator; + int fd; + int socket_family; + int socket_type; + int socket_proto; + bool init_done; + struct k_obj_core obj_core; + struct sock_obj_type_raw_stats stats; +}; +#endif /* CONFIG_NET_SOCKETS_OBJ_CORE */ #if defined(CONFIG_NET_GPTP) /** diff --git a/subsys/net/ip/net_shell.c b/subsys/net/ip/net_shell.c deleted file mode 100644 index 87995ccabb3..00000000000 --- a/subsys/net/ip/net_shell.c +++ /dev/null @@ -1,6731 +0,0 @@ -/** @file - * @brief Network shell module - * - * Provide some networking shell commands that can be useful to applications. - */ - -/* - * Copyright (c) 2016 Intel Corporation - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -LOG_MODULE_REGISTER(net_shell, LOG_LEVEL_DBG); - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#if defined(CONFIG_NET_L2_ETHERNET) && defined(CONFIG_NET_L2_ETHERNET_MGMT) -#include -#include -#endif /* CONFIG_NET_L2_ETHERNET */ - -#include "route.h" -#include "icmpv6.h" -#include "icmpv4.h" -#include "connection.h" - -#if defined(CONFIG_NET_TCP) -#include "tcp_internal.h" -#include -#endif - -#include "ipv6.h" - -#if defined(CONFIG_NET_ARP) -#include "ethernet/arp.h" -#endif - -#if defined(CONFIG_NET_L2_ETHERNET) -#include -#endif - -#if defined(CONFIG_NET_L2_ETHERNET_MGMT) -#include -#endif - -#if defined(CONFIG_NET_L2_VIRTUAL) -#include -#endif - -#if defined(CONFIG_NET_L2_VIRTUAL_MGMT) -#include -#endif - -#include - -#if defined(CONFIG_NET_GPTP) -#include -#include "ethernet/gptp/gptp_messages.h" -#include "ethernet/gptp/gptp_md.h" -#include "ethernet/gptp/gptp_state.h" -#include "ethernet/gptp/gptp_data_set.h" -#include "ethernet/gptp/gptp_private.h" -#endif - -#if defined(CONFIG_NET_L2_PPP) -#include -#include "ppp/ppp_internal.h" -#endif - -#include "net_shell.h" -#include "net_stats.h" - -#include -#include "websocket/websocket_internal.h" - -#define PR(fmt, ...) \ - shell_fprintf(sh, SHELL_NORMAL, fmt, ##__VA_ARGS__) - -#define PR_SHELL(sh, fmt, ...) \ - shell_fprintf(sh, SHELL_NORMAL, fmt, ##__VA_ARGS__) - -#define PR_ERROR(fmt, ...) \ - shell_fprintf(sh, SHELL_ERROR, fmt, ##__VA_ARGS__) - -#define PR_INFO(fmt, ...) \ - shell_fprintf(sh, SHELL_INFO, fmt, ##__VA_ARGS__) - -#define PR_WARNING(fmt, ...) \ - shell_fprintf(sh, SHELL_WARNING, fmt, ##__VA_ARGS__) - -#include "net_private.h" - -struct net_shell_user_data { - const struct shell *sh; - void *user_data; -}; - -static inline const char *addrtype2str(enum net_addr_type addr_type) -{ - switch (addr_type) { - case NET_ADDR_ANY: - return ""; - case NET_ADDR_AUTOCONF: - return "autoconf"; - case NET_ADDR_DHCP: - return "DHCP"; - case NET_ADDR_MANUAL: - return "manual"; - case NET_ADDR_OVERRIDABLE: - return "overridable"; - } - - return ""; -} - -static inline const char *addrstate2str(enum net_addr_state addr_state) -{ - switch (addr_state) { - case NET_ADDR_ANY_STATE: - return ""; - case NET_ADDR_TENTATIVE: - return "tentative"; - case NET_ADDR_PREFERRED: - return "preferred"; - case NET_ADDR_DEPRECATED: - return "deprecated"; - } - - return ""; -} - -static const char *iface2str(struct net_if *iface, const char **extra) -{ -#ifdef CONFIG_NET_L2_IEEE802154 - if (net_if_l2(iface) == &NET_L2_GET_NAME(IEEE802154)) { - if (extra) { - *extra = "============="; - } - - return "IEEE 802.15.4"; - } -#endif - -#ifdef CONFIG_NET_L2_ETHERNET - if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) { - if (extra) { - *extra = "========"; - } - - return "Ethernet"; - } -#endif - -#ifdef CONFIG_NET_L2_VIRTUAL - if (net_if_l2(iface) == &NET_L2_GET_NAME(VIRTUAL)) { - if (extra) { - *extra = "======="; - } - - return "Virtual"; - } -#endif - -#ifdef CONFIG_NET_L2_PPP - if (net_if_l2(iface) == &NET_L2_GET_NAME(PPP)) { - if (extra) { - *extra = "==="; - } - - return "PPP"; - } -#endif - -#ifdef CONFIG_NET_L2_DUMMY - if (net_if_l2(iface) == &NET_L2_GET_NAME(DUMMY)) { - if (extra) { - *extra = "====="; - } - - return "Dummy"; - } -#endif - -#ifdef CONFIG_NET_L2_OPENTHREAD - if (net_if_l2(iface) == &NET_L2_GET_NAME(OPENTHREAD)) { - if (extra) { - *extra = "=========="; - } - - return "OpenThread"; - } -#endif - -#ifdef CONFIG_NET_L2_BT - if (net_if_l2(iface) == &NET_L2_GET_NAME(BLUETOOTH)) { - if (extra) { - *extra = "========="; - } - - return "Bluetooth"; - } -#endif - -#ifdef CONFIG_NET_OFFLOAD - if (net_if_is_ip_offloaded(iface)) { - if (extra) { - *extra = "=========="; - } - - return "IP Offload"; - } -#endif - -#ifdef CONFIG_NET_L2_CANBUS_RAW - if (net_if_l2(iface) == &NET_L2_GET_NAME(CANBUS_RAW)) { - if (extra) { - *extra = "=========="; - } - - return "CANBUS_RAW"; - } -#endif - - if (extra) { - *extra = "=============="; - } - - return ""; -} - -#if defined(CONFIG_NET_L2_ETHERNET) && defined(CONFIG_NET_NATIVE) -struct ethernet_capabilities { - enum ethernet_hw_caps capability; - const char * const description; -}; - -#define EC(cap, desc) { .capability = cap, .description = desc } - -static struct ethernet_capabilities eth_hw_caps[] = { - EC(ETHERNET_HW_TX_CHKSUM_OFFLOAD, "TX checksum offload"), - EC(ETHERNET_HW_RX_CHKSUM_OFFLOAD, "RX checksum offload"), - EC(ETHERNET_HW_VLAN, "Virtual LAN"), - EC(ETHERNET_HW_VLAN_TAG_STRIP, "VLAN Tag stripping"), - EC(ETHERNET_AUTO_NEGOTIATION_SET, "Auto negotiation"), - EC(ETHERNET_LINK_10BASE_T, "10 Mbits"), - EC(ETHERNET_LINK_100BASE_T, "100 Mbits"), - EC(ETHERNET_LINK_1000BASE_T, "1 Gbits"), - EC(ETHERNET_DUPLEX_SET, "Half/full duplex"), - EC(ETHERNET_PTP, "IEEE 802.1AS gPTP clock"), - EC(ETHERNET_QAV, "IEEE 802.1Qav (credit shaping)"), - EC(ETHERNET_QBV, "IEEE 802.1Qbv (scheduled traffic)"), - EC(ETHERNET_QBU, "IEEE 802.1Qbu (frame preemption)"), - EC(ETHERNET_TXTIME, "TXTIME"), - EC(ETHERNET_PROMISC_MODE, "Promiscuous mode"), - EC(ETHERNET_PRIORITY_QUEUES, "Priority queues"), - EC(ETHERNET_HW_FILTERING, "MAC address filtering"), - EC(ETHERNET_DSA_SLAVE_PORT, "DSA slave port"), - EC(ETHERNET_DSA_MASTER_PORT, "DSA master port"), -}; - -static void print_supported_ethernet_capabilities( - const struct shell *sh, struct net_if *iface) -{ - enum ethernet_hw_caps caps = net_eth_get_hw_capabilities(iface); - int i; - - for (i = 0; i < ARRAY_SIZE(eth_hw_caps); i++) { - if (caps & eth_hw_caps[i].capability) { - PR("\t%s\n", eth_hw_caps[i].description); - } - } -} -#endif /* CONFIG_NET_L2_ETHERNET */ - -#if defined(CONFIG_NET_NATIVE) -static const char *iface_flags2str(struct net_if *iface) -{ - static char str[sizeof("POINTOPOINT") + sizeof("PROMISC") + - sizeof("NO_AUTO_START") + sizeof("SUSPENDED") + - sizeof("MCAST_FORWARD") + sizeof("IPv4") + - sizeof("IPv6") + sizeof("NO_ND") + sizeof("NO_MLD")]; - int pos = 0; - - if (net_if_flag_is_set(iface, NET_IF_POINTOPOINT)) { - pos += snprintk(str + pos, sizeof(str) - pos, - "POINTOPOINT,"); - } - - if (net_if_flag_is_set(iface, NET_IF_PROMISC)) { - pos += snprintk(str + pos, sizeof(str) - pos, - "PROMISC,"); - } - - if (net_if_flag_is_set(iface, NET_IF_NO_AUTO_START)) { - pos += snprintk(str + pos, sizeof(str) - pos, - "NO_AUTO_START,"); - } else { - pos += snprintk(str + pos, sizeof(str) - pos, - "AUTO_START,"); - } - - if (net_if_flag_is_set(iface, NET_IF_FORWARD_MULTICASTS)) { - pos += snprintk(str + pos, sizeof(str) - pos, - "MCAST_FORWARD,"); - } - - if (net_if_flag_is_set(iface, NET_IF_IPV4)) { - pos += snprintk(str + pos, sizeof(str) - pos, - "IPv4,"); - } - - if (net_if_flag_is_set(iface, NET_IF_IPV6)) { - pos += snprintk(str + pos, sizeof(str) - pos, - "IPv6,"); - } - - if (net_if_flag_is_set(iface, NET_IF_IPV6_NO_ND)) { - pos += snprintk(str + pos, sizeof(str) - pos, - "NO_ND,"); - } - - if (net_if_flag_is_set(iface, NET_IF_IPV6_NO_MLD)) { - pos += snprintk(str + pos, sizeof(str) - pos, - "NO_MLD,"); - } - - /* get rid of last ',' character */ - str[pos - 1] = '\0'; - - return str; -} -#endif - -static void iface_cb(struct net_if *iface, void *user_data) -{ -#if defined(CONFIG_NET_NATIVE) - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - -#if defined(CONFIG_NET_IPV6) - struct net_if_ipv6_prefix *prefix; - struct net_if_router *router; - struct net_if_ipv6 *ipv6; -#endif -#if defined(CONFIG_NET_IPV4) - struct net_if_ipv4 *ipv4; -#endif -#if defined(CONFIG_NET_VLAN) - struct ethernet_context *eth_ctx; -#endif -#if defined(CONFIG_NET_IP) - struct net_if_addr *unicast; - struct net_if_mcast_addr *mcast; -#endif -#if defined(CONFIG_NET_L2_ETHERNET_MGMT) - struct ethernet_req_params params; - int ret; -#endif - const char *extra; -#if defined(CONFIG_NET_IP) - int i, count; -#endif - - if (data->user_data && data->user_data != iface) { - return; - } - -#if defined(CONFIG_NET_INTERFACE_NAME) - char ifname[CONFIG_NET_INTERFACE_NAME_LEN + 1] = { 0 }; - int ret_name; - - ret_name = net_if_get_name(iface, ifname, sizeof(ifname) - 1); - if (ret_name < 1 || ifname[0] == '\0') { - snprintk(ifname, sizeof(ifname), "?"); - } - - PR("\nInterface %s (%p) (%s) [%d]\n", ifname, iface, iface2str(iface, &extra), - net_if_get_by_iface(iface)); -#else - PR("\nInterface %p (%s) [%d]\n", iface, iface2str(iface, &extra), - net_if_get_by_iface(iface)); -#endif - PR("===========================%s\n", extra); - - if (!net_if_is_up(iface)) { - PR_INFO("Interface is down.\n"); - - /* Show detailed information only when user asks information - * about one specific network interface. - */ - if (data->user_data == NULL) { - return; - } - } - -#ifdef CONFIG_NET_POWER_MANAGEMENT - if (net_if_is_suspended(iface)) { - PR_INFO("Interface is suspended, thus not able to tx/rx.\n"); - } -#endif - -#if defined(CONFIG_NET_L2_VIRTUAL) - if (!sys_slist_is_empty(&iface->config.virtual_interfaces)) { - struct virtual_interface_context *ctx, *tmp; - - PR("Virtual interfaces attached to this : "); - SYS_SLIST_FOR_EACH_CONTAINER_SAFE( - &iface->config.virtual_interfaces, - ctx, tmp, node) { - if (ctx->virtual_iface == iface) { - continue; - } - - PR("%d ", net_if_get_by_iface(ctx->virtual_iface)); - } - - PR("\n"); - } - - if (net_if_l2(iface) == &NET_L2_GET_NAME(VIRTUAL)) { - struct net_if *orig_iface; - char *name, buf[CONFIG_NET_L2_VIRTUAL_MAX_NAME_LEN]; - - name = net_virtual_get_name(iface, buf, sizeof(buf)); - if (!(name && name[0])) { - name = ""; - } - - PR("Name : %s\n", name); - - orig_iface = net_virtual_get_iface(iface); - if (orig_iface == NULL) { - PR("No attached network interface.\n"); - } else { - PR("Attached : %d (%s / %p)\n", - net_if_get_by_iface(orig_iface), - iface2str(orig_iface, NULL), - orig_iface); - } - } -#endif /* CONFIG_NET_L2_VIRTUAL */ - - net_if_lock(iface); - if (net_if_get_link_addr(iface) && - net_if_get_link_addr(iface)->addr) { - PR("Link addr : %s\n", - net_sprint_ll_addr(net_if_get_link_addr(iface)->addr, - net_if_get_link_addr(iface)->len)); - } - net_if_unlock(iface); - - PR("MTU : %d\n", net_if_get_mtu(iface)); - PR("Flags : %s\n", iface_flags2str(iface)); - -#if defined(CONFIG_NET_L2_ETHERNET_MGMT) - if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) { - count = 0; - ret = net_mgmt(NET_REQUEST_ETHERNET_GET_PRIORITY_QUEUES_NUM, - iface, ¶ms, - sizeof(struct ethernet_req_params)); - - if (!ret && params.priority_queues_num) { - count = params.priority_queues_num; - PR("Priority queues:\n"); - for (i = 0; i < count; ++i) { - params.qav_param.queue_id = i; - params.qav_param.type = - ETHERNET_QAV_PARAM_TYPE_STATUS; - ret = net_mgmt( - NET_REQUEST_ETHERNET_GET_QAV_PARAM, - iface, ¶ms, - sizeof(struct ethernet_req_params)); - - PR("\t%d: Qav ", i); - if (ret) { - PR("not supported\n"); - } else { - PR("%s\n", - params.qav_param.enabled ? - "enabled" : - "disabled"); - } - } - } - } -#endif - -#if defined(CONFIG_NET_PROMISCUOUS_MODE) - PR("Promiscuous mode : %s\n", - net_if_is_promisc(iface) ? "enabled" : "disabled"); -#endif - -#if defined(CONFIG_NET_VLAN) - if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) { - eth_ctx = net_if_l2_data(iface); - - if (eth_ctx->vlan_enabled) { - for (i = 0; i < CONFIG_NET_VLAN_COUNT; i++) { - if (eth_ctx->vlan[i].iface != iface || - eth_ctx->vlan[i].tag == - NET_VLAN_TAG_UNSPEC) { - continue; - } - - PR("VLAN tag : %d (0x%x)\n", - eth_ctx->vlan[i].tag, - eth_ctx->vlan[i].tag); - } - } else { - PR("VLAN not enabled\n"); - } - } -#endif - -#ifdef CONFIG_NET_L2_ETHERNET - if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) { - PR("Ethernet capabilities supported:\n"); - print_supported_ethernet_capabilities(sh, iface); - } -#endif /* CONFIG_NET_L2_ETHERNET */ - -#if defined(CONFIG_NET_IPV6) - count = 0; - - if (!net_if_flag_is_set(iface, NET_IF_IPV6)) { - PR("%s not %s for this interface.\n", "IPv6", "enabled"); - ipv6 = NULL; - goto skip_ipv6; - } - - ipv6 = iface->config.ip.ipv6; - - PR("IPv6 unicast addresses (max %d):\n", NET_IF_MAX_IPV6_ADDR); - for (i = 0; ipv6 && i < NET_IF_MAX_IPV6_ADDR; i++) { - unicast = &ipv6->unicast[i]; - - if (!unicast->is_used) { - continue; - } - - PR("\t%s %s %s%s%s\n", - net_sprint_ipv6_addr(&unicast->address.in6_addr), - addrtype2str(unicast->addr_type), - addrstate2str(unicast->addr_state), - unicast->is_infinite ? " infinite" : "", - unicast->is_mesh_local ? " meshlocal" : ""); - count++; - } - - if (count == 0) { - PR("\t\n"); - } - - count = 0; - - PR("IPv6 multicast addresses (max %d):\n", NET_IF_MAX_IPV6_MADDR); - for (i = 0; ipv6 && i < NET_IF_MAX_IPV6_MADDR; i++) { - mcast = &ipv6->mcast[i]; - - if (!mcast->is_used) { - continue; - } - - PR("\t%s\n", net_sprint_ipv6_addr(&mcast->address.in6_addr)); - - count++; - } - - if (count == 0) { - PR("\t\n"); - } - - count = 0; - - PR("IPv6 prefixes (max %d):\n", NET_IF_MAX_IPV6_PREFIX); - for (i = 0; ipv6 && i < NET_IF_MAX_IPV6_PREFIX; i++) { - prefix = &ipv6->prefix[i]; - - if (!prefix->is_used) { - continue; - } - - PR("\t%s/%d%s\n", - net_sprint_ipv6_addr(&prefix->prefix), - prefix->len, prefix->is_infinite ? " infinite" : ""); - - count++; - } - - if (count == 0) { - PR("\t\n"); - } - - router = net_if_ipv6_router_find_default(iface, NULL); - if (router) { - PR("IPv6 default router :\n"); - PR("\t%s%s\n", - net_sprint_ipv6_addr(&router->address.in6_addr), - router->is_infinite ? " infinite" : ""); - } - -skip_ipv6: - - if (ipv6) { - PR("IPv6 hop limit : %d\n", - ipv6->hop_limit); - PR("IPv6 base reachable time : %d\n", - ipv6->base_reachable_time); - PR("IPv6 reachable time : %d\n", - ipv6->reachable_time); - PR("IPv6 retransmit timer : %d\n", - ipv6->retrans_timer); - } -#endif /* CONFIG_NET_IPV6 */ - -#if defined(CONFIG_NET_IPV4) - /* No need to print IPv4 information for interface that does not - * support that protocol. - */ - if ( -#if defined(CONFIG_NET_L2_IEEE802154) - (net_if_l2(iface) == &NET_L2_GET_NAME(IEEE802154)) || -#endif -#if defined(CONFIG_NET_L2_BT) - (net_if_l2(iface) == &NET_L2_GET_NAME(BLUETOOTH)) || -#endif - 0) { - PR_WARNING("%s not %s for this interface.\n", "IPv4", - "supported"); - return; - } - - count = 0; - - if (!net_if_flag_is_set(iface, NET_IF_IPV4)) { - PR("%s not %s for this interface.\n", "IPv4", "enabled"); - ipv4 = NULL; - goto skip_ipv4; - } - - ipv4 = iface->config.ip.ipv4; - - PR("IPv4 unicast addresses (max %d):\n", NET_IF_MAX_IPV4_ADDR); - for (i = 0; ipv4 && i < NET_IF_MAX_IPV4_ADDR; i++) { - unicast = &ipv4->unicast[i]; - - if (!unicast->is_used) { - continue; - } - - PR("\t%s %s %s%s\n", - net_sprint_ipv4_addr(&unicast->address.in_addr), - addrtype2str(unicast->addr_type), - addrstate2str(unicast->addr_state), - unicast->is_infinite ? " infinite" : ""); - - count++; - } - - if (count == 0) { - PR("\t\n"); - } - - count = 0; - - PR("IPv4 multicast addresses (max %d):\n", NET_IF_MAX_IPV4_MADDR); - for (i = 0; ipv4 && i < NET_IF_MAX_IPV4_MADDR; i++) { - mcast = &ipv4->mcast[i]; - - if (!mcast->is_used) { - continue; - } - - PR("\t%s\n", net_sprint_ipv4_addr(&mcast->address.in_addr)); - - count++; - } - - if (count == 0) { - PR("\t\n"); - } - -skip_ipv4: - - if (ipv4) { - PR("IPv4 gateway : %s\n", - net_sprint_ipv4_addr(&ipv4->gw)); - PR("IPv4 netmask : %s\n", - net_sprint_ipv4_addr(&ipv4->netmask)); - } -#endif /* CONFIG_NET_IPV4 */ - -#if defined(CONFIG_NET_DHCPV4) - PR("DHCPv4 lease time : %u\n", - iface->config.dhcpv4.lease_time); - PR("DHCPv4 renew time : %u\n", - iface->config.dhcpv4.renewal_time); - PR("DHCPv4 server : %s\n", - net_sprint_ipv4_addr(&iface->config.dhcpv4.server_id)); - PR("DHCPv4 requested : %s\n", - net_sprint_ipv4_addr(&iface->config.dhcpv4.requested_ip)); - PR("DHCPv4 state : %s\n", - net_dhcpv4_state_name(iface->config.dhcpv4.state)); - PR("DHCPv4 attempts : %d\n", - iface->config.dhcpv4.attempts); -#endif /* CONFIG_NET_DHCPV4 */ - -#if defined(CONFIG_NET_DHCPV6) - PR("DHCPv6 address requested : %s\n", - iface->config.dhcpv6.params.request_addr ? - net_sprint_ipv6_addr(&iface->config.dhcpv6.addr) : "none"); - PR("DHCPv6 prefix requested : %s\n", - iface->config.dhcpv6.params.request_prefix ? - net_sprint_ipv6_addr(&iface->config.dhcpv6.prefix) : "none"); - PR("DHCPv6 state : %s\n", - net_dhcpv6_state_name(iface->config.dhcpv6.state)); - PR("DHCPv6 attempts : %d\n", - iface->config.dhcpv6.retransmissions + 1); -#endif /* CONFIG_NET_DHCPV6 */ - -#else - ARG_UNUSED(iface); - ARG_UNUSED(user_data); - -#endif /* CONFIG_NET_NATIVE */ -} - -#if defined(CONFIG_NET_ROUTE) && defined(CONFIG_NET_NATIVE) -static void route_cb(struct net_route_entry *entry, void *user_data) -{ - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - struct net_if *iface = data->user_data; - struct net_route_nexthop *nexthop_route; - int count; - uint32_t now = k_uptime_get_32(); - - if (entry->iface != iface) { - return; - } - - PR("IPv6 prefix : %s/%d\n", net_sprint_ipv6_addr(&entry->addr), - entry->prefix_len); - - count = 0; - - SYS_SLIST_FOR_EACH_CONTAINER(&entry->nexthop, nexthop_route, node) { - struct net_linkaddr_storage *lladdr; - char remaining_str[sizeof("01234567890 sec")]; - uint32_t remaining; - - if (!nexthop_route->nbr) { - continue; - } - - PR("\tneighbor : %p\t", nexthop_route->nbr); - - if (nexthop_route->nbr->idx == NET_NBR_LLADDR_UNKNOWN) { - PR("addr : \t"); - } else { - lladdr = net_nbr_get_lladdr(nexthop_route->nbr->idx); - - PR("addr : %s\t", net_sprint_ll_addr(lladdr->addr, - lladdr->len)); - } - - if (entry->is_infinite) { - snprintk(remaining_str, sizeof(remaining_str) - 1, - "infinite"); - } else { - remaining = net_timeout_remaining(&entry->lifetime, now); - snprintk(remaining_str, sizeof(remaining_str) - 1, - "%u sec", remaining); - } - - PR("lifetime : %s\n", remaining_str); - - count++; - } - - if (count == 0) { - PR("\t\n"); - } -} - -static void iface_per_route_cb(struct net_if *iface, void *user_data) -{ - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - const char *extra; - - PR("\nIPv6 routes for interface %d (%p) (%s)\n", - net_if_get_by_iface(iface), iface, - iface2str(iface, &extra)); - PR("=========================================%s\n", extra); - - data->user_data = iface; - - net_route_foreach(route_cb, data); -} -#endif /* CONFIG_NET_ROUTE */ - -#if defined(CONFIG_NET_ROUTE_MCAST) && defined(CONFIG_NET_NATIVE) -static void route_mcast_cb(struct net_route_entry_mcast *entry, - void *user_data) -{ - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - struct net_if *iface = data->user_data; - const char *extra; - - if (entry->iface != iface) { - return; - } - - PR("IPv6 multicast route %p for interface %d (%p) (%s)\n", entry, - net_if_get_by_iface(iface), iface, iface2str(iface, &extra)); - PR("===========================================================" - "%s\n", extra); - - PR("IPv6 group : %s\n", net_sprint_ipv6_addr(&entry->group)); - PR("IPv6 group len : %d\n", entry->prefix_len); - PR("Lifetime : %u\n", entry->lifetime); -} - -static void iface_per_mcast_route_cb(struct net_if *iface, void *user_data) -{ - struct net_shell_user_data *data = user_data; - - data->user_data = iface; - - net_route_mcast_foreach(route_mcast_cb, NULL, data); -} -#endif /* CONFIG_NET_ROUTE_MCAST */ - -#if defined(CONFIG_NET_STATISTICS) - -#if NET_TC_COUNT > 1 -static const char *priority2str(enum net_priority priority) -{ - switch (priority) { - case NET_PRIORITY_BK: - return "BK"; /* Background */ - case NET_PRIORITY_BE: - return "BE"; /* Best effort */ - case NET_PRIORITY_EE: - return "EE"; /* Excellent effort */ - case NET_PRIORITY_CA: - return "CA"; /* Critical applications */ - case NET_PRIORITY_VI: - return "VI"; /* Video, < 100 ms latency and jitter */ - case NET_PRIORITY_VO: - return "VO"; /* Voice, < 10 ms latency and jitter */ - case NET_PRIORITY_IC: - return "IC"; /* Internetwork control */ - case NET_PRIORITY_NC: - return "NC"; /* Network control */ - } - - return "??"; -} -#endif - -#if defined(CONFIG_NET_STATISTICS_ETHERNET) && \ - defined(CONFIG_NET_STATISTICS_USER_API) -static void print_eth_stats(struct net_if *iface, struct net_stats_eth *data, - const struct shell *sh) -{ - PR("Statistics for Ethernet interface %p [%d]\n", iface, - net_if_get_by_iface(iface)); - - PR("Bytes received : %u\n", data->bytes.received); - PR("Bytes sent : %u\n", data->bytes.sent); - PR("Packets received : %u\n", data->pkts.rx); - PR("Packets sent : %u\n", data->pkts.tx); - PR("Bcast received : %u\n", data->broadcast.rx); - PR("Bcast sent : %u\n", data->broadcast.tx); - PR("Mcast received : %u\n", data->multicast.rx); - PR("Mcast sent : %u\n", data->multicast.tx); - - PR("Send errors : %u\n", data->errors.tx); - PR("Receive errors : %u\n", data->errors.rx); - PR("Collisions : %u\n", data->collisions); - PR("Send Drops : %u\n", data->tx_dropped); - PR("Send timeouts : %u\n", data->tx_timeout_count); - PR("Send restarts : %u\n", data->tx_restart_queue); - PR("Unknown protocol : %u\n", data->unknown_protocol); - -#if defined(CONFIG_NET_STATISTICS_ETHERNET_VENDOR) - if (data->vendor) { - PR("Vendor specific statistics for Ethernet " - "interface %p [%d]:\n", - iface, net_if_get_by_iface(iface)); - size_t i = 0; - - do { - PR("%s : %u\n", data->vendor[i].key, - data->vendor[i].value); - i++; - } while (data->vendor[i].key); - } -#endif /* CONFIG_NET_STATISTICS_ETHERNET_VENDOR */ -} -#endif /* CONFIG_NET_STATISTICS_ETHERNET && CONFIG_NET_STATISTICS_USER_API */ - -#if defined(CONFIG_NET_STATISTICS_PPP) && \ - defined(CONFIG_NET_STATISTICS_USER_API) -static void print_ppp_stats(struct net_if *iface, struct net_stats_ppp *data, - const struct shell *sh) -{ - PR("Frames recv %u\n", data->pkts.rx); - PR("Frames sent %u\n", data->pkts.tx); - PR("Frames dropped %u\n", data->drop); - PR("Bad FCS %u\n", data->chkerr); -} -#endif /* CONFIG_NET_STATISTICS_PPP && CONFIG_NET_STATISTICS_USER_API */ - -#if !defined(CONFIG_NET_NATIVE) -#define GET_STAT(a, b) 0 -#endif - -#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) || \ - defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) -#if (NET_TC_TX_COUNT > 1) || (NET_TC_RX_COUNT > 1) -static char *get_net_pkt_tc_stats_detail(struct net_if *iface, int i, - bool is_tx) -{ - static char extra_stats[sizeof("\t[0=xxxx us]") + - sizeof("->xxxx") * - NET_PKT_DETAIL_STATS_COUNT]; - int j, total = 0, pos = 0; - - pos += snprintk(extra_stats, sizeof(extra_stats), "\t[0"); - - for (j = 0; j < NET_PKT_DETAIL_STATS_COUNT; j++) { - net_stats_t count = 0; - uint32_t avg; - - if (is_tx) { -#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) && (NET_TC_TX_COUNT > 1) - count = GET_STAT(iface, - tc.sent[i].tx_time_detail[j].count); -#endif - } else { -#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) && (NET_TC_RX_COUNT > 1) - count = GET_STAT(iface, - tc.recv[i].rx_time_detail[j].count); -#endif - } - - if (count == 0) { - break; - } - - if (is_tx) { -#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) && (NET_TC_TX_COUNT > 1) - avg = (uint32_t)(GET_STAT(iface, - tc.sent[i].tx_time_detail[j].sum) / - (uint64_t)count); -#endif - } else { -#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) && (NET_TC_RX_COUNT > 1) - avg = (uint32_t)(GET_STAT(iface, - tc.recv[i].rx_time_detail[j].sum) / - (uint64_t)count); -#endif - } - - if (avg == 0) { - continue; - } - - total += avg; - - pos += snprintk(extra_stats + pos, sizeof(extra_stats) - pos, - "->%u", avg); - } - - if (total == 0U) { - return "\0"; - } - - pos += snprintk(extra_stats + pos, sizeof(extra_stats) - pos, - "=%u us]", total); - - return extra_stats; -} -#endif /* (NET_TC_TX_COUNT > 1) || (NET_TC_RX_COUNT > 1) */ - -#if (NET_TC_TX_COUNT <= 1) || (NET_TC_RX_COUNT <= 1) -static char *get_net_pkt_stats_detail(struct net_if *iface, bool is_tx) -{ - static char extra_stats[sizeof("\t[0=xxxx us]") + sizeof("->xxxx") * - NET_PKT_DETAIL_STATS_COUNT]; - int j, total = 0, pos = 0; - - pos += snprintk(extra_stats, sizeof(extra_stats), "\t[0"); - - for (j = 0; j < NET_PKT_DETAIL_STATS_COUNT; j++) { - net_stats_t count; - uint32_t avg; - - if (is_tx) { -#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) - count = GET_STAT(iface, tx_time_detail[j].count); -#endif - } else { -#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) - count = GET_STAT(iface, rx_time_detail[j].count); -#endif - } - - if (count == 0) { - break; - } - - if (is_tx) { -#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) - avg = (uint32_t)(GET_STAT(iface, - tx_time_detail[j].sum) / - (uint64_t)count); -#endif - } else { -#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) - avg = (uint32_t)(GET_STAT(iface, - rx_time_detail[j].sum) / - (uint64_t)count); -#endif - } - - if (avg == 0) { - continue; - } - - total += avg; - - pos += snprintk(extra_stats + pos, - sizeof(extra_stats) - pos, - "->%u", avg); - } - - if (total == 0U) { - return "\0"; - } - - pos += snprintk(extra_stats + pos, sizeof(extra_stats) - pos, - "=%u us]", total); - - return extra_stats; -} -#endif /* (NET_TC_TX_COUNT == 1) || (NET_TC_RX_COUNT == 1) */ - -#else /* CONFIG_NET_PKT_TXTIME_STATS_DETAIL || - CONFIG_NET_PKT_RXTIME_STATS_DETAIL */ - -#if defined(CONFIG_NET_PKT_TXTIME_STATS) || \ - defined(CONFIG_NET_PKT_RXTIME_STATS) - -#if (NET_TC_TX_COUNT > 1) || (NET_TC_RX_COUNT > 1) -static char *get_net_pkt_tc_stats_detail(struct net_if *iface, int i, - bool is_tx) -{ - ARG_UNUSED(iface); - ARG_UNUSED(i); - ARG_UNUSED(is_tx); - - return "\0"; -} -#endif - -#if (NET_TC_TX_COUNT == 1) || (NET_TC_RX_COUNT == 1) -static char *get_net_pkt_stats_detail(struct net_if *iface, bool is_tx) -{ - ARG_UNUSED(iface); - ARG_UNUSED(is_tx); - - return "\0"; -} -#endif -#endif /* CONFIG_NET_PKT_TXTIME_STATS) || CONFIG_NET_PKT_RXTIME_STATS */ -#endif /* CONFIG_NET_PKT_TXTIME_STATS_DETAIL || - CONFIG_NET_PKT_RXTIME_STATS_DETAIL */ - -static void print_tc_tx_stats(const struct shell *sh, struct net_if *iface) -{ -#if NET_TC_TX_COUNT > 1 - int i; - - PR("TX traffic class statistics:\n"); - -#if defined(CONFIG_NET_PKT_TXTIME_STATS) - PR("TC Priority\tSent pkts\tbytes\ttime\n"); - - for (i = 0; i < NET_TC_TX_COUNT; i++) { - net_stats_t count = GET_STAT(iface, - tc.sent[i].tx_time.count); - if (count == 0) { - PR("[%d] %s (%d)\t%d\t\t%d\t-\n", i, - priority2str(GET_STAT(iface, tc.sent[i].priority)), - GET_STAT(iface, tc.sent[i].priority), - GET_STAT(iface, tc.sent[i].pkts), - GET_STAT(iface, tc.sent[i].bytes)); - } else { - PR("[%d] %s (%d)\t%d\t\t%d\t%u us%s\n", i, - priority2str(GET_STAT(iface, tc.sent[i].priority)), - GET_STAT(iface, tc.sent[i].priority), - GET_STAT(iface, tc.sent[i].pkts), - GET_STAT(iface, tc.sent[i].bytes), - (uint32_t)(GET_STAT(iface, - tc.sent[i].tx_time.sum) / - (uint64_t)count), - get_net_pkt_tc_stats_detail(iface, i, true)); - } - } -#else - PR("TC Priority\tSent pkts\tbytes\n"); - - for (i = 0; i < NET_TC_TX_COUNT; i++) { - PR("[%d] %s (%d)\t%d\t\t%d\n", i, - priority2str(GET_STAT(iface, tc.sent[i].priority)), - GET_STAT(iface, tc.sent[i].priority), - GET_STAT(iface, tc.sent[i].pkts), - GET_STAT(iface, tc.sent[i].bytes)); - } -#endif /* CONFIG_NET_PKT_TXTIME_STATS */ -#else - ARG_UNUSED(sh); - -#if defined(CONFIG_NET_PKT_TXTIME_STATS) - net_stats_t count = GET_STAT(iface, tx_time.count); - - if (count != 0) { - PR("Avg %s net_pkt (%u) time %lu us%s\n", "TX", count, - (uint32_t)(GET_STAT(iface, tx_time.sum) / (uint64_t)count), - get_net_pkt_stats_detail(iface, true)); - } -#else - ARG_UNUSED(iface); -#endif /* CONFIG_NET_PKT_TXTIME_STATS */ -#endif /* NET_TC_TX_COUNT > 1 */ -} - -static void print_tc_rx_stats(const struct shell *sh, struct net_if *iface) -{ -#if NET_TC_RX_COUNT > 1 - int i; - - PR("RX traffic class statistics:\n"); - -#if defined(CONFIG_NET_PKT_RXTIME_STATS) - PR("TC Priority\tRecv pkts\tbytes\ttime\n"); - - for (i = 0; i < NET_TC_RX_COUNT; i++) { - net_stats_t count = GET_STAT(iface, - tc.recv[i].rx_time.count); - if (count == 0) { - PR("[%d] %s (%d)\t%d\t\t%d\t-\n", i, - priority2str(GET_STAT(iface, tc.recv[i].priority)), - GET_STAT(iface, tc.recv[i].priority), - GET_STAT(iface, tc.recv[i].pkts), - GET_STAT(iface, tc.recv[i].bytes)); - } else { - PR("[%d] %s (%d)\t%d\t\t%d\t%u us%s\n", i, - priority2str(GET_STAT(iface, tc.recv[i].priority)), - GET_STAT(iface, tc.recv[i].priority), - GET_STAT(iface, tc.recv[i].pkts), - GET_STAT(iface, tc.recv[i].bytes), - (uint32_t)(GET_STAT(iface, - tc.recv[i].rx_time.sum) / - (uint64_t)count), - get_net_pkt_tc_stats_detail(iface, i, false)); - } - } -#else - PR("TC Priority\tRecv pkts\tbytes\n"); - - for (i = 0; i < NET_TC_RX_COUNT; i++) { - PR("[%d] %s (%d)\t%d\t\t%d\n", i, - priority2str(GET_STAT(iface, tc.recv[i].priority)), - GET_STAT(iface, tc.recv[i].priority), - GET_STAT(iface, tc.recv[i].pkts), - GET_STAT(iface, tc.recv[i].bytes)); - } -#endif /* CONFIG_NET_PKT_RXTIME_STATS */ -#else - ARG_UNUSED(sh); - -#if defined(CONFIG_NET_PKT_RXTIME_STATS) - net_stats_t count = GET_STAT(iface, rx_time.count); - - if (count != 0) { - PR("Avg %s net_pkt (%u) time %lu us%s\n", "RX", count, - (uint32_t)(GET_STAT(iface, rx_time.sum) / (uint64_t)count), - get_net_pkt_stats_detail(iface, false)); - } -#else - ARG_UNUSED(iface); -#endif /* CONFIG_NET_PKT_RXTIME_STATS */ - -#endif /* NET_TC_RX_COUNT > 1 */ -} - -static void print_net_pm_stats(const struct shell *sh, struct net_if *iface) -{ -#if defined(CONFIG_NET_STATISTICS_POWER_MANAGEMENT) - PR("PM suspend stats:\n"); - PR("\tLast time : %u ms\n", - GET_STAT(iface, pm.last_suspend_time)); - PR("\tAverage time : %u ms\n", - (uint32_t)(GET_STAT(iface, pm.overall_suspend_time) / - GET_STAT(iface, pm.suspend_count))); - PR("\tTotal time : %" PRIu64 " ms\n", - GET_STAT(iface, pm.overall_suspend_time)); - PR("\tHow many times: %u\n", - GET_STAT(iface, pm.suspend_count)); -#else - ARG_UNUSED(sh); - ARG_UNUSED(iface); -#endif -} - -static void net_shell_print_statistics(struct net_if *iface, void *user_data) -{ - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - - if (iface) { - const char *extra; - - PR("\nInterface %p (%s) [%d]\n", iface, - iface2str(iface, &extra), net_if_get_by_iface(iface)); - PR("===========================%s\n", extra); - } else { - PR("\nGlobal statistics\n"); - PR("=================\n"); - } - -#if defined(CONFIG_NET_STATISTICS_IPV6) && defined(CONFIG_NET_NATIVE_IPV6) - PR("IPv6 recv %d\tsent\t%d\tdrop\t%d\tforwarded\t%d\n", - GET_STAT(iface, ipv6.recv), - GET_STAT(iface, ipv6.sent), - GET_STAT(iface, ipv6.drop), - GET_STAT(iface, ipv6.forwarded)); -#if defined(CONFIG_NET_STATISTICS_IPV6_ND) - PR("IPv6 ND recv %d\tsent\t%d\tdrop\t%d\n", - GET_STAT(iface, ipv6_nd.recv), - GET_STAT(iface, ipv6_nd.sent), - GET_STAT(iface, ipv6_nd.drop)); -#endif /* CONFIG_NET_STATISTICS_IPV6_ND */ -#if defined(CONFIG_NET_STATISTICS_MLD) - PR("IPv6 MLD recv %d\tsent\t%d\tdrop\t%d\n", - GET_STAT(iface, ipv6_mld.recv), - GET_STAT(iface, ipv6_mld.sent), - GET_STAT(iface, ipv6_mld.drop)); -#endif /* CONFIG_NET_STATISTICS_MLD */ -#endif /* CONFIG_NET_STATISTICS_IPV6 */ - -#if defined(CONFIG_NET_STATISTICS_IPV4) && defined(CONFIG_NET_NATIVE_IPV4) - PR("IPv4 recv %d\tsent\t%d\tdrop\t%d\tforwarded\t%d\n", - GET_STAT(iface, ipv4.recv), - GET_STAT(iface, ipv4.sent), - GET_STAT(iface, ipv4.drop), - GET_STAT(iface, ipv4.forwarded)); -#endif /* CONFIG_NET_STATISTICS_IPV4 */ - - PR("IP vhlerr %d\thblener\t%d\tlblener\t%d\n", - GET_STAT(iface, ip_errors.vhlerr), - GET_STAT(iface, ip_errors.hblenerr), - GET_STAT(iface, ip_errors.lblenerr)); - PR("IP fragerr %d\tchkerr\t%d\tprotoer\t%d\n", - GET_STAT(iface, ip_errors.fragerr), - GET_STAT(iface, ip_errors.chkerr), - GET_STAT(iface, ip_errors.protoerr)); - -#if defined(CONFIG_NET_STATISTICS_ICMP) && defined(CONFIG_NET_NATIVE_IPV4) - PR("ICMP recv %d\tsent\t%d\tdrop\t%d\n", - GET_STAT(iface, icmp.recv), - GET_STAT(iface, icmp.sent), - GET_STAT(iface, icmp.drop)); - PR("ICMP typeer %d\tchkerr\t%d\n", - GET_STAT(iface, icmp.typeerr), - GET_STAT(iface, icmp.chkerr)); -#endif -#if defined(CONFIG_NET_STATISTICS_IGMP) - PR("IGMP recv %d\tsent\t%d\tdrop\t%d\n", - GET_STAT(iface, ipv4_igmp.recv), - GET_STAT(iface, ipv4_igmp.sent), - GET_STAT(iface, ipv4_igmp.drop)); -#endif /* CONFIG_NET_STATISTICS_IGMP */ -#if defined(CONFIG_NET_STATISTICS_UDP) && defined(CONFIG_NET_NATIVE_UDP) - PR("UDP recv %d\tsent\t%d\tdrop\t%d\n", - GET_STAT(iface, udp.recv), - GET_STAT(iface, udp.sent), - GET_STAT(iface, udp.drop)); - PR("UDP chkerr %d\n", - GET_STAT(iface, udp.chkerr)); -#endif - -#if defined(CONFIG_NET_STATISTICS_TCP) && defined(CONFIG_NET_NATIVE_TCP) - PR("TCP bytes recv %u\tsent\t%d\tresent\t%d\n", - GET_STAT(iface, tcp.bytes.received), - GET_STAT(iface, tcp.bytes.sent), - GET_STAT(iface, tcp.resent)); - PR("TCP seg recv %d\tsent\t%d\tdrop\t%d\n", - GET_STAT(iface, tcp.recv), - GET_STAT(iface, tcp.sent), - GET_STAT(iface, tcp.seg_drop)); - PR("TCP seg resent %d\tchkerr\t%d\tackerr\t%d\n", - GET_STAT(iface, tcp.rexmit), - GET_STAT(iface, tcp.chkerr), - GET_STAT(iface, tcp.ackerr)); - PR("TCP seg rsterr %d\trst\t%d\n", - GET_STAT(iface, tcp.rsterr), - GET_STAT(iface, tcp.rst)); - PR("TCP conn drop %d\tconnrst\t%d\n", - GET_STAT(iface, tcp.conndrop), - GET_STAT(iface, tcp.connrst)); - PR("TCP pkt drop %d\n", GET_STAT(iface, tcp.drop)); -#endif - - PR("Bytes received %u\n", GET_STAT(iface, bytes.received)); - PR("Bytes sent %u\n", GET_STAT(iface, bytes.sent)); - PR("Processing err %d\n", GET_STAT(iface, processing_error)); - - print_tc_tx_stats(sh, iface); - print_tc_rx_stats(sh, iface); - -#if defined(CONFIG_NET_STATISTICS_ETHERNET) && \ - defined(CONFIG_NET_STATISTICS_USER_API) - if (iface && net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) { - struct net_stats_eth eth_data; - int ret; - - ret = net_mgmt(NET_REQUEST_STATS_GET_ETHERNET, iface, - ð_data, sizeof(eth_data)); - if (!ret) { - print_eth_stats(iface, ð_data, sh); - } - } -#endif /* CONFIG_NET_STATISTICS_ETHERNET && CONFIG_NET_STATISTICS_USER_API */ - -#if defined(CONFIG_NET_STATISTICS_PPP) && \ - defined(CONFIG_NET_STATISTICS_USER_API) - if (iface && net_if_l2(iface) == &NET_L2_GET_NAME(PPP)) { - struct net_stats_ppp ppp_data; - int ret; - - ret = net_mgmt(NET_REQUEST_STATS_GET_PPP, iface, - &ppp_data, sizeof(ppp_data)); - if (!ret) { - print_ppp_stats(iface, &ppp_data, sh); - } - } -#endif /* CONFIG_NET_STATISTICS_PPP && CONFIG_NET_STATISTICS_USER_API */ - - print_net_pm_stats(sh, iface); -} -#endif /* CONFIG_NET_STATISTICS */ - -#if defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE) -static void get_addresses(struct net_context *context, - char addr_local[], int local_len, - char addr_remote[], int remote_len) -{ -#if defined(CONFIG_NET_IPV6) - if (context->local.family == AF_INET6) { - snprintk(addr_local, local_len, "[%s]:%u", - net_sprint_ipv6_addr( - net_sin6_ptr(&context->local)->sin6_addr), - ntohs(net_sin6_ptr(&context->local)->sin6_port)); - snprintk(addr_remote, remote_len, "[%s]:%u", - net_sprint_ipv6_addr( - &net_sin6(&context->remote)->sin6_addr), - ntohs(net_sin6(&context->remote)->sin6_port)); - } else -#endif -#if defined(CONFIG_NET_IPV4) - if (context->local.family == AF_INET) { - snprintk(addr_local, local_len, "%s:%d", - net_sprint_ipv4_addr( - net_sin_ptr(&context->local)->sin_addr), - ntohs(net_sin_ptr(&context->local)->sin_port)); - snprintk(addr_remote, remote_len, "%s:%d", - net_sprint_ipv4_addr( - &net_sin(&context->remote)->sin_addr), - ntohs(net_sin(&context->remote)->sin_port)); - } else -#endif - if (context->local.family == AF_UNSPEC) { - snprintk(addr_local, local_len, "AF_UNSPEC"); - } else if (context->local.family == AF_PACKET) { - snprintk(addr_local, local_len, "AF_PACKET"); - } else if (context->local.family == AF_CAN) { - snprintk(addr_local, local_len, "AF_CAN"); - } else { - snprintk(addr_local, local_len, "AF_UNK(%d)", - context->local.family); - } -} - -static void context_cb(struct net_context *context, void *user_data) -{ -#if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4) -#define ADDR_LEN NET_IPV6_ADDR_LEN -#elif defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6) -#define ADDR_LEN NET_IPV4_ADDR_LEN -#else -#define ADDR_LEN NET_IPV6_ADDR_LEN -#endif - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - int *count = data->user_data; - /* +7 for []:port */ - char addr_local[ADDR_LEN + 7]; - char addr_remote[ADDR_LEN + 7] = ""; - - get_addresses(context, addr_local, sizeof(addr_local), - addr_remote, sizeof(addr_remote)); - - PR("[%2d] %p\t%d %c%c%c %16s\t%16s\n", - (*count) + 1, context, - net_if_get_by_iface(net_context_get_iface(context)), - net_context_get_family(context) == AF_INET6 ? '6' : - (net_context_get_family(context) == AF_INET ? '4' : ' '), - net_context_get_type(context) == SOCK_DGRAM ? 'D' : - (net_context_get_type(context) == SOCK_STREAM ? 'S' : - (net_context_get_type(context) == SOCK_RAW ? 'R' : ' ')), - net_context_get_proto(context) == IPPROTO_UDP ? 'U' : - (net_context_get_proto(context) == IPPROTO_TCP ? 'T' : ' '), - addr_local, addr_remote); - - (*count)++; -} -#endif /* CONFIG_NET_OFFLOAD || CONFIG_NET_NATIVE */ - -#if CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG -static void conn_handler_cb(struct net_conn *conn, void *user_data) -{ -#if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4) -#define ADDR_LEN NET_IPV6_ADDR_LEN -#elif defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6) -#define ADDR_LEN NET_IPV4_ADDR_LEN -#else -#define ADDR_LEN NET_IPV6_ADDR_LEN -#endif - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - int *count = data->user_data; - /* +7 for []:port */ - char addr_local[ADDR_LEN + 7]; - char addr_remote[ADDR_LEN + 7] = ""; - -#if defined(CONFIG_NET_IPV6) - if (conn->local_addr.sa_family == AF_INET6) { - snprintk(addr_local, sizeof(addr_local), "[%s]:%u", - net_sprint_ipv6_addr( - &net_sin6(&conn->local_addr)->sin6_addr), - ntohs(net_sin6(&conn->local_addr)->sin6_port)); - snprintk(addr_remote, sizeof(addr_remote), "[%s]:%u", - net_sprint_ipv6_addr( - &net_sin6(&conn->remote_addr)->sin6_addr), - ntohs(net_sin6(&conn->remote_addr)->sin6_port)); - } else -#endif -#if defined(CONFIG_NET_IPV4) - if (conn->local_addr.sa_family == AF_INET) { - snprintk(addr_local, sizeof(addr_local), "%s:%d", - net_sprint_ipv4_addr( - &net_sin(&conn->local_addr)->sin_addr), - ntohs(net_sin(&conn->local_addr)->sin_port)); - snprintk(addr_remote, sizeof(addr_remote), "%s:%d", - net_sprint_ipv4_addr( - &net_sin(&conn->remote_addr)->sin_addr), - ntohs(net_sin(&conn->remote_addr)->sin_port)); - } else -#endif - if (conn->local_addr.sa_family == AF_UNSPEC) { - snprintk(addr_local, sizeof(addr_local), "AF_UNSPEC"); - } else { - snprintk(addr_local, sizeof(addr_local), "AF_UNK(%d)", - conn->local_addr.sa_family); - } - - PR("[%2d] %p %p\t%s\t%16s\t%16s\n", - (*count) + 1, conn, conn->cb, - net_proto2str(conn->local_addr.sa_family, conn->proto), - addr_local, addr_remote); - - (*count)++; -} -#endif /* CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG */ - -#if CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG -struct tcp_detail_info { - int printed_send_queue_header; - int printed_details; - int count; -}; -#endif - -#if defined(CONFIG_NET_TCP) && \ - (defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE)) -static void tcp_cb(struct tcp *conn, void *user_data) -{ - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - int *count = data->user_data; - uint16_t recv_mss = net_tcp_get_supported_mss(conn); - - PR("%p %p %5u %5u %10u %10u %5u %s\n", - conn, conn->context, - ntohs(net_sin6_ptr(&conn->context->local)->sin6_port), - ntohs(net_sin6(&conn->context->remote)->sin6_port), - conn->seq, conn->ack, recv_mss, - net_tcp_state_str(net_tcp_get_state(conn))); - - (*count)++; -} - -#if CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG -static void tcp_sent_list_cb(struct tcp *conn, void *user_data) -{ - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - struct tcp_detail_info *details = data->user_data; - struct net_pkt *pkt; - sys_snode_t *node; - - if (conn->state != TCP_LISTEN) { - if (!details->printed_details) { - PR("\nTCP Ref Recv_win Send_win Pending " - "Unacked Flags Queue\n"); - details->printed_details = true; - } - - PR("%p %ld %u\t %u\t %zd\t %d\t %d/%d/%d %s\n", - conn, atomic_get(&conn->ref_count), conn->recv_win, - conn->send_win, conn->send_data_total, conn->unacked_len, - conn->in_retransmission, conn->in_connect, conn->in_close, - sys_slist_is_empty(&conn->send_queue) ? "empty" : "data"); - - details->count++; - } - - if (sys_slist_is_empty(&conn->send_queue)) { - return; - } - - if (!details->printed_send_queue_header) { - PR("\nTCP packets waiting ACK:\n"); - PR("TCP net_pkt[ref/totlen]->net_buf[ref/len]..." - "\n"); - } - - PR("%p ", conn); - - node = sys_slist_peek_head(&conn->send_queue); - if (node) { - pkt = CONTAINER_OF(node, struct net_pkt, next); - if (pkt) { - struct net_buf *frag = pkt->frags; - - if (!details->printed_send_queue_header) { - PR("%p[%ld/%zd]", pkt, - atomic_get(&pkt->atomic_ref), - net_pkt_get_len(pkt)); - details->printed_send_queue_header = true; - } else { - PR(" %p[%ld/%zd]", - pkt, atomic_get(&pkt->atomic_ref), - net_pkt_get_len(pkt)); - } - - if (frag) { - PR("->"); - } - - while (frag) { - PR("%p[%d/%d]", frag, frag->ref, frag->len); - - frag = frag->frags; - if (frag) { - PR("->"); - } - } - - PR("\n"); - } - } - - details->printed_send_queue_header = true; -} -#endif /* CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG */ -#endif /* TCP */ - -#if defined(CONFIG_NET_IPV6_FRAGMENT) -static void ipv6_frag_cb(struct net_ipv6_reassembly *reass, - void *user_data) -{ - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - int *count = data->user_data; - char src[ADDR_LEN]; - int i; - - if (!*count) { - PR("\nIPv6 reassembly Id Remain " - "Src \tDst\n"); - } - - snprintk(src, ADDR_LEN, "%s", net_sprint_ipv6_addr(&reass->src)); - - PR("%p 0x%08x %5d %16s\t%16s\n", reass, reass->id, - k_ticks_to_ms_ceil32(k_work_delayable_remaining_get(&reass->timer)), - src, net_sprint_ipv6_addr(&reass->dst)); - - for (i = 0; i < CONFIG_NET_IPV6_FRAGMENT_MAX_PKT; i++) { - if (reass->pkt[i]) { - struct net_buf *frag = reass->pkt[i]->frags; - - PR("[%d] pkt %p->", i, reass->pkt[i]); - - while (frag) { - PR("%p", frag); - - frag = frag->frags; - if (frag) { - PR("->"); - } - } - - PR("\n"); - } - } - - (*count)++; -} -#endif /* CONFIG_NET_IPV6_FRAGMENT */ - -#if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC) -static void allocs_cb(struct net_pkt *pkt, - struct net_buf *buf, - const char *func_alloc, - int line_alloc, - const char *func_free, - int line_free, - bool in_use, - void *user_data) -{ - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - const char *str; - - if (in_use) { - str = "used"; - } else { - if (func_alloc) { - str = "free"; - } else { - str = "avail"; - } - } - - if (buf) { - goto buf; - } - - if (func_alloc) { - if (in_use) { - PR("%p/%ld\t%5s\t%5s\t%s():%d\n", - pkt, atomic_get(&pkt->atomic_ref), str, - net_pkt_slab2str(pkt->slab), - func_alloc, line_alloc); - } else { - PR("%p\t%5s\t%5s\t%s():%d -> %s():%d\n", - pkt, str, net_pkt_slab2str(pkt->slab), - func_alloc, line_alloc, func_free, - line_free); - } - } - - return; -buf: - if (func_alloc) { - struct net_buf_pool *pool = net_buf_pool_get(buf->pool_id); - - if (in_use) { - PR("%p/%d\t%5s\t%5s\t%s():%d\n", - buf, buf->ref, - str, net_pkt_pool2str(pool), func_alloc, - line_alloc); - } else { - PR("%p\t%5s\t%5s\t%s():%d -> %s():%d\n", - buf, str, net_pkt_pool2str(pool), - func_alloc, line_alloc, func_free, - line_free); - } - } -} -#endif /* CONFIG_NET_DEBUG_NET_PKT_ALLOC */ - -/* Put the actual shell commands after this */ - -static int cmd_net_allocs(const struct shell *sh, size_t argc, char *argv[]) -{ -#if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC) - struct net_shell_user_data user_data; -#endif - - ARG_UNUSED(argc); - ARG_UNUSED(argv); - -#if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC) - user_data.sh = sh; - - PR("Network memory allocations\n\n"); - PR("memory\t\tStatus\tPool\tFunction alloc -> freed\n"); - net_pkt_allocs_foreach(allocs_cb, &user_data); -#else - PR_INFO("Set %s to enable %s support.\n", - "CONFIG_NET_DEBUG_NET_PKT_ALLOC", "net_pkt allocation"); -#endif /* CONFIG_NET_DEBUG_NET_PKT_ALLOC */ - - return 0; -} - -#if defined(CONFIG_NET_ARP) && defined(CONFIG_NET_NATIVE) -static void arp_cb(struct arp_entry *entry, void *user_data) -{ - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - int *count = data->user_data; - - if (*count == 0) { - PR(" Interface Link Address\n"); - } - - PR("[%2d] %d %s %s\n", *count, - net_if_get_by_iface(entry->iface), - net_sprint_ll_addr(entry->eth.addr, sizeof(struct net_eth_addr)), - net_sprint_ipv4_addr(&entry->ip)); - - (*count)++; -} -#endif /* CONFIG_NET_ARP */ - -#if !defined(CONFIG_NET_ARP) -static void print_arp_error(const struct shell *sh) -{ - PR_INFO("Set %s to enable %s support.\n", - "CONFIG_NET_NATIVE, CONFIG_NET_ARP, CONFIG_NET_IPV4 and" - " CONFIG_NET_L2_ETHERNET", "ARP"); -} -#endif - -static int cmd_net_arp(const struct shell *sh, size_t argc, char *argv[]) -{ -#if defined(CONFIG_NET_ARP) - struct net_shell_user_data user_data; - int arg = 1; -#endif - - ARG_UNUSED(argc); - -#if defined(CONFIG_NET_ARP) - if (!argv[arg]) { - /* ARP cache content */ - int count = 0; - - user_data.sh = sh; - user_data.user_data = &count; - - if (net_arp_foreach(arp_cb, &user_data) == 0) { - PR("ARP cache is empty.\n"); - } - } -#else - print_arp_error(sh); -#endif - - return 0; -} - -static int cmd_net_arp_flush(const struct shell *sh, size_t argc, - char *argv[]) -{ - ARG_UNUSED(argc); - ARG_UNUSED(argv); - -#if defined(CONFIG_NET_ARP) - PR("Flushing ARP cache.\n"); - net_arp_clear_cache(NULL); -#else - print_arp_error(sh); -#endif - - return 0; -} - -#if defined(CONFIG_NET_CAPTURE) -static const struct device *capture_dev; - -static void get_address_str(const struct sockaddr *addr, - char *str, int str_len) -{ - if (IS_ENABLED(CONFIG_NET_IPV6) && addr->sa_family == AF_INET6) { - snprintk(str, str_len, "[%s]:%u", - net_sprint_ipv6_addr(&net_sin6(addr)->sin6_addr), - ntohs(net_sin6(addr)->sin6_port)); - - } else if (IS_ENABLED(CONFIG_NET_IPV4) && addr->sa_family == AF_INET) { - snprintk(str, str_len, "%s:%d", - net_sprint_ipv4_addr(&net_sin(addr)->sin_addr), - ntohs(net_sin(addr)->sin_port)); - - } else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) && - addr->sa_family == AF_PACKET) { - snprintk(str, str_len, "AF_PACKET"); - } else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) && - addr->sa_family == AF_CAN) { - snprintk(str, str_len, "AF_CAN"); - } else if (addr->sa_family == AF_UNSPEC) { - snprintk(str, str_len, "AF_UNSPEC"); - } else { - snprintk(str, str_len, "AF_UNK(%d)", addr->sa_family); - } -} - -static void capture_cb(struct net_capture_info *info, void *user_data) -{ - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - int *count = data->user_data; - char addr_local[ADDR_LEN + 7]; - char addr_peer[ADDR_LEN + 7]; - - if (*count == 0) { - PR(" \t\tCapture Tunnel\n"); - PR("Device\t\tiface iface Local\t\t\tPeer\n"); - } - - get_address_str(info->local, addr_local, sizeof(addr_local)); - get_address_str(info->peer, addr_peer, sizeof(addr_peer)); - - PR("%s\t%c %d %s\t%s\n", info->capture_dev->name, - info->is_enabled ? - (net_if_get_by_iface(info->capture_iface) + '0') : '-', - net_if_get_by_iface(info->tunnel_iface), - addr_local, addr_peer); - - (*count)++; -} -#endif - -static int cmd_net_capture(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if defined(CONFIG_NET_CAPTURE) - bool ret; - - if (capture_dev == NULL) { - PR_INFO("Network packet capture %s\n", "not configured"); - } else { - struct net_shell_user_data user_data; - int count = 0; - - ret = net_capture_is_enabled(capture_dev); - PR_INFO("Network packet capture %s\n", - ret ? "enabled" : "disabled"); - - user_data.sh = sh; - user_data.user_data = &count; - - net_capture_foreach(capture_cb, &user_data); - } -#else - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - PR_INFO("Set %s to enable %s support.\n", - "CONFIG_NET_CAPTURE", "network packet capture"); -#endif - return 0; -} - -static int cmd_net_capture_setup(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if defined(CONFIG_NET_CAPTURE) - int ret, arg = 1; - const char *remote, *local, *peer; - - remote = argv[arg++]; - if (!remote) { - PR_WARNING("Remote IP address not specified.\n"); - return -ENOEXEC; - } - - local = argv[arg++]; - if (!local) { - PR_WARNING("Local IP address not specified.\n"); - return -ENOEXEC; - } - - peer = argv[arg]; - if (!peer) { - PR_WARNING("Peer IP address not specified.\n"); - return -ENOEXEC; - } - - if (capture_dev != NULL) { - PR_INFO("Capture already setup, cleaning up settings.\n"); - net_capture_cleanup(capture_dev); - capture_dev = NULL; - } - - ret = net_capture_setup(remote, local, peer, &capture_dev); - if (ret < 0) { - PR_WARNING("Capture cannot be setup (%d)\n", ret); - return -ENOEXEC; - } - - PR_INFO("Capture setup done, next enable it by " - "\"net capture enable \"\n"); -#else - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - PR_INFO("Set %s to enable %s support.\n", - "CONFIG_NET_CAPTURE", "network packet capture"); -#endif - - return 0; -} - -static int cmd_net_capture_cleanup(const struct shell *sh, size_t argc, - char *argv[]) -{ - ARG_UNUSED(argc); - ARG_UNUSED(argv); - -#if defined(CONFIG_NET_CAPTURE) - int ret; - - if (capture_dev == NULL) { - return 0; - } - - ret = net_capture_cleanup(capture_dev); - if (ret < 0) { - PR_WARNING("Capture %s failed (%d)\n", "cleanup", ret); - return -ENOEXEC; - } - - capture_dev = NULL; -#else - PR_INFO("Set %s to enable %s support.\n", - "CONFIG_NET_CAPTURE", "network packet capture"); -#endif - - return 0; -} - -static int cmd_net_capture_enable(const struct shell *sh, size_t argc, - char *argv[]) -{ - ARG_UNUSED(argc); - ARG_UNUSED(argv); - -#if defined(CONFIG_NET_CAPTURE) - int ret, arg = 1, if_index; - struct net_if *iface; - - if (capture_dev == NULL) { - return 0; - } - - if (argv[arg] == NULL) { - PR_WARNING("Interface index is missing. Please give interface " - "what you want to monitor\n"); - return -ENOEXEC; - } - - if_index = atoi(argv[arg++]); - if (if_index == 0) { - PR_WARNING("Interface index %d is invalid.\n", if_index); - return -ENOEXEC; - } - - iface = net_if_get_by_index(if_index); - if (iface == NULL) { - PR_WARNING("No such interface with index %d\n", if_index); - return -ENOEXEC; - } - - ret = net_capture_enable(capture_dev, iface); - if (ret < 0) { - PR_WARNING("Capture %s failed (%d)\n", "enable", ret); - return -ENOEXEC; - } -#else - PR_INFO("Set %s to enable %s support.\n", - "CONFIG_NET_CAPTURE", "network packet capture"); -#endif - - return 0; -} - -static int cmd_net_capture_disable(const struct shell *sh, size_t argc, - char *argv[]) -{ - ARG_UNUSED(argc); - ARG_UNUSED(argv); - -#if defined(CONFIG_NET_CAPTURE) - int ret; - - if (capture_dev == NULL) { - return 0; - } - - ret = net_capture_disable(capture_dev); - if (ret < 0) { - PR_WARNING("Capture %s failed (%d)\n", "disable", ret); - return -ENOEXEC; - } -#else - PR_INFO("Set %s to enable %s support.\n", - "CONFIG_NET_CAPTURE", "network packet capture"); -#endif - - return 0; -} - -static int cmd_net_conn(const struct shell *sh, size_t argc, char *argv[]) -{ - ARG_UNUSED(argc); - ARG_UNUSED(argv); - -#if defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE) - struct net_shell_user_data user_data; - int count = 0; - - PR(" Context \tIface Flags Local Remote\n"); - - user_data.sh = sh; - user_data.user_data = &count; - - net_context_foreach(context_cb, &user_data); - - if (count == 0) { - PR("No connections\n"); - } - -#if CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG - PR("\n Handler Callback \tProto\tLocal \tRemote\n"); - - count = 0; - - net_conn_foreach(conn_handler_cb, &user_data); - - if (count == 0) { - PR("No connection handlers found.\n"); - } -#endif - -#if defined(CONFIG_NET_TCP) - PR("\nTCP Context Src port Dst port " - "Send-Seq Send-Ack MSS State\n"); - - count = 0; - - net_tcp_foreach(tcp_cb, &user_data); - - if (count == 0) { - PR("No TCP connections\n"); - } else { -#if CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG - /* Print information about pending packets */ - struct tcp_detail_info details; - - count = 0; - - if (IS_ENABLED(CONFIG_NET_TCP)) { - memset(&details, 0, sizeof(details)); - user_data.user_data = &details; - } - - net_tcp_foreach(tcp_sent_list_cb, &user_data); - - if (IS_ENABLED(CONFIG_NET_TCP)) { - if (details.count == 0) { - PR("No active connections.\n"); - } - } -#endif /* CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG */ - } - -#if CONFIG_NET_TCP_LOG_LEVEL < LOG_LEVEL_DBG - PR_INFO("Set %s to enable %s support.\n", - "CONFIG_NET_TCP_LOG_LEVEL_DBG", "TCP debugging"); -#endif /* CONFIG_NET_TCP_LOG_LEVEL < LOG_LEVEL_DBG */ - -#endif - -#if defined(CONFIG_NET_IPV6_FRAGMENT) - count = 0; - - net_ipv6_frag_foreach(ipv6_frag_cb, &user_data); - - /* Do not print anything if no fragments are pending atm */ -#endif - -#else - PR_INFO("Set %s to enable %s support.\n", - "CONFIG_NET_OFFLOAD or CONFIG_NET_NATIVE", - "connection information"); - -#endif /* CONFIG_NET_OFFLOAD || CONFIG_NET_NATIVE */ - - return 0; -} - -#if defined(CONFIG_DNS_RESOLVER) -static void dns_result_cb(enum dns_resolve_status status, - struct dns_addrinfo *info, - void *user_data) -{ - const struct shell *sh = user_data; - - if (status == DNS_EAI_CANCELED) { - PR_WARNING("dns: Timeout while resolving name.\n"); - return; - } - - if (status == DNS_EAI_INPROGRESS && info) { - char addr[NET_IPV6_ADDR_LEN]; - - if (info->ai_family == AF_INET) { - net_addr_ntop(AF_INET, - &net_sin(&info->ai_addr)->sin_addr, - addr, NET_IPV4_ADDR_LEN); - } else if (info->ai_family == AF_INET6) { - net_addr_ntop(AF_INET6, - &net_sin6(&info->ai_addr)->sin6_addr, - addr, NET_IPV6_ADDR_LEN); - } else { - strncpy(addr, "Invalid protocol family", - sizeof(addr)); - /* strncpy() doesn't guarantee NUL byte at the end. */ - addr[sizeof(addr) - 1] = 0; - } - - PR("dns: %s\n", addr); - return; - } - - if (status == DNS_EAI_ALLDONE) { - PR("dns: All results received\n"); - return; - } - - if (status == DNS_EAI_FAIL) { - PR_WARNING("dns: No such name found.\n"); - return; - } - - PR_WARNING("dns: Unhandled status %d received\n", status); -} - -static void print_dns_info(const struct shell *sh, - struct dns_resolve_context *ctx) -{ - int i; - - PR("DNS servers:\n"); - - for (i = 0; i < CONFIG_DNS_RESOLVER_MAX_SERVERS + - DNS_MAX_MCAST_SERVERS; i++) { - if (ctx->servers[i].dns_server.sa_family == AF_INET) { - PR("\t%s:%u\n", - net_sprint_ipv4_addr( - &net_sin(&ctx->servers[i].dns_server)-> - sin_addr), - ntohs(net_sin( - &ctx->servers[i].dns_server)->sin_port)); - } else if (ctx->servers[i].dns_server.sa_family == AF_INET6) { - PR("\t[%s]:%u\n", - net_sprint_ipv6_addr( - &net_sin6(&ctx->servers[i].dns_server)-> - sin6_addr), - ntohs(net_sin6( - &ctx->servers[i].dns_server)->sin6_port)); - } - } - - PR("Pending queries:\n"); - - for (i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) { - int32_t remaining; - - if (!ctx->queries[i].cb || !ctx->queries[i].query) { - continue; - } - - remaining = k_ticks_to_ms_ceil32( - k_work_delayable_remaining_get(&ctx->queries[i].timer)); - - if (ctx->queries[i].query_type == DNS_QUERY_TYPE_A) { - PR("\tIPv4[%u]: %s remaining %d\n", - ctx->queries[i].id, - ctx->queries[i].query, - remaining); - } else if (ctx->queries[i].query_type == DNS_QUERY_TYPE_AAAA) { - PR("\tIPv6[%u]: %s remaining %d\n", - ctx->queries[i].id, - ctx->queries[i].query, - remaining); - } - } -} -#endif - -static int cmd_net_dns_cancel(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if defined(CONFIG_DNS_RESOLVER) - struct dns_resolve_context *ctx; - int ret, i; -#endif - - ARG_UNUSED(argc); - ARG_UNUSED(argv); - -#if defined(CONFIG_DNS_RESOLVER) - ctx = dns_resolve_get_default(); - if (!ctx) { - PR_WARNING("No default DNS context found.\n"); - return -ENOEXEC; - } - - for (ret = 0, i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) { - if (!ctx->queries[i].cb) { - continue; - } - - if (!dns_resolve_cancel(ctx, ctx->queries[i].id)) { - ret++; - } - } - - if (ret) { - PR("Cancelled %d pending requests.\n", ret); - } else { - PR("No pending DNS requests.\n"); - } -#else - PR_INFO("Set %s to enable %s support.\n", "CONFIG_DNS_RESOLVER", - "DNS resolver"); -#endif - - return 0; -} - -static int cmd_net_dns_query(const struct shell *sh, size_t argc, - char *argv[]) -{ - -#if defined(CONFIG_DNS_RESOLVER) -#define DNS_TIMEOUT (MSEC_PER_SEC * 2) /* ms */ - enum dns_query_type qtype = DNS_QUERY_TYPE_A; - char *host, *type = NULL; - int ret, arg = 1; - - host = argv[arg++]; - if (!host) { - PR_WARNING("Hostname not specified.\n"); - return -ENOEXEC; - } - - if (argv[arg]) { - type = argv[arg]; - } - - if (type) { - if (strcmp(type, "A") == 0) { - qtype = DNS_QUERY_TYPE_A; - PR("IPv4 address type\n"); - } else if (strcmp(type, "AAAA") == 0) { - qtype = DNS_QUERY_TYPE_AAAA; - PR("IPv6 address type\n"); - } else { - PR_WARNING("Unknown query type, specify either " - "A or AAAA\n"); - return -ENOEXEC; - } - } - - ret = dns_get_addr_info(host, qtype, NULL, dns_result_cb, - (void *)sh, DNS_TIMEOUT); - if (ret < 0) { - PR_WARNING("Cannot resolve '%s' (%d)\n", host, ret); - } else { - PR("Query for '%s' sent.\n", host); - } -#else - PR_INFO("DNS resolver not supported. Set CONFIG_DNS_RESOLVER to " - "enable it.\n"); -#endif - - return 0; -} - -static int cmd_net_dns(const struct shell *sh, size_t argc, char *argv[]) -{ -#if defined(CONFIG_DNS_RESOLVER) - struct dns_resolve_context *ctx; -#endif - -#if defined(CONFIG_DNS_RESOLVER) - if (argv[1]) { - /* So this is a query then */ - cmd_net_dns_query(sh, argc, argv); - return 0; - } - - /* DNS status */ - ctx = dns_resolve_get_default(); - if (!ctx) { - PR_WARNING("No default DNS context found.\n"); - return -ENOEXEC; - } - - print_dns_info(sh, ctx); -#else - PR_INFO("DNS resolver not supported. Set CONFIG_DNS_RESOLVER to " - "enable it.\n"); -#endif - - return 0; -} - -#if defined(CONFIG_NET_MGMT_EVENT_MONITOR) -#define EVENT_MON_STACK_SIZE 1024 -#define THREAD_PRIORITY K_PRIO_COOP(2) -#define MAX_EVENT_INFO_SIZE NET_EVENT_INFO_MAX_SIZE -#define MONITOR_L2_MASK (_NET_EVENT_IF_BASE) -#define MONITOR_L3_IPV4_MASK (_NET_EVENT_IPV4_BASE) -#define MONITOR_L3_IPV6_MASK (_NET_EVENT_IPV6_BASE) -#define MONITOR_L4_MASK (_NET_EVENT_L4_BASE) - -static bool net_event_monitoring; -static bool net_event_shutting_down; -static struct net_mgmt_event_callback l2_cb; -static struct net_mgmt_event_callback l3_ipv4_cb; -static struct net_mgmt_event_callback l3_ipv6_cb; -static struct net_mgmt_event_callback l4_cb; -static struct k_thread event_mon; -static K_THREAD_STACK_DEFINE(event_mon_stack, EVENT_MON_STACK_SIZE); - -struct event_msg { - struct net_if *iface; - size_t len; - uint32_t event; - uint8_t data[MAX_EVENT_INFO_SIZE]; -}; - -K_MSGQ_DEFINE(event_mon_msgq, sizeof(struct event_msg), - CONFIG_NET_MGMT_EVENT_QUEUE_SIZE, sizeof(intptr_t)); - -static void event_handler(struct net_mgmt_event_callback *cb, - uint32_t mgmt_event, struct net_if *iface) -{ - struct event_msg msg; - int ret; - - memset(&msg, 0, sizeof(msg)); - - msg.len = MIN(sizeof(msg.data), cb->info_length); - msg.event = mgmt_event; - msg.iface = iface; - - if (cb->info_length > 0) { - memcpy(msg.data, cb->info, msg.len); - } - - ret = k_msgq_put(&event_mon_msgq, (void *)&msg, K_MSEC(10)); - if (ret < 0) { - NET_ERR("Cannot write to msgq (%d)\n", ret); - } -} - -static const char *get_l2_desc(uint32_t event) -{ - static const char *desc = ""; - - switch (event) { - case NET_EVENT_IF_DOWN: - desc = "down"; - break; - case NET_EVENT_IF_UP: - desc = "up"; - break; - } - - return desc; -} - -static char *get_l3_desc(struct event_msg *msg, - const char **desc, const char **desc2, - char *extra_info, size_t extra_info_len) -{ - static const char *desc_unknown = ""; - char *info = NULL; - - *desc = desc_unknown; - - switch (msg->event) { - case NET_EVENT_IPV6_ADDR_ADD: - *desc = "IPv6 address"; - *desc2 = "add"; - info = net_addr_ntop(AF_INET6, msg->data, extra_info, - extra_info_len); - break; - case NET_EVENT_IPV6_ADDR_DEL: - *desc = "IPv6 address"; - *desc2 = "del"; - info = net_addr_ntop(AF_INET6, msg->data, extra_info, - extra_info_len); - break; - case NET_EVENT_IPV6_MADDR_ADD: - *desc = "IPv6 mcast address"; - *desc2 = "add"; - info = net_addr_ntop(AF_INET6, msg->data, extra_info, - extra_info_len); - break; - case NET_EVENT_IPV6_MADDR_DEL: - *desc = "IPv6 mcast address"; - *desc2 = "del"; - info = net_addr_ntop(AF_INET6, msg->data, extra_info, - extra_info_len); - break; - case NET_EVENT_IPV6_PREFIX_ADD: - *desc = "IPv6 prefix"; - *desc2 = "add"; - info = net_addr_ntop(AF_INET6, msg->data, extra_info, - extra_info_len); - break; - case NET_EVENT_IPV6_PREFIX_DEL: - *desc = "IPv6 prefix"; - *desc2 = "del"; - info = net_addr_ntop(AF_INET6, msg->data, extra_info, - extra_info_len); - break; - case NET_EVENT_IPV6_MCAST_JOIN: - *desc = "IPv6 mcast"; - *desc2 = "join"; - info = net_addr_ntop(AF_INET6, msg->data, extra_info, - extra_info_len); - break; - case NET_EVENT_IPV6_MCAST_LEAVE: - *desc = "IPv6 mcast"; - *desc2 = "leave"; - info = net_addr_ntop(AF_INET6, msg->data, extra_info, - extra_info_len); - break; - case NET_EVENT_IPV6_ROUTER_ADD: - *desc = "IPv6 router"; - *desc2 = "add"; - info = net_addr_ntop(AF_INET6, msg->data, extra_info, - extra_info_len); - break; - case NET_EVENT_IPV6_ROUTER_DEL: - *desc = "IPv6 router"; - *desc2 = "del"; - info = net_addr_ntop(AF_INET6, msg->data, extra_info, - extra_info_len); - break; - case NET_EVENT_IPV6_ROUTE_ADD: - *desc = "IPv6 route"; - *desc2 = "add"; - info = net_addr_ntop(AF_INET6, msg->data, extra_info, - extra_info_len); - break; - case NET_EVENT_IPV6_ROUTE_DEL: - *desc = "IPv6 route"; - *desc2 = "del"; - info = net_addr_ntop(AF_INET6, msg->data, extra_info, - extra_info_len); - break; - case NET_EVENT_IPV6_DAD_SUCCEED: - *desc = "IPv6 DAD"; - *desc2 = "ok"; - info = net_addr_ntop(AF_INET6, msg->data, extra_info, - extra_info_len); - break; - case NET_EVENT_IPV6_DAD_FAILED: - *desc = "IPv6 DAD"; - *desc2 = "fail"; - info = net_addr_ntop(AF_INET6, msg->data, extra_info, - extra_info_len); - break; - case NET_EVENT_IPV6_NBR_ADD: - *desc = "IPv6 neighbor"; - *desc2 = "add"; - info = net_addr_ntop(AF_INET6, msg->data, extra_info, - extra_info_len); - break; - case NET_EVENT_IPV6_NBR_DEL: - *desc = "IPv6 neighbor"; - *desc2 = "del"; - info = net_addr_ntop(AF_INET6, msg->data, extra_info, - extra_info_len); - break; - case NET_EVENT_IPV6_DHCP_START: - *desc = "DHCPv6"; - *desc2 = "start"; - break; - case NET_EVENT_IPV6_DHCP_BOUND: - *desc = "DHCPv6"; - *desc2 = "bound"; -#if defined(CONFIG_NET_DHCPV6) - struct net_if_dhcpv6 *data = (struct net_if_dhcpv6 *)msg->data; - - if (data->params.request_addr) { - info = net_addr_ntop(AF_INET6, &data->addr, extra_info, - extra_info_len); - } else if (data->params.request_prefix) { - info = net_addr_ntop(AF_INET6, &data->prefix, extra_info, - extra_info_len); - } -#endif - break; - case NET_EVENT_IPV6_DHCP_STOP: - *desc = "DHCPv6"; - *desc2 = "stop"; - break; - case NET_EVENT_IPV4_ADDR_ADD: - *desc = "IPv4 address"; - *desc2 = "add"; - info = net_addr_ntop(AF_INET, msg->data, extra_info, - extra_info_len); - break; - case NET_EVENT_IPV4_ADDR_DEL: - *desc = "IPv4 address"; - *desc2 = "del"; - info = net_addr_ntop(AF_INET, msg->data, extra_info, - extra_info_len); - break; - case NET_EVENT_IPV4_ROUTER_ADD: - *desc = "IPv4 router"; - *desc2 = "add"; - info = net_addr_ntop(AF_INET, msg->data, extra_info, - extra_info_len); - break; - case NET_EVENT_IPV4_ROUTER_DEL: - *desc = "IPv4 router"; - *desc2 = "del"; - info = net_addr_ntop(AF_INET, msg->data, extra_info, - extra_info_len); - break; - case NET_EVENT_IPV4_DHCP_START: - *desc = "DHCPv4"; - *desc2 = "start"; - break; - case NET_EVENT_IPV4_DHCP_BOUND: - *desc = "DHCPv4"; - *desc2 = "bound"; -#if defined(CONFIG_NET_DHCPV4) - struct net_if_dhcpv4 *data = (struct net_if_dhcpv4 *)msg->data; - - info = net_addr_ntop(AF_INET, &data->requested_ip, extra_info, - extra_info_len); -#endif - break; - case NET_EVENT_IPV4_DHCP_STOP: - *desc = "DHCPv4"; - *desc2 = "stop"; - break; - } - - return info; -} - -static const char *get_l4_desc(uint32_t event) -{ - static const char *desc = ""; - - switch (event) { - case NET_EVENT_L4_CONNECTED: - desc = "connected"; - break; - case NET_EVENT_L4_DISCONNECTED: - desc = "disconnected"; - break; - case NET_EVENT_DNS_SERVER_ADD: - desc = "DNS server add"; - break; - case NET_EVENT_DNS_SERVER_DEL: - desc = "DNS server del"; - break; - } - - return desc; -} - -/* We use a separate thread in order not to do any shell printing from - * event handler callback (to avoid stack size issues). - */ -static void event_mon_handler(const struct shell *sh) -{ - char extra_info[NET_IPV6_ADDR_LEN]; - struct event_msg msg; - - net_mgmt_init_event_callback(&l2_cb, event_handler, - MONITOR_L2_MASK); - net_mgmt_add_event_callback(&l2_cb); - - net_mgmt_init_event_callback(&l3_ipv4_cb, event_handler, - MONITOR_L3_IPV4_MASK); - net_mgmt_add_event_callback(&l3_ipv4_cb); - - net_mgmt_init_event_callback(&l3_ipv6_cb, event_handler, - MONITOR_L3_IPV6_MASK); - net_mgmt_add_event_callback(&l3_ipv6_cb); - - net_mgmt_init_event_callback(&l4_cb, event_handler, - MONITOR_L4_MASK); - net_mgmt_add_event_callback(&l4_cb); - - while (net_event_shutting_down == false) { - const char *layer_str = ""; - const char *desc = "", *desc2 = ""; - char *info = NULL; - uint32_t layer; - - (void)k_msgq_get(&event_mon_msgq, &msg, K_FOREVER); - - if (msg.iface == NULL && msg.event == 0 && msg.len == 0) { - /* This is the stop message */ - continue; - } - - layer = NET_MGMT_GET_LAYER(msg.event); - if (layer == NET_MGMT_LAYER_L2) { - layer_str = "L2"; - desc = get_l2_desc(msg.event); - } else if (layer == NET_MGMT_LAYER_L3) { - layer_str = "L3"; - info = get_l3_desc(&msg, &desc, &desc2, - extra_info, NET_IPV6_ADDR_LEN); - } else if (layer == NET_MGMT_LAYER_L4) { - layer_str = "L4"; - desc = get_l4_desc(msg.event); - } - - PR_INFO("EVENT: %s [%d] %s%s%s%s%s\n", layer_str, - net_if_get_by_iface(msg.iface), desc, - desc2 ? " " : "", desc2 ? desc2 : "", - info ? " " : "", info ? info : ""); - } - - net_mgmt_del_event_callback(&l2_cb); - net_mgmt_del_event_callback(&l3_ipv4_cb); - net_mgmt_del_event_callback(&l3_ipv6_cb); - net_mgmt_del_event_callback(&l4_cb); - - k_msgq_purge(&event_mon_msgq); - - net_event_monitoring = false; - net_event_shutting_down = false; - - PR_INFO("Network event monitoring %s.\n", "disabled"); -} -#endif - -static int cmd_net_events_on(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if defined(CONFIG_NET_MGMT_EVENT_MONITOR) - k_tid_t tid; - - if (net_event_monitoring) { - PR_INFO("Network event monitoring is already %s.\n", - "enabled"); - return -ENOEXEC; - } - - tid = k_thread_create(&event_mon, event_mon_stack, - K_THREAD_STACK_SIZEOF(event_mon_stack), - (k_thread_entry_t)event_mon_handler, - (void *)sh, NULL, NULL, THREAD_PRIORITY, 0, - K_FOREVER); - if (!tid) { - PR_ERROR("Cannot create network event monitor thread!"); - return -ENOEXEC; - } - - k_thread_name_set(tid, "event_mon"); - - PR_INFO("Network event monitoring %s.\n", "enabled"); - - net_event_monitoring = true; - net_event_shutting_down = false; - - k_thread_start(tid); -#else - PR_INFO("Network management events are not supported. " - "Set CONFIG_NET_MGMT_EVENT_MONITOR to enable it.\n"); -#endif - - return 0; -} - -static int cmd_net_events_off(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if defined(CONFIG_NET_MGMT_EVENT_MONITOR) - static const struct event_msg msg; - int ret; - - if (!net_event_monitoring) { - PR_INFO("Network event monitoring is already %s.\n", - "disabled"); - return -ENOEXEC; - } - - net_event_shutting_down = true; - - ret = k_msgq_put(&event_mon_msgq, (void *)&msg, K_MSEC(100)); - if (ret < 0) { - PR_ERROR("Cannot write to msgq (%d)\n", ret); - return -ENOEXEC; - } -#else - PR_INFO("Network management events are not supported. " - "Set CONFIG_NET_MGMT_EVENT_MONITOR to enable it.\n"); -#endif - - return 0; -} - -static int cmd_net_events(const struct shell *sh, size_t argc, char *argv[]) -{ -#if defined(CONFIG_NET_MGMT_EVENT_MONITOR) - PR("Network event monitoring is %s.\n", - net_event_monitoring ? "enabled" : "disabled"); - - if (!argv[1]) { - PR_INFO("Give 'on' to enable event monitoring and " - "'off' to disable it.\n"); - } -#else - PR_INFO("Network management events are not supported. " - "Set CONFIG_NET_MGMT_EVENT_MONITOR to enable it.\n"); -#endif - - return 0; -} - -#if defined(CONFIG_NET_GPTP) -static const char *selected_role_str(int port); - -static void gptp_port_cb(int port, struct net_if *iface, void *user_data) -{ - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - int *count = data->user_data; - - if (*count == 0) { - PR("Port Interface \tRole\n"); - } - - (*count)++; - - PR("%2d %p [%d] \t%s\n", port, iface, net_if_get_by_iface(iface), - selected_role_str(port)); -} - -static const char *pdelay_req2str(enum gptp_pdelay_req_states state) -{ - switch (state) { - case GPTP_PDELAY_REQ_NOT_ENABLED: - return "REQ_NOT_ENABLED"; - case GPTP_PDELAY_REQ_INITIAL_SEND_REQ: - return "INITIAL_SEND_REQ"; - case GPTP_PDELAY_REQ_RESET: - return "REQ_RESET"; - case GPTP_PDELAY_REQ_SEND_REQ: - return "SEND_REQ"; - case GPTP_PDELAY_REQ_WAIT_RESP: - return "WAIT_RESP"; - case GPTP_PDELAY_REQ_WAIT_FOLLOW_UP: - return "WAIT_FOLLOW_UP"; - case GPTP_PDELAY_REQ_WAIT_ITV_TIMER: - return "WAIT_ITV_TIMER"; - } - - return ""; -}; - -static const char *pdelay_resp2str(enum gptp_pdelay_resp_states state) -{ - switch (state) { - case GPTP_PDELAY_RESP_NOT_ENABLED: - return "RESP_NOT_ENABLED"; - case GPTP_PDELAY_RESP_INITIAL_WAIT_REQ: - return "INITIAL_WAIT_REQ"; - case GPTP_PDELAY_RESP_WAIT_REQ: - return "WAIT_REQ"; - case GPTP_PDELAY_RESP_WAIT_TSTAMP: - return "WAIT_TSTAMP"; - } - - return ""; -} - -static const char *sync_rcv2str(enum gptp_sync_rcv_states state) -{ - switch (state) { - case GPTP_SYNC_RCV_DISCARD: - return "DISCARD"; - case GPTP_SYNC_RCV_WAIT_SYNC: - return "WAIT_SYNC"; - case GPTP_SYNC_RCV_WAIT_FOLLOW_UP: - return "WAIT_FOLLOW_UP"; - } - - return ""; -} - -static const char *sync_send2str(enum gptp_sync_send_states state) -{ - switch (state) { - case GPTP_SYNC_SEND_INITIALIZING: - return "INITIALIZING"; - case GPTP_SYNC_SEND_SEND_SYNC: - return "SEND_SYNC"; - case GPTP_SYNC_SEND_SEND_FUP: - return "SEND_FUP"; - } - - return ""; -} - -static const char *pss_rcv2str(enum gptp_pss_rcv_states state) -{ - switch (state) { - case GPTP_PSS_RCV_DISCARD: - return "DISCARD"; - case GPTP_PSS_RCV_RECEIVED_SYNC: - return "RECEIVED_SYNC"; - } - - return ""; -} - -static const char *pss_send2str(enum gptp_pss_send_states state) -{ - switch (state) { - case GPTP_PSS_SEND_TRANSMIT_INIT: - return "TRANSMIT_INIT"; - case GPTP_PSS_SEND_SYNC_RECEIPT_TIMEOUT: - return "SYNC_RECEIPT_TIMEOUT"; - case GPTP_PSS_SEND_SEND_MD_SYNC: - return "SEND_MD_SYNC"; - case GPTP_PSS_SEND_SET_SYNC_RECEIPT_TIMEOUT: - return "SET_SYNC_RECEIPT_TIMEOUT"; - } - - return ""; -} - -static const char *pa_rcv2str(enum gptp_pa_rcv_states state) -{ - switch (state) { - case GPTP_PA_RCV_DISCARD: - return "DISCARD"; - case GPTP_PA_RCV_RECEIVE: - return "RECEIVE"; - } - - return ""; -}; - -static const char *pa_info2str(enum gptp_pa_info_states state) -{ - switch (state) { - case GPTP_PA_INFO_DISABLED: - return "DISABLED"; - case GPTP_PA_INFO_POST_DISABLED: - return "POST_DISABLED"; - case GPTP_PA_INFO_AGED: - return "AGED"; - case GPTP_PA_INFO_UPDATE: - return "UPDATE"; - case GPTP_PA_INFO_CURRENT: - return "CURRENT"; - case GPTP_PA_INFO_RECEIVE: - return "RECEIVE"; - case GPTP_PA_INFO_SUPERIOR_MASTER_PORT: - return "SUPERIOR_MASTER_PORT"; - case GPTP_PA_INFO_REPEATED_MASTER_PORT: - return "REPEATED_MASTER_PORT"; - case GPTP_PA_INFO_INFERIOR_MASTER_OR_OTHER_PORT: - return "INFERIOR_MASTER_OR_OTHER_PORT"; - } - - return ""; -}; - -static const char *pa_transmit2str(enum gptp_pa_transmit_states state) -{ - switch (state) { - case GPTP_PA_TRANSMIT_INIT: - return "INIT"; - case GPTP_PA_TRANSMIT_PERIODIC: - return "PERIODIC"; - case GPTP_PA_TRANSMIT_IDLE: - return "IDLE"; - case GPTP_PA_TRANSMIT_POST_IDLE: - return "POST_IDLE"; - } - - return ""; -}; - -static const char *site_sync2str(enum gptp_site_sync_sync_states state) -{ - switch (state) { - case GPTP_SSS_INITIALIZING: - return "INITIALIZING"; - case GPTP_SSS_RECEIVING_SYNC: - return "RECEIVING_SYNC"; - } - - return ""; -} - -static const char *clk_slave2str(enum gptp_clk_slave_sync_states state) -{ - switch (state) { - case GPTP_CLK_SLAVE_SYNC_INITIALIZING: - return "INITIALIZING"; - case GPTP_CLK_SLAVE_SYNC_SEND_SYNC_IND: - return "SEND_SYNC_IND"; - } - - return ""; -}; - -static const char *pr_selection2str(enum gptp_pr_selection_states state) -{ - switch (state) { - case GPTP_PR_SELECTION_INIT_BRIDGE: - return "INIT_BRIDGE"; - case GPTP_PR_SELECTION_ROLE_SELECTION: - return "ROLE_SELECTION"; - } - - return ""; -}; - -static const char *cms_rcv2str(enum gptp_cms_rcv_states state) -{ - switch (state) { - case GPTP_CMS_RCV_INITIALIZING: - return "INITIALIZING"; - case GPTP_CMS_RCV_WAITING: - return "WAITING"; - case GPTP_CMS_RCV_SOURCE_TIME: - return "SOURCE_TIME"; - } - - return ""; -}; - -#if !defined(USCALED_NS_TO_NS) -#define USCALED_NS_TO_NS(val) (val >> 16) -#endif - -static const char *selected_role_str(int port) -{ - switch (GPTP_GLOBAL_DS()->selected_role[port]) { - case GPTP_PORT_INITIALIZING: - return "INITIALIZING"; - case GPTP_PORT_FAULTY: - return "FAULTY"; - case GPTP_PORT_DISABLED: - return "DISABLED"; - case GPTP_PORT_LISTENING: - return "LISTENING"; - case GPTP_PORT_PRE_MASTER: - return "PRE-MASTER"; - case GPTP_PORT_MASTER: - return "MASTER"; - case GPTP_PORT_PASSIVE: - return "PASSIVE"; - case GPTP_PORT_UNCALIBRATED: - return "UNCALIBRATED"; - case GPTP_PORT_SLAVE: - return "SLAVE"; - } - - return ""; -} - -static void gptp_print_port_info(const struct shell *sh, int port) -{ - struct gptp_port_bmca_data *port_bmca_data; - struct gptp_port_param_ds *port_param_ds; - struct gptp_port_states *port_state; - struct gptp_domain *domain; - struct gptp_port_ds *port_ds; - struct net_if *iface; - int ret, i; - - domain = gptp_get_domain(); - - ret = gptp_get_port_data(domain, - port, - &port_ds, - &port_param_ds, - &port_state, - &port_bmca_data, - &iface); - if (ret < 0) { - PR_WARNING("Cannot get gPTP information for port %d (%d)\n", - port, ret); - return; - } - - NET_ASSERT(port == port_ds->port_id.port_number, - "Port number mismatch! (%d vs %d)", port, - port_ds->port_id.port_number); - - PR("Port id : %d (%s)\n", port_ds->port_id.port_number, - selected_role_str(port_ds->port_id.port_number)); - PR("Interface : %p [%d]\n", iface, net_if_get_by_iface(iface)); - PR("Clock id : "); - for (i = 0; i < sizeof(port_ds->port_id.clk_id); i++) { - PR("%02x", port_ds->port_id.clk_id[i]); - - if (i != (sizeof(port_ds->port_id.clk_id) - 1)) { - PR(":"); - } - } - PR("\n"); - - PR("Version : %d\n", port_ds->version); - PR("AS capable : %s\n", port_ds->as_capable ? "yes" : "no"); - - PR("\nConfiguration:\n"); - PR("Time synchronization and Best Master Selection enabled " - ": %s\n", port_ds->ptt_port_enabled ? "yes" : "no"); - PR("The port is measuring the path delay " - ": %s\n", port_ds->is_measuring_delay ? "yes" : "no"); - PR("One way propagation time on %s : %u ns\n", - "the link attached to this port", - (uint32_t)port_ds->neighbor_prop_delay); - PR("Propagation time threshold for %s : %u ns\n", - "the link attached to this port", - (uint32_t)port_ds->neighbor_prop_delay_thresh); - PR("Estimate of the ratio of the frequency with the peer " - ": %u\n", (uint32_t)port_ds->neighbor_rate_ratio); - PR("Asymmetry on the link relative to the grand master time base " - ": %" PRId64 "\n", port_ds->delay_asymmetry); - PR("Maximum interval between sync %s " - ": %" PRIu64 "\n", "messages", - port_ds->sync_receipt_timeout_time_itv); - PR("Maximum number of Path Delay Requests without a response " - ": %d\n", port_ds->allowed_lost_responses); - PR("Current Sync %s : %d\n", - "sequence id for this port", port_ds->sync_seq_id); - PR("Current Path Delay Request %s : %d\n", - "sequence id for this port", port_ds->pdelay_req_seq_id); - PR("Current Announce %s : %d\n", - "sequence id for this port", port_ds->announce_seq_id); - PR("Current Signaling %s : %d\n", - "sequence id for this port", port_ds->signaling_seq_id); - PR("Whether neighborRateRatio %s : %s\n", - "needs to be computed for this port", - port_ds->compute_neighbor_rate_ratio ? "yes" : "no"); - PR("Whether neighborPropDelay %s : %s\n", - "needs to be computed for this port", - port_ds->compute_neighbor_prop_delay ? "yes" : "no"); - PR("Initial Announce Interval %s : %d\n", - "as a Logarithm to base 2", port_ds->ini_log_announce_itv); - PR("Current Announce Interval %s : %d\n", - "as a Logarithm to base 2", port_ds->cur_log_announce_itv); - PR("Initial Sync Interval %s : %d\n", - "as a Logarithm to base 2", port_ds->ini_log_half_sync_itv); - PR("Current Sync Interval %s : %d\n", - "as a Logarithm to base 2", port_ds->cur_log_half_sync_itv); - PR("Initial Path Delay Request Interval %s : %d\n", - "as a Logarithm to base 2", port_ds->ini_log_pdelay_req_itv); - PR("Current Path Delay Request Interval %s : %d\n", - "as a Logarithm to base 2", port_ds->cur_log_pdelay_req_itv); - PR("Time without receiving announce %s %s : %d ms (%d)\n", - "messages", "before running BMCA", - gptp_uscaled_ns_to_timer_ms( - &port_bmca_data->ann_rcpt_timeout_time_interval), - port_ds->announce_receipt_timeout); - PR("Time without receiving sync %s %s : %" PRIu64 " ms (%d)\n", - "messages", "before running BMCA", - (port_ds->sync_receipt_timeout_time_itv >> 16) / - (NSEC_PER_SEC / MSEC_PER_SEC), - port_ds->sync_receipt_timeout); - PR("Sync event %s : %" PRIu64 " ms\n", - "transmission interval for the port", - USCALED_NS_TO_NS(port_ds->half_sync_itv.low) / - (NSEC_PER_USEC * USEC_PER_MSEC)); - PR("Path Delay Request %s : %" PRIu64 " ms\n", - "transmission interval for the port", - USCALED_NS_TO_NS(port_ds->pdelay_req_itv.low) / - (NSEC_PER_USEC * USEC_PER_MSEC)); - PR("BMCA %s %s%d%s: %d\n", "default", "priority", 1, - " ", - domain->default_ds.priority1); - PR("BMCA %s %s%d%s: %d\n", "default", "priority", 2, - " ", - domain->default_ds.priority2); - - PR("\nRuntime status:\n"); - PR("Current global port state " - " : %s\n", selected_role_str(port)); - PR("Path Delay Request state machine variables:\n"); - PR("\tCurrent state " - ": %s\n", pdelay_req2str(port_state->pdelay_req.state)); - PR("\tInitial Path Delay Response Peer Timestamp " - ": %" PRIu64 "\n", port_state->pdelay_req.ini_resp_evt_tstamp); - PR("\tInitial Path Delay Response Ingress Timestamp " - ": %" PRIu64 "\n", port_state->pdelay_req.ini_resp_ingress_tstamp); - PR("\tPath Delay Response %s %s : %u\n", - "messages", "received", - port_state->pdelay_req.rcvd_pdelay_resp); - PR("\tPath Delay Follow Up %s %s : %u\n", - "messages", "received", - port_state->pdelay_req.rcvd_pdelay_follow_up); - PR("\tNumber of lost Path Delay Responses " - ": %u\n", port_state->pdelay_req.lost_responses); - PR("\tTimer expired send a new Path Delay Request " - ": %u\n", port_state->pdelay_req.pdelay_timer_expired); - PR("\tNeighborRateRatio has been computed successfully " - ": %u\n", port_state->pdelay_req.neighbor_rate_ratio_valid); - PR("\tPath Delay has already been computed after init " - ": %u\n", port_state->pdelay_req.init_pdelay_compute); - PR("\tCount consecutive reqs with multiple responses " - ": %u\n", port_state->pdelay_req.multiple_resp_count); - - PR("Path Delay Response state machine variables:\n"); - PR("\tCurrent state " - ": %s\n", pdelay_resp2str(port_state->pdelay_resp.state)); - - PR("SyncReceive state machine variables:\n"); - PR("\tCurrent state " - ": %s\n", sync_rcv2str(port_state->sync_rcv.state)); - PR("\tA Sync %s %s : %s\n", - "Message", "has been received", - port_state->sync_rcv.rcvd_sync ? "yes" : "no"); - PR("\tA Follow Up %s %s : %s\n", - "Message", "has been received", - port_state->sync_rcv.rcvd_follow_up ? "yes" : "no"); - PR("\tA Follow Up %s %s : %s\n", - "Message", "timeout", - port_state->sync_rcv.follow_up_timeout_expired ? "yes" : "no"); - PR("\tTime at which a Sync %s without Follow Up\n" - "\t will be discarded " - ": %" PRIu64 "\n", "Message", - port_state->sync_rcv.follow_up_receipt_timeout); - - PR("SyncSend state machine variables:\n"); - PR("\tCurrent state " - ": %s\n", sync_send2str(port_state->sync_send.state)); - PR("\tA MDSyncSend structure %s : %s\n", - "has been received", - port_state->sync_send.rcvd_md_sync ? "yes" : "no"); - PR("\tThe timestamp for the sync msg %s : %s\n", - "has been received", - port_state->sync_send.md_sync_timestamp_avail ? "yes" : "no"); - - PR("PortSyncSyncReceive state machine variables:\n"); - PR("\tCurrent state " - ": %s\n", pss_rcv2str(port_state->pss_rcv.state)); - PR("\tGrand Master / Local Clock frequency ratio " - ": %f\n", port_state->pss_rcv.rate_ratio); - PR("\tA MDSyncReceive struct is ready to be processed " - ": %s\n", port_state->pss_rcv.rcvd_md_sync ? "yes" : "no"); - PR("\tExpiry of SyncReceiptTimeoutTimer : %s\n", - port_state->pss_rcv.rcv_sync_receipt_timeout_timer_expired ? - "yes" : "no"); - - PR("PortSyncSyncSend state machine variables:\n"); - PR("\tCurrent state " - ": %s\n", pss_send2str(port_state->pss_send.state)); - PR("\tFollow Up Correction Field of last recv PSS " - ": %" PRId64 "\n", - port_state->pss_send.last_follow_up_correction_field); - PR("\tUpstream Tx Time of the last recv PortSyncSync " - ": %" PRIu64 "\n", port_state->pss_send.last_upstream_tx_time); - PR("\tRate Ratio of the last received PortSyncSync " - ": %f\n", - port_state->pss_send.last_rate_ratio); - PR("\tGM Freq Change of the last received PortSyncSync " - ": %f\n", port_state->pss_send.last_gm_freq_change); - PR("\tGM Time Base Indicator of last recv PortSyncSync " - ": %d\n", port_state->pss_send.last_gm_time_base_indicator); - PR("\tReceived Port Number of last recv PortSyncSync " - ": %d\n", - port_state->pss_send.last_rcvd_port_num); - PR("\tPortSyncSync structure is ready to be processed " - ": %s\n", port_state->pss_send.rcvd_pss_sync ? "yes" : "no"); - PR("\tFlag when the %s has expired : %s\n", - "half_sync_itv_timer", - port_state->pss_send.half_sync_itv_timer_expired ? "yes" : "no"); - PR("\tHas %s expired twice : %s\n", - "half_sync_itv_timer", - port_state->pss_send.sync_itv_timer_expired ? "yes" : "no"); - PR("\tHas syncReceiptTimeoutTime expired " - ": %s\n", - port_state->pss_send.send_sync_receipt_timeout_timer_expired ? - "yes" : "no"); - - PR("PortAnnounceReceive state machine variables:\n"); - PR("\tCurrent state " - ": %s\n", pa_rcv2str(port_state->pa_rcv.state)); - PR("\tAn announce message is ready to be processed " - ": %s\n", - port_state->pa_rcv.rcvd_announce ? "yes" : "no"); - - PR("PortAnnounceInformation state machine variables:\n"); - PR("\tCurrent state " - ": %s\n", pa_info2str(port_state->pa_info.state)); - PR("\tExpired announce information " - ": %s\n", port_state->pa_info.ann_expired ? "yes" : "no"); - - PR("PortAnnounceTransmit state machine variables:\n"); - PR("\tCurrent state " - ": %s\n", pa_transmit2str(port_state->pa_transmit.state)); - PR("\tTrigger announce information " - ": %s\n", port_state->pa_transmit.ann_trigger ? "yes" : "no"); - -#if defined(CONFIG_NET_GPTP_STATISTICS) - PR("\nStatistics:\n"); - PR("Sync %s %s : %u\n", - "messages", "received", port_param_ds->rx_sync_count); - PR("Follow Up %s %s : %u\n", - "messages", "received", port_param_ds->rx_fup_count); - PR("Path Delay Request %s %s : %u\n", - "messages", "received", port_param_ds->rx_pdelay_req_count); - PR("Path Delay Response %s %s : %u\n", - "messages", "received", port_param_ds->rx_pdelay_resp_count); - PR("Path Delay %s threshold %s : %u\n", - "messages", "exceeded", - port_param_ds->neighbor_prop_delay_exceeded); - PR("Path Delay Follow Up %s %s : %u\n", - "messages", "received", port_param_ds->rx_pdelay_resp_fup_count); - PR("Announce %s %s : %u\n", - "messages", "received", port_param_ds->rx_announce_count); - PR("ptp %s discarded : %u\n", - "messages", port_param_ds->rx_ptp_packet_discard_count); - PR("Sync %s %s : %u\n", - "reception", "timeout", - port_param_ds->sync_receipt_timeout_count); - PR("Announce %s %s : %u\n", - "reception", "timeout", - port_param_ds->announce_receipt_timeout_count); - PR("Path Delay Requests without a response " - ": %u\n", - port_param_ds->pdelay_allowed_lost_resp_exceed_count); - PR("Sync %s %s : %u\n", - "messages", "sent", port_param_ds->tx_sync_count); - PR("Follow Up %s %s : %u\n", - "messages", "sent", port_param_ds->tx_fup_count); - PR("Path Delay Request %s %s : %u\n", - "messages", "sent", port_param_ds->tx_pdelay_req_count); - PR("Path Delay Response %s %s : %u\n", - "messages", "sent", port_param_ds->tx_pdelay_resp_count); - PR("Path Delay Response FUP %s %s : %u\n", - "messages", "sent", port_param_ds->tx_pdelay_resp_fup_count); - PR("Announce %s %s : %u\n", - "messages", "sent", port_param_ds->tx_announce_count); -#endif /* CONFIG_NET_GPTP_STATISTICS */ -} -#endif /* CONFIG_NET_GPTP */ - -static int cmd_net_gptp_port(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if defined(CONFIG_NET_GPTP) - int arg = 1; - char *endptr; - int port; -#endif - -#if defined(CONFIG_NET_GPTP) - if (!argv[arg]) { - PR_WARNING("Port number must be given.\n"); - return -ENOEXEC; - } - - port = strtol(argv[arg], &endptr, 10); - - if (*endptr == '\0') { - gptp_print_port_info(sh, port); - } else { - PR_WARNING("Not a valid gPTP port number: %s\n", argv[arg]); - } -#else - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_GPTP", "gPTP"); -#endif - - return 0; -} - -static int cmd_net_gptp(const struct shell *sh, size_t argc, char *argv[]) -{ -#if defined(CONFIG_NET_GPTP) - /* gPTP status */ - struct gptp_domain *domain = gptp_get_domain(); - int count = 0; - int arg = 1; -#endif - -#if defined(CONFIG_NET_GPTP) - if (argv[arg]) { - cmd_net_gptp_port(sh, argc, argv); - } else { - struct net_shell_user_data user_data; - - user_data.sh = sh; - user_data.user_data = &count; - - gptp_foreach_port(gptp_port_cb, &user_data); - - PR("\n"); - - PR("SiteSyncSync state machine variables:\n"); - PR("\tCurrent state : %s\n", - site_sync2str(domain->state.site_ss.state)); - PR("\tA PortSyncSync struct is ready : %s\n", - domain->state.site_ss.rcvd_pss ? "yes" : "no"); - - PR("ClockSlaveSync state machine variables:\n"); - PR("\tCurrent state : %s\n", - clk_slave2str(domain->state.clk_slave_sync.state)); - PR("\tA PortSyncSync struct is ready : %s\n", - domain->state.clk_slave_sync.rcvd_pss ? "yes" : "no"); - PR("\tThe local clock has expired : %s\n", - domain->state.clk_slave_sync.rcvd_local_clk_tick ? - "yes" : "no"); - - PR("PortRoleSelection state machine variables:\n"); - PR("\tCurrent state : %s\n", - pr_selection2str(domain->state.pr_sel.state)); - - PR("ClockMasterSyncReceive state machine variables:\n"); - PR("\tCurrent state : %s\n", - cms_rcv2str(domain->state.clk_master_sync_receive.state)); - PR("\tA ClockSourceTime : %s\n", - domain->state.clk_master_sync_receive.rcvd_clock_source_req - ? "yes" : "no"); - PR("\tThe local clock has expired : %s\n", - domain->state.clk_master_sync_receive.rcvd_local_clock_tick - ? "yes" : "no"); - } -#else - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_GPTP", "gPTP"); -#endif - - return 0; -} - -static int get_iface_idx(const struct shell *sh, char *index_str) -{ - char *endptr; - int idx; - - if (!index_str) { - PR_WARNING("Interface index is missing.\n"); - return -EINVAL; - } - - idx = strtol(index_str, &endptr, 10); - if (*endptr != '\0') { - PR_WARNING("Invalid index %s\n", index_str); - return -ENOENT; - } - - if (idx < 0 || idx > 255) { - PR_WARNING("Invalid index %d\n", idx); - return -ERANGE; - } - - return idx; -} - -static int cmd_net_iface_up(const struct shell *sh, size_t argc, - char *argv[]) -{ - struct net_if *iface; - int idx, ret; - - idx = get_iface_idx(sh, argv[1]); - if (idx < 0) { - return -ENOEXEC; - } - - iface = net_if_get_by_index(idx); - if (!iface) { - PR_WARNING("No such interface in index %d\n", idx); - return -ENOEXEC; - } - - if (net_if_is_up(iface)) { - PR_WARNING("Interface %d is already up.\n", idx); - return -ENOEXEC; - } - - ret = net_if_up(iface); - if (ret) { - PR_WARNING("Cannot take interface %d up (%d)\n", idx, ret); - return -ENOEXEC; - } else { - PR("Interface %d is up\n", idx); - } - - return 0; -} - -static int cmd_net_iface_down(const struct shell *sh, size_t argc, - char *argv[]) -{ - struct net_if *iface; - int idx, ret; - - idx = get_iface_idx(sh, argv[1]); - if (idx < 0) { - return -ENOEXEC; - } - - iface = net_if_get_by_index(idx); - if (!iface) { - PR_WARNING("No such interface in index %d\n", idx); - return -ENOEXEC; - } - - ret = net_if_down(iface); - if (ret) { - PR_WARNING("Cannot take interface %d down (%d)\n", idx, ret); - return -ENOEXEC; - } else { - PR("Interface %d is down\n", idx); - } - - return 0; -} - -#if defined(CONFIG_NET_NATIVE_IPV6) - -static void address_lifetime_cb(struct net_if *iface, void *user_data) -{ - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6; - const char *extra; - int i; - - ARG_UNUSED(user_data); - - PR("\nIPv6 addresses for interface %d (%p) (%s)\n", - net_if_get_by_iface(iface), iface, iface2str(iface, &extra)); - PR("============================================%s\n", extra); - - if (!ipv6) { - PR("No IPv6 config found for this interface.\n"); - return; - } - - PR("Type \tState \tLifetime (sec)\tAddress\n"); - - for (i = 0; i < NET_IF_MAX_IPV6_ADDR; i++) { - struct net_if_ipv6_prefix *prefix; - char remaining_str[sizeof("01234567890")]; - uint64_t remaining; - uint8_t prefix_len; - - if (!ipv6->unicast[i].is_used || - ipv6->unicast[i].address.family != AF_INET6) { - continue; - } - - remaining = net_timeout_remaining(&ipv6->unicast[i].lifetime, - k_uptime_get_32()); - - prefix = net_if_ipv6_prefix_get(iface, - &ipv6->unicast[i].address.in6_addr); - if (prefix) { - prefix_len = prefix->len; - } else { - prefix_len = 128U; - } - - if (ipv6->unicast[i].is_infinite) { - snprintk(remaining_str, sizeof(remaining_str) - 1, - "infinite"); - } else { - snprintk(remaining_str, sizeof(remaining_str) - 1, - "%u", (uint32_t)(remaining / 1000U)); - } - - PR("%s \t%s\t%s \t%s/%d\n", - addrtype2str(ipv6->unicast[i].addr_type), - addrstate2str(ipv6->unicast[i].addr_state), - remaining_str, - net_sprint_ipv6_addr( - &ipv6->unicast[i].address.in6_addr), - prefix_len); - } -} -#endif /* CONFIG_NET_NATIVE_IPV6 */ - -static int cmd_net_ipv6(const struct shell *sh, size_t argc, char *argv[]) -{ -#if defined(CONFIG_NET_NATIVE_IPV6) - struct net_shell_user_data user_data; -#endif - - PR("IPv6 support : %s\n", - IS_ENABLED(CONFIG_NET_IPV6) ? - "enabled" : "disabled"); - if (!IS_ENABLED(CONFIG_NET_IPV6)) { - return -ENOEXEC; - } - -#if defined(CONFIG_NET_NATIVE_IPV6) - PR("IPv6 fragmentation support : %s\n", - IS_ENABLED(CONFIG_NET_IPV6_FRAGMENT) ? "enabled" : - "disabled"); - PR("Multicast Listener Discovery support : %s\n", - IS_ENABLED(CONFIG_NET_IPV6_MLD) ? "enabled" : - "disabled"); - PR("Neighbor cache support : %s\n", - IS_ENABLED(CONFIG_NET_IPV6_NBR_CACHE) ? "enabled" : - "disabled"); - PR("Neighbor discovery support : %s\n", - IS_ENABLED(CONFIG_NET_IPV6_ND) ? "enabled" : - "disabled"); - PR("Duplicate address detection (DAD) support : %s\n", - IS_ENABLED(CONFIG_NET_IPV6_DAD) ? "enabled" : - "disabled"); - PR("Router advertisement RDNSS option support : %s\n", - IS_ENABLED(CONFIG_NET_IPV6_RA_RDNSS) ? "enabled" : - "disabled"); - PR("6lo header compression support : %s\n", - IS_ENABLED(CONFIG_NET_6LO) ? "enabled" : - "disabled"); - - if (IS_ENABLED(CONFIG_NET_6LO_CONTEXT)) { - PR("6lo context based compression " - "support : %s\n", - IS_ENABLED(CONFIG_NET_6LO_CONTEXT) ? "enabled" : - "disabled"); - } - - PR("Max number of IPv6 network interfaces " - "in the system : %d\n", - CONFIG_NET_IF_MAX_IPV6_COUNT); - PR("Max number of unicast IPv6 addresses " - "per network interface : %d\n", - CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT); - PR("Max number of multicast IPv6 addresses " - "per network interface : %d\n", - CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT); - PR("Max number of IPv6 prefixes per network " - "interface : %d\n", - CONFIG_NET_IF_IPV6_PREFIX_COUNT); - - user_data.sh = sh; - user_data.user_data = NULL; - - /* Print information about address lifetime */ - net_if_foreach(address_lifetime_cb, &user_data); -#endif - - return 0; -} - -static int cmd_net_ip6_add(const struct shell *sh, size_t argc, char *argv[]) -{ -#if defined(CONFIG_NET_NATIVE_IPV6) - struct net_if *iface = NULL; - int idx; - struct in6_addr addr; - - if (argc != 3) { - PR_ERROR("Correct usage: net ipv6 add
    \n"); - return -EINVAL; - } - - idx = get_iface_idx(sh, argv[1]); - if (idx < 0) { - return -ENOEXEC; - } - - iface = net_if_get_by_index(idx); - if (!iface) { - PR_WARNING("No such interface in index %d\n", idx); - return -ENOENT; - } - - if (net_addr_pton(AF_INET6, argv[2], &addr)) { - PR_ERROR("Invalid address: %s\n", argv[2]); - return -EINVAL; - } - - if (!net_if_ipv6_addr_add(iface, &addr, NET_ADDR_MANUAL, 0)) { - PR_ERROR("Failed to add %s address to interface %p\n", argv[2], iface); - } - -#else /* CONFIG_NET_NATIVE_IPV6 */ - PR_INFO("Set %s and %s to enable native %s support.\n", - "CONFIG_NET_NATIVE", "CONFIG_NET_IPV6", "IPv6"); -#endif /* CONFIG_NET_NATIVE_IPV6 */ - return 0; -} - -static int cmd_net_ip6_del(const struct shell *sh, size_t argc, char *argv[]) -{ -#if defined(CONFIG_NET_NATIVE_IPV6) - struct net_if *iface = NULL; - int idx; - struct in6_addr addr; - - if (argc != 3) { - PR_ERROR("Correct usage: net ipv6 del
    \n"); - return -EINVAL; - } - - idx = get_iface_idx(sh, argv[1]); - if (idx < 0) { - return -ENOEXEC; - } - - iface = net_if_get_by_index(idx); - if (!iface) { - PR_WARNING("No such interface in index %d\n", idx); - return -ENOEXEC; - } - - if (net_addr_pton(AF_INET6, argv[2], &addr)) { - PR_ERROR("Invalid address: %s\n", argv[2]); - return -EINVAL; - } - - if (!net_if_ipv6_addr_rm(iface, &addr)) { - PR_ERROR("Failed to delete %s\n", argv[2]); - return -1; - } - -#else /* CONFIG_NET_NATIVE_IPV6 */ - PR_INFO("Set %s and %s to enable native %s support.\n", - "CONFIG_NET_NATIVE", "CONFIG_NET_IPV6", "IPv6"); -#endif /* CONFIG_NET_NATIVE_IPV6 */ - return 0; -} - -static int cmd_net_ip6_route_add(const struct shell *sh, size_t argc, char *argv[]) -{ -#if defined(CONFIG_NET_NATIVE_IPV6) && (CONFIG_NET_ROUTE) - struct net_if *iface = NULL; - int idx; - struct net_route_entry *route; - struct in6_addr gw = {0}; - struct in6_addr prefix = {0}; - - if (argc != 4) { - PR_ERROR("Correct usage: net route add " - " \n"); - return -EINVAL; - } - - idx = get_iface_idx(sh, argv[1]); - if (idx < 0) { - return -ENOEXEC; - } - - iface = net_if_get_by_index(idx); - if (!iface) { - PR_WARNING("No such interface in index %d\n", idx); - return -ENOEXEC; - } - - if (net_addr_pton(AF_INET6, argv[2], &prefix)) { - PR_ERROR("Invalid address: %s\n", argv[2]); - return -EINVAL; - } - - if (net_addr_pton(AF_INET6, argv[3], &gw)) { - PR_ERROR("Invalid gateway: %s\n", argv[3]); - return -EINVAL; - } - - route = net_route_add(iface, &prefix, NET_IPV6_DEFAULT_PREFIX_LEN, - &gw, NET_IPV6_ND_INFINITE_LIFETIME, - NET_ROUTE_PREFERENCE_MEDIUM); - if (route == NULL) { - PR_ERROR("Failed to add route\n"); - return -ENOEXEC; - } - -#else /* CONFIG_NET_NATIVE_IPV6 && CONFIG_NET_ROUTE */ - PR_INFO("Set %s and %s to enable native %s support." - " And enable CONFIG_NET_ROUTE.\n", - "CONFIG_NET_NATIVE", "CONFIG_NET_IPV6", "IPv6"); -#endif /* CONFIG_NET_NATIVE_IPV6 && CONFIG_NET_ROUTE */ - return 0; -} - -static int cmd_net_ip6_route_del(const struct shell *sh, size_t argc, char *argv[]) -{ -#if defined(CONFIG_NET_NATIVE_IPV6) && (CONFIG_NET_ROUTE) - struct net_if *iface = NULL; - int idx; - struct net_route_entry *route; - struct in6_addr prefix = { 0 }; - - if (argc != 3) { - PR_ERROR("Correct usage: net route del \n"); - return -EINVAL; - } - idx = get_iface_idx(sh, argv[1]); - if (idx < 0) { - return -ENOEXEC; - } - - iface = net_if_get_by_index(idx); - if (!iface) { - PR_WARNING("No such interface in index %d\n", idx); - return -ENOEXEC; - } - - if (net_addr_pton(AF_INET6, argv[2], &prefix)) { - PR_ERROR("Invalid address: %s\n", argv[2]); - return -EINVAL; - } - - route = net_route_lookup(iface, &prefix); - if (route) { - net_route_del(route); - } -#else /* CONFIG_NET_NATIVE_IPV6 && CONFIG_NET_ROUTE */ - PR_INFO("Set %s and %s to enable native %s support." - " And enable CONFIG_NET_ROUTE\n", - "CONFIG_NET_NATIVE", "CONFIG_NET_IPV6", "IPv6"); -#endif /* CONFIG_NET_NATIVE_IPV6 && CONFIG_NET_ROUTE */ - return 0; -} - -#if defined(CONFIG_NET_NATIVE_IPV4) -static void ip_address_lifetime_cb(struct net_if *iface, void *user_data) -{ - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - struct net_if_ipv4 *ipv4 = iface->config.ip.ipv4; - const char *extra; - int i; - - ARG_UNUSED(user_data); - - PR("\nIPv4 addresses for interface %d (%p) (%s)\n", - net_if_get_by_iface(iface), iface, iface2str(iface, &extra)); - PR("============================================%s\n", extra); - - if (!ipv4) { - PR("No IPv4 config found for this interface.\n"); - return; - } - - PR("Type \tState \tLifetime (sec)\tAddress\n"); - - for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) { - if (!ipv4->unicast[i].is_used || - ipv4->unicast[i].address.family != AF_INET) { - continue; - } - - PR("%s \t%s \t%12s/%12s\n", - addrtype2str(ipv4->unicast[i].addr_type), - addrstate2str(ipv4->unicast[i].addr_state), - net_sprint_ipv4_addr( - &ipv4->unicast[i].address.in_addr), - net_sprint_ipv4_addr( - &ipv4->netmask)); - } -} -#endif /* CONFIG_NET_NATIVE_IPV4 */ - -static int cmd_net_ipv4(const struct shell *sh, size_t argc, char *argv[]) -{ - PR("IPv4 support : %s\n", - IS_ENABLED(CONFIG_NET_IPV4) ? - "enabled" : "disabled"); - if (!IS_ENABLED(CONFIG_NET_IPV4)) { - return -ENOEXEC; - } - -#if defined(CONFIG_NET_NATIVE_IPV4) - struct net_shell_user_data user_data; - - PR("IPv4 fragmentation support : %s\n", - IS_ENABLED(CONFIG_NET_IPV4_FRAGMENT) ? "enabled" : - "disabled"); - PR("Max number of IPv4 network interfaces " - "in the system : %d\n", - CONFIG_NET_IF_MAX_IPV4_COUNT); - PR("Max number of unicast IPv4 addresses " - "per network interface : %d\n", - CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT); - PR("Max number of multicast IPv4 addresses " - "per network interface : %d\n", - CONFIG_NET_IF_MCAST_IPV4_ADDR_COUNT); - - user_data.sh = sh; - user_data.user_data = NULL; - - /* Print information about address lifetime */ - net_if_foreach(ip_address_lifetime_cb, &user_data); -#endif - - return 0; -} - -static int cmd_net_ip_add(const struct shell *sh, size_t argc, char *argv[]) -{ -#if defined(CONFIG_NET_NATIVE_IPV4) - struct net_if *iface = NULL; - int idx; - struct in_addr addr; - - if (argc != 4) { - PR_ERROR("Correct usage: net ipv4 add
    \n"); - return -EINVAL; - } - - idx = get_iface_idx(sh, argv[1]); - if (idx < 0) { - return -ENOEXEC; - } - - iface = net_if_get_by_index(idx); - if (!iface) { - PR_WARNING("No such interface in index %d\n", idx); - return -ENOEXEC; - } - - if (net_addr_pton(AF_INET, argv[2], &addr)) { - PR_ERROR("Invalid address: %s\n", argv[2]); - return -EINVAL; - } - - net_if_ipv4_addr_add(iface, &addr, NET_ADDR_MANUAL, 0); - - if (net_addr_pton(AF_INET, argv[3], &addr)) { - PR_ERROR("Invalid netmask: %s", argv[3]); - return -EINVAL; - } - - net_if_ipv4_set_netmask(iface, &addr); - -#else /* CONFIG_NET_NATIVE_IPV4 */ - PR_INFO("Set %s and %s to enable native %s support.\n", - "CONFIG_NET_NATIVE", "CONFIG_NET_IPV4", "IPv4"); -#endif /* CONFIG_NET_NATIVE_IPV4 */ - return 0; -} - -static int cmd_net_ip_del(const struct shell *sh, size_t argc, char *argv[]) -{ -#if defined(CONFIG_NET_NATIVE_IPV4) - struct net_if *iface = NULL; - int idx; - struct in_addr addr; - - if (argc != 3) { - PR_ERROR("Correct usage: net ipv4 del
    "); - return -EINVAL; - } - - idx = get_iface_idx(sh, argv[1]); - if (idx < 0) { - return -ENOEXEC; - } - - iface = net_if_get_by_index(idx); - if (!iface) { - PR_WARNING("No such interface in index %d\n", idx); - return -ENOEXEC; - } - - if (net_addr_pton(AF_INET, argv[2], &addr)) { - PR_ERROR("Invalid address: %s\n", argv[2]); - return -EINVAL; - } - - if (!net_if_ipv4_addr_rm(iface, &addr)) { - PR_ERROR("Failed to delete %s\n", argv[2]); - return -ENOEXEC; - } -#else /* CONFIG_NET_NATIVE_IPV4 */ - PR_INFO("Set %s and %s to enable native %s support.\n", - "CONFIG_NET_NATIVE", "CONFIG_NET_IPV4", "IPv4"); -#endif /* CONFIG_NET_NATIVE_IPV4 */ - return 0; -} - -static int cmd_net_iface(const struct shell *sh, size_t argc, char *argv[]) -{ - struct net_if *iface = NULL; - struct net_shell_user_data user_data; - int idx; - - if (argv[1]) { - idx = get_iface_idx(sh, argv[1]); - if (idx < 0) { - return -ENOEXEC; - } - - iface = net_if_get_by_index(idx); - if (!iface) { - PR_WARNING("No such interface in index %d\n", idx); - return -ENOEXEC; - } - } - -#if defined(CONFIG_NET_HOSTNAME_ENABLE) - PR("Hostname: %s\n\n", net_hostname_get()); -#endif - - user_data.sh = sh; - user_data.user_data = iface; - - net_if_foreach(iface_cb, &user_data); - - return 0; -} - -static int cmd_net_set_mac(const struct shell *sh, size_t argc, char *argv[]) -{ -#if !defined(CONFIG_NET_L2_ETHERNET) || !defined(CONFIG_NET_L2_ETHERNET_MGMT) - PR_WARNING("Unsupported command, please enable CONFIG_NET_L2_ETHERNET " - "and CONFIG_NET_L2_ETHERNET_MGMT\n"); - return -ENOEXEC; -#else - struct net_if *iface; - struct ethernet_req_params params; - char *mac_addr = params.mac_address.addr; - int idx; - int ret; - - if (argc < 3) { - PR_WARNING("Missing interface index and/or MAC address\n"); - goto err; - } - - idx = get_iface_idx(sh, argv[1]); - if (idx < 0) { - goto err; - } - - iface = net_if_get_by_index(idx); - if (!iface) { - PR_WARNING("No such interface in index %d\n", idx); - goto err; - } - - if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) { - PR_WARNING("MAC address can be set only for Ethernet\n"); - goto err; - } - - if ((net_bytes_from_str(mac_addr, sizeof(params.mac_address), argv[2]) < 0) || - !net_eth_is_addr_valid(¶ms.mac_address)) { - PR_WARNING("Invalid MAC address: %s\n", argv[2]); - goto err; - } - - ret = net_mgmt(NET_REQUEST_ETHERNET_SET_MAC_ADDRESS, iface, ¶ms, sizeof(params)); - if (ret < 0) { - if (ret == -EACCES) { - PR_WARNING("MAC address cannot be set when interface is operational\n"); - goto err; - } - PR_WARNING("Failed to set MAC address (%d)\n", ret); - goto err; - } - - PR_INFO("MAC address set to %s\n", - net_sprint_ll_addr(net_if_get_link_addr(iface)->addr, - net_if_get_link_addr(iface)->len)); - - return 0; -err: - return -ENOEXEC; -#endif /* CONFIG_NET_L2_ETHERNET */ -} - -struct ctx_info { - int pos; - bool are_external_pools; - struct k_mem_slab *tx_slabs[CONFIG_NET_MAX_CONTEXTS]; - struct net_buf_pool *data_pools[CONFIG_NET_MAX_CONTEXTS]; -}; - -#if defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE) -#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL) -static bool slab_pool_found_already(struct ctx_info *info, - struct k_mem_slab *slab, - struct net_buf_pool *pool) -{ - int i; - - for (i = 0; i < CONFIG_NET_MAX_CONTEXTS; i++) { - if (slab) { - if (info->tx_slabs[i] == slab) { - return true; - } - } else { - if (info->data_pools[i] == pool) { - return true; - } - } - } - - return false; -} -#endif - -static void context_info(struct net_context *context, void *user_data) -{ -#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL) - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - struct ctx_info *info = data->user_data; - struct k_mem_slab *slab; - struct net_buf_pool *pool; - - if (!net_context_is_used(context)) { - return; - } - - if (context->tx_slab) { - slab = context->tx_slab(); - - if (slab_pool_found_already(info, slab, NULL)) { - return; - } - -#if defined(CONFIG_NET_BUF_POOL_USAGE) - PR("%p\t%u\t%u\tETX\n", - slab, slab->num_blocks, k_mem_slab_num_free_get(slab)); -#else - PR("%p\t%d\tETX\n", slab, slab->num_blocks); -#endif - info->are_external_pools = true; - info->tx_slabs[info->pos] = slab; - } - - if (context->data_pool) { - pool = context->data_pool(); - - if (slab_pool_found_already(info, NULL, pool)) { - return; - } - -#if defined(CONFIG_NET_BUF_POOL_USAGE) - PR("%p\t%d\t%ld\tEDATA (%s)\n", pool, pool->buf_count, - atomic_get(&pool->avail_count), pool->name); -#else - PR("%p\t%d\tEDATA\n", pool, pool->buf_count); -#endif - info->are_external_pools = true; - info->data_pools[info->pos] = pool; - } - - info->pos++; -#endif /* CONFIG_NET_CONTEXT_NET_PKT_POOL */ -} -#endif /* CONFIG_NET_OFFLOAD || CONFIG_NET_NATIVE */ - -static int cmd_net_mem(const struct shell *sh, size_t argc, char *argv[]) -{ - ARG_UNUSED(argc); - ARG_UNUSED(argv); - -#if defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE) - struct k_mem_slab *rx, *tx; - struct net_buf_pool *rx_data, *tx_data; - - net_pkt_get_info(&rx, &tx, &rx_data, &tx_data); - -#if defined(CONFIG_NET_BUF_FIXED_DATA_SIZE) - PR("Fragment length %d bytes\n", CONFIG_NET_BUF_DATA_SIZE); -#else - PR("Fragment data pool size %d bytes\n", CONFIG_NET_BUF_DATA_POOL_SIZE); -#endif /* CONFIG_NET_BUF_FIXED_DATA_SIZE */ - - PR("Network buffer pools:\n"); - -#if defined(CONFIG_NET_BUF_POOL_USAGE) - PR("Address\t\tTotal\tAvail\tName\n"); - - PR("%p\t%d\t%u\tRX\n", - rx, rx->num_blocks, k_mem_slab_num_free_get(rx)); - - PR("%p\t%d\t%u\tTX\n", - tx, tx->num_blocks, k_mem_slab_num_free_get(tx)); - - PR("%p\t%d\t%ld\tRX DATA (%s)\n", rx_data, rx_data->buf_count, - atomic_get(&rx_data->avail_count), rx_data->name); - - PR("%p\t%d\t%ld\tTX DATA (%s)\n", tx_data, tx_data->buf_count, - atomic_get(&tx_data->avail_count), tx_data->name); -#else - PR("Address\t\tTotal\tName\n"); - - PR("%p\t%d\tRX\n", rx, rx->num_blocks); - PR("%p\t%d\tTX\n", tx, tx->num_blocks); - PR("%p\t%d\tRX DATA\n", rx_data, rx_data->buf_count); - PR("%p\t%d\tTX DATA\n", tx_data, tx_data->buf_count); - PR_INFO("Set %s to enable %s support.\n", - "CONFIG_NET_BUF_POOL_USAGE", "net_buf allocation"); -#endif /* CONFIG_NET_BUF_POOL_USAGE */ - - if (IS_ENABLED(CONFIG_NET_CONTEXT_NET_PKT_POOL)) { - struct net_shell_user_data user_data; - struct ctx_info info; - - (void)memset(&info, 0, sizeof(info)); - - user_data.sh = sh; - user_data.user_data = &info; - - net_context_foreach(context_info, &user_data); - - if (!info.are_external_pools) { - PR("No external memory pools found.\n"); - } - } -#else - PR_INFO("Set %s to enable %s support.\n", - "CONFIG_NET_OFFLOAD or CONFIG_NET_NATIVE", "memory usage"); -#endif /* CONFIG_NET_OFFLOAD || CONFIG_NET_NATIVE */ - - return 0; -} - -static int cmd_net_nbr_rm(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if defined(CONFIG_NET_IPV6) - struct in6_addr addr; - int ret; -#endif - -#if defined(CONFIG_NET_IPV6) - if (!argv[1]) { - PR_WARNING("Neighbor IPv6 address missing.\n"); - return -ENOEXEC; - } - - ret = net_addr_pton(AF_INET6, argv[1], &addr); - if (ret < 0) { - PR_WARNING("Cannot parse '%s'\n", argv[1]); - return -ENOEXEC; - } - - if (!net_ipv6_nbr_rm(NULL, &addr)) { - PR_WARNING("Cannot remove neighbor %s\n", - net_sprint_ipv6_addr(&addr)); - return -ENOEXEC; - } else { - PR("Neighbor %s removed.\n", net_sprint_ipv6_addr(&addr)); - } -#else - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - PR_INFO("IPv6 not enabled.\n"); -#endif - - return 0; -} - -#if defined(CONFIG_NET_IPV6) -static void nbr_cb(struct net_nbr *nbr, void *user_data) -{ - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - int *count = data->user_data; - char *padding = ""; - char *state_pad = ""; - const char *state_str; -#if defined(CONFIG_NET_IPV6_ND) - int64_t remaining; -#endif - -#if defined(CONFIG_NET_L2_IEEE802154) - padding = " "; -#endif - - if (*count == 0) { - PR(" Neighbor Interface Flags State " - "Remain Link %sAddress\n", padding); - } - - (*count)++; - - state_str = net_ipv6_nbr_state2str(net_ipv6_nbr_data(nbr)->state); - - /* This is not a proper way but the minimal libc does not honor - * string lengths in %s modifier so in order the output to look - * nice, do it like this. - */ - if (strlen(state_str) == 5) { - state_pad = " "; - } - -#if defined(CONFIG_NET_IPV6_ND) - remaining = net_ipv6_nbr_data(nbr)->reachable + - net_ipv6_nbr_data(nbr)->reachable_timeout - - k_uptime_get(); -#endif - - PR("[%2d] %p %d %5d/%d/%d/%d %s%s %6d %17s%s %s\n", - *count, nbr, net_if_get_by_iface(nbr->iface), - net_ipv6_nbr_data(nbr)->link_metric, - nbr->ref, - net_ipv6_nbr_data(nbr)->ns_count, - net_ipv6_nbr_data(nbr)->is_router, - state_str, - state_pad, -#if defined(CONFIG_NET_IPV6_ND) - (int)(remaining > 0 ? remaining : 0), -#else - 0, -#endif - nbr->idx == NET_NBR_LLADDR_UNKNOWN ? "?" : - net_sprint_ll_addr( - net_nbr_get_lladdr(nbr->idx)->addr, - net_nbr_get_lladdr(nbr->idx)->len), - nbr->idx == NET_NBR_LLADDR_UNKNOWN ? "" : - (net_nbr_get_lladdr(nbr->idx)->len == 8U ? "" : padding), - net_sprint_ipv6_addr(&net_ipv6_nbr_data(nbr)->addr)); -} -#endif - -static int cmd_net_nbr(const struct shell *sh, size_t argc, char *argv[]) -{ -#if defined(CONFIG_NET_IPV6) - int count = 0; - struct net_shell_user_data user_data; -#endif - - ARG_UNUSED(argc); - ARG_UNUSED(argv); - -#if defined(CONFIG_NET_IPV6) - user_data.sh = sh; - user_data.user_data = &count; - - net_ipv6_nbr_foreach(nbr_cb, &user_data); - - if (count == 0) { - PR("No neighbors.\n"); - } -#else - PR_INFO("IPv6 not enabled.\n"); -#endif /* CONFIG_NET_IPV6 */ - - return 0; -} - -#if defined(CONFIG_NET_IP) - -static struct ping_context { - struct k_work_delayable work; - struct net_addr addr; - struct net_if *iface; - const struct shell *sh; - - /* Ping parameters */ - uint32_t count; - uint32_t interval; - uint32_t sequence; - uint16_t payload_size; - uint8_t tos; - int priority; -} ping_ctx; - -static void ping_done(struct ping_context *ctx); - -#if defined(CONFIG_NET_NATIVE_IPV6) - -static enum net_verdict handle_ipv6_echo_reply(struct net_pkt *pkt, - struct net_ipv6_hdr *ip_hdr, - struct net_icmp_hdr *icmp_hdr); - -static struct net_icmpv6_handler ping6_handler = { - .type = NET_ICMPV6_ECHO_REPLY, - .code = 0, - .handler = handle_ipv6_echo_reply, -}; - -static inline void remove_ipv6_ping_handler(void) -{ - net_icmpv6_unregister_handler(&ping6_handler); -} - -static enum net_verdict handle_ipv6_echo_reply(struct net_pkt *pkt, - struct net_ipv6_hdr *ip_hdr, - struct net_icmp_hdr *icmp_hdr) -{ - NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_access, - struct net_icmpv6_echo_req); - struct net_icmpv6_echo_req *icmp_echo; - uint32_t cycles; - char time_buf[16] = { 0 }; - - icmp_echo = (struct net_icmpv6_echo_req *)net_pkt_get_data(pkt, - &icmp_access); - if (icmp_echo == NULL) { - return -NET_DROP; - } - - net_pkt_skip(pkt, sizeof(*icmp_echo)); - - if (net_pkt_remaining_data(pkt) >= sizeof(uint32_t)) { - if (net_pkt_read_be32(pkt, &cycles)) { - return -NET_DROP; - } - - cycles = k_cycle_get_32() - cycles; - - snprintf(time_buf, sizeof(time_buf), -#ifdef CONFIG_FPU - "time=%.2f ms", - (double)((uint32_t)k_cyc_to_ns_floor64(cycles) / 1000000.f) -#else - "time=%d ms", - ((uint32_t)k_cyc_to_ns_floor64(cycles) / 1000000) -#endif - ); - } - - PR_SHELL(ping_ctx.sh, "%d bytes from %s to %s: icmp_seq=%d ttl=%d " -#ifdef CONFIG_IEEE802154 - "rssi=%d " -#endif - "%s\n", - ntohs(ip_hdr->len) - net_pkt_ipv6_ext_len(pkt) - - NET_ICMPH_LEN, - net_sprint_ipv6_addr(&ip_hdr->src), - net_sprint_ipv6_addr(&ip_hdr->dst), - ntohs(icmp_echo->sequence), - ip_hdr->hop_limit, -#ifdef CONFIG_IEEE802154 - net_pkt_ieee802154_rssi_dbm(pkt), -#endif - time_buf); - - if (ntohs(icmp_echo->sequence) == ping_ctx.count) { - ping_done(&ping_ctx); - } - - net_pkt_unref(pkt); - return NET_OK; -} -#else -#define remove_ipv6_ping_handler() -#endif /* CONFIG_NET_IPV6 */ - -#if defined(CONFIG_NET_NATIVE_IPV4) - -static enum net_verdict handle_ipv4_echo_reply(struct net_pkt *pkt, - struct net_ipv4_hdr *ip_hdr, - struct net_icmp_hdr *icmp_hdr); - -static struct net_icmpv4_handler ping4_handler = { - .type = NET_ICMPV4_ECHO_REPLY, - .code = 0, - .handler = handle_ipv4_echo_reply, -}; - -static inline void remove_ipv4_ping_handler(void) -{ - net_icmpv4_unregister_handler(&ping4_handler); -} - -static enum net_verdict handle_ipv4_echo_reply(struct net_pkt *pkt, - struct net_ipv4_hdr *ip_hdr, - struct net_icmp_hdr *icmp_hdr) -{ - NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_access, - struct net_icmpv4_echo_req); - uint32_t cycles; - struct net_icmpv4_echo_req *icmp_echo; - char time_buf[16] = { 0 }; - - icmp_echo = (struct net_icmpv4_echo_req *)net_pkt_get_data(pkt, - &icmp_access); - if (icmp_echo == NULL) { - return -NET_DROP; - } - - net_pkt_skip(pkt, sizeof(*icmp_echo)); - - if (net_pkt_remaining_data(pkt) >= sizeof(uint32_t)) { - if (net_pkt_read_be32(pkt, &cycles)) { - return -NET_DROP; - } - - cycles = k_cycle_get_32() - cycles; - - snprintf(time_buf, sizeof(time_buf), -#ifdef CONFIG_FPU - "time=%.2f ms", - (double)((uint32_t)k_cyc_to_ns_floor64(cycles) / 1000000.f) -#else - "time=%d ms", - ((uint32_t)k_cyc_to_ns_floor64(cycles) / 1000000) -#endif - ); - } - - PR_SHELL(ping_ctx.sh, "%d bytes from %s to %s: icmp_seq=%d ttl=%d " - "%s\n", - ntohs(ip_hdr->len) - net_pkt_ipv6_ext_len(pkt) - - NET_ICMPH_LEN, - net_sprint_ipv4_addr(&ip_hdr->src), - net_sprint_ipv4_addr(&ip_hdr->dst), - ntohs(icmp_echo->sequence), - ip_hdr->ttl, - time_buf); - - if (ntohs(icmp_echo->sequence) == ping_ctx.count) { - ping_done(&ping_ctx); - } - - net_pkt_unref(pkt); - return NET_OK; -} - -#else -#define remove_ipv4_ping_handler() -#endif /* CONFIG_NET_IPV4 */ - -static int parse_arg(size_t *i, size_t argc, char *argv[]) -{ - int res = -1; - const char *str = argv[*i] + 2; - char *endptr; - - if (*str == 0) { - if (*i + 1 >= argc) { - return -1; - } - - *i += 1; - str = argv[*i]; - } - - errno = 0; - if (strncmp(str, "0x", 2) == 0) { - res = strtol(str, &endptr, 16); - } else { - res = strtol(str, &endptr, 10); - } - - if (errno || (endptr == str)) { - return -1; - } - - return res; -} - -static void ping_cleanup(struct ping_context *ctx) -{ - remove_ipv6_ping_handler(); - remove_ipv4_ping_handler(); - shell_set_bypass(ctx->sh, NULL); -} - -static void ping_done(struct ping_context *ctx) -{ - k_work_cancel_delayable(&ctx->work); - ping_cleanup(ctx); - /* Dummy write to refresh the prompt. */ - shell_fprintf(ctx->sh, SHELL_NORMAL, ""); -} - -static void ping_work(struct k_work *work) -{ - struct k_work_delayable *dwork = k_work_delayable_from_work(work); - struct ping_context *ctx = - CONTAINER_OF(dwork, struct ping_context, work); - const struct shell *sh = ctx->sh; - int ret; - - ctx->sequence++; - - if (ctx->sequence > ctx->count) { - PR_INFO("Ping timeout\n"); - ping_done(ctx); - return; - } - - if (ctx->sequence < ctx->count) { - k_work_reschedule(&ctx->work, K_MSEC(ctx->interval)); - } else { - k_work_reschedule(&ctx->work, K_SECONDS(2)); - } - - if (ctx->addr.family == AF_INET6) { - ret = net_icmpv6_send_echo_request(ctx->iface, - &ctx->addr.in6_addr, - sys_rand32_get(), - ctx->sequence, - ctx->tos, - ctx->priority, - NULL, - ctx->payload_size); - } else { - ret = net_icmpv4_send_echo_request(ctx->iface, - &ctx->addr.in_addr, - sys_rand32_get(), - ctx->sequence, - ctx->tos, - ctx->priority, - NULL, - ctx->payload_size); - } - - if (ret != 0) { - PR_WARNING("Failed to send ping, err: %d", ret); - ping_done(ctx); - return; - } -} - -#define ASCII_CTRL_C 0x03 - -static void ping_bypass(const struct shell *sh, uint8_t *data, size_t len) -{ - ARG_UNUSED(sh); - - for (size_t i = 0; i < len; i++) { - if (data[i] == ASCII_CTRL_C) { - k_work_cancel_delayable(&ping_ctx.work); - ping_cleanup(&ping_ctx); - break; - } - } -} - -static struct net_if *ping_select_iface(int id, struct net_addr *target) -{ - struct net_if *iface = net_if_get_by_index(id); - - if (iface != NULL) { - goto out; - } - - if (IS_ENABLED(CONFIG_NET_IPV4) && target->family == AF_INET) { - iface = net_if_ipv4_select_src_iface(&target->in_addr); - if (iface != NULL) { - goto out; - } - - iface = net_if_get_default(); - goto out; - } - - if (IS_ENABLED(CONFIG_NET_IPV6) && target->family == AF_INET6) { - struct net_nbr *nbr; -#if defined(CONFIG_NET_ROUTE) - struct net_route_entry *route; -#endif - - iface = net_if_ipv6_select_src_iface(&target->in6_addr); - if (iface != NULL) { - goto out; - } - - nbr = net_ipv6_nbr_lookup(NULL, &target->in6_addr); - if (nbr) { - iface = nbr->iface; - goto out; - } - -#if defined(CONFIG_NET_ROUTE) - route = net_route_lookup(NULL, &target->in6_addr); - if (route) { - iface = route->iface; - goto out; - } -#endif - - iface = net_if_get_default(); - } - -out: - return iface; -} - -#endif /* CONFIG_NET_IP */ - -static int cmd_net_ping(const struct shell *sh, size_t argc, char *argv[]) -{ -#if !defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6) - ARG_UNUSED(sh); - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - return -EOPNOTSUPP; -#else - char *host = NULL; - - int count = 3; - int interval = 1000; - int iface_idx = -1; - int tos = 0; - int payload_size = 4; - int priority = -1; - - for (size_t i = 1; i < argc; ++i) { - - if (*argv[i] != '-') { - host = argv[i]; - continue; - } - - switch (argv[i][1]) { - case 'c': - count = parse_arg(&i, argc, argv); - if (count < 0) { - PR_WARNING("Parse error: %s\n", argv[i]); - return -ENOEXEC; - } - - - break; - case 'i': - interval = parse_arg(&i, argc, argv); - if (interval < 0) { - PR_WARNING("Parse error: %s\n", argv[i]); - return -ENOEXEC; - } - - break; - - case 'I': - iface_idx = parse_arg(&i, argc, argv); - if (iface_idx < 0 || !net_if_get_by_index(iface_idx)) { - PR_WARNING("Parse error: %s\n", argv[i]); - return -ENOEXEC; - } - break; - - case 'p': - priority = parse_arg(&i, argc, argv); - if (priority < 0 || priority > UINT8_MAX) { - PR_WARNING("Parse error: %s\n", argv[i]); - return -ENOEXEC; - } - break; - - case 'Q': - tos = parse_arg(&i, argc, argv); - if (tos < 0 || tos > UINT8_MAX) { - PR_WARNING("Parse error: %s\n", argv[i]); - return -ENOEXEC; - } - - break; - - case 's': - payload_size = parse_arg(&i, argc, argv); - if (payload_size < 0 || payload_size > UINT16_MAX) { - PR_WARNING("Parse error: %s\n", argv[i]); - return -ENOEXEC; - } - - break; - - default: - PR_WARNING("Unrecognized argument: %s\n", argv[i]); - return -ENOEXEC; - } - } - - if (!host) { - PR_WARNING("Target host missing\n"); - return -ENOEXEC; - } - - memset(&ping_ctx, 0, sizeof(ping_ctx)); - - k_work_init_delayable(&ping_ctx.work, ping_work); - - ping_ctx.sh = sh; - ping_ctx.count = count; - ping_ctx.interval = interval; - ping_ctx.priority = priority; - ping_ctx.tos = tos; - ping_ctx.payload_size = payload_size; - - if (IS_ENABLED(CONFIG_NET_IPV6) && - net_addr_pton(AF_INET6, host, &ping_ctx.addr.in6_addr) == 0) { - ping_ctx.addr.family = AF_INET6; - net_icmpv6_register_handler(&ping6_handler); - } else if (IS_ENABLED(CONFIG_NET_IPV4) && - net_addr_pton(AF_INET, host, &ping_ctx.addr.in_addr) == 0) { - ping_ctx.addr.family = AF_INET; - net_icmpv4_register_handler(&ping4_handler); - } else { - PR_WARNING("Invalid IP address\n"); - return 0; - } - - ping_ctx.iface = ping_select_iface(iface_idx, &ping_ctx.addr); - - PR("PING %s\n", host); - - shell_set_bypass(sh, ping_bypass); - k_work_reschedule(&ping_ctx.work, K_NO_WAIT); - - return 0; -#endif -} - -static bool is_pkt_part_of_slab(const struct k_mem_slab *slab, const char *ptr) -{ - size_t last_offset = (slab->num_blocks - 1) * slab->block_size; - size_t ptr_offset; - - /* Check if pointer fits into slab buffer area. */ - if ((ptr < slab->buffer) || (ptr > slab->buffer + last_offset)) { - return false; - } - - /* Check if pointer offset is correct. */ - ptr_offset = ptr - slab->buffer; - if (ptr_offset % slab->block_size != 0) { - return false; - } - - return true; -} - -struct ctx_pkt_slab_info { - const void *ptr; - bool pkt_source_found; -}; - -static void check_context_pool(struct net_context *context, void *user_data) -{ -#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL) - if (!net_context_is_used(context)) { - return; - } - - if (context->tx_slab) { - struct ctx_pkt_slab_info *info = user_data; - struct k_mem_slab *slab = context->tx_slab(); - - if (is_pkt_part_of_slab(slab, info->ptr)) { - info->pkt_source_found = true; - } - } -#endif /* CONFIG_NET_CONTEXT_NET_PKT_POOL */ -} - -static bool is_pkt_ptr_valid(const void *ptr) -{ - struct k_mem_slab *rx, *tx; - - net_pkt_get_info(&rx, &tx, NULL, NULL); - - if (is_pkt_part_of_slab(rx, ptr) || is_pkt_part_of_slab(tx, ptr)) { - return true; - } - - if (IS_ENABLED(CONFIG_NET_CONTEXT_NET_PKT_POOL)) { - struct ctx_pkt_slab_info info; - - info.ptr = ptr; - info.pkt_source_found = false; - - net_context_foreach(check_context_pool, &info); - - if (info.pkt_source_found) { - return true; - } - } - - return false; -} - -static struct net_pkt *get_net_pkt(const char *ptr_str) -{ - uint8_t buf[sizeof(intptr_t)]; - intptr_t ptr = 0; - size_t len; - int i; - - if (ptr_str[0] == '0' && ptr_str[1] == 'x') { - ptr_str += 2; - } - - len = hex2bin(ptr_str, strlen(ptr_str), buf, sizeof(buf)); - if (!len) { - return NULL; - } - - for (i = len - 1; i >= 0; i--) { - ptr |= buf[i] << 8 * (len - 1 - i); - } - - return (struct net_pkt *)ptr; -} - -static void net_pkt_buffer_info(const struct shell *sh, struct net_pkt *pkt) -{ - struct net_buf *buf = pkt->buffer; - - PR("net_pkt %p buffer chain:\n", pkt); - PR("%p[%ld]", pkt, atomic_get(&pkt->atomic_ref)); - - if (buf) { - PR("->"); - } - - while (buf) { - PR("%p[%ld/%u (%u/%u)]", buf, atomic_get(&pkt->atomic_ref), - buf->len, net_buf_max_len(buf), buf->size); - - buf = buf->frags; - if (buf) { - PR("->"); - } - } - - PR("\n"); -} - -static void net_pkt_buffer_hexdump(const struct shell *sh, - struct net_pkt *pkt) -{ - struct net_buf *buf = pkt->buffer; - int i = 0; - - if (!buf || buf->ref == 0) { - return; - } - - PR("net_pkt %p buffer chain hexdump:\n", pkt); - - while (buf) { - PR("net_buf[%d] %p\n", i++, buf); - shell_hexdump(sh, buf->data, buf->len); - buf = buf->frags; - } -} - -static int cmd_net_pkt(const struct shell *sh, size_t argc, char *argv[]) -{ - if (argv[1]) { - struct net_pkt *pkt; - - pkt = get_net_pkt(argv[1]); - if (!pkt) { - PR_ERROR("Invalid ptr value (%s). " - "Example: 0x01020304\n", argv[1]); - - return -ENOEXEC; - } - - if (!is_pkt_ptr_valid(pkt)) { - PR_ERROR("Pointer is not recognized as net_pkt (%s).\n", - argv[1]); - - return -ENOEXEC; - } - - net_pkt_buffer_info(sh, pkt); - PR("\n"); - net_pkt_buffer_hexdump(sh, pkt); - } else { - PR_INFO("Pointer value must be given.\n"); - return -ENOEXEC; - } - - return 0; -} - -static int cmd_net_ppp_ping(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if defined(CONFIG_NET_PPP) - if (argv[1]) { - int ret, idx = get_iface_idx(sh, argv[1]); - - if (idx < 0) { - return -ENOEXEC; - } - - ret = net_ppp_ping(idx, MSEC_PER_SEC * 1); - if (ret < 0) { - if (ret == -EAGAIN) { - PR_INFO("PPP Echo-Req timeout.\n"); - } else if (ret == -ENODEV || ret == -ENOENT) { - PR_INFO("Not a PPP interface (%d)\n", idx); - } else { - PR_INFO("PPP Echo-Req failed (%d)\n", ret); - } - } else { - if (ret > 1000) { - PR_INFO("%s%d msec\n", - "Received PPP Echo-Reply in ", - ret / 1000); - } else { - PR_INFO("%s%d usec\n", - "Received PPP Echo-Reply in ", ret); - } - } - } else { - PR_INFO("PPP network interface must be given.\n"); - return -ENOEXEC; - } -#else - PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_L2_PPP", "PPP"); -#endif - return 0; -} - -static int cmd_net_ppp_status(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if defined(CONFIG_NET_PPP) - int idx = 0; - struct ppp_context *ctx; - - if (argv[1]) { - idx = get_iface_idx(sh, argv[1]); - if (idx < 0) { - return -ENOEXEC; - } - } - - ctx = net_ppp_context_get(idx); - if (!ctx) { - PR_INFO("PPP context not found.\n"); - return -ENOEXEC; - } - - PR("PPP phase : %s (%d)\n", ppp_phase_str(ctx->phase), - ctx->phase); - PR("LCP state : %s (%d)\n", - ppp_state_str(ctx->lcp.fsm.state), ctx->lcp.fsm.state); - PR("LCP retransmits : %u\n", ctx->lcp.fsm.retransmits); - PR("LCP NACK loops : %u\n", ctx->lcp.fsm.nack_loops); - PR("LCP NACKs recv : %u\n", ctx->lcp.fsm.recv_nack_loops); - PR("LCP current id : %d\n", ctx->lcp.fsm.id); - PR("LCP ACK received : %s\n", ctx->lcp.fsm.ack_received ? - "yes" : "no"); - -#if defined(CONFIG_NET_IPV4) - PR("IPCP state : %s (%d)\n", - ppp_state_str(ctx->ipcp.fsm.state), ctx->ipcp.fsm.state); - PR("IPCP retransmits : %u\n", ctx->ipcp.fsm.retransmits); - PR("IPCP NACK loops : %u\n", ctx->ipcp.fsm.nack_loops); - PR("IPCP NACKs recv : %u\n", ctx->ipcp.fsm.recv_nack_loops); - PR("IPCP current id : %d\n", ctx->ipcp.fsm.id); - PR("IPCP ACK received : %s\n", ctx->ipcp.fsm.ack_received ? - "yes" : "no"); -#endif /* CONFIG_NET_IPV4 */ - -#if defined(CONFIG_NET_IPV6) - PR("IPv6CP state : %s (%d)\n", - ppp_state_str(ctx->ipv6cp.fsm.state), ctx->ipv6cp.fsm.state); - PR("IPv6CP retransmits : %u\n", ctx->ipv6cp.fsm.retransmits); - PR("IPv6CP NACK loops : %u\n", ctx->ipv6cp.fsm.nack_loops); - PR("IPv6CP NACKs recv : %u\n", ctx->ipv6cp.fsm.recv_nack_loops); - PR("IPv6CP current id : %d\n", ctx->ipv6cp.fsm.id); - PR("IPv6CP ACK received : %s\n", ctx->ipv6cp.fsm.ack_received ? - "yes" : "no"); -#endif /* CONFIG_NET_IPV6 */ - -#if defined(CONFIG_NET_L2_PPP_PAP) - PR("PAP state : %s (%d)\n", - ppp_state_str(ctx->pap.fsm.state), ctx->pap.fsm.state); - PR("PAP retransmits : %u\n", ctx->pap.fsm.retransmits); - PR("PAP NACK loops : %u\n", ctx->pap.fsm.nack_loops); - PR("PAP NACKs recv : %u\n", ctx->pap.fsm.recv_nack_loops); - PR("PAP current id : %d\n", ctx->pap.fsm.id); - PR("PAP ACK received : %s\n", ctx->pap.fsm.ack_received ? - "yes" : "no"); -#endif /* CONFIG_NET_L2_PPP_PAP */ - -#else - PR_INFO("Set %s to enable %s support.\n", - "CONFIG_NET_L2_PPP and CONFIG_NET_PPP", "PPP"); -#endif - return 0; -} - -static int cmd_net_route(const struct shell *sh, size_t argc, char *argv[]) -{ - ARG_UNUSED(argc); - ARG_UNUSED(argv); - -#if defined(CONFIG_NET_NATIVE) -#if defined(CONFIG_NET_ROUTE) || defined(CONFIG_NET_ROUTE_MCAST) - struct net_shell_user_data user_data; -#endif - -#if defined(CONFIG_NET_ROUTE) || defined(CONFIG_NET_ROUTE_MCAST) - user_data.sh = sh; -#endif - -#if defined(CONFIG_NET_ROUTE) - net_if_foreach(iface_per_route_cb, &user_data); -#else - PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_ROUTE", - "network route"); -#endif - -#if defined(CONFIG_NET_ROUTE_MCAST) - net_if_foreach(iface_per_mcast_route_cb, &user_data); -#endif -#endif - return 0; -} - -static int cmd_net_stacks(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if !defined(CONFIG_KERNEL_SHELL) - PR("Enable CONFIG_KERNEL_SHELL and type \"kernel stacks\" to see stack information.\n"); -#else - PR("Type \"kernel stacks\" to see stack information.\n"); -#endif - return 0; -} - -#if defined(CONFIG_NET_STATISTICS_PER_INTERFACE) -static void net_shell_print_statistics_all(struct net_shell_user_data *data) -{ - net_if_foreach(net_shell_print_statistics, data); -} -#endif - -static int cmd_net_stats_all(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if defined(CONFIG_NET_STATISTICS) - struct net_shell_user_data user_data; -#endif - -#if defined(CONFIG_NET_STATISTICS) - user_data.sh = sh; - - /* Print global network statistics */ - net_shell_print_statistics_all(&user_data); -#else - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_STATISTICS", - "statistics"); -#endif - - return 0; -} - -static int cmd_net_stats_iface(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if defined(CONFIG_NET_STATISTICS) -#if defined(CONFIG_NET_STATISTICS_PER_INTERFACE) - struct net_shell_user_data data; - struct net_if *iface; - char *endptr; - int idx; -#endif -#endif - -#if defined(CONFIG_NET_STATISTICS) -#if defined(CONFIG_NET_STATISTICS_PER_INTERFACE) - if (argv[1] == NULL) { - PR_WARNING("Network interface index missing!\n"); - return -ENOEXEC; - } - - idx = strtol(argv[1], &endptr, 10); - if (*endptr != '\0') { - PR_WARNING("Invalid index %s\n", argv[1]); - return -ENOEXEC; - } - - iface = net_if_get_by_index(idx); - if (!iface) { - PR_WARNING("No such interface in index %d\n", idx); - return -ENOEXEC; - } - - data.sh = sh; - - net_shell_print_statistics(iface, &data); -#else - PR_INFO("Per network interface statistics not collected.\n"); - PR_INFO("Please enable CONFIG_NET_STATISTICS_PER_INTERFACE\n"); -#endif /* CONFIG_NET_STATISTICS_PER_INTERFACE */ -#else - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_STATISTICS", - "statistics"); -#endif - - return 0; -} - -static int cmd_net_stats(const struct shell *sh, size_t argc, char *argv[]) -{ -#if defined(CONFIG_NET_STATISTICS) - if (!argv[1]) { - cmd_net_stats_all(sh, argc, argv); - return 0; - } - - if (strcmp(argv[1], "reset") == 0) { - net_stats_reset(NULL); - } else { - cmd_net_stats_iface(sh, argc, argv); - } -#else - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_STATISTICS", - "statistics"); -#endif - - return 0; -} - -#if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_NATIVE_TCP) -static struct net_context *tcp_ctx; -static const struct shell *tcp_shell; - -#define TCP_CONNECT_TIMEOUT K_SECONDS(5) /* ms */ -#define TCP_TIMEOUT K_SECONDS(2) /* ms */ - -static void tcp_connected(struct net_context *context, - int status, - void *user_data) -{ - if (status < 0) { - PR_SHELL(tcp_shell, "TCP connection failed (%d)\n", status); - - net_context_put(context); - - tcp_ctx = NULL; - } else { - PR_SHELL(tcp_shell, "TCP connected\n"); - } -} - -static void get_my_ipv6_addr(struct net_if *iface, - struct sockaddr *myaddr) -{ -#if defined(CONFIG_NET_IPV6) - const struct in6_addr *my6addr; - - my6addr = net_if_ipv6_select_src_addr(iface, - &net_sin6(myaddr)->sin6_addr); - - memcpy(&net_sin6(myaddr)->sin6_addr, my6addr, sizeof(struct in6_addr)); - - net_sin6(myaddr)->sin6_port = 0U; /* let the IP stack to select */ -#endif -} - -static void get_my_ipv4_addr(struct net_if *iface, - struct sockaddr *myaddr) -{ -#if defined(CONFIG_NET_NATIVE_IPV4) - /* Just take the first IPv4 address of an interface. */ - memcpy(&net_sin(myaddr)->sin_addr, - &iface->config.ip.ipv4->unicast[0].address.in_addr, - sizeof(struct in_addr)); - - net_sin(myaddr)->sin_port = 0U; /* let the IP stack to select */ -#endif -} - -static void print_connect_info(const struct shell *sh, - int family, - struct sockaddr *myaddr, - struct sockaddr *addr) -{ - switch (family) { - case AF_INET: - if (IS_ENABLED(CONFIG_NET_IPV4)) { - PR("Connecting from %s:%u ", - net_sprint_ipv4_addr(&net_sin(myaddr)->sin_addr), - ntohs(net_sin(myaddr)->sin_port)); - PR("to %s:%u\n", - net_sprint_ipv4_addr(&net_sin(addr)->sin_addr), - ntohs(net_sin(addr)->sin_port)); - } else { - PR_INFO("IPv4 not supported\n"); - } - - break; - - case AF_INET6: - if (IS_ENABLED(CONFIG_NET_IPV6)) { - PR("Connecting from [%s]:%u ", - net_sprint_ipv6_addr(&net_sin6(myaddr)->sin6_addr), - ntohs(net_sin6(myaddr)->sin6_port)); - PR("to [%s]:%u\n", - net_sprint_ipv6_addr(&net_sin6(addr)->sin6_addr), - ntohs(net_sin6(addr)->sin6_port)); - } else { - PR_INFO("IPv6 not supported\n"); - } - - break; - - default: - PR_WARNING("Unknown protocol family (%d)\n", family); - break; - } -} - -static void tcp_connect(const struct shell *sh, char *host, uint16_t port, - struct net_context **ctx) -{ - struct net_if *iface = net_if_get_default(); - struct sockaddr myaddr; - struct sockaddr addr; - struct net_nbr *nbr; - int addrlen; - int family; - int ret; - - if (IS_ENABLED(CONFIG_NET_IPV6) && !IS_ENABLED(CONFIG_NET_IPV4)) { - ret = net_addr_pton(AF_INET6, host, - &net_sin6(&addr)->sin6_addr); - if (ret < 0) { - PR_WARNING("Invalid IPv6 address\n"); - return; - } - - net_sin6(&addr)->sin6_port = htons(port); - addrlen = sizeof(struct sockaddr_in6); - - nbr = net_ipv6_nbr_lookup(NULL, &net_sin6(&addr)->sin6_addr); - if (nbr) { - iface = nbr->iface; - } - - get_my_ipv6_addr(iface, &myaddr); - family = addr.sa_family = myaddr.sa_family = AF_INET6; - - } else if (IS_ENABLED(CONFIG_NET_IPV4) && - !IS_ENABLED(CONFIG_NET_IPV6)) { - ARG_UNUSED(nbr); - - ret = net_addr_pton(AF_INET, host, &net_sin(&addr)->sin_addr); - if (ret < 0) { - PR_WARNING("Invalid IPv4 address\n"); - return; - } - - get_my_ipv4_addr(iface, &myaddr); - net_sin(&addr)->sin_port = htons(port); - addrlen = sizeof(struct sockaddr_in); - family = addr.sa_family = myaddr.sa_family = AF_INET; - } else if (IS_ENABLED(CONFIG_NET_IPV6) && - IS_ENABLED(CONFIG_NET_IPV4)) { - ret = net_addr_pton(AF_INET6, host, - &net_sin6(&addr)->sin6_addr); - if (ret < 0) { - ret = net_addr_pton(AF_INET, host, - &net_sin(&addr)->sin_addr); - if (ret < 0) { - PR_WARNING("Invalid IP address\n"); - return; - } - - net_sin(&addr)->sin_port = htons(port); - addrlen = sizeof(struct sockaddr_in); - - get_my_ipv4_addr(iface, &myaddr); - family = addr.sa_family = myaddr.sa_family = AF_INET; - } else { - net_sin6(&addr)->sin6_port = htons(port); - addrlen = sizeof(struct sockaddr_in6); - - nbr = net_ipv6_nbr_lookup(NULL, - &net_sin6(&addr)->sin6_addr); - if (nbr) { - iface = nbr->iface; - } - - get_my_ipv6_addr(iface, &myaddr); - family = addr.sa_family = myaddr.sa_family = AF_INET6; - } - } else { - PR_WARNING("No IPv6 nor IPv4 is enabled\n"); - return; - } - - print_connect_info(sh, family, &myaddr, &addr); - - ret = net_context_get(family, SOCK_STREAM, IPPROTO_TCP, ctx); - if (ret < 0) { - PR_WARNING("Cannot get TCP context (%d)\n", ret); - return; - } - - ret = net_context_bind(*ctx, &myaddr, addrlen); - if (ret < 0) { - PR_WARNING("Cannot bind TCP (%d)\n", ret); - return; - } - - /* Note that we cannot put shell as a user_data when connecting - * because the tcp_connected() will be called much later and - * all local stack variables are lost at that point. - */ - tcp_shell = sh; - -#if defined(CONFIG_NET_SOCKETS_CONNECT_TIMEOUT) -#define CONNECT_TIMEOUT K_MSEC(CONFIG_NET_SOCKETS_CONNECT_TIMEOUT) -#else -#define CONNECT_TIMEOUT K_SECONDS(3) -#endif - - net_context_connect(*ctx, &addr, addrlen, tcp_connected, - CONNECT_TIMEOUT, NULL); -} - -static void tcp_sent_cb(struct net_context *context, - int status, void *user_data) -{ - PR_SHELL(tcp_shell, "Message sent\n"); -} - -static void tcp_recv_cb(struct net_context *context, struct net_pkt *pkt, - union net_ip_header *ip_hdr, - union net_proto_header *proto_hdr, - int status, void *user_data) -{ - int ret, len; - - if (pkt == NULL) { - if (!tcp_ctx || !net_context_is_used(tcp_ctx)) { - return; - } - - ret = net_context_put(tcp_ctx); - if (ret < 0) { - PR_SHELL(tcp_shell, - "Cannot close the connection (%d)\n", ret); - return; - } - - PR_SHELL(tcp_shell, "Connection closed by remote peer.\n"); - tcp_ctx = NULL; - - return; - } - - len = net_pkt_remaining_data(pkt); - - (void)net_context_update_recv_wnd(context, len); - - PR_SHELL(tcp_shell, "%zu bytes received\n", net_pkt_get_len(pkt)); - - net_pkt_unref(pkt); -} -#endif - -static int cmd_net_tcp_connect(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_NATIVE_TCP) - int arg = 0; - - /* tcp connect port */ - char *endptr; - char *ip; - uint16_t port; - - /* tcp connect port */ - if (tcp_ctx && net_context_is_used(tcp_ctx)) { - PR("Already connected\n"); - return -ENOEXEC; - } - - if (!argv[++arg]) { - PR_WARNING("Peer IP address missing.\n"); - return -ENOEXEC; - } - - ip = argv[arg]; - - if (!argv[++arg]) { - PR_WARNING("Peer port missing.\n"); - return -ENOEXEC; - } - - port = strtol(argv[arg], &endptr, 10); - if (*endptr != '\0') { - PR_WARNING("Invalid port %s\n", argv[arg]); - return -ENOEXEC; - } - - tcp_connect(sh, ip, port, &tcp_ctx); -#else - PR_INFO("Set %s to enable %s support.\n", - "CONFIG_NET_TCP and CONFIG_NET_NATIVE", "TCP"); -#endif /* CONFIG_NET_NATIVE_TCP */ - - return 0; -} - -static int cmd_net_tcp_send(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_NATIVE_TCP) - int arg = 0; - int ret; - struct net_shell_user_data user_data; - - /* tcp send */ - if (!tcp_ctx || !net_context_is_used(tcp_ctx)) { - PR_WARNING("Not connected\n"); - return -ENOEXEC; - } - - if (!argv[++arg]) { - PR_WARNING("No data to send.\n"); - return -ENOEXEC; - } - - user_data.sh = sh; - - ret = net_context_send(tcp_ctx, (uint8_t *)argv[arg], - strlen(argv[arg]), tcp_sent_cb, - TCP_TIMEOUT, &user_data); - if (ret < 0) { - PR_WARNING("Cannot send msg (%d)\n", ret); - return -ENOEXEC; - } - -#else - PR_INFO("Set %s to enable %s support.\n", - "CONFIG_NET_TCP and CONFIG_NET_NATIVE", "TCP"); -#endif /* CONFIG_NET_NATIVE_TCP */ - - return 0; -} - -static int cmd_net_tcp_recv(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_NATIVE_TCP) - int ret; - struct net_shell_user_data user_data; - - /* tcp recv */ - if (!tcp_ctx || !net_context_is_used(tcp_ctx)) { - PR_WARNING("Not connected\n"); - return -ENOEXEC; - } - - user_data.sh = sh; - - ret = net_context_recv(tcp_ctx, tcp_recv_cb, K_NO_WAIT, &user_data); - if (ret < 0) { - PR_WARNING("Cannot recv data (%d)\n", ret); - return -ENOEXEC; - } - -#else - PR_INFO("Set %s to enable %s support.\n", - "CONFIG_NET_TCP and CONFIG_NET_NATIVE", "TCP"); -#endif /* CONFIG_NET_NATIVE_TCP */ - - return 0; -} - -static int cmd_net_tcp_close(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_NATIVE_TCP) - int ret; - - /* tcp close */ - if (!tcp_ctx || !net_context_is_used(tcp_ctx)) { - PR_WARNING("Not connected\n"); - return -ENOEXEC; - } - - ret = net_context_put(tcp_ctx); - if (ret < 0) { - PR_WARNING("Cannot close the connection (%d)\n", ret); - return -ENOEXEC; - } - - PR("Connection closed.\n"); - tcp_ctx = NULL; -#else - PR_INFO("Set %s to enable %s support.\n", - "CONFIG_NET_TCP and CONFIG_NET_NATIVE", "TCP"); -#endif /* CONFIG_NET_TCP */ - - return 0; -} - -static int cmd_net_tcp(const struct shell *sh, size_t argc, char *argv[]) -{ - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - return 0; -} - -#if defined(CONFIG_NET_UDP) && defined(CONFIG_NET_NATIVE_UDP) -static struct net_context *udp_ctx; -static const struct shell *udp_shell; -K_SEM_DEFINE(udp_send_wait, 0, 1); - -static void udp_rcvd(struct net_context *context, struct net_pkt *pkt, - union net_ip_header *ip_hdr, - union net_proto_header *proto_hdr, int status, - void *user_data) -{ - if (pkt) { - size_t len = net_pkt_remaining_data(pkt); - uint8_t byte; - - PR_SHELL(udp_shell, "Received UDP packet: "); - for (size_t i = 0; i < len; ++i) { - net_pkt_read_u8(pkt, &byte); - PR_SHELL(udp_shell, "%02x ", byte); - } - PR_SHELL(udp_shell, "\n"); - - net_pkt_unref(pkt); - } -} - -static void udp_sent(struct net_context *context, int status, void *user_data) -{ - ARG_UNUSED(context); - ARG_UNUSED(status); - ARG_UNUSED(user_data); - - PR_SHELL(udp_shell, "Message sent\n"); - k_sem_give(&udp_send_wait); -} -#endif - -static int cmd_net_udp_bind(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if !defined(CONFIG_NET_UDP) || !defined(CONFIG_NET_NATIVE_UDP) - ARG_UNUSED(sh); - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - return -EOPNOTSUPP; -#else - char *addr_str = NULL; - char *endptr = NULL; - uint16_t port; - int ret; - - struct net_if *iface; - struct sockaddr addr; - int addrlen; - - if (argc < 3) { - PR_WARNING("Not enough arguments given for udp bind command\n"); - return -EINVAL; - } - - addr_str = argv[1]; - port = strtol(argv[2], &endptr, 0); - - if (endptr == argv[2]) { - PR_WARNING("Invalid port number\n"); - return -EINVAL; - } - - if (udp_ctx && net_context_is_used(udp_ctx)) { - PR_WARNING("Network context already in use\n"); - return -EALREADY; - } - - memset(&addr, 0, sizeof(addr)); - - ret = net_ipaddr_parse(addr_str, strlen(addr_str), &addr); - if (ret < 0) { - PR_WARNING("Cannot parse address \"%s\"\n", addr_str); - return ret; - } - - ret = net_context_get(addr.sa_family, SOCK_DGRAM, IPPROTO_UDP, - &udp_ctx); - if (ret < 0) { - PR_WARNING("Cannot get UDP context (%d)\n", ret); - return ret; - } - - udp_shell = sh; - - if (IS_ENABLED(CONFIG_NET_IPV6) && addr.sa_family == AF_INET6) { - net_sin6(&addr)->sin6_port = htons(port); - addrlen = sizeof(struct sockaddr_in6); - - iface = net_if_ipv6_select_src_iface( - &net_sin6(&addr)->sin6_addr); - } else if (IS_ENABLED(CONFIG_NET_IPV4) && addr.sa_family == AF_INET) { - net_sin(&addr)->sin_port = htons(port); - addrlen = sizeof(struct sockaddr_in); - - iface = net_if_ipv4_select_src_iface( - &net_sin(&addr)->sin_addr); - } else { - PR_WARNING("IPv6 and IPv4 are disabled, cannot %s.\n", "bind"); - goto release_ctx; - } - - if (!iface) { - PR_WARNING("No interface to send to given host\n"); - goto release_ctx; - } - - net_context_set_iface(udp_ctx, iface); - - ret = net_context_bind(udp_ctx, &addr, addrlen); - if (ret < 0) { - PR_WARNING("Binding to UDP port failed (%d)\n", ret); - goto release_ctx; - } - - ret = net_context_recv(udp_ctx, udp_rcvd, K_NO_WAIT, NULL); - if (ret < 0) { - PR_WARNING("Receiving from UDP port failed (%d)\n", ret); - goto release_ctx; - } - - return 0; - -release_ctx: - ret = net_context_put(udp_ctx); - if (ret < 0) { - PR_WARNING("Cannot put UDP context (%d)\n", ret); - } - - return 0; -#endif -} - -static int cmd_net_udp_close(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if !defined(CONFIG_NET_UDP) || !defined(CONFIG_NET_NATIVE_UDP) - ARG_UNUSED(sh); - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - return -EOPNOTSUPP; -#else - int ret; - - if (!udp_ctx || !net_context_is_used(udp_ctx)) { - PR_WARNING("Network context is not used. Cannot close.\n"); - return -EINVAL; - } - - ret = net_context_put(udp_ctx); - if (ret < 0) { - PR_WARNING("Cannot close UDP port (%d)\n", ret); - } - - return 0; -#endif -} - -static int cmd_net_udp_send(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if !defined(CONFIG_NET_UDP) || !defined(CONFIG_NET_NATIVE_UDP) - ARG_UNUSED(sh); - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - return -EOPNOTSUPP; -#else - char *host = NULL; - char *endptr = NULL; - uint16_t port; - uint8_t *payload = NULL; - int ret; - - struct net_if *iface; - struct sockaddr addr; - int addrlen; - - if (argc < 4) { - PR_WARNING("Not enough arguments given for udp send command\n"); - return -EINVAL; - } - - host = argv[1]; - port = strtol(argv[2], &endptr, 0); - payload = argv[3]; - - if (endptr == argv[2]) { - PR_WARNING("Invalid port number\n"); - return -EINVAL; - } - - if (udp_ctx && net_context_is_used(udp_ctx)) { - PR_WARNING("Network context already in use\n"); - return -EALREADY; - } - - memset(&addr, 0, sizeof(addr)); - ret = net_ipaddr_parse(host, strlen(host), &addr); - if (ret < 0) { - PR_WARNING("Cannot parse address \"%s\"\n", host); - return ret; - } - - ret = net_context_get(addr.sa_family, SOCK_DGRAM, IPPROTO_UDP, - &udp_ctx); - if (ret < 0) { - PR_WARNING("Cannot get UDP context (%d)\n", ret); - return ret; - } - - udp_shell = sh; - - if (IS_ENABLED(CONFIG_NET_IPV6) && addr.sa_family == AF_INET6) { - net_sin6(&addr)->sin6_port = htons(port); - addrlen = sizeof(struct sockaddr_in6); - - iface = net_if_ipv6_select_src_iface( - &net_sin6(&addr)->sin6_addr); - } else if (IS_ENABLED(CONFIG_NET_IPV4) && addr.sa_family == AF_INET) { - net_sin(&addr)->sin_port = htons(port); - addrlen = sizeof(struct sockaddr_in); - - iface = net_if_ipv4_select_src_iface( - &net_sin(&addr)->sin_addr); - } else { - PR_WARNING("IPv6 and IPv4 are disabled, cannot %s.\n", "send"); - goto release_ctx; - } - - if (!iface) { - PR_WARNING("No interface to send to given host\n"); - goto release_ctx; - } - - net_context_set_iface(udp_ctx, iface); - - ret = net_context_recv(udp_ctx, udp_rcvd, K_NO_WAIT, NULL); - if (ret < 0) { - PR_WARNING("Setting rcv callback failed (%d)\n", ret); - goto release_ctx; - } - - ret = net_context_sendto(udp_ctx, payload, strlen(payload), &addr, - addrlen, udp_sent, K_FOREVER, NULL); - if (ret < 0) { - PR_WARNING("Sending packet failed (%d)\n", ret); - goto release_ctx; - } - - ret = k_sem_take(&udp_send_wait, K_SECONDS(2)); - if (ret == -EAGAIN) { - PR_WARNING("UDP packet sending failed\n"); - } - -release_ctx: - ret = net_context_put(udp_ctx); - if (ret < 0) { - PR_WARNING("Cannot put UDP context (%d)\n", ret); - } - - return 0; -#endif -} - -static int cmd_net_udp(const struct shell *sh, size_t argc, char *argv[]) -{ - ARG_UNUSED(sh); - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - return 0; -} - -#if defined(CONFIG_NET_L2_VIRTUAL) -static void virtual_iface_cb(struct net_if *iface, void *user_data) -{ - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - int *count = data->user_data; - char *name, buf[CONFIG_NET_L2_VIRTUAL_MAX_NAME_LEN]; - struct net_if *orig_iface; - - if (net_if_l2(iface) != &NET_L2_GET_NAME(VIRTUAL)) { - return; - } - - if (*count == 0) { - PR("Interface Attached-To Description\n"); - (*count)++; - } - - orig_iface = net_virtual_get_iface(iface); - - name = net_virtual_get_name(iface, buf, sizeof(buf)); - - PR("%d %c %s\n", - net_if_get_by_iface(iface), - orig_iface ? net_if_get_by_iface(orig_iface) + '0' : '-', - name); - - (*count)++; -} - -static void attached_iface_cb(struct net_if *iface, void *user_data) -{ - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - int *count = data->user_data; - char buf[CONFIG_NET_L2_VIRTUAL_MAX_NAME_LEN]; - const char *name; - struct virtual_interface_context *ctx, *tmp; - - if (sys_slist_is_empty(&iface->config.virtual_interfaces)) { - return; - } - - if (*count == 0) { - PR("Interface Below-of Description\n"); - (*count)++; - } - - PR("%d ", net_if_get_by_iface(iface)); - - SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&iface->config.virtual_interfaces, - ctx, tmp, node) { - if (ctx->virtual_iface == iface) { - continue; - } - - PR("%d ", net_if_get_by_iface(ctx->virtual_iface)); - } - - name = net_virtual_get_name(iface, buf, sizeof(buf)); - if (name == NULL) { - name = iface2str(iface, NULL); - } - - PR(" %s\n", name); - - (*count)++; -} -#endif /* CONFIG_NET_L2_VIRTUAL */ - -static int cmd_net_virtual(const struct shell *sh, size_t argc, - char *argv[]) -{ - ARG_UNUSED(argc); - ARG_UNUSED(argv); - -#if defined(CONFIG_NET_L2_VIRTUAL) - struct net_shell_user_data user_data; - int count = 0; - - user_data.sh = sh; - user_data.user_data = &count; - - net_if_foreach(virtual_iface_cb, &user_data); - - count = 0; - PR("\n"); - - net_if_foreach(attached_iface_cb, &user_data); -#else - PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_L2_VIRTUAL", - "virtual network interface"); -#endif - return 0; -} - -#if defined(CONFIG_NET_VLAN) -static void iface_vlan_del_cb(struct net_if *iface, void *user_data) -{ - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - uint16_t vlan_tag = POINTER_TO_UINT(data->user_data); - int ret; - - ret = net_eth_vlan_disable(iface, vlan_tag); - if (ret < 0) { - if (ret != -ESRCH) { - PR_WARNING("Cannot delete VLAN tag %d from " - "interface %d (%p)\n", - vlan_tag, - net_if_get_by_iface(iface), - iface); - } - - return; - } - - PR("VLAN tag %d removed from interface %d (%p)\n", vlan_tag, - net_if_get_by_iface(iface), iface); -} - -static void iface_vlan_cb(struct net_if *iface, void *user_data) -{ - struct ethernet_context *ctx = net_if_l2_data(iface); - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - int *count = data->user_data; - int i; - - if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) { - return; - } - - if (*count == 0) { - PR(" Interface Type Tag\n"); - } - - if (!ctx->vlan_enabled) { - PR_WARNING("VLAN tag(s) not set\n"); - return; - } - - for (i = 0; i < NET_VLAN_MAX_COUNT; i++) { - if (!ctx->vlan[i].iface || ctx->vlan[i].iface != iface) { - continue; - } - - if (ctx->vlan[i].tag == NET_VLAN_TAG_UNSPEC) { - continue; - } - - PR("[%d] %p %s %d\n", net_if_get_by_iface(iface), iface, - iface2str(iface, NULL), ctx->vlan[i].tag); - - break; - } - - (*count)++; -} -#endif /* CONFIG_NET_VLAN */ - -static int cmd_net_vlan(const struct shell *sh, size_t argc, char *argv[]) -{ -#if defined(CONFIG_NET_VLAN) - struct net_shell_user_data user_data; - int count; -#endif - -#if defined(CONFIG_NET_VLAN) - count = 0; - - user_data.sh = sh; - user_data.user_data = &count; - - net_if_foreach(iface_vlan_cb, &user_data); -#else - PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_VLAN", "VLAN"); -#endif /* CONFIG_NET_VLAN */ - - return 0; -} - -static int cmd_net_vlan_add(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if defined(CONFIG_NET_VLAN) - int arg = 0; - int ret; - uint16_t tag; - struct net_if *iface; - char *endptr; - uint32_t iface_idx; -#endif - -#if defined(CONFIG_NET_VLAN) - /* vlan add */ - if (!argv[++arg]) { - PR_WARNING("VLAN tag missing.\n"); - goto usage; - } - - tag = strtol(argv[arg], &endptr, 10); - if (*endptr != '\0') { - PR_WARNING("Invalid tag %s\n", argv[arg]); - return -ENOEXEC; - } - - if (!argv[++arg]) { - PR_WARNING("Network interface index missing.\n"); - goto usage; - } - - iface_idx = strtol(argv[arg], &endptr, 10); - if (*endptr != '\0') { - PR_WARNING("Invalid index %s\n", argv[arg]); - goto usage; - } - - iface = net_if_get_by_index(iface_idx); - if (!iface) { - PR_WARNING("Network interface index %d is invalid.\n", - iface_idx); - goto usage; - } - - if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) { - PR_WARNING("Network interface %d (%p) is not ethernet interface\n", - net_if_get_by_iface(iface), iface); - return -ENOEXEC; - } - - ret = net_eth_vlan_enable(iface, tag); - if (ret < 0) { - if (ret == -ENOENT) { - PR_WARNING("No IP address configured.\n"); - } - - PR_WARNING("Cannot set VLAN tag (%d)\n", ret); - - return -ENOEXEC; - } - - PR("VLAN tag %d set to interface %d (%p)\n", tag, - net_if_get_by_iface(iface), iface); - - return 0; - -usage: - PR("Usage:\n"); - PR("\tvlan add \n"); -#else - PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_VLAN", "VLAN"); -#endif /* CONFIG_NET_VLAN */ - - return 0; -} - -static int cmd_net_vlan_del(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if defined(CONFIG_NET_VLAN) - int arg = 0; - struct net_shell_user_data user_data; - char *endptr; - uint16_t tag; -#endif - -#if defined(CONFIG_NET_VLAN) - /* vlan del */ - if (!argv[++arg]) { - PR_WARNING("VLAN tag missing.\n"); - goto usage; - } - - tag = strtol(argv[arg], &endptr, 10); - if (*endptr != '\0') { - PR_WARNING("Invalid tag %s\n", argv[arg]); - return -ENOEXEC; - } - - user_data.sh = sh; - user_data.user_data = UINT_TO_POINTER((uint32_t)tag); - - net_if_foreach(iface_vlan_del_cb, &user_data); - - return 0; - -usage: - PR("Usage:\n"); - PR("\tvlan del \n"); -#else - PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_VLAN", "VLAN"); -#endif /* CONFIG_NET_VLAN */ - - return 0; -} - -static int cmd_net_suspend(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if defined(CONFIG_NET_POWER_MANAGEMENT) - if (argv[1]) { - struct net_if *iface = NULL; - const struct device *dev; - int idx; - int ret; - - idx = get_iface_idx(sh, argv[1]); - if (idx < 0) { - return -ENOEXEC; - } - - iface = net_if_get_by_index(idx); - if (!iface) { - PR_WARNING("No such interface in index %d\n", idx); - return -ENOEXEC; - } - - dev = net_if_get_device(iface); - - ret = pm_device_action_run(dev, PM_DEVICE_ACTION_SUSPEND); - if (ret != 0) { - PR_INFO("Iface could not be suspended: "); - - if (ret == -EBUSY) { - PR_INFO("device is busy\n"); - } else if (ret == -EALREADY) { - PR_INFO("dehive is already suspended\n"); - } - } - } else { - PR("Usage:\n"); - PR("\tsuspend \n"); - } -#else - PR_INFO("You need a network driver supporting Power Management.\n"); -#endif /* CONFIG_NET_POWER_MANAGEMENT */ - - return 0; -} - -static int cmd_net_resume(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if defined(CONFIG_NET_POWER_MANAGEMENT) - if (argv[1]) { - struct net_if *iface = NULL; - const struct device *dev; - int idx; - int ret; - - idx = get_iface_idx(sh, argv[1]); - if (idx < 0) { - return -ENOEXEC; - } - - iface = net_if_get_by_index(idx); - if (!iface) { - PR_WARNING("No such interface in index %d\n", idx); - return -ENOEXEC; - } - - dev = net_if_get_device(iface); - - ret = pm_device_action_run(dev, PM_DEVICE_ACTION_RESUME); - if (ret != 0) { - PR_INFO("Iface could not be resumed\n"); - } - - } else { - PR("Usage:\n"); - PR("\tresume \n"); - } -#else - PR_INFO("You need a network driver supporting Power Management.\n"); -#endif /* CONFIG_NET_POWER_MANAGEMENT */ - - return 0; -} - -#if defined(CONFIG_WEBSOCKET_CLIENT) -static void websocket_context_cb(struct websocket_context *context, - void *user_data) -{ -#if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4) -#define ADDR_LEN NET_IPV6_ADDR_LEN -#elif defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6) -#define ADDR_LEN NET_IPV4_ADDR_LEN -#else -#define ADDR_LEN NET_IPV6_ADDR_LEN -#endif - struct net_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - struct net_context *net_ctx; - int *count = data->user_data; - /* +7 for []:port */ - char addr_local[ADDR_LEN + 7]; - char addr_remote[ADDR_LEN + 7] = ""; - - net_ctx = z_get_fd_obj(context->real_sock, NULL, 0); - if (net_ctx == NULL) { - PR_ERROR("Invalid fd %d", context->real_sock); - return; - } - - get_addresses(net_ctx, addr_local, sizeof(addr_local), - addr_remote, sizeof(addr_remote)); - - PR("[%2d] %p/%p\t%p %16s\t%16s\n", - (*count) + 1, context, net_ctx, - net_context_get_iface(net_ctx), - addr_local, addr_remote); - - (*count)++; -} -#endif /* CONFIG_WEBSOCKET_CLIENT */ - -static int cmd_net_websocket(const struct shell *sh, size_t argc, - char *argv[]) -{ -#if defined(CONFIG_WEBSOCKET_CLIENT) - struct net_shell_user_data user_data; - int count = 0; - - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - PR(" websocket/net_ctx\tIface " - "Local \tRemote\n"); - - user_data.sh = sh; - user_data.user_data = &count; - - websocket_context_foreach(websocket_context_cb, &user_data); - - if (count == 0) { - PR("No connections\n"); - } -#else - PR_INFO("Set %s to enable %s support.\n", "CONFIG_WEBSOCKET_CLIENT", - "Websocket"); -#endif /* CONFIG_WEBSOCKET_CLIENT */ - - return 0; -} - -SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_arp, - SHELL_CMD(flush, NULL, "Remove all entries from ARP cache.", - cmd_net_arp_flush), - SHELL_SUBCMD_SET_END -); - -SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_capture, - SHELL_CMD(setup, NULL, "Setup network packet capture.\n" - "'net capture setup '\n" - " is the (outer) endpoint IP address,\n" - " is the (inner) local IP address,\n" - " is the (inner) peer IP address\n" - "Local and Peer addresses can have UDP port number in them (optional)\n" - "like 198.0.51.2:9000 or [2001:db8:100::2]:4242", - cmd_net_capture_setup), - SHELL_CMD(cleanup, NULL, "Cleanup network packet capture.", - cmd_net_capture_cleanup), - SHELL_CMD(enable, NULL, "Enable network packet capture for a given " - "network interface.\n" - "'net capture enable '", - cmd_net_capture_enable), - SHELL_CMD(disable, NULL, "Disable network packet capture.", - cmd_net_capture_disable), - SHELL_SUBCMD_SET_END -); - -SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_dns, - SHELL_CMD(cancel, NULL, "Cancel all pending requests.", - cmd_net_dns_cancel), - SHELL_CMD(query, NULL, - "'net dns [A or AAAA]' queries IPv4 address " - "(default) or IPv6 address for a host name.", - cmd_net_dns_query), - SHELL_SUBCMD_SET_END -); - -SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_events, - SHELL_CMD(on, NULL, "Turn on network event monitoring.", - cmd_net_events_on), - SHELL_CMD(off, NULL, "Turn off network event monitoring.", - cmd_net_events_off), - SHELL_SUBCMD_SET_END -); - -SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_gptp, - SHELL_CMD(port, NULL, - "'net gptp []' prints detailed information about " - "gPTP port.", - cmd_net_gptp_port), - SHELL_SUBCMD_SET_END -); - -#if !defined(NET_VLAN_MAX_COUNT) -#define MAX_IFACE_COUNT NET_IF_MAX_CONFIGS -#else -#define MAX_IFACE_COUNT NET_VLAN_MAX_COUNT -#endif - -#if defined(CONFIG_NET_SHELL_DYN_CMD_COMPLETION) - -#define MAX_IFACE_HELP_STR_LEN sizeof("longbearername (0xabcd0123)") -#define MAX_IFACE_STR_LEN sizeof("xxx") - -static char iface_help_buffer[MAX_IFACE_COUNT][MAX_IFACE_HELP_STR_LEN]; -static char iface_index_buffer[MAX_IFACE_COUNT][MAX_IFACE_STR_LEN]; - -static char *set_iface_index_buffer(size_t idx) -{ - struct net_if *iface = net_if_get_by_index(idx); - - if (!iface) { - return NULL; - } - - snprintk(iface_index_buffer[idx], MAX_IFACE_STR_LEN, "%zu", idx); - - return iface_index_buffer[idx]; -} - -static char *set_iface_index_help(size_t idx) -{ - struct net_if *iface = net_if_get_by_index(idx); - - if (!iface) { - return NULL; - } - - snprintk(iface_help_buffer[idx], MAX_IFACE_HELP_STR_LEN, - "%s (%p)", iface2str(iface, NULL), iface); - - return iface_help_buffer[idx]; -} - -static void iface_index_get(size_t idx, struct shell_static_entry *entry); - -SHELL_DYNAMIC_CMD_CREATE(iface_index, iface_index_get); - -static void iface_index_get(size_t idx, struct shell_static_entry *entry) -{ - entry->handler = NULL; - entry->help = set_iface_index_help(idx); - entry->subcmd = &iface_index; - entry->syntax = set_iface_index_buffer(idx); -} - -#define IFACE_DYN_CMD &iface_index - -#if defined(CONFIG_NET_PPP) -static char *set_iface_ppp_index_buffer(size_t idx) -{ - struct net_if *iface = net_if_get_by_index(idx); - - if (!iface) { - return NULL; - } - - if (net_if_l2(iface) != &NET_L2_GET_NAME(PPP)) { - return NULL; - } - - snprintk(iface_index_buffer[idx], MAX_IFACE_STR_LEN, "%zu", idx); - - return iface_index_buffer[idx]; -} - -static char *set_iface_ppp_index_help(size_t idx) -{ - struct net_if *iface = net_if_get_by_index(idx); - - if (!iface) { - return NULL; - } - - if (net_if_l2(iface) != &NET_L2_GET_NAME(PPP)) { - return NULL; - } - - snprintk(iface_help_buffer[idx], MAX_IFACE_HELP_STR_LEN, - "%s (%p)", iface2str(iface, NULL), iface); - - return iface_help_buffer[idx]; -} - -static void iface_ppp_index_get(size_t idx, struct shell_static_entry *entry); - -SHELL_DYNAMIC_CMD_CREATE(iface_ppp_index, iface_ppp_index_get); - -static void iface_ppp_index_get(size_t idx, struct shell_static_entry *entry) -{ - entry->handler = NULL; - entry->help = set_iface_ppp_index_help(idx); - entry->subcmd = &iface_ppp_index; - entry->syntax = set_iface_ppp_index_buffer(idx); -} - -#define IFACE_PPP_DYN_CMD &iface_ppp_index -#else -#define IFACE_PPP_DYN_CMD NULL -#endif /* CONFIG_NET_PPP */ - -#else -#define IFACE_DYN_CMD NULL -#define IFACE_PPP_DYN_CMD NULL -#endif /* CONFIG_NET_SHELL_DYN_CMD_COMPLETION */ - -SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_iface, - SHELL_CMD(up, IFACE_DYN_CMD, - "'net iface up ' takes network interface up.", - cmd_net_iface_up), - SHELL_CMD(down, IFACE_DYN_CMD, - "'net iface down ' takes network interface " - "down.", - cmd_net_iface_down), - SHELL_CMD(show, IFACE_DYN_CMD, - "'net iface ' shows network interface " - "information.", - cmd_net_iface), - SHELL_CMD(set_mac, IFACE_DYN_CMD, - "'net iface set_mac ' sets MAC address for the network interface.", - cmd_net_set_mac), - SHELL_SUBCMD_SET_END -); - -SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_ip, - SHELL_CMD(add, NULL, - "'net ipv4 add
    ' adds the address to the interface.", - cmd_net_ip_add), - SHELL_CMD(del, NULL, - "'net ipv4 del
    ' deletes the address from the interface.", - cmd_net_ip_del), - SHELL_SUBCMD_SET_END -); - -SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_ip6, - SHELL_CMD(add, NULL, - "'net ipv6 add
    ' adds the address to the interface.", - cmd_net_ip6_add), - SHELL_CMD(del, NULL, - "'net ipv6 del
    ' deletes the address from the interface.", - cmd_net_ip6_del), - SHELL_SUBCMD_SET_END -); - -SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_route, - SHELL_CMD(add, NULL, - "'net route add '" - " adds the route to the destination.", - cmd_net_ip6_route_add), - SHELL_CMD(del, NULL, - "'net route del '" - " deletes the route to the destination.", - cmd_net_ip6_route_del), - SHELL_SUBCMD_SET_END -); - -SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_ppp, - SHELL_CMD(ping, IFACE_PPP_DYN_CMD, - "'net ppp ping ' sends Echo-request to PPP interface.", - cmd_net_ppp_ping), - SHELL_CMD(status, NULL, - "'net ppp status' prints information about PPP.", - cmd_net_ppp_status), - SHELL_SUBCMD_SET_END -); - -#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_SHELL_DYN_CMD_COMPLETION) -static -char nbr_address_buffer[CONFIG_NET_IPV6_MAX_NEIGHBORS][NET_IPV6_ADDR_LEN]; - -static void nbr_address_cb(struct net_nbr *nbr, void *user_data) -{ - int *count = user_data; - - if (*count >= CONFIG_NET_IPV6_MAX_NEIGHBORS) { - return; - } - - snprintk(nbr_address_buffer[*count], NET_IPV6_ADDR_LEN, - "%s", net_sprint_ipv6_addr(&net_ipv6_nbr_data(nbr)->addr)); - - (*count)++; -} - -static void nbr_populate_addresses(void) -{ - int count = 0; - - net_ipv6_nbr_foreach(nbr_address_cb, &count); -} - -static char *set_nbr_address(size_t idx) -{ - if (idx == 0) { - memset(nbr_address_buffer, 0, sizeof(nbr_address_buffer)); - nbr_populate_addresses(); - } - - if (idx >= CONFIG_NET_IPV6_MAX_NEIGHBORS) { - return NULL; - } - - if (!nbr_address_buffer[idx][0]) { - return NULL; - } - - return nbr_address_buffer[idx]; -} - -static void nbr_address_get(size_t idx, struct shell_static_entry *entry); - -SHELL_DYNAMIC_CMD_CREATE(nbr_address, nbr_address_get); - -#define NBR_ADDRESS_CMD &nbr_address - -static void nbr_address_get(size_t idx, struct shell_static_entry *entry) -{ - entry->handler = NULL; - entry->help = NULL; - entry->subcmd = &nbr_address; - entry->syntax = set_nbr_address(idx); -} - -#else -#define NBR_ADDRESS_CMD NULL -#endif /* CONFIG_NET_IPV6 && CONFIG_NET_SHELL_DYN_CMD_COMPLETION */ - -SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_nbr, - SHELL_CMD(rm, NBR_ADDRESS_CMD, - "'net nbr rm
    ' removes neighbor from cache.", - cmd_net_nbr_rm), - SHELL_SUBCMD_SET_END -); - -#if defined(CONFIG_NET_STATISTICS) && \ - defined(CONFIG_NET_STATISTICS_PER_INTERFACE) && \ - defined(CONFIG_NET_SHELL_DYN_CMD_COMPLETION) -#define STATS_IFACE_CMD &iface_index -#else -#define STATS_IFACE_CMD NULL -#endif /* CONFIG_NET_STATISTICS && CONFIG_NET_STATISTICS_PER_INTERFACE && - * CONFIG_NET_SHELL_DYN_CMD_COMPLETION - */ - -SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_stats, - SHELL_CMD(all, NULL, - "Show network statistics for all network interfaces.", - cmd_net_stats_all), - SHELL_CMD(iface, STATS_IFACE_CMD, - "'net stats ' shows network statistics for " - "one specific network interface.", - cmd_net_stats_iface), - SHELL_SUBCMD_SET_END -); - -SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_tcp, - SHELL_CMD(connect, NULL, - "'net tcp connect
    ' connects to TCP peer.", - cmd_net_tcp_connect), - SHELL_CMD(send, NULL, - "'net tcp send ' sends data to peer using TCP.", - cmd_net_tcp_send), - SHELL_CMD(recv, NULL, - "'net tcp recv' receives data using TCP.", - cmd_net_tcp_recv), - SHELL_CMD(close, NULL, - "'net tcp close' closes TCP connection.", cmd_net_tcp_close), - SHELL_SUBCMD_SET_END -); - -SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_vlan, - SHELL_CMD(add, NULL, - "'net vlan add ' adds VLAN tag to the " - "network interface.", - cmd_net_vlan_add), - SHELL_CMD(del, NULL, - "'net vlan del ' deletes VLAN tag from the network " - "interface.", - cmd_net_vlan_del), - SHELL_SUBCMD_SET_END -); - -SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_ping, - SHELL_CMD(--help, NULL, - "'net ping [-c count] [-i interval ms] [-I ] " - "[-Q tos] [-s payload size] [-p priority] ' " - "Send ICMPv4 or ICMPv6 Echo-Request to a network host.", - cmd_net_ping), - SHELL_SUBCMD_SET_END -); - -SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_pkt, - SHELL_CMD(--help, NULL, - "'net pkt [ptr in hex]' " - "Print information about given net_pkt", - cmd_net_pkt), - SHELL_SUBCMD_SET_END -); - -SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_udp, - SHELL_CMD(bind, NULL, - "'net udp bind ' binds to UDP local port.", - cmd_net_udp_bind), - SHELL_CMD(close, NULL, - "'net udp close' closes previously bound port.", - cmd_net_udp_close), - SHELL_CMD(send, NULL, - "'net udp send ' " - "sends UDP packet to a network host.", - cmd_net_udp_send), - SHELL_SUBCMD_SET_END -); - -SHELL_STATIC_SUBCMD_SET_CREATE(net_commands, - SHELL_CMD(allocs, NULL, "Print network memory allocations.", - cmd_net_allocs), - SHELL_CMD(arp, &net_cmd_arp, "Print information about IPv4 ARP cache.", - cmd_net_arp), - SHELL_CMD(capture, &net_cmd_capture, - "Configure network packet capture.", cmd_net_capture), - SHELL_CMD(conn, NULL, "Print information about network connections.", - cmd_net_conn), - SHELL_CMD(dns, &net_cmd_dns, "Show how DNS is configured.", - cmd_net_dns), - SHELL_CMD(events, &net_cmd_events, "Monitor network management events.", - cmd_net_events), - SHELL_CMD(gptp, &net_cmd_gptp, "Print information about gPTP support.", - cmd_net_gptp), - SHELL_CMD(iface, &net_cmd_iface, - "Print information about network interfaces.", - cmd_net_iface), - SHELL_CMD(ipv6, &net_cmd_ip6, - "Print information about IPv6 specific information and " - "configuration.", - cmd_net_ipv6), - SHELL_CMD(ipv4, &net_cmd_ip, - "Print information about IPv4 specific information and " - "configuration.", - cmd_net_ipv4), - SHELL_CMD(mem, NULL, "Print information about network memory usage.", - cmd_net_mem), - SHELL_CMD(nbr, &net_cmd_nbr, "Print neighbor information.", - cmd_net_nbr), - SHELL_CMD(ping, &net_cmd_ping, "Ping a network host.", cmd_net_ping), - SHELL_CMD(pkt, &net_cmd_pkt, "net_pkt information.", cmd_net_pkt), - SHELL_CMD(ppp, &net_cmd_ppp, "PPP information.", cmd_net_ppp_status), - SHELL_CMD(resume, NULL, "Resume a network interface", cmd_net_resume), - SHELL_CMD(route, &net_cmd_route, "Show network route.", cmd_net_route), - SHELL_CMD(stacks, NULL, "Show network stacks information.", - cmd_net_stacks), - SHELL_CMD(stats, &net_cmd_stats, "Show network statistics.", - cmd_net_stats), - SHELL_CMD(suspend, NULL, "Suspend a network interface", - cmd_net_suspend), - SHELL_CMD(tcp, &net_cmd_tcp, "Connect/send/close TCP connection.", - cmd_net_tcp), - SHELL_CMD(udp, &net_cmd_udp, "Send/recv UDP packet", cmd_net_udp), - SHELL_CMD(virtual, NULL, "Show virtual network interfaces.", - cmd_net_virtual), - SHELL_CMD(vlan, &net_cmd_vlan, "Show VLAN information.", cmd_net_vlan), - SHELL_CMD(websocket, NULL, "Print information about WebSocket " - "connections.", - cmd_net_websocket), - SHELL_SUBCMD_SET_END -); - -SHELL_CMD_REGISTER(net, &net_commands, "Networking commands", NULL); - -int net_shell_init(void) -{ -#if defined(CONFIG_NET_MGMT_EVENT_MONITOR_AUTO_START) - char *argv[] = { - "on", - NULL - }; - - (void)cmd_net_events_on(shell_backend_uart_get_ptr(), 1, argv); -#endif - - return 0; -} diff --git a/subsys/net/ip/net_tc.c b/subsys/net/ip/net_tc.c index b9e21ba79e4..d789232b582 100644 --- a/subsys/net/ip/net_tc.c +++ b/subsys/net/ip/net_tc.c @@ -237,8 +237,12 @@ static void net_tc_rx_stats_priority_setup(struct net_if *iface, #endif #if NET_TC_RX_COUNT > 0 -static void tc_rx_handler(struct k_fifo *fifo) +static void tc_rx_handler(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct k_fifo *fifo = p1; struct net_pkt *pkt; while (1) { @@ -253,8 +257,12 @@ static void tc_rx_handler(struct k_fifo *fifo) #endif #if NET_TC_TX_COUNT > 0 -static void tc_tx_handler(struct k_fifo *fifo) +static void tc_tx_handler(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct k_fifo *fifo = p1; struct net_pkt *pkt; while (1) { @@ -309,7 +317,7 @@ void net_tc_tx_init(void) tid = k_thread_create(&tx_classes[i].handler, tx_stack[i], K_KERNEL_STACK_SIZEOF(tx_stack[i]), - (k_thread_entry_t)tc_tx_handler, + tc_tx_handler, &tx_classes[i].fifo, NULL, NULL, priority, 0, K_FOREVER); if (!tid) { @@ -367,7 +375,7 @@ void net_tc_rx_init(void) tid = k_thread_create(&rx_classes[i].handler, rx_stack[i], K_KERNEL_STACK_SIZEOF(rx_stack[i]), - (k_thread_entry_t)tc_rx_handler, + tc_rx_handler, &rx_classes[i].fifo, NULL, NULL, priority, 0, K_FOREVER); if (!tid) { diff --git a/subsys/net/ip/tcp.c b/subsys/net/ip/tcp.c index 680fdcecb85..6ffd688a20f 100644 --- a/subsys/net/ip/tcp.c +++ b/subsys/net/ip/tcp.c @@ -11,7 +11,7 @@ LOG_MODULE_REGISTER(net_tcp, CONFIG_NET_TCP_LOG_LEVEL); #include #include #include -#include +#include #if defined(CONFIG_NET_TCP_ISN_RFC6528) #include @@ -569,7 +569,20 @@ static int tcp_conn_unref(struct tcp *conn) tcp_send_queue_flush(conn); - k_work_cancel_delayable(&conn->send_data_timer); + /* Cancel all possible delayed work and prevent any execution of newly scheduled work + * in one of the work item handlers + * Essential because the work items are destructed at the bottom of this method. + * A current ongoing execution might access the connection and schedule new work + * Solution: + * While holding the lock, cancel all delayable work. + * Because every delayable work execution takes the same lock and releases the lock, + * we're either here, or currently executing one of the workers. + * Then, after cancelling the workers within the lock, either those workers have finished + * or have been cancelled and will not execute anymore + */ + k_mutex_lock(&conn->lock, K_FOREVER); + + (void)k_work_cancel_delayable(&conn->send_data_timer); tcp_pkt_unref(conn->send_data); if (CONFIG_NET_TCP_RECV_QUEUE_TIMEOUT) { @@ -580,6 +593,10 @@ static int tcp_conn_unref(struct tcp *conn) (void)k_work_cancel_delayable(&conn->fin_timer); (void)k_work_cancel_delayable(&conn->persist_timer); (void)k_work_cancel_delayable(&conn->ack_timer); + (void)k_work_cancel_delayable(&conn->send_timer); + (void)k_work_cancel_delayable(&conn->recv_queue_timer); + + k_mutex_unlock(&conn->lock); sys_slist_find_and_remove(&tcp_conns, &conn->next); @@ -697,10 +714,12 @@ static void tcp_send_process(struct k_work *work) struct tcp *conn = CONTAINER_OF(dwork, struct tcp, send_timer); bool unref; + /* take the lock to prevent a race-condition with tcp_conn_unref */ k_mutex_lock(&conn->lock, K_FOREVER); unref = tcp_send_process_no_lock(conn); + /* release the lock only after possible scheduling of work */ k_mutex_unlock(&conn->lock); if (unref) { @@ -1145,6 +1164,82 @@ static bool is_destination_local(struct net_pkt *pkt) return false; } +void net_tcp_reply_rst(struct net_pkt *pkt) +{ + NET_PKT_DATA_ACCESS_DEFINE(tcp_access_rst, struct tcphdr); + struct tcphdr *th_pkt = th_get(pkt); + struct tcphdr *th_rst; + struct net_pkt *rst; + int ret; + + if (th_pkt == NULL || (th_flags(th_pkt) & RST)) { + /* Don't reply to a RST segment. */ + return; + } + + rst = tcp_pkt_alloc_no_conn(pkt->iface, pkt->family, + sizeof(struct tcphdr)); + if (rst == NULL) { + return; + } + + /* IP header */ + if (IS_ENABLED(CONFIG_NET_IPV4) && net_pkt_family(pkt) == AF_INET) { + ret = net_ipv4_create(rst, + (struct in_addr *)NET_IPV4_HDR(pkt)->dst, + (struct in_addr *)NET_IPV4_HDR(pkt)->src); + } else if (IS_ENABLED(CONFIG_NET_IPV6) && net_pkt_family(pkt) == AF_INET6) { + ret = net_ipv6_create(rst, + (struct in6_addr *)NET_IPV6_HDR(pkt)->dst, + (struct in6_addr *)NET_IPV6_HDR(pkt)->src); + } else { + ret = -EINVAL; + } + + if (ret < 0) { + goto err; + } + + /* TCP header */ + th_rst = (struct tcphdr *)net_pkt_get_data(rst, &tcp_access_rst); + if (th_rst == NULL) { + goto err; + } + + memset(th_rst, 0, sizeof(struct tcphdr)); + + UNALIGNED_PUT(th_pkt->th_dport, &th_rst->th_sport); + UNALIGNED_PUT(th_pkt->th_sport, &th_rst->th_dport); + th_rst->th_off = 5; + + if (th_flags(th_pkt) & ACK) { + UNALIGNED_PUT(RST, &th_rst->th_flags); + UNALIGNED_PUT(th_pkt->th_ack, &th_rst->th_seq); + } else { + uint32_t ack = ntohl(th_pkt->th_seq) + tcp_data_len(pkt); + + UNALIGNED_PUT(RST | ACK, &th_rst->th_flags); + UNALIGNED_PUT(htonl(ack), &th_rst->th_ack); + } + + ret = net_pkt_set_data(rst, &tcp_access_rst); + if (ret < 0) { + goto err; + } + + ret = tcp_finalize_pkt(rst); + if (ret < 0) { + goto err; + } + + tcp_send(rst); + + return; + +err: + tcp_pkt_unref(rst); +} + static int tcp_out_ext(struct tcp *conn, uint8_t flags, struct net_pkt *data, uint32_t seq) { @@ -1300,9 +1395,10 @@ static int tcp_pkt_append(struct net_pkt *pkt, const uint8_t *data, size_t len) static bool tcp_window_full(struct tcp *conn) { bool window_full = (conn->send_data_total >= conn->send_win); - if (IS_ENABLED(CONFIG_NET_TCP_CONGESTION_AVOIDANCE)) { - window_full = window_full || (conn->send_data_total >= conn->ca.cwnd); - } + +#ifdef CONFIG_NET_TCP_CONGESTION_AVOIDANCE + window_full = window_full || (conn->send_data_total >= conn->ca.cwnd); +#endif NET_DBG("conn: %p window_full=%hu", conn, window_full); @@ -1325,13 +1421,14 @@ static int tcp_unsent_len(struct tcp *conn) unsent_len = 0; } else { unsent_len = MIN(unsent_len, conn->send_win - conn->unacked_len); - if (IS_ENABLED(CONFIG_NET_TCP_CONGESTION_AVOIDANCE)) { - if (conn->unacked_len >= conn->ca.cwnd) { - unsent_len = 0; - } else { - unsent_len = MIN(unsent_len, conn->ca.cwnd - conn->unacked_len); - } + +#ifdef CONFIG_NET_TCP_CONGESTION_AVOIDANCE + if (conn->unacked_len >= conn->ca.cwnd) { + unsent_len = 0; + } else { + unsent_len = MIN(unsent_len, conn->ca.cwnd - conn->unacked_len); } +#endif } out: NET_DBG("unsent_len=%d", unsent_len); @@ -1448,6 +1545,7 @@ static void tcp_cleanup_recv_queue(struct k_work *work) struct k_work_delayable *dwork = k_work_delayable_from_work(work); struct tcp *conn = CONTAINER_OF(dwork, struct tcp, recv_queue_timer); + /* take the lock to prevent a race-condition with tcp_conn_unref */ k_mutex_lock(&conn->lock, K_FOREVER); NET_DBG("Cleanup recv queue conn %p len %zd seq %u", conn, @@ -1457,6 +1555,7 @@ static void tcp_cleanup_recv_queue(struct k_work *work) net_buf_unref(conn->queue_recv_data->buffer); conn->queue_recv_data->buffer = NULL; + /* release the lock only after possible scheduling of work */ k_mutex_unlock(&conn->lock); } @@ -1468,6 +1567,7 @@ static void tcp_resend_data(struct k_work *work) int ret; int exp_tcp_rto; + /* take the lock to prevent a race-condition with tcp_conn_unref */ k_mutex_lock(&conn->lock, K_FOREVER); NET_DBG("send_data_retries=%hu", conn->send_data_retries); @@ -1531,6 +1631,7 @@ static void tcp_resend_data(struct k_work *work) K_MSEC(exp_tcp_rto)); out: + /* release the lock only after possible scheduling of work */ k_mutex_unlock(&conn->lock); if (conn_unref) { @@ -1543,6 +1644,7 @@ static void tcp_timewait_timeout(struct k_work *work) struct k_work_delayable *dwork = k_work_delayable_from_work(work); struct tcp *conn = CONTAINER_OF(dwork, struct tcp, timewait_timer); + /* no need to acquire the conn->lock as there is nothing scheduled here */ NET_DBG("conn: %p %s", conn, tcp_conn_state(conn, NULL)); (void)tcp_conn_close(conn, -ETIMEDOUT); @@ -1561,6 +1663,7 @@ static void tcp_fin_timeout(struct k_work *work) struct k_work_delayable *dwork = k_work_delayable_from_work(work); struct tcp *conn = CONTAINER_OF(dwork, struct tcp, fin_timer); + /* no need to acquire the conn->lock as there is nothing scheduled here */ if (conn->state == TCP_SYN_RECEIVED) { tcp_establish_timeout(conn); return; @@ -1577,6 +1680,7 @@ static void tcp_send_zwp(struct k_work *work) struct k_work_delayable *dwork = k_work_delayable_from_work(work); struct tcp *conn = CONTAINER_OF(dwork, struct tcp, persist_timer); + /* take the lock to prevent a race-condition with tcp_conn_unref */ k_mutex_lock(&conn->lock, K_FOREVER); (void)tcp_out_ext(conn, ACK, NULL, conn->seq - 1); @@ -1600,6 +1704,7 @@ static void tcp_send_zwp(struct k_work *work) &tcp_work_q, &conn->persist_timer, K_MSEC(timeout)); } + /* release the lock only after possible scheduling of work */ k_mutex_unlock(&conn->lock); } @@ -1608,10 +1713,12 @@ static void tcp_send_ack(struct k_work *work) struct k_work_delayable *dwork = k_work_delayable_from_work(work); struct tcp *conn = CONTAINER_OF(dwork, struct tcp, ack_timer); + /* take the lock to prevent a race-condition with tcp_conn_unref */ k_mutex_lock(&conn->lock, K_FOREVER); tcp_out(conn, ACK); + /* release the lock only after possible scheduling of work */ k_mutex_unlock(&conn->lock); } @@ -1792,13 +1899,13 @@ static enum net_verdict tcp_recv(struct net_conn *net_conn, goto in; } - net_ipaddr_copy(&conn_old->context->remote, &conn->dst.sa); - conn->accepted_conn = conn_old; } in: if (conn) { verdict = tcp_in(conn, pkt); + } else { + net_tcp_reply_rst(pkt); } return verdict; @@ -1968,6 +2075,26 @@ static struct tcp *tcp_conn_new(struct net_pkt *pkt) goto err; } + /* The newly created context object for the new TCP client connection needs + * all four parameters of the tuple (local address, local port, remote + * address, remote port) to be properly identified. Remote address and port + * are already copied above from conn->dst. The call to net_context_bind + * with the prepared local_addr further copies the local address. However, + * this call wont copy the local port, as the bind would then fail due to + * an address/port reuse without the REUSEPORT option enables for both + * connections. Therefore, we copy the port after the bind call. + * It is safe to bind to this address/port combination, as the new TCP + * client connection is separated from the local listening connection + * by the specified remote address and remote port. + */ + if (IS_ENABLED(CONFIG_NET_IPV6) && + net_context_get_family(context) == AF_INET6) { + net_sin6_ptr(&context->local)->sin6_port = conn->src.sin6.sin6_port; + } else if (IS_ENABLED(CONFIG_NET_IPV4) && + net_context_get_family(context) == AF_INET) { + net_sin_ptr(&context->local)->sin_port = conn->src.sin.sin_port; + } + if (!(IS_ENABLED(CONFIG_NET_TEST_PROTOCOL) || IS_ENABLED(CONFIG_NET_TEST))) { conn->seq = tcp_init_isn(&local_addr, &context->remote); @@ -2337,6 +2464,18 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt) net_stats_update_tcp_seg_rst(net_pkt_iface(pkt)); do_close = true; close_status = -ECONNRESET; + + /* If we receive RST and ACK for the sent SYN, it means + * that there is no socket listening the port we are trying + * to connect to. Set the errno properly in this case. + */ + if (conn->in_connect) { + fl = th_flags(th); + if (FL(&fl, ==, RST | ACK)) { + close_status = -ECONNREFUSED; + } + } + goto out; } @@ -2417,6 +2556,7 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt) conn->send_options.mss_found = false; conn_seq(conn, + 1); next = TCP_SYN_SENT; + tcp_conn_ref(conn); } break; case TCP_SYN_RECEIVED: @@ -2450,8 +2590,40 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt) break; } - accept_cb(conn->context, &context->remote, - sizeof(struct sockaddr), 0, context); + net_ipaddr_copy(&conn->context->remote, &conn->dst.sa); + + /* Check if v4-mapping-to-v6 needs to be done for + * the accepted socket. + */ + if (IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6) && + net_context_get_family(conn->context) == AF_INET && + net_context_get_family(context) == AF_INET6 && + !net_context_is_v6only_set(context)) { + struct in6_addr mapped; + + net_ipv6_addr_create_v4_mapped( + &net_sin(&conn->context->remote)->sin_addr, + &mapped); + net_ipaddr_copy(&net_sin6(&conn->context->remote)->sin6_addr, + &mapped); + + net_sin6(&conn->context->remote)->sin6_family = AF_INET6; + + NET_DBG("Setting v4 mapped address %s", + net_sprint_ipv6_addr(&mapped)); + + /* Note that we cannot set the local address to IPv6 one + * as that is used to match the connection, and not just + * for printing. The remote address is only used for + * passing it to accept() and printing it by "net conn" + * command. + */ + } + + accept_cb(conn->context, &conn->context->remote, + net_context_get_family(context) == AF_INET6 ? + sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in), + 0, context); next = TCP_ESTABLISHED; @@ -2492,7 +2664,6 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt) } next = TCP_ESTABLISHED; - tcp_conn_ref(conn); net_context_set_state(conn->context, NET_CONTEXT_CONNECTED); tcp_ca_init(conn); @@ -2505,7 +2676,10 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt) * priority. */ connection_ok = true; + } else if (pkt) { + net_tcp_reply_rst(pkt); } + break; case TCP_ESTABLISHED: /* full-close */ @@ -3450,7 +3624,7 @@ int net_tcp_recv(struct net_context *context, net_context_recv_cb_t cb, return 0; } -int net_tcp_finalize(struct net_pkt *pkt) +int net_tcp_finalize(struct net_pkt *pkt, bool force_chksum) { NET_PKT_DATA_ACCESS_DEFINE(tcp_access, struct net_tcp_hdr); struct net_tcp_hdr *tcp_hdr; @@ -3462,8 +3636,9 @@ int net_tcp_finalize(struct net_pkt *pkt) tcp_hdr->chksum = 0U; - if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt))) { + if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt)) || force_chksum) { tcp_hdr->chksum = net_calc_chksum_tcp(pkt); + net_pkt_set_chksum_done(pkt, true); } return net_pkt_set_data(pkt, &tcp_access); @@ -3475,7 +3650,8 @@ struct net_tcp_hdr *net_tcp_input(struct net_pkt *pkt, struct net_tcp_hdr *tcp_hdr; if (IS_ENABLED(CONFIG_NET_TCP_CHECKSUM) && - net_if_need_calc_rx_checksum(net_pkt_iface(pkt)) && + (net_if_need_calc_rx_checksum(net_pkt_iface(pkt)) || + net_pkt_is_ip_reassembled(pkt)) && net_calc_chksum_tcp(pkt) != 0U) { NET_DBG("DROP: checksum mismatch"); goto drop; diff --git a/subsys/net/ip/tcp.h b/subsys/net/ip/tcp.h index 162407710eb..975f2a97624 100644 --- a/subsys/net/ip/tcp.h +++ b/subsys/net/ip/tcp.h @@ -102,7 +102,7 @@ void net_tcp_init(void); #define net_tcp_init(...) #endif int net_tcp_update_recv_wnd(struct net_context *context, int32_t delta); -int net_tcp_finalize(struct net_pkt *pkt); +int net_tcp_finalize(struct net_pkt *pkt, bool force_chksum); #if defined(CONFIG_NET_TEST_PROTOCOL) /** diff --git a/subsys/net/ip/tcp_internal.h b/subsys/net/ip/tcp_internal.h index 17d4581aa3d..1dd3f235532 100644 --- a/subsys/net/ip/tcp_internal.h +++ b/subsys/net/ip/tcp_internal.h @@ -14,7 +14,7 @@ #define __TCP_INTERNAL_H #include -#include +#include #include #include @@ -249,11 +249,12 @@ static inline int net_tcp_recv(struct net_context *context, * @return 0 on success, negative errno otherwise. */ #if defined(CONFIG_NET_NATIVE_TCP) -int net_tcp_finalize(struct net_pkt *pkt); +int net_tcp_finalize(struct net_pkt *pkt, bool force_chksum); #else -static inline int net_tcp_finalize(struct net_pkt *pkt) +static inline int net_tcp_finalize(struct net_pkt *pkt, bool force_chksum) { ARG_UNUSED(pkt); + ARG_UNUSED(force_chksum); return 0; } #endif @@ -429,6 +430,20 @@ struct k_sem *net_tcp_tx_sem_get(struct net_context *context); */ struct k_sem *net_tcp_conn_sem_get(struct net_context *context); +/** + * @brief Send a TCP RST reply for the received packet w/o associated connection. + * + * @param pkt TCP packet to reply for. + */ +#if defined(CONFIG_NET_NATIVE_TCP) +void net_tcp_reply_rst(struct net_pkt *pkt); +#else +static inline void net_tcp_reply_rst(struct net_pkt *pkt) +{ + ARG_UNUSED(pkt); +} +#endif + #ifdef __cplusplus } #endif diff --git a/subsys/net/ip/tcp_private.h b/subsys/net/ip/tcp_private.h index 5d633f8b6a9..7dddf75c7b7 100644 --- a/subsys/net/ip/tcp_private.h +++ b/subsys/net/ip/tcp_private.h @@ -98,6 +98,23 @@ _pkt; \ }) +#define tcp_pkt_alloc_no_conn(_iface, _family, _len) \ +({ \ + struct net_pkt *_pkt; \ + \ + if ((_len) > 0) { \ + _pkt = net_pkt_alloc_with_buffer( \ + (_iface), (_len), (_family), \ + IPPROTO_TCP, \ + TCP_PKT_ALLOC_TIMEOUT); \ + } else { \ + _pkt = net_pkt_alloc(TCP_PKT_ALLOC_TIMEOUT); \ + } \ + \ + tp_pkt_alloc(_pkt, tp_basename(__FILE__), __LINE__); \ + \ + _pkt; \ +}) #if defined(CONFIG_NET_TEST_PROTOCOL) #define conn_seq(_conn, _req) \ @@ -311,6 +328,6 @@ struct tcp { /* TCP connection */ }) #define FL(_fl, _op, _mask, _args...) \ - _flags(_fl, _op, _mask, strlen("" #_args) ? _args : true) + _flags(_fl, _op, _mask, sizeof(#_args) > 1 ? _args : true) typedef void (*net_tcp_cb_t)(struct tcp *conn, void *user_data); diff --git a/subsys/net/ip/trickle.c b/subsys/net/ip/trickle.c index debe2d16181..bddac8ced69 100644 --- a/subsys/net/ip/trickle.c +++ b/subsys/net/ip/trickle.c @@ -15,7 +15,7 @@ LOG_MODULE_REGISTER(net_trickle, CONFIG_NET_TRICKLE_LOG_LEVEL); #include #include -#include +#include #include #include diff --git a/subsys/net/ip/udp.c b/subsys/net/ip/udp.c index 972eadb5a02..e3f45b3db38 100644 --- a/subsys/net/ip/udp.c +++ b/subsys/net/ip/udp.c @@ -35,7 +35,7 @@ int net_udp_create(struct net_pkt *pkt, uint16_t src_port, uint16_t dst_port) return net_pkt_set_data(pkt, &udp_access); } -int net_udp_finalize(struct net_pkt *pkt) +int net_udp_finalize(struct net_pkt *pkt, bool force_chksum) { NET_PKT_DATA_ACCESS_DEFINE(udp_access, struct net_udp_hdr); struct net_udp_hdr *udp_hdr; @@ -51,8 +51,9 @@ int net_udp_finalize(struct net_pkt *pkt) udp_hdr->len = htons(length); - if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt))) { + if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt)) || force_chksum) { udp_hdr->chksum = net_calc_chksum_udp(pkt); + net_pkt_set_chksum_done(pkt, true); } return net_pkt_set_data(pkt, &udp_access); @@ -163,7 +164,8 @@ struct net_udp_hdr *net_udp_input(struct net_pkt *pkt, } if (IS_ENABLED(CONFIG_NET_UDP_CHECKSUM) && - net_if_need_calc_rx_checksum(net_pkt_iface(pkt))) { + (net_if_need_calc_rx_checksum(net_pkt_iface(pkt)) || + net_pkt_is_ip_reassembled(pkt))) { if (!udp_hdr->chksum) { if (IS_ENABLED(CONFIG_NET_UDP_MISSING_CHECKSUM) && net_pkt_family(pkt) == AF_INET) { diff --git a/subsys/net/ip/udp_internal.h b/subsys/net/ip/udp_internal.h index 94106d60010..00009177d0b 100644 --- a/subsys/net/ip/udp_internal.h +++ b/subsys/net/ip/udp_internal.h @@ -63,11 +63,12 @@ static inline int net_udp_create(struct net_pkt *pkt, * @return 0 on success, negative errno otherwise. */ #if defined(CONFIG_NET_NATIVE_UDP) -int net_udp_finalize(struct net_pkt *pkt); +int net_udp_finalize(struct net_pkt *pkt, bool force_chksum); #else -static inline int net_udp_finalize(struct net_pkt *pkt) +static inline int net_udp_finalize(struct net_pkt *pkt, bool force_chksum) { ARG_UNUSED(pkt); + ARG_UNUSED(force_chksum); return 0; } diff --git a/subsys/net/ip/utils.c b/subsys/net/ip/utils.c index f71aa65936e..0e3bbce5d33 100644 --- a/subsys/net/ip/utils.c +++ b/subsys/net/ip/utils.c @@ -14,7 +14,7 @@ LOG_MODULE_REGISTER(net_utils, CONFIG_NET_UTILS_LOG_LEVEL); #include #include -#include +#include #include #include #include @@ -150,9 +150,9 @@ static int net_value_to_udec(char *buf, uint32_t value, int precision) char *z_impl_net_addr_ntop(sa_family_t family, const void *src, char *dst, size_t size) { - struct in_addr *addr; - struct in6_addr *addr6; - uint16_t *w; + struct in_addr *addr = NULL; + struct in6_addr *addr6 = NULL; + uint16_t *w = NULL; uint8_t i, bl, bh, longest = 1U; int8_t pos = -1; char delim = ':'; @@ -161,12 +161,17 @@ char *z_impl_net_addr_ntop(sa_family_t family, const void *src, int len = -1; uint16_t value; bool needcolon = false; + bool mapped = false; if (family == AF_INET6) { addr6 = (struct in6_addr *)src; w = (uint16_t *)addr6->s6_addr16; len = 8; + if (net_ipv6_addr_is_v4_mapped(addr6)) { + mapped = true; + } + for (i = 0U; i < 8; i++) { uint8_t j; @@ -198,6 +203,7 @@ char *z_impl_net_addr_ntop(sa_family_t family, const void *src, return NULL; } +print_mapped: for (i = 0U; i < len; i++) { /* IPv4 address a.b.c.d */ if (len == 4) { @@ -220,6 +226,15 @@ char *z_impl_net_addr_ntop(sa_family_t family, const void *src, continue; } + if (mapped && (i > 5)) { + delim = '.'; + len = 4; + addr = (struct in_addr *)(&addr6->s6_addr32[3]); + *ptr++ = ':'; + family = AF_INET; + goto print_mapped; + } + /* IPv6 address */ if (i == pos) { if (needcolon || i == 0U) { @@ -289,14 +304,14 @@ char *z_vrfy_net_addr_ntop(sa_family_t family, const void *src, char *out; const void *addr; - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(dst, size)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(dst, size)); if (family == AF_INET) { - Z_OOPS(z_user_from_copy(&addr4, (const void *)src, + K_OOPS(k_usermode_from_copy(&addr4, (const void *)src, sizeof(addr4))); addr = &addr4; } else if (family == AF_INET6) { - Z_OOPS(z_user_from_copy(&addr6, (const void *)src, + K_OOPS(k_usermode_from_copy(&addr6, (const void *)src, sizeof(addr6))); addr = &addr6; } else { @@ -308,7 +323,7 @@ char *z_vrfy_net_addr_ntop(sa_family_t family, const void *src, return 0; } - Z_OOPS(z_user_to_copy((void *)dst, str, MIN(size, sizeof(str)))); + K_OOPS(k_usermode_to_copy((void *)dst, str, MIN(size, sizeof(str)))); return dst; } @@ -469,18 +484,18 @@ int z_vrfy_net_addr_pton(sa_family_t family, const char *src, return -EINVAL; } - if (z_user_string_copy(str, (char *)src, sizeof(str)) != 0) { + if (k_usermode_string_copy(str, (char *)src, sizeof(str)) != 0) { return -EINVAL; } - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(dst, size)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(dst, size)); err = z_impl_net_addr_pton(family, str, addr); if (err) { return err; } - Z_OOPS(z_user_to_copy((void *)dst, addr, size)); + K_OOPS(k_usermode_to_copy((void *)dst, addr, size)); return 0; } diff --git a/subsys/net/l2/bluetooth/bluetooth.c b/subsys/net/l2/bluetooth/bluetooth.c index 8879c085425..8e7685c550f 100644 --- a/subsys/net/l2/bluetooth/bluetooth.c +++ b/subsys/net/l2/bluetooth/bluetooth.c @@ -315,7 +315,8 @@ static struct net_if_api bt_if_api = { .init = bt_iface_init, }; -static int ipsp_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan) +static int ipsp_accept(struct bt_conn *conn, struct bt_l2cap_server *server, + struct bt_l2cap_chan **chan) { struct bt_if_conn *if_conn = NULL; int i; diff --git a/subsys/net/l2/ethernet/ethernet.c b/subsys/net/l2/ethernet/ethernet.c index 4671f20aec1..2be3c5f2820 100644 --- a/subsys/net/l2/ethernet/ethernet.c +++ b/subsys/net/l2/ethernet/ethernet.c @@ -14,13 +14,13 @@ LOG_MODULE_REGISTER(net_ethernet, CONFIG_NET_L2_ETHERNET_LOG_LEVEL); #include #include #include -#include +#include #if defined(CONFIG_NET_LLDP) #include #endif -#include +#include #include "arp.h" #include "eth_stats.h" @@ -518,7 +518,8 @@ static struct net_buf *ethernet_fill_header(struct ethernet_context *ctx, } if (IS_ENABLED(CONFIG_NET_VLAN) && - net_eth_is_vlan_enabled(ctx, net_pkt_iface(pkt))) { + net_eth_is_vlan_enabled(ctx, net_pkt_iface(pkt)) && + (IS_ENABLED(CONFIG_NET_GPTP_VLAN) || ptype != htons(NET_ETH_PTYPE_PTP))) { struct net_eth_vlan_hdr *hdr_vlan; hdr_vlan = (struct net_eth_vlan_hdr *)(hdr_frag->data); @@ -695,7 +696,8 @@ static int ethernet_send(struct net_if *iface, struct net_pkt *pkt) } if (IS_ENABLED(CONFIG_NET_VLAN) && - net_eth_is_vlan_enabled(ctx, iface)) { + net_eth_is_vlan_enabled(ctx, iface) && + (IS_ENABLED(CONFIG_NET_GPTP_VLAN) || ptype != htons(NET_ETH_PTYPE_PTP))) { if (set_vlan_tag(ctx, iface, pkt) == NET_DROP) { ret = -EINVAL; goto error; diff --git a/subsys/net/l2/ethernet/gptp/Kconfig b/subsys/net/l2/ethernet/gptp/Kconfig index 357edc2553d..59dcbae2327 100644 --- a/subsys/net/l2/ethernet/gptp/Kconfig +++ b/subsys/net/l2/ethernet/gptp/Kconfig @@ -103,6 +103,13 @@ config NET_GPTP_CLOCK_ACCURACY default 0x31 if NET_GPTP_CLOCK_ACCURACY_GT_10S default 0xfe +config NET_GPTP_STACK_SIZE + int "gPTP thread stack size" + default 2048 + help + Set the gPTP thread stack size in bytes. The gPTP thread handles the + gPTP state machine. There is one gPTP thread in the system. + config NET_GPTP_NUM_PORTS int "Number of gPTP ports" default 1 @@ -117,10 +124,13 @@ config NET_GPTP_VLAN select NET_MGMT_EVENT select NET_MGMT_EVENT_INFO help - This setting allows gPTP to run over VLAN link. Currently only - one port can have VLAN tag set. Note that CONFIG_NET_GPTP_VLAN_TAG - setting must have a proper tag value set, otherwise the gPTP over - VLAN will not work. + The standard requires gPTP packets to not be VLAN-tagged (see IEEE + 802.1AS chapter 11.3.3). + This setting is for testing purposes. It allows to deviate from the + standard by running gPTP over a VLAN link. Currently only one port can + have VLAN tag set. Note that CONFIG_NET_GPTP_VLAN_TAG setting must + have a proper tag value set, otherwise the gPTP over VLAN will not + work. config NET_GPTP_VLAN_TAG int "VLAN tag to use" diff --git a/subsys/net/l2/ethernet/gptp/gptp.c b/subsys/net/l2/ethernet/gptp/gptp.c index 7ba4294a2fa..2cb128d26c2 100644 --- a/subsys/net/l2/ethernet/gptp/gptp.c +++ b/subsys/net/l2/ethernet/gptp/gptp.c @@ -10,7 +10,7 @@ LOG_MODULE_REGISTER(net_gptp, CONFIG_NET_GPTP_LOG_LEVEL); #include #include #include -#include +#include #include @@ -20,8 +20,6 @@ LOG_MODULE_REGISTER(net_gptp, CONFIG_NET_GPTP_LOG_LEVEL); #include "gptp_private.h" -#define NET_GPTP_STACK_SIZE 2048 - #if CONFIG_NET_GPTP_NUM_PORTS > 32 /* * Boolean arrays sizes have been hardcoded. @@ -31,7 +29,7 @@ LOG_MODULE_REGISTER(net_gptp, CONFIG_NET_GPTP_LOG_LEVEL); #error Maximum number of ports exceeded. (Max is 32). #endif -K_KERNEL_STACK_DEFINE(gptp_stack, NET_GPTP_STACK_SIZE); +K_KERNEL_STACK_DEFINE(gptp_stack, CONFIG_NET_GPTP_STACK_SIZE); K_FIFO_DEFINE(gptp_rx_queue); static k_tid_t tid; @@ -542,8 +540,12 @@ static void gptp_state_machine(void) gptp_mi_state_machines(); } -static void gptp_thread(void) +static void gptp_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + int port; NET_DBG("Starting PTP thread"); @@ -919,7 +921,7 @@ static void init_ports(void) tid = k_thread_create(&gptp_thread_data, gptp_stack, K_KERNEL_STACK_SIZEOF(gptp_stack), - (k_thread_entry_t)gptp_thread, + gptp_thread, NULL, NULL, NULL, K_PRIO_COOP(5), 0, K_NO_WAIT); k_thread_name_set(&gptp_thread_data, "gptp"); } diff --git a/subsys/net/l2/ethernet/gptp/gptp_messages.c b/subsys/net/l2/ethernet/gptp/gptp_messages.c index f5d1d79c3ed..780c1dedb6f 100644 --- a/subsys/net/l2/ethernet/gptp/gptp_messages.c +++ b/subsys/net/l2/ethernet/gptp/gptp_messages.c @@ -198,7 +198,7 @@ struct net_pkt *gptp_prepare_sync(int port) return NULL; } - net_pkt_set_priority(pkt, NET_PRIORITY_CA); + net_pkt_set_priority(pkt, NET_PRIORITY_IC); port_ds = GPTP_PORT_DS(port); sync = GPTP_SYNC(pkt); @@ -254,7 +254,7 @@ struct net_pkt *gptp_prepare_follow_up(int port, struct net_pkt *sync) return NULL; } - net_pkt_set_priority(pkt, NET_PRIORITY_IC); + net_pkt_set_priority(pkt, NET_PRIORITY_CA); hdr = GPTP_HDR(pkt); fup = GPTP_FOLLOW_UP(pkt); @@ -318,7 +318,7 @@ struct net_pkt *gptp_prepare_pdelay_req(int port) return NULL; } - net_pkt_set_priority(pkt, NET_PRIORITY_CA); + net_pkt_set_priority(pkt, NET_PRIORITY_IC); port_ds = GPTP_PORT_DS(port); req = GPTP_PDELAY_REQ(pkt); @@ -373,7 +373,7 @@ struct net_pkt *gptp_prepare_pdelay_resp(int port, return NULL; } - net_pkt_set_priority(pkt, NET_PRIORITY_CA); + net_pkt_set_priority(pkt, NET_PRIORITY_IC); port_ds = GPTP_PORT_DS(port); @@ -434,7 +434,7 @@ struct net_pkt *gptp_prepare_pdelay_follow_up(int port, return NULL; } - net_pkt_set_priority(pkt, NET_PRIORITY_IC); + net_pkt_set_priority(pkt, NET_PRIORITY_CA); port_ds = GPTP_PORT_DS(port); @@ -503,7 +503,7 @@ struct net_pkt *gptp_prepare_announce(int port) return NULL; } - net_pkt_set_priority(pkt, NET_PRIORITY_IC); + net_pkt_set_priority(pkt, NET_PRIORITY_CA); hdr = GPTP_HDR(pkt); ann = GPTP_ANNOUNCE(pkt); diff --git a/subsys/net/l2/ieee802154/CMakeLists.txt b/subsys/net/l2/ieee802154/CMakeLists.txt index 65fbebe0391..e9d1318d81e 100644 --- a/subsys/net/l2/ieee802154/CMakeLists.txt +++ b/subsys/net/l2/ieee802154/CMakeLists.txt @@ -9,6 +9,7 @@ zephyr_library_compile_definitions_ifdef( zephyr_library_sources( ieee802154.c ieee802154_frame.c + ieee802154_utils.c ) zephyr_library_sources_ifdef( diff --git a/subsys/net/l2/ieee802154/Kconfig b/subsys/net/l2/ieee802154/Kconfig index 244d7f9da01..6aa03db01ff 100644 --- a/subsys/net/l2/ieee802154/Kconfig +++ b/subsys/net/l2/ieee802154/Kconfig @@ -14,22 +14,6 @@ config NET_L2_IEEE802154_MGMT select NET_MGMT select NET_MGMT_EVENT -# TODO: Selecting PHYs and frequency bands is abstracted by the concept -# of channel pages in recent versions of the standard (see -# IEEE 802.15.4-2020, 10.1.3). -# This option will be replaced by configuration options on driver -# instance level that allow selection of a channel page as well -# as other PHY-specific configuration options (frequency bands, -# operating modes, etc.). -# New and existing drivers should not introduce additional -# references to this option. -config NET_L2_IEEE802154_SUB_GHZ - bool - help - Enable support for Sub-GHz devices. This will add a tiny bit more - logic in L2 code for channel management. This option is automatically - selected when relevant device driver is enabled. - module = NET_L2_IEEE802154 module-dep = NET_LOG module-str = Log level for IEEE 802.15.4 diff --git a/subsys/net/l2/ieee802154/ieee802154.c b/subsys/net/l2/ieee802154/ieee802154.c index 543c4a4d43b..09fdf8d28cf 100644 --- a/subsys/net/l2/ieee802154/ieee802154.c +++ b/subsys/net/l2/ieee802154/ieee802154.c @@ -22,7 +22,7 @@ LOG_MODULE_REGISTER(net_ieee802154, CONFIG_NET_L2_IEEE802154_LOG_LEVEL); #include #include #include -#include +#include #ifdef CONFIG_NET_6LO #include "ieee802154_6lo.h" @@ -360,7 +360,7 @@ static bool ieeee802154_check_dst_addr(struct net_if *iface, struct ieee802154_m static enum net_verdict ieee802154_recv(struct net_if *iface, struct net_pkt *pkt) { const struct ieee802154_radio_api *radio = net_if_get_device(iface)->api; - enum net_verdict verdict = NET_DROP; + enum net_verdict verdict = NET_CONTINUE; struct ieee802154_fcf_seq *fs; struct ieee802154_mpdu mpdu; bool is_broadcast; @@ -387,8 +387,9 @@ static enum net_verdict ieee802154_recv(struct net_if *iface, struct net_pkt *pk if (fs->fc.frame_type == IEEE802154_FRAME_TYPE_BEACON) { verdict = ieee802154_handle_beacon(iface, &mpdu, net_pkt_ieee802154_lqi(pkt)); - if (verdict == NET_OK) { + if (verdict == NET_CONTINUE) { net_pkt_unref(pkt); + return NET_OK; } /* Beacons must not be acknowledged, see section 6.7.4.1. */ return verdict; @@ -400,7 +401,7 @@ static enum net_verdict ieee802154_recv(struct net_if *iface, struct net_pkt *pk if (fs->fc.frame_type == IEEE802154_FRAME_TYPE_MAC_COMMAND) { verdict = ieee802154_handle_mac_command(iface, &mpdu); - if (verdict != NET_OK) { + if (verdict == NET_DROP) { return verdict; } } @@ -427,7 +428,7 @@ static enum net_verdict ieee802154_recv(struct net_if *iface, struct net_pkt *pk if (fs->fc.frame_type == IEEE802154_FRAME_TYPE_MAC_COMMAND) { net_pkt_unref(pkt); - return verdict; + return NET_OK; } if (!ieee802154_decipher_data_frame(iface, pkt, &mpdu)) { @@ -453,12 +454,13 @@ static enum net_verdict ieee802154_recv(struct net_if *iface, struct net_pkt *pk #ifdef CONFIG_NET_6LO verdict = ieee802154_6lo_decode_pkt(iface, pkt); +#endif /* CONFIG_NET_6LO */ + + if (verdict == NET_CONTINUE) { + pkt_hexdump(RX_PKT_TITLE, pkt, true); + } - pkt_hexdump(RX_PKT_TITLE, pkt, true); return verdict; -#else - return NET_CONTINUE; -#endif /* CONFIG_NET_6LO */ /* At this point the call amounts to (part of) an * MCPS-DATA.indication primitive, see section 8.3.3. @@ -655,7 +657,8 @@ void ieee802154_init(struct net_if *iface) memcpy(ctx->linkaddr.addr, eui64_be, IEEE802154_EXT_ADDR_LENGTH); net_if_set_link_addr(iface, ctx->linkaddr.addr, ctx->linkaddr.len, ctx->linkaddr.type); - if (IS_ENABLED(CONFIG_IEEE802154_NET_IF_NO_AUTO_START)) { + if (IS_ENABLED(CONFIG_IEEE802154_NET_IF_NO_AUTO_START) || + IS_ENABLED(CONFIG_NET_CONFIG_SETTINGS)) { LOG_DBG("Interface auto start disabled."); net_if_flag_set(iface, NET_IF_NO_AUTO_START); } diff --git a/subsys/net/l2/ieee802154/ieee802154_frame.h b/subsys/net/l2/ieee802154/ieee802154_frame.h index a68945a0eab..2a24a5b6029 100644 --- a/subsys/net/l2/ieee802154/ieee802154_frame.h +++ b/subsys/net/l2/ieee802154/ieee802154_frame.h @@ -8,13 +8,13 @@ * @file * @brief IEEE 802.15.4 MAC frame related functions * - * This is not to be included by the application. + * @details This is not to be included by the application. * - * All specification references in this file refer to IEEE 802.15.4-2020. + * @note All references to the standard in this file cite IEEE 802.15.4-2020. * - * Note: All structs and attributes (e.g. PAN id, ext address and short - * address) in this file that directly represent IEEE 802.15.4 frames - * are in LITTLE ENDIAN, see section 4, especially section 4.3. + * @note All structs and attributes (e.g. PAN id, ext address and short address) + * in this file that directly represent parts of IEEE 802.15.4 frames are in + * LITTLE ENDIAN, see section 4, especially section 4.3. */ #ifndef __IEEE802154_FRAME_H__ @@ -42,7 +42,7 @@ #define IEEE802154_BEACON_GTS_RX 1 #define IEEE802154_BEACON_GTS_TX 0 -/* See section 7.2.2.2 */ +/** see section 7.2.2.2 */ enum ieee802154_frame_type { IEEE802154_FRAME_TYPE_BEACON = 0x0, IEEE802154_FRAME_TYPE_DATA = 0x1, @@ -54,7 +54,7 @@ enum ieee802154_frame_type { IEEE802154_FRAME_TYPE_EXTENDED = 0x7, }; -/* See section 7.2.2.9, table 7-3 */ +/** see section 7.2.2.9, table 7-3 */ enum ieee802154_addressing_mode { IEEE802154_ADDR_MODE_NONE = 0x0, IEEE802154_ADDR_MODE_RESERVED = 0x1, @@ -62,7 +62,7 @@ enum ieee802154_addressing_mode { IEEE802154_ADDR_MODE_EXTENDED = 0x3, }; -/* See section 7.2.2.10 */ +/** see section 7.2.2.10 */ enum ieee802154_version { IEEE802154_VERSION_802154_2003 = 0x0, IEEE802154_VERSION_802154_2006 = 0x1, @@ -70,9 +70,7 @@ enum ieee802154_version { IEEE802154_VERSION_RESERVED = 0x3, }; -/* - * Frame Control Field, see section 7.2.2 - */ +/** Frame Control Field, see section 7.2.2 */ struct ieee802154_fcf_seq { struct { #ifdef CONFIG_LITTLE_ENDIAN @@ -128,7 +126,7 @@ struct ieee802154_address_field { }; } __packed; -/* See section 9.4.2.2, table 9-6 */ +/** see section 9.4.2.2, table 9-6 */ enum ieee802154_security_level { IEEE802154_SECURITY_LEVEL_NONE = 0x0, IEEE802154_SECURITY_LEVEL_MIC_32 = 0x1, @@ -140,15 +138,15 @@ enum ieee802154_security_level { IEEE802154_SECURITY_LEVEL_ENC_MIC_128 = 0x7, }; -/* Levels above this level will be encrypted. */ +/** Levels above this level will be encrypted. */ #define IEEE802154_SECURITY_LEVEL_ENC IEEE802154_SECURITY_LEVEL_RESERVED -/* This will match above *_MIC_<32/64/128> */ +/** This will match above *_MIC_<32/64/128> */ #define IEEE802154_AUTH_TAG_LENGTH_32 4 #define IEEE802154_AUTH_TAG_LENGTH_64 8 #define IEEE802154_AUTH_TAG_LENGTH_128 16 -/* See section 9.4.2.3, table 9-7 */ +/** see section 9.4.2.3, table 9-7 */ enum ieee802154_key_id_mode { IEEE802154_KEY_ID_MODE_IMPLICIT = 0x0, IEEE802154_KEY_ID_MODE_INDEX = 0x1, @@ -162,7 +160,7 @@ enum ieee802154_key_id_mode { #define IEEE802154_KEY_MAX_LEN 16 -/* See section 9.4.2 */ +/** see section 9.4.2 */ struct ieee802154_security_control_field { #ifdef CONFIG_LITTLE_ENDIAN uint8_t security_level : 3; @@ -177,10 +175,14 @@ struct ieee802154_security_control_field { #define IEEE802154_SECURITY_CF_LENGTH 1 -/* see section 9.4.4 */ +/** + * @brief see section 9.4.4 + * + * @note Currently only mode 0 is supported, so this structure holds no info, + * yet. + */ struct ieee802154_key_identifier_field { union { - /* mode_0 being implicit, it holds no info here */ struct { uint8_t key_index; } mode_1; @@ -197,10 +199,7 @@ struct ieee802154_key_identifier_field { }; } __packed; -/* - * Auxiliary Security Header - * see section 9.4 - */ +/** Auxiliary Security Header, see section 9.4 */ struct ieee802154_aux_security_hdr { struct ieee802154_security_control_field control; uint32_t frame_counter; @@ -209,7 +208,7 @@ struct ieee802154_aux_security_hdr { #define IEEE802154_SECURITY_FRAME_COUNTER_LENGTH 4 -/* MAC header and footer, see section 7.2.1 */ +/** MAC header and footer, see section 7.2.1 */ struct ieee802154_mhr { struct ieee802154_fcf_seq *fs; struct ieee802154_address_field *dst_addr; @@ -219,7 +218,7 @@ struct ieee802154_mhr { #endif }; -/* see section 7.3.1.5, figure 7-10 */ +/** see section 7.3.1.5, figure 7-10 */ struct ieee802154_gts_dir { #ifdef CONFIG_LITTLE_ENDIAN uint8_t mask : 7; @@ -230,7 +229,7 @@ struct ieee802154_gts_dir { #endif } __packed; -/* see section 7.3.1.5, figure 7-11 */ +/** see section 7.3.1.5, figure 7-11 */ struct ieee802154_gts { uint16_t short_address; #ifdef CONFIG_LITTLE_ENDIAN @@ -242,7 +241,7 @@ struct ieee802154_gts { #endif } __packed; -/* see section 7.3.1.5, figure 7-9 */ +/** see section 7.3.1.5, figure 7-9 */ struct ieee802154_gts_spec { #ifdef CONFIG_LITTLE_ENDIAN /* Descriptor Count */ @@ -259,7 +258,7 @@ struct ieee802154_gts_spec { #endif } __packed; -/* see section 7.3.1.6, figure 7-13 */ +/** see section 7.3.1.6, figure 7-13 */ struct ieee802154_pas_spec { #ifdef CONFIG_LITTLE_ENDIAN /* Number of Short Addresses Pending */ @@ -278,7 +277,7 @@ struct ieee802154_pas_spec { #endif } __packed; -/* see section 7.3.1.4, figure 7-7 */ +/** see section 7.3.1.4, figure 7-7 */ struct ieee802154_beacon_sf { #ifdef CONFIG_LITTLE_ENDIAN /* Beacon Order*/ @@ -311,7 +310,7 @@ struct ieee802154_beacon_sf { #endif } __packed; -/* see section 7.3.1.1, figure 7-5 */ +/** see section 7.3.1.1, figure 7-5 */ struct ieee802154_beacon { struct ieee802154_beacon_sf sf; @@ -319,7 +318,7 @@ struct ieee802154_beacon { struct ieee802154_gts_spec gts; } __packed; -/* see section 7.5.2 */ +/** See section 7.5.2 */ struct ieee802154_cmd_assoc_req { struct { #ifdef CONFIG_LITTLE_ENDIAN @@ -346,7 +345,7 @@ struct ieee802154_cmd_assoc_req { #define IEEE802154_CMD_ASSOC_REQ_LENGTH 1 -/* See section 7.5.3 */ +/** see section 7.5.3 */ enum ieee802154_association_status_field { IEEE802154_ASF_SUCCESSFUL = 0x00, IEEE802154_ASF_PAN_AT_CAPACITY = 0x01, @@ -362,7 +361,7 @@ struct ieee802154_cmd_assoc_res { #define IEEE802154_CMD_ASSOC_RES_LENGTH 3 -/* See section 7.5.4 */ +/** see section 7.5.4 */ enum ieee802154_disassociation_reason_field { IEEE802154_DRF_RESERVED_1 = 0x00, IEEE802154_DRF_COORDINATOR_WISH = 0x01, @@ -377,7 +376,7 @@ struct ieee802154_cmd_disassoc_note { #define IEEE802154_CMD_DISASSOC_NOTE_LENGTH 1 -/* Coordinator realignment, see section 7.5.10 */ +/** Coordinator realignment, see section 7.5.10 */ struct ieee802154_cmd_coord_realign { uint16_t pan_id; uint16_t coordinator_short_addr; @@ -388,7 +387,7 @@ struct ieee802154_cmd_coord_realign { #define IEEE802154_CMD_COORD_REALIGN_LENGTH 3 -/* GTS request, see section 7.5.11 */ +/** GTS request, see section 7.5.11 */ struct ieee802154_gts_request { struct { #ifdef CONFIG_LITTLE_ENDIAN @@ -407,7 +406,7 @@ struct ieee802154_gts_request { #define IEEE802154_GTS_REQUEST_LENGTH 1 -/* Command Frame Identifiers (CFI), see section 7.5.1 */ +/** Command Frame Identifiers (CFI), see section 7.5.1 */ enum ieee802154_cfi { IEEE802154_CFI_UNKNOWN = 0x00, IEEE802154_CFI_ASSOCIATION_REQUEST = 0x01, diff --git a/subsys/net/l2/ieee802154/ieee802154_mgmt.c b/subsys/net/l2/ieee802154/ieee802154_mgmt.c index e009018c835..f9dd3dd5c6a 100644 --- a/subsys/net/l2/ieee802154/ieee802154_mgmt.c +++ b/subsys/net/l2/ieee802154/ieee802154_mgmt.c @@ -68,7 +68,7 @@ enum net_verdict ieee802154_handle_beacon(struct net_if *iface, k_sem_give(&ctx->scan_ctx_lock); - return NET_OK; + return NET_CONTINUE; } static int ieee802154_cancel_scan(uint32_t mgmt_request, struct net_if *iface, @@ -94,10 +94,11 @@ NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_CANCEL_SCAN, static int ieee802154_scan(uint32_t mgmt_request, struct net_if *iface, void *data, size_t len) { + const struct ieee802154_phy_supported_channels *supported_channels; struct ieee802154_context *ctx = net_if_l2_data(iface); + struct ieee802154_attr_value attr_value; struct ieee802154_req_params *scan; struct net_pkt *pkt = NULL; - uint8_t channel; int ret; if (len != sizeof(struct ieee802154_req_params) || !data) { @@ -127,6 +128,7 @@ static int ieee802154_scan(uint32_t mgmt_request, struct net_if *iface, pkt = ieee802154_create_mac_cmd_frame( iface, IEEE802154_CFI_BEACON_REQUEST, ¶ms); if (!pkt) { + k_sem_give(&ctx->scan_ctx_lock); NET_DBG("Could not create Beacon Request"); ret = -ENOBUFS; goto out; @@ -151,44 +153,52 @@ static int ieee802154_scan(uint32_t mgmt_request, struct net_if *iface, goto out; } - /* TODO: For now, we assume we are on 2.4Ghz - * (device will have to export current channel page) - */ - for (channel = 11U; channel <= 26U; channel++) { - if (IEEE802154_IS_CHAN_UNSCANNED(scan->channel_set, channel)) { - continue; - } + if (ieee802154_radio_attr_get(iface, IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES, + &attr_value)) { + NET_DBG("Could not determine supported channels"); + ret = -ENOENT; + goto out; + } + supported_channels = attr_value.phy_supported_channels; - scan->channel = channel; - NET_DBG("Scanning channel %u", channel); - ieee802154_radio_set_channel(iface, channel); + for (int channel_range = 0; channel_range < supported_channels->num_ranges; + channel_range++) { + for (uint16_t channel = supported_channels->ranges[channel_range].from_channel; + channel <= supported_channels->ranges[channel_range].to_channel; channel++) { + if (IEEE802154_IS_CHAN_UNSCANNED(scan->channel_set, channel)) { + continue; + } - /* Active scan sends a beacon request */ - if (mgmt_request == NET_REQUEST_IEEE802154_ACTIVE_SCAN) { - net_pkt_ref(pkt); - net_pkt_frag_ref(pkt->buffer); + scan->channel = channel; + NET_DBG("Scanning channel %u", channel); + ieee802154_radio_set_channel(iface, channel); - ret = ieee802154_radio_send(iface, pkt, pkt->buffer); - if (ret) { - NET_DBG("Could not send Beacon Request (%d)", - ret); - net_pkt_unref(pkt); - goto out; + /* Active scan sends a beacon request */ + if (mgmt_request == NET_REQUEST_IEEE802154_ACTIVE_SCAN) { + net_pkt_ref(pkt); + net_pkt_frag_ref(pkt->buffer); + + ret = ieee802154_radio_send(iface, pkt, pkt->buffer); + if (ret) { + NET_DBG("Could not send Beacon Request (%d)", ret); + net_pkt_unref(pkt); + goto out; + } } - } - /* Context aware sleep */ - k_sleep(K_MSEC(scan->duration)); + /* Context aware sleep */ + k_sleep(K_MSEC(scan->duration)); - k_sem_take(&ctx->scan_ctx_lock, K_FOREVER); + k_sem_take(&ctx->scan_ctx_lock, K_FOREVER); - if (!ctx->scan_ctx) { - NET_DBG("Scan request cancelled"); - ret = -ECANCELED; - goto out; - } + if (!ctx->scan_ctx) { + NET_DBG("Scan request cancelled"); + ret = -ECANCELED; + goto out; + } - k_sem_give(&ctx->scan_ctx_lock); + k_sem_give(&ctx->scan_ctx_lock); + } } out: @@ -357,7 +367,7 @@ enum net_verdict ieee802154_handle_mac_command(struct net_if *iface, k_sem_give(&ctx->scan_ctx_lock); - return NET_OK; + return NET_CONTINUE; } if (mpdu->command->cfi == IEEE802154_CFI_DISASSOCIATION_NOTIFICATION) { diff --git a/subsys/net/l2/ieee802154/ieee802154_mgmt_priv.h b/subsys/net/l2/ieee802154/ieee802154_mgmt_priv.h index 2e8b53693a4..acdd15a94fc 100644 --- a/subsys/net/l2/ieee802154/ieee802154_mgmt_priv.h +++ b/subsys/net/l2/ieee802154/ieee802154_mgmt_priv.h @@ -33,8 +33,8 @@ static inline void ieee802154_mgmt_init(struct net_if *iface) /** * Handles the given Beacon frame. * - * Returns NET_OK if successful. It's the caller's responsibility - * to release the corresponding package in that case. + * @retval NET_CONTINUE if successful. + * @retval NET_DROP error while parsing the beacon */ enum net_verdict ieee802154_handle_beacon(struct net_if *iface, struct ieee802154_mpdu *mpdu, @@ -43,8 +43,8 @@ enum net_verdict ieee802154_handle_beacon(struct net_if *iface, /** * Executes the given MAC command. * - * Returns NET_OK if successful. It's the caller's responsibility - * to release the corresponding package in that case. + * @retval NET_CONTINUE if successful. + * @retval NET_DROP error while parsing the mac command */ enum net_verdict ieee802154_handle_mac_command(struct net_if *iface, struct ieee802154_mpdu *mpdu); diff --git a/subsys/net/l2/ieee802154/ieee802154_radio_csma_ca.c b/subsys/net/l2/ieee802154/ieee802154_radio_csma_ca.c index 2457eb503d6..06b00b7964f 100644 --- a/subsys/net/l2/ieee802154/ieee802154_radio_csma_ca.c +++ b/subsys/net/l2/ieee802154/ieee802154_radio_csma_ca.c @@ -12,7 +12,7 @@ LOG_MODULE_REGISTER(net_ieee802154_csma, CONFIG_NET_L2_IEEE802154_LOG_LEVEL); #include #include #include -#include +#include #include #include @@ -28,9 +28,15 @@ BUILD_ASSERT(CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA_MIN_BE <= /* See section 6.2.5.1. */ static inline int unslotted_csma_ca_channel_access(struct net_if *iface) { - uint32_t turnaround_time = ieee802154_radio_get_a_turnaround_time(iface); - uint32_t symbol_period = ieee802154_radio_get_symbol_period_us(iface); + struct ieee802154_context *ctx = net_if_l2_data(iface); uint8_t be = CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA_MIN_BE; + uint32_t turnaround_time, unit_backoff_period_us; + + turnaround_time = ieee802154_radio_get_a_turnaround_time(iface); + unit_backoff_period_us = ieee802154_radio_get_multiple_of_symbol_period( + iface, ctx->channel, + IEEE802154_MAC_A_UNIT_BACKOFF_PERIOD(turnaround_time)) / + NSEC_PER_USEC; for (uint8_t nb = 0U; nb <= CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA_MAX_BO; nb++) { int ret; @@ -42,8 +48,7 @@ static inline int unslotted_csma_ca_channel_access(struct net_if *iface) * radio API should expose a precise radio clock instead (which may * fall back to k_busy_wait() if the radio does not have a clock). */ - k_busy_wait(bo_n * IEEE802154_A_UNIT_BACKOFF_PERIOD_US(turnaround_time, - symbol_period)); + k_busy_wait(bo_n * unit_backoff_period_us); } ret = ieee802154_radio_cca(iface); diff --git a/subsys/net/l2/ieee802154/ieee802154_utils.c b/subsys/net/l2/ieee802154/ieee802154_utils.c new file mode 100644 index 00000000000..7058bbe70eb --- /dev/null +++ b/subsys/net/l2/ieee802154/ieee802154_utils.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2023 Florian Grandel, Zephyr Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief IEEE 802.15.4 internal MAC and PHY Utils Implementation + * + * All references to the standard in this file cite IEEE 802.15.4-2020. + */ + +#include +LOG_MODULE_DECLARE(net_ieee802154, CONFIG_NET_L2_IEEE802154_LOG_LEVEL); + +#include "ieee802154_utils.h" + +/** + * PHY utilities + */ + +bool ieee802154_radio_verify_channel(struct net_if *iface, uint16_t channel) +{ + struct ieee802154_attr_value value; + + if (channel == IEEE802154_NO_CHANNEL) { + return false; + } + + if (ieee802154_radio_attr_get(iface, IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES, + &value)) { + return false; + } + + for (int channel_range_index = 0; + channel_range_index < value.phy_supported_channels->num_ranges; + channel_range_index++) { + const struct ieee802154_phy_channel_range *const channel_range = + &value.phy_supported_channels->ranges[channel_range_index]; + + if (channel >= channel_range->from_channel && + channel <= channel_range->to_channel) { + return true; + } + } + + return false; +} + +uint16_t ieee802154_radio_number_of_channels(struct net_if *iface) +{ + struct ieee802154_attr_value value; + uint16_t num_channels = 0; + + if (ieee802154_radio_attr_get(iface, IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES, + &value)) { + return 0; + } + + for (int channel_range_index = 0; + channel_range_index < value.phy_supported_channels->num_ranges; + channel_range_index++) { + const struct ieee802154_phy_channel_range *const channel_range = + &value.phy_supported_channels->ranges[channel_range_index]; + + __ASSERT_NO_MSG(channel_range->to_channel >= channel_range->from_channel); + num_channels += channel_range->to_channel - channel_range->from_channel + 1U; + } + + return num_channels; +} diff --git a/subsys/net/l2/ieee802154/ieee802154_utils.h b/subsys/net/l2/ieee802154/ieee802154_utils.h index 4294ba7bd9f..ec80adff20e 100644 --- a/subsys/net/l2/ieee802154/ieee802154_utils.h +++ b/subsys/net/l2/ieee802154/ieee802154_utils.h @@ -123,7 +123,7 @@ static inline int ieee802154_radio_attr_get(struct net_if *iface, /** * Sets the radio drivers extended address filter. * - * @param iface Pointer to the IEEE 802.15.4 interface + * @param iface pointer to the IEEE 802.15.4 interface * @param ieee_addr Pointer to an extended address in little endian byte order */ static inline void ieee802154_radio_filter_ieee_addr(struct net_if *iface, uint8_t *ieee_addr) @@ -278,112 +278,204 @@ static inline void ieee802154_radio_remove_pan_id(struct net_if *iface, uint16_t } } + /** - * @brief Calculates the PHY's symbol period in microseconds. - * - * @details The PHY's symbol period depends on the interface's current PHY which - * can be derived from the currently chosen channel page (phyCurrentPage). - * - * Examples: - * * SUN FSK: see section 19.1, table 19-1 - * * O-QPSK: see section 12.3.3 - * * HRP UWB: derived from the preamble symbol period (T_psym), see section - * 11.3, table 11-1 and section 15.2.5, table 15-4 + * MAC utilities * - * @note Currently the symbol period can only be calculated for SUN FSK and O-QPSK. + * @note While MAC utilities may refer to PHY utilities, the inverse is not + * true. + */ + +/** + * @brief Retrieves the currently selected channel page from the driver (see + * phyCurrentPage, section 11.3, table 11-2). This is PHY-related information + * not configured by L2 but directly provided by the driver. * - * @param iface The interface for which the symbol period should be calculated. + * @param iface pointer to the IEEE 802.15.4 interface * - * @returns The symbol period for the given interface in microseconds. + * @returns The currently active channel page. + * @retval 0 if an error occurred */ -static inline uint32_t ieee802154_radio_get_symbol_period_us(struct net_if *iface) +static inline enum ieee802154_phy_channel_page +ieee802154_radio_current_channel_page(struct net_if *iface) { - /* TODO: Move symbol period calculation to radio driver. */ + struct ieee802154_attr_value value; - if (IS_ENABLED(CONFIG_NET_L2_IEEE802154_SUB_GHZ) && - ieee802154_radio_get_hw_capabilities(iface) & IEEE802154_HW_SUB_GHZ) { - return IEEE802154_PHY_SYMBOL_PERIOD_US(true); + /* Currently we assume that drivers are statically configured to only + * support a single channel page. Once drivers need to switch channels at + * runtime this can be changed here w/o affecting clients. + */ + if (ieee802154_radio_attr_get(iface, IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_PAGES, &value)) { + return 0; } - return IEEE802154_PHY_SYMBOL_PERIOD_US(false); + return value.phy_supported_channel_pages; } /** - * @brief Calculates the PHY's turnaround time (see section 11.3, table 11-1, - * aTurnaroundTime) in PHY symbols. + * @brief Calculates a multiple of the PHY's symbol period in nanoseconds. * - * @details The PHY's turnaround time is used to calculate - among other - * parameters - the TX-to-RX turnaround time (see section 10.2.2) and the - * RX-to-TX turnaround time (see section 10.2.3). + * @details The PHY's symbol period depends on the interface's current PHY + * configuration which usually can be derived from the currently chosen channel + * page and channel (phyCurrentPage and phyCurrentChannel, section 11.3, table + * 11-2). + * + * To calculate the symbol period of HRP UWB PHYs, the nominal pulse repetition + * frequency (PRF) is required. HRP UWB drivers will be expected to expose the + * supported norminal PRF rates as a driver attribute. Existing drivers do not + * allow for runtime switching of the PRF, so currently the PRF is considered to + * be read-only and known. + * + * TODO: Add an UwbPrf argument once drivers need to support PRF switching at + * runtime. * - * @note Currently the turnaround time can only be calculated for SUN FSK and O-QPSK. + * @note We do not expose an API for a single symbol period to avoid having to + * deal with floats for PHYs that don't require it while maintaining precision + * in calculations where PHYs operate at symbol periods involving fractions of + * nanoseconds. * - * @param iface The interface for which the turnaround time should be calculated. + * @param iface pointer to the IEEE 802.15.4 interface + * @param channel The channel for which the symbol period is to be calculated. + * @param multiplier The factor by which the symbol period is to be multiplied. * - * @returns The turnaround time for the given interface. + * @returns A multiple of the symbol period for the given interface with + * nanosecond precision. + * @retval 0 if an error occurred. */ -static inline uint32_t ieee802154_radio_get_a_turnaround_time(struct net_if *iface) +static inline net_time_t ieee802154_radio_get_multiple_of_symbol_period(struct net_if *iface, + uint16_t channel, + uint16_t multiplier) { - if (IS_ENABLED(CONFIG_NET_L2_IEEE802154_SUB_GHZ) && - ieee802154_radio_get_hw_capabilities(iface) & IEEE802154_HW_SUB_GHZ) { - return IEEE802154_PHY_A_TURNAROUND_TIME(true); - } + /* To keep things simple we only calculate symbol periods for channel + * pages that are implemented by existing in-tree drivers. Add additional + * channel pages as required. + */ + switch (ieee802154_radio_current_channel_page(iface)) { + case IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915: + return (channel >= 11 + ? IEEE802154_PHY_OQPSK_780_TO_2450MHZ_SYMBOL_PERIOD_NS + : (channel > 0 ? IEEE802154_PHY_BPSK_915MHZ_SYMBOL_PERIOD_NS + : IEEE802154_PHY_BPSK_868MHZ_SYMBOL_PERIOD_NS)) * + multiplier; + + case IEEE802154_ATTR_PHY_CHANNEL_PAGE_TWO_OQPSK_868_915: + return (channel > 0 ? IEEE802154_PHY_OQPSK_780_TO_2450MHZ_SYMBOL_PERIOD_NS + : IEEE802154_PHY_OQPSK_868MHZ_SYMBOL_PERIOD_NS) * + multiplier; + + case IEEE802154_ATTR_PHY_CHANNEL_PAGE_FOUR_HRP_UWB: { + struct ieee802154_attr_value value; + + /* Currently we assume that drivers are statically configured to + * only support a single PRF. Once drivers support switching PRF + * at runtime an UWB PRF argument needs to be added to this + * function which then must be validated against the set of + * supported PRFs. + */ + if (ieee802154_radio_attr_get(iface, IEEE802154_ATTR_PHY_HRP_UWB_SUPPORTED_PRFS, + &value)) { + return 0; + } - return IEEE802154_PHY_A_TURNAROUND_TIME(false); -} + switch (value.phy_hrp_uwb_supported_nominal_prfs) { + case IEEE802154_PHY_HRP_UWB_NOMINAL_4_M: + return IEEE802154_PHY_HRP_UWB_PRF4_TPSYM_SYMBOL_PERIOD_NS * multiplier; -static inline bool ieee802154_radio_verify_channel(struct net_if *iface, uint16_t channel) -{ - if (channel == IEEE802154_NO_CHANNEL) { - return false; - } + case IEEE802154_PHY_HRP_UWB_NOMINAL_16_M: + return IEEE802154_PHY_HRP_UWB_PRF16_TPSYM_SYMBOL_PERIOD_NS * multiplier; -#ifdef CONFIG_NET_L2_IEEE802154_SUB_GHZ - const struct ieee802154_radio_api *radio = - net_if_get_device(iface)->api; + case IEEE802154_PHY_HRP_UWB_NOMINAL_64_M: + return IEEE802154_PHY_HRP_UWB_PRF64_TPSYM_SYMBOL_PERIOD_NS * multiplier; - if (!radio) { - return false; - } + case IEEE802154_PHY_HRP_UWB_NOMINAL_64_M_BPRF: + case IEEE802154_PHY_HRP_UWB_NOMINAL_128_M_HPRF: + case IEEE802154_PHY_HRP_UWB_NOMINAL_256_M_HPRF: + return IEEE802154_PHY_HRP_UWB_ERDEV_TPSYM_SYMBOL_PERIOD_NS * multiplier; - if (radio->get_capabilities(net_if_get_device(iface)) & - IEEE802154_HW_SUB_GHZ) { - if (channel > - radio->get_subg_channel_count(net_if_get_device(iface))) { - return false; + default: + CODE_UNREACHABLE; } } -#endif /* CONFIG_NET_L2_IEEE802154_SUB_GHZ */ - return true; -} + case IEEE802154_ATTR_PHY_CHANNEL_PAGE_FIVE_OQPSK_780: + return IEEE802154_PHY_OQPSK_780_TO_2450MHZ_SYMBOL_PERIOD_NS * multiplier; + + case IEEE802154_ATTR_PHY_CHANNEL_PAGE_NINE_SUN_PREDEFINED: + /* Current SUN FSK drivers only implement legacy IEEE 802.15.4g + * 863 MHz (Europe) and 915 MHz (US ISM) bands, see IEEE + * 802.15.4g, section 5.1, table 0. Once more bands are required + * we need to request the currently active frequency band from + * the driver. + */ + return IEEE802154_PHY_SUN_FSK_863MHZ_915MHZ_SYMBOL_PERIOD_NS * multiplier; + default: + CODE_UNREACHABLE; + } +} /** - * MAC utilities + * @brief Calculates the PHY's turnaround time for the current channel page (see + * section 11.3, table 11-1, aTurnaroundTime) in PHY symbols. + * + * @details The PHY's turnaround time is used to calculate - among other + * parameters - the TX-to-RX turnaround time (see section 10.2.2) and the + * RX-to-TX turnaround time (see section 10.2.3). + * + * @param iface pointer to the IEEE 802.15.4 interface * - * Note: While MAC utilities may refer to PHY utilities, - * the inverse is not true. + * @returns The turnaround time for the given interface in symbols. + * @retval 0 if an error occurred. */ +static inline uint32_t ieee802154_radio_get_a_turnaround_time(struct net_if *iface) +{ + enum ieee802154_phy_channel_page channel_page = + ieee802154_radio_current_channel_page(iface); -/** - * The number of PHY symbols forming a superframe slot when the superframe order - * is equal to zero, see sections 8.4.2, table 8-93, aBaseSlotDuration and 6.2.1. - */ -#define IEEE802154_MAC_A_BASE_SLOT_DURATION 60U + if (!channel_page) { + return 0; + } + + /* Section 11.3, table 11-1, aTurnaroundTime: "For the SUN [...] PHYs, + * the value is 1 ms expressed in symbol periods, rounded up to the next + * integer number of symbol periods using the ceiling() function. [...] + * The value is 12 [symbol periods] for all other PHYs. + */ + + if (channel_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_NINE_SUN_PREDEFINED) { + /* Current SUN FSK drivers only implement legacy IEEE 802.15.4g + * 863 MHz (Europe) and 915 MHz (US ISM) bands, see IEEE + * 802.15.4g, section 5.1, table 0. Once more bands are required + * we need to request the currently active frequency band from + * the driver. + */ + return IEEE802154_PHY_A_TURNAROUND_TIME_1MS( + IEEE802154_PHY_SUN_FSK_863MHZ_915MHZ_SYMBOL_PERIOD_NS); + } + + return IEEE802154_PHY_A_TURNAROUND_TIME_DEFAULT; +} /** - * The number of slots contained in any superframe, see section 8.4.2, - * table 8-93, aNumSuperframeSlots. + * @brief Verify if the given channel lies within the allowed range of available + * channels of the driver's currently selected channel page. + * + * @param iface pointer to the IEEE 802.15.4 interface + * @param channel The channel to verify or IEEE802154_NO_CHANNEL + * + * @returns true if the channel is available, false otherwise */ -#define IEEE802154_MAC_A_NUM_SUPERFRAME_SLOTS 16U +bool ieee802154_radio_verify_channel(struct net_if *iface, uint16_t channel); /** - * The number of PHY symbols forming a superframe when the superframe order is - * equal to zero, see section 8.4.2, table 8-93, aBaseSuperframeDuration. + * @brief Counts all available channels of the driver's currently selected + * channel page. + * + * @param iface pointer to the IEEE 802.15.4 interface + * + * @returns The number of available channels. */ -#define IEEE802154_MAC_A_BASE_SUPERFRAME_DURATION \ - (IEEE802154_MAC_A_BASE_SLOT_DURATION * IEEE802154_MAC_A_NUM_SUPERFRAME_SLOTS) +uint16_t ieee802154_radio_number_of_channels(struct net_if *iface); /** * @brief Calculates the MAC's superframe duration (see section 8.4.2, @@ -392,22 +484,18 @@ static inline bool ieee802154_radio_verify_channel(struct net_if *iface, uint16_ * @details The number of symbols forming a superframe when the superframe order * is equal to zero. * - * @param iface The interface for which the base superframe duration should be - * calculated. + * @param iface pointer to the IEEE 802.15.4 interface * * @returns The base superframe duration for the given interface in microseconds. */ static inline uint32_t ieee802154_get_a_base_superframe_duration(struct net_if *iface) { - return IEEE802154_MAC_A_BASE_SUPERFRAME_DURATION * - ieee802154_radio_get_symbol_period_us(iface); -} + struct ieee802154_context *ctx = net_if_l2_data(iface); -/** - * Default macResponseWaitTime in multiples of aBaseSuperframeDuration as - * defined in section 8.4.3.1, table 8-94. - */ -#define IEEE802154_MAC_RESONSE_WAIT_TIME_DEFAULT 32U + return ieee802154_radio_get_multiple_of_symbol_period( + iface, ctx->channel, IEEE802154_MAC_A_BASE_SUPERFRAME_DURATION) / + NSEC_PER_USEC; +} /** * @brief Retrieves macResponseWaitTime, see section 8.4.3.1, table 8-94, @@ -423,16 +511,15 @@ static inline uint32_t ieee802154_get_a_base_superframe_duration(struct net_if * * * @note Currently this parameter is read-only and uses the specified default of 32. * - * @param iface The interface for which the response wait time should be calculated. + * @param iface pointer to the IEEE 802.15.4 interface * * @returns The response wait time for the given interface in microseconds. */ static inline uint32_t ieee802154_get_response_wait_time_us(struct net_if *iface) { /* TODO: Make this parameter configurable. */ - return IEEE802154_MAC_RESONSE_WAIT_TIME_DEFAULT * + return IEEE802154_MAC_RESPONSE_WAIT_TIME_DEFAULT * ieee802154_get_a_base_superframe_duration(iface); } - #endif /* __IEEE802154_UTILS_H__ */ diff --git a/subsys/net/l2/openthread/Kconfig b/subsys/net/l2/openthread/Kconfig index f8803b316de..98113975797 100644 --- a/subsys/net/l2/openthread/Kconfig +++ b/subsys/net/l2/openthread/Kconfig @@ -151,7 +151,6 @@ endmenu # "Zephyr optimizations" config OPENTHREAD_SHELL bool "OpenThread shell" depends on SHELL - default y config MBEDTLS_PROMPTLESS bool @@ -289,6 +288,14 @@ config OPENTHREAD_TMF_ADDRESS_CACHE_ENTRIES help The number of EID-to-RLOC cache entries. +config OPENTHREAD_TMF_ADDRESS_CACHE_MAX_SNOOP_ENTRIES + int "The maximum number of EID-to-RLOC cache entries" + default 2 + help + The maximum number of EID-to-RLOC cache entries that can be used for + "snoop optimization" where an entry is created by inspecting a received + message. + config OPENTHREAD_LOG_PREPEND_LEVEL_ENABLE bool "Prepending the log level to all OpenThread log messages" help diff --git a/subsys/net/l2/ppp/Kconfig b/subsys/net/l2/ppp/Kconfig index 416fe9cf70d..db47968c512 100644 --- a/subsys/net/l2/ppp/Kconfig +++ b/subsys/net/l2/ppp/Kconfig @@ -2,8 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 menuconfig NET_L2_PPP - bool "Point-to-point (PPP) support [EXPERIMENTAL]" - select EXPERIMENTAL + bool "Point-to-point (PPP) support" select NET_MGMT select NET_MGMT_EVENT help diff --git a/subsys/net/l2/ppp/fsm.c b/subsys/net/l2/ppp/fsm.c index 7e2c739e779..1f64de14f13 100644 --- a/subsys/net/l2/ppp/fsm.c +++ b/subsys/net/l2/ppp/fsm.c @@ -12,7 +12,7 @@ LOG_MODULE_DECLARE(net_l2_ppp, CONFIG_NET_L2_PPP_LOG_LEVEL); #include #include -#include +#include #include "net_private.h" diff --git a/subsys/net/l2/ppp/lcp.c b/subsys/net/l2/ppp/lcp.c index 0d46b5b66fa..9e54f631f48 100644 --- a/subsys/net/l2/ppp/lcp.c +++ b/subsys/net/l2/ppp/lcp.c @@ -179,6 +179,10 @@ static void lcp_down(struct ppp_fsm *fsm) ppp_link_down(ctx); + if (!net_if_is_carrier_ok(ctx->iface)) { + return; + } + ppp_change_phase(ctx, PPP_ESTABLISH); } diff --git a/subsys/net/l2/ppp/ppp_l2.c b/subsys/net/l2/ppp/ppp_l2.c index b949c491406..e2bf29274cc 100644 --- a/subsys/net/l2/ppp/ppp_l2.c +++ b/subsys/net/l2/ppp/ppp_l2.c @@ -30,10 +30,10 @@ static K_FIFO_DEFINE(tx_queue); #define THREAD_PRIORITY K_PRIO_PREEMPT(CONFIG_NET_L2_PPP_THREAD_PRIO) #endif -static void tx_handler(void); +static void tx_handler(void *p1, void *p2, void *p3); static K_THREAD_DEFINE(tx_handler_thread, CONFIG_NET_L2_PPP_TX_STACK_SIZE, - (k_thread_entry_t)tx_handler, NULL, NULL, NULL, + tx_handler, NULL, NULL, NULL, THREAD_PRIORITY, 0, 0); static const struct ppp_protocol_handler *ppp_lcp; @@ -344,8 +344,12 @@ void ppp_queue_pkt(struct net_pkt *pkt) k_fifo_put(&tx_queue, pkt); } -static void tx_handler(void) +static void tx_handler(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct net_pkt *pkt; int ret; diff --git a/subsys/net/l2/virtual/virtual.c b/subsys/net/l2/virtual/virtual.c index 2efd365b0cf..ad50eb12041 100644 --- a/subsys/net/l2/virtual/virtual.c +++ b/subsys/net/l2/virtual/virtual.c @@ -13,7 +13,7 @@ LOG_MODULE_REGISTER(net_virtual, CONFIG_NET_L2_VIRTUAL_LOG_LEVEL); #include #include #include -#include +#include #include "net_private.h" diff --git a/subsys/net/l2/wifi/wifi_mgmt.c b/subsys/net/l2/wifi/wifi_mgmt.c index 4a9c3d8a63a..6e0cb761dbf 100644 --- a/subsys/net/l2/wifi/wifi_mgmt.c +++ b/subsys/net/l2/wifi/wifi_mgmt.c @@ -17,7 +17,7 @@ LOG_MODULE_REGISTER(net_wifi_mgmt, CONFIG_NET_L2_WIFI_MGMT_LOG_LEVEL); #include #endif /* CONFIG_WIFI_NM */ -const char * const wifi_security_txt(enum wifi_security_type security) +const char *wifi_security_txt(enum wifi_security_type security) { switch (security) { case WIFI_SECURITY_TYPE_NONE: @@ -42,7 +42,7 @@ const char * const wifi_security_txt(enum wifi_security_type security) } } -const char * const wifi_mfp_txt(enum wifi_mfp_options mfp) +const char *wifi_mfp_txt(enum wifi_mfp_options mfp) { switch (mfp) { case WIFI_MFP_DISABLE: @@ -57,7 +57,7 @@ const char * const wifi_mfp_txt(enum wifi_mfp_options mfp) } } -const char * const wifi_band_txt(enum wifi_frequency_bands band) +const char *wifi_band_txt(enum wifi_frequency_bands band) { switch (band) { case WIFI_FREQ_BAND_2_4_GHZ: @@ -72,7 +72,7 @@ const char * const wifi_band_txt(enum wifi_frequency_bands band) } } -const char * const wifi_state_txt(enum wifi_iface_state state) +const char *wifi_state_txt(enum wifi_iface_state state) { switch (state) { case WIFI_STATE_DISCONNECTED: @@ -101,7 +101,7 @@ const char * const wifi_state_txt(enum wifi_iface_state state) } } -const char * const wifi_mode_txt(enum wifi_iface_mode mode) +const char *wifi_mode_txt(enum wifi_iface_mode mode) { switch (mode) { case WIFI_MODE_INFRA: @@ -122,7 +122,7 @@ const char * const wifi_mode_txt(enum wifi_iface_mode mode) } } -const char * const wifi_link_mode_txt(enum wifi_link_mode link_mode) +const char *wifi_link_mode_txt(enum wifi_link_mode link_mode) { switch (link_mode) { case WIFI_0: @@ -149,7 +149,7 @@ const char * const wifi_link_mode_txt(enum wifi_link_mode link_mode) } } -const char * const wifi_ps_txt(enum wifi_ps ps_name) +const char *wifi_ps_txt(enum wifi_ps ps_name) { switch (ps_name) { case WIFI_PS_DISABLED: @@ -161,7 +161,7 @@ const char * const wifi_ps_txt(enum wifi_ps ps_name) } } -const char * const wifi_ps_mode_txt(enum wifi_ps_mode ps_mode) +const char *wifi_ps_mode_txt(enum wifi_ps_mode ps_mode) { switch (ps_mode) { case WIFI_PS_MODE_LEGACY: @@ -173,7 +173,7 @@ const char * const wifi_ps_mode_txt(enum wifi_ps_mode ps_mode) } } -const char * const wifi_twt_operation_txt(enum wifi_twt_operation twt_operation) +const char *wifi_twt_operation_txt(enum wifi_twt_operation twt_operation) { switch (twt_operation) { case WIFI_TWT_SETUP: @@ -185,7 +185,7 @@ const char * const wifi_twt_operation_txt(enum wifi_twt_operation twt_operation) } } -const char * const wifi_twt_negotiation_type_txt(enum wifi_twt_negotiation_type twt_negotiation) +const char *wifi_twt_negotiation_type_txt(enum wifi_twt_negotiation_type twt_negotiation) { switch (twt_negotiation) { case WIFI_TWT_INDIVIDUAL: @@ -199,7 +199,7 @@ const char * const wifi_twt_negotiation_type_txt(enum wifi_twt_negotiation_type } } -const char * const wifi_twt_setup_cmd_txt(enum wifi_twt_setup_cmd twt_setup) +const char *wifi_twt_setup_cmd_txt(enum wifi_twt_setup_cmd twt_setup) { switch (twt_setup) { case WIFI_TWT_SETUP_CMD_REQUEST: @@ -223,7 +223,7 @@ const char * const wifi_twt_setup_cmd_txt(enum wifi_twt_setup_cmd twt_setup) } } -const char * const wifi_ps_wakeup_mode_txt(enum wifi_ps_wakeup_mode ps_wakeup_mode) +const char *wifi_ps_wakeup_mode_txt(enum wifi_ps_wakeup_mode ps_wakeup_mode) { switch (ps_wakeup_mode) { case WIFI_PS_WAKEUP_MODE_DTIM: diff --git a/subsys/net/lib/CMakeLists.txt b/subsys/net/lib/CMakeLists.txt index 6c045b58692..756adb41341 100644 --- a/subsys/net/lib/CMakeLists.txt +++ b/subsys/net/lib/CMakeLists.txt @@ -13,6 +13,7 @@ add_subdirectory_ifdef(CONFIG_NET_SOCKETS sockets) add_subdirectory_ifdef(CONFIG_TLS_CREDENTIALS tls_credentials) add_subdirectory_ifdef(CONFIG_NET_CAPTURE capture) add_subdirectory_ifdef(CONFIG_NET_ZPERF zperf) +add_subdirectory_ifdef(CONFIG_NET_SHELL shell) if (CONFIG_DNS_RESOLVER OR CONFIG_MDNS_RESPONDER diff --git a/subsys/net/lib/coap/CMakeLists.txt b/subsys/net/lib/coap/CMakeLists.txt index 39ef8196fbb..c0a555082b2 100644 --- a/subsys/net/lib/coap/CMakeLists.txt +++ b/subsys/net/lib/coap/CMakeLists.txt @@ -10,3 +10,11 @@ zephyr_sources_ifdef(CONFIG_COAP zephyr_sources_ifdef(CONFIG_COAP_CLIENT coap_client.c ) + +zephyr_sources_ifdef(CONFIG_COAP_SERVER + coap_server.c +) + +zephyr_sources_ifdef(CONFIG_COAP_SERVER_SHELL + coap_server_shell.c +) diff --git a/subsys/net/lib/coap/Kconfig b/subsys/net/lib/coap/Kconfig index e7587ab21ac..8e62983ea72 100644 --- a/subsys/net/lib/coap/Kconfig +++ b/subsys/net/lib/coap/Kconfig @@ -89,6 +89,12 @@ config COAP_URI_WILDCARD This option enables MQTT-style wildcards in path. Disable it if resource path may contain plus or hash symbol. +config COAP_OBSERVER_EVENTS + bool "CoAP resource observer events" + help + This option enables to register a callback function to CoAP resources + that will be called when adding/removing observers. + config COAP_KEEP_USER_DATA bool "Keeping user data in the CoAP packet" help @@ -147,6 +153,105 @@ config COAP_CLIENT_MAX_REQUESTS endif # COAP_CLIENT +config COAP_SERVER + bool "CoAP server support [EXPERIMENTAL]" + select EXPERIMENTAL + select NET_SOCKETS + select NET_SOCKETPAIR + help + This option enables the API for CoAP-services to register resources. + +if COAP_SERVER + +config COAP_SERVER_STACK_SIZE + int "CoAP server thread stack size" + default 4096 + help + CoAP server thread stack size for processing RX/TX events. + +config COAP_SERVER_BLOCK_SIZE + int "CoAP server block-wise transfer size" + default 256 + range 64 1024 + help + CoAP block size used by CoAP server resources when performing block-wise + transfers. Possible values: 64, 128, 256, 512 and 1024. + +config COAP_SERVER_MESSAGE_SIZE + int "CoAP server message payload size" + default COAP_SERVER_BLOCK_SIZE + help + CoAP server message payload size. Can't be smaller than COAP_SERVER_BLOCK_SIZE. + +config COAP_SERVER_MESSAGE_OPTIONS + int "CoAP server message options" + default 16 + help + CoAP server message maximum number of options to parse. + +config COAP_SERVER_WELL_KNOWN_CORE + bool "CoAP server support ./well-known/core service" + default y + help + Enable responding to the ./well-known/core service resource. + +config COAP_SERVICE_PENDING_MESSAGES + int "CoAP service pending messages" + default 10 + help + Maximum number of pending CoAP messages to retransmit per active service. + +config COAP_SERVICE_PENDING_RETRANSMITS + int "CoAP retransmit count" + default 2 + help + Maximum number of retries to send a pending message. + +config COAP_SERVICE_OBSERVERS + int "CoAP service observers" + default 3 + help + Maximum number of CoAP observers per active service. + +choice COAP_SERVER_PENDING_ALLOCATOR + prompt "Pending data allocator" + default COAP_SERVER_PENDING_ALLOCATOR_STATIC + +config COAP_SERVER_PENDING_ALLOCATOR_NONE + bool "No pending packets" + help + Never allocate data for pending requests, this disables retransmits for confirmable + packets. + +config COAP_SERVER_PENDING_ALLOCATOR_STATIC + bool "Static reserved memory" + help + Static memory will be reserved for pending messages. The total size is equal to + COAP_SERVER_PENDING_ALLOCATOR_STATIC_BLOCKS * COAP_SERVER_MESSAGE_SIZE. + +config COAP_SERVER_PENDING_ALLOCATOR_SYSTEM_HEAP + bool "System heap allocator" + depends on HEAP_MEM_POOL_SIZE > 0 + help + Use k_malloc/k_free for pending data. + +endchoice + +config COAP_SERVER_PENDING_ALLOCATOR_STATIC_BLOCKS + int "Number of pending data blocks" + default COAP_SERVICE_PENDING_MESSAGES + depends on COAP_SERVER_PENDING_ALLOCATOR_STATIC + help + The number of data blocks to reserve for pending messages to retransmit. + +config COAP_SERVER_SHELL + bool "CoAP service shell commands" + depends on SHELL + help + Enable CoAP service shell commands. + +endif + module = COAP module-dep = NET_LOG module-str = Log level for CoAP diff --git a/subsys/net/lib/coap/coap.c b/subsys/net/lib/coap/coap.c index e3427844bb5..9fe62730b47 100644 --- a/subsys/net/lib/coap/coap.c +++ b/subsys/net/lib/coap/coap.c @@ -12,7 +12,7 @@ LOG_MODULE_REGISTER(net_coap, CONFIG_COAP_LOG_LEVEL); #include #include #include -#include +#include #include #include @@ -658,10 +658,10 @@ static int remove_middle_option(struct coap_packet *cpkt, } int coap_packet_remove_option(struct coap_packet *cpkt, uint16_t code) { - uint16_t offset = cpkt->hdr_len; + uint16_t offset = 0; uint16_t opt_delta = 0; uint16_t opt_len = 0; - uint16_t previous_offset = cpkt->hdr_len; + uint16_t previous_offset = 0; uint16_t previous_code = 0; struct coap_option option; int r; @@ -678,6 +678,9 @@ int coap_packet_remove_option(struct coap_packet *cpkt, uint16_t code) return 0; } + offset = cpkt->hdr_len; + previous_offset = cpkt->hdr_len; + /* Find the requested option */ while (offset < cpkt->hdr_len + cpkt->opt_len) { r = parse_option(cpkt->data, offset, &offset, cpkt->hdr_len + cpkt->opt_len, @@ -950,6 +953,16 @@ static uint8_t __coap_header_get_code(const struct coap_packet *cpkt) return cpkt->data[1]; } +int coap_header_set_code(const struct coap_packet *cpkt, uint8_t code) +{ + if (!cpkt || !cpkt->data) { + return -EINVAL; + } + + cpkt->data[1] = code; + return 0; +} + uint8_t coap_header_get_token(const struct coap_packet *cpkt, uint8_t *token) { uint8_t tkl; @@ -1046,10 +1059,9 @@ const uint8_t *coap_packet_get_payload(const struct coap_packet *cpkt, uint16_t cpkt->data + cpkt->hdr_len + cpkt->opt_len + 1; } -static bool uri_path_eq(const struct coap_packet *cpkt, - const char * const *path, - struct coap_option *options, - uint8_t opt_num) +bool coap_uri_path_match(const char * const *path, + struct coap_option *options, + uint8_t opt_num) { uint8_t i; uint8_t j = 0U; @@ -1130,36 +1142,35 @@ static inline bool is_empty_message(const struct coap_packet *cpkt) return __coap_header_get_code(cpkt) == COAP_CODE_EMPTY; } -static bool is_request(const struct coap_packet *cpkt) +bool coap_packet_is_request(const struct coap_packet *cpkt) { uint8_t code = coap_header_get_code(cpkt); return !(code & ~COAP_REQUEST_MASK); } -int coap_handle_request(struct coap_packet *cpkt, - struct coap_resource *resources, - struct coap_option *options, - uint8_t opt_num, - struct sockaddr *addr, socklen_t addr_len) +int coap_handle_request_len(struct coap_packet *cpkt, + struct coap_resource *resources, + size_t resources_len, + struct coap_option *options, + uint8_t opt_num, + struct sockaddr *addr, socklen_t addr_len) { - struct coap_resource *resource; - - if (!is_request(cpkt)) { + if (!coap_packet_is_request(cpkt)) { return 0; } /* FIXME: deal with hierarchical resources */ - for (resource = resources; resource && resource->path; resource++) { + for (size_t i = 0; i < resources_len; i++) { coap_method_t method; uint8_t code; - if (!uri_path_eq(cpkt, resource->path, options, opt_num)) { + if (!coap_uri_path_match(resources[i].path, options, opt_num)) { continue; } code = coap_header_get_code(cpkt); - if (method_from_code(resource, code, &method) < 0) { + if (method_from_code(&resources[i], code, &method) < 0) { return -ENOTSUP; } @@ -1167,13 +1178,29 @@ int coap_handle_request(struct coap_packet *cpkt, return -EPERM; } - return method(resource, cpkt, addr, addr_len); + return method(&resources[i], cpkt, addr, addr_len); } - NET_DBG("%d", __LINE__); return -ENOENT; } +int coap_handle_request(struct coap_packet *cpkt, + struct coap_resource *resources, + struct coap_option *options, + uint8_t opt_num, + struct sockaddr *addr, socklen_t addr_len) +{ + size_t resources_len = 0; + struct coap_resource *resource; + + for (resource = resources; resource && resource->path; resource++) { + resources_len++; + } + + return coap_handle_request_len(cpkt, resources, resources_len, options, opt_num, addr, + addr_len); +} + int coap_block_transfer_init(struct coap_block_context *ctx, enum coap_block_size block_size, size_t total_size) @@ -1195,7 +1222,7 @@ int coap_block_transfer_init(struct coap_block_context *ctx, int coap_append_descriptive_block_option(struct coap_packet *cpkt, struct coap_block_context *ctx) { - if (is_request(cpkt)) { + if (coap_packet_is_request(cpkt)) { return coap_append_block1_option(cpkt, ctx); } else { return coap_append_block2_option(cpkt, ctx); @@ -1204,7 +1231,7 @@ int coap_append_descriptive_block_option(struct coap_packet *cpkt, struct coap_b bool coap_has_descriptive_block_option(struct coap_packet *cpkt) { - if (is_request(cpkt)) { + if (coap_packet_is_request(cpkt)) { return coap_get_option_int(cpkt, COAP_OPTION_BLOCK1) >= 0; } else { return coap_get_option_int(cpkt, COAP_OPTION_BLOCK2) >= 0; @@ -1213,7 +1240,7 @@ bool coap_has_descriptive_block_option(struct coap_packet *cpkt) int coap_remove_descriptive_block_option(struct coap_packet *cpkt) { - if (is_request(cpkt)) { + if (coap_packet_is_request(cpkt)) { return coap_packet_remove_option(cpkt, COAP_OPTION_BLOCK1); } else { return coap_packet_remove_option(cpkt, COAP_OPTION_BLOCK2); @@ -1227,7 +1254,7 @@ int coap_append_block1_option(struct coap_packet *cpkt, unsigned int val = 0U; int r; - if (is_request(cpkt)) { + if (coap_packet_is_request(cpkt)) { SET_BLOCK_SIZE(val, ctx->block_size); SET_MORE(val, ctx->current + bytes < ctx->total_size); SET_NUM(val, ctx->current / bytes); @@ -1247,7 +1274,7 @@ int coap_append_block2_option(struct coap_packet *cpkt, int r, val = 0; uint16_t bytes = coap_block_size_to_bytes(ctx->block_size); - if (is_request(cpkt)) { + if (coap_packet_is_request(cpkt)) { SET_BLOCK_SIZE(val, ctx->block_size); SET_NUM(val, ctx->current / bytes); } else { @@ -1455,7 +1482,7 @@ int coap_update_from_block(const struct coap_packet *cpkt, size1 = coap_get_option_int(cpkt, COAP_OPTION_SIZE1); size2 = coap_get_option_int(cpkt, COAP_OPTION_SIZE2); - if (is_request(cpkt)) { + if (coap_packet_is_request(cpkt)) { r = update_control_block2(ctx, block2, size2); if (r) { return r; @@ -1510,7 +1537,7 @@ size_t coap_next_block(const struct coap_packet *cpkt, enum coap_option_num option; int ret; - option = is_request(cpkt) ? COAP_OPTION_BLOCK1 : COAP_OPTION_BLOCK2; + option = coap_packet_is_request(cpkt) ? COAP_OPTION_BLOCK1 : COAP_OPTION_BLOCK2; ret = coap_next_block_for_option(cpkt, ctx, option); return MAX(ret, 0); @@ -1713,7 +1740,7 @@ struct coap_reply *coap_response_received( uint8_t tkl; size_t i; - if (!is_empty_message(response) && is_request(response)) { + if (!is_empty_message(response) && coap_packet_is_request(response)) { /* Request can't be response */ return NULL; } @@ -1829,13 +1856,28 @@ bool coap_register_observer(struct coap_resource *resource, resource->age = 2; } +#ifdef CONFIG_COAP_OBSERVER_EVENTS + if (resource->observer_event_handler) { + resource->observer_event_handler(resource, observer, COAP_OBSERVER_ADDED); + } +#endif + return first; } -void coap_remove_observer(struct coap_resource *resource, +bool coap_remove_observer(struct coap_resource *resource, struct coap_observer *observer) { - sys_slist_find_and_remove(&resource->observers, &observer->list); + if (!sys_slist_find_and_remove(&resource->observers, &observer->list)) { + return false; + } + +#ifdef CONFIG_COAP_OBSERVER_EVENTS + if (resource->observer_event_handler) { + resource->observer_event_handler(resource, observer, COAP_OBSERVER_REMOVED); + } +#endif + return true; } static bool sockaddr_equal(const struct sockaddr *a, @@ -1874,6 +1916,28 @@ static bool sockaddr_equal(const struct sockaddr *a, return false; } +struct coap_observer *coap_find_observer( + struct coap_observer *observers, size_t len, + const struct sockaddr *addr, + const uint8_t *token, uint8_t token_len) +{ + if (token_len == 0U || token_len > COAP_TOKEN_MAX_LEN) { + return NULL; + } + + for (size_t i = 0; i < len; i++) { + struct coap_observer *o = &observers[i]; + + if (o->tkl == token_len && + memcmp(o->token, token, token_len) == 0 && + sockaddr_equal(&o->addr, addr)) { + return o; + } + } + + return NULL; +} + struct coap_observer *coap_find_observer_by_addr( struct coap_observer *observers, size_t len, const struct sockaddr *addr) @@ -1891,6 +1955,25 @@ struct coap_observer *coap_find_observer_by_addr( return NULL; } +struct coap_observer *coap_find_observer_by_token( + struct coap_observer *observers, size_t len, + const uint8_t *token, uint8_t token_len) +{ + if (token_len == 0U || token_len > COAP_TOKEN_MAX_LEN) { + return NULL; + } + + for (size_t i = 0; i < len; i++) { + struct coap_observer *o = &observers[i]; + + if (o->tkl == token_len && memcmp(o->token, token, token_len) == 0) { + return o; + } + } + + return NULL; +} + /** * @brief Internal initialization function for CoAP library. * diff --git a/subsys/net/lib/coap/coap_client.c b/subsys/net/lib/coap/coap_client.c index e78aafd6829..a947b15ae8e 100644 --- a/subsys/net/lib/coap/coap_client.c +++ b/subsys/net/lib/coap/coap_client.c @@ -215,6 +215,10 @@ static int coap_client_init_request(struct coap_client *client, coap_block_transfer_init(&internal_req->send_blk_ctx, coap_client_default_block_size(), req->len); + /* Generate request tag */ + uint8_t *tag = coap_next_token(); + + memcpy(internal_req->request_tag, tag, COAP_TOKEN_MAX_LEN); } ret = coap_append_block1_option(&internal_req->request, &internal_req->send_blk_ctx); @@ -223,6 +227,15 @@ static int coap_client_init_request(struct coap_client *client, LOG_ERR("Failed to append block1 option"); goto out; } + + ret = coap_packet_append_option(&internal_req->request, + COAP_OPTION_REQUEST_TAG, internal_req->request_tag, + COAP_TOKEN_MAX_LEN); + + if (ret < 0) { + LOG_ERR("Failed to append request tag option"); + goto out; + } } ret = coap_packet_append_payload_marker(&internal_req->request); @@ -319,6 +332,17 @@ int coap_client_req(struct coap_client *client, int sock, const struct sockaddr goto out; } + if (client->send_echo) { + ret = coap_packet_append_option(&internal_req->request, COAP_OPTION_ECHO, + client->echo_option.value, client->echo_option.len); + if (ret < 0) { + LOG_ERR("Failed to append echo option"); + k_mutex_unlock(&client->send_mutex); + goto out; + } + client->send_echo = false; + } + ret = coap_client_schedule_poll(client, sock, req, internal_req); if (ret < 0) { LOG_ERR("Failed to schedule polling"); @@ -591,6 +615,11 @@ struct coap_client_internal_request *get_request_with_token(struct coap_client * return NULL; } +static bool find_echo_option(const struct coap_packet *response, struct coap_option *option) +{ + return coap_find_options(response, COAP_OPTION_ECHO, option, 1); +} + static int handle_response(struct coap_client *client, const struct coap_packet *response) { int ret = 0; @@ -638,6 +667,60 @@ static int handle_response(struct coap_client *client, const struct coap_packet return 1; } + /* Received echo option */ + if (find_echo_option(response, &client->echo_option)) { + /* Resend request with echo option */ + if (response_code == COAP_RESPONSE_CODE_UNAUTHORIZED) { + k_mutex_lock(&client->send_mutex, K_FOREVER); + + ret = coap_client_init_request(client, &internal_req->coap_request, + internal_req, false); + + if (ret < 0) { + LOG_ERR("Error creating a CoAP request"); + k_mutex_unlock(&client->send_mutex); + goto fail; + } + + ret = coap_packet_append_option(&internal_req->request, COAP_OPTION_ECHO, + client->echo_option.value, + client->echo_option.len); + if (ret < 0) { + LOG_ERR("Failed to append echo option"); + k_mutex_unlock(&client->send_mutex); + goto fail; + } + + if (coap_header_get_type(&internal_req->request) == COAP_TYPE_CON) { + ret = coap_pending_init(&internal_req->pending, + &internal_req->request, &client->address, + internal_req->retry_count); + if (ret < 0) { + LOG_ERR("Error creating pending"); + k_mutex_unlock(&client->send_mutex); + goto fail; + } + + coap_pending_cycle(&internal_req->pending); + } + + ret = send_request(client->fd, internal_req->request.data, + internal_req->request.offset, 0, &client->address, + client->socklen); + k_mutex_unlock(&client->send_mutex); + + if (ret < 0) { + LOG_ERR("Error sending a CoAP request"); + goto fail; + } else { + return 1; + } + } else { + /* Send echo in next request */ + client->send_echo = true; + } + } + /* Send ack for CON */ if (response_type == COAP_TYPE_CON) { /* CON response is always a separate response, respond with empty ACK. */ diff --git a/subsys/net/lib/coap/coap_link_format.c b/subsys/net/lib/coap/coap_link_format.c index 10c72d62c9e..a3ea175b2df 100644 --- a/subsys/net/lib/coap/coap_link_format.c +++ b/subsys/net/lib/coap/coap_link_format.c @@ -432,10 +432,11 @@ int clear_more_flag(struct coap_packet *cpkt) return 0; } -int coap_well_known_core_get(struct coap_resource *resource, - struct coap_packet *request, - struct coap_packet *response, - uint8_t *data, uint16_t len) +int coap_well_known_core_get_len(struct coap_resource *resources, + size_t resources_len, + struct coap_packet *request, + struct coap_packet *response, + uint8_t *data, uint16_t len) { static struct coap_block_context ctx; struct coap_option query; @@ -446,9 +447,9 @@ int coap_well_known_core_get(struct coap_resource *resource, uint16_t id; uint8_t tkl; int r; - bool more = false; + bool more = false, first = true; - if (!resource || !request || !response || !data || !len) { + if (!resources || !request || !response || !data || !len) { return -EINVAL; } @@ -505,29 +506,31 @@ int coap_well_known_core_get(struct coap_resource *resource, offset = 0; remaining = coap_block_size_to_bytes(ctx.block_size); - while (resource++ && resource->path) { + for (size_t i = 0; i < resources_len; ++i) { if (!remaining) { more = true; break; } - if (!match_queries_resource(resource, &query, num_queries)) { + if (!match_queries_resource(&resources[i], &query, num_queries)) { continue; } - r = format_resource(resource, response, &remaining, &offset, - ctx.current, &more); - if (r < 0) { - goto end; - } - - if ((resource + 1) && (resource + 1)->path) { + if (first) { + first = false; + } else { r = append_to_coap_pkt(response, ",", 1, &remaining, &offset, ctx.current); if (!r) { goto end; } } + + r = format_resource(&resources[i], response, &remaining, &offset, + ctx.current, &more); + if (r < 0) { + goto end; + } } /* Offset is the total size now, but block2 option is already @@ -631,10 +634,11 @@ static int format_resource(const struct coap_resource *resource, return format_attributes(attributes, response); } -int coap_well_known_core_get(struct coap_resource *resource, - struct coap_packet *request, - struct coap_packet *response, - uint8_t *data, uint16_t len) +int coap_well_known_core_get_len(struct coap_resource *resources, + size_t resources_len, + const struct coap_packet *request, + struct coap_packet *response, + uint8_t *data, uint16_t data_len) { struct coap_option query; uint8_t token[COAP_TOKEN_MAX_LEN]; @@ -642,8 +646,9 @@ int coap_well_known_core_get(struct coap_resource *resource, uint8_t tkl; uint8_t num_queries; int r; + bool first = true; - if (!resource || !request || !response || !data || !len) { + if (!resources || !request || !response || !data || !data_len) { return -EINVAL; } @@ -660,7 +665,7 @@ int coap_well_known_core_get(struct coap_resource *resource, num_queries = r; - r = coap_packet_init(response, data, len, COAP_VERSION_1, COAP_TYPE_ACK, + r = coap_packet_init(response, data, data_len, COAP_VERSION_1, COAP_TYPE_ACK, tkl, token, COAP_RESPONSE_CODE_CONTENT, id); if (r < 0) { return r; @@ -677,28 +682,50 @@ int coap_well_known_core_get(struct coap_resource *resource, return -EINVAL; } - while (resource++ && resource->path) { - if (!match_queries_resource(resource, &query, num_queries)) { + for (size_t i = 0; i < resources_len; ++i) { + if (!match_queries_resource(&resources[i], &query, num_queries)) { continue; } - r = format_resource(resource, response); - if (r < 0) { - return r; - } - - if ((resource + 1)->path) { + if (first) { + first = false; + } else { r = append_u8(response, (uint8_t) ','); if (!r) { return -ENOMEM; } } + + r = format_resource(&resources[i], response); + if (r < 0) { + return r; + } } return 0; } #endif +int coap_well_known_core_get(struct coap_resource *resource, + const struct coap_packet *request, + struct coap_packet *response, + uint8_t *data, uint16_t data_len) +{ + struct coap_resource *resources = resource + 1; + size_t resources_len = 0; + + if (resource == NULL) { + return -EINVAL; + } + + while (resources[resources_len].path) { + resources_len++; + } + + return coap_well_known_core_get_len(resources, resources_len, request, response, data, + data_len); +} + /* Exposing some of the APIs to CoAP unit tests in tests/net/lib/coap */ #if defined(CONFIG_COAP_TEST_API_ENABLE) bool _coap_match_path_uri(const char * const *path, diff --git a/subsys/net/lib/coap/coap_server.c b/subsys/net/lib/coap/coap_server.c new file mode 100644 index 00000000000..4b4f1719f46 --- /dev/null +++ b/subsys/net/lib/coap/coap_server.c @@ -0,0 +1,777 @@ +/* + * Copyright (c) 2023 Basalte bv + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +LOG_MODULE_DECLARE(net_coap, CONFIG_COAP_LOG_LEVEL); + +#include + +#include +#include +#include +#include +#include +#ifdef CONFIG_ARCH_POSIX +#include +#else +#include +#endif + +#if defined(CONFIG_NET_TC_THREAD_COOPERATIVE) +/* Lowest priority cooperative thread */ +#define THREAD_PRIORITY K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1) +#else +#define THREAD_PRIORITY K_PRIO_PREEMPT(CONFIG_NUM_PREEMPT_PRIORITIES - 1) +#endif + +#define ADDRLEN(sock) \ + (((struct sockaddr *)sock)->sa_family == AF_INET ? \ + sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)) + +/* Shortened defines */ +#define MAX_OPTIONS CONFIG_COAP_SERVER_MESSAGE_OPTIONS +#define MAX_PENDINGS CONFIG_COAP_SERVICE_PENDING_MESSAGES +#define MAX_OBSERVERS CONFIG_COAP_SERVICE_OBSERVERS +#define MAX_POLL_FD CONFIG_NET_SOCKETS_POLL_MAX + +BUILD_ASSERT(CONFIG_NET_SOCKETS_POLL_MAX > 0, "CONFIG_NET_SOCKETS_POLL_MAX can't be 0"); + +static K_MUTEX_DEFINE(lock); +static int control_socks[2]; + +#if defined(CONFIG_COAP_SERVER_PENDING_ALLOCATOR_STATIC) +K_MEM_SLAB_DEFINE_STATIC(pending_data, CONFIG_COAP_SERVER_MESSAGE_SIZE, + CONFIG_COAP_SERVER_PENDING_ALLOCATOR_STATIC_BLOCKS, 4); +#endif + +static inline void *coap_server_alloc(size_t len) +{ +#if defined(CONFIG_COAP_SERVER_PENDING_ALLOCATOR_STATIC) + void *ptr; + int ret; + + if (len > CONFIG_COAP_SERVER_MESSAGE_SIZE) { + return NULL; + } + + ret = k_mem_slab_alloc(&pending_data, &ptr, K_NO_WAIT); + if (ret < 0) { + return NULL; + } + + return ptr; +#elif defined(CONFIG_COAP_SERVER_PENDING_ALLOCATOR_SYSTEM_HEAP) + return k_malloc(len); +#else + ARG_UNUSED(len); + + return NULL; +#endif +} + +static inline void coap_server_free(void *ptr) +{ +#if defined(CONFIG_COAP_SERVER_PENDING_ALLOCATOR_STATIC) + k_mem_slab_free(&pending_data, ptr); +#elif defined(CONFIG_COAP_SERVER_PENDING_ALLOCATOR_SYSTEM_HEAP) + k_free(ptr); +#else + ARG_UNUSED(ptr); +#endif +} + +static int coap_service_remove_observer(const struct coap_service *service, + struct coap_resource *resource, + const struct sockaddr *addr, + const uint8_t *token, uint8_t tkl) +{ + struct coap_observer *obs; + + if (tkl > 0 && addr != NULL) { + /* Prefer addr+token to find the observer */ + obs = coap_find_observer(service->data->observers, MAX_OBSERVERS, addr, token, tkl); + } else if (tkl > 0) { + /* Then try to to find the observer by token */ + obs = coap_find_observer_by_token(service->data->observers, MAX_OBSERVERS, token, + tkl); + } else if (addr != NULL) { + obs = coap_find_observer_by_addr(service->data->observers, MAX_OBSERVERS, addr); + } else { + /* Either a token or an address is required */ + return -EINVAL; + } + + if (obs == NULL) { + return 0; + } + + if (resource == NULL) { + COAP_SERVICE_FOREACH_RESOURCE(service, it) { + if (coap_remove_observer(it, obs)) { + memset(obs, 0, sizeof(*obs)); + return 1; + } + } + } else if (coap_remove_observer(resource, obs)) { + memset(obs, 0, sizeof(*obs)); + return 1; + } + + return 0; +} + +static int coap_server_process(int sock_fd) +{ + uint8_t buf[CONFIG_COAP_SERVER_MESSAGE_SIZE]; + struct sockaddr client_addr; + socklen_t client_addr_len = sizeof(client_addr); + struct coap_service *service = NULL; + struct coap_packet request; + struct coap_pending *pending; + struct coap_option options[MAX_OPTIONS] = { 0 }; + uint8_t opt_num = MAX_OPTIONS; + uint8_t type; + ssize_t received; + int ret; + + received = zsock_recvfrom(sock_fd, buf, sizeof(buf), ZSOCK_MSG_DONTWAIT, &client_addr, + &client_addr_len); + __ASSERT_NO_MSG(received <= sizeof(buf)); + + if (received < 0) { + if (errno == EWOULDBLOCK) { + return 0; + } + + LOG_ERR("Failed to process client request (%d)", -errno); + return -errno; + } + + ret = coap_packet_parse(&request, buf, received, options, opt_num); + if (ret < 0) { + LOG_ERR("Failed To parse coap message (%d)", ret); + return ret; + } + + (void)k_mutex_lock(&lock, K_FOREVER); + /* Find the active service */ + COAP_SERVICE_FOREACH(svc) { + if (svc->data->sock_fd == sock_fd) { + service = svc; + break; + } + } + if (service == NULL) { + ret = -ENOENT; + goto unlock; + } + + type = coap_header_get_type(&request); + + pending = coap_pending_received(&request, service->data->pending, MAX_PENDINGS); + if (pending) { + uint8_t token[COAP_TOKEN_MAX_LEN]; + uint8_t tkl; + + switch (type) { + case COAP_TYPE_RESET: + tkl = coap_header_get_token(&request, token); + coap_service_remove_observer(service, NULL, &client_addr, token, tkl); + __fallthrough; + case COAP_TYPE_ACK: + coap_server_free(pending->data); + coap_pending_clear(pending); + break; + default: + LOG_WRN("Unexpected pending type %d", type); + ret = -EINVAL; + goto unlock; + } + + goto unlock; + } else if (type == COAP_TYPE_ACK || type == COAP_TYPE_RESET) { + LOG_WRN("Unexpected type %d without pending packet", type); + ret = -EINVAL; + goto unlock; + } + + if (IS_ENABLED(CONFIG_COAP_SERVER_WELL_KNOWN_CORE) && + coap_header_get_code(&request) == COAP_METHOD_GET && + coap_uri_path_match(COAP_WELL_KNOWN_CORE_PATH, options, opt_num)) { + uint8_t well_known_buf[CONFIG_COAP_SERVER_MESSAGE_SIZE]; + struct coap_packet response; + + ret = coap_well_known_core_get_len(service->res_begin, + COAP_SERVICE_RESOURCE_COUNT(service), + &request, &response, + well_known_buf, sizeof(well_known_buf)); + if (ret < 0) { + LOG_ERR("Failed to build well known core for %s (%d)", service->name, ret); + goto unlock; + } + + ret = coap_service_send(service, &response, &client_addr, client_addr_len); + } else { + ret = coap_handle_request_len(&request, service->res_begin, + COAP_SERVICE_RESOURCE_COUNT(service), + options, opt_num, &client_addr, client_addr_len); + + /* Shortcut for replying a code without a body */ + if (ret > 0 && type == COAP_TYPE_CON) { + /* Minimal sized ack buffer */ + uint8_t ack_buf[COAP_TOKEN_MAX_LEN + 4U]; + struct coap_packet ack; + + ret = coap_ack_init(&ack, &request, ack_buf, sizeof(ack_buf), (uint8_t)ret); + if (ret < 0) { + LOG_ERR("Failed to init ACK (%d)", ret); + goto unlock; + } + + ret = coap_service_send(service, &ack, &client_addr, client_addr_len); + } + } + +unlock: + (void)k_mutex_unlock(&lock); + + return ret; +} + +static void coap_server_retransmit(void) +{ + struct coap_pending *pending; + int64_t remaining; + int64_t now = k_uptime_get(); + int ret; + + (void)k_mutex_lock(&lock, K_FOREVER); + + COAP_SERVICE_FOREACH(service) { + if (service->data->sock_fd < 0) { + continue; + } + + pending = coap_pending_next_to_expire(service->data->pending, MAX_PENDINGS); + if (pending == NULL) { + /* No work to be done */ + continue; + } + + /* Check if the pending request has expired */ + remaining = pending->t0 + pending->timeout - now; + if (remaining > 0) { + continue; + } + + if (coap_pending_cycle(pending)) { + ret = zsock_sendto(service->data->sock_fd, pending->data, pending->len, 0, + &pending->addr, ADDRLEN(&pending->addr)); + if (ret < 0) { + LOG_ERR("Failed to send pending retransmission for %s (%d)", + service->name, ret); + } + __ASSERT_NO_MSG(ret == pending->len); + } else { + LOG_WRN("Packet retransmission failed for %s", service->name); + + coap_service_remove_observer(service, NULL, &pending->addr, NULL, 0U); + coap_server_free(pending->data); + coap_pending_clear(pending); + } + } + + (void)k_mutex_unlock(&lock); +} + +static int coap_server_poll_timeout(void) +{ + struct coap_pending *pending; + int64_t result = INT64_MAX; + int64_t remaining; + int64_t now = k_uptime_get(); + + COAP_SERVICE_FOREACH(svc) { + if (svc->data->sock_fd < -1) { + continue; + } + + pending = coap_pending_next_to_expire(svc->data->pending, MAX_PENDINGS); + if (pending == NULL) { + continue; + } + + remaining = pending->t0 + pending->timeout - now; + if (result > remaining) { + result = remaining; + } + } + + if (result == INT64_MAX) { + return -1; + } + + return MAX(result, 0); +} + +static void coap_server_update_services(void) +{ + zsock_send(control_socks[1], &(char){0}, 1, 0); +} + +static inline bool coap_service_in_section(const struct coap_service *service) +{ + STRUCT_SECTION_START_EXTERN(coap_service); + STRUCT_SECTION_END_EXTERN(coap_service); + + return STRUCT_SECTION_START(coap_service) <= service && + STRUCT_SECTION_END(coap_service) > service; +} + +int coap_service_start(const struct coap_service *service) +{ + int ret; + + uint8_t af; + socklen_t len; + struct sockaddr_storage addr_storage; + union { + struct sockaddr *addr; + struct sockaddr_in *addr4; + struct sockaddr_in6 *addr6; + } addr_ptrs = { + .addr = (struct sockaddr *)&addr_storage, + }; + + if (!coap_service_in_section(service)) { + __ASSERT_NO_MSG(false); + return -EINVAL; + } + + k_mutex_lock(&lock, K_FOREVER); + + if (service->data->sock_fd >= 0) { + ret = -EALREADY; + goto end; + } + + /* set the default address (in6addr_any / INADDR_ANY are all 0) */ + addr_storage = (struct sockaddr_storage){0}; + if (IS_ENABLED(CONFIG_NET_IPV6) && service->host != NULL && + zsock_inet_pton(AF_INET6, service->host, &addr_ptrs.addr6->sin6_addr) == 1) { + /* if a literal IPv6 address is provided as the host, use IPv6 */ + af = AF_INET6; + len = sizeof(struct sockaddr_in6); + + addr_ptrs.addr6->sin6_family = AF_INET6; + addr_ptrs.addr6->sin6_port = htons(*service->port); + } else if (IS_ENABLED(CONFIG_NET_IPV4) && service->host != NULL && + zsock_inet_pton(AF_INET, service->host, &addr_ptrs.addr4->sin_addr) == 1) { + /* if a literal IPv4 address is provided as the host, use IPv4 */ + af = AF_INET; + len = sizeof(struct sockaddr_in); + + addr_ptrs.addr4->sin_family = AF_INET; + addr_ptrs.addr4->sin_port = htons(*service->port); + } else if (IS_ENABLED(CONFIG_NET_IPV6)) { + /* prefer IPv6 if both IPv6 and IPv4 are supported */ + af = AF_INET6; + len = sizeof(struct sockaddr_in6); + + addr_ptrs.addr6->sin6_family = AF_INET6; + addr_ptrs.addr6->sin6_port = htons(*service->port); + } else if (IS_ENABLED(CONFIG_NET_IPV4)) { + af = AF_INET; + len = sizeof(struct sockaddr_in); + + addr_ptrs.addr4->sin_family = AF_INET; + addr_ptrs.addr4->sin_port = htons(*service->port); + } else { + ret = -ENOTSUP; + goto end; + } + + service->data->sock_fd = zsock_socket(af, SOCK_DGRAM, IPPROTO_UDP); + if (service->data->sock_fd < 0) { + ret = -errno; + goto end; + } + + ret = zsock_fcntl(service->data->sock_fd, F_SETFL, O_NONBLOCK); + if (ret < 0) { + ret = -errno; + goto close; + } + + ret = zsock_bind(service->data->sock_fd, addr_ptrs.addr, len); + if (ret < 0) { + ret = -errno; + goto close; + } + + if (*service->port == 0) { + /* ephemeral port - read back the port number */ + len = sizeof(addr_storage); + ret = zsock_getsockname(service->data->sock_fd, addr_ptrs.addr, &len); + if (ret < 0) { + goto close; + } + + if (af == AF_INET6) { + *service->port = addr_ptrs.addr6->sin6_port; + } else { + *service->port = addr_ptrs.addr4->sin_port; + } + } + +end: + k_mutex_unlock(&lock); + + coap_server_update_services(); + + return ret; + +close: + (void)zsock_close(service->data->sock_fd); + service->data->sock_fd = -1; + + k_mutex_unlock(&lock); + + return ret; +} + +int coap_service_stop(const struct coap_service *service) +{ + int ret; + + if (!coap_service_in_section(service)) { + __ASSERT_NO_MSG(false); + return -EINVAL; + } + + k_mutex_lock(&lock, K_FOREVER); + + if (service->data->sock_fd < 0) { + ret = -EALREADY; + goto end; + } + + /* Closing a socket will trigger a poll event */ + ret = zsock_close(service->data->sock_fd); + service->data->sock_fd = -1; + +end: + k_mutex_unlock(&lock); + + return ret; +} + +int coap_service_send(const struct coap_service *service, const struct coap_packet *cpkt, + const struct sockaddr *addr, socklen_t addr_len) +{ + int ret; + + if (!coap_service_in_section(service)) { + __ASSERT_NO_MSG(false); + return -EINVAL; + } + + (void)k_mutex_lock(&lock, K_FOREVER); + + if (service->data->sock_fd < 0) { + (void)k_mutex_unlock(&lock); + return -EBADF; + } + + /* + * Check if we should start with retransmits, if creating a pending message fails we still + * try to send. + */ + if (coap_header_get_type(cpkt) == COAP_TYPE_CON) { + struct coap_pending *pending = coap_pending_next_unused(service->data->pending, + MAX_PENDINGS); + + if (pending == NULL) { + LOG_WRN("No pending message available for %s", service->name); + goto send; + } + + ret = coap_pending_init(pending, cpkt, addr, + CONFIG_COAP_SERVICE_PENDING_RETRANSMITS); + if (ret < 0) { + LOG_WRN("Failed to init pending message for %s (%d)", service->name, ret); + goto send; + } + + /* Replace tracked data with our allocated copy */ + pending->data = coap_server_alloc(pending->len); + if (pending->data == NULL) { + LOG_WRN("Failed to allocate pending message data for %s", service->name); + coap_pending_clear(pending); + goto send; + } + memcpy(pending->data, cpkt->data, pending->len); + + coap_pending_cycle(pending); + + /* Trigger event in receive loop to schedule retransmit */ + coap_server_update_services(); + } + +send: + (void)k_mutex_unlock(&lock); + + ret = zsock_sendto(service->data->sock_fd, cpkt->data, cpkt->offset, 0, addr, addr_len); + if (ret < 0) { + LOG_ERR("Failed to send CoAP message (%d)", ret); + return ret; + } + __ASSERT_NO_MSG(ret == cpkt->offset); + + return 0; +} + +int coap_resource_send(const struct coap_resource *resource, const struct coap_packet *cpkt, + const struct sockaddr *addr, socklen_t addr_len) +{ + /* Find owning service */ + COAP_SERVICE_FOREACH(svc) { + if (COAP_SERVICE_HAS_RESOURCE(svc, resource)) { + return coap_service_send(svc, cpkt, addr, addr_len); + } + } + + return -ENOENT; +} + +int coap_resource_parse_observe(struct coap_resource *resource, const struct coap_packet *request, + const struct sockaddr *addr) +{ + const struct coap_service *service = NULL; + int ret; + uint8_t token[COAP_TOKEN_MAX_LEN]; + uint8_t tkl; + + if (!coap_packet_is_request(request)) { + return -EINVAL; + } + + ret = coap_get_option_int(request, COAP_OPTION_OBSERVE); + if (ret < 0) { + return ret; + } + + /* Find owning service */ + COAP_SERVICE_FOREACH(svc) { + if (COAP_SERVICE_HAS_RESOURCE(svc, resource)) { + service = svc; + break; + } + } + + if (service == NULL) { + return -ENOENT; + } + + tkl = coap_header_get_token(request, token); + if (tkl == 0) { + return -EINVAL; + } + + (void)k_mutex_lock(&lock, K_FOREVER); + + if (ret == 0) { + struct coap_observer *observer; + + /* RFC7641 section 4.1 - Check if the current observer already exists */ + observer = coap_find_observer(service->data->observers, MAX_OBSERVERS, addr, token, + tkl); + if (observer != NULL) { + /* Client refresh */ + goto unlock; + } + + /* New client */ + observer = coap_observer_next_unused(service->data->observers, MAX_OBSERVERS); + if (observer == NULL) { + ret = -ENOMEM; + goto unlock; + } + + coap_observer_init(observer, request, addr); + coap_register_observer(resource, observer); + } else if (ret == 1) { + ret = coap_service_remove_observer(service, resource, addr, token, tkl); + if (ret < 0) { + LOG_WRN("Failed to remove observer (%d)", ret); + } + } + +unlock: + (void)k_mutex_unlock(&lock); + + return ret; +} + +static int coap_resource_remove_observer(struct coap_resource *resource, + const struct sockaddr *addr, + const uint8_t *token, uint8_t token_len) +{ + const struct coap_service *service = NULL; + int ret; + + /* Find owning service */ + COAP_SERVICE_FOREACH(svc) { + if (COAP_SERVICE_HAS_RESOURCE(svc, resource)) { + service = svc; + break; + } + } + + if (service == NULL) { + return -ENOENT; + } + + (void)k_mutex_lock(&lock, K_FOREVER); + ret = coap_service_remove_observer(service, resource, addr, token, token_len); + (void)k_mutex_unlock(&lock); + + if (ret == 1) { + /* An observer was found and removed */ + return 0; + } else if (ret == 0) { + /* No matching observer found */ + return -ENOENT; + } + + /* An error occurred */ + return ret; +} + +int coap_resource_remove_observer_by_addr(struct coap_resource *resource, + const struct sockaddr *addr) +{ + return coap_resource_remove_observer(resource, addr, NULL, 0); +} + +int coap_resource_remove_observer_by_token(struct coap_resource *resource, + const uint8_t *token, uint8_t token_len) +{ + return coap_resource_remove_observer(resource, NULL, token, token_len); +} + +static void coap_server_thread(void *p1, void *p2, void *p3) +{ + struct zsock_pollfd sock_fds[MAX_POLL_FD]; + int sock_nfds; + int ret; + + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + /* Create a socket pair to wake zsock_poll */ + ret = zsock_socketpair(AF_UNIX, SOCK_STREAM, 0, control_socks); + if (ret < 0) { + LOG_ERR("Failed to create socket pair (%d)", ret); + return; + } + + for (int i = 0; i < 2; ++i) { + ret = zsock_fcntl(control_socks[i], F_SETFL, O_NONBLOCK); + + if (ret < 0) { + zsock_close(control_socks[0]); + zsock_close(control_socks[1]); + + LOG_ERR("Failed to set socket pair [%d] non-blocking (%d)", i, ret); + return; + } + } + + COAP_SERVICE_FOREACH(svc) { + /* Init all file descriptors to -1 */ + svc->data->sock_fd = -1; + + if (svc->flags & COAP_SERVICE_AUTOSTART) { + ret = coap_service_start(svc); + if (ret < 0) { + LOG_ERR("Failed to autostart service %s (%d)", svc->name, ret); + } + } + } + + while (true) { + sock_nfds = 0; + COAP_SERVICE_FOREACH(svc) { + if (svc->data->sock_fd < 0) { + continue; + } + if (sock_nfds >= MAX_POLL_FD) { + LOG_ERR("Maximum active CoAP services reached (%d), " + "increase CONFIG_NET_SOCKETS_POLL_MAX to support more.", + MAX_POLL_FD); + break; + } + + sock_fds[sock_nfds].fd = svc->data->sock_fd; + sock_fds[sock_nfds].events = ZSOCK_POLLIN; + sock_fds[sock_nfds].revents = 0; + sock_nfds++; + } + + /* Add socket pair FD to allow wake up */ + if (sock_nfds < MAX_POLL_FD) { + sock_fds[sock_nfds].fd = control_socks[0]; + sock_fds[sock_nfds].events = ZSOCK_POLLIN; + sock_fds[sock_nfds].revents = 0; + sock_nfds++; + } + + __ASSERT_NO_MSG(sock_nfds > 0); + + ret = zsock_poll(sock_fds, sock_nfds, coap_server_poll_timeout()); + if (ret < 0) { + LOG_ERR("Poll error (%d)", -errno); + k_msleep(10); + } + + for (int i = 0; i < sock_nfds; ++i) { + /* Check the wake up event */ + if (sock_fds[i].fd == control_socks[0] && + sock_fds[i].revents & ZSOCK_POLLIN) { + char tmp; + + zsock_recv(sock_fds[i].fd, &tmp, 1, 0); + continue; + } + + /* Check if socket can receive/was closed first */ + if (sock_fds[i].revents & ZSOCK_POLLIN) { + coap_server_process(sock_fds[i].fd); + continue; + } + + if (sock_fds[i].revents & ZSOCK_POLLERR) { + LOG_ERR("Poll error on %d", sock_fds[i].fd); + } + if (sock_fds[i].revents & ZSOCK_POLLHUP) { + LOG_ERR("Poll hup on %d", sock_fds[i].fd); + } + if (sock_fds[i].revents & ZSOCK_POLLNVAL) { + LOG_ERR("Poll invalid on %d", sock_fds[i].fd); + } + } + + /* Process retransmits */ + coap_server_retransmit(); + } +} + +K_THREAD_DEFINE(coap_server_id, CONFIG_COAP_SERVER_STACK_SIZE, + coap_server_thread, NULL, NULL, NULL, + THREAD_PRIORITY, 0, 0); diff --git a/subsys/net/lib/coap/coap_server_shell.c b/subsys/net/lib/coap/coap_server_shell.c new file mode 100644 index 00000000000..bf0a52553da --- /dev/null +++ b/subsys/net/lib/coap/coap_server_shell.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2023 Basalte bv + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + + +static int cmd_list(const struct shell *sh, size_t argc, char **argv) +{ + int count = 0; + + ARG_UNUSED(argv); + + if (argc > 1) { + return -EINVAL; + } + + shell_print(sh, " Name State Endpoint"); + COAP_SERVICE_FOREACH(service) { + shell_print(sh, + "[%2d] %-16s %-16s %s:%d", + ++count, + service->name, + service->data->sock_fd < 0 ? "INACTIVE" : "ACTIVE", + service->host != NULL ? service->host : "", + *service->port); + } + + if (count == 0) { + shell_print(sh, "No services available"); + return -ENOENT; + } + + return 0; +} + +static int cmd_start(const struct shell *sh, size_t argc, char **argv) +{ + int ret = -ENOENT; + + if (argc != 2) { + shell_error(sh, "Usage: start "); + return -EINVAL; + } + + COAP_SERVICE_FOREACH(service) { + if (strcmp(argv[1], service->name) == 0) { + ret = coap_service_start(service); + break; + } + } + + if (ret < 0) { + shell_error(sh, "Failed to start service (%d)", ret); + } + + return ret; +} + +static int cmd_stop(const struct shell *sh, size_t argc, char **argv) +{ + int ret = -ENOENT; + + if (argc != 2) { + shell_error(sh, "Usage: stop "); + return -EINVAL; + } + + COAP_SERVICE_FOREACH(service) { + if (strcmp(argv[1], service->name) == 0) { + ret = coap_service_stop(service); + break; + } + } + + if (ret < 0) { + shell_error(sh, "Failed to stop service (%d)", ret); + } + + return ret; +} + +SHELL_STATIC_SUBCMD_SET_CREATE(sub_coap_service, + SHELL_CMD(start, NULL, + "Start a CoAP Service\n" + "Usage: start ", + cmd_start), + SHELL_CMD(stop, NULL, + "Stop a CoAP Service\n" + "Usage: stop ", + cmd_stop), + SHELL_SUBCMD_SET_END /* Array terminated. */ +); +SHELL_CMD_REGISTER(coap_service, &sub_coap_service, "CoAP Service commands", cmd_list); diff --git a/subsys/net/lib/config/Kconfig b/subsys/net/lib/config/Kconfig index 5ca788cebf1..c74193fec97 100644 --- a/subsys/net/lib/config/Kconfig +++ b/subsys/net/lib/config/Kconfig @@ -171,11 +171,18 @@ config NET_CONFIG_IEEE802154_SECURITY_LEVEL 1 authentication only with a 4 bytes length tag 2 authentication only with a 8 bytes length tag 3 authentication only with a 16 bytes length tag - 4 encryption only + 4 deprecated since IEEE 802.15.4-2015 5 encryption/authentication with a 4 bytes length tag 6 encryption/authentication with a 8 bytes length tag 7 encryption/authentication with a 16 bytes length tag +config NET_CONFIG_IEEE802154_ACK_REQUIRED + bool "IEEE 802.15.4 acknowledgment" + default y + help + Whether or not to request and require IEEE 802.15.4 acknowledgment + packets. + endif # NET_L2_IEEE802154 || IEEE802154_RAW_MODE config NET_CONFIG_BT_NODE diff --git a/subsys/net/lib/config/ieee802154_settings.c b/subsys/net/lib/config/ieee802154_settings.c index 5217a5cf00e..4a142bf75bd 100644 --- a/subsys/net/lib/config/ieee802154_settings.c +++ b/subsys/net/lib/config/ieee802154_settings.c @@ -17,10 +17,12 @@ LOG_MODULE_DECLARE(net_config, CONFIG_NET_CONFIG_LOG_LEVEL); #include #include -int z_net_config_ieee802154_setup(void) +int z_net_config_ieee802154_setup(struct net_if *iface) { uint16_t channel = CONFIG_NET_CONFIG_IEEE802154_CHANNEL; uint16_t pan_id = CONFIG_NET_CONFIG_IEEE802154_PAN_ID; + const struct device *const dev = iface == NULL ? DEVICE_DT_GET(DT_CHOSEN(zephyr_ieee802154)) + : net_if_get_device(iface); int16_t tx_power = CONFIG_NET_CONFIG_IEEE802154_RADIO_TX_POWER; #ifdef CONFIG_NET_L2_IEEE802154_SECURITY @@ -32,16 +34,21 @@ int z_net_config_ieee802154_setup(void) }; #endif /* CONFIG_NET_L2_IEEE802154_SECURITY */ - struct net_if *iface; - const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_ieee802154)); - if (!device_is_ready(dev)) { return -ENODEV; } - iface = net_if_lookup_by_dev(dev); if (!iface) { - return -EINVAL; + iface = net_if_lookup_by_dev(dev); + if (!iface) { + return -ENOENT; + } + } + + if (IS_ENABLED(CONFIG_NET_CONFIG_IEEE802154_ACK_REQUIRED)) { + if (net_mgmt(NET_REQUEST_IEEE802154_SET_ACK, iface, NULL, 0)) { + return -EIO; + } } if (net_mgmt(NET_REQUEST_IEEE802154_SET_PAN_ID, @@ -60,7 +67,14 @@ int z_net_config_ieee802154_setup(void) } #endif /* CONFIG_NET_L2_IEEE802154_SECURITY */ - net_if_up(iface); + if (!IS_ENABLED(CONFIG_IEEE802154_NET_IF_NO_AUTO_START)) { + /* The NET_IF_NO_AUTO_START flag was set by the driver, see + * ieee802154_init() to allow for configuration before starting + * up the interface. + */ + net_if_flag_clear(iface, NET_IF_NO_AUTO_START); + net_if_up(iface); + } return 0; } diff --git a/subsys/net/lib/config/ieee802154_settings.h b/subsys/net/lib/config/ieee802154_settings.h index 08164253c05..5f0bb70b249 100644 --- a/subsys/net/lib/config/ieee802154_settings.h +++ b/subsys/net/lib/config/ieee802154_settings.h @@ -7,7 +7,9 @@ */ #if defined(CONFIG_NET_L2_IEEE802154) && defined(CONFIG_NET_CONFIG_SETTINGS) -int z_net_config_ieee802154_setup(void); +struct net_if; + +int z_net_config_ieee802154_setup(struct net_if *iface); #else #define z_net_config_ieee802154_setup(...) 0 #endif diff --git a/subsys/net/lib/config/init.c b/subsys/net/lib/config/init.c index 098003b79b3..192cd3f5685 100644 --- a/subsys/net/lib/config/init.c +++ b/subsys/net/lib/config/init.c @@ -402,6 +402,14 @@ int net_config_init_by_iface(struct net_if *iface, const char *app_info, iface = net_if_get_default(); } + if (!iface) { + return -ENOENT; + } + + if (net_if_flag_is_set(iface, NET_IF_NO_AUTO_START)) { + return -ENETDOWN; + } + if (timeout < 0) { count = -1; } else if (timeout == 0) { @@ -489,7 +497,7 @@ int net_config_init_app(const struct device *dev, const char *app_info) } } - ret = z_net_config_ieee802154_setup(); + ret = z_net_config_ieee802154_setup(iface); if (ret < 0) { NET_ERR("Cannot setup IEEE 802.15.4 interface (%d)", ret); } @@ -502,6 +510,17 @@ int net_config_init_app(const struct device *dev, const char *app_info) } #endif + /* Only try to use a network interface that is auto started */ + if (iface == NULL) { + net_if_foreach(iface_find_cb, &iface); + } + + if (!iface) { + NET_WARN("No auto-started network interface - " + "network-bound app initialization skipped."); + return 0; + } + if (IS_ENABLED(CONFIG_NET_CONFIG_NEED_IPV6)) { flags |= NET_CONFIG_NEED_IPV6; } @@ -514,11 +533,6 @@ int net_config_init_app(const struct device *dev, const char *app_info) flags |= NET_CONFIG_NEED_IPV4; } - /* Only try to use a network interface that is auto started */ - if (iface == NULL) { - net_if_foreach(iface_find_cb, &iface); - } - /* Initialize the application automatically if needed */ ret = net_config_init_by_iface(iface, app_info, flags, CONFIG_NET_CONFIG_INIT_TIMEOUT * MSEC_PER_SEC); diff --git a/subsys/net/lib/dns/mdns_responder.c b/subsys/net/lib/dns/mdns_responder.c index 0542acad78d..04acbabbecd 100644 --- a/subsys/net/lib/dns/mdns_responder.c +++ b/subsys/net/lib/dns/mdns_responder.c @@ -38,11 +38,17 @@ LOG_MODULE_REGISTER(net_mdns_responder, CONFIG_MDNS_RESPONDER_LOG_LEVEL); #define MDNS_TTL CONFIG_MDNS_RESPONDER_TTL /* In seconds */ #if defined(CONFIG_NET_IPV4) -static struct net_context *ipv4; +#define MAX_IPV4_IFACE_COUNT CONFIG_NET_IF_MAX_IPV4_COUNT +static struct net_context *ipv4[MAX_IPV4_IFACE_COUNT]; static struct sockaddr_in local_addr4; +#else +#define MAX_IPV4_IFACE_COUNT 0 #endif #if defined(CONFIG_NET_IPV6) -static struct net_context *ipv6; +#define MAX_IPV6_IFACE_COUNT CONFIG_NET_IF_MAX_IPV6_COUNT +static struct net_context *ipv6[MAX_IPV6_IFACE_COUNT]; +#else +#define MAX_IPV6_IFACE_COUNT 0 #endif static struct net_mgmt_event_callback mgmt_cb; @@ -270,8 +276,14 @@ static int send_response(struct net_context *ctx, if (IS_ENABLED(CONFIG_NET_IPV4) && qtype == DNS_RR_TYPE_A) { const struct in_addr *addr; - addr = net_if_ipv4_select_src_addr(iface, - family == AF_INET ? (struct in_addr *)src_addr : NULL); + if (family == AF_INET) { + addr = net_if_ipv4_select_src_addr(iface, (struct in_addr *)src_addr); + } else { + struct sockaddr_in tmp_addr; + + create_ipv4_addr(&tmp_addr); + addr = net_if_ipv4_select_src_addr(iface, &tmp_addr.sin_addr); + } ret = create_answer(ctx, query, qtype, sizeof(struct in_addr), (uint8_t *)addr); if (ret != 0) { @@ -280,8 +292,14 @@ static int send_response(struct net_context *ctx, } else if (IS_ENABLED(CONFIG_NET_IPV6) && qtype == DNS_RR_TYPE_AAAA) { const struct in6_addr *addr; - addr = net_if_ipv6_select_src_addr(iface, - family == AF_INET6 ? (struct in6_addr *)src_addr : NULL); + if (family == AF_INET6) { + addr = net_if_ipv6_select_src_addr(iface, (struct in6_addr *)src_addr); + } else { + struct sockaddr_in6 tmp_addr; + + create_ipv6_addr(&tmp_addr); + addr = net_if_ipv6_select_src_addr(iface, &tmp_addr.sin6_addr); + } ret = create_answer(ctx, query, qtype, sizeof(struct in6_addr), (uint8_t *)addr); if (ret != 0) { @@ -361,14 +379,26 @@ static void send_sd_response(struct net_context *ctx, if (IS_ENABLED(CONFIG_NET_IPV4)) { /* Look up the local IPv4 address */ - addr4 = net_if_ipv4_select_src_addr(iface, - family == AF_INET ? (struct in_addr *)src_addr : NULL); + if (family == AF_INET) { + addr4 = net_if_ipv4_select_src_addr(iface, (struct in_addr *)src_addr); + } else { + struct sockaddr_in tmp_addr; + + create_ipv4_addr(&tmp_addr); + addr4 = net_if_ipv4_select_src_addr(iface, &tmp_addr.sin_addr); + } } if (IS_ENABLED(CONFIG_NET_IPV6)) { /* Look up the local IPv6 address */ - addr6 = net_if_ipv6_select_src_addr(iface, - family == AF_INET6 ? (struct in6_addr *)src_addr : NULL); + if (family == AF_INET6) { + addr6 = net_if_ipv6_select_src_addr(iface, (struct in6_addr *)src_addr); + } else { + struct sockaddr_in6 tmp_addr; + + create_ipv6_addr(&tmp_addr); + addr6 = net_if_ipv6_select_src_addr(iface, &tmp_addr.sin6_addr); + } } ret = dns_sd_query_extract(dns_msg->msg, @@ -621,55 +651,103 @@ static void setup_ipv4_addr(struct sockaddr_in *local_addr) static int init_listener(void) { - int ret, ok = 0; + int ret, ok = 0, i; + struct net_if *iface; + int iface_count; + + NET_IFACE_COUNT(&iface_count); + NET_DBG("Setting mDNS listener to %d interface%s", iface_count, + iface_count > 1 ? "s" : ""); + + if ((iface_count > MAX_IPV6_IFACE_COUNT && MAX_IPV6_IFACE_COUNT > 0) || + (iface_count > MAX_IPV4_IFACE_COUNT && MAX_IPV4_IFACE_COUNT > 0)) { + NET_WARN("You have %d interfaces configured but there " + "are %d network interfaces in the system.", + MAX(MAX_IPV6_IFACE_COUNT, + MAX_IPV6_IFACE_COUNT), iface_count); + } #if defined(CONFIG_NET_IPV6) - do { - static struct sockaddr_in6 local_addr; + struct sockaddr_in6 local_addr6; + struct net_context *v6; + + setup_ipv6_addr(&local_addr6); - setup_ipv6_addr(&local_addr); + for (i = 0; i < MAX_IPV6_IFACE_COUNT; i++) { + v6 = get_ctx(AF_INET6); + if (v6 == NULL) { + NET_ERR("Cannot get %s context out of %d. Max contexts is %d", + "IPv6", MAX_IPV6_IFACE_COUNT, CONFIG_NET_MAX_CONTEXTS); + continue; + } + + iface = net_if_get_by_index(i + 1); + if (iface == NULL) { + net_context_unref(v6); + continue; + } - ipv6 = get_ctx(AF_INET6); + net_context_bind_iface(v6, iface); - ret = bind_ctx(ipv6, (struct sockaddr *)&local_addr, - sizeof(local_addr)); + ret = bind_ctx(v6, (struct sockaddr *)&local_addr6, + sizeof(local_addr6)); if (ret < 0) { - net_context_put(ipv6); + net_context_put(v6); goto ipv6_out; } - ret = net_context_recv(ipv6, recv_cb, K_NO_WAIT, ipv6); + ret = net_context_recv(v6, recv_cb, K_NO_WAIT, v6); if (ret < 0) { - NET_WARN("Cannot receive IPv6 mDNS data (%d)", ret); - net_context_put(ipv6); + NET_WARN("Cannot receive %s mDNS data (%d)", "IPv6", ret); + net_context_put(v6); } else { + ipv6[i] = v6; ok++; } - } while (0); + } ipv6_out: + ; /* Added ";" to avoid clang compile error because of + * the "struct net_context *v4" after it. + */ #endif /* CONFIG_NET_IPV6 */ #if defined(CONFIG_NET_IPV4) - do { - setup_ipv4_addr(&local_addr4); + struct net_context *v4; - ipv4 = get_ctx(AF_INET); + setup_ipv4_addr(&local_addr4); - ret = bind_ctx(ipv4, (struct sockaddr *)&local_addr4, + for (i = 0; i < MAX_IPV4_IFACE_COUNT; i++) { + v4 = get_ctx(AF_INET); + if (v4 == NULL) { + NET_ERR("Cannot get %s context out of %d. Max contexts is %d", + "IPv4", MAX_IPV4_IFACE_COUNT, CONFIG_NET_MAX_CONTEXTS); + continue; + } + + iface = net_if_get_by_index(i + 1); + if (iface == NULL) { + net_context_unref(v4); + continue; + } + + net_context_bind_iface(v4, iface); + + ret = bind_ctx(v4, (struct sockaddr *)&local_addr4, sizeof(local_addr4)); if (ret < 0) { - net_context_put(ipv4); + net_context_put(v4); goto ipv4_out; } - ret = net_context_recv(ipv4, recv_cb, K_NO_WAIT, ipv4); + ret = net_context_recv(v4, recv_cb, K_NO_WAIT, v4); if (ret < 0) { - NET_WARN("Cannot receive IPv4 mDNS data (%d)", ret); - net_context_put(ipv4); + NET_WARN("Cannot receive %s mDNS data (%d)", "IPv4", ret); + net_context_put(v4); } else { + ipv4[i] = v4; ok++; } - } while (0); + } ipv4_out: #endif /* CONFIG_NET_IPV4 */ diff --git a/subsys/net/lib/dns/resolve.c b/subsys/net/lib/dns/resolve.c index eae02bc88ed..2741ed13a97 100644 --- a/subsys/net/lib/dns/resolve.c +++ b/subsys/net/lib/dns/resolve.c @@ -14,7 +14,7 @@ LOG_MODULE_REGISTER(net_dns_resolve, CONFIG_DNS_RESOLVER_LOG_LEVEL); #include -#include +#include #include #include #include diff --git a/subsys/net/lib/lwm2m/Kconfig b/subsys/net/lib/lwm2m/Kconfig index 1f5b83f47d0..dd3c0c45618 100644 --- a/subsys/net/lib/lwm2m/Kconfig +++ b/subsys/net/lib/lwm2m/Kconfig @@ -115,6 +115,13 @@ config LWM2M_TLS_SESSION_CACHING help Enabling this only when feature is supported in TLS library. +config LWM2M_DTLS_CID + bool "DTLS Connection Identifier support" + default y if MBEDTLS_SSL_DTLS_CONNECTION_ID + help + Request TLS stack to enable DTLS Connection identifier. This requires stack that support it + and actual effect depends on the target server as well. + config LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP bool "Bootstrap support" help diff --git a/subsys/net/lib/lwm2m/ipso_current_sensor.c b/subsys/net/lib/lwm2m/ipso_current_sensor.c index 99b12ea667b..0684db94220 100644 --- a/subsys/net/lib/lwm2m/ipso_current_sensor.c +++ b/subsys/net/lib/lwm2m/ipso_current_sensor.c @@ -177,8 +177,8 @@ static struct lwm2m_engine_obj_inst *current_sensor_create(uint16_t obj_inst_id) INIT_OBJ_RES(SENSOR_VALUE_RID, res[index], i, res_inst[index], j, 1, false, true, &sensor_value[index], sizeof(*sensor_value), NULL, NULL, NULL, sensor_value_write_cb, NULL); - INIT_OBJ_RES_DATA(SENSOR_UNITS_RID, res[index], i, res_inst[index], j, - units[index], UNIT_STR_MAX_SIZE); + INIT_OBJ_RES_DATA_LEN(SENSOR_UNITS_RID, res[index], i, res_inst[index], j, + units[index], UNIT_STR_MAX_SIZE, 0); INIT_OBJ_RES_DATA(MIN_MEASURED_VALUE_RID, res[index], i, res_inst[index], j, &min_measured_value[index], sizeof(*min_measured_value)); @@ -194,8 +194,8 @@ static struct lwm2m_engine_obj_inst *current_sensor_create(uint16_t obj_inst_id) INIT_OBJ_RES_DATA(CURRENT_CALIBRATION_RID, res[index], i, res_inst[index], j, &calibration_coefficient[index], sizeof(*calibration_coefficient)); - INIT_OBJ_RES_DATA(APPLICATION_TYPE_RID, res[index], i, res_inst[index], - j, app_type[index], APP_TYPE_STR_MAX_SIZE); + INIT_OBJ_RES_DATA_LEN(APPLICATION_TYPE_RID, res[index], i, res_inst[index], + j, app_type[index], APP_TYPE_STR_MAX_SIZE, 0); #if defined(CONFIG_LWM2M_IPSO_CURRENT_SENSOR_VERSION_1_1) INIT_OBJ_RES_OPTDATA(TIMESTAMP_RID, res[index], i, res_inst[index], j); diff --git a/subsys/net/lib/lwm2m/ipso_generic_sensor.c b/subsys/net/lib/lwm2m/ipso_generic_sensor.c index 5f1d9801a7f..def650ce9e4 100644 --- a/subsys/net/lib/lwm2m/ipso_generic_sensor.c +++ b/subsys/net/lib/lwm2m/ipso_generic_sensor.c @@ -186,8 +186,8 @@ static struct lwm2m_engine_obj_inst *generic_sensor_create(uint16_t obj_inst_id) INIT_OBJ_RES(SENSOR_VALUE_RID, res[index], i, res_inst[index], j, 1, false, true, &sensor_value[index], sizeof(*sensor_value), NULL, NULL, NULL, sensor_value_write_cb, NULL); - INIT_OBJ_RES_DATA(SENSOR_UNITS_RID, res[index], i, res_inst[index], j, - units[index], UNIT_STR_MAX_SIZE); + INIT_OBJ_RES_DATA_LEN(SENSOR_UNITS_RID, res[index], i, res_inst[index], j, + units[index], UNIT_STR_MAX_SIZE, 0); INIT_OBJ_RES_DATA(MIN_MEASURED_VALUE_RID, res[index], i, res_inst[index], j, &min_measured_value[index], sizeof(*min_measured_value)); @@ -200,10 +200,10 @@ static struct lwm2m_engine_obj_inst *generic_sensor_create(uint16_t obj_inst_id) j, &max_range_value[index], sizeof(*max_range_value)); INIT_OBJ_RES_EXECUTE(RESET_MIN_MAX_MEASURED_VALUES_RID, res[index], i, reset_min_max_measured_values_cb); - INIT_OBJ_RES_DATA(APPLICATION_TYPE_RID, res[index], i, res_inst[index], - j, app_type[index], APP_TYPE_STR_MAX_SIZE); - INIT_OBJ_RES_DATA(SENSOR_TYPE_RID, res[index], i, res_inst[index], j, - sensor_type[index], SENSOR_TYPE_STR_MAX_SIZE); + INIT_OBJ_RES_DATA_LEN(APPLICATION_TYPE_RID, res[index], i, res_inst[index], + j, app_type[index], APP_TYPE_STR_MAX_SIZE, 0); + INIT_OBJ_RES_DATA_LEN(SENSOR_TYPE_RID, res[index], i, res_inst[index], j, + sensor_type[index], SENSOR_TYPE_STR_MAX_SIZE, 0); #if defined(CONFIG_LWM2M_IPSO_GENERIC_SENSOR_VERSION_1_1) INIT_OBJ_RES_OPTDATA(TIMESTAMP_RID, res[index], i, res_inst[index], j); diff --git a/subsys/net/lib/lwm2m/ipso_humidity_sensor.c b/subsys/net/lib/lwm2m/ipso_humidity_sensor.c index fe338d1436a..24be33d37f2 100644 --- a/subsys/net/lib/lwm2m/ipso_humidity_sensor.c +++ b/subsys/net/lib/lwm2m/ipso_humidity_sensor.c @@ -170,8 +170,8 @@ humidity_sensor_create(uint16_t obj_inst_id) INIT_OBJ_RES(SENSOR_VALUE_RID, res[index], i, res_inst[index], j, 1, false, true, &sensor_value[index], sizeof(*sensor_value), NULL, NULL, NULL, sensor_value_write_cb, NULL); - INIT_OBJ_RES_DATA(SENSOR_UNITS_RID, res[index], i, res_inst[index], j, - units[index], UNIT_STR_MAX_SIZE); + INIT_OBJ_RES_DATA_LEN(SENSOR_UNITS_RID, res[index], i, res_inst[index], j, + units[index], UNIT_STR_MAX_SIZE, 0); INIT_OBJ_RES_DATA(MIN_MEASURED_VALUE_RID, res[index], i, res_inst[index], j, &min_measured_value[index], sizeof(*min_measured_value)); diff --git a/subsys/net/lib/lwm2m/ipso_light_control.c b/subsys/net/lib/lwm2m/ipso_light_control.c index beeb5f0f543..fc9a897461a 100644 --- a/subsys/net/lib/lwm2m/ipso_light_control.c +++ b/subsys/net/lib/lwm2m/ipso_light_control.c @@ -171,10 +171,10 @@ static struct lwm2m_engine_obj_inst *light_control_create(uint16_t obj_inst_id) INIT_OBJ_RES_DATA(POWER_FACTOR_RID, res[avail], i, res_inst[avail], j, &power_factor_value[avail], sizeof(*power_factor_value)); - INIT_OBJ_RES_DATA(COLOUR_RID, res[avail], i, res_inst[avail], j, - colour[avail], LIGHT_STRING_LONG); - INIT_OBJ_RES_DATA(SENSOR_UNITS_RID, res[avail], i, res_inst[avail], j, - units[avail], LIGHT_STRING_SHORT); + INIT_OBJ_RES_DATA_LEN(COLOUR_RID, res[avail], i, res_inst[avail], j, + colour[avail], LIGHT_STRING_LONG, 0); + INIT_OBJ_RES_DATA_LEN(SENSOR_UNITS_RID, res[avail], i, res_inst[avail], j, + units[avail], LIGHT_STRING_SHORT, 0); INIT_OBJ_RES_OPTDATA(APPLICATION_TYPE_RID, res[avail], i, res_inst[avail], j); diff --git a/subsys/net/lib/lwm2m/ipso_pressure_sensor.c b/subsys/net/lib/lwm2m/ipso_pressure_sensor.c index f58c718aed6..87f87e4a277 100644 --- a/subsys/net/lib/lwm2m/ipso_pressure_sensor.c +++ b/subsys/net/lib/lwm2m/ipso_pressure_sensor.c @@ -171,8 +171,8 @@ pressure_sensor_create(uint16_t obj_inst_id) INIT_OBJ_RES(SENSOR_VALUE_RID, res[index], i, res_inst[index], j, 1, false, true, &sensor_value[index], sizeof(*sensor_value), NULL, NULL, NULL, sensor_value_write_cb, NULL); - INIT_OBJ_RES_DATA(SENSOR_UNITS_RID, res[index], i, res_inst[index], j, - units[index], UNIT_STR_MAX_SIZE); + INIT_OBJ_RES_DATA_LEN(SENSOR_UNITS_RID, res[index], i, res_inst[index], j, + units[index], UNIT_STR_MAX_SIZE, 0); INIT_OBJ_RES_DATA(MIN_MEASURED_VALUE_RID, res[index], i, res_inst[index], j, &min_measured_value[index], sizeof(*min_measured_value)); diff --git a/subsys/net/lib/lwm2m/ipso_temp_sensor.c b/subsys/net/lib/lwm2m/ipso_temp_sensor.c index ff5a3bf767d..bdf59563833 100644 --- a/subsys/net/lib/lwm2m/ipso_temp_sensor.c +++ b/subsys/net/lib/lwm2m/ipso_temp_sensor.c @@ -172,8 +172,8 @@ static struct lwm2m_engine_obj_inst *temp_sensor_create(uint16_t obj_inst_id) res_inst[index], j, 1, false, true, &sensor_value[index], sizeof(*sensor_value), NULL, NULL, NULL, sensor_value_write_cb, NULL); - INIT_OBJ_RES_DATA(SENSOR_UNITS_RID, res[index], i, res_inst[index], j, - units[index], UNIT_STR_MAX_SIZE); + INIT_OBJ_RES_DATA_LEN(SENSOR_UNITS_RID, res[index], i, res_inst[index], j, + units[index], UNIT_STR_MAX_SIZE, 0); INIT_OBJ_RES_DATA(MIN_MEASURED_VALUE_RID, res[index], i, res_inst[index], j, &min_measured_value[index], sizeof(*min_measured_value)); diff --git a/subsys/net/lib/lwm2m/ipso_voltage_sensor.c b/subsys/net/lib/lwm2m/ipso_voltage_sensor.c index 1e4eff60b1b..55b45902234 100644 --- a/subsys/net/lib/lwm2m/ipso_voltage_sensor.c +++ b/subsys/net/lib/lwm2m/ipso_voltage_sensor.c @@ -178,8 +178,8 @@ static struct lwm2m_engine_obj_inst *voltage_sensor_create(uint16_t obj_inst_id) INIT_OBJ_RES(SENSOR_VALUE_RID, res[index], i, res_inst[index], j, 1, false, true, &sensor_value[index], sizeof(*sensor_value), NULL, NULL, NULL, sensor_value_write_cb, NULL); - INIT_OBJ_RES_DATA(SENSOR_UNITS_RID, res[index], i, res_inst[index], j, - units[index], UNIT_STR_MAX_SIZE); + INIT_OBJ_RES_DATA_LEN(SENSOR_UNITS_RID, res[index], i, res_inst[index], j, + units[index], UNIT_STR_MAX_SIZE, 0); INIT_OBJ_RES_DATA(MIN_MEASURED_VALUE_RID, res[index], i, res_inst[index], j, &min_measured_value[index], sizeof(*min_measured_value)); @@ -195,8 +195,8 @@ static struct lwm2m_engine_obj_inst *voltage_sensor_create(uint16_t obj_inst_id) INIT_OBJ_RES_DATA(CURRENT_CALIBRATION_RID, res[index], i, res_inst[index], j, &calibration_coefficient[index], sizeof(*calibration_coefficient)); - INIT_OBJ_RES_DATA(APPLICATION_TYPE_RID, res[index], i, res_inst[index], - j, app_type[index], APP_TYPE_STR_MAX_SIZE); + INIT_OBJ_RES_DATA_LEN(APPLICATION_TYPE_RID, res[index], i, res_inst[index], + j, app_type[index], APP_TYPE_STR_MAX_SIZE, 0); #if defined(CONFIG_LWM2M_IPSO_VOLTAGE_SENSOR_VERSION_1_1) INIT_OBJ_RES_OPTDATA(TIMESTAMP_RID, res[index], i, res_inst[index], j); diff --git a/subsys/net/lib/lwm2m/lwm2m_engine.c b/subsys/net/lib/lwm2m/lwm2m_engine.c index 651baa30ff6..45d3822bdbb 100644 --- a/subsys/net/lib/lwm2m/lwm2m_engine.c +++ b/subsys/net/lib/lwm2m/lwm2m_engine.c @@ -592,7 +592,7 @@ static void check_notifications(struct lwm2m_ctx *ctx, const int64_t timestamp) continue; } /* Check That There is not pending process*/ - if (obs->active_tx_operation) { + if (obs->active_notify != NULL) { continue; } @@ -696,8 +696,12 @@ static void socket_reset_pollfd_events(void) } /* LwM2M main work loop */ -static void socket_loop(void) +static void socket_loop(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + int i, rc; int64_t now, next; int64_t timeout, next_retransmit; @@ -983,6 +987,18 @@ int lwm2m_set_default_sockopt(struct lwm2m_ctx *ctx) return ret; } } + if (IS_ENABLED(CONFIG_LWM2M_DTLS_CID)) { + /* Enable CID */ + int cid = TLS_DTLS_CID_ENABLED; + + ret = zsock_setsockopt(ctx->sock_fd, SOL_TLS, TLS_DTLS_CID, &cid, + sizeof(cid)); + if (ret) { + ret = -errno; + LOG_ERR("Failed to enable TLS_DTLS_CID: %d", ret); + /* Not fatal, continue. */ + } + } if (ctx->hostname_verify && (ctx->desthostname != NULL)) { /** store character at len position */ @@ -1057,13 +1073,15 @@ int lwm2m_socket_start(struct lwm2m_ctx *client_ctx) int ret; #if defined(CONFIG_LWM2M_DTLS_SUPPORT) - if (client_ctx->load_credentials) { - ret = client_ctx->load_credentials(client_ctx); - } else { - ret = lwm2m_load_tls_credentials(client_ctx); - } - if (ret < 0) { - return ret; + if (client_ctx->use_dtls) { + if (client_ctx->load_credentials) { + ret = client_ctx->load_credentials(client_ctx); + } else { + ret = lwm2m_load_tls_credentials(client_ctx); + } + if (ret < 0) { + return ret; + } } #endif /* CONFIG_LWM2M_DTLS_SUPPORT */ @@ -1245,7 +1263,7 @@ static int lwm2m_engine_init(void) /* start sock receive thread */ engine_thread_id = k_thread_create(&engine_thread_data, &engine_thread_stack[0], - K_KERNEL_STACK_SIZEOF(engine_thread_stack), (k_thread_entry_t)socket_loop, + K_KERNEL_STACK_SIZEOF(engine_thread_stack), socket_loop, NULL, NULL, NULL, THREAD_PRIORITY, 0, K_NO_WAIT); k_thread_name_set(&engine_thread_data, "lwm2m-sock-recv"); LOG_DBG("LWM2M engine socket receive thread started"); diff --git a/subsys/net/lib/lwm2m/lwm2m_message_handling.c b/subsys/net/lib/lwm2m/lwm2m_message_handling.c index 678f358d1ee..6d006b4603e 100644 --- a/subsys/net/lib/lwm2m/lwm2m_message_handling.c +++ b/subsys/net/lib/lwm2m/lwm2m_message_handling.c @@ -304,6 +304,9 @@ STATIC int build_msg_block_for_send(struct lwm2m_message *msg, uint16_t block_nu } msg->cpkt.hdr_len = msg->body_encode_buffer.hdr_len; } else { + /* Keep user data between blocks */ + void *user_data = msg->reply ? msg->reply->user_data : NULL; + /* reuse message for next block. Copy token from the new query to allow * CoAP clients to use new token for every query of ongoing transaction */ @@ -323,6 +326,9 @@ STATIC int build_msg_block_for_send(struct lwm2m_message *msg, uint16_t block_nu LOG_ERR("Unable to init lwm2m message for next block!"); return ret; } + if (msg->reply) { + msg->reply->user_data = user_data; + } } /* copy the options */ @@ -1089,7 +1095,7 @@ int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst, struct lwm2m_eng break; } - len = strlen((char *)write_buf); + len = strlen((char *)write_buf) + 1; break; case LWM2M_RES_TYPE_TIME: @@ -1251,8 +1257,10 @@ static int lwm2m_read_resource_data(struct lwm2m_message *msg, void *data_ptr, s break; case LWM2M_RES_TYPE_STRING: - ret = engine_put_string(&msg->out, &msg->path, (uint8_t *)data_ptr, - strlen((uint8_t *)data_ptr)); + if (data_len) { + data_len -= 1; /* Remove the '\0' */ + } + ret = engine_put_string(&msg->out, &msg->path, (uint8_t *)data_ptr, data_len); break; case LWM2M_RES_TYPE_U32: @@ -2057,6 +2065,13 @@ static int parse_write_op(struct lwm2m_message *msg, uint16_t format) if (block_num < block_ctx->expected) { LOG_WRN("Block already handled %d, expected %d", block_num, block_ctx->expected); + (void)coap_header_set_code(msg->out.out_cpkt, COAP_RESPONSE_CODE_CONTINUE); + /* Respond with the original Block1 header, original Ack migh have been + * lost, and this is a retry. We don't know the original response, but + * since it is handled, just assume we can continue. + */ + (void)coap_append_option_int(msg->out.out_cpkt, COAP_OPTION_BLOCK1, + block_opt); return 0; } if (block_num > block_ctx->expected) { @@ -2079,30 +2094,35 @@ static int parse_write_op(struct lwm2m_message *msg, uint16_t format) * number. */ block_ctx->expected += GET_BLOCK_SIZE(block_opt) - block_ctx->ctx.block_size + 1; - - /* Handle blockwise 1 (Part 1): Set response code */ - if (!last_block) { - msg->code = COAP_RESPONSE_CODE_CONTINUE; - } } r = do_write_op(msg, format); /* Handle blockwise 1 (Part 2): Append BLOCK1 option / free context */ if (block_ctx) { - if (r >= 0 && !last_block) { - /* More to come, ack with correspond block # */ + if (r >= 0) { + /* Add block1 option to response. + * As RFC7959 Section-2.3, More flag is off, because we have already + * written the data. + */ r = coap_append_block1_option(msg->out.out_cpkt, &block_ctx->ctx); if (r < 0) { /* report as internal server error */ - LOG_ERR("Fail adding block1 option: %d", r); + LOG_DBG("Fail adding block1 option: %d", r); r = -EINVAL; } + if (!last_block) { + r = coap_header_set_code(msg->out.out_cpkt, + COAP_RESPONSE_CODE_CONTINUE); + if (r < 0) { + LOG_DBG("Failed to modify response code"); + r = -EINVAL; + } + } } if (r < 0 || last_block) { /* Free context when finished or when there is error */ free_block_ctx(block_ctx); - } } @@ -2418,7 +2438,8 @@ static int handle_request(struct coap_packet *request, struct lwm2m_message *msg goto error; } #endif - if (msg->path.obj_id == LWM2M_OBJECT_SECURITY_ID && !msg->ctx->bootstrap_mode) { + if (msg->path.level > LWM2M_PATH_LEVEL_NONE && + msg->path.obj_id == LWM2M_OBJECT_SECURITY_ID && !msg->ctx->bootstrap_mode) { r = -EACCES; goto error; } @@ -2823,7 +2844,7 @@ static void notify_message_timeout_cb(struct lwm2m_message *msg) msg->token, msg->tkl); if (obs) { - obs->active_tx_operation = false; + obs->active_notify = NULL; if (client_ctx->observe_cb) { client_ctx->observe_cb(LWM2M_OBSERVE_EVENT_NOTIFY_TIMEOUT, &msg->path, msg->reply->user_data); @@ -2895,7 +2916,7 @@ static int notify_message_reply_cb(const struct coap_packet *response, struct co reply->token, reply->tkl); if (obs) { - obs->active_tx_operation = false; + obs->active_notify = NULL; if (msg->ctx->observe_cb) { msg->ctx->observe_cb(LWM2M_OBSERVE_EVENT_NOTIFY_ACK, lwm2m_read_first_path_ptr(&obs->path_list), @@ -3068,7 +3089,7 @@ int generate_notify_message(struct lwm2m_ctx *ctx, struct observe_node *obs, voi goto cleanup; } - obs->active_tx_operation = true; + obs->active_notify = msg; obs->resource_update = false; lwm2m_information_interface_send(msg); #if defined(CONFIG_LWM2M_RESOURCE_DATA_CACHE_SUPPORT) @@ -3302,6 +3323,16 @@ int lwm2m_parse_peerinfo(char *url, struct lwm2m_ctx *client_ctx, bool is_firmwa int do_composite_read_op_for_parsed_list(struct lwm2m_message *msg, uint16_t content_format, sys_slist_t *path_list) { + struct lwm2m_obj_path_list *entry; + + /* Check access rights */ + SYS_SLIST_FOR_EACH_CONTAINER(path_list, entry, node) { + if (entry->path.level > LWM2M_PATH_LEVEL_NONE && + entry->path.obj_id == LWM2M_OBJECT_SECURITY_ID && !msg->ctx->bootstrap_mode) { + return -EACCES; + } + } + switch (content_format) { #if defined(CONFIG_LWM2M_RW_SENML_JSON_SUPPORT) diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_connmon.c b/subsys/net/lib/lwm2m/lwm2m_obj_connmon.c index acdd33ee21e..70309a0d3d6 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_connmon.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_connmon.c @@ -93,7 +93,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); /* resource state variables */ static int8_t net_bearer; static int16_t rss; -static uint8_t link_quality; +static int16_t link_quality; static uint32_t cellid; static uint16_t mnc; static uint16_t mcc; @@ -113,7 +113,7 @@ static struct lwm2m_engine_obj_field fields[] = { OBJ_FIELD_DATA(CONNMON_NETWORK_BEARER_ID, R, U8), OBJ_FIELD_DATA(CONNMON_AVAIL_NETWORK_BEARER_ID, R, U8), OBJ_FIELD_DATA(CONNMON_RADIO_SIGNAL_STRENGTH, R, S16), - OBJ_FIELD_DATA(CONNMON_LINK_QUALITY, R, U8), + OBJ_FIELD_DATA(CONNMON_LINK_QUALITY, R, S16), OBJ_FIELD_DATA(CONNMON_IP_ADDRESSES, R, STRING), OBJ_FIELD_DATA(CONNMON_ROUTER_IP_ADDRESSES, R_OPT, STRING), OBJ_FIELD_DATA(CONNMON_LINK_UTILIZATION, R_OPT, U8), diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_device.c b/subsys/net/lib/lwm2m/lwm2m_obj_device.c index 84db2f8c141..c17815795c2 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_device.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_device.c @@ -251,8 +251,8 @@ static struct lwm2m_engine_obj_inst *device_create(uint16_t obj_inst_id) NULL, current_time_post_write_cb, NULL); INIT_OBJ_RES_OPTDATA(DEVICE_UTC_OFFSET_ID, res, i, res_inst, j); INIT_OBJ_RES_OPTDATA(DEVICE_TIMEZONE_ID, res, i, res_inst, j); - INIT_OBJ_RES_DATA(DEVICE_SUPPORTED_BINDING_MODES_ID, res, i, - res_inst, j, binding_mode, DEVICE_STRING_SHORT); + INIT_OBJ_RES_DATA_LEN(DEVICE_SUPPORTED_BINDING_MODES_ID, res, i, + res_inst, j, binding_mode, DEVICE_STRING_SHORT, strlen(binding_mode) + 1); INIT_OBJ_RES_OPTDATA(DEVICE_TYPE_ID, res, i, res_inst, j); INIT_OBJ_RES_OPTDATA(DEVICE_HARDWARE_VERSION_ID, res, i, res_inst, j); INIT_OBJ_RES_OPTDATA(DEVICE_SOFTWARE_VERSION_ID, res, i, res_inst, j); diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_gateway.c b/subsys/net/lib/lwm2m/lwm2m_obj_gateway.c index 23b92fb19e5..711fd5fe127 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_gateway.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_gateway.c @@ -127,15 +127,18 @@ static struct lwm2m_engine_obj_inst *lwm2m_gw_create(uint16_t obj_inst_id) init_res_instance(res_inst[index], ARRAY_SIZE(res_inst[index])); /* initialize instance resource data */ - INIT_OBJ_RES_DATA(LWM2M_GATEWAY_DEVICE_RID, res[index], i, res_inst[index], j, - device_table[index].device_id, - CONFIG_LWM2M_GATEWAY_DEVICE_ID_MAX_STR_SIZE); - INIT_OBJ_RES(LWM2M_GATEWAY_PREFIX_RID, res[index], i, res_inst[index], j, 1, false, true, - device_table[index].prefix, CONFIG_LWM2M_GATEWAY_PREFIX_MAX_STR_SIZE, NULL, - NULL, prefix_validation_cb, NULL, NULL); - INIT_OBJ_RES_DATA(LWM2M_GATEWAY_IOT_DEVICE_OBJECTS_RID, res[index], i, res_inst[index], j, - device_table[index].iot_device_objects, - sizeof(device_table[index].iot_device_objects)); + INIT_OBJ_RES_DATA_LEN(LWM2M_GATEWAY_DEVICE_RID, res[index], i, res_inst[index], j, + device_table[index].device_id, + CONFIG_LWM2M_GATEWAY_DEVICE_ID_MAX_STR_SIZE, + strlen(device_table[index].device_id) + 1); + INIT_OBJ_RES_LEN(LWM2M_GATEWAY_PREFIX_RID, res[index], i, res_inst[index], j, 1, false, + true, device_table[index].prefix, CONFIG_LWM2M_GATEWAY_PREFIX_MAX_STR_SIZE, + strlen(device_table[index].prefix) + 1, NULL, NULL, prefix_validation_cb, + NULL, NULL); + INIT_OBJ_RES_DATA_LEN(LWM2M_GATEWAY_IOT_DEVICE_OBJECTS_RID, res[index], i, res_inst[index], + j, device_table[index].iot_device_objects, + sizeof(device_table[index].iot_device_objects), + strlen(device_table[index].iot_device_objects) + 1); inst[index].resources = res[index]; inst[index].resource_count = i; diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_portfolio.c b/subsys/net/lib/lwm2m/lwm2m_obj_portfolio.c index c06132c2514..e5cdc2198e6 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_portfolio.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_portfolio.c @@ -59,17 +59,14 @@ static struct lwm2m_engine_obj_field fields[] = { static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT]; static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][PORTFOLIO_MAX_ID]; static struct lwm2m_engine_res_inst res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT]; -static char identity[MAX_INSTANCE_COUNT*PORTFOLIO_IDENTITY_MAX][DEFAULT_IDENTITY_BUFFER_LENGTH]; +static char identity[MAX_INSTANCE_COUNT][PORTFOLIO_IDENTITY_MAX][DEFAULT_IDENTITY_BUFFER_LENGTH]; static struct lwm2m_engine_obj_inst *portfolio_create(uint16_t obj_inst_id) { - int index, avail = -1, i = 0, j = 0, indentity_buffer_start = 0; + int index, avail = -1, i = 0, j = 0; /* Check that there is no other instance with this ID */ for (index = 0; index < ARRAY_SIZE(inst); index++) { - if (index) { - indentity_buffer_start += PORTFOLIO_IDENTITY_MAX; - } if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) { LOG_ERR("Can not create instance - " "already existing: %u", @@ -95,7 +92,7 @@ static struct lwm2m_engine_obj_inst *portfolio_create(uint16_t obj_inst_id) /* initialize instance resource data */ INIT_OBJ_RES_MULTI_DATA_LEN(PORTFOLIO_IDENTITY_ID, res[avail], i, res_inst[avail], j, - PORTFOLIO_IDENTITY_MAX, false, identity[indentity_buffer_start], + PORTFOLIO_IDENTITY_MAX, false, identity[avail], DEFAULT_IDENTITY_BUFFER_LENGTH, 0); INIT_OBJ_RES_EXECUTE(PORTFOLIO_GET_AUTH_DATA_ID, res[avail], i, NULL); INIT_OBJ_RES_MULTI_OPTDATA(PORTFOLIO_AUTH_DATA_ID, res[avail], i, res_inst[avail], j, diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_server.c b/subsys/net/lib/lwm2m/lwm2m_obj_server.c index a73206df250..a1b2185ef1d 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_server.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_server.c @@ -301,11 +301,10 @@ static struct lwm2m_engine_obj_inst *server_create(uint16_t obj_inst_id) &server_flag_store_notify[index], sizeof(*server_flag_store_notify)); /* Mark Transport Binding RO as we only support UDP atm */ - INIT_OBJ_RES_DATA(SERVER_TRANSPORT_BINDING_ID, res[index], i, - res_inst[index], j, - transport_binding[index], TRANSPORT_BINDING_LEN); - INIT_OBJ_RES_EXECUTE(SERVER_REG_UPDATE_TRIGGER_ID, res[index], i, - update_trigger_cb); + INIT_OBJ_RES_DATA_LEN(SERVER_TRANSPORT_BINDING_ID, res[index], i, res_inst[index], j, + transport_binding[index], TRANSPORT_BINDING_LEN, + strlen(transport_binding[index]) + 1); + INIT_OBJ_RES_EXECUTE(SERVER_REG_UPDATE_TRIGGER_ID, res[index], i, update_trigger_cb); #if defined(CONFIG_LWM2M_SERVER_OBJECT_VERSION_1_1) INIT_OBJ_RES_EXECUTE(SERVER_BOOTSTRAP_UPDATE_TRIGGER_ID, res[index], i, bootstrap_trigger_cb); diff --git a/subsys/net/lib/lwm2m/lwm2m_object.h b/subsys/net/lib/lwm2m/lwm2m_object.h index 170a99c023d..26322f50b1b 100644 --- a/subsys/net/lib/lwm2m/lwm2m_object.h +++ b/subsys/net/lib/lwm2m/lwm2m_object.h @@ -251,7 +251,7 @@ struct lwm2m_engine_obj { if (_ri_ptr != NULL && _ri_count > 0) { \ for (int _i = 0; _i < _ri_count; _i++) { \ _ri_ptr[_ri_idx + _i].data_ptr = \ - (_data_ptr + _i); \ + ((uint8_t *) _data_ptr + (_i * _data_sz)); \ _ri_ptr[_ri_idx + _i].max_data_len = \ _data_sz; \ _ri_ptr[_ri_idx + _i].data_len = \ diff --git a/subsys/net/lib/lwm2m/lwm2m_observation.c b/subsys/net/lib/lwm2m/lwm2m_observation.c index 91ab9c1709a..9ee1fa6eda1 100644 --- a/subsys/net/lib/lwm2m/lwm2m_observation.c +++ b/subsys/net/lib/lwm2m/lwm2m_observation.c @@ -438,7 +438,7 @@ static void engine_observe_node_init(struct observe_node *obs, const uint8_t *to obs->event_timestamp = 0; } obs->resource_update = false; - obs->active_tx_operation = false; + obs->active_notify = NULL; obs->format = format; obs->counter = OBSERVE_COUNTER_START; sys_slist_append(&ctx->observer, &obs->node); @@ -529,7 +529,7 @@ struct observe_node *engine_observe_node_discover(sys_slist_t *observe_node_list const uint8_t *token, uint8_t tkl) { struct observe_node *obs; - int obs_list_size, path_list_size; + int obs_list_size, path_list_size = 0; if (lwm2m_path_list) { path_list_size = engine_path_list_size(lwm2m_path_list); @@ -596,6 +596,12 @@ static int engine_add_observer(struct lwm2m_message *msg, const uint8_t *token, memcpy(obs->token, token, tkl); obs->tkl = tkl; + /* Cancel ongoing notification */ + if (obs->active_notify != NULL) { + lwm2m_reset_message(obs->active_notify, true); + obs->active_notify = NULL; + } + LOG_DBG("OBSERVER DUPLICATE %u/%u/%u(%u) [%s]", msg->path.obj_id, msg->path.obj_inst_id, msg->path.res_id, msg->path.level, lwm2m_sprint_ip_addr(&msg->ctx->remote_addr)); @@ -679,6 +685,12 @@ static int engine_add_composite_observer(struct lwm2m_message *msg, const uint8_ memcpy(obs->token, token, tkl); obs->tkl = tkl; + /* Cancel ongoing notification */ + if (obs->active_notify != NULL) { + lwm2m_reset_message(obs->active_notify, true); + obs->active_notify = NULL; + } + LOG_DBG("OBSERVER Composite DUPLICATE [%s]", lwm2m_sprint_ip_addr(&msg->ctx->remote_addr)); diff --git a/subsys/net/lib/lwm2m/lwm2m_observation.h b/subsys/net/lib/lwm2m/lwm2m_observation.h index 95e60ab0a19..d74df74aab4 100644 --- a/subsys/net/lib/lwm2m/lwm2m_observation.h +++ b/subsys/net/lib/lwm2m/lwm2m_observation.h @@ -14,16 +14,16 @@ int lwm2m_notify_observer_path(const struct lwm2m_obj_path *path); struct observe_node { sys_snode_t node; - sys_slist_t path_list; /* List of Observation path */ - uint8_t token[MAX_TOKEN_LEN]; /* Observation Token */ - int64_t event_timestamp; /* Timestamp for trig next Notify */ - int64_t last_timestamp; /* Timestamp from last Notify */ + sys_slist_t path_list; /* List of Observation path */ + uint8_t token[MAX_TOKEN_LEN]; /* Observation Token */ + int64_t event_timestamp; /* Timestamp for trig next Notify */ + int64_t last_timestamp; /* Timestamp from last Notify */ + struct lwm2m_message *active_notify; /* Currently active notification */ uint32_t counter; uint16_t format; uint8_t tkl; - bool resource_update : 1; /* Resource is updated */ - bool composite : 1; /* Composite Observation */ - bool active_tx_operation : 1; /* Active Notification process ongoing */ + bool resource_update : 1; /* Resource is updated */ + bool composite : 1; /* Composite Observation */ }; /* Attribute handling. */ diff --git a/subsys/net/lib/lwm2m/lwm2m_rd_client.c b/subsys/net/lib/lwm2m/lwm2m_rd_client.c index ca539fcded6..d9f2e229edd 100644 --- a/subsys/net/lib/lwm2m/lwm2m_rd_client.c +++ b/subsys/net/lib/lwm2m/lwm2m_rd_client.c @@ -770,16 +770,20 @@ static int sm_send_bootstrap_registration(void) goto cleanup; } - /* TODO: handle return error */ - coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_PATH, - "bs", strlen("bs")); + ret = coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_PATH, + "bs", strlen("bs")); + if (ret < 0) { + goto cleanup; + } snprintk(query_buffer, sizeof(query_buffer) - 1, "ep=%s", client.ep_name); - /* TODO: handle return error */ - coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_QUERY, - query_buffer, strlen(query_buffer)); + ret = coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_QUERY, + query_buffer, strlen(query_buffer)); + if (ret < 0) { + goto cleanup; + } if (IS_ENABLED(CONFIG_LWM2M_VERSION_1_1)) { int pct = LWM2M_FORMAT_OMA_TLV; diff --git a/subsys/net/lib/lwm2m/lwm2m_registry.c b/subsys/net/lib/lwm2m/lwm2m_registry.c index fc297149d84..210c5525756 100644 --- a/subsys/net/lib/lwm2m/lwm2m_registry.c +++ b/subsys/net/lib/lwm2m/lwm2m_registry.c @@ -50,6 +50,41 @@ void lwm2m_registry_unlock(void) { (void)k_mutex_unlock(®istry_lock); } + +/* Default core object version */ +struct default_obj_version { + uint16_t obj_id; + uint8_t version_major; + uint8_t version_minor; +}; + +/* Based on Appendix E of the respective LwM2M specification. */ +static const struct default_obj_version default_obj_versions[] = { +#if defined(CONFIG_LWM2M_VERSION_1_0) + { LWM2M_OBJECT_SECURITY_ID, 1, 0 }, + { LWM2M_OBJECT_SERVER_ID, 1, 0 }, + { LWM2M_OBJECT_ACCESS_CONTROL_ID, 1, 0 }, + { LWM2M_OBJECT_DEVICE_ID, 1, 0 }, + { LWM2M_OBJECT_CONNECTIVITY_MONITORING_ID, 1, 0 }, + { LWM2M_OBJECT_FIRMWARE_ID, 1, 0 }, + { LWM2M_OBJECT_LOCATION_ID, 1, 0 }, + { LWM2M_OBJECT_CONNECTIVITY_STATISTICS_ID, 1, 0 }, +#elif defined(CONFIG_LWM2M_VERSION_1_1) + { LWM2M_OBJECT_SECURITY_ID, 1, 1 }, + { LWM2M_OBJECT_SERVER_ID, 1, 1 }, + { LWM2M_OBJECT_ACCESS_CONTROL_ID, 1, 0 }, + { LWM2M_OBJECT_DEVICE_ID, 1, 1 }, + { LWM2M_OBJECT_CONNECTIVITY_MONITORING_ID, 1, 2 }, + { LWM2M_OBJECT_FIRMWARE_ID, 1, 0 }, + { LWM2M_OBJECT_LOCATION_ID, 1, 0 }, + { LWM2M_OBJECT_CONNECTIVITY_STATISTICS_ID, 1, 0 }, + /* OSCORE object not implemented yet, but include it for completeness */ + { LWM2M_OBJECT_OSCORE_ID, 1, 0 }, +#else +#error "Default core object versions not defined for LwM2M version" +#endif +}; + /* Resources */ static sys_slist_t engine_obj_list; static sys_slist_t engine_obj_inst_list; @@ -1975,12 +2010,22 @@ struct lwm2m_engine_res_inst *lwm2m_engine_get_res_inst(const struct lwm2m_obj_p bool lwm2m_engine_shall_report_obj_version(const struct lwm2m_engine_obj *obj) { - if (obj->is_core) { - return obj->version_major != LWM2M_PROTOCOL_VERSION_MAJOR || - obj->version_minor != LWM2M_PROTOCOL_VERSION_MINOR; + /* For non-core objects, report version other than 1.0 */ + if (!obj->is_core) { + return obj->version_major != 1 || obj->version_minor != 0; } - return obj->version_major != 1 || obj->version_minor != 0; + /* For core objects, report version based on default version array. */ + for (size_t i = 0; i < ARRAY_SIZE(default_obj_versions); i++) { + if (obj->obj_id != default_obj_versions[i].obj_id) { + continue; + } + + return obj->version_major != default_obj_versions[i].version_major || + obj->version_minor != default_obj_versions[i].version_minor; + } + + return true; } #if defined(CONFIG_LWM2M_RESOURCE_DATA_CACHE_SUPPORT) diff --git a/subsys/net/lib/lwm2m/lwm2m_rw_link_format.c b/subsys/net/lib/lwm2m/lwm2m_rw_link_format.c index 0cf8b440434..597641450be 100644 --- a/subsys/net/lib/lwm2m/lwm2m_rw_link_format.c +++ b/subsys/net/lib/lwm2m/lwm2m_rw_link_format.c @@ -20,22 +20,19 @@ LOG_MODULE_REGISTER(net_lwm2m_link_format, CONFIG_LWM2M_LOG_LEVEL); /* * TODO: to implement a way for clients to specify alternate path * via Kconfig (LwM2M specification 8.2.2 Alternate Path) - * - * For now, in order to inform server we support JSON format, we have to - * report 'ct=11543' to the server. '' is required in order to append - * content attribute. And resource type attribute is appended because of - * Eclipse wakaama will reject the registration when 'rt="oma.lwm2m"' is - * missing. */ - +/* + * In order to inform the server about the configured LwM2M content format, we have + * to report 'ct=' with the content type value to the server. The root path '' + * is required in order to append the content type attribute. + */ #if defined(CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT) #define REG_PREFACE ";ct=" STRINGIFY(LWM2M_FORMAT_APP_SENML_CBOR) #elif defined(CONFIG_LWM2M_RW_SENML_JSON_SUPPORT) #define REG_PREFACE ";ct=" STRINGIFY(LWM2M_FORMAT_APP_SEML_JSON) #elif defined(CONFIG_LWM2M_RW_JSON_SUPPORT) -#define REG_PREFACE ";rt=\"oma.lwm2m\"" \ - ";ct=" STRINGIFY(LWM2M_FORMAT_OMA_JSON) +#define REG_PREFACE ";ct=" STRINGIFY(LWM2M_FORMAT_OMA_JSON) #else #define REG_PREFACE "" #endif diff --git a/subsys/net/lib/lwm2m/lwm2m_rw_senml_cbor.c b/subsys/net/lib/lwm2m/lwm2m_rw_senml_cbor.c index 15dc9a9451e..dd963aa0583 100644 --- a/subsys/net/lib/lwm2m/lwm2m_rw_senml_cbor.c +++ b/subsys/net/lib/lwm2m/lwm2m_rw_senml_cbor.c @@ -940,10 +940,10 @@ int do_composite_read_op_senml_cbor(struct lwm2m_message *msg) lwm2m_engine_clear_duplicate_path(&lwm_path_list, &lwm_path_free_list); - return do_composite_read_op_for_parsed_path_senml_cbor(msg, &lwm_path_list); + return do_composite_read_op_for_parsed_list(msg, LWM2M_FORMAT_APP_SENML_CBOR, + &lwm_path_list); } - int do_write_op_senml_cbor(struct lwm2m_message *msg) { uint_fast8_t dret; diff --git a/subsys/net/lib/lwm2m/lwm2m_rw_senml_json.c b/subsys/net/lib/lwm2m/lwm2m_rw_senml_json.c index a504ecceba2..6d2bb2b96b6 100644 --- a/subsys/net/lib/lwm2m/lwm2m_rw_senml_json.c +++ b/subsys/net/lib/lwm2m/lwm2m_rw_senml_json.c @@ -1653,7 +1653,7 @@ int do_composite_read_op_senml_json(struct lwm2m_message *msg) /* Clear path which are part are part of recursive path /1 will include /1/0/1 */ lwm2m_engine_clear_duplicate_path(&path_list, &free_list); - return do_composite_read_op_for_parsed_list_senml_json(msg, &path_list); + return do_composite_read_op_for_parsed_list(msg, LWM2M_FORMAT_APP_SEML_JSON, &path_list); } int do_send_op_senml_json(struct lwm2m_message *msg, sys_slist_t *lwm2m_path_list) diff --git a/subsys/net/lib/lwm2m/lwm2m_shell.c b/subsys/net/lib/lwm2m/lwm2m_shell.c index 335004ec5d5..a4cedf8cd62 100644 --- a/subsys/net/lib/lwm2m/lwm2m_shell.c +++ b/subsys/net/lib/lwm2m/lwm2m_shell.c @@ -39,7 +39,8 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); "-sX\tWrite value as intX_t\n" \ "-f \tWrite value as float\n" \ "-t \tWrite value as time_t\n" -#define LWM2M_HELP_CREATE "create PATH\nCreate object instance\n" +#define LWM2M_HELP_CREATE "create PATH\nCreate object or resource instance\n" +#define LWM2M_HELP_DELETE "delete PATH\nDelete object or resource instance\n" #define LWM2M_HELP_START "start EP_NAME [BOOTSTRAP FLAG]\n" \ "Start the LwM2M RD (Registration / Discovery) Client\n" \ "-b \tSet the bootstrap flag (default 0)\n" @@ -54,6 +55,11 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); "PATH is LwM2M path\n" \ "NUM how many elements to cache\n" \ +static void send_cb(enum lwm2m_send_status status) +{ + LOG_INF("SEND status: %d\n", status); +} + static int cmd_send(const struct shell *sh, size_t argc, char **argv) { int ret = 0; @@ -85,7 +91,7 @@ static int cmd_send(const struct shell *sh, size_t argc, char **argv) } } - ret = lwm2m_send_cb(ctx, lwm2m_path_list, path_cnt, NULL); + ret = lwm2m_send_cb(ctx, lwm2m_path_list, path_cnt, send_cb); if (ret < 0) { shell_error(sh, "can't do send operation, request failed (%d)\n", ret); @@ -322,8 +328,10 @@ static int cmd_write(const struct shell *sh, size_t argc, char **argv) } else if (strcmp(dtype, "-f") == 0) { double new = 0; - lwm2m_atof(value, &new); /* Convert string -> float */ - ret = lwm2m_set_f64(&path, new); + ret = lwm2m_atof(value, &new); /* Convert string -> float */ + if (ret == 0) { + ret = lwm2m_set_f64(&path, new); + } } else { /* All the types using stdlib funcs*/ char *e; @@ -371,10 +379,9 @@ static int cmd_write(const struct shell *sh, size_t argc, char **argv) return 0; } -static int cmd_create(const struct shell *sh, size_t argc, char **argv) +static int cmd_create_or_delete(const struct shell *sh, bool delete, size_t argc, char **argv) { struct lwm2m_obj_path path; - struct lwm2m_engine_obj_inst *obj_inst; int ret; if (argc < 2) { @@ -389,22 +396,48 @@ static int cmd_create(const struct shell *sh, size_t argc, char **argv) return -ENOEXEC; } - if (path.level != LWM2M_PATH_LEVEL_OBJECT_INST) { - shell_error(sh, "path is not an object instance\n"); - shell_help(sh); - return -EINVAL; + if (delete) { + switch (path.level) { + case LWM2M_PATH_LEVEL_RESOURCE_INST: + ret = lwm2m_delete_res_inst(&path); + break; + case LWM2M_PATH_LEVEL_OBJECT_INST: + ret = lwm2m_delete_object_inst(&path); + break; + default: + return -ENOEXEC; + } + } else { + switch (path.level) { + case LWM2M_PATH_LEVEL_RESOURCE_INST: + ret = lwm2m_create_res_inst(&path); + break; + case LWM2M_PATH_LEVEL_OBJECT_INST: + ret = lwm2m_create_object_inst(&path); + break; + default: + return -ENOEXEC; + } } - ret = lwm2m_create_obj_inst(path.obj_id, path.obj_inst_id, &obj_inst); if (ret < 0) { - shell_error(sh, "Failed to create object instance %d/%d, ret=%d", path.obj_id, - path.obj_inst_id, ret); + shell_error(sh, "operation failed, %d\n", ret); return -ENOEXEC; } return 0; } +static int cmd_create(const struct shell *sh, size_t argc, char **argv) +{ + return cmd_create_or_delete(sh, false, argc, argv); +} + +static int cmd_delete(const struct shell *sh, size_t argc, char **argv) +{ + return cmd_create_or_delete(sh, true, argc, argv); +} + static int cmd_start(const struct shell *sh, size_t argc, char **argv) { struct lwm2m_ctx *ctx = lwm2m_rd_client_ctx(); @@ -595,6 +628,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE( SHELL_CMD_ARG(read, NULL, LWM2M_HELP_READ, cmd_read, 2, 1), SHELL_CMD_ARG(write, NULL, LWM2M_HELP_WRITE, cmd_write, 3, 1), SHELL_CMD_ARG(create, NULL, LWM2M_HELP_CREATE, cmd_create, 2, 0), + SHELL_CMD_ARG(delete, NULL, LWM2M_HELP_DELETE, cmd_delete, 2, 0), SHELL_CMD_ARG(cache, NULL, LWM2M_HELP_CACHE, cmd_cache, 3, 0), SHELL_CMD_ARG(start, NULL, LWM2M_HELP_START, cmd_start, 2, 2), SHELL_CMD_ARG(stop, NULL, LWM2M_HELP_STOP, cmd_stop, 1, 1), diff --git a/subsys/net/lib/lwm2m/ucifi_lpwan.c b/subsys/net/lib/lwm2m/ucifi_lpwan.c index 4210387a201..82878724405 100644 --- a/subsys/net/lib/lwm2m/ucifi_lpwan.c +++ b/subsys/net/lib/lwm2m/ucifi_lpwan.c @@ -132,8 +132,8 @@ static struct lwm2m_engine_obj_inst *lpwan_create(uint16_t obj_inst_id) j, NETWORK_ADDRESS_MAX, false); INIT_OBJ_RES_MULTI_OPTDATA(UCIFI_LPWAN_SECONDARY_ADDRESS_RID, res[index], i, res_inst[index], j, SECONDARY_NETWORK_ADDRESS_MAX, false); - INIT_OBJ_RES_DATA(UCIFI_LPWAN_MAC_ADDRESS_RID, res[index], i, res_inst[index], j, - mac[index], MAC_ADDRESS_SIZE); + INIT_OBJ_RES_DATA_LEN(UCIFI_LPWAN_MAC_ADDRESS_RID, res[index], i, res_inst[index], j, + mac[index], MAC_ADDRESS_SIZE, 0); INIT_OBJ_RES_MULTI_OPTDATA(UCIFI_LPWAN_PEER_ADDRESS_RID, res[index], i, res_inst[index], j, PEER_ADDRESS_MAX, false); INIT_OBJ_RES_MULTI_OPTDATA(UCIFI_LPWAN_MULTICAST_GRP_ADDRESS_RID, res[index], i, diff --git a/subsys/net/lib/mqtt_sn/mqtt_sn.c b/subsys/net/lib/mqtt_sn/mqtt_sn.c index 95b79d490d6..213ca55753f 100644 --- a/subsys/net/lib/mqtt_sn/mqtt_sn.c +++ b/subsys/net/lib/mqtt_sn/mqtt_sn.c @@ -24,7 +24,6 @@ struct mqtt_sn_confirmable { int64_t last_attempt; uint16_t msg_id; uint8_t retries; - bool in_use; }; struct mqtt_sn_publish { @@ -37,8 +36,6 @@ struct mqtt_sn_publish { bool retain; }; -static struct mqtt_sn_publish mqtt_sn_pubs[CONFIG_MQTT_SN_LIB_MAX_PUBLISH]; - enum mqtt_sn_topic_state { MQTT_SN_TOPIC_STATE_REGISTERING, MQTT_SN_TOPIC_STATE_REGISTERED, @@ -58,7 +55,9 @@ struct mqtt_sn_topic { enum mqtt_sn_topic_state state; }; -static struct mqtt_sn_topic topics[CONFIG_MQTT_SN_LIB_MAX_TOPICS]; +K_MEM_SLAB_DEFINE_STATIC(publishes, sizeof(struct mqtt_sn_publish), + CONFIG_MQTT_SN_LIB_MAX_PUBLISH, 4); +K_MEM_SLAB_DEFINE_STATIC(topics, sizeof(struct mqtt_sn_topic), CONFIG_MQTT_SN_LIB_MAX_TOPICS, 4); enum mqtt_sn_client_state { MQTT_SN_CLIENT_DISCONNECTED, @@ -126,13 +125,12 @@ static void mqtt_sn_con_init(struct mqtt_sn_confirmable *con) con->last_attempt = 0; con->retries = N_RETRY; con->msg_id = next_msg_id(); - con->in_use = true; } static void mqtt_sn_publish_destroy(struct mqtt_sn_client *client, struct mqtt_sn_publish *pub) { sys_slist_find_and_remove(&client->publish, &pub->next); - memset(pub, 0, sizeof(*pub)); + k_mem_slab_free(&publishes, (void *)pub); } static void mqtt_sn_publish_destroy_all(struct mqtt_sn_client *client) @@ -142,32 +140,21 @@ static void mqtt_sn_publish_destroy_all(struct mqtt_sn_client *client) while ((next = sys_slist_get(&client->publish)) != NULL) { pub = SYS_SLIST_CONTAINER(next, pub, next); - memset(pub, 0, sizeof(*pub)); - } -} - -static struct mqtt_sn_publish *mqtt_sn_publish_find_empty(void) -{ - size_t i; - - for (i = 0; i < ARRAY_SIZE(mqtt_sn_pubs); i++) { - if (!mqtt_sn_pubs[i].con.in_use) { - return &mqtt_sn_pubs[i]; - } + k_mem_slab_free(&publishes, (void *)pub); } - - return NULL; } static struct mqtt_sn_publish *mqtt_sn_publish_create(struct mqtt_sn_data *data) { - struct mqtt_sn_publish *pub = mqtt_sn_publish_find_empty(); + struct mqtt_sn_publish *pub; - if (!pub) { + if (k_mem_slab_alloc(&publishes, (void **)&pub, K_NO_WAIT)) { LOG_ERR("Can't create PUB: no free slot"); return NULL; } + memset(pub, 0, sizeof(*pub)); + if (data && data->data && data->size) { if (data->size > sizeof(pub->pubdata)) { LOG_ERR("Can't create PUB: Too much data (%" PRIu16 ")", data->size); @@ -211,28 +198,17 @@ static struct mqtt_sn_publish *mqtt_sn_publish_find_topic(struct mqtt_sn_client return NULL; } -static struct mqtt_sn_topic *mqtt_sn_topic_find_empty(void) -{ - size_t i; - - for (i = 0; i < ARRAY_SIZE(topics); i++) { - if (!topics[i].con.in_use) { - return &topics[i]; - } - } - - return NULL; -} - static struct mqtt_sn_topic *mqtt_sn_topic_create(struct mqtt_sn_data *name) { - struct mqtt_sn_topic *topic = mqtt_sn_topic_find_empty(); + struct mqtt_sn_topic *topic; - if (!topic) { + if (k_mem_slab_alloc(&topics, (void **)&topic, K_NO_WAIT)) { LOG_ERR("Can't create topic: no free slot"); return NULL; } + memset(topic, 0, sizeof(*topic)); + if (!name || !name->data || !name->size) { LOG_ERR("Can't create topic with empty name"); return NULL; @@ -291,7 +267,6 @@ static void mqtt_sn_topic_destroy(struct mqtt_sn_client *client, struct mqtt_sn_ } sys_slist_find_and_remove(&client->topic, &topic->next); - memset(topic, 0, sizeof(*topic)); } static void mqtt_sn_topic_destroy_all(struct mqtt_sn_client *client) @@ -308,7 +283,7 @@ static void mqtt_sn_topic_destroy_all(struct mqtt_sn_client *client) mqtt_sn_publish_destroy(client, pub); } - memset(topic, 0, sizeof(*topic)); + k_mem_slab_free(&topics, (void *)topic); } } @@ -892,6 +867,7 @@ int mqtt_sn_publish(struct mqtt_sn_client *client, enum mqtt_sn_qos qos, pub = mqtt_sn_publish_create(data); if (!pub) { + k_work_reschedule(&client->process_work, K_NO_WAIT); return -ENOMEM; } diff --git a/subsys/net/lib/shell/CMakeLists.txt b/subsys/net/lib/shell/CMakeLists.txt new file mode 100644 index 00000000000..2c5c0757505 --- /dev/null +++ b/subsys/net/lib/shell/CMakeLists.txt @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library_sources(net_shell.c) +zephyr_library_include_directories(. ${ZEPHYR_BASE}/subsys/net/l2) +zephyr_library_include_directories(. ${ZEPHYR_BASE}/subsys/net/lib) +zephyr_library_include_directories(. ${ZEPHYR_BASE}/subsys/net/ip) +zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS) + +zephyr_library_sources(allocs.c) +zephyr_library_sources(arp.c) +zephyr_library_sources(capture.c) +zephyr_library_sources(conn.c) +zephyr_library_sources(dns.c) +zephyr_library_sources(events.c) +zephyr_library_sources(gptp.c) +zephyr_library_sources(iface.c) +zephyr_library_sources(ipv4.c) +zephyr_library_sources(ipv6.c) +zephyr_library_sources(mem.c) +zephyr_library_sources(nbr.c) +zephyr_library_sources(ping.c) +zephyr_library_sources(pkt.c) +zephyr_library_sources(ppp.c) +zephyr_library_sources(resume.c) +zephyr_library_sources(route.c) +zephyr_library_sources(sockets.c) +zephyr_library_sources(stats.c) +zephyr_library_sources(suspend.c) +zephyr_library_sources(tcp.c) +zephyr_library_sources(udp.c) +zephyr_library_sources(virtual.c) +zephyr_library_sources(vlan.c) +zephyr_library_sources(websocket.c) diff --git a/subsys/net/lib/shell/allocs.c b/subsys/net/lib/shell/allocs.c new file mode 100644 index 00000000000..a2669590520 --- /dev/null +++ b/subsys/net/lib/shell/allocs.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#include "net_shell_private.h" + +#if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC) +static void allocs_cb(struct net_pkt *pkt, + struct net_buf *buf, + const char *func_alloc, + int line_alloc, + const char *func_free, + int line_free, + bool in_use, + void *user_data) +{ + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + const char *str; + + if (in_use) { + str = "used"; + } else { + if (func_alloc) { + str = "free"; + } else { + str = "avail"; + } + } + + if (buf) { + goto buf; + } + + if (func_alloc) { + if (in_use) { + PR("%p/%ld\t%5s\t%5s\t%s():%d\n", + pkt, atomic_get(&pkt->atomic_ref), str, + net_pkt_slab2str(pkt->slab), + func_alloc, line_alloc); + } else { + PR("%p\t%5s\t%5s\t%s():%d -> %s():%d\n", + pkt, str, net_pkt_slab2str(pkt->slab), + func_alloc, line_alloc, func_free, + line_free); + } + } + + return; +buf: + if (func_alloc) { + struct net_buf_pool *pool = net_buf_pool_get(buf->pool_id); + + if (in_use) { + PR("%p/%d\t%5s\t%5s\t%s():%d\n", + buf, buf->ref, + str, net_pkt_pool2str(pool), func_alloc, + line_alloc); + } else { + PR("%p\t%5s\t%5s\t%s():%d -> %s():%d\n", + buf, str, net_pkt_pool2str(pool), + func_alloc, line_alloc, func_free, + line_free); + } + } +} +#endif /* CONFIG_NET_DEBUG_NET_PKT_ALLOC */ + +static int cmd_net_allocs(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC) + struct net_shell_user_data user_data; +#endif + + ARG_UNUSED(argc); + ARG_UNUSED(argv); + +#if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC) + user_data.sh = sh; + + PR("Network memory allocations\n\n"); + PR("memory\t\tStatus\tPool\tFunction alloc -> freed\n"); + net_pkt_allocs_foreach(allocs_cb, &user_data); +#else + PR_INFO("Set %s to enable %s support.\n", + "CONFIG_NET_DEBUG_NET_PKT_ALLOC", "net_pkt allocation"); +#endif /* CONFIG_NET_DEBUG_NET_PKT_ALLOC */ + + return 0; +} + +SHELL_SUBCMD_ADD((net), allocs, NULL, + "Print network memory allocations.", + cmd_net_allocs, 1, 0); diff --git a/subsys/net/lib/shell/arp.c b/subsys/net/lib/shell/arp.c new file mode 100644 index 00000000000..58889f27d5c --- /dev/null +++ b/subsys/net/lib/shell/arp.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#include "net_shell_private.h" + +#if defined(CONFIG_NET_ARP) +#include "ethernet/arp.h" +#endif + +#if defined(CONFIG_NET_ARP) && defined(CONFIG_NET_NATIVE) +static void arp_cb(struct arp_entry *entry, void *user_data) +{ + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + int *count = data->user_data; + + if (*count == 0) { + PR(" Interface Link Address\n"); + } + + PR("[%2d] %d %s %s\n", *count, + net_if_get_by_iface(entry->iface), + net_sprint_ll_addr(entry->eth.addr, sizeof(struct net_eth_addr)), + net_sprint_ipv4_addr(&entry->ip)); + + (*count)++; +} +#endif /* CONFIG_NET_ARP */ + +#if !defined(CONFIG_NET_ARP) +static void print_arp_error(const struct shell *sh) +{ + PR_INFO("Set %s to enable %s support.\n", + "CONFIG_NET_NATIVE, CONFIG_NET_ARP, CONFIG_NET_IPV4 and" + " CONFIG_NET_L2_ETHERNET", "ARP"); +} +#endif + +static int cmd_net_arp(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_ARP) + struct net_shell_user_data user_data; + int arg = 1; +#endif + + ARG_UNUSED(argc); + +#if defined(CONFIG_NET_ARP) + if (!argv[arg]) { + /* ARP cache content */ + int count = 0; + + user_data.sh = sh; + user_data.user_data = &count; + + if (net_arp_foreach(arp_cb, &user_data) == 0) { + PR("ARP cache is empty.\n"); + } + } +#else + print_arp_error(sh); +#endif + + return 0; +} + +static int cmd_net_arp_flush(const struct shell *sh, size_t argc, char *argv[]) +{ + ARG_UNUSED(argc); + ARG_UNUSED(argv); + +#if defined(CONFIG_NET_ARP) + PR("Flushing ARP cache.\n"); + net_arp_clear_cache(NULL); +#else + print_arp_error(sh); +#endif + + return 0; +} + +SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_arp, + SHELL_CMD(flush, NULL, "Remove all entries from ARP cache.", + cmd_net_arp_flush), + SHELL_SUBCMD_SET_END +); + +SHELL_SUBCMD_ADD((net), arp, &net_cmd_arp, + "Print information about IPv4 ARP cache.", + cmd_net_arp, 1, 0); diff --git a/subsys/net/lib/shell/capture.c b/subsys/net/lib/shell/capture.c new file mode 100644 index 00000000000..0c7347f8774 --- /dev/null +++ b/subsys/net/lib/shell/capture.c @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#include + +#include "net_shell_private.h" + +#include + +#if defined(CONFIG_NET_CAPTURE) +static const struct device *capture_dev; + +static void get_address_str(const struct sockaddr *addr, + char *str, int str_len) +{ + if (IS_ENABLED(CONFIG_NET_IPV6) && addr->sa_family == AF_INET6) { + snprintk(str, str_len, "[%s]:%u", + net_sprint_ipv6_addr(&net_sin6(addr)->sin6_addr), + ntohs(net_sin6(addr)->sin6_port)); + + } else if (IS_ENABLED(CONFIG_NET_IPV4) && addr->sa_family == AF_INET) { + snprintk(str, str_len, "%s:%d", + net_sprint_ipv4_addr(&net_sin(addr)->sin_addr), + ntohs(net_sin(addr)->sin_port)); + + } else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) && + addr->sa_family == AF_PACKET) { + snprintk(str, str_len, "AF_PACKET"); + } else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) && + addr->sa_family == AF_CAN) { + snprintk(str, str_len, "AF_CAN"); + } else if (addr->sa_family == AF_UNSPEC) { + snprintk(str, str_len, "AF_UNSPEC"); + } else { + snprintk(str, str_len, "AF_UNK(%d)", addr->sa_family); + } +} + +static void capture_cb(struct net_capture_info *info, void *user_data) +{ + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + int *count = data->user_data; + char addr_local[ADDR_LEN + 7]; + char addr_peer[ADDR_LEN + 7]; + + if (*count == 0) { + PR(" \t\tCapture Tunnel\n"); + PR("Device\t\tiface iface Local\t\t\tPeer\n"); + } + + get_address_str(info->local, addr_local, sizeof(addr_local)); + get_address_str(info->peer, addr_peer, sizeof(addr_peer)); + + PR("%s\t%c %d %s\t%s\n", info->capture_dev->name, + info->is_enabled ? + (net_if_get_by_iface(info->capture_iface) + '0') : '-', + net_if_get_by_iface(info->tunnel_iface), + addr_local, addr_peer); + + (*count)++; +} +#endif + +static int cmd_net_capture(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_CAPTURE) + bool ret; + + if (capture_dev == NULL) { + PR_INFO("Network packet capture %s\n", "not configured"); + } else { + struct net_shell_user_data user_data; + int count = 0; + + ret = net_capture_is_enabled(capture_dev); + PR_INFO("Network packet capture %s\n", + ret ? "enabled" : "disabled"); + + user_data.sh = sh; + user_data.user_data = &count; + + net_capture_foreach(capture_cb, &user_data); + } +#else + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + PR_INFO("Set %s to enable %s support.\n", + "CONFIG_NET_CAPTURE", "network packet capture"); +#endif + return 0; +} + +static int cmd_net_capture_setup(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_CAPTURE) + int ret, arg = 1; + const char *remote, *local, *peer; + + remote = argv[arg++]; + if (!remote) { + PR_WARNING("Remote IP address not specified.\n"); + return -ENOEXEC; + } + + local = argv[arg++]; + if (!local) { + PR_WARNING("Local IP address not specified.\n"); + return -ENOEXEC; + } + + peer = argv[arg]; + if (!peer) { + PR_WARNING("Peer IP address not specified.\n"); + return -ENOEXEC; + } + + if (capture_dev != NULL) { + PR_INFO("Capture already setup, cleaning up settings.\n"); + net_capture_cleanup(capture_dev); + capture_dev = NULL; + } + + ret = net_capture_setup(remote, local, peer, &capture_dev); + if (ret < 0) { + PR_WARNING("Capture cannot be setup (%d)\n", ret); + return -ENOEXEC; + } + + PR_INFO("Capture setup done, next enable it by " + "\"net capture enable \"\n"); +#else + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + PR_INFO("Set %s to enable %s support.\n", + "CONFIG_NET_CAPTURE", "network packet capture"); +#endif + + return 0; +} + +static int cmd_net_capture_cleanup(const struct shell *sh, size_t argc, char *argv[]) +{ + ARG_UNUSED(argc); + ARG_UNUSED(argv); + +#if defined(CONFIG_NET_CAPTURE) + int ret; + + if (capture_dev == NULL) { + return 0; + } + + ret = net_capture_cleanup(capture_dev); + if (ret < 0) { + PR_WARNING("Capture %s failed (%d)\n", "cleanup", ret); + return -ENOEXEC; + } + + capture_dev = NULL; +#else + PR_INFO("Set %s to enable %s support.\n", + "CONFIG_NET_CAPTURE", "network packet capture"); +#endif + + return 0; +} + +static int cmd_net_capture_enable(const struct shell *sh, size_t argc, char *argv[]) +{ + ARG_UNUSED(argc); + ARG_UNUSED(argv); + +#if defined(CONFIG_NET_CAPTURE) + int ret, arg = 1, if_index; + struct net_if *iface; + + if (capture_dev == NULL) { + return 0; + } + + if (argv[arg] == NULL) { + PR_WARNING("Interface index is missing. Please give interface " + "what you want to monitor\n"); + return -ENOEXEC; + } + + if_index = atoi(argv[arg++]); + if (if_index == 0) { + PR_WARNING("Interface index %d is invalid.\n", if_index); + return -ENOEXEC; + } + + iface = net_if_get_by_index(if_index); + if (iface == NULL) { + PR_WARNING("No such interface with index %d\n", if_index); + return -ENOEXEC; + } + + ret = net_capture_enable(capture_dev, iface); + if (ret < 0) { + PR_WARNING("Capture %s failed (%d)\n", "enable", ret); + return -ENOEXEC; + } +#else + PR_INFO("Set %s to enable %s support.\n", + "CONFIG_NET_CAPTURE", "network packet capture"); +#endif + + return 0; +} + +static int cmd_net_capture_disable(const struct shell *sh, size_t argc, char *argv[]) +{ + ARG_UNUSED(argc); + ARG_UNUSED(argv); + +#if defined(CONFIG_NET_CAPTURE) + int ret; + + if (capture_dev == NULL) { + return 0; + } + + ret = net_capture_disable(capture_dev); + if (ret < 0) { + PR_WARNING("Capture %s failed (%d)\n", "disable", ret); + return -ENOEXEC; + } +#else + PR_INFO("Set %s to enable %s support.\n", + "CONFIG_NET_CAPTURE", "network packet capture"); +#endif + + return 0; +} + +SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_capture, + SHELL_CMD(setup, NULL, "Setup network packet capture.\n" + "'net capture setup '\n" + " is the (outer) endpoint IP address,\n" + " is the (inner) local IP address,\n" + " is the (inner) peer IP address\n" + "Local and Peer addresses can have UDP port number in them (optional)\n" + "like 198.0.51.2:9000 or [2001:db8:100::2]:4242", + cmd_net_capture_setup), + SHELL_CMD(cleanup, NULL, "Cleanup network packet capture.", + cmd_net_capture_cleanup), + SHELL_CMD(enable, NULL, "Enable network packet capture for a given " + "network interface.\n" + "'net capture enable '", + cmd_net_capture_enable), + SHELL_CMD(disable, NULL, "Disable network packet capture.", + cmd_net_capture_disable), + SHELL_SUBCMD_SET_END +); + +SHELL_SUBCMD_ADD((net), capture, &net_cmd_capture, + "Configure network packet capture.", cmd_net_capture, 1, 0); diff --git a/subsys/net/lib/shell/conn.c b/subsys/net/lib/shell/conn.c new file mode 100644 index 00000000000..24b528537bd --- /dev/null +++ b/subsys/net/lib/shell/conn.c @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#include "net_shell_private.h" + +#if defined(CONFIG_NET_TCP) +#include "tcp_internal.h" +#include +#endif + +#if defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE) +static void context_cb(struct net_context *context, void *user_data) +{ +#if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4) +#define ADDR_LEN NET_IPV6_ADDR_LEN +#elif defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6) +#define ADDR_LEN NET_IPV4_ADDR_LEN +#else +#define ADDR_LEN NET_IPV6_ADDR_LEN +#endif + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + int *count = data->user_data; + /* +7 for []:port */ + char addr_local[ADDR_LEN + 7]; + char addr_remote[ADDR_LEN + 7] = ""; + + get_addresses(context, addr_local, sizeof(addr_local), + addr_remote, sizeof(addr_remote)); + + PR("[%2d] %p\t%d %c%c%c %16s\t%16s\n", + (*count) + 1, context, + net_if_get_by_iface(net_context_get_iface(context)), + net_context_get_family(context) == AF_INET6 ? '6' : + (net_context_get_family(context) == AF_INET ? '4' : ' '), + net_context_get_type(context) == SOCK_DGRAM ? 'D' : + (net_context_get_type(context) == SOCK_STREAM ? 'S' : + (net_context_get_type(context) == SOCK_RAW ? 'R' : ' ')), + net_context_get_proto(context) == IPPROTO_UDP ? 'U' : + (net_context_get_proto(context) == IPPROTO_TCP ? 'T' : ' '), + addr_local, addr_remote); + + (*count)++; +} +#endif /* CONFIG_NET_OFFLOAD || CONFIG_NET_NATIVE */ + +#if CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG +static void conn_handler_cb(struct net_conn *conn, void *user_data) +{ +#if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4) +#define ADDR_LEN NET_IPV6_ADDR_LEN +#elif defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6) +#define ADDR_LEN NET_IPV4_ADDR_LEN +#else +#define ADDR_LEN NET_IPV6_ADDR_LEN +#endif + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + int *count = data->user_data; + /* +7 for []:port */ + char addr_local[ADDR_LEN + 7]; + char addr_remote[ADDR_LEN + 7] = ""; + + if (IS_ENABLED(CONFIG_NET_IPV6) && conn->local_addr.sa_family == AF_INET6) { + snprintk(addr_local, sizeof(addr_local), "[%s]:%u", + net_sprint_ipv6_addr( + &net_sin6(&conn->local_addr)->sin6_addr), + ntohs(net_sin6(&conn->local_addr)->sin6_port)); + snprintk(addr_remote, sizeof(addr_remote), "[%s]:%u", + net_sprint_ipv6_addr( + &net_sin6(&conn->remote_addr)->sin6_addr), + ntohs(net_sin6(&conn->remote_addr)->sin6_port)); + + } else if (IS_ENABLED(CONFIG_NET_IPV4) && conn->local_addr.sa_family == AF_INET) { + snprintk(addr_local, sizeof(addr_local), "%s:%d", + net_sprint_ipv4_addr( + &net_sin(&conn->local_addr)->sin_addr), + ntohs(net_sin(&conn->local_addr)->sin_port)); + snprintk(addr_remote, sizeof(addr_remote), "%s:%d", + net_sprint_ipv4_addr( + &net_sin(&conn->remote_addr)->sin_addr), + ntohs(net_sin(&conn->remote_addr)->sin_port)); + + } else if (conn->local_addr.sa_family == AF_UNSPEC) { + snprintk(addr_local, sizeof(addr_local), "AF_UNSPEC"); + } else { + snprintk(addr_local, sizeof(addr_local), "AF_UNK(%d)", + conn->local_addr.sa_family); + } + + PR("[%2d] %p %p\t%s\t%16s\t%16s\n", + (*count) + 1, conn, conn->cb, + net_proto2str(conn->local_addr.sa_family, conn->proto), + addr_local, addr_remote); + + (*count)++; +} +#endif /* CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG */ + +#if CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG +struct tcp_detail_info { + int printed_send_queue_header; + int printed_details; + int count; +}; +#endif + +#if defined(CONFIG_NET_TCP) && \ + (defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE)) +static void tcp_cb(struct tcp *conn, void *user_data) +{ + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + int *count = data->user_data; + uint16_t recv_mss = net_tcp_get_supported_mss(conn); + + PR("%p %p %5u %5u %10u %10u %5u %s\n", + conn, conn->context, + ntohs(net_sin6_ptr(&conn->context->local)->sin6_port), + ntohs(net_sin6(&conn->context->remote)->sin6_port), + conn->seq, conn->ack, recv_mss, + net_tcp_state_str(net_tcp_get_state(conn))); + + (*count)++; +} + +#if CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG +static void tcp_sent_list_cb(struct tcp *conn, void *user_data) +{ + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + struct tcp_detail_info *details = data->user_data; + struct net_pkt *pkt; + sys_snode_t *node; + + if (conn->state != TCP_LISTEN) { + if (!details->printed_details) { + PR("\nTCP Ref Recv_win Send_win Pending " + "Unacked Flags Queue\n"); + details->printed_details = true; + } + + PR("%p %ld %u\t %u\t %zd\t %d\t %d/%d/%d %s\n", + conn, atomic_get(&conn->ref_count), conn->recv_win, + conn->send_win, conn->send_data_total, conn->unacked_len, + conn->in_retransmission, conn->in_connect, conn->in_close, + sys_slist_is_empty(&conn->send_queue) ? "empty" : "data"); + + details->count++; + } + + if (sys_slist_is_empty(&conn->send_queue)) { + return; + } + + if (!details->printed_send_queue_header) { + PR("\nTCP packets waiting ACK:\n"); + PR("TCP net_pkt[ref/totlen]->net_buf[ref/len]..." + "\n"); + } + + PR("%p ", conn); + + node = sys_slist_peek_head(&conn->send_queue); + if (node) { + pkt = CONTAINER_OF(node, struct net_pkt, next); + if (pkt) { + struct net_buf *frag = pkt->frags; + + if (!details->printed_send_queue_header) { + PR("%p[%ld/%zd]", pkt, + atomic_get(&pkt->atomic_ref), + net_pkt_get_len(pkt)); + details->printed_send_queue_header = true; + } else { + PR(" %p[%ld/%zd]", + pkt, atomic_get(&pkt->atomic_ref), + net_pkt_get_len(pkt)); + } + + if (frag) { + PR("->"); + } + + while (frag) { + PR("%p[%d/%d]", frag, frag->ref, frag->len); + + frag = frag->frags; + if (frag) { + PR("->"); + } + } + + PR("\n"); + } + } + + details->printed_send_queue_header = true; +} +#endif /* CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG */ +#endif /* TCP */ + +static int cmd_net_conn(const struct shell *sh, size_t argc, char *argv[]) +{ + ARG_UNUSED(argc); + ARG_UNUSED(argv); + +#if defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE) + struct net_shell_user_data user_data; + int count = 0; + + PR(" Context \tIface Flags Local Remote\n"); + + user_data.sh = sh; + user_data.user_data = &count; + + net_context_foreach(context_cb, &user_data); + + if (count == 0) { + PR("No connections\n"); + } + +#if CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG + PR("\n Handler Callback \tProto\tLocal \tRemote\n"); + + count = 0; + + net_conn_foreach(conn_handler_cb, &user_data); + + if (count == 0) { + PR("No connection handlers found.\n"); + } +#endif + +#if defined(CONFIG_NET_TCP) + PR("\nTCP Context Src port Dst port " + "Send-Seq Send-Ack MSS State\n"); + + count = 0; + + net_tcp_foreach(tcp_cb, &user_data); + + if (count == 0) { + PR("No TCP connections\n"); + } else { +#if CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG + /* Print information about pending packets */ + struct tcp_detail_info details; + + count = 0; + + if (IS_ENABLED(CONFIG_NET_TCP)) { + memset(&details, 0, sizeof(details)); + user_data.user_data = &details; + } + + net_tcp_foreach(tcp_sent_list_cb, &user_data); + + if (IS_ENABLED(CONFIG_NET_TCP)) { + if (details.count == 0) { + PR("No active connections.\n"); + } + } +#endif /* CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG */ + } + +#if CONFIG_NET_TCP_LOG_LEVEL < LOG_LEVEL_DBG + PR_INFO("Set %s to enable %s support.\n", + "CONFIG_NET_TCP_LOG_LEVEL_DBG", "TCP debugging"); +#endif /* CONFIG_NET_TCP_LOG_LEVEL < LOG_LEVEL_DBG */ + +#endif + +#if defined(CONFIG_NET_IPV6_FRAGMENT) + count = 0; + + net_ipv6_frag_foreach(ipv6_frag_cb, &user_data); + + /* Do not print anything if no fragments are pending atm */ +#endif + +#else + PR_INFO("Set %s to enable %s support.\n", + "CONFIG_NET_OFFLOAD or CONFIG_NET_NATIVE", + "connection information"); + +#endif /* CONFIG_NET_OFFLOAD || CONFIG_NET_NATIVE */ + + return 0; +} + + +SHELL_SUBCMD_ADD((net), conn, NULL, "Print information about network connections.", + cmd_net_conn, 1, 0); diff --git a/subsys/net/lib/shell/dns.c b/subsys/net/lib/shell/dns.c new file mode 100644 index 00000000000..54c768cecd1 --- /dev/null +++ b/subsys/net/lib/shell/dns.c @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#include + +#include "net_shell_private.h" + +#if defined(CONFIG_DNS_RESOLVER) +static void dns_result_cb(enum dns_resolve_status status, + struct dns_addrinfo *info, + void *user_data) +{ + const struct shell *sh = user_data; + + if (status == DNS_EAI_CANCELED) { + PR_WARNING("dns: Timeout while resolving name.\n"); + return; + } + + if (status == DNS_EAI_INPROGRESS && info) { + char addr[NET_IPV6_ADDR_LEN]; + + if (info->ai_family == AF_INET) { + net_addr_ntop(AF_INET, + &net_sin(&info->ai_addr)->sin_addr, + addr, NET_IPV4_ADDR_LEN); + } else if (info->ai_family == AF_INET6) { + net_addr_ntop(AF_INET6, + &net_sin6(&info->ai_addr)->sin6_addr, + addr, NET_IPV6_ADDR_LEN); + } else { + strncpy(addr, "Invalid protocol family", + sizeof(addr)); + /* strncpy() doesn't guarantee NUL byte at the end. */ + addr[sizeof(addr) - 1] = 0; + } + + PR("dns: %s\n", addr); + return; + } + + if (status == DNS_EAI_ALLDONE) { + PR("dns: All results received\n"); + return; + } + + if (status == DNS_EAI_FAIL) { + PR_WARNING("dns: No such name found.\n"); + return; + } + + PR_WARNING("dns: Unhandled status %d received\n", status); +} + +static void print_dns_info(const struct shell *sh, + struct dns_resolve_context *ctx) +{ + int i; + + PR("DNS servers:\n"); + + for (i = 0; i < CONFIG_DNS_RESOLVER_MAX_SERVERS + + DNS_MAX_MCAST_SERVERS; i++) { + if (ctx->servers[i].dns_server.sa_family == AF_INET) { + PR("\t%s:%u\n", + net_sprint_ipv4_addr( + &net_sin(&ctx->servers[i].dns_server)-> + sin_addr), + ntohs(net_sin( + &ctx->servers[i].dns_server)->sin_port)); + } else if (ctx->servers[i].dns_server.sa_family == AF_INET6) { + PR("\t[%s]:%u\n", + net_sprint_ipv6_addr( + &net_sin6(&ctx->servers[i].dns_server)-> + sin6_addr), + ntohs(net_sin6( + &ctx->servers[i].dns_server)->sin6_port)); + } + } + + PR("Pending queries:\n"); + + for (i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) { + int32_t remaining; + + if (!ctx->queries[i].cb || !ctx->queries[i].query) { + continue; + } + + remaining = k_ticks_to_ms_ceil32( + k_work_delayable_remaining_get(&ctx->queries[i].timer)); + + if (ctx->queries[i].query_type == DNS_QUERY_TYPE_A) { + PR("\tIPv4[%u]: %s remaining %d\n", + ctx->queries[i].id, + ctx->queries[i].query, + remaining); + } else if (ctx->queries[i].query_type == DNS_QUERY_TYPE_AAAA) { + PR("\tIPv6[%u]: %s remaining %d\n", + ctx->queries[i].id, + ctx->queries[i].query, + remaining); + } + } +} +#endif + +static int cmd_net_dns_cancel(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_DNS_RESOLVER) + struct dns_resolve_context *ctx; + int ret, i; +#endif + + ARG_UNUSED(argc); + ARG_UNUSED(argv); + +#if defined(CONFIG_DNS_RESOLVER) + ctx = dns_resolve_get_default(); + if (!ctx) { + PR_WARNING("No default DNS context found.\n"); + return -ENOEXEC; + } + + for (ret = 0, i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) { + if (!ctx->queries[i].cb) { + continue; + } + + if (!dns_resolve_cancel(ctx, ctx->queries[i].id)) { + ret++; + } + } + + if (ret) { + PR("Cancelled %d pending requests.\n", ret); + } else { + PR("No pending DNS requests.\n"); + } +#else + PR_INFO("Set %s to enable %s support.\n", "CONFIG_DNS_RESOLVER", + "DNS resolver"); +#endif + + return 0; +} + +static int cmd_net_dns_query(const struct shell *sh, size_t argc, char *argv[]) +{ + +#if defined(CONFIG_DNS_RESOLVER) +#define DNS_TIMEOUT (MSEC_PER_SEC * 2) /* ms */ + enum dns_query_type qtype = DNS_QUERY_TYPE_A; + char *host, *type = NULL; + int ret, arg = 1; + + host = argv[arg++]; + if (!host) { + PR_WARNING("Hostname not specified.\n"); + return -ENOEXEC; + } + + if (argv[arg]) { + type = argv[arg]; + } + + if (type) { + if (strcmp(type, "A") == 0) { + qtype = DNS_QUERY_TYPE_A; + PR("IPv4 address type\n"); + } else if (strcmp(type, "AAAA") == 0) { + qtype = DNS_QUERY_TYPE_AAAA; + PR("IPv6 address type\n"); + } else { + PR_WARNING("Unknown query type, specify either " + "A or AAAA\n"); + return -ENOEXEC; + } + } + + ret = dns_get_addr_info(host, qtype, NULL, dns_result_cb, + (void *)sh, DNS_TIMEOUT); + if (ret < 0) { + PR_WARNING("Cannot resolve '%s' (%d)\n", host, ret); + } else { + PR("Query for '%s' sent.\n", host); + } +#else + PR_INFO("DNS resolver not supported. Set CONFIG_DNS_RESOLVER to " + "enable it.\n"); +#endif + + return 0; +} + +static int cmd_net_dns(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_DNS_RESOLVER) + struct dns_resolve_context *ctx; +#endif + +#if defined(CONFIG_DNS_RESOLVER) + if (argv[1]) { + /* So this is a query then */ + cmd_net_dns_query(sh, argc, argv); + return 0; + } + + /* DNS status */ + ctx = dns_resolve_get_default(); + if (!ctx) { + PR_WARNING("No default DNS context found.\n"); + return -ENOEXEC; + } + + print_dns_info(sh, ctx); +#else + PR_INFO("DNS resolver not supported. Set CONFIG_DNS_RESOLVER to " + "enable it.\n"); +#endif + + return 0; +} + +SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_dns, + SHELL_CMD(cancel, NULL, "Cancel all pending requests.", + cmd_net_dns_cancel), + SHELL_CMD(query, NULL, + "'net dns [A or AAAA]' queries IPv4 address " + "(default) or IPv6 address for a host name.", + cmd_net_dns_query), + SHELL_SUBCMD_SET_END +); + +SHELL_SUBCMD_ADD((net), dns, &net_cmd_dns, + "Show how DNS is configured. Optionally do a query using a given name.", + cmd_net_dns, 1, 2); diff --git a/subsys/net/lib/shell/events.c b/subsys/net/lib/shell/events.c new file mode 100644 index 00000000000..5a5d0f38f7d --- /dev/null +++ b/subsys/net/lib/shell/events.c @@ -0,0 +1,430 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#include +#include +#include +#include + +#include "net_shell_private.h" + +#if defined(CONFIG_NET_MGMT_EVENT_MONITOR) +#define EVENT_MON_STACK_SIZE 1024 +#define THREAD_PRIORITY K_PRIO_COOP(2) +#define MAX_EVENT_INFO_SIZE NET_EVENT_INFO_MAX_SIZE +#define MONITOR_L2_MASK (_NET_EVENT_IF_BASE) +#define MONITOR_L3_IPV4_MASK (_NET_EVENT_IPV4_BASE) +#define MONITOR_L3_IPV6_MASK (_NET_EVENT_IPV6_BASE) +#define MONITOR_L4_MASK (_NET_EVENT_L4_BASE) + +static bool net_event_monitoring; +static bool net_event_shutting_down; +static struct net_mgmt_event_callback l2_cb; +static struct net_mgmt_event_callback l3_ipv4_cb; +static struct net_mgmt_event_callback l3_ipv6_cb; +static struct net_mgmt_event_callback l4_cb; +static struct k_thread event_mon; +static K_THREAD_STACK_DEFINE(event_mon_stack, EVENT_MON_STACK_SIZE); + +struct event_msg { + struct net_if *iface; + size_t len; + uint32_t event; + uint8_t data[MAX_EVENT_INFO_SIZE]; +}; + +K_MSGQ_DEFINE(event_mon_msgq, sizeof(struct event_msg), + CONFIG_NET_MGMT_EVENT_QUEUE_SIZE, sizeof(intptr_t)); + +static void event_handler(struct net_mgmt_event_callback *cb, + uint32_t mgmt_event, struct net_if *iface) +{ + struct event_msg msg; + int ret; + + memset(&msg, 0, sizeof(msg)); + + msg.len = MIN(sizeof(msg.data), cb->info_length); + msg.event = mgmt_event; + msg.iface = iface; + + if (cb->info_length > 0) { + memcpy(msg.data, cb->info, msg.len); + } + + ret = k_msgq_put(&event_mon_msgq, (void *)&msg, K_MSEC(10)); + if (ret < 0) { + NET_ERR("Cannot write to msgq (%d)\n", ret); + } +} + +static const char *get_l2_desc(uint32_t event) +{ + static const char *desc = ""; + + switch (event) { + case NET_EVENT_IF_DOWN: + desc = "down"; + break; + case NET_EVENT_IF_UP: + desc = "up"; + break; + } + + return desc; +} + +static char *get_l3_desc(struct event_msg *msg, + const char **desc, const char **desc2, + char *extra_info, size_t extra_info_len) +{ + static const char *desc_unknown = ""; + char *info = NULL; + + *desc = desc_unknown; + + switch (msg->event) { + case NET_EVENT_IPV6_ADDR_ADD: + *desc = "IPv6 address"; + *desc2 = "add"; + info = net_addr_ntop(AF_INET6, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV6_ADDR_DEL: + *desc = "IPv6 address"; + *desc2 = "del"; + info = net_addr_ntop(AF_INET6, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV6_MADDR_ADD: + *desc = "IPv6 mcast address"; + *desc2 = "add"; + info = net_addr_ntop(AF_INET6, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV6_MADDR_DEL: + *desc = "IPv6 mcast address"; + *desc2 = "del"; + info = net_addr_ntop(AF_INET6, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV6_PREFIX_ADD: + *desc = "IPv6 prefix"; + *desc2 = "add"; + info = net_addr_ntop(AF_INET6, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV6_PREFIX_DEL: + *desc = "IPv6 prefix"; + *desc2 = "del"; + info = net_addr_ntop(AF_INET6, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV6_MCAST_JOIN: + *desc = "IPv6 mcast"; + *desc2 = "join"; + info = net_addr_ntop(AF_INET6, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV6_MCAST_LEAVE: + *desc = "IPv6 mcast"; + *desc2 = "leave"; + info = net_addr_ntop(AF_INET6, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV6_ROUTER_ADD: + *desc = "IPv6 router"; + *desc2 = "add"; + info = net_addr_ntop(AF_INET6, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV6_ROUTER_DEL: + *desc = "IPv6 router"; + *desc2 = "del"; + info = net_addr_ntop(AF_INET6, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV6_ROUTE_ADD: + *desc = "IPv6 route"; + *desc2 = "add"; + info = net_addr_ntop(AF_INET6, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV6_ROUTE_DEL: + *desc = "IPv6 route"; + *desc2 = "del"; + info = net_addr_ntop(AF_INET6, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV6_DAD_SUCCEED: + *desc = "IPv6 DAD"; + *desc2 = "ok"; + info = net_addr_ntop(AF_INET6, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV6_DAD_FAILED: + *desc = "IPv6 DAD"; + *desc2 = "fail"; + info = net_addr_ntop(AF_INET6, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV6_NBR_ADD: + *desc = "IPv6 neighbor"; + *desc2 = "add"; + info = net_addr_ntop(AF_INET6, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV6_NBR_DEL: + *desc = "IPv6 neighbor"; + *desc2 = "del"; + info = net_addr_ntop(AF_INET6, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV4_ADDR_ADD: + *desc = "IPv4 address"; + *desc2 = "add"; + info = net_addr_ntop(AF_INET, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV4_ADDR_DEL: + *desc = "IPv4 address"; + *desc2 = "del"; + info = net_addr_ntop(AF_INET, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV4_ROUTER_ADD: + *desc = "IPv4 router"; + *desc2 = "add"; + info = net_addr_ntop(AF_INET, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV4_ROUTER_DEL: + *desc = "IPv4 router"; + *desc2 = "del"; + info = net_addr_ntop(AF_INET, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV4_DHCP_START: + *desc = "DHCPv4"; + *desc2 = "start"; + break; + case NET_EVENT_IPV4_DHCP_BOUND: + *desc = "DHCPv4"; + *desc2 = "bound"; +#if defined(CONFIG_NET_DHCPV4) + struct net_if_dhcpv4 *data = (struct net_if_dhcpv4 *)msg->data; + + info = net_addr_ntop(AF_INET, &data->requested_ip, extra_info, + extra_info_len); +#endif + break; + case NET_EVENT_IPV4_DHCP_STOP: + *desc = "DHCPv4"; + *desc2 = "stop"; + break; + } + + return info; +} + +static const char *get_l4_desc(uint32_t event) +{ + static const char *desc = ""; + + switch (event) { + case NET_EVENT_L4_CONNECTED: + desc = "connected"; + break; + case NET_EVENT_L4_DISCONNECTED: + desc = "disconnected"; + break; + case NET_EVENT_DNS_SERVER_ADD: + desc = "DNS server add"; + break; + case NET_EVENT_DNS_SERVER_DEL: + desc = "DNS server del"; + break; + } + + return desc; +} + +/* We use a separate thread in order not to do any shell printing from + * event handler callback (to avoid stack size issues). + */ +static void event_mon_handler(const struct shell *sh) +{ + char extra_info[NET_IPV6_ADDR_LEN]; + struct event_msg msg; + + net_mgmt_init_event_callback(&l2_cb, event_handler, + MONITOR_L2_MASK); + net_mgmt_add_event_callback(&l2_cb); + + net_mgmt_init_event_callback(&l3_ipv4_cb, event_handler, + MONITOR_L3_IPV4_MASK); + net_mgmt_add_event_callback(&l3_ipv4_cb); + + net_mgmt_init_event_callback(&l3_ipv6_cb, event_handler, + MONITOR_L3_IPV6_MASK); + net_mgmt_add_event_callback(&l3_ipv6_cb); + + net_mgmt_init_event_callback(&l4_cb, event_handler, + MONITOR_L4_MASK); + net_mgmt_add_event_callback(&l4_cb); + + while (net_event_shutting_down == false) { + const char *layer_str = ""; + const char *desc = "", *desc2 = ""; + char *info = NULL; + uint32_t layer; + + (void)k_msgq_get(&event_mon_msgq, &msg, K_FOREVER); + + if (msg.iface == NULL && msg.event == 0 && msg.len == 0) { + /* This is the stop message */ + continue; + } + + layer = NET_MGMT_GET_LAYER(msg.event); + if (layer == NET_MGMT_LAYER_L2) { + layer_str = "L2"; + desc = get_l2_desc(msg.event); + } else if (layer == NET_MGMT_LAYER_L3) { + layer_str = "L3"; + info = get_l3_desc(&msg, &desc, &desc2, + extra_info, NET_IPV6_ADDR_LEN); + } else if (layer == NET_MGMT_LAYER_L4) { + layer_str = "L4"; + desc = get_l4_desc(msg.event); + } + + PR_INFO("EVENT: %s [%d] %s%s%s%s%s\n", layer_str, + net_if_get_by_iface(msg.iface), desc, + desc2 ? " " : "", desc2 ? desc2 : "", + info ? " " : "", info ? info : ""); + } + + net_mgmt_del_event_callback(&l2_cb); + net_mgmt_del_event_callback(&l3_ipv4_cb); + net_mgmt_del_event_callback(&l3_ipv6_cb); + net_mgmt_del_event_callback(&l4_cb); + + k_msgq_purge(&event_mon_msgq); + + net_event_monitoring = false; + net_event_shutting_down = false; + + PR_INFO("Network event monitoring %s.\n", "disabled"); +} +#endif + +static int cmd_net_events_on(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_MGMT_EVENT_MONITOR) + k_tid_t tid; + + if (net_event_monitoring) { + PR_INFO("Network event monitoring is already %s.\n", + "enabled"); + return -ENOEXEC; + } + + tid = k_thread_create(&event_mon, event_mon_stack, + K_THREAD_STACK_SIZEOF(event_mon_stack), + (k_thread_entry_t)event_mon_handler, + (void *)sh, NULL, NULL, THREAD_PRIORITY, 0, + K_FOREVER); + if (!tid) { + PR_ERROR("Cannot create network event monitor thread!"); + return -ENOEXEC; + } + + k_thread_name_set(tid, "event_mon"); + + PR_INFO("Network event monitoring %s.\n", "enabled"); + + net_event_monitoring = true; + net_event_shutting_down = false; + + k_thread_start(tid); +#else + PR_INFO("Network management events are not supported. " + "Set CONFIG_NET_MGMT_EVENT_MONITOR to enable it.\n"); +#endif + + return 0; +} + +static int cmd_net_events_off(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_MGMT_EVENT_MONITOR) + static const struct event_msg msg; + int ret; + + if (!net_event_monitoring) { + PR_INFO("Network event monitoring is already %s.\n", + "disabled"); + return -ENOEXEC; + } + + net_event_shutting_down = true; + + ret = k_msgq_put(&event_mon_msgq, (void *)&msg, K_MSEC(100)); + if (ret < 0) { + PR_ERROR("Cannot write to msgq (%d)\n", ret); + return -ENOEXEC; + } +#else + PR_INFO("Network management events are not supported. " + "Set CONFIG_NET_MGMT_EVENT_MONITOR to enable it.\n"); +#endif + + return 0; +} + +static int cmd_net_events(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_MGMT_EVENT_MONITOR) + PR("Network event monitoring is %s.\n", + net_event_monitoring ? "enabled" : "disabled"); + + if (!argv[1]) { + PR_INFO("Give 'on' to enable event monitoring and " + "'off' to disable it.\n"); + } +#else + PR_INFO("Network management events are not supported. " + "Set CONFIG_NET_MGMT_EVENT_MONITOR to enable it.\n"); +#endif + + return 0; +} + +void events_enable(void) +{ + static const char * const argv[] = { + "on", + NULL + }; + + (void)cmd_net_events_on(shell_backend_uart_get_ptr(), 1, (char **)argv); +} + +SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_events, + SHELL_CMD(on, NULL, "Turn on network event monitoring.", + cmd_net_events_on), + SHELL_CMD(off, NULL, "Turn off network event monitoring.", + cmd_net_events_off), + SHELL_SUBCMD_SET_END +); + +SHELL_SUBCMD_ADD((net), events, &net_cmd_events, "Monitor network management events.", + cmd_net_events, 1, 1); diff --git a/subsys/net/lib/shell/gptp.c b/subsys/net/lib/shell/gptp.c new file mode 100644 index 00000000000..0de653e26cd --- /dev/null +++ b/subsys/net/lib/shell/gptp.c @@ -0,0 +1,652 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#include + +#if defined(CONFIG_NET_GPTP) +#include +#include "ethernet/gptp/gptp_messages.h" +#include "ethernet/gptp/gptp_md.h" +#include "ethernet/gptp/gptp_state.h" +#include "ethernet/gptp/gptp_data_set.h" +#include "ethernet/gptp/gptp_private.h" +#endif + +#include "net_shell_private.h" + +#if defined(CONFIG_NET_GPTP) +static const char *selected_role_str(int port); + +static void gptp_port_cb(int port, struct net_if *iface, void *user_data) +{ + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + int *count = data->user_data; + + if (*count == 0) { + PR("Port Interface \tRole\n"); + } + + (*count)++; + + PR("%2d %p [%d] \t%s\n", port, iface, net_if_get_by_iface(iface), + selected_role_str(port)); +} + +static const char *pdelay_req2str(enum gptp_pdelay_req_states state) +{ + switch (state) { + case GPTP_PDELAY_REQ_NOT_ENABLED: + return "REQ_NOT_ENABLED"; + case GPTP_PDELAY_REQ_INITIAL_SEND_REQ: + return "INITIAL_SEND_REQ"; + case GPTP_PDELAY_REQ_RESET: + return "REQ_RESET"; + case GPTP_PDELAY_REQ_SEND_REQ: + return "SEND_REQ"; + case GPTP_PDELAY_REQ_WAIT_RESP: + return "WAIT_RESP"; + case GPTP_PDELAY_REQ_WAIT_FOLLOW_UP: + return "WAIT_FOLLOW_UP"; + case GPTP_PDELAY_REQ_WAIT_ITV_TIMER: + return "WAIT_ITV_TIMER"; + } + + return ""; +}; + +static const char *pdelay_resp2str(enum gptp_pdelay_resp_states state) +{ + switch (state) { + case GPTP_PDELAY_RESP_NOT_ENABLED: + return "RESP_NOT_ENABLED"; + case GPTP_PDELAY_RESP_INITIAL_WAIT_REQ: + return "INITIAL_WAIT_REQ"; + case GPTP_PDELAY_RESP_WAIT_REQ: + return "WAIT_REQ"; + case GPTP_PDELAY_RESP_WAIT_TSTAMP: + return "WAIT_TSTAMP"; + } + + return ""; +} + +static const char *sync_rcv2str(enum gptp_sync_rcv_states state) +{ + switch (state) { + case GPTP_SYNC_RCV_DISCARD: + return "DISCARD"; + case GPTP_SYNC_RCV_WAIT_SYNC: + return "WAIT_SYNC"; + case GPTP_SYNC_RCV_WAIT_FOLLOW_UP: + return "WAIT_FOLLOW_UP"; + } + + return ""; +} + +static const char *sync_send2str(enum gptp_sync_send_states state) +{ + switch (state) { + case GPTP_SYNC_SEND_INITIALIZING: + return "INITIALIZING"; + case GPTP_SYNC_SEND_SEND_SYNC: + return "SEND_SYNC"; + case GPTP_SYNC_SEND_SEND_FUP: + return "SEND_FUP"; + } + + return ""; +} + +static const char *pss_rcv2str(enum gptp_pss_rcv_states state) +{ + switch (state) { + case GPTP_PSS_RCV_DISCARD: + return "DISCARD"; + case GPTP_PSS_RCV_RECEIVED_SYNC: + return "RECEIVED_SYNC"; + } + + return ""; +} + +static const char *pss_send2str(enum gptp_pss_send_states state) +{ + switch (state) { + case GPTP_PSS_SEND_TRANSMIT_INIT: + return "TRANSMIT_INIT"; + case GPTP_PSS_SEND_SYNC_RECEIPT_TIMEOUT: + return "SYNC_RECEIPT_TIMEOUT"; + case GPTP_PSS_SEND_SEND_MD_SYNC: + return "SEND_MD_SYNC"; + case GPTP_PSS_SEND_SET_SYNC_RECEIPT_TIMEOUT: + return "SET_SYNC_RECEIPT_TIMEOUT"; + } + + return ""; +} + +static const char *pa_rcv2str(enum gptp_pa_rcv_states state) +{ + switch (state) { + case GPTP_PA_RCV_DISCARD: + return "DISCARD"; + case GPTP_PA_RCV_RECEIVE: + return "RECEIVE"; + } + + return ""; +}; + +static const char *pa_info2str(enum gptp_pa_info_states state) +{ + switch (state) { + case GPTP_PA_INFO_DISABLED: + return "DISABLED"; + case GPTP_PA_INFO_POST_DISABLED: + return "POST_DISABLED"; + case GPTP_PA_INFO_AGED: + return "AGED"; + case GPTP_PA_INFO_UPDATE: + return "UPDATE"; + case GPTP_PA_INFO_CURRENT: + return "CURRENT"; + case GPTP_PA_INFO_RECEIVE: + return "RECEIVE"; + case GPTP_PA_INFO_SUPERIOR_MASTER_PORT: + return "SUPERIOR_MASTER_PORT"; + case GPTP_PA_INFO_REPEATED_MASTER_PORT: + return "REPEATED_MASTER_PORT"; + case GPTP_PA_INFO_INFERIOR_MASTER_OR_OTHER_PORT: + return "INFERIOR_MASTER_OR_OTHER_PORT"; + } + + return ""; +}; + +static const char *pa_transmit2str(enum gptp_pa_transmit_states state) +{ + switch (state) { + case GPTP_PA_TRANSMIT_INIT: + return "INIT"; + case GPTP_PA_TRANSMIT_PERIODIC: + return "PERIODIC"; + case GPTP_PA_TRANSMIT_IDLE: + return "IDLE"; + case GPTP_PA_TRANSMIT_POST_IDLE: + return "POST_IDLE"; + } + + return ""; +}; + +static const char *site_sync2str(enum gptp_site_sync_sync_states state) +{ + switch (state) { + case GPTP_SSS_INITIALIZING: + return "INITIALIZING"; + case GPTP_SSS_RECEIVING_SYNC: + return "RECEIVING_SYNC"; + } + + return ""; +} + +static const char *clk_slave2str(enum gptp_clk_slave_sync_states state) +{ + switch (state) { + case GPTP_CLK_SLAVE_SYNC_INITIALIZING: + return "INITIALIZING"; + case GPTP_CLK_SLAVE_SYNC_SEND_SYNC_IND: + return "SEND_SYNC_IND"; + } + + return ""; +}; + +static const char *pr_selection2str(enum gptp_pr_selection_states state) +{ + switch (state) { + case GPTP_PR_SELECTION_INIT_BRIDGE: + return "INIT_BRIDGE"; + case GPTP_PR_SELECTION_ROLE_SELECTION: + return "ROLE_SELECTION"; + } + + return ""; +}; + +static const char *cms_rcv2str(enum gptp_cms_rcv_states state) +{ + switch (state) { + case GPTP_CMS_RCV_INITIALIZING: + return "INITIALIZING"; + case GPTP_CMS_RCV_WAITING: + return "WAITING"; + case GPTP_CMS_RCV_SOURCE_TIME: + return "SOURCE_TIME"; + } + + return ""; +}; + +#if !defined(USCALED_NS_TO_NS) +#define USCALED_NS_TO_NS(val) (val >> 16) +#endif + +static const char *selected_role_str(int port) +{ + switch (GPTP_GLOBAL_DS()->selected_role[port]) { + case GPTP_PORT_INITIALIZING: + return "INITIALIZING"; + case GPTP_PORT_FAULTY: + return "FAULTY"; + case GPTP_PORT_DISABLED: + return "DISABLED"; + case GPTP_PORT_LISTENING: + return "LISTENING"; + case GPTP_PORT_PRE_MASTER: + return "PRE-MASTER"; + case GPTP_PORT_MASTER: + return "MASTER"; + case GPTP_PORT_PASSIVE: + return "PASSIVE"; + case GPTP_PORT_UNCALIBRATED: + return "UNCALIBRATED"; + case GPTP_PORT_SLAVE: + return "SLAVE"; + } + + return ""; +} + +static void gptp_print_port_info(const struct shell *sh, int port) +{ + struct gptp_port_bmca_data *port_bmca_data; + struct gptp_port_param_ds *port_param_ds; + struct gptp_port_states *port_state; + struct gptp_domain *domain; + struct gptp_port_ds *port_ds; + struct net_if *iface; + int ret, i; + + domain = gptp_get_domain(); + + ret = gptp_get_port_data(domain, + port, + &port_ds, + &port_param_ds, + &port_state, + &port_bmca_data, + &iface); + if (ret < 0) { + PR_WARNING("Cannot get gPTP information for port %d (%d)\n", + port, ret); + return; + } + + NET_ASSERT(port == port_ds->port_id.port_number, + "Port number mismatch! (%d vs %d)", port, + port_ds->port_id.port_number); + + PR("Port id : %d (%s)\n", port_ds->port_id.port_number, + selected_role_str(port_ds->port_id.port_number)); + PR("Interface : %p [%d]\n", iface, net_if_get_by_iface(iface)); + PR("Clock id : "); + for (i = 0; i < sizeof(port_ds->port_id.clk_id); i++) { + PR("%02x", port_ds->port_id.clk_id[i]); + + if (i != (sizeof(port_ds->port_id.clk_id) - 1)) { + PR(":"); + } + } + PR("\n"); + + PR("Version : %d\n", port_ds->version); + PR("AS capable : %s\n", port_ds->as_capable ? "yes" : "no"); + + PR("\nConfiguration:\n"); + PR("Time synchronization and Best Master Selection enabled " + ": %s\n", port_ds->ptt_port_enabled ? "yes" : "no"); + PR("The port is measuring the path delay " + ": %s\n", port_ds->is_measuring_delay ? "yes" : "no"); + PR("One way propagation time on %s : %u ns\n", + "the link attached to this port", + (uint32_t)port_ds->neighbor_prop_delay); + PR("Propagation time threshold for %s : %u ns\n", + "the link attached to this port", + (uint32_t)port_ds->neighbor_prop_delay_thresh); + PR("Estimate of the ratio of the frequency with the peer " + ": %u\n", (uint32_t)port_ds->neighbor_rate_ratio); + PR("Asymmetry on the link relative to the grand master time base " + ": %" PRId64 "\n", port_ds->delay_asymmetry); + PR("Maximum interval between sync %s " + ": %" PRIu64 "\n", "messages", + port_ds->sync_receipt_timeout_time_itv); + PR("Maximum number of Path Delay Requests without a response " + ": %d\n", port_ds->allowed_lost_responses); + PR("Current Sync %s : %d\n", + "sequence id for this port", port_ds->sync_seq_id); + PR("Current Path Delay Request %s : %d\n", + "sequence id for this port", port_ds->pdelay_req_seq_id); + PR("Current Announce %s : %d\n", + "sequence id for this port", port_ds->announce_seq_id); + PR("Current Signaling %s : %d\n", + "sequence id for this port", port_ds->signaling_seq_id); + PR("Whether neighborRateRatio %s : %s\n", + "needs to be computed for this port", + port_ds->compute_neighbor_rate_ratio ? "yes" : "no"); + PR("Whether neighborPropDelay %s : %s\n", + "needs to be computed for this port", + port_ds->compute_neighbor_prop_delay ? "yes" : "no"); + PR("Initial Announce Interval %s : %d\n", + "as a Logarithm to base 2", port_ds->ini_log_announce_itv); + PR("Current Announce Interval %s : %d\n", + "as a Logarithm to base 2", port_ds->cur_log_announce_itv); + PR("Initial Sync Interval %s : %d\n", + "as a Logarithm to base 2", port_ds->ini_log_half_sync_itv); + PR("Current Sync Interval %s : %d\n", + "as a Logarithm to base 2", port_ds->cur_log_half_sync_itv); + PR("Initial Path Delay Request Interval %s : %d\n", + "as a Logarithm to base 2", port_ds->ini_log_pdelay_req_itv); + PR("Current Path Delay Request Interval %s : %d\n", + "as a Logarithm to base 2", port_ds->cur_log_pdelay_req_itv); + PR("Time without receiving announce %s %s : %d ms (%d)\n", + "messages", "before running BMCA", + gptp_uscaled_ns_to_timer_ms( + &port_bmca_data->ann_rcpt_timeout_time_interval), + port_ds->announce_receipt_timeout); + PR("Time without receiving sync %s %s : %" PRIu64 " ms (%d)\n", + "messages", "before running BMCA", + (port_ds->sync_receipt_timeout_time_itv >> 16) / + (NSEC_PER_SEC / MSEC_PER_SEC), + port_ds->sync_receipt_timeout); + PR("Sync event %s : %" PRIu64 " ms\n", + "transmission interval for the port", + USCALED_NS_TO_NS(port_ds->half_sync_itv.low) / + (NSEC_PER_USEC * USEC_PER_MSEC)); + PR("Path Delay Request %s : %" PRIu64 " ms\n", + "transmission interval for the port", + USCALED_NS_TO_NS(port_ds->pdelay_req_itv.low) / + (NSEC_PER_USEC * USEC_PER_MSEC)); + PR("BMCA %s %s%d%s: %d\n", "default", "priority", 1, + " ", + domain->default_ds.priority1); + PR("BMCA %s %s%d%s: %d\n", "default", "priority", 2, + " ", + domain->default_ds.priority2); + + PR("\nRuntime status:\n"); + PR("Current global port state " + " : %s\n", selected_role_str(port)); + PR("Path Delay Request state machine variables:\n"); + PR("\tCurrent state " + ": %s\n", pdelay_req2str(port_state->pdelay_req.state)); + PR("\tInitial Path Delay Response Peer Timestamp " + ": %" PRIu64 "\n", port_state->pdelay_req.ini_resp_evt_tstamp); + PR("\tInitial Path Delay Response Ingress Timestamp " + ": %" PRIu64 "\n", port_state->pdelay_req.ini_resp_ingress_tstamp); + PR("\tPath Delay Response %s %s : %u\n", + "messages", "received", + port_state->pdelay_req.rcvd_pdelay_resp); + PR("\tPath Delay Follow Up %s %s : %u\n", + "messages", "received", + port_state->pdelay_req.rcvd_pdelay_follow_up); + PR("\tNumber of lost Path Delay Responses " + ": %u\n", port_state->pdelay_req.lost_responses); + PR("\tTimer expired send a new Path Delay Request " + ": %u\n", port_state->pdelay_req.pdelay_timer_expired); + PR("\tNeighborRateRatio has been computed successfully " + ": %u\n", port_state->pdelay_req.neighbor_rate_ratio_valid); + PR("\tPath Delay has already been computed after init " + ": %u\n", port_state->pdelay_req.init_pdelay_compute); + PR("\tCount consecutive reqs with multiple responses " + ": %u\n", port_state->pdelay_req.multiple_resp_count); + + PR("Path Delay Response state machine variables:\n"); + PR("\tCurrent state " + ": %s\n", pdelay_resp2str(port_state->pdelay_resp.state)); + + PR("SyncReceive state machine variables:\n"); + PR("\tCurrent state " + ": %s\n", sync_rcv2str(port_state->sync_rcv.state)); + PR("\tA Sync %s %s : %s\n", + "Message", "has been received", + port_state->sync_rcv.rcvd_sync ? "yes" : "no"); + PR("\tA Follow Up %s %s : %s\n", + "Message", "has been received", + port_state->sync_rcv.rcvd_follow_up ? "yes" : "no"); + PR("\tA Follow Up %s %s : %s\n", + "Message", "timeout", + port_state->sync_rcv.follow_up_timeout_expired ? "yes" : "no"); + PR("\tTime at which a Sync %s without Follow Up\n" + "\t will be discarded " + ": %" PRIu64 "\n", "Message", + port_state->sync_rcv.follow_up_receipt_timeout); + + PR("SyncSend state machine variables:\n"); + PR("\tCurrent state " + ": %s\n", sync_send2str(port_state->sync_send.state)); + PR("\tA MDSyncSend structure %s : %s\n", + "has been received", + port_state->sync_send.rcvd_md_sync ? "yes" : "no"); + PR("\tThe timestamp for the sync msg %s : %s\n", + "has been received", + port_state->sync_send.md_sync_timestamp_avail ? "yes" : "no"); + + PR("PortSyncSyncReceive state machine variables:\n"); + PR("\tCurrent state " + ": %s\n", pss_rcv2str(port_state->pss_rcv.state)); + PR("\tGrand Master / Local Clock frequency ratio " + ": %f\n", port_state->pss_rcv.rate_ratio); + PR("\tA MDSyncReceive struct is ready to be processed " + ": %s\n", port_state->pss_rcv.rcvd_md_sync ? "yes" : "no"); + PR("\tExpiry of SyncReceiptTimeoutTimer : %s\n", + port_state->pss_rcv.rcv_sync_receipt_timeout_timer_expired ? + "yes" : "no"); + + PR("PortSyncSyncSend state machine variables:\n"); + PR("\tCurrent state " + ": %s\n", pss_send2str(port_state->pss_send.state)); + PR("\tFollow Up Correction Field of last recv PSS " + ": %" PRId64 "\n", + port_state->pss_send.last_follow_up_correction_field); + PR("\tUpstream Tx Time of the last recv PortSyncSync " + ": %" PRIu64 "\n", port_state->pss_send.last_upstream_tx_time); + PR("\tRate Ratio of the last received PortSyncSync " + ": %f\n", + port_state->pss_send.last_rate_ratio); + PR("\tGM Freq Change of the last received PortSyncSync " + ": %f\n", port_state->pss_send.last_gm_freq_change); + PR("\tGM Time Base Indicator of last recv PortSyncSync " + ": %d\n", port_state->pss_send.last_gm_time_base_indicator); + PR("\tReceived Port Number of last recv PortSyncSync " + ": %d\n", + port_state->pss_send.last_rcvd_port_num); + PR("\tPortSyncSync structure is ready to be processed " + ": %s\n", port_state->pss_send.rcvd_pss_sync ? "yes" : "no"); + PR("\tFlag when the %s has expired : %s\n", + "half_sync_itv_timer", + port_state->pss_send.half_sync_itv_timer_expired ? "yes" : "no"); + PR("\tHas %s expired twice : %s\n", + "half_sync_itv_timer", + port_state->pss_send.sync_itv_timer_expired ? "yes" : "no"); + PR("\tHas syncReceiptTimeoutTime expired " + ": %s\n", + port_state->pss_send.send_sync_receipt_timeout_timer_expired ? + "yes" : "no"); + + PR("PortAnnounceReceive state machine variables:\n"); + PR("\tCurrent state " + ": %s\n", pa_rcv2str(port_state->pa_rcv.state)); + PR("\tAn announce message is ready to be processed " + ": %s\n", + port_state->pa_rcv.rcvd_announce ? "yes" : "no"); + + PR("PortAnnounceInformation state machine variables:\n"); + PR("\tCurrent state " + ": %s\n", pa_info2str(port_state->pa_info.state)); + PR("\tExpired announce information " + ": %s\n", port_state->pa_info.ann_expired ? "yes" : "no"); + + PR("PortAnnounceTransmit state machine variables:\n"); + PR("\tCurrent state " + ": %s\n", pa_transmit2str(port_state->pa_transmit.state)); + PR("\tTrigger announce information " + ": %s\n", port_state->pa_transmit.ann_trigger ? "yes" : "no"); + +#if defined(CONFIG_NET_GPTP_STATISTICS) + PR("\nStatistics:\n"); + PR("Sync %s %s : %u\n", + "messages", "received", port_param_ds->rx_sync_count); + PR("Follow Up %s %s : %u\n", + "messages", "received", port_param_ds->rx_fup_count); + PR("Path Delay Request %s %s : %u\n", + "messages", "received", port_param_ds->rx_pdelay_req_count); + PR("Path Delay Response %s %s : %u\n", + "messages", "received", port_param_ds->rx_pdelay_resp_count); + PR("Path Delay %s threshold %s : %u\n", + "messages", "exceeded", + port_param_ds->neighbor_prop_delay_exceeded); + PR("Path Delay Follow Up %s %s : %u\n", + "messages", "received", port_param_ds->rx_pdelay_resp_fup_count); + PR("Announce %s %s : %u\n", + "messages", "received", port_param_ds->rx_announce_count); + PR("ptp %s discarded : %u\n", + "messages", port_param_ds->rx_ptp_packet_discard_count); + PR("Sync %s %s : %u\n", + "reception", "timeout", + port_param_ds->sync_receipt_timeout_count); + PR("Announce %s %s : %u\n", + "reception", "timeout", + port_param_ds->announce_receipt_timeout_count); + PR("Path Delay Requests without a response " + ": %u\n", + port_param_ds->pdelay_allowed_lost_resp_exceed_count); + PR("Sync %s %s : %u\n", + "messages", "sent", port_param_ds->tx_sync_count); + PR("Follow Up %s %s : %u\n", + "messages", "sent", port_param_ds->tx_fup_count); + PR("Path Delay Request %s %s : %u\n", + "messages", "sent", port_param_ds->tx_pdelay_req_count); + PR("Path Delay Response %s %s : %u\n", + "messages", "sent", port_param_ds->tx_pdelay_resp_count); + PR("Path Delay Response FUP %s %s : %u\n", + "messages", "sent", port_param_ds->tx_pdelay_resp_fup_count); + PR("Announce %s %s : %u\n", + "messages", "sent", port_param_ds->tx_announce_count); +#endif /* CONFIG_NET_GPTP_STATISTICS */ +} +#endif /* CONFIG_NET_GPTP */ + +static int cmd_net_gptp_port(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_GPTP) + int arg = 1; + char *endptr; + int port; +#endif + +#if defined(CONFIG_NET_GPTP) + if (!argv[arg]) { + PR_WARNING("Port number must be given.\n"); + return -ENOEXEC; + } + + port = strtol(argv[arg], &endptr, 10); + + if (*endptr == '\0') { + gptp_print_port_info(sh, port); + } else { + PR_WARNING("Not a valid gPTP port number: %s\n", argv[arg]); + } +#else + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_GPTP", "gPTP"); +#endif + + return 0; +} + +static int cmd_net_gptp(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_GPTP) + /* gPTP status */ + struct gptp_domain *domain = gptp_get_domain(); + int count = 0; + int arg = 1; +#endif + +#if defined(CONFIG_NET_GPTP) + if (argv[arg]) { + cmd_net_gptp_port(sh, argc, argv); + } else { + struct net_shell_user_data user_data; + + user_data.sh = sh; + user_data.user_data = &count; + + gptp_foreach_port(gptp_port_cb, &user_data); + + PR("\n"); + + PR("SiteSyncSync state machine variables:\n"); + PR("\tCurrent state : %s\n", + site_sync2str(domain->state.site_ss.state)); + PR("\tA PortSyncSync struct is ready : %s\n", + domain->state.site_ss.rcvd_pss ? "yes" : "no"); + + PR("ClockSlaveSync state machine variables:\n"); + PR("\tCurrent state : %s\n", + clk_slave2str(domain->state.clk_slave_sync.state)); + PR("\tA PortSyncSync struct is ready : %s\n", + domain->state.clk_slave_sync.rcvd_pss ? "yes" : "no"); + PR("\tThe local clock has expired : %s\n", + domain->state.clk_slave_sync.rcvd_local_clk_tick ? + "yes" : "no"); + + PR("PortRoleSelection state machine variables:\n"); + PR("\tCurrent state : %s\n", + pr_selection2str(domain->state.pr_sel.state)); + + PR("ClockMasterSyncReceive state machine variables:\n"); + PR("\tCurrent state : %s\n", + cms_rcv2str(domain->state.clk_master_sync_receive.state)); + PR("\tA ClockSourceTime : %s\n", + domain->state.clk_master_sync_receive.rcvd_clock_source_req + ? "yes" : "no"); + PR("\tThe local clock has expired : %s\n", + domain->state.clk_master_sync_receive.rcvd_local_clock_tick + ? "yes" : "no"); + } +#else + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_GPTP", "gPTP"); +#endif + + return 0; +} + +SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_gptp, + SHELL_CMD(port, NULL, + "'net gptp []' prints detailed information about " + "gPTP port.", + cmd_net_gptp_port), + SHELL_SUBCMD_SET_END +); + +SHELL_SUBCMD_ADD((net), gptp, &net_cmd_gptp, + "Print information about gPTP support.", + cmd_net_gptp, 1, 1); diff --git a/subsys/net/lib/shell/iface.c b/subsys/net/lib/shell/iface.c new file mode 100644 index 00000000000..53d4e99bd21 --- /dev/null +++ b/subsys/net/lib/shell/iface.c @@ -0,0 +1,686 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#if defined(CONFIG_NET_L2_ETHERNET) +#include +#endif +#if defined(CONFIG_NET_L2_ETHERNET_MGMT) +#include +#endif +#if defined(CONFIG_NET_L2_VIRTUAL) +#include +#endif + +#include "net_shell_private.h" + +#if defined(CONFIG_NET_L2_ETHERNET) && defined(CONFIG_NET_NATIVE) +struct ethernet_capabilities { + enum ethernet_hw_caps capability; + const char * const description; +}; + +#define EC(cap, desc) { .capability = cap, .description = desc } + +static struct ethernet_capabilities eth_hw_caps[] = { + EC(ETHERNET_HW_TX_CHKSUM_OFFLOAD, "TX checksum offload"), + EC(ETHERNET_HW_RX_CHKSUM_OFFLOAD, "RX checksum offload"), + EC(ETHERNET_HW_VLAN, "Virtual LAN"), + EC(ETHERNET_HW_VLAN_TAG_STRIP, "VLAN Tag stripping"), + EC(ETHERNET_AUTO_NEGOTIATION_SET, "Auto negotiation"), + EC(ETHERNET_LINK_10BASE_T, "10 Mbits"), + EC(ETHERNET_LINK_100BASE_T, "100 Mbits"), + EC(ETHERNET_LINK_1000BASE_T, "1 Gbits"), + EC(ETHERNET_DUPLEX_SET, "Half/full duplex"), + EC(ETHERNET_PTP, "IEEE 802.1AS gPTP clock"), + EC(ETHERNET_QAV, "IEEE 802.1Qav (credit shaping)"), + EC(ETHERNET_QBV, "IEEE 802.1Qbv (scheduled traffic)"), + EC(ETHERNET_QBU, "IEEE 802.1Qbu (frame preemption)"), + EC(ETHERNET_TXTIME, "TXTIME"), + EC(ETHERNET_PROMISC_MODE, "Promiscuous mode"), + EC(ETHERNET_PRIORITY_QUEUES, "Priority queues"), + EC(ETHERNET_HW_FILTERING, "MAC address filtering"), + EC(ETHERNET_DSA_SLAVE_PORT, "DSA slave port"), + EC(ETHERNET_DSA_MASTER_PORT, "DSA master port"), +}; + +static void print_supported_ethernet_capabilities( + const struct shell *sh, struct net_if *iface) +{ + enum ethernet_hw_caps caps = net_eth_get_hw_capabilities(iface); + int i; + + for (i = 0; i < ARRAY_SIZE(eth_hw_caps); i++) { + if (caps & eth_hw_caps[i].capability) { + PR("\t%s\n", eth_hw_caps[i].description); + } + } +} +#endif /* CONFIG_NET_L2_ETHERNET */ + +#if defined(CONFIG_NET_NATIVE) +static const char *iface_flags2str(struct net_if *iface) +{ + static char str[sizeof("POINTOPOINT") + sizeof("PROMISC") + + sizeof("NO_AUTO_START") + sizeof("SUSPENDED") + + sizeof("MCAST_FORWARD") + sizeof("IPv4") + + sizeof("IPv6") + sizeof("NO_ND") + sizeof("NO_MLD")]; + int pos = 0; + + if (net_if_flag_is_set(iface, NET_IF_POINTOPOINT)) { + pos += snprintk(str + pos, sizeof(str) - pos, + "POINTOPOINT,"); + } + + if (net_if_flag_is_set(iface, NET_IF_PROMISC)) { + pos += snprintk(str + pos, sizeof(str) - pos, + "PROMISC,"); + } + + if (net_if_flag_is_set(iface, NET_IF_NO_AUTO_START)) { + pos += snprintk(str + pos, sizeof(str) - pos, + "NO_AUTO_START,"); + } else { + pos += snprintk(str + pos, sizeof(str) - pos, + "AUTO_START,"); + } + + if (net_if_flag_is_set(iface, NET_IF_FORWARD_MULTICASTS)) { + pos += snprintk(str + pos, sizeof(str) - pos, + "MCAST_FORWARD,"); + } + + if (net_if_flag_is_set(iface, NET_IF_IPV4)) { + pos += snprintk(str + pos, sizeof(str) - pos, + "IPv4,"); + } + + if (net_if_flag_is_set(iface, NET_IF_IPV6)) { + pos += snprintk(str + pos, sizeof(str) - pos, + "IPv6,"); + } + + if (net_if_flag_is_set(iface, NET_IF_IPV6_NO_ND)) { + pos += snprintk(str + pos, sizeof(str) - pos, + "NO_ND,"); + } + + if (net_if_flag_is_set(iface, NET_IF_IPV6_NO_MLD)) { + pos += snprintk(str + pos, sizeof(str) - pos, + "NO_MLD,"); + } + + /* get rid of last ',' character */ + str[pos - 1] = '\0'; + + return str; +} +#endif + +static void iface_cb(struct net_if *iface, void *user_data) +{ +#if defined(CONFIG_NET_NATIVE) + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + +#if defined(CONFIG_NET_IPV6) + struct net_if_ipv6_prefix *prefix; + struct net_if_router *router; + struct net_if_ipv6 *ipv6; +#endif +#if defined(CONFIG_NET_IPV4) + struct net_if_ipv4 *ipv4; +#endif +#if defined(CONFIG_NET_VLAN) + struct ethernet_context *eth_ctx; +#endif +#if defined(CONFIG_NET_IP) + struct net_if_addr *unicast; + struct net_if_mcast_addr *mcast; +#endif +#if defined(CONFIG_NET_L2_ETHERNET_MGMT) + struct ethernet_req_params params; + int ret; +#endif + const char *extra; +#if defined(CONFIG_NET_IP) + int i, count; +#endif + + if (data->user_data && data->user_data != iface) { + return; + } + +#if defined(CONFIG_NET_INTERFACE_NAME) + char ifname[CONFIG_NET_INTERFACE_NAME_LEN + 1] = { 0 }; + int ret_name; + + ret_name = net_if_get_name(iface, ifname, sizeof(ifname) - 1); + if (ret_name < 1 || ifname[0] == '\0') { + snprintk(ifname, sizeof(ifname), "?"); + } + + PR("\nInterface %s (%p) (%s) [%d]\n", ifname, iface, iface2str(iface, &extra), + net_if_get_by_iface(iface)); +#else + PR("\nInterface %p (%s) [%d]\n", iface, iface2str(iface, &extra), + net_if_get_by_iface(iface)); +#endif + PR("===========================%s\n", extra); + + if (!net_if_is_up(iface)) { + PR_INFO("Interface is down.\n"); + + /* Show detailed information only when user asks information + * about one specific network interface. + */ + if (data->user_data == NULL) { + return; + } + } + +#ifdef CONFIG_NET_POWER_MANAGEMENT + if (net_if_is_suspended(iface)) { + PR_INFO("Interface is suspended, thus not able to tx/rx.\n"); + } +#endif + +#if defined(CONFIG_NET_L2_VIRTUAL) + if (!sys_slist_is_empty(&iface->config.virtual_interfaces)) { + struct virtual_interface_context *ctx, *tmp; + + PR("Virtual interfaces attached to this : "); + SYS_SLIST_FOR_EACH_CONTAINER_SAFE( + &iface->config.virtual_interfaces, + ctx, tmp, node) { + if (ctx->virtual_iface == iface) { + continue; + } + + PR("%d ", net_if_get_by_iface(ctx->virtual_iface)); + } + + PR("\n"); + } + + if (net_if_l2(iface) == &NET_L2_GET_NAME(VIRTUAL)) { + struct net_if *orig_iface; + char *name, buf[CONFIG_NET_L2_VIRTUAL_MAX_NAME_LEN]; + + name = net_virtual_get_name(iface, buf, sizeof(buf)); + if (!(name && name[0])) { + name = ""; + } + + PR("Name : %s\n", name); + + orig_iface = net_virtual_get_iface(iface); + if (orig_iface == NULL) { + PR("No attached network interface.\n"); + } else { + PR("Attached : %d (%s / %p)\n", + net_if_get_by_iface(orig_iface), + iface2str(orig_iface, NULL), + orig_iface); + } + } +#endif /* CONFIG_NET_L2_VIRTUAL */ + + net_if_lock(iface); + if (net_if_get_link_addr(iface) && + net_if_get_link_addr(iface)->addr) { + PR("Link addr : %s\n", + net_sprint_ll_addr(net_if_get_link_addr(iface)->addr, + net_if_get_link_addr(iface)->len)); + } + net_if_unlock(iface); + + PR("MTU : %d\n", net_if_get_mtu(iface)); + PR("Flags : %s\n", iface_flags2str(iface)); + PR("Device : %s (%p)\n", + net_if_get_device(iface) ? net_if_get_device(iface)->name : "", + net_if_get_device(iface)); + +#if defined(CONFIG_NET_L2_ETHERNET_MGMT) + if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) { + count = 0; + ret = net_mgmt(NET_REQUEST_ETHERNET_GET_PRIORITY_QUEUES_NUM, + iface, ¶ms, + sizeof(struct ethernet_req_params)); + + if (!ret && params.priority_queues_num) { + count = params.priority_queues_num; + PR("Priority queues:\n"); + for (i = 0; i < count; ++i) { + params.qav_param.queue_id = i; + params.qav_param.type = + ETHERNET_QAV_PARAM_TYPE_STATUS; + ret = net_mgmt( + NET_REQUEST_ETHERNET_GET_QAV_PARAM, + iface, ¶ms, + sizeof(struct ethernet_req_params)); + + PR("\t%d: Qav ", i); + if (ret) { + PR("not supported\n"); + } else { + PR("%s\n", + params.qav_param.enabled ? + "enabled" : + "disabled"); + } + } + } + } +#endif + +#if defined(CONFIG_NET_PROMISCUOUS_MODE) + PR("Promiscuous mode : %s\n", + net_if_is_promisc(iface) ? "enabled" : "disabled"); +#endif + +#if defined(CONFIG_NET_VLAN) + if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) { + eth_ctx = net_if_l2_data(iface); + + if (eth_ctx->vlan_enabled) { + for (i = 0; i < CONFIG_NET_VLAN_COUNT; i++) { + if (eth_ctx->vlan[i].iface != iface || + eth_ctx->vlan[i].tag == + NET_VLAN_TAG_UNSPEC) { + continue; + } + + PR("VLAN tag : %d (0x%x)\n", + eth_ctx->vlan[i].tag, + eth_ctx->vlan[i].tag); + } + } else { + PR("VLAN not enabled\n"); + } + } +#endif + +#ifdef CONFIG_NET_L2_ETHERNET + if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) { + PR("Ethernet capabilities supported:\n"); + print_supported_ethernet_capabilities(sh, iface); + } +#endif /* CONFIG_NET_L2_ETHERNET */ + +#if defined(CONFIG_NET_IPV6) + count = 0; + + if (!net_if_flag_is_set(iface, NET_IF_IPV6)) { + PR("%s not %s for this interface.\n", "IPv6", "enabled"); + ipv6 = NULL; + goto skip_ipv6; + } + + ipv6 = iface->config.ip.ipv6; + + PR("IPv6 unicast addresses (max %d):\n", NET_IF_MAX_IPV6_ADDR); + for (i = 0; ipv6 && i < NET_IF_MAX_IPV6_ADDR; i++) { + unicast = &ipv6->unicast[i]; + + if (!unicast->is_used) { + continue; + } + + PR("\t%s %s %s%s%s\n", + net_sprint_ipv6_addr(&unicast->address.in6_addr), + addrtype2str(unicast->addr_type), + addrstate2str(unicast->addr_state), + unicast->is_infinite ? " infinite" : "", + unicast->is_mesh_local ? " meshlocal" : ""); + count++; + } + + if (count == 0) { + PR("\t\n"); + } + + count = 0; + + PR("IPv6 multicast addresses (max %d):\n", NET_IF_MAX_IPV6_MADDR); + for (i = 0; ipv6 && i < NET_IF_MAX_IPV6_MADDR; i++) { + mcast = &ipv6->mcast[i]; + + if (!mcast->is_used) { + continue; + } + + PR("\t%s\n", net_sprint_ipv6_addr(&mcast->address.in6_addr)); + + count++; + } + + if (count == 0) { + PR("\t\n"); + } + + count = 0; + + PR("IPv6 prefixes (max %d):\n", NET_IF_MAX_IPV6_PREFIX); + for (i = 0; ipv6 && i < NET_IF_MAX_IPV6_PREFIX; i++) { + prefix = &ipv6->prefix[i]; + + if (!prefix->is_used) { + continue; + } + + PR("\t%s/%d%s\n", + net_sprint_ipv6_addr(&prefix->prefix), + prefix->len, prefix->is_infinite ? " infinite" : ""); + + count++; + } + + if (count == 0) { + PR("\t\n"); + } + + router = net_if_ipv6_router_find_default(iface, NULL); + if (router) { + PR("IPv6 default router :\n"); + PR("\t%s%s\n", + net_sprint_ipv6_addr(&router->address.in6_addr), + router->is_infinite ? " infinite" : ""); + } + +skip_ipv6: + + if (ipv6) { + PR("IPv6 hop limit : %d\n", + ipv6->hop_limit); + PR("IPv6 base reachable time : %d\n", + ipv6->base_reachable_time); + PR("IPv6 reachable time : %d\n", + ipv6->reachable_time); + PR("IPv6 retransmit timer : %d\n", + ipv6->retrans_timer); + } +#endif /* CONFIG_NET_IPV6 */ + +#if defined(CONFIG_NET_IPV4) + /* No need to print IPv4 information for interface that does not + * support that protocol. + */ + if ( +#if defined(CONFIG_NET_L2_IEEE802154) + (net_if_l2(iface) == &NET_L2_GET_NAME(IEEE802154)) || +#endif +#if defined(CONFIG_NET_L2_BT) + (net_if_l2(iface) == &NET_L2_GET_NAME(BLUETOOTH)) || +#endif + 0) { + PR_WARNING("%s not %s for this interface.\n", "IPv4", + "supported"); + return; + } + + count = 0; + + if (!net_if_flag_is_set(iface, NET_IF_IPV4)) { + PR("%s not %s for this interface.\n", "IPv4", "enabled"); + ipv4 = NULL; + goto skip_ipv4; + } + + ipv4 = iface->config.ip.ipv4; + + PR("IPv4 unicast addresses (max %d):\n", NET_IF_MAX_IPV4_ADDR); + for (i = 0; ipv4 && i < NET_IF_MAX_IPV4_ADDR; i++) { + unicast = &ipv4->unicast[i]; + + if (!unicast->is_used) { + continue; + } + + PR("\t%s %s %s%s\n", + net_sprint_ipv4_addr(&unicast->address.in_addr), + addrtype2str(unicast->addr_type), + addrstate2str(unicast->addr_state), + unicast->is_infinite ? " infinite" : ""); + + count++; + } + + if (count == 0) { + PR("\t\n"); + } + + count = 0; + + PR("IPv4 multicast addresses (max %d):\n", NET_IF_MAX_IPV4_MADDR); + for (i = 0; ipv4 && i < NET_IF_MAX_IPV4_MADDR; i++) { + mcast = &ipv4->mcast[i]; + + if (!mcast->is_used) { + continue; + } + + PR("\t%s\n", net_sprint_ipv4_addr(&mcast->address.in_addr)); + + count++; + } + + if (count == 0) { + PR("\t\n"); + } + +skip_ipv4: + + if (ipv4) { + PR("IPv4 gateway : %s\n", + net_sprint_ipv4_addr(&ipv4->gw)); + PR("IPv4 netmask : %s\n", + net_sprint_ipv4_addr(&ipv4->netmask)); + } +#endif /* CONFIG_NET_IPV4 */ + +#if defined(CONFIG_NET_DHCPV4) + PR("DHCPv4 lease time : %u\n", + iface->config.dhcpv4.lease_time); + PR("DHCPv4 renew time : %u\n", + iface->config.dhcpv4.renewal_time); + PR("DHCPv4 server : %s\n", + net_sprint_ipv4_addr(&iface->config.dhcpv4.server_id)); + PR("DHCPv4 requested : %s\n", + net_sprint_ipv4_addr(&iface->config.dhcpv4.requested_ip)); + PR("DHCPv4 state : %s\n", + net_dhcpv4_state_name(iface->config.dhcpv4.state)); + PR("DHCPv4 attempts : %d\n", + iface->config.dhcpv4.attempts); +#endif /* CONFIG_NET_DHCPV4 */ + +#else + ARG_UNUSED(iface); + ARG_UNUSED(user_data); + +#endif /* CONFIG_NET_NATIVE */ +} + +static int cmd_net_set_mac(const struct shell *sh, size_t argc, char *argv[]) +{ +#if !defined(CONFIG_NET_L2_ETHERNET) || !defined(CONFIG_NET_L2_ETHERNET_MGMT) + PR_WARNING("Unsupported command, please enable CONFIG_NET_L2_ETHERNET " + "and CONFIG_NET_L2_ETHERNET_MGMT\n"); + return -ENOEXEC; +#else + struct net_if *iface; + struct ethernet_req_params params; + char *mac_addr = params.mac_address.addr; + int idx; + int ret; + + if (argc < 3) { + PR_WARNING("Missing interface index and/or MAC address\n"); + goto err; + } + + idx = get_iface_idx(sh, argv[1]); + if (idx < 0) { + goto err; + } + + iface = net_if_get_by_index(idx); + if (!iface) { + PR_WARNING("No such interface in index %d\n", idx); + goto err; + } + + if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) { + PR_WARNING("MAC address can be set only for Ethernet\n"); + goto err; + } + + if ((net_bytes_from_str(mac_addr, sizeof(params.mac_address), argv[2]) < 0) || + !net_eth_is_addr_valid(¶ms.mac_address)) { + PR_WARNING("Invalid MAC address: %s\n", argv[2]); + goto err; + } + + ret = net_mgmt(NET_REQUEST_ETHERNET_SET_MAC_ADDRESS, iface, ¶ms, sizeof(params)); + if (ret < 0) { + if (ret == -EACCES) { + PR_WARNING("MAC address cannot be set when interface is operational\n"); + goto err; + } + PR_WARNING("Failed to set MAC address (%d)\n", ret); + goto err; + } + + PR_INFO("MAC address set to %s\n", + net_sprint_ll_addr(net_if_get_link_addr(iface)->addr, + net_if_get_link_addr(iface)->len)); + + return 0; +err: + return -ENOEXEC; +#endif /* CONFIG_NET_L2_ETHERNET */ +} + +static int cmd_net_iface_up(const struct shell *sh, size_t argc, char *argv[]) +{ + struct net_if *iface; + int idx, ret; + + idx = get_iface_idx(sh, argv[1]); + if (idx < 0) { + return -ENOEXEC; + } + + iface = net_if_get_by_index(idx); + if (!iface) { + PR_WARNING("No such interface in index %d\n", idx); + return -ENOEXEC; + } + + if (net_if_is_up(iface)) { + PR_WARNING("Interface %d is already up.\n", idx); + return -ENOEXEC; + } + + ret = net_if_up(iface); + if (ret) { + PR_WARNING("Cannot take interface %d up (%d)\n", idx, ret); + return -ENOEXEC; + } + + PR("Interface %d is up\n", idx); + + return 0; +} + +static int cmd_net_iface_down(const struct shell *sh, size_t argc, char *argv[]) +{ + struct net_if *iface; + int idx, ret; + + idx = get_iface_idx(sh, argv[1]); + if (idx < 0) { + return -ENOEXEC; + } + + iface = net_if_get_by_index(idx); + if (!iface) { + PR_WARNING("No such interface in index %d\n", idx); + return -ENOEXEC; + } + + ret = net_if_down(iface); + if (ret) { + PR_WARNING("Cannot take interface %d down (%d)\n", idx, ret); + return -ENOEXEC; + } + + PR("Interface %d is down\n", idx); + + return 0; +} + +static int cmd_net_iface(const struct shell *sh, size_t argc, char *argv[]) +{ + struct net_if *iface = NULL; + struct net_shell_user_data user_data; + int idx; + + if (argv[1]) { + idx = get_iface_idx(sh, argv[1]); + if (idx < 0) { + return -ENOEXEC; + } + + iface = net_if_get_by_index(idx); + if (!iface) { + PR_WARNING("No such interface in index %d\n", idx); + return -ENOEXEC; + } + } + +#if defined(CONFIG_NET_HOSTNAME_ENABLE) + PR("Hostname: %s\n\n", net_hostname_get()); +#endif + + user_data.sh = sh; + user_data.user_data = iface; + + net_if_foreach(iface_cb, &user_data); + + return 0; +} + +#if defined(CONFIG_NET_SHELL_DYN_CMD_COMPLETION) + +#include "iface_dynamic.h" + +#endif /* CONFIG_NET_SHELL_DYN_CMD_COMPLETION */ + +SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_iface, + SHELL_CMD(up, IFACE_DYN_CMD, + "'net iface up ' takes network interface up.", + cmd_net_iface_up), + SHELL_CMD(down, IFACE_DYN_CMD, + "'net iface down ' takes network interface " + "down.", + cmd_net_iface_down), + SHELL_CMD(show, IFACE_DYN_CMD, + "'net iface ' shows network interface " + "information.", + cmd_net_iface), + SHELL_CMD(set_mac, IFACE_DYN_CMD, + "'net iface set_mac ' sets MAC address for the network interface.", + cmd_net_set_mac), + SHELL_SUBCMD_SET_END +); + +SHELL_SUBCMD_ADD((net), iface, &net_cmd_iface, + "Print information about network interfaces.", + cmd_net_iface, 1, 1); diff --git a/subsys/net/lib/shell/iface_dynamic.h b/subsys/net/lib/shell/iface_dynamic.h new file mode 100644 index 00000000000..d10e25e1c1b --- /dev/null +++ b/subsys/net/lib/shell/iface_dynamic.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Dynamic shell command completion for network interface. + * This is be used by multiple commands. + */ + +#define MAX_IFACE_HELP_STR_LEN sizeof("longbearername (0xabcd0123)") +#define MAX_IFACE_STR_LEN sizeof("xxx") + +static char iface_help_buffer[MAX_IFACE_COUNT][MAX_IFACE_HELP_STR_LEN]; +static char iface_index_buffer[MAX_IFACE_COUNT][MAX_IFACE_STR_LEN]; + +static void iface_index_get(size_t idx, struct shell_static_entry *entry); + +SHELL_DYNAMIC_CMD_CREATE(iface_index, iface_index_get); + +static char *set_iface_index_buffer(size_t idx) +{ + struct net_if *iface = net_if_get_by_index(idx); + + /* Network interfaces start at 1 */ + if (idx == 0) { + return ""; + } + + if (!iface) { + return NULL; + } + + snprintk(iface_index_buffer[idx - 1], MAX_IFACE_STR_LEN, "%d", (uint8_t)idx); + + return iface_index_buffer[idx - 1]; +} + +static char *set_iface_index_help(size_t idx) +{ + struct net_if *iface = net_if_get_by_index(idx); + + /* Network interfaces start at 1 */ + if (idx == 0) { + return ""; + } + + if (!iface) { + return NULL; + } + +#if defined(CONFIG_NET_INTERFACE_NAME) + char name[CONFIG_NET_INTERFACE_NAME_LEN + 1]; + + net_if_get_name(iface, name, CONFIG_NET_INTERFACE_NAME_LEN); + name[CONFIG_NET_INTERFACE_NAME_LEN] = '\0'; + + snprintk(iface_help_buffer[idx - 1], MAX_IFACE_HELP_STR_LEN, + "%s [%s] (%p)", name, iface2str(iface, NULL), iface); +#else + snprintk(iface_help_buffer[idx - 1], MAX_IFACE_HELP_STR_LEN, + "[%s] (%p)", iface2str(iface, NULL), iface); +#endif + + return iface_help_buffer[idx - 1]; +} + +static void iface_index_get(size_t idx, struct shell_static_entry *entry) +{ + entry->handler = NULL; + entry->help = set_iface_index_help(idx); + entry->subcmd = &iface_index; + entry->syntax = set_iface_index_buffer(idx); +} diff --git a/subsys/net/lib/shell/ipv4.c b/subsys/net/lib/shell/ipv4.c new file mode 100644 index 00000000000..e8584b205fb --- /dev/null +++ b/subsys/net/lib/shell/ipv4.c @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#include + +#include "net_shell_private.h" +#include "../ip/ipv4.h" + +#if defined(CONFIG_NET_NATIVE_IPV4) +static void ip_address_lifetime_cb(struct net_if *iface, void *user_data) +{ + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + struct net_if_ipv4 *ipv4 = iface->config.ip.ipv4; + const char *extra; + int i; + + ARG_UNUSED(user_data); + + PR("\nIPv4 addresses for interface %d (%p) (%s)\n", + net_if_get_by_iface(iface), iface, iface2str(iface, &extra)); + PR("============================================%s\n", extra); + + if (!ipv4) { + PR("No IPv4 config found for this interface.\n"); + return; + } + + PR("Type \tState \tLifetime (sec)\tAddress\n"); + + for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) { + if (!ipv4->unicast[i].is_used || + ipv4->unicast[i].address.family != AF_INET) { + continue; + } + + PR("%s \t%s \t%12s/%12s\n", + addrtype2str(ipv4->unicast[i].addr_type), + addrstate2str(ipv4->unicast[i].addr_state), + net_sprint_ipv4_addr( + &ipv4->unicast[i].address.in_addr), + net_sprint_ipv4_addr( + &ipv4->netmask)); + } +} +#endif /* CONFIG_NET_NATIVE_IPV4 */ + +static int cmd_net_ipv4(const struct shell *sh, size_t argc, char *argv[]) +{ + PR("IPv4 support : %s\n", + IS_ENABLED(CONFIG_NET_IPV4) ? + "enabled" : "disabled"); + if (!IS_ENABLED(CONFIG_NET_IPV4)) { + return -ENOEXEC; + } + +#if defined(CONFIG_NET_NATIVE_IPV4) + struct net_shell_user_data user_data; + + PR("IPv4 fragmentation support : %s\n", + IS_ENABLED(CONFIG_NET_IPV4_FRAGMENT) ? "enabled" : + "disabled"); + PR("Max number of IPv4 network interfaces " + "in the system : %d\n", + CONFIG_NET_IF_MAX_IPV4_COUNT); + PR("Max number of unicast IPv4 addresses " + "per network interface : %d\n", + CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT); + PR("Max number of multicast IPv4 addresses " + "per network interface : %d\n", + CONFIG_NET_IF_MCAST_IPV4_ADDR_COUNT); + + user_data.sh = sh; + user_data.user_data = NULL; + + /* Print information about address lifetime */ + net_if_foreach(ip_address_lifetime_cb, &user_data); +#endif + + return 0; +} + +static int cmd_net_ip_add(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_NATIVE_IPV4) + struct net_if *iface = NULL; + int idx; + struct in_addr addr; + + if (argc < 3) { + PR_ERROR("Correct usage: net ipv4 add
    []\n"); + return -EINVAL; + } + + idx = get_iface_idx(sh, argv[1]); + if (idx < 0) { + return -ENOEXEC; + } + + iface = net_if_get_by_index(idx); + if (!iface) { + PR_WARNING("No such interface in index %d\n", idx); + return -ENOEXEC; + } + + if (net_addr_pton(AF_INET, argv[2], &addr)) { + PR_ERROR("Invalid address: %s\n", argv[2]); + return -EINVAL; + } + + if (net_ipv4_is_addr_mcast(&addr)) { + int ret; + + ret = net_ipv4_igmp_join(iface, &addr); + if (ret < 0) { + PR_ERROR("Cannot %s multicast group %s for interface %d (%d)\n", + "join", net_sprint_ipv4_addr(&addr), idx, ret); + return ret; + } + } else { + struct net_if_addr *ifaddr; + + if (argc < 4) { + PR_ERROR("Netmask is missing.\n"); + return -EINVAL; + } + + ifaddr = net_if_ipv4_addr_add(iface, &addr, NET_ADDR_MANUAL, 0); + if (ifaddr == NULL) { + PR_ERROR("Cannot add address %s to interface %d\n", + net_sprint_ipv4_addr(&addr), idx); + return -ENOMEM; + } + + if (net_addr_pton(AF_INET, argv[3], &addr)) { + PR_ERROR("Invalid netmask: %s", argv[3]); + return -EINVAL; + } + + net_if_ipv4_set_netmask(iface, &addr); + } + +#else /* CONFIG_NET_NATIVE_IPV4 */ + PR_INFO("Set %s and %s to enable native %s support.\n", + "CONFIG_NET_NATIVE", "CONFIG_NET_IPV4", "IPv4"); +#endif /* CONFIG_NET_NATIVE_IPV4 */ + return 0; +} + +static int cmd_net_ip_del(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_NATIVE_IPV4) + struct net_if *iface = NULL; + int idx; + struct in_addr addr; + + if (argc != 3) { + PR_ERROR("Correct usage: net ipv4 del
    "); + return -EINVAL; + } + + idx = get_iface_idx(sh, argv[1]); + if (idx < 0) { + return -ENOEXEC; + } + + iface = net_if_get_by_index(idx); + if (!iface) { + PR_WARNING("No such interface in index %d\n", idx); + return -ENOEXEC; + } + + if (net_addr_pton(AF_INET, argv[2], &addr)) { + PR_ERROR("Invalid address: %s\n", argv[2]); + return -EINVAL; + } + + if (net_ipv4_is_addr_mcast(&addr)) { + int ret; + + ret = net_ipv4_igmp_leave(iface, &addr); + if (ret < 0) { + PR_ERROR("Cannot %s multicast group %s for interface %d (%d)\n", + "leave", net_sprint_ipv4_addr(&addr), idx, ret); + return ret; + } + } else { + if (!net_if_ipv4_addr_rm(iface, &addr)) { + PR_ERROR("Failed to delete %s\n", argv[2]); + return -ENOEXEC; + } + } +#else /* CONFIG_NET_NATIVE_IPV4 */ + PR_INFO("Set %s and %s to enable native %s support.\n", + "CONFIG_NET_NATIVE", "CONFIG_NET_IPV4", "IPv4"); +#endif /* CONFIG_NET_NATIVE_IPV4 */ + return 0; +} + +SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_ip, + SHELL_CMD(add, NULL, + "'net ipv4 add
    []' adds the address to the interface.", + cmd_net_ip_add), + SHELL_CMD(del, NULL, + "'net ipv4 del
    ' deletes the address from the interface.", + cmd_net_ip_del), + SHELL_SUBCMD_SET_END +); + +SHELL_SUBCMD_ADD((net), ipv4, &net_cmd_ip, + "Print information about IPv4 specific information and " + "configuration.", + cmd_net_ipv4, 1, 0); diff --git a/subsys/net/lib/shell/ipv6.c b/subsys/net/lib/shell/ipv6.c new file mode 100644 index 00000000000..04efda65d0f --- /dev/null +++ b/subsys/net/lib/shell/ipv6.c @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#include "net_shell_private.h" +#include "../ip/ipv6.h" + +#if defined(CONFIG_NET_IPV6_FRAGMENT) +void ipv6_frag_cb(struct net_ipv6_reassembly *reass, void *user_data) +{ + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + int *count = data->user_data; + char src[ADDR_LEN]; + int i; + + if (!*count) { + PR("\nIPv6 reassembly Id Remain " + "Src \tDst\n"); + } + + snprintk(src, ADDR_LEN, "%s", net_sprint_ipv6_addr(&reass->src)); + + PR("%p 0x%08x %5d %16s\t%16s\n", reass, reass->id, + k_ticks_to_ms_ceil32(k_work_delayable_remaining_get(&reass->timer)), + src, net_sprint_ipv6_addr(&reass->dst)); + + for (i = 0; i < CONFIG_NET_IPV6_FRAGMENT_MAX_PKT; i++) { + if (reass->pkt[i]) { + struct net_buf *frag = reass->pkt[i]->frags; + + PR("[%d] pkt %p->", i, reass->pkt[i]); + + while (frag) { + PR("%p", frag); + + frag = frag->frags; + if (frag) { + PR("->"); + } + } + + PR("\n"); + } + } + + (*count)++; +} +#endif /* CONFIG_NET_IPV6_FRAGMENT */ + +#if defined(CONFIG_NET_NATIVE_IPV6) + +static void address_lifetime_cb(struct net_if *iface, void *user_data) +{ + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6; + const char *extra; + int i; + + ARG_UNUSED(user_data); + + PR("\nIPv6 addresses for interface %d (%p) (%s)\n", + net_if_get_by_iface(iface), iface, iface2str(iface, &extra)); + PR("============================================%s\n", extra); + + if (!ipv6) { + PR("No IPv6 config found for this interface.\n"); + return; + } + + PR("Type \tState \tLifetime (sec)\tAddress\n"); + + for (i = 0; i < NET_IF_MAX_IPV6_ADDR; i++) { + struct net_if_ipv6_prefix *prefix; + char remaining_str[sizeof("01234567890")]; + uint64_t remaining; + uint8_t prefix_len; + + if (!ipv6->unicast[i].is_used || + ipv6->unicast[i].address.family != AF_INET6) { + continue; + } + + remaining = net_timeout_remaining(&ipv6->unicast[i].lifetime, + k_uptime_get_32()); + + prefix = net_if_ipv6_prefix_get(iface, + &ipv6->unicast[i].address.in6_addr); + if (prefix) { + prefix_len = prefix->len; + } else { + prefix_len = 128U; + } + + if (ipv6->unicast[i].is_infinite) { + snprintk(remaining_str, sizeof(remaining_str) - 1, + "infinite"); + } else { + snprintk(remaining_str, sizeof(remaining_str) - 1, + "%u", (uint32_t)(remaining / 1000U)); + } + + PR("%s \t%s\t%s \t%s/%d\n", + addrtype2str(ipv6->unicast[i].addr_type), + addrstate2str(ipv6->unicast[i].addr_state), + remaining_str, + net_sprint_ipv6_addr( + &ipv6->unicast[i].address.in6_addr), + prefix_len); + } +} +#endif /* CONFIG_NET_NATIVE_IPV6 */ + +static int cmd_net_ipv6(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_NATIVE_IPV6) + struct net_shell_user_data user_data; +#endif + + PR("IPv6 support : %s\n", + IS_ENABLED(CONFIG_NET_IPV6) ? + "enabled" : "disabled"); + if (!IS_ENABLED(CONFIG_NET_IPV6)) { + return -ENOEXEC; + } + +#if defined(CONFIG_NET_NATIVE_IPV6) + PR("IPv6 fragmentation support : %s\n", + IS_ENABLED(CONFIG_NET_IPV6_FRAGMENT) ? "enabled" : + "disabled"); + PR("Multicast Listener Discovery support : %s\n", + IS_ENABLED(CONFIG_NET_IPV6_MLD) ? "enabled" : + "disabled"); + PR("Neighbor cache support : %s\n", + IS_ENABLED(CONFIG_NET_IPV6_NBR_CACHE) ? "enabled" : + "disabled"); + PR("Neighbor discovery support : %s\n", + IS_ENABLED(CONFIG_NET_IPV6_ND) ? "enabled" : + "disabled"); + PR("Duplicate address detection (DAD) support : %s\n", + IS_ENABLED(CONFIG_NET_IPV6_DAD) ? "enabled" : + "disabled"); + PR("Router advertisement RDNSS option support : %s\n", + IS_ENABLED(CONFIG_NET_IPV6_RA_RDNSS) ? "enabled" : + "disabled"); + PR("6lo header compression support : %s\n", + IS_ENABLED(CONFIG_NET_6LO) ? "enabled" : + "disabled"); + + if (IS_ENABLED(CONFIG_NET_6LO_CONTEXT)) { + PR("6lo context based compression " + "support : %s\n", + IS_ENABLED(CONFIG_NET_6LO_CONTEXT) ? "enabled" : + "disabled"); + } + + PR("Max number of IPv6 network interfaces " + "in the system : %d\n", + CONFIG_NET_IF_MAX_IPV6_COUNT); + PR("Max number of unicast IPv6 addresses " + "per network interface : %d\n", + CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT); + PR("Max number of multicast IPv6 addresses " + "per network interface : %d\n", + CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT); + PR("Max number of IPv6 prefixes per network " + "interface : %d\n", + CONFIG_NET_IF_IPV6_PREFIX_COUNT); + + user_data.sh = sh; + user_data.user_data = NULL; + + /* Print information about address lifetime */ + net_if_foreach(address_lifetime_cb, &user_data); +#endif + + return 0; +} + +static int cmd_net_ip6_add(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_NATIVE_IPV6) + struct net_if *iface = NULL; + int idx; + struct in6_addr addr; + + if (argc != 3) { + PR_ERROR("Correct usage: net ipv6 add
    \n"); + return -EINVAL; + } + + idx = get_iface_idx(sh, argv[1]); + if (idx < 0) { + return -ENOEXEC; + } + + iface = net_if_get_by_index(idx); + if (!iface) { + PR_WARNING("No such interface in index %d\n", idx); + return -ENOENT; + } + + if (net_addr_pton(AF_INET6, argv[2], &addr)) { + PR_ERROR("Invalid address: %s\n", argv[2]); + return -EINVAL; + } + + if (net_ipv6_is_addr_mcast(&addr)) { + int ret; + + ret = net_ipv6_mld_join(iface, &addr); + if (ret < 0) { + PR_ERROR("Cannot %s multicast group %s for interface %d (%d)\n", + "join", net_sprint_ipv6_addr(&addr), idx, ret); + return ret; + } + } else { + if (!net_if_ipv6_addr_add(iface, &addr, NET_ADDR_MANUAL, 0)) { + PR_ERROR("Failed to add %s address to interface %p\n", argv[2], iface); + } + } + +#else /* CONFIG_NET_NATIVE_IPV6 */ + PR_INFO("Set %s and %s to enable native %s support.\n", + "CONFIG_NET_NATIVE", "CONFIG_NET_IPV6", "IPv6"); +#endif /* CONFIG_NET_NATIVE_IPV6 */ + return 0; +} + +static int cmd_net_ip6_del(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_NATIVE_IPV6) + struct net_if *iface = NULL; + int idx; + struct in6_addr addr; + + if (argc != 3) { + PR_ERROR("Correct usage: net ipv6 del
    \n"); + return -EINVAL; + } + + idx = get_iface_idx(sh, argv[1]); + if (idx < 0) { + return -ENOEXEC; + } + + iface = net_if_get_by_index(idx); + if (!iface) { + PR_WARNING("No such interface in index %d\n", idx); + return -ENOEXEC; + } + + if (net_addr_pton(AF_INET6, argv[2], &addr)) { + PR_ERROR("Invalid address: %s\n", argv[2]); + return -EINVAL; + } + + if (net_ipv6_is_addr_mcast(&addr)) { + int ret; + + ret = net_ipv6_mld_leave(iface, &addr); + if (ret < 0) { + PR_ERROR("Cannot %s multicast group %s for interface %d (%d)\n", + "leave", net_sprint_ipv6_addr(&addr), idx, ret); + return ret; + } + } else { + if (!net_if_ipv6_addr_rm(iface, &addr)) { + PR_ERROR("Failed to delete %s\n", argv[2]); + return -1; + } + } + +#else /* CONFIG_NET_NATIVE_IPV6 */ + PR_INFO("Set %s and %s to enable native %s support.\n", + "CONFIG_NET_NATIVE", "CONFIG_NET_IPV6", "IPv6"); +#endif /* CONFIG_NET_NATIVE_IPV6 */ + return 0; +} + +SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_ip6, + SHELL_CMD(add, NULL, + "'net ipv6 add
    ' adds the address to the interface.", + cmd_net_ip6_add), + SHELL_CMD(del, NULL, + "'net ipv6 del
    ' deletes the address from the interface.", + cmd_net_ip6_del), + SHELL_SUBCMD_SET_END +); + +SHELL_SUBCMD_ADD((net), ipv6, &net_cmd_ip6, + "Print information about IPv6 specific information and " + "configuration.", + cmd_net_ipv6, 1, 0); diff --git a/subsys/net/lib/shell/mem.c b/subsys/net/lib/shell/mem.c new file mode 100644 index 00000000000..47058f92767 --- /dev/null +++ b/subsys/net/lib/shell/mem.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#include "net_shell_private.h" + +struct ctx_info { + int pos; + bool are_external_pools; + struct k_mem_slab *tx_slabs[CONFIG_NET_MAX_CONTEXTS]; + struct net_buf_pool *data_pools[CONFIG_NET_MAX_CONTEXTS]; +}; + +#if defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE) +#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL) +static bool slab_pool_found_already(struct ctx_info *info, + struct k_mem_slab *slab, + struct net_buf_pool *pool) +{ + int i; + + for (i = 0; i < CONFIG_NET_MAX_CONTEXTS; i++) { + if (slab) { + if (info->tx_slabs[i] == slab) { + return true; + } + } else { + if (info->data_pools[i] == pool) { + return true; + } + } + } + + return false; +} +#endif /* CONFIG_NET_CONTEXT_NET_PKT_POOL */ + +static void context_info(struct net_context *context, void *user_data) +{ +#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL) + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + struct ctx_info *info = data->user_data; + struct k_mem_slab *slab; + struct net_buf_pool *pool; + + if (!net_context_is_used(context)) { + return; + } + + if (context->tx_slab) { + slab = context->tx_slab(); + + if (slab_pool_found_already(info, slab, NULL)) { + return; + } + +#if defined(CONFIG_NET_BUF_POOL_USAGE) + PR("%p\t%u\t%u\tETX\n", + slab, slab->info.num_blocks, k_mem_slab_num_free_get(slab)); +#else + PR("%p\t%d\tETX\n", slab, slab->info.num_blocks); +#endif + info->are_external_pools = true; + info->tx_slabs[info->pos] = slab; + } + + if (context->data_pool) { + pool = context->data_pool(); + + if (slab_pool_found_already(info, NULL, pool)) { + return; + } + +#if defined(CONFIG_NET_BUF_POOL_USAGE) + PR("%p\t%d\t%ld\tEDATA (%s)\n", pool, pool->buf_count, + atomic_get(&pool->avail_count), pool->name); +#else + PR("%p\t%d\tEDATA\n", pool, pool->buf_count); +#endif + info->are_external_pools = true; + info->data_pools[info->pos] = pool; + } + + info->pos++; +#endif /* CONFIG_NET_CONTEXT_NET_PKT_POOL */ +} +#endif /* CONFIG_NET_OFFLOAD || CONFIG_NET_NATIVE */ + +static int cmd_net_mem(const struct shell *sh, size_t argc, char *argv[]) +{ + ARG_UNUSED(argc); + ARG_UNUSED(argv); + +#if defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE) + struct k_mem_slab *rx, *tx; + struct net_buf_pool *rx_data, *tx_data; + + net_pkt_get_info(&rx, &tx, &rx_data, &tx_data); + +#if defined(CONFIG_NET_BUF_FIXED_DATA_SIZE) + PR("Fragment length %d bytes\n", CONFIG_NET_BUF_DATA_SIZE); +#else + PR("Fragment data pool size %d bytes\n", CONFIG_NET_BUF_DATA_POOL_SIZE); +#endif /* CONFIG_NET_BUF_FIXED_DATA_SIZE */ + + PR("Network buffer pools:\n"); + +#if defined(CONFIG_NET_BUF_POOL_USAGE) + PR("Address\t\tTotal\tAvail\tName\n"); + + PR("%p\t%d\t%u\tRX\n", + rx, rx->info.num_blocks, k_mem_slab_num_free_get(rx)); + + PR("%p\t%d\t%u\tTX\n", + tx, tx->info.num_blocks, k_mem_slab_num_free_get(tx)); + + PR("%p\t%d\t%ld\tRX DATA (%s)\n", rx_data, rx_data->buf_count, + atomic_get(&rx_data->avail_count), rx_data->name); + + PR("%p\t%d\t%ld\tTX DATA (%s)\n", tx_data, tx_data->buf_count, + atomic_get(&tx_data->avail_count), tx_data->name); +#else + PR("Address\t\tTotal\tName\n"); + + PR("%p\t%d\tRX\n", rx, rx->info.num_blocks); + PR("%p\t%d\tTX\n", tx, tx->info.num_blocks); + PR("%p\t%d\tRX DATA\n", rx_data, rx_data->buf_count); + PR("%p\t%d\tTX DATA\n", tx_data, tx_data->buf_count); + PR_INFO("Set %s to enable %s support.\n", + "CONFIG_NET_BUF_POOL_USAGE", "net_buf allocation"); +#endif /* CONFIG_NET_BUF_POOL_USAGE */ + + if (IS_ENABLED(CONFIG_NET_CONTEXT_NET_PKT_POOL)) { + struct net_shell_user_data user_data; + struct ctx_info info; + + (void)memset(&info, 0, sizeof(info)); + + user_data.sh = sh; + user_data.user_data = &info; + + net_context_foreach(context_info, &user_data); + + if (!info.are_external_pools) { + PR("No external memory pools found.\n"); + } + } +#else + PR_INFO("Set %s to enable %s support.\n", + "CONFIG_NET_OFFLOAD or CONFIG_NET_NATIVE", "memory usage"); +#endif /* CONFIG_NET_OFFLOAD || CONFIG_NET_NATIVE */ + + return 0; +} + +SHELL_SUBCMD_ADD((net), mem, NULL, + "Print information about network memory usage.", + cmd_net_mem, 1, 0); diff --git a/subsys/net/lib/shell/nbr.c b/subsys/net/lib/shell/nbr.c new file mode 100644 index 00000000000..63b62406702 --- /dev/null +++ b/subsys/net/lib/shell/nbr.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#include "net_shell_private.h" + +static int cmd_net_nbr_rm(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_IPV6) + struct in6_addr addr; + int ret; +#endif + +#if defined(CONFIG_NET_IPV6) + if (!argv[1]) { + PR_WARNING("Neighbor IPv6 address missing.\n"); + return -ENOEXEC; + } + + ret = net_addr_pton(AF_INET6, argv[1], &addr); + if (ret < 0) { + PR_WARNING("Cannot parse '%s'\n", argv[1]); + return -ENOEXEC; + } + + if (!net_ipv6_nbr_rm(NULL, &addr)) { + PR_WARNING("Cannot remove neighbor %s\n", + net_sprint_ipv6_addr(&addr)); + return -ENOEXEC; + } + + PR("Neighbor %s removed.\n", net_sprint_ipv6_addr(&addr)); +#else + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + PR_INFO("IPv6 not enabled.\n"); +#endif + + return 0; +} + +#if defined(CONFIG_NET_IPV6) +static void nbr_cb(struct net_nbr *nbr, void *user_data) +{ + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + int *count = data->user_data; + char *padding = ""; + char *state_pad = ""; + const char *state_str; +#if defined(CONFIG_NET_IPV6_ND) + int64_t remaining; +#endif + +#if defined(CONFIG_NET_L2_IEEE802154) + padding = " "; +#endif + + if (*count == 0) { + PR(" Neighbor Interface Flags State " + "Remain Link %sAddress\n", padding); + } + + (*count)++; + + state_str = net_ipv6_nbr_state2str(net_ipv6_nbr_data(nbr)->state); + + /* This is not a proper way but the minimal libc does not honor + * string lengths in %s modifier so in order the output to look + * nice, do it like this. + */ + if (strlen(state_str) == 5) { + state_pad = " "; + } + +#if defined(CONFIG_NET_IPV6_ND) + remaining = net_ipv6_nbr_data(nbr)->reachable + + net_ipv6_nbr_data(nbr)->reachable_timeout - + k_uptime_get(); +#endif + + PR("[%2d] %p %d %5d/%d/%d/%d %s%s %6d %17s%s %s\n", + *count, nbr, net_if_get_by_iface(nbr->iface), + net_ipv6_nbr_data(nbr)->link_metric, + nbr->ref, + net_ipv6_nbr_data(nbr)->ns_count, + net_ipv6_nbr_data(nbr)->is_router, + state_str, + state_pad, +#if defined(CONFIG_NET_IPV6_ND) + (int)(remaining > 0 ? remaining : 0), +#else + 0, +#endif + nbr->idx == NET_NBR_LLADDR_UNKNOWN ? "?" : + net_sprint_ll_addr( + net_nbr_get_lladdr(nbr->idx)->addr, + net_nbr_get_lladdr(nbr->idx)->len), + nbr->idx == NET_NBR_LLADDR_UNKNOWN ? "" : + (net_nbr_get_lladdr(nbr->idx)->len == 8U ? "" : padding), + net_sprint_ipv6_addr(&net_ipv6_nbr_data(nbr)->addr)); +} +#endif + +static int cmd_net_nbr(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_IPV6) + int count = 0; + struct net_shell_user_data user_data; +#endif + + ARG_UNUSED(argc); + ARG_UNUSED(argv); + +#if defined(CONFIG_NET_IPV6) + user_data.sh = sh; + user_data.user_data = &count; + + net_ipv6_nbr_foreach(nbr_cb, &user_data); + + if (count == 0) { + PR("No neighbors.\n"); + } +#else + PR_INFO("IPv6 not enabled.\n"); +#endif /* CONFIG_NET_IPV6 */ + + return 0; +} + +#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_SHELL_DYN_CMD_COMPLETION) +static char nbr_address_buffer[CONFIG_NET_IPV6_MAX_NEIGHBORS][NET_IPV6_ADDR_LEN]; + +static void nbr_address_cb(struct net_nbr *nbr, void *user_data) +{ + int *count = user_data; + + if (*count >= CONFIG_NET_IPV6_MAX_NEIGHBORS) { + return; + } + + snprintk(nbr_address_buffer[*count], NET_IPV6_ADDR_LEN, + "%s", net_sprint_ipv6_addr(&net_ipv6_nbr_data(nbr)->addr)); + + (*count)++; +} + +static void nbr_populate_addresses(void) +{ + int count = 0; + + net_ipv6_nbr_foreach(nbr_address_cb, &count); +} + +static char *set_nbr_address(size_t idx) +{ + if (idx == 0) { + memset(nbr_address_buffer, 0, sizeof(nbr_address_buffer)); + nbr_populate_addresses(); + } + + if (idx >= CONFIG_NET_IPV6_MAX_NEIGHBORS) { + return NULL; + } + + if (!nbr_address_buffer[idx][0]) { + return NULL; + } + + return nbr_address_buffer[idx]; +} + +static void nbr_address_get(size_t idx, struct shell_static_entry *entry); + +SHELL_DYNAMIC_CMD_CREATE(nbr_address, nbr_address_get); + +#define NBR_ADDRESS_CMD &nbr_address + +static void nbr_address_get(size_t idx, struct shell_static_entry *entry) +{ + entry->handler = NULL; + entry->help = NULL; + entry->subcmd = &nbr_address; + entry->syntax = set_nbr_address(idx); +} + +#else +#define NBR_ADDRESS_CMD NULL +#endif /* CONFIG_NET_IPV6 && CONFIG_NET_SHELL_DYN_CMD_COMPLETION */ + +SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_nbr, + SHELL_CMD(rm, NBR_ADDRESS_CMD, + "'net nbr rm
    ' removes neighbor from cache.", + cmd_net_nbr_rm), + SHELL_SUBCMD_SET_END +); + +SHELL_SUBCMD_ADD((net), nbr, &net_cmd_nbr, + "Print neighbor information.", + cmd_net_nbr, 1, 0); diff --git a/subsys/net/lib/shell/net_shell.c b/subsys/net/lib/shell/net_shell.c new file mode 100644 index 00000000000..9f932cb1bc4 --- /dev/null +++ b/subsys/net/lib/shell/net_shell.c @@ -0,0 +1,254 @@ +/** @file + * @brief Network shell module + * + * Provide some networking shell commands that can be useful to applications. + */ + +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_REGISTER(net_shell, LOG_LEVEL_DBG); + +#include +#include +#include + +#include + +#include "net_shell_private.h" +#include "net_shell.h" + +int get_iface_idx(const struct shell *sh, char *index_str) +{ + char *endptr; + int idx; + + if (!index_str) { + PR_WARNING("Interface index is missing.\n"); + return -EINVAL; + } + + idx = strtol(index_str, &endptr, 10); + if (*endptr != '\0') { + PR_WARNING("Invalid index %s\n", index_str); + return -ENOENT; + } + + if (idx < 0 || idx > 255) { + PR_WARNING("Invalid index %d\n", idx); + return -ERANGE; + } + + return idx; +} + +const char *addrtype2str(enum net_addr_type addr_type) +{ + switch (addr_type) { + case NET_ADDR_ANY: + return ""; + case NET_ADDR_AUTOCONF: + return "autoconf"; + case NET_ADDR_DHCP: + return "DHCP"; + case NET_ADDR_MANUAL: + return "manual"; + case NET_ADDR_OVERRIDABLE: + return "overridable"; + } + + return ""; +} + +const char *addrstate2str(enum net_addr_state addr_state) +{ + switch (addr_state) { + case NET_ADDR_ANY_STATE: + return ""; + case NET_ADDR_TENTATIVE: + return "tentative"; + case NET_ADDR_PREFERRED: + return "preferred"; + case NET_ADDR_DEPRECATED: + return "deprecated"; + } + + return ""; +} + +#if defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE) +void get_addresses(struct net_context *context, + char addr_local[], int local_len, + char addr_remote[], int remote_len) +{ + if (IS_ENABLED(CONFIG_NET_IPV6) && context->local.family == AF_INET6) { + snprintk(addr_local, local_len, "[%s]:%u", + net_sprint_ipv6_addr( + net_sin6_ptr(&context->local)->sin6_addr), + ntohs(net_sin6_ptr(&context->local)->sin6_port)); + snprintk(addr_remote, remote_len, "[%s]:%u", + net_sprint_ipv6_addr( + &net_sin6(&context->remote)->sin6_addr), + ntohs(net_sin6(&context->remote)->sin6_port)); + + } else if (IS_ENABLED(CONFIG_NET_IPV4) && context->local.family == AF_INET) { + snprintk(addr_local, local_len, "%s:%d", + net_sprint_ipv4_addr( + net_sin_ptr(&context->local)->sin_addr), + ntohs(net_sin_ptr(&context->local)->sin_port)); + + /* Check if we need to print the v4-mapping-to-v6 address */ + if (IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6) && + net_sin(&context->remote)->sin_family == AF_INET6 && + net_ipv6_addr_is_v4_mapped(&net_sin6(&context->remote)->sin6_addr)) { + snprintk(addr_remote, remote_len, "[%s]:%d", + net_sprint_ipv6_addr( + &net_sin6(&context->remote)->sin6_addr), + ntohs(net_sin6(&context->remote)->sin6_port)); + } else { + snprintk(addr_remote, remote_len, "%s:%d", + net_sprint_ipv4_addr( + &net_sin(&context->remote)->sin_addr), + ntohs(net_sin(&context->remote)->sin_port)); + } + + } else if (context->local.family == AF_UNSPEC) { + snprintk(addr_local, local_len, "AF_UNSPEC"); + } else if (context->local.family == AF_PACKET) { + snprintk(addr_local, local_len, "AF_PACKET"); + } else if (context->local.family == AF_CAN) { + snprintk(addr_local, local_len, "AF_CAN"); + } else { + snprintk(addr_local, local_len, "AF_UNK(%d)", + context->local.family); + } +} +#endif /* CONFIG_NET_OFFLOAD || CONFIG_NET_NATIVE */ + +const char *iface2str(struct net_if *iface, const char **extra) +{ +#ifdef CONFIG_NET_L2_IEEE802154 + if (net_if_l2(iface) == &NET_L2_GET_NAME(IEEE802154)) { + if (extra) { + *extra = "============="; + } + + return "IEEE 802.15.4"; + } +#endif + +#ifdef CONFIG_NET_L2_ETHERNET + if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) { + struct ethernet_context *eth_ctx = net_if_l2_data(iface); + + if (eth_ctx->eth_if_type == L2_ETH_IF_TYPE_WIFI) { + if (extra) { + *extra = "===="; + } + + return "WiFi"; + } + + if (extra) { + *extra = "========"; + } + + return "Ethernet"; + } +#endif + +#ifdef CONFIG_NET_L2_VIRTUAL + if (net_if_l2(iface) == &NET_L2_GET_NAME(VIRTUAL)) { + if (extra) { + *extra = "======="; + } + + return "Virtual"; + } +#endif + +#ifdef CONFIG_NET_L2_PPP + if (net_if_l2(iface) == &NET_L2_GET_NAME(PPP)) { + if (extra) { + *extra = "==="; + } + + return "PPP"; + } +#endif + +#ifdef CONFIG_NET_L2_DUMMY + if (net_if_l2(iface) == &NET_L2_GET_NAME(DUMMY)) { + if (extra) { + *extra = "====="; + } + + return "Dummy"; + } +#endif + +#ifdef CONFIG_NET_L2_OPENTHREAD + if (net_if_l2(iface) == &NET_L2_GET_NAME(OPENTHREAD)) { + if (extra) { + *extra = "=========="; + } + + return "OpenThread"; + } +#endif + +#ifdef CONFIG_NET_L2_BT + if (net_if_l2(iface) == &NET_L2_GET_NAME(BLUETOOTH)) { + if (extra) { + *extra = "========="; + } + + return "Bluetooth"; + } +#endif + +#ifdef CONFIG_NET_OFFLOAD + if (net_if_is_ip_offloaded(iface)) { + if (extra) { + *extra = "=========="; + } + + return "IP Offload"; + } +#endif + +#ifdef CONFIG_NET_L2_CANBUS_RAW + if (net_if_l2(iface) == &NET_L2_GET_NAME(CANBUS_RAW)) { + if (extra) { + *extra = "=========="; + } + + return "CANBUS_RAW"; + } +#endif + + if (extra) { + *extra = "=============="; + } + + return ""; +} + +/* Placeholder for net commands that are configured in the rest of the .c files */ +SHELL_SUBCMD_SET_CREATE(net_cmds, (net)); + +SHELL_CMD_REGISTER(net, &net_cmds, "Networking commands", NULL); + +int net_shell_init(void) +{ + if (IS_ENABLED(CONFIG_NET_MGMT_EVENT_MONITOR_AUTO_START)) { + events_enable(); + } + + return 0; +} diff --git a/subsys/net/ip/net_shell.h b/subsys/net/lib/shell/net_shell.h similarity index 100% rename from subsys/net/ip/net_shell.h rename to subsys/net/lib/shell/net_shell.h diff --git a/subsys/net/lib/shell/net_shell_private.h b/subsys/net/lib/shell/net_shell_private.h new file mode 100644 index 00000000000..8b5566022d9 --- /dev/null +++ b/subsys/net/lib/shell/net_shell_private.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#define PR(fmt, ...) \ + shell_fprintf(sh, SHELL_NORMAL, fmt, ##__VA_ARGS__) + +#define PR_SHELL(sh, fmt, ...) \ + shell_fprintf(sh, SHELL_NORMAL, fmt, ##__VA_ARGS__) + +#define PR_ERROR(fmt, ...) \ + shell_fprintf(sh, SHELL_ERROR, fmt, ##__VA_ARGS__) + +#define PR_INFO(fmt, ...) \ + shell_fprintf(sh, SHELL_INFO, fmt, ##__VA_ARGS__) + +#define PR_WARNING(fmt, ...) \ + shell_fprintf(sh, SHELL_WARNING, fmt, ##__VA_ARGS__) + +#include "net_private.h" +#include "../ip/ipv6.h" + +struct net_shell_user_data { + const struct shell *sh; + void *user_data; +}; + +#if !defined(NET_VLAN_MAX_COUNT) +#define MAX_IFACE_COUNT NET_IF_MAX_CONFIGS +#else +#define MAX_IFACE_COUNT NET_VLAN_MAX_COUNT +#endif + +#if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4) +#define ADDR_LEN NET_IPV6_ADDR_LEN +#elif defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6) +#define ADDR_LEN NET_IPV4_ADDR_LEN +#else +#define ADDR_LEN NET_IPV6_ADDR_LEN +#endif + +#if defined(CONFIG_NET_SHELL_DYN_CMD_COMPLETION) +#define IFACE_DYN_CMD &iface_index +#else +#define IFACE_DYN_CMD NULL +#endif /* CONFIG_NET_SHELL_DYN_CMD_COMPLETION */ + +const char *addrtype2str(enum net_addr_type addr_type); +const char *addrstate2str(enum net_addr_state addr_state); +void get_addresses(struct net_context *context, + char addr_local[], int local_len, + char addr_remote[], int remote_len); +void events_enable(void); +int get_iface_idx(const struct shell *sh, char *index_str); +const char *iface2str(struct net_if *iface, const char **extra); +void ipv6_frag_cb(struct net_ipv6_reassembly *reass, void *user_data); diff --git a/subsys/net/lib/shell/ping.c b/subsys/net/lib/shell/ping.c new file mode 100644 index 00000000000..833c6eb8d54 --- /dev/null +++ b/subsys/net/lib/shell/ping.c @@ -0,0 +1,502 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#include +#include +#include +#include + +#include "net_shell_private.h" + +#include "../ip/icmpv6.h" +#include "../ip/icmpv4.h" +#include "../ip/route.h" + +#if defined(CONFIG_NET_IP) + +static struct ping_context { + struct k_work_delayable work; + struct net_icmp_ctx icmp; + union { + struct sockaddr_in addr4; + struct sockaddr_in6 addr6; + struct sockaddr addr; + }; + struct net_if *iface; + const struct shell *sh; + + /* Ping parameters */ + uint32_t count; + uint32_t interval; + uint32_t sequence; + uint16_t payload_size; + uint8_t tos; + int priority; +} ping_ctx; + +static void ping_done(struct ping_context *ctx); + +#if defined(CONFIG_NET_NATIVE_IPV6) + +static int handle_ipv6_echo_reply(struct net_icmp_ctx *ctx, + struct net_pkt *pkt, + struct net_icmp_ip_hdr *hdr, + struct net_icmp_hdr *icmp_hdr, + void *user_data) +{ + NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_access, + struct net_icmpv6_echo_req); + struct net_ipv6_hdr *ip_hdr = hdr->ipv6; + struct net_icmpv6_echo_req *icmp_echo; + uint32_t cycles; + char time_buf[16] = { 0 }; + + icmp_echo = (struct net_icmpv6_echo_req *)net_pkt_get_data(pkt, + &icmp_access); + if (icmp_echo == NULL) { + return -EIO; + } + + net_pkt_skip(pkt, sizeof(*icmp_echo)); + + if (net_pkt_remaining_data(pkt) >= sizeof(uint32_t)) { + if (net_pkt_read_be32(pkt, &cycles)) { + return -EIO; + } + + cycles = k_cycle_get_32() - cycles; + + snprintf(time_buf, sizeof(time_buf), +#ifdef CONFIG_FPU + "time=%.2f ms", + (double)((uint32_t)k_cyc_to_ns_floor64(cycles) / 1000000.f) +#else + "time=%d ms", + ((uint32_t)k_cyc_to_ns_floor64(cycles) / 1000000) +#endif + ); + } + + PR_SHELL(ping_ctx.sh, "%d bytes from %s to %s: icmp_seq=%d ttl=%d " +#ifdef CONFIG_IEEE802154 + "rssi=%d " +#endif + "%s\n", + ntohs(ip_hdr->len) - net_pkt_ipv6_ext_len(pkt) - + NET_ICMPH_LEN, + net_sprint_ipv6_addr(&ip_hdr->src), + net_sprint_ipv6_addr(&ip_hdr->dst), + ntohs(icmp_echo->sequence), + ip_hdr->hop_limit, +#ifdef CONFIG_IEEE802154 + net_pkt_ieee802154_rssi_dbm(pkt), +#endif + time_buf); + + if (ntohs(icmp_echo->sequence) == ping_ctx.count) { + ping_done(&ping_ctx); + } + + net_pkt_unref(pkt); + return 0; +} +#else +static int handle_ipv6_echo_reply(struct net_icmp_ctx *ctx, + struct net_pkt *pkt, + struct net_icmp_ip_hdr *hdr, + struct net_icmp_hdr *icmp_hdr, + void *user_data) +{ + ARG_UNUSED(ctx); + ARG_UNUSED(pkt); + ARG_UNUSED(hdr); + ARG_UNUSED(icmp_hdr); + ARG_UNUSED(user_data); + + return -ENOTSUP; +} +#endif /* CONFIG_NET_IPV6 */ + +#if defined(CONFIG_NET_NATIVE_IPV4) + +static int handle_ipv4_echo_reply(struct net_icmp_ctx *ctx, + struct net_pkt *pkt, + struct net_icmp_ip_hdr *hdr, + struct net_icmp_hdr *icmp_hdr, + void *user_data) +{ + NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_access, + struct net_icmpv4_echo_req); + struct net_ipv4_hdr *ip_hdr = hdr->ipv4; + uint32_t cycles; + struct net_icmpv4_echo_req *icmp_echo; + char time_buf[16] = { 0 }; + + icmp_echo = (struct net_icmpv4_echo_req *)net_pkt_get_data(pkt, + &icmp_access); + if (icmp_echo == NULL) { + return -EIO; + } + + net_pkt_skip(pkt, sizeof(*icmp_echo)); + + if (net_pkt_remaining_data(pkt) >= sizeof(uint32_t)) { + if (net_pkt_read_be32(pkt, &cycles)) { + return -EIO; + } + + cycles = k_cycle_get_32() - cycles; + + snprintf(time_buf, sizeof(time_buf), +#ifdef CONFIG_FPU + "time=%.2f ms", + (double)((uint32_t)k_cyc_to_ns_floor64(cycles) / 1000000.f) +#else + "time=%d ms", + ((uint32_t)k_cyc_to_ns_floor64(cycles) / 1000000) +#endif + ); + } + + PR_SHELL(ping_ctx.sh, "%d bytes from %s to %s: icmp_seq=%d ttl=%d " + "%s\n", + ntohs(ip_hdr->len) - net_pkt_ipv6_ext_len(pkt) - + NET_ICMPH_LEN, + net_sprint_ipv4_addr(&ip_hdr->src), + net_sprint_ipv4_addr(&ip_hdr->dst), + ntohs(icmp_echo->sequence), + ip_hdr->ttl, + time_buf); + + if (ntohs(icmp_echo->sequence) == ping_ctx.count) { + ping_done(&ping_ctx); + } + + net_pkt_unref(pkt); + return 0; +} +#else +static int handle_ipv4_echo_reply(struct net_icmp_ctx *ctx, + struct net_pkt *pkt, + struct net_icmp_ip_hdr *hdr, + struct net_icmp_hdr *icmp_hdr, + void *user_data) +{ + ARG_UNUSED(ctx); + ARG_UNUSED(pkt); + ARG_UNUSED(hdr); + ARG_UNUSED(icmp_hdr); + ARG_UNUSED(user_data); + + return -ENOTSUP; +} +#endif /* CONFIG_NET_IPV4 */ + +static int parse_arg(size_t *i, size_t argc, char *argv[]) +{ + int res = -1; + const char *str = argv[*i] + 2; + char *endptr; + + if (*str == 0) { + if (*i + 1 >= argc) { + return -1; + } + + *i += 1; + str = argv[*i]; + } + + errno = 0; + if (strncmp(str, "0x", 2) == 0) { + res = strtol(str, &endptr, 16); + } else { + res = strtol(str, &endptr, 10); + } + + if (errno || (endptr == str)) { + return -1; + } + + return res; +} + +static void ping_cleanup(struct ping_context *ctx) +{ + (void)net_icmp_cleanup_ctx(&ctx->icmp); + shell_set_bypass(ctx->sh, NULL); +} + +static void ping_done(struct ping_context *ctx) +{ + k_work_cancel_delayable(&ctx->work); + ping_cleanup(ctx); + /* Dummy write to refresh the prompt. */ + shell_fprintf(ctx->sh, SHELL_NORMAL, ""); +} + +static void ping_work(struct k_work *work) +{ + struct k_work_delayable *dwork = k_work_delayable_from_work(work); + struct ping_context *ctx = + CONTAINER_OF(dwork, struct ping_context, work); + const struct shell *sh = ctx->sh; + struct net_icmp_ping_params params; + int ret; + + ctx->sequence++; + + if (ctx->sequence > ctx->count) { + PR_INFO("Ping timeout\n"); + ping_done(ctx); + return; + } + + if (ctx->sequence < ctx->count) { + k_work_reschedule(&ctx->work, K_MSEC(ctx->interval)); + } else { + k_work_reschedule(&ctx->work, K_SECONDS(2)); + } + + params.identifier = sys_rand32_get(); + params.sequence = ctx->sequence; + params.tc_tos = ctx->tos; + params.priority = ctx->priority; + params.data = NULL; + params.data_size = ctx->payload_size; + + ret = net_icmp_send_echo_request(&ctx->icmp, + ctx->iface, + &ctx->addr, + ¶ms, + ctx); + if (ret != 0) { + PR_WARNING("Failed to send ping, err: %d", ret); + ping_done(ctx); + return; + } +} + +#define ASCII_CTRL_C 0x03 + +static void ping_bypass(const struct shell *sh, uint8_t *data, size_t len) +{ + ARG_UNUSED(sh); + + for (size_t i = 0; i < len; i++) { + if (data[i] == ASCII_CTRL_C) { + k_work_cancel_delayable(&ping_ctx.work); + ping_cleanup(&ping_ctx); + break; + } + } +} + +static struct net_if *ping_select_iface(int id, struct sockaddr *target) +{ + struct net_if *iface = net_if_get_by_index(id); + + if (iface != NULL) { + goto out; + } + + if (IS_ENABLED(CONFIG_NET_IPV4) && target->sa_family == AF_INET) { + iface = net_if_ipv4_select_src_iface(&net_sin(target)->sin_addr); + if (iface != NULL) { + goto out; + } + + iface = net_if_get_default(); + goto out; + } + + if (IS_ENABLED(CONFIG_NET_IPV6) && target->sa_family == AF_INET6) { + struct net_nbr *nbr; +#if defined(CONFIG_NET_ROUTE) + struct net_route_entry *route; +#endif + + iface = net_if_ipv6_select_src_iface(&net_sin6(target)->sin6_addr); + if (iface != NULL) { + goto out; + } + + nbr = net_ipv6_nbr_lookup(NULL, &net_sin6(target)->sin6_addr); + if (nbr) { + iface = nbr->iface; + goto out; + } + +#if defined(CONFIG_NET_ROUTE) + route = net_route_lookup(NULL, &net_sin6(target)->sin6_addr); + if (route) { + iface = route->iface; + goto out; + } +#endif + + iface = net_if_get_default(); + } + +out: + return iface; +} + +#endif /* CONFIG_NET_IP */ + +static int cmd_net_ping(const struct shell *sh, size_t argc, char *argv[]) +{ +#if !defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6) + ARG_UNUSED(sh); + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + return -EOPNOTSUPP; +#else + char *host = NULL; + + int count = 3; + int interval = 1000; + int iface_idx = -1; + int tos = 0; + int payload_size = 4; + int priority = -1; + int ret; + + for (size_t i = 1; i < argc; ++i) { + + if (*argv[i] != '-') { + host = argv[i]; + continue; + } + + switch (argv[i][1]) { + case 'c': + count = parse_arg(&i, argc, argv); + if (count < 0) { + PR_WARNING("Parse error: %s\n", argv[i]); + return -ENOEXEC; + } + + + break; + case 'i': + interval = parse_arg(&i, argc, argv); + if (interval < 0) { + PR_WARNING("Parse error: %s\n", argv[i]); + return -ENOEXEC; + } + + break; + + case 'I': + iface_idx = parse_arg(&i, argc, argv); + if (iface_idx < 0 || !net_if_get_by_index(iface_idx)) { + PR_WARNING("Parse error: %s\n", argv[i]); + return -ENOEXEC; + } + break; + + case 'p': + priority = parse_arg(&i, argc, argv); + if (priority < 0 || priority > UINT8_MAX) { + PR_WARNING("Parse error: %s\n", argv[i]); + return -ENOEXEC; + } + break; + + case 'Q': + tos = parse_arg(&i, argc, argv); + if (tos < 0 || tos > UINT8_MAX) { + PR_WARNING("Parse error: %s\n", argv[i]); + return -ENOEXEC; + } + + break; + + case 's': + payload_size = parse_arg(&i, argc, argv); + if (payload_size < 0 || payload_size > UINT16_MAX) { + PR_WARNING("Parse error: %s\n", argv[i]); + return -ENOEXEC; + } + + break; + + default: + PR_WARNING("Unrecognized argument: %s\n", argv[i]); + return -ENOEXEC; + } + } + + if (!host) { + PR_WARNING("Target host missing\n"); + return -ENOEXEC; + } + + memset(&ping_ctx, 0, sizeof(ping_ctx)); + + k_work_init_delayable(&ping_ctx.work, ping_work); + + ping_ctx.sh = sh; + ping_ctx.count = count; + ping_ctx.interval = interval; + ping_ctx.priority = priority; + ping_ctx.tos = tos; + ping_ctx.payload_size = payload_size; + + if (IS_ENABLED(CONFIG_NET_IPV6) && + net_addr_pton(AF_INET6, host, &ping_ctx.addr6.sin6_addr) == 0) { + ping_ctx.addr6.sin6_family = AF_INET6; + + ret = net_icmp_init_ctx(&ping_ctx.icmp, NET_ICMPV6_ECHO_REPLY, 0, + handle_ipv6_echo_reply); + if (ret < 0) { + PR_WARNING("Cannot initialize ICMP context for %s\n", "IPv6"); + return 0; + } + } else if (IS_ENABLED(CONFIG_NET_IPV4) && + net_addr_pton(AF_INET, host, &ping_ctx.addr4.sin_addr) == 0) { + ping_ctx.addr4.sin_family = AF_INET; + + ret = net_icmp_init_ctx(&ping_ctx.icmp, NET_ICMPV4_ECHO_REPLY, 0, + handle_ipv4_echo_reply); + if (ret < 0) { + PR_WARNING("Cannot initialize ICMP context for %s\n", "IPv4"); + return 0; + } + } else { + PR_WARNING("Invalid IP address\n"); + return 0; + } + + ping_ctx.iface = ping_select_iface(iface_idx, &ping_ctx.addr); + + PR("PING %s\n", host); + + shell_set_bypass(sh, ping_bypass); + k_work_reschedule(&ping_ctx.work, K_NO_WAIT); + + return 0; +#endif +} + +SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_ping, + SHELL_CMD(--help, NULL, + "'net ping [-c count] [-i interval ms] [-I ] " + "[-Q tos] [-s payload size] [-p priority] ' " + "Send ICMPv4 or ICMPv6 Echo-Request to a network host.", + cmd_net_ping), + SHELL_SUBCMD_SET_END +); + +SHELL_SUBCMD_ADD((net), ping, &net_cmd_ping, + "Ping a network host.", + cmd_net_ping, 1, 13); diff --git a/subsys/net/lib/shell/pkt.c b/subsys/net/lib/shell/pkt.c new file mode 100644 index 00000000000..3306b05d1a7 --- /dev/null +++ b/subsys/net/lib/shell/pkt.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#include "net_shell_private.h" + +static bool is_pkt_part_of_slab(const struct k_mem_slab *slab, const char *ptr) +{ + size_t last_offset = (slab->info.num_blocks - 1) * slab->info.block_size; + size_t ptr_offset; + + /* Check if pointer fits into slab buffer area. */ + if ((ptr < slab->buffer) || (ptr > slab->buffer + last_offset)) { + return false; + } + + /* Check if pointer offset is correct. */ + ptr_offset = ptr - slab->buffer; + if (ptr_offset % slab->info.block_size != 0) { + return false; + } + + return true; +} + +struct ctx_pkt_slab_info { + const void *ptr; + bool pkt_source_found; +}; + +static void check_context_pool(struct net_context *context, void *user_data) +{ +#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL) + if (!net_context_is_used(context)) { + return; + } + + if (context->tx_slab) { + struct ctx_pkt_slab_info *info = user_data; + struct k_mem_slab *slab = context->tx_slab(); + + if (is_pkt_part_of_slab(slab, info->ptr)) { + info->pkt_source_found = true; + } + } +#endif /* CONFIG_NET_CONTEXT_NET_PKT_POOL */ +} + +static bool is_pkt_ptr_valid(const void *ptr) +{ + struct k_mem_slab *rx, *tx; + + net_pkt_get_info(&rx, &tx, NULL, NULL); + + if (is_pkt_part_of_slab(rx, ptr) || is_pkt_part_of_slab(tx, ptr)) { + return true; + } + + if (IS_ENABLED(CONFIG_NET_CONTEXT_NET_PKT_POOL)) { + struct ctx_pkt_slab_info info; + + info.ptr = ptr; + info.pkt_source_found = false; + + net_context_foreach(check_context_pool, &info); + + if (info.pkt_source_found) { + return true; + } + } + + return false; +} + +static struct net_pkt *get_net_pkt(const char *ptr_str) +{ + uint8_t buf[sizeof(intptr_t)]; + intptr_t ptr = 0; + size_t len; + int i; + + if (ptr_str[0] == '0' && ptr_str[1] == 'x') { + ptr_str += 2; + } + + len = hex2bin(ptr_str, strlen(ptr_str), buf, sizeof(buf)); + if (!len) { + return NULL; + } + + for (i = len - 1; i >= 0; i--) { + ptr |= buf[i] << 8 * (len - 1 - i); + } + + return (struct net_pkt *)ptr; +} + +static void net_pkt_buffer_info(const struct shell *sh, struct net_pkt *pkt) +{ + struct net_buf *buf = pkt->buffer; + + PR("net_pkt %p buffer chain:\n", pkt); + PR("%p[%ld]", pkt, atomic_get(&pkt->atomic_ref)); + + if (buf) { + PR("->"); + } + + while (buf) { + PR("%p[%ld/%u (%u/%u)]", buf, atomic_get(&pkt->atomic_ref), + buf->len, net_buf_max_len(buf), buf->size); + + buf = buf->frags; + if (buf) { + PR("->"); + } + } + + PR("\n"); +} + +static void net_pkt_buffer_hexdump(const struct shell *sh, + struct net_pkt *pkt) +{ + struct net_buf *buf = pkt->buffer; + int i = 0; + + if (!buf || buf->ref == 0) { + return; + } + + PR("net_pkt %p buffer chain hexdump:\n", pkt); + + while (buf) { + PR("net_buf[%d] %p\n", i++, buf); + shell_hexdump(sh, buf->data, buf->len); + buf = buf->frags; + } +} + +static int cmd_net_pkt(const struct shell *sh, size_t argc, char *argv[]) +{ + struct net_pkt *pkt; + + pkt = get_net_pkt(argv[1]); + if (!pkt) { + PR_ERROR("Invalid ptr value (%s). " + "Example: 0x01020304\n", argv[1]); + + return -ENOEXEC; + } + + if (!is_pkt_ptr_valid(pkt)) { + PR_ERROR("Pointer is not recognized as net_pkt (%s).\n", + argv[1]); + + return -ENOEXEC; + } + + net_pkt_buffer_info(sh, pkt); + PR("\n"); + net_pkt_buffer_hexdump(sh, pkt); + + return 0; +} + +SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_pkt, + SHELL_CMD(--help, NULL, + "'net pkt ' " + "Print information about given net_pkt", + cmd_net_pkt), + SHELL_SUBCMD_SET_END +); + +SHELL_SUBCMD_ADD((net), pkt, &net_cmd_pkt, + "net_pkt information.", + cmd_net_pkt, 2, 0); diff --git a/subsys/net/lib/shell/ppp.c b/subsys/net/lib/shell/ppp.c new file mode 100644 index 00000000000..f63c6ca3324 --- /dev/null +++ b/subsys/net/lib/shell/ppp.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#include + +#include "net_shell_private.h" + +#if defined(CONFIG_NET_L2_PPP) +#include +#include "ppp/ppp_internal.h" +#endif + +static int cmd_net_ppp_ping(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_PPP) + if (argv[1]) { + int ret, idx = get_iface_idx(sh, argv[1]); + + if (idx < 0) { + return -ENOEXEC; + } + + ret = net_ppp_ping(idx, MSEC_PER_SEC * 1); + if (ret < 0) { + if (ret == -EAGAIN) { + PR_INFO("PPP Echo-Req timeout.\n"); + } else if (ret == -ENODEV || ret == -ENOENT) { + PR_INFO("Not a PPP interface (%d)\n", idx); + } else { + PR_INFO("PPP Echo-Req failed (%d)\n", ret); + } + } else { + if (ret > 1000) { + PR_INFO("%s%d msec\n", + "Received PPP Echo-Reply in ", + ret / 1000); + } else { + PR_INFO("%s%d usec\n", + "Received PPP Echo-Reply in ", ret); + } + } + } else { + PR_INFO("PPP network interface must be given.\n"); + return -ENOEXEC; + } +#else + PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_L2_PPP", "PPP"); +#endif + return 0; +} + +static int cmd_net_ppp_status(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_PPP) + int idx = 0; + struct ppp_context *ctx; + + if (argv[1]) { + idx = get_iface_idx(sh, argv[1]); + if (idx < 0) { + return -ENOEXEC; + } + } + + ctx = net_ppp_context_get(idx); + if (!ctx) { + PR_INFO("PPP context not found.\n"); + return -ENOEXEC; + } + + PR("PPP phase : %s (%d)\n", ppp_phase_str(ctx->phase), + ctx->phase); + PR("LCP state : %s (%d)\n", + ppp_state_str(ctx->lcp.fsm.state), ctx->lcp.fsm.state); + PR("LCP retransmits : %u\n", ctx->lcp.fsm.retransmits); + PR("LCP NACK loops : %u\n", ctx->lcp.fsm.nack_loops); + PR("LCP NACKs recv : %u\n", ctx->lcp.fsm.recv_nack_loops); + PR("LCP current id : %d\n", ctx->lcp.fsm.id); + PR("LCP ACK received : %s\n", ctx->lcp.fsm.ack_received ? + "yes" : "no"); + +#if defined(CONFIG_NET_IPV4) + PR("IPCP state : %s (%d)\n", + ppp_state_str(ctx->ipcp.fsm.state), ctx->ipcp.fsm.state); + PR("IPCP retransmits : %u\n", ctx->ipcp.fsm.retransmits); + PR("IPCP NACK loops : %u\n", ctx->ipcp.fsm.nack_loops); + PR("IPCP NACKs recv : %u\n", ctx->ipcp.fsm.recv_nack_loops); + PR("IPCP current id : %d\n", ctx->ipcp.fsm.id); + PR("IPCP ACK received : %s\n", ctx->ipcp.fsm.ack_received ? + "yes" : "no"); +#endif /* CONFIG_NET_IPV4 */ + +#if defined(CONFIG_NET_IPV6) + PR("IPv6CP state : %s (%d)\n", + ppp_state_str(ctx->ipv6cp.fsm.state), ctx->ipv6cp.fsm.state); + PR("IPv6CP retransmits : %u\n", ctx->ipv6cp.fsm.retransmits); + PR("IPv6CP NACK loops : %u\n", ctx->ipv6cp.fsm.nack_loops); + PR("IPv6CP NACKs recv : %u\n", ctx->ipv6cp.fsm.recv_nack_loops); + PR("IPv6CP current id : %d\n", ctx->ipv6cp.fsm.id); + PR("IPv6CP ACK received : %s\n", ctx->ipv6cp.fsm.ack_received ? + "yes" : "no"); +#endif /* CONFIG_NET_IPV6 */ + +#if defined(CONFIG_NET_L2_PPP_PAP) + PR("PAP state : %s (%d)\n", + ppp_state_str(ctx->pap.fsm.state), ctx->pap.fsm.state); + PR("PAP retransmits : %u\n", ctx->pap.fsm.retransmits); + PR("PAP NACK loops : %u\n", ctx->pap.fsm.nack_loops); + PR("PAP NACKs recv : %u\n", ctx->pap.fsm.recv_nack_loops); + PR("PAP current id : %d\n", ctx->pap.fsm.id); + PR("PAP ACK received : %s\n", ctx->pap.fsm.ack_received ? + "yes" : "no"); +#endif /* CONFIG_NET_L2_PPP_PAP */ + +#else + PR_INFO("Set %s to enable %s support.\n", + "CONFIG_NET_L2_PPP and CONFIG_NET_PPP", "PPP"); +#endif + return 0; +} + +#if defined(CONFIG_NET_SHELL_DYN_CMD_COMPLETION) + +#define MAX_IFACE_HELP_STR_LEN sizeof("longbearername (0xabcd0123)") +#define MAX_IFACE_STR_LEN sizeof("xxx") + +#if defined(CONFIG_NET_PPP) +static char iface_ppp_help_buffer[MAX_IFACE_COUNT][MAX_IFACE_HELP_STR_LEN]; +static char iface_ppp_index_buffer[MAX_IFACE_COUNT][MAX_IFACE_STR_LEN]; + +static char *set_iface_ppp_index_buffer(size_t idx) +{ + struct net_if *iface = net_if_get_by_index(idx); + + /* Network interfaces start at 1 */ + if (idx == 0) { + return ""; + } + + if (!iface) { + return NULL; + } + + if (net_if_l2(iface) != &NET_L2_GET_NAME(PPP)) { + return NULL; + } + + snprintk(iface_ppp_index_buffer[idx], MAX_IFACE_STR_LEN, "%d", (uint8_t)idx); + + return iface_ppp_index_buffer[idx]; +} + +static char *set_iface_ppp_index_help(size_t idx) +{ + struct net_if *iface = net_if_get_by_index(idx); + + /* Network interfaces start at 1 */ + if (idx == 0) { + return ""; + } + + if (!iface) { + return NULL; + } + + if (net_if_l2(iface) != &NET_L2_GET_NAME(PPP)) { + return NULL; + } + +#if defined(CONFIG_NET_INTERFACE_NAME) + char name[CONFIG_NET_INTERFACE_NAME_LEN + 1]; + + net_if_get_name(iface, name, CONFIG_NET_INTERFACE_NAME_LEN); + name[CONFIG_NET_INTERFACE_NAME_LEN] = '\0'; + + snprintk(iface_ppp_help_buffer[idx], MAX_IFACE_HELP_STR_LEN, + "%s [%s] (%p)", name, iface2str(iface, NULL), iface); +#else + snprintk(iface_ppp_help_buffer[idx], MAX_IFACE_HELP_STR_LEN, + "%s (%p)", iface2str(iface, NULL), iface); +#endif + + return iface_ppp_help_buffer[idx]; +} + +static void iface_ppp_index_get(size_t idx, struct shell_static_entry *entry); + +SHELL_DYNAMIC_CMD_CREATE(iface_ppp_index, iface_ppp_index_get); + +static void iface_ppp_index_get(size_t idx, struct shell_static_entry *entry) +{ + entry->handler = NULL; + entry->help = set_iface_ppp_index_help(idx); + entry->subcmd = &iface_ppp_index; + entry->syntax = set_iface_ppp_index_buffer(idx); +} + +#define IFACE_PPP_DYN_CMD &iface_ppp_index +#else +#define IFACE_PPP_DYN_CMD NULL +#endif /* CONFIG_NET_PPP */ + +#else +#define IFACE_PPP_DYN_CMD NULL +#endif /* CONFIG_NET_SHELL_DYN_CMD_COMPLETION */ + +SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_ppp, + SHELL_CMD(ping, IFACE_PPP_DYN_CMD, + "'net ppp ping ' sends Echo-request to PPP interface.", + cmd_net_ppp_ping), + SHELL_CMD(status, NULL, + "'net ppp status' prints information about PPP.", + cmd_net_ppp_status), + SHELL_SUBCMD_SET_END +); + +SHELL_SUBCMD_ADD((net), ppp, &net_cmd_ppp, + "PPP information.", + cmd_net_ppp_status, 1, 0); diff --git a/subsys/net/lib/shell/resume.c b/subsys/net/lib/shell/resume.c new file mode 100644 index 00000000000..dcd3fbf309d --- /dev/null +++ b/subsys/net/lib/shell/resume.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +LOG_MODULE_DECLARE(net_shell); + +#include "net_shell_private.h" + +static int cmd_net_resume(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_POWER_MANAGEMENT) + if (argv[1]) { + struct net_if *iface = NULL; + const struct device *dev; + int idx; + int ret; + + idx = get_iface_idx(sh, argv[1]); + if (idx < 0) { + return -ENOEXEC; + } + + iface = net_if_get_by_index(idx); + if (!iface) { + PR_WARNING("No such interface in index %d\n", idx); + return -ENOEXEC; + } + + dev = net_if_get_device(iface); + + ret = pm_device_action_run(dev, PM_DEVICE_ACTION_RESUME); + if (ret != 0) { + PR_INFO("Iface could not be resumed\n"); + } + + } else { + PR("Usage:\n"); + PR("\tresume \n"); + } +#else + PR_INFO("You need a network driver supporting Power Management.\n"); +#endif /* CONFIG_NET_POWER_MANAGEMENT */ + + return 0; +} + +SHELL_SUBCMD_ADD((net), resume, NULL, + "Resume a network interface", + cmd_net_resume, 1, 0); diff --git a/subsys/net/lib/shell/route.c b/subsys/net/lib/shell/route.c new file mode 100644 index 00000000000..035b56f6dfc --- /dev/null +++ b/subsys/net/lib/shell/route.c @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#include "net_shell_private.h" + +#include "../ip/route.h" + +#if defined(CONFIG_NET_ROUTE) && defined(CONFIG_NET_NATIVE) +static void route_cb(struct net_route_entry *entry, void *user_data) +{ + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + struct net_if *iface = data->user_data; + struct net_route_nexthop *nexthop_route; + int count; + uint32_t now = k_uptime_get_32(); + + if (entry->iface != iface) { + return; + } + + PR("IPv6 prefix : %s/%d\n", net_sprint_ipv6_addr(&entry->addr), + entry->prefix_len); + + count = 0; + + SYS_SLIST_FOR_EACH_CONTAINER(&entry->nexthop, nexthop_route, node) { + struct net_linkaddr_storage *lladdr; + char remaining_str[sizeof("01234567890 sec")]; + uint32_t remaining; + + if (!nexthop_route->nbr) { + continue; + } + + PR("\tneighbor : %p\t", nexthop_route->nbr); + + if (nexthop_route->nbr->idx == NET_NBR_LLADDR_UNKNOWN) { + PR("addr : \t"); + } else { + lladdr = net_nbr_get_lladdr(nexthop_route->nbr->idx); + + PR("addr : %s\t", net_sprint_ll_addr(lladdr->addr, + lladdr->len)); + } + + if (entry->is_infinite) { + snprintk(remaining_str, sizeof(remaining_str) - 1, + "infinite"); + } else { + remaining = net_timeout_remaining(&entry->lifetime, now); + snprintk(remaining_str, sizeof(remaining_str) - 1, + "%u sec", remaining); + } + + PR("lifetime : %s\n", remaining_str); + + count++; + } + + if (count == 0) { + PR("\t\n"); + } +} + +static void iface_per_route_cb(struct net_if *iface, void *user_data) +{ + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + const char *extra; + + PR("\nIPv6 routes for interface %d (%p) (%s)\n", + net_if_get_by_iface(iface), iface, + iface2str(iface, &extra)); + PR("=========================================%s\n", extra); + + data->user_data = iface; + + net_route_foreach(route_cb, data); +} +#endif /* CONFIG_NET_ROUTE */ + +#if defined(CONFIG_NET_ROUTE_MCAST) && defined(CONFIG_NET_NATIVE) +static void route_mcast_cb(struct net_route_entry_mcast *entry, + void *user_data) +{ + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + struct net_if *iface = data->user_data; + const char *extra; + + if (entry->iface != iface) { + return; + } + + PR("IPv6 multicast route %p for interface %d (%p) (%s)\n", entry, + net_if_get_by_iface(iface), iface, iface2str(iface, &extra)); + PR("===========================================================" + "%s\n", extra); + + PR("IPv6 group : %s\n", net_sprint_ipv6_addr(&entry->group)); + PR("IPv6 group len : %d\n", entry->prefix_len); + PR("Lifetime : %u\n", entry->lifetime); +} + +static void iface_per_mcast_route_cb(struct net_if *iface, void *user_data) +{ + struct net_shell_user_data *data = user_data; + + data->user_data = iface; + + net_route_mcast_foreach(route_mcast_cb, NULL, data); +} +#endif /* CONFIG_NET_ROUTE_MCAST */ + +static int cmd_net_ip6_route_add(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_NATIVE_IPV6) && (CONFIG_NET_ROUTE) + struct net_if *iface = NULL; + int idx; + struct net_route_entry *route; + struct in6_addr gw = {0}; + struct in6_addr prefix = {0}; + + if (argc != 4) { + PR_ERROR("Correct usage: net route add " + " \n"); + return -EINVAL; + } + + idx = get_iface_idx(sh, argv[1]); + if (idx < 0) { + return -ENOEXEC; + } + + iface = net_if_get_by_index(idx); + if (!iface) { + PR_WARNING("No such interface in index %d\n", idx); + return -ENOEXEC; + } + + if (net_addr_pton(AF_INET6, argv[2], &prefix)) { + PR_ERROR("Invalid address: %s\n", argv[2]); + return -EINVAL; + } + + if (net_addr_pton(AF_INET6, argv[3], &gw)) { + PR_ERROR("Invalid gateway: %s\n", argv[3]); + return -EINVAL; + } + + route = net_route_add(iface, &prefix, NET_IPV6_DEFAULT_PREFIX_LEN, + &gw, NET_IPV6_ND_INFINITE_LIFETIME, + NET_ROUTE_PREFERENCE_MEDIUM); + if (route == NULL) { + PR_ERROR("Failed to add route\n"); + return -ENOEXEC; + } + +#else /* CONFIG_NET_NATIVE_IPV6 && CONFIG_NET_ROUTE */ + PR_INFO("Set %s and %s to enable native %s support." + " And enable CONFIG_NET_ROUTE.\n", + "CONFIG_NET_NATIVE", "CONFIG_NET_IPV6", "IPv6"); +#endif /* CONFIG_NET_NATIVE_IPV6 && CONFIG_NET_ROUTE */ + return 0; +} + +static int cmd_net_ip6_route_del(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_NATIVE_IPV6) && (CONFIG_NET_ROUTE) + struct net_if *iface = NULL; + int idx; + struct net_route_entry *route; + struct in6_addr prefix = { 0 }; + + if (argc != 3) { + PR_ERROR("Correct usage: net route del \n"); + return -EINVAL; + } + idx = get_iface_idx(sh, argv[1]); + if (idx < 0) { + return -ENOEXEC; + } + + iface = net_if_get_by_index(idx); + if (!iface) { + PR_WARNING("No such interface in index %d\n", idx); + return -ENOEXEC; + } + + if (net_addr_pton(AF_INET6, argv[2], &prefix)) { + PR_ERROR("Invalid address: %s\n", argv[2]); + return -EINVAL; + } + + route = net_route_lookup(iface, &prefix); + if (route) { + net_route_del(route); + } +#else /* CONFIG_NET_NATIVE_IPV6 && CONFIG_NET_ROUTE */ + PR_INFO("Set %s and %s to enable native %s support." + " And enable CONFIG_NET_ROUTE\n", + "CONFIG_NET_NATIVE", "CONFIG_NET_IPV6", "IPv6"); +#endif /* CONFIG_NET_NATIVE_IPV6 && CONFIG_NET_ROUTE */ + return 0; +} + +static int cmd_net_route(const struct shell *sh, size_t argc, char *argv[]) +{ + ARG_UNUSED(argc); + ARG_UNUSED(argv); + +#if defined(CONFIG_NET_NATIVE) +#if defined(CONFIG_NET_ROUTE) || defined(CONFIG_NET_ROUTE_MCAST) + struct net_shell_user_data user_data; +#endif + +#if defined(CONFIG_NET_ROUTE) || defined(CONFIG_NET_ROUTE_MCAST) + user_data.sh = sh; +#endif + +#if defined(CONFIG_NET_ROUTE) + net_if_foreach(iface_per_route_cb, &user_data); +#else + PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_ROUTE", + "network route"); +#endif + +#if defined(CONFIG_NET_ROUTE_MCAST) + net_if_foreach(iface_per_mcast_route_cb, &user_data); +#endif +#endif + return 0; +} + +SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_route, + SHELL_CMD(add, NULL, + "'net route add '" + " adds the route to the destination.", + cmd_net_ip6_route_add), + SHELL_CMD(del, NULL, + "'net route del '" + " deletes the route to the destination.", + cmd_net_ip6_route_del), + SHELL_SUBCMD_SET_END +); + +SHELL_SUBCMD_ADD((net), route, &net_cmd_route, + "Show network route.", + cmd_net_route, 1, 0); diff --git a/subsys/net/lib/shell/sockets.c b/subsys/net/lib/shell/sockets.c new file mode 100644 index 00000000000..8be67fc5faf --- /dev/null +++ b/subsys/net/lib/shell/sockets.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#include "net_shell_private.h" +#include + +#if defined(CONFIG_NET_SOCKETS_OBJ_CORE) +struct socket_info { + int opened; + int closed; +}; + +int walk_sockets(struct k_obj_core *obj_core, void *user_data) +{ +#if defined(CONFIG_THREAD_NAME) +#define THREAD_NAME_LEN CONFIG_THREAD_MAX_NAME_LEN +#else +#define THREAD_NAME_LEN 16 +#endif + struct sock_obj_type_raw_stats stats = { 0 }; + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + struct socket_info *count = data->user_data; + char thread_name[THREAD_NAME_LEN + 1]; + char fd[5] = { 0 }; + struct sock_obj *obj; + int lifetime; + int ret; + + obj = CONTAINER_OF(obj_core, struct sock_obj, obj_core); + + if (k_thread_name_copy(obj->creator, thread_name, + sizeof(thread_name) - 1) < 0) { + snprintk(thread_name, sizeof(thread_name) - 1, "%p", + obj->creator); + } + + thread_name[sizeof(thread_name) - 1] = '\0'; + + ret = k_obj_core_stats_raw(K_OBJ_CORE(obj), + &stats, sizeof(stats)); + if (ret != 0) { + PR_INFO("Failed to get statistics (%d)\n", ret); + } + + if (obj->fd < 0) { + /* Already closed socket. The create time contains the + * actual lifetime as calculated in close() + */ + lifetime = obj->create_time; + strncat(fd, "C", 1); + count->closed++; + } else { + lifetime = k_ticks_to_ms_ceil32(sys_clock_tick_get() - + obj->create_time); + snprintk(fd, sizeof(fd), "%d", obj->fd); + count->opened++; + } + + PR("%16s %-12s %c%c%c\t%-5s%-13d %-10" PRId64 "%-10" PRId64 "\n", + thread_name, obj->reg->name, + obj->socket_family == AF_INET6 ? '6' : + (obj->socket_family ? '4' : ' '), + obj->socket_type == SOCK_DGRAM ? 'D' : + (obj->socket_type == SOCK_STREAM ? 'S' : + (obj->socket_type == SOCK_RAW ? 'R' : ' ')), + obj->socket_proto == IPPROTO_UDP ? 'U' : + (obj->socket_proto == IPPROTO_TCP ? 'T' : ' '), + fd, lifetime, stats.sent, stats.received); + + return 0; +} +#endif /* CONFIG_NET_SOCKETS_OBJ_CORE */ + +static int cmd_net_sockets(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_SOCKETS_OBJ_CORE) + struct net_shell_user_data user_data; + struct k_obj_type *obj_type; + struct socket_info count = { 0 }; + + user_data.sh = sh; + user_data.user_data = &count; + + PR("%16s %-12s %-5s\t%-5s%-14s %-10s%-10s\n", + "Creator", "Name", "Flags", "FD", "Lifetime (ms)", "Sent", + "Received"); + PR("\n"); + + obj_type = k_obj_type_find(K_OBJ_TYPE_SOCK); + k_obj_type_walk_unlocked(obj_type, walk_sockets, (void *)&user_data); + + if (count.opened == 0 && count.closed == 0) { + PR("No sockets found.\n"); + } else { + if (count.opened > 0) { + PR("\n%d active socket%s found.\n", count.opened, + count.opened == 1 ? "" : "s"); + } + + if (count.closed > 0) { + if (count.opened == 0) { + PR("\n"); + } + + PR("%d closed socket%s found.\n", count.closed, + count.closed == 1 ? "" : "s"); + } + } +#else + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + PR_INFO("Set %s to enable %s support.\n", + "CONFIG_OBJ_CORE and CONFIG_NET_SOCKETS_OBJ_CORE", + "socket information"); +#endif + + return 0; +} + +SHELL_SUBCMD_ADD((net), sockets, NULL, + "Show network sockets.", + cmd_net_sockets, 1, 0); diff --git a/subsys/net/lib/shell/stats.c b/subsys/net/lib/shell/stats.c new file mode 100644 index 00000000000..666a98e35d7 --- /dev/null +++ b/subsys/net/lib/shell/stats.c @@ -0,0 +1,659 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#include + +#include "net_shell_private.h" + +#include "../ip/net_stats.h" + +#if defined(CONFIG_NET_STATISTICS) + +#if NET_TC_COUNT > 1 +static const char *priority2str(enum net_priority priority) +{ + switch (priority) { + case NET_PRIORITY_BK: + return "BK"; /* Background */ + case NET_PRIORITY_BE: + return "BE"; /* Best effort */ + case NET_PRIORITY_EE: + return "EE"; /* Excellent effort */ + case NET_PRIORITY_CA: + return "CA"; /* Critical applications */ + case NET_PRIORITY_VI: + return "VI"; /* Video, < 100 ms latency and jitter */ + case NET_PRIORITY_VO: + return "VO"; /* Voice, < 10 ms latency and jitter */ + case NET_PRIORITY_IC: + return "IC"; /* Internetwork control */ + case NET_PRIORITY_NC: + return "NC"; /* Network control */ + } + + return "??"; +} +#endif + +#if defined(CONFIG_NET_STATISTICS_ETHERNET) && \ + defined(CONFIG_NET_STATISTICS_USER_API) +static void print_eth_stats(struct net_if *iface, struct net_stats_eth *data, + const struct shell *sh) +{ + PR("Statistics for Ethernet interface %p [%d]\n", iface, + net_if_get_by_iface(iface)); + + PR("Bytes received : %u\n", data->bytes.received); + PR("Bytes sent : %u\n", data->bytes.sent); + PR("Packets received : %u\n", data->pkts.rx); + PR("Packets sent : %u\n", data->pkts.tx); + PR("Bcast received : %u\n", data->broadcast.rx); + PR("Bcast sent : %u\n", data->broadcast.tx); + PR("Mcast received : %u\n", data->multicast.rx); + PR("Mcast sent : %u\n", data->multicast.tx); + + PR("Send errors : %u\n", data->errors.tx); + PR("Receive errors : %u\n", data->errors.rx); + PR("Collisions : %u\n", data->collisions); + PR("Send Drops : %u\n", data->tx_dropped); + PR("Send timeouts : %u\n", data->tx_timeout_count); + PR("Send restarts : %u\n", data->tx_restart_queue); + PR("Unknown protocol : %u\n", data->unknown_protocol); + +#if defined(CONFIG_NET_STATISTICS_ETHERNET_VENDOR) + if (data->vendor) { + PR("Vendor specific statistics for Ethernet " + "interface %p [%d]:\n", + iface, net_if_get_by_iface(iface)); + size_t i = 0; + + do { + PR("%s : %u\n", data->vendor[i].key, + data->vendor[i].value); + i++; + } while (data->vendor[i].key); + } +#endif /* CONFIG_NET_STATISTICS_ETHERNET_VENDOR */ +} +#endif /* CONFIG_NET_STATISTICS_ETHERNET && CONFIG_NET_STATISTICS_USER_API */ + +#if defined(CONFIG_NET_STATISTICS_PPP) && \ + defined(CONFIG_NET_STATISTICS_USER_API) +static void print_ppp_stats(struct net_if *iface, struct net_stats_ppp *data, + const struct shell *sh) +{ + PR("Frames recv %u\n", data->pkts.rx); + PR("Frames sent %u\n", data->pkts.tx); + PR("Frames dropped %u\n", data->drop); + PR("Bad FCS %u\n", data->chkerr); +} +#endif /* CONFIG_NET_STATISTICS_PPP && CONFIG_NET_STATISTICS_USER_API */ + +#if !defined(CONFIG_NET_NATIVE) +#define GET_STAT(a, b) 0 +#endif + +#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) || \ + defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) +#if (NET_TC_TX_COUNT > 1) || (NET_TC_RX_COUNT > 1) +static char *get_net_pkt_tc_stats_detail(struct net_if *iface, int i, + bool is_tx) +{ + static char extra_stats[sizeof("\t[0=xxxx us]") + + sizeof("->xxxx") * + NET_PKT_DETAIL_STATS_COUNT]; + int j, total = 0, pos = 0; + + pos += snprintk(extra_stats, sizeof(extra_stats), "\t[0"); + + for (j = 0; j < NET_PKT_DETAIL_STATS_COUNT; j++) { + net_stats_t count = 0; + uint32_t avg; + + if (is_tx) { +#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) && (NET_TC_TX_COUNT > 1) + count = GET_STAT(iface, + tc.sent[i].tx_time_detail[j].count); +#endif + } else { +#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) && (NET_TC_RX_COUNT > 1) + count = GET_STAT(iface, + tc.recv[i].rx_time_detail[j].count); +#endif + } + + if (count == 0) { + break; + } + + if (is_tx) { +#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) && (NET_TC_TX_COUNT > 1) + avg = (uint32_t)(GET_STAT(iface, + tc.sent[i].tx_time_detail[j].sum) / + (uint64_t)count); +#endif + } else { +#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) && (NET_TC_RX_COUNT > 1) + avg = (uint32_t)(GET_STAT(iface, + tc.recv[i].rx_time_detail[j].sum) / + (uint64_t)count); +#endif + } + + if (avg == 0) { + continue; + } + + total += avg; + + pos += snprintk(extra_stats + pos, sizeof(extra_stats) - pos, + "->%u", avg); + } + + if (total == 0U) { + return "\0"; + } + + pos += snprintk(extra_stats + pos, sizeof(extra_stats) - pos, + "=%u us]", total); + + return extra_stats; +} +#endif /* (NET_TC_TX_COUNT > 1) || (NET_TC_RX_COUNT > 1) */ + +#if (NET_TC_TX_COUNT <= 1) || (NET_TC_RX_COUNT <= 1) +static char *get_net_pkt_stats_detail(struct net_if *iface, bool is_tx) +{ + static char extra_stats[sizeof("\t[0=xxxx us]") + sizeof("->xxxx") * + NET_PKT_DETAIL_STATS_COUNT]; + int j, total = 0, pos = 0; + + pos += snprintk(extra_stats, sizeof(extra_stats), "\t[0"); + + for (j = 0; j < NET_PKT_DETAIL_STATS_COUNT; j++) { + net_stats_t count; + uint32_t avg; + + if (is_tx) { +#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) + count = GET_STAT(iface, tx_time_detail[j].count); +#endif + } else { +#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) + count = GET_STAT(iface, rx_time_detail[j].count); +#endif + } + + if (count == 0) { + break; + } + + if (is_tx) { +#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) + avg = (uint32_t)(GET_STAT(iface, + tx_time_detail[j].sum) / + (uint64_t)count); +#endif + } else { +#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) + avg = (uint32_t)(GET_STAT(iface, + rx_time_detail[j].sum) / + (uint64_t)count); +#endif + } + + if (avg == 0) { + continue; + } + + total += avg; + + pos += snprintk(extra_stats + pos, + sizeof(extra_stats) - pos, + "->%u", avg); + } + + if (total == 0U) { + return "\0"; + } + + pos += snprintk(extra_stats + pos, sizeof(extra_stats) - pos, + "=%u us]", total); + + return extra_stats; +} +#endif /* (NET_TC_TX_COUNT == 1) || (NET_TC_RX_COUNT == 1) */ + +#else /* CONFIG_NET_PKT_TXTIME_STATS_DETAIL || CONFIG_NET_PKT_RXTIME_STATS_DETAIL */ + +#if defined(CONFIG_NET_PKT_TXTIME_STATS) || \ + defined(CONFIG_NET_PKT_RXTIME_STATS) + +#if (NET_TC_TX_COUNT > 1) || (NET_TC_RX_COUNT > 1) +static char *get_net_pkt_tc_stats_detail(struct net_if *iface, int i, + bool is_tx) +{ + ARG_UNUSED(iface); + ARG_UNUSED(i); + ARG_UNUSED(is_tx); + + return "\0"; +} +#endif + +#if (NET_TC_TX_COUNT == 1) || (NET_TC_RX_COUNT == 1) +static char *get_net_pkt_stats_detail(struct net_if *iface, bool is_tx) +{ + ARG_UNUSED(iface); + ARG_UNUSED(is_tx); + + return "\0"; +} +#endif +#endif /* CONFIG_NET_PKT_TXTIME_STATS) || CONFIG_NET_PKT_RXTIME_STATS */ +#endif /* CONFIG_NET_PKT_TXTIME_STATS_DETAIL || CONFIG_NET_PKT_RXTIME_STATS_DETAIL */ + +static void print_tc_tx_stats(const struct shell *sh, struct net_if *iface) +{ +#if NET_TC_TX_COUNT > 1 + int i; + + PR("TX traffic class statistics:\n"); + +#if defined(CONFIG_NET_PKT_TXTIME_STATS) + PR("TC Priority\tSent pkts\tbytes\ttime\n"); + + for (i = 0; i < NET_TC_TX_COUNT; i++) { + net_stats_t count = GET_STAT(iface, + tc.sent[i].tx_time.count); + if (count == 0) { + PR("[%d] %s (%d)\t%d\t\t%d\t-\n", i, + priority2str(GET_STAT(iface, tc.sent[i].priority)), + GET_STAT(iface, tc.sent[i].priority), + GET_STAT(iface, tc.sent[i].pkts), + GET_STAT(iface, tc.sent[i].bytes)); + } else { + PR("[%d] %s (%d)\t%d\t\t%d\t%u us%s\n", i, + priority2str(GET_STAT(iface, tc.sent[i].priority)), + GET_STAT(iface, tc.sent[i].priority), + GET_STAT(iface, tc.sent[i].pkts), + GET_STAT(iface, tc.sent[i].bytes), + (uint32_t)(GET_STAT(iface, + tc.sent[i].tx_time.sum) / + (uint64_t)count), + get_net_pkt_tc_stats_detail(iface, i, true)); + } + } +#else + PR("TC Priority\tSent pkts\tbytes\n"); + + for (i = 0; i < NET_TC_TX_COUNT; i++) { + PR("[%d] %s (%d)\t%d\t\t%d\n", i, + priority2str(GET_STAT(iface, tc.sent[i].priority)), + GET_STAT(iface, tc.sent[i].priority), + GET_STAT(iface, tc.sent[i].pkts), + GET_STAT(iface, tc.sent[i].bytes)); + } +#endif /* CONFIG_NET_PKT_TXTIME_STATS */ +#else + ARG_UNUSED(sh); + +#if defined(CONFIG_NET_PKT_TXTIME_STATS) + net_stats_t count = GET_STAT(iface, tx_time.count); + + if (count != 0) { + PR("Avg %s net_pkt (%u) time %" PRIu32 " us%s\n", "TX", count, + (uint32_t)(GET_STAT(iface, tx_time.sum) / (uint64_t)count), + get_net_pkt_stats_detail(iface, true)); + } +#else + ARG_UNUSED(iface); +#endif /* CONFIG_NET_PKT_TXTIME_STATS */ +#endif /* NET_TC_TX_COUNT > 1 */ +} + +static void print_tc_rx_stats(const struct shell *sh, struct net_if *iface) +{ +#if NET_TC_RX_COUNT > 1 + int i; + + PR("RX traffic class statistics:\n"); + +#if defined(CONFIG_NET_PKT_RXTIME_STATS) + PR("TC Priority\tRecv pkts\tbytes\ttime\n"); + + for (i = 0; i < NET_TC_RX_COUNT; i++) { + net_stats_t count = GET_STAT(iface, + tc.recv[i].rx_time.count); + if (count == 0) { + PR("[%d] %s (%d)\t%d\t\t%d\t-\n", i, + priority2str(GET_STAT(iface, tc.recv[i].priority)), + GET_STAT(iface, tc.recv[i].priority), + GET_STAT(iface, tc.recv[i].pkts), + GET_STAT(iface, tc.recv[i].bytes)); + } else { + PR("[%d] %s (%d)\t%d\t\t%d\t%u us%s\n", i, + priority2str(GET_STAT(iface, tc.recv[i].priority)), + GET_STAT(iface, tc.recv[i].priority), + GET_STAT(iface, tc.recv[i].pkts), + GET_STAT(iface, tc.recv[i].bytes), + (uint32_t)(GET_STAT(iface, + tc.recv[i].rx_time.sum) / + (uint64_t)count), + get_net_pkt_tc_stats_detail(iface, i, false)); + } + } +#else + PR("TC Priority\tRecv pkts\tbytes\n"); + + for (i = 0; i < NET_TC_RX_COUNT; i++) { + PR("[%d] %s (%d)\t%d\t\t%d\n", i, + priority2str(GET_STAT(iface, tc.recv[i].priority)), + GET_STAT(iface, tc.recv[i].priority), + GET_STAT(iface, tc.recv[i].pkts), + GET_STAT(iface, tc.recv[i].bytes)); + } +#endif /* CONFIG_NET_PKT_RXTIME_STATS */ +#else + ARG_UNUSED(sh); + +#if defined(CONFIG_NET_PKT_RXTIME_STATS) + net_stats_t count = GET_STAT(iface, rx_time.count); + + if (count != 0) { + PR("Avg %s net_pkt (%u) time %" PRIu32 " us%s\n", "RX", count, + (uint32_t)(GET_STAT(iface, rx_time.sum) / (uint64_t)count), + get_net_pkt_stats_detail(iface, false)); + } +#else + ARG_UNUSED(iface); +#endif /* CONFIG_NET_PKT_RXTIME_STATS */ + +#endif /* NET_TC_RX_COUNT > 1 */ +} + +static void print_net_pm_stats(const struct shell *sh, struct net_if *iface) +{ +#if defined(CONFIG_NET_STATISTICS_POWER_MANAGEMENT) + PR("PM suspend stats:\n"); + PR("\tLast time : %u ms\n", + GET_STAT(iface, pm.last_suspend_time)); + PR("\tAverage time : %u ms\n", + (uint32_t)(GET_STAT(iface, pm.overall_suspend_time) / + GET_STAT(iface, pm.suspend_count))); + PR("\tTotal time : %" PRIu64 " ms\n", + GET_STAT(iface, pm.overall_suspend_time)); + PR("\tHow many times: %u\n", + GET_STAT(iface, pm.suspend_count)); +#else + ARG_UNUSED(sh); + ARG_UNUSED(iface); +#endif +} + +static void net_shell_print_statistics(struct net_if *iface, void *user_data) +{ + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + + if (iface) { + const char *extra; + + PR("\nInterface %p (%s) [%d]\n", iface, + iface2str(iface, &extra), net_if_get_by_iface(iface)); + PR("===========================%s\n", extra); + } else { + PR("\nGlobal statistics\n"); + PR("=================\n"); + } + +#if defined(CONFIG_NET_STATISTICS_IPV6) && defined(CONFIG_NET_NATIVE_IPV6) + PR("IPv6 recv %d\tsent\t%d\tdrop\t%d\tforwarded\t%d\n", + GET_STAT(iface, ipv6.recv), + GET_STAT(iface, ipv6.sent), + GET_STAT(iface, ipv6.drop), + GET_STAT(iface, ipv6.forwarded)); +#if defined(CONFIG_NET_STATISTICS_IPV6_ND) + PR("IPv6 ND recv %d\tsent\t%d\tdrop\t%d\n", + GET_STAT(iface, ipv6_nd.recv), + GET_STAT(iface, ipv6_nd.sent), + GET_STAT(iface, ipv6_nd.drop)); +#endif /* CONFIG_NET_STATISTICS_IPV6_ND */ +#if defined(CONFIG_NET_STATISTICS_MLD) + PR("IPv6 MLD recv %d\tsent\t%d\tdrop\t%d\n", + GET_STAT(iface, ipv6_mld.recv), + GET_STAT(iface, ipv6_mld.sent), + GET_STAT(iface, ipv6_mld.drop)); +#endif /* CONFIG_NET_STATISTICS_MLD */ +#endif /* CONFIG_NET_STATISTICS_IPV6 */ + +#if defined(CONFIG_NET_STATISTICS_IPV4) && defined(CONFIG_NET_NATIVE_IPV4) + PR("IPv4 recv %d\tsent\t%d\tdrop\t%d\tforwarded\t%d\n", + GET_STAT(iface, ipv4.recv), + GET_STAT(iface, ipv4.sent), + GET_STAT(iface, ipv4.drop), + GET_STAT(iface, ipv4.forwarded)); +#endif /* CONFIG_NET_STATISTICS_IPV4 */ + + PR("IP vhlerr %d\thblener\t%d\tlblener\t%d\n", + GET_STAT(iface, ip_errors.vhlerr), + GET_STAT(iface, ip_errors.hblenerr), + GET_STAT(iface, ip_errors.lblenerr)); + PR("IP fragerr %d\tchkerr\t%d\tprotoer\t%d\n", + GET_STAT(iface, ip_errors.fragerr), + GET_STAT(iface, ip_errors.chkerr), + GET_STAT(iface, ip_errors.protoerr)); + +#if defined(CONFIG_NET_STATISTICS_ICMP) && defined(CONFIG_NET_NATIVE_IPV4) + PR("ICMP recv %d\tsent\t%d\tdrop\t%d\n", + GET_STAT(iface, icmp.recv), + GET_STAT(iface, icmp.sent), + GET_STAT(iface, icmp.drop)); + PR("ICMP typeer %d\tchkerr\t%d\n", + GET_STAT(iface, icmp.typeerr), + GET_STAT(iface, icmp.chkerr)); +#endif +#if defined(CONFIG_NET_STATISTICS_IGMP) + PR("IGMP recv %d\tsent\t%d\tdrop\t%d\n", + GET_STAT(iface, ipv4_igmp.recv), + GET_STAT(iface, ipv4_igmp.sent), + GET_STAT(iface, ipv4_igmp.drop)); +#endif /* CONFIG_NET_STATISTICS_IGMP */ +#if defined(CONFIG_NET_STATISTICS_UDP) && defined(CONFIG_NET_NATIVE_UDP) + PR("UDP recv %d\tsent\t%d\tdrop\t%d\n", + GET_STAT(iface, udp.recv), + GET_STAT(iface, udp.sent), + GET_STAT(iface, udp.drop)); + PR("UDP chkerr %d\n", + GET_STAT(iface, udp.chkerr)); +#endif + +#if defined(CONFIG_NET_STATISTICS_TCP) && defined(CONFIG_NET_NATIVE_TCP) + PR("TCP bytes recv %u\tsent\t%d\tresent\t%d\n", + GET_STAT(iface, tcp.bytes.received), + GET_STAT(iface, tcp.bytes.sent), + GET_STAT(iface, tcp.resent)); + PR("TCP seg recv %d\tsent\t%d\tdrop\t%d\n", + GET_STAT(iface, tcp.recv), + GET_STAT(iface, tcp.sent), + GET_STAT(iface, tcp.seg_drop)); + PR("TCP seg resent %d\tchkerr\t%d\tackerr\t%d\n", + GET_STAT(iface, tcp.rexmit), + GET_STAT(iface, tcp.chkerr), + GET_STAT(iface, tcp.ackerr)); + PR("TCP seg rsterr %d\trst\t%d\n", + GET_STAT(iface, tcp.rsterr), + GET_STAT(iface, tcp.rst)); + PR("TCP conn drop %d\tconnrst\t%d\n", + GET_STAT(iface, tcp.conndrop), + GET_STAT(iface, tcp.connrst)); + PR("TCP pkt drop %d\n", GET_STAT(iface, tcp.drop)); +#endif + + PR("Bytes received %u\n", GET_STAT(iface, bytes.received)); + PR("Bytes sent %u\n", GET_STAT(iface, bytes.sent)); + PR("Processing err %d\n", GET_STAT(iface, processing_error)); + + print_tc_tx_stats(sh, iface); + print_tc_rx_stats(sh, iface); + +#if defined(CONFIG_NET_STATISTICS_ETHERNET) && \ + defined(CONFIG_NET_STATISTICS_USER_API) + if (iface && net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) { + struct net_stats_eth eth_data; + int ret; + + ret = net_mgmt(NET_REQUEST_STATS_GET_ETHERNET, iface, + ð_data, sizeof(eth_data)); + if (!ret) { + print_eth_stats(iface, ð_data, sh); + } + } +#endif /* CONFIG_NET_STATISTICS_ETHERNET && CONFIG_NET_STATISTICS_USER_API */ + +#if defined(CONFIG_NET_STATISTICS_PPP) && \ + defined(CONFIG_NET_STATISTICS_USER_API) + if (iface && net_if_l2(iface) == &NET_L2_GET_NAME(PPP)) { + struct net_stats_ppp ppp_data; + int ret; + + ret = net_mgmt(NET_REQUEST_STATS_GET_PPP, iface, + &ppp_data, sizeof(ppp_data)); + if (!ret) { + print_ppp_stats(iface, &ppp_data, sh); + } + } +#endif /* CONFIG_NET_STATISTICS_PPP && CONFIG_NET_STATISTICS_USER_API */ + + print_net_pm_stats(sh, iface); +} +#endif /* CONFIG_NET_STATISTICS */ + +#if defined(CONFIG_NET_STATISTICS_PER_INTERFACE) +static void net_shell_print_statistics_all(struct net_shell_user_data *data) +{ + net_if_foreach(net_shell_print_statistics, data); +} +#endif + +int cmd_net_stats_all(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_STATISTICS) + struct net_shell_user_data user_data; +#endif + +#if defined(CONFIG_NET_STATISTICS) + user_data.sh = sh; + + /* Print global network statistics */ + net_shell_print_statistics_all(&user_data); +#else + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_STATISTICS", + "statistics"); +#endif + + return 0; +} + +int cmd_net_stats_iface(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_STATISTICS) +#if defined(CONFIG_NET_STATISTICS_PER_INTERFACE) + struct net_shell_user_data data; + struct net_if *iface; + char *endptr; + int idx; +#endif +#endif + +#if defined(CONFIG_NET_STATISTICS) +#if defined(CONFIG_NET_STATISTICS_PER_INTERFACE) + if (argv[1] == NULL) { + PR_WARNING("Network interface index missing!\n"); + return -ENOEXEC; + } + + idx = strtol(argv[1], &endptr, 10); + if (*endptr != '\0') { + PR_WARNING("Invalid index %s\n", argv[1]); + return -ENOEXEC; + } + + iface = net_if_get_by_index(idx); + if (!iface) { + PR_WARNING("No such interface in index %d\n", idx); + return -ENOEXEC; + } + + data.sh = sh; + + net_shell_print_statistics(iface, &data); +#else + PR_INFO("Per network interface statistics not collected.\n"); + PR_INFO("Please enable CONFIG_NET_STATISTICS_PER_INTERFACE\n"); +#endif /* CONFIG_NET_STATISTICS_PER_INTERFACE */ +#else + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_STATISTICS", + "statistics"); +#endif + + return 0; +} + +static int cmd_net_stats(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_STATISTICS) + if (!argv[1]) { + cmd_net_stats_all(sh, argc, argv); + return 0; + } + + if (strcmp(argv[1], "reset") == 0) { + net_stats_reset(NULL); + } else { + cmd_net_stats_iface(sh, argc, argv); + } +#else + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_STATISTICS", + "statistics"); +#endif + + return 0; +} + +#if defined(CONFIG_NET_SHELL_DYN_CMD_COMPLETION) + +#include "iface_dynamic.h" + +#endif /* CONFIG_NET_SHELL_DYN_CMD_COMPLETION */ + +SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_stats, + SHELL_CMD(all, NULL, + "Show network statistics for all network interfaces.", + cmd_net_stats_all), + SHELL_CMD(iface, IFACE_DYN_CMD, + "'net stats ' shows network statistics for " + "one specific network interface.", + cmd_net_stats_iface), + SHELL_SUBCMD_SET_END +); + +SHELL_SUBCMD_ADD((net), stats, &net_cmd_stats, + "Show network statistics.", + cmd_net_stats, 1, 1); diff --git a/subsys/net/lib/shell/suspend.c b/subsys/net/lib/shell/suspend.c new file mode 100644 index 00000000000..cfa01375cac --- /dev/null +++ b/subsys/net/lib/shell/suspend.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +LOG_MODULE_DECLARE(net_shell); + +#include "net_shell_private.h" + +static int cmd_net_suspend(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_POWER_MANAGEMENT) + if (argv[1]) { + struct net_if *iface = NULL; + const struct device *dev; + int idx; + int ret; + + idx = get_iface_idx(sh, argv[1]); + if (idx < 0) { + return -ENOEXEC; + } + + iface = net_if_get_by_index(idx); + if (!iface) { + PR_WARNING("No such interface in index %d\n", idx); + return -ENOEXEC; + } + + dev = net_if_get_device(iface); + + ret = pm_device_action_run(dev, PM_DEVICE_ACTION_SUSPEND); + if (ret != 0) { + PR_INFO("Iface could not be suspended: "); + + if (ret == -EBUSY) { + PR_INFO("device is busy\n"); + } else if (ret == -EALREADY) { + PR_INFO("dehive is already suspended\n"); + } + } + } else { + PR("Usage:\n"); + PR("\tsuspend \n"); + } +#else + PR_INFO("You need a network driver supporting Power Management.\n"); +#endif /* CONFIG_NET_POWER_MANAGEMENT */ + + return 0; +} + +SHELL_SUBCMD_ADD((net), suspend, NULL, + "Suspend a network interface", + cmd_net_suspend, 1, 0); diff --git a/subsys/net/lib/shell/tcp.c b/subsys/net/lib/shell/tcp.c new file mode 100644 index 00000000000..e2839af36ba --- /dev/null +++ b/subsys/net/lib/shell/tcp.c @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#include + +#include "net_shell_private.h" + +#if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_NATIVE_TCP) +static struct net_context *tcp_ctx; +static const struct shell *tcp_shell; + +#define TCP_CONNECT_TIMEOUT K_SECONDS(5) /* ms */ +#define TCP_TIMEOUT K_SECONDS(2) /* ms */ + +static void tcp_connected(struct net_context *context, + int status, + void *user_data) +{ + if (status < 0) { + PR_SHELL(tcp_shell, "TCP connection failed (%d)\n", status); + } else { + PR_SHELL(tcp_shell, "TCP connected\n"); + } +} + +static void get_my_ipv6_addr(struct net_if *iface, + struct sockaddr *myaddr) +{ +#if defined(CONFIG_NET_IPV6) + const struct in6_addr *my6addr; + + my6addr = net_if_ipv6_select_src_addr(iface, + &net_sin6(myaddr)->sin6_addr); + + memcpy(&net_sin6(myaddr)->sin6_addr, my6addr, sizeof(struct in6_addr)); + + net_sin6(myaddr)->sin6_port = 0U; /* let the IP stack to select */ +#endif +} + +static void get_my_ipv4_addr(struct net_if *iface, + struct sockaddr *myaddr) +{ +#if defined(CONFIG_NET_NATIVE_IPV4) + /* Just take the first IPv4 address of an interface. */ + memcpy(&net_sin(myaddr)->sin_addr, + &iface->config.ip.ipv4->unicast[0].address.in_addr, + sizeof(struct in_addr)); + + net_sin(myaddr)->sin_port = 0U; /* let the IP stack to select */ +#endif +} + +static void print_connect_info(const struct shell *sh, + int family, + struct sockaddr *myaddr, + struct sockaddr *addr) +{ + switch (family) { + case AF_INET: + if (IS_ENABLED(CONFIG_NET_IPV4)) { + PR("Connecting from %s:%u ", + net_sprint_ipv4_addr(&net_sin(myaddr)->sin_addr), + ntohs(net_sin(myaddr)->sin_port)); + PR("to %s:%u\n", + net_sprint_ipv4_addr(&net_sin(addr)->sin_addr), + ntohs(net_sin(addr)->sin_port)); + } else { + PR_INFO("IPv4 not supported\n"); + } + + break; + + case AF_INET6: + if (IS_ENABLED(CONFIG_NET_IPV6)) { + PR("Connecting from [%s]:%u ", + net_sprint_ipv6_addr(&net_sin6(myaddr)->sin6_addr), + ntohs(net_sin6(myaddr)->sin6_port)); + PR("to [%s]:%u\n", + net_sprint_ipv6_addr(&net_sin6(addr)->sin6_addr), + ntohs(net_sin6(addr)->sin6_port)); + } else { + PR_INFO("IPv6 not supported\n"); + } + + break; + + default: + PR_WARNING("Unknown protocol family (%d)\n", family); + break; + } +} + +static void tcp_connect(const struct shell *sh, char *host, uint16_t port, + struct net_context **ctx) +{ + struct net_if *iface = net_if_get_default(); + struct sockaddr myaddr; + struct sockaddr addr; + struct net_nbr *nbr; + int addrlen; + int family; + int ret; + + if (IS_ENABLED(CONFIG_NET_IPV6) && !IS_ENABLED(CONFIG_NET_IPV4)) { + ret = net_addr_pton(AF_INET6, host, + &net_sin6(&addr)->sin6_addr); + if (ret < 0) { + PR_WARNING("Invalid IPv6 address\n"); + return; + } + + net_sin6(&addr)->sin6_port = htons(port); + addrlen = sizeof(struct sockaddr_in6); + + nbr = net_ipv6_nbr_lookup(NULL, &net_sin6(&addr)->sin6_addr); + if (nbr) { + iface = nbr->iface; + } + + get_my_ipv6_addr(iface, &myaddr); + family = addr.sa_family = myaddr.sa_family = AF_INET6; + + } else if (IS_ENABLED(CONFIG_NET_IPV4) && + !IS_ENABLED(CONFIG_NET_IPV6)) { + ARG_UNUSED(nbr); + + ret = net_addr_pton(AF_INET, host, &net_sin(&addr)->sin_addr); + if (ret < 0) { + PR_WARNING("Invalid IPv4 address\n"); + return; + } + + get_my_ipv4_addr(iface, &myaddr); + net_sin(&addr)->sin_port = htons(port); + addrlen = sizeof(struct sockaddr_in); + family = addr.sa_family = myaddr.sa_family = AF_INET; + } else if (IS_ENABLED(CONFIG_NET_IPV6) && + IS_ENABLED(CONFIG_NET_IPV4)) { + ret = net_addr_pton(AF_INET6, host, + &net_sin6(&addr)->sin6_addr); + if (ret < 0) { + ret = net_addr_pton(AF_INET, host, + &net_sin(&addr)->sin_addr); + if (ret < 0) { + PR_WARNING("Invalid IP address\n"); + return; + } + + net_sin(&addr)->sin_port = htons(port); + addrlen = sizeof(struct sockaddr_in); + + get_my_ipv4_addr(iface, &myaddr); + family = addr.sa_family = myaddr.sa_family = AF_INET; + } else { + net_sin6(&addr)->sin6_port = htons(port); + addrlen = sizeof(struct sockaddr_in6); + + nbr = net_ipv6_nbr_lookup(NULL, + &net_sin6(&addr)->sin6_addr); + if (nbr) { + iface = nbr->iface; + } + + get_my_ipv6_addr(iface, &myaddr); + family = addr.sa_family = myaddr.sa_family = AF_INET6; + } + } else { + PR_WARNING("No IPv6 nor IPv4 is enabled\n"); + return; + } + + print_connect_info(sh, family, &myaddr, &addr); + + ret = net_context_get(family, SOCK_STREAM, IPPROTO_TCP, ctx); + if (ret < 0) { + PR_WARNING("Cannot get TCP context (%d)\n", ret); + return; + } + + ret = net_context_bind(*ctx, &myaddr, addrlen); + if (ret < 0) { + PR_WARNING("Cannot bind TCP (%d)\n", ret); + return; + } + + /* Note that we cannot put shell as a user_data when connecting + * because the tcp_connected() will be called much later and + * all local stack variables are lost at that point. + */ + tcp_shell = sh; + +#if defined(CONFIG_NET_SOCKETS_CONNECT_TIMEOUT) +#define CONNECT_TIMEOUT K_MSEC(CONFIG_NET_SOCKETS_CONNECT_TIMEOUT) +#else +#define CONNECT_TIMEOUT K_SECONDS(3) +#endif + + net_context_ref(*ctx); + + ret = net_context_connect(*ctx, &addr, addrlen, tcp_connected, + CONNECT_TIMEOUT, NULL); + if (ret < 0) { + PR_WARNING("Connect failed!\n"); + net_context_put(*ctx); + tcp_ctx = NULL; + } +} + +static void tcp_sent_cb(struct net_context *context, + int status, void *user_data) +{ + PR_SHELL(tcp_shell, "Message sent\n"); +} + +static void tcp_recv_cb(struct net_context *context, struct net_pkt *pkt, + union net_ip_header *ip_hdr, + union net_proto_header *proto_hdr, + int status, void *user_data) +{ + int ret, len; + + if (pkt == NULL) { + if (!tcp_ctx || !net_context_is_used(tcp_ctx)) { + return; + } + + ret = net_context_put(tcp_ctx); + if (ret < 0) { + PR_SHELL(tcp_shell, + "Cannot close the connection (%d)\n", ret); + return; + } + + PR_SHELL(tcp_shell, "Connection closed by remote peer.\n"); + tcp_ctx = NULL; + + return; + } + + len = net_pkt_remaining_data(pkt); + + (void)net_context_update_recv_wnd(context, len); + + PR_SHELL(tcp_shell, "%zu bytes received\n", net_pkt_get_len(pkt)); + + net_pkt_unref(pkt); +} +#endif + +static int cmd_net_tcp_connect(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_NATIVE_TCP) + int arg = 0; + + /* tcp connect port */ + char *endptr; + char *ip; + uint16_t port; + + /* tcp connect port */ + if (tcp_ctx && net_context_is_used(tcp_ctx)) { + PR("Already connected\n"); + return -ENOEXEC; + } + + if (!argv[++arg]) { + PR_WARNING("Peer IP address missing.\n"); + return -ENOEXEC; + } + + ip = argv[arg]; + + if (!argv[++arg]) { + PR_WARNING("Peer port missing.\n"); + return -ENOEXEC; + } + + port = strtol(argv[arg], &endptr, 10); + if (*endptr != '\0') { + PR_WARNING("Invalid port %s\n", argv[arg]); + return -ENOEXEC; + } + + tcp_connect(sh, ip, port, &tcp_ctx); +#else + PR_INFO("Set %s to enable %s support.\n", + "CONFIG_NET_TCP and CONFIG_NET_NATIVE", "TCP"); +#endif /* CONFIG_NET_NATIVE_TCP */ + + return 0; +} + +static int cmd_net_tcp_send(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_NATIVE_TCP) + int arg = 0; + int ret; + struct net_shell_user_data user_data; + + /* tcp send */ + if (!tcp_ctx || !net_context_is_used(tcp_ctx)) { + PR_WARNING("Not connected\n"); + return -ENOEXEC; + } + + if (!argv[++arg]) { + PR_WARNING("No data to send.\n"); + return -ENOEXEC; + } + + user_data.sh = sh; + + ret = net_context_send(tcp_ctx, (uint8_t *)argv[arg], + strlen(argv[arg]), tcp_sent_cb, + TCP_TIMEOUT, &user_data); + if (ret < 0) { + PR_WARNING("Cannot send msg (%d)\n", ret); + return -ENOEXEC; + } + +#else + PR_INFO("Set %s to enable %s support.\n", + "CONFIG_NET_TCP and CONFIG_NET_NATIVE", "TCP"); +#endif /* CONFIG_NET_NATIVE_TCP */ + + return 0; +} + +static int cmd_net_tcp_recv(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_NATIVE_TCP) + int ret; + struct net_shell_user_data user_data; + + /* tcp recv */ + if (!tcp_ctx || !net_context_is_used(tcp_ctx)) { + PR_WARNING("Not connected\n"); + return -ENOEXEC; + } + + user_data.sh = sh; + + ret = net_context_recv(tcp_ctx, tcp_recv_cb, K_NO_WAIT, &user_data); + if (ret < 0) { + PR_WARNING("Cannot recv data (%d)\n", ret); + return -ENOEXEC; + } + +#else + PR_INFO("Set %s to enable %s support.\n", + "CONFIG_NET_TCP and CONFIG_NET_NATIVE", "TCP"); +#endif /* CONFIG_NET_NATIVE_TCP */ + + return 0; +} + +static int cmd_net_tcp_close(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_NATIVE_TCP) + int ret; + + /* tcp close */ + if (!tcp_ctx || !net_context_is_used(tcp_ctx)) { + PR_WARNING("Not connected\n"); + return -ENOEXEC; + } + + ret = net_context_put(tcp_ctx); + if (ret < 0) { + PR_WARNING("Cannot close the connection (%d)\n", ret); + return -ENOEXEC; + } + + PR("Connection closed.\n"); + tcp_ctx = NULL; +#else + PR_INFO("Set %s to enable %s support.\n", + "CONFIG_NET_TCP and CONFIG_NET_NATIVE", "TCP"); +#endif /* CONFIG_NET_TCP */ + + return 0; +} + +static int cmd_net_tcp(const struct shell *sh, size_t argc, char *argv[]) +{ + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + return 0; +} + +SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_tcp, + SHELL_CMD(connect, NULL, + "'net tcp connect
    ' connects to TCP peer.", + cmd_net_tcp_connect), + SHELL_CMD(send, NULL, + "'net tcp send ' sends data to peer using TCP.", + cmd_net_tcp_send), + SHELL_CMD(recv, NULL, + "'net tcp recv' receives data using TCP.", + cmd_net_tcp_recv), + SHELL_CMD(close, NULL, + "'net tcp close' closes TCP connection.", cmd_net_tcp_close), + SHELL_SUBCMD_SET_END +); + +SHELL_SUBCMD_ADD((net), tcp, &net_cmd_tcp, + "Connect/send/close TCP connection.", + cmd_net_tcp, 1, 0); diff --git a/subsys/net/lib/shell/udp.c b/subsys/net/lib/shell/udp.c new file mode 100644 index 00000000000..7bccbf93ba3 --- /dev/null +++ b/subsys/net/lib/shell/udp.c @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#include + +#include "net_shell_private.h" + +#if defined(CONFIG_NET_UDP) && defined(CONFIG_NET_NATIVE_UDP) +static struct net_context *udp_ctx; +static const struct shell *udp_shell; +K_SEM_DEFINE(udp_send_wait, 0, 1); + +static void udp_rcvd(struct net_context *context, struct net_pkt *pkt, + union net_ip_header *ip_hdr, + union net_proto_header *proto_hdr, int status, + void *user_data) +{ + if (pkt) { + size_t len = net_pkt_remaining_data(pkt); + uint8_t byte; + + PR_SHELL(udp_shell, "Received UDP packet: "); + for (size_t i = 0; i < len; ++i) { + net_pkt_read_u8(pkt, &byte); + PR_SHELL(udp_shell, "%02x ", byte); + } + PR_SHELL(udp_shell, "\n"); + + net_pkt_unref(pkt); + } +} + +static void udp_sent(struct net_context *context, int status, void *user_data) +{ + ARG_UNUSED(context); + ARG_UNUSED(status); + ARG_UNUSED(user_data); + + PR_SHELL(udp_shell, "Message sent\n"); + k_sem_give(&udp_send_wait); +} +#endif + +static int cmd_net_udp_bind(const struct shell *sh, size_t argc, char *argv[]) +{ +#if !defined(CONFIG_NET_UDP) || !defined(CONFIG_NET_NATIVE_UDP) + ARG_UNUSED(sh); + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + return -EOPNOTSUPP; +#else + char *addr_str = NULL; + char *endptr = NULL; + uint16_t port; + int ret; + + struct net_if *iface; + struct sockaddr addr; + int addrlen; + + if (argc < 3) { + PR_WARNING("Not enough arguments given for udp bind command\n"); + return -EINVAL; + } + + addr_str = argv[1]; + port = strtol(argv[2], &endptr, 0); + + if (endptr == argv[2]) { + PR_WARNING("Invalid port number\n"); + return -EINVAL; + } + + if (udp_ctx && net_context_is_used(udp_ctx)) { + PR_WARNING("Network context already in use\n"); + return -EALREADY; + } + + memset(&addr, 0, sizeof(addr)); + + ret = net_ipaddr_parse(addr_str, strlen(addr_str), &addr); + if (ret < 0) { + PR_WARNING("Cannot parse address \"%s\"\n", addr_str); + return ret; + } + + ret = net_context_get(addr.sa_family, SOCK_DGRAM, IPPROTO_UDP, + &udp_ctx); + if (ret < 0) { + PR_WARNING("Cannot get UDP context (%d)\n", ret); + return ret; + } + + udp_shell = sh; + + if (IS_ENABLED(CONFIG_NET_IPV6) && addr.sa_family == AF_INET6) { + net_sin6(&addr)->sin6_port = htons(port); + addrlen = sizeof(struct sockaddr_in6); + + iface = net_if_ipv6_select_src_iface( + &net_sin6(&addr)->sin6_addr); + } else if (IS_ENABLED(CONFIG_NET_IPV4) && addr.sa_family == AF_INET) { + net_sin(&addr)->sin_port = htons(port); + addrlen = sizeof(struct sockaddr_in); + + iface = net_if_ipv4_select_src_iface( + &net_sin(&addr)->sin_addr); + } else { + PR_WARNING("IPv6 and IPv4 are disabled, cannot %s.\n", "bind"); + goto release_ctx; + } + + if (!iface) { + PR_WARNING("No interface to send to given host\n"); + goto release_ctx; + } + + net_context_set_iface(udp_ctx, iface); + + ret = net_context_bind(udp_ctx, &addr, addrlen); + if (ret < 0) { + PR_WARNING("Binding to UDP port failed (%d)\n", ret); + goto release_ctx; + } + + ret = net_context_recv(udp_ctx, udp_rcvd, K_NO_WAIT, NULL); + if (ret < 0) { + PR_WARNING("Receiving from UDP port failed (%d)\n", ret); + goto release_ctx; + } + + return 0; + +release_ctx: + ret = net_context_put(udp_ctx); + if (ret < 0) { + PR_WARNING("Cannot put UDP context (%d)\n", ret); + } + + return 0; +#endif +} + +static int cmd_net_udp_close(const struct shell *sh, size_t argc, char *argv[]) +{ +#if !defined(CONFIG_NET_UDP) || !defined(CONFIG_NET_NATIVE_UDP) + ARG_UNUSED(sh); + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + return -EOPNOTSUPP; +#else + int ret; + + if (!udp_ctx || !net_context_is_used(udp_ctx)) { + PR_WARNING("Network context is not used. Cannot close.\n"); + return -EINVAL; + } + + ret = net_context_put(udp_ctx); + if (ret < 0) { + PR_WARNING("Cannot close UDP port (%d)\n", ret); + } + + return 0; +#endif +} + +static int cmd_net_udp_send(const struct shell *sh, size_t argc, char *argv[]) +{ +#if !defined(CONFIG_NET_UDP) || !defined(CONFIG_NET_NATIVE_UDP) + ARG_UNUSED(sh); + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + return -EOPNOTSUPP; +#else + char *host = NULL; + char *endptr = NULL; + uint16_t port; + uint8_t *payload = NULL; + int ret; + + struct net_if *iface; + struct sockaddr addr; + int addrlen; + + if (argc < 4) { + PR_WARNING("Not enough arguments given for udp send command\n"); + return -EINVAL; + } + + host = argv[1]; + port = strtol(argv[2], &endptr, 0); + payload = argv[3]; + + if (endptr == argv[2]) { + PR_WARNING("Invalid port number\n"); + return -EINVAL; + } + + if (udp_ctx && net_context_is_used(udp_ctx)) { + PR_WARNING("Network context already in use\n"); + return -EALREADY; + } + + memset(&addr, 0, sizeof(addr)); + ret = net_ipaddr_parse(host, strlen(host), &addr); + if (ret < 0) { + PR_WARNING("Cannot parse address \"%s\"\n", host); + return ret; + } + + ret = net_context_get(addr.sa_family, SOCK_DGRAM, IPPROTO_UDP, + &udp_ctx); + if (ret < 0) { + PR_WARNING("Cannot get UDP context (%d)\n", ret); + return ret; + } + + udp_shell = sh; + + if (IS_ENABLED(CONFIG_NET_IPV6) && addr.sa_family == AF_INET6) { + net_sin6(&addr)->sin6_port = htons(port); + addrlen = sizeof(struct sockaddr_in6); + + iface = net_if_ipv6_select_src_iface( + &net_sin6(&addr)->sin6_addr); + } else if (IS_ENABLED(CONFIG_NET_IPV4) && addr.sa_family == AF_INET) { + net_sin(&addr)->sin_port = htons(port); + addrlen = sizeof(struct sockaddr_in); + + iface = net_if_ipv4_select_src_iface( + &net_sin(&addr)->sin_addr); + } else { + PR_WARNING("IPv6 and IPv4 are disabled, cannot %s.\n", "send"); + goto release_ctx; + } + + if (!iface) { + PR_WARNING("No interface to send to given host\n"); + goto release_ctx; + } + + net_context_set_iface(udp_ctx, iface); + + ret = net_context_recv(udp_ctx, udp_rcvd, K_NO_WAIT, NULL); + if (ret < 0) { + PR_WARNING("Setting rcv callback failed (%d)\n", ret); + goto release_ctx; + } + + ret = net_context_sendto(udp_ctx, payload, strlen(payload), &addr, + addrlen, udp_sent, K_FOREVER, NULL); + if (ret < 0) { + PR_WARNING("Sending packet failed (%d)\n", ret); + goto release_ctx; + } + + ret = k_sem_take(&udp_send_wait, K_SECONDS(2)); + if (ret == -EAGAIN) { + PR_WARNING("UDP packet sending failed\n"); + } + +release_ctx: + ret = net_context_put(udp_ctx); + if (ret < 0) { + PR_WARNING("Cannot put UDP context (%d)\n", ret); + } + + return 0; +#endif +} + +static int cmd_net_udp(const struct shell *sh, size_t argc, char *argv[]) +{ + ARG_UNUSED(sh); + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + return 0; +} + +SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_udp, + SHELL_CMD(bind, NULL, + "'net udp bind ' binds to UDP local port.", + cmd_net_udp_bind), + SHELL_CMD(close, NULL, + "'net udp close' closes previously bound port.", + cmd_net_udp_close), + SHELL_CMD(send, NULL, + "'net udp send ' " + "sends UDP packet to a network host.", + cmd_net_udp_send), + SHELL_SUBCMD_SET_END +); + +SHELL_SUBCMD_ADD((net), udp, &net_cmd_udp, + "Send/recv UDP packet", + cmd_net_udp, 1, 0); diff --git a/subsys/net/lib/shell/virtual.c b/subsys/net/lib/shell/virtual.c new file mode 100644 index 00000000000..4eaabaa9916 --- /dev/null +++ b/subsys/net/lib/shell/virtual.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#if defined(CONFIG_NET_L2_VIRTUAL) +#include +#endif + +#include "net_shell_private.h" + +#if defined(CONFIG_NET_L2_VIRTUAL) +static void virtual_iface_cb(struct net_if *iface, void *user_data) +{ + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + int *count = data->user_data; + char *name, buf[CONFIG_NET_L2_VIRTUAL_MAX_NAME_LEN]; + struct net_if *orig_iface; + + if (net_if_l2(iface) != &NET_L2_GET_NAME(VIRTUAL)) { + return; + } + + if (*count == 0) { + PR("Interface Attached-To Description\n"); + (*count)++; + } + + orig_iface = net_virtual_get_iface(iface); + + name = net_virtual_get_name(iface, buf, sizeof(buf)); + + PR("%d %c %s\n", + net_if_get_by_iface(iface), + orig_iface ? net_if_get_by_iface(orig_iface) + '0' : '-', + name); + + (*count)++; +} + +static void attached_iface_cb(struct net_if *iface, void *user_data) +{ + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + int *count = data->user_data; + char buf[CONFIG_NET_L2_VIRTUAL_MAX_NAME_LEN]; + const char *name; + struct virtual_interface_context *ctx, *tmp; + + if (sys_slist_is_empty(&iface->config.virtual_interfaces)) { + return; + } + + if (*count == 0) { + PR("Interface Below-of Description\n"); + (*count)++; + } + + PR("%d ", net_if_get_by_iface(iface)); + + SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&iface->config.virtual_interfaces, + ctx, tmp, node) { + if (ctx->virtual_iface == iface) { + continue; + } + + PR("%d ", net_if_get_by_iface(ctx->virtual_iface)); + } + + name = net_virtual_get_name(iface, buf, sizeof(buf)); + if (name == NULL) { + name = iface2str(iface, NULL); + } + + PR(" %s\n", name); + + (*count)++; +} +#endif /* CONFIG_NET_L2_VIRTUAL */ + +static int cmd_net_virtual(const struct shell *sh, size_t argc, char *argv[]) +{ + ARG_UNUSED(argc); + ARG_UNUSED(argv); + +#if defined(CONFIG_NET_L2_VIRTUAL) + struct net_shell_user_data user_data; + int count = 0; + + user_data.sh = sh; + user_data.user_data = &count; + + net_if_foreach(virtual_iface_cb, &user_data); + + if (count == 0) { + PR("No virtual interfaces found."); + } + + count = 0; + PR("\n"); + + net_if_foreach(attached_iface_cb, &user_data); +#else + PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_L2_VIRTUAL", + "virtual network interface"); +#endif + return 0; +} + +SHELL_SUBCMD_ADD((net), virtual, NULL, + "Show virtual network interfaces.", + cmd_net_virtual, 1, 0); diff --git a/subsys/net/lib/shell/vlan.c b/subsys/net/lib/shell/vlan.c new file mode 100644 index 00000000000..ea7103ef1c9 --- /dev/null +++ b/subsys/net/lib/shell/vlan.c @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#if defined(CONFIG_NET_L2_VIRTUAL) +#include +#endif +#include + +#include + +#include "net_shell_private.h" + +#if defined(CONFIG_NET_VLAN) +static void iface_vlan_del_cb(struct net_if *iface, void *user_data) +{ + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + uint16_t vlan_tag = POINTER_TO_UINT(data->user_data); + int ret; + + ret = net_eth_vlan_disable(iface, vlan_tag); + if (ret < 0) { + if (ret != -ESRCH) { + PR_WARNING("Cannot delete VLAN tag %d from " + "interface %d (%p)\n", + vlan_tag, + net_if_get_by_iface(iface), + iface); + } + + return; + } + + PR("VLAN tag %d removed from interface %d (%p)\n", vlan_tag, + net_if_get_by_iface(iface), iface); +} + +static void iface_vlan_cb(struct net_if *iface, void *user_data) +{ + struct ethernet_context *ctx = net_if_l2_data(iface); + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + int *count = data->user_data; + int i; + + if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) { + return; + } + + if (*count == 0) { + PR(" Interface Type Tag\n"); + } + + if (!ctx->vlan_enabled) { + PR_WARNING("VLAN tag(s) not set\n"); + return; + } + + for (i = 0; i < NET_VLAN_MAX_COUNT; i++) { + if (!ctx->vlan[i].iface || ctx->vlan[i].iface != iface) { + continue; + } + + if (ctx->vlan[i].tag == NET_VLAN_TAG_UNSPEC) { + continue; + } + + PR("[%d] %p %s %d\n", net_if_get_by_iface(iface), iface, + iface2str(iface, NULL), ctx->vlan[i].tag); + + break; + } + + (*count)++; +} +#endif /* CONFIG_NET_VLAN */ + +static int cmd_net_vlan(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_VLAN) + struct net_shell_user_data user_data; + int count = 0; + + user_data.sh = sh; + user_data.user_data = &count; + + net_if_foreach(iface_vlan_cb, &user_data); +#else + PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_VLAN", "VLAN"); +#endif /* CONFIG_NET_VLAN */ + + return 0; +} + +static int cmd_net_vlan_add(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_VLAN) + int arg = 0; + int ret; + uint16_t tag; + struct net_if *iface; + char *endptr; + uint32_t iface_idx; + + /* vlan add */ + if (!argv[++arg]) { + PR_WARNING("VLAN tag missing.\n"); + goto usage; + } + + tag = strtol(argv[arg], &endptr, 10); + if (*endptr != '\0') { + PR_WARNING("Invalid tag %s\n", argv[arg]); + return -ENOEXEC; + } + + if (!argv[++arg]) { + PR_WARNING("Network interface index missing.\n"); + goto usage; + } + + iface_idx = strtol(argv[arg], &endptr, 10); + if (*endptr != '\0') { + PR_WARNING("Invalid index %s\n", argv[arg]); + goto usage; + } + + iface = net_if_get_by_index(iface_idx); + if (!iface) { + PR_WARNING("Network interface index %d is invalid.\n", + iface_idx); + goto usage; + } + + if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) { + PR_WARNING("Network interface %d (%p) is not ethernet interface\n", + net_if_get_by_iface(iface), iface); + return -ENOEXEC; + } + + ret = net_eth_vlan_enable(iface, tag); + if (ret < 0) { + if (ret == -ENOENT) { + PR_WARNING("No IP address configured.\n"); + } + + PR_WARNING("Cannot set VLAN tag (%d)\n", ret); + + return -ENOEXEC; + } + + PR("VLAN tag %d set to interface %d (%p)\n", tag, + net_if_get_by_iface(iface), iface); + + return 0; + +usage: + PR("Usage:\n"); + PR("\tvlan add \n"); +#else + PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_VLAN", "VLAN"); +#endif /* CONFIG_NET_VLAN */ + + return 0; +} + +static int cmd_net_vlan_del(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_VLAN) + int arg = 0; + struct net_shell_user_data user_data; + char *endptr; + uint16_t tag; + + /* vlan del */ + if (!argv[++arg]) { + PR_WARNING("VLAN tag missing.\n"); + goto usage; + } + + tag = strtol(argv[arg], &endptr, 10); + if (*endptr != '\0') { + PR_WARNING("Invalid tag %s\n", argv[arg]); + return -ENOEXEC; + } + + user_data.sh = sh; + user_data.user_data = UINT_TO_POINTER((uint32_t)tag); + + net_if_foreach(iface_vlan_del_cb, &user_data); + + return 0; + +usage: + PR("Usage:\n"); + PR("\tvlan del \n"); +#else + PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_VLAN", "VLAN"); +#endif /* CONFIG_NET_VLAN */ + + return 0; +} + +SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_vlan, + SHELL_CMD_ARG(add, NULL, + "'net vlan add ' adds VLAN tag to the " + "network interface.", + cmd_net_vlan_add, 3, 0), + SHELL_CMD_ARG(del, NULL, + "'net vlan del ' deletes VLAN tag from the network " + "interface.", + cmd_net_vlan_del, 2, 0), + SHELL_SUBCMD_SET_END +); + +SHELL_SUBCMD_ADD((net), vlan, &net_cmd_vlan, + "Show VLAN information.", + cmd_net_vlan, 1, 0); diff --git a/subsys/net/lib/shell/websocket.c b/subsys/net/lib/shell/websocket.c new file mode 100644 index 00000000000..56e705199e3 --- /dev/null +++ b/subsys/net/lib/shell/websocket.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#if defined(CONFIG_NET_L2_VIRTUAL) +#include +#endif + +#include "net_shell_private.h" + +#include "websocket/websocket_internal.h" + +#include + +#if defined(CONFIG_WEBSOCKET_CLIENT) +static void websocket_context_cb(struct websocket_context *context, + void *user_data) +{ + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + struct net_context *net_ctx; + int *count = data->user_data; + /* +7 for []:port */ + char addr_local[ADDR_LEN + 7]; + char addr_remote[ADDR_LEN + 7] = ""; + + net_ctx = z_get_fd_obj(context->real_sock, NULL, 0); + if (net_ctx == NULL) { + PR_ERROR("Invalid fd %d", context->real_sock); + return; + } + + if ((*count) == 0) { + PR(" websocket/net_ctx\tIface " + "Local \tRemote\n"); + } + + get_addresses(net_ctx, addr_local, sizeof(addr_local), + addr_remote, sizeof(addr_remote)); + + PR("[%2d] %p/%p\t%p %16s\t%16s\n", + (*count) + 1, context, net_ctx, + net_context_get_iface(net_ctx), + addr_local, addr_remote); + + (*count)++; +} +#endif /* CONFIG_WEBSOCKET_CLIENT */ + +static int cmd_net_websocket(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_WEBSOCKET_CLIENT) + struct net_shell_user_data user_data; + int count = 0; + + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + user_data.sh = sh; + user_data.user_data = &count; + + websocket_context_foreach(websocket_context_cb, &user_data); + + if (count == 0) { + PR("No connections\n"); + } +#else + PR_INFO("Set %s to enable %s support.\n", "CONFIG_WEBSOCKET_CLIENT", + "Websocket"); +#endif /* CONFIG_WEBSOCKET_CLIENT */ + + return 0; +} + +SHELL_SUBCMD_ADD((net), websocket, NULL, + "Print information about WebSocket connections.", + cmd_net_websocket, 1, 0); diff --git a/subsys/net/lib/sockets/CMakeLists.txt b/subsys/net/lib/sockets/CMakeLists.txt index 14f4f241183..7ffd6dc476b 100644 --- a/subsys/net/lib/sockets/CMakeLists.txt +++ b/subsys/net/lib/sockets/CMakeLists.txt @@ -5,36 +5,37 @@ zephyr_syscall_header( ${ZEPHYR_BASE}/include/zephyr/net/socket_select.h ) -zephyr_include_directories(.) +zephyr_library_include_directories(.) -zephyr_sources( +zephyr_library_sources( getaddrinfo.c sockets.c sockets_select.c ) if(NOT CONFIG_NET_SOCKETS_OFFLOAD) -zephyr_sources( +zephyr_library_sources( getnameinfo.c sockets_misc.c ) endif() -zephyr_sources_ifdef(CONFIG_NET_SOCKETS_CAN sockets_can.c) -zephyr_sources_ifdef(CONFIG_NET_SOCKETS_PACKET sockets_packet.c) -zephyr_sources_ifdef(CONFIG_NET_SOCKETS_SOCKOPT_TLS sockets_tls.c) -zephyr_sources_ifdef(CONFIG_NET_SOCKETS_OFFLOAD socket_offload.c) -zephyr_sources_ifdef(CONFIG_NET_SOCKETS_OFFLOAD_DISPATCHER socket_dispatcher.c) +zephyr_library_sources_ifdef(CONFIG_NET_SOCKETS_CAN sockets_can.c) +zephyr_library_sources_ifdef(CONFIG_NET_SOCKETS_PACKET sockets_packet.c) +zephyr_library_sources_ifdef(CONFIG_NET_SOCKETS_SOCKOPT_TLS sockets_tls.c) +zephyr_library_sources_ifdef(CONFIG_NET_SOCKETS_OFFLOAD socket_offload.c) +zephyr_library_sources_ifdef(CONFIG_NET_SOCKETS_OFFLOAD_DISPATCHER socket_dispatcher.c) +zephyr_library_sources_ifdef(CONFIG_NET_SOCKETS_OBJ_CORE socket_obj_core.c) if(CONFIG_NET_SOCKETS_NET_MGMT) - zephyr_sources(sockets_net_mgmt.c) - zephyr_include_directories(${ZEPHYR_BASE}/subsys/net/ip) + zephyr_library_sources(sockets_net_mgmt.c) + zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/net/ip) endif() if(CONFIG_SOCKS) - zephyr_include_directories(${ZEPHYR_BASE}/subsys/net/lib/socks) + zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/net/lib/socks) endif() -zephyr_sources_ifdef(CONFIG_NET_SOCKETPAIR socketpair.c) +zephyr_library_sources_ifdef(CONFIG_NET_SOCKETPAIR socketpair.c) -zephyr_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS) +zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS) diff --git a/subsys/net/lib/sockets/Kconfig b/subsys/net/lib/sockets/Kconfig index 655d321ab9b..b2da30c1e48 100644 --- a/subsys/net/lib/sockets/Kconfig +++ b/subsys/net/lib/sockets/Kconfig @@ -5,6 +5,7 @@ menuconfig NET_SOCKETS bool "BSD Sockets compatible API" + select FDTABLE help Provide BSD Sockets like API on top of native Zephyr networking API. @@ -41,6 +42,7 @@ config NET_SOCKETS_POSIX_NAMES config NET_SOCKETS_POLL_MAX int "Max number of supported poll() entries" + default 6 if WIFI_NM_WPA_SUPPLICANT default 3 help Maximum number of entries supported for poll() call. @@ -260,6 +262,7 @@ if NET_SOCKETPAIR config NET_SOCKETPAIR_BUFFER_SIZE int "Size of the intermediate buffer, in bytes" + default 4096 if WIFI_NM_WPA_SUPPLICANT default 64 range 1 4096 help @@ -310,4 +313,15 @@ module-str = Log level for BSD sockets compatible API calls module-help = Enables logging for sockets code. source "subsys/net/Kconfig.template.log_config.net" +config NET_SOCKETS_OBJ_CORE + bool "Object core socket support [EXPERIMENTAL]" + depends on OBJ_CORE + select OBJ_CORE_STATS + select EXPERIMENTAL + help + Select this if you want to use object core with socket API to get + network socket information and statistics via object core. + The net-shell "net sockets" command will use this functionality + to show the socket information. + endif # NET_SOCKETS diff --git a/subsys/net/lib/sockets/getaddrinfo.c b/subsys/net/lib/sockets/getaddrinfo.c index 2a499dcebb0..70a611a3f4a 100644 --- a/subsys/net/lib/sockets/getaddrinfo.c +++ b/subsys/net/lib/sockets/getaddrinfo.c @@ -18,7 +18,7 @@ LOG_MODULE_REGISTER(net_sock_addr, CONFIG_NET_SOCKETS_LOG_LEVEL); #include #include #include -#include +#include #if defined(CONFIG_DNS_RESOLVER) || defined(CONFIG_NET_IP) #define ANY_RESOLVER @@ -281,13 +281,13 @@ static inline int z_vrfy_z_zsock_getaddrinfo_internal(const char *host, uint32_t ret; if (hints) { - Z_OOPS(z_user_from_copy(&hints_copy, (void *)hints, + K_OOPS(k_usermode_from_copy(&hints_copy, (void *)hints, sizeof(hints_copy))); } - Z_OOPS(Z_SYSCALL_MEMORY_ARRAY_WRITE(res, AI_ARR_MAX, sizeof(struct zsock_addrinfo))); + K_OOPS(K_SYSCALL_MEMORY_ARRAY_WRITE(res, AI_ARR_MAX, sizeof(struct zsock_addrinfo))); if (service) { - service_copy = z_user_string_alloc_copy((char *)service, 64); + service_copy = k_usermode_string_alloc_copy((char *)service, 64); if (!service_copy) { ret = DNS_EAI_MEMORY; goto out; @@ -295,7 +295,7 @@ static inline int z_vrfy_z_zsock_getaddrinfo_internal(const char *host, } if (host) { - host_copy = z_user_string_alloc_copy((char *)host, 64); + host_copy = k_usermode_string_alloc_copy((char *)host, 64); if (!host_copy) { ret = DNS_EAI_MEMORY; goto out; diff --git a/subsys/net/lib/sockets/socket_obj_core.c b/subsys/net/lib/sockets/socket_obj_core.c new file mode 100644 index 00000000000..4133c5cef2e --- /dev/null +++ b/subsys/net/lib/sockets/socket_obj_core.c @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Object core support for sockets */ + +#include +LOG_MODULE_DECLARE(net_sock, CONFIG_NET_SOCKETS_LOG_LEVEL); + +#include + +#include "sockets_internal.h" +#include "../../ip/net_private.h" + +static struct k_obj_type sock_obj_type; +static K_MUTEX_DEFINE(sock_obj_mutex); + +/* Allocate some extra socket objects so that we can track + * closed sockets and get some historical statistics. + */ +static struct sock_obj sock_objects[CONFIG_POSIX_MAX_FDS * 2] = { + [0 ... ((CONFIG_POSIX_MAX_FDS * 2) - 1)] = { + .fd = -1, + .init_done = false, + } +}; + +static void sock_obj_core_init_and_link(struct sock_obj *sock); +static int sock_obj_core_stats_reset(struct k_obj_core *obj); +static int sock_obj_stats_raw(struct k_obj_core *obj_core, void *stats); +static int sock_obj_core_get_reg_and_proto(int sock, + struct net_socket_register **reg); + +struct k_obj_core_stats_desc sock_obj_type_stats_desc = { + .raw_size = sizeof(struct sock_obj_type_raw_stats), + .raw = sock_obj_stats_raw, + .reset = sock_obj_core_stats_reset, + .disable = NULL, /* Stats gathering is always on */ + .enable = NULL, /* Stats gathering is always on */ +}; + +static void set_fields(struct sock_obj *obj, int fd, + struct net_socket_register *reg, + int family, int type, int proto) +{ + obj->fd = fd; + obj->socket_family = family; + obj->socket_type = type; + obj->socket_proto = proto; + obj->reg = reg; + obj->creator = k_current_get(); + obj->create_time = sys_clock_tick_get(); +} + +static void sock_obj_core_init_and_link(struct sock_obj *sock) +{ + static bool type_init_done; + + if (!type_init_done) { + z_obj_type_init(&sock_obj_type, K_OBJ_TYPE_SOCK, + offsetof(struct sock_obj, obj_core)); + k_obj_type_stats_init(&sock_obj_type, &sock_obj_type_stats_desc); + + type_init_done = true; + } + + k_obj_core_init_and_link(K_OBJ_CORE(sock), &sock_obj_type); + k_obj_core_stats_register(K_OBJ_CORE(sock), &sock->stats, + sizeof(struct sock_obj_type_raw_stats)); + + /* If the socket was closed and we re-opened it again, then clear + * the statistics. + */ + if (sock->init_done) { + k_obj_core_stats_reset(K_OBJ_CORE(sock)); + } + + sock->init_done = true; +} + +static int sock_obj_stats_raw(struct k_obj_core *obj_core, void *stats) +{ + memcpy(stats, obj_core->stats, sizeof(struct sock_obj_type_raw_stats)); + + return 0; +} + +static int sock_obj_core_stats_reset(struct k_obj_core *obj_core) +{ + memset(obj_core->stats, 0, sizeof(struct sock_obj_type_raw_stats)); + + return 0; +} + +static int sock_obj_core_get_reg_and_proto(int sock, struct net_socket_register **reg) +{ + int i, ret; + + k_mutex_lock(&sock_obj_mutex, K_FOREVER); + + for (i = 0; i < ARRAY_SIZE(sock_objects); i++) { + if (sock_objects[i].fd == sock) { + *reg = sock_objects[i].reg; + ret = sock_objects[i].socket_proto; + goto out; + } + } + + ret = -ENOENT; + +out: + k_mutex_unlock(&sock_obj_mutex); + + return ret; +} + +int sock_obj_core_alloc(int sock, struct net_socket_register *reg, + int family, int type, int proto) +{ + struct sock_obj *obj = NULL; + int ret, i; + + if (sock < 0) { + return -EINVAL; + } + + k_mutex_lock(&sock_obj_mutex, K_FOREVER); + + /* Try not to allocate already closed sockets so that we + * can see historical data. + */ + for (i = 0; i < ARRAY_SIZE(sock_objects); i++) { + if (sock_objects[i].fd < 0) { + if (sock_objects[i].init_done == false) { + obj = &sock_objects[i]; + break; + } else if (obj == NULL) { + obj = &sock_objects[i]; + } + } + } + + if (obj == NULL) { + ret = -ENOENT; + goto out; + } + + set_fields(obj, sock, reg, family, type, proto); + sock_obj_core_init_and_link(obj); + + ret = 0; + +out: + k_mutex_unlock(&sock_obj_mutex); + + return ret; +} + +int sock_obj_core_alloc_find(int sock, int new_sock, int family, int type) +{ + struct net_socket_register *reg = NULL; + int ret; + + if (new_sock < 0) { + return -EINVAL; + } + + ret = sock_obj_core_get_reg_and_proto(sock, ®); + if (ret < 0) { + goto out; + } + + ret = sock_obj_core_alloc(new_sock, reg, family, type, ret); + if (ret < 0) { + NET_ERR("Cannot allocate core object for socket %d (%d)", + new_sock, ret); + } + +out: + return ret; +} + +int sock_obj_core_dealloc(int fd) +{ + int ret; + + k_mutex_lock(&sock_obj_mutex, K_FOREVER); + + for (int i = 0; i < ARRAY_SIZE(sock_objects); i++) { + if (sock_objects[i].fd == fd) { + sock_objects[i].fd = -1; + + /* Calculate the lifetime of the socket so that + * net-shell can print it for the closed sockets. + */ + sock_objects[i].create_time = + k_ticks_to_ms_ceil32(sys_clock_tick_get() - + sock_objects[i].create_time); + ret = 0; + goto out; + } + } + + ret = -ENOENT; + +out: + k_mutex_unlock(&sock_obj_mutex); + + return ret; +} + +void sock_obj_core_update_send_stats(int fd, int bytes) +{ + if (bytes > 0) { + k_mutex_lock(&sock_obj_mutex, K_FOREVER); + + for (int i = 0; i < ARRAY_SIZE(sock_objects); i++) { + if (sock_objects[i].fd == fd) { + sock_objects[i].stats.sent += bytes; + break; + } + } + + k_mutex_unlock(&sock_obj_mutex); + } +} + +void sock_obj_core_update_recv_stats(int fd, int bytes) +{ + if (bytes > 0) { + k_mutex_lock(&sock_obj_mutex, K_FOREVER); + + for (int i = 0; i < ARRAY_SIZE(sock_objects); i++) { + if (sock_objects[i].fd == fd) { + sock_objects[i].stats.received += bytes; + break; + } + } + + k_mutex_unlock(&sock_obj_mutex); + } +} diff --git a/subsys/net/lib/sockets/socketpair.c b/subsys/net/lib/sockets/socketpair.c index 9207f4b659e..417a3b34fb1 100644 --- a/subsys/net/lib/sockets/socketpair.c +++ b/subsys/net/lib/sockets/socketpair.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include @@ -228,7 +228,7 @@ static struct spair *spair_new(void) } #elif CONFIG_USERSPACE - struct z_object *zo = z_dynamic_object_create(sizeof(*spair)); + struct k_object *zo = k_object_create_dynamic(sizeof(*spair)); if (zo == NULL) { spair = NULL; @@ -341,7 +341,7 @@ int z_vrfy_zsock_socketpair(int family, int type, int proto, int *sv) int ret; int tmp[2]; - if (!sv || Z_SYSCALL_MEMORY_WRITE(sv, sizeof(tmp)) != 0) { + if (!sv || K_SYSCALL_MEMORY_WRITE(sv, sizeof(tmp)) != 0) { /* not listed in normative spec, but mimics linux behaviour */ errno = EFAULT; ret = -1; @@ -350,7 +350,7 @@ int z_vrfy_zsock_socketpair(int family, int type, int proto, int *sv) ret = z_impl_zsock_socketpair(family, type, proto, tmp); if (ret == 0) { - Z_OOPS(z_user_to_copy(sv, tmp, sizeof(tmp))); + K_OOPS(k_usermode_to_copy(sv, tmp, sizeof(tmp))); } out: diff --git a/subsys/net/lib/sockets/sockets.c b/subsys/net/lib/sockets/sockets.c index 801ed99fe60..d35317352c9 100644 --- a/subsys/net/lib/sockets/sockets.c +++ b/subsys/net/lib/sockets/sockets.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2017 Linaro Limited * Copyright (c) 2021 Nordic Semiconductor + * Copyright (c) 2023 Arm Limited (or its affiliates). All rights reserved. * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +20,7 @@ LOG_MODULE_REGISTER(net_sock, CONFIG_NET_SOCKETS_LOG_LEVEL); #else #include #endif -#include +#include #include #include #include @@ -32,12 +33,13 @@ LOG_MODULE_REGISTER(net_sock, CONFIG_NET_SOCKETS_LOG_LEVEL); #include "sockets_internal.h" #include "../../ip/tcp_internal.h" +#include "../../ip/net_private.h" #define SET_ERRNO(x) \ { int _err = x; if (_err < 0) { errno = -_err; return -1; } } #define VTABLE_CALL(fn, sock, ...) \ - do { \ + ({ \ const struct socket_op_vtable *vtable; \ struct k_mutex *lock; \ void *obj; \ @@ -60,8 +62,8 @@ LOG_MODULE_REGISTER(net_sock, CONFIG_NET_SOCKETS_LOG_LEVEL); \ k_mutex_unlock(lock); \ \ - return ret; \ - } while (0) + ret; \ + }) const struct socket_op_vtable sock_fd_op_vtable; @@ -76,15 +78,8 @@ static inline void *get_sock_vtable(int sock, lock); #ifdef CONFIG_USERSPACE - if (ctx != NULL && z_is_in_user_syscall()) { - struct z_object *zo; - int ret; - - zo = z_object_find(ctx); - ret = z_object_validate(zo, K_OBJ_NET_SOCKET, _OBJ_INIT_TRUE); - - if (ret != 0) { - z_dump_object_error(ret, ctx, zo, K_OBJ_NET_SOCKET); + if (ctx != NULL && k_is_in_user_syscall()) { + if (!k_object_is_valid(ctx, K_OBJ_NET_SOCKET)) { /* Invalidate the context, the caller doesn't have * sufficient permission or there was some other * problem with the net socket object @@ -223,6 +218,8 @@ static int zsock_socket_internal(int family, int type, int proto) int z_impl_zsock_socket(int family, int type, int proto) { STRUCT_SECTION_FOREACH(net_socket_register, sock_family) { + int ret; + if (sock_family->family != family && sock_family->family != AF_UNSPEC) { continue; @@ -234,7 +231,11 @@ int z_impl_zsock_socket(int family, int type, int proto) continue; } - return sock_family->handler(family, type, proto); + ret = sock_family->handler(family, type, proto); + + (void)sock_obj_core_alloc(ret, sock_family, family, type, proto); + + return ret; } errno = EAFNOSUPPORT; @@ -298,6 +299,8 @@ int z_impl_zsock_close(int sock) z_free_fd(sock); + (void)sock_obj_core_dealloc(sock); + return ret; } @@ -423,12 +426,12 @@ static void zsock_received_cb(struct net_context *ctx, k_fifo_put(&ctx->recv_q, pkt); unlock: + /* Wake reader if it was sleeping */ + (void)k_condvar_signal(&ctx->cond.recv); + if (ctx->cond.lock) { (void)k_mutex_unlock(ctx->cond.lock); } - - /* Wake reader if it was sleeping */ - (void)k_condvar_signal(&ctx->cond.recv); } int zsock_shutdown_ctx(struct net_context *ctx, int how) @@ -470,7 +473,7 @@ int zsock_bind_ctx(struct net_context *ctx, const struct sockaddr *addr, int z_impl_zsock_bind(int sock, const struct sockaddr *addr, socklen_t addrlen) { - VTABLE_CALL(bind, sock, addr, addrlen); + return VTABLE_CALL(bind, sock, addr, addrlen); } #ifdef CONFIG_USERSPACE @@ -479,8 +482,8 @@ static inline int z_vrfy_zsock_bind(int sock, const struct sockaddr *addr, { struct sockaddr_storage dest_addr_copy; - Z_OOPS(Z_SYSCALL_VERIFY(addrlen <= sizeof(dest_addr_copy))); - Z_OOPS(z_user_from_copy(&dest_addr_copy, (void *)addr, addrlen)); + K_OOPS(K_SYSCALL_VERIFY(addrlen <= sizeof(dest_addr_copy))); + K_OOPS(k_usermode_from_copy(&dest_addr_copy, (void *)addr, addrlen)); return z_impl_zsock_bind(sock, (struct sockaddr *)&dest_addr_copy, addrlen); @@ -549,7 +552,7 @@ int zsock_connect_ctx(struct net_context *ctx, const struct sockaddr *addr, int z_impl_zsock_connect(int sock, const struct sockaddr *addr, socklen_t addrlen) { - VTABLE_CALL(connect, sock, addr, addrlen); + return VTABLE_CALL(connect, sock, addr, addrlen); } #ifdef CONFIG_USERSPACE @@ -558,8 +561,8 @@ int z_vrfy_zsock_connect(int sock, const struct sockaddr *addr, { struct sockaddr_storage dest_addr_copy; - Z_OOPS(Z_SYSCALL_VERIFY(addrlen <= sizeof(dest_addr_copy))); - Z_OOPS(z_user_from_copy(&dest_addr_copy, (void *)addr, addrlen)); + K_OOPS(K_SYSCALL_VERIFY(addrlen <= sizeof(dest_addr_copy))); + K_OOPS(k_usermode_from_copy(&dest_addr_copy, (void *)addr, addrlen)); return z_impl_zsock_connect(sock, (struct sockaddr *)&dest_addr_copy, addrlen); @@ -577,7 +580,7 @@ int zsock_listen_ctx(struct net_context *ctx, int backlog) int z_impl_zsock_listen(int sock, int backlog) { - VTABLE_CALL(listen, sock, backlog); + return VTABLE_CALL(listen, sock, backlog); } #ifdef CONFIG_USERSPACE @@ -674,7 +677,13 @@ int zsock_accept_ctx(struct net_context *parent, struct sockaddr *addr, int z_impl_zsock_accept(int sock, struct sockaddr *addr, socklen_t *addrlen) { - VTABLE_CALL(accept, sock, addr, addrlen); + int new_sock; + + new_sock = VTABLE_CALL(accept, sock, addr, addrlen); + + (void)sock_obj_core_alloc_find(sock, new_sock, addr->sa_family, SOCK_STREAM); + + return new_sock; } #ifdef CONFIG_USERSPACE @@ -684,14 +693,14 @@ static inline int z_vrfy_zsock_accept(int sock, struct sockaddr *addr, socklen_t addrlen_copy; int ret; - Z_OOPS(addrlen && z_user_from_copy(&addrlen_copy, addrlen, + K_OOPS(addrlen && k_usermode_from_copy(&addrlen_copy, addrlen, sizeof(socklen_t))); - Z_OOPS(addr && Z_SYSCALL_MEMORY_WRITE(addr, addrlen ? addrlen_copy : 0)); + K_OOPS(addr && K_SYSCALL_MEMORY_WRITE(addr, addrlen ? addrlen_copy : 0)); ret = z_impl_zsock_accept(sock, (struct sockaddr *)addr, addrlen ? &addrlen_copy : NULL); - Z_OOPS(ret >= 0 && addrlen && z_user_to_copy(addrlen, &addrlen_copy, + K_OOPS(ret >= 0 && addrlen && k_usermode_to_copy(addrlen, &addrlen_copy, sizeof(socklen_t))); return ret; @@ -838,7 +847,13 @@ ssize_t zsock_sendto_ctx(struct net_context *ctx, const void *buf, size_t len, ssize_t z_impl_zsock_sendto(int sock, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) { - VTABLE_CALL(sendto, sock, buf, len, flags, dest_addr, addrlen); + int bytes_sent; + + bytes_sent = VTABLE_CALL(sendto, sock, buf, len, flags, dest_addr, addrlen); + + sock_obj_core_update_send_stats(sock, bytes_sent); + + return bytes_sent; } #ifdef CONFIG_USERSPACE @@ -847,10 +862,10 @@ ssize_t z_vrfy_zsock_sendto(int sock, const void *buf, size_t len, int flags, { struct sockaddr_storage dest_addr_copy; - Z_OOPS(Z_SYSCALL_MEMORY_READ(buf, len)); + K_OOPS(K_SYSCALL_MEMORY_READ(buf, len)); if (dest_addr) { - Z_OOPS(Z_SYSCALL_VERIFY(addrlen <= sizeof(dest_addr_copy))); - Z_OOPS(z_user_from_copy(&dest_addr_copy, (void *)dest_addr, + K_OOPS(K_SYSCALL_VERIFY(addrlen <= sizeof(dest_addr_copy))); + K_OOPS(k_usermode_from_copy(&dest_addr_copy, (void *)dest_addr, addrlen)); } @@ -917,7 +932,13 @@ ssize_t zsock_sendmsg_ctx(struct net_context *ctx, const struct msghdr *msg, ssize_t z_impl_zsock_sendmsg(int sock, const struct msghdr *msg, int flags) { - VTABLE_CALL(sendmsg, sock, msg, flags); + int bytes_sent; + + bytes_sent = VTABLE_CALL(sendmsg, sock, msg, flags); + + sock_obj_core_update_send_stats(sock, bytes_sent); + + return bytes_sent; } #ifdef CONFIG_USERSPACE @@ -929,12 +950,12 @@ static inline ssize_t z_vrfy_zsock_sendmsg(int sock, size_t i; int ret; - Z_OOPS(z_user_from_copy(&msg_copy, (void *)msg, sizeof(msg_copy))); + K_OOPS(k_usermode_from_copy(&msg_copy, (void *)msg, sizeof(msg_copy))); msg_copy.msg_name = NULL; msg_copy.msg_control = NULL; - msg_copy.msg_iov = z_user_alloc_from_copy(msg->msg_iov, + msg_copy.msg_iov = k_usermode_alloc_from_copy(msg->msg_iov, msg->msg_iovlen * sizeof(struct iovec)); if (!msg_copy.msg_iov) { errno = ENOMEM; @@ -943,7 +964,7 @@ static inline ssize_t z_vrfy_zsock_sendmsg(int sock, for (i = 0; i < msg->msg_iovlen; i++) { msg_copy.msg_iov[i].iov_base = - z_user_alloc_from_copy(msg->msg_iov[i].iov_base, + k_usermode_alloc_from_copy(msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len); if (!msg_copy.msg_iov[i].iov_base) { errno = ENOMEM; @@ -954,7 +975,7 @@ static inline ssize_t z_vrfy_zsock_sendmsg(int sock, } if (msg->msg_namelen > 0) { - msg_copy.msg_name = z_user_alloc_from_copy(msg->msg_name, + msg_copy.msg_name = k_usermode_alloc_from_copy(msg->msg_name, msg->msg_namelen); if (!msg_copy.msg_name) { errno = ENOMEM; @@ -963,7 +984,7 @@ static inline ssize_t z_vrfy_zsock_sendmsg(int sock, } if (msg->msg_controllen > 0) { - msg_copy.msg_control = z_user_alloc_from_copy(msg->msg_control, + msg_copy.msg_control = k_usermode_alloc_from_copy(msg->msg_control, msg->msg_controllen); if (!msg_copy.msg_control) { errno = ENOMEM; @@ -1477,7 +1498,13 @@ ssize_t zsock_recvfrom_ctx(struct net_context *ctx, void *buf, size_t max_len, ssize_t z_impl_zsock_recvfrom(int sock, void *buf, size_t max_len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) { - VTABLE_CALL(recvfrom, sock, buf, max_len, flags, src_addr, addrlen); + int bytes_received; + + bytes_received = VTABLE_CALL(recvfrom, sock, buf, max_len, flags, src_addr, addrlen); + + sock_obj_core_update_recv_stats(sock, bytes_received); + + return bytes_received; } #ifdef CONFIG_USERSPACE @@ -1487,23 +1514,23 @@ ssize_t z_vrfy_zsock_recvfrom(int sock, void *buf, size_t max_len, int flags, socklen_t addrlen_copy; ssize_t ret; - if (Z_SYSCALL_MEMORY_WRITE(buf, max_len)) { + if (K_SYSCALL_MEMORY_WRITE(buf, max_len)) { errno = EFAULT; return -1; } if (addrlen) { - Z_OOPS(z_user_from_copy(&addrlen_copy, addrlen, + K_OOPS(k_usermode_from_copy(&addrlen_copy, addrlen, sizeof(socklen_t))); } - Z_OOPS(src_addr && Z_SYSCALL_MEMORY_WRITE(src_addr, addrlen_copy)); + K_OOPS(src_addr && K_SYSCALL_MEMORY_WRITE(src_addr, addrlen_copy)); ret = z_impl_zsock_recvfrom(sock, (void *)buf, max_len, flags, (struct sockaddr *)src_addr, addrlen ? &addrlen_copy : NULL); if (addrlen) { - Z_OOPS(z_user_to_copy(addrlen, &addrlen_copy, + K_OOPS(k_usermode_to_copy(addrlen, &addrlen_copy, sizeof(socklen_t))); } @@ -1582,7 +1609,7 @@ static inline int z_vrfy_zsock_ioctl(int sock, unsigned long request, va_list ar int *avail; avail = va_arg(args, int *); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(avail, sizeof(*avail))); + K_OOPS(K_SYSCALL_MEMORY_WRITE(avail, sizeof(*avail))); break; } @@ -1879,7 +1906,7 @@ static inline int z_vrfy_zsock_poll(struct zsock_pollfd *fds, errno = EFAULT; return -1; } - fds_copy = z_user_alloc_from_copy((void *)fds, fds_size); + fds_copy = k_usermode_alloc_from_copy((void *)fds, fds_size); if (!fds_copy) { errno = ENOMEM; return -1; @@ -1888,7 +1915,7 @@ static inline int z_vrfy_zsock_poll(struct zsock_pollfd *fds, ret = z_impl_zsock_poll(fds_copy, nfds, timeout); if (ret >= 0) { - z_user_to_copy((void *)fds, fds_copy, fds_size); + k_usermode_to_copy((void *)fds, fds_copy, fds_size); } k_free(fds_copy); @@ -1927,9 +1954,9 @@ static inline int z_vrfy_zsock_inet_pton(sa_family_t family, return -1; } - Z_OOPS(z_user_string_copy(src_copy, (char *)src, sizeof(src_copy))); + K_OOPS(k_usermode_string_copy(src_copy, (char *)src, sizeof(src_copy))); ret = z_impl_zsock_inet_pton(family, src_copy, dst_copy); - Z_OOPS(z_user_to_copy(dst, dst_copy, dst_size)); + K_OOPS(k_usermode_to_copy(dst, dst_copy, dst_size)); return ret; } @@ -1944,6 +1971,17 @@ int zsock_getsockopt_ctx(struct net_context *ctx, int level, int optname, switch (level) { case SOL_SOCKET: switch (optname) { + case SO_ERROR: { + if (*optlen != sizeof(int)) { + errno = EINVAL; + return -1; + } + + *(int *)optval = POINTER_TO_INT(ctx->user_data); + + return 0; + } + case SO_TYPE: { int type = (int)net_context_get_type(ctx); @@ -2012,6 +2050,34 @@ int zsock_getsockopt_ctx(struct net_context *ctx, int level, int optname, return 0; } break; + + case SO_REUSEADDR: + if (IS_ENABLED(CONFIG_NET_CONTEXT_REUSEADDR)) { + ret = net_context_get_option(ctx, + NET_OPT_REUSEADDR, + optval, optlen); + if (ret < 0) { + errno = -ret; + return -1; + } + + return 0; + } + break; + + case SO_REUSEPORT: + if (IS_ENABLED(CONFIG_NET_CONTEXT_REUSEPORT)) { + ret = net_context_get_option(ctx, + NET_OPT_REUSEPORT, + optval, optlen); + if (ret < 0) { + errno = -ret; + return -1; + } + + return 0; + } + break; } break; @@ -2048,6 +2114,22 @@ int zsock_getsockopt_ctx(struct net_context *ctx, int level, int optname, case IPPROTO_IPV6: switch (optname) { + case IPV6_V6ONLY: + if (IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6)) { + ret = net_context_get_option(ctx, + NET_OPT_IPV6_V6ONLY, + optval, + optlen); + if (ret < 0) { + errno = -ret; + return -1; + } + + return 0; + } + + break; + case IPV6_TCLASS: if (IS_ENABLED(CONFIG_NET_CONTEXT_DSCP_ECN)) { ret = net_context_get_option(ctx, @@ -2075,7 +2157,7 @@ int zsock_getsockopt_ctx(struct net_context *ctx, int level, int optname, int z_impl_zsock_getsockopt(int sock, int level, int optname, void *optval, socklen_t *optlen) { - VTABLE_CALL(getsockopt, sock, level, optname, optval, optlen); + return VTABLE_CALL(getsockopt, sock, level, optname, optval, optlen); } #ifdef CONFIG_USERSPACE @@ -2086,20 +2168,20 @@ int z_vrfy_zsock_getsockopt(int sock, int level, int optname, void *kernel_optval; int ret; - if (Z_SYSCALL_MEMORY_WRITE(optval, kernel_optlen)) { + if (K_SYSCALL_MEMORY_WRITE(optval, kernel_optlen)) { errno = -EPERM; return -1; } - kernel_optval = z_user_alloc_from_copy((const void *)optval, + kernel_optval = k_usermode_alloc_from_copy((const void *)optval, kernel_optlen); - Z_OOPS(!kernel_optval); + K_OOPS(!kernel_optval); ret = z_impl_zsock_getsockopt(sock, level, optname, kernel_optval, &kernel_optlen); - Z_OOPS(z_user_to_copy((void *)optval, kernel_optval, kernel_optlen)); - Z_OOPS(z_user_to_copy((void *)optlen, &kernel_optlen, + K_OOPS(k_usermode_to_copy((void *)optval, kernel_optval, kernel_optlen)); + K_OOPS(k_usermode_to_copy((void *)optlen, &kernel_optlen, sizeof(socklen_t))); k_free(kernel_optval); @@ -2148,10 +2230,34 @@ int zsock_setsockopt_ctx(struct net_context *ctx, int level, int optname, break; case SO_REUSEADDR: - /* Ignore for now. Provided to let port - * existing apps. - */ - return 0; + if (IS_ENABLED(CONFIG_NET_CONTEXT_REUSEADDR)) { + ret = net_context_set_option(ctx, + NET_OPT_REUSEADDR, + optval, optlen); + if (ret < 0) { + errno = -ret; + return -1; + } + + return 0; + } + + break; + + case SO_REUSEPORT: + if (IS_ENABLED(CONFIG_NET_CONTEXT_REUSEPORT)) { + ret = net_context_set_option(ctx, + NET_OPT_REUSEPORT, + optval, optlen); + if (ret < 0) { + errno = -ret; + return -1; + } + + return 0; + } + + break; case SO_PRIORITY: if (IS_ENABLED(CONFIG_NET_CONTEXT_PRIORITY)) { @@ -2315,8 +2421,7 @@ int zsock_setsockopt_ctx(struct net_context *ctx, int level, int optname, } } - net_context_set_iface(ctx, iface); - ctx->flags |= NET_CONTEXT_BOUND_TO_IFACE; + net_context_bind_iface(ctx, iface); return 0; } @@ -2361,9 +2466,17 @@ int zsock_setsockopt_ctx(struct net_context *ctx, int level, int optname, case IPPROTO_IPV6: switch (optname) { case IPV6_V6ONLY: - /* Ignore for now. Provided to let port - * existing apps. - */ + if (IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6)) { + ret = net_context_set_option(ctx, + NET_OPT_IPV6_V6ONLY, + optval, + optlen); + if (ret < 0) { + errno = -ret; + return -1; + } + } + return 0; case IPV6_TCLASS: @@ -2393,7 +2506,7 @@ int zsock_setsockopt_ctx(struct net_context *ctx, int level, int optname, int z_impl_zsock_setsockopt(int sock, int level, int optname, const void *optval, socklen_t optlen) { - VTABLE_CALL(setsockopt, sock, level, optname, optval, optlen); + return VTABLE_CALL(setsockopt, sock, level, optname, optval, optlen); } #ifdef CONFIG_USERSPACE @@ -2403,8 +2516,8 @@ int z_vrfy_zsock_setsockopt(int sock, int level, int optname, void *kernel_optval; int ret; - kernel_optval = z_user_alloc_from_copy((const void *)optval, optlen); - Z_OOPS(!kernel_optval); + kernel_optval = k_usermode_alloc_from_copy((const void *)optval, optlen); + K_OOPS(!kernel_optval); ret = z_impl_zsock_setsockopt(sock, level, optname, kernel_optval, optlen); @@ -2467,7 +2580,7 @@ int zsock_getpeername_ctx(struct net_context *ctx, struct sockaddr *addr, int z_impl_zsock_getpeername(int sock, struct sockaddr *addr, socklen_t *addrlen) { - VTABLE_CALL(getpeername, sock, addr, addrlen); + return VTABLE_CALL(getpeername, sock, addr, addrlen); } #ifdef CONFIG_USERSPACE @@ -2477,10 +2590,10 @@ static inline int z_vrfy_zsock_getpeername(int sock, struct sockaddr *addr, socklen_t addrlen_copy; int ret; - Z_OOPS(z_user_from_copy(&addrlen_copy, (void *)addrlen, + K_OOPS(k_usermode_from_copy(&addrlen_copy, (void *)addrlen, sizeof(socklen_t))); - if (Z_SYSCALL_MEMORY_WRITE(addr, addrlen_copy)) { + if (K_SYSCALL_MEMORY_WRITE(addr, addrlen_copy)) { errno = EFAULT; return -1; } @@ -2489,7 +2602,7 @@ static inline int z_vrfy_zsock_getpeername(int sock, struct sockaddr *addr, &addrlen_copy); if (ret == 0 && - z_user_to_copy((void *)addrlen, &addrlen_copy, + k_usermode_to_copy((void *)addrlen, &addrlen_copy, sizeof(socklen_t))) { errno = EINVAL; return -1; @@ -2546,7 +2659,7 @@ int zsock_getsockname_ctx(struct net_context *ctx, struct sockaddr *addr, int z_impl_zsock_getsockname(int sock, struct sockaddr *addr, socklen_t *addrlen) { - VTABLE_CALL(getsockname, sock, addr, addrlen); + return VTABLE_CALL(getsockname, sock, addr, addrlen); } #ifdef CONFIG_USERSPACE @@ -2556,10 +2669,10 @@ static inline int z_vrfy_zsock_getsockname(int sock, struct sockaddr *addr, socklen_t addrlen_copy; int ret; - Z_OOPS(z_user_from_copy(&addrlen_copy, (void *)addrlen, + K_OOPS(k_usermode_from_copy(&addrlen_copy, (void *)addrlen, sizeof(socklen_t))); - if (Z_SYSCALL_MEMORY_WRITE(addr, addrlen_copy)) { + if (K_SYSCALL_MEMORY_WRITE(addr, addrlen_copy)) { errno = EFAULT; return -1; } @@ -2568,7 +2681,7 @@ static inline int z_vrfy_zsock_getsockname(int sock, struct sockaddr *addr, &addrlen_copy); if (ret == 0 && - z_user_to_copy((void *)addrlen, &addrlen_copy, + k_usermode_to_copy((void *)addrlen, &addrlen_copy, sizeof(socklen_t))) { errno = EINVAL; return -1; diff --git a/subsys/net/lib/sockets/sockets_can.c b/subsys/net/lib/sockets/sockets_can.c index 5e05440d2c0..d4856a7a4be 100644 --- a/subsys/net/lib/sockets/sockets_can.c +++ b/subsys/net/lib/sockets/sockets_can.c @@ -21,7 +21,7 @@ LOG_MODULE_REGISTER(net_sock_can, CONFIG_NET_SOCKETS_LOG_LEVEL); #include #include #include -#include +#include #include #include #include diff --git a/subsys/net/lib/sockets/sockets_internal.h b/subsys/net/lib/sockets/sockets_internal.h index 12bf1f518e3..9398608b4d0 100644 --- a/subsys/net/lib/sockets/sockets_internal.h +++ b/subsys/net/lib/sockets/sockets_internal.h @@ -78,4 +78,56 @@ struct socket_op_vtable { size_t msghdr_non_empty_iov_count(const struct msghdr *msg); +#if defined(CONFIG_NET_SOCKETS_OBJ_CORE) +int sock_obj_core_alloc(int sock, struct net_socket_register *reg, + int family, int type, int proto); +int sock_obj_core_alloc_find(int sock, int new_sock, int family, int type); +int sock_obj_core_dealloc(int sock); +void sock_obj_core_update_send_stats(int sock, int bytes); +void sock_obj_core_update_recv_stats(int sock, int bytes); +#else +static inline int sock_obj_core_alloc(int sock, + struct net_socket_register *reg, + int family, int type, int proto) +{ + ARG_UNUSED(sock); + ARG_UNUSED(reg); + ARG_UNUSED(family); + ARG_UNUSED(type); + ARG_UNUSED(proto); + + return -ENOTSUP; +} + +static inline int sock_obj_core_alloc_find(int sock, int new_sock, + int family, int type) +{ + ARG_UNUSED(sock); + ARG_UNUSED(new_sock); + ARG_UNUSED(family); + ARG_UNUSED(type); + + return -ENOTSUP; +} + +static inline int sock_obj_core_dealloc(int sock) +{ + ARG_UNUSED(sock); + + return -ENOTSUP; +} + +static inline void sock_obj_core_update_send_stats(int sock, int bytes) +{ + ARG_UNUSED(sock); + ARG_UNUSED(bytes); +} + +static inline void sock_obj_core_update_recv_stats(int sock, int bytes) +{ + ARG_UNUSED(sock); + ARG_UNUSED(bytes); +} +#endif /* CONFIG_NET_SOCKETS_OBJ_CORE */ + #endif /* _SOCKETS_INTERNAL_H_ */ diff --git a/subsys/net/lib/sockets/sockets_misc.c b/subsys/net/lib/sockets/sockets_misc.c index 9729fca19fb..fb3750e110a 100644 --- a/subsys/net/lib/sockets/sockets_misc.c +++ b/subsys/net/lib/sockets/sockets_misc.c @@ -6,7 +6,7 @@ #include #include -#include +#include int z_impl_zsock_gethostname(char *buf, size_t len) { @@ -20,7 +20,7 @@ int z_impl_zsock_gethostname(char *buf, size_t len) #ifdef CONFIG_USERSPACE static inline int z_vrfy_zsock_gethostname(char *buf, size_t len) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(buf, len)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(buf, len)); return z_impl_zsock_gethostname(buf, len); } #include diff --git a/subsys/net/lib/sockets/sockets_net_mgmt.c b/subsys/net/lib/sockets/sockets_net_mgmt.c index daccfdf40a6..11b06b8863f 100644 --- a/subsys/net/lib/sockets/sockets_net_mgmt.c +++ b/subsys/net/lib/sockets/sockets_net_mgmt.c @@ -17,7 +17,7 @@ LOG_MODULE_REGISTER(net_sock_mgmt, CONFIG_NET_SOCKETS_LOG_LEVEL); #include #include #include -#include +#include #include #include #include @@ -209,8 +209,12 @@ static ssize_t znet_mgmt_recvfrom(struct net_mgmt_socket *mgmt, void *buf, if (info) { ret = info_len + sizeof(hdr); - ret = MIN(max_len, ret); - memcpy(©_to[sizeof(hdr)], info, ret); + if (ret > max_len) { + errno = EMSGSIZE; + return -1; + } + + memcpy(©_to[sizeof(hdr)], info, info_len); } else { ret = 0; } diff --git a/subsys/net/lib/sockets/sockets_packet.c b/subsys/net/lib/sockets/sockets_packet.c index 1d3d47975d9..bcf063abe29 100644 --- a/subsys/net/lib/sockets/sockets_packet.c +++ b/subsys/net/lib/sockets/sockets_packet.c @@ -22,7 +22,7 @@ LOG_MODULE_REGISTER(net_sock_packet, CONFIG_NET_SOCKETS_LOG_LEVEL); #include #include #include -#include +#include #include #include "../../ip/net_stats.h" diff --git a/subsys/net/lib/sockets/sockets_select.c b/subsys/net/lib/sockets/sockets_select.c index c6d110bad07..af88e51e758 100644 --- a/subsys/net/lib/sockets/sockets_select.c +++ b/subsys/net/lib/sockets/sockets_select.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include #include "sockets_internal.h" @@ -196,6 +196,11 @@ int z_impl_zsock_select(int nfds, zsock_fd_set *readfds, zsock_fd_set *writefds, ZSOCK_FD_SET(fd, exceptfds); num_selects++; } + + if (writefds != NULL) { + ZSOCK_FD_SET(fd, writefds); + num_selects++; + } } res--; @@ -216,7 +221,7 @@ static int z_vrfy_zsock_select(int nfds, zsock_fd_set *readfds, int ret = -1; if (readfds) { - readfds_copy = z_user_alloc_from_copy((void *)readfds, + readfds_copy = k_usermode_alloc_from_copy((void *)readfds, sizeof(zsock_fd_set)); if (!readfds_copy) { errno = ENOMEM; @@ -225,7 +230,7 @@ static int z_vrfy_zsock_select(int nfds, zsock_fd_set *readfds, } if (writefds) { - writefds_copy = z_user_alloc_from_copy((void *)writefds, + writefds_copy = k_usermode_alloc_from_copy((void *)writefds, sizeof(zsock_fd_set)); if (!writefds_copy) { errno = ENOMEM; @@ -234,7 +239,7 @@ static int z_vrfy_zsock_select(int nfds, zsock_fd_set *readfds, } if (exceptfds) { - exceptfds_copy = z_user_alloc_from_copy((void *)exceptfds, + exceptfds_copy = k_usermode_alloc_from_copy((void *)exceptfds, sizeof(zsock_fd_set)); if (!exceptfds_copy) { errno = ENOMEM; @@ -243,7 +248,7 @@ static int z_vrfy_zsock_select(int nfds, zsock_fd_set *readfds, } if (timeout) { - timeval = z_user_alloc_from_copy((void *)timeout, + timeval = k_usermode_alloc_from_copy((void *)timeout, sizeof(struct zsock_timeval)); if (!timeval) { errno = ENOMEM; @@ -256,17 +261,17 @@ static int z_vrfy_zsock_select(int nfds, zsock_fd_set *readfds, if (ret >= 0) { if (readfds_copy) { - z_user_to_copy((void *)readfds, readfds_copy, + k_usermode_to_copy((void *)readfds, readfds_copy, sizeof(zsock_fd_set)); } if (writefds_copy) { - z_user_to_copy((void *)writefds, writefds_copy, + k_usermode_to_copy((void *)writefds, writefds_copy, sizeof(zsock_fd_set)); } if (exceptfds_copy) { - z_user_to_copy((void *)exceptfds, exceptfds_copy, + k_usermode_to_copy((void *)exceptfds, exceptfds_copy, sizeof(zsock_fd_set)); } } diff --git a/subsys/net/lib/sockets/sockets_tls.c b/subsys/net/lib/sockets/sockets_tls.c index f77bf51d668..c83d2c18b80 100644 --- a/subsys/net/lib/sockets/sockets_tls.c +++ b/subsys/net/lib/sockets/sockets_tls.c @@ -18,8 +18,8 @@ LOG_MODULE_REGISTER(net_sock_tls, CONFIG_NET_SOCKETS_LOG_LEVEL); #include #include #include -#include -#include +#include +#include #include /* TODO: Remove all direct access to private fields. @@ -272,7 +272,7 @@ static int tls_ctr_drbg_random(void *ctx, unsigned char *buf, size_t len) { ARG_UNUSED(ctx); -#if defined(CONFIG_ENTROPY_HAS_DRIVER) +#if defined(CONFIG_CSPRNG_ENABLED) return sys_csrand_get(buf, len); #else sys_rand_get(buf, len); @@ -602,7 +602,7 @@ static int tls_session_save(const struct sockaddr *peer_addr, ret = mbedtls_ssl_session_save(session, entry->session, session_len, &session_len); if (ret < 0) { - NET_ERR("Failed to serialize session, err: 0x%x.", -ret); + NET_ERR("Failed to serialize session, err: -0x%x.", -ret); mbedtls_free(entry->session); entry->session = NULL; return -ENOMEM; @@ -1231,7 +1231,7 @@ static int tls_mbedtls_handshake(struct tls_context *context, /* MbedTLS API documentation requires session to * be reset in other error cases */ - NET_ERR("TLS handshake error: -%x", -ret); + NET_ERR("TLS handshake error: -0x%x", -ret); ret = tls_mbedtls_reset(context); if (ret == 0) { ret = -ECONNABORTED; @@ -1240,7 +1240,7 @@ static int tls_mbedtls_handshake(struct tls_context *context, } /* Avoid constant loop if tls_mbedtls_reset fails */ - NET_ERR("TLS reset error: -%x", -ret); + NET_ERR("TLS reset error: -0x%x", -ret); ret = -ECONNABORTED; break; } @@ -1681,7 +1681,7 @@ static int tls_opt_dtls_connection_id_set(struct tls_context *context, context->options.dtls_cid.enabled = true; if (context->options.dtls_cid.cid_len == 0) { /* generate random self cid */ -#if defined(CONFIG_ENTROPY_HAS_DRIVER) +#if defined(CONFIG_CSPRNG_ENABLED) sys_csrand_get(context->options.dtls_cid.cid, MBEDTLS_SSL_CID_OUT_LEN_MAX); #else diff --git a/subsys/net/lib/tftp/tftp_client.c b/subsys/net/lib/tftp/tftp_client.c index fc3cd2b70d9..c6f9a371d6b 100644 --- a/subsys/net/lib/tftp/tftp_client.c +++ b/subsys/net/lib/tftp/tftp_client.c @@ -155,8 +155,14 @@ static inline int send_err(int sock, struct tftpc *client, int err_code, char *e /* Copy the Error String. */ if (err_msg != NULL) { - strcpy(client->tftp_buf + req_size, err_msg); - req_size += strlen(err_msg); + size_t copy_len = strlen(err_msg); + + if (copy_len > sizeof(client->tftp_buf) - req_size) { + copy_len = sizeof(client->tftp_buf) - req_size; + } + + memcpy(client->tftp_buf + req_size, err_msg, copy_len); + req_size += copy_len; } /* Send Error to server. */ @@ -222,7 +228,11 @@ static int send_request(int sock, struct tftpc *client, } /* Limit communication to the specific address:port */ - connect(sock, &from_addr, from_addr_len); + if (connect(sock, &from_addr, from_addr_len) < 0) { + ret = -errno; + LOG_ERR("connect failed, err %d", ret); + break; + } break; @@ -293,7 +303,10 @@ int tftp_get(struct tftpc *client, const char *remote_file, const char *mode) if (client->callback == NULL) { LOG_ERR("No callback defined."); - send_err(sock, client, TFTP_ERROR_DISK_FULL, NULL); + if (send_err(sock, client, TFTP_ERROR_DISK_FULL, NULL) < 0) { + LOG_ERR("Failed to send error response, err: %d", + -errno); + } ret = TFTPC_BUFFER_OVERFLOW; goto get_end; } diff --git a/subsys/net/lib/tls_credentials/CMakeLists.txt b/subsys/net/lib/tls_credentials/CMakeLists.txt index 8df3593b994..490a558953d 100644 --- a/subsys/net/lib/tls_credentials/CMakeLists.txt +++ b/subsys/net/lib/tls_credentials/CMakeLists.txt @@ -1,9 +1,17 @@ # SPDX-License-Identifier: Apache-2.0 -zephyr_include_directories(.) -zephyr_sources_ifdef(CONFIG_TLS_CREDENTIALS_BACKEND_VOLATILE +zephyr_library_include_directories(.) + +zephyr_library_sources_ifdef(CONFIG_TLS_CREDENTIALS_BACKEND_VOLATILE tls_credentials.c + tls_credentials_digest_raw.c ) -zephyr_sources_ifdef(CONFIG_TLS_CREDENTIALS_BACKEND_PROTECTED_STORAGE +zephyr_library_sources_ifdef(CONFIG_TLS_CREDENTIALS_BACKEND_PROTECTED_STORAGE tls_credentials_trusted.c + tls_credentials_digest_raw.c +) +zephyr_library_sources_ifdef(CONFIG_TLS_CREDENTIALS_SHELL + tls_credentials_shell.c ) + +zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS) diff --git a/subsys/net/lib/tls_credentials/Kconfig b/subsys/net/lib/tls_credentials/Kconfig index 94ecc8287c6..58ec0949d47 100644 --- a/subsys/net/lib/tls_credentials/Kconfig +++ b/subsys/net/lib/tls_credentials/Kconfig @@ -54,4 +54,6 @@ config TLS_CREDENTIAL_FILENAMES This option is currently only available for secure socket offload devices. +source "subsys/net/lib/tls_credentials/Kconfig.shell" + endif # TLS_CREDENTIALS diff --git a/subsys/net/lib/tls_credentials/Kconfig.shell b/subsys/net/lib/tls_credentials/Kconfig.shell new file mode 100644 index 00000000000..3e20f6e7717 --- /dev/null +++ b/subsys/net/lib/tls_credentials/Kconfig.shell @@ -0,0 +1,35 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +menuconfig TLS_CREDENTIALS_SHELL + bool "TLS credentials management shell" + depends on TLS_CREDENTIALS + depends on SHELL + depends on BASE64 + help + Enable shell commands to manage TLS credentials. + +if TLS_CREDENTIALS_SHELL + +config TLS_CREDENTIALS_SHELL_CRED_BUF_SIZE + int "Size of buffer used for storing and retrieving credentials, measured in bytes." + default 1024 + help + The amount of preallocated buffer (in bytes) used for storing and retrieving credentials. + +config TLS_CREDENTIALS_SHELL_CRED_OUTPUT_WIDTH + int "Credential output line width (characters)" + default 32 + help + This setting specifies how long (in characters) contiguous lines of base64 credential + output should be. Must be a multiple of 4. Applies only to ??? mode. + +config TLS_CREDENTIALS_SHELL_DIGEST_BUF_SIZE + int "Buffer for generating credentials digests" + default 48 + help + The amount of preallocated buffer (in bytes) for temporarily storing credential digests. + + Also used to print error messages if digest generation fails. + +endif # TLS_CREDENTIALS_SHELL diff --git a/subsys/net/lib/tls_credentials/tls_credentials.c b/subsys/net/lib/tls_credentials/tls_credentials.c index 133d2967160..94f4d9c5cd5 100644 --- a/subsys/net/lib/tls_credentials/tls_credentials.c +++ b/subsys/net/lib/tls_credentials/tls_credentials.c @@ -9,6 +9,7 @@ #include #include "tls_internal.h" +#include "tls_credentials_digest_raw.h" /* Global pool of credentials shared among TLS contexts. */ static struct tls_credential credentials[CONFIG_TLS_MAX_CREDENTIALS_NUMBER]; @@ -74,6 +75,37 @@ struct tls_credential *credential_next_get(sec_tag_t tag, return NULL; } +sec_tag_t credential_next_tag_get(sec_tag_t iter) +{ + int i; + sec_tag_t lowest = TLS_SEC_TAG_NONE; + + /* Scan all slots and find lowest sectag greater than iter */ + for (i = 0; i < ARRAY_SIZE(credentials); i++) { + /* Skip empty slots. */ + if (credentials[i].type == TLS_CREDENTIAL_NONE) { + continue; + } + + /* Skip any slots containing sectags not greater than iter */ + if (credentials[i].tag <= iter && iter != TLS_SEC_TAG_NONE) { + continue; + } + + /* Find the lowest of such slots */ + if (lowest == TLS_SEC_TAG_NONE || credentials[i].tag < lowest) { + lowest = credentials[i].tag; + } + } + + return lowest; +} + +int credential_digest(struct tls_credential *credential, void *dest, size_t *len) +{ + return credential_digest_raw(credential, dest, len); +} + void credentials_lock(void) { k_mutex_lock(&credential_lock, K_FOREVER); diff --git a/subsys/net/lib/tls_credentials/tls_credentials_digest_raw.c b/subsys/net/lib/tls_credentials/tls_credentials_digest_raw.c new file mode 100644 index 00000000000..2013c5d52fb --- /dev/null +++ b/subsys/net/lib/tls_credentials/tls_credentials_digest_raw.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +/* This file provides an (internal-use-only) credential digest function that backends storing + * raw credentials can use. + */ + +#include + +#include +#include +#include "tls_internal.h" +#include "tls_credentials_digest_raw.h" + +/* Grab mbedTLS headers if they are available so that we can check whether SHA256 is supported */ + +#if defined(CONFIG_MBEDTLS) +#if !defined(CONFIG_MBEDTLS_CFG_FILE) +#include "mbedtls/config.h" +#else +#include CONFIG_MBEDTLS_CFG_FILE +#endif /* CONFIG_MBEDTLS_CFG_FILE */ +#endif /* CONFIG_MBEDTLS */ + +#if defined(CONFIG_TINYCRYPT_SHA256) && defined(CONFIG_BASE64) + +#include +#include + +int credential_digest_raw(struct tls_credential *credential, void *dest, size_t *len) +{ + int err = 0; + size_t written = 0; + struct tc_sha256_state_struct sha_state; + uint8_t digest_buf[TC_SHA256_DIGEST_SIZE]; + + /* Compute digest. */ + (void)tc_sha256_init(&sha_state); + (void)tc_sha256_update(&sha_state, credential->buf, credential->len); + (void)tc_sha256_final(digest_buf, &sha_state); + + /* Attempt to encode digest to destination. + * Will return -ENOMEM if there is not enough space in the destination buffer. + */ + err = base64_encode(dest, *len, &written, digest_buf, sizeof(digest_buf)); + *len = err ? 0 : written; + + /* Clean up. */ + memset(&sha_state, 0, sizeof(sha_state)); + memset(digest_buf, 0, sizeof(digest_buf)); + return err; +} + +#elif defined(MBEDTLS_SHA256_C) && defined(CONFIG_BASE64) + +#include +#include + +int credential_digest_raw(struct tls_credential *credential, void *dest, size_t *len) +{ + int err = 0; + size_t written = 0; + uint8_t digest_buf[32]; + + /* Compute digest. The '0' indicates to mbedtls to use SHA256 instead of 224. */ + mbedtls_sha256(credential->buf, credential->len, digest_buf, 0); + + /* Attempt to encode digest to destination. + * Will return -ENOMEM if there is not enough space in the destination buffer. + */ + err = base64_encode(dest, *len, &written, digest_buf, sizeof(digest_buf)); + *len = err ? 0 : written; + + /* Clean up. */ + memset(digest_buf, 0, sizeof(digest_buf)); + + return err; +} + +#else + +int credential_digest_raw(struct tls_credential *credential, void *dest, size_t *len) +{ + *len = 0; + return -ENOTSUP; +} + +#endif diff --git a/subsys/net/lib/tls_credentials/tls_credentials_digest_raw.h b/subsys/net/lib/tls_credentials/tls_credentials_digest_raw.h new file mode 100644 index 00000000000..8b39a9cba98 --- /dev/null +++ b/subsys/net/lib/tls_credentials/tls_credentials_digest_raw.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** @file + * @brief Internal helper function for generating digests for raw credentials. + */ + +#ifndef __TLS_DIGEST_RAW_H +#define __TLS_DIGEST_RAW_H + +#include +#include "tls_internal.h" + +/* Common version of credential_digest that raw credentials backends can use. */ +int credential_digest_raw(struct tls_credential *credential, void *dest, size_t *len); + +#endif /* __TLS_DIGEST_RAW_H */ diff --git a/subsys/net/lib/tls_credentials/tls_credentials_shell.c b/subsys/net/lib/tls_credentials/tls_credentials_shell.c new file mode 100644 index 00000000000..1b06520466b --- /dev/null +++ b/subsys/net/lib/tls_credentials/tls_credentials_shell.c @@ -0,0 +1,811 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_REGISTER(tls_credentials_shell, CONFIG_TLS_CREDENTIALS_LOG_LEVEL); + +#include +#include +#include +#include +#include "tls_internal.h" +#include +#include +#include + +enum cred_storage_fmt { + /* Credential is stored as a string and will be passed between the shell and storage + * unmodified. + */ + CRED_STORAGE_FMT_STRING, + + /* Credential is stored as raw binary, and is parsed from base64 before storage and encoded + * back into base64 when retrieved via the shell. + */ + CRED_STORAGE_FMT_BINARY, +}; + +struct cred_type_string { + char *name; + enum tls_credential_type type; +}; + +/* The first entry in each credential type group will be used for human-readable shell + * output. The last will be used for compact shell output. The rest are accepted synonyms. + */ +static const struct cred_type_string type_strings[] = { + {"CA_CERT", TLS_CREDENTIAL_CA_CERTIFICATE}, + {"CA", TLS_CREDENTIAL_CA_CERTIFICATE}, + + {"SERVER_CERT", TLS_CREDENTIAL_SERVER_CERTIFICATE}, + {"CLIENT_CERT", TLS_CREDENTIAL_SERVER_CERTIFICATE}, + {"SELF_CERT", TLS_CREDENTIAL_SERVER_CERTIFICATE}, + {"SELF", TLS_CREDENTIAL_SERVER_CERTIFICATE}, + {"CLIENT", TLS_CREDENTIAL_SERVER_CERTIFICATE}, + {"SERV", TLS_CREDENTIAL_SERVER_CERTIFICATE}, + + {"PRIVATE_KEY", TLS_CREDENTIAL_PRIVATE_KEY}, + {"PK", TLS_CREDENTIAL_PRIVATE_KEY}, + + {"PRE_SHARED_KEY", TLS_CREDENTIAL_PSK}, + {"PSK", TLS_CREDENTIAL_PSK}, + + {"PRE_SHARED_KEY_ID", TLS_CREDENTIAL_PSK_ID}, + {"PSK_ID", TLS_CREDENTIAL_PSK_ID} +}; + +#define ANY_KEYWORD "any" + +/* This is so that we can output base64 in chunks of this length if necessary */ +BUILD_ASSERT( + (CONFIG_TLS_CREDENTIALS_SHELL_CRED_OUTPUT_WIDTH % 4) == 0, + "CONFIG_TLS_CREDENTIALS_SHELL_CRED_OUTPUT_WIDTH must be a multiple of 4." +); + +/* Output buffers used for printing credentials and digests. + * One extra byte included for NULL termination. + */ +static char cred_out_buf[CONFIG_TLS_CREDENTIALS_SHELL_CRED_OUTPUT_WIDTH + 1]; +static char cred_digest_buf[CONFIG_TLS_CREDENTIALS_SHELL_DIGEST_BUF_SIZE + 1]; + +/* Internal buffer used for storing and retrieving credentials. + * +1 byte for potential NULL termination. + */ +static char cred_buf[CONFIG_TLS_CREDENTIALS_SHELL_CRED_BUF_SIZE + 1]; +static size_t cred_written; + +/* Some backends (namely, the volatile backend) store a reference rather than a copy of passed-in + * credentials. For these backends, we need to copy incoming credentials onto the heap before + * attempting to store them. + * + * Since the backend in use is determined at build time by KConfig, so is this behavior. + * If multi/dynamic-backend support is ever added, this will need to be updated. + */ +#define COPY_CREDENTIALS_TO_HEAP CONFIG_TLS_CREDENTIALS_BACKEND_VOLATILE + +/* Used to track credentials that have been copied permanently to the heap, in case they are + * ever deleted and need to be freed. + */ +static void *cred_refs[CONFIG_TLS_MAX_CREDENTIALS_NUMBER]; + +/* Find an empty slot in the cred_refs array, or return -1 if none exists. + * Pass NULL to find an unused slot. + */ +static int find_ref_slot(const void *const cred) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(cred_refs); i++) { + if (cred_refs[i] == cred) { + return i; + } + } + + return -1; +} + +/* Helpers */ + +/* Filter out non-printable characters from a passed-in string of known length */ +static int filter_nonprint(char *buf, size_t len, char inval) +{ + int i; + int ret = 0; + + for (i = 0; i < len; i++) { + if (!isprint((int)buf[i])) { + buf[i] = inval; + ret = -EINVAL; + } + } + + return ret; +} + +/* Verify that a provided string consists only of the characters 0-9*/ +static bool check_numeric(char *str) +{ + int i; + int len = strlen(str); + + for (i = 0; i < len; i++) { + if (!isdigit((int)str[i])) { + return false; + } + } + + return true; +} + +/* Clear the credential write buffer, returns true if anything was actually cleared. */ +static bool cred_buf_clear(void) +{ + bool cleared = cred_written != 0; + + (void)memset(cred_buf, 0, sizeof(cred_buf)); + cred_written = 0; + + return cleared; +} + +/* Parse a (possibly incomplete) chunk into the credential buffer */ +static int cred_buf_write(char *chunk) +{ + char *writehead = cred_buf + cred_written; + size_t chunk_len = strlen(chunk); + + /* Verify that there is room for the incoming chunk */ + if ((writehead + chunk_len) >= (cred_buf + sizeof(cred_buf) - 1)) { + return -ENOMEM; + } + + /* Append chunk to the credential buffer. + * Deliberately do not copy NULL terminator. + */ + memcpy(writehead, chunk, chunk_len); + cred_written += chunk_len; + + return chunk_len; +} + +/* Get the human-readable name of a TLS credential type */ +static const char *cred_type_name(enum tls_credential_type type) +{ + /* Scan over predefined type strings, and return the name + * of the first one of matching type. + */ + for (int i = 0; i < ARRAY_SIZE(type_strings); i++) { + if (type_strings[i].type == type) { + return type_strings[i].name; + } + } + + /* No matches found, it's invalid. */ + return "INVALID"; +} + +/* Get the compact name of a TLS credential type*/ +static const char *cred_type_name_compact(enum tls_credential_type type) +{ + /* Scan over predefined type strings, and return the name + * of the last one of matching type. + */ + for (int i = ARRAY_SIZE(type_strings) - 1; i >= 0; i--) { + if (type_strings[i].type == type) { + return type_strings[i].name; + } + } + + /* No matches found, it's invalid. */ + return "INV"; +} + +/* Shell interface routines */ + +/* Attempt to parse a command line argument into a sectag. + * TLS_SEC_TAG_NONE is returned if ANY_KEYWORD is provided. + */ +static int shell_parse_cred_sectag(const struct shell *sh, char *arg, sec_tag_t *out, + bool allow_any) +{ + unsigned long sectag_value; + int err = 0; + + /* Check for "ANY" special keyword if desired. */ + if (allow_any && strcasecmp(arg, ANY_KEYWORD) == 0) { + *out = TLS_SEC_TAG_NONE; + return 0; + } + + /* Otherwise, verify that the sectag is purely numeric */ + if (!check_numeric(arg)) { + err = -EINVAL; + goto error; + } + + /* Use strtoul because it has nicer validation features than atoi */ + sectag_value = shell_strtoul(arg, 10, &err); + + if (!err) { + *out = (sec_tag_t)sectag_value; + return 0; + } + +error: + shell_fprintf(sh, SHELL_ERROR, "%s is not a valid sectag.\n", arg); + return err; +} + +/* Attempt to parse a command line argument into a credential type. + * TLS_CREDENTIAL_NONE is returned if ANY_KEYWORD is provided. + */ +static int shell_parse_cred_type(const struct shell *sh, char *arg, enum tls_credential_type *out, + bool allow_any) +{ + /* Check for "ANY" special keyword if desired. */ + if (allow_any && strcasecmp(arg, ANY_KEYWORD) == 0) { + *out = TLS_CREDENTIAL_NONE; + return 0; + } + + /* Otherwise, scan over predefined type strings, and return the corresponding + * credential type if one is found + */ + for (int i = 0; i < ARRAY_SIZE(type_strings); i++) { + if (strcasecmp(arg, type_strings[i].name) == 0) { + *out = type_strings[i].type; + return 0; + } + } + + /* No matches found, it's invalid. */ + shell_fprintf(sh, SHELL_ERROR, "%s is not a valid credential type.\n", arg); + + return -EINVAL; +} + +/* Parse a backend specifier argument + * Right now, only a single backend is supported, so this is serving simply as a reserved argument. + * As such, the only valid input is "default" + */ +static int shell_parse_cred_backend(const struct shell *sh, char *arg) +{ + if (strcasecmp(arg, "default") == 0) { + return 0; + } + + shell_fprintf(sh, SHELL_ERROR, "%s is not a valid backend.\n", arg); + + return -EINVAL; +} + +/* Parse an input type specifier */ +static int shell_parse_cred_storage_format(const struct shell *sh, char *arg, + enum cred_storage_fmt *out, bool *terminated) +{ + if (strcasecmp(arg, "bin") == 0) { + *out = CRED_STORAGE_FMT_BINARY; + *terminated = false; + return 0; + } + + if (strcasecmp(arg, "bint") == 0) { + *out = CRED_STORAGE_FMT_BINARY; + *terminated = true; + return 0; + } + + if (strcasecmp(arg, "str") == 0) { + *out = CRED_STORAGE_FMT_STRING; + *terminated = false; + return 0; + } + + if (strcasecmp(arg, "strt") == 0) { + *out = CRED_STORAGE_FMT_STRING; + *terminated = true; + return 0; + } + + shell_fprintf(sh, SHELL_ERROR, "%s is not a valid storage format.\n", arg); + + return -EINVAL; +} + +/* Clear credential buffer, with shell feedback */ +static void shell_clear_cred_buf(const struct shell *sh) +{ + /* We will only print a message if some data was actually wiped. */ + if (cred_buf_clear()) { + shell_fprintf(sh, SHELL_NORMAL, "Credential buffer cleared.\n"); + } +} + +/* Write data into the credential buffer, with shell feedback. */ +static int shell_write_cred_buf(const struct shell *sh, char *chunk) +{ + int res = cred_buf_write(chunk); + + /* Report results. */ + + if (res == -ENOMEM) { + shell_fprintf(sh, SHELL_ERROR, "Not enough room in credential buffer for " + "provided data. Increase " + "CONFIG_TLS_CREDENTIALS_SHELL_CRED_BUF_SIZE.\n"); + shell_clear_cred_buf(sh); + return -ENOMEM; + } + + shell_fprintf(sh, SHELL_NORMAL, "Stored %d bytes.\n", res); + + return 0; +} + +/* Adds a credential to the credential store */ +static int tls_cred_cmd_add(const struct shell *sh, size_t argc, char *argv[]) +{ + int err = 0; + sec_tag_t sectag; + enum cred_storage_fmt format; + bool terminated; + enum tls_credential_type type; + void *cred_copy = NULL; + void *cred_chosen = NULL; + bool keep_copy = false; + int ref_slot = -1; + + /* Lock credentials so that we can interact with them directly. + * Mainly this is required by credential_get. + */ + + credentials_lock(); + + err = shell_parse_cred_sectag(sh, argv[1], §ag, false); + if (err) { + goto cleanup; + } + + err = shell_parse_cred_type(sh, argv[2], &type, false); + if (err) { + goto cleanup; + } + + err = shell_parse_cred_backend(sh, argv[3]); + if (err) { + goto cleanup; + } + + err = shell_parse_cred_storage_format(sh, argv[4], &format, &terminated); + if (err) { + goto cleanup; + } + + if (argc == 6) { + /* Credential was passed, clear credential buffer and then use the passed-in + * credential. + */ + shell_clear_cred_buf(sh); + err = shell_write_cred_buf(sh, argv[5]); + if (err) { + goto cleanup; + } + } + + /* Make sure the credential buffer isn't empty. */ + if (cred_written == 0) { + shell_fprintf(sh, SHELL_ERROR, "Please provide a credential to add.\n"); + err = -ENOENT; + goto cleanup; + } + + /* Check whether a credential of this type and sectag already exists. */ + if (credential_get(sectag, type)) { + shell_fprintf(sh, SHELL_ERROR, "TLS credential with sectag %d and type %s " + "already exists.\n", sectag, cred_type_name(type)); + err = -EEXIST; + goto cleanup; + } + + /* If binary format was specified, decode from base64. */ + if (format == CRED_STORAGE_FMT_BINARY) { + /* base64_decode can handle in-place operation. + * Pass &cred_written as olen so that it is updated to match the size of the base64 + * encoding. + * + * We use sizeof(cred_buf) - 1 since we want to keep room fors a NULL terminator. + * Though, technically, this is not actually needed since the output of + * base64_decode is always shorter than its input. + */ + err = base64_decode(cred_buf, sizeof(cred_buf) - 1, &cred_written, + cred_buf, cred_written); + if (err) { + shell_fprintf(sh, SHELL_ERROR, "Could not decode input from base64, " + "error: %d\n", err); + err = -EINVAL; + goto cleanup; + } + } + + /* If NULL termination was requested, append one. + * We are always guaranteed to have room in the buffer for this. + */ + if (terminated) { + cred_buf[cred_written] = 0; + cred_written += 1; + } + + /* Default to using cred_buf directly. */ + cred_chosen = cred_buf; + + /* If the currently active TLS Credentials backend stores credentials by reference, + * copy the incoming credentials off to the heap, and then use this copy instead. + */ + if (IS_ENABLED(COPY_CREDENTIALS_TO_HEAP)) { + /* Before copying the credential to heap, make sure we are able to store a + * reference to it so that it can be freed if the credential is ever deleted. + */ + + ref_slot = find_ref_slot(NULL); + + if (ref_slot < 0) { + shell_fprintf(sh, SHELL_ERROR, "No reference slot available, cannot copy " + "credential to heap. Credential will not be " + "stored\n"); + err = -ENOMEM; + goto cleanup; + } + + cred_copy = k_malloc(cred_written); + if (!cred_copy) { + shell_fprintf(sh, SHELL_ERROR, "Not enough heap for TLS credential of " + "size %d.\n", cred_written); + err = -ENOMEM; + goto cleanup; + } + + memset(cred_copy, 0, cred_written); + memcpy(cred_copy, cred_buf, cred_written); + + shell_fprintf(sh, SHELL_WARNING, "Credential has been copied to heap. Memory will " + "be leaked if this credential is deleted without " + "using the shell.\n"); + + cred_chosen = cred_copy; + } + + /* Finally, store the credential in whatever credentials backend is active. */ + err = tls_credential_add(sectag, type, cred_chosen, cred_written); + if (err) { + shell_fprintf(sh, SHELL_ERROR, "Failed to add TLS credential with sectag %d and " + "type %s. Error: %d\n.", sectag, + cred_type_name(type), err); + goto cleanup; + } + + /* Do not free the copied key during cleanup, since it was successfully written. */ + keep_copy = true; + + shell_fprintf(sh, SHELL_NORMAL, "Added TLS credential of type %s, sectag %d, and length %d " + "bytes.\n", cred_type_name(type), sectag, cred_written); + +cleanup: + /* Unlock credentials since we are done interacting with internal state. */ + credentials_unlock(); + + /* We are also done with the credentials buffer, so clear it for good measure. */ + shell_clear_cred_buf(sh); + + /* If we copied the credential, make sure it is eventually freed. */ + if (cred_copy) { + if (keep_copy) { + /* If the credential was successfully stored, keep a reference to it in case + * it is ever deleted and needs to be freed. + */ + cred_refs[ref_slot] = cred_copy; + } else { + /* Otherwise, clear and free it immediately */ + memset(cred_copy, 0, cred_written); + (void)k_free(cred_copy); + } + } + + return err; +} + +/* Buffers credential data into the credential buffer. */ +static int tls_cred_cmd_buf(const struct shell *sh, size_t argc, char *argv[]) +{ + /* If the "clear" keyword is provided, clear the buffer rather than write to it. */ + if (strcmp(argv[1], "clear") == 0) { + shell_clear_cred_buf(sh); + return 0; + } + + /* Otherwise, assume provided arg is base64 and attempt to write it into the credential + * buffer. + */ + return shell_write_cred_buf(sh, argv[1]); +} + +/* Deletes a credential from the credential store */ +static int tls_cred_cmd_del(const struct shell *sh, size_t argc, char *argv[]) +{ + int err = 0; + sec_tag_t sectag; + enum tls_credential_type type; + struct tls_credential *cred = NULL; + int ref_slot = -1; + + /* Lock credentials so that we can safely use internal access functions. */ + credentials_lock(); + + err = shell_parse_cred_sectag(sh, argv[1], §ag, false); + if (err) { + goto cleanup; + } + + err = shell_parse_cred_type(sh, argv[2], &type, false); + if (err) { + goto cleanup; + } + + /* Check whether a credential of this type and sectag actually exists. */ + cred = credential_get(sectag, type); + if (!cred) { + shell_fprintf(sh, SHELL_ERROR, "There is no TLS credential with sectag %d and " + "type %s.\n", sectag, cred_type_name(type)); + err = -ENOENT; + goto cleanup; + } + + ref_slot = find_ref_slot(cred->buf); + if (ref_slot >= 0) { + /* This was a credential we copied to heap. Clear and free it. */ + memset((void *)cred_buf, 0, cred->len); + k_free((void *)cred_buf); + cred->buf = NULL; + + /* Clear the reference slot so it can be used again. */ + cred_refs[ref_slot] = NULL; + + shell_fprintf(sh, SHELL_NORMAL, "Stored credential freed.\n"); + } + + /* Attempt to delete. */ + err = tls_credential_delete(sectag, type); + if (err) { + shell_fprintf(sh, SHELL_ERROR, "Deleting TLS credential with sectag %d and " + "type %s failed with error: %d.\n", sectag, + cred_type_name(type), err); + goto cleanup; + } + + shell_fprintf(sh, SHELL_NORMAL, "Deleted TLS credential with sectag %d and type %s.\n", + sectag, cred_type_name(type)); + +cleanup: + /* Unlock credentials since we are done interacting with internal state. */ + credentials_unlock(); + + return err; +} + +/* Retrieves credential data from credential store. */ +static int tls_cred_cmd_get(const struct shell *sh, size_t argc, char *argv[]) +{ + int i; + int remaining; + int written; + int err = 0; + size_t cred_len; + sec_tag_t sectag; + enum tls_credential_type type; + enum cred_storage_fmt format; + bool terminated; + + size_t line_length; + + /* Lock credentials so that we can safely use internal access functions. */ + credentials_lock(); + + err = shell_parse_cred_sectag(sh, argv[1], §ag, false); + if (err) { + goto cleanup; + } + + err = shell_parse_cred_type(sh, argv[2], &type, false); + if (err) { + goto cleanup; + } + + err = shell_parse_cred_storage_format(sh, argv[3], &format, &terminated); + if (err) { + goto cleanup; + } + + line_length = CONFIG_TLS_CREDENTIALS_SHELL_CRED_OUTPUT_WIDTH; + + /* If the credential is stored as binary, adjust line length so that the output + * base64 has width CONFIG_TLS_CREDENTIALS_SHELL_CRED_OUTPUT_WIDTH + */ + if (format == CRED_STORAGE_FMT_BINARY) { + line_length = CONFIG_TLS_CREDENTIALS_SHELL_CRED_OUTPUT_WIDTH / 4 * 3; + } + + /* Check whether a credential of this type and sectag actually exists. */ + if (!credential_get(sectag, type)) { + shell_fprintf(sh, SHELL_ERROR, "There is no TLS credential with sectag %d and " + "type %s.\n", sectag, cred_type_name(type)); + err = -ENOENT; + goto cleanup; + } + + /* Clear the credential buffer before use. */ + shell_clear_cred_buf(sh); + + /* Load the credential into the credential buffer */ + cred_len = sizeof(cred_buf); + err = tls_credential_get(sectag, type, cred_buf, &cred_len); + if (err == -EFBIG) { + shell_fprintf(sh, SHELL_ERROR, "Not enough room in the credential buffer to " + "retrieve credential with sectag %d and type %s. " + "Increase TLS_CREDENTIALS_SHELL_MAX_CRED_LEN.\n", + sectag, cred_type_name(type)); + err = -ENOMEM; + goto cleanup; + } else if (err) { + shell_fprintf(sh, SHELL_ERROR, "Could not retrieve TLS credential with sectag %d " + "and type %s due to error: %d.\n", sectag, + cred_type_name(type), err); + goto cleanup; + } + + /* Update the credential buffer writehead. + * Keeping this accurate ensures that a "Buffer Cleared" message is eventually printed. + */ + cred_written = cred_len; + + /* If the stored credential is NULL-terminated, do not include NULL termination in output */ + if (terminated) { + if (cred_buf[cred_written - 1] != 0) { + shell_fprintf(sh, SHELL_ERROR, "The stored credential isn't " + "NULL-terminated, but a NULL-terminated " + "format was specified.\n"); + + err = -EINVAL; + goto cleanup; + } + cred_written -= 1; + } + + /* Print the credential out in lines. */ + for (i = 0; i < cred_written; i += line_length) { + /* Print either a full line, or however much credential data is left. */ + remaining = MIN(line_length, cred_written - i); + + /* Read out a line of data. */ + memset(cred_out_buf, 0, sizeof(cred_out_buf)); + if (format == CRED_STORAGE_FMT_BINARY) { + (void)base64_encode(cred_out_buf, sizeof(cred_out_buf), + &written, &cred_buf[i], remaining); + } else if (format == CRED_STORAGE_FMT_STRING) { + memcpy(cred_out_buf, &cred_buf[i], remaining); + if (filter_nonprint(cred_out_buf, remaining, '?')) { + err = -EBADF; + } + } + + /* Print the line. */ + shell_fprintf(sh, SHELL_NORMAL, "%s\n", cred_out_buf); + } + + if (err) { + shell_fprintf(sh, SHELL_WARNING, "Non-printable characters were included in the " + "output and filtered. Have you selected the " + "correct storage format?\n"); + } + +cleanup: + /* Unlock credentials since we are done interacting with internal state. */ + credentials_unlock(); + + /* Clear buffers when done. */ + memset(cred_out_buf, 0, sizeof(cred_out_buf)); + shell_clear_cred_buf(sh); + + return err; +} + +/* Lists credentials in credential store. */ +static int tls_cred_cmd_list(const struct shell *sh, size_t argc, char *argv[]) +{ + int err = 0; + size_t digest_size; + sec_tag_t sectag = TLS_SEC_TAG_NONE; + struct tls_credential *cred; + int count = 0; + + sec_tag_t sectag_filter = TLS_SEC_TAG_NONE; + enum tls_credential_type type_filter = TLS_CREDENTIAL_NONE; + + /* Lock credentials so that we can safely use internal access functions. */ + credentials_lock(); + + /* Sectag filter was provided, parse it. */ + if (argc >= 2) { + err = shell_parse_cred_sectag(sh, argv[1], §ag_filter, true); + if (err) { + goto cleanup; + } + } + + /* Credential type filter was provided, parse it. */ + if (argc >= 3) { + err = shell_parse_cred_type(sh, argv[2], &type_filter, true); + if (err) { + goto cleanup; + } + } + + /* Scan through all occupied sectags */ + while ((sectag = credential_next_tag_get(sectag)) != TLS_SEC_TAG_NONE) { + /* Filter by sectag if requested. */ + if (sectag_filter != TLS_SEC_TAG_NONE && sectag != sectag_filter) { + continue; + } + + cred = NULL; + /* Scan through all credentials within each sectag */ + while ((cred = credential_next_get(sectag, cred)) != NULL) { + /* Filter by credential type if requested. */ + if (type_filter != TLS_CREDENTIAL_NONE && cred->type != type_filter) { + continue; + } + count++; + + /* Generate a digest of the credential */ + memset(cred_digest_buf, 0, sizeof(cred_digest_buf)); + strcpy(cred_digest_buf, "N/A"); + digest_size = sizeof(cred_digest_buf); + err = credential_digest(cred, cred_digest_buf, &digest_size); + + /* Print digest and sectag/type info */ + shell_fprintf(sh, err ? SHELL_ERROR : SHELL_NORMAL, "%d,%s,%s,%d\n", + sectag, cred_type_name_compact(cred->type), + err ? "ERROR" : cred_digest_buf, err); + + err = 0; + } + }; + + shell_fprintf(sh, SHELL_NORMAL, "%d credentials found.\n", count); + +cleanup: + /* Unlock credentials since we are done interacting with internal state. */ + credentials_unlock(); + + /* Clear digest buffer afterwards for good measure. */ + memset(cred_digest_buf, 0, sizeof(cred_digest_buf)); + + return 0; +} + +SHELL_STATIC_SUBCMD_SET_CREATE(tls_cred_cmds, + SHELL_CMD_ARG(buf, NULL, "Buffer in credential data so it can be added.", + tls_cred_cmd_buf, 2, 0), + SHELL_CMD_ARG(add, NULL, "Add a TLS credential.", + tls_cred_cmd_add, 5, 1), + SHELL_CMD_ARG(del, NULL, "Delete a TLS credential.", + tls_cred_cmd_del, 3, 0), + SHELL_CMD_ARG(get, NULL, "Retrieve the contents of a TLS credential", + tls_cred_cmd_get, 4, 0), + SHELL_CMD_ARG(list, NULL, "List stored TLS credentials, optionally filtering by type " + "or sectag.", + tls_cred_cmd_list, 1, 2), + SHELL_SUBCMD_SET_END +); + +SHELL_CMD_REGISTER(cred, &tls_cred_cmds, "TLS Credentials Commands", NULL); diff --git a/subsys/net/lib/tls_credentials/tls_credentials_trusted.c b/subsys/net/lib/tls_credentials/tls_credentials_trusted.c index ef105715b07..0b77e52f558 100644 --- a/subsys/net/lib/tls_credentials/tls_credentials_trusted.c +++ b/subsys/net/lib/tls_credentials/tls_credentials_trusted.c @@ -12,6 +12,7 @@ #include #include "tls_internal.h" +#include "tls_credentials_digest_raw.h" LOG_MODULE_REGISTER(tls_credentials_trusted, CONFIG_TLS_CREDENTIALS_LOG_LEVEL); @@ -262,6 +263,46 @@ struct tls_credential *credential_next_get(sec_tag_t tag, return NULL; } +sec_tag_t credential_next_tag_get(sec_tag_t iter) +{ + unsigned int slot; + psa_storage_uid_t uid; + sec_tag_t lowest_candidate = TLS_SEC_TAG_NONE; + sec_tag_t candidate; + + /* Scan all slots and find lowest sectag greater than iter */ + for (slot = 0; slot < CRED_MAX_SLOTS; slot++) { + uid = credentials_toc[slot]; + + /* Skip empty slots. */ + if (uid == 0) { + continue; + } + if (tls_credential_uid_to_type(uid) == TLS_CREDENTIAL_NONE) { + continue; + } + + candidate = tls_credential_uid_to_tag(uid); + + /* Skip any slots containing sectags not greater than iter */ + if (candidate <= iter && iter != TLS_SEC_TAG_NONE) { + continue; + } + + /* Find the lowest of such slots */ + if (lowest_candidate == TLS_SEC_TAG_NONE || candidate < lowest_candidate) { + lowest_candidate = candidate; + } + } + + return lowest_candidate; +} + +int credential_digest(struct tls_credential *credential, void *dest, size_t *len) +{ + return credential_digest_raw(credential, dest, len); +} + void credentials_lock(void) { k_mutex_lock(&credential_lock, K_FOREVER); diff --git a/subsys/net/lib/tls_credentials/tls_internal.h b/subsys/net/lib/tls_credentials/tls_internal.h index b825b6890d8..e7cfc0a1c0b 100644 --- a/subsys/net/lib/tls_credentials/tls_internal.h +++ b/subsys/net/lib/tls_credentials/tls_internal.h @@ -28,6 +28,11 @@ struct tls_credential { size_t len; }; +/* + * Special sec_tag value indicating none or invalid sec_tag. For internal use only for now. + */ +#define TLS_SEC_TAG_NONE -1 + /* Lock TLS credential access. */ void credentials_lock(void); @@ -42,7 +47,6 @@ void credentials_unlock(void); struct tls_credential *credential_get(sec_tag_t tag, enum tls_credential_type type); - /* Function for iterating over credentials by tag. * * Note, that to assure thread safety, credential access should be locked with @@ -51,4 +55,27 @@ struct tls_credential *credential_get(sec_tag_t tag, struct tls_credential *credential_next_get(sec_tag_t tag, struct tls_credential *iter); +/* Function for iterating over occupied sec tags. + * + * Returns the next occupied sec tag after the one provided, or TLS_SEC_TAG_NONE if there are no + * more. + * + * Provide TLS_SEC_TAG_NONE to start from the first available sec tag. + */ +sec_tag_t credential_next_tag_get(sec_tag_t iter); + +/* Writes a (NULL-terminated, printable) string digest of the contents of the provided credential + * to the provided destination buffer. + * + * Digest format/type is up to the tls_credentials backend in use. + * + * len pointer should be set to the amount of space available in the destination buffer prior to + * calling, and will be set to the amount written to the destination buffer after calling + * (excluding the NULL terminator). + * + * Note, that to assure thread safety, credential access should be locked with + * credentials_lock before calling this function. + */ +int credential_digest(struct tls_credential *credential, void *dest, size_t *len); + #endif /* __TLS_INTERNAL_H */ diff --git a/subsys/net/lib/websocket/websocket.c b/subsys/net/lib/websocket/websocket.c index f5975dea147..811f89c5b28 100644 --- a/subsys/net/lib/websocket/websocket.c +++ b/subsys/net/lib/websocket/websocket.c @@ -31,7 +31,7 @@ LOG_MODULE_REGISTER(net_websocket, CONFIG_NET_WEBSOCKET_LOG_LEVEL); #include #include -#include +#include #include #include #include diff --git a/subsys/net/lib/zperf/zperf_common.c b/subsys/net/lib/zperf/zperf_common.c index 29568eeef5b..4bc675ed45e 100644 --- a/subsys/net/lib/zperf/zperf_common.c +++ b/subsys/net/lib/zperf/zperf_common.c @@ -175,9 +175,9 @@ int zperf_prepare_upload_sock(const struct sockaddr *peer_addr, int tos, uint8_t prio = priority; if (!IS_ENABLED(CONFIG_NET_ALLOW_ANY_PRIORITY) && - (prio > NET_MAX_PRIORITIES)) { - NET_ERR("Priority %d is too large, maximum is %d", - priority, NET_MAX_PRIORITIES); + (prio >= NET_MAX_PRIORITIES)) { + NET_ERR("Priority %d is too large, maximum allowed is %d", + prio, NET_MAX_PRIORITIES - 1); return -EINVAL; } diff --git a/subsys/net/lib/zperf/zperf_shell.c b/subsys/net/lib/zperf/zperf_shell.c index b61501d0e9e..444cf125c31 100644 --- a/subsys/net/lib/zperf/zperf_shell.c +++ b/subsys/net/lib/zperf/zperf_shell.c @@ -536,6 +536,57 @@ static void tcp_upload_cb(enum zperf_status status, } } +static int ping_handler(struct net_icmp_ctx *ctx, + struct net_pkt *pkt, + struct net_icmp_ip_hdr *ip_hdr, + struct net_icmp_hdr *icmp_hdr, + void *user_data) +{ + struct k_sem *sem_wait = user_data; + + ARG_UNUSED(ctx); + ARG_UNUSED(pkt); + ARG_UNUSED(ip_hdr); + ARG_UNUSED(icmp_hdr); + + k_sem_give(sem_wait); + + return 0; +} + +static void send_ping(const struct shell *sh, + struct in6_addr *addr, + int timeout_ms) +{ + static struct k_sem sem_wait; + struct sockaddr_in6 dest_addr = { 0 }; + struct net_icmp_ctx ctx; + int ret; + + ret = net_icmp_init_ctx(&ctx, NET_ICMPV6_ECHO_REPLY, 0, ping_handler); + if (ret < 0) { + shell_fprintf(sh, SHELL_WARNING, "Cannot send ping (%d)\n", ret); + return; + } + + memcpy(&dest_addr.sin6_addr, addr, sizeof(struct in6_addr)); + + k_sem_init(&sem_wait, 0, 1); + + (void)net_icmp_send_echo_request(&ctx, + net_if_get_default(), + (struct sockaddr *)&dest_addr, + NULL, &sem_wait); + + ret = k_sem_take(&sem_wait, K_MSEC(timeout_ms)); + if (ret == -EAGAIN) { + shell_fprintf(sh, SHELL_WARNING, "ping %s timeout\n", + net_sprint_ipv6_addr(addr)); + } + + (void)net_icmp_cleanup_ctx(&ctx); +} + static int execute_upload(const struct shell *sh, const struct zperf_upload_params *param, bool is_udp, bool async) @@ -560,10 +611,7 @@ static int execute_upload(const struct shell *sh, * has been done for the peer. So send ping here, wait * some time and start the test after that. */ - net_icmpv6_send_echo_request(net_if_get_default(), - &ipv6->sin6_addr, 0, 0, 0, -1, NULL, 0); - - k_sleep(K_SECONDS(1)); + send_ping(sh, &ipv6->sin6_addr, MSEC_PER_SEC); } if (is_udp && IS_ENABLED(CONFIG_NET_UDP)) { diff --git a/subsys/net/lib/zperf/zperf_tcp_receiver.c b/subsys/net/lib/zperf/zperf_tcp_receiver.c index 6cc3374d0ae..344d34fe98c 100644 --- a/subsys/net/lib/zperf/zperf_tcp_receiver.c +++ b/subsys/net/lib/zperf/zperf_tcp_receiver.c @@ -165,7 +165,7 @@ static void tcp_server_session(void) if (!net_ipv4_is_addr_unspecified(addr)) { memcpy(&in4_addr->sin_addr, addr, sizeof(struct in_addr)); - } else if (MY_IP4ADDR && strlen(MY_IP4ADDR)) { + } else if (strlen(MY_IP4ADDR ? MY_IP4ADDR : "")) { /* Use Setting IP */ ret = zperf_get_ipv4_addr(MY_IP4ADDR, &in4_addr->sin_addr); @@ -210,7 +210,7 @@ static void tcp_server_session(void) if (!net_ipv6_is_addr_unspecified(addr)) { memcpy(&in6_addr->sin6_addr, addr, sizeof(struct in6_addr)); - } else if (MY_IP6ADDR && strlen(MY_IP6ADDR)) { + } else if (strlen(MY_IP6ADDR ? MY_IP6ADDR : "")) { /* Use Setting IP */ ret = zperf_get_ipv6_addr(MY_IP6ADDR, MY_PREFIX_LEN_STR, diff --git a/subsys/net/lib/zperf/zperf_udp_receiver.c b/subsys/net/lib/zperf/zperf_udp_receiver.c index 2724da4b1a9..75a0b35b234 100644 --- a/subsys/net/lib/zperf/zperf_udp_receiver.c +++ b/subsys/net/lib/zperf/zperf_udp_receiver.c @@ -257,7 +257,7 @@ static void udp_server_session(void) if (!net_ipv4_is_addr_unspecified(in4_addr)) { memcpy(&in4_addr_my->sin_addr, in4_addr, sizeof(struct in_addr)); - } else if (MY_IP4ADDR && strlen(MY_IP4ADDR)) { + } else if (strlen(MY_IP4ADDR ? MY_IP4ADDR : "")) { /* Use setting IP */ ret = zperf_get_ipv4_addr(MY_IP4ADDR, &in4_addr_my->sin_addr); @@ -305,7 +305,7 @@ static void udp_server_session(void) if (!net_ipv6_is_addr_unspecified(in6_addr)) { memcpy(&in6_addr_my->sin6_addr, in6_addr, sizeof(struct in6_addr)); - } else if (MY_IP6ADDR && strlen(MY_IP6ADDR)) { + } else if (strlen(MY_IP6ADDR ? MY_IP6ADDR : "")) { /* Use setting IP */ ret = zperf_get_ipv6_addr(MY_IP6ADDR, MY_PREFIX_LEN_STR, diff --git a/subsys/pm/Kconfig b/subsys/pm/Kconfig index 36535e383a1..aeffe8c60ec 100644 --- a/subsys/pm/Kconfig +++ b/subsys/pm/Kconfig @@ -37,6 +37,13 @@ config PM_S2RAM help This option enables suspend-to-RAM (S2RAM). +config PM_NEED_ALL_DEVICES_IDLE + bool "System Low Power Mode Needs All Devices Idle" + depends on PM_DEVICE && !SMP + help + When this option is enabled, check that no devices are busy before + entering into system low power mode. + choice PM_POLICY prompt "Idle State Power Management Policy" default PM_POLICY_DEFAULT diff --git a/subsys/pm/pm.c b/subsys/pm/pm.c index ae6e8505d89..cfeadaa4447 100644 --- a/subsys/pm/pm.c +++ b/subsys/pm/pm.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include diff --git a/subsys/pm/policy.c b/subsys/pm/policy.c index 4c3012db2cc..fa44a7069f7 100644 --- a/subsys/pm/policy.c +++ b/subsys/pm/policy.c @@ -14,6 +14,7 @@ #include #include #include +#include #if DT_HAS_COMPAT_STATUS_OKAY(zephyr_power_state) @@ -136,6 +137,12 @@ const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int32_t ticks) uint8_t num_cpu_states; const struct pm_state_info *cpu_states; +#ifdef CONFIG_PM_NEED_ALL_DEVICES_IDLE + if (pm_device_is_any_busy()) { + return NULL; + } +#endif + if (ticks != K_TICKS_FOREVER) { cyc = k_ticks_to_cyc_ceil32(ticks); } diff --git a/subsys/portability/cmsis_rtos_v1/cmsis_thread.c b/subsys/portability/cmsis_rtos_v1/cmsis_thread.c index 72570f840b6..9887e560afb 100644 --- a/subsys/portability/cmsis_rtos_v1/cmsis_thread.c +++ b/subsys/portability/cmsis_rtos_v1/cmsis_thread.c @@ -29,6 +29,8 @@ static inline uint32_t cmsis_to_zephyr_priority(int32_t c_prio) static void zephyr_thread_wrapper(void *arg1, void *arg2, void *arg3) { + ARG_UNUSED(arg2); + void * (*fun_ptr)(void *) = arg3; fun_ptr(arg1); @@ -109,7 +111,7 @@ osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *arg) tid = k_thread_create(&cm_thread[instance], stk_ptr[instance], stacksz, - (k_thread_entry_t)zephyr_thread_wrapper, + zephyr_thread_wrapper, (void *)arg, NULL, thread_def->pthread, prio, 0, K_NO_WAIT); diff --git a/subsys/portability/cmsis_rtos_v2/mempool.c b/subsys/portability/cmsis_rtos_v2/mempool.c index 8ec08cbc752..183d3ac789a 100644 --- a/subsys/portability/cmsis_rtos_v2/mempool.c +++ b/subsys/portability/cmsis_rtos_v2/mempool.c @@ -172,7 +172,7 @@ uint32_t osMemoryPoolGetCapacity(osMemoryPoolId_t mp_id) if (mslab == NULL) { return 0; } else { - return mslab->z_mslab.num_blocks; + return mslab->z_mslab.info.num_blocks; } } @@ -186,7 +186,7 @@ uint32_t osMemoryPoolGetBlockSize(osMemoryPoolId_t mp_id) if (mslab == NULL) { return 0; } else { - return mslab->z_mslab.block_size; + return mslab->z_mslab.info.block_size; } } diff --git a/subsys/portability/cmsis_rtos_v2/msgq.c b/subsys/portability/cmsis_rtos_v2/msgq.c index 05103f35539..d23a5569031 100644 --- a/subsys/portability/cmsis_rtos_v2/msgq.c +++ b/subsys/portability/cmsis_rtos_v2/msgq.c @@ -55,12 +55,17 @@ osMessageQueueId_t osMessageQueueNew(uint32_t msg_count, uint32_t msg_size, CONFIG_CMSIS_V2_MSGQ_MAX_DYNAMIC_SIZE, "message queue size exceeds dynamic maximum"); +#if (CONFIG_HEAP_MEM_POOL_SIZE > 0) msgq->pool = k_calloc(msg_count, msg_size); if (msgq->pool == NULL) { k_mem_slab_free(&cv2_msgq_slab, (void *)msgq); return NULL; } msgq->is_dynamic_allocation = TRUE; +#else + k_mem_slab_free(&cv2_msgq_slab, (void *)msgq); + return NULL; +#endif } else { msgq->pool = attr->mq_mem; msgq->is_dynamic_allocation = FALSE; diff --git a/subsys/portability/cmsis_rtos_v2/thread.c b/subsys/portability/cmsis_rtos_v2/thread.c index 22bd693612a..f5e9cd67027 100644 --- a/subsys/portability/cmsis_rtos_v2/thread.c +++ b/subsys/portability/cmsis_rtos_v2/thread.c @@ -198,7 +198,7 @@ osThreadId_t osThreadNew(osThreadFunc_t threadfunc, void *arg, (void)k_thread_create(&tid->z_thread, stack, stack_size, - (k_thread_entry_t)zephyr_thread_wrapper, + zephyr_thread_wrapper, (void *)arg, tid, threadfunc, prio, 0, K_NO_WAIT); diff --git a/subsys/random/CMakeLists.txt b/subsys/random/CMakeLists.txt index 1cb72f2bea1..cde2431ae2e 100644 --- a/subsys/random/CMakeLists.txt +++ b/subsys/random/CMakeLists.txt @@ -3,7 +3,7 @@ if (CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR OR CONFIG_TIMER_RANDOM_GENERATOR OR CONFIG_XOSHIRO_RANDOM_GENERATOR) -zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/random/rand32.h) +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/random/random.h) zephyr_library() zephyr_library_sources_ifdef(CONFIG_USERSPACE rand32_handlers.c) endif() @@ -15,11 +15,7 @@ if (CONFIG_TIMER_RANDOM_GENERATOR) Use it carefully.") endif() -# XOROSHIRO builds the XOSHIRO implementation because a Kconfig choice cannot -# select another choice as a means of deprecating the symbol. Swapping out the -# implementation lets out-of-tree users still build until the symbol is removed. zephyr_library_sources_ifdef(CONFIG_TIMER_RANDOM_GENERATOR rand32_timer.c) -zephyr_library_sources_ifdef(CONFIG_XOROSHIRO_RANDOM_GENERATOR rand32_xoshiro128.c) zephyr_library_sources_ifdef(CONFIG_XOSHIRO_RANDOM_GENERATOR rand32_xoshiro128.c) zephyr_library_sources_ifdef(CONFIG_CTR_DRBG_CSPRNG_GENERATOR rand32_ctr_drbg.c) diff --git a/subsys/random/Kconfig b/subsys/random/Kconfig index d945bbbcec0..72106f09b57 100644 --- a/subsys/random/Kconfig +++ b/subsys/random/Kconfig @@ -28,6 +28,14 @@ config TEST_RANDOM_GENERATOR device-backed random number generator, if available, will be selected by default even when CONFIG_TEST_RANDOM_GENERATOR=y. +config TIMER_RANDOM_INITIAL_STATE + int "Initial state used by clock based number generator" + default 123456789 + help + Initial state value used by TIMER_RANDOM_GENERATOR and + early random number genenator. + + choice RNG_GENERATOR_CHOICE prompt "Random generator" default ENTROPY_DEVICE_RANDOM_GENERATOR if ENTROPY_HAS_DRIVER @@ -57,11 +65,6 @@ config ENTROPY_DEVICE_RANDOM_GENERATOR selected if hardware entropy driver is designed to be a random number generator source. -config XOROSHIRO_RANDOM_GENERATOR - bool "Use Xoroshiro128+ as PRNG (DEPRECATED)" - help - This is deprecated, please use XOSHIRO_RANDOM_GENERATOR instead. - config XOSHIRO_RANDOM_GENERATOR bool "Use Xoshiro128++ as PRNG" depends on ENTROPY_HAS_DRIVER @@ -77,8 +80,7 @@ endchoice # RNG_GENERATOR_CHOICE # enabling CS generators. ENTROPY_HAS_DRIVER is the flag indicating the # CS entropy source. # -config CSPRING_ENABLED -# bool "Cryptographically secure RNG functions enabled" +config CSPRNG_ENABLED bool default y depends on ENTROPY_HAS_DRIVER diff --git a/subsys/random/rand32_ctr_drbg.c b/subsys/random/rand32_ctr_drbg.c index 7d4b858a068..88c591075f1 100644 --- a/subsys/random/rand32_ctr_drbg.c +++ b/subsys/random/rand32_ctr_drbg.c @@ -26,8 +26,6 @@ #endif /* CONFIG_MBEDTLS */ -static K_SEM_DEFINE(state_sem, 1, 1); - /* * entropy_dev is initialized at runtime to allow first time initialization * of the ctr_drbg engine. @@ -35,6 +33,7 @@ static K_SEM_DEFINE(state_sem, 1, 1); static const struct device *entropy_dev; static const unsigned char drbg_seed[] = CONFIG_CS_CTR_DRBG_PERSONALIZATION; static bool ctr_initialised; +static struct k_mutex ctr_lock; #if defined(CONFIG_MBEDTLS) @@ -107,7 +106,8 @@ static int ctr_drbg_initialize(void) int z_impl_sys_csrand_get(void *dst, uint32_t outlen) { int ret; - unsigned int key = irq_lock(); + + k_mutex_lock(&ctr_lock, K_FOREVER); if (unlikely(!ctr_initialised)) { ret = ctr_drbg_initialize(); @@ -153,7 +153,7 @@ int z_impl_sys_csrand_get(void *dst, uint32_t outlen) } #endif end: - irq_unlock(key); + k_mutex_unlock(&ctr_lock); return ret; } diff --git a/subsys/random/rand32_handlers.c b/subsys/random/rand32_handlers.c index d1e8cd8c15a..38344a00190 100644 --- a/subsys/random/rand32_handlers.c +++ b/subsys/random/rand32_handlers.c @@ -4,9 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include - +#include +#include static inline uint32_t z_vrfy_sys_rand32_get(void) { @@ -16,17 +15,16 @@ static inline uint32_t z_vrfy_sys_rand32_get(void) static inline void z_vrfy_sys_rand_get(void *dst, size_t len) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(dst, len)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(dst, len)); z_impl_sys_rand_get(dst, len); } #include -#if defined(CONFIG_CTR_DRBG_CSPRNG_GENERATOR) || \ - defined(CONFIG_HARDWARE_DEVICE_CS_GENERATOR) +#ifdef CONFIG_CSPRNG_ENABLED static inline int z_vrfy_sys_csrand_get(void *dst, size_t len) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(dst, len)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(dst, len)); return z_impl_sys_csrand_get(dst, len); } diff --git a/subsys/random/rand32_timer.c b/subsys/random/rand32_timer.c index 6b14e166ce0..4232dccfbc8 100644 --- a/subsys/random/rand32_timer.c +++ b/subsys/random/rand32_timer.c @@ -14,7 +14,7 @@ * provide a random number generator. */ -#include +#include #include #include #include @@ -35,7 +35,8 @@ static struct k_spinlock rand32_lock; */ uint32_t z_impl_sys_rand32_get(void) { - static uint64_t state = 123456789UL; /* initial seed value */ + /* initial seed value */ + static uint64_t state = (uint64_t)CONFIG_TIMER_RANDOM_INITIAL_STATE; k_spinlock_key_t key = k_spin_lock(&rand32_lock); state = state + k_cycle_get_32(); diff --git a/subsys/retention/CMakeLists.txt b/subsys/retention/CMakeLists.txt index 6cea5b490df..a70469a4171 100644 --- a/subsys/retention/CMakeLists.txt +++ b/subsys/retention/CMakeLists.txt @@ -3,3 +3,8 @@ zephyr_library() zephyr_library_sources(retention.c) zephyr_library_sources_ifdef(CONFIG_RETENTION_BOOT_MODE bootmode.c) + +if(CONFIG_RETENTION_BOOTLOADER_INFO_TYPE_MCUBOOT) + zephyr_library_sources(blinfo_mcuboot.c) + zephyr_link_libraries(MCUBOOT_BOOTUTIL) +endif() diff --git a/subsys/retention/Kconfig b/subsys/retention/Kconfig index 0f3def9abc9..e42d7e7ebf9 100644 --- a/subsys/retention/Kconfig +++ b/subsys/retention/Kconfig @@ -17,7 +17,7 @@ config RETENTION_INIT_PRIORITY default 86 help Retention device initialization priority (must be higher than init - priorities for retained memory drivers. + priorities for retained memory drivers). config RETENTION_MUTEXES bool @@ -55,6 +55,8 @@ config RETENTION_BOOT_MODE byte must be created and set as the "zephyr,boot-mode" chosen node via device tree. +source "subsys/retention/Kconfig.blinfo" + endmenu module = RETENTION diff --git a/subsys/retention/Kconfig.blinfo b/subsys/retention/Kconfig.blinfo new file mode 100644 index 00000000000..57c5222511a --- /dev/null +++ b/subsys/retention/Kconfig.blinfo @@ -0,0 +1,55 @@ +# Copyright (c) 2023, Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +menuconfig RETENTION_BOOTLOADER_INFO + bool "Bootloader info" + help + Adds a bootloader information sharing system which allows for + retreiving data from the bootloader when data sharing is enabled. + +if RETENTION_BOOTLOADER_INFO + +# Workaround for not being able to have commas in macro arguments +DT_CHOSEN_BOOTLOADER_INFO := zephyr,bootloader-info + +config RETENTION_BOOTLOADER_INFO_TYPE_MCUBOOT + bool "MCUboot" + depends on !MCUBOOT && BOOTLOADER_MCUBOOT + depends on $(dt_chosen_enabled,$(DT_CHOSEN_BOOTLOADER_INFO)) + select MCUBOOT_BOOTUTIL_LIB + help + Adds a bootloader information sharing system for MCUboot and + applications which allows applications to read the configuration of + MCUboot and the running image. This can be used by applications so + that they know how to e.g. handle firmware updates and place them + into the correct slot. + + In order to use this, a retention area must be created and set as + the "zephyr,bootloader-info" chosen node via device tree, MCUboot + must be built with the same "zephyr,bootloader-info" DTS node and + have CONFIG_BOOT_SHARE_DATA, CONFIG_BOOT_SHARE_DATA_BOOTINFO and + CONFIG_BOOT_SHARE_BACKEND_RETENTION enabled, or the shared + information will not be accessible. + +config RETENTION_BOOTLOADER_INFO_INIT_PRIORITY + int "Bootloader info init priority" + default 87 + help + Bootloader info initialization priority (must be higher than init + priorities for for retention subsystem). + +config RETENTION_BOOTLOADER_INFO_OUTPUT_FUNCTION + bool "Function" + default y + help + Allows bootloader settings to be fetched by calling a function which + will update a buffer with the requested data. + +config RETENTION_BOOTLOADER_INFO_OUTPUT_SETTINGS + bool "Settings" + depends on SETTINGS + help + Allows bootloader settings to be fetched using settings with the + "blinfo" prefix. + +endif diff --git a/subsys/retention/blinfo_mcuboot.c b/subsys/retention/blinfo_mcuboot.c new file mode 100644 index 00000000000..8c4ccaaa674 --- /dev/null +++ b/subsys/retention/blinfo_mcuboot.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2023, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(blinfo_mcuboot, CONFIG_RETENTION_LOG_LEVEL); + +static const struct device *bootloader_info_dev = + DEVICE_DT_GET(DT_CHOSEN(zephyr_bootloader_info)); + +#if !defined(CONFIG_RETENTION_BOOTLOADER_INFO_OUTPUT_FUNCTION) +static +#endif +int blinfo_lookup(uint16_t key, char *val, int val_len_max) +{ + struct shared_data_tlv_header header; + struct shared_data_tlv_entry tlv_entry = {0}; + uintptr_t offset = SHARED_DATA_HEADER_SIZE; + int rc; + + rc = retention_read(bootloader_info_dev, 0, (void *)&header, sizeof(header)); + + if (rc != 0) { + return rc; + } + + /* Iterate over the whole shared MCUboot data section and look for a TLV with + * the required tag. + */ + while (offset < header.tlv_tot_len) { + rc = retention_read(bootloader_info_dev, offset, (void *)&tlv_entry, + sizeof(tlv_entry)); + + if (rc != 0) { + return rc; + } + + if (GET_MAJOR(tlv_entry.tlv_type) == TLV_MAJOR_BLINFO && + GET_MINOR(tlv_entry.tlv_type) == key) { + /* Return an error if the provided buffer is too small to fit the + * value in it, bootloader values are small and concise and should + * be able to fit in a single buffer. + */ + if (tlv_entry.tlv_len > val_len_max) { + return -EOVERFLOW; + } + + offset += SHARED_DATA_ENTRY_HEADER_SIZE; + rc = retention_read(bootloader_info_dev, offset, val, + tlv_entry.tlv_len); + + if (rc != 0) { + return rc; + } + + return tlv_entry.tlv_len; + } + + offset += SHARED_DATA_ENTRY_SIZE(tlv_entry.tlv_len); + } + + /* Return IO error as a valid key name was provided but the TLV was not found in + * the shared data section. + */ + return -EIO; +} + +#if defined(CONFIG_RETENTION_BOOTLOADER_INFO_OUTPUT_SETTINGS) +static int blinfo_handle_get(const char *name, char *val, int val_len_max); +static int blinfo_handle_set(const char *name, size_t len, settings_read_cb read_cb, void *cb_arg); + +static struct settings_handler blinfo_handler = { + .name = "blinfo", + .h_get = blinfo_handle_get, + .h_set = blinfo_handle_set, +}; + +static int blinfo_handle_get(const char *name, char *val, int val_len_max) +{ + const char *next; + uint16_t index; + + /* Allowed keys are mode, signature_type, recovery, running_slot, bootloader_version + * and max_application_size which cannot contain any additional entries + */ + if (settings_name_steq(name, "mode", &next) && !next) { + index = BLINFO_MODE; + } else if (settings_name_steq(name, "signature_type", &next) && !next) { + index = BLINFO_SIGNATURE_TYPE; + } else if (settings_name_steq(name, "recovery", &next) && !next) { + index = BLINFO_RECOVERY; + } else if (settings_name_steq(name, "running_slot", &next) && !next) { + index = BLINFO_RUNNING_SLOT; + } else if (settings_name_steq(name, "bootloader_version", &next) && !next) { + index = BLINFO_BOOTLOADER_VERSION; + } else if (settings_name_steq(name, "max_application_size", &next) && !next) { + index = BLINFO_MAX_APPLICATION_SIZE; + } else { + return -ENOENT; + } + + return blinfo_lookup(index, val, val_len_max); +} + +static int blinfo_handle_set(const char *name, size_t len, settings_read_cb read_cb, void *cb_arg) +{ + return -ENOTSUP; +} +#endif + +static int blinfo_init(void) +{ + int rc; + + rc = retention_is_valid(bootloader_info_dev); + + if (rc == 1 || rc == -ENOTSUP) { + struct shared_data_tlv_header header; + + rc = retention_read(bootloader_info_dev, 0, (void *)&header, sizeof(header)); + + if (rc == 0 && header.tlv_magic != SHARED_DATA_TLV_INFO_MAGIC) { + /* Unknown data present */ + LOG_ERR("MCUboot data load failed, expected magic value: 0x%x, got: 0x%x", + SHARED_DATA_TLV_INFO_MAGIC, header.tlv_magic); + rc = -EINVAL; + } + } + +#if defined(CONFIG_RETENTION_BOOTLOADER_INFO_OUTPUT_SETTINGS) + if (rc == 0) { + settings_register(&blinfo_handler); + } +#endif + + return rc; +} + +SYS_INIT(blinfo_init, APPLICATION, CONFIG_RETENTION_BOOTLOADER_INFO_INIT_PRIORITY); diff --git a/subsys/rtio/Kconfig b/subsys/rtio/Kconfig index 3a28bbdf965..7231d6fefbb 100644 --- a/subsys/rtio/Kconfig +++ b/subsys/rtio/Kconfig @@ -6,21 +6,6 @@ menuconfig RTIO if RTIO -config RTIO_EXECUTOR_SIMPLE - bool "A simple executor for RTIO" - default y - help - An simple RTIO executor that will execute a queue of requested I/O - operations as if they are a single chain of submission queue entries. This - does not support concurrent chains or submissions. - -config RTIO_EXECUTOR_CONCURRENT - bool "A low cost concurrent executor for RTIO" - default y - help - A low memory cost RTIO executor that will execute a queue of requested I/O - with a fixed amount of concurrency using minimal memory overhead. - config RTIO_SUBMIT_SEM bool "Use a semaphore when waiting for completions in rtio_submit" help diff --git a/subsys/rtio/rtio_handlers.c b/subsys/rtio/rtio_handlers.c index ec7dc192e38..3930d5bdee9 100644 --- a/subsys/rtio/rtio_handlers.c +++ b/subsys/rtio/rtio_handlers.c @@ -4,10 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "zephyr/kernel.h" +#include #include #include -#include +#include /** * Verify each SQE type operation and its fields ensuring @@ -19,7 +19,7 @@ */ static inline bool rtio_vrfy_sqe(struct rtio_sqe *sqe) { - if (sqe->iodev != NULL && Z_SYSCALL_OBJ(sqe->iodev, K_OBJ_RTIO_IODEV)) { + if (sqe->iodev != NULL && K_SYSCALL_OBJ(sqe->iodev, K_OBJ_RTIO_IODEV)) { return false; } @@ -29,18 +29,18 @@ static inline bool rtio_vrfy_sqe(struct rtio_sqe *sqe) case RTIO_OP_NOP: break; case RTIO_OP_TX: - valid_sqe &= Z_SYSCALL_MEMORY(sqe->buf, sqe->buf_len, false); + valid_sqe &= K_SYSCALL_MEMORY(sqe->buf, sqe->buf_len, false); break; case RTIO_OP_RX: if ((sqe->flags & RTIO_SQE_MEMPOOL_BUFFER) == 0) { - valid_sqe &= Z_SYSCALL_MEMORY(sqe->buf, sqe->buf_len, true); + valid_sqe &= K_SYSCALL_MEMORY(sqe->buf, sqe->buf_len, true); } break; case RTIO_OP_TINY_TX: break; case RTIO_OP_TXRX: - valid_sqe &= Z_SYSCALL_MEMORY(sqe->tx_buf, sqe->txrx_buf_len, true); - valid_sqe &= Z_SYSCALL_MEMORY(sqe->rx_buf, sqe->txrx_buf_len, true); + valid_sqe &= K_SYSCALL_MEMORY(sqe->tx_buf, sqe->txrx_buf_len, true); + valid_sqe &= K_SYSCALL_MEMORY(sqe->rx_buf, sqe->txrx_buf_len, true); break; default: /* RTIO OP must be known and allowable from user mode @@ -54,7 +54,7 @@ static inline bool rtio_vrfy_sqe(struct rtio_sqe *sqe) static inline void z_vrfy_rtio_release_buffer(struct rtio *r, void *buff, uint32_t buff_len) { - Z_OOPS(Z_SYSCALL_OBJ(r, K_OBJ_RTIO)); + K_OOPS(K_SYSCALL_OBJ(r, K_OBJ_RTIO)); z_impl_rtio_release_buffer(r, buff, buff_len); } #include @@ -62,10 +62,10 @@ static inline void z_vrfy_rtio_release_buffer(struct rtio *r, void *buff, uint32 static inline int z_vrfy_rtio_cqe_get_mempool_buffer(const struct rtio *r, struct rtio_cqe *cqe, uint8_t **buff, uint32_t *buff_len) { - Z_OOPS(Z_SYSCALL_OBJ(r, K_OBJ_RTIO)); - Z_OOPS(Z_SYSCALL_MEMORY_READ(cqe, sizeof(struct rtio_cqe))); - Z_OOPS(Z_SYSCALL_MEMORY_READ(buff, sizeof(void *))); - Z_OOPS(Z_SYSCALL_MEMORY_READ(buff_len, sizeof(uint32_t))); + K_OOPS(K_SYSCALL_OBJ(r, K_OBJ_RTIO)); + K_OOPS(K_SYSCALL_MEMORY_READ(cqe, sizeof(struct rtio_cqe))); + K_OOPS(K_SYSCALL_MEMORY_READ(buff, sizeof(void *))); + K_OOPS(K_SYSCALL_MEMORY_READ(buff_len, sizeof(uint32_t))); return z_impl_rtio_cqe_get_mempool_buffer(r, cqe, buff, buff_len); } #include @@ -79,9 +79,9 @@ static inline int z_vrfy_rtio_sqe_cancel(struct rtio_sqe *sqe) static inline int z_vrfy_rtio_sqe_copy_in_get_handles(struct rtio *r, const struct rtio_sqe *sqes, struct rtio_sqe **handle, size_t sqe_count) { - Z_OOPS(Z_SYSCALL_OBJ(r, K_OBJ_RTIO)); + K_OOPS(K_SYSCALL_OBJ(r, K_OBJ_RTIO)); - Z_OOPS(Z_SYSCALL_MEMORY_ARRAY_READ(sqes, sqe_count, sizeof(struct rtio_sqe))); + K_OOPS(K_SYSCALL_MEMORY_ARRAY_READ(sqes, sqe_count, sizeof(struct rtio_sqe))); struct rtio_sqe *sqe; uint32_t acquirable = rtio_sqe_acquirable(r); @@ -100,7 +100,7 @@ static inline int z_vrfy_rtio_sqe_copy_in_get_handles(struct rtio *r, const stru if (!rtio_vrfy_sqe(sqe)) { rtio_sqe_drop_all(r); - Z_OOPS(true); + K_OOPS(true); } } @@ -114,9 +114,9 @@ static inline int z_vrfy_rtio_cqe_copy_out(struct rtio *r, size_t cqe_count, k_timeout_t timeout) { - Z_OOPS(Z_SYSCALL_OBJ(r, K_OBJ_RTIO)); + K_OOPS(K_SYSCALL_OBJ(r, K_OBJ_RTIO)); - Z_OOPS(Z_SYSCALL_MEMORY_ARRAY_WRITE(cqes, cqe_count, sizeof(struct rtio_cqe))); + K_OOPS(K_SYSCALL_MEMORY_ARRAY_WRITE(cqes, cqe_count, sizeof(struct rtio_cqe))); return z_impl_rtio_cqe_copy_out(r, cqes, cqe_count, timeout); } @@ -124,10 +124,10 @@ static inline int z_vrfy_rtio_cqe_copy_out(struct rtio *r, static inline int z_vrfy_rtio_submit(struct rtio *r, uint32_t wait_count) { - Z_OOPS(Z_SYSCALL_OBJ(r, K_OBJ_RTIO)); + K_OOPS(K_SYSCALL_OBJ(r, K_OBJ_RTIO)); #ifdef CONFIG_RTIO_SUBMIT_SEM - Z_OOPS(Z_SYSCALL_OBJ(r->submit_sem, K_OBJ_SEM)); + K_OOPS(K_SYSCALL_OBJ(r->submit_sem, K_OBJ_SEM)); #endif return z_impl_rtio_submit(r, wait_count); diff --git a/subsys/sd/Kconfig b/subsys/sd/Kconfig index 37ef6372a77..403eaef341a 100644 --- a/subsys/sd/Kconfig +++ b/subsys/sd/Kconfig @@ -72,6 +72,8 @@ config SD_BUFFER_SIZE default 512 if SDHC_BUFFER_ALIGNMENT != 1 # If MMC is being used, need 512 bytes to read EXT_CSD default 512 if MMC_STACK + # If SDIO is being used, need 512 bytes to read FUNC0 CIS + default 512 if SDIO_STACK # Otherwise, we only need 64 bytes to read SD switch function default 64 help diff --git a/subsys/sd/mmc.c b/subsys/sd/mmc.c index eada1ec261f..8ea0b5746d7 100644 --- a/subsys/sd/mmc.c +++ b/subsys/sd/mmc.c @@ -380,10 +380,10 @@ static int mmc_set_bus_width(struct sd_card *card) int ret; struct sdhc_command cmd = {0}; - if (card->host_props.host_caps.bus_8_bit_support) { + if (card->host_props.host_caps.bus_8_bit_support && card->bus_width == 8) { cmd.arg = MMC_SWITCH_8_BIT_BUS_ARG; card->bus_io.bus_width = SDHC_BUS_WIDTH8BIT; - } else if (card->host_props.host_caps.bus_4_bit_support) { + } else if (card->host_props.host_caps.bus_4_bit_support && card->bus_width >= 4) { cmd.arg = MMC_SWITCH_4_BIT_BUS_ARG; card->bus_io.bus_width = SDHC_BUS_WIDTH4BIT; } else { diff --git a/subsys/sd/sd.c b/subsys/sd/sd.c index ca00c8bcca4..87ec7a29910 100644 --- a/subsys/sd/sd.c +++ b/subsys/sd/sd.c @@ -117,7 +117,8 @@ static int sd_common_init(struct sd_card *card) static int sd_init_io(struct sd_card *card) { struct sdhc_io *bus_io = &card->bus_io; - int ret; + struct sdhc_host_props *host_props = &card->host_props; + int ret, voltage; /* SD clock should start gated */ bus_io->clock = 0; @@ -125,9 +126,22 @@ static int sd_init_io(struct sd_card *card) bus_io->bus_mode = SDHC_BUSMODE_PUSHPULL; bus_io->power_mode = SDHC_POWER_ON; bus_io->bus_width = SDHC_BUS_WIDTH1BIT; - /* Cards start with legacy timing and 3.3V signalling at power on */ + /* Cards start with legacy timing and Maximum voltage Host controller support */ bus_io->timing = SDHC_TIMING_LEGACY; - bus_io->signal_voltage = SD_VOL_3_3_V; + + if (host_props->host_caps.vol_330_support) { + LOG_DBG("Host controller support 3.3V max"); + voltage = SD_VOL_3_3_V; + } else if (host_props->host_caps.vol_300_support) { + LOG_DBG("Host controller support 3.0V max"); + voltage = SD_VOL_3_0_V; + } else { + LOG_DBG("Host controller support 1.8V max"); + voltage = SD_VOL_1_8_V; + } + + /* Set to maximum voltage support by Host controller */ + bus_io->signal_voltage = voltage; /* Toggle power to card to reset it */ LOG_DBG("Resetting power to card"); @@ -144,8 +158,8 @@ static int sd_init_io(struct sd_card *card) LOG_ERR("Could not disable card power via SDHC"); return ret; } - /* After reset or init, card voltage should be 3.3V */ - card->card_voltage = SD_VOL_3_3_V; + /* After reset or init, card voltage should be max HC support */ + card->card_voltage = voltage; /* Reset card flags */ card->flags = 0U; /* Delay so card can power up */ diff --git a/subsys/sd/sdio.c b/subsys/sd/sdio.c index cdf02814443..ea507fbf496 100644 --- a/subsys/sd/sdio.c +++ b/subsys/sd/sdio.c @@ -1,24 +1,31 @@ /* - * Copyright 2022 NXP + * Copyright 2022-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include #include #include #include #include +#include "sd_ops.h" #include "sd_utils.h" LOG_MODULE_DECLARE(sd, CONFIG_SD_LOG_LEVEL); +uint8_t cis_tuples[] = { + SDIO_TPL_CODE_MANIFID, + SDIO_TPL_CODE_FUNCID, + SDIO_TPL_CODE_FUNCE, +}; + /* * Send SDIO OCR using CMD5 */ -int sdio_send_ocr(struct sd_card *card, uint32_t ocr) +static int sdio_send_ocr(struct sd_card *card, uint32_t ocr) { struct sdhc_command cmd = {0}; int ret; @@ -56,7 +63,482 @@ int sdio_send_ocr(struct sd_card *card, uint32_t ocr) */ return 0; } + /* Check to see if card is busy with power up */ + if (cmd.response[0] & SD_OCR_PWR_BUSY_FLAG) { + break; + } + /* Delay before retrying command */ + sd_delay(10); + } + if (retries >= CONFIG_SD_OCR_RETRY_COUNT) { + /* OCR timed out */ + LOG_ERR("Card never left busy state"); + return -ETIMEDOUT; + } + LOG_DBG("SDIO responded to CMD5 after %d attempts", retries); + if (!card->host_props.is_spi) { + /* Save OCR */ + card->ocr = cmd.response[0U]; + } + return 0; +} + +static int sdio_io_rw_direct(struct sd_card *card, + enum sdio_io_dir direction, + enum sdio_func_num func, + uint32_t reg_addr, + uint8_t data_in, + uint8_t *data_out) +{ + int ret; + struct sdhc_command cmd = {0}; + + cmd.opcode = SDIO_RW_DIRECT; + cmd.arg = (func << SDIO_CMD_ARG_FUNC_NUM_SHIFT) | + ((reg_addr & SDIO_CMD_ARG_REG_ADDR_MASK) << SDIO_CMD_ARG_REG_ADDR_SHIFT); + if (direction == SDIO_IO_WRITE) { + cmd.arg |= data_in & SDIO_DIRECT_CMD_DATA_MASK; + cmd.arg |= BIT(SDIO_CMD_ARG_RW_SHIFT); + if (data_out) { + cmd.arg |= BIT(SDIO_DIRECT_CMD_ARG_RAW_SHIFT); + } + } + cmd.response_type = (SD_RSP_TYPE_R5 | SD_SPI_RSP_TYPE_R5); + cmd.timeout_ms = CONFIG_SD_CMD_TIMEOUT; + + ret = sdhc_request(card->sdhc, &cmd, NULL); + if (ret) { + return ret; + } + if (data_out) { + if (card->host_props.is_spi) { + *data_out = (cmd.response[0U] >> 8) & SDIO_DIRECT_CMD_DATA_MASK; + } else { + *data_out = cmd.response[0U] & SDIO_DIRECT_CMD_DATA_MASK; + } + } + return ret; +} + + +static int sdio_io_rw_extended(struct sd_card *card, + enum sdio_io_dir direction, + enum sdio_func_num func, + uint32_t reg_addr, + bool increment, + uint8_t *buf, + uint32_t blocks, + uint32_t block_size) +{ + struct sdhc_command cmd = {0}; + struct sdhc_data data = {0}; + + cmd.opcode = SDIO_RW_EXTENDED; + cmd.arg = (func << SDIO_CMD_ARG_FUNC_NUM_SHIFT) | + ((reg_addr & SDIO_CMD_ARG_REG_ADDR_MASK) << SDIO_CMD_ARG_REG_ADDR_SHIFT); + cmd.arg |= (direction == SDIO_IO_WRITE) ? BIT(SDIO_CMD_ARG_RW_SHIFT) : 0; + cmd.arg |= increment ? BIT(SDIO_EXTEND_CMD_ARG_OP_CODE_SHIFT) : 0; + cmd.response_type = (SD_RSP_TYPE_R5 | SD_SPI_RSP_TYPE_R5); + cmd.timeout_ms = CONFIG_SD_CMD_TIMEOUT; + if (blocks == 0) { + /* Byte mode */ + cmd.arg |= (block_size == 512) ? 0 : block_size; + } else { + /* Block mode */ + cmd.arg |= BIT(SDIO_EXTEND_CMD_ARG_BLK_SHIFT) | blocks; } + + data.block_size = block_size; + /* Host expects blocks to be at least 1 */ + data.blocks = blocks ? blocks : 1; + data.data = buf; + data.timeout_ms = CONFIG_SD_DATA_TIMEOUT; + return sdhc_request(card->sdhc, &cmd, &data); +} + +/* + * Helper for extended r/w. Splits the transfer into the minimum possible + * number of block r/w, then uses byte transfers for remaining data + */ +static int sdio_io_rw_extended_helper(struct sdio_func *func, + enum sdio_io_dir direction, + uint32_t reg_addr, + bool increment, + uint8_t *buf, + uint32_t len) +{ + int ret; + int remaining = len; + uint32_t blocks, size; + + if (func->num > SDIO_MAX_IO_NUMS) { + return -EINVAL; + } + + if ((func->card->cccr_flags & SDIO_SUPPORT_MULTIBLOCK) && + ((len > func->block_size))) { + /* Use block I/O for r/w where possible */ + while (remaining >= func->block_size) { + blocks = remaining / func->block_size; + size = blocks * func->block_size; + ret = sdio_io_rw_extended(func->card, direction, + func->num, reg_addr, increment, buf, blocks, + func->block_size); + if (ret) { + return ret; + } + /* Update remaining length and buffer pointer */ + remaining -= size; + buf += size; + if (increment) { + reg_addr += size; + } + } + } + /* Remaining data must be written using byte I/O */ + while (remaining > 0) { + size = MIN(remaining, func->cis.max_blk_size); + + ret = sdio_io_rw_extended(func->card, direction, func->num, + reg_addr, increment, buf, 0, size); + if (ret) { + return ret; + } + remaining -= size; + buf += size; + if (increment) { + reg_addr += size; + } + } + return 0; +} + +/* + * Read card capability register to determine features card supports. + */ +static int sdio_read_cccr(struct sd_card *card) +{ + int ret; + uint8_t data; + uint32_t cccr_ver; + + ret = sdio_io_rw_direct(card, SDIO_IO_READ, SDIO_FUNC_NUM_0, + SDIO_CCCR_CCCR, 0, &data); + if (ret) { + LOG_DBG("CCCR read failed: %d", ret); + return ret; + } + cccr_ver = (data & SDIO_CCCR_CCCR_REV_MASK) >> + SDIO_CCCR_CCCR_REV_SHIFT; + LOG_DBG("SDIO cccr revision %u", cccr_ver); + /* Read SD spec version */ + ret = sdio_io_rw_direct(card, SDIO_IO_READ, SDIO_FUNC_NUM_0, + SDIO_CCCR_SD, 0, &data); + if (ret) { + return ret; + } + card->sd_version = (data & SDIO_CCCR_SD_SPEC_MASK) >> SDIO_CCCR_SD_SPEC_SHIFT; + /* Read CCCR capability flags */ + ret = sdio_io_rw_direct(card, SDIO_IO_READ, SDIO_FUNC_NUM_0, + SDIO_CCCR_CAPS, 0, &data); + if (ret) { + return ret; + } + card->cccr_flags = 0; + if (data & SDIO_CCCR_CAPS_BLS) { + card->cccr_flags |= SDIO_SUPPORT_4BIT_LS_BUS; + } + if (data & SDIO_CCCR_CAPS_SMB) { + card->cccr_flags |= SDIO_SUPPORT_MULTIBLOCK; + } + if (cccr_ver >= SDIO_CCCR_CCCR_REV_2_00) { + /* Read high speed properties */ + ret = sdio_io_rw_direct(card, SDIO_IO_READ, SDIO_FUNC_NUM_0, + SDIO_CCCR_SPEED, 0, &data); + if (ret) { + return ret; + } + if (data & SDIO_CCCR_SPEED_SHS) { + card->cccr_flags |= SDIO_SUPPORT_HS; + } + } + if (cccr_ver >= SDIO_CCCR_CCCR_REV_3_00 && + (card->flags & SD_1800MV_FLAG)) { + /* Read UHS properties */ + ret = sdio_io_rw_direct(card, SDIO_IO_READ, SDIO_FUNC_NUM_0, + SDIO_CCCR_UHS, 0, &data); + if (ret) { + return ret; + } + if (sdmmc_host_uhs(&card->host_props)) { + if (data & SDIO_CCCR_UHS_SDR50) { + card->cccr_flags |= SDIO_SUPPORT_SDR50; + } + if (data & SDIO_CCCR_UHS_SDR104) { + card->cccr_flags |= SDIO_SUPPORT_SDR104; + } + if (data & SDIO_CCCR_UHS_DDR50) { + card->cccr_flags |= SDIO_SUPPORT_DDR50; + } + } + + ret = sdio_io_rw_direct(card, SDIO_IO_READ, SDIO_FUNC_NUM_0, + SDIO_CCCR_DRIVE_STRENGTH, 0, &data); + if (ret) { + return ret; + } + card->switch_caps.sd_drv_type = 0; + if (data & SDIO_CCCR_DRIVE_STRENGTH_A) { + card->switch_caps.sd_drv_type |= SD_DRIVER_TYPE_A; + } + if (data & SDIO_CCCR_DRIVE_STRENGTH_C) { + card->switch_caps.sd_drv_type |= SD_DRIVER_TYPE_C; + } + if (data & SDIO_CCCR_DRIVE_STRENGTH_D) { + card->switch_caps.sd_drv_type |= SD_DRIVER_TYPE_D; + } + } + return 0; +} + +static void sdio_decode_cis(struct sdio_cis *cis, enum sdio_func_num func, + uint8_t *data, uint8_t tpl_code, uint8_t tpl_link) +{ + switch (tpl_code) { + case SDIO_TPL_CODE_MANIFID: + cis->manf_id = data[0] | ((uint16_t)data[1] << 8); + cis->manf_code = data[2] | ((uint16_t)data[3] << 8); + break; + case SDIO_TPL_CODE_FUNCID: + cis->func_id = data[0]; + break; + case SDIO_TPL_CODE_FUNCE: + if (func == 0) { + cis->max_blk_size = data[1] | ((uint16_t)data[2] << 8); + cis->max_speed = data[3]; + } else { + cis->max_blk_size = data[12] | ((uint16_t)data[13] << 8); + cis->rdy_timeout = data[28] | ((uint16_t)data[29] << 8); + } + break; + default: + LOG_WRN("Unknown CIS tuple %d", tpl_code); + break; + } +} + +/* + * Read CIS for a given SDIO function. + * Tuples provides a list of tuples that should be decoded. + */ +static int sdio_read_cis(struct sdio_func *func, + uint8_t *tuples, + uint32_t tuple_count) +{ + int ret; + char *data = func->card->card_buffer; + uint32_t cis_ptr = 0, num = 0; + uint8_t tpl_code, tpl_link; + bool match_tpl = false; + + memset(&func->cis, 0, sizeof(struct sdio_cis)); + /* First find the CIS pointer for this function */ + for (int i = 0; i < 3; i++) { + ret = sdio_io_rw_direct(func->card, SDIO_IO_READ, SDIO_FUNC_NUM_0, + SDIO_FBR_BASE(func->num) + SDIO_FBR_CIS + i, 0, data); + if (ret) { + return ret; + } + cis_ptr |= *data << (i * 8); + } + /* Read CIS tuples until we have read all requested CIS tuple codes */ + do { + /* Read tuple code */ + ret = sdio_io_rw_direct(func->card, SDIO_IO_READ, SDIO_FUNC_NUM_0, + cis_ptr++, 0, &tpl_code); + if (ret) { + return ret; + } + if (tpl_code == SDIO_TPL_CODE_END) { + /* End of tuple chain */ + break; + } + if (tpl_code == SDIO_TPL_CODE_NULL) { + /* Skip NULL tuple */ + continue; + } + /* Read tuple link */ + ret = sdio_io_rw_direct(func->card, SDIO_IO_READ, SDIO_FUNC_NUM_0, + cis_ptr++, 0, &tpl_link); + if (ret) { + return ret; + } + if (tpl_link == SDIO_TPL_CODE_END) { + /* End of tuple chain */ + break; + } + /* Check to see if read tuple matches any we should look for */ + for (int i = 0; i < tuple_count; i++) { + if (tpl_code == tuples[i]) { + match_tpl = true; + break; + } + } + if (match_tpl) { + /* tuple chains may be maximum of 255 bytes long */ + memset(data, 0, 255); + for (int i = 0; i < tpl_link; i++) { + ret = sdio_io_rw_direct(func->card, SDIO_IO_READ, + SDIO_FUNC_NUM_0, cis_ptr++, 0, data + i); + if (ret) { + return ret; + } + } + num++; + match_tpl = false; + /* Decode the CIS data we read */ + sdio_decode_cis(&func->cis, func->num, data, + tpl_code, tpl_link); + } else { + /* Advance CIS pointer */ + cis_ptr += tpl_link; + } + } while (num < tuple_count); + LOG_DBG("SDIO CIS max block size for func %d: %d", func->num, + func->cis.max_blk_size); + return ret; +} + +static int sdio_set_bus_width(struct sd_card *card, enum sdhc_bus_width width) +{ + uint8_t reg_bus_interface = 0U; + int ret; + + ret = sdio_io_rw_direct(card, SDIO_IO_READ, SDIO_FUNC_NUM_0, + SDIO_CCCR_BUS_IF, 0, ®_bus_interface); + if (ret) { + return ret; + } + reg_bus_interface &= ~SDIO_CCCR_BUS_IF_WIDTH_MASK; + switch (width) { + case SDHC_BUS_WIDTH1BIT: + reg_bus_interface |= SDIO_CCCR_BUS_IF_WIDTH_1_BIT; + break; + case SDHC_BUS_WIDTH4BIT: + reg_bus_interface |= SDIO_CCCR_BUS_IF_WIDTH_4_BIT; + break; + case SDHC_BUS_WIDTH8BIT: + reg_bus_interface |= SDIO_CCCR_BUS_IF_WIDTH_8_BIT; + break; + default: + return -ENOTSUP; + } + ret = sdio_io_rw_direct(card, SDIO_IO_WRITE, SDIO_FUNC_NUM_0, + SDIO_CCCR_BUS_IF, reg_bus_interface, ®_bus_interface); + if (ret) { + return ret; + } + /* Card now has changed bus width. Change host bus width */ + card->bus_io.bus_width = width; + ret = sdhc_set_io(card->sdhc, &card->bus_io); + if (ret) { + LOG_DBG("Could not change host bus width"); + } + return ret; +} + +static inline void sdio_select_bus_speed(struct sd_card *card) +{ + if (card->host_props.host_caps.sdr104_support && + (card->cccr_flags & SDIO_SUPPORT_SDR104) && + (card->host_props.f_max >= SD_CLOCK_208MHZ)) { + card->card_speed = SD_TIMING_SDR104; + } else if (card->host_props.host_caps.ddr50_support && + (card->cccr_flags & SDIO_SUPPORT_DDR50) && + (card->host_props.f_max >= SD_CLOCK_50MHZ)) { + card->card_speed = SD_TIMING_DDR50; + } else if (card->host_props.host_caps.sdr50_support && + (card->cccr_flags & SDIO_SUPPORT_SDR50) && + (card->host_props.f_max >= SD_CLOCK_100MHZ)) { + card->card_speed = SD_TIMING_SDR50; + } else if (card->host_props.host_caps.high_spd_support && + (card->switch_caps.bus_speed & SDIO_SUPPORT_HS) && + (card->host_props.f_max >= SD_CLOCK_50MHZ)) { + card->card_speed = SD_TIMING_SDR25; + } else { + card->card_speed = SD_TIMING_SDR12; + } +} + +/* Applies selected card bus speed to card and host */ +static int sdio_set_bus_speed(struct sd_card *card) +{ + int ret, timing, retries = CONFIG_SD_RETRY_COUNT; + uint8_t speed_reg, target_speed; + + switch (card->card_speed) { + /* Set bus clock speed */ + case SD_TIMING_SDR104: + card->switch_caps.uhs_max_dtr = SD_CLOCK_208MHZ; + target_speed = SDIO_CCCR_SPEED_SDR104; + timing = SDHC_TIMING_SDR104; + break; + case SD_TIMING_DDR50: + card->switch_caps.uhs_max_dtr = SD_CLOCK_50MHZ; + target_speed = SDIO_CCCR_SPEED_DDR50; + timing = SDHC_TIMING_DDR50; + break; + case SD_TIMING_SDR50: + card->switch_caps.uhs_max_dtr = SD_CLOCK_100MHZ; + target_speed = SDIO_CCCR_SPEED_SDR50; + timing = SDHC_TIMING_SDR50; + break; + case SD_TIMING_SDR25: + card->switch_caps.uhs_max_dtr = SD_CLOCK_50MHZ; + target_speed = SDIO_CCCR_SPEED_SDR25; + timing = SDHC_TIMING_SDR25; + break; + case SD_TIMING_SDR12: + card->switch_caps.uhs_max_dtr = SD_CLOCK_25MHZ; + target_speed = SDIO_CCCR_SPEED_SDR12; + timing = SDHC_TIMING_SDR12; + break; + default: + /* No need to change bus speed */ + return 0; + } + /* Read the bus speed register */ + ret = sdio_io_rw_direct(card, SDIO_IO_READ, SDIO_FUNC_NUM_0, + SDIO_CCCR_SPEED, 0, &speed_reg); + if (ret) { + return ret; + } + /* Attempt to set speed several times */ + do { + /* Set new speed */ + speed_reg &= ~SDIO_CCCR_SPEED_MASK; + speed_reg |= (target_speed << SDIO_CCCR_SPEED_SHIFT); + ret = sdio_io_rw_direct(card, SDIO_IO_WRITE, SDIO_FUNC_NUM_0, + SDIO_CCCR_SPEED, speed_reg, &speed_reg); + if (ret) { + return ret; + } + } while (((speed_reg & target_speed) != target_speed) && retries-- > 0); + if (retries == 0) { + /* Don't error out, as card can still work */ + LOG_WRN("Could not set target SDIO speed"); + } else { + /* Set card bus clock and timing */ + card->bus_io.timing = timing; + card->bus_io.clock = card->switch_caps.uhs_max_dtr; + LOG_DBG("Setting bus clock to: %d", card->bus_io.clock); + ret = sdhc_set_io(card->sdhc, &card->bus_io); + if (ret) { + LOG_ERR("Failed to change host bus speed"); + return ret; + } + } + return ret; } /* @@ -65,14 +547,524 @@ int sdio_send_ocr(struct sd_card *card, uint32_t ocr) int sdio_card_init(struct sd_card *card) { int ret; + uint32_t ocr_arg = 0U; /* Probe card with SDIO OCR CM5 */ - ret = sdio_send_ocr(card, 0); + ret = sdio_send_ocr(card, ocr_arg); if (ret) { return ret; } - /* Card responded to ACMD41, type is SDIO */ + /* Card responded to CMD5, type is SDIO */ card->type = CARD_SDIO; - /* No support for SDIO */ - return -ENOTSUP; + /* Set voltage window */ + if (card->host_props.host_caps.vol_300_support) { + ocr_arg |= SD_OCR_VDD29_30FLAG; + } + ocr_arg |= (SD_OCR_VDD32_33FLAG | SD_OCR_VDD33_34FLAG); + if (IS_ENABLED(CONFIG_SDHC_SUPPORTS_NATIVE_MODE) && + card->host_props.host_caps.vol_180_support) { + /* See if the card also supports 1.8V */ + ocr_arg |= SD_OCR_SWITCH_18_REQ_FLAG; + } + ret = sdio_send_ocr(card, ocr_arg); + if (ret) { + return ret; + } + if (card->ocr & SD_OCR_SWITCH_18_ACCEPT_FLAG) { + LOG_DBG("Card supports 1.8V signalling"); + card->flags |= SD_1800MV_FLAG; + } + /* Check OCR voltage window */ + if (card->ocr & SD_OCR_VDD29_30FLAG) { + card->flags |= SD_3000MV_FLAG; + } + /* Check mem present flag */ + if (card->ocr & SDIO_OCR_MEM_PRESENT_FLAG) { + card->flags |= SD_MEM_PRESENT_FLAG; + } + /* Following steps are only required when using native SD mode */ + if (IS_ENABLED(CONFIG_SDHC_SUPPORTS_NATIVE_MODE)) { + /* + * If card and host support 1.8V, perform voltage switch sequence now. + * note that we skip this switch if the UHS protocol is not enabled. + */ + if ((card->flags & SD_1800MV_FLAG) && + (!card->host_props.is_spi) && + (card->host_props.host_caps.vol_180_support) && + IS_ENABLED(CONFIG_SD_UHS_PROTOCOL)) { + ret = sdmmc_switch_voltage(card); + if (ret) { + /* Disable host support for 1.8 V */ + card->host_props.host_caps.vol_180_support = false; + /* + * The host or SD card may have already switched to + * 1.8V. Return SD_RESTART to indicate + * negotiation should be restarted. + */ + card->status = CARD_ERROR; + return SD_RESTART; + } + } + if ((card->flags & SD_MEM_PRESENT_FLAG) && + ((card->flags & SD_SDHC_FLAG) == 0)) { + /* We must send CMD2 to get card cid */ + ret = card_read_cid(card); + if (ret) { + return ret; + } + } + /* Send CMD3 to get card relative address */ + ret = sdmmc_request_rca(card); + if (ret) { + return ret; + } + /* Move the card to transfer state (with CMD7) to run + * remaining commands + */ + ret = sdmmc_select_card(card); + if (ret) { + return ret; + } + } + /* Read SDIO card common control register */ + ret = sdio_read_cccr(card); + if (ret) { + return ret; + } + /* Initialize internal card function 0 structure */ + card->func0.num = SDIO_FUNC_NUM_0; + card->func0.card = card; + ret = sdio_read_cis(&card->func0, cis_tuples, + ARRAY_SIZE(cis_tuples)); + if (ret) { + return ret; + } + + /* If card and host support 4 bit bus, enable it */ + if (IS_ENABLED(CONFIG_SDHC_SUPPORTS_NATIVE_MODE) && + ((card->cccr_flags & SDIO_SUPPORT_HS) || + (card->cccr_flags & SDIO_SUPPORT_4BIT_LS_BUS))) { + /* Raise bus width to 4 bits */ + ret = sdio_set_bus_width(card, SDHC_BUS_WIDTH4BIT); + if (ret) { + return ret; + } + LOG_DBG("Raised card bus width to 4 bits"); + } + + /* Select and set bus speed */ + sdio_select_bus_speed(card); + ret = sdio_set_bus_speed(card); + if (ret) { + return ret; + } + if (card->card_speed == SD_TIMING_SDR50 || + card->card_speed == SD_TIMING_SDR104) { + /* SDR104, SDR50, and DDR50 mode need tuning */ + ret = sdhc_execute_tuning(card->sdhc); + if (ret) { + LOG_ERR("SD tuning failed: %d", ret); + } + } + return ret; +} + +/** + * @brief Initialize SDIO function. + * + * Initializes SDIO card function. The card function will not be enabled, + * but after this call returns the SDIO function structure can be used to read + * and write data from the card. + * @param func: function structure to initialize + * @param card: SD card to enable function on + * @param num: function number to initialize + * @retval 0 function was initialized successfully + * @retval -EIO: I/O error + */ +int sdio_init_func(struct sd_card *card, struct sdio_func *func, + enum sdio_func_num num) +{ + /* Initialize function structure */ + func->num = num; + func->card = card; + func->block_size = 0; + /* Read function properties from CCCR */ + return sdio_read_cis(func, cis_tuples, ARRAY_SIZE(cis_tuples)); +} + + + +/** + * @brief Enable SDIO function + * + * Enables SDIO card function. @ref sdio_init_func must be called to + * initialized the function structure before enabling it in the card. + * @param func: function to enable + * @retval 0 function was enabled successfully + * @retval -ETIMEDOUT: card I/O timed out + * @retval -EIO: I/O error + */ +int sdio_enable_func(struct sdio_func *func) +{ + int ret; + uint8_t reg; + uint16_t retries = CONFIG_SD_RETRY_COUNT; + + /* Enable the I/O function */ + ret = sdio_io_rw_direct(func->card, SDIO_IO_READ, SDIO_FUNC_NUM_0, + SDIO_CCCR_IO_EN, 0, ®); + if (ret) { + return ret; + } + reg |= BIT(func->num); + ret = sdio_io_rw_direct(func->card, SDIO_IO_WRITE, SDIO_FUNC_NUM_0, + SDIO_CCCR_IO_EN, reg, ®); + if (ret) { + return ret; + } + /* Wait for I/O ready to be set */ + if (func->cis.rdy_timeout) { + retries = 1U; + } + do { + /* Timeout is in units of 10ms */ + sd_delay(((uint32_t)func->cis.rdy_timeout) * 10U); + ret = sdio_io_rw_direct(func->card, SDIO_IO_READ, + SDIO_FUNC_NUM_0, SDIO_CCCR_IO_RD, 0, ®); + if (ret) { + return ret; + } + if (reg & BIT(func->num)) { + return 0; + } + } while (retries-- != 0); + return -ETIMEDOUT; +} + +/** + * @brief Set block size of SDIO function + * + * Set desired block size for SDIO function, used by block transfers + * to SDIO registers. + * @param func: function to set block size for + * @param bsize: block size + * @retval 0 block size was set + * @retval -EINVAL: unsupported/invalid block size + * @retval -EIO: I/O error + */ +int sdio_set_block_size(struct sdio_func *func, uint16_t bsize) +{ + int ret; + uint8_t reg; + + if (func->cis.max_blk_size < bsize) { + return -EINVAL; + } + for (int i = 0; i < 2; i++) { + reg = (bsize >> (i * 8)); + ret = sdio_io_rw_direct(func->card, SDIO_IO_WRITE, SDIO_FUNC_NUM_0, + SDIO_FBR_BASE(func->num) + SDIO_FBR_BLK_SIZE + i, reg, NULL); + if (ret) { + return ret; + } + } + func->block_size = bsize; + return 0; +} + +/** + * @brief Read byte from SDIO register + * + * Reads byte from SDIO register + * @param func: function to read from + * @param reg: register address to read from + * @param val: filled with byte value read from register + * @retval 0 read succeeded + * @retval -EBUSY: card is busy with another request + * @retval -ETIMEDOUT: card read timed out + * @retval -EIO: I/O error + */ +int sdio_read_byte(struct sdio_func *func, uint32_t reg, uint8_t *val) +{ + int ret; + + if ((func->card->type != CARD_SDIO) && (func->card->type != CARD_COMBO)) { + LOG_WRN("Card does not support SDIO commands"); + return -ENOTSUP; + } + ret = k_mutex_lock(&func->card->lock, K_NO_WAIT); + if (ret) { + LOG_WRN("Could not get SD card mutex"); + return -EBUSY; + } + ret = sdio_io_rw_direct(func->card, SDIO_IO_READ, func->num, reg, 0, val); + k_mutex_unlock(&func->card->lock); + return ret; +} + +/** + * @brief Write byte to SDIO register + * + * Writes byte to SDIO register + * @param func: function to write to + * @param reg: register address to write to + * @param write_val: value to write to register + * @retval 0 write succeeded + * @retval -EBUSY: card is busy with another request + * @retval -ETIMEDOUT: card write timed out + * @retval -EIO: I/O error + */ +int sdio_write_byte(struct sdio_func *func, uint32_t reg, uint8_t write_val) +{ + int ret; + + if ((func->card->type != CARD_SDIO) && (func->card->type != CARD_COMBO)) { + LOG_WRN("Card does not support SDIO commands"); + return -ENOTSUP; + } + ret = k_mutex_lock(&func->card->lock, K_NO_WAIT); + if (ret) { + LOG_WRN("Could not get SD card mutex"); + return -EBUSY; + } + ret = sdio_io_rw_direct(func->card, SDIO_IO_WRITE, func->num, reg, + write_val, NULL); + k_mutex_unlock(&func->card->lock); + return ret; +} + +/** + * @brief Write byte to SDIO register, and read result + * + * Writes byte to SDIO register, and reads the register after write + * @param func: function to write to + * @param reg: register address to write to + * @param write_val: value to write to register + * @param read_val: filled with value read from register + * @retval 0 write succeeded + * @retval -EBUSY: card is busy with another request + * @retval -ETIMEDOUT: card write timed out + * @retval -EIO: I/O error + */ +int sdio_rw_byte(struct sdio_func *func, uint32_t reg, uint8_t write_val, + uint8_t *read_val) +{ + int ret; + + if ((func->card->type != CARD_SDIO) && (func->card->type != CARD_COMBO)) { + LOG_WRN("Card does not support SDIO commands"); + return -ENOTSUP; + } + ret = k_mutex_lock(&func->card->lock, K_NO_WAIT); + if (ret) { + LOG_WRN("Could not get SD card mutex"); + return -EBUSY; + } + ret = sdio_io_rw_direct(func->card, SDIO_IO_WRITE, func->num, reg, + write_val, read_val); + k_mutex_unlock(&func->card->lock); + return ret; +} + +/** + * @brief Read bytes from SDIO fifo + * + * Reads bytes from SDIO register, treating it as a fifo. Reads will + * all be done from same address. + * @param func: function to read from + * @param reg: register address of fifo + * @param data: filled with data read from fifo + * @param len: length of data to read from card + * @retval 0 read succeeded + * @retval -EBUSY: card is busy with another request + * @retval -ETIMEDOUT: card read timed out + * @retval -EIO: I/O error + */ +int sdio_read_fifo(struct sdio_func *func, uint32_t reg, uint8_t *data, + uint32_t len) +{ + int ret; + + if ((func->card->type != CARD_SDIO) && (func->card->type != CARD_COMBO)) { + LOG_WRN("Card does not support SDIO commands"); + return -ENOTSUP; + } + ret = k_mutex_lock(&func->card->lock, K_NO_WAIT); + if (ret) { + LOG_WRN("Could not get SD card mutex"); + return -EBUSY; + } + ret = sdio_io_rw_extended_helper(func, SDIO_IO_READ, reg, false, + data, len); + k_mutex_unlock(&func->card->lock); + return ret; +} + +/** + * @brief Write bytes to SDIO fifo + * + * Writes bytes to SDIO register, treating it as a fifo. Writes will + * all be done to same address. + * @param func: function to write to + * @param reg: register address of fifo + * @param data: data to write to fifo + * @param len: length of data to write to card + * @retval 0 write succeeded + * @retval -EBUSY: card is busy with another request + * @retval -ETIMEDOUT: card write timed out + * @retval -EIO: I/O error + */ +int sdio_write_fifo(struct sdio_func *func, uint32_t reg, uint8_t *data, + uint32_t len) +{ + int ret; + + if ((func->card->type != CARD_SDIO) && (func->card->type != CARD_COMBO)) { + LOG_WRN("Card does not support SDIO commands"); + return -ENOTSUP; + } + ret = k_mutex_lock(&func->card->lock, K_NO_WAIT); + if (ret) { + LOG_WRN("Could not get SD card mutex"); + return -EBUSY; + } + ret = sdio_io_rw_extended_helper(func, SDIO_IO_WRITE, reg, false, + data, len); + k_mutex_unlock(&func->card->lock); + return ret; +} + +/** + * @brief Read blocks from SDIO fifo + * + * Reads blocks from SDIO register, treating it as a fifo. Reads will + * all be done from same address. + * @param func: function to read from + * @param reg: register address of fifo + * @param data: filled with data read from fifo + * @param blocks: number of blocks to read from fifo + * @retval 0 read succeeded + * @retval -EBUSY: card is busy with another request + * @retval -ETIMEDOUT: card read timed out + * @retval -EIO: I/O error + */ +int sdio_read_blocks_fifo(struct sdio_func *func, uint32_t reg, uint8_t *data, + uint32_t blocks) +{ + int ret; + + if ((func->card->type != CARD_SDIO) && (func->card->type != CARD_COMBO)) { + LOG_WRN("Card does not support SDIO commands"); + return -ENOTSUP; + } + ret = k_mutex_lock(&func->card->lock, K_NO_WAIT); + if (ret) { + LOG_WRN("Could not get SD card mutex"); + return -EBUSY; + } + ret = sdio_io_rw_extended(func->card, SDIO_IO_READ, func->num, reg, + false, data, blocks, func->block_size); + k_mutex_unlock(&func->card->lock); + return ret; +} + +/** + * @brief Write blocks to SDIO fifo + * + * Writes blocks from SDIO register, treating it as a fifo. Writes will + * all be done to same address. + * @param func: function to write to + * @param reg: register address of fifo + * @param data: data to write to fifo + * @param blocks: number of blocks to write to fifo + * @retval 0 write succeeded + * @retval -EBUSY: card is busy with another request + * @retval -ETIMEDOUT: card write timed out + * @retval -EIO: I/O error + */ +int sdio_write_blocks_fifo(struct sdio_func *func, uint32_t reg, uint8_t *data, + uint32_t blocks) +{ + int ret; + + if ((func->card->type != CARD_SDIO) && (func->card->type != CARD_COMBO)) { + LOG_WRN("Card does not support SDIO commands"); + return -ENOTSUP; + } + ret = k_mutex_lock(&func->card->lock, K_NO_WAIT); + if (ret) { + LOG_WRN("Could not get SD card mutex"); + return -EBUSY; + } + ret = sdio_io_rw_extended(func->card, SDIO_IO_WRITE, func->num, reg, + false, data, blocks, func->block_size); + k_mutex_unlock(&func->card->lock); + return ret; +} + +/** + * @brief Copy bytes from an SDIO card + * + * Copies bytes from an SDIO card, starting from provided address. + * @param func: function to read from + * @param reg: register address to start copy at + * @param data: buffer to copy data into + * @param len: length of data to read + * @retval 0 read succeeded + * @retval -EBUSY: card is busy with another request + * @retval -ETIMEDOUT: card read timed out + * @retval -EIO: I/O error + */ +int sdio_read_addr(struct sdio_func *func, uint32_t reg, uint8_t *data, + uint32_t len) +{ + int ret; + + if ((func->card->type != CARD_SDIO) && (func->card->type != CARD_COMBO)) { + LOG_WRN("Card does not support SDIO commands"); + return -ENOTSUP; + } + ret = k_mutex_lock(&func->card->lock, K_NO_WAIT); + if (ret) { + LOG_WRN("Could not get SD card mutex"); + return -EBUSY; + } + ret = sdio_io_rw_extended_helper(func, SDIO_IO_READ, reg, true, + data, len); + k_mutex_unlock(&func->card->lock); + return ret; +} + +/** + * @brief Copy bytes to an SDIO card + * + * Copies bytes to an SDIO card, starting from provided address. + * + * @param func: function to write to + * @param reg: register address to start copy at + * @param data: buffer to copy data from + * @param len: length of data to write + * @retval 0 write succeeded + * @retval -EBUSY: card is busy with another request + * @retval -ETIMEDOUT: card write timed out + * @retval -EIO: I/O error + */ +int sdio_write_addr(struct sdio_func *func, uint32_t reg, uint8_t *data, + uint32_t len) +{ + int ret; + + if ((func->card->type != CARD_SDIO) && (func->card->type != CARD_COMBO)) { + LOG_WRN("Card does not support SDIO commands"); + return -ENOTSUP; + } + ret = k_mutex_lock(&func->card->lock, K_NO_WAIT); + if (ret) { + LOG_WRN("Could not get SD card mutex"); + return -EBUSY; + } + ret = sdio_io_rw_extended_helper(func, SDIO_IO_WRITE, reg, true, + data, len); + k_mutex_unlock(&func->card->lock); + return ret; } diff --git a/subsys/settings/src/settings_shell.c b/subsys/settings/src/settings_shell.c index 7a9de6416e6..e8132eeeb49 100644 --- a/subsys/settings/src/settings_shell.c +++ b/subsys/settings/src/settings_shell.c @@ -56,8 +56,14 @@ static int cmd_list(const struct shell *shell_ptr, size_t argc, char *argv[]) return err; } +enum settings_value_types { + SETTINGS_VALUE_HEX, + SETTINGS_VALUE_STRING, +}; + struct settings_read_callback_params { const struct shell *shell_ptr; + const enum settings_value_types value_type; bool value_found; }; @@ -84,7 +90,23 @@ static int settings_read_callback(const char *key, return 0; } - shell_hexdump(params->shell_ptr, buffer, num_read_bytes); + if (num_read_bytes == 0) { + shell_warn(params->shell_ptr, "Value is empty"); + return 0; + } + + switch (params->value_type) { + case SETTINGS_VALUE_HEX: + shell_hexdump(params->shell_ptr, buffer, num_read_bytes); + break; + case SETTINGS_VALUE_STRING: + if (buffer[num_read_bytes - 1] != '\0') { + shell_error(params->shell_ptr, "Value is not a string"); + return 0; + } + shell_print(params->shell_ptr, "%s", buffer); + break; + } if (len > SETTINGS_MAX_VAL_LEN) { shell_print(params->shell_ptr, "(The output has been truncated)"); @@ -93,17 +115,40 @@ static int settings_read_callback(const char *key, return 0; } +static int settings_parse_type(const char *type, enum settings_value_types *value_type) +{ + if (strcmp(type, "string") == 0) { + *value_type = SETTINGS_VALUE_STRING; + } else if (strcmp(type, "hex") == 0) { + *value_type = SETTINGS_VALUE_HEX; + } else { + return -EINVAL; + } + + return 0; +} + static int cmd_read(const struct shell *shell_ptr, size_t argc, char *argv[]) { int err; - const char *name = argv[1]; + + enum settings_value_types value_type = SETTINGS_VALUE_HEX; + + if (argc > 2) { + err = settings_parse_type(argv[1], &value_type); + if (err) { + shell_error(shell_ptr, "Invalid type: %s", argv[1]); + return err; + } + } struct settings_read_callback_params params = { .shell_ptr = shell_ptr, + .value_type = value_type, .value_found = false }; - err = settings_load_subtree_direct(name, settings_read_callback, ¶ms); + err = settings_load_subtree_direct(argv[argc - 1], settings_read_callback, ¶ms); if (err) { shell_error(shell_ptr, "Failed to load setting: %d", err); @@ -119,16 +164,34 @@ static int cmd_write(const struct shell *shell_ptr, size_t argc, char *argv[]) { int err; uint8_t buffer[CONFIG_SHELL_CMD_BUFF_SIZE / 2]; - size_t buffer_len; + size_t buffer_len = 0; + enum settings_value_types value_type = SETTINGS_VALUE_HEX; + + if (argc > 3) { + err = settings_parse_type(argv[1], &value_type); + if (err) { + shell_error(shell_ptr, "Invalid type: %s", argv[1]); + return err; + } + } - buffer_len = hex2bin(argv[2], strlen(argv[2]), buffer, sizeof(buffer)); + switch (value_type) { + case SETTINGS_VALUE_HEX: + buffer_len = hex2bin(argv[argc - 1], strlen(argv[argc - 1]), + buffer, sizeof(buffer)); + break; + case SETTINGS_VALUE_STRING: + buffer_len = strlen(argv[argc - 1]) + 1; + memcpy(buffer, argv[argc - 1], buffer_len); + break; + } if (buffer_len == 0) { - shell_error(shell_ptr, "Failed to parse hex value"); + shell_error(shell_ptr, "Failed to parse value"); return -EINVAL; } - err = settings_save_one(argv[1], buffer, buffer_len); + err = settings_save_one(argv[argc - 2], buffer, buffer_len); if (err) { shell_error(shell_ptr, "Failed to write setting: %d", err); @@ -151,11 +214,25 @@ static int cmd_delete(const struct shell *shell_ptr, size_t argc, char *argv[]) } SHELL_STATIC_SUBCMD_SET_CREATE(settings_cmds, - SHELL_CMD_ARG(list, NULL, "[]", cmd_list, 1, 1), - SHELL_CMD_ARG(read, NULL, "", cmd_read, 2, 0), - SHELL_CMD_ARG(write, NULL, " ", cmd_write, 3, 0), - SHELL_CMD_ARG(delete, NULL, "", cmd_delete, 2, 0), - SHELL_SUBCMD_SET_END); + SHELL_CMD_ARG(list, NULL, + "List all settings in a subtree (omit to list all)\n" + "Usage: settings list [subtree]", + cmd_list, 1, 1), + SHELL_CMD_ARG(read, NULL, + "Read a specific setting\n" + "Usage: settings read [type] \n" + "type: string or hex (default: hex)", + cmd_read, 2, 1), + SHELL_CMD_ARG(write, NULL, + "Write to a specific setting\n" + "Usage: settings write [type] \n" + "type: string or hex (default: hex)", + cmd_write, 3, 1), + SHELL_CMD_ARG(delete, NULL, + "Delete a specific setting\n" + "Usage: settings delete ", + cmd_delete, 2, 0), + SHELL_SUBCMD_SET_END); static int cmd_settings(const struct shell *shell_ptr, size_t argc, char **argv) { diff --git a/subsys/shell/backends/Kconfig.backends b/subsys/shell/backends/Kconfig.backends index 9bab0be275d..e4e826b0316 100644 --- a/subsys/shell/backends/Kconfig.backends +++ b/subsys/shell/backends/Kconfig.backends @@ -18,8 +18,7 @@ config SHELL_BACKEND_SERIAL bool "Serial backend" # Serial (UART) requires interrupts and the RTT backend cannot be used from an ISR context. default n if SHELL_BACKEND_RTT - default "$(dt_chosen_enabled,$(DT_CHOSEN_Z_SHELL_UART))" if HAS_DTS - default y if !HAS_DTS + default "$(dt_chosen_enabled,$(DT_CHOSEN_Z_SHELL_UART))" select SERIAL select RING_BUFFER help @@ -43,23 +42,44 @@ config SHELL_PROMPT_UART Displayed prompt name for UART backend. If prompt is set, the shell will send two newlines during initialization. -# Internal config to enable UART interrupts if supported. config SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN bool "Interrupt driven" default y depends on SERIAL_SUPPORT_INTERRUPT + +choice SHELL_BACKEND_SERIAL_API + prompt "Mode" + default SHELL_BACKEND_SERIAL_API_ASYNC if UART_ASYNC_API + default SHELL_BACKEND_SERIAL_API_INTERRUPT_DRIVEN if SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN + default SHELL_BACKEND_SERIAL_API_POLLING + +config SHELL_BACKEND_SERIAL_API_POLLING + prompt "Polling" + +config SHELL_BACKEND_SERIAL_API_INTERRUPT_DRIVEN + bool "Interrupt driven" + depends on SERIAL_SUPPORT_INTERRUPT select UART_INTERRUPT_DRIVEN + +config SHELL_BACKEND_SERIAL_API_ASYNC + bool "Asynchronous" + depends on SERIAL_SUPPORT_ASYNC + select UART_ASYNC_RX_HELPER + +endchoice + config SHELL_BACKEND_SERIAL_TX_RING_BUFFER_SIZE int "Set TX ring buffer size" default 8 - depends on SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN + depends on SHELL_BACKEND_SERIAL_API_INTERRUPT_DRIVEN help If UART is utilizing DMA transfers then increasing ring buffer size increases transfers length and reduces number of interrupts. config SHELL_BACKEND_SERIAL_RX_RING_BUFFER_SIZE int "Set RX ring buffer size" + depends on SHELL_BACKEND_SERIAL_API_INTERRUPT_DRIVEN || SHELL_BACKEND_SERIAL_API_POLLING default 256 if MCUMGR_TRANSPORT_SHELL default 64 help @@ -69,16 +89,45 @@ config SHELL_BACKEND_SERIAL_RX_RING_BUFFER_SIZE escape sequences). However, if bulk data is transferred it may be required to increase it. +if SHELL_BACKEND_SERIAL_API_ASYNC + +config SHELL_BACKEND_SERIAL_ASYNC_RX_TIMEOUT + int "RX inactivity timeout (in microseconds)" + default 10000 + help + Inactivity timeout after which received data is reported. + +config SHELL_BACKEND_SERIAL_ASYNC_RX_BUFFER_COUNT + int "Number of RX buffers" + default 4 + range 2 64 + help + Number of RX buffers. Some UART driver implementations changes buffers + on timeout so this number should be big enough to cover handling on + time incoming data. 4 should be enough for almost all the cases unless + CPU load is high and there is very high shell thread latency. + +config SHELL_BACKEND_SERIAL_ASYNC_RX_BUFFER_SIZE + int "Size of the RX buffer" + default 16 + help + Size of a single RX buffer. Together with buffer count it defines the + space that can hold RX data. It may be decreased if shell input is + slow and may need to be increased if long messages are pasted directly + to the shell prompt. + +endif # SHELL_BACKEND_SERIAL_API_ASYNC + config SHELL_BACKEND_SERIAL_RX_POLL_PERIOD int "RX polling period (in milliseconds)" default 10 - depends on !SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN + depends on SHELL_BACKEND_SERIAL_API_POLLING help Determines how often UART is polled for RX byte. config SHELL_BACKEND_SERIAL_CHECK_DTR bool "Check DTR signal before TX" - depends on SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN + depends on SHELL_BACKEND_SERIAL_API_INTERRUPT_DRIVEN depends on UART_LINE_CTRL help Check DTR signal before TX. @@ -346,7 +395,11 @@ config SHELL_TELNET_SUPPORT_COMMAND help Current support is so limited it's not interesting to enable it. However, if proven to be needed at some point, it will be possible - to extend such support. + to extend such support. It does have support for echo and "character + at a time" mode, which enable the history and line-editing features + of the shell. + IMPORTANT: This will increase network usage as a TCP packet will be + sent each time a character is typed in the telnet client. module = SHELL_TELNET default-timeout = 100 diff --git a/subsys/shell/backends/shell_telnet.c b/subsys/shell/backends/shell_telnet.c index 312c1dcb4e1..a4dab627299 100644 --- a/subsys/shell/backends/shell_telnet.c +++ b/subsys/shell/backends/shell_telnet.c @@ -85,12 +85,56 @@ static void telnet_reply_ay_command(void) telnet_command_send_reply((uint8_t *)alive, strlen(alive)); } +static int telnet_echo_set(const struct shell *sh, bool val) +{ + int ret = shell_echo_set(sh_telnet->shell_context, val); + + if (ret < 0) { + LOG_ERR("Failed to set echo to: %d, err: %d", val, ret); + } + return ret; +} + +static void telnet_reply_dont_command(struct telnet_simple_command *cmd) +{ + switch (cmd->opt) { + case NVT_OPT_ECHO: + { + int ret = telnet_echo_set(sh_telnet->shell_context, false); + + if (ret >= 0) { + cmd->op = NVT_CMD_WONT; + } else { + cmd->op = NVT_CMD_WILL; + } + break; + } + default: + cmd->op = NVT_CMD_WONT; + break; + } + + telnet_command_send_reply((uint8_t *)cmd, + sizeof(struct telnet_simple_command)); +} + static void telnet_reply_do_command(struct telnet_simple_command *cmd) { switch (cmd->opt) { case NVT_OPT_SUPR_GA: cmd->op = NVT_CMD_WILL; break; + case NVT_OPT_ECHO: + { + int ret = telnet_echo_set(sh_telnet->shell_context, true); + + if (ret >= 0) { + cmd->op = NVT_CMD_WILL; + } else { + cmd->op = NVT_CMD_WONT; + } + break; + } default: cmd->op = NVT_CMD_WONT; break; @@ -120,6 +164,9 @@ static void telnet_reply_command(struct telnet_simple_command *cmd) case NVT_CMD_DO: telnet_reply_do_command(cmd); break; + case NVT_CMD_DONT: + telnet_reply_dont_command(cmd); + break; default: LOG_DBG("Operation %u not handled", cmd->op); break; @@ -250,8 +297,6 @@ static void telnet_accept(struct net_context *client, int error, void *user_data) { - int ret; - if (error) { LOG_ERR("Error %d", error); goto error; @@ -275,13 +320,10 @@ static void telnet_accept(struct net_context *client, sh_telnet->client_ctx = client; - /* Disable echo - if command handling is enabled we reply that we don't + /* Disable echo - if command handling is enabled we reply that we * support echo. */ - ret = shell_echo_set(sh_telnet->shell_context, false); - if (ret < 0) { - LOG_ERR("Failed to disable echo, err: %d", ret); - } + (void)telnet_echo_set(sh_telnet->shell_context, false); return; error: diff --git a/subsys/shell/backends/shell_uart.c b/subsys/shell/backends/shell_uart.c index ce52eb15d8c..5e4e3bd2c95 100644 --- a/subsys/shell/backends/shell_uart.c +++ b/subsys/shell/backends/shell_uart.c @@ -4,8 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include #include #include +#include #include #include #include @@ -19,34 +23,122 @@ LOG_MODULE_REGISTER(shell_uart); #define RX_POLL_PERIOD K_NO_WAIT #endif +#ifndef CONFIG_SHELL_BACKEND_SERIAL_RX_RING_BUFFER_SIZE +#define CONFIG_SHELL_BACKEND_SERIAL_RX_RING_BUFFER_SIZE 0 +#endif + +#ifndef CONFIG_SHELL_BACKEND_SERIAL_TX_RING_BUFFER_SIZE +#define CONFIG_SHELL_BACKEND_SERIAL_TX_RING_BUFFER_SIZE 0 +#endif + +#ifndef CONFIG_SHELL_BACKEND_SERIAL_ASYNC_RX_BUFFER_COUNT +#define CONFIG_SHELL_BACKEND_SERIAL_ASYNC_RX_BUFFER_COUNT 0 +#endif + +#ifndef CONFIG_SHELL_BACKEND_SERIAL_ASYNC_RX_BUFFER_SIZE +#define CONFIG_SHELL_BACKEND_SERIAL_ASYNC_RX_BUFFER_SIZE 0 +#endif + +#define ASYNC_RX_BUF_SIZE (CONFIG_SHELL_BACKEND_SERIAL_ASYNC_RX_BUFFER_COUNT * \ + (CONFIG_SHELL_BACKEND_SERIAL_ASYNC_RX_BUFFER_SIZE + \ + UART_ASYNC_RX_BUF_OVERHEAD)) + +struct shell_uart_common { + const struct device *dev; + shell_transport_handler_t handler; + void *context; + bool blocking_tx; +#ifdef CONFIG_MCUMGR_TRANSPORT_SHELL + struct smp_shell_data smp; +#endif /* CONFIG_MCUMGR_TRANSPORT_SHELL */ +}; + +struct shell_uart_int_driven { + struct shell_uart_common common; + struct ring_buf tx_ringbuf; + struct ring_buf rx_ringbuf; + struct k_timer dtr_timer; + atomic_t tx_busy; +}; + +struct shell_uart_async { + struct shell_uart_common common; + struct k_sem tx_sem; + struct uart_async_rx async_rx; + atomic_t pending_rx_req; +}; + +struct shell_uart_polling { + struct shell_uart_common common; + struct ring_buf rx_ringbuf; + struct k_timer rx_timer; +}; + +static uint8_t __noinit async_rx_data[ASYNC_RX_BUF_SIZE]; +static uint8_t __noinit rx_ringbuf_data[CONFIG_SHELL_BACKEND_SERIAL_RX_RING_BUFFER_SIZE]; +static uint8_t __noinit tx_ringbuf_data[CONFIG_SHELL_BACKEND_SERIAL_TX_RING_BUFFER_SIZE]; + +static struct shell_uart_int_driven shell_uart_i; +static struct shell_uart_async shell_uart_a; +static struct shell_uart_polling shell_uart_p; + #ifdef CONFIG_MCUMGR_TRANSPORT_SHELL NET_BUF_POOL_DEFINE(smp_shell_rx_pool, CONFIG_MCUMGR_TRANSPORT_SHELL_RX_BUF_COUNT, SMP_SHELL_RX_BUF_SIZE, 0, NULL); #endif /* CONFIG_MCUMGR_TRANSPORT_SHELL */ -SHELL_UART_DEFINE(shell_transport_uart, - CONFIG_SHELL_BACKEND_SERIAL_TX_RING_BUFFER_SIZE, - CONFIG_SHELL_BACKEND_SERIAL_RX_RING_BUFFER_SIZE); -SHELL_DEFINE(shell_uart, CONFIG_SHELL_PROMPT_UART, &shell_transport_uart, - CONFIG_SHELL_BACKEND_SERIAL_LOG_MESSAGE_QUEUE_SIZE, - CONFIG_SHELL_BACKEND_SERIAL_LOG_MESSAGE_QUEUE_TIMEOUT, - SHELL_FLAG_OLF_CRLF); +static void async_callback(const struct device *dev, struct uart_event *evt, void *user_data) +{ + struct shell_uart_async *sh_uart = (struct shell_uart_async *)user_data; + + switch (evt->type) { + case UART_TX_DONE: + k_sem_give(&sh_uart->tx_sem); + break; + case UART_RX_RDY: + uart_async_rx_on_rdy(&sh_uart->async_rx, evt->data.rx.buf, evt->data.rx.len); + sh_uart->common.handler(SHELL_TRANSPORT_EVT_RX_RDY, sh_uart->common.context); + break; + case UART_RX_BUF_REQUEST: + { + uint8_t *buf = uart_async_rx_buf_req(&sh_uart->async_rx); + size_t len = uart_async_rx_get_buf_len(&sh_uart->async_rx); + + if (buf) { + int err = uart_rx_buf_rsp(dev, buf, len); + + if (err < 0) { + uart_async_rx_on_buf_rel(&sh_uart->async_rx, buf); + } + } else { + atomic_inc(&sh_uart->pending_rx_req); + } + + break; + } + case UART_RX_BUF_RELEASED: + uart_async_rx_on_buf_rel(&sh_uart->async_rx, evt->data.rx_buf.buf); + break; + case UART_RX_DISABLED: + break; + default: + break; + }; +} -#ifdef CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN -static void uart_rx_handle(const struct device *dev, - const struct shell_uart *sh_uart) +static void uart_rx_handle(const struct device *dev, struct shell_uart_int_driven *sh_uart) { uint8_t *data; uint32_t len; uint32_t rd_len; bool new_data = false; #ifdef CONFIG_MCUMGR_TRANSPORT_SHELL - struct smp_shell_data *const smp = &sh_uart->ctrl_blk->smp; + struct smp_shell_data *const smp = &sh_uart->common.smp; #endif do { - len = ring_buf_put_claim(sh_uart->rx_ringbuf, &data, - sh_uart->rx_ringbuf->size); + len = ring_buf_put_claim(&sh_uart->rx_ringbuf, &data, + sh_uart->rx_ringbuf.size); if (len > 0) { rd_len = uart_fifo_read(dev, data, len); @@ -72,8 +164,7 @@ static void uart_rx_handle(const struct device *dev, } } #endif /* CONFIG_MCUMGR_TRANSPORT_SHELL */ - int err = ring_buf_put_finish(sh_uart->rx_ringbuf, - rd_len); + int err = ring_buf_put_finish(&sh_uart->rx_ringbuf, rd_len); (void)err; __ASSERT_NO_MSG(err == 0); } else { @@ -87,8 +178,7 @@ static void uart_rx_handle(const struct device *dev, /* If successful in getting byte from the fifo, try * feeding it to SMP as a part of mcumgr frame. */ - if ((rd_len != 0) && - (smp_shell_rx_bytes(smp, &dummy, 1) == 1)) { + if ((rd_len != 0) && (smp_shell_rx_bytes(smp, &dummy, 1) == 1)) { new_data = true; } #endif /* CONFIG_MCUMGR_TRANSPORT_SHELL */ @@ -96,8 +186,7 @@ static void uart_rx_handle(const struct device *dev, } while (rd_len && (rd_len == len)); if (new_data) { - sh_uart->ctrl_blk->handler(SHELL_TRANSPORT_EVT_RX_RDY, - sh_uart->ctrl_blk->context); + sh_uart->common.handler(SHELL_TRANSPORT_EVT_RX_RDY, sh_uart->common.context); } } @@ -123,19 +212,18 @@ static bool uart_dtr_check(const struct device *dev) static void dtr_timer_handler(struct k_timer *timer) { - const struct shell_uart *sh_uart = k_timer_user_data_get(timer); + struct shell_uart_int_driven *sh_uart = k_timer_user_data_get(timer); - if (!uart_dtr_check(sh_uart->ctrl_blk->dev)) { + if (!uart_dtr_check(sh_uart->common.dev)) { return; } /* DTR is active, stop timer and start TX */ k_timer_stop(timer); - uart_irq_tx_enable(sh_uart->ctrl_blk->dev); + uart_irq_tx_enable(sh_uart->common.dev); } -static void uart_tx_handle(const struct device *dev, - const struct shell_uart *sh_uart) +static void uart_tx_handle(const struct device *dev, struct shell_uart_int_driven *sh_uart) { uint32_t len; const uint8_t *data; @@ -143,31 +231,30 @@ static void uart_tx_handle(const struct device *dev, if (!uart_dtr_check(dev)) { /* Wait for DTR signal before sending anything to output. */ uart_irq_tx_disable(dev); - k_timer_start(sh_uart->dtr_timer, K_MSEC(100), K_MSEC(100)); + k_timer_start(&sh_uart->dtr_timer, K_MSEC(100), K_MSEC(100)); return; } - len = ring_buf_get_claim(sh_uart->tx_ringbuf, (uint8_t **)&data, - sh_uart->tx_ringbuf->size); + len = ring_buf_get_claim(&sh_uart->tx_ringbuf, (uint8_t **)&data, + sh_uart->tx_ringbuf.size); if (len) { int err; len = uart_fifo_fill(dev, data, len); - err = ring_buf_get_finish(sh_uart->tx_ringbuf, len); + err = ring_buf_get_finish(&sh_uart->tx_ringbuf, len); __ASSERT_NO_MSG(err == 0); ARG_UNUSED(err); } else { uart_irq_tx_disable(dev); - sh_uart->ctrl_blk->tx_busy = 0; + sh_uart->tx_busy = 0; } - sh_uart->ctrl_blk->handler(SHELL_TRANSPORT_EVT_TX_RDY, - sh_uart->ctrl_blk->context); + sh_uart->common.handler(SHELL_TRANSPORT_EVT_TX_RDY, sh_uart->common.context); } static void uart_callback(const struct device *dev, void *user_data) { - const struct shell_uart *sh_uart = (struct shell_uart *)user_data; + struct shell_uart_int_driven *sh_uart = (struct shell_uart_int_driven *)user_data; uart_irq_update(dev); @@ -179,80 +266,135 @@ static void uart_callback(const struct device *dev, void *user_data) uart_tx_handle(dev, sh_uart); } } -#endif /* CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN */ -static void uart_irq_init(const struct shell_uart *sh_uart) +static void irq_init(struct shell_uart_int_driven *sh_uart) { -#ifdef CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN - const struct device *dev = sh_uart->ctrl_blk->dev; + const struct device *dev = sh_uart->common.dev; - ring_buf_reset(sh_uart->tx_ringbuf); - ring_buf_reset(sh_uart->rx_ringbuf); - sh_uart->ctrl_blk->tx_busy = 0; + ring_buf_init(&sh_uart->rx_ringbuf, CONFIG_SHELL_BACKEND_SERIAL_RX_RING_BUFFER_SIZE, + rx_ringbuf_data); + ring_buf_init(&sh_uart->tx_ringbuf, CONFIG_SHELL_BACKEND_SERIAL_TX_RING_BUFFER_SIZE, + tx_ringbuf_data); + sh_uart->tx_busy = 0; uart_irq_callback_user_data_set(dev, uart_callback, (void *)sh_uart); uart_irq_rx_enable(dev); if (IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL_CHECK_DTR)) { - k_timer_init(sh_uart->dtr_timer, dtr_timer_handler, NULL); - k_timer_user_data_set(sh_uart->dtr_timer, (void *)sh_uart); + k_timer_init(&sh_uart->dtr_timer, dtr_timer_handler, NULL); + k_timer_user_data_set(&sh_uart->dtr_timer, (void *)sh_uart); } -#endif } -static void timer_handler(struct k_timer *timer) +static int rx_enable(const struct device *dev, uint8_t *buf, size_t len) +{ + return uart_rx_enable(dev, buf, len, 10000); +} + +static void async_init(struct shell_uart_async *sh_uart) +{ + static const struct uart_async_rx_config async_rx_config = { + .buffer = async_rx_data, + .length = sizeof(async_rx_data), + .buf_cnt = CONFIG_SHELL_BACKEND_SERIAL_ASYNC_RX_BUFFER_COUNT + }; + const struct device *dev = sh_uart->common.dev; + struct uart_async_rx *async_rx = &sh_uart->async_rx; + int err; + + k_sem_init(&sh_uart->tx_sem, 0, 1); + + err = uart_async_rx_init(async_rx, &async_rx_config); + (void)err; + __ASSERT_NO_MSG(err == 0); + + uint8_t *buf = uart_async_rx_buf_req(async_rx); + + err = uart_callback_set(dev, async_callback, (void *)sh_uart); + (void)err; + __ASSERT_NO_MSG(err == 0); + + err = rx_enable(dev, buf, uart_async_rx_get_buf_len(async_rx)); + (void)err; + __ASSERT_NO_MSG(err == 0); +} + +static void polling_rx_timeout_handler(struct k_timer *timer) { uint8_t c; - const struct shell_uart *sh_uart = k_timer_user_data_get(timer); + struct shell_uart_polling *sh_uart = k_timer_user_data_get(timer); - while (uart_poll_in(sh_uart->ctrl_blk->dev, &c) == 0) { - if (ring_buf_put(sh_uart->rx_ringbuf, &c, 1) == 0U) { + while (uart_poll_in(sh_uart->common.dev, &c) == 0) { + if (ring_buf_put(&sh_uart->rx_ringbuf, &c, 1) == 0U) { /* ring buffer full. */ LOG_WRN("RX ring buffer full."); } - sh_uart->ctrl_blk->handler(SHELL_TRANSPORT_EVT_RX_RDY, - sh_uart->ctrl_blk->context); + sh_uart->common.handler(SHELL_TRANSPORT_EVT_RX_RDY, sh_uart->common.context); } } +static void polling_init(struct shell_uart_polling *sh_uart) +{ + k_timer_init(&sh_uart->rx_timer, polling_rx_timeout_handler, NULL); + k_timer_user_data_set(&sh_uart->rx_timer, (void *)sh_uart); + k_timer_start(&sh_uart->rx_timer, RX_POLL_PERIOD, RX_POLL_PERIOD); + + ring_buf_init(&sh_uart->rx_ringbuf, CONFIG_SHELL_BACKEND_SERIAL_RX_RING_BUFFER_SIZE, + rx_ringbuf_data); +} + static int init(const struct shell_transport *transport, const void *config, shell_transport_handler_t evt_handler, void *context) { - const struct shell_uart *sh_uart = (struct shell_uart *)transport->ctx; + struct shell_uart_common *common = (struct shell_uart_common *)transport->ctx; - sh_uart->ctrl_blk->dev = (const struct device *)config; - sh_uart->ctrl_blk->handler = evt_handler; - sh_uart->ctrl_blk->context = context; + common->dev = (const struct device *)config; + common->handler = evt_handler; + common->context = context; #ifdef CONFIG_MCUMGR_TRANSPORT_SHELL - sh_uart->ctrl_blk->smp.buf_pool = &smp_shell_rx_pool; - k_fifo_init(&sh_uart->ctrl_blk->smp.buf_ready); + common->smp.buf_pool = &smp_shell_rx_pool; + k_fifo_init(&common->smp.buf_ready); #endif - if (IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN)) { - uart_irq_init(sh_uart); + if (IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL_API_ASYNC)) { + async_init((struct shell_uart_async *)transport->ctx); + } else if (IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL_API_INTERRUPT_DRIVEN)) { + irq_init((struct shell_uart_int_driven *)transport->ctx); } else { - k_timer_init(sh_uart->timer, timer_handler, NULL); - k_timer_user_data_set(sh_uart->timer, (void *)sh_uart); - k_timer_start(sh_uart->timer, RX_POLL_PERIOD, RX_POLL_PERIOD); + polling_init((struct shell_uart_polling *)transport->ctx); } return 0; } -static int uninit(const struct shell_transport *transport) +static void irq_uninit(struct shell_uart_int_driven *sh_uart) +{ + const struct device *dev = sh_uart->common.dev; + + k_timer_stop(&sh_uart->dtr_timer); + uart_irq_tx_disable(dev); + uart_irq_rx_disable(dev); +} + +static void async_uninit(struct shell_uart_async *sh_uart) { - const struct shell_uart *sh_uart = (struct shell_uart *)transport->ctx; +} - if (IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN)) { - const struct device *dev = sh_uart->ctrl_blk->dev; +static void polling_uninit(struct shell_uart_polling *sh_uart) +{ + k_timer_stop(&sh_uart->rx_timer); +} - k_timer_stop(sh_uart->dtr_timer); - uart_irq_tx_disable(dev); - uart_irq_rx_disable(dev); +static int uninit(const struct shell_transport *transport) +{ + if (IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL_API_ASYNC)) { + async_uninit((struct shell_uart_async *)transport->ctx); + } else if (IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL_API_INTERRUPT_DRIVEN)) { + irq_uninit((struct shell_uart_int_driven *)transport->ctx); } else { - k_timer_stop(sh_uart->timer); + polling_uninit((struct shell_uart_polling *)transport->ctx); } return 0; @@ -260,70 +402,165 @@ static int uninit(const struct shell_transport *transport) static int enable(const struct shell_transport *transport, bool blocking_tx) { - const struct shell_uart *sh_uart = (struct shell_uart *)transport->ctx; + struct shell_uart_common *sh_uart = (struct shell_uart_common *)transport->ctx; - sh_uart->ctrl_blk->blocking_tx = blocking_tx; + sh_uart->blocking_tx = blocking_tx; - if (blocking_tx) { -#ifdef CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN - uart_irq_tx_disable(sh_uart->ctrl_blk->dev); -#endif + if (IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL_API_INTERRUPT_DRIVEN) && blocking_tx) { + uart_irq_tx_disable(sh_uart->dev); } return 0; } -static void irq_write(const struct shell_uart *sh_uart, const void *data, - size_t length, size_t *cnt) +static int polling_write(struct shell_uart_common *sh_uart, + const void *data, size_t length, size_t *cnt) { - *cnt = ring_buf_put(sh_uart->tx_ringbuf, data, length); + const uint8_t *data8 = (const uint8_t *)data; - if (atomic_set(&sh_uart->ctrl_blk->tx_busy, 1) == 0) { -#ifdef CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN - uart_irq_tx_enable(sh_uart->ctrl_blk->dev); -#endif + for (size_t i = 0; i < length; i++) { + uart_poll_out(sh_uart->dev, data8[i]); + } + + *cnt = length; + + sh_uart->handler(SHELL_TRANSPORT_EVT_TX_RDY, sh_uart->context); + + return 0; +} + +static int irq_write(struct shell_uart_int_driven *sh_uart, + const void *data, size_t length, size_t *cnt) +{ + *cnt = ring_buf_put(&sh_uart->tx_ringbuf, data, length); + + if (atomic_set(&sh_uart->tx_busy, 1) == 0) { + uart_irq_tx_enable(sh_uart->common.dev); } + + return 0; +} + +static int async_write(struct shell_uart_async *sh_uart, + const void *data, size_t length, size_t *cnt) +{ + int err; + + err = uart_tx(sh_uart->common.dev, data, length, SYS_FOREVER_US); + if (err < 0) { + *cnt = 0; + return err; + } + + err = k_sem_take(&sh_uart->tx_sem, K_FOREVER); + *cnt = length; + + sh_uart->common.handler(SHELL_TRANSPORT_EVT_TX_RDY, sh_uart->common.context); + + return err; } static int write(const struct shell_transport *transport, const void *data, size_t length, size_t *cnt) { - const struct shell_uart *sh_uart = (struct shell_uart *)transport->ctx; - const uint8_t *data8 = (const uint8_t *)data; + struct shell_uart_common *sh_uart = (struct shell_uart_common *)transport->ctx; - if (IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN) && - !sh_uart->ctrl_blk->blocking_tx) { - irq_write(sh_uart, data, length, cnt); + if (IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL_API_POLLING) || sh_uart->blocking_tx) { + return polling_write(sh_uart, data, length, cnt); + } else if (IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL_API_INTERRUPT_DRIVEN)) { + return irq_write((struct shell_uart_int_driven *)transport->ctx, data, length, cnt); } else { - for (size_t i = 0; i < length; i++) { - uart_poll_out(sh_uart->ctrl_blk->dev, data8[i]); - } + return async_write((struct shell_uart_async *)transport->ctx, data, length, cnt); + } +} - *cnt = length; +static int irq_read(struct shell_uart_int_driven *sh_uart, + void *data, size_t length, size_t *cnt) +{ + *cnt = ring_buf_get(&sh_uart->rx_ringbuf, data, length); - sh_uart->ctrl_blk->handler(SHELL_TRANSPORT_EVT_TX_RDY, - sh_uart->ctrl_blk->context); - } + return 0; +} + +static int polling_read(struct shell_uart_polling *sh_uart, + void *data, size_t length, size_t *cnt) +{ + *cnt = ring_buf_get(&sh_uart->rx_ringbuf, data, length); return 0; } -static int read(const struct shell_transport *transport, - void *data, size_t length, size_t *cnt) +static int async_read(struct shell_uart_async *sh_uart, + void *data, size_t length, size_t *cnt) { - struct shell_uart *sh_uart = (struct shell_uart *)transport->ctx; + uint8_t *buf; + size_t blen; + struct uart_async_rx *async_rx = &sh_uart->async_rx; + + blen = uart_async_rx_data_claim(async_rx, &buf, length); +#ifdef CONFIG_MCUMGR_TRANSPORT_SHELL + struct smp_shell_data *const smp = &sh_uart->common.smp; + size_t sh_cnt = 0; - *cnt = ring_buf_get(sh_uart->rx_ringbuf, data, length); + for (size_t i = 0; i < blen; i++) { + if (smp_shell_rx_bytes(smp, &buf[i], 1) == 0) { + ((uint8_t *)data)[sh_cnt++] = buf[i]; + } + } +#else + size_t sh_cnt = blen; + + memcpy(data, buf, blen); +#endif + uart_async_rx_data_consume(async_rx, sh_cnt); + *cnt = sh_cnt; + + if (sh_uart->pending_rx_req) { + uint8_t *buf = uart_async_rx_buf_req(async_rx); + + if (buf) { + int err; + size_t len = uart_async_rx_get_buf_len(async_rx); + + atomic_dec(&sh_uart->pending_rx_req); + err = uart_rx_buf_rsp(sh_uart->common.dev, buf, len); + /* If it is too late and RX is disabled then re-enable it. */ + if (err < 0) { + if (err == -EACCES) { + sh_uart->pending_rx_req = 0; + err = rx_enable(sh_uart->common.dev, buf, len); + } else { + return err; + } + } + } + } return 0; } +static int read(const struct shell_transport *transport, + void *data, size_t length, size_t *cnt) +{ + if (IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL_API_INTERRUPT_DRIVEN)) { + return irq_read((struct shell_uart_int_driven *)transport->ctx, data, length, cnt); + } else if (IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL_API_ASYNC)) { + return async_read((struct shell_uart_async *)transport->ctx, data, length, cnt); + } else { + return polling_read((struct shell_uart_polling *)transport->ctx, data, length, cnt); + } +} + #ifdef CONFIG_MCUMGR_TRANSPORT_SHELL static void update(const struct shell_transport *transport) { - struct shell_uart *sh_uart = (struct shell_uart *)transport->ctx; + /* + * This is dependent on the fact that `struct shell_uart_common` + * is always the first member, regardless of the UART configuration + */ + struct shell_uart_common *sh_uart = (struct shell_uart_common *)transport->ctx; - smp_shell_process(&sh_uart->ctrl_blk->smp); + smp_shell_process(&sh_uart->smp); } #endif /* CONFIG_MCUMGR_TRANSPORT_SHELL */ @@ -338,6 +575,27 @@ const struct shell_transport_api shell_uart_transport_api = { #endif /* CONFIG_MCUMGR_TRANSPORT_SHELL */ }; +struct shell_transport shell_transport_uart = { + .api = &shell_uart_transport_api, + .ctx = IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL_API_POLLING) ? (void *)&shell_uart_p : + (IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL_API_ASYNC) ? (void *)&shell_uart_a : + (void *)&shell_uart_i) +}; + +SHELL_DEFINE(shell_uart, CONFIG_SHELL_PROMPT_UART, &shell_transport_uart, + CONFIG_SHELL_BACKEND_SERIAL_LOG_MESSAGE_QUEUE_SIZE, + CONFIG_SHELL_BACKEND_SERIAL_LOG_MESSAGE_QUEUE_TIMEOUT, + SHELL_FLAG_OLF_CRLF); + +#ifdef CONFIG_MCUMGR_TRANSPORT_SHELL +struct smp_shell_data *shell_uart_smp_shell_data_get_ptr(void) +{ + struct shell_uart_common *common = (struct shell_uart_common *)shell_transport_uart.ctx; + + return &common->smp; +} +#endif + static int enable_shell_uart(void) { const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_shell_uart)); diff --git a/subsys/shell/modules/kernel_service.c b/subsys/shell/modules/kernel_service.c index 065cdcb4b96..58a3a454dc5 100644 --- a/subsys/shell/modules/kernel_service.c +++ b/subsys/shell/modules/kernel_service.c @@ -44,13 +44,45 @@ static int cmd_kernel_version(const struct shell *sh, return 0; } -static int cmd_kernel_uptime(const struct shell *sh, - size_t argc, char **argv) +#define MINUTES_FACTOR (MSEC_PER_SEC * SEC_PER_MIN) +#define HOURS_FACTOR (MINUTES_FACTOR * MIN_PER_HOUR) +#define DAYS_FACTOR (HOURS_FACTOR * HOUR_PER_DAY) + +static int cmd_kernel_uptime(const struct shell *sh, size_t argc, char **argv) { ARG_UNUSED(argc); ARG_UNUSED(argv); - shell_print(sh, "Uptime: %u ms", k_uptime_get_32()); + int64_t milliseconds = k_uptime_get(); + int64_t days; + int64_t hours; + int64_t minutes; + int64_t seconds; + + if (argc == 1) { + shell_print(sh, "Uptime: %llu ms", milliseconds); + return 0; + } + + /* No need to enable the getopt and getopt_long for just one option. */ + if (strcmp("-p", argv[1]) && strcmp("--pretty", argv[1]) != 0) { + shell_error(sh, "Usupported option: %s", argv[1]); + return -EIO; + } + + days = milliseconds / DAYS_FACTOR; + milliseconds %= DAYS_FACTOR; + hours = milliseconds / HOURS_FACTOR; + milliseconds %= HOURS_FACTOR; + minutes = milliseconds / MINUTES_FACTOR; + milliseconds %= MINUTES_FACTOR; + seconds = milliseconds / MSEC_PER_SEC; + milliseconds = milliseconds % MSEC_PER_SEC; + + shell_print(sh, + "uptime: %llu days, %llu hours, %llu minutes, %llu seconds, %llu milliseconds", + days, hours, minutes, seconds, milliseconds); + return 0; } @@ -371,7 +403,8 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_kernel, #if defined(CONFIG_SYS_HEAP_RUNTIME_STATS) && (CONFIG_HEAP_MEM_POOL_SIZE > 0) SHELL_CMD(heap, NULL, "System heap usage statistics.", cmd_kernel_heap), #endif - SHELL_CMD(uptime, NULL, "Kernel uptime.", cmd_kernel_uptime), + SHELL_CMD_ARG(uptime, NULL, "Kernel uptime. Can be called with the -p or --pretty options", + cmd_kernel_uptime, 1, 1), SHELL_CMD(version, NULL, "Kernel version.", cmd_kernel_version), SHELL_CMD_ARG(sleep, NULL, "ms", cmd_kernel_sleep, 2, 0), #if defined(CONFIG_LOG_RUNTIME_FILTERING) diff --git a/subsys/shell/shell.c b/subsys/shell/shell.c index 34ed7daa755..efff35e2631 100644 --- a/subsys/shell/shell.c +++ b/subsys/shell/shell.c @@ -1307,6 +1307,8 @@ static void kill_handler(const struct shell *sh) sh->ctx->tid = NULL; k_thread_abort(k_current_get()); + + CODE_UNREACHABLE; } void shell_thread(void *shell_handle, void *arg_log_backend, @@ -1390,7 +1392,7 @@ int shell_init(const struct shell *sh, const void *transport_config, SHELL_THREAD_PRIORITY, 0, K_NO_WAIT); sh->ctx->tid = tid; - k_thread_name_set(tid, sh->thread_name); + k_thread_name_set(tid, sh->name); return 0; } @@ -1486,6 +1488,17 @@ void shell_process(const struct shell *sh) z_flag_processing_set(sh, false); } +const struct shell *shell_backend_get_by_name(const char *backend_name) +{ + STRUCT_SECTION_FOREACH(shell, backend) { + if (strcmp(backend_name, backend->name) == 0) { + return backend; + } + } + + return NULL; +} + /* This function mustn't be used from shell context to avoid deadlock. * However it can be used in shell command handlers. */ diff --git a/subsys/shell/shell_cmds.c b/subsys/shell/shell_cmds.c index 101f2fe5a61..0932cd4adfc 100644 --- a/subsys/shell/shell_cmds.c +++ b/subsys/shell/shell_cmds.c @@ -12,6 +12,7 @@ #include "shell_vt100.h" #define SHELL_MSG_CMD_NOT_SUPPORTED "Command not supported.\n" +#define SHELL_HELP_COMMENT "Ignore lines beginning with 'rem '" #define SHELL_HELP_RETVAL "Print return value of most recent command" #define SHELL_HELP_CLEAR "Clear screen." #define SHELL_HELP_BACKENDS "List active shell backends.\n" @@ -202,6 +203,15 @@ static int terminal_size_get(const struct shell *sh) return ret_val; } +static int cmd_comment(const struct shell *sh, size_t argc, char **argv) +{ + ARG_UNUSED(sh); + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + return 0; +} + static int cmd_clear(const struct shell *sh, size_t argc, char **argv) { ARG_UNUSED(argv); @@ -221,7 +231,7 @@ static int cmd_backends(const struct shell *sh, size_t argc, char **argv) shell_print(sh, "Active shell backends:"); STRUCT_SECTION_FOREACH(shell, obj) { - shell_print(sh, " %2d. :%s", cnt++, obj->ctx->prompt); + shell_print(sh, " %2d. :%s (%s)", cnt++, obj->ctx->prompt, sh->name); } return 0; @@ -530,6 +540,8 @@ SHELL_STATIC_SUBCMD_SET_CREATE(m_sub_resize, SHELL_SUBCMD_SET_END ); +SHELL_COND_CMD_REGISTER(CONFIG_SHELL_VT100_COMMANDS, rem, NULL, + SHELL_HELP_COMMENT, cmd_comment); SHELL_COND_CMD_ARG_REGISTER(CONFIG_SHELL_VT100_COMMANDS, clear, NULL, SHELL_HELP_CLEAR, cmd_clear, 1, 0); SHELL_CMD_REGISTER(shell, &m_sub_shell, SHELL_HELP_SHELL, NULL); diff --git a/subsys/shell/shell_log_backend.c b/subsys/shell/shell_log_backend.c index 2a90478ee97..38ee97c3ff9 100644 --- a/subsys/shell/shell_log_backend.c +++ b/subsys/shell/shell_log_backend.c @@ -143,6 +143,9 @@ static bool copy_to_pbuffer(struct mpsc_pbuf_buffer *mpsc_buffer, uint8_t *src_data = (uint8_t *)msg + sizeof(struct mpsc_pbuf_hdr); size_t hdr_wlen = DIV_ROUND_UP(sizeof(struct mpsc_pbuf_hdr), sizeof(uint32_t)); + if (wlen <= hdr_wlen) { + return false; + } dst->hdr.data = msg->buf.hdr.data; memcpy(dst_data, src_data, (wlen - hdr_wlen) * sizeof(uint32_t)); diff --git a/subsys/shell/shell_ops.c b/subsys/shell/shell_ops.c index db68c62155b..7b9af71e417 100644 --- a/subsys/shell/shell_ops.c +++ b/subsys/shell/shell_ops.c @@ -367,7 +367,29 @@ static void print_prompt(const struct shell *sh) void z_shell_print_cmd(const struct shell *sh) { - z_shell_raw_fprintf(sh->fprintf_ctx, "%s", sh->ctx->cmd_buff); + int beg_offset = 0; + int end_offset = 0; + int cmd_width = z_shell_strlen(sh->ctx->cmd_buff); + int adjust = sh->ctx->vt100_ctx.cons.name_len; + char ch; + + while (cmd_width > sh->ctx->vt100_ctx.cons.terminal_wid - adjust) { + end_offset += sh->ctx->vt100_ctx.cons.terminal_wid - adjust; + ch = sh->ctx->cmd_buff[end_offset]; + sh->ctx->cmd_buff[end_offset] = '\0'; + + z_shell_raw_fprintf(sh->fprintf_ctx, "%s\n", + &sh->ctx->cmd_buff[beg_offset]); + + sh->ctx->cmd_buff[end_offset] = ch; + cmd_width -= (sh->ctx->vt100_ctx.cons.terminal_wid - adjust); + beg_offset = end_offset; + adjust = 0; + } + if (cmd_width > 0) { + z_shell_raw_fprintf(sh->fprintf_ctx, "%s", + &sh->ctx->cmd_buff[beg_offset]); + } } void z_shell_print_prompt_and_cmd(const struct shell *sh) diff --git a/subsys/sip_svc/Kconfig b/subsys/sip_svc/Kconfig index 1d1702f4905..c7cf1b36bc5 100644 --- a/subsys/sip_svc/Kconfig +++ b/subsys/sip_svc/Kconfig @@ -22,7 +22,7 @@ config ARM_SIP_SVC_SUBSYS_INIT_PRIORITY config ARM_SIP_SVC_SUBSYS_THREAD_STACK_SIZE int "ARM SiP service thread stack size" - default 1856 + default 4096 help Stack size of the ARM SiP service. The thread calls the callbacks of the requestor @@ -55,8 +55,8 @@ config ARM_SIP_SVC_SUBSYS_MAX_TRANSACTION_ID_COUNT Maximum number of transaction_id per client. config ARM_SIP_SVC_SUBSYS_ASYNC_POLLING_DELAY - int "Delay used for polling asynchronous jobs in milliseconds" - default 10 + int "Delay used for polling asynchronous jobs in micro-seconds" + default 100 help Delay for sip_svc thread to sleep during each polling call for ASYNC response. diff --git a/subsys/sip_svc/sip_svc_agilex_mailbox_shell.c b/subsys/sip_svc/sip_svc_agilex_mailbox_shell.c index ea6e237e777..7657b3b8d09 100644 --- a/subsys/sip_svc/sip_svc_agilex_mailbox_shell.c +++ b/subsys/sip_svc/sip_svc_agilex_mailbox_shell.c @@ -15,7 +15,7 @@ #include #include -#define MAX_TIMEOUT_SECS (10 * 60UL) +#define MAX_TIMEOUT_MSECS (1 * 1000UL) struct private_data { struct k_sem semaphore; @@ -76,10 +76,10 @@ static int cmd_unreg(const struct shell *sh, size_t argc, char **argv) static int cmd_open(const struct shell *sh, size_t argc, char **argv) { - unsigned long seconds = 0; + unsigned long mseconds = 0; int err; char *endptr; - k_timeout_t timeout = K_FOREVER; + k_timeout_t timeout = K_MSEC(MAX_TIMEOUT_MSECS); if (!mb_smc_ctrl) { shell_print(sh, "Mailbox client is not registered"); @@ -88,18 +88,18 @@ static int cmd_open(const struct shell *sh, size_t argc, char **argv) if (argc > 1) { errno = 0; - seconds = strtoul(argv[1], &endptr, 10); + mseconds = strtoul(argv[1], &endptr, 10); if (errno == ERANGE) { shell_error(sh, "out of range value"); return -ERANGE; } else if (errno || endptr == argv[1] || *endptr) { return -errno; - } else if (seconds <= MAX_TIMEOUT_SECS) { - timeout = K_SECONDS(seconds); + } else if (mseconds <= MAX_TIMEOUT_MSECS) { + timeout = K_MSEC(mseconds); } else { - timeout = K_SECONDS(MAX_TIMEOUT_SECS); - shell_error(sh, "Setting timeout value to %lu seconds", - MAX_TIMEOUT_SECS); + timeout = K_MSEC(MAX_TIMEOUT_MSECS); + shell_error(sh, "Setting timeout value to %lu milliseconds", + MAX_TIMEOUT_MSECS); } } @@ -281,11 +281,11 @@ static int cmd_send(const struct shell *sh, size_t argc, char **argv) } else if (errno || endptr == argv[2] || *endptr) { shell_error(sh, "Invalid argument"); return -EINVAL; - } else if (msecond <= (MSEC_PER_SEC * MAX_TIMEOUT_SECS)) { + } else if (msecond <= (MSEC_PER_SEC * MAX_TIMEOUT_MSECS)) { timeout = K_MSEC(msecond); } else { - timeout = K_SECONDS(MAX_TIMEOUT_SECS); - shell_error(sh, "Setting timeout value to %lu seconds", MAX_TIMEOUT_SECS); + timeout = K_SECONDS(MAX_TIMEOUT_MSECS); + shell_error(sh, "Setting timeout value to %lu seconds", MAX_TIMEOUT_MSECS); } } @@ -337,7 +337,7 @@ static int cmd_send(const struct shell *sh, size_t argc, char **argv) SHELL_STATIC_SUBCMD_SET_CREATE( sub_mailbox, SHELL_CMD_ARG(reg, NULL, "", cmd_reg, 2, 0), SHELL_CMD_ARG(unreg, NULL, NULL, cmd_unreg, 1, 0), - SHELL_CMD_ARG(open, NULL, "[]", cmd_open, 1, 1), + SHELL_CMD_ARG(open, NULL, "[]", cmd_open, 1, 1), SHELL_CMD_ARG(close, NULL, NULL, cmd_close, 1, 0), SHELL_CMD_ARG(send, NULL, " []", diff --git a/subsys/sip_svc/sip_svc_shell.c b/subsys/sip_svc/sip_svc_shell.c index a291ad54558..c0d64495206 100644 --- a/subsys/sip_svc/sip_svc_shell.c +++ b/subsys/sip_svc/sip_svc_shell.c @@ -12,7 +12,7 @@ #include #include -#define MAX_TIMEOUT_SECS (10 * 60UL) +#define MAX_TIMEOUT_MSECS (1 * 1000UL) struct private_data { struct k_sem semaphore; @@ -98,10 +98,10 @@ static int cmd_open(const struct shell *sh, size_t argc, char **argv) { struct sip_svc_controller *ctrl; uint32_t c_token; - unsigned long seconds = 0; + unsigned long mseconds = 0; int err; char *endptr; - k_timeout_t timeout = K_FOREVER; + k_timeout_t timeout = K_MSEC(MAX_TIMEOUT_MSECS); err = parse_common_args(sh, argv, (void **)&ctrl); if (err < 0) { @@ -120,18 +120,19 @@ static int cmd_open(const struct shell *sh, size_t argc, char **argv) if (argc > 3) { errno = 0; - seconds = strtoul(argv[3], &endptr, 10); + mseconds = strtoul(argv[3], &endptr, 10); if (errno == ERANGE) { shell_error(sh, "Out of range value"); return -ERANGE; } else if (errno || endptr == argv[3] || *endptr) { shell_error(sh, "Invalid Argument"); return -EINVAL; - } else if (seconds <= MAX_TIMEOUT_SECS) { - timeout = K_SECONDS(seconds); + } else if (mseconds <= MAX_TIMEOUT_MSECS) { + timeout = K_MSEC(mseconds); } else { - timeout = K_SECONDS(MAX_TIMEOUT_SECS); - shell_error(sh, "Setting timeout value to %lu", MAX_TIMEOUT_SECS); + timeout = K_MSEC(MAX_TIMEOUT_MSECS); + shell_error(sh, "Setting timeout value to %lu milliseconds", + MAX_TIMEOUT_MSECS); } } @@ -376,7 +377,7 @@ static int cmd_info(const struct shell *sh, size_t argc, char **argv) SHELL_STATIC_SUBCMD_SET_CREATE( sub_sip_svc, SHELL_CMD_ARG(reg, NULL, "", cmd_reg, 2, 0), SHELL_CMD_ARG(unreg, NULL, " ", cmd_unreg, 3, 0), - SHELL_CMD_ARG(open, NULL, " <[timeout_sec]>", cmd_open, 3, 1), + SHELL_CMD_ARG(open, NULL, " <[timeout_msec]>", cmd_open, 3, 1), SHELL_CMD_ARG(close, NULL, " ", cmd_close, 3, 0), SHELL_CMD_ARG(send, NULL, " [ ... ]", cmd_send, 4, 7), SHELL_CMD_ARG(info, NULL, "", cmd_info, 2, 0), SHELL_SUBCMD_SET_END); diff --git a/subsys/sip_svc/sip_svc_subsys.c b/subsys/sip_svc/sip_svc_subsys.c index 7bf5d52e133..d4984abdf57 100644 --- a/subsys/sip_svc/sip_svc_subsys.c +++ b/subsys/sip_svc/sip_svc_subsys.c @@ -129,8 +129,7 @@ static inline bool is_sip_svc_controller(void *ct) return false; } - STRUCT_SECTION_FOREACH(sip_svc_controller, ctrl) - { + STRUCT_SECTION_FOREACH(sip_svc_controller, ctrl) { if ((void *)ctrl == ct) { return true; } @@ -284,7 +283,7 @@ int sip_svc_open(void *ct, uint32_t c_token, k_timeout_t k_timeout) * transactions are complete. */ for (bool first_iteration = false; get_timer_status(&first_iteration, &timer, k_timeout); - k_msleep(CONFIG_ARM_SIP_SVC_SUBSYS_ASYNC_POLLING_DELAY)) { + k_usleep(CONFIG_ARM_SIP_SVC_SUBSYS_ASYNC_POLLING_DELAY)) { ret = k_mutex_lock(&ctrl->data_mutex, K_NO_WAIT); if (ret != 0) { @@ -320,10 +319,8 @@ int sip_svc_open(void *ct, uint32_t c_token, k_timeout_t k_timeout) * Acquire open lock, when only one client can transact at * a time. */ - ret = k_mutex_lock(&ctrl->open_mutex, K_NO_WAIT); - if (ret != 0) { - LOG_DBG("0x%x didn't get open lock, wait for it to be released, %d", - c_token, ret); + if (!atomic_cas(&ctrl->open_lock, SIP_SVC_OPEN_UNLOCKED, SIP_SVC_OPEN_LOCKED)) { + LOG_DBG("0x%x didn't get open lock, wait for it to be released", c_token); k_mutex_unlock(&ctrl->data_mutex); continue; } @@ -331,12 +328,13 @@ int sip_svc_open(void *ct, uint32_t c_token, k_timeout_t k_timeout) /* Make the client state to be open and stop timer*/ ctrl->clients[c_idx].state = SIP_SVC_CLIENT_ST_OPEN; - LOG_INF("%x successfully opened a connection with sip_svc", c_token); + LOG_INF("0x%x successfully opened a connection with sip_svc", c_token); k_mutex_unlock(&ctrl->data_mutex); k_timer_stop(&timer); return 0; } + k_timer_stop(&timer); LOG_ERR("Timedout at %s for 0x%x", __func__, c_token); return -ETIMEDOUT; } @@ -386,7 +384,7 @@ int sip_svc_close(void *ct, uint32_t c_token, struct sip_svc_request *pre_close_ } #if CONFIG_ARM_SIP_SVC_SUBSYS_SINGLY_OPEN - k_mutex_unlock(&ctrl->open_mutex); + (void)atomic_set(&ctrl->open_lock, SIP_SVC_OPEN_UNLOCKED); #endif k_mutex_unlock(&ctrl->data_mutex); @@ -661,7 +659,7 @@ static void sip_svc_thread(void *ctrl_ptr, void *arg2, void *arg3) /* sleep only when waiting for ASYNC responses*/ if (ret_msgq == 0 && ret_resp != 0) { - k_msleep(CONFIG_ARM_SIP_SVC_SUBSYS_ASYNC_POLLING_DELAY); + k_usleep(CONFIG_ARM_SIP_SVC_SUBSYS_ASYNC_POLLING_DELAY); } } LOG_INF("Suspend thread, all transactions are completed"); @@ -802,8 +800,7 @@ void *sip_svc_get_controller(char *method) /** * For more info on below code check @ref SIP_SVC_CONTROLLER_DEFINE() */ - STRUCT_SECTION_FOREACH(sip_svc_controller, ctrl) - { + STRUCT_SECTION_FOREACH(sip_svc_controller, ctrl) { if (!strncmp(ctrl->method, method, SIP_SVC_SUBSYS_CONDUIT_NAME_LENGTH)) { return (void *)ctrl; } @@ -831,20 +828,13 @@ static int sip_svc_subsys_init(void) * SIP_SVC_CONTROLLER_DEFINE(),see @ref SIP_SVC_CONTROLLER_DEFINE() for more * info. */ - STRUCT_SECTION_FOREACH(sip_svc_controller, ctrl) - { + STRUCT_SECTION_FOREACH(sip_svc_controller, ctrl) { if (!device_is_ready(ctrl->dev)) { LOG_ERR("device not ready"); return -ENODEV; } dev = (struct device *)(ctrl->dev); - if (ctrl->num_clients > CONFIG_ARM_SIP_SVC_SUBSYS_MAX_CLIENT_COUNT) { - LOG_ERR("number of clients cannot be greater than the " - "CONFIG_ARM_SIP_SVC_SUBSYS_MAX_CLIENT_COUNT"); - return -EPROTO; - } - LOG_INF("Got registered conduit %.*s", (int)sizeof(ctrl->method), ctrl->method); ctrl->async_resp_data = k_malloc(ctrl->resp_size); @@ -884,6 +874,8 @@ static int sip_svc_subsys_init(void) return -ENOMEM; } + memset(ctrl->clients, 0, ctrl->num_clients * sizeof(struct sip_svc_client)); + /* Initialize request msgq */ k_msgq_init(&ctrl->req_msgq, msgq_buf, sizeof(struct sip_svc_request), CONFIG_ARM_SIP_SVC_SUBSYS_MSGQ_DEPTH); @@ -930,10 +922,11 @@ static int sip_svc_subsys_init(void) ctrl->active_job_cnt = 0; ctrl->active_async_job_cnt = 0; - /* Initialize mutex */ + /* Initialize atomic variable */ #if CONFIG_ARM_SIP_SVC_SUBSYS_SINGLY_OPEN - k_mutex_init(&ctrl->open_mutex); + (void)atomic_set(&ctrl->open_lock, SIP_SVC_OPEN_UNLOCKED); #endif + /* Initialize mutex */ k_mutex_init(&ctrl->data_mutex); ctrl->init = true; diff --git a/subsys/stats/Kconfig b/subsys/stats/Kconfig index 1c6d138e1df..417d5db0213 100644 --- a/subsys/stats/Kconfig +++ b/subsys/stats/Kconfig @@ -20,7 +20,6 @@ config STATS_NAMES config STATS_SHELL bool "Statistics Shell Command" - default y depends on STATS && SHELL imply STATS_NAMES help diff --git a/subsys/task_wdt/task_wdt.c b/subsys/task_wdt/task_wdt.c index 035a26017be..b7171a14e23 100644 --- a/subsys/task_wdt/task_wdt.c +++ b/subsys/task_wdt/task_wdt.c @@ -39,6 +39,7 @@ struct task_wdt_channel { /* array of all task watchdog channels */ static struct task_wdt_channel channels[CONFIG_TASK_WDT_CHANNELS]; +static struct k_spinlock channels_lock; /* timer used for watchdog handling */ static struct k_timer timer; @@ -153,10 +154,18 @@ int task_wdt_init(const struct device *hw_wdt) int task_wdt_add(uint32_t reload_period, task_wdt_callback_t callback, void *user_data) { + k_spinlock_key_t key; + if (reload_period == 0) { return -EINVAL; } + /* + * k_spin_lock instead of k_sched_lock required here to avoid being interrupted by a + * triggering other task watchdog channel (executed in ISR context). + */ + key = k_spin_lock(&channels_lock); + /* look for unused channel (reload_period set to 0) */ for (int id = 0; id < ARRAY_SIZE(channels); id++) { if (channels[id].reload_period == 0) { @@ -176,21 +185,31 @@ int task_wdt_add(uint32_t reload_period, task_wdt_callback_t callback, /* must be called after hw wdt has been started */ task_wdt_feed(id); + k_spin_unlock(&channels_lock, key); + return id; } } + k_spin_unlock(&channels_lock, key); + return -ENOMEM; } int task_wdt_delete(int channel_id) { + k_spinlock_key_t key; + if (channel_id < 0 || channel_id >= ARRAY_SIZE(channels)) { return -EINVAL; } + key = k_spin_lock(&channels_lock); + channels[channel_id].reload_period = 0; + k_spin_unlock(&channels_lock, key); + return 0; } diff --git a/subsys/testsuite/Kconfig b/subsys/testsuite/Kconfig index e2e7fba764e..eff533a9da2 100644 --- a/subsys/testsuite/Kconfig +++ b/subsys/testsuite/Kconfig @@ -78,7 +78,8 @@ config COVERAGE_GCOV_HEAP_SIZE default 16384 help This option configures the heap size allocated for gcov coverage - data to be dumped over serial. + data to be dumped over serial. If the value is 0, no buffer will be used, + data will be dumped directly over serial. config COVERAGE_DUMP bool "Dump coverage data on exit" @@ -86,6 +87,15 @@ config COVERAGE_DUMP help Dump collected coverage information to console on exit. +config FORCE_COVERAGE + bool "Force coverage" + select HAS_COVERAGE_SUPPORT + help + Regardless of platform support, it will enable coverage data production. + If the platform does not support coverage by default, setting this config + does not guarantee that coverage data will be gathered. + Application may not fit memory or crash at runtime. + config TEST_USERSPACE bool "Indicate that this test exercises user mode" help diff --git a/subsys/testsuite/boards/unit_testing/unit_testing/Kconfig.defconfig b/subsys/testsuite/boards/unit_testing/unit_testing/Kconfig.defconfig index b2efdb2bee7..939f1c97e71 100644 --- a/subsys/testsuite/boards/unit_testing/unit_testing/Kconfig.defconfig +++ b/subsys/testsuite/boards/unit_testing/unit_testing/Kconfig.defconfig @@ -2,4 +2,7 @@ # # Copyright (c) 2022 Nordic Semiconductor -# Intentionally left empty +# Bluetooth unit tests expect this backend +choice BT_HCI_BUS_TYPE + default BT_NO_DRIVER +endchoice diff --git a/subsys/testsuite/busy_sim/busy_sim.c b/subsys/testsuite/busy_sim/busy_sim.c index a7e59b97472..d401aeafdd8 100644 --- a/subsys/testsuite/busy_sim/busy_sim.c +++ b/subsys/testsuite/busy_sim/busy_sim.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #define BUFFER_SIZE 32 @@ -204,5 +204,5 @@ static int busy_sim_init(const struct device *dev) DEVICE_DT_DEFINE(DT_BUSY_SIM, busy_sim_init, NULL, &sim_data, &sim_config, - APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY, + POST_KERNEL, CONFIG_APPLICATION_INIT_PRIORITY, NULL); diff --git a/subsys/testsuite/coverage/coverage.c b/subsys/testsuite/coverage/coverage.c index e787135ffdc..dc120c14605 100644 --- a/subsys/testsuite/coverage/coverage.c +++ b/subsys/testsuite/coverage/coverage.c @@ -36,25 +36,54 @@ void __gcov_exit(void) } /** - * buff_write_u64 - Store 64 bit data on a buffer and return the size + * print_u8 - Print 8 bit of gcov data + */ +static inline void print_u8(uint8_t v) +{ + printk("%02x", v); +} + +/** + * print_u32 - Print 32 bit of gcov data + */ +static inline void print_u32(uint32_t v) +{ + uint8_t *ptr = (uint8_t *)&v; + + print_u8(*ptr); + print_u8(*(ptr+1)); + print_u8(*(ptr+2)); + print_u8(*(ptr+3)); +} + +/** + * write_u64 - Store 64 bit data on a buffer and return the size */ -static inline void buff_write_u64(void *buffer, size_t *off, uint64_t v) +static inline void write_u64(void *buffer, size_t *off, uint64_t v) { - memcpy((uint8_t *)buffer + *off, (uint8_t *)&v, sizeof(v)); + if (buffer != NULL) { + memcpy((uint8_t *)buffer + *off, (uint8_t *)&v, sizeof(v)); + } else { + print_u32(*((uint32_t *)&v)); + print_u32(*(((uint32_t *)&v) + 1)); + } *off = *off + sizeof(uint64_t); } /** - * buff_write_u32 - Store 32 bit data on a buffer and return the size + * write_u32 - Store 32 bit data on a buffer and return the size */ -static inline void buff_write_u32(void *buffer, size_t *off, uint32_t v) +static inline void write_u32(void *buffer, size_t *off, uint32_t v) { - memcpy((uint8_t *)buffer + *off, (uint8_t *)&v, sizeof(v)); + if (buffer != NULL) { + memcpy((uint8_t *)buffer + *off, (uint8_t *)&v, sizeof(v)); + } else { + print_u32(v); + } *off = *off + sizeof(uint32_t); } - size_t calculate_buff_size(struct gcov_info *info) { uint32_t iter; @@ -102,14 +131,13 @@ size_t calculate_buff_size(struct gcov_info *info) return size; } - /** - * populate_buffer - convert from gcov data set (info) to + * gcov_to_gcda - convert from gcov data set (info) to * .gcda file format. * This buffer will now have info similar to a regular gcda * format. */ -size_t populate_buffer(uint8_t *buffer, struct gcov_info *info) +size_t gcov_to_gcda(uint8_t *buffer, struct gcov_info *info) { struct gcov_fn_info *functions; struct gcov_ctr_info *counters_per_func; @@ -119,22 +147,22 @@ size_t populate_buffer(uint8_t *buffer, struct gcov_info *info) size_t buffer_write_position = 0; /* File header. */ - buff_write_u32(buffer, - &buffer_write_position, - GCOV_DATA_MAGIC); + write_u32(buffer, + &buffer_write_position, + GCOV_DATA_MAGIC); - buff_write_u32(buffer, - &buffer_write_position, - info->version); + write_u32(buffer, + &buffer_write_position, + info->version); - buff_write_u32(buffer, - &buffer_write_position, - info->stamp); + write_u32(buffer, + &buffer_write_position, + info->stamp); #ifdef GCOV_12_FORMAT - buff_write_u32(buffer, - &buffer_write_position, - info->checksum); + write_u32(buffer, + &buffer_write_position, + info->checksum); #endif for (iter_functions = 0U; @@ -144,25 +172,25 @@ size_t populate_buffer(uint8_t *buffer, struct gcov_info *info) functions = info->functions[iter_functions]; - buff_write_u32(buffer, - &buffer_write_position, - GCOV_TAG_FUNCTION); + write_u32(buffer, + &buffer_write_position, + GCOV_TAG_FUNCTION); - buff_write_u32(buffer, - &buffer_write_position, - GCOV_TAG_FUNCTION_LENGTH); + write_u32(buffer, + &buffer_write_position, + GCOV_TAG_FUNCTION_LENGTH); - buff_write_u32(buffer, - &buffer_write_position, - functions->ident); + write_u32(buffer, + &buffer_write_position, + functions->ident); - buff_write_u32(buffer, - &buffer_write_position, - functions->lineno_checksum); + write_u32(buffer, + &buffer_write_position, + functions->lineno_checksum); - buff_write_u32(buffer, - &buffer_write_position, - functions->cfg_checksum); + write_u32(buffer, + &buffer_write_position, + functions->cfg_checksum); counters_per_func = functions->ctrs; @@ -174,29 +202,28 @@ size_t populate_buffer(uint8_t *buffer, struct gcov_info *info) continue; } - buff_write_u32(buffer, - &buffer_write_position, - GCOV_TAG_FOR_COUNTER(iter_counts)); + write_u32(buffer, + &buffer_write_position, + GCOV_TAG_FOR_COUNTER(iter_counts)); #ifdef GCOV_12_FORMAT /* GCOV 12 counts the length by bytes */ - buff_write_u32(buffer, - &buffer_write_position, - counters_per_func->num * 2U * 4); + write_u32(buffer, + &buffer_write_position, + counters_per_func->num * 2U * 4); #else - buff_write_u32(buffer, - &buffer_write_position, - counters_per_func->num * 2U); + write_u32(buffer, + &buffer_write_position, + counters_per_func->num * 2U); #endif for (iter_counter_values = 0U; iter_counter_values < counters_per_func->num; iter_counter_values++) { - buff_write_u64(buffer, - &buffer_write_position, - counters_per_func->\ - values[iter_counter_values]); + write_u64(buffer, + &buffer_write_position, + counters_per_func->values[iter_counter_values]); } counters_per_func++; @@ -205,20 +232,21 @@ size_t populate_buffer(uint8_t *buffer, struct gcov_info *info) return buffer_write_position; } -void dump_on_console(const char *filename, char *ptr, size_t len) +void dump_on_console_start(const char *filename) { - uint32_t iter; - printk("\n%c", FILE_START_INDICATOR); while (*filename != '\0') { printk("%c", *filename++); } printk("%c", GCOV_DUMP_SEPARATOR); +} - /* Data dump */ - - for (iter = 0U; iter < len; iter++) { - printk(" %02x", (uint8_t)*ptr++); +void dump_on_console_data(char *ptr, size_t len) +{ + if (ptr != NULL) { + for (size_t iter = 0U; iter < len; iter++) { + print_u8((uint8_t)*ptr++); + } } } @@ -237,21 +265,22 @@ void gcov_coverage_dump(void) printk("\nGCOV_COVERAGE_DUMP_START"); while (gcov_list) { + dump_on_console_start(gcov_list->filename); size = calculate_buff_size(gcov_list); buffer = k_heap_alloc(&gcov_heap, size, K_NO_WAIT); - if (!buffer) { + if (CONFIG_COVERAGE_GCOV_HEAP_SIZE > 0 && !buffer) { printk("No Mem available to continue dump\n"); goto coverage_dump_end; } - written_size = populate_buffer(buffer, gcov_list); + written_size = gcov_to_gcda(buffer, gcov_list); if (written_size != size) { printk("Write Error on buff\n"); goto coverage_dump_end; } - dump_on_console(gcov_list->filename, buffer, size); + dump_on_console_data(buffer, size); k_heap_free(&gcov_heap, buffer); gcov_list = gcov_list->next; diff --git a/subsys/testsuite/coverage/coverage_ram.ld b/subsys/testsuite/coverage/coverage_ram.ld index 108829fed05..df348cb8aba 100644 --- a/subsys/testsuite/coverage/coverage_ram.ld +++ b/subsys/testsuite/coverage/coverage_ram.ld @@ -26,9 +26,6 @@ SECTION_DATA_PROLOGUE(_GCOV_BSS_SECTION_NAME,(NOLOAD),) __gcov_bss_end = .; } GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) - -__gcov_bss_num_words = ((__gcov_bss_end - __gcov_bss_start) >> 2); -__gcov_bss_size = __gcov_bss_end - __gcov_bss_start; #endif #ifdef CONFIG_X86_64 @@ -42,9 +39,6 @@ SECTION_PROLOGUE(_GCOV_BSS_SECTION_NAME, (NOLOAD), ALIGN(16)) __gcov_bss_end = .; }GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION) -__gcov_bss_num_words = ((__gcov_bss_end - __gcov_bss_start) >> 2); -__gcov_bss_size = __gcov_bss_end - __gcov_bss_start; - #elif CONFIG_X86 SECTION_PROLOGUE(_GCOV_BSS_SECTION_NAME, (NOLOAD),) { @@ -55,9 +49,6 @@ SECTION_PROLOGUE(_GCOV_BSS_SECTION_NAME, (NOLOAD),) MMU_PAGE_ALIGN __gcov_bss_end = .; } GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) - -__gcov_bss_num_words = ((__gcov_bss_end - __gcov_bss_start) >> 2); -__gcov_bss_size = __gcov_bss_end - __gcov_bss_start; #endif #ifdef CONFIG_ARC @@ -73,7 +64,19 @@ SECTION_PROLOGUE(_GCOV_BSS_SECTION_NAME, (NOLOAD),) #endif __gcov_bss_end = .; } GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) +#endif + +#ifdef CONFIG_RISCV +SECTION_PROLOGUE(_GCOV_BSS_SECTION_NAME, (NOLOAD),) +{ + MPU_MIN_SIZE_ALIGN + __gcov_bss_start = .; + *(".bss.__gcov0.*"); + . = ALIGN(4); + MPU_MIN_SIZE_ALIGN + __gcov_bss_end = .; +} GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) +#endif __gcov_bss_num_words = ((__gcov_bss_end - __gcov_bss_start) >> 2); __gcov_bss_size = __gcov_bss_end - __gcov_bss_start; -#endif diff --git a/subsys/testsuite/coverage/coverage_rodata.ld b/subsys/testsuite/coverage/coverage_rodata.ld index 08654fba65a..03c1cd089e2 100644 --- a/subsys/testsuite/coverage/coverage_rodata.ld +++ b/subsys/testsuite/coverage/coverage_rodata.ld @@ -3,7 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +#ifdef CONFIG_64BIT +. = ALIGN(8); +#else . = ALIGN(4); +#endif PROVIDE_HIDDEN (__init_array_start = .); KEEP (*(SORT(.init_array.*))) diff --git a/subsys/testsuite/include/zephyr/tc_util.h b/subsys/testsuite/include/zephyr/tc_util.h index 69c9359b50f..ea7ed98c8c7 100644 --- a/subsys/testsuite/include/zephyr/tc_util.h +++ b/subsys/testsuite/include/zephyr/tc_util.h @@ -127,18 +127,11 @@ static inline void print_nothing(const char *fmt, ...) } #ifndef TC_PRINT -/* Need to check for CONFIG_ZTEST_NEW_API since the TC_PRINT - * is also used by the old ztest. - */ -#ifdef CONFIG_ZTEST_NEW_API #if defined(CONFIG_ZTEST_VERBOSE_OUTPUT) #define TC_PRINT(fmt, ...) PRINT_DATA(fmt, ##__VA_ARGS__) #else #define TC_PRINT(fmt, ...) print_nothing(fmt, ##__VA_ARGS__) #endif /* CONFIG_ZTEST_VERBOSE_OUTPUT */ -#else -#define TC_PRINT(fmt, ...) PRINT_DATA(fmt, ##__VA_ARGS__) -#endif /* CONFIG_ZTEST_NEW_API */ #endif /* TC_PRINT */ #ifndef TC_SUMMARY_PRINT @@ -146,15 +139,11 @@ static inline void print_nothing(const char *fmt, ...) #endif #ifndef TC_START_PRINT -#ifdef CONFIG_ZTEST_NEW_API #if defined(CONFIG_ZTEST_VERBOSE_OUTPUT) #define TC_START_PRINT(name) PRINT_DATA("START - %s\n", name); #else #define TC_START_PRINT(name) print_nothing(name) #endif /* CONFIG_ZTEST_VERBOSE_OUTPUT */ -#else -#define TC_START_PRINT(name) PRINT_DATA("START - %s\n", name); -#endif /* CONFIG_ZTEST_NEW_API */ #endif /* TC_START_PRINT */ #ifndef TC_START @@ -169,15 +158,11 @@ static inline void print_nothing(const char *fmt, ...) #endif #ifndef TC_END_PRINT -#ifdef CONFIG_ZTEST_NEW_API #if defined(CONFIG_ZTEST_VERBOSE_OUTPUT) #define TC_END_PRINT(result, fmt, ...) PRINT_DATA(fmt, ##__VA_ARGS__); PRINT_LINE #else #define TC_END_PRINT(result, fmt, ...) print_nothing(fmt) #endif /* CONFIG_ZTEST_VERBOSE_OUTPUT */ -#else -#define TC_END_PRINT(result, fmt, ...) PRINT_DATA(fmt, ##__VA_ARGS__); PRINT_LINE -#endif /* CONFIG_ZTEST_NEW_API */ #endif /* TC_END_PRINT */ /* prints result and the function name */ diff --git a/subsys/testsuite/ztest/CMakeLists.txt b/subsys/testsuite/ztest/CMakeLists.txt index c9c93328985..7817bc2f30b 100644 --- a/subsys/testsuite/ztest/CMakeLists.txt +++ b/subsys/testsuite/ztest/CMakeLists.txt @@ -3,7 +3,6 @@ zephyr_syscall_header( ${ZEPHYR_BASE}/subsys/testsuite/ztest/include/zephyr/ztest_error_hook.h ${ZEPHYR_BASE}/subsys/testsuite/ztest/include/zephyr/ztest_test.h - ${ZEPHYR_BASE}/subsys/testsuite/ztest/include/zephyr/ztest_test_new.h ) zephyr_include_directories( @@ -16,16 +15,17 @@ if(DEFINED TC_RUNID) endif() zephyr_library() -zephyr_library_sources_ifndef(CONFIG_ZTEST_NEW_API src/ztest.c) -zephyr_library_sources_ifdef(CONFIG_ZTEST_NEW_API src/ztest_new.c) -zephyr_library_sources( src/ztest_error_hook.c) -zephyr_library_sources_ifdef(CONFIG_ZTEST_NEW_API src/ztest_rules.c) +zephyr_library_sources( + src/ztest.c + src/ztest_error_hook.c + src/ztest_rules.c + ) zephyr_library_sources_ifdef(CONFIG_ZTEST_MOCKING src/ztest_mock.c) zephyr_library_sources_ifdef(CONFIG_ZTRESS src/ztress.c) if(CONFIG_ARCH_POSIX) - zephyr_library_sources_ifdef(CONFIG_ZTEST_NEW_API src/ztest_posix.c) + zephyr_library_sources(src/ztest_posix.c) else() - zephyr_library_sources_ifdef(CONFIG_ZTEST_NEW_API src/ztest_defaults.c) + zephyr_library_sources(src/ztest_defaults.c) endif() diff --git a/subsys/testsuite/ztest/Kconfig b/subsys/testsuite/ztest/Kconfig index d48961cc844..977f882d838 100644 --- a/subsys/testsuite/ztest/Kconfig +++ b/subsys/testsuite/ztest/Kconfig @@ -10,12 +10,6 @@ config ZTEST if ZTEST -config ZTEST_NEW_API - bool "Use the new Ztest API" - help - Enables the new Ztest APIs for creating suites and unit tests in - separate compilation units as well as the new 'rules' API. - config ZTEST_STACK_SIZE int "Test function thread stack size" default 2048 if COVERAGE_GCOV @@ -113,9 +107,7 @@ config ZTEST_WARN_NO_OPTIMIZATIONS optimizations. Please don't file issues when running tests that are not explicitly tuned to work in this configuration. -if ZTEST_NEW_API - -menu "ztest provided rules" +menu "ZTest provided rules" config ZTEST_RULE_1CPU bool "Run all the tests on a single CPU" @@ -184,8 +176,6 @@ config ZTEST_FAIL_ON_ASSUME result will be shown as a failure in order to increase visibility. This precludes tests that skipped with the ZTEST_EXPECT_SKIP annotation. -endif # ZTEST_NEW_API - config TEST_LOGGING_FLUSH_AFTER_TEST bool "When enabled logs are flushed after each test case" default y diff --git a/subsys/testsuite/ztest/include/zephyr/ztest_assert.h b/subsys/testsuite/ztest/include/zephyr/ztest_assert.h index 5b88357bd40..b84b72c8d66 100644 --- a/subsys/testsuite/ztest/include/zephyr/ztest_assert.h +++ b/subsys/testsuite/ztest/include/zephyr/ztest_assert.h @@ -282,6 +282,13 @@ static inline bool z_zexpect(bool cond, const char *default_msg, const char *fil */ #define zassert_ok(cond, ...) zassert(!(cond), #cond " is non-zero", ##__VA_ARGS__) +/** + * @brief Assert that @a cond is not 0 (failure) + * @param cond Condition to check + * @param ... Optional message and variables to print if the assertion fails + */ +#define zassert_not_ok(cond, ...) zassert(!!(cond), #cond " is zero", ##__VA_ARGS__) + /** * @brief Assert that @a ptr is NULL * @param ptr Pointer to compare @@ -425,6 +432,16 @@ static inline bool z_zexpect(bool cond, const char *default_msg, const char *fil */ #define zassume_ok(cond, ...) zassume(!(cond), #cond " is non-zero", ##__VA_ARGS__) +/** + * @brief Assume that @a cond is not 0 (failure) + * + * If the assumption fails, the test will be marked as "skipped". + * + * @param cond Condition to check + * @param ... Optional message and variables to print if the assumption fails + */ +#define zassume_not_ok(cond, ...) zassume(!!(cond), #cond " is zero", ##__VA_ARGS__) + /** * @brief Assume that @a ptr is NULL * @@ -578,6 +595,15 @@ static inline bool z_zexpect(bool cond, const char *default_msg, const char *fil */ #define zexpect_ok(cond, ...) zexpect(!(cond), #cond " is non-zero", ##__VA_ARGS__) +/** + * @brief Expect that @a cond is not 0 (failure), otherwise mark test as failed but continue its + * execution. + * + * @param cond Condition to check + * @param ... Optional message and variables to print if the expectation fails + */ +#define zexpect_not_ok(cond, ...) zexpect(!!(cond), #cond " is zero", ##__VA_ARGS__) + /** * @brief Expect that @a ptr is NULL, otherwise mark test as failed but continue its execution. * diff --git a/subsys/testsuite/ztest/include/zephyr/ztest_test.h b/subsys/testsuite/ztest/include/zephyr/ztest_test.h index b9635560c02..aac7a7b2ad8 100644 --- a/subsys/testsuite/ztest/include/zephyr/ztest_test.h +++ b/subsys/testsuite/ztest/include/zephyr/ztest_test.h @@ -1,23 +1,555 @@ /* * Copyright (c) 2016 Intel Corporation - * Copyright (c) 2021 Google LLC * * SPDX-License-Identifier: Apache-2.0 */ -#ifndef ZEPHYR_TESTSUITE_INCLUDE_ZTEST_TEST_H_ -#define ZEPHYR_TESTSUITE_INCLUDE_ZTEST_TEST_H_ +/** + * @file + * + * @brief Zephyr testing framework _test. + */ + +#ifndef ZEPHYR_TESTSUITE_ZTEST_TEST_H_ +#define ZEPHYR_TESTSUITE_ZTEST_TEST_H_ -#ifdef CONFIG_ZTEST_NEW_API -#include +#include +#include +#include +#include + +#if defined(CONFIG_USERSPACE) +#define __USERSPACE_FLAGS (K_USER) #else -#include -#endif /* !CONFIG_ZTEST_NEW_API */ +#define __USERSPACE_FLAGS (0) +#endif #ifdef __cplusplus extern "C" { #endif +/** + * @brief The expected result of a test. + * + * @see ZTEST_EXPECT_FAIL + * @see ZTEST_EXPECT_SKIP + */ +enum ztest_expected_result { + ZTEST_EXPECTED_RESULT_FAIL = 0, /**< Expect a test to fail */ + ZTEST_EXPECTED_RESULT_SKIP, /**< Expect a test to pass */ +}; + +/** + * @brief A single expectation entry allowing tests to fail/skip and be considered passing. + * + * @see ZTEST_EXPECT_FAIL + * @see ZTEST_EXPECT_SKIP + */ +struct ztest_expected_result_entry { + const char *test_suite_name; /**< The test suite's name for the expectation */ + const char *test_name; /**< The test's name for the expectation */ + enum ztest_expected_result expected_result; /**< The expectation */ +}; + +extern struct ztest_expected_result_entry _ztest_expected_result_entry_list_start[]; +extern struct ztest_expected_result_entry _ztest_expected_result_entry_list_end[]; + +#define __ZTEST_EXPECT(_suite_name, _test_name, expectation) \ + static const STRUCT_SECTION_ITERABLE( \ + ztest_expected_result_entry, \ + UTIL_CAT(UTIL_CAT(z_ztest_expected_result_, _suite_name), _test_name)) = { \ + .test_suite_name = STRINGIFY(_suite_name), \ + .test_name = STRINGIFY(_test_name), \ + .expected_result = expectation, \ + } + +/** + * @brief Expect a test to fail (mark it passing if it failed) + * + * Adding this macro to your logic will allow the failing test to be considered passing, example: + * + * ZTEST_EXPECT_FAIL(my_suite, test_x); + * ZTEST(my_suite, text_x) { + * zassert_true(false, NULL); + * } + * + * @param _suite_name The name of the suite + * @param _test_name The name of the test + */ +#define ZTEST_EXPECT_FAIL(_suite_name, _test_name) \ + __ZTEST_EXPECT(_suite_name, _test_name, ZTEST_EXPECTED_RESULT_FAIL) + +/** + * @brief Expect a test to skip (mark it passing if it failed) + * + * Adding this macro to your logic will allow the failing test to be considered passing, example: + * + * ZTEST_EXPECT_SKIP(my_suite, test_x); + * ZTEST(my_suite, text_x) { + * zassume_true(false, NULL); + * } + * + * @param _suite_name The name of the suite + * @param _test_name The name of the test + */ +#define ZTEST_EXPECT_SKIP(_suite_name, _test_name) \ + __ZTEST_EXPECT(_suite_name, _test_name, ZTEST_EXPECTED_RESULT_SKIP) + +struct ztest_unit_test { + const char *test_suite_name; + const char *name; + void (*test)(void *data); + uint32_t thread_options; + + /** Stats */ + struct ztest_unit_test_stats *const stats; +}; + +extern struct ztest_unit_test _ztest_unit_test_list_start[]; +extern struct ztest_unit_test _ztest_unit_test_list_end[]; +#define ZTEST_TEST_COUNT (_ztest_unit_test_list_end - _ztest_unit_test_list_start) + +/** + * Stats about a ztest suite + */ +struct ztest_suite_stats { + /** The number of times that the suite ran */ + uint32_t run_count; + /** The number of times that the suite was skipped */ + uint32_t skip_count; + /** The number of times that the suite failed */ + uint32_t fail_count; +}; + +struct ztest_unit_test_stats { + /** The number of times that the test ran */ + uint32_t run_count; + /** The number of times that the test was skipped */ + uint32_t skip_count; + /** The number of times that the test failed */ + uint32_t fail_count; + /** The number of times that the test passed */ + uint32_t pass_count; + /** The longest duration of the test across multiple times */ + uint32_t duration_worst_ms; +}; + +/** + * Setup function to run before running this suite + * + * @return Pointer to the data structure that will be used throughout this test suite + */ +typedef void *(*ztest_suite_setup_t)(void); + +/** + * Function to run before each test in this suite + * + * @param fixture The test suite's fixture returned from setup() + */ +typedef void (*ztest_suite_before_t)(void *fixture); + +/** + * Function to run after each test in this suite + * + * @param fixture The test suite's fixture returned from setup() + */ +typedef void (*ztest_suite_after_t)(void *fixture); + +/** + * Teardown function to run after running this suite + * + * @param fixture The test suite's data returned from setup() + */ +typedef void (*ztest_suite_teardown_t)(void *fixture); + +/** + * An optional predicate function to determine if the test should run. If NULL, then the + * test will only run once on the first attempt. + * + * @param global_state The current state of the test application. + * @return True if the suite should be run; false to skip. + */ +typedef bool (*ztest_suite_predicate_t)(const void *global_state); + +/** + * A single node of test suite. Each node should be added to a single linker section which will + * allow ztest_run_test_suites() to iterate over the various nodes. + */ +struct ztest_suite_node { + /** The name of the test suite. */ + const char *const name; + + /** Setup function */ + const ztest_suite_setup_t setup; + + /** Before function */ + const ztest_suite_before_t before; + + /** After function */ + const ztest_suite_after_t after; + + /** Teardown function */ + const ztest_suite_teardown_t teardown; + + /** Optional predicate filter */ + const ztest_suite_predicate_t predicate; + + /** Stats */ + struct ztest_suite_stats *const stats; +}; + +extern struct ztest_suite_node _ztest_suite_node_list_start[]; +extern struct ztest_suite_node _ztest_suite_node_list_end[]; +#define ZTEST_SUITE_COUNT (_ztest_suite_node_list_end - _ztest_suite_node_list_start) + +/** + * Create and register a ztest suite. Using this macro creates a new test suite (using + * ztest_test_suite). It then creates a struct ztest_suite_node in a specific linker section. + * + * Tests can then be run by calling ztest_run_test_suites(const void *state) by passing + * in the current state. See the documentation for ztest_run_test_suites for more info. + * + * @param SUITE_NAME The name of the suite (see ztest_test_suite for more info) + * @param PREDICATE A function to test against the state and determine if the test should run. + * @param setup_fn The setup function to call before running this test suite + * @param before_fn The function to call before each unit test in this suite + * @param after_fn The function to call after each unit test in this suite + * @param teardown_fn The function to call after running all the tests in this suite + */ +#define ZTEST_SUITE(SUITE_NAME, PREDICATE, setup_fn, before_fn, after_fn, teardown_fn) \ + struct ztest_suite_stats UTIL_CAT(z_ztest_suite_node_stats_, SUITE_NAME); \ + static const STRUCT_SECTION_ITERABLE(ztest_suite_node, \ + UTIL_CAT(z_ztest_test_node_, SUITE_NAME)) = { \ + .name = STRINGIFY(SUITE_NAME), \ + .setup = (setup_fn), \ + .before = (before_fn), \ + .after = (after_fn), \ + .teardown = (teardown_fn), \ + .predicate = PREDICATE, \ + .stats = &UTIL_CAT(z_ztest_suite_node_stats_, SUITE_NAME), \ + } +/** + * Default entry point for running or listing registered unit tests. + * + * @param state The current state of the machine as it relates to the test executable. + */ +void ztest_run_all(const void *state); + +/** + * The result of the current running test. It's possible that the setup function sets the result + * to ZTEST_RESULT_SUITE_* which will apply the failure/skip to every test in the suite. + */ +enum ztest_result { + ZTEST_RESULT_PENDING, + ZTEST_RESULT_PASS, + ZTEST_RESULT_FAIL, + ZTEST_RESULT_SKIP, + ZTEST_RESULT_SUITE_SKIP, + ZTEST_RESULT_SUITE_FAIL, +}; +/** + * Each enum member represents a distinct phase of execution for the test binary. + * TEST_PHASE_FRAMEWORK is active when internal ztest code is executing; the rest refer to + * corresponding phases of user test code. + */ +enum ztest_phase { + TEST_PHASE_SETUP, + TEST_PHASE_BEFORE, + TEST_PHASE_TEST, + TEST_PHASE_AFTER, + TEST_PHASE_TEARDOWN, + TEST_PHASE_FRAMEWORK, +}; + +/** + * Run the registered unit tests which return true from their predicate function. + * + * @param state The current state of the machine as it relates to the test executable. + * @return The number of tests that ran. + */ + +#ifdef ZTEST_UNITTEST +int z_impl_ztest_run_test_suites(const void *state); +static inline int ztest_run_test_suites(const void *state) +{ + return z_impl_ztest_run_test_suites(state); +} + +#else +__syscall int ztest_run_test_suites(const void *state); +#endif + +#ifdef ZTEST_UNITTEST +void z_impl___ztest_set_test_result(enum ztest_result new_result); +static inline void __ztest_set_test_result(enum ztest_result new_result) +{ + z_impl___ztest_set_test_result(new_result); +} + +void z_impl___ztest_set_test_phase(enum ztest_phase new_phase); +static inline void __ztest_set_test_phase(enum ztest_phase new_phase) +{ + z_impl___ztest_set_test_phase(new_phase); +} +#else +__syscall void __ztest_set_test_result(enum ztest_result new_result); +__syscall void __ztest_set_test_phase(enum ztest_phase new_phase); +#endif + + +/** + * @brief Fails the test if any of the registered tests did not run. + * + * When registering test suites, a pragma function can be provided to determine WHEN the test should + * run. It is possible that a test suite could be registered but the pragma always prevents it from + * running. In cases where a test should make sure that ALL suites ran at least once, this function + * may be called at the end of test_main(). It will cause the test to fail if any suite was + * registered but never ran. + */ +void ztest_verify_all_test_suites_ran(void); + +/** + * @brief Run a test suite. + * + * Internal implementation. Do not call directly. This will run the full test suite along with some + * checks for fast failures and initialization. + * + * @param name The name of the suite to run. + * @return Negative value if the test suite never ran; otherwise, return the number of failures. + */ +int z_ztest_run_test_suite(const char *name); + +/** + * @brief Returns next test within suite. + * + * @param suite Name of suite to get next test from. + * @param prev Previous unit test acquired from suite, use NULL to return first + * unit test. + * @return struct ztest_unit_test* + */ +struct ztest_unit_test *z_ztest_get_next_test(const char *suite, struct ztest_unit_test *prev); + +/* definitions for use with testing application shared memory */ +#ifdef CONFIG_USERSPACE +#define ZTEST_DMEM K_APP_DMEM(ztest_mem_partition) +#define ZTEST_BMEM K_APP_BMEM(ztest_mem_partition) +#define ZTEST_SECTION K_APP_DMEM_SECTION(ztest_mem_partition) +extern struct k_mem_partition ztest_mem_partition; +#else +#define ZTEST_DMEM +#define ZTEST_BMEM +#define ZTEST_SECTION .data +#endif + +/** + * @defgroup ztest_test Ztest testing macros + * @ingroup ztest + * + * This module eases the testing process by providing helpful macros and other + * testing structures. + * + * @{ + */ + +/** + * @brief Fail the currently running test. + * + * This is the function called from failed assertions and the like. You + * probably don't need to call it yourself. + */ +void ztest_test_fail(void); + +/** + * @brief Pass the currently running test. + * + * Normally a test passes just by returning without an assertion failure. + * However, if the success case for your test involves a fatal fault, + * you can call this function from k_sys_fatal_error_handler to indicate that + * the test passed before aborting the thread. + */ +void ztest_test_pass(void); + +/** + * @brief Skip the current test. + * + */ +void ztest_test_skip(void); + + +void ztest_skip_failed_assumption(void); + +#define Z_TEST(suite, fn, t_options, use_fixture) \ + struct ztest_unit_test_stats z_ztest_unit_test_stats_##suite##_##fn; \ + static void _##suite##_##fn##_wrapper(void *data); \ + static void suite##_##fn( \ + COND_CODE_1(use_fixture, (struct suite##_fixture *fixture), (void))); \ + static STRUCT_SECTION_ITERABLE(ztest_unit_test, z_ztest_unit_test__##suite##__##fn) = { \ + .test_suite_name = STRINGIFY(suite), \ + .name = STRINGIFY(fn), \ + .test = (_##suite##_##fn##_wrapper), \ + .thread_options = t_options, \ + .stats = &z_ztest_unit_test_stats_##suite##_##fn \ + }; \ + static void _##suite##_##fn##_wrapper(void *wrapper_data) \ + { \ + COND_CODE_1(use_fixture, (suite##_##fn((struct suite##_fixture *)wrapper_data);), \ + (ARG_UNUSED(wrapper_data); suite##_##fn();)) \ + } \ + static inline void suite##_##fn( \ + COND_CODE_1(use_fixture, (struct suite##_fixture *fixture), (void))) + +#define Z_ZTEST(suite, fn, t_options) Z_TEST(suite, fn, t_options, 0) +#define Z_ZTEST_F(suite, fn, t_options) Z_TEST(suite, fn, t_options, 1) + +/** + * @brief Skips the test if config is enabled + * + * Use this macro at the start of your test case, to skip it when + * config is enabled. Useful when your test is still under development. + * + * @param config The Kconfig option used to skip the test. + */ +#define Z_TEST_SKIP_IFDEF(config) COND_CODE_1(config, (ztest_test_skip()), ()) + +/** + * @brief Skips the test if config is not enabled + * + * Use this macro at the start of your test case, to skip it when + * config is not enabled. Useful when your need to skip test if some + * conifiguration option is not enabled. + * + * @param config The Kconfig option used to skip the test (if not enabled). + */ +#define Z_TEST_SKIP_IFNDEF(config) COND_CODE_1(config, (), (ztest_test_skip())) + +/** + * @brief Create and register a new unit test. + * + * Calling this macro will create a new unit test and attach it to the declared `suite`. The `suite` + * does not need to be defined in the same compilation unit. + * + * @param suite The name of the test suite to attach this test + * @param fn The test function to call. + */ +#define ZTEST(suite, fn) Z_ZTEST(suite, fn, 0) + +/** + * @brief Define a test function that should run as a user thread + * + * This macro behaves exactly the same as ZTEST, but calls the test function in user space if + * `CONFIG_USERSPACE` was enabled. + * + * @param suite The name of the test suite to attach this test + * @param fn The test function to call. + */ +#define ZTEST_USER(suite, fn) Z_ZTEST(suite, fn, K_USER) + +/** + * @brief Define a test function + * + * This macro behaves exactly the same as ZTEST(), but the function takes an argument for the + * fixture of type `struct suite##_fixture*` named `this`. + * + * @param suite The name of the test suite to attach this test + * @param fn The test function to call. + */ +#define ZTEST_F(suite, fn) Z_ZTEST_F(suite, fn, 0) + +/** + * @brief Define a test function that should run as a user thread + * + * If CONFIG_USERSPACE is not enabled, this is functionally identical to ZTEST_F(). The test + * function takes a single fixture argument of type `struct suite##_fixture*` named `this`. + * + * @param suite The name of the test suite to attach this test + * @param fn The test function to call. + */ +#define ZTEST_USER_F(suite, fn) Z_ZTEST_F(suite, fn, K_USER) + +/** + * @brief Test rule callback function signature + * + * The function signature that can be used to register a test rule's before/after callback. This + * provides access to the test and the fixture data (if provided). + * + * @param test Pointer to the unit test in context + * @param data Pointer to the test's fixture data (may be NULL) + */ +typedef void (*ztest_rule_cb)(const struct ztest_unit_test *test, void *data); + +/** @private */ +struct ztest_test_rule { + ztest_rule_cb before_each; + ztest_rule_cb after_each; +}; + +/** + * @brief Define a test rule that will run before/after each unit test. + * + * Functions defined here will run before/after each unit test for every test suite. Along with the + * callback, the test functions are provided a pointer to the test being run, and the data. This + * provides a mechanism for tests to perform custom operations depending on the specific test or + * the data (for example logging may use the test's name). + * + * Ordering: + * - Test rule's `before` function will run before the suite's `before` function. This is done to + * allow the test suite's customization to take precedence over the rule which is applied to all + * suites. + * - Test rule's `after` function is not guaranteed to run in any particular order. + * + * @param name The name for the test rule (must be unique within the compilation unit) + * @param before_each_fn The callback function (ztest_rule_cb) to call before each test + * (may be NULL) + * @param after_each_fn The callback function (ztest_rule_cb) to call after each test (may be NULL) + */ +#define ZTEST_RULE(name, before_each_fn, after_each_fn) \ + static STRUCT_SECTION_ITERABLE(ztest_test_rule, z_ztest_test_rule_##name) = { \ + .before_each = (before_each_fn), \ + .after_each = (after_each_fn), \ + } + +extern struct ztest_test_rule _ztest_test_rule_list_start[]; +extern struct ztest_test_rule _ztest_test_rule_list_end[]; + +/** + * @brief A 'before' function to use in test suites that just need to start 1cpu + * + * Ignores data, and calls z_test_1cpu_start() + * + * @param data The test suite's data + */ +void ztest_simple_1cpu_before(void *data); + +/** + * @brief A 'after' function to use in test suites that just need to stop 1cpu + * + * Ignores data, and calls z_test_1cpu_stop() + * + * @param data The test suite's data + */ +void ztest_simple_1cpu_after(void *data); + +/** + * @brief Run the specified test suite. + * + * @param suite Test suite to run. + */ +#define ztest_run_test_suite(suite) z_ztest_run_test_suite(STRINGIFY(suite)) + +/** + * @brief Structure for architecture specific APIs + * + */ +struct ztest_arch_api { + void (*run_all)(const void *state); + bool (*should_suite_run)(const void *state, struct ztest_suite_node *suite); + bool (*should_test_run)(const char *suite, const char *test); +}; + +/** + * @} + */ + __syscall void z_test_1cpu_start(void); __syscall void z_test_1cpu_stop(void); @@ -31,4 +563,4 @@ __syscall void sys_clock_tick_set(uint64_t tick); #include #endif -#endif /* ZEPHYR_TESTSUITE_INCLUDE_ZTEST_TEST_H_ */ +#endif /* ZEPHYR_TESTSUITE_ZTEST_TEST_H_ */ diff --git a/subsys/testsuite/ztest/include/zephyr/ztest_test_deprecated.h b/subsys/testsuite/ztest/include/zephyr/ztest_test_deprecated.h deleted file mode 100644 index 8207b184a5d..00000000000 --- a/subsys/testsuite/ztest/include/zephyr/ztest_test_deprecated.h +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (c) 2016 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * - * @brief Zephyr testing framework _test_deprecated. - */ - -#ifndef ZEPHYR_TESTSUITE_ZTEST_TEST_H_ -#define ZEPHYR_TESTSUITE_ZTEST_TEST_H_ - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct unit_test { - const char *name; - void (*test)(void); - void (*setup)(void); - void (*teardown)(void); - uint32_t thread_options; -}; - -/** - * Stats about a ztest suite - */ -struct ztest_suite_stats { - /** The number of times that the suite ran */ - uint32_t run_count; - /** The number of times that the suite was skipped */ - uint32_t skip_count; - /** The number of times that the suite failed */ - uint32_t fail_count; -}; - -/** - * A single node of test suite. Each node should be added to a single linker section which will - * allow ztest_run_registered_test_suites() to iterate over the various nodes. - */ -struct ztest_suite_node { - /** The name of the test suite. */ - const char *name; - /** Pointer to the test suite. */ - struct unit_test *suite; - /** - * An optional predicate function to determine if the test should run. If NULL, then the - * test will only run once on the first attempt. - * - * @param state The current state of the test application. - * @return True if the suite should be run; false to skip. - */ - bool (*predicate)(const void *state); - /** Stats */ - struct ztest_suite_stats *stats; -}; - -extern struct ztest_suite_node _ztest_suite_node_list_start[]; -extern struct ztest_suite_node _ztest_suite_node_list_end[]; - -/** - * Create and register a ztest suite. Using this macro creates a new test suite (using - * ztest_test_suite). It then creates a struct ztest_suite_node in a specific linker section. - * - * Tests can then be run by calling ztest_run_registered_test_suites(const void *state) by passing - * in the current state. See the documentation for ztest_run_registered_test_suites for more info. - * - * @param SUITE_NAME The name of the suite (see ztest_test_suite for more info) - * @param PREDICATE A function to test against the state and determine if the test should run. - * @param args Varargs placeholder for the remaining arguments passed for the unit tests. - */ -#define ztest_register_test_suite(SUITE_NAME, PREDICATE, args...) \ - ztest_test_suite(SUITE_NAME, ##args); \ - struct ztest_suite_stats UTIL_CAT(z_ztest_test_node_stats_, SUITE_NAME); \ - static STRUCT_SECTION_ITERABLE(ztest_suite_node, z_ztest_test_node_##SUITE_NAME) = { \ - .name = #SUITE_NAME, \ - .suite = _##SUITE_NAME, \ - .predicate = PREDICATE, \ - .stats = &UTIL_CAT(z_ztest_test_node_stats_, SUITE_NAME), \ - }; - -/** - * Run the registered unit tests which return true from their pragma function. - * - * @param state The current state of the machine as it relates to the test executable. - * @return The number of tests that ran. - */ -__deprecated -int ztest_run_registered_test_suites(const void *state); - -/** - * @brief Fails the test if any of the registered tests did not run. - * - * When registering test suites, a pragma function can be provided to determine WHEN the test should - * run. It is possible that a test suite could be registered but the pragma always prevents it from - * running. In cases where a test should make sure that ALL suites ran at least once, this function - * may be called at the end of test_main(). It will cause the test to fail if any suite was - * registered but never ran. - */ -__deprecated -void ztest_verify_all_registered_test_suites_ran(void); - -/** - * @brief Run a test suite. - * - * Internal implementation. Do not call directly. This will run the full test suite along with some - * checks for fast failures and initialization. - * - * @param name The name of the suite to run. - * @param suite Pointer to the first unit test. - * @return Negative value if the test suite never ran; otherwise, return the number of failures. - */ -int z_ztest_run_test_suite(const char *name, struct unit_test *suite); - -/** - * @defgroup ztest_test_deprecated Ztest testing macros - * @ingroup ztest - * - * This module eases the testing process by providing helpful macros and other - * testing structures. - * - * @{ - */ - -/** - * @brief Fail the currently running test. - * - * This is the function called from failed assertions and the like. You - * probably don't need to call it yourself. - */ -void ztest_test_fail(void); - -/** - * @brief Pass the currently running test. - * - * Normally a test passes just by returning without an assertion failure. - * However, if the success case for your test involves a fatal fault, - * you can call this function from k_sys_fatal_error_handler to indicate that - * the test passed before aborting the thread. - */ -void ztest_test_pass(void); - -/** - * @brief Skip the current test. - */ -void ztest_test_skip(void); - -/** - * @brief Do nothing, successfully. - * - * Unit test / setup function / teardown function that does - * nothing, successfully. Can be used as a parameter to - * ztest_unit_test_setup_teardown(). - */ -static inline void unit_test_noop(void) -{ -} - -/** - * @brief Define a test with setup and teardown functions - * - * This should be called as an argument to ztest_test_suite. The test will - * be run in the following order: @a setup, @a fn, @a teardown. - * - * @param fn Main test function - * @param setup Setup function - * @param teardown Teardown function - */ -#define ztest_unit_test_setup_teardown(fn, setup, teardown) \ - { \ - STRINGIFY(fn), fn, setup, teardown, 0 \ - } - -/** - * @brief Define a user mode test with setup and teardown functions - * - * This should be called as an argument to ztest_test_suite. The test will - * be run in the following order: @a setup, @a fn, @a teardown. ALL - * test functions will be run in user mode, and only if CONFIG_USERSPACE - * is enabled, otherwise this is the same as ztest_unit_test_setup_teardown(). - * - * @param fn Main test function - * @param setup Setup function - * @param teardown Teardown function - */ -#define ztest_user_unit_test_setup_teardown(fn, setup, teardown) \ - { \ - STRINGIFY(fn), fn, setup, teardown, K_USER \ - } - -/** - * @brief Define a test function - * - * This should be called as an argument to ztest_test_suite. - * - * @param fn Test function - */ -#define ztest_unit_test(fn) \ - ztest_unit_test_setup_teardown(fn, unit_test_noop, unit_test_noop) - -/** - * @brief Define a test function that should run as a user thread - * - * This should be called as an argument to ztest_test_suite. - * If CONFIG_USERSPACE is not enabled, this is functionally identical to - * ztest_unit_test(). - * - * @param fn Test function - */ -#define ztest_user_unit_test(fn) \ - ztest_user_unit_test_setup_teardown(fn, unit_test_noop, unit_test_noop) - -/** - * @brief Define a SMP-unsafe test function - * - * As ztest_unit_test(), but ensures all test code runs on only - * one CPU when in SMP. - * - * @param fn Test function - */ -#ifdef CONFIG_SMP -#define ztest_1cpu_unit_test(fn) \ - ztest_unit_test_setup_teardown(fn, z_test_1cpu_start, z_test_1cpu_stop) -#else -#define ztest_1cpu_unit_test(fn) ztest_unit_test(fn) -#endif - -/** - * @brief Define a SMP-unsafe test function that should run as a user thread - * - * As ztest_user_unit_test(), but ensures all test code runs on only - * one CPU when in SMP. - * - * @param fn Test function - */ -#ifdef CONFIG_SMP -#define ztest_1cpu_user_unit_test(fn) \ - ztest_user_unit_test_setup_teardown(fn, z_test_1cpu_start, z_test_1cpu_stop) -#else -#define ztest_1cpu_user_unit_test(fn) ztest_user_unit_test(fn) -#endif - -/* definitions for use with testing application shared memory */ -#ifdef CONFIG_USERSPACE -#define ZTEST_DMEM K_APP_DMEM(ztest_mem_partition) -#define ZTEST_BMEM K_APP_BMEM(ztest_mem_partition) -#define ZTEST_SECTION K_APP_DMEM_SECTION(ztest_mem_partition) -extern struct k_mem_partition ztest_mem_partition; -#else -#define ZTEST_DMEM -#define ZTEST_BMEM -#define ZTEST_SECTION .data -#endif - -/** - * @brief Define a test suite - * - * This function should be called in the following fashion: - * ```{.c} - * ztest_test_suite(test_suite_name, - * ztest_unit_test(test_function), - * ztest_unit_test(test_other_function) - * ); - * - * ztest_run_test_suite(test_suite_name); - * ``` - * - * @param suite Name of the testing suite - */ -#define ztest_test_suite(suite, ...) __DEPRECATED_MACRO \ - static ZTEST_DMEM struct unit_test _##suite[] = { __VA_ARGS__, { 0 } } -/** - * @brief Run the specified test suite. - * - * @param suite Test suite to run. - */ -#define ztest_run_test_suite(suite) __DEPRECATED_MACRO \ - z_ztest_run_test_suite(#suite, _##suite) - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZEPHYR_TESTSUITE_ZTEST_TEST_H_ */ diff --git a/subsys/testsuite/ztest/include/zephyr/ztest_test_new.h b/subsys/testsuite/ztest/include/zephyr/ztest_test_new.h deleted file mode 100644 index e676bf7d3d8..00000000000 --- a/subsys/testsuite/ztest/include/zephyr/ztest_test_new.h +++ /dev/null @@ -1,560 +0,0 @@ -/* - * Copyright (c) 2016 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * - * @brief Zephyr testing framework _test. - */ - -#ifndef ZEPHYR_TESTSUITE_ZTEST_TEST_H_ -#define ZEPHYR_TESTSUITE_ZTEST_TEST_H_ - -#include -#include -#include -#include - -#if defined(CONFIG_USERSPACE) -#define __USERSPACE_FLAGS (K_USER) -#else -#define __USERSPACE_FLAGS (0) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief The expected result of a test. - * - * @see ZTEST_EXPECT_FAIL - * @see ZTEST_EXPECT_SKIP - */ -enum ztest_expected_result { - ZTEST_EXPECTED_RESULT_FAIL = 0, /**< Expect a test to fail */ - ZTEST_EXPECTED_RESULT_SKIP, /**< Expect a test to pass */ -}; - -/** - * @brief A single expectation entry allowing tests to fail/skip and be considered passing. - * - * @see ZTEST_EXPECT_FAIL - * @see ZTEST_EXPECT_SKIP - */ -struct ztest_expected_result_entry { - const char *test_suite_name; /**< The test suite's name for the expectation */ - const char *test_name; /**< The test's name for the expectation */ - enum ztest_expected_result expected_result; /**< The expectation */ -}; - -extern struct ztest_expected_result_entry _ztest_expected_result_entry_list_start[]; -extern struct ztest_expected_result_entry _ztest_expected_result_entry_list_end[]; - -#define __ZTEST_EXPECT(_suite_name, _test_name, expectation) \ - static const STRUCT_SECTION_ITERABLE( \ - ztest_expected_result_entry, \ - UTIL_CAT(UTIL_CAT(z_ztest_expected_result_, _suite_name), _test_name)) = { \ - .test_suite_name = STRINGIFY(_suite_name), \ - .test_name = STRINGIFY(_test_name), \ - .expected_result = expectation, \ - } - -/** - * @brief Expect a test to fail (mark it passing if it failed) - * - * Adding this macro to your logic will allow the failing test to be considered passing, example: - * - * ZTEST_EXPECT_FAIL(my_suite, test_x); - * ZTEST(my_suite, text_x) { - * zassert_true(false, NULL); - * } - * - * @param _suite_name The name of the suite - * @param _test_name The name of the test - */ -#define ZTEST_EXPECT_FAIL(_suite_name, _test_name) \ - __ZTEST_EXPECT(_suite_name, _test_name, ZTEST_EXPECTED_RESULT_FAIL) - -/** - * @brief Expect a test to skip (mark it passing if it failed) - * - * Adding this macro to your logic will allow the failing test to be considered passing, example: - * - * ZTEST_EXPECT_SKIP(my_suite, test_x); - * ZTEST(my_suite, text_x) { - * zassume_true(false, NULL); - * } - * - * @param _suite_name The name of the suite - * @param _test_name The name of the test - */ -#define ZTEST_EXPECT_SKIP(_suite_name, _test_name) \ - __ZTEST_EXPECT(_suite_name, _test_name, ZTEST_EXPECTED_RESULT_SKIP) - -struct ztest_unit_test { - const char *test_suite_name; - const char *name; - void (*test)(void *data); - uint32_t thread_options; - - /** Stats */ - struct ztest_unit_test_stats *const stats; -}; - -extern struct ztest_unit_test _ztest_unit_test_list_start[]; -extern struct ztest_unit_test _ztest_unit_test_list_end[]; -#define ZTEST_TEST_COUNT (_ztest_unit_test_list_end - _ztest_unit_test_list_start) - -/** - * Stats about a ztest suite - */ -struct ztest_suite_stats { - /** The number of times that the suite ran */ - uint32_t run_count; - /** The number of times that the suite was skipped */ - uint32_t skip_count; - /** The number of times that the suite failed */ - uint32_t fail_count; -}; - -struct ztest_unit_test_stats { - /** The number of times that the test ran */ - uint32_t run_count; - /** The number of times that the test was skipped */ - uint32_t skip_count; - /** The number of times that the test failed */ - uint32_t fail_count; - /** The number of times that the test passed */ - uint32_t pass_count; - /** The longest duration of the test across multiple times */ - uint32_t duration_worst_ms; -}; - -/** - * Setup function to run before running this suite - * - * @return Pointer to the data structure that will be used throughout this test suite - */ -typedef void *(*ztest_suite_setup_t)(void); - -/** - * Function to run before each test in this suite - * - * @param fixture The test suite's fixture returned from setup() - */ -typedef void (*ztest_suite_before_t)(void *fixture); - -/** - * Function to run after each test in this suite - * - * @param fixture The test suite's fixture returned from setup() - */ -typedef void (*ztest_suite_after_t)(void *fixture); - -/** - * Teardown function to run after running this suite - * - * @param fixture The test suite's data returned from setup() - */ -typedef void (*ztest_suite_teardown_t)(void *fixture); - -/** - * An optional predicate function to determine if the test should run. If NULL, then the - * test will only run once on the first attempt. - * - * @param global_state The current state of the test application. - * @return True if the suite should be run; false to skip. - */ -typedef bool (*ztest_suite_predicate_t)(const void *global_state); - -/** - * A single node of test suite. Each node should be added to a single linker section which will - * allow ztest_run_test_suites() to iterate over the various nodes. - */ -struct ztest_suite_node { - /** The name of the test suite. */ - const char *const name; - - /** Setup function */ - const ztest_suite_setup_t setup; - - /** Before function */ - const ztest_suite_before_t before; - - /** After function */ - const ztest_suite_after_t after; - - /** Teardown function */ - const ztest_suite_teardown_t teardown; - - /** Optional predicate filter */ - const ztest_suite_predicate_t predicate; - - /** Stats */ - struct ztest_suite_stats *const stats; -}; - -extern struct ztest_suite_node _ztest_suite_node_list_start[]; -extern struct ztest_suite_node _ztest_suite_node_list_end[]; -#define ZTEST_SUITE_COUNT (_ztest_suite_node_list_end - _ztest_suite_node_list_start) - -/** - * Create and register a ztest suite. Using this macro creates a new test suite (using - * ztest_test_suite). It then creates a struct ztest_suite_node in a specific linker section. - * - * Tests can then be run by calling ztest_run_test_suites(const void *state) by passing - * in the current state. See the documentation for ztest_run_test_suites for more info. - * - * @param SUITE_NAME The name of the suite (see ztest_test_suite for more info) - * @param PREDICATE A function to test against the state and determine if the test should run. - * @param setup_fn The setup function to call before running this test suite - * @param before_fn The function to call before each unit test in this suite - * @param after_fn The function to call after each unit test in this suite - * @param teardown_fn The function to call after running all the tests in this suite - */ -#define ZTEST_SUITE(SUITE_NAME, PREDICATE, setup_fn, before_fn, after_fn, teardown_fn) \ - struct ztest_suite_stats UTIL_CAT(z_ztest_suite_node_stats_, SUITE_NAME); \ - static const STRUCT_SECTION_ITERABLE(ztest_suite_node, \ - UTIL_CAT(z_ztest_test_node_, SUITE_NAME)) = { \ - .name = STRINGIFY(SUITE_NAME), \ - .setup = (setup_fn), \ - .before = (before_fn), \ - .after = (after_fn), \ - .teardown = (teardown_fn), \ - .predicate = PREDICATE, \ - .stats = &UTIL_CAT(z_ztest_suite_node_stats_, SUITE_NAME), \ - } -/** - * Default entry point for running or listing registered unit tests. - * - * @param state The current state of the machine as it relates to the test executable. - */ -void ztest_run_all(const void *state); - -/** - * The result of the current running test. It's possible that the setup function sets the result - * to ZTEST_RESULT_SUITE_* which will apply the failure/skip to every test in the suite. - */ -enum ztest_result { - ZTEST_RESULT_PENDING, - ZTEST_RESULT_PASS, - ZTEST_RESULT_FAIL, - ZTEST_RESULT_SKIP, - ZTEST_RESULT_SUITE_SKIP, - ZTEST_RESULT_SUITE_FAIL, -}; -/** - * Each enum member represents a distinct phase of execution for the test binary. - * TEST_PHASE_FRAMEWORK is active when internal ztest code is executing; the rest refer to - * corresponding phases of user test code. - */ -enum ztest_phase { - TEST_PHASE_SETUP, - TEST_PHASE_BEFORE, - TEST_PHASE_TEST, - TEST_PHASE_AFTER, - TEST_PHASE_TEARDOWN, - TEST_PHASE_FRAMEWORK, -}; - -/** - * Run the registered unit tests which return true from their predicate function. - * - * @param state The current state of the machine as it relates to the test executable. - * @return The number of tests that ran. - */ - -#ifdef ZTEST_UNITTEST -int z_impl_ztest_run_test_suites(const void *state); -static inline int ztest_run_test_suites(const void *state) -{ - return z_impl_ztest_run_test_suites(state); -} - -#else -__syscall int ztest_run_test_suites(const void *state); -#endif - -#ifdef ZTEST_UNITTEST -void z_impl___ztest_set_test_result(enum ztest_result new_result); -static inline void __ztest_set_test_result(enum ztest_result new_result) -{ - z_impl___ztest_set_test_result(new_result); -} - -void z_impl___ztest_set_test_phase(enum ztest_phase new_phase); -static inline void __ztest_set_test_phase(enum ztest_phase new_phase) -{ - z_impl___ztest_set_test_phase(new_phase); -} -#else -__syscall void __ztest_set_test_result(enum ztest_result new_result); -__syscall void __ztest_set_test_phase(enum ztest_phase new_phase); -#endif - -#ifndef ZTEST_UNITTEST -#include -#endif - -/** - * @brief Fails the test if any of the registered tests did not run. - * - * When registering test suites, a pragma function can be provided to determine WHEN the test should - * run. It is possible that a test suite could be registered but the pragma always prevents it from - * running. In cases where a test should make sure that ALL suites ran at least once, this function - * may be called at the end of test_main(). It will cause the test to fail if any suite was - * registered but never ran. - */ -void ztest_verify_all_test_suites_ran(void); - -/** - * @brief Run a test suite. - * - * Internal implementation. Do not call directly. This will run the full test suite along with some - * checks for fast failures and initialization. - * - * @param name The name of the suite to run. - * @return Negative value if the test suite never ran; otherwise, return the number of failures. - */ -int z_ztest_run_test_suite(const char *name); - -/** - * @brief Returns next test within suite. - * - * @param suite Name of suite to get next test from. - * @param prev Previous unit test acquired from suite, use NULL to return first - * unit test. - * @return struct ztest_unit_test* - */ -struct ztest_unit_test *z_ztest_get_next_test(const char *suite, struct ztest_unit_test *prev); - -/* definitions for use with testing application shared memory */ -#ifdef CONFIG_USERSPACE -#define ZTEST_DMEM K_APP_DMEM(ztest_mem_partition) -#define ZTEST_BMEM K_APP_BMEM(ztest_mem_partition) -#define ZTEST_SECTION K_APP_DMEM_SECTION(ztest_mem_partition) -extern struct k_mem_partition ztest_mem_partition; -#else -#define ZTEST_DMEM -#define ZTEST_BMEM -#define ZTEST_SECTION .data -#endif - -/** - * @defgroup ztest_test Ztest testing macros - * @ingroup ztest - * - * This module eases the testing process by providing helpful macros and other - * testing structures. - * - * @{ - */ - -/** - * @brief Fail the currently running test. - * - * This is the function called from failed assertions and the like. You - * probably don't need to call it yourself. - */ -void ztest_test_fail(void); - -/** - * @brief Pass the currently running test. - * - * Normally a test passes just by returning without an assertion failure. - * However, if the success case for your test involves a fatal fault, - * you can call this function from k_sys_fatal_error_handler to indicate that - * the test passed before aborting the thread. - */ -void ztest_test_pass(void); - -/** - * @brief Skip the current test. - * - */ -void ztest_test_skip(void); - - -void ztest_skip_failed_assumption(void); - -#define Z_TEST(suite, fn, t_options, use_fixture) \ - struct ztest_unit_test_stats z_ztest_unit_test_stats_##suite##_##fn; \ - static void _##suite##_##fn##_wrapper(void *data); \ - static void suite##_##fn( \ - COND_CODE_1(use_fixture, (struct suite##_fixture *fixture), (void))); \ - static STRUCT_SECTION_ITERABLE(ztest_unit_test, z_ztest_unit_test__##suite##__##fn) = { \ - .test_suite_name = STRINGIFY(suite), \ - .name = STRINGIFY(fn), \ - .test = (_##suite##_##fn##_wrapper), \ - .thread_options = t_options, \ - .stats = &z_ztest_unit_test_stats_##suite##_##fn \ - }; \ - static void _##suite##_##fn##_wrapper(void *wrapper_data) \ - { \ - COND_CODE_1(use_fixture, (suite##_##fn((struct suite##_fixture *)wrapper_data);), \ - (ARG_UNUSED(wrapper_data); suite##_##fn();)) \ - } \ - static inline void suite##_##fn( \ - COND_CODE_1(use_fixture, (struct suite##_fixture *fixture), (void))) - -#define Z_ZTEST(suite, fn, t_options) Z_TEST(suite, fn, t_options, 0) -#define Z_ZTEST_F(suite, fn, t_options) Z_TEST(suite, fn, t_options, 1) - -/** - * @brief Skips the test if config is enabled - * - * Use this macro at the start of your test case, to skip it when - * config is enabled. Useful when your test is still under development. - * - * @param config The Kconfig option used to skip the test. - */ -#define Z_TEST_SKIP_IFDEF(config) COND_CODE_1(config, (ztest_test_skip()), ()) - -/** - * @brief Skips the test if config is not enabled - * - * Use this macro at the start of your test case, to skip it when - * config is not enabled. Useful when your need to skip test if some - * conifiguration option is not enabled. - * - * @param config The Kconfig option used to skip the test (if not enabled). - */ -#define Z_TEST_SKIP_IFNDEF(config) COND_CODE_1(config, (), (ztest_test_skip())) - -/** - * @brief Create and register a new unit test. - * - * Calling this macro will create a new unit test and attach it to the declared `suite`. The `suite` - * does not need to be defined in the same compilation unit. - * - * @param suite The name of the test suite to attach this test - * @param fn The test function to call. - */ -#define ZTEST(suite, fn) Z_ZTEST(suite, fn, 0) - -/** - * @brief Define a test function that should run as a user thread - * - * This macro behaves exactly the same as ZTEST, but calls the test function in user space if - * `CONFIG_USERSPACE` was enabled. - * - * @param suite The name of the test suite to attach this test - * @param fn The test function to call. - */ -#define ZTEST_USER(suite, fn) Z_ZTEST(suite, fn, K_USER) - -/** - * @brief Define a test function - * - * This macro behaves exactly the same as ZTEST(), but the function takes an argument for the - * fixture of type `struct suite##_fixture*` named `this`. - * - * @param suite The name of the test suite to attach this test - * @param fn The test function to call. - */ -#define ZTEST_F(suite, fn) Z_ZTEST_F(suite, fn, 0) - -/** - * @brief Define a test function that should run as a user thread - * - * If CONFIG_USERSPACE is not enabled, this is functionally identical to ZTEST_F(). The test - * function takes a single fixture argument of type `struct suite##_fixture*` named `this`. - * - * @param suite The name of the test suite to attach this test - * @param fn The test function to call. - */ -#define ZTEST_USER_F(suite, fn) Z_ZTEST_F(suite, fn, K_USER) - -/** - * @brief Test rule callback function signature - * - * The function signature that can be used to register a test rule's before/after callback. This - * provides access to the test and the fixture data (if provided). - * - * @param test Pointer to the unit test in context - * @param data Pointer to the test's fixture data (may be NULL) - */ -typedef void (*ztest_rule_cb)(const struct ztest_unit_test *test, void *data); - -/** @private */ -struct ztest_test_rule { - ztest_rule_cb before_each; - ztest_rule_cb after_each; -}; - -/** - * @brief Define a test rule that will run before/after each unit test. - * - * Functions defined here will run before/after each unit test for every test suite. Along with the - * callback, the test functions are provided a pointer to the test being run, and the data. This - * provides a mechanism for tests to perform custom operations depending on the specific test or - * the data (for example logging may use the test's name). - * - * Ordering: - * - Test rule's `before` function will run before the suite's `before` function. This is done to - * allow the test suite's customization to take precedence over the rule which is applied to all - * suites. - * - Test rule's `after` function is not guaranteed to run in any particular order. - * - * @param name The name for the test rule (must be unique within the compilation unit) - * @param before_each_fn The callback function (ztest_rule_cb) to call before each test - * (may be NULL) - * @param after_each_fn The callback function (ztest_rule_cb) to call after each test (may be NULL) - */ -#define ZTEST_RULE(name, before_each_fn, after_each_fn) \ - static STRUCT_SECTION_ITERABLE(ztest_test_rule, z_ztest_test_rule_##name) = { \ - .before_each = (before_each_fn), \ - .after_each = (after_each_fn), \ - } - -extern struct ztest_test_rule _ztest_test_rule_list_start[]; -extern struct ztest_test_rule _ztest_test_rule_list_end[]; - -/** - * @brief A 'before' function to use in test suites that just need to start 1cpu - * - * Ignores data, and calls z_test_1cpu_start() - * - * @param data The test suite's data - */ -void ztest_simple_1cpu_before(void *data); - -/** - * @brief A 'after' function to use in test suites that just need to stop 1cpu - * - * Ignores data, and calls z_test_1cpu_stop() - * - * @param data The test suite's data - */ -void ztest_simple_1cpu_after(void *data); - -/** - * @brief Run the specified test suite. - * - * @param suite Test suite to run. - */ -#define ztest_run_test_suite(suite) z_ztest_run_test_suite(STRINGIFY(suite)) - -/** - * @brief Structure for architecture specific APIs - * - */ -struct ztest_arch_api { - void (*run_all)(const void *state); - bool (*should_suite_run)(const void *state, struct ztest_suite_node *suite); - bool (*should_test_run)(const char *suite, const char *test); -}; - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZEPHYR_TESTSUITE_ZTEST_TEST_H_ */ diff --git a/subsys/testsuite/ztest/src/ztest.c b/subsys/testsuite/ztest/src/ztest.c index 04e16b97f92..d49a1ef9c11 100644 --- a/subsys/testsuite/ztest/src/ztest.c +++ b/subsys/testsuite/ztest/src/ztest.c @@ -4,53 +4,65 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include - - #include + #include #ifdef CONFIG_USERSPACE #include #endif -#include #include +#include #ifdef KERNEL static struct k_thread ztest_thread; #endif +static bool failed_expectation; -#ifdef CONFIG_ARCH_POSIX -#include +#ifdef CONFIG_ZTEST_SHUFFLE +#include +#include + +#include +#define NUM_ITER_PER_SUITE CONFIG_ZTEST_SHUFFLE_SUITE_REPEAT_COUNT +#define NUM_ITER_PER_TEST CONFIG_ZTEST_SHUFFLE_TEST_REPEAT_COUNT +#else +#define NUM_ITER_PER_SUITE 1 +#define NUM_ITER_PER_TEST 1 #endif /* ZTEST_DMEM and ZTEST_BMEM are used for the application shared memory test */ -ZTEST_DMEM enum { - TEST_PHASE_SETUP, - TEST_PHASE_TEST, - TEST_PHASE_TEARDOWN, - TEST_PHASE_FRAMEWORK -} phase = TEST_PHASE_FRAMEWORK; - -static ZTEST_BMEM int test_status; +/** + * @brief The current status of the test binary + */ +enum ztest_status { + ZTEST_STATUS_OK, + ZTEST_STATUS_HAS_FAILURE, + ZTEST_STATUS_CRITICAL_ERROR +}; /** - * @brief Try to shorten a filename by removing the current directory - * - * This helps to reduce the very long filenames in assertion failures. It - * removes the current directory from the filename and returns the rest. - * This makes assertions a lot more readable, and sometimes they fit on one - * line. - * - * @param file Filename to check - * @returns Shortened filename, or @file if it could not be shortened + * @brief Tracks the current phase that ztest is operating in. */ -const char *__weak ztest_relative_filename(const char *file) +ZTEST_DMEM enum ztest_phase cur_phase = TEST_PHASE_FRAMEWORK; + +static ZTEST_BMEM enum ztest_status test_status = ZTEST_STATUS_OK; + +extern ZTEST_DMEM const struct ztest_arch_api ztest_api; + +static void __ztest_show_suite_summary(void); + +static void end_report(void) { - return file; + __ztest_show_suite_summary(); + if (test_status) { + TC_END_REPORT(TC_FAIL); + } else { + TC_END_REPORT(TC_PASS); + } } -static int cleanup_test(struct unit_test *test) +static int cleanup_test(struct ztest_unit_test *test) { int ret = TC_PASS; int mock_status; @@ -68,12 +80,10 @@ static int cleanup_test(struct unit_test *test) #endif if (!ret && mock_status == 1) { - PRINT("Test %s failed: Unused mock parameter values\n", - test->name); + PRINT("Test %s failed: Unused mock parameter values\n", test->name); ret = TC_FAIL; } else if (!ret && mock_status == 2) { - PRINT("Test %s failed: Unused mock return values\n", - test->name); + PRINT("Test %s failed: Unused mock return values\n", test->name); ret = TC_FAIL; } else { ; @@ -89,6 +99,7 @@ static int cleanup_test(struct unit_test *test) #define CPUHOLD_STACK_SZ (512 + CONFIG_TEST_EXTRA_STACK_SIZE) static struct k_thread cpuhold_threads[MAX_NUM_CPUHOLD]; K_KERNEL_STACK_ARRAY_DEFINE(cpuhold_stacks, MAX_NUM_CPUHOLD, CPUHOLD_STACK_SZ); + static struct k_sem cpuhold_sem; volatile int cpuhold_active; @@ -102,6 +113,7 @@ static void cpu_hold(void *arg1, void *arg2, void *arg3) ARG_UNUSED(arg1); ARG_UNUSED(arg2); ARG_UNUSED(arg3); + unsigned int key = arch_irq_lock(); uint32_t dt, start_ms = k_uptime_get_32(); @@ -139,23 +151,21 @@ void z_impl_z_test_1cpu_start(void) unsigned int num_cpus = arch_num_cpus(); cpuhold_active = 1; -#ifdef CONFIG_THREAD_NAME char tname[CONFIG_THREAD_MAX_NAME_LEN]; -#endif + k_sem_init(&cpuhold_sem, 0, 999); /* Spawn N-1 threads to "hold" the other CPUs, waiting for * each to signal us that it's locked and spinning. */ - for (int i = 0; i < num_cpus - 1; i++) { - k_thread_create(&cpuhold_threads[i], - cpuhold_stacks[i], CPUHOLD_STACK_SZ, - (k_thread_entry_t) cpu_hold, NULL, NULL, NULL, - K_HIGHEST_THREAD_PRIO, 0, K_NO_WAIT); -#ifdef CONFIG_THREAD_NAME - snprintk(tname, CONFIG_THREAD_MAX_NAME_LEN, "cpuhold%02d", i); - k_thread_name_set(&cpuhold_threads[i], tname); -#endif + for (int i = 0; i < num_cpus - 1; i++) { + k_thread_create(&cpuhold_threads[i], cpuhold_stacks[i], CPUHOLD_STACK_SZ, + cpu_hold, NULL, NULL, NULL, K_HIGHEST_THREAD_PRIO, + 0, K_NO_WAIT); + if (IS_ENABLED(CONFIG_THREAD_NAME)) { + snprintk(tname, CONFIG_THREAD_MAX_NAME_LEN, "cpuhold%02d", i); + k_thread_name_set(&cpuhold_threads[i], tname); + } k_sem_take(&cpuhold_sem, K_FOREVER); } #endif @@ -168,36 +178,107 @@ void z_impl_z_test_1cpu_stop(void) cpuhold_active = 0; - /* Note that NUM_CPUHOLD can be a value that causes coverity - * to flag the following loop as DEADCODE so suppress the warning. - */ - for (int i = 0; i < num_cpus - 1; i++) { + for (int i = 0; i < num_cpus - 1; i++) { k_thread_abort(&cpuhold_threads[i]); } #endif } #ifdef CONFIG_USERSPACE -void z_vrfy_z_test_1cpu_start(void) -{ - z_impl_z_test_1cpu_start(); -} +void z_vrfy_z_test_1cpu_start(void) { z_impl_z_test_1cpu_start(); } #include -void z_vrfy_z_test_1cpu_stop(void) -{ - z_impl_z_test_1cpu_stop(); -} +void z_vrfy_z_test_1cpu_stop(void) { z_impl_z_test_1cpu_stop(); } #include #endif /* CONFIG_USERSPACE */ #endif -static void run_test_functions(struct unit_test *test) +__maybe_unused static void run_test_rules(bool is_before, struct ztest_unit_test *test, void *data) +{ + for (struct ztest_test_rule *rule = _ztest_test_rule_list_start; + rule < _ztest_test_rule_list_end; ++rule) { + if (is_before && rule->before_each) { + rule->before_each(test, data); + } else if (!is_before && rule->after_each) { + rule->after_each(test, data); + } + } +} + +static void run_test_functions(struct ztest_suite_node *suite, struct ztest_unit_test *test, + void *data) +{ + __ztest_set_test_phase(TEST_PHASE_TEST); + test->test(data); +} + +COND_CODE_1(KERNEL, (ZTEST_BMEM), ()) static enum ztest_result test_result; + +static int get_final_test_result(const struct ztest_unit_test *test, int ret) +{ + enum ztest_expected_result expected_result = -1; + + for (struct ztest_expected_result_entry *expectation = + _ztest_expected_result_entry_list_start; + expectation < _ztest_expected_result_entry_list_end; ++expectation) { + if (strcmp(expectation->test_name, test->name) == 0 && + strcmp(expectation->test_suite_name, test->test_suite_name) == 0) { + expected_result = expectation->expected_result; + break; + } + } + + if (expected_result == ZTEST_EXPECTED_RESULT_FAIL) { + /* Expected a failure: + * - If we got a failure, return TC_PASS + * - Otherwise force a failure + */ + return (ret == TC_FAIL) ? TC_PASS : TC_FAIL; + } + if (expected_result == ZTEST_EXPECTED_RESULT_SKIP) { + /* Expected a skip: + * - If we got a skip, return TC_PASS + * - Otherwise force a failure + */ + return (ret == TC_SKIP) ? TC_PASS : TC_FAIL; + } + /* No expectation was made, no change is needed. */ + return ret; +} + +/** + * @brief Get a friendly name string for a given test phrase. + * + * @param phase an enum ztest_phase value describing the desired test phase + * @returns a string name for `phase` + */ +static inline const char *get_friendly_phase_name(enum ztest_phase phase) +{ + switch (phase) { + case TEST_PHASE_SETUP: + return "setup"; + case TEST_PHASE_BEFORE: + return "before"; + case TEST_PHASE_TEST: + return "test"; + case TEST_PHASE_AFTER: + return "after"; + case TEST_PHASE_TEARDOWN: + return "teardown"; + case TEST_PHASE_FRAMEWORK: + return "framework"; + default: + return "(unknown)"; + } +} + +static bool current_test_failed_assumption; +void ztest_skip_failed_assumption(void) { - phase = TEST_PHASE_SETUP; - test->setup(); - phase = TEST_PHASE_TEST; - test->test(); + if (IS_ENABLED(CONFIG_ZTEST_FAIL_ON_ASSUME)) { + current_test_failed_assumption = true; + } + ztest_test_skip(); } #ifndef KERNEL @@ -210,78 +291,95 @@ static void run_test_functions(struct unit_test *test) */ #include /* parasoft-suppress MISRAC2012-RULE_21_4-a MISRAC2012-RULE_21_4-b*/ #include -#include #include +#include #define FAIL_FAST 0 static jmp_buf test_fail; -static jmp_buf test_skip; static jmp_buf test_pass; +static jmp_buf test_skip; static jmp_buf stack_fail; +static jmp_buf test_suite_fail; void ztest_test_fail(void) { - raise(SIGABRT); -} - -void ztest_test_skip(void) -{ - longjmp(test_skip, 1); + switch (cur_phase) { + case TEST_PHASE_SETUP: + PRINT(" at %s function\n", get_friendly_phase_name(cur_phase)); + longjmp(test_suite_fail, 1); + case TEST_PHASE_BEFORE: + case TEST_PHASE_TEST: + PRINT(" at %s function\n", get_friendly_phase_name(cur_phase)); + longjmp(test_fail, 1); + case TEST_PHASE_AFTER: + case TEST_PHASE_TEARDOWN: + case TEST_PHASE_FRAMEWORK: + PRINT(" ERROR: cannot fail in test phase '%s()', bailing\n", + get_friendly_phase_name(cur_phase)); + longjmp(stack_fail, 1); + } } void ztest_test_pass(void) { - longjmp(test_pass, 1); + if (cur_phase == TEST_PHASE_TEST) { + longjmp(test_pass, 1); + } + PRINT(" ERROR: cannot pass in test phase '%s()', bailing\n", + get_friendly_phase_name(cur_phase)); + longjmp(stack_fail, 1); } -static void handle_signal(int sig) +void ztest_test_skip(void) { - static const char *const phase_str[] = { - "setup", - "unit test", - "teardown", - }; - - PRINT(" %s", strsignal(sig)); - switch (phase) { + switch (cur_phase) { case TEST_PHASE_SETUP: + case TEST_PHASE_BEFORE: case TEST_PHASE_TEST: - case TEST_PHASE_TEARDOWN: - PRINT(" at %s function\n", phase_str[phase]); - longjmp(test_fail, 1); - case TEST_PHASE_FRAMEWORK: - PRINT("\n"); + longjmp(test_skip, 1); + default: + PRINT(" ERROR: cannot skip in test phase '%s()', bailing\n", + get_friendly_phase_name(cur_phase)); longjmp(stack_fail, 1); } } -static void init_testing(void) +void ztest_test_expect_fail(void) { - signal(SIGABRT, handle_signal); - signal(SIGSEGV, handle_signal); + failed_expectation = true; - if (setjmp(stack_fail)) { - PRINT("TESTSUITE crashed."); - exit(1); + switch (cur_phase) { + case TEST_PHASE_SETUP: + PRINT(" at %s function\n", get_friendly_phase_name(cur_phase)); + break; + case TEST_PHASE_BEFORE: + case TEST_PHASE_TEST: + PRINT(" at %s function\n", get_friendly_phase_name(cur_phase)); + break; + case TEST_PHASE_AFTER: + case TEST_PHASE_TEARDOWN: + case TEST_PHASE_FRAMEWORK: + PRINT(" ERROR: cannot fail in test phase '%s()', bailing\n", + get_friendly_phase_name(cur_phase)); + longjmp(stack_fail, 1); } } -static int run_test(struct unit_test *test) +static int run_test(struct ztest_suite_node *suite, struct ztest_unit_test *test, void *data) { int ret = TC_PASS; - int skip = 0; TC_START(test->name); - get_start_time_cyc(); + __ztest_set_test_phase(TEST_PHASE_BEFORE); - if (setjmp(test_fail)) { + if (test_result == ZTEST_RESULT_SUITE_FAIL) { ret = TC_FAIL; goto out; } - if (setjmp(test_skip)) { - skip = 1; + if (setjmp(test_fail)) { + ret = TC_FAIL; goto out; } @@ -290,15 +388,36 @@ static int run_test(struct unit_test *test) goto out; } - run_test_functions(test); + if (setjmp(test_skip)) { + ret = TC_SKIP; + goto out; + } + + run_test_rules(/*is_before=*/true, test, data); + if (suite->before) { + suite->before(data); + } + run_test_functions(suite, test, data); out: + if (failed_expectation) { + failed_expectation = false; + ret = TC_FAIL; + } + + __ztest_set_test_phase(TEST_PHASE_AFTER); + if (test_result != ZTEST_RESULT_SUITE_FAIL) { + if (suite->after != NULL) { + suite->after(data); + } + run_test_rules(/*is_before=*/false, test, data); + } + __ztest_set_test_phase(TEST_PHASE_FRAMEWORK); ret |= cleanup_test(test); - get_test_duration_ms(); - if (skip) { - Z_TC_END_RESULT(TC_SKIP, test->name); - } else { - Z_TC_END_RESULT(ret, test->name); + ret = get_final_test_result(test, ret); + Z_TC_END_RESULT(ret, test->name); + if (ret == TC_SKIP && current_test_failed_assumption) { + test_status = 1; } return ret; @@ -315,105 +434,191 @@ static int run_test(struct unit_test *test) #define FAIL_FAST 0 #endif -K_THREAD_STACK_DEFINE(ztest_thread_stack, CONFIG_ZTEST_STACK_SIZE + - CONFIG_TEST_EXTRA_STACK_SIZE); -static ZTEST_BMEM int test_result; +K_THREAD_STACK_DEFINE(ztest_thread_stack, CONFIG_ZTEST_STACK_SIZE + CONFIG_TEST_EXTRA_STACK_SIZE); static void test_finalize(void) { if (IS_ENABLED(CONFIG_MULTITHREADING)) { k_thread_abort(&ztest_thread); + if (k_is_in_isr()) { + return; + } + k_thread_abort(k_current_get()); + CODE_UNREACHABLE; } } void ztest_test_fail(void) { - test_result = -1; - test_finalize(); + switch (cur_phase) { + case TEST_PHASE_SETUP: + __ztest_set_test_result(ZTEST_RESULT_SUITE_FAIL); + break; + case TEST_PHASE_BEFORE: + case TEST_PHASE_TEST: + __ztest_set_test_result(ZTEST_RESULT_FAIL); + test_finalize(); + break; + default: + PRINT(" ERROR: cannot fail in test phase '%s()', bailing\n", + get_friendly_phase_name(cur_phase)); + test_status = ZTEST_STATUS_CRITICAL_ERROR; + break; + } } void ztest_test_pass(void) { - test_result = 0; - test_finalize(); + switch (cur_phase) { + case TEST_PHASE_TEST: + __ztest_set_test_result(ZTEST_RESULT_PASS); + test_finalize(); + break; + default: + PRINT(" ERROR: cannot pass in test phase '%s()', bailing\n", + get_friendly_phase_name(cur_phase)); + test_status = ZTEST_STATUS_CRITICAL_ERROR; + if (cur_phase == TEST_PHASE_BEFORE) { + test_finalize(); + } + } } void ztest_test_skip(void) { - test_result = -2; - test_finalize(); + switch (cur_phase) { + case TEST_PHASE_SETUP: + __ztest_set_test_result(ZTEST_RESULT_SUITE_SKIP); + break; + case TEST_PHASE_BEFORE: + case TEST_PHASE_TEST: + __ztest_set_test_result(ZTEST_RESULT_SKIP); + test_finalize(); + break; + default: + PRINT(" ERROR: cannot skip in test phase '%s()', bailing\n", + get_friendly_phase_name(cur_phase)); + test_status = ZTEST_STATUS_CRITICAL_ERROR; + break; + } } -static void init_testing(void) +void ztest_test_expect_fail(void) { - k_object_access_all_grant(&ztest_thread); + failed_expectation = true; } -static void test_cb(void *a, void *dummy2, void *dummy) +void ztest_simple_1cpu_before(void *data) { - struct unit_test *test = (struct unit_test *)a; + ARG_UNUSED(data); + z_test_1cpu_start(); +} - ARG_UNUSED(dummy2); - ARG_UNUSED(dummy); +void ztest_simple_1cpu_after(void *data) +{ + ARG_UNUSED(data); + z_test_1cpu_stop(); +} - test_result = 1; - run_test_functions(test); - test_result = 0; +static void test_cb(void *a, void *b, void *c) +{ + struct ztest_suite_node *suite = a; + struct ztest_unit_test *test = b; + const bool config_user_mode = FIELD_GET(K_USER, test->thread_options) != 0; + + if (!IS_ENABLED(CONFIG_USERSPACE) || !k_is_user_context()) { + __ztest_set_test_result(ZTEST_RESULT_PENDING); + run_test_rules(/*is_before=*/true, test, /*data=*/c); + if (suite->before) { + suite->before(/*data=*/c); + } + if (IS_ENABLED(CONFIG_USERSPACE) && config_user_mode) { + k_thread_user_mode_enter(test_cb, a, b, c); + } + } + run_test_functions(suite, test, c); + __ztest_set_test_result(ZTEST_RESULT_PASS); } -static int run_test(struct unit_test *test) +static int run_test(struct ztest_suite_node *suite, struct ztest_unit_test *test, void *data) { int ret = TC_PASS; +#if CONFIG_ZTEST_TEST_DELAY_MS > 0 + k_busy_wait(CONFIG_ZTEST_TEST_DELAY_MS * USEC_PER_MSEC); +#endif TC_START(test->name); - get_start_time_cyc(); + __ztest_set_test_phase(TEST_PHASE_BEFORE); + + /* If the suite's setup function marked us as skipped, don't bother + * running the tests. + */ if (IS_ENABLED(CONFIG_MULTITHREADING)) { + get_start_time_cyc(); k_thread_create(&ztest_thread, ztest_thread_stack, K_THREAD_STACK_SIZEOF(ztest_thread_stack), - (k_thread_entry_t) test_cb, (struct unit_test *)test, - NULL, NULL, CONFIG_ZTEST_THREAD_PRIORITY, - test->thread_options | K_INHERIT_PERMS, - K_FOREVER); + test_cb, suite, test, data, + CONFIG_ZTEST_THREAD_PRIORITY, + K_INHERIT_PERMS, K_FOREVER); - k_thread_access_grant(&ztest_thread, test); + k_thread_access_grant(&ztest_thread, suite, test, suite->stats); if (test->name != NULL) { k_thread_name_set(&ztest_thread, test->name); } - k_thread_start(&ztest_thread); - k_thread_join(&ztest_thread, K_FOREVER); + /* Only start the thread if we're not skipping the suite */ + if (test_result != ZTEST_RESULT_SUITE_SKIP && + test_result != ZTEST_RESULT_SUITE_FAIL) { + k_thread_start(&ztest_thread); + k_thread_join(&ztest_thread, K_FOREVER); + } + } else if (test_result != ZTEST_RESULT_SUITE_SKIP && + test_result != ZTEST_RESULT_SUITE_FAIL) { + __ztest_set_test_result(ZTEST_RESULT_PENDING); + get_start_time_cyc(); + run_test_rules(/*is_before=*/true, test, data); + if (suite->before) { + suite->before(data); + } + run_test_functions(suite, test, data); + } - } else { - test_result = 1; - run_test_functions(test); + __ztest_set_test_phase(TEST_PHASE_AFTER); + if (suite->after != NULL) { + suite->after(data); } + run_test_rules(/*is_before=*/false, test, data); + get_test_duration_ms(); + if (tc_spend_time > test->stats->duration_worst_ms) { + test->stats->duration_worst_ms = tc_spend_time; + } - phase = TEST_PHASE_TEARDOWN; - test->teardown(); - phase = TEST_PHASE_FRAMEWORK; + __ztest_set_test_phase(TEST_PHASE_FRAMEWORK); /* Flush all logs in case deferred mode and default logging thread are used. */ while (IS_ENABLED(CONFIG_TEST_LOGGING_FLUSH_AFTER_TEST) && - IS_ENABLED(CONFIG_LOG_PROCESS_THREAD) && - log_data_pending()) { + IS_ENABLED(CONFIG_LOG_PROCESS_THREAD) && log_data_pending()) { k_msleep(100); } - if (test_result == -1) { + if (test_result == ZTEST_RESULT_FAIL || test_result == ZTEST_RESULT_SUITE_FAIL || + failed_expectation) { ret = TC_FAIL; + failed_expectation = false; + } else if (test_result == ZTEST_RESULT_SKIP || test_result == ZTEST_RESULT_SUITE_SKIP) { + ret = TC_SKIP; } - if (!test_result || !FAIL_FAST) { + if (test_result == ZTEST_RESULT_PASS || !FAIL_FAST) { ret |= cleanup_test(test); } - get_test_duration_ms(); - if (test_result == -2) { - Z_TC_END_RESULT(TC_SKIP, test->name); - } else { - Z_TC_END_RESULT(ret, test->name); + ret = get_final_test_result(test, ret); + Z_TC_END_RESULT(ret, test->name); + if (ret == TC_SKIP && current_test_failed_assumption) { + test_status = 1; } return ret; @@ -421,63 +626,330 @@ static int run_test(struct unit_test *test) #endif /* !KERNEL */ -int z_ztest_run_test_suite(const char *name, struct unit_test *suite) +static struct ztest_suite_node *ztest_find_test_suite(const char *name) +{ + struct ztest_suite_node *node; + + for (node = _ztest_suite_node_list_start; node < _ztest_suite_node_list_end; ++node) { + if (strcmp(name, node->name) == 0) { + return node; + } + } + + return NULL; +} + +struct ztest_unit_test *z_ztest_get_next_test(const char *suite, struct ztest_unit_test *prev) +{ + struct ztest_unit_test *test = (prev == NULL) ? _ztest_unit_test_list_start : prev + 1; + + for (; test < _ztest_unit_test_list_end; ++test) { + if (strcmp(suite, test->test_suite_name) == 0) { + return test; + } + } + return NULL; +} + +#ifdef CONFIG_ZTEST_SHUFFLE +static void z_ztest_shuffle(void *dest[], intptr_t start, size_t num_items, size_t element_size) +{ + void *tmp; + + /* Initialize dest array */ + for (size_t i = 0; i < num_items; ++i) { + dest[i] = (void *)(start + (i * element_size)); + } + + /* Shuffle dest array */ + for (size_t i = num_items - 1; i > 0; i--) { + int j = sys_rand32_get() % (i + 1); + + if (i != j) { + tmp = dest[j]; + dest[j] = dest[i]; + dest[i] = tmp; + } + } +} +#endif /* CONFIG_ZTEST_SHUFFLE */ + +static int z_ztest_run_test_suite_ptr(struct ztest_suite_node *suite) { + struct ztest_unit_test *test = NULL; + void *data = NULL; int fail = 0; + int tc_result = TC_PASS; - if (test_status < 0) { + if (FAIL_FAST && test_status != ZTEST_STATUS_OK) { return test_status; } - init_testing(); + if (suite == NULL) { + test_status = ZTEST_STATUS_CRITICAL_ERROR; + return -1; + } + +#ifndef KERNEL + if (setjmp(stack_fail)) { + PRINT("TESTSUITE crashed.\n"); + test_status = ZTEST_STATUS_CRITICAL_ERROR; + end_report(); + exit(1); + } +#else + k_object_access_all_grant(&ztest_thread); +#endif - TC_SUITE_START(name); - while (suite->test) { - fail += run_test(suite); - suite++; + TC_SUITE_START(suite->name); + current_test_failed_assumption = false; + __ztest_set_test_result(ZTEST_RESULT_PENDING); + __ztest_set_test_phase(TEST_PHASE_SETUP); +#ifndef KERNEL + if (setjmp(test_suite_fail)) { + __ztest_set_test_result(ZTEST_RESULT_SUITE_FAIL); + } +#endif + if (test_result != ZTEST_RESULT_SUITE_FAIL && suite->setup != NULL) { + data = suite->setup(); + } - if (fail && FAIL_FAST) { - break; + for (int i = 0; i < NUM_ITER_PER_TEST; i++) { + fail = 0; + +#ifdef CONFIG_ZTEST_SHUFFLE + struct ztest_unit_test *tests_to_run[ZTEST_TEST_COUNT]; + + memset(tests_to_run, 0, ZTEST_TEST_COUNT * sizeof(struct ztest_unit_test *)); + z_ztest_shuffle((void **)tests_to_run, (intptr_t)_ztest_unit_test_list_start, + ZTEST_TEST_COUNT, sizeof(struct ztest_unit_test)); + for (size_t j = 0; j < ZTEST_TEST_COUNT; ++j) { + test = tests_to_run[j]; + /* Make sure that the test belongs to this suite */ + if (strcmp(suite->name, test->test_suite_name) != 0) { + continue; + } + if (ztest_api.should_test_run(suite->name, test->name)) { + test->stats->run_count++; + tc_result = run_test(suite, test, data); + if (tc_result == TC_PASS) { + test->stats->pass_count++; + } else if (tc_result == TC_SKIP) { + test->stats->skip_count++; + } else if (tc_result == TC_FAIL) { + test->stats->fail_count++; + } + if (tc_result == TC_FAIL) { + fail++; + } + } + + if ((fail && FAIL_FAST) || test_status == ZTEST_STATUS_CRITICAL_ERROR) { + break; + } + } +#else + while (((test = z_ztest_get_next_test(suite->name, test)) != NULL)) { + if (ztest_api.should_test_run(suite->name, test->name)) { + test->stats->run_count++; + tc_result = run_test(suite, test, data); + if (tc_result == TC_PASS) { + test->stats->pass_count++; + } else if (tc_result == TC_SKIP) { + test->stats->skip_count++; + } else if (tc_result == TC_FAIL) { + test->stats->fail_count++; + } + + if (tc_result == TC_FAIL) { + fail++; + } + } + + if ((fail && FAIL_FAST) || test_status == ZTEST_STATUS_CRITICAL_ERROR) { + break; + } + } +#endif + + if (test_status == ZTEST_STATUS_OK && fail != 0) { + test_status = ZTEST_STATUS_HAS_FAILURE; } } - TC_SUITE_END(name, (fail > 0 ? TC_FAIL : TC_PASS)); - test_status = (test_status || fail) ? 1 : 0; + TC_SUITE_END(suite->name, (fail > 0 ? TC_FAIL : TC_PASS)); + __ztest_set_test_phase(TEST_PHASE_TEARDOWN); + if (suite->teardown != NULL) { + suite->teardown(data); + } return fail; } -void end_report(void) +int z_ztest_run_test_suite(const char *name) { - if (test_status) { - TC_END_REPORT(TC_FAIL); - } else { - TC_END_REPORT(TC_PASS); - } + return z_ztest_run_test_suite_ptr(ztest_find_test_suite(name)); } #ifdef CONFIG_USERSPACE K_APPMEM_PARTITION_DEFINE(ztest_mem_partition); #endif -int ztest_run_registered_test_suites(const void *state) +static void __ztest_init_unit_test_result_for_suite(struct ztest_suite_node *suite) { - struct ztest_suite_node *ptr; - int count = 0; + struct ztest_unit_test *test = NULL; + + while (((test = z_ztest_get_next_test(suite->name, test)) != NULL)) { + test->stats->run_count = 0; + test->stats->skip_count = 0; + test->stats->fail_count = 0; + test->stats->pass_count = 0; + test->stats->duration_worst_ms = 0; + } +} + +static void flush_log(void) +{ + if (IS_ENABLED(CONFIG_LOG_PROCESS_THREAD)) { + while (log_data_pending()) { + k_sleep(K_MSEC(10)); + } + k_sleep(K_MSEC(10)); + } else { + while (LOG_PROCESS()) { + } + } +} - for (ptr = _ztest_suite_node_list_start; ptr < _ztest_suite_node_list_end; ++ptr) { - struct ztest_suite_stats *stats = ptr->stats; - bool should_run = true; +/* Show one line summary for a test suite. + */ +static void __ztest_show_suite_summary_oneline(struct ztest_suite_node *suite) +{ + int distinct_pass = 0, distinct_fail = 0, distinct_skip = 0, distinct_total = 0; + int effective_total = 0; + int expanded_pass = 0, expanded_passrate = 0; + int passrate_major = 0, passrate_minor = 0, passrate_tail = 0; + int suite_result = TC_PASS; + + struct ztest_unit_test *test = NULL; + unsigned int suite_duration_worst_ms = 0; + + /** summary of disctinct run */ + while (((test = z_ztest_get_next_test(suite->name, test)) != NULL)) { + distinct_total++; + suite_duration_worst_ms += test->stats->duration_worst_ms; + if (test->stats->skip_count == test->stats->run_count) { + distinct_skip++; + } else if (test->stats->pass_count == test->stats->run_count) { + distinct_pass++; + } else { + distinct_fail++; + } + } - if (ptr->predicate != NULL) { - should_run = ptr->predicate(state); - } else { - /* If pragma is NULL, only run this test once. */ - should_run = stats->run_count == 0; + if (distinct_skip == distinct_total) { + suite_result = TC_SKIP; + passrate_major = passrate_minor = 0; + } else { + suite_result = (distinct_fail > 0) ? TC_FAIL : TC_PASS; + effective_total = distinct_total - distinct_skip; + expanded_pass = distinct_pass * 100000; + expanded_passrate = expanded_pass / effective_total; + passrate_major = expanded_passrate / 1000; + passrate_minor = (expanded_passrate - passrate_major * 1000) / 10; + passrate_tail = expanded_passrate - passrate_major * 1000 - passrate_minor * 10; + if (passrate_tail >= 5) { /* rounding */ + passrate_minor++; } + } - if (should_run) { - int fail = z_ztest_run_test_suite(ptr->name, ptr->suite); + TC_SUMMARY_PRINT("SUITE %s - %3d.%02d%% [%s]: pass = %d, fail = %d, " + "skip = %d, total = %d duration = %u.%03u seconds\n", + TC_RESULT_TO_STR(suite_result), + passrate_major, passrate_minor, + suite->name, distinct_pass, distinct_fail, + distinct_skip, distinct_total, + suite_duration_worst_ms / 1000, suite_duration_worst_ms % 1000); + flush_log(); +} + +static void __ztest_show_suite_summary_verbose(struct ztest_suite_node *suite) +{ + struct ztest_unit_test *test = NULL; + int tc_result = TC_PASS; + int flush_frequency = 0; + + if (IS_ENABLED(CONFIG_ZTEST_VERBOSE_SUMMARY) == 0) { + return; + } + + while (((test = z_ztest_get_next_test(suite->name, test)) != NULL)) { + if (test->stats->skip_count == test->stats->run_count) { + tc_result = TC_SKIP; + } else if (test->stats->pass_count == test->stats->run_count) { + tc_result = TC_PASS; + } else if (test->stats->pass_count == 0) { + tc_result = TC_FAIL; + } else { + tc_result = TC_FLAKY; + } + + if (tc_result == TC_FLAKY) { + TC_SUMMARY_PRINT(" - %s - [%s.%s] - (Failed %d of %d attempts)" + " - duration = %u.%03u seconds\n", + TC_RESULT_TO_STR(tc_result), + test->test_suite_name, test->name, + test->stats->run_count - test->stats->pass_count, + test->stats->run_count, + test->stats->duration_worst_ms / 1000, + test->stats->duration_worst_ms % 1000); + } else { + TC_SUMMARY_PRINT(" - %s - [%s.%s] duration = %u.%03u seconds\n", + TC_RESULT_TO_STR(tc_result), + test->test_suite_name, test->name, + test->stats->duration_worst_ms / 1000, + test->stats->duration_worst_ms % 1000); + } + + if (flush_frequency % 3 == 0) { + /** Reduce the flush frequencey a bit to speed up the output */ + flush_log(); + } + flush_frequency++; + } + TC_SUMMARY_PRINT("\n"); + flush_log(); +} + +static void __ztest_show_suite_summary(void) +{ + if (IS_ENABLED(CONFIG_ZTEST_SUMMARY) == 0) { + return; + } + /* Flush the log a lot to ensure that no summary content + * is dropped if it goes through the logging subsystem. + */ + flush_log(); + TC_SUMMARY_PRINT("\n------ TESTSUITE SUMMARY START ------\n\n"); + flush_log(); + for (struct ztest_suite_node *ptr = _ztest_suite_node_list_start; + ptr < _ztest_suite_node_list_end; ++ptr) { + + __ztest_show_suite_summary_oneline(ptr); + __ztest_show_suite_summary_verbose(ptr); + } + TC_SUMMARY_PRINT("------ TESTSUITE SUMMARY END ------\n\n"); + flush_log(); +} + +static int __ztest_run_test_suite(struct ztest_suite_node *ptr, const void *state) +{ + struct ztest_suite_stats *stats = ptr->stats; + int count = 0; + + for (int i = 0; i < NUM_ITER_PER_SUITE; i++) { + if (ztest_api.should_suite_run(state, ptr)) { + int fail = z_ztest_run_test_suite_ptr(ptr); count++; stats->run_count++; @@ -490,27 +962,121 @@ int ztest_run_registered_test_suites(const void *state) return count; } -void ztest_verify_all_registered_test_suites_ran(void) +int z_impl_ztest_run_test_suites(const void *state) +{ + int count = 0; + + if (test_status == ZTEST_STATUS_CRITICAL_ERROR) { + return count; + } + +#ifdef CONFIG_ZTEST_SHUFFLE + struct ztest_suite_node *suites_to_run[ZTEST_SUITE_COUNT]; + + memset(suites_to_run, 0, ZTEST_SUITE_COUNT * sizeof(struct ztest_suite_node *)); + z_ztest_shuffle((void **)suites_to_run, (intptr_t)_ztest_suite_node_list_start, + ZTEST_SUITE_COUNT, sizeof(struct ztest_suite_node)); + for (size_t i = 0; i < ZTEST_SUITE_COUNT; ++i) { + __ztest_init_unit_test_result_for_suite(suites_to_run[i]); + } + for (size_t i = 0; i < ZTEST_SUITE_COUNT; ++i) { + count += __ztest_run_test_suite(suites_to_run[i], state); + /* Stop running tests if we have a critical error or if we have a failure and + * FAIL_FAST was set + */ + if (test_status == ZTEST_STATUS_CRITICAL_ERROR || + (test_status == ZTEST_STATUS_HAS_FAILURE && FAIL_FAST)) { + break; + } + } +#else + for (struct ztest_suite_node *ptr = _ztest_suite_node_list_start; + ptr < _ztest_suite_node_list_end; ++ptr) { + __ztest_init_unit_test_result_for_suite(ptr); + count += __ztest_run_test_suite(ptr, state); + /* Stop running tests if we have a critical error or if we have a failure and + * FAIL_FAST was set + */ + if (test_status == ZTEST_STATUS_CRITICAL_ERROR || + (test_status == ZTEST_STATUS_HAS_FAILURE && FAIL_FAST)) { + break; + } + } +#endif + + return count; +} + +void z_impl___ztest_set_test_result(enum ztest_result new_result) +{ + test_result = new_result; +} + +void z_impl___ztest_set_test_phase(enum ztest_phase new_phase) +{ + cur_phase = new_phase; +} + +#ifdef CONFIG_USERSPACE +void z_vrfy___ztest_set_test_result(enum ztest_result new_result) +{ + z_impl___ztest_set_test_result(new_result); +} +#include + +void z_vrfy___ztest_set_test_phase(enum ztest_phase new_phase) +{ + z_impl___ztest_set_test_phase(new_phase); +} +#include +#endif /* CONFIG_USERSPACE */ + +void ztest_verify_all_test_suites_ran(void) { bool all_tests_run = true; - struct ztest_suite_node *ptr; + struct ztest_suite_node *suite; + struct ztest_unit_test *test; + + if (IS_ENABLED(CONFIG_ZTEST_VERIFY_RUN_ALL)) { + for (suite = _ztest_suite_node_list_start; suite < _ztest_suite_node_list_end; + ++suite) { + if (suite->stats->run_count < 1) { + PRINT("ERROR: Test suite '%s' did not run.\n", suite->name); + all_tests_run = false; + } + } - for (ptr = _ztest_suite_node_list_start; ptr < _ztest_suite_node_list_end; ++ptr) { - if (ptr->stats->run_count < 1) { - PRINT("ERROR: Test '%s' did not run.\n", ptr->name); - all_tests_run = false; + for (test = _ztest_unit_test_list_start; test < _ztest_unit_test_list_end; ++test) { + suite = ztest_find_test_suite(test->test_suite_name); + if (suite == NULL) { + PRINT("ERROR: Test '%s' assigned to test suite '%s' which doesn't " + "exist\n", + test->name, test->test_suite_name); + all_tests_run = false; + } + } + + if (!all_tests_run) { + test_status = ZTEST_STATUS_HAS_FAILURE; } } - if (!all_tests_run) { - test_status = 1; + for (test = _ztest_unit_test_list_start; test < _ztest_unit_test_list_end; ++test) { + if (test->stats->fail_count + test->stats->pass_count + test->stats->skip_count != + test->stats->run_count) { + PRINT("Bad stats for %s.%s\n", test->test_suite_name, test->name); + test_status = 1; + } } } +void ztest_run_all(const void *state) { ztest_api.run_all(state); } + void __weak test_main(void) { - ztest_run_registered_test_suites(NULL); - ztest_verify_all_registered_test_suites_ran(); + ztest_run_all(NULL); + + ztest_verify_all_test_suites_ran(); } #ifndef KERNEL @@ -519,45 +1085,41 @@ int main(void) z_init_mock(); test_main(); end_report(); +#ifdef CONFIG_ZTEST_NO_YIELD + /* + * Rather than yielding to idle thread, keep the part awake so debugger can + * still access it, since some SOCs cannot be debugged in low power states. + */ + uint32_t key = irq_lock(); + while (1) { + ; /* Spin */ + } + irq_unlock(key); +#endif return test_status; } #else int main(void) { #ifdef CONFIG_USERSPACE - int ret; - /* Partition containing globals tagged with ZTEST_DMEM and ZTEST_BMEM * macros. Any variables that user code may reference need to be * placed in this partition if no other memory domain configuration * is made. */ - ret = k_mem_domain_add_partition(&k_mem_domain_default, - &ztest_mem_partition); - if (ret != 0) { - PRINT("ERROR: failed to add ztest_mem_partition to mem domain (%d)\n", - ret); - k_oops(); - } + k_mem_domain_add_partition(&k_mem_domain_default, &ztest_mem_partition); #ifdef Z_MALLOC_PARTITION_EXISTS /* Allow access to malloc() memory */ - if (z_malloc_partition.size != 0) { - ret = k_mem_domain_add_partition(&k_mem_domain_default, - &z_malloc_partition); - if (ret != 0) { - PRINT("ERROR: failed to add z_malloc_partition" - " to mem domain (%d)\n", - ret); - k_oops(); - } - } + k_mem_domain_add_partition(&k_mem_domain_default, &z_malloc_partition); #endif #endif /* CONFIG_USERSPACE */ z_init_mock(); test_main(); end_report(); + flush_log(); + LOG_PANIC(); if (IS_ENABLED(CONFIG_ZTEST_RETEST_IF_PASSED)) { static __noinit struct { uint32_t magic; @@ -571,8 +1133,7 @@ int main(void) } state.boots += 1; if (test_status == 0) { - PRINT("Reset board #%u to test again\n", - state.boots); + PRINT("Reset board #%u to test again\n", state.boots); k_msleep(10); sys_reboot(SYS_REBOOT_COLD); } else { diff --git a/subsys/testsuite/ztest/src/ztest_error_hook.c b/subsys/testsuite/ztest/src/ztest_error_hook.c index e0a92077b0e..64dede71533 100644 --- a/subsys/testsuite/ztest/src/ztest_error_hook.c +++ b/subsys/testsuite/ztest/src/ztest_error_hook.c @@ -106,6 +106,8 @@ static inline void z_vrfy_ztest_set_assert_valid(bool valid) __weak void ztest_post_assert_fail_hook(void) { k_thread_abort(k_current_get()); + + CODE_UNREACHABLE; } #ifdef CONFIG_ASSERT_NO_FILE_INFO diff --git a/subsys/testsuite/ztest/src/ztest_new.c b/subsys/testsuite/ztest/src/ztest_new.c index 0772383bc0a..d49a1ef9c11 100644 --- a/subsys/testsuite/ztest/src/ztest_new.c +++ b/subsys/testsuite/ztest/src/ztest_new.c @@ -22,7 +22,7 @@ static bool failed_expectation; #include #include -#include +#include #define NUM_ITER_PER_SUITE CONFIG_ZTEST_SHUFFLE_SUITE_REPEAT_COUNT #define NUM_ITER_PER_TEST CONFIG_ZTEST_SHUFFLE_TEST_REPEAT_COUNT #else @@ -113,6 +113,7 @@ static void cpu_hold(void *arg1, void *arg2, void *arg3) ARG_UNUSED(arg1); ARG_UNUSED(arg2); ARG_UNUSED(arg3); + unsigned int key = arch_irq_lock(); uint32_t dt, start_ms = k_uptime_get_32(); @@ -159,7 +160,7 @@ void z_impl_z_test_1cpu_start(void) */ for (int i = 0; i < num_cpus - 1; i++) { k_thread_create(&cpuhold_threads[i], cpuhold_stacks[i], CPUHOLD_STACK_SZ, - (k_thread_entry_t)cpu_hold, NULL, NULL, NULL, K_HIGHEST_THREAD_PRIO, + cpu_hold, NULL, NULL, NULL, K_HIGHEST_THREAD_PRIO, 0, K_NO_WAIT); if (IS_ENABLED(CONFIG_THREAD_NAME)) { snprintk(tname, CONFIG_THREAD_MAX_NAME_LEN, "cpuhold%02d", i); @@ -439,7 +440,12 @@ static void test_finalize(void) { if (IS_ENABLED(CONFIG_MULTITHREADING)) { k_thread_abort(&ztest_thread); + if (k_is_in_isr()) { + return; + } + k_thread_abort(k_current_get()); + CODE_UNREACHABLE; } } @@ -553,7 +559,7 @@ static int run_test(struct ztest_suite_node *suite, struct ztest_unit_test *test get_start_time_cyc(); k_thread_create(&ztest_thread, ztest_thread_stack, K_THREAD_STACK_SIZEOF(ztest_thread_stack), - (k_thread_entry_t)test_cb, suite, test, data, + test_cb, suite, test, data, CONFIG_ZTEST_THREAD_PRIORITY, K_INHERIT_PERMS, K_FOREVER); @@ -1079,7 +1085,18 @@ int main(void) z_init_mock(); test_main(); end_report(); +#ifdef CONFIG_ZTEST_NO_YIELD + /* + * Rather than yielding to idle thread, keep the part awake so debugger can + * still access it, since some SOCs cannot be debugged in low power states. + */ + uint32_t key = irq_lock(); + while (1) { + ; /* Spin */ + } + irq_unlock(key); +#endif return test_status; } #else @@ -1124,6 +1141,18 @@ int main(void) state.boots = 0; } } +#ifdef CONFIG_ZTEST_NO_YIELD + /* + * Rather than yielding to idle thread, keep the part awake so debugger can + * still access it, since some SOCs cannot be debugged in low power states. + */ + uint32_t key = irq_lock(); + + while (1) { + ; /* Spin */ + } + irq_unlock(key); +#endif return 0; } #endif diff --git a/subsys/testsuite/ztest/src/ztest_posix.c b/subsys/testsuite/ztest/src/ztest_posix.c index fbfb3ed4137..d2c1857c04c 100644 --- a/subsys/testsuite/ztest/src/ztest_posix.c +++ b/subsys/testsuite/ztest/src/ztest_posix.c @@ -9,7 +9,7 @@ #include "cmdline.h" /* native_posix command line options header */ #include "soc.h" #include -#include +#include #include "nsi_host_trampolines.h" static const char *test_args; @@ -47,7 +47,7 @@ NATIVE_TASK(add_test_filter_option, PRE_BOOT_1, 10); * This makes assertions a lot more readable, and sometimes they fit on one * line. * - * Overrides implementation in ztest_new.c + * Overrides implementation in ztest.c * * @param file Filename to check * @returns Shortened filename, or @file if it could not be shortened @@ -176,7 +176,7 @@ static bool z_ztest_testargs_contains(const char *suite_name, const char *test_n * @brief Determines if the test case should run based on test cases listed * in the command line argument. * - * Overrides implementation in ztest_new.c + * Overrides implementation in ztest.c * * @param suite - name of test suite * @param test - name of unit test @@ -197,7 +197,7 @@ bool z_ztest_should_test_run(const char *suite, const char *test) * @brief Determines if the test suite should run based on test cases listed * in the command line argument. * - * Overrides implementation in ztest_new.c + * Overrides implementation in ztest.c * * @param state The current state of the machine as it relates to the test * executable. diff --git a/subsys/testsuite/ztest/src/ztress.c b/subsys/testsuite/ztest/src/ztress.c index a0515558e8a..0ca15b0fc96 100644 --- a/subsys/testsuite/ztest/src/ztress.c +++ b/subsys/testsuite/ztest/src/ztress.c @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include /* Flag set at startup which determines if stress test can run on this platform. diff --git a/subsys/tracing/Kconfig b/subsys/tracing/Kconfig index dd36635244d..d7aa7b12e44 100644 --- a/subsys/tracing/Kconfig +++ b/subsys/tracing/Kconfig @@ -37,7 +37,7 @@ config PERCEPIO_TRACERECORDER select THREAD_NAME select INIT_STACKS select THREAD_MONITOR - depends on ZEPHYR_TRACERECORDER_MODULE + depends on ZEPHYR_PERCEPIO_MODULE config SEGGER_SYSTEMVIEW bool "Segger SystemView support" @@ -308,6 +308,18 @@ config TRACING_EVENT help Enable tracing Events. +config TRACING_POLLING + bool "Tracing Polling" + default y + help + Enable tracing Work Polling and Polling API. + +config TRACING_PM + bool "Tracing Power Management" + default y + help + Enable tracing Power Management. + endmenu # Tracing Configuration endif diff --git a/subsys/tracing/ctf/ctf_top.c b/subsys/tracing/ctf/ctf_top.c index 38cbb30ffec..64708c075f4 100644 --- a/subsys/tracing/ctf/ctf_top.c +++ b/subsys/tracing/ctf/ctf_top.c @@ -27,7 +27,7 @@ void sys_trace_k_thread_switched_out(void) ctf_bounded_string_t name = { "unknown" }; struct k_thread *thread; - thread = z_current_get(); + thread = k_sched_current_thread_query(); _get_thread_name(thread, &name); ctf_top_thread_switched_out((uint32_t)(uintptr_t)thread, name); @@ -38,7 +38,7 @@ void sys_trace_k_thread_switched_in(void) struct k_thread *thread; ctf_bounded_string_t name = { "unknown" }; - thread = z_current_get(); + thread = k_sched_current_thread_query(); _get_thread_name(thread, &name); ctf_top_thread_switched_in((uint32_t)(uintptr_t)thread, name); diff --git a/subsys/tracing/ctf/tracing_ctf.h b/subsys/tracing/ctf/tracing_ctf.h index b278c9dc050..6b1b03e97d0 100644 --- a/subsys/tracing/ctf/tracing_ctf.h +++ b/subsys/tracing/ctf/tracing_ctf.h @@ -295,8 +295,6 @@ extern "C" { #define sys_port_trace_k_pipe_get_enter(pipe, timeout) #define sys_port_trace_k_pipe_get_blocking(pipe, timeout) #define sys_port_trace_k_pipe_get_exit(pipe, timeout, ret) -#define sys_port_trace_k_pipe_block_put_enter(pipe, sem) -#define sys_port_trace_k_pipe_block_put_exit(pipe, sem) #define sys_port_trace_k_heap_init(heap) #define sys_port_trace_k_heap_aligned_alloc_enter(heap, timeout) diff --git a/subsys/tracing/sysview/SYSVIEW_Zephyr.txt b/subsys/tracing/sysview/SYSVIEW_Zephyr.txt index b6dcd8073a2..dfad10e404a 100644 --- a/subsys/tracing/sysview/SYSVIEW_Zephyr.txt +++ b/subsys/tracing/sysview/SYSVIEW_Zephyr.txt @@ -79,7 +79,6 @@ TaskState 0xBF 1=dummy, 2=Waiting, 4=New, 8=Terminated, 16=Suspended, 32=Termina 72 k_pipe_cleanup pipe=%I | Returns %ErrCodePosix 73 k_pipe_put pipe=%I, data=%p, bytes_to_write=%u, bytes_written=%u, min_xfer=%u, Timeout=%TimeOut | Returns %ErrCodePosix 74 k_pipe_get pipe=%I, data=%p, bytes_to_read=%u, bytes_read=%u, min_xfer=%u, Timeout=%TimeOut | Returns %ErrCodePosix -75 k_pipe_block_put pipe=%I, block=%p, bytes_to_write=%u, sem=%I | Returns (void)(%ErrCodePosix) 76 k_heap_init heap=%I, mem=%p, bytes=%u 77 k_heap_alloc heap=%I, bytes=%u, Timeout=%TimeOut | Returns %p diff --git a/subsys/tracing/sysview/tracing_sysview.h b/subsys/tracing/sysview/tracing_sysview.h index 7578d6a750c..105cfb1a3ee 100644 --- a/subsys/tracing/sysview/tracing_sysview.h +++ b/subsys/tracing/sysview/tracing_sysview.h @@ -530,8 +530,6 @@ void sys_trace_thread_info(struct k_thread *thread); #define sys_port_trace_k_pipe_get_enter(pipe, timeout) #define sys_port_trace_k_pipe_get_blocking(pipe, timeout) #define sys_port_trace_k_pipe_get_exit(pipe, timeout, ret) -#define sys_port_trace_k_pipe_block_put_enter(pipe, sem) -#define sys_port_trace_k_pipe_block_put_exit(pipe, sem) #define sys_port_trace_k_event_init(event) #define sys_port_trace_k_event_post_enter(event, events, events_mask) diff --git a/subsys/tracing/test/tracing_test.h b/subsys/tracing/test/tracing_test.h index 06ca3e56cd5..6cf3ee6e583 100644 --- a/subsys/tracing/test/tracing_test.h +++ b/subsys/tracing/test/tracing_test.h @@ -366,10 +366,6 @@ sys_trace_k_pipe_get_blocking(pipe, data, bytes_to_read, bytes_read, min_xfer, timeout) #define sys_port_trace_k_pipe_get_exit(pipe, timeout, ret) \ sys_trace_k_pipe_get_exit(pipe, data, bytes_to_read, bytes_read, min_xfer, timeout, ret) -#define sys_port_trace_k_pipe_block_put_enter(pipe, sem) \ - sys_trace_k_pipe_block_put_enter(pipe, block, bytes_to_write, sem) -#define sys_port_trace_k_pipe_block_put_exit(pipe, sem) \ - sys_trace_k_pipe_block_put_exit(pipe, block, bytes_to_write, sem) #define sys_port_trace_k_heap_init(h) sys_trace_k_heap_init(h, mem, bytes) #define sys_port_trace_k_heap_aligned_alloc_enter(h, timeout) \ @@ -634,10 +630,6 @@ void sys_trace_k_pipe_get_blocking(struct k_pipe *pipe, void *data, size_t bytes size_t *bytes_read, size_t min_xfer, k_timeout_t timeout); void sys_trace_k_pipe_get_exit(struct k_pipe *pipe, void *data, size_t bytes_to_read, size_t *bytes_read, size_t min_xfer, k_timeout_t timeout, int ret); -void sys_trace_k_pipe_block_put_enter(struct k_pipe *pipe, struct k_mem_block *block, size_t size, - struct k_sem *sem); -void sys_trace_k_pipe_block_put_exit(struct k_pipe *pipe, struct k_mem_block *block, size_t size, - struct k_sem *sem); void sys_trace_k_msgq_init(struct k_msgq *msgq); void sys_trace_k_msgq_alloc_init_enter(struct k_msgq *msgq, size_t msg_size, uint32_t max_msgs); diff --git a/subsys/tracing/user/tracing_user.h b/subsys/tracing/user/tracing_user.h index 747fe875f2b..ddc6668d68a 100644 --- a/subsys/tracing/user/tracing_user.h +++ b/subsys/tracing/user/tracing_user.h @@ -280,8 +280,6 @@ void sys_trace_idle(void); #define sys_port_trace_k_pipe_get_enter(pipe, timeout) #define sys_port_trace_k_pipe_get_blocking(pipe, timeout) #define sys_port_trace_k_pipe_get_exit(pipe, timeout, ret) -#define sys_port_trace_k_pipe_block_put_enter(pipe, sem) -#define sys_port_trace_k_pipe_block_put_exit(pipe, sem) #define sys_port_trace_k_heap_init(heap) #define sys_port_trace_k_heap_aligned_alloc_enter(heap, timeout) diff --git a/subsys/usb/device/Kconfig b/subsys/usb/device/Kconfig index 8907d952d87..1f0a008058e 100644 --- a/subsys/usb/device/Kconfig +++ b/subsys/usb/device/Kconfig @@ -97,7 +97,7 @@ config USB_NUMOF_EP_WRITE_RETRIES config USB_DEVICE_SOF bool "Start of Frame processing in events" - default y if (USB_DEVICE_AUDIO && NRFX_USBD) + default y if (USB_DEVICE_AUDIO && NRF_USBD_COMMON) config USB_DEVICE_BOS bool "USB Binary Device Object Store (BOS)" diff --git a/subsys/usb/device/class/Kconfig.cdc b/subsys/usb/device/class/Kconfig.cdc index 7c748028023..59a72e25b6e 100644 --- a/subsys/usb/device/class/Kconfig.cdc +++ b/subsys/usb/device/class/Kconfig.cdc @@ -37,6 +37,13 @@ config CDC_ACM_BULK_EP_MPS help CDC ACM class bulk endpoints size +config CDC_ACM_TX_DELAY_MS + int + default 100 + help + Time in milliseconds to wait before sending actual payload to host. + This is needed to prevent tty ECHO on Linux. + config CDC_ACM_IAD bool "Force using Interface Association Descriptor" default y diff --git a/subsys/usb/device/class/audio/audio.c b/subsys/usb/device/class/audio/audio.c index dc7e15f08d8..338163940e3 100644 --- a/subsys/usb/device/class/audio/audio.c +++ b/subsys/usb/device/class/audio/audio.c @@ -24,6 +24,12 @@ #include LOG_MODULE_REGISTER(usb_audio, CONFIG_USB_AUDIO_LOG_LEVEL); +struct feature_volume { + int16_t volume_max; + int16_t volume_min; + int16_t volume_res; +}; + /* Device data structure */ struct usb_audio_dev_data { const struct usb_audio_ops *ops; @@ -41,6 +47,9 @@ struct usb_audio_dev_data { /* Not applicable for Headphones, left with 0 */ uint16_t in_frame_size; + /* Not applicable for not support volume feature device */ + struct feature_volume volumes; + bool rx_enable; bool tx_enable; }; @@ -146,11 +155,14 @@ static struct usb_ep_cfg_data dev##_usb_audio_ep_data_##i[] = { \ #define DEFINE_AUDIO_DEV_DATA(dev, i, __out_pool, __in_pool_size) \ static uint8_t dev##_controls_##i[FEATURES_SIZE(dev, i)] = {0};\ - static struct usb_audio_dev_data dev##_audio_dev_data_##i = \ - { .pool = __out_pool, \ - .in_frame_size = __in_pool_size, \ - .controls = {dev##_controls_##i, NULL}, \ - .ch_cnt = {(CH_CNT(dev, i) + 1), 0} \ + static struct usb_audio_dev_data dev##_audio_dev_data_##i = \ + { .pool = __out_pool, \ + .in_frame_size = __in_pool_size, \ + .controls = {dev##_controls_##i, NULL}, \ + .ch_cnt = {(CH_CNT(dev, i) + 1), 0}, \ + .volumes.volume_max = GET_VOLUME(dev, i, volume_max), \ + .volumes.volume_min = GET_VOLUME(dev, i, volume_min), \ + .volumes.volume_res = GET_VOLUME(dev, i, volume_res), \ } #define DEFINE_AUDIO_DEV_DATA_BIDIR(dev, i, __out_pool, __in_pool_size) \ @@ -161,7 +173,10 @@ static struct usb_ep_cfg_data dev##_usb_audio_ep_data_##i[] = { \ .in_frame_size = __in_pool_size, \ .controls = {dev##_controls0_##i, dev##_controls1_##i}, \ .ch_cnt = {(CH_CNT(dev##_MIC, i) + 1), \ - (CH_CNT(dev##_HP, i) + 1)} \ + (CH_CNT(dev##_HP, i) + 1)}, \ + .volumes.volume_max = GET_VOLUME(dev, i, volume_max), \ + .volumes.volume_min = GET_VOLUME(dev, i, volume_min), \ + .volumes.volume_res = GET_VOLUME(dev, i, volume_res), \ } /** @@ -541,6 +556,67 @@ static int handle_fu_mute_req(struct usb_audio_dev_data *audio_dev_data, return -EINVAL; } + +static int handle_fu_volume_req(struct usb_audio_dev_data *audio_dev_data, + struct usb_setup_packet *setup, int32_t *len, uint8_t **data, + struct usb_audio_fu_evt *evt, uint8_t device) +{ + uint8_t ch = (setup->wValue) & 0xFF; + uint8_t ch_cnt = audio_dev_data->ch_cnt[device]; + uint8_t *controls = audio_dev_data->controls[device]; + uint8_t *control_val = &controls[POS(VOLUME, ch, ch_cnt)]; + int16_t target_vol = 0; + int16_t temp_vol = 0; + + if (usb_reqtype_is_to_device(setup)) { + /* Check if *len has valid value */ + if (*len != LEN(1, VOLUME)) { + LOG_ERR("*len: %d, LEN(1, VOLUME): %d", *len, LEN(1, VOLUME)); + return -EINVAL; + } + if (setup->bRequest == USB_AUDIO_SET_CUR) { + target_vol = *((int16_t *)*data); + if (!IN_RANGE(target_vol, audio_dev_data->volumes.volume_min, + audio_dev_data->volumes.volume_max)) { + LOG_ERR("Volume out of range: %d", target_vol); + return -EINVAL; + } + if (target_vol % audio_dev_data->volumes.volume_res != 0) { + target_vol = ROUND_UP(target_vol, + audio_dev_data->volumes.volume_res); + } + evt->val = control_val; + evt->val_len = *len; + *((int16_t *)evt->val) = sys_le16_to_cpu(target_vol); + return 0; + } + } else { + if (setup->bRequest == USB_AUDIO_GET_CUR) { + *len = LEN(ch_cnt, VOLUME); + temp_vol = sys_cpu_to_le16(*(int16_t *)control_val); + memcpy(*data, &temp_vol, *len); + return 0; + } else if (setup->bRequest == USB_AUDIO_GET_MIN) { + *len = sizeof(audio_dev_data->volumes.volume_min); + temp_vol = sys_cpu_to_le16(audio_dev_data->volumes.volume_min); + memcpy(*data, &temp_vol, *len); + return 0; + } else if (setup->bRequest == USB_AUDIO_GET_MAX) { + *len = sizeof(audio_dev_data->volumes.volume_max); + temp_vol = sys_cpu_to_le16(audio_dev_data->volumes.volume_max); + memcpy(*data, &temp_vol, *len); + return 0; + } else if (setup->bRequest == USB_AUDIO_GET_RES) { + *len = sizeof(audio_dev_data->volumes.volume_res); + temp_vol = sys_cpu_to_le16(audio_dev_data->volumes.volume_res); + memcpy(*data, &temp_vol, *len); + return 0; + } + } + + return -EINVAL; +} + /** * @brief Handler for feature unit requests. * @@ -590,6 +666,10 @@ static int handle_feature_unit_req(struct usb_audio_dev_data *audio_dev_data, ret = handle_fu_mute_req(audio_dev_data, pSetup, len, data, &evt, device); break; + case USB_AUDIO_FU_VOLUME_CONTROL: + ret = handle_fu_volume_req(audio_dev_data, pSetup, + len, data, &evt, device); + break; default: return -ENOTSUP; } @@ -931,7 +1011,7 @@ void usb_audio_register(const struct device *dev, &usb_audio_device_init, \ NULL, \ &dev##_audio_dev_data_##i, \ - &dev##_audio_config_##i, APPLICATION, \ + &dev##_audio_config_##i, POST_KERNEL, \ CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ DUMMY_API) diff --git a/subsys/usb/device/class/audio/usb_audio_internal.h b/subsys/usb/device/class/audio/usb_audio_internal.h index c0d5383577d..7a70ae94178 100644 --- a/subsys/usb/device/class/audio/usb_audio_internal.h +++ b/subsys/usb/device/class/audio/usb_audio_internal.h @@ -160,6 +160,11 @@ #define GET_RES_HS_MIC(i) DT_PROP(DT_INST(i, COMPAT_HS), mic_resolution) #define GET_RES(dev, i) GET_RES_##dev(i) +#define GET_VOLUME_HS(i, prop) DT_PROP_OR(DT_INST(i, COMPAT_HS), prop, 0) +#define GET_VOLUME_HP(i, prop) DT_PROP_OR(DT_INST(i, COMPAT_HP), prop, 0) +#define GET_VOLUME_MIC(i, prop) DT_PROP_OR(DT_INST(i, COMPAT_MIC), prop, 0) +#define GET_VOLUME(dev, i, prop) GET_VOLUME_##dev(i, prop) + #define SYNC_TYPE_HP(i) 3 #define SYNC_TYPE_MIC(i) DT_ENUM_IDX(DT_INST(i, COMPAT_MIC), sync_type) #define SYNC_TYPE_HS_HP(i) 3 diff --git a/subsys/usb/device/class/bluetooth.c b/subsys/usb/device/class/bluetooth.c index 776c787120f..63b85238f5a 100644 --- a/subsys/usb/device/class/bluetooth.c +++ b/subsys/usb/device/class/bluetooth.c @@ -122,8 +122,12 @@ static struct usb_ep_cfg_data bluetooth_ep_data[] = { }, }; -static void hci_tx_thread(void) +static void hci_tx_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + LOG_DBG("Start USB Bluetooth thread"); while (true) { @@ -174,8 +178,12 @@ static void hci_tx_thread(void) } } -static void hci_rx_thread(void) +static void hci_rx_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + while (true) { struct net_buf *buf; int err; @@ -467,14 +475,14 @@ static int bluetooth_init(void) k_thread_create(&rx_thread_data, rx_thread_stack, K_KERNEL_STACK_SIZEOF(rx_thread_stack), - (k_thread_entry_t)hci_rx_thread, NULL, NULL, NULL, + hci_rx_thread, NULL, NULL, NULL, K_PRIO_COOP(8), 0, K_NO_WAIT); k_thread_name_set(&rx_thread_data, "usb_bt_rx"); k_thread_create(&tx_thread_data, tx_thread_stack, K_KERNEL_STACK_SIZEOF(tx_thread_stack), - (k_thread_entry_t)hci_tx_thread, NULL, NULL, NULL, + hci_tx_thread, NULL, NULL, NULL, K_PRIO_COOP(8), 0, K_NO_WAIT); k_thread_name_set(&tx_thread_data, "usb_bt_tx"); diff --git a/subsys/usb/device/class/bt_h4.c b/subsys/usb/device/class/bt_h4.c index 7ef72b2759e..d4004a82ac8 100644 --- a/subsys/usb/device/class/bt_h4.c +++ b/subsys/usb/device/class/bt_h4.c @@ -113,8 +113,12 @@ static void bt_h4_read(uint8_t ep, int size, void *priv) USB_MAX_FS_BULK_MPS, USB_TRANS_READ, bt_h4_read, NULL); } -static void hci_tx_thread(void) +static void hci_tx_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + LOG_DBG("Start USB Bluetooth thread"); while (true) { @@ -129,8 +133,12 @@ static void hci_tx_thread(void) } } -static void hci_rx_thread(void) +static void hci_rx_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + while (true) { struct net_buf *buf; @@ -235,14 +243,14 @@ static int bt_h4_init(void) k_thread_create(&rx_thread_data, rx_thread_stack, K_KERNEL_STACK_SIZEOF(rx_thread_stack), - (k_thread_entry_t)hci_rx_thread, NULL, NULL, NULL, + hci_rx_thread, NULL, NULL, NULL, K_PRIO_COOP(8), 0, K_NO_WAIT); k_thread_name_set(&rx_thread_data, "usb_bt_h4_rx"); k_thread_create(&tx_thread_data, tx_thread_stack, K_KERNEL_STACK_SIZEOF(tx_thread_stack), - (k_thread_entry_t)hci_tx_thread, NULL, NULL, NULL, + hci_tx_thread, NULL, NULL, NULL, K_PRIO_COOP(8), 0, K_NO_WAIT); k_thread_name_set(&tx_thread_data, "usb_bt_h4_tx"); diff --git a/subsys/usb/device/class/cdc_acm.c b/subsys/usb/device/class/cdc_acm.c index 874e363711a..fedccf5fdc0 100644 --- a/subsys/usb/device/class/cdc_acm.c +++ b/subsys/usb/device/class/cdc_acm.c @@ -126,6 +126,10 @@ struct cdc_acm_dev_data_t { bool suspended; /* CDC ACM paused flag */ bool rx_paused; + /* When flow_ctrl is set, poll out is blocked when the buffer is full, + * roughly emulating flow control. + */ + bool flow_ctrl; struct usb_dev_data common; }; @@ -219,12 +223,27 @@ static void cdc_acm_write_cb(uint8_t ep, int size, void *priv) k_work_submit_to_queue(&USB_WORK_Q, &dev_data->cb_work); } - if (ring_buf_is_empty(dev_data->tx_ringbuf)) { + /* If size is 0, we want to schedule tx work even if ringbuf is empty to + * ensure that actual payload will not be sent before initialization + * timeout passes. + */ + if (ring_buf_is_empty(dev_data->tx_ringbuf) && size) { LOG_DBG("tx_ringbuf is empty"); return; } - k_work_schedule_for_queue(&USB_WORK_Q, &dev_data->tx_work, K_NO_WAIT); + /* If size is 0, it means that host started polling IN data because it + * has read the ZLP we armed when interface was configured. This ZLP is + * probably the best indication that host has started to read the data. + * Wait initialization timeout before sending actual payload to make it + * possible for application to disable ECHO. The echo is long known + * problem related to the fact that POSIX defaults to ECHO ON and thus + * every application that opens tty device (on Linux) will have ECHO + * enabled in the short window between open() and ioctl() that disables + * the echo (if application wishes to disable the echo). + */ + k_work_schedule_for_queue(&USB_WORK_Q, &dev_data->tx_work, size ? + K_NO_WAIT : K_MSEC(CONFIG_CDC_ACM_TX_DELAY_MS)); } static void tx_work_handler(struct k_work *work) @@ -243,6 +262,10 @@ static void tx_work_handler(struct k_work *work) return; } + if (!dev_data->configured) { + return; + } + len = ring_buf_get_claim(dev_data->tx_ringbuf, &data, CONFIG_USB_CDC_ACM_RINGBUF_SIZE); @@ -301,8 +324,10 @@ static void cdc_acm_read_cb(uint8_t ep, int size, void *priv) } done: - usb_transfer(ep, dev_data->rx_buf, sizeof(dev_data->rx_buf), - USB_TRANS_READ, cdc_acm_read_cb, dev_data); + if (dev_data->configured) { + usb_transfer(ep, dev_data->rx_buf, sizeof(dev_data->rx_buf), + USB_TRANS_READ, cdc_acm_read_cb, dev_data); + } } /** @@ -366,15 +391,13 @@ static void cdc_acm_do_cb(struct cdc_acm_dev_data_t *dev_data, case USB_DC_CONFIGURED: LOG_INF("Device configured"); if (!dev_data->configured) { + dev_data->configured = true; cdc_acm_read_cb(cfg->endpoint[ACM_OUT_EP_IDX].ep_addr, 0, dev_data); - dev_data->configured = true; - } - if (!dev_data->tx_ready) { - dev_data->tx_ready = true; - /* if wait tx irq, invoke callback */ - if (dev_data->cb != NULL && dev_data->tx_irq_ena) { - k_work_submit_to_queue(&USB_WORK_Q, &dev_data->cb_work); + /* Queue ZLP on IN endpoint so we know when host starts polling */ + if (!dev_data->tx_ready) { + usb_transfer(cfg->endpoint[ACM_IN_EP_IDX].ep_addr, NULL, 0, + USB_TRANS_WRITE, cdc_acm_write_cb, dev_data); } } break; @@ -897,17 +920,18 @@ static int cdc_acm_line_ctrl_get(const struct device *dev, static int cdc_acm_configure(const struct device *dev, const struct uart_config *cfg) { - ARG_UNUSED(dev); - ARG_UNUSED(cfg); - /* - * We cannot implement configure API because there is - * no notification of configuration changes provided - * for the Abstract Control Model and the UART controller - * is only emulated. - * However, it allows us to use CDC ACM UART together with - * subsystems like Modbus which require configure API for - * real controllers. - */ + struct cdc_acm_dev_data_t * const dev_data = dev->data; + + switch (cfg->flow_ctrl) { + case UART_CFG_FLOW_CTRL_NONE: + dev_data->flow_ctrl = false; + break; + case UART_CFG_FLOW_CTRL_RTS_CTS: + dev_data->flow_ctrl = true; + break; + default: + return -ENOTSUP; + } return 0; } @@ -967,8 +991,8 @@ static int cdc_acm_config_get(const struct device *dev, break; }; - /* USB CDC has no notion of flow control */ - cfg->flow_ctrl = UART_CFG_FLOW_CTRL_NONE; + cfg->flow_ctrl = dev_data->flow_ctrl ? UART_CFG_FLOW_CTRL_RTS_CTS : + UART_CFG_FLOW_CTRL_NONE; return 0; } @@ -989,32 +1013,31 @@ static int cdc_acm_poll_in(const struct device *dev, unsigned char *c) /* * @brief Output a character in polled mode. * - * The poll function looks similar to cdc_acm_fifo_fill() and - * tries to do the best to mimic behavior of a hardware UART controller - * without flow control. - * This function does not block, if the USB subsystem - * is not ready, no data is transferred to the buffer, that is, c is dropped. - * If the USB subsystem is ready and the buffer is full, the first character - * from the tx_ringbuf is removed to make room for the new character. + * According to the UART API, the implementation of this routine should block + * if the transmitter is full. But blocking when the USB subsystem is not ready + * is considered highly undesirable behavior. Blocking may also be undesirable + * when CDC ACM UART is used as a logging backend. + * + * The behavior of CDC ACM poll out is: + * - Block if the TX ring buffer is full, hw_flow_control property is enabled, + * and called from a non-ISR context. + * - Do not block if the USB subsystem is not ready, poll out implementation + * is called from an ISR context, or hw_flow_control property is disabled. + * */ static void cdc_acm_poll_out(const struct device *dev, unsigned char c) { struct cdc_acm_dev_data_t * const dev_data = dev->data; - if (!dev_data->configured || dev_data->suspended) { - LOG_INF("USB device not ready, drop data"); - return; - } - dev_data->tx_ready = false; - if (!ring_buf_put(dev_data->tx_ringbuf, &c, 1)) { - LOG_INF("Ring buffer full, drain buffer"); - if (!ring_buf_get(dev_data->tx_ringbuf, NULL, 1) || - !ring_buf_put(dev_data->tx_ringbuf, &c, 1)) { - LOG_ERR("Failed to drain buffer"); - return; + while (!ring_buf_put(dev_data->tx_ringbuf, &c, 1)) { + if (k_is_in_isr() || !dev_data->flow_ctrl) { + LOG_INF("Ring buffer full, discard %c", c); + break; } + + k_msleep(1); } /* Schedule with minimal timeout to make it possible to send more than @@ -1181,6 +1204,7 @@ static const struct uart_driver_api cdc_acm_driver_api = { .line_coding = CDC_ACM_DEFAULT_BAUDRATE, \ .rx_ringbuf = &cdc_acm_rx_rb_##x, \ .tx_ringbuf = &cdc_acm_tx_rb_##x, \ + .flow_ctrl = DT_INST_PROP_OR(x, hw_flow_control, false),\ }; #define DT_DRV_COMPAT zephyr_cdc_acm_uart diff --git a/subsys/usb/device/class/hid/Kconfig b/subsys/usb/device/class/hid/Kconfig index 4afcc83368d..c95b8038261 100644 --- a/subsys/usb/device/class/hid/Kconfig +++ b/subsys/usb/device/class/hid/Kconfig @@ -65,13 +65,4 @@ config USB_HID_BOOT_PROTOCOL See Chapter 4.2 of Device Class Definition for Human Interface Devices 1.11 for more information. -config USB_HID_PROTOCOL_CODE - int "HID Boot Interface protocol code (DEPRECATED)" - default 0 - range 0 2 - depends on USB_HID_BOOT_PROTOCOL - help - This option is deprecated. - Please use usb_hid_set_proto_code() instead. - endif # USB_DEVICE_HID diff --git a/subsys/usb/device/class/hid/core.c b/subsys/usb/device/class/hid/core.c index d05fdae723e..442f1a4a0f0 100644 --- a/subsys/usb/device/class/hid/core.c +++ b/subsys/usb/device/class/hid/core.c @@ -59,7 +59,7 @@ struct usb_hid_config { .bNumEndpoints = 1, \ .bInterfaceClass = USB_BCC_HID, \ .bInterfaceSubClass = 1, \ - .bInterfaceProtocol = CONFIG_USB_HID_PROTOCOL_CODE, \ + .bInterfaceProtocol = 0, \ .iInterface = 0, \ } #else @@ -354,13 +354,22 @@ static void hid_do_status_cb(struct hid_device_info *dev_data, case USB_DC_ERROR: LOG_INF("Device error"); break; - case USB_DC_RESET: + case USB_DC_RESET: { LOG_INF("Device reset detected"); dev_data->configured = false; dev_data->suspended = false; #ifdef CONFIG_USB_HID_BOOT_PROTOCOL + const struct device *dev = dev_data->common.dev; + uint8_t prev = dev_data->protocol; + dev_data->protocol = HID_PROTOCOL_REPORT; + if (prev != HID_PROTOCOL_REPORT) { + if (dev_data->ops && dev_data->ops->protocol_change) { + dev_data->ops->protocol_change(dev, dev_data->protocol); + } + } #endif + } #ifdef CONFIG_USB_DEVICE_SOF hid_clear_idle_ctx(dev_data); #endif diff --git a/subsys/usb/device/class/msc.c b/subsys/usb/device/class/msc.c index 6eae1f6a3ab..1971c942af8 100644 --- a/subsys/usb/device/class/msc.c +++ b/subsys/usb/device/class/msc.c @@ -818,6 +818,10 @@ static void thread_memory_write_done(void) uint32_t size = defered_wr_sz; size_t overflowed_len = (curr_offset + size) - BLOCK_SIZE; + if (BLOCK_SIZE > (curr_offset + size)) { + overflowed_len = 0; + } + if (overflowed_len > 0) { memmove(page, &page[BLOCK_SIZE], overflowed_len); } @@ -968,10 +972,11 @@ USBD_DEFINE_CFG_DATA(mass_storage_config) = { .endpoint = mass_ep_data }; -static void mass_thread_main(int arg1, int unused) +static void mass_thread_main(void *p1, void *p2, void *p3) { - ARG_UNUSED(unused); - ARG_UNUSED(arg1); + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); while (1) { k_sem_take(&disk_wait_sem, K_FOREVER); @@ -1053,7 +1058,7 @@ static int mass_storage_init(void) /* Start a thread to offload disk ops */ k_thread_create(&mass_thread_data, mass_thread_stack, CONFIG_MASS_STORAGE_STACK_SIZE, - (k_thread_entry_t)mass_thread_main, NULL, NULL, NULL, + mass_thread_main, NULL, NULL, NULL, DISK_THREAD_PRIO, 0, K_NO_WAIT); k_thread_name_set(&mass_thread_data, "usb_mass"); diff --git a/subsys/usb/device/class/netusb/function_rndis.c b/subsys/usb/device/class/netusb/function_rndis.c index c58f236f866..bbdfa7513b2 100644 --- a/subsys/usb/device/class/netusb/function_rndis.c +++ b/subsys/usb/device/class/netusb/function_rndis.c @@ -883,8 +883,12 @@ static int rndis_class_handler(struct usb_setup_packet *setup, int32_t *len, return -ENOTSUP; } -static void cmd_thread(void) +static void cmd_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + LOG_INF("Command thread started"); while (true) { @@ -1051,7 +1055,7 @@ static int rndis_init(void) k_thread_create(&cmd_thread_data, cmd_stack, K_KERNEL_STACK_SIZEOF(cmd_stack), - (k_thread_entry_t)cmd_thread, + cmd_thread, NULL, NULL, NULL, K_PRIO_COOP(8), 0, K_NO_WAIT); k_thread_name_set(&cmd_thread_data, "usb_rndis"); diff --git a/subsys/usb/device/usb_transfer.c b/subsys/usb/device/usb_transfer.c index 7a75d87fd0c..95cf3198ab6 100644 --- a/subsys/usb/device/usb_transfer.c +++ b/subsys/usb/device/usb_transfer.c @@ -86,12 +86,17 @@ static void usb_transfer_work(struct k_work *item) if (trans->flags & USB_TRANS_WRITE) { if (!trans->bsize) { - if (!(trans->flags & USB_TRANS_NO_ZLP)) { - LOG_DBG("Transfer ZLP"); - usb_write(ep, NULL, 0, NULL); + if (trans->flags & USB_TRANS_NO_ZLP) { + trans->status = 0; + goto done; } - trans->status = 0; - goto done; + + /* Host have to read the ZLP just like any other DATA + * packet. Set USB_TRANS_NO_ZLP flag so the transfer + * will end next time we get ACK from host. + */ + LOG_DBG("Transfer ZLP"); + trans->flags |= USB_TRANS_NO_ZLP; } ret = usb_write(ep, trans->buffer, trans->bsize, &bytes); diff --git a/subsys/usb/device_next/Kconfig b/subsys/usb/device_next/Kconfig index d6ccd4d7bd6..90a774a9e36 100644 --- a/subsys/usb/device_next/Kconfig +++ b/subsys/usb/device_next/Kconfig @@ -18,7 +18,6 @@ source "subsys/logging/Kconfig.template.log_config" config USBD_SHELL bool "USB device shell" - default y depends on SHELL help Enable USB device shell. diff --git a/subsys/usb/device_next/class/loopback.c b/subsys/usb/device_next/class/loopback.c index bdd20717e74..d6d60243ab2 100644 --- a/subsys/usb/device_next/class/loopback.c +++ b/subsys/usb/device_next/class/loopback.c @@ -216,8 +216,6 @@ static int lb_control_to_host(struct usbd_class_node *c_nd, const struct usb_setup_packet *const setup, struct net_buf *const buf) { - struct usbd_contex *uds_ctx = c_nd->data->uds_ctx; - if (setup->RequestType.recipient != USB_REQTYPE_RECIPIENT_DEVICE) { errno = -ENOTSUP; return 0; @@ -226,7 +224,6 @@ static int lb_control_to_host(struct usbd_class_node *c_nd, if (setup->bRequest == LB_VENDOR_REQ_IN) { net_buf_add_mem(buf, lb_buf, MIN(sizeof(lb_buf), setup->wLength)); - usbd_ep_ctrl_enqueue(uds_ctx, buf); LOG_WRN("Device-to-Host, wLength %u | %zu", setup->wLength, MIN(sizeof(lb_buf), setup->wLength)); diff --git a/subsys/usb/device_next/usbd_class.c b/subsys/usb/device_next/usbd_class.c index 407e9145258..64610fa3d53 100644 --- a/subsys/usb/device_next/usbd_class.c +++ b/subsys/usb/device_next/usbd_class.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include #include diff --git a/subsys/usb/device_next/usbd_core.c b/subsys/usb/device_next/usbd_core.c index 5e68ccfcafa..655f86cb4b2 100644 --- a/subsys/usb/device_next/usbd_core.c +++ b/subsys/usb/device_next/usbd_core.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include @@ -163,8 +163,12 @@ static ALWAYS_INLINE int usbd_event_handler(struct usbd_contex *const uds_ctx, return ret; } -static void usbd_thread(void) +static void usbd_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct udc_event event; while (true) { @@ -226,7 +230,7 @@ static int usbd_pre_init(void) { k_thread_create(&usbd_thread_data, usbd_stack, K_KERNEL_STACK_SIZEOF(usbd_stack), - (k_thread_entry_t)usbd_thread, + usbd_thread, NULL, NULL, NULL, K_PRIO_COOP(8), 0, K_NO_WAIT); diff --git a/subsys/usb/host/CMakeLists.txt b/subsys/usb/host/CMakeLists.txt index 94fc529f533..1f29b2c7af2 100644 --- a/subsys/usb/host/CMakeLists.txt +++ b/subsys/usb/host/CMakeLists.txt @@ -8,6 +8,7 @@ zephyr_library_sources( usbh_ch9.c usbh_core.c usbh_api.c + usbh_device.c ) zephyr_library_sources_ifdef( diff --git a/subsys/usb/host/Kconfig b/subsys/usb/host/Kconfig index bdedc6a4aa4..e3055e0026c 100644 --- a/subsys/usb/host/Kconfig +++ b/subsys/usb/host/Kconfig @@ -17,7 +17,6 @@ source "subsys/logging/Kconfig.template.log_config" config USBH_SHELL bool "USB host shell" - default y depends on SHELL help Shell commands for USB host support. diff --git a/subsys/usb/host/usbh_ch9.c b/subsys/usb/host/usbh_ch9.c index d442f540e2d..f8f587a43c3 100644 --- a/subsys/usb/host/usbh_ch9.c +++ b/subsys/usb/host/usbh_ch9.c @@ -4,26 +4,43 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include -#include + +#include +#include #include #include #include +#include "usbh_device.h" + #include LOG_MODULE_REGISTER(usbh_ch9, CONFIG_USBH_LOG_LEVEL); -#define SETUP_REQ_TIMEOUT 1000U +/* + * For now we set it to the upper limit defined in Chapter + * "9.2.6.4 Standard Device Requests" + * This will need to be revised and set depending on the request. + */ +#define SETUP_REQ_TIMEOUT 5000U + +K_SEM_DEFINE(ch9_req_sync, 0, 1); + +static int ch9_req_cb(struct usb_device *const udev, struct uhc_transfer *const xfer) +{ + LOG_DBG("Request finished %p, err %d", xfer, xfer->err); + k_sem_give(&ch9_req_sync); + + return 0; +} -int usbh_req_setup(const struct device *dev, - const uint8_t addr, +int usbh_req_setup(struct usb_device *const udev, const uint8_t bmRequestType, const uint8_t bRequest, const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength, - uint8_t *const data) + struct net_buf *const buf) { struct usb_setup_packet req = { .bmRequestType = bmRequestType, @@ -33,108 +50,178 @@ int usbh_req_setup(const struct device *dev, .wLength = sys_cpu_to_le16(wLength), }; struct uhc_transfer *xfer; - struct net_buf *buf; uint8_t ep = usb_reqtype_is_to_device(&req) ? 0x00 : 0x80; int ret; - xfer = uhc_xfer_alloc(dev, addr, ep, 0, 64, SETUP_REQ_TIMEOUT, NULL); + xfer = usbh_xfer_alloc(udev, ep, 0, 64, SETUP_REQ_TIMEOUT, (void *)ch9_req_cb); if (!xfer) { return -ENOMEM; } - buf = uhc_xfer_buf_alloc(dev, xfer, sizeof(req)); - if (!buf) { - ret = -ENOMEM; - goto buf_alloc_err; - } - - net_buf_add_mem(buf, &req, sizeof(req)); + memcpy(xfer->setup_pkt, &req, sizeof(req)); + __ASSERT((buf != NULL && wLength) || (buf == NULL && !wLength), + "Unresolved conditions for data stage"); if (wLength) { - buf = uhc_xfer_buf_alloc(dev, xfer, wLength); - if (!buf) { - ret = -ENOMEM; + ret = usbh_xfer_buf_add(udev, xfer, buf); + if (ret) { goto buf_alloc_err; } - - if (usb_reqtype_is_to_device(&req) && data != NULL) { - net_buf_add_mem(buf, data, wLength); - } } - buf = uhc_xfer_buf_alloc(dev, xfer, 0); - if (!buf) { - ret = -ENOMEM; + ret = usbh_xfer_enqueue(udev, xfer); + if (ret) { goto buf_alloc_err; } - return uhc_ep_enqueue(dev, xfer); + k_sem_take(&ch9_req_sync, K_MSEC(SETUP_REQ_TIMEOUT)); + ret = xfer->err; buf_alloc_err: - uhc_xfer_free(dev, xfer); + usbh_xfer_free(udev, xfer); return ret; } -int usbh_req_desc(const struct device *dev, - const uint8_t addr, +int usbh_req_desc(struct usb_device *const udev, const uint8_t type, const uint8_t index, const uint8_t id, - const uint16_t len) + const uint16_t len, + struct net_buf *const buf) { const uint8_t bmRequestType = USB_REQTYPE_DIR_TO_HOST << 7; const uint8_t bRequest = USB_SREQ_GET_DESCRIPTOR; const uint16_t wValue = (type << 8) | index; - return usbh_req_setup(dev, addr, + return usbh_req_setup(udev, bmRequestType, bRequest, wValue, id, len, - NULL); + buf); } -int usbh_req_desc_dev(const struct device *dev, - const uint8_t addr) +int usbh_req_desc_dev(struct usb_device *const udev, + struct usb_device_descriptor *const desc) { const uint8_t type = USB_DESC_DEVICE; - const uint16_t wLength = 18; + const uint16_t wLength = sizeof(struct usb_device_descriptor); + struct net_buf *buf; + int ret; + + buf = usbh_xfer_buf_alloc(udev, wLength); + if (!buf) { + return -ENOMEM; + } + + ret = usbh_req_desc(udev, type, 0, 0, wLength, buf); + if (ret == 0 && buf->len == wLength) { + memcpy(desc, buf->data, wLength); + desc->bcdUSB = sys_le16_to_cpu(desc->bcdUSB); + desc->idVendor = sys_le16_to_cpu(desc->idVendor); + desc->idProduct = sys_le16_to_cpu(desc->idProduct); + desc->bcdDevice = sys_le16_to_cpu(desc->bcdDevice); + } + + usbh_xfer_buf_free(udev, buf); - return usbh_req_desc(dev, addr, type, 0, 0, wLength); + return ret; } -int usbh_req_desc_cfg(const struct device *dev, - const uint8_t addr, +int usbh_req_desc_cfg(struct usb_device *const udev, const uint8_t index, - const uint16_t len) + const uint16_t len, + struct usb_cfg_descriptor *const desc) { const uint8_t type = USB_DESC_CONFIGURATION; + const uint16_t wLength = len; + struct net_buf *buf; + int ret; + + buf = usbh_xfer_buf_alloc(udev, len); + if (!buf) { + return -ENOMEM; + } - return usbh_req_desc(dev, addr, type, index, 0, len); + ret = usbh_req_desc(udev, type, index, 0, wLength, buf); + if (ret == 0) { + memcpy(desc, buf->data, len); + desc->wTotalLength = sys_le16_to_cpu(desc->wTotalLength); + } + + usbh_xfer_buf_free(udev, buf); + + return ret; } -int usbh_req_set_address(const struct device *dev, - const uint8_t addr, const uint8_t new) +int usbh_req_set_address(struct usb_device *const udev, + const uint8_t addr) { const uint8_t bmRequestType = USB_REQTYPE_DIR_TO_DEVICE << 7; const uint8_t bRequest = USB_SREQ_SET_ADDRESS; + int ret; - return usbh_req_setup(dev, addr, - bmRequestType, bRequest, new, 0, 0, - NULL); + ret = usbh_req_setup(udev, bmRequestType, bRequest, addr, 0, 0, NULL); + if (ret == 0) { + udev->addr = addr; + if (addr == 0) { + udev->state = USB_STATE_DEFAULT; + } + + if (addr != 0 && udev->state == USB_STATE_DEFAULT) { + udev->state = USB_STATE_ADDRESSED; + } + } + + return ret; } -int usbh_req_set_cfg(const struct device *dev, - const uint8_t addr, const uint8_t new) +int usbh_req_set_cfg(struct usb_device *const udev, + const uint8_t cfg) { const uint8_t bmRequestType = USB_REQTYPE_DIR_TO_DEVICE << 7; const uint8_t bRequest = USB_SREQ_SET_CONFIGURATION; + int ret; - return usbh_req_setup(dev, addr, - bmRequestType, bRequest, new, 0, 0, - NULL); + /* Ignore the required state change condition for now. */ + ret = usbh_req_setup(udev, bmRequestType, bRequest, cfg, 0, 0, NULL); + if (ret == 0) { + udev->actual_cfg = cfg; + if (cfg == 0) { + udev->state = USB_STATE_ADDRESSED; + } + + if (cfg != 0 && udev->state == USB_STATE_ADDRESSED) { + udev->state = USB_STATE_CONFIGURED; + } + } + + return ret; +} + +int usbh_req_get_cfg(struct usb_device *const udev, + uint8_t *const cfg) +{ + const uint8_t bmRequestType = USB_REQTYPE_DIR_TO_HOST << 7; + const uint8_t bRequest = USB_SREQ_GET_CONFIGURATION; + const uint16_t wLength = 1; + struct net_buf *buf; + int ret; + + buf = usbh_xfer_buf_alloc(udev, wLength); + if (!buf) { + return -ENOMEM; + } + + ret = usbh_req_setup(udev, bmRequestType, bRequest, 0, 0, wLength, buf); + if (ret == 0 && buf->len == wLength) { + *cfg = buf->data[0]; + } + + usbh_xfer_buf_free(udev, buf); + + return ret; } -int usbh_req_set_alt(const struct device *dev, - const uint8_t addr, const uint8_t iface, - const uint8_t alt) +int usbh_req_set_alt(struct usb_device *const udev, + const uint8_t iface, const uint8_t alt) { const uint8_t bmRequestType = USB_REQTYPE_DIR_TO_DEVICE << 7 | USB_REQTYPE_RECIPIENT_INTERFACE; @@ -142,37 +229,35 @@ int usbh_req_set_alt(const struct device *dev, const uint16_t wValue = alt; const uint16_t wIndex = iface; - return usbh_req_setup(dev, addr, + return usbh_req_setup(udev, bmRequestType, bRequest, wValue, wIndex, 0, NULL); } -int usbh_req_set_sfs_rwup(const struct device *dev, - const uint8_t addr) +int usbh_req_set_sfs_rwup(struct usb_device *const udev) { const uint8_t bmRequestType = USB_REQTYPE_DIR_TO_DEVICE << 7; const uint8_t bRequest = USB_SREQ_SET_FEATURE; const uint16_t wValue = USB_SFS_REMOTE_WAKEUP; - return usbh_req_setup(dev, addr, + return usbh_req_setup(udev, bmRequestType, bRequest, wValue, 0, 0, NULL); } -int usbh_req_clear_sfs_rwup(const struct device *dev, - const uint8_t addr) +int usbh_req_clear_sfs_rwup(struct usb_device *const udev) { const uint8_t bmRequestType = USB_REQTYPE_DIR_TO_DEVICE << 7; const uint8_t bRequest = USB_SREQ_CLEAR_FEATURE; const uint16_t wValue = USB_SFS_REMOTE_WAKEUP; - return usbh_req_setup(dev, addr, + return usbh_req_setup(udev, bmRequestType, bRequest, wValue, 0, 0, NULL); } -int usbh_req_set_hcfs_ppwr(const struct device *dev, - const uint8_t addr, const uint8_t port) +int usbh_req_set_hcfs_ppwr(struct usb_device *const udev, + const uint8_t port) { const uint8_t bmRequestType = USB_REQTYPE_DIR_TO_DEVICE << 7 | USB_REQTYPE_TYPE_CLASS << 5 | @@ -181,13 +266,13 @@ int usbh_req_set_hcfs_ppwr(const struct device *dev, const uint16_t wValue = USB_HCFS_PORT_POWER; const uint16_t wIndex = port; - return usbh_req_setup(dev, addr, + return usbh_req_setup(udev, bmRequestType, bRequest, wValue, wIndex, 0, NULL); } -int usbh_req_set_hcfs_prst(const struct device *dev, - const uint8_t addr, const uint8_t port) +int usbh_req_set_hcfs_prst(struct usb_device *const udev, + const uint8_t port) { const uint8_t bmRequestType = USB_REQTYPE_DIR_TO_DEVICE << 7 | USB_REQTYPE_TYPE_CLASS << 5 | @@ -196,7 +281,7 @@ int usbh_req_set_hcfs_prst(const struct device *dev, const uint16_t wValue = USB_HCFS_PORT_RESET; const uint16_t wIndex = port; - return usbh_req_setup(dev, addr, + return usbh_req_setup(udev, bmRequestType, bRequest, wValue, wIndex, 0, NULL); } diff --git a/subsys/usb/host/usbh_ch9.h b/subsys/usb/host/usbh_ch9.h index c5a932fdec6..26c21c83715 100644 --- a/subsys/usb/host/usbh_ch9.h +++ b/subsys/usb/host/usbh_ch9.h @@ -10,49 +10,51 @@ #include #include -int usbh_req_setup(const struct device *dev, - const uint8_t addr, +#include "usbh_device.h" + +int usbh_req_setup(struct usb_device *const udev, const uint8_t bmRequestType, const uint8_t bRequest, const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength, - uint8_t *const data); + struct net_buf *const data); -int usbh_req_desc(const struct device *dev, - const uint8_t addr, +int usbh_req_desc(struct usb_device *const udev, const uint8_t type, const uint8_t index, const uint8_t id, - const uint16_t len); + const uint16_t len, + struct net_buf *const data); -int usbh_req_desc_dev(const struct device *dev, - const uint8_t addr); +int usbh_req_desc_dev(struct usb_device *const udev, + struct usb_device_descriptor *const dev); -int usbh_req_desc_cfg(const struct device *dev, - const uint8_t addr, +int usbh_req_desc_cfg(struct usb_device *const udev, const uint8_t index, - const uint16_t len); + const uint16_t len, + struct usb_cfg_descriptor *const desc); -int usbh_req_set_alt(const struct device *dev, - const uint8_t addr, const uint8_t iface, +int usbh_req_set_alt(struct usb_device *const udev, + const uint8_t iface, const uint8_t alt); -int usbh_req_set_address(const struct device *dev, - const uint8_t addr, const uint8_t new); +int usbh_req_set_address(struct usb_device *const udev, + const uint8_t addr); + +int usbh_req_set_cfg(struct usb_device *const udev, + const uint8_t cfg); -int usbh_req_set_cfg(const struct device *dev, - const uint8_t addr, const uint8_t new); +int usbh_req_get_cfg(struct usb_device *const udev, + uint8_t *const cfg); -int usbh_req_set_sfs_rwup(const struct device *dev, - const uint8_t addr); +int usbh_req_set_sfs_rwup(struct usb_device *const udev); -int usbh_req_clear_sfs_rwup(const struct device *dev, - const uint8_t addr); +int usbh_req_clear_sfs_rwup(struct usb_device *const udev); -int usbh_req_set_hcfs_ppwr(const struct device *dev, - const uint8_t addr, const uint8_t port); +int usbh_req_set_hcfs_ppwr(const struct usb_device *udev, + const uint8_t port); -int usbh_req_set_hcfs_prst(const struct device *dev, - const uint8_t addr, const uint8_t port); +int usbh_req_set_hcfs_prst(const struct usb_device *udev, + const uint8_t port); #endif /* ZEPHYR_INCLUDE_USBH_CH9_H */ diff --git a/subsys/usb/host/usbh_core.c b/subsys/usb/host/usbh_core.c index dc0f1a1da87..ea624d0305a 100644 --- a/subsys/usb/host/usbh_core.c +++ b/subsys/usb/host/usbh_core.c @@ -9,17 +9,17 @@ #include #include #include -#include "usbh_internal.h" #include + +#include "usbh_internal.h" +#include "usbh_device.h" + #include LOG_MODULE_REGISTER(uhs, CONFIG_USBH_LOG_LEVEL); static K_KERNEL_STACK_DEFINE(usbh_stack, CONFIG_USBH_STACK_SIZE); static struct k_thread usbh_thread_data; -/* TODO */ -static struct usbh_class_data *class_data; - K_MSGQ_DEFINE(usbh_msgq, sizeof(struct uhc_event), CONFIG_USBH_MAX_UHC_MSG, sizeof(uint32_t)); @@ -29,24 +29,14 @@ static int usbh_event_carrier(const struct device *dev, return k_msgq_put(&usbh_msgq, event, K_NO_WAIT); } -static int event_ep_request(struct usbh_contex *const ctx, - struct uhc_event *const event) +static int discard_ep_request(struct usbh_contex *const ctx, + struct uhc_transfer *const xfer) { - struct uhc_transfer *xfer = event->xfer; const struct device *dev = ctx->dev; - if (class_data && class_data->request) { - return class_data->request(ctx, event->xfer, event->status); - } - - while (!k_fifo_is_empty(&xfer->done)) { - struct net_buf *buf; - - buf = net_buf_get(&xfer->done, K_NO_WAIT); - if (buf) { - LOG_HEXDUMP_INF(buf->data, buf->len, "buf"); - uhc_xfer_buf_free(dev, buf); - } + if (xfer->buf) { + LOG_HEXDUMP_INF(xfer->buf->data, xfer->buf->len, "buf"); + uhc_xfer_buf_free(dev, xfer->buf); } return uhc_xfer_free(dev, xfer); @@ -57,51 +47,41 @@ static ALWAYS_INLINE int usbh_event_handler(struct usbh_contex *const ctx, { int ret = 0; + if (event->type == UHC_EVT_EP_REQUEST) { + struct usb_device *const udev = event->xfer->udev; + usbh_udev_cb_t cb = event->xfer->cb; + + if (event->xfer->cb) { + ret = cb(udev, event->xfer); + } else { + ret = discard_ep_request(ctx, event->xfer); + } + return ret; + } + switch (event->type) { case UHC_EVT_DEV_CONNECTED_LS: case UHC_EVT_DEV_CONNECTED_FS: case UHC_EVT_DEV_CONNECTED_HS: LOG_DBG("Device connected event"); - if (class_data && class_data->connected) { - ret = class_data->connected(ctx); - } break; case UHC_EVT_DEV_REMOVED: LOG_DBG("Device removed event"); - if (class_data && class_data->removed) { - ret = class_data->removed(ctx); - } break; case UHC_EVT_RESETED: LOG_DBG("Bus reset"); - /* TODO */ - if (class_data && class_data->removed) { - ret = class_data->removed(ctx); - } break; case UHC_EVT_SUSPENDED: LOG_DBG("Bus suspended"); - if (class_data && class_data->suspended) { - ret = class_data->suspended(ctx); - } break; case UHC_EVT_RESUMED: LOG_DBG("Bus resumed"); - if (class_data && class_data->resumed) { - ret = class_data->resumed(ctx); - } break; case UHC_EVT_RWUP: LOG_DBG("RWUP event"); - if (class_data && class_data->rwup) { - ret = class_data->rwup(ctx); - } - break; - case UHC_EVT_EP_REQUEST: - event_ep_request(ctx, event); break; case UHC_EVT_ERROR: - LOG_DBG("Error event"); + LOG_DBG("Error event %d", event->status); break; default: break; @@ -110,8 +90,12 @@ static ALWAYS_INLINE int usbh_event_handler(struct usbh_contex *const ctx, return ret; } -static void usbh_thread(const struct device *dev) +static void usbh_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct uhc_event event; while (true) { @@ -136,9 +120,10 @@ int usbh_init_device_intl(struct usbh_contex *const uhs_ctx) } STRUCT_SECTION_FOREACH(usbh_class_data, cdata) { - LOG_DBG("class data %p", cdata); - /* TODO */ - class_data = cdata; + /* + * For now, we have not implemented any class drivers, + * so just keep it as placeholder. + */ break; } @@ -149,7 +134,7 @@ static int uhs_pre_init(void) { k_thread_create(&usbh_thread_data, usbh_stack, K_KERNEL_STACK_SIZEOF(usbh_stack), - (k_thread_entry_t)usbh_thread, + usbh_thread, NULL, NULL, NULL, K_PRIO_COOP(9), 0, K_NO_WAIT); diff --git a/subsys/usb/host/usbh_device.c b/subsys/usb/host/usbh_device.c new file mode 100644 index 00000000000..cfc4cc5998d --- /dev/null +++ b/subsys/usb/host/usbh_device.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "usbh_device.h" + +#define USBH_USB_DEVICE_COUNT 1 + +static struct usb_device udevs[USBH_USB_DEVICE_COUNT]; + +struct usb_device *usbh_device_get_any(struct usbh_contex *const ctx) +{ + udevs->ctx = ctx; + + return udevs; +} diff --git a/subsys/usb/host/usbh_device.h b/subsys/usb/host/usbh_device.h new file mode 100644 index 00000000000..742c6a71803 --- /dev/null +++ b/subsys/usb/host/usbh_device.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_USBH_DEVICE_H +#define ZEPHYR_INCLUDE_USBH_DEVICE_H + +#include +#include +#include + +/* USB device state */ +enum usb_device_state { + USB_STATE_NOTCONNECTED, + USB_STATE_DEFAULT, + USB_STATE_ADDRESSED, + USB_STATE_CONFIGURED, +}; + +/* Host support view of a USB device */ +struct usb_device { + struct usbh_contex *ctx; + struct usb_device_descriptor dev_desc; + enum usb_device_state state; + uint8_t actual_cfg; + uint8_t addr; +}; + +/* Callback type to be used for e.g. synchronous requests */ +typedef int (*usbh_udev_cb_t)(struct usb_device *const udev, + struct uhc_transfer *const xfer); + +/* + * Get a device to work on, there will only be one for the first time + * until we implement USB device configuration/management. + */ +struct usb_device *usbh_device_get_any(struct usbh_contex *const ctx); + +/* Wrappers around to avoid glue UHC calls. */ +static inline struct uhc_transfer *usbh_xfer_alloc(struct usb_device *udev, + const uint8_t ep, + const uint8_t attrib, + const uint16_t mps, + const uint16_t timeout, + usbh_udev_cb_t *const cb) +{ + struct usbh_contex *const ctx = udev->ctx; + + return uhc_xfer_alloc(ctx->dev, udev->addr, ep, attrib, mps, timeout, udev, cb); +} + +static inline int usbh_xfer_buf_add(const struct usb_device *udev, + struct uhc_transfer *const xfer, + struct net_buf *buf) +{ + struct usbh_contex *const ctx = udev->ctx; + + return uhc_xfer_buf_add(ctx->dev, xfer, buf); +} + +static inline struct net_buf *usbh_xfer_buf_alloc(struct usb_device *udev, + const size_t size) +{ + struct usbh_contex *const ctx = udev->ctx; + + return uhc_xfer_buf_alloc(ctx->dev, size); +} + +static inline int usbh_xfer_free(const struct usb_device *udev, + struct uhc_transfer *const xfer) +{ + struct usbh_contex *const ctx = udev->ctx; + + return uhc_xfer_free(ctx->dev, xfer); +} + +static inline void usbh_xfer_buf_free(const struct usb_device *udev, + struct net_buf *const buf) +{ + struct usbh_contex *const ctx = udev->ctx; + + uhc_xfer_buf_free(ctx->dev, buf); +} + +static inline int usbh_xfer_enqueue(const struct usb_device *udev, + struct uhc_transfer *const xfer) +{ + struct usbh_contex *const ctx = udev->ctx; + + return uhc_ep_enqueue(ctx->dev, xfer); +} + +#endif /* ZEPHYR_INCLUDE_USBH_DEVICE_H */ diff --git a/subsys/usb/host/usbh_shell.c b/subsys/usb/host/usbh_shell.c index 6742e2ca5a0..0525bdeccef 100644 --- a/subsys/usb/host/usbh_shell.c +++ b/subsys/usb/host/usbh_shell.c @@ -12,7 +12,7 @@ #include #include -#include "usbh_internal.h" +#include "usbh_device.h" #include "usbh_ch9.h" #include @@ -22,8 +22,9 @@ LOG_MODULE_REGISTER(usbh_shell, CONFIG_USBH_LOG_LEVEL); #define FOOBAZ_VREQ_IN 0x5c USBH_CONTROLLER_DEFINE(uhs_ctx, DEVICE_DT_GET(DT_NODELABEL(zephyr_uhc0))); - +static struct usb_device *udev; const static struct shell *ctx_shell; +static uint8_t vreq_test_buf[1024]; static void print_dev_desc(const struct shell *sh, const struct usb_device_descriptor *const desc) @@ -57,150 +58,27 @@ static void print_cfg_desc(const struct shell *sh, shell_print(sh, "bMaxPower\t\t%u mA", desc->bMaxPower * 2); } -static void print_desc(const struct shell *sh, const struct net_buf *const buf) -{ - struct usb_desc_header *head = (void *)buf->data; - - if (buf->len < sizeof(struct usb_desc_header)) { - return; - } - - switch (head->bDescriptorType) { - case USB_DESC_DEVICE: { - struct usb_device_descriptor *desc = (void *)buf->data; - - if (buf->len < sizeof(struct usb_device_descriptor)) { - shell_hexdump(ctx_shell, buf->data, buf->len); - break; - } - - desc->bcdUSB = sys_le16_to_cpu(desc->bcdUSB); - desc->idVendor = sys_le16_to_cpu(desc->idVendor); - desc->idProduct = sys_le16_to_cpu(desc->idProduct); - desc->bcdDevice = sys_le16_to_cpu(desc->bcdDevice); - print_dev_desc(sh, desc); - break; - } - case USB_DESC_CONFIGURATION: { - struct usb_cfg_descriptor *desc = (void *)buf->data; - - if (buf->len < sizeof(struct usb_cfg_descriptor)) { - shell_hexdump(ctx_shell, buf->data, buf->len); - break; - } - - desc->wTotalLength = sys_le16_to_cpu(desc->wTotalLength); - print_cfg_desc(sh, desc); - break; - } - default: - shell_hexdump(ctx_shell, buf->data, buf->len); - break; - } -} - -static int bazfoo_request(struct usbh_contex *const ctx, - struct uhc_transfer *const xfer, - int err) -{ - const struct device *dev = ctx->dev; - - shell_info(ctx_shell, "host: transfer finished %p, err %d", xfer, err); - - while (!k_fifo_is_empty(&xfer->done)) { - struct net_buf *buf; - - buf = net_buf_get(&xfer->done, K_NO_WAIT); - if (buf) { - /* - * FIXME: We don not distinguish the context - * of the request and always try to print it - * as descriptor first. If it is not a known descriptor, - * we show a hexdump in any case. - * This is just simple enough for first steps and will - * be revised with coming peripheral device management. - */ - if (xfer->ep == USB_CONTROL_EP_IN) { - print_desc(ctx_shell, buf); - } else { - shell_hexdump(ctx_shell, buf->data, buf->len); - } - - uhc_xfer_buf_free(dev, buf); - } - } - - return uhc_xfer_free(dev, xfer); -} - -static int bazfoo_connected(struct usbh_contex *const ctx) -{ - shell_info(ctx_shell, "host: USB device connected"); - - return 0; -} - -static int bazfoo_removed(struct usbh_contex *const ctx) -{ - shell_info(ctx_shell, "host: USB device removed"); - - return 0; -} - -static int bazfoo_rwup(struct usbh_contex *const ctx) -{ - shell_info(ctx_shell, "host: Bus remote wakeup event"); - - return 0; -} - -static int bazfoo_suspended(struct usbh_contex *const ctx) -{ - shell_info(ctx_shell, "host: Bus suspended"); - - return 0; -} - -static int bazfoo_resumed(struct usbh_contex *const ctx) -{ - shell_info(ctx_shell, "host: Bus resumed"); - - return 0; -} - -USBH_DEFINE_CLASS(bazfoo) = { - .request = bazfoo_request, - .connected = bazfoo_connected, - .removed = bazfoo_removed, - .rwup = bazfoo_rwup, - .suspended = bazfoo_suspended, - .resumed = bazfoo_resumed, -}; - -static uint8_t vreq_test_buf[1024]; - static int cmd_bulk(const struct shell *sh, size_t argc, char **argv) { struct uhc_transfer *xfer; struct net_buf *buf; - uint8_t addr; uint8_t ep; size_t len; - addr = strtol(argv[1], NULL, 10); - ep = strtol(argv[2], NULL, 16); - len = MIN(sizeof(vreq_test_buf), strtol(argv[3], NULL, 10)); + ep = strtol(argv[1], NULL, 16); + len = MIN(sizeof(vreq_test_buf), strtol(argv[2], NULL, 10)); - xfer = uhc_xfer_alloc(uhs_ctx.dev, addr, ep, 0, 512, 10, NULL); + xfer = usbh_xfer_alloc(udev, ep, 0, 512, 10, NULL); if (!xfer) { return -ENOMEM; } - buf = uhc_xfer_buf_alloc(uhs_ctx.dev, xfer, len); + buf = usbh_xfer_buf_alloc(udev, len); if (!buf) { return -ENOMEM; } + xfer->buf = buf; if (USB_EP_DIR_IS_OUT(ep)) { net_buf_add_mem(buf, vreq_test_buf, len); } @@ -215,15 +93,25 @@ static int cmd_vendor_in(const struct shell *sh, (USB_REQTYPE_TYPE_VENDOR << 5); const uint8_t bRequest = FOOBAZ_VREQ_IN; const uint16_t wValue = 0x0000; + struct net_buf *buf; uint16_t wLength; - uint8_t addr; + int ret; - addr = strtol(argv[1], NULL, 10); - wLength = MIN(sizeof(vreq_test_buf), strtol(argv[2], NULL, 10)); + wLength = MIN(sizeof(vreq_test_buf), strtol(argv[1], NULL, 10)); + buf = usbh_xfer_buf_alloc(udev, wLength); + if (!buf) { + shell_print(sh, "host: Failed to allocate buffer"); + return -ENOMEM; + } + + ret = usbh_req_setup(udev, bmRequestType, bRequest, wValue, 0, wLength, buf); + if (ret == 0) { + memcpy(vreq_test_buf, buf->data, MIN(buf->len, wLength)); + } + + usbh_xfer_buf_free(udev, buf); - return usbh_req_setup(uhs_ctx.dev, addr, - bmRequestType, bRequest, wValue, 0, wLength, - NULL); + return ret; } static int cmd_vendor_out(const struct shell *sh, @@ -233,32 +121,35 @@ static int cmd_vendor_out(const struct shell *sh, (USB_REQTYPE_TYPE_VENDOR << 5); const uint8_t bRequest = FOOBAZ_VREQ_OUT; const uint16_t wValue = 0x0000; + struct net_buf *buf; uint16_t wLength; - uint8_t addr; + int ret; - addr = strtol(argv[1], NULL, 10); - wLength = MIN(sizeof(vreq_test_buf), strtol(argv[2], NULL, 10)); - - for (int i = 0; i < wLength; i++) { - vreq_test_buf[i] = i; + wLength = MIN(sizeof(vreq_test_buf), strtol(argv[1], NULL, 10)); + buf = usbh_xfer_buf_alloc(udev, wLength); + if (!buf) { + shell_print(sh, "host: Failed to allocate buffer"); + return -ENOMEM; } - return usbh_req_setup(uhs_ctx.dev, addr, - bmRequestType, bRequest, wValue, 0, wLength, - vreq_test_buf); + net_buf_add_mem(buf, &vreq_test_buf, wLength); + ret = usbh_req_setup(udev, bmRequestType, bRequest, wValue, 0, wLength, buf); + usbh_xfer_buf_free(udev, buf); + + return ret; } static int cmd_desc_device(const struct shell *sh, size_t argc, char **argv) { - uint8_t addr; + struct usb_device_descriptor desc; int err; - addr = strtol(argv[1], NULL, 10); - - err = usbh_req_desc_dev(uhs_ctx.dev, addr); + err = usbh_req_desc_dev(udev, &desc); if (err) { shell_print(sh, "host: Failed to request device descriptor"); + } else { + print_dev_desc(sh, &desc); } return err; @@ -267,17 +158,17 @@ static int cmd_desc_device(const struct shell *sh, static int cmd_desc_config(const struct shell *sh, size_t argc, char **argv) { - uint8_t addr; + struct usb_cfg_descriptor desc; uint8_t cfg; int err; - addr = strtol(argv[1], NULL, 10); - cfg = strtol(argv[2], NULL, 10); + cfg = strtol(argv[1], NULL, 10); - /* TODO: cfg is ignored, add to usbh_req_desc_cfg */ - err = usbh_req_desc_cfg(uhs_ctx.dev, addr, cfg, 128); + err = usbh_req_desc_cfg(udev, cfg, sizeof(desc), &desc); if (err) { shell_print(sh, "host: Failed to request configuration descriptor"); + } else { + print_cfg_desc(sh, &desc); } return err; @@ -287,40 +178,46 @@ static int cmd_desc_string(const struct shell *sh, size_t argc, char **argv) { const uint8_t type = USB_DESC_STRING; - uint8_t addr; + struct net_buf *buf; uint8_t id; uint8_t idx; int err; - addr = strtol(argv[1], NULL, 10); - id = strtol(argv[2], NULL, 10); - idx = strtol(argv[3], NULL, 10); + id = strtol(argv[1], NULL, 10); + idx = strtol(argv[2], NULL, 10); - err = usbh_req_desc(uhs_ctx.dev, addr, type, idx, id, 128); + buf = usbh_xfer_buf_alloc(udev, 128); + if (!buf) { + return -ENOMEM; + } + + err = usbh_req_desc(udev, type, idx, id, 128, buf); if (err) { shell_print(sh, "host: Failed to request configuration descriptor"); + } else { + shell_hexdump(ctx_shell, buf->data, buf->len); } + usbh_xfer_buf_free(udev, buf); + return err; } static int cmd_feature_set_halt(const struct shell *sh, size_t argc, char **argv) { - uint8_t addr; uint8_t ep; int err; - addr = strtol(argv[1], NULL, 10); - ep = strtol(argv[2], NULL, 16); + ep = strtol(argv[1], NULL, 16); - /* TODO: add usbh_req_set_sfs_halt(uhs_ctx.dev, 0); */ - err = usbh_req_set_sfs_rwup(uhs_ctx.dev, addr); + /* TODO: add usbh_req_set_sfs_halt(&uhs_ctx, NULL, 0); */ + err = usbh_req_set_sfs_rwup(udev); if (err) { shell_error(sh, "host: Failed to set halt feature"); } else { shell_print(sh, "host: Device 0x%02x, ep 0x%02x halt feature set", - addr, ep); + udev->addr, ep); } return err; @@ -329,16 +226,13 @@ static int cmd_feature_set_halt(const struct shell *sh, static int cmd_feature_clear_rwup(const struct shell *sh, size_t argc, char **argv) { - uint8_t addr; int err; - addr = strtol(argv[1], NULL, 10); - - err = usbh_req_clear_sfs_rwup(uhs_ctx.dev, addr); + err = usbh_req_clear_sfs_rwup(udev); if (err) { shell_error(sh, "host: Failed to clear rwup feature"); } else { - shell_print(sh, "host: Device 0x%02x, rwup feature cleared", addr); + shell_print(sh, "host: Device 0x%02x, rwup feature cleared", udev->addr); } return err; @@ -347,16 +241,13 @@ static int cmd_feature_clear_rwup(const struct shell *sh, static int cmd_feature_set_rwup(const struct shell *sh, size_t argc, char **argv) { - uint8_t addr; int err; - addr = strtol(argv[1], NULL, 10); - - err = usbh_req_set_sfs_rwup(uhs_ctx.dev, addr); + err = usbh_req_set_sfs_rwup(udev); if (err) { shell_error(sh, "host: Failed to set rwup feature"); } else { - shell_print(sh, "host: Device 0x%02x, rwup feature set", addr); + shell_print(sh, "host: Device 0x%02x, rwup feature set", udev->addr); } return err; @@ -365,19 +256,17 @@ static int cmd_feature_set_rwup(const struct shell *sh, static int cmd_feature_set_ppwr(const struct shell *sh, size_t argc, char **argv) { - uint8_t addr; uint8_t port; int err; - addr = strtol(argv[1], NULL, 10); - port = strtol(argv[2], NULL, 10); + port = strtol(argv[1], NULL, 10); - err = usbh_req_set_hcfs_ppwr(uhs_ctx.dev, addr, port); + err = usbh_req_set_hcfs_ppwr(udev, port); if (err) { shell_error(sh, "host: Failed to set ppwr feature"); } else { shell_print(sh, "host: Device 0x%02x, port %d, ppwr feature set", - addr, port); + udev->addr, port); } return err; @@ -386,40 +275,53 @@ static int cmd_feature_set_ppwr(const struct shell *sh, static int cmd_feature_set_prst(const struct shell *sh, size_t argc, char **argv) { - uint8_t addr; uint8_t port; int err; - addr = strtol(argv[1], NULL, 10); - port = strtol(argv[2], NULL, 10); + port = strtol(argv[1], NULL, 10); - err = usbh_req_set_hcfs_prst(uhs_ctx.dev, addr, port); + err = usbh_req_set_hcfs_prst(udev, port); if (err) { shell_error(sh, "host: Failed to set prst feature"); } else { shell_print(sh, "host: Device 0x%02x, port %d, prst feature set", - addr, port); + udev->addr, port); } return err; } -static int cmd_device_config(const struct shell *sh, - size_t argc, char **argv) +static int cmd_config_set(const struct shell *sh, + size_t argc, char **argv) { - uint8_t addr; uint8_t cfg; int err; - addr = strtol(argv[1], NULL, 10); - cfg = strtol(argv[2], NULL, 10); + cfg = strtol(argv[1], NULL, 10); - err = usbh_req_set_cfg(uhs_ctx.dev, addr, cfg); + err = usbh_req_set_cfg(udev, cfg); if (err) { shell_error(sh, "host: Failed to set configuration"); } else { shell_print(sh, "host: Device 0x%02x, new configuration %u", - addr, cfg); + udev->addr, cfg); + } + + return err; +} + +static int cmd_config_get(const struct shell *sh, + size_t argc, char **argv) +{ + uint8_t cfg; + int err; + + err = usbh_req_get_cfg(udev, &cfg); + if (err) { + shell_error(sh, "host: Failed to set configuration"); + } else { + shell_print(sh, "host: Device 0x%02x, current configuration %u", + udev->addr, cfg); } return err; @@ -428,21 +330,19 @@ static int cmd_device_config(const struct shell *sh, static int cmd_device_interface(const struct shell *sh, size_t argc, char **argv) { - uint8_t addr; uint8_t iface; uint8_t alt; int err; - addr = strtol(argv[1], NULL, 10); - iface = strtol(argv[2], NULL, 10); - alt = strtol(argv[3], NULL, 10); + iface = strtol(argv[1], NULL, 10); + alt = strtol(argv[2], NULL, 10); - err = usbh_req_set_alt(uhs_ctx.dev, addr, iface, alt); + err = usbh_req_set_alt(udev, iface, alt); if (err) { shell_error(sh, "host: Failed to set interface alternate"); } else { shell_print(sh, "host: Device 0x%02x, new %u alternate %u", - addr, iface, alt); + udev->addr, iface, alt); } return err; @@ -456,7 +356,7 @@ static int cmd_device_address(const struct shell *sh, addr = strtol(argv[1], NULL, 10); - err = usbh_req_set_address(uhs_ctx.dev, 0, addr); + err = usbh_req_set_address(udev, addr); if (err) { shell_error(sh, "host: Failed to set address"); } else { @@ -527,6 +427,7 @@ static int cmd_usbh_init(const struct shell *sh, int err; ctx_shell = sh; + udev = usbh_device_get_any(&uhs_ctx); err = usbh_init(&uhs_ctx); if (err == -EALREADY) { @@ -571,54 +472,62 @@ static int cmd_usbh_disable(const struct shell *sh, } SHELL_STATIC_SUBCMD_SET_CREATE(desc_cmds, - SHELL_CMD_ARG(device, NULL, "
    ", - cmd_desc_device, 2, 0), - SHELL_CMD_ARG(configuration, NULL, "
    ", - cmd_desc_config, 3, 0), - SHELL_CMD_ARG(string, NULL, "
    ", - cmd_desc_string, 4, 0), + SHELL_CMD_ARG(device, NULL, NULL, + cmd_desc_device, 1, 0), + SHELL_CMD_ARG(configuration, NULL, "", + cmd_desc_config, 2, 0), + SHELL_CMD_ARG(string, NULL, " ", + cmd_desc_string, 3, 0), SHELL_SUBCMD_SET_END ); SHELL_STATIC_SUBCMD_SET_CREATE(feature_set_cmds, - SHELL_CMD_ARG(rwup, NULL, "
    ", - cmd_feature_set_rwup, 2, 0), - SHELL_CMD_ARG(ppwr, NULL, "
    ", - cmd_feature_set_ppwr, 3, 0), - SHELL_CMD_ARG(prst, NULL, "
    ", - cmd_feature_set_prst, 3, 0), - SHELL_CMD_ARG(halt, NULL, "
    ", - cmd_feature_set_halt, 3, 0), + SHELL_CMD_ARG(rwup, NULL, NULL, + cmd_feature_set_rwup, 1, 0), + SHELL_CMD_ARG(ppwr, NULL, "", + cmd_feature_set_ppwr, 2, 0), + SHELL_CMD_ARG(prst, NULL, "", + cmd_feature_set_prst, 2, 0), + SHELL_CMD_ARG(halt, NULL, "", + cmd_feature_set_halt, 2, 0), SHELL_SUBCMD_SET_END ); SHELL_STATIC_SUBCMD_SET_CREATE(feature_clear_cmds, - SHELL_CMD_ARG(rwup, NULL, "
    ", - cmd_feature_clear_rwup, 2, 0), - SHELL_CMD_ARG(halt, NULL, "
    ", - cmd_feature_set_halt, 3, 0), + SHELL_CMD_ARG(rwup, NULL, NULL, + cmd_feature_clear_rwup, 1, 0), + SHELL_CMD_ARG(halt, NULL, "", + cmd_feature_set_halt, 2, 0), + SHELL_SUBCMD_SET_END +); + +SHELL_STATIC_SUBCMD_SET_CREATE(config_cmds, + SHELL_CMD_ARG(get, NULL, NULL, + cmd_config_get, 1, 0), + SHELL_CMD_ARG(set, NULL, "", + cmd_config_set, 2, 0), SHELL_SUBCMD_SET_END ); SHELL_STATIC_SUBCMD_SET_CREATE(device_cmds, SHELL_CMD_ARG(address, NULL, "
    ", cmd_device_address, 2, 0), - SHELL_CMD_ARG(config, NULL, "
    ", - cmd_device_config, 3, 0), - SHELL_CMD_ARG(interface, NULL, "
    ", - cmd_device_interface, 4, 0), + SHELL_CMD_ARG(config, &config_cmds, "get|set configuration", + NULL, 1, 0), + SHELL_CMD_ARG(interface, NULL, " ", + cmd_device_interface, 3, 0), SHELL_CMD_ARG(descriptor, &desc_cmds, "descriptor request", NULL, 1, 0), SHELL_CMD_ARG(feature-set, &feature_set_cmds, "feature selector", NULL, 1, 0), SHELL_CMD_ARG(feature-clear, &feature_clear_cmds, "feature selector", NULL, 1, 0), - SHELL_CMD_ARG(vendor_in, NULL, "
    ", - cmd_vendor_in, 3, 0), - SHELL_CMD_ARG(vendor_out, NULL, "
    ", - cmd_vendor_out, 3, 0), - SHELL_CMD_ARG(bulk, NULL, "
    ", - cmd_bulk, 4, 0), + SHELL_CMD_ARG(vendor_in, NULL, "", + cmd_vendor_in, 2, 0), + SHELL_CMD_ARG(vendor_out, NULL, "", + cmd_vendor_out, 2, 0), + SHELL_CMD_ARG(bulk, NULL, " ", + cmd_bulk, 3, 0), SHELL_SUBCMD_SET_END ); diff --git a/subsys/usb/usb_c/Kconfig b/subsys/usb/usb_c/Kconfig index 57be78f6819..6cd85c79d56 100644 --- a/subsys/usb/usb_c/Kconfig +++ b/subsys/usb/usb_c/Kconfig @@ -14,6 +14,14 @@ menuconfig USBC_STACK if USBC_STACK +config USBC_STACK_INIT_PRIORITY + int "USB-C stack init priority" + default 90 + help + Initialization priority of the USB-C connector driver in POST_KERNEL. + This driver must be initialized after devices referenced by USB-C connectors + like VBUS and TCPC. + config USBC_THREAD_PRIORITY int "USB-C thread priority" default 0 diff --git a/subsys/usb/usb_c/usbc_pe_common.c b/subsys/usb/usb_c/usbc_pe_common.c index 8c2e8d1fcf9..cc59cecbadc 100644 --- a/subsys/usb/usb_c/usbc_pe_common.c +++ b/subsys/usb/usb_c/usbc_pe_common.c @@ -345,6 +345,9 @@ void pe_message_received(const struct device *dev) struct policy_engine *pe = data->pe; atomic_set_bit(pe->flags, PE_FLAGS_MSG_RECEIVED); + + /* Allow the PE to be executed once more and respond faster for the received message */ + usbc_bypass_next_sleep(dev); } /** @@ -422,6 +425,9 @@ void pe_set_state(const struct device *dev, const enum usbc_pe_state state) __ASSERT(state < ARRAY_SIZE(pe_states), "invalid pe_state %d", state); smf_set_state(SMF_CTX(data->pe), &pe_states[state]); + + /* Allow the PE to execute logic from the new state without additional delay */ + usbc_bypass_next_sleep(dev); } /** diff --git a/subsys/usb/usb_c/usbc_prl.c b/subsys/usb/usb_c/usbc_prl.c index 8eb78e5ebe2..ca0465bac6d 100644 --- a/subsys/usb/usb_c/usbc_prl.c +++ b/subsys/usb/usb_c/usbc_prl.c @@ -446,7 +446,7 @@ static void increment_msgid_counter(const struct device *dev) /** * @brief Get the SOP* header for the current received message */ -static uint32_t get_sop_star_header(const struct device *dev) +static uint16_t get_sop_star_header(const struct device *dev) { struct usbc_port_data *data = dev->data; struct protocol_layer_tx_t *prl_tx = data->prl_tx; @@ -1177,7 +1177,7 @@ static void prl_rx_wait_for_phy_message(const struct device *dev) uint8_t power_role; /* Get the message */ - if (tcpc_receive_data(tcpc, rx_emsg) <= 0) { + if (tcpc_get_rx_pending_msg(tcpc, rx_emsg) <= 0) { /* No pending message or problem getting the message */ return; } diff --git a/subsys/usb/usb_c/usbc_stack.c b/subsys/usb/usb_c/usbc_stack.c index 48d4fb3d00d..08ac7cd3cb7 100644 --- a/subsys/usb/usb_c/usbc_stack.c +++ b/subsys/usb/usb_c/usbc_stack.c @@ -37,7 +37,12 @@ static ALWAYS_INLINE void usbc_handler(void *port_dev) k_thread_suspend(port->port_thread); } - k_msleep(CONFIG_USBC_STATE_MACHINE_CYCLE_TIME); + /* Check if there wasn't any request to do a one more iteration of USB-C state machines */ + if (!port->bypass_next_sleep) { + k_msleep(CONFIG_USBC_STATE_MACHINE_CYCLE_TIME); + } else { + port->bypass_next_sleep = false; + } } #define USBC_SUBSYS_INIT(inst) \ @@ -82,8 +87,8 @@ static ALWAYS_INLINE void usbc_handler(void *port_dev) }; \ \ DEVICE_DT_INST_DEFINE(inst, &usbc_subsys_init, NULL, &usbc_port_data_##inst, \ - &usbc_port_config_##inst, APPLICATION, \ - CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, NULL); + &usbc_port_config_##inst, POST_KERNEL, \ + CONFIG_USBC_STACK_INIT_PRIORITY, NULL); DT_INST_FOREACH_STATUS_OKAY(USBC_SUBSYS_INIT) @@ -133,6 +138,13 @@ int usbc_request(const struct device *dev, const enum usbc_policy_request_t req) return 0; } +void usbc_bypass_next_sleep(const struct device *dev) +{ + struct usbc_port_data *data = dev->data; + + data->bypass_next_sleep = true; +} + /** * @brief Sets the Device Policy Manager's data */ diff --git a/subsys/usb/usb_c/usbc_stack.h b/subsys/usb/usb_c/usbc_stack.h index 93a09130534..ca95f05f317 100644 --- a/subsys/usb/usb_c/usbc_stack.h +++ b/subsys/usb/usb_c/usbc_stack.h @@ -107,6 +107,9 @@ struct usbc_port_data { /** Device Policy manager Request */ struct request_value request; + /** Bypass next sleep and request one more iteration of the USB-C state machines */ + bool bypass_next_sleep; + /* USB-C Callbacks */ /** diff --git a/subsys/usb/usb_c/usbc_tc_common.c b/subsys/usb/usb_c/usbc_tc_common.c index 2cbfd30a345..94b34edf218 100644 --- a/subsys/usb/usb_c/usbc_tc_common.c +++ b/subsys/usb/usb_c/usbc_tc_common.c @@ -13,7 +13,7 @@ LOG_MODULE_DECLARE(usbc_stack, CONFIG_USBC_STACK_LOG_LEVEL); #include "usbc_tc_common_internal.h" static const struct smf_state tc_states[TC_STATE_COUNT]; -static void tc_init(const struct device *dev); +static int tc_init(const struct device *dev); /** * @brief Initializes the state machine and enters the Disabled state @@ -38,6 +38,7 @@ void tc_run(const struct device *dev, const int32_t dpm_request) struct usbc_port_data *data = dev->data; const struct device *tcpc = data->tcpc; struct tc_sm_t *tc = data->tc; + int ret; /* These requests are implicitly set by the Device Policy Manager */ if (dpm_request == PRIV_PORT_REQUEST_START) { @@ -55,7 +56,18 @@ void tc_run(const struct device *dev, const int32_t dpm_request) /* fall through */ case SM_INIT: /* Initialize the Type-C layer */ - tc_init(dev); + ret = tc_init(dev); + if (ret != 0 && ret != -EAGAIN) { + /* Transition to Disabled State */ + LOG_ERR("Disabling the Type-C Layer"); + data->tc_enabled = false; + tc_set_state(dev, TC_DISABLED_STATE); + } + + if (ret != 0) { + break; + } + data->tc_sm_state = SM_RUN; /* fall through */ case SM_RUN: @@ -66,7 +78,14 @@ void tc_run(const struct device *dev, const int32_t dpm_request) } /* Sample CC lines */ - tcpc_get_cc(tcpc, &tc->cc1, &tc->cc2); + if (tcpc_get_cc(tcpc, &tc->cc1, &tc->cc2) != 0) { + /* If this function fails, it may mean that the TCPC is in sleep mode or + * the communication with TCPC has failed, so we can assume that the CC + * lines are open or existing connection is faulty. + */ + tc->cc1 = TC_CC_VOLT_OPEN; + tc->cc2 = TC_CC_VOLT_OPEN; + } /* Detect polarity */ tc->cc_polarity = (tc->cc1 > tc->cc2) ? TC_POLARITY_CC1 : TC_POLARITY_CC2; @@ -100,11 +119,12 @@ bool tc_is_in_attached_state(const struct device *dev) /** * @brief Initializes the Type-C layer */ -static void tc_init(const struct device *dev) +static int tc_init(const struct device *dev) { struct usbc_port_data *data = dev->data; struct tc_sm_t *tc = data->tc; const struct device *tcpc = data->tcpc; + int ret; /* Initialize the timers */ usbc_timer_init(&tc->tc_t_error_recovery, TC_T_ERROR_RECOVERY_SOURCE_MIN_MS); @@ -118,14 +138,26 @@ static void tc_init(const struct device *dev) tc->flags = ATOMIC_INIT(0); /* Initialize the TCPC */ - tcpc_init(tcpc); + ret = tcpc_init(tcpc); + if (ret != 0) { + LOG_ERR("TCPC initialization failed: %d", ret); + return ret; + } #ifdef CONFIG_USBC_CSM_SOURCE_ONLY - /* Stop sourcing VBUS */ - data->policy_cb_src_en(dev, false); + /* Stop sourcing VBUS by policy callback and/or TCPC */ + ret = data->policy_cb_src_en(dev, false); + if (ret != 0) { + LOG_ERR("Couldn't disable vbus sourcing: %d", ret); + return ret; + } /* Stop sourcing VCONN */ - tcpc_set_vconn(tcpc, false); + ret = tcpc_set_vconn(tcpc, false); + if (ret != 0 && ret != -ENOTSUP) { + LOG_ERR("Couldn't disable vconn: %d", ret); + return ret; + } #endif /* Initialize the state machine */ @@ -134,6 +166,8 @@ static void tc_init(const struct device *dev) * short while if this is a system reset. */ tc_set_state(dev, TC_ERROR_RECOVERY_STATE); + + return 0; } /** @@ -179,12 +213,22 @@ void tc_select_src_collision_rp(const struct device *dev, enum tc_rp_value rp) { struct usbc_port_data *data = dev->data; const struct device *tcpc = data->tcpc; + int ret; /* Select Rp value */ - tcpc_select_rp_value(tcpc, rp); + ret = tcpc_select_rp_value(tcpc, rp); + if (ret != 0 && ret != -ENOTSUP) { + LOG_ERR("Couldn't set Rp value to %d: %d", rp, ret); + tc_set_state(dev, TC_ERROR_RECOVERY_STATE); + return; + } /* Place Rp on CC lines */ - tcpc_set_cc(tcpc, TC_CC_RP); + ret = tcpc_set_cc(tcpc, TC_CC_RP); + if (ret != 0) { + LOG_ERR("Couldn't set CC lines to Rp: %d", ret); + tc_set_state(dev, TC_ERROR_RECOVERY_STATE); + } } /** @@ -196,14 +240,24 @@ static void tc_cc_open_entry(void *obj) const struct device *dev = tc->dev; struct usbc_port_data *data = dev->data; const struct device *tcpc = data->tcpc; + int ret; tc->cc_voltage = TC_CC_VOLT_OPEN; /* Disable VCONN */ - tcpc_set_vconn(tcpc, false); + ret = tcpc_set_vconn(tcpc, false); + if (ret != 0 && ret != -ENOSYS) { + LOG_ERR("Couldn't disable vconn: %d", ret); + tc_set_state(dev, TC_ERROR_RECOVERY_STATE); + return; + } /* Open CC lines */ - tcpc_set_cc(tcpc, TC_CC_OPEN); + ret = tcpc_set_cc(tcpc, TC_CC_OPEN); + if (ret != 0) { + LOG_ERR("Couldn't set CC lines to open: %d", ret); + tc_set_state(dev, TC_ERROR_RECOVERY_STATE); + } } /** diff --git a/subsys/usb/usb_c/usbc_tc_snk_states.c b/subsys/usb/usb_c/usbc_tc_snk_states.c index 36e8cef7db1..11cc456acfb 100644 --- a/subsys/usb/usb_c/usbc_tc_snk_states.c +++ b/subsys/usb/usb_c/usbc_tc_snk_states.c @@ -79,7 +79,15 @@ static void sink_power_sub_states(const struct device *dev) */ void tc_unattached_snk_entry(void *obj) { + struct tc_sm_t *tc = (struct tc_sm_t *)obj; + LOG_INF("Unattached.SNK"); + + /* + * Allow the state machine to immediately check the state of CC lines and go into + * Attach.Wait state in case the Rp value is detected on the CC lines + */ + usbc_bypass_next_sleep(tc->dev); } /** @@ -109,6 +117,12 @@ void tc_attach_wait_snk_entry(void *obj) LOG_INF("AttachWait.SNK"); tc->cc_state = TC_CC_NONE; + + /* + * Allow the debounce timers to start immediately without additional delay added + * by going into sleep + */ + usbc_bypass_next_sleep(tc->dev); } /** @@ -138,6 +152,11 @@ void tc_attach_wait_snk_run(void *obj) /* Wait for CC debounce */ if (usbc_timer_running(&tc->tc_t_cc_debounce) && usbc_timer_expired(&tc->tc_t_cc_debounce) == false) { + if (CONFIG_USBC_STATE_MACHINE_CYCLE_TIME >= TC_T_CC_DEBOUNCE_MIN_MS) { + /* Make sure the debounce time won't be longer than specified */ + usbc_bypass_next_sleep(tc->dev); + } + return; } @@ -156,6 +175,13 @@ void tc_attach_wait_snk_run(void *obj) if (vbus_present) { tc_set_state(dev, TC_ATTACHED_SNK_STATE); } + + /* + * In case of no VBUS present, this call prevents going into the sleep and allows for + * faster VBUS detection. In case of VBUS present, allows for immediate execution of logic + * from new state. + */ + usbc_bypass_next_sleep(tc->dev); } void tc_attach_wait_snk_exit(void *obj) @@ -174,11 +200,17 @@ void tc_attached_snk_entry(void *obj) const struct device *dev = tc->dev; struct usbc_port_data *data = dev->data; const struct device *tcpc = data->tcpc; + int ret; LOG_INF("Attached.SNK"); /* Set CC polarity */ - tcpc_set_cc_polarity(tcpc, tc->cc_polarity); + ret = tcpc_set_cc_polarity(tcpc, tc->cc_polarity); + if (ret != 0) { + LOG_ERR("Couldn't set CC polarity to %d: %d", tc->cc_polarity, ret); + tc_set_state(dev, TC_ERROR_RECOVERY_STATE); + return; + } /* Enable PD */ tc_pd_enable(dev, true); @@ -227,6 +259,11 @@ void tc_cc_rd_entry(void *obj) const struct device *dev = tc->dev; struct usbc_port_data *data = dev->data; const struct device *tcpc = data->tcpc; + int ret; - tcpc_set_cc(tcpc, TC_CC_RD); + ret = tcpc_set_cc(tcpc, TC_CC_RD); + if (ret != 0) { + LOG_ERR("Couldn't set CC lines to Rd: %d", ret); + tc_set_state(dev, TC_ERROR_RECOVERY_STATE); + } } diff --git a/subsys/usb/usb_c/usbc_tc_src_states.c b/subsys/usb/usb_c/usbc_tc_src_states.c index 2fe703dfb76..972c7cdef54 100644 --- a/subsys/usb/usb_c/usbc_tc_src_states.c +++ b/subsys/usb/usb_c/usbc_tc_src_states.c @@ -222,6 +222,7 @@ void tc_attached_src_entry(void *obj) const struct device *dev = tc->dev; struct usbc_port_data *data = dev->data; const struct device *tcpc = data->tcpc; + int ret; LOG_INF("Attached.SRC"); @@ -229,7 +230,12 @@ void tc_attached_src_entry(void *obj) tcpc_set_roles(tcpc, TC_ROLE_SOURCE, TC_ROLE_DFP); /* Set cc polarity */ - tcpc_set_cc_polarity(tcpc, tc->cc_polarity); + ret = tcpc_set_cc_polarity(tcpc, tc->cc_polarity); + if (ret != 0) { + LOG_ERR("Couldn't set CC polarity to %d: %d", tc->cc_polarity, ret); + tc_set_state(dev, TC_ERROR_RECOVERY_STATE); + return; + } /* Start sourcing VBUS */ if (data->policy_cb_src_en(dev, true) == 0) { @@ -287,6 +293,7 @@ void tc_attached_src_exit(void *obj) const struct device *dev = tc->dev; struct usbc_port_data *data = dev->data; const struct device *tcpc = data->tcpc; + int ret; __ASSERT(data->policy_cb_src_en != NULL, "policy_cb_src_en must not be NULL"); @@ -298,7 +305,10 @@ void tc_attached_src_exit(void *obj) data->policy_cb_src_en(dev, false); /* Stop sourcing VCONN */ - tcpc_set_vconn(tcpc, false); + ret = tcpc_set_vconn(tcpc, false); + if (ret != 0 && ret != -ENOSYS) { + LOG_ERR("Couldn't disable VCONN source"); + } } /** @@ -312,6 +322,7 @@ void tc_cc_rp_entry(void *obj) struct usbc_port_data *data = dev->data; const struct device *tcpc = data->tcpc; enum tc_rp_value rp = TC_RP_USB; + int ret; /* * Get initial Rp value from Device Policy Manager or use @@ -322,8 +333,17 @@ void tc_cc_rp_entry(void *obj) } /* Select Rp value */ - tcpc_select_rp_value(tcpc, rp); + ret = tcpc_select_rp_value(tcpc, rp); + if (ret != 0 && ret != -ENOTSUP) { + LOG_ERR("Couldn't set Rp value to %d: %d", rp, ret); + tc_set_state(dev, TC_ERROR_RECOVERY_STATE); + return; + } /* Place Rp on CC lines */ - tcpc_set_cc(tcpc, TC_CC_RP); + ret = tcpc_set_cc(tcpc, TC_CC_RP); + if (ret != 0) { + LOG_ERR("Couldn't set CC lines to Rp: %d", ret); + tc_set_state(dev, TC_ERROR_RECOVERY_STATE); + } } diff --git a/subsys/zbus/zbus.c b/subsys/zbus/zbus.c index 4ea2d986a3f..b1178b1fea7 100644 --- a/subsys/zbus/zbus.c +++ b/subsys/zbus/zbus.c @@ -29,8 +29,8 @@ static inline struct net_buf *_zbus_create_net_buf(struct net_buf_pool *pool, si #else NET_BUF_POOL_FIXED_DEFINE(_zbus_msg_subscribers_pool, - (CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_STATIC_DATA_SIZE), (CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_SIZE), + (CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_STATIC_DATA_SIZE), sizeof(struct zbus_channel *), NULL); static inline struct net_buf *_zbus_create_net_buf(struct net_buf_pool *pool, size_t size, diff --git a/tests/application_development/code_relocation/linker_xtensa_qemu_sram2.ld b/tests/application_development/code_relocation/linker_xtensa_qemu_sram2.ld index 3cf73a090cf..3fd33186a8f 100644 --- a/tests/application_development/code_relocation/linker_xtensa_qemu_sram2.ld +++ b/tests/application_development/code_relocation/linker_xtensa_qemu_sram2.ld @@ -26,4 +26,4 @@ PHDRS #define MPU_ALIGN(region_size) \ . = ALIGN(4) -#include +#include diff --git a/tests/application_development/code_relocation/prj.conf b/tests/application_development/code_relocation/prj.conf index 8028191ca70..16d8d83470e 100644 --- a/tests/application_development/code_relocation/prj.conf +++ b/tests/application_development/code_relocation/prj.conf @@ -1,6 +1,5 @@ CONFIG_CODE_DATA_RELOCATION=y CONFIG_COVERAGE=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_HAVE_CUSTOM_LINKER_SCRIPT=y CONFIG_CUSTOM_LINKER_SCRIPT="linker_arm_sram2.ld" diff --git a/tests/application_development/code_relocation/prj_riscv.conf b/tests/application_development/code_relocation/prj_riscv.conf index 1bc4054f2d6..a4f229f85a7 100644 --- a/tests/application_development/code_relocation/prj_riscv.conf +++ b/tests/application_development/code_relocation/prj_riscv.conf @@ -1,5 +1,4 @@ CONFIG_CODE_DATA_RELOCATION=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_HAVE_CUSTOM_LINKER_SCRIPT=y CONFIG_CUSTOM_LINKER_SCRIPT="linker_riscv_qemu_sram2.ld" diff --git a/tests/application_development/code_relocation/prj_xtensa.conf b/tests/application_development/code_relocation/prj_xtensa.conf index 2c0a3874f30..6be828a0385 100644 --- a/tests/application_development/code_relocation/prj_xtensa.conf +++ b/tests/application_development/code_relocation/prj_xtensa.conf @@ -1,5 +1,4 @@ CONFIG_CODE_DATA_RELOCATION=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_HAVE_CUSTOM_LINKER_SCRIPT=y CONFIG_CUSTOM_LINKER_SCRIPT="linker_xtensa_qemu_sram2.ld" diff --git a/tests/application_development/code_relocation/testcase.yaml b/tests/application_development/code_relocation/testcase.yaml index 12e7595424d..e67885390d8 100644 --- a/tests/application_development/code_relocation/testcase.yaml +++ b/tests/application_development/code_relocation/testcase.yaml @@ -9,20 +9,12 @@ tests: platform_allow: - mimxrt1060_evk application_development.code_relocation_kinetis: - filter: CONFIG_CPU_HAS_NXP_MPU and CONFIG_MINIMAL_LIBC + filter: CONFIG_CPU_HAS_NXP_MPU arch_allow: arm extra_configs: - CONFIG_MPU_ALLOW_FLASH_WRITE=y platform_allow: - frdm_k64f - application_development.code_relocation.nxp_s32: - filter: not CONFIG_CPU_HAS_NXP_MPU and CONFIG_MINIMAL_LIBC and dt_chosen_enabled("zephyr,itcm") - arch_allow: arm - extra_configs: - - CONFIG_RELOCATE_TO_ITCM=y - - CONFIG_NULL_POINTER_EXCEPTION_DETECTION_NONE=y - platform_allow: - - mr_canhubk3 application_development.code_relocation.no_itcm: filter: not CONFIG_CPU_HAS_NXP_MPU and not dt_chosen_enabled("zephyr,itcm") arch_allow: arm diff --git a/tests/application_development/gen_inc_file/CMakeLists.txt b/tests/application_development/gen_inc_file/CMakeLists.txt index aebb2257572..45401b981c6 100644 --- a/tests/application_development/gen_inc_file/CMakeLists.txt +++ b/tests/application_development/gen_inc_file/CMakeLists.txt @@ -13,6 +13,10 @@ set(gen_dir ${ZEPHYR_BINARY_DIR}/include/generated/) set(source_file src/file.bin) generate_inc_file_for_target(app ${source_file} ${gen_dir}/file.bin.inc) +generate_inc_file_for_target(app ${source_file} ${gen_dir}/file.bin.partial.inc + --offset=100 --length=42) generate_inc_file_for_target(app ${source_file} ${gen_dir}/file.bin.gz.inc --gzip) generate_inc_file_for_target(app ${source_file} ${gen_dir}/file.bin.mtime.gz.inc --gzip --gzip-mtime=42) +generate_inc_file_for_target(app ${source_file} ${gen_dir}/file.bin.partial.gz.inc + --gzip --offset=100 --length=42) diff --git a/tests/application_development/gen_inc_file/prj.conf b/tests/application_development/gen_inc_file/prj.conf index bee34382821..f6d97748604 100644 --- a/tests/application_development/gen_inc_file/prj.conf +++ b/tests/application_development/gen_inc_file/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=2048 diff --git a/tests/application_development/gen_inc_file/src/main.c b/tests/application_development/gen_inc_file/src/main.c index a7eaf7d50b3..2fbb57c2ac3 100644 --- a/tests/application_development/gen_inc_file/src/main.c +++ b/tests/application_development/gen_inc_file/src/main.c @@ -13,11 +13,16 @@ * @cond INTERNAL_HIDDEN */ -/* The file.inc contains characters from 0 to 255 */ +/* The file.bin.inc contains characters from 0 to 255 */ static const unsigned char inc_file[] = { #include }; +/* The file.bin.partial.inc contains characters from 100 to 141 */ +static const unsigned char partial_inc_file[] = { +#include +}; + static const unsigned char no_mtime_gz_inc_file[] = { #include }; @@ -26,6 +31,10 @@ static const unsigned char mtime_gz_inc_file[] = { #include }; +static const unsigned char partial_gz_inc_file[] = { +#include +}; + /** * @endcond */ @@ -74,6 +83,17 @@ static const unsigned char compressed_inc_file[] = { 0x8c, 0x05, 0x29, 0x00, 0x01, 0x00, 0x00, }; +static const unsigned char compressed_partial_inc_file[] = { + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0xff, 0x4b, 0x49, 0x4d, 0x4b, 0xcf, 0xc8, + 0xcc, 0xca, 0xce, 0xc9, 0xcd, 0xcb, 0x2f, 0x28, + 0x2c, 0x2a, 0x2e, 0x29, 0x2d, 0x2b, 0xaf, 0xa8, + 0xac, 0xaa, 0xae, 0xa9, 0xad, 0xab, 0x6f, 0x68, + 0x6c, 0x6a, 0x6e, 0x69, 0x6d, 0x6b, 0xef, 0xe8, + 0xec, 0xea, 0xee, 0xe9, 0x05, 0x00, 0xe7, 0xa1, + 0xc1, 0x22, 0x2a, 0x00, 0x00, 0x00, +}; + ZTEST(gen_inc_file, test_gen_inc_file) { int i; @@ -85,13 +105,24 @@ ZTEST(gen_inc_file, test_gen_inc_file) } } +ZTEST(gen_inc_file, test_gen_partial_inc_file) +{ + int i; + + zassert_equal(sizeof(partial_inc_file), 42, "Invalid partial size file"); + + for (i = 0; i < sizeof(partial_inc_file); i++) { + zassert_equal(partial_inc_file[i], i + 100, "Invalid value in partial inc file"); + } +} static void do_test_gen_gz_inc_file(const unsigned char gz_inc_file[], + const unsigned char ref_file[], int ref_size, const unsigned char mtime[4]) { int i; - for (i = 0; i < sizeof(inc_file); i++) { + for (i = 0; i < ref_size; i++) { if (4 <= i && i < 8) { /* Modification time field (4 bytes) in * the gzip header. @@ -104,7 +135,7 @@ static void do_test_gen_gz_inc_file(const unsigned char gz_inc_file[], continue; } - zassert_equal(gz_inc_file[i], compressed_inc_file[i], + zassert_equal(gz_inc_file[i], ref_file[i], "Invalid value in inc file"); } } @@ -114,7 +145,8 @@ ZTEST(gen_inc_file, test_gen_gz_inc_file_no_mtime) zassert_equal(sizeof(no_mtime_gz_inc_file), sizeof(compressed_inc_file), "Invalid compressed file size"); - do_test_gen_gz_inc_file(no_mtime_gz_inc_file, mtime_zero); + do_test_gen_gz_inc_file(no_mtime_gz_inc_file, compressed_inc_file, + sizeof(compressed_inc_file), mtime_zero); } ZTEST(gen_inc_file, test_gen_gz_inc_file_mtime_arg) @@ -122,7 +154,17 @@ ZTEST(gen_inc_file, test_gen_gz_inc_file_mtime_arg) zassert_equal(sizeof(mtime_gz_inc_file), sizeof(compressed_inc_file), "Invalid compressed file size"); - do_test_gen_gz_inc_file(mtime_gz_inc_file, mtime_test_val); + do_test_gen_gz_inc_file(mtime_gz_inc_file, compressed_inc_file, + sizeof(compressed_inc_file), mtime_test_val); +} + +ZTEST(gen_inc_file, test_gen_gz_inc_partial_file) +{ + zassert_equal(sizeof(partial_gz_inc_file), sizeof(compressed_partial_inc_file), + "Invalid partial compressed file size"); + + do_test_gen_gz_inc_file(partial_gz_inc_file, compressed_partial_inc_file, + sizeof(compressed_partial_inc_file), NULL); } diff --git a/tests/arch/arc/arc_dsp_sharing/prj.conf b/tests/arch/arc/arc_dsp_sharing/prj.conf index b2d117d0bcb..f3be5294428 100644 --- a/tests/arch/arc/arc_dsp_sharing/prj.conf +++ b/tests/arch/arc/arc_dsp_sharing/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ARC_DSP=y CONFIG_ARC_DSP_SHARING=y CONFIG_MAIN_STACK_SIZE=1024 diff --git a/tests/arch/arc/arc_dsp_sharing/testcase.yaml b/tests/arch/arc/arc_dsp_sharing/testcase.yaml index 09ac8efa789..21cb221e059 100644 --- a/tests/arch/arc/arc_dsp_sharing/testcase.yaml +++ b/tests/arch/arc/arc_dsp_sharing/testcase.yaml @@ -1,8 +1,8 @@ tests: - dsp_sharing.test_load_store: + arch.arc.dsp_sharing.test_load_store: filter: CONFIG_ISA_ARCV2 and CONFIG_ARC_HAS_DSP platform_allow: nsim_em11d - dsp_sharing.test_calculation: + arch.arc.dsp_sharing.test_calculation: filter: CONFIG_ISA_ARCV2 and CONFIG_ARC_HAS_DSP toolchain_allow: arcmwdt platform_allow: nsim_em11d diff --git a/tests/arch/arm/arm_custom_interrupt/CMakeLists.txt b/tests/arch/arm/arm_custom_interrupt/CMakeLists.txt new file mode 100644 index 00000000000..04c09451564 --- /dev/null +++ b/tests/arch/arm/arm_custom_interrupt/CMakeLists.txt @@ -0,0 +1,9 @@ +#SPDX - License - Identifier : Apache - 2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(arm_interrupt) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/arch/arm/arm_custom_interrupt/Kconfig b/tests/arch/arm/arm_custom_interrupt/Kconfig new file mode 100644 index 00000000000..73a87ef561b --- /dev/null +++ b/tests/arch/arm/arm_custom_interrupt/Kconfig @@ -0,0 +1,13 @@ +# Private config options for test + +# Copyright Meta Platforms, Inc. and its affiliates. +# SPDX-License-Identifier: Apache-2.0 + +mainmenu "Custom interrupt test" + +source "Kconfig.zephyr" + +config ENABLE_CUSTOM_INTERRUPTS + bool + default y + select ARM_CUSTOM_INTERRUPT_CONTROLLER diff --git a/tests/arch/arm/arm_custom_interrupt/README.txt b/tests/arch/arm/arm_custom_interrupt/README.txt new file mode 100644 index 00000000000..d5adfc01241 --- /dev/null +++ b/tests/arch/arm/arm_custom_interrupt/README.txt @@ -0,0 +1,35 @@ +Title: Test to verify custom interrupt controller handling with on + the Cortex-M architectures. + +Description: + +This test verifies customer interrupt controller handling on +Cortex-M architectures using the CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER +option. It will locate a unused interrupt to trigger via software and test +all methods that are part of the SoC interrupt control interface. + +--------------------------------------------------------------------------- + +Sample Output +*** Booting Zephyr OS build zephyr-v3.4.0-4023-g7fca0aa8a693 *** +Running TESTSUITE arm_custom_interrupt +=================================================================== +START - test_arm_interrupt +Available IRQ line: 42 +Got IRQ: 42 +Got IRQ: 42 +Got IRQ: 42 + PASS - test_arm_interrupt in 0.001 seconds +=================================================================== +TESTSUITE arm_custom_interrupt succeeded + +------ TESTSUITE SUMMARY START ------ + +SUITE PASS - 100.00% [arm_custom_interrupt]: pass = 1, fail = 0, skip = 0, total = 1 duration = 0.001 seconds + - PASS - [arm_custom_interrupt.test_arm_interrupt] duration = 0.001 seconds + +------ TESTSUITE SUMMARY END ------ + +=================================================================== +RunID: b979ee8bbf5ad07d1754866129997539 +PROJECT EXECUTION SUCCESSFUL diff --git a/tests/arch/arm/arm_custom_interrupt/prj.conf b/tests/arch/arm/arm_custom_interrupt/prj.conf new file mode 100644 index 00000000000..ab8b7519f55 --- /dev/null +++ b/tests/arch/arm/arm_custom_interrupt/prj.conf @@ -0,0 +1,4 @@ +CONFIG_ZTEST=y +CONFIG_DYNAMIC_INTERRUPTS=y +CONFIG_IDLE_STACK_SIZE=512 +CONFIG_ASSERT_TEST=y diff --git a/tests/arch/arm/arm_custom_interrupt/src/arm_custom_interrupt.c b/tests/arch/arm/arm_custom_interrupt/src/arm_custom_interrupt.c new file mode 100644 index 00000000000..97d3c55365d --- /dev/null +++ b/tests/arch/arm/arm_custom_interrupt/src/arm_custom_interrupt.c @@ -0,0 +1,209 @@ +/* + * Copyright Meta Platforms, Inc. and its affiliates. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +unsigned int sw_irq_number = (unsigned int)(-1); +static volatile bool custom_init_called; +static volatile bool custom_enable_called; +static volatile bool custom_disable_called; +static volatile bool custom_set_priority_called; +static volatile bool custom_eoi_called; +static volatile bool irq_handler_called; + +/* Define out custom SoC interrupt controller interface methods. + * These closely match the normal Cortex-M implementations. + */ + +#define NUM_IRQS_PER_REG 32 +#define REG_FROM_IRQ(irq) (irq / NUM_IRQS_PER_REG) +#define BIT_FROM_IRQ(irq) (irq % NUM_IRQS_PER_REG) + +void z_soc_irq_init(void) +{ + int irq = 0; + + for (; irq < CONFIG_NUM_IRQS; irq++) { + NVIC_SetPriority((IRQn_Type)irq, _IRQ_PRIO_OFFSET); + } + + custom_init_called = true; +} + +void z_soc_irq_enable(unsigned int irq) +{ + if (irq == sw_irq_number) { + custom_enable_called = true; + } + NVIC_EnableIRQ((IRQn_Type)irq); +} + +void z_soc_irq_disable(unsigned int irq) +{ + if (irq == sw_irq_number) { + custom_disable_called = true; + } + NVIC_DisableIRQ((IRQn_Type)irq); +} + +int z_soc_irq_is_enabled(unsigned int irq) +{ + return NVIC->ISER[REG_FROM_IRQ(irq)] & BIT(BIT_FROM_IRQ(irq)); +} + +void z_soc_irq_eoi(unsigned int irq) +{ + if (irq == sw_irq_number) { + custom_eoi_called = true; + } +} + +inline __attribute__((always_inline)) unsigned int z_soc_irq_get_active(void) +{ + return __get_IPSR(); +} + +void z_soc_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags) +{ + if (irq == sw_irq_number) { + custom_set_priority_called = true; + } + + if (IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) && (flags & IRQ_ZERO_LATENCY)) { + prio = _EXC_ZERO_LATENCY_IRQS_PRIO; + } else { + prio += _IRQ_PRIO_OFFSET; + } + + NVIC_SetPriority((IRQn_Type)irq, prio); +} + +void arm_isr_handler(const void *args) +{ + ARG_UNUSED(args); + +#if defined(CONFIG_CPU_CORTEX_M) && defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) + /* Clear Floating Point Status and Control Register (FPSCR), + * to prevent from having the interrupt line set to pending again, + * in case FPU IRQ is selected by the test as "Available IRQ line" + */ +#if defined(CONFIG_ARMV8_1_M_MAINLINE) + /* + * For ARMv8.1-M with FPU, the FPSCR[18:16] LTPSIZE field must be set + * to 0b100 for "Tail predication not applied" as it's reset value + */ + __set_FPSCR(4 << FPU_FPDSCR_LTPSIZE_Pos); +#else + __set_FPSCR(0); +#endif +#endif + + /* IRQ numbers are offset by 16 on Cortex-M. */ + unsigned int this_irq = z_soc_irq_get_active() - 16; + + TC_PRINT("Got IRQ: %u\n", this_irq); + + zassert_equal(this_irq, sw_irq_number, "Unexpected active IRQ\n"); + irq_handler_called = true; +} + +/** + * @brief Test custom interrupt controller handling with CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER. + * @addtogroup kernel_interrupt_tests + * @ingroup all_tests + * @{ + */ + +ZTEST(arm_custom_interrupt, test_arm_interrupt) +{ + zassert_true(custom_init_called, "Custom IRQ init not called\n"); + + /* Determine an NVIC IRQ line that is not currently in use. */ + int i; + + for (i = CONFIG_NUM_IRQS - 1; i >= 0; i--) { + if (NVIC_GetEnableIRQ(i) == 0) { + /* + * Interrupts configured statically with IRQ_CONNECT(.) + * are automatically enabled. NVIC_GetEnableIRQ() + * returning false, here, implies that the IRQ line is + * either not implemented or it is not enabled, thus, + * currently not in use by Zephyr. + */ + + /* Set the NVIC line to pending. */ + NVIC_SetPendingIRQ(i); + + if (NVIC_GetPendingIRQ(i)) { + /* If the NVIC line is pending, it is + * guaranteed that it is implemented; clear the + * line. + */ + NVIC_ClearPendingIRQ(i); + + if (!NVIC_GetPendingIRQ(i)) { + /* + * If the NVIC line can be successfully + * un-pended, it is guaranteed that it + * can be used for software interrupt + * triggering. + */ + break; + } + } + } + } + + zassert_true(i >= 0, "No available IRQ line to use in the test\n"); + + TC_PRINT("Available IRQ line: %u\n", i); + sw_irq_number = i; + + zassert_false(custom_set_priority_called, "Custom set priority flag set\n"); + arch_irq_connect_dynamic(sw_irq_number, 0 /* highest priority */, arm_isr_handler, NULL, 0); + zassert_true(custom_set_priority_called, "Custom set priority not called\n"); + + NVIC_ClearPendingIRQ(i); + + zassert_false(arch_irq_is_enabled(sw_irq_number), "SW IRQ already enabled\n"); + zassert_false(custom_enable_called, "Custom IRQ enable flag is set\n"); + irq_enable(sw_irq_number); + zassert_true(custom_enable_called, "Custom IRQ enable not called\n"); + zassert_true(arch_irq_is_enabled(sw_irq_number), "SW IRQ is not enabled\n"); + + for (int j = 1; j <= 3; j++) { + custom_eoi_called = false; + irq_handler_called = false; + custom_set_priority_called = false; + + /* Set the dynamic IRQ to pending state. */ + NVIC_SetPendingIRQ(i); + + /* + * Instruction barriers to make sure the NVIC IRQ is + * set to pending state before 'test_flag' is checked. + */ + barrier_dsync_fence_full(); + barrier_isync_fence_full(); + + /* Returning here implies the thread was not aborted. */ + + /* Confirm test flag is set by the ISR handler. */ + zassert_true(custom_eoi_called, "Custom EOI handler not called\n"); + zassert_true(irq_handler_called, "ISR handler not called\n"); + } + + zassert_false(custom_disable_called, "Custom IRQ disable flag is set\n"); + irq_disable(sw_irq_number); + zassert_true(custom_disable_called, "Custom IRQ disable not called\n"); +} + +/** + * @} + */ diff --git a/tests/arch/arm/arm_custom_interrupt/src/main.c b/tests/arch/arm/arm_custom_interrupt/src/main.c new file mode 100644 index 00000000000..e1f3c267965 --- /dev/null +++ b/tests/arch/arm/arm_custom_interrupt/src/main.c @@ -0,0 +1,9 @@ +/* + * Copyright Meta Platforms, Inc. and its affiliates. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +ZTEST_SUITE(arm_custom_interrupt, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/arch/arm/arm_custom_interrupt/testcase.yaml b/tests/arch/arm/arm_custom_interrupt/testcase.yaml new file mode 100644 index 00000000000..d20f87e17ae --- /dev/null +++ b/tests/arch/arm/arm_custom_interrupt/testcase.yaml @@ -0,0 +1,10 @@ +common: + filter: CONFIG_ARMV6_M_ARMV8_M_BASELINE or CONFIG_ARMV7_M_ARMV8_M_MAINLINE + tags: + - arm + - interrupt + ignore_faults: true + arch_allow: arm +tests: + arch.arm.custom_interrupt: + filter: not CONFIG_TRUSTED_EXECUTION_NONSECURE diff --git a/tests/arch/arm/arm_hardfault_validation/prj.conf b/tests/arch/arm/arm_hardfault_validation/prj.conf index 729ee22ed38..396aa78a87d 100644 --- a/tests/arch/arm/arm_hardfault_validation/prj.conf +++ b/tests/arch/arm/arm_hardfault_validation/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT_TEST=y diff --git a/tests/arch/arm/arm_hardfault_validation/testcase.yaml b/tests/arch/arm/arm_hardfault_validation/testcase.yaml index 3294ff9c305..f65fbfdb32a 100644 --- a/tests/arch/arm/arm_hardfault_validation/testcase.yaml +++ b/tests/arch/arm/arm_hardfault_validation/testcase.yaml @@ -1,5 +1,5 @@ tests: - arch.interrupt.arm.hardfault_validation: + arch.arm.interrupt.hardfault_validation: filter: not CONFIG_TRUSTED_EXECUTION_NONSECURE and CONFIG_ARMV7_M_ARMV8_M_MAINLINE arch_allow: arm tags: arm diff --git a/tests/arch/arm/arm_interrupt/prj.conf b/tests/arch/arm/arm_interrupt/prj.conf index 4b453e77cff..5c3b1e83798 100644 --- a/tests/arch/arm/arm_interrupt/prj.conf +++ b/tests/arch/arm/arm_interrupt/prj.conf @@ -3,5 +3,4 @@ CONFIG_DYNAMIC_INTERRUPTS=y CONFIG_TEST_USERSPACE=y CONFIG_APPLICATION_DEFINED_SYSCALL=y CONFIG_IDLE_STACK_SIZE=512 -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT_TEST=y diff --git a/tests/arch/arm/arm_interrupt/src/arm_interrupt.c b/tests/arch/arm/arm_interrupt/src/arm_interrupt.c index 6ef95fb0185..1bbfe08bc01 100644 --- a/tests/arch/arm/arm_interrupt/src/arm_interrupt.c +++ b/tests/arch/arm/arm_interrupt/src/arm_interrupt.c @@ -125,8 +125,12 @@ void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) * In k_sys_fatal_error_handler above we will check that the ESF provided * as a parameter matches these expectations. */ -void set_regs_with_known_pattern(void) +void set_regs_with_known_pattern(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + __asm__ volatile( "mov r1, #1\n" "mov r2, #2\n" @@ -178,7 +182,7 @@ ZTEST(arm_interrupt, test_arm_esf_collection) TC_PRINT("Testing ESF Reporting\n"); k_thread_create(&esf_collection_thread, esf_collection_stack, K_THREAD_STACK_SIZEOF(esf_collection_stack), - (k_thread_entry_t)set_regs_with_known_pattern, + set_regs_with_known_pattern, NULL, NULL, NULL, K_PRIO_COOP(PRIORITY), 0, K_NO_WAIT); @@ -378,7 +382,7 @@ ZTEST(arm_interrupt, test_arm_interrupt) } #if defined(CONFIG_USERSPACE) -#include +#include #include "test_syscalls.h" void z_impl_test_arm_user_interrupt_syscall(void) diff --git a/tests/arch/arm/arm_interrupt/testcase.yaml b/tests/arch/arm/arm_interrupt/testcase.yaml index 9c92b947631..4895e2a90cc 100644 --- a/tests/arch/arm/arm_interrupt/testcase.yaml +++ b/tests/arch/arm/arm_interrupt/testcase.yaml @@ -7,16 +7,16 @@ common: ignore_faults: true arch_allow: arm tests: - arch.interrupt.arm: + arch.arm.interrupt: filter: not CONFIG_TRUSTED_EXECUTION_NONSECURE - arch.interrupt.no_optimizations: + arch.arm.interrupt.no_optimizations: filter: not CONFIG_TRUSTED_EXECUTION_NONSECURE extra_configs: - CONFIG_NO_OPTIMIZATIONS=y - CONFIG_ZTEST_WARN_NO_OPTIMIZATIONS=n - CONFIG_IDLE_STACK_SIZE=512 - CONFIG_MAIN_STACK_SIZE=2048 - arch.interrupt.extra_exception_info: + arch.arm.interrupt.extra_exception_info: filter: not CONFIG_TRUSTED_EXECUTION_NONSECURE extra_configs: - CONFIG_EXTRA_EXCEPTION_INFO=y diff --git a/tests/arch/arm/arm_irq_advanced_features/prj.conf b/tests/arch/arm/arm_irq_advanced_features/prj.conf index ff88b08e88b..c5c24cf5873 100644 --- a/tests/arch/arm/arm_irq_advanced_features/prj.conf +++ b/tests/arch/arm/arm_irq_advanced_features/prj.conf @@ -2,4 +2,3 @@ CONFIG_ZTEST=y CONFIG_DYNAMIC_INTERRUPTS=y CONFIG_DYNAMIC_DIRECT_INTERRUPTS=y CONFIG_ZERO_LATENCY_IRQS=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/arch/arm/arm_irq_vector_table/irq-vector-table.ld b/tests/arch/arm/arm_irq_vector_table/irq-vector-table.ld index 833b94a26b0..5f25268a2c7 100644 --- a/tests/arch/arm/arm_irq_vector_table/irq-vector-table.ld +++ b/tests/arch/arm/arm_irq_vector_table/irq-vector-table.ld @@ -5,6 +5,6 @@ KEEP(*(_IRQ_VECTOR_TABLE_SECTION_SYMS)) /* * Some ARM platforms require this symbol to be placed after the IRQ vector * table (like STM32F0). The symbol defined here is overriding the one in - * arch/arm/core/aarch32/vector_table.ld when the IRQ vector table is enabled. + * arch/arm/core/vector_table.ld when the IRQ vector table is enabled. */ _vector_end = .; diff --git a/tests/arch/arm/arm_irq_vector_table/prj.conf b/tests/arch/arm/arm_irq_vector_table/prj.conf index 28479ac0577..74a22e9196a 100644 --- a/tests/arch/arm/arm_irq_vector_table/prj.conf +++ b/tests/arch/arm/arm_irq_vector_table/prj.conf @@ -1,6 +1,5 @@ CONFIG_ZTEST=y CONFIG_GEN_ISR_TABLES=n CONFIG_NUM_IRQS=3 -CONFIG_ZTEST_NEW_API=y # Force Bluetooth disable (required by platforms that enable Bluetooth by default) CONFIG_BT=n diff --git a/tests/arch/arm/arm_irq_vector_table/testcase.yaml b/tests/arch/arm/arm_irq_vector_table/testcase.yaml index c570d1a0488..62a6bb7e912 100644 --- a/tests/arch/arm/arm_irq_vector_table/testcase.yaml +++ b/tests/arch/arm/arm_irq_vector_table/testcase.yaml @@ -8,3 +8,6 @@ common: tests: arch.arm.irq_vector_table: filter: not CONFIG_TRUSTED_EXECUTION_NONSECURE + platform_exclude: + - mr_canhubk3 + - arduino_uno_r4_minima diff --git a/tests/arch/arm/arm_irq_zero_latency_levels/prj.conf b/tests/arch/arm/arm_irq_zero_latency_levels/prj.conf index 68622c39af1..b6165cdbc99 100644 --- a/tests/arch/arm/arm_irq_zero_latency_levels/prj.conf +++ b/tests/arch/arm/arm_irq_zero_latency_levels/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_DYNAMIC_INTERRUPTS=y CONFIG_DYNAMIC_DIRECT_INTERRUPTS=y CONFIG_ZERO_LATENCY_IRQS=y diff --git a/tests/arch/arm/arm_mem_protect/prj.conf b/tests/arch/arm/arm_mem_protect/prj.conf index 3971afe4e55..e39776e7067 100644 --- a/tests/arch/arm/arm_mem_protect/prj.conf +++ b/tests/arch/arm/arm_mem_protect/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y diff --git a/tests/arch/arm/arm_mem_protect/src/main.c b/tests/arch/arm/arm_mem_protect/src/main.c index 45e2314a989..83b96cf9d0f 100644 --- a/tests/arch/arm/arm_mem_protect/src/main.c +++ b/tests/arch/arm/arm_mem_protect/src/main.c @@ -4,7 +4,7 @@ */ #include -#include +#include #include ZTEST_BMEM char user_stack[256]; diff --git a/tests/arch/arm/arm_mpu_regions/CMakeLists.txt b/tests/arch/arm/arm_mpu_regions/CMakeLists.txt deleted file mode 100644 index b847ef0b65d..00000000000 --- a/tests/arch/arm/arm_mpu_regions/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) - -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(arm_mpu_regions) - -target_sources(app PRIVATE src/main.c) diff --git a/tests/arch/arm/arm_mpu_regions/boards/mps2_an385.overlay b/tests/arch/arm/arm_mpu_regions/boards/mps2_an385.overlay deleted file mode 100644 index 4c9f1a5d5a8..00000000000 --- a/tests/arch/arm/arm_mpu_regions/boards/mps2_an385.overlay +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2021 Carlo Caione - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/ { - /delete-node/ memory@20000000; - - sram0: memory@20000000 { - compatible = "mmio-sram"; - reg = <0x20000000 0x200000>; - }; - - sram_cache: memory@20200000 { - compatible = "zephyr,memory-region", "mmio-sram"; - reg = <0x20200000 0x100000>; - zephyr,memory-region = "SRAM_CACHE"; - zephyr,memory-attr = "RAM"; - }; - - sram_no_cache: memory@20300000 { - compatible = "zephyr,memory-region", "mmio-sram"; - reg = <0x20300000 0x100000>; - zephyr,memory-region = "SRAM_NO_CACHE"; - zephyr,memory-attr = "RAM_NOCACHE"; - }; - - sram_dtcm_fake: memory@abcdabcd { - compatible = "zephyr,memory-region", "arm,dtcm"; - reg = <0xabcdabcd 0x100000>; - zephyr,memory-region = "SRAM_DTCM_FAKE"; - zephyr,memory-attr = "RAM"; - }; - - sram_no_mpu: memory@deaddead { - compatible = "zephyr,memory-region", "mmio-sram"; - reg = <0xdeaddead 0x100000>; - zephyr,memory-region = "SRAM_NO_MPU"; - }; -}; diff --git a/tests/arch/arm/arm_mpu_regions/prj.conf b/tests/arch/arm/arm_mpu_regions/prj.conf deleted file mode 100644 index 9228251051e..00000000000 --- a/tests/arch/arm/arm_mpu_regions/prj.conf +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/arch/arm/arm_mpu_regions/src/main.c b/tests/arch/arm/arm_mpu_regions/src/main.c deleted file mode 100644 index ec784787bb4..00000000000 --- a/tests/arch/arm/arm_mpu_regions/src/main.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2021 Carlo Caione - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include - -extern const struct arm_mpu_config mpu_config; - -static arm_mpu_region_attr_t cacheable = REGION_RAM_ATTR(REGION_1M); -static arm_mpu_region_attr_t noncacheable = REGION_RAM_NOCACHE_ATTR(REGION_1M); - -ZTEST(test_c_arm_mpu_regions, test_regions) -{ - int cnt = 0; - - for (size_t i = 0; i < mpu_config.num_regions; i++) { - const struct arm_mpu_region *r = &mpu_config.mpu_regions[i]; - - if (!strcmp(r->name, "SRAM_CACHE")) { - zassert_equal(r->base, 0x20200000, "Wrong base"); - zassert_equal(r->attr.rasr, cacheable.rasr, - "Wrong attr for SRAM_CACHE"); - cnt++; - } else if (!strcmp(r->name, "SRAM_NO_CACHE")) { - zassert_equal(r->base, 0x20300000, "Wrong base"); - zassert_equal(r->attr.rasr, noncacheable.rasr, - "Wrong attr for SRAM_NO_CACHE"); - cnt++; - } else if (!strcmp(r->name, "SRAM_DTCM_FAKE")) { - zassert_equal(r->base, 0xabcdabcd, "Wrong base"); - zassert_equal(r->attr.rasr, cacheable.rasr, - "Wrong attr for SRAM_DTCM_FAKE"); - cnt++; - } - } - - if (cnt != 3) { - /* - * SRAM0 and SRAM_NO_MPU should not create any MPU region. - * Check that. - */ - ztest_test_fail(); - } -} - -ZTEST_SUITE(test_c_arm_mpu_regions, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/arch/arm/arm_mpu_regions/testcase.yaml b/tests/arch/arm/arm_mpu_regions/testcase.yaml deleted file mode 100644 index b04c2689137..00000000000 --- a/tests/arch/arm/arm_mpu_regions/testcase.yaml +++ /dev/null @@ -1,6 +0,0 @@ -tests: - arch.mpu_regions.arm: - platform_allow: mps2_an385 - tags: - - sram - - mpu diff --git a/tests/arch/arm/arm_no_multithreading/prj.conf b/tests/arch/arm/arm_no_multithreading/prj.conf index 65dd4e51c05..33e8aebc274 100644 --- a/tests/arch/arm/arm_no_multithreading/prj.conf +++ b/tests/arch/arm/arm_no_multithreading/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MULTITHREADING=n CONFIG_ASSERT=y CONFIG_FPU=y diff --git a/tests/arch/arm/arm_ramfunc/CMakeLists.txt b/tests/arch/arm/arm_ramfunc/CMakeLists.txt deleted file mode 100644 index 8aa6ed15e73..00000000000 --- a/tests/arch/arm/arm_ramfunc/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) - -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(arm_zero_latency_irqs) - -FILE(GLOB app_sources src/*.c) -target_sources(app PRIVATE ${app_sources}) diff --git a/tests/arch/arm/arm_ramfunc/README.txt b/tests/arch/arm/arm_ramfunc/README.txt deleted file mode 100644 index ba68130faf8..00000000000 --- a/tests/arch/arm/arm_ramfunc/README.txt +++ /dev/null @@ -1,45 +0,0 @@ -Title: Test to verify code execution from SRAM for XIP images (ARM Only) - -Description: - -This test verifies that we can define functions in SRAM (and -successfully execute them from SRAM) in ARM XIP images. It -also verifies that the .ramfunc section is accessible by -nPRIV code when building with support for user mode -(CONFIG_TEST_USERSPACE=y). Only for ARM Cortex-M targets. - ---------------------------------------------------------------------------- - -Building and Running Project: - -This project outputs to the console. It can be built and executed on QEMU as -follows: - - ninja/make run - ---------------------------------------------------------------------------- - -Troubleshooting: - -Problems caused by out-dated project information can be addressed by -issuing one of the following commands then rebuilding the project: - - ninja/make clean # discard results of previous builds - # but keep existing configuration info -or - ninja/make pristine # discard results of previous builds - # and restore pre-defined configuration info - ---------------------------------------------------------------------------- - -Sample Output: - -***** Booting Zephyr OS build zephyr-v1.14.0-1726-gb95a71960622 ***** -Running test suite arm_ramfunc -=================================================================== -starting test - test_arm_ramfunc -PASS - test_arm_ramfunc -=================================================================== -Test suite arm_ramfunc succeeded -=================================================================== -PROJECT EXECUTION SUCCESSFUL diff --git a/tests/arch/arm/arm_ramfunc/prj.conf b/tests/arch/arm/arm_ramfunc/prj.conf deleted file mode 100644 index 04099e417a1..00000000000 --- a/tests/arch/arm/arm_ramfunc/prj.conf +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_ZTEST=y -CONFIG_TEST_USERSPACE=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/arch/arm/arm_ramfunc/src/arm_ramfunc.c b/tests/arch/arm/arm_ramfunc/src/arm_ramfunc.c deleted file mode 100644 index 10790b556d0..00000000000 --- a/tests/arch/arm/arm_ramfunc/src/arm_ramfunc.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019 Nordic Semiconductor ASA. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include - -static volatile int test_flag; - -__ramfunc static void arm_ram_function(void) -{ - test_flag = 1; -} - -ZTEST(arm_ramfunc, test_arm_ramfunc) -{ - int init_flag, post_flag; - - init_flag = test_flag; - zassert_true(init_flag == 0, "Test flag not initialized to zero"); - - /* Verify that the .ramfunc section is not empty, it is located - * inside SRAM, and that arm_ram_function(.) is located inside - * the .ramfunc section. - */ - zassert_true((uint32_t)&__ramfunc_size != 0, - ".ramfunc linker section is empty"); - zassert_true(((uint32_t)&__ramfunc_start >= (uint32_t)&_image_ram_start) - && ((uint32_t)&__ramfunc_end < (uint32_t)&_image_ram_end), - ".ramfunc linker section not in RAM"); - zassert_true( - (((uint32_t)&__ramfunc_start) <= (uint32_t)arm_ram_function) && - (((uint32_t)&__ramfunc_end) > (uint32_t)arm_ram_function), - "arm_ram_function not loaded into .ramfunc"); - - /* If we build with User Mode support, verify that the - * arm_ram_function(.) is user (read) accessible. - */ -#if defined(CONFIG_USERSPACE) - zassert_true(arch_buffer_validate((void *)&__ramfunc_start, - (size_t)&__ramfunc_size, 0) == 0 /* Success */, - ".ramfunc section not user accessible"); -#endif /* CONFIG_USERSPACE */ - - /* Execute the function from SRAM. */ - arm_ram_function(); - - /* Verify that the function is executed successfully. */ - post_flag = test_flag; - zassert_true(post_flag == 1, - "arm_ram_function() execution failed."); -} -/** - * @} - */ diff --git a/tests/arch/arm/arm_ramfunc/src/main.c b/tests/arch/arm/arm_ramfunc/src/main.c deleted file mode 100644 index a75dc004b7e..00000000000 --- a/tests/arch/arm/arm_ramfunc/src/main.c +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (c) 2019 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#if !defined(CONFIG_CPU_CORTEX_M) - #error test can only run on Cortex-M MCUs -#endif - -#include - -ZTEST_SUITE(arm_ramfunc, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/arch/arm/arm_ramfunc/testcase.yaml b/tests/arch/arm/arm_ramfunc/testcase.yaml deleted file mode 100644 index 49e97deaf58..00000000000 --- a/tests/arch/arm/arm_ramfunc/testcase.yaml +++ /dev/null @@ -1,9 +0,0 @@ -tests: - arch.arm.ramfunc: - filter: CONFIG_ARCH_HAS_RAMFUNC_SUPPORT - tags: - - arm - - userspace - arch_allow: arm - extra_configs: - - CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 diff --git a/tests/arch/arm/arm_runtime_nmi/prj.conf b/tests/arch/arm/arm_runtime_nmi/prj.conf index 5662b1aa1b7..e5c468604ab 100644 --- a/tests/arch/arm/arm_runtime_nmi/prj.conf +++ b/tests/arch/arm/arm_runtime_nmi/prj.conf @@ -1,3 +1,2 @@ CONFIG_RUNTIME_NMI=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/arch/arm/arm_runtime_nmi/src/arm_runtime_nmi.c b/tests/arch/arm/arm_runtime_nmi/src/arm_runtime_nmi.c index 870993c59e7..79a4bbedca3 100644 --- a/tests/arch/arm/arm_runtime_nmi/src/arm_runtime_nmi.c +++ b/tests/arch/arm/arm_runtime_nmi/src/arm_runtime_nmi.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include diff --git a/tests/arch/arm/arm_runtime_nmi/testcase.yaml b/tests/arch/arm/arm_runtime_nmi/testcase.yaml index 34e95fe6f74..55706b0fedd 100644 --- a/tests/arch/arm/arm_runtime_nmi/testcase.yaml +++ b/tests/arch/arm/arm_runtime_nmi/testcase.yaml @@ -1,5 +1,5 @@ tests: - arch.interrupt.arm.nmi: + arch.arm.interrupt.nmi: filter: CONFIG_ARMV6_M_ARMV8_M_BASELINE or CONFIG_ARMV7_M_ARMV8_M_MAINLINE and not CONFIG_BUILD_WITH_TFM arch_allow: arm diff --git a/tests/arch/arm/arm_sw_vector_relay/prj.conf b/tests/arch/arm/arm_sw_vector_relay/prj.conf index a36923beda2..fd20f02d7ad 100644 --- a/tests/arch/arm/arm_sw_vector_relay/prj.conf +++ b/tests/arch/arm/arm_sw_vector_relay/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y CONFIG_SW_VECTOR_RELAY=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/arch/arm/arm_sw_vector_relay/src/arm_sw_vector_relay.c b/tests/arch/arm/arm_sw_vector_relay/src/arm_sw_vector_relay.c index c728864c05f..be400746d92 100644 --- a/tests/arch/arm/arm_sw_vector_relay/src/arm_sw_vector_relay.c +++ b/tests/arch/arm/arm_sw_vector_relay/src/arm_sw_vector_relay.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include diff --git a/tests/arch/arm/arm_thread_swap/prj.conf b/tests/arch/arm/arm_thread_swap/prj.conf index a618b61b5ad..df696389344 100644 --- a/tests/arch/arm/arm_thread_swap/prj.conf +++ b/tests/arch/arm/arm_thread_swap/prj.conf @@ -1,6 +1,5 @@ CONFIG_ZTEST=y CONFIG_DYNAMIC_INTERRUPTS=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y CONFIG_APPLICATION_DEFINED_SYSCALL=y CONFIG_MAIN_STACK_SIZE=1024 diff --git a/tests/arch/arm/arm_thread_swap/src/arm_syscalls.c b/tests/arch/arm/arm_thread_swap/src/arm_syscalls.c index ec642909573..e32de6ca726 100644 --- a/tests/arch/arm/arm_thread_swap/src/arm_syscalls.c +++ b/tests/arch/arm/arm_thread_swap/src/arm_syscalls.c @@ -29,7 +29,7 @@ static struct k_thread user_thread; static K_THREAD_STACK_DEFINE(user_thread_stack, 1024); -#include +#include #include "test_syscalls.h" void z_impl_test_arm_user_syscall(void) @@ -119,8 +119,12 @@ void arm_isr_handler(const void *args) } } -static void user_thread_entry(uint32_t irq_line) +static void user_thread_entry(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + uint32_t irq_line = POINTER_TO_INT(p1); /* User Thread */ #if !defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) ARG_UNUSED(irq_line); @@ -234,7 +238,7 @@ ZTEST(arm_thread_swap, test_arm_syscalls) k_thread_create(&user_thread, user_thread_stack, K_THREAD_STACK_SIZEOF(user_thread_stack), - (k_thread_entry_t)user_thread_entry, + user_thread_entry, (uint32_t *)i, NULL, NULL, K_PRIO_COOP(PRIORITY), K_USER, K_NO_WAIT); diff --git a/tests/arch/arm/arm_thread_swap/src/arm_thread_arch.c b/tests/arch/arm/arm_thread_swap/src/arm_thread_arch.c index 0c98869bbed..f299ce4c4a0 100644 --- a/tests/arch/arm/arm_thread_swap/src/arm_thread_arch.c +++ b/tests/arch/arm/arm_thread_swap/src/arm_thread_arch.c @@ -221,8 +221,12 @@ static void verify_fp_callee_saved(const struct _preempt_float *src, #define ALT_THREAD_OPTIONS 0 #endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ -static void alt_thread_entry(void) +static void alt_thread_entry(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + int init_flag, post_flag; /* Lock interrupts to make sure we get preempted only when @@ -530,7 +534,7 @@ ZTEST(arm_thread_swap, test_arm_thread_swap) k_thread_create(&alt_thread, alt_thread_stack, K_THREAD_STACK_SIZEOF(alt_thread_stack), - (k_thread_entry_t)alt_thread_entry, + alt_thread_entry, NULL, NULL, NULL, K_PRIO_COOP(PRIORITY), ALT_THREAD_OPTIONS, K_NO_WAIT); diff --git a/tests/arch/arm/arm_thread_swap_tz/prj.conf b/tests/arch/arm/arm_thread_swap_tz/prj.conf index 5839417932f..e5fce445828 100644 --- a/tests/arch/arm/arm_thread_swap_tz/prj.conf +++ b/tests/arch/arm/arm_thread_swap_tz/prj.conf @@ -11,5 +11,4 @@ CONFIG_TFM_IPC=y CONFIG_FPU=y CONFIG_FPU_SHARING=y CONFIG_TFM_PROFILE_TYPE_NOT_SET=y -CONFIG_ZTEST_NEW_API=y CONFIG_QEMU_ICOUNT_SHIFT=8 diff --git a/tests/arch/arm/arm_tz_wrap_func/prj.conf b/tests/arch/arm/arm_tz_wrap_func/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/arch/arm/arm_tz_wrap_func/prj.conf +++ b/tests/arch/arm/arm_tz_wrap_func/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/arch/arm/arm_tz_wrap_func/src/main.c b/tests/arch/arm/arm_tz_wrap_func/src/main.c index 0323bd50617..407873f906b 100644 --- a/tests/arch/arm/arm_tz_wrap_func/src/main.c +++ b/tests/arch/arm/arm_tz_wrap_func/src/main.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include static bool expect_preface; diff --git a/tests/arch/arm64/arm64_gicv3_its/prj.conf b/tests/arch/arm64/arm64_gicv3_its/prj.conf index 91e91fc99b7..178daa8fc44 100644 --- a/tests/arch/arm64/arm64_gicv3_its/prj.conf +++ b/tests/arch/arm64/arm64_gicv3_its/prj.conf @@ -1,4 +1,3 @@ CONFIG_LOG=y CONFIG_ZTEST=y CONFIG_GIC_V3_ITS=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/arch/arm64/arm64_high_addresses/prj.conf b/tests/arch/arm64/arm64_high_addresses/prj.conf index 41614cd2a01..cc08fb4b743 100644 --- a/tests/arch/arm64/arm64_high_addresses/prj.conf +++ b/tests/arch/arm64/arm64_high_addresses/prj.conf @@ -5,4 +5,3 @@ CONFIG_LOG=y CONFIG_LOG_MODE_MINIMAL=y CONFIG_MAIN_STACK_SIZE=2560 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/arch/arm64/arm64_psci/prj.conf b/tests/arch/arm64/arm64_psci/prj.conf index 0f96f29acbf..232de93ca9d 100644 --- a/tests/arch/arm64/arm64_psci/prj.conf +++ b/tests/arch/arm64/arm64_psci/prj.conf @@ -1,3 +1,2 @@ CONFIG_TEST_USERSPACE=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/arch/arm64/arm64_smc_call/prj.conf b/tests/arch/arm64/arm64_smc_call/prj.conf index 0f96f29acbf..232de93ca9d 100644 --- a/tests/arch/arm64/arm64_smc_call/prj.conf +++ b/tests/arch/arm64/arm64_smc_call/prj.conf @@ -1,3 +1,2 @@ CONFIG_TEST_USERSPACE=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/arch/arm64/arm64_smc_call/src/main.c b/tests/arch/arm64/arm64_smc_call/src/main.c index 01589656e7c..ac397bf6289 100644 --- a/tests/arch/arm64/arm64_smc_call/src/main.c +++ b/tests/arch/arm64/arm64_smc_call/src/main.c @@ -5,7 +5,7 @@ #include -#include "zephyr/arch/arm64/arm-smccc.h" +#include /* SMC function IDs for Standard Service queries */ #define ARM_STD_SMC_CALL_COUNT 0x8400ff00UL diff --git a/tests/arch/common/ramfunc/CMakeLists.txt b/tests/arch/common/ramfunc/CMakeLists.txt new file mode 100644 index 00000000000..972d08e7e75 --- /dev/null +++ b/tests/arch/common/ramfunc/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(zero_latency_irqs) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/arch/common/ramfunc/README.txt b/tests/arch/common/ramfunc/README.txt new file mode 100644 index 00000000000..f5f2b7949f1 --- /dev/null +++ b/tests/arch/common/ramfunc/README.txt @@ -0,0 +1,53 @@ +Title: Test to verify code execution from SRAM for XIP images (only on supported architectures with CONFIG_ARCH_HAS_RAMFUNC_SUPPORT=y) + +Description: + +This test verifies that we can define functions in SRAM (and +successfully execute them from SRAM) in XIP images. It +also verifies that the .ramfunc section is accessible by +user space code when building with support for user mode +(CONFIG_TEST_USERSPACE=y). + +--------------------------------------------------------------------------- + +Building and Running Project: + +This project outputs to the console. It can be built and executed on QEMU as +follows: + + ninja/make run + +--------------------------------------------------------------------------- + +Troubleshooting: + +Problems caused by out-dated project information can be addressed by +issuing one of the following commands then rebuilding the project: + + ninja/make clean # discard results of previous builds + # but keep existing configuration info +or + ninja/make pristine # discard results of previous builds + # and restore pre-defined configuration info + +--------------------------------------------------------------------------- + +Sample Output: + +*** Booting Zephyr OS build zephyr-v3.4.0-4114-gadfd4017979f *** +Running TESTSUITE ramfunc +=================================================================== +START - test_ramfunc + PASS - test_ramfunc in 0.229 seconds +=================================================================== +TESTSUITE ramfunc succeeded + +------ TESTSUITE SUMMARY START ------ + +SUITE PASS - 100.00% [ramfunc]: pass = 1, fail = 0, skip = 0, total = 1 duration = 0.229 seconds + - PASS - [ramfunc.test_ramfunc] duration = 0.229 seconds + +------ TESTSUITE SUMMARY END ------ + +=================================================================== +PROJECT EXECUTION SUCCESSFUL diff --git a/tests/arch/arm/arm_ramfunc/boards/arty_a7_arm_designstart_m1.overlay b/tests/arch/common/ramfunc/boards/arty_a7_arm_designstart_m1.overlay similarity index 100% rename from tests/arch/arm/arm_ramfunc/boards/arty_a7_arm_designstart_m1.overlay rename to tests/arch/common/ramfunc/boards/arty_a7_arm_designstart_m1.overlay diff --git a/tests/arch/common/ramfunc/prj.conf b/tests/arch/common/ramfunc/prj.conf new file mode 100644 index 00000000000..e39776e7067 --- /dev/null +++ b/tests/arch/common/ramfunc/prj.conf @@ -0,0 +1,2 @@ +CONFIG_ZTEST=y +CONFIG_TEST_USERSPACE=y diff --git a/tests/arch/common/ramfunc/src/main.c b/tests/arch/common/ramfunc/src/main.c new file mode 100644 index 00000000000..f136c3ba992 --- /dev/null +++ b/tests/arch/common/ramfunc/src/main.c @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2019 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#if !defined(CONFIG_ARCH_HAS_RAMFUNC_SUPPORT) + #error test can only run on Cortex-M MCUs and RISC-V +#endif + +ZTEST_SUITE(ramfunc, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/arch/common/ramfunc/src/ramfunc.c b/tests/arch/common/ramfunc/src/ramfunc.c new file mode 100644 index 00000000000..cd55c653618 --- /dev/null +++ b/tests/arch/common/ramfunc/src/ramfunc.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2019 Nordic Semiconductor ASA. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +static volatile int test_flag; + +__ramfunc static void ram_function(void) +{ + test_flag = 1; +} + +ZTEST(ramfunc, test_ramfunc) +{ + int init_flag, post_flag; + + init_flag = test_flag; + zassert_true(init_flag == 0, "Test flag not initialized to zero"); + + /* Verify that the .ramfunc section is not empty, it is located + * inside SRAM, and that ram_function(.) is located inside + * the .ramfunc section. + */ + zassert_true((uint32_t)&__ramfunc_size != 0, + ".ramfunc linker section is empty"); + zassert_true(((uint32_t)&__ramfunc_start >= (uint32_t)&_image_ram_start) + && ((uint32_t)&__ramfunc_end < (uint32_t)&_image_ram_end), + ".ramfunc linker section not in RAM"); + zassert_true( + (((uint32_t)&__ramfunc_start) <= (uint32_t)ram_function) && + (((uint32_t)&__ramfunc_end) > (uint32_t)ram_function), + "ram_function not loaded into .ramfunc"); + + /* If we build with User Mode support, verify that the + * ram_function(.) is user (read) accessible. + */ +#if defined(CONFIG_USERSPACE) + zassert_true(arch_buffer_validate((void *)&__ramfunc_start, + (size_t)&__ramfunc_size, 0) == 0 /* Success */, + ".ramfunc section not user accessible"); +#endif /* CONFIG_USERSPACE */ + + /* Execute the function from SRAM. */ + ram_function(); + + /* Verify that the function is executed successfully. */ + post_flag = test_flag; + zassert_true(post_flag == 1, + "ram_function() execution failed."); +} +/** + * @} + */ diff --git a/tests/arch/common/ramfunc/testcase.yaml b/tests/arch/common/ramfunc/testcase.yaml new file mode 100644 index 00000000000..542926dc21b --- /dev/null +++ b/tests/arch/common/ramfunc/testcase.yaml @@ -0,0 +1,12 @@ +tests: + arch.common.ramfunc: + filter: CONFIG_ARCH_HAS_RAMFUNC_SUPPORT + tags: + - arm + - userspace + arch_allow: + - arm + - riscv32 + - riscv64 + extra_configs: + - CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 diff --git a/tests/arch/common/semihost/prj.conf b/tests/arch/common/semihost/prj.conf index afb77490fa9..071acb7c66f 100644 --- a/tests/arch/common/semihost/prj.conf +++ b/tests/arch/common/semihost/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SEMIHOST=y diff --git a/tests/arch/common/timing/prj.conf b/tests/arch/common/timing/prj.conf index df10e05a4ce..f483da96cd7 100644 --- a/tests/arch/common/timing/prj.conf +++ b/tests/arch/common/timing/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TIMING_FUNCTIONS=y CONFIG_FPU=y CONFIG_SCHED_CPU_MASK=y diff --git a/tests/arch/riscv/fpu_sharing/prj.conf b/tests/arch/riscv/fpu_sharing/prj.conf index f9caa918d65..ebec0da18b6 100644 --- a/tests/arch/riscv/fpu_sharing/prj.conf +++ b/tests/arch/riscv/fpu_sharing/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_FPU=y CONFIG_FPU_SHARING=y CONFIG_IRQ_OFFLOAD=y diff --git a/tests/arch/riscv/fpu_sharing/src/main.c b/tests/arch/riscv/fpu_sharing/src/main.c index db44fe34c47..55ab1a2e4a0 100644 --- a/tests/arch/riscv/fpu_sharing/src/main.c +++ b/tests/arch/riscv/fpu_sharing/src/main.c @@ -417,6 +417,34 @@ ZTEST(riscv_fpu_sharing, test_fp_insn_trap) "got %#llx instead", buf64); #endif #endif /* CONFIG_RISCV_ISA_EXT_C */ + + /* MADD major opcode space */ + reg = 3579; + TEST_TRAP("fcvt.s.w fa1, %0"); + TEST_TRAP("fmadd.s fa0, fa1, fa1, fa1"); + TEST_TRAP("fcvt.w.s %0, fa0"); + zassert_true(reg == 12812820, "got %ld instead", reg); + + /* MSUB major opcode space */ + reg = 1234; + TEST_TRAP("fcvt.s.w fa1, %0"); + TEST_TRAP("fmsub.s fa0, fa1, fa1, fa0"); + TEST_TRAP("fcvt.w.s %0, fa0"); + zassert_true(reg == -11290064, "got %ld instead", reg); + + /* NMSUB major opcode space */ + reg = -23; + TEST_TRAP("fcvt.s.w fa1, %0"); + TEST_TRAP("fnmsub.s fa0, fa1, fa1, fa0"); + TEST_TRAP("fcvt.w.s %0, fa0"); + zassert_true(reg == -11290593, "got %ld instead", reg); + + /* NMADD major opcode space */ + reg = 765; + TEST_TRAP("fcvt.s.w fa1, %0"); + TEST_TRAP("fnmadd.s fa0, fa1, fa1, fa1"); + TEST_TRAP("fcvt.w.s %0, fa0"); + zassert_true(reg == -585990, "got %ld instead", reg); } ZTEST_SUITE(riscv_fpu_sharing, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/arch/x86/cpu_scrubs_regs/prj.conf b/tests/arch/x86/cpu_scrubs_regs/prj.conf index 9f61e775c1b..6f61be1eff5 100644 --- a/tests/arch/x86/cpu_scrubs_regs/prj.conf +++ b/tests/arch/x86/cpu_scrubs_regs/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y CONFIG_APPLICATION_DEFINED_SYSCALL=y diff --git a/tests/arch/x86/cpu_scrubs_regs/src/main.c b/tests/arch/x86/cpu_scrubs_regs/src/main.c index bddcc4f7929..6c27f73cd1b 100644 --- a/tests/arch/x86/cpu_scrubs_regs/src/main.c +++ b/tests/arch/x86/cpu_scrubs_regs/src/main.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include "test_syscalls.h" diff --git a/tests/arch/x86/direct_isr/prj.conf b/tests/arch/x86/direct_isr/prj.conf index 1d84481424d..ebc05bbae73 100644 --- a/tests/arch/x86/direct_isr/prj.conf +++ b/tests/arch/x86/direct_isr/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_THREAD_STACK_INFO=y diff --git a/tests/arch/x86/info/CMakeLists.txt b/tests/arch/x86/info/CMakeLists.txt index a8c8dcdf1ad..7a6c14f12d3 100644 --- a/tests/arch/x86/info/CMakeLists.txt +++ b/tests/arch/x86/info/CMakeLists.txt @@ -8,6 +8,6 @@ project(x86_info) target_sources(app PRIVATE src/main.c) target_sources(app PRIVATE src/timer.c) -target_sources_ifdef(CONFIG_X86_ACPI app PRIVATE src/acpi.c) +target_sources_ifdef(CONFIG_ACPI app PRIVATE src/acpi.c) target_sources_ifdef(CONFIG_MULTIBOOT app PRIVATE src/multiboot.c) target_sources_ifdef(CONFIG_X86_MEMMAP app PRIVATE src/memmap.c) diff --git a/tests/arch/x86/info/prj.conf b/tests/arch/x86/info/prj.conf index 4e89c3de68a..bb56a340a7e 100644 --- a/tests/arch/x86/info/prj.conf +++ b/tests/arch/x86/info/prj.conf @@ -1,4 +1,4 @@ -CONFIG_X86_ACPI=y +CONFIG_ACPI=y CONFIG_MULTIBOOT_INFO=y CONFIG_MULTIBOOT_MEMMAP=y CONFIG_COUNTER=y diff --git a/tests/arch/x86/info/src/acpi.c b/tests/arch/x86/info/src/acpi.c index e8501bc3ef2..eae7d560c7d 100644 --- a/tests/arch/x86/info/src/acpi.c +++ b/tests/arch/x86/info/src/acpi.c @@ -4,30 +4,33 @@ */ #include -#include +#include -static void vtd_dev_scope_info(struct acpi_dmar_dev_scope *dev_scope) +static const uint32_t dmar_scope[] = {ACPI_DMAR_SCOPE_TYPE_ENDPOINT, ACPI_DMAR_SCOPE_TYPE_BRIDGE, + ACPI_DMAR_SCOPE_TYPE_IOAPIC, ACPI_DMAR_SCOPE_TYPE_HPET, + ACPI_DMAR_SCOPE_TYPE_NAMESPACE}; + +static void vtd_dev_scope_info(int type, struct acpi_dmar_device_scope *dev_scope, + union acpi_dmar_id *dmar_id, int num_inst) { - struct acpi_dmar_dev_path *path; - uint16_t id; - int n_path; + int i = 0; printk("\t\t\t. Type: "); - switch (dev_scope->type) { - case ACPI_DRHD_DEV_SCOPE_PCI_EPD: + switch (type) { + case ACPI_DMAR_SCOPE_TYPE_ENDPOINT: printk("PCI Endpoint"); break; - case ACPI_DRHD_DEV_SCOPE_PCI_SUB_H: + case ACPI_DMAR_SCOPE_TYPE_BRIDGE: printk("PCI Sub-hierarchy"); break; - case ACPI_DRHD_DEV_SCOPE_IOAPIC: - printk("IOAPIC"); + case ACPI_DMAR_SCOPE_TYPE_IOAPIC: + break; - case ACPI_DRHD_DEV_SCOPE_MSI_CAP_HPET: + case ACPI_DMAR_SCOPE_TYPE_HPET: printk("MSI Capable HPET"); break; - case ACPI_DRHD_DEV_SCOPE_NAMESPACE_DEV: + case ACPI_DMAR_SCOPE_TYPE_NAMESPACE: printk("ACPI name-space enumerated"); break; default: @@ -35,33 +38,26 @@ static void vtd_dev_scope_info(struct acpi_dmar_dev_scope *dev_scope) return; } - id = z_acpi_get_dev_id_from_dmar(dev_scope->type); - if (id != USHRT_MAX) { - printk(" ID 0x%x", id); - } - printk("\n"); - printk("\t\t\t. Enumeration ID %u\n", dev_scope->enumeration_id); - printk("\t\t\t. PCI Bus %u\n", dev_scope->start_bus_num); + printk("\t\t\t. Enumeration ID %u\n", dev_scope->EnumerationId); + printk("\t\t\t. PCI Bus %u\n", dev_scope->Bus); - path = z_acpi_get_dev_scope_paths(dev_scope, &n_path); - for (; n_path > 0; n_path--) { - printk("\t\t\t. Path D:%u F:%u\n", - path->device, path->function); - path = (struct acpi_dmar_dev_path *)(POINTER_TO_UINT(path) + - ACPI_DMAR_DEV_PATH_SIZE); + for (; num_inst > 0; num_inst--, i++) { + printk("Info: Bus: %d, dev:%d, fun:%d\n", dmar_id[i].bits.bus, + dmar_id[i].bits.device, dmar_id[i].bits.function); } printk("\n"); } -static void vtd_drhd_info(struct acpi_drhd *drhd) +static void vtd_drhd_info(struct acpi_dmar_hardware_unit *drhd) { - struct acpi_dmar_dev_scope *dev_scope; - int n_ds, i; + struct acpi_dmar_device_scope dev_scope; + union acpi_dmar_id dmar_id[4]; + int num_inst, i; - if (drhd->flags & ACPI_DRHD_FLAG_INCLUDE_PCI_ALL) { + if (drhd->Flags & ACPI_DRHD_FLAG_INCLUDE_PCI_ALL) { printk("\t\t- Includes all PCI devices"); } else { printk("\t\t- Includes only listed PCI devices"); @@ -69,20 +65,19 @@ static void vtd_drhd_info(struct acpi_drhd *drhd) printk(" under given Segment\n"); - printk("\t\t- Segment number %u\n", drhd->segment_num); - printk("\t\t- Base Address 0x%llx\n", drhd->base_address); - - dev_scope = z_acpi_get_drhd_dev_scopes(drhd, &n_ds); - if (dev_scope == NULL) { - printk("\t\t- No device scopes\n"); - return; - } + printk("\t\t- Segment number %u\n", drhd->Segment); + printk("\t\t- Base Address 0x%llx\n", drhd->Address); printk("\t\t- Device Scopes:\n"); - for (i = 0; i < n_ds; i++) { - vtd_dev_scope_info(dev_scope); - dev_scope = (struct acpi_dmar_dev_scope *)( - POINTER_TO_UINT(dev_scope) + dev_scope->length); + for (i = 0; i < 5; i++) { + if (acpi_drhd_get(dmar_scope[i], &dev_scope, dmar_id, &num_inst, 4u)) { + printk(" No DRHD entry found for scope type:%d\n", dmar_scope[i]); + continue; + } + + printk("Found DRHD entry: %d\n", i); + + vtd_dev_scope_info(dmar_scope[i], &dev_scope, dmar_id, num_inst); } printk("\n"); @@ -90,9 +85,10 @@ static void vtd_drhd_info(struct acpi_drhd *drhd) static void vtd_info(void) { - struct acpi_dmar *dmar; + struct acpi_table_dmar *dmar; + struct acpi_dmar_hardware_unit *drhd; - dmar = z_acpi_find_dmar(); + dmar = acpi_table_get("DMAR", 0); if (dmar == NULL) { printk("\tIntel VT-D not supported or exposed\n"); return; @@ -101,27 +97,22 @@ static void vtd_info(void) printk("\tIntel VT-D Supported:\n"); printk("\t-> X2APIC "); - if (dmar->flags & ACPI_DMAR_FLAG_X2APIC_OPT_OUT) { + if (dmar->Flags & ACPI_DMAR_FLAG_X2APIC_OPT_OUT) { printk("should be opted out\n"); } else { printk("does not need to be opted out\n"); } - if (dmar->flags & ACPI_DMAR_FLAG_INTR_REMAP) { - struct acpi_drhd *drhd; - int hw_n, i; + if (dmar->Flags & ACPI_DMAR_FLAG_INTR_REMAP) { printk("\t-> Interrupt remapping supported\n"); - drhd = z_acpi_find_drhds(&hw_n); - printk("\t-> %u remapping hardware found:\n", hw_n); - - for (i = 0; i < hw_n; i++) { - printk("\t\tDRHD %u:\n", i); - vtd_drhd_info(drhd); - drhd = (struct acpi_drhd *)(POINTER_TO_UINT(drhd) + - drhd->entry.length); + if (acpi_dmar_entry_get(ACPI_DMAR_TYPE_HARDWARE_UNIT, + (struct acpi_subtable_header **)&drhd)) { + printk("error in retrieve DHRD!!\n"); + return; } + vtd_drhd_info(drhd); } else { printk("\t-> Interrupt remapping not supported\n"); } @@ -131,18 +122,19 @@ void acpi(void) { int nr_cpus; - for (nr_cpus = 0; z_acpi_get_cpu(nr_cpus); ++nr_cpus) { + for (nr_cpus = 0; acpi_local_apic_get(nr_cpus); ++nr_cpus) { /* count number of CPUs present */ } if (nr_cpus == 0) { printk("ACPI: no RSDT/MADT found\n\n"); } else { - printk("ACPI: %d CPUs found\n", nr_cpus); + printk("ACPI: %d CPU%s found\n", nr_cpus, nr_cpus == 1 ? "" : "s"); for (int i = 0; i < nr_cpus; ++i) { - struct acpi_cpu *cpu = z_acpi_get_cpu(i); - printk("\tCPU #%d: APIC ID 0x%02x\n", i, cpu->apic_id); + struct acpi_madt_local_apic *cpu = acpi_local_apic_get(i); + + printk("\tCPU #%d: APIC ID 0x%02x\n", i, cpu[i].Id); } } diff --git a/tests/arch/x86/nmi/prj.conf b/tests/arch/x86/nmi/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/arch/x86/nmi/prj.conf +++ b/tests/arch/x86/nmi/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/arch/x86/pagetables/prj.conf b/tests/arch/x86/pagetables/prj.conf index 6207cb18599..1c2858b3e00 100644 --- a/tests/arch/x86/pagetables/prj.conf +++ b/tests/arch/x86/pagetables/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_HW_STACK_PROTECTION=n CONFIG_TEST_USERSPACE=y CONFIG_EXCEPTION_DEBUG=y diff --git a/tests/arch/x86/static_idt/prj.conf b/tests/arch/x86/static_idt/prj.conf index 322bec144cc..ec99b0dbe30 100644 --- a/tests/arch/x86/static_idt/prj.conf +++ b/tests/arch/x86/static_idt/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_EXCEPTION_DEBUG=n CONFIG_MAIN_THREAD_PRIORITY=6 diff --git a/tests/benchmarks/app_kernel/README.txt b/tests/benchmarks/app_kernel/README.txt index 42423891a2f..29fefad2992 100644 --- a/tests/benchmarks/app_kernel/README.txt +++ b/tests/benchmarks/app_kernel/README.txt @@ -1,31 +1,14 @@ -Title: Microkernel Object Performance +Title: Kernel Object Performance Description: -AppKernel is used to measure the performance of microkernel events, mutexes, -semaphores, FIFOs, mailboxes, pipes, memory maps, and memory pools. +The app_kernel test is used to measure the performance of the following +kernel objects: message queues, semaphores, memory slabs, mailboxes and pipes. --------------------------------------------------------------------------------- - -Building and Running Project: - -This project outputs to the console. It can be built and executed -on QEMU as follows: - - make run - --------------------------------------------------------------------------------- - -Troubleshooting: - -Problems caused by out-dated project information can be addressed by -issuing one of the following commands then rebuilding the project: - - make clean # discard results of previous builds - # but keep existing configuration info -or - make pristine # discard results of previous builds - # and restore pre-defined configuration info +When the userspace version is selected (CONF_FILE=prj_user.conf), this +benchmark will execute with four configurations (kernel/kernel, kernel/user, +user/kernel and user/user). However, any configuration involving user threads +will omit both the memory slabs and mailbox tests. -------------------------------------------------------------------------------- @@ -39,31 +22,20 @@ Sample Output: | dequeue 1 byte msg in FIFO | NNNNNN| | enqueue 4 bytes msg in FIFO | NNNNNN| | dequeue 4 bytes msg in FIFO | NNNNNN| -| enqueue 1 byte msg in FIFO to a waiting higher priority task | NNNNNN| -| enqueue 4 bytes in FIFO to a waiting higher priority task | NNNNNN| +| enqueue 192 bytes msg in MSGQ | NNNNNN| +| dequeue 192 bytes msg in MSGQ | NNNNNN| +| enqueue 1 byte msg in MSGQ to a waiting higher priority task | NNNNNN| +| enqueue 4 bytes in MSGQ to a waiting higher priority task | NNNNNN| +| enqueue 192 bytes in MSGQ to a waiting higher priority task | NNNNNN| |-----------------------------------------------------------------------------| | signal semaphore | NNNNNN| | signal to waiting high pri task | NNNNNN| | signal to waiting high pri task, with timeout | NNNNNN| -| signal to waitm (2) | NNNNNN| -| signal to waitm (2), with timeout | NNNNNN| -| signal to waitm (3) | NNNNNN| -| signal to waitm (3), with timeout | NNNNNNN| -| signal to waitm (4) | NNNNNNN| -| signal to waitm (4), with timeout | NNNNNNN| |-----------------------------------------------------------------------------| | average lock and unlock mutex | NNNNNN| |-----------------------------------------------------------------------------| | average alloc and dealloc memory page | NNNNNN| |-----------------------------------------------------------------------------| -| average alloc and dealloc memory pool block | NNNNNN| -|-----------------------------------------------------------------------------| -| Signal enabled event | NNNNNN| -| Signal event & Test event | NNNNNN| -| Signal event & TestW event | NNNNNN| -| Signal event with installed handler | -| Handler responds OK | -|-----------------------------------------------------------------------------| | M A I L B O X M E A S U R E M E N T S | |-----------------------------------------------------------------------------| | Send mailbox message to waiting high priority task and wait | diff --git a/tests/benchmarks/app_kernel/prj.conf b/tests/benchmarks/app_kernel/prj.conf index 8390369dc1a..a01e0835a81 100644 --- a/tests/benchmarks/app_kernel/prj.conf +++ b/tests/benchmarks/app_kernel/prj.conf @@ -3,8 +3,7 @@ CONFIG_TEST=y CONFIG_STDOUT_CONSOLE=y # eliminate timer interrupts during the benchmark -CONFIG_SYS_CLOCK_TICKS_PER_SEC=2 -CONFIG_TICKLESS_KERNEL=n +CONFIG_SYS_CLOCK_TICKS_PER_SEC=1 CONFIG_MAIN_THREAD_PRIORITY=6 CONFIG_FORCE_NO_ASSERT=y @@ -19,3 +18,6 @@ CONFIG_MP_MAX_NUM_CPUS=1 # Enable pipes CONFIG_PIPES=y + +CONFIG_APPLICATION_DEFINED_SYSCALL=y +CONFIG_TIMING_FUNCTIONS=y diff --git a/tests/benchmarks/app_kernel/prj_fp.conf b/tests/benchmarks/app_kernel/prj_fp.conf deleted file mode 100644 index b8eeacab557..00000000000 --- a/tests/benchmarks/app_kernel/prj_fp.conf +++ /dev/null @@ -1,22 +0,0 @@ -CONFIG_TEST=y -# all printf, fprintf to stdout go to console -CONFIG_STDOUT_CONSOLE=y -CONFIG_MAIN_THREAD_PRIORITY=6 - -CONFIG_FPU=y -CONFIG_FPU_SHARING=y - -# eliminate timer interrupts during the benchmark -CONFIG_SYS_CLOCK_TICKS_PER_SEC=1 -CONFIG_TICKLESS_KERNEL=n - -CONFIG_FORCE_NO_ASSERT=y - -# Disable HW Stack Protection (see #28664) -CONFIG_TEST_HW_STACK_PROTECTION=n -CONFIG_HW_STACK_PROTECTION=n - -CONFIG_MP_MAX_NUM_CPUS=1 - -# Enable pipes -CONFIG_PIPES=y diff --git a/tests/benchmarks/app_kernel/prj_user.conf b/tests/benchmarks/app_kernel/prj_user.conf new file mode 100644 index 00000000000..b0438e6b34c --- /dev/null +++ b/tests/benchmarks/app_kernel/prj_user.conf @@ -0,0 +1,24 @@ +CONFIG_TEST=y +# all printf, fprintf to stdout go to console +CONFIG_STDOUT_CONSOLE=y + +# eliminate timer interrupts during the benchmark +CONFIG_SYS_CLOCK_TICKS_PER_SEC=1 + +CONFIG_MAIN_THREAD_PRIORITY=6 +CONFIG_FORCE_NO_ASSERT=y + +# Disable HW Stack Protection (see #28664) +CONFIG_TEST_HW_STACK_PROTECTION=n +CONFIG_HW_STACK_PROTECTION=n +CONFIG_CBPRINTF_FP_SUPPORT=y + +# Can only run under 1 CPU +CONFIG_MP_MAX_NUM_CPUS=1 + +# Enable pipes +CONFIG_PIPES=y + +CONFIG_APPLICATION_DEFINED_SYSCALL=y +CONFIG_TIMING_FUNCTIONS=y +CONFIG_USERSPACE=y diff --git a/tests/benchmarks/app_kernel/src/config.h b/tests/benchmarks/app_kernel/src/config.h index cce54d2852b..f6cd002a315 100644 --- a/tests/benchmarks/app_kernel/src/config.h +++ b/tests/benchmarks/app_kernel/src/config.h @@ -12,28 +12,4 @@ /* Max size of a message string */ #define MAX_MSG 256 -/* flag for performing the Mailbox benchmark */ -#define MAILBOX_BENCH - -/* flag for performing the Sema benchmark */ -#define SEMA_BENCH - -/* flag for performing the FIFO benchmark */ -#define FIFO_BENCH - -/* flag for performing the Mutex benchmark */ -#define MUTEX_BENCH - -/* flag for performing the Memory Map benchmark */ -#define MEMMAP_BENCH - -/* flag for performing the Memory Pool benchmark*/ -#define MEMPOOL_BENCH - -/* flag for performing the Pipes benchmark */ -#define PIPE_BENCH - -/* flag for performing the Event benchmark */ -#define EVENT_BENCH - #endif /* _CONFIG_H */ diff --git a/tests/benchmarks/app_kernel/src/fifo_b.c b/tests/benchmarks/app_kernel/src/fifo_b.c deleted file mode 100644 index 650454a483e..00000000000 --- a/tests/benchmarks/app_kernel/src/fifo_b.c +++ /dev/null @@ -1,88 +0,0 @@ -/* fifo_b.c */ - -/* - * Copyright (c) 1997-2010, 2013-2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "master.h" - -#ifdef FIFO_BENCH - -/** - * - * @brief Queue transfer speed test - * - */ -void queue_test(void) -{ - uint32_t et; /* elapsed time */ - int i; - - PRINT_STRING(dashline); - et = BENCH_START(); - for (i = 0; i < NR_OF_FIFO_RUNS; i++) { - k_msgq_put(&DEMOQX1, data_bench, K_FOREVER); - } - et = TIME_STAMP_DELTA_GET(et); - - PRINT_F(FORMAT, "enqueue 1 byte msg in FIFO", - SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, NR_OF_FIFO_RUNS)); - - et = BENCH_START(); - for (i = 0; i < NR_OF_FIFO_RUNS; i++) { - k_msgq_get(&DEMOQX1, data_bench, K_FOREVER); - } - et = TIME_STAMP_DELTA_GET(et); - check_result(); - - PRINT_F(FORMAT, "dequeue 1 byte msg in FIFO", - SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, NR_OF_FIFO_RUNS)); - - et = BENCH_START(); - for (i = 0; i < NR_OF_FIFO_RUNS; i++) { - k_msgq_put(&DEMOQX4, data_bench, K_FOREVER); - } - et = TIME_STAMP_DELTA_GET(et); - check_result(); - - PRINT_F(FORMAT, "enqueue 4 bytes msg in FIFO", - SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, NR_OF_FIFO_RUNS)); - - et = BENCH_START(); - for (i = 0; i < NR_OF_FIFO_RUNS; i++) { - k_msgq_get(&DEMOQX4, data_bench, K_FOREVER); - } - et = TIME_STAMP_DELTA_GET(et); - check_result(); - - PRINT_F(FORMAT, "dequeue 4 bytes msg in FIFO", - SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, NR_OF_FIFO_RUNS)); - - k_sem_give(&STARTRCV); - - et = BENCH_START(); - for (i = 0; i < NR_OF_FIFO_RUNS; i++) { - k_msgq_put(&DEMOQX1, data_bench, K_FOREVER); - } - et = TIME_STAMP_DELTA_GET(et); - check_result(); - - PRINT_F(FORMAT, - "enqueue 1 byte msg in FIFO to a waiting higher priority task", - SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, NR_OF_FIFO_RUNS)); - - et = BENCH_START(); - for (i = 0; i < NR_OF_FIFO_RUNS; i++) { - k_msgq_put(&DEMOQX4, data_bench, K_FOREVER); - } - et = TIME_STAMP_DELTA_GET(et); - check_result(); - - PRINT_F(FORMAT, - "enqueue 4 bytes in FIFO to a waiting higher priority task", - SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, NR_OF_FIFO_RUNS)); -} - -#endif /* FIFO_BENCH */ diff --git a/tests/benchmarks/app_kernel/src/fifo_r.c b/tests/benchmarks/app_kernel/src/fifo_r.c deleted file mode 100644 index 1580ef114ca..00000000000 --- a/tests/benchmarks/app_kernel/src/fifo_r.c +++ /dev/null @@ -1,34 +0,0 @@ -/* fifo_r.c */ - -/* - * Copyright (c) 1997-2010, 2013-2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "receiver.h" -#include "master.h" - -#ifdef FIFO_BENCH - -/* queue transfer speed test */ -/** - * - * @brief Data receive task - * - */ -void dequtask(void) -{ - int x, i; - - for (i = 0; i < NR_OF_FIFO_RUNS; i++) { - k_msgq_get(&DEMOQX1, &x, K_FOREVER); - } - - for (i = 0; i < NR_OF_FIFO_RUNS; i++) { - k_msgq_get(&DEMOQX4, &x, K_FOREVER); - } -} - - -#endif /* FIFO_BENCH */ diff --git a/tests/benchmarks/app_kernel/src/mailbox_b.c b/tests/benchmarks/app_kernel/src/mailbox_b.c index 508cb10369a..d46b7675ef7 100644 --- a/tests/benchmarks/app_kernel/src/mailbox_b.c +++ b/tests/benchmarks/app_kernel/src/mailbox_b.c @@ -8,31 +8,8 @@ #include "master.h" -#ifdef MAILBOX_BENCH - static struct k_mbox_msg message; -#ifdef FLOAT -#define PRINT_HEADER() \ - (PRINT_STRING \ - ("| size(B) | time/packet (usec) | MB/sec" \ - " |\n")) -#define PRINT_ONE_RESULT() \ - PRINT_F("|%11u|%32.3f|%32f|\n", putsize, puttime / 1000.0, \ - (1000.0 * putsize) / SAFE_DIVISOR(puttime)) - -#define PRINT_OVERHEAD() \ - PRINT_F("| message overhead: %10.3f usec/packet " \ - " |\n", empty_msg_put_time / 1000.0) - -#define PRINT_XFER_RATE() \ - double netto_transfer_rate; \ - netto_transfer_rate = 1000.0 * \ - (putsize >> 1) / SAFE_DIVISOR(puttime - empty_msg_put_time); \ - PRINT_F("| raw transfer rate: %10.3f MB/sec (without" \ - " overhead) |\n", netto_transfer_rate) - -#else #define PRINT_HEADER() \ (PRINT_STRING \ ("| size(B) | time/packet (nsec) | KB/sec" \ @@ -53,9 +30,6 @@ static struct k_mbox_msg message; (uint32_t)((uint64_t)(putsize >> 1) * 1000000U / \ SAFE_DIVISOR(puttime - empty_msg_put_time))) -#endif - - /* * Function prototypes. */ @@ -66,9 +40,7 @@ void mailbox_put(uint32_t size, int count, uint32_t *time); */ /** - * * @brief Mailbox transfer speed test - * */ void mailbox_test(void) { @@ -115,31 +87,29 @@ void mailbox_test(void) /** - * * @brief Write the number of data chunks into the mailbox * * @param size The size of the data chunk. * @param count Number of data chunks. * @param time The total time. - * */ void mailbox_put(uint32_t size, int count, uint32_t *time) { int i; unsigned int t; + timing_t start; + timing_t end; message.rx_source_thread = K_ANY; message.tx_target_thread = K_ANY; /* first sync with the receiver */ k_sem_give(&SEM0); - t = BENCH_START(); + start = timing_timestamp_get(); for (i = 0; i < count; i++) { k_mbox_put(&MAILB1, &message, K_FOREVER); } - t = TIME_STAMP_DELTA_GET(t); + end = timing_timestamp_get(); + t = (unsigned int)timing_cycles_get(&start, &end); *time = SYS_CLOCK_HW_CYCLES_TO_NS_AVG(t, count); - check_result(); } - -#endif /* MAILBOX_BENCH */ diff --git a/tests/benchmarks/app_kernel/src/mailbox_r.c b/tests/benchmarks/app_kernel/src/mailbox_r.c index f0b5e9f87bf..b686da80f08 100644 --- a/tests/benchmarks/app_kernel/src/mailbox_r.c +++ b/tests/benchmarks/app_kernel/src/mailbox_r.c @@ -9,8 +9,6 @@ #include "receiver.h" #include "master.h" -#ifdef MAILBOX_BENCH - /* * Function prototypes. */ @@ -26,9 +24,7 @@ void mailbox_get(struct k_mbox *mailbox, /* mailbox transfer speed test */ /** - * * @brief Receive task - * */ void mailrecvtask(void) { @@ -59,7 +55,6 @@ void mailrecvtask(void) /** - * * @brief Receive data portions from the specified mailbox * * @return 0 @@ -75,7 +70,8 @@ void mailbox_get(struct k_mbox *mailbox, unsigned int *time) { int i; - unsigned int t; + timing_t start; + timing_t end; int32_t return_value = 0; struct k_mbox_msg Message; @@ -84,22 +80,17 @@ void mailbox_get(struct k_mbox *mailbox, /* sync with the sender */ k_sem_take(&SEM0, K_FOREVER); - t = BENCH_START(); + start = timing_timestamp_get(); for (i = 0; i < count; i++) { return_value |= k_mbox_get(mailbox, &Message, &data_recv, K_FOREVER); } + end = timing_timestamp_get(); + *time = timing_cycles_get(&start, &end); - t = TIME_STAMP_DELTA_GET(t); - *time = SYS_CLOCK_HW_CYCLES_TO_NS_AVG(t, count); - if (bench_test_end() < 0) { - PRINT_OVERFLOW_ERROR(); - } if (return_value != 0) { k_panic(); } } - -#endif /* MAILBOX_BENCH */ diff --git a/tests/benchmarks/app_kernel/src/master.c b/tests/benchmarks/app_kernel/src/master.c index 64109778149..0b5c8976910 100644 --- a/tests/benchmarks/app_kernel/src/master.c +++ b/tests/benchmarks/app_kernel/src/master.c @@ -7,8 +7,8 @@ */ /* - *File Naming information. - * ------------------------ + * File Naming information. + * ------------------------ * Files that end with: * _B : Is a file that contains a benchmark function * _R : Is a file that contains the receiver task @@ -17,14 +17,14 @@ #include #include "master.h" -char msg[MAX_MSG]; -char data_bench[MESSAGE_SIZE]; +#define RECV_STACK_SIZE (1024 + CONFIG_TEST_EXTRA_STACK_SIZE) +#define TEST_STACK_SIZE (1024 + CONFIG_TEST_EXTRA_STACK_SIZE) -#ifdef PIPE_BENCH -struct k_pipe *test_pipes[] = {&PIPE_NOBUFF, &PIPE_SMALLBUFF, &PIPE_BIGBUFF}; -#endif -char sline[SLINE_LEN + 1]; -const char newline[] = "\n"; +BENCH_BMEM char msg[MAX_MSG]; +BENCH_BMEM char data_bench[MESSAGE_SIZE]; + +BENCH_DMEM struct k_pipe *test_pipes[] = {&PIPE_NOBUFF, &PIPE_SMALLBUFF, &PIPE_BIGBUFF}; +BENCH_BMEM char sline[SLINE_LEN + 1]; /* * Time in timer cycles necessary to read time. @@ -32,13 +32,28 @@ const char newline[] = "\n"; */ uint32_t tm_off; +static BENCH_DMEM char *test_type_str[] = { + "| K E R N E L - - > K E R N E L | |\n", + "| K E R N E L - - > U S E R | |\n", + "| U S E R - - > K E R N E L | |\n", + "| U S E R - - > U S E R | |\n" +}; /********************************************************************/ /* static allocation */ -K_THREAD_DEFINE(RECVTASK, 1024, recvtask, NULL, NULL, NULL, 5, 0, 0); + +static struct k_thread test_thread; +static struct k_thread recv_thread; +K_THREAD_STACK_DEFINE(test_stack, TEST_STACK_SIZE); +K_THREAD_STACK_DEFINE(recv_stack, RECV_STACK_SIZE); + +#ifdef CONFIG_USERSPACE +K_APPMEM_PARTITION_DEFINE(bench_mem_partition); +#endif K_MSGQ_DEFINE(DEMOQX1, 1, 500, 4); K_MSGQ_DEFINE(DEMOQX4, 4, 500, 4); +K_MSGQ_DEFINE(DEMOQX192, 192, 500, 4); K_MSGQ_DEFINE(MB_COMM, 12, 1, 4); K_MSGQ_DEFINE(CH_COMM, 12, 1, 4); @@ -59,75 +74,211 @@ K_PIPE_DEFINE(PIPE_NOBUFF, 0, 4); K_PIPE_DEFINE(PIPE_SMALLBUFF, 256, 4); K_PIPE_DEFINE(PIPE_BIGBUFF, 4096, 4); +/* + * Custom syscalls + */ + /** + * @brief Change a thread's priority * - * @brief Check for keypress - * - * @return 1 when a keyboard key is pressed, or 0 if no keyboard support + * Unlike the normal k_thread_priority_set(), this custom syscall allows + * a user thread to raise its priority. */ -int kbhit(void) +void z_impl_test_thread_priority_set(k_tid_t thread, int prio) { - return 0; + extern void z_thread_priority_set(struct k_thread *thread, int prio); + + z_thread_priority_set((struct k_thread *)thread, prio); } + +#ifdef CONFIG_USERSPACE +static void z_vrfy_test_thread_priority_set(k_tid_t thread, int prio) +{ + z_impl_test_thread_priority_set(thread, prio); +} + +#include +#endif + /** + * @brief Obtain a timestamp * - * @brief Close output for the test - * + * Architecture timestamp routines often require MMIO that is not mapped to + * the user threads. Use a custom system call to get the timestamp. */ -void output_close(void) +timing_t z_impl_timing_timestamp_get(void) { + return timing_counter_get(); } -/* no need to wait for user key press when using console */ -#define WAIT_FOR_USER() {} +#ifdef CONFIG_USERSPACE +static timing_t z_vrfy_timing_timestamp_get(void) +{ + return z_impl_timing_timestamp_get(); +} +#include +#endif + +/* + * Main test + */ /** - * - * @brief Perform all selected benchmarks - * see config.h to select or to unselect - * + * @brief Entry point for test thread */ -int main(void) +static void test_thread_entry(void *p1, void *p2, void *p3) { - int continuously = 0; + bool skip_mem_and_mbox = (bool)(uintptr_t)(p2); - bench_test_init(); + ARG_UNUSED(p3); - PRINT_STRING(newline); - do { - PRINT_STRING(dashline); - PRINT_STRING("| S I M P L E S E R V I C E " - "M E A S U R E M E N T S | nsec |\n"); - PRINT_STRING(dashline); - queue_test(); - sema_test(); - mutex_test(); - memorymap_test(); - mailbox_test(); - pipe_test(); - PRINT_STRING("| END OF TESTS " - " |\n"); - PRINT_STRING(dashline); - PRINT_STRING("PROJECT EXECUTION SUCCESSFUL\n"); - TC_PRINT_RUNID; - } while (continuously && !kbhit()); + PRINT_STRING("\n"); + PRINT_STRING(dashline); + PRINT_STRING("| S I M P L E S E R V I C E " + "M E A S U R E M E N T S | nsec |\n"); +#ifdef CONFIG_USERSPACE + PRINT_STRING((const char *)p1); +#endif + PRINT_STRING(dashline); - WAIT_FOR_USER(); + message_queue_test(); + sema_test(); + mutex_test(); - k_thread_abort(RECVTASK); + if (!skip_mem_and_mbox) { + memorymap_test(); + mailbox_test(); + } - output_close(); - return 0; + pipe_test(); } - /** - * - * @brief Dummy test - * + * @brief Perform all benchmarks */ -void dummy_test(void) +int main(void) { + int priority; + + priority = k_thread_priority_get(k_current_get()); + +#ifdef CONFIG_USERSPACE + k_mem_domain_add_partition(&k_mem_domain_default, + &bench_mem_partition); +#endif + + bench_test_init(); + + timing_init(); + + timing_start(); + + /* ********* All threads are kernel threads ********** */ + + k_thread_create(&test_thread, test_stack, + K_THREAD_STACK_SIZEOF(test_stack), + test_thread_entry, + test_type_str[0], (void *)(uintptr_t)false, NULL, + priority, 0, K_FOREVER); + + k_thread_create(&recv_thread, recv_stack, + K_THREAD_STACK_SIZEOF(recv_stack), + recvtask, (void *)(uintptr_t)false, NULL, NULL, + 5, 0, K_FOREVER); + + k_thread_start(&recv_thread); + k_thread_start(&test_thread); + + k_thread_join(&test_thread, K_FOREVER); + k_thread_abort(&recv_thread); + +#ifdef CONFIG_USERSPACE + /* ****** Main thread is kernel, receiver is user thread ******* */ + + k_thread_create(&test_thread, test_stack, + K_THREAD_STACK_SIZEOF(test_stack), + test_thread_entry, + test_type_str[1], (void *)(uintptr_t)true, NULL, + priority, 0, K_FOREVER); + + k_thread_create(&recv_thread, recv_stack, + K_THREAD_STACK_SIZEOF(recv_stack), + recvtask, (void *)(uintptr_t)true, NULL, NULL, + 5, K_USER, K_FOREVER); + + k_thread_access_grant(&recv_thread, &DEMOQX1, &DEMOQX4, &DEMOQX192, + &MB_COMM, &CH_COMM, &SEM0, &SEM1, &SEM2, &SEM3, + &SEM4, &STARTRCV, &DEMO_MUTEX, + &PIPE_NOBUFF, &PIPE_SMALLBUFF, &PIPE_BIGBUFF); + + k_thread_start(&recv_thread); + k_thread_start(&test_thread); + + k_thread_join(&test_thread, K_FOREVER); + k_thread_abort(&recv_thread); + + /* ****** Main thread is user, receiver is kernel thread ******* */ + + k_thread_create(&test_thread, test_stack, + K_THREAD_STACK_SIZEOF(test_stack), + test_thread_entry, + test_type_str[2], (void *)(uintptr_t)true, NULL, + priority, K_USER, K_FOREVER); + + k_thread_create(&recv_thread, recv_stack, + K_THREAD_STACK_SIZEOF(recv_stack), + recvtask, (void *)(uintptr_t)true, NULL, NULL, + 5, 0, K_FOREVER); + + k_thread_access_grant(&test_thread, &DEMOQX1, &DEMOQX4, &DEMOQX192, + &MB_COMM, &CH_COMM, &SEM0, &SEM1, &SEM2, &SEM3, + &SEM4, &STARTRCV, &DEMO_MUTEX, + &PIPE_NOBUFF, &PIPE_SMALLBUFF, &PIPE_BIGBUFF); + + k_thread_start(&recv_thread); + k_thread_start(&test_thread); + + k_thread_join(&test_thread, K_FOREVER); + k_thread_abort(&recv_thread); + + /* ********* All threads are user threads ********** */ + + k_thread_create(&test_thread, test_stack, + K_THREAD_STACK_SIZEOF(test_stack), + test_thread_entry, + test_type_str[3], (void *)(uintptr_t)true, NULL, + priority, K_USER, K_FOREVER); + + k_thread_create(&recv_thread, recv_stack, + K_THREAD_STACK_SIZEOF(recv_stack), + recvtask, (void *)(uintptr_t)true, NULL, NULL, + 5, K_USER, K_FOREVER); + + k_thread_access_grant(&test_thread, &DEMOQX1, &DEMOQX4, &DEMOQX192, + &MB_COMM, &CH_COMM, &SEM0, &SEM1, &SEM2, &SEM3, + &SEM4, &STARTRCV, &DEMO_MUTEX, + &PIPE_NOBUFF, &PIPE_SMALLBUFF, &PIPE_BIGBUFF); + k_thread_access_grant(&recv_thread, &DEMOQX1, &DEMOQX4, &DEMOQX192, + &MB_COMM, &CH_COMM, &SEM0, &SEM1, &SEM2, &SEM3, + &SEM4, &STARTRCV, &DEMO_MUTEX, + &PIPE_NOBUFF, &PIPE_SMALLBUFF, &PIPE_BIGBUFF); + + k_thread_start(&recv_thread); + k_thread_start(&test_thread); + + k_thread_join(&test_thread, K_FOREVER); + k_thread_abort(&recv_thread); +#endif /* CONFIG_USERSPACE */ + + timing_stop(); + + PRINT_STRING("| END OF TESTS " + " |\n"); + PRINT_STRING(dashline); + PRINT_STRING("PROJECT EXECUTION SUCCESSFUL\n"); + TC_PRINT_RUNID; + + return 0; } diff --git a/tests/benchmarks/app_kernel/src/master.h b/tests/benchmarks/app_kernel/src/master.h index c0ff7709eb1..9f9c902afa9 100644 --- a/tests/benchmarks/app_kernel/src/master.h +++ b/tests/benchmarks/app_kernel/src/master.h @@ -21,9 +21,8 @@ #include - -/* uncomment the define below to use floating point arithmetic */ -/* #define FLOAT */ +#include +#include /* printf format defines. */ #define FORMAT "| %-65s|%10u|\n" @@ -31,26 +30,27 @@ /* length of the output line */ #define SLINE_LEN 256 -#define SLEEP_TIME ((CONFIG_SYS_CLOCK_TICKS_PER_SEC / 4) > 0 ? \ - CONFIG_SYS_CLOCK_TICKS_PER_SEC / 4 : 1) -#define WAIT_TIME ((CONFIG_SYS_CLOCK_TICKS_PER_SEC / 10) > 0 ? \ - CONFIG_SYS_CLOCK_TICKS_PER_SEC / 10 : 1) -#define NR_OF_NOP_RUNS 10000 -#define NR_OF_FIFO_RUNS 500 +#define NR_OF_MSGQ_RUNS 500 #define NR_OF_SEMA_RUNS 500 #define NR_OF_MUTEX_RUNS 1000 -#define NR_OF_POOL_RUNS 1000 #define NR_OF_MAP_RUNS 1000 -#define NR_OF_EVENT_RUNS 1000 #define NR_OF_MBOX_RUNS 128 #define NR_OF_PIPE_RUNS 256 -/* #define SEMA_WAIT_TIME (5 * CONFIG_SYS_CLOCK_TICKS_PER_SEC) */ #define SEMA_WAIT_TIME (5000) + +#ifdef CONFIG_USERSPACE +#define BENCH_BMEM K_APP_BMEM(bench_mem_partition) +#define BENCH_DMEM K_APP_DMEM(bench_mem_partition) +#else +#define BENCH_BMEM +#define BENCH_DMEM +#endif + /* global data */ + extern char msg[MAX_MSG]; extern char data_bench[MESSAGE_SIZE]; extern struct k_pipe *test_pipes[]; -extern const char newline[]; extern char sline[]; #define dashline \ @@ -60,7 +60,7 @@ extern char sline[]; /* * To avoid divisions by 0 faults, wrap the divisor with this macro */ -#define SAFE_DIVISOR(a) (((a) != 0)?(a):1) +#define SAFE_DIVISOR(a) (((a) != 0) ? (a) : 1) /* pipe amount of content to receive (0+, 1+, all) */ @@ -70,56 +70,16 @@ enum pipe_options { _ALL_N = 0x2, }; -/* dummy_test is a function that is mapped when we */ -/* do not want to test a specific Benchmark */ -extern void dummy_test(void); - /* other external functions */ -extern void bench_task(void *p1, void *p2, void *p3); extern void recvtask(void *p1, void *p2, void *p3); -#ifdef MAILBOX_BENCH extern void mailbox_test(void); -#else -#define mailbox_test dummy_test -#endif - -#ifdef SEMA_BENCH extern void sema_test(void); -#else -#define sema_test dummy_test -#endif - -#ifdef FIFO_BENCH -extern void queue_test(void); -#else -#define queue_test dummy_test -#endif - -#ifdef MUTEX_BENCH +extern void message_queue_test(void); extern void mutex_test(void); -#else -#define mutex_test dummy_test -#endif - -#ifdef MEMMAP_BENCH extern void memorymap_test(void); -#else -#define memorymap_test dummy_test -#endif - -#ifdef MEMPOOL_BENCH -extern void mempool_test(void); -#else -#define mempool_test dummy_test -#endif - -#ifdef PIPE_BENCH extern void pipe_test(void); -#else -#define pipe_test dummy_test -#endif /* kernel objects needed for benchmarking */ extern struct k_mutex DEMO_MUTEX; @@ -133,12 +93,12 @@ extern struct k_sem STARTRCV; extern struct k_msgq DEMOQX1; extern struct k_msgq DEMOQX4; +extern struct k_msgq DEMOQX192; extern struct k_msgq MB_COMM; extern struct k_msgq CH_COMM; extern struct k_mbox MAILB1; - extern struct k_pipe PIPE_NOBUFF; extern struct k_pipe PIPE_SMALLBUFF; extern struct k_pipe PIPE_BIGBUFF; @@ -146,8 +106,6 @@ extern struct k_pipe PIPE_BIGBUFF; extern struct k_mem_slab MAP1; - - /* PRINT_STRING * Macro to print an ASCII NULL terminated string. */ @@ -165,24 +123,9 @@ extern struct k_mem_slab MAP1; PRINT_STRING(sline); \ } -#define PRINT_OVERFLOW_ERROR() \ - PRINT_F(__FILE__":%d Error: tick occurred\n", __LINE__) +__syscall void test_thread_priority_set(k_tid_t thread, int prio); +__syscall timing_t timing_timestamp_get(void); -static inline uint32_t BENCH_START(void) -{ - uint32_t et; - - bench_test_start(); - et = TIME_STAMP_DELTA_GET(0); - return et; -} - -static inline void check_result(void) -{ - if (bench_test_end() < 0) { - PRINT_OVERFLOW_ERROR(); - return; /* error */ - } -} +#include #endif /* _MASTER_H */ diff --git a/tests/benchmarks/app_kernel/src/memmap_b.c b/tests/benchmarks/app_kernel/src/memmap_b.c index a32385a7c68..a6451b4f930 100644 --- a/tests/benchmarks/app_kernel/src/memmap_b.c +++ b/tests/benchmarks/app_kernel/src/memmap_b.c @@ -9,23 +9,20 @@ #include "master.h" #include -#ifdef MEMMAP_BENCH - - /** - * * @brief Memory map get/free test - * */ void memorymap_test(void) { uint32_t et; /* elapsed time */ + timing_t start; + timing_t end; int i; void *p; int alloc_status; PRINT_STRING(dashline); - et = BENCH_START(); + start = timing_timestamp_get(); for (i = 0; i < NR_OF_MAP_RUNS; i++) { alloc_status = k_mem_slab_alloc(&MAP1, &p, K_FOREVER); if (alloc_status != 0) { @@ -35,11 +32,9 @@ void memorymap_test(void) } k_mem_slab_free(&MAP1, p); } - et = TIME_STAMP_DELTA_GET(et); - check_result(); + end = timing_timestamp_get(); + et = (uint32_t)timing_cycles_get(&start, &end); PRINT_F(FORMAT, "average alloc and dealloc memory page", SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, (2 * NR_OF_MAP_RUNS))); } - -#endif /* MEMMAP_BENCH */ diff --git a/tests/benchmarks/app_kernel/src/msgq_b.c b/tests/benchmarks/app_kernel/src/msgq_b.c new file mode 100644 index 00000000000..a542fdf7355 --- /dev/null +++ b/tests/benchmarks/app_kernel/src/msgq_b.c @@ -0,0 +1,115 @@ +/* msgq_b.c */ + +/* + * Copyright (c) 1997-2010, 2013-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "master.h" + +/** + * @brief Message queue transfer speed test + */ +void message_queue_test(void) +{ + uint32_t et; /* elapsed time */ + int i; + timing_t start; + timing_t end; + + PRINT_STRING(dashline); + start = timing_timestamp_get(); + for (i = 0; i < NR_OF_MSGQ_RUNS; i++) { + k_msgq_put(&DEMOQX1, data_bench, K_FOREVER); + } + end = timing_timestamp_get(); + et = (uint32_t)timing_cycles_get(&start, &end); + PRINT_F(FORMAT, "enqueue 1 byte msg in MSGQ", + SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, NR_OF_MSGQ_RUNS)); + + start = timing_timestamp_get(); + for (i = 0; i < NR_OF_MSGQ_RUNS; i++) { + k_msgq_get(&DEMOQX1, data_bench, K_FOREVER); + } + end = timing_timestamp_get(); + et = (uint32_t)timing_cycles_get(&start, &end); + + PRINT_F(FORMAT, "dequeue 1 byte msg from MSGQ", + SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, NR_OF_MSGQ_RUNS)); + + start = timing_timestamp_get(); + for (i = 0; i < NR_OF_MSGQ_RUNS; i++) { + k_msgq_put(&DEMOQX4, data_bench, K_FOREVER); + } + end = timing_timestamp_get(); + et = (uint32_t)timing_cycles_get(&start, &end); + + PRINT_F(FORMAT, "enqueue 4 bytes msg in MSGQ", + SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, NR_OF_MSGQ_RUNS)); + + start = timing_timestamp_get(); + for (i = 0; i < NR_OF_MSGQ_RUNS; i++) { + k_msgq_get(&DEMOQX4, data_bench, K_FOREVER); + } + end = timing_timestamp_get(); + et = (uint32_t)timing_cycles_get(&start, &end); + + PRINT_F(FORMAT, "dequeue 4 bytes msg in MSGQ", + SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, NR_OF_MSGQ_RUNS)); + + start = timing_timestamp_get(); + for (i = 0; i < NR_OF_MSGQ_RUNS; i++) { + k_msgq_put(&DEMOQX192, data_bench, K_FOREVER); + } + end = timing_timestamp_get(); + et = (uint32_t)timing_cycles_get(&start, &end); + + PRINT_F(FORMAT, "enqueue 192 bytes msg in MSGQ", + SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, NR_OF_MSGQ_RUNS)); + + start = timing_timestamp_get(); + for (i = 0; i < NR_OF_MSGQ_RUNS; i++) { + k_msgq_get(&DEMOQX192, data_bench, K_FOREVER); + } + end = timing_timestamp_get(); + et = (uint32_t)timing_cycles_get(&start, &end); + + PRINT_F(FORMAT, "dequeue 192 bytes msg in MSGQ", + SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, NR_OF_MSGQ_RUNS)); + + k_sem_give(&STARTRCV); + + start = timing_timestamp_get(); + for (i = 0; i < NR_OF_MSGQ_RUNS; i++) { + k_msgq_put(&DEMOQX1, data_bench, K_FOREVER); + } + end = timing_timestamp_get(); + et = (uint32_t)timing_cycles_get(&start, &end); + + PRINT_F(FORMAT, + "enqueue 1 byte msg in MSGQ to a waiting higher priority task", + SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, NR_OF_MSGQ_RUNS)); + + start = timing_timestamp_get(); + for (i = 0; i < NR_OF_MSGQ_RUNS; i++) { + k_msgq_put(&DEMOQX4, data_bench, K_FOREVER); + } + end = timing_timestamp_get(); + et = (uint32_t)timing_cycles_get(&start, &end); + + PRINT_F(FORMAT, + "enqueue 4 bytes in MSGQ to a waiting higher priority task", + SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, NR_OF_MSGQ_RUNS)); + + start = timing_timestamp_get(); + for (i = 0; i < NR_OF_MSGQ_RUNS; i++) { + k_msgq_put(&DEMOQX192, data_bench, K_FOREVER); + } + end = timing_timestamp_get(); + et = (uint32_t)timing_cycles_get(&start, &end); + + PRINT_F(FORMAT, + "enqueue 192 bytes in MSGQ to a waiting higher priority task", + SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, NR_OF_MSGQ_RUNS)); +} diff --git a/tests/benchmarks/app_kernel/src/msgq_r.c b/tests/benchmarks/app_kernel/src/msgq_r.c new file mode 100644 index 00000000000..dcef1be80ff --- /dev/null +++ b/tests/benchmarks/app_kernel/src/msgq_r.c @@ -0,0 +1,34 @@ +/* msgq_r.c */ + +/* + * Copyright (c) 1997-2010, 2013-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "receiver.h" +#include "master.h" + +/* message queue transfer speed test */ + +static BENCH_BMEM char buffer[192]; + +/** + * @brief Data receive task + */ +void dequtask(void) +{ + int i; + + for (i = 0; i < NR_OF_MSGQ_RUNS; i++) { + k_msgq_get(&DEMOQX1, buffer, K_FOREVER); + } + + for (i = 0; i < NR_OF_MSGQ_RUNS; i++) { + k_msgq_get(&DEMOQX4, buffer, K_FOREVER); + } + + for (i = 0; i < NR_OF_MSGQ_RUNS; i++) { + k_msgq_get(&DEMOQX192, buffer, K_FOREVER); + } +} diff --git a/tests/benchmarks/app_kernel/src/mutex_b.c b/tests/benchmarks/app_kernel/src/mutex_b.c index 9ad987dbd50..ce93acea121 100644 --- a/tests/benchmarks/app_kernel/src/mutex_b.c +++ b/tests/benchmarks/app_kernel/src/mutex_b.c @@ -8,29 +8,25 @@ #include "master.h" -#ifdef MUTEX_BENCH - /** - * * @brief Mutex lock/unlock test - * */ void mutex_test(void) { uint32_t et; /* elapsed time */ int i; + timing_t start; + timing_t end; PRINT_STRING(dashline); - et = BENCH_START(); + start = timing_timestamp_get(); for (i = 0; i < NR_OF_MUTEX_RUNS; i++) { k_mutex_lock(&DEMO_MUTEX, K_FOREVER); k_mutex_unlock(&DEMO_MUTEX); } - et = TIME_STAMP_DELTA_GET(et); - check_result(); + end = timing_timestamp_get(); + et = (uint32_t)timing_cycles_get(&start, &end); PRINT_F(FORMAT, "average lock and unlock mutex", SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, (2 * NR_OF_MUTEX_RUNS))); } - -#endif /* MUTEX_BENCH */ diff --git a/tests/benchmarks/app_kernel/src/pipe_b.c b/tests/benchmarks/app_kernel/src/pipe_b.c index e0c8b9aa83f..921f217b638 100644 --- a/tests/benchmarks/app_kernel/src/pipe_b.c +++ b/tests/benchmarks/app_kernel/src/pipe_b.c @@ -8,40 +8,6 @@ #include "master.h" -#ifdef PIPE_BENCH - -#ifdef FLOAT -#define PRINT_ALL_TO_N_HEADER_UNIT() \ - PRINT_STRING("| size(B) | time/packet (usec) | " \ - " MB/sec |\n") - -#define PRINT_ALL_TO_N() \ - PRINT_F("|%5u|%5u|%10.3f|%10.3f|%10.3f|%10.3f|%10.3f|%10.3f|\n", \ - putsize, putsize, puttime[0] / 1000.0, puttime[1] / 1000.0, \ - puttime[2] / 1000.0, \ - (1000.0 * putsize) / SAFE_DIVISOR(puttime[0]), \ - (1000.0 * putsize) / SAFE_DIVISOR(puttime[1]), \ - (1000.0 * putsize) / SAFE_DIVISOR(puttime[2])) - -#define PRINT_1_TO_N_HEADER() \ - do { \ - PRINT_STRING("| size(B) | time/packet (usec) |" \ - " MB/sec |\n"); \ - PRINT_STRING(dashline); \ - } while (0) - -#define PRINT_1_TO_N() \ - PRINT_F("|%5u|%5d|%10.3f|%10.3f|%10.3f|%10.3f|%10.3f|%10.3f|\n", \ - putsize, \ - getsize, \ - puttime[0] / 1000.0, \ - puttime[1] / 1000.0, \ - puttime[2] / 1000.0, \ - (1000.0 * putsize) / SAFE_DIVISOR(puttime[0]), \ - (1000.0 * putsize) / SAFE_DIVISOR(puttime[1]), \ - (1000.0 * putsize) / SAFE_DIVISOR(puttime[2])) - -#else #define PRINT_ALL_TO_N_HEADER_UNIT() \ PRINT_STRING("| size(B) | time/packet (nsec) | " \ " KB/sec |\n") @@ -74,7 +40,6 @@ SAFE_DIVISOR(puttime[1])), \ (uint32_t)(((uint64_t)putsize * 1000000U) / \ SAFE_DIVISOR(puttime[2]))) -#endif /* FLOAT */ /* * Function prototypes. @@ -87,9 +52,7 @@ int pipeput(struct k_pipe *pipe, enum pipe_options */ /** - * * @brief Test the pipes transfer speed - * */ void pipe_test(void) { @@ -152,7 +115,7 @@ void pipe_test(void) PRINT_STRING("| " "non-matching sizes (1_TO_N) to lower priority" " |\n"); - k_thread_priority_set(k_current_get(), TaskPrio - 2); + test_thread_priority_set(k_current_get(), TaskPrio - 2); } PRINT_STRING(dashline); PRINT_1_TO_N_HEADER(); @@ -173,13 +136,12 @@ void pipe_test(void) PRINT_1_TO_N(); } PRINT_STRING(dashline); - k_thread_priority_set(k_current_get(), TaskPrio); + test_thread_priority_set(k_current_get(), TaskPrio); } } /** - * * @brief Write a data portion to the pipe and measure time * * @return 0 on success, 1 on error @@ -198,12 +160,14 @@ int pipeput(struct k_pipe *pipe, { int i; unsigned int t; + timing_t start; + timing_t end; size_t sizexferd_total = 0; size_t size2xfer_total = size * count; /* first sync with the receiver */ k_sem_give(&SEM0); - t = BENCH_START(); + start = timing_timestamp_get(); for (i = 0; option == _1_TO_N || (i < count); i++) { size_t sizexferd = 0; size_t size2xfer = MIN(size, size2xfer_total - sizexferd_total); @@ -233,17 +197,10 @@ int pipeput(struct k_pipe *pipe, } } - t = TIME_STAMP_DELTA_GET(t); + end = timing_timestamp_get(); + t = (unsigned int)timing_cycles_get(&start, &end); + *time = SYS_CLOCK_HW_CYCLES_TO_NS_AVG(t, count); - if (bench_test_end() < 0) { - if (high_timer_overflow()) { - PRINT_STRING("| Timer overflow. Results are invalid "); - } else { - PRINT_STRING("| Tick occurred. Results may be inaccurate "); - } - PRINT_STRING(" |\n"); - } + return 0; } - -#endif /* PIPE_BENCH */ diff --git a/tests/benchmarks/app_kernel/src/pipe_r.c b/tests/benchmarks/app_kernel/src/pipe_r.c index bda40114efd..653e66491fa 100644 --- a/tests/benchmarks/app_kernel/src/pipe_r.c +++ b/tests/benchmarks/app_kernel/src/pipe_r.c @@ -9,9 +9,6 @@ #include "receiver.h" #include "master.h" -#ifdef PIPE_BENCH - - /* * Function prototypes. */ @@ -25,9 +22,7 @@ int pipeget(struct k_pipe *pipe, enum pipe_options option, /* pipes transfer speed test */ /** - * * @brief Receive task - * */ void piperecvtask(void) { @@ -55,26 +50,25 @@ void piperecvtask(void) for (prio = 0; prio < 2; prio++) { /* non-matching (1_TO_N) */ - for (getsize = (MESSAGE_SIZE_PIPE); getsize >= 8; getsize >>= 1) { - getcount = MESSAGE_SIZE_PIPE / getsize; - for (pipe = 0; pipe < 3; pipe++) { - /* size*count == MESSAGE_SIZE_PIPE */ - pipeget(test_pipes[pipe], _1_TO_N, - getsize, getcount, &gettime); - getinfo.time = gettime; - getinfo.size = getsize; - getinfo.count = getcount; - /* acknowledge to master */ - k_msgq_put(&CH_COMM, &getinfo, K_FOREVER); + for (getsize = (MESSAGE_SIZE_PIPE); getsize >= 8; getsize >>= 1) { + getcount = MESSAGE_SIZE_PIPE / getsize; + for (pipe = 0; pipe < 3; pipe++) { + /* size*count == MESSAGE_SIZE_PIPE */ + pipeget(test_pipes[pipe], _1_TO_N, + getsize, getcount, &gettime); + getinfo.time = gettime; + getinfo.size = getsize; + getinfo.count = getcount; + /* acknowledge to master */ + k_msgq_put(&CH_COMM, &getinfo, K_FOREVER); + } } } - } } /** - * * @brief Read a data portion from the pipe and measure time * * @return 0 on success, 1 on error @@ -90,12 +84,14 @@ int pipeget(struct k_pipe *pipe, enum pipe_options option, int size, int count, { int i; unsigned int t; + timing_t start; + timing_t end; size_t sizexferd_total = 0; size_t size2xfer_total = size * count; /* sync with the sender */ k_sem_take(&SEM0, K_FOREVER); - t = BENCH_START(); + start = timing_timestamp_get(); for (i = 0; option == _1_TO_N || (i < count); i++) { size_t sizexferd = 0; size_t size2xfer = MIN(size, size2xfer_total - sizexferd_total); @@ -122,19 +118,9 @@ int pipeget(struct k_pipe *pipe, enum pipe_options option, int size, int count, } } - t = TIME_STAMP_DELTA_GET(t); + end = timing_timestamp_get(); + t = (unsigned int) timing_cycles_get(&start, &end); *time = SYS_CLOCK_HW_CYCLES_TO_NS_AVG(t, count); - if (bench_test_end() < 0) { - if (high_timer_overflow()) { - PRINT_STRING("| Timer overflow. " - "Results are invalid "); - } else { - PRINT_STRING("| Tick occurred. " - "Results may be inaccurate "); - } - PRINT_STRING(" |\n"); - } + return 0; } - -#endif /* PIPE_BENCH */ diff --git a/tests/benchmarks/app_kernel/src/receiver.c b/tests/benchmarks/app_kernel/src/receiver.c index cd8d8964a36..5d5f74f45da 100644 --- a/tests/benchmarks/app_kernel/src/receiver.c +++ b/tests/benchmarks/app_kernel/src/receiver.c @@ -17,7 +17,7 @@ #include "receiver.h" -char data_recv[MESSAGE_SIZE] = { 0 }; +BENCH_DMEM char data_recv[MESSAGE_SIZE] = { 0 }; void dequtask(void); void waittask(void); @@ -25,27 +25,28 @@ void mailrecvtask(void); void piperecvtask(void); /** - * * @brief Main function of the task that receives data in the test - * */ void recvtask(void *p1, void *p2, void *p3) { + bool skip_mbox = (bool)(uintptr_t)(p1); + + ARG_UNUSED(p2); + ARG_UNUSED(p3); + /* order must be compatible with master.c ! */ -#ifdef FIFO_BENCH + k_sem_take(&STARTRCV, K_FOREVER); dequtask(); -#endif -#ifdef SEMA_BENCH + k_sem_take(&STARTRCV, K_FOREVER); waittask(); -#endif -#ifdef MAILBOX_BENCH - k_sem_take(&STARTRCV, K_FOREVER); - mailrecvtask(); -#endif -#ifdef PIPE_BENCH + + if (!skip_mbox) { + k_sem_take(&STARTRCV, K_FOREVER); + mailrecvtask(); + } + k_sem_take(&STARTRCV, K_FOREVER); piperecvtask(); -#endif } diff --git a/tests/benchmarks/app_kernel/src/sema_b.c b/tests/benchmarks/app_kernel/src/sema_b.c index 2b3942a01ab..36c2451978f 100644 --- a/tests/benchmarks/app_kernel/src/sema_b.c +++ b/tests/benchmarks/app_kernel/src/sema_b.c @@ -8,26 +8,23 @@ #include "master.h" -#ifdef SEMA_BENCH - - /** - * * @brief Semaphore signal speed test - * */ void sema_test(void) { uint32_t et; /* elapsed Time */ int i; + timing_t start; + timing_t end; PRINT_STRING(dashline); - et = BENCH_START(); + start = timing_timestamp_get(); for (i = 0; i < NR_OF_SEMA_RUNS; i++) { k_sem_give(&SEM0); } - et = TIME_STAMP_DELTA_GET(et); - check_result(); + end = timing_timestamp_get(); + et = (uint32_t)timing_cycles_get(&start, &end); PRINT_F(FORMAT, "signal semaphore", SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, NR_OF_SEMA_RUNS)); @@ -35,26 +32,23 @@ void sema_test(void) k_sem_reset(&SEM1); k_sem_give(&STARTRCV); - et = BENCH_START(); + start = timing_timestamp_get(); for (i = 0; i < NR_OF_SEMA_RUNS; i++) { k_sem_give(&SEM1); } - et = TIME_STAMP_DELTA_GET(et); - check_result(); + end = timing_timestamp_get(); + et = (uint32_t)timing_cycles_get(&start, &end); PRINT_F(FORMAT, "signal to waiting high pri task", SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, NR_OF_SEMA_RUNS)); - et = BENCH_START(); + start = timing_timestamp_get(); for (i = 0; i < NR_OF_SEMA_RUNS; i++) { k_sem_give(&SEM1); } - et = TIME_STAMP_DELTA_GET(et); - check_result(); + end = timing_timestamp_get(); + et = (uint32_t)timing_cycles_get(&start, &end); PRINT_F(FORMAT, "signal to waiting high pri task, with timeout", SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, NR_OF_SEMA_RUNS)); - } - -#endif /* SEMA_BENCH */ diff --git a/tests/benchmarks/app_kernel/src/sema_r.c b/tests/benchmarks/app_kernel/src/sema_r.c index 21f16e0eed0..df968b5a14c 100644 --- a/tests/benchmarks/app_kernel/src/sema_r.c +++ b/tests/benchmarks/app_kernel/src/sema_r.c @@ -9,14 +9,10 @@ #include "receiver.h" #include "master.h" -#ifdef SEMA_BENCH - /* semaphore signal speed test */ /** - * * @brief Receive task (Wait task) - * */ void waittask(void) { @@ -25,10 +21,9 @@ void waittask(void) for (i = 0; i < NR_OF_SEMA_RUNS; i++) { k_sem_take(&SEM1, K_FOREVER); } + for (i = 0; i < NR_OF_SEMA_RUNS; i++) { k_sem_take(&SEM1, K_MSEC(SEMA_WAIT_TIME)); } } - -#endif /* SEMA_BENCH */ diff --git a/tests/benchmarks/app_kernel/testcase.yaml b/tests/benchmarks/app_kernel/testcase.yaml index 085ec0a32dc..19aeb6fbe52 100644 --- a/tests/benchmarks/app_kernel/testcase.yaml +++ b/tests/benchmarks/app_kernel/testcase.yaml @@ -3,50 +3,16 @@ common: - benchmark - kernel timeout: 420 + min_flash: 34 + min_ram: 128 tests: benchmark.kernel.application: - min_flash: 34 integration_platforms: - mps2_an385 - qemu_x86 - benchmark.kernel.application.fp: - extra_args: CONF_FILE=prj_fp.conf - extra_configs: - - arch:x86:CONFIG_X86_SSE=y - - arch:x86:CONFIG_X86_SSE_FP_MATH=n - arch_allow: - - x86 - - arm - filter: CONFIG_CPU_HAS_FPU or CONFIG_ARMV7_M_ARMV8_M_FP - min_flash: 34 - min_ram: 32 - slow: true - toolchain_exclude: - - llvm - - oneApi - integration_platforms: - - qemu_x86 - benchmark.kernel.application.fp.x86.no_sse: - extra_args: CONF_FILE=prj_fp.conf - extra_configs: - - CONFIG_X86_SSE=n - - CONFIG_X86_SSE_FP_MATH=n - arch_allow: x86 - filter: CONFIG_CPU_HAS_FPU - min_flash: 34 - min_ram: 32 - slow: true - integration_platforms: - - qemu_x86 - benchmark.kernel.application.fp.x86.sse: - extra_args: CONF_FILE=prj_fp.conf - extra_configs: - - CONFIG_X86_SSE=y - - CONFIG_X86_SSE_FP_MATH=y - arch_allow: x86 - filter: CONFIG_CPU_HAS_FPU - min_flash: 34 - min_ram: 32 - slow: true + benchmark.kernel.application.user: + extra_args: CONF_FILE=prj_user.conf + filter: CONFIG_ARCH_HAS_USERSPACE integration_platforms: - qemu_x86 + - qemu_cortex_a53 diff --git a/tests/benchmarks/cmsis_dsp/basicmath/prj.conf b/tests/benchmarks/cmsis_dsp/basicmath/prj.conf index ad76c3a269a..b2e3d9799b8 100644 --- a/tests/benchmarks/cmsis_dsp/basicmath/prj.conf +++ b/tests/benchmarks/cmsis_dsp/basicmath/prj.conf @@ -1,5 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_CMSIS_DSP=y -CONFIG_CMSIS_DSP_BASICMATH=y diff --git a/tests/benchmarks/cmsis_dsp/basicmath/testcase.yaml b/tests/benchmarks/cmsis_dsp/basicmath/testcase.yaml index df3ab65a9c7..c2527111322 100644 --- a/tests/benchmarks/cmsis_dsp/basicmath/testcase.yaml +++ b/tests/benchmarks/cmsis_dsp/basicmath/testcase.yaml @@ -1,27 +1,24 @@ +common: + arch_allow: arm + filter: (CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + == 1 + tags: + - benchmark + - cmsis_dsp + min_flash: 128 + min_ram: 64 tests: benchmark.cmsis_dsp.basicmath: - filter: (CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1 integration_platforms: - frdm_k64f - sam_e70_xplained - mps2_an521 - tags: - - benchmark - - cmsis_dsp - min_flash: 128 - min_ram: 64 benchmark.cmsis_dsp.basicmath.fpu: - filter: (CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_CPU_HAS_FPU integration_platforms: - mps2_an521_remote - mps3_an547 tags: - - benchmark - - cmsis_dsp - fpu extra_configs: - CONFIG_FPU=y - min_flash: 128 - min_ram: 64 diff --git a/tests/benchmarks/data_structure_perf/dlist_perf/prj.conf b/tests/benchmarks/data_structure_perf/dlist_perf/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/benchmarks/data_structure_perf/dlist_perf/prj.conf +++ b/tests/benchmarks/data_structure_perf/dlist_perf/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/benchmarks/data_structure_perf/rbtree_perf/prj.conf b/tests/benchmarks/data_structure_perf/rbtree_perf/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/benchmarks/data_structure_perf/rbtree_perf/prj.conf +++ b/tests/benchmarks/data_structure_perf/rbtree_perf/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/benchmarks/footprints/src/pm_device.c b/tests/benchmarks/footprints/src/pm_device.c index 6b2e6f32e50..028eff1e3f9 100644 --- a/tests/benchmarks/footprints/src/pm_device.c +++ b/tests/benchmarks/footprints/src/pm_device.c @@ -26,11 +26,11 @@ static int dummy_device_pm_action(const struct device *dev, PM_DEVICE_DEFINE(dummy_pm_driver, dummy_device_pm_action); DEVICE_DEFINE(dummy_pm_driver, DUMMY_PM_DRIVER_NAME, NULL, - PM_DEVICE_GET(dummy_pm_driver), NULL, NULL, APPLICATION, + PM_DEVICE_GET(dummy_pm_driver), NULL, NULL, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, NULL); DEVICE_DEFINE(dummy_driver, DUMMY_DRIVER_NAME, NULL, NULL, NULL, NULL, - APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, NULL); + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, NULL); void run_pm_device(void) { diff --git a/tests/benchmarks/footprints/src/userspace.c b/tests/benchmarks/footprints/src/userspace.c index 231c4279137..ef6a62cdeac 100644 --- a/tests/benchmarks/footprints/src/userspace.c +++ b/tests/benchmarks/footprints/src/userspace.c @@ -11,7 +11,7 @@ */ #include #include -#include +#include #include #include "footprint.h" @@ -41,9 +41,9 @@ int z_impl_validation_overhead_syscall(void) static inline int z_vrfy_validation_overhead_syscall(void) { - bool status_0 = Z_SYSCALL_OBJ_INIT(&test_sema, K_OBJ_SEM); + bool status_0 = K_SYSCALL_OBJ_INIT(&test_sema, K_OBJ_SEM); - bool status_1 = Z_SYSCALL_OBJ(&test_sema, K_OBJ_SEM); + bool status_1 = K_SYSCALL_OBJ(&test_sema, K_OBJ_SEM); return status_0 || status_1; } diff --git a/tests/benchmarks/footprints/src/workq.c b/tests/benchmarks/footprints/src/workq.c index a00afd732a8..2ad2d0152c7 100644 --- a/tests/benchmarks/footprints/src/workq.c +++ b/tests/benchmarks/footprints/src/workq.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include "footprint.h" diff --git a/tests/benchmarks/latency_measure/README.rst b/tests/benchmarks/latency_measure/README.rst index 160dc184e40..7f17e979697 100644 --- a/tests/benchmarks/latency_measure/README.rst +++ b/tests/benchmarks/latency_measure/README.rst @@ -1,44 +1,109 @@ Latency Measurements #################### -This benchmark measures the latency of selected kernel capabilities, including: +This benchmark measures the average latency of selected kernel capabilities, +including: - -* Measure time to switch from ISR back to interrupted thread -* Measure time from ISR to executing a different thread (rescheduled) -* Measure average time to signal a semaphore then test that semaphore -* Measure average time to signal a semaphore then test that semaphore with a context switch -* Measure average time to lock a mutex then unlock that mutex -* Measure average context switch time between threads using (k_yield) -* Measure average context switch time between threads (coop) -* Time it takes to suspend a thread -* Time it takes to resume a suspended thread +* Context switch time between preemptive threads using k_yield +* Context switch time between cooperative threads using k_yield +* Time to switch from ISR back to interrupted thread +* Time from ISR to executing a different thread (rescheduled) +* Times to signal a semaphore then test that semaphore +* Times to signal a semaphore then test that semaphore with a context switch +* Times to lock a mutex then unlock that mutex * Time it takes to create a new thread (without starting it) * Time it takes to start a newly created thread +* Time it takes to suspend a thread +* Time it takes to resume a suspended thread +* Time it takes to abort a thread * Measure average time to alloc memory from heap then free that memory +When userspace is enabled using the prj_user.conf configuration file, this benchmark will +where possible, also test the above capabilities using various configurations involving user +threads: + +* Kernel thread to kernel thread +* Kernel thread to user thread +* User thread to kernel thread +* User thread to user thread + +Sample output of the benchmark (without userspace enabled):: + + *** Booting Zephyr OS build v3.5.0-rc1-139-gdab69aeed11d *** + START - Time Measurement + Timing results: Clock frequency: 120 MHz + Preemptive threads ctx switch via k_yield (K -> K) : 519 cycles , 4325 ns : + Cooperative threads ctx switch via k_yield (K -> K) : 519 cycles , 4325 ns : + Switch from ISR back to interrupted thread : 508 cycles , 4241 ns : + Switch from ISR to another thread (kernel) : 554 cycles , 4616 ns : + Create kernel thread from kernel thread : 396 cycles , 3308 ns : + Start kernel thread from kernel thread : 603 cycles , 5033 ns : + Suspend kernel thread from kernel thread : 599 cycles , 4992 ns : + Resume kernel thread from kernel thread : 547 cycles , 4558 ns : + Abort kernel thread from kernel thread : 339 cycles , 2825 ns : + Give a semaphore (no waiters) from kernel thread : 134 cycles , 1116 ns : + Take a semaphore (no blocking) from kernel thread : 53 cycles , 441 ns : + Take a semaphore (context switch K -> K) : 689 cycles , 5742 ns : + Give a semaphore (context switch K -> K) : 789 cycles , 6575 ns : + Lock a mutex from kernel thread : 94 cycles , 783 ns : + Unlock a mutex from kernel thread : 24 cycles , 200 ns : + Average time for heap malloc : 620 cycles , 5166 ns : + Average time for heap free : 431 cycles , 3591 ns : + =================================================================== + PROJECT EXECUTION SUCCESSFUL -Sample output of the benchmark:: +Sample output of the benchmark (with userspace enabled):: - *** Booting Zephyr OS build zephyr-v2.6.0-1119-g378a1e082ac5 *** + *** Booting Zephyr OS build v3.5.0-rc1-139-gdab69aeed11d *** START - Time Measurement - Timing results: Clock frequency: 1000 MHz - Average thread context switch using yield : 9060 cycles , 9060 ns - Average context switch time between threads (coop) : 9503 cycles , 9503 ns - Switch from ISR back to interrupted thread : 14208 cycles , 14208 ns - Time from ISR to executing a different thread : 9664 cycles , 9664 ns - Time to create a thread (without start) : 3968 cycles , 3968 ns - Time to start a thread : 12064 cycles , 12064 ns - Time to suspend a thread : 12640 cycles , 12640 ns - Time to resume a thread : 12096 cycles , 12096 ns - Time to abort a thread (not running) : 2208 cycles , 2208 ns - Average semaphore signal time : 8928 cycles , 8928 ns - Average semaphore test time : 2048 cycles , 2048 ns - Semaphore take time (context switch) : 13472 cycles , 13472 ns - Semaphore give time (context switch) : 18400 cycles , 18400 ns - Average time to lock a mutex : 3072 cycles , 3072 ns - Average time to unlock a mutex : 9251 cycles , 9251 ns - Average time for heap malloc : 13056 cycles , 13056 ns - Average time for heap free : 7776 cycles , 7776 ns + Timing results: Clock frequency: 120 MHz + Preemptive threads ctx switch via k_yield (K -> K) : 1195 cycles , 9958 ns : + Preemptive threads ctx switch via k_yield (U -> U) : 1485 cycles , 12379 ns : + Preemptive threads ctx switch via k_yield (K -> U) : 1390 cycles , 11587 ns : + Preemptive threads ctx switch via k_yield (U -> K) : 1289 cycles , 10749 ns : + Cooperative threads ctx switch via k_yield (K -> K) : 1185 cycles , 9875 ns : + Cooperative threads ctx switch via k_yield (U -> U) : 1475 cycles , 12295 ns : + Cooperative threads ctx switch via k_yield (K -> U) : 1380 cycles , 11504 ns : + Cooperative threads ctx switch via k_yield (U -> K) : 1280 cycles , 10666 ns : + Switch from ISR back to interrupted thread : 1130 cycles , 9416 ns : + Switch from ISR to another thread (kernel) : 1184 cycles , 9874 ns : + Switch from ISR to another thread (user) : 1390 cycles , 11583 ns : + Create kernel thread from kernel thread : 985 cycles , 8208 ns : + Start kernel thread from kernel thread : 1275 cycles , 10625 ns : + Suspend kernel thread from kernel thread : 1220 cycles , 10167 ns : + Resume kernel thread from kernel thread : 1193 cycles , 9942 ns : + Abort kernel thread from kernel thread : 2555 cycles , 21292 ns : + Create user thread from kernel thread : 849 cycles , 7083 ns : + Start user thread from kernel thread : 6715 cycles , 55960 ns : + Suspend user thread from kernel thread : 1585 cycles , 13208 ns : + Resume user thread from kernel thread : 1383 cycles , 11525 ns : + Abort user thread from kernel thread : 2420 cycles , 20167 ns : + Create user thread from user thread : 2110 cycles , 17584 ns : + Start user thread from user thread : 7070 cycles , 58919 ns : + Suspend user thread from user thread : 1784 cycles , 14874 ns : + Resume user thread from user thread : 1740 cycles , 14502 ns : + Abort user thread from user thread : 3000 cycles , 25000 ns : + Start kernel thread from user thread : 1630 cycles , 13583 ns : + Suspend kernel thread from user thread : 1420 cycles , 11833 ns : + Resume kernel thread from user thread : 1550 cycles , 12917 ns : + Abort kernel thread from user thread : 3135 cycles , 26125 ns : + Give a semaphore (no waiters) from kernel thread : 160 cycles , 1333 ns : + Take a semaphore (no blocking) from kernel thread : 95 cycles , 791 ns : + Give a semaphore (no waiters) from user thread : 380 cycles , 3166 ns : + Take a semaphore (no blocking) from user thread : 315 cycles , 2625 ns : + Take a semaphore (context switch K -> K) : 1340 cycles , 11167 ns : + Give a semaphore (context switch K -> K) : 1460 cycles , 12167 ns : + Take a semaphore (context switch K -> U) : 1540 cycles , 12838 ns : + Give a semaphore (context switch U -> K) : 1800 cycles , 15000 ns : + Take a semaphore (context switch U -> K) : 1690 cycles , 14084 ns : + Give a semaphore (context switch K -> U) : 1650 cycles , 13750 ns : + Take a semaphore (context switch U -> U) : 1890 cycles , 15756 ns : + Give a semaphore (context switch U -> U) : 1990 cycles , 16583 ns : + Lock a mutex from kernel thread : 105 cycles , 875 ns : + Unlock a mutex from kernel thread : 17 cycles , 141 ns : + Lock a mutex from user thread : 330 cycles , 2750 ns : + Unlock a mutex from user thread : 255 cycles , 2125 ns : + Average time for heap malloc : 606 cycles , 5058 ns : + Average time for heap free : 422 cycles , 3516 ns : =================================================================== PROJECT EXECUTION SUCCESSFUL diff --git a/tests/benchmarks/latency_measure/prj.conf b/tests/benchmarks/latency_measure/prj.conf index 4a786177bbc..d1bc5fbaa17 100644 --- a/tests/benchmarks/latency_measure/prj.conf +++ b/tests/benchmarks/latency_measure/prj.conf @@ -2,7 +2,6 @@ CONFIG_TEST=y # eliminate timer interrupts during the benchmark CONFIG_SYS_CLOCK_TICKS_PER_SEC=1 -CONFIG_TICKLESS_KERNEL=n # We use irq_offload(), enable it CONFIG_IRQ_OFFLOAD=y @@ -24,3 +23,4 @@ CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_TIMING_FUNCTIONS=y CONFIG_HEAP_MEM_POOL_SIZE=2048 +CONFIG_APPLICATION_DEFINED_SYSCALL=y diff --git a/tests/benchmarks/latency_measure/prj_user.conf b/tests/benchmarks/latency_measure/prj_user.conf new file mode 100644 index 00000000000..92ca89a3bea --- /dev/null +++ b/tests/benchmarks/latency_measure/prj_user.conf @@ -0,0 +1,27 @@ +CONFIG_TEST=y + +# eliminate timer interrupts during the benchmark +CONFIG_SYS_CLOCK_TICKS_PER_SEC=1 + +# We use irq_offload(), enable it +CONFIG_IRQ_OFFLOAD=y + +# Reduce memory/code footprint +CONFIG_BT=n +CONFIG_FORCE_NO_ASSERT=y + +CONFIG_TEST_HW_STACK_PROTECTION=n +# Disable HW Stack Protection (see #28664) +CONFIG_HW_STACK_PROTECTION=n +CONFIG_COVERAGE=n + +# Disable system power management +CONFIG_PM=n + +# Can only run under 1 CPU +CONFIG_MP_MAX_NUM_CPUS=1 +CONFIG_TIMING_FUNCTIONS=y + +CONFIG_HEAP_MEM_POOL_SIZE=2048 +CONFIG_APPLICATION_DEFINED_SYSCALL=y +CONFIG_USERSPACE=y diff --git a/tests/benchmarks/latency_measure/src/coop_ctx_switch.c b/tests/benchmarks/latency_measure/src/coop_ctx_switch.c deleted file mode 100644 index 1cecda1358c..00000000000 --- a/tests/benchmarks/latency_measure/src/coop_ctx_switch.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2012-2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * - * @brief Measure context switch time between cooperative threads - * - * This file contains thread (coop) context switch time measurement. - * The thread starts two cooperative thread. One thread waits on a semaphore. The other, - * after starting, releases a semaphore which enable the first thread to run. - * Each thread increases a common global counter and context switch back and - * forth by yielding the cpu. When counter reaches the maximal value, threads - * stop and the average time of context switch is displayed. - */ -#include -#include -#include "utils.h" - -/* number of context switches */ -#define NCTXSWITCH 10000 -#ifndef STACKSIZE -#define STACKSIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE) -#endif - -/* stack used by the threads */ -static K_THREAD_STACK_DEFINE(thread_one_stack, STACKSIZE); -static K_THREAD_STACK_DEFINE(thread_two_stack, STACKSIZE); -static struct k_thread thread_one_data; -static struct k_thread thread_two_data; - -static timing_t timestamp_start; -static timing_t timestamp_end; - -/* context switches counter */ -static volatile uint32_t ctx_switch_counter; - -/* context switch balancer. Incremented by one thread, decremented by another*/ -static volatile int ctx_switch_balancer; - -K_SEM_DEFINE(sync_sema, 0, 1); - -/** - * - * thread_one - * - * Fiber makes all the test preparations: registers the interrupt handler, - * gets the first timestamp and invokes the software interrupt. - * - */ -static void thread_one(void) -{ - k_sem_take(&sync_sema, K_FOREVER); - - timestamp_start = timing_counter_get(); - - while (ctx_switch_counter < NCTXSWITCH) { - k_yield(); - ctx_switch_counter++; - ctx_switch_balancer--; - } - - timestamp_end = timing_counter_get(); -} - -/** - * - * @brief Check the time when it gets executed after the semaphore - * - * Fiber starts, waits on semaphore. When the interrupt handler releases - * the semaphore, thread measures the time. - * - * @return 0 on success - */ -static void thread_two(void) -{ - k_sem_give(&sync_sema); - while (ctx_switch_counter < NCTXSWITCH) { - k_yield(); - ctx_switch_counter++; - ctx_switch_balancer++; - } -} - -/** - * - * @brief The test main function - * - * @return 0 on success - */ -int coop_ctx_switch(void) -{ - ctx_switch_counter = 0U; - ctx_switch_balancer = 0; - char error_string[80]; - const char *notes = ""; - bool failed = false; - int end; - - timing_start(); - bench_test_start(); - - k_thread_create(&thread_one_data, thread_one_stack, STACKSIZE, - (k_thread_entry_t)thread_one, NULL, NULL, NULL, - K_PRIO_COOP(6), 0, K_NO_WAIT); - k_thread_create(&thread_two_data, thread_two_stack, STACKSIZE, - (k_thread_entry_t)thread_two, NULL, NULL, NULL, - K_PRIO_COOP(6), 0, K_NO_WAIT); - - end = bench_test_end(); - - if (ctx_switch_balancer > 3 || ctx_switch_balancer < -3) { - error_count++; - snprintk(error_string, 78, " Balance is %d", - ctx_switch_balancer); - notes = error_string; - failed = true; - } else if (end != 0) { - error_count++; - notes = TICK_OCCURRENCE_ERROR; - } - - uint32_t diff; - - diff = timing_cycles_get(×tamp_start, ×tamp_end); - PRINT_STATS_AVG("Average context switch time between threads (coop)", - diff, ctx_switch_counter, failed, notes); - - timing_stop(); - - return 0; -} diff --git a/tests/benchmarks/latency_measure/src/int_to_thread.c b/tests/benchmarks/latency_measure/src/int_to_thread.c index 50c4c56555b..ad3cf70fad7 100644 --- a/tests/benchmarks/latency_measure/src/int_to_thread.c +++ b/tests/benchmarks/latency_measure/src/int_to_thread.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2014 Wind River Systems, Inc. - * Copyright (c) 2017 Intel Corporation. + * Copyright (c) 2017, 2023 Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,48 +10,151 @@ * * @brief Measure time from ISR back to interrupted thread * - * This file contains test that measures time to switch from the interrupt - * handler back to the interrupted thread. + * This file covers three interrupt to threads scenarios: + * 1. ISR returning to the interrupted kernel thread + * 2. ISR returning to a different (kernel) thread + * 3. ISR returning to a different (user) thread + * + * In all three scenarios, the source of the ISR is a software generated + * interrupt originating from a kernel thread. Ideally, these tests would + * also cover the scenarios where the interrupted thread is a user thread. + * However, some implementations of the irq_offload() routine lock interrupts, + * which is not allowed in userspace. */ #include #include "utils.h" +#include "timing_sc.h" #include -static volatile int flag_var; - -static timing_t timestamp_start; -static timing_t timestamp_end; +static K_SEM_DEFINE(isr_sem, 0, 1); /** + * @brief Test ISR used to measure time to return to thread * - * @brief Test ISR used to measure best case interrupt latency - * - * The interrupt handler gets the second timestamp. - * + * The interrupt handler gets the first timestamp used in the test. + * It then copies the timetsamp into a message queue and returns. */ -static void latency_test_isr(const void *unused) +static void test_isr(const void *arg) { - ARG_UNUSED(unused); - flag_var = 1; + struct k_sem *sem = (struct k_sem *)arg; - timestamp_start = timing_counter_get(); + if (arg != NULL) { + k_sem_give(sem); + } + + timestamp.sample = timing_timestamp_get(); } /** + * @brief Measure time to return from interrupt * - * @brief Interrupt preparation function - * - * Function makes all the test preparations: registers the interrupt handler, - * gets the first timestamp and invokes the software interrupt. - * + * This function is used to measure the time it takes to return from an + * interrupt. */ -static void make_int(void) +static void int_to_interrupted_thread(uint32_t num_iterations, uint64_t *sum) +{ + timing_t start; + timing_t finish; + + *sum = 0ull; + + for (uint32_t i = 0; i < num_iterations; i++) { + irq_offload(test_isr, NULL); + finish = timing_timestamp_get(); + start = timestamp.sample; + + *sum += timing_cycles_get(&start, &finish); + } +} + +static void start_thread_entry(void *p1, void *p2, void *p3) +{ + uint32_t num_iterations = (uint32_t)(uintptr_t)p1; + struct k_sem *sem = p2; + + ARG_UNUSED(p3); + + uint64_t sum = 0ull; + timing_t start; + timing_t finish; + + /* Ensure that is unavailable */ + + (void) k_sem_take(sem, K_NO_WAIT); + k_thread_start(&alt_thread); + + for (uint32_t i = 0; i < num_iterations; i++) { + + /* 1. Wait on an unavailable semaphore */ + + k_sem_take(sem, K_FOREVER); + + /* 3. Obtain the start and finish timestamps */ + + finish = timing_timestamp_get(); + start = timestamp.sample; + + sum += timing_cycles_get(&start, &finish); + } + + timestamp.cycles = sum; +} + +static void alt_thread_entry(void *p1, void *p2, void *p3) { - flag_var = 0; - irq_offload(latency_test_isr, NULL); - timestamp_end = timing_counter_get(); + uint32_t num_iterations = (uint32_t)(uintptr_t)p1; + struct k_sem *sem = p2; + + ARG_UNUSED(p3); + + for (uint32_t i = 0; i < num_iterations; i++) { + + /* 2. Trigger the test_isr() to execute */ + + irq_offload(test_isr, sem); + + /* + * ISR expected to have awakened higher priority start_thread + * thereby preempting alt_thread. + */ + } + + k_thread_join(&start_thread, K_FOREVER); +} + +static void int_to_another_thread(uint32_t num_iterations, uint64_t *sum, + uint32_t options) +{ + int priority; + *sum = 0ull; + + priority = k_thread_priority_get(k_current_get()); + + k_thread_create(&start_thread, start_stack, + K_THREAD_STACK_SIZEOF(start_stack), + start_thread_entry, + (void *)(uintptr_t)num_iterations, &isr_sem, NULL, + priority - 2, options, K_FOREVER); + + k_thread_create(&alt_thread, alt_stack, + K_THREAD_STACK_SIZEOF(alt_stack), + alt_thread_entry, + (void *)(uintptr_t)num_iterations, &isr_sem, NULL, + priority - 1, 0, K_FOREVER); + +#if CONFIG_USERSPACE + if (options != 0) { + k_thread_access_grant(&start_thread, &isr_sem, &alt_thread); + } +#endif + + k_thread_start(&start_thread); + + k_thread_join(&alt_thread, K_FOREVER); + + *sum = timestamp.cycles; } /** @@ -60,24 +163,40 @@ static void make_int(void) * * @return 0 on success */ -int int_to_thread(void) +int int_to_thread(uint32_t num_iterations) { - uint32_t diff; - bool failed = false; - const char *notes = ""; + uint64_t sum; timing_start(); TICK_SYNCH(); - make_int(); - if (flag_var != 1) { - error_count++; - notes = "Flag variable did not change"; - failed = true; - } - diff = timing_cycles_get(×tamp_start, ×tamp_end); - PRINT_STATS("Switch from ISR back to interrupted thread", - diff, failed, notes); + int_to_interrupted_thread(num_iterations, &sum); + + sum -= timestamp_overhead_adjustment(0, 0); + + PRINT_STATS_AVG("Switch from ISR back to interrupted thread", + (uint32_t)sum, num_iterations, false, ""); + + /* ************** */ + + int_to_another_thread(num_iterations, &sum, 0); + + sum -= timestamp_overhead_adjustment(0, 0); + + PRINT_STATS_AVG("Switch from ISR to another thread (kernel)", + (uint32_t)sum, num_iterations, false, ""); + + /* ************** */ + +#if CONFIG_USERSPACE + int_to_another_thread(num_iterations, &sum, K_USER); + + sum -= timestamp_overhead_adjustment(0, K_USER); + + PRINT_STATS_AVG("Switch from ISR to another thread (user)", + (uint32_t)sum, num_iterations, false, ""); +#endif + timing_stop(); return 0; } diff --git a/tests/benchmarks/latency_measure/src/int_to_thread_evt.c b/tests/benchmarks/latency_measure/src/int_to_thread_evt.c deleted file mode 100644 index 35ba280df3b..00000000000 --- a/tests/benchmarks/latency_measure/src/int_to_thread_evt.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2012-2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * - * @brief measure time from ISR to a rescheduled thread - * - * This file contains test that measures time to switch from an interrupt - * handler to executing a thread after rescheduling. In other words, execution - * after interrupt handler resume in a different thread than the one which got - * interrupted. - */ - -#include -#include - -#include "utils.h" - -static timing_t timestamp_start; -static timing_t timestamp_end; -static struct k_work work; - -K_SEM_DEFINE(INTSEMA, 0, 1); -K_SEM_DEFINE(WORKSEMA, 0, 1); - -/** - * - * @brief Test ISR used to measure best case interrupt latency - * - * The interrupt handler gets the second timestamp. - * - */ -static void latency_test_isr(const void *unused) -{ - ARG_UNUSED(unused); - - k_work_submit(&work); - timestamp_start = timing_counter_get(); -} - -static void worker(struct k_work *item) -{ - (void)item; - - timestamp_end = timing_counter_get(); - k_sem_give(&WORKSEMA); -} - -/** - * - * @brief Software interrupt generating thread - * - * Lower priority thread that, when it starts, it waits for a semaphore. When - * it gets it, released by the main thread, sets up the interrupt handler and - * generates the software interrupt - * - * @return 0 on success - */ -void int_thread(void) -{ - k_sem_take(&INTSEMA, K_FOREVER); - irq_offload(latency_test_isr, NULL); - k_thread_suspend(k_current_get()); -} - -K_THREAD_DEFINE(int_thread_id, 512, (k_thread_entry_t)int_thread, NULL, NULL, - NULL, 11, 0, 0); - -/** - * - * @brief The test main function - * - * @return 0 on success - */ -int int_to_thread_evt(void) -{ - uint32_t diff; - - k_work_init(&work, worker); - - timing_start(); - TICK_SYNCH(); - k_sem_give(&INTSEMA); - k_sem_take(&WORKSEMA, K_FOREVER); - timing_stop(); - - diff = timing_cycles_get(×tamp_start, ×tamp_end); - - PRINT_STATS("Time from ISR to executing a different thread", - diff, false, ""); - - return 0; -} diff --git a/tests/benchmarks/latency_measure/src/main.c b/tests/benchmarks/latency_measure/src/main.c index 3940184404a..499ce1273f1 100644 --- a/tests/benchmarks/latency_measure/src/main.c +++ b/tests/benchmarks/latency_measure/src/main.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2015 Wind River Systems, Inc. + * Copyright (c) 2023 Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,30 +10,58 @@ * This file contains the main testing module that invokes all the tests. */ +#include #include +#include #include "utils.h" +#include "timing_sc.h" #include +#define NUM_ITERATIONS 10000 + #define STACK_SIZE (1024 + CONFIG_TEST_EXTRA_STACK_SIZE) -uint32_t tm_off; /* time necessary to read the time */ +uint32_t tm_off; + +BENCH_BMEM struct timestamp_data timestamp; + +#ifdef CONFIG_USERSPACE +K_APPMEM_PARTITION_DEFINE(bench_mem_partition); +#endif + +K_THREAD_STACK_DEFINE(start_stack, START_STACK_SIZE); +K_THREAD_STACK_DEFINE(alt_stack, START_STACK_SIZE); + +K_SEM_DEFINE(pause_sem, 0, 1); + +struct k_thread start_thread; +struct k_thread alt_thread; + int error_count; /* track number of errors */ -extern void thread_switch_yield(void); -extern void int_to_thread(void); -extern void int_to_thread_evt(void); -extern void sema_test_signal(void); -extern void mutex_lock_unlock(void); -extern int coop_ctx_switch(void); -extern int sema_test(void); -extern int sema_context_switch(void); -extern int suspend_resume(void); +extern void thread_switch_yield(uint32_t num_iterations, bool is_cooperative); +extern void int_to_thread(uint32_t num_iterations); +extern void sema_test_signal(uint32_t num_iterations, uint32_t options); +extern void mutex_lock_unlock(uint32_t num_iterations, uint32_t options); +extern void sema_context_switch(uint32_t num_iterations, + uint32_t start_options, uint32_t alt_options); +extern int thread_ops(uint32_t num_iterations, uint32_t start_options, + uint32_t alt_options); extern void heap_malloc_free(void); -void test_thread(void *arg1, void *arg2, void *arg3) +static void test_thread(void *arg1, void *arg2, void *arg3) { uint32_t freq; + ARG_UNUSED(arg1); + ARG_UNUSED(arg2); + ARG_UNUSED(arg3); + +#ifdef CONFIG_USERSPACE + k_mem_domain_add_partition(&k_mem_domain_default, + &bench_mem_partition); +#endif + timing_init(); bench_test_init(); @@ -42,28 +71,49 @@ void test_thread(void *arg1, void *arg2, void *arg3) TC_START("Time Measurement"); TC_PRINT("Timing results: Clock frequency: %u MHz\n", freq); - thread_switch_yield(); + timestamp_overhead_init(NUM_ITERATIONS); + + /* Preemptive threads context switching */ + thread_switch_yield(NUM_ITERATIONS, false); - coop_ctx_switch(); + /* Cooperative threads context switching */ + thread_switch_yield(NUM_ITERATIONS, true); - int_to_thread(); + int_to_thread(NUM_ITERATIONS); - int_to_thread_evt(); + /* Thread creation, starting, suspending, resuming and aborting. */ - suspend_resume(); + thread_ops(NUM_ITERATIONS, 0, 0); +#ifdef CONFIG_USERSPACE + thread_ops(NUM_ITERATIONS, 0, K_USER); + thread_ops(NUM_ITERATIONS, K_USER, K_USER); + thread_ops(NUM_ITERATIONS, K_USER, 0); +#endif - sema_test_signal(); + sema_test_signal(NUM_ITERATIONS, 0); +#ifdef CONFIG_USERSPACE + sema_test_signal(NUM_ITERATIONS, K_USER); +#endif - sema_context_switch(); + sema_context_switch(NUM_ITERATIONS, 0, 0); +#ifdef CONFIG_USERSPACE + sema_context_switch(NUM_ITERATIONS, 0, K_USER); + sema_context_switch(NUM_ITERATIONS, K_USER, 0); + sema_context_switch(NUM_ITERATIONS, K_USER, K_USER); +#endif - mutex_lock_unlock(); + mutex_lock_unlock(NUM_ITERATIONS, 0); +#ifdef CONFIG_USERSPACE + mutex_lock_unlock(NUM_ITERATIONS, K_USER); +#endif heap_malloc_free(); TC_END_REPORT(error_count); } -K_THREAD_DEFINE(test_thread_id, STACK_SIZE, test_thread, NULL, NULL, NULL, K_PRIO_PREEMPT(10), 0, 0); +K_THREAD_DEFINE(test_thread_id, STACK_SIZE, test_thread, NULL, NULL, NULL, + K_PRIO_PREEMPT(10), 0, 0); int main(void) { diff --git a/tests/benchmarks/latency_measure/src/mutex_lock_unlock.c b/tests/benchmarks/latency_measure/src/mutex_lock_unlock.c index cfc8ae2118b..5ab52b43dcd 100644 --- a/tests/benchmarks/latency_measure/src/mutex_lock_unlock.c +++ b/tests/benchmarks/latency_measure/src/mutex_lock_unlock.c @@ -1,18 +1,65 @@ /* * Copyright (c) 2012-2015 Wind River Systems, Inc. - * Copyright (c) 2020 Intel Corporation + * Copyright (c) 2020,2023 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ +/* + * @file measure time for mutex lock and unlock + * + * This file contains the test that measures mutex lock and unlock times + * in the kernel. There is no contention on the mutex being tested. + */ + #include #include #include "utils.h" +#include "timing_sc.h" + +static K_MUTEX_DEFINE(test_mutex); + +static void start_lock_unlock(void *p1, void *p2, void *p3) +{ + uint32_t i; + uint32_t num_iterations = (uint32_t)(uintptr_t)p1; + timing_t start; + timing_t finish; + uint64_t lock_cycles; + uint64_t unlock_cycles; + + ARG_UNUSED(p2); + ARG_UNUSED(p3); -/* the number of mutex lock/unlock cycles */ -#define N_TEST_MUTEX 1000 + start = timing_timestamp_get(); -K_MUTEX_DEFINE(test_mutex); + /* Recursively lock take the mutex */ + + for (i = 0; i < num_iterations; i++) { + k_mutex_lock(&test_mutex, K_NO_WAIT); + } + + finish = timing_timestamp_get(); + + lock_cycles = timing_cycles_get(&start, &finish); + + start = timing_timestamp_get(); + + /* Recursively unlock the mutex */ + + for (i = 0; i < num_iterations; i++) { + k_mutex_unlock(&test_mutex); + } + + finish = timing_timestamp_get(); + + unlock_cycles = timing_cycles_get(&start, &finish); + + timestamp.cycles = lock_cycles; + k_sem_take(&pause_sem, K_FOREVER); + + timestamp.cycles = unlock_cycles; +} /** @@ -24,55 +71,43 @@ K_MUTEX_DEFINE(test_mutex); * * @return 0 on success */ -int mutex_lock_unlock(void) +int mutex_lock_unlock(uint32_t num_iterations, uint32_t options) { - int i; - uint32_t diff; - timing_t timestamp_start; - timing_t timestamp_end; - const char *notes = ""; - int end; + char description[80]; + int priority; + uint64_t cycles; timing_start(); - bench_test_start(); - timestamp_start = timing_counter_get(); + priority = k_thread_priority_get(k_current_get()); - for (i = 0; i < N_TEST_MUTEX; i++) { - k_mutex_lock(&test_mutex, K_FOREVER); - } + k_thread_create(&start_thread, start_stack, + K_THREAD_STACK_SIZEOF(start_stack), + start_lock_unlock, + (void *)(uintptr_t)num_iterations, NULL, NULL, + priority - 1, options, K_FOREVER); - timestamp_end = timing_counter_get(); - end = bench_test_end(); + k_thread_access_grant(&start_thread, &test_mutex, &pause_sem); + k_thread_start(&start_thread); - diff = timing_cycles_get(×tamp_start, ×tamp_end); + cycles = timestamp.cycles; + cycles -= timestamp_overhead_adjustment(options, options); + k_sem_give(&pause_sem); - if (end != 0) { - notes = TICK_OCCURRENCE_ERROR; - error_count++; - } + snprintf(description, sizeof(description), + "Lock a mutex from %s thread", + (options & K_USER) == K_USER ? "user" : "kernel"); + PRINT_STATS_AVG(description, (uint32_t)cycles, num_iterations, + false, ""); - PRINT_STATS_AVG("Average time to lock a mutex", diff, N_TEST_MUTEX, - false, notes); - - bench_test_start(); - timestamp_start = timing_counter_get(); - - for (i = 0; i < N_TEST_MUTEX; i++) { - k_mutex_unlock(&test_mutex); - } - - timestamp_end = timing_counter_get(); - end = bench_test_end(); - diff = timing_cycles_get(×tamp_start, ×tamp_end); - - if (end != 0) { - notes = TICK_OCCURRENCE_ERROR; - error_count++; - } + cycles = timestamp.cycles; + cycles -= timestamp_overhead_adjustment(options, options); - PRINT_STATS_AVG("Average time to unlock a mutex", diff, N_TEST_MUTEX, - false, notes); + snprintf(description, sizeof(description), + "Unlock a mutex from %s thread", + (options & K_USER) == K_USER ? "user" : "kernel"); + PRINT_STATS_AVG(description, (uint32_t)cycles, num_iterations, + false, ""); timing_stop(); return 0; diff --git a/tests/benchmarks/latency_measure/src/sema_test_signal_release.c b/tests/benchmarks/latency_measure/src/sema_test_signal_release.c index f5d2d4a8332..e5ea2b72992 100644 --- a/tests/benchmarks/latency_measure/src/sema_test_signal_release.c +++ b/tests/benchmarks/latency_measure/src/sema_test_signal_release.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2015 Wind River Systems, Inc. + * Copyright (c) 2023 Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,68 +8,218 @@ /* * @file measure time for sema lock and release * - * This file contains the test that measures semaphore and mutex lock and - * release time in the kernel. There is no contention on the sema nor the - * mutex being tested. + * This file contains the test that measures semaphore give and take time + * in the kernel. There is no contention on the semaphore being tested. */ #include #include #include "utils.h" +#include "timing_sc.h" -/* the number of semaphore give/take cycles */ -#define N_TEST_SEMA 1000 +static struct k_sem sem; -#define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE) -/* stack used by the threads */ -static K_THREAD_STACK_DEFINE(thread_one_stack, STACK_SIZE); +static void alt_thread_entry(void *p1, void *p2, void *p3) +{ + uint32_t num_iterations = (uint32_t)(uintptr_t)p1; + timing_t mid; + + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + for (uint32_t i = 0; i < num_iterations; i++) { + + /* + * 2. Give the semaphore, thereby forcing a context switch back + * to . + */ + + mid = timing_timestamp_get(); + k_sem_give(&sem); -static struct k_thread thread_one_data; + /* 5. Share the timestamp. */ -K_SEM_DEFINE(lock_unlock_sema, 0, N_TEST_SEMA); + timestamp.sample = mid; -K_SEM_DEFINE(sem_bench, 0, 1); + /* 6. Give so resumes execution */ -timing_t timestamp_start_sema_t_c; -timing_t timestamp_end_sema_t_c; -timing_t timestamp_start_sema_g_c; -timing_t timestamp_end_sema_g_c; + k_sem_give(&sem); + } +} -void thread_sema_test1(void *p1, void *p2, void *p3) +static void start_thread_entry(void *p1, void *p2, void *p3) { - timestamp_start_sema_t_c = timing_counter_get(); - k_sem_take(&sem_bench, K_FOREVER); - timestamp_end_sema_g_c = timing_counter_get(); + uint32_t num_iterations = (uint32_t)(uintptr_t)p1; + timing_t start; + timing_t mid; + timing_t finish; + uint32_t i; + uint64_t take_sum = 0ull; + uint64_t give_sum = 0ull; + + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + k_thread_start(&alt_thread); + + for (i = 0; i < num_iterations; i++) { + + /* + * 1. Block on taking the semaphore and force a context switch + * to . + */ + + start = timing_timestamp_get(); + k_sem_take(&sem, K_FOREVER); + + /* 3. Get the timestamp. */ + + finish = timing_timestamp_get(); + + /* + * 4. Let run so it can share its + * timestamp. + */ + + k_sem_take(&sem, K_FOREVER); + + /* 7. Retrieve the timestamp */ + + mid = timestamp.sample; + + take_sum += timing_cycles_get(&start, &mid); + give_sum += timing_cycles_get(&mid, &finish); + } + + k_thread_join(&alt_thread, K_FOREVER); + + /* Share the totals with the main thread */ + + timestamp.cycles = take_sum; + + k_sem_take(&sem, K_FOREVER); + + timestamp.cycles = give_sum; } -int sema_context_switch(void) +void sema_context_switch(uint32_t num_iterations, + uint32_t start_options, uint32_t alt_options) { - uint32_t diff; + uint64_t cycles; + char description[80]; + int priority; timing_start(); - k_thread_create(&thread_one_data, thread_one_stack, - STACK_SIZE, thread_sema_test1, - NULL, NULL, NULL, - K_PRIO_PREEMPT(3), 0, K_FOREVER); - k_thread_name_set(&thread_one_data, "sema_test1"); - k_thread_start(&thread_one_data); + priority = k_thread_priority_get(k_current_get()); + + k_thread_create(&start_thread, start_stack, + K_THREAD_STACK_SIZEOF(start_stack), + start_thread_entry, + (void *)(uintptr_t)num_iterations, NULL, NULL, + priority - 2, start_options, K_FOREVER); + + k_thread_create(&alt_thread, alt_stack, + K_THREAD_STACK_SIZEOF(alt_stack), + alt_thread_entry, + (void *)(uintptr_t)num_iterations, NULL, NULL, + priority - 1, alt_options, K_FOREVER); + + k_thread_access_grant(&start_thread, &sem, &alt_thread); + + k_thread_access_grant(&alt_thread, &sem); - timestamp_end_sema_t_c = timing_counter_get(); - diff = timing_cycles_get(×tamp_start_sema_t_c, ×tamp_end_sema_t_c); - PRINT_STATS("Semaphore take time (context switch)", diff, false, ""); + /* Start the test threads */ + k_thread_start(&start_thread); - timestamp_start_sema_g_c = timing_counter_get(); - k_sem_give(&sem_bench); - diff = timing_cycles_get(×tamp_start_sema_g_c, ×tamp_end_sema_g_c); - PRINT_STATS("Semaphore give time (context switch)", diff, false, ""); + /* Retrieve the number of cycles spent taking the semaphore */ + + cycles = timestamp.cycles; + cycles -= timestamp_overhead_adjustment(start_options, alt_options); + + snprintf(description, sizeof(description), + "Take a semaphore (context switch %c -> %c)", + ((start_options & K_USER) == K_USER) ? 'U' : 'K', + ((alt_options & K_USER) == K_USER) ? 'U' : 'K'); + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + + /* Unblock */ + + k_sem_give(&sem); + + /* Retrieve the number of cycles spent taking the semaphore */ + + cycles = timestamp.cycles; + cycles -= timestamp_overhead_adjustment(start_options, alt_options); + + snprintf(description, sizeof(description), + "Give a semaphore (context switch %c -> %c)", + ((alt_options & K_USER) == K_USER) ? 'U' : 'K', + ((start_options & K_USER) == K_USER) ? 'U' : 'K'); + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + + k_thread_join(&start_thread, K_FOREVER); timing_stop(); - return 0; + return; } +/** + * This is the entry point for the test that performs uncontested operations + * on the semaphore. It gives the semaphore many times, takes the semaphore + * many times and then sends the results back to the main thread. + */ +static void immediate_give_take(void *p1, void *p2, void *p3) +{ + uint32_t num_iterations = (uint32_t)(uintptr_t)p1; + timing_t start; + timing_t finish; + uint64_t give_cycles; + uint64_t take_cycles; + + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + /* 1. Give a semaphore. No threads are waiting on it */ + + start = timing_timestamp_get(); + + for (uint32_t i = 0; i < num_iterations; i++) { + k_sem_give(&sem); + } + + finish = timing_timestamp_get(); + give_cycles = timing_cycles_get(&start, &finish); + + /* 2. Take a semaphore--no contention */ + + start = timing_timestamp_get(); + + for (uint32_t i = 0; i < num_iterations; i++) { + k_sem_take(&sem, K_NO_WAIT); + } + + finish = timing_timestamp_get(); + take_cycles = timing_cycles_get(&start, &finish); + + /* 3. Post the number of cycles spent giving the semaphore */ + + timestamp.cycles = give_cycles; + + /* 4. Wait for the main thread to retrieve the data */ + + k_sem_take(&sem, K_FOREVER); + + /* 7. Post the number of cycles spent taking the semaphore */ + + timestamp.cycles = take_cycles; +} + + /** * * @brief The function tests semaphore test/signal time @@ -78,58 +229,60 @@ int sema_context_switch(void) * * @return 0 on success */ -int sema_test_signal(void) +int sema_test_signal(uint32_t num_iterations, uint32_t options) { - int i; - uint32_t diff; - timing_t timestamp_start; - timing_t timestamp_end; - const char *notes = ""; - int end; - - bench_test_start(); + uint64_t cycles; + int priority; + char description[80]; + timing_start(); - timestamp_start = timing_counter_get(); + k_sem_init(&sem, 0, num_iterations); - for (i = 0; i < N_TEST_SEMA; i++) { - k_sem_give(&lock_unlock_sema); - } + priority = k_thread_priority_get(k_current_get()); - timestamp_end = timing_counter_get(); - end = bench_test_end(); - timing_stop(); + k_thread_create(&start_thread, start_stack, + K_THREAD_STACK_SIZEOF(start_stack), + immediate_give_take, + (void *)(uintptr_t)num_iterations, NULL, NULL, + priority - 1, options, K_FOREVER); - if (end != 0) { - error_count++; - notes = TICK_OCCURRENCE_ERROR; - } + k_thread_access_grant(&start_thread, &sem); + k_thread_start(&start_thread); - diff = timing_cycles_get(×tamp_start, ×tamp_end); - PRINT_STATS_AVG("Average semaphore signal time", diff, N_TEST_SEMA, - false, notes); + /* 5. Retrieve the number of cycles spent giving the semaphore */ - bench_test_start(); - timing_start(); + cycles = timestamp.cycles; + cycles -= timestamp_overhead_adjustment(options, options); - timestamp_start = timing_counter_get(); + snprintf(description, sizeof(description), + "Give a semaphore (no waiters) from %s thread", + (options & K_USER) == K_USER ? "user" : "kernel"); - for (i = 0; i < N_TEST_SEMA; i++) { - k_sem_take(&lock_unlock_sema, K_FOREVER); - } + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); - timestamp_end = timing_counter_get(); - end = bench_test_end(); - timing_stop(); + /* 6. Unblock */ - if (end != 0) { - error_count++; - notes = TICK_OCCURRENCE_ERROR; - } + k_sem_give(&sem); + + /* 8. Wait for to finish */ + + k_thread_join(&start_thread, K_FOREVER); + + /* 9. Retrieve the number of cycles spent taking the semaphore */ - diff = timing_cycles_get(×tamp_start, ×tamp_end); - PRINT_STATS_AVG("Average semaphore test time", diff, N_TEST_SEMA, - false, notes); + cycles = timestamp.cycles; + cycles -= timestamp_overhead_adjustment(options, options); + + snprintf(description, sizeof(description), + "Take a semaphore (no blocking) from %s thread", + (options & K_USER) == K_USER ? "user" : "kernel"); + + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + + timing_stop(); return 0; } diff --git a/tests/benchmarks/latency_measure/src/thread.c b/tests/benchmarks/latency_measure/src/thread.c index 5178eef784c..4448b0e2304 100644 --- a/tests/benchmarks/latency_measure/src/thread.c +++ b/tests/benchmarks/latency_measure/src/thread.c @@ -1,86 +1,308 @@ /* - * Copyright (c) 2020 Intel Corporation + * Copyright (c) 2020, 2023 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ + +/* + * @file measure time for various thread operations + * + * This file contains the tests that measures the times for the following + * thread operations from both kernel threads and user threads: + * 1. Creating a thread + * 2. Starting a thread + * 3. Suspending a thread + * 4. Resuming a thread + * 5. Aborting a thread + * + * It is worthwhile to note that there is no measurement for creating a kernel + * thread from a user thread as that is an invalid operation. + */ + #include #include #include "utils.h" +#include "timing_sc.h" #define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE) -/* stack used by the threads */ -static K_THREAD_STACK_DEFINE(t1_stack, STACK_SIZE); -static struct k_thread t1; +#define START_ALT 0x01 +#define ALT_USER 0x02 + +static void alt_thread_entry(void *p1, void *p2, void *p3) +{ + int priority; + + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); -timing_t timestamp_start_create_c; -timing_t timestamp_end_create_c; -timing_t timestamp_start_start_c; -timing_t timestamp_end_start_c; -timing_t timestamp_start_suspend_c; -timing_t timestamp_end_suspend_c; -timing_t timestamp_start_resume_c; -timing_t timestamp_end_resume_c; + /* 3. Finish measuring time to start */ -timing_t timestamp_start_abort_1; -timing_t timestamp_end_abort_1; + timestamp.sample = timing_timestamp_get(); -void thread_suspend_resume(void *p1, void *p2, void *p3) + /* 4. Let process the time measurement. */ + + k_sem_take(&pause_sem, K_FOREVER); /* Let 'start_thread' execute */ + + /* 7. Begin measuring time to suspend active thread (self/alt_thread) */ + + timestamp.sample = timing_timestamp_get(); + k_thread_suspend(&alt_thread); + + /* 10. Finish measuring time to resume (self) */ + + timestamp.sample = timing_timestamp_get(); + + /* 11. Lower the priority so can terminate us. */ + + priority = k_thread_priority_get(&alt_thread); + k_thread_priority_set(&alt_thread, priority + 2); +} + +static void start_thread_entry(void *p1, void *p2, void *p3) { - timestamp_start_suspend_c = timing_counter_get(); - k_thread_suspend(_current); + uint32_t num_iterations = (uint32_t)(uintptr_t)p1; + uint32_t bit_options = (uint32_t)(uintptr_t)p2; + timing_t start; + timing_t finish; + uint64_t thread_create_sum = 0ull; + uint64_t thread_start_sum = 0ull; + uint64_t thread_suspend_sum = 0ull; + uint64_t thread_resume_sum = 0ull; + uint64_t thread_abort_sum = 0ull; + int priority; + + ARG_UNUSED(p3); + + priority = k_thread_priority_get(&start_thread); + + for (uint32_t i = 0; i < num_iterations; i++) { + + /* 1. Measure time to create, but not start */ + + if ((bit_options & START_ALT) == START_ALT) { + start = timing_timestamp_get(); + k_thread_create(&alt_thread, alt_stack, + K_THREAD_STACK_SIZEOF(alt_stack), + alt_thread_entry, NULL, NULL, NULL, + priority, + (bit_options & ALT_USER) == ALT_USER ? + K_USER : 0, K_FOREVER); + finish = timing_timestamp_get(); + + thread_create_sum += timing_cycles_get(&start, &finish); + } else { + + /* + * Wait for the "main" thread to create + * as this thread can not do it. + */ + + k_sem_take(&pause_sem, K_FOREVER); + } + + if ((bit_options & ALT_USER) == ALT_USER) { + k_thread_access_grant(&alt_thread, &pause_sem); + } + + /* + * Let the main thread change the priority of + * to a higher priority level as user threads may not create + * a thread of higher priority than itself. + */ + + k_sem_take(&pause_sem, K_FOREVER); + + + /* 2. Begin measuring time to start */ + + start = timing_timestamp_get(); + k_thread_start(&alt_thread); + + /* 5. Process the time to start */ - /* comes to this line once its resumed*/ - timestamp_start_resume_c = timing_counter_get(); + finish = timestamp.sample; + thread_start_sum += timing_cycles_get(&start, &finish); + /* 6. Allow to continue */ + + k_sem_give(&pause_sem); + + /* 8. Finish measuring time to suspend */ + + start = timestamp.sample; + finish = timing_timestamp_get(); + thread_suspend_sum += timing_cycles_get(&start, &finish); + + /* 9. Being measuring time to resume */ + + start = timing_timestamp_get(); + k_thread_resume(&alt_thread); + + /* 12. Process the time it took to resume */ + + finish = timestamp.sample; + thread_resume_sum += timing_cycles_get(&start, &finish); + + /* 13. Process the time to terminate */ + + start = timing_timestamp_get(); + k_thread_abort(&alt_thread); + finish = timing_timestamp_get(); + thread_abort_sum += timing_cycles_get(&start, &finish); + } + + timestamp.cycles = thread_create_sum; + k_sem_take(&pause_sem, K_FOREVER); + + timestamp.cycles = thread_start_sum; + k_sem_take(&pause_sem, K_FOREVER); + + timestamp.cycles = thread_suspend_sum; + k_sem_take(&pause_sem, K_FOREVER); + + timestamp.cycles = thread_resume_sum; + k_sem_take(&pause_sem, K_FOREVER); + + timestamp.cycles = thread_abort_sum; + k_sem_take(&pause_sem, K_FOREVER); } -int suspend_resume(void) +int thread_ops(uint32_t num_iterations, uint32_t start_options, uint32_t alt_options) { - uint32_t diff; + int priority; + uint64_t cycles; + uint32_t bit_options = START_ALT; + char description[80]; + + priority = k_thread_priority_get(k_current_get()); timing_start(); - timestamp_start_create_c = timing_counter_get(); + /* + * Determine if is allowed to start . + * If it can not, then can not create as it + * would be a user thread trying to create a kernel + * thread. Instead, create here. + */ + + k_thread_create(&alt_thread, alt_stack, + K_THREAD_STACK_SIZEOF(alt_stack), + alt_thread_entry, + NULL, NULL, NULL, + priority - 1, alt_options, K_FOREVER); + + /* Give sends us back to */ + + k_sem_give(&pause_sem); + } + + /* + * needs to be of higher priority than + * , which can not always be done in + * as sometimes it is a user thread. + */ + + k_thread_priority_set(&alt_thread, priority - 2); + k_sem_give(&pause_sem); + } + + cycles = timestamp.cycles; + cycles -= timestamp_overhead_adjustment(start_options, alt_options); + k_sem_give(&pause_sem); + + if ((bit_options & START_ALT) == START_ALT) { + + /* Only report stats if created */ + + snprintf(description, sizeof(description), + "Create %s thread from %s thread", + (alt_options & K_USER) != 0 ? "user" : "kernel", + (start_options & K_USER) != 0 ? "user" : "kernel"); + + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + } + + cycles = timestamp.cycles; + cycles -= timestamp_overhead_adjustment(start_options, alt_options); + k_sem_give(&pause_sem); - k_tid_t t1_tid = k_thread_create(&t1, t1_stack, STACK_SIZE, - thread_suspend_resume, NULL, NULL, - NULL, K_PRIO_PREEMPT(6), 0, K_FOREVER); + snprintf(description, sizeof(description), + "Start %s thread from %s thread", + (alt_options & K_USER) != 0 ? "user" : "kernel", + (start_options & K_USER) != 0 ? "user" : "kernel"); - timestamp_end_create_c = timing_counter_get(); - k_thread_name_set(t1_tid, "t1"); + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); - timestamp_start_start_c = timing_counter_get(); - k_thread_start(t1_tid); + cycles = timestamp.cycles; + cycles -= timestamp_overhead_adjustment(start_options, alt_options); + k_sem_give(&pause_sem); - timestamp_end_suspend_c = timing_counter_get(); - k_thread_resume(t1_tid); - timestamp_end_resume_c = timing_counter_get(); + snprintf(description, sizeof(description), + "Suspend %s thread from %s thread", + (alt_options & K_USER) != 0 ? "user" : "kernel", + (start_options & K_USER) != 0 ? "user" : "kernel"); + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); - diff = timing_cycles_get(×tamp_start_create_c, - ×tamp_end_create_c); - PRINT_STATS("Time to create a thread (without start)", diff, false, ""); + cycles = timestamp.cycles; + cycles -= timestamp_overhead_adjustment(start_options, alt_options); + k_sem_give(&pause_sem); - diff = timing_cycles_get(×tamp_start_start_c, - ×tamp_start_suspend_c); - PRINT_STATS("Time to start a thread", diff, false, ""); + snprintf(description, sizeof(description), + "Resume %s thread from %s thread", + (alt_options & K_USER) != 0 ? "user" : "kernel", + (start_options & K_USER) != 0 ? "user" : "kernel"); - diff = timing_cycles_get(×tamp_start_suspend_c, - ×tamp_end_suspend_c); - PRINT_STATS("Time to suspend a thread", diff, false, ""); + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); - diff = timing_cycles_get(×tamp_start_resume_c, - ×tamp_end_resume_c); - PRINT_STATS("Time to resume a thread", diff, false, ""); + cycles = timestamp.cycles; + cycles -= timestamp_overhead_adjustment(start_options, alt_options); + k_sem_give(&pause_sem); - timestamp_start_abort_1 = timing_counter_get(); - k_thread_abort(t1_tid); - timestamp_end_abort_1 = timing_counter_get(); + snprintf(description, sizeof(description), + "Abort %s thread from %s thread", + (alt_options & K_USER) != 0 ? "user" : "kernel", + (start_options & K_USER) != 0 ? "user" : "kernel"); - diff = timing_cycles_get(×tamp_start_abort_1, - ×tamp_end_abort_1); - PRINT_STATS("Time to abort a thread (not running)", diff, false, ""); + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); timing_stop(); return 0; diff --git a/tests/benchmarks/latency_measure/src/thread_switch_yield.c b/tests/benchmarks/latency_measure/src/thread_switch_yield.c index 4df75a16884..44ccc5932c5 100644 --- a/tests/benchmarks/latency_measure/src/thread_switch_yield.c +++ b/tests/benchmarks/latency_measure/src/thread_switch_yield.c @@ -1,113 +1,171 @@ /* * Copyright (c) 2012-2014 Wind River Systems, Inc. + * Copyright (c) 2023 Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 */ /** * @file - * This file contains the benchmark that measure the average time it takes to - * do context switches between threads using k_yield () to force - * context switch. + * This file contains the benchmarking code that measures the average time it + * takes to perform context switches between threads using k_yield(). + * + * When user threads are supported, there are four cases to consider. These are + * 1. Kernel thread -> Kernel thread + * 2. User thread -> User thread + * 3. Kernel thread -> User thread + * 4. User thread -> Kernel thread */ #include #include #include #include -#include "utils.h" /* PRINT () and other macros */ -/* context switch enough time so our measurement is precise */ -#define NB_OF_YIELD 1000 +#include "utils.h" +#include "timing_sc.h" -static uint32_t helper_thread_iterations; +static void alt_thread_entry(void *p1, void *p2, void *p3) +{ + uint32_t num_iterations; -#define Y_STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE) -#define Y_PRIORITY K_PRIO_PREEMPT(10) + ARG_UNUSED(p2); + ARG_UNUSED(p2); -K_THREAD_STACK_DEFINE(y_stack_area, Y_STACK_SIZE); -static struct k_thread y_thread; + num_iterations = (uint32_t)(uintptr_t)p1; + + for (uint32_t i = 0; i < num_iterations; i++) { + + /* 3. Obtain the 'finish' timestamp */ + + timestamp.sample = timing_timestamp_get(); + + /* 4. Switch to */ -/** - * @brief Helper thread for measuring thread switch latency using yield - */ -void yielding_thread(void *arg1, void *arg2, void *arg3) -{ - while (helper_thread_iterations < NB_OF_YIELD) { k_yield(); - helper_thread_iterations++; } + } -/** - * @brief Entry point for thread context switch using yield test - */ -void thread_switch_yield(void) +static void start_thread_entry(void *p1, void *p2, void *p3) { - uint32_t iterations = 0U; - int32_t delta; - timing_t timestamp_start; - timing_t timestamp_end; - uint32_t ts_diff; - const char *notes = ""; - char error_string[80]; - bool failed = false; - int end; - - timing_start(); - bench_test_start(); - - /* launch helper thread of the same priority as the thread - * of routine - */ - k_thread_create(&y_thread, y_stack_area, Y_STACK_SIZE, yielding_thread, - NULL, NULL, NULL, Y_PRIORITY, 0, K_NO_WAIT); - - /* get initial timestamp */ - timestamp_start = timing_counter_get(); - - /* loop until either helper or this routine reaches number of yields */ - while (iterations < NB_OF_YIELD && - helper_thread_iterations < NB_OF_YIELD) { + uint64_t sum = 0ull; + uint32_t num_iterations; + timing_t start; + timing_t finish; + + ARG_UNUSED(p2); + ARG_UNUSED(p2); + + num_iterations = (uint32_t)(uintptr_t)p1; + + k_thread_start(&alt_thread); + + for (uint32_t i = 0; i < num_iterations; i++) { + + /* 1. Get 'start' timestamp */ + + start = timing_timestamp_get(); + + /* 2. Switch to */ + k_yield(); - iterations++; + + /* 5. Get the 'finish' timestamp obtained in */ + + finish = timestamp.sample; + + /* 6. Track the sum of elapsed times */ + + sum += timing_cycles_get(&start, &finish); } - /* get the number of cycles it took to do the test */ - timestamp_end = timing_counter_get(); - end = bench_test_end(); - - /* Ensure both helper and this routine were context switching back & - * forth. - * For execution to reach the line below, either this routine or helper - * routine reached NB_OF_YIELD. The other loop must be at most one - * iteration away from reaching NB_OF_YIELD if execute was switching - * back and forth. - */ - delta = iterations - helper_thread_iterations; - if (abs(delta) > 1) { - /* expecting even alternating context switch, seems one routine - * called yield without the other having chance to execute - */ - error_count++; - snprintk(error_string, 78, - "Error: iteration:%u : helper iteration:%u", - iterations, helper_thread_iterations); - notes = error_string; - failed = true; - } else if (end != 0) { - error_count++; - notes = TICK_OCCURRENCE_ERROR; + /* Wait for to complete */ + + k_thread_join(&alt_thread, K_FOREVER); + + /* Record the number of cycles for use by the main thread */ + + timestamp.cycles = sum; +} + +static void thread_switch_yield_common(const char *description, + uint32_t num_iterations, + uint32_t start_options, + uint32_t alt_options, + int priority) +{ + uint64_t sum; + char summary[80]; + + /* Create the two threads */ + + k_thread_create(&start_thread, start_stack, + K_THREAD_STACK_SIZEOF(start_stack), + start_thread_entry, + (void *)(uintptr_t)num_iterations, NULL, NULL, + priority - 1, start_options, K_FOREVER); + + k_thread_create(&alt_thread, alt_stack, + K_THREAD_STACK_SIZEOF(alt_stack), + alt_thread_entry, + (void *)(uintptr_t)num_iterations, NULL, NULL, + priority - 1, alt_options, K_FOREVER); + + /* Grant access rights if necessary */ + + if ((start_options & K_USER) == K_USER) { + k_thread_access_grant(&start_thread, &alt_thread); } - /* - * thread_yield is called (iterations + helper_thread_iterations) - * times in total. - */ + k_thread_start(&start_thread); + + /* Wait until finishes */ + + k_thread_join(&start_thread, K_FOREVER); + + /* Get the sum total of measured cycles */ + + sum = timestamp.cycles; + + sum -= timestamp_overhead_adjustment(start_options, alt_options); + + snprintf(summary, sizeof(summary), + "%s (%c -> %c)", + description, + (start_options & K_USER) == K_USER ? 'U' : 'K', + (alt_options & K_USER) == K_USER ? 'U' : 'K'); + + PRINT_STATS_AVG(summary, (uint32_t)sum, num_iterations, 0, ""); +} + +void thread_switch_yield(uint32_t num_iterations, bool is_cooperative) +{ + int priority; + char description[60]; + + priority = is_cooperative ? K_PRIO_COOP(6) + : k_thread_priority_get(k_current_get()) - 1; + + snprintf(description, sizeof(description), + "%s threads ctx switch via k_yield", + is_cooperative ? "Cooperative" : "Preemptive"); + + /* Kernel -> Kernel */ + thread_switch_yield_common(description, num_iterations, 0, 0, + priority); + +#if CONFIG_USERSPACE + /* User -> User */ + thread_switch_yield_common(description, num_iterations, K_USER, K_USER, + priority); - ts_diff = timing_cycles_get(×tamp_start, ×tamp_end); - PRINT_STATS_AVG("Average thread context switch using yield", ts_diff, - (iterations + helper_thread_iterations), failed, notes); + /* Kernel -> User */ + thread_switch_yield_common(description, num_iterations, 0, K_USER, + priority); - timing_stop(); + /* User -> Kernel */ + thread_switch_yield_common(description, num_iterations, K_USER, 0, + priority); +#endif } diff --git a/tests/benchmarks/latency_measure/src/timing_sc.c b/tests/benchmarks/latency_measure/src/timing_sc.c new file mode 100644 index 00000000000..051b9d1810b --- /dev/null +++ b/tests/benchmarks/latency_measure/src/timing_sc.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * @file + * This file contains routines for implementing a timestamp system call + * as well as routines for determining the overhead associated with it. + */ + +#include +#include +#include "utils.h" +#include "timing_sc.h" + +BENCH_BMEM uint64_t timestamp_overhead; +#ifdef CONFIG_USERSPACE +BENCH_BMEM uint64_t user_timestamp_overhead; +#endif + +timing_t z_impl_timing_timestamp_get(void) +{ + return timing_counter_get(); +} + +#ifdef CONFIG_USERSPACE +timing_t z_vrfy_timing_timestamp_get(void) +{ + return z_impl_timing_timestamp_get(); +} +#include +#endif + +static void start_thread_entry(void *p1, void *p2, void *p3) +{ + uint32_t num_iterations = (uint32_t)(uintptr_t)p1; + timing_t start; + timing_t finish; + + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + start = timing_timestamp_get(); + for (uint32_t i = 0; i < num_iterations; i++) { + timing_timestamp_get(); + } + finish = timing_timestamp_get(); + + timestamp.cycles = timing_cycles_get(&start, &finish); +} + +void timestamp_overhead_init(uint32_t num_iterations) +{ + int priority; + + priority = k_thread_priority_get(k_current_get()); + + k_thread_create(&start_thread, start_stack, + K_THREAD_STACK_SIZEOF(start_stack), + start_thread_entry, + (void *)(uintptr_t)num_iterations, NULL, NULL, + priority - 1, 0, K_FOREVER); + + k_thread_start(&start_thread); + + k_thread_join(&start_thread, K_FOREVER); + + timestamp_overhead = timestamp.cycles; + +#ifdef CONFIG_USERSPACE + k_thread_create(&start_thread, start_stack, + K_THREAD_STACK_SIZEOF(start_stack), + start_thread_entry, + (void *)(uintptr_t)num_iterations, NULL, NULL, + priority - 1, K_USER, K_FOREVER); + + k_thread_start(&start_thread); + + k_thread_join(&start_thread, K_FOREVER); + + user_timestamp_overhead = timestamp.cycles; +#endif +} + +uint64_t timestamp_overhead_adjustment(uint32_t options1, uint32_t options2) +{ +#ifdef CONFIG_USERSPACE + if (((options1 | options2) & K_USER) == K_USER) { + if (((options1 & options2) & K_USER) == K_USER) { + /* + * Both start and finish timestamps were obtained + * from userspace. + */ + return user_timestamp_overhead; + } + /* + * One timestamp came from userspace, and the other came + * from kernel space. Estimate the overhead as the mean + * between the two. + */ + return (timestamp_overhead + user_timestamp_overhead) / 2; + } +#endif + + /* + * Both start and finish timestamps were obtained + * from kernel space. + */ + return timestamp_overhead; +} diff --git a/tests/benchmarks/latency_measure/src/timing_sc.h b/tests/benchmarks/latency_measure/src/timing_sc.h new file mode 100644 index 00000000000..265d71f5048 --- /dev/null +++ b/tests/benchmarks/latency_measure/src/timing_sc.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _LATENCY_MEASURE_TIMING_SC_H +#define _LATENCY_MEASURE_TIMING_SC_H + +#include +#include +#include + +__syscall timing_t timing_timestamp_get(void); + +void timestamp_overhead_init(uint32_t num_iterations); +uint64_t timestamp_overhead_adjustment(uint32_t options1, uint32_t options2); + +#include + +#endif diff --git a/tests/benchmarks/latency_measure/src/utils.h b/tests/benchmarks/latency_measure/src/utils.h index 56027b1c850..62d2fb7259e 100644 --- a/tests/benchmarks/latency_measure/src/utils.h +++ b/tests/benchmarks/latency_measure/src/utils.h @@ -7,7 +7,7 @@ #ifndef _LATENCY_MEASURE_UNIT_H #define _LATENCY_MEASURE_UNIT_H /* - * @brief This file contains function declarations, macroses and inline functions + * @brief This file contains function declarations, macros and inline functions * used in latency measurement. */ @@ -16,8 +16,33 @@ #include #include -#define INT_IMM8_OFFSET 1 -#define IRQ_PRIORITY 3 +#define START_STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE) +#define ALT_STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE) + +#ifdef CONFIG_USERSPACE +#define BENCH_BMEM K_APP_BMEM(bench_mem_partition) +#else +#define BENCH_BMEM +#endif + +struct timestamp_data { + uint64_t cycles; + timing_t sample; +}; + +K_THREAD_STACK_DECLARE(start_stack, START_STACK_SIZE); +K_THREAD_STACK_DECLARE(alt_stack, ALT_STACK_SIZE); + +extern struct k_thread start_thread; +extern struct k_thread alt_thread; + +extern struct k_sem pause_sem; + +extern struct timestamp_data timestamp; +#ifdef CONFIG_USERSPACE +extern uint64_t user_timestamp_overhead; +#endif +extern uint64_t timestamp_overhead; extern int error_count; diff --git a/tests/benchmarks/latency_measure/testcase.yaml b/tests/benchmarks/latency_measure/testcase.yaml index 694a4138130..eb63c107d86 100644 --- a/tests/benchmarks/latency_measure/testcase.yaml +++ b/tests/benchmarks/latency_measure/testcase.yaml @@ -36,3 +36,20 @@ tests: regex: "(?P.*):(?P.*) cycles ,(?P.*) ns" regex: - "PROJECT EXECUTION SUCCESSFUL" + + # Obtain the benchmark results for various user thread / kernel thread + # configurations on platforms that support user space. + benchmark.user.latency: + filter: CONFIG_ARCH_HAS_USERSPACE + timeout: 300 + extra_args: CONF_FILE=prj_user.conf + harness: console + integration_platforms: + - qemu_x86 + - qemu_cortex_a53 + harness_config: + type: one_line + record: + regex: "(?P.*):(?P.*) cycles ,(?P.*) ns" + regex: + - "PROJECT EXECUTION SUCCESSFUL" diff --git a/tests/benchmarks/mbedtls/src/benchmark.c b/tests/benchmarks/mbedtls/src/benchmark.c index 985388faedc..12bc3cdc3d5 100644 --- a/tests/benchmarks/mbedtls/src/benchmark.c +++ b/tests/benchmarks/mbedtls/src/benchmark.c @@ -70,7 +70,7 @@ #include #include -#include +#include #include diff --git a/tests/benchmarks/sched/src/main.c b/tests/benchmarks/sched/src/main.c index 43f5ff896e0..79a519ccf2c 100644 --- a/tests/benchmarks/sched/src/main.c +++ b/tests/benchmarks/sched/src/main.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include /* This is a scheduler microbenchmark, designed to measure latencies diff --git a/tests/benchmarks/sched_userspace/src/main.c b/tests/benchmarks/sched_userspace/src/main.c index ff3f66e68cb..5e921d9ee30 100644 --- a/tests/benchmarks/sched_userspace/src/main.c +++ b/tests/benchmarks/sched_userspace/src/main.c @@ -6,7 +6,9 @@ #include #include -#include + +/* private kernel APIs */ +#include #include #include "app_threads.h" diff --git a/tests/benchmarks/sched_userspace/testcase.yaml b/tests/benchmarks/sched_userspace/testcase.yaml index e4da7bc1bcf..60b6f2f3808 100644 --- a/tests/benchmarks/sched_userspace/testcase.yaml +++ b/tests/benchmarks/sched_userspace/testcase.yaml @@ -7,6 +7,8 @@ tests: - userspace slow: true filter: CONFIG_ARCH_HAS_USERSPACE + arch_exclude: + - posix harness: console harness_config: type: multi_line diff --git a/tests/benchmarks/sys_kernel/README.txt b/tests/benchmarks/sys_kernel/README.txt index 086887d4675..5579acd2720 100644 --- a/tests/benchmarks/sys_kernel/README.txt +++ b/tests/benchmarks/sys_kernel/README.txt @@ -7,34 +7,12 @@ lifo, fifo, stack and memslab objects. -------------------------------------------------------------------------------- -Building and Running Project: - -This project outputs to the console. It can be built and executed -on QEMU as follows: - - make run - --------------------------------------------------------------------------------- - -Troubleshooting: - -Problems caused by out-dated project information can be addressed by -issuing one of the following commands then rebuilding the project: - - make clean # discard results of previous builds - # but keep existing configuration info -or - make pristine # discard results of previous builds - # and restore pre-defined configuration info - --------------------------------------------------------------------------------- - Sample Output: MODULE: kernel API test -KERNEL VERSION: 0x1066300 +KERNEL VERSION: 0xXXYYZZZZ -Each test below is repeated 5000 times; +Each test below is repeated 10 times; average time for one iteration is displayed. TEST CASE: Semaphore #1 @@ -50,7 +28,7 @@ END TEST CASE TEST CASE: Semaphore #2 TEST COVERAGE: k_sem_init - k_sem_take(TICKS_NONE) + k_sem_take(K_NO_WAIT) k_yield k_sem_give Starting test. Please wait... @@ -84,7 +62,7 @@ TEST CASE: LIFO #2 TEST COVERAGE: k_lifo_init k_lifo_get(K_FOREVER) - k_lifo_get(TICKS_NONE) + k_lifo_get(K_NO_WAIT) k_lifo_put k_yield Starting test. Please wait... @@ -118,7 +96,7 @@ TEST CASE: FIFO #2 TEST COVERAGE: k_fifo_init k_fifo_get(K_FOREVER) - k_fifo_get(TICKS_NONE) + k_fifo_get(K_NO_WAIT) k_fifo_put k_yield Starting test. Please wait... @@ -189,4 +167,3 @@ DETAILS: Average time for 1 iteration: NNNN nSec END TEST CASE PROJECT EXECUTION SUCCESSFUL -QEMU: Terminated diff --git a/tests/benchmarks/sys_kernel/src/lifo.c b/tests/benchmarks/sys_kernel/src/lifo.c index 2d7d6497648..bc076a77055 100644 --- a/tests/benchmarks/sys_kernel/src/lifo.c +++ b/tests/benchmarks/sys_kernel/src/lifo.c @@ -177,7 +177,7 @@ int lifo_test(void) fprintf(output_file, sz_description, "\n\tk_lifo_init" "\n\tk_lifo_get(K_FOREVER)" - "\n\tk_lifo_get(TICKS_NONE)" + "\n\tk_lifo_get(K_NO_WAIT)" "\n\tk_lifo_put" "\n\tk_yield"); printf(sz_test_start_fmt); diff --git a/tests/benchmarks/sys_kernel/src/mwfifo.c b/tests/benchmarks/sys_kernel/src/mwfifo.c index 25e1969baa2..bd0fbe04019 100644 --- a/tests/benchmarks/sys_kernel/src/mwfifo.c +++ b/tests/benchmarks/sys_kernel/src/mwfifo.c @@ -177,7 +177,7 @@ int fifo_test(void) fprintf(output_file, sz_description, "\n\tk_fifo_init" "\n\tk_fifo_get(K_FOREVER)" - "\n\tk_fifo_get(TICKS_NONE)" + "\n\tk_fifo_get(K_NO_WAIT)" "\n\tk_fifo_put" "\n\tk_yield"); printf(sz_test_start_fmt); diff --git a/tests/benchmarks/sys_kernel/src/sema.c b/tests/benchmarks/sys_kernel/src/sema.c index e6d08735c30..ac01068d94f 100644 --- a/tests/benchmarks/sys_kernel/src/sema.c +++ b/tests/benchmarks/sys_kernel/src/sema.c @@ -137,7 +137,7 @@ int sema_test(void) "Semaphore #2"); fprintf(output_file, sz_description, "\n\tk_sem_init" - "\n\tk_sem_take(TICKS_NONE)" + "\n\tk_sem_take(K_NO_WAIT)" "\n\tk_yield" "\n\tk_sem_give"); printf(sz_test_start_fmt); diff --git a/tests/bluetooth/addr/prj.conf b/tests/bluetooth/addr/prj.conf index 84088e6b035..fec5098eecf 100644 --- a/tests/bluetooth/addr/prj.conf +++ b/tests/bluetooth/addr/prj.conf @@ -1,6 +1,5 @@ CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CTLR=n diff --git a/tests/bluetooth/adv/prj.conf b/tests/bluetooth/adv/prj.conf index e6fddd337d0..21011240824 100644 --- a/tests/bluetooth/adv/prj.conf +++ b/tests/bluetooth/adv/prj.conf @@ -3,4 +3,3 @@ CONFIG_LOG=y CONFIG_BT_DEVICE_NAME="Test Adv Data" CONFIG_ASSERT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/at/prj.conf b/tests/bluetooth/at/prj.conf index 32b489c0b08..42737f3052b 100644 --- a/tests/bluetooth/at/prj.conf +++ b/tests/bluetooth/at/prj.conf @@ -3,5 +3,4 @@ CONFIG_BT_BREDR=y CONFIG_BT_HFP_HF=y CONFIG_NET_BUF=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SERIAL=y diff --git a/tests/bluetooth/audio/ascs/prj.conf b/tests/bluetooth/audio/ascs/prj.conf index 9376de2355b..9dfa71a952a 100644 --- a/tests/bluetooth/audio/ascs/prj.conf +++ b/tests/bluetooth/audio/ascs/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_MAX_CONN=1 diff --git a/tests/bluetooth/audio/ascs/src/main.c b/tests/bluetooth/audio/ascs/src/main.c index 126c82d63bb..2937bd6d916 100644 --- a/tests/bluetooth/audio/ascs/src/main.c +++ b/tests/bluetooth/audio/ascs/src/main.c @@ -648,3 +648,84 @@ ZTEST_F(ascs_test_suite, test_cis_link_loss_in_enabling_state_client_retries) bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); } + +static struct bt_bap_stream *stream_allocated; +static const struct bt_audio_codec_qos_pref qos_pref = + BT_AUDIO_CODEC_QOS_PREF(true, BT_GAP_LE_PHY_2M, 0x02, 10, 40000, 40000, 40000, 40000); + +static int unicast_server_cb_config_custom_fake(struct bt_conn *conn, const struct bt_bap_ep *ep, + enum bt_audio_dir dir, + const struct bt_audio_codec_cfg *codec_cfg, + struct bt_bap_stream **stream, + struct bt_audio_codec_qos_pref *const pref, + struct bt_bap_ascs_rsp *rsp) +{ + *stream = stream_allocated; + *pref = qos_pref; + *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS, BT_BAP_ASCS_REASON_NONE); + + bt_bap_stream_cb_register(*stream, &mock_bap_stream_ops); + + return 0; +} + +ZTEST_F(ascs_test_suite, test_ase_state_notification_retry) +{ + struct bt_bap_stream *stream = &fixture->stream; + struct bt_conn *conn = &fixture->conn; + const struct bt_gatt_attr *ase, *cp; + struct bt_conn_info info; + uint8_t ase_id; + int err; + + if (IS_ENABLED(CONFIG_BT_ASCS_ASE_SNK)) { + ase = fixture->ase_snk.attr; + ase_id = fixture->ase_snk.id; + } else { + ase = fixture->ase_src.attr; + ase_id = fixture->ase_src.id; + } + + zexpect_not_null(ase); + zassert_not_equal(ase_id, 0x00); + + cp = test_ase_control_point_get(); + zexpect_not_null(cp); + + bt_bap_unicast_server_register_cb(&mock_bap_unicast_server_cb); + + stream_allocated = stream; + mock_bap_unicast_server_cb_config_fake.custom_fake = unicast_server_cb_config_custom_fake; + + /* Mock out of buffers case */ + mock_bt_gatt_notify_cb_fake.return_val = -ENOMEM; + + const uint8_t buf[] = { + 0x01, /* Opcode = Config Codec */ + 0x01, /* Number_of_ASEs */ + ase_id, /* ASE_ID[0] */ + 0x01, /* Target_Latency[0] = Target low latency */ + 0x02, /* Target_PHY[0] = LE 2M PHY */ + 0x06, /* Codec_ID[0].Coding_Format = LC3 */ + 0x00, 0x00, /* Codec_ID[0].Company_ID */ + 0x00, 0x00, /* Codec_ID[0].Vendor_Specific_Codec_ID */ + 0x00, /* Codec_Specific_Configuration_Length[0] */ + }; + + cp->write(conn, cp, (void *)buf, sizeof(buf), 0, 0); + + /* Verification */ + expect_bt_bap_stream_ops_configured_not_called(); + + mock_bt_gatt_notify_cb_fake.return_val = 0; + + err = bt_conn_get_info(conn, &info); + zassert_equal(err, 0); + + /* Wait for ASE state notification retry */ + k_sleep(K_MSEC(BT_CONN_INTERVAL_TO_MS(info.le.interval))); + + expect_bt_bap_stream_ops_configured_called_once(stream, EMPTY); + + bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); +} diff --git a/tests/bluetooth/audio/ascs/src/test_common.c b/tests/bluetooth/audio/ascs/src/test_common.c index 941cbc98f02..17f5bf71e2b 100644 --- a/tests/bluetooth/audio/ascs/src/test_common.c +++ b/tests/bluetooth/audio/ascs/src/test_common.c @@ -68,6 +68,7 @@ void test_conn_init(struct bt_conn *conn) conn->info.security.level = BT_SECURITY_L2; conn->info.security.enc_key_size = BT_ENC_KEY_SIZE_MAX; conn->info.security.flags = BT_SECURITY_FLAG_OOB | BT_SECURITY_FLAG_SC; + conn->info.le.interval = BT_GAP_INIT_CONN_INT_MIN; } const struct bt_gatt_attr *test_ase_control_point_get(void) diff --git a/tests/bluetooth/audio/bap_broadcast_source/CMakeLists.txt b/tests/bluetooth/audio/bap_broadcast_source/CMakeLists.txt new file mode 100644 index 00000000000..46976424220 --- /dev/null +++ b/tests/bluetooth/audio/bap_broadcast_source/CMakeLists.txt @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +project(bluetooth_ascs) +find_package(Zephyr COMPONENTS unittest HINTS $ENV{ZEPHYR_BASE}) + +add_subdirectory(${ZEPHYR_BASE}/tests/bluetooth/audio/bap_broadcast_source/uut uut) + +target_link_libraries(testbinary PRIVATE uut) + +target_include_directories(testbinary PRIVATE include) + +target_sources(testbinary + PRIVATE + src/main.c +) diff --git a/tests/bluetooth/audio/bap_broadcast_source/prj.conf b/tests/bluetooth/audio/bap_broadcast_source/prj.conf new file mode 100644 index 00000000000..4f4534ac2a5 --- /dev/null +++ b/tests/bluetooth/audio/bap_broadcast_source/prj.conf @@ -0,0 +1,18 @@ +CONFIG_ZTEST=y + +CONFIG_BT=y +CONFIG_BT_AUDIO=y + +CONFIG_BT_ISO_MAX_CHAN=2 + +CONFIG_BT_BAP_BROADCAST_SOURCE=y +CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT=2 +CONFIG_BT_BAP_BROADCAST_SRC_COUNT=1 +CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT=2 + +CONFIG_LOG=y +CONFIG_BT_BAP_BROADCAST_SOURCE_LOG_LEVEL_DBG=y + +CONFIG_ASSERT=y +CONFIG_ASSERT_LEVEL=2 +CONFIG_ASSERT_VERBOSE=y diff --git a/tests/bluetooth/audio/bap_broadcast_source/src/main.c b/tests/bluetooth/audio/bap_broadcast_source/src/main.c new file mode 100644 index 00000000000..8d85eb321ac --- /dev/null +++ b/tests/bluetooth/audio/bap_broadcast_source/src/main.c @@ -0,0 +1,1434 @@ +/* main.c - Application main entry point */ + +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "bluetooth.h" +#include "bap_stream_expects.h" + +DEFINE_FFF_GLOBALS; + +static void mock_init_rule_before(const struct ztest_unit_test *test, void *fixture) +{ + mock_bap_stream_init(); +} + +static void mock_destroy_rule_after(const struct ztest_unit_test *test, void *fixture) +{ + mock_bap_stream_cleanup(); +} + +ZTEST_RULE(mock_rule, mock_init_rule_before, mock_destroy_rule_after); + +struct bap_broadcast_source_test_suite_fixture { + struct bt_bap_broadcast_source_param *param; + size_t stream_cnt; + struct bt_bap_broadcast_source *source; +}; + +static void bap_broadcast_source_test_suite_fixture_init( + struct bap_broadcast_source_test_suite_fixture *fixture) +{ + const uint8_t bis_cfg_data[] = { + BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC, + BT_AUDIO_LOCATION_FRONT_LEFT | BT_AUDIO_LOCATION_FRONT_RIGHT), + }; + const size_t streams_per_subgroup = CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT / + CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT; + const enum bt_audio_context ctx = BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED; + const enum bt_audio_location loc = BT_AUDIO_LOCATION_FRONT_LEFT; + struct bt_bap_broadcast_source_subgroup_param *subgroup_param; + struct bt_bap_broadcast_source_stream_param *stream_params; + struct bt_audio_codec_cfg *codec_cfg; + struct bt_audio_codec_qos *codec_qos; + struct bt_bap_stream *streams; + const uint16_t latency = 10U; /* ms*/ + const uint32_t pd = 40000U; /* us */ + const uint16_t sdu = 40U; /* octets */ + const uint8_t rtn = 2U; + uint8_t *bis_data; + + zassert_true(streams_per_subgroup > 0U); + zassert_true(sizeof(bis_cfg_data) <= CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE); + + /* Allocate memory for everything */ + fixture->param = malloc(sizeof(struct bt_bap_broadcast_source_param)); + subgroup_param = malloc(sizeof(struct bt_bap_broadcast_source_subgroup_param) * + CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT); + zassert_not_null(subgroup_param); + stream_params = malloc(sizeof(struct bt_bap_broadcast_source_stream_param) * + CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT); + zassert_not_null(stream_params); + codec_cfg = malloc(sizeof(struct bt_audio_codec_cfg)); + zassert_not_null(codec_cfg); + codec_qos = malloc(sizeof(struct bt_audio_codec_qos)); + zassert_not_null(codec_qos); + streams = malloc(sizeof(struct bt_bap_stream) * CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT); + zassert_not_null(streams); + bis_data = malloc(CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE); + zassert_not_null(bis_data); + + /* Memset everything to 0 */ + memset(fixture->param, 0, sizeof(*fixture->param)); + memset(subgroup_param, 0, + sizeof(struct bt_bap_broadcast_source_subgroup_param) * + CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT); + memset(stream_params, 0, + sizeof(struct bt_bap_broadcast_source_stream_param) * + CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT); + memset(codec_cfg, 0, sizeof(struct bt_audio_codec_cfg)); + memset(codec_qos, 0, sizeof(struct bt_audio_codec_qos)); + memset(streams, 0, sizeof(struct bt_bap_stream) * CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT); + memset(bis_data, 0, CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE); + + /* Initialize default values*/ + *codec_cfg = BT_AUDIO_CODEC_LC3_CONFIG_16_2(loc, ctx); + *codec_qos = BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(sdu, rtn, latency, pd); + memcpy(bis_data, bis_cfg_data, sizeof(bis_cfg_data)); + + for (size_t i = 0U; i < CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT; i++) { + subgroup_param[i].params_count = streams_per_subgroup; + subgroup_param[i].params = stream_params + i * streams_per_subgroup; + subgroup_param[i].codec_cfg = codec_cfg; + } + + for (size_t i = 0U; i < CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT; i++) { + stream_params[i].stream = &streams[i]; + stream_params[i].data = bis_data; + stream_params[i].data_len = sizeof(bis_cfg_data); + bt_bap_stream_cb_register(stream_params[i].stream, &mock_bap_stream_ops); + } + + fixture->param->params_count = CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT; + fixture->param->params = subgroup_param; + fixture->param->qos = codec_qos; + fixture->param->encryption = false; + memset(fixture->param->broadcast_code, 0, sizeof(fixture->param->broadcast_code)); + fixture->param->packing = BT_ISO_PACKING_SEQUENTIAL; + + fixture->stream_cnt = fixture->param->params_count * streams_per_subgroup; +} + +static void *bap_broadcast_source_test_suite_setup(void) +{ + struct bap_broadcast_source_test_suite_fixture *fixture; + + fixture = malloc(sizeof(*fixture)); + zassert_not_null(fixture); + + return fixture; +} + +static void bap_broadcast_source_test_suite_before(void *f) +{ + memset(f, 0, sizeof(struct bap_broadcast_source_test_suite_fixture)); + bap_broadcast_source_test_suite_fixture_init(f); +} + +static void bap_broadcast_source_test_suite_after(void *f) +{ + struct bap_broadcast_source_test_suite_fixture *fixture = f; + struct bt_bap_broadcast_source_param *param; + + if (fixture->source != NULL) { + int err; + + (void)bt_bap_broadcast_source_stop(fixture->source); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; + } + + param = fixture->param; + + free(param->params[0].params[0].data); + free(param->params[0].params[0].stream); + free(param->params[0].params); + free(param->params[0].codec_cfg); + free(param->params); + free(param->qos); + free(param); +} + +static void bap_broadcast_source_test_suite_teardown(void *f) +{ + free(f); +} + +ZTEST_SUITE(bap_broadcast_source_test_suite, NULL, bap_broadcast_source_test_suite_setup, + bap_broadcast_source_test_suite_before, bap_broadcast_source_test_suite_after, + bap_broadcast_source_test_suite_teardown); + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_create_delete) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + create_param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + for (size_t i = 0u; i < create_param->params_count; i++) { + for (size_t j = 0u; j < create_param->params[i].params_count; j++) { + const struct bt_bap_stream *stream = + create_param->params[i].params[j].stream; + + zassert_equal(create_param->qos->sdu, stream->qos->sdu, + "Unexpected stream SDU"); + zassert_equal(create_param->qos->rtn, stream->qos->rtn, + "Unexpected stream RTN"); + zassert_equal(create_param->qos->phy, stream->qos->phy, + "Unexpected stream PHY"); + } + } + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_create_start_send_stop_delete) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + struct bt_le_ext_adv ext_adv = {0}; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + create_param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + err = bt_bap_broadcast_source_start(fixture->source, &ext_adv); + zassert_equal(0, err, "Unable to start broadcast source: err %d", err); + + zexpect_call_count("bt_bap_stream_ops.started", fixture->stream_cnt, + mock_bap_stream_started_cb_fake.call_count); + + for (size_t i = 0U; i < create_param->params_count; i++) { + for (size_t j = 0U; j < create_param->params[i].params_count; j++) { + struct bt_bap_stream *bap_stream = create_param->params[i].params[j].stream; + + /* Since BAP doesn't care about the `buf` we can just provide NULL */ + err = bt_bap_stream_send(bap_stream, NULL, 0, BT_ISO_TIMESTAMP_NONE); + zassert_equal(0, err, + "Unable to send on broadcast stream[%zu][%zu]: err %d", i, j, + err); + } + } + + zexpect_call_count("bt_bap_stream_ops.sent", fixture->stream_cnt, + mock_bap_stream_sent_cb_fake.call_count); + + err = bt_bap_broadcast_source_stop(fixture->source); + zassert_equal(0, err, "Unable to stop broadcast source: err %d", err); + + zexpect_call_count("bt_bap_stream_ops.stopped", fixture->stream_cnt, + mock_bap_stream_stopped_cb_fake.call_count); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_create_inval_param_null) +{ + int err; + + err = bt_bap_broadcast_source_create(NULL, &fixture->source); + zassert_not_equal(0, err, "Did not fail with null params"); +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_create_inval_source_null) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + int err; + + err = bt_bap_broadcast_source_create(create_param, NULL); + zassert_not_equal(0, err, "Did not fail with null source"); +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_create_inval_subgroup_params_count_0) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + int err; + + create_param->params_count = 0U; + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_not_equal(0, err, "Did not fail with params_count %u", create_param->params_count); +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_create_inval_subgroup_params_count_above_max) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + int err; + + create_param->params_count = CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT + 1; + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_not_equal(0, err, "Did not fail with params_count %u", create_param->params_count); +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_create_inval_subgroup_params_null) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = &create_param->params[0]; + int err; + + create_param->params = NULL; + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + /* Restore the params for the cleanup after function */ + create_param->params = subgroup_params; + zassert_not_equal(0, err, "Did not fail with NULL subgroup params"); +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_create_inval_qos_null) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + struct bt_audio_codec_qos *qos = create_param->qos; + int err; + + create_param->qos = NULL; + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + /* Restore the params for the cleanup after function */ + create_param->qos = qos; + zassert_not_equal(0, err, "Did not fail with NULL qos"); +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_create_inval_packing) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + int err; + + create_param->packing = 0x02; + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_not_equal(0, err, "Did not fail with packing %u", create_param->packing); +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_create_inval_subgroup_params_params_count_0) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = &create_param->params[0]; + int err; + + subgroup_params->params_count = 0U; + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_not_equal(0, err, "Did not fail with %u stream params", + subgroup_params->params_count); +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_create_inval_subgroup_params_params_count_above_max) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = &create_param->params[0]; + int err; + + subgroup_params->params_count = CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT + 1; + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_not_equal(0, err, "Did not fail with %u stream params", + subgroup_params->params_count); +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_create_inval_subgroup_params_stream_params_null) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = &create_param->params[0]; + struct bt_bap_broadcast_source_stream_param *stream_params = &subgroup_params->params[0]; + int err; + + subgroup_params->params = NULL; + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + /* Restore the params for the cleanup after function */ + subgroup_params->params = stream_params; + zassert_not_equal(0, err, "Did not fail with NULL stream params"); +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_create_inval_subgroup_params_codec_cfg_null) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = &create_param->params[0]; + struct bt_audio_codec_cfg *codec_cfg = subgroup_params->codec_cfg; + int err; + + subgroup_params->codec_cfg = NULL; + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + /* Restore the params for the cleanup after function */ + subgroup_params->codec_cfg = codec_cfg; + zassert_not_equal(0, err, "Did not fail with NULL codec_cfg"); +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_create_inval_subgroup_params_codec_cfg_data_len) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = &create_param->params[0]; + struct bt_audio_codec_cfg *codec_cfg = subgroup_params->codec_cfg; + int err; + + codec_cfg->data_len = CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE + 1; + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_not_equal(0, err, "Did not fail with codec_cfg->data_len %zu", codec_cfg->data_len); +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_create_inval_subgroup_params_codec_cfg_meta_len) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = &create_param->params[0]; + struct bt_audio_codec_cfg *codec_cfg = subgroup_params->codec_cfg; + int err; + + codec_cfg->meta_len = CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE + 1; + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_not_equal(0, err, "Did not fail with codec_cfg->meta_len %zu", codec_cfg->meta_len); +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_create_inval_subgroup_params_codec_cfg_cid) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = &create_param->params[0]; + struct bt_audio_codec_cfg *codec_cfg = subgroup_params->codec_cfg; + int err; + + codec_cfg->id = BT_HCI_CODING_FORMAT_LC3; + codec_cfg->cid = 0x01; /* Shall be 0 if id == 0x06 (LC3)*/ + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_not_equal(0, err, "Did not fail with codec_cfg->cid %u", codec_cfg->cid); +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_create_inval_subgroup_params_codec_cfg_vid) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = &create_param->params[0]; + struct bt_audio_codec_cfg *codec_cfg = subgroup_params->codec_cfg; + int err; + + codec_cfg->id = BT_HCI_CODING_FORMAT_LC3; + codec_cfg->vid = 0x01; /* Shall be 0 if id == 0x06 (LC3)*/ + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_not_equal(0, err, "Did not fail with codec_cfg->vid %u", codec_cfg->vid); +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_create_inval_stream_params_stream_null) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = &create_param->params[0]; + struct bt_bap_broadcast_source_stream_param *stream_params = &subgroup_params->params[0]; + struct bt_bap_stream *stream = stream_params->stream; + int err; + + stream_params->stream = NULL; + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + /* Restore the params for the cleanup after function */ + stream_params->stream = stream; + zassert_not_equal(0, err, "Did not fail with NULL stream_params->stream"); +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_create_inval_stream_params_data_null) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = &create_param->params[0]; + struct bt_bap_broadcast_source_stream_param *stream_params = &subgroup_params->params[0]; + uint8_t *data = stream_params->data; + int err; + + stream_params->data = NULL; + stream_params->data_len = 1; + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + /* Restore the params for the cleanup after function */ + stream_params->data = data; + zassert_not_equal( + 0, err, + "Did not fail with NULL stream_params->data and stream_params_>data_len %zu", + stream_params->data_len); +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_create_inval_stream_params_data_len) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = &create_param->params[0]; + struct bt_bap_broadcast_source_stream_param *stream_params = &subgroup_params->params[0]; + int err; + + stream_params->data_len = CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE + 1; + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_not_equal(0, err, "Did not fail with stream_params_>data_len %zu", + stream_params->data_len); +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_start_inval_source_null) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + struct bt_le_ext_adv ext_adv = {0}; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + create_param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + err = bt_bap_broadcast_source_start(NULL, &ext_adv); + zassert_not_equal(0, err, "Did not fail with null source"); +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_start_inval_ext_adv_null) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + create_param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + err = bt_bap_broadcast_source_start(fixture->source, NULL); + zassert_not_equal(0, err, "Did not fail with null ext_adv"); +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_start_inval_double_start) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + struct bt_le_ext_adv ext_adv = {0}; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + create_param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + err = bt_bap_broadcast_source_start(fixture->source, &ext_adv); + zassert_equal(0, err, "Unable to start broadcast source: err %d", err); + + err = bt_bap_broadcast_source_start(fixture->source, &ext_adv); + zassert_not_equal(0, err, "Did not fail with starting already started source"); +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_reconfigure_single_subgroup) +{ + struct bt_bap_broadcast_source_param *reconf_param = fixture->param; + const size_t subgroup_cnt = reconf_param->params_count; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + reconf_param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(reconf_param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + for (size_t i = 0u; i < reconf_param->params_count; i++) { + for (size_t j = 0u; j < reconf_param->params[i].params_count; j++) { + const struct bt_bap_stream *stream = + reconf_param->params[i].params[j].stream; + + zassert_equal(reconf_param->qos->sdu, stream->qos->sdu, + "Unexpected stream SDU"); + zassert_equal(reconf_param->qos->rtn, stream->qos->rtn, + "Unexpected stream RTN"); + zassert_equal(reconf_param->qos->phy, stream->qos->phy, + "Unexpected stream PHY"); + } + } + + reconf_param->params_count = 1U; + reconf_param->qos->sdu = 100U; + reconf_param->qos->rtn = 3U; + reconf_param->qos->phy = 1U; + + err = bt_bap_broadcast_source_reconfig(fixture->source, reconf_param); + zassert_equal(0, err, "Unable to reconfigure broadcast source: err %d", err); + + for (size_t i = 0u; i < subgroup_cnt; i++) { + for (size_t j = 0u; j < reconf_param->params[i].params_count; j++) { + const struct bt_bap_stream *stream = + reconf_param->params[i].params[j].stream; + + zassert_equal(reconf_param->qos->sdu, stream->qos->sdu, + "Unexpected stream SDU"); + zassert_equal(reconf_param->qos->rtn, stream->qos->rtn, + "Unexpected stream RTN"); + zassert_equal(reconf_param->qos->phy, stream->qos->phy, + "Unexpected stream PHY"); + } + } + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_reconfigure_all) +{ + struct bt_bap_broadcast_source_param *reconf_param = fixture->param; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + reconf_param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(reconf_param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + for (size_t i = 0u; i < reconf_param->params_count; i++) { + for (size_t j = 0u; j < reconf_param->params[i].params_count; j++) { + const struct bt_bap_stream *stream = + reconf_param->params[i].params[j].stream; + + zassert_equal(reconf_param->qos->sdu, stream->qos->sdu, + "Unexpected stream SDU"); + zassert_equal(reconf_param->qos->rtn, stream->qos->rtn, + "Unexpected stream RTN"); + zassert_equal(reconf_param->qos->phy, stream->qos->phy, + "Unexpected stream PHY"); + } + } + + reconf_param->qos->sdu = 100U; + reconf_param->qos->rtn = 3U; + reconf_param->qos->phy = 1U; + + err = bt_bap_broadcast_source_reconfig(fixture->source, reconf_param); + zassert_equal(0, err, "Unable to reconfigure broadcast source: err %d", err); + + for (size_t i = 0u; i < reconf_param->params_count; i++) { + for (size_t j = 0u; j < reconf_param->params[i].params_count; j++) { + const struct bt_bap_stream *stream = + reconf_param->params[i].params[j].stream; + + zassert_equal(reconf_param->qos->sdu, stream->qos->sdu, + "Unexpected stream SDU"); + zassert_equal(reconf_param->qos->rtn, stream->qos->rtn, + "Unexpected stream RTN"); + zassert_equal(reconf_param->qos->phy, stream->qos->phy, + "Unexpected stream PHY"); + } + } + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_reconfigure_inval_param_null) +{ + struct bt_bap_broadcast_source_param *param = fixture->param; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + err = bt_bap_broadcast_source_reconfig(fixture->source, NULL); + zassert_not_equal(0, err, "Did not fail with null params"); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_reconfigure_inval_source_null) +{ + struct bt_bap_broadcast_source_param *param = fixture->param; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + err = bt_bap_broadcast_source_reconfig(NULL, param); + zassert_not_equal(0, err, "Did not fail with null source"); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_reconfigure_inval_subgroup_params_count_0) +{ + struct bt_bap_broadcast_source_param *param = fixture->param; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + param->params_count = 0U; + err = bt_bap_broadcast_source_reconfig(fixture->source, param); + zassert_not_equal(0, err, "Did not fail with params_count %u", param->params_count); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_reconfigure_inval_subgroup_params_count_above_max) +{ + struct bt_bap_broadcast_source_param *param = fixture->param; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + param->params_count = CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT + 1; + err = bt_bap_broadcast_source_reconfig(fixture->source, param); + zassert_not_equal(0, err, "Did not fail with params_count %u", param->params_count); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_reconfigure_inval_subgroup_params_null) +{ + struct bt_bap_broadcast_source_param *param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = ¶m->params[0]; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + param->params = NULL; + err = bt_bap_broadcast_source_reconfig(fixture->source, param); + /* Restore the params for the cleanup after function */ + param->params = subgroup_params; + zassert_not_equal(0, err, "Did not fail with NULL subgroup params"); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_reconfigure_inval_qos_null) +{ + struct bt_bap_broadcast_source_param *param = fixture->param; + struct bt_audio_codec_qos *qos = param->qos; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + param->qos = NULL; + err = bt_bap_broadcast_source_reconfig(fixture->source, param); + /* Restore the params for the cleanup after function */ + param->qos = qos; + zassert_not_equal(0, err, "Did not fail with NULL qos"); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_reconfigure_inval_packing) +{ + struct bt_bap_broadcast_source_param *param = fixture->param; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + param->packing = 0x02; + err = bt_bap_broadcast_source_reconfig(fixture->source, param); + zassert_not_equal(0, err, "Did not fail with packing %u", param->packing); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_reconfigure_inval_subgroup_params_params_count_0) +{ + struct bt_bap_broadcast_source_param *param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = ¶m->params[0]; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + subgroup_params->params_count = 0U; + err = bt_bap_broadcast_source_reconfig(fixture->source, param); + zassert_not_equal(0, err, "Did not fail with %u stream params", + subgroup_params->params_count); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_reconfigure_inval_subgroup_params_params_count_above_max) +{ + struct bt_bap_broadcast_source_param *param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = ¶m->params[0]; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + subgroup_params->params_count = CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT + 1; + err = bt_bap_broadcast_source_reconfig(fixture->source, param); + zassert_not_equal(0, err, "Did not fail with %u stream params", + subgroup_params->params_count); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_reconfigure_inval_subgroup_params_stream_params_null) +{ + struct bt_bap_broadcast_source_param *param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = ¶m->params[0]; + struct bt_bap_broadcast_source_stream_param *stream_params = &subgroup_params->params[0]; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + subgroup_params->params = NULL; + err = bt_bap_broadcast_source_reconfig(fixture->source, param); + /* Restore the params for the cleanup after function */ + subgroup_params->params = stream_params; + zassert_not_equal(0, err, "Did not fail with NULL stream params"); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_reconfigure_inval_subgroup_params_codec_cfg_null) +{ + struct bt_bap_broadcast_source_param *param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = ¶m->params[0]; + struct bt_audio_codec_cfg *codec_cfg = subgroup_params->codec_cfg; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + subgroup_params->codec_cfg = NULL; + err = bt_bap_broadcast_source_reconfig(fixture->source, param); + /* Restore the params for the cleanup after function */ + subgroup_params->codec_cfg = codec_cfg; + zassert_not_equal(0, err, "Did not fail with NULL codec_cfg"); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_reconfigure_inval_subgroup_params_codec_cfg_data_len) +{ + struct bt_bap_broadcast_source_param *param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = ¶m->params[0]; + struct bt_audio_codec_cfg *codec_cfg = subgroup_params->codec_cfg; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + codec_cfg->data_len = CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE + 1; + err = bt_bap_broadcast_source_reconfig(fixture->source, param); + zassert_not_equal(0, err, "Did not fail with codec_cfg->data_len %zu", codec_cfg->data_len); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_reconfigure_inval_subgroup_params_codec_cfg_meta_len) +{ + struct bt_bap_broadcast_source_param *param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = ¶m->params[0]; + struct bt_audio_codec_cfg *codec_cfg = subgroup_params->codec_cfg; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + codec_cfg->meta_len = CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE + 1; + err = bt_bap_broadcast_source_reconfig(fixture->source, param); + zassert_not_equal(0, err, "Did not fail with codec_cfg->meta_len %zu", codec_cfg->meta_len); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_reconfigure_inval_subgroup_params_codec_cfg_cid) +{ + struct bt_bap_broadcast_source_param *param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = ¶m->params[0]; + struct bt_audio_codec_cfg *codec_cfg = subgroup_params->codec_cfg; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + codec_cfg->id = 0x06; + codec_cfg->cid = 0x01; /* Shall be 0 if id == 0x06 (LC3)*/ + err = bt_bap_broadcast_source_reconfig(fixture->source, param); + zassert_not_equal(0, err, "Did not fail with codec_cfg->cid %u", codec_cfg->cid); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_reconfigure_inval_subgroup_params_codec_cfg_vid) +{ + struct bt_bap_broadcast_source_param *param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = ¶m->params[0]; + struct bt_audio_codec_cfg *codec_cfg = subgroup_params->codec_cfg; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + codec_cfg->id = 0x06; + codec_cfg->vid = 0x01; /* Shall be 0 if id == 0x06 (LC3)*/ + err = bt_bap_broadcast_source_reconfig(fixture->source, param); + zassert_not_equal(0, err, "Did not fail with codec_cfg->vid %u", codec_cfg->vid); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_reconfigure_inval_stream_params_stream_null) +{ + struct bt_bap_broadcast_source_param *param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = ¶m->params[0]; + struct bt_bap_broadcast_source_stream_param *stream_params = &subgroup_params->params[0]; + struct bt_bap_stream *stream = stream_params->stream; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + stream_params->stream = NULL; + err = bt_bap_broadcast_source_reconfig(fixture->source, param); + /* Restore the params for the cleanup after function */ + stream_params->stream = stream; + zassert_not_equal(0, err, "Did not fail with NULL stream_params->stream"); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_reconfigure_inval_stream_params_data_null) +{ + struct bt_bap_broadcast_source_param *param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = ¶m->params[0]; + struct bt_bap_broadcast_source_stream_param *stream_params = &subgroup_params->params[0]; + uint8_t *data = stream_params->data; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + stream_params->data = NULL; + stream_params->data_len = 1; + err = bt_bap_broadcast_source_reconfig(fixture->source, param); + /* Restore the params for the cleanup after function */ + stream_params->data = data; + zassert_not_equal( + 0, err, + "Did not fail with NULL stream_params->data and stream_params_>data_len %zu", + stream_params->data_len); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, + test_broadcast_source_reconfigure_inval_stream_params_data_len) +{ + struct bt_bap_broadcast_source_param *param = fixture->param; + struct bt_bap_broadcast_source_subgroup_param *subgroup_params = ¶m->params[0]; + struct bt_bap_broadcast_source_stream_param *stream_params = &subgroup_params->params[0]; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + stream_params->data_len = CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE + 1; + err = bt_bap_broadcast_source_reconfig(fixture->source, param); + zassert_not_equal(0, err, "Did not fail with stream_params_>data_len %zu", + stream_params->data_len); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_reconfigure_inval_state) +{ + struct bt_bap_broadcast_source_param *param = fixture->param; + struct bt_bap_broadcast_source *source; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + source = fixture->source; + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; + + err = bt_bap_broadcast_source_reconfig(source, param); + zassert_not_equal(0, err, "Did not fail with deleted broadcast source"); +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_stop_inval_source_null) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + struct bt_le_ext_adv ext_adv = {0}; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + create_param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + err = bt_bap_broadcast_source_start(fixture->source, &ext_adv); + zassert_equal(0, err, "Unable to start broadcast source: err %d", err); + + err = bt_bap_broadcast_source_stop(NULL); + zassert_not_equal(0, err, "Did not fail with null source"); +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_stop_inval_state) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + struct bt_le_ext_adv ext_adv = {0}; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + create_param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + err = bt_bap_broadcast_source_start(fixture->source, &ext_adv); + zassert_equal(0, err, "Unable to start broadcast source: err %d", err); + + err = bt_bap_broadcast_source_stop(fixture->source); + zassert_equal(0, err, "Unable to stop broadcast source: err %d", err); + + err = bt_bap_broadcast_source_stop(NULL); + zassert_not_equal(0, err, "Did not fail with stopping already stopped source"); +} + + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_delete_inval_source_null) +{ + int err; + + err = bt_bap_broadcast_source_delete(NULL); + zassert_not_equal(0, err, "Did not fail with null source"); +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_delete_inval_double_start) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + struct bt_bap_broadcast_source *source; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + create_param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to start broadcast source: err %d", err); + + source = fixture->source; + /* Set to NULL to avoid deleting it in bap_broadcast_source_test_suite_after */ + fixture->source = NULL; + + err = bt_bap_broadcast_source_delete(source); + zassert_not_equal(0, err, "Did not fail with deleting already deleting source"); +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_get_id) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + uint32_t broadcast_id; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + create_param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + err = bt_bap_broadcast_source_get_id(fixture->source, &broadcast_id); + zassert_equal(0, err, "Unable to get broadcast ID: err %d", err); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_get_id_inval_source_null) +{ + uint32_t broadcast_id; + int err; + + err = bt_bap_broadcast_source_get_id(NULL, &broadcast_id); + zassert_not_equal(0, err, "Did not fail with null source"); +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_get_id_inval_id_null) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + create_param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + err = bt_bap_broadcast_source_get_id(fixture->source, NULL); + zassert_not_equal(0, err, "Did not fail with null ID"); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_get_id_inval_state) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + struct bt_bap_broadcast_source *source; + uint32_t broadcast_id; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + create_param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + source = fixture->source; + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; + + err = bt_bap_broadcast_source_get_id(source, &broadcast_id); + zassert_not_equal(0, err, "Did not fail with deleted broadcast source"); +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_get_base_single_bis) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + int err; + + const uint8_t expected_base[] = { + 0x51, 0x18, /* uuid */ + 0x40, 0x9C, 0x00, /* pd */ + 0x01, /* subgroup count */ + 0x01, /* bis count */ + 0x06, 0x00, 0x00, 0x00, 0x00, /* LC3 codec_id*/ + 0x10, /* cc length */ + 0x02, 0x01, 0x03, 0x02, 0x02, 0x01, 0x05, 0x03, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x04, 0x28, 0x00, /* cc */ + 0x04, /* meta length */ + 0x03, 0x02, 0x01, 0x00, /* meta */ + 0x01, /* bis index */ + 0x03, /* bis cc length */ + 0x02, 0x03, 0x03 /* bis cc length */ + }; + + NET_BUF_SIMPLE_DEFINE(base_buf, 64); + + /* Make the create param simpler for verification */ + create_param->params_count = 1U; + create_param->params[0].params_count = 1U; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + create_param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + err = bt_bap_broadcast_source_get_base(fixture->source, &base_buf); + zassert_equal(0, err, "Unable to get broadcast source BASE: err %d", err); + + zassert_equal(sizeof(expected_base), base_buf.len, "Incorrect base_buf.len %u, expected %u", + base_buf.len, sizeof(expected_base)); + + /* Use memcmp to print the buffers if they are not identical as zassert_mem_equal does not + * do that + */ + if (memcmp(expected_base, base_buf.data, base_buf.len) != 0) { + for (size_t i = 0U; i < base_buf.len; i++) { + printk("[%zu]: 0x%02X %s 0x%02X\n", i, expected_base[i], + expected_base[i] == base_buf.data[i] ? "==" : "!=", + base_buf.data[i]); + } + + zassert_mem_equal(expected_base, base_buf.data, base_buf.len); + } + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_get_base) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + int err; + + const uint8_t expected_base[] = { + 0x51, 0x18, /* uuid */ + 0x40, 0x9C, 0x00, /* pd */ + 0x02, /* subgroup count */ + 0x01, /* Subgroup 1: bis count */ + 0x06, 0x00, 0x00, 0x00, 0x00, /* LC3 codec_id*/ + 0x10, /* cc length */ + 0x02, 0x01, 0x03, 0x02, 0x02, 0x01, 0x05, 0x03, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x04, 0x28, 0x00, /* cc */ + 0x04, /* meta length */ + 0x03, 0x02, 0x01, 0x00, /* meta */ + 0x01, /* bis index */ + 0x03, /* bis cc length */ + 0x02, 0x03, 0x03, /* bis cc length */ + 0x01, /* Subgroup 1: bis count */ + 0x06, 0x00, 0x00, 0x00, 0x00, /* LC3 codec_id*/ + 0x10, /* cc length */ + 0x02, 0x01, 0x03, 0x02, 0x02, 0x01, 0x05, 0x03, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x04, 0x28, 0x00, /* cc */ + 0x04, /* meta length */ + 0x03, 0x02, 0x01, 0x00, /* meta */ + 0x02, /* bis index */ + 0x03, /* bis cc length */ + 0x02, 0x03, 0x03 /* bis cc length */ + }; + + NET_BUF_SIMPLE_DEFINE(base_buf, 128); + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + create_param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + err = bt_bap_broadcast_source_get_base(fixture->source, &base_buf); + zassert_equal(0, err, "Unable to get broadcast source BASE: err %d", err); + + zassert_equal(sizeof(expected_base), base_buf.len, "Incorrect base_buf.len %u, expected %u", + base_buf.len, sizeof(expected_base)); + + /* Use memcmp to print the buffers if they are not identical as zassert_mem_equal does not + * do that + */ + if (memcmp(expected_base, base_buf.data, base_buf.len) != 0) { + for (size_t i = 0U; i < base_buf.len; i++) { + printk("[%zu]: 0x%02X %s 0x%02X\n", i, expected_base[i], + expected_base[i] == base_buf.data[i] ? "==" : "!=", + base_buf.data[i]); + } + + zassert_mem_equal(expected_base, base_buf.data, base_buf.len); + } + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_get_base_inval_source_null) +{ + int err; + + NET_BUF_SIMPLE_DEFINE(base_buf, 64); + + err = bt_bap_broadcast_source_get_base(NULL, &base_buf); + zassert_not_equal(0, err, "Did not fail with null source"); +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_get_base_inval_base_buf_null) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + int err; + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + create_param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + err = bt_bap_broadcast_source_get_base(fixture->source, NULL); + zassert_not_equal(0, err, "Did not fail with null BASE buffer"); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_get_base_inval_state) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + struct bt_bap_broadcast_source *source; + int err; + + NET_BUF_SIMPLE_DEFINE(base_buf, 64); + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + create_param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + source = fixture->source; + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; + + err = bt_bap_broadcast_source_get_base(source, &base_buf); + zassert_not_equal(0, err, "Did not fail with deleted broadcast source"); +} + +/** This tests that providing a buffer too small for _any_ BASE fails correctly */ +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_get_base_inval_very_small_buf) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + int err; + + NET_BUF_SIMPLE_DEFINE(base_buf, 15); /* Too small to hold any BASE */ + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + create_param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + err = bt_bap_broadcast_source_get_base(fixture->source, &base_buf); + zassert_not_equal(0, err, "Did not fail with too small base_buf (%u)", base_buf.size); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} + +/** This tests that providing a buffer too small for the BASE we want to setup fails correctly */ +ZTEST_F(bap_broadcast_source_test_suite, test_broadcast_source_get_base_inval_small_buf) +{ + struct bt_bap_broadcast_source_param *create_param = fixture->param; + int err; + + /* Can hold a base, but not large enough for this configuration */ + NET_BUF_SIMPLE_DEFINE(base_buf, 64); + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + create_param->params_count, fixture->stream_cnt); + + err = bt_bap_broadcast_source_create(create_param, &fixture->source); + zassert_equal(0, err, "Unable to create broadcast source: err %d", err); + + err = bt_bap_broadcast_source_get_base(fixture->source, &base_buf); + zassert_not_equal(0, err, "Did not fail with too small base_buf (%u)", base_buf.size); + + err = bt_bap_broadcast_source_delete(fixture->source); + zassert_equal(0, err, "Unable to delete broadcast source: err %d", err); + fixture->source = NULL; +} diff --git a/tests/bluetooth/audio/bap_broadcast_source/testcase.yaml b/tests/bluetooth/audio/bap_broadcast_source/testcase.yaml new file mode 100644 index 00000000000..7e97c62613a --- /dev/null +++ b/tests/bluetooth/audio/bap_broadcast_source/testcase.yaml @@ -0,0 +1,7 @@ +common: + tags: + - bluetooth + - bluetooth_audio +tests: + bluetooth.audio.bap_broadcast_source.test_default: + type: unit diff --git a/tests/bluetooth/audio/bap_broadcast_source/uut/CMakeLists.txt b/tests/bluetooth/audio/bap_broadcast_source/uut/CMakeLists.txt new file mode 100644 index 00000000000..85f68a6d1a6 --- /dev/null +++ b/tests/bluetooth/audio/bap_broadcast_source/uut/CMakeLists.txt @@ -0,0 +1,21 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +# CMakeLists.txt file for creating of uut library. +# + +add_library(uut STATIC + ${ZEPHYR_BASE}/subsys/bluetooth/audio/bap_iso.c + ${ZEPHYR_BASE}/subsys/bluetooth/audio/bap_stream.c + ${ZEPHYR_BASE}/subsys/bluetooth/audio/bap_broadcast_source.c + ${ZEPHYR_BASE}/subsys/logging/log_minimal.c + ${ZEPHYR_BASE}/subsys/net/buf_simple.c +) + +add_subdirectory(${ZEPHYR_BASE}/tests/bluetooth/audio/mocks mocks) + +target_link_libraries(uut PUBLIC test_interface mocks) + +target_compile_options(uut PRIVATE -std=c11 -include ztest.h) diff --git a/tests/bluetooth/audio/codec/prj.conf b/tests/bluetooth/audio/codec/prj.conf index 5ac78f09abc..7701c36e5e3 100644 --- a/tests/bluetooth/audio/codec/prj.conf +++ b/tests/bluetooth/audio/codec/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_AUDIO=y @@ -8,6 +7,8 @@ CONFIG_BT_BAP_UNICAST_SERVER=y CONFIG_LOG=y CONFIG_BT_AUDIO_LOG_LEVEL_DBG=y CONFIG_BT_AUDIO_CODEC_LOG_LEVEL_DBG=y +CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE=15 +CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE=15 CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/audio/codec/src/main.c b/tests/bluetooth/audio/codec/src/main.c index 982082328a1..386ef40e7f7 100644 --- a/tests/bluetooth/audio/codec/src/main.c +++ b/tests/bluetooth/audio/codec/src/main.c @@ -9,11 +9,43 @@ #include #include #include +#include DEFINE_FFF_GLOBALS; ZTEST_SUITE(audio_codec_test_suite, NULL, NULL, NULL, NULL, NULL); +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_freq_to_freq_hz) +{ + const struct freq_test_input { + enum bt_audio_codec_config_freq freq; + uint32_t freq_hz; + } freq_test_inputs[] = { + {.freq = BT_AUDIO_CODEC_CONFIG_LC3_FREQ_8KHZ, .freq_hz = 8000U}, + {.freq = BT_AUDIO_CODEC_CONFIG_LC3_FREQ_11KHZ, .freq_hz = 11025U}, + {.freq = BT_AUDIO_CODEC_CONFIG_LC3_FREQ_16KHZ, .freq_hz = 16000U}, + {.freq = BT_AUDIO_CODEC_CONFIG_LC3_FREQ_22KHZ, .freq_hz = 22050U}, + {.freq = BT_AUDIO_CODEC_CONFIG_LC3_FREQ_24KHZ, .freq_hz = 24000U}, + {.freq = BT_AUDIO_CODEC_CONFIG_LC3_FREQ_32KHZ, .freq_hz = 32000U}, + {.freq = BT_AUDIO_CODEC_CONFIG_LC3_FREQ_44KHZ, .freq_hz = 44100U}, + {.freq = BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ, .freq_hz = 48000U}, + {.freq = BT_AUDIO_CODEC_CONFIG_LC3_FREQ_88KHZ, .freq_hz = 88200U}, + {.freq = BT_AUDIO_CODEC_CONFIG_LC3_FREQ_96KHZ, .freq_hz = 96000U}, + {.freq = BT_AUDIO_CODEC_CONFIG_LC3_FREQ_176KHZ, .freq_hz = 176400U}, + {.freq = BT_AUDIO_CODEC_CONFIG_LC3_FREQ_192KHZ, .freq_hz = 192000U}, + {.freq = BT_AUDIO_CODEC_CONFIG_LC3_FREQ_384KHZ, .freq_hz = 384000U}, + }; + + for (size_t i = 0U; i < ARRAY_SIZE(freq_test_inputs); i++) { + const struct freq_test_input *fti = &freq_test_inputs[i]; + + zassert_equal(bt_audio_codec_cfg_freq_to_freq_hz(fti->freq), fti->freq_hz, + "freq %d was not coverted to %u", fti->freq, fti->freq_hz); + zassert_equal(bt_audio_codec_cfg_freq_hz_to_freq(fti->freq_hz), fti->freq, + "freq_hz %u was not coverted to %d", fti->freq_hz, fti->freq); + } +} + ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_get_freq) { const struct bt_bap_lc3_preset preset = @@ -22,21 +54,76 @@ ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_get_freq) int ret; ret = bt_audio_codec_cfg_get_freq(&preset.codec_cfg); - zassert_equal(ret, 16000u, "unexpected return value %d", ret); + zassert_equal(ret, 0x03, "unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_set_freq) +{ + struct bt_bap_lc3_preset preset = BT_BAP_LC3_UNICAST_PRESET_16_2_1( + BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); + int ret; + + ret = bt_audio_codec_cfg_get_freq(&preset.codec_cfg); + zassert_equal(ret, 0x03, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_set_freq(&preset.codec_cfg, BT_AUDIO_CODEC_CONFIG_LC3_FREQ_32KHZ); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_get_freq(&preset.codec_cfg); + zassert_equal(ret, 0x06, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_frame_dur_to_frame_dur_us) +{ + const struct frame_dur_test_input { + enum bt_audio_codec_config_frame_dur frame_dur; + uint32_t frame_dur_us; + } frame_dur_test_inputs[] = { + {.frame_dur = BT_AUDIO_CODEC_CONFIG_LC3_DURATION_7_5, .frame_dur_us = 7500U}, + {.frame_dur = BT_AUDIO_CODEC_CONFIG_LC3_DURATION_10, .frame_dur_us = 10000U}, + }; + + for (size_t i = 0U; i < ARRAY_SIZE(frame_dur_test_inputs); i++) { + const struct frame_dur_test_input *fdti = &frame_dur_test_inputs[i]; + + zassert_equal(bt_audio_codec_cfg_frame_dur_to_frame_dur_us(fdti->frame_dur), + fdti->frame_dur_us, "frame_dur %d was not coverted to %u", + fdti->frame_dur, fdti->frame_dur_us); + zassert_equal(bt_audio_codec_cfg_frame_dur_us_to_frame_dur(fdti->frame_dur_us), + fdti->frame_dur, "frame_dur_us %u was not coverted to %d", + fdti->frame_dur_us, fdti->frame_dur); + } } -ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_get_frame_duration_us) +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_get_frame_dur) { const struct bt_bap_lc3_preset preset = BT_BAP_LC3_UNICAST_PRESET_48_2_2(BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); int ret; - ret = bt_audio_codec_cfg_get_frame_duration_us(&preset.codec_cfg); - zassert_equal(ret, 10000u, "unexpected return value %d", ret); + ret = bt_audio_codec_cfg_get_frame_dur(&preset.codec_cfg); + zassert_equal(ret, 0x01, "unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_set_frame_dur) +{ + struct bt_bap_lc3_preset preset = BT_BAP_LC3_UNICAST_PRESET_16_2_1( + BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); + int ret; + + ret = bt_audio_codec_cfg_get_frame_dur(&preset.codec_cfg); + zassert_equal(ret, 0x01, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_set_frame_dur(&preset.codec_cfg, + BT_AUDIO_CODEC_CONFIG_LC3_DURATION_7_5); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_get_frame_dur(&preset.codec_cfg); + zassert_equal(ret, 0x00, "Unexpected return value %d", ret); } -ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_get_chan_allocation_val) +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_get_chan_allocation) { const struct bt_bap_lc3_preset preset = BT_BAP_LC3_UNICAST_PRESET_8_1_1(BT_AUDIO_LOCATION_FRONT_LEFT, @@ -44,10 +131,33 @@ ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_get_chan_allocation_val) enum bt_audio_location chan_allocation = BT_AUDIO_LOCATION_FRONT_RIGHT; int err; - err = bt_audio_codec_cfg_get_chan_allocation_val(&preset.codec_cfg, &chan_allocation); + err = bt_audio_codec_cfg_get_chan_allocation(&preset.codec_cfg, &chan_allocation); zassert_false(err, "unexpected error %d", err); - zassert_equal(chan_allocation, BT_AUDIO_LOCATION_FRONT_LEFT, - "unexpected return value %d", chan_allocation); + zassert_equal(chan_allocation, BT_AUDIO_LOCATION_FRONT_LEFT, "unexpected return value %d", + chan_allocation); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_set_chan_allocation) +{ + struct bt_bap_lc3_preset preset = BT_BAP_LC3_UNICAST_PRESET_16_2_1( + BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); + enum bt_audio_location chan_allocation; + int err; + + err = bt_audio_codec_cfg_get_chan_allocation(&preset.codec_cfg, &chan_allocation); + zassert_equal(err, 0, "Unexpected return value %d", err); + zassert_equal(chan_allocation, 0x00000001, "Unexpected chan_allocation value %d", + chan_allocation); + + chan_allocation = BT_AUDIO_LOCATION_FRONT_RIGHT | BT_AUDIO_LOCATION_SIDE_RIGHT | + BT_AUDIO_LOCATION_TOP_SIDE_RIGHT | BT_AUDIO_LOCATION_RIGHT_SURROUND; + err = bt_audio_codec_cfg_set_chan_allocation(&preset.codec_cfg, chan_allocation); + zassert_true(err > 0, "Unexpected return value %d", err); + + err = bt_audio_codec_cfg_get_chan_allocation(&preset.codec_cfg, &chan_allocation); + zassert_equal(err, 0, "Unexpected return value %d", err); + zassert_equal(chan_allocation, 0x8080802, "Unexpected chan_allocation value %d", + chan_allocation); } ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_get_octets_per_frame) @@ -61,6 +171,22 @@ ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_get_octets_per_frame) zassert_equal(ret, 80u, "unexpected return value %d", ret); } +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_set_octets_per_frame) +{ + struct bt_bap_lc3_preset preset = BT_BAP_LC3_UNICAST_PRESET_32_2_2( + BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); + int ret; + + ret = bt_audio_codec_cfg_get_octets_per_frame(&preset.codec_cfg); + zassert_equal(ret, 80, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_set_octets_per_frame(&preset.codec_cfg, 120); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_get_octets_per_frame(&preset.codec_cfg); + zassert_equal(ret, 120, "Unexpected return value %d", ret); +} + ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_get_frame_blocks_per_sdu) { const struct bt_bap_lc3_preset preset = @@ -71,3 +197,959 @@ ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_get_frame_blocks_per_sdu) ret = bt_audio_codec_cfg_get_frame_blocks_per_sdu(&preset.codec_cfg, true); zassert_equal(ret, 1u, "unexpected return value %d", ret); } + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_set_frame_blocks_per_sdu) +{ + struct bt_bap_lc3_preset preset = BT_BAP_LC3_UNICAST_PRESET_32_2_2( + BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); + int ret; + + ret = bt_audio_codec_cfg_get_frame_blocks_per_sdu(&preset.codec_cfg, true); + zassert_equal(ret, 1, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_set_frame_blocks_per_sdu(&preset.codec_cfg, 2U); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_get_frame_blocks_per_sdu(&preset.codec_cfg, true); + zassert_equal(ret, 2, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_get_pref_context) +{ + const enum bt_audio_context ctx = + BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | BT_AUDIO_CONTEXT_TYPE_MEDIA; + const struct bt_audio_codec_cfg codec_cfg = + BT_AUDIO_CODEC_CFG(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PREF_CONTEXT, + BT_BYTES_LIST_LE16(ctx))}); + int ret; + + ret = bt_audio_codec_cfg_meta_get_pref_context(&codec_cfg); + zassert_equal(ret, 0x0005, "unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_set_pref_context) +{ + const enum bt_audio_context ctx = + BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | BT_AUDIO_CONTEXT_TYPE_MEDIA; + const enum bt_audio_context new_ctx = BT_AUDIO_CONTEXT_TYPE_NOTIFICATIONS; + struct bt_audio_codec_cfg codec_cfg = + BT_AUDIO_CODEC_CFG(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PREF_CONTEXT, + BT_BYTES_LIST_LE16(ctx))}); + int ret; + + ret = bt_audio_codec_cfg_meta_get_pref_context(&codec_cfg); + zassert_equal(ret, 0x0005, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_meta_set_pref_context(&codec_cfg, new_ctx); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_meta_get_pref_context(&codec_cfg); + zassert_equal(ret, 0x0100, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_get_stream_context) +{ + const enum bt_audio_context ctx = + BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | BT_AUDIO_CONTEXT_TYPE_MEDIA; + const struct bt_audio_codec_cfg codec_cfg = + BT_AUDIO_CODEC_CFG(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT, + BT_BYTES_LIST_LE16(ctx))}); + int ret; + + ret = bt_audio_codec_cfg_meta_get_stream_context(&codec_cfg); + zassert_equal(ret, 0x0005, "unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_set_stream_context) +{ + enum bt_audio_context ctx = BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | BT_AUDIO_CONTEXT_TYPE_MEDIA; + struct bt_audio_codec_cfg codec_cfg = + BT_AUDIO_CODEC_CFG(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT, + BT_BYTES_LIST_LE16(ctx))}); + int ret; + + ret = bt_audio_codec_cfg_meta_get_stream_context(&codec_cfg); + zassert_equal(ret, 0x0005, "Unexpected return value %d", ret); + + ctx = BT_AUDIO_CONTEXT_TYPE_NOTIFICATIONS; + ret = bt_audio_codec_cfg_meta_set_stream_context(&codec_cfg, ctx); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_meta_get_stream_context(&codec_cfg); + zassert_equal(ret, 0x0100, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_get_program_info) +{ + const uint8_t expected_data[] = {'P', 'r', 'o', 'g', 'r', 'a', 'm', ' ', + 'I', 'n', 'f', 'o'}; + const struct bt_audio_codec_cfg codec_cfg = BT_AUDIO_CODEC_CFG( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PROGRAM_INFO, + 'P', 'r', 'o', 'g', 'r', 'a', 'm', ' ', + 'I', 'n', 'f', 'o')}); + const uint8_t *program_data; + int ret; + + ret = bt_audio_codec_cfg_meta_get_program_info(&codec_cfg, &program_data); + zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(expected_data, program_data, ARRAY_SIZE(expected_data)); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_set_program_info) +{ + const uint8_t expected_data[] = {'P', 'r', 'o', 'g', 'r', 'a', + 'm', ' ', 'I', 'n', 'f', 'o'}; + const uint8_t new_expected_data[] = {'N', 'e', 'w', ' ', 'i', 'n', 'f', 'o'}; + struct bt_audio_codec_cfg codec_cfg = BT_AUDIO_CODEC_CFG( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PROGRAM_INFO, 'P', 'r', 'o', 'g', 'r', + 'a', 'm', ' ', 'I', 'n', 'f', 'o')}); + const uint8_t *program_data; + int ret; + + ret = bt_audio_codec_cfg_meta_get_program_info(&codec_cfg, &program_data); + zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(expected_data, program_data, ARRAY_SIZE(expected_data)); + + ret = bt_audio_codec_cfg_meta_set_program_info(&codec_cfg, new_expected_data, + ARRAY_SIZE(new_expected_data)); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_meta_get_program_info(&codec_cfg, &program_data); + zassert_equal(ret, ARRAY_SIZE(new_expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(new_expected_data, program_data, ARRAY_SIZE(new_expected_data)); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_get_stream_lang) +{ + const uint32_t expected_data = sys_get_le24((uint8_t[]){'e', 'n', 'g'}); + const struct bt_audio_codec_cfg codec_cfg = BT_AUDIO_CODEC_CFG( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_STREAM_LANG, 'e', 'n', 'g')}); + int ret; + + ret = bt_audio_codec_cfg_meta_get_stream_lang(&codec_cfg); + zassert_equal(ret, expected_data, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_set_stream_lang) +{ + const uint32_t expected_data = sys_get_le24((uint8_t[]){'e', 'n', 'g'}); + const uint32_t new_expected_data = sys_get_le24((uint8_t[]){'d', 'e', 'u'}); + struct bt_audio_codec_cfg codec_cfg = BT_AUDIO_CODEC_CFG( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_STREAM_LANG, 'e', 'n', 'g')}); + const uint32_t new_stream_lang = sys_le32_to_cpu(new_expected_data); + int ret; + + ret = bt_audio_codec_cfg_meta_get_stream_lang(&codec_cfg); + zassert_equal(ret, expected_data, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_meta_set_stream_lang(&codec_cfg, new_stream_lang); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_meta_get_stream_lang(&codec_cfg); + zassert_equal(ret, new_expected_data, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_get_ccid_list) +{ + const uint8_t expected_data[] = {0x05, 0x10, 0x15}; + const struct bt_audio_codec_cfg codec_cfg = BT_AUDIO_CODEC_CFG( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_CCID_LIST, 0x05, 0x10, 0x15)}); + const uint8_t *ccid_list; + int ret; + + ret = bt_audio_codec_cfg_meta_get_ccid_list(&codec_cfg, &ccid_list); + zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(expected_data, ccid_list, ARRAY_SIZE(expected_data)); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_set_ccid_list) +{ + const uint8_t expected_data[] = {0x05, 0x10, 0x15}; + const uint8_t new_expected_data[] = {0x25, 0x30}; + struct bt_audio_codec_cfg codec_cfg = BT_AUDIO_CODEC_CFG( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_CCID_LIST, 0x05, 0x10, 0x15)}); + const uint8_t *ccid_list; + int ret; + + ret = bt_audio_codec_cfg_meta_get_ccid_list(&codec_cfg, &ccid_list); + zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(expected_data, ccid_list, ARRAY_SIZE(expected_data)); + + ret = bt_audio_codec_cfg_meta_set_ccid_list(&codec_cfg, new_expected_data, + ARRAY_SIZE(new_expected_data)); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_meta_get_ccid_list(&codec_cfg, &ccid_list); + zassert_equal(ret, ARRAY_SIZE(new_expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(new_expected_data, ccid_list, ARRAY_SIZE(new_expected_data)); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_get_parental_rating) +{ + const struct bt_audio_codec_cfg codec_cfg = + BT_AUDIO_CODEC_CFG(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PARENTAL_RATING, + BT_AUDIO_PARENTAL_RATING_AGE_10_OR_ABOVE)}); + int ret; + + ret = bt_audio_codec_cfg_meta_get_parental_rating(&codec_cfg); + zassert_equal(ret, 0x07, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_set_parental_rating) +{ + struct bt_audio_codec_cfg codec_cfg = + BT_AUDIO_CODEC_CFG(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PARENTAL_RATING, + BT_AUDIO_PARENTAL_RATING_AGE_10_OR_ABOVE)}); + int ret; + + ret = bt_audio_codec_cfg_meta_get_parental_rating(&codec_cfg); + zassert_equal(ret, 0x07, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_meta_set_parental_rating(&codec_cfg, + BT_AUDIO_PARENTAL_RATING_AGE_13_OR_ABOVE); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_meta_get_parental_rating(&codec_cfg); + zassert_equal(ret, 0x0a, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_get_program_info_uri) +{ + const uint8_t expected_data[] = {'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm'}; + const struct bt_audio_codec_cfg codec_cfg = BT_AUDIO_CODEC_CFG( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PROGRAM_INFO_URI, + 'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm')}); + const uint8_t *program_info_uri; + int ret; + + ret = bt_audio_codec_cfg_meta_get_program_info_uri(&codec_cfg, &program_info_uri); + zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(expected_data, program_info_uri, ARRAY_SIZE(expected_data)); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_set_program_info_uri) +{ + const uint8_t expected_data[] = {'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm'}; + const uint8_t new_expected_data[] = {'n', 'e', 'w', '.', 'c', 'o', 'm'}; + struct bt_audio_codec_cfg codec_cfg = BT_AUDIO_CODEC_CFG( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PROGRAM_INFO_URI, 'e', 'x', 'a', 'm', + 'p', 'l', 'e', '.', 'c', 'o', 'm')}); + const uint8_t *program_info_uri; + int ret; + + ret = bt_audio_codec_cfg_meta_get_program_info_uri(&codec_cfg, &program_info_uri); + zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(expected_data, program_info_uri, ARRAY_SIZE(expected_data)); + + ret = bt_audio_codec_cfg_meta_set_program_info_uri(&codec_cfg, new_expected_data, + ARRAY_SIZE(new_expected_data)); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_meta_get_program_info_uri(&codec_cfg, &program_info_uri); + zassert_equal(ret, ARRAY_SIZE(new_expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(new_expected_data, program_info_uri, ARRAY_SIZE(new_expected_data)); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_get_audio_active_state) +{ + const struct bt_audio_codec_cfg codec_cfg = + BT_AUDIO_CODEC_CFG(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_AUDIO_STATE, + BT_AUDIO_ACTIVE_STATE_ENABLED)}); + int ret; + + ret = bt_audio_codec_cfg_meta_get_audio_active_state(&codec_cfg); + zassert_equal(ret, 0x01, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_set_audio_active_state) +{ + struct bt_audio_codec_cfg codec_cfg = + BT_AUDIO_CODEC_CFG(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_AUDIO_STATE, + BT_AUDIO_ACTIVE_STATE_ENABLED)}); + int ret; + + ret = bt_audio_codec_cfg_meta_get_audio_active_state(&codec_cfg); + zassert_equal(ret, 0x01, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_meta_set_audio_active_state(&codec_cfg, + BT_AUDIO_ACTIVE_STATE_DISABLED); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_meta_get_audio_active_state(&codec_cfg); + zassert_equal(ret, 0x00, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_get_bcast_audio_immediate_rend_flag) +{ + const struct bt_audio_codec_cfg codec_cfg = BT_AUDIO_CODEC_CFG( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_BROADCAST_IMMEDIATE)}); + int ret; + + ret = bt_audio_codec_cfg_meta_get_bcast_audio_immediate_rend_flag(&codec_cfg); + zassert_equal(ret, 0, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_set_bcast_audio_immediate_rend_flag) +{ + struct bt_audio_codec_cfg codec_cfg = + BT_AUDIO_CODEC_CFG(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, {}); + int ret; + + ret = bt_audio_codec_cfg_meta_get_bcast_audio_immediate_rend_flag(&codec_cfg); + zassert_equal(ret, -ENODATA, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_meta_set_bcast_audio_immediate_rend_flag(&codec_cfg); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_meta_get_bcast_audio_immediate_rend_flag(&codec_cfg); + zassert_equal(ret, 0, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_get_extended) +{ + const uint8_t expected_data[] = {0x00, 0x01, 0x02, 0x03}; + const struct bt_audio_codec_cfg codec_cfg = BT_AUDIO_CODEC_CFG( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_EXTENDED, 0x00, 0x01, 0x02, 0x03)}); + const uint8_t *extended_meta; + int ret; + + ret = bt_audio_codec_cfg_meta_get_extended(&codec_cfg, &extended_meta); + zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(expected_data, extended_meta, ARRAY_SIZE(expected_data)); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_set_extended) +{ + const uint8_t expected_data[] = {0x00, 0x01, 0x02, 0x03}; + const uint8_t new_expected_data[] = {0x04, 0x05}; + struct bt_audio_codec_cfg codec_cfg = BT_AUDIO_CODEC_CFG( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_EXTENDED, 0x00, 0x01, 0x02, 0x03)}); + const uint8_t *extended_meta; + int ret; + + ret = bt_audio_codec_cfg_meta_get_extended(&codec_cfg, &extended_meta); + zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(expected_data, extended_meta, ARRAY_SIZE(expected_data)); + + ret = bt_audio_codec_cfg_meta_set_extended(&codec_cfg, new_expected_data, + ARRAY_SIZE(new_expected_data)); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_meta_get_extended(&codec_cfg, &extended_meta); + zassert_equal(ret, ARRAY_SIZE(new_expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(new_expected_data, extended_meta, ARRAY_SIZE(new_expected_data)); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_get_vendor) +{ + const uint8_t expected_data[] = {0x00, 0x01, 0x02, 0x03}; + const struct bt_audio_codec_cfg codec_cfg = BT_AUDIO_CODEC_CFG( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_VENDOR, 0x00, 0x01, 0x02, 0x03)}); + const uint8_t *vendor_meta; + int ret; + + ret = bt_audio_codec_cfg_meta_get_vendor(&codec_cfg, &vendor_meta); + zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(expected_data, vendor_meta, ARRAY_SIZE(expected_data)); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_set_vendor) +{ + const uint8_t expected_data[] = {0x00, 0x01, 0x02, 0x03}; + const uint8_t new_expected_data[] = {0x04, 0x05, 0x06, 0x07, 0x08}; + struct bt_audio_codec_cfg codec_cfg = BT_AUDIO_CODEC_CFG( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_VENDOR, 0x00, 0x01, 0x02, 0x03)}); + const uint8_t *extended_meta; + int ret; + + ret = bt_audio_codec_cfg_meta_get_vendor(&codec_cfg, &extended_meta); + zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(expected_data, extended_meta, ARRAY_SIZE(expected_data)); + + ret = bt_audio_codec_cfg_meta_set_vendor(&codec_cfg, new_expected_data, + ARRAY_SIZE(new_expected_data)); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cfg_meta_get_vendor(&codec_cfg, &extended_meta); + zassert_equal(ret, ARRAY_SIZE(new_expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(new_expected_data, extended_meta, ARRAY_SIZE(new_expected_data)); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_get_freq) +{ + const struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3( + BT_AUDIO_CODEC_LC3_FREQ_16KHZ, BT_AUDIO_CODEC_LC3_DURATION_10, + BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40U, 120U, 2U, + (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)); + + int ret; + + ret = bt_audio_codec_cap_get_freq(&codec_cap); + zassert_equal(ret, 4, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_set_freq) +{ + struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3( + BT_AUDIO_CODEC_LC3_FREQ_16KHZ, BT_AUDIO_CODEC_LC3_DURATION_10, + BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40U, 120U, 2U, + (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)); + + int ret; + + ret = bt_audio_codec_cap_get_freq(&codec_cap); + zassert_equal(ret, 4, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_set_freq(&codec_cap, BT_AUDIO_CODEC_LC3_FREQ_22KHZ); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_get_freq(&codec_cap); + zassert_equal(ret, 8, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_get_frame_dur) +{ + const struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3( + BT_AUDIO_CODEC_LC3_FREQ_16KHZ, BT_AUDIO_CODEC_LC3_DURATION_10, + BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40U, 120U, 2U, + (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)); + + int ret; + + ret = bt_audio_codec_cap_get_frame_dur(&codec_cap); + zassert_equal(ret, 2, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_set_frame_dur) +{ + struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3( + BT_AUDIO_CODEC_LC3_FREQ_16KHZ, BT_AUDIO_CODEC_LC3_DURATION_10, + BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40U, 120U, 2U, + (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)); + + int ret; + + ret = bt_audio_codec_cap_get_frame_dur(&codec_cap); + zassert_equal(ret, 2, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_set_frame_dur(&codec_cap, BT_AUDIO_CODEC_LC3_DURATION_7_5); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_get_frame_dur(&codec_cap); + zassert_equal(ret, 1, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_get_supported_audio_chan_counts) +{ + const struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3( + BT_AUDIO_CODEC_LC3_FREQ_16KHZ, BT_AUDIO_CODEC_LC3_DURATION_10, + BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(2), 40U, 120U, 2U, + (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)); + + int ret; + + ret = bt_audio_codec_cap_get_supported_audio_chan_counts(&codec_cap); + zassert_equal(ret, 2, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_set_supported_audio_chan_counts) +{ + struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3( + BT_AUDIO_CODEC_LC3_FREQ_16KHZ, BT_AUDIO_CODEC_LC3_DURATION_10, + BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40U, 120U, 2U, + (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)); + + int ret; + + ret = bt_audio_codec_cap_get_supported_audio_chan_counts(&codec_cap); + zassert_equal(ret, 1, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_set_frame_dur(&codec_cap, + BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(2)); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_get_frame_dur(&codec_cap); + zassert_equal(ret, 2, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_get_octets_per_frame) +{ + struct bt_audio_codec_octets_per_codec_frame expected = { + .min = 40U, + .max = 120U, + }; + const struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3( + BT_AUDIO_CODEC_LC3_FREQ_16KHZ, BT_AUDIO_CODEC_LC3_DURATION_10, + BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40U, 120U, 2U, + (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)); + struct bt_audio_codec_octets_per_codec_frame codec_frame; + + int ret; + + ret = bt_audio_codec_cap_get_octets_per_frame(&codec_cap, &codec_frame); + zassert_equal(ret, 0, "Unexpected return value %d", ret); + zassert_equal(codec_frame.min, expected.min, "Unexpected minimum value %d", + codec_frame.min); + zassert_equal(codec_frame.max, expected.max, "Unexpected maximum value %d", + codec_frame.max); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_set_octets_per_frame) +{ + struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3( + BT_AUDIO_CODEC_LC3_FREQ_16KHZ, BT_AUDIO_CODEC_LC3_DURATION_10, + BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40U, 120U, 2U, + (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)); + struct bt_audio_codec_octets_per_codec_frame codec_frame; + int ret; + + ret = bt_audio_codec_cap_get_octets_per_frame(&codec_cap, &codec_frame); + zassert_equal(ret, 0, "Unexpected return value %d", ret); + zassert_equal(codec_frame.min, 40U, "Unexpected minimum value %d", codec_frame.min); + zassert_equal(codec_frame.max, 120U, "Unexpected maximum value %d", codec_frame.max); + + codec_frame.min = 50U; + codec_frame.max = 100U; + ret = bt_audio_codec_cap_set_octets_per_frame(&codec_cap, &codec_frame); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_get_octets_per_frame(&codec_cap, &codec_frame); + zassert_equal(ret, 0, "Unexpected return value %d", ret); + zassert_equal(codec_frame.min, 50U, "Unexpected minimum value %d", codec_frame.min); + zassert_equal(codec_frame.max, 100U, "Unexpected maximum value %d", codec_frame.max); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_get_max_codec_frames_per_sdu) +{ + const struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3( + BT_AUDIO_CODEC_LC3_FREQ_16KHZ, BT_AUDIO_CODEC_LC3_DURATION_10, + BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40U, 120U, 2U, + (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)); + + int ret; + + ret = bt_audio_codec_cap_get_max_codec_frames_per_sdu(&codec_cap); + zassert_equal(ret, 2, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_set_max_codec_frames_per_sdu) +{ + struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3( + BT_AUDIO_CODEC_LC3_FREQ_16KHZ, BT_AUDIO_CODEC_LC3_DURATION_10, + BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40U, 120U, 2U, + (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)); + + int ret; + + ret = bt_audio_codec_cap_get_max_codec_frames_per_sdu(&codec_cap); + zassert_equal(ret, 2, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_set_max_codec_frames_per_sdu(&codec_cap, 4U); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_get_max_codec_frames_per_sdu(&codec_cap); + zassert_equal(ret, 4, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_get_pref_context) +{ + const enum bt_audio_context ctx = + BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | BT_AUDIO_CONTEXT_TYPE_MEDIA; + const struct bt_audio_codec_cap codec_cap = + BT_AUDIO_CODEC_CAP(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PREF_CONTEXT, + BT_BYTES_LIST_LE16(ctx))}); + int ret; + + ret = bt_audio_codec_cap_meta_get_pref_context(&codec_cap); + zassert_equal(ret, 0x0005, "unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_set_pref_context) +{ + const enum bt_audio_context ctx = + BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | BT_AUDIO_CONTEXT_TYPE_MEDIA; + const enum bt_audio_context new_ctx = BT_AUDIO_CONTEXT_TYPE_NOTIFICATIONS; + struct bt_audio_codec_cap codec_cap = + BT_AUDIO_CODEC_CAP(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PREF_CONTEXT, + BT_BYTES_LIST_LE16(ctx))}); + int ret; + + ret = bt_audio_codec_cap_meta_get_pref_context(&codec_cap); + zassert_equal(ret, 0x0005, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_meta_set_pref_context(&codec_cap, new_ctx); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_meta_get_pref_context(&codec_cap); + zassert_equal(ret, 0x0100, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_get_stream_context) +{ + const enum bt_audio_context ctx = + BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | BT_AUDIO_CONTEXT_TYPE_MEDIA; + const struct bt_audio_codec_cap codec_cap = + BT_AUDIO_CODEC_CAP(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT, + BT_BYTES_LIST_LE16(ctx))}); + int ret; + + ret = bt_audio_codec_cap_meta_get_stream_context(&codec_cap); + zassert_equal(ret, 0x0005, "unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_set_stream_context) +{ + enum bt_audio_context ctx = BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | BT_AUDIO_CONTEXT_TYPE_MEDIA; + struct bt_audio_codec_cap codec_cap = + BT_AUDIO_CODEC_CAP(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT, + BT_BYTES_LIST_LE16(ctx))}); + int ret; + + ret = bt_audio_codec_cap_meta_get_stream_context(&codec_cap); + zassert_equal(ret, 0x0005, "Unexpected return value %d", ret); + + ctx = BT_AUDIO_CONTEXT_TYPE_NOTIFICATIONS; + ret = bt_audio_codec_cap_meta_set_stream_context(&codec_cap, ctx); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_meta_get_stream_context(&codec_cap); + zassert_equal(ret, 0x0100, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_get_program_info) +{ + const uint8_t expected_data[] = {'P', 'r', 'o', 'g', 'r', 'a', 'm', ' ', + 'I', 'n', 'f', 'o'}; + const struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PROGRAM_INFO, + 'P', 'r', 'o', 'g', 'r', 'a', 'm', ' ', + 'I', 'n', 'f', 'o')}); + const uint8_t *program_data; + int ret; + + ret = bt_audio_codec_cap_meta_get_program_info(&codec_cap, &program_data); + zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(expected_data, program_data, ARRAY_SIZE(expected_data)); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_set_program_info) +{ + const uint8_t expected_data[] = {'P', 'r', 'o', 'g', 'r', 'a', + 'm', ' ', 'I', 'n', 'f', 'o'}; + const uint8_t new_expected_data[] = {'N', 'e', 'w', ' ', 'i', 'n', 'f', 'o'}; + struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PROGRAM_INFO, 'P', 'r', 'o', 'g', 'r', + 'a', 'm', ' ', 'I', 'n', 'f', 'o')}); + const uint8_t *program_data; + int ret; + + ret = bt_audio_codec_cap_meta_get_program_info(&codec_cap, &program_data); + zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(expected_data, program_data, ARRAY_SIZE(expected_data)); + + ret = bt_audio_codec_cap_meta_set_program_info(&codec_cap, new_expected_data, + ARRAY_SIZE(new_expected_data)); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_meta_get_program_info(&codec_cap, &program_data); + zassert_equal(ret, ARRAY_SIZE(new_expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(new_expected_data, program_data, ARRAY_SIZE(new_expected_data)); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_get_stream_lang) +{ + const uint32_t expected_data = sys_get_le24((uint8_t[]){'e', 'n', 'g'}); + const struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_STREAM_LANG, 'e', 'n', 'g')}); + int ret; + + ret = bt_audio_codec_cap_meta_get_stream_lang(&codec_cap); + zassert_equal(ret, expected_data, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_set_stream_lang) +{ + const uint32_t expected_data = sys_get_le24((uint8_t[]){'e', 'n', 'g'}); + const uint32_t new_expected_data = sys_get_le24((uint8_t[]){'d', 'e', 'u'}); + struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_STREAM_LANG, 'e', 'n', 'g')}); + const uint32_t new_stream_lang = sys_le32_to_cpu(new_expected_data); + int ret; + + ret = bt_audio_codec_cap_meta_get_stream_lang(&codec_cap); + zassert_equal(ret, expected_data, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_meta_set_stream_lang(&codec_cap, new_stream_lang); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_meta_get_stream_lang(&codec_cap); + zassert_equal(ret, new_expected_data, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_get_ccid_list) +{ + const uint8_t expected_data[] = {0x05, 0x10, 0x15}; + const struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_CCID_LIST, 0x05, 0x10, 0x15)}); + const uint8_t *ccid_list; + int ret; + + ret = bt_audio_codec_cap_meta_get_ccid_list(&codec_cap, &ccid_list); + zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(expected_data, ccid_list, ARRAY_SIZE(expected_data)); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_set_ccid_list) +{ + const uint8_t expected_data[] = {0x05, 0x10, 0x15}; + const uint8_t new_expected_data[] = {0x25, 0x30}; + struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_CCID_LIST, 0x05, 0x10, 0x15)}); + const uint8_t *ccid_list; + int ret; + + ret = bt_audio_codec_cap_meta_get_ccid_list(&codec_cap, &ccid_list); + zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(expected_data, ccid_list, ARRAY_SIZE(expected_data)); + + ret = bt_audio_codec_cap_meta_set_ccid_list(&codec_cap, new_expected_data, + ARRAY_SIZE(new_expected_data)); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_meta_get_ccid_list(&codec_cap, &ccid_list); + zassert_equal(ret, ARRAY_SIZE(new_expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(new_expected_data, ccid_list, ARRAY_SIZE(new_expected_data)); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_get_parental_rating) +{ + const struct bt_audio_codec_cap codec_cap = + BT_AUDIO_CODEC_CAP(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PARENTAL_RATING, + BT_AUDIO_PARENTAL_RATING_AGE_10_OR_ABOVE)}); + int ret; + + ret = bt_audio_codec_cap_meta_get_parental_rating(&codec_cap); + zassert_equal(ret, 0x07, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_set_parental_rating) +{ + struct bt_audio_codec_cap codec_cap = + BT_AUDIO_CODEC_CAP(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PARENTAL_RATING, + BT_AUDIO_PARENTAL_RATING_AGE_10_OR_ABOVE)}); + int ret; + + ret = bt_audio_codec_cap_meta_get_parental_rating(&codec_cap); + zassert_equal(ret, 0x07, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_meta_set_parental_rating(&codec_cap, + BT_AUDIO_PARENTAL_RATING_AGE_13_OR_ABOVE); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_meta_get_parental_rating(&codec_cap); + zassert_equal(ret, 0x0a, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_get_program_info_uri) +{ + const uint8_t expected_data[] = {'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm'}; + const struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PROGRAM_INFO_URI, + 'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm')}); + const uint8_t *program_info_uri; + int ret; + + ret = bt_audio_codec_cap_meta_get_program_info_uri(&codec_cap, &program_info_uri); + zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(expected_data, program_info_uri, ARRAY_SIZE(expected_data)); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_set_program_info_uri) +{ + const uint8_t expected_data[] = {'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm'}; + const uint8_t new_expected_data[] = {'n', 'e', 'w', '.', 'c', 'o', 'm'}; + struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PROGRAM_INFO_URI, 'e', 'x', 'a', 'm', + 'p', 'l', 'e', '.', 'c', 'o', 'm')}); + const uint8_t *program_info_uri; + int ret; + + ret = bt_audio_codec_cap_meta_get_program_info_uri(&codec_cap, &program_info_uri); + zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(expected_data, program_info_uri, ARRAY_SIZE(expected_data)); + + ret = bt_audio_codec_cap_meta_set_program_info_uri(&codec_cap, new_expected_data, + ARRAY_SIZE(new_expected_data)); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_meta_get_program_info_uri(&codec_cap, &program_info_uri); + zassert_equal(ret, ARRAY_SIZE(new_expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(new_expected_data, program_info_uri, ARRAY_SIZE(new_expected_data)); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_get_audio_active_state) +{ + const struct bt_audio_codec_cap codec_cap = + BT_AUDIO_CODEC_CAP(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_AUDIO_STATE, + BT_AUDIO_ACTIVE_STATE_ENABLED)}); + int ret; + + ret = bt_audio_codec_cap_meta_get_audio_active_state(&codec_cap); + zassert_equal(ret, 0x01, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_set_audio_active_state) +{ + struct bt_audio_codec_cap codec_cap = + BT_AUDIO_CODEC_CAP(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_AUDIO_STATE, + BT_AUDIO_ACTIVE_STATE_ENABLED)}); + int ret; + + ret = bt_audio_codec_cap_meta_get_audio_active_state(&codec_cap); + zassert_equal(ret, 0x01, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_meta_set_audio_active_state(&codec_cap, + BT_AUDIO_ACTIVE_STATE_DISABLED); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_meta_get_audio_active_state(&codec_cap); + zassert_equal(ret, 0x00, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_get_bcast_audio_immediate_rend_flag) +{ + const struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_BROADCAST_IMMEDIATE)}); + int ret; + + ret = bt_audio_codec_cap_meta_get_bcast_audio_immediate_rend_flag(&codec_cap); + zassert_equal(ret, 0, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_set_bcast_audio_immediate_rend_flag) +{ + struct bt_audio_codec_cap codec_cap = + BT_AUDIO_CODEC_CAP(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, {}); + int ret; + + ret = bt_audio_codec_cap_meta_get_bcast_audio_immediate_rend_flag(&codec_cap); + zassert_equal(ret, -ENODATA, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_meta_set_bcast_audio_immediate_rend_flag(&codec_cap); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_meta_get_bcast_audio_immediate_rend_flag(&codec_cap); + zassert_equal(ret, 0, "Unexpected return value %d", ret); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_get_extended) +{ + const uint8_t expected_data[] = {0x00, 0x01, 0x02, 0x03}; + const struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_EXTENDED, 0x00, 0x01, 0x02, 0x03)}); + const uint8_t *extended_meta; + int ret; + + ret = bt_audio_codec_cap_meta_get_extended(&codec_cap, &extended_meta); + zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(expected_data, extended_meta, ARRAY_SIZE(expected_data)); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_set_extended) +{ + const uint8_t expected_data[] = {0x00, 0x01, 0x02, 0x03}; + const uint8_t new_expected_data[] = {0x04, 0x05}; + struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_EXTENDED, 0x00, 0x01, 0x02, 0x03)}); + const uint8_t *extended_meta; + int ret; + + ret = bt_audio_codec_cap_meta_get_extended(&codec_cap, &extended_meta); + zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(expected_data, extended_meta, ARRAY_SIZE(expected_data)); + + ret = bt_audio_codec_cap_meta_set_extended(&codec_cap, new_expected_data, + ARRAY_SIZE(new_expected_data)); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_meta_get_extended(&codec_cap, &extended_meta); + zassert_equal(ret, ARRAY_SIZE(new_expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(new_expected_data, extended_meta, ARRAY_SIZE(new_expected_data)); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_get_vendor) +{ + const uint8_t expected_data[] = {0x00, 0x01, 0x02, 0x03}; + const struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_VENDOR, 0x00, 0x01, 0x02, 0x03)}); + const uint8_t *vendor_meta; + int ret; + + ret = bt_audio_codec_cap_meta_get_vendor(&codec_cap, &vendor_meta); + zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(expected_data, vendor_meta, ARRAY_SIZE(expected_data)); +} + +ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_set_vendor) +{ + const uint8_t expected_data[] = {0x00, 0x01, 0x02, 0x03}; + const uint8_t new_expected_data[] = {0x04, 0x05, 0x06, 0x07, 0x08}; + struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP( + BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {}, + {BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_VENDOR, 0x00, 0x01, 0x02, 0x03)}); + const uint8_t *extended_meta; + int ret; + + ret = bt_audio_codec_cap_meta_get_vendor(&codec_cap, &extended_meta); + zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(expected_data, extended_meta, ARRAY_SIZE(expected_data)); + + ret = bt_audio_codec_cap_meta_set_vendor(&codec_cap, new_expected_data, + ARRAY_SIZE(new_expected_data)); + zassert_true(ret > 0, "Unexpected return value %d", ret); + + ret = bt_audio_codec_cap_meta_get_vendor(&codec_cap, &extended_meta); + zassert_equal(ret, ARRAY_SIZE(new_expected_data), "Unexpected return value %d", ret); + zassert_mem_equal(new_expected_data, extended_meta, ARRAY_SIZE(new_expected_data)); +} diff --git a/tests/bluetooth/audio/mocks/CMakeLists.txt b/tests/bluetooth/audio/mocks/CMakeLists.txt index 10d37d191bf..270a9b75f19 100644 --- a/tests/bluetooth/audio/mocks/CMakeLists.txt +++ b/tests/bluetooth/audio/mocks/CMakeLists.txt @@ -11,6 +11,7 @@ add_library(mocks STATIC src/bap_unicast_client.c src/bap_unicast_server.c src/conn.c + src/crypto.c src/fatal.c src/gatt.c src/iso.c diff --git a/tests/bluetooth/audio/mocks/include/bluetooth.h b/tests/bluetooth/audio/mocks/include/bluetooth.h new file mode 100644 index 00000000000..43baf8b03ee --- /dev/null +++ b/tests/bluetooth/audio/mocks/include/bluetooth.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef MOCKS_BLUETOOTH_H_ +#define MOCKS_BLUETOOTH_H_ + +struct bt_le_ext_adv { + /* ID Address used for advertising */ + uint8_t id; + + /* Advertising handle */ + uint8_t handle; +}; + +#endif /* MOCKS_BLUETOOTH_H_ */ diff --git a/tests/bluetooth/audio/mocks/include/conn.h b/tests/bluetooth/audio/mocks/include/conn.h index eb78a05fe6e..ae6d3dc70d4 100644 --- a/tests/bluetooth/audio/mocks/include/conn.h +++ b/tests/bluetooth/audio/mocks/include/conn.h @@ -12,6 +12,7 @@ struct bt_conn { uint8_t index; struct bt_conn_info info; + struct bt_iso_chan *chan; }; void mock_bt_conn_disconnected(struct bt_conn *conn, uint8_t err); diff --git a/tests/bluetooth/audio/mocks/include/crypto.h b/tests/bluetooth/audio/mocks/include/crypto.h new file mode 100644 index 00000000000..1aa01e5203f --- /dev/null +++ b/tests/bluetooth/audio/mocks/include/crypto.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef MOCKS_CRYPTO_H_ +#define MOCKS_CRYPTO_H_ + +#include +#include + +/* List of fakes used by this unit tester */ +#define CRYPTO_FFF_FAKES_LIST(FAKE) FAKE(bt_rand) + +DECLARE_FAKE_VALUE_FUNC(int, bt_rand, void *, size_t); + +#endif /* MOCKS_CRYPTO_H_ */ diff --git a/tests/bluetooth/audio/mocks/include/gatt.h b/tests/bluetooth/audio/mocks/include/gatt.h index f54ad42492e..43b56dac29e 100644 --- a/tests/bluetooth/audio/mocks/include/gatt.h +++ b/tests/bluetooth/audio/mocks/include/gatt.h @@ -15,6 +15,8 @@ void mock_bt_gatt_cleanup(void); DECLARE_FAKE_VALUE_FUNC(int, mock_bt_gatt_notify_cb, struct bt_conn *, struct bt_gatt_notify_params *); +DECLARE_FAKE_VALUE_FUNC(bool, mock_bt_gatt_is_subscribed, struct bt_conn *, + const struct bt_gatt_attr *, uint16_t); void bt_gatt_notify_cb_reset(void); uint16_t bt_gatt_get_mtu(struct bt_conn *conn); diff --git a/tests/bluetooth/audio/mocks/include/iso.h b/tests/bluetooth/audio/mocks/include/iso.h index 40fd0ed94cd..82536c6f0fe 100644 --- a/tests/bluetooth/audio/mocks/include/iso.h +++ b/tests/bluetooth/audio/mocks/include/iso.h @@ -10,14 +10,19 @@ #include #include +#if defined(CONFIG_BT_BAP_BROADCAST_SOURCE) +struct bt_iso_big { + struct bt_iso_chan *bis[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT]; + uint8_t num_bis; +}; +#endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */ + void mock_bt_iso_init(void); void mock_bt_iso_cleanup(void); int mock_bt_iso_accept(struct bt_conn *conn, uint8_t cig_id, uint8_t cis_id, struct bt_iso_chan **chan); int mock_bt_iso_disconnected(struct bt_iso_chan *chan, uint8_t err); -DECLARE_FAKE_VALUE_FUNC(int, bt_iso_chan_send, struct bt_iso_chan *, struct net_buf *, uint16_t, - uint32_t); DECLARE_FAKE_VALUE_FUNC(int, bt_iso_chan_get_tx_sync, const struct bt_iso_chan *, struct bt_iso_tx_info *); diff --git a/tests/bluetooth/audio/mocks/include/mock_kernel.h b/tests/bluetooth/audio/mocks/include/mock_kernel.h index 8da6a064cda..360ff79f416 100644 --- a/tests/bluetooth/audio/mocks/include/mock_kernel.h +++ b/tests/bluetooth/audio/mocks/include/mock_kernel.h @@ -15,7 +15,6 @@ void mock_kernel_init(void); void mock_kernel_cleanup(void); DECLARE_FAKE_VALUE_FUNC(k_ticks_t, z_timeout_remaining, const struct _timeout *); -DECLARE_FAKE_VALUE_FUNC(int, k_work_schedule, struct k_work_delayable *, k_timeout_t); DECLARE_FAKE_VALUE_FUNC(bool, k_work_cancel_delayable_sync, struct k_work_delayable *, struct k_work_sync *); DECLARE_FAKE_VALUE_FUNC(int, k_sem_take, struct k_sem *, k_timeout_t); diff --git a/tests/bluetooth/audio/mocks/src/bap_stream.c b/tests/bluetooth/audio/mocks/src/bap_stream.c index c022865dc0a..f55fe226ec7 100644 --- a/tests/bluetooth/audio/mocks/src/bap_stream.c +++ b/tests/bluetooth/audio/mocks/src/bap_stream.c @@ -40,12 +40,14 @@ void mock_bap_stream_init(void) { FFF_FAKES_LIST(RESET_FAKE); +#if defined(CONFIG_BT_BAP_UNICAST) mock_bap_stream_ops.configured = mock_bap_stream_configured_cb; mock_bap_stream_ops.qos_set = mock_bap_stream_qos_set_cb; mock_bap_stream_ops.enabled = mock_bap_stream_enabled_cb; mock_bap_stream_ops.metadata_updated = mock_bap_stream_metadata_updated_cb; mock_bap_stream_ops.disabled = mock_bap_stream_disabled_cb; mock_bap_stream_ops.released = mock_bap_stream_released_cb; +#endif /* CONFIG_BT_BAP_UNICAST */ mock_bap_stream_ops.started = mock_bap_stream_started_cb; mock_bap_stream_ops.stopped = mock_bap_stream_stopped_cb; #if defined(CONFIG_BT_AUDIO_RX) diff --git a/tests/bluetooth/audio/mocks/src/crypto.c b/tests/bluetooth/audio/mocks/src/crypto.c new file mode 100644 index 00000000000..05e23238be2 --- /dev/null +++ b/tests/bluetooth/audio/mocks/src/crypto.c @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include "crypto.h" + +DEFINE_FAKE_VALUE_FUNC(int, bt_rand, void *, size_t); diff --git a/tests/bluetooth/audio/mocks/src/gatt.c b/tests/bluetooth/audio/mocks/src/gatt.c index be2ca633df8..29ab2ee2b0d 100644 --- a/tests/bluetooth/audio/mocks/src/gatt.c +++ b/tests/bluetooth/audio/mocks/src/gatt.c @@ -18,9 +18,12 @@ LOG_MODULE_REGISTER(bt_gatt); /* List of fakes used by this unit tester */ #define FFF_FAKES_LIST(FAKE) \ FAKE(mock_bt_gatt_notify_cb) \ + FAKE(mock_bt_gatt_is_subscribed) \ DEFINE_FAKE_VALUE_FUNC(int, mock_bt_gatt_notify_cb, struct bt_conn *, struct bt_gatt_notify_params *); +DEFINE_FAKE_VALUE_FUNC(bool, mock_bt_gatt_is_subscribed, struct bt_conn *, + const struct bt_gatt_attr *, uint16_t); ssize_t bt_gatt_attr_read_service(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) @@ -53,14 +56,42 @@ ssize_t bt_gatt_attr_write_ccc(struct bt_conn *conn, const struct bt_gatt_attr * void mock_bt_gatt_init(void) { FFF_FAKES_LIST(RESET_FAKE); + + mock_bt_gatt_is_subscribed_fake.return_val = true; } -static void notify_params_deep_copy_destroy(void) +static void notify_params_deep_copy_destroy(struct bt_gatt_notify_params *params) { struct bt_gatt_notify_params *copy; for (unsigned int i = 0; i < mock_bt_gatt_notify_cb_fake.call_count; i++) { copy = mock_bt_gatt_notify_cb_fake.arg1_history[i]; + if (copy != params) { + continue; + } + + /* Free UUID deep copy */ + if (copy->uuid) { + free((void *)copy->uuid); + } + + free(copy); + + mock_bt_gatt_notify_cb_fake.arg1_history[i] = NULL; + + break; + } +} + +static void notify_params_deep_copy_destroy_all(void) +{ + struct bt_gatt_notify_params *copy; + + for (unsigned int i = 0; i < mock_bt_gatt_notify_cb_fake.call_count; i++) { + copy = mock_bt_gatt_notify_cb_fake.arg1_history[i]; + if (copy == NULL) { + continue; + } /* Free UUID deep copy */ if (copy->uuid) { @@ -73,7 +104,7 @@ static void notify_params_deep_copy_destroy(void) void mock_bt_gatt_cleanup(void) { - notify_params_deep_copy_destroy(); + notify_params_deep_copy_destroy_all(); } static struct bt_uuid *uuid_deep_copy(const struct bt_uuid *uuid) @@ -121,6 +152,9 @@ static struct bt_gatt_notify_params *notify_params_deep_copy(struct bt_gatt_noti int bt_gatt_notify_cb(struct bt_conn *conn, struct bt_gatt_notify_params *params) { + struct bt_gatt_notify_params *copy; + int err; + zassert_not_null(params, "'%s()' was called with incorrect '%s' value", __func__, "params"); /* Either params->uuid, params->attr, or both has to be provided */ @@ -128,12 +162,19 @@ int bt_gatt_notify_cb(struct bt_conn *conn, struct bt_gatt_notify_params *params "'%s()' was called with incorrect '%s' value", __func__, "params->uuid or params->attr"); - return mock_bt_gatt_notify_cb(conn, notify_params_deep_copy(params)); + copy = notify_params_deep_copy(params); + + err = mock_bt_gatt_notify_cb(conn, copy); + if (err != 0) { + notify_params_deep_copy_destroy(copy); + } + + return err; } void bt_gatt_notify_cb_reset(void) { - notify_params_deep_copy_destroy(); + notify_params_deep_copy_destroy_all(); RESET_FAKE(mock_bt_gatt_notify_cb); } @@ -246,3 +287,9 @@ uint16_t bt_gatt_get_mtu(struct bt_conn *conn) { return 64; } + +bool bt_gatt_is_subscribed(struct bt_conn *conn, + const struct bt_gatt_attr *attr, uint16_t ccc_type) +{ + return mock_bt_gatt_is_subscribed(conn, attr, ccc_type); +} diff --git a/tests/bluetooth/audio/mocks/src/iso.c b/tests/bluetooth/audio/mocks/src/iso.c index 875ba170577..ccf29c07737 100644 --- a/tests/bluetooth/audio/mocks/src/iso.c +++ b/tests/bluetooth/audio/mocks/src/iso.c @@ -11,18 +11,22 @@ #include "iso.h" /* List of fakes used by this unit tester */ -#define FFF_FAKES_LIST(FAKE) \ - FAKE(bt_iso_chan_send) \ - FAKE(bt_iso_chan_get_tx_sync) +#define FFF_FAKES_LIST(FAKE) FAKE(bt_iso_chan_get_tx_sync) static struct bt_iso_server *iso_server; -DEFINE_FAKE_VALUE_FUNC(int, bt_iso_chan_send, struct bt_iso_chan *, struct net_buf *, uint16_t, - uint32_t); - DEFINE_FAKE_VALUE_FUNC(int, bt_iso_chan_get_tx_sync, const struct bt_iso_chan *, struct bt_iso_tx_info *); +int bt_iso_chan_send(struct bt_iso_chan *chan, struct net_buf *buf, uint16_t seq_num, uint32_t ts) +{ + if (chan->ops != NULL && chan->ops->sent != NULL) { + chan->ops->sent(chan); + } + + return 0; +} + int bt_iso_server_register(struct bt_iso_server *server) { zassert_not_null(server, "server is NULL"); @@ -59,6 +63,16 @@ void mock_bt_iso_cleanup(void) } +void mock_bt_iso_connected(struct bt_conn *iso) +{ + struct bt_iso_chan *chan = iso->chan; + + chan->state = BT_ISO_STATE_CONNECTED; + chan->iso = iso; + + chan->ops->connected(chan); +} + int mock_bt_iso_accept(struct bt_conn *conn, uint8_t cig_id, uint8_t cis_id, struct bt_iso_chan **chan) { @@ -67,6 +81,7 @@ int mock_bt_iso_accept(struct bt_conn *conn, uint8_t cig_id, uint8_t cis_id, .cig_id = cig_id, .cis_id = cis_id, }; + struct bt_conn *iso; int err; zassert_not_null(iso_server, "iso_server is NULL"); @@ -78,11 +93,11 @@ int mock_bt_iso_accept(struct bt_conn *conn, uint8_t cig_id, uint8_t cis_id, zassert_not_null(*chan, "chan is NULL"); - (*chan)->state = BT_ISO_STATE_CONNECTED; - (*chan)->iso = malloc(sizeof(struct bt_conn)); - zassert_not_null((*chan)->iso); + iso = malloc(sizeof(struct bt_conn)); + zassert_not_null(iso); - (*chan)->ops->connected(*chan); + iso->chan = (*chan); + mock_bt_iso_connected(iso); return 0; } @@ -96,3 +111,56 @@ int mock_bt_iso_disconnected(struct bt_iso_chan *chan, uint8_t err) return 0; } + +#if defined(CONFIG_BT_BAP_BROADCAST_SOURCE) +int bt_iso_big_create(struct bt_le_ext_adv *padv, struct bt_iso_big_create_param *param, + struct bt_iso_big **out_big) +{ + struct bt_iso_big *big; + + zassert_not_null(out_big); + zassert_not_null(param); + zassert_not_equal(param->num_bis, 0); + + big = malloc(sizeof(struct bt_iso_big)); + zassert_not_null(big); + big->num_bis = 0U; + + for (uint8_t i = 0U; i < param->num_bis; i++) { + struct bt_iso_chan *bis = param->bis_channels[i]; + struct bt_conn *iso; + + zassert_not_null(bis); + + iso = malloc(sizeof(struct bt_conn)); + zassert_not_null(iso); + big->bis[i] = bis; + big->num_bis++; + + iso->chan = bis; + mock_bt_iso_connected(iso); + } + + *out_big = big; + + return 0; +} + +int bt_iso_big_terminate(struct bt_iso_big *big) +{ + /* TODO: Call chan->ops->disconnected(*chan); for each BIS */ + zassert_not_equal(big->num_bis, 0); + + for (uint8_t i = 0U; i < big->num_bis; i++) { + struct bt_iso_chan *bis = big->bis[i]; + + zassert_not_null(bis, "big %p", big); + + mock_bt_iso_disconnected(bis, BT_HCI_ERR_LOCALHOST_TERM_CONN); + } + + free(big); + + return 0; +} +#endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */ diff --git a/tests/bluetooth/audio/mocks/src/kernel.c b/tests/bluetooth/audio/mocks/src/kernel.c index 03dc2cf582d..5cd8bbbd852 100644 --- a/tests/bluetooth/audio/mocks/src/kernel.c +++ b/tests/bluetooth/audio/mocks/src/kernel.c @@ -6,6 +6,7 @@ */ #include +#include #include #include "mock_kernel.h" @@ -13,14 +14,12 @@ /* List of fakes used by this unit tester */ #define FFF_FAKES_LIST(FAKE) \ FAKE(z_timeout_remaining) \ - FAKE(k_work_schedule) \ FAKE(k_work_cancel_delayable_sync) \ /* List of k_work items to be worked. */ static sys_slist_t work_pending; DEFINE_FAKE_VALUE_FUNC(k_ticks_t, z_timeout_remaining, const struct _timeout *); -DEFINE_FAKE_VALUE_FUNC(int, k_work_schedule, struct k_work_delayable *, k_timeout_t); DEFINE_FAKE_VALUE_FUNC(bool, k_work_cancel_delayable_sync, struct k_work_delayable *, struct k_work_sync *); DEFINE_FAKE_VALUE_FUNC(int, k_sem_take, struct k_sem *, k_timeout_t); @@ -32,19 +31,49 @@ void k_work_init_delayable(struct k_work_delayable *dwork, k_work_handler_t hand } int k_work_reschedule(struct k_work_delayable *dwork, k_timeout_t delay) +{ + bool on_list = false; + struct k_work *work; + + dwork->timeout.dticks = delay.ticks; + + /* Determine whether the work item is queued already. */ + SYS_SLIST_FOR_EACH_CONTAINER(&work_pending, work, node) { + on_list = work == &dwork->work; + if (on_list) { + break; + } + } + + if (dwork->timeout.dticks == 0) { + dwork->work.handler(&dwork->work); + if (on_list) { + (void)sys_slist_remove(&work_pending, NULL, &dwork->work.node); + } + } else if (!on_list) { + sys_slist_append(&work_pending, &dwork->work.node); + } + + return 0; +} + +int k_work_schedule(struct k_work_delayable *dwork, k_timeout_t delay) { struct k_work *work; /* Determine whether the work item is queued already. */ SYS_SLIST_FOR_EACH_CONTAINER(&work_pending, work, node) { if (work == &dwork->work) { - dwork->timeout.dticks = delay.ticks; return 0; } } dwork->timeout.dticks = delay.ticks; - sys_slist_append(&work_pending, &dwork->work.node); + if (dwork->timeout.dticks == 0) { + dwork->work.handler(&dwork->work); + } else { + sys_slist_append(&work_pending, &dwork->work.node); + } return 0; } diff --git a/tests/bluetooth/audio/mocks/src/mem_slab.c b/tests/bluetooth/audio/mocks/src/mem_slab.c index ec3ef196e5b..65209b848e5 100644 --- a/tests/bluetooth/audio/mocks/src/mem_slab.c +++ b/tests/bluetooth/audio/mocks/src/mem_slab.c @@ -9,20 +9,20 @@ int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem, k_timeout_t timeout) { - if (slab->num_used >= slab->num_blocks) { + if (slab->info.num_used >= slab->info.num_blocks) { *mem = NULL; return -ENOMEM; } - *mem = malloc(slab->block_size); + *mem = malloc(slab->info.block_size); zassert_not_null(*mem); - slab->num_used++; + slab->info.num_used++; return 0; } void k_mem_slab_free(struct k_mem_slab *slab, void *mem) { free(mem); - slab->num_used--; + slab->info.num_used--; } diff --git a/tests/bluetooth/bluetooth/prj.conf b/tests/bluetooth/bluetooth/prj.conf index c150a19272d..ee911c43132 100644 --- a/tests/bluetooth/bluetooth/prj.conf +++ b/tests/bluetooth/bluetooth/prj.conf @@ -4,4 +4,3 @@ CONFIG_BT_NO_DRIVER=y CONFIG_LOG=y CONFIG_UART_INTERRUPT_DRIVEN=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/bt_crypto/prj.conf b/tests/bluetooth/bt_crypto/prj.conf index 84088e6b035..fec5098eecf 100644 --- a/tests/bluetooth/bt_crypto/prj.conf +++ b/tests/bluetooth/bt_crypto/prj.conf @@ -1,6 +1,5 @@ CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CTLR=n diff --git a/tests/bluetooth/bt_crypto/src/test_bt_crypto.c b/tests/bluetooth/bt_crypto/src/test_bt_crypto.c index 8f5aec3e36c..bddce1849c3 100644 --- a/tests/bluetooth/bt_crypto/src/test_bt_crypto.c +++ b/tests/bluetooth/bt_crypto/src/test_bt_crypto.c @@ -2,7 +2,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "zephyr/ztest_assert.h" +#include #include #include diff --git a/tests/bluetooth/bt_crypto_ccm/prj.conf b/tests/bluetooth/bt_crypto_ccm/prj.conf index 37164576b39..68662d4a0c5 100644 --- a/tests/bluetooth/bt_crypto_ccm/prj.conf +++ b/tests/bluetooth/bt_crypto_ccm/prj.conf @@ -1,6 +1,5 @@ CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CTLR=n diff --git a/tests/bluetooth/common/testlib/CMakeLists.txt b/tests/bluetooth/common/testlib/CMakeLists.txt new file mode 100644 index 00000000000..7166abd3e06 --- /dev/null +++ b/tests/bluetooth/common/testlib/CMakeLists.txt @@ -0,0 +1,24 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +add_library(testlib) + +target_link_libraries(testlib PUBLIC + kernel + subsys__bluetooth__host + zephyr_interface +) + +target_include_directories(testlib PUBLIC + include +) + +target_sources(testlib PRIVATE + src/adv.c + src/att_read.c + src/att_write.c + src/connect.c + src/conn_wait.c + src/scan.c + src/security.c +) diff --git a/tests/bluetooth/common/testlib/include/testlib/adv.h b/tests/bluetooth/common/testlib/include/testlib/adv.h new file mode 100644 index 00000000000..2b326802b1c --- /dev/null +++ b/tests/bluetooth/common/testlib/include/testlib/adv.h @@ -0,0 +1,12 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_ADV_H_ +#define ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_ADV_H_ + +#include + +int bt_testlib_adv_conn(struct bt_conn **conn, int id, uint32_t adv_options); + +#endif /* ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_ADV_H_ */ diff --git a/tests/bluetooth/common/testlib/include/testlib/att_read.h b/tests/bluetooth/common/testlib/include/testlib/att_read.h new file mode 100644 index 00000000000..6e12d441e4e --- /dev/null +++ b/tests/bluetooth/common/testlib/include/testlib/att_read.h @@ -0,0 +1,44 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_ATT_READ_H_ +#define ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_ATT_READ_H_ + +#include +#include + +/** Perform a single ATT_READ_BY_TYPE_REQ. */ +int bt_testlib_att_read_by_type_sync(struct net_buf_simple *result_data, uint16_t *result_size, + uint16_t *result_handle, uint16_t *result_att_mtu, + struct bt_conn *conn, enum bt_att_chan_opt bearer, + const struct bt_uuid *type, uint16_t start_handle, + uint16_t end_handle); + +/** If offset == 0, perform a single ATT_READ_REQ. + * If offset > 0, perform a signle ATT_READ_BLOB_REQ. + */ +int bt_testlib_att_read_by_handle_sync(struct net_buf_simple *result_data, uint16_t *result_size, + uint16_t *result_att_mtu, struct bt_conn *conn, + enum bt_att_chan_opt bearer, uint16_t handle, + uint16_t offset); + +int bt_testlib_gatt_long_read(struct net_buf_simple *result_data, uint16_t *result_size, + struct bt_conn *conn, enum bt_att_chan_opt bearer, uint16_t handle, + uint16_t offset); + +int bt_testlib_gatt_discover_primary(uint16_t *result_handle, uint16_t *result_end_handle, + struct bt_conn *conn, const struct bt_uuid *uuid, + uint16_t start_handle, uint16_t end_handle); + +/* Note: svc_end_handle must be the service end handle. (The discovery + * algorithm requires it to recognize the last characteristic in a + * service and deduce its end handle.) + */ +int bt_testlib_gatt_discover_characteristic(uint16_t *const result_value_handle, + uint16_t *const result_end_handle, + uint16_t *const result_def_handle, struct bt_conn *conn, + const struct bt_uuid *uuid, uint16_t start_handle, + uint16_t svc_end_handle); + +#endif /* ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_ATT_READ_H_ */ diff --git a/tests/bluetooth/common/testlib/include/testlib/att_write.h b/tests/bluetooth/common/testlib/include/testlib/att_write.h new file mode 100644 index 00000000000..0cfd03e88b6 --- /dev/null +++ b/tests/bluetooth/common/testlib/include/testlib/att_write.h @@ -0,0 +1,14 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_ATT_WRITE_H_ +#define ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_ATT_WRITE_H_ + +#include +#include + +int bt_testlib_att_write(struct bt_conn *conn, enum bt_att_chan_opt bearer, uint16_t handle, + const uint8_t *data, uint16_t size); + +#endif /* ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_ATT_WRITE_H_ */ diff --git a/tests/bluetooth/common/testlib/include/testlib/conn_ref.h b/tests/bluetooth/common/testlib/include/testlib/conn_ref.h new file mode 100644 index 00000000000..9e96eb3fc40 --- /dev/null +++ b/tests/bluetooth/common/testlib/include/testlib/conn_ref.h @@ -0,0 +1,42 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_CONN_REF_H_ +#define ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_CONN_REF_H_ + +#include +#include + +/** + * @file + * @brief Reified connection reference counting. + * @ingroup testlib conn ref + * + * This file provides functions to reify the moving and cloning of @ref + * bt_conn references for increased safety. + * + * Reifying means that the existence of a reference is always tied + * one-to-one with a non-NULL value in a owning pointer variable. + * + * The functions in this file will trigger an assert if they attempt to + * overwrite a non-NULL value in a owning pointer variable. This is to + * prevent leaking the reference that presumable is tied the value that + * would be overwritten. + * + * The functions in this file are intended to guard against undefined + * behavor due to NULL pointer dereferencing. They will assert on any + * relevant pointers. + */ + +void bt_testlib_conn_unref(struct bt_conn **connp) +{ + struct bt_conn *conn; + + __ASSERT_NO_MSG(connp); + conn = atomic_ptr_set((void **)connp, NULL); + __ASSERT_NO_MSG(conn); + bt_conn_unref(conn); +} + +#endif /* ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_CONN_REF_H_ */ diff --git a/tests/bluetooth/common/testlib/include/testlib/conn_wait.h b/tests/bluetooth/common/testlib/include/testlib/conn_wait.h new file mode 100644 index 00000000000..00f8ddb5cdc --- /dev/null +++ b/tests/bluetooth/common/testlib/include/testlib/conn_wait.h @@ -0,0 +1,12 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_CONN_WAIT_H_ +#define ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_CONN_WAIT_H_ +#include + +int bt_testlib_wait_connected(struct bt_conn *conn); +int bt_testlib_wait_disconnected(struct bt_conn *conn); + +#endif /* ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_CONN_WAIT_H_ */ diff --git a/tests/bluetooth/common/testlib/include/testlib/connect.h b/tests/bluetooth/common/testlib/include/testlib/connect.h new file mode 100644 index 00000000000..912e4d0cdc7 --- /dev/null +++ b/tests/bluetooth/common/testlib/include/testlib/connect.h @@ -0,0 +1,12 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_CONNECT_H_ +#define ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_CONNECT_H_ + +#include + +int bt_testlib_connect(const bt_addr_le_t *peer, struct bt_conn **conn); + +#endif /* ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_CONNECT_H_ */ diff --git a/tests/bluetooth/common/testlib/include/testlib/log_utils.h b/tests/bluetooth/common/testlib/include/testlib/log_utils.h new file mode 100644 index 00000000000..66cd2c0a2f7 --- /dev/null +++ b/tests/bluetooth/common/testlib/include/testlib/log_utils.h @@ -0,0 +1,41 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_LOG_UTILS_H_ +#define ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_LOG_UTILS_H_ + +#include +#include + +static inline void bt_testlib_log_level_set(char *module, uint32_t new_level) +{ + int source_id; + uint32_t result_level; + + __ASSERT_NO_MSG(IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING)); + + source_id = log_source_id_get(module); + __ASSERT(source_id >= 0, "%d", source_id); + + result_level = log_filter_set(NULL, Z_LOG_LOCAL_DOMAIN_ID, source_id, new_level); + __ASSERT(result_level == new_level, "%u %u", result_level, new_level); +} + +static inline void bt_testlib_log_level_set_all(uint32_t new_level) +{ + uint32_t source_count; + + __ASSERT_NO_MSG(IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING)); + + source_count = log_src_cnt_get(Z_LOG_LOCAL_DOMAIN_ID); + + for (uint32_t source_id = 0; source_id < source_count; source_id++) { + uint32_t result_level; + + result_level = log_filter_set(NULL, Z_LOG_LOCAL_DOMAIN_ID, source_id, new_level); + __ASSERT(result_level == new_level, "%u %u", result_level, new_level); + } +} + +#endif /* ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_LOG_UTILS_H_ */ diff --git a/tests/bluetooth/common/testlib/include/testlib/scan.h b/tests/bluetooth/common/testlib/include/testlib/scan.h new file mode 100644 index 00000000000..d68f3aba684 --- /dev/null +++ b/tests/bluetooth/common/testlib/include/testlib/scan.h @@ -0,0 +1,12 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_SCAN_H_ +#define ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_SCAN_H_ + +#include + +int bt_testlib_scan_find_name(bt_addr_le_t *result, const char *name); + +#endif /* ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_SCAN_H_ */ diff --git a/tests/bluetooth/common/testlib/include/testlib/security.h b/tests/bluetooth/common/testlib/include/testlib/security.h new file mode 100644 index 00000000000..9950f5f71b9 --- /dev/null +++ b/tests/bluetooth/common/testlib/include/testlib/security.h @@ -0,0 +1,12 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_SECURITY_H_ +#define ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_SECURITY_H_ + +#include + +int bt_testlib_secure(struct bt_conn *conn, bt_security_t new_minimum); + +#endif /* ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_SECURITY_H_ */ diff --git a/tests/bluetooth/common/testlib/src/adv.c b/tests/bluetooth/common/testlib/src/adv.c new file mode 100644 index 00000000000..e67d3bb6fe8 --- /dev/null +++ b/tests/bluetooth/common/testlib/src/adv.c @@ -0,0 +1,83 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct bt_testlib_adv_ctx { + struct bt_conn **result; + struct k_condvar done; +}; + +/* Context pool (with capacity of one). */ +static K_SEM_DEFINE(g_ctx_free, 1, 1); +static K_MUTEX_DEFINE(g_ctx_lock); +static struct bt_testlib_adv_ctx *g_ctx; + +static void connected_cb(struct bt_le_ext_adv *adv, struct bt_le_ext_adv_connected_info *info) +{ + k_mutex_lock(&g_ctx_lock, K_FOREVER); + + if (g_ctx->result) { + *g_ctx->result = bt_conn_ref(info->conn); + } + k_condvar_signal(&g_ctx->done); + + k_mutex_unlock(&g_ctx_lock); +} + +int bt_testlib_adv_conn(struct bt_conn **conn, int id, uint32_t adv_options) +{ + int api_err; + struct bt_le_ext_adv *adv = NULL; + struct bt_le_adv_param param = {}; + struct bt_testlib_adv_ctx ctx = { + .result = conn, + }; + static const struct bt_le_ext_adv_cb cb = { + .connected = connected_cb, + }; + + param.id = id; + param.interval_min = BT_GAP_ADV_FAST_INT_MIN_1; + param.interval_max = BT_GAP_ADV_FAST_INT_MAX_1; + param.options |= BT_LE_ADV_OPT_CONNECTABLE; + param.options |= adv_options; + + k_condvar_init(&ctx.done); + + k_sem_take(&g_ctx_free, K_FOREVER); + k_mutex_lock(&g_ctx_lock, K_FOREVER); + g_ctx = &ctx; + + api_err = bt_le_ext_adv_create(¶m, &cb, &adv); + if (!api_err) { + api_err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT); + } + + if (!api_err) { + k_condvar_wait(&ctx.done, &g_ctx_lock, K_FOREVER); + } + + /* Delete adv before giving semaphore so that it's potentially available + * for the next taker of the semaphore. + */ + if (adv) { + bt_le_ext_adv_delete(adv); + } + + g_ctx = NULL; + k_mutex_unlock(&g_ctx_lock); + k_sem_give(&g_ctx_free); + + return api_err; +} diff --git a/tests/bluetooth/common/testlib/src/att_read.c b/tests/bluetooth/common/testlib/src/att_read.c new file mode 100644 index 00000000000..d7dd17ee07c --- /dev/null +++ b/tests/bluetooth/common/testlib/src/att_read.c @@ -0,0 +1,387 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +LOG_MODULE_REGISTER(bt_testlib_att_read, LOG_LEVEL_DBG); + +struct bt_testlib_att_read_closure { + uint8_t att_err; + struct bt_conn *conn; + struct bt_gatt_read_params params; + uint16_t *result_size; + uint16_t *result_handle; + struct net_buf_simple *result_data; + struct k_mutex lock; + struct k_condvar done; + uint16_t *att_mtu; + bool long_read; +}; + +static uint8_t att_read_cb(struct bt_conn *conn, uint8_t att_err, + struct bt_gatt_read_params *params, const void *read_data, + uint16_t read_len) +{ + struct bt_testlib_att_read_closure *ctx = + CONTAINER_OF(params, struct bt_testlib_att_read_closure, params); + + k_mutex_lock(&ctx->lock, K_FOREVER); + + if (read_data == NULL) { + __ASSERT_NO_MSG(ctx->long_read); + k_condvar_signal(&ctx->done); + k_mutex_unlock(&ctx->lock); + return BT_GATT_ITER_STOP; + } + + ctx->att_err = att_err; + + if (!att_err && ctx->result_handle) { + *ctx->result_handle = params->by_uuid.start_handle; + } + + if (!att_err && ctx->result_size) { + LOG_DBG("Adding %u bytes to result", read_len); + *ctx->result_size += read_len; + if (*ctx->result_size > BT_ATT_MAX_ATTRIBUTE_LEN) { + LOG_ERR("result_size > 512"); + } + } + + if (!att_err && ctx->result_data) { + uint16_t result_data_size = + MIN(read_len, net_buf_simple_tailroom(ctx->result_data)); + + net_buf_simple_add_mem(ctx->result_data, read_data, result_data_size); + } + + if (!att_err && ctx->att_mtu) { + *ctx->att_mtu = params->_att_mtu; + } + + if (ctx->long_read) { + /* Don't signal `&ctx->done` */ + k_mutex_unlock(&ctx->lock); + return BT_GATT_ITER_CONTINUE; + } + + k_condvar_signal(&ctx->done); + k_mutex_unlock(&ctx->lock); + return BT_GATT_ITER_STOP; +} + +static int bt_testlib_sync_bt_gatt_read(struct bt_testlib_att_read_closure *ctx) +{ + int api_err; + + ctx->params.func = att_read_cb; + + k_mutex_init(&ctx->lock); + k_condvar_init(&ctx->done); + + k_mutex_lock(&ctx->lock, K_FOREVER); + + api_err = bt_gatt_read(ctx->conn, &ctx->params); + + if (!api_err) { + k_condvar_wait(&ctx->done, &ctx->lock, K_FOREVER); + } + + k_mutex_unlock(&ctx->lock); + + if (api_err) { + __ASSERT_NO_MSG(api_err < 0); + return api_err; + } + + __ASSERT_NO_MSG(ctx->att_err >= 0); + return ctx->att_err; +} + +int bt_testlib_att_read_by_type_sync(struct net_buf_simple *result_data, uint16_t *result_size, + uint16_t *result_handle, uint16_t *result_att_mtu, + struct bt_conn *conn, enum bt_att_chan_opt bearer, + const struct bt_uuid *type, uint16_t start_handle, + uint16_t end_handle) +{ + struct bt_testlib_att_read_closure ctx = {.result_handle = result_handle, + .result_size = result_size, + .conn = conn, + .result_data = result_data, + .att_mtu = result_att_mtu, + .params = { + .by_uuid = {.uuid = type, + .start_handle = start_handle, + .end_handle = end_handle}, + }}; + + IF_ENABLED(CONFIG_BT_EATT, ({ ctx.params.chan_opt = bearer; })) + + if (bearer == BT_ATT_CHAN_OPT_ENHANCED_ONLY) { + __ASSERT(IS_ENABLED(CONFIG_BT_EATT), "EATT not complied in"); + } + + return bt_testlib_sync_bt_gatt_read(&ctx); +} + +int bt_testlib_att_read_by_handle_sync(struct net_buf_simple *result_data, uint16_t *result_size, + uint16_t *result_att_mtu, struct bt_conn *conn, + enum bt_att_chan_opt bearer, uint16_t handle, + uint16_t offset) +{ + struct bt_testlib_att_read_closure ctx = { + .result_size = result_size, + .conn = conn, + .att_mtu = result_att_mtu, + .result_data = result_data, + .params = { + .handle_count = 1, + .single = {.handle = handle, .offset = offset}, + IF_ENABLED(CONFIG_BT_EATT, (.chan_opt = bearer,)) + }}; + + if (bearer == BT_ATT_CHAN_OPT_ENHANCED_ONLY) { + __ASSERT(IS_ENABLED(CONFIG_BT_EATT), "EATT not complied in"); + } + + *result_size = 0; + + return bt_testlib_sync_bt_gatt_read(&ctx); +} + +int bt_testlib_gatt_long_read(struct net_buf_simple *result_data, uint16_t *result_size, + struct bt_conn *conn, enum bt_att_chan_opt bearer, uint16_t handle, + uint16_t offset) +{ + int err; + uint16_t _result_data_size = 0; + + struct bt_testlib_att_read_closure ctx = { + .long_read = true, + .result_size = &_result_data_size, + .conn = conn, + .result_data = result_data, + .params = { + .handle_count = 1, + .single = {.handle = handle, .offset = offset}, + IF_ENABLED(CONFIG_BT_EATT, (.chan_opt = bearer,)) + }}; + + if (bearer == BT_ATT_CHAN_OPT_ENHANCED_ONLY) { + __ASSERT(IS_ENABLED(CONFIG_BT_EATT), "EATT not complied in"); + } + + err = bt_testlib_sync_bt_gatt_read(&ctx); + + if (result_size) { + *result_size = _result_data_size; + } + + return err; +} + +struct bt_testlib_gatt_discover_service_closure { + struct bt_gatt_discover_params params; + uint8_t att_err; + uint16_t *const result_handle; + uint16_t *const result_end_handle; + struct k_mutex lock; + struct k_condvar done; +}; + +static uint8_t gatt_discover_service_cb(struct bt_conn *conn, const struct bt_gatt_attr *attr, + struct bt_gatt_discover_params *params) +{ + struct bt_testlib_gatt_discover_service_closure *ctx = + CONTAINER_OF(params, struct bt_testlib_gatt_discover_service_closure, params); + + k_mutex_lock(&ctx->lock, K_FOREVER); + + ctx->att_err = attr ? BT_ATT_ERR_SUCCESS : BT_ATT_ERR_ATTRIBUTE_NOT_FOUND; + + if (!ctx->att_err) { + if (ctx->result_handle) { + *ctx->result_handle = attr->handle; + } + + if (ctx->result_end_handle) { + *ctx->result_end_handle = 0; + /* Output 'group end handle'. */ + if (params->type == BT_GATT_DISCOVER_PRIMARY || + params->type == BT_GATT_DISCOVER_SECONDARY) { + *ctx->result_end_handle = + ((struct bt_gatt_service_val *)attr->user_data)->end_handle; + } + } + } + + k_condvar_signal(&ctx->done); + k_mutex_unlock(&ctx->lock); + return BT_GATT_ITER_STOP; +} + +/** AKA Service discovery by UUID. + */ +int bt_testlib_gatt_discover_primary(uint16_t *result_handle, uint16_t *result_end_handle, + struct bt_conn *conn, const struct bt_uuid *uuid, + uint16_t start_handle, uint16_t end_handle) +{ + int api_err; + + struct bt_testlib_gatt_discover_service_closure ctx_val = { + .result_handle = result_handle, + .result_end_handle = result_end_handle, + .params = { + .type = BT_GATT_DISCOVER_PRIMARY, + .start_handle = start_handle, + .end_handle = end_handle, + .func = gatt_discover_service_cb, + .uuid = uuid, + }}; + struct bt_testlib_gatt_discover_service_closure *const ctx = &ctx_val; + + k_mutex_init(&ctx->lock); + k_condvar_init(&ctx->done); + + __ASSERT_NO_MSG(conn); + __ASSERT_NO_MSG(IN_RANGE(start_handle, BT_ATT_FIRST_ATTRIBUTE_HANDLE, + BT_ATT_LAST_ATTRIBUTE_HANDLE)); + __ASSERT_NO_MSG( + IN_RANGE(end_handle, BT_ATT_FIRST_ATTRIBUTE_HANDLE, BT_ATT_LAST_ATTRIBUTE_HANDLE)); + + k_mutex_lock(&ctx->lock, K_FOREVER); + + api_err = bt_gatt_discover(conn, &ctx->params); + + if (!api_err) { + k_condvar_wait(&ctx->done, &ctx->lock, K_FOREVER); + } + + k_mutex_unlock(&ctx->lock); + + if (api_err) { + __ASSERT_NO_MSG(api_err < 0); + return api_err; + } + __ASSERT_NO_MSG(ctx->att_err >= 0); + return ctx->att_err; +} + +struct bt_testlib_gatt_discover_char_closure { + struct bt_gatt_discover_params params; + uint8_t att_err; + uint16_t *const result_def_handle; + uint16_t *const result_value_handle; + uint16_t *const result_end_handle; + uint16_t svc_end_handle; + struct k_mutex lock; + struct k_condvar done; +}; + +static uint8_t gatt_discover_char_cb(struct bt_conn *conn, const struct bt_gatt_attr *attr, + struct bt_gatt_discover_params *params) +{ + struct bt_testlib_gatt_discover_char_closure *ctx = + CONTAINER_OF(params, struct bt_testlib_gatt_discover_char_closure, params); + bool read_more = false; + + k_mutex_lock(&ctx->lock, K_FOREVER); + + if (ctx->att_err == BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) { + /* The start of the charachteristic was not found yet. + * This is the start of the characteristic. + */ + if (attr) { + ctx->att_err = BT_ATT_ERR_SUCCESS; + if (ctx->result_def_handle) { + *ctx->result_def_handle = attr->handle; + } + if (ctx->result_value_handle) { + *ctx->result_value_handle = + ((struct bt_gatt_chrc *)attr->user_data)->value_handle; + } + if (ctx->result_end_handle) { + read_more = true; + } + } + } else { + /* This is the end of the characteristic. + */ + if (attr) { + __ASSERT_NO_MSG(ctx->result_end_handle); + *ctx->result_end_handle = (attr->handle - 1); + } + }; + + if (!read_more) { + k_condvar_signal(&ctx->done); + } + k_mutex_unlock(&ctx->lock); + return read_more ? BT_GATT_ITER_CONTINUE : BT_GATT_ITER_STOP; +} + +int bt_testlib_gatt_discover_characteristic(uint16_t *const result_value_handle, + uint16_t *const result_end_handle, + uint16_t *const result_def_handle, struct bt_conn *conn, + const struct bt_uuid *uuid, uint16_t start_handle, + uint16_t svc_end_handle) +{ + int api_err; + + if (result_end_handle) { + /* If there is no second result, the end_handle is the svc_end. */ + *result_end_handle = svc_end_handle; + } + + struct bt_testlib_gatt_discover_char_closure ctx_val = { + .att_err = BT_ATT_ERR_ATTRIBUTE_NOT_FOUND, + .result_value_handle = result_value_handle, + .result_def_handle = result_def_handle, + .result_end_handle = result_end_handle, + .params = { + .type = BT_GATT_DISCOVER_CHARACTERISTIC, + .start_handle = start_handle, + .end_handle = svc_end_handle, + .func = gatt_discover_char_cb, + .uuid = uuid, + }}; + struct bt_testlib_gatt_discover_char_closure *const ctx = &ctx_val; + + k_mutex_init(&ctx->lock); + k_condvar_init(&ctx->done); + + __ASSERT_NO_MSG(conn); + __ASSERT_NO_MSG(IN_RANGE(start_handle, BT_ATT_FIRST_ATTRIBUTE_HANDLE, + BT_ATT_LAST_ATTRIBUTE_HANDLE)); + __ASSERT_NO_MSG(IN_RANGE(svc_end_handle, BT_ATT_FIRST_ATTRIBUTE_HANDLE, + BT_ATT_LAST_ATTRIBUTE_HANDLE)); + + k_mutex_lock(&ctx->lock, K_FOREVER); + + api_err = bt_gatt_discover(conn, &ctx->params); + + if (!api_err) { + k_condvar_wait(&ctx->done, &ctx->lock, K_FOREVER); + } + + k_mutex_unlock(&ctx->lock); + + if (api_err) { + __ASSERT_NO_MSG(api_err < 0); + return api_err; + } + __ASSERT_NO_MSG(ctx->att_err >= 0); + return ctx->att_err; +} diff --git a/tests/bluetooth/common/testlib/src/att_write.c b/tests/bluetooth/common/testlib/src/att_write.c new file mode 100644 index 00000000000..8da01ea233a --- /dev/null +++ b/tests/bluetooth/common/testlib/src/att_write.c @@ -0,0 +1,74 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(bt_testlib_att_write, LOG_LEVEL_DBG); + +struct bt_testlib_att_write_closure { + uint8_t att_err; + struct bt_gatt_write_params params; + struct k_mutex lock; + struct k_condvar done; +}; + +static void att_write_cb(struct bt_conn *conn, uint8_t att_err, struct bt_gatt_write_params *params) +{ + struct bt_testlib_att_write_closure *ctx = + CONTAINER_OF(params, struct bt_testlib_att_write_closure, params); + + k_mutex_lock(&ctx->lock, K_FOREVER); + + ctx->att_err = att_err; + + k_condvar_signal(&ctx->done); + k_mutex_unlock(&ctx->lock); +} + +int bt_testlib_att_write(struct bt_conn *conn, enum bt_att_chan_opt bearer, uint16_t handle, + uint8_t *data, uint16_t size) +{ + int api_err; + struct bt_testlib_att_write_closure ctx_val = {.params = { + .handle = handle, + .offset = 0, + .func = att_write_cb, + .data = data, + .length = size, + }}; + struct bt_testlib_att_write_closure *const ctx = &ctx_val; + + k_mutex_init(&ctx->lock); + k_condvar_init(&ctx->done); + + __ASSERT_NO_MSG(conn); + __ASSERT_NO_MSG( + IN_RANGE(handle, BT_ATT_FIRST_ATTRIBUTE_HANDLE, BT_ATT_LAST_ATTRIBUTE_HANDLE)); + + k_mutex_lock(&ctx->lock, K_FOREVER); + + api_err = bt_gatt_write(conn, &ctx->params); + + if (!api_err) { + k_condvar_wait(&ctx->done, &ctx->lock, K_FOREVER); + } + + k_mutex_unlock(&ctx->lock); + + if (api_err) { + __ASSERT_NO_MSG(api_err < 0); + return api_err; + } + __ASSERT_NO_MSG(ctx->att_err >= 0); + return ctx->att_err; +} diff --git a/tests/bluetooth/common/testlib/src/conn_wait.c b/tests/bluetooth/common/testlib/src/conn_wait.c new file mode 100644 index 00000000000..a99b47a0edc --- /dev/null +++ b/tests/bluetooth/common/testlib/src/conn_wait.c @@ -0,0 +1,66 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(bt_testlib_conn_wait, LOG_LEVEL_DBG); + +static K_MUTEX_DEFINE(conn_wait_mutex); +static K_CONDVAR_DEFINE(something_changed); + +static void on_change(struct bt_conn *conn, uint8_t err) +{ + k_mutex_lock(&conn_wait_mutex, K_FOREVER); + k_condvar_broadcast(&something_changed); + k_mutex_unlock(&conn_wait_mutex); +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = on_change, + .disconnected = on_change, +}; + +static enum bt_conn_state bt_conn_state(struct bt_conn *conn) +{ + int err; + struct bt_conn_info info; + + __ASSERT(conn != NULL, "Invalid connection"); + err = bt_conn_get_info(conn, &info); + __ASSERT(err == 0, "Failed to get connection info"); + + return info.state; +} + +int bt_testlib_wait_connected(struct bt_conn *conn) +{ + __ASSERT_NO_MSG(conn != NULL); + k_mutex_lock(&conn_wait_mutex, K_FOREVER); + while (bt_conn_state(conn) != BT_CONN_STATE_CONNECTED) { + k_condvar_wait(&something_changed, &conn_wait_mutex, K_FOREVER); + } + k_mutex_unlock(&conn_wait_mutex); + return 0; +} + +int bt_testlib_wait_disconnected(struct bt_conn *conn) +{ + __ASSERT_NO_MSG(conn != NULL); + k_mutex_lock(&conn_wait_mutex, K_FOREVER); + while (bt_conn_state(conn) != BT_CONN_STATE_DISCONNECTED) { + k_condvar_wait(&something_changed, &conn_wait_mutex, K_FOREVER); + } + k_mutex_unlock(&conn_wait_mutex); + return 0; +} diff --git a/tests/bluetooth/common/testlib/src/connect.c b/tests/bluetooth/common/testlib/src/connect.c new file mode 100644 index 00000000000..afb4b9c271d --- /dev/null +++ b/tests/bluetooth/common/testlib/src/connect.c @@ -0,0 +1,85 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(bt_testlib_connect, LOG_LEVEL_INF); + +struct bt_testlib_connect_closure { + uint8_t conn_err; + struct bt_conn **conn; + struct k_mutex lock; + struct k_condvar done; +}; + +/* Context pool (with capacity of one). */ +static K_SEM_DEFINE(g_ctx_free, 1, 1); +static K_MUTEX_DEFINE(g_ctx_lock); +static struct bt_testlib_connect_closure *g_ctx; + +static void connected_cb(struct bt_conn *conn, uint8_t conn_err) +{ + /* Loop over each (allocated) item in pool. */ + + k_mutex_lock(&g_ctx_lock, K_FOREVER); + + if (g_ctx && conn == *g_ctx->conn) { + g_ctx->conn_err = conn_err; + k_condvar_signal(&g_ctx->done); + } + + k_mutex_unlock(&g_ctx_lock); +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected_cb, +}; + +int bt_testlib_connect(const bt_addr_le_t *peer, struct bt_conn **conn) +{ + int api_err; + struct bt_testlib_connect_closure ctx = { + .conn = conn, + }; + + __ASSERT_NO_MSG(conn); + __ASSERT_NO_MSG(*conn == NULL); + + k_condvar_init(&ctx.done); + + k_sem_take(&g_ctx_free, K_FOREVER); + k_mutex_lock(&g_ctx_lock, K_FOREVER); + g_ctx = &ctx; + + api_err = bt_conn_le_create(peer, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT, conn); + + if (!api_err) { + LOG_INF("Connecting.. conn %u", bt_conn_index(*conn)); + k_condvar_wait(&ctx.done, &g_ctx_lock, K_FOREVER); + LOG_INF("Connect complete"); + } + + g_ctx = NULL; + k_mutex_unlock(&g_ctx_lock); + k_sem_give(&g_ctx_free); + + if (api_err) { + LOG_ERR("bt_conn_le_create err %d", api_err); + __ASSERT_NO_MSG(api_err < 0); + return api_err; + } + + if (ctx.conn_err) { + LOG_ERR("Connect HCI err %d", ctx.conn_err); + __ASSERT_NO_MSG(ctx.conn_err >= 0); + return ctx.conn_err; + } + + return 0; +} diff --git a/tests/bluetooth/common/testlib/src/scan.c b/tests/bluetooth/common/testlib/src/scan.c new file mode 100644 index 00000000000..a06ce5d3bf7 --- /dev/null +++ b/tests/bluetooth/common/testlib/src/scan.c @@ -0,0 +1,98 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(bt_testlib_scan, LOG_LEVEL_INF); + +struct bt_scan_find_name_closure { + const char *wanted_name; + bt_addr_le_t *result; + struct k_condvar done; +}; + +/* Context pool (with capacity of one). */ +static K_SEM_DEFINE(g_ctx_free, 1, 1); +static K_MUTEX_DEFINE(g_ctx_lock); +static struct bt_scan_find_name_closure *g_ctx; + +static bool bt_scan_find_name_cb_data_cb(struct bt_data *data, void *user_data) +{ + const char **wanted = user_data; + + if (data->type == BT_DATA_NAME_COMPLETE) { + if (data->data_len == strlen(*wanted) && + !memcmp(*wanted, data->data, data->data_len)) { + *wanted = NULL; + /* Stop bt_data_parse. */ + return false; + } + } + + /* Continue with next ad data. */ + return true; +} + +static void bt_scan_find_name_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_type, + struct net_buf_simple *buf) +{ + const char *wanted; + + k_mutex_lock(&g_ctx_lock, K_FOREVER); + + __ASSERT_NO_MSG(g_ctx); + __ASSERT_NO_MSG(g_ctx->wanted_name); + + wanted = g_ctx->wanted_name; + + bt_data_parse(buf, bt_scan_find_name_cb_data_cb, &wanted); + + if (!wanted) { + (void)bt_le_scan_stop(); + *g_ctx->result = *addr; + k_condvar_signal(&g_ctx->done); + } + + k_mutex_unlock(&g_ctx_lock); +} + +int bt_testlib_scan_find_name(bt_addr_le_t *result, const char *name) +{ + int api_err; + struct bt_scan_find_name_closure ctx = { + .wanted_name = name, + .result = result, + }; + + k_condvar_init(&ctx.done); + + k_sem_take(&g_ctx_free, K_FOREVER); + k_mutex_lock(&g_ctx_lock, K_FOREVER); + g_ctx = &ctx; + + api_err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, bt_scan_find_name_cb); + if (!api_err) { + k_condvar_wait(&ctx.done, &g_ctx_lock, K_FOREVER); + } + + g_ctx = NULL; + k_mutex_unlock(&g_ctx_lock); + k_sem_give(&g_ctx_free); + + if (!api_err) { + char str[BT_ADDR_LE_STR_LEN]; + (void)bt_addr_le_to_str(result, str, ARRAY_SIZE(str)); + LOG_INF("Scan match: %s", str); + } else { + LOG_ERR("Scan error: %d", api_err); + } + + return api_err; +} diff --git a/tests/bluetooth/common/testlib/src/security.c b/tests/bluetooth/common/testlib/src/security.c new file mode 100644 index 00000000000..a229cf5487c --- /dev/null +++ b/tests/bluetooth/common/testlib/src/security.c @@ -0,0 +1,108 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(bt_testlib_security, LOG_LEVEL_INF); + +struct testlib_security_ctx { + enum bt_security_err result; + struct bt_conn *conn; + bt_security_t new_minimum; + struct k_condvar done; +}; + +/* Context pool (with capacity of one). */ +static K_SEM_DEFINE(g_ctx_free, 1, 1); +static K_MUTEX_DEFINE(g_ctx_lock); +static struct testlib_security_ctx *g_ctx; + +static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) +{ + LOG_INF("conn %u level %d err %d", bt_conn_index(conn), level, err); + + /* Mutex operations establish a happens-before relationship. This + * ensures variables have the expected values despite non-atomic + * accesses. + */ + k_mutex_lock(&g_ctx_lock, K_FOREVER); + + if (g_ctx && (g_ctx->conn == conn)) { + g_ctx->result = err; + /* Assumption: A security error means there will be further + * security changes for this connection. + */ + if (err || level >= g_ctx->new_minimum) { + k_condvar_signal(&g_ctx->done); + } + } + + k_mutex_unlock(&g_ctx_lock); +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .security_changed = security_changed, +}; + +int bt_testlib_secure(struct bt_conn *conn, bt_security_t new_minimum) +{ + int api_err = 0; + struct testlib_security_ctx ctx = { + .conn = conn, + .new_minimum = new_minimum, + }; + + k_condvar_init(&ctx.done); + + /* The semaphore allocates `g_ctx` to this invocation of + * `bt_testlib_secure`, in case this function is called from multiple + * threads in parallel. + */ + k_sem_take(&g_ctx_free, K_FOREVER); + /* The mutex synchronizes this function with `security_changed()`. */ + k_mutex_lock(&g_ctx_lock, K_FOREVER); + + /* Do the thing. */ + api_err = bt_conn_set_security(conn, new_minimum); + + /* Holding the mutex will pause any thread entering + * `security_changed_cb`, delaying it until `k_condvar_wait`. This + * ensures that the condition variable is signaled while this thread is + * in `k_condvar_wait`, even if the event happens before, e.g. between + * `bt_conn_get_security` and `k_condvar_wait`. + * + * If the security level is already satisfied, there is no point in + * waiting, and it would deadlock if security was already satisfied + * before the mutex was taken, `bt_conn_set_security` will result in no + * operation. + */ + if (!api_err && bt_conn_get_security(conn) < new_minimum) { + /* Waiting on a condvar releases the mutex and waits for a + * signal on the condvar, atomically, without a gap between the + * release and wait. The mutex is locked again before returning. + */ + g_ctx = &ctx; + k_condvar_wait(&ctx.done, &g_ctx_lock, K_FOREVER); + g_ctx = NULL; + } + + k_mutex_unlock(&g_ctx_lock); + k_sem_give(&g_ctx_free); + + if (api_err) { + __ASSERT_NO_MSG(api_err < 0); + return api_err; + } + + __ASSERT_NO_MSG(ctx.result >= 0); + return ctx.result; +} diff --git a/tests/bluetooth/controller/common/src/helper_pdu.c b/tests/bluetooth/controller/common/src/helper_pdu.c index d952ccfb7ff..fe2af51bd67 100644 --- a/tests/bluetooth/controller/common/src/helper_pdu.c +++ b/tests/bluetooth/controller/common/src/helper_pdu.c @@ -5,8 +5,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "zephyr/types.h" -#include "zephyr/ztest.h" +#include +#include #include #include @@ -1213,8 +1213,8 @@ void helper_pdu_verify_cis_ind(const char *file, uint32_t line, struct pdu_data zassert_mem_equal(pdu->llctrl.cis_ind.cis_sync_delay, p->cis_sync_delay, sizeof(p->cis_sync_delay), "cis_sync_delay mismatch.\nCalled at %s:%d\n", file, line); - - pdu->llctrl.cis_ind.conn_event_count = p->conn_event_count; + zassert_equal(pdu->llctrl.cis_ind.conn_event_count, p->conn_event_count, + "conn_event_count mismatch.\nCalled at %s:%d\n", file, line); } void helper_pdu_verify_cis_terminate_ind(const char *file, uint32_t line, struct pdu_data *pdu, diff --git a/tests/bluetooth/controller/common/src/helper_util.c b/tests/bluetooth/controller/common/src/helper_util.c index 0356fdc1846..d89126c7857 100644 --- a/tests/bluetooth/controller/common/src/helper_util.c +++ b/tests/bluetooth/controller/common/src/helper_util.c @@ -5,8 +5,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "zephyr/types.h" -#include "zephyr/ztest.h" +#include +#include #include #include diff --git a/tests/bluetooth/controller/ctrl_api/prj.conf b/tests/bluetooth/controller/ctrl_api/prj.conf index ff1da608b4e..7718b673947 100644 --- a/tests/bluetooth/controller/ctrl_api/prj.conf +++ b/tests/bluetooth/controller/ctrl_api/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_chmu/prj.conf b/tests/bluetooth/controller/ctrl_chmu/prj.conf index ff1da608b4e..7718b673947 100644 --- a/tests/bluetooth/controller/ctrl_chmu/prj.conf +++ b/tests/bluetooth/controller/ctrl_chmu/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_cis_create/prj.conf b/tests/bluetooth/controller/ctrl_cis_create/prj.conf index 095af7f8082..7b2d389656b 100644 --- a/tests/bluetooth/controller/ctrl_cis_create/prj.conf +++ b/tests/bluetooth/controller/ctrl_cis_create/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_cis_create/src/main.c b/tests/bluetooth/controller/ctrl_cis_create/src/main.c index 853eaa0e570..54a8d742208 100644 --- a/tests/bluetooth/controller/ctrl_cis_create/src/main.c +++ b/tests/bluetooth/controller/ctrl_cis_create/src/main.c @@ -39,6 +39,7 @@ DEFINE_FFF_GLOBALS; #include "ull_iso_types.h" #include "ull_conn_types.h" #include "ull_conn_iso_types.h" +#include "ull_conn_iso_internal.h" #include "ull_llcp.h" #include "ull_conn_internal.h" #include "ull_llcp_internal.h" @@ -48,6 +49,9 @@ DEFINE_FFF_GLOBALS; static struct ll_conn conn; +static struct ll_conn_iso_group cig_mock = { 0 }; +static struct ll_conn_iso_stream cis_mock = { .established = 1, .group = &cig_mock }; + /* struct ll_conn_iso_stream *ll_conn_iso_stream_get(uint16_t handle); */ FAKE_VALUE_FUNC(struct ll_conn_iso_stream *, ll_conn_iso_stream_get, uint16_t); @@ -63,15 +67,16 @@ static bool is_instant_reached(struct ll_conn *conn, uint16_t instant) return ((event_counter(conn) - instant) & 0xFFFF) <= 0x7FFF; } +#define MAX_xDU 160 static struct pdu_data_llctrl_cis_req remote_cis_req = { .cig_id = 0x01, .cis_id = 0x02, .c_phy = 0x01, .p_phy = 0x01, - .c_max_sdu_packed = { 0, 160}, - .p_max_sdu = { 0, 160}, - .c_max_pdu = 160, - .p_max_pdu = 160, + .c_max_sdu_packed = { MAX_xDU, 0 }, + .p_max_sdu = { MAX_xDU, 0 }, + .c_max_pdu = MAX_xDU, + .p_max_pdu = MAX_xDU, .nse = 2, .p_bn = 1, .c_bn = 1, @@ -94,6 +99,37 @@ static struct pdu_data_llctrl_cis_ind remote_cis_ind = { .conn_event_count = 12 }; +static struct pdu_data_llctrl_cis_req local_cis_req = { + .cig_id = 0x00, + .cis_id = 0x02, + .c_phy = 0x01, + .p_phy = 0x01, + .c_max_sdu_packed = { MAX_xDU, 0 }, + .p_max_sdu = { MAX_xDU, 0 }, + .c_max_pdu = MAX_xDU, + .p_max_pdu = MAX_xDU, + .nse = 2, + .p_bn = 1, + .c_bn = 1, + .c_ft = 1, + .p_ft = 1, + .iso_interval = 6, + .conn_event_count = 0, + .c_sdu_interval = { 0, 0, 0}, + .p_sdu_interval = { 0, 0, 0}, + .sub_interval = { 0, 0, 0}, + .cis_offset_min = { 0, 0, 0}, + .cis_offset_max = { 0, 0, 0} +}; + +static struct pdu_data_llctrl_cis_ind local_cis_ind = { + .aa = { 0, 0, 0, 0}, + .cig_sync_delay = { 0, 0, 0}, + .cis_offset = { 0, 0, 0}, + .cis_sync_delay = { 0, 0, 0}, + .conn_event_count = 13 +}; + #define ERROR_CODE 0x17 /* * Central-initiated CIS Create procedure. @@ -141,10 +177,9 @@ ZTEST(cis_create, test_cc_create_periph_rem_host_accept) .cis_handle = 0x00, .status = 0x00 }; - struct ll_conn_iso_stream cis = { 0 }; /* Prepare mocked call to ll_conn_iso_stream_get() */ - ll_conn_iso_stream_get_fake.return_val = &cis; + ll_conn_iso_stream_get_fake.return_val = &cis_mock; /* Role */ test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL); @@ -237,7 +272,7 @@ ZTEST(cis_create, test_cc_create_periph_rem_host_accept) event_done(&conn); /* NODE_CIS_ESTABLISHED carry extra information in header rx footer param field */ - zassert_equal_ptr(ntf->hdr.rx_ftr.param, &cis); + zassert_equal_ptr(ntf->hdr.rx_ftr.param, &cis_mock); zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(), "Free CTX buffers %d", llcp_ctx_buffers_free()); @@ -438,10 +473,10 @@ ZTEST(cis_create, test_cc_create_periph_rem_invalid_phy) .cis_id = 0x02, .c_phy = 0x03, .p_phy = 0x01, - .c_max_sdu_packed = { 0, 160}, - .p_max_sdu = { 0, 160}, - .c_max_pdu = 160, - .p_max_pdu = 160, + .c_max_sdu_packed = { MAX_xDU, 0 }, + .p_max_sdu = { MAX_xDU, 0 }, + .c_max_pdu = MAX_xDU, + .p_max_pdu = MAX_xDU, .nse = 2, .p_bn = 1, .c_bn = 1, @@ -490,4 +525,339 @@ ZTEST(cis_create, test_cc_create_periph_rem_invalid_phy) "Free CTX buffers %d", llcp_ctx_buffers_free()); } +/* + * Central-initiated CIS Create procedure. + * Host requests CIS, LL replies with 'remote feature unsupported' + * + * +-----+ +-------+ +-----+ + * | UT | | LL_C | | LT | + * +-----+ +-------+ +-----+ + * | | | + * | LE CIS Create | | + * |-------------------------->| | + * | | | + * | | (FEAT unsupported) | + * | | | + * | | | + * | LE CIS ESTABLISHED | | + * | (rem feat unsupported) | | + * |<--------------------------| | + */ +ZTEST(cis_create, test_cc_create_central_rem_unsupported) +{ + struct ll_conn_iso_stream *cis; + struct node_rx_pdu *ntf; + uint8_t err; + + struct node_rx_conn_iso_estab cis_estab = { + .cis_handle = 0x00, + .status = BT_HCI_ERR_UNSUPP_REMOTE_FEATURE + }; + + /* Prepare mocked call to ll_conn_iso_stream_get() */ + ll_conn_iso_stream_get_fake.return_val = &cis_mock; + + /* Role */ + test_set_role(&conn, BT_HCI_ROLE_CENTRAL); + + /* Connect */ + ull_cp_state_set(&conn, ULL_CP_CONNECTED); + conn.llcp.fex.valid = 1; + + cis = ll_conn_iso_stream_get(LL_CIS_HANDLE_BASE); + cis->lll.acl_handle = conn.lll.handle; + + err = ull_cp_cis_create(&conn, cis); + zassert_equal(err, BT_HCI_ERR_SUCCESS); + + /* Prepare */ + event_prepare(&conn); + + /* Done */ + event_done(&conn); + + /* Prepare */ + event_prepare(&conn); + + /* There should be excactly one host notification + * with status BT_HCI_ERR_UNSUPP_REMOTE_FEATURE + */ + ut_rx_node(NODE_CIS_ESTABLISHED, &ntf, &cis_estab); + ut_rx_q_is_empty(); + + /* Done */ + event_done(&conn); + + zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(), + "Free CTX buffers %d", llcp_ctx_buffers_free()); +} + +/* + * Central-initiated CIS Create procedure. + * Central requests CIS, peripheral accepts + * + * +-----+ +-------+ +-----+ + * | UT | | LL_C | | LT | + * +-----+ +-------+ +-----+ + * | | | + * | LE CIS Create | | + * |-------------------------->| | + * | | LL_CIS_REQ | + * | |-------------------------->| + * | | | + * | | LL_CIS_RSP | + * | |<--------------------------| + * | | | + * | | | + * | | LL_CIS_IND | + * | |-------------------------->| + * | | | + * | | | + * | | | + * | | | + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * | | | + * | LE CIS ESTABLISHED | | + * |<--------------------------| | + */ +ZTEST(cis_create, test_cc_create_central_rem_accept) +{ + struct pdu_data_llctrl_cis_rsp remote_cis_rsp = { + .cis_offset_max = { 0, 0, 0}, + .cis_offset_min = { 0, 0, 0}, + .conn_event_count = 13 + }; + struct node_rx_conn_iso_estab cis_estab = { + .cis_handle = 0x00, + .status = BT_HCI_ERR_SUCCESS + }; + struct ll_conn_iso_stream *cis; + struct node_rx_pdu *ntf; + struct node_tx *tx; + uint8_t err; + + /* Prepare mocked call to ll_conn_iso_stream_get() */ + ll_conn_iso_stream_get_fake.return_val = &cis_mock; + + /* Role */ + test_set_role(&conn, BT_HCI_ROLE_CENTRAL); + + /* Connect */ + ull_cp_state_set(&conn, ULL_CP_CONNECTED); + conn.llcp.fex.valid = 1; + conn.llcp.fex.features_peer |= BIT64(BT_LE_FEAT_BIT_CIS_PERIPHERAL); + + /* Setup default CIS/CIG parameters */ + cis = ll_conn_iso_stream_get(LL_CIS_HANDLE_BASE); + cis->lll.acl_handle = conn.lll.handle; + cis->group->cig_id = local_cis_req.cig_id; + cis->cis_id = local_cis_req.cis_id; + cis->lll.tx.phy = local_cis_req.c_phy; + cis->lll.rx.phy = local_cis_req.p_phy; + cis->group->c_sdu_interval = 0; + cis->group->p_sdu_interval = 0; + cis->lll.tx.max_pdu = MAX_xDU; + cis->lll.rx.max_pdu = MAX_xDU; + cis->c_max_sdu = MAX_xDU; + cis->p_max_sdu = MAX_xDU; + cis->group->iso_interval = local_cis_req.iso_interval; + cis->framed = 0; + cis->lll.nse = local_cis_req.nse; + cis->lll.sub_interval = 0; + cis->lll.tx.bn = local_cis_req.c_bn; + cis->lll.rx.bn = local_cis_req.p_bn; + cis->lll.tx.ft = local_cis_req.c_ft; + cis->lll.rx.ft = local_cis_req.p_ft; + + err = ull_cp_cis_create(&conn, cis); + zassert_equal(err, BT_HCI_ERR_SUCCESS); + + /* Prepare */ + event_prepare(&conn); + + /* Tx Queue should have one LL Control PDU */ + lt_rx(LL_CIS_REQ, &conn, &tx, &local_cis_req); + lt_rx_q_is_empty(&conn); + + /* Done */ + event_done(&conn); + + /* Prepare */ + event_prepare(&conn); + + /* Rx */ + lt_tx(LL_CIS_RSP, &conn, &remote_cis_rsp); + + /* Done */ + event_done(&conn); + + /* Prepare */ + event_prepare(&conn); + + /* Tx Queue should have one LL Control PDU */ + lt_rx(LL_CIS_IND, &conn, &tx, &local_cis_ind); + lt_rx_q_is_empty(&conn); + + /* Done */ + event_done(&conn); + + /* */ + while (!is_instant_reached(&conn, remote_cis_rsp.conn_event_count)) { + /* Prepare */ + event_prepare(&conn); + + /* Tx Queue should NOT have a LL Control PDU */ + lt_rx_q_is_empty(&conn); + + /* Done */ + event_done(&conn); + + /* There should NOT be a host notification */ + ut_rx_q_is_empty(); + } + + /* Prepare */ + event_prepare(&conn); + + /* Done */ + event_done(&conn); + + /* Emulate CIS becoming established */ + ull_cp_cc_established(&conn, 0); + + /* Prepare */ + event_prepare(&conn); + + /* Tx Queue should NOT have a LL Control PDU */ + lt_rx_q_is_empty(&conn); + + /* Done */ + event_done(&conn); + + /* Prepare */ + event_prepare(&conn); + + /* There should be excactly one host notification */ + ut_rx_node(NODE_CIS_ESTABLISHED, &ntf, &cis_estab); + ut_rx_q_is_empty(); + + /* Done */ + event_done(&conn); + + zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(), + "Free CTX buffers %d", llcp_ctx_buffers_free()); +} + +/* + * Central-initiated CIS Create procedure. + * Central requests CIS, peripheral rejects with 'unsupported remote feature' + * + * +-----+ +-------+ +-----+ + * | UT | | LL_C | | LT | + * +-----+ +-------+ +-----+ + * | | | + * | LE CIS Create | | + * |-------------------------->| | + * | | LL_CIS_REQ | + * | |-------------------------->| + * | | | + * | | LL_REJECT_EXT_IND | + * | | (unsupported remote feat) | + * | |<--------------------------| + * | | | + * | | | + * | | | + * | | | + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * | | | + * | LE CIS ESTABLISHED | | + * |<--------------------------| | + */ +ZTEST(cis_create, test_cc_create_central_rem_reject) +{ + struct node_rx_conn_iso_estab cis_estab = { + .cis_handle = 0x00, + .status = BT_HCI_ERR_UNSUPP_REMOTE_FEATURE + }; + struct pdu_data_llctrl_reject_ext_ind remote_reject = { + .error_code = BT_HCI_ERR_UNSUPP_REMOTE_FEATURE, + .reject_opcode = PDU_DATA_LLCTRL_TYPE_CIS_REQ + }; + struct ll_conn_iso_stream *cis; + struct node_rx_pdu *ntf; + struct node_tx *tx; + uint8_t err; + + /* Prepare mocked call to ll_conn_iso_stream_get() */ + ll_conn_iso_stream_get_fake.return_val = &cis_mock; + + /* Role */ + test_set_role(&conn, BT_HCI_ROLE_CENTRAL); + + /* Connect */ + ull_cp_state_set(&conn, ULL_CP_CONNECTED); + conn.llcp.fex.valid = 1; + conn.llcp.fex.features_peer |= BIT64(BT_LE_FEAT_BIT_CIS_PERIPHERAL); + + /* Setup default CIS/CIG parameters */ + cis = ll_conn_iso_stream_get(LL_CIS_HANDLE_BASE); + cis->lll.acl_handle = conn.lll.handle; + cis->group->cig_id = local_cis_req.cig_id; + cis->cis_id = local_cis_req.cis_id; + cis->lll.tx.phy = local_cis_req.c_phy; + cis->lll.rx.phy = local_cis_req.p_phy; + cis->group->c_sdu_interval = 0; + cis->group->p_sdu_interval = 0; + cis->lll.tx.max_pdu = MAX_xDU; + cis->lll.rx.max_pdu = MAX_xDU; + cis->c_max_sdu = MAX_xDU; + cis->p_max_sdu = MAX_xDU; + cis->group->iso_interval = local_cis_req.iso_interval; + cis->framed = 0; + cis->lll.nse = local_cis_req.nse; + cis->lll.sub_interval = 0; + cis->lll.tx.bn = local_cis_req.c_bn; + cis->lll.rx.bn = local_cis_req.p_bn; + cis->lll.tx.ft = local_cis_req.c_ft; + cis->lll.rx.ft = local_cis_req.p_ft; + + err = ull_cp_cis_create(&conn, cis); + zassert_equal(err, BT_HCI_ERR_SUCCESS); + + /* Prepare */ + event_prepare(&conn); + + /* Tx Queue should have one LL Control PDU */ + lt_rx(LL_CIS_REQ, &conn, &tx, &local_cis_req); + lt_rx_q_is_empty(&conn); + + /* Done */ + event_done(&conn); + + /* Prepare */ + event_prepare(&conn); + + /* Rx */ + lt_tx(LL_REJECT_EXT_IND, &conn, &remote_reject); + + /* Done */ + event_done(&conn); + + /* Prepare */ + event_prepare(&conn); + + /* There should be excactly one host notification */ + ut_rx_node(NODE_CIS_ESTABLISHED, &ntf, &cis_estab); + ut_rx_q_is_empty(); + + zassert_equal(conn.llcp.fex.features_peer & BIT64(BT_LE_FEAT_BIT_CIS_PERIPHERAL), 0); + + /* Done */ + event_done(&conn); + + zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(), + "Free CTX buffers %d", llcp_ctx_buffers_free()); +} + + ZTEST_SUITE(cis_create, NULL, NULL, cis_create_setup, NULL, NULL); diff --git a/tests/bluetooth/controller/ctrl_cis_terminate/prj.conf b/tests/bluetooth/controller/ctrl_cis_terminate/prj.conf index 095af7f8082..7b2d389656b 100644 --- a/tests/bluetooth/controller/ctrl_cis_terminate/prj.conf +++ b/tests/bluetooth/controller/ctrl_cis_terminate/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_collision/prj.conf b/tests/bluetooth/controller/ctrl_collision/prj.conf index ff1da608b4e..7718b673947 100644 --- a/tests/bluetooth/controller/ctrl_collision/prj.conf +++ b/tests/bluetooth/controller/ctrl_collision/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_conn_update/prj.conf b/tests/bluetooth/controller/ctrl_conn_update/prj.conf index c1f2003a02e..6026d874f22 100644 --- a/tests/bluetooth/controller/ctrl_conn_update/prj.conf +++ b/tests/bluetooth/controller/ctrl_conn_update/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_conn_update/prj_apm.conf b/tests/bluetooth/controller/ctrl_conn_update/prj_apm.conf index 6fdf6b43600..5827974497f 100644 --- a/tests/bluetooth/controller/ctrl_conn_update/prj_apm.conf +++ b/tests/bluetooth/controller/ctrl_conn_update/prj_apm.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_conn_update/prj_no_param_req.conf b/tests/bluetooth/controller/ctrl_conn_update/prj_no_param_req.conf index 661adea35c0..7c90aa769a1 100644 --- a/tests/bluetooth/controller/ctrl_conn_update/prj_no_param_req.conf +++ b/tests/bluetooth/controller/ctrl_conn_update/prj_no_param_req.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_cte_req/prj.conf b/tests/bluetooth/controller/ctrl_cte_req/prj.conf index aacab6b2903..8941e79bc4f 100644 --- a/tests/bluetooth/controller/ctrl_cte_req/prj.conf +++ b/tests/bluetooth/controller/ctrl_cte_req/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_data_length_update/prj.conf b/tests/bluetooth/controller/ctrl_data_length_update/prj.conf index 23f11745d4c..09d9cd9bab9 100644 --- a/tests/bluetooth/controller/ctrl_data_length_update/prj.conf +++ b/tests/bluetooth/controller/ctrl_data_length_update/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_data_length_update/prj_nocoded.conf b/tests/bluetooth/controller/ctrl_data_length_update/prj_nocoded.conf index 0eea80b585c..dcfc2eded1d 100644 --- a/tests/bluetooth/controller/ctrl_data_length_update/prj_nocoded.conf +++ b/tests/bluetooth/controller/ctrl_data_length_update/prj_nocoded.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_data_length_update/prj_nophy.conf b/tests/bluetooth/controller/ctrl_data_length_update/prj_nophy.conf index f1bf04d0f4a..115ad42a41a 100644 --- a/tests/bluetooth/controller/ctrl_data_length_update/prj_nophy.conf +++ b/tests/bluetooth/controller/ctrl_data_length_update/prj_nophy.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_encrypt/prj.conf b/tests/bluetooth/controller/ctrl_encrypt/prj.conf index 23f11745d4c..09d9cd9bab9 100644 --- a/tests/bluetooth/controller/ctrl_encrypt/prj.conf +++ b/tests/bluetooth/controller/ctrl_encrypt/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_feature_exchange/prj.conf b/tests/bluetooth/controller/ctrl_feature_exchange/prj.conf index ff1da608b4e..7718b673947 100644 --- a/tests/bluetooth/controller/ctrl_feature_exchange/prj.conf +++ b/tests/bluetooth/controller/ctrl_feature_exchange/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_hci/prj.conf b/tests/bluetooth/controller/ctrl_hci/prj.conf index 80b2156e0fa..5f5a1abb057 100644 --- a/tests/bluetooth/controller/ctrl_hci/prj.conf +++ b/tests/bluetooth/controller/ctrl_hci/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_invalid/prj.conf b/tests/bluetooth/controller/ctrl_invalid/prj.conf index 23f11745d4c..09d9cd9bab9 100644 --- a/tests/bluetooth/controller/ctrl_invalid/prj.conf +++ b/tests/bluetooth/controller/ctrl_invalid/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_le_ping/prj.conf b/tests/bluetooth/controller/ctrl_le_ping/prj.conf index 23f11745d4c..09d9cd9bab9 100644 --- a/tests/bluetooth/controller/ctrl_le_ping/prj.conf +++ b/tests/bluetooth/controller/ctrl_le_ping/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_min_used_chans/prj.conf b/tests/bluetooth/controller/ctrl_min_used_chans/prj.conf index 23f11745d4c..09d9cd9bab9 100644 --- a/tests/bluetooth/controller/ctrl_min_used_chans/prj.conf +++ b/tests/bluetooth/controller/ctrl_min_used_chans/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_phy_update/prj.conf b/tests/bluetooth/controller/ctrl_phy_update/prj.conf index 23f11745d4c..09d9cd9bab9 100644 --- a/tests/bluetooth/controller/ctrl_phy_update/prj.conf +++ b/tests/bluetooth/controller/ctrl_phy_update/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_phy_update/prj_rx_cnt.conf b/tests/bluetooth/controller/ctrl_phy_update/prj_rx_cnt.conf index e35492c67ff..20d9e982e95 100644 --- a/tests/bluetooth/controller/ctrl_phy_update/prj_rx_cnt.conf +++ b/tests/bluetooth/controller/ctrl_phy_update/prj_rx_cnt.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_sca_update/prj.conf b/tests/bluetooth/controller/ctrl_sca_update/prj.conf index 23f11745d4c..09d9cd9bab9 100644 --- a/tests/bluetooth/controller/ctrl_sca_update/prj.conf +++ b/tests/bluetooth/controller/ctrl_sca_update/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_terminate/prj.conf b/tests/bluetooth/controller/ctrl_terminate/prj.conf index 23f11745d4c..09d9cd9bab9 100644 --- a/tests/bluetooth/controller/ctrl_terminate/prj.conf +++ b/tests/bluetooth/controller/ctrl_terminate/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj.conf b/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj.conf index 4076b0b23c1..e3a1f8d893b 100644 --- a/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj.conf +++ b/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj_1.conf b/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj_1.conf index 12186f6b20b..de0e26455ee 100644 --- a/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj_1.conf +++ b/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj_1.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj_2.conf b/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj_2.conf index 5e350b3767f..46650448d02 100644 --- a/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj_2.conf +++ b/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj_2.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj_3.conf b/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj_3.conf index c3dd3905e17..b829cf265e4 100644 --- a/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj_3.conf +++ b/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj_3.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj_max.conf b/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj_max.conf index b504bee37e7..c01ee28211d 100644 --- a/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj_max.conf +++ b/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj_max.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj_max_common.conf b/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj_max_common.conf index 444758372dc..7b83d2d6a12 100644 --- a/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj_max_common.conf +++ b/tests/bluetooth/controller/ctrl_tx_buffer_alloc/prj_max_common.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_tx_queue/prj.conf b/tests/bluetooth/controller/ctrl_tx_queue/prj.conf index 23f11745d4c..09d9cd9bab9 100644 --- a/tests/bluetooth/controller/ctrl_tx_queue/prj.conf +++ b/tests/bluetooth/controller/ctrl_tx_queue/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_unsupported/prj.conf b/tests/bluetooth/controller/ctrl_unsupported/prj.conf index 23f11745d4c..09d9cd9bab9 100644 --- a/tests/bluetooth/controller/ctrl_unsupported/prj.conf +++ b/tests/bluetooth/controller/ctrl_unsupported/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_unsupported/prj_unsupported.conf b/tests/bluetooth/controller/ctrl_unsupported/prj_unsupported.conf index b763fb00f5d..f01e17406ee 100644 --- a/tests/bluetooth/controller/ctrl_unsupported/prj_unsupported.conf +++ b/tests/bluetooth/controller/ctrl_unsupported/prj_unsupported.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/ctrl_version/prj.conf b/tests/bluetooth/controller/ctrl_version/prj.conf index 23f11745d4c..09d9cd9bab9 100644 --- a/tests/bluetooth/controller/ctrl_version/prj.conf +++ b/tests/bluetooth/controller/ctrl_version/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/controller/mock_ctrl/src/ull_central.c b/tests/bluetooth/controller/mock_ctrl/src/ull_central.c index 763a09006eb..ab067dcbb9d 100644 --- a/tests/bluetooth/controller/mock_ctrl/src/ull_central.c +++ b/tests/bluetooth/controller/mock_ctrl/src/ull_central.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "zephyr/types.h" +#include #include #include "util/util.h" #include "util/mem.h" @@ -42,7 +42,7 @@ int ull_central_reset(void) } uint16_t ull_central_iso_cis_offset_get(uint16_t cis_handle, uint32_t *cis_offset_min, - uint32_t *cis_offset_max) + uint32_t *cis_offset_max, uint16_t *conn_event_count) { return 0; } diff --git a/tests/bluetooth/controller/mock_ctrl/src/ull_conn_iso.c b/tests/bluetooth/controller/mock_ctrl/src/ull_conn_iso.c index 031d856e67e..36e457ee284 100644 --- a/tests/bluetooth/controller/mock_ctrl/src/ull_conn_iso.c +++ b/tests/bluetooth/controller/mock_ctrl/src/ull_conn_iso.c @@ -42,7 +42,7 @@ #include "hal/debug.h" static struct ll_conn_iso_group cig = { 0 }; -static struct ll_conn_iso_stream cis = { 0 }; +static struct ll_conn_iso_stream cis = { .established = 1, .group = &cig }; __weak struct ll_conn_iso_stream *ll_conn_iso_stream_get_by_acl(struct ll_conn *conn, uint16_t *cis_iter) diff --git a/tests/bluetooth/controller/mock_ctrl/src/ull_peripheral.c b/tests/bluetooth/controller/mock_ctrl/src/ull_peripheral.c index 52aa930c8fd..fb7a6f8f1c5 100644 --- a/tests/bluetooth/controller/mock_ctrl/src/ull_peripheral.c +++ b/tests/bluetooth/controller/mock_ctrl/src/ull_peripheral.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "zephyr/types.h" +#include #include #include "util/util.h" #include "util/mem.h" diff --git a/tests/bluetooth/ctrl_isoal/prj.conf b/tests/bluetooth/ctrl_isoal/prj.conf index 2f429dd8c47..18fd120fcbe 100644 --- a/tests/bluetooth/ctrl_isoal/prj.conf +++ b/tests/bluetooth/ctrl_isoal/prj.conf @@ -1,6 +1,5 @@ CONFIG_NET_BUF=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_ASSERT_VERBOSE=3 CONFIG_ZTEST_STACK_SIZE=4096 CONFIG_ZTEST_ASSERT_HOOK=y diff --git a/tests/bluetooth/ctrl_sw_privacy/prj.conf b/tests/bluetooth/ctrl_sw_privacy/prj.conf index 89c8424a243..7324043fdbd 100644 --- a/tests/bluetooth/ctrl_sw_privacy/prj.conf +++ b/tests/bluetooth/ctrl_sw_privacy/prj.conf @@ -4,6 +4,5 @@ CONFIG_BT_LL_SW_SPLIT=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT_PRIVACY=y CONFIG_BT_CTLR_SW_DEFERRED_PRIVACY=y diff --git a/tests/bluetooth/ctrl_sw_privacy_unit/prj.conf b/tests/bluetooth/ctrl_sw_privacy_unit/prj.conf index 44906f1edc0..3cc871bc394 100644 --- a/tests/bluetooth/ctrl_sw_privacy_unit/prj.conf +++ b/tests/bluetooth/ctrl_sw_privacy_unit/prj.conf @@ -2,5 +2,4 @@ CONFIG_NET_BUF=y CONFIG_ZTEST=y CONFIG_ZTEST_ASSERT_VERBOSE=3 CONFIG_ZTEST_STACK_SIZE=4096 -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_PARAMETER_COUNT=32 diff --git a/tests/bluetooth/ctrl_user_ext/prj.conf b/tests/bluetooth/ctrl_user_ext/prj.conf index 368094d9b8f..d254da34fba 100644 --- a/tests/bluetooth/ctrl_user_ext/prj.conf +++ b/tests/bluetooth/ctrl_user_ext/prj.conf @@ -4,7 +4,6 @@ CONFIG_BT_LL_SW_SPLIT=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT_CTLR_ADVANCED_FEATURES=y CONFIG_BT_CTLR_USER_EXT=y CONFIG_BT_CTLR_USER_EVT_RANGE=10 diff --git a/tests/bluetooth/df/connection_cte_req/prj.conf b/tests/bluetooth/df/connection_cte_req/prj.conf index 9796e6a3763..77d3260135d 100644 --- a/tests/bluetooth/df/connection_cte_req/prj.conf +++ b/tests/bluetooth/df/connection_cte_req/prj.conf @@ -1,6 +1,5 @@ CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y diff --git a/tests/bluetooth/df/connection_cte_tx_params/prj.conf b/tests/bluetooth/df/connection_cte_tx_params/prj.conf index 9284e101e44..162d6ba6b77 100644 --- a/tests/bluetooth/df/connection_cte_tx_params/prj.conf +++ b/tests/bluetooth/df/connection_cte_tx_params/prj.conf @@ -1,6 +1,5 @@ CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y # It does not matter for the test whether central or peripheral is used. diff --git a/tests/bluetooth/df/connectionless_cte_chains/prj.conf b/tests/bluetooth/df/connectionless_cte_chains/prj.conf index d0b26e94e0e..45e5534c44d 100644 --- a/tests/bluetooth/df/connectionless_cte_chains/prj.conf +++ b/tests/bluetooth/df/connectionless_cte_chains/prj.conf @@ -1,6 +1,5 @@ CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_EXT_ADV=y diff --git a/tests/bluetooth/df/connectionless_cte_rx/prj.conf b/tests/bluetooth/df/connectionless_cte_rx/prj.conf index f7f7068e7d6..4d2cb06c548 100644 --- a/tests/bluetooth/df/connectionless_cte_rx/prj.conf +++ b/tests/bluetooth/df/connectionless_cte_rx/prj.conf @@ -1,6 +1,5 @@ CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_EXT_ADV=y diff --git a/tests/bluetooth/df/connectionless_cte_tx/prj.conf b/tests/bluetooth/df/connectionless_cte_tx/prj.conf index d229af80f19..6f215ed07fb 100644 --- a/tests/bluetooth/df/connectionless_cte_tx/prj.conf +++ b/tests/bluetooth/df/connectionless_cte_tx/prj.conf @@ -1,6 +1,5 @@ CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_EXT_ADV=y diff --git a/tests/bluetooth/gatt/prj.conf b/tests/bluetooth/gatt/prj.conf index 796b840d681..c59f96a921e 100644 --- a/tests/bluetooth/gatt/prj.conf +++ b/tests/bluetooth/gatt/prj.conf @@ -1,6 +1,5 @@ CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CTLR=n diff --git a/tests/bluetooth/hci_codecs_info/prj.conf b/tests/bluetooth/hci_codecs_info/prj.conf index 92653f4a3e1..316132fffc1 100644 --- a/tests/bluetooth/hci_codecs_info/prj.conf +++ b/tests/bluetooth/hci_codecs_info/prj.conf @@ -1,6 +1,5 @@ CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CTLR=y diff --git a/tests/bluetooth/hci_prop_evt/prj.conf b/tests/bluetooth/hci_prop_evt/prj.conf index 242ff1e1954..4951f0c3b3a 100644 --- a/tests/bluetooth/hci_prop_evt/prj.conf +++ b/tests/bluetooth/hci_prop_evt/prj.conf @@ -1,6 +1,5 @@ CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CTLR=n diff --git a/tests/bluetooth/hci_uart_async/prj.conf b/tests/bluetooth/hci_uart_async/prj.conf index b038c7c4312..408e8f611e4 100644 --- a/tests/bluetooth/hci_uart_async/prj.conf +++ b/tests/bluetooth/hci_uart_async/prj.conf @@ -7,4 +7,3 @@ CONFIG_LOG=y CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/hci_uart_async/src/test_hci_uart_async.c b/tests/bluetooth/hci_uart_async/src/test_hci_uart_async.c index 1996aba177a..08ea8bc1a79 100644 --- a/tests/bluetooth/hci_uart_async/src/test_hci_uart_async.c +++ b/tests/bluetooth/hci_uart_async/src/test_hci_uart_async.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include diff --git a/tests/bluetooth/hci_uart_async/testcase.yaml b/tests/bluetooth/hci_uart_async/testcase.yaml index f7f4a6255eb..31b7ac8bde4 100644 --- a/tests/bluetooth/hci_uart_async/testcase.yaml +++ b/tests/bluetooth/hci_uart_async/testcase.yaml @@ -1,6 +1,8 @@ tests: - samples.bluetooth.hci_uart_async: - tags: bluetooth uart + bluetooth.hci_uart_async: + tags: + - bluetooth + - uart harness: ztest platform_allow: - native_posix diff --git a/tests/bluetooth/host/buf/bt_buf_get_cmd_complete/prj.conf b/tests/bluetooth/host/buf/bt_buf_get_cmd_complete/prj.conf index 86979a3110d..652e7e5d169 100644 --- a/tests/bluetooth/host/buf/bt_buf_get_cmd_complete/prj.conf +++ b/tests/bluetooth/host/buf/bt_buf_get_cmd_complete/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/host/buf/bt_buf_get_evt/prj.conf b/tests/bluetooth/host/buf/bt_buf_get_evt/prj.conf index 86979a3110d..652e7e5d169 100644 --- a/tests/bluetooth/host/buf/bt_buf_get_evt/prj.conf +++ b/tests/bluetooth/host/buf/bt_buf_get_evt/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/host/buf/bt_buf_get_rx/prj.conf b/tests/bluetooth/host/buf/bt_buf_get_rx/prj.conf index 86979a3110d..652e7e5d169 100644 --- a/tests/bluetooth/host/buf/bt_buf_get_rx/prj.conf +++ b/tests/bluetooth/host/buf/bt_buf_get_rx/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/host/buf/bt_buf_get_type/prj.conf b/tests/bluetooth/host/buf/bt_buf_get_type/prj.conf index 86979a3110d..652e7e5d169 100644 --- a/tests/bluetooth/host/buf/bt_buf_get_type/prj.conf +++ b/tests/bluetooth/host/buf/bt_buf_get_type/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 diff --git a/tests/bluetooth/host/crypto/bt_encrypt_be/prj.conf b/tests/bluetooth/host/crypto/bt_encrypt_be/prj.conf index 542d140aa56..9b9d1e2cafc 100644 --- a/tests/bluetooth/host/crypto/bt_encrypt_be/prj.conf +++ b/tests/bluetooth/host/crypto/bt_encrypt_be/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_PAIRED=7 diff --git a/tests/bluetooth/host/crypto/bt_encrypt_le/prj.conf b/tests/bluetooth/host/crypto/bt_encrypt_le/prj.conf index 542d140aa56..9b9d1e2cafc 100644 --- a/tests/bluetooth/host/crypto/bt_encrypt_le/prj.conf +++ b/tests/bluetooth/host/crypto/bt_encrypt_le/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_PAIRED=7 diff --git a/tests/bluetooth/host/crypto/bt_rand/prj.conf b/tests/bluetooth/host/crypto/bt_rand/prj.conf index 542d140aa56..9b9d1e2cafc 100644 --- a/tests/bluetooth/host/crypto/bt_rand/prj.conf +++ b/tests/bluetooth/host/crypto/bt_rand/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_PAIRED=7 diff --git a/tests/bluetooth/host/crypto/prng_init/prj.conf b/tests/bluetooth/host/crypto/prng_init/prj.conf index 542d140aa56..9b9d1e2cafc 100644 --- a/tests/bluetooth/host/crypto/prng_init/prj.conf +++ b/tests/bluetooth/host/crypto/prng_init/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_PAIRED=7 diff --git a/tests/bluetooth/host/data/bt_data_parse/prj.conf b/tests/bluetooth/host/data/bt_data_parse/prj.conf index c68da48c1fb..432d8998c06 100644 --- a/tests/bluetooth/host/data/bt_data_parse/prj.conf +++ b/tests/bluetooth/host/data/bt_data_parse/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 CONFIG_ASSERT_VERBOSE=y diff --git a/tests/bluetooth/host/ecc/bt_dh_key_gen/prj.conf b/tests/bluetooth/host/ecc/bt_dh_key_gen/prj.conf index 542d140aa56..9b9d1e2cafc 100644 --- a/tests/bluetooth/host/ecc/bt_dh_key_gen/prj.conf +++ b/tests/bluetooth/host/ecc/bt_dh_key_gen/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_PAIRED=7 diff --git a/tests/bluetooth/host/ecc/bt_pub_key_gen/prj.conf b/tests/bluetooth/host/ecc/bt_pub_key_gen/prj.conf index 542d140aa56..9b9d1e2cafc 100644 --- a/tests/bluetooth/host/ecc/bt_pub_key_gen/prj.conf +++ b/tests/bluetooth/host/ecc/bt_pub_key_gen/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_PAIRED=7 diff --git a/tests/bluetooth/host/ecc/bt_pub_key_get/prj.conf b/tests/bluetooth/host/ecc/bt_pub_key_get/prj.conf index 542d140aa56..9b9d1e2cafc 100644 --- a/tests/bluetooth/host/ecc/bt_pub_key_get/prj.conf +++ b/tests/bluetooth/host/ecc/bt_pub_key_get/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_PAIRED=7 diff --git a/tests/bluetooth/host/ecc/bt_pub_key_is_debug/prj.conf b/tests/bluetooth/host/ecc/bt_pub_key_is_debug/prj.conf index 542d140aa56..9b9d1e2cafc 100644 --- a/tests/bluetooth/host/ecc/bt_pub_key_is_debug/prj.conf +++ b/tests/bluetooth/host/ecc/bt_pub_key_is_debug/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_PAIRED=7 diff --git a/tests/bluetooth/host/id/bt_br_oob_get_local/prj.conf b/tests/bluetooth/host/id/bt_br_oob_get_local/prj.conf index a047bb3413e..8d352723bb4 100644 --- a/tests/bluetooth/host/id/bt_br_oob_get_local/prj.conf +++ b/tests/bluetooth/host/id/bt_br_oob_get_local/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_BREDR=y diff --git a/tests/bluetooth/host/id/bt_id_add/prj.conf b/tests/bluetooth/host/id/bt_id_add/prj.conf index 32e36bb46eb..82e46bfe20f 100644 --- a/tests/bluetooth/host/id/bt_id_add/prj.conf +++ b/tests/bluetooth/host/id/bt_id_add/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_SMP=y diff --git a/tests/bluetooth/host/id/bt_id_adv_random_addr_check/prj.conf b/tests/bluetooth/host/id/bt_id_adv_random_addr_check/prj.conf index 7c5a2780471..3de82617e40 100644 --- a/tests/bluetooth/host/id/bt_id_adv_random_addr_check/prj.conf +++ b/tests/bluetooth/host/id/bt_id_adv_random_addr_check/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_ID_MAX=2 CONFIG_ASSERT=y diff --git a/tests/bluetooth/host/id/bt_id_create/prj.conf b/tests/bluetooth/host/id/bt_id_create/prj.conf index af15b84fb76..5f8cdcef017 100644 --- a/tests/bluetooth/host/id/bt_id_create/prj.conf +++ b/tests/bluetooth/host/id/bt_id_create/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_ID_MAX=2 diff --git a/tests/bluetooth/host/id/bt_id_del/prj.conf b/tests/bluetooth/host/id/bt_id_del/prj.conf index 32e36bb46eb..82e46bfe20f 100644 --- a/tests/bluetooth/host/id/bt_id_del/prj.conf +++ b/tests/bluetooth/host/id/bt_id_del/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_SMP=y diff --git a/tests/bluetooth/host/id/bt_id_delete/prj.conf b/tests/bluetooth/host/id/bt_id_delete/prj.conf index e53ac736d42..cae35e7d56c 100644 --- a/tests/bluetooth/host/id/bt_id_delete/prj.conf +++ b/tests/bluetooth/host/id/bt_id_delete/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_SMP=y diff --git a/tests/bluetooth/host/id/bt_id_get/prj.conf b/tests/bluetooth/host/id/bt_id_get/prj.conf index e53ac736d42..cae35e7d56c 100644 --- a/tests/bluetooth/host/id/bt_id_get/prj.conf +++ b/tests/bluetooth/host/id/bt_id_get/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_SMP=y diff --git a/tests/bluetooth/host/id/bt_id_init/prj.conf b/tests/bluetooth/host/id/bt_id_init/prj.conf index af15b84fb76..5f8cdcef017 100644 --- a/tests/bluetooth/host/id/bt_id_init/prj.conf +++ b/tests/bluetooth/host/id/bt_id_init/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_ID_MAX=2 diff --git a/tests/bluetooth/host/id/bt_id_read_public_addr/prj.conf b/tests/bluetooth/host/id/bt_id_read_public_addr/prj.conf index cabe512642a..42703d41300 100644 --- a/tests/bluetooth/host/id/bt_id_read_public_addr/prj.conf +++ b/tests/bluetooth/host/id/bt_id_read_public_addr/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_ASSERT=y diff --git a/tests/bluetooth/host/id/bt_id_reset/prj.conf b/tests/bluetooth/host/id/bt_id_reset/prj.conf index e53ac736d42..cae35e7d56c 100644 --- a/tests/bluetooth/host/id/bt_id_reset/prj.conf +++ b/tests/bluetooth/host/id/bt_id_reset/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_SMP=y diff --git a/tests/bluetooth/host/id/bt_id_scan_random_addr_check/prj.conf b/tests/bluetooth/host/id/bt_id_scan_random_addr_check/prj.conf index af15b84fb76..5f8cdcef017 100644 --- a/tests/bluetooth/host/id/bt_id_scan_random_addr_check/prj.conf +++ b/tests/bluetooth/host/id/bt_id_scan_random_addr_check/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_ID_MAX=2 diff --git a/tests/bluetooth/host/id/bt_id_set_adv_own_addr/prj.conf b/tests/bluetooth/host/id/bt_id_set_adv_own_addr/prj.conf index 10ea773d687..2682cec05b5 100644 --- a/tests/bluetooth/host/id/bt_id_set_adv_own_addr/prj.conf +++ b/tests/bluetooth/host/id/bt_id_set_adv_own_addr/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_SMP=y diff --git a/tests/bluetooth/host/id/bt_id_set_adv_private_addr/prj.conf b/tests/bluetooth/host/id/bt_id_set_adv_private_addr/prj.conf index af15b84fb76..5f8cdcef017 100644 --- a/tests/bluetooth/host/id/bt_id_set_adv_private_addr/prj.conf +++ b/tests/bluetooth/host/id/bt_id_set_adv_private_addr/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_ID_MAX=2 diff --git a/tests/bluetooth/host/id/bt_id_set_adv_private_addr/src/main.c b/tests/bluetooth/host/id/bt_id_set_adv_private_addr/src/main.c index b8c4974c03f..73f51ad4bf2 100644 --- a/tests/bluetooth/host/id/bt_id_set_adv_private_addr/src/main.c +++ b/tests/bluetooth/host/id/bt_id_set_adv_private_addr/src/main.c @@ -24,7 +24,7 @@ static void fff_reset_rule_before(const struct ztest_unit_test *test, void *fixt { memset(&bt_dev, 0x00, sizeof(struct bt_dev)); bt_addr_le_copy(&bt_dev.random_addr, &bt_addr_le_none); -#if defined(CONFIG_BT_PRIVACY) +#if defined(CONFIG_BT_RPA_SHARING) bt_addr_copy(&bt_dev.rpa[BT_ID_DEFAULT], BT_ADDR_NONE); #endif diff --git a/tests/bluetooth/host/id/bt_id_set_adv_random_addr/prj.conf b/tests/bluetooth/host/id/bt_id_set_adv_random_addr/prj.conf index af15b84fb76..5f8cdcef017 100644 --- a/tests/bluetooth/host/id/bt_id_set_adv_random_addr/prj.conf +++ b/tests/bluetooth/host/id/bt_id_set_adv_random_addr/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_ID_MAX=2 diff --git a/tests/bluetooth/host/id/bt_id_set_create_conn_own_addr/prj.conf b/tests/bluetooth/host/id/bt_id_set_create_conn_own_addr/prj.conf index 10ea773d687..2682cec05b5 100644 --- a/tests/bluetooth/host/id/bt_id_set_create_conn_own_addr/prj.conf +++ b/tests/bluetooth/host/id/bt_id_set_create_conn_own_addr/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_SMP=y diff --git a/tests/bluetooth/host/id/bt_id_set_private_addr/prj.conf b/tests/bluetooth/host/id/bt_id_set_private_addr/prj.conf index af15b84fb76..5f8cdcef017 100644 --- a/tests/bluetooth/host/id/bt_id_set_private_addr/prj.conf +++ b/tests/bluetooth/host/id/bt_id_set_private_addr/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_ID_MAX=2 diff --git a/tests/bluetooth/host/id/bt_id_set_scan_own_addr/prj.conf b/tests/bluetooth/host/id/bt_id_set_scan_own_addr/prj.conf index 10ea773d687..2682cec05b5 100644 --- a/tests/bluetooth/host/id/bt_id_set_scan_own_addr/prj.conf +++ b/tests/bluetooth/host/id/bt_id_set_scan_own_addr/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_SMP=y diff --git a/tests/bluetooth/host/id/bt_le_ext_adv_oob_get_local/prj.conf b/tests/bluetooth/host/id/bt_le_ext_adv_oob_get_local/prj.conf index f0c02aa41d3..7041a2b047e 100644 --- a/tests/bluetooth/host/id/bt_le_ext_adv_oob_get_local/prj.conf +++ b/tests/bluetooth/host/id/bt_le_ext_adv_oob_get_local/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_EXT_ADV=y diff --git a/tests/bluetooth/host/id/bt_le_oob_get_local/prj.conf b/tests/bluetooth/host/id/bt_le_oob_get_local/prj.conf index 10ea773d687..2682cec05b5 100644 --- a/tests/bluetooth/host/id/bt_le_oob_get_local/prj.conf +++ b/tests/bluetooth/host/id/bt_le_oob_get_local/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_SMP=y diff --git a/tests/bluetooth/host/id/bt_le_oob_get_sc_data/prj.conf b/tests/bluetooth/host/id/bt_le_oob_get_sc_data/prj.conf index f0c02aa41d3..7041a2b047e 100644 --- a/tests/bluetooth/host/id/bt_le_oob_get_sc_data/prj.conf +++ b/tests/bluetooth/host/id/bt_le_oob_get_sc_data/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_EXT_ADV=y diff --git a/tests/bluetooth/host/id/bt_le_oob_set_legacy_tk/prj.conf b/tests/bluetooth/host/id/bt_le_oob_set_legacy_tk/prj.conf index f0c02aa41d3..7041a2b047e 100644 --- a/tests/bluetooth/host/id/bt_le_oob_set_legacy_tk/prj.conf +++ b/tests/bluetooth/host/id/bt_le_oob_set_legacy_tk/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_EXT_ADV=y diff --git a/tests/bluetooth/host/id/bt_le_oob_set_sc_data/prj.conf b/tests/bluetooth/host/id/bt_le_oob_set_sc_data/prj.conf index f0c02aa41d3..7041a2b047e 100644 --- a/tests/bluetooth/host/id/bt_le_oob_set_sc_data/prj.conf +++ b/tests/bluetooth/host/id/bt_le_oob_set_sc_data/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_EXT_ADV=y diff --git a/tests/bluetooth/host/id/bt_lookup_id_addr/prj.conf b/tests/bluetooth/host/id/bt_lookup_id_addr/prj.conf index af15b84fb76..5f8cdcef017 100644 --- a/tests/bluetooth/host/id/bt_lookup_id_addr/prj.conf +++ b/tests/bluetooth/host/id/bt_lookup_id_addr/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_ID_MAX=2 diff --git a/tests/bluetooth/host/id/bt_setup_public_id_addr/prj.conf b/tests/bluetooth/host/id/bt_setup_public_id_addr/prj.conf index cabe512642a..42703d41300 100644 --- a/tests/bluetooth/host/id/bt_setup_public_id_addr/prj.conf +++ b/tests/bluetooth/host/id/bt_setup_public_id_addr/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_ASSERT=y diff --git a/tests/bluetooth/host/id/bt_setup_random_id_addr/prj.conf b/tests/bluetooth/host/id/bt_setup_random_id_addr/prj.conf index cabe512642a..42703d41300 100644 --- a/tests/bluetooth/host/id/bt_setup_random_id_addr/prj.conf +++ b/tests/bluetooth/host/id/bt_setup_random_id_addr/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_ASSERT=y diff --git a/tests/bluetooth/host/keys/bt_keys_add_type/prj.conf b/tests/bluetooth/host/keys/bt_keys_add_type/prj.conf index 2d9af947d94..419fdcd6047 100644 --- a/tests/bluetooth/host/keys/bt_keys_add_type/prj.conf +++ b/tests/bluetooth/host/keys/bt_keys_add_type/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_PAIRED=11 diff --git a/tests/bluetooth/host/keys/bt_keys_clear/prj.conf b/tests/bluetooth/host/keys/bt_keys_clear/prj.conf index 2d9af947d94..419fdcd6047 100644 --- a/tests/bluetooth/host/keys/bt_keys_clear/prj.conf +++ b/tests/bluetooth/host/keys/bt_keys_clear/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_PAIRED=11 diff --git a/tests/bluetooth/host/keys/bt_keys_find/prj.conf b/tests/bluetooth/host/keys/bt_keys_find/prj.conf index 4f07ff59817..b7101de0bf0 100644 --- a/tests/bluetooth/host/keys/bt_keys_find/prj.conf +++ b/tests/bluetooth/host/keys/bt_keys_find/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_PAIRED=7 diff --git a/tests/bluetooth/host/keys/bt_keys_find_addr/prj.conf b/tests/bluetooth/host/keys/bt_keys_find_addr/prj.conf index 2d9af947d94..419fdcd6047 100644 --- a/tests/bluetooth/host/keys/bt_keys_find_addr/prj.conf +++ b/tests/bluetooth/host/keys/bt_keys_find_addr/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_PAIRED=11 diff --git a/tests/bluetooth/host/keys/bt_keys_find_irk/prj.conf b/tests/bluetooth/host/keys/bt_keys_find_irk/prj.conf index 2d9af947d94..419fdcd6047 100644 --- a/tests/bluetooth/host/keys/bt_keys_find_irk/prj.conf +++ b/tests/bluetooth/host/keys/bt_keys_find_irk/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_PAIRED=11 diff --git a/tests/bluetooth/host/keys/bt_keys_foreach_bond/prj.conf b/tests/bluetooth/host/keys/bt_keys_foreach_bond/prj.conf index f974a1868bb..d50176dd3d3 100644 --- a/tests/bluetooth/host/keys/bt_keys_foreach_bond/prj.conf +++ b/tests/bluetooth/host/keys/bt_keys_foreach_bond/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_PAIRED=4 diff --git a/tests/bluetooth/host/keys/bt_keys_foreach_type/prj.conf b/tests/bluetooth/host/keys/bt_keys_foreach_type/prj.conf index e45b77e8764..b650eff88e5 100644 --- a/tests/bluetooth/host/keys/bt_keys_foreach_type/prj.conf +++ b/tests/bluetooth/host/keys/bt_keys_foreach_type/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_PAIRED=7 diff --git a/tests/bluetooth/host/keys/bt_keys_get_addr/prj.conf b/tests/bluetooth/host/keys/bt_keys_get_addr/prj.conf index f974a1868bb..d50176dd3d3 100644 --- a/tests/bluetooth/host/keys/bt_keys_get_addr/prj.conf +++ b/tests/bluetooth/host/keys/bt_keys_get_addr/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_PAIRED=4 diff --git a/tests/bluetooth/host/keys/bt_keys_get_type/prj.conf b/tests/bluetooth/host/keys/bt_keys_get_type/prj.conf index 4f07ff59817..b7101de0bf0 100644 --- a/tests/bluetooth/host/keys/bt_keys_get_type/prj.conf +++ b/tests/bluetooth/host/keys/bt_keys_get_type/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_PAIRED=7 diff --git a/tests/bluetooth/host/keys/bt_keys_store/prj.conf b/tests/bluetooth/host/keys/bt_keys_store/prj.conf index 2d9af947d94..419fdcd6047 100644 --- a/tests/bluetooth/host/keys/bt_keys_store/prj.conf +++ b/tests/bluetooth/host/keys/bt_keys_store/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_PAIRED=11 diff --git a/tests/bluetooth/host/keys/bt_keys_update_usage/prj.conf b/tests/bluetooth/host/keys/bt_keys_update_usage/prj.conf index 2d9af947d94..419fdcd6047 100644 --- a/tests/bluetooth/host/keys/bt_keys_update_usage/prj.conf +++ b/tests/bluetooth/host/keys/bt_keys_update_usage/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_PAIRED=11 diff --git a/tests/bluetooth/host_long_adv_recv/prj.conf b/tests/bluetooth/host_long_adv_recv/prj.conf index 68a16e68501..c25b96cf196 100644 --- a/tests/bluetooth/host_long_adv_recv/prj.conf +++ b/tests/bluetooth/host_long_adv_recv/prj.conf @@ -1,6 +1,5 @@ CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CTLR=n diff --git a/tests/bluetooth/init/prj.conf b/tests/bluetooth/init/prj.conf index 2103829ea4e..ccc9ef1dcef 100644 --- a/tests/bluetooth/init/prj.conf +++ b/tests/bluetooth/init/prj.conf @@ -1,4 +1,3 @@ CONFIG_BT=y CONFIG_LOG=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_0.conf b/tests/bluetooth/init/prj_0.conf index efb286cf1ec..371990240bf 100644 --- a/tests/bluetooth/init/prj_0.conf +++ b/tests/bluetooth/init/prj_0.conf @@ -1,3 +1,2 @@ CONFIG_BT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_1.conf b/tests/bluetooth/init/prj_1.conf index 354c519cb44..4c8c6144a5c 100644 --- a/tests/bluetooth/init/prj_1.conf +++ b/tests/bluetooth/init/prj_1.conf @@ -1,4 +1,3 @@ CONFIG_BT=y CONFIG_BT_PERIPHERAL=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_10.conf b/tests/bluetooth/init/prj_10.conf index c2f94c28bad..6aca7357972 100644 --- a/tests/bluetooth/init/prj_10.conf +++ b/tests/bluetooth/init/prj_10.conf @@ -7,4 +7,3 @@ CONFIG_BT_SMP_SC_ONLY=y CONFIG_BT_TINYCRYPT_ECC=y CONFIG_BT_USE_DEBUG_KEYS=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_11.conf b/tests/bluetooth/init/prj_11.conf index 39046408626..6b46c845df8 100644 --- a/tests/bluetooth/init/prj_11.conf +++ b/tests/bluetooth/init/prj_11.conf @@ -9,4 +9,3 @@ CONFIG_BT_USE_DEBUG_KEYS=y CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y CONFIG_BT_GATT_CLIENT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_12.conf b/tests/bluetooth/init/prj_12.conf index 45ad9163b66..55111c5b288 100644 --- a/tests/bluetooth/init/prj_12.conf +++ b/tests/bluetooth/init/prj_12.conf @@ -8,4 +8,3 @@ CONFIG_BT_USE_DEBUG_KEYS=y CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y CONFIG_BT_GATT_CLIENT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_13.conf b/tests/bluetooth/init/prj_13.conf index c6b607952af..0de0be405ce 100644 --- a/tests/bluetooth/init/prj_13.conf +++ b/tests/bluetooth/init/prj_13.conf @@ -8,4 +8,3 @@ CONFIG_BT_USE_DEBUG_KEYS=y CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y CONFIG_BT_GATT_CLIENT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_14.conf b/tests/bluetooth/init/prj_14.conf index ecd5f2bf8d7..a25c48d4bbb 100644 --- a/tests/bluetooth/init/prj_14.conf +++ b/tests/bluetooth/init/prj_14.conf @@ -5,4 +5,3 @@ CONFIG_BT_SMP=y CONFIG_BT_SIGNING=y CONFIG_BT_TINYCRYPT_ECC=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_15.conf b/tests/bluetooth/init/prj_15.conf index 466cc3fcdd1..3839272ce11 100644 --- a/tests/bluetooth/init/prj_15.conf +++ b/tests/bluetooth/init/prj_15.conf @@ -5,4 +5,3 @@ CONFIG_BT_SMP=y CONFIG_BT_SMP_SC_ONLY=y CONFIG_BT_TINYCRYPT_ECC=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_16.conf b/tests/bluetooth/init/prj_16.conf index ba1a467bca4..bc30a21c277 100644 --- a/tests/bluetooth/init/prj_16.conf +++ b/tests/bluetooth/init/prj_16.conf @@ -5,4 +5,3 @@ CONFIG_BT_USE_DEBUG_KEYS=y CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y CONFIG_BT_GATT_CLIENT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_17.conf b/tests/bluetooth/init/prj_17.conf index 9c2b3689f3a..f085ad19fcd 100644 --- a/tests/bluetooth/init/prj_17.conf +++ b/tests/bluetooth/init/prj_17.conf @@ -20,4 +20,3 @@ CONFIG_BT_ATT_LOG_LEVEL_DBG=y CONFIG_BT_GATT_LOG_LEVEL_DBG=y CONFIG_BT_BREDR=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_18.conf b/tests/bluetooth/init/prj_18.conf index 3c9228643a1..66348e7e53d 100644 --- a/tests/bluetooth/init/prj_18.conf +++ b/tests/bluetooth/init/prj_18.conf @@ -2,4 +2,3 @@ CONFIG_BT=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_BREDR=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_19.conf b/tests/bluetooth/init/prj_19.conf index 55306b30462..af0aac027f8 100644 --- a/tests/bluetooth/init/prj_19.conf +++ b/tests/bluetooth/init/prj_19.conf @@ -2,4 +2,3 @@ CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_BREDR=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_2.conf b/tests/bluetooth/init/prj_2.conf index 349f9bfdf76..a1f822a48ab 100644 --- a/tests/bluetooth/init/prj_2.conf +++ b/tests/bluetooth/init/prj_2.conf @@ -1,4 +1,3 @@ CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_20.conf b/tests/bluetooth/init/prj_20.conf index 23b7ed7cb6f..96dc6501491 100644 --- a/tests/bluetooth/init/prj_20.conf +++ b/tests/bluetooth/init/prj_20.conf @@ -27,4 +27,3 @@ CONFIG_BT_A2DP=y CONFIG_BT_HFP_HF=y CONFIG_BT_HFP_HF_LOG_LEVEL_DBG=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_21.conf b/tests/bluetooth/init/prj_21.conf index 5ddee9de9e1..8ec212aa4eb 100644 --- a/tests/bluetooth/init/prj_21.conf +++ b/tests/bluetooth/init/prj_21.conf @@ -20,4 +20,3 @@ CONFIG_BT_ATT_LOG_LEVEL_DBG=y CONFIG_BT_GATT_LOG_LEVEL_DBG=y CONFIG_BT_BREDR=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_22.conf b/tests/bluetooth/init/prj_22.conf index 173ad3938ae..5fab545bc2c 100644 --- a/tests/bluetooth/init/prj_22.conf +++ b/tests/bluetooth/init/prj_22.conf @@ -3,4 +3,3 @@ CONFIG_BT_BREDR=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_SMP=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_3.conf b/tests/bluetooth/init/prj_3.conf index 33e4cacf9b5..9a0afb63d16 100644 --- a/tests/bluetooth/init/prj_3.conf +++ b/tests/bluetooth/init/prj_3.conf @@ -2,4 +2,3 @@ CONFIG_BT=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_4.conf b/tests/bluetooth/init/prj_4.conf index 334beabe5fe..ff9b717cf8b 100644 --- a/tests/bluetooth/init/prj_4.conf +++ b/tests/bluetooth/init/prj_4.conf @@ -2,4 +2,3 @@ CONFIG_BT=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_SMP=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_5.conf b/tests/bluetooth/init/prj_5.conf index dff5403766a..490d3509e31 100644 --- a/tests/bluetooth/init/prj_5.conf +++ b/tests/bluetooth/init/prj_5.conf @@ -2,4 +2,3 @@ CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_SMP=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_6.conf b/tests/bluetooth/init/prj_6.conf index cece23f25f3..2a8566b9b46 100644 --- a/tests/bluetooth/init/prj_6.conf +++ b/tests/bluetooth/init/prj_6.conf @@ -3,4 +3,3 @@ CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y CONFIG_BT_SMP=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_7.conf b/tests/bluetooth/init/prj_7.conf index a5a4afde20c..93423f64742 100644 --- a/tests/bluetooth/init/prj_7.conf +++ b/tests/bluetooth/init/prj_7.conf @@ -4,4 +4,3 @@ CONFIG_BT_CENTRAL=y CONFIG_BT_SMP=y CONFIG_BT_SIGNING=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_8.conf b/tests/bluetooth/init/prj_8.conf index e596936e543..2fdd7773009 100644 --- a/tests/bluetooth/init/prj_8.conf +++ b/tests/bluetooth/init/prj_8.conf @@ -5,4 +5,3 @@ CONFIG_BT_SMP=y CONFIG_BT_SIGNING=y CONFIG_BT_SMP_SC_ONLY=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_9.conf b/tests/bluetooth/init/prj_9.conf index 1b55964abcb..be22972e42d 100644 --- a/tests/bluetooth/init/prj_9.conf +++ b/tests/bluetooth/init/prj_9.conf @@ -6,4 +6,3 @@ CONFIG_BT_SIGNING=y CONFIG_BT_SMP_SC_ONLY=y CONFIG_BT_TINYCRYPT_ECC=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr.conf b/tests/bluetooth/init/prj_ctlr.conf index dc31bd76e08..d64a64cc2a2 100644 --- a/tests/bluetooth/init/prj_ctlr.conf +++ b/tests/bluetooth/init/prj_ctlr.conf @@ -14,4 +14,3 @@ CONFIG_BT_BREDR=n CONFIG_FLASH=y CONFIG_SOC_FLASH_NRF_RADIO_SYNC_TICKER=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_4_0.conf b/tests/bluetooth/init/prj_ctlr_4_0.conf index 4f9ec70d3bb..eed589e96d8 100644 --- a/tests/bluetooth/init/prj_ctlr_4_0.conf +++ b/tests/bluetooth/init/prj_ctlr_4_0.conf @@ -37,4 +37,3 @@ CONFIG_BT_BREDR=n CONFIG_FLASH=y CONFIG_SOC_FLASH_NRF_RADIO_SYNC_TICKER=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_4_0_dbg.conf b/tests/bluetooth/init/prj_ctlr_4_0_dbg.conf index 5fc61cf98c6..95b9763b073 100644 --- a/tests/bluetooth/init/prj_ctlr_4_0_dbg.conf +++ b/tests/bluetooth/init/prj_ctlr_4_0_dbg.conf @@ -39,4 +39,3 @@ CONFIG_BT_BREDR=n CONFIG_FLASH=y CONFIG_SOC_FLASH_NRF_RADIO_SYNC_TICKER=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_5_x_dbg.conf b/tests/bluetooth/init/prj_ctlr_5_x_dbg.conf index 50f72889476..03e6838e3ed 100644 --- a/tests/bluetooth/init/prj_ctlr_5_x_dbg.conf +++ b/tests/bluetooth/init/prj_ctlr_5_x_dbg.conf @@ -72,4 +72,3 @@ CONFIG_DEBUG=y CONFIG_FLASH=y CONFIG_SOC_FLASH_NRF_RADIO_SYNC_TICKER=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_broadcaster.conf b/tests/bluetooth/init/prj_ctlr_broadcaster.conf index 8bc2c0c7403..d062716f66b 100644 --- a/tests/bluetooth/init/prj_ctlr_broadcaster.conf +++ b/tests/bluetooth/init/prj_ctlr_broadcaster.conf @@ -8,4 +8,3 @@ CONFIG_BT_EXT_ADV=n CONFIG_BT_CTLR_ADV_EXT=n CONFIG_BT_LL_SW_SPLIT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_broadcaster_ext.conf b/tests/bluetooth/init/prj_ctlr_broadcaster_ext.conf index 5edaf811ec9..389e622135d 100644 --- a/tests/bluetooth/init/prj_ctlr_broadcaster_ext.conf +++ b/tests/bluetooth/init/prj_ctlr_broadcaster_ext.conf @@ -8,4 +8,3 @@ CONFIG_BT_EXT_ADV=y CONFIG_BT_CTLR_ADV_EXT=y CONFIG_BT_LL_SW_SPLIT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_broadcaster_iso.conf b/tests/bluetooth/init/prj_ctlr_broadcaster_iso.conf index 0f6faaf70c1..cd6f57dd75c 100644 --- a/tests/bluetooth/init/prj_ctlr_broadcaster_iso.conf +++ b/tests/bluetooth/init/prj_ctlr_broadcaster_iso.conf @@ -9,4 +9,3 @@ CONFIG_BT_LL_SW_SPLIT=y CONFIG_BT_CTLR_ADV_EXT=y CONFIG_BT_CTLR_ADV_ISO=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_central.conf b/tests/bluetooth/init/prj_ctlr_central.conf index b2b5b4d7952..f00fe35ea64 100644 --- a/tests/bluetooth/init/prj_ctlr_central.conf +++ b/tests/bluetooth/init/prj_ctlr_central.conf @@ -8,4 +8,3 @@ CONFIG_BT_EXT_ADV=n CONFIG_BT_CTLR_ADV_EXT=n CONFIG_BT_LL_SW_SPLIT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_central_ext.conf b/tests/bluetooth/init/prj_ctlr_central_ext.conf index 7ceaa6367c2..4508d629e35 100644 --- a/tests/bluetooth/init/prj_ctlr_central_ext.conf +++ b/tests/bluetooth/init/prj_ctlr_central_ext.conf @@ -8,4 +8,3 @@ CONFIG_BT_EXT_ADV=y CONFIG_BT_CTLR_ADV_EXT=y CONFIG_BT_LL_SW_SPLIT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_central_ext_priv.conf b/tests/bluetooth/init/prj_ctlr_central_ext_priv.conf index c4523b00c10..59f8a46addb 100644 --- a/tests/bluetooth/init/prj_ctlr_central_ext_priv.conf +++ b/tests/bluetooth/init/prj_ctlr_central_ext_priv.conf @@ -10,4 +10,3 @@ CONFIG_BT_EXT_ADV=y CONFIG_BT_CTLR_ADV_EXT=y CONFIG_BT_LL_SW_SPLIT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_central_iso.conf b/tests/bluetooth/init/prj_ctlr_central_iso.conf index 96efca2d081..ad23e1c6675 100644 --- a/tests/bluetooth/init/prj_ctlr_central_iso.conf +++ b/tests/bluetooth/init/prj_ctlr_central_iso.conf @@ -5,4 +5,3 @@ CONFIG_BT_LL_SW_SPLIT=y CONFIG_BT_ISO_CENTRAL=y CONFIG_BT_CTLR_CENTRAL_ISO=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_central_priv.conf b/tests/bluetooth/init/prj_ctlr_central_priv.conf index 9a6770f2f47..3bf4650f1e7 100644 --- a/tests/bluetooth/init/prj_ctlr_central_priv.conf +++ b/tests/bluetooth/init/prj_ctlr_central_priv.conf @@ -10,4 +10,3 @@ CONFIG_BT_EXT_ADV=n CONFIG_BT_CTLR_ADV_EXT=n CONFIG_BT_LL_SW_SPLIT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_dbg.conf b/tests/bluetooth/init/prj_ctlr_dbg.conf index 2f8224cdfea..ac9efeb9338 100644 --- a/tests/bluetooth/init/prj_ctlr_dbg.conf +++ b/tests/bluetooth/init/prj_ctlr_dbg.conf @@ -58,4 +58,3 @@ CONFIG_DEBUG=y CONFIG_FLASH=y CONFIG_SOC_FLASH_NRF_RADIO_SYNC_TICKER=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_observer.conf b/tests/bluetooth/init/prj_ctlr_observer.conf index e785cda5f1d..96d1d2d8edb 100644 --- a/tests/bluetooth/init/prj_ctlr_observer.conf +++ b/tests/bluetooth/init/prj_ctlr_observer.conf @@ -8,4 +8,3 @@ CONFIG_BT_EXT_ADV=n CONFIG_BT_CTLR_ADV_EXT=n CONFIG_BT_LL_SW_SPLIT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_observer_ext.conf b/tests/bluetooth/init/prj_ctlr_observer_ext.conf index ae744255677..4d540d59f25 100644 --- a/tests/bluetooth/init/prj_ctlr_observer_ext.conf +++ b/tests/bluetooth/init/prj_ctlr_observer_ext.conf @@ -8,4 +8,3 @@ CONFIG_BT_EXT_ADV=y CONFIG_BT_CTLR_ADV_EXT=y CONFIG_BT_LL_SW_SPLIT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_per_adv.conf b/tests/bluetooth/init/prj_ctlr_per_adv.conf index 4897e55fa55..c070838fc06 100644 --- a/tests/bluetooth/init/prj_ctlr_per_adv.conf +++ b/tests/bluetooth/init/prj_ctlr_per_adv.conf @@ -11,4 +11,3 @@ CONFIG_BT_CTLR_ADV_PERIODIC=y CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT=y CONFIG_BT_LL_SW_SPLIT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_per_adv_no_adi.conf b/tests/bluetooth/init/prj_ctlr_per_adv_no_adi.conf index 3701e092252..e2bd0cc711c 100644 --- a/tests/bluetooth/init/prj_ctlr_per_adv_no_adi.conf +++ b/tests/bluetooth/init/prj_ctlr_per_adv_no_adi.conf @@ -11,4 +11,3 @@ CONFIG_BT_CTLR_ADV_PERIODIC=y CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT=n CONFIG_BT_LL_SW_SPLIT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_per_sync.conf b/tests/bluetooth/init/prj_ctlr_per_sync.conf index 0c3d99e87af..60142f55adc 100644 --- a/tests/bluetooth/init/prj_ctlr_per_sync.conf +++ b/tests/bluetooth/init/prj_ctlr_per_sync.conf @@ -12,4 +12,3 @@ CONFIG_BT_CTLR_SYNC_PERIODIC=y CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT=y CONFIG_BT_LL_SW_SPLIT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_per_sync_no_adi.conf b/tests/bluetooth/init/prj_ctlr_per_sync_no_adi.conf index 4fa71725642..c2e9ce0defc 100644 --- a/tests/bluetooth/init/prj_ctlr_per_sync_no_adi.conf +++ b/tests/bluetooth/init/prj_ctlr_per_sync_no_adi.conf @@ -12,4 +12,3 @@ CONFIG_BT_CTLR_SYNC_PERIODIC=y CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT=n CONFIG_BT_LL_SW_SPLIT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_per_sync_no_filter.conf b/tests/bluetooth/init/prj_ctlr_per_sync_no_filter.conf index 1fe748a9590..62b952a7e89 100644 --- a/tests/bluetooth/init/prj_ctlr_per_sync_no_filter.conf +++ b/tests/bluetooth/init/prj_ctlr_per_sync_no_filter.conf @@ -12,4 +12,3 @@ CONFIG_BT_CTLR_SYNC_PERIODIC=y CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT=n CONFIG_BT_LL_SW_SPLIT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_peripheral.conf b/tests/bluetooth/init/prj_ctlr_peripheral.conf index 60f89899c28..3a41b00e864 100644 --- a/tests/bluetooth/init/prj_ctlr_peripheral.conf +++ b/tests/bluetooth/init/prj_ctlr_peripheral.conf @@ -8,4 +8,3 @@ CONFIG_BT_EXT_ADV=n CONFIG_BT_CTLR_ADV_EXT=n CONFIG_BT_LL_SW_SPLIT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_peripheral_ext.conf b/tests/bluetooth/init/prj_ctlr_peripheral_ext.conf index f2e3218db6d..9f1b6919aa9 100644 --- a/tests/bluetooth/init/prj_ctlr_peripheral_ext.conf +++ b/tests/bluetooth/init/prj_ctlr_peripheral_ext.conf @@ -8,4 +8,3 @@ CONFIG_BT_EXT_ADV=y CONFIG_BT_CTLR_ADV_EXT=y CONFIG_BT_LL_SW_SPLIT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_peripheral_ext_priv.conf b/tests/bluetooth/init/prj_ctlr_peripheral_ext_priv.conf index e7e5ac7ed7b..e0c3f9487c0 100644 --- a/tests/bluetooth/init/prj_ctlr_peripheral_ext_priv.conf +++ b/tests/bluetooth/init/prj_ctlr_peripheral_ext_priv.conf @@ -10,4 +10,3 @@ CONFIG_BT_EXT_ADV=y CONFIG_BT_CTLR_ADV_EXT=y CONFIG_BT_LL_SW_SPLIT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_peripheral_iso.conf b/tests/bluetooth/init/prj_ctlr_peripheral_iso.conf index 5efb8c6b848..c2e3ca23a5b 100644 --- a/tests/bluetooth/init/prj_ctlr_peripheral_iso.conf +++ b/tests/bluetooth/init/prj_ctlr_peripheral_iso.conf @@ -10,4 +10,3 @@ CONFIG_BT_CTLR_ADVANCED_FEATURES=y CONFIG_BT_CTLR_PERIPHERAL_ISO_EARLY_CIG_START=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_peripheral_priv.conf b/tests/bluetooth/init/prj_ctlr_peripheral_priv.conf index a7628e54aec..9175c302272 100644 --- a/tests/bluetooth/init/prj_ctlr_peripheral_priv.conf +++ b/tests/bluetooth/init/prj_ctlr_peripheral_priv.conf @@ -10,4 +10,3 @@ CONFIG_BT_EXT_ADV=n CONFIG_BT_CTLR_ADV_EXT=n CONFIG_BT_LL_SW_SPLIT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_sync_iso.conf b/tests/bluetooth/init/prj_ctlr_sync_iso.conf index 8ae4e44e450..c61443085e1 100644 --- a/tests/bluetooth/init/prj_ctlr_sync_iso.conf +++ b/tests/bluetooth/init/prj_ctlr_sync_iso.conf @@ -11,4 +11,3 @@ CONFIG_BT_CTLR_SYNC_PERIODIC=y CONFIG_BT_CTLR_SYNC_ISO=y CONFIG_BT_LL_SW_SPLIT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_ticker.conf b/tests/bluetooth/init/prj_ctlr_ticker.conf index 4e5b962231e..efeae970f31 100644 --- a/tests/bluetooth/init/prj_ctlr_ticker.conf +++ b/tests/bluetooth/init/prj_ctlr_ticker.conf @@ -61,4 +61,3 @@ CONFIG_DEBUG=y CONFIG_FLASH=y CONFIG_SOC_FLASH_NRF_RADIO_SYNC_TICKER=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_ctlr_tiny.conf b/tests/bluetooth/init/prj_ctlr_tiny.conf index ce75583da16..f0056881680 100644 --- a/tests/bluetooth/init/prj_ctlr_tiny.conf +++ b/tests/bluetooth/init/prj_ctlr_tiny.conf @@ -44,4 +44,3 @@ CONFIG_ASSERT=n CONFIG_FLASH=y CONFIG_SOC_FLASH_NRF_RADIO_SYNC_TICKER=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_h5.conf b/tests/bluetooth/init/prj_h5.conf index 5a1eb7ae2c6..976697e3dba 100644 --- a/tests/bluetooth/init/prj_h5.conf +++ b/tests/bluetooth/init/prj_h5.conf @@ -1,4 +1,3 @@ CONFIG_BT=y CONFIG_BT_H5=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_h5_dbg.conf b/tests/bluetooth/init/prj_h5_dbg.conf index 28ef86d3e09..a0e25ac20d2 100644 --- a/tests/bluetooth/init/prj_h5_dbg.conf +++ b/tests/bluetooth/init/prj_h5_dbg.conf @@ -3,4 +3,3 @@ CONFIG_BT_H5=y CONFIG_LOG=y CONFIG_BT_HCI_DRIVER_LOG_LEVEL_DBG=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/prj_llcp.conf b/tests/bluetooth/init/prj_llcp.conf index ffa52753363..626e6c40e2b 100644 --- a/tests/bluetooth/init/prj_llcp.conf +++ b/tests/bluetooth/init/prj_llcp.conf @@ -16,4 +16,3 @@ CONFIG_SOC_FLASH_NRF_RADIO_SYNC_TICKER=y CONFIG_BT_CTLR_ADVANCED_FEATURES=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/l2cap/prj.conf b/tests/bluetooth/l2cap/prj.conf index 3a7449d2618..69eb3d64ca7 100644 --- a/tests/bluetooth/l2cap/prj.conf +++ b/tests/bluetooth/l2cap/prj.conf @@ -1,6 +1,5 @@ CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CTLR=n diff --git a/tests/bluetooth/l2cap/src/main.c b/tests/bluetooth/l2cap/src/main.c index 029b5f90287..165c5cc7fa7 100644 --- a/tests/bluetooth/l2cap/src/main.c +++ b/tests/bluetooth/l2cap/src/main.c @@ -14,7 +14,8 @@ #include #include -static int l2cap_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan) +static int l2cap_accept(struct bt_conn *conn, struct bt_l2cap_server *server, + struct bt_l2cap_chan **chan) { return -ENOSYS; } diff --git a/tests/bluetooth/ll_settings/prj.conf b/tests/bluetooth/ll_settings/prj.conf index eddcfe8428b..ab133036bf9 100644 --- a/tests/bluetooth/ll_settings/prj.conf +++ b/tests/bluetooth/ll_settings/prj.conf @@ -1,6 +1,5 @@ CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CTLR=y diff --git a/tests/bluetooth/mesh/basic/src/main.c b/tests/bluetooth/mesh/basic/src/main.c index 8c6c1796c02..d48a012bb2a 100644 --- a/tests/bluetooth/mesh/basic/src/main.c +++ b/tests/bluetooth/mesh/basic/src/main.c @@ -15,7 +15,7 @@ static bool has_reg_fault = true; -static int fault_get_cur(struct bt_mesh_model *model, uint8_t *test_id, +static int fault_get_cur(const struct bt_mesh_model *model, uint8_t *test_id, uint16_t *company_id, uint8_t *faults, uint8_t *fault_count) { uint8_t reg_faults[MAX_FAULT] = { [0 ... (MAX_FAULT - 1)] = 0xff }; @@ -30,7 +30,7 @@ static int fault_get_cur(struct bt_mesh_model *model, uint8_t *test_id, return 0; } -static int fault_get_reg(struct bt_mesh_model *model, uint16_t company_id, +static int fault_get_reg(const struct bt_mesh_model *model, uint16_t company_id, uint8_t *test_id, uint8_t *faults, uint8_t *fault_count) { if (company_id != BT_COMP_ID_LF) { @@ -53,7 +53,7 @@ static int fault_get_reg(struct bt_mesh_model *model, uint16_t company_id, return 0; } -static int fault_clear(struct bt_mesh_model *model, uint16_t company_id) +static int fault_clear(const struct bt_mesh_model *model, uint16_t company_id) { if (company_id != BT_COMP_ID_LF) { return -EINVAL; @@ -64,7 +64,7 @@ static int fault_clear(struct bt_mesh_model *model, uint16_t company_id) return 0; } -static int fault_test(struct bt_mesh_model *model, uint8_t test_id, +static int fault_test(const struct bt_mesh_model *model, uint8_t test_id, uint16_t company_id) { if (company_id != BT_COMP_ID_LF) { @@ -90,12 +90,12 @@ static struct bt_mesh_health_srv health_srv = { BT_MESH_HEALTH_PUB_DEFINE(health_pub, MAX_FAULT); -static struct bt_mesh_model root_models[] = { +static const struct bt_mesh_model root_models[] = { BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub), }; -static int vnd_publish(struct bt_mesh_model *mod) +static int vnd_publish(const struct bt_mesh_model *mod) { printk("Vendor publish\n"); return 0; @@ -109,12 +109,12 @@ static const struct bt_mesh_model_op vnd_ops[] = { BT_MESH_MODEL_OP_END, }; -static struct bt_mesh_model vnd_models[] = { +static const struct bt_mesh_model vnd_models[] = { BT_MESH_MODEL_VND(BT_COMP_ID_LF, 0x1234, vnd_ops, &vnd_pub, NULL), BT_MESH_MODEL_VND(BT_COMP_ID_LF, 0x4321, vnd_ops, &vnd_pub2, NULL), }; -static struct bt_mesh_elem elements[] = { +static const struct bt_mesh_elem elements[] = { BT_MESH_ELEM(0, root_models, vnd_models), }; diff --git a/tests/bluetooth/mesh/blob_io_flash/prj.conf b/tests/bluetooth/mesh/blob_io_flash/prj.conf index e65e7914724..2a0e98421fa 100644 --- a/tests/bluetooth/mesh/blob_io_flash/prj.conf +++ b/tests/bluetooth/mesh/blob_io_flash/prj.conf @@ -19,5 +19,3 @@ CONFIG_BT_MESH_V1d1=y CONFIG_BT_MESH_BLOB_SRV=y CONFIG_BT_MESH_BLOB_CLI=y CONFIG_BT_MESH_BLOB_IO_FLASH=y - -CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/mesh/rpl/prj.conf b/tests/bluetooth/mesh/rpl/prj.conf index 0d11d85e2fa..31c31ebcd12 100644 --- a/tests/bluetooth/mesh/rpl/prj.conf +++ b/tests/bluetooth/mesh/rpl/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_MOCKING=y diff --git a/tests/bluetooth/mesh_shell/src/main.c b/tests/bluetooth/mesh_shell/src/main.c index 60863f7455a..f5dbdc41b40 100644 --- a/tests/bluetooth/mesh_shell/src/main.c +++ b/tests/bluetooth/mesh_shell/src/main.c @@ -43,7 +43,7 @@ struct bt_mesh_large_comp_data_cli large_comp_data_cli; BT_MESH_SHELL_HEALTH_PUB_DEFINE(health_pub); -static struct bt_mesh_model root_models[] = { +static const struct bt_mesh_model root_models[] = { BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), BT_MESH_MODEL_HEALTH_SRV(&bt_mesh_shell_health_srv, &health_pub), @@ -107,7 +107,7 @@ static struct bt_mesh_model root_models[] = { #endif }; -static struct bt_mesh_elem elements[] = { +static const struct bt_mesh_elem elements[] = { BT_MESH_ELEM(0, root_models, BT_MESH_MODEL_NONE), }; diff --git a/tests/bluetooth/shell/audio.conf b/tests/bluetooth/shell/audio.conf index e43583cc160..8cf39af0bdb 100644 --- a/tests/bluetooth/shell/audio.conf +++ b/tests/bluetooth/shell/audio.conf @@ -46,6 +46,7 @@ CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER=y # Support an ISO channel per ASE CONFIG_BT_ISO_MAX_CHAN=4 +CONFIG_BT_ISO_TEST_PARAMS=y CONFIG_BT_ISO_TX_BUF_COUNT=10 CONFIG_BT_ISO_RX_BUF_COUNT=20 CONFIG_BT_ISO_TX_MTU=310 @@ -152,6 +153,7 @@ CONFIG_BT_HAS_PRESET_CONTROL_POINT_NOTIFIABLE=y CONFIG_BT_CAP_ACCEPTOR=y CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER=y CONFIG_BT_CAP_INITIATOR=y +CONFIG_BT_CAP_COMMANDER=y # Telephone and Media Audio Profile CONFIG_BT_TMAP=y @@ -200,4 +202,5 @@ CONFIG_BT_CSIP_SET_COORDINATOR_LOG_LEVEL_DBG=y CONFIG_BT_CSIP_SET_MEMBER_LOG_LEVEL_DBG=y CONFIG_BT_CAP_ACCEPTOR_LOG_LEVEL_DBG=y CONFIG_BT_CAP_INITIATOR_LOG_LEVEL_DBG=y +CONFIG_BT_CAP_COMMANDER_LOG_LEVEL_DBG=y CONFIG_BT_TMAP_LOG_LEVEL_DBG=y diff --git a/tests/bluetooth/shell/boards/native_posix.conf b/tests/bluetooth/shell/boards/native_posix.conf index f35bf051edc..a2ab2f4e87a 100644 --- a/tests/bluetooth/shell/boards/native_posix.conf +++ b/tests/bluetooth/shell/boards/native_posix.conf @@ -14,5 +14,3 @@ CONFIG_LIBLC3=y # The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence # inctease stack size for that thread. CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 -# LC3 lib requires floating point support in the c-lib NEWLIB is one way of getting that. -CONFIG_NEWLIB_LIBC=y diff --git a/tests/bluetooth/shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/tests/bluetooth/shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf index f7c6bbfd3db..8d48d5e1c20 100644 --- a/tests/bluetooth/shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf +++ b/tests/bluetooth/shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -4,5 +4,3 @@ CONFIG_LIBLC3=y # The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence # inctease stack size for that thread. CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 -# LC3 lib requires floating point support in the c-lib NEWLIB is one way of getting that. -CONFIG_NEWLIB_LIBC=y diff --git a/tests/bluetooth/shell/boards/nrf5340dk_nrf5340_cpuapp.conf b/tests/bluetooth/shell/boards/nrf5340dk_nrf5340_cpuapp.conf index f7c6bbfd3db..8d48d5e1c20 100644 --- a/tests/bluetooth/shell/boards/nrf5340dk_nrf5340_cpuapp.conf +++ b/tests/bluetooth/shell/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -4,5 +4,3 @@ CONFIG_LIBLC3=y # The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence # inctease stack size for that thread. CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 -# LC3 lib requires floating point support in the c-lib NEWLIB is one way of getting that. -CONFIG_NEWLIB_LIBC=y diff --git a/tests/bluetooth/tester/CMakeLists.txt b/tests/bluetooth/tester/CMakeLists.txt index fb8f9114e41..842b6ebe5d8 100644 --- a/tests/bluetooth/tester/CMakeLists.txt +++ b/tests/bluetooth/tester/CMakeLists.txt @@ -43,3 +43,23 @@ endif() if (CONFIG_BT_CSIP_SET_MEMBER) target_sources(app PRIVATE src/btp_csis.c) endif() + +if(CONFIG_BT_MICP_MIC_DEV) + target_sources(app PRIVATE src/btp_micp.c) +endif() + +if(CONFIG_BT_AICS) + target_sources(app PRIVATE src/btp_aics.c) +endif() + +if (CONFIG_BT_TBS_CLIENT) + target_sources(app PRIVATE src/btp_ccp.c) +endif() + +if (CONFIG_BT_CAP_ACCEPTOR) + target_sources(app PRIVATE src/btp_cas.c) +endif() + +if(CONFIG_BT_MCC) + target_sources(app PRIVATE src/btp_mcp.c) +endif() diff --git a/tests/bluetooth/tester/boards/native_sim.conf b/tests/bluetooth/tester/boards/native_sim.conf new file mode 100644 index 00000000000..30abfdbc3d9 --- /dev/null +++ b/tests/bluetooth/tester/boards/native_sim.conf @@ -0,0 +1,3 @@ +CONFIG_UART_PIPE=n +CONFIG_SERIAL=y +CONFIG_UART_NATIVE_POSIX=y diff --git a/tests/bluetooth/tester/nrf5340_hci_ipc.conf b/tests/bluetooth/tester/nrf5340_hci_ipc.conf new file mode 100644 index 00000000000..689ee0ea5af --- /dev/null +++ b/tests/bluetooth/tester/nrf5340_hci_ipc.conf @@ -0,0 +1,5 @@ +# Those have to be the same as in the controller (hci_ipc) +CONFIG_BT_MAX_CONN=2 +CONFIG_BT_BUF_EVT_RX_COUNT=16 +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_CMD_TX_SIZE=255 diff --git a/tests/bluetooth/tester/nrf5340_hci_ipc_cpunet.conf b/tests/bluetooth/tester/nrf5340_hci_ipc_cpunet.conf new file mode 100644 index 00000000000..399262b47c9 --- /dev/null +++ b/tests/bluetooth/tester/nrf5340_hci_ipc_cpunet.conf @@ -0,0 +1,5 @@ +# Apply this overlay at hci_ipc controller build +CONFIG_BT_CTLR_CONN_ISO_LOW_LATENCY_POLICY=y +CONFIG_BT_CTLR_DATA_LENGTH_MAX=100 +CONFIG_BT_BUF_ACL_RX_SIZE=100 +CONFIG_BT_CTLR_PERIPHERAL_ISO_EARLY_CIG_START=y diff --git a/tests/bluetooth/tester/nrf5340_hci_rpmsg.conf b/tests/bluetooth/tester/nrf5340_hci_rpmsg.conf deleted file mode 100644 index 234d0f5a249..00000000000 --- a/tests/bluetooth/tester/nrf5340_hci_rpmsg.conf +++ /dev/null @@ -1,5 +0,0 @@ -# Those have to be the same as in the controller (hci_rpmsg) -CONFIG_BT_MAX_CONN=2 -CONFIG_BT_BUF_EVT_RX_COUNT=16 -CONFIG_BT_BUF_EVT_RX_SIZE=255 -CONFIG_BT_BUF_CMD_TX_SIZE=255 diff --git a/tests/bluetooth/tester/nrf5340_hci_rpmsg_cpunet.conf b/tests/bluetooth/tester/nrf5340_hci_rpmsg_cpunet.conf deleted file mode 100644 index 7a484587c5c..00000000000 --- a/tests/bluetooth/tester/nrf5340_hci_rpmsg_cpunet.conf +++ /dev/null @@ -1,5 +0,0 @@ -# Apply this overlay at hci_rpmsg controller build -CONFIG_BT_CTLR_CONN_ISO_LOW_LATENCY_POLICY=y -CONFIG_BT_CTLR_DATA_LENGTH_MAX=100 -CONFIG_BT_BUF_ACL_RX_SIZE=100 -CONFIG_BT_CTLR_PERIPHERAL_ISO_EARLY_CIG_START=y diff --git a/tests/bluetooth/tester/overlay-le-audio.conf b/tests/bluetooth/tester/overlay-le-audio.conf index c482c64b5dc..4a7fc4e606c 100644 --- a/tests/bluetooth/tester/overlay-le-audio.conf +++ b/tests/bluetooth/tester/overlay-le-audio.conf @@ -5,11 +5,12 @@ CONFIG_BT_BAP_UNICAST_CLIENT=y CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT=2 CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT=2 CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT=4 +CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE=16 # Ring buffer for streaming ISO data CONFIG_RING_BUFFER=y -# These have to be the same as in the controller (hci_rpmsg) +# These have to be the same as in the controller (hci_ipc) CONFIG_BT_MAX_CONN=2 CONFIG_BT_BUF_EVT_RX_COUNT=16 CONFIG_BT_BUF_EVT_RX_SIZE=255 @@ -19,6 +20,33 @@ CONFIG_BT_BUF_CMD_TX_SIZE=255 # were freed too slow. The bt_bap_stream_ops.configured callback comes earlier. CONFIG_BT_L2CAP_TX_BUF_COUNT=4 +# MICP +CONFIG_BT_MICP_MIC_DEV=y +CONFIG_BT_MICP_MIC_DEV_AICS_INSTANCE_COUNT=1 +CONFIG_BT_MICP_MIC_CTLR=y +CONFIG_BT_MICP_MIC_CTLR_MAX_AICS_INST=1 + +# Broadcast Source +CONFIG_BT_BAP_BROADCAST_SOURCE=y +CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT=2 +CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT=2 +CONFIG_BT_ISO_TX_BUF_COUNT=4 +CONFIG_BT_BAP_BROADCAST_ASSISTANT=y + +# Broadcast Sink +CONFIG_BT_BAP_SCAN_DELEGATOR=y +CONFIG_BT_BAP_BROADCAST_SINK=y +CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT=2 +CONFIG_BT_BAP_BROADCAST_SNK_SUBGROUP_COUNT=2 + +# BASS +CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER=y +CONFIG_BT_BAP_SCAN_DELEGATOR_MAX_METADATA_LEN=255 +CONFIG_BT_PER_ADV_SYNC_TRANSFER_RECEIVER=y +# BASS notifications need higher MTU +CONFIG_BT_L2CAP_TX_MTU=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 + # ASCS CONFIG_BT_ASCS_ASE_SNK_COUNT=2 CONFIG_BT_ASCS_ASE_SRC_COUNT=2 @@ -29,6 +57,11 @@ CONFIG_BT_ISO_MAX_CHAN=4 # PACS CONFIG_BT_PAC_SNK_LOC_WRITEABLE=y CONFIG_BT_PAC_SRC_LOC_WRITEABLE=y +CONFIG_BT_PAC_SNK_LOC_NOTIFIABLE=y +CONFIG_BT_PAC_SRC_LOC_NOTIFIABLE=y +CONFIG_BT_PAC_SNK_NOTIFIABLE=y +CONFIG_BT_PAC_SRC_NOTIFIABLE=y +CONFIG_BT_PACS_SUPPORTED_CONTEXT_NOTIFIABLE=y # Volume Offset Control Service CONFIG_BT_VOCS_MAX_INSTANCE_COUNT=2 @@ -43,6 +76,10 @@ CONFIG_BT_VCP_VOL_REND=y CONFIG_BT_VCP_VOL_REND_VOCS_INSTANCE_COUNT=2 CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT=2 CONFIG_BT_VCP_VOL_REND_LOG_LEVEL_DBG=y +CONFIG_BT_VCP_VOL_CTLR=y +CONFIG_BT_VCP_VOL_CTLR_MAX_VOCS_INST=1 +CONFIG_BT_VCP_VOL_CTLR_MAX_AICS_INST=1 +CONFIG_BT_VCP_VOL_CTLR_LOG_LEVEL_DBG=y # IAS CONFIG_BT_IAS=y @@ -55,3 +92,17 @@ CONFIG_BT_HAS_PRESET_NAME_DYNAMIC=y # CSIS CONFIG_BT_CSIP_SET_MEMBER=y + +# CCP +CONFIG_BT_L2CAP_TX_BUF_COUNT=12 +CONFIG_BT_TBS_CLIENT_GTBS=y +CONFIG_BT_TBS_CLIENT_TBS=n + +# CAS +CONFIG_BT_CAP_ACCEPTOR=y +CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER=y + +# MCP +CONFIG_BT_MCC=y +CONFIG_BT_OTS_CLIENT=y +CONFIG_BT_MCC_OTS=y diff --git a/tests/bluetooth/tester/prj.conf b/tests/bluetooth/tester/prj.conf index 58e8cdc34a1..b24eca84c6a 100644 --- a/tests/bluetooth/tester/prj.conf +++ b/tests/bluetooth/tester/prj.conf @@ -32,6 +32,7 @@ CONFIG_BT_ATT_RETRY_ON_SEC_ERR=n CONFIG_BT_GATT_DYNAMIC_DB=y CONFIG_BT_EXT_ADV=y CONFIG_BT_BUF_ACL_RX_SIZE=100 +CONFIG_BT_RX_STACK_SIZE=4096 CONFIG_BT_TINYCRYPT_ECC=y CONFIG_BT_TESTING=y diff --git a/tests/bluetooth/tester/src/btp.c b/tests/bluetooth/tester/src/btp.c index ced25b2210e..60f3bc1cbbd 100644 --- a/tests/bluetooth/tester/src/btp.c +++ b/tests/bluetooth/tester/src/btp.c @@ -50,6 +50,9 @@ static struct { size_t num; } service_handler[BTP_SERVICE_ID_MAX + 1]; +static struct net_buf_simple *rsp_buf = NET_BUF_SIMPLE(BTP_MTU); +static K_MUTEX_DEFINE(rsp_buf_mutex); + static void tester_send_with_index(uint8_t service, uint8_t opcode, uint8_t index, const uint8_t *data, size_t len); static void tester_rsp_with_index(uint8_t service, uint8_t opcode, uint8_t index, @@ -241,6 +244,34 @@ void tester_init(void) BTP_INDEX_NONE, NULL, 0); } +int tester_rsp_buffer_lock(void) +{ + if (k_mutex_lock(&rsp_buf_mutex, Z_FOREVER) != 0) { + LOG_ERR("Cannot lock rsp_ring_buf"); + + return -EACCES; + } + + return 0; +} + +void tester_rsp_buffer_unlock(void) +{ + k_mutex_unlock(&rsp_buf_mutex); +} + +void tester_rsp_buffer_free(void) +{ + net_buf_simple_init(rsp_buf, 0); +} + +void tester_rsp_buffer_allocate(size_t len, uint8_t **data) +{ + tester_rsp_buffer_free(); + + *data = net_buf_simple_add(rsp_buf, len); +} + static void tester_send_with_index(uint8_t service, uint8_t opcode, uint8_t index, const uint8_t *data, size_t len) { diff --git a/tests/bluetooth/tester/src/btp/btp.h b/tests/bluetooth/tester/src/btp/btp.h index 5c0384c0b9f..c7781932801 100644 --- a/tests/bluetooth/tester/src/btp/btp.h +++ b/tests/bluetooth/tester/src/btp/btp.h @@ -25,6 +25,12 @@ #include "btp_bap.h" #include "btp_has.h" #include "btp_csis.h" +#include "btp_micp.h" +#include "btp_mics.h" +#include "btp_ccp.h" +#include "btp_vcp.h" +#include "btp_cas.h" +#include "btp_mcp.h" #define BTP_MTU 1024 #define BTP_DATA_MAX_SIZE (BTP_MTU - sizeof(struct btp_hdr)) @@ -48,15 +54,23 @@ #define BTP_SERVICE_ID_ASCS 13 #define BTP_SERVICE_ID_BAP 14 #define BTP_SERVICE_ID_HAS 15 +#define BTP_SERVICE_ID_MICP 16 #define BTP_SERVICE_ID_CSIS 17 +#define BTP_SERVICE_ID_MICS 18 +#define BTP_SERVICE_ID_CCP 19 +#define BTP_SERVICE_ID_VCP 20 +#define BTP_SERVICE_ID_CAS 21 +#define BTP_SERVICE_ID_MCP 22 -#define BTP_SERVICE_ID_MAX BTP_SERVICE_ID_CSIS +#define BTP_SERVICE_ID_MAX BTP_SERVICE_ID_MCP #define BTP_STATUS_SUCCESS 0x00 #define BTP_STATUS_FAILED 0x01 #define BTP_STATUS_UNKNOWN_CMD 0x02 #define BTP_STATUS_NOT_READY 0x03 +#define BTP_STATUS_VAL(err) (err) ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS + /* TODO indicate delay response, should be removed when all commands are * converted to cmd+status+ev pattern */ diff --git a/tests/bluetooth/tester/src/btp/btp_aics.h b/tests/bluetooth/tester/src/btp/btp_aics.h index 41a52390591..8057f9a4a21 100644 --- a/tests/bluetooth/tester/src/btp/btp_aics.h +++ b/tests/bluetooth/tester/src/btp/btp_aics.h @@ -7,29 +7,139 @@ */ #include +#include /*AICS service */ +struct btp_aics_instance { + /** Number of Audio Input Control Service instances */ + uint8_t aics_cnt; + /** Array of pointers to Audio Input Control Service instances */ + struct bt_aics **aics; +}; + +extern struct bt_aics_cb aics_client_cb; +extern struct btp_aics_instance aics_client_instance; +extern struct btp_aics_instance aics_server_instance; +void btp_send_aics_state_ev(struct bt_conn *conn, uint8_t att_status, int8_t gain, uint8_t mute, + uint8_t mode); +void btp_send_gain_setting_properties_ev(struct bt_conn *conn, uint8_t att_status, uint8_t units, + int8_t minimum, int8_t maximum); +void btp_send_aics_input_type_event(struct bt_conn *conn, uint8_t att_status, uint8_t input_type); +void btp_send_aics_status_ev(struct bt_conn *conn, uint8_t att_status, bool active); +void btp_send_aics_description_ev(struct bt_conn *conn, uint8_t att_status, uint8_t data_len, + char *description); +void btp_send_aics_procedure_ev(struct bt_conn *conn, uint8_t att_status, uint8_t opcode); + #define BTP_AICS_READ_SUPPORTED_COMMANDS 0x01 struct btp_aics_read_supported_commands_rp { uint8_t data[0]; } __packed; +/* AICS client/server commands */ #define BTP_AICS_SET_GAIN 0x02 struct btp_aics_set_gain_cmd { + bt_addr_le_t address; int8_t gain; } __packed; #define BTP_AICS_MUTE 0x03 +struct btp_aics_mute_cmd { + bt_addr_le_t address; +} __packed; + #define BTP_AICS_UNMUTE 0x04 -#define BTP_AICS_MAN_GAIN 0x05 -#define BTP_AICS_AUTO_GAIN 0x06 -#define BTP_AICS_MAN_GAIN_ONLY 0x07 -#define BTP_AICS_AUTO_GAIN_ONLY 0x08 +struct btp_aics_unmute_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_AICS_MAN_GAIN_SET 0x05 +struct btp_aics_manual_gain_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_AICS_AUTO_GAIN_SET 0x06 +struct btp_aics_auto_gain_cmd { + bt_addr_le_t address; +} __packed; -#define BTP_AICS_DESCRIPTION 0x09 +#define BTP_AICS_SET_MAN_GAIN_ONLY 0x07 +#define BTP_AICS_SET_AUTO_GAIN_ONLY 0x08 +#define BTP_AICS_AUDIO_DESCRIPTION_SET 0x09 struct btp_aics_audio_desc_cmd { uint8_t desc_len; uint8_t desc[0]; } __packed; #define BTP_AICS_MUTE_DISABLE 0x0a +#define BTP_AICS_GAIN_SETTING_PROP_GET 0x0b +struct btp_aics_gain_setting_prop_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_AICS_TYPE_GET 0x0c +struct btp_aics_type_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_AICS_STATUS_GET 0x0d +struct btp_aics_status_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_AICS_STATE_GET 0x0e +struct btp_aics_state_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_AICS_DESCRIPTION_GET 0x0f +struct btp_aics_desc_cmd { + bt_addr_le_t address; +} __packed; + +/* AICS events */ +#define BTP_AICS_STATE_EV 0x80 +struct btp_aics_state_ev { + bt_addr_le_t address; + uint8_t att_status; + int8_t gain; + uint8_t mute; + uint8_t mode; +} __packed; + +#define BTP_GAIN_SETTING_PROPERTIES_EV 0x81 +struct btp_gain_setting_properties_ev { + bt_addr_le_t address; + uint8_t att_status; + uint8_t units; + int8_t minimum; + int8_t maximum; +} __packed; + +#define BTP_AICS_INPUT_TYPE_EV 0x82 +struct btp_aics_input_type_ev { + bt_addr_le_t address; + uint8_t att_status; + uint8_t input_type; +} __packed; + +#define BTP_AICS_STATUS_EV 0x83 +struct btp_aics_status_ev { + bt_addr_le_t address; + uint8_t att_status; + bool active; +} __packed; + +#define BTP_AICS_DESCRIPTION_EV 0x84 +struct btp_aics_description_ev { + bt_addr_le_t address; + uint8_t att_status; + uint8_t data_len; + char data[0]; +} __packed; + +#define BTP_AICS_PROCEDURE_EV 0x85 +struct btp_aics_procedure_ev { + bt_addr_le_t address; + uint8_t att_status; + uint8_t opcode; +} __packed; diff --git a/tests/bluetooth/tester/src/btp/btp_ascs.h b/tests/bluetooth/tester/src/btp/btp_ascs.h index a5968a919af..739e8c7d824 100644 --- a/tests/bluetooth/tester/src/btp/btp_ascs.h +++ b/tests/bluetooth/tester/src/btp/btp_ascs.h @@ -1,4 +1,4 @@ -/* btp_bap.h - Bluetooth tester headers */ +/* btp_ascs.h - Bluetooth tester headers */ /* * Copyright (c) 2023 Codecoup @@ -19,8 +19,8 @@ struct btp_ascs_configure_codec_cmd { uint8_t coding_format; uint16_t vid; uint16_t cid; - uint8_t ltvs_len; - uint8_t ltvs[0]; + uint8_t cc_ltvs_len; + uint8_t cc_ltvs[0]; } __packed; #define BTP_ASCS_CONFIGURE_QOS 0x03 diff --git a/tests/bluetooth/tester/src/btp/btp_bap.h b/tests/bluetooth/tester/src/btp/btp_bap.h index 2157d6c79fc..d094d536390 100644 --- a/tests/bluetooth/tester/src/btp/btp_bap.h +++ b/tests/bluetooth/tester/src/btp/btp_bap.h @@ -6,13 +6,15 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + /* BAP commands */ -#define BTP_BAP_READ_SUPPORTED_COMMANDS 0x01 +#define BTP_BAP_READ_SUPPORTED_COMMANDS 0x01 struct btp_bap_read_supported_commands_rp { uint8_t data[0]; } __packed; -#define BTP_BAP_DISCOVER 0x02 +#define BTP_BAP_DISCOVER 0x02 struct btp_bap_discover_cmd { bt_addr_le_t address; } __packed; @@ -20,7 +22,7 @@ struct btp_bap_discover_cmd { #define BTP_BAP_DISCOVERY_STATUS_SUCCESS 0x00 #define BTP_BAP_DISCOVERY_STATUS_FAILED 0x01 -#define BTP_BAP_SEND 0x03 +#define BTP_BAP_SEND 0x03 struct btp_bap_send_cmd { bt_addr_le_t address; uint8_t ase_id; @@ -32,14 +34,156 @@ struct btp_bap_send_rp { uint8_t data_len; } __packed; +#define BTP_BAP_BROADCAST_SOURCE_SETUP 0x04 +struct btp_bap_broadcast_source_setup_cmd { + uint8_t streams_per_subgroup; + uint8_t subgroups; + uint8_t sdu_interval[3]; + uint8_t framing; + uint16_t max_sdu; + uint8_t retransmission_num; + uint16_t max_transport_latency; + uint8_t presentation_delay[3]; + uint8_t coding_format; + uint16_t vid; + uint16_t cid; + uint8_t cc_ltvs_len; + uint8_t cc_ltvs[]; +} __packed; +struct btp_bap_broadcast_source_setup_rp { + uint32_t gap_settings; + uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE]; +} __packed; + +#define BTP_BAP_BROADCAST_SOURCE_RELEASE 0x05 +struct btp_bap_broadcast_source_release_cmd { + uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE]; +} __packed; + +#define BTP_BAP_BROADCAST_ADV_START 0x06 +struct btp_bap_broadcast_adv_start_cmd { + uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE]; +} __packed; + +#define BTP_BAP_BROADCAST_ADV_STOP 0x07 +struct btp_bap_broadcast_adv_stop_cmd { + uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE]; +} __packed; + +#define BTP_BAP_BROADCAST_SOURCE_START 0x08 +struct btp_bap_broadcast_source_start_cmd { + uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE]; +} __packed; + +#define BTP_BAP_BROADCAST_SOURCE_STOP 0x09 +struct btp_bap_broadcast_source_stop_cmd { + uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE]; +} __packed; + +#define BTP_BAP_BROADCAST_SINK_SETUP 0x0a +struct btp_bap_broadcast_sink_setup_cmd { +} __packed; + +#define BTP_BAP_BROADCAST_SINK_RELEASE 0x0b +struct btp_bap_broadcast_sink_release_cmd { +} __packed; + +#define BTP_BAP_BROADCAST_SCAN_START 0x0c +struct btp_bap_broadcast_scan_start_cmd { +} __packed; + +#define BTP_BAP_BROADCAST_SCAN_STOP 0x0d +struct btp_bap_broadcast_scan_stop_cmd { +} __packed; + +#define BTP_BAP_BROADCAST_SINK_SYNC 0x0e +struct btp_bap_broadcast_sink_sync_cmd { + bt_addr_le_t address; + uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE]; + uint8_t advertiser_sid; + uint16_t skip; + uint16_t sync_timeout; + uint8_t past_avail; + uint8_t src_id; +} __packed; + +#define BTP_BAP_BROADCAST_SINK_STOP 0x0f +struct btp_bap_broadcast_sink_stop_cmd { + bt_addr_le_t address; + uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE]; +} __packed; + +#define BTP_BAP_BROADCAST_SINK_BIS_SYNC 0x10 +struct btp_bap_broadcast_sink_bis_sync_cmd { + bt_addr_le_t address; + uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE]; + uint32_t requested_bis_sync; +} __packed; + +#define BTP_BAP_DISCOVER_SCAN_DELEGATORS 0x11 +struct btp_bap_discover_scan_delegators_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_BAP_BROADCAST_ASSISTANT_SCAN_START 0x12 +struct btp_bap_broadcast_assistant_scan_start_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_BAP_BROADCAST_ASSISTANT_SCAN_STOP 0x13 +struct btp_bap_broadcast_assistant_scan_stop_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_BAP_ADD_BROADCAST_SRC 0x14 +struct btp_bap_add_broadcast_src_cmd { + bt_addr_le_t address; + bt_addr_le_t broadcaster_address; + uint8_t advertiser_sid; + uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE]; + uint8_t padv_sync; + uint16_t padv_interval; + uint8_t num_subgroups; + uint8_t subgroups[0]; +} __packed; + +#define BTP_BAP_REMOVE_BROADCAST_SRC 0x15 +struct btp_bap_remove_broadcast_src_cmd { + bt_addr_le_t address; + uint8_t src_id; +} __packed; + +#define BTP_BAP_MODIFY_BROADCAST_SRC 0x16 +struct btp_bap_modify_broadcast_src_cmd { + bt_addr_le_t address; + uint8_t src_id; + uint8_t padv_sync; + uint16_t padv_interval; + uint8_t num_subgroups; + uint8_t subgroups[0]; +} __packed; + +#define BTP_BAP_SET_BROADCAST_CODE 0x17 +struct btp_bap_set_broadcast_code_cmd { + bt_addr_le_t address; + uint8_t src_id; + uint8_t broadcast_code[BT_AUDIO_BROADCAST_CODE_SIZE]; +} __packed; + +#define BTP_BAP_SEND_PAST 0x18 +struct btp_bap_send_past_cmd { + bt_addr_le_t address; + uint8_t src_id; +} __packed; + /* BAP events */ -#define BTP_BAP_EV_DISCOVERY_COMPLETED 0x80 +#define BTP_BAP_EV_DISCOVERY_COMPLETED 0x80 struct btp_bap_discovery_completed_ev { bt_addr_le_t address; uint8_t status; } __packed; -#define BTP_BAP_EV_CODEC_CAP_FOUND 0x81 +#define BTP_BAP_EV_CODEC_CAP_FOUND 0x81 struct btp_bap_codec_cap_found_ev { bt_addr_le_t address; uint8_t dir; @@ -50,17 +194,83 @@ struct btp_bap_codec_cap_found_ev { uint8_t channel_counts; } __packed; -#define BTP_BAP_EV_ASE_FOUND 0x82 +#define BTP_BAP_EV_ASE_FOUND 0x82 struct btp_ascs_ase_found_ev { bt_addr_le_t address; uint8_t dir; uint8_t ase_id; } __packed; -#define BTP_BAP_EV_STREAM_RECEIVED 0x83 +#define BTP_BAP_EV_STREAM_RECEIVED 0x83 struct btp_bap_stream_received_ev { bt_addr_le_t address; uint8_t ase_id; uint8_t data_len; - uint8_t data[0]; + uint8_t data[]; +} __packed; + +#define BTP_BAP_EV_BAA_FOUND 0x84 +struct btp_bap_baa_found_ev { + bt_addr_le_t address; + uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE]; + uint8_t advertiser_sid; + uint16_t padv_interval; +} __packed; + +#define BTP_BAP_EV_BIS_FOUND 0x85 +struct btp_bap_bis_found_ev { + bt_addr_le_t address; + uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE]; + uint8_t presentation_delay[3]; + uint8_t subgroup_id; + uint8_t bis_id; + uint8_t coding_format; + uint16_t vid; + uint16_t cid; + uint8_t cc_ltvs_len; + uint8_t cc_ltvs[]; +} __packed; + +#define BTP_BAP_EV_BIS_SYNCED 0x86 +struct btp_bap_bis_syned_ev { + bt_addr_le_t address; + uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE]; + uint8_t bis_id; +} __packed; + +#define BTP_BAP_EV_BIS_STREAM_RECEIVED 0x87 +struct btp_bap_bis_stream_received_ev { + bt_addr_le_t address; + uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE]; + uint8_t bis_id; + uint8_t data_len; + uint8_t data[]; +} __packed; + +#define BTP_BAP_EV_SCAN_DELEGATOR_FOUND 0x88 +struct btp_bap_scan_delegator_found_ev { + bt_addr_le_t address; +} __packed; + +#define BTP_BAP_EV_BROADCAST_RECEIVE_STATE 0x89 +struct btp_bap_broadcast_receive_state_ev { + bt_addr_le_t address; + uint8_t src_id; + bt_addr_le_t broadcaster_address; + uint8_t advertiser_sid; + uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE]; + uint8_t pa_sync_state; + uint8_t big_encryption; + uint8_t num_subgroups; + uint8_t subgroups[0]; +} __packed; + +#define BTP_BAP_EV_PA_SYNC_REQ 0x8a +struct btp_bap_pa_sync_req_ev { + bt_addr_le_t address; + uint8_t src_id; + uint8_t advertiser_sid; + uint8_t broadcast_id[BT_AUDIO_BROADCAST_ID_SIZE]; + uint8_t past_avail; + uint16_t pa_interval; } __packed; diff --git a/tests/bluetooth/tester/src/btp/btp_cas.h b/tests/bluetooth/tester/src/btp/btp_cas.h new file mode 100644 index 00000000000..a0e63342f97 --- /dev/null +++ b/tests/bluetooth/tester/src/btp/btp_cas.h @@ -0,0 +1,29 @@ +/* btp_cas.h - Bluetooth tester headers */ + +/* + * Copyright (c) 2023 Oticon + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* CAS commands */ +#define BTP_CAS_READ_SUPPORTED_COMMANDS 0x01 +struct btp_cas_read_supported_commands_rp { + uint8_t data[0]; +} __packed; + +#define BTP_CAS_SET_MEMBER_LOCK 0x02 +struct btp_cas_set_member_lock_cmd { + bt_addr_le_t address; + uint8_t lock; + uint8_t force; +} __packed; + +#define BTP_CAS_GET_MEMBER_RSI 0x03 +struct btp_cas_get_member_rsi_cmd { + bt_addr_le_t address; +} __packed; + +struct btp_cas_get_member_rsi_rp { + uint8_t rsi[BT_CSIP_RSI_SIZE]; +} __packed; diff --git a/tests/bluetooth/tester/src/btp/btp_ccp.h b/tests/bluetooth/tester/src/btp/btp_ccp.h new file mode 100644 index 00000000000..1792637de2e --- /dev/null +++ b/tests/bluetooth/tester/src/btp/btp_ccp.h @@ -0,0 +1,63 @@ +/* btp_ccp.h - Bluetooth tester headers */ + +/* + * Copyright (c) 2023 Oticon + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +/* CCP commands */ +#define BTP_CCP_READ_SUPPORTED_COMMANDS 0x01 +struct btp_ccp_read_supported_commands_rp { + uint8_t data[0]; +} __packed; + +#define BTP_CCP_DISCOVER_TBS 0x02 +struct btp_ccp_discover_tbs_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_CCP_ACCEPT_CALL 0x03 +struct btp_ccp_accept_call_cmd { + bt_addr_le_t address; + uint8_t inst_index; + uint8_t call_id; +} __packed; + +#define BTP_CCP_TERMINATE_CALL 0x04 +struct btp_ccp_terminate_call_cmd { + bt_addr_le_t address; + uint8_t inst_index; + uint8_t call_id; +} __packed; + +#define BTP_CCP_ORIGINATE_CALL 0x05 +struct btp_ccp_originate_call_cmd { + bt_addr_le_t address; + uint8_t inst_index; + uint8_t uri_len; + char uri[0]; +} __packed; + +#define BTP_CCP_READ_CALL_STATE 0x06 +struct btp_ccp_read_call_state_cmd { + bt_addr_le_t address; + uint8_t inst_index; +} __packed; + +/* CCP events */ +#define BTP_CCP_EV_DISCOVERED 0x80 +struct btp_ccp_discovered_ev { + int status; + uint8_t tbs_count; + bool gtbs_found; +} __packed; + +#define BTP_CCP_EV_CALL_STATES 0x81 +struct btp_ccp_call_states_ev { + int status; + uint8_t inst_index; + uint8_t call_count; + struct bt_tbs_client_call_state call_states[0]; +} __packed; diff --git a/tests/bluetooth/tester/src/btp/btp_gap.h b/tests/bluetooth/tester/src/btp/btp_gap.h index dee7d5be517..a727ffce4e4 100644 --- a/tests/bluetooth/tester/src/btp/btp_gap.h +++ b/tests/bluetooth/tester/src/btp/btp_gap.h @@ -101,6 +101,10 @@ struct btp_gap_set_bondable_rp { uint32_t current_settings; } __packed; +#define BTP_GAP_ADDR_TYPE_IDENTITY 0 +#define BTP_GAP_ADDR_TYPE_RESOLVABLE_PRIVATE 1 +#define BTP_GAP_ADDR_TYPE_NON_RESOLVABLE_PRIVATE 2 + #define BTP_GAP_START_ADVERTISING 0x0a struct btp_gap_start_advertising_cmd { uint8_t adv_data_len; @@ -233,7 +237,7 @@ struct btp_gap_set_mitm { #define BTP_GAP_SET_FILTER_LIST 0x1c struct btp_gap_set_filter_list { uint8_t cnt; - bt_addr_le_t addr[0]; + bt_addr_le_t addr[]; } __packed; #define BTP_GAP_SET_PRIVACY 0x1d @@ -249,6 +253,69 @@ struct btp_gap_set_extended_advertising_rp { uint32_t current_settings; } __packed; +#define BTP_GAP_PADV_CONFIGURE 0x22 +/* bitmap of flags*/ +#define BTP_GAP_PADV_INCLUDE_TX_POWER BIT(0) +struct btp_gap_padv_configure_cmd { + uint8_t flags; + uint16_t interval_min; + uint16_t interval_max; +} __packed; +struct btp_gap_padv_configure_rp { + uint32_t current_settings; +} __packed; + +#define BTP_GAP_PADV_START 0x23 +struct btp_gap_padv_start_cmd { + uint8_t flags; +} __packed; +struct btp_gap_padv_start_rp { + uint32_t current_settings; +} __packed; + +#define BTP_GAP_PADV_STOP 0x24 +struct btp_gap_padv_stop_cmd { +} __packed; +struct btp_gap_padv_stop_rp { + uint32_t current_settings; +} __packed; + +#define BTP_GAP_PADV_SET_DATA 0x25 +struct btp_gap_padv_set_data_cmd { + uint16_t data_len; + uint8_t data[]; +} __packed; + +#define BTP_GAP_PADV_CREATE_SYNC 0x26 +struct btp_gap_padv_create_sync_cmd { + bt_addr_le_t address; + uint8_t advertiser_sid; + uint16_t skip; + uint16_t sync_timeout; + uint8_t flags; +} __packed; + +#define BTP_GAP_PADV_SYNC_TRANSFER_SET_INFO 0x27 +struct btp_gap_padv_sync_transfer_set_info_cmd { + bt_addr_le_t address; + uint16_t service_data; +} __packed; + +#define BTP_GAP_PADV_SYNC_TRANSFER_START 0x28 +struct btp_gap_padv_sync_transfer_start_cmd { + uint16_t sync_handle; + bt_addr_le_t address; + uint16_t service_data; +} __packed; + +#define BTP_GAP_PADV_SYNC_TRANSFER_RECV 0x29 +struct btp_gap_padv_sync_transfer_recv_cmd { + bt_addr_le_t address; + uint16_t skip; + uint16_t sync_timeout; + uint8_t flags; +} __packed; + /* events */ #define BTP_GAP_EV_NEW_SETTINGS 0x80 struct btp_gap_new_settings_ev { @@ -337,3 +404,58 @@ struct btp_gap_bond_pairing_failed_ev { bt_addr_le_t address; uint8_t reason; } __packed; + +#define BTP_GAP_EV_PERIODIC_SYNC_ESTABLISHED 0x8d +struct btp_gap_ev_periodic_sync_established_ev { + bt_addr_le_t address; + uint16_t sync_handle; + uint8_t status; +} __packed; + +#define BTP_GAP_EV_PERIODIC_SYNC_LOST 0x8e +struct btp_gap_ev_periodic_sync_lost_ev { + uint16_t sync_handle; + uint8_t reason; +} __packed; + +#define BTP_GAP_EV_PERIODIC_REPORT 0x8f +struct btp_gap_ev_periodic_report_ev { + uint16_t sync_handle; + uint8_t tx_power; + uint8_t rssi; + uint8_t cte_type; + uint8_t data_status; + uint8_t data_len; + uint8_t data[]; +} __packed; + +#define BTP_GAP_EV_PERIODIC_TRANSFER_RECEIVED 0x90 +struct btp_gap_ev_periodic_transfer_received_ev { + uint16_t sync_handle; + uint8_t tx_power; + uint8_t rssi; + uint8_t cte_type; + uint8_t data_status; + uint8_t data_len; + uint8_t data[]; +} __packed; + +#if defined(CONFIG_BT_EXT_ADV) +struct bt_le_per_adv_param; +struct bt_le_per_adv_sync_param; +struct bt_le_adv_param; +struct bt_data; +struct bt_le_ext_adv *tester_gap_ext_adv_get(void); +struct bt_le_per_adv_sync *tester_gap_padv_get(void); +int tester_gap_create_adv_instance(struct bt_le_adv_param *param, uint8_t own_addr_type, + const struct bt_data *ad, size_t ad_len, + const struct bt_data *sd, size_t sd_len, uint32_t *settings); +int tester_gap_stop_ext_adv(void); +int tester_gap_start_ext_adv(void); +int tester_gap_padv_configure(const struct bt_le_per_adv_param *param); +int tester_gap_padv_set_data(struct bt_data *per_ad, uint8_t ad_len); +int tester_gap_padv_start(void); +int tester_gap_padv_stop(void); +int tester_gap_padv_create_sync(struct bt_le_per_adv_sync_param *create_params); +int tester_gap_padv_stop_sync(void); +#endif /* defined(CONFIG_BT_EXT_ADV) */ diff --git a/tests/bluetooth/tester/src/btp/btp_ias.h b/tests/bluetooth/tester/src/btp/btp_ias.h index 295aea2871a..a2af9d35f59 100644 --- a/tests/bluetooth/tester/src/btp/btp_ias.h +++ b/tests/bluetooth/tester/src/btp/btp_ias.h @@ -6,7 +6,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "zephyr/bluetooth/services/ias.h" +#include #include /* events */ diff --git a/tests/bluetooth/tester/src/btp/btp_mcp.h b/tests/bluetooth/tester/src/btp/btp_mcp.h new file mode 100644 index 00000000000..d9b7f84e410 --- /dev/null +++ b/tests/bluetooth/tester/src/btp/btp_mcp.h @@ -0,0 +1,291 @@ +/* btp_mcp.h - Bluetooth tester headers */ + +/* + * Copyright (c) 2023 Codecoup + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +/* MCP commands */ +#define BTP_MCP_READ_SUPPORTED_COMMANDS 0x01 +struct btp_mcp_read_supported_commands_rp { + uint8_t data[0]; +} __packed; + +#define BTP_MCP_DISCOVER 0x02 +struct btp_mcp_discover_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_MCP_TRACK_DURATION_READ 0x03 +struct btp_mcp_track_duration_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_MCP_TRACK_POSITION_READ 0x04 +struct btp_mcp_track_position_read_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_MCP_TRACK_POSITION_SET 0x05 +struct btp_mcp_track_position_set_cmd { + bt_addr_le_t address; + int32_t pos; +} __packed; + +#define BTP_MCP_PLAYBACK_SPEED_READ 0x06 +struct btp_mcp_playback_speed_read_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_MCP_PLAYBACK_SPEED_SET 0x07 +struct btp_mcp_playback_speed_set { + bt_addr_le_t address; + int8_t speed; +} __packed; + +#define BTP_MCP_SEEKING_SPEED_READ 0x08 +struct btp_mcp_seeking_speed_read_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_MCP_ICON_OBJ_ID_READ 0x09 +struct btp_mcp_icon_obj_id_read_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_MCP_NEXT_TRACK_OBJ_ID_READ 0x0a +struct btp_mcp_next_track_obj_id_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_MCP_NEXT_TRACK_OBJ_ID_SET 0x0b +struct btp_mcp_set_next_track_obj_id_cmd { + bt_addr_le_t address; + uint8_t id[BT_OTS_OBJ_ID_SIZE]; +} __packed; + +#define BTP_MCP_PARENT_GROUP_OBJ_ID_READ 0x0c +struct btp_mcp_parent_group_obj_id_read_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_MCP_CURRENT_GROUP_OBJ_ID_READ 0x0d +struct btp_mcp_current_group_obj_id_read_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_MCP_CURRENT_GROUP_OBJ_ID_SET 0x0e +struct btp_mcp_current_group_obj_id_set_cmd { + bt_addr_le_t address; + uint8_t id[BT_OTS_OBJ_ID_SIZE]; +} __packed; + +#define BTP_MCP_PLAYING_ORDER_READ 0x0f +struct btp_mcp_playing_order_read_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_MCP_PLAYING_ORDER_SET 0x10 +struct btp_mcp_playing_order_set_cmd { + bt_addr_le_t address; + uint8_t order; +} __packed; + +#define BTP_MCP_PLAYING_ORDERS_SUPPORTED_READ 0x11 +struct btp_mcp_playing_orders_supported_read_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_MCP_MEDIA_STATE_READ 0x12 +struct btp_mcp_media_state_read_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_MCP_OPCODES_SUPPORTED_READ 0x13 +struct btp_mcp_opcodes_supported_read_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_MCP_CONTENT_CONTROL_ID_READ 0x14 +struct btp_mcp_content_control_id_read_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_MCP_SEGMENTS_OBJ_ID_READ 0x15 +struct btp_mcp_segments_obj_id_read_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_MCP_CURRENT_TRACK_OBJ_ID_READ 0x16 +struct btp_mcp_current_track_obj_id_read_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_MCP_CURRENT_TRACK_OBJ_ID_SET 0x17 +struct btp_mcp_current_track_obj_id_set_cmd { + bt_addr_le_t address; + uint8_t id[BT_OTS_OBJ_ID_SIZE]; +} __packed; + +#define BTP_MCP_CMD_SEND 0x18 +struct btp_mcp_send_cmd { + bt_addr_le_t address; + uint8_t opcode; + uint8_t use_param; + int32_t param; +} __packed; + +#define BTP_MCP_CMD_SEARCH 0x19 +struct btp_mcp_search_cmd { + bt_addr_le_t address; + uint8_t type; + uint8_t param_len; + uint8_t param[]; +} __packed; + +/* MCP events */ +#define BTP_MCP_DISCOVERED_EV 0x80 +struct btp_mcp_discovered_ev { + bt_addr_le_t address; + uint8_t status; +} __packed; + +#define BTP_MCP_TRACK_DURATION_EV 0x81 +struct btp_mcp_track_duration_ev { + bt_addr_le_t address; + uint8_t status; + int32_t dur; +} __packed; + +#define BTP_MCP_TRACK_POSITION_EV 0x82 +struct btp_mcp_track_position_ev { + bt_addr_le_t address; + uint8_t status; + int32_t pos; +} __packed; + +#define BTP_MCP_PLAYBACK_SPEED_EV 0x83 +struct btp_mcp_playback_speed_ev { + bt_addr_le_t address; + uint8_t status; + int8_t speed; +} __packed; + +#define BTP_MCP_SEEKING_SPEED_EV 0x84 +struct btp_mcp_seeking_speed_ev { + bt_addr_le_t address; + uint8_t status; + int8_t speed; +} __packed; + +#define BTP_MCP_ICON_OBJ_ID_EV 0x85 +struct btp_mcp_icon_obj_id_ev { + bt_addr_le_t address; + uint8_t status; + uint8_t id[BT_OTS_OBJ_ID_SIZE]; +} __packed; + +#define BTP_MCP_NEXT_TRACK_OBJ_ID_EV 0x86 +struct btp_mcp_next_track_obj_id_ev { + bt_addr_le_t address; + uint8_t status; + uint8_t id[BT_OTS_OBJ_ID_SIZE]; +} __packed; + +#define BTP_MCP_PARENT_GROUP_OBJ_ID_EV 0x87 +struct btp_mcp_parent_group_obj_id_ev { + bt_addr_le_t address; + uint8_t status; + uint8_t id[BT_OTS_OBJ_ID_SIZE]; +} __packed; + +#define BTP_MCP_CURRENT_GROUP_OBJ_ID_EV 0x88 +struct btp_mcp_current_group_obj_id_ev { + bt_addr_le_t address; + uint8_t status; + uint8_t id[BT_OTS_OBJ_ID_SIZE]; +} __packed; + +#define BTP_MCP_PLAYING_ORDER_EV 0x89 +struct btp_mcp_playing_order_ev { + bt_addr_le_t address; + uint8_t status; + uint8_t order; +} __packed; + +#define BTP_MCP_PLAYING_ORDERS_SUPPORTED_EV 0x8a +struct btp_mcp_playing_orders_supported_ev { + bt_addr_le_t address; + uint8_t status; + uint16_t orders; +} __packed; + +#define BTP_MCP_MEDIA_STATE_EV 0x8b +struct btp_mcp_media_state_ev { + bt_addr_le_t address; + uint8_t status; + uint8_t state; +} __packed; + +#define BTP_MCP_OPCODES_SUPPORTED_EV 0x8c +struct btp_mcp_opcodes_supported_ev { + bt_addr_le_t address; + uint8_t status; + uint32_t opcodes; +} __packed; + +#define BTP_MCP_CONTENT_CONTROL_ID_EV 0x8d +struct btp_mcp_content_control_id_ev { + bt_addr_le_t address; + uint8_t status; + uint8_t ccid; +} __packed; + +#define BTP_MCP_SEGMENTS_OBJ_ID_EV 0x8e +struct btp_mcp_segments_obj_id_ev { + bt_addr_le_t address; + uint8_t status; + uint8_t id[BT_OTS_OBJ_ID_SIZE]; +} __packed; + +#define BTP_MCP_CURRENT_TRACK_OBJ_ID_EV 0x8f +struct btp_mcp_current_track_obj_id_ev { + bt_addr_le_t address; + uint8_t status; + uint8_t id[BT_OTS_OBJ_ID_SIZE]; +} __packed; + +#define BTP_MCP_MEDIA_CP_EV 0x90 +struct btp_mcp_media_cp_ev { + bt_addr_le_t address; + uint8_t status; + uint8_t opcode; + bool use_param; + int32_t param; +} __packed; + +#define BTP_MCP_SEARCH_CP_EV 0x91 +struct btp_mcp_search_cp_ev { + bt_addr_le_t address; + uint8_t status; + uint8_t param_len; + uint8_t search_type; + uint8_t param[]; +} __packed; + +#define BTP_MCP_NTF_EV 0x92 +struct btp_mcp_cmd_ntf_ev { + bt_addr_le_t address; + uint8_t status; + uint8_t requested_opcode; + uint8_t result_code; +} __packed; + +#define BTP_SCP_NTF_EV 0x93 +struct btp_scp_cmd_ntf_ev { + bt_addr_le_t address; + uint8_t status; + uint8_t result_code; +} __packed; diff --git a/tests/bluetooth/tester/src/btp/btp_micp.h b/tests/bluetooth/tester/src/btp/btp_micp.h new file mode 100644 index 00000000000..02220917b08 --- /dev/null +++ b/tests/bluetooth/tester/src/btp/btp_micp.h @@ -0,0 +1,49 @@ +/* btp_micp.h - Bluetooth tester headers */ + +/* + * Copyright (c) 2023 Codecoup + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* MICP commands */ +#define BTP_MICP_READ_SUPPORTED_COMMANDS 0x01 +struct btp_micp_read_supported_commands_rp { + uint8_t data[0]; +} __packed; + +#define BTP_MICP_CTLR_DISCOVER 0x02 +struct btp_micp_discover_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_MICP_CTLR_MUTE_READ 0x03 +struct btp_micp_mute_read_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_MICP_CTLR_MUTE 0x04 +struct btp_micp_mute_cmd { + bt_addr_le_t address; +} __packed; + +/* MICP events */ +#define BTP_MICP_DISCOVERED_EV 0x80 +struct btp_micp_discovered_ev { + bt_addr_le_t address; + uint8_t att_status; + uint16_t mute_handle; + uint16_t state_handle; + uint16_t gain_handle; + uint16_t type_handle; + uint16_t status_handle; + uint16_t control_handle; + uint16_t desc_handle; +} __packed; + +#define BTP_MICP_MUTE_STATE_EV 0x81 +struct btp_micp_mute_state_ev { + bt_addr_le_t address; + uint8_t att_status; + uint8_t mute; +} __packed; diff --git a/tests/bluetooth/tester/src/btp/btp_mics.h b/tests/bluetooth/tester/src/btp/btp_mics.h new file mode 100644 index 00000000000..924abb696c5 --- /dev/null +++ b/tests/bluetooth/tester/src/btp/btp_mics.h @@ -0,0 +1,23 @@ +/* btp_mics.h - Bluetooth tester headers */ + +/* + * Copyright (c) 2023 Codecoup + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* MICS commands */ +#define BTP_MICS_READ_SUPPORTED_COMMANDS 0x01 +struct btp_mics_read_supported_commands_rp { + uint8_t data[0]; +} __packed; + +#define BTP_MICS_DEV_MUTE_DISABLE 0x02 +#define BTP_MICS_DEV_MUTE_READ 0x03 +#define BTP_MICS_DEV_MUTE 0x04 +#define BTP_MICS_DEV_UNMUTE 0x05 + +#define BTP_MICS_MUTE_STATE_EV 0x80 +struct btp_mics_mute_state_ev { + uint8_t mute; +} __packed; diff --git a/tests/bluetooth/tester/src/btp/btp_pacs.h b/tests/bluetooth/tester/src/btp/btp_pacs.h index f0fab1553ea..7403feee762 100644 --- a/tests/bluetooth/tester/src/btp/btp_pacs.h +++ b/tests/bluetooth/tester/src/btp/btp_pacs.h @@ -1,4 +1,4 @@ -/* btp_bap.h - Bluetooth tester headers */ +/* btp_pacs.h - Bluetooth tester headers */ /* * Copyright (c) 2023 Codecoup @@ -19,7 +19,25 @@ struct btp_pacs_read_supported_commands_rp { #define BTP_PACS_CHARACTERISTIC_AVAILABLE_AUDIO_CONTEXTS 0x05 #define BTP_PACS_CHARACTERISTIC_SUPPORTED_AUDIO_CONTEXTS 0x06 -#define BTP_PACS_UPDATE_CHARACTERISTIC 0x02 +#define BTP_PACS_UPDATE_CHARACTERISTIC 0x02 struct btp_pacs_update_characteristic_cmd { uint8_t characteristic; } __packed; + +#define BTP_PACS_SET_LOCATION 0x03 +struct btp_pacs_set_location_cmd { + uint8_t dir; + uint32_t location; +} __packed; + +#define BTP_PACS_SET_AVAILABLE_CONTEXTS 0x04 +struct btp_pacs_set_available_contexts_cmd { + uint16_t sink_contexts; + uint16_t source_contexts; +} __packed; + +#define BTP_PACS_SET_SUPPORTED_CONTEXTS 0x05 +struct btp_pacs_set_supported_contexts_cmd { + uint16_t sink_contexts; + uint16_t source_contexts; +} __packed; diff --git a/tests/bluetooth/tester/src/btp/btp_vcp.h b/tests/bluetooth/tester/src/btp/btp_vcp.h new file mode 100644 index 00000000000..1b0a729d20e --- /dev/null +++ b/tests/bluetooth/tester/src/btp/btp_vcp.h @@ -0,0 +1,115 @@ +/* btp_vcp.h - Bluetooth tester headers */ + +/* + * Copyright (c) 2023 Codecoup + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#define BTP_VCP_READ_SUPPORTED_COMMANDS 0x01 +struct btp_vcp_read_supported_commands_rp { + uint8_t data[0]; +} __packed; + +#define BTP_VCP_VOL_CTLR_DISCOVER 0x02 +struct btp_vcp_discover_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_VCP_VOL_CTLR_STATE_READ 0x03 +struct btp_vcp_state_read_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_VCP_VOL_CTLR_FLAGS_READ 0x04 +struct btp_vcp_flags_read_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_VCP_VOL_CTLR_VOL_DOWN 0x05 +struct btp_vcp_ctlr_vol_down_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_VCP_VOL_CTLR_VOL_UP 0x06 +struct btp_vcp_ctlr_vol_up_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_VCP_VOL_CTLR_UNMUTE_VOL_DOWN 0x07 +struct btp_vcp_ctlr_unmute_vol_down_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_VCP_VOL_CTLR_UNMUTE_VOL_UP 0x08 +struct btp_vcp_ctlr_unmute_vol_up_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_VCP_VOL_CTLR_SET_VOL 0x09 +struct btp_vcp_ctlr_set_vol_cmd { + bt_addr_le_t address; + uint8_t volume; +} __packed; + +#define BTP_VCP_VOL_CTLR_UNMUTE 0x0a +struct btp_vcp_ctlr_unmute_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_VCP_VOL_CTLR_MUTE 0x0b +struct btp_vcp_ctlr_mute_cmd { + bt_addr_le_t address; +} __packed; + +/* VCP events */ +#define BTP_VCP_DISCOVERED_EV 0x80 +struct btp_vcp_discovered_ev { + bt_addr_le_t address; + uint8_t att_status; + struct { + uint16_t control_handle; + uint16_t flag_handle; + uint16_t state_handle; + } vcs_handles; + + struct { + uint16_t state_handle; + uint16_t location_handle; + uint16_t control_handle; + uint16_t desc_handle; + } vocs_handles; + + struct { + uint16_t state_handle; + uint16_t gain_handle; + uint16_t type_handle; + uint16_t status_handle; + uint16_t control_handle; + uint16_t desc_handle; + } aics_handles; +} __packed; + +#define BTP_VCP_STATE_EV 0x81 +struct btp_vcp_state_ev { + bt_addr_le_t address; + uint8_t att_status; + uint8_t volume; + uint8_t mute; +} __packed; + +#define BTP_VCP_FLAGS_EV 0x82 +struct btp_vcp_volume_flags_ev { + bt_addr_le_t address; + uint8_t att_status; + uint8_t flags; +} __packed; + +#define BTP_VCP_PROCEDURE_EV 0x83 +struct btp_vcp_procedure_ev { + bt_addr_le_t address; + uint8_t att_status; + uint8_t opcode; +} __packed; diff --git a/tests/bluetooth/tester/src/btp/btp_vocs.h b/tests/bluetooth/tester/src/btp/btp_vocs.h index cb9621c9454..e5beb6805fe 100644 --- a/tests/bluetooth/tester/src/btp/btp_vocs.h +++ b/tests/bluetooth/tester/src/btp/btp_vocs.h @@ -15,6 +15,7 @@ struct btp_vocs_read_supported_commands_rp { #define BTP_VOCS_UPDATE_LOC 0x02 struct btp_vocs_audio_loc_cmd { + bt_addr_le_t address; uint32_t loc; } __packed; @@ -23,3 +24,40 @@ struct btp_vocs_audio_desc_cmd { uint8_t desc_len; uint8_t desc[0]; } __packed; + +#define BTP_VOCS_STATE_GET 0x04 +struct btp_vocs_state_get_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_VOCS_LOCATION_GET 0x05 +struct btp_vocs_location_get_cmd { + bt_addr_le_t address; +} __packed; + +#define BTP_VOCS_OFFSET_STATE_SET 0x06 +struct btp_vocs_offset_set_cmd { + bt_addr_le_t address; + int16_t offset; +} __packed; + +#define BTP_VOCS_OFFSET_STATE_EV 0x80 +struct btp_vocs_offset_state_ev { + bt_addr_le_t address; + uint8_t att_status; + int16_t offset; +} __packed; + +#define BTP_VOCS_AUDIO_LOCATION_EV 0x81 +struct btp_vocs_audio_location_ev { + bt_addr_le_t address; + uint8_t att_status; + uint32_t location; +} __packed; + +#define BTP_VOCS_PROCEDURE_EV 0x82 +struct btp_vocs_procedure_ev { + bt_addr_le_t address; + uint8_t att_status; + uint8_t opcode; +} __packed; diff --git a/tests/bluetooth/tester/src/btp/bttester.h b/tests/bluetooth/tester/src/btp/bttester.h index 84d4722a913..ce8b1259a42 100644 --- a/tests/bluetooth/tester/src/btp/bttester.h +++ b/tests/bluetooth/tester/src/btp/bttester.h @@ -31,6 +31,10 @@ void tester_init(void); void tester_rsp(uint8_t service, uint8_t opcode, uint8_t status); void tester_rsp_full(uint8_t service, uint8_t opcode, const void *rsp, size_t len); void tester_event(uint8_t service, uint8_t opcode, const void *data, size_t len); +int tester_rsp_buffer_lock(void); +void tester_rsp_buffer_unlock(void); +void tester_rsp_buffer_free(void); +void tester_rsp_buffer_allocate(size_t len, uint8_t **data); /* Used to indicate that command length is variable and that validation will * be done in handler. @@ -95,3 +99,21 @@ uint8_t tester_unregister_has(void); uint8_t tester_init_csis(void); uint8_t tester_unregister_csis(void); + +uint8_t tester_init_micp(void); +uint8_t tester_unregister_micp(void); + +uint8_t tester_init_mics(void); +uint8_t tester_unregister_mics(void); + +uint8_t tester_init_ccp(void); +uint8_t tester_unregister_ccp(void); + +uint8_t tester_init_vcp(void); +uint8_t tester_unregister_vcp(void); + +uint8_t tester_init_cas(void); +uint8_t tester_unregister_cas(void); + +uint8_t tester_init_mcp(void); +uint8_t tester_unregister_mcp(void); diff --git a/tests/bluetooth/tester/src/btp_aics.c b/tests/bluetooth/tester/src/btp_aics.c new file mode 100644 index 00000000000..e3a1ad106df --- /dev/null +++ b/tests/bluetooth/tester/src/btp_aics.c @@ -0,0 +1,655 @@ +/* btp_aics.c - Bluetooth AICS Tester */ + +/* + * Copyright (c) 2023 Codecoup + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "bap_endpoint.h" +#include "btp/btp.h" + +#define LOG_MODULE_NAME bttester_aics +LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL); + +#define BT_AICS_MAX_INPUT_DESCRIPTION_SIZE 16 +#define BT_AICS_MAX_OUTPUT_DESCRIPTION_SIZE 16 + +struct btp_aics_instance aics_client_instance; +struct btp_aics_instance aics_server_instance; + +static struct net_buf_simple *rx_ev_buf = NET_BUF_SIMPLE(BT_AICS_MAX_INPUT_DESCRIPTION_SIZE + + sizeof(struct btp_aics_description_ev)); + +static uint8_t aics_supported_commands(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + struct btp_aics_read_supported_commands_rp *rp = rsp; + + /* octet 0 */ + tester_set_bit(rp->data, BTP_AICS_READ_SUPPORTED_COMMANDS); + tester_set_bit(rp->data, BTP_AICS_SET_GAIN); + tester_set_bit(rp->data, BTP_AICS_MUTE); + tester_set_bit(rp->data, BTP_AICS_UNMUTE); + tester_set_bit(rp->data, BTP_AICS_MAN_GAIN_SET); + tester_set_bit(rp->data, BTP_AICS_AUTO_GAIN_SET); + tester_set_bit(rp->data, BTP_AICS_SET_MAN_GAIN_ONLY); + + /* octet 1 */ + tester_set_bit(rp->data, BTP_AICS_SET_AUTO_GAIN_ONLY); + tester_set_bit(rp->data, BTP_AICS_AUDIO_DESCRIPTION_SET); + tester_set_bit(rp->data, BTP_AICS_MUTE_DISABLE); + tester_set_bit(rp->data, BTP_AICS_GAIN_SETTING_PROP_GET); + tester_set_bit(rp->data, BTP_AICS_TYPE_GET); + tester_set_bit(rp->data, BTP_AICS_STATUS_GET); + tester_set_bit(rp->data, BTP_AICS_STATE_GET); + + /* octet 2 */ + tester_set_bit(rp->data, BTP_AICS_DESCRIPTION_GET); + + *rsp_len = sizeof(*rp) + 2; + + return BTP_STATUS_SUCCESS; +} + +void btp_send_aics_state_ev(struct bt_conn *conn, uint8_t att_status, int8_t gain, uint8_t mute, + uint8_t mode) +{ + struct btp_aics_state_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.att_status = att_status; + ev.gain = gain; + ev.mute = mute; + ev.mode = mode; + + tester_event(BTP_SERVICE_ID_AICS, BTP_AICS_STATE_EV, &ev, sizeof(ev)); +} + +void btp_send_gain_setting_properties_ev(struct bt_conn *conn, uint8_t att_status, uint8_t units, + int8_t minimum, int8_t maximum) +{ + struct btp_gain_setting_properties_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.att_status = att_status; + ev.units = units; + ev.minimum = minimum; + ev.maximum = maximum; + + tester_event(BTP_SERVICE_ID_AICS, BTP_GAIN_SETTING_PROPERTIES_EV, &ev, sizeof(ev)); +} + +void btp_send_aics_input_type_event(struct bt_conn *conn, uint8_t att_status, uint8_t input_type) +{ + struct btp_aics_input_type_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.att_status = att_status; + ev.input_type = input_type; + + tester_event(BTP_SERVICE_ID_AICS, BTP_AICS_INPUT_TYPE_EV, &ev, sizeof(ev)); +} + +void btp_send_aics_status_ev(struct bt_conn *conn, uint8_t att_status, bool active) +{ + struct btp_aics_status_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.att_status = att_status; + ev.active = active; + + tester_event(BTP_SERVICE_ID_AICS, BTP_AICS_STATUS_EV, &ev, sizeof(ev)); +} + +void btp_send_aics_description_ev(struct bt_conn *conn, uint8_t att_status, uint8_t data_len, + char *description) +{ + struct btp_aics_description_ev *ev; + + net_buf_simple_init(rx_ev_buf, 0); + + ev = net_buf_simple_add(rx_ev_buf, sizeof(*ev)); + + bt_addr_le_copy(&ev->address, bt_conn_get_dst(conn)); + + ev->att_status = att_status; + ev->data_len = data_len; + memcpy(ev->data, description, data_len); + + tester_event(BTP_SERVICE_ID_AICS, BTP_AICS_DESCRIPTION_EV, ev, sizeof(*ev) + data_len); +} + +void btp_send_aics_procedure_ev(struct bt_conn *conn, uint8_t att_status, uint8_t opcode) +{ + struct btp_aics_procedure_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.att_status = att_status; + ev.opcode = opcode; + + tester_event(BTP_SERVICE_ID_AICS, BTP_AICS_PROCEDURE_EV, &ev, sizeof(ev)); +} + +static uint8_t aics_set_gain(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_aics_set_gain_cmd *cp = cmd; + + LOG_DBG("AICS set gain %d", cp->gain); + + if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) { + if (bt_aics_gain_set(aics_client_instance.aics[0], cp->gain) != 0) { + return BTP_STATUS_FAILED; + } + } else { + for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) { + if (bt_aics_gain_set(aics_server_instance.aics[i], cp->gain) != 0) { + return BTP_STATUS_FAILED; + } + } + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t aics_unmute(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_aics_unmute_cmd *cp = cmd; + + LOG_DBG("AICS Unmute"); + + if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) { + if (bt_aics_unmute(aics_client_instance.aics[0]) != 0) { + return BTP_STATUS_FAILED; + } + } else { + for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) { + if (bt_aics_unmute(aics_server_instance.aics[i]) != 0) { + return BTP_STATUS_FAILED; + } + } + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t aics_mute(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_aics_mute_cmd *cp = cmd; + + LOG_DBG("AICS Mute"); + + if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) { + if (bt_aics_mute(aics_client_instance.aics[0]) != 0) { + return BTP_STATUS_FAILED; + } + } else { + for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) { + if (bt_aics_mute(aics_server_instance.aics[i]) != 0) { + return BTP_STATUS_FAILED; + } + } + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t aics_state_get(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_aics_state_cmd *cp = cmd; + + LOG_DBG("AICS State"); + + if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) { + if (bt_aics_state_get(aics_client_instance.aics[0]) != 0) { + return BTP_STATUS_FAILED; + } + } else { + for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) { + if (bt_aics_state_get(aics_server_instance.aics[i]) != 0) { + return BTP_STATUS_FAILED; + } + } + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t aics_type_get(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_aics_type_cmd *cp = cmd; + + LOG_DBG("AICS Type"); + + if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) { + if (bt_aics_type_get(aics_client_instance.aics[0]) != 0) { + return BTP_STATUS_FAILED; + } + } else { + for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) { + if (bt_aics_type_get(aics_server_instance.aics[i]) != 0) { + return BTP_STATUS_FAILED; + } + } + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t aics_status_get(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_aics_status_cmd *cp = cmd; + + LOG_DBG("AICS Status"); + + if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) { + if (bt_aics_status_get(aics_client_instance.aics[0]) != 0) { + return BTP_STATUS_FAILED; + } + } else { + for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) { + if (bt_aics_status_get(aics_server_instance.aics[i]) != 0) { + return BTP_STATUS_FAILED; + } + } + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t aics_gain_setting_prop_get(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_aics_gain_setting_prop_cmd *cp = cmd; + + LOG_DBG("AICS Gain settings properties"); + + if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) { + if (bt_aics_gain_setting_get(aics_client_instance.aics[0]) != 0) { + return BTP_STATUS_FAILED; + } + } else { + for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) { + if (bt_aics_gain_setting_get(aics_server_instance.aics[i]) != 0) { + return BTP_STATUS_FAILED; + } + } + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t aics_man_gain_set(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_aics_manual_gain_cmd *cp = cmd; + + LOG_DBG("AICS set manual gain mode"); + + if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) { + if (bt_aics_manual_gain_set(aics_client_instance.aics[0]) != 0) { + return BTP_STATUS_FAILED; + } + } else { + for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) { + if (bt_aics_manual_gain_set(aics_server_instance.aics[i]) != 0) { + return BTP_STATUS_FAILED; + } + } + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t aics_auto_gain_set(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_aics_auto_gain_cmd *cp = cmd; + + LOG_DBG("AICS set automatic gain mode"); + + if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) { + if (bt_aics_automatic_gain_set(aics_client_instance.aics[0]) != 0) { + return BTP_STATUS_FAILED; + } + } else { + for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) { + if (bt_aics_automatic_gain_set(aics_server_instance.aics[i]) != 0) { + return BTP_STATUS_FAILED; + } + } + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t aics_set_man_gain_only(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + LOG_DBG("AICS manual gain only set"); + + for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) { + if (bt_aics_gain_set_manual_only(aics_server_instance.aics[i]) != 0) { + return BTP_STATUS_FAILED; + } + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t aics_set_auto_gain_only(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + LOG_DBG("AICS auto gain only set"); + + for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) { + if (bt_aics_gain_set_auto_only(aics_server_instance.aics[i]) != 0) { + return BTP_STATUS_FAILED; + } + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t aics_mute_disable(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + LOG_DBG("AICS disable mute"); + + for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) { + if (bt_aics_disable_mute(aics_server_instance.aics[i]) != 0) { + return BTP_STATUS_FAILED; + } + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t aics_desc_set(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_aics_audio_desc_cmd *cp = cmd; + char description[BT_AICS_MAX_INPUT_DESCRIPTION_SIZE]; + + LOG_DBG("AICS set description"); + + if (cmd_len < sizeof(*cp) || cmd_len != sizeof(*cp) + cp->desc_len) { + return BTP_STATUS_FAILED; + } + + if (cp->desc_len >= sizeof(description)) { + return BTP_STATUS_FAILED; + } + + if (cp->desc_len > (BT_AICS_MAX_INPUT_DESCRIPTION_SIZE - 1)) { + return BTP_STATUS_FAILED; + } + + memcpy(description, cp->desc, cp->desc_len); + description[cp->desc_len] = '\0'; + + for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) { + if (bt_aics_description_set(aics_server_instance.aics[i], description) != 0) { + return BTP_STATUS_FAILED; + } + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t aics_desc_get(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_aics_desc_cmd *cp = cmd; + + LOG_DBG("AICS Description"); + + if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) { + if (bt_aics_description_get(aics_client_instance.aics[0]) != 0) { + return BTP_STATUS_FAILED; + } + } else { + for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) { + if (bt_aics_description_get(aics_server_instance.aics[i]) != 0) { + return BTP_STATUS_FAILED; + } + } + } + + return BTP_STATUS_SUCCESS; +} + +static const struct btp_handler aics_handlers[] = { + { + .opcode = BTP_AICS_READ_SUPPORTED_COMMANDS, + .index = BTP_INDEX_NONE, + .expect_len = 0, + .func = aics_supported_commands, + }, + { + .opcode = BTP_AICS_SET_GAIN, + .expect_len = sizeof(struct btp_aics_set_gain_cmd), + .func = aics_set_gain, + }, + { + .opcode = BTP_AICS_MUTE, + .expect_len = sizeof(struct btp_aics_mute_cmd), + .func = aics_mute, + }, + { + .opcode = BTP_AICS_UNMUTE, + .expect_len = sizeof(struct btp_aics_unmute_cmd), + .func = aics_unmute, + }, + { + .opcode = BTP_AICS_GAIN_SETTING_PROP_GET, + .expect_len = sizeof(struct btp_aics_gain_setting_prop_cmd), + .func = aics_gain_setting_prop_get, + }, + { + .opcode = BTP_AICS_MUTE_DISABLE, + .expect_len = 0, + .func = aics_mute_disable, + }, + { + .opcode = BTP_AICS_MAN_GAIN_SET, + .expect_len = sizeof(struct btp_aics_manual_gain_cmd), + .func = aics_man_gain_set, + }, + { + .opcode = BTP_AICS_AUTO_GAIN_SET, + .expect_len = sizeof(struct btp_aics_auto_gain_cmd), + .func = aics_auto_gain_set, + }, + { + .opcode = BTP_AICS_SET_AUTO_GAIN_ONLY, + .expect_len = 0, + .func = aics_set_auto_gain_only, + }, + { + .opcode = BTP_AICS_SET_MAN_GAIN_ONLY, + .expect_len = 0, + .func = aics_set_man_gain_only, + }, + { + .opcode = BTP_AICS_AUDIO_DESCRIPTION_SET, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = aics_desc_set, + }, + { + .opcode = BTP_AICS_DESCRIPTION_GET, + .expect_len = sizeof(struct btp_aics_desc_cmd), + .func = aics_desc_get, + }, + { + .opcode = BTP_AICS_TYPE_GET, + .expect_len = sizeof(struct btp_aics_type_cmd), + .func = aics_type_get, + }, + { + .opcode = BTP_AICS_STATUS_GET, + .expect_len = sizeof(struct btp_aics_status_cmd), + .func = aics_status_get, + }, + { + .opcode = BTP_AICS_STATE_GET, + .expect_len = sizeof(struct btp_aics_state_cmd), + .func = aics_state_get, + }, +}; + +static void aics_state_cb(struct bt_aics *inst, int err, int8_t gain, uint8_t mute, uint8_t mode) +{ + struct bt_conn *conn; + + bt_aics_client_conn_get(inst, &conn); + + if (err) { + if (err < 0) { + err = BT_ATT_ERR_UNLIKELY; + } + btp_send_aics_state_ev(conn, err, 0, 0, 0); + } else { + btp_send_aics_state_ev(conn, 0, gain, mute, mode); + } + + LOG_DBG("AICS state callback (%d)", err); +} + +static void aics_gain_setting_cb(struct bt_aics *inst, int err, uint8_t units, int8_t minimum, + int8_t maximum) +{ + struct bt_conn *conn; + + bt_aics_client_conn_get(inst, &conn); + btp_send_gain_setting_properties_ev(conn, err, units, minimum, maximum); + + LOG_DBG("AICS gain setting callback (%d)", err); +} + +static void aics_input_type_cb(struct bt_aics *inst, int err, uint8_t input_type) +{ + struct bt_conn *conn; + + bt_aics_client_conn_get(inst, &conn); + btp_send_aics_input_type_event(conn, err, input_type); + + LOG_DBG("AICS input type callback (%d)", err); +} + +static void aics_status_cb(struct bt_aics *inst, int err, bool active) +{ + struct bt_conn *conn; + + bt_aics_client_conn_get(inst, &conn); + btp_send_aics_status_ev(conn, err, active); + + LOG_DBG("AICS status callback (%d)", err); +} + +static void aics_description_cb(struct bt_aics *inst, int err, char *description) +{ + struct bt_conn *conn; + uint8_t data_len = strlen(description); + + bt_aics_client_conn_get(inst, &conn); + btp_send_aics_description_ev(conn, err, data_len, description); + + LOG_DBG("AICS description callback (%d)", err); +} + +static void aics_set_gain_cb(struct bt_aics *inst, int err) +{ + struct bt_conn *conn; + + bt_aics_client_conn_get(inst, &conn); + + btp_send_aics_procedure_ev(conn, err, BTP_AICS_SET_GAIN); + + LOG_DBG("AICS set gain cb (%d)", err); +} + +static void aics_mute_cb(struct bt_aics *inst, int err) +{ + struct bt_conn *conn; + + bt_aics_client_conn_get(inst, &conn); + + btp_send_aics_procedure_ev(conn, err, BTP_AICS_MUTE); + + LOG_DBG("AICS mute cb (%d)", err); +} + +static void aics_unmute_cb(struct bt_aics *inst, int err) +{ + struct bt_conn *conn; + + bt_aics_client_conn_get(inst, &conn); + + btp_send_aics_procedure_ev(conn, err, BTP_AICS_UNMUTE); + + LOG_DBG("AICS unmute cb (%d)", err); +} + +static void aics_set_man_gain_cb(struct bt_aics *inst, int err) +{ + struct bt_conn *conn; + + bt_aics_client_conn_get(inst, &conn); + + btp_send_aics_procedure_ev(conn, err, BTP_AICS_MAN_GAIN_SET); + + LOG_DBG("AICS set manual gain cb (%d)", err); +} + +static void aics_set_auto_gain_cb(struct bt_aics *inst, int err) +{ + struct bt_conn *conn; + + bt_aics_client_conn_get(inst, &conn); + + btp_send_aics_procedure_ev(conn, err, BTP_AICS_AUTO_GAIN_SET); + + LOG_DBG("AICS set automatic gain cb (%d)", err); +} + +struct bt_aics_cb aics_client_cb = { + .state = aics_state_cb, + .gain_setting = aics_gain_setting_cb, + .type = aics_input_type_cb, + .status = aics_status_cb, + .description = aics_description_cb, +#if defined(CONFIG_BT_AICS_CLIENT) + .set_gain = aics_set_gain_cb, + .unmute = aics_unmute_cb, + .mute = aics_mute_cb, + .set_manual_mode = aics_set_man_gain_cb, + .set_auto_mode = aics_set_auto_gain_cb +#endif /* CONFIG_BT_AICS_CLIENT */ +}; + +uint8_t tester_init_aics(void) +{ + tester_register_command_handlers(BTP_SERVICE_ID_AICS, aics_handlers, + ARRAY_SIZE(aics_handlers)); + + return BTP_STATUS_SUCCESS; +} + +uint8_t tester_unregister_aics(void) +{ + return BTP_STATUS_SUCCESS; +} diff --git a/tests/bluetooth/tester/src/btp_bap.c b/tests/bluetooth/tester/src/btp_bap.c index 096950df83f..d6149d2c3ac 100644 --- a/tests/bluetooth/tester/src/btp_bap.c +++ b/tests/bluetooth/tester/src/btp_bap.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include "bap_endpoint.h" #include @@ -44,8 +46,6 @@ static const struct bt_audio_codec_cap vendor_codec_cap = BT_AUDIO_CODEC_CAP( struct audio_stream { struct bt_bap_stream stream; - uint8_t ase_id; - uint8_t conn_id; atomic_t seq_num; uint16_t last_req_seq_num; uint16_t last_sent_seq_num; @@ -53,10 +53,25 @@ struct audio_stream { size_t len_to_send; struct k_work_delayable audio_clock_work; struct k_work_delayable audio_send_work; - uint8_t cig_id; - uint8_t cis_id; - struct bt_bap_unicast_group **cig; bool already_sent; + bool broadcast; + + union { + /* Unicast */ + struct { + uint8_t ase_id; + uint8_t conn_id; + uint8_t cig_id; + uint8_t cis_id; + struct bt_bap_unicast_group **cig; + }; + + /* Broadcast */ + struct { + uint8_t bis_id; + bool bis_synced; + }; + }; }; #define MAX_STREAMS_COUNT MAX(CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT, \ @@ -72,7 +87,7 @@ struct audio_connection { struct bt_audio_codec_qos qos; struct bt_bap_ep *end_points[MAX_END_POINTS_COUNT]; size_t end_points_count; -} connections[CONFIG_BT_MAX_CONN]; +} connections[CONFIG_BT_MAX_CONN], broadcast_connection; static struct bt_bap_unicast_group *cigs[CONFIG_BT_ISO_MAX_CIG]; @@ -95,6 +110,25 @@ static void audio_send_timeout(struct k_work *work); K_THREAD_STACK_DEFINE(iso_data_thread_stack_area, ISO_DATA_THREAD_STACK_SIZE); static struct k_work_q iso_data_work_q; +static struct bt_bap_broadcast_source *broadcast_source; +static struct audio_connection *broadcaster; +static struct bt_bap_broadcast_sink *broadcast_sink; +static bt_addr_le_t broadcaster_addr; +static uint32_t broadcaster_broadcast_id; +static struct bt_bap_stream *sink_streams[MAX_STREAMS_COUNT]; +/* A mask for the maximum BIS we can sync to. +1 since the BIS indexes start from 1. */ +static const uint32_t bis_index_mask = BIT_MASK(MAX_STREAMS_COUNT + 1); +static uint32_t bis_index_bitfield; +static uint32_t requested_bis_sync; +#define INVALID_BROADCAST_ID (BT_AUDIO_BROADCAST_ID_MAX + 1) +#define SYNC_RETRY_COUNT 6 /* similar to retries for connections */ +#define PA_SYNC_SKIP 5 +/* Sample assumes that we only have a single Scan Delegator receive state */ +static const struct bt_bap_scan_delegator_recv_state *sink_recv_state; +static const struct bt_bap_scan_delegator_recv_state *broadcast_recv_state; +static uint8_t sink_broadcast_code[BT_AUDIO_BROADCAST_CODE_SIZE]; +static struct bt_bap_scan_delegator_subgroup delegator_subgroups[BROADCAST_SNK_SUBGROUP_CNT]; + static bool print_cb(struct bt_data *data, void *user_data) { const char *str = (const char *)user_data; @@ -110,17 +144,26 @@ static void print_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg) LOG_DBG("codec_cfg 0x%02x cid 0x%04x vid 0x%04x count %u", codec_cfg->id, codec_cfg->cid, codec_cfg->vid, codec_cfg->data_len); - if (codec_cfg->id == BT_AUDIO_CODEC_LC3_ID) { - /* LC3 uses the generic LTV format - other codecs might do as well */ - + if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) { enum bt_audio_location chan_allocation; + int ret; + + /* LC3 uses the generic LTV format - other codecs might do as well */ bt_audio_data_parse(codec_cfg->data, codec_cfg->data_len, print_cb, "data"); - LOG_DBG(" Frequency: %d Hz", bt_audio_codec_cfg_get_freq(codec_cfg)); - LOG_DBG(" Frame Duration: %d us", - bt_audio_codec_cfg_get_frame_duration_us(codec_cfg)); - if (bt_audio_codec_cfg_get_chan_allocation_val(codec_cfg, &chan_allocation) == 0) { + ret = bt_audio_codec_cfg_get_freq(codec_cfg); + if (ret > 0) { + LOG_DBG(" Frequency: %d Hz", bt_audio_codec_cfg_freq_to_freq_hz(ret)); + } + + ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg); + if (ret > 0) { + LOG_DBG(" Frame Duration: %d us", + bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret)); + } + + if (bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &chan_allocation) == 0) { LOG_DBG(" Channel allocation: 0x%x", chan_allocation); } @@ -140,7 +183,7 @@ static void print_codec_cap(const struct bt_audio_codec_cap *codec_cap) LOG_DBG("codec_cap 0x%02x cid 0x%04x vid 0x%04x count %zu", codec_cap->id, codec_cap->cid, codec_cap->vid, codec_cap->data_len); - if (codec_cap->id == BT_AUDIO_CODEC_LC3_ID) { + if (codec_cap->id == BT_HCI_CODING_FORMAT_LC3) { bt_audio_data_parse(codec_cap->data, codec_cap->data_len, print_cb, "data"); } else { LOG_HEXDUMP_DBG(codec_cap->data, codec_cap->data_len, "data"); @@ -203,10 +246,8 @@ static void btp_send_ascs_operation_completed_ev(struct bt_conn *conn, uint8_t a uint8_t opcode, uint8_t status) { struct btp_ascs_operation_completed_ev ev; - struct bt_conn_info info; - (void)bt_conn_get_info(conn, &info); - bt_addr_le_copy(&ev.address, info.le.dst); + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); ev.ase_id = ase_id; ev.opcode = opcode; ev.status = status; @@ -218,10 +259,8 @@ static void btp_send_ascs_operation_completed_ev(struct bt_conn *conn, uint8_t a static void btp_send_ascs_ase_state_changed_ev(struct bt_conn *conn, uint8_t ase_id, uint8_t state) { struct btp_ascs_ase_state_changed_ev ev; - struct bt_conn_info info; - (void)bt_conn_get_info(conn, &info); - bt_addr_le_copy(&ev.address, info.le.dst); + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); ev.ase_id = ase_id; ev.state = state; @@ -230,27 +269,26 @@ static void btp_send_ascs_ase_state_changed_ev(struct bt_conn *conn, uint8_t ase static int validate_codec_parameters(const struct bt_audio_codec_cfg *codec_cfg) { - int freq_hz; - int frame_duration_us; int frames_per_sdu; int octets_per_frame; int chan_allocation_err; enum bt_audio_location chan_allocation; + int ret; - freq_hz = bt_audio_codec_cfg_get_freq(codec_cfg); - frame_duration_us = bt_audio_codec_cfg_get_frame_duration_us(codec_cfg); chan_allocation_err = - bt_audio_codec_cfg_get_chan_allocation_val(codec_cfg, &chan_allocation); + bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &chan_allocation); octets_per_frame = bt_audio_codec_cfg_get_octets_per_frame(codec_cfg); frames_per_sdu = bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true); - if (freq_hz < 0) { - LOG_DBG("Error: Invalid codec frequency."); + ret = bt_audio_codec_cfg_get_freq(codec_cfg); + if (ret < 0) { + LOG_DBG("Error: Invalid codec frequency: %d", ret); return -EINVAL; } - if (frame_duration_us < 0) { - LOG_DBG("Error: Invalid frame duration."); + ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg); + if (ret < 0) { + LOG_DBG("Error: Invalid frame duration: %d", ret); return -EINVAL; } @@ -454,18 +492,15 @@ static void btp_send_stream_received_ev(struct bt_conn *conn, struct bt_bap_ep * uint8_t data_len, uint8_t *data) { struct btp_bap_stream_received_ev *ev; - struct bt_conn_info info; LOG_DBG("Stream received, ep %d, dir %d, len %d", ep->status.id, ep->dir, data_len); - (void)bt_conn_get_info(conn, &info); - net_buf_simple_init(rx_ev_buf, 0); ev = net_buf_simple_add(rx_ev_buf, sizeof(*ev)); - bt_addr_le_copy(&ev->address, info.le.dst); + bt_addr_le_copy(&ev->address, bt_conn_get_dst(conn)); ev->ase_id = ep->status.id; ev->data_len = data_len; @@ -474,6 +509,39 @@ static void btp_send_stream_received_ev(struct bt_conn *conn, struct bt_bap_ep * tester_event(BTP_SERVICE_ID_BAP, BTP_BAP_EV_STREAM_RECEIVED, ev, sizeof(*ev) + data_len); } +static void btp_send_bis_syced_ev(const bt_addr_le_t *address, uint32_t broadcast_id, + uint8_t bis_id) +{ + struct btp_bap_bis_syned_ev ev; + + bt_addr_le_copy(&ev.address, address); + sys_put_le24(broadcast_id, ev.broadcast_id); + ev.bis_id = bis_id; + + tester_event(BTP_SERVICE_ID_BAP, BTP_BAP_EV_BIS_SYNCED, &ev, sizeof(ev)); +} + +static void btp_send_bis_stream_received_ev(const bt_addr_le_t *address, uint32_t broadcast_id, + uint8_t bis_id, uint8_t data_len, uint8_t *data) +{ + struct btp_bap_bis_stream_received_ev *ev; + + LOG_DBG("Stream received, len %d", data_len); + + net_buf_simple_init(rx_ev_buf, 0); + + ev = net_buf_simple_add(rx_ev_buf, sizeof(*ev)); + + bt_addr_le_copy(&ev->address, address); + sys_put_le24(broadcast_id, ev->broadcast_id); + ev->bis_id = bis_id; + ev->data_len = data_len; + memcpy(ev->data, data, data_len); + + tester_event(BTP_SERVICE_ID_BAP, BTP_BAP_EV_BIS_STREAM_RECEIVED, ev, + sizeof(*ev) + data_len); +} + static void stream_configured(struct bt_bap_stream *stream, const struct bt_audio_codec_qos_pref *pref) { @@ -613,8 +681,14 @@ static void stream_started(struct bt_bap_stream *stream) K_USEC(a_stream->stream.qos->interval)); } - btp_send_ascs_ase_state_changed_ev(stream->conn, a_stream->ase_id, - stream->ep->status.state); + if (a_stream->broadcast) { + a_stream->bis_synced = true; + btp_send_bis_syced_ev(&broadcaster_addr, broadcaster_broadcast_id, + a_stream->bis_id); + } else { + btp_send_ascs_ase_state_changed_ev(stream->conn, a_stream->ase_id, + stream->ep->status.state); + } } static void stream_stopped(struct bt_bap_stream *stream, uint8_t reason) @@ -627,8 +701,12 @@ static void stream_stopped(struct bt_bap_stream *stream, uint8_t reason) k_work_cancel_delayable(&a_stream->audio_clock_work); k_work_cancel_delayable(&a_stream->audio_send_work); - btp_send_ascs_operation_completed_ev(stream->conn, a_stream->ase_id, - BT_ASCS_STOP_OP, BTP_STATUS_SUCCESS); + if (!a_stream->broadcast) { + btp_send_ascs_operation_completed_ev(stream->conn, a_stream->ase_id, + BT_ASCS_STOP_OP, BTP_STATUS_SUCCESS); + } else { + a_stream->bis_synced = false; + } } static void stream_recv(struct bt_bap_stream *stream, @@ -643,7 +721,13 @@ static void stream_recv(struct bt_bap_stream *stream, */ LOG_DBG("Incoming audio on stream %p len %u", stream, buf->len); a_stream->already_sent = true; - btp_send_stream_received_ev(stream->conn, stream->ep, buf->len, buf->data); + + if (a_stream->broadcast) { + btp_send_bis_stream_received_ev(&broadcaster_addr, broadcaster_broadcast_id, + a_stream->bis_id, buf->len, buf->data); + } else { + btp_send_stream_received_ev(stream->conn, stream->ep, buf->len, buf->data); + } } } @@ -668,10 +752,8 @@ static struct bt_bap_stream_ops stream_ops = { static void btp_send_discovery_completed_ev(struct bt_conn *conn, uint8_t status) { struct btp_bap_discovery_completed_ev ev; - struct bt_conn_info info; - (void) bt_conn_get_info(conn, &info); - bt_addr_le_copy(&ev.address, info.le.dst); + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); ev.status = status; tester_event(BTP_SERVICE_ID_BAP, BTP_BAP_EV_DISCOVERY_COMPLETED, &ev, sizeof(ev)); @@ -728,11 +810,9 @@ static void btp_send_pac_codec_found_ev(struct bt_conn *conn, enum bt_audio_dir dir) { struct btp_bap_codec_cap_found_ev ev; - struct bt_conn_info info; const uint8_t *data; - (void)bt_conn_get_info(conn, &info); - bt_addr_le_copy(&ev.address, info.le.dst); + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); ev.dir = dir; ev.coding_format = codec_cap->id; @@ -759,10 +839,8 @@ static void btp_send_pac_codec_found_ev(struct bt_conn *conn, static void btp_send_ase_found_ev(struct bt_conn *conn, struct bt_bap_ep *ep) { struct btp_ascs_ase_found_ev ev; - struct bt_conn_info info; - (void)bt_conn_get_info(conn, &info); - bt_addr_le_copy(&ev.address, info.le.dst); + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); ev.ase_id = ep->status.id; ev.dir = ep->dir; @@ -1006,38 +1084,32 @@ static void audio_send_timeout(struct k_work *work) /* TODO: Synchronize the Host clock with the Controller clock */ } - buf = net_buf_alloc(&tx_pool, K_NO_WAIT); - if (!buf) { - LOG_ERR("Cannot allocate net_buf. Dropping data."); - k_work_schedule_for_queue(&iso_data_work_q, dwork, - K_USEC(stream->stream.qos->interval)); - return; - } - - net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); - /* Get buffer within a ring buffer memory */ size = ring_buf_get_claim(&audio_ring_buf, &data, stream->stream.qos->sdu); - if (size != 0) { - net_buf_add_mem(buf, data, size); - } + if (size > 0) { + buf = net_buf_alloc(&tx_pool, K_NO_WAIT); + if (!buf) { + LOG_ERR("Cannot allocate net_buf. Dropping data."); + } else { + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); + net_buf_add_mem(buf, data, size); - /* Because the seq_num field of the audio_stream struct is atomic_val_t (4 bytes), - * let's allow an overflow and just cast it to uint16_t. - */ - stream->last_req_seq_num = (uint16_t)atomic_get(&stream->seq_num); + /* Because the seq_num field of the audio_stream struct is atomic_val_t + * (4 bytes), let's allow an overflow and just cast it to uint16_t. + */ + stream->last_req_seq_num = (uint16_t)atomic_get(&stream->seq_num); - LOG_DBG("Sending data to ASE: ase_id %d len %d seq %d", stream->stream.ep->status.id, - size, stream->last_req_seq_num); + LOG_DBG("Sending data to stream %p len %d seq %d", &stream->stream, size, + stream->last_req_seq_num); - err = bt_bap_stream_send(&stream->stream, buf, 0, BT_ISO_TIMESTAMP_NONE); - if (err != 0) { - LOG_ERR("Failed to send audio data to stream: ase_id %d dir %d seq %d err %d", - stream->ase_id, stream->stream.ep->dir, stream->last_req_seq_num, err); - net_buf_unref(buf); - } + err = bt_bap_stream_send(&stream->stream, buf, 0, BT_ISO_TIMESTAMP_NONE); + if (err != 0) { + LOG_ERR("Failed to send audio data to stream %p, err %d", + &stream->stream, err); + net_buf_unref(buf); + } + } - if (size != 0) { /* Free ring buffer memory */ err = ring_buf_get_finish(&audio_ring_buf, size); if (err != 0) { @@ -1086,209 +1158,1371 @@ static uint8_t bap_send(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } -static void connected(struct bt_conn *conn, uint8_t err) +static int setup_broadcast_source(uint8_t streams_per_subgroup, uint8_t subgroups, + struct bt_bap_broadcast_source **source) { - struct audio_connection *audio_conn; - char addr[BT_ADDR_LE_STR_LEN]; + int err; + struct bt_bap_broadcast_source_stream_param + stream_params[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT]; + struct bt_bap_broadcast_source_subgroup_param + subgroup_param[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT]; + struct bt_bap_broadcast_source_param create_param; + + if (streams_per_subgroup * subgroups > CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT || + subgroups > CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT) { + return -EINVAL; + } - bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + for (size_t i = 0U; i < subgroups; i++) { + subgroup_param[i].params_count = streams_per_subgroup; + subgroup_param[i].params = stream_params + i * streams_per_subgroup; + subgroup_param[i].codec_cfg = &broadcaster->codec_cfg; + } - if (err != 0) { - LOG_DBG("Failed to connect to %s (%u)", addr, err); - return; + for (size_t j = 0U; j < streams_per_subgroup; j++) { + broadcaster->streams[j].broadcast = true; + stream_params[j].stream = &broadcaster->streams[j].stream; + stream_params[j].data = NULL; + stream_params[j].data_len = 0U; + bt_bap_stream_cb_register(stream_params[j].stream, &stream_ops); } - LOG_DBG("Connected: %s", addr); + create_param.params_count = subgroups; + create_param.params = subgroup_param; + create_param.qos = &broadcaster->qos; + create_param.encryption = false; + create_param.packing = BT_ISO_PACKING_SEQUENTIAL; - audio_conn = &connections[bt_conn_index(conn)]; - memset(audio_conn, 0, sizeof(*audio_conn)); + LOG_DBG("Creating broadcast source with %zu subgroups with %zu streams", + subgroups, subgroups * streams_per_subgroup); - for (size_t i = 0; i < ARRAY_SIZE(audio_conn->streams); i++) { - bt_bap_stream_cb_register(&audio_conn->streams[i].stream, &stream_ops); + if (*source == NULL) { + err = bt_bap_broadcast_source_create(&create_param, source); + if (err != 0) { + LOG_DBG("Unable to create broadcast source: %d", err); + + return err; + } + } else { + err = bt_bap_broadcast_source_reconfig(*source, &create_param); + if (err != 0) { + LOG_DBG("Unable to reconfig broadcast source: %d", err); + + return err; + } } + + return 0; } -static void disconnected(struct bt_conn *conn, uint8_t reason) +static uint8_t broadcast_source_setup(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { - char addr[BT_ADDR_LE_STR_LEN]; + int err; + const struct btp_bap_broadcast_source_setup_cmd *cp = cmd; + struct btp_bap_broadcast_source_setup_rp *rp = rsp; + struct bt_le_adv_param *param = BT_LE_EXT_ADV_NCONN_NAME; + uint32_t broadcast_id; + uint32_t gap_settings = BIT(BTP_GAP_SETTINGS_DISCOVERABLE) | + BIT(BTP_GAP_SETTINGS_EXTENDED_ADVERTISING); - bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + NET_BUF_SIMPLE_DEFINE(ad_buf, BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE); + NET_BUF_SIMPLE_DEFINE(base_buf, 128); - LOG_DBG("Disconnected: %s (reason 0x%02x)", addr, reason); -} + /* Broadcast Audio Streaming Endpoint advertising data */ + struct bt_data base_ad; + struct bt_data per_ad; -static struct bt_conn_cb conn_callbacks = { - .connected = connected, - .disconnected = disconnected, -}; + LOG_DBG(""); -static struct bt_pacs_cap cap_sink = { - .codec_cap = &default_codec_cap, -}; + broadcaster->codec_cfg.id = cp->coding_format; + broadcaster->codec_cfg.vid = cp->vid; + broadcaster->codec_cfg.cid = cp->cid; + broadcaster->codec_cfg.data_len = cp->cc_ltvs_len; + memcpy(broadcaster->codec_cfg.data, cp->cc_ltvs, cp->cc_ltvs_len); + + broadcaster->qos.phy = BT_AUDIO_CODEC_QOS_2M; + broadcaster->qos.framing = cp->framing; + broadcaster->qos.rtn = cp->retransmission_num; + broadcaster->qos.latency = sys_le16_to_cpu(cp->max_transport_latency); + broadcaster->qos.interval = sys_get_le24(cp->sdu_interval); + broadcaster->qos.pd = sys_get_le24(cp->presentation_delay); + broadcaster->qos.sdu = sys_le16_to_cpu(cp->max_sdu); + + err = setup_broadcast_source(cp->streams_per_subgroup, cp->subgroups, &broadcast_source); + if (err != 0) { + LOG_DBG("Unable to setup broadcast source: %d", err); -static struct bt_pacs_cap cap_source = { - .codec_cap = &default_codec_cap, -}; + return BTP_STATUS_FAILED; + } -static struct bt_pacs_cap vendor_cap_sink = { - .codec_cap = &vendor_codec_cap, -}; + err = bt_bap_broadcast_source_get_id(broadcast_source, &broadcast_id); + if (err != 0) { + LOG_DBG("Unable to get broadcast ID: %d", err); -static struct bt_pacs_cap vendor_cap_source = { - .codec_cap = &vendor_codec_cap, -}; + return BTP_STATUS_FAILED; + } -static uint8_t ascs_supported_commands(const void *cmd, uint16_t cmd_len, - void *rsp, uint16_t *rsp_len) -{ - struct btp_ascs_read_supported_commands_rp *rp = rsp; + /* Setup extended advertising data */ + net_buf_simple_add_le16(&ad_buf, BT_UUID_BROADCAST_AUDIO_VAL); + net_buf_simple_add_le24(&ad_buf, broadcast_id); + base_ad.type = BT_DATA_SVC_DATA16; + base_ad.data_len = ad_buf.len; + base_ad.data = ad_buf.data; + err = tester_gap_create_adv_instance(param, BTP_GAP_ADDR_TYPE_IDENTITY, &base_ad, 1, NULL, + 0, &gap_settings); + if (err != 0) { + LOG_DBG("Failed to create extended advertising instance: %d", err); - /* octet 0 */ - tester_set_bit(rp->data, BTP_ASCS_READ_SUPPORTED_COMMANDS); + return BTP_STATUS_FAILED; + } + err = tester_gap_padv_configure(BT_LE_PER_ADV_PARAM(BT_GAP_PER_ADV_FAST_INT_MIN_2, + BT_GAP_PER_ADV_FAST_INT_MAX_2, + BT_LE_PER_ADV_OPT_USE_TX_POWER)); + if (err != 0) { + LOG_DBG("Failed to configure periodic advertising: %d", err); + + return BTP_STATUS_FAILED; + } + + err = bt_bap_broadcast_source_get_base(broadcast_source, &base_buf); + if (err != 0) { + LOG_DBG("Failed to get encoded BASE: %d\n", err); + + return BTP_STATUS_FAILED; + } + + per_ad.type = BT_DATA_SVC_DATA16; + per_ad.data_len = base_buf.len; + per_ad.data = base_buf.data; + err = tester_gap_padv_set_data(&per_ad, 1); + if (err != 0) { + return BTP_STATUS_FAILED; + } + + rp->gap_settings = gap_settings; + sys_put_le24(broadcast_id, rp->broadcast_id); *rsp_len = sizeof(*rp) + 1; return BTP_STATUS_SUCCESS; } -static int server_stream_config(struct bt_conn *conn, struct bt_bap_stream *stream, - struct bt_audio_codec_cfg *codec_cfg, - struct bt_audio_codec_qos_pref *qos) +static uint8_t broadcast_source_release(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { int err; - struct bt_bap_ep *ep; - err = bt_bap_unicast_server_config_ase(conn, stream, codec_cfg, qos); + LOG_DBG(""); + + err = bt_bap_broadcast_source_delete(broadcast_source); if (err != 0) { - return err; - } + LOG_DBG("Unable to delete broadcast source: %d", err); - print_codec_cfg(codec_cfg); + return BTP_STATUS_FAILED; + } - ep = stream->ep; - LOG_DBG("ASE Codec Config: ase_id %u dir %u", ep->status.id, ep->dir); - LOG_DBG("ASE Codec Config stream %p", stream); + memset(broadcaster, 0, sizeof(*broadcaster)); + broadcast_source = NULL; - return 0; + return BTP_STATUS_SUCCESS; } -static uint8_t client_add_ase_to_cis(struct audio_connection *audio_conn, uint8_t ase_id, - uint8_t cis_id, uint8_t cig_id) +static uint8_t broadcast_adv_start(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { - struct audio_stream *stream; + int err; + struct bt_le_ext_adv *ext_adv = tester_gap_ext_adv_get(); - if (cig_id >= CONFIG_BT_ISO_MAX_CIG || cis_id >= UNICAST_GROUP_STREAM_CNT) { + LOG_DBG(""); + + if (ext_adv == NULL) { return BTP_STATUS_FAILED; } - stream = stream_find(audio_conn, ase_id); - if (stream == NULL) { + err = tester_gap_start_ext_adv(); + if (err != 0) { return BTP_STATUS_FAILED; } - LOG_DBG("Added ASE %u to CIS %u at CIG %u", ase_id, cis_id, cig_id); + err = tester_gap_padv_start(); + if (err != 0) { + LOG_DBG("Unable to start periodic advertising: %d", err); - stream->cig = &cigs[cig_id]; - stream->cig_id = cig_id; - stream->cis_id = cis_id; + return BTP_STATUS_FAILED; + } - return 0; + return BTP_STATUS_SUCCESS; } -static int client_create_unicast_group(struct audio_connection *audio_conn, uint8_t ase_id, - uint8_t cig_id) +static uint8_t broadcast_adv_stop(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { int err; - struct bt_bap_unicast_group_stream_pair_param pair_params[MAX_STREAMS_COUNT]; - struct bt_bap_unicast_group_stream_param stream_params[MAX_STREAMS_COUNT]; - struct bt_bap_unicast_group_param param; - size_t stream_cnt = 0; - size_t src_cnt = 0; - size_t sink_cnt = 0; - size_t cis_cnt = 0; - (void)memset(pair_params, 0, sizeof(pair_params)); - (void)memset(stream_params, 0, sizeof(stream_params)); + LOG_DBG(""); - if (cig_id >= CONFIG_BT_ISO_MAX_CIG) { - return -EINVAL; + err = tester_gap_padv_stop(); + if (err != 0) { + return BTP_STATUS_FAILED; } - /* API does not allow to assign a CIG ID freely, so ensure we create groups - * in the right order. - */ - for (uint8_t i = 0; i < cig_id; i++) { - if (cigs[i] == NULL) { - return -EINVAL; - } + err = tester_gap_stop_ext_adv(); + if (err != 0) { + return BTP_STATUS_FAILED; } - /* Assign end points to CISes */ - for (size_t i = 0; i < MAX_STREAMS_COUNT; i++) { - struct audio_stream *a_stream = &audio_conn->streams[i]; - struct bt_bap_stream *stream = &a_stream->stream; - - if (stream == NULL || stream->ep == NULL || a_stream->cig == NULL || - a_stream->cig_id != cig_id) { - continue; - } - - stream_params[stream_cnt].stream = stream; - stream_params[stream_cnt].qos = &audio_conn->qos; - - if (stream->ep->dir == BT_AUDIO_DIR_SOURCE) { - if (pair_params[a_stream->cis_id].rx_param != NULL) { - return -EINVAL; - } + return BTP_STATUS_SUCCESS; +} - pair_params[a_stream->cis_id].rx_param = &stream_params[stream_cnt]; - src_cnt++; - } else { - if (pair_params[a_stream->cis_id].tx_param != NULL) { - return -EINVAL; - } +static uint8_t broadcast_source_start(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + struct bt_le_ext_adv *ext_adv = tester_gap_ext_adv_get(); - pair_params[a_stream->cis_id].tx_param = &stream_params[stream_cnt]; - sink_cnt++; - } + LOG_DBG(""); - stream_cnt++; + if (ext_adv == NULL) { + return BTP_STATUS_FAILED; } - /* Count CISes to be established */ - for (size_t i = 0; i < MAX_STREAMS_COUNT; i++) { - if (pair_params[i].tx_param == NULL && pair_params[i].rx_param == NULL) { - /* No gaps allowed */ - break; - } + err = bt_bap_broadcast_source_start(broadcast_source, ext_adv); + if (err != 0) { + LOG_DBG("Unable to start broadcast source: %d", err); - cis_cnt++; + return BTP_STATUS_FAILED; } - /* Make sure there are no gaps in the pair_params */ - if (cis_cnt == 0 || cis_cnt < MAX(sink_cnt, src_cnt)) { - return -EINVAL; - } + return BTP_STATUS_SUCCESS; +} - param.params = pair_params; - param.params_count = cis_cnt; - param.packing = BT_ISO_PACKING_SEQUENTIAL; +static uint8_t broadcast_source_stop(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; - LOG_DBG("Creating unicast group"); - err = bt_bap_unicast_group_create(¶m, &cigs[cig_id]); + LOG_DBG(""); + + err = bt_bap_broadcast_source_stop(broadcast_source); if (err != 0) { - LOG_DBG("Could not create unicast group (err %d)", err); - return -EINVAL; + LOG_DBG("Unable to stop broadcast source: %d", err); + + return BTP_STATUS_FAILED; } - return 0; + return BTP_STATUS_SUCCESS; } -static int client_configure_codec(struct audio_connection *audio_conn, struct bt_conn *conn, - uint8_t ase_id, struct bt_audio_codec_cfg *codec_cfg) +static int broadcast_sink_reset(void) { - int err; - struct bt_bap_ep *ep; + bis_index_bitfield = 0U; + sink_recv_state = NULL; + (void)memset(sink_broadcast_code, 0, sizeof(sink_broadcast_code)); + (void)memset(&broadcaster_addr, 0, sizeof(broadcaster_addr)); + (void)memset(broadcaster, 0, sizeof(*broadcaster)); + broadcaster_broadcast_id = INVALID_BROADCAST_ID; + + return 0; +} + +static void btp_send_baa_found_ev(const bt_addr_le_t *address, uint32_t broadcast_id, + uint8_t sid, uint16_t interval) +{ + struct btp_bap_baa_found_ev ev; + + bt_addr_le_copy(&ev.address, address); + sys_put_le24(broadcast_id, ev.broadcast_id); + ev.advertiser_sid = sid; + ev.padv_interval = sys_cpu_to_le16(interval); + + tester_event(BTP_SERVICE_ID_BAP, BTP_BAP_EV_BAA_FOUND, &ev, sizeof(ev)); +} + +static bool baa_check(struct bt_data *data, void *user_data) +{ + const struct bt_le_scan_recv_info *info = user_data; + char le_addr[BT_ADDR_LE_STR_LEN]; + struct bt_uuid_16 adv_uuid; + uint32_t broadcast_id; + + /* Parse the scanned Broadcast Audio Announcement */ + + if (data->type != BT_DATA_SVC_DATA16) { + return true; + } + + if (data->data_len < BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE) { + return true; + } + + if (!bt_uuid_create(&adv_uuid.uuid, data->data, BT_UUID_SIZE_16)) { + return true; + } + + if (bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_BROADCAST_AUDIO)) { + return true; + } + + broadcast_id = sys_get_le24(data->data + BT_UUID_SIZE_16); + + bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr)); + + LOG_DBG("Found BAA with ID 0x%06X, addr %s, sid 0x%02X, interval 0x%04X", + broadcast_id, le_addr, info->sid, info->interval); + + btp_send_baa_found_ev(info->addr, broadcast_id, info->sid, info->interval); + + /* Stop parsing */ + return false; +} + +static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info, struct net_buf_simple *ad) +{ + /* If 0 there is no periodic advertising. */ + if (info->interval != 0U) { + bt_data_parse(ad, baa_check, (void *)info); + } +} + +static struct bt_le_scan_cb bap_scan_cb = { + .recv = broadcast_scan_recv, +}; + +static void btp_send_bis_found_ev(const bt_addr_le_t *address, uint32_t broadcast_id, uint32_t pd, + uint8_t subgroup_index, uint8_t bis_index, + const struct bt_audio_codec_cfg *codec_cfg) +{ + struct btp_bap_bis_found_ev *ev; + + tester_rsp_buffer_lock(); + tester_rsp_buffer_allocate(sizeof(*ev) + codec_cfg->data_len, (uint8_t **)&ev); + + bt_addr_le_copy(&ev->address, address); + sys_put_le24(broadcast_id, ev->broadcast_id); + sys_put_le24(pd, ev->presentation_delay); + ev->subgroup_id = subgroup_index; + ev->bis_id = bis_index; + ev->coding_format = codec_cfg->id; + ev->vid = sys_cpu_to_le16(codec_cfg->vid); + ev->cid = sys_cpu_to_le16(codec_cfg->cid); + + ev->cc_ltvs_len = codec_cfg->data_len; + memcpy(ev->cc_ltvs, codec_cfg->data, ev->cc_ltvs_len); + + tester_event(BTP_SERVICE_ID_BAP, BTP_BAP_EV_BIS_FOUND, ev, + sizeof(*ev) + ev->cc_ltvs_len); + + tester_rsp_buffer_free(); + tester_rsp_buffer_unlock(); +} + +static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap_base *base) +{ + size_t stream_count = 0U; + uint32_t base_bis_index_bitfield = 0U; + const struct bt_audio_codec_cfg *codec_cfg; + + LOG_DBG(""); + + if (broadcaster_broadcast_id != sink->broadcast_id) { + return; + } + + LOG_DBG("Received BASE: broadcast sink %p subgroups %u", sink, base->subgroup_count); + + for (size_t i = 0U; i < base->subgroup_count; i++) { + for (size_t j = 0U; j < base->subgroups[i].bis_count; j++) { + const uint8_t index = base->subgroups[i].bis_data[j].index; + + codec_cfg = &base->subgroups[i].codec_cfg; + base_bis_index_bitfield |= BIT(index); + + if (stream_count < MAX_STREAMS_COUNT) { + broadcaster->streams[stream_count++].bis_id = index; + } + + btp_send_bis_found_ev(&broadcaster_addr, sink->broadcast_id, + sink->base.pd, i, index, codec_cfg); + } + } + + bis_index_bitfield = base_bis_index_bitfield & bis_index_mask; + LOG_DBG("bis_index_bitfield 0x%08x", bis_index_bitfield); +} + +static void syncable_cb(struct bt_bap_broadcast_sink *sink, bool encrypted) +{ + int err; + uint32_t index_bitfield; + + LOG_DBG("PA found, encrypted %d, requested_bis_sync %d", encrypted, requested_bis_sync); + + if (encrypted) { + /* Wait for Set Broadcast Code and start sync at broadcast_code_cb */ + return; + } + + if (!requested_bis_sync) { + /* No sync with any BIS was requested yet */ + return; + } + + index_bitfield = bis_index_bitfield & requested_bis_sync; + err = bt_bap_broadcast_sink_sync(broadcast_sink, index_bitfield, sink_streams, + sink_broadcast_code); + if (err != 0) { + LOG_DBG("Unable to sync to broadcast source: %d", err); + } +} + +static struct bt_bap_broadcast_sink_cb broadcast_sink_cbs = { + .base_recv = base_recv_cb, + .syncable = syncable_cb, +}; + +static void pa_timer_handler(struct k_work *work) +{ + if (broadcast_recv_state != NULL) { + enum bt_bap_pa_state pa_state; + + if (broadcast_recv_state->pa_sync_state == BT_BAP_PA_STATE_INFO_REQ) { + pa_state = BT_BAP_PA_STATE_NO_PAST; + } else { + pa_state = BT_BAP_PA_STATE_FAILED; + } + + bt_bap_scan_delegator_set_pa_state(broadcast_recv_state->src_id, + pa_state); + } + + LOG_DBG("PA timeout"); +} + +static K_WORK_DELAYABLE_DEFINE(pa_timer, pa_timer_handler); + +static void bap_pa_sync_synced_cb(struct bt_le_per_adv_sync *sync, + struct bt_le_per_adv_sync_synced_info *info) +{ + int err; + + LOG_DBG("Sync info: service_data 0x%04X", info->service_data); + + k_work_cancel_delayable(&pa_timer); + + err = bt_bap_broadcast_sink_create(sync, broadcaster_broadcast_id, &broadcast_sink); + if (err != 0) { + LOG_DBG("Failed to create broadcast sink: ID 0x%06X, err %d", + broadcaster_broadcast_id, err); + } +} + +static struct bt_le_per_adv_sync_cb bap_pa_sync_cb = { + .synced = bap_pa_sync_synced_cb, +}; + +static void btp_send_pas_sync_req_ev(struct bt_conn *conn, uint8_t src_id, + uint8_t advertiser_sid, uint32_t broadcast_id, + bool past_avail, uint16_t pa_interval) +{ + struct btp_bap_pa_sync_req_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + ev.src_id = src_id; + ev.advertiser_sid = advertiser_sid; + sys_put_le24(broadcast_id, ev.broadcast_id); + ev.past_avail = past_avail; + ev.pa_interval = sys_cpu_to_le16(pa_interval); + + tester_event(BTP_SERVICE_ID_BAP, BTP_BAP_EV_PA_SYNC_REQ, &ev, sizeof(ev)); +} + +static void btp_send_scan_delegator_found_ev(struct bt_conn *conn) +{ + struct btp_bap_scan_delegator_found_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + tester_event(BTP_SERVICE_ID_BAP, BTP_BAP_EV_SCAN_DELEGATOR_FOUND, &ev, sizeof(ev)); +} + +static void btp_send_broadcast_receive_state_ev(struct bt_conn *conn, + const struct bt_bap_scan_delegator_recv_state *state) +{ + struct btp_bap_broadcast_receive_state_ev *ev; + size_t len; + uint8_t *ptr; + + tester_rsp_buffer_lock(); + tester_rsp_buffer_allocate(sizeof(*ev) + BT_BAP_SCAN_DELEGATOR_MAX_SUBGROUPS * + sizeof(struct bt_bap_scan_delegator_subgroup), (uint8_t **)&ev); + + if (conn) { + bt_addr_le_copy(&ev->address, bt_conn_get_dst(conn)); + } else { + (void)memset(&ev->address, 0, sizeof(ev->address)); + } + + ev->src_id = state->src_id; + bt_addr_le_copy(&ev->broadcaster_address, &state->addr); + ev->advertiser_sid = state->adv_sid; + sys_put_le24(state->broadcast_id, ev->broadcast_id); + ev->pa_sync_state = state->pa_sync_state; + ev->big_encryption = state->encrypt_state; + ev->num_subgroups = state->num_subgroups; + + ptr = ev->subgroups; + for (uint8_t i = 0; i < ev->num_subgroups; i++) { + const struct bt_bap_scan_delegator_subgroup *subgroup = &state->subgroups[i]; + + sys_put_le32(subgroup->bis_sync >> 1, ptr); + ptr += sizeof(subgroup->bis_sync); + *ptr = subgroup->metadata_len; + ptr += sizeof(subgroup->metadata_len); + memcpy(ptr, subgroup->metadata, subgroup->metadata_len); + ptr += subgroup->metadata_len; + } + + len = sizeof(*ev) + ptr - ev->subgroups; + tester_event(BTP_SERVICE_ID_BAP, BTP_BAP_EV_BROADCAST_RECEIVE_STATE, ev, len); + + tester_rsp_buffer_free(); + tester_rsp_buffer_unlock(); +} + +static int pa_sync_past(struct bt_conn *conn, uint16_t sync_timeout) +{ + struct bt_le_per_adv_sync_transfer_param param = { 0 }; + int err; + + param.skip = PA_SYNC_SKIP; + param.timeout = sync_timeout; + + err = bt_le_per_adv_sync_transfer_subscribe(conn, ¶m); + if (err != 0) { + LOG_DBG("Could not do PAST subscribe: %d", err); + } else { + LOG_DBG("Syncing with PAST: %d", err); + (void)k_work_reschedule(&pa_timer, K_MSEC(param.timeout * 10)); + } + + return err; +} + +static int pa_sync_req_cb(struct bt_conn *conn, + const struct bt_bap_scan_delegator_recv_state *recv_state, + bool past_avail, uint16_t pa_interval) +{ + LOG_DBG("sync state %d ", recv_state->pa_sync_state); + + sink_recv_state = recv_state; + broadcast_recv_state = recv_state; + + btp_send_pas_sync_req_ev(conn, recv_state->src_id, recv_state->adv_sid, + recv_state->broadcast_id, past_avail, pa_interval); + + return 0; +} + +static int pa_sync_term_req_cb(struct bt_conn *conn, + const struct bt_bap_scan_delegator_recv_state *recv_state) +{ + LOG_DBG(""); + + sink_recv_state = recv_state; + + tester_gap_padv_stop_sync(); + + return 0; +} + +static void broadcast_code_cb(struct bt_conn *conn, + const struct bt_bap_scan_delegator_recv_state *recv_state, + const uint8_t broadcast_code[BT_AUDIO_BROADCAST_CODE_SIZE]) +{ + int err; + uint32_t index_bitfield; + + LOG_DBG("Broadcast code received for %p", recv_state); + + sink_recv_state = recv_state; + + (void)memcpy(sink_broadcast_code, broadcast_code, BT_AUDIO_BROADCAST_CODE_SIZE); + + if (!requested_bis_sync) { + return; + } + + index_bitfield = bis_index_bitfield & requested_bis_sync; + err = bt_bap_broadcast_sink_sync(broadcast_sink, index_bitfield, sink_streams, + sink_broadcast_code); + if (err != 0) { + LOG_DBG("Unable to sync to broadcast source: %d", err); + } +} + +static int bis_sync_req_cb(struct bt_conn *conn, + const struct bt_bap_scan_delegator_recv_state *recv_state, + const uint32_t bis_sync_req[BT_BAP_SCAN_DELEGATOR_MAX_SUBGROUPS]) +{ + bool bis_synced = false; + + LOG_DBG("BIS sync request received for %p: 0x%08x", recv_state, bis_sync_req[0]); + + for (int i = 0; i < MAX_STREAMS_COUNT; i++) { + if (broadcaster->streams[i].bis_synced) { + bis_synced = true; + break; + } + } + + /* We only care about a single subgroup in this sample */ + if (bis_synced) { + /* If the BIS sync request is received while we are already + * synced, it means that the requested BIS sync has changed. + */ + int err; + + /* The stream stopped callback will be called as part of this, + * and we do not need to wait for any events from the + * controller. Thus, when this returns, the `bis_synced` + * is back to false. + */ + err = bt_bap_broadcast_sink_stop(broadcast_sink); + if (err != 0) { + LOG_DBG("Failed to stop Broadcast Sink: %d", err); + + return err; + } + } + + requested_bis_sync = bis_sync_req[0]; + broadcaster_broadcast_id = recv_state->broadcast_id; + + return 0; +} + +static void recv_state_updated_cb(struct bt_conn *conn, + const struct bt_bap_scan_delegator_recv_state *recv_state) +{ + LOG_DBG("Receive state with ID %u updated", recv_state->src_id); + + btp_send_broadcast_receive_state_ev(conn, recv_state); +} + +static struct bt_bap_scan_delegator_cb scan_delegator_cbs = { + .recv_state_updated = recv_state_updated_cb, + .pa_sync_req = pa_sync_req_cb, + .pa_sync_term_req = pa_sync_term_req_cb, + .broadcast_code = broadcast_code_cb, + .bis_sync_req = bis_sync_req_cb, +}; + +static uint8_t broadcast_sink_setup(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + + LOG_DBG(""); + + err = broadcast_sink_reset(); + if (err != 0) { + return BTP_STATUS_FAILED; + } + + for (size_t i = 0U; i < MAX_STREAMS_COUNT; i++) { + broadcaster->streams[i].broadcast = true; + sink_streams[i] = &broadcaster->streams[i].stream; + sink_streams[i]->ops = &stream_ops; + } + + /* For Scan Delegator role */ + bt_bap_scan_delegator_register_cb(&scan_delegator_cbs); + + /* For Broadcast Sink role */ + bt_bap_broadcast_sink_register_cb(&broadcast_sink_cbs); + bt_le_per_adv_sync_cb_register(&bap_pa_sync_cb); + + /* For Broadcast Sink or Broadcast Assistant role */ + bt_le_scan_cb_register(&bap_scan_cb); + + return BTP_STATUS_SUCCESS; +} + +static uint8_t broadcast_sink_release(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + + LOG_DBG(""); + + err = broadcast_sink_reset(); + if (err != 0) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t broadcast_scan_start(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + + LOG_DBG(""); + + err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, NULL); + if (err != 0 && err != -EALREADY) { + LOG_DBG("Unable to start scan for broadcast sources: %d", err); + + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t broadcast_scan_stop(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + + LOG_DBG(""); + + err = bt_le_scan_stop(); + if (err != 0) { + LOG_DBG("Failed to stop scan, %d", err); + + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t broadcast_sink_sync(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + struct bt_conn *conn; + const struct btp_bap_broadcast_sink_sync_cmd *cp = cmd; + struct bt_le_per_adv_sync_param create_params = {0}; + + LOG_DBG(""); + + broadcaster_broadcast_id = sys_get_le24(cp->broadcast_id); + bt_addr_le_copy(&broadcaster_addr, &cp->address); + + if (IS_ENABLED(CONFIG_BT_PER_ADV_SYNC_TRANSFER_RECEIVER) && cp->past_avail) { + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + return BTP_STATUS_FAILED; + } + + err = bt_bap_scan_delegator_set_pa_state(cp->src_id, BT_BAP_PA_STATE_INFO_REQ); + if (err != 0) { + LOG_DBG("Failed to set INFO_REQ state: %d", err); + } + + err = pa_sync_past(conn, cp->sync_timeout); + } else { + bt_addr_le_copy(&create_params.addr, &cp->address); + create_params.options = 0; + create_params.sid = cp->advertiser_sid; + create_params.skip = cp->skip; + create_params.timeout = cp->sync_timeout; + err = tester_gap_padv_create_sync(&create_params); + } + + if (err != 0) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t broadcast_sink_stop(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + + LOG_DBG(""); + + requested_bis_sync = 0; + + err = bt_bap_broadcast_sink_stop(broadcast_sink); + if (err != 0) { + LOG_DBG("Unable to sync to broadcast source: %d", err); + + return BTP_STATUS_FAILED; + } + + err = tester_gap_padv_stop_sync(); + if (err != 0) { + LOG_DBG("Failed to stop PA sync, %d", err); + + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t broadcast_sink_bis_sync(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + const struct btp_bap_broadcast_sink_bis_sync_cmd *cp = cmd; + + LOG_DBG(""); + + if (cp->requested_bis_sync == BT_BAP_BIS_SYNC_NO_PREF) { + requested_bis_sync = sys_le32_to_cpu(cp->requested_bis_sync); + } else { + /* For semantic purposes Zephyr API uses BIS Index bitfield + * where BIT(1) means BIS Index 1 + */ + requested_bis_sync = sys_le32_to_cpu(cp->requested_bis_sync) << 1; + } + + err = bt_bap_broadcast_sink_sync(broadcast_sink, requested_bis_sync, sink_streams, + sink_broadcast_code); + if (err != 0) { + LOG_DBG("Unable to sync to BISes, req_bis_sync %d, err %d", requested_bis_sync, + err); + + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static void bap_broadcast_assistant_discover_cb(struct bt_conn *conn, int err, + uint8_t recv_state_count) +{ + LOG_DBG("err %d", err); + + if (err != 0) { + LOG_DBG("BASS discover failed (%d)", err); + } else { + LOG_DBG("BASS discover done with %u recv states", recv_state_count); + + btp_send_scan_delegator_found_ev(conn); + } +} + +static void bap_broadcast_assistant_scan_cb(const struct bt_le_scan_recv_info *info, + uint32_t broadcast_id) +{ + char le_addr[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr)); + LOG_DBG("[DEVICE]: %s, broadcast_id 0x%06X, interval (ms) %u), SID 0x%x, RSSI %i", le_addr, + broadcast_id, BT_GAP_PER_ADV_INTERVAL_TO_MS(info->interval), info->sid, info->rssi); +} + +static void bap_broadcast_assistant_recv_state_cb(struct bt_conn *conn, int err, + const struct bt_bap_scan_delegator_recv_state *state) +{ + LOG_DBG("err: %d", err); + + if (err != 0 || state == NULL) { + return; + } + + btp_send_broadcast_receive_state_ev(conn, state); +} + +static void bap_broadcast_assistant_recv_state_removed_cb(struct bt_conn *conn, int err, + uint8_t src_id) +{ + LOG_DBG("err: %d", err); +} + +static void bap_broadcast_assistant_scan_start_cb(struct bt_conn *conn, int err) +{ + LOG_DBG("err: %d", err); +} + +static void bap_broadcast_assistant_scan_stop_cb(struct bt_conn *conn, int err) +{ + LOG_DBG("err: %d", err); +} + +static void bap_broadcast_assistant_add_src_cb(struct bt_conn *conn, int err) +{ + LOG_DBG("err: %d", err); +} + +static void bap_broadcast_assistant_mod_src_cb(struct bt_conn *conn, int err) +{ + LOG_DBG("err: %d", err); +} + +static void bap_broadcast_assistant_broadcast_code_cb(struct bt_conn *conn, int err) +{ + LOG_DBG("err: %d", err); +} + +static void bap_broadcast_assistant_rem_src_cb(struct bt_conn *conn, int err) +{ + LOG_DBG("err: %d", err); +} + +static struct bt_bap_broadcast_assistant_cb broadcast_assistant_cb = { + .discover = bap_broadcast_assistant_discover_cb, + .scan = bap_broadcast_assistant_scan_cb, + .recv_state = bap_broadcast_assistant_recv_state_cb, + .recv_state_removed = bap_broadcast_assistant_recv_state_removed_cb, + .scan_start = bap_broadcast_assistant_scan_start_cb, + .scan_stop = bap_broadcast_assistant_scan_stop_cb, + .add_src = bap_broadcast_assistant_add_src_cb, + .mod_src = bap_broadcast_assistant_mod_src_cb, + .broadcast_code = bap_broadcast_assistant_broadcast_code_cb, + .rem_src = bap_broadcast_assistant_rem_src_cb, +}; + +static uint8_t broadcast_discover_scan_delegators(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + struct bt_conn *conn; + const struct btp_bap_discover_scan_delegators_cmd *cp = cmd; + + LOG_DBG(""); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + return BTP_STATUS_FAILED; + } + + err = bt_bap_broadcast_assistant_discover(conn); + if (err != 0) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t broadcast_assistant_scan_start(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + struct bt_conn *conn; + const struct btp_bap_broadcast_assistant_scan_start_cmd *cp = cmd; + + LOG_DBG(""); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + return BTP_STATUS_FAILED; + } + + err = bt_bap_broadcast_assistant_scan_start(conn, true); + if (err != 0) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t broadcast_assistant_scan_stop(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + struct bt_conn *conn; + const struct btp_bap_broadcast_assistant_scan_stop_cmd *cp = cmd; + + LOG_DBG(""); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + return BTP_STATUS_FAILED; + } + + err = bt_bap_broadcast_assistant_scan_stop(conn); + if (err != 0) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t broadcast_assistant_add_src(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + const uint8_t *ptr; + struct bt_conn *conn; + const struct btp_bap_add_broadcast_src_cmd *cp = cmd; + struct bt_bap_broadcast_assistant_add_src_param param = { 0 }; + + LOG_DBG(""); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + return BTP_STATUS_FAILED; + } + + memset(delegator_subgroups, 0, sizeof(delegator_subgroups)); + bt_addr_le_copy(¶m.addr, &cp->broadcaster_address); + param.adv_sid = cp->advertiser_sid; + param.pa_sync = cp->padv_sync > 0 ? true : false; + param.broadcast_id = sys_get_le24(cp->broadcast_id); + param.pa_interval = sys_le16_to_cpu(cp->padv_interval); + param.num_subgroups = MIN(cp->num_subgroups, BROADCAST_SNK_SUBGROUP_CNT); + param.subgroups = delegator_subgroups; + + ptr = cp->subgroups; + for (uint8_t i = 0; i < param.num_subgroups; i++) { + struct bt_bap_scan_delegator_subgroup *subgroup = &delegator_subgroups[i]; + + subgroup->bis_sync = sys_get_le32(ptr); + ptr += sizeof(subgroup->bis_sync); + subgroup->metadata_len = *ptr; + ptr += sizeof(subgroup->metadata_len); + memcpy(subgroup->metadata, ptr, subgroup->metadata_len); + ptr += subgroup->metadata_len; + } + + err = bt_bap_broadcast_assistant_add_src(conn, ¶m); + if (err != 0) { + LOG_DBG("err %d", err); + + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t broadcast_assistant_remove_src(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + struct bt_conn *conn; + const struct btp_bap_remove_broadcast_src_cmd *cp = cmd; + + LOG_DBG(""); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + return BTP_STATUS_FAILED; + } + + err = bt_bap_broadcast_assistant_rem_src(conn, cp->src_id); + if (err != 0) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t broadcast_assistant_modify_src(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + const uint8_t *ptr; + struct bt_conn *conn; + const struct btp_bap_modify_broadcast_src_cmd *cp = cmd; + struct bt_bap_broadcast_assistant_mod_src_param param = { 0 }; + + LOG_DBG(""); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + return BTP_STATUS_FAILED; + } + + memset(delegator_subgroups, 0, sizeof(delegator_subgroups)); + param.src_id = cp->src_id; + param.pa_sync = cp->padv_sync > 0 ? true : false; + param.pa_interval = sys_le16_to_cpu(cp->padv_interval); + param.num_subgroups = MIN(cp->num_subgroups, BROADCAST_SNK_SUBGROUP_CNT); + param.subgroups = delegator_subgroups; + + ptr = cp->subgroups; + for (uint8_t i = 0; i < param.num_subgroups; i++) { + struct bt_bap_scan_delegator_subgroup *subgroup = &delegator_subgroups[i]; + + subgroup->bis_sync = sys_get_le32(ptr); + ptr += sizeof(subgroup->bis_sync); + subgroup->metadata_len = *ptr; + ptr += sizeof(subgroup->metadata_len); + memcpy(subgroup->metadata, ptr, subgroup->metadata_len); + ptr += subgroup->metadata_len; + } + + err = bt_bap_broadcast_assistant_mod_src(conn, ¶m); + if (err != 0) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t broadcast_assistant_set_broadcast_code(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + struct bt_conn *conn; + const struct btp_bap_set_broadcast_code_cmd *cp = cmd; + + LOG_DBG(""); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + return BTP_STATUS_FAILED; + } + + err = bt_bap_broadcast_assistant_set_broadcast_code(conn, cp->src_id, cp->broadcast_code); + if (err != 0) { + LOG_DBG("err %d", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t broadcast_assistant_send_past(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + uint16_t service_data; + struct bt_conn *conn; + struct bt_le_per_adv_sync *pa_sync; + const struct btp_bap_send_past_cmd *cp = cmd; + + LOG_DBG(""); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + return BTP_STATUS_FAILED; + } + + pa_sync = tester_gap_padv_get(); + if (!pa_sync) { + LOG_DBG("Could not send PAST to Scan Delegator"); + + return BTP_STATUS_FAILED; + } + + LOG_DBG("Sending PAST"); + + /* If octet 0 is set to 0, it means AdvA in PAST matches AdvA in ADV_EXT_IND. + * Octet 1 shall be set to Source_ID. + */ + service_data = cp->src_id << 8; + + err = bt_le_per_adv_sync_transfer(pa_sync, conn, service_data); + if (err != 0) { + LOG_DBG("Could not transfer periodic adv sync: %d", err); + + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static void connected(struct bt_conn *conn, uint8_t err) +{ + struct audio_connection *audio_conn; + char addr[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + if (err != 0) { + LOG_DBG("Failed to connect to %s (%u)", addr, err); + return; + } + + LOG_DBG("Connected: %s", addr); + + audio_conn = &connections[bt_conn_index(conn)]; + memset(audio_conn, 0, sizeof(*audio_conn)); + + for (size_t i = 0; i < ARRAY_SIZE(audio_conn->streams); i++) { + bt_bap_stream_cb_register(&audio_conn->streams[i].stream, &stream_ops); + } +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + LOG_DBG("Disconnected: %s (reason 0x%02x)", addr, reason); +} + +static struct bt_conn_cb conn_callbacks = { + .connected = connected, + .disconnected = disconnected, +}; + +static struct bt_pacs_cap cap_sink = { + .codec_cap = &default_codec_cap, +}; + +static struct bt_pacs_cap cap_source = { + .codec_cap = &default_codec_cap, +}; + +static struct bt_pacs_cap vendor_cap_sink = { + .codec_cap = &vendor_codec_cap, +}; + +static struct bt_pacs_cap vendor_cap_source = { + .codec_cap = &vendor_codec_cap, +}; + +static uint8_t ascs_supported_commands(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + struct btp_ascs_read_supported_commands_rp *rp = rsp; + + /* octet 0 */ + tester_set_bit(rp->data, BTP_ASCS_READ_SUPPORTED_COMMANDS); + + *rsp_len = sizeof(*rp) + 1; + + return BTP_STATUS_SUCCESS; +} + +static int server_stream_config(struct bt_conn *conn, struct bt_bap_stream *stream, + struct bt_audio_codec_cfg *codec_cfg, + struct bt_audio_codec_qos_pref *qos) +{ + int err; + struct bt_bap_ep *ep; + + err = bt_bap_unicast_server_config_ase(conn, stream, codec_cfg, qos); + if (err != 0) { + return err; + } + + print_codec_cfg(codec_cfg); + + ep = stream->ep; + LOG_DBG("ASE Codec Config: ase_id %u dir %u", ep->status.id, ep->dir); + LOG_DBG("ASE Codec Config stream %p", stream); + + return 0; +} + +static uint8_t client_add_ase_to_cis(struct audio_connection *audio_conn, uint8_t ase_id, + uint8_t cis_id, uint8_t cig_id) +{ + struct audio_stream *stream; + + if (cig_id >= CONFIG_BT_ISO_MAX_CIG || cis_id >= UNICAST_GROUP_STREAM_CNT) { + return BTP_STATUS_FAILED; + } + + stream = stream_find(audio_conn, ase_id); + if (stream == NULL) { + return BTP_STATUS_FAILED; + } + + LOG_DBG("Added ASE %u to CIS %u at CIG %u", ase_id, cis_id, cig_id); + + stream->cig = &cigs[cig_id]; + stream->cig_id = cig_id; + stream->cis_id = cis_id; + + return 0; +} + +static int client_create_unicast_group(struct audio_connection *audio_conn, uint8_t ase_id, + uint8_t cig_id) +{ + int err; + struct bt_bap_unicast_group_stream_pair_param pair_params[MAX_STREAMS_COUNT]; + struct bt_bap_unicast_group_stream_param stream_params[MAX_STREAMS_COUNT]; + struct bt_bap_unicast_group_param param; + size_t stream_cnt = 0; + size_t src_cnt = 0; + size_t sink_cnt = 0; + size_t cis_cnt = 0; + + (void)memset(pair_params, 0, sizeof(pair_params)); + (void)memset(stream_params, 0, sizeof(stream_params)); + + if (cig_id >= CONFIG_BT_ISO_MAX_CIG) { + return -EINVAL; + } + + /* API does not allow to assign a CIG ID freely, so ensure we create groups + * in the right order. + */ + for (uint8_t i = 0; i < cig_id; i++) { + if (cigs[i] == NULL) { + return -EINVAL; + } + } + + /* Assign end points to CISes */ + for (size_t i = 0; i < MAX_STREAMS_COUNT; i++) { + struct audio_stream *a_stream = &audio_conn->streams[i]; + struct bt_bap_stream *stream = &a_stream->stream; + + if (stream == NULL || stream->ep == NULL || a_stream->cig == NULL || + a_stream->cig_id != cig_id) { + continue; + } + + stream_params[stream_cnt].stream = stream; + stream_params[stream_cnt].qos = &audio_conn->qos; + + if (stream->ep->dir == BT_AUDIO_DIR_SOURCE) { + if (pair_params[a_stream->cis_id].rx_param != NULL) { + return -EINVAL; + } + + pair_params[a_stream->cis_id].rx_param = &stream_params[stream_cnt]; + src_cnt++; + } else { + if (pair_params[a_stream->cis_id].tx_param != NULL) { + return -EINVAL; + } + + pair_params[a_stream->cis_id].tx_param = &stream_params[stream_cnt]; + sink_cnt++; + } + + stream_cnt++; + } + + /* Count CISes to be established */ + for (size_t i = 0; i < MAX_STREAMS_COUNT; i++) { + if (pair_params[i].tx_param == NULL && pair_params[i].rx_param == NULL) { + /* No gaps allowed */ + break; + } + + cis_cnt++; + } + + /* Make sure there are no gaps in the pair_params */ + if (cis_cnt == 0 || cis_cnt < MAX(sink_cnt, src_cnt)) { + return -EINVAL; + } + + param.params = pair_params; + param.params_count = cis_cnt; + param.packing = BT_ISO_PACKING_SEQUENTIAL; + + LOG_DBG("Creating unicast group"); + err = bt_bap_unicast_group_create(¶m, &cigs[cig_id]); + if (err != 0) { + LOG_DBG("Could not create unicast group (err %d)", err); + return -EINVAL; + } + + return 0; +} + +static int client_configure_codec(struct audio_connection *audio_conn, struct bt_conn *conn, + uint8_t ase_id, struct bt_audio_codec_cfg *codec_cfg) +{ + int err; + struct bt_bap_ep *ep; struct audio_stream *stream; stream = stream_find(audio_conn, ase_id); @@ -1383,9 +2617,9 @@ static uint8_t ascs_configure_codec(const void *cmd, uint16_t cmd_len, codec_cfg->vid = cp->vid; codec_cfg->cid = cp->cid; - if (cp->ltvs_len != 0) { - codec_cfg->data_len = cp->ltvs_len; - memcpy(codec_cfg->data, cp->ltvs, cp->ltvs_len); + if (cp->cc_ltvs_len != 0) { + codec_cfg->data_len = cp->cc_ltvs_len; + memcpy(codec_cfg->data, cp->cc_ltvs, cp->cc_ltvs_len); } if (conn_info.role == BT_HCI_ROLE_CENTRAL) { @@ -1842,6 +3076,10 @@ static uint8_t pacs_supported_commands(const void *cmd, uint16_t cmd_len, /* octet 0 */ tester_set_bit(rp->data, BTP_PACS_READ_SUPPORTED_COMMANDS); + tester_set_bit(rp->data, BTP_PACS_UPDATE_CHARACTERISTIC); + tester_set_bit(rp->data, BTP_PACS_SET_LOCATION); + tester_set_bit(rp->data, BTP_PACS_SET_AVAILABLE_CONTEXTS); + tester_set_bit(rp->data, BTP_PACS_SET_SUPPORTED_CONTEXTS); *rsp_len = sizeof(*rp) + 1; @@ -1894,6 +3132,52 @@ static uint8_t pacs_update_characteristic(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } +static uint8_t pacs_set_location(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_pacs_set_location_cmd *cp = cmd; + int err; + + err = bt_pacs_set_location((enum bt_audio_dir)cp->dir, + (enum bt_audio_location)cp->location); + + return (err) ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS; +} + +static uint8_t pacs_set_available_contexts(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_pacs_set_available_contexts_cmd *cp = cmd; + int err; + + err = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SINK, + (enum bt_audio_context)cp->sink_contexts); + if (err) { + return BTP_STATUS_FAILED; + } + err = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SOURCE, + (enum bt_audio_context)cp->source_contexts); + + return (err) ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS; +} + +static uint8_t pacs_set_supported_contexts(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_pacs_set_supported_contexts_cmd *cp = cmd; + int err; + + err = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SINK, + (enum bt_audio_context)cp->sink_contexts); + if (err) { + return BTP_STATUS_FAILED; + } + err = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SOURCE, + (enum bt_audio_context)cp->source_contexts); + + return (err) ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS; +} + static const struct btp_handler pacs_handlers[] = { { .opcode = BTP_PACS_READ_SUPPORTED_COMMANDS, @@ -1906,6 +3190,21 @@ static const struct btp_handler pacs_handlers[] = { .expect_len = sizeof(struct btp_pacs_update_characteristic_cmd), .func = pacs_update_characteristic, }, + { + .opcode = BTP_PACS_SET_LOCATION, + .expect_len = sizeof(struct btp_pacs_set_location_cmd), + .func = pacs_set_location + }, + { + .opcode = BTP_PACS_SET_AVAILABLE_CONTEXTS, + .expect_len = sizeof(struct btp_pacs_set_available_contexts_cmd), + .func = pacs_set_available_contexts + }, + { + .opcode = BTP_PACS_SET_SUPPORTED_CONTEXTS, + .expect_len = sizeof(struct btp_pacs_set_supported_contexts_cmd), + .func = pacs_set_supported_contexts + } }; static uint8_t bap_supported_commands(const void *cmd, uint16_t cmd_len, @@ -1938,6 +3237,111 @@ static const struct btp_handler bap_handlers[] = { .expect_len = BTP_HANDLER_LENGTH_VARIABLE, .func = bap_send, }, + { + .opcode = BTP_BAP_BROADCAST_SOURCE_SETUP, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = broadcast_source_setup, + }, + { + .opcode = BTP_BAP_BROADCAST_SOURCE_RELEASE, + .expect_len = sizeof(struct btp_bap_broadcast_source_release_cmd), + .func = broadcast_source_release, + }, + { + .opcode = BTP_BAP_BROADCAST_ADV_START, + .expect_len = sizeof(struct btp_bap_broadcast_adv_start_cmd), + .func = broadcast_adv_start, + }, + { + .opcode = BTP_BAP_BROADCAST_ADV_STOP, + .expect_len = sizeof(struct btp_bap_broadcast_adv_stop_cmd), + .func = broadcast_adv_stop, + }, + { + .opcode = BTP_BAP_BROADCAST_SOURCE_START, + .expect_len = sizeof(struct btp_bap_broadcast_source_start_cmd), + .func = broadcast_source_start, + }, + { + .opcode = BTP_BAP_BROADCAST_SOURCE_STOP, + .expect_len = sizeof(struct btp_bap_broadcast_source_stop_cmd), + .func = broadcast_source_stop, + }, + { + .opcode = BTP_BAP_BROADCAST_SINK_SETUP, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = broadcast_sink_setup, + }, + { + .opcode = BTP_BAP_BROADCAST_SINK_RELEASE, + .expect_len = sizeof(struct btp_bap_broadcast_sink_release_cmd), + .func = broadcast_sink_release, + }, + { + .opcode = BTP_BAP_BROADCAST_SCAN_START, + .expect_len = sizeof(struct btp_bap_broadcast_scan_start_cmd), + .func = broadcast_scan_start, + }, + { + .opcode = BTP_BAP_BROADCAST_SCAN_STOP, + .expect_len = sizeof(struct btp_bap_broadcast_scan_stop_cmd), + .func = broadcast_scan_stop, + }, + { + .opcode = BTP_BAP_BROADCAST_SINK_SYNC, + .expect_len = sizeof(struct btp_bap_broadcast_sink_sync_cmd), + .func = broadcast_sink_sync, + }, + { + .opcode = BTP_BAP_BROADCAST_SINK_STOP, + .expect_len = sizeof(struct btp_bap_broadcast_sink_stop_cmd), + .func = broadcast_sink_stop, + }, + { + .opcode = BTP_BAP_BROADCAST_SINK_BIS_SYNC, + .expect_len = sizeof(struct btp_bap_broadcast_sink_bis_sync_cmd), + .func = broadcast_sink_bis_sync, + }, + { + .opcode = BTP_BAP_DISCOVER_SCAN_DELEGATORS, + .expect_len = sizeof(struct btp_bap_discover_scan_delegators_cmd), + .func = broadcast_discover_scan_delegators, + }, + { + .opcode = BTP_BAP_BROADCAST_ASSISTANT_SCAN_START, + .expect_len = sizeof(struct btp_bap_broadcast_assistant_scan_start_cmd), + .func = broadcast_assistant_scan_start, + }, + { + .opcode = BTP_BAP_BROADCAST_ASSISTANT_SCAN_STOP, + .expect_len = sizeof(struct btp_bap_broadcast_assistant_scan_stop_cmd), + .func = broadcast_assistant_scan_stop, + }, + { + .opcode = BTP_BAP_ADD_BROADCAST_SRC, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = broadcast_assistant_add_src, + }, + { + .opcode = BTP_BAP_REMOVE_BROADCAST_SRC, + .expect_len = sizeof(struct btp_bap_remove_broadcast_src_cmd), + .func = broadcast_assistant_remove_src, + }, + { + .opcode = BTP_BAP_MODIFY_BROADCAST_SRC, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = broadcast_assistant_modify_src, + }, + { + .opcode = BTP_BAP_SET_BROADCAST_CODE, + .expect_len = sizeof(struct btp_bap_set_broadcast_code_cmd), + .func = broadcast_assistant_set_broadcast_code, + }, + { + .opcode = BTP_BAP_SEND_PAST, + .expect_len = sizeof(struct btp_bap_send_past_cmd), + .func = broadcast_assistant_send_past, + }, }; uint8_t tester_init_pacs(void) @@ -1999,12 +3403,17 @@ uint8_t tester_init_bap(void) /* reset data */ (void)memset(connections, 0, sizeof(connections)); + broadcaster = &broadcast_connection; + err = bt_bap_unicast_client_register_cb(&unicast_client_cbs); if (err != 0) { LOG_DBG("Failed to register client callbacks: %d", err); return BTP_STATUS_FAILED; } + /* For Broadcast Assistant role */ + bt_bap_broadcast_assistant_register_cb(&broadcast_assistant_cb); + k_work_queue_init(&iso_data_work_q); k_work_queue_start(&iso_data_work_q, iso_data_thread_stack_area, K_THREAD_STACK_SIZEOF(iso_data_thread_stack_area), diff --git a/tests/bluetooth/tester/src/btp_cas.c b/tests/bluetooth/tester/src/btp_cas.c new file mode 100644 index 00000000000..feb64ea3323 --- /dev/null +++ b/tests/bluetooth/tester/src/btp_cas.c @@ -0,0 +1,106 @@ +/* btp_cas.c - Bluetooth CAS Tester */ + +/* + * Copyright (c) 2023 Oticon + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include "btp/btp.h" +#include "zephyr/sys/byteorder.h" +#include + +#include +#define LOG_MODULE_NAME bttester_cas +LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL); + +static struct bt_csip_set_member_svc_inst *csis_svc_inst; + +static uint8_t cas_supported_commands(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + struct btp_cas_read_supported_commands_rp *rp = rsp; + + /* octet 0 */ + tester_set_bit(rp->data, BTP_CAS_READ_SUPPORTED_COMMANDS); + tester_set_bit(rp->data, BTP_CAS_SET_MEMBER_LOCK); + tester_set_bit(rp->data, BTP_CAS_GET_MEMBER_RSI); + + *rsp_len = sizeof(*rp) + 1; + + return BTP_STATUS_SUCCESS; +} + +static uint8_t cas_set_member_lock(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_cas_set_member_lock_cmd *cp = cmd; + int err = -EINVAL; + + if (csis_svc_inst) { + err = bt_csip_set_member_lock(csis_svc_inst, cp->lock, cp->force); + } + + return BTP_STATUS_VAL(err); +} + +static uint8_t cas_get_member_rsi(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + struct btp_cas_get_member_rsi_rp *rp = rsp; + int err = -EINVAL; + + if (csis_svc_inst) { + err = bt_csip_set_member_generate_rsi(csis_svc_inst, rp->rsi); + } + *rsp_len = sizeof(*rp); + + return BTP_STATUS_VAL(err); +} + +static const struct btp_handler cas_handlers[] = { + { + .opcode = BTP_CAS_READ_SUPPORTED_COMMANDS, + .index = BTP_INDEX_NONE, + .expect_len = 0, + .func = cas_supported_commands + }, + { + .opcode = BTP_CAS_SET_MEMBER_LOCK, + .expect_len = sizeof(struct btp_cas_set_member_lock_cmd), + .func = cas_set_member_lock + }, + { + .opcode = BTP_CAS_GET_MEMBER_RSI, + .expect_len = sizeof(struct btp_cas_get_member_rsi_cmd), + .func = cas_get_member_rsi + } +}; + +uint8_t tester_init_cas(void) +{ + tester_register_command_handlers(BTP_SERVICE_ID_CAS, cas_handlers, + ARRAY_SIZE(cas_handlers)); + +#if defined(CONFIG_BT_CAP_ACCEPTOR) && defined(CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER) + struct bt_csip_set_member_register_param register_params = { + .set_size = 2, + .set_sirk = { 0xB8, 0x03, 0xEA, 0xC6, 0xAF, 0xBB, 0x65, 0xA2, + 0x5A, 0x41, 0xF1, 0x53, 0x05, 0x68, 0x8E, 0x83 }, + .lockable = true, + .rank = 1, + .cb = NULL + }; + int err = bt_cap_acceptor_register(®ister_params, &csis_svc_inst); +#else + int err = 0; +#endif /* CONFIG_BT_CAP_ACCEPTOR && CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER */ + + return BTP_STATUS_VAL(err); +} + +uint8_t tester_unregister_cas(void) +{ + return BTP_STATUS_SUCCESS; +} diff --git a/tests/bluetooth/tester/src/btp_ccp.c b/tests/bluetooth/tester/src/btp_ccp.c new file mode 100644 index 00000000000..6c0d18258c3 --- /dev/null +++ b/tests/bluetooth/tester/src/btp_ccp.c @@ -0,0 +1,343 @@ +/* btp_ccp.c - Bluetooth CCP Tester */ + +/* + * Copyright (c) 2023 Oticon + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "btp/btp.h" +#include "zephyr/sys/byteorder.h" +#include + +#include +#define LOG_MODULE_NAME bttester_ccp +LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL); + +static uint8_t ccp_supported_commands(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + struct btp_ccp_read_supported_commands_rp *rp = rsp; + + /* octet 0 */ + tester_set_bit(rp->data, BTP_CCP_READ_SUPPORTED_COMMANDS); + tester_set_bit(rp->data, BTP_CCP_DISCOVER_TBS); + tester_set_bit(rp->data, BTP_CCP_ACCEPT_CALL); + tester_set_bit(rp->data, BTP_CCP_TERMINATE_CALL); + tester_set_bit(rp->data, BTP_CCP_ORIGINATE_CALL); + tester_set_bit(rp->data, BTP_CCP_READ_CALL_STATE); + + *rsp_len = sizeof(*rp) + 1; + + return BTP_STATUS_SUCCESS; +} + +static void tbs_client_discovered_ev(int err, uint8_t tbs_count, bool gtbs_found) +{ + struct btp_ccp_discovered_ev ev; + + ev.status = sys_cpu_to_le32(err); + ev.tbs_count = tbs_count; + ev.gtbs_found = gtbs_found; + + tester_event(BTP_SERVICE_ID_CCP, BTP_CCP_EV_DISCOVERED, &ev, sizeof(ev)); +} + +/** + * @brief Callback function for ccp_discover. + * + * @param conn The connection that was used to discover CCP for a + * device. + * @param err Error value. BT_TBS_CLIENT_RESULT_CODE_*, + * GATT error or errno value. + * @param tbs_count Number of TBS instances on peer device. + * @param gtbs_found Whether or not the server has a Generic TBS instance. + */ +static void tbs_client_discover_cb(struct bt_conn *conn, + int err, + uint8_t tbs_count, + bool gtbs_found) +{ + LOG_DBG("Discovered TBS - err (%u) GTBS (%u)", err, gtbs_found); + + tbs_client_discovered_ev(err, tbs_count, gtbs_found); +} + +/** + * @brief Callback function for the CCP call control functions. + * + * @param conn The connection used in the function. + * @param err Error value. BT_TBS_CLIENT_RESULT_CODE_*, + * GATT error or errno value. + * @param inst_index The index of the TBS instance that was updated. + * @param call_index The call index. For #bt_tbs_client_originate_call this will + * always be 0, and does not reflect the actual call index. + */ +static void tbs_client_originate_call_cb(struct bt_conn *conn, + int err, + uint8_t inst_index, + uint8_t call_index) +{ + LOG_DBG("Originate call - err (%u) Call Index (%u)", err, call_index); +} + +/** + * @brief Callback function for the CCP call control functions. + * + * @param conn The connection used in the function. + * @param err Error value. BT_TBS_CLIENT_RESULT_CODE_*, + * GATT error or errno value. + * @param inst_index The index of the TBS instance that was updated. + * @param call_index The call index. For #bt_tbs_client_originate_call this will + * always be 0, and does not reflect the actual call index. + */ +static void tbs_client_terminate_call_cb(struct bt_conn *conn, + int err, + uint8_t inst_index, + uint8_t call_index) +{ + LOG_DBG("Terminate call - err (%u) Call Index (%u)", err, call_index); +} + +/** + * @brief Callback function for the CCP call control functions. + * + * @param conn The connection used in the function. + * @param err Error value. BT_TBS_CLIENT_RESULT_CODE_*, + * GATT error or errno value. + * @param inst_index The index of the TBS instance that was updated. + * @param call_index The call index. For #bt_tbs_client_originate_call this will + * always be 0, and does not reflect the actual call index. + */ +static void tbs_client_accept_call_cb(struct bt_conn *conn, + int err, + uint8_t inst_index, + uint8_t call_index) +{ + LOG_DBG("Accept call - err (%u) Call Index (%u)", err, call_index); +} + +/** + * @brief Callback function for the CCP call control functions. + * + * @param conn The connection used in the function. + * @param err Error value. BT_TBS_CLIENT_RESULT_CODE_*, + * GATT error or errno value. + * @param inst_index The index of the TBS instance that was updated. + * @param call_index The call index. For #bt_tbs_client_originate_call this will + * always be 0, and does not reflect the actual call index. + */ +static void tbs_client_retrieve_call_cb(struct bt_conn *conn, + int err, + uint8_t inst_index, + uint8_t call_index) +{ + LOG_DBG("Retrieve call - err (%u) Call Index (%u)", err, call_index); +} + +typedef struct bt_tbs_client_call_state bt_tbs_client_call_state_t; + +#define CALL_STATES_EV_SIZE sizeof(struct btp_ccp_call_states_ev) + \ + sizeof(bt_tbs_client_call_state_t) * \ + CONFIG_BT_TBS_CLIENT_MAX_CALLS + +static void tbs_client_call_states_ev(int err, + uint8_t inst_index, + uint8_t call_count, + const bt_tbs_client_call_state_t *call_states) +{ + struct net_buf_simple *buf = NET_BUF_SIMPLE(CALL_STATES_EV_SIZE); + struct btp_ccp_call_states_ev ev = { + sys_cpu_to_le32(err), inst_index, call_count + }; + + net_buf_simple_init(buf, 0); + net_buf_simple_add_mem(buf, &ev, sizeof(ev)); + + for (uint8_t n = 0; n < call_count; n++, call_states++) { + net_buf_simple_add_mem(buf, call_states, sizeof(bt_tbs_client_call_state_t)); + } + + tester_event(BTP_SERVICE_ID_CCP, BTP_CCP_EV_CALL_STATES, buf->data, buf->len); +} + +/** + * @brief Callback function for ccp_read_call_state. + * + * @param conn The connection used in the function. + * @param err Error value. BT_TBS_CLIENT_RESULT_CODE_*, + * GATT error or errno value. + * @param inst_index The index of the TBS instance that was updated. + * @param call_count Number of call states read. + * @param call_states Array of call states. The array is not kept by + * the client, so must be copied to be saved. + */ +static void tbs_client_call_states_cb(struct bt_conn *conn, + int err, + uint8_t inst_index, + uint8_t call_count, + const bt_tbs_client_call_state_t *call_states) +{ + LOG_DBG("Call states - err (%u) Call Count (%u)", err, call_count); + + tbs_client_call_states_ev(err, inst_index, call_count, call_states); +} + +/** + * @brief Callback function for ccp_read_termination_reason. + * + * @param conn The connection used in the function. + * @param err Error value. BT_TBS_CLIENT_RESULT_CODE_*, + * GATT error or errno value. + * @param inst_index The index of the TBS instance that was updated. + * @param call_index The call index. + * @param reason The termination reason. + */ +static void tbs_client_termination_reason_cb(struct bt_conn *conn, + int err, + uint8_t inst_index, + uint8_t call_index, + uint8_t reason) +{ + LOG_DBG("Termination reason - err (%u) Call Index (%u) Reason (%u)", + err, call_index, reason); +} + +static const struct bt_tbs_client_cb tbs_client_callbacks = { + .discover = tbs_client_discover_cb, + .originate_call = tbs_client_originate_call_cb, + .terminate_call = tbs_client_terminate_call_cb, + .accept_call = tbs_client_accept_call_cb, + .retrieve_call = tbs_client_retrieve_call_cb, + .call_state = tbs_client_call_states_cb, + .termination_reason = tbs_client_termination_reason_cb +}; + +static uint8_t ccp_discover_tbs(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_ccp_discover_tbs_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + err = (conn) ? bt_tbs_client_discover(conn) : -ENOTCONN; + if (conn) { + bt_conn_unref(conn); + } + + return BTP_STATUS_VAL(err); +} + +static uint8_t ccp_accept_call(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_ccp_accept_call_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + err = (conn) ? bt_tbs_client_accept_call(conn, cp->inst_index, cp->call_id) : -ENOTCONN; + if (conn) { + bt_conn_unref(conn); + } + + return BTP_STATUS_VAL(err); +} + +static uint8_t ccp_terminate_call(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_ccp_terminate_call_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + err = (conn) ? bt_tbs_client_terminate_call(conn, cp->inst_index, cp->call_id) : + -ENOTCONN; + if (conn) { + bt_conn_unref(conn); + } + + return BTP_STATUS_VAL(err); +} + +static uint8_t ccp_originate_call(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_ccp_originate_call_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + err = (conn) ? bt_tbs_client_originate_call(conn, cp->inst_index, cp->uri) : -ENOTCONN; + if (conn) { + bt_conn_unref(conn); + } + + return BTP_STATUS_VAL(err); +} + +static uint8_t ccp_read_call_state(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_ccp_read_call_state_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + err = (conn) ? bt_tbs_client_read_call_state(conn, cp->inst_index) : -ENOTCONN; + if (conn) { + bt_conn_unref(conn); + } + + return BTP_STATUS_VAL(err); +} + +static const struct btp_handler ccp_handlers[] = { + { + .opcode = BTP_CCP_READ_SUPPORTED_COMMANDS, + .index = BTP_INDEX_NONE, + .expect_len = 0, + .func = ccp_supported_commands + }, + { + .opcode = BTP_CCP_DISCOVER_TBS, + .expect_len = sizeof(struct btp_ccp_discover_tbs_cmd), + .func = ccp_discover_tbs + }, + { + .opcode = BTP_CCP_ACCEPT_CALL, + .expect_len = sizeof(struct btp_ccp_accept_call_cmd), + .func = ccp_accept_call + }, + { + .opcode = BTP_CCP_TERMINATE_CALL, + .expect_len = sizeof(struct btp_ccp_terminate_call_cmd), + .func = ccp_terminate_call + }, + { + .opcode = BTP_CCP_ORIGINATE_CALL, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = ccp_originate_call + }, + { + .opcode = BTP_CCP_READ_CALL_STATE, + .expect_len = sizeof(struct btp_ccp_read_call_state_cmd), + .func = ccp_read_call_state + } +}; + +uint8_t tester_init_ccp(void) +{ + tester_register_command_handlers(BTP_SERVICE_ID_CCP, ccp_handlers, + ARRAY_SIZE(ccp_handlers)); + + bt_tbs_client_register_cb(&tbs_client_callbacks); + + return BTP_STATUS_SUCCESS; +} + +uint8_t tester_unregister_ccp(void) +{ + return BTP_STATUS_SUCCESS; +} diff --git a/tests/bluetooth/tester/src/btp_core.c b/tests/bluetooth/tester/src/btp_core.c index 7ece1224ed0..8c157a5eccb 100644 --- a/tests/bluetooth/tester/src/btp_core.c +++ b/tests/bluetooth/tester/src/btp_core.c @@ -80,6 +80,21 @@ static uint8_t supported_services(const void *cmd, uint16_t cmd_len, #if defined(CONFIG_BT_CSIP_SET_MEMBER) tester_set_bit(rp->data, BTP_SERVICE_ID_CSIS); #endif /* CONFIG_BT_CSIP_SET_MEMBER */ +#if defined(CONFIG_BT_MICP_MIC_DEV) || defined(CONFIG_BT_MICP_MIC_CTLR) + tester_set_bit(rp->data, BTP_SERVICE_ID_MICP); +#endif /* CONFIG_BT_MICP_MIC_DEV */ +#if defined(CONFIG_BT_TBS_CLIENT) + tester_set_bit(rp->data, BTP_SERVICE_ID_CCP); +#endif /* CONFIG_BT_TBS_CLIENT */ +#if defined(CONFIG_BT_VCP_VOL_CTLR) + tester_set_bit(rp->data, BTP_SERVICE_ID_VCP); +#endif /* CONFIG_BT_VCP_VOL_CTLR */ +#if defined(CONFIG_BT_CAP_ACCEPTOR) + tester_set_bit(rp->data, BTP_SERVICE_ID_CAS); +#endif /* CONFIG_BT_CAP_ACCEPTOR */ +#if defined(CONFIG_BT_MCC) + tester_set_bit(rp->data, BTP_SERVICE_ID_MCP); +#endif /* CONFIG_BT_MCC */ *rsp_len = sizeof(*rp) + 2; @@ -122,7 +137,7 @@ static uint8_t register_service(const void *cmd, uint16_t cmd_len, status = tester_init_mmdl(); break; #endif /* CONFIG_BT_MESH */ -#if defined(CONFIG_BT_VCP_VOL_REND) +#if defined(CONFIG_BT_VCP_VOL_REND) || defined(CONFIG_BT_VCP_VOL_CTLR) case BTP_SERVICE_ID_VCS: status = tester_init_vcs(); break; @@ -132,13 +147,17 @@ static uint8_t register_service(const void *cmd, uint16_t cmd_len, case BTP_SERVICE_ID_AICS: status = tester_init_aics(); break; + case BTP_SERVICE_ID_VCP: + status = tester_init_vcp(); + break; #endif /* CONFIG_BT_VCP_VOL_REND */ #if defined(CONFIG_BT_IAS) case BTP_SERVICE_ID_IAS: status = tester_init_ias(); break; #endif /* CONFIG_BT_IAS */ -#if defined(CONFIG_BT_BAP_UNICAST_CLIENT) || defined(CONFIG_BT_BAP_UNICAST_SERVER) +#if defined(CONFIG_BT_BAP_UNICAST_CLIENT) || defined(CONFIG_BT_BAP_UNICAST_SERVER) || \ + defined(CONFIG_BT_BAP_BROADCAST_SOURCE) || defined(CONFIG_BT_BAP_BROADCAST_SINK) case BTP_SERVICE_ID_PACS: status = tester_init_pacs(); break; @@ -148,7 +167,17 @@ static uint8_t register_service(const void *cmd, uint16_t cmd_len, case BTP_SERVICE_ID_BAP: status = tester_init_bap(); break; -#endif /* CONFIG_BT_BAP_UNICAST_CLIENT or CONFIG_BT_BAP_UNICAST_SERVER */ +#endif /* CONFIG_BT_BAP_UNICAST_CLIENT || CONFIG_BT_BAP_UNICAST_SERVER || \ + * CONFIG_BT_BAP_BROADCAST_SOURCE || CONFIG_BT_BAP_BROADCAST_SINK + */ +#if defined(CONFIG_BT_MICP_MIC_DEV) || defined(CONFIG_BT_MICP_MIC_CTLR) + case BTP_SERVICE_ID_MICP: + status = tester_init_micp(); + break; + case BTP_SERVICE_ID_MICS: + status = tester_init_mics(); + break; +#endif /* CONFIG_BT_MICP_MIC_DEV or CONFIG_BT_MICP_MIC_CTLR */ #if defined(CONFIG_BT_HAS) case BTP_SERVICE_ID_HAS: status = tester_init_has(); @@ -159,6 +188,21 @@ static uint8_t register_service(const void *cmd, uint16_t cmd_len, status = tester_init_csis(); break; #endif /* CONFIG_BT_CSIP_SET_MEMBER */ +#if defined(CONFIG_BT_TBS_CLIENT) + case BTP_SERVICE_ID_CCP: + status = tester_init_ccp(); + break; +#endif /* CONFIG_BT_TBS_CLIENT */ +#if defined(CONFIG_BT_CAP_ACCEPTOR) + case BTP_SERVICE_ID_CAS: + status = tester_init_cas(); + break; +#endif /* CONFIG_BT_CAP_ACCEPTOR */ +#if defined(CONFIG_BT_MCC) + case BTP_SERVICE_ID_MCP: + status = tester_init_mcp(); + break; +#endif /* CONFIG_BT_MCC */ default: LOG_WRN("unknown id: 0x%02x", cp->id); status = BTP_STATUS_FAILED; @@ -224,7 +268,8 @@ static uint8_t unregister_service(const void *cmd, uint16_t cmd_len, status = tester_unregister_ias(); break; #endif /* CONFIG_BT_IAS */ -#if defined(CONFIG_BT_BAP_UNICAST_CLIENT) || defined(CONFIG_BT_BAP_UNICAST_SERVER) +#if defined(CONFIG_BT_BAP_UNICAST_CLIENT) || defined(CONFIG_BT_BAP_UNICAST_SERVER) || \ + defined(CONFIG_BT_BAP_BROADCAST_SOURCE) || defined(CONFIG_BT_BAP_BROADCAST_SINK) case BTP_SERVICE_ID_PACS: status = tester_unregister_pacs(); break; @@ -234,7 +279,17 @@ static uint8_t unregister_service(const void *cmd, uint16_t cmd_len, case BTP_SERVICE_ID_BAP: status = tester_unregister_bap(); break; -#endif /* CONFIG_BT_BAP_UNICAST_CLIENT or CONFIG_BT_BAP_UNICAST_SERVER */ +#endif /* CONFIG_BT_BAP_UNICAST_CLIENT || CONFIG_BT_BAP_UNICAST_SERVER || \ + * CONFIG_BT_BAP_BROADCAST_SOURCE || CONFIG_BT_BAP_BROADCAST_SINK + */ +#if defined(CONFIG_BT_MICP_MIC_DEV) || defined(CONFIG_BT_MICP_MIC_CTLR) + case BTP_SERVICE_ID_MICP: + status = tester_unregister_micp(); + break; + case BTP_SERVICE_ID_MICS: + status = tester_unregister_mics(); + break; +#endif /* CONFIG_BT_MICP_MIC_DEV or CONFIG_BT_MICP_MIC_CTLR */ #if defined(CONFIG_BT_HAS) case BTP_SERVICE_ID_HAS: status = tester_unregister_has(); @@ -245,6 +300,21 @@ static uint8_t unregister_service(const void *cmd, uint16_t cmd_len, status = tester_unregister_csis(); break; #endif /* CONFIG_BT_CSIP_SET_MEMBER */ +#if defined(CONFIG_BT_TBS_CLIENT) + case BTP_SERVICE_ID_CCP: + status = tester_unregister_ccp(); + break; +#endif /* CONFIG_BT_TBS_CLIENT */ +#if defined(CONFIG_BT_CAP_ACCEPTOR) + case BTP_SERVICE_ID_CAS: + status = tester_unregister_cas(); + break; +#endif /* CONFIG_BT_CAP_ACCEPTOR */ +#if defined(CONFIG_BT_MCC) + case BTP_SERVICE_ID_MCP: + status = tester_unregister_mcp(); + break; +#endif /* CONFIG_BT_MCC */ default: LOG_WRN("unknown id: 0x%x", cp->id); status = BTP_STATUS_FAILED; diff --git a/tests/bluetooth/tester/src/btp_csis.c b/tests/bluetooth/tester/src/btp_csis.c index c7c57dbf035..08e9b05723f 100644 --- a/tests/bluetooth/tester/src/btp_csis.c +++ b/tests/bluetooth/tester/src/btp_csis.c @@ -8,7 +8,7 @@ #include #include "btp/btp.h" -#include "zephyr/sys/byteorder.h" +#include #include #define LOG_MODULE_NAME bttester_csis diff --git a/tests/bluetooth/tester/src/btp_gap.c b/tests/bluetooth/tester/src/btp_gap.c index 65792e7da65..e09e90a06e1 100644 --- a/tests/bluetooth/tester/src/btp_gap.c +++ b/tests/bluetooth/tester/src/btp_gap.c @@ -32,10 +32,6 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL); #define BT_LE_AD_DISCOV_MASK (BT_LE_AD_LIMITED | BT_LE_AD_GENERAL) #define ADV_BUF_LEN (sizeof(struct btp_gap_device_found_ev) + 2 * 31) -#if defined(CONFIG_BT_EXT_ADV) -static struct bt_le_ext_adv *ext_adv; -#endif - static atomic_t current_settings; struct bt_conn_auth_cb cb; static uint8_t oob_legacy_tk[16] = { 0 }; @@ -476,6 +472,47 @@ static struct bt_data ad[10] = { }; static struct bt_data sd[10]; +#if defined(CONFIG_BT_EXT_ADV) +static struct bt_le_ext_adv *ext_adv; + +struct bt_le_ext_adv *tester_gap_ext_adv_get(void) +{ + return ext_adv; +} + +int tester_gap_start_ext_adv(void) +{ + int err; + + err = bt_le_ext_adv_start(ext_adv, BT_LE_EXT_ADV_START_DEFAULT); + if (err != 0) { + LOG_ERR("Failed to start advertising"); + + return -EINVAL; + } + + atomic_set_bit(¤t_settings, BTP_GAP_SETTINGS_ADVERTISING); + + return 0; +} + +int tester_gap_stop_ext_adv(void) +{ + int err; + + err = bt_le_ext_adv_stop(ext_adv); + if (err != 0) { + LOG_ERR("Failed to stop advertising"); + + return -EINVAL; + } + + atomic_clear_bit(¤t_settings, BTP_GAP_SETTINGS_ADVERTISING); + + return 0; +} +#endif /* defined(CONFIG_BT_EXT_ADV) */ + static uint8_t set_discoverable(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) { @@ -528,6 +565,66 @@ static uint8_t set_bondable(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } +int tester_gap_create_adv_instance(struct bt_le_adv_param *param, uint8_t own_addr_type, + const struct bt_data *ad, size_t ad_len, + const struct bt_data *sd, size_t sd_len, + uint32_t *settings) +{ + int err = 0; + + if (settings != NULL) { + atomic_set(¤t_settings, *settings); + } + + if (atomic_test_bit(¤t_settings, BTP_GAP_SETTINGS_CONNECTABLE)) { + param->options |= BT_LE_ADV_OPT_CONNECTABLE; + } + + switch (own_addr_type) { + case BTP_GAP_ADDR_TYPE_IDENTITY: + param->options |= BT_LE_ADV_OPT_USE_IDENTITY; + break; +#if defined(CONFIG_BT_PRIVACY) + case BTP_GAP_ADDR_TYPE_RESOLVABLE_PRIVATE: + /* RPA usage is is controlled via privacy settings */ + if (!atomic_test_bit(¤t_settings, BTP_GAP_SETTINGS_PRIVACY)) { + return -EINVAL; + } + break; + case BTP_GAP_ADDR_TYPE_NON_RESOLVABLE_PRIVATE: + /* NRPA is used only for non-connectable advertising */ + if (atomic_test_bit(¤t_settings, BTP_GAP_SETTINGS_CONNECTABLE)) { + return -EINVAL; + } + break; +#endif + default: + return -EINVAL; + } + + if (IS_ENABLED(CONFIG_BT_EXT_ADV) && atomic_test_bit(¤t_settings, + BTP_GAP_SETTINGS_EXTENDED_ADVERTISING)) { + param->options |= BT_LE_ADV_OPT_EXT_ADV; + if (ext_adv != NULL) { + err = bt_le_ext_adv_delete(ext_adv); + if (err != 0) { + return err; + } + + ext_adv = NULL; + } + + err = bt_le_ext_adv_create(param, NULL, &ext_adv); + if (err != 0) { + return BTP_STATUS_FAILED; + } + + err = bt_le_ext_adv_set_data(ext_adv, ad, ad_len, sd_len ? sd : NULL, sd_len); + } + + return err; +} + static uint8_t start_advertising(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) { @@ -583,57 +680,16 @@ static uint8_t start_advertising(const void *cmd, uint16_t cmd_len, i += sd[sd_len].data_len; } - if (atomic_test_bit(¤t_settings, BTP_GAP_SETTINGS_CONNECTABLE)) { - param.options |= BT_LE_ADV_OPT_CONNECTABLE; - } - - switch (own_addr_type) { - case 0x00: - param.options |= BT_LE_ADV_OPT_USE_IDENTITY; - break; -#if defined(CONFIG_BT_PRIVACY) - case 0x01: - /* RPA usage is is controlled via privacy settings */ - if (!atomic_test_bit(¤t_settings, BTP_GAP_SETTINGS_PRIVACY)) { - return BTP_STATUS_FAILED; - } - break; - case 0x02: - /* NRPA is used only for non-connectable advertising */ - if (atomic_test_bit(¤t_settings, BTP_GAP_SETTINGS_CONNECTABLE)) { - return BTP_STATUS_FAILED; - } - break; -#endif - default: + err = tester_gap_create_adv_instance(¶m, own_addr_type, ad, adv_len, sd, sd_len, NULL); + if (err != 0) { return BTP_STATUS_FAILED; } - if (atomic_test_bit(¤t_settings, BTP_GAP_SETTINGS_EXTENDED_ADVERTISING)) { #if defined(CONFIG_BT_EXT_ADV) - param.options |= BT_LE_ADV_OPT_EXT_ADV; - if (ext_adv != NULL) { - err = bt_le_ext_adv_delete(ext_adv); - if (err) { - return BTP_STATUS_FAILED; - } - - ext_adv = NULL; - } - - err = bt_le_ext_adv_create(¶m, NULL, &ext_adv); - if (err) { - return BTP_STATUS_FAILED; - } - - err = bt_le_ext_adv_set_data(ext_adv, ad, adv_len, sd_len ? sd : NULL, sd_len); - if (err) { - return BTP_STATUS_FAILED; - } - + if (atomic_test_bit(¤t_settings, BTP_GAP_SETTINGS_EXTENDED_ADVERTISING)) { err = bt_le_ext_adv_start(ext_adv, BT_LE_EXT_ADV_START_DEFAULT); #else - return BTP_STATUS_FAILED; + if (0) { #endif } else { err = bt_le_adv_start(¶m, ad, adv_len, sd_len ? sd : NULL, sd_len); @@ -642,6 +698,7 @@ static uint8_t start_advertising(const void *cmd, uint16_t cmd_len, /* BTP API don't allow to set empty scan response data. */ if (err < 0) { LOG_ERR("Failed to start advertising"); + return BTP_STATUS_FAILED; } @@ -1273,6 +1330,303 @@ static uint8_t set_extended_advertising(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } +#if defined(CONFIG_BT_PER_ADV) +static struct bt_data padv[10]; +static struct bt_le_per_adv_sync *pa_sync; + +struct bt_le_per_adv_sync *tester_gap_padv_get(void) +{ + return pa_sync; +} + +static void pa_sync_synced_cb(struct bt_le_per_adv_sync *sync, + struct bt_le_per_adv_sync_synced_info *info) +{ + LOG_DBG(""); +} + +static void pa_sync_terminated_cb(struct bt_le_per_adv_sync *sync, + const struct bt_le_per_adv_sync_term_info *info) +{ + LOG_DBG(""); + + if (sync == pa_sync) { + LOG_DBG("PA sync lost with reason %u", info->reason); + pa_sync = NULL; + } +} + +static struct bt_le_per_adv_sync_cb pa_sync_cb = { + .synced = pa_sync_synced_cb, + .term = pa_sync_terminated_cb, +}; + +int tester_gap_padv_configure(const struct bt_le_per_adv_param *param) +{ + int err; + struct bt_le_adv_param ext_adv_param = BT_LE_ADV_PARAM_INIT(BT_LE_ADV_OPT_ONE_TIME, + param->interval_min, + param->interval_max, + NULL); + + if (ext_adv == NULL) { + current_settings = BIT(BTP_GAP_SETTINGS_DISCOVERABLE) | + BIT(BTP_GAP_SETTINGS_EXTENDED_ADVERTISING); + err = tester_gap_create_adv_instance(&ext_adv_param, BTP_GAP_ADDR_TYPE_IDENTITY, ad, + 1, NULL, 0, NULL); + if (err != 0) { + return -EINVAL; + } + } + + /* Set periodic advertising parameters and the required + * bit in AD Flags of extended advertising. + */ + err = bt_le_per_adv_set_param(ext_adv, param); + if (err != 0) { + LOG_DBG("Failed to set periodic advertising parameters (err %d)\n", err); + } + + return err; +} + +static uint8_t padv_configure(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + uint32_t options = BT_LE_PER_ADV_OPT_NONE; + const struct btp_gap_padv_configure_cmd *cp = cmd; + struct btp_gap_padv_configure_rp *rp = rsp; + + if (cp->flags & BTP_GAP_PADV_INCLUDE_TX_POWER) { + options |= BT_LE_PER_ADV_OPT_USE_TX_POWER; + } + + err = tester_gap_padv_configure(BT_LE_PER_ADV_PARAM(sys_le16_to_cpu(cp->interval_min), + sys_le16_to_cpu(cp->interval_max), + options)); + if (err) { + return BTP_STATUS_FAILED; + } + + rp->current_settings = sys_cpu_to_le32(current_settings); + + *rsp_len = sizeof(*rp); + + return BTP_STATUS_SUCCESS; +} + +int tester_gap_padv_start(void) +{ + int err; + + if (ext_adv == NULL) { + return -EINVAL; + } + + if (!atomic_test_bit(¤t_settings, BTP_GAP_SETTINGS_ADVERTISING)) { + err = tester_gap_start_ext_adv(); + if (err != 0) { + return -EINVAL; + } + } + + /* Enable Periodic Advertising */ + err = bt_le_per_adv_start(ext_adv); + if (err != 0) { + LOG_DBG("Failed to start periodic advertising data: %d", err); + } + + return err; +} + +static uint8_t padv_start(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + struct btp_gap_padv_start_rp *rp = rsp; + + err = tester_gap_padv_start(); + + if (err) { + return BTP_STATUS_FAILED; + } + + rp->current_settings = sys_cpu_to_le32(current_settings); + + *rsp_len = sizeof(*rp); + + return BTP_STATUS_SUCCESS; +} + +int tester_gap_padv_stop(void) +{ + int err; + + if (ext_adv == NULL) { + return -EINVAL; + } + + /* Enable Periodic Advertising */ + err = bt_le_per_adv_stop(ext_adv); + if (err != 0) { + LOG_DBG("Failed to stop periodic advertising data: %d", err); + } + + return err; +} + +static uint8_t padv_stop(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + struct btp_gap_padv_stop_rp *rp = rsp; + + err = tester_gap_padv_stop(); + + if (err) { + return BTP_STATUS_FAILED; + } + + rp->current_settings = sys_cpu_to_le32(current_settings); + + *rsp_len = sizeof(*rp); + + return BTP_STATUS_SUCCESS; +} + +int tester_gap_padv_set_data(struct bt_data *per_ad, uint8_t ad_len) +{ + int err; + + if (ext_adv == NULL) { + return -EINVAL; + } + + /* Set Periodic Advertising data */ + err = bt_le_per_adv_set_data(ext_adv, per_ad, ad_len); + if (err != 0) { + LOG_DBG("Failed to set periodic advertising data: %d", err); + } + + return err; +} + +static uint8_t padv_set_data(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + uint8_t padv_len = 0U; + const struct btp_gap_padv_set_data_cmd *cp = cmd; + + for (uint8_t i = 0; i < cp->data_len; padv_len++) { + if (padv_len >= ARRAY_SIZE(padv)) { + LOG_ERR("padv[] Out of memory"); + return BTP_STATUS_FAILED; + } + + padv[padv_len].data_len = cp->data[i++] - 1; + padv[padv_len].type = cp->data[i++]; + padv[padv_len].data = &cp->data[i]; + i += padv[padv_len].data_len; + } + + err = tester_gap_padv_set_data(padv, padv_len); + if (err != 0) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +int tester_gap_padv_create_sync(struct bt_le_per_adv_sync_param *create_params) +{ + int err; + + if (pa_sync != NULL) { + return -EBUSY; + } + + err = bt_le_per_adv_sync_create(create_params, &pa_sync); + + if (err != 0) { + LOG_DBG("Unable to sync to PA: %d", err); + } + + return err; +} + +int tester_gap_padv_stop_sync(void) +{ + int err; + + if (pa_sync == NULL) { + return -EALREADY; + } + + err = bt_le_per_adv_sync_delete(pa_sync); + if (err != 0) { + LOG_DBG("Unable to stop sync to PA: %d", err); + } + + return err; +} + +static uint8_t padv_create_sync(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + const struct btp_gap_padv_create_sync_cmd *cp = cmd; + struct bt_le_per_adv_sync_param create_params = {0}; + + bt_addr_le_copy(&create_params.addr, &cp->address); + create_params.options = BT_LE_PER_ADV_SYNC_OPT_FILTER_DUPLICATE; + create_params.sid = cp->advertiser_sid; + create_params.skip = cp->skip; + create_params.timeout = cp->sync_timeout; + + err = tester_gap_padv_create_sync(&create_params); + if (err != 0) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t padv_sync_transfer_set_info(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_gap_padv_sync_transfer_set_info_cmd *cp = cmd; + (void)cp; + + /* TODO */ + + return BTP_STATUS_FAILED; +} + +static uint8_t padv_sync_transfer_start(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_gap_padv_sync_transfer_start_cmd *cp = cmd; + (void)cp; + + /* TODO */ + + return BTP_STATUS_FAILED; +} + +static uint8_t padv_sync_transfer_recv(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_gap_padv_sync_transfer_recv_cmd *cp = cmd; + (void)cp; + + /* TODO */ + + return BTP_STATUS_FAILED; +} +#endif /* defined(CONFIG_BT_PER_ADV) */ + static const struct btp_handler handlers[] = { { .opcode = BTP_GAP_READ_SUPPORTED_COMMANDS, @@ -1404,7 +1758,49 @@ static const struct btp_handler handlers[] = { .expect_len = sizeof(struct btp_gap_set_extended_advertising_cmd), .func = set_extended_advertising, }, -#endif +#if defined(CONFIG_BT_PER_ADV) + { + .opcode = BTP_GAP_PADV_CONFIGURE, + .expect_len = sizeof(struct btp_gap_padv_configure_cmd), + .func = padv_configure, + }, + { + .opcode = BTP_GAP_PADV_START, + .expect_len = sizeof(struct btp_gap_padv_start_cmd), + .func = padv_start, + }, + { + .opcode = BTP_GAP_PADV_STOP, + .expect_len = sizeof(struct btp_gap_padv_stop_cmd), + .func = padv_stop, + }, + { + .opcode = BTP_GAP_PADV_SET_DATA, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = padv_set_data, + }, + { + .opcode = BTP_GAP_PADV_CREATE_SYNC, + .expect_len = sizeof(struct btp_gap_padv_create_sync_cmd), + .func = padv_create_sync, + }, + { + .opcode = BTP_GAP_PADV_SYNC_TRANSFER_SET_INFO, + .expect_len = sizeof(struct btp_gap_padv_sync_transfer_set_info_cmd), + .func = padv_sync_transfer_set_info, + }, + { + .opcode = BTP_GAP_PADV_SYNC_TRANSFER_START, + .expect_len = sizeof(struct btp_gap_padv_sync_transfer_start_cmd), + .func = padv_sync_transfer_start, + }, + { + .opcode = BTP_GAP_PADV_SYNC_TRANSFER_RECV, + .expect_len = sizeof(struct btp_gap_padv_sync_transfer_recv_cmd), + .func = padv_sync_transfer_recv, + }, +#endif /* defined(CONFIG_BT_PER_ADV) */ +#endif /* defined(CONFIG_BT_EXT_ADV) */ }; uint8_t tester_init_gap(void) @@ -1436,6 +1832,10 @@ uint8_t tester_init_gap(void) bt_conn_cb_register(&conn_callbacks); bt_conn_auth_info_cb_register(&auth_info_cb); +#if defined(CONFIG_BT_PER_ADV) + bt_le_per_adv_sync_cb_register(&pa_sync_cb); +#endif /* defined(CONFIG_BT_PER_ADV) */ + tester_register_command_handlers(BTP_SERVICE_ID_GAP, handlers, ARRAY_SIZE(handlers)); diff --git a/tests/bluetooth/tester/src/btp_has.c b/tests/bluetooth/tester/src/btp_has.c index 76aa2d85acb..d33d51f54ea 100644 --- a/tests/bluetooth/tester/src/btp_has.c +++ b/tests/bluetooth/tester/src/btp_has.c @@ -8,8 +8,8 @@ #include #include "btp/btp.h" -#include "zephyr/sys/byteorder.h" -#include "zephyr/arch/common/ffs.h" +#include +#include #include #include diff --git a/tests/bluetooth/tester/src/btp_ias.c b/tests/bluetooth/tester/src/btp_ias.c index d8750948858..58d0aa71f64 100644 --- a/tests/bluetooth/tester/src/btp_ias.c +++ b/tests/bluetooth/tester/src/btp_ias.c @@ -8,7 +8,7 @@ #include #include "btp/btp.h" -#include "zephyr/sys/byteorder.h" +#include #include #include diff --git a/tests/bluetooth/tester/src/btp_l2cap.c b/tests/bluetooth/tester/src/btp_l2cap.c index 0ed01cf5087..ff78fa9ad55 100644 --- a/tests/bluetooth/tester/src/btp_l2cap.c +++ b/tests/bluetooth/tester/src/btp_l2cap.c @@ -433,7 +433,8 @@ static bool is_free_psm(uint16_t psm) return true; } -static int accept(struct bt_conn *conn, struct bt_l2cap_chan **l2cap_chan) +static int accept(struct bt_conn *conn, struct bt_l2cap_server *server, + struct bt_l2cap_chan **l2cap_chan) { struct channel *chan; diff --git a/tests/bluetooth/tester/src/btp_mcp.c b/tests/bluetooth/tester/src/btp_mcp.c new file mode 100644 index 00000000000..d04dca35dc0 --- /dev/null +++ b/tests/bluetooth/tester/src/btp_mcp.c @@ -0,0 +1,1319 @@ +/* btp_mcp.c - Bluetooth MCP Tester */ + +/* + * Copyright (c) 2023 Codecoup + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "bap_endpoint.h" +#include "btp/btp.h" +#include "../../../../include/zephyr/bluetooth/audio/media_proxy.h" + +#define LOG_MODULE_NAME bttester_mcp +LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL); + +#define SEARCH_LEN_MAX 64 + +static struct net_buf_simple *rx_ev_buf = NET_BUF_SIMPLE(SEARCH_LEN_MAX + + sizeof(struct btp_mcp_search_cp_ev)); + +/* Media Control Profile */ +static void btp_send_mcp_found_ev(struct bt_conn *conn, uint8_t status) +{ + struct btp_mcp_discovered_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + + tester_event(BTP_SERVICE_ID_MCP, BTP_MCP_DISCOVERED_EV, &ev, sizeof(ev)); +} + +static void btp_send_mcp_track_duration_ev(struct bt_conn *conn, uint8_t status, int32_t dur) +{ + struct btp_mcp_track_duration_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + ev.dur = sys_cpu_to_le32(dur); + + tester_event(BTP_SERVICE_ID_MCP, BTP_MCP_TRACK_DURATION_EV, &ev, sizeof(ev)); +} + +static void btp_send_mcp_track_position_ev(struct bt_conn *conn, uint8_t status, int32_t pos) +{ + struct btp_mcp_track_position_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + ev.pos = sys_cpu_to_le32(pos); + + tester_event(BTP_SERVICE_ID_MCP, BTP_MCP_TRACK_POSITION_EV, &ev, sizeof(ev)); +} + +static void btp_send_mcp_playback_speed_ev(struct bt_conn *conn, uint8_t status, int8_t speed) +{ + struct btp_mcp_playback_speed_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + ev.speed = speed; + + tester_event(BTP_SERVICE_ID_MCP, BTP_MCP_PLAYBACK_SPEED_EV, &ev, sizeof(ev)); +} + +static void btp_send_mcp_seeking_speed_ev(struct bt_conn *conn, uint8_t status, int8_t speed) +{ + struct btp_mcp_seeking_speed_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + ev.speed = speed; + + tester_event(BTP_SERVICE_ID_MCP, BTP_MCP_SEEKING_SPEED_EV, &ev, sizeof(ev)); +} + +static void btp_send_mcp_icon_obj_id_ev(struct bt_conn *conn, uint8_t status, uint64_t id) +{ + struct btp_mcp_icon_obj_id_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + sys_put_le48(id, ev.id); + + tester_event(BTP_SERVICE_ID_MCP, BTP_MCP_ICON_OBJ_ID_EV, &ev, sizeof(ev)); +} + +static void btp_send_mcp_next_track_obj_id_ev(struct bt_conn *conn, uint8_t status, + uint64_t id) +{ + struct btp_mcp_next_track_obj_id_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + sys_put_le48(id, ev.id); + + tester_event(BTP_SERVICE_ID_MCP, BTP_MCP_NEXT_TRACK_OBJ_ID_EV, &ev, sizeof(ev)); +} + +static void btp_send_parent_group_obj_id_ev(struct bt_conn *conn, uint8_t status, uint64_t id) +{ + struct btp_mcp_parent_group_obj_id_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + sys_put_le48(id, ev.id); + + tester_event(BTP_SERVICE_ID_MCP, BTP_MCP_PARENT_GROUP_OBJ_ID_EV, &ev, sizeof(ev)); +} + +static void btp_send_current_group_obj_id_ev(struct bt_conn *conn, uint8_t status, uint64_t id) +{ + struct btp_mcp_current_group_obj_id_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + sys_put_le48(id, ev.id); + + tester_event(BTP_SERVICE_ID_MCP, BTP_MCP_CURRENT_GROUP_OBJ_ID_EV, &ev, sizeof(ev)); +} + +static void btp_send_mcp_playing_order_ev(struct bt_conn *conn, uint8_t status, uint8_t order) +{ + struct btp_mcp_playing_order_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + ev.order = order; + + tester_event(BTP_SERVICE_ID_MCP, BTP_MCP_PLAYING_ORDER_EV, &ev, sizeof(ev)); +} + +static void btp_send_mcp_playing_orders_supported_ev(struct bt_conn *conn, uint8_t status, + uint16_t orders) +{ + struct btp_mcp_playing_orders_supported_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + ev.orders = sys_cpu_to_le16(orders); + + tester_event(BTP_SERVICE_ID_MCP, BTP_MCP_PLAYING_ORDERS_SUPPORTED_EV, &ev, sizeof(ev)); +} + +static void btp_send_mcp_media_state_ev(struct bt_conn *conn, uint8_t status, uint8_t state) +{ + struct btp_mcp_media_state_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + ev.state = state; + + tester_event(BTP_SERVICE_ID_MCP, BTP_MCP_MEDIA_STATE_EV, &ev, sizeof(ev)); +} + +static void btp_send_mcp_opcodes_supported_ev(struct bt_conn *conn, uint8_t status, + uint32_t opcodes) +{ + struct btp_mcp_opcodes_supported_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + ev.opcodes = sys_cpu_to_le32(opcodes); + + tester_event(BTP_SERVICE_ID_MCP, BTP_MCP_OPCODES_SUPPORTED_EV, &ev, sizeof(ev)); +} + +static void btp_send_mcp_content_control_id_ev(struct bt_conn *conn, uint8_t status, + uint8_t ccid) +{ + struct btp_mcp_content_control_id_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + ev.ccid = ccid; + + tester_event(BTP_SERVICE_ID_MCP, BTP_MCP_CONTENT_CONTROL_ID_EV, &ev, sizeof(ev)); +} + +static void btp_send_segments_obj_id_ev(struct bt_conn *conn, uint8_t status, uint64_t id) +{ + struct btp_mcp_segments_obj_id_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + sys_put_le48(id, ev.id); + + tester_event(BTP_SERVICE_ID_MCP, BTP_MCP_SEGMENTS_OBJ_ID_EV, &ev, sizeof(ev)); +} + +static void btp_send_current_track_obj_id_ev(struct bt_conn *conn, uint8_t status, uint64_t id) +{ + struct btp_mcp_current_track_obj_id_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + sys_put_le48(id, ev.id); + + tester_event(BTP_SERVICE_ID_MCP, BTP_MCP_CURRENT_TRACK_OBJ_ID_EV, &ev, sizeof(ev)); +} + +static void btp_send_media_cp_ev(struct bt_conn *conn, uint8_t status, + const struct mpl_cmd *cmd) +{ + struct btp_mcp_media_cp_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + ev.opcode = cmd->opcode; + ev.use_param = cmd->use_param; + ev.param = sys_cpu_to_le32(cmd->param); + + tester_event(BTP_SERVICE_ID_MCP, BTP_MCP_MEDIA_CP_EV, &ev, sizeof(ev)); +} + +static void btp_send_search_cp_ev(struct bt_conn *conn, uint8_t status, + const struct mpl_search *search) +{ + struct btp_mcp_search_cp_ev *ev; + uint8_t param[SEARCH_LEN_MAX]; + + net_buf_simple_init(rx_ev_buf, 0); + + ev = net_buf_simple_add(rx_ev_buf, sizeof(*ev)); + + bt_addr_le_copy(&ev->address, bt_conn_get_dst(conn)); + + ev->status = status; + ev->param_len = (uint8_t)search->search[0]; + + if (ev->param_len > (SEARCH_LEN_MAX - sizeof(ev->param_len))) { + return; + } + + ev->search_type = search->search[1]; + strcpy(param, &search->search[2]); + net_buf_simple_add_mem(rx_ev_buf, param, ev->param_len); + + tester_event(BTP_SERVICE_ID_MCP, BTP_MCP_SEARCH_CP_EV, ev, sizeof(*ev) + ev->param_len); +} + +static void btp_send_command_notifications_ev(struct bt_conn *conn, uint8_t status, + const struct mpl_cmd_ntf *ntf) +{ + struct btp_mcp_cmd_ntf_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + ev.requested_opcode = ntf->requested_opcode; + ev.result_code = ntf->result_code; + + tester_event(BTP_SERVICE_ID_MCP, BTP_MCP_NTF_EV, &ev, sizeof(ev)); +} + +static void btp_send_search_notifications_ev(struct bt_conn *conn, uint8_t status, + uint8_t result_code) +{ + struct btp_scp_cmd_ntf_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + ev.result_code = result_code; + + tester_event(BTP_SERVICE_ID_MCP, BTP_SCP_NTF_EV, &ev, sizeof(ev)); +} + +static void mcc_discover_cb(struct bt_conn *conn, int err) +{ + if (err) { + LOG_DBG("Discovery failed (%d)", err); + return; + } + + btp_send_mcp_found_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS); +} + +static void mcc_read_track_duration_cb(struct bt_conn *conn, int err, int32_t dur) +{ + LOG_DBG("MCC Read track duration cb (%d)", err); + + btp_send_mcp_track_duration_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, dur); +} + +static void mcc_read_track_position_cb(struct bt_conn *conn, int err, int32_t pos) +{ + LOG_DBG("MCC Read track position cb (%d)", err); + + btp_send_mcp_track_position_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, pos); +} + +static void mcc_set_track_position_cb(struct bt_conn *conn, int err, int32_t pos) +{ + LOG_DBG("MCC Set track position cb (%d)", err); + + btp_send_mcp_track_position_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, pos); +} + +static void mcc_read_playback_speed_cb(struct bt_conn *conn, int err, int8_t speed) +{ + LOG_DBG("MCC read playback speed cb (%d)", err); + + btp_send_mcp_playback_speed_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, speed); +} + +static void mcc_set_playback_speed_cb(struct bt_conn *conn, int err, int8_t speed) +{ + LOG_DBG("MCC set playback speed cb (%d)", err); + + btp_send_mcp_playback_speed_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, speed); +} + +static void mcc_read_seeking_speed_cb(struct bt_conn *conn, int err, int8_t speed) +{ + LOG_DBG("MCC read seeking speed cb (%d)", err); + + btp_send_mcp_seeking_speed_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, speed); +} + +static void mcc_read_icon_obj_id_cb(struct bt_conn *conn, int err, uint64_t id) +{ + LOG_DBG("MCC read Icon Object ID cb (%d)", err); + + btp_send_mcp_icon_obj_id_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, id); +} + +static void mcc_read_next_track_obj_id_cb(struct bt_conn *conn, int err, uint64_t id) +{ + LOG_DBG("MCC read next track obj ID cb (%d)", err); + + btp_send_mcp_next_track_obj_id_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, id); +} + +static void mcc_set_next_track_obj_id_cb(struct bt_conn *conn, int err, uint64_t id) +{ + LOG_DBG("MCC set next track obj ID cb (%d)", err); + + btp_send_mcp_next_track_obj_id_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, id); +} + +static void mcc_read_parent_group_obj_id_cb(struct bt_conn *conn, int err, uint64_t id) +{ + LOG_DBG("MCC read parent group obj ID cb (%d)", err); + + btp_send_parent_group_obj_id_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, id); +} + +static void mcc_read_current_group_obj_id_cb(struct bt_conn *conn, int err, uint64_t id) +{ + LOG_DBG("MCC read current group obj ID cb (%d)", err); + + btp_send_current_group_obj_id_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, id); +} + +static void mcc_set_current_group_obj_id_cb(struct bt_conn *conn, int err, uint64_t id) +{ + LOG_DBG("MCC read current group obj ID cb (%d)", err); + + btp_send_current_group_obj_id_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, id); +} + +static void mcc_read_playing_order_cb(struct bt_conn *conn, int err, uint8_t order) +{ + LOG_DBG("MCC read playing order cb (%d)", err); + + btp_send_mcp_playing_order_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, order); +} + +static void mcc_set_playing_order_cb(struct bt_conn *conn, int err, uint8_t order) +{ + LOG_DBG("MCC set playing order cb (%d)", err); + + btp_send_mcp_playing_order_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, order); +} + +static void mcc_read_playing_orders_supported_cb(struct bt_conn *conn, int err, uint16_t orders) +{ + LOG_DBG("MCC set playing order cb (%d)", err); + + btp_send_mcp_playing_orders_supported_ev(conn, + err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, + orders); +} + +static void mcc_media_state_read_cb(struct bt_conn *conn, int err, uint8_t state) +{ + LOG_DBG("MCC media state read cb (%d)", err); + + btp_send_mcp_media_state_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, state); +} + +static void mcc_opcodes_supported_cb(struct bt_conn *conn, int err, uint32_t opcodes) +{ + LOG_DBG("MCC opcodes supported cb (%d)", err); + + btp_send_mcp_opcodes_supported_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, + opcodes); +} + +static void mcc_content_control_id_cb(struct bt_conn *conn, int err, uint8_t ccid) +{ + LOG_DBG("MCC Content control ID cb (%d)", err); + + btp_send_mcp_content_control_id_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, + ccid); +} + +static void mcc_segments_object_id_cb(struct bt_conn *conn, int err, uint64_t id) +{ + LOG_DBG("MCC Segments Object ID cb (%d)", err); + + btp_send_segments_obj_id_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, id); +} + +static void mcc_current_track_obj_id_read_cb(struct bt_conn *conn, int err, uint64_t id) +{ + LOG_DBG("MCC Segments Object ID read cb (%d)", err); + + btp_send_current_track_obj_id_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, id); +} + +static void mcc_current_track_obj_id_set_cb(struct bt_conn *conn, int err, uint64_t id) +{ + LOG_DBG("MCC Segments Object ID set cb (%d)", err); + + btp_send_current_track_obj_id_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, id); +} + +static void mcc_send_cmd_cb(struct bt_conn *conn, int err, const struct mpl_cmd *cmd) +{ + LOG_DBG("MCC Send Command cb (%d)", err); + + btp_send_media_cp_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, cmd); +} + +static void mcc_send_search_cb(struct bt_conn *conn, int err, const struct mpl_search *search) +{ + LOG_DBG("MCC Send Search cb (%d)", err); + + btp_send_search_cp_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, search); +} + +static void mcc_cmd_ntf_cb(struct bt_conn *conn, int err, const struct mpl_cmd_ntf *ntf) +{ + LOG_DBG("MCC Media Control Point Command Notify cb (%d)", err); + + btp_send_command_notifications_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, ntf); +} + +static void mcc_search_ntf_cb(struct bt_conn *conn, int err, uint8_t result_code) +{ + LOG_DBG("MCC Search Control Point Notify cb (%d)", err); + + btp_send_search_notifications_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, + result_code); +} + +static struct bt_mcc_cb mcp_cb = { + .discover_mcs = mcc_discover_cb, + .read_track_duration = mcc_read_track_duration_cb, + .read_track_position = mcc_read_track_position_cb, + .set_track_position = mcc_set_track_position_cb, + .read_playback_speed = mcc_read_playback_speed_cb, + .set_playback_speed = mcc_set_playback_speed_cb, + .read_seeking_speed = mcc_read_seeking_speed_cb, + .read_playing_order = mcc_read_playing_order_cb, + .set_playing_order = mcc_set_playing_order_cb, + .read_playing_orders_supported = mcc_read_playing_orders_supported_cb, + .read_media_state = mcc_media_state_read_cb, + .read_opcodes_supported = mcc_opcodes_supported_cb, + .read_content_control_id = mcc_content_control_id_cb, + .send_cmd = mcc_send_cmd_cb, + .cmd_ntf = mcc_cmd_ntf_cb, +#ifdef CONFIG_BT_OTS_CLIENT + .read_icon_obj_id = mcc_read_icon_obj_id_cb, + .read_next_track_obj_id = mcc_read_next_track_obj_id_cb, + .set_next_track_obj_id = mcc_set_next_track_obj_id_cb, + .read_parent_group_obj_id = mcc_read_parent_group_obj_id_cb, + .read_current_group_obj_id = mcc_read_current_group_obj_id_cb, + .set_current_group_obj_id = mcc_set_current_group_obj_id_cb, + .read_segments_obj_id = mcc_segments_object_id_cb, + .read_current_track_obj_id = mcc_current_track_obj_id_read_cb, + .set_current_track_obj_id = mcc_current_track_obj_id_set_cb, + .send_search = mcc_send_search_cb, + .search_ntf = mcc_search_ntf_cb, +#endif /* CONFIG_BT_OTS_CLIENT */ +}; + +static uint8_t mcp_supported_commands(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + struct btp_mcp_read_supported_commands_rp *rp = rsp; + + /* octet 0 */ + tester_set_bit(rp->data, BTP_MCP_READ_SUPPORTED_COMMANDS); + tester_set_bit(rp->data, BTP_MCP_DISCOVER); + tester_set_bit(rp->data, BTP_MCP_TRACK_DURATION_READ); + tester_set_bit(rp->data, BTP_MCP_TRACK_POSITION_READ); + tester_set_bit(rp->data, BTP_MCP_TRACK_POSITION_SET); + tester_set_bit(rp->data, BTP_MCP_PLAYBACK_SPEED_READ); + tester_set_bit(rp->data, BTP_MCP_PLAYBACK_SPEED_SET); + + /* octet 1 */ + tester_set_bit(rp->data, BTP_MCP_SEEKING_SPEED_READ); + tester_set_bit(rp->data, BTP_MCP_ICON_OBJ_ID_READ); + tester_set_bit(rp->data, BTP_MCP_NEXT_TRACK_OBJ_ID_READ); + tester_set_bit(rp->data, BTP_MCP_NEXT_TRACK_OBJ_ID_SET); + tester_set_bit(rp->data, BTP_MCP_PARENT_GROUP_OBJ_ID_READ); + tester_set_bit(rp->data, BTP_MCP_CURRENT_GROUP_OBJ_ID_READ); + tester_set_bit(rp->data, BTP_MCP_CURRENT_GROUP_OBJ_ID_SET); + + /* octet 2 */ + tester_set_bit(rp->data, BTP_MCP_PLAYING_ORDER_READ); + tester_set_bit(rp->data, BTP_MCP_PLAYING_ORDER_SET); + tester_set_bit(rp->data, BTP_MCP_PLAYING_ORDERS_SUPPORTED_READ); + tester_set_bit(rp->data, BTP_MCP_MEDIA_STATE_READ); + tester_set_bit(rp->data, BTP_MCP_OPCODES_SUPPORTED_READ); + tester_set_bit(rp->data, BTP_MCP_CONTENT_CONTROL_ID_READ); + tester_set_bit(rp->data, BTP_MCP_SEGMENTS_OBJ_ID_READ); + + /* octet 3 */ + tester_set_bit(rp->data, BTP_MCP_CURRENT_TRACK_OBJ_ID_READ); + tester_set_bit(rp->data, BTP_MCP_CURRENT_TRACK_OBJ_ID_SET); + tester_set_bit(rp->data, BTP_MCP_CMD_SEND); + tester_set_bit(rp->data, BTP_MCP_CMD_SEARCH); + + *rsp_len = sizeof(*rp) + 1; + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_discover(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_mcp_discover_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_discover_mcs(conn, true); + if (err) { + LOG_DBG("Discovery failed: %d", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_track_duration_read(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_mcp_track_duration_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Read track duration"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_read_track_duration(conn); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_track_position_read(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_mcp_track_position_read_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Read track position"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_read_track_position(conn); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_track_position_set(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_mcp_track_position_set_cmd *cp = cmd; + uint32_t pos = sys_le32_to_cpu(cp->pos); + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Set track position"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_set_track_position(conn, pos); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_playback_speed_read(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_mcp_playback_speed_read_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Read playback speed"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_read_playback_speed(conn); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_playback_speed_set(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_mcp_playback_speed_set *cp = cmd; + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Set playback speed"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_set_playback_speed(conn, cp->speed); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_seeking_speed_read(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_mcp_seeking_speed_read_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Read seeking speed"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_read_seeking_speed(conn); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_read_icon_obj_id(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_mcp_icon_obj_id_read_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Read Icon Object ID"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_read_icon_obj_id(conn); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_read_next_track_obj_id(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_mcp_next_track_obj_id_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Read Next Track Object ID"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_read_next_track_obj_id(conn); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_set_next_track_obj_id(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_mcp_set_next_track_obj_id_cmd *cp = cmd; + uint64_t id = sys_get_le48(cp->id); + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Set Next Track Object ID"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_set_next_track_obj_id(conn, id); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_parent_group_obj_id_read(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_mcp_parent_group_obj_id_read_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Read Parent Group Object ID"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_read_parent_group_obj_id(conn); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_current_group_obj_id_read(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_mcp_current_group_obj_id_read_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Read Current Group Object ID"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_read_current_group_obj_id(conn); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_set_current_group_obj_id(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_mcp_current_group_obj_id_set_cmd *cp = cmd; + uint64_t id = sys_get_le48(cp->id); + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Set Next Track Object ID"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_set_current_group_obj_id(conn, id); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_playing_order_read(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_mcp_playing_order_read_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Read Playing Order"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_read_playing_order(conn); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_playing_order_set(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_mcp_playing_order_set_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Set Playing Order"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_set_playing_order(conn, cp->order); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_playing_orders_supported_read(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_mcp_playing_orders_supported_read_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Playing orders supported read"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_read_playing_orders_supported(conn); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_media_state_read(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_mcp_media_state_read_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Media State read"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_read_media_state(conn); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_opcodes_supported_read(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_mcp_opcodes_supported_read_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Supported opcodes read"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_read_opcodes_supported(conn); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_content_control_id_read(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_mcp_content_control_id_read_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Content Control ID read"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_read_content_control_id(conn); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_segments_obj_id_read(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_mcp_segments_obj_id_read_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Track Segments Object ID read"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_read_segments_obj_id(conn); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_current_track_obj_id_read(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_mcp_current_track_obj_id_read_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Current Track Object ID read"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_read_current_track_obj_id(conn); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_current_track_obj_id_set(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_mcp_current_track_obj_id_set_cmd *cp = cmd; + uint64_t id = sys_get_le48(cp->id); + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Set Current Track Object ID"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_mcc_set_current_track_obj_id(conn, id); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_cmd_send(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_mcp_send_cmd *cp = cmd; + struct mpl_cmd mcp_cmd; + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Send Command"); + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + mcp_cmd.opcode = cp->opcode; + mcp_cmd.use_param = cp->use_param; + mcp_cmd.param = sys_le32_to_cpu(cp->param); + + err = bt_mcc_send_cmd(conn, &mcp_cmd); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mcp_cmd_search(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_mcp_search_cmd *cp = cmd; + struct mpl_search search_items; + struct mpl_sci scp_cmd; + struct bt_conn *conn; + int err; + + LOG_DBG("MCC Send Search Control Point Command"); + + if (cmd_len < sizeof(*cp) || cmd_len != sizeof(*cp) + cp->param_len) { + return BTP_STATUS_FAILED; + } + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + search_items.len = 0; + scp_cmd.type = cp->type; + + if (scp_cmd.type == BT_MCS_SEARCH_TYPE_ONLY_TRACKS || + scp_cmd.type == BT_MCS_SEARCH_TYPE_ONLY_GROUPS) { + scp_cmd.len = sizeof(scp_cmd.type); + + if (ARRAY_SIZE(search_items.search) < (sizeof(scp_cmd.len) + + sizeof(scp_cmd.type))) { + return BTP_STATUS_FAILED; + } + + memcpy(&search_items.search[search_items.len], &scp_cmd.len, sizeof(scp_cmd.len)); + search_items.len += sizeof(scp_cmd.len); + + memcpy(&search_items.search[search_items.len], &scp_cmd.type, + sizeof(scp_cmd.type)); + search_items.len += sizeof(scp_cmd.type); + } else { + if (cp->param_len >= (SEARCH_LEN_MAX - 1)) { + return BTP_STATUS_FAILED; + } + + strcpy(scp_cmd.param, cp->param); + scp_cmd.len = sizeof(scp_cmd.type) + strlen(scp_cmd.param); + + if (ARRAY_SIZE(search_items.search) < (sizeof(scp_cmd.len) + sizeof(scp_cmd.len) + + strlen(scp_cmd.param))) { + return BTP_STATUS_FAILED; + } + + memcpy(&search_items.search[search_items.len], &scp_cmd.len, sizeof(scp_cmd.len)); + search_items.len += sizeof(scp_cmd.len); + + memcpy(&search_items.search[search_items.len], &scp_cmd.type, + sizeof(scp_cmd.type)); + search_items.len += sizeof(scp_cmd.type); + + strcpy(&search_items.search[search_items.len], scp_cmd.param); + search_items.len += strlen(scp_cmd.param); + search_items.search[search_items.len] = '\0'; + } + + err = bt_mcc_send_search(conn, &search_items); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static const struct btp_handler mcp_handlers[] = { + { + .opcode = BTP_MCP_READ_SUPPORTED_COMMANDS, + .index = BTP_INDEX_NONE, + .expect_len = 0, + .func = mcp_supported_commands, + }, + { + .opcode = BTP_MCP_DISCOVER, + .expect_len = sizeof(struct btp_mcp_discover_cmd), + .func = mcp_discover, + }, + { + .opcode = BTP_MCP_TRACK_DURATION_READ, + .expect_len = sizeof(struct btp_mcp_track_duration_cmd), + .func = mcp_track_duration_read, + }, + { + .opcode = BTP_MCP_TRACK_POSITION_READ, + .expect_len = sizeof(struct btp_mcp_track_position_read_cmd), + .func = mcp_track_position_read, + }, + { + .opcode = BTP_MCP_TRACK_POSITION_SET, + .expect_len = sizeof(struct btp_mcp_track_position_set_cmd), + .func = mcp_track_position_set, + }, + { + .opcode = BTP_MCP_PLAYBACK_SPEED_READ, + .expect_len = sizeof(struct btp_mcp_playback_speed_read_cmd), + .func = mcp_playback_speed_read, + }, + { + .opcode = BTP_MCP_PLAYBACK_SPEED_SET, + .expect_len = sizeof(struct btp_mcp_playback_speed_set), + .func = mcp_playback_speed_set, + }, + { + .opcode = BTP_MCP_SEEKING_SPEED_READ, + .expect_len = sizeof(struct btp_mcp_seeking_speed_read_cmd), + .func = mcp_seeking_speed_read, + }, + { + .opcode = BTP_MCP_ICON_OBJ_ID_READ, + .expect_len = sizeof(struct btp_mcp_icon_obj_id_read_cmd), + .func = mcp_read_icon_obj_id, + }, + { + .opcode = BTP_MCP_NEXT_TRACK_OBJ_ID_READ, + .expect_len = sizeof(struct btp_mcp_next_track_obj_id_cmd), + .func = mcp_read_next_track_obj_id, + }, + { + .opcode = BTP_MCP_NEXT_TRACK_OBJ_ID_SET, + .expect_len = sizeof(struct btp_mcp_set_next_track_obj_id_cmd), + .func = mcp_set_next_track_obj_id, + }, + { + .opcode = BTP_MCP_PARENT_GROUP_OBJ_ID_READ, + .expect_len = sizeof(struct btp_mcp_parent_group_obj_id_read_cmd), + .func = mcp_parent_group_obj_id_read, + }, + { + .opcode = BTP_MCP_CURRENT_GROUP_OBJ_ID_READ, + .expect_len = sizeof(struct btp_mcp_current_group_obj_id_read_cmd), + .func = mcp_current_group_obj_id_read, + }, + { + .opcode = BTP_MCP_CURRENT_GROUP_OBJ_ID_SET, + .expect_len = sizeof(struct btp_mcp_current_group_obj_id_set_cmd), + .func = mcp_set_current_group_obj_id, + }, + { + .opcode = BTP_MCP_PLAYING_ORDER_READ, + .expect_len = sizeof(struct btp_mcp_playing_order_read_cmd), + .func = mcp_playing_order_read, + }, + { + .opcode = BTP_MCP_PLAYING_ORDER_SET, + .expect_len = sizeof(struct btp_mcp_playing_order_set_cmd), + .func = mcp_playing_order_set, + }, + { + .opcode = BTP_MCP_PLAYING_ORDERS_SUPPORTED_READ, + .expect_len = sizeof(struct btp_mcp_playing_orders_supported_read_cmd), + .func = mcp_playing_orders_supported_read, + }, + { + .opcode = BTP_MCP_MEDIA_STATE_READ, + .expect_len = sizeof(struct btp_mcp_media_state_read_cmd), + .func = mcp_media_state_read, + }, + { + .opcode = BTP_MCP_OPCODES_SUPPORTED_READ, + .expect_len = sizeof(struct btp_mcp_opcodes_supported_read_cmd), + .func = mcp_opcodes_supported_read, + }, + { + .opcode = BTP_MCP_CONTENT_CONTROL_ID_READ, + .expect_len = sizeof(struct btp_mcp_content_control_id_read_cmd), + .func = mcp_content_control_id_read, + }, + { + .opcode = BTP_MCP_SEGMENTS_OBJ_ID_READ, + .expect_len = sizeof(struct btp_mcp_segments_obj_id_read_cmd), + .func = mcp_segments_obj_id_read, + }, + { + .opcode = BTP_MCP_CURRENT_TRACK_OBJ_ID_READ, + .expect_len = sizeof(struct btp_mcp_current_track_obj_id_read_cmd), + .func = mcp_current_track_obj_id_read, + }, + { + .opcode = BTP_MCP_CURRENT_TRACK_OBJ_ID_SET, + .expect_len = sizeof(struct btp_mcp_current_track_obj_id_set_cmd), + .func = mcp_current_track_obj_id_set, + }, + { + .opcode = BTP_MCP_CMD_SEND, + .expect_len = sizeof(struct btp_mcp_send_cmd), + .func = mcp_cmd_send, + }, + { + .opcode = BTP_MCP_CMD_SEARCH, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = mcp_cmd_search, + }, +}; + +uint8_t tester_init_mcp(void) +{ + int err; + + err = bt_mcc_init(&mcp_cb); + if (err) { + LOG_DBG("Failed to initialize Media Control Client: %d", err); + return BTP_STATUS_FAILED; + } + + tester_register_command_handlers(BTP_SERVICE_ID_MCP, mcp_handlers, + ARRAY_SIZE(mcp_handlers)); + + return BTP_STATUS_SUCCESS; +} + +uint8_t tester_unregister_mcp(void) +{ + return BTP_STATUS_SUCCESS; +} diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index bdc37c2f2e5..ab5fcf515bd 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -454,7 +454,7 @@ static struct bt_mesh_dfu_srv dfu_srv = #define AUTH_METHOD_INPUT 0x03 static struct model_data { - struct bt_mesh_model *model; + const struct bt_mesh_model *model; uint16_t addr; uint16_t appkey_idx; } model_bound[MODEL_BOUNDS_MAX]; @@ -587,7 +587,7 @@ static void get_faults(uint8_t *faults, uint8_t faults_size, uint8_t *dst, uint8 } } -static int fault_get_cur(struct bt_mesh_model *model, uint8_t *test_id, +static int fault_get_cur(const struct bt_mesh_model *model, uint8_t *test_id, uint16_t *company_id, uint8_t *faults, uint8_t *fault_count) { LOG_DBG(""); @@ -600,7 +600,7 @@ static int fault_get_cur(struct bt_mesh_model *model, uint8_t *test_id, return 0; } -static int fault_get_reg(struct bt_mesh_model *model, uint16_t company_id, +static int fault_get_reg(const struct bt_mesh_model *model, uint16_t company_id, uint8_t *test_id, uint8_t *faults, uint8_t *fault_count) { LOG_DBG("company_id 0x%04x", company_id); @@ -616,7 +616,7 @@ static int fault_get_reg(struct bt_mesh_model *model, uint16_t company_id, return 0; } -static int fault_clear(struct bt_mesh_model *model, uint16_t company_id) +static int fault_clear(const struct bt_mesh_model *model, uint16_t company_id) { LOG_DBG("company_id 0x%04x", company_id); @@ -629,7 +629,7 @@ static int fault_clear(struct bt_mesh_model *model, uint16_t company_id) return 0; } -static int fault_test(struct bt_mesh_model *model, uint8_t test_id, +static int fault_test(const struct bt_mesh_model *model, uint8_t test_id, uint16_t company_id) { LOG_DBG("test_id 0x%02x company_id 0x%04x", test_id, company_id); @@ -820,7 +820,7 @@ static uint8_t priv_beacon_set(const void *cmd, uint16_t cmd_len, val.enabled = cp->enabled; val.rand_interval = cp->rand_interval; - err = bt_mesh_priv_beacon_cli_set(net.net_idx, cp->dst, &val); + err = bt_mesh_priv_beacon_cli_set(net.net_idx, cp->dst, &val, &val); if (err) { LOG_ERR("Failed to send Private Beacon Set (err %d)", err); return BTP_STATUS_FAILED; @@ -857,7 +857,7 @@ static uint8_t priv_gatt_proxy_set(const void *cmd, uint16_t cmd_len, state = cp->state; - err = bt_mesh_priv_beacon_cli_gatt_proxy_set(net.net_idx, cp->dst, &state); + err = bt_mesh_priv_beacon_cli_gatt_proxy_set(net.net_idx, cp->dst, state, &state); if (err) { LOG_ERR("Failed to send Private GATT Proxy Set (err %d)", err); return BTP_STATUS_FAILED; @@ -896,7 +896,7 @@ static uint8_t priv_node_id_set(const void *cmd, uint16_t cmd_len, val.net_idx = cp->net_idx; val.state = cp->state; - err = bt_mesh_priv_beacon_cli_node_id_set(net.net_idx, cp->dst, &val); + err = bt_mesh_priv_beacon_cli_node_id_set(net.net_idx, cp->dst, &val, &val); if (err) { LOG_ERR("Failed to send Private Node Identity Set (err %d)", err); return BTP_STATUS_FAILED; @@ -1024,7 +1024,7 @@ static uint8_t proxy_solicit(const void *cmd, uint16_t cmd_len, } #endif /* CONFIG_BT_MESH_PROXY_SOLICITATION */ -static struct bt_mesh_model root_models[] = { +static const struct bt_mesh_model root_models[] = { BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub), @@ -1091,12 +1091,12 @@ struct model_data *lookup_model_bound(uint16_t id) return NULL; } -static struct bt_mesh_model vnd_models[] = { +static const struct bt_mesh_model vnd_models[] = { BT_MESH_MODEL_VND(CID_LOCAL, VND_MODEL_ID_1, BT_MESH_MODEL_NO_OPS, NULL, NULL), }; -static struct bt_mesh_elem elements[] = { +static const struct bt_mesh_elem elements[] = { BT_MESH_ELEM(0, root_models, vnd_models), }; @@ -1715,7 +1715,7 @@ static uint8_t model_send(const void *cmd, uint16_t cmd_len, { const struct btp_mesh_model_send_cmd *cp = cmd; NET_BUF_SIMPLE_DEFINE(msg, UINT8_MAX); - struct bt_mesh_model *model = NULL; + const struct bt_mesh_model *model = NULL; uint16_t src; int err; @@ -1739,7 +1739,7 @@ static uint8_t model_send(const void *cmd, uint16_t cmd_len, /* Lookup source address */ for (int i = 0; i < ARRAY_SIZE(model_bound); i++) { - if (bt_mesh_model_elem(model_bound[i].model)->addr == src) { + if (bt_mesh_model_elem(model_bound[i].model)->rt->addr == src) { model = model_bound[i].model; ctx.app_idx = model_bound[i].appkey_idx; @@ -5228,7 +5228,7 @@ void model_recv_ev(uint16_t src, uint16_t dst, const void *payload, tester_event(BTP_SERVICE_ID_MESH, BTP_MESH_EV_MODEL_RECV, buf.data, buf.len); } -static void model_bound_cb(uint16_t addr, struct bt_mesh_model *model, +static void model_bound_cb(uint16_t addr, const struct bt_mesh_model *model, uint16_t key_idx) { int i; @@ -5249,7 +5249,7 @@ static void model_bound_cb(uint16_t addr, struct bt_mesh_model *model, LOG_ERR("model_bound is full"); } -static void model_unbound_cb(uint16_t addr, struct bt_mesh_model *model, +static void model_unbound_cb(uint16_t addr, const struct bt_mesh_model *model, uint16_t key_idx) { int i; diff --git a/tests/bluetooth/tester/src/btp_micp.c b/tests/bluetooth/tester/src/btp_micp.c new file mode 100644 index 00000000000..4ead39ca179 --- /dev/null +++ b/tests/bluetooth/tester/src/btp_micp.c @@ -0,0 +1,482 @@ +/* btp_micp.c - Bluetooth MICP Tester */ + +/* + * Copyright (c) 2023 Codecoup + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include <../../subsys/bluetooth/audio/micp_internal.h> +#include <../../subsys/bluetooth/audio/aics_internal.h> + +#include "bap_endpoint.h" +#include "btp/btp.h" + +#define LOG_MODULE_NAME bttester_micp +LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL); + +static struct bt_micp_mic_ctlr *mic_ctlr; +static struct bt_micp_mic_dev_register_param mic_dev_register_param; +static uint8_t mute_state; + +#if defined(CONFIG_BT_MICP_MIC_CTLR_AICS) +static struct bt_micp_included micp_included; +struct chrc_handles { + uint16_t mute_handle; + uint16_t state_handle; + uint16_t gain_handle; + uint16_t type_handle; + uint16_t status_handle; + uint16_t control_handle; + uint16_t desc_handle; +}; +struct chrc_handles micp_handles; +extern struct btp_aics_instance aics_client_instance; +extern struct bt_aics_cb aics_client_cb; +#endif /* CONFIG_BT_MICP_MIC_CTLR_AICS */ + +/* Microphone Control Profile */ +static void btp_send_micp_found_ev(struct bt_conn *conn, uint8_t att_status, + const struct chrc_handles *micp_handles) +{ + struct btp_micp_discovered_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.att_status = att_status; + ev.mute_handle = sys_cpu_to_le16(micp_handles->mute_handle); + ev.state_handle = sys_cpu_to_le16(micp_handles->state_handle); + ev.gain_handle = sys_cpu_to_le16(micp_handles->gain_handle); + ev.type_handle = sys_cpu_to_le16(micp_handles->type_handle); + ev.status_handle = sys_cpu_to_le16(micp_handles->status_handle); + ev.control_handle = sys_cpu_to_le16(micp_handles->control_handle); + ev.desc_handle = sys_cpu_to_le16(micp_handles->desc_handle); + + tester_event(BTP_SERVICE_ID_MICP, BTP_MICP_DISCOVERED_EV, &ev, sizeof(ev)); +} + +static void btp_send_micp_mute_state_ev(struct bt_conn *conn, uint8_t att_status, uint8_t mute) +{ + struct btp_micp_mute_state_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.att_status = att_status; + ev.mute = mute; + + tester_event(BTP_SERVICE_ID_MICP, BTP_MICP_MUTE_STATE_EV, &ev, sizeof(ev)); +} + +static void micp_mic_ctlr_mute_cb(struct bt_micp_mic_ctlr *mic_ctlr, int err, uint8_t mute) +{ + struct bt_conn *conn; + + mute_state = mute; + + bt_micp_mic_ctlr_conn_get(mic_ctlr, &conn); + btp_send_micp_mute_state_ev(conn, err, mute_state); + + LOG_DBG("MICP Mute cb (%d)", err); +} + +static void micp_mic_ctlr_mute_written_cb(struct bt_micp_mic_ctlr *mic_ctlr, int err) +{ + struct bt_conn *conn; + + bt_micp_mic_ctlr_conn_get(mic_ctlr, &conn); + btp_send_micp_mute_state_ev(conn, err, mute_state); + + LOG_DBG("MICP Mute Written cb (%d))", err); +} + +static void micp_mic_ctlr_unmute_written_cb(struct bt_micp_mic_ctlr *mic_ctlr, int err) +{ + struct bt_conn *conn; + + bt_micp_mic_ctlr_conn_get(mic_ctlr, &conn); + btp_send_micp_mute_state_ev(conn, err, mute_state); + + LOG_DBG("MICP Mute Unwritten cb (%d))", err); +} + +static void micp_mic_ctlr_discover_cb(struct bt_micp_mic_ctlr *mic_ctlr, int err, + uint8_t aics_count) +{ + struct bt_conn *conn; + + if (err) { + LOG_DBG("Discovery failed (%d)", err); + return; + } + + LOG_DBG("Discovery done with %u AICS", + aics_count); + + bt_micp_mic_ctlr_conn_get(mic_ctlr, &conn); + +#if defined(CONFIG_BT_MICP_MIC_CTLR_AICS) + if (bt_micp_mic_ctlr_included_get(mic_ctlr, &micp_included) != 0) { + LOG_DBG("Could not get included services"); + memset(&micp_handles, 0, sizeof(micp_handles)); + } else { + aics_client_instance.aics_cnt = micp_included.aics_cnt; + aics_client_instance.aics = micp_included.aics; + bt_aics_client_cb_register(aics_client_instance.aics[0], &aics_client_cb); + + micp_handles.state_handle = micp_included.aics[0]->cli.state_handle; + micp_handles.gain_handle = micp_included.aics[0]->cli.gain_handle; + micp_handles.type_handle = micp_included.aics[0]->cli.type_handle; + micp_handles.status_handle = micp_included.aics[0]->cli.status_handle; + micp_handles.control_handle = micp_included.aics[0]->cli.control_handle; + micp_handles.desc_handle = micp_included.aics[0]->cli.desc_handle; + } +#endif /* CONFIG_BT_MICP_MIC_CTLR_AICS */ + + micp_handles.mute_handle = mic_ctlr->mute_handle; + btp_send_micp_found_ev(conn, err, &micp_handles); +} + +static struct bt_micp_mic_ctlr_cb micp_cbs = { + .discover = micp_mic_ctlr_discover_cb, + .mute = micp_mic_ctlr_mute_cb, + .mute_written = micp_mic_ctlr_mute_written_cb, + .unmute_written = micp_mic_ctlr_unmute_written_cb, +}; + +static uint8_t micp_supported_commands(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + struct btp_micp_read_supported_commands_rp *rp = rsp; + + /* octet 0 */ + tester_set_bit(rp->data, BTP_MICP_READ_SUPPORTED_COMMANDS); + tester_set_bit(rp->data, BTP_MICP_CTLR_DISCOVER); + tester_set_bit(rp->data, BTP_MICP_CTLR_MUTE_READ); + tester_set_bit(rp->data, BTP_MICP_CTLR_MUTE); + + *rsp_len = sizeof(*rp) + 1; + + return BTP_STATUS_SUCCESS; +} + +static uint8_t micp_discover(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_micp_discover_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_micp_mic_ctlr_discover(conn, &mic_ctlr); + if (err) { + LOG_DBG("Fail: %d", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t micp_mute_read(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + int err; + + LOG_DBG("Read mute"); + + err = bt_micp_mic_ctlr_mute_get(mic_ctlr); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t micp_mute(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + int err; + + LOG_DBG("MICP Mute"); + + err = bt_micp_mic_ctlr_mute(mic_ctlr); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static const struct btp_handler micp_handlers[] = { + { + .opcode = BTP_MICP_READ_SUPPORTED_COMMANDS, + .index = BTP_INDEX_NONE, + .expect_len = 0, + .func = micp_supported_commands, + }, + { + .opcode = BTP_MICP_CTLR_DISCOVER, + .expect_len = sizeof(struct btp_micp_discover_cmd), + .func = micp_discover, + }, + { + .opcode = BTP_MICP_CTLR_MUTE_READ, + .expect_len = sizeof(struct btp_micp_mute_read_cmd), + .func = micp_mute_read, + }, + { + .opcode = BTP_MICP_CTLR_MUTE, + .expect_len = sizeof(struct btp_micp_mute_cmd), + .func = micp_mute, + }, +}; + +uint8_t tester_init_micp(void) +{ + int err; + + err = bt_micp_mic_ctlr_cb_register(&micp_cbs); + + if (err) { + LOG_DBG("Failed to register callbacks: %d", err); + return BTP_STATUS_FAILED; + } + + tester_register_command_handlers(BTP_SERVICE_ID_MICP, micp_handlers, + ARRAY_SIZE(micp_handlers)); + + return BTP_STATUS_SUCCESS; +} + +uint8_t tester_unregister_micp(void) +{ + (void)bt_micp_mic_ctlr_cb_register(NULL); + return BTP_STATUS_SUCCESS; +} + +/* Microphone Control Service */ +static uint8_t mics_supported_commands(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + struct btp_mics_read_supported_commands_rp *rp = rsp; + + /* octet 0 */ + tester_set_bit(rp->data, BTP_MICS_READ_SUPPORTED_COMMANDS); + tester_set_bit(rp->data, BTP_MICS_DEV_MUTE_DISABLE); + tester_set_bit(rp->data, BTP_MICS_DEV_MUTE_READ); + tester_set_bit(rp->data, BTP_MICS_DEV_MUTE); + tester_set_bit(rp->data, BTP_MICS_DEV_UNMUTE); + + *rsp_len = sizeof(*rp) + 1; + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mics_mute_disable(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + int err; + + LOG_DBG("MICP Mute disable"); + + err = bt_micp_mic_dev_mute_disable(); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mics_mute_read(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + int err; + + LOG_DBG("MICS Mute state read"); + + err = bt_micp_mic_dev_mute_get(); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mics_mute(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + int err; + + LOG_DBG("MICS Mute"); + + err = bt_micp_mic_dev_mute(); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t mics_unmute(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + int err; + + LOG_DBG("MICS Mute"); + + err = bt_micp_mic_dev_unmute(); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static void btp_send_mics_mute_state_ev(uint8_t mute) +{ + struct btp_mics_mute_state_ev ev; + + ev.mute = mute; + + tester_event(BTP_SERVICE_ID_MICS, BTP_MICS_MUTE_STATE_EV, &ev, sizeof(ev)); +} + +static void mic_dev_mute_cb(uint8_t mute) +{ + LOG_DBG("Microphone Device Mute cb"); + + btp_send_mics_mute_state_ev(mute); +} + +static struct bt_micp_mic_dev_cb mic_dev_cb = { + .mute = mic_dev_mute_cb, +}; + +#if defined(CONFIG_BT_MICP_MIC_DEV_AICS) +static void aics_state_cb(struct bt_aics *inst, int err, int8_t gain, + uint8_t mute, uint8_t mode) +{ + LOG_DBG("AICS state callback (%d)", err); +} + +static void aics_gain_setting_cb(struct bt_aics *inst, int err, uint8_t units, + int8_t minimum, int8_t maximum) +{ + LOG_DBG("AICS gain setting callback (%d)", err); +} + +static void aics_input_type_cb(struct bt_aics *inst, int err, + uint8_t input_type) +{ + LOG_DBG("AICS input type callback (%d)", err); +} + +static void aics_status_cb(struct bt_aics *inst, int err, bool active) +{ + LOG_DBG("AICS status callback (%d)", err); +} + +static void aics_description_cb(struct bt_aics *inst, int err, + char *description) +{ + LOG_DBG("AICS description callback (%d)", err); +} + +struct bt_aics_cb aics_mic_dev_cb = { + .state = aics_state_cb, + .gain_setting = aics_gain_setting_cb, + .type = aics_input_type_cb, + .status = aics_status_cb, + .description = aics_description_cb, +}; +#endif /* CONFIG_BT_MICP_MIC_DEV_AICS */ + +static const struct btp_handler mics_handlers[] = { + { + .opcode = BTP_MICS_READ_SUPPORTED_COMMANDS, + .index = BTP_INDEX_NONE, + .expect_len = 0, + .func = mics_supported_commands, + }, + { + .opcode = BTP_MICS_DEV_MUTE_DISABLE, + .expect_len = 0, + .func = mics_mute_disable, + }, + { + .opcode = BTP_MICS_DEV_MUTE_READ, + .expect_len = 0, + .func = mics_mute_read, + }, + { + .opcode = BTP_MICS_DEV_MUTE, + .expect_len = 0, + .func = mics_mute, + }, + { + .opcode = BTP_MICS_DEV_UNMUTE, + .expect_len = 0, + .func = mics_unmute, + }, +}; + +uint8_t tester_init_mics(void) +{ + int err; + + memset(&mic_dev_register_param, 0, sizeof(mic_dev_register_param)); + +#if defined(CONFIG_BT_MICP_MIC_DEV_AICS) + char input_desc[CONFIG_BT_MICP_MIC_DEV_AICS_INSTANCE_COUNT][16]; + + for (size_t i = 0; i < ARRAY_SIZE(mic_dev_register_param.aics_param); i++) { + mic_dev_register_param.aics_param[i].desc_writable = true; + snprintf(input_desc[i], sizeof(input_desc[i]), + "Input %zu", i + 1); + mic_dev_register_param.aics_param[i].description = input_desc[i]; + mic_dev_register_param.aics_param[i].type = BT_AICS_INPUT_TYPE_DIGITAL; + mic_dev_register_param.aics_param[i].status = 1; + mic_dev_register_param.aics_param[i].gain_mode = BT_AICS_MODE_MANUAL; + mic_dev_register_param.aics_param[i].units = 1; + mic_dev_register_param.aics_param[i].min_gain = 0; + mic_dev_register_param.aics_param[i].max_gain = 100; + mic_dev_register_param.aics_param[i].cb = &aics_mic_dev_cb; + } +#endif /* CONFIG_BT_MICP_MIC_DEV_AICS */ + + mic_dev_register_param.cb = &mic_dev_cb; + + err = bt_micp_mic_dev_register(&mic_dev_register_param); + if (err) { + return BTP_STATUS_FAILED; + } + +#if defined(CONFIG_BT_MICP_MIC_DEV_AICS) + err = bt_micp_mic_dev_included_get(&micp_included); + if (err) { + return BTP_STATUS_FAILED; + } +#endif /* CONFIG_BT_MICP_MIC_DEV_AICS */ + + tester_register_command_handlers(BTP_SERVICE_ID_MICS, mics_handlers, + ARRAY_SIZE(mics_handlers)); + + return BTP_STATUS_SUCCESS; +} + +uint8_t tester_unregister_mics(void) +{ + return BTP_STATUS_SUCCESS; +} diff --git a/tests/bluetooth/tester/src/btp_vcp.c b/tests/bluetooth/tester/src/btp_vcp.c index 744adf8ddc1..04e82c35807 100644 --- a/tests/bluetooth/tester/src/btp_vcp.c +++ b/tests/bluetooth/tester/src/btp_vcp.c @@ -7,25 +7,61 @@ */ #include +#include #include #include #include #include #include -#include "zephyr/bluetooth/audio/vocs.h" -#include "zephyr/sys/util.h" +#include +#include +#include "btp/btp.h" +#include <../../subsys/bluetooth/audio/micp_internal.h> +#include <../../subsys/bluetooth/audio/aics_internal.h> +#include <../../subsys/bluetooth/audio/vcp_internal.h> +#include <../../subsys/bluetooth/audio/vocs_internal.h> #include + #define LOG_MODULE_NAME bttester_vcp LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL); -#include "btp/btp.h" - #define BT_AICS_MAX_INPUT_DESCRIPTION_SIZE 16 #define BT_AICS_MAX_OUTPUT_DESCRIPTION_SIZE 16 static struct bt_vcp_vol_rend_register_param vcp_register_param; +static struct bt_vcp_vol_ctlr *vol_ctlr; static struct bt_vcp_included included; +extern struct btp_aics_instance aics_server_instance; +extern struct btp_aics_instance aics_client_instance; +extern struct bt_aics_cb aics_client_cb; + +struct service_handles { + struct { + uint16_t ctrl_pt; + uint16_t flags; + uint16_t state; + } vcp_handles; + + struct { + uint16_t state; + uint16_t location; + uint16_t control; + uint16_t desc; + } vocs_handles; + + struct { + uint16_t mute; + uint16_t state; + uint16_t gain; + uint16_t type; + uint16_t status; + uint16_t control; + uint16_t desc; + } aics_handles; +}; + +struct service_handles chrc_handles; /* Volume Control Service */ static uint8_t vcs_supported_commands(const void *cmd, uint16_t cmd_len, @@ -157,189 +193,133 @@ static const struct btp_handler vcs_handlers[] = { }, }; -/* Audio Input Control Service */ -static uint8_t aics_supported_commands(const void *cmd, uint16_t cmd_len, +/* Volume Offset Control Service */ +static uint8_t vocs_supported_commands(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) { - struct btp_aics_read_supported_commands_rp *rp = rsp; + struct btp_vocs_read_supported_commands_rp *rp = rsp; /* octet 0 */ - tester_set_bit(rp->data, BTP_AICS_READ_SUPPORTED_COMMANDS); - tester_set_bit(rp->data, BTP_AICS_SET_GAIN); - tester_set_bit(rp->data, BTP_AICS_MUTE); - tester_set_bit(rp->data, BTP_AICS_UNMUTE); - tester_set_bit(rp->data, BTP_AICS_MUTE_DISABLE); - tester_set_bit(rp->data, BTP_AICS_MAN_GAIN); - tester_set_bit(rp->data, BTP_AICS_AUTO_GAIN); - tester_set_bit(rp->data, BTP_AICS_MAN_GAIN_ONLY); - tester_set_bit(rp->data, BTP_AICS_AUTO_GAIN_ONLY); - - /* octet 1 */ - tester_set_bit(rp->data, BTP_AICS_DESCRIPTION); + tester_set_bit(rp->data, BTP_VOCS_READ_SUPPORTED_COMMANDS); + tester_set_bit(rp->data, BTP_VOCS_UPDATE_LOC); + tester_set_bit(rp->data, BTP_VOCS_UPDATE_DESC); + tester_set_bit(rp->data, BTP_VOCS_STATE_GET); + tester_set_bit(rp->data, BTP_VOCS_LOCATION_GET); + tester_set_bit(rp->data, BTP_VOCS_OFFSET_STATE_SET); - *rsp_len = sizeof(*rp) + 2; + *rsp_len = sizeof(*rp) + 1; return BTP_STATUS_SUCCESS; } -static void aics_state_cb(struct bt_aics *inst, int err, int8_t gain, - uint8_t mute, uint8_t mode) -{ - LOG_DBG("AICS state callback (%d)", err); -} - -static void aics_gain_setting_cb(struct bt_aics *inst, int err, uint8_t units, - int8_t minimum, int8_t maximum) -{ - LOG_DBG("AICS gain setting callback (%d)", err); -} - -static void aics_input_type_cb(struct bt_aics *inst, int err, - uint8_t input_type) +static void vocs_state_cb(struct bt_vocs *inst, int err, int16_t offset) { - LOG_DBG("AICS input type callback (%d)", err); + LOG_DBG("VOCS state callback err (%d)", err); } -static void aics_status_cb(struct bt_aics *inst, int err, bool active) +static void vocs_location_cb(struct bt_vocs *inst, int err, uint32_t location) { - LOG_DBG("AICS status callback (%d)", err); + LOG_DBG("VOCS location callback err (%d)", err); } -static void aics_description_cb(struct bt_aics *inst, int err, +static void vocs_description_cb(struct bt_vocs *inst, int err, char *description) { - LOG_DBG("AICS description callback (%d)", err); + LOG_DBG("VOCS desctripion callback (%d)", err); } -static struct bt_aics_cb aics_cb = { - .state = aics_state_cb, - .gain_setting = aics_gain_setting_cb, - .type = aics_input_type_cb, - .status = aics_status_cb, - .description = aics_description_cb +static struct bt_vocs_cb vocs_cb = { + .state = vocs_state_cb, + .location = vocs_location_cb, + .description = vocs_description_cb }; -static uint8_t aics_set_gain(const void *cmd, uint16_t cmd_len, - void *rsp, uint16_t *rsp_len) +static void btp_send_vocs_state_ev(struct bt_conn *conn, uint8_t att_status, int16_t offset) { - const struct btp_aics_set_gain_cmd *cp = cmd; + struct btp_vocs_offset_state_ev ev; - LOG_DBG("AICS set gain %d", cp->gain); + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); - for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT; i++) { - if (bt_aics_gain_set(included.aics[0], cp->gain) != 0) { - return BTP_STATUS_FAILED; - } - } + ev.att_status = att_status; + ev.offset = sys_cpu_to_le16(offset); - return BTP_STATUS_SUCCESS; + tester_event(BTP_SERVICE_ID_VOCS, BTP_VOCS_OFFSET_STATE_EV, &ev, sizeof(ev)); } -static uint8_t aics_mute(const void *cmd, uint16_t cmd_len, - void *rsp, uint16_t *rsp_len) +static void btp_send_vocs_location_ev(struct bt_conn *conn, uint8_t att_status, uint32_t location) { - LOG_DBG("AICS mute"); + struct btp_vocs_audio_location_ev ev; - for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT; i++) { - if (bt_aics_mute(included.aics[i]) != 0) { - return BTP_STATUS_FAILED; - } - } - - return BTP_STATUS_SUCCESS; -} + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); -static uint8_t aics_mute_disable(const void *cmd, uint16_t cmd_len, - void *rsp, uint16_t *rsp_len) -{ - LOG_DBG("AICS mute disable"); - - for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT; i++) { - if (bt_aics_disable_mute(included.aics[i]) != 0) { - return BTP_STATUS_FAILED; - } - } + ev.att_status = att_status; + ev.location = sys_cpu_to_le32(location); - return BTP_STATUS_SUCCESS; + tester_event(BTP_SERVICE_ID_VOCS, BTP_VOCS_AUDIO_LOCATION_EV, &ev, sizeof(ev)); } -static uint8_t aics_unmute(const void *cmd, uint16_t cmd_len, - void *rsp, uint16_t *rsp_len) +static void btp_send_vocs_procedure_ev(struct bt_conn *conn, uint8_t att_status, uint8_t opcode) { - LOG_DBG("AICS unmute"); + struct btp_vocs_procedure_ev ev; - for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT; i++) { - if (bt_aics_unmute(included.aics[i]) != 0) { - return BTP_STATUS_FAILED; - } - } + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); - return BTP_STATUS_SUCCESS; + ev.att_status = att_status; + ev.opcode = opcode; + + tester_event(BTP_SERVICE_ID_VOCS, BTP_VOCS_PROCEDURE_EV, &ev, sizeof(ev)); } -static uint8_t aics_man_gain(const void *cmd, uint16_t cmd_len, - void *rsp, uint16_t *rsp_len) +static void vcp_vocs_state_cb(struct bt_vocs *inst, int err, int16_t offset) { - LOG_DBG("AICS manual gain set"); + struct bt_conn *conn; - for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT; i++) { - if (bt_aics_manual_gain_set(included.aics[i]) != 0) { - return BTP_STATUS_FAILED; - } - } + bt_vocs_client_conn_get(inst, &conn); + btp_send_vocs_state_ev(conn, err, offset); - return BTP_STATUS_SUCCESS; + LOG_DBG("VOCS Offset State callback"); } -static uint8_t aics_auto_gain(const void *cmd, uint16_t cmd_len, - void *rsp, uint16_t *rsp_len) +static void vcp_vocs_location_cb(struct bt_vocs *inst, int err, uint32_t location) { - LOG_DBG("AICS auto gain set"); + struct bt_conn *conn; - for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT; i++) { - if (bt_aics_automatic_gain_set(included.aics[i]) != 0) { - return BTP_STATUS_FAILED; - } - } + bt_vocs_client_conn_get(inst, &conn); + btp_send_vocs_location_ev(conn, err, location); - return BTP_STATUS_SUCCESS; + LOG_DBG("VOCS location callback err (%d)", err); } -static uint8_t aics_auto_gain_only(const void *cmd, uint16_t cmd_len, - void *rsp, uint16_t *rsp_len) +static void vcp_vocs_description_cb(struct bt_vocs *inst, int err, + char *description) { - LOG_DBG("AICS auto gain only set"); - - for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT; i++) { - if (bt_aics_gain_set_auto_only(included.aics[i]) != 0) { - return BTP_STATUS_FAILED; - } - } - - return BTP_STATUS_SUCCESS; + LOG_DBG("VOCS desctripion callback (%d)", err); } -static uint8_t aics_man_gain_only(const void *cmd, uint16_t cmd_len, - void *rsp, uint16_t *rsp_len) +static void vcp_vocs_set_offset_cb(struct bt_vocs *inst, int err) { - LOG_DBG("AICS manual gain only set"); + struct bt_conn *conn; - for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT; i++) { - if (bt_aics_gain_set_manual_only(included.aics[i]) != 0) { - return BTP_STATUS_FAILED; - } - } + bt_vocs_client_conn_get(inst, &conn); + btp_send_vocs_procedure_ev(conn, err, BTP_VOCS_OFFSET_STATE_SET); - return BTP_STATUS_SUCCESS; + LOG_DBG("VOCS Set Offset callback (%d)", err); } -static uint8_t aics_desc(const void *cmd, uint16_t cmd_len, - void *rsp, uint16_t *rsp_len) -{ - const struct btp_aics_audio_desc_cmd *cp = cmd; - char description[BT_AICS_MAX_INPUT_DESCRIPTION_SIZE]; +static struct bt_vocs_cb vocs_cl_cb = { + .state = vcp_vocs_state_cb, + .location = vcp_vocs_location_cb, + .description = vcp_vocs_description_cb, +#if defined(CONFIG_BT_VOCS_CLIENT) + .set_offset = vcp_vocs_set_offset_cb +#endif /* CONFIG_BT_VOCS_CLIENT */ +}; - LOG_DBG("AICS description"); +static uint8_t vocs_audio_desc(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_vocs_audio_desc_cmd *cp = cmd; + char description[BT_AICS_MAX_OUTPUT_DESCRIPTION_SIZE]; if (cmd_len < sizeof(*cp) || cmd_len != sizeof(*cp) + cp->desc_len) { @@ -353,8 +333,8 @@ static uint8_t aics_desc(const void *cmd, uint16_t cmd_len, memcpy(description, cp->desc, cp->desc_len); description[cp->desc_len] = '\0'; - for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT; i++) { - if (bt_aics_description_set(included.aics[i], description) != 0) { + for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_VOCS_INSTANCE_COUNT; i++) { + if (bt_vocs_description_set(included.vocs[i], description) != 0) { return BTP_STATUS_FAILED; } } @@ -362,135 +342,60 @@ static uint8_t aics_desc(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } -static const struct btp_handler aics_handlers[] = { - { - .opcode = BTP_AICS_READ_SUPPORTED_COMMANDS, - .index = BTP_INDEX_NONE, - .expect_len = 0, - .func = aics_supported_commands, - }, - { - .opcode = BTP_AICS_SET_GAIN, - .expect_len = sizeof(struct btp_aics_set_gain_cmd), - .func = aics_set_gain, - }, - { - .opcode = BTP_AICS_MUTE, - .expect_len = 0, - .func = aics_mute, - }, - { - .opcode = BTP_AICS_UNMUTE, - .expect_len = 0, - .func = aics_unmute, - }, - { - .opcode = BTP_AICS_MUTE_DISABLE, - .expect_len = 0, - .func = aics_mute_disable, - }, - { - .opcode = BTP_AICS_MAN_GAIN, - .expect_len = 0, - .func = aics_man_gain, - }, - { - .opcode = BTP_AICS_AUTO_GAIN, - .expect_len = 0, - .func = aics_auto_gain, - }, - { - .opcode = BTP_AICS_AUTO_GAIN_ONLY, - .expect_len = 0, - .func = aics_auto_gain_only, - }, - { - .opcode = BTP_AICS_MAN_GAIN_ONLY, - .expect_len = 0, - .func = aics_man_gain_only, - }, - { - .opcode = BTP_AICS_DESCRIPTION, - .expect_len = BTP_HANDLER_LENGTH_VARIABLE, - .func = aics_desc, - }, -}; - -/* Volume Offset Control Service */ -static uint8_t vocs_supported_commands(const void *cmd, uint16_t cmd_len, - void *rsp, uint16_t *rsp_len) +static uint8_t vocs_audio_loc(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) { - struct btp_vocs_read_supported_commands_rp *rp = rsp; - - /* octet 0 */ - tester_set_bit(rp->data, BTP_VOCS_READ_SUPPORTED_COMMANDS); - tester_set_bit(rp->data, BTP_VOCS_UPDATE_LOC); - tester_set_bit(rp->data, BTP_VOCS_UPDATE_DESC); + const struct btp_vocs_audio_loc_cmd *cp = cmd; + uint32_t loc = sys_le32_to_cpu(cp->loc); - *rsp_len = sizeof(*rp) + 1; + for (uint8_t i = 0; i < included.vocs_cnt; i++) { + if (bt_vocs_location_set(included.vocs[i], loc) != 0) { + return BTP_STATUS_FAILED; + } + } return BTP_STATUS_SUCCESS; } -static void vocs_state_cb(struct bt_vocs *inst, int err, int16_t offset) +static uint8_t vocs_state_get(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) { - LOG_DBG("VOCS state callback err (%d)", err); -} + int err; -static void vocs_location_cb(struct bt_vocs *inst, int err, uint32_t location) -{ - LOG_DBG("VOCS location callback err (%d)", err); -} + LOG_DBG("Volume Offset Control Service offset state get"); -static void vocs_description_cb(struct bt_vocs *inst, int err, - char *description) -{ - LOG_DBG("VOCS desctripion callback (%d)", err); -} + err = bt_vocs_state_get(included.vocs[0]); + if (err) { + return BTP_STATUS_FAILED; + } -static struct bt_vocs_cb vocs_cb = { - .state = vocs_state_cb, - .location = vocs_location_cb, - .description = vocs_description_cb -}; + return BTP_STATUS_SUCCESS; +} -static uint8_t vocs_audio_desc(const void *cmd, uint16_t cmd_len, - void *rsp, uint16_t *rsp_len) +static uint8_t vocs_state_set(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) { - const struct btp_vocs_audio_desc_cmd *cp = cmd; - char description[BT_AICS_MAX_OUTPUT_DESCRIPTION_SIZE]; + const struct btp_vocs_offset_set_cmd *cp = cmd; + int16_t offset = sys_le16_to_cpu(cp->offset); + int err; - if (cmd_len < sizeof(*cp) || - cmd_len != sizeof(*cp) + cp->desc_len) { - return BTP_STATUS_FAILED; - } + LOG_DBG("VCP CTLR Set absolute volume %d", offset); - if (cp->desc_len >= sizeof(description)) { + err = bt_vocs_state_set(included.vocs[0], cp->offset); + if (err) { return BTP_STATUS_FAILED; } - memcpy(description, cp->desc, cp->desc_len); - description[cp->desc_len] = '\0'; - - for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_VOCS_INSTANCE_COUNT; i++) { - if (bt_vocs_description_set(included.vocs[i], description) != 0) { - return BTP_STATUS_FAILED; - } - } - return BTP_STATUS_SUCCESS; } -static uint8_t vocs_audio_loc(const void *cmd, uint16_t cmd_len, - void *rsp, uint16_t *rsp_len) +static uint8_t vocs_audio_location_get(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) { - const struct btp_vocs_audio_loc_cmd *cp = cmd; - uint32_t loc = sys_le32_to_cpu(cp->loc); + int err; - for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_VOCS_INSTANCE_COUNT; i++) { - if (bt_vocs_location_set(included.vocs[i], loc) != 0) { - return BTP_STATUS_FAILED; - } + LOG_DBG("Volume Offset Control Service Audio Location get"); + + err = bt_vocs_location_get(included.vocs[0]); + if (err) { + return BTP_STATUS_FAILED; } return BTP_STATUS_SUCCESS; @@ -513,6 +418,59 @@ static const struct btp_handler vocs_handlers[] = { .expect_len = sizeof(struct btp_vocs_audio_loc_cmd), .func = vocs_audio_loc, }, + { + .opcode = BTP_VOCS_STATE_GET, + .expect_len = sizeof(struct btp_vocs_state_get_cmd), + .func = vocs_state_get, + }, + { + .opcode = BTP_VOCS_LOCATION_GET, + .expect_len = sizeof(struct btp_vocs_location_get_cmd), + .func = vocs_audio_location_get, + }, + { + .opcode = BTP_VOCS_OFFSET_STATE_SET, + .expect_len = sizeof(struct btp_vocs_offset_set_cmd), + .func = vocs_state_set, + }, +}; + +/* AICS Callbacks */ +static void aics_state_cb(struct bt_aics *inst, int err, int8_t gain, + uint8_t mute, uint8_t mode) +{ + LOG_DBG("AICS state callback (%d)", err); +} + +static void aics_gain_setting_cb(struct bt_aics *inst, int err, uint8_t units, + int8_t minimum, int8_t maximum) +{ + LOG_DBG("AICS gain setting callback (%d)", err); +} + +static void aics_input_type_cb(struct bt_aics *inst, int err, + uint8_t input_type) +{ + LOG_DBG("AICS input type callback (%d)", err); +} + +static void aics_status_cb(struct bt_aics *inst, int err, bool active) +{ + LOG_DBG("AICS status callback (%d)", err); +} + +static void aics_description_cb(struct bt_aics *inst, int err, + char *description) +{ + LOG_DBG("AICS description callback (%d)", err); +} + +struct bt_aics_cb aics_server_cb = { + .state = aics_state_cb, + .gain_setting = aics_gain_setting_cb, + .type = aics_input_type_cb, + .status = aics_status_cb, + .description = aics_description_cb, }; /* General profile handling */ @@ -545,7 +503,7 @@ static void set_register_params(uint8_t gain_mode) vcp_register_param.aics_param[i].units = 1; vcp_register_param.aics_param[i].min_gain = 0; vcp_register_param.aics_param[i].max_gain = 100; - vcp_register_param.aics_param[i].cb = &aics_cb; + vcp_register_param.aics_param[i].cb = &aics_server_cb; } vcp_register_param.step = 1; @@ -570,6 +528,9 @@ uint8_t tester_init_vcs(void) return BTP_STATUS_FAILED; } + aics_server_instance.aics_cnt = included.aics_cnt; + aics_server_instance.aics = included.aics; + tester_register_command_handlers(BTP_SERVICE_ID_VCS, vcs_handlers, ARRAY_SIZE(vcs_handlers)); @@ -581,28 +542,488 @@ uint8_t tester_unregister_vcs(void) return BTP_STATUS_SUCCESS; } -uint8_t tester_init_aics(void) +uint8_t tester_init_vocs(void) { - tester_register_command_handlers(BTP_SERVICE_ID_AICS, aics_handlers, - ARRAY_SIZE(aics_handlers)); + tester_register_command_handlers(BTP_SERVICE_ID_VOCS, vocs_handlers, + ARRAY_SIZE(vocs_handlers)); - return tester_init_vcs(); + return BTP_STATUS_SUCCESS; } -uint8_t tester_unregister_aics(void) +uint8_t tester_unregister_vocs(void) { return BTP_STATUS_SUCCESS; } -uint8_t tester_init_vocs(void) +/* Volume Control Profile */ +static void btp_send_vcp_found_ev(struct bt_conn *conn, uint8_t att_status, + const struct service_handles *chrc_handles) { - tester_register_command_handlers(BTP_SERVICE_ID_VOCS, vocs_handlers, - ARRAY_SIZE(vocs_handlers)); + struct btp_vcp_discovered_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.att_status = att_status; + ev.vcs_handles.control_handle = sys_cpu_to_le16(chrc_handles->vcp_handles.ctrl_pt); + ev.vcs_handles.flag_handle = sys_cpu_to_le16(chrc_handles->vcp_handles.flags); + ev.vcs_handles.state_handle = sys_cpu_to_le16(chrc_handles->vcp_handles.state); + ev.vocs_handles.state_handle = sys_cpu_to_le16(chrc_handles->vocs_handles.state); + ev.vocs_handles.location_handle = sys_cpu_to_le16(chrc_handles->vocs_handles.location); + ev.vocs_handles.control_handle = sys_cpu_to_le16(chrc_handles->vocs_handles.control); + ev.vocs_handles.desc_handle = sys_cpu_to_le16(chrc_handles->vocs_handles.desc); + ev.aics_handles.state_handle = sys_cpu_to_le16(chrc_handles->aics_handles.state); + ev.aics_handles.gain_handle = sys_cpu_to_le16(chrc_handles->aics_handles.gain); + ev.aics_handles.type_handle = sys_cpu_to_le16(chrc_handles->aics_handles.type); + ev.aics_handles.status_handle = sys_cpu_to_le16(chrc_handles->aics_handles.status); + ev.aics_handles.control_handle = sys_cpu_to_le16(chrc_handles->aics_handles.control); + ev.aics_handles.desc_handle = sys_cpu_to_le16(chrc_handles->aics_handles.desc); + + tester_event(BTP_SERVICE_ID_VCP, BTP_VCP_DISCOVERED_EV, &ev, sizeof(ev)); +} - return tester_init_vcs(); +static void btp_send_vcp_state_ev(struct bt_conn *conn, uint8_t att_status, uint8_t volume, + uint8_t mute) +{ + struct btp_vcp_state_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.att_status = att_status; + ev.volume = volume; + ev.mute = mute; + + tester_event(BTP_SERVICE_ID_VCP, BTP_VCP_STATE_EV, &ev, sizeof(ev)); } -uint8_t tester_unregister_vocs(void) +static void btp_send_vcp_volume_flags_ev(struct bt_conn *conn, uint8_t att_status, uint8_t flags) +{ + struct btp_vcp_volume_flags_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.att_status = att_status; + ev.flags = flags; + + tester_event(BTP_SERVICE_ID_VCP, BTP_VCP_FLAGS_EV, &ev, sizeof(ev)); +} + +static void btp_send_vcp_procedure_ev(struct bt_conn *conn, uint8_t att_status, uint8_t opcode) +{ + struct btp_vcp_procedure_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.att_status = att_status; + ev.opcode = opcode; + + tester_event(BTP_SERVICE_ID_VCP, BTP_VCP_PROCEDURE_EV, &ev, sizeof(ev)); +} + +static uint8_t vcp_supported_commands(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + struct btp_vcp_read_supported_commands_rp *rp = rsp; + + /* octet 0 */ + tester_set_bit(rp->data, BTP_VCP_READ_SUPPORTED_COMMANDS); + tester_set_bit(rp->data, BTP_VCP_VOL_CTLR_DISCOVER); + tester_set_bit(rp->data, BTP_VCP_VOL_CTLR_STATE_READ); + tester_set_bit(rp->data, BTP_VCP_VOL_CTLR_FLAGS_READ); + tester_set_bit(rp->data, BTP_VCP_VOL_CTLR_VOL_DOWN); + tester_set_bit(rp->data, BTP_VCP_VOL_CTLR_VOL_UP); + tester_set_bit(rp->data, BTP_VCP_VOL_CTLR_UNMUTE_VOL_DOWN); + + /* octet 1 */ + tester_set_bit(rp->data, BTP_VCP_VOL_CTLR_UNMUTE_VOL_UP); + tester_set_bit(rp->data, BTP_VCP_VOL_CTLR_SET_VOL); + tester_set_bit(rp->data, BTP_VCP_VOL_CTLR_UNMUTE); + tester_set_bit(rp->data, BTP_VCP_VOL_CTLR_MUTE); + + *rsp_len = sizeof(*rp) + 1; + + return BTP_STATUS_SUCCESS; +} + +static void vcp_vol_ctlr_discover_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err, uint8_t vocs_count, + uint8_t aics_count) +{ + struct bt_conn *conn; + + if (err) { + LOG_DBG("Discovery failed (%d)", err); + return; + } + + LOG_DBG("Discovery done with %u VOCS, %u AICS", + vocs_count, aics_count); + + bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn); + + if (bt_vcp_vol_ctlr_included_get(vol_ctlr, &included) != 0) { + LOG_DBG("Could not get included services"); + memset(&chrc_handles.vocs_handles, 0, sizeof(chrc_handles.vocs_handles)); + memset(&chrc_handles.aics_handles, 0, sizeof(chrc_handles.aics_handles)); + } else { + aics_client_instance.aics_cnt = included.aics_cnt; + aics_client_instance.aics = included.aics; + bt_vocs_client_cb_register(vol_ctlr->vocs[0], &vocs_cl_cb); + bt_aics_client_cb_register(vol_ctlr->aics[0], &aics_client_cb); + + struct bt_vocs_client *vocs_cli = + CONTAINER_OF(vol_ctlr->vocs[0], struct bt_vocs_client, vocs); + struct bt_aics_client *aics_cli = &vol_ctlr->aics[0]->cli; + + chrc_handles.vocs_handles.state = vocs_cli->state_handle; + chrc_handles.vocs_handles.location = vocs_cli->location_handle; + chrc_handles.vocs_handles.control = vocs_cli->control_handle; + chrc_handles.vocs_handles.desc = vocs_cli->desc_handle; + chrc_handles.aics_handles.state = aics_cli->state_handle; + chrc_handles.aics_handles.gain = aics_cli->gain_handle; + chrc_handles.aics_handles.type = aics_cli->type_handle; + chrc_handles.aics_handles.status = aics_cli->status_handle; + chrc_handles.aics_handles.control = aics_cli->control_handle; + chrc_handles.aics_handles.desc = aics_cli->desc_handle; + } + + chrc_handles.vcp_handles.ctrl_pt = vol_ctlr->control_handle; + chrc_handles.vcp_handles.flags = vol_ctlr->flag_handle; + chrc_handles.vcp_handles.state = vol_ctlr->state_handle; + btp_send_vcp_found_ev(conn, err, &chrc_handles); +} + +static void vcp_vol_ctlr_state_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err, uint8_t volume, + uint8_t mute) +{ + struct bt_conn *conn; + + bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn); + btp_send_vcp_state_ev(conn, err, volume, mute); + + LOG_DBG("VCP Volume CTLR State callback"); +} + +static void vcp_vol_ctlr_flags_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err, uint8_t flags) +{ + struct bt_conn *conn; + + bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn); + btp_send_vcp_volume_flags_ev(conn, err, flags); + + LOG_DBG("VCP CTLR Volume Flags callback"); +} + +static void vcp_vol_ctlr_vol_down_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err) +{ + struct bt_conn *conn; + + bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn); + btp_send_vcp_procedure_ev(conn, err, BTP_VCP_VOL_CTLR_VOL_DOWN); + + LOG_DBG("VCP CTLR Volume down callback"); +} + +static void vcp_vol_ctlr_vol_up_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err) +{ + struct bt_conn *conn; + + bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn); + btp_send_vcp_procedure_ev(conn, err, BTP_VCP_VOL_CTLR_VOL_UP); + + LOG_DBG("VCP CTLR Volume down callback"); +} + +static void vcp_vol_ctlr_unmute_vol_down_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err) +{ + struct bt_conn *conn; + + bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn); + btp_send_vcp_procedure_ev(conn, err, BTP_VCP_VOL_CTLR_UNMUTE_VOL_DOWN); + + LOG_DBG("VCP CTLR Volume down and unmute callback"); +} + +static void vcp_vol_ctlr_unmute_vol_up_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err) +{ + struct bt_conn *conn; + + bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn); + btp_send_vcp_procedure_ev(conn, err, BTP_VCP_VOL_CTLR_UNMUTE_VOL_UP); + + LOG_DBG("VCP CTLR Volume down and unmute callback"); +} + +static void vcp_vol_ctlr_set_vol_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err) +{ + struct bt_conn *conn; + + bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn); + btp_send_vcp_procedure_ev(conn, err, BTP_VCP_VOL_CTLR_SET_VOL); + + LOG_DBG("VCP CTLR Set absolute volume callback"); +} + +static void vcp_vol_ctlr_unmute_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err) +{ + struct bt_conn *conn; + + bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn); + btp_send_vcp_procedure_ev(conn, err, BTP_VCP_VOL_CTLR_UNMUTE); + + LOG_DBG("VCP CTLR Volume down and unmute callback"); +} + +static void vcp_vol_ctlr_mute_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err) +{ + struct bt_conn *conn; + + bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn); + btp_send_vcp_procedure_ev(conn, err, BTP_VCP_VOL_CTLR_MUTE); + + LOG_DBG("VCP CTLR Set absolute volume callback"); +} + +static struct bt_vcp_vol_ctlr_cb vcp_cbs = { + .discover = vcp_vol_ctlr_discover_cb, + .state = vcp_vol_ctlr_state_cb, + .flags = vcp_vol_ctlr_flags_cb, + .vol_down = vcp_vol_ctlr_vol_down_cb, + .vol_up = vcp_vol_ctlr_vol_up_cb, + .mute = vcp_vol_ctlr_mute_cb, + .unmute = vcp_vol_ctlr_unmute_cb, + .vol_down_unmute = vcp_vol_ctlr_unmute_vol_down_cb, + .vol_up_unmute = vcp_vol_ctlr_unmute_vol_up_cb, + .vol_set = vcp_vol_ctlr_set_vol_cb +}; + +static uint8_t vcp_discover(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_vcp_discover_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_vcp_vol_ctlr_discover(conn, &vol_ctlr); + if (err) { + LOG_DBG("Fail: %d", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t vcp_state_read(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + int err; + + LOG_DBG("VCP State read"); + + err = bt_vcp_vol_ctlr_read_state(vol_ctlr); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t vcp_volume_flags_read(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + int err; + + LOG_DBG("VCP Volume Flags read"); + + err = bt_vcp_vol_ctlr_read_flags(vol_ctlr); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t vcp_ctlr_vol_down(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + int err; + + LOG_DBG("VCP CTLR Volume down"); + + err = bt_vcp_vol_ctlr_vol_down(vol_ctlr); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t vcp_ctlr_vol_up(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + int err; + + LOG_DBG("VCP CTLR Volume up"); + + err = bt_vcp_vol_ctlr_vol_up(vol_ctlr); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t vcp_ctlr_unmute_vol_down(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + int err; + + LOG_DBG("VCP CTLR Unmute, vol down"); + + err = bt_vcp_vol_ctlr_unmute_vol_down(vol_ctlr); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t vcp_ctlr_unmute_vol_up(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + int err; + + LOG_DBG("VCP CTLR Unmute, Volume up"); + + err = bt_vcp_vol_ctlr_unmute_vol_up(vol_ctlr); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t vcp_ctlr_set_vol(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_vcp_ctlr_set_vol_cmd *cp = cmd; + int err; + + LOG_DBG("VCP CTLR Set absolute volume %d", cp->volume); + + err = bt_vcp_vol_ctlr_set_vol(vol_ctlr, cp->volume); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t vcp_ctlr_unmute(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + int err; + + LOG_DBG("VCP CTLR Unmute"); + + err = bt_vcp_vol_ctlr_unmute(vol_ctlr); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t vcp_ctlr_mute(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + int err; + + LOG_DBG("VCP CTLR Mute"); + + err = bt_vcp_vol_ctlr_mute(vol_ctlr); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static const struct btp_handler vcp_handlers[] = { + { + .opcode = BTP_VCP_READ_SUPPORTED_COMMANDS, + .index = BTP_INDEX_NONE, + .expect_len = 0, + .func = vcp_supported_commands, + }, + { + .opcode = BTP_VCP_VOL_CTLR_DISCOVER, + .expect_len = sizeof(struct btp_vcp_discover_cmd), + .func = vcp_discover, + }, + { + .opcode = BTP_VCP_VOL_CTLR_STATE_READ, + .expect_len = sizeof(struct btp_vcp_state_read_cmd), + .func = vcp_state_read, + }, + { + .opcode = BTP_VCP_VOL_CTLR_FLAGS_READ, + .expect_len = sizeof(struct btp_vcp_flags_read_cmd), + .func = vcp_volume_flags_read, + }, + { + .opcode = BTP_VCP_VOL_CTLR_VOL_DOWN, + .expect_len = sizeof(struct btp_vcp_ctlr_vol_down_cmd), + .func = vcp_ctlr_vol_down, + }, + { + .opcode = BTP_VCP_VOL_CTLR_VOL_UP, + .expect_len = sizeof(struct btp_vcp_ctlr_vol_up_cmd), + .func = vcp_ctlr_vol_up, + }, + { + .opcode = BTP_VCP_VOL_CTLR_UNMUTE_VOL_DOWN, + .expect_len = sizeof(struct btp_vcp_ctlr_unmute_vol_down_cmd), + .func = vcp_ctlr_unmute_vol_down, + }, + { + .opcode = BTP_VCP_VOL_CTLR_UNMUTE_VOL_UP, + .expect_len = sizeof(struct btp_vcp_ctlr_unmute_vol_up_cmd), + .func = vcp_ctlr_unmute_vol_up, + }, + { + .opcode = BTP_VCP_VOL_CTLR_SET_VOL, + .expect_len = sizeof(struct btp_vcp_ctlr_set_vol_cmd), + .func = vcp_ctlr_set_vol, + }, + { + .opcode = BTP_VCP_VOL_CTLR_UNMUTE, + .expect_len = sizeof(struct btp_vcp_ctlr_unmute_cmd), + .func = vcp_ctlr_unmute, + }, + { + .opcode = BTP_VCP_VOL_CTLR_MUTE, + .expect_len = sizeof(struct btp_vcp_ctlr_mute_cmd), + .func = vcp_ctlr_mute, + }, +}; + +uint8_t tester_init_vcp(void) +{ + int err; + + err = bt_vcp_vol_ctlr_cb_register(&vcp_cbs); + + if (err) { + LOG_DBG("Failed to register callbacks: %d", err); + return BTP_STATUS_FAILED; + } + + tester_register_command_handlers(BTP_SERVICE_ID_VCP, vcp_handlers, + ARRAY_SIZE(vcp_handlers)); + + return BTP_STATUS_SUCCESS; +} + +uint8_t tester_unregister_vcp(void) { + (void)bt_vcp_vol_ctlr_cb_register(NULL); return BTP_STATUS_SUCCESS; } diff --git a/tests/bluetooth/tester/testcase.yaml b/tests/bluetooth/tester/testcase.yaml index dba67716af1..8c36291b30f 100644 --- a/tests/bluetooth/tester/testcase.yaml +++ b/tests/bluetooth/tester/testcase.yaml @@ -4,6 +4,7 @@ tests: platform_allow: - qemu_x86 - native_posix + - native_sim - nrf52840dk_nrf52840 tags: bluetooth harness: bluetooth @@ -12,6 +13,7 @@ tests: platform_allow: - qemu_x86 - native_posix + - native_sim - nrf5340dk_nrf5340_cpuapp extra_args: OVERLAY_CONFIG="overlay-le-audio.conf" tags: bluetooth @@ -21,6 +23,7 @@ tests: platform_allow: - qemu_x86 - native_posix + - native_sim - nrf52840dk_nrf52840 extra_args: OVERLAY_CONFIG="overlay-mesh.conf" tags: bluetooth @@ -30,6 +33,7 @@ tests: platform_allow: - qemu_x86 - native_posix + - native_sim - nrf52840dk_nrf52840 extra_args: OVERLAY_CONFIG="overlay-mesh.conf;overlay-mesh-v1d1.conf" tags: bluetooth diff --git a/tests/bluetooth/uuid/prj.conf b/tests/bluetooth/uuid/prj.conf index 84088e6b035..fec5098eecf 100644 --- a/tests/bluetooth/uuid/prj.conf +++ b/tests/bluetooth/uuid/prj.conf @@ -1,6 +1,5 @@ CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BT=y CONFIG_BT_CTLR=n diff --git a/tests/boards/altera_max10/i2c_master/prj.conf b/tests/boards/altera_max10/i2c_master/prj.conf index 875d1696308..3ec96195906 100644 --- a/tests/boards/altera_max10/i2c_master/prj.conf +++ b/tests/boards/altera_max10/i2c_master/prj.conf @@ -1,4 +1,3 @@ CONFIG_I2C=y CONFIG_I2C_INIT_PRIORITY=60 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/boards/altera_max10/msgdma/prj.conf b/tests/boards/altera_max10/msgdma/prj.conf index 1d460e0c60f..ac2c3481e93 100644 --- a/tests/boards/altera_max10/msgdma/prj.conf +++ b/tests/boards/altera_max10/msgdma/prj.conf @@ -1,3 +1,2 @@ CONFIG_DMA=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/boards/altera_max10/qspi/prj.conf b/tests/boards/altera_max10/qspi/prj.conf index 3c9f3c6f619..c1de9b374e2 100644 --- a/tests/boards/altera_max10/qspi/prj.conf +++ b/tests/boards/altera_max10/qspi/prj.conf @@ -2,4 +2,3 @@ CONFIG_STDOUT_CONSOLE=y CONFIG_FLASH=y CONFIG_SOC_FLASH_NIOS2_QSPI=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/boards/altera_max10/sysid/prj.conf b/tests/boards/altera_max10/sysid/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/boards/altera_max10/sysid/prj.conf +++ b/tests/boards/altera_max10/sysid/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/boards/espressif_esp32/cache_coex/prj.conf b/tests/boards/espressif_esp32/cache_coex/prj.conf index 6265acda775..577a3f115e1 100644 --- a/tests/boards/espressif_esp32/cache_coex/prj.conf +++ b/tests/boards/espressif_esp32/cache_coex/prj.conf @@ -5,4 +5,3 @@ CONFIG_ESP_HEAP_SEARCH_ALL_REGIONS=n CONFIG_FLASH=y CONFIG_ENTROPY_GENERATOR=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/boards/espressif_esp32/cache_coex/src/cache_coex.c b/tests/boards/espressif_esp32/cache_coex/src/cache_coex.c index b89b6c8aece..7f2370ed6e1 100644 --- a/tests/boards/espressif_esp32/cache_coex/src/cache_coex.c +++ b/tests/boards/espressif_esp32/cache_coex/src/cache_coex.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include /* definitions used in Flash & RAM operations */ diff --git a/tests/boards/frdm_k64f/i2c/prj.conf b/tests/boards/frdm_k64f/i2c/prj.conf index cc1ebd041b5..21a62cda1d8 100644 --- a/tests/boards/frdm_k64f/i2c/prj.conf +++ b/tests/boards/frdm_k64f/i2c/prj.conf @@ -3,4 +3,3 @@ CONFIG_I2C_CALLBACK=y CONFIG_POLL=y CONFIG_I2C_INIT_PRIORITY=60 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/boards/intel_adsp/cache/prj.conf b/tests/boards/intel_adsp/cache/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/boards/intel_adsp/cache/prj.conf +++ b/tests/boards/intel_adsp/cache/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/boards/intel_adsp/hda/prj.conf b/tests/boards/intel_adsp/hda/prj.conf index a91b5e32bbd..0d43e90cdf3 100644 --- a/tests/boards/intel_adsp/hda/prj.conf +++ b/tests/boards/intel_adsp/hda/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_DMA=y diff --git a/tests/boards/intel_adsp/hda_log/prj.conf b/tests/boards/intel_adsp/hda_log/prj.conf index 0e6000bdc4f..2fd4793b5d9 100644 --- a/tests/boards/intel_adsp/hda_log/prj.conf +++ b/tests/boards/intel_adsp/hda_log/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_DMA=y CONFIG_ASSERT=y CONFIG_LOG=y diff --git a/tests/boards/intel_adsp/mm/prj.conf b/tests/boards/intel_adsp/mm/prj.conf index 7ccdfd1ddf2..06a1545dad7 100644 --- a/tests/boards/intel_adsp/mm/prj.conf +++ b/tests/boards/intel_adsp/mm/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MM_DRV=y diff --git a/tests/boards/intel_adsp/smoke/prj.conf b/tests/boards/intel_adsp/smoke/prj.conf index f8f0f741aa4..a30e22b8c55 100644 --- a/tests/boards/intel_adsp/smoke/prj.conf +++ b/tests/boards/intel_adsp/smoke/prj.conf @@ -1,8 +1,6 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SMP=y CONFIG_SMP_BOOT_DELAY=y CONFIG_SCHED_CPU_MASK=y CONFIG_IPM=y CONFIG_IPM_CAVS_HOST=y -CONFIG_IPM_CAVS_IDC=n diff --git a/tests/boards/intel_adsp/ssp/prj.conf b/tests/boards/intel_adsp/ssp/prj.conf index 49124c6d82c..5acbe35fdf4 100644 --- a/tests/boards/intel_adsp/ssp/prj.conf +++ b/tests/boards/intel_adsp/ssp/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_DAI=y CONFIG_INTEL_MN=y CONFIG_DMA_DW_HOST_MASK=1 diff --git a/tests/boards/mec15xxevb_assy6853/i2c_api/prj.conf b/tests/boards/mec15xxevb_assy6853/i2c_api/prj.conf index 7e3f6b38804..4b19609ecfb 100644 --- a/tests/boards/mec15xxevb_assy6853/i2c_api/prj.conf +++ b/tests/boards/mec15xxevb_assy6853/i2c_api/prj.conf @@ -1,3 +1,2 @@ CONFIG_I2C=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/boards/mec15xxevb_assy6853/qspi/prj.conf b/tests/boards/mec15xxevb_assy6853/qspi/prj.conf index 0637abd47e2..45cd80f14c1 100644 --- a/tests/boards/mec15xxevb_assy6853/qspi/prj.conf +++ b/tests/boards/mec15xxevb_assy6853/qspi/prj.conf @@ -1,5 +1,4 @@ CONFIG_SPI=y CONFIG_SPI_EXTENDED_MODES=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y diff --git a/tests/boards/mec172xevb_assy6906/i2c_api/prj.conf b/tests/boards/mec172xevb_assy6906/i2c_api/prj.conf index 7e3f6b38804..4b19609ecfb 100644 --- a/tests/boards/mec172xevb_assy6906/i2c_api/prj.conf +++ b/tests/boards/mec172xevb_assy6906/i2c_api/prj.conf @@ -1,3 +1,2 @@ CONFIG_I2C=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/boards/mec172xevb_assy6906/qspi/CMakeLists.txt b/tests/boards/mec172xevb_assy6906/qspi/CMakeLists.txt new file mode 100644 index 00000000000..5c672271901 --- /dev/null +++ b/tests/boards/mec172xevb_assy6906/qspi/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(qspi) + +target_sources(app PRIVATE src/main.c) diff --git a/tests/boards/mec172xevb_assy6906/qspi/README.txt b/tests/boards/mec172xevb_assy6906/qspi/README.txt new file mode 100644 index 00000000000..6cab25952b5 --- /dev/null +++ b/tests/boards/mec172xevb_assy6906/qspi/README.txt @@ -0,0 +1,2 @@ +Build test for: + Microchip mec172xevb_assy6906 qspi driver test. diff --git a/tests/boards/mec172xevb_assy6906/qspi/boards/mec172xevb_assy6906.overlay b/tests/boards/mec172xevb_assy6906/qspi/boards/mec172xevb_assy6906.overlay new file mode 100644 index 00000000000..c59d40a485e --- /dev/null +++ b/tests/boards/mec172xevb_assy6906/qspi/boards/mec172xevb_assy6906.overlay @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&spi0 { + status = "okay"; + chip-select = <0>; + lines = <4>; + + pinctrl-0 = < &shd_cs0_n_gpio055 + &shd_clk_gpio056 + &shd_io0_gpio223 + &shd_io1_gpio224 + &shd_io2_gpio227 + &shd_io3_gpio016 >; +}; diff --git a/tests/boards/mec172xevb_assy6906/qspi/prj.conf b/tests/boards/mec172xevb_assy6906/qspi/prj.conf new file mode 100644 index 00000000000..45cd80f14c1 --- /dev/null +++ b/tests/boards/mec172xevb_assy6906/qspi/prj.conf @@ -0,0 +1,4 @@ +CONFIG_SPI=y +CONFIG_SPI_EXTENDED_MODES=y +CONFIG_ZTEST=y +CONFIG_TEST_USERSPACE=y diff --git a/tests/boards/mec172xevb_assy6906/qspi/src/main.c b/tests/boards/mec172xevb_assy6906/qspi/src/main.c new file mode 100644 index 00000000000..feac946c46e --- /dev/null +++ b/tests/boards/mec172xevb_assy6906/qspi/src/main.c @@ -0,0 +1,657 @@ +/* + * Copyright (c) 2020 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#define TEST_FREQ_HZ 24000000U +#define W25Q128_JEDEC_ID 0x001840efU + +#define TEST_BUF_SIZE 4096U +/* #define MAX_SPI_BUF 8 */ + +#define SPI_STATUS1_BUSY 0x01U +#define SPI_STATUS1_WEL 0x02U +#define SPI_STATUS2_QE 0x02U +#define SPI_READ_JEDEC_ID 0x9FU +#define SPI_READ_STATUS1 0x05U +#define SPI_READ_STATUS2 0x35U +#define SPI_WRITE_STATUS2 0x31U +#define SPI_WRITE_ENABLE_VS 0x50U +#define SPI_WRITE_ENABLE 0x06U +#define SPI_SECTOR_ERASE 0x20U +#define SPI_SINGLE_WRITE_DATA 0x02U +#define SPI_QUAD_WRITE_DATA 0x32U + +/* bits[7:0] = spi opcode, + * bits[15:8] = bytes number of clocks with data lines tri-stated + */ +#define SPI_FAST_READ_DATA 0x080BU +#define SPI_DUAL_FAST_READ_DATA 0x083BU +#define SPI_QUAD_FAST_READ_DATA 0x086BU +#define SPI_OCTAL_QUAD_READ_DATA 0xE3U + +#define BUF_SIZE 11 +uint8_t buffer_tx[] = "0123456789\0"; +#define BUF_SIZE_2 7 +uint8_t buffer_tx_2[] = "abcdef\0"; + +#define SPI_TEST_ADDRESS 0x000010U +#define SPI_TEST_ADDRESS_2 0x000020U + +static uint8_t safbuf[TEST_BUF_SIZE] __aligned(4); +static uint8_t safbuf2[TEST_BUF_SIZE] __aligned(4); +static const struct device *const spi_dev = DEVICE_DT_GET(DT_NODELABEL(spi0)); + +/* static struct spi_buf spi_bufs[MAX_SPI_BUF]; */ + +static const struct spi_config spi_cfg_single = { + .frequency = TEST_FREQ_HZ, + .operation = (SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8) + | SPI_LINES_SINGLE), +}; + +static const struct spi_config spi_cfg_single_hold_cs = { + .frequency = TEST_FREQ_HZ, + .operation = (SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8) + | SPI_LINES_SINGLE | SPI_HOLD_ON_CS), +}; + +static const struct spi_config spi_cfg_dual = { + .frequency = TEST_FREQ_HZ, + .operation = (SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8) + | SPI_LINES_DUAL), +}; + +static const struct spi_config spi_cfg_quad = { + .frequency = TEST_FREQ_HZ, + .operation = (SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8) + | SPI_LINES_QUAD), +}; + +static void spi_single_init(void) +{ + zassert_true(device_is_ready(spi_dev), "SPI controller device is not ready"); +} + +static void clear_buffers(void) +{ + memset(safbuf, 0, sizeof(safbuf)); + memset(safbuf2, 0, sizeof(safbuf2)); +} + +/* Compute the number of bytes required to generate the requested number of + * SPI clocks based on single, dual, or quad mode. + * mode = 1(full-duplex), 2(dual), 4(quad) + * full-duplex: 8 clocks per byte + * dual: 4 clocks per byte + * quad: 2 clocks per byte + */ +static uint32_t spi_clocks_to_bytes(uint32_t spi_clocks, uint8_t mode) +{ + uint32_t nbytes; + + if (mode == 4u) { + nbytes = spi_clocks / 2U; + } else if (mode == 2u) { + nbytes = spi_clocks / 4U; + } else { + nbytes = spi_clocks / 8U; + } + + return nbytes; +} + + +static int spi_flash_address_format(uint8_t *dest, size_t destsz, + uint32_t spi_addr, size_t addrsz) +{ + if (!dest || (addrsz == 0) || (addrsz > 4U) || (addrsz > destsz)) { + return -EINVAL; + } + + for (size_t i = 0; i < addrsz; i++) { + dest[i] = (uint8_t)((spi_addr >> ((addrsz - (i + 1U)) * 8U)) & 0xffU); + } + + return 0; +} + +static int spi_flash_read_status(const struct device *dev, uint8_t opcode, uint8_t *status) +{ + struct spi_buf spi_bufs[2] = { 0 }; + uint32_t txdata = 0; + uint32_t rxdata = 0; + int ret = 0; + + txdata = opcode; + + spi_bufs[0].buf = &txdata; + spi_bufs[0].len = 1U; + spi_bufs[1].buf = &rxdata; + spi_bufs[1].len = 1U; + + const struct spi_buf_set txset = { + .buffers = &spi_bufs[0], + .count = 2U, + }; + const struct spi_buf_set rxset = { + .buffers = &spi_bufs[0], + .count = 2U, + }; + + ret = spi_transceive(spi_dev, &spi_cfg_single, &txset, &rxset); + if (ret) { + return ret; + } + + if (status) { + *status = (uint8_t)(rxdata & 0xffu); + } + + return 0; +} + +static int spi_flash_write_status(const struct device *dev, uint8_t opcode, uint8_t spi_status) +{ + struct spi_buf spi_bufs[1] = { 0 }; + uint32_t txdata = 0; + int ret = 0; + + txdata = spi_status; + txdata <<= 8U; + txdata |= opcode; + + spi_bufs[0].buf = &txdata; + spi_bufs[0].len = 2U; + + const struct spi_buf_set txset = { + .buffers = &spi_bufs[0], + .count = 1U, + }; + + ret = spi_transceive(spi_dev, &spi_cfg_single, &txset, NULL); + if (ret) { + return ret; + } + + return 0; +} + +static int spi_flash_tx_one_byte_cmd(const struct device *dev, uint8_t opcode) +{ + struct spi_buf spi_bufs[1] = { 0 }; + uint32_t txdata = 0; + int ret = 0; + + txdata = opcode; + spi_bufs[0].buf = &txdata; + spi_bufs[0].len = 1U; + + const struct spi_buf_set txset = { + .buffers = &spi_bufs[0], + .count = 1U, + }; + + ret = spi_transceive(spi_dev, &spi_cfg_single, &txset, NULL); + if (ret) { + return ret; + } + + return 0; +} + +/** + * @brief Test spi device + * @details + * - Find spi device + * - Read flash jedec id + */ +ZTEST_USER(spi, test_spi_device) +{ + struct spi_buf spi_bufs[2] = { 0 }; + uint32_t txdata = 0; + uint32_t jedec_id = 0; + int ret = 0; + + /* read jedec id */ + txdata = SPI_READ_JEDEC_ID; + + spi_bufs[0].buf = &txdata; + spi_bufs[0].len = 1U; + spi_bufs[1].buf = &jedec_id; + spi_bufs[1].len = 3U; + + const struct spi_buf_set txset = { + .buffers = &spi_bufs[0], + .count = 2U, + }; + const struct spi_buf_set rxset = { + .buffers = &spi_bufs[0], + .count = 2U, + }; + + ret = spi_transceive(spi_dev, &spi_cfg_single, &txset, &rxset); + zassert_true(ret == 0, "Read JEDEC ID spi_transceive failure: " + "error %d", ret); + zassert_true(jedec_id == W25Q128_JEDEC_ID, + "JEDEC ID doesn't match: expected 0x%08x, read 0x%08x", + W25Q128_JEDEC_ID, jedec_id); +} + +/** + * @brief Test spi sector erase + * @details + * - write enable + * - erase data in flash device + * - read register1 and wait for erase operation completed + */ +ZTEST_USER(spi_sector_erase, test_spi_sector_erase) +{ + struct spi_buf spi_bufs[2] = { 0 }; + int ret = 0; + uint8_t spi_status = 0; + + clear_buffers(); + + /* write enable */ + ret = spi_flash_tx_one_byte_cmd(spi_dev, SPI_WRITE_ENABLE); + zassert_true(ret == 0, "Send write enable spi_transceive failure: error %d", ret); + + /* erase data start from address SPI_TEST_ADDRESS */ + safbuf[0] = SPI_SECTOR_ERASE; + spi_flash_address_format(&safbuf[1], 4U, SPI_TEST_ADDRESS, 3U); + + spi_bufs[0].buf = &safbuf; + spi_bufs[0].len = 4; + + const struct spi_buf_set txset = { + .buffers = &spi_bufs[0], + .count = 1U, + }; + + ret = spi_transceive(spi_dev, &spi_cfg_single, &txset, NULL); + zassert_true(ret == 0, "Send sector erase data spi_transceive failure: error %d", ret); + + /* read SPI flash status register1 to check whether erase operation completed */ + spi_status = SPI_STATUS1_BUSY; + while (spi_status & SPI_STATUS1_BUSY) { + ret = spi_flash_read_status(spi_dev, SPI_READ_STATUS1, &spi_status); + zassert_true(ret == 0, "Send read register1 spi_transceive " + "failure: error %d", ret); + } +} + +/** + * @brief Write data into flash using spi api + * @details + * - flash write enable + * - write data into flash using spi api + */ +static void test_spi_single_write(void) +{ + struct spi_buf spi_bufs[1] = { 0 }; + int ret = 0; + uint8_t spi_status = 0; + + clear_buffers(); + + ret = spi_flash_tx_one_byte_cmd(spi_dev, SPI_WRITE_ENABLE); + zassert_true(ret == 0, "Send write enable spi_transceive failure: " + "error %d", ret); + + /* write data start from address SPI_TEST_ADDRESS */ + safbuf[0] = SPI_SINGLE_WRITE_DATA; + spi_flash_address_format(&safbuf[1], 4U, SPI_TEST_ADDRESS, 3U); + + memcpy(&safbuf[4], buffer_tx, BUF_SIZE); + + spi_bufs[0].buf = &safbuf; + spi_bufs[0].len = 4U + BUF_SIZE; + + const struct spi_buf_set txset = { + .buffers = &spi_bufs[0], + .count = 1U, + }; + + ret = spi_transceive(spi_dev, &spi_cfg_single, &txset, NULL); + zassert_true(ret == 0, "Send write data spi_transceive failure: error %d", ret); + + /* read register1 to check whether program operation completed */ + spi_status = SPI_STATUS1_BUSY; + while (spi_status & SPI_STATUS1_BUSY) { + ret = spi_flash_read_status(spi_dev, SPI_READ_STATUS1, &spi_status); + zassert_true(ret == 0, "Read SPI flash STATUS opcode 0x%02x error: %d", + SPI_READ_STATUS1, ret); + } +} + +/** + * @brief Read data from flash using spi single mode + * @details + * - read data using spi single mode + * - check read buffer data whether correct + * @note SPI flash fast instructions require a certain number of SPI clocks + * to be generated with I/O lines tri-stated after the address has been + * transmitted. The purpose is allow SPI flash time to move get data ready + * and enable its output line(s). The MCHP XEC SPI driver can do this by + * specifying a struct spi_buf with buf pointer set to NULL and length set + * to the number of bytes which will generate the required number of clocks. + * For full-duplex one byte is 8 clocks, dual one byte is 4 clocks, and for + * quad one byte is 2 clocks. + */ +ZTEST_USER(spi, test_spi_single_read) +{ + struct spi_buf spi_bufs[3] = { 0 }; + int ret = 0; + uint16_t spi_opcode = 0; + uint8_t cnt = 0; + + clear_buffers(); + + /* bits[7:0] = opcode, + * bits[15:8] = number of SPI clocks with I/O lines tri-stated after + * address transmit before data read phase. + */ + spi_opcode = SPI_FAST_READ_DATA; + + /* read data using spi single mode */ + /* set the spi operation code and address */ + safbuf[0] = spi_opcode & 0xFFU; + spi_flash_address_format(&safbuf[1], 4U, SPI_TEST_ADDRESS, 3U); + + spi_bufs[cnt].buf = &safbuf; + spi_bufs[cnt].len = 4U; + + /* set the dummy clocks */ + if (spi_opcode & 0xFF00U) { + cnt++; + spi_bufs[cnt].buf = NULL; + spi_bufs[cnt].len = spi_clocks_to_bytes(((spi_opcode >> 8) & 0xffU), 1u); + } + + cnt++; + spi_bufs[cnt].buf = &safbuf2; + spi_bufs[cnt].len = BUF_SIZE; + cnt++; /* total number of buffers */ + + const struct spi_buf_set txset = { + .buffers = &spi_bufs[0], + .count = cnt, + }; + + const struct spi_buf_set rxset = { + .buffers = &spi_bufs[0], + .count = cnt, + }; + + ret = spi_transceive(spi_dev, &spi_cfg_single, &txset, &rxset); + zassert_true(ret == 0, "Send fast read data spi_transceive failure: error %d", ret); + + /* check read buffer data whether correct */ + zassert_true(memcmp(buffer_tx, safbuf2, BUF_SIZE) == 0, + "Buffer read data is different to write data"); +} + +static void spi_dual_init(void) +{ + zassert_true(device_is_ready(spi_dev), "SPI controller device is not ready"); +} + +/** + * @brief Read data from flash using spi dual mode + * @details + * - read data using spi dual mode + * - check read buffer data whether correct + */ +ZTEST_USER(spi, test_spi_dual_read) +{ + struct spi_buf spi_bufs[3] = { 0 }; + int ret = 0; + uint16_t spi_opcode = 0; + uint8_t cnt = 0; + + clear_buffers(); + + spi_dual_init(); + + spi_opcode = SPI_DUAL_FAST_READ_DATA; + + /* read data using spi dual mode */ + /* set the spi operation code and address */ + safbuf[0] = spi_opcode & 0xFFU; + spi_flash_address_format(&safbuf[1], 4U, SPI_TEST_ADDRESS, 3U); + + spi_bufs[cnt].buf = &safbuf; + spi_bufs[cnt].len = 4U; + + /* set the dummy clocks */ + if (spi_opcode & 0xFF00U) { + cnt++; + spi_bufs[cnt].buf = NULL; + spi_bufs[cnt].len = spi_clocks_to_bytes(((spi_opcode >> 8) & 0xffU), 1u); + } + + cnt++; + spi_bufs[cnt].buf = &safbuf2; + spi_bufs[cnt].len = BUF_SIZE; + + const struct spi_buf_set txset = { + .buffers = &spi_bufs[0], + .count = cnt, + }; + + const struct spi_buf_set rxset = { + .buffers = &spi_bufs[cnt], + .count = 1U, + }; + + /* send opcode, address, and tri-state clocks using single mode */ + ret = spi_transceive(spi_dev, &spi_cfg_single_hold_cs, &txset, NULL); + zassert_true(ret == 0, "Send fast read data spi_transceive failure: error %d", ret); + + /* get read data using dual mode */ + ret = spi_transceive(spi_dev, &spi_cfg_dual, NULL, &rxset); + zassert_true(ret == 0, "Receive fast read data spi_transceive failure: error %d", ret); + + /* check read buffer data whether correct */ + zassert_true(memcmp(buffer_tx, safbuf2, BUF_SIZE) == 0, + "Buffer read data is different to write data"); + + /* release spi device */ + ret = spi_release(spi_dev, &spi_cfg_single); + zassert_true(ret == 0, "Spi release failure: error %d", ret); +} + +/** + * @brief Write data into flash using spi quad mode + * @details + * - check and make sure spi quad mode is enabled + * - write data using spi quad mode + */ +static void test_spi_quad_write(void) +{ + struct spi_buf spi_bufs[2] = { 0 }; + int ret = 0; + uint8_t spi_status = 0; + uint8_t spi_status2 = 0; + + clear_buffers(); + + /* read register2 to judge whether quad mode is enabled */ + ret = spi_flash_read_status(spi_dev, SPI_READ_STATUS2, &spi_status2); + zassert_true(ret == 0, "SPI read flash STATUS2 failure: error %d", ret); + + /* set register2 QE=1 to enable quad mode. We write the volatile STATUS2 register + * not the normal STATUS2 which retains the value across a power cycle. + */ + if ((spi_status2 & SPI_STATUS2_QE) == 0U) { + ret = spi_flash_tx_one_byte_cmd(spi_dev, SPI_WRITE_ENABLE_VS); + zassert_true(ret == 0, "Send write enable volatile spi_transceive failure: " + "error %d", ret); + + spi_status2 |= SPI_STATUS2_QE; + ret = spi_flash_write_status(spi_dev, SPI_WRITE_STATUS2, spi_status2); + zassert_true(ret == 0, "Write spi status2 QE=1 spi_transceive failure: " + "error %d", ret); + + /* read register2 to confirm quad mode is enabled */ + spi_status2 = 0u; + ret = spi_flash_read_status(spi_dev, SPI_READ_STATUS2, &spi_status2); + zassert_true(ret == 0, "Read register2 status spi_transceive failure: " + "error %d", ret); + + zassert_true((spi_status2 & SPI_STATUS2_QE) == SPI_STATUS2_QE, + "Enable QSPI mode failure"); + } + + /* write enable */ + ret = spi_flash_tx_one_byte_cmd(spi_dev, SPI_WRITE_ENABLE); + zassert_true(ret == 0, "Send write enable spi_transceive failure: error %d", ret); + + /* write data using spi quad mode */ + /* send quad write opcode and address using single mode */ + safbuf[0] = SPI_QUAD_WRITE_DATA; + spi_flash_address_format(&safbuf[1], 4U, SPI_TEST_ADDRESS_2, 3U); + + spi_bufs[0].buf = &safbuf; + spi_bufs[0].len = 4; + + const struct spi_buf_set txset = { + .buffers = &spi_bufs[0], + .count = 1U, + }; + + ret = spi_transceive(spi_dev, &spi_cfg_single_hold_cs, &txset, NULL); + zassert_true(ret == 0, "Send quad write data spi_transceive failure: error %d", ret); + + /* send data using quad mode */ + memcpy(&safbuf[0], buffer_tx_2, BUF_SIZE_2); + + spi_bufs[0].buf = &safbuf; + spi_bufs[0].len = BUF_SIZE_2; + + ret = spi_transceive(spi_dev, &spi_cfg_quad, &txset, NULL); + zassert_true(ret == 0, "Send quad write data spi_transceive failure: error %d", ret); + + /* call SPI release API to clear SPI CS Hold On lock */ + ret = spi_release(spi_dev, &spi_cfg_single); + zassert_true(ret == 0, "Spi release failure: error %d", ret); + + /* poll busy bit in flash status1 register */ + spi_status = SPI_STATUS1_BUSY; + while (spi_status & SPI_STATUS1_BUSY) { + ret = spi_flash_read_status(spi_dev, SPI_READ_STATUS1, &spi_status); + zassert_true(ret == 0, "Read flash STATUS1 register error %d", ret); + } +} + +/** + * @brief Read data from flash using spi quad mode + * @details + * - read data using spi quad mode + * - check read buffer data whether correct + */ +ZTEST_USER(spi_quad, test_spi_quad_read) +{ + struct spi_buf spi_bufs[3] = {0}; + int ret = 0; + uint16_t spi_opcode = 0; + uint8_t cnt = 0; + + clear_buffers(); + + spi_opcode = SPI_QUAD_FAST_READ_DATA; + + /* read data using spi quad mode + * Transmit opcode, address, and tri-state clocks using full-duplex mode + * with driver Hold CS ON flag. + * Next, read data using dual configuration. + * Call driver release API to release lock set by Hold CS ON flag. + */ + + /* set the spi operation code and address */ + safbuf[0] = spi_opcode & 0xFFU; + spi_flash_address_format(&safbuf[1], 4U, SPI_TEST_ADDRESS_2, 3U); + + spi_bufs[cnt].buf = &safbuf; + spi_bufs[cnt].len = 4U; + + /* set the dummy clocks */ + if (spi_opcode & 0xFF00U) { + cnt++; + spi_bufs[cnt].buf = NULL; + spi_bufs[cnt].len = spi_clocks_to_bytes(((spi_opcode >> 8) & 0xffU), 1u); + } + + cnt++; + spi_bufs[cnt].buf = &safbuf2; + spi_bufs[cnt].len = BUF_SIZE_2; + + const struct spi_buf_set txset = { + .buffers = &spi_bufs[0], + .count = cnt, + }; + + const struct spi_buf_set rxset = { + .buffers = &spi_bufs[cnt], + .count = 1U, + }; + + /* send opcode and address using single mode with Hold CS ON flag */ + ret = spi_transceive(spi_dev, &spi_cfg_single_hold_cs, &txset, NULL); + zassert_true(ret == 0, "Send fast read data spi_transceive failure: error %d", ret); + + /* read data using quad mode */ + ret = spi_transceive(spi_dev, &spi_cfg_quad, NULL, &rxset); + zassert_true(ret == 0, "Receive fast read data spi_transceive failure: error %d", ret); + + /* release spi device */ + ret = spi_release(spi_dev, &spi_cfg_single); + zassert_true(ret == 0, "Spi release failure: error %d", ret); + + /* check read buffer data whether correct */ + zassert_true(memcmp(buffer_tx_2, safbuf2, BUF_SIZE_2) == 0, + "Buffer read data is different to write data"); +} + +void *spi_setup(void) +{ + spi_single_init(); + + return NULL; +} + +void *spi_single_setup(void) +{ + spi_single_init(); + + /* The writing test goes + * first berfore testing + * the reading. + */ + test_spi_single_write(); + + return NULL; +} + +void *spi_quad_setup(void) +{ + spi_dual_init(); + + /* The writing test goes + * first berfore testing + * the reading. + */ + test_spi_quad_write(); + + return NULL; +} + +/* Test assumes flash test regions is in erased state */ +ZTEST_SUITE(spi, NULL, spi_single_setup, NULL, NULL, NULL); +ZTEST_SUITE(spi_quad, NULL, spi_quad_setup, NULL, NULL, NULL); +ZTEST_SUITE(spi_sector_erase, NULL, spi_setup, NULL, NULL, NULL); diff --git a/tests/boards/mec172xevb_assy6906/qspi/testcase.yaml b/tests/boards/mec172xevb_assy6906/qspi/testcase.yaml new file mode 100644 index 00000000000..f0302f66cbb --- /dev/null +++ b/tests/boards/mec172xevb_assy6906/qspi/testcase.yaml @@ -0,0 +1,7 @@ +tests: + boards.mec172xevb_assy6906.qspi: + platform_allow: mec172xevb_assy6906 + tags: + - drivers + - spi + - qspi diff --git a/tests/boards/native_posix/cpu_wait/prj.conf b/tests/boards/native_posix/cpu_wait/prj.conf index 55d02e5dad7..868a51c52b0 100644 --- a/tests/boards/native_posix/cpu_wait/prj.conf +++ b/tests/boards/native_posix/cpu_wait/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TICKLESS_KERNEL=n CONFIG_ZTEST_THREAD_PRIORITY=1 diff --git a/tests/boards/native_posix/rtc/prj.conf b/tests/boards/native_posix/rtc/prj.conf index 82d90a522d3..686b5a9dee3 100644 --- a/tests/boards/native_posix/rtc/prj.conf +++ b/tests/boards/native_posix/rtc/prj.conf @@ -1,3 +1,2 @@ CONFIG_NATIVE_POSIX_SLOWDOWN_TO_REAL_TIME=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/boards/nrf52_bsim/egu/prj.conf b/tests/boards/nrf52_bsim/egu/prj.conf index bcc4d42973f..ac89734f004 100644 --- a/tests/boards/nrf52_bsim/egu/prj.conf +++ b/tests/boards/nrf52_bsim/egu/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_GEN_IRQ_VECTOR_TABLE=y CONFIG_DYNAMIC_INTERRUPTS=y diff --git a/tests/boot/mcuboot_data_sharing/CMakeLists.txt b/tests/boot/mcuboot_data_sharing/CMakeLists.txt new file mode 100644 index 00000000000..6bdbb43d36b --- /dev/null +++ b/tests/boot/mcuboot_data_sharing/CMakeLists.txt @@ -0,0 +1,30 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(mcuboot_recovery_retention) + +if(NOT (DEFINED SYSBUILD)) + message(FATAL_ERROR "This test must be built with sysbuild.") +endif() + +FILE(GLOB app_sources + src/*.c +) + +target_sources(app PRIVATE ${app_sources}) + +# Get MCUboot version from the VERSION file in the repository and create a local output header +# version file so that it can be compared against in the test +set(VERSION_FILE ${ZEPHYR_MCUBOOT_MODULE_DIR}/boot/zephyr/VERSION) +set(VERSION_TYPE MCUBOOT) +set(BUILD_VERSION_NAME MCUBOOT_BUILD_VERSION) +include(${ZEPHYR_BASE}/cmake/modules/version.cmake) +file(READ ${ZEPHYR_BASE}/version.h.in version_content) +string(CONFIGURE "${version_content}" version_content) +string(CONFIGURE "${version_content}" version_content) +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/zephyr/include/generated/mcuboot_version.h "${version_content}") diff --git a/tests/boot/mcuboot_data_sharing/boards/nrf52840dk_nrf52840.conf b/tests/boot/mcuboot_data_sharing/boards/nrf52840dk_nrf52840.conf new file mode 100644 index 00000000000..8f39b13f7ec --- /dev/null +++ b/tests/boot/mcuboot_data_sharing/boards/nrf52840dk_nrf52840.conf @@ -0,0 +1,7 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_RETAINED_MEM_NRF_GPREGRET=n +CONFIG_RETAINED_MEM_ZEPHYR_RAM=y diff --git a/tests/boot/mcuboot_data_sharing/boards/nrf52840dk_nrf52840.overlay b/tests/boot/mcuboot_data_sharing/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 00000000000..5aaff71d8d7 --- /dev/null +++ b/tests/boot/mcuboot_data_sharing/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/ { + sram@2003F000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x2003F000 DT_SIZE_K(1)>; + zephyr,memory-region = "RetainedMem"; + status = "okay"; + + retainedmem { + compatible = "zephyr,retained-ram"; + status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + + boot_info0: boot_info@0 { + compatible = "zephyr,retention"; + status = "okay"; + reg = <0x0 0x100>; + }; + }; + }; + + chosen { + zephyr,bootloader-info = &boot_info0; + }; +}; + +/delete-node/ &gpregret1; +/delete-node/ &gpregret2; +/delete-node/ &boot_partition; +/delete-node/ &slot0_partition; +/delete-node/ &slot1_partition; + +&sram0 { + reg = <0x20000000 DT_SIZE_K(255)>; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x00020000>; + }; + slot0_partition: partition@20000 { + label = "image-0"; + reg = <0x00020000 0x00022000>; + }; + slot1_partition: partition@42000 { + label = "image-1"; + reg = <0x00042000 0x00024000>; + }; + }; +}; diff --git a/tests/boot/mcuboot_data_sharing/prj.conf b/tests/boot/mcuboot_data_sharing/prj.conf new file mode 100644 index 00000000000..ba709fadb62 --- /dev/null +++ b/tests/boot/mcuboot_data_sharing/prj.conf @@ -0,0 +1,13 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_ZTEST=y +CONFIG_RETAINED_MEM=y +CONFIG_RETENTION=y +CONFIG_SETTINGS=y +CONFIG_SETTINGS_RUNTIME=y +CONFIG_RETENTION_BOOTLOADER_INFO=y +CONFIG_RETENTION_BOOTLOADER_INFO_TYPE_MCUBOOT=y +CONFIG_RETENTION_BOOTLOADER_INFO_OUTPUT_SETTINGS=y diff --git a/tests/boot/mcuboot_data_sharing/src/main.c b/tests/boot/mcuboot_data_sharing/src/main.c new file mode 100644 index 00000000000..1cf3954169b --- /dev/null +++ b/tests/boot/mcuboot_data_sharing/src/main.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define FLASH_SECTOR_SIZE 1024 +#define FLASH_SECTOR_SIZE_KB 4 +#define FLASH_MAX_APP_SECTORS 34 +#define FLASH_RESERVED_SECTORS 1 +#define FLASH_MAX_APP_SIZE ((FLASH_MAX_APP_SECTORS - FLASH_RESERVED_SECTORS) \ + * FLASH_SECTOR_SIZE_KB) +#define RUNNING_SLOT 0 + +ZTEST(mcuboot_shared_data, test_mode) +{ + uint8_t var[1]; + int rc; + + memset(var, 0xff, sizeof(var)); + rc = settings_runtime_get("blinfo/mode", var, sizeof(var)); + zassert_equal(rc, sizeof(var), "Expected data length mismatch"); + zassert_equal(var[0], MCUBOOT_MODE_SWAP_USING_MOVE, "Expected data mismatch"); +} + +ZTEST(mcuboot_shared_data, test_signature_type) +{ + uint8_t var[1]; + int rc; + + memset(var, 0xff, sizeof(var)); + rc = settings_runtime_get("blinfo/signature_type", var, sizeof(var)); + zassert_equal(rc, sizeof(var), "Expected data length mismatch"); + zassert_equal(var[0], MCUBOOT_SIGNATURE_TYPE_RSA, "Expected data mismatch"); +} + +ZTEST(mcuboot_shared_data, test_recovery) +{ + uint8_t var[1]; + int rc; + + memset(var, 0xff, sizeof(var)); + rc = settings_runtime_get("blinfo/recovery", var, sizeof(var)); + zassert_equal(rc, sizeof(var), "Expected data length mismatch"); + zassert_equal(var[0], MCUBOOT_RECOVERY_MODE_NONE, "Expected data mismatch"); +} + +ZTEST(mcuboot_shared_data, test_running_slot) +{ + uint8_t var[1]; + int rc; + + memset(var, 0xff, sizeof(var)); + rc = settings_runtime_get("blinfo/running_slot", var, sizeof(var)); + zassert_equal(rc, sizeof(var), "Expected data length mismatch"); + zassert_equal(var[0], RUNNING_SLOT, "Expected data mismatch"); +} + +ZTEST(mcuboot_shared_data, test_bootloader_version) +{ + uint8_t var[8]; + int rc; + struct image_version *version = (void *)var; + + memset(var, 0xff, sizeof(var)); + rc = settings_runtime_get("blinfo/bootloader_version", var, sizeof(var)); + zassert_equal(rc, sizeof(var), "Expected data length mismatch"); + + zassert_equal(version->iv_major, MCUBOOT_VERSION_MAJOR, + "Expected version (major) mismatch"); + zassert_equal(version->iv_minor, MCUBOOT_VERSION_MINOR, + "Expected version (minor) mismatch"); + zassert_equal(version->iv_revision, MCUBOOT_PATCHLEVEL, + "Expected version (patch level) mismatch"); + zassert_equal(version->iv_build_num, 0, "Expected version (build number) mismatch"); +} + +ZTEST(mcuboot_shared_data, test_max_application_size) +{ + uint8_t var[4]; + uint32_t value; + int rc; + + memset(var, 0xff, sizeof(var)); + rc = settings_runtime_get("blinfo/max_application_size", var, sizeof(var)); + zassert_equal(rc, sizeof(var), "Expected data length mismatch"); + memcpy(&value, var, sizeof(value)); + value /= FLASH_SECTOR_SIZE; + zassert_equal(value, FLASH_MAX_APP_SIZE, "Expected data mismatch"); +} + +ZTEST(mcuboot_shared_data, test_invalid) +{ + uint8_t var[4]; + int rc; + + memset(var, 0xff, sizeof(var)); + rc = settings_runtime_get("blinfo/does_not_exist", var, sizeof(var)); + zassert_not_equal(rc, sizeof(var), "Expected data length (error) mismatch"); + zassert_not_equal(rc, 0, "Expected data length (error) mismatch"); +} + +ZTEST(mcuboot_shared_data, test_bootloader_version_limited) +{ + uint8_t var[2]; + int rc; + + memset(var, 0xff, sizeof(var)); + rc = settings_runtime_get("blinfo/bootloader_version", var, sizeof(var)); + zassert_not_equal(rc, sizeof(var), "Expected data length mismatch"); +} + +ZTEST_SUITE(mcuboot_shared_data, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/boot/mcuboot_data_sharing/sysbuild.conf b/tests/boot/mcuboot_data_sharing/sysbuild.conf new file mode 100644 index 00000000000..47f00ff3cff --- /dev/null +++ b/tests/boot/mcuboot_data_sharing/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_BOOTLOADER_MCUBOOT=y diff --git a/tests/boot/mcuboot_data_sharing/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf b/tests/boot/mcuboot_data_sharing/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf new file mode 100644 index 00000000000..0553e1bd746 --- /dev/null +++ b/tests/boot/mcuboot_data_sharing/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf @@ -0,0 +1,5 @@ +CONFIG_USE_SEGGER_RTT=n +CONFIG_NORDIC_QSPI_NOR=n +CONFIG_BOOT_VALIDATE_SLOT0=n +CONFIG_MCUBOOT_CLEANUP_ARM_CORE=n +CONFIG_BOOT_WATCHDOG_FEED=n diff --git a/tests/boot/mcuboot_data_sharing/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay b/tests/boot/mcuboot_data_sharing/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 00000000000..e54f7fbf3a3 --- /dev/null +++ b/tests/boot/mcuboot_data_sharing/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +#include "../../../boards/nrf52840dk_nrf52840.overlay" + +/ { + chosen { + zephyr,code-partition = &boot_partition; + }; +}; diff --git a/tests/boot/mcuboot_data_sharing/sysbuild/mcuboot/prj.conf b/tests/boot/mcuboot_data_sharing/sysbuild/mcuboot/prj.conf new file mode 100644 index 00000000000..102bd1bc1bf --- /dev/null +++ b/tests/boot/mcuboot_data_sharing/sysbuild/mcuboot/prj.conf @@ -0,0 +1,7 @@ +CONFIG_RETAINED_MEM=y +CONFIG_RETENTION=y +CONFIG_BOOT_SHARE_DATA=y +CONFIG_BOOT_SHARE_DATA_BOOTINFO=y +CONFIG_BOOT_SHARE_BACKEND_RETENTION=y +CONFIG_FLASH=y +CONFIG_FLASH_MAP=y diff --git a/tests/boot/mcuboot_data_sharing/testcase.yaml b/tests/boot/mcuboot_data_sharing/testcase.yaml new file mode 100644 index 00000000000..b12fb012f4b --- /dev/null +++ b/tests/boot/mcuboot_data_sharing/testcase.yaml @@ -0,0 +1,14 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +common: + sysbuild: true +tests: + bootloader.mcuboot.data.sharing: + platform_allow: nrf52840dk_nrf52840 + tags: + - mcuboot + - sysbuild + - retention diff --git a/tests/boot/mcuboot_recovery_retention/boards/nrf52840dk_nrf52840.overlay b/tests/boot/mcuboot_recovery_retention/boards/nrf52840dk_nrf52840.overlay index 2257c1a8888..bd69d21527d 100644 --- a/tests/boot/mcuboot_recovery_retention/boards/nrf52840dk_nrf52840.overlay +++ b/tests/boot/mcuboot_recovery_retention/boards/nrf52840dk_nrf52840.overlay @@ -3,6 +3,7 @@ / { chosen { zephyr,boot-mode = &boot_mode0; + zephyr,uart-mcumgr = &cdc_acm_uart; }; }; @@ -16,6 +17,14 @@ }; }; +&zephyr_udc0 { + status = "okay"; + + cdc_acm_uart: cdc_acm_uart { + compatible = "zephyr,cdc-acm-uart"; + }; +}; + /delete-node/ &boot_partition; /delete-node/ &slot0_partition; /delete-node/ &slot1_partition; diff --git a/tests/boot/mcuboot_recovery_retention/boards/nrf52840dk_nrf52840_mem.overlay b/tests/boot/mcuboot_recovery_retention/boards/nrf52840dk_nrf52840_mem.overlay index 907b1c0cb50..a6b9dc2e528 100644 --- a/tests/boot/mcuboot_recovery_retention/boards/nrf52840dk_nrf52840_mem.overlay +++ b/tests/boot/mcuboot_recovery_retention/boards/nrf52840dk_nrf52840_mem.overlay @@ -26,6 +26,15 @@ chosen { zephyr,boot-mode = &boot_mode0; + zephyr,uart-mcumgr = &cdc_acm_uart; + }; +}; + +&zephyr_udc0 { + status = "okay"; + + cdc_acm_uart: cdc_acm_uart { + compatible = "zephyr,cdc-acm-uart"; }; }; diff --git a/tests/boot/mcuboot_recovery_retention/sysbuild.conf b/tests/boot/mcuboot_recovery_retention/sysbuild.conf index 47f00ff3cff..3b5b3c96380 100644 --- a/tests/boot/mcuboot_recovery_retention/sysbuild.conf +++ b/tests/boot/mcuboot_recovery_retention/sysbuild.conf @@ -1 +1,2 @@ SB_CONFIG_BOOTLOADER_MCUBOOT=y +SB_CONFIG_PARTITION_MANAGER=n diff --git a/tests/boot/mcuboot_recovery_retention/testcase.yaml b/tests/boot/mcuboot_recovery_retention/testcase.yaml index a66c361c1d2..084aedcba58 100644 --- a/tests/boot/mcuboot_recovery_retention/testcase.yaml +++ b/tests/boot/mcuboot_recovery_retention/testcase.yaml @@ -21,13 +21,13 @@ common: - "Secondary image: magic" - "Boot source: none" tests: - mcuboot.recovery.retention: + bootloader.mcuboot.recovery.retention: platform_allow: nrf52840dk_nrf52840 tags: - mcuboot - sysbuild - recovery - mcuboot.recovery.retention.mem: + bootloader.mcuboot.recovery.retention.mem: platform_allow: nrf52840dk_nrf52840 extra_args: - OVERLAY_CONFIG="boards/nrf52840dk_nrf52840_mem.conf" diff --git a/tests/boot/test_mcuboot/sysbuild.conf b/tests/boot/test_mcuboot/sysbuild.conf index 47f00ff3cff..3b5b3c96380 100644 --- a/tests/boot/test_mcuboot/sysbuild.conf +++ b/tests/boot/test_mcuboot/sysbuild.conf @@ -1 +1,2 @@ SB_CONFIG_BOOTLOADER_MCUBOOT=y +SB_CONFIG_PARTITION_MANAGER=n diff --git a/tests/boot/test_mcuboot/testcase.yaml b/tests/boot/test_mcuboot/testcase.yaml index 20f29f0a41b..c5622139386 100644 --- a/tests/boot/test_mcuboot/testcase.yaml +++ b/tests/boot/test_mcuboot/testcase.yaml @@ -10,17 +10,24 @@ common: - "I: Starting swap using (.*)" - "Swapped application booted on (.*)" tests: - boot.mcuboot: + bootloader.mcuboot: tags: mcuboot - skip: true # disabled due to issue #58080 platform_allow: - frdm_k64f + - mimxrt1020_evk + - mimxrt1024_evk + - mimxrt1050_evk - mimxrt1060_evk + - mimxrt1064_evk + - mimxrt1160_evk_cm7 + - mimxrt1170_evk_cm7 + - mimxrt595_evk_cm33 + - mimxrt685_evk_cm33 - nrf52840dk_nrf52840 integration_platforms: - frdm_k64f - nrf52840dk_nrf52840 - boot.mcuboot.assert: + bootloader.mcuboot.assert: tags: mcuboot platform_allow: - b_u585i_iot02a diff --git a/tests/boot/uefi/prj.conf b/tests/boot/uefi/prj.conf index 17df3666c72..48ca509cdd5 100644 --- a/tests/boot/uefi/prj.conf +++ b/tests/boot/uefi/prj.conf @@ -1,4 +1,4 @@ CONFIG_QEMU_UEFI_BOOT=y CONFIG_BUILD_OUTPUT_EFI=y CONFIG_SRAM_SIZE=204800 -CONFIG_X86_ACPI=y +CONFIG_ACPI=y diff --git a/tests/boot/with_mcumgr/CMakeLists.txt b/tests/boot/with_mcumgr/CMakeLists.txt new file mode 100644 index 00000000000..640c52434a4 --- /dev/null +++ b/tests/boot/with_mcumgr/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(with_mcumgr) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/boot/with_mcumgr/README.rst b/tests/boot/with_mcumgr/README.rst new file mode 100644 index 00000000000..5f0ef82d30a --- /dev/null +++ b/tests/boot/with_mcumgr/README.rst @@ -0,0 +1,30 @@ +Upgrade testing with MCUmgr +########################### + +This application is based on :ref:`smp_svr_sample`. It is built +using **sysbuild**. Tests are automated with pytest, a new harness of Twister +(more information can be found here :ref:`integration-with-pytest`) + +.. note:: + Pytest uses the MCUmgr fixture which requires the ``mcumgr`` available + in the system PATH. + More information about MCUmgr can be found here :ref:`mcu_mgr`. + +To run tests with Twister on ``nrf52840dk_nrf52840`` platform, +use following command: + +.. code-block:: console + + ./zephyr/scripts/twister -vv --west-flash --enable-slow -T zephyr/tests/boot/with_mcumgr \ + -p nrf52840dk_nrf52840 --device-testing --device-serial /dev/ttyACM0 + +.. note:: + Twister requires ``--west-flash`` flag enabled (without additional parameters + like ``erase``) to use sysbuild. + +Test scripts can be found in ``pytest`` directory. To list available +scenarios with described procedures, one can use a pytest command: + +.. code-block:: console + + pytest zephyr/tests/boot/with_mcumgr/pytest --collect-only -v diff --git a/tests/boot/with_mcumgr/prj.conf b/tests/boot/with_mcumgr/prj.conf new file mode 100644 index 00000000000..3ddf7a4a45d --- /dev/null +++ b/tests/boot/with_mcumgr/prj.conf @@ -0,0 +1,23 @@ +# Enable MCUmgr and dependencies. +CONFIG_NET_BUF=y +CONFIG_ZCBOR=y +CONFIG_CRC=y +CONFIG_MCUMGR=y +CONFIG_STREAM_FLASH=y +CONFIG_FLASH_MAP=y + +# Enable the shell MCUmgr transport. +CONFIG_BASE64=y +CONFIG_SHELL=y +CONFIG_MCUBOOT_SHELL=y +CONFIG_SHELL_BACKEND_SERIAL=y +CONFIG_MCUMGR_TRANSPORT_SHELL=y + +# Enable most core commands. +CONFIG_FLASH=y +CONFIG_IMG_MANAGER=y +CONFIG_MCUMGR_GRP_IMG=y +CONFIG_MCUMGR_GRP_OS=y + +# mcumgr-cli application doesn't accepts log in the channel it uses +CONFIG_SHELL_LOG_BACKEND=n diff --git a/tests/boot/with_mcumgr/pytest/test_downgrade_prevention.py b/tests/boot/with_mcumgr/pytest/test_downgrade_prevention.py new file mode 100755 index 00000000000..a4439c26fba --- /dev/null +++ b/tests/boot/with_mcumgr/pytest/test_downgrade_prevention.py @@ -0,0 +1,62 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations + +import logging + +from pathlib import Path +from twister_harness import DeviceAdapter, Shell, MCUmgr +from utils import ( + find_in_config, + match_lines, + match_no_lines, + check_with_shell_command, + check_with_mcumgr_command, +) +from test_upgrade import create_signed_image, PROJECT_NAME + + +logger = logging.getLogger(__name__) + + +def test_downgrade_prevention(dut: DeviceAdapter, shell: Shell, mcumgr: MCUmgr): + """ + Verify that the application is not downgraded + 1) Device flashed with MCUboot and an application that contains SMP server. + Image version is 1.1.1+1 + 2) Prepare an update of an application containing the SMP server, where + image version is 0.0.0 (lower than version of the original app) + 3) Upload the application update to slot 1 using mcumgr + 4) Flag the application update in slot 1 as 'pending' by using mcumgr 'test' + 5) Restart the device, verify that downgrade prevention mechanism + blocked the image swap + 6) Verify that the original application is booted (version 1.1.1) + """ + origin_version = find_in_config( + Path(dut.device_config.build_dir) / PROJECT_NAME / 'zephyr' / '.config', + 'CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION' + ) + check_with_shell_command(shell, origin_version) + assert origin_version != '0.0.0+0' + + logger.info('Prepare upgrade image with lower version') + image_to_test = create_signed_image(dut.device_config.build_dir, '0.0.0+0') + + logger.info('Upload image with mcumgr') + dut.disconnect() + mcumgr.image_upload(image_to_test) + + logger.info('Test uploaded APP image') + second_hash = mcumgr.get_hash_to_test() + mcumgr.image_test(second_hash) + mcumgr.reset_device() + + dut.connect() + output = dut.readlines_until('Launching primary slot application') + match_no_lines(output, ['Starting swap using move algorithm']) + match_lines(output, ['erased due to downgrade prevention']) + logger.info('Verify that the original APP is booted') + check_with_shell_command(shell, origin_version) + dut.disconnect() + check_with_mcumgr_command(mcumgr, origin_version) diff --git a/tests/boot/with_mcumgr/pytest/test_upgrade.py b/tests/boot/with_mcumgr/pytest/test_upgrade.py new file mode 100755 index 00000000000..7772bd197ee --- /dev/null +++ b/tests/boot/with_mcumgr/pytest/test_upgrade.py @@ -0,0 +1,204 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations + +import pytest +import logging + +from pathlib import Path +from twister_harness import DeviceAdapter, Shell, MCUmgr +from west_sign_wrapper import west_sign_with_imgtool +from utils import ( + find_in_config, + match_lines, + match_no_lines, + check_with_shell_command, + check_with_mcumgr_command, +) + +logger = logging.getLogger(__name__) +PROJECT_NAME = 'with_mcumgr' + + +def create_signed_image(build_dir: Path, version: str) -> Path: + image_to_test = Path(build_dir) / 'test_{}.signed.bin'.format( + version.replace('.', '_').replace('+', '_')) + origin_key_file = find_in_config( + Path(build_dir) / 'mcuboot' / 'zephyr' / '.config', + 'CONFIG_BOOT_SIGNATURE_KEY_FILE' + ) + west_sign_with_imgtool( + build_dir=Path(build_dir) / PROJECT_NAME, + output_bin=image_to_test, + key_file=Path(origin_key_file), + version=version + ) + assert image_to_test.is_file() + return image_to_test + + +def test_upgrade_with_confirm(dut: DeviceAdapter, shell: Shell, mcumgr: MCUmgr): + """ + Verify that the application can be updated + 1) Device flashed with MCUboot and an application that contains SMP server + 2) Prepare an update of an application containing the SMP server + 3) Upload the application update to slot 1 using mcumgr + 4) Flag the application update in slot 1 as 'pending' by using mcumgr 'test' + 5) Restart the device, verify that swapping process is initiated + 6) Verify that the updated application is booted + 7) Confirm the image using mcumgr + 8) Restart the device, and verify that the new application is still booted + """ + origin_version = find_in_config( + Path(dut.device_config.build_dir) / PROJECT_NAME / 'zephyr' / '.config', + 'CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION' + ) + check_with_shell_command(shell, origin_version) + + logger.info('Prepare upgrade image') + new_version = '0.0.2+0' + image_to_test = create_signed_image(dut.device_config.build_dir, new_version) + + logger.info('Upload image with mcumgr') + dut.disconnect() + mcumgr.image_upload(image_to_test) + + logger.info('Test uploaded APP image') + second_hash = mcumgr.get_hash_to_test() + mcumgr.image_test(second_hash) + mcumgr.reset_device() + + dut.connect() + output = dut.readlines_until('Launching primary slot application') + match_lines(output, [ + 'Swap type: test', + 'Starting swap using move algorithm' + ]) + logger.info('Verify new APP is booted') + check_with_shell_command(shell, new_version, swap_type='test') + dut.disconnect() + check_with_mcumgr_command(mcumgr, new_version) + + logger.info('Confirm the image') + mcumgr.image_confirm(second_hash) + mcumgr.reset_device() + + dut.connect() + output = dut.readlines_until('Launching primary slot application') + match_no_lines(output, [ + 'Starting swap using move algorithm' + ]) + logger.info('Verify new APP is still booted') + check_with_shell_command(shell, new_version) + + +def test_upgrade_with_revert(dut: DeviceAdapter, shell: Shell, mcumgr: MCUmgr): + """ + Verify that MCUboot will roll back an image that is not confirmed + 1) Device flashed with MCUboot and an application that contains SMP server + 2) Prepare an update of an application containing the SMP server + 3) Upload the application update to slot 1 using mcumgr + 4) Flag the application update in slot 1 as 'pending' by using mcumgr 'test' + 5) Restart the device, verify that swapping process is initiated + 6) Verify that the updated application is booted + 7) Reset the device without confirming the image + 8) Verify that MCUboot reverts update + """ + origin_version = find_in_config( + Path(dut.device_config.build_dir) / PROJECT_NAME / 'zephyr' / '.config', + 'CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION' + ) + check_with_shell_command(shell, origin_version) + + logger.info('Prepare upgrade image') + new_version = '0.0.3+0' + image_to_test = create_signed_image(dut.device_config.build_dir, new_version) + + logger.info('Upload image with mcumgr') + dut.disconnect() + mcumgr.image_upload(image_to_test) + + logger.info('Test uploaded APP image') + second_hash = mcumgr.get_hash_to_test() + mcumgr.image_test(second_hash) + mcumgr.reset_device() + + dut.connect() + output = dut.readlines_until('Launching primary slot application') + match_lines(output, [ + 'Swap type: test', + 'Starting swap using move algorithm' + ]) + logger.info('Verify new APP is booted') + check_with_shell_command(shell, new_version, swap_type='test') + dut.disconnect() + check_with_mcumgr_command(mcumgr, new_version) + + logger.info('Revert images') + mcumgr.reset_device() + + dut.connect() + output = dut.readlines_until('Launching primary slot application') + match_lines(output, [ + 'Swap type: revert', + 'Starting swap using move algorithm' + ]) + logger.info('Verify that MCUboot reverts update') + check_with_shell_command(shell, origin_version) + + +@pytest.mark.parametrize( + 'key_file', [None, 'root-ec-p256.pem'], + ids=[ + 'no_key', + 'invalid_key' + ]) +def test_upgrade_signature(dut: DeviceAdapter, shell: Shell, mcumgr: MCUmgr, key_file): + """ + Verify that the application is not updated when app is not signed or signed with invalid key + 1) Device flashed with MCUboot and an application that contains SMP server + 2) Prepare an update of an application containing the SMP server that has + been signed: + a) without any key + b) with a different key than MCUboot was compiled with + 3) Upload the application update to slot 1 using mcumgr + 4) Flag the application update in slot 1 as 'pending' by using mcumgr 'test' + 5) Restart the device, verify that swap is not started + """ + if key_file: + origin_key_file = find_in_config( + Path(dut.device_config.build_dir) / 'mcuboot' / 'zephyr' / '.config', + 'CONFIG_BOOT_SIGNATURE_KEY_FILE' + ).strip('"\'') + key_file = Path(origin_key_file).parent / key_file + assert key_file.is_file() + assert not key_file.samefile(origin_key_file) + image_to_test = image_to_test = Path(dut.device_config.build_dir) / 'test_invalid_key.bin' + logger.info('Sign second image with an invalid key') + else: + image_to_test = image_to_test = Path(dut.device_config.build_dir) / 'test_no_key.bin' + logger.info('Sign second imagewith no key') + + west_sign_with_imgtool( + build_dir=Path(dut.device_config.build_dir) / PROJECT_NAME, + output_bin=image_to_test, + key_file=key_file, + version='0.0.3+4' # must differ from the origin version, if not then hash is not updated + ) + assert image_to_test.is_file() + + logger.info('Upload image with mcumgr') + dut.disconnect() + mcumgr.image_upload(image_to_test) + + logger.info('Test uploaded APP image') + second_hash = mcumgr.get_hash_to_test() + mcumgr.image_test(second_hash) + mcumgr.reset_device() + + logger.info('Verify that swap is not started') + dut.connect() + output = dut.readlines_until('Launching primary slot application') + match_no_lines(output, ['Starting swap using move algorithm']) + match_lines(output, ['Image in the secondary slot is not valid']) diff --git a/tests/boot/with_mcumgr/pytest/utils.py b/tests/boot/with_mcumgr/pytest/utils.py new file mode 100644 index 00000000000..208bd92d166 --- /dev/null +++ b/tests/boot/with_mcumgr/pytest/utils.py @@ -0,0 +1,50 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations + +import logging +import re + +from pathlib import Path +from twister_harness import Shell, MCUmgr +from twister_harness.helpers.shell import ShellMCUbootCommandParsed + + +logger = logging.getLogger(__name__) + + +def find_in_config(config_file: Path | str, config_key: str) -> str: + re_key = re.compile(rf'{config_key}=(.+)') + with open(config_file) as f: + lines = f.readlines() + for line in lines: + if m := re_key.match(line): + logger.debug('Found matching key: %s' % line.strip()) + return m.group(1).strip('"\'') + return '' + + +def match_lines(output_lines: list[str], searched_lines: list[str]) -> None: + """Check all lines exist in the output""" + for sl in searched_lines: + assert any(sl in line for line in output_lines) + + +def match_no_lines(output_lines: list[str], searched_lines: list[str]) -> None: + """Check lines not found in the output""" + for sl in searched_lines: + assert all(sl not in line for line in output_lines) + + +def check_with_shell_command(shell: Shell, version: str, swap_type: str | None = None) -> None: + mcuboot_areas = ShellMCUbootCommandParsed.create_from_cmd_output(shell.exec_command('mcuboot')) + assert mcuboot_areas.areas[0].version == version + if swap_type: + assert mcuboot_areas.areas[0].swap_type == swap_type + + +def check_with_mcumgr_command(mcumgr: MCUmgr, version: str) -> None: + image_list = mcumgr.get_image_list() + # version displayed by MCUmgr does not print +0 and changes + to '.' for non-zero values + assert image_list[0].version == version.replace('+0', '').replace('+', '.') diff --git a/tests/boot/with_mcumgr/pytest/west_sign_wrapper.py b/tests/boot/with_mcumgr/pytest/west_sign_wrapper.py new file mode 100644 index 00000000000..daabac6c32e --- /dev/null +++ b/tests/boot/with_mcumgr/pytest/west_sign_wrapper.py @@ -0,0 +1,45 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations + +import logging +import shlex + +from subprocess import check_output +from pathlib import Path + + +logger = logging.getLogger(__name__) + + +def west_sign_with_imgtool( + build_dir: Path, + output_bin: Path | None = None, + key_file: Path | None = None, + version: str | None = None, + timeout: int = 10 +): + """Wrapper method for `west sign -t imgtool` comamnd""" + command = [ + 'west', 'sign', + '-t', 'imgtool', + '--no-hex', + '--build-dir', str(build_dir) + ] + if output_bin: + command.extend(['--sbin', str(output_bin)]) + + command_extra_args = [] + if key_file: + command_extra_args.extend(['--key', str(key_file)]) + if version: + command_extra_args.extend(['--version', version]) + + if command_extra_args: + command.append('--') + command.extend(command_extra_args) + + logger.info(f"CMD: {shlex.join(command)}") + output = check_output(command, text=True, timeout=timeout) + logger.debug('OUT: %s' % output) diff --git a/tests/boot/with_mcumgr/src/main.c b/tests/boot/with_mcumgr/src/main.c new file mode 100644 index 00000000000..ac05fd8ff51 --- /dev/null +++ b/tests/boot/with_mcumgr/src/main.c @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/* Main entry point */ +int main(void) +{ + printk("Launching primary slot application on %s\n", CONFIG_BOARD); + return 0; +} diff --git a/tests/boot/with_mcumgr/sysbuild.conf b/tests/boot/with_mcumgr/sysbuild.conf new file mode 100644 index 00000000000..47f00ff3cff --- /dev/null +++ b/tests/boot/with_mcumgr/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_BOOTLOADER_MCUBOOT=y diff --git a/tests/boot/with_mcumgr/sysbuild/mcuboot.conf b/tests/boot/with_mcumgr/sysbuild/mcuboot.conf new file mode 100644 index 00000000000..69938a0f972 --- /dev/null +++ b/tests/boot/with_mcumgr/sysbuild/mcuboot.conf @@ -0,0 +1 @@ +CONFIG_MCUBOOT_LOG_LEVEL_INF=y diff --git a/tests/boot/with_mcumgr/testcase.yaml b/tests/boot/with_mcumgr/testcase.yaml new file mode 100644 index 00000000000..08904c177bd --- /dev/null +++ b/tests/boot/with_mcumgr/testcase.yaml @@ -0,0 +1,34 @@ +common: + sysbuild: true + platform_allow: + - nrf52840dk_nrf52840 + - nrf5340dk_nrf5340_cpuapp + - nrf9160dk_nrf9160 + integration_platforms: + - nrf52840dk_nrf52840 + timeout: 600 + slow: true +tests: + boot.with_mcumgr.test_upgrade: + tags: + - pytest + - mcuboot + - mcumgr + harness: pytest + harness_config: + pytest_root: + - "pytest/test_upgrade.py" + + boot.with_mcumgr.test_downgrade_prevention: + tags: + - pytest + - mcuboot + - mcumgr + harness: pytest + harness_config: + pytest_root: + - "pytest/test_downgrade_prevention.py" + extra_args: + - mcuboot_CONFIG_MCUBOOT_DOWNGRADE_PREVENTION=y + extra_configs: + - CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION="1.1.1+1" diff --git a/tests/bsim/bluetooth/audio/prj.conf b/tests/bsim/bluetooth/audio/prj.conf index 8f2d6a585a9..8f387c8016f 100644 --- a/tests/bsim/bluetooth/audio/prj.conf +++ b/tests/bsim/bluetooth/audio/prj.conf @@ -117,6 +117,7 @@ CONFIG_BT_BAP_BROADCAST_ASSISTANT=y # Hearing Access CONFIG_BT_HAS=y +CONFIG_BT_HAS_PRESET_COUNT=3 CONFIG_BT_HAS_CLIENT=y CONFIG_BT_HAS_FEATURES_NOTIFIABLE=y @@ -201,7 +202,7 @@ CONFIG_BT_CTLR_ISOAL_SOURCES=2 CONFIG_BT_CTLR_ISOAL_SINKS=2 CONFIG_BT_CTLR_CONN_ISO_LOW_LATENCY_POLICY=y -CONFIG_BT_CTLR_ISO_TX_BUFFERS=3 +CONFIG_BT_CTLR_ISO_TX_BUFFERS=4 # Controller advanced options CONFIG_BT_CTLR_ADVANCED_FEATURES=y diff --git a/tests/bsim/bluetooth/audio/src/bap_broadcast_sink_test.c b/tests/bsim/bluetooth/audio/src/bap_broadcast_sink_test.c index 59c832ac3e3..70e2e74d738 100644 --- a/tests/bsim/bluetooth/audio/src/bap_broadcast_sink_test.c +++ b/tests/bsim/bluetooth/audio/src/bap_broadcast_sink_test.c @@ -17,20 +17,25 @@ extern enum bst_result_t bst_result; CREATE_FLAG(broadcaster_found); -CREATE_FLAG(base_received); +CREATE_FLAG(flag_base_received); CREATE_FLAG(flag_base_metadata_updated); CREATE_FLAG(pa_synced); CREATE_FLAG(flag_syncable); CREATE_FLAG(pa_sync_lost); CREATE_FLAG(flag_received); +CREATE_FLAG(flag_pa_request); +CREATE_FLAG(flag_bis_sync_requested); static struct bt_bap_broadcast_sink *g_sink; static struct bt_le_scan_recv_info broadcaster_info; static bt_addr_le_t broadcaster_addr; static struct bt_le_per_adv_sync *pa_sync; static uint32_t broadcaster_broadcast_id; -static struct bt_bap_stream broadcast_sink_streams[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT]; +static struct bap_test_stream broadcast_sink_streams[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT]; static struct bt_bap_stream *streams[ARRAY_SIZE(broadcast_sink_streams)]; +static uint32_t requested_bis_sync; +static struct bt_le_ext_adv *ext_adv; +static const struct bt_bap_scan_delegator_recv_state *req_recv_state; static const struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3( BT_AUDIO_CODEC_LC3_FREQ_ANY, BT_AUDIO_CODEC_LC3_DURATION_ANY, @@ -53,7 +58,7 @@ static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap { uint32_t base_bis_index_bitfield = 0U; - if (TEST_FLAG(base_received)) { + if (TEST_FLAG(flag_base_received)) { if (base->subgroup_count > 0 && memcmp(metadata, base->subgroups[0].codec_cfg.meta, @@ -62,6 +67,7 @@ static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap (void)memcpy(metadata, base->subgroups[0].codec_cfg.meta, sizeof(base->subgroups[0].codec_cfg.meta)); + printk("Metadata updated\n"); SET_FLAG(flag_base_metadata_updated); } @@ -82,7 +88,7 @@ static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap bis_index_bitfield = base_bis_index_bitfield & bis_index_mask; - SET_FLAG(base_received); + SET_FLAG(flag_base_received); } static void syncable_cb(struct bt_bap_broadcast_sink *sink, bool encrypted) @@ -185,6 +191,61 @@ static struct bt_pacs_cap cap = { .codec_cap = &codec_cap, }; +static int pa_sync_req_cb(struct bt_conn *conn, + const struct bt_bap_scan_delegator_recv_state *recv_state, + bool past_avail, uint16_t pa_interval) +{ + if (recv_state->pa_sync_state == BT_BAP_PA_STATE_SYNCED || + recv_state->pa_sync_state == BT_BAP_PA_STATE_INFO_REQ) { + /* Already syncing */ + /* TODO: Terminate existing sync and then sync to new?*/ + return -EALREADY; + } + + req_recv_state = recv_state; + + SET_FLAG(flag_pa_request); + + return 0; +} + +static int pa_sync_term_req_cb(struct bt_conn *conn, + const struct bt_bap_scan_delegator_recv_state *recv_state) +{ + if (pa_sync == NULL || recv_state->pa_sync_state == BT_BAP_PA_STATE_NOT_SYNCED) { + return -EALREADY; + } + + req_recv_state = recv_state; + + UNSET_FLAG(flag_pa_request); + + return 0; +} + +static int bis_sync_req_cb(struct bt_conn *conn, + const struct bt_bap_scan_delegator_recv_state *recv_state, + const uint32_t bis_sync_req[BT_BAP_SCAN_DELEGATOR_MAX_SUBGROUPS]) +{ + printk("BIS sync request received for %p: 0x%08x\n", recv_state, bis_sync_req[0]); + /* We only care about a single subgroup in this test */ + requested_bis_sync = bis_sync_req[0]; + broadcaster_broadcast_id = recv_state->broadcast_id; + if (bis_sync_req[0] != 0) { + SET_FLAG(flag_bis_sync_requested); + } else { + UNSET_FLAG(flag_bis_sync_requested); + } + + return 0; +} + +static struct bt_bap_scan_delegator_cb scan_delegator_cbs = { + .pa_sync_req = pa_sync_req_cb, + .pa_sync_term_req = pa_sync_term_req_cb, + .bis_sync_req = bis_sync_req_cb, +}; + static void started_cb(struct bt_bap_stream *stream) { printk("Stream %p started\n", stream); @@ -201,7 +262,47 @@ static void recv_cb(struct bt_bap_stream *stream, const struct bt_iso_recv_info *info, struct net_buf *buf) { - SET_FLAG(flag_received); + struct bap_test_stream *test_stream = CONTAINER_OF(stream, struct bap_test_stream, stream); + + if ((test_stream->rx_cnt % 100U) == 0U) { + printk("Incoming audio on stream %p len %u and ts %u\n", stream, buf->len, + info->ts); + } + + if (test_stream->rx_cnt > 0U && info->ts == test_stream->last_info.ts) { + FAIL("Duplicated timestamp received: %u\n", test_stream->last_info.ts); + return; + } + + if (test_stream->rx_cnt > 0U && info->seq_num == test_stream->last_info.seq_num) { + FAIL("Duplicated PSN received: %u\n", test_stream->last_info.seq_num); + return; + } + + if (info->flags & BT_ISO_FLAGS_ERROR) { + /* Fail the test if we have not received what we expected */ + if (!TEST_FLAG(flag_received)) { + FAIL("ISO receive error\n"); + } + + return; + } + + if (info->flags & BT_ISO_FLAGS_LOST) { + FAIL("ISO receive lost\n"); + return; + } + + if (memcmp(buf->data, mock_iso_data, buf->len) == 0) { + test_stream->rx_cnt++; + + if (test_stream->rx_cnt >= MIN_SEND_COUNT) { + /* We set the flag is just one stream has received the expected */ + SET_FLAG(flag_received); + } + } else { + FAIL("Unexpected data received"); + } } static struct bt_bap_stream_ops stream_ops = { @@ -241,15 +342,16 @@ static int init(void) return err; } + bt_bap_scan_delegator_register_cb(&scan_delegator_cbs); bt_le_per_adv_sync_cb_register(&bap_pa_sync_cb); bt_le_scan_cb_register(&bap_scan_cb); UNSET_FLAG(broadcaster_found); - UNSET_FLAG(base_received); + UNSET_FLAG(flag_base_received); UNSET_FLAG(pa_synced); for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { - streams[i] = &broadcast_sink_streams[i]; + streams[i] = &broadcast_sink_streams[i].stream; bt_bap_stream_cb_register(streams[i], &stream_ops); } @@ -290,6 +392,18 @@ static int pa_sync_create(void) return bt_le_per_adv_sync_create(&create_params, &pa_sync); } +static void test_pa_sync_delete(void) +{ + int err; + + err = bt_le_per_adv_sync_delete(pa_sync); + if (err != 0) { + FAIL("Unable to stop sink: %d", err); + return; + } + + pa_sync = NULL; +} static void test_scan_and_pa_sync(void) { @@ -474,6 +588,7 @@ static void test_broadcast_delete(void) } /* No "sync lost" event is generated when we initialized the disconnect */ + g_sink = NULL; } static void test_broadcast_delete_inval(void) @@ -487,6 +602,39 @@ static void test_broadcast_delete_inval(void) } } +static void test_start_adv(void) +{ + const struct bt_data ad[] = { + BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), + BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(BT_UUID_BASS_VAL), + BT_UUID_16_ENCODE(BT_UUID_PACS_VAL)), + BT_DATA_BYTES(BT_DATA_SVC_DATA16, BT_UUID_16_ENCODE(BT_UUID_BASS_VAL)), + }; + int err; + + /* Create a non-connectable non-scannable advertising set */ + err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN_NAME, NULL, &ext_adv); + if (err != 0) { + FAIL("Failed to create advertising set (err %d)\n", err); + + return; + } + + err = bt_le_ext_adv_set_data(ext_adv, ad, ARRAY_SIZE(ad), NULL, 0); + if (err != 0) { + FAIL("Failed to set advertising data (err %d)\n", err); + + return; + } + + err = bt_le_ext_adv_start(ext_adv, BT_LE_EXT_ADV_START_DEFAULT); + if (err != 0) { + FAIL("Failed to start advertising set (err %d)\n", err); + + return; + } +} + static void test_common(void) { int err; @@ -503,7 +651,7 @@ static void test_common(void) test_broadcast_sink_create(); printk("Broadcast source PA synced, waiting for BASE\n"); - WAIT_FOR_FLAG(base_received); + WAIT_FOR_FLAG(flag_base_received); printk("BASE received\n"); printk("Waiting for BIG syncable\n"); @@ -514,16 +662,20 @@ static void test_common(void) printk("Waiting for data\n"); WAIT_FOR_FLAG(flag_received); + backchannel_sync_send_all(); /* let other devices know we have received what we wanted */ /* Ensure that we also see the metadata update */ printk("Waiting for metadata update\n"); WAIT_FOR_FLAG(flag_base_metadata_updated) + backchannel_sync_send_all(); /* let other devices know we have received what we wanted */ } static void test_main(void) { test_common(); + backchannel_sync_send_all(); /* let the broadcast source know it can stop */ + /* The order of PA sync lost and BIG Sync lost is irrelevant * and depend on timeout parameters. We just wait for PA first, but * either way will work. @@ -552,25 +704,85 @@ static void test_sink_disconnect(void) test_broadcast_delete_inval(); test_broadcast_delete(); - g_sink = NULL; + + backchannel_sync_send_all(); /* let the broadcast source know it can stop */ PASS("Broadcast sink disconnect passed\n"); } +static void broadcast_sink_with_assistant(void) +{ + int err; + + err = init(); + if (err) { + FAIL("Init failed (err %d)\n", err); + return; + } + + test_start_adv(); + WAIT_FOR_FLAG(flag_connected); + + printk("Waiting for PA sync request\n"); + WAIT_FOR_FLAG(flag_pa_request); + + test_scan_and_pa_sync(); + test_broadcast_sink_create(); + + printk("Broadcast source PA synced, waiting for BASE\n"); + WAIT_FOR_FLAG(flag_base_received); + printk("BASE received\n"); + + printk("Waiting for BIG syncable\n"); + WAIT_FOR_FLAG(flag_syncable); + + printk("Waiting for BIG sync request\n"); + WAIT_FOR_FLAG(flag_bis_sync_requested); + test_broadcast_sync(); + + printk("Waiting for data\n"); + WAIT_FOR_FLAG(flag_received); + backchannel_sync_send_all(); /* let other devices know we have received what we wanted */ + + /* Ensure that we also see the metadata update */ + printk("Waiting for metadata update\n"); + WAIT_FOR_FLAG(flag_base_metadata_updated) + backchannel_sync_send_all(); /* let other devices know we have received what we wanted */ + + printk("Waiting for BIG sync terminate request\n"); + WAIT_FOR_UNSET_FLAG(flag_bis_sync_requested); + test_broadcast_stop(); + + printk("Waiting for PA sync terminate request\n"); + WAIT_FOR_UNSET_FLAG(flag_pa_request); + test_pa_sync_delete(); + test_broadcast_delete(); + + backchannel_sync_send_all(); /* let the broadcast source know it can stop */ + + PASS("Broadcast sink with assistant passed\n"); +} + static const struct bst_test_instance test_broadcast_sink[] = { { .test_id = "broadcast_sink", .test_post_init_f = test_init, .test_tick_f = test_tick, - .test_main_f = test_main + .test_main_f = test_main, }, { .test_id = "broadcast_sink_disconnect", .test_post_init_f = test_init, .test_tick_f = test_tick, - .test_main_f = test_sink_disconnect + .test_main_f = test_sink_disconnect, + }, + { + .test_id = "broadcast_sink_with_assistant", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = broadcast_sink_with_assistant, }, - BSTEST_END_MARKER + BSTEST_END_MARKER, }; struct bst_test_list *test_broadcast_sink_install(struct bst_test_list *tests) diff --git a/tests/bsim/bluetooth/audio/src/bap_broadcast_source_test.c b/tests/bsim/bluetooth/audio/src/bap_broadcast_source_test.c index 8f741279b60..2c6c5bc1828 100644 --- a/tests/bsim/bluetooth/audio/src/bap_broadcast_source_test.c +++ b/tests/bsim/bluetooth/audio/src/bap_broadcast_source_test.c @@ -28,16 +28,14 @@ NET_BUF_POOL_FIXED_DEFINE(tx_pool, CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); extern enum bst_result_t bst_result; -static struct bt_bap_stream broadcast_source_streams[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT]; -static struct bt_bap_stream *streams[ARRAY_SIZE(broadcast_source_streams)]; +static struct bap_test_stream broadcast_source_streams[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT]; static struct bt_bap_lc3_preset preset_16_2_1 = BT_BAP_LC3_BROADCAST_PRESET_16_2_1( BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); -static struct bt_bap_lc3_preset preset_16_2_2 = BT_BAP_LC3_BROADCAST_PRESET_16_2_2( +static struct bt_bap_lc3_preset preset_16_1_1 = BT_BAP_LC3_BROADCAST_PRESET_16_1_1( BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); -CREATE_FLAG(flag_stopping); -static K_SEM_DEFINE(sem_started, 0U, ARRAY_SIZE(streams)); -static K_SEM_DEFINE(sem_stopped, 0U, ARRAY_SIZE(streams)); +static K_SEM_DEFINE(sem_started, 0U, ARRAY_SIZE(broadcast_source_streams)); +static K_SEM_DEFINE(sem_stopped, 0U, ARRAY_SIZE(broadcast_source_streams)); static void started_cb(struct bt_bap_stream *stream) { @@ -51,24 +49,18 @@ static void stopped_cb(struct bt_bap_stream *stream, uint8_t reason) k_sem_give(&sem_stopped); } -static void sent_cb(struct bt_bap_stream *stream) +static void stream_sent_cb(struct bt_bap_stream *stream) { - static uint8_t mock_data[CONFIG_BT_ISO_TX_MTU]; - static bool mock_data_initialized; - static uint16_t seq_num; + struct bap_test_stream *test_stream = CONTAINER_OF(stream, struct bap_test_stream, stream); struct net_buf *buf; int ret; - if (TEST_FLAG(flag_stopping)) { + if (!test_stream->tx_active) { return; } - if (!mock_data_initialized) { - for (size_t i = 0U; i < ARRAY_SIZE(mock_data); i++) { - /* Initialize mock data */ - mock_data[i] = (uint8_t)i; - } - mock_data_initialized = true; + if ((test_stream->tx_cnt % 100U) == 0U) { + printk("Sent with seq_num %u\n", test_stream->seq_num); } buf = net_buf_alloc(&tx_pool, K_FOREVER); @@ -79,481 +71,47 @@ static void sent_cb(struct bt_bap_stream *stream) } net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); - /* Use preset_16_2_1 as that is the config we end up using */ - net_buf_add_mem(buf, mock_data, preset_16_2_1.qos.sdu); - ret = bt_bap_stream_send(stream, buf, seq_num++, - BT_ISO_TIMESTAMP_NONE); + net_buf_add_mem(buf, mock_iso_data, test_stream->tx_sdu_size); + ret = bt_bap_stream_send(stream, buf, test_stream->seq_num++, BT_ISO_TIMESTAMP_NONE); if (ret < 0) { /* This will end broadcasting on this stream. */ - printk("Unable to broadcast data on %p: %d\n", stream, ret); net_buf_unref(buf); - return; - } -} - -static struct bt_bap_stream_ops stream_ops = { - .started = started_cb, - .stopped = stopped_cb, - .sent = sent_cb -}; - -static uint8_t valid_bis_codec_data[] = {BT_AUDIO_CODEC_DATA( - BT_AUDIO_CODEC_CONFIG_LC3_FREQ, BT_BYTES_LIST_LE16(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_16KHZ))}; - -static void broadcast_source_create_inval_reset_param( - struct bt_bap_broadcast_source_create_param *param, - struct bt_bap_broadcast_source_subgroup_param *subgroup_param, - struct bt_bap_broadcast_source_stream_param *stream_param) -{ - struct bt_bap_broadcast_source_stream_param valid_stream_param; - struct bt_bap_broadcast_source_subgroup_param valid_subgroup_param; - struct bt_bap_broadcast_source_create_param create_param; - - valid_stream_param.stream = &broadcast_source_streams[0]; - valid_stream_param.data_len = ARRAY_SIZE(valid_bis_codec_data); - valid_stream_param.data = valid_bis_codec_data; - - valid_subgroup_param.params_count = 1U; - valid_subgroup_param.params = &valid_stream_param; - valid_subgroup_param.codec_cfg = &preset_16_2_1.codec_cfg; - - create_param.params_count = 1U; - create_param.params = &valid_subgroup_param; - create_param.qos = &preset_16_2_1.qos; - create_param.packing = BT_ISO_PACKING_SEQUENTIAL; - create_param.encryption = false; - - memcpy(param, &create_param, sizeof(create_param)); - memcpy(subgroup_param, &valid_subgroup_param, sizeof(valid_subgroup_param)); - memcpy(stream_param, &valid_stream_param, sizeof(valid_stream_param)); - param->params = subgroup_param; - subgroup_param->params = stream_param; -} - -static void broadcast_source_create_inval_stream_param(void) -{ - struct bt_bap_broadcast_source_subgroup_param subgroup_param; - struct bt_bap_broadcast_source_create_param create_param; - struct bt_bap_broadcast_source_stream_param stream_param; - struct bt_bap_broadcast_source *broadcast_source; - int err; - - broadcast_source_create_inval_reset_param(&create_param, &subgroup_param, &stream_param); - - /* Set data NULL while count is 1 */ - stream_param.data = NULL; - - printk("Test bt_bap_broadcast_source_create with NULL stream_param\n"); - err = bt_bap_broadcast_source_create(&create_param, &broadcast_source); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with NULL stream_param data did not " - "fail\n"); - return; - } - - broadcast_source_create_inval_reset_param(&create_param, &subgroup_param, &stream_param); - - /* Initialize codec configuration data that is too large */ - stream_param.data_len = CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE + 1; - - printk("Test bt_bap_broadcast_source_create with stream_param.data_len %zu\n", - stream_param.data_len); - err = bt_bap_broadcast_source_create(&create_param, &broadcast_source); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with stream_param data len %u " - "did not fail\n", - stream_param.data_len); - return; - } - - broadcast_source_create_inval_reset_param(&create_param, &subgroup_param, &stream_param); - - /* Set stream to NULL */ - stream_param.stream = NULL; - - printk("Test bt_bap_broadcast_source_create with NULL stream_param.stream\n"); - err = bt_bap_broadcast_source_create(&create_param, &broadcast_source); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with NULL stream_param stream " - "did not fail\n"); - return; - } - - broadcast_source_create_inval_reset_param(&create_param, &subgroup_param, &stream_param); - - if (CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE < 255) { - uint8_t bis_codec_data[CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE + 1] = {0}; - - memcpy(bis_codec_data, valid_bis_codec_data, ARRAY_SIZE(valid_bis_codec_data)); - /* Set LTV data to invalid size */ - stream_param.data_len = CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE + 1; - stream_param.data = bis_codec_data; - - printk("Test bt_bap_broadcast_source_create with CC LTV size %u\n", - stream_param.data_len); - err = bt_bap_broadcast_source_create(&create_param, &broadcast_source); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with CC LTV size %u in stream_param " - "did not fail\n", - stream_param.data_len); - return; + /* Only fail if tx is active (may fail if we are disabling the stream) */ + if (test_stream->tx_active) { + FAIL("Unable to broadcast data on %p: %d\n", stream, ret); } - } -} - -static void broadcast_source_create_inval_subgroup_codec_param(void) -{ - struct bt_bap_broadcast_source_subgroup_param subgroup_param; - struct bt_bap_broadcast_source_create_param create_param; - struct bt_bap_broadcast_source_stream_param stream_param; - struct bt_bap_broadcast_source *broadcast_source; - struct bt_audio_codec_cfg codec_cfg; - int err; - - broadcast_source_create_inval_reset_param(&create_param, &subgroup_param, &stream_param); - subgroup_param.codec_cfg = - memcpy(&codec_cfg, &preset_16_2_1.codec_cfg, sizeof(preset_16_2_1.codec_cfg)); - - codec_cfg.data_len = CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE + 1; - - printk("Test bt_bap_broadcast_source_create with codec.data_len %zu\n", codec_cfg.data_len); - err = bt_bap_broadcast_source_create(&create_param, &broadcast_source); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with codec data len %zu did not fail\n", - codec_cfg.data_len); - return; - } - - broadcast_source_create_inval_reset_param(&create_param, &subgroup_param, &stream_param); - subgroup_param.codec_cfg = - memcpy(&codec_cfg, &preset_16_2_1.codec_cfg, sizeof(preset_16_2_1.codec_cfg)); - - codec_cfg.meta_len = CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE + 1; - printk("Test bt_bap_broadcast_source_create with codec.meta_len %zu\n", codec_cfg.meta_len); - err = bt_bap_broadcast_source_create(&create_param, &broadcast_source); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with codec meta len %zu did not fail\n", - codec_cfg.meta_len); return; } - if (CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE < 255) { - broadcast_source_create_inval_reset_param(&create_param, &subgroup_param, - &stream_param); - subgroup_param.codec_cfg = memcpy(&codec_cfg, &preset_16_2_1.codec_cfg, - sizeof(preset_16_2_1.codec_cfg)); - - /* Set LTV data to invalid size */ - codec_cfg.data_len = CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE + 1; - - printk("Test bt_bap_broadcast_source_create with CC LTV size %u\n", - codec_cfg.data_len); - err = bt_bap_broadcast_source_create(&create_param, &broadcast_source); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with CC LTV size %zu in " - "subgroup_param did not fail\n", - codec_cfg.data_len); - return; - } - } - - if (CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE < 255) { - broadcast_source_create_inval_reset_param(&create_param, &subgroup_param, - &stream_param); - subgroup_param.codec_cfg = memcpy(&codec_cfg, &preset_16_2_1.codec_cfg, - sizeof(preset_16_2_1.codec_cfg)); - - /* Set LTV data to invalid size */ - codec_cfg.meta_len = CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE + 1; - - printk("Test bt_bap_broadcast_source_create with Meta LTV size %u\n", - codec_cfg.meta_len); - err = bt_bap_broadcast_source_create(&create_param, &broadcast_source); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with meta LTV size %zu in " - "subgroup_param did not fail\n", - codec_cfg.meta_len); - return; - } - } + test_stream->tx_cnt++; } -static void broadcast_source_create_inval_subgroup_param(void) -{ - struct bt_bap_broadcast_source_subgroup_param subgroup_param; - struct bt_bap_broadcast_source_create_param create_param; - struct bt_bap_broadcast_source_stream_param stream_param; - struct bt_bap_broadcast_source *broadcast_source; - int err; - - broadcast_source_create_inval_reset_param(&create_param, &subgroup_param, &stream_param); - - /* Set count to 0 */ - subgroup_param.params_count = 0; - - err = bt_bap_broadcast_source_create(&create_param, &broadcast_source); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with 0 stream_param count did not fail\n"); - return; - } - - /* Set count higher than max */ - subgroup_param.params_count = CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT + 1; - - err = bt_bap_broadcast_source_create(&create_param, &broadcast_source); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with too high stream_param count did not " - "fail\n"); - return; - } - - broadcast_source_create_inval_reset_param(&create_param, &subgroup_param, &stream_param); - - /* Set params to NULL */ - subgroup_param.params = NULL; - - err = bt_bap_broadcast_source_create(&create_param, &broadcast_source); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with NULL stream_param did not fail\n"); - return; - } - - broadcast_source_create_inval_reset_param(&create_param, &subgroup_param, &stream_param); - - /* Set codec to NULL */ - subgroup_param.codec_cfg = NULL; - - err = bt_bap_broadcast_source_create(&create_param, &broadcast_source); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with NULL codec did not fail\n"); - return; - } - - /* Invalid codec values */ - broadcast_source_create_inval_subgroup_codec_param(); -} - -static void broadcast_source_create_inval(void) -{ - struct bt_bap_broadcast_source_stream_param stream_param; - struct bt_bap_broadcast_source_subgroup_param subgroup_param; - struct bt_bap_broadcast_source_create_param create_param; - struct bt_bap_broadcast_source *broadcast_sources[CONFIG_BT_BAP_BROADCAST_SRC_COUNT + 1U]; - struct bt_audio_codec_qos qos; - int err; - - /* Test NULL parameters */ - printk("Test bt_bap_broadcast_source_create with NULL param\n"); - err = bt_bap_broadcast_source_create(NULL, &broadcast_sources[0]); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with NULL param did not fail\n"); - return; - } - - printk("Test bt_bap_broadcast_source_create with NULL broadcast source\n"); - err = bt_bap_broadcast_source_create(&create_param, NULL); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with NULL broadcast source did not " - "fail\n"); - return; - } - - /* Test stream_param values */ - broadcast_source_create_inval_stream_param(); - - /* Test invalid subgroup_param values*/ - broadcast_source_create_inval_subgroup_param(); - - /* Invalid create_param values */ - broadcast_source_create_inval_reset_param(&create_param, &subgroup_param, &stream_param); - create_param.params_count = 0; - - printk("Test bt_bap_broadcast_source_create with 0 params_count\n"); - err = bt_bap_broadcast_source_create(&create_param, &broadcast_sources[0]); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with 0 params_count did not fail\n"); - return; - } - - broadcast_source_create_inval_reset_param(&create_param, &subgroup_param, &stream_param); - create_param.params = NULL; - - printk("Test bt_bap_broadcast_source_create with NULL params\n"); - err = bt_bap_broadcast_source_create(&create_param, &broadcast_sources[0]); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with NULL params did not fail\n"); - return; - } - - broadcast_source_create_inval_reset_param(&create_param, &subgroup_param, &stream_param); - create_param.packing = 0x35; - - printk("Test bt_bap_broadcast_source_create with packing 0x%02X\n", create_param.packing); - err = bt_bap_broadcast_source_create(&create_param, &broadcast_sources[0]); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with invalid packing did not fail\n"); - return; - } - - broadcast_source_create_inval_reset_param(&create_param, &subgroup_param, &stream_param); - create_param.qos = NULL; - - printk("Test bt_bap_broadcast_source_create with NULL qos\n"); - err = bt_bap_broadcast_source_create(&create_param, &broadcast_sources[0]); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with NULL qos did not fail\n"); - return; - } - - /* Invalid QoS values */ - broadcast_source_create_inval_reset_param(&create_param, &subgroup_param, &stream_param); - create_param.qos = memcpy(&qos, &preset_16_2_1.qos, sizeof(preset_16_2_1.qos)); - qos.phy = BT_AUDIO_CODEC_QOS_CODED + 1; - - printk("Test bt_bap_broadcast_source_create with qos.phy 0x%02X\n", qos.phy); - err = bt_bap_broadcast_source_create(&create_param, &broadcast_sources[0]); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with invalid PHY did not fail\n"); - return; - } - - memcpy(&qos, &preset_16_2_1.qos, sizeof(preset_16_2_1.qos)); - - qos.framing = BT_AUDIO_CODEC_QOS_FRAMING_FRAMED + 1; - - printk("Test bt_bap_broadcast_source_create with qos.framing 0x%02X\n", qos.framing); - err = bt_bap_broadcast_source_create(&create_param, &broadcast_sources[0]); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with invalid framing did not fail\n"); - return; - } - - memcpy(&qos, &preset_16_2_1.qos, sizeof(preset_16_2_1.qos)); - - qos.rtn = BT_ISO_BROADCAST_RTN_MAX + 1; - - printk("Test bt_bap_broadcast_source_create with qos.rtn 0x%02X\n", qos.rtn); - err = bt_bap_broadcast_source_create(&create_param, &broadcast_sources[0]); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with invalid RTN did not fail\n"); - return; - } - - memcpy(&qos, &preset_16_2_1.qos, sizeof(preset_16_2_1.qos)); - - qos.sdu = BT_ISO_MAX_SDU + 1; - - printk("Test bt_bap_broadcast_source_create with qos.sdu 0x%02X\n", qos.sdu); - err = bt_bap_broadcast_source_create(&create_param, &broadcast_sources[0]); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with invalid SDU size did not fail\n"); - return; - } - - memcpy(&qos, &preset_16_2_1.qos, sizeof(preset_16_2_1.qos)); - - qos.latency = BT_ISO_LATENCY_MIN - 1; - - printk("Test bt_bap_broadcast_source_create with qos.latency 0x%02X\n", qos.latency); - err = bt_bap_broadcast_source_create(&create_param, &broadcast_sources[0]); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with too low latency did not fail\n"); - return; - } - - memcpy(&qos, &preset_16_2_1.qos, sizeof(preset_16_2_1.qos)); - - qos.latency = BT_ISO_LATENCY_MAX + 1; - - printk("Test bt_bap_broadcast_source_create with qos.latency 0x%02X\n", qos.latency); - err = bt_bap_broadcast_source_create(&create_param, &broadcast_sources[0]); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with too high latency did not fail\n"); - return; - } - - memcpy(&qos, &preset_16_2_1.qos, sizeof(preset_16_2_1.qos)); - - qos.interval = BT_ISO_SDU_INTERVAL_MIN - 1; - - printk("Test bt_bap_broadcast_source_create with qos.interval 0x%02X\n", qos.interval); - err = bt_bap_broadcast_source_create(&create_param, &broadcast_sources[0]); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with too low interval did not fail\n"); - return; - } - - memcpy(&qos, &preset_16_2_1.qos, sizeof(preset_16_2_1.qos)); - - qos.interval = BT_ISO_SDU_INTERVAL_MAX + 1; - - printk("Test bt_bap_broadcast_source_create with qos.interval 0x%02X\n", qos.interval); - err = bt_bap_broadcast_source_create(&create_param, &broadcast_sources[0]); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with too high interval did not fail\n"); - return; - } - - /* Exceeding memory limits */ - broadcast_source_create_inval_reset_param(&create_param, &subgroup_param, &stream_param); - - printk("Test bt_bap_broadcast_source_create with %zu broadcast sources\n", - ARRAY_SIZE(broadcast_sources)); - for (size_t i = 0U; i < ARRAY_SIZE(broadcast_sources); i++) { - err = bt_bap_broadcast_source_create(&create_param, &broadcast_sources[i]); - - if (i < CONFIG_BT_BAP_BROADCAST_SRC_COUNT) { - if (err != 0) { - FAIL("bt_bap_broadcast_source_create[%zu] failed: %d\n", i, err); - return; - } - } else { - if (err == 0) { - FAIL("bt_bap_broadcast_source_create[%zu] did not fail\n", i); - return; - } - } - } - - for (size_t i = 0U; i < ARRAY_SIZE(broadcast_sources) - 1; i++) { - err = bt_bap_broadcast_source_delete(broadcast_sources[i]); - if (err != 0) { - FAIL("bt_bap_broadcast_source_delete[%zu] failed: %d\n", i, err); - return; - } - broadcast_sources[i] = NULL; - } - - create_param.params_count = CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT + 1; - - printk("Test bt_bap_broadcast_source_create with %zu subgroups\n", - create_param.params_count); - err = bt_bap_broadcast_source_create(&create_param, &broadcast_sources[0]); - if (err == 0) { - FAIL("bt_bap_broadcast_source_create with %zu subgroups did not fail\n", - create_param.params_count); - return; - } -} +static struct bt_bap_stream_ops stream_ops = { + .started = started_cb, + .stopped = stopped_cb, + .sent = stream_sent_cb, +}; static int setup_broadcast_source(struct bt_bap_broadcast_source **source) { - uint8_t bis_codec_data[] = {3, BT_AUDIO_CODEC_CONFIG_LC3_FREQ, - BT_BYTES_LIST_LE16(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_16KHZ)}; + uint8_t bis_codec_data[] = { + BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CONFIG_LC3_FREQ, + BT_BYTES_LIST_LE16(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_16KHZ)), + }; struct bt_bap_broadcast_source_stream_param stream_params[ARRAY_SIZE(broadcast_source_streams)]; struct bt_bap_broadcast_source_subgroup_param subgroup_params[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT]; - struct bt_bap_broadcast_source_create_param create_param; + struct bt_bap_broadcast_source_param create_param; int err; (void)memset(broadcast_source_streams, 0, sizeof(broadcast_source_streams)); for (size_t i = 0; i < ARRAY_SIZE(stream_params); i++) { - stream_params[i].stream = &broadcast_source_streams[i]; + stream_params[i].stream = &broadcast_source_streams[i].stream; bt_bap_stream_cb_register(stream_params[i].stream, &stream_ops); #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 @@ -565,12 +123,12 @@ static int setup_broadcast_source(struct bt_bap_broadcast_source **source) for (size_t i = 0U; i < ARRAY_SIZE(subgroup_params); i++) { subgroup_params[i].params_count = 1U; subgroup_params[i].params = &stream_params[i]; - subgroup_params[i].codec_cfg = &preset_16_2_1.codec_cfg; + subgroup_params[i].codec_cfg = &preset_16_1_1.codec_cfg; } create_param.params_count = ARRAY_SIZE(subgroup_params); create_param.params = subgroup_params; - create_param.qos = &preset_16_2_2.qos; + create_param.qos = &preset_16_2_1.qos; create_param.packing = BT_ISO_PACKING_SEQUENTIAL; create_param.encryption = false; @@ -582,27 +140,13 @@ static int setup_broadcast_source(struct bt_bap_broadcast_source **source) return err; } - return 0; -} + for (size_t i = 0U; i < ARRAY_SIZE(broadcast_source_streams); i++) { + struct bap_test_stream *test_stream = &broadcast_source_streams[i]; -static void test_broadcast_source_get_id_inval(struct bt_bap_broadcast_source *source, - uint32_t *broadcast_id_out) -{ - int err; - - printk("Test bt_bap_broadcast_source_get_id with NULL source\n"); - err = bt_bap_broadcast_source_get_id(NULL, broadcast_id_out); - if (err == 0) { - FAIL("bt_bap_broadcast_source_get_id with NULL source did not fail\n"); - return; + test_stream->tx_sdu_size = preset_16_1_1.qos.sdu; } - printk("Test bt_bap_broadcast_source_get_id with NULL broadcast_id\n"); - err = bt_bap_broadcast_source_get_id(source, NULL); - if (err == 0) { - FAIL("bt_bap_broadcast_source_get_id with NULL ID did not fail\n"); - return; - } + return 0; } static void test_broadcast_source_get_id(struct bt_bap_broadcast_source *source, @@ -617,43 +161,6 @@ static void test_broadcast_source_get_id(struct bt_bap_broadcast_source *source, } } -static void test_broadcast_source_get_base_inval(struct bt_bap_broadcast_source *source, - struct net_buf_simple *base_buf) -{ - /* Large enough for minimum, but not large enough for any CC or Meta data */ - NET_BUF_SIMPLE_DEFINE(small_base_buf, BT_BAP_BASE_MIN_SIZE + 2); - NET_BUF_SIMPLE_DEFINE(very_small_base_buf, 4); - int err; - - printk("Test bt_bap_broadcast_source_get_base with NULL source\n"); - err = bt_bap_broadcast_source_get_base(NULL, base_buf); - if (err == 0) { - FAIL("bt_bap_broadcast_source_get_base with NULL source did not fail\n"); - return; - } - - printk("Test bt_bap_broadcast_source_get_base with NULL buf\n"); - err = bt_bap_broadcast_source_get_base(source, NULL); - if (err == 0) { - FAIL("bt_bap_broadcast_source_get_base with NULL buf did not fail\n"); - return; - } - - printk("Test bt_bap_broadcast_source_get_base with very small buf\n"); - err = bt_bap_broadcast_source_get_base(source, &very_small_base_buf); - if (err == 0) { - FAIL("bt_bap_broadcast_source_get_base with very small buf did not fail\n"); - return; - } - - printk("Test bt_bap_broadcast_source_get_base with small buf\n"); - err = bt_bap_broadcast_source_get_base(source, &small_base_buf); - if (err == 0) { - FAIL("bt_bap_broadcast_source_get_base with small buf did not fail\n"); - return; - } -} - static void test_broadcast_source_get_base(struct bt_bap_broadcast_source *source, struct net_buf_simple *base_buf) { @@ -692,7 +199,6 @@ static int setup_extended_adv(struct bt_bap_broadcast_source *source, struct bt_ return err; } - test_broadcast_source_get_id_inval(source, &broadcast_id); test_broadcast_source_get_id(source, &broadcast_id); /* Setup extended advertising data */ @@ -708,7 +214,6 @@ static int setup_extended_adv(struct bt_bap_broadcast_source *source, struct bt_ } /* Setup periodic advertising data */ - test_broadcast_source_get_base_inval(source, &base_buf); test_broadcast_source_get_base(source, &base_buf); per_ad.type = BT_DATA_SVC_DATA16; @@ -737,239 +242,48 @@ static int setup_extended_adv(struct bt_bap_broadcast_source *source, struct bt_ return 0; } -static void test_broadcast_source_reconfig_inval_state(struct bt_bap_broadcast_source *source) -{ - int err; - - printk("Test bt_bap_broadcast_source_reconfig in stopped state\n"); - err = bt_bap_broadcast_source_reconfig(source, &preset_16_2_1.codec_cfg, - &preset_16_2_1.qos); - if (err == 0) { - FAIL("bt_bap_broadcast_source_reconfig in stopped state did not fail\n"); - return; - } -} - -static void test_broadcast_source_reconfig_inval(struct bt_bap_broadcast_source *source) +static void test_broadcast_source_reconfig(struct bt_bap_broadcast_source *source) { - struct bt_audio_codec_qos qos; - struct bt_audio_codec_cfg codec_cfg; + uint8_t bis_codec_data[] = { + BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CONFIG_LC3_FREQ, + BT_BYTES_LIST_LE16(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_16KHZ)), + }; + struct bt_bap_broadcast_source_stream_param + stream_params[ARRAY_SIZE(broadcast_source_streams)]; + struct bt_bap_broadcast_source_subgroup_param + subgroup_params[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT]; + struct bt_bap_broadcast_source_param reconfig_param; int err; - /* Test NULL values */ - printk("Test bt_bap_broadcast_source_reconfig with NULL source\n"); - err = bt_bap_broadcast_source_reconfig(NULL, &preset_16_2_1.codec_cfg, &preset_16_2_1.qos); - if (err == 0) { - FAIL("bt_bap_broadcast_source_reconfig with NULL broadcast source did not fail\n"); - return; - } - - printk("Test bt_bap_broadcast_source_reconfig with NULL codec\n"); - err = bt_bap_broadcast_source_reconfig(source, NULL, &preset_16_2_1.qos); - if (err == 0) { - FAIL("bt_bap_broadcast_source_reconfig with NULL codec did not fail\n"); - return; - } - - printk("Test bt_bap_broadcast_source_reconfig with NULL QoS\n"); - err = bt_bap_broadcast_source_reconfig(source, &preset_16_2_1.codec_cfg, NULL); - if (err == 0) { - FAIL("bt_bap_broadcast_source_reconfig with NULL QoS did not fail\n"); - return; - } - - /* Test invalid codec values */ - memcpy(&codec_cfg, &preset_16_2_1.codec_cfg, sizeof(preset_16_2_1.codec_cfg)); - - codec_cfg.data_len = CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE + 1; - - printk("Test bt_bap_broadcast_source_reconfig with codec.data_len %zu\n", - codec_cfg.data_len); - err = bt_bap_broadcast_source_reconfig(source, &codec_cfg, &preset_16_2_1.qos); - if (err == 0) { - FAIL("bt_bap_broadcast_source_reconfig with too high codec data len did not " - "fail\n"); - return; - } - - memcpy(&codec_cfg, &preset_16_2_1.codec_cfg, sizeof(preset_16_2_1.codec_cfg)); - - codec_cfg.meta_len = CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE + 1; - - printk("Test bt_bap_broadcast_source_reconfig with codec.meta_len %zu\n", - codec_cfg.meta_len); - err = bt_bap_broadcast_source_reconfig(source, &codec_cfg, &preset_16_2_1.qos); - if (err == 0) { - FAIL("bt_bap_broadcast_source_reconfig with too high codec meta len did not " - "fail\n"); - return; - } - - memcpy(&codec_cfg, &preset_16_2_1.codec_cfg, sizeof(preset_16_2_1.codec_cfg)); - - if (CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE < 255) { - /* Set LTV data to invalid size */ - codec_cfg.data_len = CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE + 1; - - printk("Test bt_bap_broadcast_source_reconfig with CC LTV size %u\n", - codec_cfg.data_len); - err = bt_bap_broadcast_source_reconfig(source, &codec_cfg, &preset_16_2_1.qos); - if (err == 0) { - FAIL("bt_bap_broadcast_source_reconfig with too large CC LTV did not " - "fail\n"); - return; - } - - memcpy(&codec_cfg, &preset_16_2_1.codec_cfg, sizeof(preset_16_2_1.codec_cfg)); - } - - if (CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE < 255) { - /* Set LTV data to invalid size */ - codec_cfg.meta_len = CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE + 1; - - printk("Test bt_bap_broadcast_source_reconfig with meta LTV size %u\n", - codec_cfg.meta_len); - err = bt_bap_broadcast_source_reconfig(source, &codec_cfg, &preset_16_2_1.qos); - if (err == 0) { - FAIL("bt_bap_broadcast_source_reconfig with too large meta LTV did not " - "fail\n"); - return; - } - - memcpy(&codec_cfg, &preset_16_2_1.codec_cfg, sizeof(preset_16_2_1.codec_cfg)); - } - - memcpy(&qos, &preset_16_2_1.qos, sizeof(preset_16_2_1.qos)); - qos.phy = BT_AUDIO_CODEC_QOS_CODED + 1; - - printk("Test bt_bap_broadcast_source_reconfig with qos.phy %u\n", qos.phy); - err = bt_bap_broadcast_source_reconfig(source, &preset_16_2_1.codec_cfg, &qos); - if (err == 0) { - FAIL("bt_bap_broadcast_source_reconfig with invalid PHY did not fail\n"); - return; - } - - memcpy(&qos, &preset_16_2_1.qos, sizeof(preset_16_2_1.qos)); - - qos.framing = BT_AUDIO_CODEC_QOS_FRAMING_FRAMED + 1; - - printk("Test bt_bap_broadcast_source_reconfig with qos.framing %u\n", qos.framing); - err = bt_bap_broadcast_source_reconfig(source, &preset_16_2_1.codec_cfg, &qos); - if (err == 0) { - FAIL("bt_bap_broadcast_source_reconfig with invalid framing did not fail\n"); - return; - } - - memcpy(&qos, &preset_16_2_1.qos, sizeof(preset_16_2_1.qos)); - - qos.rtn = BT_ISO_BROADCAST_RTN_MAX + 1; - - printk("Test bt_bap_broadcast_source_reconfig with qos.rtn %u\n", qos.rtn); - err = bt_bap_broadcast_source_reconfig(source, &preset_16_2_1.codec_cfg, &qos); - if (err == 0) { - FAIL("bt_bap_broadcast_source_reconfig with invalid RTN did not fail\n"); - return; - } - - memcpy(&qos, &preset_16_2_1.qos, sizeof(preset_16_2_1.qos)); - - qos.sdu = BT_ISO_MAX_SDU + 1; - - printk("Test bt_bap_broadcast_source_reconfig with qos.sdu %u\n", qos.sdu); - err = bt_bap_broadcast_source_reconfig(source, &preset_16_2_1.codec_cfg, &qos); - if (err == 0) { - FAIL("bt_bap_broadcast_source_reconfig with invalid SDU size did not fail\n"); - return; - } - - memcpy(&qos, &preset_16_2_1.qos, sizeof(preset_16_2_1.qos)); - - qos.latency = BT_ISO_LATENCY_MIN - 1; - - printk("Test bt_bap_broadcast_source_reconfig with qos.latency %u\n", qos.latency); - err = bt_bap_broadcast_source_reconfig(source, &preset_16_2_1.codec_cfg, &qos); - if (err == 0) { - FAIL("bt_bap_broadcast_source_reconfig with too low latency did not fail\n"); - return; - } - - memcpy(&qos, &preset_16_2_1.qos, sizeof(preset_16_2_1.qos)); - - qos.latency = BT_ISO_LATENCY_MAX + 1; - - printk("Test bt_bap_broadcast_source_reconfig with qos.latency %u\n", qos.latency); - err = bt_bap_broadcast_source_reconfig(source, &preset_16_2_1.codec_cfg, &qos); - if (err == 0) { - FAIL("bt_bap_broadcast_source_reconfig with too high latency did not fail\n"); - return; - } - - memcpy(&qos, &preset_16_2_1.qos, sizeof(preset_16_2_1.qos)); - - qos.interval = BT_ISO_SDU_INTERVAL_MIN - 1; - - printk("Test bt_bap_broadcast_source_reconfig with qos.interval %u\n", qos.interval); - err = bt_bap_broadcast_source_reconfig(source, &preset_16_2_1.codec_cfg, &qos); - if (err == 0) { - FAIL("bt_bap_broadcast_source_reconfig with too low interval did not fail\n"); - return; + for (size_t i = 0; i < ARRAY_SIZE(stream_params); i++) { + stream_params[i].stream = &broadcast_source_streams[i].stream; + stream_params[i].data_len = ARRAY_SIZE(bis_codec_data); + stream_params[i].data = bis_codec_data; } - memcpy(&qos, &preset_16_2_1.qos, sizeof(preset_16_2_1.qos)); - - qos.interval = BT_ISO_SDU_INTERVAL_MAX + 1; - - printk("Test bt_bap_broadcast_source_reconfig with qos.interval %u\n", qos.interval); - err = bt_bap_broadcast_source_reconfig(source, &preset_16_2_1.codec_cfg, &qos); - if (err == 0) { - FAIL("bt_bap_broadcast_source_reconfig with too high interval did not fail\n"); - return; + for (size_t i = 0U; i < ARRAY_SIZE(subgroup_params); i++) { + subgroup_params[i].params_count = 1U; + subgroup_params[i].params = &stream_params[i]; + subgroup_params[i].codec_cfg = &preset_16_1_1.codec_cfg; } -} -static void test_broadcast_source_reconfig(struct bt_bap_broadcast_source *source) -{ - int err; + reconfig_param.params_count = ARRAY_SIZE(subgroup_params); + reconfig_param.params = subgroup_params; + reconfig_param.qos = &preset_16_1_1.qos; + reconfig_param.packing = BT_ISO_PACKING_SEQUENTIAL; + reconfig_param.encryption = false; printk("Reconfiguring broadcast source\n"); - err = bt_bap_broadcast_source_reconfig(source, &preset_16_2_1.codec_cfg, - &preset_16_2_1.qos); + err = bt_bap_broadcast_source_reconfig(source, &reconfig_param); if (err != 0) { FAIL("Unable to reconfigure broadcast source: %d\n", err); return; } -} - -static void test_broadcast_source_start_inval_state(struct bt_bap_broadcast_source *source, - struct bt_le_ext_adv *adv) -{ - int err; - - printk("Test bt_bap_broadcast_source_start in streaming state\n"); - err = bt_bap_broadcast_source_start(source, adv); - if (err == 0) { - FAIL("bt_bap_broadcast_source_start in streaming state did not fail\n"); - return; - } -} - -static void test_broadcast_source_start_inval(struct bt_bap_broadcast_source *source, - struct bt_le_ext_adv *adv) -{ - int err; - printk("Test bt_bap_broadcast_source_start with NULL source\n"); - err = bt_bap_broadcast_source_start(NULL, adv); - if (err == 0) { - FAIL("bt_bap_broadcast_source_start with NULL source did not fail\n"); - return; - } + for (size_t i = 0U; i < ARRAY_SIZE(broadcast_source_streams); i++) { + struct bap_test_stream *test_stream = &broadcast_source_streams[i]; - printk("Test bt_bap_broadcast_source_start with NULL adv\n"); - err = bt_bap_broadcast_source_start(source, NULL); - if (err == 0) { - FAIL("bt_bap_broadcast_source_start with NULL adv did not fail\n"); - return; + test_stream->tx_sdu_size = preset_16_1_1.qos.sdu; } } @@ -987,42 +301,21 @@ static void test_broadcast_source_start(struct bt_bap_broadcast_source *source, /* Wait for all to be started */ printk("Waiting for streams to be started\n"); - for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { + for (size_t i = 0U; i < ARRAY_SIZE(broadcast_source_streams); i++) { k_sem_take(&sem_started, K_FOREVER); } } -static void test_broadcast_source_stop_inval_state(struct bt_bap_broadcast_source *source) -{ - int err; - - printk("Test bt_bap_broadcast_source_stop in stopped state\n"); - err = bt_bap_broadcast_source_stop(source); - if (err == 0) { - FAIL("bt_bap_broadcast_source_stop in stopped state did not fail\n"); - return; - } -} - -static void test_broadcast_source_stop_inval(void) -{ - int err; - - printk("Test bt_bap_broadcast_source_stop with NULL source\n"); - err = bt_bap_broadcast_source_stop(NULL); - if (err == 0) { - FAIL("bt_bap_broadcast_source_stop with NULL source did not fail\n"); - return; - } -} - static void test_broadcast_source_stop(struct bt_bap_broadcast_source *source) { int err; - SET_FLAG(flag_stopping); printk("Stopping broadcast source\n"); + for (size_t i = 0U; i < ARRAY_SIZE(broadcast_source_streams); i++) { + broadcast_source_streams[i].tx_active = false; + } + err = bt_bap_broadcast_source_stop(source); if (err != 0) { FAIL("Unable to stop broadcast source: %d\n", err); @@ -1031,40 +324,15 @@ static void test_broadcast_source_stop(struct bt_bap_broadcast_source *source) /* Wait for all to be stopped */ printk("Waiting for streams to be stopped\n"); - for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { + for (size_t i = 0U; i < ARRAY_SIZE(broadcast_source_streams); i++) { k_sem_take(&sem_stopped, K_FOREVER); } } -static void test_broadcast_source_delete_inval_state(struct bt_bap_broadcast_source *source) -{ - int err; - - printk("Test bt_bap_broadcast_source_delete in streaming state\n"); - err = bt_bap_broadcast_source_delete(NULL); - if (err == 0) { - FAIL("bt_bap_broadcast_source_delete in streaming state not fail\n"); - return; - } -} - -static void test_broadcast_source_delete_inval(void) -{ - int err; - - printk("Test bt_bap_broadcast_source_delete with NULL source\n"); - err = bt_bap_broadcast_source_delete(NULL); - if (err == 0) { - FAIL("bt_bap_broadcast_source_delete with NULL source did not fail\n"); - return; - } -} - static void test_broadcast_source_delete(struct bt_bap_broadcast_source *source) { int err; - SET_FLAG(flag_stopping); printk("Deleting broadcast source\n"); err = bt_bap_broadcast_source_delete(source); @@ -1114,7 +382,6 @@ static void test_main(void) printk("Bluetooth initialized\n"); - broadcast_source_create_inval(); err = setup_broadcast_source(&source); if (err != 0) { FAIL("Unable to setup broadcast source: %d\n", err); @@ -1127,43 +394,43 @@ static void test_main(void) return; } - test_broadcast_source_reconfig_inval(source); test_broadcast_source_reconfig(source); - test_broadcast_source_start_inval(source, adv); test_broadcast_source_start(source, adv); - test_broadcast_source_reconfig_inval_state(source); - test_broadcast_source_start_inval_state(source, adv); /* Initialize sending */ - for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { + printk("Sending data\n"); + for (size_t i = 0U; i < ARRAY_SIZE(broadcast_source_streams); i++) { for (unsigned int j = 0U; j < BROADCAST_ENQUEUE_COUNT; j++) { - sent_cb(streams[i]); + struct bap_test_stream *test_stream = + CONTAINER_OF(&broadcast_source_streams[i].stream, + struct bap_test_stream, stream); + + test_stream->tx_active = true; + stream_sent_cb(&broadcast_source_streams[i].stream); } } - /* Keeping running for a little while */ - k_sleep(K_SECONDS(15)); + /* Wait for other devices to have received what they wanted */ + backchannel_sync_wait_any(); /* Update metadata while streaming */ printk("Updating metadata\n"); err = bt_bap_broadcast_source_update_metadata(source, new_metadata, ARRAY_SIZE(new_metadata)); if (err != 0) { - FAIL("Failed to update metadata broadcast source: %d", err); + FAIL("Failed to update metadata broadcast source: %d\n", err); return; } - /* Keeping running for a little while */ - k_sleep(K_SECONDS(5)); + /* Wait for other devices to have received what they wanted */ + backchannel_sync_wait_any(); - test_broadcast_source_delete_inval_state(source); + /* Wait for other devices to let us know when we can stop the source */ + backchannel_sync_wait_any(); - test_broadcast_source_stop_inval(); test_broadcast_source_stop(source); - test_broadcast_source_stop_inval_state(source); - test_broadcast_source_delete_inval(); test_broadcast_source_delete(source); source = NULL; diff --git a/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c b/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c index 3fbd70458b9..96265267e80 100644 --- a/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c +++ b/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c @@ -16,9 +16,15 @@ #define BAP_STREAM_RETRY_WAIT K_MSEC(100) +#define ENQUEUE_COUNT 2U +#define TOTAL_BUF_NEEDED (ENQUEUE_COUNT * CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT) +NET_BUF_POOL_FIXED_DEFINE(tx_pool, TOTAL_BUF_NEEDED, BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), + CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); + extern enum bst_result_t bst_result; -static struct bt_bap_stream g_streams[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT]; +static volatile size_t sent_count; +static struct bap_test_stream g_streams[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT]; static struct bt_bap_ep *g_sinks[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT]; static struct bt_bap_ep *g_sources[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT]; @@ -39,6 +45,7 @@ static atomic_t flag_stream_qos_configured; CREATE_FLAG(flag_stream_enabled); CREATE_FLAG(flag_stream_metadata); CREATE_FLAG(flag_stream_started); +CREATE_FLAG(flag_stream_disabled); CREATE_FLAG(flag_stream_released); CREATE_FLAG(flag_operation_success); @@ -56,8 +63,12 @@ static void stream_configured(struct bt_bap_stream *stream, static void stream_qos_set(struct bt_bap_stream *stream) { + struct bap_test_stream *test_stream = CONTAINER_OF(stream, struct bap_test_stream, stream); + printk("QoS set stream %p\n", stream); + test_stream->tx_sdu_size = stream->qos->sdu; + atomic_inc(&flag_stream_qos_configured); } @@ -84,7 +95,13 @@ static void stream_metadata_updated(struct bt_bap_stream *stream) static void stream_disabled(struct bt_bap_stream *stream) { + struct bap_test_stream *test_stream = CONTAINER_OF(stream, struct bap_test_stream, stream); + + test_stream->tx_active = false; + printk("Disabled stream %p\n", stream); + + SET_FLAG(flag_stream_disabled); } static void stream_stopped(struct bt_bap_stream *stream, uint8_t reason) @@ -99,6 +116,74 @@ static void stream_released(struct bt_bap_stream *stream) SET_FLAG(flag_stream_released); } +static void stream_recv_cb(struct bt_bap_stream *stream, const struct bt_iso_recv_info *info, + struct net_buf *buf) +{ + struct bap_test_stream *test_stream = CONTAINER_OF(stream, struct bap_test_stream, stream); + + printk("Incoming audio on stream %p len %u and ts %u\n", stream, buf->len, info->ts); + + if (test_stream->rx_cnt > 0U && info->ts == test_stream->last_info.ts) { + FAIL("Duplicated timestamp received: %u\n", test_stream->last_info.ts); + return; + } + + if (test_stream->rx_cnt > 0U && info->seq_num == test_stream->last_info.seq_num) { + FAIL("Duplicated PSN received: %u\n", test_stream->last_info.seq_num); + return; + } + + if (info->flags & BT_ISO_FLAGS_ERROR) { + FAIL("ISO receive error\n"); + return; + } + + if (info->flags & BT_ISO_FLAGS_LOST) { + FAIL("ISO receive lost\n"); + return; + } + + if (memcmp(buf->data, mock_iso_data, buf->len) == 0) { + test_stream->rx_cnt++; + } else { + FAIL("Unexpected data received"); + } +} + +static void stream_sent_cb(struct bt_bap_stream *stream) +{ + struct bap_test_stream *test_stream = CONTAINER_OF(stream, struct bap_test_stream, stream); + struct net_buf *buf; + int ret; + + if (!test_stream->tx_active) { + return; + } + + buf = net_buf_alloc(&tx_pool, K_FOREVER); + if (buf == NULL) { + printk("Could not allocate buffer when sending on %p\n", stream); + return; + } + + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); + net_buf_add_mem(buf, mock_iso_data, test_stream->tx_sdu_size); + ret = bt_bap_stream_send(stream, buf, test_stream->seq_num++, BT_ISO_TIMESTAMP_NONE); + if (ret < 0) { + /* This will end broadcasting on this stream. */ + net_buf_unref(buf); + + /* Only fail if tx is active (may fail if we are disabling the stream) */ + if (test_stream->tx_active) { + FAIL("Unable to send data on %p: %d\n", stream, ret); + } + + return; + } + + test_stream->tx_cnt++; +} + static struct bt_bap_stream_ops stream_ops = { .configured = stream_configured, .qos_set = stream_qos_set, @@ -108,6 +193,8 @@ static struct bt_bap_stream_ops stream_ops = { .disabled = stream_disabled, .stopped = stream_stopped, .released = stream_released, + .recv = stream_recv_cb, + .sent = stream_sent_cb, }; static void unicast_client_location_cb(struct bt_conn *conn, @@ -403,7 +490,7 @@ static void init(void) } for (size_t i = 0; i < ARRAY_SIZE(g_streams); i++) { - g_streams[i].ops = &stream_ops; + g_streams[i].stream.ops = &stream_ops; } bt_le_scan_cb_register(&bap_scan_cb); @@ -587,7 +674,7 @@ static int enable_stream(struct bt_bap_stream *stream) static void enable_streams(size_t stream_cnt) { for (size_t i = 0U; i < stream_cnt; i++) { - struct bt_bap_stream *stream = &g_streams[i]; + struct bt_bap_stream *stream = &g_streams[i].stream; int err; err = enable_stream(stream); @@ -626,7 +713,7 @@ static int metadata_update_stream(struct bt_bap_stream *stream) static void metadata_update_streams(size_t stream_cnt) { for (size_t i = 0U; i < stream_cnt; i++) { - struct bt_bap_stream *stream = &g_streams[i]; + struct bt_bap_stream *stream = &g_streams[i].stream; int err; err = metadata_update_stream(stream); @@ -692,7 +779,64 @@ static void start_streams(void) } } -static size_t release_streams(size_t stream_cnt) +static void transceive_streams(void) +{ + struct bt_bap_stream *source_stream; + struct bt_bap_stream *sink_stream; + + source_stream = pair_params[0].rx_param == NULL ? NULL : pair_params[0].rx_param->stream; + sink_stream = pair_params[0].tx_param == NULL ? NULL : pair_params[0].tx_param->stream; + + if (sink_stream != NULL) { + struct bap_test_stream *test_stream = + CONTAINER_OF(sink_stream, struct bap_test_stream, stream); + + test_stream->tx_active = true; + for (unsigned int i = 0U; i < ENQUEUE_COUNT; i++) { + stream_sent_cb(sink_stream); + } + + /* Keep sending until we reach the minimum expected */ + while (test_stream->tx_cnt < MIN_SEND_COUNT) { + k_sleep(K_MSEC(100)); + } + } + + if (source_stream != NULL) { + const struct bap_test_stream *test_stream = + CONTAINER_OF(source_stream, struct bap_test_stream, stream); + + /* Keep receiving until we reach the minimum expected */ + while (test_stream->rx_cnt < MIN_SEND_COUNT) { + k_sleep(K_MSEC(100)); + } + } +} + +static void disable_streams(size_t stream_cnt) +{ + for (size_t i = 0; i < stream_cnt; i++) { + int err; + + UNSET_FLAG(flag_operation_success); + UNSET_FLAG(flag_stream_disabled); + + do { + err = bt_bap_stream_disable(&g_streams[i].stream); + if (err == -EBUSY) { + k_sleep(BAP_STREAM_RETRY_WAIT); + } else if (err != 0) { + FAIL("Could not disable stream: %d\n", err); + return; + } + } while (err == -EBUSY); + + WAIT_FOR_FLAG(flag_operation_success); + WAIT_FOR_FLAG(flag_stream_disabled); + } +} + +static void release_streams(size_t stream_cnt) { for (size_t i = 0; i < stream_cnt; i++) { int err; @@ -701,20 +845,18 @@ static size_t release_streams(size_t stream_cnt) UNSET_FLAG(flag_stream_released); do { - err = bt_bap_stream_release(&g_streams[i]); + err = bt_bap_stream_release(&g_streams[i].stream); if (err == -EBUSY) { k_sleep(BAP_STREAM_RETRY_WAIT); } else if (err != 0) { FAIL("Could not release stream: %d\n", err); - return err; + return; } } while (err == -EBUSY); WAIT_FOR_FLAG(flag_operation_success); WAIT_FOR_FLAG(flag_stream_released); } - - return stream_cnt; } static size_t create_unicast_group(struct bt_bap_unicast_group **unicast_group) @@ -732,7 +874,7 @@ static size_t create_unicast_group(struct bt_bap_unicast_group **unicast_group) break; } - stream_params[stream_cnt].stream = &g_streams[stream_cnt]; + stream_params[stream_cnt].stream = &g_streams[stream_cnt].stream; stream_params[stream_cnt].qos = &preset_16_2_1.qos; pair_params[i].tx_param = &stream_params[stream_cnt]; @@ -746,7 +888,7 @@ static size_t create_unicast_group(struct bt_bap_unicast_group **unicast_group) break; } - stream_params[stream_cnt].stream = &g_streams[stream_cnt]; + stream_params[stream_cnt].stream = &g_streams[stream_cnt].stream; stream_params[stream_cnt].qos = &preset_16_2_1.qos; pair_params[i].rx_param = &stream_params[stream_cnt]; @@ -839,6 +981,12 @@ static void test_main(void) printk("Starting streams\n"); start_streams(); + printk("Starting transceiving\n"); + transceive_streams(); + + printk("Stopping streams\n"); + disable_streams(stream_cnt); + printk("Releasing streams\n"); release_streams(stream_cnt); @@ -860,6 +1008,8 @@ static void test_main_acl_disconnect(void) init(); + stream_ops.recv = NULL; /* We do not care about data in this test */ + scan_and_connect(); exchange_mtu(); @@ -868,10 +1018,6 @@ static void test_main_acl_disconnect(void) discover_sources(); - /* Run the stream setup multiple time to ensure states are properly - * set and reset - */ - printk("Creating unicast group\n"); stream_cnt = create_unicast_group(&unicast_group); diff --git a/tests/bsim/bluetooth/audio/src/bap_unicast_common.c b/tests/bsim/bluetooth/audio/src/bap_unicast_common.c index 36023339bbf..4a828e2d6a2 100644 --- a/tests/bsim/bluetooth/audio/src/bap_unicast_common.c +++ b/tests/bsim/bluetooth/audio/src/bap_unicast_common.c @@ -48,7 +48,7 @@ void print_codec_cap(const struct bt_audio_codec_cap *codec_cap) printk("codec_cap ID 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cap->id, codec_cap->cid, codec_cap->vid, codec_cap->data_len); - if (codec_cap->id == BT_AUDIO_CODEC_LC3_ID) { + if (codec_cap->id == BT_HCI_CODING_FORMAT_LC3) { print_ltv_array("data", codec_cap->data, codec_cap->data_len); } else { /* If not LC3, we cannot assume it's LTV */ printk("data: "); @@ -64,7 +64,7 @@ void print_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg) printk("codec_cfg ID 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cfg->id, codec_cfg->cid, codec_cfg->vid, codec_cfg->data_len); - if (codec_cfg->id == BT_AUDIO_CODEC_LC3_ID) { + if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) { print_ltv_array("data", codec_cfg->data, codec_cfg->data_len); } else { /* If not LC3, we cannot assume it's LTV */ printk("data: "); diff --git a/tests/bsim/bluetooth/audio/src/bap_unicast_server_test.c b/tests/bsim/bluetooth/audio/src/bap_unicast_server_test.c index 58acdc1726c..e9e43a8a14a 100644 --- a/tests/bsim/bluetooth/audio/src/bap_unicast_server_test.c +++ b/tests/bsim/bluetooth/audio/src/bap_unicast_server_test.c @@ -19,9 +19,14 @@ extern enum bst_result_t bst_result; #define PREF_CONTEXT (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA) +#define ENQUEUE_COUNT 2U +#define TOTAL_BUF_NEEDED (ENQUEUE_COUNT * CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT) +NET_BUF_POOL_FIXED_DEFINE(tx_pool, TOTAL_BUF_NEEDED, BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), + CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); + static const struct bt_audio_codec_cap lc3_codec_cap = { .path_id = BT_ISO_DATA_PATH_HCI, - .id = BT_AUDIO_CODEC_LC3_ID, + .id = BT_HCI_CODING_FORMAT_LC3, .cid = 0x0000U, .vid = 0x0000U, .data_len = (3 + 1) + (2 + 1) + (2 + 1) + (5 + 1) + (2 + 1), @@ -43,7 +48,7 @@ static const struct bt_audio_codec_cap lc3_codec_cap = { }, }; -static struct bt_bap_stream streams[CONFIG_BT_ASCS_ASE_SNK_COUNT + CONFIG_BT_ASCS_ASE_SRC_COUNT]; +static struct bap_test_stream streams[CONFIG_BT_ASCS_ASE_SNK_COUNT + CONFIG_BT_ASCS_ASE_SRC_COUNT]; static const struct bt_audio_codec_qos_pref qos_pref = BT_AUDIO_CODEC_QOS_PREF(true, BT_GAP_LE_PHY_2M, 0x02, 10, 40000, 40000, 40000, 40000); @@ -64,7 +69,7 @@ static const struct bt_data unicast_server_ad[] = { static struct bt_le_ext_adv *ext_adv; CREATE_FLAG(flag_stream_configured); - +CREATE_FLAG(flag_stream_started); static void print_ase_info(struct bt_bap_ep *ep, void *user_data) { struct bt_bap_ep_info info; @@ -76,7 +81,7 @@ static void print_ase_info(struct bt_bap_ep *ep, void *user_data) static struct bt_bap_stream *stream_alloc(void) { for (size_t i = 0; i < ARRAY_SIZE(streams); i++) { - struct bt_bap_stream *stream = &streams[i]; + struct bt_bap_stream *stream = &streams[i].stream; if (!stream->conn) { return stream; @@ -128,10 +133,14 @@ static int lc3_reconfig(struct bt_bap_stream *stream, enum bt_audio_dir dir, static int lc3_qos(struct bt_bap_stream *stream, const struct bt_audio_codec_qos *qos, struct bt_bap_ascs_rsp *rsp) { + struct bap_test_stream *test_stream = CONTAINER_OF(stream, struct bap_test_stream, stream); + printk("QoS: stream %p qos %p\n", stream, qos); print_qos(qos); + test_stream->tx_sdu_size = qos->sdu; + return 0; } @@ -173,8 +182,12 @@ static int lc3_metadata(struct bt_bap_stream *stream, const uint8_t meta[], size static int lc3_disable(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp) { + struct bap_test_stream *test_stream = CONTAINER_OF(stream, struct bap_test_stream, stream); + printk("Disable: stream %p\n", stream); + test_stream->tx_active = false; + return 0; } @@ -228,17 +241,153 @@ static void stream_enabled_cb(struct bt_bap_stream *stream) } } -static void stream_recv(struct bt_bap_stream *stream, const struct bt_iso_recv_info *info, - struct net_buf *buf) +static void stream_started_cb(struct bt_bap_stream *stream) { - printk("Incoming audio on stream %p len %u\n", stream, buf->len); + printk("Started: stream %p\n", stream); + + SET_FLAG(flag_stream_started); +} + +static void stream_recv_cb(struct bt_bap_stream *stream, const struct bt_iso_recv_info *info, + struct net_buf *buf) +{ + struct bap_test_stream *test_stream = CONTAINER_OF(stream, struct bap_test_stream, stream); + + printk("Incoming audio on stream %p len %u and ts %u\n", stream, buf->len, info->ts); + + if (test_stream->rx_cnt > 0U && info->ts == test_stream->last_info.ts) { + FAIL("Duplicated timestamp received: %u\n", test_stream->last_info.ts); + return; + } + + if (test_stream->rx_cnt > 0U && info->seq_num == test_stream->last_info.seq_num) { + FAIL("Duplicated PSN received: %u\n", test_stream->last_info.seq_num); + return; + } + + if (info->flags & BT_ISO_FLAGS_ERROR) { + FAIL("ISO receive error\n"); + return; + } + + if (info->flags & BT_ISO_FLAGS_LOST) { + FAIL("ISO receive lost\n"); + return; + } + + if (memcmp(buf->data, mock_iso_data, buf->len) == 0) { + test_stream->rx_cnt++; + } else { + FAIL("Unexpected data received"); + } +} + +static void stream_sent_cb(struct bt_bap_stream *stream) +{ + struct bap_test_stream *test_stream = CONTAINER_OF(stream, struct bap_test_stream, stream); + struct net_buf *buf; + int ret; + + if (!test_stream->tx_active) { + return; + } + + buf = net_buf_alloc(&tx_pool, K_FOREVER); + if (buf == NULL) { + printk("Could not allocate buffer when sending on %p\n", stream); + return; + } + + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); + net_buf_add_mem(buf, mock_iso_data, test_stream->tx_sdu_size); + ret = bt_bap_stream_send(stream, buf, test_stream->seq_num++, BT_ISO_TIMESTAMP_NONE); + if (ret < 0) { + /* This will end broadcasting on this stream. */ + net_buf_unref(buf); + + /* Only fail if tx is active (may fail if we are disabling the stream) */ + if (test_stream->tx_active) { + FAIL("Unable to send data on %p: %d\n", stream, ret); + } + + return; + } + + test_stream->tx_cnt++; } static struct bt_bap_stream_ops stream_ops = { .enabled = stream_enabled_cb, - .recv = stream_recv + .started = stream_started_cb, + .recv = stream_recv_cb, + .sent = stream_sent_cb, }; +static void transceive_streams(void) +{ + struct bt_bap_stream *source_stream = NULL; + struct bt_bap_stream *sink_stream = NULL; + struct bt_bap_ep_info info; + int err; + + for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { + struct bt_bap_stream *stream = &streams[i].stream; + + if (stream->ep == NULL) { + break; + } + + while (true) { + err = bt_bap_ep_get_info(stream->ep, &info); + if (err != 0) { + FAIL("Failed to get endpoint info for stream[%zu] %p: %d\n", i, + stream, err); + return; + } + + /* Ensure that all configured streams are in the streaming state before + * starting TX and RX + */ + if (info.state == BT_BAP_EP_STATE_STREAMING) { + break; + } + + k_sleep(K_MSEC(100)); + } + + if (info.dir == BT_AUDIO_DIR_SINK && sink_stream == NULL) { + sink_stream = stream; + } else if (info.dir == BT_AUDIO_DIR_SOURCE && source_stream == NULL) { + source_stream = stream; + } + } + + if (source_stream != NULL) { + struct bap_test_stream *test_stream = + CONTAINER_OF(source_stream, struct bap_test_stream, stream); + + test_stream->tx_active = true; + for (unsigned int i = 0U; i < ENQUEUE_COUNT; i++) { + stream_sent_cb(source_stream); + } + + /* Keep sending until we reach the minimum expected */ + while (test_stream->tx_cnt < MIN_SEND_COUNT) { + k_sleep(K_MSEC(100)); + } + } + + if (sink_stream != NULL) { + const struct bap_test_stream *test_stream = + CONTAINER_OF(sink_stream, struct bap_test_stream, stream); + + /* Keep receiving until we reach the minimum expected */ + while (test_stream->rx_cnt < MIN_SEND_COUNT) { + k_sleep(K_MSEC(100)); + } + } +} + static void set_location(void) { int err; @@ -333,7 +482,7 @@ static void init(void) set_available_contexts(); for (size_t i = 0; i < ARRAY_SIZE(streams); i++) { - bt_bap_stream_cb_register(&streams[i], &stream_ops); + bt_bap_stream_cb_register(&streams[i].stream, &stream_ops); } /* Create a non-connectable non-scannable advertising set */ @@ -367,8 +516,10 @@ static void test_main(void) WAIT_FOR_FLAG(flag_connected); WAIT_FOR_FLAG(flag_stream_configured); - WAIT_FOR_UNSET_FLAG(flag_connected); + WAIT_FOR_FLAG(flag_stream_started); + transceive_streams(); + WAIT_FOR_UNSET_FLAG(flag_connected); PASS("Unicast server passed\n"); } @@ -405,6 +556,8 @@ static void test_main_acl_disconnect(void) init(); + stream_ops.recv = NULL; /* We do not care about data in this test */ + /* Create CONFIG_BT_MAX_CONN - 1 dummy advertising sets, to ensure that we only have 1 free * connection when attempting to restart advertising, which should ensure that the * bt_conn object is properly unref'ed by the stack diff --git a/tests/bsim/bluetooth/audio/src/cap_initiator_broadcast_test.c b/tests/bsim/bluetooth/audio/src/cap_initiator_broadcast_test.c index 6e533255a19..b5c98ba1a9c 100644 --- a/tests/bsim/bluetooth/audio/src/cap_initiator_broadcast_test.c +++ b/tests/bsim/bluetooth/audio/src/cap_initiator_broadcast_test.c @@ -406,11 +406,18 @@ static void test_broadcast_audio_update_inval(struct bt_cap_broadcast_source *br static void test_broadcast_audio_update(struct bt_cap_broadcast_source *broadcast_source) { - const uint16_t mock_ccid = 0xAB; +#if defined(CONFIG_BT_TBS) + /* TODO: We do not have a way to get the CCID value of GTBS, but for now set to 0x00 as we + * know that it is the first content control service initialized + */ + const uint16_t gtbs_ccid = 0x00; +#endif /* CONFIG_BT_TBS */ const uint8_t new_metadata[] = { BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT, - BT_BYTES_LIST_LE16(BT_AUDIO_CONTEXT_TYPE_MEDIA)), - BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_CCID_LIST, mock_ccid), + BT_BYTES_LIST_LE16(BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL)), +#if defined(CONFIG_BT_TBS) + BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_CCID_LIST, gtbs_ccid), +#endif /* CONFIG_BT_TBS */ }; int err; diff --git a/tests/bsim/bluetooth/audio/src/cap_initiator_unicast_test.c b/tests/bsim/bluetooth/audio/src/cap_initiator_unicast_test.c index 4df05cdb8c1..335b2894838 100644 --- a/tests/bsim/bluetooth/audio/src/cap_initiator_unicast_test.c +++ b/tests/bsim/bluetooth/audio/src/cap_initiator_unicast_test.c @@ -54,7 +54,9 @@ extern enum bst_result_t bst_result; static struct bt_bap_lc3_preset unicast_preset_16_2_1 = BT_BAP_LC3_UNICAST_PRESET_16_2_1( BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); -static struct bt_cap_stream unicast_client_streams[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT]; +static struct bt_cap_stream unicast_client_sink_streams[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT]; +static struct bt_cap_stream + unicast_client_source_streams[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT]; static struct bt_bap_ep *unicast_sink_eps[CONFIG_BT_MAX_CONN][CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT]; static struct bt_bap_ep @@ -351,8 +353,12 @@ static void init(void) return; } - for (size_t i = 0; i < ARRAY_SIZE(unicast_client_streams); i++) { - bt_cap_stream_ops_register(&unicast_client_streams[i], &unicast_stream_ops); + for (size_t i = 0; i < ARRAY_SIZE(unicast_client_sink_streams); i++) { + bt_cap_stream_ops_register(&unicast_client_sink_streams[i], &unicast_stream_ops); + } + + for (size_t i = 0; i < ARRAY_SIZE(unicast_client_source_streams); i++) { + bt_cap_stream_ops_register(&unicast_client_source_streams[i], &unicast_stream_ops); } } @@ -506,15 +512,18 @@ static void discover_cas(struct bt_conn *conn) static void unicast_group_create(struct bt_bap_unicast_group **out_unicast_group) { - struct bt_bap_unicast_group_stream_param group_stream_params; + struct bt_bap_unicast_group_stream_param group_source_stream_params; + struct bt_bap_unicast_group_stream_param group_sink_stream_params; struct bt_bap_unicast_group_stream_pair_param pair_params; struct bt_bap_unicast_group_param group_param; int err; - group_stream_params.qos = &unicast_preset_16_2_1.qos; - group_stream_params.stream = &unicast_client_streams[0].bap_stream; - pair_params.tx_param = &group_stream_params; - pair_params.rx_param = NULL; + group_sink_stream_params.qos = &unicast_preset_16_2_1.qos; + group_sink_stream_params.stream = &unicast_client_sink_streams[0].bap_stream; + group_source_stream_params.qos = &unicast_preset_16_2_1.qos; + group_source_stream_params.stream = &unicast_client_source_streams[0].bap_stream; + pair_params.tx_param = &group_sink_stream_params; + pair_params.rx_param = &group_source_stream_params; group_param.packing = BT_ISO_PACKING_SEQUENTIAL; group_param.params_count = 1; @@ -542,7 +551,7 @@ static void unicast_audio_start_inval(struct bt_bap_unicast_group *unicast_group valid_start_param.stream_params = &valid_stream_param; valid_stream_param.member.member = default_conn; - valid_stream_param.stream = &unicast_client_streams[0]; + valid_stream_param.stream = &unicast_client_sink_streams[0]; valid_stream_param.ep = unicast_sink_eps[bt_conn_index(default_conn)][0]; valid_stream_param.codec_cfg = &unicast_preset_16_2_1.codec_cfg; @@ -639,18 +648,23 @@ static void unicast_audio_start_inval(struct bt_bap_unicast_group *unicast_group static void unicast_audio_start(struct bt_bap_unicast_group *unicast_group, bool wait) { - struct bt_cap_unicast_audio_start_stream_param stream_param[1]; + struct bt_cap_unicast_audio_start_stream_param stream_param[2]; struct bt_cap_unicast_audio_start_param param; int err; param.type = BT_CAP_SET_TYPE_AD_HOC; - param.count = 1u; + param.count = ARRAY_SIZE(stream_param); param.stream_params = stream_param; stream_param[0].member.member = default_conn; - stream_param[0].stream = &unicast_client_streams[0]; + stream_param[0].stream = &unicast_client_sink_streams[0]; stream_param[0].ep = unicast_sink_eps[bt_conn_index(default_conn)][0]; stream_param[0].codec_cfg = &unicast_preset_16_2_1.codec_cfg; + stream_param[1].member.member = default_conn; + stream_param[1].stream = &unicast_client_source_streams[0]; + stream_param[1].ep = unicast_source_eps[bt_conn_index(default_conn)][0]; + stream_param[1].codec_cfg = &unicast_preset_16_2_1.codec_cfg; + UNSET_FLAG(flag_started); err = bt_cap_initiator_unicast_audio_start(¶m, unicast_group); @@ -671,7 +685,7 @@ static void unicast_audio_update_inval(void) struct bt_cap_unicast_audio_update_param param; int err; - param.stream = &unicast_client_streams[0]; + param.stream = &unicast_client_sink_streams[0]; param.meta = unicast_preset_16_2_1.codec_cfg.meta; param.meta_len = unicast_preset_16_2_1.codec_cfg.meta_len; @@ -701,22 +715,35 @@ static void unicast_audio_update_inval(void) static void unicast_audio_update(void) { - struct bt_cap_unicast_audio_update_param param; + struct bt_cap_unicast_audio_update_param param[2]; + uint8_t new_meta[] = { + 3, + BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT, + BT_BYTES_LIST_LE16(BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED), + LONG_META_LEN, + BT_AUDIO_METADATA_TYPE_VENDOR, + LONG_META, + }; int err; - param.stream = &unicast_client_streams[0]; - param.meta = unicast_preset_16_2_1.codec_cfg.meta; - param.meta_len = unicast_preset_16_2_1.codec_cfg.meta_len; + param[0].stream = &unicast_client_sink_streams[0]; + param[0].meta = new_meta; + param[0].meta_len = ARRAY_SIZE(new_meta); + + param[1].stream = &unicast_client_source_streams[0]; + param[1].meta = new_meta; + param[1].meta_len = ARRAY_SIZE(new_meta); UNSET_FLAG(flag_updated); - err = bt_cap_initiator_unicast_audio_update(¶m, 1); + err = bt_cap_initiator_unicast_audio_update(param, ARRAY_SIZE(param)); if (err != 0) { FAIL("Failed to update unicast audio: %d\n", err); return; } WAIT_FOR_FLAG(flag_updated); + printk("READ LONG META\n"); } static void unicast_audio_stop_inval(void) @@ -808,6 +835,7 @@ static void test_main_cap_initiator_unicast(void) discover_cas(default_conn); discover_sink(default_conn); + discover_source(default_conn); for (size_t i = 0U; i < iterations; i++) { unicast_group_create(&unicast_group); @@ -841,6 +869,7 @@ static void test_main_cap_initiator_unicast_inval(void) discover_cas(default_conn); discover_sink(default_conn); + discover_source(default_conn); unicast_group_create(&unicast_group); @@ -875,6 +904,7 @@ static void test_cap_initiator_unicast_timeout(void) discover_cas(default_conn); discover_sink(default_conn); + discover_source(default_conn); unicast_group_create(&unicast_group); @@ -985,36 +1015,6 @@ static int cap_initiator_ac_create_unicast_group(const struct cap_initiator_ac_p return bt_bap_unicast_group_create(&group_param, unicast_group); } -static int set_chan_alloc(enum bt_audio_location loc, struct bt_audio_codec_cfg *codec_cfg) -{ - for (size_t i = 0U; i < codec_cfg->data_len;) { - const uint8_t len = codec_cfg->data[i++]; - uint8_t value_len; - uint8_t *value; - uint8_t type; - - if (len == 0 || len > codec_cfg->data_len - i) { - /* Invalid len field */ - return false; - } - - type = codec_cfg->data[i++]; - value = &codec_cfg->data[i]; - value_len = len - sizeof(type); - - if (type == BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC) { - const uint32_t loc_32 = loc; - - sys_put_le32(loc_32, value); - - return 0; - } - i += value_len; - } - - return -ENODATA; -} - static int cap_initiator_ac_cap_unicast_start(const struct cap_initiator_ac_param *param, struct unicast_stream *snk_uni_streams[], size_t snk_cnt, @@ -1104,7 +1104,13 @@ static int cap_initiator_ac_cap_unicast_start(const struct cap_initiator_ac_para stream_cnt++; if (param->conn_cnt > 1) { - set_chan_alloc(BIT(i), stream_param->codec_cfg); + const int err = bt_audio_codec_cfg_set_chan_allocation( + stream_param->codec_cfg, (enum bt_audio_location)BIT(i)); + + if (err < 0) { + FAIL("Failed to set channel allocation: %d\n", err); + return err; + } } } @@ -1121,7 +1127,13 @@ static int cap_initiator_ac_cap_unicast_start(const struct cap_initiator_ac_para stream_cnt++; if (param->conn_cnt > 1) { - set_chan_alloc(BIT(i), stream_param->codec_cfg); + const int err = bt_audio_codec_cfg_set_chan_allocation( + stream_param->codec_cfg, (enum bt_audio_location)BIT(i)); + + if (err < 0) { + FAIL("Failed to set channel allocation: %d\n", err); + return err; + } } } } diff --git a/tests/bsim/bluetooth/audio/src/common.c b/tests/bsim/bluetooth/audio/src/common.c index 90a8cb98efa..3ad69daf9ae 100644 --- a/tests/bsim/bluetooth/audio/src/common.c +++ b/tests/bsim/bluetooth/audio/src/common.c @@ -5,12 +5,18 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "bs_dynargs.h" +#include "bs_pc_backchannel.h" +#include +#include + #include "common.h" extern enum bst_result_t bst_result; struct bt_conn *default_conn; atomic_t flag_connected; atomic_t flag_conn_updated; +volatile bt_security_t security_level; const struct bt_data ad[AD_SIZE] = { BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)) @@ -74,7 +80,7 @@ static void connected(struct bt_conn *conn, uint8_t err) return; } - printk("Connected to %s\n", addr); + printk("Connected to %s (%p)\n", addr, conn); SET_FLAG(flag_connected); } @@ -94,6 +100,7 @@ void disconnected(struct bt_conn *conn, uint8_t reason) default_conn = NULL; UNSET_FLAG(flag_connected); UNSET_FLAG(flag_conn_updated); + security_level = BT_SECURITY_L1; } static void conn_param_updated_cb(struct bt_conn *conn, uint16_t interval, uint16_t latency, @@ -105,10 +112,20 @@ static void conn_param_updated_cb(struct bt_conn *conn, uint16_t interval, uint1 SET_FLAG(flag_conn_updated); } +static void security_changed_cb(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) +{ + printk("Security changed: %p level %d err %d\n", conn, level, err); + + if (err == BT_SECURITY_ERR_SUCCESS) { + security_level = level; + } +} + BT_CONN_CB_DEFINE(conn_callbacks) = { .connected = connected, .disconnected = disconnected, .le_param_updated = conn_param_updated_cb, + .security_changed = security_changed_cb, }; void test_tick(bs_time_t HW_device_time) @@ -123,3 +140,182 @@ void test_init(void) bst_ticker_set_next_tick_absolute(WAIT_TIME); bst_result = In_progress; } + +#define SYNC_MSG_SIZE 1 +static int32_t dev_cnt; +static uint backchannel_nums[255]; +static uint chan_cnt; + +static void register_more_cmd_args(void) +{ + static bs_args_struct_t args_struct_toadd[] = { + { + .option = "D", + .name = "number_devices", + .type = 'i', + .dest = (void *)&dev_cnt, + .descript = "Number of devices which will connect in this phy", + .is_mandatory = true, + }, + ARG_TABLE_ENDMARKER, + }; + + bs_add_extra_dynargs(args_struct_toadd); +} +NATIVE_TASK(register_more_cmd_args, PRE_BOOT_1, 100); + +/** + * @brief Get the channel id based on remote device ID + * + * The is effectively a very simple hashing function to generate unique channel IDs from device IDs + * + * @param dev 16-bit device ID + * + * @return uint 32-bit channel ID + */ +static uint get_chan_num(uint16_t dev) +{ + uint16_t self = (uint16_t)bsim_args_get_global_device_nbr(); + uint channel_id; + + if (self < dev) { + channel_id = (dev << 16) | self; + } else { + channel_id = (self << 16) | dev; + } + + return channel_id; +} + +/** + * @brief Set up the backchannels between each pair of device + * + * Each pair of devices will get a unique channel + */ +static void setup_backchannels(void) +{ + __ASSERT_NO_MSG(dev_cnt > 0 && dev_cnt < ARRAY_SIZE(backchannel_nums)); + const uint self = bsim_args_get_global_device_nbr(); + uint device_numbers[dev_cnt]; + uint *channels; + + for (int32_t i = 0; i < dev_cnt; i++) { + if (i != self) { /* skip ourselves*/ + backchannel_nums[chan_cnt] = get_chan_num((uint16_t)i); + device_numbers[chan_cnt++] = i; + } + } + + channels = bs_open_back_channel(self, device_numbers, backchannel_nums, chan_cnt); + __ASSERT_NO_MSG(channels != NULL); +} +NATIVE_TASK(setup_backchannels, PRE_BOOT_3, 100); + +static uint get_chan_id_from_chan_num(uint chan_num) +{ + for (uint i = 0; i < ARRAY_SIZE(backchannel_nums); i++) { + if (backchannel_nums[i] == chan_num) { + return i; + } + } + + return 0; +} + +void backchannel_sync_send(uint dev) +{ + const uint chan_id = get_chan_id_from_chan_num(get_chan_num((uint16_t)dev)); + uint8_t sync_msg[SYNC_MSG_SIZE] = {0}; + + printk("Sending sync to %u\n", chan_id); + bs_bc_send_msg(chan_id, sync_msg, ARRAY_SIZE(sync_msg)); +} + +void backchannel_sync_send_all(void) +{ + for (int32_t i = 0; i < dev_cnt; i++) { + const uint self = bsim_args_get_global_device_nbr(); + + if (i != self) { /* skip ourselves*/ + backchannel_sync_send(i); + } + } +} + +void backchannel_sync_wait(uint dev) +{ + const uint chan_id = get_chan_id_from_chan_num(get_chan_num((uint16_t)dev)); + + printk("Waiting for sync to %u\n", chan_id); + + while (true) { + if (bs_bc_is_msg_received(chan_id) > 0) { + uint8_t sync_msg[SYNC_MSG_SIZE]; + + bs_bc_receive_msg(chan_id, sync_msg, ARRAY_SIZE(sync_msg)); + /* We don't really care about the content of the message */ + break; + } + + k_sleep(K_MSEC(1)); + } +} + +void backchannel_sync_wait_all(void) +{ + for (int32_t i = 0; i < dev_cnt; i++) { + const uint self = bsim_args_get_global_device_nbr(); + + if (i != self) { /* skip ourselves*/ + backchannel_sync_wait(i); + } + } +} + +void backchannel_sync_wait_any(void) +{ + while (true) { + for (int32_t i = 0; i < dev_cnt; i++) { + const uint self = bsim_args_get_global_device_nbr(); + + if (i != self) { /* skip ourselves*/ + const uint chan_id = + get_chan_id_from_chan_num(get_chan_num((uint16_t)i)); + + if (bs_bc_is_msg_received(chan_id) > 0) { + uint8_t sync_msg[SYNC_MSG_SIZE]; + + bs_bc_receive_msg(chan_id, sync_msg, ARRAY_SIZE(sync_msg)); + /* We don't really care about the content of the message */ + + return; + } + } + } + + k_sleep(K_MSEC(100)); + } +} + +void backchannel_sync_clear(uint dev) +{ + const uint chan_id = get_chan_id_from_chan_num(get_chan_num((uint16_t)dev)); + + while (bs_bc_is_msg_received(chan_id)) { + uint8_t sync_msg[SYNC_MSG_SIZE]; + + bs_bc_receive_msg(chan_id, sync_msg, ARRAY_SIZE(sync_msg)); + /* We don't really care about the content of the message */ + } +} + +void backchannel_sync_clear_all(void) +{ + for (int32_t i = 0; i < dev_cnt; i++) { + const uint self = bsim_args_get_global_device_nbr(); + + if (i != self) { /* skip ourselves*/ + backchannel_sync_clear(i); + } + } +} diff --git a/tests/bsim/bluetooth/audio/src/common.h b/tests/bsim/bluetooth/audio/src/common.h index 14d6dbbc092..cc0b8d11a96 100644 --- a/tests/bsim/bluetooth/audio/src/common.h +++ b/tests/bsim/bluetooth/audio/src/common.h @@ -12,22 +12,44 @@ #include +#include "bstests.h" #include "bs_types.h" #include "bs_tracing.h" #include "time_machine.h" -#include "bstests.h" #include #include #include #include +#include #include #include #include #include #include +static const uint8_t mock_iso_data[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, + 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, + 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, + 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, + 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, + 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, +}; + +#define MIN_SEND_COUNT 100 #define WAIT_SECONDS 60 /* seconds */ #define WAIT_TIME (WAIT_SECONDS * USEC_PER_SEC) /* microseconds*/ @@ -70,9 +92,29 @@ extern const struct bt_data ad[AD_SIZE]; extern struct bt_conn *default_conn; extern atomic_t flag_connected; extern atomic_t flag_conn_updated; +extern volatile bt_security_t security_level; void disconnected(struct bt_conn *conn, uint8_t reason); void test_tick(bs_time_t HW_device_time); void test_init(void); +void backchannel_sync_send(uint dev); +void backchannel_sync_send_all(void); +void backchannel_sync_wait(uint dev); +void backchannel_sync_wait_all(void); +void backchannel_sync_wait_any(void); +void backchannel_sync_clear(uint dev); +void backchannel_sync_clear_all(void); + +struct bap_test_stream { + struct bt_bap_stream stream; + + uint16_t seq_num; + bool tx_active; + size_t tx_cnt; + uint16_t tx_sdu_size; + + struct bt_iso_recv_info last_info; + size_t rx_cnt; +}; #endif /* ZEPHYR_TEST_BSIM_BT_AUDIO_TEST_ */ diff --git a/tests/bsim/bluetooth/audio/src/csip_notify_client_test.c b/tests/bsim/bluetooth/audio/src/csip_notify_client_test.c new file mode 100644 index 00000000000..2ccad4046ba --- /dev/null +++ b/tests/bsim/bluetooth/audio/src/csip_notify_client_test.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2023 Demant A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "common.h" +#include "common/bt_str.h" + +extern enum bst_result_t bst_result; + +CREATE_FLAG(flag_csip_set_lock_discovered); +CREATE_FLAG(flag_all_notifications_received); + +static void csip_discover_cb(struct bt_conn *conn, + const struct bt_csip_set_coordinator_set_member *member, + int err, size_t set_count) +{ + if (err != 0) { + printk("CSIP Lock Discover failed (err = %d)\n", err); + return; + } + + if (member->insts->info.lockable) { + SET_FLAG(flag_csip_set_lock_discovered); + } +} + +static void csip_lock_changed(struct bt_csip_set_coordinator_csis_inst *inst, bool locked) +{ + SET_FLAG(flag_all_notifications_received); +} + +static struct bt_csip_set_coordinator_cb cbs = { + .lock_changed = csip_lock_changed, + .discover = csip_discover_cb, +}; + +static void test_main(void) +{ + int err; + + printk("Enabling Bluetooth\n"); + err = bt_enable(NULL); + if (err != 0) { + FAIL("Bluetooth enable failed (err %d)\n", err); + return; + } + + bt_le_scan_cb_register(&common_scan_cb); + bt_csip_set_coordinator_register_cb(&cbs); + + printk("Starting scan\n"); + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); + if (err != 0) { + FAIL("Could not start scanning (err %d)\n", err); + return; + } + + printk("Waiting for connect\n"); + WAIT_FOR_FLAG(flag_connected); + + printk("Raising security\n"); + err = bt_conn_set_security(default_conn, BT_SECURITY_L2); + if (err) { + FAIL("Failed to ser security level %d (err %d)\n", BT_SECURITY_L2, err); + return; + } + + printk("Starting Discovery\n"); + bt_csip_set_coordinator_discover(default_conn); + WAIT_FOR_FLAG(flag_csip_set_lock_discovered); + + printk("Waiting for all notifications to be received\n"); + + WAIT_FOR_FLAG(flag_all_notifications_received); + + /* Disconnect and wait for server to advertise again (after notifications are triggered) */ + bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + UNSET_FLAG(flag_all_notifications_received); + UNSET_FLAG(flag_csip_set_lock_discovered); + + printk("Waiting for disconnect\n"); + WAIT_FOR_UNSET_FLAG(flag_connected); + + printk("Starting scan\n"); + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); + if (err != 0) { + FAIL("Could not start scanning (err %d)\n", err); + return; + } + + printk("Waiting for reconnect\n"); + WAIT_FOR_FLAG(flag_connected); + + printk("Raising security\n"); + err = bt_conn_set_security(default_conn, BT_SECURITY_L2); + if (err) { + FAIL("Failed to ser security level %d (err %d)\n", BT_SECURITY_L2, err); + return; + } + + printk("Starting Discovery\n"); + bt_csip_set_coordinator_discover(default_conn); + WAIT_FOR_FLAG(flag_csip_set_lock_discovered); + + printk("Waiting for all notifications to be received\n"); + WAIT_FOR_FLAG(flag_all_notifications_received); + + bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + WAIT_FOR_UNSET_FLAG(flag_connected); + + PASS("CSIP Notify client Passed\n"); +} + +static const struct bst_test_instance test_csip_notify_client[] = { + { + .test_id = "csip_notify_client", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_main, + }, + BSTEST_END_MARKER, +}; + +struct bst_test_list *test_csip_notify_client_install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, test_csip_notify_client); +} diff --git a/tests/bsim/bluetooth/audio/src/csip_notify_server_test.c b/tests/bsim/bluetooth/audio/src/csip_notify_server_test.c new file mode 100644 index 00000000000..ec94a320ffd --- /dev/null +++ b/tests/bsim/bluetooth/audio/src/csip_notify_server_test.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2023 Demant A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "common.h" + +extern enum bst_result_t bst_result; + +static struct bt_csip_set_member_svc_inst *svc_inst; + +static bool is_peer_subscribed(struct bt_conn *conn) +{ + struct bt_gatt_attr *attr; + + attr = bt_gatt_find_by_uuid(NULL, 0, BT_UUID_CSIS_SET_LOCK); + if (!attr) { + printk("No BT_UUID_PACS_SNK attribute found\n"); + return false; + } + + return bt_gatt_is_subscribed(conn, attr, BT_GATT_CCC_NOTIFY); +} + +static void csip_set_member_lock_changed_cb(struct bt_conn *conn, + struct bt_csip_set_member_svc_inst *svc_inst, + bool locked) +{ + printk("Client %p %s the lock\n", conn, locked ? "locked" : "released"); +} + +static struct bt_csip_set_member_cb csip_cb = { + .lock_changed = csip_set_member_lock_changed_cb, +}; + +static void test_main(void) +{ + int err; + const struct bt_data ad[] = { + BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), + }; + struct bt_csip_set_member_register_param csip_params = { + .set_size = 1, + .rank = 1, + .lockable = true, + .cb = &csip_cb, + }; + + printk("Enabling Bluetooth\n"); + err = bt_enable(NULL); + if (err != 0) { + FAIL("Bluetooth enable failed (err %d)\n", err); + return; + } + + printk("Registering CSIP Set Member\n"); + + err = bt_cap_acceptor_register(&csip_params, &svc_inst); + if (err != 0) { + printk("Failed to register csip\n"); + return; + } + + printk("Start Advertising\n"); + err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0); + if (err != 0) { + FAIL("Advertising failed to start (err %d)\n", err); + return; + } + + printk("Waiting to be connected\n"); + WAIT_FOR_FLAG(flag_connected); + printk("Connected\n"); + printk("Waiting to be subscribed\n"); + + while (!is_peer_subscribed(default_conn)) { + (void)k_sleep(K_MSEC(10)); + } + printk("Subscribed\n"); + + err = bt_csip_set_member_lock(svc_inst, true, false); + if (err != 0) { + FAIL("Failed to set lock (err %d)\n", err); + return; + } + + /* Now wait for client to disconnect, then stop adv so it does not reconnect */ + printk("Wait for client disconnect\n"); + WAIT_FOR_UNSET_FLAG(flag_connected); + printk("Client disconnected\n"); + + err = bt_le_adv_stop(); + if (err != 0) { + FAIL("Advertising failed to stop (err %d)\n", err); + return; + } + + /* Trigger changes while device is disconnected */ + err = bt_csip_set_member_lock(svc_inst, false, false); + if (err != 0) { + FAIL("Failed to set lock (err %d)\n", err); + return; + } + + printk("Start Advertising\n"); + err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0); + if (err != 0) { + FAIL("Advertising failed to start (err %d)\n", err); + return; + } + + WAIT_FOR_FLAG(flag_connected); + WAIT_FOR_UNSET_FLAG(flag_connected); + + PASS("CSIP Notify Server passed\n"); +} + +static const struct bst_test_instance test_csip_notify_server[] = { + { + .test_id = "csip_notify_server", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_main, + }, + BSTEST_END_MARKER, +}; + +struct bst_test_list *test_csip_notify_server_install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, test_csip_notify_server); +} diff --git a/tests/bsim/bluetooth/audio/src/has_client_test.c b/tests/bsim/bluetooth/audio/src/has_client_test.c index 6690c6b032e..27ad787fef1 100644 --- a/tests/bsim/bluetooth/audio/src/has_client_test.c +++ b/tests/bsim/bluetooth/audio/src/has_client_test.c @@ -4,9 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifdef CONFIG_BT_HAS_CLIENT #include +#include "../../subsys/bluetooth/audio/has_internal.h" + #include "common.h" extern enum bst_result_t bst_result; @@ -14,12 +15,15 @@ extern enum bst_result_t bst_result; extern const char *test_preset_name_1; extern const char *test_preset_name_5; extern const uint8_t test_preset_index_1; +extern const uint8_t test_preset_index_3; extern const uint8_t test_preset_index_5; extern const enum bt_has_properties test_preset_properties; +#ifdef CONFIG_BT_HAS_CLIENT CREATE_FLAG(g_service_discovered); CREATE_FLAG(g_preset_switched); CREATE_FLAG(g_preset_1_found); +CREATE_FLAG(g_preset_3_found); CREATE_FLAG(g_preset_5_found); static struct bt_has *g_has; @@ -82,10 +86,23 @@ static void preset_read_rsp_cb(struct bt_has *has, int err, } } +static void preset_update_cb(struct bt_has *has, uint8_t index_prev, + const struct bt_has_preset_record *record, bool is_last) +{ + if (record->index == test_preset_index_1) { + SET_FLAG(g_preset_1_found); + } else if (record->index == test_preset_index_3) { + SET_FLAG(g_preset_3_found); + } else if (record->index == test_preset_index_5) { + SET_FLAG(g_preset_5_found); + } +} + static const struct bt_has_client_cb has_cb = { .discover = discover_cb, .preset_switch = preset_switch_cb, .preset_read_rsp = preset_read_rsp_cb, + .preset_update = preset_update_cb, }; static bool test_preset_switch(uint8_t index) @@ -229,14 +246,445 @@ static void test_main(void) PASS("HAS main PASS\n"); } +#endif /* CONFIG_BT_HAS_CLIENT */ + +#define FEATURES_SUB_NTF BIT(0) +#define ACTIVE_INDEX_SUB_NTF BIT(1) +#define PRESET_CHANGED_SUB_NTF BIT(2) +#define SUB_NTF_ALL (FEATURES_SUB_NTF | ACTIVE_INDEX_SUB_NTF | PRESET_CHANGED_SUB_NTF) + +CREATE_FLAG(flag_features_discovered); +CREATE_FLAG(flag_active_preset_index_discovered); +CREATE_FLAG(flag_control_point_discovered); +CREATE_FLAG(flag_all_notifications_received); + +enum preset_state { + STATE_UNKNOWN, + STATE_AVAILABLE, + STATE_UNAVAILABLE, + STATE_DELETED, +}; + +static enum preset_state preset_state_1; +static enum preset_state preset_state_3; +static enum preset_state preset_state_5; + +static struct bt_uuid_16 uuid = BT_UUID_INIT_16(0); +static struct bt_gatt_discover_params discover_params; +static struct bt_gatt_subscribe_params features_sub; +static struct bt_gatt_subscribe_params active_preset_index_sub; +static struct bt_gatt_subscribe_params control_point_sub; +static uint8_t notify_received_mask; + +static void preset_availability_changed(uint8_t index, bool available) +{ + enum preset_state state = available ? STATE_AVAILABLE : STATE_UNAVAILABLE; + + if (index == test_preset_index_1) { + preset_state_1 = state; + } else if (index == test_preset_index_3) { + preset_state_3 = state; + } else if (index == test_preset_index_5) { + preset_state_5 = state; + } else { + FAIL("invalid preset index 0x%02x", index); + } +} + +static uint8_t notify_handler(struct bt_conn *conn, struct bt_gatt_subscribe_params *params, + const void *data, uint16_t length) +{ + printk("conn %p params %p data %p length %u\n", (void *)conn, params, data, length); + + if (params == &features_sub) { + if (data == NULL) { + printk("features_sub [UNSUBSCRIBED]\n"); + return BT_GATT_ITER_STOP; + } + + printk("Received features_sub notification\n"); + notify_received_mask |= FEATURES_SUB_NTF; + } else if (params == &active_preset_index_sub) { + if (data == NULL) { + printk("active_preset_index_sub_sub [UNSUBSCRIBED]\n"); + return BT_GATT_ITER_STOP; + } + + printk("Received active_preset_index_sub_sub notification\n"); + notify_received_mask |= ACTIVE_INDEX_SUB_NTF; + } else if (params == &control_point_sub) { + const struct bt_has_cp_hdr *hdr; + + if (data == NULL) { + printk("control_point_sub [UNSUBSCRIBED]\n"); + return BT_GATT_ITER_STOP; + } + + if (length < sizeof(*hdr)) { + FAIL("malformed bt_has_cp_hdr"); + return BT_GATT_ITER_STOP; + } + + hdr = data; + + if (hdr->opcode == BT_HAS_OP_PRESET_CHANGED) { + const struct bt_has_cp_preset_changed *pc; + + if (length < (sizeof(*hdr) + sizeof(*pc))) { + FAIL("malformed bt_has_cp_preset_changed"); + return BT_GATT_ITER_STOP; + } + + pc = (const void *)hdr->data; + + switch (pc->change_id) { + case BT_HAS_CHANGE_ID_GENERIC_UPDATE: { + const struct bt_has_cp_generic_update *gu; + bool is_available; + + if (length < (sizeof(*hdr) + sizeof(*pc) + sizeof(*gu))) { + FAIL("malformed bt_has_cp_generic_update"); + return BT_GATT_ITER_STOP; + } + + gu = (const void *)pc->additional_params; + + printk("Received generic update index 0x%02x props 0x%02x\n", + gu->index, gu->properties); + + is_available = (gu->properties & BT_HAS_PROP_AVAILABLE) != 0; + + preset_availability_changed(gu->index, is_available); + break; + } + default: + printk("Unexpected Change ID 0x%02x", pc->change_id); + return BT_GATT_ITER_STOP; + } + + if (pc->is_last) { + notify_received_mask |= PRESET_CHANGED_SUB_NTF; + } + } else { + printk("Unexpected opcode 0x%02x", hdr->opcode); + return BT_GATT_ITER_STOP; + } + } + + printk("pacs_instance.notify_received_mask is %d\n", notify_received_mask); + + if (notify_received_mask == SUB_NTF_ALL) { + SET_FLAG(flag_all_notifications_received); + notify_received_mask = 0; + } + + return BT_GATT_ITER_CONTINUE; +} + +static void subscribe_cb(struct bt_conn *conn, uint8_t err, struct bt_gatt_subscribe_params *params) +{ + if (err != BT_ATT_ERR_SUCCESS) { + return; + } + + printk("[SUBSCRIBED]\n"); + + if (params == &features_sub) { + SET_FLAG(flag_features_discovered); + return; + } + + if (params == &control_point_sub) { + SET_FLAG(flag_control_point_discovered); + return; + } + + if (params == &active_preset_index_sub) { + SET_FLAG(flag_active_preset_index_discovered); + return; + } +} + +static uint8_t discover_features_cb(struct bt_conn *conn, const struct bt_gatt_attr *attr, + struct bt_gatt_discover_params *params) +{ + struct bt_gatt_subscribe_params *subscribe_params; + int err; + + if (!attr) { + printk("Discover complete\n"); + (void)memset(params, 0, sizeof(*params)); + return BT_GATT_ITER_STOP; + } + + if (!bt_uuid_cmp(params->uuid, BT_UUID_HAS_HEARING_AID_FEATURES)) { + printk("HAS Hearing Aid Features handle at %d\n", attr->handle); + memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(uuid)); + discover_params.uuid = &uuid.uuid; + discover_params.start_handle = attr->handle + 2; + discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR; + subscribe_params = &features_sub; + subscribe_params->value_handle = bt_gatt_attr_value_handle(attr); + + err = bt_gatt_discover(conn, &discover_params); + if (err) { + printk("Discover failed (err %d)\n", err); + } + } else if (!bt_uuid_cmp(params->uuid, BT_UUID_GATT_CCC)) { + printk("CCC handle at %d\n", attr->handle); + subscribe_params = &features_sub; + subscribe_params->notify = notify_handler; + subscribe_params->value = BT_GATT_CCC_NOTIFY; + subscribe_params->ccc_handle = attr->handle; + subscribe_params->subscribe = subscribe_cb; + + err = bt_gatt_subscribe(conn, subscribe_params); + if (err && err != -EALREADY) { + printk("Subscribe failed (err %d)\n", err); + } + } else { + printk("Unknown handle at %d\n", attr->handle); + return BT_GATT_ITER_CONTINUE; + } + + return BT_GATT_ITER_STOP; +} + +static void discover_and_subscribe_features(void) +{ + int err = 0; + + printk("%s\n", __func__); + + memcpy(&uuid, BT_UUID_HAS_HEARING_AID_FEATURES, sizeof(uuid)); + discover_params.uuid = &uuid.uuid; + discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE; + discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; + discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC; + discover_params.func = discover_features_cb; + + err = bt_gatt_discover(default_conn, &discover_params); + if (err != 0) { + FAIL("Service Discovery failed (err %d)\n", err); + return; + } +} + +static uint8_t discover_active_preset_index_cb(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + struct bt_gatt_discover_params *params) +{ + struct bt_gatt_subscribe_params *subscribe_params; + int err; + + if (!attr) { + printk("Discover complete\n"); + (void)memset(params, 0, sizeof(*params)); + return BT_GATT_ITER_STOP; + } + + if (!bt_uuid_cmp(params->uuid, BT_UUID_HAS_ACTIVE_PRESET_INDEX)) { + printk("HAS Hearing Aid Features handle at %d\n", attr->handle); + memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(uuid)); + discover_params.uuid = &uuid.uuid; + discover_params.start_handle = attr->handle + 2; + discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR; + subscribe_params = &active_preset_index_sub; + subscribe_params->value_handle = bt_gatt_attr_value_handle(attr); + + err = bt_gatt_discover(conn, &discover_params); + if (err) { + printk("Discover failed (err %d)\n", err); + } + } else if (!bt_uuid_cmp(params->uuid, BT_UUID_GATT_CCC)) { + printk("CCC handle at %d\n", attr->handle); + subscribe_params = &active_preset_index_sub; + subscribe_params->notify = notify_handler; + subscribe_params->value = BT_GATT_CCC_NOTIFY; + subscribe_params->ccc_handle = attr->handle; + subscribe_params->subscribe = subscribe_cb; + + err = bt_gatt_subscribe(conn, subscribe_params); + if (err && err != -EALREADY) { + printk("Subscribe failed (err %d)\n", err); + } + } else { + printk("Unknown handle at %d\n", attr->handle); + return BT_GATT_ITER_CONTINUE; + } + + return BT_GATT_ITER_STOP; +} + +static void discover_and_subscribe_active_preset_index(void) +{ + int err = 0; + + printk("%s\n", __func__); + + memcpy(&uuid, BT_UUID_HAS_ACTIVE_PRESET_INDEX, sizeof(uuid)); + discover_params.uuid = &uuid.uuid; + discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE; + discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; + discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC; + discover_params.func = discover_active_preset_index_cb; + + err = bt_gatt_discover(default_conn, &discover_params); + if (err != 0) { + FAIL("Service Discovery failed (err %d)\n", err); + return; + } +} + +static uint8_t discover_control_point_cb(struct bt_conn *conn, const struct bt_gatt_attr *attr, + struct bt_gatt_discover_params *params) +{ + struct bt_gatt_subscribe_params *subscribe_params; + int err; + + if (!attr) { + printk("Discover complete\n"); + (void)memset(params, 0, sizeof(*params)); + return BT_GATT_ITER_STOP; + } + + if (!bt_uuid_cmp(params->uuid, BT_UUID_HAS_PRESET_CONTROL_POINT)) { + printk("HAS Control Point handle at %d\n", attr->handle); + memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(uuid)); + discover_params.uuid = &uuid.uuid; + discover_params.start_handle = attr->handle + 2; + discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR; + subscribe_params = &control_point_sub; + subscribe_params->value_handle = bt_gatt_attr_value_handle(attr); + + err = bt_gatt_discover(conn, &discover_params); + if (err) { + printk("Discover failed (err %d)\n", err); + } + } else if (!bt_uuid_cmp(params->uuid, BT_UUID_GATT_CCC)) { + printk("CCC handle at %d\n", attr->handle); + subscribe_params = &control_point_sub; + subscribe_params->notify = notify_handler; + subscribe_params->value = BT_GATT_CCC_INDICATE; + subscribe_params->ccc_handle = attr->handle; + subscribe_params->subscribe = subscribe_cb; + + err = bt_gatt_subscribe(conn, subscribe_params); + if (err && err != -EALREADY) { + printk("Subscribe failed (err %d)\n", err); + } + } else { + printk("Unknown handle at %d\n", attr->handle); + return BT_GATT_ITER_CONTINUE; + } + + return BT_GATT_ITER_STOP; +} + +static void discover_and_subscribe_control_point(void) +{ + int err = 0; + + printk("%s\n", __func__); + + memcpy(&uuid, BT_UUID_HAS_PRESET_CONTROL_POINT, sizeof(uuid)); + discover_params.uuid = &uuid.uuid; + discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE; + discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; + discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC; + discover_params.func = discover_control_point_cb; + + err = bt_gatt_discover(default_conn, &discover_params); + if (err != 0) { + FAIL("Control Point failed (err %d)\n", err); + return; + } +} + +static void test_gatt_client(void) +{ + int err; + + err = bt_enable(NULL); + if (err < 0) { + FAIL("Bluetooth discover failed (err %d)\n", err); + return; + } + + printk("Bluetooth initialized\n"); + + bt_le_scan_cb_register(&common_scan_cb); + + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); + if (err < 0) { + FAIL("Scanning failed to start (err %d)\n", err); + return; + } + + printk("Scanning successfully started\n"); + + WAIT_FOR_FLAG(flag_connected); + + err = bt_conn_set_security(default_conn, BT_SECURITY_L2); + if (err) { + FAIL("Failed to set security level %d (err %d)\n", BT_SECURITY_L2, err); + return; + } + + WAIT_FOR_COND(security_level == BT_SECURITY_L2); + + discover_and_subscribe_features(); + WAIT_FOR_FLAG(flag_features_discovered); + + discover_and_subscribe_active_preset_index(); + WAIT_FOR_FLAG(flag_active_preset_index_discovered); + + discover_and_subscribe_control_point(); + WAIT_FOR_FLAG(flag_control_point_discovered); + + bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + WAIT_FOR_UNSET_FLAG(flag_connected); + + notify_received_mask = 0; + UNSET_FLAG(flag_all_notifications_received); + + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); + if (err < 0) { + FAIL("Scanning failed to start (err %d)\n", err); + return; + } + + printk("Scanning successfully started\n"); + + WAIT_FOR_FLAG(flag_connected); + + err = bt_conn_set_security(default_conn, BT_SECURITY_L2); + if (err) { + FAIL("Failed to set security level %d (err %d)\n", BT_SECURITY_L2, err); + return; + } + + WAIT_FOR_FLAG(flag_all_notifications_received); + + PASS("HAS main PASS\n"); +} static const struct bst_test_instance test_has[] = { +#ifdef CONFIG_BT_HAS_CLIENT { .test_id = "has_client", .test_post_init_f = test_init, .test_tick_f = test_tick, .test_main_f = test_main, }, +#endif /* CONFIG_BT_HAS_CLIENT */ + { + .test_id = "has_client_offline_behavior", + .test_descr = "Test receiving notifications after reconnection", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_gatt_client, + }, BSTEST_END_MARKER }; @@ -244,10 +692,3 @@ struct bst_test_list *test_has_client_install(struct bst_test_list *tests) { return bst_add_tests(tests, test_has); } -#else -struct bst_test_list *test_has_client_install(struct bst_test_list *tests) -{ - return tests; -} - -#endif /* CONFIG_BT_HAS_CLIENT */ diff --git a/tests/bsim/bluetooth/audio/src/has_test.c b/tests/bsim/bluetooth/audio/src/has_test.c index f8178b61d26..f2b5bdeade9 100644 --- a/tests/bsim/bluetooth/audio/src/has_test.c +++ b/tests/bsim/bluetooth/audio/src/has_test.c @@ -13,8 +13,10 @@ extern enum bst_result_t bst_result; const uint8_t test_preset_index_1 = 0x01; +const uint8_t test_preset_index_3 = 0x03; const uint8_t test_preset_index_5 = 0x05; const char *test_preset_name_1 = "test_preset_name_1"; +const char *test_preset_name_3 = "test_preset_name_3"; const char *test_preset_name_5 = "test_preset_name_5"; const enum bt_has_properties test_preset_properties = BT_HAS_PROP_AVAILABLE; @@ -27,7 +29,7 @@ static const struct bt_has_preset_ops preset_ops = { .select = preset_select, }; -static void test_main(void) +static void test_common(void) { struct bt_has_features_param has_param = {0}; struct bt_has_preset_register_param preset_param; @@ -94,6 +96,55 @@ static void test_main(void) PASS("HAS passed\n"); } +static void test_main(void) +{ + test_common(); + + PASS("HAS passed\n"); +} + +static void test_offline_behavior(void) +{ + struct bt_has_preset_register_param preset_param; + struct bt_has_features_param has_param = {0}; + int err; + + test_common(); + + WAIT_FOR_FLAG(flag_connected); + WAIT_FOR_UNSET_FLAG(flag_connected); + + preset_param.index = test_preset_index_3; + preset_param.properties = test_preset_properties; + preset_param.name = test_preset_name_3; + preset_param.ops = &preset_ops, + + err = bt_has_preset_register(&preset_param); + if (err) { + FAIL("Preset register failed (err %d)\n", err); + return; + } + + has_param.type = BT_HAS_HEARING_AID_TYPE_BINAURAL; + has_param.preset_sync_support = true; + + err = bt_has_features_set(&has_param); + if (err) { + FAIL("Features set failed (err %d)\n", err); + return; + } + + err = bt_has_preset_active_set(test_preset_index_3); + if (err) { + FAIL("Preset activation failed (err %d)\n", err); + return; + } + + WAIT_FOR_FLAG(flag_connected); + + PASS("HAS passed\n"); +} + static const struct bst_test_instance test_has[] = { { .test_id = "has", @@ -101,6 +152,12 @@ static const struct bst_test_instance test_has[] = { .test_tick_f = test_tick, .test_main_f = test_main, }, + { + .test_id = "has_offline_behavior", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_offline_behavior, + }, BSTEST_END_MARKER, }; diff --git a/tests/bsim/bluetooth/audio/src/ias_client_test.c b/tests/bsim/bluetooth/audio/src/ias_client_test.c index 7c24b1a172a..0966d899306 100644 --- a/tests/bsim/bluetooth/audio/src/ias_client_test.c +++ b/tests/bsim/bluetooth/audio/src/ias_client_test.c @@ -7,7 +7,7 @@ #include #ifdef CONFIG_BT_IAS_CLIENT -#include "zephyr/bluetooth/services/ias.h" +#include #include "common.h" extern enum bst_result_t bst_result; diff --git a/tests/bsim/bluetooth/audio/src/main.c b/tests/bsim/bluetooth/audio/src/main.c index 95df4844002..f4ef6294545 100644 --- a/tests/bsim/bluetooth/audio/src/main.c +++ b/tests/bsim/bluetooth/audio/src/main.c @@ -35,6 +35,8 @@ extern struct bst_test_list *test_tmap_client_install(struct bst_test_list *test extern struct bst_test_list *test_tmap_server_install(struct bst_test_list *tests); extern struct bst_test_list *test_pacs_notify_client_install(struct bst_test_list *tests); extern struct bst_test_list *test_pacs_notify_server_install(struct bst_test_list *tests); +extern struct bst_test_list *test_csip_notify_client_install(struct bst_test_list *tests); +extern struct bst_test_list *test_csip_notify_server_install(struct bst_test_list *tests); bst_test_install_t test_installers[] = { test_vcp_install, @@ -66,6 +68,8 @@ bst_test_install_t test_installers[] = { test_tmap_client_install, test_pacs_notify_client_install, test_pacs_notify_server_install, + test_csip_notify_client_install, + test_csip_notify_server_install, NULL }; diff --git a/tests/bsim/bluetooth/audio/test_scripts/bap_bass_client_sync.sh b/tests/bsim/bluetooth/audio/test_scripts/bap_bass_client_sync.sh index 658fb605180..1410af91138 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/bap_bass_client_sync.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/bap_bass_client_sync.sh @@ -16,14 +16,14 @@ printf "\n\n======== Running BASS Client Sync =========\n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=bap_scan_delegator_client_sync \ - -rs=24 + -rs=24 -D=3 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 \ - -testid=bap_broadcast_assistant_client_sync -rs=46 + -testid=bap_broadcast_assistant_client_sync -rs=46 -D=3 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=2 -testid=bass_broadcaster -rs=69 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=2 -testid=bass_broadcaster -rs=69 -D=3 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -D=3 \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/bap_bass_server_sync_client_rem.sh b/tests/bsim/bluetooth/audio/test_scripts/bap_bass_server_sync_client_rem.sh index 9c04e187c33..a20060b2e6c 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/bap_bass_server_sync_client_rem.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/bap_bass_server_sync_client_rem.sh @@ -28,14 +28,14 @@ printf "\n\n======== Running BASS Server Sync Client Remove =========\n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 \ - -testid=bap_scan_delegator_server_sync_client_rem -rs=24 + -testid=bap_scan_delegator_server_sync_client_rem -rs=24 -D=3 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 \ - -testid=bap_broadcast_assistant_server_sync_client_rem -rs=46 + -testid=bap_broadcast_assistant_server_sync_client_rem -rs=46 -D=3 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=2 -testid=bass_broadcaster -rs=69 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=2 -testid=bass_broadcaster -rs=69 -D=3 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -D=3 \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/bap_bass_server_sync_server_rem.sh b/tests/bsim/bluetooth/audio/test_scripts/bap_bass_server_sync_server_rem.sh index aec69e55745..65dedab5363 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/bap_bass_server_sync_server_rem.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/bap_bass_server_sync_server_rem.sh @@ -28,14 +28,14 @@ printf "\n\n======== Running BASS Server Sync Server Remove =========\n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 \ - -testid=bap_scan_delegator_server_sync_server_rem -rs=24 + -testid=bap_scan_delegator_server_sync_server_rem -rs=24 -D=3 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 \ - -testid=bap_broadcast_assistant_server_sync_server_rem -rs=46 + -testid=bap_broadcast_assistant_server_sync_server_rem -rs=46 -D=3 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=2 -testid=bass_broadcaster -rs=69 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=2 -testid=bass_broadcaster -rs=69 -D=3 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -D=3 \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/bap_broadcast_audio.sh b/tests/bsim/bluetooth/audio/test_scripts/bap_broadcast_audio.sh index 10e9af21bbe..c80d54c99ad 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/bap_broadcast_audio.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/bap_broadcast_audio.sh @@ -16,11 +16,11 @@ printf "\n\n======== Broadcaster test =========\n\n" SIMULATION_ID="broadcaster" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=broadcast_source -rs=23 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=broadcast_source -rs=23 -D=2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=broadcast_sink -rs=27 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=broadcast_sink -rs=27 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ @@ -33,12 +33,12 @@ printf "\n\n======== Broadcaster sink disconnect test =========\n\n" SIMULATION_ID="broadcaster_sink_disconnect" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=broadcast_source -rs=23 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=broadcast_source -rs=23 -D=2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 \ - -testid=broadcast_sink_disconnect -rs=27 + -testid=broadcast_sink_disconnect -rs=27 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/bap_broadcast_audio_assistant.sh b/tests/bsim/bluetooth/audio/test_scripts/bap_broadcast_audio_assistant.sh new file mode 100755 index 00000000000..82fcdff6c13 --- /dev/null +++ b/tests/bsim/bluetooth/audio/test_scripts/bap_broadcast_audio_assistant.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 + +SIMULATION_ID="bap_broadcast_audio_assistant" +VERBOSITY_LEVEL=2 +EXECUTE_TIMEOUT=20 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +cd ${BSIM_OUT_PATH}/bin + +printf "\n\n======== Running BAP Broadcast Audio Assistant =========\n\n" + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 \ + -testid=broadcast_sink_with_assistant -rs=24 -D=3 + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 \ + -testid=bap_broadcast_assistant_client_sync -rs=46 -D=3 + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=2 \ + -testid=broadcast_source -rs=69 -D=3 + +# Simulation time should be larger than the WAIT_TIME in common.h +Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -D=3 -sim_length=60e6 $@ + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/audio/test_scripts/bap_unicast_audio.sh b/tests/bsim/bluetooth/audio/test_scripts/bap_unicast_audio.sh index 425f20ccff3..c804336ec1f 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/bap_unicast_audio.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/bap_unicast_audio.sh @@ -15,10 +15,10 @@ cd ${BSIM_OUT_PATH}/bin printf "\n\n======== Unicast Audio test =========\n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=unicast_client -rs=23 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=unicast_client -rs=23 -D=2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=unicast_server -rs=28 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=unicast_server -rs=28 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/bap_unicast_audio_acl_disconnect.sh b/tests/bsim/bluetooth/audio/test_scripts/bap_unicast_audio_acl_disconnect.sh index 875a2b752dc..e3852b539ab 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/bap_unicast_audio_acl_disconnect.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/bap_unicast_audio_acl_disconnect.sh @@ -15,10 +15,10 @@ cd ${BSIM_OUT_PATH}/bin printf "\n\n======== Unicast Audio ACL Disconnect test =========\n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=unicast_client_acl_disconnect -rs=23 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=unicast_client_acl_disconnect -rs=23 -D=2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=unicast_server_acl_disconnect -rs=28 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=unicast_server_acl_disconnect -rs=28 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/cap_broadcast.sh b/tests/bsim/bluetooth/audio/test_scripts/cap_broadcast.sh index cf4f95a49e0..ce2b37d1eae 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/cap_broadcast.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/cap_broadcast.sh @@ -15,10 +15,10 @@ cd ${BSIM_OUT_PATH}/bin printf "\n\n======== Running CAP broadcast test =========\n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_broadcast -rs=46 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_broadcast -rs=46 -D=2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_broadcast -rs=23 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_broadcast -rs=23 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast.sh b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast.sh index 7a888e1ff0e..a4404412b3c 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast.sh @@ -15,10 +15,10 @@ cd ${BSIM_OUT_PATH}/bin printf "\n\n======== Running CAP unicast test =========\n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_unicast -rs=46 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_unicast -rs=46 -D=2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast -rs=23 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast -rs=23 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_1.sh b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_1.sh index b7b52002c7d..199b0144b34 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_1.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_1.sh @@ -17,11 +17,11 @@ function Execute_AC_1() { Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_ac_1 \ - -RealEncryption=1 -rs=23 -argstest sink_preset $1 + -RealEncryption=1 -rs=23 -D=2 -argstest sink_preset $1 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast \ - -RealEncryption=1 -rs=46 + -RealEncryption=1 -rs=46 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ @@ -40,8 +40,8 @@ Execute_AC_1 24_1_1 Execute_AC_1 24_2_1 Execute_AC_1 32_1_1 Execute_AC_1 32_2_1 -# Execute_AC_1 441_1_1 # ASSERTION FAIL [iso_interval_us >= cig->c_sdu_interval] -# Execute_AC_1 441_2_1 # ASSERTION FAIL [iso_interval_us >= cig->c_sdu_interval] +Execute_AC_1 441_1_1 +Execute_AC_1 441_2_1 Execute_AC_1 48_1_1 Execute_AC_1 48_2_1 Execute_AC_1 48_3_1 diff --git a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_10.sh b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_10.sh index c1a3a90b51f..af35c7ad66b 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_10.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_10.sh @@ -17,11 +17,11 @@ function Execute_AC_10() { Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_ac_10 \ - -RealEncryption=1 -rs=23 -argstest source_preset $1 + -RealEncryption=1 -rs=23 -D=2 -argstest source_preset $1 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast \ - -RealEncryption=1 -rs=46 + -RealEncryption=1 -rs=46 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ @@ -40,8 +40,8 @@ Execute_AC_10 24_1_1 Execute_AC_10 24_2_1 Execute_AC_10 32_1_1 Execute_AC_10 32_2_1 -# Execute_AC_10 441_1_1 # ASSERTION FAIL [iso_interval_us >= cig->c_sdu_interval] -# Execute_AC_10 441_2_1 # ASSERTION FAIL [iso_interval_us >= cig->c_sdu_interval] +Execute_AC_10 441_1_1 +Execute_AC_10 441_2_1 Execute_AC_10 48_1_1 Execute_AC_10 48_2_1 Execute_AC_10 48_3_1 diff --git a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_11_i.sh b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_11_i.sh index e2cb567d185..0356cd0b594 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_11_i.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_11_i.sh @@ -17,11 +17,11 @@ function Execute_AC_11_I() { Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_ac_11_i \ - -RealEncryption=1 -rs=23 -argstest sink_preset $1 source_preset $2 + -RealEncryption=1 -rs=23 -D=2 -argstest sink_preset $1 source_preset $2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast \ - -RealEncryption=1 -rs=46 + -RealEncryption=1 -rs=46 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ @@ -46,5 +46,5 @@ Execute_AC_11_I 48_1_1 48_1_1 Execute_AC_11_I 48_2_1 48_2_1 Execute_AC_11_I 48_3_1 48_3_1 Execute_AC_11_I 48_4_1 48_4_1 -# Execute_AC_11_I 48_5_1 48_5_1 # ASSERTION FAIL [c_latency <= cig->c_latency] +Execute_AC_11_I 48_5_1 48_5_1 Execute_AC_11_I 48_6_1 48_6_1 diff --git a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_11_ii.sh b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_11_ii.sh index a1f194d92b4..c83bdc8c4be 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_11_ii.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_11_ii.sh @@ -17,15 +17,15 @@ function Execute_AC_11_II() { Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_ac_11_ii \ - -RealEncryption=1 -rs=23 -argstest sink_preset $1 source_preset $2 + -RealEncryption=1 -rs=23 -D=3 -argstest sink_preset $1 source_preset $2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast \ - -RealEncryption=1 -rs=46 + -RealEncryption=1 -rs=46 -D=3 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=2 -testid=cap_acceptor_unicast \ - -RealEncryption=1 -rs=69 + -RealEncryption=1 -rs=69 -D=3 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ @@ -50,5 +50,5 @@ Execute_AC_11_II 48_1_1 48_1_1 Execute_AC_11_II 48_2_1 48_2_1 Execute_AC_11_II 48_3_1 48_3_1 Execute_AC_11_II 48_4_1 48_4_1 -# Execute_AC_11_II 48_5_1 48_5_1 # Controller assert: ASSERTION FAIL [c_latency <= cig->c_latency] +Execute_AC_11_II 48_5_1 48_5_1 Execute_AC_11_II 48_6_1 48_6_1 diff --git a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_2.sh b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_2.sh index cb6b9e8d427..76a9b762fd1 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_2.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_2.sh @@ -18,11 +18,11 @@ function Execute_AC_2() { Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_ac_2 \ - -RealEncryption=1 -rs=23 -argstest source_preset $1 + -RealEncryption=1 -rs=23 -D=2 -argstest source_preset $1 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast \ - -RealEncryption=1 -rs=46 + -RealEncryption=1 -rs=46 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ @@ -41,8 +41,8 @@ Execute_AC_2 24_1_1 Execute_AC_2 24_2_1 Execute_AC_2 32_1_1 Execute_AC_2 32_2_1 -# Execute_AC_2 441_1_1 # ASSERTION FAIL [iso_interval_us >= cig->c_sdu_interval] -# Execute_AC_2 441_2_1 # ASSERTION FAIL [iso_interval_us >= cig->c_sdu_interval] +Execute_AC_2 441_1_1 +Execute_AC_2 441_2_1 Execute_AC_2 48_1_1 Execute_AC_2 48_2_1 Execute_AC_2 48_3_1 diff --git a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_3.sh b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_3.sh index 9c303b768e6..e4682d10197 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_3.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_3.sh @@ -18,11 +18,11 @@ function Execute_AC_3() { Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_ac_3 \ - -RealEncryption=1 -rs=23 -argstest sink_preset $1 source_preset $2 + -RealEncryption=1 -rs=23 -D=2 -argstest sink_preset $1 source_preset $2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast \ - -RealEncryption=1 -rs=46 + -RealEncryption=1 -rs=46 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ @@ -41,8 +41,8 @@ Execute_AC_3 24_1_1 24_1_1 Execute_AC_3 24_2_1 24_2_1 Execute_AC_3 32_1_1 32_1_1 Execute_AC_3 32_2_1 32_2_1 -# Execute_AC_3 441_1_1 441_1_1 # ASSERTION FAIL [iso_interval_us >= cig->c_sdu_interval] -# Execute_AC_3 441_2_1 441_2_1 # ASSERTION FAIL [iso_interval_us >= cig->c_sdu_interval] +Execute_AC_3 441_1_1 441_1_1 +Execute_AC_3 441_2_1 441_2_1 Execute_AC_3 48_1_1 48_1_1 Execute_AC_3 48_2_1 48_2_1 Execute_AC_3 48_3_1 48_3_1 diff --git a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_4.sh b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_4.sh index 85ab40eaae0..a863b359252 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_4.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_4.sh @@ -17,11 +17,11 @@ function Execute_AC_4() { Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_ac_4 \ - -RealEncryption=1 -rs=23 -argstest sink_preset $1 + -RealEncryption=1 -rs=23 -D=2 -argstest sink_preset $1 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast \ - -RealEncryption=1 -rs=46 + -RealEncryption=1 -rs=46 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ @@ -38,8 +38,8 @@ Execute_AC_4 24_1_1 Execute_AC_4 24_2_1 Execute_AC_4 32_1_1 Execute_AC_4 32_2_1 -# Execute_AC_4 441_1_1 # ASSERTION FAIL [iso_interval_us >= cig->c_sdu_interval] -# Execute_AC_4 441_2_1 # ASSERTION FAIL [iso_interval_us >= cig->c_sdu_interval] +Execute_AC_4 441_1_1 +Execute_AC_4 441_2_1 Execute_AC_4 48_1_1 Execute_AC_4 48_2_1 Execute_AC_4 48_3_1 diff --git a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_5.sh b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_5.sh index bc3cfbffa7f..5eb9f6f5e30 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_5.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_5.sh @@ -18,11 +18,11 @@ function Execute_AC_5() { Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_ac_5 \ - -RealEncryption=1 -rs=23 -argstest sink_preset $1 source_preset $2 + -RealEncryption=1 -rs=23 -D=2 -argstest sink_preset $1 source_preset $2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast \ - -RealEncryption=1 -rs=46 + -RealEncryption=1 -rs=46 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ @@ -46,4 +46,4 @@ Execute_AC_5 48_2_1 48_2_1 Execute_AC_5 48_3_1 48_3_1 Execute_AC_5 48_4_1 48_4_1 Execute_AC_5 48_5_1 48_5_1 -# Execute_AC_5 48_6_1 48_6_1 # ASSERTION FAIL [c_latency <= cig->c_latency] +Execute_AC_5 48_6_1 48_6_1 diff --git a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_6_i.sh b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_6_i.sh index 3e34f75be16..7a848655619 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_6_i.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_6_i.sh @@ -17,11 +17,11 @@ function Execute_AC_6_I() { Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_ac_6_i \ - -RealEncryption=1 -rs=23 -argstest sink_preset $1 + -RealEncryption=1 -rs=23 -D=2 -argstest sink_preset $1 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast \ - -RealEncryption=1 -rs=46 + -RealEncryption=1 -rs=46 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_6_ii.sh b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_6_ii.sh index e354dd45287..bb3a4dca003 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_6_ii.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_6_ii.sh @@ -17,15 +17,15 @@ function Execute_AC_6_II() { Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_ac_6_ii \ - -RealEncryption=1 -rs=23 -argstest sink_preset $1 + -RealEncryption=1 -rs=23 -D=3 -argstest sink_preset $1 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast \ - -RealEncryption=1 -rs=46 + -RealEncryption=1 -rs=46 -D=3 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=2 -testid=cap_acceptor_unicast \ - -RealEncryption=1 -rs=69 + -RealEncryption=1 -rs=69 -D=3 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_7_i.sh b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_7_i.sh index bf5a9174aa0..279322562ed 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_7_i.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_7_i.sh @@ -17,11 +17,11 @@ function Execute_AC_7_I() { Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_ac_7_i \ - -RealEncryption=1 -rs=23 -argstest sink_preset $1 source_preset $2 + -RealEncryption=1 -rs=23 -D=2 -argstest sink_preset $1 source_preset $2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast \ - -RealEncryption=1 -rs=46 + -RealEncryption=1 -rs=46 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ @@ -40,8 +40,8 @@ Execute_AC_7_I 24_1_1 24_1_1 Execute_AC_7_I 24_2_1 24_2_1 Execute_AC_7_I 32_1_1 32_1_1 Execute_AC_7_I 32_2_1 32_2_1 -# Execute_AC_7_I 441_1_1 441_1_1 # ASSERTION FAIL [iso_interval_us >= cig->c_sdu_interval] -# Execute_AC_7_I 441_2_1 441_2_1 # ASSERTION FAIL [iso_interval_us >= cig->c_sdu_interval] +Execute_AC_7_I 441_1_1 441_1_1 +Execute_AC_7_I 441_2_1 441_2_1 Execute_AC_7_I 48_1_1 48_1_1 Execute_AC_7_I 48_2_1 48_2_1 Execute_AC_7_I 48_3_1 48_3_1 diff --git a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_7_ii.sh b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_7_ii.sh index 1dd957f86dc..bea1ee05173 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_7_ii.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_7_ii.sh @@ -17,15 +17,15 @@ function Execute_AC_7_II() { Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_ac_7_ii \ - -RealEncryption=1 -rs=23 -argstest sink_preset $1 source_preset $2 + -RealEncryption=1 -rs=23 -D=3 -argstest sink_preset $1 source_preset $2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast \ - -RealEncryption=1 -rs=46 + -RealEncryption=1 -rs=46 -D=3 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=2 -testid=cap_acceptor_unicast \ - -RealEncryption=1 -rs=69 + -RealEncryption=1 -rs=69 -D=3 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_8_i.sh b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_8_i.sh index 00955fd8063..420e08646f4 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_8_i.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_8_i.sh @@ -17,11 +17,11 @@ function Execute_AC_8_I() { Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_ac_8_i \ - -RealEncryption=1 -rs=23 -argstest sink_preset $1 source_preset $2 + -RealEncryption=1 -rs=23 -D=2 -argstest sink_preset $1 source_preset $2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast \ - -RealEncryption=1 -rs=46 + -RealEncryption=1 -rs=46 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_8_ii.sh b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_8_ii.sh index 1539bd0ceac..5de94703d69 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_8_ii.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_8_ii.sh @@ -17,15 +17,15 @@ function Execute_AC_8_II() { Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_ac_8_ii \ - -RealEncryption=1 -rs=23 -argstest sink_preset $1 source_preset $2 + -RealEncryption=1 -rs=23 -D=3 -argstest sink_preset $1 source_preset $2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast \ - -RealEncryption=1 -rs=46 + -RealEncryption=1 -rs=46 -D=3 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=2 -testid=cap_acceptor_unicast \ - -RealEncryption=1 -rs=69 + -RealEncryption=1 -rs=69 -D=3 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_9_i.sh b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_9_i.sh index b6097a88b58..75dc048593f 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_9_i.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_9_i.sh @@ -17,11 +17,11 @@ function Execute_AC_9_I() { Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_ac_9_i \ - -RealEncryption=1 -rs=23 -argstest source_preset $1 + -RealEncryption=1 -rs=23 -D=2 -argstest source_preset $1 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast \ - -RealEncryption=1 -rs=46 + -RealEncryption=1 -rs=46 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_9_ii.sh b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_9_ii.sh index 5f17668a626..75a02a1e38b 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_9_ii.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_ac_9_ii.sh @@ -17,15 +17,15 @@ function Execute_AC_9_II() { Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_ac_9_ii \ - -RealEncryption=1 -rs=23 -argstest source_preset $1 + -RealEncryption=1 -rs=23 -D=3 -argstest source_preset $1 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast \ - -RealEncryption=1 -rs=46 + -RealEncryption=1 -rs=46 -D=3 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=2 -testid=cap_acceptor_unicast \ - -RealEncryption=1 -rs=69 + -RealEncryption=1 -rs=69 -D=3 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_inval.sh b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_inval.sh index c868f738d7b..6869821f35b 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_inval.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_inval.sh @@ -15,10 +15,10 @@ cd ${BSIM_OUT_PATH}/bin printf "\n\n======== Running CAP unicast test =========\n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_unicast_inval -rs=46 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_unicast_inval -rs=46 -D=2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast -rs=23 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast -rs=23 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_timeout.sh b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_timeout.sh index 8b806d40959..65b088e9805 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_timeout.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/cap_unicast_timeout.sh @@ -15,10 +15,10 @@ cd ${BSIM_OUT_PATH}/bin printf "\n\n======== Running CAP unicast timeout test =========\n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_unicast_timeout -rs=46 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_initiator_unicast_timeout -rs=46 -D=2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast_timeout -rs=23 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=cap_acceptor_unicast_timeout -rs=23 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/csip.sh b/tests/bsim/bluetooth/audio/test_scripts/csip.sh index 03cf05a14d3..82f929a9779 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/csip.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/csip.sh @@ -18,19 +18,19 @@ SIMULATION_ID="csip" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=csip_set_coordinator \ - -RealEncryption=1 -rs=1 + -RealEncryption=1 -rs=1 -D=4 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=csip_set_member \ - -RealEncryption=1 -rs=2 -argstest rank 1 + -RealEncryption=1 -rs=2 -D=4 -argstest rank 1 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=2 -testid=csip_set_member \ - -RealEncryption=1 -rs=3 -argstest rank 2 + -RealEncryption=1 -rs=3 -D=4 -argstest rank 2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=3 -testid=csip_set_member \ - -RealEncryption=1 -rs=4 -argstest rank 3 + -RealEncryption=1 -rs=4 -D=4 -argstest rank 3 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/csip_encrypted_sirk.sh b/tests/bsim/bluetooth/audio/test_scripts/csip_encrypted_sirk.sh index 939234a4beb..96b5c511913 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/csip_encrypted_sirk.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/csip_encrypted_sirk.sh @@ -18,19 +18,19 @@ SIMULATION_ID="csip_sirk_encrypted" printf "\n\n======== Running test with SIRK encrypted ========\n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=csip_set_coordinator \ - -RealEncryption=1 -rs=1 + -RealEncryption=1 -rs=1 -D=4 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=csip_set_member_enc \ - -RealEncryption=1 -rs=2 -argstest rank 1 + -RealEncryption=1 -rs=2 -D=4 -argstest rank 1 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=2 -testid=csip_set_member_enc \ - -RealEncryption=1 -rs=3 -argstest rank 2 + -RealEncryption=1 -rs=3 -D=4 -argstest rank 2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=3 -testid=csip_set_member_enc \ - -RealEncryption=1 -rs=4 -argstest rank 3 + -RealEncryption=1 -rs=4 -D=4 -argstest rank 3 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/csip_forced_release.sh b/tests/bsim/bluetooth/audio/test_scripts/csip_forced_release.sh index 917fbc590d0..93f945027cf 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/csip_forced_release.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/csip_forced_release.sh @@ -18,19 +18,19 @@ SIMULATION_ID="csip_forced_release" printf "\n\n======== Running test with forced release of lock ========\n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=csip_set_coordinator \ - -RealEncryption=1 -rs=1 + -RealEncryption=1 -rs=1 -D=4 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=csip_set_member \ - -RealEncryption=1 -rs=2 -argstest rank 1 + -RealEncryption=1 -rs=2 -D=4 -argstest rank 1 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=2 -testid=csip_set_member \ - -RealEncryption=1 -rs=3 -argstest rank 2 + -RealEncryption=1 -rs=3 -D=4 -argstest rank 2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=3 -testid=csip_set_member_release \ - -RealEncryption=1 -rs=4 -argstest rank 3 + -RealEncryption=1 -rs=4 -D=4 -argstest rank 3 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/csip_no_lock.sh b/tests/bsim/bluetooth/audio/test_scripts/csip_no_lock.sh index 70f54844865..22484600c85 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/csip_no_lock.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/csip_no_lock.sh @@ -17,19 +17,19 @@ SIMULATION_ID="csip_no_lock" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=csip_set_coordinator \ - -RealEncryption=1 -rs=1 -argstest no-lock + -RealEncryption=1 -rs=1 -D=4 -argstest no-lock Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=csip_set_member \ - -RealEncryption=1 -rs=2 -argstest rank 1 not-lockable + -RealEncryption=1 -rs=2 -D=4 -argstest rank 1 not-lockable Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=2 -testid=csip_set_member \ - -RealEncryption=1 -rs=3 -argstest rank 2 not-lockable + -RealEncryption=1 -rs=3 -D=4 -argstest rank 2 not-lockable Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=3 -testid=csip_set_member \ - -RealEncryption=1 -rs=4 -argstest rank 3 not-lockable + -RealEncryption=1 -rs=4 -D=4 -argstest rank 3 not-lockable # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/csip_no_rank.sh b/tests/bsim/bluetooth/audio/test_scripts/csip_no_rank.sh index ab6d09ce116..5eebc7759ec 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/csip_no_rank.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/csip_no_rank.sh @@ -17,19 +17,19 @@ SIMULATION_ID="csip_no_rank" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=csip_set_coordinator \ - -RealEncryption=1 -rs=1 -argstest no-rank no-lock + -RealEncryption=1 -rs=1 -D=4 -argstest no-rank no-lock Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=csip_set_member \ - -RealEncryption=1 -rs=2 -argstest rank 0 not-lockable + -RealEncryption=1 -rs=2 -D=4 -argstest rank 0 not-lockable Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=2 -testid=csip_set_member \ - -RealEncryption=1 -rs=3 -argstest rank 0 not-lockable + -RealEncryption=1 -rs=3 -D=4 -argstest rank 0 not-lockable Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=3 -testid=csip_set_member \ - -RealEncryption=1 -rs=4 -argstest rank 0 not-lockable + -RealEncryption=1 -rs=4 -D=4 -argstest rank 0 not-lockable # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/csip_no_size.sh b/tests/bsim/bluetooth/audio/test_scripts/csip_no_size.sh index dfd10200d8d..c586fde9205 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/csip_no_size.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/csip_no_size.sh @@ -17,19 +17,19 @@ SIMULATION_ID="csip_no_size" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=csip_set_coordinator \ - -RealEncryption=1 -rs=1 -argstest no-size + -RealEncryption=1 -rs=1 -D=4 -argstest no-size Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=csip_set_member \ - -RealEncryption=1 -rs=2 -argstest rank 1 size 0 + -RealEncryption=1 -rs=2 -D=4 -argstest rank 1 size 0 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=2 -testid=csip_set_member \ - -RealEncryption=1 -rs=3 -argstest rank 2 size 0 + -RealEncryption=1 -rs=3 -D=4 -argstest rank 2 size 0 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=3 -testid=csip_set_member \ - -RealEncryption=1 -rs=4 -argstest rank 3s size 0 + -RealEncryption=1 -rs=4 -D=4 -argstest rank 3s size 0 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/csip_notify.sh b/tests/bsim/bluetooth/audio/test_scripts/csip_notify.sh new file mode 100755 index 00000000000..ceaf984d037 --- /dev/null +++ b/tests/bsim/bluetooth/audio/test_scripts/csip_notify.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2023 Demant A/S +# +# SPDX-License-Identifier: Apache-2.0 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +SIMULATION_ID="csip_notify" +VERBOSITY_LEVEL=2 +EXECUTE_TIMEOUT=200 + +cd ${BSIM_OUT_PATH}/bin + +printf "\n\n======== Running CSIP Notify test =========\n\n" + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=csip_notify_server -rs=24 -D=2 + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=csip_notify_client -rs=46 -D=2 + +Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ + -D=2 -sim_length=60e6 $@ + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/audio/test_scripts/has.sh b/tests/bsim/bluetooth/audio/test_scripts/has.sh index e2bface0396..3d7f6508fd0 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/has.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/has.sh @@ -15,10 +15,10 @@ cd ${BSIM_OUT_PATH}/bin printf "\n\n======== Running HAS main (API) test =========\n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=has -rs=24 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=has -rs=24 -D=2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=has_client -rs=46 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=has_client -rs=46 -D=2 Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ -D=2 -sim_length=60e6 $@ diff --git a/tests/bsim/bluetooth/audio/test_scripts/has_offline.sh b/tests/bsim/bluetooth/audio/test_scripts/has_offline.sh new file mode 100755 index 00000000000..7e5b0a40d7a --- /dev/null +++ b/tests/bsim/bluetooth/audio/test_scripts/has_offline.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2023 Codecoup +# +# SPDX-License-Identifier: Apache-2.0 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +SIMULATION_ID="has_offline_behavior" +VERBOSITY_LEVEL=2 +EXECUTE_TIMEOUT=20 + +cd ${BSIM_OUT_PATH}/bin + +printf "\n\n Running Preset Changed Offline Behavior test \n\n" + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=has_offline_behavior -rs=24 -D=2 + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=has_client_offline_behavior -rs=46 -D=2 + +Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ + -D=2 -sim_length=60e6 $@ + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/audio/test_scripts/ias.sh b/tests/bsim/bluetooth/audio/test_scripts/ias.sh index 3547d6996e8..cf3afed69ed 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/ias.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/ias.sh @@ -15,10 +15,10 @@ cd ${BSIM_OUT_PATH}/bin printf "\n\n======== Running IAS main (API) test =========\n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=ias -rs=23 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=ias -rs=23 -D=2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=ias_client -rs=6 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=ias_client -rs=6 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/mcs_mcc.sh b/tests/bsim/bluetooth/audio/test_scripts/mcs_mcc.sh index 1e31932efe7..4857a5cad05 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/mcs_mcc.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/mcs_mcc.sh @@ -15,10 +15,10 @@ cd ${BSIM_OUT_PATH}/bin printf "\n\n======== Running MCS and MCC test =========\n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=mcc -rs=46 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=mcc -rs=46 -D=2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=mcs -rs=23 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=mcs -rs=23 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/media_controller.sh b/tests/bsim/bluetooth/audio/test_scripts/media_controller.sh index ab036d39497..3e504f7275e 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/media_controller.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/media_controller.sh @@ -15,7 +15,7 @@ cd ${BSIM_OUT_PATH}/bin printf "\n\n======== Running media controller local_player test =========\n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=media_controller_local_player -rs=23 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=media_controller_local_player -rs=23 -D=1 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ @@ -26,10 +26,10 @@ wait_for_background_jobs printf "\n\n======== Running media controller remote_player test =========\n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=media_controller_remote_player -rs=46 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=media_controller_remote_player -rs=46 -D=2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=media_controller_server -rs=23 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=media_controller_server -rs=23 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/micp.sh b/tests/bsim/bluetooth/audio/test_scripts/micp.sh index 3117f665116..56bc0ac4650 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/micp.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/micp.sh @@ -15,7 +15,7 @@ cd ${BSIM_OUT_PATH}/bin printf "\n\n==== Running MICP Microphone Device Only (API) test ====n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=micp_mic_dev_only -rs=23 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=micp_mic_dev_only -rs=23 -D=1 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ @@ -26,10 +26,10 @@ wait_for_background_jobs printf "\n\n==== Running MICP Microphone Device and MICP Microphone Controller test ====n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=micp_mic_dev -rs=23 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=micp_mic_dev -rs=23 -D=2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=micp_mic_ctlr -rs=46 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=micp_mic_ctlr -rs=46 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/pacs_notify.sh b/tests/bsim/bluetooth/audio/test_scripts/pacs_notify.sh index 5e29bf2b005..721a794cbd3 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/pacs_notify.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/pacs_notify.sh @@ -15,10 +15,10 @@ cd ${BSIM_OUT_PATH}/bin printf "\n\n======== Running PACS Notify test =========\n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=pacs_notify_server -rs=24 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=pacs_notify_server -rs=24 -D=2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=pacs_notify_client -rs=46 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=pacs_notify_client -rs=46 -D=2 Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ -D=2 -sim_length=60e6 $@ diff --git a/tests/bsim/bluetooth/audio/test_scripts/tbs.sh b/tests/bsim/bluetooth/audio/test_scripts/tbs.sh index 894376434aa..491443a60aa 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/tbs.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/tbs.sh @@ -16,7 +16,7 @@ cd ${BSIM_OUT_PATH}/bin printf "\n\n==== Running TBS Server Only (API) test ====n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=tbs_test_server_only -rs=23 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=tbs_test_server_only -rs=23 -D=1 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ @@ -27,10 +27,10 @@ wait_for_background_jobs printf "\n\n==== Running TBS server & client tests ====n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=tbs -rs=23 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=tbs -rs=23 -D=2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=tbs_client -rs=6 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=tbs_client -rs=6 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/tmap.sh b/tests/bsim/bluetooth/audio/test_scripts/tmap.sh index 38da32d6f34..069d4b463bb 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/tmap.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/tmap.sh @@ -15,10 +15,10 @@ cd ${BSIM_OUT_PATH}/bin printf "\n\n======== Running TMAP client & server test =========\n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=tmap_client -rs=24 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=tmap_client -rs=24 -D=2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=tmap_server -rs=23 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=tmap_server -rs=23 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio/test_scripts/vcp.sh b/tests/bsim/bluetooth/audio/test_scripts/vcp.sh index 0be421894ba..8d394c225b6 100755 --- a/tests/bsim/bluetooth/audio/test_scripts/vcp.sh +++ b/tests/bsim/bluetooth/audio/test_scripts/vcp.sh @@ -15,7 +15,7 @@ cd ${BSIM_OUT_PATH}/bin printf "\n\n======== Running VCP Volume Renderer standalone (API) test =========\n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=vcp_vol_rend_standalone -rs=23 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=vcp_vol_rend_standalone -rs=23 -D=1 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ @@ -26,10 +26,10 @@ wait_for_background_jobs printf "\n\n======== Running VCP Volume Renderer and VCP Volume Controller test =========\n\n" Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=vcp_vol_rend -rs=23 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=vcp_vol_rend -rs=23 -D=2 Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ - -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=vcp_vol_ctlr -rs=46 + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=vcp_vol_ctlr -rs=46 -D=2 # Simulation time should be larger than the WAIT_TIME in common.h Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ diff --git a/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/CMakeLists.txt b/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/CMakeLists.txt new file mode 100644 index 00000000000..8a2c3e86803 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/CMakeLists.txt @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(broadcast_audio_sink_self_tets) + +set(broadcast_audio_sink_path ${ZEPHYR_BASE}/samples/bluetooth/broadcast_audio_sink) + +target_sources(app PRIVATE + ${broadcast_audio_sink_path}/src/main.c +) + +target_sources(app PRIVATE + src/broadcast_audio_sink_test.c + src/test_main.c +) + +zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) + +zephyr_include_directories( + ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ + ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ + ) diff --git a/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/Kconfig b/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/Kconfig new file mode 100644 index 00000000000..fadad0e4456 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/Kconfig @@ -0,0 +1,4 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "${ZEPHYR_BASE}/samples/bluetooth/broadcast_audio_sink/Kconfig" diff --git a/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/Kconfig.sysbuild b/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/Kconfig.sysbuild new file mode 100644 index 00000000000..6ef6bede28d --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "${ZEPHYR_BASE}/samples/bluetooth/broadcast_audio_sink/Kconfig.sysbuild" + +config NATIVE_SIMULATOR_PRIMARY_MCU_INDEX + int + # Let's pass the test arguments to the application MCU test + # otherwise by default they would have gone to the net core. + default 0 if $(BOARD) = "nrf5340bsim_nrf5340_cpuapp" diff --git a/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/prj.conf b/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/prj.conf new file mode 100644 index 00000000000..36e53c8cabe --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/prj.conf @@ -0,0 +1,2 @@ +# Please build using the sample configuration file: +# ${ZEPHYR_BASE}/samples/bluetooth/broadcast_audio_sink/prj.conf diff --git a/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/src/broadcast_audio_sink_test.c b/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/src/broadcast_audio_sink_test.c new file mode 100644 index 00000000000..dc23f131125 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/src/broadcast_audio_sink_test.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * Copyright (c) 2017-2019 Oticon A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_types.h" +#include "bs_tracing.h" +#include "bs_utils.h" +#include "time_machine.h" +#include "bstests.h" + +#define WAIT_TIME 10 /* Seconds */ + +#define PASS_THRESHOLD 100 /* Audio packets */ + +extern enum bst_result_t bst_result; + +#define FAIL(...) \ + do { \ + bst_result = Failed; \ + bs_trace_error_time_line(__VA_ARGS__); \ + } while (0) + +#define PASS(...) \ + do { \ + bst_result = Passed; \ + bs_trace_info_time(1, __VA_ARGS__); \ + } while (0) + +static void test_broadcast_sink_sample_init(void) +{ + /* We set an absolute deadline in 30 seconds */ + bst_ticker_set_next_tick_absolute(WAIT_TIME*1e6); + bst_result = In_progress; +} + +static void test_broadcast_sink_sample_tick(bs_time_t HW_device_time) +{ + /* + * If in WAIT_TIME seconds we did not get enough packets through + * we consider the test failed + */ + + extern uint64_t total_rx_iso_packet_count; + + bs_trace_info_time(2, "%"PRIu64" packets received, expected >= %i\n", + total_rx_iso_packet_count, PASS_THRESHOLD); + + if (total_rx_iso_packet_count >= PASS_THRESHOLD) { + PASS("broadcast_sink PASSED\n"); + bs_trace_exit("Done, disconnecting from simulation\n"); + } else { + FAIL("broadcast_sink FAILED (Did not pass after %i seconds)\n", + WAIT_TIME); + } +} + +static const struct bst_test_instance test_sample[] = { + { + .test_id = "broadcast_audio_sink", + .test_descr = "Test based on the broadcast audio sink sample. " + "It expects to be connected to a compatible broadcast audio source, " + "waits for " STR(WAIT_TIME) " seconds, and checks how " + "many ISO packets have been received correctly", + .test_post_init_f = test_broadcast_sink_sample_init, + .test_tick_f = test_broadcast_sink_sample_tick, + }, + BSTEST_END_MARKER +}; + +struct bst_test_list *test_broadcast_sink_test_install(struct bst_test_list *tests) +{ + tests = bst_add_tests(tests, test_sample); + return tests; +} diff --git a/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/src/test_main.c b/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/src/test_main.c new file mode 100644 index 00000000000..cd9df72aaae --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/src/test_main.c @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bstests.h" + +extern struct bst_test_list *test_broadcast_sink_test_install(struct bst_test_list *tests); + +bst_test_install_t test_installers[] = { + test_broadcast_sink_test_install, + NULL +}; diff --git a/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/sysbuild.cmake b/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/sysbuild.cmake new file mode 100644 index 00000000000..2bf2920a476 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/sysbuild.cmake @@ -0,0 +1,6 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +include(${ZEPHYR_BASE}/samples/bluetooth/broadcast_audio_sink/sysbuild.cmake) + +native_simulator_set_primary_mcu_index(${DEFAULT_IMAGE} ${NET_APP}) diff --git a/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/tests_scripts/broadcast_audio.sh b/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/tests_scripts/broadcast_audio.sh new file mode 100755 index 00000000000..64e6ac4aa9f --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/broadcast_audio_sink/tests_scripts/broadcast_audio.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Simple selfchecking test for the broadcast audio sink/source samples, +# It relies on the bs_tests hooks to register a test timer callback, which after a deadline +# will check how many audio packets the broadcast audio sink has received, and if over a threshold +# it considers the test passed + +simulation_id="broadcast_audio_samples_test" +verbosity_level=2 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +EXECUTE_TIMEOUT=100 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_${BOARD}_samples_bluetooth_broadcast_audio_source_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -RealEncryption=1 + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_samples_broadcast_audio_sink_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -RealEncryption=1 \ + -testid=broadcast_audio_sink + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=20e6 $@ + +wait_for_background_jobs #Wait for all programs in background and return != 0 if any fails diff --git a/tests/bsim/bluetooth/audio_samples/compile.sh b/tests/bsim/bluetooth/audio_samples/compile.sh new file mode 100755 index 00000000000..79b1a212c6e --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/compile.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Compile all the applications needed by the bsim tests in these subfolders + +#set -x #uncomment this line for debugging +set -ue + +: "${BSIM_COMPONENTS_PATH:?BSIM_COMPONENTS_PATH must be defined}" +: "${ZEPHYR_BASE:?ZEPHYR_BASE must be set to point to the zephyr root\ + directory}" + +WORK_DIR="${WORK_DIR:-${ZEPHYR_BASE}/bsim_out}" + +BOARD_ROOT="${BOARD_ROOT:-${ZEPHYR_BASE}}" + +mkdir -p ${WORK_DIR} + +source ${ZEPHYR_BASE}/tests/bsim/compile.source + +if [ "${BOARD}" == "nrf5340bsim_nrf5340_cpuapp" ]; then + app=samples/bluetooth/unicast_audio_server sysbuild=1 compile + app=samples/bluetooth/broadcast_audio_source sysbuild=1 compile + app=tests/bsim/bluetooth/audio_samples/unicast_audio_client sysbuild=1 compile + app=tests/bsim/bluetooth/audio_samples/broadcast_audio_sink sysbuild=1 \ + conf_file=${ZEPHYR_BASE}/samples/bluetooth/broadcast_audio_sink/prj.conf \ + exe_name=bs_${BOARD}_${app}_prj_conf sysbuild=1 compile +else + app=samples/bluetooth/unicast_audio_server conf_overlay=overlay-bt_ll_sw_split.conf \ + exe_name=bs_${BOARD}_${app}_prj_conf sysbuild=1 compile + app=samples/bluetooth/broadcast_audio_source conf_overlay=overlay-bt_ll_sw_split.conf \ + exe_name=bs_${BOARD}_${app}_prj_conf sysbuild=1 compile + app=tests/bsim/bluetooth/audio_samples/unicast_audio_client \ + conf_overlay=${ZEPHYR_BASE}/samples/bluetooth/unicast_audio_client/overlay-bt_ll_sw_split.conf \ + exe_name=bs_${BOARD}_${app}_prj_conf sysbuild=1 compile + app=tests/bsim/bluetooth/audio_samples/broadcast_audio_sink \ + conf_file=${ZEPHYR_BASE}/samples/bluetooth/broadcast_audio_sink/prj.conf \ + conf_overlay=${ZEPHYR_BASE}/samples/bluetooth/broadcast_audio_sink/overlay-bt_ll_sw_split.conf \ + exe_name=bs_${BOARD}_${app}_prj_conf sysbuild=1 compile +fi + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/audio_samples/unicast_audio_client/CMakeLists.txt b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/CMakeLists.txt new file mode 100644 index 00000000000..1afb5029b33 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/CMakeLists.txt @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(unicast_audio_client_self_tets) + +set(unicast_client_path ${ZEPHYR_BASE}/samples/bluetooth/unicast_audio_client) + +target_sources(app PRIVATE + ${unicast_client_path}/src/main.c +) + +target_sources(app PRIVATE + src/unicast_client_sample_test.c + src/test_main.c +) + +zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) + +zephyr_include_directories( + ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ + ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ + ) diff --git a/tests/bsim/bluetooth/audio_samples/unicast_audio_client/Kconfig.sysbuild b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/Kconfig.sysbuild new file mode 100644 index 00000000000..4e7f66926c2 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "${ZEPHYR_BASE}/samples/bluetooth/unicast_audio_client/Kconfig.sysbuild" + +config NATIVE_SIMULATOR_PRIMARY_MCU_INDEX + int + # Let's pass the test arguments to the application MCU test + # otherwise by default they would have gone to the net core. + default 0 if $(BOARD) = "nrf5340bsim_nrf5340_cpuapp" diff --git a/tests/bsim/bluetooth/audio_samples/unicast_audio_client/boards/nrf52_bsim.conf b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/boards/nrf52_bsim.conf new file mode 100644 index 00000000000..e8c8629ce62 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/boards/nrf52_bsim.conf @@ -0,0 +1,5 @@ +# This file content is just a copy of the equivalent one in the unicast client sample + +# For LC3 the following configs are needed +CONFIG_FPU=y +CONFIG_LIBLC3=y diff --git a/tests/bsim/bluetooth/audio_samples/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpuapp.conf b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpuapp.conf new file mode 100644 index 00000000000..f1624acbc19 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpuapp.conf @@ -0,0 +1,12 @@ +# This file content is just a copy of the equivalent one in the unicast client sample + +# For LC3 the following configs are needed +CONFIG_FPU=y +CONFIG_LIBLC3=y + +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +CONFIG_BT_TINYCRYPT_ECC=y diff --git a/tests/bsim/bluetooth/audio_samples/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpunet.conf b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpunet.conf new file mode 100644 index 00000000000..e8c8629ce62 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpunet.conf @@ -0,0 +1,5 @@ +# This file content is just a copy of the equivalent one in the unicast client sample + +# For LC3 the following configs are needed +CONFIG_FPU=y +CONFIG_LIBLC3=y diff --git a/tests/bsim/bluetooth/audio_samples/unicast_audio_client/prj.conf b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/prj.conf new file mode 100644 index 00000000000..c7385ae8cda --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/prj.conf @@ -0,0 +1,16 @@ +# This file content is just a copy of the unicast client sample prj.conf + +CONFIG_BT=y +CONFIG_LOG=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_AUDIO=y +CONFIG_BT_BAP_UNICAST_CLIENT=y +CONFIG_BT_ISO_TX_BUF_COUNT=4 +# Support an ISO channel per ASE +CONFIG_BT_ISO_MAX_CHAN=4 +CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT=4 +CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT=2 +CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT=2 +CONFIG_BT_KEYS_OVERWRITE_OLDEST=y + +CONFIG_BT_EXT_ADV=y diff --git a/tests/bsim/bluetooth/audio_samples/unicast_audio_client/src/test_main.c b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/src/test_main.c new file mode 100644 index 00000000000..dbba2106b19 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/src/test_main.c @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bstests.h" + +extern struct bst_test_list *test_unicast_client_sample_install(struct bst_test_list *tests); + +bst_test_install_t test_installers[] = { + test_unicast_client_sample_install, + NULL +}; diff --git a/tests/bsim/bluetooth/audio_samples/unicast_audio_client/src/unicast_client_sample_test.c b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/src/unicast_client_sample_test.c new file mode 100644 index 00000000000..729e4267b7c --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/src/unicast_client_sample_test.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * Copyright (c) 2017-2019 Oticon A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_types.h" +#include "bs_tracing.h" +#include "bs_utils.h" +#include "time_machine.h" +#include "bstests.h" + +#define WAIT_TIME 10 /* Seconds */ + +#define PASS_THRESHOLD 100 /* Audio packets */ + +extern enum bst_result_t bst_result; + +#define FAIL(...) \ + do { \ + bst_result = Failed; \ + bs_trace_error_time_line(__VA_ARGS__); \ + } while (0) + +#define PASS(...) \ + do { \ + bst_result = Passed; \ + bs_trace_info_time(1, __VA_ARGS__); \ + } while (0) + +static void test_unicast_client_sample_init(void) +{ + /* We set an absolute deadline in 30 seconds */ + bst_ticker_set_next_tick_absolute(WAIT_TIME*1e6); + bst_result = In_progress; +} + +static void test_unicast_client_sample_tick(bs_time_t HW_device_time) +{ + /* + * If in WAIT_TIME seconds we did not get enough packets through + * we consider the test failed + */ + + extern uint64_t unicast_audio_recv_ctr; + + bs_trace_info_time(2, "%"PRIu64" packets received, expected >= %i\n", + unicast_audio_recv_ctr, PASS_THRESHOLD); + + if (unicast_audio_recv_ctr >= PASS_THRESHOLD) { + PASS("unicast_client PASSED\n"); + bs_trace_exit("Done, disconnecting from simulation\n"); + } else { + FAIL("unicast_client FAILED (Did not pass after %i seconds)\n", + WAIT_TIME); + } +} + +static const struct bst_test_instance test_sample[] = { + { + .test_id = "unicast_client", + .test_descr = "Test based on the unicast client sample. " + "It expects to be connected to a compatible unicast server, " + "waits for " STR(WAIT_TIME) " seconds, and checks how " + "many audio packets have been received correctly", + .test_post_init_f = test_unicast_client_sample_init, + .test_tick_f = test_unicast_client_sample_tick, + }, + BSTEST_END_MARKER +}; + +struct bst_test_list *test_unicast_client_sample_install(struct bst_test_list *tests) +{ + tests = bst_add_tests(tests, test_sample); + return tests; +} diff --git a/tests/bsim/bluetooth/audio_samples/unicast_audio_client/sysbuild.cmake b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/sysbuild.cmake new file mode 100644 index 00000000000..85b85b7cb63 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/sysbuild.cmake @@ -0,0 +1,6 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +include(${ZEPHYR_BASE}/samples/bluetooth/unicast_audio_client/sysbuild.cmake) + +native_simulator_set_primary_mcu_index(${DEFAULT_IMAGE} ${NET_APP}) diff --git a/tests/bsim/bluetooth/audio_samples/unicast_audio_client/tests_scripts/unicast_client.sh b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/tests_scripts/unicast_client.sh new file mode 100755 index 00000000000..cc92cda1328 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/tests_scripts/unicast_client.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Simple selfchecking test for the unicast client/server samples, +# It relies on the bs_tests hooks to register a test timer callback, which after a deadline +# will check how many audio packets the unicast client has received, and if over a threshold +# it considers the test passed + +simulation_id="unicast_samples_test" +verbosity_level=2 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +EXECUTE_TIMEOUT=100 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_${BOARD}_samples_bluetooth_unicast_audio_server_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -RealEncryption=1 + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_samples_unicast_audio_client_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -RealEncryption=1 \ + -testid=unicast_client + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=20e6 $@ + +wait_for_background_jobs #Wait for all programs in background and return != 0 if any fails diff --git a/tests/bsim/bluetooth/compile.nrf5340bsim_nrf5340_cpuapp.sh b/tests/bsim/bluetooth/compile.nrf5340bsim_nrf5340_cpuapp.sh new file mode 100755 index 00000000000..65769185867 --- /dev/null +++ b/tests/bsim/bluetooth/compile.nrf5340bsim_nrf5340_cpuapp.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# Copyright 2018 Oticon A/S +# SPDX-License-Identifier: Apache-2.0 + +# Compile all bluetooth applications needed for the split stack tests + +#set -x #uncomment this line for debugging +set -ue +: "${BSIM_COMPONENTS_PATH:?BSIM_COMPONENTS_PATH must be defined}" +: "${ZEPHYR_BASE:?ZEPHYR_BASE must be set to point to the zephyr root\ + directory}" + +WORK_DIR="${WORK_DIR:-${ZEPHYR_BASE}/bsim_out}" + +BOARD_ROOT="${BOARD_ROOT:-${ZEPHYR_BASE}}" +BOARD="${BOARD:-nrf5340bsim_nrf5340_cpuapp}" + +mkdir -p ${WORK_DIR} + +source ${ZEPHYR_BASE}/tests/bsim/compile.source + +app=tests/bsim/bluetooth/ll/conn conf_file=prj_split_privacy.conf sysbuild=1 compile +app=tests/bsim/bluetooth/ll/bis sysbuild=1 compile +app=tests/bsim/bluetooth/ll/cis conf_overlay=overlay-acl_group.conf sysbuild=1 compile + +run_in_background ${ZEPHYR_BASE}/tests/bsim/bluetooth/audio_samples/compile.sh + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/compile.nrf5340bsim_nrf5340_cpunet.sh b/tests/bsim/bluetooth/compile.nrf5340bsim_nrf5340_cpunet.sh new file mode 100755 index 00000000000..e8d78683b2e --- /dev/null +++ b/tests/bsim/bluetooth/compile.nrf5340bsim_nrf5340_cpunet.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# Copyright 2018 Oticon A/S +# SPDX-License-Identifier: Apache-2.0 + +# Compile all the applications needed by the Bluetooth bsim tests on the nrf5340_cpunet + +#set -x #uncomment this line for debugging +set -ue +: "${BSIM_COMPONENTS_PATH:?BSIM_COMPONENTS_PATH must be defined}" +: "${ZEPHYR_BASE:?ZEPHYR_BASE must be set to point to the zephyr root\ + directory}" + +WORK_DIR="${WORK_DIR:-${ZEPHYR_BASE}/bsim_out}" + +BOARD_ROOT="${BOARD_ROOT:-${ZEPHYR_BASE}}" + +mkdir -p ${WORK_DIR} + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +${ZEPHYR_BASE}/tests/bsim/bluetooth/ll/compile.sh + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/compile.sh b/tests/bsim/bluetooth/compile.sh index df5c85489c3..b6b709f84d2 100755 --- a/tests/bsim/bluetooth/compile.sh +++ b/tests/bsim/bluetooth/compile.sh @@ -18,9 +18,15 @@ mkdir -p ${WORK_DIR} source ${ZEPHYR_BASE}/tests/bsim/sh_common.source +# Note: We do not parallelize the call into the build of the host, ll and mesh images as those +# are already building many images in parallel in themselves, and otherwise we would be +# launching too many parallel builds which can lead to a too high system load. +# On the other hand the audio compile script, only builds one image. So we parallelize it with +# the rest to save a couple of seconds. run_in_background ${ZEPHYR_BASE}/tests/bsim/bluetooth/audio/compile.sh -run_in_background ${ZEPHYR_BASE}/tests/bsim/bluetooth/host/compile.sh -run_in_background ${ZEPHYR_BASE}/tests/bsim/bluetooth/ll/compile.sh -run_in_background ${ZEPHYR_BASE}/tests/bsim/bluetooth/mesh/compile.sh +${ZEPHYR_BASE}/tests/bsim/bluetooth/audio_samples/compile.sh +${ZEPHYR_BASE}/tests/bsim/bluetooth/host/compile.sh +${ZEPHYR_BASE}/tests/bsim/bluetooth/ll/compile.sh +${ZEPHYR_BASE}/tests/bsim/bluetooth/mesh/compile.sh wait_for_background_jobs diff --git a/tests/bsim/bluetooth/host/adv/resume/src/bs_bt_utils.h b/tests/bsim/bluetooth/host/adv/resume/src/bs_bt_utils.h index 90a77be66e3..a28a046800e 100644 --- a/tests/bsim/bluetooth/host/adv/resume/src/bs_bt_utils.h +++ b/tests/bsim/bluetooth/host/adv/resume/src/bs_bt_utils.h @@ -10,7 +10,7 @@ #include "bs_types.h" #include "bstests.h" #include "time_machine.h" -#include "zephyr/sys/__assert.h" +#include #include diff --git a/tests/bsim/bluetooth/host/adv/resume/src/dut.c b/tests/bsim/bluetooth/host/adv/resume/src/dut.c index 4a58e9f5cad..40e4612b04d 100644 --- a/tests/bsim/bluetooth/host/adv/resume/src/dut.c +++ b/tests/bsim/bluetooth/host/adv/resume/src/dut.c @@ -5,10 +5,10 @@ */ #include "bs_bt_utils.h" -#include "zephyr/bluetooth/addr.h" -#include "zephyr/bluetooth/bluetooth.h" -#include "zephyr/bluetooth/conn.h" -#include "zephyr/toolchain/gcc.h" +#include +#include +#include +#include #include #include diff --git a/tests/bsim/bluetooth/host/adv/resume/src/tester.c b/tests/bsim/bluetooth/host/adv/resume/src/tester.c index 3c6bae7f4a7..9cb5854f260 100644 --- a/tests/bsim/bluetooth/host/adv/resume/src/tester.c +++ b/tests/bsim/bluetooth/host/adv/resume/src/tester.c @@ -5,8 +5,8 @@ */ #include "bs_bt_utils.h" -#include "zephyr/bluetooth/addr.h" -#include "zephyr/bluetooth/conn.h" +#include +#include #include diff --git a/tests/bsim/bluetooth/host/att/long_read/CMakeLists.txt b/tests/bsim/bluetooth/host/att/long_read/CMakeLists.txt new file mode 100644 index 00000000000..0f6727fd5a4 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/long_read/CMakeLists.txt @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) +project(app) + +add_subdirectory(${ZEPHYR_BASE}/tests/bluetooth/common/testlib testlib) + +target_sources(app PRIVATE + bs_main.c + bs_sync.c + main.c +) + +zephyr_include_directories( + ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ + ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ +) + +target_link_libraries(app PRIVATE + testlib +) diff --git a/tests/bsim/bluetooth/host/att/long_read/_build.sh b/tests/bsim/bluetooth/host/att/long_read/_build.sh new file mode 100755 index 00000000000..637512b3826 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/long_read/_build.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +set -eu +dotslash="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" +bin_dir="${BSIM_OUT_PATH}/bin" +BOARD="${BOARD:-nrf52_bsim}" + +cd "${dotslash}" + +compile_path="${bin_dir}/bs_${BOARD}_" +compile_path+="$(realpath --relative-to "$(west topdir)"/zephyr prj.conf | tr /. _)" + +west build -b nrf52_bsim +cp -v build/zephyr/zephyr.exe "${compile_path}" diff --git a/tests/bsim/bluetooth/host/att/long_read/bs_macro.h b/tests/bsim/bluetooth/host/att/long_read/bs_macro.h new file mode 100644 index 00000000000..b9e52beea6c --- /dev/null +++ b/tests/bsim/bluetooth/host/att/long_read/bs_macro.h @@ -0,0 +1,23 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#define PASS(...) \ + do { \ + extern enum bst_result_t bst_result; \ + bst_result = Passed; \ + bs_trace_info_time(1, __VA_ARGS__); \ + } while (0) + +static inline void bt_testlib_expect_zero(int err, char *where_file, int where_line) +{ + if (err) { + bs_trace_print(BS_TRACE_ERROR, where_file, where_line, 0, BS_TRACE_AUTOTIME, 0, + "err %d\n", err); + } +} + +#define EXPECT_ZERO(expr) bt_testlib_expect_zero((expr), __FILE__, __LINE__) diff --git a/tests/bsim/bluetooth/host/att/long_read/bs_main.c b/tests/bsim/bluetooth/host/att/long_read/bs_main.c new file mode 100644 index 00000000000..26985a8d415 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/long_read/bs_main.c @@ -0,0 +1,31 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +void the_test(void); + +static const struct bst_test_instance test_to_add[] = { + { + .test_id = "the_test", + .test_main_f = the_test, + }, + BSTEST_END_MARKER, +}; + +static struct bst_test_list *install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, test_to_add); +}; + +bst_test_install_t test_installers[] = {install, NULL}; + +int main(void) +{ + bst_main(); + + return 0; +} diff --git a/tests/bsim/bluetooth/host/att/long_read/bs_sync.c b/tests/bsim/bluetooth/host/att/long_read/bs_sync.c new file mode 100644 index 00000000000..c7c432c74b7 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/long_read/bs_sync.c @@ -0,0 +1,107 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +LOG_MODULE_REGISTER(bs_sync, LOG_LEVEL_INF); + +static int n_devs; + +static void register_more_cmd_args(void) +{ + static bs_args_struct_t args_struct_toadd[] = { + { + .option = "D", + .name = "number_devices", + .type = 'i', + .dest = (void *)&n_devs, + .descript = "Number of devices which will connect in this phy", + .is_mandatory = true, + }, + ARG_TABLE_ENDMARKER, + }; + + bs_add_extra_dynargs(args_struct_toadd); +} +NATIVE_TASK(register_more_cmd_args, PRE_BOOT_1, 100); + +static uint *backchannels; +static void setup_backchannels(void) +{ + __ASSERT_NO_MSG(n_devs > 0); + uint self = get_device_nbr(); + uint device_nbrs[n_devs]; + uint channel_numbers[n_devs]; + + for (int i = 0; i < n_devs; i++) { + device_nbrs[i] = i; + channel_numbers[i] = 0; + } + + backchannels = + bs_open_back_channel(self, device_nbrs, channel_numbers, ARRAY_SIZE(device_nbrs)); + __ASSERT_NO_MSG(backchannels != NULL); +} +NATIVE_TASK(setup_backchannels, PRE_BOOT_3, 100); + +void bs_bc_receive_msg_sync(uint ch, size_t size, uint8_t *data) +{ + while (bs_bc_is_msg_received(ch) < size) { + k_msleep(1); + } + bs_bc_receive_msg(ch, data, size); +} + +void bs_bc_send_uint(uint ch, uint64_t data) +{ + uint8_t data_bytes[sizeof(data)]; + + sys_put_le64(data, data_bytes); + bs_bc_send_msg(ch, data_bytes, sizeof(data_bytes)); +} + +uint64_t bs_bc_recv_uint(uint ch) +{ + uint8_t data[sizeof(uint64_t)]; + + bs_bc_receive_msg_sync(ch, sizeof(data), data); + return sys_get_le64(data); +} + +void bt_testlib_bs_sync_all(void) +{ + static uint64_t counter; + + LOG_DBG("%llu d%u enter", counter, get_device_nbr()); + + /* Device 0 acts as hub. */ + if (get_device_nbr() == 0) { + for (int i = 1; i < n_devs; i++) { + uint64_t counter_cfm; + + counter_cfm = bs_bc_recv_uint(backchannels[i]); + __ASSERT(counter_cfm == counter, "%luu %luu", counter_cfm, counter); + } + for (int i = 1; i < n_devs; i++) { + bs_bc_send_uint(backchannels[i], counter); + } + } else { + uint64_t counter_cfm; + + bs_bc_send_uint(backchannels[0], counter); + counter_cfm = bs_bc_recv_uint(backchannels[0]); + __ASSERT(counter_cfm == counter, "%luu %luu", counter_cfm, counter); + } + + LOG_DBG("%llu d%u exit", counter, get_device_nbr()); + + counter++; +} diff --git a/tests/bsim/bluetooth/host/att/long_read/bs_sync.h b/tests/bsim/bluetooth/host/att/long_read/bs_sync.h new file mode 100644 index 00000000000..f69336cb1c2 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/long_read/bs_sync.h @@ -0,0 +1,5 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +void bt_testlib_bs_sync_all(void); diff --git a/tests/bsim/bluetooth/host/att/long_read/main.c b/tests/bsim/bluetooth/host/att/long_read/main.c new file mode 100644 index 00000000000..29a3de0a9e6 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/long_read/main.c @@ -0,0 +1,232 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "testlib/adv.h" +#include "testlib/att_read.h" +#include "testlib/att_write.h" +#include "bs_macro.h" +#include "bs_sync.h" +#include "testlib/conn_ref.h" +#include "testlib/conn_wait.h" +#include "testlib/connect.h" +#include "testlib/log_utils.h" +#include "testlib/scan.h" +#include "testlib/security.h" + +/* This test uses system asserts to fail tests. */ +BUILD_ASSERT(__ASSERT_ON); + +#define CENTRAL_DEVICE_NBR 0 +#define PERIPHERAL_DEVICE_NBR 1 + +LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG); + +#define UUID_1 \ + BT_UUID_DECLARE_128(0xdb, 0x1f, 0xe2, 0x52, 0xf3, 0xc6, 0x43, 0x66, 0xb3, 0x92, 0x5d, \ + 0xc6, 0xe7, 0xc9, 0x59, 0x9d) + +#define UUID_2 \ + BT_UUID_DECLARE_128(0x3f, 0xa4, 0x7f, 0x44, 0x2e, 0x2a, 0x43, 0x05, 0xab, 0x38, 0x07, \ + 0x8d, 0x16, 0xbf, 0x99, 0xf1) + +static ssize_t read_mtu_validation_chrc(struct bt_conn *conn, const struct bt_gatt_attr *attr, + void *buf, uint16_t buf_len, uint16_t offset) +{ + ssize_t read_len; + + LOG_INF("Server side buf_len %u", buf_len); + + /* Note: We assume `buf_len` is equal to the usable payload + * capacity of the response PDU. I.e. `(ATT_MTU - 1)` for + * BT_ATT_OP_READ_RSP and BT_ATT_OP_READ_BLOB_RSP. + */ + + /* Send back a full PDU on the first read (on offset 0). Then an + * not full one for the second read to conlude the long read.. + */ + read_len = buf_len; + if (offset > 0) { + __ASSERT_NO_MSG(read_len > 0); + /* The second PDU is one-less-than-full to test for off + * by one errors. + */ + read_len -= 1; + } + + /* If the ATT_MTU is too large, sending a one-less-than-full + * response would exeed the max attribute length limit. + */ + __ASSERT(buf_len < (BT_ATT_MAX_ATTRIBUTE_LEN / 2), + "The EATT buffer is too large for this test."); + + /* Ensure the padding bytes (that are not overwritten later in + * this function) are initialized. + */ + memset(buf, 0, read_len); + + /* Echo back the requested read size in the first two bytes of + * each read. + */ + __ASSERT_NO_MSG(read_len >= 2); + sys_put_le16(read_len, buf); + + return read_len; +} + +static struct bt_gatt_attr attrs[] = { + BT_GATT_PRIMARY_SERVICE(UUID_1), + BT_GATT_CHARACTERISTIC(UUID_2, BT_GATT_CHRC_READ, BT_GATT_PERM_READ, + read_mtu_validation_chrc, NULL, NULL), +}; + +static struct bt_gatt_service svc = { + .attrs = attrs, + .attr_count = ARRAY_SIZE(attrs), +}; + +static void find_the_chrc(struct bt_conn *conn, uint16_t *chrc_value_handle) +{ + uint16_t svc_handle; + uint16_t svc_end_handle; + uint16_t chrc_end_handle; + + EXPECT_ZERO(bt_testlib_gatt_discover_primary(&svc_handle, &svc_end_handle, conn, UUID_1, 1, + 0xffff)); + + LOG_INF("svc_handle: %u, svc_end_handle: %u", svc_handle, svc_end_handle); + + EXPECT_ZERO(bt_testlib_gatt_discover_characteristic(chrc_value_handle, &chrc_end_handle, + NULL, conn, UUID_2, (svc_handle + 1), + svc_end_handle)); + + LOG_INF("chrc_value_handle: %u, chrc_end_handle: %u", *chrc_value_handle, chrc_end_handle); +} + +static void bs_sync_all_log(char *log_msg) +{ + /* Everyone meets here. */ + bt_testlib_bs_sync_all(); + + if (get_device_nbr() == 0) { + LOG_WRN("Sync point: %s", log_msg); + } + + /* Everyone waits for d0 to finish logging. */ + bt_testlib_bs_sync_all(); +} + +static inline void bt_enable_quiet(void) +{ + bt_testlib_log_level_set("bt_hci_core", LOG_LEVEL_ERR); + bt_testlib_log_level_set("bt_id", LOG_LEVEL_ERR); + + EXPECT_ZERO(bt_enable(NULL)); + + bt_testlib_log_level_set("bt_hci_core", LOG_LEVEL_INF); + bt_testlib_log_level_set("bt_id", LOG_LEVEL_INF); +} + +static void test_long_read(enum bt_att_chan_opt bearer, uint16_t chrc_value_handle, + struct bt_conn *conn) +{ + bool central = (get_device_nbr() == CENTRAL_DEVICE_NBR); + + if (central) { + size_t read_count; + + NET_BUF_SIMPLE_DEFINE(attr_value_buf, BT_ATT_MAX_ATTRIBUTE_LEN); + + /* Perform the whole long read operation. */ + EXPECT_ZERO(bt_testlib_gatt_long_read(&attr_value_buf, NULL, conn, bearer, + chrc_value_handle, 0)); + + /* Parse the read attribute value to verify the + * integrity of the transfer. + * + * Each response starts with the length of the whole + * response and the rest is zero-padded. + */ + for (read_count = 0; attr_value_buf.len; read_count++) { + uint16_t encoded_len; + uint16_t padding_size; + + LOG_INF("Verifying read %u", read_count); + + __ASSERT(attr_value_buf.len >= sizeof(encoded_len), + "Incomplete encoded length"); + encoded_len = net_buf_simple_pull_le16(&attr_value_buf); + + padding_size = (encoded_len - sizeof(uint16_t)); + LOG_INF("Padding size %u", padding_size); + + /* Check and discard padding. */ + for (uint16_t i = 0; i < padding_size; i++) { + __ASSERT(attr_value_buf.len, "Unexpected end of buffer"); + __ASSERT(net_buf_simple_pull_u8(&attr_value_buf) == 0, + "Expected a padding byte at %u", i); + } + } + LOG_INF("Verified %u reads", read_count); + __ASSERT(read_count > 1, "Expected at least two reads"); + } +} + +void the_test(void) +{ + bool central = (get_device_nbr() == CENTRAL_DEVICE_NBR); + bool peripheral = (get_device_nbr() == PERIPHERAL_DEVICE_NBR); + bt_addr_le_t adva; + struct bt_conn *conn = NULL; + uint16_t chrc_value_handle = 0; + + if (peripheral) { + EXPECT_ZERO(bt_gatt_service_register(&svc)); + } + + bt_enable_quiet(); + + if (peripheral) { + EXPECT_ZERO(bt_set_name("peripheral")); + EXPECT_ZERO(bt_testlib_adv_conn( + &conn, BT_ID_DEFAULT, + (BT_LE_ADV_OPT_USE_NAME | BT_LE_ADV_OPT_FORCE_NAME_IN_AD))); + } + + if (central) { + EXPECT_ZERO(bt_testlib_scan_find_name(&adva, "peripheral")); + EXPECT_ZERO(bt_testlib_connect(&adva, &conn)); + + /* Establish EATT bearers. */ + EXPECT_ZERO(bt_testlib_secure(conn, BT_SECURITY_L2)); + + while (bt_eatt_count(conn) == 0) { + k_msleep(100); + }; + } + + bs_sync_all_log("Connected"); + + /* Perform discovery. */ + if (central) { + find_the_chrc(conn, &chrc_value_handle); + } + + bs_sync_all_log("Testing UATT"); + test_long_read(BT_ATT_CHAN_OPT_UNENHANCED_ONLY, chrc_value_handle, conn); + + bs_sync_all_log("Testing EATT"); + test_long_read(BT_ATT_CHAN_OPT_ENHANCED_ONLY, chrc_value_handle, conn); + + bs_sync_all_log("Test Complete"); + + PASS("Test complete\n"); +} diff --git a/tests/bsim/bluetooth/host/att/long_read/prj.conf b/tests/bsim/bluetooth/host/att/long_read/prj.conf new file mode 100644 index 00000000000..1e5e8dc8b41 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/long_read/prj.conf @@ -0,0 +1,26 @@ +CONFIG_ASSERT=y +CONFIG_BOOT_BANNER=n +CONFIG_BT_BUF_ACL_RX_SIZE=204 +CONFIG_BT_CENTRAL=y +CONFIG_BT_DEVICE_NAME_DYNAMIC=y +CONFIG_BT_EATT=y +CONFIG_BT_EXT_ADV=y +CONFIG_BT_GATT_CLIENT=y +CONFIG_BT_GATT_DYNAMIC_DB=y +CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y +CONFIG_BT_L2CAP_ECRED=y +CONFIG_BT_L2CAP_TX_MTU=200 +CONFIG_BT_MAX_CONN=3 +CONFIG_BT_MAX_PAIRED=2 +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_PRIVACY=n +CONFIG_BT_SMP=y +CONFIG_BT_TESTING=y +CONFIG_BT=y +CONFIG_FLASH_MAP=y +CONFIG_FLASH_PAGE_LAYOUT=y +CONFIG_FLASH=y +CONFIG_LOG_BACKEND_FORMAT_TIMESTAMP=n +CONFIG_LOG_RUNTIME_FILTERING=y +CONFIG_LOG_TAG_MAX_LEN=20 +CONFIG_LOG=y diff --git a/tests/bsim/bluetooth/host/att/long_read/run.sh b/tests/bsim/bluetooth/host/att/long_read/run.sh new file mode 100755 index 00000000000..b1b7a5c6eb0 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/long_read/run.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +set -eu +dotslash="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" +bin_dir="${BSIM_OUT_PATH}/bin" +BOARD="${BOARD:-nrf52_bsim}" + +cd "${dotslash}" + +compile_path="${bin_dir}/bs_${BOARD}_" +compile_path+="$(realpath --relative-to "$(west topdir)"/zephyr prj.conf | tr /. _)" + +args_all=(-s=long_read -D=2) +args_dev=(-v=2 -RealEncryption=1 -testid=the_test) +sim_seconds=60 + +echo "Simulation time: $sim_seconds seconds" + +# bs_2G4_phy_v1 requires pwd to at its location +cd "${BSIM_OUT_PATH}/bin" + +("${compile_path}" "${args_all[@]}" "${args_dev[@]}" -d=0 || echo d0 $?) & +("${compile_path}" "${args_all[@]}" "${args_dev[@]}" -d=1 || echo d1 $?) & +(./bs_2G4_phy_v1 "${args_all[@]}" -v=6 -sim_length=$((sim_seconds * 10 ** 6)) || echo phy $?) & + +wait diff --git a/tests/bsim/bluetooth/host/att/retry_on_sec_err/client/CMakeLists.txt b/tests/bsim/bluetooth/host/att/retry_on_sec_err/client/CMakeLists.txt new file mode 100644 index 00000000000..b244078e761 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/retry_on_sec_err/client/CMakeLists.txt @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) +project(app) + +add_subdirectory(${ZEPHYR_BASE}/tests/bluetooth/common/testlib testlib) + +target_sources(app PRIVATE + ../test_utils.c + main.c +) + +zephyr_include_directories( + ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ + ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ +) + +target_link_libraries(app PRIVATE + testlib +) diff --git a/tests/bsim/bluetooth/host/att/retry_on_sec_err/client/main.c b/tests/bsim/bluetooth/host/att/retry_on_sec_err/client/main.c new file mode 100644 index 00000000000..2a3c005515c --- /dev/null +++ b/tests/bsim/bluetooth/host/att/retry_on_sec_err/client/main.c @@ -0,0 +1,195 @@ +/* Copyright (c) 2023 Codecoup + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "../common_defs.h" +#include "../test_utils.h" + +#include "testlib/connect.h" +#include "testlib/scan.h" +#include "testlib/security.h" + +LOG_MODULE_REGISTER(client, LOG_LEVEL_DBG); + +DEFINE_FLAG(flag_attr_read_success); + +static uint8_t gatt_attr_read_cb(struct bt_conn *conn, uint8_t att_err, + struct bt_gatt_read_params *params, const void *data, uint16_t len) +{ + __ASSERT_NO_MSG(!att_err); + + SET_FLAG(flag_attr_read_success); + + return BT_GATT_ITER_STOP; +} + +static void gatt_attr_read(struct bt_conn *conn) +{ + static struct bt_gatt_read_params params; + static struct bt_uuid_128 uuid; + int err; + + memset(¶ms, 0, sizeof(params)); + params.func = gatt_attr_read_cb; + params.by_uuid.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE; + params.by_uuid.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; + memcpy(&uuid.uuid, TEST_CHRC_UUID, sizeof(uuid)); + params.by_uuid.uuid = &uuid.uuid; + + err = bt_gatt_read(conn, ¶ms); + __ASSERT_NO_MSG(!err); +} + +DEFINE_FLAG(flag_conn_encrypted); + +static void security_changed_cb(struct bt_conn *conn, bt_security_t level, + enum bt_security_err err) +{ + if (err != BT_SECURITY_ERR_SUCCESS || level < BT_SECURITY_L2) { + return; + } + + SET_FLAG(flag_conn_encrypted); +} + +static struct bt_conn_cb conn_cb = { + .security_changed = security_changed_cb, +}; + +static void test_client(void) +{ + struct bt_conn *conn = NULL; + bt_addr_le_t scan_result; + int err; + + err = bt_enable(NULL); + __ASSERT_NO_MSG(!err); + + bt_conn_cb_register(&conn_cb); + + err = bt_testlib_scan_find_name(&scan_result, "d1"); + __ASSERT_NO_MSG(!err); + + err = bt_testlib_connect(&scan_result, &conn); + __ASSERT_NO_MSG(!err); + + /* Read characteristic value that requires encryption */ + gatt_attr_read(conn); + + /* Expect link encryption */ + WAIT_FOR_FLAG(flag_conn_encrypted); + + /* Wait for successful Read Response */ + WAIT_FOR_FLAG(flag_attr_read_success); + + err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + __ASSERT_NO_MSG(!err); + + bt_conn_unref(conn); + conn = NULL; + + PASS("PASS\n"); +} + +DEFINE_FLAG(flag_pairing_in_progress); + +static void auth_cancel_cb(struct bt_conn *conn) +{ + +} + +static void auth_pairing_confirm_cb(struct bt_conn *conn) +{ + SET_FLAG(flag_pairing_in_progress); +} + +static struct bt_conn_auth_cb auth_cb = { + .cancel = auth_cancel_cb, + .pairing_confirm = auth_pairing_confirm_cb, +}; + +static void test_client_security_request(void) +{ + struct bt_conn *conn = NULL; + bt_addr_le_t scan_result; + int err; + + err = bt_enable(NULL); + __ASSERT_NO_MSG(!err); + + bt_conn_cb_register(&conn_cb); + + err = bt_conn_auth_cb_register(&auth_cb); + __ASSERT_NO_MSG(!err); + + err = bt_testlib_scan_find_name(&scan_result, "d1"); + __ASSERT_NO_MSG(!err); + + err = bt_testlib_connect(&scan_result, &conn); + __ASSERT_NO_MSG(!err); + + /* Wait for peripheral to initaiate pairing */ + WAIT_FOR_FLAG(flag_pairing_in_progress); + + /* Read characteristic value that requires encryption */ + gatt_attr_read(conn); + + /* Accept pairing */ + err = bt_conn_auth_pairing_confirm(conn); + __ASSERT_NO_MSG(!err); + + /* Expect link encryption */ + WAIT_FOR_FLAG(flag_conn_encrypted); + + /* Wait for successful Read Response */ + WAIT_FOR_FLAG(flag_attr_read_success); + + err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + __ASSERT_NO_MSG(!err); + + bt_conn_unref(conn); + conn = NULL; + + PASS("PASS\n"); +} + +static const struct bst_test_instance client_tests[] = { + { + .test_id = "test_client", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_client, + }, + { + .test_id = "test_client_security_request", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_client_security_request, + }, + BSTEST_END_MARKER, +}; + +static struct bst_test_list *client_tests_install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, client_tests); +}; + +bst_test_install_t test_installers[] = { + client_tests_install, + NULL +}; + +int main(void) +{ + bst_main(); + + return 0; +} diff --git a/tests/bsim/bluetooth/host/att/retry_on_sec_err/client/prj.conf b/tests/bsim/bluetooth/host/att/retry_on_sec_err/client/prj.conf new file mode 100644 index 00000000000..32e911d4396 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/retry_on_sec_err/client/prj.conf @@ -0,0 +1,12 @@ +CONFIG_ASSERT=y + +CONFIG_BT=y +CONFIG_BT_CENTRAL=y + +CONFIG_BT_SMP=y + +CONFIG_BT_GATT_CLIENT=y +CONFIG_BT_ATT_RETRY_ON_SEC_ERR=y + +CONFIG_LOG=y +CONFIG_BT_ATT_LOG_LEVEL_DBG=y diff --git a/tests/bsim/bluetooth/host/att/retry_on_sec_err/common_defs.h b/tests/bsim/bluetooth/host/att/retry_on_sec_err/common_defs.h new file mode 100644 index 00000000000..7f9a091203b --- /dev/null +++ b/tests/bsim/bluetooth/host/att/retry_on_sec_err/common_defs.h @@ -0,0 +1,12 @@ +/* Copyright (c) 2023 Codecoup + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#define TEST_SERVICE_UUID \ + BT_UUID_DECLARE_128(0x1f, 0x5c, 0x31, 0x85, 0x05, 0xe8, 0x4d, 0x58, 0xb9, 0xf5, 0xae, \ + 0xf1, 0x7a, 0x88, 0xbe, 0x82) +#define TEST_CHRC_UUID \ + BT_UUID_DECLARE_128(0x68, 0xb4, 0x35, 0x19, 0x01, 0x65, 0x4d, 0xdc, 0xb9, 0xf3, 0x91, \ + 0x0f, 0xf3, 0x18, 0x46, 0x7b) diff --git a/tests/bsim/bluetooth/host/att/retry_on_sec_err/server/CMakeLists.txt b/tests/bsim/bluetooth/host/att/retry_on_sec_err/server/CMakeLists.txt new file mode 100644 index 00000000000..b244078e761 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/retry_on_sec_err/server/CMakeLists.txt @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) +project(app) + +add_subdirectory(${ZEPHYR_BASE}/tests/bluetooth/common/testlib testlib) + +target_sources(app PRIVATE + ../test_utils.c + main.c +) + +zephyr_include_directories( + ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ + ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ +) + +target_link_libraries(app PRIVATE + testlib +) diff --git a/tests/bsim/bluetooth/host/att/retry_on_sec_err/server/main.c b/tests/bsim/bluetooth/host/att/retry_on_sec_err/server/main.c new file mode 100644 index 00000000000..b07f0034aab --- /dev/null +++ b/tests/bsim/bluetooth/host/att/retry_on_sec_err/server/main.c @@ -0,0 +1,98 @@ +/* Copyright (c) 2023 Codecoup + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include + +#include "testlib/adv.h" +#include "testlib/security.h" + +#include "../common_defs.h" +#include "../test_utils.h" + +LOG_MODULE_REGISTER(server, LOG_LEVEL_DBG); + +static ssize_t read_chrc(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, + uint16_t buf_len, uint16_t offset) +{ + return 0; +} + +BT_GATT_SERVICE_DEFINE(test_svc, + BT_GATT_PRIMARY_SERVICE(TEST_SERVICE_UUID), + BT_GATT_CHARACTERISTIC(TEST_CHRC_UUID, BT_GATT_CHRC_READ, + BT_GATT_PERM_READ_ENCRYPT, read_chrc, NULL, NULL)); + +static void test_common(struct bt_conn **conn) +{ + int err; + + err = bt_enable(NULL); + __ASSERT_NO_MSG(!err); + + __ASSERT_NO_MSG(get_device_nbr() == 1); + err = bt_set_name("d1"); + __ASSERT_NO_MSG(!err); + + err = bt_testlib_adv_conn(conn, BT_ID_DEFAULT, + (BT_LE_ADV_OPT_USE_NAME | BT_LE_ADV_OPT_FORCE_NAME_IN_AD)); + __ASSERT_NO_MSG(!err); +} + +static void test_server(void) +{ + test_common(NULL); + + PASS("PASS\n"); +} + +static void test_server_security_request(void) +{ + struct bt_conn *conn = NULL; + int err; + + test_common(&conn); + + err = bt_testlib_secure(conn, BT_SECURITY_L2); + __ASSERT(!err, "err %d", err); + + PASS("PASS\n"); +} + +static const struct bst_test_instance server_tests[] = { + { + .test_id = "test_server", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_server, + }, + { + .test_id = "test_server_security_request", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_server_security_request, + }, + BSTEST_END_MARKER, +}; + +static struct bst_test_list *server_tests_install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, server_tests); +}; + +bst_test_install_t test_installers[] = { + server_tests_install, + NULL +}; + +int main(void) +{ + bst_main(); + + return 0; +} diff --git a/tests/bsim/bluetooth/host/att/retry_on_sec_err/server/prj.conf b/tests/bsim/bluetooth/host/att/retry_on_sec_err/server/prj.conf new file mode 100644 index 00000000000..1b3a186979e --- /dev/null +++ b/tests/bsim/bluetooth/host/att/retry_on_sec_err/server/prj.conf @@ -0,0 +1,13 @@ +CONFIG_ASSERT=y + +CONFIG_BT=y +CONFIG_BT_PERIPHERAL=y + +CONFIG_BT_DEVICE_NAME_DYNAMIC=y + +CONFIG_BT_SMP=y + +CONFIG_BT_EXT_ADV=y + +CONFIG_LOG=y +CONFIG_BT_ATT_LOG_LEVEL_DBG=y diff --git a/tests/bsim/bluetooth/host/att/retry_on_sec_err/test_scripts/_compile.sh b/tests/bsim/bluetooth/host/att/retry_on_sec_err/test_scripts/_compile.sh new file mode 100755 index 00000000000..88a5454b674 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/retry_on_sec_err/test_scripts/_compile.sh @@ -0,0 +1,18 @@ +#!/bin/env bash +# Copyright 2023 Codecoup +# SPDX-License-Identifier: Apache-2.0 + +set -eu +bash_source_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" + +source "${bash_source_dir}/_env.sh" + +pushd client +west build -b nrf52_bsim && \ + cp -v build/zephyr/zephyr.exe "${test_exe_d0}" +popd + +pushd server +west build -b nrf52_bsim && \ + cp -v build/zephyr/zephyr.exe "${test_exe_d1}" +popd diff --git a/tests/bsim/bluetooth/host/att/retry_on_sec_err/test_scripts/_env.sh b/tests/bsim/bluetooth/host/att/retry_on_sec_err/test_scripts/_env.sh new file mode 100755 index 00000000000..66b074ca3d8 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/retry_on_sec_err/test_scripts/_env.sh @@ -0,0 +1,15 @@ +#!/bin/env bash +# Copyright 2023 Codecoup +# SPDX-License-Identifier: Apache-2.0 + +set -eu +bash_source_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" + +: "${BSIM_OUT_PATH:?BSIM_OUT_PATH must be defined}" + +test_name="$(basename "$(realpath "$bash_source_dir/..")")" +bsim_bin="${BSIM_OUT_PATH}/bin" +verbosity_level=2 +BOARD="${BOARD:-nrf52_bsim}" +test_exe_d0="${bsim_bin}/bs_${BOARD}_tests_bsim_bluetooth_host_att_${test_name}_client_prj_conf" +test_exe_d1="${bsim_bin}/bs_${BOARD}_tests_bsim_bluetooth_host_att_${test_name}_server_prj_conf" diff --git a/tests/bsim/bluetooth/host/att/retry_on_sec_err/test_scripts/run_test.sh b/tests/bsim/bluetooth/host/att/retry_on_sec_err/test_scripts/run_test.sh new file mode 100755 index 00000000000..8ea8f38cddc --- /dev/null +++ b/tests/bsim/bluetooth/host/att/retry_on_sec_err/test_scripts/run_test.sh @@ -0,0 +1,27 @@ +#!/bin/env bash +# Copyright 2023 Codecoup +# SPDX-License-Identifier: Apache-2.0 + +set -eu +bash_source_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" + +simulation_id=$(basename "$0") +source "${bash_source_dir}/_env.sh" +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +cd ${BSIM_OUT_PATH}/bin + +printf "\n\n===== ATT retry on security error (auto security elevation) ======\n\n" + +Execute "$test_exe_d0" \ + -v=${verbosity_level} -s="${simulation_id}" -d=0 -testid=test_client \ + -RealEncryption=1 + +Execute "$test_exe_d1" \ + -v=${verbosity_level} -s="${simulation_id}" -d=1 -testid=test_server \ + -RealEncryption=1 + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s="${simulation_id}" \ + -D=2 -sim_length=60e6 $@ + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/host/att/retry_on_sec_err/test_scripts/run_test_security_request.sh b/tests/bsim/bluetooth/host/att/retry_on_sec_err/test_scripts/run_test_security_request.sh new file mode 100755 index 00000000000..8d7c86c4d04 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/retry_on_sec_err/test_scripts/run_test_security_request.sh @@ -0,0 +1,27 @@ +#!/bin/env bash +# Copyright 2023 Codecoup +# SPDX-License-Identifier: Apache-2.0 + +set -eu +bash_source_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" + +simulation_id=$(basename "$0") +source "${bash_source_dir}/_env.sh" +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +cd ${BSIM_OUT_PATH}/bin + +printf "\n\n==== ATT retry on security error (peripheral security request) ====\n\n" + +Execute "$test_exe_d0" \ + -v=${verbosity_level} -s="${simulation_id}" -d=0 -testid=test_client_security_request \ + -RealEncryption=1 + +Execute "$test_exe_d1" \ + -v=${verbosity_level} -s="${simulation_id}" -d=1 -testid=test_server_security_request \ + -RealEncryption=1 + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s="${simulation_id}" \ + -D=2 -sim_length=60e6 $@ + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/host/att/retry_on_sec_err/test_utils.c b/tests/bsim/bluetooth/host/att/retry_on_sec_err/test_utils.c new file mode 100644 index 00000000000..cacb0fa9e53 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/retry_on_sec_err/test_utils.c @@ -0,0 +1,21 @@ +/* Copyright (c) 2023 Codecoup + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "test_utils.h" + +void test_init(void) +{ + bst_result = In_progress; + bst_ticker_set_next_tick_absolute(SIMULATED_TEST_TIMEOUT); +} + +void test_tick(bs_time_t HW_device_time) +{ + bs_trace_debug_time(0, "Simulation ends now.\n"); + if (bst_result == In_progress) { + bst_result = Failed; + bs_trace_error("Test did not pass before simulation ended. Consider increasing " + "simulation length.\n"); + } +} diff --git a/tests/bsim/bluetooth/host/att/retry_on_sec_err/test_utils.h b/tests/bsim/bluetooth/host/att/retry_on_sec_err/test_utils.h new file mode 100644 index 00000000000..0d5113f00f6 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/retry_on_sec_err/test_utils.h @@ -0,0 +1,29 @@ +/* Copyright (c) 2023 Codecoup + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#define DECLARE_FLAG(flag) extern atomic_t flag +#define DEFINE_FLAG(flag) atomic_t flag = (atomic_t) false +#define SET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) true) +#define UNSET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) false) +#define WAIT_FOR_FLAG(flag) \ + while (!(bool)atomic_get(&flag)) { \ + (void)k_sleep(K_MSEC(1)); \ + } + +#define PASS(...) \ + do { \ + bst_result = Passed; \ + bs_trace_info_time(1, __VA_ARGS__); \ + } while (0) + +#define BS_SECONDS(dur_sec) ((bs_time_t)dur_sec * 1000000) +#define SIMULATED_TEST_TIMEOUT BS_SECONDS(60) + +extern enum bst_result_t bst_result; + +void test_init(void); +void test_tick(bs_time_t HW_device_time); diff --git a/tests/bsim/bluetooth/host/att/sequential/common/utils.h b/tests/bsim/bluetooth/host/att/sequential/common/utils.h new file mode 100644 index 00000000000..b4892d5a087 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/sequential/common/utils.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_tracing.h" +#include "bs_types.h" +#include "bstests.h" + +#define BS_SECONDS(dur_sec) ((bs_time_t)dur_sec * USEC_PER_SEC) +#define TEST_TIMEOUT_SIMULATED BS_SECONDS(10) + +extern enum bst_result_t bst_result; + +#define DECLARE_FLAG(flag) extern atomic_t flag +#define DEFINE_FLAG(flag) atomic_t flag = (atomic_t) false +#define SET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) true) +#define UNSET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) false) + +#define WAIT_FOR_VAL(var, val) \ + while (atomic_get(&var) != val) { \ + (void)k_sleep(K_MSEC(1)); \ + } +#define WAIT_FOR_FLAG(flag) \ + while (!(bool)atomic_get(&flag)) { \ + (void)k_sleep(K_MSEC(1)); \ + } +#define WAIT_FOR_FLAG_UNSET(flag) \ + while ((bool)atomic_get(&flag)) { \ + (void)k_sleep(K_MSEC(1)); \ + } +#define TAKE_FLAG(flag) \ + while (!(bool)atomic_cas(&flag, true, false)) { \ + (void)k_sleep(K_MSEC(1)); \ + } + +#define ASSERT(expr, ...) \ + do { \ + if (!(expr)) { \ + FAIL(__VA_ARGS__); \ + } \ + } while (0) + +#define FAIL(...) \ + do { \ + bst_result = Failed; \ + bs_trace_error_time_line(__VA_ARGS__); \ + } while (0) + +#define PASS(...) \ + do { \ + bst_result = Passed; \ + bs_trace_info_time(1, __VA_ARGS__); \ + } while (0) + +#define HVX_HANDLE 0x0012 +#define INDICATION_PAYLOAD "indication" +#define NOTIFICATION_PAYLOAD "notification" diff --git a/tests/bsim/bluetooth/host/att/sequential/dut/CMakeLists.txt b/tests/bsim/bluetooth/host/att/sequential/dut/CMakeLists.txt new file mode 100644 index 00000000000..b6c34df4916 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/sequential/dut/CMakeLists.txt @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(bsim_test_sequential_dut) + +target_sources(app PRIVATE + src/main.c +) + +zephyr_include_directories( + ../common/ + ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ + ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ +) diff --git a/tests/bsim/bluetooth/host/att/sequential/dut/prj.conf b/tests/bsim/bluetooth/host/att/sequential/dut/prj.conf new file mode 100644 index 00000000000..34fe43f0950 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/sequential/dut/prj.conf @@ -0,0 +1,41 @@ +CONFIG_LOG=y +CONFIG_ASSERT=y + +CONFIG_BT=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_DEVICE_NAME="Sequential" + +CONFIG_BT_GATT_CLIENT=y +CONFIG_BT_GATT_ENFORCE_SUBSCRIPTION=n + +# Enable bt_testing_tx_tid_get() +CONFIG_BT_TESTING=y + +# Replace `Execute` with `gdb --args` in the shell script +# and get a nice backtrace on assert +CONFIG_ARCH_POSIX_TRAP_ON_FATAL=y + +# Prepend logs with thread names +CONFIG_THREAD_NAME=y +CONFIG_LOG_THREAD_ID_PREFIX=y + +# Enable those as needed +# CONFIG_BT_L2CAP_LOG_LEVEL_DBG=y +# CONFIG_BT_ATT_LOG_LEVEL_DBG=y +# CONFIG_BT_GATT_LOG_LEVEL_DBG=y + +# Allow whole L2CAP PDUs to fit on-air +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_ACL_RX_SIZE=251 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_BT_DATA_LEN_UPDATE=y +CONFIG_BT_USER_DATA_LEN_UPDATE=y + +# Disable auto-initiated procedures so they don't +# mess with the test's execution. +CONFIG_BT_AUTO_PHY_UPDATE=n +CONFIG_BT_AUTO_DATA_LEN_UPDATE=n +CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=n + +CONFIG_BT_MAX_CONN=1 diff --git a/tests/bsim/bluetooth/host/att/sequential/dut/src/main.c b/tests/bsim/bluetooth/host/att/sequential/dut/src/main.c new file mode 100644 index 00000000000..d44d172eb0c --- /dev/null +++ b/tests/bsim/bluetooth/host/att/sequential/dut/src/main.c @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" +#include "bstests.h" + +#include +LOG_MODULE_REGISTER(dut, LOG_LEVEL_INF); + +DEFINE_FLAG(is_connected); +DEFINE_FLAG(is_subscribed); +DEFINE_FLAG(one_indication); +DEFINE_FLAG(two_notifications); +DEFINE_FLAG(flag_data_length_updated); + +static atomic_t nwrites; +static atomic_t indications; +static atomic_t notifications; + +/* Defined in hci_core.c */ +extern k_tid_t bt_testing_tx_tid_get(void); + +static struct bt_conn *dconn; + +static void connected(struct bt_conn *conn, uint8_t conn_err) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + if (conn_err) { + FAIL("Failed to connect to %s (%u)", addr, conn_err); + return; + } + + LOG_DBG("%s", addr); + + dconn = bt_conn_ref(conn); + SET_FLAG(is_connected); +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + LOG_DBG("%p %s (reason 0x%02x)", conn, addr, reason); + + bt_conn_unref(dconn); + UNSET_FLAG(is_connected); +} + +static void data_len_updated(struct bt_conn *conn, + struct bt_conn_le_data_len_info *info) +{ + LOG_DBG("Data length updated: TX %d RX %d", + info->tx_max_len, + info->rx_max_len); + SET_FLAG(flag_data_length_updated); +} + +static void do_dlu(void) +{ + int err; + struct bt_conn_le_data_len_param param; + + param.tx_max_len = CONFIG_BT_CTLR_DATA_LENGTH_MAX; + param.tx_max_time = 2500; + + err = bt_conn_le_data_len_update(dconn, ¶m); + ASSERT(err == 0, "Can't update data length (err %d)\n", err); + + WAIT_FOR_FLAG(flag_data_length_updated); +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected, + .disconnected = disconnected, + .le_data_len_updated = data_len_updated, +}; + +static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type, + struct net_buf_simple *ad) +{ + char str[BT_ADDR_LE_STR_LEN]; + struct bt_le_conn_param *param; + struct bt_conn *conn; + int err; + + err = bt_le_scan_stop(); + if (err) { + FAIL("Stop LE scan failed (err %d)", err); + return; + } + + bt_addr_le_to_str(addr, str, sizeof(str)); + LOG_DBG("Connecting to %s", str); + + param = BT_LE_CONN_PARAM_DEFAULT; + err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, param, &conn); + if (err) { + FAIL("Create conn failed (err %d)", err); + return; + } +} + +static void connect(void) +{ + int err; + struct bt_le_scan_param scan_param = { + .type = BT_LE_SCAN_TYPE_ACTIVE, + .options = BT_LE_SCAN_OPT_NONE, + .interval = BT_GAP_SCAN_FAST_INTERVAL, + .window = BT_GAP_SCAN_FAST_WINDOW, + }; + + UNSET_FLAG(is_connected); + + err = bt_le_scan_start(&scan_param, device_found); + ASSERT(!err, "Scanning failed to start (err %d)\n", err); + + LOG_DBG("Central initiating connection..."); + WAIT_FOR_FLAG(is_connected); + LOG_INF("Connected as central"); + + /* No security support on the tinyhost unfortunately */ +} + +static ssize_t written_to(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + const void *buf, + uint16_t len, + uint16_t offset, + uint8_t flags) +{ + LOG_INF("written to: handle 0x%x len %d flags 0x%x", + attr->handle, + len, + flags); + + LOG_HEXDUMP_DBG(buf, len, "Write data"); + + if (atomic_get(&nwrites) == 0) { + /* Suspend on the first write, which is an ATT Request */ + LOG_INF("suspending HCI TX thread"); + k_thread_suspend(bt_testing_tx_tid_get()); + } + + atomic_inc(&nwrites); + + return len; +} + +#define test_service_uuid \ + BT_UUID_DECLARE_128(BT_UUID_128_ENCODE(0xf0debc9a, 0x7856, 0x3412, 0x7856, 0x341278563412)) +#define test_characteristic_uuid \ + BT_UUID_DECLARE_128(BT_UUID_128_ENCODE(0xf2debc9a, 0x7856, 0x3412, 0x7856, 0x341278563412)) + +BT_GATT_SERVICE_DEFINE(test_gatt_service, BT_GATT_PRIMARY_SERVICE(test_service_uuid), + BT_GATT_CHARACTERISTIC(test_characteristic_uuid, + (BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | + BT_GATT_CHRC_NOTIFY | BT_GATT_CHRC_INDICATE), + BT_GATT_PERM_READ | BT_GATT_PERM_WRITE, + NULL, written_to, NULL), + BT_GATT_CCC(NULL, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),); + +static uint8_t notified(struct bt_conn *conn, struct bt_gatt_subscribe_params *params, + const void *data, uint16_t length) +{ + static uint8_t notification[] = NOTIFICATION_PAYLOAD; + static uint8_t indication[] = INDICATION_PAYLOAD; + bool is_nfy; + + ASSERT(length >= sizeof(indication), "Unexpected data"); + ASSERT(length <= sizeof(notification), "Unexpected data"); + + LOG_HEXDUMP_DBG(data, length, "HVx data"); + + is_nfy = memcmp(data, notification, length) == 0; + + LOG_INF("%s from 0x%x", is_nfy ? "notified" : "indicated", + params->value_handle); + + if (is_nfy) { + atomic_inc(¬ifications); + } else { + atomic_inc(&indications); + } + + return BT_GATT_ITER_CONTINUE; +} + +static void subscribed(struct bt_conn *conn, + uint8_t err, + struct bt_gatt_subscribe_params *params) +{ + ASSERT(!err, "Subscribe failed (err %d)\n", err); + + ASSERT(params, "params is NULL\n"); + + SET_FLAG(is_subscribed); + /* spoiler: tester doesn't really have attributes */ + LOG_INF("Subscribed to Tester attribute"); +} + +void subscribe(void) +{ + int err; + + /* Handle values don't matter, as long as they match on the tester */ + static struct bt_gatt_subscribe_params params = { + .notify = notified, + .subscribe = subscribed, + .value = BT_GATT_CCC_NOTIFY | BT_GATT_CCC_INDICATE, + .value_handle = HVX_HANDLE, + .ccc_handle = (HVX_HANDLE + 1), + }; + + err = bt_gatt_subscribe(dconn, ¶ms); + ASSERT(!err, "Subscribe failed (err %d)\n", err); + + WAIT_FOR_FLAG(is_subscribed); +} + +static void send_write_handle(void) +{ + int err; + uint16_t handle; + uint8_t data[sizeof(handle)]; + const struct bt_gatt_attr *attr = &test_gatt_service.attrs[2]; + + /* Inform tester which handle it should write to */ + handle = bt_gatt_attr_get_handle(attr); + sys_put_le16(handle, data); + + err = bt_gatt_notify(dconn, attr, data, sizeof(data)); + ASSERT(!err, "Failed to transmit handle for write (err %d)\n", err); +} + +void test_procedure_0(void) +{ + LOG_DBG("Test start: ATT sequential protocol"); + int err; + + err = bt_enable(NULL); + ASSERT(err == 0, "Can't enable Bluetooth (err %d)\n", err); + LOG_DBG("Central: Bluetooth initialized."); + + /* Test purpose: + * Test Spec V.3 P.F 3.3.2 Sequential protocol + * + * Verify that a Zephyr host server/client combo can process + * concurrently: one Request, one Indication, multiple + * Notifications and multiple Commands. + * + * To do this, the application on the DUT will purposefully stall the + * HCI TX thread, ensuring that the responses are not sent until the + * tester has finished sending everything. + * + * Test procedure: + * + * [setup] + * - connect ACL + * - update data length (tinyhost doens't have recombination) + * - dut: subscribe to INDICATE and NOTIFY on tester CHRC + * - dut: send a handle the tester can write to + * + * [proc] + * - tester: send one ATT write request + * - tester: send one ATT indication + * - tester: send two ATT notifications + * - tester: send two ATT commands + * + * - dut: handle the REQuest, build & put the RSP PDU on the HCI TX queue + * - dut: suspend the HCI TX thread + * - dut: handle the INDication + * - dut: handle the notifications + * - dut: handle the (write) commands + * - dut: resume the TX thread after a short while + * + * [verdict] + * - all procedures complete successfully, no buffer allocation failures + * or timeouts. + */ + connect(); + subscribe(); + + do_dlu(); + + send_write_handle(); + + WAIT_FOR_VAL(indications, 1); + WAIT_FOR_VAL(notifications, 2); + /* One REQ, two CMDs */ + WAIT_FOR_VAL(nwrites, 3); + + /* Send RSP to LL */ + k_thread_resume(bt_testing_tx_tid_get()); + + PASS("DUT done\n"); +} + +void test_tick(bs_time_t HW_device_time) +{ + bs_trace_debug_time(0, "Simulation ends now.\n"); + if (bst_result != Passed) { + bst_result = Failed; + bs_trace_error("Test did not pass before simulation ended.\n"); + } +} + +void test_init(void) +{ + bst_ticker_set_next_tick_absolute(TEST_TIMEOUT_SIMULATED); + bst_result = In_progress; +} + +static const struct bst_test_instance test_to_add[] = { + { + .test_id = "dut", + .test_pre_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_procedure_0, + }, + BSTEST_END_MARKER, +}; + +static struct bst_test_list *install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, test_to_add); +}; + +bst_test_install_t test_installers[] = {install, NULL}; + +int main(void) +{ + bst_main(); + + return 0; +} diff --git a/tests/bsim/bluetooth/host/att/sequential/scripts/_compile.sh b/tests/bsim/bluetooth/host/att/sequential/scripts/_compile.sh new file mode 100755 index 00000000000..2e81445690f --- /dev/null +++ b/tests/bsim/bluetooth/host/att/sequential/scripts/_compile.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Path checks, etc +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +BOARD="${BOARD:-nrf52_bsim}" +dut_exe="bs_${BOARD}_tests_bsim_bluetooth_host_att_sequential_dut_prj_conf" +tester_exe="bs_${BOARD}_tests_bsim_bluetooth_host_att_sequential_tester_prj_conf" + +# terminate running simulations (if any) +${BSIM_COMPONENTS_PATH}/common/stop_bsim.sh + +west build -b ${BOARD} -d build_dut dut && \ + cp build_dut/zephyr/zephyr.exe "${BSIM_OUT_PATH}/bin/${dut_exe}" && +west build -b ${BOARD} -d build_tester tester && \ + cp build_tester/zephyr/zephyr.exe "${BSIM_OUT_PATH}/bin/${tester_exe}" diff --git a/tests/bsim/bluetooth/host/att/sequential/scripts/sequential.sh b/tests/bsim/bluetooth/host/att/sequential/scripts/sequential.sh new file mode 100755 index 00000000000..61153432781 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/sequential/scripts/sequential.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +BOARD="${BOARD:-nrf52_bsim}" +dut_exe="bs_${BOARD}_tests_bsim_bluetooth_host_att_sequential_dut_prj_conf" +tester_exe="bs_${BOARD}_tests_bsim_bluetooth_host_att_sequential_tester_prj_conf" + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +test_name="att_sequential" +simulation_id="${test_name}" +verbosity_level=2 +EXECUTE_TIMEOUT=30 +sim_length_us=10e6 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_2G4_phy_v1 \ + -v=${verbosity_level} -s="${simulation_id}" -D=2 -sim_length=${sim_length_us} $@ + +Execute "./$tester_exe" \ + -v=${verbosity_level} -s="${simulation_id}" -d=1 -testid=tester -RealEncryption=0 -rs=100 + +Execute "./$dut_exe" \ + -v=${verbosity_level} -s="${simulation_id}" -d=0 -testid=dut -RealEncryption=0 + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/host/att/sequential/tester/CMakeLists.txt b/tests/bsim/bluetooth/host/att/sequential/tester/CMakeLists.txt new file mode 100644 index 00000000000..c4410ee0b9e --- /dev/null +++ b/tests/bsim/bluetooth/host/att/sequential/tester/CMakeLists.txt @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(bsim_test_sequential_tester) + +target_sources(app PRIVATE + src/main.c +) + +zephyr_include_directories( + ../common/ + ${ZEPHYR_BASE}/subsys/bluetooth/common/ + ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ + ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ +) diff --git a/tests/bsim/bluetooth/host/att/sequential/tester/prj.conf b/tests/bsim/bluetooth/host/att/sequential/tester/prj.conf new file mode 100644 index 00000000000..461c7dd5029 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/sequential/tester/prj.conf @@ -0,0 +1,19 @@ +CONFIG_LOG=y +CONFIG_ASSERT=y + +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_HCI_RAW_RESERVE=1 +CONFIG_BT_MAX_CONN=1 + +CONFIG_BT_BUF_CMD_TX_COUNT=10 + +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_CMD_TX_SIZE=255 +CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=255 + +# Allow whole L2CAP PDUs to fit on-air +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_ACL_RX_SIZE=251 +CONFIG_BT_DATA_LEN_UPDATE=y +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 diff --git a/tests/bsim/bluetooth/host/att/sequential/tester/src/main.c b/tests/bsim/bluetooth/host/att/sequential/tester/src/main.c new file mode 100644 index 00000000000..cecbd8cab13 --- /dev/null +++ b/tests/bsim/bluetooth/host/att/sequential/tester/src/main.c @@ -0,0 +1,668 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "common/bt_str.h" + +#include "host/conn_internal.h" +#include "host/l2cap_internal.h" + +#include "utils.h" +#include "bstests.h" + +#include +LOG_MODULE_REGISTER(bt_tinyhost, LOG_LEVEL_INF); + +#define BT_ATT_OP_MTU_REQ 0x02 +#define BT_ATT_OP_MTU_RSP 0x03 +#define BT_ATT_OP_WRITE_REQ 0x12 +#define BT_ATT_OP_WRITE_RSP 0x13 +#define BT_ATT_OP_NOTIFY 0x1b +#define BT_ATT_OP_INDICATE 0x1d +#define BT_ATT_OP_CONFIRM 0x1e +#define BT_ATT_OP_WRITE_CMD 0x52 +#define BT_L2CAP_CID_ATT 0x0004 + +DEFINE_FLAG(is_connected); +DEFINE_FLAG(flag_data_length_updated); +DEFINE_FLAG(flag_handle); +DEFINE_FLAG(flag_notified); +DEFINE_FLAG(flag_write_ack); +DEFINE_FLAG(flag_indication_ack); + +static uint16_t server_write_handle; + +static K_FIFO_DEFINE(rx_queue); + +#define CMD_BUF_SIZE MAX(BT_BUF_EVT_RX_SIZE, BT_BUF_CMD_TX_SIZE) +NET_BUF_POOL_FIXED_DEFINE(hci_cmd_pool, CONFIG_BT_BUF_CMD_TX_COUNT, + CMD_BUF_SIZE, 8, NULL); + +static K_SEM_DEFINE(cmd_sem, 1, 1); +static struct k_sem acl_pkts; +static uint16_t conn_handle; + +static volatile uint16_t active_opcode = 0xFFFF; +static struct net_buf *cmd_rsp; + +struct net_buf *bt_hci_cmd_create(uint16_t opcode, uint8_t param_len) +{ + struct bt_hci_cmd_hdr *hdr; + struct net_buf *buf; + + LOG_DBG("opcode 0x%04x param_len %u", opcode, param_len); + + buf = net_buf_alloc(&hci_cmd_pool, K_FOREVER); + ASSERT(buf, "failed allocation"); + + LOG_DBG("buf %p", buf); + + net_buf_reserve(buf, BT_BUF_RESERVE); + + bt_buf_set_type(buf, BT_BUF_CMD); + + hdr = net_buf_add(buf, sizeof(*hdr)); + hdr->opcode = sys_cpu_to_le16(opcode); + hdr->param_len = param_len; + + return buf; +} + +static void handle_cmd_complete(struct net_buf *buf) +{ + struct bt_hci_evt_hdr *hdr; + uint8_t status, ncmd; + uint16_t opcode; + struct net_buf_simple_state state; + + net_buf_simple_save(&buf->b, &state); + + hdr = net_buf_pull_mem(buf, sizeof(*hdr)); + + if (hdr->evt == BT_HCI_EVT_CMD_COMPLETE) { + struct bt_hci_evt_cmd_complete *evt; + + evt = net_buf_pull_mem(buf, sizeof(*evt)); + status = 0; + ncmd = evt->ncmd; + opcode = sys_le16_to_cpu(evt->opcode); + + } else if (hdr->evt == BT_HCI_EVT_CMD_STATUS) { + struct bt_hci_evt_cmd_status *evt; + + evt = net_buf_pull_mem(buf, sizeof(*evt)); + status = buf->data[0]; + ncmd = evt->ncmd; + opcode = sys_le16_to_cpu(evt->opcode); + + } else { + FAIL("unhandled event 0x%x", hdr->evt); + } + + LOG_DBG("opcode 0x%04x status %x", opcode, status); + + ASSERT(status == 0x00, "cmd status: %x", status); + + ASSERT(active_opcode == opcode, "unexpected opcode %x != %x", active_opcode, opcode); + + if (active_opcode) { + active_opcode = 0xFFFF; + cmd_rsp = net_buf_ref(buf); + net_buf_simple_restore(&buf->b, &state); + } + + if (ncmd) { + k_sem_give(&cmd_sem); + } +} + +static void handle_meta_event(struct net_buf *buf) +{ + uint8_t code = buf->data[2]; + + switch (code) { + case BT_HCI_EVT_LE_ENH_CONN_COMPLETE: + case BT_HCI_EVT_LE_ENH_CONN_COMPLETE_V2: + conn_handle = sys_get_le16(&buf->data[4]); + LOG_DBG("connected: handle: %d", conn_handle); + SET_FLAG(is_connected); + break; + case BT_HCI_EVT_LE_DATA_LEN_CHANGE: + SET_FLAG(flag_data_length_updated); + break; + case BT_HCI_EVT_LE_CHAN_SEL_ALGO: + /* do nothing */ + break; + default: + LOG_ERR("unhandled meta event %x", code); + LOG_HEXDUMP_ERR(buf->data, buf->len, "HCI META EVT"); + } +} + +static void handle_ncp(struct net_buf *buf) +{ + struct bt_hci_evt_num_completed_packets *evt; + struct bt_hci_evt_hdr *hdr; + uint16_t handle, count; + + hdr = net_buf_pull_mem(buf, sizeof(*hdr)); + + evt = (void *)buf->data; + handle = sys_le16_to_cpu(evt->h[0].handle); + count = sys_le16_to_cpu(evt->h[0].count); + + LOG_DBG("sent %d packets", count); + + while (count--) { + k_sem_give(&acl_pkts); + } +} + +static void handle_att_notification(struct net_buf *buf) +{ + uint16_t handle = net_buf_pull_le16(buf); + + LOG_INF("Got notification for 0x%04x len %d", handle, buf->len); + LOG_HEXDUMP_DBG(buf->data, buf->len, "payload"); + + server_write_handle = net_buf_pull_le16(buf); + LOG_INF("Retrieved handle to write to: 0x%x", server_write_handle); + SET_FLAG(flag_handle); +} + +struct net_buf *alloc_l2cap_pdu(void); +static void send_l2cap_packet(struct net_buf *buf, uint16_t cid); + +static void send_write_rsp(void) +{ + struct net_buf *buf = alloc_l2cap_pdu(); + + net_buf_add_u8(buf, BT_ATT_OP_WRITE_RSP); + send_l2cap_packet(buf, BT_L2CAP_CID_ATT); +} + +static void handle_att_write(struct net_buf *buf) +{ + uint16_t handle = net_buf_pull_le16(buf); + + LOG_INF("Got write for 0x%04x len %d", handle, buf->len); + LOG_HEXDUMP_DBG(buf->data, buf->len, "payload"); + + send_write_rsp(); +} + +static void handle_att(struct net_buf *buf) +{ + uint8_t op = net_buf_pull_u8(buf); + + switch (op) { + case BT_ATT_OP_NOTIFY: + handle_att_notification(buf); + return; + case BT_ATT_OP_WRITE_REQ: + handle_att_write(buf); + return; + case BT_ATT_OP_WRITE_RSP: + LOG_INF("got ATT write RSP"); + SET_FLAG(flag_write_ack); + return; + case BT_ATT_OP_CONFIRM: + LOG_INF("got ATT indication confirm"); + SET_FLAG(flag_indication_ack); + return; + case BT_ATT_OP_MTU_RSP: + LOG_INF("got ATT MTU RSP"); + return; + default: + LOG_HEXDUMP_ERR(buf->data, buf->len, "payload"); + FAIL("unhandled opcode %x\n", op); + return; + } +} + +static void handle_l2cap(struct net_buf *buf) +{ + struct bt_l2cap_hdr *hdr; + uint16_t cid; + + hdr = net_buf_pull_mem(buf, sizeof(*hdr)); + cid = sys_le16_to_cpu(hdr->cid); + + LOG_DBG("Packet for CID %u len %u", cid, buf->len); + LOG_HEXDUMP_DBG(buf->data, buf->len, "l2cap"); + + /* Make sure we don't have to recombine packets */ + ASSERT(buf->len == hdr->len, "buflen = %d != hdrlen %d", + buf->len, hdr->len); + + ASSERT(cid == BT_L2CAP_CID_ATT, "We only support (U)ATT"); + + /* (U)ATT PDU */ + handle_att(buf); +} + +static void handle_acl(struct net_buf *buf) +{ + struct bt_hci_acl_hdr *hdr; + uint16_t len, handle; + uint8_t flags; + + hdr = net_buf_pull_mem(buf, sizeof(*hdr)); + len = sys_le16_to_cpu(hdr->len); + handle = sys_le16_to_cpu(hdr->handle); + + flags = bt_acl_flags(handle); + handle = bt_acl_handle(handle); + + ASSERT(flags == BT_ACL_START, + "Fragmentation not supported"); + + LOG_DBG("ACL: conn %d len %d flags %d", handle, len, flags); + LOG_HEXDUMP_DBG(buf->data, buf->len, "HCI ACL"); + + handle_l2cap(buf); +} + +static void recv(struct net_buf *buf) +{ + LOG_HEXDUMP_DBG(buf->data, buf->len, "HCI RX"); + + uint8_t code = buf->data[0]; + + if (bt_buf_get_type(buf) == BT_BUF_EVT) { + switch (code) { + case BT_HCI_EVT_CMD_COMPLETE: + case BT_HCI_EVT_CMD_STATUS: + handle_cmd_complete(buf); + break; + case BT_HCI_EVT_LE_META_EVENT: + handle_meta_event(buf); + break; + case BT_HCI_EVT_DISCONN_COMPLETE: + UNSET_FLAG(is_connected); + break; + case BT_HCI_EVT_NUM_COMPLETED_PACKETS: + handle_ncp(buf); + break; + default: + LOG_ERR("unhandled msg %x", code); + LOG_HEXDUMP_ERR(buf->data, buf->len, "HCI EVT"); + } + + /* handlers should take a ref if they want to access the buffer + * later + */ + net_buf_unref(buf); + return; + } + + if (bt_buf_get_type(buf) == BT_BUF_ACL_IN) { + handle_acl(buf); + net_buf_unref(buf); + return; + } + + LOG_ERR("HCI RX (not data or event)"); + net_buf_unref(buf); +} + +static void send_cmd(uint16_t opcode, struct net_buf *cmd, struct net_buf **rsp) +{ + LOG_DBG("opcode %x", opcode); + + if (!cmd) { + cmd = bt_hci_cmd_create(opcode, 0); + } + + k_sem_take(&cmd_sem, K_FOREVER); + ASSERT(active_opcode == 0xFFFF, ""); + + active_opcode = opcode; + + LOG_HEXDUMP_DBG(cmd->data, cmd->len, "HCI TX"); + bt_send(cmd); + + /* Wait until the command completes */ + k_sem_take(&cmd_sem, K_FOREVER); + k_sem_give(&cmd_sem); + + net_buf_unref(cmd); + + /* return response. it's okay if cmd_rsp gets overwritten, since the app + * gets the ref to the underlying buffer when this fn returns. + */ + if (rsp) { + *rsp = cmd_rsp; + } else { + net_buf_unref(cmd_rsp); + cmd_rsp = NULL; + } +} + +static K_THREAD_STACK_DEFINE(rx_thread_stack, 1024); +static struct k_thread rx_thread_data; + +static void rx_thread(void *p1, void *p2, void *p3) +{ + LOG_DBG("start HCI rx"); + + while (true) { + struct net_buf *buf; + + /* Wait until a buffer is available */ + buf = net_buf_get(&rx_queue, K_FOREVER); + recv(buf); + } +} + +static void le_read_buffer_size_complete(struct net_buf *rsp) +{ + struct bt_hci_rp_le_read_buffer_size *rp = (void *)rsp->data; + + LOG_DBG("status 0x%02x", rp->status); + LOG_DBG("max len %d max num %d", rp->le_max_len, rp->le_max_num); + + k_sem_init(&acl_pkts, rp->le_max_num, rp->le_max_num); + net_buf_unref(rsp); +} + +static void read_max_data_len(uint16_t *tx_octets, uint16_t *tx_time) +{ + struct bt_hci_rp_le_read_max_data_len *rp; + struct net_buf *rsp; + + send_cmd(BT_HCI_OP_LE_READ_MAX_DATA_LEN, NULL, &rsp); + + rp = (void *)rsp->data; + *tx_octets = sys_le16_to_cpu(rp->max_tx_octets); + *tx_time = sys_le16_to_cpu(rp->max_tx_time); + net_buf_unref(rsp); +} + +static void write_default_data_len(uint16_t tx_octets, uint16_t tx_time) +{ + struct bt_hci_cp_le_write_default_data_len *cp; + struct net_buf *buf = bt_hci_cmd_create(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN, sizeof(*cp)); + + ASSERT(buf, ""); + + cp = net_buf_add(buf, sizeof(*cp)); + cp->max_tx_octets = sys_cpu_to_le16(tx_octets); + cp->max_tx_time = sys_cpu_to_le16(tx_time); + + send_cmd(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN, buf, NULL); +} + +static void set_data_len(void) +{ + uint16_t tx_octets, tx_time; + + read_max_data_len(&tx_octets, &tx_time); + write_default_data_len(tx_octets, tx_time); +} + +static void set_event_mask(uint16_t opcode) +{ + struct bt_hci_cp_set_event_mask *cp_mask; + struct net_buf *buf; + uint64_t mask = 0U; + + /* The two commands have the same length/params */ + buf = bt_hci_cmd_create(opcode, sizeof(*cp_mask)); + ASSERT(buf, ""); + + /* Forward all events */ + cp_mask = net_buf_add(buf, sizeof(*cp_mask)); + mask = UINT64_MAX; + sys_put_le64(mask, cp_mask->events); + + send_cmd(opcode, buf, NULL); +} + +static void set_random_address(void) +{ + struct net_buf *buf; + bt_addr_le_t addr = {BT_ADDR_LE_RANDOM, {{0x0A, 0x89, 0x67, 0x45, 0x23, 0xC1}}}; + + LOG_DBG("%s", bt_addr_str(&addr.a)); + + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, sizeof(addr.a)); + ASSERT(buf, ""); + + net_buf_add_mem(buf, &addr.a, sizeof(addr.a)); + send_cmd(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, buf, NULL); +} + +void start_adv(void) +{ + struct bt_hci_cp_le_set_adv_param set_param; + struct net_buf *buf; + uint16_t interval = 60; /* Interval doesn't matter */ + + (void)memset(&set_param, 0, sizeof(set_param)); + + set_param.min_interval = sys_cpu_to_le16(interval); + set_param.max_interval = sys_cpu_to_le16(interval); + set_param.channel_map = 0x07; + set_param.filter_policy = BT_LE_ADV_FP_NO_FILTER; + set_param.type = BT_HCI_ADV_IND; + set_param.own_addr_type = 0x01; /* random */ + + /* configure */ + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_PARAM, sizeof(set_param)); + net_buf_add_mem(buf, &set_param, sizeof(set_param)); + send_cmd(BT_HCI_OP_LE_SET_ADV_PARAM, buf, NULL); + + /* start */ + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_ENABLE, 1); + net_buf_add_u8(buf, BT_HCI_LE_ADV_ENABLE); + send_cmd(BT_HCI_OP_LE_SET_ADV_ENABLE, buf, NULL); +} + +NET_BUF_POOL_DEFINE(acl_tx_pool, 5, BT_L2CAP_BUF_SIZE(200), 8, NULL); + +struct net_buf *alloc_l2cap_pdu(void) +{ + struct net_buf *buf; + uint16_t reserve; + + buf = net_buf_alloc(&acl_tx_pool, K_FOREVER); + ASSERT(buf, "failed ACL allocation"); + + reserve = sizeof(struct bt_l2cap_hdr); + reserve += sizeof(struct bt_hci_acl_hdr) + BT_BUF_RESERVE; + + net_buf_reserve(buf, reserve); + + return buf; +} + +static int send_acl(struct net_buf *buf) +{ + struct bt_hci_acl_hdr *hdr; + uint8_t flags = BT_ACL_START_NO_FLUSH; + + hdr = net_buf_push(buf, sizeof(*hdr)); + hdr->handle = sys_cpu_to_le16(bt_acl_handle_pack(conn_handle, flags)); + hdr->len = sys_cpu_to_le16(buf->len - sizeof(*hdr)); + + bt_buf_set_type(buf, BT_BUF_ACL_OUT); + + k_sem_take(&acl_pkts, K_FOREVER); + + return bt_send(buf); +} + +static void send_l2cap_packet(struct net_buf *buf, uint16_t cid) +{ + struct bt_l2cap_hdr *hdr; + + hdr = net_buf_push(buf, sizeof(*hdr)); + hdr->len = sys_cpu_to_le16(buf->len - sizeof(*hdr)); + hdr->cid = sys_cpu_to_le16(cid); + + /* Always entire packets, no HCI fragmentation */ + ASSERT(buf->len <= CONFIG_BT_BUF_ACL_TX_SIZE, + "Fragmentation not supported"); + + send_acl(buf); +} + +static void gatt_write(uint16_t op) +{ + static uint8_t data[] = "write"; + uint16_t handle = server_write_handle; + struct net_buf *buf = alloc_l2cap_pdu(); + + net_buf_add_u8(buf, op); + net_buf_add_le16(buf, handle); + net_buf_add_mem(buf, data, sizeof(data)); + + LOG_INF("send ATT write %s", + op == BT_ATT_OP_WRITE_REQ ? "REQ" : "CMD"); + + send_l2cap_packet(buf, BT_L2CAP_CID_ATT); +} + +static void gatt_notify(void) +{ + static uint8_t data[] = NOTIFICATION_PAYLOAD; + uint16_t handle = HVX_HANDLE; + struct net_buf *buf = alloc_l2cap_pdu(); + + net_buf_add_u8(buf, BT_ATT_OP_NOTIFY); + net_buf_add_le16(buf, handle); + net_buf_add_mem(buf, data, sizeof(data)); + + LOG_INF("send ATT notification"); + send_l2cap_packet(buf, BT_L2CAP_CID_ATT); +} + +static void gatt_indicate(void) +{ + static uint8_t data[] = INDICATION_PAYLOAD; + uint16_t handle = HVX_HANDLE; + struct net_buf *buf = alloc_l2cap_pdu(); + + net_buf_add_u8(buf, BT_ATT_OP_INDICATE); + net_buf_add_le16(buf, handle); + net_buf_add_mem(buf, data, sizeof(data)); + + LOG_INF("send ATT indication"); + send_l2cap_packet(buf, BT_L2CAP_CID_ATT); +} + +static void prepare_controller(void) +{ + /* Initialize controller */ + struct net_buf *rsp; + + send_cmd(BT_HCI_OP_RESET, NULL, NULL); + send_cmd(BT_HCI_OP_LE_READ_BUFFER_SIZE, NULL, &rsp); + le_read_buffer_size_complete(rsp); + + set_data_len(); + set_event_mask(BT_HCI_OP_SET_EVENT_MASK); + set_event_mask(BT_HCI_OP_LE_SET_EVENT_MASK); + set_random_address(); +} + +static void init_tinyhost(void) +{ + bt_enable_raw(&rx_queue); + + /* Start the RX thread */ + k_thread_create(&rx_thread_data, rx_thread_stack, + K_THREAD_STACK_SIZEOF(rx_thread_stack), rx_thread, + NULL, NULL, NULL, K_PRIO_PREEMPT(0), 0, K_NO_WAIT); + k_thread_name_set(&rx_thread_data, "HCI RX"); + + k_thread_priority_set(k_current_get(), K_PRIO_PREEMPT(0)); + + prepare_controller(); +} + +void test_procedure_0(void) +{ + init_tinyhost(); + + /* Start advertising & wait for a connection */ + start_adv(); + WAIT_FOR_FLAG(is_connected); + LOG_INF("connected"); + + /* We need this to be able to send whole L2CAP PDUs on-air. */ + WAIT_FOR_FLAG(flag_data_length_updated); + + /* Get handle we will write to */ + WAIT_FOR_FLAG(flag_handle); + + LOG_INF("##################### START TEST #####################"); + + gatt_write(BT_ATT_OP_WRITE_REQ); /* will prompt a response PDU */ + gatt_indicate(); /* will prompt a confirmation PDU */ + + gatt_notify(); + gatt_write(BT_ATT_OP_WRITE_CMD); + + gatt_notify(); + gatt_write(BT_ATT_OP_WRITE_CMD); + + WAIT_FOR_FLAG(flag_write_ack); + WAIT_FOR_FLAG(flag_indication_ack); + + PASS("Tester done\n"); +} + +void test_tick(bs_time_t HW_device_time) +{ + bs_trace_debug_time(0, "Simulation ends now.\n"); + if (bst_result != Passed) { + bst_result = Failed; + bs_trace_error("Test did not pass before simulation ended.\n"); + } +} + +void test_init(void) +{ + bst_ticker_set_next_tick_absolute(TEST_TIMEOUT_SIMULATED); + bst_result = In_progress; +} + +static const struct bst_test_instance test_to_add[] = { + { + .test_id = "tester", + .test_pre_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_procedure_0, + }, + BSTEST_END_MARKER, +}; + +static struct bst_test_list *install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, test_to_add); +}; + +bst_test_install_t test_installers[] = {install, NULL}; + + +int main(void) +{ + bst_main(); + + return 0; +} diff --git a/tests/bsim/bluetooth/host/compile.sh b/tests/bsim/bluetooth/host/compile.sh index 98d6c79e3ef..ff42fd27adf 100755 --- a/tests/bsim/bluetooth/host/compile.sh +++ b/tests/bsim/bluetooth/host/compile.sh @@ -35,6 +35,11 @@ app=tests/bsim/bluetooth/host/att/eatt_notif conf_file=prj.conf compile app=tests/bsim/bluetooth/host/att/mtu_update compile app=tests/bsim/bluetooth/host/att/read_fill_buf/client compile app=tests/bsim/bluetooth/host/att/read_fill_buf/server compile +app=tests/bsim/bluetooth/host/att/retry_on_sec_err/client compile +app=tests/bsim/bluetooth/host/att/retry_on_sec_err/server compile +app=tests/bsim/bluetooth/host/att/sequential/dut compile +app=tests/bsim/bluetooth/host/att/sequential/tester compile +app=tests/bsim/bluetooth/host/att/long_read compile app=tests/bsim/bluetooth/host/gatt/caching compile app=tests/bsim/bluetooth/host/gatt/general compile @@ -46,6 +51,8 @@ app=tests/bsim/bluetooth/host/gatt/ccc_store compile app=tests/bsim/bluetooth/host/gatt/ccc_store conf_file=prj_2.conf compile app=tests/bsim/bluetooth/host/gatt/sc_indicate compile +app=tests/bsim/bluetooth/host/iso/cis compile + app=tests/bsim/bluetooth/host/l2cap/general compile app=tests/bsim/bluetooth/host/l2cap/userdata compile app=tests/bsim/bluetooth/host/l2cap/stress compile @@ -59,9 +66,12 @@ app=tests/bsim/bluetooth/host/l2cap/send_on_connect compile app=tests/bsim/bluetooth/host/l2cap/send_on_connect conf_file=prj_ecred.conf compile app=tests/bsim/bluetooth/host/misc/disable compile +app=tests/bsim/bluetooth/host/misc/disconnect/dut compile +app=tests/bsim/bluetooth/host/misc/disconnect/tester compile app=tests/bsim/bluetooth/host/privacy/central compile app=tests/bsim/bluetooth/host/privacy/peripheral compile +app=tests/bsim/bluetooth/host/privacy/peripheral conf_file=prj_rpa_sharing.conf compile app=tests/bsim/bluetooth/host/privacy/device compile app=tests/bsim/bluetooth/host/privacy/legacy compile @@ -70,7 +80,9 @@ app=tests/bsim/bluetooth/host/security/bond_overwrite_denied compile app=tests/bsim/bluetooth/host/security/bond_per_connection compile app=tests/bsim/bluetooth/host/security/ccc_update compile app=tests/bsim/bluetooth/host/security/ccc_update conf_file=prj_2.conf compile -app=tests/bsim/bluetooth/host/security/id_addr_update compile +app=tests/bsim/bluetooth/host/security/id_addr_update/central compile +app=tests/bsim/bluetooth/host/security/id_addr_update/peripheral compile +app=tests/bsim/bluetooth/host/security/security_changed_callback compile app=tests/bsim/bluetooth/host/id/settings compile diff --git a/tests/bsim/bluetooth/host/gatt/settings/src/client.c b/tests/bsim/bluetooth/host/gatt/settings/src/client.c index 8720fdea219..fc33f17bd4b 100644 --- a/tests/bsim/bluetooth/host/gatt/settings/src/client.c +++ b/tests/bsim/bluetooth/host/gatt/settings/src/client.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include diff --git a/tests/bsim/bluetooth/host/gatt/settings/src/gatt_utils.c b/tests/bsim/bluetooth/host/gatt/settings/src/gatt_utils.c index fae0531a0b3..abfcbcfafc8 100644 --- a/tests/bsim/bluetooth/host/gatt/settings/src/gatt_utils.c +++ b/tests/bsim/bluetooth/host/gatt/settings/src/gatt_utils.c @@ -125,8 +125,6 @@ DEFINE_FLAG(flag_discovered); static uint8_t discover_func(struct bt_conn *conn, const struct bt_gatt_attr *attr, struct bt_gatt_discover_params *params) { - int err; - if (attr == NULL) { for (int i = 0; i < ARRAY_SIZE(gatt_handles); i++) { printk("handle[%d] = 0x%x\n", i, gatt_handles[i]); @@ -143,20 +141,7 @@ static uint8_t discover_func(struct bt_conn *conn, const struct bt_gatt_attr *at return BT_GATT_ITER_STOP; } - if (params->type == BT_GATT_DISCOVER_PRIMARY && - bt_uuid_cmp(params->uuid, &test_svc_uuid.uuid) == 0) { - printk("Found test service\n"); - params->uuid = NULL; - params->start_handle = attr->handle + 1; - params->type = BT_GATT_DISCOVER_CHARACTERISTIC; - - err = bt_gatt_discover(conn, params); - if (err != 0) { - FAIL("Discover failed (err %d)\n", err); - } - - return BT_GATT_ITER_STOP; - } else if (params->type == BT_GATT_DISCOVER_CHARACTERISTIC) { + if (params->type == BT_GATT_DISCOVER_CHARACTERISTIC) { const struct bt_gatt_chrc *chrc = (struct bt_gatt_chrc *)attr->user_data; if (bt_uuid_cmp(chrc->uuid, BT_UUID_GATT_CLIENT_FEATURES) == 0) { diff --git a/tests/bsim/bluetooth/host/gatt/settings/src/server.c b/tests/bsim/bluetooth/host/gatt/settings/src/server.c index 9457febc5d4..7fff0f72c15 100644 --- a/tests/bsim/bluetooth/host/gatt/settings/src/server.c +++ b/tests/bsim/bluetooth/host/gatt/settings/src/server.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include diff --git a/tests/bsim/bluetooth/host/gatt/settings/src/settings.c b/tests/bsim/bluetooth/host/gatt/settings/src/settings.c index c87a8470883..2aebd77f05f 100644 --- a/tests/bsim/bluetooth/host/gatt/settings/src/settings.c +++ b/tests/bsim/bluetooth/host/gatt/settings/src/settings.c @@ -11,7 +11,7 @@ #include #include -#include "zephyr/types.h" +#include #include "errno.h" #include "argparse.h" diff --git a/tests/bsim/bluetooth/host/iso/cis/CMakeLists.txt b/tests/bsim/bluetooth/host/iso/cis/CMakeLists.txt new file mode 100644 index 00000000000..b856e60fcf3 --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/cis/CMakeLists.txt @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(bsim_test_l2cap_send_on_connect) + +target_sources(app PRIVATE + src/common.c + src/cis_central.c + src/cis_peripheral.c + src/main.c +) + +zephyr_include_directories( + ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ + ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ + ) diff --git a/tests/bsim/bluetooth/host/iso/cis/prj.conf b/tests/bsim/bluetooth/host/iso/cis/prj.conf new file mode 100644 index 00000000000..d1a1b8cd161 --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/cis/prj.conf @@ -0,0 +1,23 @@ +CONFIG_BT=y +CONFIG_LOG=y +CONFIG_ASSERT=y +CONFIG_BT_SMP=y + +CONFIG_BT_DEVICE_NAME="CIS test" + +CONFIG_BT_ISO_CENTRAL=y +CONFIG_BT_ISO_PERIPHERAL=y +CONFIG_BT_ISO_TX_BUF_COUNT=4 +CONFIG_BT_ISO_MAX_CHAN=4 +CONFIG_BT_ISO_TX_MTU=200 +CONFIG_BT_ISO_RX_MTU=200 + +CONFIG_BT_ISO_LOG_LEVEL_DBG=y + +# Controller Connected ISO configs +CONFIG_BT_CTLR_CENTRAL_ISO=y +CONFIG_BT_CTLR_PERIPHERAL_ISO=y +CONFIG_BT_CTLR_ISOAL_SOURCES=2 +CONFIG_BT_CTLR_ISOAL_SINKS=2 + +CONFIG_BT_CTLR_ISO_TX_BUFFERS=4 diff --git a/tests/bsim/bluetooth/host/iso/cis/src/cis_central.c b/tests/bsim/bluetooth/host/iso/cis/src/cis_central.c new file mode 100644 index 00000000000..c86741bcaf3 --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/cis/src/cis_central.c @@ -0,0 +1,421 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "common.h" + +#include +#include +#include + +#define ENQUEUE_COUNT 2 + +extern enum bst_result_t bst_result; +static struct bt_iso_chan iso_chans[CONFIG_BT_ISO_MAX_CHAN]; +static struct bt_iso_chan *default_chan = &iso_chans[0]; +static struct bt_iso_cig *cig; +static uint16_t seq_num; +static volatile size_t enqueue_cnt; +static uint32_t latency_ms = 10U; /* 10ms */ +static uint32_t interval_us = 10U * USEC_PER_MSEC; /* 10 ms */ +NET_BUF_POOL_FIXED_DEFINE(tx_pool, ENQUEUE_COUNT, BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), + CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); + +BUILD_ASSERT(CONFIG_BT_ISO_MAX_CHAN > 1, "CONFIG_BT_ISO_MAX_CHAN shall be at least 2"); + +CREATE_FLAG(flag_iso_connected); + +static void send_data_cb(struct k_work *work) +{ + static uint8_t buf_data[CONFIG_BT_ISO_TX_MTU]; + static size_t len_to_send = 1; + static bool data_initialized; + struct net_buf *buf; + int ret; + + if (!TEST_FLAG(flag_iso_connected)) { + /* TX has been aborted */ + return; + } + + if (!data_initialized) { + for (int i = 0; i < ARRAY_SIZE(buf_data); i++) { + buf_data[i] = (uint8_t)i; + } + + data_initialized = true; + } + + buf = net_buf_alloc(&tx_pool, K_FOREVER); + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); + + net_buf_add_mem(buf, buf_data, len_to_send); + + ret = bt_iso_chan_send(default_chan, buf, seq_num++, BT_ISO_TIMESTAMP_NONE); + if (ret < 0) { + printk("Failed to send ISO data (%d)\n", ret); + net_buf_unref(buf); + + /* Reschedule for next interval */ + k_work_reschedule(k_work_delayable_from_work(work), K_USEC(interval_us)); + + return; + } + + len_to_send++; + if (len_to_send > ARRAY_SIZE(buf_data)) { + len_to_send = 1; + } + + enqueue_cnt--; + if (enqueue_cnt > 0U) { + /* If we have more buffers available, we reschedule the workqueue item immediately + * to trigger another encode + TX, but without blocking this call for too long + */ + k_work_reschedule(k_work_delayable_from_work(work), K_NO_WAIT); + } +} +K_WORK_DELAYABLE_DEFINE(iso_send_work, send_data_cb); + +static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type, + struct net_buf_simple *ad) +{ + int err; + + err = bt_le_scan_stop(); + if (err) { + FAIL("Failed to stop scanning (err %d)\n", err); + + return; + } + + err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT, + &default_conn); + if (err) { + FAIL("Failed to create connection (err %d)\n", err); + + return; + } +} + +static void iso_connected(struct bt_iso_chan *chan) +{ + printk("ISO Channel %p connected\n", chan); + + seq_num = 0U; + enqueue_cnt = ENQUEUE_COUNT; + + /* Start send timer */ + k_work_schedule(&iso_send_work, K_MSEC(0)); + + SET_FLAG(flag_iso_connected); +} + +static void iso_disconnected(struct bt_iso_chan *chan, uint8_t reason) +{ + printk("ISO Channel %p disconnected (reason 0x%02x)\n", chan, reason); + + k_work_cancel_delayable(&iso_send_work); + + UNSET_FLAG(flag_iso_connected); +} + +static void sdu_sent_cb(struct bt_iso_chan *chan) +{ + int err; + + enqueue_cnt++; + + if (!TEST_FLAG(flag_iso_connected)) { + /* TX has been aborted */ + return; + } + + err = k_work_schedule(&iso_send_work, K_NO_WAIT); + if (err < 0) { + FAIL("Failed to schedule TX for chan %p: %d\n", chan, err); + } +} + +static void init(void) +{ + static struct bt_iso_chan_ops iso_ops = { + .connected = iso_connected, + .disconnected = iso_disconnected, + .sent = sdu_sent_cb, + }; + static struct bt_iso_chan_io_qos iso_tx = { + .sdu = CONFIG_BT_ISO_TX_MTU, + .phy = BT_GAP_LE_PHY_2M, + .rtn = 1, + .path = NULL, + }; + static struct bt_iso_chan_qos iso_qos = { + .tx = &iso_tx, + .rx = NULL, + }; + int err; + + err = bt_enable(NULL); + if (err != 0) { + FAIL("Bluetooth enable failed (err %d)\n", err); + + return; + } + + for (size_t i = 0U; i < ARRAY_SIZE(iso_chans); i++) { + iso_chans[i].ops = &iso_ops; + iso_chans[i].qos = &iso_qos; +#if defined(CONFIG_BT_SMP) + iso_chans[i].required_sec_level = BT_SECURITY_L2; +#endif /* CONFIG_BT_SMP */ + } +} + +static void set_cig_defaults(struct bt_iso_cig_param *param) +{ + param->cis_channels = &default_chan; + param->num_cis = 1U; + param->sca = BT_GAP_SCA_UNKNOWN; + param->packing = BT_ISO_PACKING_SEQUENTIAL; + param->framing = BT_ISO_FRAMING_UNFRAMED; + param->c_to_p_latency = latency_ms; /* ms */ + param->p_to_c_latency = latency_ms; /* ms */ + param->c_to_p_interval = interval_us; /* us */ + param->p_to_c_interval = interval_us; /* us */ + +} + +static void create_cig(void) +{ + struct bt_iso_cig_param param; + int err; + + set_cig_defaults(¶m); + + err = bt_iso_cig_create(¶m, &cig); + if (err != 0) { + FAIL("Failed to create CIG (%d)\n", err); + + return; + } +} + +static int reconfigure_cig_interval(struct bt_iso_cig_param *param) +{ + int err; + + /* Test modifying CIG parameter without any CIS */ + param->num_cis = 0U; + param->c_to_p_interval = 7500; /* us */ + param->p_to_c_interval = param->c_to_p_interval; + err = bt_iso_cig_reconfigure(cig, param); + if (err != 0) { + FAIL("Failed to reconfigure CIG to new interval (%d)\n", err); + + return err; + } + + err = bt_iso_cig_reconfigure(cig, param); + if (err != 0) { + FAIL("Failed to reconfigure CIG to same interval (%d)\n", err); + + return err; + } + + /* Test modifying to different values for both intervals */ + param->c_to_p_interval = 5000; /* us */ + param->p_to_c_interval = 2500; /* us */ + err = bt_iso_cig_reconfigure(cig, param); + if (err != 0) { + FAIL("Failed to reconfigure CIG to new interval (%d)\n", err); + + return err; + } + + return 0; +} + +static int reconfigure_cig_latency(struct bt_iso_cig_param *param) +{ + int err; + + /* Test modifying CIG latency without any CIS */ + param->num_cis = 0U; + param->c_to_p_latency = 20; /* ms */ + param->p_to_c_latency = param->c_to_p_latency; + err = bt_iso_cig_reconfigure(cig, param); + if (err != 0) { + FAIL("Failed to reconfigure CIG latency (%d)\n", err); + + return err; + } + + param->c_to_p_latency = 30; /* ms */ + param->p_to_c_latency = 40; /* ms */ + err = bt_iso_cig_reconfigure(cig, param); + if (err != 0) { + FAIL("Failed to reconfigure CIG for different latencies (%d)\n", err); + + return err; + } + + return 0; +} + +static void reconfigure_cig(void) +{ + struct bt_iso_chan *channels[2]; + struct bt_iso_cig_param param; + int err; + + for (size_t i = 0U; i < ARRAY_SIZE(channels); i++) { + channels[i] = &iso_chans[i]; + } + + set_cig_defaults(¶m); + + /* Test modifying existing CIS */ + default_chan->qos->tx->rtn++; + + err = bt_iso_cig_reconfigure(cig, ¶m); + if (err != 0) { + FAIL("Failed to reconfigure CIS to new RTN (%d)\n", err); + + return; + } + + /* Test modifying interval parameter */ + err = reconfigure_cig_interval(¶m); + if (err != 0) { + return; + } + + /* Test modifying latency parameter */ + err = reconfigure_cig_latency(¶m); + if (err != 0) { + return; + } + + /* Add CIS to the CIG and restore all other parameters */ + set_cig_defaults(¶m); + param.cis_channels = &channels[1]; + + err = bt_iso_cig_reconfigure(cig, ¶m); + if (err != 0) { + FAIL("Failed to reconfigure CIG with new CIS and original parameters (%d)\n", err); + + return; + } +} + +static void connect_acl(void) +{ + int err; + + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found); + if (err != 0) { + FAIL("Scanning failed to start (err %d)\n", err); + + return; + } + + WAIT_FOR_FLAG_SET(flag_connected); +} + +static void connect_cis(void) +{ + const struct bt_iso_connect_param connect_param = { + .acl = default_conn, + .iso_chan = default_chan, + }; + int err; + + err = bt_iso_chan_connect(&connect_param, 1); + if (err) { + FAIL("Failed to connect ISO (%d)\n", err); + + return; + } + + WAIT_FOR_FLAG_SET(flag_iso_connected); +} + +static void disconnect_cis(void) +{ + int err; + + err = bt_iso_chan_disconnect(default_chan); + if (err) { + FAIL("Failed to disconnect ISO (err %d)\n", err); + + return; + } + + WAIT_FOR_FLAG_UNSET(flag_iso_connected); +} + +static void disconnect_acl(void) +{ + int err; + + err = bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + if (err) { + FAIL("Failed to disconnect ACL (err %d)\n", err); + + return; + } + + WAIT_FOR_FLAG_UNSET(flag_connected); +} + +static void terminate_cig(void) +{ + int err; + + err = bt_iso_cig_terminate(cig); + if (err != 0) { + FAIL("Failed to terminate CIG (%d)\n", err); + + return; + } + + cig = NULL; +} + +static void test_main(void) +{ + init(); + create_cig(); + reconfigure_cig(); + connect_acl(); + connect_cis(); + + while (seq_num < 100U) { + k_sleep(K_USEC(interval_us)); + } + + disconnect_cis(); + disconnect_acl(); + terminate_cig(); + + PASS("Test passed\n"); +} + +static const struct bst_test_instance test_def[] = { + { + .test_id = "central", + .test_descr = "Central", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_main, + }, + BSTEST_END_MARKER, +}; + +struct bst_test_list *test_main_cis_central_install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, test_def); +} diff --git a/tests/bsim/bluetooth/host/iso/cis/src/cis_peripheral.c b/tests/bsim/bluetooth/host/iso/cis/src/cis_peripheral.c new file mode 100644 index 00000000000..fdaed6ef0ed --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/cis/src/cis_peripheral.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "common.h" + +#include +#include +#include + +extern enum bst_result_t bst_result; + +CREATE_FLAG(flag_iso_connected); +CREATE_FLAG(flag_data_received); + +static const struct bt_data ad[] = { + BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), +}; +static struct bt_iso_chan iso_chan; + +/** Print data as d_0 d_1 d_2 ... d_(n-2) d_(n-1) d_(n) to show the 3 first and 3 last octets + * + * Examples: + * 01 + * 0102 + * 010203 + * 01020304 + * 0102030405 + * 010203040506 + * 010203...050607 + * 010203...060708 + * etc. + */ +static void iso_print_data(uint8_t *data, size_t data_len) +{ + /* Maximum number of octets from each end of the data */ + const uint8_t max_octets = 3; + char data_str[35]; + size_t str_len; + + str_len = bin2hex(data, MIN(max_octets, data_len), data_str, sizeof(data_str)); + if (data_len > max_octets) { + if (data_len > (max_octets * 2)) { + static const char dots[] = "..."; + + strcat(&data_str[str_len], dots); + str_len += strlen(dots); + } + + str_len += bin2hex(data + (data_len - MIN(max_octets, data_len - max_octets)), + MIN(max_octets, data_len - max_octets), data_str + str_len, + sizeof(data_str) - str_len); + } + + printk("\t %s\n", data_str); +} + +static void iso_recv(struct bt_iso_chan *chan, const struct bt_iso_recv_info *info, + struct net_buf *buf) +{ + if (info->flags & BT_ISO_FLAGS_VALID) { + printk("Incoming data channel %p len %u\n", chan, buf->len); + iso_print_data(buf->data, buf->len); + SET_FLAG(flag_data_received); + } +} + +static void iso_connected(struct bt_iso_chan *chan) +{ + printk("ISO Channel %p connected\n", chan); + + SET_FLAG(flag_iso_connected); +} + +static void iso_disconnected(struct bt_iso_chan *chan, uint8_t reason) +{ + printk("ISO Channel %p disconnected (reason 0x%02x)\n", chan, reason); + + UNSET_FLAG(flag_iso_connected); +} + +static int iso_accept(const struct bt_iso_accept_info *info, struct bt_iso_chan **chan) +{ + printk("Incoming request from %p\n", (void *)info->acl); + + if (iso_chan.iso) { + FAIL("No channels available\n"); + + return -ENOMEM; + } + + *chan = &iso_chan; + + return 0; +} + +static void init(void) +{ + static struct bt_iso_chan_io_qos iso_rx = { + .sdu = CONFIG_BT_ISO_TX_MTU, + .path = NULL, + }; + static struct bt_iso_server iso_server = { +#if defined(CONFIG_BT_SMP) + .sec_level = BT_SECURITY_L2, +#endif /* CONFIG_BT_SMP */ + .accept = iso_accept, + }; + static struct bt_iso_chan_ops iso_ops = { + .recv = iso_recv, + .connected = iso_connected, + .disconnected = iso_disconnected, + }; + static struct bt_iso_chan_qos iso_qos = { + .rx = &iso_rx, + .tx = NULL, + }; + int err; + + err = bt_enable(NULL); + if (err) { + FAIL("Bluetooth enable failed (err %d)\n", err); + + return; + } + + iso_chan.ops = &iso_ops; + iso_chan.qos = &iso_qos; +#if defined(CONFIG_BT_SMP) + iso_chan.required_sec_level = BT_SECURITY_L2, +#endif /* CONFIG_BT_SMP */ + + err = bt_iso_server_register(&iso_server); + if (err) { + FAIL("Unable to register ISO server (err %d)\n", err); + + return; + } +} + +static void adv_connect(void) +{ + int err; + + err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0); + if (err) { + FAIL("Advertising failed to start (err %d)\n", err); + + return; + } + + printk("Advertising successfully started\n"); + + WAIT_FOR_FLAG_SET(flag_connected); +} + +static void test_main(void) +{ + init(); + adv_connect(); + WAIT_FOR_FLAG_SET(flag_iso_connected); + WAIT_FOR_FLAG_SET(flag_data_received); + WAIT_FOR_FLAG_UNSET(flag_iso_connected); + WAIT_FOR_FLAG_UNSET(flag_connected); + + PASS("Test passed\n"); +} + +static const struct bst_test_instance test_def[] = { + { + .test_id = "peripheral", + .test_descr = "Peripheral", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_main, + }, + BSTEST_END_MARKER, +}; + +struct bst_test_list *test_main_cis_peripheral_install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, test_def); +} diff --git a/tests/bsim/bluetooth/host/iso/cis/src/common.c b/tests/bsim/bluetooth/host/iso/cis/src/common.c new file mode 100644 index 00000000000..ef1a4e9f9dd --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/cis/src/common.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include +#include +#include +#include + +#include "common.h" + +extern enum bst_result_t bst_result; +struct bt_conn *default_conn; +atomic_t flag_connected; +atomic_t flag_conn_updated; + +static void connected(struct bt_conn *conn, uint8_t err) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + if (default_conn == NULL) { + default_conn = bt_conn_ref(conn); + } + + if (err != 0) { + bt_conn_unref(default_conn); + default_conn = NULL; + + FAIL("Failed to connect to %s (0x%02x)\n", addr, err); + + return; + } + + printk("Connected to %s\n", addr); + SET_FLAG(flag_connected); +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + if (conn != default_conn) { + return; + } + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + printk("Disconnected: %s (reason 0x%02x)\n", addr, reason); + + bt_conn_unref(default_conn); + default_conn = NULL; + UNSET_FLAG(flag_connected); + UNSET_FLAG(flag_conn_updated); +} + +static void conn_param_updated_cb(struct bt_conn *conn, uint16_t interval, uint16_t latency, + uint16_t timeout) +{ + printk("Connection parameter updated: %p 0x%04X (%u us), 0x%04X, 0x%04X\n", conn, interval, + BT_CONN_INTERVAL_TO_US(interval), latency, timeout); + + SET_FLAG(flag_conn_updated); +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected, + .disconnected = disconnected, + .le_param_updated = conn_param_updated_cb, +}; + +void test_init(void) +{ + bst_result = In_progress; + bst_ticker_set_next_tick_absolute(WAIT_TIME); +} + +void test_tick(bs_time_t HW_device_time) +{ + if (bst_result != Passed) { + FAIL("Test failed (not passed after %i us)\n", WAIT_TIME); + } +} diff --git a/tests/bsim/bluetooth/host/iso/cis/src/common.h b/tests/bsim/bluetooth/host/iso/cis/src/common.h new file mode 100644 index 00000000000..0b41515d223 --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/cis/src/common.h @@ -0,0 +1,49 @@ +/* + * Common functions and helpers for ISO tests + * + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include + +#include "bs_types.h" +#include "bs_tracing.h" +#include "bstests.h" + +#define CREATE_FLAG(flag) static atomic_t flag = (atomic_t) false +#define SET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) true) +#define UNSET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) false) +#define TEST_FLAG(flag) (atomic_get(&flag) == (atomic_t) true) +#define WAIT_FOR_FLAG_SET(flag) \ + while (!(bool)atomic_get(&flag)) { \ + (void)k_sleep(K_MSEC(1)); \ + } +#define WAIT_FOR_FLAG_UNSET(flag) \ + while ((bool)atomic_get(&flag)) { \ + (void)k_sleep(K_MSEC(1)); \ + } + +#define WAIT_TIME (30e6) /* 30 seconds*/ + +#define FAIL(...) \ + do { \ + bst_result = Failed; \ + bs_trace_error_time_line(__VA_ARGS__); \ + } while (0) + +#define PASS(...) \ + do { \ + bst_result = Passed; \ + bs_trace_info_time(1, __VA_ARGS__); \ + } while (0) + +extern struct bt_conn *default_conn; +extern atomic_t flag_connected; +extern atomic_t flag_conn_updated; + +void test_init(void); +void test_tick(bs_time_t HW_device_time); diff --git a/tests/bsim/bluetooth/host/iso/cis/src/main.c b/tests/bsim/bluetooth/host/iso/cis/src/main.c new file mode 100644 index 00000000000..0c30d4b3b45 --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/cis/src/main.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bstests.h" + +extern struct bst_test_list *test_main_cis_peripheral_install(struct bst_test_list *tests); +extern struct bst_test_list *test_main_cis_central_install(struct bst_test_list *tests); + +bst_test_install_t test_installers[] = { + test_main_cis_central_install, + test_main_cis_peripheral_install, + NULL, +}; + +int main(void) +{ + bst_main(); + return 0; +} diff --git a/tests/bsim/bluetooth/host/iso/cis/tests_scripts/_compile.sh b/tests/bsim/bluetooth/host/iso/cis/tests_scripts/_compile.sh new file mode 100755 index 00000000000..f1803766794 --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/cis/tests_scripts/_compile.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +set -eu +bash_source_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" + +source "${bash_source_dir}/_env.sh" + +: "${BSIM_OUT_PATH:?BSIM_OUT_PATH must be defined}" +: "${BSIM_COMPONENTS_PATH:?BSIM_COMPONENTS_PATH must be defined}" +: "${ZEPHYR_BASE:?ZEPHYR_BASE must be defined}" + +WORK_DIR="${WORK_DIR:-${ZEPHYR_BASE}/bsim_out}" +BOARD="${BOARD:-nrf52_bsim}" +BOARD_ROOT="${BOARD_ROOT:-${ZEPHYR_BASE}}" +INCR_BUILD=1 +mkdir -p ${WORK_DIR} + +west build -b nrf52_bsim +cp build/zephyr/zephyr.exe $central_exe diff --git a/tests/bsim/bluetooth/host/iso/cis/tests_scripts/_env.sh b/tests/bsim/bluetooth/host/iso/cis/tests_scripts/_env.sh new file mode 100755 index 00000000000..f595a2006e3 --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/cis/tests_scripts/_env.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +set -eu +bash_source_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" + +test_name="$(basename "$(realpath "$bash_source_dir/..")")" +bsim_bin="${BSIM_OUT_PATH}/bin" +verbosity_level=2 +BOARD="${BOARD:-nrf52_bsim}" +simulation_id="$test_name" +central_exe="${bsim_bin}/bs_${BOARD}_tests_bsim_bluetooth_host_iso_cis_prj_conf" +peripheral_exe="${central_exe}" diff --git a/tests/bsim/bluetooth/host/iso/cis/tests_scripts/cis.sh b/tests/bsim/bluetooth/host/iso/cis/tests_scripts/cis.sh new file mode 100755 index 00000000000..5cf55fde8e3 --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/cis/tests_scripts/cis.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# Copyright (c) 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +simulation_id="iso_cis" +verbosity_level=2 +EXECUTE_TIMEOUT=120 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_host_iso_cis_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_host_iso_cis_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=30e6 $@ + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/host/l2cap/credits/src/main.c b/tests/bsim/bluetooth/host/l2cap/credits/src/main.c index ea44dbccd67..570693ae98b 100644 --- a/tests/bsim/bluetooth/host/l2cap/credits/src/main.c +++ b/tests/bsim/bluetooth/host/l2cap/credits/src/main.c @@ -135,7 +135,8 @@ static struct bt_l2cap_chan_ops ops = { .sent = sent_cb, }; -int server_accept_cb(struct bt_conn *conn, struct bt_l2cap_chan **chan) +int server_accept_cb(struct bt_conn *conn, struct bt_l2cap_server *server, + struct bt_l2cap_chan **chan) { struct bt_l2cap_le_chan *le_chan = &test_ctx.le_chan; diff --git a/tests/bsim/bluetooth/host/l2cap/credits_seg_recv/src/main.c b/tests/bsim/bluetooth/host/l2cap/credits_seg_recv/src/main.c index 3f941851a21..deead1a8b10 100644 --- a/tests/bsim/bluetooth/host/l2cap/credits_seg_recv/src/main.c +++ b/tests/bsim/bluetooth/host/l2cap/credits_seg_recv/src/main.c @@ -141,7 +141,8 @@ static struct bt_l2cap_chan_ops ops = { .sent = sent_cb, }; -int server_accept_cb(struct bt_conn *conn, struct bt_l2cap_chan **chan) +int server_accept_cb(struct bt_conn *conn, struct bt_l2cap_server *server, + struct bt_l2cap_chan **chan) { struct bt_l2cap_le_chan *le_chan = &test_ctx.le_chan; diff --git a/tests/bsim/bluetooth/host/l2cap/general/src/main_l2cap_ecred.c b/tests/bsim/bluetooth/host/l2cap/general/src/main_l2cap_ecred.c index e7f6589bef6..d89e71d327f 100644 --- a/tests/bsim/bluetooth/host/l2cap/general/src/main_l2cap_ecred.c +++ b/tests/bsim/bluetooth/host/l2cap/general/src/main_l2cap_ecred.c @@ -261,7 +261,8 @@ static void disconnect_all_channels(void) } } -static int accept(struct bt_conn *conn, struct bt_l2cap_chan **l2cap_chan) +static int accept(struct bt_conn *conn, struct bt_l2cap_server *server, + struct bt_l2cap_chan **l2cap_chan) { struct channel *chan; diff --git a/tests/bsim/bluetooth/host/l2cap/send_on_connect/src/main_l2cap_send_on_connect.c b/tests/bsim/bluetooth/host/l2cap/send_on_connect/src/main_l2cap_send_on_connect.c index b214928d036..485c97c11dc 100644 --- a/tests/bsim/bluetooth/host/l2cap/send_on_connect/src/main_l2cap_send_on_connect.c +++ b/tests/bsim/bluetooth/host/l2cap/send_on_connect/src/main_l2cap_send_on_connect.c @@ -75,7 +75,8 @@ static const struct bt_l2cap_chan_ops l2cap_ops = { static struct bt_l2cap_le_chan channel; -static int accept(struct bt_conn *conn, struct bt_l2cap_chan **l2cap_chan) +static int accept(struct bt_conn *conn, struct bt_l2cap_server *server, + struct bt_l2cap_chan **l2cap_chan) { channel.chan.ops = &l2cap_ops; *l2cap_chan = &channel.chan; diff --git a/tests/bsim/bluetooth/host/l2cap/split/dut/src/main.c b/tests/bsim/bluetooth/host/l2cap/split/dut/src/main.c index db7a45dfa48..72818bee5c2 100644 --- a/tests/bsim/bluetooth/host/l2cap/split/dut/src/main.c +++ b/tests/bsim/bluetooth/host/l2cap/split/dut/src/main.c @@ -89,7 +89,8 @@ static struct bt_l2cap_chan_ops ops = { .sent = sent_cb, }; -int server_accept_cb(struct bt_conn *conn, struct bt_l2cap_chan **chan) +int server_accept_cb(struct bt_conn *conn, struct bt_l2cap_server *server, + struct bt_l2cap_chan **chan) { struct bt_l2cap_le_chan *le_chan = &test_chan; diff --git a/tests/bsim/bluetooth/host/l2cap/stress/src/main.c b/tests/bsim/bluetooth/host/l2cap/stress/src/main.c index 0af76643a34..244d69b7fa2 100644 --- a/tests/bsim/bluetooth/host/l2cap/stress/src/main.c +++ b/tests/bsim/bluetooth/host/l2cap/stress/src/main.c @@ -206,7 +206,8 @@ struct test_ctx *alloc_test_context(void) return NULL; } -int server_accept_cb(struct bt_conn *conn, struct bt_l2cap_chan **chan) +int server_accept_cb(struct bt_conn *conn, struct bt_l2cap_server *server, + struct bt_l2cap_chan **chan) { struct test_ctx *ctx = NULL; diff --git a/tests/bsim/bluetooth/host/l2cap/userdata/src/main_l2cap_userdata.c b/tests/bsim/bluetooth/host/l2cap/userdata/src/main_l2cap_userdata.c index 9230089dd95..46d1389dee9 100644 --- a/tests/bsim/bluetooth/host/l2cap/userdata/src/main_l2cap_userdata.c +++ b/tests/bsim/bluetooth/host/l2cap/userdata/src/main_l2cap_userdata.c @@ -48,7 +48,8 @@ static const struct bt_l2cap_chan_ops l2cap_ops = { static struct bt_l2cap_le_chan channel; -static int accept(struct bt_conn *conn, struct bt_l2cap_chan **l2cap_chan) +static int accept(struct bt_conn *conn, struct bt_l2cap_server *server, + struct bt_l2cap_chan **l2cap_chan) { channel.chan.ops = &l2cap_ops; *l2cap_chan = &channel.chan; diff --git a/tests/bsim/bluetooth/host/misc/disconnect/common/sync.c b/tests/bsim/bluetooth/host/misc/disconnect/common/sync.c new file mode 100644 index 00000000000..d66a01832b3 --- /dev/null +++ b/tests/bsim/bluetooth/host/misc/disconnect/common/sync.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "argparse.h" +#include "bs_types.h" +#include "bs_tracing.h" +#include "time_machine.h" +#include "bstests.h" +#include "bs_pc_backchannel.h" + +#include +LOG_MODULE_REGISTER(sync, LOG_LEVEL_INF); + +#define CHANNEL_ID 0 +#define MSG_SIZE 1 + +int backchannel_init(void) +{ + uint device_number = get_device_nbr(); + uint peer_number = device_number ^ 1; + uint device_numbers[] = { peer_number }; + uint channel_numbers[] = { CHANNEL_ID }; + uint *ch; + + ch = bs_open_back_channel(device_number, device_numbers, channel_numbers, + ARRAY_SIZE(channel_numbers)); + + if (!ch) { + return -1; + } + + return 0; +} + +void backchannel_sync_send(void) +{ + uint8_t sync_msg[MSG_SIZE] = { get_device_nbr() }; + + LOG_INF("Sending sync"); + bs_bc_send_msg(CHANNEL_ID, sync_msg, ARRAY_SIZE(sync_msg)); +} + +void backchannel_sync_wait(void) +{ + uint8_t sync_msg[MSG_SIZE]; + + while (true) { + if (bs_bc_is_msg_received(CHANNEL_ID) > 0) { + bs_bc_receive_msg(CHANNEL_ID, sync_msg, ARRAY_SIZE(sync_msg)); + if (sync_msg[0] != get_device_nbr()) { + /* Received a message from another device, exit */ + break; + } + } + + k_sleep(K_MSEC(1)); + } + + LOG_INF("Sync received"); +} diff --git a/tests/bsim/bluetooth/host/misc/disconnect/common/sync.h b/tests/bsim/bluetooth/host/misc/disconnect/common/sync.h new file mode 100644 index 00000000000..aa3ef4e48ce --- /dev/null +++ b/tests/bsim/bluetooth/host/misc/disconnect/common/sync.h @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +int backchannel_init(void); +void backchannel_sync_send(void); +void backchannel_sync_wait(void); diff --git a/tests/bsim/bluetooth/host/misc/disconnect/common/utils.h b/tests/bsim/bluetooth/host/misc/disconnect/common/utils.h new file mode 100644 index 00000000000..d5be7e04bb3 --- /dev/null +++ b/tests/bsim/bluetooth/host/misc/disconnect/common/utils.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_tracing.h" +#include "bs_types.h" +#include "bstests.h" + +#define BS_SECONDS(dur_sec) ((bs_time_t)dur_sec * USEC_PER_SEC) +#define TEST_TIMEOUT_SIMULATED BS_SECONDS(10) + +extern enum bst_result_t bst_result; + +#define DECLARE_FLAG(flag) extern atomic_t flag +#define DEFINE_FLAG(flag) atomic_t flag = (atomic_t) false +#define SET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) true) +#define UNSET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) false) + +#define WAIT_FOR_EXPR(var, expr) \ + while (atomic_get(&var) expr) { \ + (void)k_sleep(K_MSEC(1)); \ + } +#define WAIT_FOR_VAL(var, val) \ + while (atomic_get(&var) != val) { \ + (void)k_sleep(K_MSEC(1)); \ + } +#define WAIT_FOR_FLAG(flag) \ + while (!(bool)atomic_get(&flag)) { \ + (void)k_sleep(K_MSEC(1)); \ + } +#define WAIT_FOR_FLAG_UNSET(flag) \ + while ((bool)atomic_get(&flag)) { \ + (void)k_sleep(K_MSEC(1)); \ + } +#define TAKE_FLAG(flag) \ + while (!(bool)atomic_cas(&flag, true, false)) { \ + (void)k_sleep(K_MSEC(1)); \ + } + +#define ASSERT(expr, ...) \ + do { \ + if (!(expr)) { \ + FAIL(__VA_ARGS__); \ + } \ + } while (0) + +#define FAIL(...) \ + do { \ + bst_result = Failed; \ + bs_trace_error_time_line(__VA_ARGS__); \ + } while (0) + +#define PASS(...) \ + do { \ + bst_result = Passed; \ + bs_trace_info_time(1, __VA_ARGS__); \ + } while (0) + +#define HVX_HANDLE 0x0012 +#define INDICATION_PAYLOAD "indication" +#define NOTIFICATION_PAYLOAD "notification" diff --git a/tests/bsim/bluetooth/host/misc/disconnect/dut/CMakeLists.txt b/tests/bsim/bluetooth/host/misc/disconnect/dut/CMakeLists.txt new file mode 100644 index 00000000000..9546e14eeb2 --- /dev/null +++ b/tests/bsim/bluetooth/host/misc/disconnect/dut/CMakeLists.txt @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(bsim_test_disconnect_dut) + +target_sources(app PRIVATE + src/main.c + ../common/sync.c +) + +zephyr_include_directories( + ../common/ + ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ + ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ +) diff --git a/tests/bsim/bluetooth/host/misc/disconnect/dut/prj.conf b/tests/bsim/bluetooth/host/misc/disconnect/dut/prj.conf new file mode 100644 index 00000000000..4da2a5c3504 --- /dev/null +++ b/tests/bsim/bluetooth/host/misc/disconnect/dut/prj.conf @@ -0,0 +1,38 @@ +CONFIG_LOG=y +CONFIG_ASSERT=y + +CONFIG_BT=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_DEVICE_NAME="Sequential" + +CONFIG_BT_GATT_CLIENT=y +CONFIG_BT_GATT_ENFORCE_SUBSCRIPTION=n + +# Replace `Execute` with `gdb --args` in the shell script +# and get a nice backtrace on assert +CONFIG_ARCH_POSIX_TRAP_ON_FATAL=y + +# Prepend logs with thread names +CONFIG_THREAD_NAME=y +CONFIG_LOG_THREAD_ID_PREFIX=y + +# Enable those as needed +# CONFIG_BT_L2CAP_LOG_LEVEL_DBG=y +# CONFIG_BT_ATT_LOG_LEVEL_DBG=y +# CONFIG_BT_GATT_LOG_LEVEL_DBG=y + +# Allow whole L2CAP PDUs to fit on-air +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_ACL_RX_SIZE=251 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_BT_DATA_LEN_UPDATE=y +CONFIG_BT_USER_DATA_LEN_UPDATE=y + +# Disable auto-initiated procedures so they don't +# mess with the test's execution. +CONFIG_BT_AUTO_PHY_UPDATE=n +CONFIG_BT_AUTO_DATA_LEN_UPDATE=n +CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=n + +CONFIG_BT_MAX_CONN=1 diff --git a/tests/bsim/bluetooth/host/misc/disconnect/dut/src/main.c b/tests/bsim/bluetooth/host/misc/disconnect/dut/src/main.c new file mode 100644 index 00000000000..90a70c30c52 --- /dev/null +++ b/tests/bsim/bluetooth/host/misc/disconnect/dut/src/main.c @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" +#include "sync.h" +#include "bstests.h" + +#include +LOG_MODULE_REGISTER(dut, LOG_LEVEL_INF); + +DEFINE_FLAG(is_connected); +DEFINE_FLAG(is_subscribed); +DEFINE_FLAG(flag_data_length_updated); + +static atomic_t notifications; + +/* Defined in hci_core.c */ +extern k_tid_t bt_testing_tx_tid_get(void); + +static struct bt_conn *dconn; + +static void connected(struct bt_conn *conn, uint8_t conn_err) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + if (conn_err) { + FAIL("Failed to connect to %s (%u)", addr, conn_err); + return; + } + + LOG_INF("%s: %s", __func__, addr); + + dconn = bt_conn_ref(conn); + SET_FLAG(is_connected); +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + LOG_INF("%s: %p %s (reason 0x%02x)", __func__, conn, addr, reason); + + bt_conn_unref(dconn); + UNSET_FLAG(is_connected); +} + +static void data_len_updated(struct bt_conn *conn, + struct bt_conn_le_data_len_info *info) +{ + LOG_DBG("Data length updated: TX %d RX %d", + info->tx_max_len, + info->rx_max_len); + SET_FLAG(flag_data_length_updated); +} + +static void do_dlu(void) +{ + int err; + struct bt_conn_le_data_len_param param; + + param.tx_max_len = CONFIG_BT_CTLR_DATA_LENGTH_MAX; + param.tx_max_time = 2500; + + err = bt_conn_le_data_len_update(dconn, ¶m); + ASSERT(err == 0, "Can't update data length (err %d)\n", err); + + WAIT_FOR_FLAG(flag_data_length_updated); +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected, + .disconnected = disconnected, + .le_data_len_updated = data_len_updated, +}; + +static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type, + struct net_buf_simple *ad) +{ + char str[BT_ADDR_LE_STR_LEN]; + struct bt_le_conn_param *param; + struct bt_conn *conn; + int err; + + err = bt_le_scan_stop(); + if (err) { + FAIL("Stop LE scan failed (err %d)", err); + return; + } + + bt_addr_le_to_str(addr, str, sizeof(str)); + LOG_DBG("Connecting to %s", str); + + param = BT_LE_CONN_PARAM_DEFAULT; + err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, param, &conn); + if (err) { + FAIL("Create conn failed (err %d)", err); + return; + } +} + +static void connect(void) +{ + int err; + struct bt_le_scan_param scan_param = { + .type = BT_LE_SCAN_TYPE_ACTIVE, + .options = BT_LE_SCAN_OPT_NONE, + .interval = BT_GAP_SCAN_FAST_INTERVAL, + .window = BT_GAP_SCAN_FAST_WINDOW, + }; + + UNSET_FLAG(is_connected); + + err = bt_le_scan_start(&scan_param, device_found); + ASSERT(!err, "Scanning failed to start (err %d)\n", err); + + LOG_DBG("Central initiating connection..."); + WAIT_FOR_FLAG(is_connected); + LOG_INF("Connected as central"); + + /* No security support on the tinyhost unfortunately */ +} + +static uint8_t notified(struct bt_conn *conn, struct bt_gatt_subscribe_params *params, + const void *data, uint16_t length) +{ + static uint8_t notification[] = NOTIFICATION_PAYLOAD; + static uint8_t indication[] = INDICATION_PAYLOAD; + bool is_nfy; + + LOG_HEXDUMP_DBG(data, length, "HVx data"); + + if (length == 0) { + /* The host's backward way of telling us we are unsubscribed + * from this characteristic. + */ + LOG_DBG("Unsubscribed"); + return BT_GATT_ITER_CONTINUE; + } + + ASSERT(length >= sizeof(indication), "Unexpected data\n"); + ASSERT(length <= sizeof(notification), "Unexpected data\n"); + + is_nfy = memcmp(data, notification, length) == 0; + + LOG_INF("%s from 0x%x", is_nfy ? "notified" : "indicated", + params->value_handle); + + ASSERT(is_nfy, "Unexpected indication\n"); + + atomic_inc(¬ifications); + + if (atomic_get(¬ifications) == 3) { + LOG_INF("##################### BRB.."); + backchannel_sync_send(); + + /* Make scheduler rotate us in and out multiple times */ + for (int i = 0; i < 10; i++) { + LOG_DBG("sleep"); + k_sleep(K_MSEC(100)); + LOG_DBG("sleep"); + } + + LOG_INF("##################### ..back to work"); + } + + return BT_GATT_ITER_CONTINUE; +} + +static void subscribed(struct bt_conn *conn, + uint8_t err, + struct bt_gatt_subscribe_params *params) +{ + ASSERT(!err, "Subscribe failed (err %d)\n", err); + + ASSERT(params, "params is NULL\n"); + + SET_FLAG(is_subscribed); + /* spoiler: tester doesn't really have attributes */ + LOG_INF("Subscribed to Tester attribute"); +} + +void subscribe(void) +{ + int err; + + /* Handle values don't matter, as long as they match on the tester */ + static struct bt_gatt_subscribe_params params = { + .notify = notified, + .subscribe = subscribed, + .value = BT_GATT_CCC_NOTIFY | BT_GATT_CCC_INDICATE, + .value_handle = HVX_HANDLE, + .ccc_handle = (HVX_HANDLE + 1), + }; + + err = bt_gatt_subscribe(dconn, ¶ms); + ASSERT(!err, "Subscribe failed (err %d)\n", err); + + WAIT_FOR_FLAG(is_subscribed); +} + +void test_procedure_0(void) +{ + ASSERT(backchannel_init() == 0, "Failed to open backchannel\n"); + + LOG_DBG("Test start: ATT disconnect protocol"); + int err; + + err = bt_enable(NULL); + ASSERT(err == 0, "Can't enable Bluetooth (err %d)\n", err); + LOG_DBG("Central: Bluetooth initialized."); + + /* Test purpose: + * Make sure the host handles long blocking in notify callbacks + * gracefully, especially in the case of a disconnect while waiting. + * + * Test procedure: + * + * [setup] + * - connect ACL, DUT is central and GATT client + * - update data length (tinyhost doens't have recombination) + * - dut: subscribe to NOTIFY on tester CHRC + * + * [procedure] + * - tester: start periodic notifications + * - dut: wait 10x 100ms in notification RX callback + * - tester: disconnect (not gracefully) while DUT is waiting + * -> simulates a power or range loss situation + * - dut: exit notification callback + * - dut: wait for `disconnected` conn callback + * + * [verdict] + * - The DUT gets the `disconnected` callback, no hanging or timeouts. + */ + connect(); + subscribe(); + + do_dlu(); + + WAIT_FOR_EXPR(notifications, < 4); + + WAIT_FOR_FLAG_UNSET(is_connected); + + LOG_INF("##################### END TEST #####################"); + + PASS("DUT exit\n"); +} + +void test_tick(bs_time_t HW_device_time) +{ + bs_trace_debug_time(0, "Simulation ends now.\n"); + if (bst_result != Passed) { + bst_result = Failed; + bs_trace_error("Test did not pass before simulation ended.\n"); + } +} + +void test_init(void) +{ + bst_ticker_set_next_tick_absolute(TEST_TIMEOUT_SIMULATED); + bst_result = In_progress; +} + +static const struct bst_test_instance test_to_add[] = { + { + .test_id = "dut", + .test_pre_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_procedure_0, + }, + BSTEST_END_MARKER, +}; + +static struct bst_test_list *install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, test_to_add); +}; + +bst_test_install_t test_installers[] = {install, NULL}; + +int main(void) +{ + bst_main(); + + return 0; +} diff --git a/tests/bsim/bluetooth/host/misc/disconnect/scripts/_compile.sh b/tests/bsim/bluetooth/host/misc/disconnect/scripts/_compile.sh new file mode 100755 index 00000000000..555faa068f2 --- /dev/null +++ b/tests/bsim/bluetooth/host/misc/disconnect/scripts/_compile.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Path checks, etc +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +BOARD="${BOARD:-nrf52_bsim}" +dut_exe="bs_${BOARD}_tests_bsim_bluetooth_host_misc_disconnect_dut_prj_conf" +tester_exe="bs_${BOARD}_tests_bsim_bluetooth_host_misc_disconnect_tester_prj_conf" + +# terminate running simulations (if any) +${BSIM_COMPONENTS_PATH}/common/stop_bsim.sh + +west build -b ${BOARD} -d build_dut dut && \ + cp build_dut/zephyr/zephyr.exe "${BSIM_OUT_PATH}/bin/${dut_exe}" && +west build -b ${BOARD} -d build_tester tester && \ + cp build_tester/zephyr/zephyr.exe "${BSIM_OUT_PATH}/bin/${tester_exe}" diff --git a/tests/bsim/bluetooth/host/misc/disconnect/scripts/disconnect.sh b/tests/bsim/bluetooth/host/misc/disconnect/scripts/disconnect.sh new file mode 100755 index 00000000000..4380119a3e7 --- /dev/null +++ b/tests/bsim/bluetooth/host/misc/disconnect/scripts/disconnect.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +BOARD="${BOARD:-nrf52_bsim}" +dut_exe="bs_${BOARD}_tests_bsim_bluetooth_host_misc_disconnect_dut_prj_conf" +tester_exe="bs_${BOARD}_tests_bsim_bluetooth_host_misc_disconnect_tester_prj_conf" + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +test_name="misc_disconnect" +simulation_id="${test_name}" +verbosity_level=2 +EXECUTE_TIMEOUT=30 +sim_length_us=10e6 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_2G4_phy_v1 \ + -v=${verbosity_level} -s="${simulation_id}" -D=2 -sim_length=${sim_length_us} $@ + +Execute "./$tester_exe" \ + -v=${verbosity_level} -s="${simulation_id}" -d=1 -testid=tester -RealEncryption=0 -rs=100 + +Execute "./$dut_exe" \ + -v=${verbosity_level} -s="${simulation_id}" -d=0 -testid=dut -RealEncryption=0 + +# wait_for_background_jobs, but doesn't exit on error +exit_code=0 +for process_id in $_process_ids; do +wait $process_id || let "exit_code=$?" +done + +# Make pcaps +for j in {0..1}; do + i=$(printf '%02i' $j) + + ${BSIM_OUT_PATH}/components/ext_2G4_phy_v1/dump_post_process/csv2pcap -o \ + ${BSIM_OUT_PATH}/results/${simulation_id}/Trace_$i.Tx.pcap \ + ${BSIM_OUT_PATH}/results/${simulation_id}/d_2G4_$i.Tx.csv + + ${BSIM_OUT_PATH}/components/ext_2G4_phy_v1/dump_post_process/csv2pcap -o \ + ${BSIM_OUT_PATH}/results/${simulation_id}/Trace_$i.Rx.pcap \ + ${BSIM_OUT_PATH}/results/${simulation_id}/d_2G4_$i.Rx.csv + + echo "${BSIM_OUT_PATH}/results/${simulation_id}/Trace_$i.Tx.pcap" + echo "${BSIM_OUT_PATH}/results/${simulation_id}/Trace_$i.Rx.pcap" +done diff --git a/tests/bsim/bluetooth/host/misc/disconnect/tester/CMakeLists.txt b/tests/bsim/bluetooth/host/misc/disconnect/tester/CMakeLists.txt new file mode 100644 index 00000000000..e3a567377ef --- /dev/null +++ b/tests/bsim/bluetooth/host/misc/disconnect/tester/CMakeLists.txt @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(bsim_test_disconnect_tester) + +target_sources(app PRIVATE + src/main.c + ../common/sync.c +) + +zephyr_include_directories( + ../common/ + ${ZEPHYR_BASE}/subsys/bluetooth/common/ + ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ + ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ +) diff --git a/tests/bsim/bluetooth/host/misc/disconnect/tester/prj.conf b/tests/bsim/bluetooth/host/misc/disconnect/tester/prj.conf new file mode 100644 index 00000000000..461c7dd5029 --- /dev/null +++ b/tests/bsim/bluetooth/host/misc/disconnect/tester/prj.conf @@ -0,0 +1,19 @@ +CONFIG_LOG=y +CONFIG_ASSERT=y + +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_HCI_RAW_RESERVE=1 +CONFIG_BT_MAX_CONN=1 + +CONFIG_BT_BUF_CMD_TX_COUNT=10 + +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_CMD_TX_SIZE=255 +CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=255 + +# Allow whole L2CAP PDUs to fit on-air +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_ACL_RX_SIZE=251 +CONFIG_BT_DATA_LEN_UPDATE=y +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 diff --git a/tests/bsim/bluetooth/host/misc/disconnect/tester/src/main.c b/tests/bsim/bluetooth/host/misc/disconnect/tester/src/main.c new file mode 100644 index 00000000000..4755a55d4d3 --- /dev/null +++ b/tests/bsim/bluetooth/host/misc/disconnect/tester/src/main.c @@ -0,0 +1,627 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "common/bt_str.h" + +#include "host/conn_internal.h" +#include "host/l2cap_internal.h" + +#include "utils.h" +#include "sync.h" +#include "bstests.h" +#include "NRF_HWLowL.h" /* for hwll_disconnect_phy(); */ + +#include +LOG_MODULE_REGISTER(bt_tinyhost, LOG_LEVEL_INF); + +#define BT_ATT_OP_MTU_REQ 0x02 +#define BT_ATT_OP_MTU_RSP 0x03 +#define BT_ATT_OP_WRITE_REQ 0x12 +#define BT_ATT_OP_WRITE_RSP 0x13 +#define BT_ATT_OP_NOTIFY 0x1b +#define BT_ATT_OP_INDICATE 0x1d +#define BT_ATT_OP_CONFIRM 0x1e +#define BT_ATT_OP_WRITE_CMD 0x52 +#define BT_L2CAP_CID_ATT 0x0004 + +DEFINE_FLAG(is_connected); +DEFINE_FLAG(flag_data_length_updated); + +static K_FIFO_DEFINE(rx_queue); + +#define CMD_BUF_SIZE MAX(BT_BUF_EVT_RX_SIZE, BT_BUF_CMD_TX_SIZE) +NET_BUF_POOL_FIXED_DEFINE(hci_cmd_pool, CONFIG_BT_BUF_CMD_TX_COUNT, + CMD_BUF_SIZE, 8, NULL); + +static K_SEM_DEFINE(cmd_sem, 1, 1); +static struct k_sem acl_pkts; +static uint16_t conn_handle; + +static volatile uint16_t active_opcode = 0xFFFF; +static struct net_buf *cmd_rsp; + +struct net_buf *bt_hci_cmd_create(uint16_t opcode, uint8_t param_len) +{ + struct bt_hci_cmd_hdr *hdr; + struct net_buf *buf; + + LOG_DBG("opcode 0x%04x param_len %u", opcode, param_len); + + buf = net_buf_alloc(&hci_cmd_pool, K_FOREVER); + ASSERT(buf, "failed allocation"); + + LOG_DBG("buf %p", buf); + + net_buf_reserve(buf, BT_BUF_RESERVE); + + bt_buf_set_type(buf, BT_BUF_CMD); + + hdr = net_buf_add(buf, sizeof(*hdr)); + hdr->opcode = sys_cpu_to_le16(opcode); + hdr->param_len = param_len; + + return buf; +} + +static void handle_cmd_complete(struct net_buf *buf) +{ + struct bt_hci_evt_hdr *hdr; + uint8_t status, ncmd; + uint16_t opcode; + struct net_buf_simple_state state; + + net_buf_simple_save(&buf->b, &state); + + hdr = net_buf_pull_mem(buf, sizeof(*hdr)); + + if (hdr->evt == BT_HCI_EVT_CMD_COMPLETE) { + struct bt_hci_evt_cmd_complete *evt; + + evt = net_buf_pull_mem(buf, sizeof(*evt)); + status = 0; + ncmd = evt->ncmd; + opcode = sys_le16_to_cpu(evt->opcode); + + } else if (hdr->evt == BT_HCI_EVT_CMD_STATUS) { + struct bt_hci_evt_cmd_status *evt; + + evt = net_buf_pull_mem(buf, sizeof(*evt)); + status = buf->data[0]; + ncmd = evt->ncmd; + opcode = sys_le16_to_cpu(evt->opcode); + + } else { + FAIL("unhandled event 0x%x", hdr->evt); + } + + LOG_DBG("opcode 0x%04x status %x", opcode, status); + + ASSERT(status == 0x00, "cmd status: %x", status); + + ASSERT(active_opcode == opcode, "unexpected opcode %x != %x", active_opcode, opcode); + + if (active_opcode) { + active_opcode = 0xFFFF; + cmd_rsp = net_buf_ref(buf); + net_buf_simple_restore(&buf->b, &state); + } + + if (ncmd) { + k_sem_give(&cmd_sem); + } +} + +static void handle_meta_event(struct net_buf *buf) +{ + uint8_t code = buf->data[2]; + + switch (code) { + case BT_HCI_EVT_LE_ENH_CONN_COMPLETE: + case BT_HCI_EVT_LE_ENH_CONN_COMPLETE_V2: + conn_handle = sys_get_le16(&buf->data[4]); + LOG_DBG("connected: handle: %d", conn_handle); + SET_FLAG(is_connected); + break; + case BT_HCI_EVT_LE_DATA_LEN_CHANGE: + SET_FLAG(flag_data_length_updated); + break; + case BT_HCI_EVT_LE_CHAN_SEL_ALGO: + /* do nothing */ + break; + default: + LOG_ERR("unhandled meta event %x", code); + LOG_HEXDUMP_ERR(buf->data, buf->len, "HCI META EVT"); + } +} + +static void handle_ncp(struct net_buf *buf) +{ + struct bt_hci_evt_num_completed_packets *evt; + struct bt_hci_evt_hdr *hdr; + uint16_t handle, count; + + hdr = net_buf_pull_mem(buf, sizeof(*hdr)); + + evt = (void *)buf->data; + handle = sys_le16_to_cpu(evt->h[0].handle); + count = sys_le16_to_cpu(evt->h[0].count); + + LOG_DBG("sent %d packets", count); + + while (count--) { + k_sem_give(&acl_pkts); + } +} + +struct net_buf *alloc_l2cap_pdu(void); +static void send_l2cap_packet(struct net_buf *buf, uint16_t cid); + +static void send_write_rsp(void) +{ + struct net_buf *buf = alloc_l2cap_pdu(); + + net_buf_add_u8(buf, BT_ATT_OP_WRITE_RSP); + send_l2cap_packet(buf, BT_L2CAP_CID_ATT); +} + +static void handle_att_write(struct net_buf *buf) +{ + uint16_t handle = net_buf_pull_le16(buf); + + LOG_INF("Got write for 0x%04x len %d", handle, buf->len); + LOG_HEXDUMP_DBG(buf->data, buf->len, "payload"); + + static uint8_t ccc_write[2] = {0x03, 0x00}; + + ASSERT(buf->len == 2, "unexpected write length: %d\n", buf->len); + ASSERT(memcmp(buf->data, ccc_write, sizeof(ccc_write)) == 0, "bad data\n"); + + send_write_rsp(); +} + +static void handle_att(struct net_buf *buf) +{ + uint8_t op = net_buf_pull_u8(buf); + + switch (op) { + case BT_ATT_OP_WRITE_REQ: + handle_att_write(buf); + return; + case BT_ATT_OP_MTU_RSP: + LOG_INF("got ATT MTU RSP"); + return; + default: + LOG_HEXDUMP_ERR(buf->data, buf->len, "payload"); + FAIL("unhandled opcode %x\n", op); + return; + } +} + +static void handle_l2cap(struct net_buf *buf) +{ + struct bt_l2cap_hdr *hdr; + uint16_t cid; + + hdr = net_buf_pull_mem(buf, sizeof(*hdr)); + cid = sys_le16_to_cpu(hdr->cid); + + LOG_DBG("Packet for CID %u len %u", cid, buf->len); + LOG_HEXDUMP_DBG(buf->data, buf->len, "l2cap"); + + /* Make sure we don't have to recombine packets */ + ASSERT(buf->len == hdr->len, "buflen = %d != hdrlen %d", + buf->len, hdr->len); + + ASSERT(cid == BT_L2CAP_CID_ATT, "We only support (U)ATT"); + + /* (U)ATT PDU */ + handle_att(buf); +} + +static void handle_acl(struct net_buf *buf) +{ + struct bt_hci_acl_hdr *hdr; + uint16_t len, handle; + uint8_t flags; + + hdr = net_buf_pull_mem(buf, sizeof(*hdr)); + len = sys_le16_to_cpu(hdr->len); + handle = sys_le16_to_cpu(hdr->handle); + + flags = bt_acl_flags(handle); + handle = bt_acl_handle(handle); + + ASSERT(flags == BT_ACL_START, + "Fragmentation not supported"); + + LOG_DBG("ACL: conn %d len %d flags %d", handle, len, flags); + LOG_HEXDUMP_DBG(buf->data, buf->len, "HCI ACL"); + + handle_l2cap(buf); +} + +static void recv(struct net_buf *buf) +{ + LOG_HEXDUMP_DBG(buf->data, buf->len, "HCI RX"); + + uint8_t code = buf->data[0]; + + if (bt_buf_get_type(buf) == BT_BUF_EVT) { + switch (code) { + case BT_HCI_EVT_CMD_COMPLETE: + case BT_HCI_EVT_CMD_STATUS: + handle_cmd_complete(buf); + break; + case BT_HCI_EVT_LE_META_EVENT: + handle_meta_event(buf); + break; + case BT_HCI_EVT_DISCONN_COMPLETE: + UNSET_FLAG(is_connected); + break; + case BT_HCI_EVT_NUM_COMPLETED_PACKETS: + handle_ncp(buf); + break; + default: + LOG_ERR("unhandled msg %x", code); + LOG_HEXDUMP_ERR(buf->data, buf->len, "HCI EVT"); + } + + /* handlers should take a ref if they want to access the buffer + * later + */ + net_buf_unref(buf); + return; + } + + if (bt_buf_get_type(buf) == BT_BUF_ACL_IN) { + handle_acl(buf); + net_buf_unref(buf); + return; + } + + LOG_ERR("HCI RX (not data or event)"); + net_buf_unref(buf); +} + +static void send_cmd(uint16_t opcode, struct net_buf *cmd, struct net_buf **rsp) +{ + LOG_DBG("opcode %x", opcode); + + if (!cmd) { + cmd = bt_hci_cmd_create(opcode, 0); + } + + k_sem_take(&cmd_sem, K_FOREVER); + ASSERT(active_opcode == 0xFFFF, ""); + + active_opcode = opcode; + + LOG_HEXDUMP_DBG(cmd->data, cmd->len, "HCI TX"); + bt_send(cmd); + + /* Wait until the command completes */ + k_sem_take(&cmd_sem, K_FOREVER); + k_sem_give(&cmd_sem); + + net_buf_unref(cmd); + + /* return response. it's okay if cmd_rsp gets overwritten, since the app + * gets the ref to the underlying buffer when this fn returns. + */ + if (rsp) { + *rsp = cmd_rsp; + } else { + net_buf_unref(cmd_rsp); + cmd_rsp = NULL; + } +} + +static K_THREAD_STACK_DEFINE(rx_thread_stack, 1024); +static struct k_thread rx_thread_data; + +static void rx_thread(void *p1, void *p2, void *p3) +{ + LOG_DBG("start HCI rx"); + + while (true) { + struct net_buf *buf; + + /* Wait until a buffer is available */ + buf = net_buf_get(&rx_queue, K_FOREVER); + recv(buf); + } +} + +static void le_read_buffer_size_complete(struct net_buf *rsp) +{ + struct bt_hci_rp_le_read_buffer_size *rp = (void *)rsp->data; + + LOG_DBG("status 0x%02x", rp->status); + LOG_DBG("max len %d max num %d", rp->le_max_len, rp->le_max_num); + + k_sem_init(&acl_pkts, rp->le_max_num, rp->le_max_num); + net_buf_unref(rsp); +} + +static void read_max_data_len(uint16_t *tx_octets, uint16_t *tx_time) +{ + struct bt_hci_rp_le_read_max_data_len *rp; + struct net_buf *rsp; + + send_cmd(BT_HCI_OP_LE_READ_MAX_DATA_LEN, NULL, &rsp); + + rp = (void *)rsp->data; + *tx_octets = sys_le16_to_cpu(rp->max_tx_octets); + *tx_time = sys_le16_to_cpu(rp->max_tx_time); + net_buf_unref(rsp); +} + +static void write_default_data_len(uint16_t tx_octets, uint16_t tx_time) +{ + struct bt_hci_cp_le_write_default_data_len *cp; + struct net_buf *buf = bt_hci_cmd_create(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN, sizeof(*cp)); + + ASSERT(buf, ""); + + cp = net_buf_add(buf, sizeof(*cp)); + cp->max_tx_octets = sys_cpu_to_le16(tx_octets); + cp->max_tx_time = sys_cpu_to_le16(tx_time); + + send_cmd(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN, buf, NULL); +} + +static void set_data_len(void) +{ + uint16_t tx_octets, tx_time; + + read_max_data_len(&tx_octets, &tx_time); + write_default_data_len(tx_octets, tx_time); +} + +static void set_event_mask(uint16_t opcode) +{ + struct bt_hci_cp_set_event_mask *cp_mask; + struct net_buf *buf; + uint64_t mask = 0U; + + /* The two commands have the same length/params */ + buf = bt_hci_cmd_create(opcode, sizeof(*cp_mask)); + ASSERT(buf, ""); + + /* Forward all events */ + cp_mask = net_buf_add(buf, sizeof(*cp_mask)); + mask = UINT64_MAX; + sys_put_le64(mask, cp_mask->events); + + send_cmd(opcode, buf, NULL); +} + +static void set_random_address(void) +{ + struct net_buf *buf; + bt_addr_le_t addr = {BT_ADDR_LE_RANDOM, {{0x0A, 0x89, 0x67, 0x45, 0x23, 0xC1}}}; + + LOG_DBG("%s", bt_addr_str(&addr.a)); + + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, sizeof(addr.a)); + ASSERT(buf, ""); + + net_buf_add_mem(buf, &addr.a, sizeof(addr.a)); + send_cmd(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, buf, NULL); +} + +void start_adv(void) +{ + struct bt_hci_cp_le_set_adv_param set_param; + struct net_buf *buf; + uint16_t interval = 60; /* Interval doesn't matter */ + + (void)memset(&set_param, 0, sizeof(set_param)); + + set_param.min_interval = sys_cpu_to_le16(interval); + set_param.max_interval = sys_cpu_to_le16(interval); + set_param.channel_map = 0x07; + set_param.filter_policy = BT_LE_ADV_FP_NO_FILTER; + set_param.type = BT_HCI_ADV_IND; + set_param.own_addr_type = 0x01; /* random */ + + /* configure */ + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_PARAM, sizeof(set_param)); + net_buf_add_mem(buf, &set_param, sizeof(set_param)); + send_cmd(BT_HCI_OP_LE_SET_ADV_PARAM, buf, NULL); + + /* start */ + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_ENABLE, 1); + net_buf_add_u8(buf, BT_HCI_LE_ADV_ENABLE); + send_cmd(BT_HCI_OP_LE_SET_ADV_ENABLE, buf, NULL); +} + +NET_BUF_POOL_DEFINE(acl_tx_pool, 5, BT_L2CAP_BUF_SIZE(200), 8, NULL); + +struct net_buf *alloc_l2cap_pdu(void) +{ + struct net_buf *buf; + uint16_t reserve; + + buf = net_buf_alloc(&acl_tx_pool, K_FOREVER); + ASSERT(buf, "failed ACL allocation"); + + reserve = sizeof(struct bt_l2cap_hdr); + reserve += sizeof(struct bt_hci_acl_hdr) + BT_BUF_RESERVE; + + net_buf_reserve(buf, reserve); + + return buf; +} + +static int send_acl(struct net_buf *buf) +{ + struct bt_hci_acl_hdr *hdr; + uint8_t flags = BT_ACL_START_NO_FLUSH; + + hdr = net_buf_push(buf, sizeof(*hdr)); + hdr->handle = sys_cpu_to_le16(bt_acl_handle_pack(conn_handle, flags)); + hdr->len = sys_cpu_to_le16(buf->len - sizeof(*hdr)); + + bt_buf_set_type(buf, BT_BUF_ACL_OUT); + + k_sem_take(&acl_pkts, K_FOREVER); + + return bt_send(buf); +} + +static void send_l2cap_packet(struct net_buf *buf, uint16_t cid) +{ + struct bt_l2cap_hdr *hdr; + + hdr = net_buf_push(buf, sizeof(*hdr)); + hdr->len = sys_cpu_to_le16(buf->len - sizeof(*hdr)); + hdr->cid = sys_cpu_to_le16(cid); + + /* Always entire packets, no HCI fragmentation */ + ASSERT(buf->len <= CONFIG_BT_BUF_ACL_TX_SIZE, + "Fragmentation not supported"); + + send_acl(buf); +} + +static void gatt_notify(void) +{ + static uint8_t data[] = NOTIFICATION_PAYLOAD; + uint16_t handle = HVX_HANDLE; + struct net_buf *buf = alloc_l2cap_pdu(); + + net_buf_add_u8(buf, BT_ATT_OP_NOTIFY); + net_buf_add_le16(buf, handle); + net_buf_add_mem(buf, data, sizeof(data)); + + LOG_INF("send ATT notification"); + send_l2cap_packet(buf, BT_L2CAP_CID_ATT); +} + +static void prepare_controller(void) +{ + /* Initialize controller */ + struct net_buf *rsp; + + send_cmd(BT_HCI_OP_RESET, NULL, NULL); + send_cmd(BT_HCI_OP_LE_READ_BUFFER_SIZE, NULL, &rsp); + le_read_buffer_size_complete(rsp); + + set_data_len(); + set_event_mask(BT_HCI_OP_SET_EVENT_MASK); + set_event_mask(BT_HCI_OP_LE_SET_EVENT_MASK); + set_random_address(); +} + +static void init_tinyhost(void) +{ + bt_enable_raw(&rx_queue); + + /* Start the RX thread */ + k_thread_create(&rx_thread_data, rx_thread_stack, + K_THREAD_STACK_SIZEOF(rx_thread_stack), rx_thread, + NULL, NULL, NULL, K_PRIO_PREEMPT(0), 0, K_NO_WAIT); + k_thread_name_set(&rx_thread_data, "HCI RX"); + + k_thread_priority_set(k_current_get(), K_PRIO_PREEMPT(0)); + + prepare_controller(); +} + +void test_procedure_0(void) +{ + ASSERT(backchannel_init() == 0, "Failed to open backchannel\n"); + + init_tinyhost(); + + /* Start advertising & wait for a connection */ + start_adv(); + WAIT_FOR_FLAG(is_connected); + LOG_INF("connected"); + + /* We need this to be able to send whole L2CAP PDUs on-air. */ + WAIT_FOR_FLAG(flag_data_length_updated); + + LOG_INF("##################### START TEST #####################"); + + for (int n = 0; n < 3; n++) { + gatt_notify(); + } + + /* Wait until DUT starts sleeping */ + backchannel_sync_wait(); + + /* Send some more, so DUT has some more data to process before having to + * handle the disconnect. + */ + for (int n = 0; n < 3; n++) { + gatt_notify(); + } + + /* Wait >2 conn events, to be sure at least one more notification makes + * it to the other peer before breaking the link. + */ + k_sleep(K_MSEC(50)); + + LOG_INF("kill radio"); + hwll_disconnect_phy(); + + /* Pass has to be before the exit() for process to not error out */ + PASS("Tester exit\n"); + bs_trace_silent_exit(0); +} + +void test_tick(bs_time_t HW_device_time) +{ + bs_trace_debug_time(0, "Simulation ends now.\n"); + if (bst_result != Passed) { + bst_result = Failed; + bs_trace_error("Test did not pass before simulation ended.\n"); + } +} + +void test_init(void) +{ + bst_ticker_set_next_tick_absolute(TEST_TIMEOUT_SIMULATED); + bst_result = In_progress; +} + +static const struct bst_test_instance test_to_add[] = { + { + .test_id = "tester", + .test_pre_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_procedure_0, + }, + BSTEST_END_MARKER, +}; + +static struct bst_test_list *install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, test_to_add); +}; + +bst_test_install_t test_installers[] = {install, NULL}; + + +int main(void) +{ + bst_main(); + + return 0; +} diff --git a/tests/bsim/bluetooth/host/privacy/central/src/tester.c b/tests/bsim/bluetooth/host/privacy/central/src/tester.c index d511202c450..1c29b53e0c4 100644 --- a/tests/bsim/bluetooth/host/privacy/central/src/tester.c +++ b/tests/bsim/bluetooth/host/privacy/central/src/tester.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include DEFINE_FLAG(flag_new_address); diff --git a/tests/bsim/bluetooth/host/privacy/central/test_scripts/_env.sh b/tests/bsim/bluetooth/host/privacy/central/test_scripts/_env.sh index 18c60bb7c45..0db56a594dc 100755 --- a/tests/bsim/bluetooth/host/privacy/central/test_scripts/_env.sh +++ b/tests/bsim/bluetooth/host/privacy/central/test_scripts/_env.sh @@ -5,10 +5,7 @@ set -eu bash_source_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" -test_name="$(basename "$(realpath "$bash_source_dir/..")")" bsim_bin="${BSIM_OUT_PATH}/bin" -verbosity_level=2 BOARD="${BOARD:-nrf52_bsim}" -simulation_id="$test_name" central_exe="${bsim_bin}/bs_${BOARD}_tests_bsim_bluetooth_host_privacy_central_prj_conf" peripheral_exe="${central_exe}" diff --git a/tests/bsim/bluetooth/host/privacy/central/test_scripts/run_test.sh b/tests/bsim/bluetooth/host/privacy/central/test_scripts/run_test.sh index 3ba95eab78c..ce65d58f6ce 100755 --- a/tests/bsim/bluetooth/host/privacy/central/test_scripts/run_test.sh +++ b/tests/bsim/bluetooth/host/privacy/central/test_scripts/run_test.sh @@ -8,6 +8,8 @@ bash_source_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" source "${bash_source_dir}/_env.sh" source ${ZEPHYR_BASE}/tests/bsim/sh_common.source +verbosity_level=2 +simulation_id="$(basename "$(realpath "$bash_source_dir/..")")" EXECUTE_TIMEOUT=30 cd ${BSIM_OUT_PATH}/bin diff --git a/tests/bsim/bluetooth/host/privacy/device/test_scripts/_env.sh b/tests/bsim/bluetooth/host/privacy/device/test_scripts/_env.sh index bb1b50678cc..ee8b534d1db 100755 --- a/tests/bsim/bluetooth/host/privacy/device/test_scripts/_env.sh +++ b/tests/bsim/bluetooth/host/privacy/device/test_scripts/_env.sh @@ -7,9 +7,6 @@ bash_source_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" : "${BSIM_OUT_PATH:?BSIM_OUT_PATH must be defined}" -test_name="$(basename "$(realpath "$bash_source_dir/..")")" bsim_bin="${BSIM_OUT_PATH}/bin" -verbosity_level=2 BOARD="${BOARD:-nrf52_bsim}" -simulation_id="$test_name" test_exe="${bsim_bin}/bs_${BOARD}_tests_bsim_bluetooth_host_privacy_device_prj_conf" diff --git a/tests/bsim/bluetooth/host/privacy/device/test_scripts/run_tests.sh b/tests/bsim/bluetooth/host/privacy/device/test_scripts/run_tests.sh index 89c180cf57a..d02b58df58d 100755 --- a/tests/bsim/bluetooth/host/privacy/device/test_scripts/run_tests.sh +++ b/tests/bsim/bluetooth/host/privacy/device/test_scripts/run_tests.sh @@ -8,6 +8,8 @@ bash_source_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" source "${bash_source_dir}/_env.sh" source ${ZEPHYR_BASE}/tests/bsim/sh_common.source +verbosity_level=2 +simulation_id="$(basename "$(realpath "$bash_source_dir/..")")" EXECUTE_TIMEOUT=30 cd ${BSIM_OUT_PATH}/bin diff --git a/tests/bsim/bluetooth/host/privacy/legacy/src/tester.c b/tests/bsim/bluetooth/host/privacy/legacy/src/tester.c index 1648e030be5..ed425febe3c 100644 --- a/tests/bsim/bluetooth/host/privacy/legacy/src/tester.c +++ b/tests/bsim/bluetooth/host/privacy/legacy/src/tester.c @@ -5,8 +5,8 @@ */ #include "bs_bt_utils.h" -#include "zephyr/bluetooth/addr.h" -#include "zephyr/bluetooth/conn.h" +#include +#include #include #include diff --git a/tests/bsim/bluetooth/host/privacy/legacy/test_scripts/_env.sh b/tests/bsim/bluetooth/host/privacy/legacy/test_scripts/_env.sh index 241e989c100..714fe3eb996 100755 --- a/tests/bsim/bluetooth/host/privacy/legacy/test_scripts/_env.sh +++ b/tests/bsim/bluetooth/host/privacy/legacy/test_scripts/_env.sh @@ -5,10 +5,7 @@ set -eu bash_source_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" -test_name="$(basename "$(realpath "$bash_source_dir/..")")" bsim_bin="${BSIM_OUT_PATH}/bin" -verbosity_level=2 BOARD="${BOARD:-nrf52_bsim}" -simulation_id="$test_name" central_exe="${bsim_bin}/bs_${BOARD}_tests_bsim_bluetooth_host_privacy_legacy_prj_conf" peripheral_exe="${central_exe}" diff --git a/tests/bsim/bluetooth/host/privacy/legacy/test_scripts/run_test.sh b/tests/bsim/bluetooth/host/privacy/legacy/test_scripts/run_test.sh index 2a574a29742..ccbe6e844f2 100755 --- a/tests/bsim/bluetooth/host/privacy/legacy/test_scripts/run_test.sh +++ b/tests/bsim/bluetooth/host/privacy/legacy/test_scripts/run_test.sh @@ -8,6 +8,8 @@ bash_source_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" source "${bash_source_dir}/_env.sh" source ${ZEPHYR_BASE}/tests/bsim/sh_common.source +verbosity_level=2 +simulation_id="$(basename "$(realpath "$bash_source_dir/..")")" EXECUTE_TIMEOUT=30 cd ${BSIM_OUT_PATH}/bin diff --git a/tests/bsim/bluetooth/host/privacy/peripheral/prj.conf b/tests/bsim/bluetooth/host/privacy/peripheral/prj.conf index bd5bf844bd0..9113a44382b 100644 --- a/tests/bsim/bluetooth/host/privacy/peripheral/prj.conf +++ b/tests/bsim/bluetooth/host/privacy/peripheral/prj.conf @@ -8,4 +8,16 @@ CONFIG_BT_EXT_ADV=y CONFIG_BT_PRIVACY=y CONFIG_BT_RPA_TIMEOUT=10 CONFIG_BT_EXT_ADV_MAX_ADV_SET=3 +CONFIG_BT_CTLR_ADVANCED_FEATURES=y +CONFIG_BT_CTLR_ADV_DATA_BUF_MAX=3 CONFIG_BT_ID_MAX=3 + +CONFIG_FLASH=y +CONFIG_FLASH_PAGE_LAYOUT=y +CONFIG_FLASH_MAP=y +CONFIG_NVS=y +CONFIG_SETTINGS=y +CONFIG_BT_SETTINGS=y + +# Increased stack due to settings API usage +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 diff --git a/tests/bsim/bluetooth/host/privacy/peripheral/prj_rpa_sharing.conf b/tests/bsim/bluetooth/host/privacy/peripheral/prj_rpa_sharing.conf new file mode 100644 index 00000000000..bebce9933ca --- /dev/null +++ b/tests/bsim/bluetooth/host/privacy/peripheral/prj_rpa_sharing.conf @@ -0,0 +1,26 @@ +CONFIG_BT=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_SMP=y +CONFIG_ASSERT=y + +CONFIG_BT_EXT_ADV=y +CONFIG_BT_PRIVACY=y +CONFIG_BT_RPA_TIMEOUT=10 +CONFIG_BT_EXT_ADV_MAX_ADV_SET=3 +CONFIG_BT_CTLR_ADVANCED_FEATURES=y +CONFIG_BT_CTLR_ADV_DATA_BUF_MAX=3 +CONFIG_BT_ID_MAX=3 + +CONFIG_FLASH=y +CONFIG_FLASH_PAGE_LAYOUT=y +CONFIG_FLASH_MAP=y +CONFIG_NVS=y +CONFIG_SETTINGS=y +CONFIG_BT_SETTINGS=y + +# Increased stack due to settings API usage +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 + +# Enable the RPA sharing mode +CONFIG_BT_RPA_SHARING=y diff --git a/tests/bsim/bluetooth/host/privacy/peripheral/src/dut.c b/tests/bsim/bluetooth/host/privacy/peripheral/src/dut.c index 6446545d72a..9d72b5368b2 100644 --- a/tests/bsim/bluetooth/host/privacy/peripheral/src/dut.c +++ b/tests/bsim/bluetooth/host/privacy/peripheral/src/dut.c @@ -12,10 +12,14 @@ #include #include #include -#include +#include +#include #include "common/bt_str.h" +#define ID_A_INDEX 1 +#define ID_B_INDEX 2 + #define ADV_SET_INDEX_ONE 0x00 #define ADV_SET_INDEX_TWO 0x01 #define ADV_SET_INDEX_THREE 0x02 @@ -66,8 +70,7 @@ static void create_adv(struct bt_le_ext_adv **adv, int id) void start_advertising(void) { int err; - int id_a; - int id_b; + size_t bt_id_count; /* Enable bluetooth */ err = bt_enable(NULL); @@ -75,24 +78,44 @@ void start_advertising(void) FAIL("Failed to enable bluetooth (err %d\n)", err); } - id_a = bt_id_create(NULL, NULL); - if (id_a < 0) { - FAIL("bt_id_create id_a failed (err %d)\n", id_a); + err = settings_load(); + if (err) { + FAIL("Failed to enable settings (err %d\n)", err); + } + + bt_id_get(NULL, &bt_id_count); + if (bt_id_count == 1) { + int id_a; + int id_b; + + printk("No extra identity found in settings, creating new ones...\n"); + + id_a = bt_id_create(NULL, NULL); + if (id_a != ID_A_INDEX) { + FAIL("bt_id_create id_a failed (err %d)\n", id_a); + } + + id_b = bt_id_create(NULL, NULL); + if (id_b != ID_B_INDEX) { + FAIL("bt_id_create id_b failed (err %d)\n", id_b); + } + } else { + printk("Extra identities loaded from settings\n"); } - id_b = bt_id_create(NULL, NULL); - if (id_b < 0) { - FAIL("bt_id_create id_b failed (err %d)\n", id_b); + bt_id_get(NULL, &bt_id_count); + if (bt_id_count != CONFIG_BT_ID_MAX) { + FAIL("bt_id_get returned incorrect number of identities %u\n", bt_id_count); } for (int i = 0; i < CONFIG_BT_EXT_ADV_MAX_ADV_SET; i++) { if (i != ADV_SET_INDEX_THREE) { /* Create advertising set 1 and 2 with same id */ - create_adv(&adv_set[i], id_a); + create_adv(&adv_set[i], ID_A_INDEX); } else { /* Create advertising set 3 with different id */ - create_adv(&adv_set[i], id_b); + create_adv(&adv_set[i], ID_B_INDEX); } /* Set extended advertising data */ diff --git a/tests/bsim/bluetooth/host/privacy/peripheral/src/tester.c b/tests/bsim/bluetooth/host/privacy/peripheral/src/tester.c index eae8dc61515..db363cd6ea0 100644 --- a/tests/bsim/bluetooth/host/privacy/peripheral/src/tester.c +++ b/tests/bsim/bluetooth/host/privacy/peripheral/src/tester.c @@ -5,10 +5,11 @@ */ #include "bs_bt_utils.h" -#include "zephyr/bluetooth/addr.h" -#include "zephyr/bluetooth/conn.h" +#include +#include #include #include +#include #define EXPECTED_NUM_ROTATIONS 5 @@ -40,9 +41,20 @@ static void validate_rpa_addr_generated_for_adv_sets(void) return; } } - /* First two adv sets have same address as they use same ID and third adv set use diff ID */ - if (!bt_addr_le_eq(&adv_set_data[0].old_addr, &adv_set_data[1].old_addr)) { - FAIL("RPA not same for adv sets with same id\n"); + if (bt_addr_le_eq(&adv_set_data[0].old_addr, &adv_set_data[1].old_addr)) { + /* With RPA sharing mode disabled, the first two adv sets should have + * a different address even though they use the same Bluetooth ID. + */ + if (!IS_ENABLED(CONFIG_BT_RPA_SHARING)) { + FAIL("RPA same for adv sets with same id and RPA sharing disabled\n"); + } + } else { + /* In the RPA sharing mode, the first two adv sets should have + * the same address as they use the same Bluetooth ID. + */ + if (IS_ENABLED(CONFIG_BT_RPA_SHARING)) { + FAIL("RPA not same for adv sets with same id and RPA sharing enabled\n"); + } } if (bt_addr_le_eq(&adv_set_data[0].old_addr, &adv_set_data[3].old_addr)) { FAIL("RPA same for adv sets with different id's\n"); @@ -59,6 +71,10 @@ static void test_address(bt_addr_le_t *addr) { int64_t diff_ms, rpa_timeout_ms; + if (!BT_ADDR_IS_RPA(&addr->a)) { + FAIL("Bluetooth address is not RPA\n"); + } + /* Only save the address + time if this is the first scan */ if (bt_addr_le_eq(&adv_set_data[adv_index].old_addr, BT_ADDR_LE_ANY)) { bt_addr_le_copy(&adv_set_data[adv_index].old_addr, addr); @@ -83,7 +99,7 @@ static void test_address(bt_addr_le_t *addr) rpa_timeout_ms = CONFIG_BT_RPA_TIMEOUT * MSEC_PER_SEC; if (abs(diff_ms - rpa_timeout_ms) > (rpa_timeout_ms / 10)) { - FAIL("RPA rotation did not occur within +-10% of CONFIG_BT_RPA_TIMEOUT\n"); + FAIL("RPA rotation did not occur within +-10%% of CONFIG_BT_RPA_TIMEOUT\n"); } bt_addr_le_copy(&adv_set_data[adv_index].old_addr, addr); @@ -128,6 +144,11 @@ void tester_procedure(void) FAIL("Failed to enable bluetooth (err %d\n)", err); } + err = settings_load(); + if (err) { + FAIL("Failed to enable settings (err %d\n)", err); + } + start_scanning(); /* The rest of the test is driven by the callback */ diff --git a/tests/bsim/bluetooth/host/privacy/peripheral/test_scripts/_env.sh b/tests/bsim/bluetooth/host/privacy/peripheral/test_scripts/_env.sh index 2e3593a3df4..3c86078a7a6 100755 --- a/tests/bsim/bluetooth/host/privacy/peripheral/test_scripts/_env.sh +++ b/tests/bsim/bluetooth/host/privacy/peripheral/test_scripts/_env.sh @@ -5,10 +5,10 @@ set -eu bash_source_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" -test_name="$(basename "$(realpath "$bash_source_dir/..")")" bsim_bin="${BSIM_OUT_PATH}/bin" -verbosity_level=2 BOARD="${BOARD:-nrf52_bsim}" -simulation_id="$test_name" central_exe="${bsim_bin}/bs_${BOARD}_tests_bsim_bluetooth_host_privacy_peripheral_prj_conf" peripheral_exe="${central_exe}" +central_exe_rpa_sharing="\ +${bsim_bin}/bs_${BOARD}_tests_bsim_bluetooth_host_privacy_peripheral_prj_rpa_sharing_conf" +peripheral_exe_rpa_sharing="${central_exe_rpa_sharing}" diff --git a/tests/bsim/bluetooth/host/privacy/peripheral/test_scripts/run_test.sh b/tests/bsim/bluetooth/host/privacy/peripheral/test_scripts/run_test.sh index 2a574a29742..37929a4efb2 100755 --- a/tests/bsim/bluetooth/host/privacy/peripheral/test_scripts/run_test.sh +++ b/tests/bsim/bluetooth/host/privacy/peripheral/test_scripts/run_test.sh @@ -8,15 +8,36 @@ bash_source_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" source "${bash_source_dir}/_env.sh" source ${ZEPHYR_BASE}/tests/bsim/sh_common.source +verbosity_level=2 +simulation_id="$(basename "$(realpath "$bash_source_dir/..")")" EXECUTE_TIMEOUT=30 cd ${BSIM_OUT_PATH}/bin Execute "$central_exe" \ - -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central -RealEncryption=1 + -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central -RealEncryption=1 \ + -flash="${simulation_id}.central.log.bin" + Execute "$peripheral_exe" \ - -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral -RealEncryption=1 + -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral -RealEncryption=1 \ + -flash="${simulation_id}.peripheral.log.bin" + + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=70e6 $@ + +wait_for_background_jobs + +Execute "$central_exe" \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central -RealEncryption=1 \ + -flash="${simulation_id}.central.log.bin" -flash_rm + + +Execute "$peripheral_exe" \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral -RealEncryption=1 \ + -flash="${simulation_id}.peripheral.log.bin" -flash_rm + Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ -D=2 -sim_length=70e6 $@ diff --git a/tests/bsim/bluetooth/host/privacy/peripheral/test_scripts/run_test_rpa_sharing.sh b/tests/bsim/bluetooth/host/privacy/peripheral/test_scripts/run_test_rpa_sharing.sh new file mode 100755 index 00000000000..2b0d5e4c4b7 --- /dev/null +++ b/tests/bsim/bluetooth/host/privacy/peripheral/test_scripts/run_test_rpa_sharing.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +set -eu +bash_source_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" + +source "${bash_source_dir}/_env.sh" +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +verbosity_level=2 +simulation_id="$(basename "$(realpath "$bash_source_dir/..")")" +simulation_id="${simulation_id}_rpa_sharing" +EXECUTE_TIMEOUT=30 + +cd ${BSIM_OUT_PATH}/bin + +Execute "$central_exe_rpa_sharing" \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central -RealEncryption=1 \ + -flash="${simulation_id}.central.log.bin" + + +Execute "$peripheral_exe_rpa_sharing" \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral -RealEncryption=1 \ + -flash="${simulation_id}.peripheral.log.bin" + + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=70e6 $@ + +wait_for_background_jobs + +Execute "$central_exe_rpa_sharing" \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central -RealEncryption=1 \ + -flash="${simulation_id}.central.log.bin" -flash_rm + + +Execute "$peripheral_exe_rpa_sharing" \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral -RealEncryption=1 \ + -flash="${simulation_id}.peripheral.log.bin" -flash_rm + + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=70e6 $@ + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/host/security/bond_overwrite_allowed/src/bs_bt_utils.h b/tests/bsim/bluetooth/host/security/bond_overwrite_allowed/src/bs_bt_utils.h index 1013fad20fe..b3718eb769d 100644 --- a/tests/bsim/bluetooth/host/security/bond_overwrite_allowed/src/bs_bt_utils.h +++ b/tests/bsim/bluetooth/host/security/bond_overwrite_allowed/src/bs_bt_utils.h @@ -10,7 +10,7 @@ #include "bs_types.h" #include "bstests.h" #include "time_machine.h" -#include "zephyr/sys/__assert.h" +#include #include #include diff --git a/tests/bsim/bluetooth/host/security/bond_overwrite_allowed/src/central.c b/tests/bsim/bluetooth/host/security/bond_overwrite_allowed/src/central.c index 0ea460ab122..164646fe79c 100644 --- a/tests/bsim/bluetooth/host/security/bond_overwrite_allowed/src/central.c +++ b/tests/bsim/bluetooth/host/security/bond_overwrite_allowed/src/central.c @@ -5,8 +5,8 @@ */ #include "bs_bt_utils.h" -#include "zephyr/bluetooth/addr.h" -#include "zephyr/bluetooth/conn.h" +#include +#include #include diff --git a/tests/bsim/bluetooth/host/security/bond_overwrite_allowed/src/peripheral.c b/tests/bsim/bluetooth/host/security/bond_overwrite_allowed/src/peripheral.c index 7dca9913dd7..633768879d3 100644 --- a/tests/bsim/bluetooth/host/security/bond_overwrite_allowed/src/peripheral.c +++ b/tests/bsim/bluetooth/host/security/bond_overwrite_allowed/src/peripheral.c @@ -5,10 +5,10 @@ */ #include "bs_bt_utils.h" -#include "zephyr/bluetooth/addr.h" -#include "zephyr/bluetooth/bluetooth.h" -#include "zephyr/bluetooth/conn.h" -#include "zephyr/toolchain/gcc.h" +#include +#include +#include +#include #include #include diff --git a/tests/bsim/bluetooth/host/security/bond_overwrite_denied/src/bs_bt_utils.h b/tests/bsim/bluetooth/host/security/bond_overwrite_denied/src/bs_bt_utils.h index 1013fad20fe..b3718eb769d 100644 --- a/tests/bsim/bluetooth/host/security/bond_overwrite_denied/src/bs_bt_utils.h +++ b/tests/bsim/bluetooth/host/security/bond_overwrite_denied/src/bs_bt_utils.h @@ -10,7 +10,7 @@ #include "bs_types.h" #include "bstests.h" #include "time_machine.h" -#include "zephyr/sys/__assert.h" +#include #include #include diff --git a/tests/bsim/bluetooth/host/security/bond_overwrite_denied/src/central.c b/tests/bsim/bluetooth/host/security/bond_overwrite_denied/src/central.c index e1e8e0efc4d..26f3bee4710 100644 --- a/tests/bsim/bluetooth/host/security/bond_overwrite_denied/src/central.c +++ b/tests/bsim/bluetooth/host/security/bond_overwrite_denied/src/central.c @@ -5,8 +5,8 @@ */ #include "bs_bt_utils.h" -#include "zephyr/bluetooth/addr.h" -#include "zephyr/bluetooth/conn.h" +#include +#include #include diff --git a/tests/bsim/bluetooth/host/security/bond_overwrite_denied/src/peripheral.c b/tests/bsim/bluetooth/host/security/bond_overwrite_denied/src/peripheral.c index fb3527b7ef2..319779c94f1 100644 --- a/tests/bsim/bluetooth/host/security/bond_overwrite_denied/src/peripheral.c +++ b/tests/bsim/bluetooth/host/security/bond_overwrite_denied/src/peripheral.c @@ -5,10 +5,10 @@ */ #include "bs_bt_utils.h" -#include "zephyr/bluetooth/addr.h" -#include "zephyr/bluetooth/bluetooth.h" -#include "zephyr/bluetooth/conn.h" -#include "zephyr/toolchain/gcc.h" +#include +#include +#include +#include #include #include diff --git a/tests/bsim/bluetooth/host/security/bond_per_connection/src/bs_bt_utils.h b/tests/bsim/bluetooth/host/security/bond_per_connection/src/bs_bt_utils.h index fc440c6bec8..c16d9cb9676 100644 --- a/tests/bsim/bluetooth/host/security/bond_per_connection/src/bs_bt_utils.h +++ b/tests/bsim/bluetooth/host/security/bond_per_connection/src/bs_bt_utils.h @@ -10,7 +10,7 @@ #include "bs_types.h" #include "bstests.h" #include "time_machine.h" -#include "zephyr/sys/__assert.h" +#include #include #include diff --git a/tests/bsim/bluetooth/host/security/bond_per_connection/src/central.c b/tests/bsim/bluetooth/host/security/bond_per_connection/src/central.c index f31261b68c0..4e0052310d3 100644 --- a/tests/bsim/bluetooth/host/security/bond_per_connection/src/central.c +++ b/tests/bsim/bluetooth/host/security/bond_per_connection/src/central.c @@ -5,8 +5,8 @@ */ #include "bs_bt_utils.h" -#include "zephyr/bluetooth/addr.h" -#include "zephyr/bluetooth/conn.h" +#include +#include #include diff --git a/tests/bsim/bluetooth/host/security/bond_per_connection/src/peripheral.c b/tests/bsim/bluetooth/host/security/bond_per_connection/src/peripheral.c index 01956d251df..04fc3cdd8f2 100644 --- a/tests/bsim/bluetooth/host/security/bond_per_connection/src/peripheral.c +++ b/tests/bsim/bluetooth/host/security/bond_per_connection/src/peripheral.c @@ -5,10 +5,10 @@ */ #include "bs_bt_utils.h" -#include "zephyr/bluetooth/addr.h" -#include "zephyr/bluetooth/bluetooth.h" -#include "zephyr/bluetooth/conn.h" -#include "zephyr/toolchain/gcc.h" +#include +#include +#include +#include #include #include diff --git a/tests/bsim/bluetooth/host/security/id_addr_update/CMakeLists.txt b/tests/bsim/bluetooth/host/security/id_addr_update/CMakeLists.txt deleted file mode 100644 index 6bb8754c71d..00000000000 --- a/tests/bsim/bluetooth/host/security/id_addr_update/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) - -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(bsim_test_id_addr_update) - -target_sources(app PRIVATE - src/bs_bt_utils.c - src/central.c - src/main.c - src/peripheral.c -) - -zephyr_include_directories( - ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ - ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ - ) diff --git a/tests/bsim/bluetooth/host/security/id_addr_update/central/CMakeLists.txt b/tests/bsim/bluetooth/host/security/id_addr_update/central/CMakeLists.txt new file mode 100644 index 00000000000..0ca6f4313bd --- /dev/null +++ b/tests/bsim/bluetooth/host/security/id_addr_update/central/CMakeLists.txt @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(bsim_test_id_addr_update) + +target_sources(app PRIVATE + src/central.c + src/utils.c) + +zephyr_include_directories( + ../common/ + ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ + ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ + ) diff --git a/tests/bsim/bluetooth/host/security/id_addr_update/central/prj.conf b/tests/bsim/bluetooth/host/security/id_addr_update/central/prj.conf new file mode 100644 index 00000000000..789cce1f21f --- /dev/null +++ b/tests/bsim/bluetooth/host/security/id_addr_update/central/prj.conf @@ -0,0 +1,26 @@ +CONFIG_BT=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_GATT_CLIENT=y + +# Both BT_SMP and BT_SETTINGS options need to be enabled to trigger +# code execution of the bt_gatt_identity_resolved function. +CONFIG_BT_SMP=y +CONFIG_BT_SETTINGS=y + +# Enabled the dependencies of the BT_SETTINGS option. +CONFIG_FLASH=y +CONFIG_FLASH_MAP=y +CONFIG_NVS=y +CONFIG_SETTINGS_NVS=y +CONFIG_SETTINGS=y + +CONFIG_ASSERT=y +CONFIG_BT_TESTING=y +CONFIG_LOG=y + +CONFIG_BT_ID_MAX=3 +CONFIG_BT_MAX_PAIRED=2 + +CONFIG_BT_MAX_CONN=2 + +CONFIG_BT_PRIVACY=y diff --git a/tests/bsim/bluetooth/host/security/id_addr_update/central/src/central.c b/tests/bsim/bluetooth/host/security/id_addr_update/central/src/central.c new file mode 100644 index 00000000000..15c9fa69cfd --- /dev/null +++ b/tests/bsim/bluetooth/host/security/id_addr_update/central/src/central.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_bt_utils.h" +#include "utils.h" +#include +#include + +#include + +#include + +#include +LOG_MODULE_REGISTER(central, LOG_LEVEL_INF); + +void central(void) +{ + bs_bt_utils_setup(); + + struct bt_conn *conn_a; + struct bt_conn *conn_b; + + /* Connect to the first identity of the peripheral. */ + LOG_INF("conn first"); + scan_connect_to_first_result(); + LOG_INF("wait conn"); + wait_connected(&conn_a); + + /* Subscribe to battery notifications and wait on the first one. */ + LOG_INF("subscribe first"); + bas_subscribe(conn_a); + wait_bas_notification(); + + /* Connect to the second identity of the peripheral. */ + LOG_INF("scan 2nd id"); + scan_connect_to_first_result(); + wait_connected(&conn_b); + + /* Establish security with the second identity and resolve identity address. */ + LOG_INF("set sec"); + set_security(conn_b, BT_SECURITY_L2); + wait_pairing_completed(); + + /* Wait for notification from the first connection after identity address resolution. */ + LOG_INF("wait notif"); + wait_bas_notification(); + + /* Disconnect the first identity of the peripheral. */ + LOG_INF("discon id first"); + disconnect(conn_a); + wait_disconnected(); + clear_conn(conn_a); + + /* Disconnect the second identity of the peripheral. */ + LOG_INF("discon id second"); + disconnect(conn_b); + wait_disconnected(); + clear_conn(conn_b); + + PASS("PASS\n"); +} + +static const struct bst_test_instance test_to_add[] = { + { + .test_id = "central", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = central, + }, + BSTEST_END_MARKER, +}; + +static struct bst_test_list *install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, test_to_add); +}; + +bst_test_install_t test_installers[] = {install, NULL}; + +int main(void) +{ + bst_main(); + return 0; +} diff --git a/tests/bsim/bluetooth/host/security/id_addr_update/central/src/utils.c b/tests/bsim/bluetooth/host/security/id_addr_update/central/src/utils.c new file mode 100644 index 00000000000..a1ccc4f6996 --- /dev/null +++ b/tests/bsim/bluetooth/host/security/id_addr_update/central/src/utils.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_bt_utils.h" +#include "utils.h" + +BUILD_ASSERT(CONFIG_BT_MAX_PAIRED >= 2, "CONFIG_BT_MAX_PAIRED is too small."); +BUILD_ASSERT(CONFIG_BT_ID_MAX >= 3, "CONFIG_BT_ID_MAX is too small."); +BUILD_ASSERT(CONFIG_BT_MAX_CONN == 2, "CONFIG_BT_MAX_CONN should be equal to two."); +BUILD_ASSERT(CONFIG_BT_GATT_CLIENT, "CONFIG_BT_GATT_CLIENT is disabled."); + +void test_tick(bs_time_t HW_device_time) +{ + bs_trace_debug_time(0, "Simulation ends now.\n"); + if (bst_result != Passed) { + bst_result = Failed; + bs_trace_error("Test did not pass before simulation ended.\n"); + } +} + +void test_init(void) +{ + bst_ticker_set_next_tick_absolute(TEST_TIMEOUT_SIMULATED); + bst_result = In_progress; +} + +DEFINE_FLAG(flag_has_new_conn); +struct bt_conn *new_conn; + +DEFINE_FLAG(flag_has_disconnected); + +void clear_conn(struct bt_conn *conn) +{ + if (new_conn == conn) { + new_conn = NULL; + } + + ASSERT(conn, "Test error: No new_conn!\n"); + bt_conn_unref(conn); +} + +void wait_connected(struct bt_conn **conn) +{ + WAIT_FOR_FLAG(flag_has_new_conn); + UNSET_FLAG(flag_has_new_conn); + + ASSERT(new_conn, "connection unpopulated."); + *conn = new_conn; + new_conn = NULL; +} + +void wait_disconnected(void) +{ + WAIT_FOR_FLAG(flag_has_disconnected); + UNSET_FLAG(flag_has_disconnected); +} + +static void print_conn_state_transition(const char *prefix, struct bt_conn *conn) +{ + int err; + struct bt_conn_info info; + char addr_str[BT_ADDR_LE_STR_LEN]; + + err = bt_conn_get_info(conn, &info); + ASSERT(!err, "Unexpected conn info result."); + + bt_addr_le_to_str(info.le.dst, addr_str, sizeof(addr_str)); + printk("%s: %s\n", prefix, addr_str); +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + print_conn_state_transition("Disonnected", conn); + SET_FLAG(flag_has_disconnected); +} + +static void connected(struct bt_conn *conn, uint8_t err) +{ + ASSERT((!new_conn || (conn == new_conn)), "Unexpected new connection."); + + if (!new_conn) { + new_conn = bt_conn_ref(conn); + } + + if (err != 0) { + clear_conn(conn); + return; + } + + print_conn_state_transition("Connected", conn); + SET_FLAG(flag_has_new_conn); +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected, + .disconnected = disconnected, +}; + +DEFINE_FLAG(flag_pairing_completed); + +static void pairing_complete(struct bt_conn *conn, bool bonded) +{ + print_conn_state_transition("Paired", conn); + SET_FLAG(flag_pairing_completed); +} + +static struct bt_conn_auth_info_cb bt_conn_auth_info_cb = { + .pairing_complete = pairing_complete, +}; + +void set_security(struct bt_conn *conn, bt_security_t sec) +{ + int err; + + err = bt_conn_set_security(conn, sec); + ASSERT(!err, "Err bt_conn_set_security %d", err); +} + +void wait_pairing_completed(void) +{ + WAIT_FOR_FLAG(flag_pairing_completed); + UNSET_FLAG(flag_pairing_completed); +} + +void bs_bt_utils_setup(void) +{ + int err; + + err = bt_enable(NULL); + ASSERT(!err, "bt_enable failed.\n"); + err = bt_conn_auth_info_cb_register(&bt_conn_auth_info_cb); + ASSERT(!err, "bt_conn_auth_info_cb_register failed.\n"); + + err = settings_load(); + ASSERT(!err, "settings_load failed.\n"); +} + +static void scan_connect_to_first_result__device_found(const bt_addr_le_t *addr, int8_t rssi, + uint8_t type, struct net_buf_simple *ad) +{ + char addr_str[BT_ADDR_LE_STR_LEN]; + int err; + + /* We're only interested in connectable events */ + if (type != BT_HCI_ADV_IND && type != BT_HCI_ADV_DIRECT_IND) { + FAIL("Unexpected advertisement type."); + } + + bt_addr_le_to_str(addr, addr_str, sizeof(addr_str)); + printk("Got scan result, connecting.. dst %s, RSSI %d\n", addr_str, rssi); + + err = bt_le_scan_stop(); + ASSERT(!err, "Err bt_le_scan_stop %d", err); + + err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT, &new_conn); + ASSERT(!err, "Err bt_conn_le_create %d", err); +} + +void scan_connect_to_first_result(void) +{ + int err; + + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, scan_connect_to_first_result__device_found); + ASSERT(!err, "Err bt_le_scan_start %d", err); +} + +void disconnect(struct bt_conn *conn) +{ + int err; + + err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + ASSERT(!err, "Err bt_conn_disconnect %d", err); +} + +DEFINE_FLAG(flag_bas_has_notification); + +static uint8_t bas_level = 50; + +static uint8_t bas_notify_func(struct bt_conn *conn, + struct bt_gatt_subscribe_params *params, + const void *data, uint16_t length) +{ + const uint8_t *lvl8 = data; + + if ((length == 1) && (*lvl8 == bas_level)) { + printk("BAS notification\n"); + SET_FLAG(flag_bas_has_notification); + } + + return BT_GATT_ITER_CONTINUE; +} + +void wait_bas_notification(void) +{ + WAIT_FOR_FLAG(flag_bas_has_notification); + UNSET_FLAG(flag_bas_has_notification); +} + +/* Not actually used, see below why we also have this on the central */ +BT_GATT_SERVICE_DEFINE(bas, + BT_GATT_PRIMARY_SERVICE(BT_UUID_BAS), + BT_GATT_CHARACTERISTIC(BT_UUID_BAS_BATTERY_LEVEL, + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, + BT_GATT_PERM_READ, NULL, NULL, &bas_level), + BT_GATT_CCC(NULL, + BT_GATT_PERM_READ | BT_GATT_PERM_WRITE), +); + +void bas_subscribe(struct bt_conn *conn) +{ + int err; + static struct bt_gatt_subscribe_params subscribe_params = {0}; + + /* This is a bit of a shortcut: to skip discovery, we assume the handles + * will be the same on the central & peripheral images. + */ + subscribe_params.ccc_handle = bt_gatt_attr_get_handle(&bas.attrs[3]); + subscribe_params.value_handle = bt_gatt_attr_get_handle(&bas.attrs[2]); + subscribe_params.value = BT_GATT_CCC_NOTIFY; + subscribe_params.notify = bas_notify_func; + + err = bt_gatt_subscribe(conn, &subscribe_params); + ASSERT(!err, "bt_gatt_subscribe failed (err %d)\n", err); +} diff --git a/tests/bsim/bluetooth/host/security/id_addr_update/central/src/utils.h b/tests/bsim/bluetooth/host/security/id_addr_update/central/src/utils.h new file mode 100644 index 00000000000..af79f165858 --- /dev/null +++ b/tests/bsim/bluetooth/host/security/id_addr_update/central/src/utils.h @@ -0,0 +1,19 @@ +#include +#include + +void test_tick(bs_time_t HW_device_time); +void test_init(void); + +void bs_bt_utils_setup(void); + +void clear_conn(struct bt_conn *conn); +void wait_connected(struct bt_conn **conn); +void wait_disconnected(void); +void disconnect(struct bt_conn *conn); +void scan_connect_to_first_result(void); + +void set_security(struct bt_conn *conn, bt_security_t sec); +void wait_pairing_completed(void); + +void bas_subscribe(struct bt_conn *conn); +void wait_bas_notification(void); diff --git a/tests/bsim/bluetooth/host/security/id_addr_update/common/bs_bt_utils.h b/tests/bsim/bluetooth/host/security/id_addr_update/common/bs_bt_utils.h new file mode 100644 index 00000000000..2b4b4a48911 --- /dev/null +++ b/tests/bsim/bluetooth/host/security/id_addr_update/common/bs_bt_utils.h @@ -0,0 +1,89 @@ +/** + * Common functions and helpers for this test + * + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_tracing.h" +#include "bs_types.h" +#include "bstests.h" +#include "time_machine.h" +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +extern enum bst_result_t bst_result; + +#define BS_SECONDS(dur_sec) ((bs_time_t)dur_sec * 1000000) +#define TEST_TIMEOUT_SIMULATED BS_SECONDS(60) + +#define DECLARE_FLAG(flag) extern atomic_t flag +#define DEFINE_FLAG(flag) atomic_t flag = (atomic_t) false +#define SET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) true) +#define UNSET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) false) +#define WAIT_FOR_FLAG(flag) \ + while (!(bool)atomic_get(&flag)) { \ + (void)k_sleep(K_MSEC(1)); \ + } +#define WAIT_FOR_FLAG_UNSET(flag) \ + while ((bool)atomic_get(&flag)) { \ + (void)k_sleep(K_MSEC(1)); \ + } +#define TAKE_FLAG(flag) \ + while (!(bool)atomic_cas(&flag, true, false)) { \ + (void)k_sleep(K_MSEC(1)); \ + } +#define GET_FLAG(flag) \ + (bool)atomic_get(&flag) + +#define ASSERT(expr, ...) \ + do { \ + if (!(expr)) { \ + FAIL(__VA_ARGS__); \ + } \ + } while (0) + +#define FAIL(...) \ + do { \ + bst_result = Failed; \ + bs_trace_error_time_line(__VA_ARGS__); \ + } while (0) + +#define PASS(...) \ + do { \ + bst_result = Passed; \ + bs_trace_info_time(1, __VA_ARGS__); \ + } while (0) + +void test_tick(bs_time_t HW_device_time); +void test_init(void); + +void bs_bt_utils_setup(void); + +void clear_conn(struct bt_conn *conn); +void wait_connected(struct bt_conn **conn); +void wait_disconnected(void); +void disconnect(struct bt_conn *conn); +void scan_connect_to_first_result(void); +void advertise_connectable(int id); + +void set_security(struct bt_conn *conn, bt_security_t sec); +void wait_pairing_completed(void); + +void bas_subscribe(struct bt_conn *conn); +void wait_bas_ccc_subscription(void); +void bas_notify(struct bt_conn *conn); +void wait_bas_notification(void); diff --git a/tests/bsim/bluetooth/host/security/id_addr_update/peripheral/CMakeLists.txt b/tests/bsim/bluetooth/host/security/id_addr_update/peripheral/CMakeLists.txt new file mode 100644 index 00000000000..5ea3558fa64 --- /dev/null +++ b/tests/bsim/bluetooth/host/security/id_addr_update/peripheral/CMakeLists.txt @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(bsim_test_id_addr_update) + +target_sources(app PRIVATE + src/peripheral.c + src/utils.c +) + +zephyr_include_directories( + ../common/ + ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ + ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ + ) diff --git a/tests/bsim/bluetooth/host/security/id_addr_update/peripheral/prj.conf b/tests/bsim/bluetooth/host/security/id_addr_update/peripheral/prj.conf new file mode 100644 index 00000000000..86394cab289 --- /dev/null +++ b/tests/bsim/bluetooth/host/security/id_addr_update/peripheral/prj.conf @@ -0,0 +1,25 @@ +CONFIG_BT=y +CONFIG_BT_PERIPHERAL=y + +# Both BT_SMP and BT_SETTINGS options need to be enabled to trigger +# code execution of the bt_gatt_identity_resolved function. +CONFIG_BT_SMP=y +CONFIG_BT_SETTINGS=y + +# Enabled the dependencies of the BT_SETTINGS option. +CONFIG_FLASH=y +CONFIG_FLASH_MAP=y +CONFIG_NVS=y +CONFIG_SETTINGS_NVS=y +CONFIG_SETTINGS=y + +CONFIG_ASSERT=y +CONFIG_BT_TESTING=y +CONFIG_LOG=y + +CONFIG_BT_ID_MAX=3 +CONFIG_BT_MAX_PAIRED=2 + +CONFIG_BT_MAX_CONN=2 + +CONFIG_BT_PRIVACY=y diff --git a/tests/bsim/bluetooth/host/security/id_addr_update/peripheral/src/peripheral.c b/tests/bsim/bluetooth/host/security/id_addr_update/peripheral/src/peripheral.c new file mode 100644 index 00000000000..5420fdf0dd4 --- /dev/null +++ b/tests/bsim/bluetooth/host/security/id_addr_update/peripheral/src/peripheral.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_bt_utils.h" +#include "utils.h" +#include +#include +#include +#include + +#include +#include + +#include +LOG_MODULE_REGISTER(peripheral, LOG_LEVEL_INF); + +static void verify_equal_address(struct bt_conn *conn_a, struct bt_conn *conn_b) +{ + int err; + struct bt_conn_info info_a; + struct bt_conn_info info_b; + + err = bt_conn_get_info(conn_a, &info_a); + ASSERT(!err, "Unexpected info_a result."); + + err = bt_conn_get_info(conn_b, &info_b); + ASSERT(!err, "Unexpected info_b result."); + + ASSERT(bt_addr_le_eq(info_a.le.dst, info_b.le.dst), + "Conn A address is not equal with the conn B address"); +} + +void peripheral(void) +{ + bs_bt_utils_setup(); + + int id_a; + int id_b; + + struct bt_conn *conn_a; + struct bt_conn *conn_b; + + /* Create two identities that will simultaneously connect with the same central peer. */ + id_a = bt_id_create(NULL, NULL); + ASSERT(id_a >= 0, "bt_id_create id_a failed (err %d)\n", id_a); + + id_b = bt_id_create(NULL, NULL); + ASSERT(id_b >= 0, "bt_id_create id_b failed (err %d)\n", id_b); + + /* Connect with the first identity. */ + LOG_INF("adv"); + advertise_connectable(id_a); + LOG_INF("wait conn"); + wait_connected(&conn_a); + + /* Send battery notification on the first connection. */ + wait_bas_ccc_subscription(); + bas_notify(conn_a); + + /* Connect with the second identity. */ + LOG_INF("adv id 2"); + advertise_connectable(id_b); + wait_connected(&conn_b); + + /* Wait for the pairing completed callback on the second identity. */ + wait_pairing_completed(); + + /* Both connections should relate to the identity address of the same Central peer. */ + verify_equal_address(conn_a, conn_b); + + /* Send notification after identity address resolution to the first connection object. */ + bas_notify(conn_a); + + /* Disconnect the first identity. */ + wait_disconnected(); + clear_conn(conn_a); + + /* Disconnect the second identity. */ + wait_disconnected(); + clear_conn(conn_b); + + PASS("PASS\n"); +} + +static const struct bst_test_instance test_to_add[] = { + { + .test_id = "peripheral", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = peripheral, + }, + BSTEST_END_MARKER, +}; + +static struct bst_test_list *install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, test_to_add); +}; + +bst_test_install_t test_installers[] = {install, NULL}; + +int main(void) +{ + bst_main(); + return 0; +} diff --git a/tests/bsim/bluetooth/host/security/id_addr_update/peripheral/src/utils.c b/tests/bsim/bluetooth/host/security/id_addr_update/peripheral/src/utils.c new file mode 100644 index 00000000000..1e566fe1d4b --- /dev/null +++ b/tests/bsim/bluetooth/host/security/id_addr_update/peripheral/src/utils.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_bt_utils.h" +#include "utils.h" + +BUILD_ASSERT(CONFIG_BT_MAX_PAIRED >= 2, "CONFIG_BT_MAX_PAIRED is too small."); +BUILD_ASSERT(CONFIG_BT_ID_MAX >= 3, "CONFIG_BT_ID_MAX is too small."); +BUILD_ASSERT(CONFIG_BT_MAX_CONN == 2, "CONFIG_BT_MAX_CONN should be equal to two."); + +void test_tick(bs_time_t HW_device_time) +{ + bs_trace_debug_time(0, "Simulation ends now.\n"); + if (bst_result != Passed) { + bst_result = Failed; + bs_trace_error("Test did not pass before simulation ended.\n"); + } +} + +void test_init(void) +{ + bst_ticker_set_next_tick_absolute(TEST_TIMEOUT_SIMULATED); + bst_result = In_progress; +} + +DEFINE_FLAG(flag_has_new_conn); +struct bt_conn *new_conn; + +DEFINE_FLAG(flag_has_disconnected); + +void clear_conn(struct bt_conn *conn) +{ + if (new_conn == conn) { + new_conn = NULL; + } + + ASSERT(conn, "Test error: No new_conn!\n"); + bt_conn_unref(conn); +} + +void wait_connected(struct bt_conn **conn) +{ + WAIT_FOR_FLAG(flag_has_new_conn); + UNSET_FLAG(flag_has_new_conn); + + ASSERT(new_conn, "connection unpopulated."); + *conn = new_conn; + new_conn = NULL; +} + +void wait_disconnected(void) +{ + WAIT_FOR_FLAG(flag_has_disconnected); + UNSET_FLAG(flag_has_disconnected); +} + +static void print_conn_state_transition(const char *prefix, struct bt_conn *conn) +{ + int err; + struct bt_conn_info info; + char addr_str[BT_ADDR_LE_STR_LEN]; + + err = bt_conn_get_info(conn, &info); + ASSERT(!err, "Unexpected conn info result."); + + bt_addr_le_to_str(info.le.dst, addr_str, sizeof(addr_str)); + printk("%s: %s\n", prefix, addr_str); +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + print_conn_state_transition("Disonnected", conn); + SET_FLAG(flag_has_disconnected); +} + +static void connected(struct bt_conn *conn, uint8_t err) +{ + ASSERT((!new_conn || (conn == new_conn)), "Unexpected new connection."); + + if (!new_conn) { + new_conn = bt_conn_ref(conn); + } + + if (err != 0) { + clear_conn(conn); + return; + } + + print_conn_state_transition("Connected", conn); + SET_FLAG(flag_has_new_conn); +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected, + .disconnected = disconnected, +}; + +DEFINE_FLAG(flag_pairing_completed); + +static void pairing_complete(struct bt_conn *conn, bool bonded) +{ + print_conn_state_transition("Paired", conn); + SET_FLAG(flag_pairing_completed); +} + +static struct bt_conn_auth_info_cb bt_conn_auth_info_cb = { + .pairing_complete = pairing_complete, +}; + +void set_security(struct bt_conn *conn, bt_security_t sec) +{ + int err; + + err = bt_conn_set_security(conn, sec); + ASSERT(!err, "Err bt_conn_set_security %d", err); +} + +void wait_pairing_completed(void) +{ + WAIT_FOR_FLAG(flag_pairing_completed); + UNSET_FLAG(flag_pairing_completed); +} + +void bs_bt_utils_setup(void) +{ + int err; + + err = bt_enable(NULL); + ASSERT(!err, "bt_enable failed.\n"); + err = bt_conn_auth_info_cb_register(&bt_conn_auth_info_cb); + ASSERT(!err, "bt_conn_auth_info_cb_register failed.\n"); + + err = settings_load(); + ASSERT(!err, "settings_load failed.\n"); +} + +void disconnect(struct bt_conn *conn) +{ + int err; + + err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + ASSERT(!err, "Err bt_conn_disconnect %d", err); +} + +void advertise_connectable(int id) +{ + int err; + struct bt_le_adv_param param = {}; + + param.id = id; + param.interval_min = 0x0020; + param.interval_max = 0x4000; + param.options |= BT_LE_ADV_OPT_ONE_TIME; + param.options |= BT_LE_ADV_OPT_CONNECTABLE; + + err = bt_le_adv_start(¶m, NULL, 0, NULL, 0); + ASSERT(!err, "Advertising failed to start (err %d)\n", err); +} + +DEFINE_FLAG(flag_bas_ccc_subscribed); +static uint8_t bas_level = 50; + +static void bas_ccc_cfg_changed(const struct bt_gatt_attr *attr, + uint16_t value) +{ + ARG_UNUSED(attr); + + if (value == BT_GATT_CCC_NOTIFY) { + printk("BAS CCCD: notification enabled\n"); + SET_FLAG(flag_bas_ccc_subscribed); + } +} + +void wait_bas_ccc_subscription(void) +{ + WAIT_FOR_FLAG(flag_bas_ccc_subscribed); + UNSET_FLAG(flag_bas_ccc_subscribed); +} + +static ssize_t bas_read(struct bt_conn *conn, + const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset) +{ + uint8_t lvl8 = bas_level; + + return bt_gatt_attr_read(conn, attr, buf, len, offset, &lvl8, + sizeof(lvl8)); +} + +BT_GATT_SERVICE_DEFINE(bas, + BT_GATT_PRIMARY_SERVICE(BT_UUID_BAS), + BT_GATT_CHARACTERISTIC(BT_UUID_BAS_BATTERY_LEVEL, + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, + BT_GATT_PERM_READ, bas_read, NULL, &bas_level), + BT_GATT_CCC(bas_ccc_cfg_changed, + BT_GATT_PERM_READ | BT_GATT_PERM_WRITE), +); + +void bas_notify(struct bt_conn *conn) +{ + int err; + + err = bt_gatt_notify(conn, &bas.attrs[2], &bas_level, sizeof(bas_level)); + ASSERT(!err, "bt_gatt_notify failed (err %d)\n", err); +} + +DEFINE_FLAG(flag_bas_has_notification); diff --git a/tests/bsim/bluetooth/host/security/id_addr_update/peripheral/src/utils.h b/tests/bsim/bluetooth/host/security/id_addr_update/peripheral/src/utils.h new file mode 100644 index 00000000000..01690b2c82c --- /dev/null +++ b/tests/bsim/bluetooth/host/security/id_addr_update/peripheral/src/utils.h @@ -0,0 +1,18 @@ +#include +#include + +void test_tick(bs_time_t HW_device_time); +void test_init(void); + +void bs_bt_utils_setup(void); + +void clear_conn(struct bt_conn *conn); +void wait_connected(struct bt_conn **conn); +void wait_disconnected(void); +void disconnect(struct bt_conn *conn); +void advertise_connectable(int id); + +void set_security(struct bt_conn *conn, bt_security_t sec); +void wait_pairing_completed(void); + +void bas_notify(struct bt_conn *conn); diff --git a/tests/bsim/bluetooth/host/security/id_addr_update/prj.conf b/tests/bsim/bluetooth/host/security/id_addr_update/prj.conf deleted file mode 100644 index 818505da4c5..00000000000 --- a/tests/bsim/bluetooth/host/security/id_addr_update/prj.conf +++ /dev/null @@ -1,26 +0,0 @@ -CONFIG_BT=y -CONFIG_BT_PERIPHERAL=y -CONFIG_BT_CENTRAL=y -CONFIG_BT_GATT_CLIENT=y - -# Both BT_SMP and BT_SETTINGS options need to be enabled to trigger -# code execution of the bt_gatt_identity_resolved function. -CONFIG_BT_SMP=y -CONFIG_BT_SETTINGS=y - -# Enabled the dependencies of the BT_SETTINGS option. -CONFIG_FLASH=y -CONFIG_FLASH_MAP=y -CONFIG_NVS=y -CONFIG_SETTINGS_NVS=y -CONFIG_SETTINGS=y - -CONFIG_ASSERT=y -CONFIG_BT_TESTING=y -CONFIG_LOG=y - -CONFIG_BT_ID_MAX=3 -CONFIG_BT_MAX_PAIRED=2 -CONFIG_BT_MAX_CONN=2 - -CONFIG_BT_PRIVACY=y diff --git a/tests/bsim/bluetooth/host/security/id_addr_update/src/bs_bt_utils.c b/tests/bsim/bluetooth/host/security/id_addr_update/src/bs_bt_utils.c deleted file mode 100644 index dcf7c4535a0..00000000000 --- a/tests/bsim/bluetooth/host/security/id_addr_update/src/bs_bt_utils.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "bs_bt_utils.h" - -BUILD_ASSERT(CONFIG_BT_MAX_PAIRED >= 2, "CONFIG_BT_MAX_PAIRED is too small."); -BUILD_ASSERT(CONFIG_BT_ID_MAX >= 3, "CONFIG_BT_ID_MAX is too small."); -BUILD_ASSERT(CONFIG_BT_MAX_CONN == 2, "CONFIG_BT_MAX_CONN should be equal to two."); -BUILD_ASSERT(CONFIG_BT_GATT_CLIENT, "CONFIG_BT_GATT_CLIENT is disabled."); - -#define BS_SECONDS(dur_sec) ((bs_time_t)dur_sec * 1000000) -#define TEST_TIMEOUT_SIMULATED BS_SECONDS(60) - -void test_tick(bs_time_t HW_device_time) -{ - bs_trace_debug_time(0, "Simulation ends now.\n"); - if (bst_result != Passed) { - bst_result = Failed; - bs_trace_error("Test did not pass before simulation ended.\n"); - } -} - -void test_init(void) -{ - bst_ticker_set_next_tick_absolute(TEST_TIMEOUT_SIMULATED); - bst_result = In_progress; -} - -DEFINE_FLAG(flag_has_new_conn); -struct bt_conn *new_conn; - -DEFINE_FLAG(flag_has_disconnected); - -void clear_conn(struct bt_conn *conn) -{ - if (new_conn == conn) { - new_conn = NULL; - } - - ASSERT(conn, "Test error: No new_conn!\n"); - bt_conn_unref(conn); -} - -void wait_connected(struct bt_conn **conn) -{ - WAIT_FOR_FLAG(flag_has_new_conn); - UNSET_FLAG(flag_has_new_conn); - - ASSERT(new_conn, "connection unpopulated."); - *conn = new_conn; - new_conn = NULL; -} - -void wait_disconnected(void) -{ - WAIT_FOR_FLAG(flag_has_disconnected); - UNSET_FLAG(flag_has_disconnected); -} - -static void print_conn_state_transition(const char *prefix, struct bt_conn *conn) -{ - int err; - struct bt_conn_info info; - char addr_str[BT_ADDR_LE_STR_LEN]; - - err = bt_conn_get_info(conn, &info); - ASSERT(!err, "Unexpected conn info result."); - - bt_addr_le_to_str(info.le.dst, addr_str, sizeof(addr_str)); - printk("%s: %s\n", prefix, addr_str); -} - -static void disconnected(struct bt_conn *conn, uint8_t reason) -{ - print_conn_state_transition("Disonnected", conn); - SET_FLAG(flag_has_disconnected); -} - -static void connected(struct bt_conn *conn, uint8_t err) -{ - ASSERT((!new_conn || (conn == new_conn)), "Unexpected new connection."); - - if (!new_conn) { - new_conn = bt_conn_ref(conn); - } - - if (err != 0) { - clear_conn(conn); - return; - } - - print_conn_state_transition("Connected", conn); - SET_FLAG(flag_has_new_conn); -} - -BT_CONN_CB_DEFINE(conn_callbacks) = { - .connected = connected, - .disconnected = disconnected, -}; - -DEFINE_FLAG(flag_pairing_completed); - -static void pairing_complete(struct bt_conn *conn, bool bonded) -{ - print_conn_state_transition("Paired", conn); - SET_FLAG(flag_pairing_completed); -} - -static struct bt_conn_auth_info_cb bt_conn_auth_info_cb = { - .pairing_complete = pairing_complete, -}; - -void set_security(struct bt_conn *conn, bt_security_t sec) -{ - int err; - - err = bt_conn_set_security(conn, sec); - ASSERT(!err, "Err bt_conn_set_security %d", err); -} - -void wait_pairing_completed(void) -{ - WAIT_FOR_FLAG(flag_pairing_completed); - UNSET_FLAG(flag_pairing_completed); -} - -void bs_bt_utils_setup(void) -{ - int err; - - err = bt_enable(NULL); - ASSERT(!err, "bt_enable failed.\n"); - err = bt_conn_auth_info_cb_register(&bt_conn_auth_info_cb); - ASSERT(!err, "bt_conn_auth_info_cb_register failed.\n"); - - err = settings_load(); - ASSERT(!err, "settings_load failed.\n"); -} - -static void scan_connect_to_first_result__device_found(const bt_addr_le_t *addr, int8_t rssi, - uint8_t type, struct net_buf_simple *ad) -{ - char addr_str[BT_ADDR_LE_STR_LEN]; - int err; - - /* We're only interested in connectable events */ - if (type != BT_HCI_ADV_IND && type != BT_HCI_ADV_DIRECT_IND) { - FAIL("Unexpected advertisement type."); - } - - bt_addr_le_to_str(addr, addr_str, sizeof(addr_str)); - printk("Got scan result, connecting.. dst %s, RSSI %d\n", addr_str, rssi); - - err = bt_le_scan_stop(); - ASSERT(!err, "Err bt_le_scan_stop %d", err); - - err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT, &new_conn); - ASSERT(!err, "Err bt_conn_le_create %d", err); -} - -void scan_connect_to_first_result(void) -{ - int err; - - err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, scan_connect_to_first_result__device_found); - ASSERT(!err, "Err bt_le_scan_start %d", err); -} - -void disconnect(struct bt_conn *conn) -{ - int err; - - err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); - ASSERT(!err, "Err bt_conn_disconnect %d", err); -} - -void advertise_connectable(int id) -{ - int err; - struct bt_le_adv_param param = {}; - - param.id = id; - param.interval_min = 0x0020; - param.interval_max = 0x4000; - param.options |= BT_LE_ADV_OPT_ONE_TIME; - param.options |= BT_LE_ADV_OPT_CONNECTABLE; - - err = bt_le_adv_start(¶m, NULL, 0, NULL, 0); - ASSERT(!err, "Advertising failed to start (err %d)\n", err); -} - -DEFINE_FLAG(flag_bas_ccc_subscribed); -static uint8_t bas_level = 50; - -static void bas_ccc_cfg_changed(const struct bt_gatt_attr *attr, - uint16_t value) -{ - ARG_UNUSED(attr); - - if (value == BT_GATT_CCC_NOTIFY) { - printk("BAS CCCD: notification enabled\n"); - SET_FLAG(flag_bas_ccc_subscribed); - } -} - -void wait_bas_ccc_subscription(void) -{ - WAIT_FOR_FLAG(flag_bas_ccc_subscribed); - UNSET_FLAG(flag_bas_ccc_subscribed); -} - -static ssize_t bas_read(struct bt_conn *conn, - const struct bt_gatt_attr *attr, void *buf, - uint16_t len, uint16_t offset) -{ - uint8_t lvl8 = bas_level; - - return bt_gatt_attr_read(conn, attr, buf, len, offset, &lvl8, - sizeof(lvl8)); -} - -BT_GATT_SERVICE_DEFINE(bas, - BT_GATT_PRIMARY_SERVICE(BT_UUID_BAS), - BT_GATT_CHARACTERISTIC(BT_UUID_BAS_BATTERY_LEVEL, - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, - BT_GATT_PERM_READ, bas_read, NULL, &bas_level), - BT_GATT_CCC(bas_ccc_cfg_changed, - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE), -); - -void bas_notify(struct bt_conn *conn) -{ - int err; - - err = bt_gatt_notify(conn, &bas.attrs[2], &bas_level, sizeof(bas_level)); - ASSERT(!err, "bt_gatt_notify failed (err %d)\n", err); -} - -DEFINE_FLAG(flag_bas_has_notification); - -static uint8_t bas_notify_func(struct bt_conn *conn, - struct bt_gatt_subscribe_params *params, - const void *data, uint16_t length) -{ - const uint8_t *lvl8 = data; - - if ((length == 1) && (*lvl8 == bas_level)) { - printk("BAS notification\n"); - SET_FLAG(flag_bas_has_notification); - } - - return BT_GATT_ITER_CONTINUE; -} - -void wait_bas_notification(void) -{ - WAIT_FOR_FLAG(flag_bas_has_notification); - UNSET_FLAG(flag_bas_has_notification); -} - -void bas_subscribe(struct bt_conn *conn) -{ - int err; - static struct bt_gatt_subscribe_params subscribe_params = {0}; - - subscribe_params.ccc_handle = bt_gatt_attr_get_handle(&bas.attrs[3]); - subscribe_params.value_handle = bt_gatt_attr_get_handle(&bas.attrs[2]); - subscribe_params.value = BT_GATT_CCC_NOTIFY; - subscribe_params.notify = bas_notify_func; - - err = bt_gatt_subscribe(conn, &subscribe_params); - ASSERT(!err, "bt_gatt_subscribe failed (err %d)\n", err); -} diff --git a/tests/bsim/bluetooth/host/security/id_addr_update/src/bs_bt_utils.h b/tests/bsim/bluetooth/host/security/id_addr_update/src/bs_bt_utils.h deleted file mode 100644 index bbee0ab7880..00000000000 --- a/tests/bsim/bluetooth/host/security/id_addr_update/src/bs_bt_utils.h +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Common functions and helpers for BSIM GATT tests - * - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "bs_tracing.h" -#include "bs_types.h" -#include "bstests.h" -#include "time_machine.h" -#include "zephyr/sys/__assert.h" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -extern enum bst_result_t bst_result; - -#define DECLARE_FLAG(flag) extern atomic_t flag -#define DEFINE_FLAG(flag) atomic_t flag = (atomic_t) false -#define SET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) true) -#define UNSET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) false) -#define WAIT_FOR_FLAG(flag) \ - while (!(bool)atomic_get(&flag)) { \ - (void)k_sleep(K_MSEC(1)); \ - } -#define WAIT_FOR_FLAG_UNSET(flag) \ - while ((bool)atomic_get(&flag)) { \ - (void)k_sleep(K_MSEC(1)); \ - } -#define TAKE_FLAG(flag) \ - while (!(bool)atomic_cas(&flag, true, false)) { \ - (void)k_sleep(K_MSEC(1)); \ - } -#define GET_FLAG(flag) \ - (bool)atomic_get(&flag) - -#define ASSERT(expr, ...) \ - do { \ - if (!(expr)) { \ - FAIL(__VA_ARGS__); \ - } \ - } while (0) - -#define FAIL(...) \ - do { \ - bst_result = Failed; \ - bs_trace_error_time_line(__VA_ARGS__); \ - } while (0) - -#define PASS(...) \ - do { \ - bst_result = Passed; \ - bs_trace_info_time(1, __VA_ARGS__); \ - } while (0) - -void test_tick(bs_time_t HW_device_time); -void test_init(void); - -void bs_bt_utils_setup(void); - -void clear_conn(struct bt_conn *conn); -void wait_connected(struct bt_conn **conn); -void wait_disconnected(void); -void disconnect(struct bt_conn *conn); -void scan_connect_to_first_result(void); -void advertise_connectable(int id); - -void set_security(struct bt_conn *conn, bt_security_t sec); -void wait_pairing_completed(void); - -void bas_subscribe(struct bt_conn *conn); -void wait_bas_ccc_subscription(void); -void bas_notify(struct bt_conn *conn); -void wait_bas_notification(void); diff --git a/tests/bsim/bluetooth/host/security/id_addr_update/src/central.c b/tests/bsim/bluetooth/host/security/id_addr_update/src/central.c deleted file mode 100644 index 0739a92ea79..00000000000 --- a/tests/bsim/bluetooth/host/security/id_addr_update/src/central.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "bs_bt_utils.h" -#include "zephyr/bluetooth/addr.h" -#include "zephyr/bluetooth/conn.h" - -#include - -#include - -void central(void) -{ - bs_bt_utils_setup(); - - struct bt_conn *conn_a; - struct bt_conn *conn_b; - - /* Connect to the first identity of the peripheral. */ - scan_connect_to_first_result(); - wait_connected(&conn_a); - - /* Subscribe to battery notifications and wait on the first one. */ - bas_subscribe(conn_a); - wait_bas_notification(); - - /* Connect to the second identity of the peripheral. */ - scan_connect_to_first_result(); - wait_connected(&conn_b); - - /* Establish security with the second identity and resolve identity address. */ - set_security(conn_b, BT_SECURITY_L2); - wait_pairing_completed(); - - /* Wait for notification from the first connection after identity address resolution. */ - wait_bas_notification(); - - /* Disconnect the first identity of the peripheral. */ - disconnect(conn_a); - wait_disconnected(); - clear_conn(conn_a); - - /* Disconnect the second identity of the peripheral. */ - disconnect(conn_b); - wait_disconnected(); - clear_conn(conn_b); - - PASS("PASS\n"); -} diff --git a/tests/bsim/bluetooth/host/security/id_addr_update/src/main.c b/tests/bsim/bluetooth/host/security/id_addr_update/src/main.c deleted file mode 100644 index 7553f7b5f83..00000000000 --- a/tests/bsim/bluetooth/host/security/id_addr_update/src/main.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "bs_bt_utils.h" -#include "bstests.h" - -void central(void); -void peripheral(void); - -static const struct bst_test_instance test_to_add[] = { - { - .test_id = "central", - .test_post_init_f = test_init, - .test_tick_f = test_tick, - .test_main_f = central, - }, - { - .test_id = "peripheral", - .test_post_init_f = test_init, - .test_tick_f = test_tick, - .test_main_f = peripheral, - }, - BSTEST_END_MARKER, -}; - -static struct bst_test_list *install(struct bst_test_list *tests) -{ - return bst_add_tests(tests, test_to_add); -}; - -bst_test_install_t test_installers[] = {install, NULL}; - -int main(void) -{ - bst_main(); - return 0; -} diff --git a/tests/bsim/bluetooth/host/security/id_addr_update/src/peripheral.c b/tests/bsim/bluetooth/host/security/id_addr_update/src/peripheral.c deleted file mode 100644 index 530b5287dbf..00000000000 --- a/tests/bsim/bluetooth/host/security/id_addr_update/src/peripheral.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "bs_bt_utils.h" -#include "zephyr/bluetooth/addr.h" -#include "zephyr/bluetooth/bluetooth.h" -#include "zephyr/bluetooth/conn.h" -#include "zephyr/toolchain/gcc.h" - -#include -#include - -static void verify_equal_address(struct bt_conn *conn_a, struct bt_conn *conn_b) -{ - int err; - struct bt_conn_info info_a; - struct bt_conn_info info_b; - - err = bt_conn_get_info(conn_a, &info_a); - ASSERT(!err, "Unexpected info_a result."); - - err = bt_conn_get_info(conn_b, &info_b); - ASSERT(!err, "Unexpected info_b result."); - - ASSERT(bt_addr_le_eq(info_a.le.dst, info_b.le.dst), - "Conn A address is not equal with the conn B address"); -} - -void peripheral(void) -{ - bs_bt_utils_setup(); - - int id_a; - int id_b; - - struct bt_conn *conn_a; - struct bt_conn *conn_b; - - /* Create two identities that will simultaneously connect with the same central peer. */ - id_a = bt_id_create(NULL, NULL); - ASSERT(id_a >= 0, "bt_id_create id_a failed (err %d)\n", id_a); - - id_b = bt_id_create(NULL, NULL); - ASSERT(id_b >= 0, "bt_id_create id_b failed (err %d)\n", id_b); - - /* Connect with the first identity. */ - advertise_connectable(id_a); - wait_connected(&conn_a); - - /* Send battery notification on the first connection. */ - wait_bas_ccc_subscription(); - bas_notify(conn_a); - - /* Connect with the second identity. */ - advertise_connectable(id_b); - wait_connected(&conn_b); - - /* Wait for the pairing completed callback on the second identity. */ - wait_pairing_completed(); - - /* Both connections should relate to the identity address of the same Central peer. */ - verify_equal_address(conn_a, conn_b); - - /* Send notification after identity address resolution to the first connection object. */ - bas_notify(conn_a); - - /* Disconnect the first identity. */ - wait_disconnected(); - clear_conn(conn_a); - - /* Disconnect the second identity. */ - wait_disconnected(); - clear_conn(conn_b); - - PASS("PASS\n"); -} diff --git a/tests/bsim/bluetooth/host/security/id_addr_update/test_scripts/_compile.sh b/tests/bsim/bluetooth/host/security/id_addr_update/test_scripts/_compile.sh index a19e4baf6e4..ca555ea526c 100755 --- a/tests/bsim/bluetooth/host/security/id_addr_update/test_scripts/_compile.sh +++ b/tests/bsim/bluetooth/host/security/id_addr_update/test_scripts/_compile.sh @@ -17,4 +17,8 @@ BOARD_ROOT="${BOARD_ROOT:-${ZEPHYR_BASE}}" INCR_BUILD=1 mkdir -p ${WORK_DIR} source ${ZEPHYR_BASE}/tests/bsim/compile.source -app="tests/bsim/bluetooth/host/security/$test_name" compile + +app="tests/bsim/bluetooth/host/security/$test_name/central" compile +app="tests/bsim/bluetooth/host/security/$test_name/peripheral" compile + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/host/security/id_addr_update/test_scripts/_env.sh b/tests/bsim/bluetooth/host/security/id_addr_update/test_scripts/_env.sh index fec28290db9..8ac4b9eaf69 100755 --- a/tests/bsim/bluetooth/host/security/id_addr_update/test_scripts/_env.sh +++ b/tests/bsim/bluetooth/host/security/id_addr_update/test_scripts/_env.sh @@ -9,10 +9,11 @@ bash_source_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" test_name="id_addr_update" bsim_bin="${BSIM_OUT_PATH}/bin" verbosity_level=2 -BOARD="${BOARD:-nrf52_bsim}" +board="${BOARD:-nrf52_bsim}" simulation_id="$test_name" -central_exe="${bsim_bin}/bs_${BOARD}_tests_bsim_bluetooth_host_security_${test_name}_prj_conf" -peripheral_exe="${central_exe}" +test_path="tests_bsim_bluetooth_host_security_${test_name}" +central_exe="${bsim_bin}/bs_${board}_${test_path}_central_prj_conf" +peripheral_exe="${bsim_bin}/bs_${board}_${test_path}_peripheral_prj_conf" function print_var { # Print a shell-sourceable variable definition. @@ -24,7 +25,7 @@ function print_var { print_var test_name print_var bsim_bin print_var verbosity_level -print_var BOARD +print_var board print_var simulation_id print_var central_exe print_var peripheral_exe diff --git a/tests/bsim/bluetooth/host/security/id_addr_update/test_scripts/run_test.sh b/tests/bsim/bluetooth/host/security/id_addr_update/test_scripts/run_test.sh index 351f44523cc..b44fa62d61c 100755 --- a/tests/bsim/bluetooth/host/security/id_addr_update/test_scripts/run_test.sh +++ b/tests/bsim/bluetooth/host/security/id_addr_update/test_scripts/run_test.sh @@ -9,7 +9,7 @@ bash_source_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" source "${bash_source_dir}/_env.sh" source ${ZEPHYR_BASE}/tests/bsim/sh_common.source -EXECUTE_TIMEOUT=30 +EXECUTE_TIMEOUT=10 cd ${BSIM_OUT_PATH}/bin @@ -17,7 +17,7 @@ Execute "$central_exe" \ -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central -RealEncryption=1 Execute "$peripheral_exe" \ - -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral -RealEncryption=1 + -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral -RealEncryption=1 -rs=200 Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ -D=2 -sim_length=60e6 $@ diff --git a/tests/bsim/bluetooth/host/security/security_changed_callback/CMakeLists.txt b/tests/bsim/bluetooth/host/security/security_changed_callback/CMakeLists.txt new file mode 100644 index 00000000000..e6dcda9d49a --- /dev/null +++ b/tests/bsim/bluetooth/host/security/security_changed_callback/CMakeLists.txt @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(bsim_test_security_changed_callback) + +target_sources(app PRIVATE + src/bs_bt_utils.c + src/central.c + src/main.c + src/peripheral.c +) + +zephyr_include_directories( + ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ + ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ +) diff --git a/tests/bsim/bluetooth/host/security/security_changed_callback/prj.conf b/tests/bsim/bluetooth/host/security/security_changed_callback/prj.conf new file mode 100644 index 00000000000..abf1bd7ffb7 --- /dev/null +++ b/tests/bsim/bluetooth/host/security/security_changed_callback/prj.conf @@ -0,0 +1,24 @@ +CONFIG_BT_TESTING=y + +CONFIG_BT=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y + +CONFIG_BT_SMP=y +CONFIG_BT_PRIVACY=y + +CONFIG_SETTINGS=y +CONFIG_BT_SETTINGS=y +CONFIG_FLASH=y +CONFIG_FLASH_PAGE_LAYOUT=y +CONFIG_NVS=y +CONFIG_FLASH_MAP=y +CONFIG_SETTINGS_NVS=y + +CONFIG_ASSERT=y + +CONFIG_LOG=y +CONFIG_BT_SMP_LOG_LEVEL_DBG=y + +CONFIG_THREAD_NAME=y +CONFIG_LOG_THREAD_ID_PREFIX=y diff --git a/tests/bsim/bluetooth/host/security/security_changed_callback/src/bs_bt_utils.c b/tests/bsim/bluetooth/host/security/security_changed_callback/src/bs_bt_utils.c new file mode 100644 index 00000000000..3f9fabe544a --- /dev/null +++ b/tests/bsim/bluetooth/host/security/security_changed_callback/src/bs_bt_utils.c @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_bt_utils.h" + +#include +#include + +LOG_MODULE_REGISTER(bs_bt_utils, LOG_LEVEL_DBG); + +#define BS_SECONDS(dur_sec) ((bs_time_t)dur_sec * 1000000) +#define TEST_TIMEOUT_SIMULATED BS_SECONDS(60) + +void test_tick(bs_time_t HW_device_time) +{ + bs_trace_debug_time(0, "Simulation ends now.\n"); + if (bst_result != Passed) { + bst_result = Failed; + bs_trace_error("Test did not pass before simulation ended.\n"); + } +} + +void test_init(void) +{ + bst_ticker_set_next_tick_absolute(TEST_TIMEOUT_SIMULATED); + bst_result = In_progress; +} + +DEFINE_FLAG(flag_is_connected); +struct bt_conn *g_conn; + +void wait_connected(void) +{ + LOG_DBG("Wait for connection..."); + WAIT_FOR_FLAG(flag_is_connected); +} + +void wait_disconnected(void) +{ + WAIT_FOR_FLAG_UNSET(flag_is_connected); +} + +static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) +{ + LOG_DBG("security changed"); +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + UNSET_FLAG(flag_is_connected); +} + +static void connected(struct bt_conn *conn, uint8_t err) +{ + ASSERT((!g_conn || (conn == g_conn)), "Unexpected new connection."); + + if (!g_conn) { + g_conn = bt_conn_ref(conn); + } + + if (err != 0) { + clear_g_conn(); + return; + } + + SET_FLAG(flag_is_connected); +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected, + .disconnected = disconnected, + .security_changed = security_changed, +}; + +void clear_g_conn(void) +{ + struct bt_conn *conn; + + conn = g_conn; + g_conn = NULL; + ASSERT(conn, "Test error: No g_conn!\n"); + bt_conn_unref(conn); +} + +/* The following flags are raised by events and lowered by test code. */ +DEFINE_FLAG(flag_pairing_complete); +DEFINE_FLAG(flag_bonded); +DEFINE_FLAG(flag_not_bonded); + +static void pairing_complete(struct bt_conn *conn, bool bonded) +{ + LOG_INF("pairing complete"); + SET_FLAG(flag_pairing_complete); + + if (bonded) { + SET_FLAG(flag_bonded); + LOG_DBG("Bonded status: true"); + } else { + SET_FLAG(flag_not_bonded); + LOG_DBG("Bonded status: false"); + } +} + +static void pairing_failed(struct bt_conn *conn, enum bt_security_err err) +{ + LOG_INF("Pairing failed"); +} + +static struct bt_conn_auth_info_cb bt_conn_auth_info_cb = { + .pairing_complete = pairing_complete, + .pairing_failed = pairing_failed, +}; + +void bs_bt_utils_setup(void) +{ + int err; + + err = bt_enable(NULL); + ASSERT(!err, "bt_enable failed.\n"); + err = bt_conn_auth_info_cb_register(&bt_conn_auth_info_cb); + ASSERT(!err, "bt_conn_auth_info_cb_register failed.\n"); + + err = settings_load(); + if (err) { + FAIL("Settings load failed (err %d)\n", err); + } +} + +static void stop_scan_and_connect(const bt_addr_le_t *addr, + int8_t rssi, + uint8_t type, + struct net_buf_simple *ad) +{ + char addr_str[BT_ADDR_LE_STR_LEN]; + int err; + + if (g_conn != NULL) { + return; + } + + bt_addr_le_to_str(addr, addr_str, sizeof(addr_str)); + printk("Got scan result, connecting.. dst %s, RSSI %d\n", addr_str, rssi); + + err = bt_le_scan_stop(); + ASSERT(!err, "Err bt_le_scan_stop %d", err); + + err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT, &g_conn); + ASSERT(!err, "Err bt_conn_le_create %d", err); +} + +void scan_connect_to_first_result(void) +{ + int err; + + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, stop_scan_and_connect); + ASSERT(!err, "Err bt_le_scan_start %d", err); +} + +void set_security(bt_security_t sec) +{ + int err; + + err = bt_conn_set_security(g_conn, sec); + ASSERT(!err, "Err bt_conn_set_security %d", err); +} + +void advertise_connectable(int id, bt_addr_le_t *directed_dst) +{ + int err; + struct bt_le_adv_param param = {}; + + param.id = id; + param.interval_min = 0x0020; + param.interval_max = 0x4000; + param.options |= BT_LE_ADV_OPT_ONE_TIME; + param.options |= BT_LE_ADV_OPT_CONNECTABLE; + + if (directed_dst) { + param.options |= BT_LE_ADV_OPT_DIR_ADDR_RPA; + param.peer = directed_dst; + } + + err = bt_le_adv_start(¶m, NULL, 0, NULL, 0); + ASSERT(err == 0, "Advertising failed to start (err %d)\n", err); +} diff --git a/tests/bsim/bluetooth/host/security/security_changed_callback/src/bs_bt_utils.h b/tests/bsim/bluetooth/host/security/security_changed_callback/src/bs_bt_utils.h new file mode 100644 index 00000000000..ed6cea0d5ef --- /dev/null +++ b/tests/bsim/bluetooth/host/security/security_changed_callback/src/bs_bt_utils.h @@ -0,0 +1,79 @@ +/** + * Common functions and helpers for BSIM tests + * + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_tracing.h" +#include "bs_types.h" +#include "bstests.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +extern enum bst_result_t bst_result; + +#define DECLARE_FLAG(flag) extern atomic_t flag +#define DEFINE_FLAG(flag) atomic_t flag = (atomic_t) false +#define SET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) true) +#define UNSET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) false) +#define WAIT_FOR_FLAG(flag) \ + while (!(bool)atomic_get(&flag)) { \ + (void)k_sleep(K_MSEC(1)); \ + } +#define WAIT_FOR_FLAG_UNSET(flag) \ + while ((bool)atomic_get(&flag)) { \ + (void)k_sleep(K_MSEC(1)); \ + } +#define TAKE_FLAG(flag) \ + while (!(bool)atomic_cas(&flag, true, false)) { \ + (void)k_sleep(K_MSEC(1)); \ + } +#define GET_FLAG(flag) (bool)atomic_get(&flag) + +#define ASSERT(expr, ...) \ + do { \ + if (!(expr)) { \ + FAIL(__VA_ARGS__); \ + } \ + } while (0) + +#define FAIL(...) \ + do { \ + bst_result = Failed; \ + bs_trace_error_time_line(__VA_ARGS__); \ + } while (0) + +#define PASS(...) \ + do { \ + bst_result = Passed; \ + bs_trace_info_time(1, __VA_ARGS__); \ + } while (0) + +void test_tick(bs_time_t HW_device_time); +void test_init(void); + +DECLARE_FLAG(flag_pairing_complete); +DECLARE_FLAG(flag_bonded); +DECLARE_FLAG(flag_not_bonded); + +extern struct bt_conn *g_conn; +void wait_connected(void); +void wait_disconnected(void); +void clear_g_conn(void); +void bs_bt_utils_setup(void); +void scan_connect_to_first_result(void); +void set_security(bt_security_t sec); +void advertise_connectable(int id, bt_addr_le_t *directed_dst); +void set_bondable(bool enable); diff --git a/tests/bsim/bluetooth/host/security/security_changed_callback/src/central.c b/tests/bsim/bluetooth/host/security/security_changed_callback/src/central.c new file mode 100644 index 00000000000..abf896d8618 --- /dev/null +++ b/tests/bsim/bluetooth/host/security/security_changed_callback/src/central.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include + +#include "bs_bt_utils.h" + +LOG_MODULE_REGISTER(test_central, LOG_LEVEL_DBG); + +BUILD_ASSERT(CONFIG_BT_BONDABLE, "CONFIG_BT_BONDABLE must be enabled by default."); + +void central(void) +{ + LOG_DBG("===== Central ====="); + + bs_bt_utils_setup(); + + scan_connect_to_first_result(); + wait_connected(); + set_security(BT_SECURITY_L2); + + TAKE_FLAG(flag_pairing_complete); + TAKE_FLAG(flag_bonded); + + LOG_DBG("Wait for disconnection..."); + wait_disconnected(); + + clear_g_conn(); + + PASS("PASS\n"); +} diff --git a/tests/bsim/bluetooth/host/security/security_changed_callback/src/main.c b/tests/bsim/bluetooth/host/security/security_changed_callback/src/main.c new file mode 100644 index 00000000000..07bf437f8fa --- /dev/null +++ b/tests/bsim/bluetooth/host/security/security_changed_callback/src/main.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_bt_utils.h" +#include "bstests.h" + +void central(void); +void peripheral_unpair_in_sec_cb(void); +void peripheral_disconnect_in_sec_cb(void); + +static const struct bst_test_instance test_to_add[] = { + { + .test_id = "central", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = central, + }, + { + .test_id = "peripheral_unpair_in_sec_cb", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = peripheral_unpair_in_sec_cb, + }, + { + .test_id = "peripheral_disconnect_in_sec_cb", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = peripheral_disconnect_in_sec_cb, + }, + BSTEST_END_MARKER, +}; + +static struct bst_test_list *install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, test_to_add); +}; + +bst_test_install_t test_installers[] = {install, NULL}; + +int main(void) +{ + bst_main(); + return 0; +} diff --git a/tests/bsim/bluetooth/host/security/security_changed_callback/src/peripheral.c b/tests/bsim/bluetooth/host/security/security_changed_callback/src/peripheral.c new file mode 100644 index 00000000000..56c351efb05 --- /dev/null +++ b/tests/bsim/bluetooth/host/security/security_changed_callback/src/peripheral.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include +#include + +#include "bs_bt_utils.h" + +LOG_MODULE_REGISTER(test_peripheral, LOG_LEVEL_DBG); + +BUILD_ASSERT(CONFIG_BT_BONDABLE, "CONFIG_BT_BONDABLE must be enabled by default."); + +static void pairing_complete_unpair(struct bt_conn *conn, bool bonded) +{ + FAIL("Pairing succeed\n"); +} + +static void peripheral_security_changed_unpair(struct bt_conn *conn, + bt_security_t level, + enum bt_security_err err) +{ + /* Try to trigger fault here */ + k_msleep(2000); + LOG_INF("remove pairing..."); + bt_unpair(BT_ID_DEFAULT, bt_conn_get_dst(conn)); + LOG_DBG("unpaired"); +} + +void peripheral_unpair_in_sec_cb(void) +{ + LOG_DBG("===== Peripheral (will trigger unpair in sec changed cb) ====="); + + int err; + struct bt_conn_cb peripheral_cb = {}; + struct bt_conn_auth_info_cb peripheral_auth_info_cb = {}; + + /* Call `bt_unpair` in security changed callback */ + + peripheral_cb.security_changed = peripheral_security_changed_unpair; + peripheral_auth_info_cb.pairing_complete = pairing_complete_unpair; + + bs_bt_utils_setup(); + + bt_conn_cb_register(&peripheral_cb); + err = bt_conn_auth_info_cb_register(&peripheral_auth_info_cb); + ASSERT(!err, "bt_conn_auth_info_cb_register failed.\n"); + + advertise_connectable(BT_ID_DEFAULT, NULL); + wait_connected(); + + wait_disconnected(); + + clear_g_conn(); + + PASS("PASS\n"); +} + +static void pairing_failed_disconnect(struct bt_conn *conn, enum bt_security_err err) +{ + FAIL("Pairing failed\n"); +} + +static void peripheral_security_changed_disconnect(struct bt_conn *conn, + bt_security_t level, + enum bt_security_err err) +{ + /* Try to trigger fault here */ + k_msleep(2000); + LOG_INF("disconnecting..."); + bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); +} + +void peripheral_disconnect_in_sec_cb(void) +{ + LOG_DBG("===== Peripheral (will trigger unpair in sec changed cb) ====="); + + int err; + struct bt_conn_cb peripheral_cb = {}; + struct bt_conn_auth_info_cb peripheral_auth_info_cb = {}; + + /* Disconnect in security changed callback */ + + peripheral_cb.security_changed = peripheral_security_changed_disconnect; + peripheral_auth_info_cb.pairing_failed = pairing_failed_disconnect; + + bs_bt_utils_setup(); + + bt_conn_cb_register(&peripheral_cb); + err = bt_conn_auth_info_cb_register(&peripheral_auth_info_cb); + ASSERT(!err, "bt_conn_auth_info_cb_register failed.\n"); + + advertise_connectable(BT_ID_DEFAULT, NULL); + wait_connected(); + + wait_disconnected(); + + clear_g_conn(); + + PASS("PASS\n"); +} diff --git a/tests/bsim/bluetooth/host/security/security_changed_callback/test_scripts/_compile.sh b/tests/bsim/bluetooth/host/security/security_changed_callback/test_scripts/_compile.sh new file mode 100755 index 00000000000..a7d3a9c569f --- /dev/null +++ b/tests/bsim/bluetooth/host/security/security_changed_callback/test_scripts/_compile.sh @@ -0,0 +1,18 @@ +#!/bin/env bash +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +set -eu + +# Terminate running simulations (if any) +${BSIM_COMPONENTS_PATH}/common/stop_bsim.sh + +test_name='security_changed_callback' + +: "${BSIM_OUT_PATH:?BSIM_OUT_PATH must be defined}" +bsim_bin="${BSIM_OUT_PATH}/bin" +BOARD="${BOARD:-nrf52_bsim}" +test_exe="${bsim_bin}/bs_${BOARD}_tests_bsim_bluetooth_host_security_${test_name}_prj_conf" + +west build -b nrf52_bsim -d build && \ + cp -v build/zephyr/zephyr.exe "${test_exe}" diff --git a/tests/bsim/bluetooth/host/security/security_changed_callback/test_scripts/security_changed_callback.sh b/tests/bsim/bluetooth/host/security/security_changed_callback/test_scripts/security_changed_callback.sh new file mode 100755 index 00000000000..122ba43e12f --- /dev/null +++ b/tests/bsim/bluetooth/host/security/security_changed_callback/test_scripts/security_changed_callback.sh @@ -0,0 +1,35 @@ +#!/bin/env bash +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +test_name='security_changed_callback' +test_exe="bs_${BOARD}_tests_bsim_bluetooth_host_security_${test_name}_prj_conf" +simulation_id="${test_name}" +verbosity_level=2 +EXECUTE_TIMEOUT=30 + +cd ${BSIM_OUT_PATH}/bin + +Execute "./${test_exe}" \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central + +Execute "./${test_exe}" \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral_disconnect_in_sec_cb + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=60e6 + +wait_for_background_jobs + +Execute "./${test_exe}" \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central + +Execute "./${test_exe}" \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral_unpair_in_sec_cb + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=60e6 + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/ll/bis/Kconfig.sysbuild b/tests/bsim/bluetooth/ll/bis/Kconfig.sysbuild new file mode 100644 index 00000000000..6c89fddc9f3 --- /dev/null +++ b/tests/bsim/bluetooth/ll/bis/Kconfig.sysbuild @@ -0,0 +1,14 @@ +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config NET_CORE_BOARD + string + default "nrf5340bsim_nrf5340_cpunet" if $(BOARD) = "nrf5340bsim_nrf5340_cpuapp" + +config NATIVE_SIMULATOR_PRIMARY_MCU_INDEX + int + # Let's pass the test arguments to the application MCU test + # otherwise by default they would have gone to the net core. + default 0 if $(BOARD) = "nrf5340bsim_nrf5340_cpuapp" diff --git a/tests/bsim/bluetooth/ll/bis/prj.conf b/tests/bsim/bluetooth/ll/bis/prj.conf index c599e0d0656..02e2f3168db 100644 --- a/tests/bsim/bluetooth/ll/bis/prj.conf +++ b/tests/bsim/bluetooth/ll/bis/prj.conf @@ -21,3 +21,6 @@ CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=251 CONFIG_BT_CTLR_SYNC_ISO_PDU_LEN_MAX=251 CONFIG_BT_CTLR_TEST=y + +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_ACL_RX_SIZE=255 diff --git a/tests/bsim/bluetooth/ll/bis/src/main.c b/tests/bsim/bluetooth/ll/bis/src/main.c index eb1edeb6711..232613171aa 100644 --- a/tests/bsim/bluetooth/ll/bis/src/main.c +++ b/tests/bsim/bluetooth/ll/bis/src/main.c @@ -183,7 +183,7 @@ static void iso_send(struct k_work *work) iso_data_len = MAX(sizeof(seq_num), ((seq_num % CONFIG_BT_ISO_TX_MTU) + 1)); net_buf_add_mem(buf, iso_data, iso_data_len); - printk("ISO send: seq_num %u\n", seq_num); + bs_trace_info_time(4, "ISO send: seq_num %u\n", seq_num); ret = bt_iso_chan_send(&bis_iso_chan, buf, seq_num++, BT_ISO_TIMESTAMP_NONE); if (ret < 0) { @@ -338,7 +338,7 @@ static void create_big(struct bt_le_ext_adv *adv, struct bt_iso_big **big) printk("ISO connected\n"); } -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) static void create_advanced_big(struct bt_le_ext_adv *adv, struct bt_iso_big **big) { struct bt_iso_big_create_param big_create_param; @@ -377,7 +377,7 @@ static void create_advanced_big(struct bt_le_ext_adv *adv, struct bt_iso_big **b } printk("ISO connected\n"); } -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ static void terminate_big(struct bt_iso_big *big) { @@ -441,7 +441,7 @@ static void test_iso_main(void) k_sleep(K_MSEC(2500)); printk("Periodic Advertising and ISO Channel Map Update..."); - err = ll_chm_update(chan_map); + err = bt_le_set_chan_map(chan_map); if (err) { FAIL("Channel Map Update failed.\n"); } @@ -469,7 +469,7 @@ static void test_iso_main(void) terminate_big(big); big = NULL; -#if defined(CONFIG_BT_ISO_ADVANCED) +#if defined(CONFIG_BT_ISO_TEST_PARAMS) /* Quick check to just verify that creating a BIG using advanced/test * parameters work */ @@ -477,7 +477,7 @@ static void test_iso_main(void) terminate_big(big); big = NULL; -#endif /* CONFIG_BT_ISO_ADVANCED */ +#endif /* CONFIG_BT_ISO_TEST_PARAMS */ k_sleep(K_MSEC(10000)); diff --git a/tests/bsim/bluetooth/ll/bis/sysbuild.cmake b/tests/bsim/bluetooth/ll/bis/sysbuild.cmake new file mode 100644 index 00000000000..69397264edf --- /dev/null +++ b/tests/bsim/bluetooth/ll/bis/sysbuild.cmake @@ -0,0 +1,24 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if(NOT("${SB_CONFIG_NET_CORE_BOARD}" STREQUAL "")) + set(NET_APP hci_ipc) + set(NET_APP_SRC_DIR ${ZEPHYR_BASE}/samples/bluetooth/${NET_APP}) + + ExternalZephyrProject_Add( + APPLICATION ${NET_APP} + SOURCE_DIR ${NET_APP_SRC_DIR} + BOARD ${SB_CONFIG_NET_CORE_BOARD} + ) + + set(${NET_APP}_CONF_FILE + ${NET_APP_SRC_DIR}/nrf5340_cpunet_iso-bt_ll_sw_split.conf + CACHE INTERNAL "" + ) + + native_simulator_set_primary_mcu_index(${DEFAULT_IMAGE} ${NET_APP}) + + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) +endif() + +native_simulator_set_final_executable(${DEFAULT_IMAGE}) diff --git a/tests/bsim/bluetooth/ll/cis/Kconfig.sysbuild b/tests/bsim/bluetooth/ll/cis/Kconfig.sysbuild new file mode 100644 index 00000000000..6c89fddc9f3 --- /dev/null +++ b/tests/bsim/bluetooth/ll/cis/Kconfig.sysbuild @@ -0,0 +1,14 @@ +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config NET_CORE_BOARD + string + default "nrf5340bsim_nrf5340_cpunet" if $(BOARD) = "nrf5340bsim_nrf5340_cpuapp" + +config NATIVE_SIMULATOR_PRIMARY_MCU_INDEX + int + # Let's pass the test arguments to the application MCU test + # otherwise by default they would have gone to the net core. + default 0 if $(BOARD) = "nrf5340bsim_nrf5340_cpuapp" diff --git a/tests/bsim/bluetooth/ll/cis/overlay-acl_first_ft_cen_skip_4_se.conf b/tests/bsim/bluetooth/ll/cis/overlay-acl_first_ft_cen_skip_4_se.conf new file mode 100644 index 00000000000..e3a02840dba --- /dev/null +++ b/tests/bsim/bluetooth/ll/cis/overlay-acl_first_ft_cen_skip_4_se.conf @@ -0,0 +1,9 @@ +CONFIG_TEST_USE_LEGACY_ADVERTISING=n +CONFIG_TEST_CONNECT_ACL_FIRST=y +CONFIG_TEST_FT_CEN_SKIP_SUBEVENTS=y +CONFIG_TEST_FT_CEN_SKIP_EVENTS_COUNT=2 +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_ISO_MAX_CHAN=1 +CONFIG_BT_CTLR_LLCP_LOCAL_PROC_CTX_BUF_NUM=9 +CONFIG_BT_CTLR_ADVANCED_FEATURES=y +CONFIG_BT_CTLR_ISOAL_PSN_IGNORE=y diff --git a/tests/bsim/bluetooth/ll/cis/overlay-acl_first_ft_per_skip_4_se.conf b/tests/bsim/bluetooth/ll/cis/overlay-acl_first_ft_per_skip_4_se.conf new file mode 100644 index 00000000000..f1c78198c87 --- /dev/null +++ b/tests/bsim/bluetooth/ll/cis/overlay-acl_first_ft_per_skip_4_se.conf @@ -0,0 +1,9 @@ +CONFIG_TEST_USE_LEGACY_ADVERTISING=n +CONFIG_TEST_CONNECT_ACL_FIRST=y +CONFIG_TEST_FT_PER_SKIP_SUBEVENTS=y +CONFIG_TEST_FT_PER_SKIP_EVENTS_COUNT=2 +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_ISO_MAX_CHAN=1 +CONFIG_BT_CTLR_LLCP_LOCAL_PROC_CTX_BUF_NUM=9 +CONFIG_BT_CTLR_ADVANCED_FEATURES=y +CONFIG_BT_CTLR_ISOAL_PSN_IGNORE=y diff --git a/tests/bsim/bluetooth/ll/cis/src/main.c b/tests/bsim/bluetooth/ll/cis/src/main.c index b544546a404..fe0530eba05 100644 --- a/tests/bsim/bluetooth/ll/cis/src/main.c +++ b/tests/bsim/bluetooth/ll/cis/src/main.c @@ -104,7 +104,7 @@ static bt_addr_le_t peer_addr; #define NAME_LEN 30 -#define BUF_ALLOC_TIMEOUT (40) /* milliseconds */ +#define BUF_ALLOC_TIMEOUT (50) /* milliseconds */ NET_BUF_POOL_FIXED_DEFINE(tx_pool, CONFIG_BT_ISO_TX_BUF_COUNT, BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), 8, NULL); @@ -413,11 +413,14 @@ static void test_cis_central(void) cig_param.sca = BT_GAP_SCA_UNKNOWN; cig_param.packing = 0U; cig_param.framing = 0U; - cig_param.interval = ISO_INTERVAL_US; + cig_param.c_to_p_interval = ISO_INTERVAL_US; + cig_param.p_to_c_interval = ISO_INTERVAL_US; if (IS_ENABLED(CONFIG_TEST_FT_SKIP_SUBEVENTS)) { - cig_param.latency = ISO_LATENCY_FT_MS; + cig_param.c_to_p_latency = ISO_LATENCY_FT_MS; + cig_param.p_to_c_latency = ISO_LATENCY_FT_MS; } else { - cig_param.latency = ISO_LATENCY_MS; + cig_param.c_to_p_latency = ISO_LATENCY_MS; + cig_param.p_to_c_latency = ISO_LATENCY_MS; } printk("Create CIG..."); diff --git a/tests/bsim/bluetooth/ll/cis/sysbuild.cmake b/tests/bsim/bluetooth/ll/cis/sysbuild.cmake new file mode 100644 index 00000000000..a1258ecf1f2 --- /dev/null +++ b/tests/bsim/bluetooth/ll/cis/sysbuild.cmake @@ -0,0 +1,24 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if(NOT("${SB_CONFIG_NET_CORE_BOARD}" STREQUAL "")) + set(NET_APP hci_ipc) + set(NET_APP_SRC_DIR ${ZEPHYR_BASE}/samples/bluetooth/${NET_APP}) + + ExternalZephyrProject_Add( + APPLICATION ${NET_APP} + SOURCE_DIR ${NET_APP_SRC_DIR} + BOARD ${SB_CONFIG_NET_CORE_BOARD} + ) + + set(${NET_APP}_CONF_FILE + ${APP_DIR}/sysbuild/hci_ipc/nrf5340_cpunet_iso_acl_group-bt_ll_sw_split.conf + CACHE INTERNAL "" + ) + + native_simulator_set_primary_mcu_index(${DEFAULT_IMAGE} ${NET_APP}) + + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) +endif() + +native_simulator_set_final_executable(${DEFAULT_IMAGE}) diff --git a/tests/bsim/bluetooth/ll/cis/sysbuild/hci_ipc/nrf5340_cpunet_iso_acl_group-bt_ll_sw_split.conf b/tests/bsim/bluetooth/ll/cis/sysbuild/hci_ipc/nrf5340_cpunet_iso_acl_group-bt_ll_sw_split.conf new file mode 100644 index 00000000000..a3c8f43c71f --- /dev/null +++ b/tests/bsim/bluetooth/ll/cis/sysbuild/hci_ipc/nrf5340_cpunet_iso_acl_group-bt_ll_sw_split.conf @@ -0,0 +1,122 @@ +CONFIG_IPC_SERVICE=y +CONFIG_MBOX=y + +CONFIG_ISR_STACK_SIZE=1024 +CONFIG_IDLE_STACK_SIZE=256 +CONFIG_MAIN_STACK_SIZE=512 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512 +CONFIG_IPC_SERVICE_BACKEND_RPMSG_WQ_STACK_SIZE=512 +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_CBPRINTF_REDUCED_INTEGRAL=y + +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_HCI_RAW_RESERVE=1 +CONFIG_BT_MAX_CONN=4 + +# Workaround: Unable to allocate command buffer when using K_NO_WAIT since +# Host number of completed commands does not follow normal flow control. +CONFIG_BT_BUF_CMD_TX_COUNT=10 + +CONFIG_BT_BUF_EVT_RX_COUNT=16 + +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +# Tx/Rx Thread Stack Sizes +CONFIG_BT_HCI_TX_STACK_SIZE_WITH_PROMPT=y +CONFIG_BT_HCI_TX_STACK_SIZE=1152 +CONFIG_BT_RX_STACK_SIZE=640 +CONFIG_BT_CTLR_RX_PRIO_STACK_SIZE=448 + +# Host features +CONFIG_BT_EXT_ADV=y +CONFIG_BT_PER_ADV=y +CONFIG_BT_PER_ADV_SYNC=y +CONFIG_BT_PER_ADV_SYNC_MAX=2 + +# Broadcast and Connected ISO +CONFIG_BT_ISO_BROADCASTER=y +CONFIG_BT_ISO_SYNC_RECEIVER=y +CONFIG_BT_ISO_CENTRAL=y +CONFIG_BT_ISO_PERIPHERAL=y + +# ISO Streams +CONFIG_BT_ISO_MAX_CHAN=4 + +# Controller +CONFIG_BT_LL_SW_SPLIT=y +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_CTLR_DTM_HCI=y + +# Rx ACL and Adv Reports +CONFIG_BT_CTLR_RX_BUFFERS=9 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 + +# Coded PHY support +CONFIG_BT_CTLR_PHY_CODED=n + +# Advertising Sets and Extended Scanning +CONFIG_BT_CTLR_ADV_EXT=y +CONFIG_BT_CTLR_ADV_SET=3 +CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 +CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=1650 + +CONFIG_BT_CTLR_ADVANCED_FEATURES=y +CONFIG_BT_CTLR_ADV_AUX_SET=3 +CONFIG_BT_CTLR_ADV_AUX_PDU_BACK2BACK=y +CONFIG_BT_CTLR_ADV_SYNC_SET=3 +CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK=y +CONFIG_BT_CTLR_ADV_DATA_BUF_MAX=6 + +# Increase the below to receive interleaved advertising chains +CONFIG_BT_CTLR_SCAN_AUX_SET=1 + +CONFIG_BT_CTLR_ADV_RESERVE_MAX=n +CONFIG_BT_CTLR_CENTRAL_RESERVE_MAX=n +# CONFIG_BT_CTLR_CENTRAL_SPACING=10000 +CONFIG_BT_CTLR_CENTRAL_SPACING=0 +CONFIG_BT_CTLR_SLOT_RESERVATION_UPDATE=n +CONFIG_BT_CTLR_SCAN_UNRESERVED=n +CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH=y +CONFIG_BT_TICKER_EXT=y +CONFIG_BT_TICKER_EXT_SLOT_WINDOW_YIELD=y + +# Control Procedure +CONFIG_BT_CTLR_LLCP_LOCAL_PROC_CTX_BUF_NUM=9 + +# ISO Broadcaster Controller +CONFIG_BT_CTLR_ADV_EXT=y +CONFIG_BT_CTLR_ADV_PERIODIC=y +CONFIG_BT_CTLR_ADV_ISO=y +CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=251 +CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 + +# ISO Receive Controller +CONFIG_BT_CTLR_ADV_EXT=y +CONFIG_BT_CTLR_SYNC_PERIODIC=y +CONFIG_BT_CTLR_SYNC_ISO=y +CONFIG_BT_CTLR_SYNC_ISO_PDU_LEN_MAX=251 +CONFIG_BT_CTLR_SYNC_ISO_STREAM_MAX=2 + +# ISO Connection Oriented +CONFIG_BT_CTLR_CENTRAL_ISO=y +CONFIG_BT_CTLR_PERIPHERAL_ISO=y +CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=251 +CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251 +CONFIG_BT_CTLR_CONN_ISO_STREAMS=4 +CONFIG_BT_CTLR_CONN_ISO_STREAMS_PER_GROUP=4 + +# ISO Transmissions +CONFIG_BT_CTLR_ISO_TX_BUFFERS=18 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 +CONFIG_BT_CTLR_ISOAL_SOURCES=4 + +# ISO Receptions +CONFIG_BT_CTLR_ISO_RX_BUFFERS=8 +CONFIG_BT_CTLR_ISOAL_SINKS=4 + +# Tx Power Dynamic Control +CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y diff --git a/tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_cen_skip_4_se.sh b/tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_cen_skip_4_se.sh new file mode 100755 index 00000000000..f75790e3fcf --- /dev/null +++ b/tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_cen_skip_4_se.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +# Basic Connected ISO test: a Central connects to 1 Peripheral and tests RTN=2, +# FT=2, skips 4 subevents in the central +simulation_id="connected_iso_acl_first_ft_cen_skip_4_se" +verbosity_level=2 +EXECUTE_TIMEOUT=60 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_ll_cis_prj_conf_overlay-acl_first_ft_cen_skip_4_se_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_ll_cis_prj_conf_overlay-acl_first_ft_cen_skip_4_se_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=30e6 $@ + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_per_skip_4_se.sh b/tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_per_skip_4_se.sh new file mode 100755 index 00000000000..8fd00d9a057 --- /dev/null +++ b/tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_per_skip_4_se.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +# Basic Connected ISO test: a Central connects to 1 Peripheral and tests RTN=2, +# FT=2, skips 4 subevents in the peripheral +simulation_id="connected_iso_acl_first_ft_per_skip_4_se" +verbosity_level=2 +EXECUTE_TIMEOUT=60 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_ll_cis_prj_conf_overlay-acl_first_ft_per_skip_4_se_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_ll_cis_prj_conf_overlay-acl_first_ft_per_skip_4_se_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=30e6 $@ + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/ll/compile.sh b/tests/bsim/bluetooth/ll/compile.sh index 6d530d05d72..d16e17ed8ea 100755 --- a/tests/bsim/bluetooth/ll/compile.sh +++ b/tests/bsim/bluetooth/ll/compile.sh @@ -42,6 +42,7 @@ app=tests/bsim/bluetooth/ll/cis conf_overlay=overlay-peripheral_cis.conf compile app=tests/bsim/bluetooth/ll/cis conf_overlay=overlay-acl_first_ft_per_skip_2_se.conf compile app=tests/bsim/bluetooth/ll/cis conf_overlay=overlay-acl_first_ft_per_skip_4_se.conf compile app=tests/bsim/bluetooth/ll/cis conf_overlay=overlay-acl_first_ft_cen_skip_2_se.conf compile +app=tests/bsim/bluetooth/ll/cis conf_overlay=overlay-acl_first_ft_cen_skip_4_se.conf compile app=tests/bsim/bluetooth/ll/edtt/hci_test_app \ conf_file=prj_dut_llcp.conf compile diff --git a/tests/bsim/bluetooth/ll/conn/Kconfig.sysbuild b/tests/bsim/bluetooth/ll/conn/Kconfig.sysbuild new file mode 100644 index 00000000000..6c89fddc9f3 --- /dev/null +++ b/tests/bsim/bluetooth/ll/conn/Kconfig.sysbuild @@ -0,0 +1,14 @@ +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config NET_CORE_BOARD + string + default "nrf5340bsim_nrf5340_cpunet" if $(BOARD) = "nrf5340bsim_nrf5340_cpuapp" + +config NATIVE_SIMULATOR_PRIMARY_MCU_INDEX + int + # Let's pass the test arguments to the application MCU test + # otherwise by default they would have gone to the net core. + default 0 if $(BOARD) = "nrf5340bsim_nrf5340_cpuapp" diff --git a/tests/bsim/bluetooth/ll/conn/sysbuild.cmake b/tests/bsim/bluetooth/ll/conn/sysbuild.cmake new file mode 100644 index 00000000000..4dfa34ef519 --- /dev/null +++ b/tests/bsim/bluetooth/ll/conn/sysbuild.cmake @@ -0,0 +1,19 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if(NOT("${SB_CONFIG_NET_CORE_BOARD}" STREQUAL "")) + set(NET_APP hci_ipc) + set(NET_APP_SRC_DIR ${ZEPHYR_BASE}/samples/bluetooth/${NET_APP}) + + ExternalZephyrProject_Add( + APPLICATION ${NET_APP} + SOURCE_DIR ${NET_APP_SRC_DIR} + BOARD ${SB_CONFIG_NET_CORE_BOARD} + ) + + native_simulator_set_primary_mcu_index(${DEFAULT_IMAGE} ${NET_APP}) + + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) +endif() + +native_simulator_set_final_executable(${DEFAULT_IMAGE}) diff --git a/tests/bsim/bluetooth/ll/edtt/common/edtt_driver.h b/tests/bsim/bluetooth/ll/edtt/common/edtt_driver.h index 04b94c80294..576aa68fa11 100644 --- a/tests/bsim/bluetooth/ll/edtt/common/edtt_driver.h +++ b/tests/bsim/bluetooth/ll/edtt/common/edtt_driver.h @@ -10,7 +10,7 @@ #include #include -#include "zephyr/types.h" +#include #define EDTTT_NONBLOCK 0 #define EDTTT_BLOCK 1 diff --git a/tests/bsim/bluetooth/mesh/CMakeLists.txt b/tests/bsim/bluetooth/mesh/CMakeLists.txt index b1be544ed86..44c72dd9cbb 100644 --- a/tests/bsim/bluetooth/mesh/CMakeLists.txt +++ b/tests/bsim/bluetooth/mesh/CMakeLists.txt @@ -30,6 +30,7 @@ if(CONFIG_SETTINGS) src/test_dfu.c src/test_blob.c src/test_sar.c + src/test_lcd.c ) endif() @@ -46,6 +47,12 @@ elseif(CONFIG_BT_MESH_GATT_PROXY) src/test_advertiser.c ) + if(CONFIG_BT_MESH_V1d1) + target_sources(app PRIVATE + src/test_beacon.c + ) + endif() + elseif(CONFIG_BT_CTLR_LOW_LAT) target_sources(app PRIVATE @@ -72,7 +79,7 @@ else() src/test_blob.c src/test_op_agg.c src/test_sar.c - src/test_lcd.c + src/test_cdp1.c ) endif() diff --git a/tests/bsim/bluetooth/mesh/overlay_gatt.conf b/tests/bsim/bluetooth/mesh/overlay_gatt.conf index b2c1bba7fbf..f94a26d623f 100644 --- a/tests/bsim/bluetooth/mesh/overlay_gatt.conf +++ b/tests/bsim/bluetooth/mesh/overlay_gatt.conf @@ -4,4 +4,5 @@ CONFIG_BT_MESH_PB_GATT=y CONFIG_BT_MESH_LOW_POWER=n CONFIG_BT_MESH_FRIEND=n -CONFIG_BT_MESH_IV_UPDATE_TEST=n +CONFIG_BT_CENTRAL=y +CONFIG_BT_MESH_PROXY_CLIENT=y diff --git a/tests/bsim/bluetooth/mesh/overlay_pst.conf b/tests/bsim/bluetooth/mesh/overlay_pst.conf index 0933bdf1020..6a56ec8065b 100644 --- a/tests/bsim/bluetooth/mesh/overlay_pst.conf +++ b/tests/bsim/bluetooth/mesh/overlay_pst.conf @@ -19,3 +19,4 @@ CONFIG_BT_MESH_SEQ_STORE_RATE=1 CONFIG_BT_MESH_RPL_STORE_TIMEOUT=1 CONFIG_BT_MESH_STORE_TIMEOUT=1 CONFIG_BT_MESH_TX_SEG_RETRANS_COUNT=1 +CONFIG_BT_MESH_COMP_PST_BUF_SIZE=600 diff --git a/tests/bsim/bluetooth/mesh/prj.conf b/tests/bsim/bluetooth/mesh/prj.conf index 2e55a6a588b..b0738c4fa05 100644 --- a/tests/bsim/bluetooth/mesh/prj.conf +++ b/tests/bsim/bluetooth/mesh/prj.conf @@ -43,3 +43,4 @@ CONFIG_BT_MESH_CDB_NODE_COUNT=4 CONFIG_BT_MESH_PROV_OOB_PUBLIC_KEY=y CONFIG_BT_MESH_MODEL_EXTENSIONS=y CONFIG_BT_MESH_SUBNET_COUNT=5 +CONFIG_BT_TESTING=y diff --git a/tests/bsim/bluetooth/mesh/prj_mesh1d1.conf b/tests/bsim/bluetooth/mesh/prj_mesh1d1.conf index 2e08329b7ef..ab6066e01bf 100644 --- a/tests/bsim/bluetooth/mesh/prj_mesh1d1.conf +++ b/tests/bsim/bluetooth/mesh/prj_mesh1d1.conf @@ -25,6 +25,7 @@ CONFIG_BT_MESH_TX_SEG_MAX=32 CONFIG_BT_MESH_RX_SEG_MAX=32 CONFIG_BT_MESH_TX_SEG_MSG_COUNT=10 CONFIG_BT_MESH_RX_SEG_MSG_COUNT=10 +CONFIG_BT_MESH_SEG_BUFS=100 CONFIG_BT_MESH_CFG_CLI=y CONFIG_BT_MESH_MODEL_GROUP_COUNT=3 CONFIG_BT_MESH_LOW_POWER=y @@ -62,7 +63,11 @@ CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD=y CONFIG_BT_MESH_DFU_SLOT_CNT=4 CONFIG_BT_MESH_PRIV_BEACON_SRV=y CONFIG_BT_MESH_PRIV_BEACON_CLI=y +CONFIG_BT_MESH_OD_PRIV_PROXY_SRV=y +CONFIG_BT_MESH_OD_PRIV_PROXY_CLI=y CONFIG_BT_MESH_COMP_PAGE_1=y +CONFIG_BT_MESH_COMP_PAGE_2=y +CONFIG_BT_TESTING=y # Needed for RPR tests due to huge amount of retransmitted messages CONFIG_BT_MESH_MSG_CACHE_SIZE=64 diff --git a/tests/bsim/bluetooth/mesh/src/main.c b/tests/bsim/bluetooth/mesh/src/main.c index 3c314e24a58..127e52faa49 100644 --- a/tests/bsim/bluetooth/mesh/src/main.c +++ b/tests/bsim/bluetooth/mesh/src/main.c @@ -14,10 +14,15 @@ extern struct bst_test_list *test_provision_pst_install(struct bst_test_list *te #if defined(CONFIG_BT_MESH_V1d1) extern struct bst_test_list *test_dfu_install(struct bst_test_list *test); extern struct bst_test_list *test_blob_pst_install(struct bst_test_list *test); +extern struct bst_test_list *test_lcd_install(struct bst_test_list *test); extern struct bst_test_list *test_sar_pst_install(struct bst_test_list *test); #endif /* defined(CONFIG_BT_MESH_V1d1) */ #elif defined(CONFIG_BT_MESH_GATT_PROXY) extern struct bst_test_list *test_adv_install(struct bst_test_list *test); +#if defined(CONFIG_BT_MESH_V1d1) +extern struct bst_test_list *test_beacon_install(struct bst_test_list *tests); +#endif /* defined(CONFIG_BT_MESH_V1d1) */ + #elif defined(CONFIG_BT_CTLR_LOW_LAT) extern struct bst_test_list *test_transport_install(struct bst_test_list *tests); extern struct bst_test_list *test_friendship_install(struct bst_test_list *tests); @@ -35,7 +40,7 @@ extern struct bst_test_list *test_adv_install(struct bst_test_list *test); extern struct bst_test_list *test_blob_install(struct bst_test_list *test); extern struct bst_test_list *test_op_agg_install(struct bst_test_list *test); extern struct bst_test_list *test_sar_install(struct bst_test_list *test); -extern struct bst_test_list *test_lcd_install(struct bst_test_list *test); +extern struct bst_test_list *test_cdp1_install(struct bst_test_list *test); #endif /* defined(CONFIG_BT_MESH_V1d1) */ #endif @@ -47,10 +52,14 @@ bst_test_install_t test_installers[] = { test_provision_pst_install, test_dfu_install, test_blob_pst_install, + test_lcd_install, test_sar_pst_install, #endif /* defined(CONFIG_BT_MESH_V1d1) */ #elif defined(CONFIG_BT_MESH_GATT_PROXY) test_adv_install, +#if defined(CONFIG_BT_MESH_V1d1) + test_beacon_install, +#endif /* defined(CONFIG_BT_MESH_V1d1) */ #elif defined(CONFIG_BT_CTLR_LOW_LAT) test_transport_install, test_friendship_install, @@ -68,7 +77,7 @@ bst_test_install_t test_installers[] = { test_blob_install, test_op_agg_install, test_sar_install, - test_lcd_install, + test_cdp1_install, #endif /* defined(CONFIG_BT_MESH_V1d1) */ #endif NULL diff --git a/tests/bsim/bluetooth/mesh/src/mesh_test.c b/tests/bsim/bluetooth/mesh/src/mesh_test.c index 95c9d09598f..5dce0c8dc9d 100644 --- a/tests/bsim/bluetooth/mesh/src/mesh_test.c +++ b/tests/bsim/bluetooth/mesh/src/mesh_test.c @@ -27,7 +27,7 @@ struct bt_mesh_test_stats test_stats; struct bt_mesh_msg_ctx test_send_ctx; static void (*ra_cb)(uint8_t *, size_t); -static int msg_rx(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int msg_rx(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { size_t len = buf->len + BT_MESH_MODEL_OP_LEN(TEST_MSG_OP_1); @@ -75,7 +75,7 @@ static int msg_rx(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, return 0; } -static int ra_rx(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, +static int ra_rx(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { LOG_INF("\tlen: %d bytes", buf->len); @@ -97,19 +97,19 @@ static const struct bt_mesh_model_op model_op[] = { BT_MESH_MODEL_OP_END }; -int __weak test_model_pub_update(struct bt_mesh_model *mod) +int __weak test_model_pub_update(const struct bt_mesh_model *mod) { return -1; } -int __weak test_model_settings_set(struct bt_mesh_model *model, +int __weak test_model_settings_set(const struct bt_mesh_model *model, const char *name, size_t len_rd, settings_read_cb read_cb, void *cb_arg) { return -1; } -void __weak test_model_reset(struct bt_mesh_model *model) +void __weak test_model_reset(const struct bt_mesh_model *model) { /* No-op. */ } @@ -128,19 +128,19 @@ static const struct bt_mesh_model_op vnd_model_op[] = { BT_MESH_MODEL_OP_END, }; -int __weak test_vnd_model_pub_update(struct bt_mesh_model *mod) +int __weak test_vnd_model_pub_update(const struct bt_mesh_model *mod) { return -1; } -int __weak test_vnd_model_settings_set(struct bt_mesh_model *model, +int __weak test_vnd_model_settings_set(const struct bt_mesh_model *model, const char *name, size_t len_rd, settings_read_cb read_cb, void *cb_arg) { return -1; } -void __weak test_vnd_model_reset(struct bt_mesh_model *model) +void __weak test_vnd_model_reset(const struct bt_mesh_model *model) { /* No-op. */ } @@ -166,7 +166,15 @@ static struct bt_mesh_model_pub health_pub = { static struct bt_mesh_sar_cfg_cli sar_cfg_cli; #endif -static struct bt_mesh_model models[] = { +#if defined(CONFIG_BT_MESH_PRIV_BEACONS) +static struct bt_mesh_priv_beacon_cli priv_beacon_cli; +#endif + +#if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_CLI) +static struct bt_mesh_od_priv_proxy_cli priv_proxy_cli; +#endif + +static const struct bt_mesh_model models[] = { BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), BT_MESH_MODEL_CB(TEST_MOD_ID, model_op, &pub, NULL, &test_model_cb), @@ -175,18 +183,28 @@ static struct bt_mesh_model models[] = { BT_MESH_MODEL_SAR_CFG_SRV, BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli), #endif +#if defined(CONFIG_BT_MESH_PRIV_BEACONS) + BT_MESH_MODEL_PRIV_BEACON_SRV, + BT_MESH_MODEL_PRIV_BEACON_CLI(&priv_beacon_cli), +#endif +#if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV) + BT_MESH_MODEL_OD_PRIV_PROXY_SRV, +#endif +#if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_CLI) + BT_MESH_MODEL_OD_PRIV_PROXY_CLI(&priv_proxy_cli), +#endif }; -struct bt_mesh_model *test_model = &models[2]; +const struct bt_mesh_model *test_model = &models[2]; -static struct bt_mesh_model vnd_models[] = { +static const struct bt_mesh_model vnd_models[] = { BT_MESH_MODEL_VND_CB(TEST_VND_COMPANY_ID, TEST_VND_MOD_ID, vnd_model_op, &vnd_pub, NULL, &test_vnd_model_cb), }; -struct bt_mesh_model *test_vnd_model = &vnd_models[0]; +const struct bt_mesh_model *test_vnd_model = &vnd_models[0]; -static struct bt_mesh_elem elems[] = { +static const struct bt_mesh_elem elems[] = { BT_MESH_ELEM(0, models, vnd_models), }; diff --git a/tests/bsim/bluetooth/mesh/src/mesh_test.h b/tests/bsim/bluetooth/mesh/src/mesh_test.h index 8e7f41cf978..a5c8694947b 100644 --- a/tests/bsim/bluetooth/mesh/src/mesh_test.h +++ b/tests/bsim/bluetooth/mesh/src/mesh_test.h @@ -31,7 +31,7 @@ #define TEST_VND_COMPANY_ID 0x1234 #define TEST_VND_MOD_ID 0x5678 -#define MODEL_LIST(...) ((struct bt_mesh_model[]){ __VA_ARGS__ }) +#define MODEL_LIST(...) ((const struct bt_mesh_model[]){ __VA_ARGS__ }) #define FAIL(msg, ...) \ do { \ @@ -66,21 +66,40 @@ } \ } while (0) -#define ASSERT_TRUE(cond, ...) \ +#define ASSERT_TRUE(cond) \ do { \ if (!(cond)) { \ bst_result = Failed; \ bs_trace_error_time_line( \ - #cond " is false.", ##__VA_ARGS__); \ + #cond " is false.\n"); \ } \ } while (0) -#define ASSERT_FALSE(cond, ...) \ +#define ASSERT_TRUE_MSG(cond, fmt, ...) \ + do { \ + if (!(cond)) { \ + bst_result = Failed; \ + bs_trace_error_time_line( \ + #cond " is false. " fmt, ##__VA_ARGS__); \ + } \ + } while (0) + + +#define ASSERT_FALSE(cond) \ + do { \ + if (cond) { \ + bst_result = Failed; \ + bs_trace_error_time_line( \ + #cond " is true.\n"); \ + } \ + } while (0) + +#define ASSERT_FALSE_MSG(cond, fmt, ...) \ do { \ if (cond) { \ bst_result = Failed; \ bs_trace_error_time_line( \ - #cond " is true.", ##__VA_ARGS__); \ + #cond " is true. " fmt, ##__VA_ARGS__); \ } \ } while (0) @@ -94,6 +113,31 @@ } \ } while (0) +#define ASSERT_IN_RANGE(got, min, max) \ + do { \ + if (!IN_RANGE(got, min, max)) { \ + bst_result = Failed; \ + bs_trace_error_time_line(#got " not in range %d <-> %d, " #got " = %d\n", \ + (min), (max), (got)); \ + } \ + } while (0) + +#define WAIT_FOR_COND(cond, wait) \ + do { \ + bool _err = false; \ + for (uint8_t sec = (wait); !(cond); sec--) { \ + if (!sec) { \ + _err = true; \ + break; \ + } \ + k_sleep(K_SECONDS(1)); \ + } \ + \ + if (_err) { \ + bst_result = Failed; \ + bs_trace_error_time_line("Waiting for " #cond " timed out\n"); \ + } \ + } while (0) struct bt_mesh_test_cfg { uint16_t addr; @@ -127,8 +171,8 @@ struct bt_mesh_test_sync_ctx { extern enum bst_result_t bst_result; extern const struct bt_mesh_test_cfg *cfg; -extern struct bt_mesh_model *test_model; -extern struct bt_mesh_model *test_vnd_model; +extern const struct bt_mesh_model *test_model; +extern const struct bt_mesh_model *test_vnd_model; extern const uint8_t test_net_key[16]; extern const uint8_t test_app_key[16]; extern const uint8_t test_va_uuid[16]; diff --git a/tests/bsim/bluetooth/mesh/src/test_access.c b/tests/bsim/bluetooth/mesh/src/test_access.c index 56fce393388..b8b10fd7634 100644 --- a/tests/bsim/bluetooth/mesh/src/test_access.c +++ b/tests/bsim/bluetooth/mesh/src/test_access.c @@ -35,15 +35,15 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_INF); #define RX_JITTER_MAX (10 + CONFIG_BT_MESH_NETWORK_TRANSMIT_COUNT * \ (CONFIG_BT_MESH_NETWORK_TRANSMIT_INTERVAL + 10)) -static int model1_init(struct bt_mesh_model *model); -static int model2_init(struct bt_mesh_model *model); -static int model3_init(struct bt_mesh_model *model); -static int model4_init(struct bt_mesh_model *model); -static int model5_init(struct bt_mesh_model *model); -static int test_msg_handler(struct bt_mesh_model *model, +static int model1_init(const struct bt_mesh_model *model); +static int model2_init(const struct bt_mesh_model *model); +static int model3_init(const struct bt_mesh_model *model); +static int model4_init(const struct bt_mesh_model *model); +static int model5_init(const struct bt_mesh_model *model); +static int test_msg_handler(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf); -static int test_msg_ne_handler(struct bt_mesh_model *model, +static int test_msg_ne_handler(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf); @@ -99,7 +99,7 @@ static const struct { static struct k_sem publish_sem; static bool publish_allow; -static int model1_update(struct bt_mesh_model *model) +static int model1_update(const struct bt_mesh_model *model) { model->pub->msg->data[1]++; @@ -108,7 +108,7 @@ static int model1_update(struct bt_mesh_model *model) return publish_allow ? k_sem_give(&publish_sem), 0 : -1; } -static int test_msgf_handler(struct bt_mesh_model *model, +static int test_msgf_handler(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -204,7 +204,7 @@ static const struct bt_mesh_model_op model_ne_op5[] = { static struct bt_mesh_cfg_cli cfg_cli; /* do not change model sequence. it will break pointer arithmetic. */ -static struct bt_mesh_model models[] = { +static const struct bt_mesh_model models[] = { BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), BT_MESH_MODEL_CB(TEST_MODEL_ID_1, model_op1, &model_pub1, NULL, &test_model1_cb), @@ -215,7 +215,7 @@ static struct bt_mesh_model models[] = { }; /* do not change model sequence. it will break pointer arithmetic. */ -static struct bt_mesh_model models_ne[] = { +static const struct bt_mesh_model models_ne[] = { BT_MESH_MODEL_CB(TEST_MODEL_ID_1, model_ne_op1, NULL, NULL, &test_model1_cb), BT_MESH_MODEL_CB(TEST_MODEL_ID_2, model_ne_op2, NULL, NULL, &test_model2_cb), BT_MESH_MODEL_CB(TEST_MODEL_ID_3, model_ne_op3, NULL, NULL, &test_model3_cb), @@ -223,9 +223,9 @@ static struct bt_mesh_model models_ne[] = { BT_MESH_MODEL_CB(TEST_MODEL_ID_5, model_ne_op5, NULL, NULL, &test_model5_cb), }; -static struct bt_mesh_model vnd_models[] = {}; +static const struct bt_mesh_model vnd_models[] = {}; -static struct bt_mesh_elem elems[] = { +static const struct bt_mesh_elem elems[] = { BT_MESH_ELEM(0, models, vnd_models), BT_MESH_ELEM(1, models_ne, vnd_models), }; @@ -246,43 +246,43 @@ const struct bt_mesh_comp local_comp = { * m4 mne4 */ -static int model1_init(struct bt_mesh_model *model) +static int model1_init(const struct bt_mesh_model *model) { return 0; } -static int model2_init(struct bt_mesh_model *model) +static int model2_init(const struct bt_mesh_model *model) { return 0; } -static int model3_init(struct bt_mesh_model *model) +static int model3_init(const struct bt_mesh_model *model) { ASSERT_OK(bt_mesh_model_extend(model, model - 2)); ASSERT_OK(bt_mesh_model_extend(model, model - 1)); - if (model->elem_idx == 0) { - ASSERT_OK(bt_mesh_model_extend(&models_ne[2], model)); + if (model->rt->elem_idx == 1) { + ASSERT_OK(bt_mesh_model_extend(model, &models[4])); } return 0; } -static int model4_init(struct bt_mesh_model *model) +static int model4_init(const struct bt_mesh_model *model) { ASSERT_OK(bt_mesh_model_extend(model, model - 1)); return 0; } -static int model5_init(struct bt_mesh_model *model) +static int model5_init(const struct bt_mesh_model *model) { ASSERT_OK(bt_mesh_model_extend(model, model - 4)); return 0; } -static int test_msg_handler(struct bt_mesh_model *model, +static int test_msg_handler(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -292,7 +292,7 @@ static int test_msg_handler(struct bt_mesh_model *model, return 0; } -static int test_msg_ne_handler(struct bt_mesh_model *model, +static int test_msg_ne_handler(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -515,7 +515,7 @@ static void pub_param_set(uint8_t period, uint8_t transmit) static void msgf_publish(void) { - struct bt_mesh_model *model = &models[2]; + const struct bt_mesh_model *model = &models[2]; bt_mesh_model_msg_init(model->pub->msg, TEST_MESSAGE_OP_F); net_buf_simple_add_u8(model->pub->msg, 1); @@ -591,7 +591,7 @@ static void recv_jitter_check(int32_t interval, uint8_t count) */ static void test_tx_period(void) { - struct bt_mesh_model *model = &models[2]; + const struct bt_mesh_model *model = &models[2]; bt_mesh_test_cfg_set(NULL, 60); bt_mesh_device_setup(&prov, &local_comp); @@ -647,7 +647,7 @@ static void test_rx_period(void) */ static void test_tx_transmit(void) { - struct bt_mesh_model *model = &models[2]; + const struct bt_mesh_model *model = &models[2]; uint8_t status; int err; @@ -719,7 +719,7 @@ static void test_rx_transmit(void) */ static void test_tx_cancel(void) { - struct bt_mesh_model *model = &models[2]; + const struct bt_mesh_model *model = &models[2]; int err; bt_mesh_test_cfg_set(NULL, 20); diff --git a/tests/bsim/bluetooth/mesh/src/test_advertiser.c b/tests/bsim/bluetooth/mesh/src/test_advertiser.c index 6a171b499bf..073651ae843 100644 --- a/tests/bsim/bluetooth/mesh/src/test_advertiser.c +++ b/tests/bsim/bluetooth/mesh/src/test_advertiser.c @@ -84,7 +84,7 @@ static void allocate_all_array(struct net_buf **buf, size_t num_buf, uint8_t xmi *buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL, xmit, K_NO_WAIT); - ASSERT_FALSE(!*buf, "Out of buffers"); + ASSERT_FALSE_MSG(!*buf, "Out of buffers\n"); buf++; } } @@ -96,7 +96,7 @@ static void verify_adv_queue_overflow(void) /* Verity Queue overflow */ dummy_buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL, BT_MESH_TRANSMIT(2, 20), K_NO_WAIT); - ASSERT_TRUE(!dummy_buf, "Unexpected extra buffer"); + ASSERT_TRUE_MSG(!dummy_buf, "Unexpected extra buffer\n"); } static bool check_delta_time(uint8_t transmit, uint64_t interval) @@ -162,7 +162,7 @@ static void realloc_end_cb(int err, void *cb_data) ASSERT_EQUAL(0, err); buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL, BT_MESH_TRANSMIT(2, 20), K_NO_WAIT); - ASSERT_FALSE(!buf, "Out of buffers"); + ASSERT_FALSE_MSG(!buf, "Out of buffers\n"); k_sem_give(&observer_sem); } @@ -248,13 +248,13 @@ static void rx_gatt_beacons(void) int err; err = bt_le_scan_start(&scan_param, gatt_scan_cb); - ASSERT_FALSE(err && err != -EALREADY, "starting scan failed (err %d)", err); + ASSERT_FALSE_MSG(err && err != -EALREADY, "Starting scan failed (err %d)\n", err); err = k_sem_take(&observer_sem, K_SECONDS(20)); ASSERT_OK(err); err = bt_le_scan_stop(); - ASSERT_FALSE(err && err != -EALREADY, "stopping scan failed (err %d)", err); + ASSERT_FALSE_MSG(err && err != -EALREADY, "Stopping scan failed (err %d)\n", err); } static void xmit_scan_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_type, @@ -294,13 +294,13 @@ static void rx_xmit_adv(void) int err; err = bt_le_scan_start(&scan_param, xmit_scan_cb); - ASSERT_FALSE(err && err != -EALREADY, "starting scan failed (err %d)", err); + ASSERT_FALSE_MSG(err && err != -EALREADY, "Starting scan failed (err %d)\n", err); err = k_sem_take(&observer_sem, K_SECONDS(20)); ASSERT_OK(err); err = bt_le_scan_stop(); - ASSERT_FALSE(err && err != -EALREADY, "stopping scan failed (err %d)", err); + ASSERT_FALSE_MSG(err && err != -EALREADY, "Stopping scan failed (err %d)\n", err); } static void send_order_start_cb(uint16_t duration, int err, void *user_data) @@ -324,7 +324,7 @@ static void send_order_end_cb(int err, void *user_data) struct net_buf *buf = (struct net_buf *)user_data; ASSERT_OK_MSG(err, "Failed adv start cb err (%d)", err); - ASSERT_TRUE(!buf->data, "Data not cleared!"); + ASSERT_TRUE_MSG(!buf->data, "Data not cleared!\n"); seq_checker++; LOG_INF("tx end: seq(%d)", seq_checker); @@ -368,7 +368,7 @@ static void receive_order(int expect_adv) int err; err = bt_le_scan_start(&scan_param, receive_order_scan_cb); - ASSERT_FALSE(err && err != -EALREADY, "starting scan failed (err %d)", err); + ASSERT_FALSE_MSG(err && err != -EALREADY, "Starting scan failed (err %d)\n", err); previous_checker = 0xff; for (int i = 0; i < expect_adv; i++) { @@ -377,7 +377,7 @@ static void receive_order(int expect_adv) } err = bt_le_scan_stop(); - ASSERT_FALSE(err && err != -EALREADY, "stopping scan failed (err %d)", err); + ASSERT_FALSE_MSG(err && err != -EALREADY, "Stopping scan failed (err %d)\n", err); } static void send_adv_buf(struct net_buf *buf, uint8_t curr, uint8_t prev) @@ -427,7 +427,7 @@ static void test_tx_cb_single(void) buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL, BT_MESH_TRANSMIT(2, 20), K_NO_WAIT); - ASSERT_FALSE(!buf, "Out of buffers"); + ASSERT_FALSE_MSG(!buf, "Out of buffers\n"); send_cb.start = single_start_cb; send_cb.end = single_end_cb; @@ -641,13 +641,13 @@ static void test_tx_random_order(void) ASSERT_FALSE_MSG(!buf[0], "Out of buffers\n"); buf[1] = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL, xmit, K_NO_WAIT); - ASSERT_FALSE(!buf[1], "Out of buffers"); + ASSERT_FALSE_MSG(!buf[1], "Out of buffers\n"); send_adv_buf(buf[0], 0, 0xff); buf[2] = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL, xmit, K_NO_WAIT); - ASSERT_FALSE(!buf[2], "Out of buffers"); + ASSERT_FALSE_MSG(!buf[2], "Out of buffers\n"); send_adv_buf(buf[2], 2, 0); diff --git a/tests/bsim/bluetooth/mesh/src/test_beacon.c b/tests/bsim/bluetooth/mesh/src/test_beacon.c index 117a90c1d86..e93c2301e46 100644 --- a/tests/bsim/bluetooth/mesh/src/test_beacon.c +++ b/tests/bsim/bluetooth/mesh/src/test_beacon.c @@ -13,6 +13,8 @@ #include "mesh/foundation.h" #include "mesh/crypto.h" #include "argparse.h" +#include "mesh/proxy_cli.h" +#include "mesh/proxy.h" #define LOG_MODULE_NAME test_beacon @@ -52,6 +54,22 @@ static const struct bt_mesh_test_cfg rx_cfg = { .dev_key = { 0x02 }, }; +typedef void (*snb_cb)(const struct bt_mesh_snb *snb); + +static snb_cb snb_cb_ptr; +static struct k_sem beacon_sem; + +static void snb_received(const struct bt_mesh_snb *snb) +{ + if (snb_cb_ptr) { + snb_cb_ptr(snb); + } +} + +BT_MESH_BEACON_CB_DEFINE(snb) = { + .snb_received = snb_received, +}; + /* Setting for scanner defining what beacon is expected next, SNB as default */ static uint8_t expected_beacon = BEACON_TYPE_SECURE; #if CONFIG_BT_MESH_V1d1 @@ -61,7 +79,7 @@ static struct bt_mesh_priv_beacon_cli priv_beacon_cli; static const struct bt_mesh_comp prb_comp = { .elem = - (struct bt_mesh_elem[]){ + (const struct bt_mesh_elem[]){ BT_MESH_ELEM(1, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), @@ -315,6 +333,8 @@ static struct { uint32_t iv_index; #if CONFIG_BT_MESH_V1d1 uint8_t random[13]; + uint64_t pp_hash; + uint64_t pp_random; bt_addr_le_t adv_addr; #endif bool (*process_cb)(const uint8_t *net_id, void *ctx); @@ -363,8 +383,9 @@ static void beacon_scan_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_ty } } -/* Listens to beacons for one beacon interval (10 seconds). */ -static bool wait_for_beacon(bool (*process_cb)(const uint8_t *net_id, void *ctx), void *ctx) +/* Listens to beacons */ +static bool wait_for_beacon(bt_le_scan_cb_t scan_cb, uint16_t wait, + bool (*process_cb)(const uint8_t *net_id, void *ctx), void *ctx) { struct bt_le_scan_param scan_param = { .type = BT_HCI_LE_SCAN_PASSIVE, @@ -378,7 +399,7 @@ static bool wait_for_beacon(bool (*process_cb)(const uint8_t *net_id, void *ctx) beacon.process_cb = process_cb; beacon.user_ctx = ctx; - err = bt_le_scan_start(&scan_param, beacon_scan_cb); + err = bt_le_scan_start(&scan_param, scan_cb); if (err && err != -EALREADY) { FAIL("starting scan failed (err %d)", err); } @@ -392,7 +413,7 @@ static bool wait_for_beacon(bool (*process_cb)(const uint8_t *net_id, void *ctx) * waiting time (BEACON_INTERVAL + 1) to guarantee that beacon comes * before timer expiration. */ - err = k_sem_take(&observer_sem, K_SECONDS(BEACON_INTERVAL + 1)); + err = k_sem_take(&observer_sem, K_SECONDS(wait)); if (!err) { received = true; } else { @@ -486,8 +507,8 @@ static void corrupted_beacon_test(const uint8_t *offsets, send_beacon(buf); buf->data[offsets[i]] ^= 0xFF; /* Ensure that interval is not affected. */ - ASSERT_TRUE(wait_for_beacon(NULL, NULL)); - ASSERT_TRUE(wait_for_beacon(NULL, NULL)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); ASSERT_EQUAL(0x00, beacon.flags); ASSERT_EQUAL(0x0000, beacon.iv_index); } @@ -500,8 +521,8 @@ static void corrupted_beacon_test(const uint8_t *offsets, /* The beacon interval shall be changed and the node shall skip transmission of the next * beacon. */ - ASSERT_FALSE(wait_for_beacon(NULL, NULL)); - ASSERT_TRUE(wait_for_beacon(NULL, NULL)); + ASSERT_FALSE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); ASSERT_EQUAL(0x02, beacon.flags); ASSERT_EQUAL(0x0001, beacon.iv_index); } @@ -588,16 +609,16 @@ static void test_tx_kr_old_key(void) */ beacon_create(&buf, test_net_key, 0x01, 0x0000); send_beacon(&buf); - ASSERT_FALSE(wait_for_beacon(NULL, NULL)); - ASSERT_TRUE(wait_for_beacon(NULL, NULL)); + ASSERT_FALSE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); ASSERT_EQUAL(0x00, beacon.flags); ASSERT_EQUAL(0x0000, beacon.iv_index); /* The old Net Key can still initiate IV Index update. */ beacon_create(&buf, test_net_key, 0x02, 0x0001); send_beacon(&buf); - ASSERT_FALSE(wait_for_beacon(NULL, NULL)); - ASSERT_TRUE(wait_for_beacon(NULL, NULL)); + ASSERT_FALSE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); ASSERT_EQUAL(0x02, beacon.flags); ASSERT_EQUAL(0x0001, beacon.iv_index); @@ -607,8 +628,8 @@ static void test_tx_kr_old_key(void) */ beacon_create(&buf, test_net_key_secondary, 0x03, 0x0001); send_beacon(&buf); - ASSERT_FALSE(wait_for_beacon(NULL, NULL)); - ASSERT_TRUE(wait_for_beacon(NULL, NULL)); + ASSERT_FALSE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); ASSERT_EQUAL(0x03, beacon.flags); ASSERT_EQUAL(0x0001, beacon.iv_index); @@ -617,8 +638,8 @@ static void test_tx_kr_old_key(void) */ beacon_create(&buf, test_net_key, 0x01, 0x0001); send_beacon(&buf); - ASSERT_TRUE(wait_for_beacon(NULL, NULL)); - ASSERT_TRUE(wait_for_beacon(NULL, NULL)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); ASSERT_EQUAL(0x03, beacon.flags); ASSERT_EQUAL(0x0001, beacon.iv_index); @@ -627,8 +648,8 @@ static void test_tx_kr_old_key(void) */ beacon_create(&buf, test_net_key_secondary, 0x02, 0x0001); send_beacon(&buf); - ASSERT_FALSE(wait_for_beacon(NULL, NULL)); - ASSERT_TRUE(wait_for_beacon(NULL, NULL)); + ASSERT_FALSE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); ASSERT_EQUAL(0x02, beacon.flags); ASSERT_EQUAL(0x0001, beacon.iv_index); @@ -637,8 +658,8 @@ static void test_tx_kr_old_key(void) */ beacon_create(&buf, test_net_key, 0x00, 0x0001); send_beacon(&buf); - ASSERT_TRUE(wait_for_beacon(NULL, NULL)); - ASSERT_TRUE(wait_for_beacon(NULL, NULL)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); ASSERT_EQUAL(0x02, beacon.flags); ASSERT_EQUAL(0x0001, beacon.iv_index); @@ -647,8 +668,8 @@ static void test_tx_kr_old_key(void) */ beacon_create(&buf, test_net_key_secondary, 0x00, 0x0001); send_beacon(&buf); - ASSERT_FALSE(wait_for_beacon(NULL, NULL)); - ASSERT_TRUE(wait_for_beacon(NULL, NULL)); + ASSERT_FALSE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); ASSERT_EQUAL(0x00, beacon.flags); ASSERT_EQUAL(0x0001, beacon.iv_index); @@ -784,8 +805,10 @@ static void test_tx_multiple_netkeys(void) */ beacon_create(&buf, net_key_pairs[i].primary, 0x01, 0x0000); send_beacon(&buf); - ASSERT_FALSE(wait_for_beacon(beacon_confirm_by_subnet, &buf.data[2])); - ASSERT_TRUE(wait_for_beacon(beacon_confirm_by_subnet, &buf.data[2])); + ASSERT_FALSE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, + beacon_confirm_by_subnet, &buf.data[2])); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, + beacon_confirm_by_subnet, &buf.data[2])); ASSERT_EQUAL(0x00, beacon.flags); ASSERT_EQUAL(0x0000, beacon.iv_index); @@ -794,8 +817,10 @@ static void test_tx_multiple_netkeys(void) */ beacon_create(&buf, net_key_pairs[i].secondary, 0x01, 0x0000); send_beacon(&buf); - ASSERT_FALSE(wait_for_beacon(beacon_confirm_by_subnet, net_id_secondary)); - ASSERT_TRUE(wait_for_beacon(beacon_confirm_by_subnet, net_id_secondary)); + ASSERT_FALSE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, + beacon_confirm_by_subnet, net_id_secondary)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, + beacon_confirm_by_subnet, net_id_secondary)); ASSERT_EQUAL(0x01, beacon.flags); ASSERT_EQUAL(0x0000, beacon.iv_index); @@ -804,8 +829,10 @@ static void test_tx_multiple_netkeys(void) */ beacon_create(&buf, net_key_pairs[i].primary, 0x00, 0x0000); send_beacon(&buf); - ASSERT_TRUE(wait_for_beacon(beacon_confirm_by_subnet, net_id_secondary)); - ASSERT_TRUE(wait_for_beacon(beacon_confirm_by_subnet, net_id_secondary)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, + beacon_confirm_by_subnet, net_id_secondary)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, + beacon_confirm_by_subnet, net_id_secondary)); ASSERT_EQUAL(0x01, beacon.flags); ASSERT_EQUAL(0x0000, beacon.iv_index); @@ -814,8 +841,10 @@ static void test_tx_multiple_netkeys(void) */ beacon_create(&buf, net_key_pairs[i].secondary, 0x00, 0x0000); send_beacon(&buf); - ASSERT_FALSE(wait_for_beacon(beacon_confirm_by_subnet, net_id_secondary)); - ASSERT_TRUE(wait_for_beacon(beacon_confirm_by_subnet, net_id_secondary)); + ASSERT_FALSE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, + beacon_confirm_by_subnet, net_id_secondary)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, + beacon_confirm_by_subnet, net_id_secondary)); ASSERT_EQUAL(0x00, beacon.flags); ASSERT_EQUAL(0x0000, beacon.iv_index); } @@ -823,13 +852,15 @@ static void test_tx_multiple_netkeys(void) /* Create a valid beacon secured with unknown Net Key. The node shall ignore the beacon and * continue sending beacons regularly. */ - uint8_t unknown_net_key[16] = { 0xde, 0xad, 0xbe, 0xef }; + uint8_t unknown_net_key[16] = {0xde, 0xad, 0xbe, 0xef}; beacon_create(&buf, unknown_net_key, 0x00, 0x0000); send_beacon(&buf); /* Ensure that interval is not affected. */ - ASSERT_TRUE(wait_for_beacon(beacon_confirm_all_subnets, NULL)); - ASSERT_TRUE(wait_for_beacon(beacon_confirm_all_subnets, NULL)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, beacon_confirm_all_subnets, + NULL)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, beacon_confirm_all_subnets, + NULL)); PASS(); } @@ -930,7 +961,7 @@ static void test_rx_secure_beacon_interval(void) beacon_create(&buf, test_net_key, 0, 0); k_sleep(K_SECONDS(5)); /*wait provisioned tx node to send the first beacon*/ - ASSERT_TRUE(wait_for_beacon(NULL, NULL)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); k_sleep(K_SECONDS(2)); /** @@ -941,9 +972,11 @@ static void test_rx_secure_beacon_interval(void) for (size_t i = 1; i < 5; i++) { if (i % 2) { send_beacon(&buf); - ASSERT_FALSE(wait_for_beacon(NULL, NULL)); + ASSERT_FALSE( + wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); } else { - ASSERT_TRUE(wait_for_beacon(NULL, NULL)); + ASSERT_TRUE( + wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); } } @@ -951,9 +984,9 @@ static void test_rx_secure_beacon_interval(void) * Verify that tx node keeps the 20s SNB interval until adapts itself and * sends SNB in 10s again. */ - ASSERT_FALSE(wait_for_beacon(NULL, NULL)); - ASSERT_TRUE(wait_for_beacon(NULL, NULL)); - ASSERT_TRUE(wait_for_beacon(NULL, NULL)); + ASSERT_FALSE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); beacon_recv_time = k_uptime_get(); /* Start sending SNB */ k_work_schedule(&beacon_timer, K_NO_WAIT); @@ -965,7 +998,7 @@ static void test_rx_secure_beacon_interval(void) */ delta = 0; for (size_t i = 0; i < 60; i++) { - if (wait_for_beacon(NULL, NULL)) { + if (wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)) { delta = k_uptime_delta(&beacon_recv_time); break; } @@ -975,17 +1008,89 @@ static void test_rx_secure_beacon_interval(void) PASS(); } +static uint8_t snb_cnt; + +static void snb_recv(const struct bt_mesh_snb *snb) +{ + /* IV idx of 2 marks end of test */ + if (snb->iv_idx == 2) { + k_sem_give(&beacon_sem); + return; + } + + ASSERT_EQUAL(snb->flags, 0x02); + ASSERT_EQUAL(snb->iv_idx, 1); + snb_cnt++; +} + +static void test_rx_beacon_cache(void) +{ + k_sem_init(&beacon_sem, 0, 1); + snb_cb_ptr = snb_recv; + + bt_mesh_test_cfg_set(&rx_cfg, WAIT_TIME); + bt_mesh_test_setup(); + + /* Wait for secondary SNB to end test. */ + ASSERT_OK_MSG(k_sem_take(&beacon_sem, K_SECONDS(40)), + "Didn't receive SNB in time"); + + /* Verify that only one SNB for IV_idx=1 was handled. */ + ASSERT_EQUAL(snb_cnt, 1); + PASS(); +} + +static void test_tx_beacon_cache(void) +{ + bt_mesh_test_cfg_set(NULL, WAIT_TIME); + bt_mesh_crypto_init(); + ASSERT_OK_MSG(bt_enable(NULL), "Bluetooth init failed"); + + NET_BUF_SIMPLE_DEFINE(iv1, 22); + NET_BUF_SIMPLE_DEFINE(iv2, 22); + beacon_create(&iv1, test_net_key, 0x02, 0x0001); + beacon_create(&iv2, test_net_key, 0x02, 0x0002); + + /* Send two copies of the same SNB. */ + for (size_t i = 0; i < 2; i++) { + k_sleep(K_SECONDS(5)); + send_beacon(&iv1); + } + + /* Send secondary SNB to mark end of test. */ + k_sleep(K_SECONDS(5)); + send_beacon(&iv2); + + PASS(); +} + #if CONFIG_BT_MESH_V1d1 + +typedef void (*priv_beacon_cb)(const struct bt_mesh_prb *prb); + +static priv_beacon_cb priv_beacon_cb_ptr; + +static void priv_received(const struct bt_mesh_prb *prb) +{ + if (priv_beacon_cb_ptr) { + priv_beacon_cb_ptr(prb); + } +} + +BT_MESH_BEACON_CB_DEFINE(priv_beacon) = { + .priv_received = priv_received, +}; + static bool private_beacon_check(const uint8_t *net_id, void *ctx) { bool ret; - bool same_random = (bool *)ctx; + bool same_random = *(bool *)ctx; - if (memcmp(beacon.adv_addr.a.val, &last_beacon_adv_addr, BT_ADDR_SIZE) == 0) { + if (memcmp(beacon.adv_addr.a.val, last_beacon_adv_addr.a.val, BT_ADDR_SIZE) == 0) { return false; } - memcpy(&last_beacon_adv_addr, beacon.adv_addr.a.val, BT_ADDR_SIZE); + memcpy(&last_beacon_adv_addr.a.val, beacon.adv_addr.a.val, BT_ADDR_SIZE); if (same_random) { ret = memcmp(beacon.random, last_random, 13) == 0; @@ -1026,7 +1131,7 @@ static void tx_priv_setup(void) FAIL("Beacon set failed (err %d, status %u)", err, status); } - err = bt_mesh_priv_beacon_cli_set(0, tx_cfg.addr, &val); + err = bt_mesh_priv_beacon_cli_set(0, tx_cfg.addr, &val, &val); if (err) { FAIL("Failed to enable Private Beacon (err=%d)", err); } @@ -1064,7 +1169,7 @@ static void test_tx_priv_adv(void) val.enabled = 1; val.rand_interval = 1; - err = bt_mesh_priv_beacon_cli_set(0, tx_cfg.addr, &val); + err = bt_mesh_priv_beacon_cli_set(0, tx_cfg.addr, &val, &val); if (err) { FAIL("Failed to enable Private Beacon (err=%d)", err); } @@ -1073,7 +1178,7 @@ static void test_tx_priv_adv(void) val.rand_interval = 0; - err = bt_mesh_priv_beacon_cli_set(0, tx_cfg.addr, &val); + err = bt_mesh_priv_beacon_cli_set(0, tx_cfg.addr, &val, &val); if (err) { FAIL("Failed to enable Private Beacon (err=%d)", err); } @@ -1082,7 +1187,7 @@ static void test_tx_priv_adv(void) val.rand_interval = 0; - err = bt_mesh_priv_beacon_cli_set(0, tx_cfg.addr, &val); + err = bt_mesh_priv_beacon_cli_set(0, tx_cfg.addr, &val, &val); if (err) { FAIL("Failed to enable Private Beacon (err=%d)", err); } @@ -1091,7 +1196,7 @@ static void test_tx_priv_adv(void) val.rand_interval = 3; - err = bt_mesh_priv_beacon_cli_set(0, tx_cfg.addr, &val); + err = bt_mesh_priv_beacon_cli_set(0, tx_cfg.addr, &val, &val); if (err) { FAIL("Failed to enable Private Beacon (err=%d)", err); } @@ -1119,7 +1224,8 @@ static void test_rx_priv_adv(void) * and with Random Interval = 0 for another 6 */ for (i = 0; i < 12; i++) { - wait_for_beacon(private_beacon_check, &same_random); + wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, private_beacon_check, + &same_random); } /* TX device is advertising with Random Interval = 3 */ @@ -1127,14 +1233,16 @@ static void test_rx_priv_adv(void) same_random = true; for (int j = 0; j < 2; j++) { - wait_for_beacon(private_beacon_check, &same_random); + wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, private_beacon_check, + &same_random); } k_sleep(K_SECONDS(BEACON_INTERVAL)); /* Beacon random should change here */ same_random = true; - wait_for_beacon(private_beacon_check, &same_random); + wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, private_beacon_check, + &same_random); } PASS(); @@ -1160,7 +1268,7 @@ static void private_beacon_create(struct net_buf_simple *buf, const uint8_t *net } bt_rand(random_val, sizeof(random_val)); - bt_mesh_beacon_encrypt(&priv_beacon_key, flags, bt_mesh.iv_index + 1, + bt_mesh_beacon_encrypt(&priv_beacon_key, flags, iv_index, random_val, data, auth); net_buf_simple_reset(buf); @@ -1220,7 +1328,7 @@ static void test_rx_priv_invalid(void) FAIL("Beacon set failed (err %d, status %u)", err, status); } - err = bt_mesh_priv_beacon_cli_set(0, rx_cfg.addr, &val); + err = bt_mesh_priv_beacon_cli_set(0, rx_cfg.addr, &val, &val); if (err) { FAIL("Failed to enable Private Beacon (err=%d)", err); } @@ -1253,7 +1361,7 @@ static void toggle_priv_beacon(uint16_t addr, uint8_t enabled) val.enabled = enabled; val.rand_interval = 1; - err = bt_mesh_priv_beacon_cli_set(0, addr, &val); + err = bt_mesh_priv_beacon_cli_set(0, addr, &val, &val); if (err) { FAIL("Failed to enable Private Beacon (err=%d)", err); } @@ -1322,6 +1430,7 @@ static void test_tx_priv_interleave(void) static void test_rx_priv_interleave(void) { int err; + bool same_random = false; bt_mesh_test_cfg_set(&rx_cfg, BEACON_INTERVAL_WAIT_TIME); bt_mesh_crypto_init(); @@ -1338,25 +1447,27 @@ static void test_rx_priv_interleave(void) } expected_beacon = BEACON_TYPE_SECURE; - ASSERT_TRUE(wait_for_beacon(NULL, NULL)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); expected_beacon = BEACON_TYPE_PRIVATE; - ASSERT_TRUE(wait_for_beacon(private_beacon_check, false)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, private_beacon_check, + &same_random)); /* IVU was started here */ - ASSERT_TRUE(wait_for_beacon(private_beacon_check, false)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, private_beacon_check, + &same_random)); ASSERT_EQUAL(0x02, beacon.flags); ASSERT_EQUAL(0x0001, beacon.iv_index); memset(&beacon, 0, sizeof(beacon)); expected_beacon = BEACON_TYPE_SECURE; - ASSERT_TRUE(wait_for_beacon(NULL, NULL)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); ASSERT_EQUAL(0x02, beacon.flags); ASSERT_EQUAL(0x0001, beacon.iv_index); /* KR was started here */ - ASSERT_TRUE(wait_for_beacon(NULL, NULL)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL)); ASSERT_EQUAL(0x03, beacon.flags); ASSERT_EQUAL(0x0001, beacon.iv_index); @@ -1364,12 +1475,437 @@ static void test_rx_priv_interleave(void) err = bt_mesh_private_beacon_key(net_key_new, &priv_beacon_key); - ASSERT_TRUE(wait_for_beacon(private_beacon_check, false)); + ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, private_beacon_check, + &same_random)); ASSERT_EQUAL(0x03, beacon.flags); ASSERT_EQUAL(0x0001, beacon.iv_index); PASS(); } + +static uint8_t prb_cnt; + +static void priv_beacon_recv(const struct bt_mesh_prb *prb) +{ + /* IV idx of 2 marks end of test */ + if (prb->iv_idx == 2) { + k_sem_give(&beacon_sem); + return; + } + + ASSERT_EQUAL(prb->flags, 0x02); + ASSERT_EQUAL(prb->iv_idx, 1); + prb_cnt++; +} + +static void test_rx_priv_beacon_cache(void) +{ + k_sem_init(&beacon_sem, 0, 1); + priv_beacon_cb_ptr = priv_beacon_recv; + + bt_mesh_test_cfg_set(&rx_cfg, WAIT_TIME); + bt_mesh_device_setup(&prov, &prb_comp); + provision(&rx_cfg); + + /* Wait for secondary private beacon to end test. */ + ASSERT_OK_MSG(k_sem_take(&beacon_sem, K_SECONDS(40)), + "Didn't receive private beacon in time"); + + /* Verify that only one private beacon for IV_idx=1 was handled. */ + ASSERT_EQUAL(prb_cnt, 1); + PASS(); +} + +static void test_tx_priv_beacon_cache(void) +{ + bt_mesh_test_cfg_set(NULL, WAIT_TIME); + bt_mesh_crypto_init(); + ASSERT_OK_MSG(bt_enable(NULL), "Bluetooth init failed"); + + NET_BUF_SIMPLE_DEFINE(iv1, 27); + NET_BUF_SIMPLE_DEFINE(iv2, 27); + private_beacon_create(&iv1, test_net_key, 0x02, 0x0001); + private_beacon_create(&iv2, test_net_key, 0x02, 0x0002); + + /* Send two copies of the same private beacon. */ + for (size_t i = 0; i < 2; i++) { + k_sleep(K_SECONDS(5)); + send_beacon(&iv1); + } + + /* Send secondary private beacon to mark end of test. */ + k_sleep(K_SECONDS(5)); + send_beacon(&iv2); + + PASS(); +} + +#if IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) + +#define BEACON_TYPE_PRIVATE_NET_ID 2 +#define BEACON_TYPE_PRIVATE_NODE_ID 3 +#define BEACON_TYPE_PRIVATE_LEN 28 +#define TEST_NET_IDX1 0 +#define TEST_NET_IDX2 1 +#define MAX_TIMEOUT ((CONFIG_BT_MESH_NODE_ID_TIMEOUT * 1000) / 6) + +#define PP_NET_ID_WAIT_TIME 610 /*seconds*/ +#define PP_NODE_ID_WAIT_TIME 80 /*seconds*/ +#define PP_MULT_NET_ID_WAIT_TIME 50 /*seconds*/ + +struct pp_netkey_ctx { + uint8_t *net_key; + uint8_t net_id[8]; + struct bt_mesh_key id_key; +}; + +static struct pp_netkey_ctx pp_net0 = {.net_key = (uint8_t *)test_net_key}; +static struct pp_netkey_ctx pp_net1 = {.net_key = (uint8_t *)test_net_key_secondary}; + +struct priv_test_ctx { + uint8_t beacon_type; + uint16_t *node_id_addr; +}; + +static void pp_netkey_ctx_init(struct pp_netkey_ctx *net) +{ + ASSERT_OK_MSG(bt_mesh_identity_key(net->net_key, &net->id_key), + "Failed to generate ID key"); + ASSERT_OK_MSG(bt_mesh_k3(net->net_key, net->net_id), "Failed to generate Net ID"); +} + +static bool pp_type_check(uint16_t expected_beacon, uint8_t adv_type, struct net_buf_simple *buf) +{ + if (adv_type != BT_GAP_ADV_TYPE_ADV_IND || buf->len != BEACON_TYPE_PRIVATE_LEN) { + return false; + } + + /* Remove Header */ + (void)net_buf_simple_pull_mem(buf, 11); + + uint8_t beacon_type = net_buf_simple_pull_u8(buf); + + if (beacon_type != expected_beacon) { + return false; + } + + return true; +} + +static uint64_t pp_hash_calc(struct pp_netkey_ctx *net, uint64_t random, uint16_t *addr) +{ + uint64_t hash; + uint8_t tmp[16] = {0, 0, 0, 0, 0, 3}; + + if (addr) { + memcpy(&tmp[6], &random, 8); + sys_put_be16(*addr, &tmp[14]); + + } else { + memcpy(&tmp[0], net->net_id, 8); + memcpy(&tmp[8], &random, 8); + } + + bt_mesh_encrypt(&net->id_key, tmp, tmp); + memcpy(&hash, &tmp[8], 8); + + return hash; +} + +static bool pp_beacon_check(const uint8_t *net_id, void *ctx) +{ + struct priv_test_ctx *test_ctx = (struct priv_test_ctx *)ctx; + + ASSERT_EQUAL(beacon.pp_hash, + pp_hash_calc(&pp_net0, beacon.pp_random, test_ctx->node_id_addr)); + + if (memcmp(beacon.adv_addr.a.val, last_beacon_adv_addr.a.val, BT_ADDR_SIZE) == 0) { + return false; + } + + memcpy(&last_beacon_adv_addr.a.val, beacon.adv_addr.a.val, BT_ADDR_SIZE); + + return true; +} + +static void priv_scan_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_type, + struct net_buf_simple *buf) +{ + struct priv_test_ctx *ctx = (struct priv_test_ctx *)beacon.user_ctx; + + if (!pp_type_check(ctx->beacon_type, adv_type, buf)) { + /* Wrong message type */ + return; + } + + bt_addr_le_copy(&beacon.adv_addr, addr); + + beacon.pp_hash = net_buf_simple_pull_le64(buf); + beacon.pp_random = net_buf_simple_pull_le64(buf); + + if (!beacon.process_cb || beacon.process_cb(NULL, beacon.user_ctx)) { + k_sem_give(&observer_sem); + } +} + +static void rx_priv_common_init(uint16_t wait) +{ + bt_mesh_test_cfg_set(&rx_cfg, wait); + bt_mesh_crypto_init(); + pp_netkey_ctx_init(&pp_net0); + k_sem_init(&observer_sem, 0, 1); + ASSERT_OK_MSG(bt_enable(NULL), "Bluetooth init failed"); +} + +static void tx_priv_common_init(uint16_t wait) +{ + bt_mesh_test_cfg_set(NULL, wait); + bt_mesh_device_setup(&prov, &prb_comp); + provision(&tx_cfg); + + /* Disable GATT proxy */ + ASSERT_OK_MSG(bt_mesh_gatt_proxy_set(BT_MESH_GATT_PROXY_DISABLED), + "Failed to disable gatt proxy"); +} + +static void test_tx_priv_net_id(void) +{ + tx_priv_common_init(PP_NET_ID_WAIT_TIME); + + /* Enable private GATT proxy */ + ASSERT_OK_MSG(bt_mesh_priv_gatt_proxy_set(BT_MESH_GATT_PROXY_ENABLED), + "Failed to set private gatt proxy"); + + PASS(); +} + +static void test_rx_priv_net_id(void) +{ + struct priv_test_ctx ctx = { + .beacon_type = BEACON_TYPE_PRIVATE_NET_ID, + .node_id_addr = NULL, + }; + + rx_priv_common_init(PP_NET_ID_WAIT_TIME); + + /* Scan for first net ID */ + ASSERT_TRUE( + wait_for_beacon(priv_scan_cb, 1, pp_beacon_check, &ctx)); + + uint64_t last_pp_random = beacon.pp_random; + + /* Wait for 10 minutes, then scan for another net + * ID beacon and verify that random field has changed + */ + k_sleep(K_SECONDS(600)); + ASSERT_TRUE( + wait_for_beacon(priv_scan_cb, 1, pp_beacon_check, &ctx)); + ASSERT_FALSE(beacon.pp_random == last_pp_random); + + PASS(); +} + +static void test_tx_priv_node_id(void) +{ + enum bt_mesh_feat_state state; + + tx_priv_common_init(PP_NODE_ID_WAIT_TIME); + + /* Start first node advertisement */ + ASSERT_OK_MSG(bt_mesh_subnet_priv_node_id_set(TEST_NET_IDX1, BT_MESH_NODE_IDENTITY_RUNNING), + "Failed to set private node ID"); + + /* Wait for Node ID advertising to end */ + k_sleep(K_SECONDS(65)); + + /* Check that advertisment has stopped */ + ASSERT_OK_MSG(bt_mesh_subnet_priv_node_id_get(TEST_NET_IDX1, &state), + "Failed to get private node ID"); + ASSERT_EQUAL(state, BT_MESH_NODE_IDENTITY_STOPPED); + + /* Start second node advertisement */ + ASSERT_OK_MSG(bt_mesh_subnet_priv_node_id_set(TEST_NET_IDX1, BT_MESH_NODE_IDENTITY_RUNNING), + "Failed to set private node ID"); + + /* Wait to let node ID advertise for a while */ + k_sleep(K_SECONDS(5)); + + PASS(); +} + +static void test_rx_priv_node_id(void) +{ + struct priv_test_ctx ctx = { + .beacon_type = BEACON_TYPE_PRIVATE_NODE_ID, + .node_id_addr = (uint16_t *)&tx_cfg.addr, + }; + + rx_priv_common_init(PP_NODE_ID_WAIT_TIME); + + /* Scan for first node ID */ + ASSERT_TRUE( + wait_for_beacon(priv_scan_cb, 1, pp_beacon_check, &ctx)); + + uint64_t last_pp_random = beacon.pp_random; + + /* Wait for first node ID advertisment to finish, then scan for + * second node ID and verify that random field has changed + */ + + k_sleep(K_SECONDS(65)); + ASSERT_TRUE( + wait_for_beacon(priv_scan_cb, 1, pp_beacon_check, &ctx)); + ASSERT_FALSE(beacon.pp_random == last_pp_random); + + PASS(); +} + +static void test_tx_priv_multi_net_id(void) +{ + tx_priv_common_init(PP_MULT_NET_ID_WAIT_TIME); + + /* TODO: This should be removed as soon as + * SNB/proxy service advertising issue has + * been resolved. + */ + bt_mesh_beacon_set(false); + + /* Add second network */ + ASSERT_OK_MSG(bt_mesh_subnet_add(TEST_NET_IDX2, test_net_key_secondary), + "Failed to add second subnet"); + + /* Enable private GATT proxy */ + ASSERT_OK_MSG(bt_mesh_priv_gatt_proxy_set(BT_MESH_GATT_PROXY_ENABLED), + "Failed to set private gatt proxy"); + + PASS(); +} + +static void test_rx_priv_multi_net_id(void) +{ + rx_priv_common_init(PP_MULT_NET_ID_WAIT_TIME); + pp_netkey_ctx_init(&pp_net1); + + struct priv_test_ctx ctx = { + .beacon_type = BEACON_TYPE_PRIVATE_NET_ID, + .node_id_addr = NULL, + }; + + uint16_t itr = 4; + static uint8_t old_idx = 0xff; + static struct { + struct pp_netkey_ctx *net; + uint16_t recv_cnt; + int64_t start; + } net_ctx[2] = { + {.net = &pp_net0}, + + {.net = &pp_net1}, + }; + + while (itr) { + /* Scan for net ID from both networks */ + ASSERT_TRUE(wait_for_beacon(priv_scan_cb, 2, NULL, &ctx)); + + for (size_t i = 0; i < ARRAY_SIZE(net_ctx); i++) { + if (beacon.pp_hash == + pp_hash_calc(net_ctx[i].net, beacon.pp_random, NULL)) { + if (old_idx == 0xff) { + /* Received first Net ID advertisment */ + old_idx = i; + net_ctx[i].start = k_uptime_get(); + net_ctx[i].recv_cnt++; + } else if (old_idx != i) { + /* Received Net ID adv for new subnet */ + + /* Verify last Net ID adv result */ + ASSERT_IN_RANGE(k_uptime_get() - net_ctx[old_idx].start, + MAX_TIMEOUT - 1000, MAX_TIMEOUT); + ASSERT_IN_RANGE(net_ctx[old_idx].recv_cnt, 9, 10); + net_ctx[old_idx].recv_cnt = 0; + old_idx = i; + + /* The test ends when all itterations are completed */ + itr--; + + net_ctx[i].start = k_uptime_get(); + net_ctx[i].recv_cnt++; + } else { + /* Received another Net ID adv from same subnet*/ + net_ctx[i].recv_cnt++; + } + + break; + } + } + } + + PASS(); +} + +static void test_tx_priv_gatt_proxy(void) +{ + bt_mesh_test_cfg_set(NULL, WAIT_TIME); + bt_mesh_device_setup(&prov, &prb_comp); + provision(&tx_cfg); + bt_mesh_iv_update_test(true); + + ASSERT_TRUE(bt_mesh.iv_index == 0); + + /* Disable SNB. */ + bt_mesh_beacon_set(false); + ASSERT_OK_MSG(bt_mesh_scan_disable(), "Failed to disable scanner"); + ASSERT_OK_MSG(bt_mesh_gatt_proxy_set(BT_MESH_GATT_PROXY_DISABLED), + "Failed to disable gatt proxy"); + ASSERT_OK_MSG(bt_mesh_priv_gatt_proxy_set(BT_MESH_PRIV_GATT_PROXY_ENABLED), + "Failed to set private gatt proxy"); + + /* Wait for proxy connection to complete. */ + WAIT_FOR_COND(bt_mesh_proxy_srv_connected_cnt() == 1, 10); + + /* Wait a bit so RX device can disable scanner, then start IV update */ + k_sleep(K_SECONDS(2)); + ASSERT_TRUE(bt_mesh_iv_update()); + + /* Check that IV index has updated */ + ASSERT_TRUE(bt_mesh.iv_index == 1); + PASS(); +} + +static void test_rx_priv_gatt_proxy(void) +{ + bt_mesh_test_cfg_set(NULL, WAIT_TIME); + bt_mesh_device_setup(&prov, &prb_comp); + provision(&rx_cfg); + bt_mesh_iv_update_test(true); + + ASSERT_TRUE(bt_mesh.iv_index == 0); + + /* Disable SNB. */ + bt_mesh_beacon_set(false); + ASSERT_OK_MSG(bt_mesh_gatt_proxy_set(BT_MESH_GATT_PROXY_DISABLED), + "Failed to disable gatt proxy"); + ASSERT_OK_MSG(bt_mesh_priv_gatt_proxy_set(BT_MESH_PRIV_GATT_PROXY_ENABLED), + "Failed to set private gatt proxy"); + ASSERT_OK_MSG(bt_mesh_proxy_connect(TEST_NET_IDX1), "Failed to connect over proxy"); + + /* Wait for connection to complete, then disable scanner + * to ensure that all RX communication arrives over GATT. + */ + WAIT_FOR_COND(bt_mesh_proxy_cli_is_connected(TEST_NET_IDX1), 10); + ASSERT_OK_MSG(bt_mesh_scan_disable(), "Failed to disable scanner"); + + /* Wait for the IV index to update. + * Verifying that IV index has changed proves that a private + * beacon arrived successfully over the GATT connection. + */ + WAIT_FOR_COND(bt_mesh.iv_index == 1, 10); + + PASS(); +} + +#endif + #endif /* CONFIG_BT_MESH_V1d1 */ #define TEST_CASE(role, name, description) \ @@ -1389,12 +1925,20 @@ static const struct bst_test_instance test_beacon[] = { TEST_CASE(tx, kr_old_key, "Beacon: send old Net Key"), TEST_CASE(tx, multiple_netkeys, "Beacon: multiple Net Keys"), TEST_CASE(tx, secure_beacon_interval, "Beacon: send secure beacons"), + TEST_CASE(tx, beacon_cache, "Beacon: advertise duplicate SNBs"), #if CONFIG_BT_MESH_V1d1 TEST_CASE(tx, priv_on_iv_update, "Private Beacon: send on IV update"), TEST_CASE(tx, priv_on_key_refresh, "Private Beacon: send on Key Refresh"), TEST_CASE(tx, priv_adv, "Private Beacon: advertise Private Beacons"), TEST_CASE(tx, priv_invalid, "Private Beacon: advertise invalid beacons"), TEST_CASE(tx, priv_interleave, "Private Beacon: advertise interleaved with SNB"), + TEST_CASE(tx, priv_beacon_cache, "Private Beacon: advertise duplicate Private Beacons"), +#if CONFIG_BT_MESH_GATT_PROXY + TEST_CASE(tx, priv_net_id, "Private Proxy: advertise Net ID"), + TEST_CASE(tx, priv_node_id, "Private Proxy: advertise Node ID"), + TEST_CASE(tx, priv_multi_net_id, "Private Proxy: advertise multiple Net ID"), + TEST_CASE(tx, priv_gatt_proxy, "Private Proxy: Send Private Beacons over GATT"), +#endif #endif TEST_CASE(rx, on_iv_update, "Beacon: receive with IV update flag"), @@ -1403,10 +1947,18 @@ static const struct bst_test_instance test_beacon[] = { TEST_CASE(rx, kr_old_key, "Beacon: receive old Net Key"), TEST_CASE(rx, multiple_netkeys, "Beacon: multiple Net Keys"), TEST_CASE(rx, secure_beacon_interval, "Beacon: receive and send secure beacons"), + TEST_CASE(rx, beacon_cache, "Beacon: receive duplicate SNBs"), #if CONFIG_BT_MESH_V1d1 TEST_CASE(rx, priv_adv, "Private Beacon: verify random regeneration"), TEST_CASE(rx, priv_invalid, "Private Beacon: receive invalid beacons"), TEST_CASE(rx, priv_interleave, "Private Beacon: interleaved with SNB"), + TEST_CASE(rx, priv_beacon_cache, "Private Beacon: receive duplicate Private Beacons"), +#if CONFIG_BT_MESH_GATT_PROXY + TEST_CASE(rx, priv_net_id, "Private Proxy: scan for Net ID"), + TEST_CASE(rx, priv_node_id, "Private Proxy: scan for Node ID"), + TEST_CASE(rx, priv_multi_net_id, "Private Proxy: scan for multiple Net ID"), + TEST_CASE(rx, priv_gatt_proxy, "Private Proxy: Receive Private Beacons over GATT"), +#endif #endif BSTEST_END_MARKER }; diff --git a/tests/bsim/bluetooth/mesh/src/test_blob.c b/tests/bsim/bluetooth/mesh/src/test_blob.c index 564fb6fe8d1..4258ff77c62 100644 --- a/tests/bsim/bluetooth/mesh/src/test_blob.c +++ b/tests/bsim/bluetooth/mesh/src/test_blob.c @@ -77,13 +77,13 @@ static int blob_chunk_wr(const struct bt_mesh_blob_io *io, const struct bt_mesh_blob_chunk *chunk) { partial_block += chunk->size; - ASSERT_TRUE(partial_block <= block->size, "Received block is too large"); + ASSERT_TRUE_MSG(partial_block <= block->size, "Received block is too large\n"); if (partial_block == block->size) { partial_block = 0; - ASSERT_FALSE(atomic_test_and_set_bit(block_bitfield, block->number), - "Received duplicate block"); + ASSERT_FALSE_MSG(atomic_test_and_set_bit(block_bitfield, block->number), + "Received duplicate block\n"); } if (atomic_test_bit(block_bitfield, 0)) { @@ -233,7 +233,7 @@ static struct bt_mesh_sar_cfg_cli sar_cfg_cli; static const struct bt_mesh_comp srv_comp = { .elem = - (struct bt_mesh_elem[]){ + (const struct bt_mesh_elem[]){ BT_MESH_ELEM(1, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), @@ -247,7 +247,7 @@ static const struct bt_mesh_comp srv_comp = { static const struct bt_mesh_comp cli_comp = { .elem = - (struct bt_mesh_elem[]){ + (const struct bt_mesh_elem[]){ BT_MESH_ELEM(1, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), @@ -261,7 +261,7 @@ static const struct bt_mesh_comp cli_comp = { static struct k_sem info_get_sem; -static int mock_handle_info_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int mock_handle_info_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { k_sem_give(&info_get_sem); @@ -275,7 +275,7 @@ static const struct bt_mesh_model_op model_op1[] = { static const struct bt_mesh_comp none_rsp_srv_comp = { .elem = - (struct bt_mesh_elem[]){ + (const struct bt_mesh_elem[]){ BT_MESH_ELEM(1, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), @@ -1310,7 +1310,7 @@ static void test_srv_fail_on_block_get(void) PASS(); } -static int dummy_xfer_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int dummy_xfer_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { return 0; @@ -1328,7 +1328,7 @@ static const struct bt_mesh_model_op model_op2[] = { */ static const struct bt_mesh_comp srv_broken_comp = { .elem = - (struct bt_mesh_elem[]){ + (const struct bt_mesh_elem[]){ BT_MESH_ELEM(1, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), @@ -1525,7 +1525,7 @@ static void srv_check_reboot_and_continue(void) ASSERT_EQUAL(0, blob_srv.state.ttl); ASSERT_EQUAL(BLOB_CLI_ADDR, blob_srv.state.cli); ASSERT_EQUAL(1, blob_srv.state.timeout_base); - ASSERT_TRUE(BT_MESH_TX_SDU_MAX, blob_srv.state.mtu_size); + ASSERT_EQUAL(BT_MESH_RX_SDU_MAX - BT_MESH_MIC_SHORT, blob_srv.state.mtu_size); ASSERT_EQUAL(CONFIG_BT_MESH_BLOB_BLOCK_SIZE_MAX * 2, blob_srv.state.xfer.size); ASSERT_EQUAL(12, blob_srv.state.xfer.block_size_log); ASSERT_EQUAL(1, blob_srv.state.xfer.id); diff --git a/tests/bsim/bluetooth/mesh/src/test_cdp1.c b/tests/bsim/bluetooth/mesh/src/test_cdp1.c new file mode 100644 index 00000000000..35befdea95b --- /dev/null +++ b/tests/bsim/bluetooth/mesh/src/test_cdp1.c @@ -0,0 +1,434 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + * + * Composition Data Page 1 (CDP1) test + */ + +#include "mesh_test.h" + +#include +#include +#include +#include + +#include +#define LOG_MODULE_NAME test_cdp1 +LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_INF); + +#define NODE_ADDR 0x00a1 +#define WAIT_TIME 60 /* seconds */ + +#define TEST_MODEL_ID_1 0x2a2a +#define TEST_MODEL_ID_2 0x2b2b +#define TEST_MODEL_ID_3 0x2c2c +#define TEST_MODEL_ID_4 0x2d2d +#define TEST_MODEL_ID_5 0x2e2e +#define TEST_MODEL_ID_6 0x2f2f +#define TEST_VND_MODEL_ID_1 0x3a3a + +#define TEST_MODEL_DECLARE(number) \ + static int model_##number##_init(const struct bt_mesh_model *model); \ + static const struct bt_mesh_model_cb test_model_##number##_cb = { \ + .init = model_##number##_init, \ + }; \ + static const struct bt_mesh_model_op model_op_##number[] = { \ + BT_MESH_MODEL_OP_END, \ + }; + +TEST_MODEL_DECLARE(1); +TEST_MODEL_DECLARE(2); +TEST_MODEL_DECLARE(3); +TEST_MODEL_DECLARE(4); +TEST_MODEL_DECLARE(5); +TEST_MODEL_DECLARE(6); +TEST_MODEL_DECLARE(vnd1); + +static uint8_t app_key[16] = {0xaa}; +static uint8_t net_key[16] = {0xcc}; + +static const struct bt_mesh_test_cfg node_1_cfg = { + .addr = NODE_ADDR, + .dev_key = {0xaa}, +}; + +static struct bt_mesh_prov prov; +static struct bt_mesh_cfg_cli cfg_cli; + +static const struct bt_mesh_model models_1[] = { + BT_MESH_MODEL_CFG_SRV, + BT_MESH_MODEL_CFG_CLI(&cfg_cli), + BT_MESH_MODEL_CB(TEST_MODEL_ID_1, model_op_1, NULL, NULL, &test_model_1_cb), + BT_MESH_MODEL_CB(TEST_MODEL_ID_2, model_op_2, NULL, NULL, &test_model_2_cb), + BT_MESH_MODEL_CB(TEST_MODEL_ID_3, model_op_3, NULL, NULL, &test_model_3_cb), +}; + +static const struct bt_mesh_model models_2[] = { + BT_MESH_MODEL_CB(TEST_MODEL_ID_4, model_op_4, NULL, NULL, &test_model_4_cb), +}; + +static const struct bt_mesh_model models_3[] = { + BT_MESH_MODEL_CB(TEST_MODEL_ID_5, model_op_5, NULL, NULL, &test_model_5_cb), +}; + +static const struct bt_mesh_model models_4[] = { + BT_MESH_MODEL_CB(TEST_MODEL_ID_6, model_op_6, NULL, NULL, &test_model_6_cb), +}; + +static const struct bt_mesh_model models_vnd1[] = { + BT_MESH_MODEL_VND_CB(TEST_VND_COMPANY_ID, TEST_VND_MODEL_ID_1, model_op_vnd1, NULL, NULL, + &test_model_vnd1_cb), +}; + +static const struct bt_mesh_elem elems[] = { + BT_MESH_ELEM(0, models_1, models_vnd1), + BT_MESH_ELEM(1, models_2, BT_MESH_MODEL_NONE), + BT_MESH_ELEM(2, models_3, BT_MESH_MODEL_NONE), + BT_MESH_ELEM(3, models_3, BT_MESH_MODEL_NONE), + BT_MESH_ELEM(4, models_4, BT_MESH_MODEL_NONE), +}; + +static const struct bt_mesh_comp comp = { + .cid = TEST_VND_COMPANY_ID, + .vid = 0xdead, + .pid = 0xface, + .elem = elems, + .elem_count = ARRAY_SIZE(elems), +}; + +/* The extensions and correspondence between models are as follows: + * Within elements: + * E0: M2 extends M1. VND1 extends M2. M3 and VND1 corresponds. + * + * Between elements: + * M3 on E0 extends M4 on E1. + * M2 on E0 and M4 on E1 corresponds. + * M6 on E4 extends M1 on E0 + */ +static int model_1_init(const struct bt_mesh_model *model) +{ + return 0; +} + +static int model_2_init(const struct bt_mesh_model *model) +{ + ASSERT_OK(bt_mesh_model_extend(model, bt_mesh_model_find(&elems[0], TEST_MODEL_ID_1))); + return 0; +} + +static int model_3_init(const struct bt_mesh_model *model) +{ + return 0; +} + +static int model_4_init(const struct bt_mesh_model *model) +{ + ASSERT_OK(bt_mesh_model_extend(bt_mesh_model_find(&elems[0], TEST_MODEL_ID_3), model)); + ASSERT_OK(bt_mesh_model_correspond(model, bt_mesh_model_find(&elems[0], TEST_MODEL_ID_2))); + return 0; +} + +static int model_5_init(const struct bt_mesh_model *model) +{ + return 0; +} + +static int model_6_init(const struct bt_mesh_model *model) +{ + ASSERT_OK(bt_mesh_model_extend(model, bt_mesh_model_find(&elems[0], TEST_MODEL_ID_1))); + return 0; +} + +static int model_vnd1_init(const struct bt_mesh_model *model) +{ + ASSERT_OK(bt_mesh_model_extend(model, bt_mesh_model_find(&elems[0], TEST_MODEL_ID_1))); + ASSERT_OK(bt_mesh_model_correspond(model, bt_mesh_model_find(&elems[0], TEST_MODEL_ID_3))); + return 0; +} + +/* Hardcoded version of the CDP1 fields. + * Extensions are named extending-model_base-model. + */ + +static struct bt_mesh_comp_p1_ext_item test_p1_ext_mod2_mod1 = {.type = SHORT, + .short_item = { + .elem_offset = 0, + .mod_item_idx = 2, + }}; + +static struct bt_mesh_comp_p1_ext_item test_p1_ext_vnd1_mod1 = {.type = SHORT, + .short_item = { + .elem_offset = 0, + .mod_item_idx = 2, + }}; + +static struct bt_mesh_comp_p1_ext_item test_p1_ext_mod3_mod4 = {.type = SHORT, + .short_item = { + .elem_offset = 7, + .mod_item_idx = 0, + }}; + +static struct bt_mesh_comp_p1_ext_item test_p1_ext_mod6_mod1 = {.type = LONG, + .long_item = { + .elem_offset = 4, + .mod_item_idx = 2, + }}; + +static const struct bt_mesh_comp_p1_model_item test_p1_cfg_srv_mod = { + .cor_present = 0, + .format = 0, + .ext_item_cnt = 0, +}; + +static const struct bt_mesh_comp_p1_model_item test_p1_cfg_cli_mod = { + .cor_present = 0, + .format = 0, + .ext_item_cnt = 0, +}; + +static const struct bt_mesh_comp_p1_model_item test_p1_mod1 = { + .cor_present = 0, + .format = 0, + .ext_item_cnt = 0, +}; + +static const struct bt_mesh_comp_p1_model_item test_p1_mod2 = { + .cor_present = 1, + .format = 0, + .ext_item_cnt = 1, + .cor_id = 0, +}; + +static const struct bt_mesh_comp_p1_model_item test_p1_mod3 = { + .cor_present = 1, + .format = 0, + .ext_item_cnt = 1, + .cor_id = 0, +}; + +static const struct bt_mesh_comp_p1_model_item test_p1_mod4 = { + .cor_present = 1, + .format = 0, + .ext_item_cnt = 0, + .cor_id = 0, +}; + +static const struct bt_mesh_comp_p1_model_item test_p1_mod5 = { + .cor_present = 0, + .format = 0, + .ext_item_cnt = 0, +}; + +static const struct bt_mesh_comp_p1_model_item test_p1_mod6 = { + .cor_present = 0, + .format = 1, + .ext_item_cnt = 1, +}; + +static const struct bt_mesh_comp_p1_model_item test_p1_vnd1 = { + .cor_present = 1, + .format = 0, + .ext_item_cnt = 1, + .cor_id = 0, +}; + +static const struct bt_mesh_comp_p1_model_item test_p1_elem0_models[] = { + test_p1_cfg_srv_mod, test_p1_cfg_cli_mod, test_p1_mod1, + test_p1_mod2, test_p1_mod3, test_p1_vnd1, +}; + +static const struct bt_mesh_comp_p1_model_item test_p1_elem1_models[] = { + test_p1_mod4, +}; + +static const struct bt_mesh_comp_p1_model_item test_p1_elem2_models[] = { + test_p1_mod5, +}; + +static const struct bt_mesh_comp_p1_model_item test_p1_elem3_models[] = { + test_p1_mod5, +}; + +static const struct bt_mesh_comp_p1_model_item test_p1_elem4_models[] = { + test_p1_mod6, +}; + +static const struct bt_mesh_comp_p1_model_item *test_p1_elem_models[] = { + test_p1_elem0_models, test_p1_elem1_models, test_p1_elem2_models, + test_p1_elem3_models, test_p1_elem4_models, +}; + +static const struct bt_mesh_comp_p1_elem test_p1_elem0 = { + .nsig = 5, + .nvnd = 1, +}; + +static const struct bt_mesh_comp_p1_elem test_p1_elem1 = { + .nsig = 1, + .nvnd = 0, +}; + +static const struct bt_mesh_comp_p1_elem test_p1_elem2 = { + .nsig = 1, + .nvnd = 0, +}; + +static const struct bt_mesh_comp_p1_elem test_p1_elem3 = { + .nsig = 1, + .nvnd = 0, +}; + +static const struct bt_mesh_comp_p1_elem test_p1_elem4 = { + .nsig = 1, + .nvnd = 0, +}; + +static struct bt_mesh_comp_p1_elem test_p1_elems[] = { + test_p1_elem0, test_p1_elem1, test_p1_elem2, test_p1_elem3, test_p1_elem4, +}; + +static void provision_and_configure(struct bt_mesh_test_cfg cfg) +{ + int err; + uint8_t status; + + err = bt_mesh_provision(net_key, 0, 0, 0, cfg.addr, cfg.dev_key); + if (err) { + FAIL("Provisioning failed (err %d)", err); + } + + err = bt_mesh_cfg_cli_app_key_add(0, cfg.addr, 0, 0, app_key, &status); + if (err || status) { + FAIL("AppKey add failed (err %d, status %u)", err, status); + } +} + +static void verify_model_item(struct bt_mesh_comp_p1_model_item *mod_item, int elem_idx, + int mod_idx, int offset) +{ + ASSERT_EQUAL(test_p1_elem_models[elem_idx][mod_idx + offset].cor_present, + mod_item->cor_present); + ASSERT_EQUAL(test_p1_elem_models[elem_idx][mod_idx + offset].format, mod_item->format); + ASSERT_EQUAL(test_p1_elem_models[elem_idx][mod_idx + offset].ext_item_cnt, + mod_item->ext_item_cnt); + if (mod_item->cor_present) { + ASSERT_EQUAL(test_p1_elem_models[elem_idx][mod_idx + offset].cor_id, + mod_item->cor_id); + } +} + +static void verify_ext_item(struct bt_mesh_comp_p1_ext_item *ext_item, int elem_idx, int mod_idx, + int offset) +{ + struct bt_mesh_comp_p1_ext_item *test_p1_ext_item; + + switch (elem_idx * 100 + (mod_idx + offset)) { + case 3: /* elem_idx=0, mod_idx=3, offset = 0 */ + test_p1_ext_item = &test_p1_ext_mod2_mod1; + break; + case 4: /* elem_idx=0, mod_idx=4, offset = 0 */ + test_p1_ext_item = &test_p1_ext_mod3_mod4; + break; + case 5: /* elem_idx=0, mod_idx=0, offset = 5 */ + test_p1_ext_item = &test_p1_ext_vnd1_mod1; + break; + case 400: /* elem_idx=4, mod_idx=0, offset = 0 */ + test_p1_ext_item = &test_p1_ext_mod6_mod1; + break; + default: + FAIL("Unexpected call to %s (elem %d, mod %d, offset %d)", __func__, elem_idx, + mod_idx, offset); + } + + ASSERT_EQUAL(test_p1_ext_item->type, ext_item->type); + if (ext_item->type == SHORT) { + ASSERT_EQUAL(test_p1_ext_item->short_item.elem_offset, + ext_item->short_item.elem_offset); + ASSERT_EQUAL(test_p1_ext_item->short_item.mod_item_idx, + ext_item->short_item.mod_item_idx); + } else { + ASSERT_EQUAL(test_p1_ext_item->long_item.elem_offset, + ext_item->long_item.elem_offset); + ASSERT_EQUAL(test_p1_ext_item->long_item.mod_item_idx, + ext_item->long_item.mod_item_idx); + } +} + +static void verify_cdp1(struct bt_mesh_comp_p1_elem *p1_elem, + struct bt_mesh_comp_p1_model_item *mod_item, + struct bt_mesh_comp_p1_ext_item *ext_item, + struct net_buf_simple *p1_dev_comp) +{ + int elem_idx = 0; + + while (bt_mesh_comp_p1_elem_pull(p1_dev_comp, p1_elem)) { + ASSERT_EQUAL(test_p1_elems[elem_idx].nsig, p1_elem->nsig); + ASSERT_EQUAL(test_p1_elems[elem_idx].nvnd, p1_elem->nvnd); + + for (int mod_idx = 0; mod_idx < p1_elem->nsig; mod_idx++) { + if (bt_mesh_comp_p1_item_pull(p1_elem, mod_item)) { + verify_model_item(mod_item, elem_idx, mod_idx, 0); + } + + for (int ext_mod_idx = 0; ext_mod_idx < mod_item->ext_item_cnt; + ext_mod_idx++) { + bt_mesh_comp_p1_pull_ext_item(mod_item, ext_item); + verify_ext_item(ext_item, elem_idx, mod_idx, 0); + } + } + + for (int mod_idx = 0; mod_idx < p1_elem->nvnd; mod_idx++) { + if (bt_mesh_comp_p1_item_pull(p1_elem, mod_item)) { + verify_model_item(mod_item, elem_idx, mod_idx, p1_elem->nsig); + } + + for (int ext_mod_idx = 0; ext_mod_idx < mod_item->ext_item_cnt; + ext_mod_idx++) { + bt_mesh_comp_p1_pull_ext_item(mod_item, ext_item); + verify_ext_item(ext_item, elem_idx, mod_idx, p1_elem->nsig); + } + } + elem_idx++; + } +} + +static void test_node_data_comparison(void) +{ + bt_mesh_test_cfg_set(NULL, WAIT_TIME); + bt_mesh_device_setup(&prov, &comp); + provision_and_configure(node_1_cfg); + + NET_BUF_SIMPLE_DEFINE(p1_dev_comp, 500); + uint8_t page_rsp; + + ASSERT_OK(bt_mesh_cfg_cli_comp_data_get(0, node_1_cfg.addr, 1, &page_rsp, &p1_dev_comp)); + ASSERT_EQUAL(1, page_rsp); + + NET_BUF_SIMPLE_DEFINE(p1_buf, 500); + NET_BUF_SIMPLE_DEFINE(p1_item_buf, 500); + struct bt_mesh_comp_p1_elem p1_elem = {._buf = &p1_buf}; + struct bt_mesh_comp_p1_model_item mod_item = {._buf = &p1_item_buf}; + struct bt_mesh_comp_p1_ext_item ext_item = {0}; + + verify_cdp1(&p1_elem, &mod_item, &ext_item, &p1_dev_comp); + + PASS(); +} + +#define TEST_CASE(role, name, description) \ + { \ + .test_id = "cdp1_" #role "_" #name, .test_descr = description, \ + .test_tick_f = bt_mesh_test_timeout, .test_main_f = test_##role##_##name, \ + } + +static const struct bst_test_instance test_cdp1[] = { + TEST_CASE(node, data_comparison, "Compare encoded and decoded CDP1 data."), + + BSTEST_END_MARKER}; + +struct bst_test_list *test_cdp1_install(struct bst_test_list *tests) +{ + tests = bst_add_tests(tests, test_cdp1); + return tests; +} diff --git a/tests/bsim/bluetooth/mesh/src/test_dfu.c b/tests/bsim/bluetooth/mesh/src/test_dfu.c index 46ad4cecb41..06f7248a6ad 100644 --- a/tests/bsim/bluetooth/mesh/src/test_dfu.c +++ b/tests/bsim/bluetooth/mesh/src/test_dfu.c @@ -290,7 +290,7 @@ static struct bt_mesh_dfu_srv dfu_srv = BT_MESH_DFU_SRV_INIT(&dfu_handlers, dfu_ static const struct bt_mesh_comp dist_comp = { .elem = - (struct bt_mesh_elem[]){ + (const struct bt_mesh_elem[]){ BT_MESH_ELEM(1, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), @@ -304,7 +304,7 @@ static const struct bt_mesh_comp dist_comp = { static const struct bt_mesh_comp dist_comp_self_update = { .elem = - (struct bt_mesh_elem[]){ + (const struct bt_mesh_elem[]){ BT_MESH_ELEM(1, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), @@ -325,7 +325,7 @@ static const struct bt_mesh_model_op model_dummy_op[] = { static const struct bt_mesh_comp target_comp = { .elem = - (struct bt_mesh_elem[]){ + (const struct bt_mesh_elem[]){ BT_MESH_ELEM(1, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), @@ -602,8 +602,8 @@ static void test_dist_dfu_slot_create(void) size_t metadata_len = 4; int err, i; - ASSERT_TRUE(CONFIG_BT_MESH_DFU_SLOT_CNT >= 3, - "CONFIG_BT_MESH_DFU_SLOT_CNT must be at least 3"); + ASSERT_TRUE_MSG(CONFIG_BT_MESH_DFU_SLOT_CNT >= 3, + "CONFIG_BT_MESH_DFU_SLOT_CNT must be at least 3\n"); bt_mesh_test_cfg_set(NULL, WAIT_TIME); bt_mesh_device_setup(&prov, &dist_comp); @@ -614,7 +614,7 @@ static void test_dist_dfu_slot_create(void) metadata[0] = i; slot[i] = slot_reserve_and_set(size, fwid, fwid_len, metadata, metadata_len); - ASSERT_FALSE(slot[i] == NULL, "Failed to add slot"); + ASSERT_FALSE_MSG(slot[i] == NULL, "Failed to add slot\n"); if (i > 0) { /* All but first slot are committed */ @@ -669,8 +669,8 @@ static void test_dist_dfu_slot_create_recover(void) size_t metadata_len = 4; int i, idx; - ASSERT_TRUE(CONFIG_BT_MESH_DFU_SLOT_CNT >= 3, - "CONFIG_BT_MESH_DFU_SLOT_CNT must be at least 3"); + ASSERT_TRUE_MSG(CONFIG_BT_MESH_DFU_SLOT_CNT >= 3, + "CONFIG_BT_MESH_DFU_SLOT_CNT must be at least 3\n"); bt_mesh_test_cfg_set(NULL, WAIT_TIME); bt_mesh_device_setup(&prov, &dist_comp); @@ -699,8 +699,8 @@ static void check_delete_all(void) const struct bt_mesh_dfu_slot *slot; size_t slot_count; - ASSERT_TRUE(CONFIG_BT_MESH_DFU_SLOT_CNT >= 3, - "CONFIG_BT_MESH_DFU_SLOT_CNT must be at least 3"); + ASSERT_TRUE_MSG(CONFIG_BT_MESH_DFU_SLOT_CNT >= 3, + "CONFIG_BT_MESH_DFU_SLOT_CNT must be at least 3\n"); slot_count = bt_mesh_dfu_slot_foreach(NULL, NULL); ASSERT_EQUAL(0, slot_count); @@ -713,8 +713,8 @@ static void check_delete_all(void) static void test_dist_dfu_slot_delete_all(void) { - ASSERT_TRUE(CONFIG_BT_MESH_DFU_SLOT_CNT >= 3, - "CONFIG_BT_MESH_DFU_SLOT_CNT must be at least 3"); + ASSERT_TRUE_MSG(CONFIG_BT_MESH_DFU_SLOT_CNT >= 3, + "CONFIG_BT_MESH_DFU_SLOT_CNT must be at least 3\n"); bt_mesh_test_cfg_set(NULL, WAIT_TIME); bt_mesh_device_setup(&prov, &dist_comp); @@ -764,8 +764,8 @@ static void test_dist_dfu_slot_idempotency(void) size_t fwid_len = 4; struct bt_mesh_dfu_slot *slot; - ASSERT_TRUE(CONFIG_BT_MESH_DFU_SLOT_CNT >= 1, - "CONFIG_BT_MESH_DFU_SLOT_CNT must be at least 1"); + ASSERT_TRUE_MSG(CONFIG_BT_MESH_DFU_SLOT_CNT >= 1, + "CONFIG_BT_MESH_DFU_SLOT_CNT must be at least 1\n"); bt_mesh_test_cfg_set(NULL, WAIT_TIME); bt_mesh_device_setup(&prov, &dist_comp); @@ -941,7 +941,7 @@ static struct bt_mesh_dfu_cli dfu_cli = BT_MESH_DFU_CLI_INIT(&dfu_cli_cb); static const struct bt_mesh_comp cli_comp = { .elem = - (struct bt_mesh_elem[]){ + (const struct bt_mesh_elem[]){ BT_MESH_ELEM(1, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), @@ -1309,7 +1309,7 @@ static void test_cli_stop(void) static struct k_sem caps_get_sem; -static int mock_handle_caps_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int mock_handle_caps_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { LOG_WRN("Rejecting BLOB Information Get message"); @@ -1326,7 +1326,7 @@ static const struct bt_mesh_model_op model_caps_op1[] = { static const struct bt_mesh_comp srv_caps_broken_comp = { .elem = - (struct bt_mesh_elem[]){ + (const struct bt_mesh_elem[]){ BT_MESH_ELEM(1, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), @@ -1340,7 +1340,7 @@ static const struct bt_mesh_comp srv_caps_broken_comp = { .elem_count = 1, }; -static int mock_handle_chunks(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int mock_handle_chunks(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { LOG_WRN("Skipping receiving block"); @@ -1357,7 +1357,7 @@ static const struct bt_mesh_model_op model_caps_op2[] = { static const struct bt_mesh_comp broken_target_comp = { .elem = - (struct bt_mesh_elem[]){ + (const struct bt_mesh_elem[]){ BT_MESH_ELEM(1, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), @@ -1373,7 +1373,7 @@ static const struct bt_mesh_comp broken_target_comp = { static struct k_sem update_get_sem; -static int mock_handle_update_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int mock_handle_update_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { LOG_WRN("Rejecting Firmware Update Get message"); @@ -1389,7 +1389,7 @@ static const struct bt_mesh_model_op model_update_get_op1[] = { static const struct bt_mesh_comp srv_update_get_broken_comp = { .elem = - (struct bt_mesh_elem[]){ + (const struct bt_mesh_elem[]){ BT_MESH_ELEM(1, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), @@ -1406,7 +1406,7 @@ static const struct bt_mesh_comp srv_update_get_broken_comp = { static struct k_sem update_apply_sem; -static int mock_handle_update_apply(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int mock_handle_update_apply(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { LOG_WRN("Rejecting Firmware Update Apply message"); @@ -1422,7 +1422,7 @@ static const struct bt_mesh_model_op model_update_apply_op1[] = { static const struct bt_mesh_comp srv_update_apply_broken_comp = { .elem = - (struct bt_mesh_elem[]){ + (const struct bt_mesh_elem[]){ BT_MESH_ELEM(1, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), diff --git a/tests/bsim/bluetooth/mesh/src/test_lcd.c b/tests/bsim/bluetooth/mesh/src/test_lcd.c index dc819b8d0de..e1c7adde730 100644 --- a/tests/bsim/bluetooth/mesh/src/test_lcd.c +++ b/tests/bsim/bluetooth/mesh/src/test_lcd.c @@ -15,6 +15,7 @@ #include #include +#include "argparse.h" LOG_MODULE_REGISTER(test_lcd, LOG_LEVEL_INF); @@ -33,6 +34,7 @@ LOG_MODULE_REGISTER(test_lcd, LOG_LEVEL_INF); #define TEST_MODEL_CNT_CB(_dummy_op, _metadata) \ { \ .id = 0x1234, \ + BT_MESH_MODEL_RUNTIME_INIT(NULL) \ .pub = NULL, \ .keys = NULL, \ .keys_cnt = 0, \ @@ -40,7 +42,6 @@ LOG_MODULE_REGISTER(test_lcd, LOG_LEVEL_INF); .groups_cnt = 0, \ .op = _dummy_op, \ .cb = NULL, \ - .user_data = NULL, \ .metadata = _metadata, \ } @@ -50,6 +51,41 @@ const struct bt_mesh_model_op dummy_op[] = { BT_MESH_MODEL_OP_END, }; +static const uint8_t elem_offset2[3] = {4, 5, 6}; +static const uint8_t additional_data[2] = {100, 200}; /* A Mesh Profile may have additional data. */ +static const struct bt_mesh_comp2_record comp_rec[40] = { + [0 ... 39] = {.id = 10, + .version.x = 20, + .version.y = 30, + .version.z = 40, + .elem_offset_cnt = sizeof(elem_offset2), + .elem_offset = elem_offset2, + .data_len = sizeof(additional_data), + .data = additional_data}, +}; +static const struct bt_mesh_comp2 comp_p2 = {.record_cnt = ARRAY_SIZE(comp_rec), + .record = comp_rec}; + +static int comp_page; +static bool comp_changed; +static void test_args_parse(int argc, char *argv[]) +{ + bs_args_struct_t args_struct[] = { + {.dest = &comp_page, + .type = 'i', + .name = "{page}", + .option = "page", + .descript = "Current composition data page"}, + {.dest = &comp_changed, + .type = 'b', + .name = "{0, 1}", + .option = "comp-changed-mode", + .descript = "Composition data has changed"}, + }; + + bs_args_parse_all_cmd_line(argc, argv, args_struct); +} + static struct bt_mesh_models_metadata_entry *dummy_meta_entry[] = {}; /* Empty elements to create large composition/meta data */ @@ -71,7 +107,7 @@ static struct bt_mesh_cfg_cli cfg_cli; static struct bt_mesh_large_comp_data_cli lcd_cli; /* Creates enough composition data to send a max SDU comp status message + 1 byte */ -static struct bt_mesh_elem elements_1[] = { +static const struct bt_mesh_elem elements_1[] = { BT_MESH_ELEM(1, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), @@ -82,7 +118,7 @@ static struct bt_mesh_elem elements_1[] = { }; /* Creates enough metadata to send a max SDU metadata status message + 1 byte */ -static struct bt_mesh_elem elements_2[] = { +static const struct bt_mesh_elem elements_2[] = { BT_MESH_ELEM(1, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), @@ -224,7 +260,7 @@ static void test_cli_max_sdu_comp_data_request(void) if (err && err != -E2BIG) { FAIL("CLIENT: Failed to get comp data Page 0: %d", err); } - total_size = bt_mesh_comp_page_0_size(); + total_size = bt_mesh_comp_page_size(0); /* Get server composition data and check integrity */ ASSERT_OK(bt_mesh_large_comp_data_get(0, SRV_ADDR, page, offset, &srv_rsp)); @@ -238,12 +274,11 @@ static void test_cli_max_sdu_comp_data_request(void) static void test_cli_split_comp_data_request(void) { int err; - uint8_t page = 0; - uint16_t offset, total_size, prev_len = 0; + uint16_t offset = 0, prev_len = 0; - NET_BUF_SIMPLE_DEFINE(local_comp, 200); - NET_BUF_SIMPLE_DEFINE(srv_rsp_comp_1, 64); - NET_BUF_SIMPLE_DEFINE(srv_rsp_comp_2, 64); + NET_BUF_SIMPLE_DEFINE(local_comp, CONFIG_BT_MESH_COMP_PST_BUF_SIZE); + NET_BUF_SIMPLE_DEFINE(srv_rsp_comp_1, 500); + NET_BUF_SIMPLE_DEFINE(srv_rsp_comp_2, 500); net_buf_simple_init(&local_comp, 0); net_buf_simple_init(&srv_rsp_comp_1, 0); net_buf_simple_init(&srv_rsp_comp_2, 0); @@ -255,32 +290,38 @@ static void test_cli_split_comp_data_request(void) .data = &srv_rsp_comp_2, }; - bt_mesh_device_setup(&prov, &comp_1); + bt_mesh_device_setup(&prov, (comp_page == 0 || comp_page == 128) ? &comp_1 : &comp_2); + bt_mesh_comp2_register(&comp_p2); prov_and_conf(cli_cfg); - target_node_alloc(comp_1, srv_cfg); - - offset = 0; + target_node_alloc((comp_page == 0 || comp_page == 128) ? comp_1 : comp_2, srv_cfg); /* Get local data */ - err = bt_mesh_comp_data_get_page_0(&local_comp, offset); + err = bt_mesh_comp_data_get_page(&local_comp, comp_page, 0); /* Operation is successful even if all data cannot fit in the buffer (-E2BIG) */ if (err && err != -E2BIG) { - FAIL("CLIENT: Failed to get comp data Page 0: %d", err); + FAIL("CLIENT: Failed to get comp data Page %d: %d", err, comp_page); } - total_size = bt_mesh_comp_page_0_size(); + + uint16_t total_size = bt_mesh_comp_page_size(comp_page); + + /* Verify that the total comp page size is not larger than the provided buffer */ + ASSERT_TRUE(total_size <= CONFIG_BT_MESH_COMP_PST_BUF_SIZE); + + /* Wait a bit until the server is ready to respond*/ + k_sleep(K_SECONDS(2)); /* Get first server composition data sample and verify data */ - ASSERT_OK(bt_mesh_large_comp_data_get(0, SRV_ADDR, page, offset, &srv_rsp_1)); - rsp_equals_local_data_assert(SRV_ADDR, &srv_rsp_1, &local_comp, page, offset, total_size, - &prev_len); + ASSERT_OK(bt_mesh_large_comp_data_get(0, SRV_ADDR, comp_page, offset, &srv_rsp_1)); + rsp_equals_local_data_assert(SRV_ADDR, &srv_rsp_1, &local_comp, comp_page, offset, + total_size, &prev_len); prev_len = srv_rsp_comp_1.len; - offset += prev_len; + offset = prev_len; /* Get next server composition data sample */ - ASSERT_OK(bt_mesh_large_comp_data_get(0, SRV_ADDR, page, offset, &srv_rsp_2)); - rsp_equals_local_data_assert(SRV_ADDR, &srv_rsp_2, &local_comp, page, offset, total_size, - &prev_len); + ASSERT_OK(bt_mesh_large_comp_data_get(0, SRV_ADDR, comp_page, offset, &srv_rsp_2)); + rsp_equals_local_data_assert(SRV_ADDR, &srv_rsp_2, &local_comp, comp_page, offset, + total_size, &prev_len); /* Check data integrity of merged sample data */ merge_and_compare_assert(&srv_rsp_comp_1, &srv_rsp_comp_2, &local_comp); @@ -383,9 +424,16 @@ static void test_cli_split_metadata_request(void) static void test_srv_comp_data_status_respond(void) { - bt_mesh_device_setup(&prov, &comp_1); + bt_mesh_device_setup(&prov, (comp_page == 0 || comp_page == 128) ? &comp_1 : &comp_2); + bt_mesh_comp2_register(&comp_p2); prov_and_conf(srv_cfg); + /* Simulate an update of composition data */ + if (comp_changed) { + bt_mesh_comp_change_prepare(); + atomic_set_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY); + } + /* No server callback available. Wait 10 sec for message to be recived */ k_sleep(K_SECONDS(10)); @@ -411,6 +459,7 @@ static void test_srv_metadata_status_respond(void) { \ .test_id = "lcd_" #role "_" #name, \ .test_descr = description, \ + .test_args_f = test_args_parse, \ .test_tick_f = bt_mesh_test_timeout, \ .test_post_init_f = test_##role##_init, \ .test_main_f = test_##role##_##name, \ diff --git a/tests/bsim/bluetooth/mesh/src/test_op_agg.c b/tests/bsim/bluetooth/mesh/src/test_op_agg.c index 9f091491e00..fe15219246f 100644 --- a/tests/bsim/bluetooth/mesh/src/test_op_agg.c +++ b/tests/bsim/bluetooth/mesh/src/test_op_agg.c @@ -51,17 +51,10 @@ static struct k_sem cli_suspend_sem; static struct k_sem srv_suspend_sem; static const uint8_t dev_key[16] = {0xaa}; static uint8_t cli_sent_array[TEST_SEND_ITR], cli_rcvd_array[TEST_SEND_ITR]; - -static struct bt_mesh_msg_ctx test_ctx = { - .net_idx = 0, - .app_idx = 0, - .addr = SRV_ADDR, -}; - static struct bt_mesh_prov prov; static struct bt_mesh_cfg_cli cfg_cli; -static int get_handler(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int get_handler(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { uint8_t seq = net_buf_simple_pull_u8(buf); @@ -85,7 +78,7 @@ static int get_handler(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, return bt_mesh_model_send(model, ctx, &msg, NULL, NULL); } -static int status_handler(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int status_handler(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { uint8_t seq = net_buf_simple_pull_u8(buf); @@ -100,7 +93,8 @@ static int status_handler(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *c return 0; } -static int dummy_vnd_mod_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, uint8_t seq) +static int dummy_vnd_mod_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, + uint8_t seq) { BT_MESH_MODEL_BUF_DEFINE(msg, BT_MESH_DUMMY_VND_MOD_GET_OP, BT_MESH_DUMMY_VND_MOD_MSG_MAXLEN); @@ -125,7 +119,7 @@ const struct bt_mesh_model_op _dummy_vnd_mod_op[] = { BT_MESH_MODEL_OP_END, }; -static struct bt_mesh_elem elements[] = {BT_MESH_ELEM( +static const struct bt_mesh_elem elements[] = {BT_MESH_ELEM( 0, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), BT_MESH_MODEL_OP_AGG_SRV, BT_MESH_MODEL_OP_AGG_CLI), @@ -168,25 +162,43 @@ static void op_agg_test_prov_and_conf(uint16_t addr) } } -static void test_cli_max_len_sequence_msg_send(void) +static void common_init(uint16_t own_addr, uint16_t dst_addr, bool agg_cli_fill) { - struct bt_mesh_model *dummy_vnd_model = &elements[0].vnd_models[0]; - uint8_t seq; - bt_mesh_test_cfg_set(NULL, WAIT_TIME); bt_mesh_device_setup(&prov, &comp); - op_agg_test_prov_and_conf(CLI_ADDR); + op_agg_test_prov_and_conf(own_addr); ASSERT_OK(k_sem_init(&cli_suspend_sem, 0, 1)); - ASSERT_OK(bt_mesh_op_agg_cli_seq_start(0, 0, SRV_ADDR, SRV_ADDR)); + ASSERT_OK(k_sem_init(&srv_suspend_sem, 0, 1)); + ASSERT_OK(bt_mesh_op_agg_cli_seq_start(0, 0, dst_addr, dst_addr)); + + if (!agg_cli_fill) { + return; + } + + struct bt_mesh_msg_ctx ctx = { + .net_idx = 0, + .app_idx = 0, + .addr = dst_addr, + }; + /* Populate the op_agg sequence */ for (int i = 0; i < TEST_SEND_ITR; i++) { - seq = cli_sent_array[i] = i; - ASSERT_OK(dummy_vnd_mod_get(dummy_vnd_model, &test_ctx, seq)); + cli_sent_array[i] = i; + ASSERT_OK(dummy_vnd_mod_get(&elements[0].vnd_models[0], &ctx, i)); } +} - ASSERT_OK(bt_mesh_op_agg_cli_seq_send()); +static void confirm_agg_seq(void) +{ + /* Wait for all expected GET messages to be received */ + if (k_sem_take(&srv_suspend_sem, SEM_TIMEOUT)) { + FAIL("Server suspension timed out. Get-messages received: %d", get_rcvd_count); + } +} +static void confirm_agg_status(void) +{ /* Wait for all expected STATUS messages to be received */ if (k_sem_take(&cli_suspend_sem, SEM_TIMEOUT)) { FAIL("Client suspension timed out. Status-messages received: %d", @@ -196,22 +208,69 @@ static void test_cli_max_len_sequence_msg_send(void) if (memcmp(cli_sent_array, cli_rcvd_array, ARRAY_SIZE(cli_rcvd_array))) { FAIL("Message arrays (sent / rcvd) are not equal."); } +} +static void test_cli_max_len_sequence_msg_send(void) +{ + common_init(CLI_ADDR, SRV_ADDR, true); + ASSERT_OK(bt_mesh_op_agg_cli_seq_send()); + confirm_agg_status(); PASS(); } static void test_srv_max_len_status_msg_send(void) { - bt_mesh_test_cfg_set(NULL, WAIT_TIME); - bt_mesh_device_setup(&prov, &comp); - op_agg_test_prov_and_conf(SRV_ADDR); + common_init(SRV_ADDR, CLI_ADDR, false); + confirm_agg_seq(); + PASS(); +} - ASSERT_OK(k_sem_init(&srv_suspend_sem, 0, 1)); +static void test_tester_model_coex(void) +{ + common_init(CLI_ADDR, SRV_ADDR, true); - /* Wait for all expected GET messages to be received */ - if (k_sem_take(&srv_suspend_sem, SEM_TIMEOUT)) { - FAIL("Server suspension timed out. Get-messages received: %d", get_rcvd_count); - } + /* Immediately send aggregated sequence to srv device */ + ASSERT_OK(bt_mesh_op_agg_cli_seq_send()); + + /* Confirm status messages for sequence */ + confirm_agg_status(); + + /* Confirm incoming sequence messages from server */ + confirm_agg_seq(); + + PASS(); +} + +static void test_dut_model_coex(void) +{ + /* Start an aggregated sequence, but postpone sending it */ + common_init(SRV_ADDR, CLI_ADDR, true); + + /* Wait and confirm incoming sequence messages from cli device */ + confirm_agg_seq(); + + /* After incoming sequence completes, send aggregated sequence to srv device */ + ASSERT_OK(bt_mesh_op_agg_cli_seq_send()); + + /* Confirm status messages for sequence */ + confirm_agg_status(); + + PASS(); +} + +static void test_dut_model_coex_loopback(void) +{ + /* Start an aggregated sequence */ + common_init(SRV_ADDR, SRV_ADDR, true); + + /* Send aggregated sequence to server model over loopback */ + ASSERT_OK(bt_mesh_op_agg_cli_seq_send()); + + /* Confirm incoming sequence messages */ + confirm_agg_seq(); + + /* Confirm status messages for sequence */ + confirm_agg_status(); PASS(); } @@ -228,8 +287,11 @@ static const struct bst_test_instance test_op_agg[] = { TEST_CASE(cli, max_len_sequence_msg_send, "OpAggCli composes a sequence request list, expecting a 380 Byte status message " "in return."), + TEST_CASE(tester, model_coex, "Tester: Coexistence of OpAggSrv and OpAggCli."), TEST_CASE(srv, max_len_status_msg_send, "OpAggSrv will respond with a 380 Byte status message. "), + TEST_CASE(dut, model_coex, "DUT: Coexistence of OpAggSrv and OpAggCli."), + TEST_CASE(dut, model_coex_loopback, "DUT: Coexistence for OpAggSrv and OpAggCli loopback."), BSTEST_END_MARKER}; diff --git a/tests/bsim/bluetooth/mesh/src/test_persistence.c b/tests/bsim/bluetooth/mesh/src/test_persistence.c index aab9c6dd185..4bf1f9faa93 100644 --- a/tests/bsim/bluetooth/mesh/src/test_persistence.c +++ b/tests/bsim/bluetooth/mesh/src/test_persistence.c @@ -204,6 +204,14 @@ static const struct stack_cfg { enum bt_mesh_feat_state state; uint8_t transmit; } relay; +#ifdef CONFIG_BT_MESH_PRIV_BEACONS + uint8_t priv_beacon; + uint8_t priv_beacon_int; + uint8_t priv_beacon_gatt; +#endif +#ifdef CONFIG_BT_MESH_OD_PRIV_PROXY_SRV + uint8_t priv_proxy_val; +#endif } stack_cfgs[] = { { .beacon = 1, @@ -212,6 +220,14 @@ static const struct stack_cfg { .friend = 1, .net_transmit = BT_MESH_TRANSMIT(3, 20), .relay = { .state = BT_MESH_FEATURE_ENABLED, .transmit = BT_MESH_TRANSMIT(2, 20) }, +#ifdef CONFIG_BT_MESH_PRIV_BEACONS + .priv_beacon = 1, + .priv_beacon_int = 123, + .priv_beacon_gatt = 0, +#endif +#ifdef CONFIG_BT_MESH_OD_PRIV_PROXY_SRV + .priv_proxy_val = 10, +#endif }, { .beacon = 0, @@ -220,6 +236,14 @@ static const struct stack_cfg { .friend = 0, .net_transmit = BT_MESH_TRANSMIT(1, 30), .relay = { .state = BT_MESH_FEATURE_ENABLED, .transmit = BT_MESH_TRANSMIT(1, 10) }, +#ifdef CONFIG_BT_MESH_PRIV_BEACONS + .priv_beacon = 1, + .priv_beacon_int = 100, + .priv_beacon_gatt = 1, +#endif +#ifdef CONFIG_BT_MESH_OD_PRIV_PROXY_SRV + .priv_proxy_val = 20, +#endif }, }; static const struct stack_cfg *current_stack_cfg; @@ -314,7 +338,7 @@ static void check_mod_pub_params(const struct bt_mesh_cfg_cli_mod_pub *expected, ASSERT_EQUAL(expected->transmit, got->transmit); } -int test_model_settings_set(struct bt_mesh_model *model, +int test_model_settings_set(const struct bt_mesh_model *model, const char *name, size_t len_rd, settings_read_cb read_cb, void *cb_arg) { @@ -340,12 +364,12 @@ int test_model_settings_set(struct bt_mesh_model *model, return 0; } -void test_model_reset(struct bt_mesh_model *model) +void test_model_reset(const struct bt_mesh_model *model) { ASSERT_OK(bt_mesh_model_data_store(test_model, false, TEST_MOD_DATA_NAME, NULL, 0)); } -int test_vnd_model_settings_set(struct bt_mesh_model *model, +int test_vnd_model_settings_set(const struct bt_mesh_model *model, const char *name, size_t len_rd, settings_read_cb read_cb, void *cb_arg) { @@ -371,7 +395,7 @@ int test_vnd_model_settings_set(struct bt_mesh_model *model, return 0; } -void test_vnd_model_reset(struct bt_mesh_model *model) +void test_vnd_model_reset(const struct bt_mesh_model *model) { ASSERT_OK(bt_mesh_model_data_store(test_vnd_model, true, TEST_VND_MOD_DATA_NAME, NULL, 0)); } @@ -923,6 +947,37 @@ static void test_cfg_save(void) current_stack_cfg->relay.transmit); } +#ifdef CONFIG_BT_MESH_PRIV_BEACONS + struct bt_mesh_priv_beacon priv_beacon_state = { + .enabled = current_stack_cfg->priv_beacon, + .rand_interval = current_stack_cfg->priv_beacon_int, + }; + + err = bt_mesh_priv_beacon_cli_set(test_netkey_idx, TEST_ADDR, &priv_beacon_state, + &priv_beacon_state); + if (err) { + FAIL("Failed to enable Private Beacon (err %d)", err); + } + + uint8_t priv_beacon_gatt = current_stack_cfg->priv_beacon_gatt; + + err = bt_mesh_priv_beacon_cli_gatt_proxy_set(test_netkey_idx, TEST_ADDR, priv_beacon_gatt, + &priv_beacon_gatt); + if (err) { + FAIL("Failed to enable Private Beacon GATT proxy (err %d)", err); + } +#endif + +#if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV) && defined(CONFIG_BT_MESH_OD_PRIV_PROXY_CLI) + uint8_t priv_proxy_val; + + err = bt_mesh_od_priv_proxy_cli_set(test_netkey_idx, TEST_ADDR, + current_stack_cfg->priv_proxy_val, &priv_proxy_val); + if (err || priv_proxy_val != current_stack_cfg->priv_proxy_val) { + FAIL("Failed to set OD Private proxy (err %d, value %d)", err, priv_proxy_val); + } +#endif + k_sleep(K_SECONDS(CONFIG_BT_MESH_STORE_TIMEOUT)); PASS(); @@ -974,6 +1029,33 @@ static void test_cfg_load(void) FAIL("Relay get failed (err %d, state %u, transmit %x)", err, status, transmit); } +#ifdef CONFIG_BT_MESH_PRIV_BEACONS + struct bt_mesh_priv_beacon priv_beacon_state; + uint8_t priv_beacon_gatt; + + err = bt_mesh_priv_beacon_cli_get(test_netkey_idx, TEST_ADDR, &priv_beacon_state); + if (err || priv_beacon_state.enabled != current_stack_cfg->priv_beacon || + priv_beacon_state.rand_interval != current_stack_cfg->priv_beacon_int) { + FAIL("Private beacon get failed (err %d, enabled %u, interval %x)", err, + priv_beacon_state.enabled, priv_beacon_state.rand_interval); + } + + err = bt_mesh_priv_beacon_cli_gatt_proxy_get(test_netkey_idx, TEST_ADDR, &priv_beacon_gatt); + if (err || priv_beacon_gatt != current_stack_cfg->priv_beacon_gatt) { + FAIL("Private beacon GATT proxy get failed (err %d, enabled %u)", err, + priv_beacon_gatt); + } +#endif + +#if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV) && defined(CONFIG_BT_MESH_OD_PRIV_PROXY_CLI) + uint8_t priv_proxy_val; + + err = bt_mesh_od_priv_proxy_cli_get(test_netkey_idx, TEST_ADDR, &priv_proxy_val); + if (err || priv_proxy_val != current_stack_cfg->priv_proxy_val) { + FAIL("Private proxy get failed (err %d, value %u)", err, priv_proxy_val); + } +#endif + PASS(); } diff --git a/tests/bsim/bluetooth/mesh/src/test_provision.c b/tests/bsim/bluetooth/mesh/src/test_provision.c index c78fe8dc87d..f2c98778a3b 100644 --- a/tests/bsim/bluetooth/mesh/src/test_provision.c +++ b/tests/bsim/bluetooth/mesh/src/test_provision.c @@ -118,7 +118,7 @@ static struct bt_mesh_rpr_cli rpr_cli = { static const struct bt_mesh_comp rpr_cli_comp = { .elem = - (struct bt_mesh_elem[]){ + (const struct bt_mesh_elem[]){ BT_MESH_ELEM(1, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&(struct bt_mesh_cfg_cli){}), @@ -130,7 +130,7 @@ static const struct bt_mesh_comp rpr_cli_comp = { static const struct bt_mesh_comp rpr_srv_comp = { .elem = - (struct bt_mesh_elem[]){ + (const struct bt_mesh_elem[]){ BT_MESH_ELEM(1, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_RPR_SRV), @@ -141,7 +141,7 @@ static const struct bt_mesh_comp rpr_srv_comp = { static const struct bt_mesh_comp rpr_cli_srv_comp = { .elem = - (struct bt_mesh_elem[]){ + (const struct bt_mesh_elem[]){ BT_MESH_ELEM(1, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&(struct bt_mesh_cfg_cli){}), @@ -152,7 +152,7 @@ static const struct bt_mesh_comp rpr_cli_srv_comp = { .elem_count = 1, }; -static int mock_pdu_send(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int mock_pdu_send(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { /* Device becomes unresponsive and doesn't communicate with other nodes anymore */ @@ -168,10 +168,10 @@ static const struct bt_mesh_model_op model_rpr_op1[] = { BT_MESH_MODEL_OP_END }; -static int mock_model_init(struct bt_mesh_model *mod) +static int mock_model_init(const struct bt_mesh_model *mod) { mod->keys[0] = BT_MESH_KEY_DEV_LOCAL; - mod->flags |= BT_MESH_MOD_DEVKEY_ONLY; + mod->rt->flags |= BT_MESH_MOD_DEVKEY_ONLY; return 0; } @@ -182,7 +182,7 @@ const struct bt_mesh_model_cb mock_model_cb = { static const struct bt_mesh_comp rpr_srv_comp_unresponsive = { .elem = - (struct bt_mesh_elem[]){ + (const struct bt_mesh_elem[]){ BT_MESH_ELEM(1, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CB(IMPOSTER_MODEL_ID, @@ -194,9 +194,34 @@ static const struct bt_mesh_comp rpr_srv_comp_unresponsive = { .elem_count = 1, }; +static const uint8_t elem_offset1[2] = {1, 2}; +static const uint8_t elem_offset2[3] = {4, 5, 6}; +static const uint8_t additional_data[2] = {100, 200}; + +static const struct bt_mesh_comp2_record comp_rec[2] = { + {.id = 1, + .version.x = 2, + .version.y = 3, + .version.z = 4, + .elem_offset_cnt = sizeof(elem_offset1), + .elem_offset = elem_offset1, + .data_len = 0}, + {.id = 10, + .version.x = 20, + .version.y = 30, + .version.z = 40, + .elem_offset_cnt = sizeof(elem_offset2), + .elem_offset = elem_offset2, + .data_len = sizeof(additional_data), + .data = additional_data}, +}; + +static const struct bt_mesh_comp2 comp_p2_1 = {.record_cnt = 1, .record = comp_rec}; +static const struct bt_mesh_comp2 comp_p2_2 = {.record_cnt = 2, .record = comp_rec}; + static const struct bt_mesh_comp rpr_srv_comp_2_elem = { .elem = - (struct bt_mesh_elem[]){ + (const struct bt_mesh_elem[]){ BT_MESH_ELEM(1, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_RPR_SRV), @@ -553,7 +578,7 @@ static void node_configure_and_reset(void) BT_MESH_MODEL_ID_HEALTH_SRV, &healthpub, &status)); ASSERT_EQUAL(0, status); - ASSERT_TRUE(healthpub.addr == BT_MESH_ADDR_UNASSIGNED, "Pub not cleared"); + ASSERT_TRUE_MSG(healthpub.addr == BT_MESH_ADDR_UNASSIGNED, "Pub not cleared\n"); /* Set pub and sub to check that they are reset */ healthpub.addr = 0xc001; @@ -567,26 +592,26 @@ static void node_configure_and_reset(void) &status)); ASSERT_EQUAL(0, status); - k_sleep(K_SECONDS(1)); + k_sleep(K_SECONDS(2)); ASSERT_OK(bt_mesh_cfg_cli_mod_app_bind(0, current_dev_addr, current_dev_addr, 0x0, BT_MESH_MODEL_ID_HEALTH_SRV, &status)); ASSERT_EQUAL(0, status); - k_sleep(K_SECONDS(1)); + k_sleep(K_SECONDS(2)); ASSERT_OK(bt_mesh_cfg_cli_mod_sub_add(0, current_dev_addr, current_dev_addr, 0xc000, BT_MESH_MODEL_ID_HEALTH_SRV, &status)); ASSERT_EQUAL(0, status); - k_sleep(K_SECONDS(1)); + k_sleep(K_SECONDS(2)); ASSERT_OK(bt_mesh_cfg_cli_mod_pub_set(0, current_dev_addr, current_dev_addr, BT_MESH_MODEL_ID_HEALTH_SRV, &healthpub, &status)); ASSERT_EQUAL(0, status); - k_sleep(K_SECONDS(1)); + k_sleep(K_SECONDS(2)); ASSERT_OK(bt_mesh_cfg_cli_node_reset(0, current_dev_addr, (bool *)&status)); @@ -894,14 +919,18 @@ static void device_pb_remote_server_setup(const struct bt_mesh_comp *comp, bool ASSERT_OK(bt_mesh_prov_enable(BT_MESH_PROV_REMOTE)); } -static void device_pb_remote_server_setup_unproved(const struct bt_mesh_comp *comp) +static void device_pb_remote_server_setup_unproved(const struct bt_mesh_comp *comp, + const struct bt_mesh_comp2 *comp_p2) { device_pb_remote_server_setup(comp, true); + bt_mesh_comp2_register(comp_p2); } -static void device_pb_remote_server_setup_proved(const struct bt_mesh_comp *comp) +static void device_pb_remote_server_setup_proved(const struct bt_mesh_comp *comp, + const struct bt_mesh_comp2 *comp_p2) { device_pb_remote_server_setup(comp, false); + bt_mesh_comp2_register(comp_p2); } /** @brief Verify that the provisioner can provision a device multiple times after resets using @@ -1231,7 +1260,7 @@ static void test_provisioner_pb_remote_client_nppi_robustness(void) */ static void test_device_pb_remote_server_unproved(void) { - device_pb_remote_server_setup_unproved(&rpr_srv_comp); + device_pb_remote_server_setup_unproved(&rpr_srv_comp, &comp_p2_1); PASS(); } @@ -1242,7 +1271,7 @@ static void test_device_pb_remote_server_unproved(void) */ static void test_device_pb_remote_server_unproved_unresponsive(void) { - device_pb_remote_server_setup_unproved(&rpr_srv_comp_unresponsive); + device_pb_remote_server_setup_unproved(&rpr_srv_comp_unresponsive, NULL); k_sem_init(&pdu_send_sem, 0, 1); ASSERT_OK(k_sem_take(&pdu_send_sem, K_SECONDS(200))); @@ -1255,7 +1284,7 @@ static void test_device_pb_remote_server_unproved_unresponsive(void) */ static void test_device_pb_remote_server_proved(void) { - device_pb_remote_server_setup_proved(&rpr_srv_comp); + device_pb_remote_server_setup_proved(&rpr_srv_comp, &comp_p2_1); PASS(); } @@ -1543,6 +1572,9 @@ static void comp_data_get(uint16_t server_addr, uint8_t page, struct net_buf_sim { uint8_t page_rsp; + /* Let complete advertising of the transaction to prevent collisions. */ + k_sleep(K_SECONDS(3)); + net_buf_simple_reset(comp); ASSERT_OK(bt_mesh_cfg_cli_comp_data_get(0, server_addr, page, &page_rsp, comp)); ASSERT_EQUAL(page, page_rsp); @@ -1572,30 +1604,30 @@ static void test_provisioner_pb_remote_client_ncrp(void) { NET_BUF_SIMPLE_DEFINE(dev_comp_p0, BT_MESH_RX_SDU_MAX); NET_BUF_SIMPLE_DEFINE(dev_comp_p1, BT_MESH_RX_SDU_MAX); + NET_BUF_SIMPLE_DEFINE(dev_comp_p2, BT_MESH_RX_SDU_MAX); NET_BUF_SIMPLE_DEFINE(dev_comp_p128, BT_MESH_RX_SDU_MAX); NET_BUF_SIMPLE_DEFINE(dev_comp_p129, BT_MESH_RX_SDU_MAX); + NET_BUF_SIMPLE_DEFINE(dev_comp_p130, BT_MESH_RX_SDU_MAX); uint16_t pb_remote_server_addr = 0x0003; - uint8_t page; k_sem_init(&prov_sem, 0, 1); k_sem_init(&reprov_sem, 0, 1); bt_mesh_device_setup(&prov, &rpr_cli_comp); - /* Store Composition Data Page 0, 1, 128 and 129. */ - ASSERT_OK(bt_mesh_cfg_cli_comp_data_get(0, pb_remote_server_addr, 0, &page, &dev_comp_p0)); - ASSERT_EQUAL(0, page); - ASSERT_OK(bt_mesh_cfg_cli_comp_data_get(0, pb_remote_server_addr, 1, &page, &dev_comp_p1)); - ASSERT_EQUAL(1, page); - ASSERT_OK(bt_mesh_cfg_cli_comp_data_get(0, pb_remote_server_addr, 128, &page, - &dev_comp_p128)); - ASSERT_EQUAL(128, page); - ASSERT_OK(bt_mesh_cfg_cli_comp_data_get(0, pb_remote_server_addr, 129, &page, - &dev_comp_p129)); - ASSERT_EQUAL(129, page); - ASSERT_TRUE(dev_comp_p0.len != dev_comp_p128.len); - ASSERT_TRUE(dev_comp_p1.len != dev_comp_p129.len); + /* Store Composition Data Page 0, 1, 2, 128, 129 and 130. */ + comp_data_get(pb_remote_server_addr, 0, &dev_comp_p0); + comp_data_get(pb_remote_server_addr, 128, &dev_comp_p128); + comp_data_compare(&dev_comp_p0, &dev_comp_p128, false); + + comp_data_get(pb_remote_server_addr, 1, &dev_comp_p1); + comp_data_get(pb_remote_server_addr, 129, &dev_comp_p129); + comp_data_compare(&dev_comp_p1, &dev_comp_p129, false); + + comp_data_get(pb_remote_server_addr, 2, &dev_comp_p2); + comp_data_get(pb_remote_server_addr, 130, &dev_comp_p130); + comp_data_compare(&dev_comp_p2, &dev_comp_p130, false); LOG_INF("Start Node Composition Refresh procedure...\n"); @@ -1612,59 +1644,34 @@ static void test_provisioner_pb_remote_client_ncrp(void) ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(20))); /* Check that Composition Data Page 128 still exists and is now equal to Page 0. */ - net_buf_simple_reset(&dev_comp_p0); - ASSERT_OK(bt_mesh_cfg_cli_comp_data_get(0, pb_remote_server_addr, 0, &page, &dev_comp_p0)); - ASSERT_EQUAL(0, page); - ASSERT_EQUAL(dev_comp_p0.len, dev_comp_p128.len); - if (memcmp(dev_comp_p0.data, dev_comp_p128.data, dev_comp_p0.len)) { - FAIL("Wrong composition data page 0"); - } - - net_buf_simple_reset(&dev_comp_p128); - ASSERT_OK(bt_mesh_cfg_cli_comp_data_get(0, pb_remote_server_addr, 128, &page, - &dev_comp_p128)); - ASSERT_EQUAL(128, page); - ASSERT_EQUAL(dev_comp_p0.len, dev_comp_p128.len); - if (memcmp(dev_comp_p0.data, dev_comp_p128.data, dev_comp_p0.len)) { - FAIL("Wrong composition data page 128"); - } + comp_data_get(pb_remote_server_addr, 0, &dev_comp_p0); + comp_data_compare(&dev_comp_p0, &dev_comp_p128, true); + comp_data_get(pb_remote_server_addr, 128, &dev_comp_p128); + comp_data_compare(&dev_comp_p0, &dev_comp_p128, true); /* Check that Composition Data Page 129 still exists and is now equal to Page 1. */ - net_buf_simple_reset(&dev_comp_p1); - ASSERT_OK(bt_mesh_cfg_cli_comp_data_get(0, pb_remote_server_addr, 1, &page, &dev_comp_p1)); - ASSERT_EQUAL(1, page); - ASSERT_EQUAL(dev_comp_p1.len, dev_comp_p129.len); - if (memcmp(dev_comp_p1.data, dev_comp_p129.data, dev_comp_p1.len)) { - FAIL("Wrong composition data page 1"); - } + comp_data_get(pb_remote_server_addr, 1, &dev_comp_p1); + comp_data_compare(&dev_comp_p1, &dev_comp_p129, true); + comp_data_get(pb_remote_server_addr, 129, &dev_comp_p129); + comp_data_compare(&dev_comp_p1, &dev_comp_p129, true); - net_buf_simple_reset(&dev_comp_p129); - ASSERT_OK(bt_mesh_cfg_cli_comp_data_get(0, pb_remote_server_addr, 129, &page, - &dev_comp_p129)); - ASSERT_EQUAL(129, page); - ASSERT_EQUAL(dev_comp_p1.len, dev_comp_p129.len); - if (memcmp(dev_comp_p1.data, dev_comp_p129.data, dev_comp_p1.len)) { - FAIL("Wrong composition data page 129"); - } + /* Check that Composition Data Page 130 still exists and is now equal to Page 2. */ + comp_data_get(pb_remote_server_addr, 2, &dev_comp_p2); + comp_data_compare(&dev_comp_p2, &dev_comp_p130, true); + comp_data_get(pb_remote_server_addr, 130, &dev_comp_p130); + comp_data_compare(&dev_comp_p2, &dev_comp_p130, true); PASS(); } -static void comp_data_pages_equal_check(uint16_t server_addr, uint8_t page1, uint8_t page2) +static void comp_data_pages_get_and_equal_check(uint16_t server_addr, uint8_t page1, uint8_t page2) { NET_BUF_SIMPLE_DEFINE(comp_1, BT_MESH_RX_SDU_MAX); NET_BUF_SIMPLE_DEFINE(comp_2, BT_MESH_RX_SDU_MAX); - uint8_t page; - ASSERT_OK(bt_mesh_cfg_cli_comp_data_get(0, server_addr, page1, &page, &comp_1)); - ASSERT_EQUAL(page1, page); - ASSERT_OK(bt_mesh_cfg_cli_comp_data_get(0, server_addr, page2, &page, - &comp_2)); - ASSERT_EQUAL(page2, page); - ASSERT_TRUE(comp_1.len == comp_2.len); - if (memcmp(comp_1.data, comp_2.data, comp_1.len)) { - FAIL("Composition data page %d is not the same as page %d", page1, page2); - } + comp_data_get(server_addr, page1, &comp_1); + comp_data_get(server_addr, page2, &comp_2); + comp_data_compare(&comp_1, &comp_2, true); } /** @brief Test Node Composition Refresh procedure on Remote Provisioning client: @@ -1680,9 +1687,9 @@ static void test_provisioner_pb_remote_client_ncrp_second_time(void) bt_mesh_device_setup(&prov, &rpr_cli_comp); - comp_data_pages_equal_check(pb_remote_server_addr, 0, 128); - comp_data_pages_equal_check(pb_remote_server_addr, 1, 129); - + comp_data_pages_get_and_equal_check(pb_remote_server_addr, 0, 128); + comp_data_pages_get_and_equal_check(pb_remote_server_addr, 1, 129); + comp_data_pages_get_and_equal_check(pb_remote_server_addr, 2, 130); LOG_INF("Start Node Composition Refresh procedure...\n"); struct bt_mesh_rpr_node srv = { @@ -1707,7 +1714,7 @@ static void test_provisioner_pb_remote_client_ncrp_second_time(void) */ static void test_device_pb_remote_server_ncrp_prepare(void) { - device_pb_remote_server_setup_unproved(&rpr_srv_comp); + device_pb_remote_server_setup_unproved(&rpr_srv_comp, &comp_p2_1); LOG_INF("Preparing for Composition Data change"); bt_mesh_comp_change_prepare(); @@ -1721,7 +1728,7 @@ static void test_device_pb_remote_server_ncrp_prepare(void) */ static void test_device_pb_remote_server_ncrp(void) { - device_pb_remote_server_setup_proved(&rpr_srv_comp_2_elem); + device_pb_remote_server_setup_proved(&rpr_srv_comp_2_elem, &comp_p2_2); LOG_INF("Waiting for being re-provisioned."); ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(30))); @@ -1737,7 +1744,7 @@ static void test_device_pb_remote_server_ncrp_second_time(void) { int err; - device_pb_remote_server_setup_proved(&rpr_srv_comp_2_elem); + device_pb_remote_server_setup_proved(&rpr_srv_comp_2_elem, &comp_p2_2); LOG_INF("Wait to verify that node is not re-provisioned..."); err = k_sem_take(&reprov_sem, K_SECONDS(30)); diff --git a/tests/bsim/bluetooth/mesh/src/test_replay_cache.c b/tests/bsim/bluetooth/mesh/src/test_replay_cache.c index d7c140ab3ed..68dc52a7b5d 100644 --- a/tests/bsim/bluetooth/mesh/src/test_replay_cache.c +++ b/tests/bsim/bluetooth/mesh/src/test_replay_cache.c @@ -182,7 +182,7 @@ static void test_rx_immediate_replay_attack(void) k_sleep(K_SECONDS(6 * TEST_DATA_WAITING_TIME)); - ASSERT_TRUE(rx_cnt == 3, "Device didn't receive expected data"); + ASSERT_TRUE_MSG(rx_cnt == 3, "Device didn't receive expected data\n"); PASS(); } @@ -243,7 +243,7 @@ static void test_rx_power_replay_attack(void) k_sleep(K_SECONDS(6 * TEST_DATA_WAITING_TIME)); - ASSERT_TRUE(rx_cnt == 3, "Device didn't receive expected data"); + ASSERT_TRUE_MSG(rx_cnt == 3, "Device didn't receive expected data\n"); PASS(); } diff --git a/tests/bsim/bluetooth/mesh/src/test_sar.c b/tests/bsim/bluetooth/mesh/src/test_sar.c index a928d973a25..61c7946235d 100644 --- a/tests/bsim/bluetooth/mesh/src/test_sar.c +++ b/tests/bsim/bluetooth/mesh/src/test_sar.c @@ -91,7 +91,7 @@ static void data_integrity_check(struct net_buf_simple *buf) net_buf_simple_restore(buf, &state); } -static int get_handler(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int get_handler(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { data_integrity_check(buf); @@ -104,7 +104,7 @@ static int get_handler(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, return bt_mesh_model_send(model, ctx, &msg, NULL, NULL); } -static int status_handler(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int status_handler(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { data_integrity_check(buf); @@ -112,7 +112,7 @@ static int status_handler(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *c return 0; } -static int dummy_vnd_mod_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, +static int dummy_vnd_mod_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, uint8_t msg[]) { BT_MESH_MODEL_BUF_DEFINE(buf, DUMMY_VND_MOD_GET_OP, MAX_SDU_MSG_LEN); @@ -131,7 +131,7 @@ static const struct bt_mesh_model_op _dummy_vnd_mod_op[] = { uint16_t dummy_keys[CONFIG_BT_MESH_MODEL_KEY_COUNT] = { 0 }; -static struct bt_mesh_elem elements[] = {BT_MESH_ELEM( +static const struct bt_mesh_elem elements[] = {BT_MESH_ELEM( 0, MODEL_LIST(BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), @@ -185,7 +185,7 @@ static void array_random_fill(uint8_t array[], uint16_t len, int seed) static void cli_max_len_sdu_send(struct bt_mesh_sar_rx *sar_rx_config, struct bt_mesh_sar_tx *sar_tx_config) { - struct bt_mesh_model *dummy_vnd_mod = &elements[0].vnd_models[0]; + const struct bt_mesh_model *dummy_vnd_mod = &elements[0].vnd_models[0]; bt_mesh_test_cfg_set(NULL, WAIT_TIME); bt_mesh_device_setup(&prov, &comp); diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/beacon/beacon_cache.sh b/tests/bsim/bluetooth/mesh/tests_scripts/beacon/beacon_cache.sh new file mode 100755 index 00000000000..c0f741e9aae --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/beacon/beacon_cache.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test Beacon cache +# +# Test procedure: +# 0. RX device starts monitoring all accepted SNB messages. +# 1. TX device sends two identical SNBs to the RX device. +# 2. TX device sends a secondary SNBs to the RX device, marking the end of the test. +# 3. RX device verifies that only one of the two identical beacons was processed. +RunTest mesh_beacon_cache \ + beacon_tx_beacon_cache \ + beacon_rx_beacon_cache + +conf=prj_mesh1d1_conf +RunTest mesh_beacon_cache \ + beacon_tx_beacon_cache \ + beacon_rx_beacon_cache + +conf=prj_mesh1d1_conf +overlay=overlay_psa_conf +RunTest mesh_beacon_cache \ + beacon_tx_beacon_cache \ + beacon_rx_beacon_cache diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/comp_data/cdp1_encode_decode.sh b/tests/bsim/bluetooth/mesh/tests_scripts/comp_data/cdp1_encode_decode.sh new file mode 100755 index 00000000000..e4f99e80d5d --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/comp_data/cdp1_encode_decode.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test that the composition data page 1 (CDP1) is encoded correctly. The +# composition consists of model extensions within and between elements, +# extensions requiring long and short formats, and correspondence between +# a SIG and vendor model. +# +# Test procedure: +# 0. Provisioning and setup. +# 1. Configuration client requests the node's CDP1. +# 2. The received CDP1 is compared to a hardcoded version. +conf=prj_mesh1d1_conf +RunTest mesh_cdp1_test \ + cdp1_node_data_comparison + +conf=prj_mesh1d1_conf +overlay=overlay_psa_conf +RunTest mesh_cdp1_test_psa \ + cdp1_node_data_comparison diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp0_data_split.sh b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp0_data_split.sh new file mode 100755 index 00000000000..d65326b3d7f --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp0_data_split.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test that the LCD server model is able to split the +# composition data when the total size exceeds the maximum access message size. +# +# Test procedure: +# 0. Provisioning and setup. Server and client has same comp data. +# 1. Client requests a sample exceeding the maximum avaialble payload from the +# server's composition data. +# 2. Client fetch its local comp data. +# 3. When server status arrive, remove status field data and compare received +# comp data with corresponding bytes in local comp data. +# 4. Client requests the next sample from server's composition data. +# 5. When server status arrive, remove status field data and compare received +# comp data with correspending bytes in local comp data. +# 6. Client merges the two samples and checks that the collected data is +# correctly merged, continuous, and matches its local comp data. +conf=prj_mesh1d1_conf +overlay=overlay_pst_conf +RunTest mesh_lcd_test_comp0_data_split \ + lcd_srv_comp_data_status_respond lcd_cli_split_comp_data_request -- -argstest page=0 + +conf=prj_mesh1d1_conf +overlay="overlay_pst_conf_overlay_psa_conf" +RunTest mesh_lcd_test_comp0_data_split \ + lcd_srv_comp_data_status_respond lcd_cli_split_comp_data_request -- -argstest page=0 diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp0_data_split_dfu.sh b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp0_data_split_dfu.sh new file mode 100755 index 00000000000..6a65a2492ed --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp0_data_split_dfu.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test that the LCD server model is able to split the +# composition data when the total size exceeds the maximum access message size. +# The test environment simulates a scenario where the server has completed DFU. +# +# Test procedure: +# 0. Provisioning and setup. Server and client has same comp data. +# 1. Client requests a sample exceeding the maximum avaialble payload from the +# server's composition data. +# 2. Client fetch its local comp data. +# 3. When server status arrive, remove status field data and compare received +# comp data with corresponding bytes in local comp data. +# 4. Client requests the next sample from server's composition data. +# 5. When server status arrive, remove status field data and compare received +# comp data with correspending bytes in local comp data. +# 6. Client merges the two samples and checks that the collected data is +# correctly merged, continuous, and matches its local comp data. +conf=prj_mesh1d1_conf +overlay=overlay_pst_conf +RunTest mesh_lcd_test_comp0_data_split_dfu \ + lcd_srv_comp_data_status_respond \ + lcd_cli_split_comp_data_request -- -argstest page=0 comp-changed-mode=1 + +conf=prj_mesh1d1_conf +overlay="overlay_pst_conf_overlay_psa_conf" +RunTest mesh_lcd_test_comp0_data_split_dfu \ + lcd_srv_comp_data_status_respond \ + lcd_cli_split_comp_data_request -- -argstest page=0 comp-changed-mode=1 diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp128_data_split.sh b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp128_data_split.sh new file mode 100755 index 00000000000..77d4a1737a5 --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp128_data_split.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test that the LCD server model is able to split the +# composition data when the total size exceeds the maximum access message size. +# +# Test procedure: +# 0. Provisioning and setup. Server and client has same comp data. +# 1. Client requests a sample exceeding the maximum avaialble payload from the +# server's composition data. +# 2. Client fetch its local comp data. +# 3. When server status arrive, remove status field data and compare received +# comp data with corresponding bytes in local comp data. +# 4. Client requests the next sample from server's composition data. +# 5. When server status arrive, remove status field data and compare received +# comp data with correspending bytes in local comp data. +# 6. Client merges the two samples and checks that the collected data is +# correctly merged, continuous, and matches its local comp data. +conf=prj_mesh1d1_conf +overlay=overlay_pst_conf +RunTest mesh_lcd_test_comp128_data_split \ + lcd_srv_comp_data_status_respond lcd_cli_split_comp_data_request -- -argstest page=128 + +conf=prj_mesh1d1_conf +overlay="overlay_pst_conf_overlay_psa_conf" +RunTest mesh_lcd_test_comp128_data_split \ + lcd_srv_comp_data_status_respond lcd_cli_split_comp_data_request -- -argstest page=128 diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp128_data_split_dfu.sh b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp128_data_split_dfu.sh new file mode 100755 index 00000000000..9abdfd00dd7 --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp128_data_split_dfu.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test that the LCD server model is able to split the +# composition data when the total size exceeds the maximum access message size. +# The test environment simulates a scenario where the server has completed DFU. +# +# Test procedure: +# 0. Provisioning and setup. Server and client has same comp data. +# 1. Client requests a sample exceeding the maximum avaialble payload from the +# server's composition data. +# 2. Client fetch its local comp data. +# 3. When server status arrive, remove status field data and compare received +# comp data with corresponding bytes in local comp data. +# 4. Client requests the next sample from server's composition data. +# 5. When server status arrive, remove status field data and compare received +# comp data with correspending bytes in local comp data. +# 6. Client merges the two samples and checks that the collected data is +# correctly merged, continuous, and matches its local comp data. +conf=prj_mesh1d1_conf +overlay=overlay_pst_conf +RunTest mesh_lcd_test_comp128_data_split_dfu \ + lcd_srv_comp_data_status_respond \ + lcd_cli_split_comp_data_request -- -argstest page=128 comp-changed-mode=1 + +conf=prj_mesh1d1_conf +overlay="overlay_pst_conf_overlay_psa_conf" +RunTest mesh_lcd_test_comp128_data_split_dfu \ + lcd_srv_comp_data_status_respond \ + lcd_cli_split_comp_data_request -- -argstest page=128 comp-changed-mode=1 diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp129_data_split.sh b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp129_data_split.sh new file mode 100755 index 00000000000..fba1760cb36 --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp129_data_split.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test that the LCD server model is able to split the +# composition data when the total size exceeds the maximum access message size. +# +# Test procedure: +# 0. Provisioning and setup. Server and client has same comp data. +# 1. Client requests a sample exceeding the maximum avaialble payload from the +# server's composition data. +# 2. Client fetch its local comp data. +# 3. When server status arrive, remove status field data and compare received +# comp data with corresponding bytes in local comp data. +# 4. Client requests the next sample from server's composition data. +# 5. When server status arrive, remove status field data and compare received +# comp data with correspending bytes in local comp data. +# 6. Client merges the two samples and checks that the collected data is +# correctly merged, continuous, and matches its local comp data. +conf=prj_mesh1d1_conf +overlay=overlay_pst_conf +RunTest mesh_lcd_test_comp129_data_split \ + lcd_srv_comp_data_status_respond lcd_cli_split_comp_data_request -- -argstest page=129 + +conf=prj_mesh1d1_conf +overlay="overlay_pst_conf_overlay_psa_conf" +RunTest mesh_lcd_test_comp129_data_split \ + lcd_srv_comp_data_status_respond lcd_cli_split_comp_data_request -- -argstest page=129 diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp129_data_split_dfu.sh b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp129_data_split_dfu.sh new file mode 100755 index 00000000000..282c3425c81 --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp129_data_split_dfu.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test that the LCD server model is able to split the +# composition data when the total size exceeds the maximum access message size. +# The test environment simulates a scenario where the server has completed DFU. +# +# Test procedure: +# 0. Provisioning and setup. Server and client has same comp data. +# 1. Client requests a sample exceeding the maximum avaialble payload from the +# server's composition data. +# 2. Client fetch its local comp data. +# 3. When server status arrive, remove status field data and compare received +# comp data with corresponding bytes in local comp data. +# 4. Client requests the next sample from server's composition data. +# 5. When server status arrive, remove status field data and compare received +# comp data with correspending bytes in local comp data. +# 6. Client merges the two samples and checks that the collected data is +# correctly merged, continuous, and matches its local comp data. +conf=prj_mesh1d1_conf +overlay=overlay_pst_conf +RunTest mesh_lcd_test_comp129_data_split_dfu \ + lcd_srv_comp_data_status_respond \ + lcd_cli_split_comp_data_request -- -argstest page=129 comp-changed-mode=1 + +conf=prj_mesh1d1_conf +overlay="overlay_pst_conf_overlay_psa_conf" +RunTest mesh_lcd_test_comp129_data_split_dfu \ + lcd_srv_comp_data_status_respond \ + lcd_cli_split_comp_data_request -- -argstest page=129 comp-changed-mode=1 diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp130_data_split.sh b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp130_data_split.sh new file mode 100755 index 00000000000..e3e8f2bad85 --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp130_data_split.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test that the LCD server model is able to split the +# composition data when the total size exceeds the maximum access message size. +# +# Test procedure: +# 0. Provisioning and setup. Server and client has same comp data. +# 1. Client requests a sample exceeding the maximum avaialble payload from the +# server's composition data. +# 2. Client fetch its local comp data. +# 3. When server status arrive, remove status field data and compare received +# comp data with corresponding bytes in local comp data. +# 4. Client requests the next sample from server's composition data. +# 5. When server status arrive, remove status field data and compare received +# comp data with correspending bytes in local comp data. +# 6. Client merges the two samples and checks that the collected data is +# correctly merged, continuous, and matches its local comp data. +conf=prj_mesh1d1_conf +overlay=overlay_pst_conf +RunTest mesh_lcd_test_comp130_data_split \ + lcd_srv_comp_data_status_respond lcd_cli_split_comp_data_request -- -argstest page=130 + +conf=prj_mesh1d1_conf +overlay="overlay_pst_conf_overlay_psa_conf" +RunTest mesh_lcd_test_comp130_data_split \ + lcd_srv_comp_data_status_respond lcd_cli_split_comp_data_request -- -argstest page=130 diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp130_data_split_dfu.sh b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp130_data_split_dfu.sh new file mode 100755 index 00000000000..5daf32c54c0 --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp130_data_split_dfu.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test that the LCD server model is able to split the +# composition data when the total size exceeds the maximum access message size. +# The test environment simulates a scenario where the server has completed DFU. +# +# Test procedure: +# 0. Provisioning and setup. Server and client has same comp data. +# 1. Client requests a sample exceeding the maximum avaialble payload from the +# server's composition data. +# 2. Client fetch its local comp data. +# 3. When server status arrive, remove status field data and compare received +# comp data with corresponding bytes in local comp data. +# 4. Client requests the next sample from server's composition data. +# 5. When server status arrive, remove status field data and compare received +# comp data with correspending bytes in local comp data. +# 6. Client merges the two samples and checks that the collected data is +# correctly merged, continuous, and matches its local comp data. +conf=prj_mesh1d1_conf +overlay=overlay_pst_conf +RunTest mesh_lcd_test_comp130_data_split_dfu \ + lcd_srv_comp_data_status_respond \ + lcd_cli_split_comp_data_request -- -argstest page=130 comp-changed-mode=1 + +conf=prj_mesh1d1_conf +overlay="overlay_pst_conf_overlay_psa_conf" +RunTest mesh_lcd_test_comp130_data_split_dfu \ + lcd_srv_comp_data_status_respond \ + lcd_cli_split_comp_data_request -- -argstest page=130 comp-changed-mode=1 diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp1_data_split.sh b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp1_data_split.sh new file mode 100755 index 00000000000..bc24a9c9bf9 --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp1_data_split.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test that the LCD server model is able to split the +# composition data when the total size exceeds the maximum access message size. +# +# Test procedure: +# 0. Provisioning and setup. Server and client has same comp data. +# 1. Client requests a sample exceeding the maximum avaialble payload from the +# server's composition data. +# 2. Client fetch its local comp data. +# 3. When server status arrive, remove status field data and compare received +# comp data with corresponding bytes in local comp data. +# 4. Client requests the next sample from server's composition data. +# 5. When server status arrive, remove status field data and compare received +# comp data with correspending bytes in local comp data. +# 6. Client merges the two samples and checks that the collected data is +# correctly merged, continuous, and matches its local comp data. +conf=prj_mesh1d1_conf +overlay=overlay_pst_conf +RunTest mesh_lcd_test_comp1_data_split \ + lcd_srv_comp_data_status_respond lcd_cli_split_comp_data_request -- -argstest page=1 + +conf=prj_mesh1d1_conf +overlay="overlay_pst_conf_overlay_psa_conf" +RunTest mesh_lcd_test_comp1_data_split \ + lcd_srv_comp_data_status_respond lcd_cli_split_comp_data_request -- -argstest page=1 diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp1_data_split_dfu.sh b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp1_data_split_dfu.sh new file mode 100755 index 00000000000..59383bb18f1 --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp1_data_split_dfu.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test that the LCD server model is able to split the +# composition data when the total size exceeds the maximum access message size. +# The test environment simulates a scenario where the server has completed DFU. +# +# Test procedure: +# 0. Provisioning and setup. Server and client has same comp data. +# 1. Client requests a sample exceeding the maximum avaialble payload from the +# server's composition data. +# 2. Client fetch its local comp data. +# 3. When server status arrive, remove status field data and compare received +# comp data with corresponding bytes in local comp data. +# 4. Client requests the next sample from server's composition data. +# 5. When server status arrive, remove status field data and compare received +# comp data with correspending bytes in local comp data. +# 6. Client merges the two samples and checks that the collected data is +# correctly merged, continuous, and matches its local comp data. +conf=prj_mesh1d1_conf +overlay=overlay_pst_conf +RunTest mesh_lcd_test_comp1_data_split_dfu \ + lcd_srv_comp_data_status_respond \ + lcd_cli_split_comp_data_request -- -argstest page=1 comp-changed-mode=1 + +conf=prj_mesh1d1_conf +overlay="overlay_pst_conf_overlay_psa_conf" +RunTest mesh_lcd_test_comp1_data_split_dfu \ + lcd_srv_comp_data_status_respond \ + lcd_cli_split_comp_data_request -- -argstest page=1 comp-changed-mode=1 diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp2_data_split.sh b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp2_data_split.sh new file mode 100755 index 00000000000..53def43d5a0 --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp2_data_split.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test that the LCD server model is able to split the +# composition data when the total size exceeds the maximum access message size. +# +# Test procedure: +# 0. Provisioning and setup. Server and client has same comp data. +# 1. Client requests a sample exceeding the maximum avaialble payload from the +# server's composition data. +# 2. Client fetch its local comp data. +# 3. When server status arrive, remove status field data and compare received +# comp data with corresponding bytes in local comp data. +# 4. Client requests the next sample from server's composition data. +# 5. When server status arrive, remove status field data and compare received +# comp data with correspending bytes in local comp data. +# 6. Client merges the two samples and checks that the collected data is +# correctly merged, continuous, and matches its local comp data. +conf=prj_mesh1d1_conf +overlay=overlay_pst_conf +RunTest mesh_lcd_test_comp2_data_split \ + lcd_srv_comp_data_status_respond lcd_cli_split_comp_data_request -- -argstest page=2 + +conf=prj_mesh1d1_conf +overlay="overlay_pst_conf_overlay_psa_conf" +RunTest mesh_lcd_test_comp2_data_split \ + lcd_srv_comp_data_status_respond lcd_cli_split_comp_data_request -- -argstest page=2 diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp2_data_split_dfu.sh b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp2_data_split_dfu.sh new file mode 100755 index 00000000000..f314f00d6ef --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp2_data_split_dfu.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test that the LCD server model is able to split the +# composition data when the total size exceeds the maximum access message size. +# The test environment simulates a scenario where the server has completed DFU. +# +# Test procedure: +# 0. Provisioning and setup. Server and client has same comp data. +# 1. Client requests a sample exceeding the maximum avaialble payload from the +# server's composition data. +# 2. Client fetch its local comp data. +# 3. When server status arrive, remove status field data and compare received +# comp data with corresponding bytes in local comp data. +# 4. Client requests the next sample from server's composition data. +# 5. When server status arrive, remove status field data and compare received +# comp data with correspending bytes in local comp data. +# 6. Client merges the two samples and checks that the collected data is +# correctly merged, continuous, and matches its local comp data. +conf=prj_mesh1d1_conf +overlay=overlay_pst_conf +RunTest mesh_lcd_test_comp2_data_split_dfu \ + lcd_srv_comp_data_status_respond \ + lcd_cli_split_comp_data_request -- -argstest page=2 comp-changed-mode=1 + +conf=prj_mesh1d1_conf +overlay="overlay_pst_conf_overlay_psa_conf" +RunTest mesh_lcd_test_comp2_data_split_dfu \ + lcd_srv_comp_data_status_respond \ + lcd_cli_split_comp_data_request -- -argstest page=2 comp-changed-mode=1 diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp_data_max_sdu.sh b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp_data_max_sdu.sh index 99f05637653..b050037ccf0 100755 --- a/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp_data_max_sdu.sh +++ b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp_data_max_sdu.sh @@ -15,10 +15,11 @@ source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh # comp data with local comp data and assure that the received message length # is 378 bytes (380 bytes access payload). conf=prj_mesh1d1_conf +overlay=overlay_pst_conf RunTest mesh_lcd_test_max_access_payload \ lcd_cli_max_sdu_comp_data_request lcd_srv_comp_data_status_respond conf=prj_mesh1d1_conf -overlay=overlay_psa_conf +overlay="overlay_pst_conf_overlay_psa_conf" RunTest mesh_lcd_test_max_access_payload_psa \ lcd_cli_max_sdu_comp_data_request lcd_srv_comp_data_status_respond diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp_data_split.sh b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp_data_split.sh deleted file mode 100755 index 45d2c103246..00000000000 --- a/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_comp_data_split.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash -# Copyright 2023 Nordic Semiconductor -# SPDX-License-Identifier: Apache-2.0 - -source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh - -# Test that the LCD server model is able to split the -# composition data when the total size exceeds the maximum access message size. -# -# Test procedure: -# 0. Provisioning and setup. Server and client has same comp data. -# 1. Client requests a sample exceeding the maximum avaialble payload from the -# server's composition data. -# 2. Client fetch its local comp data. -# 3. When server status arrive, remove status field data and compare received -# comp data with corresponding bytes in local comp data. -# 4. Client requests the next sample from server's composition data. -# 5. When server status arrive, remove status field data and compare received -# comp data with correspending bytes in local comp data. -# 6. Client merges the two samples and checks that the collected data is -# correctly merged, continuous, and matches its local comp data. -conf=prj_mesh1d1_conf -RunTest mesh_lcd_test_split_comp_data \ - lcd_cli_split_comp_data_request lcd_srv_comp_data_status_respond - -conf=prj_mesh1d1_conf -overlay=overlay_psa_conf -RunTest mesh_lcd_test_split_comp_data_psa \ - lcd_cli_split_comp_data_request lcd_srv_comp_data_status_respond diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_metadata_max_sdu.sh b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_metadata_max_sdu.sh index 83cc788844f..9b0be5ea20f 100755 --- a/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_metadata_max_sdu.sh +++ b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_metadata_max_sdu.sh @@ -16,10 +16,11 @@ source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh # 4. Remove status field data and compare received metadata with # local metadata data. conf=prj_mesh1d1_conf +overlay=overlay_pst_conf RunTest mesh_lcd_test_max_metadata_access_payload \ lcd_cli_max_sdu_metadata_request lcd_srv_metadata_status_respond conf=prj_mesh1d1_conf -overlay=overlay_psa_conf +overlay="overlay_pst_conf_overlay_psa_conf" RunTest mesh_lcd_test_max_metadata_access_payload_psa \ lcd_cli_max_sdu_metadata_request lcd_srv_metadata_status_respond diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_metadata_split.sh b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_metadata_split.sh index 622b4ce5dba..0e29e7d4219 100755 --- a/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_metadata_split.sh +++ b/tests/bsim/bluetooth/mesh/tests_scripts/large_comp_data/get_metadata_split.sh @@ -19,10 +19,11 @@ source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh # 6. Client merges the two samples and checks that the collected data is # correctly merged, continuous, and matches its local metadata. conf=prj_mesh1d1_conf +overlay=overlay_pst_conf RunTest mesh_lcd_test_split_metadata \ lcd_cli_split_metadata_request lcd_srv_metadata_status_respond conf=prj_mesh1d1_conf -overlay=overlay_psa_conf +overlay="overlay_pst_conf_overlay_psa_conf" RunTest mesh_lcd_test_split_metadata_psa \ lcd_cli_split_metadata_request lcd_srv_metadata_status_respond diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/op_agg/loopback.sh b/tests/bsim/bluetooth/mesh/tests_scripts/op_agg/loopback.sh new file mode 100755 index 00000000000..3a4720bdaf4 --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/op_agg/loopback.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test that an Opcode aggregated message can be sent and received on loopback. +# +# Test procedure: +# 1. The device initializes both Opcode aggregator server and client. +# The device starts an Opcode aggregator sequence and populates the buffer. +# 2. The device starts sending the sequence on loopback. +# 3. The device verifies that the sequence is correctly received by the server model. +# 4. The device confirms that the client model received all status messages. +conf=prj_mesh1d1_conf +RunTest mesh_op_agg_model_coex_loopback \ + op_agg_dut_model_coex_loopback + +conf=prj_mesh1d1_conf +overlay=overlay_psa_conf +RunTest mesh_op_agg_model_coex_loopback \ + op_agg_dut_model_coex_loopback diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/op_agg/model_coex.sh b/tests/bsim/bluetooth/mesh/tests_scripts/op_agg/model_coex.sh new file mode 100755 index 00000000000..08fcdf9f41e --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/op_agg/model_coex.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test that Opcode aggregator server and client can coexist on the same device. +# In this test scenario, the DUT has a sequence in progress on the Opcode +# Aggregator client model that is interrupted by an incoming sequence to the Opcode +# Aggregator server model. The test verifies that both the incoming and outgoing +# sequence on the DUT completes successfully. +# +# Test procedure: +# 1. Both Tester and DUT device initialize both Opcode aggregator server and client. +# Both devices starts an Opcode aggregator sequence and populates the buffer. +# 2. The Tester device immediately starts sending the sequence. +# 3. The DUT device waits, and verifies that the sequence is correctly received. +# Then it starts sending its own aggregated sequence. +# 4. The Tester device confirms that it received all status messages related to its +# own aggregated sequence from the DUT device, then it verifies that the +# aggregated sequence from the DUT device is correctly received. +# 5. Finally, the DUT device waits and confirms that it received all status messages +# related to its own aggregated sequence from the cli device. +conf=prj_mesh1d1_conf +RunTest mesh_op_agg_model_coex \ + op_agg_tester_model_coex op_agg_dut_model_coex + +conf=prj_mesh1d1_conf +overlay=overlay_psa_conf +RunTest mesh_op_agg_model_coex \ + op_agg_tester_model_coex op_agg_dut_model_coex diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/priv_beacon/priv_beacon_cache.sh b/tests/bsim/bluetooth/mesh/tests_scripts/priv_beacon/priv_beacon_cache.sh new file mode 100755 index 00000000000..0cb5cdaea0a --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/priv_beacon/priv_beacon_cache.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test Private Beacon cache +# +# Test procedure: +# 0. RX device starts monitoring all accepted private beacon messages. +# 1. TX device sends two identical private beacons to the RX device. +# 2. TX device sends a secondary private beacons to the RX device, marking the end of the test. +# 3. RX device verifies that only one of the two identical beacons was processed. + +conf=prj_mesh1d1_conf +RunTest mesh_priv_beacon_cache \ + beacon_tx_priv_beacon_cache \ + beacon_rx_priv_beacon_cache + +conf=prj_mesh1d1_conf +overlay=overlay_psa_conf +RunTest mesh_priv_beacon_cache \ + beacon_tx_priv_beacon_cache \ + beacon_rx_priv_beacon_cache diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/priv_beacon/priv_proxy_gatt.sh b/tests/bsim/bluetooth/mesh/tests_scripts/priv_beacon/priv_proxy_gatt.sh new file mode 100755 index 00000000000..a1b9ea7d8d6 --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/priv_beacon/priv_proxy_gatt.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test Private over GATT connection +# +# Test procedure: +# 0. Both TX and RX device disables SNB and GATT proxy, and enables +# Private GATT proxy. Test mode for IV update is also enabled on both devices. +# 1. The RX device (Proxy CLI) establish a GATT connection to the TX device +# (Proxy SRV), using Private Network Identity. +# 2. Both TX and RX device disables the scanner to prevent interferance +# by the adv bearer. +# 3. The TX device (Proxy SRV) starts an IV update procedure. +# 4. Both TX and RX device verifies that the IV index has been updated. +# This proves that the RX device (Proxy CLI) successfully received +# a Private beacon over the GATT connection +conf=prj_mesh1d1_conf +overlay=overlay_gatt_conf +RunTest mesh_priv_proxy_gatt_priv_beacon \ + beacon_tx_priv_gatt_proxy \ + beacon_rx_priv_gatt_proxy + +conf=prj_mesh1d1_conf +overlay=overlay_gatt_conf_overlay_psa_conf +RunTest mesh_priv_proxy_gatt_priv_beacon \ + beacon_tx_priv_gatt_proxy \ + beacon_rx_priv_gatt_proxy diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/priv_beacon/priv_proxy_net_id.sh b/tests/bsim/bluetooth/mesh/tests_scripts/priv_beacon/priv_proxy_net_id.sh new file mode 100755 index 00000000000..02fcf03c001 --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/priv_beacon/priv_proxy_net_id.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test Private Net ID advertisment +# +# Test procedure: +# 0. TX device disables GATT proxy and enables Private GATT proxy. +# 1. RX device enables scanner and scans for Net ID advertisments. +# 2. RX device scans for a single Net ID advertisment and stores +# the random field of that message. +# 3. RX device waits for 10 minutes. +# 4. RX device scans for a another Private Net ID advertisement and compares +# the random field of that message with the random field +# of the previous Private Net ID. +# 5. Test passes if the random field of the two Private Net ID advertisements +# are NOT equal. + +conf=prj_mesh1d1_conf +overlay=overlay_gatt_conf +RunTest mesh_priv_proxy_net_id \ + beacon_tx_priv_net_id \ + beacon_rx_priv_net_id + +conf=prj_mesh1d1_conf +overlay=overlay_gatt_conf_overlay_psa_conf +RunTest mesh_priv_proxy_net_id \ + beacon_tx_priv_net_id \ + beacon_rx_priv_net_id diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/priv_beacon/priv_proxy_net_id_multi.sh b/tests/bsim/bluetooth/mesh/tests_scripts/priv_beacon/priv_proxy_net_id_multi.sh new file mode 100755 index 00000000000..9d89b5af36c --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/priv_beacon/priv_proxy_net_id_multi.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test Private Net ID advertisment with multiple networks +# +# Test procedure: +# 0. TX device disables GATT proxy, adds a second network to the device +# and enables Private GATT proxy. +# 1. RX device enables scanner and scans for Private Net ID advertisements from +# both of the networks. +# 2. Test passes when RX device verifies reception of one Private Net ID +# advertisemen from each of the networks within the given time +# limit. + +conf=prj_mesh1d1_conf +overlay=overlay_gatt_conf +RunTest mesh_priv_proxy_net_id_multi \ + beacon_tx_priv_multi_net_id \ + beacon_rx_priv_multi_net_id + +conf=prj_mesh1d1_conf +overlay=overlay_gatt_conf_overlay_psa_conf +RunTest mesh_priv_proxy_net_id_multi \ + beacon_tx_priv_multi_net_id \ + beacon_rx_priv_multi_net_id diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/priv_beacon/priv_proxy_node_id.sh b/tests/bsim/bluetooth/mesh/tests_scripts/priv_beacon/priv_proxy_node_id.sh new file mode 100755 index 00000000000..2aff351bd78 --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/priv_beacon/priv_proxy_node_id.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test Private Node ID advertisment +# +# Test procedure: +# 0. TX device disables GATT proxy and enables the Private Node +# Identity state for the network. Then it waits for the +# advertisment to complete. +# 1. RX device enables scanner and scans for Private Node ID advertisements. +# 2. RX device scans for a single Private Node ID advertisement and stores +# the random field of that message. Then it waits for the +# advertisement to complete. +# 3. TC device verifies that the previous advertisement is finished +# and enables the Private Node Identity state for the network +# again. +# 4. RX device scans for a another Private Node ID advertisement and compares +# the random field of that message with the random field +# of the previous Net ID. +# 5. Test passes if the random field of the two Private Node ID advertisements +# are NOT equal. + +conf=prj_mesh1d1_conf +overlay=overlay_gatt_conf +RunTest mesh_priv_proxy_node_id \ + beacon_tx_priv_node_id \ + beacon_rx_priv_node_id + +conf=prj_mesh1d1_conf +overlay=overlay_gatt_conf_overlay_psa_conf +RunTest mesh_priv_proxy_node_id \ + beacon_tx_priv_node_id \ + beacon_rx_priv_node_id diff --git a/tests/bsim/bluetooth/tests.nrf52bsim.txt b/tests/bsim/bluetooth/tests.nrf52bsim.txt new file mode 100644 index 00000000000..9b76be4ec75 --- /dev/null +++ b/tests/bsim/bluetooth/tests.nrf52bsim.txt @@ -0,0 +1,3 @@ +# Search paths(s) for tests which will be run in the nrf52bsim +# This file is used in CI to select which tests are run +tests/bsim/bluetooth/ diff --git a/tests/bsim/bluetooth/tests.nrf5340bsim_nrf5340_cpuapp.txt b/tests/bsim/bluetooth/tests.nrf5340bsim_nrf5340_cpuapp.txt new file mode 100644 index 00000000000..27a1fc4a76f --- /dev/null +++ b/tests/bsim/bluetooth/tests.nrf5340bsim_nrf5340_cpuapp.txt @@ -0,0 +1,5 @@ +# Search paths(s) for tests which will be run in the nrf5340 split stack configuration +# This file is used in CI to select which tests are run +tests/bsim/bluetooth/ll/conn/tests_scripts/basic_conn_encrypted_split_privacy.sh +tests/bsim/bluetooth/ll/bis/tests_scripts/broadcast_iso.sh +tests/bsim/bluetooth/audio_samples/ diff --git a/tests/bsim/bluetooth/tests.nrf5340bsim_nrf5340_cpunet.txt b/tests/bsim/bluetooth/tests.nrf5340bsim_nrf5340_cpunet.txt new file mode 100644 index 00000000000..1d9d73630db --- /dev/null +++ b/tests/bsim/bluetooth/tests.nrf5340bsim_nrf5340_cpunet.txt @@ -0,0 +1,4 @@ +# Search paths(s) for tests which will be run in the nrf5340 net core (both app, host and controller +# built in the net core) +# This file is used in CI to select which tests are run +tests/bsim/bluetooth/ll/ diff --git a/tests/bsim/compile.source b/tests/bsim/compile.source index 603585d15eb..5cababeaefa 100644 --- a/tests/bsim/compile.source +++ b/tests/bsim/compile.source @@ -13,6 +13,7 @@ function _compile(){ : "${app:?app must be defined}" local app_root="${app_root:-${ZEPHYR_BASE}}" + local BOARD_ROOT="${BOARD_ROOT:-${ZEPHYR_BASE}}" local conf_file="${conf_file:-prj.conf}" local conf_overlay="${conf_overlay:-""}" @@ -46,7 +47,12 @@ function _compile(){ fi local cmake_cmd+=( -DOVERLAY_CONFIG="${conf_overlay}" \ ${modules_arg} \ - ${cmake_args} -DCMAKE_C_FLAGS=\"${cc_flags}\" ${app_root}/${app}) + ${cmake_args} -DCMAKE_C_FLAGS=\"${cc_flags}\") + if [ -v sysbuild ]; then + local cmake_cmd+=( -DAPP_DIR=${app_root}/${app} ${ZEPHYR_BASE}/share/sysbuild/) + else + local cmake_cmd+=( ${app_root}/${app}) + fi # Set INCR_BUILD when calling to only do an incremental build if [ ! -v INCR_BUILD ] || [ ! -d "${this_dir}" ]; then diff --git a/tests/bsim/net/sockets/echo_test/overlay-ot.conf b/tests/bsim/net/sockets/echo_test/overlay-ot.conf index 83ead1cf289..fb74b5f12d2 100644 --- a/tests/bsim/net/sockets/echo_test/overlay-ot.conf +++ b/tests/bsim/net/sockets/echo_test/overlay-ot.conf @@ -1,6 +1,6 @@ # This file content is just a copy of the echo client overlay-ot.conf -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y # Disable TCP and IPv4 (TCP disabled to avoid heavy traffic) CONFIG_NET_TCP=n diff --git a/tests/bsim/run_parallel.sh b/tests/bsim/run_parallel.sh index 395dc7f6084..80e74512ef3 100755 --- a/tests/bsim/run_parallel.sh +++ b/tests/bsim/run_parallel.sh @@ -13,8 +13,8 @@ function display_help(){ echo " Testcases are searched for in \${SEARCH_PATH}," echo " which by default is the folder the script is run from" echo " You can instead also provide a space separated test list with \${TESTS_LIST}, " - echo " or an input file including a list of tests \${TESTS_FILE} (w one line" - echo " per test, you can comment lines with #)" + echo " or an input file including a list of tests and/or tests search paths" + echo " \${TESTS_FILE} (w one line per test/path, you can comment lines with #)" echo "" echo " Examples (run from \${ZEPHYR_BASE}):" echo " * Run all tests found under one folder:" @@ -44,13 +44,15 @@ i=0 if [ -n "${TESTS_FILE}" ]; then #remove comments and empty lines from file - all_cases=$(sed 's/#.*$//;/^$/d' "${TESTS_FILE}") + search_pattern=$(sed 's/#.*$//;/^$/d' "${TESTS_FILE}") || exit 1 + all_cases=`find ${search_pattern} -name "*.sh" | \ + grep -Ev "(/_|run_parallel|compile|generate_coverage_report.sh)"` elif [ -n "${TESTS_LIST}" ]; then all_cases=${TESTS_LIST} else SEARCH_PATH="${SEARCH_PATH:-.}" all_cases=`find ${SEARCH_PATH} -name "*.sh" | \ - grep -Ev "(/_|run_parallel|compile.sh|generate_coverage_report.sh)"` + grep -Ev "(/_|run_parallel|compile|generate_coverage_report.sh)"` #we dont run ourselves fi diff --git a/tests/bsim/sh_common.source b/tests/bsim/sh_common.source index 05c29c79070..ddcce6df818 100644 --- a/tests/bsim/sh_common.source +++ b/tests/bsim/sh_common.source @@ -43,5 +43,5 @@ function Execute() { EXECUTE_TIMEOUT="${EXECUTE_TIMEOUT:-30}" check_program_exists $1 - run_in_background timeout -v ${EXECUTE_TIMEOUT} $@ + run_in_background timeout --kill-after=5 -v ${EXECUTE_TIMEOUT} $@ } diff --git a/tests/cmake/config_dir/testcase.yaml b/tests/cmake/config_dir/testcase.yaml index 86bbfd786d8..16105025664 100644 --- a/tests/cmake/config_dir/testcase.yaml +++ b/tests/cmake/config_dir/testcase.yaml @@ -1,5 +1,5 @@ tests: - cmake.config_dir.user_defined: + buildsystem.config_dir.user_defined: platform_allow: native_posix build_only: true extra_args: APPLICATION_CONFIG_DIR:PATH=foo diff --git a/tests/cmake/overlays/var_expansions/prj.conf b/tests/cmake/overlays/var_expansions/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/cmake/overlays/var_expansions/prj.conf +++ b/tests/cmake/overlays/var_expansions/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/cmake/overlays/var_expansions/testcase.yaml b/tests/cmake/overlays/var_expansions/testcase.yaml index 9aff9128526..1149a7f7c28 100644 --- a/tests/cmake/overlays/var_expansions/testcase.yaml +++ b/tests/cmake/overlays/var_expansions/testcase.yaml @@ -3,16 +3,16 @@ common: build_only: true platform_allow: native_posix tests: - cmake.overlays.var_expansions.CONF_FILE: + buildsystem.overlays.var_expansions.CONF_FILE: extra_conf_files: - ${ZEPHYR_MY_MODULE_NAME_MODULE_DIR}/zephyr/my_module-overlay.conf - ${ZEPHYR_MY_EXTRA_MODULE_NAME_MODULE_DIR}/zephyr/my_extra_module-overlay.conf - prj.conf - cmake.overlays.var_expansions.OVERLAY_CONFIG: + buildsystem.overlays.var_expansions.OVERLAY_CONFIG: extra_overlay_confs: - ${ZEPHYR_MY_MODULE_NAME_MODULE_DIR}/zephyr/my_module-overlay.conf - ${ZEPHYR_MY_EXTRA_MODULE_NAME_MODULE_DIR}/zephyr/my_extra_module-overlay.conf - cmake.overlays.var_expansions.DTC_OVERLAY_FILE: + buildsystem.overlays.var_expansions.DTC_OVERLAY_FILE: extra_dtc_overlay_files: - ${ZEPHYR_MY_MODULE_NAME_MODULE_DIR}/zephyr/my_module-board.overlay - ${ZEPHYR_MY_EXTRA_MODULE_NAME_MODULE_DIR}/zephyr/my_extra_module-board.overlay diff --git a/tests/cmake/snippets/prj.conf b/tests/cmake/snippets/prj.conf index 32b9aa38ccc..4eb46139fd2 100644 --- a/tests/cmake/snippets/prj.conf +++ b/tests/cmake/snippets/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_FOO_VAL=774392 CONFIG_TEST_BAR_VAL=182834 CONFIG_TEST_COMMON_VAL=588411 diff --git a/tests/cmake/snippets/testcase.yaml b/tests/cmake/snippets/testcase.yaml index 08eaee0fc16..c8dad26a94f 100644 --- a/tests/cmake/snippets/testcase.yaml +++ b/tests/cmake/snippets/testcase.yaml @@ -10,26 +10,26 @@ common: tests: # Test the initial state with no snippets applied - cmake.snippets.none: + buildsystem.snippets.none: extra_configs: - CONFIG_TEST_TYPE_NONE=y # Test the `foo` snippet from the default application snippet root - cmake.snippets.foo: + buildsystem.snippets.foo: extra_args: SNIPPET="foo" extra_configs: - CONFIG_TEST_TYPE_FOO=y # Test the `bar` snippet from an extra snippet root - cmake.snippets.bar: + buildsystem.snippets.bar: extra_args: SNIPPET="bar" extra_configs: - CONFIG_TEST_TYPE_BAR=y # Test the snippet processing order (1. foo, 2. bar) - cmake.snippets.foo_bar: + buildsystem.snippets.foo_bar: extra_args: SNIPPET="foo;bar" extra_configs: - CONFIG_TEST_TYPE_FOO_BAR=y # Test the snippet processing order (1. bar, 2. foo) - cmake.snippets.bar_foo: + buildsystem.snippets.bar_foo: extra_args: SNIPPET="bar;foo" extra_configs: - CONFIG_TEST_TYPE_BAR_FOO=y diff --git a/tests/cmake/zephyr_get/testcase.yaml b/tests/cmake/zephyr_get/testcase.yaml index 901b9200798..5159efb093c 100644 --- a/tests/cmake/zephyr_get/testcase.yaml +++ b/tests/cmake/zephyr_get/testcase.yaml @@ -3,9 +3,9 @@ common: build_only: true platform_allow: native_posix tests: - zephyr_get.no_sysbuild: + buildsystem.extensions.zephyr_get.no_sysbuild: sysbuild: false - zephyr_get.sysbuild: + buildsystem.extensions.zephyr_get.sysbuild: sysbuild: true extra_args: TESTCASE_VARIABLE="sysbuild.main" zephyr_get_2nd_TESTCASE_VARIABLE="sysbuild.2nd" diff --git a/tests/crypto/crypto_hash/prj.conf b/tests/crypto/crypto_hash/prj.conf index 0b8d6e2aa48..5aba0ef5c39 100644 --- a/tests/crypto/crypto_hash/prj.conf +++ b/tests/crypto/crypto_hash/prj.conf @@ -1,6 +1,5 @@ CONFIG_ZTEST_STACK_SIZE=4096 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MBEDTLS=y CONFIG_MBEDTLS_BUILTIN=y diff --git a/tests/crypto/mbedtls/prj.conf b/tests/crypto/mbedtls/prj.conf index 7532e84b251..9b6af503e03 100644 --- a/tests/crypto/mbedtls/prj.conf +++ b/tests/crypto/mbedtls/prj.conf @@ -3,7 +3,6 @@ CONFIG_MBEDTLS=y CONFIG_MBEDTLS_BUILTIN=y CONFIG_MBEDTLS_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y CONFIG_MINIMAL_LIBC_NON_REENTRANT_FUNCTIONS=y CONFIG_MINIMAL_LIBC_RAND=y diff --git a/tests/crypto/rand32/prj.conf b/tests/crypto/rand32/prj.conf index 78b88c04317..420e89ab17f 100644 --- a/tests/crypto/rand32/prj.conf +++ b/tests/crypto/rand32/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_LOG=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/crypto/rand32/prj_ctr_drbg.conf b/tests/crypto/rand32/prj_ctr_drbg.conf index e5848839734..996a530cd41 100644 --- a/tests/crypto/rand32/prj_ctr_drbg.conf +++ b/tests/crypto/rand32/prj_ctr_drbg.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_LOG=y CONFIG_ENTROPY_GENERATOR=y diff --git a/tests/crypto/rand32/prj_hw_random_psa_crypto.conf b/tests/crypto/rand32/prj_hw_random_psa_crypto.conf index 91638df0cf3..4c6c2180c46 100644 --- a/tests/crypto/rand32/prj_hw_random_psa_crypto.conf +++ b/tests/crypto/rand32/prj_hw_random_psa_crypto.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_LOG=y CONFIG_ENTROPY_GENERATOR=y CONFIG_HARDWARE_DEVICE_CS_GENERATOR=y diff --git a/tests/crypto/rand32/prj_hw_random_xoshiro.conf b/tests/crypto/rand32/prj_hw_random_xoshiro.conf index 97b69d65f39..aaabc2e41c9 100644 --- a/tests/crypto/rand32/prj_hw_random_xoshiro.conf +++ b/tests/crypto/rand32/prj_hw_random_xoshiro.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_LOG=y CONFIG_ENTROPY_GENERATOR=y CONFIG_XOSHIRO_RANDOM_GENERATOR=y diff --git a/tests/crypto/rand32/prj_sw_random_systimer.conf b/tests/crypto/rand32/prj_sw_random_systimer.conf index 2adbee9e418..6a6c996b86b 100644 --- a/tests/crypto/rand32/prj_sw_random_systimer.conf +++ b/tests/crypto/rand32/prj_sw_random_systimer.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_LOG=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/crypto/rand32/src/main.c b/tests/crypto/rand32/src/main.c index 7b5a06083f1..1f2492e69e3 100644 --- a/tests/crypto/rand32/src/main.c +++ b/tests/crypto/rand32/src/main.c @@ -8,14 +8,14 @@ /* * This tests the following random number routines: - * void z_early_boot_rand_get(uint8_t *buf, size_t length) + * void z_early_rand_get(uint8_t *buf, size_t length) * uint32_t sys_rand32_get(void); */ #include #include -#include +#include #define N_VALUES 10 @@ -35,11 +35,11 @@ ZTEST(rand32_common, test_rand32) /* Test early boot random number generation function */ /* Cover the case, where argument "length" is < size of "size_t" */ - z_early_boot_rand_get((uint8_t *)&tmp, (size_t)1); - z_early_boot_rand_get((uint8_t *)&last_gen, sizeof(last_gen)); - z_early_boot_rand_get((uint8_t *)&gen, sizeof(gen)); + z_early_rand_get((uint8_t *)&tmp, (size_t)1); + z_early_rand_get((uint8_t *)&last_gen, sizeof(last_gen)); + z_early_rand_get((uint8_t *)&gen, sizeof(gen)); zassert_true(last_gen != gen && last_gen != tmp && tmp != gen, - "z_early_boot_rand_get failed"); + "z_early_rand_get failed"); /* * Test subsequently calls sys_rand32_get(), checking @@ -85,7 +85,7 @@ ZTEST(rand32_common, test_rand32) "random numbers returned same value with high probability"); } -#if defined(CONFIG_CSPRING_ENABLED) +#if defined(CONFIG_CSPRNG_ENABLED) printk("Generating bulk fill cryptographically secure random numbers\n"); @@ -109,7 +109,7 @@ ZTEST(rand32_common, test_rand32) printk("Cryptographically secure random number APIs not enabled\n"); -#endif /* CONFIG_CSPRING_ENABLED */ +#endif /* CONFIG_CSPRNG_ENABLED */ } ZTEST_SUITE(rand32_common, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/crypto/tinycrypt/prj.conf b/tests/crypto/tinycrypt/prj.conf index 8869f167ef3..4cb73548b4f 100644 --- a/tests/crypto/tinycrypt/prj.conf +++ b/tests/crypto/tinycrypt/prj.conf @@ -13,4 +13,3 @@ CONFIG_TINYCRYPT_ECC_DH=y CONFIG_TINYCRYPT_ECC_DSA=y CONFIG_ZTEST_STACK_SIZE=5120 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/crypto/tinycrypt/src/ecc_dsa.c b/tests/crypto/tinycrypt/src/ecc_dsa.c index 96bf71fda83..f62f63c77dc 100644 --- a/tests/crypto/tinycrypt/src/ecc_dsa.c +++ b/tests/crypto/tinycrypt/src/ecc_dsa.c @@ -67,7 +67,7 @@ #include #include "test_ecc_utils.h" #include -#include +#include #include #include diff --git a/tests/crypto/tinycrypt_hmac_prng/prj.conf b/tests/crypto/tinycrypt_hmac_prng/prj.conf index 718b2bb5dc2..8e3d3dbd042 100644 --- a/tests/crypto/tinycrypt_hmac_prng/prj.conf +++ b/tests/crypto/tinycrypt_hmac_prng/prj.conf @@ -4,4 +4,3 @@ CONFIG_TINYCRYPT_SHA256=y CONFIG_TINYCRYPT_SHA256_HMAC=y CONFIG_TINYCRYPT_SHA256_HMAC_PRNG=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/adc/adc_api/boards/b_u585i_iot02a.overlay b/tests/drivers/adc/adc_api/boards/b_u585i_iot02a.overlay index 52f641d34e5..90377971a58 100644 --- a/tests/drivers/adc/adc_api/boards/b_u585i_iot02a.overlay +++ b/tests/drivers/adc/adc_api/boards/b_u585i_iot02a.overlay @@ -7,11 +7,12 @@ / { zephyr,user { /* adjust channel number according to pinmux in board.dts */ - io-channels = <&adc1 15>; + io-channels = <&adc1 15>, <&adc1 16>; }; }; &adc1 { + pinctrl-0 = <&adc1_in15_pb0 &adc1_in16_pb1>; #address-cells = <1>; #size-cells = <0>; @@ -19,7 +20,19 @@ reg = <15>; zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; + zephyr,acquisition-time = ; zephyr,resolution = <12>; }; + + channel@10 { + reg = <16>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; + +&adc4 { + status = "disabled"; }; diff --git a/tests/drivers/adc/adc_api/boards/b_u585i_iot02a_adc4.overlay b/tests/drivers/adc/adc_api/boards/b_u585i_iot02a_adc4.overlay new file mode 100644 index 00000000000..3020a0c5997 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/b_u585i_iot02a_adc4.overlay @@ -0,0 +1,38 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 STMicroelectronics + */ + +/ { + zephyr,user { + /* adjust channel number according to pinmux in board.dts */ + io-channels = <&adc4 18>, <&adc4 19>; + }; +}; + +&adc4 { + pinctrl-0 = <&adc4_in18_pb0 &adc4_in19_pb1>; + #address-cells = <1>; + #size-cells = <0>; + + channel@12 { + reg = <18>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@13 { + reg = <19>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; + +&adc1 { + status = "disabled"; +}; diff --git a/tests/drivers/adc/adc_api/boards/cy8cproto_063_ble.overlay b/tests/drivers/adc/adc_api/boards/cy8cproto_063_ble.overlay index 4863af8b2c8..b8f7b78001e 100644 --- a/tests/drivers/adc/adc_api/boards/cy8cproto_063_ble.overlay +++ b/tests/drivers/adc/adc_api/boards/cy8cproto_063_ble.overlay @@ -24,7 +24,7 @@ zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; zephyr,resolution = <12>; - zephyr,input-positive = <0>; /* P10.0 */ + zephyr,input-positive = <2>; /* P10.2 */ }; channel@1 { @@ -33,6 +33,6 @@ zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; zephyr,resolution = <12>; - zephyr,input-positive = <1>; /* P10.1 */ + zephyr,input-positive = <3>; /* P10.3 */ }; }; diff --git a/tests/drivers/adc/adc_api/boards/disco_l475_iot1.overlay b/tests/drivers/adc/adc_api/boards/disco_l475_iot1.overlay index 9f35165ef87..42d8f177261 100644 --- a/tests/drivers/adc/adc_api/boards/disco_l475_iot1.overlay +++ b/tests/drivers/adc/adc_api/boards/disco_l475_iot1.overlay @@ -7,7 +7,7 @@ / { zephyr,user { /* adjust channel number according to pinmux in board.dts */ - io-channels = <&adc1 5>; + io-channels = <&adc1 4>, <&adc1 5>; }; }; @@ -15,11 +15,19 @@ #address-cells = <1>; #size-cells = <0>; + channel@4 { + reg = <4>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + channel@5 { reg = <5>; zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; - zephyr,resolution = <10>; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; }; }; diff --git a/tests/drivers/adc/adc_api/boards/esp32c3_luatos_core.conf b/tests/drivers/adc/adc_api/boards/esp32c3_luatos_core.conf new file mode 100644 index 00000000000..b6c5c80f924 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/esp32c3_luatos_core.conf @@ -0,0 +1 @@ +CONFIG_ADC_ASYNC=n diff --git a/tests/drivers/adc/adc_api/boards/esp32c3_luatos_core.overlay b/tests/drivers/adc/adc_api/boards/esp32c3_luatos_core.overlay new file mode 100644 index 00000000000..c288312aa3a --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/esp32c3_luatos_core.overlay @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022 Wolter HV + * Copyright (c) 2023 Benjamin Björnsson + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + zephyr,user { + /* adjust channel number according to pinmux in board.dts */ + io-channels = <&adc0 0>, <&adc0 1>; + }; +}; + +&adc0 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; diff --git a/tests/drivers/adc/adc_api/boards/esp32c3_luatos_core_usb.conf b/tests/drivers/adc/adc_api/boards/esp32c3_luatos_core_usb.conf new file mode 100644 index 00000000000..b6c5c80f924 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/esp32c3_luatos_core_usb.conf @@ -0,0 +1 @@ +CONFIG_ADC_ASYNC=n diff --git a/tests/drivers/adc/adc_api/boards/esp32c3_luatos_core_usb.overlay b/tests/drivers/adc/adc_api/boards/esp32c3_luatos_core_usb.overlay new file mode 100644 index 00000000000..c288312aa3a --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/esp32c3_luatos_core_usb.overlay @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022 Wolter HV + * Copyright (c) 2023 Benjamin Björnsson + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + zephyr,user { + /* adjust channel number according to pinmux in board.dts */ + io-channels = <&adc0 0>, <&adc0 1>; + }; +}; + +&adc0 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; diff --git a/tests/drivers/adc/adc_api/boards/esp32s3_luatos_core.conf b/tests/drivers/adc/adc_api/boards/esp32s3_luatos_core.conf new file mode 100644 index 00000000000..b6c5c80f924 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/esp32s3_luatos_core.conf @@ -0,0 +1 @@ +CONFIG_ADC_ASYNC=n diff --git a/tests/drivers/adc/adc_api/boards/esp32s3_luatos_core.overlay b/tests/drivers/adc/adc_api/boards/esp32s3_luatos_core.overlay new file mode 100644 index 00000000000..76683e1e993 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/esp32s3_luatos_core.overlay @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022 Wolter HV + * + * SPDX-License-Identifier: Apache-2.0 + */ + + / { + zephyr,user { + io-channels = <&adc0 9>, <&adc1 0>; + }; + }; + + &adc0 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + channel@9 { + reg = <9>; + zephyr,gain = "ADC_GAIN_1_4"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + }; + + &adc1 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1_4"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + }; diff --git a/tests/drivers/adc/adc_api/boards/esp32s3_luatos_core_usb.conf b/tests/drivers/adc/adc_api/boards/esp32s3_luatos_core_usb.conf new file mode 100644 index 00000000000..b6c5c80f924 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/esp32s3_luatos_core_usb.conf @@ -0,0 +1 @@ +CONFIG_ADC_ASYNC=n diff --git a/tests/drivers/adc/adc_api/boards/esp32s3_luatos_core_usb.overlay b/tests/drivers/adc/adc_api/boards/esp32s3_luatos_core_usb.overlay new file mode 100644 index 00000000000..76683e1e993 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/esp32s3_luatos_core_usb.overlay @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022 Wolter HV + * + * SPDX-License-Identifier: Apache-2.0 + */ + + / { + zephyr,user { + io-channels = <&adc0 9>, <&adc1 0>; + }; + }; + + &adc0 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + channel@9 { + reg = <9>; + zephyr,gain = "ADC_GAIN_1_4"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + }; + + &adc1 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1_4"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + }; diff --git a/tests/drivers/adc/adc_api/boards/lpcxpresso55s69_cpu0.overlay b/tests/drivers/adc/adc_api/boards/lpcxpresso55s69_cpu0.overlay index efddec22a21..386e405b7bb 100644 --- a/tests/drivers/adc/adc_api/boards/lpcxpresso55s69_cpu0.overlay +++ b/tests/drivers/adc/adc_api/boards/lpcxpresso55s69_cpu0.overlay @@ -8,7 +8,7 @@ / { zephyr,user { - io-channels = <&adc0 0>, <&adc0 1>; + io-channels = <&adc0 0>, <&adc0 1>, <&adc0 2>; }; }; @@ -16,21 +16,45 @@ #address-cells = <1>; #size-cells = <0>; + /* + * Channel 0 is used in single ended mode, with 12 bit resolution + * CH0A is routed to P19 pin 4 + */ channel@0 { reg = <0>; zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_EXTERNAL0"; + zephyr,vref-mv = <3300>; zephyr,acquisition-time = ; - zephyr,resolution = <12>; - zephyr,input-positive = ; + zephyr,resolution = <13>; + zephyr,input-positive = ; }; + /* + * Channel 1 is used in single ended mode, with 16 bit resolution + * CH4A is routed to P17 pin 19 + */ channel@1 { reg = <1>; zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_EXTERNAL0"; + zephyr,vref-mv = <3300>; + zephyr,acquisition-time = ; + zephyr,resolution = <16>; + zephyr,input-positive = ; + }; + + /* + * Channel 2 is used in single ended mode, with 12 bit resolution + * CH4B is routed to P18 pin 1 + */ + channel@2 { + reg = <2>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_EXTERNAL0"; + zephyr,vref-mv = <3300>; zephyr,acquisition-time = ; zephyr,resolution = <12>; - zephyr,input-positive = ; + zephyr,input-positive = ; }; }; diff --git a/tests/drivers/adc/adc_api/boards/npcx4m8f_evb.overlay b/tests/drivers/adc/adc_api/boards/npcx4m8f_evb.overlay new file mode 100644 index 00000000000..5614d545114 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/npcx4m8f_evb.overlay @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Benjamin Björnsson + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + zephyr,user { + io-channels = <&adc0 0>, <&adc0 2>; + }; +}; + +&adc0 { + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <10>; + }; + + channel@2 { + reg = <2>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <10>; + }; +}; diff --git a/tests/drivers/adc/adc_api/boards/nucleo_f091rc.overlay b/tests/drivers/adc/adc_api/boards/nucleo_f091rc.overlay index f0d65c1e941..d8d89d460a0 100644 --- a/tests/drivers/adc/adc_api/boards/nucleo_f091rc.overlay +++ b/tests/drivers/adc/adc_api/boards/nucleo_f091rc.overlay @@ -7,11 +7,12 @@ / { zephyr,user { /* adjust channel number according to pinmux in board.dts */ - io-channels = <&adc1 0>; + io-channels = <&adc1 0>, <&adc1 1>; }; }; &adc1 { + pinctrl-0 = <&adc_in0_pa0 &adc_in1_pa1>; #address-cells = <1>; #size-cells = <0>; @@ -19,7 +20,15 @@ reg = <0>; zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; zephyr,resolution = <12>; }; }; diff --git a/tests/drivers/adc/adc_api/boards/nucleo_f207zg.overlay b/tests/drivers/adc/adc_api/boards/nucleo_f207zg.overlay index f0d65c1e941..3f87caeb294 100644 --- a/tests/drivers/adc/adc_api/boards/nucleo_f207zg.overlay +++ b/tests/drivers/adc/adc_api/boards/nucleo_f207zg.overlay @@ -7,11 +7,12 @@ / { zephyr,user { /* adjust channel number according to pinmux in board.dts */ - io-channels = <&adc1 0>; + io-channels = <&adc1 0>, <&adc1 3>; }; }; &adc1 { + pinctrl-0 = <&adc1_in0_pa0 &adc1_in3_pa3>; #address-cells = <1>; #size-cells = <0>; @@ -19,7 +20,15 @@ reg = <0>; zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@3 { + reg = <3>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; zephyr,resolution = <12>; }; }; diff --git a/tests/drivers/adc/adc_api/boards/nucleo_f401re.overlay b/tests/drivers/adc/adc_api/boards/nucleo_f401re.overlay index f0d65c1e941..ebb788c73b7 100644 --- a/tests/drivers/adc/adc_api/boards/nucleo_f401re.overlay +++ b/tests/drivers/adc/adc_api/boards/nucleo_f401re.overlay @@ -7,11 +7,12 @@ / { zephyr,user { /* adjust channel number according to pinmux in board.dts */ - io-channels = <&adc1 0>; + io-channels = <&adc1 0>, <&adc1 1>; }; }; &adc1 { + pinctrl-0 = <&adc1_in0_pa0 &adc1_in1_pa1>; #address-cells = <1>; #size-cells = <0>; @@ -19,7 +20,15 @@ reg = <0>; zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@10 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; zephyr,resolution = <12>; }; }; diff --git a/tests/drivers/adc/adc_api/boards/nucleo_f429zi.overlay b/tests/drivers/adc/adc_api/boards/nucleo_f429zi.overlay index f0d65c1e941..3f87caeb294 100644 --- a/tests/drivers/adc/adc_api/boards/nucleo_f429zi.overlay +++ b/tests/drivers/adc/adc_api/boards/nucleo_f429zi.overlay @@ -7,11 +7,12 @@ / { zephyr,user { /* adjust channel number according to pinmux in board.dts */ - io-channels = <&adc1 0>; + io-channels = <&adc1 0>, <&adc1 3>; }; }; &adc1 { + pinctrl-0 = <&adc1_in0_pa0 &adc1_in3_pa3>; #address-cells = <1>; #size-cells = <0>; @@ -19,7 +20,15 @@ reg = <0>; zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@3 { + reg = <3>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; zephyr,resolution = <12>; }; }; diff --git a/tests/drivers/adc/adc_api/boards/nucleo_f746zg.overlay b/tests/drivers/adc/adc_api/boards/nucleo_f746zg.overlay index f0d65c1e941..3f87caeb294 100644 --- a/tests/drivers/adc/adc_api/boards/nucleo_f746zg.overlay +++ b/tests/drivers/adc/adc_api/boards/nucleo_f746zg.overlay @@ -7,11 +7,12 @@ / { zephyr,user { /* adjust channel number according to pinmux in board.dts */ - io-channels = <&adc1 0>; + io-channels = <&adc1 0>, <&adc1 3>; }; }; &adc1 { + pinctrl-0 = <&adc1_in0_pa0 &adc1_in3_pa3>; #address-cells = <1>; #size-cells = <0>; @@ -19,7 +20,15 @@ reg = <0>; zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@3 { + reg = <3>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; zephyr,resolution = <12>; }; }; diff --git a/tests/drivers/adc/adc_api/boards/nucleo_g071rb.overlay b/tests/drivers/adc/adc_api/boards/nucleo_g071rb.overlay index f0d65c1e941..a40478a6ee1 100644 --- a/tests/drivers/adc/adc_api/boards/nucleo_g071rb.overlay +++ b/tests/drivers/adc/adc_api/boards/nucleo_g071rb.overlay @@ -7,7 +7,7 @@ / { zephyr,user { /* adjust channel number according to pinmux in board.dts */ - io-channels = <&adc1 0>; + io-channels = <&adc1 0>, <&adc1 1>; }; }; @@ -19,7 +19,15 @@ reg = <0>; zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; zephyr,resolution = <12>; }; }; diff --git a/tests/drivers/adc/adc_api/boards/nucleo_g474re.overlay b/tests/drivers/adc/adc_api/boards/nucleo_g474re.overlay index 33188a18cf4..7407481014a 100644 --- a/tests/drivers/adc/adc_api/boards/nucleo_g474re.overlay +++ b/tests/drivers/adc/adc_api/boards/nucleo_g474re.overlay @@ -7,11 +7,12 @@ / { zephyr,user { /* adjust channel number according to pinmux in board.dts */ - io-channels = <&adc1 1>; + io-channels = <&adc1 1>, <&adc1 2>; }; }; &adc1 { + pinctrl-0 = <&adc1_in1_pa0 &adc1_in2_pa1>; #address-cells = <1>; #size-cells = <0>; @@ -22,4 +23,12 @@ zephyr,acquisition-time = ; zephyr,resolution = <12>; }; + + channel@2 { + reg = <2>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; }; diff --git a/tests/drivers/adc/adc_api/boards/nucleo_l073rz.overlay b/tests/drivers/adc/adc_api/boards/nucleo_l073rz.overlay index f0d65c1e941..d8d89d460a0 100644 --- a/tests/drivers/adc/adc_api/boards/nucleo_l073rz.overlay +++ b/tests/drivers/adc/adc_api/boards/nucleo_l073rz.overlay @@ -7,11 +7,12 @@ / { zephyr,user { /* adjust channel number according to pinmux in board.dts */ - io-channels = <&adc1 0>; + io-channels = <&adc1 0>, <&adc1 1>; }; }; &adc1 { + pinctrl-0 = <&adc_in0_pa0 &adc_in1_pa1>; #address-cells = <1>; #size-cells = <0>; @@ -19,7 +20,15 @@ reg = <0>; zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; zephyr,resolution = <12>; }; }; diff --git a/tests/drivers/adc/adc_api/boards/nucleo_l152re.overlay b/tests/drivers/adc/adc_api/boards/nucleo_l152re.overlay index f0d65c1e941..d8d89d460a0 100644 --- a/tests/drivers/adc/adc_api/boards/nucleo_l152re.overlay +++ b/tests/drivers/adc/adc_api/boards/nucleo_l152re.overlay @@ -7,11 +7,12 @@ / { zephyr,user { /* adjust channel number according to pinmux in board.dts */ - io-channels = <&adc1 0>; + io-channels = <&adc1 0>, <&adc1 1>; }; }; &adc1 { + pinctrl-0 = <&adc_in0_pa0 &adc_in1_pa1>; #address-cells = <1>; #size-cells = <0>; @@ -19,7 +20,15 @@ reg = <0>; zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; zephyr,resolution = <12>; }; }; diff --git a/tests/drivers/adc/adc_api/boards/nucleo_l552ze_q.overlay b/tests/drivers/adc/adc_api/boards/nucleo_l552ze_q.overlay index 33188a18cf4..ab283660858 100644 --- a/tests/drivers/adc/adc_api/boards/nucleo_l552ze_q.overlay +++ b/tests/drivers/adc/adc_api/boards/nucleo_l552ze_q.overlay @@ -7,11 +7,12 @@ / { zephyr,user { /* adjust channel number according to pinmux in board.dts */ - io-channels = <&adc1 1>; + io-channels = <&adc1 1>, <&adc1 2>; }; }; &adc1 { + pinctrl-0 = <&adc1_in1_pc0 &adc1_in2_pc1>; #address-cells = <1>; #size-cells = <0>; @@ -19,7 +20,15 @@ reg = <1>; zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@2 { + reg = <2>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; zephyr,resolution = <12>; }; }; diff --git a/tests/drivers/adc/adc_api/boards/nucleo_u5a5zj_q.overlay b/tests/drivers/adc/adc_api/boards/nucleo_u5a5zj_q.overlay new file mode 100644 index 00000000000..33fbcb51723 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/nucleo_u5a5zj_q.overlay @@ -0,0 +1,25 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 STMicroelectronics + */ + +/ { + zephyr,user { + /* adjust channel number according to pinmux in board.dts */ + io-channels = <&adc1 1>; + }; +}; + +&adc1 { + #address-cells = <1>; + #size-cells = <0>; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; diff --git a/tests/drivers/adc/adc_api/boards/nucleo_wb55rg.overlay b/tests/drivers/adc/adc_api/boards/nucleo_wb55rg.overlay index 33188a18cf4..82f3300458c 100644 --- a/tests/drivers/adc/adc_api/boards/nucleo_wb55rg.overlay +++ b/tests/drivers/adc/adc_api/boards/nucleo_wb55rg.overlay @@ -7,19 +7,28 @@ / { zephyr,user { /* adjust channel number according to pinmux in board.dts */ - io-channels = <&adc1 1>; + io-channels = <&adc1 3>, <&adc1 4>; }; }; &adc1 { + pinctrl-0 = <&adc1_in3_pc2 &adc1_in4_pc3>; #address-cells = <1>; #size-cells = <0>; - channel@1 { - reg = <1>; + channel@3 { + reg = <3>; zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@4 { + reg = <4>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; zephyr,resolution = <12>; }; }; diff --git a/tests/drivers/adc/adc_api/boards/nucleo_wba52cg.overlay b/tests/drivers/adc/adc_api/boards/nucleo_wba52cg.overlay index 6b96b54ef63..ae2f4afc58c 100644 --- a/tests/drivers/adc/adc_api/boards/nucleo_wba52cg.overlay +++ b/tests/drivers/adc/adc_api/boards/nucleo_wba52cg.overlay @@ -7,19 +7,28 @@ / { zephyr,user { /* adjust channel number according to pinmux in board.dts */ - io-channels = <&adc4 8>; + io-channels = <&adc4 7>, <&adc4 8>; }; }; &adc4 { + pinctrl-0 = <&adc4_in7_pa2 &adc4_in8_pa1>; #address-cells = <1>; #size-cells = <0>; + channel@7 { + reg = <7>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + channel@8 { reg = <8>; zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; + zephyr,acquisition-time = ; zephyr,resolution = <12>; }; }; diff --git a/tests/drivers/adc/adc_api/boards/nucleo_wl55jc.overlay b/tests/drivers/adc/adc_api/boards/nucleo_wl55jc.overlay index f0d65c1e941..6e8e84b6678 100644 --- a/tests/drivers/adc/adc_api/boards/nucleo_wl55jc.overlay +++ b/tests/drivers/adc/adc_api/boards/nucleo_wl55jc.overlay @@ -7,19 +7,28 @@ / { zephyr,user { /* adjust channel number according to pinmux in board.dts */ - io-channels = <&adc1 0>; + io-channels = <&adc1 4>, <&adc1 5>; }; }; &adc1 { + pinctrl-0 = <&adc_in4_pb2 &adc_in5_pb1>; #address-cells = <1>; #size-cells = <0>; - channel@0 { - reg = <0>; + channel@4 { + reg = <4>; zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@5 { + reg = <5>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; zephyr,resolution = <12>; }; }; diff --git a/tests/drivers/adc/adc_api/boards/stm32f3_disco.overlay b/tests/drivers/adc/adc_api/boards/stm32f3_disco.overlay index f0d65c1e941..06897f4a6e4 100644 --- a/tests/drivers/adc/adc_api/boards/stm32f3_disco.overlay +++ b/tests/drivers/adc/adc_api/boards/stm32f3_disco.overlay @@ -7,19 +7,28 @@ / { zephyr,user { /* adjust channel number according to pinmux in board.dts */ - io-channels = <&adc1 0>; + io-channels = <&adc1 1>, <&adc1 2>; }; }; &adc1 { + pinctrl-0 = <&adc1_in1_pa0 &adc1_in2_pa1>; #address-cells = <1>; #size-cells = <0>; - channel@0 { - reg = <0>; + channel@1 { + reg = <1>; zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@2 { + reg = <2>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; zephyr,resolution = <12>; }; }; diff --git a/tests/drivers/adc/adc_api/boards/stm32h573i_dk.overlay b/tests/drivers/adc/adc_api/boards/stm32h573i_dk.overlay index af607867c7b..4a71e03421d 100644 --- a/tests/drivers/adc/adc_api/boards/stm32h573i_dk.overlay +++ b/tests/drivers/adc/adc_api/boards/stm32h573i_dk.overlay @@ -8,16 +8,25 @@ / { zephyr,user { /* adjust channel number according to pinmux in board.dts */ - io-channels = <&adc1 1>; + io-channels = <&adc1 3>, <&adc1 6>; }; }; &adc1 { + pinctrl-0 = < &adc1_inp3_pa6 &adc1_inp6_pf12>; #address-cells = <1>; #size-cells = <0>; - channel@1 { - reg = <1>; + channel@3 { + reg = <3>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@6 { + reg = <6>; zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; zephyr,acquisition-time = ; diff --git a/tests/drivers/adc/adc_api/boards/stm32l4r9i_disco.overlay b/tests/drivers/adc/adc_api/boards/stm32l4r9i_disco.overlay new file mode 100644 index 00000000000..692d5d9aac5 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/stm32l4r9i_disco.overlay @@ -0,0 +1,24 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) STMicroelectronics + */ + +/ { + zephyr,user { + io-channels = <&adc1 0>; + }; +}; + +&adc1 { + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; diff --git a/tests/drivers/adc/adc_api/boards/stm32l562e_dk.overlay b/tests/drivers/adc/adc_api/boards/stm32l562e_dk.overlay index 33188a18cf4..fbeba28dcd6 100644 --- a/tests/drivers/adc/adc_api/boards/stm32l562e_dk.overlay +++ b/tests/drivers/adc/adc_api/boards/stm32l562e_dk.overlay @@ -7,19 +7,28 @@ / { zephyr,user { /* adjust channel number according to pinmux in board.dts */ - io-channels = <&adc1 1>; + io-channels = <&adc1 13>, <&adc1 14>; }; }; &adc1 { + pinctrl-0 = <&adc1_in13_pc4 &adc1_in14_pc5>; #address-cells = <1>; #size-cells = <0>; - channel@1 { - reg = <1>; + channel@d { + reg = <13>; zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@e { + reg = <14>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; zephyr,resolution = <12>; }; }; diff --git a/tests/drivers/adc/adc_api/boards/stm32u5a9j_dk.overlay b/tests/drivers/adc/adc_api/boards/stm32u5a9j_dk.overlay new file mode 100644 index 00000000000..83335cd9aa4 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/stm32u5a9j_dk.overlay @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + zephyr,user { + /* adjust channel number according to pinmux in board.dts */ + io-channels = <&adc1 5>; + }; +}; diff --git a/tests/drivers/adc/adc_api/prj.conf b/tests/drivers/adc/adc_api/prj.conf index 94f86d9fcb4..d95ab6031c2 100644 --- a/tests/drivers/adc/adc_api/prj.conf +++ b/tests/drivers/adc/adc_api/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ADC=y CONFIG_ADC_ASYNC=y diff --git a/tests/drivers/adc/adc_api/src/test_adc.c b/tests/drivers/adc/adc_api/src/test_adc.c index de21f5c434f..250982b1d69 100644 --- a/tests/drivers/adc/adc_api/src/test_adc.c +++ b/tests/drivers/adc/adc_api/src/test_adc.c @@ -93,7 +93,7 @@ static int test_task_one_channel(void) init_adc(); (void)adc_sequence_init_dt(&adc_channels[0], &sequence); - ret = adc_read(adc_channels[0].dev, &sequence); + ret = adc_read_dt(&adc_channels[0], &sequence); zassert_equal(ret, 0, "adc_read() failed with code %d", ret); check_samples(1); @@ -124,7 +124,7 @@ static int test_task_multiple_channels(void) sequence.channels |= BIT(adc_channels[i].channel_id); } - ret = adc_read(adc_channels[0].dev, &sequence); + ret = adc_read_dt(&adc_channels[0], &sequence); if (ret == -ENOTSUP) { ztest_test_skip(); } @@ -230,7 +230,7 @@ static int test_task_with_interval(void) (void)adc_sequence_init_dt(&adc_channels[0], &sequence); - ret = adc_read(adc_channels[0].dev, &sequence); + ret = adc_read_dt(&adc_channels[0], &sequence); if (ret == -ENOTSUP) { ztest_test_skip(); } @@ -261,12 +261,12 @@ static enum adc_action repeated_samplings_callback(const struct device *dev, ++m_samplings_done; TC_PRINT("%s: done %d\n", __func__, m_samplings_done); if (m_samplings_done == 1U) { - check_samples(adc_channels_count); + check_samples(MIN(adc_channels_count, 2)); /* After first sampling continue normally. */ return ADC_ACTION_CONTINUE; } else { - check_samples(2 * adc_channels_count); + check_samples(2 * MIN(adc_channels_count, 2)); /* * The second sampling is repeated 9 times (the samples are @@ -310,7 +310,7 @@ static int test_task_repeated_samplings(void) sequence.channels |= BIT(adc_channels[1].channel_id); } - ret = adc_read(adc_channels[0].dev, &sequence); + ret = adc_read_dt(&adc_channels[0], &sequence); if (ret == -ENOTSUP) { ztest_test_skip(); } @@ -339,7 +339,7 @@ static int test_task_invalid_request(void) init_adc(); - ret = adc_read(adc_channels[0].dev, &sequence); + ret = adc_read_dt(&adc_channels[0], &sequence); zassert_not_equal(ret, 0, "adc_read() unexpectedly succeeded"); #if defined(CONFIG_ADC_ASYNC) @@ -352,7 +352,7 @@ static int test_task_invalid_request(void) */ sequence.resolution = adc_channels[0].resolution; - ret = adc_read(adc_channels[0].dev, &sequence); + ret = adc_read_dt(&adc_channels[0], &sequence); zassert_equal(ret, 0, "adc_read() failed with code %d", ret); check_samples(1); diff --git a/tests/drivers/adc/adc_api/testcase.yaml b/tests/drivers/adc/adc_api/testcase.yaml index b29afdf561c..5e8217cb2c3 100644 --- a/tests/drivers/adc/adc_api/testcase.yaml +++ b/tests/drivers/adc/adc_api/testcase.yaml @@ -7,3 +7,8 @@ tests: drivers.adc: depends_on: adc min_flash: 40 + drivers.adc.b_u585i_iot02a_adc4: + extra_args: + DTC_OVERLAY_FILE="boards/b_u585i_iot02a_adc4.overlay" + platform_allow: + - b_u585i_iot02a diff --git a/tests/drivers/adc/adc_dma/boards/nucleo_h743zi.overlay b/tests/drivers/adc/adc_dma/boards/nucleo_h743zi.overlay index 22590af7af4..fdedd2a4635 100644 --- a/tests/drivers/adc/adc_dma/boards/nucleo_h743zi.overlay +++ b/tests/drivers/adc/adc_dma/boards/nucleo_h743zi.overlay @@ -3,6 +3,9 @@ * * SPDX-License-Identifier: Apache-2.0 */ + +#include + &adc1 { dmas = < &dmamux1 0 9 (STM32_DMA_PERIPH_TO_MEMORY | STM32_DMA_MEM_INC | STM32_DMA_MEM_16BITS | STM32_DMA_PERIPH_16BITS) >; @@ -22,7 +25,7 @@ /* ADC driver expects a buffer in a non-cachable memory region */ &sram4 { - zephyr,memory-attr = "RAM_NOCACHE"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) )>; }; &dma1 { diff --git a/tests/drivers/adc/adc_dma/prj.conf b/tests/drivers/adc/adc_dma/prj.conf index 81a73e12de1..e2b567f4bd8 100644 --- a/tests/drivers/adc/adc_dma/prj.conf +++ b/tests/drivers/adc/adc_dma/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ADC=y CONFIG_ADC_LOG_LEVEL_INF=y diff --git a/tests/drivers/adc/adc_dma/testcase.yaml b/tests/drivers/adc/adc_dma/testcase.yaml index daf073bab5c..6db57d4be6c 100644 --- a/tests/drivers/adc/adc_dma/testcase.yaml +++ b/tests/drivers/adc/adc_dma/testcase.yaml @@ -4,7 +4,7 @@ common: - dma - trigger tests: - drivers.adc-dma: + drivers.adc.dma: depends_on: - adc - dma diff --git a/tests/drivers/adc/adc_emul/prj.conf b/tests/drivers/adc/adc_emul/prj.conf index eaab1b20102..ab4663f4f9b 100644 --- a/tests/drivers/adc/adc_emul/prj.conf +++ b/tests/drivers/adc/adc_emul/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ADC=y CONFIG_ADC_LOG_LEVEL_INF=y diff --git a/tests/drivers/adc/adc_rescale/prj.conf b/tests/drivers/adc/adc_rescale/prj.conf index eaab1b20102..ab4663f4f9b 100644 --- a/tests/drivers/adc/adc_rescale/prj.conf +++ b/tests/drivers/adc/adc_rescale/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ADC=y CONFIG_ADC_LOG_LEVEL_INF=y diff --git a/tests/drivers/adc/adc_rescale/src/main.c b/tests/drivers/adc/adc_rescale/src/main.c index 4bc9c3cccd8..121801b3be8 100644 --- a/tests/drivers/adc/adc_rescale/src/main.c +++ b/tests/drivers/adc/adc_rescale/src/main.c @@ -69,7 +69,7 @@ static int test_task_voltage_divider(void) }; adc_sequence_init_dt(&adc_node_0.port, &sequence); - ret = adc_read(adc_node_0.port.dev, &sequence); + ret = adc_read_dt(&adc_node_0.port, &sequence); zassert_equal(ret, 0, "adc_read() failed with code %d", ret); ret = adc_raw_to_millivolts_dt(&adc_node_0.port, &calculated_voltage); @@ -109,7 +109,7 @@ static int test_task_current_sense_shunt(void) }; adc_sequence_init_dt(&adc_node_1.port, &sequence); - ret = adc_read(adc_node_1.port.dev, &sequence); + ret = adc_read_dt(&adc_node_1.port, &sequence); zassert_equal(ret, 0, "adc_read() failed with code %d", ret); ret = adc_raw_to_millivolts_dt(&adc_node_1.port, &calculated_current); @@ -149,7 +149,7 @@ static int test_task_current_sense_amplifier(void) }; adc_sequence_init_dt(&adc_node_2.port, &sequence); - ret = adc_read(adc_node_2.port.dev, &sequence); + ret = adc_read_dt(&adc_node_2.port, &sequence); zassert_equal(ret, 0, "adc_read() failed with code %d", ret); ret = adc_raw_to_millivolts_dt(&adc_node_2.port, &calculated_current); diff --git a/tests/drivers/bbram/emul/prj.conf b/tests/drivers/bbram/emul/prj.conf index 79984859b7e..61986e63a19 100644 --- a/tests/drivers/bbram/emul/prj.conf +++ b/tests/drivers/bbram/emul/prj.conf @@ -2,5 +2,4 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BBRAM=y diff --git a/tests/drivers/bbram/prj.conf b/tests/drivers/bbram/prj.conf index 79984859b7e..61986e63a19 100644 --- a/tests/drivers/bbram/prj.conf +++ b/tests/drivers/bbram/prj.conf @@ -2,5 +2,4 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BBRAM=y diff --git a/tests/drivers/bbram/stm32_rtc.conf b/tests/drivers/bbram/stm32_rtc.conf new file mode 100644 index 00000000000..3a87a9c6c6e --- /dev/null +++ b/tests/drivers/bbram/stm32_rtc.conf @@ -0,0 +1 @@ +CONFIG_RTC=y diff --git a/tests/drivers/bbram/testcase.yaml b/tests/drivers/bbram/testcase.yaml index 00dd965870a..db1d1640772 100644 --- a/tests/drivers/bbram/testcase.yaml +++ b/tests/drivers/bbram/testcase.yaml @@ -22,3 +22,8 @@ tests: filter: dt_compat_enabled("st,stm32-bbram") integration_platforms: - stm32f746g_disco + drivers.bbram.stm32_rtc: + extra_args: OVERLAY_CONFIG="stm32_rtc.conf" + filter: dt_compat_enabled("st,stm32-bbram") + integration_platforms: + - stm32f746g_disco diff --git a/tests/drivers/bc12/prj.conf b/tests/drivers/bc12/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/drivers/bc12/prj.conf +++ b/tests/drivers/bc12/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/bc12/testcase.yaml b/tests/drivers/bc12/testcase.yaml index f7244908edf..1562b625592 100644 --- a/tests/drivers/bc12/testcase.yaml +++ b/tests/drivers/bc12/testcase.yaml @@ -1,6 +1,7 @@ tests: - drivers.bc12: + drivers.usb.bc12: tags: - drivers + - usb - bc12 platform_allow: native_posix diff --git a/tests/drivers/build_all/adc/boards/native_posix.overlay b/tests/drivers/build_all/adc/boards/native_posix.overlay index 8cba0de309a..120e05dcfb0 100644 --- a/tests/drivers/build_all/adc/boards/native_posix.overlay +++ b/tests/drivers/build_all/adc/boards/native_posix.overlay @@ -87,6 +87,13 @@ reg = <0x7>; #io-channel-cells = <1>; }; + + test_i2c_ltc2451: ltc2451@8{ + compatible = "lltc,ltc2451"; + reg = <0x8>; + conversion-speed = <60>; + #io-channel-cells = <1>; + }; }; test_spi: spi@33334444 { @@ -99,6 +106,16 @@ /* one entry for every devices at spi.dtsi */ cs-gpios = <&test_gpio 0 0>, + <&test_gpio 0 0>, + <&test_gpio 0 0>, + <&test_gpio 0 0>, + <&test_gpio 0 0>, + <&test_gpio 0 0>, + <&test_gpio 0 0>, + <&test_gpio 0 0>, + <&test_gpio 0 0>, + <&test_gpio 0 0>, + <&test_gpio 0 0>, <&test_gpio 0 0>, <&test_gpio 0 0>, <&test_gpio 0 0>, @@ -229,6 +246,86 @@ drdy-gpios = <&test_gpio 0 0>; start-sync-gpios = <&test_gpio 0 0>; }; + + test_spi_max11102: max11102@a { + compatible = "maxim,max11102"; + reg = <0xa>; + spi-max-frequency = <0>; + #io-channel-cells = <1>; + chsel-gpios = <&test_gpio 0 0>; + }; + + test_spi_max11103: max11103@b { + compatible = "maxim,max11103"; + reg = <0xb>; + spi-max-frequency = <0>; + #io-channel-cells = <1>; + chsel-gpios = <&test_gpio 0 0>; + }; + + test_spi_max11105: max11105@c { + compatible = "maxim,max11105"; + reg = <0xc>; + spi-max-frequency = <0>; + #io-channel-cells = <1>; + }; + + test_spi_max11106: max11106@d { + compatible = "maxim,max11106"; + reg = <0xd>; + spi-max-frequency = <0>; + #io-channel-cells = <1>; + chsel-gpios = <&test_gpio 0 0>; + }; + + test_spi_max11110: max11110@e { + compatible = "maxim,max11110"; + reg = <0xe>; + spi-max-frequency = <0>; + #io-channel-cells = <1>; + }; + + test_spi_max11111: max11111@f { + compatible = "maxim,max11111"; + reg = <0xf>; + spi-max-frequency = <0>; + #io-channel-cells = <1>; + chsel-gpios = <&test_gpio 0 0>; + }; + + test_spi_max11115: max11115@10 { + compatible = "maxim,max11115"; + reg = <0x10>; + spi-max-frequency = <0>; + #io-channel-cells = <1>; + }; + + test_spi_max11116: max11116@11 { + compatible = "maxim,max11116"; + reg = <0x11>; + spi-max-frequency = <0>; + #io-channel-cells = <1>; + }; + + test_spi_max11117: max11117@12 { + compatible = "maxim,max11117"; + reg = <0x12>; + spi-max-frequency = <0>; + #io-channel-cells = <1>; + }; + + test_spi_ad5592: ad5592@13 { + compatible = "adi,ad5592"; + status = "okay"; + reg = <0x13>; + spi-max-frequency = <0>; + reset-gpios = <&test_gpio 0 0>; + + ad5592_adc: adc-controller { + compatible = "adi,ad5592-adc"; + #io-channel-cells = <1>; + }; + }; }; }; }; diff --git a/tests/drivers/build_all/adc/prj.conf b/tests/drivers/build_all/adc/prj.conf index afb4cf20d79..cdf8b315168 100644 --- a/tests/drivers/build_all/adc/prj.conf +++ b/tests/drivers/build_all/adc/prj.conf @@ -3,3 +3,5 @@ CONFIG_TEST_USERSPACE=y CONFIG_ADC=y CONFIG_MAX_THREAD_BYTES=4 CONFIG_ADC_INIT_PRIORITY=80 +CONFIG_KOBJECT_RODATA_AREA_EXTRA_BYTES=256 +CONFIG_SPI=y diff --git a/tests/drivers/build_all/adc/testcase.yaml b/tests/drivers/build_all/adc/testcase.yaml index cde46e57a09..a8102364b60 100644 --- a/tests/drivers/build_all/adc/testcase.yaml +++ b/tests/drivers/build_all/adc/testcase.yaml @@ -9,52 +9,30 @@ tests: platform_allow: - native_posix - native_posix_64 - tags: - - adc_mcp302x - - adc_lmp90xxx - - adc_ads1x1x - - adc_ads1119 - - adc_ads1112 - - adc_ads114s08 - - adc_emul - - adc_max1125x extra_args: "CONFIG_GPIO=y" drivers.adc.cc32xx.build: platform_allow: cc3220sf_launchxl - tags: adc_cc32xx drivers.adc.ite.it8xxx2.build: platform_allow: it8xxx2_evb - tags: adc_ite_it8xxx2 drivers.adc.mcux.adc12.build: platform_allow: twr_ke18f - tags: adc_mcux_adc12 drivers.adc.mcux.adc16.build: platform_allow: frdm_k22f - tags: adc_mcux_adc16 drivers.adc.mcux.lpadc.build: platform_allow: lpcxpresso55s28 - tags: adc_mcux_lpadc drivers.adc.npcx.build: platform_allow: npcx7m6fb_evb - tags: adc_npcx drivers.adc.nrf.build: platform_allow: nrf51dk_nrf51422 - tags: adc_nrfx_adc drivers.adc.nrf.saadc.build: platform_allow: nrf21540dk_nrf52840 - tags: adc_nrfx_saadc drivers.adc.sam0.build: platform_allow: atsame54_xpro - tags: adc_sam0 drivers.adc.sam.afec.build: platform_allow: sam_e70_xplained - tags: adc_sam_afec drivers.adc.stm32.build: platform_allow: disco_l475_iot1 - tags: adc_stm32 drivers.adc.xec.build: platform_allow: mec15xxevb_assy6853 - tags: adc_xec drivers.adc.test.build: platform_allow: qemu_cortex_m3 - tags: adc_test diff --git a/tests/drivers/build_all/can/testcase.yaml b/tests/drivers/build_all/can/testcase.yaml index 4cad66e888f..c276b24c652 100644 --- a/tests/drivers/build_all/can/testcase.yaml +++ b/tests/drivers/build_all/can/testcase.yaml @@ -4,9 +4,18 @@ common: - drivers - can tests: - drivers.build_all.can.mcp2515: + drivers.can.build_all.mcp2515: depends_on: - arduino_spi - arduino_gpio extra_args: SHIELD=dfrobot_can_bus_v2_0 platform_allow: frdm_k64f + drivers.can.build_all.tcan4x5x: + depends_on: + - arduino_spi + - arduino_gpio + extra_args: SHIELD=tcan4550evm + platform_allow: frdm_k64f + drivers.can.build_all.mcp251xfd: + extra_args: SHIELD=mikroe_mcp2518fd_click + platform_allow: lpcxpresso55s28 diff --git a/tests/drivers/build_all/charger/CMakeLists.txt b/tests/drivers/build_all/charger/CMakeLists.txt new file mode 100644 index 00000000000..65cdb555717 --- /dev/null +++ b/tests/drivers/build_all/charger/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2023 Cirrus Logic, Inc. +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(build_all) + +target_sources(app PRIVATE src/main.c) diff --git a/tests/drivers/build_all/charger/app.overlay b/tests/drivers/build_all/charger/app.overlay new file mode 100644 index 00000000000..1df6a67da98 --- /dev/null +++ b/tests/drivers/build_all/charger/app.overlay @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 Cirrus Logic, Inc. + * SPDX-License-Identifier: Apache-2.0 + */ + + #include + +/ { + test { + #address-cells = <1>; + #size-cells = <1>; + + test_i2c: i2c@11112222 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "vnd,i2c"; + reg = <0x11112222 0x1000>; + status = "okay"; + clock-frequency = ; + + #include "i2c.dtsi" + }; + }; +}; diff --git a/tests/drivers/build_all/charger/i2c.dtsi b/tests/drivers/build_all/charger/i2c.dtsi new file mode 100644 index 00000000000..c30efdcfcb8 --- /dev/null +++ b/tests/drivers/build_all/charger/i2c.dtsi @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Cirrus Logic, Inc. + * SPDX-License-Identifier: Apache-2.0 + */ + +/**************************************** + * PLEASE KEEP REG ADDRESSES SEQUENTIAL * + ***************************************/ + +bq24190@0 { + compatible = "ti,bq24190"; + reg = <0x0>; + status = "okay"; + + constant-charge-current-max-microamp = <1000000>; + constant-charge-voltage-max-microvolt = <4208000>; +}; + +max20335@1 { + compatible = "maxim,max20335"; + reg = <0x01>; + status = "okay"; + + charger: charger { + compatible = "maxim,max20335-charger"; + + constant-charge-current-max-microamp = <100000>; + constant-charge-voltage-max-microvolt = <4050000>; + }; +}; diff --git a/tests/drivers/build_all/charger/prj.conf b/tests/drivers/build_all/charger/prj.conf new file mode 100644 index 00000000000..922c6f65a09 --- /dev/null +++ b/tests/drivers/build_all/charger/prj.conf @@ -0,0 +1 @@ +CONFIG_CHARGER=y diff --git a/tests/drivers/build_all/charger/src/main.c b/tests/drivers/build_all/charger/src/main.c new file mode 100644 index 00000000000..504c9ebc22c --- /dev/null +++ b/tests/drivers/build_all/charger/src/main.c @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2023 Cirrus Logic, Inc. + * SPDX-License-Identifier: Apache-2.0 + */ + +int main(void) +{ + return 0; +} diff --git a/tests/drivers/build_all/charger/testcase.yaml b/tests/drivers/build_all/charger/testcase.yaml new file mode 100644 index 00000000000..f2005d9f238 --- /dev/null +++ b/tests/drivers/build_all/charger/testcase.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Cirrus Logic, Inc. +# SPDX-License-Identifier: Apache-2.0 + +tests: + drivers.charger.build: + tags: + - drivers + - charger + build_only: true + platform_allow: native_posix diff --git a/tests/drivers/build_all/dac/app.overlay b/tests/drivers/build_all/dac/app.overlay index c1e91469744..ee82a5e8b86 100644 --- a/tests/drivers/build_all/dac/app.overlay +++ b/tests/drivers/build_all/dac/app.overlay @@ -68,6 +68,18 @@ /* one entry for every devices at spi.dtsi */ cs-gpios = <&test_gpio 0 0>, + <&test_gpio 0 0>, + <&test_gpio 0 0>, + <&test_gpio 0 0>, + <&test_gpio 0 0>, + <&test_gpio 0 0>, + <&test_gpio 0 0>, + <&test_gpio 0 0>, + <&test_gpio 0 0>, + <&test_gpio 0 0>, + <&test_gpio 0 0>, + <&test_gpio 0 0>, + <&test_gpio 0 0>, <&test_gpio 0 0>, <&test_gpio 0 0>, <&test_gpio 0 0>, @@ -134,6 +146,107 @@ spi-max-frequency = <0>; #io-channel-cells = <1>; }; + + test_spi_ad5628: ad5628@5 { + compatible = "adi,ad5628"; + reg = <0x5>; + spi-max-frequency = <0>; + #io-channel-cells = <1>; + reset-gpios = <&test_gpio 0 0>; + }; + + test_spi_ad5648: ad5648@6 { + compatible = "adi,ad5648"; + reg = <0x6>; + spi-max-frequency = <0>; + #io-channel-cells = <1>; + reset-gpios = <&test_gpio 0 0>; + }; + + test_spi_ad5668: ad5668@7 { + compatible = "adi,ad5668"; + reg = <0x7>; + spi-max-frequency = <0>; + #io-channel-cells = <1>; + reset-gpios = <&test_gpio 0 0>; + }; + + test_spi_ad5672: ad5672@8 { + compatible = "adi,ad5672"; + reg = <0x8>; + spi-max-frequency = <0>; + #io-channel-cells = <1>; + reset-gpios = <&test_gpio 0 0>; + }; + + test_spi_ad5674: ad5674@9 { + compatible = "adi,ad5674"; + reg = <0x9>; + spi-max-frequency = <0>; + #io-channel-cells = <1>; + reset-gpios = <&test_gpio 0 0>; + }; + + test_spi_ad5676: ad5676@A { + compatible = "adi,ad5676"; + reg = <0xA>; + spi-max-frequency = <0>; + #io-channel-cells = <1>; + reset-gpios = <&test_gpio 0 0>; + }; + + test_spi_ad5679: ad5679@B { + compatible = "adi,ad5679"; + reg = <0xB>; + spi-max-frequency = <0>; + #io-channel-cells = <1>; + reset-gpios = <&test_gpio 0 0>; + }; + + test_spi_ad5684: ad5684@C { + compatible = "adi,ad5684"; + reg = <0xC>; + spi-max-frequency = <0>; + #io-channel-cells = <1>; + reset-gpios = <&test_gpio 0 0>; + }; + + test_spi_ad5686: ad5686@D { + compatible = "adi,ad5686"; + reg = <0xD>; + spi-max-frequency = <0>; + #io-channel-cells = <1>; + reset-gpios = <&test_gpio 0 0>; + }; + + test_spi_ad5687: ad5687@E { + compatible = "adi,ad5687"; + reg = <0xE>; + spi-max-frequency = <0>; + #io-channel-cells = <1>; + reset-gpios = <&test_gpio 0 0>; + }; + + test_spi_ad5689: ad5689@F { + compatible = "adi,ad5689"; + reg = <0xF>; + spi-max-frequency = <0>; + #io-channel-cells = <1>; + reset-gpios = <&test_gpio 0 0>; + }; + + test_spi_ad5592: ad5592@10 { + compatible = "adi,ad5592"; + status = "okay"; + reg = <0x10>; + spi-max-frequency = <0>; + reset-gpios = <&test_gpio 0 0>; + + ad5592_dac: dac-controller { + compatible = "adi,ad5592-dac"; + #io-channel-cells = <1>; + }; + }; }; }; }; diff --git a/tests/drivers/build_all/dac/testcase.yaml b/tests/drivers/build_all/dac/testcase.yaml index 5796038ef9d..12252b8661f 100644 --- a/tests/drivers/build_all/dac/testcase.yaml +++ b/tests/drivers/build_all/dac/testcase.yaml @@ -7,23 +7,12 @@ tests: drivers.dac.build: # will cover I2C, SPI based drivers platform_allow: native_posix - tags: - - dac_dacx0508 - - dac_dacx3608 - - dac_mcp4725 - - dac_mcp4728 - - dac_ltc1660 - - dac_ltc1665 extra_args: "CONFIG_GPIO=y" drivers.dac.mcux.build: platform_allow: frdm_k22f - tags: dac_mcux drivers.dac.mcux32.build: platform_allow: twr_ke18f - tags: dac_mcux32 drivers.dac.sam0.build: platform_allow: atsamd21_xpro - tags: dac_sam0 drivers.dac.stm32.build: platform_allow: nucleo_f091rc - tags: dac_stm32 diff --git a/tests/drivers/build_all/ethernet/app.overlay b/tests/drivers/build_all/ethernet/app.overlay index 5f1d7fb2f45..a80c949e036 100644 --- a/tests/drivers/build_all/ethernet/app.overlay +++ b/tests/drivers/build_all/ethernet/app.overlay @@ -33,6 +33,8 @@ /* one entry for every devices at spi.dtsi */ cs-gpios = <&test_gpio 0 0>, + <&test_gpio 0 0>, + <&test_gpio 0 0>, <&test_gpio 0 0>, <&test_gpio 0 0>; @@ -60,6 +62,64 @@ int-gpios = <&test_gpio 0 0>; reset-gpios = <&test_gpio 0 0>; }; + + test_spi_adin1110: adin1110@3 { + compatible = "adi,adin1110"; + reg = <0x3>; + spi-max-frequency = <25000000>; + int-gpios = <&test_gpio 0 0>; + reset-gpios = <&test_gpio 0 0>; + + port1 { + local-mac-address = [ CA 2F B7 10 23 63 ]; + }; + + mdio { + compatible = "adi,adin2111-mdio"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + ethernet-phy@1 { + reg = <0x1>; + compatible = "adi,adin2111-phy"; + status = "okay"; + }; + }; + }; + + test_spi_adin2111: adin2111@4 { + compatible = "adi,adin2111"; + reg = <0x4>; + spi-max-frequency = <0>; + int-gpios = <&test_gpio 0 0>; + reset-gpios = <&test_gpio 0 0>; + + port1 { + local-mac-address = [ CA 2F B7 10 23 63 ]; + }; + port2 { + local-mac-address = [ 3C 82 D4 A2 29 8E ]; + }; + + mdio { + compatible = "adi,adin2111-mdio"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + ethernet-phy@1 { + reg = <0x1>; + compatible = "adi,adin2111-phy"; + status = "okay"; + }; + ethernet-phy@2 { + reg = <0x2>; + compatible = "adi,adin2111-phy"; + status = "okay"; + }; + }; + }; }; }; }; diff --git a/tests/drivers/build_all/ethernet/prj.conf b/tests/drivers/build_all/ethernet/prj.conf index de2c010c47f..f20cbb1d088 100644 --- a/tests/drivers/build_all/ethernet/prj.conf +++ b/tests/drivers/build_all/ethernet/prj.conf @@ -7,3 +7,8 @@ CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_TEST_USERSPACE=y CONFIG_GPIO=y + +CONFIG_SPI_INIT_PRIORITY=50 +CONFIG_ETH_INIT_PRIORITY=50 +CONFIG_MDIO_INIT_PRIORITY=50 +CONFIG_PHY_INIT_PRIORITY=50 diff --git a/tests/drivers/build_all/fpga/testcase.yaml b/tests/drivers/build_all/fpga/testcase.yaml index 75821c7a1a7..33cccf76dde 100644 --- a/tests/drivers/build_all/fpga/testcase.yaml +++ b/tests/drivers/build_all/fpga/testcase.yaml @@ -5,5 +5,5 @@ common: platform_allow: native_posix build_only: true tests: - fpga.build: + drivers.fpga.build: tags: fpga diff --git a/tests/drivers/build_all/gpio/adc_ads1145s0x_gpio.conf b/tests/drivers/build_all/gpio/adc_ads1145s0x_gpio.conf new file mode 100644 index 00000000000..64290a4a491 --- /dev/null +++ b/tests/drivers/build_all/gpio/adc_ads1145s0x_gpio.conf @@ -0,0 +1,3 @@ +CONFIG_ADC=y +CONFIG_ADC_ADS114S0X_GPIO=y +CONFIG_ADC_INIT_PRIORITY=80 diff --git a/tests/drivers/build_all/gpio/adc_ads1145s0x_gpio.overlay b/tests/drivers/build_all/gpio/adc_ads1145s0x_gpio.overlay new file mode 100644 index 00000000000..60078a4efff --- /dev/null +++ b/tests/drivers/build_all/gpio/adc_ads1145s0x_gpio.overlay @@ -0,0 +1,21 @@ +&test_spi { + test_spi_ads114s08: ads114s08@0 { + compatible = "ti,ads114s08"; + status = "okay"; + spi-max-frequency = <10000000>; + reg = <0x00>; + #address-cells = <1>; + #size-cells = <0>; + #io-channel-cells = <1>; + reset-gpios = <&test_gpio 0 0>; + drdy-gpios = <&test_gpio 0 0>; + start-sync-gpios = <&test_gpio 0 0>; + + test_spi_ads114s08_gpio: ads114s0x_gpio { + compatible = "ti,ads114s0x-gpio"; + gpio-controller; + ngpios = <4>; + #gpio-cells = <2>; + }; + }; +}; diff --git a/tests/drivers/build_all/gpio/altera.overlay b/tests/drivers/build_all/gpio/altera.overlay new file mode 100644 index 00000000000..2d92889aff4 --- /dev/null +++ b/tests/drivers/build_all/gpio/altera.overlay @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + test { + #address-cells = <1>; + #size-cells = <1>; + + test_int_gpio { + #address-cells = <1>; + #size-cells = <1>; + test_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + #address-cells = < 0x0 >; + #interrupt-cells = < 0x1 >; + interrupt-controller; + phandle = < 0x1 >; + }; + + test_gpio0: gpio@30070 { + interrupt-parent = < &test_intc >; + compatible = "altr,pio-1.0"; + reg = < 0x30070 0x10 >; + gpio-controller; + #gpio-cells = < 0x2 >; + status = "okay"; + ngpios = < 16 >; + #direction = "input"; + interrupts = <28>; + }; + }; + }; + +}; diff --git a/tests/drivers/build_all/gpio/app.overlay b/tests/drivers/build_all/gpio/app.overlay index 2fd3bdc2597..375b3ab25dc 100644 --- a/tests/drivers/build_all/gpio/app.overlay +++ b/tests/drivers/build_all/gpio/app.overlay @@ -51,7 +51,7 @@ test_i2c_pcal6416a: pcal6416a@2 { compatible = "nxp,pcal6416a"; - reg = <0x1>; + reg = <0x2>; gpio-controller; #gpio-cells = <2>; ngpios = <16>; @@ -103,63 +103,72 @@ gpio-controller; }; - test_i2c_nct3807: nct3807@72 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "nuvoton,nct38xx-gpio"; + mfd-nct38xx@72 { + compatible = "nuvoton,nct38xx"; reg = <0x72>; + test_i2c_nct3807: nct3807 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nuvoton,nct38xx-gpio"; - gpio@0 { - compatible = "nuvoton,nct38xx-gpio-port"; - reg = <0x0>; - gpio-controller; - #gpio-cells = <2>; - ngpios = <8>; - pin_mask = <0xff>; - pinmux_mask = <0xf7>; - }; + gpio@0 { + compatible = "nuvoton,nct38xx-gpio-port"; + reg = <0x0>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + pin_mask = <0xff>; + pinmux_mask = <0xf7>; + }; - gpio@1 { - compatible = "nuvoton,nct38xx-gpio-port"; - reg = <0x1>; - gpio-controller; - #gpio-cells = <2>; - ngpios = <8>; - pin_mask = <0xff>; + gpio@1 { + compatible = "nuvoton,nct38xx-gpio-port"; + reg = <0x1>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + pin_mask = <0xff>; + }; }; }; - test_i2c_nct3808_p1: nct3808_0_P1@71 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "nuvoton,nct38xx-gpio"; + test_i2c_nct3808_p1: mfd-nct38xx@71 { + compatible = "nuvoton,nct38xx"; reg = <0x71>; + nct3808_0_P1 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nuvoton,nct38xx-gpio"; - gpio@0 { - compatible = "nuvoton,nct38xx-gpio-port"; - reg = <0x0>; - gpio-controller; - #gpio-cells = <2>; - ngpios = <8>; - pin_mask = <0xdc>; - pinmux_mask = <0xff>; + gpio@0 { + compatible = "nuvoton,nct38xx-gpio-port"; + reg = <0x0>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + pin_mask = <0xdc>; + pinmux_mask = <0xff>; + }; }; }; - test_i2c_nct3808_p2: nct3808_0_P2@75 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "nuvoton,nct38xx-gpio"; + test_i2c_nct3808_p2: mfd-nct38xx@75 { + compatible = "nuvoton,nct38xx"; reg = <0x75>; + nct3808_0_P2 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nuvoton,nct38xx-gpio"; - gpio@0 { - compatible = "nuvoton,nct38xx-gpio-port"; - reg = <0x0>; - gpio-controller; - #gpio-cells = <2>; - ngpios = <8>; - pin_mask = <0xdc>; - pinmux_mask = <0xff>; + gpio@0 { + compatible = "nuvoton,nct38xx-gpio-port"; + reg = <0x0>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + pin_mask = <0xdc>; + pinmux_mask = <0xff>; + }; }; }; @@ -201,7 +210,11 @@ clock-frequency = <2000000>; /* one entry for every devices at spi.dtsi */ - cs-gpios = <&test_gpio 0 0 &test_gpio 0 0 &test_gpio 0 0>; + cs-gpios = <&test_gpio 0 0 + &test_gpio 0 0 + &test_gpio 0 0 + &test_gpio 0 0 + &test_gpio 0 0>; test_spi_mcp23s17: mcp23s17@0 { compatible = "microchip,mcp23s17"; @@ -212,44 +225,50 @@ ngpios = <16>; }; - test_spi_mcp23sxx: mcp23sxx@0 { + test_spi_mcp23sxx: mcp23sxx@1 { compatible = "microchip,mcp23sxx"; spi-max-frequency = <0>; - reg = <0x0>; + reg = <0x01>; gpio-controller; #gpio-cells = <2>; ngpios = <16>; }; - test_spi_bd8lb600fs: bd8lb600fs@0 { + test_spi_bd8lb600fs: bd8lb600fs@2 { compatible = "rohm,bd8lb600fs"; spi-max-frequency = <0>; - reg = <0x0>; + reg = <0x02>; gpio-controller; #gpio-cells = <2>; ngpios = <8>; reset-gpios = <&test_gpio 0 0>; }; - test_spi_ads114s08: ads114s08@0 { - compatible = "ti,ads114s08"; + test_spi_ad5592: ad5592@3 { + compatible = "adi,ad5592"; status = "okay"; - spi-max-frequency = <10000000>; - reg = <0x0>; - #address-cells = <1>; - #size-cells = <0>; - #io-channel-cells = <1>; + reg = <0x03>; + spi-max-frequency = <0>; reset-gpios = <&test_gpio 0 0>; - drdy-gpios = <&test_gpio 0 0>; - start-sync-gpios = <&test_gpio 0 0>; - test_spi_ads114s08_gpio: ads114s0x_gpio { - compatible = "ti,ads114s0x-gpio"; + ad5592_gpio: gpio-controller { + compatible = "adi,ad5592-gpio"; gpio-controller; - ngpios = <4>; #gpio-cells = <2>; + ngpios = <8>; }; }; + + test_spi_tle9104: tle9104@4 { + compatible = "infineon,tle9104"; + spi-max-frequency = <0>; + reg = <0x04>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <4>; + resn-gpios = <&test_gpio 0 0>; + en-gpios = <&test_gpio 0 0>; + }; }; }; }; diff --git a/tests/drivers/build_all/gpio/prj.conf b/tests/drivers/build_all/gpio/prj.conf index 1517e7a4b76..6e24ab48c84 100644 --- a/tests/drivers/build_all/gpio/prj.conf +++ b/tests/drivers/build_all/gpio/prj.conf @@ -4,4 +4,3 @@ CONFIG_TEST_USERSPACE=y CONFIG_I2C=y CONFIG_GPIO_PCA95XX_INTERRUPT=y CONFIG_SPI=y -CONFIG_ADC_ADS114S0X_GPIO=y diff --git a/tests/drivers/build_all/gpio/testcase.yaml b/tests/drivers/build_all/gpio/testcase.yaml index bd720d569d5..88d62c5b770 100644 --- a/tests/drivers/build_all/gpio/testcase.yaml +++ b/tests/drivers/build_all/gpio/testcase.yaml @@ -17,3 +17,20 @@ tests: platform_allow: titanium_ti60_f225 depends_on: gpio extra_args: DTC_OVERLAY_FILE="efinix_sapphire.overlay" + + drivers.gpio.build.altera_pio: + min_ram: 32 + platform_allow: niosv_m niosv_g + depends_on: gpio + extra_args: DTC_OVERLAY_FILE="altera.overlay" + + drivers.gpio.build.adc_ads1145s0x_gpio: + min_ram: 32 + platform_allow: m5stack_core2 nrf52840dk_nrf52840 + depends_on: + - gpio + - adc + - spi + extra_args: + - DTC_OVERLAY_FILE="app.overlay;adc_ads1145s0x_gpio.overlay" + - CONF_FILE="adc_ads1145s0x_gpio.conf" diff --git a/tests/drivers/build_all/i2c/testcase.yaml b/tests/drivers/build_all/i2c/testcase.yaml index 36513e230a2..3c672c12167 100644 --- a/tests/drivers/build_all/i2c/testcase.yaml +++ b/tests/drivers/build_all/i2c/testcase.yaml @@ -7,5 +7,4 @@ tests: drivers.i2c.build: # will cover drivers without in-tree boards platform_allow: qemu_cortex_m3 - tags: i2c_xilinx_axi extra_args: "CONFIG_I2C=y" diff --git a/tests/drivers/build_all/input/app.overlay b/tests/drivers/build_all/input/app.overlay index 4a1956be5d2..cf826cfe4fa 100644 --- a/tests/drivers/build_all/input/app.overlay +++ b/tests/drivers/build_all/input/app.overlay @@ -26,6 +26,15 @@ }; }; + kbd-matrix { + compatible = "gpio-kbd-matrix"; + row-gpios = <&test_gpio 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>, + <&test_gpio 1 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + col-gpios = <&test_gpio 2 GPIO_ACTIVE_LOW>, + <&test_gpio 3 GPIO_ACTIVE_LOW>, + <&test_gpio 4 GPIO_ACTIVE_LOW>; + }; + qdec-gpio { compatible = "gpio-qdec"; gpios = <&test_gpio 0 0>, <&test_gpio 1 0>; @@ -61,23 +70,33 @@ gt911@1 { compatible = "goodix,gt911"; reg = <0x1>; - irq-gpios = <&gpio0 0 0>; - reset-gpios = <&gpio0 0 0>; + irq-gpios = <&test_gpio 0 0>; + reset-gpios = <&test_gpio 1 0>; }; - cst816s: cst816s@2 { + cst816s@2 { compatible = "hynitron,cst816s"; reg = <0x2>; - irq-gpios = <&gpio0 0 0>; - rst-gpios = <&gpio0 0 0>; + irq-gpios = <&test_gpio 0 0>; + rst-gpios = <&test_gpio 1 0>; }; cap1203@3 { compatible = "microchip,cap1203"; reg = <0x3>; - int-gpios = <&gpio0 0 0>; + int-gpios = <&test_gpio 0 0>; input-codes = <0 1 2>; }; + + stmpe811@4 { + compatible = "st,stmpe811"; + reg = <0x4>; + int-gpios = <&test_gpio 0 0>; + panel-driver-settling-time-us = <10>; + touch-detect-delay-us = <10>; + touch-average-control = <1>; + tracking-index = <0>; + }; }; spi@2 { diff --git a/tests/drivers/build_all/interrupt_controller/intc_plic/CMakeLists.txt b/tests/drivers/build_all/interrupt_controller/intc_plic/CMakeLists.txt new file mode 100644 index 00000000000..518596a02f7 --- /dev/null +++ b/tests/drivers/build_all/interrupt_controller/intc_plic/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(build_all) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/build_all/interrupt_controller/intc_plic/Kconfig b/tests/drivers/build_all/interrupt_controller/intc_plic/Kconfig new file mode 100644 index 00000000000..6d7b572d877 --- /dev/null +++ b/tests/drivers/build_all/interrupt_controller/intc_plic/Kconfig @@ -0,0 +1,7 @@ +# Copyright (c) 2023 Meta +# SPDX-License-Identifier: Apache-2.0 + +config NUM_IRQS + int "" + +source "Kconfig" diff --git a/tests/drivers/build_all/interrupt_controller/intc_plic/app.multi_instance.overlay b/tests/drivers/build_all/interrupt_controller/intc_plic/app.multi_instance.overlay new file mode 100644 index 00000000000..93d8c626aa7 --- /dev/null +++ b/tests/drivers/build_all/interrupt_controller/intc_plic/app.multi_instance.overlay @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + + /{ + soc { + plic1: interrupt-controller@8000000 { + riscv,max-priority = <7>; + riscv,ndev = <0x35>; + reg = <0x08000000 0x04000000>; + interrupts-extended = < + &hlic0 0x03 + &hlic1 0x03 + &hlic2 0x03 + &hlic3 0x03 + &hlic4 0x03 + &hlic5 0x03 + &hlic6 0x03 + &hlic7 0x03 + >; + interrupt-controller; + compatible = "sifive,plic-1.0.0"; + #address-cells = <0x00>; + #interrupt-cells = <0x02>; + }; + }; + + uart1: uart@10000100 { + interrupts = <0x0a 1>; + interrupt-parent = <&plic1>; + clock-frequency = <0x384000>; + reg = <0x10000100 0x100>; + compatible = "ns16550"; + reg-shift = <0>; + }; +}; diff --git a/tests/drivers/build_all/interrupt_controller/intc_plic/prj.conf b/tests/drivers/build_all/interrupt_controller/intc_plic/prj.conf new file mode 100644 index 00000000000..4fac64b8a33 --- /dev/null +++ b/tests/drivers/build_all/interrupt_controller/intc_plic/prj.conf @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_TEST=y diff --git a/tests/drivers/build_all/interrupt_controller/intc_plic/src/main.c b/tests/drivers/build_all/interrupt_controller/intc_plic/src/main.c new file mode 100644 index 00000000000..06e02aa86d1 --- /dev/null +++ b/tests/drivers/build_all/interrupt_controller/intc_plic/src/main.c @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +int main(void) +{ + return 0; +} diff --git a/tests/drivers/build_all/interrupt_controller/intc_plic/testcase.yaml b/tests/drivers/build_all/interrupt_controller/intc_plic/testcase.yaml new file mode 100644 index 00000000000..ea80ccf8d26 --- /dev/null +++ b/tests/drivers/build_all/interrupt_controller/intc_plic/testcase.yaml @@ -0,0 +1,22 @@ +common: + build_only: true + filter: CONFIG_PLIC + platform_allow: + - qemu_riscv32 + - qemu_riscv64 + tags: + - drivers + - interrupt + - plic +tests: + drivers.interrupt_controller.intc_plic.build: {} + drivers.interrupt_controller.intc_plic.multi_instance.build: + extra_args: + DTC_OVERLAY_FILE="./app.multi_instance.overlay" + extra_configs: + - CONFIG_NUM_IRQS=116 + - CONFIG_MULTI_LEVEL_INTERRUPTS=y + - CONFIG_DYNAMIC_INTERRUPTS=y + - CONFIG_NUM_2ND_LEVEL_AGGREGATORS=2 + - CONFIG_2ND_LVL_INTR_01_OFFSET=3 + - CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/tests/drivers/build_all/mdio/CMakeLists.txt b/tests/drivers/build_all/mdio/CMakeLists.txt new file mode 100644 index 00000000000..518596a02f7 --- /dev/null +++ b/tests/drivers/build_all/mdio/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(build_all) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/build_all/mdio/app.overlay b/tests/drivers/build_all/mdio/app.overlay new file mode 100644 index 00000000000..e03c9e95065 --- /dev/null +++ b/tests/drivers/build_all/mdio/app.overlay @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 Aleksandr Senin + * + * SPDX-License-Identifier: Apache-2.0 + * + * Application overlay for testing driver builds + * + * Names in this file should be chosen in a way that won't conflict + * with real-world devicetree nodes, to allow these tests to run on + * (and be extended to test) real hardware. + */ + +/ { + test { + #address-cells = <1>; + #size-cells = <1>; + + test_gpio: gpio@deadbeef { + compatible = "vnd,gpio"; + gpio-controller; + reg = <0xdeadbeef 0x1000>; + #gpio-cells = <0x2>; + status = "okay"; + }; + + test_mdio0: mdio@11112222 { + compatible = "zephyr,mdio-gpio"; + reg = <0x11112222 1>; + mdc-gpios = <&test_gpio 0 0>; + mdio-gpios = <&test_gpio 0 0>; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + }; + + test_mdio1: mdio@33334444 { + compatible = "zephyr,mdio-gpio"; + reg = <0x33334444 1>; + mdc-gpios = <&test_gpio 0 0>; + mdio-gpios = <&test_gpio 0 0>; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + }; + }; +}; diff --git a/tests/drivers/build_all/mdio/prj.conf b/tests/drivers/build_all/mdio/prj.conf new file mode 100644 index 00000000000..1e4bd3763fb --- /dev/null +++ b/tests/drivers/build_all/mdio/prj.conf @@ -0,0 +1,5 @@ +CONFIG_TEST=y +CONFIG_TEST_USERSPACE=y +CONFIG_GPIO=y +CONFIG_MDIO=y +CONFIG_MDIO_GPIO=y diff --git a/tests/drivers/build_all/mdio/src/main.c b/tests/drivers/build_all/mdio/src/main.c new file mode 100644 index 00000000000..4c52a4c62a6 --- /dev/null +++ b/tests/drivers/build_all/mdio/src/main.c @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2023 Aleksandr Senin + * + * SPDX-License-Identifier: Apache-2.0 + */ + +int main(void) +{ + return 0; +} diff --git a/tests/drivers/build_all/mdio/testcase.yaml b/tests/drivers/build_all/mdio/testcase.yaml new file mode 100644 index 00000000000..19e16e0f2be --- /dev/null +++ b/tests/drivers/build_all/mdio/testcase.yaml @@ -0,0 +1,8 @@ +common: + build_only: true + tags: + - drivers + - mdio +tests: + drivers.mdio.build: + platform_allow: qemu_cortex_m0 diff --git a/tests/drivers/build_all/modem/testcase.yaml b/tests/drivers/build_all/modem/testcase.yaml index 8b42363b4ff..89abfbd79df 100644 --- a/tests/drivers/build_all/modem/testcase.yaml +++ b/tests/drivers/build_all/modem/testcase.yaml @@ -63,7 +63,9 @@ tests: - CONFIG_UART_MUX=y drivers.modem.esp_at.build: extra_args: CONF_FILE=modem_esp_at.conf - platform_exclude: ip_k66f + platform_exclude: + - ip_k66f + - cy8cproto_062_4343w filter: CONFIG_SERIAL min_ram: 36 drivers.modem.esp_at.async.build: diff --git a/tests/drivers/build_all/modem/uart.dtsi b/tests/drivers/build_all/modem/uart.dtsi index 1600b6e165b..3d649a2ff60 100644 --- a/tests/drivers/build_all/modem/uart.dtsi +++ b/tests/drivers/build_all/modem/uart.dtsi @@ -47,10 +47,26 @@ test_quectel_bg9x: quectel_bg9x { mdm-reset-gpios = <&test_gpio 0 0>; }; +test_quectel_eg25_g: quectel_eg25_g { + compatible = "quectel,eg25-g"; + + mdm-reset-gpios = <&test_gpio 0 0>; +}; + test_gsm_ppp: gsm_ppp { compatible = "zephyr,gsm-ppp"; }; +test_telit_me910g1: telit_me910g1 { + compatible = "telit,me910g1"; + + mdm-power-gpios = <&test_gpio 0 0>; + mdm-reset-gpios = <&test_gpio 0 0>; + + mdm-dtr-gpios = <&test_gpio 0 0>; + mdm-ri-gpios = <&test_gpio 0 0>; +}; + test_esp_at: esp_at { compatible = "espressif,esp-at"; }; diff --git a/tests/drivers/build_all/pwm/testcase.yaml b/tests/drivers/build_all/pwm/testcase.yaml index 5a4477374ff..61d93f789d0 100644 --- a/tests/drivers/build_all/pwm/testcase.yaml +++ b/tests/drivers/build_all/pwm/testcase.yaml @@ -6,73 +6,51 @@ common: tests: drivers.pwm.cc13xx_cc26xx_timer.build: platform_allow: cc1352p1_launchxl - tags: pwm_cc13xx_cc26xx_timer drivers.pwm.gecko.build: platform_allow: efr32_radio_brd4250b - tags: pwm_gecko drivers.pwm.imx.build: platform_allow: colibri_imx7d_m4 - tags: pwm_imx drivers.pwm.litex.build: platform_allow: litex_vexriscv - tags: pwm_litex drivers.pwm.mcux.ftm.build: platform_allow: frdm_k22f - tags: pwm_mcux_ftm drivers.pwm.mcux.pwt.build: platform_allow: twr_ke18f - tags: pwm_mcux_pwt extra_configs: - CONFIG_PWM_CAPTURE=y drivers.pwm.mcux.tpm.build: platform_allow: frdm_kw41z - tags: pwm_mcux_tpm drivers.pwm.mcux.build: platform_allow: mimxrt1064_evk - tags: pwm_mcux drivers.pwm.mcux.sctimer.build: platform_allow: mimxrt685_evk_cm33 - tags: pwm_mcux_sctimer drivers.pwm.rv32m1.tpm.build: platform_allow: rv32m1_vega_ri5cy - tags: pwm_rv32m1_tpm drivers.pwm.sifive.build: platform_allow: hifive1_revb - tags: pwm_sifive drivers.pwm.npcx.build: platform_allow: npcx7m6fb_evb - tags: pwm_npcx drivers.pwm.nrf.sw.build: platform_allow: nrf51dk_nrf51422 - tags: pwm_nrf5_sw drivers.pwm.nrf.build: platform_allow: nrf52840dk_nrf52840 - tags: pwm_nrfx drivers.pwm.pca9685.build: platform_allow: nrf52840dk_nrf52840 extra_args: SHIELD=adafruit_pca9685 - tags: pwm_pca9685 drivers.pwm.sam0.tcc.build: platform_allow: atsame54_xpro - tags: pwm_sam0_tcc drivers.pwm.build.sam: platform_allow: - sam_e70_xplained - sam_v71b_xult - tags: pwm_sam drivers.pwm.stm32.build: platform_allow: disco_l475_iot1 - tags: pwm_stm32 drivers.pwm.xec.build: platform_allow: mec15xxevb_assy6853 - tags: pwm_xec drivers.pwm.build.xlnx: platform_allow: arty_a7_arm_designstart_m1 - tags: pwm_xlnx_axi_timer drivers.pwm.build.test: platform_allow: qemu_cortex_m3 - tags: pwm_test drivers.pwm.max31790.build: platform_allow: nucleo_f429zi extra_args: DTC_OVERLAY_FILE=max31790.overlay - tags: pwm_max31790 diff --git a/tests/drivers/build_all/regulator/i2c.dtsi b/tests/drivers/build_all/regulator/i2c.dtsi index 12988303a61..82668e03492 100644 --- a/tests/drivers/build_all/regulator/i2c.dtsi +++ b/tests/drivers/build_all/regulator/i2c.dtsi @@ -75,3 +75,18 @@ axp192@4 { LDO3 {}; }; }; + +max20335@5 { + compatible = "maxim,max20335"; + reg = <0x5>; + + regulators { + compatible = "maxim,max20335-regulator"; + + BUCK1 {}; + BUCK2 {}; + LDO1 {}; + LDO2 {}; + LDO3 {}; + }; +}; diff --git a/tests/drivers/build_all/sensor/Kconfig b/tests/drivers/build_all/sensor/Kconfig index 10730a1f50b..439e70051cb 100644 --- a/tests/drivers/build_all/sensor/Kconfig +++ b/tests/drivers/build_all/sensor/Kconfig @@ -3,7 +3,7 @@ config GENERIC_SENSOR_TEST bool "Compile and run the generic sensor tests" - depends on ZTEST && ZTEST_NEW_API + depends on ZTEST help Enables building and running the generic sensor test suite that will iterate through the device tree and run sample path tests on any diff --git a/tests/drivers/build_all/sensor/adc.dtsi b/tests/drivers/build_all/sensor/adc.dtsi index 52b41ce0f7c..e05c9bd0368 100644 --- a/tests/drivers/build_all/sensor/adc.dtsi +++ b/tests/drivers/build_all/sensor/adc.dtsi @@ -14,7 +14,27 @@ test_adc_mcp9700a: mcp9700a { io-channels = <&test_adc 0>; }; -test_adc_emul: adc { +test_voltage: voltage { + status = "okay"; + compatible = "voltage-divider"; + io-channels = <&test_adc 1>; + io-channel-names = "VOLTAGE"; + output-ohms = <47000>; /* R1 */ + full-ohms = <(100000 + 47000)>; /* R2 + R1 */ + power-gpios = <&test_gpio 0 0>; +}; + +test_current: current_amp { + status = "okay"; + compatible = "current-sense-amplifier"; + io-channels = <&test_adc 2>; + io-channel-names = "CURRENT_AMP"; + sense-resistor-micro-ohms = <10>; + sense-gain-mult = <1>; + sense-gain-div = <1>; +}; + +test_adc_emul: adc-emul { compatible = "zephyr,adc-emul"; nchannels = <2>; ref-internal-mv = <3300>; @@ -23,10 +43,9 @@ test_adc_emul: adc { status = "okay"; }; -test_ntc_thermistor_generic: ntc-thermistor-generic { +test_adc_ntc_thermistor_generic: ntc-thermistor-generic { compatible = "ntc-thermistor-generic"; - io-channels = <&adc0 0>; - r25-ohm = <10000>; + io-channels = <&test_adc 0>; pullup-uv = <3300000>; pullup-ohm = <0>; pulldown-ohm = <10000>; @@ -34,10 +53,18 @@ test_ntc_thermistor_generic: ntc-thermistor-generic { zephyr,compensation-table = <0 0>, <1 1>; }; -test_epcos_b57861s0103a039: epcos-b57861s0103a039 { +test_adc_epcos_b57861s0103a039: epcos-b57861s0103a039 { compatible = "epcos,b57861s0103a039"; - io-channels = <&adc0 0>; - r25-ohm = <10000>; + io-channels = <&test_adc 0>; + pullup-uv = <3300000>; + pullup-ohm = <0>; + pulldown-ohm = <10000>; + connected-positive; +}; + +test_murata_ncp15wb473: murata-ncp15wb473 { + compatible = "murata,ncp15wb473"; + io-channels = <&test_adc 0>; pullup-uv = <3300000>; pullup-ohm = <0>; pulldown-ohm = <10000>; diff --git a/tests/drivers/build_all/sensor/app.overlay b/tests/drivers/build_all/sensor/app.overlay index 36bb97915d7..9f7c604bf30 100644 --- a/tests/drivers/build_all/sensor/app.overlay +++ b/tests/drivers/build_all/sensor/app.overlay @@ -32,6 +32,24 @@ zephyr,resolution = <12>; }; + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1_6"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = <0>; + zephyr,resolution = <12>; + }; + + channel@2 { + reg = <2>; + zephyr,gain = "ADC_GAIN_1_6"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = <0>; + zephyr,resolution = <12>; + }; + #include "adc.dtsi" }; @@ -101,7 +119,10 @@ <&test_gpio 0 0>, <&test_gpio 0 0>, <&test_gpio 0 0>, - <&test_gpio 0 0>; /* 0x24 */ + <&test_gpio 0 0>, + <&test_gpio 0 0>, /* 0x25 */ + <&test_gpio 0 0>, /* 0x26 */ + <&test_gpio 0 0>; /* 0x27 */ #include "spi.dtsi" }; @@ -124,12 +145,16 @@ #include "w1.dtsi" }; - dht22 { - compatible = "aosong,dht"; + test_i3c: i3c@f0cacc1a { + #address-cells = <3>; + #size-cells = <0>; + compatible = "vnd,i3c"; + reg = <0xf0cacc1a 0x1000>; status = "okay"; - dio-gpios = <&test_gpio 0 0>; - /* dht22; */ + + #include "i3c.dtsi" }; + }; }; diff --git a/tests/drivers/build_all/sensor/gpio.dtsi b/tests/drivers/build_all/sensor/gpio.dtsi index 6994cc23b09..95626ae9015 100644 --- a/tests/drivers/build_all/sensor/gpio.dtsi +++ b/tests/drivers/build_all/sensor/gpio.dtsi @@ -10,3 +10,10 @@ test_gpio_sm351lt: sm351lt0 { compatible = "honeywell,sm351lt"; gpios = <&test_gpio 0 0>; }; + +test_gpio_dht22: dht22 { + compatible = "aosong,dht"; + status = "okay"; + dio-gpios = <&test_gpio 0 0>; + /* dht22; */ +}; diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index fd957bc5b9b..6ad5ac8703e 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -6,6 +6,18 @@ * Application overlay for i2c devices */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + /**************************************** * PLEASE KEEP REG ADDRESSES SEQUENTIAL * ***************************************/ @@ -88,6 +100,7 @@ test_i2c_bmg160: bmg160@c { test_i2c_bmm150: bmm150@d { compatible = "bosch,bmm150"; reg = <0xd>; + drdy-gpios = <&test_gpio 0 0>; }; test_i2c_hmc5883l: hmc5883l@e { @@ -120,7 +133,7 @@ test_i2c_mpu9250: mpu9250@12 { gyro-dlpf = <5>; gyro-fs = <250>; accel-fs = <2>; - accel-dlpf="5.05"; + accel-dlpf = "5.05"; }; test_i2c_ina219: ina219@13 { @@ -250,6 +263,8 @@ test_i2c_iis2dlpc: iis2dlpc@27 { compatible = "st,iis2dlpc"; reg = <0x27>; drdy-gpios = <&test_gpio 0 0>; + tap-mode = ; + power-mode = ; }; test_i2c_iis2mdc: iis2mdc@28 { @@ -262,6 +277,8 @@ test_i2c_ism330dhcx: ism330dhcx@29 { compatible = "st,ism330dhcx"; reg = <0x29>; drdy-gpios = <&test_gpio 0 0>; + accel-odr = ; + gyro-odr = ; }; test_i2c_lis2dh: lis2dh@2a { @@ -269,6 +286,9 @@ test_i2c_lis2dh: lis2dh@2a { reg = <0x2a>; irq-gpios = <&test_gpio 0 0>; /* disconnect-sdo-sa0-pull-up; */ + int1-gpio-config = ; + int2-gpio-config = ; + anym-mode = ; }; test_i2c_lis2dh12: lis2dh12@2b { @@ -282,12 +302,19 @@ test_i2c_lis2ds12: lis2ds12@2c { compatible = "st,lis2ds12"; reg = <0x2c>; irq-gpios = <&test_gpio 0 0>; + power-mode = ; + odr = ; }; test_i2c_lis2dw12: lis2dw12@2d { compatible = "st,lis2dw12"; reg = <0x2d>; irq-gpios = <&test_gpio 0 0>; + wakeup-duration = ; + ff-threshold = ; + tap-mode = ; + power-mode = ; + bw-filt = ; }; test_i2c_lis2mdl: lis2mdl@2e { @@ -318,6 +345,7 @@ test_i2c_lps22hh: lps22hh@32 { compatible = "st,lps22hh"; reg = <0x32>; drdy-gpios = <&test_gpio 0 0>; + odr = ; }; test_i2c_lps25hb_press: lps25hb-press@33 { @@ -361,6 +389,12 @@ test_i2c_lsm6dso: lsm6dso@39 { compatible = "st,lsm6dso"; reg = <0x39>; irq-gpios = <&test_gpio 0 0>; + accel-pm = ; + accel-range = ; + accel-odr = ; + gyro-pm = ; + gyro-range = ; + gyro-odr = ; }; test_i2c_lsm9ds0_gyro: lsm9ds0-gyro@3a { @@ -471,6 +505,8 @@ test_i2c_iis2iclx: iis2iclx@4c { reg = <0x4c>; drdy-gpios = <&test_gpio 0 0>; int-pin = <1>; + range = ; + odr = ; }; test_i2c_wsen_hids: wsen_hids@4d { @@ -527,6 +563,7 @@ test_i2c_bmi160: bmi160@52 { test_i2c_bmi270: bmi270@53 { compatible = "bosch,bmi270"; reg = <0x53>; + irq-gpios = <&test_gpio 0 0>; }; test_i2c_fdc2x1x: fdc2x1x@54 { @@ -688,12 +725,21 @@ test_i2c_lsm6dso16is: lsm6dso16is@68 { compatible = "st,lsm6dso16is"; reg = <0x68>; irq-gpios = <&test_gpio 0 0>; + accel-range = ; + accel-odr = ; + gyro-range = ; + gyro-odr = ; }; test_i2c_lsm6dsv16x: lsm6dsv16x@69 { compatible = "st,lsm6dsv16x"; reg = <0x69>; - irq-gpios = <&test_gpio 0 0>; + int1-gpios = <&test_gpio 0 0>; + int2-gpios = <&test_gpio 0 0>; + accel-range = ; + accel-odr = ; + gyro-range = ; + gyro-odr = ; }; test_i2c_mcp9600: mcp9600@6a { @@ -707,7 +753,7 @@ test_i2c_tcs3400: tcs3400@6b { int-gpios = <&test_gpio 0 0>; }; -test_tcn75a: tcn75a@6c { +test_i2c_tcn75a: tcn75a@6c { compatible = "microchip,tcn75a"; reg = <0x6c>; alert-gpios = <&test_gpio 0 0>; @@ -735,8 +781,80 @@ test_i2c_bmi08x_gyro: bmi08x@6e { gyro-fs = <1000>; }; -test_i2c_ist8310@6f { +test_i2c_ist8310: ist8310@6f { compatible = "isentek,ist8310"; reg = <0x6f>; status = "okay"; }; + +test_i2c_f75303: f75303@70 { + compatible = "fintek,f75303"; + reg = <0x70>; +}; + +test_i2c_tsl2540: tsl2540@71 { + compatible = "ams,tsl2540"; + reg = <0x71>; + int-gpios = <&test_gpio 0 0>; +}; + +test_i2c_adltc2990@72 { + compatible = "adi,adltc2990"; + reg = <0x72>; + status = "okay"; + measurement-mode = <7 3>; + pins-v1-v2-current-resistor = <1>; + pin-v1-voltage-divider-resistors = <100 10>; + pin-v2-voltage-divider-resistors = <100 10>; + pin-v3-voltage-divider-resistors = <100 100>; + pin-v4-voltage-divider-resistors = <0 1>; +}; + +test_i2c_hm330x@73 { + compatible = "seeed,hm330x"; + reg = <0x73>; + status = "okay"; +}; + +test_i2c_amd_sb_tsi: amd_sb_tsi@74 { + compatible = "amd,sb-tsi"; + reg = <0x74>; +}; + +test_i2c_mc3419: mc3419@75 { + compatible = "memsic,mc3419"; + reg = <0x75>; + int-gpios = <&test_gpio 0 0>; +}; + +test_i2c_ltrf216a0: ltrf216a@76 { + compatible = "ltr,f216a"; + reg = <0x76>; +}; + +test_i2c_adxl367: adxl367@77 { + compatible = "adi,adxl367"; + reg = <0x77>; + odr = <4>; + int1-gpios = <&test_gpio 0 0>; +}; + +test_i2c_tsl2561: tsl2561@78 { + compatible = "ams,tsl2561"; + reg = <0x78>; +}; + +test_i2c_lps22df: lps22df@79 { + compatible = "st,lps22df"; + reg = <0x79>; + drdy-gpios = <&test_gpio 0 0>; + status = "okay"; + odr = ; + lpf = ; + avg = ; +}; + +test_i2c_hs300x: hs300x@79 { + compatible = "renesas,hs300x"; + reg = <0x79>; +}; diff --git a/tests/drivers/build_all/sensor/i3c.dtsi b/tests/drivers/build_all/sensor/i3c.dtsi new file mode 100644 index 00000000000..42adb3fb175 --- /dev/null +++ b/tests/drivers/build_all/sensor/i3c.dtsi @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + * + * Application overlay for i3c devices + */ + +/**************************************** + * PLEASE KEEP REG ADDRESSES SEQUENTIAL * + ***************************************/ + +test_i3c_lps22hh: lps22hh@100000803E0000001 { + compatible = "st,lps22hh"; + reg = <0x1 0x00000803 0xE0000001>; + assigned-address = <0x1>; + drdy-gpios = <&test_gpio 0 0>; +}; + +test_i3c_lps22df: lps22df@200000803E0000002 { + compatible = "st,lps22df"; + reg = <0x2 0x00000803 0xE0000002>; + assigned-address = <0x2>; + drdy-gpios = <&test_gpio 0 0>; +}; diff --git a/tests/drivers/build_all/sensor/prj.conf b/tests/drivers/build_all/sensor/prj.conf index b29c11a64bb..67172951b7d 100644 --- a/tests/drivers/build_all/sensor/prj.conf +++ b/tests/drivers/build_all/sensor/prj.conf @@ -6,6 +6,7 @@ CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 CONFIG_ADC=y CONFIG_GPIO=y CONFIG_I2C=y +CONFIG_I3C=y CONFIG_SERIAL=y CONFIG_SPI=y CONFIG_W1=y diff --git a/tests/drivers/build_all/sensor/sensors_no_default.conf b/tests/drivers/build_all/sensor/sensors_no_default.conf new file mode 100644 index 00000000000..ac42f5db80f --- /dev/null +++ b/tests/drivers/build_all/sensor/sensors_no_default.conf @@ -0,0 +1,2 @@ +CONFIG_VL53L1X_INTERRUPT_MODE=n +CONFIG_VL53L1X_XSHUT=n diff --git a/tests/drivers/build_all/sensor/sensors_trigger_global.conf b/tests/drivers/build_all/sensor/sensors_trigger_global.conf index a18d55ab42e..c42b4fa951e 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_global.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_global.conf @@ -1,6 +1,7 @@ CONFIG_ADT7310_TRIGGER_GLOBAL_THREAD=y CONFIG_ADT7420_TRIGGER_GLOBAL_THREAD=y CONFIG_ADXL362_TRIGGER_GLOBAL_THREAD=y +CONFIG_ADXL367_TRIGGER_GLOBAL_THREAD=y CONFIG_ADXL372_TRIGGER_GLOBAL_THREAD=y CONFIG_AMG88XX_TRIGGER_GLOBAL_THREAD=y CONFIG_APDS9960_TRIGGER_GLOBAL_THREAD=y @@ -10,6 +11,7 @@ CONFIG_BMI08X_ACCEL_TRIGGER_GLOBAL_THREAD=y CONFIG_BMI08X_GYRO_TRIGGER_GLOBAL_THREAD=y CONFIG_BMI160_TRIGGER_GLOBAL_THREAD=y CONFIG_BMI270_TRIGGER_GLOBAL_THREAD=y +CONFIG_BMM150_TRIGGER_GLOBAL_THREAD=y CONFIG_BMP388_TRIGGER_GLOBAL_THREAD=y CONFIG_BQ274XX_TRIGGER_GLOBAL_THREAD=y CONFIG_CCS811_TRIGGER_GLOBAL_THREAD=y @@ -34,6 +36,7 @@ CONFIG_LIS2DS12_TRIGGER_GLOBAL_THREAD=y CONFIG_LIS2DW12_TRIGGER_GLOBAL_THREAD=y CONFIG_LIS2MDL_TRIGGER_GLOBAL_THREAD=y CONFIG_LIS3MDL_TRIGGER_GLOBAL_THREAD=y +CONFIG_LPS22DF_TRIGGER_GLOBAL_THREAD=y CONFIG_LPS22HH_TRIGGER_GLOBAL_THREAD=y CONFIG_LSM6DSL_TRIGGER_GLOBAL_THREAD=y CONFIG_LSM6DSO_TRIGGER_GLOBAL_THREAD=y @@ -47,8 +50,10 @@ CONFIG_SM351LT_TRIGGER_GLOBAL_THREAD=y CONFIG_STTS751_TRIGGER_GLOBAL_THREAD=y CONFIG_SX9500_TRIGGER_GLOBAL_THREAD=y CONFIG_TCN75A_TRIGGER_GLOBAL_THREAD=y +CONFIG_TMAG5170_TRIGGER_GLOBAL_THREAD=y CONFIG_TMD2620_TRIGGER_GLOBAL_THREAD=y CONFIG_TMP007_TRIGGER_GLOBAL_THREAD=y +CONFIG_TSL2540_TRIGGER_GLOBAL_THREAD=y CONFIG_VCNL4040_TRIGGER_GLOBAL_THREAD=y CONFIG_WSEN_HIDS_TRIGGER_GLOBAL_THREAD=y CONFIG_WSEN_TIDS_TRIGGER_GLOBAL_THREAD=y diff --git a/tests/drivers/build_all/sensor/sensors_trigger_none.conf b/tests/drivers/build_all/sensor/sensors_trigger_none.conf index b374ff86525..9c46cb3637e 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_none.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_none.conf @@ -1,6 +1,7 @@ CONFIG_ADT7310_TRIGGER_NONE=y CONFIG_ADT7420_TRIGGER_NONE=y CONFIG_ADXL362_TRIGGER_NONE=y +CONFIG_ADXL367_TRIGGER_NONE=y CONFIG_ADXL372_TRIGGER_NONE=y CONFIG_AMG88XX_TRIGGER_NONE=y CONFIG_APDS9960_TRIGGER_NONE=y @@ -10,6 +11,7 @@ CONFIG_BMI08X_ACCEL_TRIGGER_NONE=y CONFIG_BMI08X_GYRO_TRIGGER_NONE=y CONFIG_BMI160_TRIGGER_NONE=y CONFIG_BMI270_TRIGGER_NONE=y +CONFIG_BMM150_TRIGGER_NONE=y CONFIG_BMP388_TRIGGER_NONE=y CONFIG_BQ274XX_TRIGGER_NONE=y CONFIG_CCS811_TRIGGER_NONE=y @@ -34,6 +36,7 @@ CONFIG_LIS2DS12_TRIGGER_NONE=y CONFIG_LIS2DW12_TRIGGER_NONE=y CONFIG_LIS2MDL_TRIGGER_NONE=y CONFIG_LIS3MDL_TRIGGER_NONE=y +CONFIG_LPS22DF_TRIGGER_NONE=y CONFIG_LPS22HH_TRIGGER_NONE=y CONFIG_LSM6DSL_TRIGGER_NONE=y CONFIG_LSM6DSO_TRIGGER_NONE=y @@ -47,8 +50,10 @@ CONFIG_SM351LT_TRIGGER_NONE=y CONFIG_STTS751_TRIGGER_NONE=y CONFIG_SX9500_TRIGGER_NONE=y CONFIG_TCN75A_TRIGGER_NONE=y +CONFIG_TMAG5170_TRIGGER_NONE=y CONFIG_TMD2620_TRIGGER_NONE=y CONFIG_TMP007_TRIGGER_NONE=y +CONFIG_TSL2540_TRIGGER_NONE=y CONFIG_VCNL4040_TRIGGER_NONE=y CONFIG_WSEN_HIDS_TRIGGER_NONE=y CONFIG_WSEN_TIDS_TRIGGER_NONE=y diff --git a/tests/drivers/build_all/sensor/sensors_trigger_own.conf b/tests/drivers/build_all/sensor/sensors_trigger_own.conf index 04892cf8ad5..5ecacb03d9a 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_own.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_own.conf @@ -1,6 +1,7 @@ CONFIG_ADT7310_TRIGGER_OWN_THREAD=y CONFIG_ADT7420_TRIGGER_OWN_THREAD=y CONFIG_ADXL362_TRIGGER_OWN_THREAD=y +CONFIG_ADXL367_TRIGGER_OWN_THREAD=y CONFIG_ADXL372_TRIGGER_OWN_THREAD=y CONFIG_AMG88XX_TRIGGER_OWN_THREAD=y CONFIG_BMA280_TRIGGER_OWN_THREAD=y @@ -9,6 +10,7 @@ CONFIG_BMI08X_ACCEL_TRIGGER_OWN_THREAD=y CONFIG_BMI08X_GYRO_TRIGGER_OWN_THREAD=y CONFIG_BMI160_TRIGGER_OWN_THREAD=y CONFIG_BMI270_TRIGGER_OWN_THREAD=y +CONFIG_BMM150_TRIGGER_OWN_THREAD=y CONFIG_BMP388_TRIGGER_OWN_THREAD=y CONFIG_BQ274XX_TRIGGER_OWN_THREAD=y CONFIG_CCS811_TRIGGER_OWN_THREAD=y @@ -32,11 +34,13 @@ CONFIG_LIS2DS12_TRIGGER_OWN_THREAD=y CONFIG_LIS2DW12_TRIGGER_OWN_THREAD=y CONFIG_LIS2MDL_TRIGGER_OWN_THREAD=y CONFIG_LIS3MDL_TRIGGER_OWN_THREAD=y +CONFIG_LPS22DF_TRIGGER_OWN_THREAD=y CONFIG_LPS22HH_TRIGGER_OWN_THREAD=y CONFIG_LSM6DSL_TRIGGER_OWN_THREAD=y CONFIG_LSM6DSO_TRIGGER_OWN_THREAD=y CONFIG_LSM6DSO16IS_TRIGGER_OWN_THREAD=y CONFIG_LSM6DSV16X_TRIGGER_OWN_THREAD=y +CONFIG_MC3419_TRIGGER_OWN_THREAD=y CONFIG_MCP9808_TRIGGER_OWN_THREAD=y CONFIG_MPU6050_TRIGGER_OWN_THREAD=y CONFIG_MPU9250_TRIGGER_OWN_THREAD=y @@ -45,7 +49,9 @@ CONFIG_SM351LT_TRIGGER_OWN_THREAD=y CONFIG_STTS751_TRIGGER_OWN_THREAD=y CONFIG_SX9500_TRIGGER_OWN_THREAD=y CONFIG_TCN75A_TRIGGER_OWN_THREAD=y +CONFIG_TMAG5170_TRIGGER_OWN_THREAD=y CONFIG_TMP007_TRIGGER_OWN_THREAD=y +CONFIG_TSL2540_TRIGGER_OWN_THREAD=y CONFIG_VCNL4040_TRIGGER_OWN_THREAD=y CONFIG_WSEN_HIDS_TRIGGER_OWN_THREAD=y CONFIG_WSEN_TIDS_TRIGGER_OWN_THREAD=y diff --git a/tests/drivers/build_all/sensor/spi.dtsi b/tests/drivers/build_all/sensor/spi.dtsi index b352cd193fd..cd7bf1b66ec 100644 --- a/tests/drivers/build_all/sensor/spi.dtsi +++ b/tests/drivers/build_all/sensor/spi.dtsi @@ -162,6 +162,7 @@ test_spi_bmi270: bmi270@15 { compatible = "bosch,bmi270"; reg = <0x15>; spi-max-frequency = <0>; + irq-gpios = <&test_gpio 0 0>; }; test_spi_bmp388: bmp388@16 { @@ -225,6 +226,7 @@ test_spi_bmm150: bmm150@1d { compatible = "bosch,bmm150"; reg = <0x1d>; spi-max-frequency = <0>; + drdy-gpios = <&test_gpio 0 0>; }; test_spi_hts221: hts221@1e { @@ -259,7 +261,8 @@ test_spi_lsm6dsv16x: lsm6dsv16x@22 { compatible = "st,lsm6dsv16x"; reg = <0x22>; spi-max-frequency = <0>; - irq-gpios = <&test_gpio 0 0>; + int1-gpios = <&test_gpio 0 0>; + int2-gpios = <&test_gpio 0 0>; }; test_spi_bmi08x_accel: bmi08x@23 { @@ -285,3 +288,27 @@ test_spi_bmi08x_gyro: bmi08x@24 { gyro-hz = "1000_116"; gyro-fs = <1000>; }; + +test_spi_tmag5170: tmag5170@25 { + compatible = "ti,tmag5170"; + reg = <0x25>; + spi-max-frequency = <0>; + int-gpios = <&test_gpio 0 0>; + operating-mode = <1>; +}; + +test_spi_adxl367: adxl367@26 { + compatible = "adi,adxl367"; + reg = <0x26>; + spi-max-frequency = <0>; + odr = <4>; + int1-gpios = <&test_gpio 0 0>; +}; + +test_spi_lps22df: lps22df@27 { + compatible = "st,lps22df"; + reg = <0x27>; + spi-max-frequency = <0>; + drdy-gpios = <&test_gpio 0 0>; + status = "okay"; +}; diff --git a/tests/drivers/build_all/sensor/src/generic_test.c b/tests/drivers/build_all/sensor/src/generic_test.c index 0df8b953da9..9a1dc537535 100644 --- a/tests/drivers/build_all/sensor/src/generic_test.c +++ b/tests/drivers/build_all/sensor/src/generic_test.c @@ -8,12 +8,24 @@ #include #include #include +#include #include #include #include LOG_MODULE_REGISTER(generic_test); +/** + * A union of all sensor data types. + */ +union sensor_data_union { + struct sensor_three_axis_data three_axis; + struct sensor_occurrence_data occurrence; + struct sensor_q31_data q31; + struct sensor_byte_data byte; + struct sensor_uint64_data uint64; +}; + /* * Set up an RTIO context that can be shared for all sensors */ @@ -45,8 +57,8 @@ static void before(void *args) iodev_read_config.sensor = NULL; /* Wipe the mempool by marking every block free */ - zassert_ok(sys_bitarray_clear_region(sensor_read_rtio_ctx_block_pool.mempool->bitmap, - sensor_read_rtio_ctx_block_pool.mempool->num_blocks, + zassert_ok(sys_bitarray_clear_region(sensor_read_rtio_ctx.block_pool->bitmap, + sensor_read_rtio_ctx.block_pool->info.num_blocks, 0)); /* Flush the SQ and CQ */ @@ -176,36 +188,72 @@ static void run_generic_test(const struct device *dev) /* Release the CQE */ rtio_cqe_release(&sensor_read_rtio_ctx, cqe); - enum sensor_channel channel; - sensor_frame_iterator_t fit = {0}; - sensor_channel_iterator_t cit = {0}; const struct sensor_decoder_api *decoder; - int8_t shift; - q31_t q; + union sensor_data_union decoded_data; zassert_ok(sensor_get_decoder(dev, &decoder)); - /* Decode the buffer and verify all channels */ - while (decoder->decode(buf, &fit, &cit, &channel, &q, 1) > 0) { - zassert_true(channel_table[channel].supported); - zassert_false(channel_table[channel].received); - channel_table[channel].received = true; + /* Loop through each channel */ + for (int ch = 0; ch < ARRAY_SIZE(channel_table); ch++) { + if (!channel_table[ch].supported) { + continue; + } - zassert_ok(decoder->get_shift(buf, channel, &shift)); + struct sensor_decode_context ctx = + SENSOR_DECODE_CONTEXT_INIT(decoder, buf, ch, 0); + + rv = sensor_decode(&ctx, &decoded_data, 1); + zassert_equal(1, rv, "Could not decode (error %d, ch %d, iteration %d/%d)", + rv, ch, iteration + 1, + CONFIG_GENERIC_SENSOR_TEST_NUM_EXPECTED_VALS); + + channel_table[ch].received = true; + + /* Retrieve the actual value */ + q31_t q; + int8_t shift; + + switch (ch) { + /* Special handling to break out triplet samples. */ + case SENSOR_CHAN_MAGN_X: + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_GYRO_X: + q = decoded_data.three_axis.readings[0].x; + shift = decoded_data.three_axis.shift; + break; + case SENSOR_CHAN_MAGN_Y: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_GYRO_Y: + q = decoded_data.three_axis.readings[0].y; + shift = decoded_data.three_axis.shift; + break; + case SENSOR_CHAN_MAGN_Z: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_GYRO_Z: + q = decoded_data.three_axis.readings[0].z; + shift = decoded_data.three_axis.shift; + break; + + /* Default case for single Q31 samples */ + default: + q = decoded_data.q31.readings[0].value; + shift = decoded_data.q31.shift; + break; + } /* Align everything to be a 64-bit Q32.32 number for comparison */ int64_t expected_shifted = - (int64_t)channel_table[channel].expected_values[iteration] - << channel_table[channel].expected_value_shift; + (int64_t)channel_table[ch].expected_values[iteration] + << channel_table[ch].expected_value_shift; int64_t actual_shifted = (int64_t)q << shift; - int64_t epsilon_shifted = (int64_t)channel_table[channel].epsilon - << channel_table[channel].expected_value_shift; + int64_t epsilon_shifted = (int64_t)channel_table[ch].epsilon + << channel_table[ch].expected_value_shift; zassert_within(expected_shifted, actual_shifted, epsilon_shifted, "Expected %lld, got %lld (shift %d, ch %d, iteration %d/%d, " "Error %lld, Epsilon %lld)", - expected_shifted, actual_shifted, shift, channel, - iteration + 1, CONFIG_GENERIC_SENSOR_TEST_NUM_EXPECTED_VALS, + expected_shifted, actual_shifted, shift, ch, iteration + 1, + CONFIG_GENERIC_SENSOR_TEST_NUM_EXPECTED_VALS, expected_shifted - actual_shifted, epsilon_shifted); } @@ -221,7 +269,8 @@ static void run_generic_test(const struct device *dev) } } - zassert_equal(0, missing_channel_count); + zassert_equal(0, missing_channel_count, "%d channel(s) not received", + missing_channel_count); } } @@ -233,6 +282,7 @@ static void run_generic_test(const struct device *dev) /* Iterate through each of the emulated buses and create a test for each device. */ DT_FOREACH_CHILD_STATUS_OKAY(DT_NODELABEL(test_i2c), DECLARE_ZTEST_PER_DEVICE) +DT_FOREACH_CHILD_STATUS_OKAY(DT_NODELABEL(test_i3c), DECLARE_ZTEST_PER_DEVICE) DT_FOREACH_CHILD_STATUS_OKAY(DT_NODELABEL(test_spi), DECLARE_ZTEST_PER_DEVICE) ZTEST_SUITE(generic, NULL, NULL, before, NULL, NULL); diff --git a/tests/drivers/build_all/sensor/testcase.yaml b/tests/drivers/build_all/sensor/testcase.yaml index bfc423b65f6..2bf581e58da 100644 --- a/tests/drivers/build_all/sensor/testcase.yaml +++ b/tests/drivers/build_all/sensor/testcase.yaml @@ -2,7 +2,11 @@ common: tags: - drivers - sensors - platform_allow: native_posix + platform_allow: + - native_posix + - native_sim + integration_platforms: + - native_sim build_only: true tests: sensors.build.sensorhub: @@ -13,6 +17,8 @@ tests: extra_args: OVERLAY_CONFIG=sensors_trigger_global.conf sensors.build.trigger.none: extra_args: OVERLAY_CONFIG=sensors_trigger_none.conf + sensors.build.no_default: + extra_args: OVERLAY_CONFIG=sensors_no_default.conf sensors.build: tags: sensors sensors.build.pm: @@ -24,7 +30,6 @@ tests: extra_configs: - CONFIG_GENERIC_SENSOR_TEST=y - CONFIG_ZTEST=y - - CONFIG_ZTEST_NEW_API=y - CONFIG_EMUL=y - CONFIG_NATIVE_UART_0_ON_STDINOUT=y - CONFIG_SENSOR_ASYNC_API=y diff --git a/tests/drivers/build_all/sensor/uart.dtsi b/tests/drivers/build_all/sensor/uart.dtsi index 9d63ee3555f..05a2634f24a 100644 --- a/tests/drivers/build_all/sensor/uart.dtsi +++ b/tests/drivers/build_all/sensor/uart.dtsi @@ -7,26 +7,30 @@ * Application overlay for uart devices */ -test_uart_mhz19b { +test_uart_mhz19b: mhz19b { compatible = "winsen,mhz19b"; maximum-range = <10000>; abc-on; }; -test_uart_pms7003 { +test_uart_pms7003: pms7003 { compatible = "plantower,pms7003"; }; -test_uart_grow_r502a { +grow_r502a { #address-cells=<1>; #size-cells=<0>; - grow_r502a@0 { + test_uart_grow_r502a: grow_r502a@0 { compatible = "hzgrow,r502a"; reg = <0x0>; int-gpios = <&test_gpio 0 0>; }; }; -test_uart_a01nyub { +test_uart_a01nyub: a01nyub { compatible = "dfrobot,a01nyub"; }; + +test_uart_explorir_m: explorir-m { + compatible = "gss,explorir-m"; +}; diff --git a/tests/drivers/build_all/sensor/w1.dtsi b/tests/drivers/build_all/sensor/w1.dtsi index 49734624231..a7a6a554eb0 100644 --- a/tests/drivers/build_all/sensor/w1.dtsi +++ b/tests/drivers/build_all/sensor/w1.dtsi @@ -6,7 +6,7 @@ * Application overlay for w1 devices */ -test-w1-ds18b20 { +test_w1_ds18b20: ds18b20 { compatible = "maxim,ds18b20"; family-code = <0x28>; resolution = <12>; diff --git a/tests/drivers/build_all/uart/testcase.yaml b/tests/drivers/build_all/uart/testcase.yaml index c652d1cb767..6c69f06e720 100644 --- a/tests/drivers/build_all/uart/testcase.yaml +++ b/tests/drivers/build_all/uart/testcase.yaml @@ -7,6 +7,5 @@ tests: drivers.uart.build: # will cover drivers without in-tree boards platform_allow: qemu_cortex_m3 - tags: uart_cdns extra_configs: - CONFIG_SERIAL=y diff --git a/tests/drivers/build_all/watchdog/testcase.yaml b/tests/drivers/build_all/watchdog/testcase.yaml index 3102453a740..82f8cd027bd 100644 --- a/tests/drivers/build_all/watchdog/testcase.yaml +++ b/tests/drivers/build_all/watchdog/testcase.yaml @@ -1,9 +1,10 @@ common: build_only: true - tags: drivers watchdog + tags: + - drivers + - watchdog tests: drivers.watchdog.build: # will cover drivers without in-tree boards platform_allow: qemu_cortex_m3 - tags: wdt_xilinx_axi extra_args: "CONFIG_WATCHDOG=y" diff --git a/tests/drivers/can/api/CMakeLists.txt b/tests/drivers/can/api/CMakeLists.txt index 5468c766cd3..fb936332e04 100644 --- a/tests/drivers/can/api/CMakeLists.txt +++ b/tests/drivers/can/api/CMakeLists.txt @@ -8,3 +8,4 @@ target_sources(app PRIVATE src/common.c) target_sources(app PRIVATE src/classic.c) target_sources(app PRIVATE src/utilities.c) target_sources_ifdef(CONFIG_CAN_FD_MODE app PRIVATE src/canfd.c) +target_sources_ifdef(CONFIG_CAN_STATS app PRIVATE src/stats.c) diff --git a/tests/drivers/can/api/prj.conf b/tests/drivers/can/api/prj.conf index 8fa4d640945..a163dc5077f 100644 --- a/tests/drivers/can/api/prj.conf +++ b/tests/drivers/can/api/prj.conf @@ -1,8 +1,9 @@ CONFIG_CAN=y CONFIG_CAN_FD_MODE=y CONFIG_CAN_AUTO_BUS_OFF_RECOVERY=n +CONFIG_STATS=y +CONFIG_CAN_STATS=y CONFIG_TEST_USERSPACE=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y # The canfd test suite may be skipped CONFIG_ZTEST_VERIFY_RUN_ALL=n diff --git a/tests/drivers/can/api/src/canfd.c b/tests/drivers/can/api/src/canfd.c index 852d1fad7e1..d8dfb8b3c31 100644 --- a/tests/drivers/can/api/src/canfd.c +++ b/tests/drivers/can/api/src/canfd.c @@ -235,7 +235,7 @@ ZTEST(canfd, test_get_capabilities) err = can_get_capabilities(can_dev, &cap); zassert_equal(err, 0, "failed to get CAN capabilities (err %d)", err); zassert_not_equal(cap & (CAN_MODE_LOOPBACK | CAN_MODE_FD), 0, - "CAN-FD loopback mode not supported"); + "CAN FD loopback mode not supported"); } /** @@ -248,7 +248,7 @@ ZTEST(canfd, test_send_receive_classic) } /** - * @brief Test send/receive with standard (11-bit) CAN IDs and CAN-FD frames. + * @brief Test send/receive with standard (11-bit) CAN IDs and CAN FD frames. */ ZTEST(canfd, test_send_receive_fd) { @@ -257,7 +257,7 @@ ZTEST(canfd, test_send_receive_fd) } /** - * @brief Test send/receive with (11-bit) CAN IDs, mixed classic and CAN-FD frames. + * @brief Test send/receive with (11-bit) CAN IDs, mixed classic and CAN FD frames. */ ZTEST(canfd, test_send_receive_mixed) { @@ -290,7 +290,7 @@ static void check_filters_preserved_between_modes(can_mode_t first, can_mode_t s err = can_start(can_dev); zassert_equal(err, 0, "failed to start CAN controller (err %d)", err); - /* Add classic CAN and CAN-FD filter */ + /* Add classic CAN and CAN FD filter */ filter_id_1 = add_rx_msgq(can_dev, &test_std_filter_1); filter_id_2 = add_rx_msgq(can_dev, &test_std_fdf_filter_2); @@ -301,7 +301,7 @@ static void check_filters_preserved_between_modes(can_mode_t first, can_mode_t s assert_frame_equal(&frame, &test_std_frame_1, 0); if ((first & CAN_MODE_FD) != 0) { - /* Verify CAN-FD filter in first mode */ + /* Verify CAN FD filter in first mode */ send_test_frame(can_dev, &test_std_fdf_frame_2); err = k_msgq_get(&can_msgq, &frame, TEST_RECEIVE_TIMEOUT); zassert_equal(err, 0, "receive timeout"); @@ -329,14 +329,14 @@ static void check_filters_preserved_between_modes(can_mode_t first, can_mode_t s assert_frame_equal(&frame, &test_std_frame_1, 0); if ((second & CAN_MODE_FD) != 0) { - /* Verify CAN-FD filter in second mode */ + /* Verify CAN FD filter in second mode */ send_test_frame(can_dev, &test_std_fdf_frame_2); err = k_msgq_get(&can_msgq, &frame, TEST_RECEIVE_TIMEOUT); zassert_equal(err, 0, "receive timeout"); assert_frame_equal(&frame, &test_std_fdf_frame_2, 0); } - /* Stop controller and restore CAN-FD loopback mode */ + /* Stop controller and restore CAN FD loopback mode */ err = can_stop(can_dev); zassert_equal(err, 0, "failed to stop CAN controller (err %d)", err); @@ -356,7 +356,7 @@ static void check_filters_preserved_between_modes(can_mode_t first, can_mode_t s /** * @brief Test that CAN RX filters are preserved through CAN controller mode changes between classic - * CAN and CAN-FD. + * CAN and CAN FD. */ ZTEST_USER(canfd, test_filters_preserved_through_classic_to_fd_mode_change) { @@ -364,7 +364,7 @@ ZTEST_USER(canfd, test_filters_preserved_through_classic_to_fd_mode_change) } /** - * @brief Test that CAN RX filters are preserved through CAN controller mode changes between CAN-FD + * @brief Test that CAN RX filters are preserved through CAN controller mode changes between CAN FD * and classic CAN. */ ZTEST_USER(canfd, test_filters_preserved_through_fd_to_classic_mode_change) @@ -389,11 +389,9 @@ ZTEST_USER(canfd, test_set_bitrate_data_while_started) */ ZTEST_USER(canfd, test_set_timing_data_while_started) { - struct can_timing timing; + struct can_timing timing = { 0 }; int err; - timing.sjw = CAN_SJW_NO_CHANGE; - err = can_calc_timing_data(can_dev, &timing, TEST_BITRATE_3, TEST_SAMPLE_POINT); zassert_ok(err, "failed to calculate data timing (err %d)", err); @@ -434,7 +432,7 @@ void *canfd_setup(void) (void)can_stop(can_dev); err = can_set_mode(can_dev, CAN_MODE_LOOPBACK | CAN_MODE_FD); - zassert_equal(err, 0, "failed to set CAN-FD loopback mode (err %d)", err); + zassert_equal(err, 0, "failed to set CAN FD loopback mode (err %d)", err); err = can_start(can_dev); zassert_equal(err, 0, "failed to start CAN controller (err %d)", err); diff --git a/tests/drivers/can/api/src/classic.c b/tests/drivers/can/api/src/classic.c index 1b40dc0deac..34a9b42dc1d 100644 --- a/tests/drivers/can/api/src/classic.c +++ b/tests/drivers/can/api/src/classic.c @@ -785,7 +785,7 @@ ZTEST_USER(can_classic, test_send_invalid_dlc) } /** - * @brief Test that CAN-FD format frames are rejected in non-FD mode. + * @brief Test that CAN FD format frames are rejected in non-FD mode. */ ZTEST_USER(can_classic, test_send_fd_format) { @@ -797,7 +797,7 @@ ZTEST_USER(can_classic, test_send_fd_format) frame.flags = CAN_FRAME_FDF; err = can_send(can_dev, &frame, TEST_SEND_TIMEOUT, NULL, NULL); - zassert_equal(err, -ENOTSUP, "sent a CAN-FD format frame in non-FD mode"); + zassert_equal(err, -ENOTSUP, "sent a CAN FD format frame in non-FD mode"); } /** @@ -1031,11 +1031,9 @@ ZTEST_USER(can_classic, test_set_bitrate_while_started) */ ZTEST_USER(can_classic, test_set_timing_while_started) { - struct can_timing timing; + struct can_timing timing = { 0 }; int err; - timing.sjw = CAN_SJW_NO_CHANGE; - err = can_calc_timing(can_dev, &timing, TEST_BITRATE_1, TEST_SAMPLE_POINT); zassert_ok(err, "failed to calculate timing (err %d)", err); diff --git a/tests/drivers/can/api/src/common.c b/tests/drivers/can/api/src/common.c index fd85c2938bf..234bf1eb761 100644 --- a/tests/drivers/can/api/src/common.c +++ b/tests/drivers/can/api/src/common.c @@ -81,7 +81,7 @@ const struct can_frame test_ext_rtr_frame_1 = { }; /** - * @brief Standard (11-bit) CAN ID frame 1 with CAN-FD payload. + * @brief Standard (11-bit) CAN ID frame 1 with CAN FD payload. */ const struct can_frame test_std_fdf_frame_1 = { .flags = CAN_FRAME_FDF | CAN_FRAME_BRS, @@ -95,7 +95,7 @@ const struct can_frame test_std_fdf_frame_1 = { }; /** - * @brief Standard (11-bit) CAN ID frame 1 with CAN-FD payload. + * @brief Standard (11-bit) CAN ID frame 1 with CAN FD payload. */ const struct can_frame test_std_fdf_frame_2 = { .flags = CAN_FRAME_FDF | CAN_FRAME_BRS, @@ -219,7 +219,7 @@ const struct can_filter test_std_some_filter = { }; /** - * @brief Standard (11-bit) CAN-FD ID filter 1. This filter matches + * @brief Standard (11-bit) CAN FD ID filter 1. This filter matches * ``test_std_fdf_frame_1``. */ const struct can_filter test_std_fdf_filter_1 = { @@ -229,7 +229,7 @@ const struct can_filter test_std_fdf_filter_1 = { }; /** - * @brief Standard (11-bit) CAN-FD ID filter 2. This filter matches + * @brief Standard (11-bit) CAN FD ID filter 2. This filter matches * ``test_std_fdf_frame_2``. */ const struct can_filter test_std_fdf_filter_2 = { @@ -252,5 +252,9 @@ void assert_frame_equal(const struct can_frame *frame1, zassert_equal(frame1->flags, frame2->flags, "Flags do not match"); zassert_equal(frame1->id | id_mask, frame2->id | id_mask, "ID does not match"); zassert_equal(frame1->dlc, frame2->dlc, "DLC does not match"); - zassert_mem_equal(frame1->data, frame2->data, frame1->dlc, "Received data differ"); + + if ((frame1->flags & CAN_FRAME_RTR) == 0U) { + zassert_mem_equal(frame1->data, frame2->data, can_dlc_to_bytes(frame1->dlc), + "Received data differ"); + } } diff --git a/tests/drivers/can/api/src/common.h b/tests/drivers/can/api/src/common.h index bc4ba765280..65475add23f 100644 --- a/tests/drivers/can/api/src/common.h +++ b/tests/drivers/can/api/src/common.h @@ -87,12 +87,12 @@ extern const struct can_frame test_std_rtr_frame_1; extern const struct can_frame test_ext_rtr_frame_1; /** - * @brief Standard (11-bit) CAN ID frame 1 with CAN-FD payload. + * @brief Standard (11-bit) CAN ID frame 1 with CAN FD payload. */ extern const struct can_frame test_std_fdf_frame_1; /** - * @brief Standard (11-bit) CAN ID frame 2 with CAN-FD payload. + * @brief Standard (11-bit) CAN ID frame 2 with CAN FD payload. */ extern const struct can_frame test_std_fdf_frame_2; @@ -163,13 +163,13 @@ extern const struct can_filter test_ext_rtr_filter_1; extern const struct can_filter test_std_some_filter; /** - * @brief Standard (11-bit) CAN-FD ID filter 1. This filter matches + * @brief Standard (11-bit) CAN FD ID filter 1. This filter matches * ``test_std_fdf_frame_1``. */ extern const struct can_filter test_std_fdf_filter_1; /** - * @brief Standard (11-bit) CAN-FD ID filter 2. This filter matches + * @brief Standard (11-bit) CAN FD ID filter 2. This filter matches * ``test_std_fdf_frame_2``. */ extern const struct can_filter test_std_fdf_filter_2; diff --git a/tests/drivers/can/api/src/stats.c b/tests/drivers/can/api/src/stats.c new file mode 100644 index 00000000000..c272cc89b9f --- /dev/null +++ b/tests/drivers/can/api/src/stats.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 Vestas Wind Systems A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "common.h" + +/** + * @addtogroup t_driver_can + * @{ + * @defgroup t_can_stats test_can_stats + * @} + */ + +/** + * @brief Test that CAN statistics can be accessed from user mode threads. + */ +ZTEST_USER(can_stats, test_can_stats_accessors) +{ + uint32_t val; + + val = can_stats_get_bit_errors(can_dev); + val = can_stats_get_bit0_errors(can_dev); + val = can_stats_get_bit1_errors(can_dev); + val = can_stats_get_stuff_errors(can_dev); + val = can_stats_get_crc_errors(can_dev); + val = can_stats_get_form_errors(can_dev); + val = can_stats_get_ack_errors(can_dev); + val = can_stats_get_rx_overruns(can_dev); +} + +void *can_stats_setup(void) +{ + k_object_access_grant(can_dev, k_current_get()); + + zassert_true(device_is_ready(can_dev), "CAN device not ready"); + + return NULL; +} + +ZTEST_SUITE(can_stats, NULL, can_stats_setup, NULL, NULL, NULL); diff --git a/tests/drivers/can/api/src/utilities.c b/tests/drivers/can/api/src/utilities.c index 785c4b9cedf..90f5cbd2cf5 100644 --- a/tests/drivers/can/api/src/utilities.c +++ b/tests/drivers/can/api/src/utilities.c @@ -24,12 +24,12 @@ ZTEST(can_utilities, test_can_dlc_to_bytes) { uint8_t dlc; - /* CAN 2.0B/CAN-FD DLC, 0 to 8 data bytes */ + /* CAN 2.0B/CAN FD DLC, 0 to 8 data bytes */ for (dlc = 0; dlc <= 8; dlc++) { zassert_equal(can_dlc_to_bytes(dlc), dlc, "wrong number of bytes for DLC %u", dlc); } - /* CAN-FD DLC, 12 to 64 data bytes in steps */ + /* CAN FD DLC, 12 to 64 data bytes in steps */ zassert_equal(can_dlc_to_bytes(9), 12, "wrong number of bytes for DLC 9"); zassert_equal(can_dlc_to_bytes(10), 16, "wrong number of bytes for DLC 10"); zassert_equal(can_dlc_to_bytes(11), 20, "wrong number of bytes for DLC 11"); @@ -51,7 +51,7 @@ ZTEST(can_utilities, test_can_bytes_to_dlc) zassert_equal(can_bytes_to_dlc(bytes), bytes, "wrong DLC for %u byte(s)", bytes); } - /* CAN-FD DLC, 12 to 64 data bytes in steps */ + /* CAN FD DLC, 12 to 64 data bytes in steps */ zassert_equal(can_bytes_to_dlc(12), 9, "wrong DLC for 12 bytes"); zassert_equal(can_bytes_to_dlc(16), 10, "wrong DLC for 16 bytes"); zassert_equal(can_bytes_to_dlc(20), 11, "wrong DLC for 20 bytes"); @@ -119,17 +119,17 @@ ZTEST(can_utilities, test_can_frame_matches_filter) zassert_false(can_frame_matches_filter(&test_std_frame_1, &test_std_rtr_filter_1)); zassert_false(can_frame_matches_filter(&test_ext_frame_1, &test_ext_rtr_filter_1)); - /* CAN-FD format frames and filters */ + /* CAN FD format frames and filters */ zassert_true(can_frame_matches_filter(&test_std_fdf_frame_1, &test_std_fdf_filter_1)); zassert_true(can_frame_matches_filter(&test_std_fdf_frame_2, &test_std_fdf_filter_2)); zassert_false(can_frame_matches_filter(&test_std_fdf_frame_1, &test_std_fdf_filter_2)); zassert_false(can_frame_matches_filter(&test_std_fdf_frame_2, &test_std_fdf_filter_1)); - /* CAN-FD format frames and classic filters */ + /* CAN FD format frames and classic filters */ zassert_false(can_frame_matches_filter(&test_std_fdf_frame_1, &test_std_filter_1)); zassert_false(can_frame_matches_filter(&test_std_fdf_frame_2, &test_std_filter_2)); - /* Classic format frames and CAN-FD format filters */ + /* Classic format frames and CAN FD format filters */ zassert_false(can_frame_matches_filter(&test_std_frame_1, &test_std_fdf_filter_1)); zassert_false(can_frame_matches_filter(&test_std_frame_2, &test_std_fdf_filter_2)); } diff --git a/tests/drivers/can/shell/app.overlay b/tests/drivers/can/shell/app.overlay index 60366fc3a52..2e6c8c99790 100644 --- a/tests/drivers/can/shell/app.overlay +++ b/tests/drivers/can/shell/app.overlay @@ -8,11 +8,9 @@ fake_can: fake_can { compatible = "zephyr,fake-can"; status = "okay"; - sjw = <1>; sample-point = <875>; bus-speed = <125000>; sample-point = <875>; - sjw-data = <1>; bus-speed-data = <1000000>; sample-point-data = <750>; }; diff --git a/tests/drivers/can/shell/prj.conf b/tests/drivers/can/shell/prj.conf index fd34da718d2..15c6eafdff7 100644 --- a/tests/drivers/can/shell/prj.conf +++ b/tests/drivers/can/shell/prj.conf @@ -6,5 +6,4 @@ CONFIG_CAN_AUTO_BUS_OFF_RECOVERY=n CONFIG_CAN_FD_MODE=y CONFIG_CAN_SHELL=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=1536 diff --git a/tests/drivers/can/shell/src/main.c b/tests/drivers/can/shell/src/main.c index cf2f5cc348c..61bd80ec72f 100644 --- a/tests/drivers/can/shell/src/main.c +++ b/tests/drivers/can/shell/src/main.c @@ -136,11 +136,9 @@ static void can_shell_test_bitrate(const char *cmd, uint32_t expected_bitrate, uint16_t expected_sample_pnt) { const struct shell *sh = shell_backend_dummy_get_ptr(); - struct can_timing expected; + struct can_timing expected = { 0 }; int err; - expected.sjw = CAN_SJW_NO_CHANGE; - err = can_calc_timing(fake_can_dev, &expected, expected_bitrate, expected_sample_pnt); zassert_ok(err, "failed to calculate reference timing (err %d)", err); @@ -180,13 +178,11 @@ static void can_shell_test_dbitrate(const char *cmd, uint32_t expected_bitrate, uint16_t expected_sample_pnt) { const struct shell *sh = shell_backend_dummy_get_ptr(); - struct can_timing expected; + struct can_timing expected = { 0 }; int err; Z_TEST_SKIP_IFNDEF(CONFIG_CAN_FD_MODE); - expected.sjw = CAN_SJW_NO_CHANGE; - err = can_calc_timing_data(fake_can_dev, &expected, expected_bitrate, expected_sample_pnt); zassert_ok(err, "failed to calculate reference timing (err %d)", err); @@ -210,6 +206,75 @@ ZTEST(can_shell, test_can_dbitrate_sample_point) can_shell_test_dbitrate("can dbitrate " FAKE_CAN_NAME " 1000000 875", 1000000, 875); } +ZTEST(can_shell, test_can_timing) +{ + const struct shell *sh = shell_backend_dummy_get_ptr(); + struct can_timing expected = { + .sjw = 1U, + .prop_seg = 2U, + .phase_seg1 = 3U, + .phase_seg2 = 4U, + .prescaler = 5U, + }; + int err; + + fake_can_set_timing_fake.custom_fake = can_shell_test_capture_timing; + + err = shell_execute_cmd(sh, "can timing " FAKE_CAN_NAME " 1 2 3 4 5"); + zassert_ok(err, "failed to execute shell command (err %d)", err); + zassert_equal(fake_can_set_timing_fake.call_count, 1, "set_timing function not called"); + zassert_equal(fake_can_set_timing_fake.arg0_val, fake_can_dev, "wrong device pointer"); + assert_can_timing_equal(&expected, &timing_capture); +} + +ZTEST(can_shell, test_can_timing_missing_value) +{ + const struct shell *sh = shell_backend_dummy_get_ptr(); + int err; + + Z_TEST_SKIP_IFNDEF(CONFIG_CAN_FD_MODE); + + err = shell_execute_cmd(sh, "can timing " FAKE_CAN_NAME); + zassert_not_equal(err, 0, " executed shell command without timing"); + zassert_equal(fake_can_set_timing_fake.call_count, 0, + "set_timing function called"); +} + +ZTEST(can_shell, test_can_dtiming) +{ + const struct shell *sh = shell_backend_dummy_get_ptr(); + struct can_timing expected = { + .sjw = 1U, + .prop_seg = 2U, + .phase_seg1 = 3U, + .phase_seg2 = 4U, + .prescaler = 5U, + }; + int err; + + fake_can_set_timing_data_fake.custom_fake = can_shell_test_capture_timing; + + err = shell_execute_cmd(sh, "can dtiming " FAKE_CAN_NAME " 1 2 3 4 5"); + zassert_ok(err, "failed to execute shell command (err %d)", err); + zassert_equal(fake_can_set_timing_data_fake.call_count, 1, + "set_timing_data function not called"); + zassert_equal(fake_can_set_timing_data_fake.arg0_val, fake_can_dev, "wrong device pointer"); + assert_can_timing_equal(&expected, &timing_capture); +} + +ZTEST(can_shell, test_can_dtiming_missing_value) +{ + const struct shell *sh = shell_backend_dummy_get_ptr(); + int err; + + Z_TEST_SKIP_IFNDEF(CONFIG_CAN_FD_MODE); + + err = shell_execute_cmd(sh, "can dtiming " FAKE_CAN_NAME); + zassert_not_equal(err, 0, " executed shell command without dtiming"); + zassert_equal(fake_can_set_timing_data_fake.call_count, 0, + "set_timing_data function called"); +} + ZTEST(can_shell, test_can_mode_missing_value) { const struct shell *sh = shell_backend_dummy_get_ptr(); diff --git a/tests/drivers/can/timing/prj.conf b/tests/drivers/can/timing/prj.conf index 52b5adf9c2d..137d8604819 100644 --- a/tests/drivers/can/timing/prj.conf +++ b/tests/drivers/can/timing/prj.conf @@ -2,4 +2,3 @@ CONFIG_CAN=y CONFIG_CAN_FD_MODE=y CONFIG_TEST_USERSPACE=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/can/timing/src/main.c b/tests/drivers/can/timing/src/main.c index 2c90863ad64..7f576de6c0b 100644 --- a/tests/drivers/can/timing/src/main.c +++ b/tests/drivers/can/timing/src/main.c @@ -70,7 +70,7 @@ static const struct can_timing_test can_timing_data_tests[] = { { 500000, 800, false }, /** Valid bitrate, invalid sample point. */ { 500000, 1000, true }, - /** Invalid CAN-FD bitrate, valid sample point. */ + /** Invalid CAN FD bitrate, valid sample point. */ { 8000000 + 1, 750, true }, }; #endif /* CONFIG_CAN_FD_MODE */ @@ -115,13 +115,13 @@ static void assert_timing_within_bounds(struct can_timing *timing, const struct can_timing *min, const struct can_timing *max) { - zassert_true(timing->sjw == CAN_SJW_NO_CHANGE, "sjw does not equal CAN_SJW_NO_CHANGE"); - + zassert_true(timing->sjw <= max->sjw, "sjw exceeds max"); zassert_true(timing->prop_seg <= max->prop_seg, "prop_seg exceeds max"); zassert_true(timing->phase_seg1 <= max->phase_seg1, "phase_seg1 exceeds max"); zassert_true(timing->phase_seg2 <= max->phase_seg2, "phase_seg2 exceeds max"); zassert_true(timing->prescaler <= max->prescaler, "prescaler exceeds max"); + zassert_true(timing->sjw >= min->sjw, "sjw lower than min"); zassert_true(timing->prop_seg >= min->prop_seg, "prop_seg lower than min"); zassert_true(timing->phase_seg1 >= min->phase_seg1, "phase_seg1 lower than min"); zassert_true(timing->phase_seg2 >= min->phase_seg2, "phase_seg2 lower than min"); @@ -169,15 +169,13 @@ static void test_timing_values(const struct device *dev, const struct can_timing printk("testing bitrate %u, sample point %u.%u%% (%s): ", test->bitrate, test->sp / 10, test->sp % 10, test->invalid ? "invalid" : "valid"); - timing.sjw = CAN_SJW_NO_CHANGE; - if (data_phase) { if (IS_ENABLED(CONFIG_CAN_FD_MODE)) { min = can_get_timing_data_min(dev); max = can_get_timing_data_max(dev); sp_err = can_calc_timing_data(dev, &timing, test->bitrate, test->sp); } else { - zassert_unreachable("data phase timing test without CAN-FD support"); + zassert_unreachable("data phase timing test without CAN FD support"); } } else { min = can_get_timing_min(dev); @@ -193,8 +191,9 @@ static void test_timing_values(const struct device *dev, const struct can_timing zassert_true(sp_err <= SAMPLE_POINT_MARGIN, "sample point error %d too large", sp_err); - printk("prop_seg = %u, phase_seg1 = %u, phase_seg2 = %u, prescaler = %u ", - timing.prop_seg, timing.phase_seg1, timing.phase_seg2, timing.prescaler); + printk("sjw = %u, prop_seg = %u, phase_seg1 = %u, phase_seg2 = %u, prescaler = %u ", + timing.sjw, timing.prop_seg, timing.phase_seg1, timing.phase_seg2, + timing.prescaler); assert_bitrate_correct(dev, &timing, test->bitrate); assert_timing_within_bounds(&timing, min, max); diff --git a/tests/drivers/charger/sbs_charger/CMakeLists.txt b/tests/drivers/charger/sbs_charger/CMakeLists.txt new file mode 100644 index 00000000000..2c1dfa0e021 --- /dev/null +++ b/tests/drivers/charger/sbs_charger/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(device) + +FILE(GLOB app_sources src/test_sbs_charger.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/charger/sbs_charger/boards/emulated_board.conf b/tests/drivers/charger/sbs_charger/boards/emulated_board.conf new file mode 100644 index 00000000000..ed85179e5cb --- /dev/null +++ b/tests/drivers/charger/sbs_charger/boards/emulated_board.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2023 Cirrus Logic, Inc. +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_EMUL=y diff --git a/tests/drivers/charger/sbs_charger/boards/emulated_board.overlay b/tests/drivers/charger/sbs_charger/boards/emulated_board.overlay new file mode 100644 index 00000000000..a4684a78a96 --- /dev/null +++ b/tests/drivers/charger/sbs_charger/boards/emulated_board.overlay @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Cirrus Logic, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + fake_i2c_bus: i2c@100 { + status = "okay"; + compatible = "zephyr,i2c-emul-controller"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x100 4>; + }; +}; + +&fake_i2c_bus { + clock-frequency = ; + compatible = "zephyr,i2c-emul-controller"; + smartcharger0: smartcharger@b { + compatible = "sbs,sbs-charger"; + reg = <0x0B>; + status = "okay"; + }; +}; diff --git a/tests/drivers/charger/sbs_charger/boards/qemu_cortex_a53.conf b/tests/drivers/charger/sbs_charger/boards/qemu_cortex_a53.conf new file mode 100644 index 00000000000..ed85179e5cb --- /dev/null +++ b/tests/drivers/charger/sbs_charger/boards/qemu_cortex_a53.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2023 Cirrus Logic, Inc. +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_EMUL=y diff --git a/tests/drivers/charger/sbs_charger/boards/qemu_cortex_a53.overlay b/tests/drivers/charger/sbs_charger/boards/qemu_cortex_a53.overlay new file mode 100644 index 00000000000..cd29ddf8284 --- /dev/null +++ b/tests/drivers/charger/sbs_charger/boards/qemu_cortex_a53.overlay @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Cirrus Logic, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + fake_i2c_bus: i2c@100 { + status = "okay"; + compatible = "zephyr,i2c-emul-controller"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + /* + * qemu_cortex_a53 SoC requires a 64 bit child addresses (reg properties) + * See its /soc #address-cells & #size-cells properties. + */ + reg = <0x0 0x100 0 4>; + }; +}; + +&fake_i2c_bus { + clock-frequency = ; + compatible = "zephyr,i2c-emul-controller"; + smartcharger0: smartcharger@b { + compatible = "sbs,sbs-charger"; + reg = <0x0B>; + status = "okay"; + }; +}; diff --git a/tests/drivers/charger/sbs_charger/prj.conf b/tests/drivers/charger/sbs_charger/prj.conf new file mode 100644 index 00000000000..9703f17c7cb --- /dev/null +++ b/tests/drivers/charger/sbs_charger/prj.conf @@ -0,0 +1,5 @@ +CONFIG_ZTEST=y +CONFIG_TEST_USERSPACE=y +CONFIG_LOG=y + +CONFIG_CHARGER=y diff --git a/tests/drivers/charger/sbs_charger/src/test_sbs_charger.c b/tests/drivers/charger/sbs_charger/src/test_sbs_charger.c new file mode 100644 index 00000000000..9b2b9e66900 --- /dev/null +++ b/tests/drivers/charger/sbs_charger/src/test_sbs_charger.c @@ -0,0 +1,77 @@ +/* + * Copyright 2023 Cirrus Logic, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct sbs_charger_fixture { + const struct device *dev; + const struct charger_driver_api *api; +}; + +static void *sbs_charger_setup(void) +{ + static ZTEST_DMEM struct sbs_charger_fixture fixture; + + fixture.dev = DEVICE_DT_GET_ANY(sbs_sbs_charger); + + k_object_access_all_grant(fixture.dev); + + zassert_true(device_is_ready(fixture.dev), "Charger not found"); + + return &fixture; +} + +ZTEST_USER_F(sbs_charger, test_get_prop_failed_returns_negative) +{ + /* Grab a bogus property */ + charger_prop_t prop = CHARGER_PROP_MAX; + union charger_propval val = {0}; + + int ret = charger_get_prop(fixture->dev, prop, &val); + + zassert_equal(ret, -ENOTSUP, "Getting bad property %d has a good status.", prop); +} + +ZTEST_USER_F(sbs_charger, test_get_prop_success_returns_zero) +{ + /* Validate what props are supported by the driver */ + charger_prop_t prop = CHARGER_PROP_ONLINE; + union charger_propval val = {0}; + + int ret = charger_get_prop(fixture->dev, prop, &val); + + zassert_equal(ret, 0, "Getting good property %d has a good status.", prop); +} + +ZTEST_USER_F(sbs_charger, test_set_prop_failed_returns_negative) +{ + /* Set a bogus property */ + charger_prop_t prop = CHARGER_PROP_MAX; + union charger_propval val = {0}; + + int ret = charger_set_prop(fixture->dev, prop, &val); + + zassert_equal(ret, -ENOTSUP, "Setting bad property %d has a good status.", prop); +} + +ZTEST_USER_F(sbs_charger, test_set_prop_success_returns_zero) +{ + union charger_propval val = {.status = CHARGER_STATUS_NOT_CHARGING}; + charger_prop_t prop = CHARGER_PROP_STATUS; + + int ret = charger_set_prop(fixture->dev, prop, &val); + + zassert_equal(ret, 0, "Setting good property %d has a good status.", prop); +} + +ZTEST_SUITE(sbs_charger, NULL, sbs_charger_setup, NULL, NULL, NULL); diff --git a/tests/drivers/charger/sbs_charger/testcase.yaml b/tests/drivers/charger/sbs_charger/testcase.yaml new file mode 100644 index 00000000000..1cc4904010b --- /dev/null +++ b/tests/drivers/charger/sbs_charger/testcase.yaml @@ -0,0 +1,38 @@ +tests: + # section.subsection + drivers.charger.sbs.emulated: + tags: + - drivers + - charger + filter: > + dt_compat_enabled("sbs,sbs-charger") and + (CONFIG_QEMU_TARGET or CONFIG_BOARD_NATIVE_POSIX) + extra_args: + CONF_FILE="prj.conf;boards/emulated_board.conf" + DTC_OVERLAY_FILE="boards/emulated_board.overlay" + platform_exclude: + - qemu_cortex_a53 + - qemu_cortex_a53_smp + - qemu_kvm_arm64 + - xenvm + - xenvm_gicv3 + - hifive_unmatched + - rcar_h3ulcb_ca57 + - rcar_salvator_xs_m3 + - numaker_pfm_m467 + drivers.charger.sbs.emulated_64_bit_i2c_addr: + tags: + - drivers + - charger + filter: > + dt_compat_enabled("sbs,sbs-charger") and + (CONFIG_QEMU_TARGET or CONFIG_BOARD_NATIVE_POSIX) + platform_allow: + - qemu_cortex_a53 + - qemu_cortex_a53_smp + - qemu_kvm_arm64 + - xenvm + - xenvm_gicv3 + extra_args: + CONF_FILE="prj.conf;boards/qemu_cortex_a53.conf" + DTC_OVERLAY_FILE="boards/qemu_cortex_a53.overlay" diff --git a/tests/drivers/clock_control/adsp_clock/prj.conf b/tests/drivers/clock_control/adsp_clock/prj.conf index 664faa92589..903dc40185b 100644 --- a/tests/drivers/clock_control/adsp_clock/prj.conf +++ b/tests/drivers/clock_control/adsp_clock/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_CLOCK_CONTROL=y diff --git a/tests/drivers/clock_control/adsp_clock/testcase.yaml b/tests/drivers/clock_control/adsp_clock/testcase.yaml index 5abe4765022..48df05a8462 100644 --- a/tests/drivers/clock_control/adsp_clock/testcase.yaml +++ b/tests/drivers/clock_control/adsp_clock/testcase.yaml @@ -2,7 +2,7 @@ tests: drivers.clock.adsp_clock_control: tags: - drivers - - clock + - clock_control platform_allow: intel_adsp_cavs25 integration_platforms: - intel_adsp_cavs25 diff --git a/tests/drivers/clock_control/clock_control_api/nrf_lfclk_rc.conf b/tests/drivers/clock_control/clock_control_api/nrf_lfclk_rc.conf index 5ac091262bd..46e88f7b150 100644 --- a/tests/drivers/clock_control/clock_control_api/nrf_lfclk_rc.conf +++ b/tests/drivers/clock_control/clock_control_api/nrf_lfclk_rc.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION=n diff --git a/tests/drivers/clock_control/clock_control_api/prj.conf b/tests/drivers/clock_control/clock_control_api/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/drivers/clock_control/clock_control_api/prj.conf +++ b/tests/drivers/clock_control/clock_control_api/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/clock_control/clock_control_api/testcase.yaml b/tests/drivers/clock_control/clock_control_api/testcase.yaml index 18d75385551..be789c8382a 100644 --- a/tests/drivers/clock_control/clock_control_api/testcase.yaml +++ b/tests/drivers/clock_control/clock_control_api/testcase.yaml @@ -2,7 +2,7 @@ tests: drivers.clock.clock_control_nrf5: tags: - drivers - - cloc + - clock_control platform_allow: - nrf51dk_nrf51422 - nrf52dk_nrf52832 @@ -13,7 +13,7 @@ tests: drivers.clock.clock_control_nrf5_lfclk_rc: tags: - drivers - - clock + - clock_control platform_allow: - nrf51dk_nrf51422 - nrf52dk_nrf52832 diff --git a/tests/drivers/clock_control/fixed_clock/prj.conf b/tests/drivers/clock_control/fixed_clock/prj.conf index b60d57cd846..bbeba0a33c4 100644 --- a/tests/drivers/clock_control/fixed_clock/prj.conf +++ b/tests/drivers/clock_control/fixed_clock/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_CLOCK_CONTROL=y CONFIG_CLOCK_CONTROL_FIXED_RATE_CLOCK=y diff --git a/tests/drivers/clock_control/nrf_clock_calibration/prj.conf b/tests/drivers/clock_control/nrf_clock_calibration/prj.conf index e885da62fd6..5c7bfc52ad7 100644 --- a/tests/drivers/clock_control/nrf_clock_calibration/prj.conf +++ b/tests/drivers/clock_control/nrf_clock_calibration/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_MAX_SKIP=1 CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_TEMP_DIFF=2 diff --git a/tests/drivers/clock_control/nrf_clock_calibration/testcase.yaml b/tests/drivers/clock_control/nrf_clock_calibration/testcase.yaml index e7ac90ec7b9..092471d30e4 100644 --- a/tests/drivers/clock_control/nrf_clock_calibration/testcase.yaml +++ b/tests/drivers/clock_control/nrf_clock_calibration/testcase.yaml @@ -2,7 +2,7 @@ tests: drivers.clock.nrf5_clock_calibration: tags: - drivers - - clock + - clock_control platform_allow: - nrf51dk_nrf51422 - nrf52dk_nrf52832 diff --git a/tests/drivers/clock_control/nrf_lf_clock_start/prj.conf b/tests/drivers/clock_control/nrf_lf_clock_start/prj.conf index f3825418170..9467c292689 100644 --- a/tests/drivers/clock_control/nrf_lf_clock_start/prj.conf +++ b/tests/drivers/clock_control/nrf_lf_clock_start/prj.conf @@ -1,5 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y - -# Disable boot banner to reduce time between clock start and test execution -CONFIG_BOOT_BANNER=n diff --git a/tests/drivers/clock_control/nrf_lf_clock_start/testcase.yaml b/tests/drivers/clock_control/nrf_lf_clock_start/testcase.yaml index 01ba725e780..f4940d79896 100644 --- a/tests/drivers/clock_control/nrf_lf_clock_start/testcase.yaml +++ b/tests/drivers/clock_control/nrf_lf_clock_start/testcase.yaml @@ -1,7 +1,7 @@ common: tags: - drivers - - clock + - clock_control integration_platforms: - nrf51dk_nrf51422 tests: diff --git a/tests/drivers/clock_control/nrf_onoff_and_bt/prj.conf b/tests/drivers/clock_control/nrf_onoff_and_bt/prj.conf index 8471c482366..d25c9c7d100 100644 --- a/tests/drivers/clock_control/nrf_onoff_and_bt/prj.conf +++ b/tests/drivers/clock_control/nrf_onoff_and_bt/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ENTROPY_GENERATOR=y diff --git a/tests/drivers/clock_control/nrf_onoff_and_bt/testcase.yaml b/tests/drivers/clock_control/nrf_onoff_and_bt/testcase.yaml index 04c107da954..19c77496933 100644 --- a/tests/drivers/clock_control/nrf_onoff_and_bt/testcase.yaml +++ b/tests/drivers/clock_control/nrf_onoff_and_bt/testcase.yaml @@ -2,7 +2,7 @@ tests: drivers.clock.nrf_onoff_and_bt: tags: - drivers - - clock + - clock_control platform_allow: - nrf51dk_nrf51422 - nrf52dk_nrf52832 diff --git a/tests/drivers/clock_control/onoff/prj.conf b/tests/drivers/clock_control/onoff/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/drivers/clock_control/onoff/prj.conf +++ b/tests/drivers/clock_control/onoff/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/clock_control/onoff/testcase.yaml b/tests/drivers/clock_control/onoff/testcase.yaml index abedf82f2a4..a6e03d9a0ec 100644 --- a/tests/drivers/clock_control/onoff/testcase.yaml +++ b/tests/drivers/clock_control/onoff/testcase.yaml @@ -2,7 +2,7 @@ tests: drivers.clock.clock_control_onoff: tags: - drivers - - clock + - clock_control platform_allow: - nrf51dk_nrf51422 - nrf52dk_nrf52832 diff --git a/tests/drivers/clock_control/pwm_clock/CMakeLists.txt b/tests/drivers/clock_control/pwm_clock/CMakeLists.txt new file mode 100644 index 00000000000..c6217f1aabf --- /dev/null +++ b/tests/drivers/clock_control/pwm_clock/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(pwm_clock) + +target_sources(app PRIVATE src/main.c) diff --git a/tests/drivers/clock_control/pwm_clock/boards/sam_v71_xult.overlay b/tests/drivers/clock_control/pwm_clock/boards/sam_v71_xult.overlay new file mode 100644 index 00000000000..f744dc9f0e5 --- /dev/null +++ b/tests/drivers/clock_control/pwm_clock/boards/sam_v71_xult.overlay @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 Andriy Gelman + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + pwmclock: pwmclock { + status = "okay"; + compatible = "pwm-clock"; + #clock-cells = <1>; + clock-frequency = <1000000>; + pwms = <&pwm0 0 PWM_KHZ(1000) PWM_POLARITY_NORMAL>; + }; + + samplenode: samplenode { + status = "okay"; + compatible = "test-clock-control-pwm-clock"; + clocks = <&pwmclock 0>; + }; +}; + +&pwm0 { + prescaler = <1>; +}; diff --git a/tests/drivers/clock_control/pwm_clock/boards/xmc45_relax_kit.overlay b/tests/drivers/clock_control/pwm_clock/boards/xmc45_relax_kit.overlay new file mode 100644 index 00000000000..16218f42596 --- /dev/null +++ b/tests/drivers/clock_control/pwm_clock/boards/xmc45_relax_kit.overlay @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 Andriy Gelman + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + pwmclock: pwmclock { + status = "okay"; + compatible = "pwm-clock"; + #clock-cells = <1>; + clock-frequency = <1000000>; + pwms = <&pwm_ccu40 2 PWM_KHZ(1000) PWM_POLARITY_NORMAL>; + }; + + samplenode: samplenode { + status = "okay"; + compatible = "test-clock-control-pwm-clock"; + clocks = <&pwmclock 0>; + }; +}; + +&pwm_ccu40 { + status = "okay"; + slice-prescaler = <0 0 0 0>; +}; diff --git a/tests/drivers/clock_control/pwm_clock/boards/xmc47_relax_kit.overlay b/tests/drivers/clock_control/pwm_clock/boards/xmc47_relax_kit.overlay new file mode 100644 index 00000000000..880430e4c68 --- /dev/null +++ b/tests/drivers/clock_control/pwm_clock/boards/xmc47_relax_kit.overlay @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 Andriy Gelman + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + pwmclock: pwmclock { + status = "okay"; + compatible = "pwm-clock"; + #clock-cells = <1>; + clock-frequency = <1000000>; + pwms = <&pwm_ccu80 0 PWM_KHZ(1000) PWM_POLARITY_NORMAL>; + }; + + samplenode: samplenode { + status = "okay"; + compatible = "test-clock-control-pwm-clock"; + clocks = <&pwmclock 0>; + }; +}; + +&pwm_ccu80 { + status = "okay"; + slice-prescaler = <0 0 0 0>; +}; diff --git a/tests/drivers/clock_control/pwm_clock/dts/bindings/test-clock-control-clock-pwm.yaml b/tests/drivers/clock_control/pwm_clock/dts/bindings/test-clock-control-clock-pwm.yaml new file mode 100644 index 00000000000..078e3bc39cd --- /dev/null +++ b/tests/drivers/clock_control/pwm_clock/dts/bindings/test-clock-control-clock-pwm.yaml @@ -0,0 +1,10 @@ +description: Example binding for a node using a PWM clock + +compatible: "test-clock-control-pwm-clock" + +include: base.yaml + +properties: + clocks: + required: true + description: Clock phandle array diff --git a/tests/drivers/clock_control/pwm_clock/prj.conf b/tests/drivers/clock_control/pwm_clock/prj.conf new file mode 100644 index 00000000000..903dc40185b --- /dev/null +++ b/tests/drivers/clock_control/pwm_clock/prj.conf @@ -0,0 +1,2 @@ +CONFIG_ZTEST=y +CONFIG_CLOCK_CONTROL=y diff --git a/tests/drivers/clock_control/pwm_clock/src/main.c b/tests/drivers/clock_control/pwm_clock/src/main.c new file mode 100644 index 00000000000..87fa8601473 --- /dev/null +++ b/tests/drivers/clock_control/pwm_clock/src/main.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2023 Andriy Gelman + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#define NODELABEL DT_NODELABEL(samplenode) +static const struct device *clk_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(NODELABEL)); + +static void *pwm_clock_setup(void) +{ + int ret; + uint32_t clock_rate; + uint32_t clock_rate_dt = DT_PROP_BY_PHANDLE(NODELABEL, clocks, clock_frequency); + + zassert_equal(device_is_ready(clk_dev), true, "%s: PWM clock device is not ready", + clk_dev->name); + + ret = clock_control_get_rate(clk_dev, 0, &clock_rate); + zassert_equal(0, ret, "%s: Unexpected err (%d) from clock_control_get_rate", + clk_dev->name, ret); + + zassert_equal(clock_rate_dt, clock_rate, + "%s: devicetree clock rate mismatch. Expected %dHz Fetched %dHz", + clk_dev->name, clock_rate_dt, clock_rate); + + ret = clock_control_on(clk_dev, 0); + zassert_equal(0, ret, "%s: Unexpected err (%d) from clock_control_on", clk_dev->name, ret); + + return NULL; +} + +ZTEST(pwm_clock, test_clock_control_get_rate) +{ + int ret; + uint32_t clock_rate; + + ret = clock_control_get_rate(clk_dev, 0, &clock_rate); + zassert_equal(0, ret, "%s: Unexpected err (%d) from clock_control_get_rate", + clk_dev->name, ret); +} + +ZTEST(pwm_clock, test_clock_control_set_rate) +{ + int ret; + uint32_t clock_rate, clock_rate_new; + + ret = clock_control_get_rate(clk_dev, 0, &clock_rate); + zassert_equal(0, ret, "%s: Unexpected err (%d) from clock_control_get_rate", + clk_dev->name, ret); + + clock_rate /= 2; + + ret = clock_control_set_rate(clk_dev, 0, (clock_control_subsys_rate_t)clock_rate); + zassert_equal(0, ret, "%s: unexpected err (%d) from clock_control_set_rate", + clk_dev->name, ret); + + ret = clock_control_get_rate(clk_dev, 0, &clock_rate_new); + zassert_equal(0, ret, "%s: Unexpected err (%d) from clock_control_get_rate", + clk_dev->name, ret); + + zassert_equal(clock_rate, clock_rate_new, + "%s: Clock rate mismatch. Expected %dHz Fetched %dHz", clk_dev->name, + clock_rate, clock_rate_new); +} + +ZTEST_SUITE(pwm_clock, NULL, pwm_clock_setup, NULL, NULL, NULL); diff --git a/tests/drivers/clock_control/pwm_clock/testcase.yaml b/tests/drivers/clock_control/pwm_clock/testcase.yaml new file mode 100644 index 00000000000..0789fcf0722 --- /dev/null +++ b/tests/drivers/clock_control/pwm_clock/testcase.yaml @@ -0,0 +1,7 @@ +tests: + drivers.clock.pwm_clock: + filter: dt_compat_enabled("pwm-clock") and dt_compat_enabled("test-clock-control-pwm-clock") + tags: + - drivers + - clock + - pwm diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_core/prj.conf b/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_core/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_core/prj.conf +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_core/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_core/testcase.yaml b/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_core/testcase.yaml index 7800f6ed294..563108bfe91 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_core/testcase.yaml +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_core/testcase.yaml @@ -6,9 +6,10 @@ # - add the fixture in map file common: timeout: 5 - tags: clock-control + tags: + - clock_control tests: - drivers.stm32_clock_configuration.common_core.l4_l5.sysclksrc_pll_48_msi_4: + drivers.clock.stm32_clock_configuration.common_core.l4_l5.sysclksrc_pll_48_msi_4: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/clear_msi.overlay;boards/pll_48_msi_4.overlay" platform_allow: @@ -17,7 +18,7 @@ tests: - stm32l562e_dk integration_platforms: - disco_l475_iot1 - drivers.stm32_clock_configuration.common_core.l4_l5.sysclksrc_pll_64_hsi_16: + drivers.clock.stm32_clock_configuration.common_core.l4_l5.sysclksrc_pll_64_hsi_16: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/clear_msi.overlay;boards/pll_64_hsi_16.overlay" platform_allow: @@ -26,7 +27,7 @@ tests: - stm32l562e_dk integration_platforms: - disco_l475_iot1 - drivers.stm32_clock_configuration.common_core.sysclksrc_hsi_16: + drivers.clock.stm32_clock_configuration.common_core.sysclksrc_hsi_16: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/clear_msi.overlay;boards/hsi_16.overlay" platform_allow: @@ -37,7 +38,7 @@ tests: - nucleo_wl55jc integration_platforms: - disco_l475_iot1 - drivers.stm32_clock_configuration.common_core.sysclksrc_msi_48: + drivers.clock.stm32_clock_configuration.common_core.sysclksrc_msi_48: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/clear_msi.overlay;boards/msi_range11.overlay" platform_allow: @@ -48,7 +49,7 @@ tests: - nucleo_wb55rg integration_platforms: - disco_l475_iot1 - drivers.stm32_clock_configuration.common_core.l4_l5.sysclksrc_hse_8.fixup: + drivers.clock.stm32_clock_configuration.common_core.l4_l5.sysclksrc_hse_8.fixup: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/clear_msi.overlay;boards/hse_8.overlay" platform_allow: @@ -60,7 +61,7 @@ tests: fixture: mco_sb_closed integration_platforms: - disco_l475_iot1 - drivers.stm32_clock_configuration.common_core.l4_l5.sysclksrc_pll_64_hse_8.fixup: + drivers.clock.stm32_clock_configuration.common_core.l4_l5.sysclksrc_pll_64_hse_8.fixup: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/clear_msi.overlay;boards/pll_64_hse_8.overlay" platform_allow: @@ -72,7 +73,7 @@ tests: fixture: mco_sb_closed integration_platforms: - disco_l475_iot1 - drivers.stm32_clock_configuration.common_core.g0.sysclksrc_pll_64_hse_8: + drivers.clock.stm32_clock_configuration.common_core.g0.sysclksrc_pll_64_hse_8: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_64_hse_8.overlay" platform_allow: nucleo_g071rb harness: ztest @@ -80,40 +81,40 @@ tests: fixture: mco_sb_closed integration_platforms: - nucleo_g071rb - drivers.stm32_clock_configuration.common_core.g0.sysclksrc_hsi_g0_16_div_2: + drivers.clock.stm32_clock_configuration.common_core.g0.sysclksrc_hsi_g0_16_div_2: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/hsi_g0_16_div_2.overlay" platform_allow: nucleo_g071rb integration_platforms: - nucleo_g071rb - drivers.stm32_clock_configuration.common_core.g0.sysclksrc_hsi_g0_16_div_4: + drivers.clock.stm32_clock_configuration.common_core.g0.sysclksrc_hsi_g0_16_div_4: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/hsi_g0_16_div_4.overlay" platform_allow: nucleo_g071rb integration_platforms: - nucleo_g071rb - drivers.stm32_clock_configuration.common_core.g4.sysclksrc_pll_64_hsi_16: + drivers.clock.stm32_clock_configuration.common_core.g4.sysclksrc_pll_64_hsi_16: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_64_hsi_16.overlay" platform_allow: nucleo_g474re integration_platforms: - nucleo_g474re - drivers.stm32_clock_configuration.common_core.g0.sysclksrc_pll_g0_64_hsi_16: + drivers.clock.stm32_clock_configuration.common_core.g0.sysclksrc_pll_g0_64_hsi_16: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_g0_64_hsi_16.overlay" platform_allow: nucleo_g071rb integration_platforms: - nucleo_g071rb - drivers.stm32_clock_configuration.common_core.g4.sysclksrc_hsi_16: + drivers.clock.stm32_clock_configuration.common_core.g4.sysclksrc_hsi_16: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/hsi_16.overlay" platform_allow: nucleo_g474re integration_platforms: - nucleo_g474re - drivers.stm32_clock_configuration.common_core.g0.sysclksrc_hsi_g0_16: + drivers.clock.stm32_clock_configuration.common_core.g0.sysclksrc_hsi_g0_16: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/hsi_g0_16.overlay" platform_allow: nucleo_g071rb integration_platforms: - nucleo_g071rb - drivers.stm32_clock_configuration.common_core.g4.sysclksrc_hse_24: + drivers.clock.stm32_clock_configuration.common_core.g4.sysclksrc_hse_24: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/hse_24.overlay" platform_allow: nucleo_g474re - drivers.stm32_clock_configuration.common_core.l0_l1.sysclksrc_hse_8: + drivers.clock.stm32_clock_configuration.common_core.l0_l1.sysclksrc_hse_8: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/clear_msi.overlay;boards/hse_8.overlay" platform_allow: @@ -121,77 +122,77 @@ tests: - nucleo_l073rz integration_platforms: - nucleo_l152re - drivers.stm32_clock_configuration.common_core.l0_l1.sysclksrc_pll_32_hse_8: + drivers.clock.stm32_clock_configuration.common_core.l0_l1.sysclksrc_pll_32_hse_8: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_32_hse_8.overlay" platform_allow: - nucleo_l152re - nucleo_l073rz integration_platforms: - nucleo_l152re - drivers.stm32_clock_configuration.common_core.l0_l1.sysclksrc_pll_32_hsi_16: + drivers.clock.stm32_clock_configuration.common_core.l0_l1.sysclksrc_pll_32_hsi_16: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_32_hsi_16.overlay" platform_allow: - nucleo_l152re - nucleo_l073rz integration_platforms: - nucleo_l152re - drivers.stm32_clock_configuration.common_core.l0_l1.sysclksrc_msi_range6: + drivers.clock.stm32_clock_configuration.common_core.l0_l1.sysclksrc_msi_range6: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/msi_range6.overlay" platform_allow: - nucleo_l152re - nucleo_l073rz integration_platforms: - nucleo_l152re - drivers.stm32_clock_configuration.common_core.wl.sysclksrc_pll_48_hsi_16: + drivers.clock.stm32_clock_configuration.common_core.wl.sysclksrc_pll_48_hsi_16: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_48_hsi_16.overlay" platform_allow: nucleo_wl55jc integration_platforms: - nucleo_wl55jc - drivers.stm32_clock_configuration.common_core.wl.sysclksrc_pll_48_hse_32: + drivers.clock.stm32_clock_configuration.common_core.wl.sysclksrc_pll_48_hse_32: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/wl_pll_48_hse_32.overlay" platform_allow: nucleo_wl55jc integration_platforms: - nucleo_wl55jc - drivers.stm32_clock_configuration.common_core.wl.sysclksrc_hse_32: + drivers.clock.stm32_clock_configuration.common_core.wl.sysclksrc_hse_32: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/wl_32_hse.overlay" platform_allow: nucleo_wl55jc integration_platforms: - nucleo_wl55jc - drivers.stm32_clock_configuration.common_core.wb.sysclksrc_hse_32: + drivers.clock.stm32_clock_configuration.common_core.wb.sysclksrc_hse_32: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/hse_32.overlay" platform_allow: nucleo_wb55rg integration_platforms: - nucleo_wb55rg - drivers.stm32_clock_configuration.common_core.wb.sysclksrc_pll_48_hsi_16: + drivers.clock.stm32_clock_configuration.common_core.wb.sysclksrc_pll_48_hsi_16: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/wb_pll_48_hsi_16.overlay" platform_allow: nucleo_wb55rg integration_platforms: - nucleo_wb55rg - drivers.stm32_clock_configuration.common_core.wb.sysclksrc_pll_64_hse_32: + drivers.clock.stm32_clock_configuration.common_core.wb.sysclksrc_pll_64_hse_32: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/wb_pll_64_hse_32.overlay" platform_allow: nucleo_wb55rg integration_platforms: - nucleo_wb55rg - drivers.stm32_clock_configuration.common_core.wb.sysclksrc_pll_48_msi_4: + drivers.clock.stm32_clock_configuration.common_core.wb.sysclksrc_pll_48_msi_4: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/wb_pll_48_msi_4.overlay" platform_allow: nucleo_wb55rg integration_platforms: - nucleo_wb55rg - drivers.stm32_clock_configuration.common_core.f0_f3.sysclksrc_hsi_8: + drivers.clock.stm32_clock_configuration.common_core.f0_f3.sysclksrc_hsi_8: extra_args: DTC_OVERLAY_FILE="boards/clear_f0_f1_f3_clocks.overlay;boards/hsi_8.overlay" platform_allow: - nucleo_f091rc - stm32f3_disco integration_platforms: - nucleo_f091rc - drivers.stm32_clock_configuration.common_core.f0_f3.sysclksrc_hse_8: + drivers.clock.stm32_clock_configuration.common_core.f0_f3.sysclksrc_hse_8: extra_args: DTC_OVERLAY_FILE="boards/clear_f0_f1_f3_clocks.overlay;boards/hse_8_bypass.overlay" platform_allow: - nucleo_f091rc - stm32f3_disco integration_platforms: - nucleo_f091rc - drivers.stm32_clock_configuration.common_core.f0_f3.sysclksrc_pll_32_hsi_8: + drivers.clock.stm32_clock_configuration.common_core.f0_f3.sysclksrc_pll_32_hsi_8: extra_args: DTC_OVERLAY_FILE="boards/clear_f0_f1_f3_clocks.overlay;boards/f0_f3_pll_32_hsi_8.overlay" platform_allow: @@ -199,7 +200,7 @@ tests: - stm32f3_disco integration_platforms: - nucleo_f091rc - drivers.stm32_clock_configuration.common_core.f0_f3.sysclksrc_pll_32_hse_8: + drivers.clock.stm32_clock_configuration.common_core.f0_f3.sysclksrc_pll_32_hse_8: extra_args: DTC_OVERLAY_FILE="boards/clear_f0_f1_f3_clocks.overlay;boards/f0_f3_pll_32_hse_8.overlay" platform_allow: @@ -207,29 +208,29 @@ tests: - stm32f3_disco integration_platforms: - nucleo_f091rc - drivers.stm32_clock_configuration.common_core.f1.sysclksrc_hsi_8: + drivers.clock.stm32_clock_configuration.common_core.f1.sysclksrc_hsi_8: extra_args: DTC_OVERLAY_FILE="boards/clear_f0_f1_f3_clocks.overlay;boards/hsi_8.overlay" platform_allow: nucleo_f103rb integration_platforms: - nucleo_f103rb - drivers.stm32_clock_configuration.common_core.f1.sysclksrc_hse_8: + drivers.clock.stm32_clock_configuration.common_core.f1.sysclksrc_hse_8: extra_args: DTC_OVERLAY_FILE="boards/clear_f0_f1_f3_clocks.overlay;boards/hse_8.overlay" platform_allow: nucleo_f103rb integration_platforms: - nucleo_f103rb - drivers.stm32_clock_configuration.common_core.f1.sysclksrc_pll_64_hsi_8: + drivers.clock.stm32_clock_configuration.common_core.f1.sysclksrc_pll_64_hsi_8: extra_args: DTC_OVERLAY_FILE="boards/clear_f0_f1_f3_clocks.overlay;boards/f1_pll_64_hsi_8.overlay" platform_allow: nucleo_f103rb integration_platforms: - nucleo_f103rb - drivers.stm32_clock_configuration.common_core.f1.sysclksrc_pll_64_hse_8: + drivers.clock.stm32_clock_configuration.common_core.f1.sysclksrc_pll_64_hse_8: extra_args: DTC_OVERLAY_FILE="boards/clear_f0_f1_f3_clocks.overlay;boards/f1_pll_64_hse_8.overlay" platform_allow: nucleo_f103rb integration_platforms: - nucleo_f103rb - drivers.stm32_clock_configuration.common_core.f2_f4_f7.sysclksrc_hsi_16: + drivers.clock.stm32_clock_configuration.common_core.f2_f4_f7.sysclksrc_hsi_16: extra_args: DTC_OVERLAY_FILE="boards/clear_f2_f4_f7_clocks.overlay;boards/hsi_16.overlay" platform_allow: - nucleo_f207zg @@ -238,7 +239,7 @@ tests: - nucleo_f746zg integration_platforms: - nucleo_f207zg - drivers.stm32_clock_configuration.common_core.f2_f4_f7.sysclksrc_hse_8: + drivers.clock.stm32_clock_configuration.common_core.f2_f4_f7.sysclksrc_hse_8: extra_args: DTC_OVERLAY_FILE="boards/clear_f2_f4_f7_clocks.overlay;boards/hse_8.overlay" platform_allow: - nucleo_f207zg @@ -247,7 +248,7 @@ tests: - nucleo_f746zg integration_platforms: - nucleo_f207zg - drivers.stm32_clock_configuration.common_core.f2_f4_f7.sysclksrc_pll_64_hsi_16: + drivers.clock.stm32_clock_configuration.common_core.f2_f4_f7.sysclksrc_pll_64_hsi_16: extra_args: DTC_OVERLAY_FILE="boards/clear_f2_f4_f7_clocks.overlay;boards/f2_f4_f7_pll_64_hsi_16.overlay" platform_allow: @@ -257,7 +258,7 @@ tests: - nucleo_f746zg integration_platforms: - nucleo_f207zg - drivers.stm32_clock_configuration.common_core.f2_f4_f7.sysclksrc_pll_64_hse_8: + drivers.clock.stm32_clock_configuration.common_core.f2_f4_f7.sysclksrc_pll_64_hse_8: extra_args: DTC_OVERLAY_FILE="boards/clear_f2_f4_f7_clocks.overlay;boards/f2_f4_f7_pll_64_hse_8.overlay" platform_allow: @@ -267,7 +268,7 @@ tests: - nucleo_f746zg integration_platforms: - nucleo_f207zg - drivers.stm32_clock_configuration.common_core.f2_f4_f7.sysclksrc_pll_100_hsi_16_ahb2: + drivers.clock.stm32_clock_configuration.common_core.f2_f4_f7.sysclksrc_pll_100_hsi_16_ahb2: extra_args: DTC_OVERLAY_FILE="boards/clear_f2_f4_f7_clocks.overlay;boards/f2_f4_f7_pll_100_hsi_16_ahb_2.overlay" platform_allow: diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_devices/prj.conf b/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_devices/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_devices/prj.conf +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_devices/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_devices/testcase.yaml b/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_devices/testcase.yaml index 351268c6a5f..535a16a4ed9 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_devices/testcase.yaml +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_devices/testcase.yaml @@ -1,36 +1,36 @@ common: timeout: 5 tests: - drivers.stm32_clock_configuration.common_device.wb.i2c1_hsi_lptim1_lse: + drivers.clock.stm32_clock_configuration.common_device.wb.i2c1_hsi_lptim1_lse: extra_args: DTC_OVERLAY_FILE="boards/wb_i2c1_hsi_lptim1_lse.overlay" platform_allow: nucleo_wb55rg - drivers.stm32_clock_configuration.common_device.wb.i2c1_sysclk_lptim1_lsi: + drivers.clock.stm32_clock_configuration.common_device.wb.i2c1_sysclk_lptim1_lsi: extra_args: DTC_OVERLAY_FILE="boards/wb_i2c1_sysclk_lptim1_lsi.overlay" platform_allow: nucleo_wb55rg - drivers.stm32_clock_configuration.common_device.g0.i2c1_sysclk_lptim1_lsi: + drivers.clock.stm32_clock_configuration.common_device.g0.i2c1_sysclk_lptim1_lsi: extra_args: DTC_OVERLAY_FILE="boards/g0_i2c1_sysclk_lptim1_lsi.overlay" platform_allow: nucleo_g071rb - drivers.stm32_clock_configuration.common_device.g0.i2c1_hsi_lptim1_lse_adc1_pllp: + drivers.clock.stm32_clock_configuration.common_device.g0.i2c1_hsi_lptim1_lse_adc1_pllp: extra_args: DTC_OVERLAY_FILE="boards/g0_i2c1_hsi_lptim1_lse_adc1_pllp.overlay" platform_allow: nucleo_g071rb - drivers.stm32_clock_configuration.common_device.wl.i2c1_hsi_lptim1_lse_adc1_pllp: + drivers.clock.stm32_clock_configuration.common_device.wl.i2c1_hsi_lptim1_lse_adc1_pllp: extra_args: DTC_OVERLAY_FILE="boards/wl_i2c1_hsi_lptim1_lse_adc1_pllp.overlay" platform_allow: nucleo_wl55jc - drivers.stm32_clock_configuration.common_device.wl.i2c1_sysclk_lptim1_lsi: + drivers.clock.stm32_clock_configuration.common_device.wl.i2c1_sysclk_lptim1_lsi: extra_args: DTC_OVERLAY_FILE="boards/wl_i2c1_sysclk_lptim1_lsi.overlay" platform_allow: nucleo_wl55jc - drivers.stm32_clock_configuration.common_device.l4.i2c1_sysclk_lptim1_lsi: + drivers.clock.stm32_clock_configuration.common_device.l4.i2c1_sysclk_lptim1_lsi: extra_args: DTC_OVERLAY_FILE="boards/l4_i2c1_sysclk_lptim1_lsi.overlay" platform_allow: disco_l475_iot1 - drivers.stm32_clock_configuration.common_device.l4.i2c1_hsi_lptim1_lse: + drivers.clock.stm32_clock_configuration.common_device.l4.i2c1_hsi_lptim1_lse: extra_args: DTC_OVERLAY_FILE="boards/l4_i2c1_hsi_lptim1_lse.overlay" platform_allow: disco_l475_iot1 - drivers.stm32_clock_configuration.common_device.g4.i2c1_hsi_adc1_pllp: + drivers.clock.stm32_clock_configuration.common_device.g4.i2c1_hsi_adc1_pllp: extra_args: DTC_OVERLAY_FILE="boards/g4_i2c1_hsi_adc1_pllp.overlay" platform_allow: nucleo_g474re - drivers.stm32_clock_configuration.common_device.f0.i2c1_hsi: + drivers.clock.stm32_clock_configuration.common_device.f0.i2c1_hsi: extra_args: DTC_OVERLAY_FILE="boards/f0_i2c1_hsi.overlay" platform_allow: nucleo_f091rc - drivers.stm32_clock_configuration.common_device.f3.i2c1_hsi: + drivers.clock.stm32_clock_configuration.common_device.f3.i2c1_hsi: extra_args: DTC_OVERLAY_FILE="boards/f3_i2c1_hsi.overlay" platform_allow: stm32f3_disco diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32h5_core/prj.conf b/tests/drivers/clock_control/stm32_clock_configuration/stm32h5_core/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32h5_core/prj.conf +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32h5_core/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32h5_core/testcase.yaml b/tests/drivers/clock_control/stm32_clock_configuration/stm32h5_core/testcase.yaml index d1e72c25174..0fce41b326f 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32h5_core/testcase.yaml +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32h5_core/testcase.yaml @@ -3,30 +3,30 @@ common: tags: clock_control tests: - drivers.stm32_clock_configuration.h5.sysclksrc_pll_csi_100: + drivers.clock.stm32_clock_configuration.h5.sysclksrc_pll_csi_100: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_csi_100.overlay" platform_allow: stm32h573i_dk - drivers.stm32_clock_configuration.h5.sysclksrc_pll_csi_240: + drivers.clock.stm32_clock_configuration.h5.sysclksrc_pll_csi_240: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_csi_240.overlay" platform_allow: stm32h573i_dk - drivers.stm32_clock_configuration.h5.sysclksrc_pll_hsi_240: + drivers.clock.stm32_clock_configuration.h5.sysclksrc_pll_hsi_240: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_hsi_240.overlay" platform_allow: stm32h573i_dk - drivers.stm32_clock_configuration.h5.sysclksrc_pll_hse25_100: + drivers.clock.stm32_clock_configuration.h5.sysclksrc_pll_hse25_100: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_hse25_100.overlay" platform_allow: stm32h573i_dk - drivers.stm32_clock_configuration.h5.sysclksrc_pll_hse25_240: + drivers.clock.stm32_clock_configuration.h5.sysclksrc_pll_hse25_240: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_hse25_240.overlay" platform_allow: stm32h573i_dk - drivers.stm32_clock_configuration.h5.sysclksrc_csi4: + drivers.clock.stm32_clock_configuration.h5.sysclksrc_csi4: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/csi4.overlay" platform_allow: stm32h573i_dk - drivers.stm32_clock_configuration.h5.sysclksrc_hse_25: + drivers.clock.stm32_clock_configuration.h5.sysclksrc_hse_25: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/hse25.overlay" platform_allow: stm32h573i_dk - drivers.stm32_clock_configuration.h5.pll_csi_ahb_2_100: + drivers.clock.stm32_clock_configuration.h5.pll_csi_ahb_2_100: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_csi_ahb_2_100.overlay" platform_allow: stm32h573i_dk - drivers.stm32_clock_configuration.h5.pll_hse25_ahb_2_100: + drivers.clock.stm32_clock_configuration.h5.pll_hse25_ahb_2_100: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_hse25_ahb_2_100.overlay" platform_allow: stm32h573i_dk diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_core/prj.conf b/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_core/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_core/prj.conf +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_core/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_core/testcase.yaml b/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_core/testcase.yaml index 4883264e303..f134f811906 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_core/testcase.yaml +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_core/testcase.yaml @@ -3,37 +3,37 @@ common: tags: clock_control tests: - drivers.stm32_clock_configuration.h7_core.sysclksrc_pll_hse_96: + drivers.clock.stm32_clock_configuration.h7_core.sysclksrc_pll_hse_96: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_hse_96.overlay" platform_allow: nucleo_h743zi integration_platforms: - nucleo_h743zi - drivers.stm32_clock_configuration.h7_core.sysclksrc_pll_hsi_96: + drivers.clock.stm32_clock_configuration.h7_core.sysclksrc_pll_hsi_96: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_hsi_96.overlay" platform_allow: nucleo_h743zi integration_platforms: - nucleo_h743zi - drivers.stm32_clock_configuration.h7_core.sysclksrc_hsi_64: + drivers.clock.stm32_clock_configuration.h7_core.sysclksrc_hsi_64: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/hsi_64.overlay" platform_allow: nucleo_h743zi integration_platforms: - nucleo_h743zi - drivers.stm32_clock_configuration.h7_core.sysclksrc_csi_4: + drivers.clock.stm32_clock_configuration.h7_core.sysclksrc_csi_4: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/csi_4.overlay" platform_allow: nucleo_h743zi integration_platforms: - nucleo_h743zi - drivers.stm32_clock_configuration.h7_core.sysclksrc_hse_8: + drivers.clock.stm32_clock_configuration.h7_core.sysclksrc_hse_8: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/hse_8.overlay" platform_allow: nucleo_h743zi integration_platforms: - nucleo_h743zi - drivers.stm32_clock_configuration.h7_core.sysclksrc_pll_csi_96: + drivers.clock.stm32_clock_configuration.h7_core.sysclksrc_pll_csi_96: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_csi_96.overlay" platform_allow: nucleo_h743zi integration_platforms: - nucleo_h743zi - drivers.stm32_clock_configuration.h7_core.sysclksrc_pll_hse_550: + drivers.clock.stm32_clock_configuration.h7_core.sysclksrc_pll_hse_550: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_hse_550.overlay" platform_allow: - nucleo_h723zg diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_devices/prj.conf b/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_devices/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_devices/prj.conf +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_devices/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_devices/testcase.yaml b/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_devices/testcase.yaml index d914bb93ae3..692c716fcee 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_devices/testcase.yaml +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_devices/testcase.yaml @@ -2,17 +2,17 @@ common: timeout: 5 platform_allow: nucleo_h723zg tests: - drivers.stm32_clock_configuration.h7_dev.spi1_pllq_1_d1ppre_1: + drivers.clock.stm32_clock_configuration.h7_dev.spi1_pllq_1_d1ppre_1: extra_args: DTC_OVERLAY_FILE="boards/core_init.overlay;boards/spi1_pllq_1_d1ppre_1.overlay" - drivers.stm32_clock_configuration.h7_dev.spi1_pllq_2_d1ppre_4: + drivers.clock.stm32_clock_configuration.h7_dev.spi1_pllq_2_d1ppre_4: extra_args: DTC_OVERLAY_FILE="boards/core_init.overlay;boards/spi1_pllq_2_d1ppre_4.overlay" - drivers.stm32_clock_configuration.h7_dev.spi1_pll2p_1: + drivers.clock.stm32_clock_configuration.h7_dev.spi1_pll2p_1: extra_args: DTC_OVERLAY_FILE="boards/core_init.overlay;boards/spi1_pll2p_1.overlay" - drivers.stm32_clock_configuration.h7_dev.spi1_pll3p_1_d1ppre_4: + drivers.clock.stm32_clock_configuration.h7_dev.spi1_pll3p_1_d1ppre_4: extra_args: DTC_OVERLAY_FILE="boards/core_init.overlay;boards/spi1_pll3p_1_d1ppre_4.overlay" - drivers.stm32_clock_configuration.h7_dev.spi1_per_ck_d1ppre_1: + drivers.clock.stm32_clock_configuration.h7_dev.spi1_per_ck_d1ppre_1: extra_args: DTC_OVERLAY_FILE="boards/core_init.overlay;boards/spi1_per_ck_d1ppre_1.overlay" - drivers.stm32_clock_configuration.h7_dev.spi1_per_ck_hsi: + drivers.clock.stm32_clock_configuration.h7_dev.spi1_per_ck_hsi: extra_args: DTC_OVERLAY_FILE="boards/core_init.overlay;boards/spi1_per_ck_hsi.overlay" - drivers.stm32_clock_configuration.h7_dev.spi1_per_ck_hse: + drivers.clock.stm32_clock_configuration.h7_dev.spi1_per_ck_hse: extra_args: DTC_OVERLAY_FILE="boards/core_init.overlay;boards/spi1_per_ck_hse.overlay" diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/boards/pll_hse_fracn_160.overlay b/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/boards/pll_hse_fracn_160.overlay new file mode 100644 index 00000000000..014ef48fd7d --- /dev/null +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/boards/pll_hse_fracn_160.overlay @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 Jatty Andriean + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Warning: This overlay performs configuration from clean sheet. + * It is assumed that it is applied after clear_clocks.overlay file. + */ + +/* + * Warning: HSE is not implemented on available boards, hence: + * This configuration is only available for build + */ + +&clk_hse { + status = "okay"; + clock-frequency = <16777216>; +}; + +&pll1 { + div-m = <2>; + mul-n = <19>; + div-p = <1>; + div-q = <1>; + div-r = <1>; + fracn = <602>; + clocks = <&clk_hse>; + status = "okay"; +}; + +&rcc { + clocks = <&pll>; + clock-frequency = ; + ahb-prescaler = <1>; + apb1-prescaler = <1>; + apb2-prescaler = <1>; + apb3-prescaler = <1>; +}; diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/boards/pll_hsi_fracn_160.overlay b/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/boards/pll_hsi_fracn_160.overlay new file mode 100644 index 00000000000..ffc339ad184 --- /dev/null +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/boards/pll_hsi_fracn_160.overlay @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 Jatty Andriean + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Warning: This overlay performs configuration from clean sheet. + * It is assumed that it is applied after clear_clocks.overlay file. + */ + +&clk_hsi { + status = "okay"; +}; + +&pll1 { + div-m = <1>; + mul-n = <20>; + div-p = <2>; + div-q = <2>; + div-r = <2>; + fracn = <0>; + clocks = <&clk_hsi>; + status = "okay"; +}; + +&rcc { + clocks = <&pll>; + clock-frequency = ; + ahb-prescaler = <1>; + apb1-prescaler = <1>; + apb2-prescaler = <1>; + apb3-prescaler = <1>; +}; diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/prj.conf b/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/prj.conf +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/testcase.yaml b/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/testcase.yaml index 6443e08f139..8c6e003b913 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/testcase.yaml +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/testcase.yaml @@ -2,25 +2,31 @@ common: timeout: 5 platform_allow: b_u585i_iot02a tests: - drivers.stm32_clock_configuration.u5.sysclksrc_pll_msis_160: + drivers.clock.stm32_clock_configuration.u5.sysclksrc_pll_msis_160: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_msis_160.overlay" - drivers.stm32_clock_configuration.u5.pll_msis_ahb_2_40: + drivers.clock.stm32_clock_configuration.u5.pll_msis_ahb_2_40: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_msis_ahb_2_40.overlay" - drivers.stm32_clock_configuration.u5.sysclksrc_pll_hsi_160: + drivers.clock.stm32_clock_configuration.u5.sysclksrc_pll_hsi_160: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_hsi_160.overlay" - drivers.stm32_clock_configuration.u5.sysclksrc_pll_hsi_40: + drivers.clock.stm32_clock_configuration.u5.sysclksrc_pll_hsi_40: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_hsi_40.overlay" - drivers.stm32_clock_configuration.u5.sysclksrc_msis_48: + drivers.clock.stm32_clock_configuration.u5.sysclksrc_msis_48: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/msis_48.overlay" - drivers.stm32_clock_configuration.u5.sysclksrc_msis_24: + drivers.clock.stm32_clock_configuration.u5.sysclksrc_msis_24: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/msis_24.overlay" - drivers.stm32_clock_configuration.u5.sysclksrc_hsi_16: + drivers.clock.stm32_clock_configuration.u5.sysclksrc_hsi_16: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/hsi_16.overlay" - drivers.stm32_clock_configuration.u5.sysclksrc_hse_16: + drivers.clock.stm32_clock_configuration.u5.sysclksrc_hse_16: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/hse_16.overlay" # Build only as HSE not implemened on available boards build_only: true - drivers.stm32_clock_configuration.u5.sysclksrc_pll_hse_160: + drivers.clock.stm32_clock_configuration.u5.sysclksrc_pll_hse_160: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_hse_160.overlay" # Build only as HSE not implemened on available boards build_only: true + drivers.clock.stm32_clock_configuration.u5.sysclksrc_pll_hse_fracn_160: + extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_hse_fracn_160.overlay" + # Build only as HSE not implemened on available boards + build_only: true + drivers.clock.stm32_clock_configuration.u5.sysclksrc_pll_hsi_fracn_160: + extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_hsi_fracn_160.overlay" diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_devices/prj.conf b/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_devices/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_devices/prj.conf +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_devices/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_devices/testcase.yaml b/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_devices/testcase.yaml index 5f27ed3bfbc..1a01b0c3895 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_devices/testcase.yaml +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_devices/testcase.yaml @@ -2,11 +2,11 @@ common: timeout: 5 platform_allow: b_u585i_iot02a tests: - drivers.stm32_clock_configuration.dev_u5.spi1_pclk2: + drivers.clock.stm32_clock_configuration.dev_u5.spi1_pclk2: extra_args: DTC_OVERLAY_FILE="boards/core_init.overlay;boards/spi1_pclk2.overlay" - drivers.stm32_clock_configuration.dev_u5.spi1_hsi_16: + drivers.clock.stm32_clock_configuration.dev_u5.spi1_hsi_16: extra_args: DTC_OVERLAY_FILE="boards/core_init.overlay;boards/spi1_hsi_16.overlay" - drivers.stm32_clock_configuration.dev_u5.spi1_msik: + drivers.clock.stm32_clock_configuration.dev_u5.spi1_msik: extra_args: DTC_OVERLAY_FILE="boards/core_init.overlay;boards/spi1_msik.overlay" - drivers.stm32_clock_configuration.dev_u5.spi1_sysclk: + drivers.clock.stm32_clock_configuration.dev_u5.spi1_sysclk: extra_args: DTC_OVERLAY_FILE="boards/core_init.overlay;boards/spi1_sysclk.overlay" diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32wba_core/prj.conf b/tests/drivers/clock_control/stm32_clock_configuration/stm32wba_core/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32wba_core/prj.conf +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32wba_core/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32wba_core/testcase.yaml b/tests/drivers/clock_control/stm32_clock_configuration/stm32wba_core/testcase.yaml index e540315bcea..bdaf05c588e 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32wba_core/testcase.yaml +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32wba_core/testcase.yaml @@ -2,15 +2,15 @@ common: timeout: 5 platform_allow: nucleo_wba52cg tests: - drivers.stm32_clock_configuration.wba.sysclksrc_hsi_32: + drivers.clock.stm32_clock_configuration.wba.sysclksrc_hsi_32: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/hsi_16.overlay" - drivers.stm32_clock_configuration.wba.sysclksrc_hsi_32_ahb5_div: + drivers.clock.stm32_clock_configuration.wba.sysclksrc_hsi_32_ahb5_div: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/hsi_16_ahb5_div.overlay" - drivers.stm32_clock_configuration.wba.sysclksrc_hse_16: + drivers.clock.stm32_clock_configuration.wba.sysclksrc_hse_16: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/hse_16.overlay" - drivers.stm32_clock_configuration.wba.sysclksrc_hse_32: + drivers.clock.stm32_clock_configuration.wba.sysclksrc_hse_32: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/hse_32.overlay" - drivers.stm32_clock_configuration.wba.sysclksrc_pll_hse_100: + drivers.clock.stm32_clock_configuration.wba.sysclksrc_pll_hse_100: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_hse_100.overlay" - drivers.stm32_clock_configuration.wba.sysclksrc_pll_hse_50: + drivers.clock.stm32_clock_configuration.wba.sysclksrc_pll_hse_50: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_hse_100_ahb_50.overlay" diff --git a/tests/drivers/coredump/coredump_api/prj.conf b/tests/drivers/coredump/coredump_api/prj.conf index 55308753805..9684306ce68 100644 --- a/tests/drivers/coredump/coredump_api/prj.conf +++ b/tests/drivers/coredump/coredump_api/prj.conf @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_COREDUMP_DEVICE=y diff --git a/tests/drivers/coredump/coredump_api/testcase.yaml b/tests/drivers/coredump/coredump_api/testcase.yaml index 3f18bedd22e..bece8efb2b2 100644 --- a/tests/drivers/coredump/coredump_api/testcase.yaml +++ b/tests/drivers/coredump/coredump_api/testcase.yaml @@ -33,6 +33,8 @@ tests: debug.coredump.drivers.api: filter: CONFIG_ARCH_SUPPORTS_COREDUMP platform_exclude: qemu_riscv32 + arch_exclude: + - posix harness: console integration_platforms: - qemu_x86 diff --git a/tests/drivers/counter/counter_basic_api/boards/esp32c3_luatos_core.overlay b/tests/drivers/counter/counter_basic_api/boards/esp32c3_luatos_core.overlay new file mode 100644 index 00000000000..241947b0643 --- /dev/null +++ b/tests/drivers/counter/counter_basic_api/boards/esp32c3_luatos_core.overlay @@ -0,0 +1,3 @@ +&timer0 { + status = "okay"; +}; diff --git a/tests/drivers/counter/counter_basic_api/boards/esp32c3_luatos_core_usb.overlay b/tests/drivers/counter/counter_basic_api/boards/esp32c3_luatos_core_usb.overlay new file mode 100644 index 00000000000..241947b0643 --- /dev/null +++ b/tests/drivers/counter/counter_basic_api/boards/esp32c3_luatos_core_usb.overlay @@ -0,0 +1,3 @@ +&timer0 { + status = "okay"; +}; diff --git a/tests/drivers/counter/counter_basic_api/boards/esp32s3_luatos_core.overlay b/tests/drivers/counter/counter_basic_api/boards/esp32s3_luatos_core.overlay new file mode 100644 index 00000000000..2b3ef4f24ca --- /dev/null +++ b/tests/drivers/counter/counter_basic_api/boards/esp32s3_luatos_core.overlay @@ -0,0 +1,3 @@ +&timer3 { + status = "okay"; +}; diff --git a/tests/drivers/counter/counter_basic_api/boards/esp32s3_luatos_core_usb.overlay b/tests/drivers/counter/counter_basic_api/boards/esp32s3_luatos_core_usb.overlay new file mode 100644 index 00000000000..2b3ef4f24ca --- /dev/null +++ b/tests/drivers/counter/counter_basic_api/boards/esp32s3_luatos_core_usb.overlay @@ -0,0 +1,3 @@ +&timer3 { + status = "okay"; +}; diff --git a/tests/drivers/counter/counter_basic_api/boards/lpcxpresso55s69_cpu0.overlay b/tests/drivers/counter/counter_basic_api/boards/lpcxpresso55s69_cpu0.overlay new file mode 100644 index 00000000000..968741c5148 --- /dev/null +++ b/tests/drivers/counter/counter_basic_api/boards/lpcxpresso55s69_cpu0.overlay @@ -0,0 +1,15 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&mrt_channel1 { + status = "okay"; +}; + +/* channel 2 disabled to test disabled channel not breaking things */ + +&mrt_channel3 { + status = "okay"; +}; diff --git a/tests/drivers/counter/counter_basic_api/boards/s32z270dc2_rtu0_r52.overlay b/tests/drivers/counter/counter_basic_api/boards/s32z270dc2_rtu0_r52.overlay index 32e77ec10fe..d35e70e8a12 100644 --- a/tests/drivers/counter/counter_basic_api/boards/s32z270dc2_rtu0_r52.overlay +++ b/tests/drivers/counter/counter_basic_api/boards/s32z270dc2_rtu0_r52.overlay @@ -1,5 +1,5 @@ /* - * Copyright 2022 NXP + * Copyright 2022-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,3 +23,9 @@ prescaler = <32>; status = "okay"; }; + +&pit0 { + pit-channel = <0>; + pit-period = <1000000>; + status = "okay"; +}; diff --git a/tests/drivers/counter/counter_basic_api/boards/s32z270dc2_rtu1_r52.overlay b/tests/drivers/counter/counter_basic_api/boards/s32z270dc2_rtu1_r52.overlay index 32e77ec10fe..d35e70e8a12 100644 --- a/tests/drivers/counter/counter_basic_api/boards/s32z270dc2_rtu1_r52.overlay +++ b/tests/drivers/counter/counter_basic_api/boards/s32z270dc2_rtu1_r52.overlay @@ -1,5 +1,5 @@ /* - * Copyright 2022 NXP + * Copyright 2022-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,3 +23,9 @@ prescaler = <32>; status = "okay"; }; + +&pit0 { + pit-channel = <0>; + pit-period = <1000000>; + status = "okay"; +}; diff --git a/tests/drivers/counter/counter_basic_api/prj.conf b/tests/drivers/counter/counter_basic_api/prj.conf index 934b7d4a9de..cc386ea8623 100644 --- a/tests/drivers/counter/counter_basic_api/prj.conf +++ b/tests/drivers/counter/counter_basic_api/prj.conf @@ -1,6 +1,5 @@ CONFIG_COUNTER=y CONFIG_BT=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y CONFIG_LOG=y diff --git a/tests/drivers/counter/counter_basic_api/src/test_counter.c b/tests/drivers/counter/counter_basic_api/src/test_counter.c index f2677648b25..f63ee5ce6c4 100644 --- a/tests/drivers/counter/counter_basic_api/src/test_counter.c +++ b/tests/drivers/counter/counter_basic_api/src/test_counter.c @@ -66,6 +66,9 @@ static const struct device *const devices[] = { #ifdef CONFIG_COUNTER_MCUX_QTMR DEVS_FOR_DT_COMPAT(nxp_imx_tmr) #endif +#ifdef CONFIG_COUNTER_NXP_MRT + DEVS_FOR_DT_COMPAT(nxp_mrt_channel) +#endif #ifdef CONFIG_COUNTER_MCUX_LPC_RTC DEVS_FOR_DT_COMPAT(nxp_lpc_rtc) #endif @@ -93,6 +96,9 @@ static const struct device *const devices[] = { #ifdef CONFIG_COUNTER_TIMER_GD32 DEVS_FOR_DT_COMPAT(gd_gd32_timer) #endif +#ifdef CONFIG_COUNTER_TIMER_RPI_PICO + DEVS_FOR_DT_COMPAT(raspberrypi_pico_timer) +#endif }; static const struct device *const period_devs[] = { diff --git a/tests/drivers/counter/counter_basic_api/testcase.yaml b/tests/drivers/counter/counter_basic_api/testcase.yaml index f31fa8f3af9..2173d417c06 100644 --- a/tests/drivers/counter/counter_basic_api/testcase.yaml +++ b/tests/drivers/counter/counter_basic_api/testcase.yaml @@ -18,3 +18,12 @@ tests: - CONFIG_ZERO_LATENCY_IRQS=y extra_args: DTC_OVERLAY_FILE="boards/nrf52840dk_nrf52840.overlay;boards/nrf52840dk_nrf52840_zli.overlay" + drivers.counter.basic_api.stm32_subsec: + tags: + - drivers + - counter + depends_on: counter + platform_allow: nucleo_f429zi nucleo_wba52cg + timeout: 600 + extra_configs: + - CONFIG_COUNTER_RTC_STM32_SUBSECONDS=y diff --git a/tests/drivers/counter/counter_nrf_rtc/fixed_top/prj.conf b/tests/drivers/counter/counter_nrf_rtc/fixed_top/prj.conf index cf88000ca13..e00e8973c78 100644 --- a/tests/drivers/counter/counter_nrf_rtc/fixed_top/prj.conf +++ b/tests/drivers/counter/counter_nrf_rtc/fixed_top/prj.conf @@ -1,4 +1,3 @@ CONFIG_COUNTER=y CONFIG_BT=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/counter/counter_seconds/prj.conf b/tests/drivers/counter/counter_seconds/prj.conf index ebdc464620e..e99f557e87c 100644 --- a/tests/drivers/counter/counter_seconds/prj.conf +++ b/tests/drivers/counter/counter_seconds/prj.conf @@ -1,3 +1,2 @@ CONFIG_COUNTER=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/counter/maxim_ds3231_api/prj.conf b/tests/drivers/counter/maxim_ds3231_api/prj.conf index ca174661fcb..7efb84aa558 100644 --- a/tests/drivers/counter/maxim_ds3231_api/prj.conf +++ b/tests/drivers/counter/maxim_ds3231_api/prj.conf @@ -4,6 +4,5 @@ CONFIG_COUNTER_MAXIM_DS3231=y CONFIG_COUNTER_INIT_PRIORITY=65 CONFIG_BT=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y CONFIG_LOG=y diff --git a/tests/drivers/dac/dac_api/prj.conf b/tests/drivers/dac/dac_api/prj.conf index 7e6cabcc12b..c9ef47c7248 100644 --- a/tests/drivers/dac/dac_api/prj.conf +++ b/tests/drivers/dac/dac_api/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_DAC=y CONFIG_TEST_USERSPACE=y diff --git a/tests/drivers/dac/dac_api/src/test_dac.c b/tests/drivers/dac/dac_api/src/test_dac.c index 491fc61a317..9c45ea041f6 100644 --- a/tests/drivers/dac/dac_api/src/test_dac.c +++ b/tests/drivers/dac/dac_api/src/test_dac.c @@ -27,6 +27,7 @@ defined(CONFIG_BOARD_STM32H573I_DK) || \ defined(CONFIG_BOARD_B_U585I_IOT02A) || \ defined(CONFIG_BOARD_NUCLEO_U575ZI_Q) || \ + defined(CONFIG_BOARD_NUCLEO_U5A5ZJ_Q) || \ defined(CONFIG_BOARD_NUCLEO_WL55JC) || \ defined(CONFIG_BOARD_RONOTH_LODEV) @@ -45,7 +46,8 @@ defined(CONFIG_BOARD_FRDM_K22F) || \ defined(CONFIG_BOARD_SEEEDUINO_XIAO) || \ defined(CONFIG_BOARD_ARDUINO_MKRZERO) || \ - defined(CONFIG_BOARD_ARDUINO_ZERO) + defined(CONFIG_BOARD_ARDUINO_ZERO) || \ + defined(CONFIG_BOARD_LPCXPRESSO55S36) #define DAC_DEVICE_NODE DT_NODELABEL(dac0) #define DAC_RESOLUTION 12 diff --git a/tests/drivers/dac/dac_loopback/boards/lpcxpresso55s36.overlay b/tests/drivers/dac/dac_loopback/boards/lpcxpresso55s36.overlay new file mode 100644 index 00000000000..4c56612e5b6 --- /dev/null +++ b/tests/drivers/dac/dac_loopback/boards/lpcxpresso55s36.overlay @@ -0,0 +1,10 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&dac0 { + /* To align reference voltage with ADC. */ + voltage-reference = <1>; +}; diff --git a/tests/drivers/dac/dac_loopback/prj.conf b/tests/drivers/dac/dac_loopback/prj.conf index a5f652dd229..4ec36d6e3e0 100644 --- a/tests/drivers/dac/dac_loopback/prj.conf +++ b/tests/drivers/dac/dac_loopback/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_DAC=y CONFIG_ADC=y diff --git a/tests/drivers/dac/dac_loopback/src/test_dac.c b/tests/drivers/dac/dac_loopback/src/test_dac.c index dff32bbfba2..9b571bf384c 100644 --- a/tests/drivers/dac/dac_loopback/src/test_dac.c +++ b/tests/drivers/dac/dac_loopback/src/test_dac.c @@ -125,6 +125,22 @@ #define ADC_ACQUISITION_TIME ADC_ACQ_TIME_DEFAULT #define ADC_CHANNEL_ID 23 +#elif defined(CONFIG_BOARD_LPCXPRESSO55S36) + +/* DAC0 output is internally available on ADC0_SE4 */ + +#define DAC_DEVICE_NODE DT_NODELABEL(dac0) +#define DAC_RESOLUTION 12 +#define DAC_CHANNEL_ID 0 + +#define ADC_DEVICE_NODE DT_NODELABEL(adc0) +#define ADC_RESOLUTION 12 +#define ADC_GAIN ADC_GAIN_1 +#define ADC_REFERENCE ADC_REF_EXTERNAL0 +#define ADC_ACQUISITION_TIME ADC_ACQ_TIME_DEFAULT +#define ADC_CHANNEL_ID 0 +#define ADC_1ST_CHANNEL_INPUT 4 + #elif defined(CONFIG_BOARD_BL652_DVK) || \ defined(CONFIG_BOARD_BL653_DVK) || \ defined(CONFIG_BOARD_BL654_DVK) || \ @@ -168,7 +184,8 @@ static const struct adc_channel_cfg adc_ch_cfg = { #if defined(CONFIG_BOARD_BL652_DVK) || \ defined(CONFIG_BOARD_BL653_DVK) || \ defined(CONFIG_BOARD_BL654_DVK) || \ - defined(CONFIG_BOARD_BL5340_DVK_CPUAPP) + defined(CONFIG_BOARD_BL5340_DVK_CPUAPP) || \ + defined(CONFIG_BOARD_LPCXPRESSO55S36) .input_positive = ADC_1ST_CHANNEL_INPUT, #endif }; diff --git a/tests/drivers/dac/dac_loopback/testcase.yaml b/tests/drivers/dac/dac_loopback/testcase.yaml index fe1962e5b2f..f1a682f2f5b 100644 --- a/tests/drivers/dac/dac_loopback/testcase.yaml +++ b/tests/drivers/dac/dac_loopback/testcase.yaml @@ -28,5 +28,6 @@ tests: - nucleo_f746zg - nucleo_g071rb - nucleo_wl55jc + - lpcxpresso55s36 integration_platforms: - nucleo_f207zg diff --git a/tests/drivers/disk/disk_access/boards/qemu_x86_64.conf b/tests/drivers/disk/disk_access/boards/qemu_x86_64.conf index 9760440e93b..0c14f763bf9 100644 --- a/tests/drivers/disk/disk_access/boards/qemu_x86_64.conf +++ b/tests/drivers/disk/disk_access/boards/qemu_x86_64.conf @@ -1,4 +1,4 @@ -CONFIG_X86_ACPI=y +CONFIG_ACPI=y CONFIG_PCIE=y CONFIG_PCIE_MSI=y CONFIG_PCIE_MSI_X=y diff --git a/tests/drivers/disk/disk_access/boards/qemu_x86_64.overlay b/tests/drivers/disk/disk_access/boards/qemu_x86_64.overlay index 1485f30e4d5..65f66de9273 100644 --- a/tests/drivers/disk/disk_access/boards/qemu_x86_64.overlay +++ b/tests/drivers/disk/disk_access/boards/qemu_x86_64.overlay @@ -18,4 +18,11 @@ status = "okay"; }; }; + + ramdisk0 { + compatible = "zephyr,ram-disk"; + disk-name = "RAM"; + sector-size = <512>; + sector-count = <192>; + }; }; diff --git a/tests/drivers/disk/disk_access/prj.conf b/tests/drivers/disk/disk_access/prj.conf index 2fa7f3a59f1..0fbfa56642f 100644 --- a/tests/drivers/disk/disk_access/prj.conf +++ b/tests/drivers/disk/disk_access/prj.conf @@ -1,4 +1,3 @@ CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_DISK_ACCESS=y diff --git a/tests/drivers/disk/disk_access/src/main.c b/tests/drivers/disk/disk_access/src/main.c index 3677556ef0c..97fafae9d8c 100644 --- a/tests/drivers/disk/disk_access/src/main.c +++ b/tests/drivers/disk/disk_access/src/main.c @@ -19,7 +19,7 @@ #elif IS_ENABLED(CONFIG_DISK_DRIVER_MMC) #define DISK_NAME CONFIG_MMC_VOLUME_NAME #elif IS_ENABLED(CONFIG_DISK_DRIVER_RAM) -#define DISK_NAME CONFIG_DISK_RAM_VOLUME_NAME +#define DISK_NAME "RAM" #elif IS_ENABLED(CONFIG_NVME) #define DISK_NAME "nvme0n0" #else @@ -41,7 +41,8 @@ static const char *disk_pdrv = DISK_NAME; static uint32_t disk_sector_count; static uint32_t disk_sector_size; -static uint8_t scratch_buf[2][SECTOR_COUNT4 * SECTOR_SIZE + 1]; +/* + 4 to make sure the second buffer is dword-aligned for NVME */ +static uint8_t scratch_buf[2][SECTOR_COUNT4 * SECTOR_SIZE + 4]; /* Sets up test by initializing disk */ diff --git a/tests/drivers/disk/disk_access/testcase.yaml b/tests/drivers/disk/disk_access/testcase.yaml index 2dc6cac00af..86c7a365a5f 100644 --- a/tests/drivers/disk/disk_access/testcase.yaml +++ b/tests/drivers/disk/disk_access/testcase.yaml @@ -14,8 +14,6 @@ tests: - mimxrt1050_evk - mimxrt1064_evk drivers.disk.ram: - extra_configs: - - CONFIG_DISK_DRIVER_RAM=y platform_allow: qemu_x86_64 drivers.disk.nvme: extra_configs: diff --git a/tests/drivers/disk/disk_performance/boards/qemu_x86_64.conf b/tests/drivers/disk/disk_performance/boards/qemu_x86_64.conf index 9760440e93b..0c14f763bf9 100644 --- a/tests/drivers/disk/disk_performance/boards/qemu_x86_64.conf +++ b/tests/drivers/disk/disk_performance/boards/qemu_x86_64.conf @@ -1,4 +1,4 @@ -CONFIG_X86_ACPI=y +CONFIG_ACPI=y CONFIG_PCIE=y CONFIG_PCIE_MSI=y CONFIG_PCIE_MSI_X=y diff --git a/tests/drivers/disk/disk_performance/prj.conf b/tests/drivers/disk/disk_performance/prj.conf index 8973b711ba5..db25d96059d 100644 --- a/tests/drivers/disk/disk_performance/prj.conf +++ b/tests/drivers/disk/disk_performance/prj.conf @@ -1,6 +1,5 @@ CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_DISK_ACCESS=y CONFIG_TIMING_FUNCTIONS=y CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/drivers/disk/disk_performance/src/main.c b/tests/drivers/disk/disk_performance/src/main.c index 5def5931319..7d3a67b7a51 100644 --- a/tests/drivers/disk/disk_performance/src/main.c +++ b/tests/drivers/disk/disk_performance/src/main.c @@ -10,14 +10,12 @@ #include #include #include -#include +#include #if defined(CONFIG_DISK_DRIVER_SDMMC) #define DISK_NAME CONFIG_SDMMC_VOLUME_NAME #elif IS_ENABLED(CONFIG_DISK_DRIVER_MMC) #define DISK_NAME CONFIG_MMC_VOLUME_NAME -#elif IS_ENABLED(CONFIG_DISK_DRIVER_RAM) -#define DISK_NAME CONFIG_DISK_RAM_VOLUME_NAME #elif IS_ENABLED(CONFIG_NVME) #define DISK_NAME "nvme0n0" #else diff --git a/tests/drivers/disk/disk_performance/testcase.yaml b/tests/drivers/disk/disk_performance/testcase.yaml index f51e9f196e7..af008bf56e0 100644 --- a/tests/drivers/disk/disk_performance/testcase.yaml +++ b/tests/drivers/disk/disk_performance/testcase.yaml @@ -11,7 +11,7 @@ tests: integration_platforms: - mimxrt1064_evk - mimxrt595_evk_cm33 - drivers.disk_performance.disk.nvme: + drivers.disk.disk_performance.disk.nvme: extra_configs: - CONFIG_NVME=y platform_allow: qemu_x86_64 diff --git a/tests/drivers/dma/chan_blen_transfer/Kconfig b/tests/drivers/dma/chan_blen_transfer/Kconfig index 7867be5a629..748f380b71e 100644 --- a/tests/drivers/dma/chan_blen_transfer/Kconfig +++ b/tests/drivers/dma/chan_blen_transfer/Kconfig @@ -21,3 +21,7 @@ config DMA_LOOP_TRANSFER_SRAM_SECTION config DMA_LOOP_TRANSFER_NUMBER_OF_DMAS int "Number of DMAs to test" default 1 + +config DMA_TRANSFER_BURST16 + bool "Enable loop transfers of 16-beat bursts" + default y diff --git a/tests/drivers/dma/chan_blen_transfer/boards/adp_xc7k_ae350.conf b/tests/drivers/dma/chan_blen_transfer/boards/adp_xc7k_ae350.conf new file mode 100644 index 00000000000..c448e14811f --- /dev/null +++ b/tests/drivers/dma/chan_blen_transfer/boards/adp_xc7k_ae350.conf @@ -0,0 +1 @@ +CONFIG_NOCACHE_MEMORY=y diff --git a/tests/drivers/dma/chan_blen_transfer/boards/adp_xc7k_ae350.overlay b/tests/drivers/dma/chan_blen_transfer/boards/adp_xc7k_ae350.overlay new file mode 100644 index 00000000000..c58ffdfcc20 --- /dev/null +++ b/tests/drivers/dma/chan_blen_transfer/boards/adp_xc7k_ae350.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2023 Andes Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +test_dma0: &dma0 { + status = "okay"; +}; diff --git a/tests/drivers/dma/chan_blen_transfer/boards/da1469x_dk_pro.conf b/tests/drivers/dma/chan_blen_transfer/boards/da1469x_dk_pro.conf new file mode 100644 index 00000000000..9664ee7c621 --- /dev/null +++ b/tests/drivers/dma/chan_blen_transfer/boards/da1469x_dk_pro.conf @@ -0,0 +1 @@ +CONFIG_DMA_TRANSFER_BURST16=n diff --git a/tests/drivers/dma/chan_blen_transfer/boards/da1469x_dk_pro.overlay b/tests/drivers/dma/chan_blen_transfer/boards/da1469x_dk_pro.overlay new file mode 100644 index 00000000000..eca3c9dc752 --- /dev/null +++ b/tests/drivers/dma/chan_blen_transfer/boards/da1469x_dk_pro.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2023 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + + test_dma0: &dma { + status = "okay"; +}; diff --git a/tests/drivers/dma/chan_blen_transfer/boards/esp32c3_luatos_core.conf b/tests/drivers/dma/chan_blen_transfer/boards/esp32c3_luatos_core.conf new file mode 100644 index 00000000000..56bf25e718b --- /dev/null +++ b/tests/drivers/dma/chan_blen_transfer/boards/esp32c3_luatos_core.conf @@ -0,0 +1,3 @@ +CONFIG_DMA_TRANSFER_CHANNEL_NR_0=5 +CONFIG_DMA_TRANSFER_CHANNEL_NR_1=0 +CONFIG_HEAP_MEM_POOL_SIZE=32768 diff --git a/tests/drivers/dma/chan_blen_transfer/boards/esp32c3_luatos_core.overlay b/tests/drivers/dma/chan_blen_transfer/boards/esp32c3_luatos_core.overlay new file mode 100644 index 00000000000..9098b0dd5b9 --- /dev/null +++ b/tests/drivers/dma/chan_blen_transfer/boards/esp32c3_luatos_core.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&dma { + status = "okay"; +}; + +test_dma0: &dma { }; diff --git a/tests/drivers/dma/chan_blen_transfer/boards/esp32c3_luatos_core_usb.conf b/tests/drivers/dma/chan_blen_transfer/boards/esp32c3_luatos_core_usb.conf new file mode 100644 index 00000000000..56bf25e718b --- /dev/null +++ b/tests/drivers/dma/chan_blen_transfer/boards/esp32c3_luatos_core_usb.conf @@ -0,0 +1,3 @@ +CONFIG_DMA_TRANSFER_CHANNEL_NR_0=5 +CONFIG_DMA_TRANSFER_CHANNEL_NR_1=0 +CONFIG_HEAP_MEM_POOL_SIZE=32768 diff --git a/tests/drivers/dma/chan_blen_transfer/boards/esp32c3_luatos_core_usb.overlay b/tests/drivers/dma/chan_blen_transfer/boards/esp32c3_luatos_core_usb.overlay new file mode 100644 index 00000000000..9098b0dd5b9 --- /dev/null +++ b/tests/drivers/dma/chan_blen_transfer/boards/esp32c3_luatos_core_usb.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&dma { + status = "okay"; +}; + +test_dma0: &dma { }; diff --git a/tests/drivers/dma/chan_blen_transfer/boards/esp32s3_luatos_core.conf b/tests/drivers/dma/chan_blen_transfer/boards/esp32s3_luatos_core.conf new file mode 100644 index 00000000000..d8c5932fbe9 --- /dev/null +++ b/tests/drivers/dma/chan_blen_transfer/boards/esp32s3_luatos_core.conf @@ -0,0 +1,2 @@ +CONFIG_DMA_TRANSFER_CHANNEL_NR_0=5 +CONFIG_DMA_TRANSFER_CHANNEL_NR_1=0 diff --git a/tests/drivers/dma/chan_blen_transfer/boards/esp32s3_luatos_core.overlay b/tests/drivers/dma/chan_blen_transfer/boards/esp32s3_luatos_core.overlay new file mode 100644 index 00000000000..ca3f3ca2c99 --- /dev/null +++ b/tests/drivers/dma/chan_blen_transfer/boards/esp32s3_luatos_core.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&dma { + status = "okay"; +}; + +test_dma0: &dma { }; diff --git a/tests/drivers/dma/chan_blen_transfer/boards/esp32s3_luatos_core_usb.conf b/tests/drivers/dma/chan_blen_transfer/boards/esp32s3_luatos_core_usb.conf new file mode 100644 index 00000000000..d8c5932fbe9 --- /dev/null +++ b/tests/drivers/dma/chan_blen_transfer/boards/esp32s3_luatos_core_usb.conf @@ -0,0 +1,2 @@ +CONFIG_DMA_TRANSFER_CHANNEL_NR_0=5 +CONFIG_DMA_TRANSFER_CHANNEL_NR_1=0 diff --git a/tests/drivers/dma/chan_blen_transfer/boards/esp32s3_luatos_core_usb.overlay b/tests/drivers/dma/chan_blen_transfer/boards/esp32s3_luatos_core_usb.overlay new file mode 100644 index 00000000000..ca3f3ca2c99 --- /dev/null +++ b/tests/drivers/dma/chan_blen_transfer/boards/esp32s3_luatos_core_usb.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&dma { + status = "okay"; +}; + +test_dma0: &dma { }; diff --git a/tests/drivers/dma/chan_blen_transfer/boards/mr_canhubk3.conf b/tests/drivers/dma/chan_blen_transfer/boards/mr_canhubk3.conf new file mode 100644 index 00000000000..8c952de5bd9 --- /dev/null +++ b/tests/drivers/dma/chan_blen_transfer/boards/mr_canhubk3.conf @@ -0,0 +1,2 @@ +CONFIG_DMA_TRANSFER_CHANNEL_NR_0=12 +CONFIG_DMA_TRANSFER_CHANNEL_NR_1=31 diff --git a/tests/drivers/dma/chan_blen_transfer/boards/mr_canhubk3.overlay b/tests/drivers/dma/chan_blen_transfer/boards/mr_canhubk3.overlay new file mode 100644 index 00000000000..afc9c1b2495 --- /dev/null +++ b/tests/drivers/dma/chan_blen_transfer/boards/mr_canhubk3.overlay @@ -0,0 +1,7 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +test_dma0: &edma0 { }; diff --git a/tests/drivers/dma/chan_blen_transfer/boards/nucleo_h743zi.overlay b/tests/drivers/dma/chan_blen_transfer/boards/nucleo_h743zi.overlay index 20c8062f325..35e5f3935d3 100644 --- a/tests/drivers/dma/chan_blen_transfer/boards/nucleo_h743zi.overlay +++ b/tests/drivers/dma/chan_blen_transfer/boards/nucleo_h743zi.overlay @@ -2,6 +2,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + &dma1 { status = "okay"; }; @@ -18,7 +20,7 @@ test_dma0: &dmamux1 { * to be non-cachable. */ &sram4 { - zephyr,memory-attr = "RAM_NOCACHE"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) )>; }; &bdma1 { diff --git a/tests/drivers/dma/chan_blen_transfer/prj.conf b/tests/drivers/dma/chan_blen_transfer/prj.conf index 178b21813f2..605d90989ed 100644 --- a/tests/drivers/dma/chan_blen_transfer/prj.conf +++ b/tests/drivers/dma/chan_blen_transfer/prj.conf @@ -2,4 +2,3 @@ CONFIG_DMA=y CONFIG_ZTEST=y CONFIG_LOG=y CONFIG_DMA_LOG_LEVEL_INF=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/dma/chan_blen_transfer/src/test_dma.c b/tests/drivers/dma/chan_blen_transfer/src/test_dma.c index d0fa561f37b..312e7666aec 100644 --- a/tests/drivers/dma/chan_blen_transfer/src/test_dma.c +++ b/tests/drivers/dma/chan_blen_transfer/src/test_dma.c @@ -106,6 +106,7 @@ static int test_task(const struct device *dma, uint32_t chan_id, uint32_t blen) #define DMA_NAME(i, _) test_dma##i #define DMA_LIST LISTIFY(CONFIG_DMA_LOOP_TRANSFER_NUMBER_OF_DMAS, DMA_NAME, (,)) +#if CONFIG_DMA_TRANSFER_BURST16 #define TEST_TASK(dma_name) \ ZTEST(dma_m2m, test_##dma_name##_m2m_chan0_burst8) \ { \ @@ -130,5 +131,19 @@ static int test_task(const struct device *dma, uint32_t chan_id, uint32_t blen) const struct device *dma = DEVICE_DT_GET(DT_NODELABEL(dma_name)); \ zassert_true((test_task(dma, CONFIG_DMA_TRANSFER_CHANNEL_NR_1, 16) == TC_PASS)); \ } +#else +#define TEST_TASK(dma_name) \ + ZTEST(dma_m2m, test_##dma_name##_m2m_chan0_burst8) \ + { \ + const struct device *dma = DEVICE_DT_GET(DT_NODELABEL(dma_name)); \ + zassert_true((test_task(dma, CONFIG_DMA_TRANSFER_CHANNEL_NR_0, 8) == TC_PASS)); \ + } \ + \ + ZTEST(dma_m2m, test_##dma_name##_m2m_chan1_burst8) \ + { \ + const struct device *dma = DEVICE_DT_GET(DT_NODELABEL(dma_name)); \ + zassert_true((test_task(dma, CONFIG_DMA_TRANSFER_CHANNEL_NR_1, 8) == TC_PASS)); \ + } +#endif FOR_EACH(TEST_TASK, (), DMA_LIST); diff --git a/tests/drivers/dma/chan_blen_transfer/testcase.yaml b/tests/drivers/dma/chan_blen_transfer/testcase.yaml index 972313adff0..b87f7bb9d34 100644 --- a/tests/drivers/dma/chan_blen_transfer/testcase.yaml +++ b/tests/drivers/dma/chan_blen_transfer/testcase.yaml @@ -1,15 +1,17 @@ tests: drivers.dma.chan_blen_transfer: min_ram: 16 - depends_on: dma + depends_on: + - dma tags: - - drivers - dma filter: dt_nodelabel_enabled("test_dma0") drivers.dma.chan_blen_transfer.low_footprint: - min_ram: 6 - depends_on: dma - - drivers + tags: + - dma + min_ram: 12 + depends_on: - dma filter: dt_nodelabel_enabled("test_dma0") - platform_allow: nucleo_c031c6 + platform_allow: + - nucleo_c031c6 diff --git a/tests/drivers/dma/chan_link_transfer/boards/mr_canhubk3.overlay b/tests/drivers/dma/chan_link_transfer/boards/mr_canhubk3.overlay new file mode 100644 index 00000000000..f13c97d754e --- /dev/null +++ b/tests/drivers/dma/chan_link_transfer/boards/mr_canhubk3.overlay @@ -0,0 +1,7 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +dma0: &edma0 { }; diff --git a/tests/drivers/dma/chan_link_transfer/prj.conf b/tests/drivers/dma/chan_link_transfer/prj.conf index 178b21813f2..605d90989ed 100644 --- a/tests/drivers/dma/chan_link_transfer/prj.conf +++ b/tests/drivers/dma/chan_link_transfer/prj.conf @@ -2,4 +2,3 @@ CONFIG_DMA=y CONFIG_ZTEST=y CONFIG_LOG=y CONFIG_DMA_LOG_LEVEL_INF=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/dma/loop_transfer/boards/adp_xc7k_ae350.conf b/tests/drivers/dma/loop_transfer/boards/adp_xc7k_ae350.conf new file mode 100644 index 00000000000..c448e14811f --- /dev/null +++ b/tests/drivers/dma/loop_transfer/boards/adp_xc7k_ae350.conf @@ -0,0 +1 @@ +CONFIG_NOCACHE_MEMORY=y diff --git a/tests/drivers/dma/loop_transfer/boards/adp_xc7k_ae350.overlay b/tests/drivers/dma/loop_transfer/boards/adp_xc7k_ae350.overlay new file mode 100644 index 00000000000..c58ffdfcc20 --- /dev/null +++ b/tests/drivers/dma/loop_transfer/boards/adp_xc7k_ae350.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2023 Andes Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +test_dma0: &dma0 { + status = "okay"; +}; diff --git a/tests/drivers/dma/loop_transfer/boards/esp32c3_luatos_core.conf b/tests/drivers/dma/loop_transfer/boards/esp32c3_luatos_core.conf new file mode 100644 index 00000000000..311bfc8f535 --- /dev/null +++ b/tests/drivers/dma/loop_transfer/boards/esp32c3_luatos_core.conf @@ -0,0 +1,2 @@ +CONFIG_DMA_LOOP_TRANSFER_CHANNEL_NR=0 +CONFIG_DMA_LOOP_TRANSFER_SIZE=4094 diff --git a/tests/drivers/dma/loop_transfer/boards/esp32c3_luatos_core.overlay b/tests/drivers/dma/loop_transfer/boards/esp32c3_luatos_core.overlay new file mode 100644 index 00000000000..9098b0dd5b9 --- /dev/null +++ b/tests/drivers/dma/loop_transfer/boards/esp32c3_luatos_core.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&dma { + status = "okay"; +}; + +test_dma0: &dma { }; diff --git a/tests/drivers/dma/loop_transfer/boards/esp32c3_luatos_core_usb.conf b/tests/drivers/dma/loop_transfer/boards/esp32c3_luatos_core_usb.conf new file mode 100644 index 00000000000..311bfc8f535 --- /dev/null +++ b/tests/drivers/dma/loop_transfer/boards/esp32c3_luatos_core_usb.conf @@ -0,0 +1,2 @@ +CONFIG_DMA_LOOP_TRANSFER_CHANNEL_NR=0 +CONFIG_DMA_LOOP_TRANSFER_SIZE=4094 diff --git a/tests/drivers/dma/loop_transfer/boards/esp32c3_luatos_core_usb.overlay b/tests/drivers/dma/loop_transfer/boards/esp32c3_luatos_core_usb.overlay new file mode 100644 index 00000000000..9098b0dd5b9 --- /dev/null +++ b/tests/drivers/dma/loop_transfer/boards/esp32c3_luatos_core_usb.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&dma { + status = "okay"; +}; + +test_dma0: &dma { }; diff --git a/tests/drivers/dma/loop_transfer/boards/esp32s3_luatos_core.conf b/tests/drivers/dma/loop_transfer/boards/esp32s3_luatos_core.conf new file mode 100644 index 00000000000..60eda4cd0fd --- /dev/null +++ b/tests/drivers/dma/loop_transfer/boards/esp32s3_luatos_core.conf @@ -0,0 +1,2 @@ +CONFIG_DMA_LOOP_TRANSFER_CHANNEL_NR=4 +CONFIG_DMA_LOOP_TRANSFER_SIZE=4094 diff --git a/tests/drivers/dma/loop_transfer/boards/esp32s3_luatos_core.overlay b/tests/drivers/dma/loop_transfer/boards/esp32s3_luatos_core.overlay new file mode 100644 index 00000000000..ca3f3ca2c99 --- /dev/null +++ b/tests/drivers/dma/loop_transfer/boards/esp32s3_luatos_core.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&dma { + status = "okay"; +}; + +test_dma0: &dma { }; diff --git a/tests/drivers/dma/loop_transfer/boards/esp32s3_luatos_core_usb.conf b/tests/drivers/dma/loop_transfer/boards/esp32s3_luatos_core_usb.conf new file mode 100644 index 00000000000..60eda4cd0fd --- /dev/null +++ b/tests/drivers/dma/loop_transfer/boards/esp32s3_luatos_core_usb.conf @@ -0,0 +1,2 @@ +CONFIG_DMA_LOOP_TRANSFER_CHANNEL_NR=4 +CONFIG_DMA_LOOP_TRANSFER_SIZE=4094 diff --git a/tests/drivers/dma/loop_transfer/boards/esp32s3_luatos_core_usb.overlay b/tests/drivers/dma/loop_transfer/boards/esp32s3_luatos_core_usb.overlay new file mode 100644 index 00000000000..ca3f3ca2c99 --- /dev/null +++ b/tests/drivers/dma/loop_transfer/boards/esp32s3_luatos_core_usb.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&dma { + status = "okay"; +}; + +test_dma0: &dma { }; diff --git a/tests/drivers/dma/loop_transfer/boards/intel_adsp_ace15_mtpm.conf b/tests/drivers/dma/loop_transfer/boards/intel_adsp_ace15_mtpm.conf index 3707e852fcc..8c916f1ef93 100644 --- a/tests/drivers/dma/loop_transfer/boards/intel_adsp_ace15_mtpm.conf +++ b/tests/drivers/dma/loop_transfer/boards/intel_adsp_ace15_mtpm.conf @@ -1,5 +1,6 @@ -CONFIG_PM_DEVICE=y -CONFIG_PM_DEVICE_RUNTIME=y -CONFIG_PM_DEVICE_POWER_DOMAIN=y +CONFIG_PM=n +CONFIG_PM_DEVICE=n +CONFIG_PM_DEVICE_RUNTIME=n +CONFIG_PM_DEVICE_POWER_DOMAIN=n CONFIG_POWER_DOMAIN=y CONFIG_POWER_DOMAIN_INTEL_ADSP=y diff --git a/tests/drivers/dma/loop_transfer/boards/mr_canhubk3.overlay b/tests/drivers/dma/loop_transfer/boards/mr_canhubk3.overlay new file mode 100644 index 00000000000..afc9c1b2495 --- /dev/null +++ b/tests/drivers/dma/loop_transfer/boards/mr_canhubk3.overlay @@ -0,0 +1,7 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +test_dma0: &edma0 { }; diff --git a/tests/drivers/dma/loop_transfer/boards/nucleo_h743zi.overlay b/tests/drivers/dma/loop_transfer/boards/nucleo_h743zi.overlay index 20c8062f325..eb94644f3f3 100644 --- a/tests/drivers/dma/loop_transfer/boards/nucleo_h743zi.overlay +++ b/tests/drivers/dma/loop_transfer/boards/nucleo_h743zi.overlay @@ -18,7 +18,7 @@ test_dma0: &dmamux1 { * to be non-cachable. */ &sram4 { - zephyr,memory-attr = "RAM_NOCACHE"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) )>; }; &bdma1 { diff --git a/tests/drivers/dma/loop_transfer/prj.conf b/tests/drivers/dma/loop_transfer/prj.conf index 809f21a15e7..40e96629277 100644 --- a/tests/drivers/dma/loop_transfer/prj.conf +++ b/tests/drivers/dma/loop_transfer/prj.conf @@ -2,4 +2,3 @@ CONFIG_ZTEST=y CONFIG_DMA=y CONFIG_LOG=y CONFIG_DMA_LOG_LEVEL_INF=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/dma/scatter_gather/boards/mr_canhubk3.conf b/tests/drivers/dma/scatter_gather/boards/mr_canhubk3.conf new file mode 100644 index 00000000000..61f2d18ca3c --- /dev/null +++ b/tests/drivers/dma/scatter_gather/boards/mr_canhubk3.conf @@ -0,0 +1 @@ +CONFIG_DMA_TCD_QUEUE_SIZE=4 diff --git a/tests/drivers/dma/scatter_gather/prj.conf b/tests/drivers/dma/scatter_gather/prj.conf index 809f21a15e7..40e96629277 100644 --- a/tests/drivers/dma/scatter_gather/prj.conf +++ b/tests/drivers/dma/scatter_gather/prj.conf @@ -2,4 +2,3 @@ CONFIG_ZTEST=y CONFIG_DMA=y CONFIG_LOG=y CONFIG_DMA_LOG_LEVEL_INF=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/eeprom/api/boards/native_posix.conf b/tests/drivers/eeprom/api/at2x_emul.conf similarity index 100% rename from tests/drivers/eeprom/api/boards/native_posix.conf rename to tests/drivers/eeprom/api/at2x_emul.conf diff --git a/tests/drivers/eeprom/api/boards/native_posix.overlay b/tests/drivers/eeprom/api/at2x_emul.overlay similarity index 100% rename from tests/drivers/eeprom/api/boards/native_posix.overlay rename to tests/drivers/eeprom/api/at2x_emul.overlay diff --git a/tests/drivers/eeprom/api/prj.conf b/tests/drivers/eeprom/api/prj.conf index e6a92b035af..97ba3259588 100644 --- a/tests/drivers/eeprom/api/prj.conf +++ b/tests/drivers/eeprom/api/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y CONFIG_EEPROM=y diff --git a/tests/drivers/eeprom/api/testcase.yaml b/tests/drivers/eeprom/api/testcase.yaml index 5735d63da65..8bc76b3e9e6 100644 --- a/tests/drivers/eeprom/api/testcase.yaml +++ b/tests/drivers/eeprom/api/testcase.yaml @@ -9,9 +9,31 @@ tests: platform_allow: - native_posix - native_posix_64 + - native_sim + - native_sim_64 - qemu_x86 - nucleo_l152re - nucleo_l073rz + integration_platforms: + - qemu_x86 + drivers.eeprom.api.w_at2x_emul: + # Tests overwrite EEPROM content, only run on select boards + extra_args: + - DTC_OVERLAY_FILE=at2x_emul.overlay + - OVERLAY_CONFIG=at2x_emul.conf + platform_allow: + - native_posix + - native_posix_64 + - native_sim + - native_sim_64 + integration_platforms: + - native_sim drivers.eeprom.api.build: # Build-only test for boards with EEPROMs build_only: true + platform_exclude: + - native_sim + - native_sim_64 + - qemu_x86 + - nucleo_l152re + - nucleo_l073rz diff --git a/tests/drivers/eeprom/shell/prj.conf b/tests/drivers/eeprom/shell/prj.conf index b3aeff1e25a..82e8a22cf7b 100644 --- a/tests/drivers/eeprom/shell/prj.conf +++ b/tests/drivers/eeprom/shell/prj.conf @@ -5,4 +5,3 @@ CONFIG_EEPROM=y CONFIG_EEPROM_SHELL=y CONFIG_EEPROM_SHELL_BUFFER_SIZE=8 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/eeprom/shell/testcase.yaml b/tests/drivers/eeprom/shell/testcase.yaml index e9bdafceda5..fd78ec2c70f 100644 --- a/tests/drivers/eeprom/shell/testcase.yaml +++ b/tests/drivers/eeprom/shell/testcase.yaml @@ -1,8 +1,8 @@ tests: drivers.eeprom.shell: integration_platforms: - - native_posix - - native_posix_64 + - native_sim + - native_sim_64 tags: - drivers - eeprom diff --git a/tests/drivers/entropy/api/prj.conf b/tests/drivers/entropy/api/prj.conf index aa099f9564f..a33b10382d4 100644 --- a/tests/drivers/entropy/api/prj.conf +++ b/tests/drivers/entropy/api/prj.conf @@ -1,3 +1,2 @@ CONFIG_ENTROPY_GENERATOR=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/entropy/api/testcase.yaml b/tests/drivers/entropy/api/testcase.yaml index a2944f0230b..dfab54db635 100644 --- a/tests/drivers/entropy/api/testcase.yaml +++ b/tests/drivers/entropy/api/testcase.yaml @@ -5,7 +5,9 @@ tests: - drivers - entropy drivers.entropy.bt_hci: - platform_allow: nrf52_bsim + platform_allow: + - nrf52_bsim + - nrf5340bsim_nrf5340_cpunet extra_args: - DTC_OVERLAY_FILE=./entropy_bt_hci.overlay - OVERLAY_CONFIG=./entropy_bt_hci.conf diff --git a/tests/drivers/espi/boards/native_posix.overlay b/tests/drivers/espi/boards/native_sim.overlay similarity index 100% rename from tests/drivers/espi/boards/native_posix.overlay rename to tests/drivers/espi/boards/native_sim.overlay diff --git a/tests/drivers/espi/prj.conf b/tests/drivers/espi/prj.conf index df2c524adf9..cb0a355b123 100644 --- a/tests/drivers/espi/prj.conf +++ b/tests/drivers/espi/prj.conf @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ESPI=y CONFIG_EMUL=y CONFIG_EMUL_ESPI_HOST=y diff --git a/tests/drivers/espi/testcase.yaml b/tests/drivers/espi/testcase.yaml index 89f1c45c2bc..d8d55bb2e33 100644 --- a/tests/drivers/espi/testcase.yaml +++ b/tests/drivers/espi/testcase.yaml @@ -8,6 +8,7 @@ tests: - espi filter: dt_compat_enabled("zephyr,espi-emul-controller") harness: ztest - platform_allow: native_posix + platform_allow: + - native_sim integration_platforms: - - native_posix + - native_sim diff --git a/tests/drivers/ethernet/eth_ivshmem_queue/prj.conf b/tests/drivers/ethernet/eth_ivshmem_queue/prj.conf index ec2681e0763..c1f98dab82f 100644 --- a/tests/drivers/ethernet/eth_ivshmem_queue/prj.conf +++ b/tests/drivers/ethernet/eth_ivshmem_queue/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_OPENAMP=y diff --git a/tests/drivers/ethernet/eth_ivshmem_queue/testcase.yaml b/tests/drivers/ethernet/eth_ivshmem_queue/testcase.yaml index c4512d95326..9411b3d83ff 100644 --- a/tests/drivers/ethernet/eth_ivshmem_queue/testcase.yaml +++ b/tests/drivers/ethernet/eth_ivshmem_queue/testcase.yaml @@ -1,3 +1,3 @@ tests: - net.eth_ivshmem_queue: + net.ethernet.eth_ivshmem_queue: platform_allow: qemu_cortex_a53 diff --git a/tests/drivers/flash/common/boards/esp32c3_luatos_core.conf b/tests/drivers/flash/common/boards/esp32c3_luatos_core.conf new file mode 100644 index 00000000000..2bcf636958b --- /dev/null +++ b/tests/drivers/flash/common/boards/esp32c3_luatos_core.conf @@ -0,0 +1 @@ +CONFIG_HEAP_MEM_POOL_SIZE=16384 diff --git a/tests/drivers/flash/common/boards/esp32c3_luatos_core_usb.conf b/tests/drivers/flash/common/boards/esp32c3_luatos_core_usb.conf new file mode 100644 index 00000000000..2bcf636958b --- /dev/null +++ b/tests/drivers/flash/common/boards/esp32c3_luatos_core_usb.conf @@ -0,0 +1 @@ +CONFIG_HEAP_MEM_POOL_SIZE=16384 diff --git a/tests/drivers/flash/common/boards/nrf52840dk_mx25r_high_perf.overlay b/tests/drivers/flash/common/boards/nrf52840dk_mx25r_high_perf.overlay index eabb26ebda6..a67f25e46c0 100644 --- a/tests/drivers/flash/common/boards/nrf52840dk_mx25r_high_perf.overlay +++ b/tests/drivers/flash/common/boards/nrf52840dk_mx25r_high_perf.overlay @@ -1,5 +1,9 @@ /delete-node/ &qspi; +&gpio0 { + gpio-reserved-ranges = <0 2>, <6 1>, <8 3>, <18 6>; +}; + &spi2 { compatible = "nordic,nrf-spim"; status = "okay"; diff --git a/tests/drivers/flash/common/boards/nrf52840dk_spi_nor.overlay b/tests/drivers/flash/common/boards/nrf52840dk_spi_nor.overlay new file mode 100644 index 00000000000..1042b429ee3 --- /dev/null +++ b/tests/drivers/flash/common/boards/nrf52840dk_spi_nor.overlay @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023 Intercreate, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Build test for jedec,spi-nor compatible (drivers/flash/spi_nor.c) + */ + +/ { + aliases { + spi-flash0 = &mx25v1635fzui; + }; +}; + +/delete-node/ &mx25r64; + +&pinctrl { + spi0_default: spi0_default { + group1 { + psels = , + , + ; + }; + }; + + spi0_sleep: spi0_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; +}; + +&spi0 { + compatible = "nordic,nrf-spim"; + status = "okay"; + cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; // mx25v16 + pinctrl-0 = <&spi0_default>; + pinctrl-1 = <&spi0_sleep>; + pinctrl-names = "default", "sleep"; + + mx25v1635fzui: mx25v1635fzui@0 { + compatible = "jedec,spi-nor"; + status = "okay"; + reg = <0>; + spi-max-frequency = <8000000>; // chip supports 80Mhz, SPI0 supports 8MHz + size = <0x1000000>; // bits + has-dpd; + t-enter-dpd = <10000>; + t-exit-dpd = <45000>; + jedec-id = [ C2 23 15 ]; + sfdp-bfp = [ + e5 20 f1 ff ff ff ff 00 44 eb 08 6b 08 3b 04 bb + ee ff ff ff ff ff 00 ff ff ff 00 ff 0c 20 0f 52 + 10 d8 00 ff 23 72 f1 00 82 ec 04 c2 44 83 48 44 + 30 b0 30 b0 f7 c4 d5 5c 00 be 29 ff f0 d0 ff ff + ]; + }; +}; diff --git a/tests/drivers/flash/common/boards/nrf52840dk_spi_nor_wp_hold.overlay b/tests/drivers/flash/common/boards/nrf52840dk_spi_nor_wp_hold.overlay new file mode 100644 index 00000000000..f17febff6c3 --- /dev/null +++ b/tests/drivers/flash/common/boards/nrf52840dk_spi_nor_wp_hold.overlay @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2023 Intercreate, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Build test for jedec,spi-nor compatible (drivers/flash/spi_nor.c) wp-gpios and hold-gpios + */ + +/ { + aliases { + spi-flash0 = &mx25v1635fzui; + }; +}; + +/delete-node/ &mx25r64; + +&pinctrl { + spi0_default: spi0_default { + group1 { + psels = , + , + ; + }; + }; + + spi0_sleep: spi0_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; +}; + +&spi0 { + compatible = "nordic,nrf-spim"; + status = "okay"; + cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; // mx25v16 + pinctrl-0 = <&spi0_default>; + pinctrl-1 = <&spi0_sleep>; + pinctrl-names = "default", "sleep"; + + mx25v1635fzui: mx25v1635fzui@0 { + compatible = "jedec,spi-nor"; + status = "okay"; + reg = <0>; + spi-max-frequency = <8000000>; // chip supports 80Mhz, SPI0 supports 8MHz + size = <0x1000000>; // bits + hold-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + has-dpd; + t-enter-dpd = <10000>; + t-exit-dpd = <45000>; + jedec-id = [ C2 23 15 ]; + sfdp-bfp = [ + e5 20 f1 ff ff ff ff 00 44 eb 08 6b 08 3b 04 bb + ee ff ff ff ff ff 00 ff ff ff 00 ff 0c 20 0f 52 + 10 d8 00 ff 23 72 f1 00 82 ec 04 c2 44 83 48 44 + 30 b0 30 b0 f7 c4 d5 5c 00 be 29 ff f0 d0 ff ff + ]; + }; +}; diff --git a/tests/drivers/flash/common/prj.conf b/tests/drivers/flash/common/prj.conf index cb2c08a8bd1..cffa07b7f26 100644 --- a/tests/drivers/flash/common/prj.conf +++ b/tests/drivers/flash/common/prj.conf @@ -1,5 +1,4 @@ CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_FLASH=y CONFIG_MAIN_STACK_SIZE=2048 diff --git a/tests/drivers/flash/common/testcase.yaml b/tests/drivers/flash/common/testcase.yaml index d1a3174c901..88ce0a40e07 100644 --- a/tests/drivers/flash/common/testcase.yaml +++ b/tests/drivers/flash/common/testcase.yaml @@ -21,7 +21,7 @@ tests: - OVERLAY_CONFIG=boards/nrf52840_flash_qspi.conf - DTC_OVERLAY_FILE=boards/nrf52840dk_mx25l51245g.overlay harness_config: - fixture: external_flash + fixture: external_flash_mx25l51245g integration_platforms: - nrf52840dk_nrf52840 drivers.flash.common.soc_flash_nrf: @@ -35,12 +35,6 @@ tests: integration_platforms: - qemu_x86 - mimxrt1060_evk - platform_allow: - - qemu_x86 - - mimxrt1060_evk - - it8xxx2_evb - - mimxrt685_evk_cm33 - - mimxrt595_evk_cm33 drivers.flash.common.tfm_ns: build_only: true filter: (CONFIG_FLASH_HAS_DRIVER_ENABLED and CONFIG_TRUSTED_EXECUTION_NONSECURE @@ -79,3 +73,22 @@ tests: platform_allow: mr_canhubk3 extra_configs: - CONFIG_FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME=y + drivers.flash.common.spi_nor: + platform_allow: nrf52840dk_nrf52840 + extra_args: + - OVERLAY_CONFIG=boards/nrf52840dk_flash_spi.conf + - DTC_OVERLAY_FILE=boards/nrf52840dk_spi_nor.overlay + harness_config: + fixture: external_flash_mx25v1635f + drivers.flash.common.spi_nor_wp_hold: + platform_allow: nrf52840dk_nrf52840 + extra_args: + - OVERLAY_CONFIG=boards/nrf52840dk_flash_spi.conf + - DTC_OVERLAY_FILE=boards/nrf52840dk_spi_nor_wp_hold.overlay + harness_config: + fixture: external_flash_mx25v1635f + drivers.flash.common.sam0: + platform_allow: + - atsamd20_xpro + - atsamr21_xpro + - atsame54_xpro diff --git a/tests/drivers/flash/stm32/boards/disco_l475_iot1.overlay b/tests/drivers/flash/stm32/boards/disco_l475_iot1.overlay new file mode 100644 index 00000000000..711a96d0161 --- /dev/null +++ b/tests/drivers/flash/stm32/boards/disco_l475_iot1.overlay @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Do not use the storage-partition of the external qspi-NOR flash */ +/delete-node/ &storage_partition; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserve 4KiB of flash for storage_partition. */ + storage_partition: partition@f0000 { + label = "storage"; + reg = <0x000f0000 DT_SIZE_K(4)>; + }; + }; +}; diff --git a/tests/drivers/flash/stm32/prj.conf b/tests/drivers/flash/stm32/prj.conf index 4f43063f0cd..15aa2063b47 100644 --- a/tests/drivers/flash/stm32/prj.conf +++ b/tests/drivers/flash/stm32/prj.conf @@ -1,11 +1,8 @@ CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_FLASH=y CONFIG_FLASH_EX_OP_ENABLED=y -CONFIG_FLASH_STM32_READOUT_PROTECTION=y -CONFIG_FLASH_STM32_WRITE_PROTECT=y CONFIG_FLASH_STM32_BLOCK_REGISTERS=y CONFIG_MAIN_STACK_SIZE=2048 diff --git a/tests/drivers/flash/stm32/src/main.c b/tests/drivers/flash/stm32/src/main.c index 9d8ae0acc5b..d4d0bf1c201 100644 --- a/tests/drivers/flash/stm32/src/main.c +++ b/tests/drivers/flash/stm32/src/main.c @@ -20,6 +20,8 @@ #define EXPECTED_SIZE 512 static const struct device *const flash_dev = TEST_AREA_DEVICE; + +#if defined(CONFIG_FLASH_STM32_WRITE_PROTECT) static const struct flash_parameters *flash_params; static uint32_t sector_mask; static uint8_t __aligned(4) expected[EXPECTED_SIZE]; @@ -39,14 +41,17 @@ static int sector_mask_from_offset(const struct device *dev, off_t offset, return 0; } +#endif static void *flash_stm32_setup(void) { +#if defined(CONFIG_FLASH_STM32_WRITE_PROTECT) struct flash_stm32_ex_op_sector_wp_out wp_status; struct flash_stm32_ex_op_sector_wp_in wp_request; uint8_t buf[EXPECTED_SIZE]; bool is_buf_clear = true; int rc; +#endif /* Check if tested region fits in flash. */ zassert_true((TEST_AREA_OFFSET + EXPECTED_SIZE) < TEST_AREA_MAX, @@ -54,6 +59,7 @@ static void *flash_stm32_setup(void) zassert_true(device_is_ready(flash_dev)); +#if defined(CONFIG_FLASH_STM32_WRITE_PROTECT) flash_params = flash_get_parameters(flash_dev); rc = sector_mask_from_offset(flash_dev, TEST_AREA_OFFSET, EXPECTED_SIZE, @@ -102,10 +108,12 @@ static void *flash_stm32_setup(void) for (int i = 0; i < EXPECTED_SIZE; i++) { expected[i] = i; } +#endif return NULL; } +#if defined(CONFIG_FLASH_STM32_WRITE_PROTECT) ZTEST(flash_stm32, test_stm32_write_protection) { struct flash_stm32_ex_op_sector_wp_in wp_request; @@ -153,7 +161,9 @@ ZTEST(flash_stm32, test_stm32_write_protection) zassert_equal(memcmp(buf, expected, EXPECTED_SIZE), 0, "Read data doesn't match expected data"); } +#endif +#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION) ZTEST(flash_stm32, test_stm32_readout_protection_disabled) { struct flash_stm32_ex_op_rdp rdp_status; @@ -167,5 +177,6 @@ ZTEST(flash_stm32, test_stm32_readout_protection_disabled) TC_PRINT("RDP is disabled\n"); } +#endif ZTEST_SUITE(flash_stm32, NULL, flash_stm32_setup, NULL, NULL, NULL); diff --git a/tests/drivers/flash/stm32/testcase.yaml b/tests/drivers/flash/stm32/testcase.yaml index 9fcfa102744..f3346c96052 100644 --- a/tests/drivers/flash/stm32/testcase.yaml +++ b/tests/drivers/flash/stm32/testcase.yaml @@ -3,9 +3,27 @@ common: - drivers - flash tests: - drivers.flash.stm32.default: + drivers.flash.stm32.f4: platform_allow: - nucleo_f429zi - google_dragonclaw - filter: dt_compat_enabled("st,stm32-flash-controller") and + extra_configs: + - CONFIG_FLASH_STM32_WRITE_PROTECT=y + - CONFIG_FLASH_STM32_READOUT_PROTECTION=y + filter: dt_compat_enabled("st,stm32f4-flash-controller") and dt_label_with_parent_compat_enabled("storage_partition", "fixed-partitions") + drivers.flash.stm32.l4: + platform_allow: + - nucleo_l452re_p + - disco_l475_iot1 + extra_configs: + - CONFIG_FLASH_STM32_READOUT_PROTECTION=y + filter: dt_compat_enabled("st,stm32l4-flash-controller") and + dt_label_with_parent_compat_enabled("storage_partition", "fixed-partitions") + drivers.flash.stm32.g4: + platform_allow: + - nucleo_g474re + extra_configs: + - CONFIG_FLASH_STM32_READOUT_PROTECTION=y + filter: dt_compat_enabled("st,stm32g4-flash-controller") and + dt_label_with_parent_compat_enabled("storage_partition", "fixed-partitions") diff --git a/tests/drivers/flash_simulator/prj.conf b/tests/drivers/flash_simulator/prj.conf index ecaec58f5c6..c9fb30e0402 100644 --- a/tests/drivers/flash_simulator/prj.conf +++ b/tests/drivers/flash_simulator/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_FLASH=y CONFIG_FLASH_SIMULATOR=y CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=n diff --git a/tests/drivers/fuel_gauge/bq27z746/CMakeLists.txt b/tests/drivers/fuel_gauge/bq27z746/CMakeLists.txt new file mode 100644 index 00000000000..24070133dbd --- /dev/null +++ b/tests/drivers/fuel_gauge/bq27z746/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(device) + +FILE(GLOB app_sources src/test_bq27z746.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/fuel_gauge/max17048/boards/native_posix.conf b/tests/drivers/fuel_gauge/bq27z746/boards/native_sim.conf similarity index 100% rename from tests/drivers/fuel_gauge/max17048/boards/native_posix.conf rename to tests/drivers/fuel_gauge/bq27z746/boards/native_sim.conf diff --git a/tests/drivers/fuel_gauge/bq27z746/boards/native_sim.overlay b/tests/drivers/fuel_gauge/bq27z746/boards/native_sim.overlay new file mode 100644 index 00000000000..2dc85db341a --- /dev/null +++ b/tests/drivers/fuel_gauge/bq27z746/boards/native_sim.overlay @@ -0,0 +1,11 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +&i2c0 { + bq27z746: bq27z746@55 { + compatible = "ti,bq27z746"; + reg = <0x55>; + status = "okay"; + }; +}; diff --git a/tests/drivers/fuel_gauge/bq27z746/prj.conf b/tests/drivers/fuel_gauge/bq27z746/prj.conf new file mode 100644 index 00000000000..ce11abb435a --- /dev/null +++ b/tests/drivers/fuel_gauge/bq27z746/prj.conf @@ -0,0 +1,6 @@ +CONFIG_ZTEST=y +CONFIG_I2C=y +CONFIG_TEST_USERSPACE=y +CONFIG_LOG=y + +CONFIG_FUEL_GAUGE=y diff --git a/tests/drivers/fuel_gauge/bq27z746/src/test_bq27z746.c b/tests/drivers/fuel_gauge/bq27z746/src/test_bq27z746.c new file mode 100644 index 00000000000..a45dc096008 --- /dev/null +++ b/tests/drivers/fuel_gauge/bq27z746/src/test_bq27z746.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2023, ithinx GmbH + * Copyright (c) 2023, Tonies GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct bq27z746_fixture { + const struct device *dev; + const struct fuel_gauge_driver_api *api; +}; + +static void *bq27z746_setup(void) +{ + static ZTEST_DMEM struct bq27z746_fixture fixture; + + fixture.dev = DEVICE_DT_GET_ANY(ti_bq27z746); + k_object_access_all_grant(fixture.dev); + + zassert_true(device_is_ready(fixture.dev), "Fuel Gauge not found"); + + return &fixture; +} + +ZTEST_USER_F(bq27z746, test_get_some_props_failed_returns_bad_status) +{ + fuel_gauge_prop_t props[] = { + /* First invalid property */ + FUEL_GAUGE_PROP_MAX, + /* Second invalid property */ + FUEL_GAUGE_PROP_MAX, + /* Valid property */ + FUEL_GAUGE_VOLTAGE, + }; + union fuel_gauge_prop_val vals[ARRAY_SIZE(props)]; + + int ret = fuel_gauge_get_props(fixture->dev, props, vals, ARRAY_SIZE(props)); + + zassert_equal(ret, -ENOTSUP, "Getting bad property has a good status."); +} + +ZTEST_USER_F(bq27z746, test_get_buffer_prop) +{ + int ret; + + { + struct sbs_gauge_manufacturer_name mfg_name; + + ret = fuel_gauge_get_buffer_prop(fixture->dev, FUEL_GAUGE_MANUFACTURER_NAME, + &mfg_name, sizeof(mfg_name)); + zassert_ok(ret); +#if CONFIG_EMUL + /* Only test for fixed values in emulation since the real device might be */ + /* reprogrammed and respond with different values */ + zassert_equal(sizeof("Texas Instruments") - 1, mfg_name.manufacturer_name_length); + zassert_mem_equal(mfg_name.manufacturer_name, "Texas Instruments", + mfg_name.manufacturer_name_length, + "mfg_name.manufacturer_name='%s'", mfg_name.manufacturer_name); +#endif + } + { + struct sbs_gauge_device_name dev_name; + + ret = fuel_gauge_get_buffer_prop(fixture->dev, FUEL_GAUGE_DEVICE_NAME, &dev_name, + sizeof(dev_name)); + zassert_ok(ret); +#if CONFIG_EMUL + /* Only test for fixed values in emulation since the real device might be */ + /* reprogrammed and respond with different values */ + zassert_equal(sizeof("BQ27Z746") - 1, dev_name.device_name_length); + zassert_mem_equal(dev_name.device_name, "BQ27Z746", dev_name.device_name_length); +#endif + } + { + struct sbs_gauge_device_chemistry device_chemistry; + + ret = fuel_gauge_get_buffer_prop(fixture->dev, FUEL_GAUGE_DEVICE_CHEMISTRY, + &device_chemistry, sizeof(device_chemistry)); + zassert_ok(ret); +#if CONFIG_EMUL + /* Only test for fixed values in emulation since the real device might be */ + /* reprogrammed and respond with different values */ + zassert_equal(sizeof("LION") - 1, device_chemistry.device_chemistry_length); + zassert_mem_equal(device_chemistry.device_chemistry, "LION", + device_chemistry.device_chemistry_length); +#endif + } +} + +ZTEST_USER_F(bq27z746, test_get_props__returns_ok) +{ + /* Validate what props are supported by the driver */ + + fuel_gauge_prop_t props[] = { + FUEL_GAUGE_AVG_CURRENT, + FUEL_GAUGE_CYCLE_COUNT, + FUEL_GAUGE_CURRENT, + FUEL_GAUGE_FULL_CHARGE_CAPACITY, + FUEL_GAUGE_REMAINING_CAPACITY, + FUEL_GAUGE_RUNTIME_TO_EMPTY, + FUEL_GAUGE_RUNTIME_TO_FULL, + FUEL_GAUGE_SBS_MFR_ACCESS, + FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE, + FUEL_GAUGE_TEMPERATURE, + FUEL_GAUGE_VOLTAGE, + FUEL_GAUGE_SBS_ATRATE, + FUEL_GAUGE_SBS_ATRATE_TIME_TO_EMPTY, + FUEL_GAUGE_CHARGE_VOLTAGE, + FUEL_GAUGE_CHARGE_CURRENT, + FUEL_GAUGE_STATUS, + FUEL_GAUGE_DESIGN_CAPACITY, + }; + union fuel_gauge_prop_val vals[ARRAY_SIZE(props)]; + + zassert_ok(fuel_gauge_get_props(fixture->dev, props, vals, ARRAY_SIZE(props))); + + /* Check properties for valid ranges */ +#if CONFIG_EMUL + /* When emulating, check for the fixed values coming from the emulator */ + zassert_equal(vals[0].avg_current, -2000); + zassert_equal(vals[1].cycle_count, 100); + zassert_equal(vals[2].current, -2000); + zassert_equal(vals[3].full_charge_capacity, 1000); + zassert_equal(vals[4].remaining_capacity, 1000); + zassert_equal(vals[5].runtime_to_empty, 1); + zassert_equal(vals[6].runtime_to_full, 1); + zassert_equal(vals[7].sbs_mfr_access_word, 1); + zassert_equal(vals[8].relative_state_of_charge, 1); + zassert_equal(vals[9].temperature, 1); + zassert_equal(vals[10].voltage, 1000); + zassert_equal(vals[11].sbs_at_rate, -2); + zassert_equal(vals[12].sbs_at_rate_time_to_empty, 1); + zassert_equal(vals[13].chg_voltage, 1000); + zassert_equal(vals[14].chg_current, 1000); + zassert_equal(vals[15].fg_status, 1); + zassert_equal(vals[16].design_cap, 1); +#else + /* When having a real device, check for the valid ranges */ + zassert_between_inclusive(props[0].avg_current, -32768 * 1000, 32767 * 1000); + zassert_between_inclusive(props[1].cycle_count, 0, 6553500); + zassert_between_inclusive(props[2].current, -32768 * 1000, 32767 * 1000); + zassert_between_inclusive(props[3].full_charge_capacity, 0, 32767 * 1000); + zassert_between_inclusive(props[4].remaining_capacity, 0, 32767 * 1000); + zassert_between_inclusive(props[5].runtime_to_empty, 0, 65535); + zassert_between_inclusive(props[6].runtime_to_full, 0, 65535); + /* Not testing props[7]. This is the manufacturer access and has only status bits */ + zassert_between_inclusive(props[8].relative_state_of_charge, 0, 100); + zassert_between_inclusive(props[9].temperature, 0, 32767); + zassert_between_inclusive(props[10].voltage, 0, 32767 * 1000); + zassert_between_inclusive(props[11].sbs_at_rate, -32768, 32767); + zassert_between_inclusive(props[12].sbs_at_rate_time_to_empty, 0, 65535); + zassert_between_inclusive(props[13].chg_voltage, 0, 32767); + zassert_between_inclusive(props[14].chg_current, 0, 32767); + /* Not testing props[15]. This property is the status and only has only status bits */ + zassert_between_inclusive(props[16].design_cap, 0, 32767); +#endif +} + +ZTEST_SUITE(bq27z746, NULL, bq27z746_setup, NULL, NULL, NULL); diff --git a/tests/drivers/fuel_gauge/bq27z746/testcase.yaml b/tests/drivers/fuel_gauge/bq27z746/testcase.yaml new file mode 100644 index 00000000000..3bf2755af76 --- /dev/null +++ b/tests/drivers/fuel_gauge/bq27z746/testcase.yaml @@ -0,0 +1,7 @@ +tests: + drivers.fuel_gauge.bq27z746: + tags: + - fuel_gauge + filter: dt_compat_enabled("ti,bq27z746") + platform_allow: + - native_sim diff --git a/tests/drivers/fuel_gauge/max17048/boards/native_sim.conf b/tests/drivers/fuel_gauge/max17048/boards/native_sim.conf new file mode 100644 index 00000000000..022a71dd0f0 --- /dev/null +++ b/tests/drivers/fuel_gauge/max17048/boards/native_sim.conf @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_EMUL=y diff --git a/tests/drivers/fuel_gauge/max17048/boards/native_posix.overlay b/tests/drivers/fuel_gauge/max17048/boards/native_sim.overlay similarity index 100% rename from tests/drivers/fuel_gauge/max17048/boards/native_posix.overlay rename to tests/drivers/fuel_gauge/max17048/boards/native_sim.overlay diff --git a/tests/drivers/fuel_gauge/max17048/prj.conf b/tests/drivers/fuel_gauge/max17048/prj.conf index 23ceb0b3cdd..ce11abb435a 100644 --- a/tests/drivers/fuel_gauge/max17048/prj.conf +++ b/tests/drivers/fuel_gauge/max17048/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_I2C=y CONFIG_TEST_USERSPACE=y CONFIG_LOG=y diff --git a/tests/drivers/fuel_gauge/max17048/src/test_max17048.c b/tests/drivers/fuel_gauge/max17048/src/test_max17048.c index 8507b36049e..957a632ad4a 100644 --- a/tests/drivers/fuel_gauge/max17048/src/test_max17048.c +++ b/tests/drivers/fuel_gauge/max17048/src/test_max17048.c @@ -32,121 +32,63 @@ static void *max17048_setup(void) return &fixture; } -ZTEST_USER_F(max17048, test_get_all_props_failed_returns_negative) +ZTEST_USER_F(max17048, test_get_some_props_failed_returns_bad_status) { - struct fuel_gauge_get_property props[] = { - { - /* Invalid property */ - .property_type = FUEL_GAUGE_PROP_MAX, - }, + fuel_gauge_prop_t prop_types[] = { + /* First invalid property */ + FUEL_GAUGE_PROP_MAX, + /* Second invalid property */ + FUEL_GAUGE_PROP_MAX, + /* Valid property */ + FUEL_GAUGE_VOLTAGE, }; + union fuel_gauge_prop_val props[ARRAY_SIZE(prop_types)]; - int ret = fuel_gauge_get_prop(fixture->dev, props, ARRAY_SIZE(props)); + int ret = fuel_gauge_get_props(fixture->dev, prop_types, props, ARRAY_SIZE(props)); - zassert_equal(props[0].status, -ENOTSUP, "Getting bad property %d has a good status.", - props[0].property_type); - - zassert_true(ret < 0); -} - -ZTEST_USER_F(max17048, test_get_some_props_failed_returns_failed_prop_count) -{ - struct fuel_gauge_get_property props[] = { - { - /* First invalid property */ - .property_type = FUEL_GAUGE_PROP_MAX, - }, - { - /* Second invalid property */ - .property_type = FUEL_GAUGE_PROP_MAX, - }, - { - /* Valid property */ - .property_type = FUEL_GAUGE_VOLTAGE, - }, - - }; - - int ret = fuel_gauge_get_prop(fixture->dev, props, ARRAY_SIZE(props)); - - zassert_equal(props[0].status, -ENOTSUP, "Getting bad property %d has a good status.", - props[0].property_type); - - zassert_equal(props[1].status, -ENOTSUP, "Getting bad property %d has a good status.", - props[1].property_type); - - zassert_ok(props[2].status, "Property %d getting %d has a bad status.", 2, - props[2].property_type); - - zassert_equal(ret, 2); + zassert_equal(ret, -ENOTSUP, "Getting bad property has a good status."); } - ZTEST_USER_F(max17048, test_get_props__returns_ok) { /* Validate what props are supported by the driver */ - struct fuel_gauge_get_property props[] = { - { - .property_type = FUEL_GAUGE_RUNTIME_TO_EMPTY, - }, - { - .property_type = FUEL_GAUGE_RUNTIME_TO_FULL, - }, - { - .property_type = FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE, - }, - { - .property_type = FUEL_GAUGE_VOLTAGE, - } + fuel_gauge_prop_t prop_types[] = { + FUEL_GAUGE_VOLTAGE, + FUEL_GAUGE_RUNTIME_TO_EMPTY, + FUEL_GAUGE_RUNTIME_TO_FULL, + FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE, }; - int ret = fuel_gauge_get_prop(fixture->dev, props, ARRAY_SIZE(props)); + union fuel_gauge_prop_val props[ARRAY_SIZE(prop_types)]; - for (int i = 0; i < ARRAY_SIZE(props); i++) { - zassert_ok(props[i].status, "Property %d getting %d has a bad status.", i, - props[i].property_type); - } - - zassert_ok(ret); + zassert_ok(fuel_gauge_get_props(fixture->dev, prop_types, props, ARRAY_SIZE(props))); } ZTEST_USER_F(max17048, test_current_rate_zero) { /* Test when crate is 0, which is a special case */ - struct fuel_gauge_get_property props[] = { - { - .property_type = FUEL_GAUGE_RUNTIME_TO_EMPTY, - }, - { - .property_type = FUEL_GAUGE_RUNTIME_TO_FULL, - } + fuel_gauge_prop_t prop_types[] = { + FUEL_GAUGE_RUNTIME_TO_EMPTY, + FUEL_GAUGE_RUNTIME_TO_FULL, }; + union fuel_gauge_prop_val props[ARRAY_SIZE(prop_types)]; /** Null value, not charging either discharging. If not handled correctly, * it will cause a division by zero */ emul_max17048_set_crate_status(0); - int ret = fuel_gauge_get_prop(fixture->dev, props, ARRAY_SIZE(props)); - - for (int i = 0; i < ARRAY_SIZE(props); i++) { - zassert_ok(props[i].status, "Property %d getting %d has a bad status.", i, - props[i].property_type); - } - zassert_equal(props[0].value.runtime_to_empty, 0, - "Runtime to empty is %d but it should be 0.", - props[0].value.runtime_to_full - ); - zassert_equal(props[1].value.runtime_to_full, 0, - "Runtime to full is %d but it should be 0.", - props[1].value.runtime_to_full - ); + int ret = fuel_gauge_get_props(fixture->dev, prop_types, props, ARRAY_SIZE(props)); + + zassert_equal(props[0].runtime_to_empty, 0, "Runtime to empty is %d but it should be 0.", + props[0].runtime_to_full); + zassert_equal(props[1].runtime_to_full, 0, "Runtime to full is %d but it should be 0.", + props[1].runtime_to_full); zassert_ok(ret); /* Return value to the original state */ emul_max17048_set_crate_status(0x4000); } - ZTEST_SUITE(max17048, NULL, max17048_setup, NULL, NULL, NULL); diff --git a/tests/drivers/fuel_gauge/max17048/testcase.yaml b/tests/drivers/fuel_gauge/max17048/testcase.yaml index 742d2fee9ea..3f187d27cd7 100644 --- a/tests/drivers/fuel_gauge/max17048/testcase.yaml +++ b/tests/drivers/fuel_gauge/max17048/testcase.yaml @@ -1,5 +1,7 @@ tests: - # section.subsection - drivers.max17048: + drivers.fuel_gauge.max17048: + tags: + - fuel_gauge filter: dt_compat_enabled("maxim,max17048") - platform_allow: native_posix + platform_allow: + - native_sim diff --git a/tests/drivers/fuel_gauge/sbs_gauge/boards/qemu_cortex_a53.conf b/tests/drivers/fuel_gauge/sbs_gauge/boards/qemu_cortex_a53.conf deleted file mode 120000 index 851b864e289..00000000000 --- a/tests/drivers/fuel_gauge/sbs_gauge/boards/qemu_cortex_a53.conf +++ /dev/null @@ -1 +0,0 @@ -emulated_board.conf \ No newline at end of file diff --git a/tests/drivers/fuel_gauge/sbs_gauge/boards/qemu_cortex_a53.conf b/tests/drivers/fuel_gauge/sbs_gauge/boards/qemu_cortex_a53.conf new file mode 100644 index 00000000000..f8452191dba --- /dev/null +++ b/tests/drivers/fuel_gauge/sbs_gauge/boards/qemu_cortex_a53.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2022 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_EMUL=y diff --git a/tests/drivers/fuel_gauge/sbs_gauge/prj.conf b/tests/drivers/fuel_gauge/sbs_gauge/prj.conf index 23ceb0b3cdd..ce11abb435a 100644 --- a/tests/drivers/fuel_gauge/sbs_gauge/prj.conf +++ b/tests/drivers/fuel_gauge/sbs_gauge/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_I2C=y CONFIG_TEST_USERSPACE=y CONFIG_LOG=y diff --git a/tests/drivers/fuel_gauge/sbs_gauge/src/test_sbs_gauge.c b/tests/drivers/fuel_gauge/sbs_gauge/src/test_sbs_gauge.c index 2e5cea19609..6b302c42f63 100644 --- a/tests/drivers/fuel_gauge/sbs_gauge/src/test_sbs_gauge.c +++ b/tests/drivers/fuel_gauge/sbs_gauge/src/test_sbs_gauge.c @@ -32,344 +32,206 @@ static void *sbs_gauge_new_api_setup(void) return &fixture; } -ZTEST_USER_F(sbs_gauge_new_api, test_get_all_props_failed_returns_negative) +ZTEST_USER_F(sbs_gauge_new_api, test_get_some_props_failed_returns_bad_status) { - struct fuel_gauge_get_property props[] = { - { - /* Invalid property */ - .property_type = FUEL_GAUGE_PROP_MAX, - }, + fuel_gauge_prop_t prop_types[] = { + /* First invalid property */ + FUEL_GAUGE_PROP_MAX, + /* Second invalid property */ + FUEL_GAUGE_PROP_MAX, + /* Valid property */ + FUEL_GAUGE_VOLTAGE, }; + union fuel_gauge_prop_val props[ARRAY_SIZE(prop_types)]; - int ret = fuel_gauge_get_prop(fixture->dev, props, ARRAY_SIZE(props)); + int ret = fuel_gauge_get_props(fixture->dev, prop_types, props, ARRAY_SIZE(props)); - zassert_equal(props[0].status, -ENOTSUP, "Getting bad property %d has a good status.", - props[0].property_type); - - zassert_true(ret < 0); + zassert_equal(ret, -ENOTSUP, "Getting bad property has a good status."); } -ZTEST_USER_F(sbs_gauge_new_api, test_get_some_props_failed_returns_failed_prop_count) +ZTEST_USER_F(sbs_gauge_new_api, test_set_all_props_failed_returns_err) { - struct fuel_gauge_get_property props[] = { - { - /* First invalid property */ - .property_type = FUEL_GAUGE_PROP_MAX, - }, - { - /* Second invalid property */ - .property_type = FUEL_GAUGE_PROP_MAX, - }, - { - /* Valid property */ - .property_type = FUEL_GAUGE_VOLTAGE, - }, - + fuel_gauge_prop_t prop_types[] = { + /* Invalid property */ + FUEL_GAUGE_PROP_MAX, }; + union fuel_gauge_prop_val props[ARRAY_SIZE(prop_types)]; - int ret = fuel_gauge_get_prop(fixture->dev, props, ARRAY_SIZE(props)); - - zassert_equal(props[0].status, -ENOTSUP, "Getting bad property %d has a good status.", - props[0].property_type); - - zassert_equal(props[1].status, -ENOTSUP, "Getting bad property %d has a good status.", - props[1].property_type); + int ret = fuel_gauge_set_props(fixture->dev, prop_types, props, ARRAY_SIZE(props)); - zassert_ok(props[2].status, "Property %d getting %d has a bad status.", 2, - props[2].property_type); - - zassert_equal(ret, 2); + zassert_equal(ret, -ENOTSUP); } -ZTEST_USER_F(sbs_gauge_new_api, test_set_all_props_failed_returns_negative) +ZTEST_USER_F(sbs_gauge_new_api, test_set_some_props_failed_returns_err) { - struct fuel_gauge_set_property props[] = { - { - /* Invalid property */ - .property_type = FUEL_GAUGE_PROP_MAX, - }, - }; - - int ret = fuel_gauge_set_prop(fixture->dev, props, ARRAY_SIZE(props)); - - zassert_equal(props[0].status, -ENOTSUP, "Setting bad property %d has a good status.", - props[0].property_type); - - zassert_true(ret < 0); -} - -ZTEST_USER_F(sbs_gauge_new_api, test_set_some_props_failed_returns_failed_prop_count) -{ - struct fuel_gauge_set_property props[] = { - { - /* First invalid property */ - .property_type = FUEL_GAUGE_PROP_MAX, - }, - { - /* Second invalid property */ - .property_type = FUEL_GAUGE_PROP_MAX, - }, - { - /* Valid property */ - .property_type = FUEL_GAUGE_SBS_MFR_ACCESS, - /* Set Manufacturer's Access to arbitrary word */ - .value.sbs_mfr_access_word = 1, - }, + fuel_gauge_prop_t prop_types[] = { + /* First invalid property */ + FUEL_GAUGE_PROP_MAX, + /* Second invalid property */ + FUEL_GAUGE_PROP_MAX, + /* Valid property */ + FUEL_GAUGE_SBS_MFR_ACCESS, + /* Set Manufacturer's Access to arbitrary word */ }; - int ret = fuel_gauge_set_prop(fixture->dev, props, ARRAY_SIZE(props)); - - zassert_equal(props[0].status, -ENOTSUP, "Setting bad property %d has a good status.", - props[0].property_type); - - zassert_equal(props[1].status, -ENOTSUP, "Setting bad property %d has a good status.", - props[1].property_type); + union fuel_gauge_prop_val props[] = { + /* First invalid property */ + {0}, + /* Second invalid property */ + {0}, + /* Valid property */ + /* Set Manufacturer's Access to arbitrary word */ + {.sbs_mfr_access_word = 1}, + }; - zassert_ok(props[2].status, "Property %d setting %d has a bad status.", 2, - props[2].property_type); + int ret = fuel_gauge_set_props(fixture->dev, prop_types, props, ARRAY_SIZE(props)); - zassert_equal(ret, 2); + zassert_equal(ret, -ENOTSUP); } ZTEST_USER_F(sbs_gauge_new_api, test_set_prop_can_be_get) { uint16_t word = BIT(15) | BIT(0); - struct fuel_gauge_set_property set_props[] = { - { - /* Valid property */ - .property_type = FUEL_GAUGE_SBS_MFR_ACCESS, - /* Set Manufacturer's Access to 16 bit word */ - .value.sbs_mfr_access_word = word, - }, - { - .property_type = FUEL_GAUGE_SBS_REMAINING_CAPACITY_ALARM, - .value.sbs_remaining_capacity_alarm = word, - }, - { - .property_type = FUEL_GAUGE_SBS_REMAINING_TIME_ALARM, - .value.sbs_remaining_time_alarm = word, - }, - { - .property_type = FUEL_GAUGE_SBS_MODE, - .value.sbs_mode = word, - }, - { - .property_type = FUEL_GAUGE_SBS_ATRATE, - .value.sbs_at_rate = (int16_t)word, - }, + + fuel_gauge_prop_t prop_types[] = { + FUEL_GAUGE_SBS_MFR_ACCESS, + FUEL_GAUGE_SBS_REMAINING_CAPACITY_ALARM, + FUEL_GAUGE_SBS_REMAINING_TIME_ALARM, + FUEL_GAUGE_SBS_MODE, + FUEL_GAUGE_SBS_ATRATE, }; - struct fuel_gauge_get_property get_props[] = { + union fuel_gauge_prop_val set_props[] = { { - .property_type = FUEL_GAUGE_SBS_MFR_ACCESS, + .sbs_mfr_access_word = word, }, { - .property_type = FUEL_GAUGE_SBS_REMAINING_CAPACITY_ALARM, + .sbs_remaining_capacity_alarm = word, }, { - .property_type = FUEL_GAUGE_SBS_REMAINING_TIME_ALARM, + .sbs_remaining_time_alarm = word, }, { - .property_type = FUEL_GAUGE_SBS_MODE, + .sbs_mode = word, }, { - .property_type = FUEL_GAUGE_SBS_ATRATE, + .sbs_at_rate = (int16_t)word, }, }; - zassert_ok(fuel_gauge_set_prop(fixture->dev, set_props, ARRAY_SIZE(set_props))); - for (int i = 0; i < ARRAY_SIZE(set_props); i++) { - zassert_ok(set_props[i].status, "Property %d writing %d has a bad status.", i, - set_props[i].property_type); - } - - zassert_ok(fuel_gauge_get_prop(fixture->dev, get_props, ARRAY_SIZE(get_props))); - for (int i = 0; i < ARRAY_SIZE(get_props); i++) { - zassert_ok(get_props[i].status, "Property %d getting %d has a bad status.", i, - get_props[i].property_type); - } - - zassert_equal(get_props[0].value.sbs_mfr_access_word, word); - zassert_equal(get_props[1].value.sbs_remaining_capacity_alarm, word); - zassert_equal(get_props[2].value.sbs_remaining_time_alarm, word); - zassert_equal(get_props[3].value.sbs_mode, word); - zassert_equal(get_props[4].value.sbs_at_rate, (int16_t)word); + union fuel_gauge_prop_val get_props[ARRAY_SIZE(prop_types)]; + + zassert_ok( + fuel_gauge_set_props(fixture->dev, prop_types, set_props, ARRAY_SIZE(set_props))); + + zassert_ok( + fuel_gauge_get_props(fixture->dev, prop_types, get_props, ARRAY_SIZE(get_props))); + + zassert_equal(get_props[0].sbs_mfr_access_word, word); + zassert_equal(get_props[1].sbs_remaining_capacity_alarm, word); + zassert_equal(get_props[2].sbs_remaining_time_alarm, word); + zassert_equal(get_props[3].sbs_mode, word); + zassert_equal(get_props[4].sbs_at_rate, (int16_t)word); } ZTEST_USER_F(sbs_gauge_new_api, test_get_props__returns_ok) { /* Validate what props are supported by the driver */ - struct fuel_gauge_get_property props[] = { - { - .property_type = FUEL_GAUGE_VOLTAGE, - }, - { - .property_type = FUEL_GAUGE_CURRENT, - }, - { - .property_type = FUEL_GAUGE_AVG_CURRENT, - }, - { - .property_type = FUEL_GAUGE_TEMPERATURE, - }, - { - .property_type = FUEL_GAUGE_ABSOLUTE_STATE_OF_CHARGE, - }, - { - .property_type = FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE, - }, - { - .property_type = FUEL_GAUGE_RUNTIME_TO_FULL, - }, - { - .property_type = FUEL_GAUGE_RUNTIME_TO_EMPTY, - }, - { - .property_type = FUEL_GAUGE_REMAINING_CAPACITY, - }, - { - .property_type = FUEL_GAUGE_FULL_CHARGE_CAPACITY, - }, - { - .property_type = FUEL_GAUGE_CYCLE_COUNT, - }, - { - .property_type = FUEL_GAUGE_SBS_MFR_ACCESS, - }, - { - .property_type = FUEL_GAUGE_SBS_MODE, - }, - { - .property_type = FUEL_GAUGE_CHARGE_CURRENT, - }, - { - .property_type = FUEL_GAUGE_CHARGE_VOLTAGE, - }, - { - .property_type = FUEL_GAUGE_STATUS, - }, - { - .property_type = FUEL_GAUGE_DESIGN_CAPACITY, - }, - { - .property_type = FUEL_GAUGE_DESIGN_VOLTAGE, - }, - { - .property_type = FUEL_GAUGE_SBS_ATRATE, - }, - { - .property_type = FUEL_GAUGE_SBS_ATRATE_TIME_TO_FULL, - }, - { - .property_type = FUEL_GAUGE_SBS_ATRATE_TIME_TO_EMPTY, - }, - { - .property_type = FUEL_GAUGE_SBS_ATRATE_OK, - }, - { - .property_type = FUEL_GAUGE_SBS_REMAINING_CAPACITY_ALARM, - }, - { - .property_type = FUEL_GAUGE_SBS_REMAINING_TIME_ALARM, - }, + fuel_gauge_prop_t prop_types[] = { + FUEL_GAUGE_VOLTAGE, + FUEL_GAUGE_CURRENT, + FUEL_GAUGE_AVG_CURRENT, + FUEL_GAUGE_TEMPERATURE, + FUEL_GAUGE_ABSOLUTE_STATE_OF_CHARGE, + FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE, + FUEL_GAUGE_RUNTIME_TO_FULL, + FUEL_GAUGE_RUNTIME_TO_EMPTY, + FUEL_GAUGE_REMAINING_CAPACITY, + FUEL_GAUGE_FULL_CHARGE_CAPACITY, + FUEL_GAUGE_CYCLE_COUNT, + FUEL_GAUGE_SBS_MFR_ACCESS, + FUEL_GAUGE_SBS_MODE, + FUEL_GAUGE_CHARGE_CURRENT, + FUEL_GAUGE_CHARGE_VOLTAGE, + FUEL_GAUGE_STATUS, + FUEL_GAUGE_DESIGN_CAPACITY, + FUEL_GAUGE_DESIGN_VOLTAGE, + FUEL_GAUGE_SBS_ATRATE, + FUEL_GAUGE_SBS_ATRATE_TIME_TO_FULL, + FUEL_GAUGE_SBS_ATRATE_TIME_TO_EMPTY, + FUEL_GAUGE_SBS_ATRATE_OK, + FUEL_GAUGE_SBS_REMAINING_CAPACITY_ALARM, + FUEL_GAUGE_SBS_REMAINING_TIME_ALARM, }; - int ret = fuel_gauge_get_prop(fixture->dev, props, ARRAY_SIZE(props)); - - for (int i = 0; i < ARRAY_SIZE(props); i++) { - zassert_ok(props[i].status, "Property %d getting %d has a bad status.", i, - props[i].property_type); - } + union fuel_gauge_prop_val props[ARRAY_SIZE(prop_types)]; - zassert_ok(ret); + zassert_ok(fuel_gauge_get_props(fixture->dev, prop_types, props, ARRAY_SIZE(props))); } ZTEST_USER_F(sbs_gauge_new_api, test_set_props__returns_ok) { - /* Validate what props are supported by the driver */ + fuel_gauge_prop_t prop_types[] = { + FUEL_GAUGE_SBS_MFR_ACCESS, + FUEL_GAUGE_SBS_MODE, + FUEL_GAUGE_SBS_ATRATE, + FUEL_GAUGE_SBS_REMAINING_TIME_ALARM, + FUEL_GAUGE_SBS_REMAINING_CAPACITY_ALARM, - struct fuel_gauge_set_property props[] = { - { - .property_type = FUEL_GAUGE_SBS_MFR_ACCESS, - }, - { - .property_type = FUEL_GAUGE_SBS_REMAINING_CAPACITY_ALARM, - }, - { - .property_type = FUEL_GAUGE_SBS_REMAINING_TIME_ALARM, - }, - { - .property_type = FUEL_GAUGE_SBS_MODE, - }, - { - .property_type = FUEL_GAUGE_SBS_ATRATE, - }, }; + union fuel_gauge_prop_val props[ARRAY_SIZE(prop_types)]; - int ret = fuel_gauge_set_prop(fixture->dev, props, ARRAY_SIZE(props)); - - for (int i = 0; i < ARRAY_SIZE(props); i++) { - zassert_ok(props[i].status, "Property %d writing %d has a bad status.", i, - props[i].property_type); - } - - zassert_ok(ret); + zassert_ok(fuel_gauge_set_props(fixture->dev, prop_types, props, ARRAY_SIZE(props))); } - ZTEST_USER_F(sbs_gauge_new_api, test_get_buffer_props__returns_ok) { /* Validate what properties are supported by the driver */ - struct fuel_gauge_get_buffer_property prop; struct sbs_gauge_manufacturer_name mfg_name; struct sbs_gauge_device_name dev_name; struct sbs_gauge_device_chemistry chem; - int ret; - - prop.property_type = FUEL_GAUGE_MANUFACTURER_NAME; - ret = fuel_gauge_get_buffer_prop(fixture->dev, &prop, &mfg_name, sizeof(mfg_name)); - zassert_ok(prop.status, "Property %d has a bad status.", prop.property_type); - zassert_ok(ret); - - prop.property_type = FUEL_GAUGE_DEVICE_NAME; - ret = fuel_gauge_get_buffer_prop(fixture->dev, &prop, &dev_name, sizeof(dev_name)); - zassert_ok(prop.status, "Property %d has a bad status.", prop.property_type); - zassert_ok(ret); - - prop.property_type = FUEL_GAUGE_DEVICE_CHEMISTRY; - ret = fuel_gauge_get_buffer_prop(fixture->dev, &prop, &chem, sizeof(chem)); - zassert_ok(prop.status, "Property %d has a bad status.", prop.property_type); - zassert_ok(ret); + + zassert_ok(fuel_gauge_get_buffer_prop(fixture->dev, FUEL_GAUGE_MANUFACTURER_NAME, &mfg_name, + sizeof(mfg_name))); + + zassert_ok(fuel_gauge_get_buffer_prop(fixture->dev, FUEL_GAUGE_DEVICE_NAME, &dev_name, + sizeof(dev_name))); + + zassert_ok(fuel_gauge_get_buffer_prop(fixture->dev, FUEL_GAUGE_DEVICE_CHEMISTRY, &chem, + sizeof(chem))); } -ZTEST_F(sbs_gauge_new_api, test_charging_5v_3a) +ZTEST_USER_F(sbs_gauge_new_api, test_charging_5v_3a) { - /* Validate what props are supported by the driver */ uint32_t expected_uV = 5000 * 1000; uint32_t expected_uA = 3000 * 1000; - struct fuel_gauge_get_property props[] = { - { - .property_type = FUEL_GAUGE_VOLTAGE, - }, - { - .property_type = FUEL_GAUGE_CURRENT, - }, - }; + union fuel_gauge_prop_val voltage; + union fuel_gauge_prop_val current; zassume_ok(emul_fuel_gauge_set_battery_charging(fixture->sbs_fuel_gauge, expected_uV, expected_uA)); - zassert_ok(fuel_gauge_get_prop(fixture->dev, props, ARRAY_SIZE(props))); + zassert_ok(fuel_gauge_get_prop(fixture->dev, FUEL_GAUGE_VOLTAGE, &voltage)); + zassert_ok(fuel_gauge_get_prop(fixture->dev, FUEL_GAUGE_CURRENT, ¤t)); + + zassert_equal(voltage.voltage, expected_uV, "Got %d instead of %d", voltage, expected_uV); + zassert_equal(current.current, expected_uA, "Got %d instead of %d", current, expected_uA); +} - zassert_ok(props[0].status); - zassert_equal(props[0].value.voltage, expected_uV, "Got %d instead of %d", - props[0].value.voltage, expected_uV); +ZTEST_USER_F(sbs_gauge_new_api, test_set_get_single_prop) +{ + uint16_t test_value = 0x1001; + + union fuel_gauge_prop_val mfr_acc_set = { + .sbs_mfr_access_word = test_value, + }; + union fuel_gauge_prop_val mfr_acc_get; - zassert_ok(props[1].status); - zassert_equal(props[1].value.current, expected_uA, "Got %d instead of %d", - props[1].value.current, expected_uA); + zassert_ok(fuel_gauge_set_prop(fixture->dev, FUEL_GAUGE_SBS_MFR_ACCESS, mfr_acc_set)); + zassert_ok(fuel_gauge_get_prop(fixture->dev, FUEL_GAUGE_SBS_MFR_ACCESS, &mfr_acc_get)); + zassert_equal(mfr_acc_get.sbs_mfr_access_word, test_value); } ZTEST_SUITE(sbs_gauge_new_api, NULL, sbs_gauge_new_api_setup, NULL, NULL, NULL); diff --git a/tests/drivers/fuel_gauge/sbs_gauge/testcase.yaml b/tests/drivers/fuel_gauge/sbs_gauge/testcase.yaml index d7f85f58bb6..97d25b26a05 100644 --- a/tests/drivers/fuel_gauge/sbs_gauge/testcase.yaml +++ b/tests/drivers/fuel_gauge/sbs_gauge/testcase.yaml @@ -1,12 +1,11 @@ tests: - # section.subsection - drivers.sbs_gauge_new_api.emulated: + drivers.fuel_gauge.sbs_gauge_new_api.emulated: tags: - drivers - fuel_gauge filter: > dt_compat_enabled("sbs,sbs-gauge-new-api") and - (CONFIG_QEMU_TARGET or CONFIG_BOARD_NATIVE_POSIX) + (CONFIG_QEMU_TARGET or CONFIG_BOARD_NATIVE_SIM) extra_args: - CONF_FILE="prj.conf;boards/emulated_board.conf" - DTC_OVERLAY_FILE="boards/emulated_board.overlay" @@ -21,13 +20,13 @@ tests: - rcar_salvator_xs_m3 integration_platforms: - qemu_x86 - drivers.sbs_gauge_new_api.emulated_64_bit_i2c_addr: + drivers.fuel_gauge.sbs_gauge_new_api.emulated_64_bit_i2c_addr: tags: - drivers - fuel_gauge filter: > dt_compat_enabled("sbs,sbs-gauge-new-api") and - (CONFIG_QEMU_TARGET or CONFIG_BOARD_NATIVE_POSIX) + (CONFIG_QEMU_TARGET or CONFIG_BOARD_NATIVE_SIM) platform_allow: - hifive_unmatched - qemu_cortex_a53 @@ -40,7 +39,7 @@ tests: extra_args: - CONF_FILE="prj.conf;boards/qemu_cortex_a53.conf" - DTC_OVERLAY_FILE="boards/qemu_cortex_a53.overlay" - drivers.sbs_gauge_new_api.emulated.cutoff: + drivers.fuel_gauge.sbs_gauge_new_api.emulated.cutoff: tags: - drivers - fuel_gauge @@ -53,4 +52,5 @@ tests: - CONFIG_USERSPACE=y platform_allow: - native_posix + - native_sim - qemu_x86 diff --git a/tests/drivers/gnss/gnss_nmea0183/CMakeLists.txt b/tests/drivers/gnss/gnss_nmea0183/CMakeLists.txt new file mode 100644 index 00000000000..73183c90acc --- /dev/null +++ b/tests/drivers/gnss/gnss_nmea0183/CMakeLists.txt @@ -0,0 +1,14 @@ +# Copyright (c) 2023 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(gnss_nmea0183) + +target_sources(app PRIVATE + src/main.c +) + +target_include_directories(app PRIVATE ${ZEPHYR_BASE}/drivers/gnss) diff --git a/tests/drivers/gnss/gnss_nmea0183/prj.conf b/tests/drivers/gnss/gnss_nmea0183/prj.conf new file mode 100644 index 00000000000..d2cc9d2b645 --- /dev/null +++ b/tests/drivers/gnss/gnss_nmea0183/prj.conf @@ -0,0 +1,7 @@ +# Copyright (c) 2023 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_GNSS=y +CONFIG_GNSS_NMEA0183=y +CONFIG_ZTEST=y +CONFIG_ZTEST_STACK_SIZE=4096 diff --git a/tests/drivers/gnss/gnss_nmea0183/src/main.c b/tests/drivers/gnss/gnss_nmea0183/src/main.c new file mode 100644 index 00000000000..680382f7dbc --- /dev/null +++ b/tests/drivers/gnss/gnss_nmea0183/src/main.c @@ -0,0 +1,739 @@ +/* + * Copyright 2023 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "gnss_nmea0183.h" + +#define TEST_DDMM_MMMM_MAX_ROUNDING_ERROR_NDEG (1) + +struct test_ddmm_mmmm_sample { + const char *ddmm_mmmm; + int64_t ndeg; +}; + +/* + * The conversion from ddmm.mmmm to decimal nano degree is + * ((1/60) * mm.mmmm * 1E9) + (dd * 1E9) + */ +static const struct test_ddmm_mmmm_sample ddmm_mmmm_samples[] = { + {.ddmm_mmmm = "00.0", .ndeg = 0}, + {.ddmm_mmmm = "000.0", .ndeg = 0}, + {.ddmm_mmmm = "9000.0000", .ndeg = 90000000000}, + {.ddmm_mmmm = "4530.0000", .ndeg = 45500000000}, + {.ddmm_mmmm = "4530.3000", .ndeg = 45505000000}, + {.ddmm_mmmm = "4530.3001", .ndeg = 45505001667}, + {.ddmm_mmmm = "4530.9999", .ndeg = 45516665000}, + {.ddmm_mmmm = "18000.0000", .ndeg = 180000000000} +}; + +ZTEST(gnss_nmea0183, test_ddmm_mmmm) +{ + int64_t min_ndeg; + int64_t max_ndeg; + int64_t ndeg; + + for (size_t i = 0; i < ARRAY_SIZE(ddmm_mmmm_samples); i++) { + zassert_ok(gnss_nmea0183_ddmm_mmmm_to_ndeg(ddmm_mmmm_samples[i].ddmm_mmmm, &ndeg), + "Parse failed"); + + min_ndeg = ddmm_mmmm_samples[i].ndeg - TEST_DDMM_MMMM_MAX_ROUNDING_ERROR_NDEG; + max_ndeg = ddmm_mmmm_samples[i].ndeg + TEST_DDMM_MMMM_MAX_ROUNDING_ERROR_NDEG; + zassert_true(ndeg >= min_ndeg, "Parsed value falls below max rounding error"); + zassert_true(ndeg <= max_ndeg, "Parsed value is above max rounding error"); + } + + /* Minutes can only go from 0 to 59.9999 */ + zassert_equal(gnss_nmea0183_ddmm_mmmm_to_ndeg("99.0000", &ndeg), -EINVAL, + "Parse should fail"); + + zassert_equal(gnss_nmea0183_ddmm_mmmm_to_ndeg("60.0000", &ndeg), -EINVAL, + "Parse should fail"); + + /* Missing dot */ + zassert_equal(gnss_nmea0183_ddmm_mmmm_to_ndeg("18000", &ndeg), -EINVAL, + "Parse should fail"); + + /* Invalid chars */ + zassert_equal(gnss_nmea0183_ddmm_mmmm_to_ndeg("900#.0a000", &ndeg), -EINVAL, + "Parse should fail"); + + /* Negative angle */ + zassert_equal(gnss_nmea0183_ddmm_mmmm_to_ndeg("-18000.0", &ndeg), -EINVAL, + "Parse should fail"); +} + +struct test_knots_to_mms_sample { + const char *str; + int64_t value; +}; + +static const struct test_knots_to_mms_sample knots_to_mms_samples[] = { + {.str = "1", .value = 514}, + {.str = "2.2", .value = 1131}, + {.str = "003241.12543", .value = 1667364} +}; + +ZTEST(gnss_nmea0183, test_knots_to_mms) +{ + int64_t mms; + + for (size_t i = 0; i < ARRAY_SIZE(knots_to_mms_samples); i++) { + zassert_ok(gnss_nmea0183_knots_to_mms(knots_to_mms_samples[i].str, &mms), + "Parse failed"); + + zassert_equal(knots_to_mms_samples[i].value, mms, + "Parsed value falls below max rounding error"); + } +} + +struct test_hhmmss_sample { + const char *str; + uint8_t hour; + uint8_t minute; + uint16_t millisecond; +}; + +static const struct test_hhmmss_sample hhmmss_samples[] = { + {.str = "000102", .hour = 0, .minute = 1, .millisecond = 2000}, + {.str = "235959.999", .hour = 23, .minute = 59, .millisecond = 59999}, + {.str = "000000.0", .hour = 0, .minute = 0, .millisecond = 0} +}; + +ZTEST(gnss_nmea0183, test_hhmmss) +{ + struct gnss_time utc; + int ret; + + for (size_t i = 0; i < ARRAY_SIZE(hhmmss_samples); i++) { + zassert_ok(gnss_nmea0183_parse_hhmmss(hhmmss_samples[i].str, &utc), + "Parse failed"); + + zassert_equal(hhmmss_samples[i].hour, utc.hour, "Failed to parse hour"); + zassert_equal(hhmmss_samples[i].minute, utc.minute, "Failed to parse minute"); + zassert_equal(hhmmss_samples[i].millisecond, utc.millisecond, + "Failed to parse millisecond"); + } + + ret = gnss_nmea0183_parse_hhmmss("-101010", &utc); + zassert_equal(ret, -EINVAL, "Should fail to parse invalid value"); + + ret = gnss_nmea0183_parse_hhmmss("01010", &utc); + zassert_equal(ret, -EINVAL, "Should fail to parse invalid value"); + + ret = gnss_nmea0183_parse_hhmmss("246060.999", &utc); + zassert_equal(ret, -EINVAL, "Should fail to parse invalid value"); + + ret = gnss_nmea0183_parse_hhmmss("99a9c9", &utc); + zassert_equal(ret, -EINVAL, "Should fail to parse invalid value"); + + ret = gnss_nmea0183_parse_hhmmss("12121212", &utc); + zassert_equal(ret, -EINVAL, "Should fail to parse invalid value"); +} + +struct test_ddmmyy_sample { + const char *str; + uint8_t month_day; + uint8_t month; + uint16_t century_year; +}; + +static const struct test_ddmmyy_sample ddmmyy_samples[] = { + {.str = "010203", .month_day = 1, .month = 2, .century_year = 3}, + {.str = "311299", .month_day = 31, .month = 12, .century_year = 99}, + {.str = "010100", .month_day = 1, .month = 1, .century_year = 0} +}; + +ZTEST(gnss_nmea0183, test_ddmmyy) +{ + struct gnss_time utc; + int ret; + + for (size_t i = 0; i < ARRAY_SIZE(ddmmyy_samples); i++) { + zassert_ok(gnss_nmea0183_parse_ddmmyy(ddmmyy_samples[i].str, &utc), + "Parse failed"); + + zassert_equal(ddmmyy_samples[i].month_day, utc.month_day, + "Failed to parse monthday"); + + zassert_equal(ddmmyy_samples[i].month, utc.month, "Failed to parse month"); + zassert_equal(ddmmyy_samples[i].century_year, utc.century_year, + "Failed to parse year"); + } + + ret = gnss_nmea0183_parse_ddmmyy("000000", &utc); + zassert_equal(ret, -EINVAL, "Should fail to parse invalid value"); + + ret = gnss_nmea0183_parse_ddmmyy("-12123", &utc); + zassert_equal(ret, -EINVAL, "Should fail to parse invalid value"); + + ret = gnss_nmea0183_parse_ddmmyy("01010", &utc); + zassert_equal(ret, -EINVAL, "Should fail to parse invalid value"); + + ret = gnss_nmea0183_parse_ddmmyy("999999", &utc); + zassert_equal(ret, -EINVAL, "Should fail to parse invalid value"); + + ret = gnss_nmea0183_parse_ddmmyy("99a9c9", &utc); + zassert_equal(ret, -EINVAL, "Should fail to parse invalid value"); + + ret = gnss_nmea0183_parse_ddmmyy("12121212", &utc); + zassert_equal(ret, -EINVAL, "Should fail to parse invalid value"); +} + +/* "$GNRMC,160833.099,V,,,,,,,090923,,,N,V*27" */ +const char *rmc_argv_no_fix[15] = { + "$GNRMC", + "160833.099", + "V", + "", + "", + "", + "", + "", + "", + "090923", + "", + "", + "N", + "V", + "27" +}; + +static struct gnss_data data; + +ZTEST(gnss_nmea0183, test_parse_rmc_no_fix) +{ + int ret; + + /* Corrupt data */ + memset(&data, 0xFF, sizeof(data)); + + ret = gnss_nmea0183_parse_rmc(rmc_argv_no_fix, ARRAY_SIZE(rmc_argv_no_fix), &data); + zassert_ok(ret, "NMEA0183 RMC message parse should succeed"); +} + +/* "$GNGGA,160834.099,,,,,0,0,,,M,,M,,*5E" */ +const char *gga_argv_no_fix[16] = { + "$GNGGA", + "160834.099", + "", + "", + "", + "", + "0", + "0", + "", + "", + "M", + "", + "M", + "", + "5E" +}; + +ZTEST(gnss_nmea0183, test_parse_gga_no_fix) +{ + int ret; + + /* Corrupt data */ + memset(&data, 0xFF, sizeof(data)); + + ret = gnss_nmea0183_parse_gga(gga_argv_no_fix, ARRAY_SIZE(gga_argv_no_fix), &data); + zassert_ok(ret, "NMEA0183 GGA message parse should succeed"); + zassert_equal(data.info.fix_quality, GNSS_FIX_QUALITY_INVALID, + "Incorrectly parsed fix quality"); + + zassert_equal(data.info.fix_status, GNSS_FIX_STATUS_NO_FIX, + "Incorrectly parsed fix status"); +} + +/* "$GNRMC,160849.000,A,5709.736602,N,00957.660738,E,0.33,0.00,090923,,,A,V*03" */ +const char *rmc_argv_fix[15] = { + "$GNRMC", + "160849.000", + "A", + "5709.736602", + "N", + "00957.660738", + "E", + "0.33", + "33.31", + "090923", + "", + "", + "A", + "V", + "03", +}; + +ZTEST(gnss_nmea0183, test_parse_rmc_fix) +{ + int ret; + + /* Corrupt data */ + memset(&data, 0xFF, sizeof(data)); + + ret = gnss_nmea0183_parse_rmc(rmc_argv_fix, ARRAY_SIZE(rmc_argv_fix), &data); + zassert_ok(ret, "NMEA0183 RMC message parse should succeed"); + zassert_equal(data.nav_data.latitude, 57162276699, "Incorrectly parsed latitude"); + zassert_equal(data.nav_data.longitude, 9961012299, "Incorrectly parsed longitude"); + zassert_equal(data.nav_data.speed, 169, "Incorrectly parsed speed"); + zassert_equal(data.nav_data.bearing, 33310, "Incorrectly parsed speed"); + zassert_equal(data.utc.hour, 16, "Incorrectly parsed hour"); + zassert_equal(data.utc.minute, 8, "Incorrectly parsed minute"); + zassert_equal(data.utc.millisecond, 49000, "Incorrectly parsed millisecond"); + zassert_equal(data.utc.month_day, 9, "Incorrectly parsed month day"); + zassert_equal(data.utc.month, 9, "Incorrectly parsed month"); + zassert_equal(data.utc.century_year, 23, "Incorrectly parsed century year"); +} + +/* "$GNGGA,160858.000,5709.734778,N,00957.659514,E,1,6,1.41,15.234,M,42.371,M,,*72" */ +const char *gga_argv_fix[16] = { + "$GNGGA", + "160858.000", + "5709.734778", + "N", + "00957.659514", + "E", + "1", + "6", + "1.41", + "15.234", + "M", + "42.371", + "M", + "", + "", + "72", +}; + +ZTEST(gnss_nmea0183, test_parse_gga_fix) +{ + int ret; + + /* Corrupt data */ + memset(&data, 0xFF, sizeof(data)); + + ret = gnss_nmea0183_parse_gga(gga_argv_fix, ARRAY_SIZE(gga_argv_fix), &data); + zassert_ok(ret, "NMEA0183 GGA message parse should succeed"); + zassert_equal(data.info.fix_quality, GNSS_FIX_QUALITY_GNSS_SPS, + "Incorrectly parsed fix quality"); + + zassert_equal(data.info.fix_status, GNSS_FIX_STATUS_GNSS_FIX, + "Incorrectly parsed fix status"); + + zassert_equal(data.info.satellites_cnt, 6, + "Incorrectly parsed number of satelites"); + + zassert_equal(data.info.hdop, 1410, "Incorrectly parsed HDOP"); + zassert_equal(data.nav_data.altitude, 42371, "Incorrectly parsed altitude"); +} + +ZTEST(gnss_nmea0183, test_snprintk) +{ + int ret; + char buf[sizeof("$PAIR002,3*27")]; + + ret = gnss_nmea0183_snprintk(buf, sizeof(buf), "PAIR%03u,%u", 2, 3); + zassert_equal(ret, (sizeof("$PAIR002,3*27") - 1), "Failed to format NMEA0183 message"); + zassert_ok(strcmp(buf, "$PAIR002,3*27"), "Incorrectly formatted NMEA0183 message"); + + ret = gnss_nmea0183_snprintk(buf, sizeof(buf) - 1, "PAIR%03u,%u", 2, 3); + zassert_equal(ret, -ENOMEM, "Should fail with -ENOMEM as buffer is too small"); +} + +/* $GPGSV,8,1,25,21,44,141,47,15,14,049,44,6,31,255,46,3,25,280,44*75 */ +const char *gpgsv_8_1_25[21] = { + "$GPGSV", + "8", + "1", + "25", + "21", + "44", + "141", + "47", + "15", + "14", + "049", + "44", + "6", + "31", + "255", + "46", + "3", + "25", + "280", + "44", + "75", +}; + +static const struct gnss_nmea0183_gsv_header gpgsv_8_1_25_header = { + .system = GNSS_SYSTEM_GPS, + .number_of_messages = 8, + .message_number = 1, + .number_of_svs = 25 +}; + +static const struct gnss_satellite gpgsv_8_1_25_sats[] = { + {.prn = 21, .elevation = 44, .azimuth = 141, .snr = 47, + .system = GNSS_SYSTEM_GPS, .is_tracked = true}, + {.prn = 15, .elevation = 14, .azimuth = 49, .snr = 44, + .system = GNSS_SYSTEM_GPS, .is_tracked = true}, + {.prn = 6, .elevation = 31, .azimuth = 255, .snr = 46, + .system = GNSS_SYSTEM_GPS, .is_tracked = true}, + {.prn = 3, .elevation = 25, .azimuth = 280, .snr = 44, + .system = GNSS_SYSTEM_GPS, .is_tracked = true}, +}; + +/* $GPGSV,8,2,25,18,61,057,48,22,68,320,52,27,34,268,47,24,32,076,45*76 */ +const char *gpgsv_8_2_25[21] = { + "$GPGSV", + "8", + "2", + "25", + "18", + "61", + "057", + "48", + "22", + "68", + "320", + "52", + "27", + "34", + "268", + "47", + "24", + "32", + "076", + "45", + "76", +}; + +static const struct gnss_nmea0183_gsv_header gpgsv_8_2_25_header = { + .system = GNSS_SYSTEM_GPS, + .number_of_messages = 8, + .message_number = 2, + .number_of_svs = 25 +}; + +static const struct gnss_satellite gpgsv_8_2_25_sats[] = { + {.prn = 18, .elevation = 61, .azimuth = 57, .snr = 48, + .system = GNSS_SYSTEM_GPS, .is_tracked = true}, + {.prn = 22, .elevation = 68, .azimuth = 320, .snr = 52, + .system = GNSS_SYSTEM_GPS, .is_tracked = true}, + {.prn = 27, .elevation = 34, .azimuth = 268, .snr = 47, + .system = GNSS_SYSTEM_GPS, .is_tracked = true}, + {.prn = 24, .elevation = 32, .azimuth = 76, .snr = 45, + .system = GNSS_SYSTEM_GPS, .is_tracked = true}, +}; + +/* $GPGSV,8,3,25,14,51,214,49,19,23,308,46*7E */ +const char *gpgsv_8_3_25[13] = { + "$GPGSV", + "8", + "3", + "25", + "14", + "51", + "214", + "49", + "19", + "23", + "308", + "46", + "7E", +}; + +static const struct gnss_nmea0183_gsv_header gpgsv_8_3_25_header = { + .system = GNSS_SYSTEM_GPS, + .number_of_messages = 8, + .message_number = 3, + .number_of_svs = 25 +}; + +static const struct gnss_satellite gpgsv_8_3_25_sats[] = { + {.prn = 14, .elevation = 51, .azimuth = 214, .snr = 49, + .system = GNSS_SYSTEM_GPS, .is_tracked = true}, + {.prn = 19, .elevation = 23, .azimuth = 308, .snr = 46, + .system = GNSS_SYSTEM_GPS, .is_tracked = true}, +}; + +/* $GPGSV,8,4,25,51,44,183,49,46,41,169,43,48,36,220,45*47 */ +const char *gpgsv_8_4_25[17] = { + "$GPGSV", + "8", + "4", + "25", + "51", + "44", + "183", + "49", + "46", + "41", + "169", + "43", + "48", + "36", + "220", + "45", + "47", +}; + +static const struct gnss_nmea0183_gsv_header gpgsv_8_4_25_header = { + .system = GNSS_SYSTEM_GPS, + .number_of_messages = 8, + .message_number = 4, + .number_of_svs = 25 +}; + +static const struct gnss_satellite gpgsv_8_4_25_sats[] = { + {.prn = (51 + 87), .elevation = 44, .azimuth = 183, .snr = 49, + .system = GNSS_SYSTEM_SBAS, .is_tracked = true}, + {.prn = (46 + 87), .elevation = 41, .azimuth = 169, .snr = 43, + .system = GNSS_SYSTEM_SBAS, .is_tracked = true}, + {.prn = (48 + 87), .elevation = 36, .azimuth = 220, .snr = 45, + .system = GNSS_SYSTEM_SBAS, .is_tracked = true}, +}; + +/* $GLGSV,8,5,25,82,49,219,52,76,22,051,41,83,37,316,51,67,57,010,51*6C */ +const char *glgsv_8_5_25[21] = { + "$GLGSV", + "8", + "5", + "25", + "82", + "49", + "219", + "52", + "76", + "22", + "051", + "41", + "83", + "37", + "316", + "51", + "67", + "57", + "010", + "51", + "6C", +}; + +static const struct gnss_nmea0183_gsv_header glgsv_8_5_25_header = { + .system = GNSS_SYSTEM_GLONASS, + .number_of_messages = 8, + .message_number = 5, + .number_of_svs = 25 +}; + +static const struct gnss_satellite glgsv_8_5_25_sats[] = { + {.prn = (82 - 64), .elevation = 49, .azimuth = 219, .snr = 52, + .system = GNSS_SYSTEM_GLONASS, .is_tracked = true}, + {.prn = (76 - 64), .elevation = 22, .azimuth = 51, .snr = 41, + .system = GNSS_SYSTEM_GLONASS, .is_tracked = true}, + {.prn = (83 - 64), .elevation = 37, .azimuth = 316, .snr = 51, + .system = GNSS_SYSTEM_GLONASS, .is_tracked = true}, + {.prn = (67 - 64), .elevation = 57, .azimuth = 10, .snr = 51, + .system = GNSS_SYSTEM_GLONASS, .is_tracked = true}, +}; + +/* $GLGSV,8,6,25,77,24,108,44,81,10,181,46,78,1,152,34,66,18,060,45*50 */ +const char *glgsv_8_6_25[21] = { + "$GLGSV", + "8", + "6", + "25", + "77", + "24", + "108", + "44", + "81", + "10", + "181", + "46", + "78", + "1", + "152", + "34", + "66", + "18", + "060", + "45", + "50", +}; + +static const struct gnss_nmea0183_gsv_header glgsv_8_6_25_header = { + .system = GNSS_SYSTEM_GLONASS, + .number_of_messages = 8, + .message_number = 6, + .number_of_svs = 25 +}; + +static const struct gnss_satellite glgsv_8_6_25_sats[] = { + {.prn = (77 - 64), .elevation = 24, .azimuth = 108, .snr = 44, + .system = GNSS_SYSTEM_GLONASS, .is_tracked = true}, + {.prn = (81 - 64), .elevation = 10, .azimuth = 181, .snr = 46, + .system = GNSS_SYSTEM_GLONASS, .is_tracked = true}, + {.prn = (78 - 64), .elevation = 1, .azimuth = 152, .snr = 34, + .system = GNSS_SYSTEM_GLONASS, .is_tracked = true}, + {.prn = (66 - 64), .elevation = 18, .azimuth = 60, .snr = 45, + .system = GNSS_SYSTEM_GLONASS, .is_tracked = true}, +}; + +/* $GLGSV,8,7,25,68,37,284,50*5C */ +const char *glgsv_8_7_25[9] = { + "$GLGSV", + "8", + "7", + "25", + "68", + "37", + "284", + "50", + "5C", +}; + +static const struct gnss_nmea0183_gsv_header glgsv_8_7_25_header = { + .system = GNSS_SYSTEM_GLONASS, + .number_of_messages = 8, + .message_number = 7, + .number_of_svs = 25 +}; + +static const struct gnss_satellite glgsv_8_7_25_sats[] = { + {.prn = (68 - 64), .elevation = 37, .azimuth = 284, .snr = 50, + .system = GNSS_SYSTEM_GLONASS, .is_tracked = true}, +}; + +/* $GBGSV,8,8,25,111,35,221,47,112,4,179,39,114,48,290,48*11 */ +const char *gbgsv_8_8_25[17] = { + "$GBGSV", + "8", + "8", + "25", + "111", + "35", + "221", + "47", + "112", + "4", + "179", + "39", + "114", + "48", + "290", + "48", + "11", +}; + +static const struct gnss_nmea0183_gsv_header gbgsv_8_8_25_header = { + .system = GNSS_SYSTEM_BEIDOU, + .number_of_messages = 8, + .message_number = 8, + .number_of_svs = 25 +}; + +static const struct gnss_satellite gbgsv_8_8_25_sats[] = { + {.prn = (111 - 100), .elevation = 35, .azimuth = 221, .snr = 47, + .system = GNSS_SYSTEM_BEIDOU, .is_tracked = true}, + {.prn = (112 - 100), .elevation = 4, .azimuth = 179, .snr = 39, + .system = GNSS_SYSTEM_BEIDOU, .is_tracked = true}, + {.prn = (114 - 100), .elevation = 48, .azimuth = 290, .snr = 48, + .system = GNSS_SYSTEM_BEIDOU, .is_tracked = true}, +}; + +struct test_gsv_sample { + const char **argv; + uint16_t argc; + const struct gnss_nmea0183_gsv_header *header; + const struct gnss_satellite *satellites; + uint16_t number_of_svs; +}; + +static const struct test_gsv_sample gsv_samples[] = { + {.argv = gpgsv_8_1_25, .argc = ARRAY_SIZE(gpgsv_8_1_25), .header = &gpgsv_8_1_25_header, + .satellites = gpgsv_8_1_25_sats, .number_of_svs = ARRAY_SIZE(gpgsv_8_1_25_sats)}, + {.argv = gpgsv_8_2_25, .argc = ARRAY_SIZE(gpgsv_8_2_25), .header = &gpgsv_8_2_25_header, + .satellites = gpgsv_8_2_25_sats, .number_of_svs = ARRAY_SIZE(gpgsv_8_2_25_sats)}, + {.argv = gpgsv_8_3_25, .argc = ARRAY_SIZE(gpgsv_8_3_25), .header = &gpgsv_8_3_25_header, + .satellites = gpgsv_8_3_25_sats, .number_of_svs = ARRAY_SIZE(gpgsv_8_3_25_sats)}, + {.argv = gpgsv_8_4_25, .argc = ARRAY_SIZE(gpgsv_8_4_25), .header = &gpgsv_8_4_25_header, + .satellites = gpgsv_8_4_25_sats, .number_of_svs = ARRAY_SIZE(gpgsv_8_4_25_sats)}, + {.argv = glgsv_8_5_25, .argc = ARRAY_SIZE(glgsv_8_5_25), .header = &glgsv_8_5_25_header, + .satellites = glgsv_8_5_25_sats, .number_of_svs = ARRAY_SIZE(glgsv_8_5_25_sats)}, + {.argv = glgsv_8_6_25, .argc = ARRAY_SIZE(glgsv_8_6_25), .header = &glgsv_8_6_25_header, + .satellites = glgsv_8_6_25_sats, .number_of_svs = ARRAY_SIZE(glgsv_8_6_25_sats)}, + {.argv = glgsv_8_7_25, .argc = ARRAY_SIZE(glgsv_8_7_25), .header = &glgsv_8_7_25_header, + .satellites = glgsv_8_7_25_sats, .number_of_svs = ARRAY_SIZE(glgsv_8_7_25_sats)}, + {.argv = gbgsv_8_8_25, .argc = ARRAY_SIZE(gbgsv_8_8_25), .header = &gbgsv_8_8_25_header, + .satellites = gbgsv_8_8_25_sats, .number_of_svs = ARRAY_SIZE(gbgsv_8_8_25_sats)}, +}; + +ZTEST(gnss_nmea0183, test_gsv_parse_headers) +{ + struct gnss_nmea0183_gsv_header header; + int ret; + + for (uint16_t i = 0; i < ARRAY_SIZE(gsv_samples); i++) { + ret = gnss_nmea0183_parse_gsv_header(gsv_samples[i].argv, gsv_samples[i].argc, + &header); + + zassert_ok(ret, "Failed to parse GSV header"); + + zassert_equal(header.system, gsv_samples[i].header->system, + "Failed to parse GNSS system"); + + zassert_equal(header.number_of_messages, + gsv_samples[i].header->number_of_messages, + "Failed to parse number of messages"); + + zassert_equal(header.message_number, gsv_samples[i].header->message_number, + "Failed to parse message number"); + + zassert_equal(header.number_of_svs, gsv_samples[i].header->number_of_svs, + "Failed to parse number of space vehicles"); + } +} + +ZTEST(gnss_nmea0183, test_gsv_parse_satellites) +{ + struct gnss_satellite satellites[4]; + int ret; + + for (uint16_t i = 0; i < ARRAY_SIZE(gsv_samples); i++) { + ret = gnss_nmea0183_parse_gsv_svs(gsv_samples[i].argv, gsv_samples[i].argc, + satellites, ARRAY_SIZE(satellites)); + + zassert_equal(ret, gsv_samples[i].number_of_svs, + "Incorrect number of satellites parsed"); + + for (uint16_t u = 0; u < gsv_samples[i].number_of_svs; u++) { + zassert_equal(gsv_samples[i].satellites[u].prn, + satellites[u].prn, + "Failed to parse satellite prn"); + zassert_equal(gsv_samples[i].satellites[u].snr, + satellites[u].snr, + "Failed to parse satellite snr"); + zassert_equal(gsv_samples[i].satellites[u].elevation, + satellites[u].elevation, + "Failed to parse satellite elevation"); + zassert_equal(gsv_samples[i].satellites[u].azimuth, + satellites[u].azimuth, + "Failed to parse satellite azimuth"); + zassert_equal(gsv_samples[i].satellites[u].system, + satellites[u].system, + "Failed to parse satellite system"); + zassert_equal(gsv_samples[i].satellites[u].is_tracked, + satellites[u].is_tracked, + "Failed to parse satellite is_tracked"); + } + } +} + +ZTEST_SUITE(gnss_nmea0183, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/drivers/gnss/gnss_nmea0183/testcase.yaml b/tests/drivers/gnss/gnss_nmea0183/testcase.yaml new file mode 100644 index 00000000000..b63e7f24dbf --- /dev/null +++ b/tests/drivers/gnss/gnss_nmea0183/testcase.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +tests: + drivers.gnss.gnss_nmea0183: + tags: + - drivers + - gnss + - parse + - nmea0183 diff --git a/tests/drivers/gnss/gnss_parse/CMakeLists.txt b/tests/drivers/gnss/gnss_parse/CMakeLists.txt new file mode 100644 index 00000000000..ec07dff7dc1 --- /dev/null +++ b/tests/drivers/gnss/gnss_parse/CMakeLists.txt @@ -0,0 +1,14 @@ +# Copyright (c) 2023 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(gnss_parse) + +target_sources(app PRIVATE + src/main.c +) + +target_include_directories(app PRIVATE ${ZEPHYR_BASE}/drivers/gnss) diff --git a/tests/drivers/gnss/gnss_parse/prj.conf b/tests/drivers/gnss/gnss_parse/prj.conf new file mode 100644 index 00000000000..78ac36dd3db --- /dev/null +++ b/tests/drivers/gnss/gnss_parse/prj.conf @@ -0,0 +1,7 @@ +# Copyright (c) 2023 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_GNSS=y +CONFIG_GNSS_PARSE=y +CONFIG_ZTEST=y +CONFIG_ZTEST_STACK_SIZE=4096 diff --git a/tests/drivers/gnss/gnss_parse/src/main.c b/tests/drivers/gnss/gnss_parse/src/main.c new file mode 100644 index 00000000000..9bf1c0e4eb6 --- /dev/null +++ b/tests/drivers/gnss/gnss_parse/src/main.c @@ -0,0 +1,99 @@ +/* + * Copyright 2023 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "gnss_parse.h" + +struct test_atoi_sample { + const char *str; + uint8_t base; + int32_t value; +}; + +static const struct test_atoi_sample atoi_samples[] = { + {.str = "10", .base = 10, .value = 10}, + {.str = "1", .base = 10, .value = 1}, + {.str = "002", .base = 10, .value = 2}, + {.str = "-10", .base = 10, .value = -10}, + {.str = "-1", .base = 10, .value = -1}, + {.str = "-002", .base = 10, .value = -2}, + {.str = "30000000", .base = 10, .value = 30000000}, + {.str = "-30000000", .base = 10, .value = -30000000}, + {.str = "00", .base = 16, .value = 0}, + {.str = "20", .base = 16, .value = 32}, + {.str = "42", .base = 16, .value = 66}, + {.str = "122", .base = 16, .value = 290}, + {.str = "0122", .base = 16, .value = 290}, +}; + +ZTEST(gnss_parse, test_atoi) +{ + int32_t value; + + for (size_t i = 0; i < ARRAY_SIZE(atoi_samples); i++) { + zassert_ok(gnss_parse_atoi(atoi_samples[i].str, atoi_samples[i].base, &value), + "Parse failed"); + + zassert_equal(atoi_samples[i].value, value, "Parsed value is incorrect"); + } + + zassert_equal(gnss_parse_atoi("a10", 10, &value), -EINVAL, + "Parse should fail due to invalid base 10 chars"); + + zassert_equal(gnss_parse_atoi("h#1c", 16, &value), -EINVAL, + "Parse should fail due to invalid base 16 chars"); +} + +struct test_dec_sample { + const char *str; + int64_t value; +}; + +static const struct test_dec_sample dec_to_nano_samples[] = { + {.str = "10", .value = 10000000000}, + {.str = "1", .value = 1000000000}, + {.str = "002", .value = 2000000000}, + {.str = "-10", .value = -10000000000}, + {.str = "-1", .value = -1000000000}, + {.str = "-002", .value = -2000000000}, + {.str = "30000000", .value = 30000000000000000}, + {.str = "-30000000", .value = -30000000000000000}, + {.str = "0.10", .value = 100000000}, + {.str = "-0.10", .value = -100000000}, + {.str = "1", .value = 1000000000}, + {.str = "002.000", .value = 2000000000}, + {.str = "-002.000", .value = -2000000000}, + {.str = "0.989812343", .value = 989812343}, + {.str = "-0.989812343", .value = -989812343}, + {.str = "0.112211", .value = 112211000}, + {.str = "-0.112211", .value = -112211000}, + {.str = "000000000.112211000000000000", .value = 112211000}, + {.str = "-000000000.11221100000000000", .value = -112211000}, +}; + +ZTEST(gnss_parse, test_dec_to_nano) +{ + int64_t value; + + for (volatile size_t i = 0; i < ARRAY_SIZE(dec_to_nano_samples); i++) { + zassert_ok(gnss_parse_dec_to_nano(dec_to_nano_samples[i].str, &value), + "Parse failed"); + + zassert_equal(dec_to_nano_samples[i].value, value, "Parsed value is incorrect"); + } + + zassert_equal(gnss_parse_dec_to_nano("-0s02..000", &value), -EINVAL, + "Parse should fail due to double dot"); + + zassert_equal(gnss_parse_dec_to_nano("--002.000", &value), -EINVAL, + "Parse should fail due to double -"); + + zassert_equal(gnss_parse_dec_to_nano("-00s2.000", &value), -EINVAL, + "Parse should fail due to invalid char"); +} + +ZTEST_SUITE(gnss_parse, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/drivers/gnss/gnss_parse/testcase.yaml b/tests/drivers/gnss/gnss_parse/testcase.yaml new file mode 100644 index 00000000000..82939ba446a --- /dev/null +++ b/tests/drivers/gnss/gnss_parse/testcase.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +tests: + drivers.gnss.gnss_parse: + tags: + - drivers + - gnss + - parse diff --git a/tests/drivers/gpio/gpio_api_1pin/prj.conf b/tests/drivers/gpio/gpio_api_1pin/prj.conf index 962df8f1d50..0e799280f51 100644 --- a/tests/drivers/gpio/gpio_api_1pin/prj.conf +++ b/tests/drivers/gpio/gpio_api_1pin/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_GPIO=y diff --git a/tests/drivers/gpio/gpio_basic_api/boards/cy8cproto_063_ble.overlay b/tests/drivers/gpio/gpio_basic_api/boards/cy8cproto_063_ble.overlay new file mode 100644 index 00000000000..a01e0d692c5 --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/cy8cproto_063_ble.overlay @@ -0,0 +1,18 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + */ + +/ { + resources { + compatible = "test-gpio-basic-api"; + out-gpios = <&gpio_prt9 4 0>; + in-gpios = <&gpio_prt9 2 0>; + }; +}; + +&gpio_prt9 { + status = "okay"; +}; diff --git a/tests/drivers/gpio/gpio_basic_api/boards/esp32c3_luatos_core.overlay b/tests/drivers/gpio/gpio_basic_api/boards/esp32c3_luatos_core.overlay new file mode 100644 index 00000000000..6c4f3e2e226 --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/esp32c3_luatos_core.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + resources { + compatible = "test-gpio-basic-api"; + out-gpios = <&gpio0 4 0>; + in-gpios = <&gpio0 5 0>; + }; +}; diff --git a/tests/drivers/gpio/gpio_basic_api/boards/esp32c3_luatos_core_usb.overlay b/tests/drivers/gpio/gpio_basic_api/boards/esp32c3_luatos_core_usb.overlay new file mode 100644 index 00000000000..6c4f3e2e226 --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/esp32c3_luatos_core_usb.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + resources { + compatible = "test-gpio-basic-api"; + out-gpios = <&gpio0 4 0>; + in-gpios = <&gpio0 5 0>; + }; +}; diff --git a/tests/drivers/gpio/gpio_basic_api/boards/esp32s3_luatos_core.overlay b/tests/drivers/gpio/gpio_basic_api/boards/esp32s3_luatos_core.overlay new file mode 100644 index 00000000000..6c4f3e2e226 --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/esp32s3_luatos_core.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + resources { + compatible = "test-gpio-basic-api"; + out-gpios = <&gpio0 4 0>; + in-gpios = <&gpio0 5 0>; + }; +}; diff --git a/tests/drivers/gpio/gpio_basic_api/boards/esp32s3_luatos_core_usb.overlay b/tests/drivers/gpio/gpio_basic_api/boards/esp32s3_luatos_core_usb.overlay new file mode 100644 index 00000000000..6c4f3e2e226 --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/esp32s3_luatos_core_usb.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + resources { + compatible = "test-gpio-basic-api"; + out-gpios = <&gpio0 4 0>; + in-gpios = <&gpio0 5 0>; + }; +}; diff --git a/tests/drivers/gpio/gpio_basic_api/boards/mr_canhubk3_wkpu.overlay b/tests/drivers/gpio/gpio_basic_api/boards/mr_canhubk3_wkpu.overlay new file mode 100644 index 00000000000..e9ca00dbabf --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/mr_canhubk3_wkpu.overlay @@ -0,0 +1,20 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + resources { + compatible = "test-gpio-basic-api"; + /* Use LPSPI1 MISO/MOSI pins which are also used for spi_loopback test */ + out-gpios = <&gpioa_h 13 0>; + in-gpios = <&gpioa_h 14 NXP_S32_GPIO_INT_WKPU>; + }; +}; + +&wkpu { + status = "okay"; +}; diff --git a/tests/drivers/gpio/gpio_basic_api/prj.conf b/tests/drivers/gpio/gpio_basic_api/prj.conf index 41559c7df1f..b5511690df7 100644 --- a/tests/drivers/gpio/gpio_basic_api/prj.conf +++ b/tests/drivers/gpio/gpio_basic_api/prj.conf @@ -1,7 +1,6 @@ CONFIG_GPIO=y CONFIG_GPIO_GET_CONFIG=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y #CONFIG_TEST_USERSPACE=y diff --git a/tests/drivers/gpio/gpio_basic_api/src/main.c b/tests/drivers/gpio/gpio_basic_api/src/main.c index 11c5da9671d..143be7d314d 100644 --- a/tests/drivers/gpio/gpio_basic_api/src/main.c +++ b/tests/drivers/gpio/gpio_basic_api/src/main.c @@ -115,3 +115,9 @@ ZTEST_SUITE(gpio_port_cb_mgmt, NULL, gpio_basic_setup, NULL, NULL, NULL); /* Test GPIO callbacks */ ZTEST_SUITE(gpio_port_cb_vari, NULL, gpio_basic_setup, NULL, NULL, NULL); + +/* Test GPIO port configuration influence on callbacks. Want to run just + * after flash, hence the name starting in 'a' + */ +ZTEST_SUITE(after_flash_gpio_config_trigger, NULL, gpio_basic_setup, NULL, NULL, + NULL); diff --git a/tests/drivers/gpio/gpio_basic_api/src/test_callback_manage.c b/tests/drivers/gpio/gpio_basic_api/src/test_callback_manage.c index 97e217f298a..3a409009c70 100644 --- a/tests/drivers/gpio/gpio_basic_api/src/test_callback_manage.c +++ b/tests/drivers/gpio/gpio_basic_api/src/test_callback_manage.c @@ -43,12 +43,12 @@ static int init_callback(const struct device *dev, } if (rc == 0) { /* 1. set PIN_OUT */ - rc = gpio_pin_configure(dev, PIN_OUT, GPIO_OUTPUT_LOW); + rc = gpio_pin_configure(dev, PIN_OUT, (GPIO_OUTPUT_LOW | PIN_OUT_FLAGS)); } if (rc == 0) { /* 2. configure PIN_IN callback, but don't enable */ - rc = gpio_pin_configure(dev, PIN_IN, GPIO_INPUT); + rc = gpio_pin_configure(dev, PIN_IN, (GPIO_INPUT | PIN_IN_FLAGS)); } if (rc == 0) { diff --git a/tests/drivers/gpio/gpio_basic_api/src/test_callback_trigger.c b/tests/drivers/gpio/gpio_basic_api/src/test_callback_trigger.c index 2209e988230..868e3822399 100644 --- a/tests/drivers/gpio/gpio_basic_api/src/test_callback_trigger.c +++ b/tests/drivers/gpio/gpio_basic_api/src/test_callback_trigger.c @@ -40,7 +40,7 @@ static int test_callback(int mode) gpio_pin_interrupt_configure(dev, PIN_OUT, GPIO_INT_DISABLE); /* 1. set PIN_OUT to logical initial state inactive */ - uint32_t out_flags = GPIO_OUTPUT_LOW; + uint32_t out_flags = GPIO_OUTPUT_LOW | PIN_OUT_FLAGS; if ((mode & GPIO_INT_LOW_0) != 0) { out_flags = GPIO_OUTPUT_HIGH | GPIO_ACTIVE_LOW; @@ -54,7 +54,7 @@ static int test_callback(int mode) } /* 2. configure PIN_IN callback and trigger condition */ - rc = gpio_pin_configure(dev, PIN_IN, GPIO_INPUT); + rc = gpio_pin_configure(dev, PIN_IN, (GPIO_INPUT | PIN_IN_FLAGS)); if (rc != 0) { TC_ERROR("config PIN_IN fail: %d\n", rc); goto err_exit; diff --git a/tests/drivers/gpio/gpio_basic_api/src/test_config_trigger.c b/tests/drivers/gpio/gpio_basic_api/src/test_config_trigger.c new file mode 100644 index 00000000000..869e550aba4 --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/src/test_config_trigger.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#include "test_gpio.h" + +static struct drv_data data; +static int cb_cnt; + +static void callback(const struct device *dev, + struct gpio_callback *gpio_cb, uint32_t pins) +{ + /*= checkpoint: pins should be marked with correct pin number bit =*/ + zassert_equal(pins, BIT(PIN_IN), + "unexpected pins %x", pins); + + ++cb_cnt; +} + +ZTEST(after_flash_gpio_config_trigger, test_gpio_config_twice_trigger) +{ + const struct device *const dev = DEVICE_DT_GET(DEV); + struct drv_data *drv_data = &data; + int ret; + + cb_cnt = 0; + + ret = gpio_pin_configure(dev, PIN_OUT, GPIO_DISCONNECTED); + + /* 1. Configure PIN_IN callback */ + ret = gpio_pin_configure(dev, PIN_IN, GPIO_INPUT); + zassert_ok(ret, "config PIN_IN failed"); + + gpio_init_callback(&drv_data->gpio_cb, callback, BIT(PIN_IN)); + ret = gpio_add_callback(dev, &drv_data->gpio_cb); + zassert_ok(ret, "add callback failed"); + + /* 2. Enable PIN callback as both edges */ + ret = gpio_pin_interrupt_configure(dev, PIN_IN, GPIO_INT_EDGE_BOTH); + zassert_ok(ret, "enable callback failed"); + + /* 3. Configure PIN_OUT as open drain, internal pull-up (may trigger + * callback) + */ + ret = gpio_pin_configure(dev, PIN_OUT, + GPIO_OUTPUT | GPIO_OPEN_DRAIN | GPIO_PULL_UP); + if (ret == -ENOTSUP) { + TC_PRINT("Open drain not supported.\n"); + gpio_remove_callback(dev, &drv_data->gpio_cb); + ztest_test_skip(); + return; + } + zassert_ok(ret, "config PIN_OUT failed"); + + /* 4. Configure PIN_OUT again (should not trigger callback) */ + ret = gpio_pin_configure(dev, PIN_OUT, + GPIO_OUTPUT | GPIO_OPEN_DRAIN | GPIO_PULL_UP); + zassert_ok(ret, "config PIN_OUT twice failed"); + + /* 5. Wait a bit and ensure that interrupt happened at most once */ + k_sleep(K_MSEC(10)); + zassert_between_inclusive(cb_cnt, 0, 1, "Got %d interrupts", cb_cnt); + + gpio_remove_callback(dev, &drv_data->gpio_cb); +} + +ZTEST(after_flash_gpio_config_trigger, test_gpio_config_trigger) +{ + const struct device *const dev = DEVICE_DT_GET(DEV); + struct drv_data *drv_data = &data; + int ret; + + cb_cnt = 0; + + ret = gpio_pin_configure(dev, PIN_OUT, GPIO_DISCONNECTED); + + /* 1. Configure PIN_IN callback */ + ret = gpio_pin_configure(dev, PIN_IN, GPIO_INPUT); + zassert_ok(ret, "config PIN_IN failed"); + + gpio_init_callback(&drv_data->gpio_cb, callback, BIT(PIN_IN)); + ret = gpio_add_callback(dev, &drv_data->gpio_cb); + zassert_ok(ret, "add callback failed"); + + /* 2. Enable PIN callback as both edges */ + ret = gpio_pin_interrupt_configure(dev, PIN_IN, GPIO_INT_EDGE_BOTH); + zassert_ok(ret, "enable callback failed"); + + /* 3. Configure PIN_OUT as open drain, internal pull-up (may trigger + * callback) + */ + ret = gpio_pin_configure(dev, PIN_OUT, + GPIO_OUTPUT | GPIO_OPEN_DRAIN | GPIO_PULL_UP); + if (ret == -ENOTSUP) { + TC_PRINT("Open drain not supported.\n"); + gpio_remove_callback(dev, &drv_data->gpio_cb); + ztest_test_skip(); + return; + } + zassert_ok(ret, "config PIN_OUT failed"); + + /* 4. Wait a bit and ensure that interrupt happened at most once */ + k_sleep(K_MSEC(10)); + zassert_between_inclusive(cb_cnt, 0, 1, "Got %d interrupts", cb_cnt); + + gpio_remove_callback(dev, &drv_data->gpio_cb); +} diff --git a/tests/drivers/gpio/gpio_basic_api/src/test_gpio.h b/tests/drivers/gpio/gpio_basic_api/src/test_gpio.h index 38a15dc3dce..ba3d3ae5eba 100644 --- a/tests/drivers/gpio/gpio_basic_api/src/test_gpio.h +++ b/tests/drivers/gpio/gpio_basic_api/src/test_gpio.h @@ -25,7 +25,9 @@ #define DEV_IN DT_GPIO_CTLR(DT_INST(0, test_gpio_basic_api), in_gpios) #define DEV DEV_OUT /* DEV_OUT should equal DEV_IN, we test for this */ #define PIN_OUT DT_GPIO_PIN(DT_INST(0, test_gpio_basic_api), out_gpios) +#define PIN_OUT_FLAGS DT_GPIO_FLAGS(DT_INST(0, test_gpio_basic_api), out_gpios) #define PIN_IN DT_GPIO_PIN(DT_INST(0, test_gpio_basic_api), in_gpios) +#define PIN_IN_FLAGS DT_GPIO_FLAGS(DT_INST(0, test_gpio_basic_api), in_gpios) #elif DT_NODE_HAS_STATUS(DT_ALIAS(gpio_0), okay) #define DEV DT_GPIO_CTLR(DT_ALIAS(gpio_0)) diff --git a/tests/drivers/gpio/gpio_basic_api/testcase.yaml b/tests/drivers/gpio/gpio_basic_api/testcase.yaml index 9fb9d7fb292..cc572e82ef0 100644 --- a/tests/drivers/gpio/gpio_basic_api/testcase.yaml +++ b/tests/drivers/gpio/gpio_basic_api/testcase.yaml @@ -16,3 +16,7 @@ tests: platform_allow: nrf52840dk_nrf52840 nrf52_bsim extra_args: "DTC_OVERLAY_FILE=boards/nrf52840dk_nrf52840.overlay;\ boards/nrf52840dk_nrf52840_sense_edge.overlay" + + drivers.gpio.mr_canhubk3_wkpu: + platform_allow: mr_canhubk3 + extra_args: "DTC_OVERLAY_FILE=boards/mr_canhubk3_wkpu.overlay" diff --git a/tests/drivers/gpio/gpio_enable_disable_interrupt/prj.conf b/tests/drivers/gpio/gpio_enable_disable_interrupt/prj.conf index 26e3362e645..510d8b6359c 100644 --- a/tests/drivers/gpio/gpio_enable_disable_interrupt/prj.conf +++ b/tests/drivers/gpio/gpio_enable_disable_interrupt/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_GPIO=y CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT=y diff --git a/tests/drivers/gpio/gpio_get_direction/prj.conf b/tests/drivers/gpio/gpio_get_direction/prj.conf index 3d3a27cb855..11186aeb7fb 100644 --- a/tests/drivers/gpio/gpio_get_direction/prj.conf +++ b/tests/drivers/gpio/gpio_get_direction/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_GPIO=y CONFIG_GPIO_GET_DIRECTION=y diff --git a/tests/drivers/gpio/gpio_hogs/prj.conf b/tests/drivers/gpio/gpio_hogs/prj.conf index 7361f2b9ee8..4bb163987af 100644 --- a/tests/drivers/gpio/gpio_hogs/prj.conf +++ b/tests/drivers/gpio/gpio_hogs/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_GPIO=y CONFIG_GPIO_GET_DIRECTION=y CONFIG_GPIO_GET_CONFIG=y diff --git a/tests/drivers/gpio/gpio_reserved_ranges/prj.conf b/tests/drivers/gpio/gpio_reserved_ranges/prj.conf index 66f87b668e8..caec3b5f874 100644 --- a/tests/drivers/gpio/gpio_reserved_ranges/prj.conf +++ b/tests/drivers/gpio/gpio_reserved_ranges/prj.conf @@ -1,4 +1,3 @@ CONFIG_GPIO=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y #CONFIG_TEST_USERSPACE=y diff --git a/tests/drivers/hwinfo/api/prj.conf b/tests/drivers/hwinfo/api/prj.conf index b00bb9bf425..616a826fabb 100644 --- a/tests/drivers/hwinfo/api/prj.conf +++ b/tests/drivers/hwinfo/api/prj.conf @@ -1,3 +1,2 @@ CONFIG_HWINFO=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/i2c/i2c_api/boards/cy8cproto_063_ble.overlay b/tests/drivers/i2c/i2c_api/boards/cy8cproto_063_ble.overlay new file mode 100644 index 00000000000..17df1697469 --- /dev/null +++ b/tests/drivers/i2c/i2c_api/boards/cy8cproto_063_ble.overlay @@ -0,0 +1,32 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + */ + +/ { + aliases { + gy271 = &i2c1; + i2c-0 =&i2c1; + }; +}; + +i2c1: &scb1 { + compatible = "infineon,cat1-i2c"; + + status = "okay"; + pinctrl-0 = <&p10_0_scb1_i2c_scl &p10_1_scb1_i2c_sda>; + pinctrl-names = "default"; +}; + +/* Configure pin control bias mode for i2c pins */ +&p10_0_scb1_i2c_scl { + drive-open-drain; + input-enable; +}; + +&p10_1_scb1_i2c_sda { + drive-open-drain; + input-enable; +}; diff --git a/tests/drivers/i2c/i2c_api/prj.conf b/tests/drivers/i2c/i2c_api/prj.conf index 7e3f6b38804..4b19609ecfb 100644 --- a/tests/drivers/i2c/i2c_api/prj.conf +++ b/tests/drivers/i2c/i2c_api/prj.conf @@ -1,3 +1,2 @@ CONFIG_I2C=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/i2c/i2c_target_api/boards/b_u585i_iot02a.conf b/tests/drivers/i2c/i2c_target_api/boards/b_u585i_iot02a.conf new file mode 100644 index 00000000000..34b2571d125 --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/b_u585i_iot02a.conf @@ -0,0 +1,2 @@ +CONFIG_I2C_STM32_INTERRUPT=y +CONFIG_I2C_VIRTUAL=n diff --git a/tests/drivers/i2c/i2c_target_api/boards/b_u585i_iot02a.overlay b/tests/drivers/i2c/i2c_target_api/boards/b_u585i_iot02a.overlay new file mode 100644 index 00000000000..f07d43230e9 --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/b_u585i_iot02a.overlay @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/* I2C bus pins are exposed on the STMod+. + * + * Bus SDA SCL + * Pin Hdr Pin Hdr + * i2c1 PB9 CN3:10 PB8 CN3:7 + * i2c2 PH5 CN2:10 PH4 CN2:7 + * + * Short Pin PB9 to PH5, and PB8 to PH4, for the test to pass. + */ + +&i2c1 { + eeprom0: eeprom@54 { + compatible = "zephyr,i2c-target-eeprom"; + reg = <0x54>; + size = <1024>; + }; +}; + +&i2c2 { + eeprom1: eeprom@56 { + compatible = "zephyr,i2c-target-eeprom"; + reg = <0x56>; + size = <1024>; + }; +}; diff --git a/tests/drivers/i2c/i2c_target_api/boards/nucleo_f091rc.overlay b/tests/drivers/i2c/i2c_target_api/boards/nucleo_f091rc.overlay index 6ca9868d734..0e2323a1a0f 100644 --- a/tests/drivers/i2c/i2c_target_api/boards/nucleo_f091rc.overlay +++ b/tests/drivers/i2c/i2c_target_api/boards/nucleo_f091rc.overlay @@ -20,9 +20,16 @@ &i2c2 { + /* i2c2 is disabled by default because of pin conflict with can1 */ + status = "okay"; eeprom1: eeprom@56 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x56>; size = <1024>; }; }; + +&can1 { + /* can1 shares the pins with i2c2 and must be disabled */ + status = "disabled"; +}; diff --git a/tests/drivers/i2c/i2c_target_api/boards/nucleo_wb55rg.conf b/tests/drivers/i2c/i2c_target_api/boards/nucleo_wb55rg.conf new file mode 100644 index 00000000000..34b2571d125 --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/nucleo_wb55rg.conf @@ -0,0 +1,2 @@ +CONFIG_I2C_STM32_INTERRUPT=y +CONFIG_I2C_VIRTUAL=n diff --git a/tests/drivers/i2c/i2c_target_api/boards/nucleo_wb55rg.overlay b/tests/drivers/i2c/i2c_target_api/boards/nucleo_wb55rg.overlay new file mode 100644 index 00000000000..121265cad7c --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/nucleo_wb55rg.overlay @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/* I2C bus pins are exposed on the Arduino Shield Connectors and Morpho connectors. + * + * Bus SDA SCL + * Pin Hdr Pin Hdr + * i2c1 PB9 CN5:9 PB8 CN5:10 + * i2c3 PA7 CN5:4 PB14 CN10:28 + * + * Short Pin PB9 to PA7, and PB8 to PB14, for the test to pass. + */ + +&i2c1 { + eeprom0: eeprom@54 { + compatible = "zephyr,i2c-target-eeprom"; + reg = <0x54>; + size = <1024>; + }; +}; + +&i2c3 { + pinctrl-0 = <&i2c3_scl_pa7 &i2c3_sda_pb14>; + pinctrl-names = "default"; + status = "okay"; + clock-frequency = ; + eeprom1: eeprom@56 { + compatible = "zephyr,i2c-target-eeprom"; + reg = <0x56>; + size = <1024>; + }; +}; diff --git a/tests/drivers/i2c/i2c_target_api/boards/stm32f3_disco.conf b/tests/drivers/i2c/i2c_target_api/boards/stm32f3_disco.conf new file mode 100644 index 00000000000..34b2571d125 --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/stm32f3_disco.conf @@ -0,0 +1,2 @@ +CONFIG_I2C_STM32_INTERRUPT=y +CONFIG_I2C_VIRTUAL=n diff --git a/tests/drivers/i2c/i2c_target_api/boards/stm32f3_disco.overlay b/tests/drivers/i2c/i2c_target_api/boards/stm32f3_disco.overlay new file mode 100644 index 00000000000..b23520b04ac --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/stm32f3_disco.overlay @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/* I2C bus pins are exposed on the ST P2 connector. + * + * Bus SDA SCL + * Pin Hdr Pin Hdr + * i2c1 PB7 P2:21 PB6 P2:22 + * i2c2 PA10 P2:43 PA9 P2:44 + * + * Short Pin PB7 to PA10, and PB6 to PA9, for the test to pass. + */ + + + +&i2c1 { + eeprom0: eeprom@54 { + compatible = "zephyr,i2c-target-eeprom"; + reg = <0x54>; + size = <1024>; + }; +}; + +&i2c2 { + eeprom1: eeprom@56 { + compatible = "zephyr,i2c-target-eeprom"; + reg = <0x56>; + size = <1024>; + }; + +}; diff --git a/tests/drivers/i2c/i2c_target_api/prj.conf b/tests/drivers/i2c/i2c_target_api/prj.conf index 9fe909e2e72..b79f33ce0a9 100644 --- a/tests/drivers/i2c/i2c_target_api/prj.conf +++ b/tests/drivers/i2c/i2c_target_api/prj.conf @@ -2,7 +2,6 @@ CONFIG_LOG=y CONFIG_I2C_LOG_LEVEL_INF=y CONFIG_BOOT_BANNER=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_I2C=y CONFIG_I2C_TARGET=y CONFIG_I2C_EEPROM_TARGET=y diff --git a/tests/drivers/i2c/i2c_target_api/testcase.yaml b/tests/drivers/i2c/i2c_target_api/testcase.yaml index a6113986274..d3c5a408495 100644 --- a/tests/drivers/i2c/i2c_target_api/testcase.yaml +++ b/tests/drivers/i2c/i2c_target_api/testcase.yaml @@ -10,16 +10,19 @@ common: tests: drivers.i2c.target_api.dual_role: platform_allow: + - b_u585i_iot02a - nucleo_f746zg - nucleo_g474re - nucleo_f091rc - stm32f072b_disco + - stm32f3_disco - nucleo_g071rb - nucleo_f207zg - nucleo_f429zi - nucleo_wl55jc - nucleo_l073rz - nucleo_l152re + - nucleo_wb55rg - rpi_pico - efr32bg22_brd4184a - mr_canhubk3 diff --git a/tests/drivers/i2c/i2c_tca954x/prj.conf b/tests/drivers/i2c/i2c_tca954x/prj.conf index fc01984ad47..0066bf2a93c 100644 --- a/tests/drivers/i2c/i2c_tca954x/prj.conf +++ b/tests/drivers/i2c/i2c_tca954x/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_I2C=y CONFIG_I2C_TCA954X_ROOT_INIT_PRIO=61 CONFIG_I2C_TCA954X_CHANNEL_INIT_PRIO=62 diff --git a/tests/drivers/i2s/i2s_api/prj.conf b/tests/drivers/i2s/i2s_api/prj.conf index d225c836f56..7c088b1ffe4 100644 --- a/tests/drivers/i2s/i2s_api/prj.conf +++ b/tests/drivers/i2s/i2s_api/prj.conf @@ -1,4 +1,3 @@ CONFIG_I2S=y CONFIG_ZTEST=y CONFIG_TEST_USERSPACE=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/i2s/i2s_speed/prj.conf b/tests/drivers/i2s/i2s_speed/prj.conf index 018e9027158..99ff252406a 100644 --- a/tests/drivers/i2s/i2s_speed/prj.conf +++ b/tests/drivers/i2s/i2s_speed/prj.conf @@ -1,3 +1,2 @@ CONFIG_I2S=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/input/gpio_keys/boards/native_posix_64.overlay b/tests/drivers/input/gpio_keys/boards/native_posix_64.overlay deleted file mode 100644 index 166e6f02e82..00000000000 --- a/tests/drivers/input/gpio_keys/boards/native_posix_64.overlay +++ /dev/null @@ -1,6 +0,0 @@ -/* - * Copyright 2023 Google LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "native_posix.overlay" diff --git a/tests/drivers/input/gpio_keys/boards/native_posix.overlay b/tests/drivers/input/gpio_keys/boards/native_sim.overlay similarity index 100% rename from tests/drivers/input/gpio_keys/boards/native_posix.overlay rename to tests/drivers/input/gpio_keys/boards/native_sim.overlay diff --git a/tests/drivers/input/gpio_keys/boards/native_sim_64.overlay b/tests/drivers/input/gpio_keys/boards/native_sim_64.overlay new file mode 100644 index 00000000000..a906fce7488 --- /dev/null +++ b/tests/drivers/input/gpio_keys/boards/native_sim_64.overlay @@ -0,0 +1,6 @@ +/* + * Copyright 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "native_sim.overlay" diff --git a/tests/drivers/input/gpio_keys/prj.conf b/tests/drivers/input/gpio_keys/prj.conf index 0da3a38cadf..5cd6cb6ceb3 100644 --- a/tests/drivers/input/gpio_keys/prj.conf +++ b/tests/drivers/input/gpio_keys/prj.conf @@ -1,7 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_GPIO=y CONFIG_INPUT=y CONFIG_INPUT_MODE_SYNCHRONOUS=y diff --git a/tests/drivers/input/gpio_keys/src/main.c b/tests/drivers/input/gpio_keys/src/main.c index aa86f5f05e3..b5764d7283a 100644 --- a/tests/drivers/input/gpio_keys/src/main.c +++ b/tests/drivers/input/gpio_keys/src/main.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "zephyr/sys/util.h" +#include #include #include #include diff --git a/tests/drivers/input/gpio_keys/testcase.yaml b/tests/drivers/input/gpio_keys/testcase.yaml index b8fd702d96a..be4cb2b17e9 100644 --- a/tests/drivers/input/gpio_keys/testcase.yaml +++ b/tests/drivers/input/gpio_keys/testcase.yaml @@ -6,7 +6,7 @@ tests: - drivers - input platform_allow: - - native_posix - - native_posix_64 + - native_sim + - native_sim_64 integration_platforms: - - native_posix + - native_sim diff --git a/tests/drivers/interrupt_controller/intc_plic/CMakeLists.txt b/tests/drivers/interrupt_controller/intc_plic/CMakeLists.txt new file mode 100644 index 00000000000..59fd0a3bb2f --- /dev/null +++ b/tests/drivers/interrupt_controller/intc_plic/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(intc_plic) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/interrupt_controller/intc_plic/Kconfig b/tests/drivers/interrupt_controller/intc_plic/Kconfig new file mode 100644 index 00000000000..53ccc573482 --- /dev/null +++ b/tests/drivers/interrupt_controller/intc_plic/Kconfig @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +config TEST_INTC_PLIC + bool + default y + help + Declare some intc_plic.c functions in the global scope for verification. + +source "Kconfig" diff --git a/tests/drivers/interrupt_controller/intc_plic/prj.conf b/tests/drivers/interrupt_controller/intc_plic/prj.conf new file mode 100644 index 00000000000..9467c292689 --- /dev/null +++ b/tests/drivers/interrupt_controller/intc_plic/prj.conf @@ -0,0 +1 @@ +CONFIG_ZTEST=y diff --git a/tests/drivers/interrupt_controller/intc_plic/src/main.c b/tests/drivers/interrupt_controller/intc_plic/src/main.c new file mode 100644 index 00000000000..631e0e8915a --- /dev/null +++ b/tests/drivers/interrupt_controller/intc_plic/src/main.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +uint32_t local_irq_to_reg_index(uint32_t local_irq); +uint32_t local_irq_to_reg_offset(uint32_t local_irq); + +ZTEST_SUITE(intc_plic, NULL, NULL, NULL, NULL, NULL); + +/* Test calculating the register index from a local IRQ number */ +ZTEST(intc_plic, test_local_irq_to_reg_index) +{ + zassert_equal(0, local_irq_to_reg_index(0x1f)); + zassert_equal(1, local_irq_to_reg_index(0x20)); + zassert_equal(1, local_irq_to_reg_index(0x3f)); + zassert_equal(2, local_irq_to_reg_index(0x40)); +} + +/* Test calculating the register offset from a local IRQ number */ +ZTEST(intc_plic, test_local_irq_to_reg_offset) +{ + zassert_equal(0, local_irq_to_reg_offset(0x1f)); + zassert_equal(4, local_irq_to_reg_offset(0x20)); + zassert_equal(4, local_irq_to_reg_offset(0x3f)); + zassert_equal(8, local_irq_to_reg_offset(0x40)); +} diff --git a/tests/drivers/interrupt_controller/intc_plic/testcase.yaml b/tests/drivers/interrupt_controller/intc_plic/testcase.yaml new file mode 100644 index 00000000000..11c1f74fa39 --- /dev/null +++ b/tests/drivers/interrupt_controller/intc_plic/testcase.yaml @@ -0,0 +1,7 @@ +tests: + drivers.interrupt_controller.intc_plic: + tags: + - drivers + - interrupt + - plic + platform_allow: qemu_riscv64 diff --git a/tests/drivers/ipm/src/main.c b/tests/drivers/ipm/src/main.c index 95b97b2ce92..bbb97e46580 100644 --- a/tests/drivers/ipm/src/main.c +++ b/tests/drivers/ipm/src/main.c @@ -24,7 +24,8 @@ #define DEST IPM_CONSOLE_STDOUT #endif -#define INIT_PRIO_IPM_SEND 50 +#define INIT_PRIO_IPM_SEND 40 +#define INIT_PRIO_IPM_RECV 50 extern struct ipm_driver_api ipm_dummy_api; @@ -44,7 +45,7 @@ static struct ipm_console_sender_config_info sender_config = { }; DEVICE_DEFINE(ipm_console_send0, "ipm_send0", ipm_console_sender_init, NULL, NULL, &sender_config, - APPLICATION, INIT_PRIO_IPM_SEND, NULL); + POST_KERNEL, INIT_PRIO_IPM_SEND, NULL); /* Receiving side of the console IPM driver. These numbers are * more or less arbitrary @@ -70,7 +71,7 @@ static struct ipm_console_receiver_config_info receiver_config = { struct ipm_console_receiver_runtime_data receiver_data; DEVICE_DEFINE(ipm_console_recv0, "ipm_recv0", ipm_console_receiver_init, NULL, &receiver_data, &receiver_config, - APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, NULL); + POST_KERNEL, INIT_PRIO_IPM_RECV, NULL); static const char thestr[] = "everything is awesome\n"; diff --git a/tests/drivers/kscan/kscan_api/mec15xxevb_assy6853.conf b/tests/drivers/kscan/kscan_api/mec15xxevb_assy6853.conf index c72a6a75259..ded66973827 100644 --- a/tests/drivers/kscan/kscan_api/mec15xxevb_assy6853.conf +++ b/tests/drivers/kscan/kscan_api/mec15xxevb_assy6853.conf @@ -1,3 +1,2 @@ CONFIG_KSCAN=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/kscan/kscan_api/prj.conf b/tests/drivers/kscan/kscan_api/prj.conf index b6f267a8907..f291b8d5b75 100644 --- a/tests/drivers/kscan/kscan_api/prj.conf +++ b/tests/drivers/kscan/kscan_api/prj.conf @@ -1,4 +1,3 @@ CONFIG_KSCAN=y CONFIG_TEST_USERSPACE=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/kscan/kscan_input/prj.conf b/tests/drivers/kscan/kscan_input/prj.conf index 965fbe4cb78..79104173119 100644 --- a/tests/drivers/kscan/kscan_input/prj.conf +++ b/tests/drivers/kscan/kscan_input/prj.conf @@ -1,7 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_KSCAN=y CONFIG_INPUT=y CONFIG_INPUT_MODE_SYNCHRONOUS=y diff --git a/tests/drivers/led/led_api/prj.conf b/tests/drivers/led/led_api/prj.conf index e50218a7c38..acfa3b1fa62 100644 --- a/tests/drivers/led/led_api/prj.conf +++ b/tests/drivers/led/led_api/prj.conf @@ -1,5 +1,4 @@ CONFIG_LED=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y CONFIG_LOG=y diff --git a/tests/drivers/led/led_api/testcase.yaml b/tests/drivers/led/led_api/testcase.yaml index 3af8b79d855..35e3eaca9d4 100644 --- a/tests/drivers/led/led_api/testcase.yaml +++ b/tests/drivers/led/led_api/testcase.yaml @@ -1,5 +1,5 @@ tests: - drivers.led_api.i2c: + drivers.led.api.i2c: tags: - drivers - led diff --git a/tests/drivers/memc/ram/prj.conf b/tests/drivers/memc/ram/prj.conf index f4133ef834e..4aba052c6b4 100644 --- a/tests/drivers/memc/ram/prj.conf +++ b/tests/drivers/memc/ram/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y CONFIG_MEMC=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/mipi_dsi/api/prj.conf b/tests/drivers/mipi_dsi/api/prj.conf index 2d62518bcaf..f27ed3f141b 100644 --- a/tests/drivers/mipi_dsi/api/prj.conf +++ b/tests/drivers/mipi_dsi/api/prj.conf @@ -1,4 +1,3 @@ CONFIG_DISPLAY=y CONFIG_TEST_USERSPACE=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/mm/sys_mm_drv_api/prj.conf b/tests/drivers/mm/sys_mm_drv_api/prj.conf index 7ccdfd1ddf2..06a1545dad7 100644 --- a/tests/drivers/mm/sys_mm_drv_api/prj.conf +++ b/tests/drivers/mm/sys_mm_drv_api/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MM_DRV=y diff --git a/tests/drivers/mm/sys_mm_drv_bank/prj.conf b/tests/drivers/mm/sys_mm_drv_bank/prj.conf index 7ccdfd1ddf2..06a1545dad7 100644 --- a/tests/drivers/mm/sys_mm_drv_bank/prj.conf +++ b/tests/drivers/mm/sys_mm_drv_bank/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MM_DRV=y diff --git a/tests/drivers/mm/sys_mm_drv_bank/src/main.c b/tests/drivers/mm/sys_mm_drv_bank/src/main.c index dfde79302d2..882d57cb1f5 100644 --- a/tests/drivers/mm/sys_mm_drv_bank/src/main.c +++ b/tests/drivers/mm/sys_mm_drv_bank/src/main.c @@ -11,7 +11,7 @@ #define EXPECTED(x) ((x) * CONFIG_MM_DRV_PAGE_SIZE) -static struct mem_drv_bank bank_data = {0x123, 0x234, 0x345}; +static struct sys_mm_drv_bank bank_data = {0x123, 0x234, 0x345}; static void test_stats(const char *error_string, struct sys_memory_stats *stats, diff --git a/tests/drivers/pinctrl/api/prj.conf b/tests/drivers/pinctrl/api/prj.conf index 2068a8582f2..e2f20b2b829 100644 --- a/tests/drivers/pinctrl/api/prj.conf +++ b/tests/drivers/pinctrl/api/prj.conf @@ -2,6 +2,5 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_PINCTRL=y CONFIG_PINCTRL_DYNAMIC=y diff --git a/tests/drivers/pinctrl/api/testcase.yaml b/tests/drivers/pinctrl/api/testcase.yaml index dc23dadafe9..90a6f48a496 100644 --- a/tests/drivers/pinctrl/api/testcase.yaml +++ b/tests/drivers/pinctrl/api/testcase.yaml @@ -1,23 +1,21 @@ # Copyright (c) 2021 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 +common: + platform_allow: + - native_posix + - native_posix_64 + - native_sim + - native_sim_64 + integration_platforms: + - native_sim tests: drivers.pinctrl.api: tags: - drivers - pinctrl - platform_allow: - - native_posix - - native_posix_64 - integration_platforms: - - native_posix drivers.pinctrl.api_reg: tags: - drivers - pinctrl - platform_allow: - - native_posix - - native_posix_64 extra_args: CONF_FILE="prj.conf;reg.conf" - integration_platforms: - - native_posix diff --git a/tests/drivers/pinctrl/gd32/prj.conf b/tests/drivers/pinctrl/gd32/prj.conf index 7bd26f0e73a..bb844ad2efa 100644 --- a/tests/drivers/pinctrl/gd32/prj.conf +++ b/tests/drivers/pinctrl/gd32/prj.conf @@ -2,5 +2,4 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_PINCTRL_TEST_NON_STATIC=y diff --git a/tests/drivers/pinctrl/nrf/prj.conf b/tests/drivers/pinctrl/nrf/prj.conf index 217560e6308..5e341d7d387 100644 --- a/tests/drivers/pinctrl/nrf/prj.conf +++ b/tests/drivers/pinctrl/nrf/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_PINCTRL_TEST_NON_STATIC=y diff --git a/tests/drivers/pwm/pwm_api/boards/esp32c3_luatos_core.overlay b/tests/drivers/pwm/pwm_api/boards/esp32c3_luatos_core.overlay new file mode 100644 index 00000000000..5c0a5285e6e --- /dev/null +++ b/tests/drivers/pwm/pwm_api/boards/esp32c3_luatos_core.overlay @@ -0,0 +1,35 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + */ + +#include +#include + +/ { + aliases { + pwm-0 = &ledc0; + }; +}; + +&pinctrl { + ledc0_default: ledc0_default { + group1 { + pinmux = ; + output-enable; + }; + }; +}; + +&ledc0 { + pinctrl-0 = <&ledc0_default>; + pinctrl-names = "default"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + channel0@0 { + reg = <0x0>; + timer = <0>; + }; +}; diff --git a/tests/drivers/pwm/pwm_api/boards/esp32c3_luatos_core_usb.overlay b/tests/drivers/pwm/pwm_api/boards/esp32c3_luatos_core_usb.overlay new file mode 100644 index 00000000000..5c0a5285e6e --- /dev/null +++ b/tests/drivers/pwm/pwm_api/boards/esp32c3_luatos_core_usb.overlay @@ -0,0 +1,35 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + */ + +#include +#include + +/ { + aliases { + pwm-0 = &ledc0; + }; +}; + +&pinctrl { + ledc0_default: ledc0_default { + group1 { + pinmux = ; + output-enable; + }; + }; +}; + +&ledc0 { + pinctrl-0 = <&ledc0_default>; + pinctrl-names = "default"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + channel0@0 { + reg = <0x0>; + timer = <0>; + }; +}; diff --git a/tests/drivers/pwm/pwm_api/boards/esp32s3_luatos_core.overlay b/tests/drivers/pwm/pwm_api/boards/esp32s3_luatos_core.overlay new file mode 100644 index 00000000000..23fd331d41a --- /dev/null +++ b/tests/drivers/pwm/pwm_api/boards/esp32s3_luatos_core.overlay @@ -0,0 +1,35 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + */ + +#include +#include + +/ { + aliases { + pwm-0 = &ledc0; + }; +}; + +&pinctrl { + ledc0_default: ledc0_default { + group1 { + pinmux = ; + output-enable; + }; + }; +}; + +&ledc0 { + pinctrl-0 = <&ledc0_default>; + pinctrl-names = "default"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + channel0@0 { + reg = <0x0>; + timer = <0>; + }; +}; diff --git a/tests/drivers/pwm/pwm_api/boards/esp32s3_luatos_core_usb.overlay b/tests/drivers/pwm/pwm_api/boards/esp32s3_luatos_core_usb.overlay new file mode 100644 index 00000000000..23fd331d41a --- /dev/null +++ b/tests/drivers/pwm/pwm_api/boards/esp32s3_luatos_core_usb.overlay @@ -0,0 +1,35 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + */ + +#include +#include + +/ { + aliases { + pwm-0 = &ledc0; + }; +}; + +&pinctrl { + ledc0_default: ledc0_default { + group1 { + pinmux = ; + output-enable; + }; + }; +}; + +&ledc0 { + pinctrl-0 = <&ledc0_default>; + pinctrl-names = "default"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + channel0@0 { + reg = <0x0>; + timer = <0>; + }; +}; diff --git a/tests/drivers/pwm/pwm_api/boards/mimxrt1060_evk.overlay b/tests/drivers/pwm/pwm_api/boards/mimxrt1060_evk.overlay new file mode 100644 index 00000000000..ebd3af9f582 --- /dev/null +++ b/tests/drivers/pwm/pwm_api/boards/mimxrt1060_evk.overlay @@ -0,0 +1,18 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Enable PWM outputs on J24 pin 3 and J22 pin 6. These outputs are not used + * by the test, but can be tested using the PWM shell. + */ + +&flexpwm1_pwm3 { + status = "okay"; +}; + +&flexpwm1_pwm0 { + status = "okay"; +}; diff --git a/tests/drivers/pwm/pwm_api/prj.conf b/tests/drivers/pwm/pwm_api/prj.conf index 7375a2bd0b4..21d92de3cb4 100644 --- a/tests/drivers/pwm/pwm_api/prj.conf +++ b/tests/drivers/pwm/pwm_api/prj.conf @@ -1,4 +1,3 @@ CONFIG_PWM=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y diff --git a/tests/drivers/pwm/pwm_api/src/test_pwm.c b/tests/drivers/pwm/pwm_api/src/test_pwm.c index 28b7ea541f2..867025d99b1 100644 --- a/tests/drivers/pwm/pwm_api/src/test_pwm.c +++ b/tests/drivers/pwm/pwm_api/src/test_pwm.c @@ -56,7 +56,7 @@ #if defined(CONFIG_BOARD_COLIBRI_IMX7D_M4) || defined(CONFIG_SOC_MK64F12) || \ defined(CONFIG_SOC_MKW41Z4) || defined(CONFIG_SOC_SERIES_ESP32S2) || \ - defined(CONFIG_SOC_ESP32S3) || defined(CONFIG_SOC_SERIES_ESP32C3) + defined(CONFIG_SOC_SERIES_ESP32S3) || defined(CONFIG_SOC_SERIES_ESP32C3) #define DEFAULT_PERIOD_CYCLE 1024 #define DEFAULT_PULSE_CYCLE 512 #define DEFAULT_PERIOD_NSEC 2000000 diff --git a/tests/drivers/pwm/pwm_loopback/boards/esp32s3_luatos_core.overlay b/tests/drivers/pwm/pwm_loopback/boards/esp32s3_luatos_core.overlay new file mode 100644 index 00000000000..4c9f9e5ff53 --- /dev/null +++ b/tests/drivers/pwm/pwm_loopback/boards/esp32s3_luatos_core.overlay @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + pwm_loopback_0 { + compatible = "test-pwm-loopback"; + /* first index must be a 32-Bit timer */ + pwms = <&mcpwm0 0 0 PWM_POLARITY_NORMAL>, + <&mcpwm0 6 0 PWM_POLARITY_NORMAL>; + }; +}; + +&pinctrl { + mcpwm0_default: mcpwm0_default { + group1 { + pinmux = ; + output-enable; + }; + group2 { + pinmux = ; + }; + }; +}; + +&mcpwm0 { + pinctrl-0 = <&mcpwm0_default>; + pinctrl-names = "default"; + prescale = <255>; + prescale-timer0 = <103>; + status = "okay"; +}; diff --git a/tests/drivers/pwm/pwm_loopback/boards/esp32s3_luatos_core_usb.overlay b/tests/drivers/pwm/pwm_loopback/boards/esp32s3_luatos_core_usb.overlay new file mode 100644 index 00000000000..4c9f9e5ff53 --- /dev/null +++ b/tests/drivers/pwm/pwm_loopback/boards/esp32s3_luatos_core_usb.overlay @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + pwm_loopback_0 { + compatible = "test-pwm-loopback"; + /* first index must be a 32-Bit timer */ + pwms = <&mcpwm0 0 0 PWM_POLARITY_NORMAL>, + <&mcpwm0 6 0 PWM_POLARITY_NORMAL>; + }; +}; + +&pinctrl { + mcpwm0_default: mcpwm0_default { + group1 { + pinmux = ; + output-enable; + }; + group2 { + pinmux = ; + }; + }; +}; + +&mcpwm0 { + pinctrl-0 = <&mcpwm0_default>; + pinctrl-names = "default"; + prescale = <255>; + prescale-timer0 = <103>; + status = "okay"; +}; diff --git a/tests/drivers/pwm/pwm_loopback/boards/mr_canhubk3.overlay b/tests/drivers/pwm/pwm_loopback/boards/mr_canhubk3.overlay new file mode 100644 index 00000000000..898b6d938f7 --- /dev/null +++ b/tests/drivers/pwm/pwm_loopback/boards/mr_canhubk3.overlay @@ -0,0 +1,41 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + pwm_loopback_0 { + compatible = "test-pwm-loopback"; + /* Connect P8A pin 3 and P8A pin 6 */ + pwms = <&emios0_pwm 0 0 PWM_POLARITY_NORMAL>, + <&emios0_pwm 1 0 PWM_POLARITY_NORMAL>; + }; +}; + +&pinctrl { + emios0_default { + group2 { + pinmux = ; + input-enable; + }; + }; +}; + +&emios0 { + emios0_pwm: pwm { + pinctrl-0 = <&emios0_default>; + pinctrl-names = "default"; + status = "okay"; + + pwm_1 { + /delete-property/ period; + /delete-property/ polarity; + /delete-property/ duty-cycle; + prescaler = <16>; + pwm-mode = "SAIC"; + }; + }; +}; diff --git a/tests/drivers/pwm/pwm_loopback/boards/nucleo_h743zi.overlay b/tests/drivers/pwm/pwm_loopback/boards/nucleo_h743zi.overlay index 5007b962ec9..7ebf049ee13 100644 --- a/tests/drivers/pwm/pwm_loopback/boards/nucleo_h743zi.overlay +++ b/tests/drivers/pwm/pwm_loopback/boards/nucleo_h743zi.overlay @@ -31,5 +31,10 @@ status = "okay"; pinctrl-0 = <&tim5_ch1_pa0>; /* CN11 PIN28 */ pinctrl-names = "default"; + + /* At least one of the test devices need to verify + * the four-channel-capture-support in this test. + */ + four-channel-capture-support; }; }; diff --git a/tests/drivers/pwm/pwm_loopback/prj.conf b/tests/drivers/pwm/pwm_loopback/prj.conf index 3d01d55ecb8..73f7ae3cd45 100644 --- a/tests/drivers/pwm/pwm_loopback/prj.conf +++ b/tests/drivers/pwm/pwm_loopback/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y CONFIG_PWM=y diff --git a/tests/drivers/regulator/api/prj.conf b/tests/drivers/regulator/api/prj.conf index cff67c610cd..27ddee1caa1 100644 --- a/tests/drivers/regulator/api/prj.conf +++ b/tests/drivers/regulator/api/prj.conf @@ -2,5 +2,4 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_REGULATOR=y diff --git a/tests/drivers/regulator/api/testcase.yaml b/tests/drivers/regulator/api/testcase.yaml index 95a27f73d64..6aa48cc3aa2 100644 --- a/tests/drivers/regulator/api/testcase.yaml +++ b/tests/drivers/regulator/api/testcase.yaml @@ -1,24 +1,22 @@ # Copyright (c) 2022 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 +common: + platform_allow: + - native_posix + - native_posix_64 + - native_sim + - native_sim_64 + integration_platforms: + - native_sim tests: drivers.regulator.api: tags: - drivers - regulator - platform_allow: - - native_posix - - native_posix_64 - integration_platforms: - - native_posix drivers.regulator.api.nothreadsaferefcnt: tags: - drivers - regulator - platform_allow: - - native_posix - - native_posix_64 - integration_platforms: - - native_posix extra_configs: - CONFIG_REGULATOR_THREAD_SAFE_REFCNT=n diff --git a/tests/drivers/regulator/fixed/prj.conf b/tests/drivers/regulator/fixed/prj.conf index b127d7b5fac..1f835c10be6 100644 --- a/tests/drivers/regulator/fixed/prj.conf +++ b/tests/drivers/regulator/fixed/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_GPIO=y CONFIG_REGULATOR=y diff --git a/tests/drivers/regulator/voltage/boards/lpcxpresso55s36.overlay b/tests/drivers/regulator/voltage/boards/lpcxpresso55s36.overlay new file mode 100644 index 00000000000..a6414a494ca --- /dev/null +++ b/tests/drivers/regulator/voltage/boards/lpcxpresso55s36.overlay @@ -0,0 +1,39 @@ +/* + * Copyright 2023 NXP + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* To do this test, connect AN (J7-1) to VREF_OUT (J12-16) */ + +/ { + resources: resources { + compatible = "test-regulator-voltage"; + regulators = <&vref0>; + tolerance-microvolt = <1000000>; + set-read-delay-ms = <10>; + adc-avg-count = <10>; + io-channels = <&adc0 0>; + }; +}; + +&vref0 { + regulator-initial-mode = ; +}; + +&adc0 { + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_EXTERNAL0"; + zephyr,vref-mv = <1800>; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + zephyr,input-positive = ; + }; +}; diff --git a/tests/drivers/regulator/voltage/prj.conf b/tests/drivers/regulator/voltage/prj.conf index b4cfccb82b3..2a0ced2728d 100644 --- a/tests/drivers/regulator/voltage/prj.conf +++ b/tests/drivers/regulator/voltage/prj.conf @@ -2,6 +2,5 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ADC=y CONFIG_REGULATOR=y diff --git a/tests/drivers/regulator/voltage/src/main.c b/tests/drivers/regulator/voltage/src/main.c index 37db851d237..3978022130c 100644 --- a/tests/drivers/regulator/voltage/src/main.c +++ b/tests/drivers/regulator/voltage/src/main.c @@ -83,7 +83,7 @@ ZTEST(regulator_voltage, test_output_voltage) } for (unsigned int k = 0U; k < adc_avg_count; k++) { - ret = adc_read(adc_chs[i].dev, &sequence); + ret = adc_read_dt(&adc_chs[i], &sequence); zassert_equal(ret, 0); val_mv += buf; diff --git a/tests/drivers/regulator/voltage/testcase.yaml b/tests/drivers/regulator/voltage/testcase.yaml index 71c94e59c82..04b83333079 100644 --- a/tests/drivers/regulator/voltage/testcase.yaml +++ b/tests/drivers/regulator/voltage/testcase.yaml @@ -15,8 +15,12 @@ tests: - SHIELD=npm6001_ek harness_config: fixture: npm6001_ek_to_adc - drivers.regulator.voltage.mimxrt685_evk_cm33: - platform_allow: mimxrt685_evk_cm33 + drivers.regulator.voltage.nxp: + platform_allow: + - mimxrt685_evk_cm33 + - lpcxpresso55s36 + harness_config: + fixture: gpio_loopback drivers.regulator.voltage.rpi_pico_vreg: platform_allow: rpi_pico harness_config: diff --git a/tests/drivers/retained_mem/api/prj.conf b/tests/drivers/retained_mem/api/prj.conf index bc2d8751acb..dced67bae05 100644 --- a/tests/drivers/retained_mem/api/prj.conf +++ b/tests/drivers/retained_mem/api/prj.conf @@ -1,3 +1,2 @@ CONFIG_RETAINED_MEM=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/rtc/rtc_api/prj.conf b/tests/drivers/rtc/rtc_api/prj.conf index 2d8e4c373a8..f03c21df912 100644 --- a/tests/drivers/rtc/rtc_api/prj.conf +++ b/tests/drivers/rtc/rtc_api/prj.conf @@ -3,4 +3,3 @@ CONFIG_RTC=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/rtc/rtc_api/src/test_y2k.c b/tests/drivers/rtc/rtc_api/src/test_y2k.c index 2d7e95aeb1b..d702a2d008b 100644 --- a/tests/drivers/rtc/rtc_api/src/test_y2k.c +++ b/tests/drivers/rtc/rtc_api/src/test_y2k.c @@ -50,8 +50,10 @@ ZTEST(rtc_api, test_y2k) zassert_equal(rtm[Y2K].tm_year + 1900, 2000, "wrong year: %d", rtm[Y2K].tm_year + 1900); zassert_equal(rtm[Y2K].tm_mon, 0, "wrong month: %d", rtm[Y2K].tm_mon); zassert_equal(rtm[Y2K].tm_mday, 1, "wrong day-of-month: %d", rtm[Y2K].tm_mday); - zassert_equal(rtm[Y2K].tm_yday, 0, "wrong day-of-year: %d", rtm[Y2K].tm_yday); - zassert_equal(rtm[Y2K].tm_wday, 6, "wrong day-of-week: %d", rtm[Y2K].tm_wday); + zassert_true(rtm[Y2K].tm_yday == 0 || rtm[Y2K].tm_yday == -1, "wrong day-of-year: %d", + rtm[Y2K].tm_yday); + zassert_true(rtm[Y2K].tm_wday == 6 || rtm[Y2K].tm_wday == -1, "wrong day-of-week: %d", + rtm[Y2K].tm_wday); zassert_equal(rtm[Y2K].tm_hour, 0, "wrong hour: %d", rtm[Y2K].tm_hour); zassert_equal(rtm[Y2K].tm_min, 0, "wrong minute: %d", rtm[Y2K].tm_min); zassert_equal(rtm[Y2K].tm_sec, SECONDS_AFTER, "wrong second: %d", rtm[Y2K].tm_sec); diff --git a/tests/drivers/rtc/rtc_api_helpers/prj.conf b/tests/drivers/rtc/rtc_api_helpers/prj.conf index 2d8e4c373a8..f03c21df912 100644 --- a/tests/drivers/rtc/rtc_api_helpers/prj.conf +++ b/tests/drivers/rtc/rtc_api_helpers/prj.conf @@ -3,4 +3,3 @@ CONFIG_RTC=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/rtc/shell/prj.conf b/tests/drivers/rtc/shell/prj.conf index 095af0ea29d..3629fad7e72 100644 --- a/tests/drivers/rtc/shell/prj.conf +++ b/tests/drivers/rtc/shell/prj.conf @@ -4,5 +4,4 @@ CONFIG_SHELL_BACKEND_DUMMY=y CONFIG_RTC=y CONFIG_RTC_SHELL=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=1536 diff --git a/tests/drivers/sdhc/prj.conf b/tests/drivers/sdhc/prj.conf index 794d5e61d32..3dd36a8597a 100644 --- a/tests/drivers/sdhc/prj.conf +++ b/tests/drivers/sdhc/prj.conf @@ -1,4 +1,3 @@ CONFIG_TEST=y CONFIG_ZTEST=y CONFIG_SDHC=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/sdhc/src/main.c b/tests/drivers/sdhc/src/main.c index 559884499b0..1ee9b7a1ba9 100644 --- a/tests/drivers/sdhc/src/main.c +++ b/tests/drivers/sdhc/src/main.c @@ -15,6 +15,8 @@ static struct sdhc_io io; #define SDHC_FREQUENCY_SLIP 10000000 +K_SEM_DEFINE(card_sem, 0, 1); + /* Resets SD host controller, verifies API */ ZTEST(sdhc, test_reset) { @@ -73,9 +75,22 @@ ZTEST(sdhc, test_set_io) zassert_not_equal(ret, 0, "Invalid io configuration should not succeed"); } +void sdhc_interrupt_cb(const struct device *dev, int source, const void *data) +{ + ARG_UNUSED(data); + + /* Check that the device pointer is correct */ + zassert_equal(dev, sdhc_dev, "Incorrect device pointer in interrupt callback"); + zassert_equal(source, SDHC_INT_INSERTED, "Got unexpected SDHC interrupt"); + k_sem_give(&card_sem); +} + -/* Verify that the driver can detect a present SD card */ -ZTEST(sdhc, test_card_presence) +/* + * Verify that the driver can detect a present SD card + * This test must run first, to ensure the card is present. + */ +ZTEST(sdhc, test_0_card_presence) { int ret; @@ -85,6 +100,19 @@ ZTEST(sdhc, test_card_presence) k_msleep(props.power_delay); ret = sdhc_card_present(sdhc_dev); + if (ret == 0) { + /* Card not in slot, test card insertion interrupt */ + TC_PRINT("Waiting for card to be present in slot\n"); + ret = sdhc_enable_interrupt(sdhc_dev, sdhc_interrupt_cb, + SDHC_INT_INSERTED, NULL); + zassert_equal(ret, 0, "Could not install card insertion interrupt"); + /* Wait for card insertion */ + ret = k_sem_take(&card_sem, K_FOREVER); + /* Delay now that card is in slot */ + k_msleep(props.power_delay); + zassert_equal(ret, 0, "Card insertion interrupt did not fire"); + ret = sdhc_card_present(sdhc_dev); + } zassert_equal(ret, 1, "Card is not reported as present, is one connected?"); } diff --git a/tests/drivers/sensor/accel/boards/native_posix.conf b/tests/drivers/sensor/accel/boards/native_sim.conf similarity index 100% rename from tests/drivers/sensor/accel/boards/native_posix.conf rename to tests/drivers/sensor/accel/boards/native_sim.conf diff --git a/tests/drivers/sensor/accel/boards/native_posix.overlay b/tests/drivers/sensor/accel/boards/native_sim.overlay similarity index 100% rename from tests/drivers/sensor/accel/boards/native_posix.overlay rename to tests/drivers/sensor/accel/boards/native_sim.overlay diff --git a/tests/drivers/sensor/accel/prj.conf b/tests/drivers/sensor/accel/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/drivers/sensor/accel/prj.conf +++ b/tests/drivers/sensor/accel/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/sensor/accel/testcase.yaml b/tests/drivers/sensor/accel/testcase.yaml index becbd1a03f4..fd18df000da 100644 --- a/tests/drivers/sensor/accel/testcase.yaml +++ b/tests/drivers/sensor/accel/testcase.yaml @@ -4,4 +4,5 @@ tests: - drivers - sensor - subsys - platform_allow: native_posix + platform_allow: + - native_sim diff --git a/tests/drivers/sensor/adltc2990/CMakeLists.txt b/tests/drivers/sensor/adltc2990/CMakeLists.txt new file mode 100644 index 00000000000..5ef69b69d50 --- /dev/null +++ b/tests/drivers/sensor/adltc2990/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-FileCopyrightText: Copyright (c) 2023 Carl Zeiss Meditec AG +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(device) + +target_sources(app PRIVATE src/main.c) diff --git a/tests/drivers/sensor/adltc2990/boards/native_sim.overlay b/tests/drivers/sensor/adltc2990/boards/native_sim.overlay new file mode 100644 index 00000000000..a3f7ae3ed7b --- /dev/null +++ b/tests/drivers/sensor/adltc2990/boards/native_sim.overlay @@ -0,0 +1,98 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2023 Carl Zeiss Meditec AG + * SPDX-License-Identifier: Apache-2.0 + */ + +&i2c0 { + adltc2990_0_0: adltc2990_0_0@1 { + compatible = "adi,adltc2990"; + reg = <0x1>; + measurement-mode = <0 0>; + pins-v1-v2-current-resistor = <0>; + pins-v3-v4-current-resistor = <0>; + pin-v1-voltage-divider-resistors = <500 1000>; + pin-v2-voltage-divider-resistors = <110000 100000>; + pin-v3-voltage-divider-resistors = <7000 1000>; + pin-v4-voltage-divider-resistors = <500 1000>; + }; + + adltc2990_1_3: adltc2990_1_3@b { + compatible = "adi,adltc2990"; + reg = <0xb>; + temperature-format = <0>; + acquistion-format = <1>; + measurement-mode = <1 3>; + pins-v1-v2-current-resistor = <1000000>; + pins-v3-v4-current-resistor = <0>; + pin-v1-voltage-divider-resistors = <0 1>; + pin-v2-voltage-divider-resistors = <0 1>; + pin-v3-voltage-divider-resistors = <0 1>; + pin-v4-voltage-divider-resistors = <0 1>; + }; + + adltc2990_4_3: adltc2990_4_3@c { + compatible = "adi,adltc2990"; + reg = <0xc>; + measurement-mode = <4 3>; + pins-v1-v2-current-resistor = <1000000>; + pins-v3-v4-current-resistor = <0>; + pin-v1-voltage-divider-resistors = <0 1>; + pin-v2-voltage-divider-resistors = <0 1>; + pin-v3-voltage-divider-resistors = <0 1>; + pin-v4-voltage-divider-resistors = <0 1>; + }; + + adltc2990_5_3: adltc2990_5_3@d { + compatible = "adi,adltc2990"; + reg = <0xd>; + temperature-format = <1>; + acquistion-format = <1>; + measurement-mode = <5 3>; + pins-v1-v2-current-resistor = <1000000>; + pins-v3-v4-current-resistor = <0>; + pin-v1-voltage-divider-resistors = <0 1>; + pin-v2-voltage-divider-resistors = <0 1>; + pin-v3-voltage-divider-resistors = <0 1>; + pin-v4-voltage-divider-resistors = <0 1>; + }; + + adltc2990_6_3: adltc2990_6_3@e { + compatible = "adi,adltc2990"; + reg = <0xe>; + temperature-format = <1>; + acquistion-format = <1>; + measurement-mode = <6 3>; + pins-v1-v2-current-resistor = <10000>; + pins-v3-v4-current-resistor = <100000>; + pin-v1-voltage-divider-resistors = <500 1000>; + pin-v2-voltage-divider-resistors = <110000 100000>; + pin-v3-voltage-divider-resistors = <7000 1000>; + pin-v4-voltage-divider-resistors = <500 1000>; + }; + + adltc2990_7_3: adltc2990_7_3@f { + compatible = "adi,adltc2990"; + reg = <0xf>; + temperature-format = <1>; + acquistion-format = <1>; + measurement-mode = <7 3>; + pins-v1-v2-current-resistor = <0>; + pins-v3-v4-current-resistor = <0>; + pin-v1-voltage-divider-resistors = <500 1000>; + pin-v2-voltage-divider-resistors = <110000 100000>; + pin-v3-voltage-divider-resistors = <7000 1000>; + pin-v4-voltage-divider-resistors = <500 1000>; + }; + + adltc2990_incorrect: adltc2990_incorrect@0 { + compatible = "adi,adltc2990"; + reg = <0x0>; + measurement-mode = <8 4>; + pins-v1-v2-current-resistor = <0>; + pins-v3-v4-current-resistor = <0>; + pin-v1-voltage-divider-resistors = <500 1000>; + pin-v2-voltage-divider-resistors = <110000 100000>; + pin-v3-voltage-divider-resistors = <7000 1000>; + pin-v4-voltage-divider-resistors = <500 1000>; + }; +}; diff --git a/tests/drivers/sensor/adltc2990/prj.conf b/tests/drivers/sensor/adltc2990/prj.conf new file mode 100644 index 00000000000..5a97fffa465 --- /dev/null +++ b/tests/drivers/sensor/adltc2990/prj.conf @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: Copyright (c) 2023 Carl Zeiss Meditec AG +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_ZTEST=y + +# Set log levels +CONFIG_I2C_LOG_LEVEL_WRN=y +CONFIG_SENSOR_LOG_LEVEL_WRN=y + +# Enable sensors +CONFIG_SENSOR=y + +# Enable emulation +CONFIG_EMUL=y + +# Enable Floating Point +CONFIG_FPU=y diff --git a/tests/drivers/sensor/adltc2990/src/main.c b/tests/drivers/sensor/adltc2990/src/main.c new file mode 100644 index 00000000000..fabeb8ab0dc --- /dev/null +++ b/tests/drivers/sensor/adltc2990/src/main.c @@ -0,0 +1,504 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2023 Carl Zeiss Meditec AG + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include "adltc2990.h" +#include "adltc2990_emul.h" +#include "adltc2990_reg.h" + +/* Colllection of common assertion macros */ +#define CHECK_SINGLE_ENDED_VOLTAGE(sensor_val, index, pin_voltage, r1, r2) \ + zassert_ok(sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_VOLTAGE)); \ + zassert_ok(sensor_channel_get(fixture->dev, SENSOR_CHAN_VOLTAGE, sensor_val)); \ + zassert_between_inclusive( \ + sensor_val[index].val1 + (double)sensor_val[index].val2 / 1000000, \ + (pin_voltage - 0.01f) * ((r1 + r2) / (float)r2), \ + (pin_voltage + 0.01f) * ((r1 + r2) / (float)r2), \ + "%f Out of Range [%f,%f] input %f, [%dmΩ, %dmΩ] " \ + "\nCheck if the sensor node is configured correctly", \ + sensor_val[index].val1 + (double)sensor_val[index].val2 / 1000000, \ + (pin_voltage - 0.01f) * ((r1 + r2) / (float)r2), \ + (pin_voltage + 0.01f) * ((r1 + r2) / (float)r2), pin_voltage, r1, r2); + +#define CHECK_CURRENT(sensor_val, index, pin_voltage, r_microohms) \ + zassert_ok(sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_CURRENT)); \ + zassert_ok(sensor_channel_get(fixture->dev, SENSOR_CHAN_CURRENT, sensor_val)); \ + zassert_between_inclusive( \ + sensor_val[index].val1 + (double)sensor_val[index].val2 / 1000000, \ + (pin_voltage - 0.01f) * ADLTC2990_MICROOHM_CONVERSION_FACTOR / r_microohms, \ + (pin_voltage + 0.01f) * ADLTC2990_MICROOHM_CONVERSION_FACTOR / r_microohms, \ + "%f Out of Range [%f,%f] input %f, current-resistor: %dµΩ\nCheck if the sensor " \ + "node is configured correctly", \ + sensor_val[index].val1 + (double)sensor_val[index].val2 / 1000000, \ + (pin_voltage - 0.001f) * ADLTC2990_MICROOHM_CONVERSION_FACTOR / r_microohms, \ + (pin_voltage + 0.001f) * ADLTC2990_MICROOHM_CONVERSION_FACTOR / r_microohms, \ + pin_voltage, r_microohms); + +#define CHECK_TEMPERATURE(sensor_val, index, expected_temperature, temperature_type) \ + zassert_ok(sensor_sample_fetch_chan(fixture->dev, temperature_type)); \ + zassert_ok(sensor_channel_get(fixture->dev, temperature_type, sensor_val)); \ + zassert_equal(expected_temperature, \ + sensor_val[index].val1 + (float)sensor_val[index].val2 / 1000000, \ + "expected %f, got %f", expected_temperature, \ + sensor_val[index].val1 + (float)sensor_val[index].val2 / 1000000); + +/*** TEST-SUITE: ADLTC2990 Measurement Mode 0 0***/ + +struct adltc2990_0_0_fixture { + const struct device *dev; + const struct emul *target; +}; + +static void *adltc2990_0_0_setup(void) +{ + static struct adltc2990_0_0_fixture fixture = { + .dev = DEVICE_DT_GET(DT_NODELABEL(adltc2990_0_0)), + .target = EMUL_DT_GET(DT_NODELABEL(adltc2990_0_0)), + }; + + zassert_not_null(fixture.dev); + zassert_not_null(fixture.target); + return &fixture; +} + +static void adltc2990_0_0_before(void *f) +{ + struct adltc2990_0_0_fixture *fixture = f; + + adltc2990_emul_reset(fixture->target); +} + +ZTEST_SUITE(adltc2990_0_0, NULL, adltc2990_0_0_setup, adltc2990_0_0_before, NULL, NULL); + +ZTEST_F(adltc2990_0_0, test_measure_mode_internal_temperature_only) +{ + struct sensor_value value[1]; + + zassert_equal(-ENOTSUP, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_MAGN_X)); + zassert_equal(-ENOTSUP, sensor_channel_get(fixture->dev, SENSOR_CHAN_MAGN_Z, value)); + zassert_equal(-EINVAL, sensor_channel_get(fixture->dev, SENSOR_CHAN_CURRENT, value)); + zassert_equal(-EINVAL, sensor_channel_get(fixture->dev, SENSOR_CHAN_AMBIENT_TEMP, value)); +} + +/*** TEST-SUITE: ADLTC2990 Measurement Mode 4 3***/ + +struct adltc2990_4_3_fixture { + const struct device *dev; + const struct emul *target; +}; + +static void *adltc2990_4_3_setup(void) +{ + static struct adltc2990_4_3_fixture fixture = { + .dev = DEVICE_DT_GET(DT_NODELABEL(adltc2990_4_3)), + .target = EMUL_DT_GET(DT_NODELABEL(adltc2990_4_3)), + }; + + zassert_not_null(fixture.dev); + zassert_not_null(fixture.target); + return &fixture; +} + +static void adltc2990_4_3_before(void *f) +{ + struct adltc2990_4_3_fixture *fixture = f; + + adltc2990_emul_reset(fixture->target); +} + +ZTEST_SUITE(adltc2990_4_3, NULL, adltc2990_4_3_setup, adltc2990_4_3_before, NULL, NULL); + +ZTEST_F(adltc2990_4_3, test_available_channels) +{ + struct sensor_value value[3]; + + zassert_equal(0, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_VOLTAGE)); + zassert_equal(0, sensor_channel_get(fixture->dev, SENSOR_CHAN_VOLTAGE, value)); + zassert_equal(0, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_AMBIENT_TEMP)); + zassert_equal(0, sensor_channel_get(fixture->dev, SENSOR_CHAN_AMBIENT_TEMP, value)); + zassert_equal(0, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_CURRENT)); + zassert_equal(0, sensor_channel_get(fixture->dev, SENSOR_CHAN_CURRENT, value)); +} + +/*** TEST-SUITE: ADLTC2990 Measurement Mode 1 3***/ + +struct adltc2990_1_3_fixture { + const struct device *dev; + const struct emul *target; +}; + +static void *adltc2990_1_3_setup(void) +{ + static struct adltc2990_1_3_fixture fixture = { + .dev = DEVICE_DT_GET(DT_NODELABEL(adltc2990_1_3)), + .target = EMUL_DT_GET(DT_NODELABEL(adltc2990_1_3)), + }; + + zassert_not_null(fixture.dev); + zassert_not_null(fixture.target); + return &fixture; +} + +static void adltc2990_1_3_before(void *f) +{ + struct adltc2990_1_3_fixture *fixture = f; + + adltc2990_emul_reset(fixture->target); +} + +ZTEST_SUITE(adltc2990_1_3, NULL, adltc2990_1_3_setup, adltc2990_1_3_before, NULL, NULL); + +ZTEST_F(adltc2990_1_3, test_die_temperature) +{ + /* The following values are taken from datasheet and should translate to 125°c */ + uint8_t msb = 0b00000111, lsb = 0b11010000; + + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_INTERNAL_TEMP_MSB, &msb); + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_INTERNAL_TEMP_LSB, &lsb); + + struct sensor_value temp_value[1]; + + CHECK_TEMPERATURE(temp_value, 0, 125.00, SENSOR_CHAN_DIE_TEMP); + + /*0b00011101 0b10000000 –40.0000*/ + msb = 0b00011101; + lsb = 0b10000000; + + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_INTERNAL_TEMP_MSB, &msb); + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_INTERNAL_TEMP_LSB, &lsb); + + CHECK_TEMPERATURE(temp_value, 0, -40.00, SENSOR_CHAN_DIE_TEMP); +} + +ZTEST_F(adltc2990_1_3, test_ambient_temperature) +{ + /* 0b00000001 0b10010001 +25.0625 */ + uint8_t msb = 0b00000001, lsb = 0b10010001; + struct sensor_value temp_ambient[1]; + + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V3_MSB, &msb); + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V3_LSB, &lsb); + + CHECK_TEMPERATURE(temp_ambient, 0, 25.06250, SENSOR_CHAN_AMBIENT_TEMP); +} + +ZTEST_F(adltc2990_1_3, test_current) +{ + /* 0b00111100 0b01011000 +0.300 */ + uint8_t msb_reg_value = 0b00111100, lsb_reg_value = 0b01011000; + + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V1_MSB, &msb_reg_value); + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V1_LSB, &lsb_reg_value); + + struct sensor_value current_values[1]; + const struct adltc2990_config *dev_config = fixture->target->dev->config; + + CHECK_CURRENT(current_values, 0, 0.3, dev_config->pins_v1_v2.pins_current_resistor); + + /* 0b00100000 0b00000000 +0.159 */ + msb_reg_value = 0b00100000, lsb_reg_value = 0b00000000; + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V1_MSB, &msb_reg_value); + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V1_LSB, &lsb_reg_value); + CHECK_CURRENT(current_values, 0, 0.159, dev_config->pins_v1_v2.pins_current_resistor); +} + +ZTEST_F(adltc2990_1_3, test_V1_MINUS_V2_VCC) +{ + uint8_t msb = 0b01100000, lsb = 0b00000000; + + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V1_MSB, &msb); + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V1_LSB, &lsb); + + msb = 0b00000010; + lsb = 0b10001111; + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_VCC_MSB, &msb); + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_VCC_LSB, &lsb); + + zassert_ok(sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_VOLTAGE)); + + struct sensor_value voltage_values[2]; + + zassert_ok(sensor_channel_get(fixture->dev, SENSOR_CHAN_VOLTAGE, voltage_values)); + + float test_value = voltage_values[0].val1 + (float)voltage_values[0].val2 / 1000000; + + zassert_between_inclusive(test_value, -0.16, -0.159, "Out of Range [-0.16,-0.159]%.6f", + test_value); + + test_value = voltage_values[1].val1 + (double)voltage_values[1].val2 / 1000000; + zassert_between_inclusive(test_value, 2.69, 2.7, "Out of Range [2.69, 2.7]%.6f", + test_value); +} + +/*** TEST-SUITE: ADLTC2990 Measurement Mode 5 3***/ + +struct adltc2990_5_3_fixture { + const struct device *dev; + const struct emul *target; +}; + +static void *adltc2990_5_3_setup(void) +{ + static struct adltc2990_5_3_fixture fixture = { + .dev = DEVICE_DT_GET(DT_NODELABEL(adltc2990_5_3)), + .target = EMUL_DT_GET(DT_NODELABEL(adltc2990_5_3)), + }; + + zassert_not_null(fixture.dev); + zassert_not_null(fixture.target); + return &fixture; +} + +static void adltc2990_5_3_before(void *f) +{ + struct adltc2990_5_3_fixture *fixture = f; + + adltc2990_emul_reset(fixture->target); +} + +ZTEST_SUITE(adltc2990_5_3, NULL, adltc2990_5_3_setup, adltc2990_5_3_before, NULL, NULL); + +ZTEST_F(adltc2990_5_3, test_ambient_temperature) +{ + /*Kelvin 0b00010001 0b00010010 273.1250*/ + uint8_t msb = 0b00010001, lsb = 0b00010010; + + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V1_MSB, &msb); + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V1_LSB, &lsb); + + struct sensor_value temp_value[2]; + + CHECK_TEMPERATURE(temp_value, 0, 273.1250, SENSOR_CHAN_AMBIENT_TEMP); + + /*Kelvin 0b00001110 0b10010010 233.125*/ + msb = 0b00001110; + lsb = 0b10010010; + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V3_MSB, &msb); + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V3_LSB, &lsb); + CHECK_TEMPERATURE(temp_value, 1, 233.1250, SENSOR_CHAN_AMBIENT_TEMP); +} + +ZTEST_F(adltc2990_5_3, test_die_temperature) +{ + /*0b00011000 0b11100010 398.1250*/ + uint8_t msb = 0b00011000, lsb = 0b11100010; + + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_INTERNAL_TEMP_MSB, &msb); + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_INTERNAL_TEMP_LSB, &lsb); + + struct sensor_value temp_value[1]; + + CHECK_TEMPERATURE(temp_value, 0, 398.1250, SENSOR_CHAN_DIE_TEMP); +} + +/*** TEST-SUITE: ADLTC2990 Measurement Mode 7 3***/ + +struct adltc2990_6_3_fixture { + const struct device *dev; + const struct emul *target; +}; + +static void *adltc2990_6_3_setup(void) +{ + static struct adltc2990_6_3_fixture fixture = { + .dev = DEVICE_DT_GET(DT_NODELABEL(adltc2990_6_3)), + .target = EMUL_DT_GET(DT_NODELABEL(adltc2990_6_3)), + }; + + zassert_not_null(fixture.dev); + zassert_not_null(fixture.target); + return &fixture; +} + +static void adltc2990_6_3_before(void *f) +{ + struct adltc2990_6_3_fixture *fixture = f; + + adltc2990_emul_reset(fixture->target); +} + +ZTEST_SUITE(adltc2990_6_3, NULL, adltc2990_6_3_setup, adltc2990_6_3_before, NULL, NULL); + +ZTEST_F(adltc2990_6_3, test_current) +{ + /* 0b00111100 0b01011000 +0.300 */ + uint8_t msb_reg_value = 0b00111100, lsb_reg_value = 0b01011000; + + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V1_MSB, &msb_reg_value); + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V1_LSB, &lsb_reg_value); + + struct sensor_value current_values[2]; + const struct adltc2990_config *dev_config = fixture->target->dev->config; + + CHECK_CURRENT(current_values, 0, 0.3, dev_config->pins_v1_v2.pins_current_resistor); + + /* 0b00100000 0b00000000 +0.159 */ + msb_reg_value = 0b00100000, lsb_reg_value = 0b00000000; + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V3_MSB, &msb_reg_value); + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V3_LSB, &lsb_reg_value); + CHECK_CURRENT(current_values, 1, 0.159, dev_config->pins_v3_v4.pins_current_resistor); +} + +/*** TEST-SUITE: ADLTC2990 Measurement Mode 7 3***/ +struct adltc2990_7_3_fixture { + const struct device *dev; + const struct emul *target; +}; + +static void *adltc2990_7_3_setup(void) +{ + static struct adltc2990_7_3_fixture fixture = { + .dev = DEVICE_DT_GET(DT_NODELABEL(adltc2990_7_3)), + .target = EMUL_DT_GET(DT_NODELABEL(adltc2990_7_3)), + }; + + zassert_not_null(fixture.dev); + zassert_not_null(fixture.target); + return &fixture; +} + +static void adltc2990_7_3_before(void *f) +{ + struct adltc2990_7_3_fixture *fixture = f; + + adltc2990_emul_reset(fixture->target); +} + +ZTEST_SUITE(adltc2990_7_3, NULL, adltc2990_7_3_setup, adltc2990_7_3_before, NULL, NULL); + +ZTEST_F(adltc2990_7_3, test_available_channels) +{ + zassert_equal(-EINVAL, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_AMBIENT_TEMP)); + zassert_equal(-EINVAL, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_CURRENT)); +} + +ZTEST_F(adltc2990_7_3, test_is_device_busy) +{ + uint8_t is_busy = BIT(0); + + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_STATUS, &is_busy); + zassert_equal(-EBUSY, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_ALL)); + is_busy = 0; + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_STATUS, &is_busy); + zassert_equal(0, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_ALL)); +} + +ZTEST_F(adltc2990_7_3, test_die_temperature) +{ + /* The following values are taken from datasheet and should translate to 398.1250K */ + + uint8_t msb = 0b00011000, lsb = 0b11100010; + + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_INTERNAL_TEMP_MSB, &msb); + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_INTERNAL_TEMP_LSB, &lsb); + + struct sensor_value *die_temp_value_null = (struct sensor_value *)NULL; + + zassert_equal(-EINVAL, + sensor_channel_get(fixture->dev, SENSOR_CHAN_ALL, die_temp_value_null)); + + struct sensor_value die_temp_value[1]; + + CHECK_TEMPERATURE(die_temp_value, 0, 398.1250, SENSOR_CHAN_DIE_TEMP); +} + +ZTEST_F(adltc2990_7_3, test_V1_V2_V3_V4_VCC) +{ + /* 0b00111111 0b11111111 >5 */ + uint8_t msb_reg_value = 0b00111111, lsb_reg_value = 0b11111111; + + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V1_MSB, &msb_reg_value); + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V1_LSB, &lsb_reg_value); + + /* 0b00101100 0b11001101 3.500 */ + msb_reg_value = 0b00101100; + lsb_reg_value = 0b11001101; + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V2_MSB, &msb_reg_value); + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V2_LSB, &lsb_reg_value); + + /* 0b00011111 0b11111111 2.500 */ + msb_reg_value = 0b00011111; + lsb_reg_value = 0b11111111; + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V3_MSB, &msb_reg_value); + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V3_LSB, &lsb_reg_value); + + /* 0b01111100 0b00101001 –0.300 */ + msb_reg_value = 0b01111100; + lsb_reg_value = 0b00101001; + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V4_MSB, &msb_reg_value); + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_V4_LSB, &lsb_reg_value); + + /* VCC = 6V */ + msb_reg_value = 0b00101100; + lsb_reg_value = 0b11001101; + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_VCC_MSB, &msb_reg_value); + adltc2990_emul_set_reg(fixture->target, ADLTC2990_REG_VCC_LSB, &lsb_reg_value); + + struct sensor_value voltage_values[5]; + + const struct adltc2990_config *dev_config = fixture->dev->config; + + CHECK_SINGLE_ENDED_VOLTAGE(voltage_values, 0, 5.0, + dev_config->pins_v1_v2.voltage_divider_resistors.v1_r1_r2[0], + dev_config->pins_v1_v2.voltage_divider_resistors.v1_r1_r2[1]); + + CHECK_SINGLE_ENDED_VOLTAGE(voltage_values, 1, 3.5, + dev_config->pins_v1_v2.voltage_divider_resistors.v2_r1_r2[0], + dev_config->pins_v1_v2.voltage_divider_resistors.v2_r1_r2[1]); + + CHECK_SINGLE_ENDED_VOLTAGE(voltage_values, 2, 2.5, + dev_config->pins_v3_v4.voltage_divider_resistors.v3_r1_r2[0], + dev_config->pins_v3_v4.voltage_divider_resistors.v3_r1_r2[1]); + + CHECK_SINGLE_ENDED_VOLTAGE(voltage_values, 3, -0.3, + dev_config->pins_v3_v4.voltage_divider_resistors.v4_r1_r2[0], + dev_config->pins_v3_v4.voltage_divider_resistors.v4_r1_r2[1]); + + float test_value = voltage_values[4].val1 + (double)voltage_values[4].val2 / 1000000; + + zassert_between_inclusive(test_value, 6.0, 6.1, "Out of Range [6.0,6.1] %.6f", test_value); + + zassert_equal(6, voltage_values[4].val1); +} + +/*** TEST-SUITE: ADLTC2990 Measurement Mode Incorrect***/ +struct adltc2990_incorrect_fixture { + const struct device *dev; + const struct emul *target; +}; + +static void *adltc2990_incorrect_setup(void) +{ + static struct adltc2990_incorrect_fixture fixture = { + .dev = DEVICE_DT_GET(DT_NODELABEL(adltc2990_incorrect)), + .target = EMUL_DT_GET(DT_NODELABEL(adltc2990_incorrect)), + }; + + zassert_not_null(fixture.dev); + zassert_not_null(fixture.target); + return &fixture; +} + +static void adltc2990_incorrect_before(void *f) +{ + struct adltc2990_incorrect_fixture *fixture = f; + + adltc2990_emul_reset(fixture->target); +} + +ZTEST_SUITE(adltc2990_incorrect, NULL, adltc2990_incorrect_setup, adltc2990_incorrect_before, NULL, + NULL); + +ZTEST_F(adltc2990_incorrect, test_current_cannot_be_measured) +{ + struct sensor_value current[1]; + + zassert_equal(-EINVAL, sensor_channel_get(fixture->dev, SENSOR_CHAN_CURRENT, current)); +} diff --git a/tests/drivers/sensor/adltc2990/testcase.yaml b/tests/drivers/sensor/adltc2990/testcase.yaml new file mode 100644 index 00000000000..2bf6dcfe5c8 --- /dev/null +++ b/tests/drivers/sensor/adltc2990/testcase.yaml @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: Copyright (c) 2023 Carl Zeiss Meditec AG +# SPDX-License-Identifier: Apache-2.0 + +tests: + drivers.sensor.adltc2990: + tags: + - drivers + - sensor + - subsys + platform_allow: + - native_sim diff --git a/tests/drivers/sensor/akm09918c/boards/native_posix.overlay b/tests/drivers/sensor/akm09918c/boards/native_sim.overlay similarity index 100% rename from tests/drivers/sensor/akm09918c/boards/native_posix.overlay rename to tests/drivers/sensor/akm09918c/boards/native_sim.overlay diff --git a/tests/drivers/sensor/akm09918c/prj.conf b/tests/drivers/sensor/akm09918c/prj.conf index 640be4b7c72..aa2dcfc0b9b 100644 --- a/tests/drivers/sensor/akm09918c/prj.conf +++ b/tests/drivers/sensor/akm09918c/prj.conf @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y # Set log levels CONFIG_I2C_LOG_LEVEL_WRN=y diff --git a/tests/drivers/sensor/akm09918c/testcase.yaml b/tests/drivers/sensor/akm09918c/testcase.yaml index 4ccafdfbec9..bc5167fda4b 100644 --- a/tests/drivers/sensor/akm09918c/testcase.yaml +++ b/tests/drivers/sensor/akm09918c/testcase.yaml @@ -7,4 +7,5 @@ tests: - drivers - sensor - subsys - platform_allow: native_posix + platform_allow: + - native_sim diff --git a/tests/drivers/sensor/generic/prj.conf b/tests/drivers/sensor/generic/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/drivers/sensor/generic/prj.conf +++ b/tests/drivers/sensor/generic/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/sensor/generic/prj_fpu.conf b/tests/drivers/sensor/generic/prj_fpu.conf index 9aa1950dbdb..b93a5675d97 100644 --- a/tests/drivers/sensor/generic/prj_fpu.conf +++ b/tests/drivers/sensor/generic/prj_fpu.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_FPU=y diff --git a/tests/drivers/sensor/generic/src/dummy_sensor.c b/tests/drivers/sensor/generic/src/dummy_sensor.c index b825cea14ac..556ad33c5de 100644 --- a/tests/drivers/sensor/generic/src/dummy_sensor.c +++ b/tests/drivers/sensor/generic/src/dummy_sensor.c @@ -178,9 +178,9 @@ static const struct sensor_driver_api dummy_sensor_no_trig_api = { }; DEVICE_DEFINE(dummy_sensor, DUMMY_SENSOR_NAME, &dummy_sensor_init, - NULL, &dummy_data, &dummy_config, APPLICATION, + NULL, &dummy_data, &dummy_config, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &dummy_sensor_api); DEVICE_DEFINE(dummy_sensor_no_trig, DUMMY_SENSOR_NAME_NO_TRIG, &dummy_sensor_init, - NULL, &dummy_data, &dummy_config, APPLICATION, + NULL, &dummy_data, &dummy_config, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &dummy_sensor_no_trig_api); diff --git a/tests/drivers/sensor/icm42688/boards/native_posix.overlay b/tests/drivers/sensor/icm42688/boards/native_sim.overlay similarity index 100% rename from tests/drivers/sensor/icm42688/boards/native_posix.overlay rename to tests/drivers/sensor/icm42688/boards/native_sim.overlay diff --git a/tests/drivers/sensor/icm42688/prj.conf b/tests/drivers/sensor/icm42688/prj.conf index 39b8b60e462..61addc37590 100644 --- a/tests/drivers/sensor/icm42688/prj.conf +++ b/tests/drivers/sensor/icm42688/prj.conf @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y # Enable GPIO CONFIG_GPIO=y diff --git a/tests/drivers/sensor/icm42688/testcase.yaml b/tests/drivers/sensor/icm42688/testcase.yaml index f8f5929078c..6f886cb6191 100644 --- a/tests/drivers/sensor/icm42688/testcase.yaml +++ b/tests/drivers/sensor/icm42688/testcase.yaml @@ -7,4 +7,5 @@ tests: - drivers - sensor - subsys - platform_allow: native_posix + platform_allow: + - native_sim diff --git a/tests/drivers/sensor/ina230/boards/native_posix.overlay b/tests/drivers/sensor/ina230/boards/native_sim.overlay similarity index 100% rename from tests/drivers/sensor/ina230/boards/native_posix.overlay rename to tests/drivers/sensor/ina230/boards/native_sim.overlay diff --git a/tests/drivers/sensor/ina230/prj.conf b/tests/drivers/sensor/ina230/prj.conf index b3d184bfa78..6ad5ef41b56 100644 --- a/tests/drivers/sensor/ina230/prj.conf +++ b/tests/drivers/sensor/ina230/prj.conf @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SENSOR=y CONFIG_EMUL=y diff --git a/tests/drivers/sensor/ina230/testcase.yaml b/tests/drivers/sensor/ina230/testcase.yaml index a0f962e4a6c..9ead4ab22b1 100644 --- a/tests/drivers/sensor/ina230/testcase.yaml +++ b/tests/drivers/sensor/ina230/testcase.yaml @@ -7,4 +7,5 @@ tests: - drivers - sensor - subsys - platform_allow: native_posix + platform_allow: + - native_sim diff --git a/tests/drivers/sensor/ina237/boards/native_posix.overlay b/tests/drivers/sensor/ina237/boards/native_sim.overlay similarity index 100% rename from tests/drivers/sensor/ina237/boards/native_posix.overlay rename to tests/drivers/sensor/ina237/boards/native_sim.overlay diff --git a/tests/drivers/sensor/ina237/prj.conf b/tests/drivers/sensor/ina237/prj.conf index 3c7471b31b9..4e594c68f66 100644 --- a/tests/drivers/sensor/ina237/prj.conf +++ b/tests/drivers/sensor/ina237/prj.conf @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SENSOR=y CONFIG_EMUL=y diff --git a/tests/drivers/sensor/ina237/testcase.yaml b/tests/drivers/sensor/ina237/testcase.yaml index afad2c5726c..3c9f97d7604 100644 --- a/tests/drivers/sensor/ina237/testcase.yaml +++ b/tests/drivers/sensor/ina237/testcase.yaml @@ -7,4 +7,5 @@ tests: - drivers - sensor - subsys - platform_allow: native_posix + platform_allow: + - native_sim diff --git a/tests/drivers/sensor/sbs_gauge/boards/native_posix.overlay b/tests/drivers/sensor/sbs_gauge/boards/native_sim.overlay similarity index 100% rename from tests/drivers/sensor/sbs_gauge/boards/native_posix.overlay rename to tests/drivers/sensor/sbs_gauge/boards/native_sim.overlay diff --git a/tests/drivers/sensor/sbs_gauge/prj.conf b/tests/drivers/sensor/sbs_gauge/prj.conf index 58b778780af..7185ba608b4 100644 --- a/tests/drivers/sensor/sbs_gauge/prj.conf +++ b/tests/drivers/sensor/sbs_gauge/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SENSOR=y CONFIG_I2C=y CONFIG_TEST_USERSPACE=y diff --git a/tests/drivers/sensor/sbs_gauge/testcase.yaml b/tests/drivers/sensor/sbs_gauge/testcase.yaml index 9be31c476a9..e585ed6f807 100644 --- a/tests/drivers/sensor/sbs_gauge/testcase.yaml +++ b/tests/drivers/sensor/sbs_gauge/testcase.yaml @@ -1,6 +1,6 @@ tests: # section.subsection - drivers.sensors.sbs_gauge: + drivers.sensor.sbs_gauge: build_only: true tags: - drivers @@ -9,16 +9,16 @@ tests: dt_compat_enabled("sbs,sbs-gauge") and not dt_compat_enabled("zephyr,i2c-emul-controller") integration_platforms: - nucleo_f070rb - drivers.sensors.sbs_gauge.emulated: + drivers.sensor.sbs_gauge.emulated: tags: - drivers - sensors filter: dt_compat_enabled("sbs,sbs-gauge") platform_allow: - - native_posix + - native_sim - qemu_cortex_a9 - qemu_arc_hs integration_platforms: - - native_posix + - native_sim extra_configs: - CONFIG_EMUL=y diff --git a/tests/drivers/smbus/smbus_api/prj.conf b/tests/drivers/smbus/smbus_api/prj.conf index 5dc81c75693..92a1cb2ef95 100644 --- a/tests/drivers/smbus/smbus_api/prj.conf +++ b/tests/drivers/smbus/smbus_api/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SMBUS=y CONFIG_SMBUS_INTEL_PCH=y diff --git a/tests/drivers/smbus/smbus_api/src/test_smbus.c b/tests/drivers/smbus/smbus_api/src/test_smbus.c index 5642bd664a6..5d1dd9ca49a 100644 --- a/tests/drivers/smbus/smbus_api/src/test_smbus.c +++ b/tests/drivers/smbus/smbus_api/src/test_smbus.c @@ -45,7 +45,7 @@ ZTEST_USER(test_smbus_general, test_smbus_basic_api) * The test is run in userspace only if CONFIG_USERSPACE option is * enabled, otherwise it is the same as ZTEST() */ -ZTEST_USER(test_smbus_general, test_smbus_smbalert_api) +ZTEST(test_smbus_general, test_smbus_smbalert_api) { const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(smbus0)); void *dummy; /* For the dummy function pointer use this */ @@ -90,7 +90,7 @@ ZTEST_USER(test_smbus_general, test_smbus_smbalert_api) * The test is run in userspace only if CONFIG_USERSPACE option is * enabled, otherwise it is the same as ZTEST() */ -ZTEST_USER(test_smbus_general, test_smbus_host_notify_api) +ZTEST(test_smbus_general, test_smbus_host_notify_api) { const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(smbus0)); void *dummy; /* For the dummy function pointer use this */ diff --git a/tests/drivers/smbus/smbus_emul/prj.conf b/tests/drivers/smbus/smbus_emul/prj.conf index 9dd20e84904..996a530cd41 100644 --- a/tests/drivers/smbus/smbus_emul/prj.conf +++ b/tests/drivers/smbus/smbus_emul/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y CONFIG_LOG=y -CONFIG_ZTEST_NEW_API=y CONFIG_ENTROPY_GENERATOR=y diff --git a/tests/drivers/smbus/smbus_emul/src/smbus.c b/tests/drivers/smbus/smbus_emul/src/smbus.c index 8157fa1aef4..1d2a3b5200e 100644 --- a/tests/drivers/smbus/smbus_emul/src/smbus.c +++ b/tests/drivers/smbus/smbus_emul/src/smbus.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include @@ -101,7 +101,7 @@ static struct pch_config pch_config_data = { }; DEVICE_DEFINE(dummy_driver, SMBUS_EMUL, &pch_smbus_init, - NULL, &smbus_data, &pch_config_data, APPLICATION, + NULL, &smbus_data, &pch_config_data, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &funcs); ZTEST(test_smbus_emul, test_byte) diff --git a/tests/drivers/spi/dt_spec/prj.conf b/tests/drivers/spi/dt_spec/prj.conf index 34d372396ca..e86373a9930 100644 --- a/tests/drivers/spi/dt_spec/prj.conf +++ b/tests/drivers/spi/dt_spec/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SPI=y CONFIG_GPIO=y diff --git a/tests/drivers/spi/spi_loopback/Kconfig b/tests/drivers/spi/spi_loopback/Kconfig index 5f1033ea470..8c26b723092 100644 --- a/tests/drivers/spi/spi_loopback/Kconfig +++ b/tests/drivers/spi/spi_loopback/Kconfig @@ -6,3 +6,20 @@ source "Kconfig.zephyr" config SPI_LOOPBACK_MODE_LOOP bool "Configure the SPI in LOOP mode, so that no extra wiring is needed" + +if SOC_SERIES_STM32H7X + +config SPI_LOOPBACK_16BITS_FRAMES + bool "Use 16 bits frames for tests" + +config DT_DEFINED_NOCACHE + bool "Enable this if nocache regions are defined in devicetree" + +if DT_DEFINED_NOCACHE + +config DT_DEFINED_NOCACHE_NAME + string "Name of the nocache region defined in devicetree (capitals)" + +endif # DT_DEFINED_NOCACHE + +endif # SOC_SERIES_STM32H7X diff --git a/tests/drivers/spi/spi_loopback/boards/cy8cproto_062_4343w.overlay b/tests/drivers/spi/spi_loopback/boards/cy8cproto_062_4343w.overlay new file mode 100644 index 00000000000..893e8416631 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/cy8cproto_062_4343w.overlay @@ -0,0 +1,41 @@ +spi1: &scb3 { + compatible = "infineon,cat1-spi"; + status = "okay"; + + pinctrl-0 = <&p6_0_scb3_spi_m_mosi &p6_1_scb3_spi_m_miso &p6_2_scb3_spi_m_clk>; + pinctrl-names = "default"; + cs-gpios = <&gpio_prt6 3 GPIO_ACTIVE_LOW>; + + slow@0 { + compatible = "test-spi-loopback-slow"; + reg = <0>; + spi-max-frequency = <2000000>; + }; + fast@0 { + compatible = "test-spi-loopback-fast"; + reg = <0>; + spi-max-frequency = <3000000>; + }; +}; + +&gpio_prt6 { + status = "okay"; +}; + +&pinctrl { + /* Configure pin control bias mode for SPI pins */ + p6_0_scb3_spi_m_mosi: p6_0_scb3_spi_m_mosi { + pinmux = ; + drive-push-pull; + }; + + p6_1_scb3_spi_m_miso: p6_1_scb3_spi_m_miso { + pinmux = ; + input-enable; + }; + + p6_2_scb3_spi_m_clk: p6_2_scb3_spi_m_clk { + pinmux = ; + drive-push-pull; + }; +}; diff --git a/tests/drivers/spi/spi_loopback/boards/cy8cproto_063_ble.overlay b/tests/drivers/spi/spi_loopback/boards/cy8cproto_063_ble.overlay new file mode 100644 index 00000000000..e6ddcc3ef2e --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/cy8cproto_063_ble.overlay @@ -0,0 +1,42 @@ +&pinctrl { + /* Configure pin control bias mode for SPI pins (MASTER) */ + p10_0_scb1_spi_m_mosi: p10_0_scb1_spi_m_mosi { + pinmux = ; + drive-push-pull; + }; + + p10_1_scb1_spi_m_miso: p10_1_scb1_spi_m_miso { + pinmux = ; + input-enable; + }; + + p10_2_scb1_spi_m_clk: p10_2_scb1_spi_m_clk { + pinmux = ; + drive-push-pull; + }; +}; + +spi: &scb1 { + compatible = "infineon,cat1-spi"; + status = "okay"; + + pinctrl-0 = <&p10_0_scb1_spi_m_mosi &p10_1_scb1_spi_m_miso &p10_2_scb1_spi_m_clk>; + pinctrl-names = "default"; + cs-gpios = <&gpio_prt10 3 GPIO_ACTIVE_LOW>; + + slow@0 { + compatible = "test-spi-loopback-slow"; + reg = <0>; + spi-max-frequency = <200000>; + }; + + fast@0 { + compatible = "test-spi-loopback-fast"; + reg = <0>; + spi-max-frequency = <1500000>; + }; +}; + +&gpio_prt10 { + status = "okay"; +}; diff --git a/tests/drivers/spi/spi_loopback/boards/esp32c3_luatos_core.conf b/tests/drivers/spi/spi_loopback/boards/esp32c3_luatos_core.conf new file mode 100644 index 00000000000..3438f794f66 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/esp32c3_luatos_core.conf @@ -0,0 +1,2 @@ +CONFIG_SPI_ESP32_INTERRUPT=y +CONFIG_HEAP_MEM_POOL_SIZE=32768 diff --git a/tests/drivers/spi/spi_loopback/boards/esp32c3_luatos_core.overlay b/tests/drivers/spi/spi_loopback/boards/esp32c3_luatos_core.overlay new file mode 100644 index 00000000000..8e5037e7691 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/esp32c3_luatos_core.overlay @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 Kumar Gala + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + spim2_loopback: spim2_loopback { + group1 { + pinmux = ; + output-enable; /* Enable internal loopback */ + }; + group2 { + pinmux = ; + input-enable; /* Enable internal loopback */ + }; + group3 { + pinmux = , + ; + }; + }; +}; + +&spi2 { + slow@0 { + compatible = "test-spi-loopback-slow"; + reg = <0>; + spi-max-frequency = <500000>; + }; + fast@0 { + compatible = "test-spi-loopback-fast"; + reg = <0>; + spi-max-frequency = <16000000>; + }; +}; + +&spi2 { + dma-enabled; + pinctrl-0 = <&spim2_loopback>; +}; diff --git a/tests/drivers/spi/spi_loopback/boards/esp32c3_luatos_core_usb.conf b/tests/drivers/spi/spi_loopback/boards/esp32c3_luatos_core_usb.conf new file mode 100644 index 00000000000..3438f794f66 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/esp32c3_luatos_core_usb.conf @@ -0,0 +1,2 @@ +CONFIG_SPI_ESP32_INTERRUPT=y +CONFIG_HEAP_MEM_POOL_SIZE=32768 diff --git a/tests/drivers/spi/spi_loopback/boards/esp32c3_luatos_core_usb.overlay b/tests/drivers/spi/spi_loopback/boards/esp32c3_luatos_core_usb.overlay new file mode 100644 index 00000000000..8e5037e7691 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/esp32c3_luatos_core_usb.overlay @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 Kumar Gala + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + spim2_loopback: spim2_loopback { + group1 { + pinmux = ; + output-enable; /* Enable internal loopback */ + }; + group2 { + pinmux = ; + input-enable; /* Enable internal loopback */ + }; + group3 { + pinmux = , + ; + }; + }; +}; + +&spi2 { + slow@0 { + compatible = "test-spi-loopback-slow"; + reg = <0>; + spi-max-frequency = <500000>; + }; + fast@0 { + compatible = "test-spi-loopback-fast"; + reg = <0>; + spi-max-frequency = <16000000>; + }; +}; + +&spi2 { + dma-enabled; + pinctrl-0 = <&spim2_loopback>; +}; diff --git a/tests/drivers/spi/spi_loopback/boards/esp32s3_luatos_core.conf b/tests/drivers/spi/spi_loopback/boards/esp32s3_luatos_core.conf new file mode 100644 index 00000000000..fb0909611c8 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/esp32s3_luatos_core.conf @@ -0,0 +1 @@ +CONFIG_SPI_ESP32_INTERRUPT=y diff --git a/tests/drivers/spi/spi_loopback/boards/esp32s3_luatos_core.overlay b/tests/drivers/spi/spi_loopback/boards/esp32s3_luatos_core.overlay new file mode 100644 index 00000000000..ce9c8e7891b --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/esp32s3_luatos_core.overlay @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 Kumar Gala + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + spim3_loopback: spim3_loopback { + group1 { + pinmux = ; + output-enable; /* Enable internal loopback */ + }; + group2 { + pinmux = ; + input-enable; /* Enable internal loopback */ + }; + group3 { + pinmux = , + ; + }; + }; +}; + +&spi3 { + slow@0 { + compatible = "test-spi-loopback-slow"; + reg = <0>; + spi-max-frequency = <100000>; + }; + fast@0 { + compatible = "test-spi-loopback-fast"; + reg = <0>; + spi-max-frequency = <16000000>; + }; +}; + +&spi3 { + dma-enabled; + pinctrl-0 = <&spim3_loopback>; +}; diff --git a/tests/drivers/spi/spi_loopback/boards/esp32s3_luatos_core_usb.conf b/tests/drivers/spi/spi_loopback/boards/esp32s3_luatos_core_usb.conf new file mode 100644 index 00000000000..fb0909611c8 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/esp32s3_luatos_core_usb.conf @@ -0,0 +1 @@ +CONFIG_SPI_ESP32_INTERRUPT=y diff --git a/tests/drivers/spi/spi_loopback/boards/esp32s3_luatos_core_usb.overlay b/tests/drivers/spi/spi_loopback/boards/esp32s3_luatos_core_usb.overlay new file mode 100644 index 00000000000..ce9c8e7891b --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/esp32s3_luatos_core_usb.overlay @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 Kumar Gala + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + spim3_loopback: spim3_loopback { + group1 { + pinmux = ; + output-enable; /* Enable internal loopback */ + }; + group2 { + pinmux = ; + input-enable; /* Enable internal loopback */ + }; + group3 { + pinmux = , + ; + }; + }; +}; + +&spi3 { + slow@0 { + compatible = "test-spi-loopback-slow"; + reg = <0>; + spi-max-frequency = <100000>; + }; + fast@0 { + compatible = "test-spi-loopback-fast"; + reg = <0>; + spi-max-frequency = <16000000>; + }; +}; + +&spi3 { + dma-enabled; + pinctrl-0 = <&spim3_loopback>; +}; diff --git a/tests/drivers/spi/spi_loopback/boards/mimxrt1170_evk_cm7.conf b/tests/drivers/spi/spi_loopback/boards/mimxrt1170_evk_cm7.conf new file mode 100644 index 00000000000..1ce2ad49200 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/mimxrt1170_evk_cm7.conf @@ -0,0 +1,6 @@ +# +# Copyright 2023 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_SPI_MCUX_LPSPI_DMA=y diff --git a/tests/drivers/spi/spi_loopback/boards/mimxrt1170_evk_cm7.overlay b/tests/drivers/spi/spi_loopback/boards/mimxrt1170_evk_cm7.overlay new file mode 100644 index 00000000000..fa2b906bbd7 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/mimxrt1170_evk_cm7.overlay @@ -0,0 +1,18 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&lpspi1 { + slow@0 { + compatible = "test-spi-loopback-slow"; + reg = <0>; + spi-max-frequency = <500000>; + }; + fast@0 { + compatible = "test-spi-loopback-fast"; + reg = <0>; + spi-max-frequency = <16000000>; + }; +}; diff --git a/tests/drivers/spi/spi_loopback/boards/mr_canhubk3.conf b/tests/drivers/spi/spi_loopback/boards/mr_canhubk3.conf new file mode 100644 index 00000000000..f199db4f3be --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/mr_canhubk3.conf @@ -0,0 +1,5 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SPI_MCUX_LPSPI_DMA=y +CONFIG_SPI_ASYNC=n diff --git a/tests/drivers/spi/spi_loopback/boards/mr_canhubk3.overlay b/tests/drivers/spi/spi_loopback/boards/mr_canhubk3.overlay index 928f05a9929..9d12ceef80e 100644 --- a/tests/drivers/spi/spi_loopback/boards/mr_canhubk3.overlay +++ b/tests/drivers/spi/spi_loopback/boards/mr_canhubk3.overlay @@ -6,6 +6,9 @@ &lpspi1 { status = "okay"; + /* DMA channels 10 and 12, muxed to LPSPI1 TX and RX */ + dmas = <&edma0 10 45>, <&edma0 12 46>; + dma-names = "tx", "rx"; slow@0 { compatible = "test-spi-loopback-slow"; diff --git a/tests/drivers/spi/spi_loopback/boards/nucleo_h743zi.overlay b/tests/drivers/spi/spi_loopback/boards/nucleo_h743zi.overlay index 7e3b9a2d6c2..0b6e78046f5 100644 --- a/tests/drivers/spi/spi_loopback/boards/nucleo_h743zi.overlay +++ b/tests/drivers/spi/spi_loopback/boards/nucleo_h743zi.overlay @@ -4,6 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + +&sram2 { + zephyr,memory-attr = < DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) >; +}; + &spi1 { dmas = <&dmamux1 0 38 (STM32_DMA_PERIPH_TX | STM32_DMA_PRIORITY_HIGH) &dmamux1 1 37 (STM32_DMA_PERIPH_RX | STM32_DMA_PRIORITY_HIGH)>; diff --git a/tests/drivers/spi/spi_loopback/boards/nucleo_h753zi.overlay b/tests/drivers/spi/spi_loopback/boards/nucleo_h753zi.overlay index 5fc1ba71d53..e9aa1127ab7 100644 --- a/tests/drivers/spi/spi_loopback/boards/nucleo_h753zi.overlay +++ b/tests/drivers/spi/spi_loopback/boards/nucleo_h753zi.overlay @@ -4,6 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + +&sram2 { + zephyr,memory-attr = < DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) >; +}; + &spi1 { dmas = <&dmamux1 0 38 (STM32_DMA_PERIPH_TX | STM32_DMA_PRIORITY_HIGH) &dmamux1 1 37 (STM32_DMA_PERIPH_RX | STM32_DMA_PRIORITY_HIGH)>; diff --git a/tests/drivers/spi/spi_loopback/boards/xmc45_relax_kit.conf b/tests/drivers/spi/spi_loopback/boards/xmc45_relax_kit.conf index d066213b5da..3f96b399e0e 100644 --- a/tests/drivers/spi/spi_loopback/boards/xmc45_relax_kit.conf +++ b/tests/drivers/spi/spi_loopback/boards/xmc45_relax_kit.conf @@ -1,3 +1,2 @@ -CONFIG_SPI_XMC4XXX_INTERRUPT=y CONFIG_SPI_XMC4XXX_DMA=y CONFIG_SPI_LOOPBACK_MODE_LOOP=y diff --git a/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits-dma-no-nocache.conf b/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits-dma-no-nocache.conf new file mode 100644 index 00000000000..4bb96e35f58 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits-dma-no-nocache.conf @@ -0,0 +1,14 @@ +# +# Copyright (c) 2023 Graphcore Ltd, All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# + +# enable DMA mode for SPI loopback test +CONFIG_SPI_STM32_DMA=y +CONFIG_SPI_STM32_INTERRUPT=n +CONFIG_SPI_ASYNC=n +CONFIG_NOCACHE_MEMORY=n +CONFIG_DT_DEFINED_NOCACHE=y +CONFIG_DT_DEFINED_NOCACHE_NAME="SRAM2" +CONFIG_SPI_LOOPBACK_16BITS_FRAMES=y diff --git a/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits-dma.conf b/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits-dma.conf new file mode 100644 index 00000000000..c49efea868a --- /dev/null +++ b/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits-dma.conf @@ -0,0 +1,11 @@ +# +# Copyright (c) 2023 Graphcore Ltd, All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# + +# enable DMA mode for SPI loopback test +CONFIG_SPI_STM32_DMA=y +CONFIG_SPI_STM32_INTERRUPT=n +CONFIG_SPI_ASYNC=n +CONFIG_SPI_LOOPBACK_16BITS_FRAMES=y diff --git a/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits.conf b/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits.conf new file mode 100644 index 00000000000..00ca04782b4 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits.conf @@ -0,0 +1,6 @@ +# +# Copyright (c) 2023 Graphcore Ltd, All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_SPI_LOOPBACK_16BITS_FRAMES=y diff --git a/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits.overlay b/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits.overlay new file mode 100644 index 00000000000..ee0ad036da6 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits.overlay @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Graphcore Ltd, All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&sram2 { + zephyr,memory-attr = < DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) >; +}; + +&spi1 { + dmas = <&dmamux1 0 38 (STM32_DMA_PERIPH_TX | STM32_DMA_PRIORITY_HIGH | STM32_DMA_MEM_16BITS | STM32_DMA_PERIPH_16BITS) + &dmamux1 1 37 (STM32_DMA_PERIPH_RX | STM32_DMA_PRIORITY_HIGH | STM32_DMA_MEM_16BITS | STM32_DMA_PERIPH_16BITS)>; + dma-names = "tx", "rx"; + slow@0 { + compatible = "test-spi-loopback-slow"; + reg = <0>; + spi-max-frequency = <500000>; + }; + fast@0 { + compatible = "test-spi-loopback-fast"; + reg = <0>; + spi-max-frequency = <16000000>; + }; +}; + +&dma1 { + status = "okay"; +}; + +&dma2 { + status = "okay"; +}; + +&dmamux1 { + status = "okay"; +}; diff --git a/tests/drivers/spi/spi_loopback/overlay-stm32-spi-dma-no-nocache.conf b/tests/drivers/spi/spi_loopback/overlay-stm32-spi-dma-no-nocache.conf new file mode 100644 index 00000000000..12eeb52c3b2 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/overlay-stm32-spi-dma-no-nocache.conf @@ -0,0 +1,7 @@ +# enable DMA mode for SPI loopback test +CONFIG_SPI_STM32_DMA=y +CONFIG_SPI_STM32_INTERRUPT=n +CONFIG_SPI_ASYNC=n +CONFIG_NOCACHE_MEMORY=n +CONFIG_DT_DEFINED_NOCACHE=y +CONFIG_DT_DEFINED_NOCACHE_NAME="SRAM2" diff --git a/tests/drivers/spi/spi_loopback/overlay-stm32-spi-interrupt.conf b/tests/drivers/spi/spi_loopback/overlay-stm32-spi-interrupt.conf new file mode 100644 index 00000000000..f678c776824 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/overlay-stm32-spi-interrupt.conf @@ -0,0 +1,7 @@ +# +# Copyright (c) 2023 Graphcore Ltd, All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_SPI_STM32_INTERRUPT=y diff --git a/tests/drivers/spi/spi_loopback/prj.conf b/tests/drivers/spi/spi_loopback/prj.conf index 2f981c600ec..f0e641f7623 100644 --- a/tests/drivers/spi/spi_loopback/prj.conf +++ b/tests/drivers/spi/spi_loopback/prj.conf @@ -4,4 +4,3 @@ CONFIG_SPI=y CONFIG_SPI_ASYNC=y CONFIG_SPI_LOG_LEVEL_INF=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/spi/spi_loopback/src/spi.c b/tests/drivers/spi/spi_loopback/src/spi.c index 62896fbcecf..e272cf23567 100644 --- a/tests/drivers/spi/spi_loopback/src/spi.c +++ b/tests/drivers/spi/spi_loopback/src/spi.c @@ -12,6 +12,7 @@ LOG_MODULE_REGISTER(spi_loopback); #include #include #include +#include #include #include @@ -25,34 +26,53 @@ LOG_MODULE_REGISTER(spi_loopback); #define MODE_LOOP 0 #endif -#define SPI_OP SPI_OP_MODE_MASTER | SPI_MODE_CPOL | MODE_LOOP | \ - SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_LINES_SINGLE +#ifdef CONFIG_SPI_LOOPBACK_16BITS_FRAMES +#define FRAME_SIZE (16) +#define FRAME_SIZE_STR ", frame size = 16" +#else +#define FRAME_SIZE (8) +#define FRAME_SIZE_STR ", frame size = 8" +#endif /* CONFIG_SPI_LOOPBACK_16BITS_FRAMES */ + +#ifdef CONFIG_DMA + +#ifdef CONFIG_NOCACHE_MEMORY +#define DMA_ENABLED_STR ", DMA enabled" +#else /* CONFIG_NOCACHE_MEMORY */ +#define DMA_ENABLED_STR ", DMA enabled (without CONFIG_NOCACHE_MEMORY)" +#endif + +#else /* CONFIG_DMA */ + +#define DMA_ENABLED_STR +#endif /* CONFIG_DMA */ +#define SPI_OP(frame_size) SPI_OP_MODE_MASTER | SPI_MODE_CPOL | MODE_LOOP | \ + SPI_MODE_CPHA | SPI_WORD_SET(frame_size) | SPI_LINES_SINGLE -static struct spi_dt_spec spi_fast = SPI_DT_SPEC_GET(SPI_FAST_DEV, SPI_OP, 0); -static struct spi_dt_spec spi_slow = SPI_DT_SPEC_GET(SPI_SLOW_DEV, SPI_OP, 0); +static struct spi_dt_spec spi_fast = SPI_DT_SPEC_GET(SPI_FAST_DEV, SPI_OP(FRAME_SIZE), 0); +static struct spi_dt_spec spi_slow = SPI_DT_SPEC_GET(SPI_SLOW_DEV, SPI_OP(FRAME_SIZE), 0); /* to run this test, connect MOSI pin to the MISO of the SPI */ #define STACK_SIZE 512 -#define BUF_SIZE 17 +#define BUF_SIZE 18 #define BUF2_SIZE 36 #if CONFIG_NOCACHE_MEMORY -static const char tx_data[BUF_SIZE] = "0123456789abcdef\0"; -static __aligned(32) char buffer_tx[BUF_SIZE] __used __attribute__((__section__(".nocache"))); -static __aligned(32) char buffer_rx[BUF_SIZE] __used __attribute__((__section__(".nocache"))); +#define __NOCACHE __attribute__((__section__(".nocache"))) +#elif defined(CONFIG_DT_DEFINED_NOCACHE) +#define __NOCACHE __attribute__((__section__(CONFIG_DT_DEFINED_NOCACHE_NAME))) +#else /* CONFIG_NOCACHE_MEMORY */ +#define __NOCACHE +#endif /* CONFIG_NOCACHE_MEMORY */ + +static const char tx_data[BUF_SIZE] = "0123456789abcdef-\0"; +static __aligned(32) char buffer_tx[BUF_SIZE] __used __NOCACHE; +static __aligned(32) char buffer_rx[BUF_SIZE] __used __NOCACHE; static const char tx2_data[BUF2_SIZE] = "Thequickbrownfoxjumpsoverthelazydog\0"; -static __aligned(32) char buffer2_tx[BUF2_SIZE] __used __attribute__((__section__(".nocache"))); -static __aligned(32) char buffer2_rx[BUF2_SIZE] __used __attribute__((__section__(".nocache"))); -#else -/* this src memory shall be in RAM to support using as a DMA source pointer.*/ -static uint8_t buffer_tx[] = "0123456789abcdef\0"; -static uint8_t buffer_rx[BUF_SIZE] = {}; - -static uint8_t buffer2_tx[] = "Thequickbrownfoxjumpsoverthelazydog\0"; -static uint8_t buffer2_rx[BUF2_SIZE] = {}; -#endif +static __aligned(32) char buffer2_tx[BUF2_SIZE] __used __NOCACHE; +static __aligned(32) char buffer2_rx[BUF2_SIZE] __used __NOCACHE; /* * We need 5x(buffer size) + 1 to print a comma-separated list of each @@ -423,6 +443,80 @@ static int spi_rx_every_4(struct spi_dt_spec *spec) return 0; } +static int spi_rx_bigger_than_tx(struct spi_dt_spec *spec) +{ + const uint32_t tx_buf_size = 8; + + BUILD_ASSERT(tx_buf_size < BUF_SIZE, + "Transmit buffer is expected to be smaller than the receive buffer"); + + const struct spi_buf tx_bufs[] = { + { + .buf = buffer_tx, + .len = tx_buf_size, + }, + }; + const struct spi_buf rx_bufs[] = { + { + .buf = buffer_rx, + .len = BUF_SIZE, + } + }; + const struct spi_buf_set tx = { + .buffers = tx_bufs, + .count = ARRAY_SIZE(tx_bufs) + }; + const struct spi_buf_set rx = { + .buffers = rx_bufs, + .count = ARRAY_SIZE(rx_bufs) + }; + int ret; + + if (IS_ENABLED(CONFIG_SPI_STM32_DMA)) { + LOG_INF("Skip rx bigger than tx"); + return 0; + } + + LOG_INF("Start rx bigger than tx"); + + (void)memset(buffer_rx, 0xff, BUF_SIZE); + + ret = spi_transceive_dt(spec, &tx, &rx); + if (ret) { + LOG_ERR("Code %d", ret); + zassert_false(ret, "SPI transceive failed"); + return -1; + } + + if (memcmp(buffer_tx, buffer_rx, tx_buf_size)) { + to_display_format(buffer_tx, tx_buf_size, buffer_print_tx); + to_display_format(buffer_rx, tx_buf_size, buffer_print_rx); + LOG_ERR("Buffer contents are different: %s", buffer_print_tx); + LOG_ERR(" vs: %s", buffer_print_rx); + zassert_false(1, "Buffer contents are different"); + return -1; + } + + const uint8_t all_zeroes_buf[BUF_SIZE] = {0}; + + if (memcmp(all_zeroes_buf, buffer_rx + tx_buf_size, BUF_SIZE - tx_buf_size)) { + to_display_format( + buffer_rx + tx_buf_size, BUF_SIZE - tx_buf_size, buffer_print_tx); + + to_display_format( + all_zeroes_buf, BUF_SIZE - tx_buf_size, buffer_print_rx); + + LOG_ERR("Buffer contents are different: %s", buffer_print_tx); + LOG_ERR(" vs: %s", buffer_print_rx); + zassert_false(1, "Buffer contents are different"); + return -1; + } + + LOG_INF("Passed"); + + return 0; +} + #if (CONFIG_SPI_ASYNC) static struct k_poll_signal async_sig = K_POLL_SIGNAL_INITIALIZER(async_sig); static struct k_poll_event async_evt = @@ -433,10 +527,16 @@ static K_SEM_DEFINE(caller, 0, 1); K_THREAD_STACK_DEFINE(spi_async_stack, STACK_SIZE); static int result = 1; -static void spi_async_call_cb(struct k_poll_event *evt, - struct k_sem *caller_sem, - void *unused) +static void spi_async_call_cb(void *p1, + void *p2, + void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct k_poll_event *evt = p1; + struct k_sem *caller_sem = p2; int ret; LOG_DBG("Polling..."); @@ -461,12 +561,20 @@ static int spi_async_call(struct spi_dt_spec *spec) .buf = buffer_tx, .len = BUF_SIZE, }, + { + .buf = buffer2_tx, + .len = BUF2_SIZE, + }, }; const struct spi_buf rx_bufs[] = { { .buf = buffer_rx, .len = BUF_SIZE, }, + { + .buf = buffer2_rx, + .len = BUF2_SIZE, + }, }; const struct spi_buf_set tx = { .buffers = tx_bufs, @@ -479,6 +587,8 @@ static int spi_async_call(struct spi_dt_spec *spec) int ret; LOG_INF("Start async call"); + memset(buffer_rx, 0, sizeof(buffer_rx)); + memset(buffer2_rx, 0, sizeof(buffer2_rx)); ret = spi_transceive_signal(spec->bus, &spec->config, &tx, &rx, &async_sig); if (ret == -ENOTSUP) { @@ -500,6 +610,24 @@ static int spi_async_call(struct spi_dt_spec *spec) return -1; } + if (memcmp(buffer_tx, buffer_rx, BUF_SIZE)) { + to_display_format(buffer_tx, BUF_SIZE, buffer_print_tx); + to_display_format(buffer_rx, BUF_SIZE, buffer_print_rx); + LOG_ERR("Buffer contents are different: %s", buffer_print_tx); + LOG_ERR(" vs: %s", buffer_print_rx); + zassert_false(1, "Buffer contents are different"); + return -1; + } + + if (memcmp(buffer2_tx, buffer2_rx, BUF2_SIZE)) { + to_display_format(buffer2_tx, BUF2_SIZE, buffer_print_tx2); + to_display_format(buffer2_rx, BUF2_SIZE, buffer_print_rx2); + LOG_ERR("Buffer 2 contents are different: %s", buffer_print_tx2); + LOG_ERR(" vs: %s", buffer_print_rx2); + zassert_false(1, "Buffer 2 contents are different"); + return -1; + } + LOG_INF("Passed"); return 0; @@ -534,12 +662,15 @@ ZTEST(spi_loopback, test_spi_loopback) struct k_thread async_thread; k_tid_t async_thread_id; #endif - LOG_INF("SPI test on buffers TX/RX %p/%p", buffer_tx, buffer_rx); + + LOG_INF("SPI test on buffers TX/RX %p/%p" FRAME_SIZE_STR DMA_ENABLED_STR, + buffer_tx, + buffer_rx); #if (CONFIG_SPI_ASYNC) async_thread_id = k_thread_create(&async_thread, spi_async_stack, STACK_SIZE, - (k_thread_entry_t)spi_async_call_cb, + spi_async_call_cb, &async_evt, &caller, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); #endif @@ -552,7 +683,8 @@ ZTEST(spi_loopback, test_spi_loopback) spi_null_tx_buf(&spi_slow) || spi_rx_half_start(&spi_slow) || spi_rx_half_end(&spi_slow) || - spi_rx_every_4(&spi_slow) + spi_rx_every_4(&spi_slow) || + spi_rx_bigger_than_tx(&spi_slow) #if (CONFIG_SPI_ASYNC) || spi_async_call(&spi_slow) #endif @@ -569,7 +701,8 @@ ZTEST(spi_loopback, test_spi_loopback) spi_null_tx_buf(&spi_fast) || spi_rx_half_start(&spi_fast) || spi_rx_half_end(&spi_fast) || - spi_rx_every_4(&spi_fast) + spi_rx_every_4(&spi_fast) || + spi_rx_bigger_than_tx(&spi_fast) #if (CONFIG_SPI_ASYNC) || spi_async_call(&spi_fast) #endif @@ -592,12 +725,10 @@ ZTEST(spi_loopback, test_spi_loopback) static void *spi_loopback_setup(void) { -#if CONFIG_NOCACHE_MEMORY memset(buffer_tx, 0, sizeof(buffer_tx)); memcpy(buffer_tx, tx_data, sizeof(tx_data)); memset(buffer2_tx, 0, sizeof(buffer2_tx)); memcpy(buffer2_tx, tx2_data, sizeof(tx2_data)); -#endif return NULL; } diff --git a/tests/drivers/spi/spi_loopback/src/spi_rtio.c b/tests/drivers/spi/spi_loopback/src/spi_rtio.c index 5c1bb4a356d..be52fc8c3ee 100644 --- a/tests/drivers/spi/spi_loopback/src/spi_rtio.c +++ b/tests/drivers/spi/spi_loopback/src/spi_rtio.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "zephyr/devicetree.h" +#include #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL #include LOG_MODULE_REGISTER(spi_rtio_loopback); diff --git a/tests/drivers/spi/spi_loopback/testcase.yaml b/tests/drivers/spi/spi_loopback/testcase.yaml index 42e649fed22..3c6995e37cd 100644 --- a/tests/drivers/spi/spi_loopback/testcase.yaml +++ b/tests/drivers/spi/spi_loopback/testcase.yaml @@ -13,6 +13,20 @@ tests: drivers.spi.loopback: {} drivers.spi.loopback.internal: filter: CONFIG_SPI_LOOPBACK_MODE_LOOP + drivers.spi.loopback.lpspi.dma: + filter: CONFIG_HAS_MCUX_LPSPI and CONFIG_HAS_MCUX_EDMA + extra_configs: + - CONFIG_SPI_MCUX_LPSPI_DMA=y + drivers.spi.loopback.lpspi.async.unset: + filter: CONFIG_HAS_MCUX_LPSPI and CONFIG_HAS_MCUX_EDMA + extra_configs: + - CONFIG_SPI_MCUX_LPSPI_DMA=n + - CONFIG_SPI_ASYNC=n + drivers.spi.loopback.lpspi.dma.async.unset: + filter: CONFIG_HAS_MCUX_LPSPI and CONFIG_HAS_MCUX_EDMA + extra_configs: + - CONFIG_SPI_MCUX_LPSPI_DMA=y + - CONFIG_SPI_ASYNC=n drivers.spi.loopback.rtio: extra_configs: - CONFIG_SPI_RTIO=y @@ -32,6 +46,13 @@ tests: - tdk_robokit1 integration_platforms: - sam_e70_xplained + drivers.spi.stm32_spi_16bits_frames.loopback: + extra_args: + - OVERLAY_CONFIG="overlay-stm32-spi-16bits.conf" + - DTC_OVERLAY_FILE="overlay-stm32-spi-16bits.overlay" + platform_allow: + - nucleo_h743zi + - nucleo_h753zi drivers.spi.stm32_spi_dma.loopback: extra_args: OVERLAY_CONFIG="overlay-stm32-spi-dma.conf" filter: CONFIG_SOC_FAMILY_STM32 @@ -44,9 +65,39 @@ tests: - nucleo_l152re - nucleo_wl55jc - nucleo_h743zi + - nucleo_h753zi - stm32h573i_dk integration_platforms: - nucleo_g474re + drivers.spi.stm32_spi_dma_no_nocache.loopback: + extra_args: + - OVERLAY_CONFIG="overlay-stm32-spi-dma-no-nocache.conf" + filter: CONFIG_SOC_FAMILY_STM32 + platform_allow: + - nucleo_h743zi + - nucleo_h753zi + drivers.spi.stm32_spi_16bits_frames_dma.loopback: + extra_args: + - OVERLAY_CONFIG="overlay-stm32-spi-16bits-dma.conf" + - DTC_OVERLAY_FILE="overlay-stm32-spi-16bits.overlay" + filter: CONFIG_SOC_FAMILY_STM32 + platform_allow: + - nucleo_h743zi + - nucleo_h753zi + drivers.spi.stm32_spi_16bits_frames_dma_no_nocache.loopback: + extra_args: + - OVERLAY_CONFIG="overlay-stm32-spi-16bits-dma-no-nocache.conf" + - DTC_OVERLAY_FILE="overlay-stm32-spi-16bits.overlay" + filter: CONFIG_SOC_FAMILY_STM32 + platform_allow: + - nucleo_h743zi + - nucleo_h753zi + drivers.spi.stm32_spi_interrupt.loopback: + extra_args: OVERLAY_CONFIG="overlay-stm32-spi-interrupt.conf" + filter: CONFIG_SOC_FAMILY_STM32 + platform_allow: + - nucleo_h743zi + - nucleo_h753zi drivers.spi.gd32_spi_interrupt.loopback: extra_args: OVERLAY_CONFIG="overlay-gd32-spi-interrupt.conf" platform_allow: @@ -73,31 +124,31 @@ tests: - gd32vf103v_eval - longan_nano - longan_nano_lite - drivers.pl022_spi_interrupt.loopback: + drivers.spi.pl022_spi_interrupt.loopback: extra_configs: - CONFIG_SPI_PL022_INTERRUPT=y - CONFIG_SPI_PL022_DMA=n platform_allow: rpi_pico - drivers.pl022_spi_dma.loopback: + drivers.spi.pl022_spi_dma.loopback: extra_configs: - CONFIG_SPI_PL022_INTERRUPT=n - CONFIG_SPI_PL022_DMA=y - CONFIG_DMA=y platform_allow: rpi_pico - drivers.pl022_spi_dma_and_interrupt.loopback: + drivers.spi.pl022_spi_dma_and_interrupt.loopback: extra_configs: - CONFIG_SPI_PL022_INTERRUPT=y - CONFIG_SPI_PL022_DMA=y - CONFIG_DMA=y platform_allow: rpi_pico - drivers.pl022_spi_dma_no_dma_props.loopback: + drivers.spi.pl022_spi_dma_no_dma_props.loopback: extra_args: DTC_OVERLAY_FILE="boards/rpi_pico_delete_dma_props.overlay" extra_configs: - CONFIG_SPI_PL022_INTERRUPT=n - CONFIG_SPI_PL022_DMA=y - CONFIG_DMA=y platform_allow: rpi_pico - drivers.pl022_spi_dma_and_interrupt_no_dma_props.loopback: + drivers.spi.pl022_spi_dma_and_interrupt_no_dma_props.loopback: extra_args: DTC_OVERLAY_FILE="boards/rpi_pico_delete_dma_props.overlay" extra_configs: - CONFIG_SPI_PL022_INTERRUPT=y diff --git a/tests/drivers/syscon/prj.conf b/tests/drivers/syscon/prj.conf index 7dabbfb75d9..9970e77ce57 100644 --- a/tests/drivers/syscon/prj.conf +++ b/tests/drivers/syscon/prj.conf @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SYSCON=y CONFIG_MMU=y CONFIG_HAVE_CUSTOM_LINKER_SCRIPT=y diff --git a/tests/drivers/timer/nrf_rtc_timer/prj.conf b/tests/drivers/timer/nrf_rtc_timer/prj.conf index d0b55e455c7..15c8902ce88 100644 --- a/tests/drivers/timer/nrf_rtc_timer/prj.conf +++ b/tests/drivers/timer/nrf_rtc_timer/prj.conf @@ -1,8 +1,11 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=2 CONFIG_SYS_CLOCK_TICKS_PER_SEC=32768 +# This test assumes it can use all configured NRF_RTC_TIMER_USER_CHAN_COUNT +# But the sync RTC code uses one while it synchronizes. Let's just disable it. +CONFIG_NRF53_SYNC_RTC=n + # Debug build # CONFIG_NO_OPTIMIZATIONS=y # CONFIG_ZTEST_STACK_SIZE=2048 diff --git a/tests/drivers/timer/nrf_rtc_timer/testcase.yaml b/tests/drivers/timer/nrf_rtc_timer/testcase.yaml index 8ebe05e8e96..9c3f9a94413 100644 --- a/tests/drivers/timer/nrf_rtc_timer/testcase.yaml +++ b/tests/drivers/timer/nrf_rtc_timer/testcase.yaml @@ -19,5 +19,7 @@ tests: - nrf52dk_nrf52832 - nrf52840dk_nrf52840 - nrf52_bsim + - nrf5340bsim_nrf5340_cpuapp + - nrf5340bsim_nrf5340_cpunet integration_platforms: - nrf52dk_nrf52832 diff --git a/tests/drivers/uart/uart_async_api/boards/esp32c3_luatos_core.conf b/tests/drivers/uart/uart_async_api/boards/esp32c3_luatos_core.conf new file mode 100644 index 00000000000..76f7644d896 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/esp32c3_luatos_core.conf @@ -0,0 +1,2 @@ +CONFIG_HEAP_MEM_POOL_SIZE=32768 +CONFIG_DMA=y diff --git a/tests/drivers/uart/uart_async_api/boards/esp32c3_luatos_core.overlay b/tests/drivers/uart/uart_async_api/boards/esp32c3_luatos_core.overlay new file mode 100644 index 00000000000..3582e7dcf94 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/esp32c3_luatos_core.overlay @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + uart1_test: uart1_test { + group1 { + pinmux = ; + input-enable; + }; + group2 { + pinmux = ; + output-enable; + }; + }; +}; + +dut: &uart1 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart1_test>; + pinctrl-names = "default"; + dmas = <&dma 0>, <&dma 1>; + dma-names = "rx", "tx"; +}; + +&dma { + status = "okay"; +}; diff --git a/tests/drivers/uart/uart_async_api/boards/esp32c3_luatos_core_usb.conf b/tests/drivers/uart/uart_async_api/boards/esp32c3_luatos_core_usb.conf new file mode 100644 index 00000000000..76f7644d896 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/esp32c3_luatos_core_usb.conf @@ -0,0 +1,2 @@ +CONFIG_HEAP_MEM_POOL_SIZE=32768 +CONFIG_DMA=y diff --git a/tests/drivers/uart/uart_async_api/boards/esp32c3_luatos_core_usb.overlay b/tests/drivers/uart/uart_async_api/boards/esp32c3_luatos_core_usb.overlay new file mode 100644 index 00000000000..c23a4f9a0b4 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/esp32c3_luatos_core_usb.overlay @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * Copyright (c) 2023 YuLong Yao + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + uart1_test: uart1_test { + group1 { + pinmux = ; + input-enable; + }; + group2 { + pinmux = ; + output-enable; + }; + }; +}; + +dut: &uart1 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart1_test>; + pinctrl-names = "default"; + dmas = <&dma 0>, <&dma 1>; + dma-names = "rx", "tx"; +}; + +&dma { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; diff --git a/tests/drivers/uart/uart_async_api/boards/esp32s3_luatos_core.conf b/tests/drivers/uart/uart_async_api/boards/esp32s3_luatos_core.conf new file mode 100644 index 00000000000..73aff8957e7 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/esp32s3_luatos_core.conf @@ -0,0 +1 @@ +CONFIG_DMA=y diff --git a/tests/drivers/uart/uart_async_api/boards/esp32s3_luatos_core.overlay b/tests/drivers/uart/uart_async_api/boards/esp32s3_luatos_core.overlay new file mode 100644 index 00000000000..50d6012d7bd --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/esp32s3_luatos_core.overlay @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + uart1_test: uart1_test { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + bias-pull-up; + }; + }; +}; + +dut: &uart1 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart1_test>; + pinctrl-names = "default"; + dmas = <&dma 0>, <&dma 1>; + dma-names = "rx", "tx"; +}; + +&dma { + status = "okay"; +}; diff --git a/tests/drivers/uart/uart_async_api/boards/esp32s3_luatos_core_usb.conf b/tests/drivers/uart/uart_async_api/boards/esp32s3_luatos_core_usb.conf new file mode 100644 index 00000000000..73aff8957e7 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/esp32s3_luatos_core_usb.conf @@ -0,0 +1 @@ +CONFIG_DMA=y diff --git a/tests/drivers/uart/uart_async_api/boards/esp32s3_luatos_core_usb.overlay b/tests/drivers/uart/uart_async_api/boards/esp32s3_luatos_core_usb.overlay new file mode 100644 index 00000000000..c43f4e551ec --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/esp32s3_luatos_core_usb.overlay @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * Copyright (c) 2023 YuLong Yao + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + uart1_test: uart1_test { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + bias-pull-up; + }; + }; +}; + +dut: &uart1 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart1_test>; + pinctrl-names = "default"; + dmas = <&dma 0>, <&dma 1>; + dma-names = "rx", "tx"; +}; + +&dma { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; diff --git a/tests/drivers/uart/uart_async_api/boards/mr_canhubk3.overlay b/tests/drivers/uart/uart_async_api/boards/mr_canhubk3.overlay new file mode 100644 index 00000000000..bf265a6a962 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/mr_canhubk3.overlay @@ -0,0 +1,16 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ +/ { + chosen { + zephyr,sram = &dtcm; + }; +}; + +dut: &lpuart10 { + current-speed = <115200>; + nxp,loopback; + status = "okay"; +}; diff --git a/tests/drivers/uart/uart_async_api/boards/nucleo_wba52cg.overlay b/tests/drivers/uart/uart_async_api/boards/nucleo_wba52cg.overlay new file mode 100644 index 00000000000..c495168048b --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/nucleo_wba52cg.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +dut: &lpuart1 { + dmas = <&gpdma1 0 16 STM32_DMA_PERIPH_TX + &gpdma1 1 15 STM32_DMA_PERIPH_RX>; + dma-names = "tx", "rx"; +}; + +&gpdma1 { + status = "okay"; +}; diff --git a/tests/drivers/uart/uart_async_api/boards/stm32h735g_disco.conf b/tests/drivers/uart/uart_async_api/boards/stm32h735g_disco.conf new file mode 100644 index 00000000000..24be02d577c --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/stm32h735g_disco.conf @@ -0,0 +1 @@ +CONFIG_DCACHE=n diff --git a/tests/drivers/uart/uart_async_api/boards/stm32h735g_disco.overlay b/tests/drivers/uart/uart_async_api/boards/stm32h735g_disco.overlay new file mode 100644 index 00000000000..58618373e6f --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/stm32h735g_disco.overlay @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 STMicroelectronics + * Copyright (c) 2023 Benjamin Deuter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +dut: &uart7 { + dmas = <&dmamux1 2 80 STM32_DMA_PERIPH_TX>, + <&dmamux1 3 79 STM32_DMA_PERIPH_RX>; + dma-names = "tx", "rx"; + pinctrl-0 = <&uart7_tx_pf7 &uart7_rx_pf6>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&dma1 { + status = "okay"; +}; + +&dma2 { + status = "okay"; +}; + +&dmamux1 { + status = "okay"; +}; diff --git a/tests/drivers/uart/uart_async_api/prj.conf b/tests/drivers/uart/uart_async_api/prj.conf index 630e06c9306..39c50952d48 100644 --- a/tests/drivers/uart/uart_async_api/prj.conf +++ b/tests/drivers/uart/uart_async_api/prj.conf @@ -1,5 +1,5 @@ CONFIG_SERIAL=y CONFIG_UART_ASYNC_API=y +CONFIG_UART_USE_RUNTIME_CONFIGURE=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y diff --git a/tests/drivers/uart/uart_async_api/src/test_uart_async.c b/tests/drivers/uart/uart_async_api/src/test_uart_async.c index af3a63b197d..9579e49c759 100644 --- a/tests/drivers/uart/uart_async_api/src/test_uart_async.c +++ b/tests/drivers/uart/uart_async_api/src/test_uart_async.c @@ -79,10 +79,11 @@ static void uart_async_test_init(void) struct test_data { volatile uint32_t tx_aborted_count; - uint8_t rx_buf[5]; - bool rx_buf_req_done; - bool supply_next_buffer; - uint8_t *last_rx_buf; + uint8_t rx_first_buffer[10]; + uint32_t recv_bytes_first_buffer; + uint8_t rx_second_buffer[5]; + uint32_t recv_bytes_second_buffer; + bool supply_second_buffer; }; ZTEST_BMEM struct test_data tdata; @@ -101,17 +102,22 @@ static void test_single_read_callback(const struct device *dev, data->tx_aborted_count++; break; case UART_RX_RDY: - data->last_rx_buf = &evt->data.rx.buf[evt->data.rx.offset]; + if ((uintptr_t)evt->data.rx.buf < (uintptr_t)tdata.rx_second_buffer) { + data->recv_bytes_first_buffer += evt->data.rx.len; + } else { + data->recv_bytes_second_buffer += evt->data.rx.len; + } k_sem_give(&rx_rdy); break; case UART_RX_BUF_RELEASED: k_sem_give(&rx_buf_released); break; case UART_RX_BUF_REQUEST: - if (data->supply_next_buffer) { + if (data->supply_second_buffer) { /* Reply to one buffer request. */ - uart_rx_buf_rsp(dev, data->rx_buf, sizeof(data->rx_buf)); - data->supply_next_buffer = false; + uart_rx_buf_rsp(dev, data->rx_second_buffer, + sizeof(data->rx_second_buffer)); + data->supply_second_buffer = false; } break; case UART_RX_DISABLED: @@ -129,7 +135,7 @@ static void *single_read_setup(void) uart_async_test_init(); memset(&tdata, 0, sizeof(tdata)); - tdata.supply_next_buffer = true; + tdata.supply_second_buffer = true; uart_callback_set(uart_dev, test_single_read_callback, (void *) &tdata); @@ -137,30 +143,57 @@ static void *single_read_setup(void) return NULL; } -ZTEST_USER(uart_async_single_read, test_single_read) +static void tdata_check_recv_buffers(const uint8_t *tx_buf, uint32_t sent_bytes) { - uint8_t rx_buf[10] = {0}; + uint32_t recv_bytes_total; + + recv_bytes_total = tdata.recv_bytes_first_buffer + tdata.recv_bytes_second_buffer; + zassert_equal(recv_bytes_total, sent_bytes, "Incorrect number of bytes received"); + + zassert_equal(memcmp(tx_buf, tdata.rx_first_buffer, tdata.recv_bytes_first_buffer), 0, + "Invalid data received in first buffer"); + zassert_equal(memcmp(tx_buf + tdata.recv_bytes_first_buffer, tdata.rx_second_buffer, + tdata.recv_bytes_second_buffer), + 0, "Invalid data received in second buffer"); + + /* check that the remaining bytes in the buffers are zero */ + for (int i = tdata.recv_bytes_first_buffer; i < sizeof(tdata.rx_first_buffer); i++) { + zassert_equal(tdata.rx_first_buffer[i], 0, + "Received extra data to the first buffer"); + } + for (int i = tdata.recv_bytes_second_buffer; i < sizeof(tdata.rx_second_buffer); i++) { + zassert_equal(tdata.rx_second_buffer[i], 0, + "Received extra data to the second buffer"); + } +} + +ZTEST_USER(uart_async_single_read, test_single_read) +{ /* Check also if sending from read only memory (e.g. flash) works. */ - static const uint8_t tx_buf[5] = "test\0"; + static const uint8_t tx_buf[] = "0123456789"; + uint32_t sent_bytes = 0; - zassert_not_equal(memcmp(tx_buf, rx_buf, 5), 0, + zassert_not_equal(memcmp(tx_buf, tdata.rx_first_buffer, 5), 0, "Initial buffer check failed"); - uart_rx_enable(uart_dev, rx_buf, 10, 50 * USEC_PER_MSEC); + uart_rx_enable(uart_dev, tdata.rx_first_buffer, 10, 50 * USEC_PER_MSEC); zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), -EAGAIN, "RX_RDY not expected at this point"); - uart_tx(uart_dev, tx_buf, sizeof(tx_buf), 100 * USEC_PER_MSEC); + uart_tx(uart_dev, tx_buf, 5, 100 * USEC_PER_MSEC); + sent_bytes += 5; + zassert_equal(k_sem_take(&tx_done, K_MSEC(100)), 0, "TX_DONE timeout"); zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), 0, "RX_RDY timeout"); zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), -EAGAIN, "Extra RX_RDY received"); - zassert_equal(memcmp(tx_buf, tdata.last_rx_buf, 5), 0, "Buffers not equal"); - zassert_not_equal(memcmp(tx_buf, rx_buf+5, 5), 0, "Buffers not equal"); + tdata_check_recv_buffers(tx_buf, sent_bytes); + + uart_tx(uart_dev, tx_buf + sent_bytes, 5, 100 * USEC_PER_MSEC); + sent_bytes += 5; - uart_tx(uart_dev, tx_buf, sizeof(tx_buf), 100 * USEC_PER_MSEC); zassert_equal(k_sem_take(&tx_done, K_MSEC(100)), 0, "TX_DONE timeout"); zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), 0, "RX_RDY timeout"); zassert_equal(k_sem_take(&rx_buf_released, K_MSEC(100)), @@ -173,7 +206,8 @@ ZTEST_USER(uart_async_single_read, test_single_read) zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), -EAGAIN, "Extra RX_RDY received"); - zassert_equal(memcmp(tx_buf, tdata.last_rx_buf, 5), 0, "Buffers not equal"); + tdata_check_recv_buffers(tx_buf, sent_bytes); + zassert_equal(tdata.tx_aborted_count, 0, "TX aborted triggered"); } @@ -196,11 +230,13 @@ ZTEST_USER(uart_async_multi_rx, test_multiple_rx_enable) { /* Check also if sending from read only memory (e.g. flash) works. */ static const uint8_t tx_buf[] = "test"; - uint8_t rx_buf[sizeof(tx_buf)] = {0}; + const uint32_t rx_buf_size = sizeof(tx_buf); int ret; + BUILD_ASSERT(rx_buf_size <= sizeof(tdata.rx_first_buffer), "Invalid buf size"); + /* Enable RX without a timeout. */ - ret = uart_rx_enable(uart_dev, rx_buf, sizeof(rx_buf), SYS_FOREVER_US); + ret = uart_rx_enable(uart_dev, tdata.rx_first_buffer, rx_buf_size, SYS_FOREVER_US); zassert_equal(ret, 0, "uart_rx_enable failed"); zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), -EAGAIN, "RX_RDY not expected at this point"); @@ -221,7 +257,7 @@ ZTEST_USER(uart_async_multi_rx, test_multiple_rx_enable) k_sem_reset(&rx_disabled); /* Check that RX can be reenabled after "manual" disabling. */ - ret = uart_rx_enable(uart_dev, rx_buf, sizeof(rx_buf), + ret = uart_rx_enable(uart_dev, tdata.rx_first_buffer, rx_buf_size, 50 * USEC_PER_MSEC); zassert_equal(ret, 0, "uart_rx_enable failed"); zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), -EAGAIN, @@ -240,17 +276,17 @@ ZTEST_USER(uart_async_multi_rx, test_multiple_rx_enable) "RX_DISABLED timeout"); zassert_equal(tx_aborted_count, 0, "Unexpected TX abort"); - zassert_equal(memcmp(tx_buf, rx_buf, sizeof(tx_buf)), 0, - "Buffers not equal"); + tdata_check_recv_buffers(tx_buf, sizeof(tx_buf)); k_sem_reset(&rx_rdy); k_sem_reset(&rx_buf_released); k_sem_reset(&rx_disabled); k_sem_reset(&tx_done); - memset(rx_buf, 0, sizeof(rx_buf)); + + memset(&tdata, 0, sizeof(tdata)); /* Check that RX can be reenabled after automatic disabling. */ - ret = uart_rx_enable(uart_dev, rx_buf, sizeof(rx_buf), + ret = uart_rx_enable(uart_dev, tdata.rx_first_buffer, rx_buf_size, 50 * USEC_PER_MSEC); zassert_equal(ret, 0, "uart_rx_enable failed"); zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), -EAGAIN, @@ -269,8 +305,7 @@ ZTEST_USER(uart_async_multi_rx, test_multiple_rx_enable) "RX_DISABLED timeout"); zassert_equal(tx_aborted_count, 0, "Unexpected TX abort"); - zassert_equal(memcmp(tx_buf, rx_buf, sizeof(tx_buf)), 0, - "Buffers not equal"); + tdata_check_recv_buffers(tx_buf, sizeof(tx_buf)); } ZTEST_BMEM uint8_t chained_read_buf[2][8]; diff --git a/tests/drivers/uart/uart_async_rx/CMakeLists.txt b/tests/drivers/uart/uart_async_rx/CMakeLists.txt new file mode 100644 index 00000000000..9cb2446f3c6 --- /dev/null +++ b/tests/drivers/uart/uart_async_rx/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(uart_async_rx) + +target_sources(app PRIVATE + src/main.c +) diff --git a/tests/drivers/uart/uart_async_rx/prj.conf b/tests/drivers/uart/uart_async_rx/prj.conf new file mode 100644 index 00000000000..eb88c509ea7 --- /dev/null +++ b/tests/drivers/uart/uart_async_rx/prj.conf @@ -0,0 +1,3 @@ +CONFIG_ZTEST=y +CONFIG_ZTRESS=y +CONFIG_UART_ASYNC_RX_HELPER=y diff --git a/tests/drivers/uart/uart_async_rx/src/main.c b/tests/drivers/uart/uart_async_rx/src/main.c new file mode 100644 index 00000000000..d95c6a69066 --- /dev/null +++ b/tests/drivers/uart/uart_async_rx/src/main.c @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +LOG_MODULE_REGISTER(test); + +static void mem_fill(uint8_t *buf, uint8_t init, size_t len) +{ + for (size_t i = 0; i < len; i++) { + buf[i] = init + i; + } +} + +static bool mem_check(uint8_t *buf, uint8_t init, size_t len) +{ + for (size_t i = 0; i < len; i++) { + if (buf[i] != init + i) { + return false; + } + } + + return true; +} + +ZTEST(uart_async_rx, test_rx) +{ + int err; + uint8_t buf[40]; + static const int buf_cnt = 4; + size_t aloc_len; + size_t claim_len; + uint8_t *claim_buf; + uint8_t *aloc_buf; + struct uart_async_rx async_rx; + const struct uart_async_rx_config config = { + .buffer = buf, + .length = sizeof(buf), + .buf_cnt = buf_cnt + }; + + err = uart_async_rx_init(&async_rx, &config); + zassert_equal(err, 0); + + aloc_len = uart_async_rx_get_buf_len(&async_rx); + aloc_buf = uart_async_rx_buf_req(&async_rx); + + mem_fill(aloc_buf, 0, aloc_len - 2); + + /* No data to read. */ + claim_len = uart_async_rx_data_claim(&async_rx, &claim_buf, 1); + zassert_equal(claim_len, 0); + + /* Simulate partial write */ + uart_async_rx_on_rdy(&async_rx, aloc_buf, aloc_len - 4); + + /* There is at least 1 byte available */ + claim_len = uart_async_rx_data_claim(&async_rx, &claim_buf, 1); + zassert_equal(claim_len, 1); + zassert_equal(claim_buf, aloc_buf); + zassert_true(mem_check(claim_buf, 0, 1)); + + /* All received data is available */ + claim_len = uart_async_rx_data_claim(&async_rx, &claim_buf, 100); + zassert_equal(claim_len, aloc_len - 4); + zassert_equal(claim_buf, aloc_buf); + zassert_true(mem_check(claim_buf, 0, aloc_len - 4)); + + /* Simulate 2 bytes received to the same buffer. */ + uart_async_rx_on_rdy(&async_rx, aloc_buf, 2); + + /* Indicate and of the current buffer. */ + uart_async_rx_on_buf_rel(&async_rx, aloc_buf); + + /* Claim all data received so far */ + claim_len = uart_async_rx_data_claim(&async_rx, &claim_buf, 100); + zassert_equal(claim_len, aloc_len - 2); + zassert_equal(claim_buf, aloc_buf); + zassert_true(mem_check(claim_buf, 0, aloc_len - 2)); + + /* Consume first 2 bytes. */ + uart_async_rx_data_consume(&async_rx, 2); + + /* Now claim will return buffer taking into account that first 2 bytes are + * consumed. + */ + claim_len = uart_async_rx_data_claim(&async_rx, &claim_buf, 100); + zassert_equal(claim_len, aloc_len - 4); + zassert_equal(claim_buf, &aloc_buf[2]); + zassert_true(mem_check(claim_buf, 2, aloc_len - 4)); + + /* Consume rest of data. Get indication that it was end of the buffer. */ + uart_async_rx_data_consume(&async_rx, aloc_len - 4); +} + +ZTEST(uart_async_rx, test_rx_late_consume) +{ + int err; + uint8_t buf[40] __aligned(4); + static const int buf_cnt = 4; + size_t aloc_len; + size_t claim_len; + uint8_t *claim_buf; + uint8_t *aloc_buf; + struct uart_async_rx async_rx; + const struct uart_async_rx_config config = { + .buffer = buf, + .length = sizeof(buf), + .buf_cnt = buf_cnt + }; + + err = uart_async_rx_init(&async_rx, &config); + zassert_equal(err, 0); + + aloc_len = uart_async_rx_get_buf_len(&async_rx); + for (int i = 0; i < buf_cnt; i++) { + aloc_buf = uart_async_rx_buf_req(&async_rx); + + aloc_buf[0] = (uint8_t)i; + uart_async_rx_on_rdy(&async_rx, aloc_buf, 1); + uart_async_rx_on_buf_rel(&async_rx, aloc_buf); + } + + for (int i = 0; i < buf_cnt; i++) { + claim_len = uart_async_rx_data_claim(&async_rx, &claim_buf, 100); + zassert_equal(claim_len, 1); + zassert_equal(claim_buf[0], (uint8_t)i); + + uart_async_rx_data_consume(&async_rx, 1); + } + + claim_len = uart_async_rx_data_claim(&async_rx, &claim_buf, 100); + zassert_equal(claim_len, 0); +} + +struct test_async_rx { + struct uart_async_rx async_rx; + atomic_t pending_req; + atomic_t total_pending_req; + bool in_chunks; + uint8_t exp_consume; + uint32_t byte_cnt; + uint8_t curr_len; + uint8_t *curr_buf; + uint8_t *next_buf; + struct k_spinlock lock; +}; + +static bool producer_no_chunks(void *user_data, uint32_t cnt, bool last, int prio) +{ + struct test_async_rx *test_data = (struct test_async_rx *)user_data; + struct uart_async_rx *async_rx = &test_data->async_rx; + uint32_t r = sys_rand32_get(); + uint32_t len = MAX(1, MIN(uart_async_rx_get_buf_len(async_rx), r & 0x7)); + + if (test_data->curr_buf) { + + for (int i = 0; i < len; i++) { + test_data->curr_buf[i] = (uint8_t)test_data->byte_cnt; + test_data->byte_cnt++; + } + uart_async_rx_on_rdy(async_rx, test_data->curr_buf, len); + uart_async_rx_on_buf_rel(async_rx, test_data->curr_buf); + test_data->curr_buf = test_data->next_buf; + test_data->next_buf = NULL; + + uint8_t *buf = uart_async_rx_buf_req(async_rx); + + if (buf) { + if (test_data->curr_buf == NULL) { + test_data->curr_buf = buf; + } else { + test_data->next_buf = buf; + } + } else { + atomic_inc(&test_data->pending_req); + atomic_inc(&test_data->total_pending_req); + } + } + + return true; +} + +static bool consumer(void *user_data, uint32_t cnt, bool last, int prio) +{ + struct test_async_rx *test_data = (struct test_async_rx *)user_data; + struct uart_async_rx *async_rx = &test_data->async_rx; + uint32_t r = sys_rand32_get(); + uint32_t rpt = MAX(1, r & 0x7); + + r >>= 3; + + for (uint32_t i = 0; i < rpt; i++) { + size_t claim_len = MAX(1, r & 0x7); + size_t len; + uint8_t *buf; + + r >>= 3; + len = uart_async_rx_data_claim(async_rx, &buf, claim_len); + + if (len == 0) { + return true; + } + + for (int j = 0; j < len; j++) { + zassert_equal(buf[j], test_data->exp_consume, + "%02x (exp:%02x) len:%d, total:%d", + buf[j], test_data->exp_consume, len, test_data->byte_cnt); + test_data->exp_consume++; + } + + uart_async_rx_data_consume(async_rx, len); + + if (test_data->pending_req) { + buf = uart_async_rx_buf_req(async_rx); + if (buf) { + atomic_dec(&test_data->pending_req); + } + k_spinlock_key_t key = k_spin_lock(&test_data->lock); + + if (test_data->curr_buf == NULL) { + test_data->curr_buf = buf; + } else if (test_data->next_buf == NULL) { + test_data->next_buf = buf; + } else { + zassert_true(false); + } + k_spin_unlock(&test_data->lock, key); + } + } + + return true; +} + +static bool producer_in_chunks(void *user_data, uint32_t cnt, bool last, int prio) +{ + struct test_async_rx *test_data = (struct test_async_rx *)user_data; + struct uart_async_rx *async_rx = &test_data->async_rx; + uint32_t r = sys_rand32_get(); + uint32_t rem = uart_async_rx_get_buf_len(async_rx) - test_data->curr_len; + uint32_t len = MAX(1, MIN(uart_async_rx_get_buf_len(async_rx), r & 0x7)); + + len = MIN(rem, len); + + if (test_data->curr_buf) { + for (int i = 0; i < len; i++) { + test_data->curr_buf[test_data->curr_len + i] = (uint8_t)test_data->byte_cnt; + test_data->byte_cnt++; + } + uart_async_rx_on_rdy(async_rx, test_data->curr_buf, len); + test_data->curr_len += len; + + if ((test_data->curr_len == uart_async_rx_get_buf_len(async_rx)) || (r & BIT(31))) { + test_data->curr_len = 0; + uart_async_rx_on_buf_rel(async_rx, test_data->curr_buf); + + test_data->curr_buf = test_data->next_buf; + test_data->next_buf = NULL; + + uint8_t *buf = uart_async_rx_buf_req(async_rx); + + if (buf) { + if (test_data->curr_buf == NULL) { + test_data->curr_buf = buf; + } else { + test_data->next_buf = buf; + } + } else { + atomic_inc(&test_data->pending_req); + } + } + } + + return true; +} + +static void stress_test(bool in_chunks) +{ + int err; + uint8_t buf[40]; + static const int buf_cnt = 4; + int preempt = 1000; + int timeout = 5000; + struct test_async_rx test_data; + const struct uart_async_rx_config config = { + .buffer = buf, + .length = sizeof(buf), + .buf_cnt = buf_cnt + }; + + memset(&test_data, 0, sizeof(test_data)); + + err = uart_async_rx_init(&test_data.async_rx, &config); + zassert_equal(err, 0); + + test_data.in_chunks = in_chunks; + test_data.curr_buf = uart_async_rx_buf_req(&test_data.async_rx); + + ztress_set_timeout(K_MSEC(timeout)); + + ZTRESS_EXECUTE(ZTRESS_THREAD(in_chunks ? producer_in_chunks : producer_no_chunks, + &test_data, 0, 0, Z_TIMEOUT_TICKS(20)), + ZTRESS_THREAD(consumer, &test_data, 0, preempt, Z_TIMEOUT_TICKS(20))); + + TC_PRINT("total bytes: %d\n", test_data.byte_cnt); + ztress_set_timeout(K_NO_WAIT); +} + +ZTEST(uart_async_rx, test_rx_ztress_no_chunks) +{ + stress_test(false); +} + +ZTEST(uart_async_rx, test_rx_ztress_with_chunks) +{ + stress_test(true); +} + +ZTEST_SUITE(uart_async_rx, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/drivers/uart/uart_async_rx/testcase.yaml b/tests/drivers/uart/uart_async_rx/testcase.yaml new file mode 100644 index 00000000000..64311dc1eb7 --- /dev/null +++ b/tests/drivers/uart/uart_async_rx/testcase.yaml @@ -0,0 +1,15 @@ +tests: + drivers.uart.async_rx: + filter: CONFIG_SERIAL + tags: drivers uart + integration_platforms: + - native_posix + drivers.uart.async_rx.ztress: + filter: CONFIG_SERIAL + tags: drivers uart + platform_allow: > + qemu_cortex_m3 qemu_x86 qemu_x86_64 qemu_riscv32 + integration_platforms: + - qemu_x86 + extra_configs: + - CONFIG_SYS_CLOCK_TICKS_PER_SEC=10000 diff --git a/tests/drivers/uart/uart_basic_api/prj.conf b/tests/drivers/uart/uart_basic_api/prj.conf index 56d8fda633b..4234fa73398 100644 --- a/tests/drivers/uart/uart_basic_api/prj.conf +++ b/tests/drivers/uart/uart_basic_api/prj.conf @@ -1,5 +1,5 @@ CONFIG_SERIAL=y -CONFIG_ZTEST_NEW_API=y CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_UART_USE_RUNTIME_CONFIGURE=y CONFIG_ZTEST=y CONFIG_NATIVE_UART_0_ON_STDINOUT=y diff --git a/tests/drivers/uart/uart_basic_api/prj_poll.conf b/tests/drivers/uart/uart_basic_api/prj_poll.conf index 2840968fd40..7b1c9273665 100644 --- a/tests/drivers/uart/uart_basic_api/prj_poll.conf +++ b/tests/drivers/uart/uart_basic_api/prj_poll.conf @@ -1,4 +1,4 @@ CONFIG_SERIAL=y +CONFIG_UART_USE_RUNTIME_CONFIGURE=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NATIVE_UART_0_ON_STDINOUT=y diff --git a/tests/drivers/uart/uart_basic_api/prj_shell.conf b/tests/drivers/uart/uart_basic_api/prj_shell.conf index a1bcae5b67e..f4ce1d0334c 100644 --- a/tests/drivers/uart/uart_basic_api/prj_shell.conf +++ b/tests/drivers/uart/uart_basic_api/prj_shell.conf @@ -1,7 +1,7 @@ CONFIG_SERIAL=y CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_UART_USE_RUNTIME_CONFIGURE=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SHELL_CMD_BUFF_SIZE=90 CONFIG_SHELL=y CONFIG_NATIVE_UART_0_ON_STDINOUT=y diff --git a/tests/drivers/uart/uart_basic_api/testcase.yaml b/tests/drivers/uart/uart_basic_api/testcase.yaml index 17f0b5a7986..ee4fd934660 100644 --- a/tests/drivers/uart/uart_basic_api/testcase.yaml +++ b/tests/drivers/uart/uart_basic_api/testcase.yaml @@ -12,6 +12,7 @@ tests: - CONFIG_UART_WIDE_DATA=y tags: drivers uart filter: CONFIG_UART_CONSOLE + harness: keyboard arch_allow: arm platform_allow: nucleo_h743zi integration_platforms: diff --git a/tests/drivers/uart/uart_emul/prj.conf b/tests/drivers/uart/uart_emul/prj.conf index 99676d377b4..0fe0e70acee 100644 --- a/tests/drivers/uart/uart_emul/prj.conf +++ b/tests/drivers/uart/uart_emul/prj.conf @@ -1,3 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/tests/drivers/uart/uart_emul/src/main.c b/tests/drivers/uart/uart_emul/src/main.c index 5e698d0b1e9..cea1dc72334 100644 --- a/tests/drivers/uart/uart_emul/src/main.c +++ b/tests/drivers/uart/uart_emul/src/main.c @@ -12,11 +12,22 @@ #define EMUL_UART_NODE DT_NODELABEL(euart0) #define EMUL_UART_RX_FIFO_SIZE DT_PROP(EMUL_UART_NODE, rx_fifo_size) #define EMUL_UART_TX_FIFO_SIZE DT_PROP(EMUL_UART_NODE, tx_fifo_size) -#define SAMPLE_DATA_SIZE MIN(EMUL_UART_RX_FIFO_SIZE, EMUL_UART_TX_FIFO_SIZE) + +/* + * Leave one byte left in tx to avoid filling it completely which will block the UART + * tx ready IRQ event. + */ +#define SAMPLE_DATA_SIZE MIN(EMUL_UART_RX_FIFO_SIZE, EMUL_UART_TX_FIFO_SIZE) - 1 struct uart_emul_fixture { const struct device *dev; uint8_t sample_data[SAMPLE_DATA_SIZE]; + uint8_t tx_content[SAMPLE_DATA_SIZE]; + uint8_t rx_content[SAMPLE_DATA_SIZE]; + struct k_sem tx_done_sem; + struct k_sem rx_done_sem; + size_t tx_remaining; + size_t rx_remaining; }; static void *uart_emul_setup(void) @@ -27,6 +38,9 @@ static void *uart_emul_setup(void) fixture.sample_data[i] = i; } + k_sem_init(&fixture.tx_done_sem, 0, 1); + k_sem_init(&fixture.rx_done_sem, 0, 1); + zassert_not_null(fixture.dev); return &fixture; } @@ -35,8 +49,22 @@ static void uart_emul_before(void *f) { struct uart_emul_fixture *fixture = f; + uart_irq_tx_disable(fixture->dev); + uart_irq_rx_disable(fixture->dev); + uart_emul_flush_rx_data(fixture->dev); uart_emul_flush_tx_data(fixture->dev); + + uart_err_check(fixture->dev); + + k_sem_reset(&fixture->tx_done_sem); + k_sem_reset(&fixture->rx_done_sem); + + memset(fixture->tx_content, 0, sizeof(fixture->tx_content)); + memset(fixture->rx_content, 0, sizeof(fixture->rx_content)); + + fixture->tx_remaining = SAMPLE_DATA_SIZE; + fixture->rx_remaining = SAMPLE_DATA_SIZE; } ZTEST_F(uart_emul, test_polling_out) @@ -59,20 +87,133 @@ ZTEST_F(uart_emul, test_polling_out) ZTEST_F(uart_emul, test_polling_in) { - uint8_t rx_content[SAMPLE_DATA_SIZE] = {0}; int rc; uart_emul_put_rx_data(fixture->dev, fixture->sample_data, SAMPLE_DATA_SIZE); for (size_t i = 0; i < SAMPLE_DATA_SIZE; i++) { - rc = uart_poll_in(fixture->dev, &rx_content[i]); + rc = uart_poll_in(fixture->dev, &fixture->rx_content[i]); zassert_equal(rc, 0, "RX buffer should contain data"); } - zassert_mem_equal(rx_content, fixture->sample_data, SAMPLE_DATA_SIZE); + zassert_mem_equal(fixture->rx_content, fixture->sample_data, SAMPLE_DATA_SIZE); + + /* No more data in RX buffer */ + rc = uart_poll_in(fixture->dev, &fixture->rx_content[0]); + zassert_equal(rc, -1, "RX buffer should be empty"); +} + +ZTEST_F(uart_emul, test_errors) +{ + int errors; + + uart_emul_set_errors(fixture->dev, (UART_ERROR_PARITY | UART_ERROR_FRAMING)); + errors = uart_err_check(fixture->dev); + zassert_equal(errors, (UART_ERROR_PARITY | UART_ERROR_FRAMING), "UART errors do not match"); + + /* uart_err_check should also clear existing errors */ + errors = uart_err_check(fixture->dev); + zassert_equal(errors, 0, "Should be no errors"); + + /* overflowing rx buffer should produce an overrun error */ + uart_emul_put_rx_data(fixture->dev, fixture->sample_data, SAMPLE_DATA_SIZE); + errors = uart_err_check(fixture->dev); + zassert_equal(errors, 0, "Should be no errors"); + uart_emul_put_rx_data(fixture->dev, fixture->sample_data, SAMPLE_DATA_SIZE); + errors = uart_err_check(fixture->dev); + zassert_equal(errors, UART_ERROR_OVERRUN, "UART errors do not match"); +} + +static void uart_emul_isr_handle_tx_ready(struct uart_emul_fixture *fixture) +{ + uint32_t sample_data_it; + int ret; + + if (fixture->tx_remaining) { + sample_data_it = sizeof(fixture->sample_data) - fixture->tx_remaining; + ret = uart_fifo_fill(fixture->dev, &fixture->sample_data[sample_data_it], + fixture->tx_remaining); + fixture->tx_remaining -= (size_t)ret; + } + + if (fixture->tx_remaining == 0) { + uart_irq_tx_disable(fixture->dev); + k_sem_give(&fixture->tx_done_sem); + } +} + +static void uart_emul_isr_handle_rx_ready(struct uart_emul_fixture *fixture) +{ + uint32_t rx_content_it; + int ret; + + if (fixture->tx_remaining) { + rx_content_it = sizeof(fixture->rx_content) - fixture->rx_remaining; + ret = uart_fifo_read(fixture->dev, &fixture->rx_content[rx_content_it], + fixture->rx_remaining); + fixture->rx_remaining -= (size_t)ret; + } + + if (fixture->rx_remaining == 0) { + k_sem_give(&fixture->rx_done_sem); + } +} + +static void uart_emul_isr(const struct device *dev, void *user_data) +{ + struct uart_emul_fixture *fixture = user_data; + + while (uart_irq_update(dev) && uart_irq_is_pending(dev)) { + if (uart_irq_tx_ready(fixture->dev)) { + uart_emul_isr_handle_tx_ready(fixture); + } + if (uart_irq_rx_ready(fixture->dev)) { + uart_emul_isr_handle_rx_ready(fixture); + } + } +} + +ZTEST_F(uart_emul, test_irq_tx) +{ + size_t tx_len; + + uart_irq_callback_user_data_set(fixture->dev, uart_emul_isr, fixture); + /* enabling the tx irq will call the callback, if set */ + uart_irq_tx_enable(fixture->dev); + /* Wait for all data to be received in full */ + zassert_equal(k_sem_take(&fixture->tx_done_sem, K_SECONDS(1)), 0, + "Timeout waiting for UART ISR"); + + tx_len = uart_emul_get_tx_data(fixture->dev, fixture->tx_content, SAMPLE_DATA_SIZE); + zassert_equal(tx_len, SAMPLE_DATA_SIZE, "TX buffer length does not match"); + zassert_mem_equal(fixture->tx_content, fixture->sample_data, SAMPLE_DATA_SIZE); + + /* No more data in TX buffer */ + tx_len = uart_emul_get_tx_data(fixture->dev, fixture->tx_content, + sizeof(fixture->tx_content)); + zassert_equal(tx_len, 0, "TX buffer should be empty"); +} + +ZTEST_F(uart_emul, test_irq_rx) +{ + int rc; + + uart_irq_callback_user_data_set(fixture->dev, uart_emul_isr, fixture); + uart_irq_rx_enable(fixture->dev); + + /* putting rx data will call the irq callback, if enabled */ + uart_emul_put_rx_data(fixture->dev, fixture->sample_data, SAMPLE_DATA_SIZE); + + /* Wait for all data to be received in full */ + zassert_equal(k_sem_take(&fixture->rx_done_sem, K_SECONDS(1)), 0, + "Timeout waiting for UART ISR"); + + zassert_mem_equal(fixture->rx_content, fixture->sample_data, SAMPLE_DATA_SIZE); /* No more data in RX buffer */ - rc = uart_poll_in(fixture->dev, &rx_content[0]); + rc = uart_poll_in(fixture->dev, &fixture->rx_content[0]); zassert_equal(rc, -1, "RX buffer should be empty"); + + uart_irq_rx_disable(fixture->dev); } ZTEST_SUITE(uart_emul, NULL, uart_emul_setup, uart_emul_before, NULL, NULL); diff --git a/tests/drivers/uart/uart_emul/testcase.yaml b/tests/drivers/uart/uart_emul/testcase.yaml index 087a3408415..68838e56a36 100644 --- a/tests/drivers/uart/uart_emul/testcase.yaml +++ b/tests/drivers/uart/uart_emul/testcase.yaml @@ -3,7 +3,6 @@ common: - drivers - uart harness: ztest - depends_on: uart_emul tests: - drivers.uart_emul.polling: + drivers.uart.emul.polling: platform_allow: qemu_x86 diff --git a/tests/drivers/uart/uart_mix_fifo_poll/prj.conf b/tests/drivers/uart/uart_mix_fifo_poll/prj.conf index ec19f1d90b5..fa22b3a47b8 100644 --- a/tests/drivers/uart/uart_mix_fifo_poll/prj.conf +++ b/tests/drivers/uart/uart_mix_fifo_poll/prj.conf @@ -1,6 +1,5 @@ CONFIG_SERIAL=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y CONFIG_ZTEST_THREAD_PRIORITY=5 CONFIG_MAIN_STACK_SIZE=2048 diff --git a/tests/drivers/uart/uart_mix_fifo_poll/src/main.c b/tests/drivers/uart/uart_mix_fifo_poll/src/main.c index f26cce740c0..a080945a067 100644 --- a/tests/drivers/uart/uart_mix_fifo_poll/src/main.c +++ b/tests/drivers/uart/uart_mix_fifo_poll/src/main.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include /* RX and TX pins have to be connected together*/ #if DT_NODE_EXISTS(DT_NODELABEL(dut)) diff --git a/tests/drivers/uart/uart_pm/prj.conf b/tests/drivers/uart/uart_pm/prj.conf index fbd77228aa2..81baa4cf552 100644 --- a/tests/drivers/uart/uart_pm/prj.conf +++ b/tests/drivers/uart/uart_pm/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SERIAL=y CONFIG_NATIVE_UART_0_ON_STDINOUT=y CONFIG_PM=y diff --git a/tests/drivers/udc/prj.conf b/tests/drivers/udc/prj.conf index 8d4e846b181..e57264e1a24 100644 --- a/tests/drivers/udc/prj.conf +++ b/tests/drivers/udc/prj.conf @@ -3,7 +3,6 @@ CONFIG_LOG=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_UDC_DRIVER=y CONFIG_UDC_BUF_COUNT=32 diff --git a/tests/drivers/udc/src/main.c b/tests/drivers/udc/src/main.c index 43ff416f2aa..24e1eb4d1f2 100644 --- a/tests/drivers/udc/src/main.c +++ b/tests/drivers/udc/src/main.c @@ -46,8 +46,12 @@ static void event_ep_request(const struct device *dev, struct udc_event event) } } -static void test_udc_thread(const struct device *dev) +static void test_udc_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; struct udc_event event; while (true) { @@ -423,7 +427,7 @@ static void *test_udc_device_get(void) k_thread_create(&test_udc_thread_data, test_udc_stack, K_KERNEL_STACK_SIZEOF(test_udc_stack), - (k_thread_entry_t)test_udc_thread, + test_udc_thread, (void *)dev, NULL, NULL, K_PRIO_COOP(9), 0, K_NO_WAIT); diff --git a/tests/drivers/udc/testcase.yaml b/tests/drivers/udc/testcase.yaml index 0379e3de615..97b644d6d8c 100644 --- a/tests/drivers/udc/testcase.yaml +++ b/tests/drivers/udc/testcase.yaml @@ -1,5 +1,5 @@ tests: - drivers.udc: + drivers.usb.udc: tags: - usb - drivers diff --git a/tests/drivers/virtualization/ivshmem/plain/prj.conf b/tests/drivers/virtualization/ivshmem/plain/prj.conf index 208db061ed3..f3553216f5f 100644 --- a/tests/drivers/virtualization/ivshmem/plain/prj.conf +++ b/tests/drivers/virtualization/ivshmem/plain/prj.conf @@ -2,7 +2,6 @@ CONFIG_STACK_CANARIES=n CONFIG_INIT_STACKS=y CONFIG_TEST_USERSPACE=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y CONFIG_PCIE=y diff --git a/tests/drivers/virtualization/ivshmem/plain/src/ivshmem.c b/tests/drivers/virtualization/ivshmem/plain/src/ivshmem.c index f2da2d0b803..97c540012f6 100644 --- a/tests/drivers/virtualization/ivshmem/plain/src/ivshmem.c +++ b/tests/drivers/virtualization/ivshmem/plain/src/ivshmem.c @@ -48,15 +48,19 @@ ZTEST(ivshmem, test_ivshmem_plain) "registering handlers should not be supported"); } -static void test_is_usermode(void) +static void test_is_usermode(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + zassert_true(k_is_user_context(), "thread left in kernel mode"); } ZTEST(ivshmem, test_quit_kernel) { #ifdef CONFIG_USERSPACE - k_thread_user_mode_enter((k_thread_entry_t)test_is_usermode, + k_thread_user_mode_enter(test_is_usermode, NULL, NULL, NULL); #else ztest_test_skip(); diff --git a/tests/drivers/virtualization/ivshmem/plain/testcase.yaml b/tests/drivers/virtualization/ivshmem/plain/testcase.yaml index 37208f9367f..26330e1b133 100644 --- a/tests/drivers/virtualization/ivshmem/plain/testcase.yaml +++ b/tests/drivers/virtualization/ivshmem/plain/testcase.yaml @@ -1,5 +1,5 @@ tests: - virtualization.ivshmem: + drivers.virtualization.ivshmem: arch_allow: - x86 - arm64 diff --git a/tests/drivers/w1/w1_api/prj.conf b/tests/drivers/w1/w1_api/prj.conf index d1c628b0bc7..44a7057de64 100644 --- a/tests/drivers/w1/w1_api/prj.conf +++ b/tests/drivers/w1/w1_api/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_W1=y CONFIG_TEST_USERSPACE=y diff --git a/tests/drivers/watchdog/wdt_basic_api/boards/up_squared_pro_7000.overlay b/tests/drivers/watchdog/wdt_basic_api/boards/up_squared_pro_7000.overlay new file mode 100644 index 00000000000..660b55c0512 --- /dev/null +++ b/tests/drivers/watchdog/wdt_basic_api/boards/up_squared_pro_7000.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&tco_wdt { + status = "okay"; +}; diff --git a/tests/drivers/watchdog/wdt_basic_api/boards/xmc45_relax_kit.overlay b/tests/drivers/watchdog/wdt_basic_api/boards/xmc45_relax_kit.overlay new file mode 100644 index 00000000000..44cc7a91cda --- /dev/null +++ b/tests/drivers/watchdog/wdt_basic_api/boards/xmc45_relax_kit.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2023 SLB + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&wdt0 { + status = "okay"; +}; diff --git a/tests/drivers/watchdog/wdt_basic_api/boards/xmc47_relax_kit.overlay b/tests/drivers/watchdog/wdt_basic_api/boards/xmc47_relax_kit.overlay new file mode 100644 index 00000000000..44cc7a91cda --- /dev/null +++ b/tests/drivers/watchdog/wdt_basic_api/boards/xmc47_relax_kit.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2023 SLB + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&wdt0 { + status = "okay"; +}; diff --git a/tests/drivers/watchdog/wdt_basic_api/prj.conf b/tests/drivers/watchdog/wdt_basic_api/prj.conf index 4954b4358b0..fe10038e334 100644 --- a/tests/drivers/watchdog/wdt_basic_api/prj.conf +++ b/tests/drivers/watchdog/wdt_basic_api/prj.conf @@ -1,5 +1,4 @@ CONFIG_WATCHDOG=y CONFIG_WDT_DISABLE_AT_BOOT=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_BOOT_BANNER=n diff --git a/tests/drivers/watchdog/wdt_basic_api/testcase.yaml b/tests/drivers/watchdog/wdt_basic_api/testcase.yaml index 4ea568ca15e..a2f8ea97f1f 100644 --- a/tests/drivers/watchdog/wdt_basic_api/testcase.yaml +++ b/tests/drivers/watchdog/wdt_basic_api/testcase.yaml @@ -14,6 +14,8 @@ tests: - mec15xxevb_assy6853 - s32z270dc2_rtu0_r52 - s32z270dc2_rtu1_r52 + - s32z270dc2_rtu0_r52@D + - s32z270dc2_rtu1_r52@D drivers.watchdog.stm32wwdg: filter: dt_compat_enabled("st,stm32-window-watchdog") or dt_compat_enabled("st,stm32-watchdog") extra_args: DTC_OVERLAY_FILE="boards/stm32_wwdg.overlay" @@ -112,11 +114,14 @@ tests: - longan_nano integration_platforms: - gd32e103v_eval - drivers.watchdog.s32z270dc2_r52: + drivers.watchdog.nxp_s32: build_only: true platform_allow: - s32z270dc2_rtu0_r52 - s32z270dc2_rtu1_r52 + - s32z270dc2_rtu0_r52@D + - s32z270dc2_rtu1_r52@D + - mr_canhubk3 drivers.watchdog.mimxrt1050_evk_ti_tps382x: filter: dt_compat_enabled("ti,tps382x") platform_allow: mimxrt1050_evk diff --git a/tests/drivers/watchdog/wdt_basic_reset_none/prj.conf b/tests/drivers/watchdog/wdt_basic_reset_none/prj.conf index d4844704878..df54d156dc7 100644 --- a/tests/drivers/watchdog/wdt_basic_reset_none/prj.conf +++ b/tests/drivers/watchdog/wdt_basic_reset_none/prj.conf @@ -2,5 +2,4 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_WATCHDOG=y diff --git a/tests/drivers/watchdog/wdt_basic_reset_none/testcase.yaml b/tests/drivers/watchdog/wdt_basic_reset_none/testcase.yaml index 0096842c2ec..0290edbafc1 100644 --- a/tests/drivers/watchdog/wdt_basic_reset_none/testcase.yaml +++ b/tests/drivers/watchdog/wdt_basic_reset_none/testcase.yaml @@ -6,6 +6,8 @@ tests: platform_allow: - s32z270dc2_rtu0_r52 - s32z270dc2_rtu1_r52 + - s32z270dc2_rtu0_r52@D + - s32z270dc2_rtu1_r52@D tags: - drivers - watchdog diff --git a/tests/kconfig/configdefault/CMakeLists.txt b/tests/kconfig/configdefault/CMakeLists.txt new file mode 100644 index 00000000000..93e45bf9ce9 --- /dev/null +++ b/tests/kconfig/configdefault/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(kconfig_configdefault) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/kconfig/configdefault/Kconfig b/tests/kconfig/configdefault/Kconfig new file mode 100644 index 00000000000..7c19c642bbe --- /dev/null +++ b/tests/kconfig/configdefault/Kconfig @@ -0,0 +1,259 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2022 CSIRO + +config DEP_Y + bool "Dependency that evaluates to enabled" + default y + +config DEP_N + bool "Dependency that evaluates to disabled" + default n + +# configdefault after main def +config SYM_Y_1 + bool "SYM Y 1" + +configdefault SYM_Y_1 + default y if DEP_Y + +config SYM_N_1 + bool "SYM N 1" + +configdefault SYM_N_1 + default y if DEP_N + +# configdefault before main def +configdefault SYM_Y_2 + default y if DEP_Y + +config SYM_Y_2 + bool "SYM Y 2" + +configdefault SYM_N_2 + default y if DEP_N + +config SYM_N_2 + bool "SYM N 2" + +# configdefaults with multiple defaults +configdefault SYM_Y_3 + default y if DEP_Y + default y if DEP_N + +config SYM_Y_3 + bool "SYM Y 3" + +configdefault SYM_N_3 + default y if DEP_N + default y if DEP_N + +config SYM_N_3 + bool "SYM N 3" + +# multiple configdefaults +configdefault SYM_Y_4 + default y if DEP_Y +configdefault SYM_Y_4 + default y if DEP_N + +config SYM_Y_4 + bool "SYM Y 4" + +configdefault SYM_N_4 + default y if DEP_N +configdefault SYM_N_4 + default y if DEP_N + +config SYM_N_4 + bool "SYM N 4" + +# if surrounding configdefault +config SYM_Y_5 + bool "SYM Y 5" +if DEP_Y +configdefault SYM_Y_5 + default y +endif + +config SYM_N_5 + bool "SYM N 5" +if DEP_N +configdefault SYM_N_5 + default y +endif + +# if surrounding definition +if DEP_Y +config SYM_Y_6 + bool "SYM Y 6" +endif + +configdefault SYM_Y_6 + default y + +if DEP_N +config SYM_N_6 + bool "SYM N 6" +endif + +configdefault SYM_N_6 + default y + +# if surrounding complete +if DEP_Y +config SYM_Y_7 + bool "SYM Y 7" +configdefault SYM_Y_7 + default y +endif + +if DEP_N +config SYM_N_7 + bool "SYM N 7" +configdefault SYM_N_7 + default y +endif + +# configdefault default symbol +config SYM_Y_8 + bool "SYM Y 8" + +configdefault SYM_Y_8 + default DEP_Y + +config SYM_N_8 + bool "SYM N 8" + +configdefault SYM_N_8 + default DEP_N + +# configdefault with "prompt if " +configdefault SYM_Y_9 + default y + +config SYM_Y_9 + bool "SYM Y 9" if DEP_Y + default y if DEP_N + +configdefault SYM_N_9 + default n if DEP_Y + +config SYM_N_9 + bool "SYM N 9" if DEP_Y + default y + +# configdefault with "prompt if " +configdefault SYM_Y_10 + default y if DEP_Y + +config SYM_Y_10 + bool "SYM Y 10" if DEP_N + +configdefault SYM_N_10 + default n if DEP_Y + +config SYM_N_10 + bool "SYM N 10" if DEP_N + default y + +# configdefault with "prompt if " and surrounding 'if' +configdefault SYM_Y_11 + default y + +if DEP_Y +config SYM_Y_11 + bool "SYM Y 11" if DEP_Y + default y if DEP_N +endif + +configdefault SYM_N_11 + default y + +if DEP_N +config SYM_N_11 + bool "SYM N 11" if DEP_Y + default n if DEP_N +endif + +# Multiple symbols, no configdefault effect +configdefault SYM_Y_12 + default y if DEP_N + +config SYM_Y_12 + bool "SYM Y 12" + default y if DEP_N + depends on DEP_N + +config SYM_Y_12 + default y + +configdefault SYM_N_12 + default y if DEP_N + +config SYM_N_12 + bool "SYM N 12" + default y if DEP_N + +config SYM_N_12 + default n + +# configdefault does not define integer +config SYM_INT_UNDEF + int "Undefined integer" + default 0 + depends on DEP_N + +configdefault SYM_INT_UNDEF + default 1 + +# Integer default +config SYM_INT_1 + int "Int 1" + depends on DEP_Y + +configdefault SYM_INT_1 + default 1 + +# configdefault doesn't overwrite ordering +config SYM_INT_2 + int "Int 2" + default 2 + +configdefault SYM_INT_2 + default 3 + +configdefault SYM_INT_3 + default 3 + +configdefault SYM_INT_3 + default 4 + +config SYM_INT_3 + int "Int 3" + default 2 + +configdefault SYM_INT_4 + default 3 if DEP_N + +configdefault SYM_INT_4 + default 4 + +config SYM_INT_4 + int "Int 4" + default 2 + +# Hex value +configdefault SYM_HEX_20 + default 0x20 + +config SYM_HEX_20 + hex "Hex 0x20" + +# String value +configdefault SYM_STRING + default "TEST" + +config SYM_STRING + string "Hex 0x20" + +source "Kconfig.zephyr" diff --git a/tests/kconfig/configdefault/prj.conf b/tests/kconfig/configdefault/prj.conf new file mode 100644 index 00000000000..9467c292689 --- /dev/null +++ b/tests/kconfig/configdefault/prj.conf @@ -0,0 +1 @@ +CONFIG_ZTEST=y diff --git a/tests/kconfig/configdefault/src/main.c b/tests/kconfig/configdefault/src/main.c new file mode 100644 index 00000000000..abff0c54671 --- /dev/null +++ b/tests/kconfig/configdefault/src/main.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022 CSIRO + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +ZTEST_SUITE(test_configdefault, NULL, NULL, NULL, NULL, NULL); + +ZTEST(test_configdefault, test_expectedvalues) +{ + zassert_true(IS_ENABLED(CONFIG_DEP_Y), ""); + zassert_false(IS_ENABLED(CONFIG_DEP_N), ""); + + zassert_true(IS_ENABLED(CONFIG_SYM_Y_1), ""); + zassert_true(IS_ENABLED(CONFIG_SYM_Y_2), ""); + zassert_true(IS_ENABLED(CONFIG_SYM_Y_3), ""); + zassert_true(IS_ENABLED(CONFIG_SYM_Y_4), ""); + zassert_true(IS_ENABLED(CONFIG_SYM_Y_5), ""); + zassert_true(IS_ENABLED(CONFIG_SYM_Y_6), ""); + zassert_true(IS_ENABLED(CONFIG_SYM_Y_7), ""); + zassert_true(IS_ENABLED(CONFIG_SYM_Y_8), ""); + zassert_true(IS_ENABLED(CONFIG_SYM_Y_9), ""); + zassert_true(IS_ENABLED(CONFIG_SYM_Y_10), ""); + zassert_true(IS_ENABLED(CONFIG_SYM_Y_11), ""); + zassert_true(IS_ENABLED(CONFIG_SYM_Y_12), ""); + + zassert_false(IS_ENABLED(CONFIG_SYM_N_1), ""); + zassert_false(IS_ENABLED(CONFIG_SYM_N_2), ""); + zassert_false(IS_ENABLED(CONFIG_SYM_N_3), ""); + zassert_false(IS_ENABLED(CONFIG_SYM_N_4), ""); + zassert_false(IS_ENABLED(CONFIG_SYM_N_5), ""); + zassert_false(IS_ENABLED(CONFIG_SYM_N_6), ""); + zassert_false(IS_ENABLED(CONFIG_SYM_N_7), ""); + zassert_false(IS_ENABLED(CONFIG_SYM_N_8), ""); + zassert_false(IS_ENABLED(CONFIG_SYM_N_9), ""); + zassert_false(IS_ENABLED(CONFIG_SYM_N_10), ""); + zassert_false(IS_ENABLED(CONFIG_SYM_N_11), ""); + zassert_false(IS_ENABLED(CONFIG_SYM_N_12), ""); + + zassert_false(IS_ENABLED(CONFIG_SYM_INT_UNDEF), ""); + zassert_equal(1, CONFIG_SYM_INT_1, ""); + zassert_equal(2, CONFIG_SYM_INT_2, ""); + zassert_equal(3, CONFIG_SYM_INT_3, ""); + zassert_equal(4, CONFIG_SYM_INT_4, ""); + + zassert_equal(0x20, CONFIG_SYM_HEX_20, ""); + zassert_mem_equal("TEST", CONFIG_SYM_STRING, strlen("TEST"), ""); +} diff --git a/tests/kconfig/configdefault/testcase.yaml b/tests/kconfig/configdefault/testcase.yaml new file mode 100644 index 00000000000..dcf193ec001 --- /dev/null +++ b/tests/kconfig/configdefault/testcase.yaml @@ -0,0 +1,3 @@ +tests: + kconfig.configdefault: + tags: kconfig diff --git a/tests/kernel/cache/prj.conf b/tests/kernel/cache/prj.conf index 3971afe4e55..e39776e7067 100644 --- a/tests/kernel/cache/prj.conf +++ b/tests/kernel/cache/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y diff --git a/tests/kernel/common/prj.conf b/tests/kernel/common/prj.conf index a31c6961785..eb2a4d4ccd8 100644 --- a/tests/kernel/common/prj.conf +++ b/tests/kernel/common/prj.conf @@ -6,4 +6,3 @@ CONFIG_BOOT_DELAY=500 CONFIG_IRQ_OFFLOAD=y CONFIG_TEST_USERSPACE=y CONFIG_BOUNDS_CHECK_BYPASS_MITIGATION=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/common/src/atomic.c b/tests/kernel/common/src/atomic.c index 02b97fb1e85..af5273ed25b 100644 --- a/tests/kernel/common/src/atomic.c +++ b/tests/kernel/common/src/atomic.c @@ -338,6 +338,51 @@ ZTEST(atomic, test_threads_access_atomic) "atomic counting failure"); } +/** + * @brief Checks that the value of atomic_t will be the same in case of overflow + * if incremented in atomic and non-atomic manner + * + * @details According to C standard the value of a signed variable + * is undefined in case of overflow. This test checks that the the value + * of atomic_t will be the same in case of overflow if incremented in atomic + * and non-atomic manner. This allows us to increment an atomic variable + * in a non-atomic manner (as long as it is logically safe) + * and expect its value to match the result of the similar atomic increment. + * + * @ingroup kernel_common_tests + */ +ZTEST(atomic, test_atomic_overflow) +{ + /* Check overflow over max signed value */ + uint64_t overflowed_value = (uint64_t)1 << (ATOMIC_BITS - 1); + atomic_val_t atomic_value = overflowed_value - 1; + atomic_t atomic_var = ATOMIC_INIT(atomic_value); + + atomic_value++; + atomic_inc(&atomic_var); + + zassert_true(atomic_value == atomic_get(&atomic_var), + "max signed overflow mismatch: %lx/%lx", + atomic_value, atomic_get(&atomic_var)); + zassert_true(atomic_value == (atomic_val_t)overflowed_value, + "unexpected value after overflow: %lx, expected: %lx", + atomic_value, (atomic_val_t)overflowed_value); + + /* Check overflow over max unsigned value */ + atomic_value = -1; + atomic_var = ATOMIC_INIT(atomic_value); + + atomic_value++; + atomic_inc(&atomic_var); + + zassert_true(atomic_value == atomic_get(&atomic_var), + "max unsigned overflow mismatch: %lx/%lx", + atomic_value, atomic_get(&atomic_var)); + zassert_true(atomic_value == 0, + "unexpected value after overflow: %lx, expected: 0", + atomic_value); +} + extern void *common_setup(void); ZTEST_SUITE(atomic, NULL, common_setup, NULL, NULL, NULL); /** diff --git a/tests/kernel/common/src/byteorder.c b/tests/kernel/common/src/byteorder.c index 1357c2e6926..8fcda358a7f 100644 --- a/tests/kernel/common/src/byteorder.c +++ b/tests/kernel/common/src/byteorder.c @@ -456,6 +456,69 @@ ZTEST(byteorder, test_sys_put_le64) zassert_mem_equal(tmp, buf, sizeof(uint64_t), "sys_put_le64() failed"); } +/** + * @brief Test sys_uint16_to_array() functionality + * + * @details Test if sys_uint16_to_array() correctly handles endianness. + * + * @see sys_uint16_to_array() + */ +ZTEST(byteorder, test_sys_uint16_to_array) +{ + #define VAL 0xf0e1 + uint8_t tmp[sizeof(uint16_t)] = sys_uint16_to_array(VAL); + uint8_t buf[] = { + COND_CODE_1(CONFIG_LITTLE_ENDIAN, + (0xe1, 0xf0), + (0xf0, 0xe1)) + }; + + zassert_mem_equal(tmp, buf, sizeof(uint16_t), "sys_uint16_to_array() failed"); + #undef VAL +} + +/** + * @brief Test sys_uint32_to_array() functionality + * + * @details Test if sys_uint32_to_array() correctly handles endianness. + * + * @see sys_uint32_to_array() + */ +ZTEST(byteorder, test_sys_uint32_to_array) +{ + #define VAL 0xf0e1d2c3 + uint8_t tmp[sizeof(uint32_t)] = sys_uint32_to_array(VAL); + uint8_t buf[] = { + COND_CODE_1(CONFIG_LITTLE_ENDIAN, + (0xc3, 0xd2, 0xe1, 0xf0), + (0xf0, 0xe1, 0xd2, 0xc3)) + }; + + zassert_mem_equal(tmp, buf, sizeof(uint32_t), "sys_uint32_to_array() failed"); + #undef VAL +} + +/** + * @brief Test sys_uint64_to_array() functionality + * + * @details Test if sys_uint64_to_array() correctly handles endianness. + * + * @see sys_uint64_to_array() + */ +ZTEST(byteorder, test_sys_uint64_to_array) +{ + #define VAL 0xf0e1d2c3b4a59687 + uint8_t tmp[sizeof(uint64_t)] = sys_uint64_to_array(VAL); + uint8_t buf[] = { + COND_CODE_1(CONFIG_LITTLE_ENDIAN, + (0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1, 0xf0), + (0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87)) + }; + + zassert_mem_equal(tmp, buf, sizeof(uint64_t), "sys_uint64_to_array() failed"); + #undef VAL +} + extern void *common_setup(void); ZTEST_SUITE(byteorder, NULL, common_setup, NULL, NULL, NULL); diff --git a/tests/kernel/common/src/printk.c b/tests/kernel/common/src/printk.c index 35e91eb960c..85a0ccbb4d3 100644 --- a/tests/kernel/common/src/printk.c +++ b/tests/kernel/common/src/printk.c @@ -17,16 +17,61 @@ int (*_old_char_out)(int); #if defined(CONFIG_PICOLIBC) +#define ZEPHYR_PICOLIBC_VERSION (__PICOLIBC__ * 10000 + \ + __PICOLIBC_MINOR__ * 100 + \ + __PICOLIBC_PATCHLEVEL__) + +#ifdef CONFIG_PICOLIBC_IO_MINIMAL +/* + * If picolibc is >= 1.8.4, then minimal printf is available. Otherwise, + * we're going to get the floating point version when the minimal one is + * selected. + */ +#if ZEPHYR_PICOLIBC_VERSION >= 10804 +#define HAS_PICOLIBC_IO_MINIMAL +#else +#define HAS_PICOLIBC_IO_FLOAT +#endif +#endif + +#ifdef CONFIG_PICOLIBC_IO_LONG_LONG +/* + * If picolibc is >= 1.8.5, then long long printf is available. Otherwise, + * we're going to get the floating point version when the long long one is + * selected. + */ +#if ZEPHYR_PICOLIBC_VERSION >= 10805 +#define HAS_PICOLIBC_IO_LONG_LONG +#else +#define HAS_PICOLIBC_IO_FLOAT +#endif +#endif + +#ifdef CONFIG_PICOLIBC_IO_FLOAT +#define HAS_PICOLIBC_IO_FLOAT +#endif + /* - * Picolibc long long support is present if the picolibc _WANT_IO_LONG_LONG - * symbol is defined or if the Zephyr configuration has enabled floating - * point support. Note that CONFIG_PICOLIBC_IO_LONG_LONG is only useful - * when using the picolibc module as it cannot affect picolibc included - * with the toolchain + * Picolibc long long support is present if Zephyr configuration has + * enabled long long or floating point support. */ char expected_32[] = "22 113 10000 32768 40000 22\n" "p 112 -10000 -32768 -40000 -22\n" +#if defined(HAS_PICOLIBC_IO_MINIMAL) + "0x1 0x1 0x1 0x1 0x1\n" + "0x1 0x1 0x1 0x1\n" + "42 42 42 42\n" + "-42 -42 -42 -42\n" + "42 42 42 42\n" + "42 42 42 42\n" + "25542abcdef 42\n" +#if defined(_WANT_MINIMAL_IO_LONG_LONG) + "68719476735 -1 18446744073709551615 ffffffffffffffff\n" +#else + "-1 -1 4294967295 ffffffff\n" +#endif +#else "0x1 0x01 0x0001 0x00000001 0x0000000000000001\n" "0x1 0x 1 0x 1 0x 1\n" "42 42 0042 00000042\n" @@ -34,15 +79,26 @@ char expected_32[] = "22 113 10000 32768 40000 22\n" "42 42 42 42\n" "42 42 0042 00000042\n" "255 42 abcdef 42\n" -#if defined(_WANT_IO_LONG_LONG) || defined(CONFIG_PICOLIBC_IO_FLOAT) +#if defined(HAS_PICOLIBC_IO_LONG_LONG) || defined(HAS_PICOLIBC_IO_FLOAT) "68719476735 -1 18446744073709551615 ffffffffffffffff\n" #else "-1 -1 4294967295 ffffffff\n" +#endif #endif "0xcafebabe 0xbeef 0x2a\n" ; + char expected_64[] = "22 113 10000 32768 40000 22\n" "p 112 -10000 -32768 -40000 -22\n" +#if defined(HAS_PICOLIBC_IO_MINIMAL) + "0x1 0x1 0x1 0x1 0x1\n" + "0x1 0x1 0x1 0x1\n" + "42 42 42 42\n" + "-42 -42 -42 -42\n" + "42 42 42 42\n" + "42 42 42 42\n" + "25542abcdef 42\n" +#else "0x1 0x01 0x0001 0x00000001 0x0000000000000001\n" "0x1 0x 1 0x 1 0x 1\n" "42 42 0042 00000042\n" @@ -50,6 +106,7 @@ char expected_64[] = "22 113 10000 32768 40000 22\n" "42 42 42 42\n" "42 42 0042 00000042\n" "255 42 abcdef 42\n" +#endif "68719476735 -1 18446744073709551615 ffffffffffffffff\n" "0xcafebabe 0xbeef 0x2a\n" ; @@ -161,6 +218,8 @@ ZTEST(printk, test_printk) printk("0x%x %p %-2p\n", hex, ptr, (char *)42); pk_console[pos] = '\0'; + __printk_hook_install(_old_char_out); + printk("expected '%s'\n", expected); zassert_true((strcmp(pk_console, expected) == 0), "printk failed"); (void)memset(pk_console, 0, sizeof(pk_console)); diff --git a/tests/kernel/condvar/condvar_api/prj.conf b/tests/kernel/condvar/condvar_api/prj.conf index 3fe44daafe5..13ae16f5400 100644 --- a/tests/kernel/condvar/condvar_api/prj.conf +++ b/tests/kernel/condvar/condvar_api/prj.conf @@ -3,4 +3,3 @@ CONFIG_IRQ_OFFLOAD=y CONFIG_TEST_USERSPACE=y CONFIG_ZTEST_FATAL_HOOK=y CONFIG_MP_MAX_NUM_CPUS=1 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/condvar/condvar_api/src/main.c b/tests/kernel/condvar/condvar_api/src/main.c index 0ce6f36d630..3b422f7d1a6 100644 --- a/tests/kernel/condvar/condvar_api/src/main.c +++ b/tests/kernel/condvar/condvar_api/src/main.c @@ -393,6 +393,10 @@ ZTEST_USER(condvar_tests, test_multiple_condvar_wait_wake) #ifdef CONFIG_USERSPACE static void cond_init_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); k_condvar_init(NULL); @@ -403,7 +407,7 @@ static void cond_init_null(void *p1, void *p2, void *p3) ZTEST_USER(condvar_tests, test_condvar_init_null) { k_tid_t tid = k_thread_create(&condvar_tid, stack_1, STACK_SIZE, - (k_thread_entry_t)cond_init_null, + cond_init_null, NULL, NULL, NULL, K_PRIO_PREEMPT(0), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -420,6 +424,10 @@ ZTEST_USER(condvar_tests, test_condvar_init_null) #ifdef CONFIG_USERSPACE static void cond_signal_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); k_condvar_signal(NULL); @@ -429,6 +437,10 @@ static void cond_signal_null(void *p1, void *p2, void *p3) static void cond_broadcast_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); k_condvar_broadcast(NULL); @@ -438,6 +450,10 @@ static void cond_broadcast_null(void *p1, void *p2, void *p3) static void cond_wait_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); k_condvar_wait(NULL, NULL, K_FOREVER); @@ -448,7 +464,7 @@ static void cond_wait_null(void *p1, void *p2, void *p3) ZTEST_USER(condvar_tests, test_condvar_signal_null) { k_tid_t tid = k_thread_create(&condvar_tid, stack_1, STACK_SIZE, - (k_thread_entry_t)cond_signal_null, + cond_signal_null, NULL, NULL, NULL, K_PRIO_PREEMPT(0), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -457,7 +473,7 @@ ZTEST_USER(condvar_tests, test_condvar_signal_null) ZTEST_USER(condvar_tests, test_condvar_broadcast_null) { k_tid_t tid = k_thread_create(&condvar_tid, stack_1, STACK_SIZE, - (k_thread_entry_t)cond_broadcast_null, + cond_broadcast_null, NULL, NULL, NULL, K_PRIO_PREEMPT(0), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -467,7 +483,7 @@ ZTEST_USER(condvar_tests, test_condvar_broadcast_null) ZTEST_USER(condvar_tests, test_condvar_wait_null) { k_tid_t tid = k_thread_create(&condvar_tid, stack_1, STACK_SIZE, - (k_thread_entry_t)cond_wait_null, + cond_wait_null, NULL, NULL, NULL, K_PRIO_PREEMPT(0), K_USER | K_INHERIT_PERMS, K_NO_WAIT); diff --git a/tests/kernel/context/prj.conf b/tests/kernel/context/prj.conf index 1a2e48f4d80..b138c1a230f 100644 --- a/tests/kernel/context/prj.conf +++ b/tests/kernel/context/prj.conf @@ -4,4 +4,3 @@ CONFIG_ZTEST=y #CONFIG_ZTEST_STACK_SIZE=2048 #CONFIG_IDLE_STACK_SIZE=512 CONFIG_MP_MAX_NUM_CPUS=1 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/device/prj.conf b/tests/kernel/device/prj.conf index bf4d69ece20..4818bf0f5f9 100644 --- a/tests/kernel/device/prj.conf +++ b/tests/kernel/device/prj.conf @@ -2,4 +2,3 @@ CONFIG_ZTEST=y CONFIG_TEST_USERSPACE=y CONFIG_PM_DEVICE=y CONFIG_PM_DEVICE_RUNTIME=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/device/src/main.c b/tests/kernel/device/src/main.c index a3e9430c15a..4c02a52ce94 100644 --- a/tests/kernel/device/src/main.c +++ b/tests/kernel/device/src/main.c @@ -284,9 +284,9 @@ ZTEST(device, test_device_init_level) bool seq_correct = true; /* we check if the stored executing sequence for different level is - * correct, and it should be 1, 2, 3, 4 + * correct, and it should be 1, 2, 3 */ - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 3; i++) { if (init_level_sequence[i] != (i + 1)) { seq_correct = false; } diff --git a/tests/kernel/device/src/test_driver_init.c b/tests/kernel/device/src/test_driver_init.c index e89d6acc7ff..aaca820942f 100644 --- a/tests/kernel/device/src/test_driver_init.c +++ b/tests/kernel/device/src/test_driver_init.c @@ -19,7 +19,6 @@ #define MY_DRIVER_LV_1 "my_driver_level_1" #define MY_DRIVER_LV_2 "my_driver_level_2" #define MY_DRIVER_LV_3 "my_driver_level_3" -#define MY_DRIVER_LV_4 "my_driver_level_4" #define MY_DRIVER_PRI_1 "my_driver_priority_1" #define MY_DRIVER_PRI_2 "my_driver_priority_2" #define MY_DRIVER_PRI_3 "my_driver_priority_3" @@ -28,7 +27,6 @@ #define LEVEL_PRE_KERNEL_1 1 #define LEVEL_PRE_KERNEL_2 2 #define LEVEL_POST_KERNEL 3 -#define LEVEL_APPLICATION 4 #define PRIORITY_1 1 #define PRIORITY_2 2 @@ -37,7 +35,7 @@ /* this is for storing sequence during initialization */ -__pinned_bss int init_level_sequence[4] = {0}; +__pinned_bss int init_level_sequence[3] = {0}; __pinned_bss int init_priority_sequence[4] = {0}; __pinned_bss int init_sub_priority_sequence[3] = {0}; __pinned_bss unsigned int seq_level_cnt; @@ -87,14 +85,6 @@ static int my_driver_lv_3_init(const struct device *dev) return 0; } -static int my_driver_lv_4_init(const struct device *dev) -{ - init_level_sequence[seq_level_cnt] = LEVEL_APPLICATION; - seq_level_cnt++; - - return 0; -} - /* driver init function of testing priority */ static int my_driver_pri_1_init(const struct device *dev) { @@ -173,10 +163,6 @@ DEVICE_DEFINE(my_driver_level_3, MY_DRIVER_LV_3, &my_driver_lv_3_init, NULL, NULL, NULL, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &funcs_my_drivers); -DEVICE_DEFINE(my_driver_level_4, MY_DRIVER_LV_4, &my_driver_lv_4_init, - NULL, NULL, NULL, APPLICATION, - CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &funcs_my_drivers); - /* We use priority value of 20 to create a possible sorting conflict with * priority value of 2. So if the linker sorting isn't working correctly * we'll find out. @@ -201,8 +187,8 @@ DEVICE_DEFINE(my_driver_priority_3, MY_DRIVER_PRI_3, * other in devicetree so that we can validate linker sorting. */ DEVICE_DT_DEFINE(DT_NODELABEL(fakedomain_0), my_driver_sub_pri_0_init, - NULL, NULL, NULL, APPLICATION, 33, NULL); + NULL, NULL, NULL, POST_KERNEL, 33, NULL); DEVICE_DT_DEFINE(DT_NODELABEL(fakedomain_1), my_driver_sub_pri_1_init, - NULL, NULL, NULL, APPLICATION, 33, NULL); + NULL, NULL, NULL, POST_KERNEL, 33, NULL); DEVICE_DT_DEFINE(DT_NODELABEL(fakedomain_2), my_driver_sub_pri_2_init, - NULL, NULL, NULL, APPLICATION, 33, NULL); + NULL, NULL, NULL, POST_KERNEL, 33, NULL); diff --git a/tests/kernel/device/testcase.yaml b/tests/kernel/device/testcase.yaml index 8634e2746ed..40aee98fa57 100644 --- a/tests/kernel/device/testcase.yaml +++ b/tests/kernel/device/testcase.yaml @@ -9,6 +9,7 @@ tests: tags: - kernel - device + platform_exclude: xenvm kernel.device.minimallibc: filter: CONFIG_MINIMAL_LIBC_SUPPORTED tags: @@ -17,10 +18,11 @@ tests: - libc extra_configs: - CONFIG_MINIMAL_LIBC=y + platform_exclude: xenvm kernel.device.pm: tags: - kernel - device - platform_exclude: mec15xxevb_assy6853 + platform_exclude: mec15xxevb_assy6853 xenvm extra_configs: - CONFIG_PM_DEVICE=y diff --git a/tests/kernel/early_sleep/prj.conf b/tests/kernel/early_sleep/prj.conf index a4371f75a4d..dc48ba72008 100644 --- a/tests/kernel/early_sleep/prj.conf +++ b/tests/kernel/early_sleep/prj.conf @@ -1,4 +1,3 @@ CONFIG_IRQ_OFFLOAD=y CONFIG_ZTEST=y CONFIG_MP_MAX_NUM_CPUS=1 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/events/event_api/CMakeLists.txt b/tests/kernel/events/event_api/CMakeLists.txt index 1e43c202fc7..9c0c203380f 100644 --- a/tests/kernel/events/event_api/CMakeLists.txt +++ b/tests/kernel/events/event_api/CMakeLists.txt @@ -6,3 +6,7 @@ project(events_api) FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) + +target_include_directories(app PRIVATE + ${ZEPHYR_BASE}/kernel/include + ) diff --git a/tests/kernel/events/event_api/prj.conf b/tests/kernel/events/event_api/prj.conf index 57c597956a4..43f8d28ad1e 100644 --- a/tests/kernel/events/event_api/prj.conf +++ b/tests/kernel/events/event_api/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y CONFIG_IRQ_OFFLOAD=y CONFIG_EVENTS=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/events/event_api/src/test_event_apis.c b/tests/kernel/events/event_api/src/test_event_apis.c index 275040f508d..a6c81272bcd 100644 --- a/tests/kernel/events/event_api/src/test_event_apis.c +++ b/tests/kernel/events/event_api/src/test_event_apis.c @@ -5,7 +5,7 @@ */ #include -#include +#include #define DELAY K_MSEC(50) #define SHORT_TIMEOUT K_MSEC(100) diff --git a/tests/kernel/events/sys_event/prj.conf b/tests/kernel/events/sys_event/prj.conf index 1e2b887abac..12449507de4 100644 --- a/tests/kernel/events/sys_event/prj.conf +++ b/tests/kernel/events/sys_event/prj.conf @@ -2,4 +2,3 @@ CONFIG_ZTEST=y CONFIG_TEST_USERSPACE=y CONFIG_ZTEST_FATAL_HOOK=y CONFIG_EVENTS=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/events/sys_event/testcase.yaml b/tests/kernel/events/sys_event/testcase.yaml index ebbc06427b6..32e6f91a519 100644 --- a/tests/kernel/events/sys_event/testcase.yaml +++ b/tests/kernel/events/sys_event/testcase.yaml @@ -1,6 +1,8 @@ tests: kernel.events.usage: filter: CONFIG_ARCH_HAS_USERSPACE + arch_exclude: + - posix tags: - kernel - userspace diff --git a/tests/kernel/fatal/exception/prj.conf b/tests/kernel/fatal/exception/prj.conf index 348bab96d49..b06bc82f596 100644 --- a/tests/kernel/fatal/exception/prj.conf +++ b/tests/kernel/fatal/exception/prj.conf @@ -3,4 +3,3 @@ CONFIG_COVERAGE=n CONFIG_TEST_USERSPACE=y CONFIG_APPLICATION_DEFINED_SYSCALL=y CONFIG_MP_MAX_NUM_CPUS=1 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/fatal/exception/prj_arm_fpu_sharing.conf b/tests/kernel/fatal/exception/prj_arm_fpu_sharing.conf index caaba597a6e..b06edc0788b 100644 --- a/tests/kernel/fatal/exception/prj_arm_fpu_sharing.conf +++ b/tests/kernel/fatal/exception/prj_arm_fpu_sharing.conf @@ -5,4 +5,3 @@ CONFIG_ZTEST=y CONFIG_COVERAGE=n CONFIG_TEST_USERSPACE=y CONFIG_APPLICATION_DEFINED_SYSCALL=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/fatal/exception/prj_armv8m_mpu_stack_guard.conf b/tests/kernel/fatal/exception/prj_armv8m_mpu_stack_guard.conf index 167d9c3a144..c8b61ce52f6 100644 --- a/tests/kernel/fatal/exception/prj_armv8m_mpu_stack_guard.conf +++ b/tests/kernel/fatal/exception/prj_armv8m_mpu_stack_guard.conf @@ -4,4 +4,3 @@ CONFIG_TEST_USERSPACE=y CONFIG_APPLICATION_DEFINED_SYSCALL=y CONFIG_BUILTIN_STACK_GUARD=n CONFIG_MPU_STACK_GUARD=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/fatal/exception/protection_no_userspace.conf b/tests/kernel/fatal/exception/protection_no_userspace.conf index 6d333fb999c..ef423fc99da 100644 --- a/tests/kernel/fatal/exception/protection_no_userspace.conf +++ b/tests/kernel/fatal/exception/protection_no_userspace.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y CONFIG_COVERAGE=n CONFIG_TEST_USERSPACE=n -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/fatal/exception/sentinel.conf b/tests/kernel/fatal/exception/sentinel.conf index a875554f246..b4750a403c4 100644 --- a/tests/kernel/fatal/exception/sentinel.conf +++ b/tests/kernel/fatal/exception/sentinel.conf @@ -5,4 +5,3 @@ CONFIG_HW_STACK_PROTECTION=n CONFIG_ZTEST=y CONFIG_COVERAGE=n CONFIG_MP_MAX_NUM_CPUS=1 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/fatal/exception/src/main.c b/tests/kernel/fatal/exception/src/main.c index 51b338183e6..ea4ffaa7c34 100644 --- a/tests/kernel/fatal/exception/src/main.c +++ b/tests/kernel/fatal/exception/src/main.c @@ -13,8 +13,8 @@ #include #if defined(CONFIG_USERSPACE) -#include -#include +#include +#include #include "test_syscalls.h" #endif diff --git a/tests/kernel/fatal/exception/testcase.yaml b/tests/kernel/fatal/exception/testcase.yaml index c325a84166b..0d5b9e46100 100644 --- a/tests/kernel/fatal/exception/testcase.yaml +++ b/tests/kernel/fatal/exception/testcase.yaml @@ -5,6 +5,8 @@ tests: extra_args: CONF_FILE=prj.conf platform_exclude: twr_ke18f filter: CONFIG_ARCH_HAS_STACK_PROTECTION + arch_exclude: + - posix tags: - kernel - userspace @@ -18,6 +20,7 @@ tests: kernel.common.stack_protection_arm_fpu_sharing: extra_args: CONF_FILE=prj_arm_fpu_sharing.conf platform_exclude: twr_ke18f + arch_allow: arm filter: CONFIG_ARCH_HAS_STACK_PROTECTION and CONFIG_ARMV7_M_ARMV8_M_FP tags: - fpu diff --git a/tests/kernel/fatal/no-multithreading/prj.conf b/tests/kernel/fatal/no-multithreading/prj.conf index d981eb1d25e..b9f5efeec95 100644 --- a/tests/kernel/fatal/no-multithreading/prj.conf +++ b/tests/kernel/fatal/no-multithreading/prj.conf @@ -2,4 +2,3 @@ CONFIG_ZTEST=y CONFIG_COVERAGE=n CONFIG_TEST_USERSPACE=n CONFIG_MULTITHREADING=n -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/fifo/fifo_api/prj.conf b/tests/kernel/fifo/fifo_api/prj.conf index 1d97b0e7c43..9a75212e89d 100644 --- a/tests/kernel/fifo/fifo_api/prj.conf +++ b/tests/kernel/fifo/fifo_api/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y CONFIG_IRQ_OFFLOAD=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/fifo/fifo_timeout/prj.conf b/tests/kernel/fifo/fifo_timeout/prj.conf index b45f6f7c6f4..4fb51ffd857 100644 --- a/tests/kernel/fifo/fifo_timeout/prj.conf +++ b/tests/kernel/fifo/fifo_timeout/prj.conf @@ -3,4 +3,3 @@ CONFIG_IRQ_OFFLOAD=y CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_TIMESLICING=n CONFIG_ASSERT_VERBOSE=n -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/fifo/fifo_usage/prj.conf b/tests/kernel/fifo/fifo_usage/prj.conf index a5cc7194765..dfb5d99e39b 100644 --- a/tests/kernel/fifo/fifo_usage/prj.conf +++ b/tests/kernel/fifo/fifo_usage/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y CONFIG_IRQ_OFFLOAD=y CONFIG_MP_MAX_NUM_CPUS=1 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/fpu_sharing/float_disable/prj.conf b/tests/kernel/fpu_sharing/float_disable/prj.conf index fea7fb1f898..10a56920dcd 100644 --- a/tests/kernel/fpu_sharing/float_disable/prj.conf +++ b/tests/kernel/fpu_sharing/float_disable/prj.conf @@ -5,4 +5,3 @@ CONFIG_FPU_SHARING=y CONFIG_CBPRINTF_NANO=y CONFIG_MAIN_STACK_SIZE=1024 CONFIG_MP_MAX_NUM_CPUS=1 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/fpu_sharing/float_disable/prj_x86.conf b/tests/kernel/fpu_sharing/float_disable/prj_x86.conf index 7bc3bc35aed..ed987a5581e 100644 --- a/tests/kernel/fpu_sharing/float_disable/prj_x86.conf +++ b/tests/kernel/fpu_sharing/float_disable/prj_x86.conf @@ -3,4 +3,3 @@ CONFIG_TEST_USERSPACE=y CONFIG_FPU=y CONFIG_FPU_SHARING=y CONFIG_X86_SSE=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/fpu_sharing/float_disable/src/k_float_disable.c b/tests/kernel/fpu_sharing/float_disable/src/k_float_disable.c index fbf02f2682b..c6b4acff46d 100644 --- a/tests/kernel/fpu_sharing/float_disable/src/k_float_disable.c +++ b/tests/kernel/fpu_sharing/float_disable/src/k_float_disable.c @@ -28,8 +28,12 @@ K_THREAD_STACK_DEFINE(usr_fp_thread_stack, STACKSIZE); ZTEST_BMEM static volatile int test_ret = TC_PASS; -static void usr_fp_thread_entry_1(void) +static void usr_fp_thread_entry_1(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + k_yield(); } @@ -39,8 +43,12 @@ static void usr_fp_thread_entry_1(void) #define K_FLOAT_DISABLE_SYSCALL_RETVAL -ENOTSUP #endif -static void usr_fp_thread_entry_2(void) +static void usr_fp_thread_entry_2(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + k_yield(); /* System call to disable FP mode */ @@ -65,7 +73,7 @@ ZTEST(k_float_disable, test_k_float_disable_common) * priority as the current thread. */ k_thread_create(&usr_fp_thread, usr_fp_thread_stack, STACKSIZE, - (k_thread_entry_t)usr_fp_thread_entry_1, NULL, NULL, NULL, + usr_fp_thread_entry_1, NULL, NULL, NULL, PRIORITY, K_USER | K_FP_OPTS, K_NO_WAIT); @@ -114,7 +122,7 @@ ZTEST(k_float_disable, test_k_float_disable_syscall) * FP mode. */ k_thread_create(&usr_fp_thread, usr_fp_thread_stack, STACKSIZE, - (k_thread_entry_t)usr_fp_thread_entry_2, NULL, NULL, NULL, + usr_fp_thread_entry_2, NULL, NULL, NULL, PRIORITY, K_INHERIT_PERMS | K_USER | K_FP_OPTS, K_NO_WAIT); @@ -171,8 +179,12 @@ void arm_test_isr_handler(const void *args) } } -static void sup_fp_thread_entry(void) +static void sup_fp_thread_entry(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + /* Verify K_FP_REGS flag is set */ if ((sup_fp_thread.base.user_options & K_FP_REGS) == 0) { @@ -249,7 +261,7 @@ ZTEST(k_float_disable, test_k_float_disable_irq) * priority as the current thread. */ k_thread_create(&sup_fp_thread, sup_fp_thread_stack, STACKSIZE, - (k_thread_entry_t)sup_fp_thread_entry, NULL, NULL, NULL, + sup_fp_thread_entry, NULL, NULL, NULL, PRIORITY, K_FP_REGS, K_NO_WAIT); diff --git a/tests/kernel/fpu_sharing/generic/prj.conf b/tests/kernel/fpu_sharing/generic/prj.conf index b655c5fef0f..1d88a6850a5 100644 --- a/tests/kernel/fpu_sharing/generic/prj.conf +++ b/tests/kernel/fpu_sharing/generic/prj.conf @@ -4,5 +4,4 @@ CONFIG_FPU_SHARING=y CONFIG_STDOUT_CONSOLE=y CONFIG_CBPRINTF_FP_SUPPORT=y CONFIG_MAIN_STACK_SIZE=2048 -CONFIG_ZTEST_NEW_API=y CONFIG_MP_MAX_NUM_CPUS=1 diff --git a/tests/kernel/fpu_sharing/generic/prj_x86.conf b/tests/kernel/fpu_sharing/generic/prj_x86.conf index f0e2d45ae8c..20c8ab24669 100644 --- a/tests/kernel/fpu_sharing/generic/prj_x86.conf +++ b/tests/kernel/fpu_sharing/generic/prj_x86.conf @@ -3,4 +3,3 @@ CONFIG_FPU=y CONFIG_X86_SSE=y CONFIG_FPU_SHARING=y CONFIG_STDOUT_CONSOLE=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/gen_isr_table/prj.conf b/tests/kernel/gen_isr_table/prj.conf index 02a10f05087..a3f0a41c8d2 100644 --- a/tests/kernel/gen_isr_table/prj.conf +++ b/tests/kernel/gen_isr_table/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y CONFIG_DYNAMIC_INTERRUPTS=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/gen_isr_table/src/main.c b/tests/kernel/gen_isr_table/src/main.c index bdb63d69ec0..c58b866a92e 100644 --- a/tests/kernel/gen_isr_table/src/main.c +++ b/tests/kernel/gen_isr_table/src/main.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include diff --git a/tests/kernel/interrupt/CMakeLists.txt b/tests/kernel/interrupt/CMakeLists.txt index 20851bb5ff4..b464719f89a 100644 --- a/tests/kernel/interrupt/CMakeLists.txt +++ b/tests/kernel/interrupt/CMakeLists.txt @@ -7,6 +7,7 @@ project(interrupt) target_include_directories(app PRIVATE ${ZEPHYR_BASE}/kernel/include ${ZEPHYR_BASE}/arch/${ARCH}/include + ${ZEPHYR_BASE}/arch/common/include ) target_sources(app PRIVATE @@ -17,3 +18,12 @@ target_sources(app PRIVATE target_sources_ifdef(CONFIG_DYNAMIC_INTERRUPTS app PRIVATE src/dynamic_isr.c) target_sources_ifdef(CONFIG_X86 app PRIVATE src/regular_isr.c) +target_sources_ifdef(CONFIG_SHARED_INTERRUPTS app PRIVATE src/static_shared_irq.c) + +if (CONFIG_SHARED_INTERRUPTS) +target_sources_ifdef(CONFIG_DYNAMIC_INTERRUPTS app PRIVATE src/dynamic_shared_irq.c) +endif() + +if(CONFIG_MULTI_LEVEL_INTERRUPTS) + target_sources_ifdef(CONFIG_DYNAMIC_INTERRUPTS app PRIVATE src/sw_isr_table.c) +endif() diff --git a/tests/kernel/interrupt/prj.conf b/tests/kernel/interrupt/prj.conf index 538b1511178..bfddd929c43 100644 --- a/tests/kernel/interrupt/prj.conf +++ b/tests/kernel/interrupt/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_DYNAMIC_INTERRUPTS=y CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_THREAD_STACK_INFO=y diff --git a/tests/kernel/interrupt/src/dynamic_isr.c b/tests/kernel/interrupt/src/dynamic_isr.c index 35f42220fb8..d697fda32e8 100644 --- a/tests/kernel/interrupt/src/dynamic_isr.c +++ b/tests/kernel/interrupt/src/dynamic_isr.c @@ -73,7 +73,7 @@ ZTEST(interrupt_feature, test_isr_dynamic) #define TEST_IRQ_DYN_LINE 5 #endif -void test_isr_dynamic(void) +ZTEST(interrupt_feature, test_isr_dynamic) { int vector_num; @@ -118,5 +118,6 @@ extern const void *x86_irq_args[]; "interrupt triggered but handler has not run(%d)", handler_has_run); + irq_disable(TEST_IRQ_DYN_LINE); } #endif /* CONFIG_GEN_SW_ISR_TABLE */ diff --git a/tests/kernel/interrupt/src/dynamic_shared_irq.c b/tests/kernel/interrupt/src/dynamic_shared_irq.c new file mode 100644 index 00000000000..db7bc1a688c --- /dev/null +++ b/tests/kernel/interrupt/src/dynamic_shared_irq.c @@ -0,0 +1,227 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "test_shared_irq.h" + +struct shared_irq_fixture { + unsigned int irq1; + unsigned int irq2; + unsigned int irq1_table_idx; + unsigned int irq2_table_idx; + unsigned int irq_priority; +}; + +static struct shared_irq_fixture fixture; + +static void reset_test_vector(void) +{ + int i; + + for (i = 0; i < TEST_VECTOR_SIZE; i++) { + test_vector[i] = 0; + } +} + +static void dynamic_shared_irq_suite_after(void *data) +{ + ARG_UNUSED(data); + + /* note: no need to check the state of the SW ISR tables after + * all these disconnect operations. If there's something wrong + * it should be detected by dynamic_shared_irq_suite_before(). + */ + arch_irq_disconnect_dynamic(fixture.irq1, fixture.irq_priority, + test_isr_0, 0, 0); + arch_irq_disconnect_dynamic(fixture.irq1, fixture.irq_priority, + test_isr_1, (void *)1, 0); + arch_irq_disconnect_dynamic(fixture.irq2, fixture.irq_priority, + test_isr_2, (void *)2, 0); +} + +static void dummy_isr(const void *data) +{ + ARG_UNUSED(data); + + test_vector[0] = TEST_DUMMY_ISR_VAL; +} + +static unsigned int get_irq_slot(unsigned int start) +{ + unsigned int i, table_idx; + + for (i = start; i <= CONFIG_GEN_IRQ_START_VECTOR + CONFIG_NUM_IRQS - 1; i++) { + table_idx = i - CONFIG_GEN_IRQ_START_VECTOR; + + if (_sw_isr_table[table_idx].isr == &z_irq_spurious) { + test_vector[0] = 0; + + /* check to see if we can trigger this IRQ */ + arch_irq_connect_dynamic(i, IRQ_PRIORITY, dummy_isr, + NULL, 0); + irq_enable(i); + trigger_irq(i); + + /* wait a bit */ + k_busy_wait(100); + + if (test_vector[0] == TEST_DUMMY_ISR_VAL) { + /* found a valid INTID */ + irq_disable(i); + + arch_irq_disconnect_dynamic(i, IRQ_PRIORITY, + dummy_isr, NULL, 0); + return i; + } + } + } + + return TEST_INVALID_IRQ; +} + +static void *dynamic_shared_irq_suite_setup(void) +{ + fixture.irq1 = get_irq_slot(CONFIG_GEN_IRQ_START_VECTOR); + zassert_true(fixture.irq1 != TEST_INVALID_IRQ, + "no suitable value found for irq1"); + fixture.irq2 = get_irq_slot(fixture.irq1 + 1); + zassert_true(fixture.irq2 != TEST_INVALID_IRQ, + "no suitable value found for irq2"); + fixture.irq_priority = IRQ_PRIORITY; + + fixture.irq1_table_idx = fixture.irq1 - CONFIG_GEN_IRQ_START_VECTOR; + fixture.irq2_table_idx = fixture.irq2 - CONFIG_GEN_IRQ_START_VECTOR; + + return NULL; +} + +static void dynamic_shared_irq_suite_before(void *data) +{ + ARG_UNUSED(data); + + arch_irq_connect_dynamic(fixture.irq1, fixture.irq_priority, + test_isr_0, 0, 0); + + zassert_true(_sw_isr_table[fixture.irq1_table_idx].isr == test_isr_0, + "wrong _sw_isr_table ISR at irq1"); + zassert_true(!_sw_isr_table[fixture.irq1_table_idx].arg, + "wrong _sw_isr_table argument at irq1"); + zassert_true(!z_shared_sw_isr_table[fixture.irq1_table_idx].client_num, + "wrong client number at irq1"); + + arch_irq_connect_dynamic(fixture.irq1, fixture.irq_priority, + test_isr_1, (void *)1, 0); + + zassert_true(_sw_isr_table[fixture.irq1_table_idx].isr == z_shared_isr, + "wrong _sw_isr_table ISR at irq1"); + zassert_true(_sw_isr_table[fixture.irq1_table_idx].arg == + &z_shared_sw_isr_table[fixture.irq1_table_idx], + "wrong _sw_isr_table argument at irq1"); + zassert_true(z_shared_sw_isr_table[fixture.irq1_table_idx].client_num == 2, + "wrong client number at irq1"); + + zassert_true(client_exists_at_index(test_isr_0, 0, fixture.irq1_table_idx, 0), + "unexpected client data for irq1, index 0"); + zassert_true(client_exists_at_index(test_isr_1, (void *)1, fixture.irq1_table_idx, 1), + "unexpected client data for irq1, index 1"); + + arch_irq_connect_dynamic(fixture.irq2, fixture.irq_priority, + test_isr_2, (void *)2, 0); + + zassert_true(_sw_isr_table[fixture.irq2_table_idx].isr == test_isr_2, + "wrong _sw_isr_table ISR at irq2"); + zassert_true(_sw_isr_table[fixture.irq2_table_idx].arg == (void *)2, + "wrong _sw_isr_table argument at irq2"); + zassert_true(!z_shared_sw_isr_table[fixture.irq2_table_idx].client_num, + "wrong client number at irq2"); + + reset_test_vector(); +} + +/** + * @brief Test writing to a vector with a shared interrupt + * + * @ingroup kernel_interrupt_tests + * + * @details This tests if interrupts are dynamically shared successfully + * (i.e: multiple ISR/arg pairs are called whenever the interrupt + * they were registered for is triggered). + */ +ZTEST(shared_irq_feature, test_dynamic_shared_irq_write) +{ + int i; + + irq_enable(fixture.irq1); + irq_enable(fixture.irq2); + + trigger_irq(fixture.irq1); + trigger_irq(fixture.irq2); + + /* wait 5ms before checking the results */ + k_busy_wait(5000); + + for (i = 0; i < TEST_VECTOR_SIZE; i++) { + zassert_true(test_vector[i] == result_vector[i], + "wrong test_vector value at %d: 0x%x vs 0x%x", + i, test_vector[i], result_vector[i]); + } + + irq_disable(fixture.irq1); + irq_disable(fixture.irq2); +} + +/** + * @brief Test writing to a vector after an ISR/arg disconnect. + * + * @ingroup kernel_interrupt_tests + * + * @details This tests if ISR/arg pairs are disconnected successfully + * and the interrupts are "unshared" whenever a single ISR/arg pair is + * left. + */ +ZTEST(shared_irq_feature, test_dynamic_shared_irq_disconnect_write) +{ + int i; + + /* remove test_isr_0/NULL pair. After this statement we expect + * irq1 to be unshared. + */ + arch_irq_disconnect_dynamic(fixture.irq1, fixture.irq_priority, + test_isr_0, 0, 0); + + zassert_true(_sw_isr_table[fixture.irq1_table_idx].isr == test_isr_1, + "wrong _sw_isr_table ISR at irq1"); + zassert_true(_sw_isr_table[fixture.irq1_table_idx].arg == (void *)1, + "wrong _sw_isr_table arg at irq1"); + zassert_true(!z_shared_sw_isr_table[fixture.irq1_table_idx].client_num, + "wrong client number at irq1"); + + irq_enable(fixture.irq1); + trigger_irq(fixture.irq1); + + /* wait 5ms before checking the results */ + k_busy_wait(5000); + + for (i = 0; i < TEST_VECTOR_SIZE; i++) { + if (i == 1) { + zassert_true(test_vector[i] == result_vector[i], + "wrong test_vector at %d: 0x%x vs 0x%x", + i, test_vector[i], result_vector[i]); + continue; + } + + zassert_true(!test_vector[i], + "wrong test_vector value at %d: 0x%x vs 0x%x", + i, test_vector[i], result_vector[i]); + } + + irq_disable(fixture.irq1); +} + +ZTEST_SUITE(shared_irq_feature, NULL, + dynamic_shared_irq_suite_setup, + dynamic_shared_irq_suite_before, + dynamic_shared_irq_suite_after, + NULL); diff --git a/tests/kernel/interrupt/src/interrupt_offload.c b/tests/kernel/interrupt/src/interrupt_offload.c index f025cbc4261..b2ac007c14f 100644 --- a/tests/kernel/interrupt/src/interrupt_offload.c +++ b/tests/kernel/interrupt/src/interrupt_offload.c @@ -7,6 +7,9 @@ #include #include #include +#if defined(CONFIG_ARCH_POSIX) +#include +#endif #define STACK_SIZE 1024 #define NUM_WORK 4 @@ -89,7 +92,11 @@ void isr_handler(const void *param) #define TEST_IRQ_DYN_LINE 26 #elif defined(CONFIG_ARCH_POSIX) -#define TEST_IRQ_DYN_LINE 5 +#if defined(OFFLOAD_SW_IRQ) +#define TEST_IRQ_DYN_LINE OFFLOAD_SW_IRQ +#else +#define TEST_IRQ_DYN_LINE 0 +#endif #else #define TEST_IRQ_DYN_LINE 0 @@ -128,6 +135,10 @@ static void trigger_offload_interrupt(const bool real_irq, void *work) static void t_running(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + k_sem_give(&sync_sem); while (wait_for_end == false) { @@ -182,7 +193,7 @@ static void run_test_offload(int case_type, int real_irq) } k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)t_running, + t_running, NULL, NULL, NULL, thread_prio, K_INHERIT_PERMS, K_NO_WAIT); diff --git a/tests/kernel/interrupt/src/static_shared_irq.c b/tests/kernel/interrupt/src/static_shared_irq.c new file mode 100644 index 00000000000..1a7daeb52f1 --- /dev/null +++ b/tests/kernel/interrupt/src/static_shared_irq.c @@ -0,0 +1,96 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "test_shared_irq.h" + +#define GIC_IRQ1 10 +#define GIC_IRQ2 11 + +/** + * @brief Test writing to a vector using static shared interrupts. + * + * @ingroup kernel_interrupt_tests + * + * @details This tests if interrupts are statically shared successfully + * (i.e: multiple ISR/arg pairs are called whenever the interrupt they + * were registered for is triggered). + */ +ZTEST(interrupt_feature, test_static_shared_irq_write) +{ + /* note: this test is very brittle since it requires that + * the chosen interrupt lines be unused for all of the + * testing platforms. Failing to meet this requirement + * leads to build failures due to the number of clients + * exceeding the limit. Still, it's important to test that + * the static shared interrupts work properly. As such, + * this test shall be restricted to a single platform, thus + * decreasing the risk of build errors appearing due to the + * chosen interrupts being used. + */ +#ifndef CONFIG_BOARD_QEMU_CORTEX_A53 + ztest_test_skip(); +#else + int i; + + IRQ_CONNECT(GIC_IRQ1, IRQ_PRIORITY, test_isr_0, 0, 0); + IRQ_CONNECT(GIC_IRQ1, IRQ_PRIORITY, test_isr_1, (void *)1, 0); + IRQ_CONNECT(GIC_IRQ2, IRQ_PRIORITY, test_isr_2, (void *)2, 0); + + zassert_true(_sw_isr_table[GIC_IRQ1].isr == z_shared_isr, + "wrong _sw_isr_table ISR at GIC_IRQ1"); + zassert_true(_sw_isr_table[GIC_IRQ2].isr == test_isr_2, + "wrong _sw_isr_table ISR at GIC_IRQ1"); + + zassert_true(_sw_isr_table[GIC_IRQ1].arg == + &z_shared_sw_isr_table[GIC_IRQ1], + "wrong _sw_isr_table arg at GIC_IRQ1"); + zassert_true(_sw_isr_table[GIC_IRQ2].arg == (void *)2, + "wrong _sw_isr_table arg at GIC_IRQ2"); + + zassert_true(z_shared_sw_isr_table[GIC_IRQ1].client_num == 2, + "wrong client number for GIC_IRQ1"); + zassert_true(!z_shared_sw_isr_table[GIC_IRQ2].client_num, + "wrong client number for GIC_IRQ2"); + + zassert_true(client_exists_at_index(test_isr_0, 0, GIC_IRQ1, + TEST_INVALID_IDX), + "test_isr_0 not a client for GIC_IRQ1"); + zassert_true(client_exists_at_index(test_isr_1, (void *)1, GIC_IRQ1, + TEST_INVALID_IDX), + "test_isr_1 not a client for GIC_IRQ1"); + + irq_enable(GIC_IRQ1); + irq_enable(GIC_IRQ2); + + trigger_irq(GIC_IRQ1); + trigger_irq(GIC_IRQ2); + + /* wait 5ms before checking the results */ + k_busy_wait(5000); + + for (i = 0; i < TEST_VECTOR_SIZE; i++) { + zassert_true(test_vector[i] == result_vector[i], + "wrong test_vector value at %d: 0x%x vs 0x%x", + i, test_vector[i], result_vector[i]); + } + + irq_disable(GIC_IRQ1); + irq_disable(GIC_IRQ2); + +#ifdef CONFIG_DYNAMIC_INTERRUPTS + /* if dynamic interrupts are enabled this will restore the _sw_isr_table + * entries for GIC_IRQ1 and GIC_IRQ2 to their default values (NULL, + * z_irq_spurious). In turn, this will increase the probability of + * dynamic_shared_irq.c's get_irq_slot() being able to find an available + * slot. + */ + arch_irq_disconnect_dynamic(GIC_IRQ1, IRQ_PRIORITY, test_isr_0, 0, 0); + arch_irq_disconnect_dynamic(GIC_IRQ1, IRQ_PRIORITY, test_isr_1, (void *)1, 0); + arch_irq_disconnect_dynamic(GIC_IRQ2, IRQ_PRIORITY, test_isr_2, (void *)2, 0); +#endif /* CONFIG_DYNAMIC_INTERRUPTS */ + +#endif /* CONFIG_BOARD_QEMU_CORTEX_A53 */ +} diff --git a/tests/kernel/interrupt/src/sw_isr_table.c b/tests/kernel/interrupt/src/sw_isr_table.c new file mode 100644 index 00000000000..385f2c244b5 --- /dev/null +++ b/tests/kernel/interrupt/src/sw_isr_table.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sw_isr_common.h" + +#include + +extern const struct _irq_parent_entry _lvl2_irq_list[]; + +/** + * @brief Test sw_isr_table function + * + * @details Validates that: + * - z_get_sw_isr_device_from_irq() returns the parent interrupt controller for an IRQN + * - z_get_sw_isr_irq_from_device() returns the IRQN of a parent interrupt controller + * - z_get_sw_isr_table_idx() returns the corresponding SW ISR table index for an IRQN + */ +ZTEST(interrupt_feature, test_sw_isr_irq_parent_table) +{ + const struct device *parent_dev; + unsigned int parent_irq; + unsigned int parent_isr_offset; + const struct device *test_dev; + unsigned int test_irq; + unsigned int test_isr_offset; + + for (size_t i = 0; i < CONFIG_NUM_2ND_LEVEL_AGGREGATORS; i++) { + parent_dev = _lvl2_irq_list[i].dev; + parent_irq = _lvl2_irq_list[i].irq; + parent_isr_offset = _lvl2_irq_list[i].offset; + + for (unsigned int local_irq = 0; + local_irq < BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS); local_irq++) { + test_irq = irq_to_level_2(local_irq) | parent_irq; + test_dev = z_get_sw_isr_device_from_irq(test_irq); + zassert_equal_ptr(parent_dev, test_dev, "expected dev: %p, got: %p", + parent_dev, test_dev); + } + + test_irq = z_get_sw_isr_irq_from_device(parent_dev); + zassert_equal(parent_irq, test_irq, "expected offset: %d, got: %d", parent_irq, + test_irq); + + for (unsigned int local_irq = 0; + local_irq < BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS); local_irq++) { + test_irq = irq_to_level_2(local_irq) | parent_irq; + test_isr_offset = z_get_sw_isr_table_idx(test_irq); + zassert_equal(parent_isr_offset + local_irq, test_isr_offset, + "expected offset: %d, got: %d", parent_isr_offset + local_irq, + test_isr_offset); + } + } +} diff --git a/tests/kernel/interrupt/src/test_shared_irq.h b/tests/kernel/interrupt/src/test_shared_irq.h new file mode 100644 index 00000000000..fd3c4c4a624 --- /dev/null +++ b/tests/kernel/interrupt/src/test_shared_irq.h @@ -0,0 +1,69 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __TEST_SHARED_IRQ_H__ +#define __TEST_SHARED_IRQ_H__ + +#include +#include + +#define IRQ_PRIORITY 1 +#define TEST_VECTOR_SIZE 10 +#define TEST_INVALID_IDX 0xcafebabe +#define TEST_DUMMY_ISR_VAL 0xdeadbeef +#define TEST_INVALID_IRQ 0xcafebabe + +#define ISR_DEFINE(name) \ +static inline void name(const void *data) \ +{ \ + int idx = POINTER_TO_INT(data); \ + test_vector[idx] = result_vector[idx]; \ +} \ + +static uint32_t test_vector[TEST_VECTOR_SIZE] = { +}; + +static uint32_t result_vector[TEST_VECTOR_SIZE] = { + 0xdeadbeef, + 0xcafebabe, + 0x1234cafe, +}; + +ISR_DEFINE(test_isr_0); +ISR_DEFINE(test_isr_1); +ISR_DEFINE(test_isr_2); + +static inline bool client_exists_at_index(void (*routine)(const void *arg), + void *arg, int irq, size_t idx) +{ + size_t i; + struct z_shared_isr_table_entry *shared_entry; + struct z_shared_isr_client *client; + + shared_entry = &z_shared_sw_isr_table[irq]; + + if (idx == TEST_INVALID_IDX) { + for (i = 0; i < shared_entry->client_num; i++) { + client = &shared_entry->clients[i]; + + if (client->isr == routine && client->arg == arg) { + return true; + } + } + } else { + if (shared_entry->client_num <= idx) { + return false; + } + + client = &shared_entry->clients[idx]; + + return client->isr == routine && client->arg == arg; + } + + return false; +} + +#endif /* __TEST_SHARED_IRQ_H__ */ diff --git a/tests/kernel/interrupt/testcase.yaml b/tests/kernel/interrupt/testcase.yaml index bdec3a794ee..cbe58c65e47 100644 --- a/tests/kernel/interrupt/testcase.yaml +++ b/tests/kernel/interrupt/testcase.yaml @@ -36,3 +36,19 @@ tests: extra_configs: - CONFIG_QEMU_ICOUNT=y - CONFIG_MINIMAL_LIBC=y + arch.shared_interrupt: + # excluded because of failures during test_prevent_interruption + platform_exclude: qemu_cortex_m0 + arch_exclude: + # same as above, #22956 + - nios2 + # test needs 2 working interrupt lines + - xtensa + # TODO: make test work on this arch + - mips + tags: + - kernel + - interrupt + extra_configs: + - CONFIG_SHARED_INTERRUPTS=y + filter: not CONFIG_TRUSTED_EXECUTION_NONSECURE diff --git a/tests/kernel/lifo/lifo_api/prj.conf b/tests/kernel/lifo/lifo_api/prj.conf index 1d97b0e7c43..9a75212e89d 100644 --- a/tests/kernel/lifo/lifo_api/prj.conf +++ b/tests/kernel/lifo/lifo_api/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y CONFIG_IRQ_OFFLOAD=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/lifo/lifo_usage/prj.conf b/tests/kernel/lifo/lifo_usage/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/kernel/lifo/lifo_usage/prj.conf +++ b/tests/kernel/lifo/lifo_usage/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/mbox/mbox_api/prj.conf b/tests/kernel/mbox/mbox_api/prj.conf index eda7ea93a01..bc5762b0edd 100644 --- a/tests/kernel/mbox/mbox_api/prj.conf +++ b/tests/kernel/mbox/mbox_api/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NUM_MBOX_ASYNC_MSGS=5 CONFIG_MP_MAX_NUM_CPUS=1 diff --git a/tests/kernel/mbox/mbox_api/src/test_mbox_api.c b/tests/kernel/mbox/mbox_api/src/test_mbox_api.c index c2e192819b9..e0268ea96e6 100644 --- a/tests/kernel/mbox/mbox_api/src/test_mbox_api.c +++ b/tests/kernel/mbox/mbox_api/src/test_mbox_api.c @@ -30,10 +30,9 @@ static struct k_mbox mbox; static k_tid_t sender_tid, receiver_tid, random_tid; static K_THREAD_STACK_DEFINE(tstack, STACK_SIZE); -static K_THREAD_STACK_DEFINE(rtstack, STACK_SIZE); static K_THREAD_STACK_DEFINE(tstack_1, STACK_SIZE); static K_THREAD_STACK_ARRAY_DEFINE(waiting_get_stack, 5, STACK_SIZE); -static struct k_thread tdata, rtdata, async_tid, waiting_get_tid[5]; +static struct k_thread tdata, async_tid, waiting_get_tid[5]; static struct k_sem end_sema, sync_sema; @@ -164,7 +163,6 @@ static void tmbox_put(struct k_mbox *pmbox) /* Get a msg and dispose it by making the size = 0 */ mmsg.size = 0; mmsg.tx_data = data[1]; - mmsg.tx_block.data = NULL; mmsg.tx_target_thread = K_ANY; zassert_true(k_mbox_put(pmbox, &mmsg, K_FOREVER) == 0); break; @@ -432,122 +430,6 @@ ZTEST(mbox_api, test_mbox_kdefine) tmbox(&kmbox); } -static void thread_mbox_data_get_null(void *p1, void *p2, void *p3) -{ - struct k_mbox_msg get_msg = {0}; - char str_data[] = "it string for get msg test"; - - get_msg.size = 16; - get_msg.rx_source_thread = K_ANY; - get_msg.tx_block.data = str_data; - get_msg._syncing_thread = NULL; - - k_mbox_data_get(&get_msg, NULL); - k_sem_give(&end_sema); -} - -/** - * - * @brief Test k_mbox_data_get() API - * - * @details - * - Init a mbox and just invoke k_mbox_data_get() with different - * input to check robust of API. - * - * @see k_mbox_data_get() - * - * @ingroup kernel_mbox_api - */ -ZTEST(mbox_api, test_mbox_data_get_null) -{ - k_sem_reset(&end_sema); - - receiver_tid = k_thread_create(&tdata, tstack, STACK_SIZE, - thread_mbox_data_get_null, - NULL, NULL, NULL, - K_PRIO_PREEMPT(0), 0, - K_NO_WAIT); - k_sem_take(&end_sema, K_FOREVER); - /*test case teardown*/ - k_thread_abort(receiver_tid); -} - -static void thread_mbox_get_block_data(void *p1, void *p2, void *p3) -{ - k_sem_take(&sync_sema, K_FOREVER); - struct k_mbox_msg bdmsg = {0}; - - bdmsg.size = MAIL_LEN; - bdmsg.rx_source_thread = sender_tid; - bdmsg.tx_target_thread = receiver_tid; - bdmsg.tx_data = NULL; - bdmsg.tx_block.data = data; - bdmsg.tx_data = data; - - zassert_equal(k_mbox_get((struct k_mbox *)p1, &bdmsg, p2, K_FOREVER), - 0, NULL); - - k_sem_give(&end_sema); -} - -/* give a block data to API k_mbox_async_put */ -static void thread_mbox_put_block_data(void *p1, void *p2, void *p3) -{ - struct k_mbox_msg put_msg = {0}; - - put_msg.size = MAIL_LEN; - put_msg.tx_data = NULL; - put_msg.tx_block.data = p2; - put_msg.tx_target_thread = receiver_tid; - put_msg.rx_source_thread = sender_tid; - - k_mbox_async_put((struct k_mbox *)p1, &put_msg, NULL); -} - -/** - * - * @brief Test put and get mailbox with block data - * - * @details - * - Create two threads to put and get block data with - * specify thread ID and K_FOREVER for each other. - * - Check the result after finished exchange. - * - * @see k_mbox_init() k_mbox_async_put() k_mbox_get() - * - * @ingroup kernel_mbox_api - */ -ZTEST(mbox_api, test_mbox_get_put_block_data) -{ - struct k_mbox bdmbox; - /*test case setup*/ - k_sem_reset(&end_sema); - k_sem_reset(&sync_sema); - k_mbox_init(&bdmbox); - char buff[MAIL_LEN]; - char data_put[] = "mbox put data"; - - /**TESTPOINT: thread-thread data passing via mbox*/ - sender_tid = k_current_get(); - receiver_tid = k_thread_create(&rtdata, rtstack, STACK_SIZE, - thread_mbox_get_block_data, - &bdmbox, buff, NULL, - K_PRIO_PREEMPT(0), 0, K_NO_WAIT); - - sender_tid = k_thread_create(&tdata, tstack, STACK_SIZE, - thread_mbox_put_block_data, - &bdmbox, data_put, NULL, - K_PRIO_PREEMPT(0), 0, K_NO_WAIT); - k_sem_give(&sync_sema); - k_sem_take(&end_sema, K_FOREVER); - /*abort receiver thread*/ - k_thread_abort(receiver_tid); - k_thread_abort(sender_tid); - - zassert_equal(memcmp(buff, data_put, sizeof(data_put)), 0, - NULL); -} - static ZTEST_BMEM char __aligned(4) buffer[8]; /** diff --git a/tests/kernel/mbox/mbox_usage/prj.conf b/tests/kernel/mbox/mbox_usage/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/kernel/mbox/mbox_usage/prj.conf +++ b/tests/kernel/mbox/mbox_usage/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/mbox/mbox_usage/src/main.c b/tests/kernel/mbox/mbox_usage/src/main.c index 10b95df3a2c..e472d22e658 100644 --- a/tests/kernel/mbox/mbox_usage/src/main.c +++ b/tests/kernel/mbox/mbox_usage/src/main.c @@ -32,6 +32,7 @@ static enum mmsg_type { static void msg_sender(struct k_mbox *pmbox, k_timeout_t timeout) { static struct k_mbox_msg mmsg; + int ret; (void)memset(&mmsg, 0, sizeof(mmsg)); @@ -41,13 +42,9 @@ static void msg_sender(struct k_mbox *pmbox, k_timeout_t timeout) mmsg.info = PUT_GET_NULL; mmsg.size = 0; mmsg.tx_data = NULL; - if (K_TIMEOUT_EQ(timeout, K_FOREVER)) { - k_mbox_put(pmbox, &mmsg, K_FOREVER); - } else if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) { - k_mbox_put(pmbox, &mmsg, K_NO_WAIT); - } else { - k_mbox_put(pmbox, &mmsg, timeout); - } + + ret = k_mbox_put(pmbox, &mmsg, timeout); + zassert_ok(ret, "k_mbox_put() failed, ret %d", ret); break; default: break; @@ -59,20 +56,20 @@ static void msg_receiver(struct k_mbox *pmbox, k_tid_t thd_id, { static struct k_mbox_msg mmsg; static char rxdata[MAIL_LEN]; + int ret; switch (info_type) { case PUT_GET_NULL: mmsg.size = sizeof(rxdata); mmsg.rx_source_thread = thd_id; + + ret = k_mbox_get(pmbox, &mmsg, rxdata, timeout); if (K_TIMEOUT_EQ(timeout, K_FOREVER)) { - zassert_true(k_mbox_get(pmbox, &mmsg, - rxdata, K_FOREVER) == 0, NULL); + zassert_ok(ret, "k_mbox_get() ret %d", ret); } else if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) { - zassert_false(k_mbox_get(pmbox, &mmsg, - rxdata, K_NO_WAIT) == 0, NULL); + zassert_false(ret == 0, "k_mbox_get() ret %d", ret); } else { - zassert_true(k_mbox_get(pmbox, &mmsg, - rxdata, timeout) == 0, NULL); + zassert_ok(ret, "k_mbox_get() ret %d", ret); } break; default: @@ -163,7 +160,7 @@ static void thread_high_prio(void *p1, void *p2, void *p3) k_sem_give(&sync_sema); } -ZTEST_USER(mbox_usage_1cpu, test_multi_thread_send_get) +ZTEST(mbox_usage_1cpu, test_multi_thread_send_get) { static k_tid_t low_prio, high_prio; struct k_mbox_msg mmsg = {0}; @@ -178,7 +175,6 @@ ZTEST_USER(mbox_usage_1cpu, test_multi_thread_send_get) thread_high_prio, &multi_tmbox, NULL, NULL, HIGH_PRIO, 0, K_NO_WAIT); - k_sleep(K_MSEC(20)); mmsg.size = sizeof(msg_data[0]); mmsg.tx_data = msg_data[0]; mmsg.tx_target_thread = K_ANY; diff --git a/tests/kernel/mem_heap/k_heap_api/prj.conf b/tests/kernel/mem_heap/k_heap_api/prj.conf index 0e28a855341..9a75212e89d 100644 --- a/tests/kernel/mem_heap/k_heap_api/prj.conf +++ b/tests/kernel/mem_heap/k_heap_api/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_IRQ_OFFLOAD=y diff --git a/tests/kernel/mem_heap/mheap_api_concept/prj.conf b/tests/kernel/mem_heap/mheap_api_concept/prj.conf index d5c24a96c5a..9491650b184 100644 --- a/tests/kernel/mem_heap/mheap_api_concept/prj.conf +++ b/tests/kernel/mem_heap/mheap_api_concept/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_HEAP_MEM_POOL_SIZE=256 diff --git a/tests/kernel/mem_heap/mheap_api_concept/testcase.yaml b/tests/kernel/mem_heap/mheap_api_concept/testcase.yaml index 897aca938e9..380c9a0726f 100644 --- a/tests/kernel/mem_heap/mheap_api_concept/testcase.yaml +++ b/tests/kernel/mem_heap/mheap_api_concept/testcase.yaml @@ -24,6 +24,7 @@ tests: - qemu_riscv32 - qemu_riscv32e - qemu_riscv64 + - qemu_leon3 integration_platforms: - qemu_cortex_m3 extra_configs: diff --git a/tests/kernel/mem_heap/shared_multi_heap/boards/mps2_an521.overlay b/tests/kernel/mem_heap/shared_multi_heap/boards/mps2_an521.overlay index c52183dfe81..fca88ad07fd 100644 --- a/tests/kernel/mem_heap/shared_multi_heap/boards/mps2_an521.overlay +++ b/tests/kernel/mem_heap/shared_multi_heap/boards/mps2_an521.overlay @@ -4,6 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include + / { /delete-node/ memory@38000000; @@ -17,20 +20,20 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x38100000 0x1000>; zephyr,memory-region = "RES0"; - zephyr,memory-attr = "RAM"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; res1: memory@38200000 { compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x38200000 0x2000>; zephyr,memory-region = "RES1"; - zephyr,memory-attr = "RAM_NOCACHE"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) )>; }; res2: memory@38300000 { compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x38300000 0x3000>; zephyr,memory-region = "RES2"; - zephyr,memory-attr = "RAM"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; }; diff --git a/tests/kernel/mem_heap/shared_multi_heap/boards/qemu_cortex_a53.overlay b/tests/kernel/mem_heap/shared_multi_heap/boards/qemu_cortex_a53.overlay index a4ec256ad17..e00b217a8eb 100644 --- a/tests/kernel/mem_heap/shared_multi_heap/boards/qemu_cortex_a53.overlay +++ b/tests/kernel/mem_heap/shared_multi_heap/boards/qemu_cortex_a53.overlay @@ -4,20 +4,23 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include + / { soc { res0: memory@42000000 { compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x0 0x42000000 0x0 0x1000>; zephyr,memory-region = "RES0"; - zephyr,memory-attr = "RAM"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; res1: memory@43000000 { compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x0 0x43000000 0x0 0x2000>; zephyr,memory-region = "RES1"; - zephyr,memory-attr = "RAM_NOCACHE"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) )>; }; res_no_mpu: memory@45000000 { @@ -30,7 +33,7 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x0 0x44000000 0x0 0x3000>; zephyr,memory-region = "RES2"; - zephyr,memory-attr = "RAM"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; }; }; diff --git a/tests/kernel/mem_heap/shared_multi_heap/prj.conf b/tests/kernel/mem_heap/shared_multi_heap/prj.conf index 0da3bf56922..c596cfecac4 100644 --- a/tests/kernel/mem_heap/shared_multi_heap/prj.conf +++ b/tests/kernel/mem_heap/shared_multi_heap/prj.conf @@ -3,4 +3,3 @@ CONFIG_ZTEST=y CONFIG_SHARED_MULTI_HEAP=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/mem_heap/shared_multi_heap/src/main.c b/tests/kernel/mem_heap/shared_multi_heap/src/main.c index d2169f9164a..a9883ecc1c9 100644 --- a/tests/kernel/mem_heap/shared_multi_heap/src/main.c +++ b/tests/kernel/mem_heap/shared_multi_heap/src/main.c @@ -7,7 +7,8 @@ #include #include #include -#include +#include +#include #include @@ -22,14 +23,14 @@ struct region_map { uintptr_t p_addr; }; -#define FOREACH_REG(n) \ - { \ - .region = { \ - .addr = (uintptr_t) DT_INST_REG_ADDR(n), \ - .size = DT_INST_REG_SIZE(n), \ - .attr = DT_INST_ENUM_IDX_OR(n, zephyr_memory_attr, \ - SMH_REG_ATTR_NUM), \ - }, \ +#define FOREACH_REG(n) \ + { \ + .region = { \ + .addr = (uintptr_t) DT_INST_REG_ADDR(n), \ + .size = DT_INST_REG_SIZE(n), \ + .attr = DT_INST_PROP_OR(n, zephyr_memory_attr, \ + DT_MEM_ARM_MPU_UNKNOWN), \ + }, \ }, struct region_map map[] = { @@ -66,7 +67,7 @@ static struct region_map *get_region_map(void *v_addr) return NULL; } -static inline enum shared_multi_heap_attr mpu_to_reg_attr(int mpu_attr) +static inline enum shared_multi_heap_attr mpu_to_reg_attr(uint32_t dt_attr) { /* * All the memory regions defined in the DT with the MPU property `RAM` @@ -82,10 +83,10 @@ static inline enum shared_multi_heap_attr mpu_to_reg_attr(int mpu_attr) * RAM -> SMH_REG_ATTR_CACHEABLE * RAM_NOCACHE -> SMH_REG_ATTR_NON_CACHEABLE */ - switch (mpu_attr) { - case 0: /* RAM */ + switch (DT_MEM_ARM_GET(dt_attr)) { + case DT_MEM_ARM_MPU_RAM: return SMH_REG_ATTR_CACHEABLE; - case 1: /* RAM_NOCACHE */ + case DT_MEM_ARM_MPU_RAM_NOCACHE: return SMH_REG_ATTR_NON_CACHEABLE; default: /* How ? */ @@ -104,7 +105,7 @@ static void fill_multi_heap(void) reg_map = &map[idx]; /* zephyr,memory-attr property not found. Skip it. */ - if (reg_map->region.attr == SMH_REG_ATTR_NUM) { + if (reg_map->region.attr == DT_MEM_ARM_MPU_UNKNOWN) { continue; } diff --git a/tests/kernel/mem_protect/demand_paging/prj.conf b/tests/kernel/mem_protect/demand_paging/prj.conf index 1efbc867ff0..bbdf6393496 100644 --- a/tests/kernel/mem_protect/demand_paging/prj.conf +++ b/tests/kernel/mem_protect/demand_paging/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_DEMAND_PAGING_STATS=y CONFIG_DEMAND_PAGING_THREAD_STATS=y CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM=y diff --git a/tests/kernel/mem_protect/demand_paging/src/main.c b/tests/kernel/mem_protect/demand_paging/src/main.c index ed90e0fbe97..a453c06a573 100644 --- a/tests/kernel/mem_protect/demand_paging/src/main.c +++ b/tests/kernel/mem_protect/demand_paging/src/main.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include #include diff --git a/tests/kernel/mem_protect/futex/prj.conf b/tests/kernel/mem_protect/futex/prj.conf index d8e436e42a2..fb220f5594d 100644 --- a/tests/kernel/mem_protect/futex/prj.conf +++ b/tests/kernel/mem_protect/futex/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_IRQ_OFFLOAD=y CONFIG_TEST_USERSPACE=y CONFIG_MP_MAX_NUM_CPUS=1 diff --git a/tests/kernel/mem_protect/futex/testcase.yaml b/tests/kernel/mem_protect/futex/testcase.yaml index 8961283d526..6efaf0e66aa 100644 --- a/tests/kernel/mem_protect/futex/testcase.yaml +++ b/tests/kernel/mem_protect/futex/testcase.yaml @@ -1,6 +1,8 @@ tests: kernel.futex: filter: CONFIG_ARCH_HAS_USERSPACE + arch_exclude: + - posix tags: - kernel - userspace diff --git a/tests/kernel/mem_protect/mem_map/prj.conf b/tests/kernel/mem_protect/mem_map/prj.conf index 3971afe4e55..e39776e7067 100644 --- a/tests/kernel/mem_protect/mem_map/prj.conf +++ b/tests/kernel/mem_protect/mem_map/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y diff --git a/tests/kernel/mem_protect/mem_map/prj_x86_64_coverage_exec.conf b/tests/kernel/mem_protect/mem_map/prj_x86_64_coverage_exec.conf index 0c816860494..5ec0e877e4e 100644 --- a/tests/kernel/mem_protect/mem_map/prj_x86_64_coverage_exec.conf +++ b/tests/kernel/mem_protect/mem_map/prj_x86_64_coverage_exec.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y # Enable large memory model to avoid relative addressing # so the execution test can run with the function at diff --git a/tests/kernel/mem_protect/mem_map/src/main.c b/tests/kernel/mem_protect/mem_map/src/main.c index 6db32356440..45ca0aa1cf3 100644 --- a/tests/kernel/mem_protect/mem_map/src/main.c +++ b/tests/kernel/mem_protect/mem_map/src/main.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include #include diff --git a/tests/kernel/mem_protect/mem_protect/prj.conf b/tests/kernel/mem_protect/mem_protect/prj.conf index 26e3e5c04df..ffb1d6279ef 100644 --- a/tests/kernel/mem_protect/mem_protect/prj.conf +++ b/tests/kernel/mem_protect/mem_protect/prj.conf @@ -1,6 +1,5 @@ CONFIG_STACK_CANARIES=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=2048 CONFIG_MAX_THREAD_BYTES=4 CONFIG_TEST_USERSPACE=y diff --git a/tests/kernel/mem_protect/mem_protect/src/inherit.c b/tests/kernel/mem_protect/mem_protect/src/inherit.c index 7f22d308af6..8925535ef33 100644 --- a/tests/kernel/mem_protect/mem_protect/src/inherit.c +++ b/tests/kernel/mem_protect/mem_protect/src/inherit.c @@ -5,7 +5,7 @@ */ #include "mem_protect.h" -#include +#include #include /* for z_libc_partition */ /* function prototypes */ @@ -169,7 +169,7 @@ void parent_handler(void *p1, void *p2, void *p3) * * @ingroup kernel_memprotect_tests * - * @see z_thread_heap_assign() + * @see k_thread_heap_assign() */ ZTEST(mem_protect, test_inherit_resource_pool) { diff --git a/tests/kernel/mem_protect/mem_protect/src/kobject.c b/tests/kernel/mem_protect/mem_protect/src/kobject.c index 2cb37c72eba..79bd0549b09 100644 --- a/tests/kernel/mem_protect/mem_protect/src/kobject.c +++ b/tests/kernel/mem_protect/mem_protect/src/kobject.c @@ -5,18 +5,18 @@ */ #include "mem_protect.h" -#include +#include /* Kernel objects */ -K_THREAD_STACK_DEFINE(child_stack, KOBJECT_STACK_SIZE); +K_THREAD_STACK_DECLARE(child_stack, KOBJECT_STACK_SIZE); K_THREAD_STACK_DEFINE(extra_stack, KOBJECT_STACK_SIZE); K_SEM_DEFINE(kobject_sem, SEMAPHORE_INIT_COUNT, SEMAPHORE_MAX_COUNT); K_SEM_DEFINE(kobject_public_sem, SEMAPHORE_INIT_COUNT, SEMAPHORE_MAX_COUNT); K_MUTEX_DEFINE(kobject_mutex); -struct k_thread child_thread; +extern struct k_thread child_thread; struct k_thread extra_thread; struct k_sem *random_sem_type; @@ -42,7 +42,7 @@ ZTEST(mem_protect_kobj, test_kobject_access_grant) { set_fault_valid(false); - z_object_init(random_sem_type); + k_object_init(random_sem_type); k_thread_access_grant(k_current_get(), &kobject_sem, &kobject_mutex, @@ -481,7 +481,7 @@ ZTEST(mem_protect_kobj, test_thread_has_residual_permissions) * @ingroup kernel_memprotect_tests * * @see k_object_access_grant(), k_object_access_revoke(), - * z_object_find() + * k_object_find() */ ZTEST(mem_protect_kobj, test_kobject_access_grant_to_invalid_thread) { @@ -492,7 +492,7 @@ ZTEST(mem_protect_kobj, test_kobject_access_grant_to_invalid_thread) k_object_access_grant(&kobject_sem, &uninit_thread); k_object_access_revoke(&kobject_sem, &uninit_thread); - zassert_not_equal(Z_SYSCALL_OBJ(&uninit_thread, K_OBJ_THREAD), 0, + zassert_not_equal(K_SYSCALL_OBJ(&uninit_thread, K_OBJ_THREAD), 0, "Access granted/revoked to invalid thread k_object"); } @@ -1034,18 +1034,11 @@ ZTEST(mem_protect_kobj, test_create_new_invalid_prio_thread_from_user) /* Function to init thread's stack objects */ static void thread_stack_init_objects(void *p1, void *p2, void *p3) { - int ret; - struct z_object *ko; - /* check that thread is initialized when running */ - ko = z_object_find(&child_thread); - ret = z_object_validate(ko, K_OBJ_ANY, _OBJ_INIT_TRUE); - zassert_equal(ret, _OBJ_INIT_TRUE); + zassert_true(k_object_is_valid(&child_thread, K_OBJ_ANY)); /* check that stack is initialized when running */ - ko = z_object_find(child_stack); - ret = z_object_validate(ko, K_OBJ_ANY, _OBJ_INIT_TRUE); - zassert_equal(ret, _OBJ_INIT_TRUE); + zassert_true(k_object_is_valid(child_stack, K_OBJ_ANY)); } /** @@ -1061,7 +1054,7 @@ ZTEST(mem_protect_kobj, test_mark_thread_exit_uninitialized) set_fault_valid(false); int ret; - struct z_object *ko; + struct k_object *ko; k_thread_access_grant(&child_thread, &child_stack); @@ -1076,13 +1069,13 @@ ZTEST(mem_protect_kobj, test_mark_thread_exit_uninitialized) k_thread_join(&child_thread, K_FOREVER); /* check thread is uninitialized after its exit */ - ko = z_object_find(&child_thread); - ret = z_object_validate(ko, K_OBJ_ANY, _OBJ_INIT_FALSE); + ko = k_object_find(&child_thread); + ret = k_object_validate(ko, K_OBJ_ANY, _OBJ_INIT_FALSE); zassert_equal(ret, _OBJ_INIT_FALSE); /* check stack is uninitialized after thread exit */ - ko = z_object_find(child_stack); - ret = z_object_validate(ko, K_OBJ_ANY, _OBJ_INIT_FALSE); + ko = k_object_find(child_stack); + ret = k_object_validate(ko, K_OBJ_ANY, _OBJ_INIT_FALSE); zassert_equal(ret, _OBJ_INIT_FALSE); } @@ -1091,6 +1084,10 @@ ZTEST(mem_protect_kobj, test_mark_thread_exit_uninitialized) static void tThread_object_free_error(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + /* a K_ERR_CPU_EXCEPTION expected */ set_fault_valid(true); k_object_free(NULL); @@ -1115,7 +1112,7 @@ ZTEST(mem_protect_kobj, test_kobject_free_error) k_tid_t tid = k_thread_create(&child_thread, child_stack, K_THREAD_STACK_SIZEOF(child_stack), - (k_thread_entry_t)&tThread_object_free_error, + tThread_object_free_error, (void *)&tid, NULL, NULL, K_PRIO_PREEMPT(1), perm, K_NO_WAIT); @@ -1332,9 +1329,11 @@ struct k_condvar condvar; static void entry_error_perm(void *p1, void *p2, void *p3) { - set_fault_valid(true); - k_object_access_grant(p2, k_current_get()); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + set_fault_valid(true); + k_object_access_grant(p1, k_current_get()); } /** @@ -1350,7 +1349,9 @@ static void entry_error_perm(void *p1, void *p2, void *p3) */ ZTEST(mem_protect_kobj, test_kobject_perm_error) { - void *kobj[16]; +#define NUM_KOBJS 13 + + void *kobj[NUM_KOBJS]; kobj[0] = &ms; kobj[1] = &mq; @@ -1366,16 +1367,18 @@ ZTEST(mem_protect_kobj, test_kobject_perm_error) kobj[11] = &f; kobj[12] = &condvar; - for (int i = 0; i < 12 ; i++) { + for (int i = 0; i < NUM_KOBJS; i++) { k_tid_t tid = k_thread_create(&child_thread, child_stack, K_THREAD_STACK_SIZEOF(child_stack), - (k_thread_entry_t)entry_error_perm, - (void *)&tid, kobj[i], NULL, + entry_error_perm, + kobj[i], NULL, NULL, 1, K_USER, K_NO_WAIT); k_thread_join(tid, K_FOREVER); } + +#undef NUM_KOBJS } extern const char *otype_to_str(enum k_objects otype); diff --git a/tests/kernel/mem_protect/mem_protect/src/mem_domain.c b/tests/kernel/mem_protect/mem_protect/src/mem_domain.c index 5c4c6c1ce81..4ea5ad7ed1b 100644 --- a/tests/kernel/mem_protect/mem_protect/src/mem_domain.c +++ b/tests/kernel/mem_protect/mem_protect/src/mem_domain.c @@ -8,8 +8,8 @@ #include /* For z_main_thread */ #include /* for z_libc_partition */ -static struct k_thread child_thread; -static K_THREAD_STACK_DEFINE(child_stack, 512 + CONFIG_TEST_EXTRA_STACK_SIZE); +struct k_thread child_thread; +K_THREAD_STACK_DEFINE(child_stack, KOBJECT_STACK_SIZE); /* Special memory domain for test case purposes */ static struct k_mem_domain test_domain; diff --git a/tests/kernel/mem_protect/mem_protect/testcase.yaml b/tests/kernel/mem_protect/mem_protect/testcase.yaml index 5d46e54fcd0..20a9e8f7ac8 100644 --- a/tests/kernel/mem_protect/mem_protect/testcase.yaml +++ b/tests/kernel/mem_protect/mem_protect/testcase.yaml @@ -7,6 +7,8 @@ common: tests: kernel.memory_protection: filter: CONFIG_ARCH_HAS_USERSPACE + arch_exclude: + - posix platform_exclude: twr_ke18f extra_args: - CONFIG_TEST_HW_STACK_PROTECTION=n diff --git a/tests/kernel/mem_protect/obj_validation/prj.conf b/tests/kernel/mem_protect/obj_validation/prj.conf index 99a7ff95e16..cb297c820e6 100644 --- a/tests/kernel/mem_protect/obj_validation/prj.conf +++ b/tests/kernel/mem_protect/obj_validation/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y CONFIG_DYNAMIC_OBJECTS=y CONFIG_HEAP_MEM_POOL_SIZE=8192 diff --git a/tests/kernel/mem_protect/obj_validation/src/main.c b/tests/kernel/mem_protect/obj_validation/src/main.c index 9cc74a36063..3b0b2a3cae9 100644 --- a/tests/kernel/mem_protect/obj_validation/src/main.c +++ b/tests/kernel/mem_protect/obj_validation/src/main.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include @@ -31,12 +31,12 @@ static int test_object(struct k_sem *sem, int retval) int ret; if (retval) { - /* Expected to fail; bypass z_obj_validation_check() so we don't + /* Expected to fail; bypass k_object_validation_check() so we don't * fill the logs with spam */ - ret = z_object_validate(z_object_find(sem), K_OBJ_SEM, 0); + ret = k_object_validate(k_object_find(sem), K_OBJ_SEM, 0); } else { - ret = z_obj_validation_check(z_object_find(sem), sem, + ret = k_object_validation_check(k_object_find(sem), sem, K_OBJ_SEM, 0); } @@ -179,7 +179,7 @@ ZTEST(object_validation, test_no_ref_dyn_kobj_release_mem) k_object_access_revoke(test_dyn_mutex, thread); /* check object was released, when no threads have access to it */ - ret = z_object_validate(z_object_find(test_dyn_mutex), K_OBJ_MUTEX, 0); + ret = k_object_validate(k_object_find(test_dyn_mutex), K_OBJ_MUTEX, 0); zassert_true(ret == -EBADF, "Dynamic kernel object not released"); } diff --git a/tests/kernel/mem_protect/obj_validation/testcase.yaml b/tests/kernel/mem_protect/obj_validation/testcase.yaml index fd4b04a4222..7b6c3e8a457 100644 --- a/tests/kernel/mem_protect/obj_validation/testcase.yaml +++ b/tests/kernel/mem_protect/obj_validation/testcase.yaml @@ -1,6 +1,8 @@ tests: kernel.memory_protection.obj_validation: filter: CONFIG_ARCH_HAS_USERSPACE + arch_exclude: + - posix tags: - kernel - security diff --git a/tests/kernel/mem_protect/protection/prj.conf b/tests/kernel/mem_protect/protection/prj.conf index 00d6c1e6499..a3b3b01065c 100644 --- a/tests/kernel/mem_protect/protection/prj.conf +++ b/tests/kernel/mem_protect/protection/prj.conf @@ -1,3 +1,2 @@ CONFIG_HEAP_MEM_POOL_SIZE=256 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/mem_protect/stack_random/prj.conf b/tests/kernel/mem_protect/stack_random/prj.conf index 7bd01029e8a..85d03412f0e 100644 --- a/tests/kernel/mem_protect/stack_random/prj.conf +++ b/tests/kernel/mem_protect/stack_random/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_STACK_POINTER_RANDOM=64 CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/kernel/mem_protect/stack_random/src/main.c b/tests/kernel/mem_protect/stack_random/src/main.c index b659db5d683..12caf4a333d 100644 --- a/tests/kernel/mem_protect/stack_random/src/main.c +++ b/tests/kernel/mem_protect/stack_random/src/main.c @@ -24,8 +24,12 @@ volatile unsigned int changed; #pragma GCC diagnostic ignored "-Wdangling-pointer" #endif -void alternate_thread(void) +void alternate_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + int i; void *sp_val; @@ -68,7 +72,7 @@ ZTEST(stack_pointer_randomness, test_stack_pt_randomization) /* Start thread */ for (i = 0; i < THREAD_COUNT; i++) { k_thread_create(&alt_thread_data, alt_thread_stack_area, - STACKSIZE, (k_thread_entry_t)alternate_thread, + STACKSIZE, alternate_thread, NULL, NULL, NULL, K_HIGHEST_THREAD_PRIO, 0, K_NO_WAIT); k_sleep(K_MSEC(10)); diff --git a/tests/kernel/mem_protect/stack_random/testcase.yaml b/tests/kernel/mem_protect/stack_random/testcase.yaml index 73ed615bac6..b809f2875b9 100644 --- a/tests/kernel/mem_protect/stack_random/testcase.yaml +++ b/tests/kernel/mem_protect/stack_random/testcase.yaml @@ -1,6 +1,7 @@ tests: kernel.memory_protection.stack_random: - arch_exclude: posix + arch_exclude: + - posix tags: - kernel - memory_protection diff --git a/tests/kernel/mem_protect/stackprot/prj.conf b/tests/kernel/mem_protect/stackprot/prj.conf index 641dc9c6b38..63875657b1b 100644 --- a/tests/kernel/mem_protect/stackprot/prj.conf +++ b/tests/kernel/mem_protect/stackprot/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_STACK_CANARIES=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/kernel/mem_protect/stackprot/src/main.c b/tests/kernel/mem_protect/stackprot/src/main.c index 695142881f5..94877687c46 100644 --- a/tests/kernel/mem_protect/stackprot/src/main.c +++ b/tests/kernel/mem_protect/stackprot/src/main.c @@ -78,8 +78,12 @@ void __attribute__((noinline)) check_input(const char *name, const char *input) * and will not set ret to TC_FAIL. * */ -void alternate_thread(void) +void alternate_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + TC_PRINT("Starts %s\n", __func__); check_input(__func__, "Input string is too long and stack overflowed!\n"); @@ -129,7 +133,7 @@ ZTEST(stackprot, test_create_alt_thread) { /* Start thread */ k_thread_create(&alt_thread_data, alt_thread_stack_area, STACKSIZE, - (k_thread_entry_t)alternate_thread, NULL, NULL, NULL, + alternate_thread, NULL, NULL, NULL, K_PRIO_COOP(1), K_USER, K_NO_WAIT); /* Note that this sleep is required on SMP platforms where @@ -152,6 +156,9 @@ extern volatile uintptr_t __stack_chk_guard; */ void alternate_thread_canary(void *arg1, void *arg2, void *arg3) { + ARG_UNUSED(arg2); + ARG_UNUSED(arg3); + TC_PRINT("Starts %s\n", __func__); #ifdef CONFIG_STACK_CANARIES_TLS @@ -173,7 +180,7 @@ ZTEST(stackprot, test_canary_value) { /* Start thread */ k_thread_create(&alt_thread_data, alt_thread_stack_area, STACKSIZE, - (k_thread_entry_t)alternate_thread_canary, + alternate_thread_canary, (void *)__stack_chk_guard, NULL, NULL, K_PRIO_COOP(1), K_USER, K_NO_WAIT); diff --git a/tests/kernel/mem_protect/sys_sem/prj.conf b/tests/kernel/mem_protect/sys_sem/prj.conf index 57b97c472ee..29f2d64944e 100644 --- a/tests/kernel/mem_protect/sys_sem/prj.conf +++ b/tests/kernel/mem_protect/sys_sem/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_IRQ_OFFLOAD=y CONFIG_TEST_USERSPACE=y diff --git a/tests/kernel/mem_protect/sys_sem/testcase.yaml b/tests/kernel/mem_protect/sys_sem/testcase.yaml index f20f04894de..58d505de475 100644 --- a/tests/kernel/mem_protect/sys_sem/testcase.yaml +++ b/tests/kernel/mem_protect/sys_sem/testcase.yaml @@ -1,6 +1,8 @@ tests: kernel.memory_protection.sys_sem: filter: CONFIG_ARCH_HAS_USERSPACE + arch_exclude: + - posix tags: - kernel - userspace diff --git a/tests/kernel/mem_protect/syscalls/prj.conf b/tests/kernel/mem_protect/syscalls/prj.conf index a8996be31e6..cf42fb16e3f 100644 --- a/tests/kernel/mem_protect/syscalls/prj.conf +++ b/tests/kernel/mem_protect/syscalls/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y CONFIG_TIMESLICING=y CONFIG_TIMESLICE_SIZE=20 diff --git a/tests/kernel/mem_protect/syscalls/src/main.c b/tests/kernel/mem_protect/syscalls/src/main.c index 20bc624b002..ed57d7e9120 100644 --- a/tests/kernel/mem_protect/syscalls/src/main.c +++ b/tests/kernel/mem_protect/syscalls/src/main.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include #include "test_syscalls.h" @@ -25,8 +25,6 @@ #define FAULTY_ADDRESS 0x0FFFFFFF #elif defined(CONFIG_BOARD_QEMU_CORTEX_R5) #define FAULTY_ADDRESS 0xBFFFFFFF -#elif defined(CONFIG_SOC_SERIES_S32ZE_R52) -#define FAULTY_ADDRESS ((uintptr_t)(&_image_ram_end)) #elif CONFIG_MMU /* Just past the zephyr image mapping should be a non-present page */ #define FAULTY_ADDRESS Z_FREE_VM_START @@ -48,7 +46,7 @@ void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) size_t z_impl_string_nlen(char *src, size_t maxlen, int *err) { - return z_user_string_nlen(src, maxlen, err); + return k_usermode_string_nlen(src, maxlen, err); } static inline size_t z_vrfy_string_nlen(char *src, size_t maxlen, int *err) @@ -57,11 +55,11 @@ static inline size_t z_vrfy_string_nlen(char *src, size_t maxlen, int *err) size_t ret; ret = z_impl_string_nlen((char *)src, maxlen, &err_copy); - if (!err_copy && Z_SYSCALL_MEMORY_READ(src, ret + 1)) { + if (!err_copy && K_SYSCALL_MEMORY_READ(src, ret + 1)) { err_copy = -1; } - Z_OOPS(z_user_to_copy((int *)err, &err_copy, sizeof(err_copy))); + K_OOPS(k_usermode_to_copy((int *)err, &err_copy, sizeof(err_copy))); return ret; } @@ -81,7 +79,7 @@ static inline int z_vrfy_string_alloc_copy(char *src) char *src_copy; int ret; - src_copy = z_user_string_alloc_copy((char *)src, BUF_SIZE); + src_copy = k_usermode_string_alloc_copy((char *)src, BUF_SIZE); if (!src_copy) { return -1; } @@ -104,7 +102,7 @@ int z_impl_string_copy(char *src) static inline int z_vrfy_string_copy(char *src) { - int ret = z_user_string_copy(kernel_buf, (char *)src, BUF_SIZE); + int ret = k_usermode_string_copy(kernel_buf, (char *)src, BUF_SIZE); if (ret) { return ret; @@ -125,7 +123,7 @@ int z_impl_to_copy(char *dest) static inline int z_vrfy_to_copy(char *dest) { - return z_user_to_copy((char *)dest, user_string, BUF_SIZE); + return k_usermode_to_copy((char *)dest, user_string, BUF_SIZE); } #include @@ -195,14 +193,14 @@ static inline uint32_t z_vrfy_more_args(uint32_t arg1, uint32_t arg2, #include /** - * @brief Test to demonstrate usage of z_user_string_nlen() + * @brief Test to demonstrate usage of k_usermode_string_nlen() * * @details The test will be called from user mode and kernel - * mode to check the behavior of z_user_string_nlen() + * mode to check the behavior of k_usermode_string_nlen() * * @ingroup kernel_memprotect_tests * - * @see z_user_string_nlen() + * @see k_usermode_string_nlen() */ ZTEST_USER(syscalls, test_string_nlen) { @@ -250,7 +248,7 @@ ZTEST_USER(syscalls, test_string_nlen) * * @ingroup kernel_memprotect_tests * - * @see z_user_string_alloc_copy(), strcmp() + * @see k_usermode_string_alloc_copy(), strcmp() */ ZTEST_USER(syscalls, test_user_string_alloc_copy) { @@ -275,7 +273,7 @@ ZTEST_USER(syscalls, test_user_string_alloc_copy) * * @ingroup kernel_memprotect_tests * - * @see z_user_string_copy(), strcmp() + * @see k_usermode_string_copy(), strcmp() */ ZTEST_USER(syscalls, test_user_string_copy) { @@ -299,7 +297,7 @@ ZTEST_USER(syscalls, test_user_string_copy) * * @ingroup kernel_memprotect_tests * - * @see memcpy(), z_user_to_copy() + * @see memcpy(), k_usermode_to_copy() */ ZTEST_USER(syscalls, test_to_copy) { @@ -412,7 +410,7 @@ ZTEST(syscalls, test_syscall_torture) bool z_impl_syscall_context(void) { - return z_is_in_user_syscall(); + return k_is_in_user_syscall(); } static inline bool z_vrfy_syscall_context(void) @@ -435,7 +433,7 @@ void test_syscall_context_user(void *p1, void *p2, void *p3) ZTEST(syscalls, test_syscall_context) { /* We're a regular supervisor thread. */ - zassert_false(z_is_in_user_syscall(), + zassert_false(k_is_in_user_syscall(), "reported in user syscall when in supv. thread ctx"); /* Make a system call from supervisor mode. The check in the diff --git a/tests/kernel/mem_protect/syscalls/testcase.yaml b/tests/kernel/mem_protect/syscalls/testcase.yaml index 41d222b0893..0f2587f3859 100644 --- a/tests/kernel/mem_protect/syscalls/testcase.yaml +++ b/tests/kernel/mem_protect/syscalls/testcase.yaml @@ -2,6 +2,8 @@ tests: kernel.memory_protection.syscalls: platform_exclude: qemu_arc_em filter: CONFIG_ARCH_HAS_USERSPACE + arch_exclude: + - posix tags: - kernel - security diff --git a/tests/kernel/mem_protect/userspace/boards/nucleo_f746zg.overlay b/tests/kernel/mem_protect/userspace/boards/nucleo_f746zg.overlay new file mode 100644 index 00000000000..50fa5dcc6e1 --- /dev/null +++ b/tests/kernel/mem_protect/userspace/boards/nucleo_f746zg.overlay @@ -0,0 +1,13 @@ +/* + * Copyright 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Disable quadspi MPU region for testing + * on this stm32f7 target + * else one region is missing among 8 MPU regions + */ + +/delete-node/ &quadspi_memory; diff --git a/tests/kernel/mem_protect/userspace/prj.conf b/tests/kernel/mem_protect/userspace/prj.conf index 471a4af8f41..c963d1f7f94 100644 --- a/tests/kernel/mem_protect/userspace/prj.conf +++ b/tests/kernel/mem_protect/userspace/prj.conf @@ -1,6 +1,5 @@ CONFIG_STACK_CANARIES=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_INIT_STACKS=y CONFIG_APPLICATION_DEFINED_SYSCALL=y CONFIG_TEST_USERSPACE=y diff --git a/tests/kernel/mem_protect/userspace/src/main.c b/tests/kernel/mem_protect/userspace/src/main.c index 6e996e9e605..1c0e7d3ef21 100644 --- a/tests/kernel/mem_protect/userspace/src/main.c +++ b/tests/kernel/mem_protect/userspace/src/main.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include "test_syscall.h" #include /* for z_libc_partition */ @@ -327,7 +327,7 @@ ZTEST_USER(userspace, test_write_kerntext) /* Try to write to kernel text. */ set_fault(K_ERR_CPU_EXCEPTION); - memset(&z_is_thread_essential, 0, 4); + memset(&k_current_get, 0, 4); zassert_unreachable("Write to kernel text did not fault"); } @@ -451,8 +451,11 @@ ZTEST_USER(userspace, test_pass_noperms_object) } -void thread_body(void) +void thread_body(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); } /** @@ -465,7 +468,7 @@ ZTEST_USER(userspace, test_start_kernel_thread) /* Try to start a kernel thread from a usermode thread */ set_fault(K_ERR_KERNEL_OOPS); k_thread_create(&test_thread, test_stack, STACKSIZE, - (k_thread_entry_t)thread_body, NULL, NULL, NULL, + thread_body, NULL, NULL, NULL, K_PRIO_PREEMPT(1), K_INHERIT_PERMS, K_NO_WAIT); zassert_unreachable("Create a kernel thread did not fault"); @@ -568,8 +571,12 @@ ZTEST_USER(userspace, test_access_after_revoke) zassert_unreachable("Using revoked object did not fault"); } -static void umode_enter_func(void) +static void umode_enter_func(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + zassert_true(k_is_user_context(), "Thread did not enter user mode"); } @@ -586,7 +593,7 @@ ZTEST(userspace, test_user_mode_enter) { clear_fault(); - k_thread_user_mode_enter((k_thread_entry_t)umode_enter_func, + k_thread_user_mode_enter(umode_enter_func, NULL, NULL, NULL); } @@ -854,28 +861,28 @@ static struct k_sem recycle_sem; * @details Test recycle valid/invalid kernel object, see if * perms_count changes as expected. * - * @see z_object_recycle(), z_object_find() + * @see k_object_recycle(), k_object_find() * * @ingroup kernel_memprotect_tests */ ZTEST(userspace, test_object_recycle) { - struct z_object *ko; + struct k_object *ko; int perms_count = 0; int dummy = 0; /* Validate recycle invalid objects, after recycling this invalid * object, perms_count should finally still be 1. */ - ko = z_object_find(&dummy); + ko = k_object_find(&dummy); zassert_true(ko == NULL, "not an invalid object"); - z_object_recycle(&dummy); + k_object_recycle(&dummy); - ko = z_object_find(&recycle_sem); + ko = k_object_find(&recycle_sem); (void)memset(ko->perms, 0xFF, sizeof(ko->perms)); - z_object_recycle(&recycle_sem); + k_object_recycle(&recycle_sem); zassert_true(ko != NULL, "kernel object not found"); zassert_true(ko->flags & K_OBJ_FLAG_INITIALIZED, "object wasn't marked as initialized"); diff --git a/tests/kernel/mem_protect/userspace/testcase.yaml b/tests/kernel/mem_protect/userspace/testcase.yaml index 8be32fbae47..b098883c05f 100644 --- a/tests/kernel/mem_protect/userspace/testcase.yaml +++ b/tests/kernel/mem_protect/userspace/testcase.yaml @@ -4,6 +4,8 @@ common: - kernel - security - userspace + arch_exclude: + - posix tests: kernel.memory_protection.userspace: filter: CONFIG_ARCH_HAS_USERSPACE diff --git a/tests/kernel/mem_slab/mslab/prj.conf b/tests/kernel/mem_slab/mslab/prj.conf index 83b0a650119..2ed231771b6 100644 --- a/tests/kernel/mem_slab/mslab/prj.conf +++ b/tests/kernel/mem_slab/mslab/prj.conf @@ -1,5 +1,4 @@ CONFIG_BT=n CONFIG_MAIN_THREAD_PRIORITY=5 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MP_MAX_NUM_CPUS=1 diff --git a/tests/kernel/mem_slab/mslab_api/prj.conf b/tests/kernel/mem_slab/mslab_api/prj.conf index b889211aa64..dfb5d99e39b 100644 --- a/tests/kernel/mem_slab/mslab_api/prj.conf +++ b/tests/kernel/mem_slab/mslab_api/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_IRQ_OFFLOAD=y CONFIG_MP_MAX_NUM_CPUS=1 diff --git a/tests/kernel/mem_slab/mslab_api/testcase.yaml b/tests/kernel/mem_slab/mslab_api/testcase.yaml index fbfdffda5fa..3f067a1529f 100644 --- a/tests/kernel/mem_slab/mslab_api/testcase.yaml +++ b/tests/kernel/mem_slab/mslab_api/testcase.yaml @@ -22,6 +22,7 @@ tests: - qemu_riscv32 - qemu_riscv32e - qemu_riscv64 + - qemu_leon3 integration_platforms: - qemu_cortex_m3 - qemu_arc_hs diff --git a/tests/kernel/mem_slab/mslab_concept/prj.conf b/tests/kernel/mem_slab/mslab_concept/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/kernel/mem_slab/mslab_concept/prj.conf +++ b/tests/kernel/mem_slab/mslab_concept/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/mem_slab/mslab_stats/prj.conf b/tests/kernel/mem_slab/mslab_stats/prj.conf index 670062ee387..a5a2801a982 100644 --- a/tests/kernel/mem_slab/mslab_stats/prj.conf +++ b/tests/kernel/mem_slab/mslab_stats/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION=y CONFIG_MP_MAX_NUM_CPUS=1 diff --git a/tests/kernel/mem_slab/mslab_threadsafe/prj.conf b/tests/kernel/mem_slab/mslab_threadsafe/prj.conf index e546e87d271..8ef1ecc8faa 100644 --- a/tests/kernel/mem_slab/mslab_threadsafe/prj.conf +++ b/tests/kernel/mem_slab/mslab_threadsafe/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 # FIXME: restore after #13813 is resolved # 1 millisecond diff --git a/tests/kernel/mp/prj.conf b/tests/kernel/mp/prj.conf index 6c2881737d8..5b0d7a6bdea 100644 --- a/tests/kernel/mp/prj.conf +++ b/tests/kernel/mp/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SMP=n diff --git a/tests/kernel/msgq/msgq_api/prj.conf b/tests/kernel/msgq/msgq_api/prj.conf index 57b97c472ee..29f2d64944e 100644 --- a/tests/kernel/msgq/msgq_api/prj.conf +++ b/tests/kernel/msgq/msgq_api/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_IRQ_OFFLOAD=y CONFIG_TEST_USERSPACE=y diff --git a/tests/kernel/msgq/msgq_usage/prj.conf b/tests/kernel/msgq/msgq_usage/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/kernel/msgq/msgq_usage/prj.conf +++ b/tests/kernel/msgq/msgq_usage/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/mutex/mutex_api/prj.conf b/tests/kernel/mutex/mutex_api/prj.conf index d8e436e42a2..fb220f5594d 100644 --- a/tests/kernel/mutex/mutex_api/prj.conf +++ b/tests/kernel/mutex/mutex_api/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_IRQ_OFFLOAD=y CONFIG_TEST_USERSPACE=y CONFIG_MP_MAX_NUM_CPUS=1 diff --git a/tests/kernel/mutex/mutex_api/src/test_mutex_apis.c b/tests/kernel/mutex/mutex_api/src/test_mutex_apis.c index e141e57222c..2f45e684001 100644 --- a/tests/kernel/mutex/mutex_api/src/test_mutex_apis.c +++ b/tests/kernel/mutex/mutex_api/src/test_mutex_apis.c @@ -104,6 +104,8 @@ static void tmutex_test_lock_unlock(struct k_mutex *pmutex) static void tThread_T1_priority_inheritance(void *p1, void *p2, void *p3) { + ARG_UNUSED(p3); + /* t1 will get mutex first */ zassert_true(k_mutex_lock((struct k_mutex *)p1, K_FOREVER) == 0, "access locked resource from spawn thread T1"); @@ -150,6 +152,9 @@ static void tThread_T1_priority_inheritance(void *p1, void *p2, void *p3) static void tThread_T2_priority_inheritance(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + if (case_type == 1) { zassert_true(k_mutex_lock((struct k_mutex *)p1, K_FOREVER) == 0, "access locked resource from spawn thread T2"); @@ -166,6 +171,9 @@ static void tThread_T2_priority_inheritance(void *p1, void *p2, void *p3) static void tThread_lock_with_time_period(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + zassert_true(k_mutex_lock((struct k_mutex *)p1, K_FOREVER) == 0, "access locked resource from spawn thread"); @@ -177,6 +185,9 @@ static void tThread_lock_with_time_period(void *p1, void *p2, void *p3) static void tThread_waiter(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + /* This thread participates in recursive locking tests */ /* Wait for mutex to be released */ zassert_true(k_mutex_lock((struct k_mutex *)p1, K_FOREVER) == 0, @@ -261,7 +272,7 @@ ZTEST_USER(mutex_api, test_mutex_recursive) thread_ret = TC_FAIL; /* Spawn a waiter thread */ k_thread_create(&tdata3, tstack3, STACK_SIZE, - (k_thread_entry_t)tThread_waiter, &tmutex, NULL, NULL, + tThread_waiter, &tmutex, NULL, NULL, K_PRIO_PREEMPT(12), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -305,7 +316,7 @@ ZTEST_USER(mutex_api_1cpu, test_mutex_priority_inheritance) /* spawn a lower priority thread t1 for holding the mutex */ k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)tThread_T1_priority_inheritance, + tThread_T1_priority_inheritance, &tmutex, &tdata, NULL, K_PRIO_PREEMPT(THREAD_LOW_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -319,7 +330,7 @@ ZTEST_USER(mutex_api_1cpu, test_mutex_priority_inheritance) /* spawn a higher priority thread t2 for holding the mutex */ k_thread_create(&tdata2, tstack2, STACK_SIZE, - (k_thread_entry_t)tThread_T2_priority_inheritance, + tThread_T2_priority_inheritance, &tmutex, &tdata2, NULL, K_PRIO_PREEMPT(THREAD_HIGH_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -335,7 +346,7 @@ ZTEST_USER(mutex_api_1cpu, test_mutex_priority_inheritance) /* spawn a lower priority thread t1 for holding the mutex */ k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)tThread_T1_priority_inheritance, + tThread_T1_priority_inheritance, &tmutex, &tdata, NULL, K_PRIO_PREEMPT(THREAD_HIGH_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -345,7 +356,7 @@ ZTEST_USER(mutex_api_1cpu, test_mutex_priority_inheritance) /* spawn a higher priority thread t2 for holding the mutex */ k_thread_create(&tdata2, tstack2, STACK_SIZE, - (k_thread_entry_t)tThread_T2_priority_inheritance, + tThread_T2_priority_inheritance, &tmutex, &tdata2, NULL, K_PRIO_PREEMPT(THREAD_LOW_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -361,7 +372,7 @@ ZTEST_USER(mutex_api_1cpu, test_mutex_priority_inheritance) /* spawn a lower priority thread t1 for holding the mutex */ k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)tThread_T1_priority_inheritance, + tThread_T1_priority_inheritance, &tmutex, &tdata, NULL, K_PRIO_PREEMPT(THREAD_LOW_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -371,14 +382,14 @@ ZTEST_USER(mutex_api_1cpu, test_mutex_priority_inheritance) /* spawn a higher priority thread t2 for holding the mutex */ k_thread_create(&tdata2, tstack2, STACK_SIZE, - (k_thread_entry_t)tThread_T2_priority_inheritance, + tThread_T2_priority_inheritance, &tmutex, &tdata2, NULL, K_PRIO_PREEMPT(THREAD_HIGH_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); /* spawn a higher priority thread t3 for holding the mutex */ k_thread_create(&tdata3, tstack3, STACK_SIZE, - (k_thread_entry_t)tThread_lock_with_time_period, + tThread_lock_with_time_period, &tmutex, &tdata3, NULL, K_PRIO_PREEMPT(THREAD_MID_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); diff --git a/tests/kernel/mutex/mutex_error_case/prj.conf b/tests/kernel/mutex/mutex_error_case/prj.conf index e9ab90559ca..d144e826538 100644 --- a/tests/kernel/mutex/mutex_error_case/prj.conf +++ b/tests/kernel/mutex/mutex_error_case/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_IRQ_OFFLOAD=y CONFIG_TEST_USERSPACE=y CONFIG_MP_MAX_NUM_CPUS=1 diff --git a/tests/kernel/mutex/mutex_error_case/src/test_mutex_error.c b/tests/kernel/mutex/mutex_error_case/src/test_mutex_error.c index 955af138b7d..d1ba0557727 100644 --- a/tests/kernel/mutex/mutex_error_case/src/test_mutex_error.c +++ b/tests/kernel/mutex/mutex_error_case/src/test_mutex_error.c @@ -47,6 +47,9 @@ void ztest_post_fatal_error_hook(unsigned int reason, static void tThread_entry_negative(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p3); + int choice = *((int *)p2); TC_PRINT("current case is %d\n", choice); @@ -102,7 +105,7 @@ static int create_negative_test_thread(int choice) case_type = choice; k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)tThread_entry_negative, + tThread_entry_negative, &mutex, (void *)&case_type, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), perm, K_NO_WAIT); diff --git a/tests/kernel/mutex/mutex_error_case/testcase.yaml b/tests/kernel/mutex/mutex_error_case/testcase.yaml index ac89d216fbe..16d8252b6e9 100644 --- a/tests/kernel/mutex/mutex_error_case/testcase.yaml +++ b/tests/kernel/mutex/mutex_error_case/testcase.yaml @@ -1,6 +1,8 @@ tests: kernel.mutex.error: filter: CONFIG_ARCH_HAS_USERSPACE + arch_exclude: + - posix tags: - kernel - userspace diff --git a/tests/kernel/mutex/sys_mutex/prj.conf b/tests/kernel/mutex/sys_mutex/prj.conf index 19669cdffb6..25081bfa959 100644 --- a/tests/kernel/mutex/sys_mutex/prj.conf +++ b/tests/kernel/mutex/sys_mutex/prj.conf @@ -1,4 +1,3 @@ CONFIG_MAIN_THREAD_PRIORITY=10 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y diff --git a/tests/kernel/mutex/sys_mutex/src/main.c b/tests/kernel/mutex/sys_mutex/src/main.c index b335e80f53e..9da45b0bebe 100644 --- a/tests/kernel/mutex/sys_mutex/src/main.c +++ b/tests/kernel/mutex/sys_mutex/src/main.c @@ -88,7 +88,7 @@ static ZTEST_BMEM SYS_MUTEX_DEFINE(bad_count_mutex); #define CREATE_PARTICIPANT_THREAD(id, pri) \ k_thread_create(&thread_##id##_thread_data, thread_##id##_stack_area, \ K_THREAD_STACK_SIZEOF(thread_##id##_stack_area), \ - (k_thread_entry_t)thread_##id, \ + thread_##id, \ NULL, NULL, NULL, \ pri, PARTICIPANT_THREAD_OPTIONS, K_FOREVER); #define START_PARTICIPANT_THREAD(id) k_thread_start(&(thread_##id##_thread_data)); @@ -100,8 +100,12 @@ static ZTEST_BMEM SYS_MUTEX_DEFINE(bad_count_mutex); * */ -void thread_05(void) +void thread_05(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + int rv; k_sleep(K_MSEC(3500)); @@ -122,8 +126,12 @@ void thread_05(void) * */ -void thread_06(void) +void thread_06(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + int rv; k_sleep(K_MSEC(3750)); @@ -153,8 +161,12 @@ void thread_06(void) * */ -void thread_07(void) +void thread_07(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + int rv; k_sleep(K_MSEC(2500)); @@ -182,8 +194,12 @@ void thread_07(void) * */ -void thread_08(void) +void thread_08(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + int rv; k_sleep(K_MSEC(1500)); @@ -205,8 +221,12 @@ void thread_08(void) * */ -void thread_09(void) +void thread_09(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + int rv; k_sleep(K_MSEC(500)); /* Allow lower priority thread to run */ @@ -237,8 +257,12 @@ void thread_09(void) * */ -void thread_11(void) +void thread_11(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + int rv; k_sleep(K_MSEC(3500)); @@ -253,7 +277,7 @@ void thread_11(void) K_THREAD_STACK_DEFINE(thread_12_stack_area, STACKSIZE); struct k_thread thread_12_thread_data; -extern void thread_12(void); +extern void thread_12(void *p1, void *p2, void *p3); @@ -395,7 +419,7 @@ ZTEST_USER_OR_NOT(mutex_complex, test_mutex) /* Start thread */ k_thread_create(&thread_12_thread_data, thread_12_stack_area, STACKSIZE, - (k_thread_entry_t)thread_12, NULL, NULL, NULL, + thread_12, NULL, NULL, NULL, K_PRIO_PREEMPT(12), PARTICIPANT_THREAD_OPTIONS, K_NO_WAIT); k_sleep(K_MSEC(5)); /* Give thread_12 a chance to block on the mutex */ diff --git a/tests/kernel/mutex/sys_mutex/src/thread_12.c b/tests/kernel/mutex/sys_mutex/src/thread_12.c index f70b654f4b5..fcf548fb645 100644 --- a/tests/kernel/mutex/sys_mutex/src/thread_12.c +++ b/tests/kernel/mutex/sys_mutex/src/thread_12.c @@ -29,8 +29,12 @@ extern struct sys_mutex private_mutex; * */ -void thread_12(void) +void thread_12(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + int rv; /* Wait for private mutex to be released */ diff --git a/tests/kernel/mutex/sys_mutex/testcase.yaml b/tests/kernel/mutex/sys_mutex/testcase.yaml index c3669a6cfef..031c56cc2a4 100644 --- a/tests/kernel/mutex/sys_mutex/testcase.yaml +++ b/tests/kernel/mutex/sys_mutex/testcase.yaml @@ -1,11 +1,12 @@ tests: kernel.mutex.system: filter: CONFIG_ARCH_HAS_USERSPACE + arch_exclude: + - posix tags: - kernel - userspace - mutex - kernel.mutex.system.nouser: tags: - kernel diff --git a/tests/kernel/obj_core/obj_core/CMakeLists.txt b/tests/kernel/obj_core/obj_core/CMakeLists.txt new file mode 100644 index 00000000000..a9c26c7493c --- /dev/null +++ b/tests/kernel/obj_core/obj_core/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(obj_core) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/kernel/obj_core/obj_core/prj.conf b/tests/kernel/obj_core/obj_core/prj.conf new file mode 100644 index 00000000000..6c006bcb8e9 --- /dev/null +++ b/tests/kernel/obj_core/obj_core/prj.conf @@ -0,0 +1,5 @@ +CONFIG_ZTEST=y +CONFIG_OBJ_CORE=y +CONFIG_EVENTS=y +CONFIG_PIPES=y +CONFIG_SYS_MEM_BLOCKS=y diff --git a/tests/kernel/obj_core/obj_core/src/main.c b/tests/kernel/obj_core/obj_core/src/main.c new file mode 100644 index 00000000000..9ec5eefb324 --- /dev/null +++ b/tests/kernel/obj_core/obj_core/src/main.c @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2023, Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +SYS_MEM_BLOCKS_DEFINE(block1, 32, 4, 16); + +K_MEM_SLAB_DEFINE(slab1, 32, 4, 16); +static char slab2_buffer[256] __aligned(8); +struct k_mem_slab slab2; + +K_TIMER_DEFINE(timer1, NULL, NULL); +struct k_timer timer2; + +K_STACK_DEFINE(stack1, 8); +static struct k_stack stack2; +stack_data_t stack2_buffer[8]; + +static K_FIFO_DEFINE(fifo1); +static struct k_fifo fifo2; + +static K_LIFO_DEFINE(lifo1); +static struct k_lifo lifo2; + +K_PIPE_DEFINE(pipe1, 16, 8); +static struct k_pipe pipe2; +static char pipe2_buffer[16]; + +K_MSGQ_DEFINE(msgq1, 16, 4, 8); +static struct k_msgq msgq2; +static char msgq2_buffer[16]; + +static K_MBOX_DEFINE(mbox1); +static struct k_mbox mbox2; + +static K_CONDVAR_DEFINE(condvar1); +static struct k_condvar condvar2; + +static K_EVENT_DEFINE(event1); +static struct k_event event2; + +static K_MUTEX_DEFINE(mutex1); +static struct k_mutex mutex2; + +static K_SEM_DEFINE(sem1, 0, 1); +static struct k_sem sem2; + +static void thread_entry(void *, void *, void *); +K_THREAD_DEFINE(thread1, 512 + CONFIG_TEST_EXTRA_STACK_SIZE, + thread_entry, NULL, NULL, NULL, + K_HIGHEST_THREAD_PRIO, 0, 0); +static struct k_thread thread2; +K_THREAD_STACK_DEFINE(thread2_stack, 512 + CONFIG_TEST_EXTRA_STACK_SIZE); + +struct obj_core_find_data { + struct k_obj_core *obj_core; /* Object core to search for */ +}; + +static void thread_entry(void *p1, void *p2, void *p3) +{ + k_sem_take(&sem1, K_FOREVER); +} + +static int obj_core_find_op(struct k_obj_core *obj_core, void *data) +{ + struct obj_core_find_data *find_data = data; + + if (find_data->obj_core == obj_core) { + + /* Object core found. Abort the search. */ + + return 1; + } + + /* Object core not found--continue searching. */ + + return 0; +} + +static void common_obj_core_test(uint32_t type_id, const char *str, + struct k_obj_core *static_obj_core, + struct k_obj_core *dyn_obj_core) +{ + struct k_obj_type *obj_type; + struct obj_core_find_data walk_data; + int status; + + obj_type = k_obj_type_find(type_id); + + zassert_not_null(obj_type, "%s object type not found\n", str); + + /* Search for statically initialized object */ + + if (static_obj_core != NULL) { + walk_data.obj_core = static_obj_core; + status = k_obj_type_walk_locked(obj_type, obj_core_find_op, + &walk_data); + zassert_equal(status, 1, + "static %s not found with locked walk\n", str); + + status = k_obj_type_walk_unlocked(obj_type, obj_core_find_op, + &walk_data); + zassert_equal(status, 1, + "static %s not found with unlocked walk\n", str); + } + + /* Search for dynamically initialized object */ + + if (dyn_obj_core != NULL) { + walk_data.obj_core = dyn_obj_core; + status = k_obj_type_walk_locked(obj_type, obj_core_find_op, + &walk_data); + zassert_equal(status, 1, + "dynamic %s not found with locked walk\n", str); + + status = k_obj_type_walk_unlocked(obj_type, obj_core_find_op, + &walk_data); + zassert_equal(status, 1, + "dynamic %s not found with unlocked walk\n", str); + } +} + +ZTEST(obj_core, test_obj_core_thread) +{ + k_thread_create(&thread2, thread2_stack, + K_THREAD_STACK_SIZEOF(thread2_stack), thread_entry, + NULL, NULL, NULL, K_HIGHEST_THREAD_PRIO, 0, K_NO_WAIT); + + common_obj_core_test(K_OBJ_TYPE_THREAD_ID, "thread", + K_OBJ_CORE(thread1), K_OBJ_CORE(&thread2)); + + /* Terminate both thread1 and thread 2 */ + + k_thread_abort(thread1); + k_thread_abort(&thread2); + + /* + * Neither thread1 nor thread2 should be in the thread object type's + * list of threads anymore. Verify this. + */ + + struct k_obj_type *obj_type; + struct obj_core_find_data walk_data; + int status; + + obj_type = k_obj_type_find(K_OBJ_TYPE_THREAD_ID); + + zassert_not_null(obj_type, "thread object type not found\n"); + + /* Search for statically initialized object */ + + walk_data.obj_core = K_OBJ_CORE(thread1); + status = k_obj_type_walk_locked(obj_type, obj_core_find_op, + &walk_data); + zassert_equal(status, 0, "static thread found with locked walk\n"); + + status = k_obj_type_walk_unlocked(obj_type, obj_core_find_op, + &walk_data); + zassert_equal(status, 0, "static thread found with unlocked walk\n"); + + walk_data.obj_core = K_OBJ_CORE(&thread2); + status = k_obj_type_walk_locked(obj_type, obj_core_find_op, + &walk_data); + zassert_equal(status, 0, "dynamic thread found with locked walk\n"); + + status = k_obj_type_walk_unlocked(obj_type, obj_core_find_op, + &walk_data); + zassert_equal(status, 0, "dynamic thread found with unlocked walk\n"); +} + +ZTEST(obj_core, test_obj_core_system) +{ + int i; + char cpu_str[16]; + + /* + * Use the existing object cores in the _cpu and z_kerenl structures + * as we should not be creating new ones. + */ + + for (i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) { + sprintf(cpu_str, "CPU%d", i); + common_obj_core_test(K_OBJ_TYPE_CPU_ID, cpu_str, + K_OBJ_CORE(&_kernel.cpus[i]), NULL); + } + + common_obj_core_test(K_OBJ_TYPE_KERNEL_ID, "_kernel", + K_OBJ_CORE(&_kernel), NULL); +} + +ZTEST(obj_core, test_obj_core_sys_mem_block) +{ + common_obj_core_test(K_OBJ_TYPE_MEM_BLOCK_ID, "memory block", + K_OBJ_CORE(&block1), NULL); +} + +ZTEST(obj_core, test_obj_core_mem_slab) +{ + k_mem_slab_init(&slab2, slab2_buffer, 32, 8); + common_obj_core_test(K_OBJ_TYPE_MEM_SLAB_ID, "memory slab", + K_OBJ_CORE(&slab1), K_OBJ_CORE(&slab2)); +} + +ZTEST(obj_core, test_obj_core_timer) +{ + k_timer_init(&timer2, NULL, NULL); + common_obj_core_test(K_OBJ_TYPE_TIMER_ID, "timer", + K_OBJ_CORE(&timer1), K_OBJ_CORE(&timer2)); +} + +ZTEST(obj_core, test_obj_core_stack) +{ + k_stack_init(&stack2, stack2_buffer, 8); + common_obj_core_test(K_OBJ_TYPE_STACK_ID, "stack", + K_OBJ_CORE(&stack1), K_OBJ_CORE(&stack2)); +} + +ZTEST(obj_core, test_obj_core_fifo) +{ + k_fifo_init(&fifo2); + common_obj_core_test(K_OBJ_TYPE_FIFO_ID, "FIFO", + K_OBJ_CORE(&fifo1), K_OBJ_CORE(&fifo2)); +} + +ZTEST(obj_core, test_obj_core_lifo) +{ + k_lifo_init(&lifo2); + common_obj_core_test(K_OBJ_TYPE_LIFO_ID, "LIFO", + K_OBJ_CORE(&lifo1), K_OBJ_CORE(&lifo2)); +} + +ZTEST(obj_core, test_obj_core_pipe) +{ + k_pipe_init(&pipe2, pipe2_buffer, sizeof(pipe2_buffer)); + common_obj_core_test(K_OBJ_TYPE_PIPE_ID, "pipe", + K_OBJ_CORE(&pipe1), K_OBJ_CORE(&pipe2)); +} + +ZTEST(obj_core, test_obj_core_msgq) +{ + k_msgq_init(&msgq2, msgq2_buffer, 4, 4); + common_obj_core_test(K_OBJ_TYPE_MSGQ_ID, "message queue", + K_OBJ_CORE(&msgq1), K_OBJ_CORE(&msgq2)); +} + +ZTEST(obj_core, test_obj_core_mbox) +{ + k_mbox_init(&mbox2); + common_obj_core_test(K_OBJ_TYPE_MBOX_ID, "mailbox", + K_OBJ_CORE(&mbox1), K_OBJ_CORE(&mbox2)); +} + +ZTEST(obj_core, test_obj_core_condvar) +{ + k_condvar_init(&condvar2); + common_obj_core_test(K_OBJ_TYPE_CONDVAR_ID, "condition variable", + K_OBJ_CORE(&condvar1), K_OBJ_CORE(&condvar2)); +} + +ZTEST(obj_core, test_obj_core_event) +{ + k_event_init(&event2); + common_obj_core_test(K_OBJ_TYPE_EVENT_ID, "event", + K_OBJ_CORE(&event1), K_OBJ_CORE(&event2)); +} + +ZTEST(obj_core, test_obj_core_mutex) +{ + k_mutex_init(&mutex2); + common_obj_core_test(K_OBJ_TYPE_MUTEX_ID, "mutex", + K_OBJ_CORE(&mutex1), K_OBJ_CORE(&mutex2)); +} + +ZTEST(obj_core, test_obj_core_sem) +{ + k_sem_init(&sem2, 0, 1); + + common_obj_core_test(K_OBJ_TYPE_SEM_ID, "semaphore", + K_OBJ_CORE(&sem1), K_OBJ_CORE(&sem2)); +} + +ZTEST_SUITE(obj_core, NULL, NULL, + ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL); diff --git a/tests/kernel/obj_core/obj_core/testcase.yaml b/tests/kernel/obj_core/obj_core/testcase.yaml new file mode 100644 index 00000000000..e6bcafafc56 --- /dev/null +++ b/tests/kernel/obj_core/obj_core/testcase.yaml @@ -0,0 +1,9 @@ +tests: + kernel.obj_core: + tags: kernel + ignore_faults: true + integration_platforms: + - qemu_x86 + platform_exclude: + - qemu_x86_tiny + - qemu_x86_tiny@768 diff --git a/tests/kernel/obj_core/obj_core_stats/CMakeLists.txt b/tests/kernel/obj_core/obj_core_stats/CMakeLists.txt new file mode 100644 index 00000000000..a9c26c7493c --- /dev/null +++ b/tests/kernel/obj_core/obj_core_stats/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(obj_core) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/kernel/obj_core/obj_core_stats/prj.conf b/tests/kernel/obj_core/obj_core_stats/prj.conf new file mode 100644 index 00000000000..0e9e95a76cd --- /dev/null +++ b/tests/kernel/obj_core/obj_core_stats/prj.conf @@ -0,0 +1,7 @@ +CONFIG_ZTEST=y +CONFIG_OBJ_CORE=y +CONFIG_OBJ_CORE_STATS=y +CONFIG_SCHED_THREAD_USAGE=y +CONFIG_SCHED_THREAD_USAGE_ANALYSIS=y +CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION=y +CONFIG_SYS_MEM_BLOCKS=y diff --git a/tests/kernel/obj_core/obj_core_stats/src/main.c b/tests/kernel/obj_core/obj_core_stats/src/main.c new file mode 100644 index 00000000000..e46ecf510bb --- /dev/null +++ b/tests/kernel/obj_core/obj_core_stats/src/main.c @@ -0,0 +1,706 @@ +/* + * Copyright (c) 2023, Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +SYS_MEM_BLOCKS_DEFINE(mem_block, 32, 4, 16); /* Four 32 byte blocks */ + +K_MEM_SLAB_DEFINE(mem_slab, 32, 4, 16); /* Four 32 byte blocks */ + +#if !defined(CONFIG_ARCH_POSIX) && !defined(CONFIG_SPARC) && !defined(CONFIG_MIPS) +static void test_thread_entry(void *, void *, void *); +K_THREAD_DEFINE(test_thread, 1024 + CONFIG_TEST_EXTRA_STACK_SIZE, + test_thread_entry, NULL, NULL, NULL, + K_HIGHEST_THREAD_PRIO, 0, 0); + +K_SEM_DEFINE(wake_main_thread, 0, 1); +K_SEM_DEFINE(wake_test_thread, 0, 1); +#endif /* !CONFIG_ARCH_POSIX && !CONFIG_SPARC && !CONFIG_MIPS */ + +#if CONFIG_MP_MAX_NUM_CPUS > 1 +K_THREAD_STACK_ARRAY_DEFINE(busy_thread_stack, CONFIG_MP_MAX_NUM_CPUS - 1, + 512 + CONFIG_TEST_EXTRA_STACK_SIZE); + +struct k_thread busy_thread[CONFIG_MP_MAX_NUM_CPUS - 1]; + +void busy_thread_entry(void *p1, void *p2, void *p3) +{ + while (1) { + /* Busy loop to prevent CPU from entering idle */ + } +} + +#endif + +/***************** SYSTEM (CPUs and KERNEL) ******************/ + +/* + * As the k_obj_core_stats_xxx() APIs are essentially wrappers to the + * thread runtime stats APIs, limit this test to the same architectures as + * that thread runtime stats test. + */ + +#if !defined(CONFIG_ARCH_POSIX) && !defined(CONFIG_SPARC) && !defined(CONFIG_MIPS) +ZTEST(obj_core_stats_system, test_obj_core_stats_system) +{ + int status; + struct k_cycle_stats kernel_raw[CONFIG_MP_MAX_NUM_CPUS]; + struct k_cycle_stats cpu_raw; + struct k_thread_runtime_stats kernel_query; + struct k_thread_runtime_stats cpu_query; + struct k_thread_runtime_stats sum_query; + unsigned int i; + +#if CONFIG_MP_MAX_NUM_CPUS > 1 + + /* Create 1 busy thread for each core except the current */ + + int prio; + + prio = k_thread_priority_get(k_current_get()); + + for (i = 0; i < CONFIG_MP_MAX_NUM_CPUS - 1; i++) { + k_thread_create(&busy_thread[i], busy_thread_stack[i], + K_THREAD_STACK_SIZEOF(busy_thread_stack[i]), + busy_thread_entry, NULL, NULL, NULL, + prio + 10, 0, K_NO_WAIT); + } +#endif + + status = k_obj_core_stats_raw(K_OBJ_CORE(&_kernel), kernel_raw, + sizeof(kernel_raw)); + zassert_equal(status, 0, "Expected 0, got %d\n", status); + + /* + * Not much can be predicted for the raw stats aside from the + * the contents of the CPU sampling to be at least as large as + * kernel sampling. The same goes for the query stats. + */ + + for (i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) { + status = k_obj_core_stats_raw(K_OBJ_CORE(&_kernel.cpus[i]), + &cpu_raw, sizeof(cpu_raw)); + zassert_equal(status, 0, "Expected 0, got %d on CPU %u\n", + status, i); + + zassert_true(cpu_raw.total >= kernel_raw[i].total); +#ifdef CONFIG_SCHED_THREAD_USAGE_ANALYSIS + zassert_true(cpu_raw.current >= kernel_raw[i].current); + zassert_true(cpu_raw.longest >= kernel_raw[i].longest); + zassert_true(cpu_raw.num_windows >= kernel_raw[i].num_windows); +#endif + zassert_true(cpu_raw.track_usage == kernel_raw[i].track_usage); + } + + status = k_obj_core_stats_query(K_OBJ_CORE(&_kernel), &kernel_query, + sizeof(kernel_query)); + zassert_equal(status, 0, "Expected 0, got %d\n", status); + + sum_query = (struct k_thread_runtime_stats){}; + + for (i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) { + status = k_obj_core_stats_query(K_OBJ_CORE(&_kernel.cpus[i]), + &cpu_query, sizeof(cpu_query)); + zassert_equal(status, 0, "Expected 0, got %d on CPU %u\n", + status, i); + +#ifdef CONFIG_SCHED_THREAD_USAGE + sum_query.execution_cycles += cpu_query.execution_cycles; + sum_query.total_cycles += cpu_query.total_cycles; +#endif +#ifdef CONFIG_SCHED_THREAD_USAGE_ANALYSIS + sum_query.current_cycles += cpu_query.current_cycles; + sum_query.peak_cycles += cpu_query.peak_cycles; + sum_query.average_cycles += cpu_query.average_cycles; +#endif +#ifdef CONFIG_SCHED_THREAD_USAGE_ALL + sum_query.idle_cycles += cpu_query.idle_cycles; +#endif + } + +#ifdef CONFIG_SCHED_THREAD_USAGE + zassert_true(sum_query.execution_cycles >= kernel_query.execution_cycles); + zassert_true(sum_query.total_cycles >= kernel_query.total_cycles); +#endif +#ifdef CONFIG_SCHED_THREAD_USAGE_ANALYSIS + zassert_true(sum_query.current_cycles >= kernel_query.current_cycles); + zassert_true(sum_query.peak_cycles >= kernel_query.peak_cycles); + zassert_true(sum_query.average_cycles >= kernel_query.average_cycles); +#endif +#ifdef CONFIG_SCHED_THREAD_USAGE_ALL + zassert_true(sum_query.idle_cycles >= kernel_query.idle_cycles); +#endif +} +#endif /* !CONFIG_ARCH_POSIX && !CONFIG_SPARC && !CONFIG_MIPS */ + +ZTEST(obj_core_stats_system, test_obj_core_stats_cpu_reset) +{ + int status; + + for (unsigned int i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) { + status = k_obj_core_stats_reset(K_OBJ_CORE(&_kernel.cpus[i])); + zassert_equal(status, -ENOTSUP, + "Expected %d, got %d on CPU%d\n", + -ENOTSUP, status, i); + } +} + +ZTEST(obj_core_stats_system, test_obj_core_stats_cpu_disable) +{ + int status; + + for (unsigned int i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) { + status = k_obj_core_stats_disable(K_OBJ_CORE(&_kernel.cpus[i])); + zassert_equal(status, -ENOTSUP, + "Expected %d, got %d on CPU%d\n", + -ENOTSUP, status, i); + } +} + +ZTEST(obj_core_stats_system, test_obj_core_stats_cpu_enable) +{ + int status; + + for (unsigned int i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) { + status = k_obj_core_stats_enable(K_OBJ_CORE(&_kernel.cpus[i])); + zassert_equal(status, -ENOTSUP, + "Expected %d, got %d on CPU%d\n", + -ENOTSUP, status, i); + } +} + +ZTEST(obj_core_stats_system, test_obj_core_stats_kernel_reset) +{ + int status; + + status = k_obj_core_stats_reset(K_OBJ_CORE(&_kernel)); + zassert_equal(status, -ENOTSUP, "Expected %d, got %d\n", + -ENOTSUP, status); +} + +ZTEST(obj_core_stats_system, test_obj_core_stats_kernel_disable) +{ + int status; + + status = k_obj_core_stats_disable(K_OBJ_CORE(&_kernel)); + zassert_equal(status, -ENOTSUP, "Expected %d, got %d\n", + -ENOTSUP, status); +} + +ZTEST(obj_core_stats_system, test_obj_core_stats_kernel_enable) +{ + int status; + + status = k_obj_core_stats_enable(K_OBJ_CORE(&_kernel)); + zassert_equal(status, -ENOTSUP, "Expected %d, got %d\n", + -ENOTSUP, status); +} + +/***************** THREADS ******************/ + +#if !defined(CONFIG_ARCH_POSIX) && !defined(CONFIG_SPARC) && !defined(CONFIG_MIPS) +/* + * As the k_obj_core_stats_xxx() APIs are essentially wrappers to the + * thread runtime stats APIs, limit this test to the same architectures as + * that thread runtime stats test. + */ +void test_thread_entry(void *p1, void *p2, void *p3) +{ + while (1) { + k_busy_wait(10000); + + k_sem_give(&wake_main_thread); + k_sem_take(&wake_test_thread, K_FOREVER); + } +} + +ZTEST(obj_core_stats_thread, test_obj_core_stats_thread_test) +{ + struct k_cycle_stats raw1; + struct k_cycle_stats raw2; + struct k_thread_runtime_stats query1; + struct k_thread_runtime_stats query2; + struct k_thread_runtime_stats query3; + int status; + + k_sem_take(&wake_main_thread, K_FOREVER); + k_busy_wait(10000); + + /* test_thread should now be blocked on wake_test_thread */ + + status = k_obj_core_stats_raw(K_OBJ_CORE(test_thread), &raw1, + sizeof(raw1)); + zassert_equal(status, 0, "Expected 0, got %d", status); + + status = k_obj_core_stats_query(K_OBJ_CORE(test_thread), &query1, + sizeof(query1)); + zassert_equal(status, 0, "Expected 0, got %d", status); + + /* + * Busy wait for 10 msec. As test_thread should still be blocked, + * its stats data should not change. + */ + + k_busy_wait(10000); + + status = k_obj_core_stats_raw(K_OBJ_CORE(test_thread), &raw2, + sizeof(raw2)); + zassert_equal(status, 0, "Expected 0, got %d", status); + + status = k_obj_core_stats_query(K_OBJ_CORE(test_thread), &query2, + sizeof(query2)); + zassert_equal(status, 0, "Expected 0, got %d", status); + + zassert_mem_equal(&raw1, &raw2, sizeof(raw1), + "Thread raw stats changed while blocked\n"); + zassert_mem_equal(&query1, &query2, sizeof(query1), + "Thread query stats changed while blocked\n"); + + /* + * Let test_thread execute for a short bit and then re-sample the + * stats. As the k_obj_core_stats_query() backend is identical to + * that of k_thread_runtime_stats_get(), their queries should be + * identical (and different from the previous sample). + */ + + k_sem_give(&wake_test_thread); + k_sem_take(&wake_main_thread, K_FOREVER); + k_busy_wait(10000); + + /* test_thread should now be blocked. */ + + status = k_obj_core_stats_query(K_OBJ_CORE(test_thread), &query2, + sizeof(query3)); + zassert_equal(status, 0, "Expected 0, got %d\n", status); + + status = k_thread_runtime_stats_get(test_thread, &query3); + zassert_equal(status, 0, "Expected 0, got %d\n", status); + zassert_mem_equal(&query2, &query3, sizeof(query2), + "Queries not equal!\n"); + +#ifdef CONFIG_SCHED_THREAD_USAGE + zassert_true(query2.execution_cycles > query1.execution_cycles, + "Execution cycles did not increase\n"); + zassert_true(query2.total_cycles > query1.total_cycles, + "Total cycles did not increase\n"); +#endif + +#ifdef CONFIG_SCHED_THREAD_USAGE_ANALYSIS + + /* + * [current_cycles], [peak_cycles] and [average_cycles] can not be + * predicted by this test. + */ + +#endif + +#ifdef CONFIG_SCHED_THREAD_USAGE_ALL + zassert_equal(query2.idle_cycles, 0, + "Expected 0, got %llu\n", query2.idle_cycles); +#endif + + /* Reset the stats */ + + status = k_obj_core_stats_reset(K_OBJ_CORE(test_thread)); + zassert_equal(status, 0, "Expected 0, got %d\n", status); + + status = k_obj_core_stats_query(K_OBJ_CORE(test_thread), + &query3, sizeof(query3)); + zassert_equal(status, 0, "Expected 0, got %d\n", status); + +#ifdef CONFIG_SCHED_THREAD_USAGE + zassert_equal(query3.execution_cycles, 0, + "Expected 0, got %llu\n", query3.execution_cycles); + zassert_equal(query3.total_cycles, 0, + "Expected 0, got %llu\n", query3.total_cycles); +#endif + +#ifdef CONFIG_SCHED_THREAD_USAGE_ANALYSIS + zassert_equal(query3.current_cycles, 0, + "Expected 0, got %llu\n", query3.current_cycles); + zassert_equal(query3.peak_cycles, 0, + "Expected 0, got %llu\n", query3.peak_cycles); + zassert_equal(query3.average_cycles, 0, + "Expected 0, got %llu\n", query3.average_cycles); +#endif + +#ifdef CONFIG_SCHED_THREAD_USAGE_ALL + zassert_equal(query3.idle_cycles, 0, + "Expected 0, got %llu\n", query3.idle_cycles); +#endif + + /* Disable the stats (re-using query2 and query3) */ + + status = k_obj_core_stats_disable(K_OBJ_CORE(test_thread)); + zassert_equal(status, 0, "Expected 0, got %llu\n", status); + + k_sem_give(&wake_test_thread); + k_sem_take(&wake_main_thread, K_FOREVER); + k_busy_wait(10000); + + k_obj_core_stats_query(K_OBJ_CORE(test_thread), + &query2, sizeof(query2)); + + zassert_mem_equal(&query2, &query3, sizeof(query2), + "Stats changed while disabled!\n"); + + /* Enable the stats */ + + status = k_obj_core_stats_enable(K_OBJ_CORE(test_thread)); + zassert_equal(status, 0, "Expected 0, got %llu\n", status); + + k_sem_give(&wake_test_thread); + k_sem_take(&wake_main_thread, K_FOREVER); + k_busy_wait(10000); + + k_obj_core_stats_query(K_OBJ_CORE(test_thread), + &query3, sizeof(query3)); + + /* We can not predict the stats, but they should be non-zero. */ + +#ifdef CONFIG_SCHED_THREAD_USAGE + zassert_true(query3.execution_cycles > 0); + zassert_true(query3.total_cycles > 0); +#endif +#ifdef CONFIG_SCHED_THREAD_USAGE + zassert_true(query3.current_cycles > 0); + zassert_true(query3.peak_cycles > 0); + zassert_true(query3.average_cycles > 0); +#endif +#ifdef CONFIG_SCHED_THREAD_USAGE_ALL + zassert_true(query3.idle_cycles == 0); +#endif + + k_thread_abort(test_thread); +} +#endif /* !CONFIG_ARCH_POSIX && !CONFIG_SPARC && !CONFIG_MIPS */ + +/***************** SYSTEM MEMORY BLOCKS *********************/ + +ZTEST(obj_core_stats_mem_block, test_sys_mem_block_enable) +{ + int status; + + status = k_obj_core_stats_enable(K_OBJ_CORE(&mem_block)); + zassert_equal(status, -ENOTSUP, + "Not supposed to be supported. Got %d, not %d\n", + status, -ENOTSUP); +} + +ZTEST(obj_core_stats_mem_block, test_sys_mem_block_disable) +{ + int status; + + status = k_obj_core_stats_disable(K_OBJ_CORE(&mem_block)); + zassert_equal(status, -ENOTSUP, + "Not supposed to be supported. Got %d, not %d\n", + status, -ENOTSUP); +} + +static void test_mem_block_raw(const char *str, + struct sys_mem_blocks_info *expected) +{ + int status; + struct sys_mem_blocks_info raw; + + status = k_obj_core_stats_raw(K_OBJ_CORE(&mem_block), &raw, + sizeof(raw)); + zassert_equal(status, 0, + "%s: Failed to get raw stats (%d)\n", str, status); + + zassert_equal(raw.num_blocks, expected->num_blocks, + "%s: Expected %u blocks, got %u\n", + str, expected->num_blocks, raw.num_blocks); + zassert_equal(raw.blk_sz_shift, expected->blk_sz_shift, + "%s: Expected blk_sz_shift=%u, got %u\n", + str, expected->blk_sz_shift, raw.blk_sz_shift); +#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS + zassert_equal(raw.used_blocks, expected->used_blocks, + "%s: Expected %u used, got %d\n", + str, expected->used_blocks, raw.used_blocks); + zassert_equal(raw.max_used_blocks, expected->max_used_blocks, + "%s: Expected max %u used, got %d\n", + str, expected->max_used_blocks, raw.max_used_blocks); +#endif +} + +static void test_mem_block_query(const char *str, + struct sys_memory_stats *expected) +{ + struct sys_memory_stats query; + int status; + + status = k_obj_core_stats_query(K_OBJ_CORE(&mem_block), &query, + sizeof(query)); + zassert_equal(status, 0, + "%s: Failed to get query stats (%d)\n", str, status); + + zassert_equal(query.free_bytes, expected->free_bytes, + "%s: Expected %u free bytes, got %u\n", + str, expected->free_bytes, query.free_bytes); +#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS + zassert_equal(query.allocated_bytes, expected->allocated_bytes, + "%s: Expected %u allocated bytes, got %u\n", + str, expected->allocated_bytes, query.allocated_bytes); + zassert_equal(query.max_allocated_bytes, expected->max_allocated_bytes, + "%s: Expected %u max_allocated bytes, got %d\n", + str, expected->max_allocated_bytes, + query.max_allocated_bytes); +#endif +} + +ZTEST(obj_core_stats_mem_block, test_obj_core_stats_mem_block) +{ + struct sys_mem_blocks_info raw = { + .num_blocks = 4, .blk_sz_shift = 5, +#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS + .used_blocks = 0, .max_used_blocks = 0 +#endif + }; + struct sys_memory_stats query = { + .free_bytes = 128, + .allocated_bytes = 0, + .max_allocated_bytes = 0 + }; + void *mem1; + void *mem2; + int status; + + /* + * As the ordering of the "raw", "query" and "reset" tests matter, + * they have been grouped together here. As they are for the most + * wrappers for the runtime stats routines, minimal testing is + * being done. + */ + + /* Initial checks */ + + test_mem_block_raw("Initial", &raw); + test_mem_block_query("Initial", &query); + + /* Allocate 1st block */ + + status = sys_mem_blocks_alloc(&mem_block, 1, &mem1); + zassert_equal(status, 0, "Expected 0, got %d\n", status); + + query.free_bytes -= 32; + query.allocated_bytes += 32; +#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS + raw.used_blocks++; + raw.max_used_blocks++; + query.max_allocated_bytes += 32; +#endif + test_mem_block_raw("1st Alloc", &raw); + test_mem_block_query("1st Alloc", &query); + + /* Allocate 2nd block */ + + status = sys_mem_blocks_alloc(&mem_block, 1, &mem2); + zassert_equal(status, 0, "Expected 0, got %d\n", status); + + query.free_bytes -= 32; + query.allocated_bytes += 32; +#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS + raw.used_blocks++; + raw.max_used_blocks++; + query.max_allocated_bytes += 32; +#endif + test_mem_block_raw("2nd Alloc", &raw); + test_mem_block_query("2nd Alloc", &query); + + /* Free 1st block */ + + sys_mem_blocks_free(&mem_block, 1, &mem1); + + query.free_bytes += 32; + query.allocated_bytes -= 32; +#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS + raw.used_blocks--; +#endif + test_mem_block_raw("Free 1st", &raw); + test_mem_block_query("Free 1st", &query); + + /* Reset the mem block stats */ + + status = k_obj_core_stats_reset(K_OBJ_CORE(&mem_block)); + zassert_equal(status, 0, "Expected 0, got %d\n", status); +#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS + raw.max_used_blocks = raw.used_blocks; + query.max_allocated_bytes = query.allocated_bytes; +#endif + test_mem_block_raw("Reset", &raw); + test_mem_block_query("Reset", &query); + + /* Cleanup - Free 2nd block */ + sys_mem_blocks_free(&mem_block, 1, &mem2); +} + +/***************** MEMORY SLABS *********************/ + +ZTEST(obj_core_stats_mem_slab, test_mem_slab_enable) +{ + int status; + + status = k_obj_core_stats_disable(K_OBJ_CORE(&mem_slab)); + zassert_equal(status, -ENOTSUP, + "Not supposed to be supported. Got %d, not %d\n", + status, -ENOTSUP); +} + +ZTEST(obj_core_stats_mem_slab, test_mem_slab_disable) +{ + int status; + + status = k_obj_core_stats_disable(K_OBJ_CORE(&mem_slab)); + zassert_equal(status, -ENOTSUP, + "Not supposed to be supported. Got %d, not %d\n", + status, -ENOTSUP); +} + +static void test_mem_slab_raw(const char *str, struct k_mem_slab_info *expected) +{ + int status; + struct k_mem_slab_info raw; + + status = k_obj_core_stats_raw(K_OBJ_CORE(&mem_slab), &raw, + sizeof(raw)); + zassert_equal(status, 0, + "%s: Failed to get raw stats (%d)\n", str, status); + + zassert_equal(raw.num_blocks, expected->num_blocks, + "%s: Expected %u blocks, got %u\n", + str, expected->num_blocks, raw.num_blocks); + zassert_equal(raw.block_size, expected->block_size, + "%s: Expected block size=%u blocks, got %u\n", + str, expected->block_size, raw.block_size); + zassert_equal(raw.num_used, expected->num_used, + "%s: Expected %u used, got %d\n", + str, expected->num_used, raw.num_used); +#ifdef CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION + zassert_equal(raw.max_used, expected->max_used, + "%s: Expected max %u used, got %d\n", + str, expected->max_used, raw.max_used); +#endif +} + +static void test_mem_slab_query(const char *str, + struct sys_memory_stats *expected) +{ + struct sys_memory_stats query; + int status; + + status = k_obj_core_stats_query(K_OBJ_CORE(&mem_slab), &query, + sizeof(query)); + zassert_equal(status, 0, + "%s: Failed to get query stats (%d)\n", str, status); + + zassert_equal(query.free_bytes, expected->free_bytes, + "%s: Expected %u free bytes, got %u\n", + str, expected->free_bytes, query.free_bytes); + zassert_equal(query.allocated_bytes, expected->allocated_bytes, + "%s: Expected %u allocated bytes, got %u\n", + str, expected->allocated_bytes, query.allocated_bytes); + zassert_equal(query.max_allocated_bytes, expected->max_allocated_bytes, + "%s: Expected %u max_allocated bytes, got %d\n", + str, expected->max_allocated_bytes, + query.max_allocated_bytes); +} + +ZTEST(obj_core_stats_mem_slab, test_obj_core_stats_mem_slab) +{ + struct k_mem_slab_info raw = { + .num_blocks = 4, .block_size = 32, .num_used = 0, +#ifdef CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION + .max_used = 0 +#endif + }; + struct sys_memory_stats query = { + .free_bytes = 128, + .allocated_bytes = 0, + .max_allocated_bytes = 0 + }; + void *mem1; + void *mem2; + int status; + + /* + * As the ordering of the "raw", "query" and "reset" tests matter, + * they have been grouped together here. As they are for the most + * wrappers for the runtime stats routines, minimal testing is + * being done. + */ + + + /* Initial checks */ + + test_mem_slab_raw("Initial", &raw); + test_mem_slab_query("Initial", &query); + + /* Allocate 1st block */ + + status = k_mem_slab_alloc(&mem_slab, &mem1, K_FOREVER); + zassert_equal(status, 0, "Expected 0, got %d\n", status); + + raw.num_used++; + query.free_bytes -= 32; + query.allocated_bytes += 32; +#ifdef CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION + raw.max_used++; + query.max_allocated_bytes += 32; +#endif + test_mem_slab_raw("1st Alloc", &raw); + test_mem_slab_query("1st Alloc", &query); + + /* Allocate 2nd block */ + + status = k_mem_slab_alloc(&mem_slab, &mem2, K_FOREVER); + zassert_equal(status, 0, "Expected 0, got %d\n", status); + + raw.num_used++; + query.free_bytes -= 32; + query.allocated_bytes += 32; +#ifdef CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION + raw.max_used++; + query.max_allocated_bytes += 32; +#endif + test_mem_slab_raw("2nd Alloc", &raw); + test_mem_slab_query("2nd Alloc", &query); + + /* Free 1st block */ + k_mem_slab_free(&mem_slab, mem1); + + raw.num_used--; + query.free_bytes += 32; + query.allocated_bytes -= 32; + test_mem_slab_raw("Free 1st", &raw); + test_mem_slab_query("Free 1st", &query); + + /* Reset the mem slab stats */ + status = k_obj_core_stats_reset(K_OBJ_CORE(&mem_slab)); + zassert_equal(status, 0, "Expected 0, got %d\n", status); +#ifdef CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION + raw.max_used = raw.num_used; + query.max_allocated_bytes = query.allocated_bytes; +#endif + test_mem_slab_raw("Reset", &raw); + test_mem_slab_query("Reset", &query); + + /* Cleanup - Free 2nd block */ + k_mem_slab_free(&mem_slab, mem2); +} + +ZTEST_SUITE(obj_core_stats_system, NULL, NULL, + ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL); + +ZTEST_SUITE(obj_core_stats_thread, NULL, NULL, + ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL); + +ZTEST_SUITE(obj_core_stats_mem_block, NULL, NULL, + ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL); + +ZTEST_SUITE(obj_core_stats_mem_slab, NULL, NULL, + ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL); diff --git a/tests/kernel/obj_core/obj_core_stats/testcase.yaml b/tests/kernel/obj_core/obj_core_stats/testcase.yaml new file mode 100644 index 00000000000..28bbaf1ec71 --- /dev/null +++ b/tests/kernel/obj_core/obj_core_stats/testcase.yaml @@ -0,0 +1,9 @@ +tests: + kernel.obj_core.stats: + tags: kernel + ignore_faults: true + integration_platforms: + - qemu_x86 + platform_exclude: + - qemu_x86_tiny + - qemu_x86_tiny@768 diff --git a/tests/kernel/obj_core/obj_core_stats_api/CMakeLists.txt b/tests/kernel/obj_core/obj_core_stats_api/CMakeLists.txt new file mode 100644 index 00000000000..a9c26c7493c --- /dev/null +++ b/tests/kernel/obj_core/obj_core_stats_api/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(obj_core) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/kernel/obj_core/obj_core_stats_api/prj.conf b/tests/kernel/obj_core/obj_core_stats_api/prj.conf new file mode 100644 index 00000000000..d163a31e105 --- /dev/null +++ b/tests/kernel/obj_core/obj_core_stats_api/prj.conf @@ -0,0 +1,6 @@ +CONFIG_ZTEST=y +CONFIG_OBJ_CORE=y +CONFIG_OBJ_CORE_STATS=y +CONFIG_PIPES=y +CONFIG_SCHED_THREAD_USAGE=y +CONFIG_SCHED_THREAD_USAGE_ANALYSIS=y diff --git a/tests/kernel/obj_core/obj_core_stats_api/src/main.c b/tests/kernel/obj_core/obj_core_stats_api/src/main.c new file mode 100644 index 00000000000..bfd9e881779 --- /dev/null +++ b/tests/kernel/obj_core/obj_core_stats_api/src/main.c @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2023, Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +K_SEM_DEFINE(test_sem, 0, 1); + +static void test_thread_entry(void *, void *, void *); +K_THREAD_DEFINE(test_thread, 512 + CONFIG_TEST_EXTRA_STACK_SIZE, + test_thread_entry, NULL, NULL, NULL, + K_HIGHEST_THREAD_PRIO, 0, 0); + +/* + * As the test mucks about with the set of object core statistics operators + * for the test_thread, we want to ensure that no other test mucks with it + * at an inopportune time. This could also be done by setting the CPU count + * in the prj.conf to 1. However, for this test to allow it to be run on both + * UP and SMP systems the mutex is being used. + */ + +K_MUTEX_DEFINE(test_mutex); + +static void test_thread_entry(void *p1, void *p2, void *p3) +{ + k_sem_take(&test_sem, K_FOREVER); +} + +ZTEST(obj_core_stats_api, test_obj_core_stats_enable) +{ + int status; + int (*saved_enable)(struct k_obj_core *obj_core); + + k_mutex_lock(&test_mutex, K_FOREVER); + + /* + * Attempt to enable stats for an object core that is not enabled + * for statistics (semaphores). + */ + + status = k_obj_core_stats_enable(K_OBJ_CORE(&test_sem)); + zassert_equal(status, -ENOTSUP, + "Expected %d, got %d\n", -ENOTSUP, status); + + saved_enable = K_OBJ_CORE(test_thread)->type->stats_desc->enable; + K_OBJ_CORE(test_thread)->type->stats_desc->enable = NULL; + status = k_obj_core_stats_enable(K_OBJ_CORE(test_thread)); + zassert_equal(status, -ENOTSUP, + "Expected %d, got %d\n", -ENOTSUP, status); + K_OBJ_CORE(test_thread)->type->stats_desc->enable = saved_enable; + + /* + * Note: Testing the stats enable function pointer is done in another + * set of tests. + */ + + k_mutex_unlock(&test_mutex); +} + +ZTEST(obj_core_stats_api, test_obj_core_stats_disable) +{ + int status; + int (*saved_disable)(struct k_obj_core *obj_core); + + k_mutex_lock(&test_mutex, K_FOREVER); + + /* + * Attempt to disable stats for an object core that is not enabled + * for statistics (semaphores). + */ + + status = k_obj_core_stats_disable(K_OBJ_CORE(&test_sem)); + zassert_equal(status, -ENOTSUP, + "Expected %d, got %d\n", -ENOTSUP, status); + + saved_disable = K_OBJ_CORE(test_thread)->type->stats_desc->disable; + K_OBJ_CORE(test_thread)->type->stats_desc->disable = NULL; + status = k_obj_core_stats_disable(K_OBJ_CORE(test_thread)); + zassert_equal(status, -ENOTSUP, + "Expected %d, got %d\n", -ENOTSUP, status); + K_OBJ_CORE(test_thread)->type->stats_desc->disable = saved_disable; + + /* + * Note: Testing the stats disable function pointer is done in + * another set of tests. + */ + + k_mutex_unlock(&test_mutex); +} + +ZTEST(obj_core_stats_api, test_obj_core_stats_reset) +{ + int status; + int (*saved_reset)(struct k_obj_core *obj_core); + + k_mutex_lock(&test_mutex, K_FOREVER); + + /* + * Attempt to reset stats for an object core that is not enabled + * for statistics (semaphores). + */ + + status = k_obj_core_stats_reset(K_OBJ_CORE(&test_sem)); + zassert_equal(status, -ENOTSUP, + "Expected %d, got %d\n", -ENOTSUP, status); + + saved_reset = K_OBJ_CORE(test_thread)->type->stats_desc->reset; + K_OBJ_CORE(test_thread)->type->stats_desc->reset = NULL; + status = k_obj_core_stats_reset(K_OBJ_CORE(test_thread)); + zassert_equal(status, -ENOTSUP, + "Expected %d, got %d\n", -ENOTSUP, status); + K_OBJ_CORE(test_thread)->type->stats_desc->reset = saved_reset; + + /* + * Note: Testing the stats reset function pointer is done in + * another set of tests. + */ + + k_mutex_unlock(&test_mutex); +} + +ZTEST(obj_core_stats_api, test_obj_core_stats_query) +{ + int status; + struct k_thread_runtime_stats query; + int (*saved_query)(struct k_obj_core *obj_core, void *stats); + + k_mutex_lock(&test_mutex, K_FOREVER); + + /* + * Attempt to query stats for an object core that is not enabled + * for statistics (semaphores). + */ + + status = k_obj_core_stats_query(K_OBJ_CORE(&test_sem), &query, + sizeof(struct k_thread_runtime_stats)); + zassert_equal(status, -ENOTSUP, + "Expected %d, got %d\n", -ENOTSUP, status); + + saved_query = K_OBJ_CORE(test_thread)->type->stats_desc->query; + K_OBJ_CORE(test_thread)->type->stats_desc->query = NULL; + status = k_obj_core_stats_query(K_OBJ_CORE(test_thread), + &query, sizeof(query)); + zassert_equal(status, -ENOTSUP, + "Expected %d, got %d\n", -ENOTSUP, status); + K_OBJ_CORE(test_thread)->type->stats_desc->query = saved_query; + + /* + * Note: Testing the stats query function pointer is done in + * another set of tests. + */ + + k_mutex_unlock(&test_mutex); +} + +ZTEST(obj_core_stats_api, test_obj_core_stats_raw) +{ + int status; + char buffer[sizeof(struct k_cycle_stats)]; + int (*saved_raw)(struct k_obj_core *obj_core, void *stats); + void *saved_stats; + + k_mutex_lock(&test_mutex, K_FOREVER); + + /* + * Attempt to get raw stats for an object core that is not enabled + * for statistics (semaphores). + */ + + status = k_obj_core_stats_raw(K_OBJ_CORE(&test_sem), + buffer, sizeof(buffer)); + zassert_equal(status, -ENOTSUP, + "Expected %d, got %d\n", -ENOTSUP, status); + + /* Force there to be no means to obtain raw data */ + + saved_raw = K_OBJ_CORE(test_thread)->type->stats_desc->raw; + K_OBJ_CORE(test_thread)->type->stats_desc->raw = NULL; + status = k_obj_core_stats_raw(K_OBJ_CORE(test_thread), + buffer, sizeof(buffer)); + zassert_equal(status, -ENOTSUP, + "Expected %d, got %d\n", -ENOTSUP, status); + + K_OBJ_CORE(test_thread)->type->stats_desc->raw = saved_raw; + + /* + * Verify that passing a buffer with unexpected length + * returns the expected error (-EINVAL). + */ + + status = k_obj_core_stats_raw(K_OBJ_CORE(test_thread), + buffer, 0); + zassert_equal(status, -EINVAL, + "Expected %d, got %d\n", -EINVAL, status); + + /* + * Verify that if the object core's pointer to raw stats data + * is NULL, we get the expected error (-EINVAL). + */ + + saved_stats = K_OBJ_CORE(test_thread)->stats; + K_OBJ_CORE(test_thread)->stats = NULL; + status = k_obj_core_stats_raw(K_OBJ_CORE(test_thread), + buffer, sizeof(buffer)); + zassert_equal(status, -EINVAL, + "Expected %d, got %d\n", -EINVAL, status); + K_OBJ_CORE(test_thread)->stats = saved_stats; + + /* + * Note: Further testing the stats query function pointer is done in + * another set of tests. + */ + + k_mutex_unlock(&test_mutex); +} + +ZTEST(obj_core_stats_api, test_obj_core_stats_dereg) +{ + int status; + char buffer[sizeof(struct k_cycle_stats)]; + + k_mutex_lock(&test_mutex, K_FOREVER); + + /* + * Attempt to de-register stats for an object core that does + * not have them enabled (semaphores). + */ + + status = k_obj_core_stats_deregister(K_OBJ_CORE(&test_sem)); + zassert_equal(status, -ENOTSUP, "Expected %d, got %d\n", 0, -ENOTSUP); + + /* De-register stats for the test thread. */ + + status = k_obj_core_stats_deregister(K_OBJ_CORE(test_thread)); + zassert_equal(status, 0, "Expected %d, got %d\n", 0, status); + + /* Attempt to get raw stats for the de-registered thread */ + + status = k_obj_core_stats_raw(K_OBJ_CORE(test_thread), + buffer, sizeof(buffer)); + zassert_equal(status, -EINVAL, + "Expected %d, got %d\n", -EINVAL, status); + + /* Restore the raw stats */ + + status = k_obj_core_stats_register(K_OBJ_CORE(test_thread), + &test_thread->base.usage, + sizeof(struct k_cycle_stats)); + + k_mutex_unlock(&test_mutex); +} + +ZTEST(obj_core_stats_api, test_obj_core_stats_register) +{ + int status; + char buffer[sizeof(struct k_cycle_stats)]; + char data[sizeof(struct k_cycle_stats)]; + + /* + * Ensure only one thread is mucking around with test_thread + * at a time. + */ + + k_mutex_lock(&test_mutex, K_FOREVER); + + /* + * Attempt to register stats for a semaphore + * (which does not currently exist). + */ + + status = k_obj_core_stats_register(K_OBJ_CORE(&test_sem), + (void *)0xBAD0BAD1, + 42); + + zassert_equal(status, -ENOTSUP, + "Expected %d, got %d\n" + "--Were semaphore stats recently implemented?\n", + -ENOTSUP, status); + /* + * Attempt to register stats for a thread with the wrong buffer + * size. + */ + + status = k_obj_core_stats_register(K_OBJ_CORE(test_thread), + buffer, sizeof(buffer) + 42); + + zassert_equal(status, -EINVAL, + "Expected %d, got %d\n", -EINVAL, status); + + /* + * Attempt to register stats for a thread with the right buffer + * size. + */ + + status = k_obj_core_stats_register(K_OBJ_CORE(test_thread), + buffer, sizeof(buffer)); + + zassert_equal(status, 0, + "Failed to change raw buffer pointer (%d)\n", status); + + memset(buffer, 0xaa, sizeof(buffer)); + memset(data, 0x00, sizeof(data)); + + status = k_obj_core_stats_raw(K_OBJ_CORE(test_thread), + data, sizeof(data)); + zassert_equal(status, 0, "Expected %d, got %d\n", 0, status); + + zassert_mem_equal(buffer, data, sizeof(buffer), + "Test thread raw stats buffer was not changed\n"); + + /* Restore the test thread's raw stats buffer */ + + status = k_obj_core_stats_register(K_OBJ_CORE(test_thread), + &test_thread->base.usage, + sizeof(test_thread->base.usage)); + zassert_equal(status, 0, + "Expected %d, got %d\n", 0, status); + + k_mutex_unlock(&test_mutex); +} + +ZTEST_SUITE(obj_core_stats_api, NULL, NULL, + ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL); diff --git a/tests/kernel/obj_core/obj_core_stats_api/testcase.yaml b/tests/kernel/obj_core/obj_core_stats_api/testcase.yaml new file mode 100644 index 00000000000..c17ff99e213 --- /dev/null +++ b/tests/kernel/obj_core/obj_core_stats_api/testcase.yaml @@ -0,0 +1,9 @@ +tests: + kernel.obj_core.stats.api: + tags: kernel + ignore_faults: true + integration_platforms: + - qemu_x86 + platform_exclude: + - qemu_x86_tiny + - qemu_x86_tiny@768 diff --git a/tests/kernel/obj_tracking/prj.conf b/tests/kernel/obj_tracking/prj.conf index 3e52a83f308..38956d67953 100644 --- a/tests/kernel/obj_tracking/prj.conf +++ b/tests/kernel/obj_tracking/prj.conf @@ -3,6 +3,5 @@ CONFIG_IRQ_OFFLOAD=y CONFIG_TRACING=y CONFIG_TRACING_OBJECT_TRACKING=y CONFIG_TRACING_NONE=y -CONFIG_ZTEST_NEW_API=y CONFIG_PIPES=y CONFIG_EVENTS=y diff --git a/tests/kernel/pending/prj.conf b/tests/kernel/pending/prj.conf index 2e877ea403a..f8d48f84037 100644 --- a/tests/kernel/pending/prj.conf +++ b/tests/kernel/pending/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y CONFIG_MP_MAX_NUM_CPUS=1 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/pipe/pipe/prj.conf b/tests/kernel/pipe/pipe/prj.conf index 36ceb4e4501..05f0c74d408 100644 --- a/tests/kernel/pipe/pipe/prj.conf +++ b/tests/kernel/pipe/pipe/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y CONFIG_TEST_USERSPACE=y CONFIG_MP_MAX_NUM_CPUS=1 -CONFIG_ZTEST_NEW_API=y CONFIG_PIPES=y diff --git a/tests/kernel/pipe/pipe_api/prj.conf b/tests/kernel/pipe/pipe_api/prj.conf index 8afa8604aca..d080e2fbdbd 100644 --- a/tests/kernel/pipe/pipe_api/prj.conf +++ b/tests/kernel/pipe/pipe_api/prj.conf @@ -4,5 +4,4 @@ CONFIG_TEST_USERSPACE=y CONFIG_DYNAMIC_OBJECTS=y CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_ZTEST_FATAL_HOOK=y -CONFIG_ZTEST_NEW_API=y CONFIG_PIPES=y diff --git a/tests/kernel/pipe/pipe_api/src/test_pipe_contexts.c b/tests/kernel/pipe/pipe_api/src/test_pipe_contexts.c index 2d14dfad1a3..3c7a119bf41 100644 --- a/tests/kernel/pipe/pipe_api/src/test_pipe_contexts.c +++ b/tests/kernel/pipe/pipe_api/src/test_pipe_contexts.c @@ -437,7 +437,6 @@ ZTEST(pipe_api, test_pipe_get_large) */ ZTEST(pipe_api, test_pipe_reader_wait) { - /**TESTPOINT: test k_pipe_block_put with semaphore*/ k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, thread_handler, &kpipe1, NULL, NULL, K_PRIO_PREEMPT(0), 0, K_NO_WAIT); diff --git a/tests/kernel/poll/prj.conf b/tests/kernel/poll/prj.conf index 43621e0d7eb..1369b5d2775 100644 --- a/tests/kernel/poll/prj.conf +++ b/tests/kernel/poll/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_POLL=y CONFIG_DYNAMIC_OBJECTS=y CONFIG_TEST_USERSPACE=y diff --git a/tests/kernel/poll/src/test_poll.c b/tests/kernel/poll/src/test_poll.c index 3faa591826a..8af64040a0c 100644 --- a/tests/kernel/poll/src/test_poll.c +++ b/tests/kernel/poll/src/test_poll.c @@ -787,52 +787,3 @@ ZTEST(poll_api_1cpu, test_poll_zero_events) zassert_equal(k_poll(&event, 0, K_MSEC(50)), -EAGAIN); } - -/* subthread entry */ -void polling_event(void *p1, void *p2, void *p3) -{ - k_poll(p1, 1, K_FOREVER); -} - -/** - * @brief Detect is_polling is false in signal_poll_event() - * - * @details - * Define and initialize a signal event, and spawn a thread to - * poll event, and set dticks as invalid, check if the value - * of is_polling in function signal_poll_event(). - * - * @ingroup kernel_poll_tests - */ -ZTEST(poll_api_1cpu, test_detect_is_polling) -{ - k_poll_signal_init(&test_signal); - - struct k_thread *p = &test_thread; - struct k_poll_event events[1] = { - K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL, - K_POLL_MODE_NOTIFY_ONLY, - &test_signal), - }; - - k_tid_t tid = k_thread_create(&test_thread, test_stack, - K_THREAD_STACK_SIZEOF(test_stack), polling_event, - events, NULL, NULL, K_PRIO_PREEMPT(0), - K_INHERIT_PERMS, K_NO_WAIT); - - /* Set up the thread timeout value to check if - * what happened if dticks is invalid. - */ - p->base.timeout.dticks = _EXPIRED; - /* Wait for register event successfully */ - k_sleep(K_MSEC(50)); - - /* Raise a signal */ - int ret = k_poll_signal_raise(&test_signal, 0x1337); - - zassert_true(ret == -EAGAIN, "thread expired failed\n"); - zassert_true(events[0].poller->is_polling == false, - "the value of is_polling is invalid\n"); - - k_thread_abort(tid); -} diff --git a/tests/kernel/profiling/profiling_api/Kconfig b/tests/kernel/profiling/profiling_api/Kconfig deleted file mode 100644 index 658baad0aa8..00000000000 --- a/tests/kernel/profiling/profiling_api/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -config KERNEL_PROFILING_API_TEST - bool - default y - help - Hidden option enabling LPS_0 power state regardless of hardware - support. This ensures that power management hooks used in this - test to profile idle thread will be executed. - -# Include Zephyr's Kconfig. -source "Kconfig" diff --git a/tests/kernel/profiling/profiling_api/prj.conf b/tests/kernel/profiling/profiling_api/prj.conf index 2fe7fe30d2f..f46372c436c 100644 --- a/tests/kernel/profiling/profiling_api/prj.conf +++ b/tests/kernel/profiling/profiling_api/prj.conf @@ -12,4 +12,3 @@ CONFIG_PM_POLICY_CUSTOM=y CONFIG_IDLE_STACK_SIZE=2048 # to check isr CONFIG_IRQ_OFFLOAD=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/queue/prj.conf b/tests/kernel/queue/prj.conf index 44334ab367d..3f4e0e82950 100644 --- a/tests/kernel/queue/prj.conf +++ b/tests/kernel/queue/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_IRQ_OFFLOAD=y CONFIG_TEST_USERSPACE=y CONFIG_ZTEST_FATAL_HOOK=y diff --git a/tests/kernel/queue/src/test_queue_contexts.c b/tests/kernel/queue/src/test_queue_contexts.c index a96a2300fc8..33832b5b419 100644 --- a/tests/kernel/queue/src/test_queue_contexts.c +++ b/tests/kernel/queue/src/test_queue_contexts.c @@ -294,7 +294,7 @@ static void tqueue_alloc(struct k_queue *pqueue) * @brief Test queue alloc append and prepend * @ingroup kernel_queue_tests * @see k_queue_alloc_append(), k_queue_alloc_prepend(), - * z_thread_heap_assign(), k_queue_is_empty(), + * k_thread_heap_assign(), k_queue_is_empty(), * k_queue_get(), k_queue_remove() */ ZTEST(queue_api, test_queue_alloc) diff --git a/tests/kernel/sched/deadline/prj.conf b/tests/kernel/sched/deadline/prj.conf index 1777becdf07..d2c392f6dba 100644 --- a/tests/kernel/sched/deadline/prj.conf +++ b/tests/kernel/sched/deadline/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_SCHED_DEADLINE=y diff --git a/tests/kernel/sched/deadline/src/main.c b/tests/kernel/sched/deadline/src/main.c index f221ec8967e..7e1cf7a63c8 100644 --- a/tests/kernel/sched/deadline/src/main.c +++ b/tests/kernel/sched/deadline/src/main.c @@ -5,7 +5,7 @@ */ #include #include -#include +#include #define NUM_THREADS 8 /* this should be large enough for us @@ -125,6 +125,8 @@ void yield_worker(void *p1, void *p2, void *p3) zassert_true(n_exec == NUM_THREADS, ""); k_thread_abort(k_current_get()); + + CODE_UNREACHABLE; } ZTEST(suite_deadline, test_yield) diff --git a/tests/kernel/sched/metairq/prj.conf b/tests/kernel/sched/metairq/prj.conf index 2f46ed04f50..bb706e14ab5 100644 --- a/tests/kernel/sched/metairq/prj.conf +++ b/tests/kernel/sched/metairq/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_NUM_METAIRQ_PRIORITIES=1 diff --git a/tests/kernel/sched/metairq/src/main.c b/tests/kernel/sched/metairq/src/main.c index 89b54f7ba77..be8985413f2 100644 --- a/tests/kernel/sched/metairq/src/main.c +++ b/tests/kernel/sched/metairq/src/main.c @@ -40,7 +40,7 @@ #define CREATE_PARTICIPANT_THREAD(id, pri, entry) \ k_thread_create(&thread_##id##_thread_data, thread_##id##_stack_area, \ K_THREAD_STACK_SIZEOF(thread_##id##_stack_area), \ - (k_thread_entry_t)entry, \ + entry, \ NULL, NULL, NULL, \ pri, PARTICIPANT_THREAD_OPTIONS, K_FOREVER); #define START_PARTICIPANT_THREAD(id) k_thread_start(&(thread_##id##_thread_data)); @@ -59,8 +59,12 @@ volatile int coop_cnt2; #define LOOP_CNT 4 /* Number of times low priority thread waits */ /* Meta-IRQ thread */ -void metairq_thread(void) +void metairq_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + k_sem_take(&metairq_sem, K_FOREVER); printk("metairq start\n"); @@ -82,8 +86,12 @@ void metairq_thread(void) } /* High-priority cooperative thread */ -void coop_thread1(void) +void coop_thread1(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + int cnt1, cnt2; printk("thread1 take sem\n"); @@ -109,8 +117,12 @@ void coop_thread1(void) } /* Low-priority cooperative thread */ -void coop_thread2(void) +void coop_thread2(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + int cnt1, cnt2; printk("thread2 take sem\n"); diff --git a/tests/kernel/sched/preempt/prj.conf b/tests/kernel/sched/preempt/prj.conf index e7528fd6031..f68b1a7dcb6 100644 --- a/tests/kernel/sched/preempt/prj.conf +++ b/tests/kernel/sched/preempt/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_NUM_METAIRQ_PRIORITIES=1 CONFIG_IRQ_OFFLOAD=y diff --git a/tests/kernel/sched/schedule_api/prj.conf b/tests/kernel/sched/schedule_api/prj.conf index 4178dc560a9..785e9a3987b 100644 --- a/tests/kernel/sched/schedule_api/prj.conf +++ b/tests/kernel/sched/schedule_api/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_IRQ_OFFLOAD=y CONFIG_NUM_PREEMPT_PRIORITIES=30 CONFIG_NUM_COOP_PRIORITIES=30 diff --git a/tests/kernel/sched/schedule_api/prj_dumb.conf b/tests/kernel/sched/schedule_api/prj_dumb.conf index 5331db2daed..a1d0cf6dced 100644 --- a/tests/kernel/sched/schedule_api/prj_dumb.conf +++ b/tests/kernel/sched/schedule_api/prj_dumb.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_IRQ_OFFLOAD=y CONFIG_TEST_USERSPACE=y CONFIG_SCHED_DUMB=y diff --git a/tests/kernel/sched/schedule_api/prj_multiq.conf b/tests/kernel/sched/schedule_api/prj_multiq.conf index 0c37654fd60..77b3a49fd34 100644 --- a/tests/kernel/sched/schedule_api/prj_multiq.conf +++ b/tests/kernel/sched/schedule_api/prj_multiq.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_IRQ_OFFLOAD=y CONFIG_TEST_USERSPACE=y CONFIG_SCHED_MULTIQ=y diff --git a/tests/kernel/sched/schedule_api/src/test_priority_scheduling.c b/tests/kernel/sched/schedule_api/src/test_priority_scheduling.c index dfd7ba57460..7d72b54c0d6 100644 --- a/tests/kernel/sched/schedule_api/src/test_priority_scheduling.c +++ b/tests/kernel/sched/schedule_api/src/test_priority_scheduling.c @@ -16,7 +16,7 @@ #else #define NUM_THREAD 10 #endif -#define ITRERATION_COUNT 5 +#define ITERATION_COUNT 5 #define BASE_PRIORITY 1 BUILD_ASSERT(NUM_THREAD <= MAX_NUM_THREAD); @@ -83,7 +83,7 @@ ZTEST(threads_scheduling, test_priority_scheduling) K_NO_WAIT); } - while (count < ITRERATION_COUNT) { + while (count < ITERATION_COUNT) { /* Wait for each thread to complete */ for (int i = 0; i < NUM_THREAD; i++) { diff --git a/tests/kernel/sched/schedule_api/src/test_sched_timeslice_and_lock.c b/tests/kernel/sched/schedule_api/src/test_sched_timeslice_and_lock.c index 2039d3af509..e3307735f11 100644 --- a/tests/kernel/sched/schedule_api/src/test_sched_timeslice_and_lock.c +++ b/tests/kernel/sched/schedule_api/src/test_sched_timeslice_and_lock.c @@ -189,6 +189,10 @@ ZTEST(threads_scheduling, test_sleep_wakeup_preemptible) static int executed; static void coop_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + k_sem_take(&pend_sema, K_MSEC(100)); executed = 1; } @@ -211,7 +215,7 @@ ZTEST(threads_scheduling, test_pending_thread_wakeup) /* Create a thread which waits for semaphore */ k_tid_t tid = k_thread_create(&t, tstack, STACK_SIZE, - (k_thread_entry_t)coop_thread, + coop_thread, NULL, NULL, NULL, K_PRIO_COOP(1), 0, K_NO_WAIT); diff --git a/tests/kernel/sched/schedule_api/src/test_slice_scheduling.c b/tests/kernel/sched/schedule_api/src/test_slice_scheduling.c index af2d1ff9884..a65e7dcb3c7 100644 --- a/tests/kernel/sched/schedule_api/src/test_slice_scheduling.c +++ b/tests/kernel/sched/schedule_api/src/test_slice_scheduling.c @@ -19,7 +19,7 @@ #define NUM_THREAD 10 #endif #define BASE_PRIORITY 0 -#define ITRERATION_COUNT 5 +#define ITERATION_COUNT 5 BUILD_ASSERT(NUM_THREAD <= MAX_NUM_THREAD); /* slice size in millisecond */ @@ -113,7 +113,7 @@ ZTEST(threads_scheduling, test_slice_scheduling) /* enable time slice */ k_sched_time_slice_set(SLICE_SIZE, K_PRIO_PREEMPT(BASE_PRIORITY)); - while (count < ITRERATION_COUNT) { + while (count < ITERATION_COUNT) { k_uptime_delta(&elapsed_slice); /* Keep the current thread busy for more than one slice, diff --git a/tests/kernel/sched/schedule_api/src/user_api.c b/tests/kernel/sched/schedule_api/src/user_api.c index f113de5b4ee..e18eb378e32 100644 --- a/tests/kernel/sched/schedule_api/src/user_api.c +++ b/tests/kernel/sched/schedule_api/src/user_api.c @@ -96,6 +96,10 @@ ZTEST_USER(threads_scheduling, test_user_k_is_preempt) #ifdef CONFIG_USERSPACE static void thread_suspend_init_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); k_thread_suspend(NULL); @@ -116,7 +120,7 @@ static void thread_suspend_init_null(void *p1, void *p2, void *p3) ZTEST_USER(threads_scheduling, test_k_thread_suspend_init_null) { k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE, - (k_thread_entry_t)thread_suspend_init_null, + thread_suspend_init_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -133,6 +137,10 @@ ZTEST_USER(threads_scheduling, test_k_thread_suspend_init_null) #ifdef CONFIG_USERSPACE static void thread_resume_init_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); k_thread_resume(NULL); @@ -153,7 +161,7 @@ static void thread_resume_init_null(void *p1, void *p2, void *p3) ZTEST_USER(threads_scheduling, test_k_thread_resume_init_null) { k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE, - (k_thread_entry_t)thread_resume_init_null, + thread_resume_init_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -170,6 +178,10 @@ ZTEST_USER(threads_scheduling, test_k_thread_resume_init_null) #ifdef CONFIG_USERSPACE static void thread_priority_get_init_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); k_thread_priority_get(NULL); @@ -190,7 +202,7 @@ static void thread_priority_get_init_null(void *p1, void *p2, void *p3) ZTEST_USER(threads_scheduling, test_k_thread_priority_get_init_null) { k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE, - (k_thread_entry_t)thread_priority_get_init_null, + thread_priority_get_init_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -207,6 +219,10 @@ ZTEST_USER(threads_scheduling, test_k_thread_priority_get_init_null) #ifdef CONFIG_USERSPACE static void thread_priority_set_init_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); k_thread_priority_set(NULL, 0); @@ -227,7 +243,7 @@ static void thread_priority_set_init_null(void *p1, void *p2, void *p3) ZTEST_USER(threads_scheduling, test_k_thread_priority_set_init_null) { k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE, - (k_thread_entry_t)thread_priority_set_init_null, + thread_priority_set_init_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -244,6 +260,10 @@ ZTEST_USER(threads_scheduling, test_k_thread_priority_set_init_null) #ifdef CONFIG_USERSPACE static void thread_priority_set_overmax(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); /* set valid priority value outside the priority range will invoke fatal error */ @@ -265,7 +285,7 @@ static void thread_priority_set_overmax(void *p1, void *p2, void *p3) ZTEST_USER(threads_scheduling, test_k_thread_priority_set_overmax) { k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE, - (k_thread_entry_t)thread_priority_set_overmax, + thread_priority_set_overmax, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -282,6 +302,10 @@ ZTEST_USER(threads_scheduling, test_k_thread_priority_set_overmax) #ifdef CONFIG_USERSPACE static void thread_priority_set_upgrade(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); /* at first, set an valid priority */ @@ -305,7 +329,7 @@ static void thread_priority_set_upgrade(void *p1, void *p2, void *p3) ZTEST_USER(threads_scheduling, test_k_thread_priority_set_upgrade) { k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE, - (k_thread_entry_t)thread_priority_set_upgrade, + thread_priority_set_upgrade, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -322,6 +346,10 @@ ZTEST_USER(threads_scheduling, test_k_thread_priority_set_upgrade) #ifdef CONFIG_USERSPACE static void thread_wakeup_init_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); k_wakeup(NULL); @@ -342,7 +370,7 @@ static void thread_wakeup_init_null(void *p1, void *p2, void *p3) ZTEST_USER(threads_scheduling, test_k_wakeup_init_null) { k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE, - (k_thread_entry_t)thread_wakeup_init_null, + thread_wakeup_init_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); diff --git a/tests/kernel/semaphore/semaphore/prj.conf b/tests/kernel/semaphore/semaphore/prj.conf index c882831edb0..a8b0a3e4d25 100644 --- a/tests/kernel/semaphore/semaphore/prj.conf +++ b/tests/kernel/semaphore/semaphore/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_IRQ_OFFLOAD=y CONFIG_TEST_USERSPACE=y CONFIG_ZTEST_FATAL_HOOK=y diff --git a/tests/kernel/semaphore/semaphore/src/main.c b/tests/kernel/semaphore/semaphore/src/main.c index cff315f119b..c1efcb8889c 100644 --- a/tests/kernel/semaphore/semaphore/src/main.c +++ b/tests/kernel/semaphore/semaphore/src/main.c @@ -565,7 +565,7 @@ ZTEST_USER(semaphore, test_sem_take_timeout_forever) * @brief Test k_sem_take() with timeout in ISR context * @see k_sem_take() */ -ZTEST(semaphore, test_sem_take_timeout_isr) +ZTEST(semaphore_1cpu, test_sem_take_timeout_isr) { /* * Signal the semaphore upon which the another thread is waiting. The @@ -1150,6 +1150,10 @@ ZTEST(semaphore_1cpu, test_sem_queue_mutual_exclusion) #ifdef CONFIG_USERSPACE static void thread_sem_give_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); k_sem_give(NULL); @@ -1169,7 +1173,7 @@ static void thread_sem_give_null(void *p1, void *p2, void *p3) ZTEST_USER(semaphore_null_case, test_sem_give_null) { k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)thread_sem_give_null, + thread_sem_give_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -1181,6 +1185,10 @@ ZTEST_USER(semaphore_null_case, test_sem_give_null) #ifdef CONFIG_USERSPACE static void thread_sem_init_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); k_sem_init(NULL, 0, 1); @@ -1200,7 +1208,7 @@ static void thread_sem_init_null(void *p1, void *p2, void *p3) ZTEST_USER(semaphore_null_case, test_sem_init_null) { k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)thread_sem_init_null, + thread_sem_init_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -1212,6 +1220,10 @@ ZTEST_USER(semaphore_null_case, test_sem_init_null) #ifdef CONFIG_USERSPACE static void thread_sem_take_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); k_sem_take(NULL, K_MSEC(1)); @@ -1231,7 +1243,7 @@ static void thread_sem_take_null(void *p1, void *p2, void *p3) ZTEST_USER(semaphore_null_case, test_sem_take_null) { k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)thread_sem_take_null, + thread_sem_take_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -1243,6 +1255,10 @@ ZTEST_USER(semaphore_null_case, test_sem_take_null) #ifdef CONFIG_USERSPACE static void thread_sem_reset_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); k_sem_reset(NULL); @@ -1262,7 +1278,7 @@ static void thread_sem_reset_null(void *p1, void *p2, void *p3) ZTEST_USER(semaphore_null_case, test_sem_reset_null) { k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)thread_sem_reset_null, + thread_sem_reset_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -1274,6 +1290,10 @@ ZTEST_USER(semaphore_null_case, test_sem_reset_null) #ifdef CONFIG_USERSPACE static void thread_sem_count_get_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); k_sem_count_get(NULL); @@ -1293,7 +1313,7 @@ static void thread_sem_count_get_null(void *p1, void *p2, void *p3) ZTEST_USER(semaphore_null_case, test_sem_count_get_null) { k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)thread_sem_count_get_null, + thread_sem_count_get_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); diff --git a/tests/kernel/semaphore/sys_sem/prj.conf b/tests/kernel/semaphore/sys_sem/prj.conf index 2abfa9b67e9..869fd338e6a 100644 --- a/tests/kernel/semaphore/sys_sem/prj.conf +++ b/tests/kernel/semaphore/sys_sem/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y CONFIG_ZTEST_FATAL_HOOK=y diff --git a/tests/kernel/semaphore/sys_sem/testcase.yaml b/tests/kernel/semaphore/sys_sem/testcase.yaml index c434ad3c798..35441e11bca 100644 --- a/tests/kernel/semaphore/sys_sem/testcase.yaml +++ b/tests/kernel/semaphore/sys_sem/testcase.yaml @@ -1,6 +1,8 @@ tests: kernel.semaphore.usage: filter: CONFIG_ARCH_HAS_USERSPACE + arch_exclude: + - posix tags: - kernel - userspace diff --git a/tests/kernel/sleep/prj.conf b/tests/kernel/sleep/prj.conf index d658dc25122..a948cf31924 100644 --- a/tests/kernel/sleep/prj.conf +++ b/tests/kernel/sleep/prj.conf @@ -2,4 +2,3 @@ CONFIG_IRQ_OFFLOAD=y CONFIG_ZTEST=y CONFIG_TEST_USERSPACE=y CONFIG_MP_MAX_NUM_CPUS=1 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/sleep/src/main.c b/tests/kernel/sleep/src/main.c index 28168c1e61e..89da43b82ca 100644 --- a/tests/kernel/sleep/src/main.c +++ b/tests/kernel/sleep/src/main.c @@ -100,8 +100,12 @@ static int sleep_time_valid(uint32_t start, uint32_t end, uint32_t dur) return dt >= dur && dt <= (dur + TICK_MARGIN); } -static void test_thread(int arg1, int arg2) +static void test_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + uint32_t start_tick; uint32_t end_tick; @@ -171,8 +175,11 @@ static void irq_offload_isr(const void *arg) k_wakeup((k_tid_t) arg); } -static void helper_thread(int arg1, int arg2) +static void helper_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); k_sem_take(&helper_thread_sem, K_FOREVER); /* Wake the test thread */ @@ -205,7 +212,7 @@ ZTEST(sleep, test_sleep) test_thread_id = k_thread_create(&test_thread_data, test_thread_stack, THREAD_STACK, - (k_thread_entry_t) test_thread, + test_thread, 0, 0, NULL, TEST_THREAD_PRIORITY, 0, K_NO_WAIT); @@ -213,7 +220,7 @@ ZTEST(sleep, test_sleep) helper_thread_id = k_thread_create(&helper_thread_data, helper_thread_stack, THREAD_STACK, - (k_thread_entry_t) helper_thread, + helper_thread, 0, 0, NULL, HELPER_THREAD_PRIORITY, 0, K_NO_WAIT); diff --git a/tests/kernel/smp/prj.conf b/tests/kernel/smp/prj.conf index 97fab31062d..82aba8421f9 100644 --- a/tests/kernel/smp/prj.conf +++ b/tests/kernel/smp/prj.conf @@ -2,4 +2,3 @@ CONFIG_ZTEST=y CONFIG_SMP=y CONFIG_TRACE_SCHED_IPI=y CONFIG_POLL=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/smp/src/main.c b/tests/kernel/smp/src/main.c index 794ad88027e..698acb16af5 100644 --- a/tests/kernel/smp/src/main.c +++ b/tests/kernel/smp/src/main.c @@ -575,6 +575,10 @@ ZTEST(smp, test_wakeup_threads) /* a thread for testing get current cpu */ static void thread_get_cpu_entry(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + int bsp_id = *(int *)p1; int cpu_id = -1; @@ -660,7 +664,7 @@ ZTEST(smp, test_get_cpu) _cpu_id = arch_curr_cpu()->id; thread_id = k_thread_create(&t2, t2_stack, T2_STACK_SIZE, - (k_thread_entry_t)thread_get_cpu_entry, + thread_get_cpu_entry, &_cpu_id, NULL, NULL, K_PRIO_COOP(2), K_INHERIT_PERMS, K_NO_WAIT); @@ -849,6 +853,9 @@ ZTEST(smp, test_workq_on_smp) static void t1_mutex_lock(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + /* t1 will get mutex first */ k_mutex_lock((struct k_mutex *)p1, K_FOREVER); @@ -859,6 +866,9 @@ static void t1_mutex_lock(void *p1, void *p2, void *p3) static void t2_mutex_lock(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + zassert_equal(_current->base.global_lock_count, 0, "thread global lock cnt %d is incorrect", _current->base.global_lock_count); @@ -894,14 +904,14 @@ ZTEST(smp, test_smp_release_global_lock) tinfo[0].tid = k_thread_create(&tthread[0], tstack[0], STACK_SIZE, - (k_thread_entry_t)t1_mutex_lock, + t1_mutex_lock, &smutex, NULL, NULL, K_PRIO_PREEMPT(5), K_INHERIT_PERMS, K_NO_WAIT); tinfo[1].tid = k_thread_create(&tthread[1], tstack[1], STACK_SIZE, - (k_thread_entry_t)t2_mutex_lock, + t2_mutex_lock, &smutex, NULL, NULL, K_PRIO_PREEMPT(3), K_INHERIT_PERMS, K_MSEC(1)); @@ -1004,8 +1014,12 @@ static void inc_global_cnt(void *a, void *b, void *c) } } -static int run_concurrency(int type, void *func) +static int run_concurrency(void *p1, void *p2, void *p3) { + ARG_UNUSED(p3); + + int type = POINTER_TO_INT(p1); + k_thread_entry_t func = p2; uint32_t start_t, end_t; sync_init(type); @@ -1014,21 +1028,21 @@ static int run_concurrency(int type, void *func) tinfo[0].tid = k_thread_create(&tthread[0], tstack[0], STACK_SIZE, - (k_thread_entry_t)func, + func, NULL, NULL, NULL, K_PRIO_PREEMPT(1), K_INHERIT_PERMS, K_NO_WAIT); tinfo[1].tid = k_thread_create(&tthread[1], tstack[1], STACK_SIZE, - (k_thread_entry_t)func, + func, NULL, NULL, NULL, K_PRIO_PREEMPT(1), K_INHERIT_PERMS, K_NO_WAIT); k_tid_t tid = k_thread_create(&t2, t2_stack, T2_STACK_SIZE, - (k_thread_entry_t)func, + func, NULL, NULL, NULL, K_PRIO_PREEMPT(1), K_INHERIT_PERMS, K_NO_WAIT); @@ -1065,15 +1079,15 @@ static int run_concurrency(int type, void *func) ZTEST(smp, test_inc_concurrency) { /* increasing global var with irq lock */ - zassert_true(run_concurrency(LOCK_IRQ, inc_global_cnt), + zassert_true(run_concurrency(INT_TO_POINTER(LOCK_IRQ), inc_global_cnt, NULL), "total count %d is wrong(i)", global_cnt); /* increasing global var with irq lock */ - zassert_true(run_concurrency(LOCK_SEM, inc_global_cnt), + zassert_true(run_concurrency(INT_TO_POINTER(LOCK_SEM), inc_global_cnt, NULL), "total count %d is wrong(s)", global_cnt); /* increasing global var with irq lock */ - zassert_true(run_concurrency(LOCK_MUTEX, inc_global_cnt), + zassert_true(run_concurrency(INT_TO_POINTER(LOCK_MUTEX), inc_global_cnt, NULL), "total count %d is wrong(M)", global_cnt); } @@ -1087,6 +1101,9 @@ ZTEST(smp, test_inc_concurrency) */ static void process_events(void *arg0, void *arg1, void *arg2) { + ARG_UNUSED(arg1); + ARG_UNUSED(arg2); + uintptr_t id = (uintptr_t) arg0; while (1) { @@ -1137,7 +1154,7 @@ ZTEST(smp, test_smp_switch_torture) K_POLL_MODE_NOTIFY_ONLY, &tsignal[i]); k_thread_create(&tthread[i], tstack[i], STACK_SIZE, - (k_thread_entry_t) process_events, + process_events, (void *) i, NULL, NULL, K_PRIO_PREEMPT(i + 1), K_INHERIT_PERMS, K_NO_WAIT); } diff --git a/tests/kernel/smp_boot_delay/prj.conf b/tests/kernel/smp_boot_delay/prj.conf index d486230020e..a7c6e63161a 100644 --- a/tests/kernel/smp_boot_delay/prj.conf +++ b/tests/kernel/smp_boot_delay/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y CONFIG_SMP=y CONFIG_SMP_BOOT_DELAY=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/spinlock/CMakeLists.txt b/tests/kernel/spinlock/CMakeLists.txt index 823174ba17e..821ffd70fe8 100644 --- a/tests/kernel/spinlock/CMakeLists.txt +++ b/tests/kernel/spinlock/CMakeLists.txt @@ -6,3 +6,4 @@ project(spinlock) target_sources(app PRIVATE src/main.c) target_sources(app PRIVATE src/spinlock_error_case.c) +target_sources(app PRIVATE src/spinlock_fairness.c) diff --git a/tests/kernel/spinlock/prj.conf b/tests/kernel/spinlock/prj.conf index 801265f63e3..57fec00f826 100644 --- a/tests/kernel/spinlock/prj.conf +++ b/tests/kernel/spinlock/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y CONFIG_SPIN_VALIDATE=y CONFIG_SPIN_LOCK_TIME_LIMIT=100000 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/spinlock/src/main.c b/tests/kernel/spinlock/src/main.c index 88d3ba8733d..ddd53eca4e2 100644 --- a/tests/kernel/spinlock/src/main.c +++ b/tests/kernel/spinlock/src/main.c @@ -44,18 +44,18 @@ ZTEST(spinlock, test_spinlock_basic) k_spinlock_key_t key; static struct k_spinlock l; - zassert_true(!l.locked, "Spinlock initialized to locked"); + zassert_true(!z_spin_is_locked(&l), "Spinlock initialized to locked"); key = k_spin_lock(&l); - zassert_true(l.locked, "Spinlock failed to lock"); + zassert_true(z_spin_is_locked(&l), "Spinlock failed to lock"); k_spin_unlock(&l, key); - zassert_true(!l.locked, "Spinlock failed to unlock"); + zassert_true(!z_spin_is_locked(&l), "Spinlock failed to unlock"); } -void bounce_once(int id, bool trylock) +static void bounce_once(int id, bool trylock) { int ret; int i, locked; @@ -97,15 +97,16 @@ void bounce_once(int id, bool trylock) */ bounce_owner = id; - for (i = 0; i < 100; i++) { + for (i = 0; i < 5; i++) { zassert_true(bounce_owner == id, "Locked data changed"); + k_busy_wait(1); } /* Release the lock */ k_spin_unlock(&bounce_lock, key); } -void cpu1_fn(void *p1, void *p2, void *p3) +static void cpu1_fn(void *p1, void *p2, void *p3) { ARG_UNUSED(p1); ARG_UNUSED(p2); @@ -164,7 +165,7 @@ ZTEST(spinlock, test_spinlock_mutual_exclusion) key = k_spin_lock(&lock_runtime); - zassert_true(lock_runtime.locked, "Spinlock failed to lock"); + zassert_true(z_spin_is_locked(&lock_runtime), "Spinlock failed to lock"); /* check irq has not locked */ zassert_true(arch_irq_unlocked(key.key), @@ -184,10 +185,10 @@ ZTEST(spinlock, test_spinlock_mutual_exclusion) k_spin_unlock(&lock_runtime, key); - zassert_true(!lock_runtime.locked, "Spinlock failed to unlock"); + zassert_true(!z_spin_is_locked(&lock_runtime), "Spinlock failed to unlock"); } -void trylock_fn(void *p1, void *p2, void *p3) +static void trylock_fn(void *p1, void *p2, void *p3) { ARG_UNUSED(p1); ARG_UNUSED(p2); @@ -232,6 +233,9 @@ static void before(void *ctx) ARG_UNUSED(ctx); bounce_done = 0; + bounce_owner = 0; + trylock_failures = 0; + trylock_successes = 0; } ZTEST_SUITE(spinlock, NULL, NULL, before, NULL, NULL); diff --git a/tests/kernel/spinlock/src/spinlock_error_case.c b/tests/kernel/spinlock/src/spinlock_error_case.c index 4dd09c7f217..b69e12a0d74 100644 --- a/tests/kernel/spinlock/src/spinlock_error_case.c +++ b/tests/kernel/spinlock/src/spinlock_error_case.c @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -#include "zephyr/ztest_test_new.h" +#include #include #include #include diff --git a/tests/kernel/spinlock/src/spinlock_fairness.c b/tests/kernel/spinlock/src/spinlock_fairness.c new file mode 100644 index 00000000000..d61acde2259 --- /dev/null +++ b/tests/kernel/spinlock/src/spinlock_fairness.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2023 Syntacore. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "zephyr/ztest_test.h" +#include +#include +#include + +#ifdef CONFIG_SCHED_CPU_MASK + +#define STACK_SIZE (8 * 1024) +#define CORES_NUM CONFIG_MP_MAX_NUM_CPUS +#define FAIRNESS_TEST_CYCLES_PER_CORE 1000 + +BUILD_ASSERT(CONFIG_MP_MAX_NUM_CPUS > 1); + +static K_THREAD_STACK_ARRAY_DEFINE(tstack, CORES_NUM, STACK_SIZE); +static struct k_thread tthread[CORES_NUM]; +static uint32_t spinlock_grabbed[CORES_NUM]; +static atomic_t fairness_test_cycles; +static struct k_spinlock lock; +static atomic_t start_sync; + +static inline struct k_thread *get_thread(uint8_t core_id) +{ + return &tthread[core_id]; +} + +/** + * @brief Execution thread which runs concurrently on each CPU in the system + * + * @param [in] arg1 - thread argument 1 + * @param [in] arg2 - thread argument 2 + * @param [in] arg3 - thread argument 3 + */ +static void test_thread(void *arg1, void *arg2, void *arg3) +{ + int core_id = (uintptr_t)arg1; + + /* Synchronize all the cores as much as possible */ + int key = arch_irq_lock(); + + atomic_dec(&start_sync); + while (atomic_get(&start_sync) != 0) + ; + + /* + * Run the test: let the cores contend for the spinlock and + * collect the spinlock acquisition statistics + */ + do { + k_spinlock_key_t spinlock_key = k_spin_lock(&lock); + + if (atomic_get(&fairness_test_cycles) == 0) { + k_spin_unlock(&lock, spinlock_key); + arch_irq_unlock(key); + return; + } + + spinlock_grabbed[core_id]++; + + /* Imitate some work which takes time */ + volatile uint32_t countdown = 10000; + + while (countdown--) + ; + + atomic_dec(&fairness_test_cycles); + + k_spin_unlock(&lock, spinlock_key); + } while (atomic_get(&fairness_test_cycles) != 0); + + arch_irq_unlock(key); +} + +static void test_init(void) +{ + memset(tthread, 0x00, sizeof(tthread)); + memset(tstack, 0x00, sizeof(tstack)); + atomic_set(&start_sync, CORES_NUM); + atomic_set(&fairness_test_cycles, FAIRNESS_TEST_CYCLES_PER_CORE * CORES_NUM); + + for (uintptr_t core_id = 0; core_id < CORES_NUM; core_id++) { + struct k_thread *thread = get_thread(core_id); + + k_thread_create(thread, tstack[core_id], STACK_SIZE, + (k_thread_entry_t)test_thread, + (void *)core_id, NULL, NULL, + K_PRIO_COOP(10), 0, K_FOREVER); + + /* + * Pin each thread to a particular CPU core. + * The larger the core's memory access latency in comparison to the + * other cores - the less chances to win a contention for the spinlock + * this core will have in case the spinlock implementation doesn't + * provide acquisition fairness. + */ + k_thread_cpu_pin(thread, core_id); + } +} + +/** + * @brief Test spinlock acquisition fairness + * + * @details This test verifies a spinlock acquisition fairness in relation + * to the cores contending for the spinlock. Memory access latency may + * vary between the CPU cores, so that some CPUs reach the spinlock faster + * than the others and depending on spinlock implementation may get + * higher chance to win the contention for the spinlock than the other + * cores, making them to starve. + * This effect may become critical for some real-life platforms + * (e.g. NUMA) resulting in performance loss or even a live-lock, + * when a single CPU is continuously winning the contention. + * This test ensures that the probability to win the contention for a + * spinlock is evenly distributed between all of the contending cores. + * + * @ingroup kernel_spinlock_tests + * + * @see k_spin_lock(), k_spin_unlock() + */ +ZTEST(spinlock, test_spinlock_fairness) +{ + test_init(); + + /* Launching all the threads */ + for (uint8_t core_id = 0; core_id < CORES_NUM; core_id++) { + struct k_thread *thread = get_thread(core_id); + + k_thread_start(thread); + } + /* Waiting for all the threads to complete */ + for (uint8_t core_id = 0; core_id < CORES_NUM; core_id++) { + struct k_thread *thread = get_thread(core_id); + + k_thread_join(thread, K_FOREVER); + } + + /* Print statistics */ + for (uint8_t core_id = 0; core_id < CORES_NUM; core_id++) { + printk("CPU%u acquired spinlock %u times, expected %u\n", + core_id, spinlock_grabbed[core_id], FAIRNESS_TEST_CYCLES_PER_CORE); + } + + /* Verify spinlock acquisition fairness */ + for (uint8_t core_id = 0; core_id < CORES_NUM; core_id++) { + zassert_false(spinlock_grabbed[core_id] < FAIRNESS_TEST_CYCLES_PER_CORE, + "CPU%d starved on a spinlock: acquired %u times, expected %u\n", + core_id, spinlock_grabbed[core_id], FAIRNESS_TEST_CYCLES_PER_CORE); + } +} + +#endif /* CONFIG_SCHED_CPU_MASK */ diff --git a/tests/kernel/spinlock/testcase.yaml b/tests/kernel/spinlock/testcase.yaml index 7844db39e61..3b1bd6ea513 100644 --- a/tests/kernel/spinlock/testcase.yaml +++ b/tests/kernel/spinlock/testcase.yaml @@ -19,3 +19,14 @@ tests: - smp extra_configs: - CONFIG_MINIMAL_LIBC=y + kernel.multiprocessing.spinlock_fairness: + tags: + - kernel + - smp + - spinlock + filter: CONFIG_SMP and CONFIG_MP_MAX_NUM_CPUS > 1 and CONFIG_MP_MAX_NUM_CPUS <= 4 + depends_on: + - smp + extra_configs: + - CONFIG_SCHED_CPU_MASK=y + - CONFIG_TICKET_SPINLOCKS=y diff --git a/tests/kernel/stack/stack/prj.conf b/tests/kernel/stack/stack/prj.conf index 9baa4dcc23c..3fc9377dc69 100644 --- a/tests/kernel/stack/stack/prj.conf +++ b/tests/kernel/stack/stack/prj.conf @@ -3,4 +3,3 @@ CONFIG_IRQ_OFFLOAD=y CONFIG_TEST_USERSPACE=y CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_ZTEST_FATAL_HOOK=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/threads/dynamic_thread/prj.conf b/tests/kernel/threads/dynamic_thread/prj.conf index f7d01312787..f70a552b445 100644 --- a/tests/kernel/threads/dynamic_thread/prj.conf +++ b/tests/kernel/threads/dynamic_thread/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y -CONFIG_HEAP_MEM_POOL_SIZE=21504 +CONFIG_HEAP_MEM_POOL_SIZE=32768 diff --git a/tests/kernel/threads/dynamic_thread/src/main.c b/tests/kernel/threads/dynamic_thread/src/main.c index 8db6a32c4c5..0321aa792c7 100644 --- a/tests/kernel/threads/dynamic_thread/src/main.c +++ b/tests/kernel/threads/dynamic_thread/src/main.c @@ -159,7 +159,7 @@ ZTEST(thread_dynamic, test_thread_index_management) #include /** @endcond */ } - blob = z_dynamic_object_aligned_create(16, ret); + blob = k_object_create_dynamic_aligned(16, ret); zassert_true(blob != NULL, "out of heap memory"); /* Free one of the threads... */ diff --git a/tests/kernel/threads/dynamic_thread/testcase.yaml b/tests/kernel/threads/dynamic_thread/testcase.yaml index c97f6bce8a5..d4c6c4a09d4 100644 --- a/tests/kernel/threads/dynamic_thread/testcase.yaml +++ b/tests/kernel/threads/dynamic_thread/testcase.yaml @@ -6,5 +6,7 @@ tests: - userspace ignore_faults: true filter: CONFIG_ARCH_HAS_USERSPACE + arch_exclude: + - posix integration_platforms: - qemu_x86 diff --git a/tests/kernel/threads/dynamic_thread_stack/prj.conf b/tests/kernel/threads/dynamic_thread_stack/prj.conf index 07c01bd661f..3a4e7fd4159 100644 --- a/tests/kernel/threads/dynamic_thread_stack/prj.conf +++ b/tests/kernel/threads/dynamic_thread_stack/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_INIT_STACKS=y CONFIG_THREAD_STACK_INFO=y CONFIG_MAX_THREAD_BYTES=5 diff --git a/tests/kernel/threads/no-multithreading/prj.conf b/tests/kernel/threads/no-multithreading/prj.conf index 1fbc3608d0f..ac4088fe07f 100644 --- a/tests/kernel/threads/no-multithreading/prj.conf +++ b/tests/kernel/threads/no-multithreading/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MULTITHREADING=n CONFIG_BT=n CONFIG_USB_DEVICE_STACK=n diff --git a/tests/kernel/threads/no-multithreading/testcase.yaml b/tests/kernel/threads/no-multithreading/testcase.yaml index 990965d459f..d29165f683c 100644 --- a/tests/kernel/threads/no-multithreading/testcase.yaml +++ b/tests/kernel/threads/no-multithreading/testcase.yaml @@ -22,5 +22,6 @@ tests: - qemu_riscv32 - qemu_riscv32e - qemu_riscv64 + - qemu_leon3 integration_platforms: - qemu_cortex_m0 diff --git a/tests/kernel/threads/thread_apis/prj.conf b/tests/kernel/threads/thread_apis/prj.conf index 7df1af4b9ae..68e030211e7 100644 --- a/tests/kernel/threads/thread_apis/prj.conf +++ b/tests/kernel/threads/thread_apis/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_THREAD_MONITOR=y CONFIG_THREAD_CUSTOM_DATA=y CONFIG_THREAD_NAME=y diff --git a/tests/kernel/threads/thread_apis/src/main.c b/tests/kernel/threads/thread_apis/src/main.c index f287ec8daa6..86add19a5c7 100644 --- a/tests/kernel/threads/thread_apis/src/main.c +++ b/tests/kernel/threads/thread_apis/src/main.c @@ -20,6 +20,9 @@ #include #include +#include +LOG_MODULE_REGISTER(test); + struct k_thread tdata; #define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE) K_THREAD_STACK_DEFINE(tstack, STACK_SIZE); @@ -183,7 +186,7 @@ ZTEST_USER(threads_lifecycle, test_thread_name_user_get_set) ret = k_thread_name_copy(&z_main_thread, thread_name, sizeof(thread_name)); zassert_equal(ret, 0, "couldn't get main thread name"); - printk("Main thread name is '%s'\n", thread_name); + LOG_DBG("Main thread name is '%s'", thread_name); /* Set and get child thread's name */ k_tid_t tid = k_thread_create(&tdata_name, tstack_name, STACK_SIZE, @@ -248,7 +251,7 @@ static void enter_user_mode_entry(void *p1, void *p2, void *p3) zassert_true(z_is_thread_essential(), "Thread isn't set" " as essential\n"); - k_thread_user_mode_enter((k_thread_entry_t)umode_entry, + k_thread_user_mode_enter(umode_entry, k_current_get(), NULL, NULL); } @@ -278,7 +281,7 @@ enum control_method { ISR_RUNNING }; -void join_entry(void *p1, void *p2, void *p3) +static void join_entry(void *p1, void *p2, void *p3) { enum control_method m = (enum control_method)(intptr_t)p1; @@ -288,41 +291,41 @@ void join_entry(void *p1, void *p2, void *p3) case OTHER_ABORT: case OTHER_ABORT_TIMEOUT: case ISR_RUNNING: - printk("join_thread: sleeping forever\n"); + LOG_DBG("join_thread: sleeping forever"); k_sleep(K_FOREVER); break; case SELF_ABORT: case ALREADY_EXIT: case ISR_ALREADY_EXIT: - printk("join_thread: self-exiting\n"); + LOG_DBG("join_thread: self-exiting"); return; } } -void control_entry(void *p1, void *p2, void *p3) +static void control_entry(void *p1, void *p2, void *p3) { - printk("control_thread: killing join thread\n"); + LOG_DBG("control_thread: killing join thread"); k_thread_abort(&join_thread); } -void do_join_from_isr(const void *arg) +static void do_join_from_isr(const void *arg) { int *ret = (int *)arg; zassert_true(k_is_in_isr()); - printk("isr: joining join_thread\n"); + LOG_DBG("isr: joining join_thread"); *ret = k_thread_join(&join_thread, K_NO_WAIT); - printk("isr: k_thread_join() returned with %d\n", *ret); + LOG_DBG("isr: k_thread_join() returned with %d", *ret); } #define JOIN_TIMEOUT_MS 100 -int join_scenario_interval(enum control_method m, int64_t *interval) +static int join_scenario_interval(enum control_method m, int64_t *interval) { k_timeout_t timeout = K_FOREVER; int ret; - printk("ztest_thread: method %d, create join_thread\n", m); + LOG_DBG("ztest_thread: method %d, create join_thread", m); k_thread_create(&join_thread, join_stack, STACK_SIZE, join_entry, (void *)m, NULL, NULL, K_PRIO_PREEMPT(1), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -337,7 +340,7 @@ int join_scenario_interval(enum control_method m, int64_t *interval) timeout = K_MSEC(JOIN_TIMEOUT_MS); __fallthrough; case OTHER_ABORT: - printk("ztest_thread: create control_thread\n"); + LOG_DBG("ztest_thread: create control_thread"); k_thread_create(&control_thread, control_stack, STACK_SIZE, control_entry, NULL, NULL, NULL, K_PRIO_PREEMPT(2), @@ -356,7 +359,7 @@ int join_scenario_interval(enum control_method m, int64_t *interval) if (m == ISR_ALREADY_EXIT || m == ISR_RUNNING) { irq_offload(do_join_from_isr, (const void *)&ret); } else { - printk("ztest_thread: joining join_thread\n"); + LOG_DBG("ztest_thread: joining join_thread"); if (interval != NULL) { *interval = k_uptime_get(); @@ -368,7 +371,7 @@ int join_scenario_interval(enum control_method m, int64_t *interval) *interval = k_uptime_get() - *interval; } - printk("ztest_thread: k_thread_join() returned with %d\n", ret); + LOG_DBG("ztest_thread: k_thread_join() returned with %d", ret); } if (ret != 0) { @@ -421,7 +424,7 @@ K_THREAD_STACK_DEFINE(deadlock1_stack, STACK_SIZE); struct k_thread deadlock2_thread; K_THREAD_STACK_DEFINE(deadlock2_stack, STACK_SIZE); -void deadlock1_entry(void *p1, void *p2, void *p3) +static void deadlock1_entry(void *p1, void *p2, void *p3) { int ret; @@ -431,7 +434,7 @@ void deadlock1_entry(void *p1, void *p2, void *p3) zassert_equal(ret, -EDEADLK, "failed mutual join case"); } -void deadlock2_entry(void *p1, void *p2, void *p3) +static void deadlock2_entry(void *p1, void *p2, void *p3) { int ret; @@ -470,6 +473,7 @@ static void user_start_thread(void *p1, void *p2, void *p3) { /* do nothing */ } + ZTEST_USER(threads_lifecycle, test_thread_timeout_remaining_expires) { k_ticks_t r, e, r1, ticks, expected_expires_ticks; @@ -484,7 +488,7 @@ ZTEST_USER(threads_lifecycle, test_thread_timeout_remaining_expires) k_msleep(10); e = k_thread_timeout_expires_ticks(tid); - TC_PRINT("thread_expires_ticks: %d, expect: %d\n", (int)e, + LOG_DBG("thread_expires_ticks: %d, expect: %d", (int)e, (int)expected_expires_ticks); zassert_true(e >= expected_expires_ticks); @@ -520,6 +524,7 @@ static void foreach_callback(const struct k_thread *thread, void *user_data) ((k_thread_runtime_stats_t *)user_data)->execution_cycles += stats.execution_cycles; } + /* This case accumulates every thread's execution_cycles first, then * get the total execution_cycles from a global * k_thread_runtime_stats_t to see that all time is reflected in the @@ -594,7 +599,7 @@ ZTEST_USER(threads_lifecycle_1cpu, test_k_busy_wait_user) } #define INT_ARRAY_SIZE 128 -int large_stack(size_t *space) +static int large_stack(size_t *space) { /* use "volatile" to protect this variable from being optimized out */ volatile int a[INT_ARRAY_SIZE]; @@ -605,7 +610,7 @@ int large_stack(size_t *space) } -int small_stack(size_t *space) +static int small_stack(size_t *space) { return k_thread_stack_space_get(k_current_get(), space); } @@ -628,7 +633,7 @@ ZTEST_USER(threads_lifecycle, test_k_thread_stack_space_get_user) zassert_true(b <= a); } -void *thread_test_setup(void) +static void *thread_test_setup(void) { k_thread_access_grant(k_current_get(), &tdata, tstack, &tdata_custom, tstack_custom, diff --git a/tests/kernel/threads/thread_apis/src/test_essential_thread.c b/tests/kernel/threads/thread_apis/src/test_essential_thread.c index 7f62296f396..7cebccf4776 100644 --- a/tests/kernel/threads/thread_apis/src/test_essential_thread.c +++ b/tests/kernel/threads/thread_apis/src/test_essential_thread.c @@ -6,7 +6,10 @@ #include #include #include + +/* Internal APIs */ #include +#include struct k_thread kthread_thread; struct k_thread kthread_thread1; @@ -19,6 +22,10 @@ static bool fatal_error_signaled; static void thread_entry(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + z_thread_essential_set(); if (z_is_thread_essential()) { @@ -44,7 +51,7 @@ static void thread_entry(void *p1, void *p2, void *p3) ZTEST(threads_lifecycle, test_essential_thread_operation) { k_tid_t tid = k_thread_create(&kthread_thread, kthread_stack, - STACKSIZE, (k_thread_entry_t)thread_entry, NULL, + STACKSIZE, thread_entry, NULL, NULL, NULL, K_PRIO_PREEMPT(0), 0, K_NO_WAIT); @@ -65,6 +72,10 @@ void k_sys_fatal_error_handler(unsigned int reason, static void abort_thread_entry(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + z_thread_essential_set(); if (z_is_thread_essential()) { @@ -91,7 +102,7 @@ static void abort_thread_entry(void *p1, void *p2, void *p3) ZTEST(threads_lifecycle, test_essential_thread_abort) { k_tid_t tid = k_thread_create(&kthread_thread1, kthread_stack, STACKSIZE, - (k_thread_entry_t)abort_thread_entry, + abort_thread_entry, NULL, NULL, NULL, K_PRIO_PREEMPT(0), 0, K_NO_WAIT); diff --git a/tests/kernel/threads/thread_apis/src/test_kthread_for_each.c b/tests/kernel/threads/thread_apis/src/test_kthread_for_each.c index 76c10d96656..654e2224d57 100644 --- a/tests/kernel/threads/thread_apis/src/test_kthread_for_each.c +++ b/tests/kernel/threads/thread_apis/src/test_kthread_for_each.c @@ -24,6 +24,10 @@ K_THREAD_STACK_DEFINE(tstack1, STACK_SIZE); static void thread_entry(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + k_msleep(SLEEP_MS); } @@ -48,7 +52,7 @@ void thread_callback_unlocked(const struct k_thread *thread, void *user_data) if (create_thread) { in_callback_tid = k_thread_create(&tdata1, tstack1, STACK_SIZE, - (k_thread_entry_t)thread_entry, + thread_entry, NULL, NULL, NULL, K_PRIO_PREEMPT(0), 0, K_NO_WAIT); create_thread = false; @@ -98,7 +102,7 @@ ZTEST(threads_lifecycle_1cpu, test_k_thread_foreach) /* Create new thread which should add a new entry to the thread list */ k_tid_t tid = k_thread_create(&tdata, tstack, - STACK_SIZE, (k_thread_entry_t)thread_entry, NULL, + STACK_SIZE, thread_entry, NULL, NULL, NULL, K_PRIO_PREEMPT(0), 0, K_NO_WAIT); k_msleep(1); @@ -147,7 +151,7 @@ ZTEST(threads_lifecycle_1cpu, test_k_thread_foreach_unlocked) /* Create new thread which should add a new entry to the thread list */ k_tid_t tid = k_thread_create(&tdata, tstack, - STACK_SIZE, (k_thread_entry_t)thread_entry, NULL, + STACK_SIZE, thread_entry, NULL, NULL, NULL, K_PRIO_PREEMPT(0), 0, K_NO_WAIT); k_msleep(1); diff --git a/tests/kernel/threads/thread_apis/src/test_threads_cancel_abort.c b/tests/kernel/threads/thread_apis/src/test_threads_cancel_abort.c index 481aeac676d..aad8842a11e 100644 --- a/tests/kernel/threads/thread_apis/src/test_threads_cancel_abort.c +++ b/tests/kernel/threads/thread_apis/src/test_threads_cancel_abort.c @@ -25,6 +25,7 @@ static void thread_entry_abort(void *p1, void *p2, void *p3) /**TESTPOINT: abort current thread*/ execute_flag = 1; k_thread_abort(k_current_get()); + CODE_UNREACHABLE; /*unreachable*/ execute_flag = 2; zassert_true(1 == 0); @@ -109,6 +110,10 @@ void *block; static void delayed_thread_entry(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + execute_flag = 1; zassert_unreachable("Delayed thread shouldn't be executed"); @@ -133,7 +138,7 @@ ZTEST(threads_lifecycle_1cpu, test_delayed_thread_abort) * current thread */ k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)delayed_thread_entry, NULL, NULL, NULL, + delayed_thread_entry, NULL, NULL, NULL, K_PRIO_PREEMPT(1), 0, K_MSEC(100)); /* Give up CPU */ diff --git a/tests/kernel/threads/thread_apis/src/test_threads_set_priority.c b/tests/kernel/threads/thread_apis/src/test_threads_set_priority.c index ec70c043cb4..e43487704f0 100644 --- a/tests/kernel/threads/thread_apis/src/test_threads_set_priority.c +++ b/tests/kernel/threads/thread_apis/src/test_threads_set_priority.c @@ -18,8 +18,12 @@ K_SEM_DEFINE(sem_thread1, 0, 1); * @brief thread2 portion to test setting the priority * */ -void thread2_set_prio_test(void) +void thread2_set_prio_test(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + /* lower thread2 priority by 5 */ k_sem_take(&sem_thread2, K_FOREVER); thread2_data = k_thread_priority_get(k_current_get()); @@ -72,7 +76,7 @@ ZTEST(threads_lifecycle, test_threads_priority_set) int thread2_prio = prio + 1; k_tid_t thread2_id = k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)thread2_set_prio_test, + thread2_set_prio_test, NULL, NULL, NULL, thread2_prio, 0, K_NO_WAIT); diff --git a/tests/kernel/threads/thread_error_case/prj.conf b/tests/kernel/threads/thread_error_case/prj.conf index 9b1f9bcd5a7..292c830bc05 100644 --- a/tests/kernel/threads/thread_error_case/prj.conf +++ b/tests/kernel/threads/thread_error_case/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_THREAD_MONITOR=y CONFIG_THREAD_CUSTOM_DATA=y CONFIG_THREAD_NAME=y diff --git a/tests/kernel/threads/thread_error_case/src/main.c b/tests/kernel/threads/thread_error_case/src/main.c index a986fb7eac4..b4df5a899a7 100644 --- a/tests/kernel/threads/thread_error_case/src/main.c +++ b/tests/kernel/threads/thread_error_case/src/main.c @@ -35,6 +35,9 @@ static void test_thread(void *p1, void *p2, void *p3) static void tThread_entry_negative(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + int choice = *((int *)p1); uint32_t perm = K_INHERIT_PERMS; @@ -114,7 +117,7 @@ static void create_negative_test_thread(int choice) case_type = choice; k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)tThread_entry_negative, + tThread_entry_negative, (void *)&case_type, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), perm, K_NO_WAIT); diff --git a/tests/kernel/threads/thread_init/prj.conf b/tests/kernel/threads/thread_init/prj.conf index e2cf6732b3f..390173dc4a5 100644 --- a/tests/kernel/threads/thread_init/prj.conf +++ b/tests/kernel/threads/thread_init/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y CONFIG_SMP=n diff --git a/tests/kernel/threads/thread_stack/prj.conf b/tests/kernel/threads/thread_stack/prj.conf index ddc7b71cef9..b6b5951635d 100644 --- a/tests/kernel/threads/thread_stack/prj.conf +++ b/tests/kernel/threads/thread_stack/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_INIT_STACKS=y CONFIG_THREAD_STACK_INFO=y CONFIG_APPLICATION_DEFINED_SYSCALL=y diff --git a/tests/kernel/threads/thread_stack/prj_armv8m_mpu_stack_guard.conf b/tests/kernel/threads/thread_stack/prj_armv8m_mpu_stack_guard.conf index a16b81cc689..143e2667522 100644 --- a/tests/kernel/threads/thread_stack/prj_armv8m_mpu_stack_guard.conf +++ b/tests/kernel/threads/thread_stack/prj_armv8m_mpu_stack_guard.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_INIT_STACKS=y CONFIG_THREAD_STACK_INFO=y CONFIG_APPLICATION_DEFINED_SYSCALL=y diff --git a/tests/kernel/threads/thread_stack/src/main.c b/tests/kernel/threads/thread_stack/src/main.c index b84b3b3dd44..a2ea5e95753 100644 --- a/tests/kernel/threads/thread_stack/src/main.c +++ b/tests/kernel/threads/thread_stack/src/main.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include "test_syscall.h" @@ -41,8 +41,8 @@ void z_impl_stack_info_get(char **start_addr, size_t *size) static inline void z_vrfy_stack_info_get(char **start_addr, size_t *size) { - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(start_addr, sizeof(uintptr_t))); - Z_OOPS(Z_SYSCALL_MEMORY_WRITE(size, sizeof(size_t))); + K_OOPS(K_SYSCALL_MEMORY_WRITE(start_addr, sizeof(uintptr_t))); + K_OOPS(K_SYSCALL_MEMORY_WRITE(size, sizeof(size_t))); z_impl_stack_info_get(start_addr, size); } @@ -333,9 +333,9 @@ void scenario_entry(void *stack_obj, size_t obj_size, size_t reported_size, size_t metadata_size; #ifdef CONFIG_USERSPACE - struct z_object *zo; + struct k_object *zo; - zo = z_object_find(stack_obj); + zo = k_object_find(stack_obj); if (zo != NULL) { is_user = true; #ifdef CONFIG_GEN_PRIV_STACKS diff --git a/tests/kernel/threads/tls/prj.conf b/tests/kernel/threads/tls/prj.conf index 390b9c589d7..36a39b3c777 100644 --- a/tests/kernel/threads/tls/prj.conf +++ b/tests/kernel/threads/tls/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_THREAD_LOCAL_STORAGE=y diff --git a/tests/kernel/threads/tls/testcase.yaml b/tests/kernel/threads/tls/testcase.yaml index 1eb12ec1036..4206ecdeff2 100644 --- a/tests/kernel/threads/tls/testcase.yaml +++ b/tests/kernel/threads/tls/testcase.yaml @@ -14,6 +14,8 @@ tests: - userspace filter: CONFIG_ARCH_HAS_THREAD_LOCAL_STORAGE and CONFIG_ARCH_HAS_USERSPACE and CONFIG_TOOLCHAIN_SUPPORTS_THREAD_LOCAL_STORAGE + arch_exclude: + - posix # ARCMWDT can't handle THREAD_LOCAL_STORAGE with USERSPACE, see #52570 for details toolchain_exclude: arcmwdt extra_configs: diff --git a/tests/kernel/tickless/tickless_concept/prj.conf b/tests/kernel/tickless/tickless_concept/prj.conf index ce473bdd87d..9290ae5a65d 100644 --- a/tests/kernel/tickless/tickless_concept/prj.conf +++ b/tests/kernel/tickless/tickless_concept/prj.conf @@ -2,4 +2,3 @@ CONFIG_ZTEST=y CONFIG_PM=y CONFIG_SYS_CLOCK_TICKS_PER_SEC=100 CONFIG_MP_MAX_NUM_CPUS=1 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/timer/cycle64/prj.conf b/tests/kernel/timer/cycle64/prj.conf index 90c1449d102..bb965b32e32 100644 --- a/tests/kernel/timer/cycle64/prj.conf +++ b/tests/kernel/timer/cycle64/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_PRINTK=y diff --git a/tests/kernel/timer/starve/prj.conf b/tests/kernel/timer/starve/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/kernel/timer/starve/prj.conf +++ b/tests/kernel/timer/starve/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/timer/timepoints/prj.conf b/tests/kernel/timer/timepoints/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/kernel/timer/timepoints/prj.conf +++ b/tests/kernel/timer/timepoints/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/timer/timer_api/prj.conf b/tests/kernel/timer/timer_api/prj.conf index 7b39ab9d874..dfcd95a730f 100644 --- a/tests/kernel/timer/timer_api/prj.conf +++ b/tests/kernel/timer/timer_api/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y CONFIG_MP_MAX_NUM_CPUS=1 diff --git a/tests/kernel/timer/timer_api/prj_tickless.conf b/tests/kernel/timer/timer_api/prj_tickless.conf index 5fcd26b74bf..2b00d1fe866 100644 --- a/tests/kernel/timer/timer_api/prj_tickless.conf +++ b/tests/kernel/timer/timer_api/prj_tickless.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_PM=y CONFIG_TICKLESS_KERNEL=y CONFIG_MP_MAX_NUM_CPUS=1 diff --git a/tests/kernel/timer/timer_api/src/timer_convert.c b/tests/kernel/timer/timer_api/src/timer_convert.c index f8911f240c2..5e4d76723c7 100644 --- a/tests/kernel/timer/timer_api/src/timer_convert.c +++ b/tests/kernel/timer/timer_api/src/timer_convert.c @@ -6,7 +6,7 @@ #include #include #include -#include +#include #define NUM_RANDOM 100 @@ -30,9 +30,108 @@ struct test_rec { #define TESTREC(src, dst, round, prec) { \ UNIT_##src, UNIT_##dst, prec, ROUND_##round, \ - (void *)k_##src##_to_##dst##_##round##prec \ + (void *)test_##src##_to_##dst##_##round##prec \ } \ +#ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME +#define TESTVAR(src, dst, round, prec) +#else +#define TESTVAR(src, dst, round, prec) \ + uint##prec##_t test_##src##_to_##dst##_##round##prec##_val = \ + k_##src##_to_##dst##_##round##prec(42); +#endif + +#define TESTFUNC(src, dst, round, prec) \ + TESTVAR(src, dst, round, prec) \ + static uint##prec##_t test_##src##_to_##dst##_##round##prec(uint##prec##_t t) { \ + return k_##src##_to_##dst##_##round##prec(t); \ + } + +TESTFUNC(ms, cyc, floor, 32) +TESTFUNC(ms, cyc, floor, 64) +TESTFUNC(ms, cyc, near, 32) +TESTFUNC(ms, cyc, near, 64) +TESTFUNC(ms, cyc, ceil, 32) +TESTFUNC(ms, cyc, ceil, 64) +TESTFUNC(ms, ticks, floor, 32) +TESTFUNC(ms, ticks, floor, 64) +TESTFUNC(ms, ticks, near, 32) +TESTFUNC(ms, ticks, near, 64) +TESTFUNC(ms, ticks, ceil, 32) +TESTFUNC(ms, ticks, ceil, 64) +TESTFUNC(us, cyc, floor, 32) +TESTFUNC(us, cyc, floor, 64) +TESTFUNC(us, cyc, near, 32) +TESTFUNC(us, cyc, near, 64) +TESTFUNC(us, cyc, ceil, 32) +TESTFUNC(us, cyc, ceil, 64) +TESTFUNC(us, ticks, floor, 32) +TESTFUNC(us, ticks, floor, 64) +TESTFUNC(us, ticks, near, 32) +TESTFUNC(us, ticks, near, 64) +TESTFUNC(us, ticks, ceil, 32) +TESTFUNC(us, ticks, ceil, 64) +TESTFUNC(cyc, ms, floor, 32) +TESTFUNC(cyc, ms, floor, 64) +TESTFUNC(cyc, ms, near, 32) +TESTFUNC(cyc, ms, near, 64) +TESTFUNC(cyc, ms, ceil, 32) +TESTFUNC(cyc, ms, ceil, 64) +TESTFUNC(cyc, us, floor, 32) +TESTFUNC(cyc, us, floor, 64) +TESTFUNC(cyc, us, near, 32) +TESTFUNC(cyc, us, near, 64) +TESTFUNC(cyc, us, ceil, 32) +TESTFUNC(cyc, us, ceil, 64) +TESTFUNC(cyc, ticks, floor, 32) +TESTFUNC(cyc, ticks, floor, 64) +TESTFUNC(cyc, ticks, near, 32) +TESTFUNC(cyc, ticks, near, 64) +TESTFUNC(cyc, ticks, ceil, 32) +TESTFUNC(cyc, ticks, ceil, 64) +TESTFUNC(ticks, ms, floor, 32) +TESTFUNC(ticks, ms, floor, 64) +TESTFUNC(ticks, ms, near, 32) +TESTFUNC(ticks, ms, near, 64) +TESTFUNC(ticks, ms, ceil, 32) +TESTFUNC(ticks, ms, ceil, 64) +TESTFUNC(ticks, us, floor, 32) +TESTFUNC(ticks, us, floor, 64) +TESTFUNC(ticks, us, near, 32) +TESTFUNC(ticks, us, near, 64) +TESTFUNC(ticks, us, ceil, 32) +TESTFUNC(ticks, us, ceil, 64) +TESTFUNC(ticks, cyc, floor, 32) +TESTFUNC(ticks, cyc, floor, 64) +TESTFUNC(ticks, cyc, near, 32) +TESTFUNC(ticks, cyc, near, 64) +TESTFUNC(ticks, cyc, ceil, 32) +TESTFUNC(ticks, cyc, ceil, 64) +TESTFUNC(ns, cyc, floor, 32) +TESTFUNC(ns, cyc, floor, 64) +TESTFUNC(ns, cyc, near, 32) +TESTFUNC(ns, cyc, near, 64) +TESTFUNC(ns, cyc, ceil, 32) +TESTFUNC(ns, cyc, ceil, 64) +TESTFUNC(ns, ticks, floor, 32) +TESTFUNC(ns, ticks, floor, 64) +TESTFUNC(ns, ticks, near, 32) +TESTFUNC(ns, ticks, near, 64) +TESTFUNC(ns, ticks, ceil, 32) +TESTFUNC(ns, ticks, ceil, 64) +TESTFUNC(cyc, ns, floor, 32) +TESTFUNC(cyc, ns, floor, 64) +TESTFUNC(cyc, ns, near, 32) +TESTFUNC(cyc, ns, near, 64) +TESTFUNC(cyc, ns, ceil, 32) +TESTFUNC(cyc, ns, ceil, 64) +TESTFUNC(ticks, ns, floor, 32) +TESTFUNC(ticks, ns, floor, 64) +TESTFUNC(ticks, ns, near, 32) +TESTFUNC(ticks, ns, near, 64) +TESTFUNC(ticks, ns, ceil, 32) +TESTFUNC(ticks, ns, ceil, 64) + static struct test_rec tests[] = { TESTREC(ms, cyc, floor, 32), TESTREC(ms, cyc, floor, 64), diff --git a/tests/kernel/timer/timer_api/testcase.yaml b/tests/kernel/timer/timer_api/testcase.yaml index 1847499e49f..82919939e43 100644 --- a/tests/kernel/timer/timer_api/testcase.yaml +++ b/tests/kernel/timer/timer_api/testcase.yaml @@ -34,6 +34,7 @@ tests: - qemu_arc_em - qemu_arc_hs - qemu_arc_hs6x + - qemu_leon3 integration_platforms: - qemu_cortex_m3 - nsim_em diff --git a/tests/kernel/timer/timer_behavior/Kconfig b/tests/kernel/timer/timer_behavior/Kconfig index b881fdeb741..ba5f18e969e 100644 --- a/tests/kernel/timer/timer_behavior/Kconfig +++ b/tests/kernel/timer/timer_behavior/Kconfig @@ -23,6 +23,7 @@ config TIMER_TEST_PERIOD config TIMER_TEST_MAX_STDDEV int "Maximum standard deviation in microseconds allowed" + default 33 if NPCX_ITIM_TIMER default 10 config TIMER_TEST_MAX_DRIFT @@ -41,3 +42,32 @@ config TIMER_TEST_PERIOD_MAX_DRIFT_PERCENT default 10 help A value of 10 means 10%. + +config TIMER_EXTERNAL_TEST + bool "Perform test using an external tool" + help + Toggles a GPIO pin, on every period, that can be used by an external + tool (such as a logic analyzer) to gather timing data. A pytest harness + is used to get the data collected by the tool and evaluate it. + +if TIMER_EXTERNAL_TEST + +config TIMER_EXTERNAL_TEST_MAX_DRIFT_PPM + int "Maximum drift in PPM for tests using external tool" + default 4500 + help + Parts Per Million of allowed drift when using an external tool + connected to a GPIO pin is used to measure time behaviour. + +config TIMER_EXTERNAL_TEST_PERIOD_MAX_DRIFT_PPM + int "Maximum timer period drift in PPM for tests using external tool" + default 100000 + help + Parts Per Million of allowed period drift when using an external tool + connected to a GPIO pin is used to measure time behaviour. + +config TIMER_EXTERNAL_TEST_SYNC_DELAY + int "Delay, in seconds, between tests, so that external tool can be ready" + default 3 + +endif # TIMER_EXTERNAL_TEST diff --git a/tests/kernel/timer/timer_behavior/README b/tests/kernel/timer/timer_behavior/README index b94b091049c..64fc2d37112 100644 --- a/tests/kernel/timer/timer_behavior/README +++ b/tests/kernel/timer/timer_behavior/README @@ -6,3 +6,79 @@ Records and calculates statistical values against a timer validating that. 2. Periodic timers do not drift in either direction from expected total time. Timers are meant to be precise and accurate. This test validates an implementation is both. + +-------------------------------------------------------------------------------- + +External tool testing + +It's also possible to use an external tool, such as a logic analyzer, to +collect samples. The "kernel.timer.timer_behavior_external" test will toggle a +GPIO pin on every cycle - first cycle will be a rising edge. This test expects +a Python module to interface with the external tool, which will provide the +necessary statistics that the test will use to assert the test status. + +GPIO pin + +To enable external tool testing on a board, it must provide the compatible +"test-kernel-timer-behavior-external", with property "timeout-gpios" being the +GPIO pin that will be toggled each period. + +External tool interface + +In order to get data from the external tool, the test expects a Python module, +named on testcase.yaml, with the following interface: + + run(seconds: float, options: str) -> {} + +The `seconds` parameter defines for how long the data collection is expected +to run; `options` is a string defined on testcase.yaml with options known to +the external tool helper module. It should return a dictionary with the +following statistics, in seconds: + + 'mean': Mean time of each period + 'stddev': Standard deviation from the mean time + 'var': Variance from the mean time + 'min': Minimum period registered + 'max': Maximum period registered + 'total_time': Total time, between first and last period. + +Note that the collection may need to go a bit after the "seconds" parameter, +to account for expected drift in the test and between the DUT and the external +tool. + +One can check `pytest/saleae_logic2.py` file as a sample of external tool +helper module. + +Twister + +For Twister execute the external tool testing, the fixture "gpio_timerout" +must be available on the device. Also, testcase.yaml +"harness_config/pytest_args" from "kernel.timer.timer_behavior_external" must +have parameters "tool", with the name of a loadable Python module and +"tool-options", a string with options passed to the Python module helper. + +Check testcase.yaml for an example using the saleae_logic2 module. + +Configuration options + +At its heart, the external testing is actually comparing two clocks: one on +the board under test and one at the external tool (Zephyr implementation of +the timer also plays a role, and it's the real target of the test, but it +depends on the board's clock). Different clocks run at different speeds, so +they tend to drift. To be able to account for this drift, the external test +doesn't reuse CONFIG_TIMER_TEST_MAX_DRIFT and +CONFIG_TIMER_TEST_PERIOD_MAX_DRIFT_PERCENT, instead introducing +CONFIG_TIMER_EXTERNAL_TEST_MAX_DRIFT_PPM and +CONFIG_TIMER_EXTERNAL_TEST_PERIOD_MAX_DRIFT_PPM, that can be more finely tuned +for the hardware in question. + +Also, CONFIG_TIMER_EXTERNAL_TEST_SYNC_DELAY is used to set a delay before a +test cycle starts, so that the external tool can be set up. + +Dependencies + +The external tool interface may have its own dependencies. For instance, +the saleae_logic2 module ones are listed at pytest/requirements-saleae.txt. +One can install them with pip (possibly in some virtual environment): + + pip install -r pytest/requirements-saleae.txt diff --git a/tests/kernel/timer/timer_behavior/boards/esp32s3_devkitm.overlay b/tests/kernel/timer/timer_behavior/boards/esp32s3_devkitm.overlay new file mode 100644 index 00000000000..e8bc477d394 --- /dev/null +++ b/tests/kernel/timer/timer_behavior/boards/esp32s3_devkitm.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + resources { + compatible = "test-kernel-timer-behavior-external"; + + timerout-gpios = <&gpio0 4 GPIO_ACTIVE_LOW>; + }; +}; diff --git a/tests/kernel/timer/timer_behavior/boards/frdm_k64f.overlay b/tests/kernel/timer/timer_behavior/boards/frdm_k64f.overlay new file mode 100644 index 00000000000..c72edf876d8 --- /dev/null +++ b/tests/kernel/timer/timer_behavior/boards/frdm_k64f.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + resources { + compatible = "test-kernel-timer-behavior-external"; + + timerout-gpios = <&gpioc 3 GPIO_ACTIVE_LOW>; /* Arduino D7 */ + }; +}; diff --git a/tests/kernel/timer/timer_behavior/boards/mec15xxevb_assy6853.overlay b/tests/kernel/timer/timer_behavior/boards/mec15xxevb_assy6853.overlay new file mode 100644 index 00000000000..25c39b6c390 --- /dev/null +++ b/tests/kernel/timer/timer_behavior/boards/mec15xxevb_assy6853.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + resources { + compatible = "test-kernel-timer-behavior-external"; + + timerout-gpios = <&gpio_140_176 14 GPIO_ACTIVE_LOW>; + }; +}; diff --git a/tests/kernel/timer/timer_behavior/dts/bindings/timer-behavior-external.yaml b/tests/kernel/timer/timer_behavior/dts/bindings/timer-behavior-external.yaml new file mode 100644 index 00000000000..0809145fe29 --- /dev/null +++ b/tests/kernel/timer/timer_behavior/dts/bindings/timer-behavior-external.yaml @@ -0,0 +1,19 @@ +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +description: | + Binding providing resources required to build and run the + tests/kernel/timer/timer_behavior/kernel.timer.timer_behavior_external + test in Zephyr. + +compatible: "test-kernel-timer-behavior-external" + +properties: + timerout-gpios: + type: phandle-array + required: true + description: + GPIO pin that will toggle on each cycle of the test, to be + connected to an external tool (such as a logic analyzer) + that will collect timing information. diff --git a/tests/kernel/timer/timer_behavior/prj.conf b/tests/kernel/timer/timer_behavior/prj.conf index 3333fd8dd41..92eef4c0ddb 100644 --- a/tests/kernel/timer/timer_behavior/prj.conf +++ b/tests/kernel/timer/timer_behavior/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_CBPRINTF_FP_SUPPORT=y # Make sure this is off. Otherwise a single 60-character line at diff --git a/tests/kernel/timer/timer_behavior/pytest/conftest.py b/tests/kernel/timer/timer_behavior/pytest/conftest.py new file mode 100644 index 00000000000..d9564664b70 --- /dev/null +++ b/tests/kernel/timer/timer_behavior/pytest/conftest.py @@ -0,0 +1,41 @@ +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +import pytest + +from pathlib import Path + +def pytest_addoption(parser): + parser.addoption('--tool') + parser.addoption('--tool-options') + parser.addoption('--sys-clock-hw-cycles-per-sec', default=None) + +@pytest.fixture() +def tool(request): + return request.config.getoption('--tool') + +@pytest.fixture() +def tool_options(request): + return request.config.getoption('--tool-options') + +@pytest.fixture() +def config(request): + build_dir = Path(request.config.getoption('--build-dir')) + file_name = build_dir / 'zephyr' / '.config' + + cfgs = {} + with open(file_name) as fp: + for line in fp: + if line.startswith('CONFIG_'): + k, v = line.split('=', maxsplit=1) + cfgs[k[7:]] = v + + return cfgs + +@pytest.fixture() +def sys_clock_hw_cycles_per_sec(request, config): + if request.config.getoption('--sys-clock-hw-cycles-per-sec'): + return int(request.config.getoption('--sys-clock-hw-cycles-per-sec')) + + return int(config['SYS_CLOCK_HW_CYCLES_PER_SEC']) diff --git a/tests/kernel/timer/timer_behavior/pytest/requirements-saleae.txt b/tests/kernel/timer/timer_behavior/pytest/requirements-saleae.txt new file mode 100644 index 00000000000..1a5dc09125b --- /dev/null +++ b/tests/kernel/timer/timer_behavior/pytest/requirements-saleae.txt @@ -0,0 +1,2 @@ +numpy +logic2-automation diff --git a/tests/kernel/timer/timer_behavior/pytest/saleae_logic2.py b/tests/kernel/timer/timer_behavior/pytest/saleae_logic2.py new file mode 100644 index 00000000000..7ec141dabd3 --- /dev/null +++ b/tests/kernel/timer/timer_behavior/pytest/saleae_logic2.py @@ -0,0 +1,88 @@ +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +# Sample code showing an external tool Python module helper for Saleae Logic 2 +# compatible logic analyzer. +# To use it, the Saleae Logic 2 Automation server must be enabled. For more +# information on it, check +# https://saleae.github.io/logic2-automation/getting_started.html + +import numpy as np +import tempfile + +from pathlib import Path +from saleae import automation +from saleae.automation import (CaptureConfiguration, LogicDeviceConfiguration, +DigitalTriggerCaptureMode, DigitalTriggerType) + +def do_collection(device_id, port, channel, sample_rate, threshold_volts, + seconds, output_dir): + with automation.Manager.connect(port=port) as manager: + + device_configuration = LogicDeviceConfiguration( + enabled_digital_channels=[channel], + digital_sample_rate=sample_rate, + digital_threshold_volts=threshold_volts, + ) + + capture_mode = DigitalTriggerCaptureMode(DigitalTriggerType.RISING, + channel, + after_trigger_seconds=seconds) + capture_configuration = CaptureConfiguration(capture_mode=capture_mode) + + with manager.start_capture( + device_id=device_id, + device_configuration=device_configuration, + capture_configuration=capture_configuration) as capture: + + capture.wait() + + capture.export_raw_data_csv(directory=output_dir, + digital_channels=[channel]) + +def do_analysis(output_dir): + file_name = Path(output_dir) / 'digital.csv' + all_data = np.loadtxt(file_name, delimiter=',', skiprows=1, usecols=0) + + # Pre trigger data is negative on CSV + non_negative = all_data[all_data >= 0] + + # Last sample is just captured at last moment of capture, not related + # to gpio toggle. Discard it + data = non_negative[:-1] + + diff = np.diff(data) + + mean = np.mean(diff) + std = np.std(diff) + var = np.var(diff) + minimum = np.min(diff) + maximum = np.max(diff) + total_time = data[-1] + + return {'mean': mean, 'stddev': std, 'var': var, 'min': minimum, + 'max': maximum, 'total_time': total_time} + + +# options should be a string of the format: +# [device-id=,]port=, +# channel=,sample-rate=, +# threshold-volts= +def run(seconds, options): + options = [i for p in options.split(',') for i in p.split('=')] + options = dict(zip(options[::2], options[1::2])) + + device_id = options.get('device-id') + port = int(options.get('port')) + channel = int(options.get('channel')) + sample_rate = int(options.get('sample-rate')) + threshold_volts = float(options.get('threshold-volts')) + + with tempfile.TemporaryDirectory() as output_dir: + output_dir = tempfile.mkdtemp() + # Add one second to ensure all data is captured + do_collection(device_id, port, channel, sample_rate, threshold_volts, + seconds + 1, output_dir) + + return do_analysis(output_dir) diff --git a/tests/kernel/timer/timer_behavior/pytest/test_timer.py b/tests/kernel/timer/timer_behavior/pytest/test_timer.py new file mode 100755 index 00000000000..c6dced949c1 --- /dev/null +++ b/tests/kernel/timer/timer_behavior/pytest/test_timer.py @@ -0,0 +1,77 @@ +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +import logging + +from math import ceil + +from twister_harness import DeviceAdapter + +logger = logging.getLogger(__name__) + + +def do_analysys(test, stats, config, sys_clock_hw_cycles_per_sec): + logger.info('====================================================') + logger.info(f'periodic timer behaviour using {test} mechanism:') + + test_period = int(config['TIMER_TEST_PERIOD']) + test_samples = int(config['TIMER_TEST_SAMPLES']) + + seconds = (test_period * test_samples) / 1_000_000 + + periods_sec = test_period / 1_000_000 + ticks_per_sec = int(config['SYS_CLOCK_TICKS_PER_SEC']) + periods_tick = ceil(ticks_per_sec * periods_sec) + + expected_period = test_period * sys_clock_hw_cycles_per_sec / 1_000_000 + cyc_per_tick = sys_clock_hw_cycles_per_sec / ticks_per_sec + expected_period_drift = ((periods_tick * cyc_per_tick - expected_period) / + sys_clock_hw_cycles_per_sec * 1_000_000) + expected_total_drift = expected_period_drift * test_samples / 1_000_000 + + period_max_drift = (int(config['TIMER_EXTERNAL_TEST_PERIOD_MAX_DRIFT_PPM']) + / 1_000_000) + min_bound = (test_period - period_max_drift * test_period + + expected_period_drift) / 1_000_000 + max_bound = (test_period + period_max_drift * test_period + + expected_period_drift) / 1_000_000 + + max_stddev = int(config['TIMER_TEST_MAX_STDDEV']) / 1_000_000 + + max_drift_ppm = int(config['TIMER_EXTERNAL_TEST_MAX_DRIFT_PPM']) + time_diff = stats['total_time'] - seconds - expected_total_drift + + logger.info(f'min: {stats["min"] * 1_000_000:.6f} us') + logger.info(f'max: {stats["max"] * 1_000_000:.6f} us') + logger.info(f'mean: {stats["mean"] * 1_000_000:.6f} us') + logger.info(f'variance: {stats["var"] * 1_000_000:.6f} us') + logger.info(f'stddev: {stats["stddev"] * 1_000_000:.6f} us') + logger.info(f'total time: {stats["total_time"] * 1_000_000:.6f} us') + logger.info(f'expected drift: {seconds * max_drift_ppm} us') + logger.info(f'real drift: {time_diff * 1_000_000:.6f} us') + logger.info('====================================================') + + assert stats['stddev'] < max_stddev + assert stats['min'] >= min_bound + assert stats['max'] <= max_bound + assert abs(time_diff) < seconds * max_drift_ppm / 1_000_000 + + +def wait_sync_point(dut: DeviceAdapter, point): + dut.readlines_until(regex=f"===== {point} =====") + + +def test_flash(dut: DeviceAdapter, tool, tool_options, config, + sys_clock_hw_cycles_per_sec): + tool = __import__(tool) + + test_period = int(config['TIMER_TEST_PERIOD']) + test_samples = int(config['TIMER_TEST_SAMPLES']) + seconds = (test_period * test_samples) / 1_000_000 + + tests = ["builtin", "startdelay"] + for test in tests: + wait_sync_point(dut, test) + stats = tool.run(seconds, tool_options) + do_analysys(test, stats, config, sys_clock_hw_cycles_per_sec) diff --git a/tests/kernel/timer/timer_behavior/src/jitter_drift.c b/tests/kernel/timer/timer_behavior/src/jitter_drift.c index 6d3e78d514b..d78adb40eaf 100644 --- a/tests/kernel/timer/timer_behavior/src/jitter_drift.c +++ b/tests/kernel/timer/timer_behavior/src/jitter_drift.c @@ -9,10 +9,17 @@ #include #include +#include #include #include +#ifdef CONFIG_TIMER_EXTERNAL_TEST +#define TIMER_OUT_NODE DT_INST(0, test_kernel_timer_behavior_external) +static const struct gpio_dt_spec timer_out = GPIO_DT_SPEC_GET(TIMER_OUT_NODE, + timerout_gpios); +#endif + static uint32_t periodic_idx; static uint64_t periodic_data[CONFIG_TIMER_TEST_SAMPLES + 1]; static uint64_t periodic_start, periodic_end; @@ -28,6 +35,10 @@ static void timer_period_fn(struct k_timer *t) { uint64_t curr_cycle; +#ifdef CONFIG_TIMER_EXTERNAL_TEST + gpio_pin_toggle_dt(&timer_out); +#endif + #ifdef CONFIG_TIMER_HAS_64BIT_CYCLE_COUNTER curr_cycle = k_cycle_get_64(); #else @@ -62,6 +73,10 @@ static void timer_startdelay_fn(struct k_timer *t) { uint64_t curr_cycle; +#ifdef CONFIG_TIMER_EXTERNAL_TEST + gpio_pin_toggle_dt(&timer_out); +#endif + #ifdef CONFIG_TIMER_HAS_64BIT_CYCLE_COUNTER curr_cycle = k_cycle_get_64(); #else @@ -277,12 +292,28 @@ static void do_test_using(void (*sample_collection_fn)(void)) ZTEST(timer_jitter_drift, test_jitter_drift_timer_period) { TC_PRINT("periodic timer behavior test using built-in restart mechanism\n"); +#ifdef CONFIG_TIMER_EXTERNAL_TEST + TC_PRINT("===== External Tool Sync Point =====\n"); + TC_PRINT("===== builtin =====\n"); + TC_PRINT("===== Waiting %d seconds =====\n", + CONFIG_TIMER_EXTERNAL_TEST_SYNC_DELAY); + k_sleep(K_SECONDS(CONFIG_TIMER_EXTERNAL_TEST_SYNC_DELAY)); + gpio_pin_configure_dt(&timer_out, GPIO_OUTPUT_LOW); +#endif do_test_using(collect_timer_period_time_samples); } ZTEST(timer_jitter_drift, test_jitter_drift_timer_startdelay) { TC_PRINT("periodic timer behavior test using explicit start with delay\n"); +#ifdef CONFIG_TIMER_EXTERNAL_TEST + TC_PRINT("===== External Tool Sync Point =====\n"); + TC_PRINT("===== startdelay =====\n"); + TC_PRINT("===== Waiting %d seconds =====\n", + CONFIG_TIMER_EXTERNAL_TEST_SYNC_DELAY); + k_sleep(K_SECONDS(CONFIG_TIMER_EXTERNAL_TEST_SYNC_DELAY)); + gpio_pin_configure_dt(&timer_out, GPIO_OUTPUT_LOW); +#endif do_test_using(collect_timer_startdelay_time_samples); } diff --git a/tests/kernel/timer/timer_behavior/src/main.c b/tests/kernel/timer/timer_behavior/src/main.c index ac2e68d59c3..f3806198e8a 100644 --- a/tests/kernel/timer/timer_behavior/src/main.c +++ b/tests/kernel/timer/timer_behavior/src/main.c @@ -9,5 +9,7 @@ void test_main(void) { ztest_run_test_suite(timer_jitter_drift); +#ifndef CONFIG_TIMER_EXTERNAL_TEST ztest_run_test_suite(timer_tick_train); +#endif } diff --git a/tests/kernel/timer/timer_behavior/testcase.yaml b/tests/kernel/timer/timer_behavior/testcase.yaml index cb63b66be71..cf761006b73 100644 --- a/tests/kernel/timer/timer_behavior/testcase.yaml +++ b/tests/kernel/timer/timer_behavior/testcase.yaml @@ -17,3 +17,13 @@ tests: - hifive_unleashed - mps2_an385 - mps2_an521_ns + kernel.timer.timer_behavior_external: + filter: dt_compat_enabled("test-kernel-timer-behavior-external") + harness: pytest + harness_config: + pytest_args: ['--tool', 'saleae_logic2', '--tool-options', + 'port=10430,channel=1,sample-rate=6_250_000,threshold-volts=3.3'] + fixture: gpio_timerout + extra_configs: + - CONFIG_TIMER_EXTERNAL_TEST=y + - CONFIG_BOOT_DELAY=5000 diff --git a/tests/kernel/timer/timer_error_case/prj.conf b/tests/kernel/timer/timer_error_case/prj.conf index bf7f45f9b92..29c94cedb7d 100644 --- a/tests/kernel/timer/timer_error_case/prj.conf +++ b/tests/kernel/timer/timer_error_case/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y CONFIG_IRQ_OFFLOAD=y CONFIG_MP_MAX_NUM_CPUS=1 diff --git a/tests/kernel/timer/timer_error_case/src/main.c b/tests/kernel/timer/timer_error_case/src/main.c index 770253677f3..e6ffe75330c 100644 --- a/tests/kernel/timer/timer_error_case/src/main.c +++ b/tests/kernel/timer/timer_error_case/src/main.c @@ -22,6 +22,10 @@ static K_THREAD_STACK_DEFINE(tstack, STACK_SIZE); static void thread_timer_start_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); k_timer_start(NULL, K_MSEC(DURATION), K_NO_WAIT); @@ -47,7 +51,7 @@ ZTEST_USER(timer_api_error, test_timer_start_null) #endif k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)thread_timer_start_null, + thread_timer_start_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -57,6 +61,10 @@ ZTEST_USER(timer_api_error, test_timer_start_null) static void thread_timer_stop_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); k_timer_stop(NULL); @@ -81,7 +89,7 @@ ZTEST_USER(timer_api_error, test_timer_stop_null) #endif k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)thread_timer_stop_null, + thread_timer_stop_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -91,6 +99,10 @@ ZTEST_USER(timer_api_error, test_timer_stop_null) static void thread_timer_status_get_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); k_timer_status_get(NULL); @@ -115,7 +127,7 @@ ZTEST_USER(timer_api_error, test_timer_status_get_null) #endif k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)thread_timer_status_get_null, + thread_timer_status_get_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -125,6 +137,10 @@ ZTEST_USER(timer_api_error, test_timer_status_get_null) static void thread_timer_status_sync_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); k_timer_status_sync(NULL); @@ -149,7 +165,7 @@ ZTEST_USER(timer_api_error, test_timer_status_sync_null) #endif k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)thread_timer_status_sync_null, + thread_timer_status_sync_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -159,6 +175,10 @@ ZTEST_USER(timer_api_error, test_timer_status_sync_null) static void thread_timer_remaining_ticks_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); k_timer_remaining_ticks(NULL); @@ -183,7 +203,7 @@ ZTEST_USER(timer_api_error, test_timer_remaining_ticks_null) #endif k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)thread_timer_remaining_ticks_null, + thread_timer_remaining_ticks_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -193,6 +213,10 @@ ZTEST_USER(timer_api_error, test_timer_remaining_ticks_null) static void thread_timer_expires_ticks_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); k_timer_expires_ticks(NULL); @@ -216,7 +240,7 @@ ZTEST_USER(timer_api_error, test_timer_expires_ticks_null) ztest_test_skip(); #endif k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)thread_timer_expires_ticks_null, + thread_timer_expires_ticks_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -226,6 +250,10 @@ ZTEST_USER(timer_api_error, test_timer_expires_ticks_null) static void thread_timer_user_data_get_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + ztest_set_fault_valid(true); k_timer_user_data_get(NULL); @@ -249,7 +277,7 @@ ZTEST_USER(timer_api_error, test_timer_user_data_get_null) ztest_test_skip(); #endif k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)thread_timer_user_data_get_null, + thread_timer_user_data_get_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); @@ -259,6 +287,10 @@ ZTEST_USER(timer_api_error, test_timer_user_data_get_null) static void thread_timer_user_data_set_null(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + int user_data = 1; ztest_set_fault_valid(true); @@ -285,7 +317,7 @@ ZTEST_USER(timer_api_error, test_timer_user_data_set_null) #endif k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)thread_timer_user_data_set_null, + thread_timer_user_data_set_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); diff --git a/tests/kernel/timer/timer_monotonic/prj.conf b/tests/kernel/timer/timer_monotonic/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/kernel/timer/timer_monotonic/prj.conf +++ b/tests/kernel/timer/timer_monotonic/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/timer/timer_monotonic/testcase.yaml b/tests/kernel/timer/timer_monotonic/testcase.yaml index 058a821123b..9c38d456986 100644 --- a/tests/kernel/timer/timer_monotonic/testcase.yaml +++ b/tests/kernel/timer/timer_monotonic/testcase.yaml @@ -15,3 +15,11 @@ tests: extra_configs: - CONFIG_APIC_TSC_DEADLINE_TIMER=y - CONFIG_HPET_TIMER=n + kernel.timer.monotonic.icount_off: + # Extra test for GH-48608 + tags: + - kernel + - timer + platform_allow: mps2_an385 + extra_configs: + - CONFIG_QEMU_ICOUNT=n diff --git a/tests/kernel/usage/thread_runtime_stats/prj.conf b/tests/kernel/usage/thread_runtime_stats/prj.conf index 2f491e3188c..7be342bcae7 100644 --- a/tests/kernel/usage/thread_runtime_stats/prj.conf +++ b/tests/kernel/usage/thread_runtime_stats/prj.conf @@ -4,4 +4,3 @@ CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_THREAD_RUNTIME_STATS=y CONFIG_SCHED_THREAD_USAGE_ALL=y CONFIG_SCHED_THREAD_USAGE_ANALYSIS=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/kernel/usage/thread_runtime_stats/testcase.yaml b/tests/kernel/usage/thread_runtime_stats/testcase.yaml index 30d67c3741c..05fabf3ba57 100644 --- a/tests/kernel/usage/thread_runtime_stats/testcase.yaml +++ b/tests/kernel/usage/thread_runtime_stats/testcase.yaml @@ -16,3 +16,5 @@ tests: integration_platforms: - qemu_x86 - mps2_an385 + platform_exclude: + - mr_canhubk3 diff --git a/tests/kernel/workq/critical/prj.conf b/tests/kernel/workq/critical/prj.conf index 16f71a11c09..f8d48f84037 100644 --- a/tests/kernel/workq/critical/prj.conf +++ b/tests/kernel/workq/critical/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MP_MAX_NUM_CPUS=1 diff --git a/tests/kernel/workq/user_work/prj.conf b/tests/kernel/workq/user_work/prj.conf index a93770f3515..d94ab7302d1 100644 --- a/tests/kernel/workq/user_work/prj.conf +++ b/tests/kernel/workq/user_work/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_IRQ_OFFLOAD=y CONFIG_HEAP_MEM_POOL_SIZE=1024 CONFIG_THREAD_NAME=y diff --git a/tests/kernel/workq/user_work/testcase.yaml b/tests/kernel/workq/user_work/testcase.yaml index e57d1221461..65356aaa316 100644 --- a/tests/kernel/workq/user_work/testcase.yaml +++ b/tests/kernel/workq/user_work/testcase.yaml @@ -2,6 +2,8 @@ tests: kernel.workqueue.user: min_flash: 34 filter: CONFIG_ARCH_HAS_USERSPACE + arch_exclude: + - posix tags: - kernel - userspace diff --git a/tests/kernel/workq/work/prj.conf b/tests/kernel/workq/work/prj.conf index 8dda06ff724..bb385ff2fc4 100644 --- a/tests/kernel/workq/work/prj.conf +++ b/tests/kernel/workq/work/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_IRQ_OFFLOAD=y CONFIG_HEAP_MEM_POOL_SIZE=1024 CONFIG_THREAD_NAME=y diff --git a/tests/kernel/workq/work/src/main.c b/tests/kernel/workq/work/src/main.c index 8c3368227cd..68a89588379 100644 --- a/tests/kernel/workq/work/src/main.c +++ b/tests/kernel/workq/work/src/main.c @@ -875,6 +875,7 @@ static void test_drain_wait_cb(struct k_timer *timer) ZTEST(work_1cpu, test_1cpu_drain_wait) { struct test_drain_wait_timer *ctx = &test_drain_wait_ctx; + struct k_work *wp = &ctx->work; int rc; /* Reset state, allow one re-submission, and use the delaying @@ -882,10 +883,10 @@ ZTEST(work_1cpu, test_1cpu_drain_wait) */ reset_counters(); atomic_set(&resubmits_left, 1); - k_work_init(&common_work, delay_handler); + k_work_init(wp, delay_handler); /* Submit to the cooperative queue. */ - rc = k_work_submit_to_queue(&coophi_queue, &common_work); + rc = k_work_submit_to_queue(&coophi_queue, wp); zassert_equal(rc, 1); zassert_equal(coophi_counter(), 0); diff --git a/tests/kernel/workq/work_queue/prj.conf b/tests/kernel/workq/work_queue/prj.conf index 33189097be7..1df67695310 100644 --- a/tests/kernel/workq/work_queue/prj.conf +++ b/tests/kernel/workq/work_queue/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_POLL=y CONFIG_ASSERT=y diff --git a/tests/kernel/workq/work_queue/src/main.c b/tests/kernel/workq/work_queue/src/main.c index 70d186cae6a..b14d2878717 100644 --- a/tests/kernel/workq/work_queue/src/main.c +++ b/tests/kernel/workq/work_queue/src/main.c @@ -20,6 +20,9 @@ #include #include +#include +LOG_MODULE_REGISTER(test); + #define NUM_TEST_ITEMS 6 /* Each work item takes 100ms by default. */ @@ -93,7 +96,7 @@ static void work_handler(struct k_work *work) struct delayed_test_item *ti = CONTAINER_OF(dwork, struct delayed_test_item, work); - TC_PRINT(" - Running test item %d\n", ti->key); + LOG_DBG(" - Running test item %d", ti->key); k_msleep(WORK_ITEM_WAIT); results[num_results++] = ti->key; @@ -124,18 +127,19 @@ static void reset_results(void) num_results = 0; } -static void coop_work_main(int arg1, int arg2) +static void coop_work_main(void *p1, void *p2, void *p3) { - int i; + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); - ARG_UNUSED(arg1); - ARG_UNUSED(arg2); + int i; /* Let the preempt thread submit the first work item. */ k_msleep(SUBMIT_WAIT / 2); for (i = 1; i < NUM_TEST_ITEMS; i += 2) { - TC_PRINT(" - Submitting work %d from coop thread\n", i + 1); + LOG_DBG(" - Submitting work %d from coop thread", i + 1); k_work_schedule(&delayed_tests[i].work, K_NO_WAIT); k_msleep(SUBMIT_WAIT); } @@ -150,11 +154,11 @@ static void delayed_test_items_submit(void) int i; k_thread_create(&co_op_data, co_op_stack, STACK_SIZE, - (k_thread_entry_t)coop_work_main, + coop_work_main, NULL, NULL, NULL, K_PRIO_COOP(10), 0, K_NO_WAIT); for (i = 0; i < NUM_TEST_ITEMS; i += 2) { - TC_PRINT(" - Submitting work %d from preempt thread\n", i + 1); + LOG_DBG(" - Submitting work %d from preempt thread", i + 1); k_work_schedule(&delayed_tests[i].work, K_NO_WAIT); k_msleep(SUBMIT_WAIT); } @@ -186,13 +190,13 @@ static void check_results(int num_tests) */ static void test_sequence(void) { - TC_PRINT(" - Initializing test items\n"); + LOG_DBG(" - Initializing test items"); delayed_test_items_init(); - TC_PRINT(" - Submitting test items\n"); + LOG_DBG(" - Submitting test items"); delayed_test_items_submit(); - TC_PRINT(" - Waiting for work to finish\n"); + LOG_DBG(" - Waiting for work to finish"); k_msleep(CHECK_WAIT); check_results(NUM_TEST_ITEMS); @@ -213,7 +217,7 @@ static void resubmit_work_handler(struct k_work *work) if (ti->key < NUM_TEST_ITEMS) { ti->key++; - TC_PRINT(" - Resubmitting work\n"); + LOG_DBG(" - Resubmitting work"); k_work_submit(work); } } @@ -226,18 +230,18 @@ static void resubmit_work_handler(struct k_work *work) */ ZTEST(workqueue_triggered, test_resubmit) { - TC_PRINT("Starting resubmit test\n"); + LOG_DBG("Starting resubmit test"); delayed_tests[0].key = 1; k_work_init_delayable(&delayed_tests[0].work, resubmit_work_handler); - TC_PRINT(" - Submitting work\n"); + LOG_DBG(" - Submitting work"); k_work_schedule(&delayed_tests[0].work, K_NO_WAIT); - TC_PRINT(" - Waiting for work to finish\n"); + LOG_DBG(" - Waiting for work to finish"); k_msleep(CHECK_WAIT); - TC_PRINT(" - Checking results\n"); + LOG_DBG(" - Checking results"); check_results(NUM_TEST_ITEMS); reset_results(); } @@ -248,7 +252,7 @@ static void delayed_work_handler(struct k_work *work) struct delayed_test_item *ti = CONTAINER_OF(dwork, struct delayed_test_item, work); - TC_PRINT(" - Running delayed test item %d\n", ti->key); + LOG_DBG(" - Running delayed test item %d", ti->key); results[num_results++] = ti->key; } @@ -271,19 +275,20 @@ static void test_delayed_init(void) } } -static void coop_delayed_work_main(int arg1, int arg2) +static void coop_delayed_work_main(void *p1, void *p2, void *p3) { - int i; + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); - ARG_UNUSED(arg1); - ARG_UNUSED(arg2); + int i; /* Let the preempt thread submit the first work item. */ k_msleep(SUBMIT_WAIT / 2); for (i = 1; i < NUM_TEST_ITEMS; i += 2) { - TC_PRINT(" - Submitting delayed work %d from" - " coop thread\n", i + 1); + LOG_DBG(" - Submitting delayed work %d from" + " coop thread", i + 1); k_work_schedule(&delayed_tests[i].work, K_MSEC((i + 1) * WORK_ITEM_WAIT)); } @@ -301,26 +306,27 @@ static void test_delayed_submit(void) int i; k_thread_create(&co_op_data, co_op_stack, STACK_SIZE, - (k_thread_entry_t)coop_delayed_work_main, + coop_delayed_work_main, NULL, NULL, NULL, K_PRIO_COOP(10), 0, K_NO_WAIT); for (i = 0; i < NUM_TEST_ITEMS; i += 2) { - TC_PRINT(" - Submitting delayed work %d from" - " preempt thread\n", i + 1); + LOG_DBG(" - Submitting delayed work %d from" + " preempt thread", i + 1); zassert_true(k_work_reschedule(&delayed_tests[i].work, K_MSEC((i + 1) * WORK_ITEM_WAIT)) >= 0, NULL); } } -static void coop_delayed_work_cancel_main(int arg1, int arg2) +static void coop_delayed_work_cancel_main(void *p1, void *p2, void *p3) { - ARG_UNUSED(arg1); - ARG_UNUSED(arg2); + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); k_work_schedule(&delayed_tests[1].work, K_MSEC(WORK_ITEM_WAIT)); - TC_PRINT(" - Cancel delayed work from coop thread\n"); + LOG_DBG(" - Cancel delayed work from coop thread"); k_work_cancel_delayable(&delayed_tests[1].work); } @@ -334,52 +340,52 @@ static void coop_delayed_work_cancel_main(int arg1, int arg2) */ ZTEST(workqueue_delayed, test_delayed_cancel) { - TC_PRINT("Starting delayed cancel test\n"); + LOG_DBG("Starting delayed cancel test"); k_work_schedule(&delayed_tests[0].work, K_MSEC(WORK_ITEM_WAIT)); - TC_PRINT(" - Cancel delayed work from preempt thread\n"); + LOG_DBG(" - Cancel delayed work from preempt thread"); k_work_cancel_delayable(&delayed_tests[0].work); k_thread_create(&co_op_data, co_op_stack, STACK_SIZE, - (k_thread_entry_t)coop_delayed_work_cancel_main, + coop_delayed_work_cancel_main, NULL, NULL, NULL, K_HIGHEST_THREAD_PRIO, 0, K_NO_WAIT); - TC_PRINT(" - Waiting for work to finish\n"); + LOG_DBG(" - Waiting for work to finish"); k_msleep(WORK_ITEM_WAIT_ALIGNED); - TC_PRINT(" - Checking results\n"); + LOG_DBG(" - Checking results"); check_results(0); reset_results(); } ZTEST(workqueue_delayed, test_delayed_pending) { - TC_PRINT("Starting delayed pending test\n"); + LOG_DBG("Starting delayed pending test"); k_work_init_delayable(&delayed_tests[0].work, delayed_work_handler); zassert_false(k_work_delayable_is_pending(&delayed_tests[0].work)); - TC_PRINT(" - Check pending delayed work when in workqueue\n"); + LOG_DBG(" - Check pending delayed work when in workqueue"); k_work_schedule(&delayed_tests[0].work, K_NO_WAIT); zassert_true(k_work_delayable_is_pending(&delayed_tests[0].work)); k_msleep(1); zassert_false(k_work_delayable_is_pending(&delayed_tests[0].work)); - TC_PRINT(" - Checking results\n"); + LOG_DBG(" - Checking results"); check_results(1); reset_results(); - TC_PRINT(" - Check pending delayed work with timeout\n"); + LOG_DBG(" - Check pending delayed work with timeout"); k_work_schedule(&delayed_tests[0].work, K_MSEC(WORK_ITEM_WAIT)); zassert_true(k_work_delayable_is_pending(&delayed_tests[0].work)); k_msleep(WORK_ITEM_WAIT_ALIGNED); zassert_false(k_work_delayable_is_pending(&delayed_tests[0].work)); - TC_PRINT(" - Checking results\n"); + LOG_DBG(" - Checking results"); check_results(1); reset_results(); } @@ -393,18 +399,18 @@ ZTEST(workqueue_delayed, test_delayed_pending) */ ZTEST(workqueue_delayed, test_delayed) { - TC_PRINT("Starting delayed test\n"); + LOG_DBG("Starting delayed test"); - TC_PRINT(" - Initializing delayed test items\n"); + LOG_DBG(" - Initializing delayed test items"); test_delayed_init(); - TC_PRINT(" - Submitting delayed test items\n"); + LOG_DBG(" - Submitting delayed test items"); test_delayed_submit(); - TC_PRINT(" - Waiting for delayed work to finish\n"); + LOG_DBG(" - Waiting for delayed work to finish"); k_msleep(CHECK_WAIT); - TC_PRINT(" - Checking results\n"); + LOG_DBG(" - Checking results"); check_results(NUM_TEST_ITEMS); reset_results(); } @@ -415,7 +421,7 @@ static void triggered_work_handler(struct k_work *work) struct triggered_test_item *ti = CONTAINER_OF(pwork, struct triggered_test_item, work); - TC_PRINT(" - Running triggered test item %d\n", ti->key); + LOG_DBG(" - Running triggered test item %d", ti->key); zassert_equal(ti->work.poll_result, expected_poll_result, "res %d expect %d", ti->work.poll_result, expected_poll_result); @@ -459,7 +465,7 @@ static void test_triggered_submit(k_timeout_t timeout) int i; for (i = 0; i < NUM_TEST_ITEMS; i++) { - TC_PRINT(" - Submitting triggered work %d\n", i + 1); + LOG_DBG(" - Submitting triggered work %d", i + 1); zassert_true(k_work_poll_submit(&triggered_tests[i].work, &triggered_tests[i].event, 1, timeout) == 0, NULL); @@ -476,7 +482,7 @@ static void test_triggered_trigger(void) int i; for (i = 0; i < NUM_TEST_ITEMS; i++) { - TC_PRINT(" - Triggering work %d\n", i + 1); + LOG_DBG(" - Triggering work %d", i + 1); zassert_true(k_poll_signal_raise(&triggered_tests[i].signal, 1) == 0, NULL); } @@ -491,24 +497,24 @@ static void test_triggered_trigger(void) */ ZTEST(workqueue_triggered, test_triggered) { - TC_PRINT("Starting triggered test\n"); + LOG_DBG("Starting triggered test"); /* As work items are triggered, they should indicate an event. */ expected_poll_result = 0; - TC_PRINT(" - Initializing triggered test items\n"); + LOG_DBG(" - Initializing triggered test items"); test_triggered_init(); - TC_PRINT(" - Submitting triggered test items\n"); + LOG_DBG(" - Submitting triggered test items"); test_triggered_submit(K_FOREVER); - TC_PRINT(" - Triggering test items execution\n"); + LOG_DBG(" - Triggering test items execution"); test_triggered_trigger(); /* Items should be executed when we will be sleeping. */ k_msleep(WORK_ITEM_WAIT); - TC_PRINT(" - Checking results\n"); + LOG_DBG(" - Checking results"); check_results(NUM_TEST_ITEMS); reset_results(); } @@ -522,24 +528,24 @@ ZTEST(workqueue_triggered, test_triggered) */ ZTEST(workqueue_triggered, test_already_triggered) { - TC_PRINT("Starting triggered test\n"); + LOG_DBG("Starting triggered test"); /* As work items are triggered, they should indicate an event. */ expected_poll_result = 0; - TC_PRINT(" - Initializing triggered test items\n"); + LOG_DBG(" - Initializing triggered test items"); test_triggered_init(); - TC_PRINT(" - Triggering test items execution\n"); + LOG_DBG(" - Triggering test items execution"); test_triggered_trigger(); - TC_PRINT(" - Submitting triggered test items\n"); + LOG_DBG(" - Submitting triggered test items"); test_triggered_submit(K_FOREVER); /* Items should be executed when we will be sleeping. */ k_msleep(WORK_ITEM_WAIT); - TC_PRINT(" - Checking results\n"); + LOG_DBG(" - Checking results"); check_results(NUM_TEST_ITEMS); reset_results(); } @@ -554,7 +560,7 @@ static void triggered_resubmit_work_handler(struct k_work *work) if (ti->key < NUM_TEST_ITEMS) { ti->key++; - TC_PRINT(" - Resubmitting triggered work\n"); + LOG_DBG(" - Resubmitting triggered work"); k_poll_signal_reset(&triggered_tests[0].signal); zassert_true(k_work_poll_submit(&triggered_tests[0].work, @@ -574,7 +580,7 @@ ZTEST(workqueue_triggered, test_triggered_resubmit) { int i; - TC_PRINT("Starting triggered resubmit test\n"); + LOG_DBG("Starting triggered resubmit test"); /* As work items are triggered, they should indicate an event. */ expected_poll_result = 0; @@ -589,20 +595,19 @@ ZTEST(workqueue_triggered, test_triggered_resubmit) K_POLL_MODE_NOTIFY_ONLY, &triggered_tests[0].signal); - TC_PRINT(" - Submitting triggered work\n"); + LOG_DBG(" - Submitting triggered work"); zassert_true(k_work_poll_submit(&triggered_tests[0].work, &triggered_tests[0].event, 1, K_FOREVER) == 0, NULL); for (i = 0; i < NUM_TEST_ITEMS; i++) { - TC_PRINT(" - Triggering test item execution (iteration: %d)\n", - i + 1); + LOG_DBG(" - Triggering test item execution (iteration: %d)", i + 1); zassert_true(k_poll_signal_raise(&triggered_tests[0].signal, 1) == 0, NULL); k_msleep(WORK_ITEM_WAIT); } - TC_PRINT(" - Checking results\n"); + LOG_DBG(" - Checking results"); check_results(NUM_TEST_ITEMS); reset_results(); } @@ -616,24 +621,24 @@ ZTEST(workqueue_triggered, test_triggered_resubmit) */ ZTEST(workqueue_triggered, test_triggered_no_wait) { - TC_PRINT("Starting triggered test\n"); + LOG_DBG("Starting triggered test"); /* As work items are triggered, they should indicate an event. */ expected_poll_result = 0; - TC_PRINT(" - Initializing triggered test items\n"); + LOG_DBG(" - Initializing triggered test items"); test_triggered_init(); - TC_PRINT(" - Triggering test items execution\n"); + LOG_DBG(" - Triggering test items execution"); test_triggered_trigger(); - TC_PRINT(" - Submitting triggered test items\n"); + LOG_DBG(" - Submitting triggered test items"); test_triggered_submit(K_NO_WAIT); /* Items should be executed when we will be sleeping. */ k_msleep(WORK_ITEM_WAIT); - TC_PRINT(" - Checking results\n"); + LOG_DBG(" - Checking results"); check_results(NUM_TEST_ITEMS); reset_results(); } @@ -647,21 +652,21 @@ ZTEST(workqueue_triggered, test_triggered_no_wait) */ ZTEST(workqueue_triggered, test_triggered_no_wait_expired) { - TC_PRINT("Starting triggered test\n"); + LOG_DBG("Starting triggered test"); /* As work items are not triggered, they should be marked as expired. */ expected_poll_result = -EAGAIN; - TC_PRINT(" - Initializing triggered test items\n"); + LOG_DBG(" - Initializing triggered test items"); test_triggered_init(); - TC_PRINT(" - Submitting triggered test items\n"); + LOG_DBG(" - Submitting triggered test items"); test_triggered_submit(K_NO_WAIT); /* Items should be executed when we will be sleeping. */ k_msleep(WORK_ITEM_WAIT); - TC_PRINT(" - Checking results\n"); + LOG_DBG(" - Checking results"); check_results(NUM_TEST_ITEMS); reset_results(); } @@ -675,24 +680,24 @@ ZTEST(workqueue_triggered, test_triggered_no_wait_expired) */ ZTEST(workqueue_triggered, test_triggered_wait) { - TC_PRINT("Starting triggered test\n"); + LOG_DBG("Starting triggered test"); /* As work items are triggered, they should indicate an event. */ expected_poll_result = 0; - TC_PRINT(" - Initializing triggered test items\n"); + LOG_DBG(" - Initializing triggered test items"); test_triggered_init(); - TC_PRINT(" - Triggering test items execution\n"); + LOG_DBG(" - Triggering test items execution"); test_triggered_trigger(); - TC_PRINT(" - Submitting triggered test items\n"); + LOG_DBG(" - Submitting triggered test items"); test_triggered_submit(K_MSEC(2 * SUBMIT_WAIT)); /* Items should be executed when we will be sleeping. */ k_msleep(SUBMIT_WAIT); - TC_PRINT(" - Checking results\n"); + LOG_DBG(" - Checking results"); check_results(NUM_TEST_ITEMS); reset_results(); } @@ -706,25 +711,25 @@ ZTEST(workqueue_triggered, test_triggered_wait) */ ZTEST(workqueue_triggered, test_triggered_wait_expired) { - TC_PRINT("Starting triggered test\n"); + LOG_DBG("Starting triggered test"); /* As work items are not triggered, they should time out. */ expected_poll_result = -EAGAIN; - TC_PRINT(" - Initializing triggered test items\n"); + LOG_DBG(" - Initializing triggered test items"); test_triggered_init(); - TC_PRINT(" - Submitting triggered test items\n"); + LOG_DBG(" - Submitting triggered test items"); test_triggered_submit(K_MSEC(2 * SUBMIT_WAIT)); /* Items should not be executed when we will be sleeping here. */ k_msleep(SUBMIT_WAIT); - TC_PRINT(" - Checking results (before timeout)\n"); + LOG_DBG(" - Checking results (before timeout)"); check_results(0); /* Items should be executed when we will be sleeping here. */ k_msleep(SUBMIT_WAIT * 2); - TC_PRINT(" - Checking results (after timeout)\n"); + LOG_DBG(" - Checking results (after timeout)"); check_results(NUM_TEST_ITEMS); reset_results(); @@ -796,12 +801,12 @@ static void test_triggered_from_msgq_start(void) */ ZTEST(workqueue_triggered, test_triggered_from_msgq) { - TC_PRINT("Starting triggered from msgq test\n"); + LOG_DBG("Starting triggered from msgq test"); - TC_PRINT(" - Initializing kernel objects\n"); + LOG_DBG(" - Initializing kernel objects"); test_triggered_from_msgq_init(); - TC_PRINT(" - Starting the thread\n"); + LOG_DBG(" - Starting the thread"); test_triggered_from_msgq_start(); reset_results(); @@ -840,12 +845,12 @@ ZTEST(workqueue_triggered, test_triggered_cancel) { int ret; - TC_PRINT("Starting triggered test\n"); + LOG_DBG("Starting triggered test"); /* As work items are triggered, they should indicate an event. */ expected_poll_result = 0; - TC_PRINT(" - Initializing triggered test items\n"); + LOG_DBG(" - Initializing triggered test items"); test_triggered_init(); test_triggered_submit(K_FOREVER); diff --git a/tests/kernel/xip/prj.conf b/tests/kernel/xip/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/kernel/xip/prj.conf +++ b/tests/kernel/xip/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/lib/acpi/CMakeLists.txt b/tests/lib/acpi/CMakeLists.txt new file mode 100644 index 00000000000..c7b741d444a --- /dev/null +++ b/tests/lib/acpi/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(acpi) + +target_sources(app PRIVATE src/main.c) diff --git a/tests/lib/acpi/prj.conf b/tests/lib/acpi/prj.conf new file mode 100644 index 00000000000..855b08c19da --- /dev/null +++ b/tests/lib/acpi/prj.conf @@ -0,0 +1,4 @@ +CONFIG_ZTEST=y +CONFIG_ACPI=y +CONFIG_PCIE=y +CONFIG_PCIE_PRT=y diff --git a/tests/lib/acpi/src/main.c b/tests/lib/acpi/src/main.c new file mode 100644 index 00000000000..e05a7181cc1 --- /dev/null +++ b/tests/lib/acpi/src/main.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +ZTEST(acpi, test_mcfg_table) +{ + struct acpi_mcfg *mcfg; + + mcfg = acpi_table_get("MCFG", 0); + + zassert_not_null(mcfg, "Failed to get MCFG table"); +} + +ZTEST(acpi, test_irq_routing_table) +{ + static ACPI_PCI_ROUTING_TABLE irq_prt_table[CONFIG_ACPI_MAX_PRT_ENTRY]; + int status; + + status = acpi_get_irq_routing_table(CONFIG_ACPI_PRT_BUS_NAME, + irq_prt_table, ARRAY_SIZE(irq_prt_table)); + zassert_ok(status, "Failed to get PRT"); +} + +ZTEST_SUITE(acpi, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/lib/acpi/testcase.yaml b/tests/lib/acpi/testcase.yaml new file mode 100644 index 00000000000..e35f91559d2 --- /dev/null +++ b/tests/lib/acpi/testcase.yaml @@ -0,0 +1,8 @@ +tests: + acpi.basic: + tags: + - acpi + - acpica + integration_platforms: + - qemu_x86_64 + depends_on: acpi diff --git a/tests/lib/c_lib/CMakeLists.txt b/tests/lib/c_lib/CMakeLists.txt deleted file mode 100644 index 2d5c65a0329..00000000000 --- a/tests/lib/c_lib/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(c_lib) - -FILE(GLOB app_sources src/*.c) -target_sources(app PRIVATE ${app_sources}) diff --git a/tests/lib/c_lib/common/CMakeLists.txt b/tests/lib/c_lib/common/CMakeLists.txt new file mode 100644 index 00000000000..1731374ae7c --- /dev/null +++ b/tests/lib/c_lib/common/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(libc_common) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/lib/c_lib/README.txt b/tests/lib/c_lib/common/README.txt similarity index 100% rename from tests/lib/c_lib/README.txt rename to tests/lib/c_lib/common/README.txt diff --git a/tests/lib/c_lib/common/prj.conf b/tests/lib/c_lib/common/prj.conf new file mode 100644 index 00000000000..331c19559db --- /dev/null +++ b/tests/lib/c_lib/common/prj.conf @@ -0,0 +1,5 @@ +CONFIG_ZTEST=y +CONFIG_TEST_USERSPACE=y +CONFIG_ZTEST_FATAL_HOOK=y +CONFIG_MINIMAL_LIBC_NON_REENTRANT_FUNCTIONS=y +CONFIG_MINIMAL_LIBC_RAND=y diff --git a/tests/lib/c_lib/common/src/main.c b/tests/lib/c_lib/common/src/main.c new file mode 100644 index 00000000000..986dba55f8e --- /dev/null +++ b/tests/lib/c_lib/common/src/main.c @@ -0,0 +1,1263 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * @file test access to the minimal C libraries + * + * This module verifies that the various minimal C libraries can be used. + * + * IMPORTANT: The module only ensures that each supported library is present, + * and that a bare minimum of its functionality is operating correctly. It does + * NOT guarantee that ALL standards-defined functionality is present, nor does + * it guarantee that ALL functionality provided is working correctly. + */ + +#ifdef CONFIG_NEWLIB_LIBC +#define _POSIX_C_SOURCE 200809 +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_PICOLIBC +#include +#endif +#ifdef CONFIG_NEWLIB_LIBC +#include +#endif + +#define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE) +#define LIST_LEN 2 + +/* Recent GCC's are issuing a warning for the truncated strncpy() + * below (the static source string is longer than the locally-defined + * destination array). That's exactly the case we're testing, so turn + * it off. + */ +#if defined(__GNUC__) && __GNUC__ >= 8 +#pragma GCC diagnostic ignored "-Wstringop-truncation" +#endif + +ZTEST_SUITE(libc_common, NULL, NULL, NULL, NULL, NULL); + +/* + * variables used during limits library testing; must be marked as "volatile" + * to prevent compiler from computing results at compile time + */ + +volatile long long_max = LONG_MAX; +volatile long long_one = 1L; + +/** + * + * @brief Test implementation-defined constants library + * @defgroup libc_api + * @ingroup all_tests + * @{ + * + */ + +ZTEST(libc_common, test_limits) +{ + + zassert_true((long_max + long_one == LONG_MIN)); +} + +static ssize_t foobar(void) +{ + return -1; +} + +ZTEST(libc_common, test_ssize_t) +{ + zassert_true(foobar() < 0); +} + +/** + * + * @brief Test boolean types and values library + * + */ +ZTEST(libc_common, test_stdbool) +{ + + zassert_true((true == 1), "true value"); + zassert_true((false == 0), "false value"); +} + +/* + * variables used during stddef library testing; must be marked as "volatile" + * to prevent compiler from computing results at compile time + */ + +volatile long long_variable; +volatile size_t size_of_long_variable = sizeof(long_variable); + +/** + * + * @brief Test standard type definitions library + * + */ +ZTEST(libc_common, test_stddef) +{ +#ifdef CONFIG_64BIT + zassert_true((size_of_long_variable == 8), "sizeof"); +#else + zassert_true((size_of_long_variable == 4), "sizeof"); +#endif +} + +/* + * variables used during stdint library testing; must be marked as "volatile" + * to prevent compiler from computing results at compile time + */ + +volatile uint8_t unsigned_byte = 0xff; +volatile uint32_t unsigned_int = 0xffffff00; + +/** + * + * @brief Test integer types library + * + */ +ZTEST(libc_common, test_stdint) +{ + zassert_true((unsigned_int + unsigned_byte + 1u == 0U)); + +#if (UINT8_C(1) == 1) \ + && (INT8_C(-1) == -1) \ + && (UINT16_C(2) == 2) \ + && (INT16_C(-2) == -2) \ + && (UINT32_C(4) == 4) \ + && (INT32_C(-4) == -4) \ + && (UINT64_C(8) == 8) \ + && (INT64_C(-8) == -8) \ + && (UINTMAX_C(11) == 11) \ + && (INTMAX_C(-11) == -11) + zassert_true(true); +#else + zassert_true(false, "const int expr values ..."); +#endif +} + +/** + * + * @brief Test time_t to make sure it is at least 64 bits + * + */ +ZTEST(libc_common, test_time_t) +{ +#ifdef CONFIG_EXTERNAL_LIBC + ztest_test_skip(); +#else + zassert_true(sizeof(time_t) >= sizeof(uint64_t)); +#endif +} + +/* + * variables used during string library testing + */ + +#define BUFSIZE 10 + +char buffer[BUFSIZE]; + +/** + * + * @brief Test string memset + * + */ +ZTEST(libc_common, test_memset) +{ + int i, ret; + const char set = 'a'; + int size = 0; + + memset(buffer, 0, 10); + for (i = 0; i < 10; i++) { + memset(buffer + i, set, size); + memset(buffer + i, set, 1); + ret = memcmp(buffer + i, &set, 1); + zassert_true((ret == 0), "memset buffer a failed"); + } +} + +/** + * + * @brief Test string length function + * + * @see strlen(), strnlen(). + * + */ +ZTEST(libc_common, test_strlen) +{ + (void)memset(buffer, '\0', BUFSIZE); + (void)memset(buffer, 'b', 5); /* 5 is BUFSIZE / 2 */ + zassert_equal(strlen(buffer), 5, "strlen failed"); + + zassert_equal(strnlen(buffer, 3), 3, "strnlen failed"); + zassert_equal(strnlen(buffer, BUFSIZE), 5, "strnlen failed"); +} + +/** + * + * @brief Test string compare function + * + * @see strcmp(), strncasecmp(). + * + */ +ZTEST(libc_common, test_strcmp) +{ + strcpy(buffer, "eeeee"); + char test = 0; + + zassert_true((strcmp(buffer, "fffff") < 0), "strcmp less ..."); + zassert_true((strcmp(buffer, "eeeee") == 0), "strcmp equal ..."); + zassert_true((strcmp(buffer, "ddddd") > 0), "strcmp greater ..."); + + zassert_true((strncasecmp(buffer, "FFFFF", 3) < 0), "strncasecmp less ..."); + zassert_true((strncasecmp(buffer, "DDDDD", 3) > 0), "strncasecmp equal ..."); + zassert_true((strncasecmp(buffer, "EEEEE", 3) == 0), "strncasecmp greater ..."); + zassert_true((strncasecmp(&test, &test, 1) == 0), "strncasecmp failed"); +} + +/** + * + * @brief Test string N compare function + * + * @see strncmp(). + */ +ZTEST(libc_common, test_strncmp) +{ + static const char pattern[] = "eeeeeeeeeeee"; + + /* Note we don't want to count the final \0 that sizeof will */ + __ASSERT_NO_MSG(sizeof(pattern) - 1 > BUFSIZE); + memcpy(buffer, pattern, BUFSIZE); + + zassert_true((strncmp(buffer, "fffff", 0) == 0), "strncmp 0"); + zassert_true((strncmp(buffer, "eeeff", 3) == 0), "strncmp 3"); + zassert_true((strncmp(buffer, "eeeff", 4) != 0), "strncmp 4"); + zassert_true((strncmp(buffer, "eeeeeeeeeeeff", BUFSIZE) == 0), + "strncmp 10"); + + /* test compare the same strings */ + buffer[BUFSIZE - 1] = '\0'; + zassert_true((strncmp(buffer, buffer, BUFSIZE) == 0), + "strncmp 10 with \0"); +} + + +/** + * + * @brief Test string copy function + * + * @see strcpy(). + */ +ZTEST(libc_common, test_strcpy) +{ + (void)memset(buffer, '\0', BUFSIZE); + strcpy(buffer, "10 chars!\0"); + + zassert_true((strcmp(buffer, "10 chars!\0") == 0), "strcpy"); +} + +/** + * + * @brief Test string N copy function + * + * @see strncpy(). + */ +ZTEST(libc_common, test_strncpy) +{ + int ret; + + (void)memset(buffer, '\0', BUFSIZE); + strncpy(buffer, "This is over 10 characters", BUFSIZE); + + /* Purposely different values */ + ret = strncmp(buffer, "This is over 20 characters", BUFSIZE); + zassert_true((ret == 0), "strncpy"); + +} + +/** + * + * @brief Test string scanning function + * + * @see strchr(). + */ +ZTEST(libc_common, test_strchr) +{ + char *rs = NULL; + int ret; + + (void)memset(buffer, '\0', BUFSIZE); + strncpy(buffer, "Copy 10", BUFSIZE); + + rs = strchr(buffer, '1'); + + zassert_not_null(rs, "strchr"); + + + ret = strncmp(rs, "10", 2); + zassert_true((ret == 0), "strchr"); + +} + +/** + * + * @brief Test string prefix match functions + * + * @see strspn(),strcspn(). + */ +ZTEST(libc_common, test_strxspn) +{ + const char *empty = ""; + const char *cset = "abc"; + + zassert_true(strspn("", empty) == 0U, "strspn empty empty"); + zassert_true(strcspn("", empty) == 0U, "strcspn empty empty"); + + zassert_true(strspn("abde", cset) == 2U, "strspn match"); + zassert_true(strcspn("abde", cset) == 0U, "strcspn nomatch"); + + zassert_true(strspn("da", cset) == 0U, "strspn nomatch"); + zassert_true(strcspn("da", cset) == 1U, "strcspn match"); + + zassert_true(strspn("abac", cset) == 4U, "strspn all"); + zassert_true(strcspn("defg", cset) == 4U, "strcspn all"); +} + +/** + * + * @brief Test memory comparison function + * + * @see memcmp() + */ +ZTEST(libc_common, test_memcmp) +{ + int ret; + unsigned char m1[] = "a\0$def"; + unsigned char m2[] = "a\0$dhj"; + + + ret = memcmp(m1, m2, 4); + zassert_true((ret == 0), "memcmp four characters failed"); + + ret = memcmp(m1, m2, 5); + zassert_true((ret != 0), "memcmp five characters failed"); + + ret = memcmp(m1, m2, 0); + zassert_true((ret == 0), "memcmp zero character failed"); + + ret = memcmp(m1, m2, sizeof(m2)); + zassert_true((ret != 0), "memcmp 2 block of memory failed"); +} + +/** + * + * @brief Test binary search function + * + * @see bsearch() + */ +int cmp_func(const void *a, const void *b) +{ + return (*(int *)a - *(int *)b); +} + +ZTEST(libc_common, test_bsearch) +{ + void *result = NULL; + int arr[5] = { 2, 5, 20, 50, 60 }; + size_t size = ARRAY_SIZE(arr); + int key = 30; + + result = (int *)bsearch(&key, arr, size, sizeof(int), cmp_func); + zassert_is_null(result, "bsearch -key not found"); + + key = 60; + result = (int *)bsearch(&key, arr, size, sizeof(int), cmp_func); + zassert_not_null(result, "bsearch -key found"); +} + +/** + * + * @brief Test abs function + * + * @see abs() + */ +ZTEST(libc_common, test_abs) +{ + int val = -5, value = 5; + + zassert_equal(abs(val), 5, "abs -5"); + zassert_equal(abs(value), 5, "abs 5"); +} + +/** + * + * @brief Test atoi function + * + * @see atoi() + */ +ZTEST(libc_common, test_atoi) +{ + zassert_equal(atoi("123"), 123, "atoi error"); + zassert_equal(atoi("2c5"), 2, "atoi error"); + zassert_equal(atoi("acd"), 0, "atoi error"); + zassert_equal(atoi(" "), 0, "atoi error"); + zassert_equal(atoi(""), 0, "atoi error"); + zassert_equal(atoi("3-4e"), 3, "atoi error"); + zassert_equal(atoi("8+1c"), 8, "atoi error"); + zassert_equal(atoi("+3"), 3, "atoi error"); + zassert_equal(atoi("-1"), -1, "atoi error"); +} + +/** + * + * @brief Test value type + * + * @details This function check the char type, + * and verify the return value. + * + * @see isalnum(), isalpha(), isdigit(), isgraph(), + * isprint(), isspace(), isupper(), isxdigit(). + * + */ +ZTEST(libc_common, test_checktype) +{ + static const char exp_alnum[] = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + static const char exp_alpha[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + static const char exp_digit[] = "0123456789"; + static const char exp_graph[] = + "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; + static const char exp_print[] = + " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; + static const char exp_space[] = {"\x9\xa\xb\xc\xd\x20"}; + + static const char exp_upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + static const char exp_xdigit[] = "0123456789ABCDEFabcdef"; + char buf[128]; + char *ptr = buf; + + for (int i = 0; i < 128; i++) { + if (isalnum(i) != 0) { + *ptr++ = i; + } + } + *ptr = '\0'; + zassert_equal(strcmp(buf, exp_alnum), 0, "isalnum error"); + + ptr = buf; + for (int i = 0; i < 128; i++) { + if (isalpha(i) != 0) { + *ptr++ = i; + } + } + *ptr = '\0'; + zassert_equal(strcmp(buf, exp_alpha), 0, "isalpha error"); + + ptr = buf; + for (int i = 0; i < 128; i++) { + if (isdigit(i) != 0) { + *ptr++ = i; + } + } + *ptr = '\0'; + zassert_equal(strcmp(buf, exp_digit), 0, "isdigit error"); + + ptr = buf; + for (int i = 0; i < 128; i++) { + if (isgraph(i) != 0) { + *ptr++ = i; + } + } + *ptr = '\0'; + zassert_equal(strcmp(buf, exp_graph), 0, "isgraph error"); + + ptr = buf; + for (int i = 0; i < 128; i++) { + if (isprint(i) != 0) { + *ptr++ = i; + } + } + *ptr = '\0'; + zassert_equal(strcmp(buf, exp_print), 0, "isprint error"); + + ptr = buf; + for (int i = 0; i < 128; i++) { + if (isupper(i) != 0) { + *ptr++ = i; + } + } + *ptr = '\0'; + zassert_equal(strcmp(buf, exp_upper), 0, "isupper error"); + + ptr = buf; + for (int i = 0; i < 128; i++) { + if (isspace(i) != 0) { + *ptr++ = i; + } + } + *ptr = '\0'; + zassert_equal(strcmp(buf, exp_space), 0, "isspace error"); + + ptr = buf; + for (int i = 0; i < 128; i++) { + if (isxdigit(i) != 0) { + *ptr++ = i; + } + } + *ptr = '\0'; + zassert_equal(strcmp(buf, exp_xdigit), 0, "isxdigit error"); +} + +/** + * @brief Test memchr function + * + * @see memchr(). + */ +ZTEST(libc_common, test_memchr) +{ + static const char str[] = "testfunction"; + + /* verify the character inside the count scope */ + zassert_not_null(memchr(str, 'e', strlen(str)), "memchr serach e"); + zassert_not_null(memchr(str, '\0', strlen(str)+1), "memchr serach \0"); + + /* verify when the count parm is zero */ + zassert_is_null(memchr(str, 't', 0), "memchr count 0 error"); + /* verify the wanted character outside the count scope */ + zassert_is_null(memchr(str, '\0', strlen(str)), "memchr scope error"); +} + +/** + * @brief Test memcpy operation + * + * @see memcpy(). + */ +ZTEST(libc_common, test_memcpy) +{ + /* make sure the buffer is word aligned */ + uintptr_t mem_dest[4] = {0}; + uintptr_t mem_src[4] = {0}; + unsigned char *mem_dest_tmp = NULL; + unsigned char *mem_src_tmp = NULL; + + unsigned char *mem_dest_byte = (unsigned char *)mem_dest; + unsigned char *mem_src_byte = (unsigned char *)mem_src; + + /* initialize source buffer in bytes */ + for (int i = 0; i < sizeof(mem_src); i++) { + mem_src_byte[i] = i; + } + + /* verify when dest in not word aligned */ + mem_dest_tmp = mem_dest_byte + 1; + mem_src_tmp = mem_src_byte; + zassert_equal(memcpy(mem_dest_tmp, mem_src_tmp, 10), + mem_dest_tmp, "memcpy error"); + zassert_equal(memcmp(mem_dest_tmp, mem_src_tmp, 10), + 0, "memcpy failed"); + + /* restore the environment */ + memset(mem_dest_byte, '\0', sizeof(mem_dest)); + /* verify when dest and src are all in not word aligned */ + mem_dest_tmp = mem_dest_byte + sizeof(uintptr_t) - 1; + mem_src_tmp = mem_src_byte + sizeof(uintptr_t) - 1; + zassert_equal(memcpy(mem_dest_tmp, mem_src_tmp, 10), + mem_dest_tmp, "memcpy error"); + zassert_equal(memcmp(mem_dest_tmp, mem_src_tmp, 10), + 0, "memcpy failed"); + + /* restore the environment */ + memset(mem_dest_byte, '\0', sizeof(mem_dest)); + /* verify when the copy count is zero, the copy will directly return */ + mem_dest_tmp = mem_dest_byte + sizeof(uintptr_t) - 1; + mem_src_tmp = mem_src_byte + sizeof(uintptr_t) - 1; + zassert_equal(memcpy(mem_dest_tmp, mem_src_tmp, 0), + mem_dest_tmp, "memcpy error"); + zassert_not_equal(memcmp(mem_dest_tmp, mem_src_tmp, 10), + 0, "memcpy failed"); +} + +/** + * @brief Test memmove operation + * + * @see memmove(). + */ +ZTEST(libc_common, test_memmove) +{ + char move_buffer[6] = "12123"; + char move_new[6] = {0}; + static const char move_overlap[6] = "12121"; + + /* verify buffer overlaps with the start of the buffer */ + zassert_equal(memmove(move_buffer + 2, move_buffer, 3), move_buffer + 2, + "memmove error"); + zassert_equal(memcmp(move_overlap, move_buffer, sizeof(move_buffer)), 0, + "memmove failed"); + + /* verify the buffer is not overlap, then forward-copy */ + zassert_equal(memmove(move_new, move_buffer, sizeof(move_buffer)), move_new, + "memmove error"); + zassert_equal(memcmp(move_new, move_buffer, sizeof(move_buffer)), 0, + "memmove failed"); +} + +/** + * + * @brief test str operate functions + * + * @see strcat(), strcspn(), strncat(). + * + */ +ZTEST(libc_common, test_str_operate) +{ + char str1[10] = "aabbcc", ncat[10] = "ddee"; + char *str2 = "b"; + char *str3 = "d"; + int ret; + char *ptr; + + zassert_not_null(strcat(str1, str3), "strcat false"); + zassert_equal(strcmp(str1, "aabbccd"), 0, "test strcat failed"); + + ret = strcspn(str1, str2); + zassert_equal(ret, 2, "strcspn failed"); + ret = strcspn(str1, str3); + zassert_equal(ret, 6, "strcspn not found str"); + + zassert_true(strncat(ncat, str1, 2), "strncat failed"); + zassert_not_null(strncat(str1, str3, 2), "strncat failed"); +#if defined(__GNUC__) && __GNUC__ >= 7 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif + zassert_not_null(strncat(str1, str3, 1), "strncat failed"); +#if defined(__GNUC__) && __GNUC__ >= 7 +#pragma GCC diagnostic pop +#endif + zassert_equal(strcmp(ncat, "ddeeaa"), 0, "strncat failed"); + + zassert_is_null(strrchr(ncat, 'z'), + "strrchr not found this word. failed"); + ptr = strrchr(ncat, 'e'); + zassert_equal(strcmp(ptr, "eaa"), 0, "strrchr failed"); + + zassert_is_null(strstr(str1, "ayz"), "strstr aabbccd with ayz failed"); + zassert_not_null(strstr(str1, str2), "strstr aabbccd with b succeed"); + zassert_not_null(strstr(str1, "bb"), "strstr aabbccd with bb succeed"); + zassert_not_null(strstr(str1, ""), "strstr aabbccd with \0 failed"); +} + +/** + * + * @brief test strtol function + * + * @detail in 32bit system: + * when base is 10, [-2147483648..2147483647] + * in 64bit system: + * when base is 10, + * [-9,223,372,036,854,775,808..9,223,372,036,854,775,807] + * + * @see strtol(). + * + */ +ZTEST(libc_common, test_strtol) +{ + static const char buf1[] = "+10379aegi"; + static const char buf2[] = " -10379aegi"; + static const char buf3[] = "-010379aegi"; + static const char buf4[] = "0x10379aegi"; + static const char buf5[] = "0X10379aegi"; + static const char buf6[] = "01037aegi"; + static const char buf7[] = "1037aegi"; + static const char buf8[] = "++1037aegi"; + static const char buf9[] = "A1037aegi"; + static const char buf10[] = "a1037aegi"; + static const char str_normal[] = "-1011 This stopped it"; + static const char str_abnormal[] = "ABCDEFGH"; + char *stop = NULL; + long ret; + + /* test function strtol() */ + ret = strtol(buf3, NULL, 8); + zassert_equal(ret, -543, "strtol base = 8 failed"); + ret = strtol(buf1, NULL, 10); + zassert_equal(ret, 10379, "strtol base = 10 failed"); + ret = strtol(buf2, NULL, 10); + zassert_equal(ret, -10379, "strtol base = 10 failed"); + ret = strtol(buf4, NULL, 16); + zassert_equal(ret, 17004974, "strtol base = 16 failed"); + ret = strtol(buf4, NULL, 0); + zassert_equal(ret, 17004974, "strtol base = 16 failed"); + ret = strtol(buf5, NULL, 0); + zassert_equal(ret, 17004974, "strtol base = 16 failed"); + ret = strtol(buf6, NULL, 0); + zassert_equal(ret, 543, "strtol base = 8 failed"); + ret = strtol(buf7, NULL, 0); + zassert_equal(ret, 1037, "strtol base = 10 failed"); + ret = strtol(buf8, NULL, 10); + zassert_not_equal(ret, 1037, "strtol base = 10 failed"); + ret = strtol(buf9, NULL, 10); + zassert_not_equal(ret, 1037, "strtol base = 10 failed"); + ret = strtol(buf10, NULL, 10); + zassert_not_equal(ret, 1037, "strtol base = 10 failed"); + + ret = strtol(str_normal, &stop, 10); + zassert_equal(ret, -1011, "strtol base = 10 failed"); + zassert_true((strcmp(stop, " This stopped it") == 0), + "strtol get stop failed"); + + ret = strtol(str_abnormal, &stop, 0); + zassert_equal(ret, 0, "strtol base = 0 failed"); + zassert_true((strcmp(stop, "ABCDEFGH") == 0), + "strtol get stop failed"); + +#if LONG_MAX > 2147483647 + char border1[] = "-9223372036854775809"; + char border2[] = "+9223372036854775808"; + char border3[] = "+9223372036854775806"; + char border4[] = "922337203685477580000000"; + + ret = strtol(border1, NULL, 10); + zassert_equal(ret, LONG_MIN, "strtol base = 10 failed"); + ret = strtol(border2, NULL, 10); + zassert_equal(ret, LONG_MAX, "strtol base = 10 failed"); + ret = strtol(border3, NULL, 10); + zassert_equal(ret, 9223372036854775806, "strtol base = 10 failed"); + ret = strtol(border4, NULL, 10); + zassert_equal(ret, LONG_MAX, "strtol base = 10 failed"); +#else + char border1[] = "-2147483649"; + char border2[] = "+2147483648"; + char border3[] = "+2147483646"; + char border4[] = "214748364000000"; + + ret = strtol(border1, NULL, 10); + zassert_equal(ret, LONG_MIN, "strtol base = 10 failed"); + ret = strtol(border2, NULL, 10); + zassert_equal(ret, LONG_MAX, "strtol base = 10 failed"); + ret = strtol(border3, NULL, 10); + zassert_equal(ret, 2147483646, "strtol base = 10 failed"); + ret = strtol(border4, NULL, 10); + zassert_equal(ret, LONG_MAX, "strtol base = 10 failed"); +#endif +} + +/** + * + * @brief test strtoul function + * + * @see strtoul(). + * + */ +ZTEST(libc_common, test_strtoul) +{ + static const char buf1[] = "+10379aegi"; + static const char buf2[] = " -10379aegi"; + static const char buf3[] = "-010379aegi"; + static const char buf4[] = "0x10379aegi"; + static const char buf5[] = "0X10379aegi"; + static const char buf6[] = "01037aegi"; + static const char buf7[] = "1037aegi"; + static const char buf8[] = "++1037aegi"; + static const char buf9[] = "A1037aegi"; + static const char buf10[] = "a1037aegi"; + static const char str_normal[] = "-1011 This stopped it"; + static const char str_abnormal[] = "ABCDEFGH"; + char *stop = NULL; + long ret; + + /* test function strtol() */ + ret = strtoul(buf3, NULL, 8); + zassert_equal(ret, -543, "strtol base = 8 failed"); + ret = strtoul(buf1, NULL, 10); + zassert_equal(ret, 10379, "strtol base = 10 failed"); + ret = strtoul(buf2, NULL, 10); + zassert_equal(ret, -10379, "strtol base = 10 failed"); + ret = strtoul(buf4, NULL, 16); + zassert_equal(ret, 17004974, "strtol base = 16 failed"); + ret = strtoul(buf4, NULL, 0); + zassert_equal(ret, 17004974, "strtol base = 16 failed"); + ret = strtoul(buf5, NULL, 0); + zassert_equal(ret, 17004974, "strtol base = 16 failed"); + ret = strtoul(buf6, NULL, 0); + zassert_equal(ret, 543, "strtol base = 8 failed"); + ret = strtoul(buf7, NULL, 0); + zassert_equal(ret, 1037, "strtol base = 10 failed"); + ret = strtoul(buf8, NULL, 10); + zassert_not_equal(ret, 1037, "strtol base = 10 failed"); + ret = strtoul(buf9, NULL, 10); + zassert_not_equal(ret, 1037, "strtol base = 10 failed"); + ret = strtoul(buf10, NULL, 10); + zassert_not_equal(ret, 1037, "strtol base = 10 failed"); + + ret = strtoul(str_normal, &stop, 10); + zassert_equal(ret, -1011, "strtol base = 10 failed"); + zassert_true((strcmp(stop, " This stopped it") == 0), + "strtol get stop failed"); + + ret = strtoul(str_abnormal, &stop, 0); + zassert_equal(ret, 0, "strtol base = 0 failed"); + zassert_true((strcmp(stop, "ABCDEFGH") == 0), + "strtol get stop failed"); + +#if LONG_MAX > 2147483647 + char border1[] = "18446744073709551615"; + char border2[] = "-18446744073709551615000"; + char border3[] = "18446744073709551619"; + + ret = strtoul(border1, NULL, 10); + zassert_equal(ret, ULONG_MAX, "strtol base = 10 failed"); + ret = strtoul(border2, NULL, 10); + zassert_equal(ret, ULONG_MAX, "strtol base = 10 failed"); + ret = strtoul(border3, NULL, 10); + zassert_equal(ret, ULONG_MAX, "strtol base = 10 failed"); + +#else + char border1[] = "+4294967295"; + char border2[] = "-4294967295000"; + char border3[] = "+4294967299"; + + ret = strtoul(border1, NULL, 10); + zassert_equal(ret, ULONG_MAX, "strtol base = 10 failed"); + ret = strtoul(border2, NULL, 10); + zassert_equal(ret, ULONG_MAX, "strtol base = 10 failed"); + ret = strtoul(border3, NULL, 10); + zassert_equal(ret, ULONG_MAX, "strtol base = 10 failed"); +#endif +} + +/** + * + * @brief test strtoll function + * + * @see strtoll(). + * + */ +void test_strtoll(void) +{ + static const char buf1[] = "+10379aegi"; + static const char buf2[] = " -10379aegi"; + static const char buf3[] = "-010379aegi"; + static const char buf4[] = "0x10379aegi"; + static const char buf5[] = "0X10379aegi"; + static const char buf6[] = "01037aegi"; + static const char buf7[] = "1037aegi"; + static const char buf8[] = "++1037aegi"; + static const char buf9[] = "A1037aegi"; + static const char buf10[] = "a1037aegi"; + static const char str_normal[] = "-1011 This stopped it"; + static const char str_abnormal[] = "ABCDEFGH"; + char *stop = NULL; + long long ret; + + /* test function strtoll() */ + ret = strtoll(buf3, NULL, 8); + zassert_equal(ret, -543, "strtoll base = 8 failed"); + ret = strtoll(buf1, NULL, 10); + zassert_equal(ret, 10379, "strtoll base = 10 failed"); + ret = strtoll(buf2, NULL, 10); + zassert_equal(ret, -10379, "strtoll base = 10 failed"); + ret = strtoll(buf4, NULL, 16); + zassert_equal(ret, 17004974, "strtoll base = 16 failed"); + ret = strtoll(buf4, NULL, 0); + zassert_equal(ret, 17004974, "strtoll base = 16 failed"); + ret = strtoll(buf5, NULL, 0); + zassert_equal(ret, 17004974, "strtoll base = 16 failed"); + ret = strtoll(buf6, NULL, 0); + zassert_equal(ret, 543, "strtoll base = 8 failed"); + ret = strtoll(buf7, NULL, 0); + zassert_equal(ret, 1037, "strtoll base = 10 failed"); + ret = strtoll(buf8, NULL, 10); + zassert_not_equal(ret, 1037, "strtoll base = 10 failed"); + ret = strtoll(buf9, NULL, 10); + zassert_not_equal(ret, 1037, "strtoll base = 10 failed"); + ret = strtoll(buf10, NULL, 10); + zassert_not_equal(ret, 1037, "strtoll base = 10 failed"); + + ret = strtoll(str_normal, &stop, 10); + zassert_equal(ret, -1011, "strtoll base = 10 failed"); + zassert_true((strcmp(stop, " This stopped it") == 0), "strtoll get stop failed"); + + ret = strtoll(str_abnormal, &stop, 0); + zassert_equal(ret, 0, "strtoll base = 0 failed"); + zassert_true((strcmp(stop, "ABCDEFGH") == 0), "strtoll get stop failed"); + + char border1[] = "-9223372036854775808"; + char border2[] = "+9223372036854775807"; + char border3[] = "+9223372036854775806"; + char border4[] = "922337203685477580000000"; + char border5[] = "0x0000000000000000000000000000000000001"; + char border6[] = "10000000000000000000000000000000000001"; + char border7[] = "-10000000000000000000000000000000000001"; + + ret = strtoll(border1, NULL, 10); + zassert_equal(ret, LLONG_MIN, "strtoll base = 10 failed"); + ret = strtoll(border2, NULL, 10); + zassert_equal(ret, LLONG_MAX, "strtoll base = 10 failed"); + ret = strtoll(border3, NULL, 10); + zassert_equal(ret, 9223372036854775806, "strtoll base = 10 failed"); + ret = strtoll(border4, NULL, 10); + zassert_equal(ret, LLONG_MAX, "strtoll base = 10 failed"); + ret = strtoull(border5, NULL, 16); + zassert_equal(ret, 1, "strtoull base = 16 failed, %s != 0x%x", border5, ret); + ret = strtoull(border6, NULL, 10); + zassert_equal(errno, ERANGE, "strtoull base = 10 failed, %s != %lld", border6, ret); + ret = strtoull(border7, NULL, 10); + zassert_equal(errno, ERANGE, "strtoull base = 10 failed, %s != %lld", border7, ret); +} + +/** + * + * @brief test strtoull function + * + * @see strtoull(). + * + */ +void test_strtoull(void) +{ + static const char buf1[] = "+10379aegi"; + static const char buf2[] = " -10379aegi"; + static const char buf3[] = "-010379aegi"; + static const char buf4[] = "0x10379aegi"; + static const char buf5[] = "0X10379aegi"; + static const char buf6[] = "01037aegi"; + static const char buf7[] = "1037aegi"; + static const char buf8[] = "++1037aegi"; + static const char buf9[] = "A1037aegi"; + static const char buf10[] = "a1037aegi"; + static const char str_normal[] = "-1011 This stopped it"; + static const char str_abnormal[] = "ABCDEFGH"; + char *stop = NULL; + unsigned long long ret; + + /* test function strtoull() */ + ret = strtoull(buf3, NULL, 8); + zassert_equal(ret, -543, "strtoull base = 8 failed"); + ret = strtoull(buf1, NULL, 10); + zassert_equal(ret, 10379, "strtoull base = 10 failed"); + ret = strtoull(buf2, NULL, 10); + zassert_equal(ret, -10379, "strtoull base = 10 failed"); + ret = strtoull(buf4, NULL, 16); + zassert_equal(ret, 17004974, "strtoull base = 16 failed"); + ret = strtoull(buf4, NULL, 0); + zassert_equal(ret, 17004974, "strtoull base = 16 failed"); + ret = strtoull(buf5, NULL, 0); + zassert_equal(ret, 17004974, "strtoull base = 16 failed"); + ret = strtoull(buf6, NULL, 0); + zassert_equal(ret, 543, "strtoull base = 8 failed"); + ret = strtoull(buf7, NULL, 0); + zassert_equal(ret, 1037, "strtoull base = 10 failed"); + ret = strtoull(buf8, NULL, 10); + zassert_not_equal(ret, 1037, "strtoull base = 10 failed"); + ret = strtoull(buf9, NULL, 10); + zassert_not_equal(ret, 1037, "strtoull base = 10 failed"); + ret = strtoull(buf10, NULL, 10); + zassert_not_equal(ret, 1037, "strtoull base = 10 failed"); + + ret = strtoull(str_normal, &stop, 10); + zassert_equal(ret, -1011, "strtoull base = 10 failed"); + zassert_true((strcmp(stop, " This stopped it") == 0), "strtoull get stop failed"); + + ret = strtoull(str_abnormal, &stop, 0); + zassert_equal(ret, 0, "strtoull base = 0 failed"); + zassert_true((strcmp(stop, "ABCDEFGH") == 0), "strtoull get stop failed"); + + char border1[] = "+18446744073709551615"; + char border2[] = "-18446744073709551615000"; + char border3[] = "+18446744073709551619"; + char border4[] = "0x0000000000000000000000000000000000001"; + char border5[] = "10000000000000000000000000000000000001"; + char border6[] = "-10000000000000000000000000000000000001"; + + ret = strtoull(border1, NULL, 10); + zassert_equal(ret, ULLONG_MAX, "strtoull base = 10 failed"); + ret = strtoull(border2, NULL, 10); + zassert_equal(ret, ULLONG_MAX, "strtoull base = 10 failed"); + ret = strtoull(border3, NULL, 10); + zassert_equal(ret, ULLONG_MAX, "strtoull base = 10 failed"); + ret = strtoull(border4, NULL, 16); + zassert_equal(ret, 1, "strtoull base = 16 failed, %s != 0x%x", border4, ret); + ret = strtoull(border5, NULL, 10); + zassert_equal(errno, ERANGE, "strtoull base = 10 failed, %s != %lld", border5, ret); + ret = strtoull(border6, NULL, 10); + zassert_equal(errno, ERANGE, "strtoull base = 10 failed, %s != %lld", border6, ret); +} + +/** + * + * @brief test convert function + * + */ +ZTEST(libc_common, test_tolower_toupper) +{ + static const char test[] = "Az09Za{#!"; + static const char toup[] = "AZ09ZA{#!"; + static const char tolw[] = "az09za{#!"; + char up[11]; + char lw[11]; + int i = 0; + + for (; i < strlen(test); i++) { + up[i] = toupper(test[i]); + lw[i] = tolower(test[i]); + } + lw[i] = up[i] = '\0'; + + zassert_equal(strcmp(up, toup), 0, "toupper error"); + zassert_equal(strcmp(lw, tolw), 0, "tolower error"); +} + +void test_strtok_r_do(char *str, char *sep, int tlen, + const char * const *toks, bool expect) +{ + int len = 0; + char *state, *tok, buf[64+1] = {0}; + + strncpy(buf, str, 64); + + tok = strtok_r(buf, sep, &state); + while (tok && len < tlen) { + if (strcmp(tok, toks[len]) != 0) { + break; + } + tok = strtok_r(NULL, sep, &state); + len++; + } + if (expect) { + zassert_equal(len, tlen, + "strtok_r error '%s' / '%s'", str, sep); + } else { + zassert_not_equal(len, tlen, + "strtok_r error '%s' / '%s'", str, sep); + } +} + +ZTEST(libc_common, test_strtok_r) +{ + static const char * const tc01[] = { "1", "2", "3", "4", "5" }; + + test_strtok_r_do("1,2,3,4,5", ",", 5, tc01, true); + test_strtok_r_do(",, 1 ,2 ,3 4,5 ", ", ", 5, tc01, true); + test_strtok_r_do("1,,,2 3,,,4 5", ", ", 5, tc01, true); + test_strtok_r_do("1,2 3,,,4 5 ", ", ", 5, tc01, true); + test_strtok_r_do("0,1,,,2 3,,,4 5", ", ", 5, tc01, false); + test_strtok_r_do("1,,,2 3,,,4 5", ",", 5, tc01, false); + test_strtok_r_do("A,,,2,3,,,4 5", ",", 5, tc01, false); + test_strtok_r_do("1,,,2,3,,,", ",", 5, tc01, false); + test_strtok_r_do("1|2|3,4|5", "| ", 5, tc01, false); +} + +/** + * + * @brief Test time function + * + * @see gmtime(),gmtime_r(). + */ +ZTEST(libc_common, test_time) +{ + time_t tests1 = 0; + time_t tests2 = -5; + time_t tests3 = (time_t) -214748364800; + time_t tests4 = 951868800; + + struct tm tp; + + zassert_not_null(gmtime(&tests1), "gmtime failed"); + zassert_not_null(gmtime(&tests2), "gmtime failed"); + + tp.tm_wday = -5; + zassert_not_null(gmtime_r(&tests3, &tp), "gmtime_r failed"); + zassert_not_null(gmtime_r(&tests4, &tp), "gmtime_r failed"); +} + +/** + * + * @brief Test rand function + * + */ +ZTEST(libc_common, test_rand) +{ +#ifdef CONFIG_MINIMAL_LIBC + int a; + + a = rand(); + /* The default seed is 1 */ + zassert_equal(a, 1103527590, "rand failed"); +#else + ztest_test_skip(); +#endif +} + +/** + * + * @brief Test srand function + * + */ +ZTEST(libc_common, test_srand) +{ +#ifdef CONFIG_MINIMAL_LIBC + int a; + + srand(0); + a = rand(); + zassert_equal(a, 12345, "srand with seed 0 failed"); + + srand(1); + a = rand(); + zassert_equal(a, 1103527590, "srand with seed 1 failed"); + + srand(10); + a = rand(); + zassert_equal(a, 297746555, "srand with seed 10 failed"); + + srand(UINT_MAX - 1); + a = rand(); + zassert_equal(a, 2087949151, "srand with seed UINT_MAX - 1 failed"); + + srand(UINT_MAX); + a = rand(); + zassert_equal(a, 1043980748, "srand with seed UINT_MAX failed"); +#else + ztest_test_skip(); +#endif +} + +/** + * + * @brief Test rand function for reproducibility + * + */ +ZTEST(libc_common, test_rand_reproducibility) +{ +#ifdef CONFIG_MINIMAL_LIBC + int a; + int b; + int c; + + srand(0); + a = rand(); + zassert_equal(a, 12345, "srand with seed 0 failed"); + srand(0); + b = rand(); + zassert_equal(b, 12345, "srand with seed 0 failed (2nd)"); + srand(0); + c = rand(); + zassert_equal(c, 12345, "srand with seed 0 failed (3rd)"); + + srand(1); + a = rand(); + zassert_equal(a, 1103527590, "srand with seed 1 failed"); + srand(1); + b = rand(); + zassert_equal(b, 1103527590, "srand with seed 1 failed (2nd)"); + srand(1); + c = rand(); + zassert_equal(c, 1103527590, "srand with seed 1 failed (3rd)"); + + srand(10); + a = rand(); + zassert_equal(a, 297746555, "srand with seed 10 failed"); + srand(10); + b = rand(); + zassert_equal(b, 297746555, "srand with seed 10 failed (2nd)"); + srand(10); + c = rand(); + zassert_equal(c, 297746555, "srand with seed 10 failed (3rd)"); + + srand(UINT_MAX - 1); + a = rand(); + zassert_equal(a, 2087949151, "srand with seed UINT_MAX - 1 failed"); + srand(UINT_MAX - 1); + b = rand(); + zassert_equal(b, 2087949151, "srand with seed UINT_MAX - 1 failed (2nd)"); + srand(UINT_MAX - 1); + c = rand(); + zassert_equal(c, 2087949151, "srand with seed UINT_MAX - 1 failed (3rd)"); + + srand(UINT_MAX); + a = rand(); + zassert_equal(a, 1043980748, "srand with seed UINT_MAX failed"); + srand(UINT_MAX); + b = rand(); + zassert_equal(b, 1043980748, "srand with seed UINT_MAX failed (2nd)"); + srand(UINT_MAX); + c = rand(); + zassert_equal(c, 1043980748, "srand with seed UINT_MAX failed (3rd)"); +#else + ztest_test_skip(); +#endif +} + +/** + * + * @brief test abort functions + * + * @see abort(). + */ +ZTEST(libc_common, test_abort) +{ +#ifdef CONFIG_EXTERNAL_LIBC + ztest_test_skip(); +#else + int a = 0; + + ztest_set_fault_valid(true); + abort(); + zassert_equal(a, 0, "abort failed"); +#endif +} + +/** + * + * @brief test exit functions + * + */ +#ifndef CONFIG_EXTERNAL_LIBC +static void exit_program(void *p1, void *p2, void *p3) +{ + exit(1); +} + +static K_THREAD_STACK_DEFINE(tstack, STACK_SIZE); +static struct k_thread tdata; + +#endif + +ZTEST(libc_common, test_exit) +{ +#ifdef CONFIG_EXTERNAL_LIBC + ztest_test_skip(); +#else + int a = 0; + + k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, exit_program, + NULL, NULL, NULL, K_PRIO_PREEMPT(0), 0, K_NO_WAIT); + k_sleep(K_MSEC(10)); + k_thread_abort(tid); + zassert_equal(a, 0, "exit failed"); +#endif +} diff --git a/tests/lib/c_lib/src/test_qsort.c b/tests/lib/c_lib/common/src/test_qsort.c similarity index 98% rename from tests/lib/c_lib/src/test_qsort.c rename to tests/lib/c_lib/common/src/test_qsort.c index 9cfddc396c9..37db119803f 100644 --- a/tests/lib/c_lib/src/test_qsort.c +++ b/tests/lib/c_lib/common/src/test_qsort.c @@ -22,7 +22,7 @@ static int compare_ints(const void *a, const void *b) * @brief Test qsort function * */ -ZTEST(test_c_lib, test_qsort) +ZTEST(libc_common, test_qsort) { { int actual_int[] = { 1, 3, 2 }; @@ -138,7 +138,7 @@ static int compare_ints_with_boolp_arg(const void *a, const void *b, void *argp) return (aa > bb) - (aa < bb); } -ZTEST(test_c_lib, test_qsort_r) +ZTEST(libc_common, test_qsort_r) { bool arg = false; diff --git a/tests/lib/c_lib/src/test_sqrt.c b/tests/lib/c_lib/common/src/test_sqrt.c similarity index 99% rename from tests/lib/c_lib/src/test_sqrt.c rename to tests/lib/c_lib/common/src/test_sqrt.c index 99af27717af..59edad9c193 100644 --- a/tests/lib/c_lib/src/test_sqrt.c +++ b/tests/lib/c_lib/common/src/test_sqrt.c @@ -94,7 +94,7 @@ static int isnanf(float x) #define MAX_FLOAT_ERROR_PERCENT (3.5e-5) #define MAX_DOUBLE_ERROR_PERCENT (4.5e-14) -ZTEST(test_c_lib, test_sqrtf) +ZTEST(libc_common, test_sqrtf) { int i; float exponent, resf, square, root_squared; @@ -164,7 +164,7 @@ int32_t *p_root_squared = (int32_t *)&root_squared; TC_PRINT("test_sqrtf max error %d counts\n", max_error); } -ZTEST(test_c_lib, test_sqrt) +ZTEST(libc_common, test_sqrt) { int i; double resd, error, square, root_squared, exponent; diff --git a/tests/lib/c_lib/common/testcase.yaml b/tests/lib/c_lib/common/testcase.yaml new file mode 100644 index 00000000000..28a7d54194c --- /dev/null +++ b/tests/lib/c_lib/common/testcase.yaml @@ -0,0 +1,45 @@ +common: + tags: + - clib + ignore_faults: true + integration_platforms: + - mps2_an385 +tests: + libraries.libc.common: {} + libraries.libc.common.minimal: + filter: CONFIG_MINIMAL_LIBC_SUPPORTED + tags: minimal_libc + extra_configs: + - CONFIG_MINIMAL_LIBC=y + - CONFIG_MINIMAL_LIBC_NON_REENTRANT_FUNCTIONS=y + - CONFIG_MINIMAL_LIBC_RAND=y + libraries.libc.common.newlib: + filter: CONFIG_NEWLIB_LIBC_SUPPORTED + min_ram: 32 + tags: newlib + extra_configs: + - CONFIG_NEWLIB_LIBC=y + libraries.libc.common.newlib_nano: + filter: CONFIG_NEWLIB_LIBC_SUPPORTED and CONFIG_HAS_NEWLIB_LIBC_NANO + tags: newlib + extra_configs: + - CONFIG_NEWLIB_LIBC=y + - CONFIG_NEWLIB_LIBC_NANO=y + libraries.libc.common.picolibc: + filter: CONFIG_PICOLIBC_SUPPORTED + tags: picolibc + extra_configs: + - CONFIG_PICOLIBC=y + libraries.libc.common.picolibc.module: + filter: CONFIG_ZEPHYR_PICOLIBC_MODULE + tags: picolibc + extra_configs: + - CONFIG_PICOLIBC=y + - CONFIG_PICOLIBC_USE_MODULE=y + libraries.libc.common.picolibc.notls: + filter: CONFIG_ZEPHYR_PICOLIBC_MODULE + tags: picolibc + extra_configs: + - CONFIG_PICOLIBC=y + - CONFIG_PICOLIBC_USE_MODULE=y + - CONFIG_THREAD_LOCAL_STORAGE=n diff --git a/tests/lib/c_lib/prj.conf b/tests/lib/c_lib/prj.conf deleted file mode 100644 index d21e1ad31fb..00000000000 --- a/tests/lib/c_lib/prj.conf +++ /dev/null @@ -1,6 +0,0 @@ -CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y -CONFIG_TEST_USERSPACE=y -CONFIG_ZTEST_FATAL_HOOK=y -CONFIG_MINIMAL_LIBC_NON_REENTRANT_FUNCTIONS=y -CONFIG_MINIMAL_LIBC_RAND=y diff --git a/tests/lib/c_lib/src/main.c b/tests/lib/c_lib/src/main.c deleted file mode 100644 index 6b3e96cbf99..00000000000 --- a/tests/lib/c_lib/src/main.c +++ /dev/null @@ -1,1238 +0,0 @@ -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/* - * @file test access to the minimal C libraries - * - * This module verifies that the various minimal C libraries can be used. - * - * IMPORTANT: The module only ensures that each supported library is present, - * and that a bare minimum of its functionality is operating correctly. It does - * NOT guarantee that ALL standards-defined functionality is present, nor does - * it guarantee that ALL functionality provided is working correctly. - */ - -#ifdef CONFIG_NEWLIB_LIBC -#define _POSIX_C_SOURCE 200809 -#endif - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_PICOLIBC -#include -#endif -#ifdef CONFIG_NEWLIB_LIBC -#include -#endif - -#define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE) -#define LIST_LEN 2 - -static K_THREAD_STACK_DEFINE(tstack, STACK_SIZE); -static struct k_thread tdata; - -/* Recent GCC's are issuing a warning for the truncated strncpy() - * below (the static source string is longer than the locally-defined - * destination array). That's exactly the case we're testing, so turn - * it off. - */ -#if defined(__GNUC__) && __GNUC__ >= 8 -#pragma GCC diagnostic ignored "-Wstringop-truncation" -#endif - -ZTEST_SUITE(test_c_lib, NULL, NULL, NULL, NULL, NULL); - -/* - * variables used during limits library testing; must be marked as "volatile" - * to prevent compiler from computing results at compile time - */ - -volatile long long_max = LONG_MAX; -volatile long long_one = 1L; - -/** - * - * @brief Test implementation-defined constants library - * @defgroup libc_api - * @ingroup all_tests - * @{ - * - */ - -ZTEST(test_c_lib, test_limits) -{ - - zassert_true((long_max + long_one == LONG_MIN)); -} - -static ssize_t foobar(void) -{ - return -1; -} - -ZTEST(test_c_lib, test_ssize_t) -{ - zassert_true(foobar() < 0); -} - -/** - * - * @brief Test boolean types and values library - * - */ -ZTEST(test_c_lib, test_stdbool) -{ - - zassert_true((true == 1), "true value"); - zassert_true((false == 0), "false value"); -} - -/* - * variables used during stddef library testing; must be marked as "volatile" - * to prevent compiler from computing results at compile time - */ - -volatile long long_variable; -volatile size_t size_of_long_variable = sizeof(long_variable); - -/** - * - * @brief Test standard type definitions library - * - */ -ZTEST(test_c_lib, test_stddef) -{ -#ifdef CONFIG_64BIT - zassert_true((size_of_long_variable == 8), "sizeof"); -#else - zassert_true((size_of_long_variable == 4), "sizeof"); -#endif -} - -/* - * variables used during stdint library testing; must be marked as "volatile" - * to prevent compiler from computing results at compile time - */ - -volatile uint8_t unsigned_byte = 0xff; -volatile uint32_t unsigned_int = 0xffffff00; - -/** - * - * @brief Test integer types library - * - */ -ZTEST(test_c_lib, test_stdint) -{ - zassert_true((unsigned_int + unsigned_byte + 1u == 0U)); - -#if (UINT8_C(1) == 1) \ - && (INT8_C(-1) == -1) \ - && (UINT16_C(2) == 2) \ - && (INT16_C(-2) == -2) \ - && (UINT32_C(4) == 4) \ - && (INT32_C(-4) == -4) \ - && (UINT64_C(8) == 8) \ - && (INT64_C(-8) == -8) \ - && (UINTMAX_C(11) == 11) \ - && (INTMAX_C(-11) == -11) - zassert_true(true); -#else - zassert_true(false, "const int expr values ..."); -#endif -} - -/* - * variables used during string library testing - */ - -#define BUFSIZE 10 - -char buffer[BUFSIZE]; - -/** - * - * @brief Test string memset - * - */ -ZTEST(test_c_lib, test_memset) -{ - int i, ret; - const char set = 'a'; - int size = 0; - - memset(buffer, 0, 10); - for (i = 0; i < 10; i++) { - memset(buffer + i, set, size); - memset(buffer + i, set, 1); - ret = memcmp(buffer + i, &set, 1); - zassert_true((ret == 0), "memset buffer a failed"); - } -} - -/** - * - * @brief Test string length function - * - * @see strlen(), strnlen(). - * - */ -ZTEST(test_c_lib, test_strlen) -{ - (void)memset(buffer, '\0', BUFSIZE); - (void)memset(buffer, 'b', 5); /* 5 is BUFSIZE / 2 */ - zassert_equal(strlen(buffer), 5, "strlen failed"); - - zassert_equal(strnlen(buffer, 3), 3, "strnlen failed"); - zassert_equal(strnlen(buffer, BUFSIZE), 5, "strnlen failed"); -} - -/** - * - * @brief Test string compare function - * - * @see strcmp(), strncasecmp(). - * - */ -ZTEST(test_c_lib, test_strcmp) -{ - strcpy(buffer, "eeeee"); - char test = 0; - - zassert_true((strcmp(buffer, "fffff") < 0), "strcmp less ..."); - zassert_true((strcmp(buffer, "eeeee") == 0), "strcmp equal ..."); - zassert_true((strcmp(buffer, "ddddd") > 0), "strcmp greater ..."); - - zassert_true((strncasecmp(buffer, "FFFFF", 3) < 0), "strncasecmp less ..."); - zassert_true((strncasecmp(buffer, "DDDDD", 3) > 0), "strncasecmp equal ..."); - zassert_true((strncasecmp(buffer, "EEEEE", 3) == 0), "strncasecmp greater ..."); - zassert_true((strncasecmp(&test, &test, 1) == 0), "strncasecmp failed"); -} - -/** - * - * @brief Test string N compare function - * - * @see strncmp(). - */ -ZTEST(test_c_lib, test_strncmp) -{ - static const char pattern[] = "eeeeeeeeeeee"; - - /* Note we don't want to count the final \0 that sizeof will */ - __ASSERT_NO_MSG(sizeof(pattern) - 1 > BUFSIZE); - memcpy(buffer, pattern, BUFSIZE); - - zassert_true((strncmp(buffer, "fffff", 0) == 0), "strncmp 0"); - zassert_true((strncmp(buffer, "eeeff", 3) == 0), "strncmp 3"); - zassert_true((strncmp(buffer, "eeeff", 4) != 0), "strncmp 4"); - zassert_true((strncmp(buffer, "eeeeeeeeeeeff", BUFSIZE) == 0), - "strncmp 10"); - - /* test compare the same strings */ - buffer[BUFSIZE - 1] = '\0'; - zassert_true((strncmp(buffer, buffer, BUFSIZE) == 0), - "strncmp 10 with \0"); -} - - -/** - * - * @brief Test string copy function - * - * @see strcpy(). - */ -ZTEST(test_c_lib, test_strcpy) -{ - (void)memset(buffer, '\0', BUFSIZE); - strcpy(buffer, "10 chars!\0"); - - zassert_true((strcmp(buffer, "10 chars!\0") == 0), "strcpy"); -} - -/** - * - * @brief Test string N copy function - * - * @see strncpy(). - */ -ZTEST(test_c_lib, test_strncpy) -{ - int ret; - - (void)memset(buffer, '\0', BUFSIZE); - strncpy(buffer, "This is over 10 characters", BUFSIZE); - - /* Purposely different values */ - ret = strncmp(buffer, "This is over 20 characters", BUFSIZE); - zassert_true((ret == 0), "strncpy"); - -} - -/** - * - * @brief Test string scanning function - * - * @see strchr(). - */ -ZTEST(test_c_lib, test_strchr) -{ - char *rs = NULL; - int ret; - - (void)memset(buffer, '\0', BUFSIZE); - strncpy(buffer, "Copy 10", BUFSIZE); - - rs = strchr(buffer, '1'); - - zassert_not_null(rs, "strchr"); - - - ret = strncmp(rs, "10", 2); - zassert_true((ret == 0), "strchr"); - -} - -/** - * - * @brief Test string prefix match functions - * - * @see strspn(),strcspn(). - */ -ZTEST(test_c_lib, test_strxspn) -{ - const char *empty = ""; - const char *cset = "abc"; - - zassert_true(strspn("", empty) == 0U, "strspn empty empty"); - zassert_true(strcspn("", empty) == 0U, "strcspn empty empty"); - - zassert_true(strspn("abde", cset) == 2U, "strspn match"); - zassert_true(strcspn("abde", cset) == 0U, "strcspn nomatch"); - - zassert_true(strspn("da", cset) == 0U, "strspn nomatch"); - zassert_true(strcspn("da", cset) == 1U, "strcspn match"); - - zassert_true(strspn("abac", cset) == 4U, "strspn all"); - zassert_true(strcspn("defg", cset) == 4U, "strcspn all"); -} - -/** - * - * @brief Test memory comparison function - * - * @see memcmp() - */ -ZTEST(test_c_lib, test_memcmp) -{ - int ret; - unsigned char m1[] = "a\0$def"; - unsigned char m2[] = "a\0$dhj"; - - - ret = memcmp(m1, m2, 4); - zassert_true((ret == 0), "memcmp four characters failed"); - - ret = memcmp(m1, m2, 5); - zassert_true((ret != 0), "memcmp five characters failed"); - - ret = memcmp(m1, m2, 0); - zassert_true((ret == 0), "memcmp zero character failed"); - - ret = memcmp(m1, m2, sizeof(m2)); - zassert_true((ret != 0), "memcmp 2 block of memory failed"); -} - -/** - * - * @brief Test binary search function - * - * @see bsearch() - */ -int cmp_func(const void *a, const void *b) -{ - return (*(int *)a - *(int *)b); -} - -ZTEST(test_c_lib, test_bsearch) -{ - void *result = NULL; - int arr[5] = { 2, 5, 20, 50, 60 }; - size_t size = ARRAY_SIZE(arr); - int key = 30; - - result = (int *)bsearch(&key, arr, size, sizeof(int), cmp_func); - zassert_is_null(result, "bsearch -key not found"); - - key = 60; - result = (int *)bsearch(&key, arr, size, sizeof(int), cmp_func); - zassert_not_null(result, "bsearch -key found"); -} - -/** - * - * @brief Test abs function - * - * @see abs() - */ -ZTEST(test_c_lib, test_abs) -{ - int val = -5, value = 5; - - zassert_equal(abs(val), 5, "abs -5"); - zassert_equal(abs(value), 5, "abs 5"); -} - -/** - * - * @brief Test atoi function - * - * @see atoi() - */ -ZTEST(test_c_lib, test_atoi) -{ - zassert_equal(atoi("123"), 123, "atoi error"); - zassert_equal(atoi("2c5"), 2, "atoi error"); - zassert_equal(atoi("acd"), 0, "atoi error"); - zassert_equal(atoi(" "), 0, "atoi error"); - zassert_equal(atoi(""), 0, "atoi error"); - zassert_equal(atoi("3-4e"), 3, "atoi error"); - zassert_equal(atoi("8+1c"), 8, "atoi error"); - zassert_equal(atoi("+3"), 3, "atoi error"); - zassert_equal(atoi("-1"), -1, "atoi error"); -} - -/** - * - * @brief Test value type - * - * @details This function check the char type, - * and verify the return value. - * - * @see isalnum(), isalpha(), isdigit(), isgraph(), - * isprint(), isspace(), isupper(), isxdigit(). - * - */ -ZTEST(test_c_lib, test_checktype) -{ - static const char exp_alnum[] = - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - static const char exp_alpha[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - static const char exp_digit[] = "0123456789"; - static const char exp_graph[] = - "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; - static const char exp_print[] = - " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; - static const char exp_space[] = {"\x9\xa\xb\xc\xd\x20"}; - - static const char exp_upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - static const char exp_xdigit[] = "0123456789ABCDEFabcdef"; - char buf[128]; - char *ptr = buf; - - for (int i = 0; i < 128; i++) { - if (isalnum(i) != 0) { - *ptr++ = i; - } - } - *ptr = '\0'; - zassert_equal(strcmp(buf, exp_alnum), 0, "isalnum error"); - - ptr = buf; - for (int i = 0; i < 128; i++) { - if (isalpha(i) != 0) { - *ptr++ = i; - } - } - *ptr = '\0'; - zassert_equal(strcmp(buf, exp_alpha), 0, "isalpha error"); - - ptr = buf; - for (int i = 0; i < 128; i++) { - if (isdigit(i) != 0) { - *ptr++ = i; - } - } - *ptr = '\0'; - zassert_equal(strcmp(buf, exp_digit), 0, "isdigit error"); - - ptr = buf; - for (int i = 0; i < 128; i++) { - if (isgraph(i) != 0) { - *ptr++ = i; - } - } - *ptr = '\0'; - zassert_equal(strcmp(buf, exp_graph), 0, "isgraph error"); - - ptr = buf; - for (int i = 0; i < 128; i++) { - if (isprint(i) != 0) { - *ptr++ = i; - } - } - *ptr = '\0'; - zassert_equal(strcmp(buf, exp_print), 0, "isprint error"); - - ptr = buf; - for (int i = 0; i < 128; i++) { - if (isupper(i) != 0) { - *ptr++ = i; - } - } - *ptr = '\0'; - zassert_equal(strcmp(buf, exp_upper), 0, "isupper error"); - - ptr = buf; - for (int i = 0; i < 128; i++) { - if (isspace(i) != 0) { - *ptr++ = i; - } - } - *ptr = '\0'; - zassert_equal(strcmp(buf, exp_space), 0, "isspace error"); - - ptr = buf; - for (int i = 0; i < 128; i++) { - if (isxdigit(i) != 0) { - *ptr++ = i; - } - } - *ptr = '\0'; - zassert_equal(strcmp(buf, exp_xdigit), 0, "isxdigit error"); -} - -/** - * @brief Test memchr function - * - * @see memchr(). - */ -ZTEST(test_c_lib, test_memchr) -{ - static const char str[] = "testfunction"; - - /* verify the character inside the count scope */ - zassert_not_null(memchr(str, 'e', strlen(str)), "memchr serach e"); - zassert_not_null(memchr(str, '\0', strlen(str)+1), "memchr serach \0"); - - /* verify when the count parm is zero */ - zassert_is_null(memchr(str, 't', 0), "memchr count 0 error"); - /* verify the wanted character outside the count scope */ - zassert_is_null(memchr(str, '\0', strlen(str)), "memchr scope error"); -} - -/** - * @brief Test memcpy operation - * - * @see memcpy(). - */ -ZTEST(test_c_lib, test_memcpy) -{ - /* make sure the buffer is word aligned */ - uintptr_t mem_dest[4] = {0}; - uintptr_t mem_src[4] = {0}; - unsigned char *mem_dest_tmp = NULL; - unsigned char *mem_src_tmp = NULL; - - unsigned char *mem_dest_byte = (unsigned char *)mem_dest; - unsigned char *mem_src_byte = (unsigned char *)mem_src; - - /* initialize source buffer in bytes */ - for (int i = 0; i < sizeof(mem_src); i++) { - mem_src_byte[i] = i; - } - - /* verify when dest in not word aligned */ - mem_dest_tmp = mem_dest_byte + 1; - mem_src_tmp = mem_src_byte; - zassert_equal(memcpy(mem_dest_tmp, mem_src_tmp, 10), - mem_dest_tmp, "memcpy error"); - zassert_equal(memcmp(mem_dest_tmp, mem_src_tmp, 10), - 0, "memcpy failed"); - - /* restore the environment */ - memset(mem_dest_byte, '\0', sizeof(mem_dest)); - /* verify when dest and src are all in not word aligned */ - mem_dest_tmp = mem_dest_byte + sizeof(uintptr_t) - 1; - mem_src_tmp = mem_src_byte + sizeof(uintptr_t) - 1; - zassert_equal(memcpy(mem_dest_tmp, mem_src_tmp, 10), - mem_dest_tmp, "memcpy error"); - zassert_equal(memcmp(mem_dest_tmp, mem_src_tmp, 10), - 0, "memcpy failed"); - - /* restore the environment */ - memset(mem_dest_byte, '\0', sizeof(mem_dest)); - /* verify when the copy count is zero, the copy will directly return */ - mem_dest_tmp = mem_dest_byte + sizeof(uintptr_t) - 1; - mem_src_tmp = mem_src_byte + sizeof(uintptr_t) - 1; - zassert_equal(memcpy(mem_dest_tmp, mem_src_tmp, 0), - mem_dest_tmp, "memcpy error"); - zassert_not_equal(memcmp(mem_dest_tmp, mem_src_tmp, 10), - 0, "memcpy failed"); -} - -/** - * @brief Test memmove operation - * - * @see memmove(). - */ -ZTEST(test_c_lib, test_memmove) -{ - char move_buffer[6] = "12123"; - char move_new[6] = {0}; - static const char move_overlap[6] = "12121"; - - /* verify buffer overlaps with the start of the buffer */ - zassert_equal(memmove(move_buffer + 2, move_buffer, 3), move_buffer + 2, - "memmove error"); - zassert_equal(memcmp(move_overlap, move_buffer, sizeof(move_buffer)), 0, - "memmove failed"); - - /* verify the buffer is not overlap, then forward-copy */ - zassert_equal(memmove(move_new, move_buffer, sizeof(move_buffer)), move_new, - "memmove error"); - zassert_equal(memcmp(move_new, move_buffer, sizeof(move_buffer)), 0, - "memmove failed"); -} - -/** - * - * @brief test str operate functions - * - * @see strcat(), strcspn(), strncat(). - * - */ -ZTEST(test_c_lib, test_str_operate) -{ - char str1[10] = "aabbcc", ncat[10] = "ddee"; - char *str2 = "b"; - char *str3 = "d"; - int ret; - char *ptr; - - zassert_not_null(strcat(str1, str3), "strcat false"); - zassert_equal(strcmp(str1, "aabbccd"), 0, "test strcat failed"); - - ret = strcspn(str1, str2); - zassert_equal(ret, 2, "strcspn failed"); - ret = strcspn(str1, str3); - zassert_equal(ret, 6, "strcspn not found str"); - - zassert_true(strncat(ncat, str1, 2), "strncat failed"); - zassert_not_null(strncat(str1, str3, 2), "strncat failed"); -#if defined(__GNUC__) && __GNUC__ >= 7 -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstringop-overflow" -#endif - zassert_not_null(strncat(str1, str3, 1), "strncat failed"); -#if defined(__GNUC__) && __GNUC__ >= 7 -#pragma GCC diagnostic pop -#endif - zassert_equal(strcmp(ncat, "ddeeaa"), 0, "strncat failed"); - - zassert_is_null(strrchr(ncat, 'z'), - "strrchr not found this word. failed"); - ptr = strrchr(ncat, 'e'); - zassert_equal(strcmp(ptr, "eaa"), 0, "strrchr failed"); - - zassert_is_null(strstr(str1, "ayz"), "strstr aabbccd with ayz failed"); - zassert_not_null(strstr(str1, str2), "strstr aabbccd with b succeed"); - zassert_not_null(strstr(str1, "bb"), "strstr aabbccd with bb succeed"); - zassert_not_null(strstr(str1, ""), "strstr aabbccd with \0 failed"); -} - -/** - * - * @brief test strtol function - * - * @detail in 32bit system: - * when base is 10, [-2147483648..2147483647] - * in 64bit system: - * when base is 10, - * [-9,223,372,036,854,775,808..9,223,372,036,854,775,807] - * - * @see strtol(). - * - */ -ZTEST(test_c_lib, test_strtol) -{ - static const char buf1[] = "+10379aegi"; - static const char buf2[] = " -10379aegi"; - static const char buf3[] = "-010379aegi"; - static const char buf4[] = "0x10379aegi"; - static const char buf5[] = "0X10379aegi"; - static const char buf6[] = "01037aegi"; - static const char buf7[] = "1037aegi"; - static const char buf8[] = "++1037aegi"; - static const char buf9[] = "A1037aegi"; - static const char buf10[] = "a1037aegi"; - static const char str_normal[] = "-1011 This stopped it"; - static const char str_abnormal[] = "ABCDEFGH"; - char *stop = NULL; - long ret; - - /* test function strtol() */ - ret = strtol(buf3, NULL, 8); - zassert_equal(ret, -543, "strtol base = 8 failed"); - ret = strtol(buf1, NULL, 10); - zassert_equal(ret, 10379, "strtol base = 10 failed"); - ret = strtol(buf2, NULL, 10); - zassert_equal(ret, -10379, "strtol base = 10 failed"); - ret = strtol(buf4, NULL, 16); - zassert_equal(ret, 17004974, "strtol base = 16 failed"); - ret = strtol(buf4, NULL, 0); - zassert_equal(ret, 17004974, "strtol base = 16 failed"); - ret = strtol(buf5, NULL, 0); - zassert_equal(ret, 17004974, "strtol base = 16 failed"); - ret = strtol(buf6, NULL, 0); - zassert_equal(ret, 543, "strtol base = 8 failed"); - ret = strtol(buf7, NULL, 0); - zassert_equal(ret, 1037, "strtol base = 10 failed"); - ret = strtol(buf8, NULL, 10); - zassert_not_equal(ret, 1037, "strtol base = 10 failed"); - ret = strtol(buf9, NULL, 10); - zassert_not_equal(ret, 1037, "strtol base = 10 failed"); - ret = strtol(buf10, NULL, 10); - zassert_not_equal(ret, 1037, "strtol base = 10 failed"); - - ret = strtol(str_normal, &stop, 10); - zassert_equal(ret, -1011, "strtol base = 10 failed"); - zassert_true((strcmp(stop, " This stopped it") == 0), - "strtol get stop failed"); - - ret = strtol(str_abnormal, &stop, 0); - zassert_equal(ret, 0, "strtol base = 0 failed"); - zassert_true((strcmp(stop, "ABCDEFGH") == 0), - "strtol get stop failed"); - -#if LONG_MAX > 2147483647 - char border1[] = "-9223372036854775809"; - char border2[] = "+9223372036854775808"; - char border3[] = "+9223372036854775806"; - char border4[] = "922337203685477580000000"; - - ret = strtol(border1, NULL, 10); - zassert_equal(ret, LONG_MIN, "strtol base = 10 failed"); - ret = strtol(border2, NULL, 10); - zassert_equal(ret, LONG_MAX, "strtol base = 10 failed"); - ret = strtol(border3, NULL, 10); - zassert_equal(ret, 9223372036854775806, "strtol base = 10 failed"); - ret = strtol(border4, NULL, 10); - zassert_equal(ret, LONG_MAX, "strtol base = 10 failed"); -#else - char border1[] = "-2147483649"; - char border2[] = "+2147483648"; - char border3[] = "+2147483646"; - char border4[] = "214748364000000"; - - ret = strtol(border1, NULL, 10); - zassert_equal(ret, LONG_MIN, "strtol base = 10 failed"); - ret = strtol(border2, NULL, 10); - zassert_equal(ret, LONG_MAX, "strtol base = 10 failed"); - ret = strtol(border3, NULL, 10); - zassert_equal(ret, 2147483646, "strtol base = 10 failed"); - ret = strtol(border4, NULL, 10); - zassert_equal(ret, LONG_MAX, "strtol base = 10 failed"); -#endif -} - -/** - * - * @brief test strtoul function - * - * @see strtoul(). - * - */ -ZTEST(test_c_lib, test_strtoul) -{ - static const char buf1[] = "+10379aegi"; - static const char buf2[] = " -10379aegi"; - static const char buf3[] = "-010379aegi"; - static const char buf4[] = "0x10379aegi"; - static const char buf5[] = "0X10379aegi"; - static const char buf6[] = "01037aegi"; - static const char buf7[] = "1037aegi"; - static const char buf8[] = "++1037aegi"; - static const char buf9[] = "A1037aegi"; - static const char buf10[] = "a1037aegi"; - static const char str_normal[] = "-1011 This stopped it"; - static const char str_abnormal[] = "ABCDEFGH"; - char *stop = NULL; - long ret; - - /* test function strtol() */ - ret = strtoul(buf3, NULL, 8); - zassert_equal(ret, -543, "strtol base = 8 failed"); - ret = strtoul(buf1, NULL, 10); - zassert_equal(ret, 10379, "strtol base = 10 failed"); - ret = strtoul(buf2, NULL, 10); - zassert_equal(ret, -10379, "strtol base = 10 failed"); - ret = strtoul(buf4, NULL, 16); - zassert_equal(ret, 17004974, "strtol base = 16 failed"); - ret = strtoul(buf4, NULL, 0); - zassert_equal(ret, 17004974, "strtol base = 16 failed"); - ret = strtoul(buf5, NULL, 0); - zassert_equal(ret, 17004974, "strtol base = 16 failed"); - ret = strtoul(buf6, NULL, 0); - zassert_equal(ret, 543, "strtol base = 8 failed"); - ret = strtoul(buf7, NULL, 0); - zassert_equal(ret, 1037, "strtol base = 10 failed"); - ret = strtoul(buf8, NULL, 10); - zassert_not_equal(ret, 1037, "strtol base = 10 failed"); - ret = strtoul(buf9, NULL, 10); - zassert_not_equal(ret, 1037, "strtol base = 10 failed"); - ret = strtoul(buf10, NULL, 10); - zassert_not_equal(ret, 1037, "strtol base = 10 failed"); - - ret = strtoul(str_normal, &stop, 10); - zassert_equal(ret, -1011, "strtol base = 10 failed"); - zassert_true((strcmp(stop, " This stopped it") == 0), - "strtol get stop failed"); - - ret = strtoul(str_abnormal, &stop, 0); - zassert_equal(ret, 0, "strtol base = 0 failed"); - zassert_true((strcmp(stop, "ABCDEFGH") == 0), - "strtol get stop failed"); - -#if LONG_MAX > 2147483647 - char border1[] = "18446744073709551615"; - char border2[] = "-18446744073709551615000"; - char border3[] = "18446744073709551619"; - - ret = strtoul(border1, NULL, 10); - zassert_equal(ret, ULONG_MAX, "strtol base = 10 failed"); - ret = strtoul(border2, NULL, 10); - zassert_equal(ret, ULONG_MAX, "strtol base = 10 failed"); - ret = strtoul(border3, NULL, 10); - zassert_equal(ret, ULONG_MAX, "strtol base = 10 failed"); - -#else - char border1[] = "+4294967295"; - char border2[] = "-4294967295000"; - char border3[] = "+4294967299"; - - ret = strtoul(border1, NULL, 10); - zassert_equal(ret, ULONG_MAX, "strtol base = 10 failed"); - ret = strtoul(border2, NULL, 10); - zassert_equal(ret, ULONG_MAX, "strtol base = 10 failed"); - ret = strtoul(border3, NULL, 10); - zassert_equal(ret, ULONG_MAX, "strtol base = 10 failed"); -#endif -} - -/** - * - * @brief test strtoll function - * - * @see strtoll(). - * - */ -void test_strtoll(void) -{ - static const char buf1[] = "+10379aegi"; - static const char buf2[] = " -10379aegi"; - static const char buf3[] = "-010379aegi"; - static const char buf4[] = "0x10379aegi"; - static const char buf5[] = "0X10379aegi"; - static const char buf6[] = "01037aegi"; - static const char buf7[] = "1037aegi"; - static const char buf8[] = "++1037aegi"; - static const char buf9[] = "A1037aegi"; - static const char buf10[] = "a1037aegi"; - static const char str_normal[] = "-1011 This stopped it"; - static const char str_abnormal[] = "ABCDEFGH"; - char *stop = NULL; - long long ret; - - /* test function strtoll() */ - ret = strtoll(buf3, NULL, 8); - zassert_equal(ret, -543, "strtoll base = 8 failed"); - ret = strtoll(buf1, NULL, 10); - zassert_equal(ret, 10379, "strtoll base = 10 failed"); - ret = strtoll(buf2, NULL, 10); - zassert_equal(ret, -10379, "strtoll base = 10 failed"); - ret = strtoll(buf4, NULL, 16); - zassert_equal(ret, 17004974, "strtoll base = 16 failed"); - ret = strtoll(buf4, NULL, 0); - zassert_equal(ret, 17004974, "strtoll base = 16 failed"); - ret = strtoll(buf5, NULL, 0); - zassert_equal(ret, 17004974, "strtoll base = 16 failed"); - ret = strtoll(buf6, NULL, 0); - zassert_equal(ret, 543, "strtoll base = 8 failed"); - ret = strtoll(buf7, NULL, 0); - zassert_equal(ret, 1037, "strtoll base = 10 failed"); - ret = strtoll(buf8, NULL, 10); - zassert_not_equal(ret, 1037, "strtoll base = 10 failed"); - ret = strtoll(buf9, NULL, 10); - zassert_not_equal(ret, 1037, "strtoll base = 10 failed"); - ret = strtoll(buf10, NULL, 10); - zassert_not_equal(ret, 1037, "strtoll base = 10 failed"); - - ret = strtoll(str_normal, &stop, 10); - zassert_equal(ret, -1011, "strtoll base = 10 failed"); - zassert_true((strcmp(stop, " This stopped it") == 0), "strtoll get stop failed"); - - ret = strtoll(str_abnormal, &stop, 0); - zassert_equal(ret, 0, "strtoll base = 0 failed"); - zassert_true((strcmp(stop, "ABCDEFGH") == 0), "strtoll get stop failed"); - - char border1[] = "-9223372036854775808"; - char border2[] = "+9223372036854775807"; - char border3[] = "+9223372036854775806"; - char border4[] = "922337203685477580000000"; - char border5[] = "0x0000000000000000000000000000000000001"; - char border6[] = "10000000000000000000000000000000000001"; - char border7[] = "-10000000000000000000000000000000000001"; - - ret = strtoll(border1, NULL, 10); - zassert_equal(ret, LLONG_MIN, "strtoll base = 10 failed"); - ret = strtoll(border2, NULL, 10); - zassert_equal(ret, LLONG_MAX, "strtoll base = 10 failed"); - ret = strtoll(border3, NULL, 10); - zassert_equal(ret, 9223372036854775806, "strtoll base = 10 failed"); - ret = strtoll(border4, NULL, 10); - zassert_equal(ret, LLONG_MAX, "strtoll base = 10 failed"); - ret = strtoull(border5, NULL, 16); - zassert_equal(ret, 1, "strtoull base = 16 failed, %s != 0x%x", border5, ret); - ret = strtoull(border6, NULL, 10); - zassert_equal(errno, ERANGE, "strtoull base = 10 failed, %s != %lld", border6, ret); - ret = strtoull(border7, NULL, 10); - zassert_equal(errno, ERANGE, "strtoull base = 10 failed, %s != %lld", border7, ret); -} - -/** - * - * @brief test strtoull function - * - * @see strtoull(). - * - */ -void test_strtoull(void) -{ - static const char buf1[] = "+10379aegi"; - static const char buf2[] = " -10379aegi"; - static const char buf3[] = "-010379aegi"; - static const char buf4[] = "0x10379aegi"; - static const char buf5[] = "0X10379aegi"; - static const char buf6[] = "01037aegi"; - static const char buf7[] = "1037aegi"; - static const char buf8[] = "++1037aegi"; - static const char buf9[] = "A1037aegi"; - static const char buf10[] = "a1037aegi"; - static const char str_normal[] = "-1011 This stopped it"; - static const char str_abnormal[] = "ABCDEFGH"; - char *stop = NULL; - unsigned long long ret; - - /* test function strtoull() */ - ret = strtoull(buf3, NULL, 8); - zassert_equal(ret, -543, "strtoull base = 8 failed"); - ret = strtoull(buf1, NULL, 10); - zassert_equal(ret, 10379, "strtoull base = 10 failed"); - ret = strtoull(buf2, NULL, 10); - zassert_equal(ret, -10379, "strtoull base = 10 failed"); - ret = strtoull(buf4, NULL, 16); - zassert_equal(ret, 17004974, "strtoull base = 16 failed"); - ret = strtoull(buf4, NULL, 0); - zassert_equal(ret, 17004974, "strtoull base = 16 failed"); - ret = strtoull(buf5, NULL, 0); - zassert_equal(ret, 17004974, "strtoull base = 16 failed"); - ret = strtoull(buf6, NULL, 0); - zassert_equal(ret, 543, "strtoull base = 8 failed"); - ret = strtoull(buf7, NULL, 0); - zassert_equal(ret, 1037, "strtoull base = 10 failed"); - ret = strtoull(buf8, NULL, 10); - zassert_not_equal(ret, 1037, "strtoull base = 10 failed"); - ret = strtoull(buf9, NULL, 10); - zassert_not_equal(ret, 1037, "strtoull base = 10 failed"); - ret = strtoull(buf10, NULL, 10); - zassert_not_equal(ret, 1037, "strtoull base = 10 failed"); - - ret = strtoull(str_normal, &stop, 10); - zassert_equal(ret, -1011, "strtoull base = 10 failed"); - zassert_true((strcmp(stop, " This stopped it") == 0), "strtoull get stop failed"); - - ret = strtoull(str_abnormal, &stop, 0); - zassert_equal(ret, 0, "strtoull base = 0 failed"); - zassert_true((strcmp(stop, "ABCDEFGH") == 0), "strtoull get stop failed"); - - char border1[] = "+18446744073709551615"; - char border2[] = "-18446744073709551615000"; - char border3[] = "+18446744073709551619"; - char border4[] = "0x0000000000000000000000000000000000001"; - char border5[] = "10000000000000000000000000000000000001"; - char border6[] = "-10000000000000000000000000000000000001"; - - ret = strtoull(border1, NULL, 10); - zassert_equal(ret, ULLONG_MAX, "strtoull base = 10 failed"); - ret = strtoull(border2, NULL, 10); - zassert_equal(ret, ULLONG_MAX, "strtoull base = 10 failed"); - ret = strtoull(border3, NULL, 10); - zassert_equal(ret, ULLONG_MAX, "strtoull base = 10 failed"); - ret = strtoull(border4, NULL, 16); - zassert_equal(ret, 1, "strtoull base = 16 failed, %s != 0x%x", border4, ret); - ret = strtoull(border5, NULL, 10); - zassert_equal(errno, ERANGE, "strtoull base = 10 failed, %s != %lld", border5, ret); - ret = strtoull(border6, NULL, 10); - zassert_equal(errno, ERANGE, "strtoull base = 10 failed, %s != %lld", border6, ret); -} - -/** - * - * @brief test convert function - * - */ -ZTEST(test_c_lib, test_tolower_toupper) -{ - static const char test[] = "Az09Za{#!"; - static const char toup[] = "AZ09ZA{#!"; - static const char tolw[] = "az09za{#!"; - char up[11]; - char lw[11]; - int i = 0; - - for (; i < strlen(test); i++) { - up[i] = toupper(test[i]); - lw[i] = tolower(test[i]); - } - lw[i] = up[i] = '\0'; - - zassert_equal(strcmp(up, toup), 0, "toupper error"); - zassert_equal(strcmp(lw, tolw), 0, "tolower error"); -} - -void test_strtok_r_do(char *str, char *sep, int tlen, - const char * const *toks, bool expect) -{ - int len = 0; - char *state, *tok, buf[64+1] = {0}; - - strncpy(buf, str, 64); - - tok = strtok_r(buf, sep, &state); - while (tok && len < tlen) { - if (strcmp(tok, toks[len]) != 0) { - break; - } - tok = strtok_r(NULL, sep, &state); - len++; - } - if (expect) { - zassert_equal(len, tlen, - "strtok_r error '%s' / '%s'", str, sep); - } else { - zassert_not_equal(len, tlen, - "strtok_r error '%s' / '%s'", str, sep); - } -} - -ZTEST(test_c_lib, test_strtok_r) -{ - static const char * const tc01[] = { "1", "2", "3", "4", "5" }; - - test_strtok_r_do("1,2,3,4,5", ",", 5, tc01, true); - test_strtok_r_do(",, 1 ,2 ,3 4,5 ", ", ", 5, tc01, true); - test_strtok_r_do("1,,,2 3,,,4 5", ", ", 5, tc01, true); - test_strtok_r_do("1,2 3,,,4 5 ", ", ", 5, tc01, true); - test_strtok_r_do("0,1,,,2 3,,,4 5", ", ", 5, tc01, false); - test_strtok_r_do("1,,,2 3,,,4 5", ",", 5, tc01, false); - test_strtok_r_do("A,,,2,3,,,4 5", ",", 5, tc01, false); - test_strtok_r_do("1,,,2,3,,,", ",", 5, tc01, false); - test_strtok_r_do("1|2|3,4|5", "| ", 5, tc01, false); -} - -/** - * - * @brief Test time function - * - * @see gmtime(),gmtime_r(). - */ -ZTEST(test_c_lib, test_time) -{ - time_t tests1 = 0; - time_t tests2 = -5; - time_t tests3 = -214748364800; - time_t tests4 = 951868800; - - struct tm tp; - - zassert_not_null(gmtime(&tests1), "gmtime failed"); - zassert_not_null(gmtime(&tests2), "gmtime failed"); - - tp.tm_wday = -5; - zassert_not_null(gmtime_r(&tests3, &tp), "gmtime_r failed"); - zassert_not_null(gmtime_r(&tests4, &tp), "gmtime_r failed"); -} - -/** - * - * @brief Test rand function - * - */ -ZTEST(test_c_lib, test_rand) -{ -#ifdef CONFIG_MINIMAL_LIBC - int a; - - a = rand(); - /* The default seed is 1 */ - zassert_equal(a, 1103527590, "rand failed"); -#else - ztest_test_skip(); -#endif -} - -/** - * - * @brief Test srand function - * - */ -ZTEST(test_c_lib, test_srand) -{ -#ifdef CONFIG_MINIMAL_LIBC - int a; - - srand(0); - a = rand(); - zassert_equal(a, 12345, "srand with seed 0 failed"); - - srand(1); - a = rand(); - zassert_equal(a, 1103527590, "srand with seed 1 failed"); - - srand(10); - a = rand(); - zassert_equal(a, 297746555, "srand with seed 10 failed"); - - srand(UINT_MAX - 1); - a = rand(); - zassert_equal(a, 2087949151, "srand with seed UINT_MAX - 1 failed"); - - srand(UINT_MAX); - a = rand(); - zassert_equal(a, 1043980748, "srand with seed UINT_MAX failed"); -#else - ztest_test_skip(); -#endif -} - -/** - * - * @brief Test rand function for reproducibility - * - */ -ZTEST(test_c_lib, test_rand_reproducibility) -{ -#ifdef CONFIG_MINIMAL_LIBC - int a; - int b; - int c; - - srand(0); - a = rand(); - zassert_equal(a, 12345, "srand with seed 0 failed"); - srand(0); - b = rand(); - zassert_equal(b, 12345, "srand with seed 0 failed (2nd)"); - srand(0); - c = rand(); - zassert_equal(c, 12345, "srand with seed 0 failed (3rd)"); - - srand(1); - a = rand(); - zassert_equal(a, 1103527590, "srand with seed 1 failed"); - srand(1); - b = rand(); - zassert_equal(b, 1103527590, "srand with seed 1 failed (2nd)"); - srand(1); - c = rand(); - zassert_equal(c, 1103527590, "srand with seed 1 failed (3rd)"); - - srand(10); - a = rand(); - zassert_equal(a, 297746555, "srand with seed 10 failed"); - srand(10); - b = rand(); - zassert_equal(b, 297746555, "srand with seed 10 failed (2nd)"); - srand(10); - c = rand(); - zassert_equal(c, 297746555, "srand with seed 10 failed (3rd)"); - - srand(UINT_MAX - 1); - a = rand(); - zassert_equal(a, 2087949151, "srand with seed UINT_MAX - 1 failed"); - srand(UINT_MAX - 1); - b = rand(); - zassert_equal(b, 2087949151, "srand with seed UINT_MAX - 1 failed (2nd)"); - srand(UINT_MAX - 1); - c = rand(); - zassert_equal(c, 2087949151, "srand with seed UINT_MAX - 1 failed (3rd)"); - - srand(UINT_MAX); - a = rand(); - zassert_equal(a, 1043980748, "srand with seed UINT_MAX failed"); - srand(UINT_MAX); - b = rand(); - zassert_equal(b, 1043980748, "srand with seed UINT_MAX failed (2nd)"); - srand(UINT_MAX); - c = rand(); - zassert_equal(c, 1043980748, "srand with seed UINT_MAX failed (3rd)"); -#else - ztest_test_skip(); -#endif -} - -/** - * - * @brief test abort functions - * - * @see abort(). - */ -ZTEST(test_c_lib, test_abort) -{ - int a = 0; - - ztest_set_fault_valid(true); - abort(); - zassert_equal(a, 0, "abort failed"); -} - -/** - * - * @brief test exit functions - * - */ -static void exit_program(void *p1, void *p2, void *p3) -{ - exit(1); -} - -ZTEST(test_c_lib, test_exit) -{ - int a = 0; - - k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, exit_program, - NULL, NULL, NULL, K_PRIO_PREEMPT(0), 0, K_NO_WAIT); - k_sleep(K_MSEC(10)); - k_thread_abort(tid); - zassert_equal(a, 0, "exit failed"); -} diff --git a/tests/lib/c_lib/src/test_strerror.c b/tests/lib/c_lib/src/test_strerror.c deleted file mode 100644 index 25a31df0624..00000000000 --- a/tests/lib/c_lib/src/test_strerror.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2022 Meta - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifdef CONFIG_NEWLIB_LIBC -#define _POSIX_C_SOURCE 200809 -#endif - -#include -#include - -#include - -ZTEST(test_c_lib, test_strerror) -{ - const char *expected; - const char *actual; - - errno = 4242; - if (IS_ENABLED(CONFIG_MINIMAL_LIBC_DISABLE_STRING_ERROR_TABLE)) { - expected = ""; - actual = strerror(EINVAL); - } else { - expected = "Invalid argument"; - actual = strerror(EINVAL); - } - zassert_equal(0, strcmp(expected, actual), - "mismatch: exp: %s act: %s", expected, actual); - - /* do not change errno on success */ - zassert_equal(4242, errno, ""); - - /* consistent behaviour w.r.t. errno with invalid input */ - errno = 0; - expected = ""; - actual = strerror(-42); - zassert_equal(0, strcmp(expected, actual), "mismatch: exp: %s act: %s", - expected, actual); - actual = strerror(4242); - zassert_equal(0, strcmp(expected, actual), "mismatch: exp: %s act: %s", - expected, actual); - /* do not change errno on failure (for consistence) */ - zassert_equal(0, errno, ""); - - /* consistent behaviour for "Success" */ - if (!IS_ENABLED(CONFIG_MINIMAL_LIBC_DISABLE_STRING_ERROR_TABLE)) { - expected = "Success"; - actual = strerror(0); - zassert_equal(0, strcmp(expected, actual), - "mismatch: exp: %s act: %s", expected, actual); - } -} - -ZTEST(test_c_lib, test_strerror_r) -{ - const char *expected; - char actual[] = {'1', 'n', 'v', 'a', '1', '1', 'd', ' ', 'a', - '2', 'g', 'u', 'm', '3', 'n', '7', 0x00, 0x42}; - static const size_t n = sizeof(actual); - - if (IS_ENABLED(CONFIG_NEWLIB_LIBC) || IS_ENABLED(CONFIG_ARCMWDT_LIBC)) { - /* FIXME: Please see Issue #46846 */ - ztest_test_skip(); - } - - errno = 4242; - if (IS_ENABLED(CONFIG_MINIMAL_LIBC_DISABLE_STRING_ERROR_TABLE)) { - expected = ""; - zassert_equal(0, strerror_r(EINVAL, actual, n), ""); - zassert_equal(0, strncmp(expected, actual, n), - "mismatch: exp: %s act: %s", expected, actual); - } else { - expected = "Invalid argument"; - zassert_equal(0, strerror_r(EINVAL, actual, n), "%d", - strerror_r(EINVAL, actual, n)); - zassert_equal(0, strncmp(expected, actual, n), - "mismatch: exp: %s act: %s", expected, actual); - /* only the necessary buffer area is written */ - zassert_equal(0x42, (uint8_t)actual[n - 1], - "exp: %02x act: %02x", 0x42, - (uint8_t)actual[n - 1]); - - zassert_equal(ERANGE, strerror_r(EINVAL, actual, 0), ""); - } - - /* do not change errno on success */ - zassert_equal(4242, errno, ""); - - errno = 0; - zassert_equal(EINVAL, strerror_r(-42, actual, n), ""); - zassert_equal(EINVAL, strerror_r(4242, actual, n), ""); - /* do not change errno on failure */ - zassert_equal(0, errno, ""); -} diff --git a/tests/lib/c_lib/strerror/CMakeLists.txt b/tests/lib/c_lib/strerror/CMakeLists.txt new file mode 100644 index 00000000000..350d76aa6d7 --- /dev/null +++ b/tests/lib/c_lib/strerror/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(c_lib_strerror) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/lib/c_lib/Kconfig b/tests/lib/c_lib/strerror/Kconfig similarity index 100% rename from tests/lib/c_lib/Kconfig rename to tests/lib/c_lib/strerror/Kconfig diff --git a/tests/lib/c_lib/strerror/prj.conf b/tests/lib/c_lib/strerror/prj.conf new file mode 100644 index 00000000000..e39776e7067 --- /dev/null +++ b/tests/lib/c_lib/strerror/prj.conf @@ -0,0 +1,2 @@ +CONFIG_ZTEST=y +CONFIG_TEST_USERSPACE=y diff --git a/tests/lib/c_lib/strerror/src/main.c b/tests/lib/c_lib/strerror/src/main.c new file mode 100644 index 00000000000..8bfd06bbff5 --- /dev/null +++ b/tests/lib/c_lib/strerror/src/main.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2022 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifdef CONFIG_NEWLIB_LIBC +#define _POSIX_C_SOURCE 200809 +#endif + +#include +#include + +#include + +ZTEST(libc_strerror, test_strerror) +{ + const char *expected; + const char *actual; + + errno = 4242; + if (IS_ENABLED(CONFIG_MINIMAL_LIBC_DISABLE_STRING_ERROR_TABLE)) { + expected = ""; + actual = strerror(EINVAL); + } else { + expected = "Invalid argument"; + actual = strerror(EINVAL); + } + zassert_equal(0, strcmp(expected, actual), + "mismatch: exp: %s act: %s", expected, actual); + + /* do not change errno on success */ + zassert_equal(4242, errno, ""); + +#ifndef CONFIG_EXTERNAL_LIBC + /* consistent behaviour w.r.t. errno with invalid input */ + errno = 0; + expected = ""; + actual = strerror(-42); + zassert_equal(0, strcmp(expected, actual), "mismatch: exp: %s act: %s", + expected, actual); + actual = strerror(4242); + zassert_equal(0, strcmp(expected, actual), "mismatch: exp: %s act: %s", + expected, actual); + /* do not change errno on failure (for consistence) */ + zassert_equal(0, errno, ""); +#endif + + /* consistent behaviour for "Success" */ + if (!IS_ENABLED(CONFIG_MINIMAL_LIBC_DISABLE_STRING_ERROR_TABLE)) { + expected = "Success"; + actual = strerror(0); + zassert_equal(0, strcmp(expected, actual), + "mismatch: exp: %s act: %s", expected, actual); + } +} + +ZTEST(libc_strerror, test_strerror_r) +{ + const char *expected; + char actual[] = {'1', 'n', 'v', 'a', '1', '1', 'd', ' ', 'a', + '2', 'g', 'u', 'm', '3', 'n', '7', 0x00, 0x42}; + static const size_t n = sizeof(actual); + + if (IS_ENABLED(CONFIG_NEWLIB_LIBC) || IS_ENABLED(CONFIG_ARCMWDT_LIBC)) { + /* FIXME: Please see Issue #46846 */ + ztest_test_skip(); + } + + errno = 4242; + if (IS_ENABLED(CONFIG_MINIMAL_LIBC_DISABLE_STRING_ERROR_TABLE)) { + expected = ""; + zassert_equal(0, strerror_r(EINVAL, actual, n), ""); + zassert_equal(0, strncmp(expected, actual, n), + "mismatch: exp: %s act: %s", expected, actual); + } else { + expected = "Invalid argument"; + zassert_equal(0, strerror_r(EINVAL, actual, n), "%d", + strerror_r(EINVAL, actual, n)); + zassert_equal(0, strncmp(expected, actual, n), + "mismatch: exp: %s act: %s", expected, actual); + /* only the necessary buffer area is written */ + zassert_equal(0x42, (uint8_t)actual[n - 1], + "exp: %02x act: %02x", 0x42, + (uint8_t)actual[n - 1]); + + zassert_equal(ERANGE, strerror_r(EINVAL, actual, 0), ""); + } + + /* do not change errno on success */ + zassert_equal(4242, errno, ""); + + errno = 0; + zassert_equal(EINVAL, strerror_r(-42, actual, n), ""); + zassert_equal(EINVAL, strerror_r(4242, actual, n), ""); + /* do not change errno on failure */ + zassert_equal(0, errno, ""); +} + +ZTEST_SUITE(libc_strerror, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/lib/c_lib/strerror/testcase.yaml b/tests/lib/c_lib/strerror/testcase.yaml new file mode 100644 index 00000000000..2475c3e31ec --- /dev/null +++ b/tests/lib/c_lib/strerror/testcase.yaml @@ -0,0 +1,55 @@ +common: + tags: + - clib + integration_platforms: + - qemu_x86 +tests: + libraries.libc.strerror.minimal.strerror_table: + filter: CONFIG_MINIMAL_LIBC_SUPPORTED + tags: minimal_libc + extra_configs: + - CONFIG_MINIMAL_LIBC=y + - CONFIG_MINIMAL_LIBC_STRING_ERROR_TABLE=y + - CONFIG_MINIMAL_LIBC_NON_REENTRANT_FUNCTIONS=y + libraries.libc.strerror.minimal.no_strerror_table: + filter: CONFIG_MINIMAL_LIBC_SUPPORTED + tags: minimal_libc + extra_configs: + - CONFIG_MINIMAL_LIBC=y + - CONFIG_MINIMAL_LIBC_STRING_ERROR_TABLE=n + - CONFIG_MINIMAL_LIBC_NON_REENTRANT_FUNCTIONS=y + libraries.libc.strerror.newlib: + filter: CONFIG_NEWLIB_LIBC_SUPPORTED + min_ram: 32 + tags: newlib + ignore_faults: true + extra_configs: + - CONFIG_NEWLIB_LIBC=y + libraries.libc.strerror.newlib_nano: + filter: CONFIG_NEWLIB_LIBC_SUPPORTED and CONFIG_HAS_NEWLIB_LIBC_NANO + tags: newlib + ignore_faults: true + extra_configs: + - CONFIG_NEWLIB_LIBC=y + - CONFIG_NEWLIB_LIBC_NANO=y + libraries.libc.strerror.picolibc: + filter: CONFIG_PICOLIBC_SUPPORTED + tags: picolibc + ignore_faults: true + extra_configs: + - CONFIG_PICOLIBC=y + libraries.libc.strerror.picolibc.module: + filter: CONFIG_ZEPHYR_PICOLIBC_MODULE + tags: picolibc + ignore_faults: true + extra_configs: + - CONFIG_PICOLIBC=y + - CONFIG_PICOLIBC_USE_MODULE=y + libraries.libc.strerror.picolibc.notls: + filter: CONFIG_ZEPHYR_PICOLIBC_MODULE + tags: picolibc + ignore_faults: true + extra_configs: + - CONFIG_PICOLIBC=y + - CONFIG_PICOLIBC_USE_MODULE=y + - CONFIG_THREAD_LOCAL_STORAGE=n diff --git a/tests/lib/c_lib/testcase.yaml b/tests/lib/c_lib/testcase.yaml deleted file mode 100644 index 7bc5833a96a..00000000000 --- a/tests/lib/c_lib/testcase.yaml +++ /dev/null @@ -1,40 +0,0 @@ -common: - tags: - - clib - filter: not CONFIG_NATIVE_APPLICATION - integration_platforms: - - mps2_an385 -tests: - libraries.libc: - ignore_faults: true - filter: not (CONFIG_ARCH_POSIX and CONFIG_EXTERNAL_LIBC) - libraries.libc.picolibc: - filter: CONFIG_PICOLIBC_SUPPORTED - tags: picolibc - ignore_faults: true - extra_configs: - - CONFIG_PICOLIBC=y - libraries.libc.newlib: - filter: CONFIG_NEWLIB_LIBC_SUPPORTED - min_ram: 32 - tags: newlib - ignore_faults: true - extra_configs: - - CONFIG_NEWLIB_LIBC=y - libraries.libc.newlib_nano: - filter: CONFIG_NEWLIB_LIBC_SUPPORTED and CONFIG_HAS_NEWLIB_LIBC_NANO - tags: newlib - ignore_faults: true - extra_configs: - - CONFIG_NEWLIB_LIBC=y - - CONFIG_NEWLIB_LIBC_NANO=y - libraries.libc.minimal.strerror_table: - tags: minimal_libc - extra_configs: - - CONFIG_MINIMAL_LIBC=y - - CONFIG_MINIMAL_LIBC_STRING_ERROR_TABLE=y - libraries.libc.minimal.no_strerror_table: - tags: minimal_libc - extra_configs: - - CONFIG_MINIMAL_LIBC=y - - CONFIG_MINIMAL_LIBC_STRING_ERROR_TABLE=n diff --git a/tests/lib/c_lib/thrd/CMakeLists.txt b/tests/lib/c_lib/thrd/CMakeLists.txt new file mode 100644 index 00000000000..795545f0cb9 --- /dev/null +++ b/tests/lib/c_lib/thrd/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(c11_threads) + +FILE(GLOB app_sources src/*.c) + +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/lib/c_lib/thrd/prj.conf b/tests/lib/c_lib/thrd/prj.conf new file mode 100644 index 00000000000..dfa2820de7c --- /dev/null +++ b/tests/lib/c_lib/thrd/prj.conf @@ -0,0 +1,9 @@ +CONFIG_ZTEST=y +CONFIG_TEST_USERSPACE=y +CONFIG_ZTEST_FATAL_HOOK=y + +CONFIG_POSIX_API=y +CONFIG_THREAD_STACK_INFO=y +CONFIG_DYNAMIC_THREAD=y +CONFIG_DYNAMIC_THREAD_POOL_SIZE=2 +CONFIG_COMMON_LIBC_THRD=y diff --git a/tests/lib/c_lib/thrd/src/cnd.c b/tests/lib/c_lib/thrd/src/cnd.c new file mode 100644 index 00000000000..aaf00f9cb7b --- /dev/null +++ b/tests/lib/c_lib/thrd/src/cnd.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2023, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "thrd.h" + +#include +#include + +#include + +#define WAIT_TIME_MS 100 + +static struct libc_cnd_fixture { + /* shared between threads in tests */ + cnd_t cond; + mtx_t mutex; + + /* de-duplicate local variables in test cases */ + int res1; + int res2; + thrd_t thrd1; + thrd_t thrd2; + bool do_timedwait; + bool is_broadcast; + struct timespec time_point; +} _libc_cnd_fixture; + +ZTEST_F(libc_cnd, test_cnd_init_destroy) +{ + /* degenerate cases */ + if (false) { + /* pthread_cond_init() pthread_cond_destroy() are not hardened against these */ + zassert_equal(thrd_error, cnd_init(NULL)); + zassert_equal(thrd_error, cnd_init((cnd_t *)BIOS_FOOD)); + cnd_destroy(NULL); + cnd_destroy((cnd_t *)BIOS_FOOD); + } + + /* happy path tested in before() / after() */ +} + +ZTEST_F(libc_cnd, test_cnd_errors) +{ + /* degenerate test cases */ + if (false) { + /* pthread_cond_*() are not hardened against these */ + zassert_equal(thrd_error, cnd_signal(NULL)); + zassert_equal(thrd_error, cnd_broadcast(NULL)); + zassert_equal(thrd_error, cnd_wait(NULL, NULL)); + zassert_equal(thrd_error, cnd_wait(NULL, &fixture->mutex)); + zassert_equal(thrd_error, cnd_wait(&fixture->cond, NULL)); + zassert_equal(thrd_error, cnd_timedwait(NULL, NULL, NULL)); + zassert_equal(thrd_error, cnd_timedwait(NULL, NULL, &fixture->time_point)); + zassert_equal(thrd_error, cnd_timedwait(NULL, &fixture->mutex, NULL)); + zassert_equal(thrd_error, + cnd_timedwait(NULL, &fixture->mutex, &fixture->time_point)); + zassert_equal(thrd_error, cnd_timedwait(&fixture->cond, NULL, NULL)); + zassert_equal(thrd_error, + cnd_timedwait(&fixture->cond, NULL, &fixture->time_point)); + zassert_equal(thrd_error, cnd_timedwait(&fixture->cond, &fixture->mutex, NULL)); + } +} + +static int test_cnd_thread_fn(void *arg) +{ + int res = thrd_success; + struct timespec time_point; + struct libc_cnd_fixture *const fixture = arg; + + if (fixture->do_timedwait) { + zassume_ok(clock_gettime(CLOCK_MONOTONIC, &time_point)); + timespec_add_ms(&time_point, WAIT_TIME_MS); + res = cnd_timedwait(&fixture->cond, &fixture->mutex, &time_point); + } else { + res = cnd_wait(&fixture->cond, &fixture->mutex); + } + + if (fixture->is_broadcast) { + /* re-signal so that the next thread wakes up too */ + zassert_equal(thrd_success, cnd_signal(&fixture->cond)); + } + + (void)mtx_unlock(&fixture->mutex); + + return res; +} + +static void tst_cnd_common(struct libc_cnd_fixture *fixture, size_t wait_ms, bool th2, int exp1, + int exp2) +{ + zassert_equal(thrd_success, mtx_lock(&fixture->mutex)); + + zassert_equal(thrd_success, thrd_create(&fixture->thrd1, test_cnd_thread_fn, fixture)); + if (th2) { + zassert_equal(thrd_success, + thrd_create(&fixture->thrd2, test_cnd_thread_fn, fixture)); + } + + k_msleep(wait_ms); + + if (fixture->is_broadcast) { + zassert_equal(thrd_success, cnd_broadcast(&fixture->cond)); + } else { + zassert_equal(thrd_success, cnd_signal(&fixture->cond)); + } + + zassert_equal(thrd_success, mtx_unlock(&fixture->mutex)); + + zassert_equal(thrd_success, thrd_join(fixture->thrd1, &fixture->res1)); + if (th2) { + zassert_equal(thrd_success, thrd_join(fixture->thrd2, &fixture->res2)); + } + + zassert_equal(exp1, fixture->res1); + if (th2) { + zassert_equal(exp2, fixture->res2); + } +} + +ZTEST_F(libc_cnd, test_cnd_signal_wait) +{ + tst_cnd_common(fixture, WAIT_TIME_MS / 2, false, thrd_success, DONT_CARE); +} + +ZTEST_F(libc_cnd, test_cnd_signal_timedwait) +{ + fixture->do_timedwait = true; + tst_cnd_common(fixture, WAIT_TIME_MS / 2, false, thrd_success, DONT_CARE); +} + +ZTEST_F(libc_cnd, test_cnd_timedwait_timeout) +{ + fixture->do_timedwait = true; + tst_cnd_common(fixture, WAIT_TIME_MS * 2, false, thrd_timedout, DONT_CARE); +} + +ZTEST_F(libc_cnd, test_cnd_broadcast_wait) +{ + fixture->is_broadcast = true; + tst_cnd_common(fixture, WAIT_TIME_MS, true, thrd_success, thrd_success); +} + +static void *setup(void) +{ + return &_libc_cnd_fixture; +} + +static void before(void *arg) +{ + struct libc_cnd_fixture *const fixture = arg; + + *fixture = (struct libc_cnd_fixture){ + .res1 = FORTY_TWO, + .res2 = SEVENTY_THREE, + }; + + zassert_equal(thrd_success, mtx_init(&fixture->mutex, mtx_plain)); + zassert_equal(thrd_success, cnd_init(&fixture->cond)); +} + +static void after(void *arg) +{ + struct libc_cnd_fixture *const fixture = arg; + + cnd_destroy(&fixture->cond); + mtx_destroy(&fixture->mutex); +} + +ZTEST_SUITE(libc_cnd, NULL, setup, before, after, NULL); diff --git a/tests/lib/c_lib/thrd/src/mtx.c b/tests/lib/c_lib/thrd/src/mtx.c new file mode 100644 index 00000000000..433ea0e64e4 --- /dev/null +++ b/tests/lib/c_lib/thrd/src/mtx.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2023, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "thrd.h" + +#include +#include + +#include +#include + +static const int valid_mtx_types[] = { + mtx_plain, + mtx_timed, + mtx_plain | mtx_recursive, + mtx_timed | mtx_recursive, +}; + +ZTEST(libc_mtx, test_mtx_init) +{ + mtx_t mutex; + + zassert_not_equal(thrd_success, mtx_init(NULL, FORTY_TWO)); + zassert_not_equal(thrd_success, mtx_init(&mutex, FORTY_TWO)); + + if (false) { + /* pthread_mutexattr_init() is not hardened against this */ + zassert_not_equal(thrd_success, mtx_init(NULL, mtx_plain)); + zassert_not_equal(thrd_success, mtx_init((mtx_t *)BIOS_FOOD, FORTY_TWO)); + } + + for (size_t i = 0; i < ARRAY_SIZE(valid_mtx_types); ++i) { + int type = valid_mtx_types[i]; + + zassert_equal(thrd_success, mtx_init(&mutex, type)); + mtx_destroy(&mutex); + } +} + +ZTEST(libc_mtx, test_mtx_destroy) +{ + mtx_t mutex; + + if (false) { + /* degenerate cases */ + /* pthread_mutex_destroy() is not hardened against these */ + mtx_destroy(NULL); + mtx_destroy((mtx_t *)BIOS_FOOD); + } + + zassert_equal(thrd_success, mtx_init(&mutex, mtx_plain)); + mtx_destroy(&mutex); +} + +ZTEST(libc_mtx, test_mtx_lock) +{ + mtx_t mutex; + + if (false) { + /* pthread_mutex_lock() is not hardened against this */ + zassert_not_equal(thrd_success, mtx_lock(NULL)); + zassert_not_equal(thrd_success, mtx_lock((mtx_t *)BIOS_FOOD)); + } + + /* test plain mutex */ + for (size_t i = 0; i < ARRAY_SIZE(valid_mtx_types); ++i) { + int type = valid_mtx_types[i]; + + zassert_equal(thrd_success, mtx_init(&mutex, type)); + zassert_equal(thrd_success, mtx_lock(&mutex)); + if ((type & mtx_recursive) == 0) { + if (false) { + /* pthread_mutex_lock() is not hardened against this */ + zassert_not_equal(thrd_success, mtx_lock((&mutex))); + } + } else { + zassert_equal(thrd_success, mtx_lock(&mutex)); + zassert_equal(thrd_success, mtx_unlock(&mutex)); + } + zassert_equal(thrd_success, mtx_unlock(&mutex)); + mtx_destroy(&mutex); + } +} + +#define TIMEDLOCK_TIMEOUT_MS 200 +#define TIMEDLOCK_TIMEOUT_DELAY_MS 100 + +BUILD_ASSERT(TIMEDLOCK_TIMEOUT_DELAY_MS >= 100, "TIMEDLOCK_TIMEOUT_DELAY_MS too small"); +BUILD_ASSERT(TIMEDLOCK_TIMEOUT_MS >= 2 * TIMEDLOCK_TIMEOUT_DELAY_MS, + "TIMEDLOCK_TIMEOUT_MS too small"); + +static int mtx_timedlock_fn(void *arg) +{ + struct timespec time_point; + mtx_t *mutex = (mtx_t *)arg; + + zassume_ok(clock_gettime(CLOCK_MONOTONIC, &time_point)); + timespec_add_ms(&time_point, TIMEDLOCK_TIMEOUT_MS); + + return mtx_timedlock(mutex, &time_point); +} + +ZTEST(libc_mtx, test_mtx_timedlock) +{ + int ret; + thrd_t th; + mtx_t mutex; + + /* + * mtx_timed here is technically unnecessary, because all pthreads can + * be used for timed locks, but that is sort of peeking into the + * implementation + */ + zassert_equal(thrd_success, mtx_init(&mutex, mtx_timed)); + + printk("Expecting timedlock with timeout of %d ms to fail\n", TIMEDLOCK_TIMEOUT_MS); + zassert_equal(thrd_success, mtx_lock(&mutex)); + zassert_equal(thrd_success, thrd_create(&th, mtx_timedlock_fn, &mutex)); + zassert_equal(thrd_success, thrd_join(th, &ret)); + /* ensure timeout occurs */ + zassert_equal(thrd_timedout, ret); + + printk("Expecting timedlock with timeout of %d ms to succeed after 100ms\n", + TIMEDLOCK_TIMEOUT_MS); + zassert_equal(thrd_success, thrd_create(&th, mtx_timedlock_fn, &mutex)); + /* unlock before timeout expires */ + k_msleep(TIMEDLOCK_TIMEOUT_DELAY_MS); + zassert_equal(thrd_success, mtx_unlock(&mutex)); + zassert_equal(thrd_success, thrd_join(th, &ret)); + /* ensure lock is successful, in spite of delay */ + zassert_equal(thrd_success, ret); + + mtx_destroy(&mutex); +} + +static int mtx_trylock_fn(void *arg) +{ + mtx_t *mutex = (mtx_t *)arg; + + return mtx_trylock(mutex); +} + +ZTEST(libc_mtx, test_mtx_trylock) +{ + int ret; + thrd_t th; + mtx_t mutex; + + zassert_equal(thrd_success, mtx_init(&mutex, mtx_plain)); + + /* ensure trylock fails when lock is held */ + zassert_equal(thrd_success, mtx_lock(&mutex)); + zassert_equal(thrd_success, thrd_create(&th, mtx_trylock_fn, &mutex)); + zassert_equal(thrd_success, thrd_join(th, &ret)); + /* ensure lock fails */ + zassert_equal(thrd_busy, ret); + + mtx_destroy(&mutex); +} + +ZTEST(libc_mtx, test_mtx_unlock) +{ + mtx_t mutex = (mtx_t)BIOS_FOOD; + + /* degenerate case */ + zassert_not_equal(thrd_success, mtx_unlock(&mutex)); + + zassert_equal(thrd_success, mtx_init(&mutex, mtx_plain)); + zassert_equal(thrd_success, mtx_lock(&mutex)); + zassert_equal(thrd_success, mtx_unlock(&mutex)); + mtx_destroy(&mutex); +} + +ZTEST_SUITE(libc_mtx, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/lib/c_lib/thrd/src/once.c b/tests/lib/c_lib/thrd/src/once.c new file mode 100644 index 00000000000..e239206d9b4 --- /dev/null +++ b/tests/lib/c_lib/thrd/src/once.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "thrd.h" + +#include +#include + +#include + +static size_t number_of_calls; +static once_flag flag = ONCE_FLAG_INIT; + +static void once_func(void) +{ + number_of_calls++; +} + +ZTEST(libc_once, test_call_once) +{ + zassert_equal(number_of_calls, 0); + + call_once(&flag, once_func); + call_once(&flag, once_func); + call_once(&flag, once_func); + + zassert_equal(number_of_calls, 1); +} + +ZTEST_SUITE(libc_once, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/lib/c_lib/thrd/src/thrd.c b/tests/lib/c_lib/thrd/src/thrd.c new file mode 100644 index 00000000000..55cd1841c13 --- /dev/null +++ b/tests/lib/c_lib/thrd/src/thrd.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2023, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "thrd.h" + +#include +#include + +#include +#include + +ZTEST(libc_thrd, test_thrd_sleep) +{ + int64_t end; + int64_t start; + struct timespec duration = {0}; + struct timespec remaining; + const uint16_t delay_ms[] = {0, 100, 200, 400}; + + zassert_not_equal(0, thrd_sleep(NULL, NULL)); + zassert_ok(thrd_sleep(&duration, NULL)); + zassert_ok(thrd_sleep(&duration, &duration)); + + for (int i = 0; i < ARRAY_SIZE(delay_ms); ++i) { + duration = (struct timespec){.tv_nsec = delay_ms[i] * NSEC_PER_MSEC}; + remaining = (struct timespec){.tv_sec = 4242, .tv_nsec = 4242}; + + printk("sleeping %d ms\n", delay_ms[i]); + start = k_uptime_get(); + zassert_ok(thrd_sleep(&duration, &remaining)); + end = k_uptime_get(); + zassert_equal(remaining.tv_sec, 0); + zassert_equal(remaining.tv_nsec, 0); + zassert_true(end - start >= delay_ms[i]); + } +} + +static int thrd_create_join_fn(void *arg) +{ + uintptr_t *x = (uintptr_t *)arg; + + if (x != NULL) { + *x = BIOS_FOOD; + } + + return FORTY_TWO; +} + +ZTEST(libc_thrd, test_thrd_create_join) +{ + thrd_t thr; + int res = 0; + uintptr_t x = 0; + thrd_start_t fun = thrd_create_join_fn; + + if (false) { + /* pthread_create() is not hardened for degenerate cases like this */ + zassert_equal(thrd_error, thrd_create(NULL, NULL, NULL)); + zassert_equal(thrd_error, thrd_create(NULL, NULL, &x)); + zassert_equal(thrd_error, thrd_create(NULL, fun, NULL)); + zassert_equal(thrd_error, thrd_create(NULL, fun, &x)); + zassert_equal(thrd_error, thrd_create(&thr, NULL, NULL)); + zassert_equal(thrd_error, thrd_create(&thr, NULL, &x)); + } + + zassert_equal(thrd_success, thrd_create(&thr, fun, NULL)); + zassert_equal(thrd_success, thrd_join(thr, NULL)); + + zassert_equal(thrd_success, thrd_create(&thr, fun, &x)); + zassert_equal(thrd_success, thrd_join(thr, &res)); + zassert_equal(BIOS_FOOD, x, "expected: %d actual: %d", BIOS_FOOD, x); + zassert_equal(FORTY_TWO, res); +} + +static int thrd_exit_fn(void *arg) +{ + uintptr_t *x = (uintptr_t *)arg; + + *x = BIOS_FOOD; + + thrd_exit(SEVENTY_THREE); + + return FORTY_TWO; + + CODE_UNREACHABLE; +} + +ZTEST(libc_thrd, test_thrd_exit) +{ + thrd_t thr; + int res = 0; + uintptr_t x = 0; + + zassert_equal(thrd_success, thrd_create(&thr, thrd_exit_fn, &x)); + zassert_equal(thrd_success, thrd_join(thr, &res)); + zassert_equal(BIOS_FOOD, x); + zassert_equal(SEVENTY_THREE, res); +} + +ZTEST(libc_thrd, test_thrd_yield) +{ + thrd_yield(); +} + +static thrd_t child; +static thrd_t parent; + +static int thrd_current_equal_fn(void *arg) +{ + ARG_UNUSED(arg); + + zassert_equal(thrd_current(), child); + zassert_not_equal(child, parent); + + zassert_true(thrd_equal(thrd_current(), child)); + zassert_false(thrd_equal(child, parent)); + + return 0; +} + +ZTEST(libc_thrd, test_thrd_current_equal) +{ + parent = thrd_current(); + + zassert_equal(thrd_success, thrd_create(&child, thrd_current_equal_fn, NULL)); + zassert_equal(thrd_success, thrd_join(child, NULL)); +} + +static bool detached_thread_is_probably_done; + +static int thrd_detach_fn(void *arg) +{ + ARG_UNUSED(arg); + + detached_thread_is_probably_done = true; + return SEVENTY_THREE; +} + +ZTEST(libc_thrd, test_thrd_detach) +{ + thrd_t thr; + + zassert_equal(thrd_success, thrd_create(&thr, thrd_detach_fn, NULL)); + zassert_equal(thrd_success, thrd_detach(thr)); + zassert_equal(thrd_error, thrd_join(thr, NULL)); + + do { + k_msleep(100); + } while (!detached_thread_is_probably_done); + + zassert_equal(thrd_error, thrd_join(thr, NULL)); +} + +ZTEST(libc_thrd, test_thrd_reuse) +{ + thrd_t thr; + + for (int i = 0; i < FORTY_TWO; ++i) { + zassert_equal(thrd_success, thrd_create(&thr, thrd_create_join_fn, NULL)); + zassert_equal(thrd_success, thrd_join(thr, NULL)); + } +} + +ZTEST_SUITE(libc_thrd, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/lib/c_lib/thrd/src/thrd.h b/tests/lib/c_lib/thrd/src/thrd.h new file mode 100644 index 00000000000..02861b2ac6e --- /dev/null +++ b/tests/lib/c_lib/thrd/src/thrd.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef TESTS_LIB_CLIB_SRC_TEST_THRD_H_ +#define TESTS_LIB_CLIB_SRC_TEST_THRD_H_ + +#include + +#include +#include + +/* arbitrary magic numbers used for testing */ +#define BIOS_FOOD 0xb105f00d +#define FORTY_TWO 42 +#define SEVENTY_THREE 73 +#define DONT_CARE 0x370ca2e5 + +static inline void timespec_add_ms(struct timespec *ts, uint32_t ms) +{ + bool oflow; + + ts->tv_nsec += ms * NSEC_PER_MSEC; + oflow = ts->tv_nsec >= NSEC_PER_SEC; + ts->tv_sec += oflow; + ts->tv_nsec -= oflow * NSEC_PER_SEC; +} + +#endif diff --git a/tests/lib/c_lib/thrd/src/tss.c b/tests/lib/c_lib/thrd/src/tss.c new file mode 100644 index 00000000000..d68a6489dc5 --- /dev/null +++ b/tests/lib/c_lib/thrd/src/tss.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2023, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "thrd.h" + +#include +#include + +#include + +static tss_t key; +static int32_t destroyed_values[2]; +static const int32_t forty_two = FORTY_TWO; +static const int32_t seventy_three = SEVENTY_THREE; + +static void destroy_fn(void *arg) +{ + int32_t val = *(int32_t *)arg; + + switch (val) { + case FORTY_TWO: + destroyed_values[0] = FORTY_TWO; + break; + case SEVENTY_THREE: + destroyed_values[1] = SEVENTY_THREE; + break; + default: + zassert_true(val == FORTY_TWO || val == SEVENTY_THREE, "unexpected val %d", val); + } +} + +ZTEST(libc_tss, test_tss_create_delete) +{ + /* degenerate test cases */ + if (false) { + /* pthread_key_create() has not been hardened against this */ + zassert_equal(thrd_error, tss_create(NULL, NULL)); + zassert_equal(thrd_error, tss_create(NULL, destroy_fn)); + } + tss_delete(BIOS_FOOD); + + /* happy path tested in before() / after() */ +} + +static int thread_fn(void *arg) +{ + int32_t val = *(int32_t *)arg; + + zassert_equal(tss_get(key), NULL); + tss_set(key, arg); + zassert_equal(tss_get(key), arg); + + return val; +} + +/* test out separate threads doing tss_get() / tss_set() */ +ZTEST(libc_tss, test_tss_get_set) +{ + thrd_t thread1; + thrd_t thread2; + int res1 = BIOS_FOOD; + int res2 = BIOS_FOOD; + + /* degenerate test cases */ + zassert_is_null(tss_get(BIOS_FOOD)); + zassert_not_equal(thrd_success, tss_set(FORTY_TWO, (void *)BIOS_FOOD)); + zassert_is_null(tss_get(FORTY_TWO)); + + zassert_equal(thrd_success, thrd_create(&thread1, thread_fn, (void *)&forty_two)); + zassert_equal(thrd_success, thrd_create(&thread2, thread_fn, (void *)&seventy_three)); + + zassert_equal(thrd_success, thrd_join(thread1, &res1)); + zassert_equal(thrd_success, thrd_join(thread2, &res2)); + zassert_equal(FORTY_TWO, res1); + zassert_equal(SEVENTY_THREE, res2); + + zassert_equal(destroyed_values[0], FORTY_TWO); + zassert_equal(destroyed_values[1], SEVENTY_THREE); +} + +static void before(void *arg) +{ + destroyed_values[0] = 0; + destroyed_values[1] = 0; + + zassert_equal(thrd_success, tss_create(&key, destroy_fn)); +} + +static void after(void *arg) +{ + tss_delete(key); +} + +ZTEST_SUITE(libc_tss, NULL, NULL, before, after, NULL); diff --git a/tests/lib/c_lib/thrd/testcase.yaml b/tests/lib/c_lib/thrd/testcase.yaml new file mode 100644 index 00000000000..ecba688407f --- /dev/null +++ b/tests/lib/c_lib/thrd/testcase.yaml @@ -0,0 +1,52 @@ +common: + tags: + - clib c11 threads + filter: not CONFIG_NATIVE_APPLICATION + integration_platforms: + - qemu_x86 + platform_exclude: + - native_posix + - native_posix_64 +tests: + libraries.libc.c11_threads.minimal: + tags: minimal_libc + filter: CONFIG_MINIMAL_LIBC_SUPPORTED + extra_configs: + - CONFIG_MINIMAL_LIBC=y + - CONFIG_MINIMAL_LIBC_NON_REENTRANT_FUNCTIONS=y + - CONFIG_MINIMAL_LIBC_RAND=y + libraries.libc.c11_threads.picolibc: + filter: CONFIG_PICOLIBC_SUPPORTED + tags: picolibc + extra_configs: + - CONFIG_PICOLIBC=y + libraries.libc.c11_threads.picolibc.module: + filter: CONFIG_ZEPHYR_PICOLIBC_MODULE + tags: picolibc + extra_configs: + - CONFIG_PICOLIBC=y + - CONFIG_PICOLIBC_USE_MODULE=y + - CONFIG_THREAD_LOCAL_STORAGE=y + libraries.libc.c11_threads.picolibc.notls: + filter: CONFIG_ZEPHYR_PICOLIBC_MODULE + tags: picolibc + extra_configs: + - CONFIG_PICOLIBC=y + - CONFIG_PICOLIBC_USE_MODULE=y + - CONFIG_THREAD_LOCAL_STORAGE=n + libraries.libc.c11_threads.newlib: + filter: CONFIG_NEWLIB_LIBC_SUPPORTED + arch_exclude: + - posix + min_ram: 32 + tags: newlib + extra_configs: + - CONFIG_NEWLIB_LIBC=y + libraries.libc.c11_threads.newlib_nano: + filter: CONFIG_NEWLIB_LIBC_SUPPORTED and CONFIG_HAS_NEWLIB_LIBC_NANO + arch_exclude: + - posix + tags: newlib + extra_configs: + - CONFIG_NEWLIB_LIBC=y + - CONFIG_NEWLIB_LIBC_NANO=y diff --git a/tests/lib/cbprintf_fp/testcase.yaml b/tests/lib/cbprintf_fp/testcase.yaml index 1d8585c53b5..6cc638b5060 100644 --- a/tests/lib/cbprintf_fp/testcase.yaml +++ b/tests/lib/cbprintf_fp/testcase.yaml @@ -7,7 +7,7 @@ common: - qemu_x86_64 filter: CONFIG_CONSOLE_HAS_DRIVER tests: - libraries.cbprintf_fp.printk: + libraries.cbprintf.fp.printk: extra_configs: - CONFIG_APP_FORMATTER_PRINTK=y harness_config: @@ -16,7 +16,7 @@ tests: regex: - "Hello with printk" - "Complete" - libraries.cbprintf_fp.printf: + libraries.cbprintf.fp.printf: extra_configs: - CONFIG_APP_FORMATTER_PRINTF=y harness_config: @@ -25,7 +25,7 @@ tests: regex: - "Hello with printf" - "Complete" - libraries.cbprintf_fp.printf_nl: + libraries.cbprintf.fp.printf_nl: filter: TOOLCHAIN_HAS_NEWLIB == 1 extra_configs: - CONFIG_APP_FORMATTER_PRINTF=y @@ -36,7 +36,7 @@ tests: regex: - "Hello with printf/newlib" - "Complete" - libraries.cbprintf_fp.printfcb: + libraries.cbprintf.fp.printfcb: extra_configs: - CONFIG_APP_FORMATTER_PRINTFCB=y harness_config: @@ -45,7 +45,7 @@ tests: regex: - "Hello with printfcb" - "Complete" - libraries.cbprintf_fp.printfcb_nl: + libraries.cbprintf.fp.printfcb_nl: filter: TOOLCHAIN_HAS_NEWLIB == 1 extra_configs: - CONFIG_APP_FORMATTER_PRINTFCB=y @@ -56,7 +56,7 @@ tests: regex: - "Hello with printfcb/newlib" - "Complete" - libraries.cbprintf_fp.fprintf: + libraries.cbprintf.fp.fprintf: extra_configs: - CONFIG_APP_FORMATTER_FPRINTF=y harness_config: @@ -65,7 +65,7 @@ tests: regex: - "Hello with fprintf" - "Complete" - libraries.cbprintf_fp.fprintfcb: + libraries.cbprintf.fp.fprintfcb: extra_configs: - CONFIG_APP_FORMATTER_FPRINTFCB=y harness_config: @@ -74,7 +74,7 @@ tests: regex: - "Hello with fprintfcb" - "Complete" - libraries.cbprintf_fp.printf.picolibc: + libraries.cbprintf.fp.printf.picolibc: filter: CONFIG_PICOLIBC_SUPPORTED tags: picolibc extra_configs: @@ -86,7 +86,7 @@ tests: regex: - "Hello with printf" - "Complete" - libraries.cbprintf_fp.printfcb.picolibc: + libraries.cbprintf.fp.printfcb.picolibc: filter: CONFIG_PICOLIBC_SUPPORTED tags: picolibc extra_configs: diff --git a/tests/lib/cbprintf_package/prj.conf b/tests/lib/cbprintf_package/prj.conf index c1c71f42bc4..d89dc93d02d 100644 --- a/tests/lib/cbprintf_package/prj.conf +++ b/tests/lib/cbprintf_package/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_CBPRINTF_LIBC_SUBSTS=y CONFIG_TEST_EXTRA_STACK_SIZE=1024 diff --git a/tests/lib/cbprintf_package/testcase.yaml b/tests/lib/cbprintf_package/testcase.yaml index 61654bc1187..61545936181 100644 --- a/tests/lib/cbprintf_package/testcase.yaml +++ b/tests/lib/cbprintf_package/testcase.yaml @@ -5,20 +5,20 @@ common: tags: cbprintf min_flash: 48 tests: - libraries.cbprintf_package: + libraries.cbprintf.package: extra_configs: - CONFIG_CBPRINTF_COMPLETE=y integration_platforms: - native_posix - libraries.cbprintf_package_no_generic: + libraries.cbprintf.package_no_generic: extra_configs: - CONFIG_CBPRINTF_COMPLETE=y - CONFIG_COMPILER_OPT="-DZ_C_GENERIC=0" integration_platforms: - native_posix - libraries.cbprintf_package_fp: + libraries.cbprintf.package_fp: filter: CONFIG_CPU_HAS_FPU extra_configs: - CONFIG_CBPRINTF_FP_SUPPORT=y @@ -27,7 +27,7 @@ tests: integration_platforms: - native_posix - libraries.cbprintf_package_fp_align_offset: + libraries.cbprintf.package_fp_align_offset: filter: CONFIG_CPU_HAS_FPU extra_configs: - CONFIG_CBPRINTF_FP_SUPPORT=y @@ -37,7 +37,7 @@ tests: integration_platforms: - native_posix - libraries.cbprintf_package_long_double: + libraries.cbprintf.package_long_double: filter: CONFIG_CPU_HAS_FPU extra_configs: - CONFIG_CBPRINTF_FP_SUPPORT=y @@ -48,7 +48,7 @@ tests: integration_platforms: - native_posix - libraries.cbprintf_package_long_double_align_offset: + libraries.cbprintf.package_long_double_align_offset: filter: CONFIG_CPU_HAS_FPU extra_configs: - CONFIG_CBPRINTF_FP_SUPPORT=y @@ -60,21 +60,21 @@ tests: integration_platforms: - native_posix - libraries.cbprintf_package_nano: + libraries.cbprintf.package_nano: extra_configs: - CONFIG_CBPRINTF_NANO=y integration_platforms: - native_posix # Same test but with test compiled as C++ - libraries.cbprintf_package_cpp: + libraries.cbprintf.package_cpp: extra_configs: - CONFIG_CPP=y - CONFIG_CBPRINTF_COMPLETE=y integration_platforms: - native_posix - libraries.cbprintf_package_no_generic_cpp: + libraries.cbprintf.package_no_generic_cpp: extra_configs: - CONFIG_CPP=y - CONFIG_CBPRINTF_COMPLETE=y @@ -82,7 +82,7 @@ tests: integration_platforms: - native_posix - libraries.cbprintf_package_fp_cpp: + libraries.cbprintf.package_fp_cpp: filter: CONFIG_CPU_HAS_FPU extra_configs: - CONFIG_CPP=y @@ -92,7 +92,7 @@ tests: integration_platforms: - native_posix - libraries.cbprintf_package_fp_align_offset_cpp: + libraries.cbprintf.package_fp_align_offset_cpp: filter: CONFIG_CPU_HAS_FPU extra_configs: - CONFIG_CPP=y @@ -103,7 +103,7 @@ tests: integration_platforms: - native_posix - libraries.cbprintf_package_long_double_cpp: + libraries.cbprintf.package_long_double_cpp: filter: CONFIG_CPU_HAS_FPU extra_configs: - CONFIG_CPP=y @@ -115,7 +115,7 @@ tests: integration_platforms: - native_posix - libraries.cbprintf_package_long_double_align_offset_cpp: + libraries.cbprintf.package_long_double_align_offset_cpp: filter: CONFIG_CPU_HAS_FPU extra_configs: - CONFIG_CPP=y @@ -128,14 +128,14 @@ tests: integration_platforms: - native_posix - libraries.cbprintf_package_nano_cpp: + libraries.cbprintf.package_nano_cpp: extra_configs: - CONFIG_CPP=y - CONFIG_CBPRINTF_NANO=y integration_platforms: - native_posix - libraries.cbprintf_package.picolibc: + libraries.cbprintf.package.picolibc: filter: CONFIG_PICOLIBC_SUPPORTED tags: picolibc extra_configs: @@ -144,7 +144,7 @@ tests: integration_platforms: - qemu_x86 - libraries.cbprintf_package_no_generic.picolibc: + libraries.cbprintf.package_no_generic.picolibc: filter: CONFIG_PICOLIBC_SUPPORTED tags: picolibc extra_configs: @@ -154,7 +154,7 @@ tests: integration_platforms: - qemu_x86 - libraries.cbprintf_package_fp.picolibc: + libraries.cbprintf.package_fp.picolibc: filter: CONFIG_CPU_HAS_FPU and CONFIG_PICOLIBC_SUPPORTED tags: picolibc extra_configs: @@ -166,7 +166,7 @@ tests: - qemu_x86 # Same test but with test compiled as C++ - libraries.cbprintf_package_cpp.picolibc: + libraries.cbprintf.package_cpp.picolibc: filter: CONFIG_PICOLIBC_SUPPORTED tags: picolibc extra_configs: @@ -176,7 +176,7 @@ tests: integration_platforms: - qemu_x86 - libraries.cbprintf_package_no_generic_cpp.picolibc: + libraries.cbprintf.package_no_generic_cpp.picolibc: filter: CONFIG_PICOLIBC_SUPPORTED tags: picolibc extra_configs: @@ -187,7 +187,7 @@ tests: integration_platforms: - qemu_x86 - libraries.cbprintf_package_fp_cpp.picolibc: + libraries.cbprintf.package_fp_cpp.picolibc: filter: CONFIG_CPU_HAS_FPU and CONFIG_PICOLIBC_SUPPORTED tags: picolibc extra_configs: diff --git a/tests/lib/cmsis_dsp/bayes/prj.conf b/tests/lib/cmsis_dsp/bayes/prj.conf index 4699ae06e09..b2e3d9799b8 100644 --- a/tests/lib/cmsis_dsp/bayes/prj.conf +++ b/tests/lib/cmsis_dsp/bayes/prj.conf @@ -1,5 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_CMSIS_DSP=y -CONFIG_CMSIS_DSP_BAYES=y diff --git a/tests/lib/cmsis_dsp/bayes/testcase.yaml b/tests/lib/cmsis_dsp/bayes/testcase.yaml index 97582355f73..8bc620caac7 100644 --- a/tests/lib/cmsis_dsp/bayes/testcase.yaml +++ b/tests/lib/cmsis_dsp/bayes/testcase.yaml @@ -1,7 +1,7 @@ tests: libraries.cmsis_dsp.bayes: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -12,7 +12,7 @@ tests: min_ram: 32 libraries.cmsis_dsp.bayes.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 diff --git a/tests/lib/cmsis_dsp/common/test_common.h b/tests/lib/cmsis_dsp/common/test_common.h index 033245ab812..f65637ac93b 100644 --- a/tests/lib/cmsis_dsp/common/test_common.h +++ b/tests/lib/cmsis_dsp/common/test_common.h @@ -26,7 +26,6 @@ #define ASSERT_MSG_ERROR_LIMIT_EXCEED "error limit exceeded" #define ASSERT_MSG_INCORRECT_COMP_RESULT "incorrect computation result" -#if defined(CONFIG_ZTEST_NEW_API) #define DEFINE_TEST_VARIANT1(suite, name, variant, a1) \ ZTEST(suite, test_##name##_##variant) \ { \ @@ -68,49 +67,6 @@ { \ test_##name(a1, a2, a3, a4, a5, a6, a7); \ } -#else /* !defined(CONFIG_ZTEST_NEW_API) */ -#define DEFINE_TEST_VARIANT1(name, variant, a1) \ - static void test_##name##_##variant(void) \ - { \ - test_##name(a1); \ - } - -#define DEFINE_TEST_VARIANT2(name, variant, a1, a2) \ - static void test_##name##_##variant(void) \ - { \ - test_##name(a1, a2); \ - } - -#define DEFINE_TEST_VARIANT3(name, variant, a1, a2, a3) \ - static void test_##name##_##variant(void) \ - { \ - test_##name(a1, a2, a3); \ - } - -#define DEFINE_TEST_VARIANT4(name, variant, a1, a2, a3, a4) \ - static void test_##name##_##variant(void) \ - { \ - test_##name(a1, a2, a3, a4); \ - } - -#define DEFINE_TEST_VARIANT5(name, variant, a1, a2, a3, a4, a5) \ - static void test_##name##_##variant(void) \ - { \ - test_##name(a1, a2, a3, a4, a5); \ - } - -#define DEFINE_TEST_VARIANT6(name, variant, a1, a2, a3, a4, a5, a6) \ - static void test_##name##_##variant(void) \ - { \ - test_##name(a1, a2, a3, a4, a5, a6); \ - } - -#define DEFINE_TEST_VARIANT7(name, variant, a1, a2, a3, a4, a5, a6, a7) \ - static void test_##name##_##variant(void) \ - { \ - test_##name(a1, a2, a3, a4, a5, a6, a7); \ - } -#endif /* !defined(CONFIG_ZTEST_NEW_API) */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" diff --git a/tests/lib/cmsis_dsp/complexmath/prj.conf b/tests/lib/cmsis_dsp/complexmath/prj.conf index c9ccc0fc0d5..b2e3d9799b8 100644 --- a/tests/lib/cmsis_dsp/complexmath/prj.conf +++ b/tests/lib/cmsis_dsp/complexmath/prj.conf @@ -1,5 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_CMSIS_DSP=y -CONFIG_CMSIS_DSP_COMPLEXMATH=y diff --git a/tests/lib/cmsis_dsp/complexmath/testcase.yaml b/tests/lib/cmsis_dsp/complexmath/testcase.yaml index d03cd223a08..13f98d88b2b 100644 --- a/tests/lib/cmsis_dsp/complexmath/testcase.yaml +++ b/tests/lib/cmsis_dsp/complexmath/testcase.yaml @@ -1,7 +1,7 @@ tests: libraries.cmsis_dsp.complexmath: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -12,7 +12,7 @@ tests: min_ram: 144 libraries.cmsis_dsp.complexmath.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 diff --git a/tests/lib/cmsis_dsp/distance/prj.conf b/tests/lib/cmsis_dsp/distance/prj.conf index 4ac4431074f..b2e3d9799b8 100644 --- a/tests/lib/cmsis_dsp/distance/prj.conf +++ b/tests/lib/cmsis_dsp/distance/prj.conf @@ -1,5 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_CMSIS_DSP=y -CONFIG_CMSIS_DSP_DISTANCE=y diff --git a/tests/lib/cmsis_dsp/distance/testcase.yaml b/tests/lib/cmsis_dsp/distance/testcase.yaml index e0feb91dd32..cbc956055fb 100644 --- a/tests/lib/cmsis_dsp/distance/testcase.yaml +++ b/tests/lib/cmsis_dsp/distance/testcase.yaml @@ -1,7 +1,7 @@ tests: libraries.cmsis_dsp.distance: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -12,7 +12,7 @@ tests: min_ram: 32 libraries.cmsis_dsp.distance.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 diff --git a/tests/lib/cmsis_dsp/fastmath/prj.conf b/tests/lib/cmsis_dsp/fastmath/prj.conf index c47d04656b0..b2e3d9799b8 100644 --- a/tests/lib/cmsis_dsp/fastmath/prj.conf +++ b/tests/lib/cmsis_dsp/fastmath/prj.conf @@ -1,5 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_CMSIS_DSP=y -CONFIG_CMSIS_DSP_FASTMATH=y diff --git a/tests/lib/cmsis_dsp/fastmath/testcase.yaml b/tests/lib/cmsis_dsp/fastmath/testcase.yaml index 3c363bdda3a..d63115edc42 100644 --- a/tests/lib/cmsis_dsp/fastmath/testcase.yaml +++ b/tests/lib/cmsis_dsp/fastmath/testcase.yaml @@ -1,7 +1,7 @@ tests: libraries.cmsis_dsp.fastmath: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -12,7 +12,7 @@ tests: min_ram: 64 libraries.cmsis_dsp.fastmath.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 diff --git a/tests/lib/cmsis_dsp/filtering/prj.conf b/tests/lib/cmsis_dsp/filtering/prj.conf index e7885f018d8..4b0e8a8121d 100644 --- a/tests/lib/cmsis_dsp/filtering/prj.conf +++ b/tests/lib/cmsis_dsp/filtering/prj.conf @@ -1,8 +1,6 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_CMSIS_DSP=y -CONFIG_CMSIS_DSP_FILTERING=y # Test Options CONFIG_CMSIS_DSP_TEST_FILTERING_BIQUAD=y diff --git a/tests/lib/cmsis_dsp/filtering/prj_base.conf b/tests/lib/cmsis_dsp/filtering/prj_base.conf index 48cde7ba869..b2e3d9799b8 100644 --- a/tests/lib/cmsis_dsp/filtering/prj_base.conf +++ b/tests/lib/cmsis_dsp/filtering/prj_base.conf @@ -1,5 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_CMSIS_DSP=y -CONFIG_CMSIS_DSP_FILTERING=y diff --git a/tests/lib/cmsis_dsp/filtering/testcase.yaml b/tests/lib/cmsis_dsp/filtering/testcase.yaml index 80705309a45..115367cdfc4 100644 --- a/tests/lib/cmsis_dsp/filtering/testcase.yaml +++ b/tests/lib/cmsis_dsp/filtering/testcase.yaml @@ -3,13 +3,13 @@ common: tests: libraries.cmsis_dsp.filtering: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX tags: cmsis_dsp skip: true libraries.cmsis_dsp.filtering.biquad: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -23,7 +23,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_FILTERING_BIQUAD=y libraries.cmsis_dsp.filtering.biquad.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 @@ -37,8 +37,8 @@ tests: - CONFIG_CMSIS_DSP_TEST_FILTERING_BIQUAD=y - CONFIG_FPU=y libraries.cmsis_dsp.filtering.decim: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -52,7 +52,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_FILTERING_DECIM=y libraries.cmsis_dsp.filtering.decim.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 @@ -66,8 +66,8 @@ tests: - CONFIG_CMSIS_DSP_TEST_FILTERING_DECIM=y - CONFIG_FPU=y libraries.cmsis_dsp.filtering.fir: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -81,7 +81,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_FILTERING_FIR=y libraries.cmsis_dsp.filtering.fir.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 @@ -95,8 +95,8 @@ tests: - CONFIG_CMSIS_DSP_TEST_FILTERING_FIR=y - CONFIG_FPU=y libraries.cmsis_dsp.filtering.misc: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -110,9 +110,10 @@ tests: - CONFIG_CMSIS_DSP_TEST_FILTERING_MISC=y libraries.cmsis_dsp.filtering.misc.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote + platform_exclude: - mps3_an547 tags: - cmsis_dsp diff --git a/tests/lib/cmsis_dsp/interpolation/prj.conf b/tests/lib/cmsis_dsp/interpolation/prj.conf index 0fbd97dded0..b2e3d9799b8 100644 --- a/tests/lib/cmsis_dsp/interpolation/prj.conf +++ b/tests/lib/cmsis_dsp/interpolation/prj.conf @@ -1,5 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_CMSIS_DSP=y -CONFIG_CMSIS_DSP_INTERPOLATION=y diff --git a/tests/lib/cmsis_dsp/interpolation/testcase.yaml b/tests/lib/cmsis_dsp/interpolation/testcase.yaml index ef4b94ff3a6..358a683c7ce 100644 --- a/tests/lib/cmsis_dsp/interpolation/testcase.yaml +++ b/tests/lib/cmsis_dsp/interpolation/testcase.yaml @@ -1,7 +1,7 @@ tests: libraries.cmsis_dsp.interpolation: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -12,7 +12,7 @@ tests: min_ram: 64 libraries.cmsis_dsp.interpolation.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 diff --git a/tests/lib/cmsis_dsp/matrix/prj.conf b/tests/lib/cmsis_dsp/matrix/prj.conf index f3cf8bc423c..e6cfe7a6774 100644 --- a/tests/lib/cmsis_dsp/matrix/prj.conf +++ b/tests/lib/cmsis_dsp/matrix/prj.conf @@ -1,8 +1,6 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_CMSIS_DSP=y -CONFIG_CMSIS_DSP_MATRIX=y # Test Options CONFIG_CMSIS_DSP_TEST_MATRIX_UNARY_Q7=y diff --git a/tests/lib/cmsis_dsp/matrix/prj_base.conf b/tests/lib/cmsis_dsp/matrix/prj_base.conf index a4c8db100f3..b2e3d9799b8 100644 --- a/tests/lib/cmsis_dsp/matrix/prj_base.conf +++ b/tests/lib/cmsis_dsp/matrix/prj_base.conf @@ -1,5 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_CMSIS_DSP=y -CONFIG_CMSIS_DSP_MATRIX=y diff --git a/tests/lib/cmsis_dsp/matrix/src/binary_f64.c b/tests/lib/cmsis_dsp/matrix/src/binary_f64.c index 4c30dfc8856..2a552750092 100644 --- a/tests/lib/cmsis_dsp/matrix/src/binary_f64.c +++ b/tests/lib/cmsis_dsp/matrix/src/binary_f64.c @@ -13,7 +13,7 @@ #include "binary_f64.pat" -#define SNR_ERROR_THRESH ((float32_t)120) +#define SNR_ERROR_THRESH ((float64_t)120) #define REL_ERROR_THRESH (1.0e-6) #define ABS_ERROR_THRESH (1.0e-5) diff --git a/tests/lib/cmsis_dsp/matrix/src/unary_f64.c b/tests/lib/cmsis_dsp/matrix/src/unary_f64.c index 1835cda30ff..e42a9bd87fc 100644 --- a/tests/lib/cmsis_dsp/matrix/src/unary_f64.c +++ b/tests/lib/cmsis_dsp/matrix/src/unary_f64.c @@ -13,11 +13,11 @@ #include "unary_f64.pat" -#define SNR_ERROR_THRESH ((float32_t)120) +#define SNR_ERROR_THRESH ((float64_t)120) #define REL_ERROR_THRESH (1.0e-6) #define ABS_ERROR_THRESH (1.0e-5) -#define SNR_ERROR_THRESH_CHOL ((float32_t)270) +#define SNR_ERROR_THRESH_CHOL ((float64_t)270) #define REL_ERROR_THRESH_CHOL (1.0e-9) #define ABS_ERROR_THRESH_CHOL (1.0e-9) diff --git a/tests/lib/cmsis_dsp/matrix/testcase.yaml b/tests/lib/cmsis_dsp/matrix/testcase.yaml index cf3365fc923..4a6912505e0 100644 --- a/tests/lib/cmsis_dsp/matrix/testcase.yaml +++ b/tests/lib/cmsis_dsp/matrix/testcase.yaml @@ -1,12 +1,12 @@ tests: libraries.cmsis_dsp.matrix: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX tags: cmsis_dsp skip: true libraries.cmsis_dsp.matrix.unary_q7: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -20,7 +20,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_MATRIX_UNARY_Q7=y libraries.cmsis_dsp.matrix.unary_q7.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 @@ -34,8 +34,8 @@ tests: - CONFIG_CMSIS_DSP_TEST_MATRIX_UNARY_Q7=y - CONFIG_FPU=y libraries.cmsis_dsp.matrix.unary_q15: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -49,7 +49,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_MATRIX_UNARY_Q15=y libraries.cmsis_dsp.matrix.unary_q15.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 @@ -63,8 +63,8 @@ tests: - CONFIG_CMSIS_DSP_TEST_MATRIX_UNARY_Q15=y - CONFIG_FPU=y libraries.cmsis_dsp.matrix.unary_q31: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -78,7 +78,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_MATRIX_UNARY_Q31=y libraries.cmsis_dsp.matrix.unary_q31.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 @@ -93,7 +93,7 @@ tests: - CONFIG_FPU=y libraries.cmsis_dsp.matrix.unary_f16: filter: (CONFIG_CMSIS_DSP_FLOAT16 and (CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) - and TOOLCHAIN_HAS_NEWLIB == 1) + and CONFIG_FULL_LIBC_SUPPORTED) integration_platforms: - frdm_k64f - sam_e70_xplained @@ -106,7 +106,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_MATRIX_UNARY_F16=y libraries.cmsis_dsp.matrix.unary_f16.fpu: filter: (CONFIG_CMSIS_DSP_FLOAT16 and (CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) - and CONFIG_CPU_HAS_FPU and TOOLCHAIN_HAS_NEWLIB == 1) + and CONFIG_CPU_HAS_FPU and CONFIG_FULL_LIBC_SUPPORTED) integration_platforms: - mps2_an521_remote - mps3_an547 @@ -120,8 +120,8 @@ tests: - CONFIG_CMSIS_DSP_TEST_MATRIX_UNARY_F16=y - CONFIG_FPU=y libraries.cmsis_dsp.matrix.unary_f32: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -135,7 +135,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_MATRIX_UNARY_F32=y libraries.cmsis_dsp.matrix.unary_f32.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 @@ -149,8 +149,8 @@ tests: - CONFIG_CMSIS_DSP_TEST_MATRIX_UNARY_F32=y - CONFIG_FPU=y libraries.cmsis_dsp.matrix.unary_f64: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -164,7 +164,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_MATRIX_UNARY_F64=y libraries.cmsis_dsp.matrix.unary_f64.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 @@ -178,8 +178,8 @@ tests: - CONFIG_CMSIS_DSP_TEST_MATRIX_UNARY_F64=y - CONFIG_FPU=y libraries.cmsis_dsp.matrix.binary_q7: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -194,7 +194,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_MATRIX_BINARY_Q7=y libraries.cmsis_dsp.matrix.binary_q7.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 @@ -209,8 +209,8 @@ tests: - CONFIG_CMSIS_DSP_TEST_MATRIX_BINARY_Q7=y - CONFIG_FPU=y libraries.cmsis_dsp.matrix.binary_q15: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -225,7 +225,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_MATRIX_BINARY_Q15=y libraries.cmsis_dsp.matrix.binary_q15.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 @@ -240,8 +240,8 @@ tests: - CONFIG_CMSIS_DSP_TEST_MATRIX_BINARY_Q15=y - CONFIG_FPU=y libraries.cmsis_dsp.matrix.binary_q31: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -256,7 +256,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_MATRIX_BINARY_Q31=y libraries.cmsis_dsp.matrix.binary_q31.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 @@ -272,7 +272,7 @@ tests: - CONFIG_FPU=y libraries.cmsis_dsp.matrix.binary_f16: filter: (CONFIG_CMSIS_DSP_FLOAT16 and (CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) - and TOOLCHAIN_HAS_NEWLIB == 1) + and CONFIG_FULL_LIBC_SUPPORTED) integration_platforms: - frdm_k64f - sam_e70_xplained @@ -285,7 +285,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_MATRIX_BINARY_F16=y libraries.cmsis_dsp.matrix.binary_f16.fpu: filter: (CONFIG_CMSIS_DSP_FLOAT16 and (CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) - and CONFIG_CPU_HAS_FPU and TOOLCHAIN_HAS_NEWLIB == 1) + and CONFIG_CPU_HAS_FPU and CONFIG_FULL_LIBC_SUPPORTED) integration_platforms: - mps2_an521_remote - mps3_an547 @@ -299,8 +299,8 @@ tests: - CONFIG_CMSIS_DSP_TEST_MATRIX_BINARY_F16=y - CONFIG_FPU=y libraries.cmsis_dsp.matrix.binary_f32: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -315,7 +315,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_MATRIX_BINARY_F32=y libraries.cmsis_dsp.matrix.binary_f32.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 @@ -330,8 +330,8 @@ tests: - CONFIG_CMSIS_DSP_TEST_MATRIX_BINARY_F32=y - CONFIG_FPU=y libraries.cmsis_dsp.matrix.binary_f64: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -346,7 +346,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_MATRIX_BINARY_F64=y libraries.cmsis_dsp.matrix.binary_f64.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 diff --git a/tests/lib/cmsis_dsp/quaternionmath/prj.conf b/tests/lib/cmsis_dsp/quaternionmath/prj.conf index 8de8c52d3c5..b2e3d9799b8 100644 --- a/tests/lib/cmsis_dsp/quaternionmath/prj.conf +++ b/tests/lib/cmsis_dsp/quaternionmath/prj.conf @@ -1,5 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_CMSIS_DSP=y -CONFIG_CMSIS_DSP_QUATERNIONMATH=y diff --git a/tests/lib/cmsis_dsp/quaternionmath/testcase.yaml b/tests/lib/cmsis_dsp/quaternionmath/testcase.yaml index 9c2ebb958dc..3d005e8a343 100644 --- a/tests/lib/cmsis_dsp/quaternionmath/testcase.yaml +++ b/tests/lib/cmsis_dsp/quaternionmath/testcase.yaml @@ -1,7 +1,7 @@ tests: libraries.cmsis_dsp.quaternionmath: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -12,7 +12,7 @@ tests: min_ram: 64 libraries.cmsis_dsp.quaternionmath.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 diff --git a/tests/lib/cmsis_dsp/statistics/prj.conf b/tests/lib/cmsis_dsp/statistics/prj.conf index 2eb1011afe3..b2e3d9799b8 100644 --- a/tests/lib/cmsis_dsp/statistics/prj.conf +++ b/tests/lib/cmsis_dsp/statistics/prj.conf @@ -1,5 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_CMSIS_DSP=y -CONFIG_CMSIS_DSP_STATISTICS=y diff --git a/tests/lib/cmsis_dsp/statistics/testcase.yaml b/tests/lib/cmsis_dsp/statistics/testcase.yaml index 7d23dd7155d..9082e8edf5f 100644 --- a/tests/lib/cmsis_dsp/statistics/testcase.yaml +++ b/tests/lib/cmsis_dsp/statistics/testcase.yaml @@ -1,7 +1,7 @@ tests: libraries.cmsis_dsp.statistics: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -11,8 +11,9 @@ tests: min_flash: 128 min_ram: 64 libraries.cmsis_dsp.statistics.fpu: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) + and CONFIG_CPU_HAS_FPU + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 diff --git a/tests/lib/cmsis_dsp/support/prj.conf b/tests/lib/cmsis_dsp/support/prj.conf index 80c8923b3a7..b2e3d9799b8 100644 --- a/tests/lib/cmsis_dsp/support/prj.conf +++ b/tests/lib/cmsis_dsp/support/prj.conf @@ -1,5 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_CMSIS_DSP=y -CONFIG_CMSIS_DSP_SUPPORT=y diff --git a/tests/lib/cmsis_dsp/support/testcase.yaml b/tests/lib/cmsis_dsp/support/testcase.yaml index 87839c923f0..1fed8894b42 100644 --- a/tests/lib/cmsis_dsp/support/testcase.yaml +++ b/tests/lib/cmsis_dsp/support/testcase.yaml @@ -1,7 +1,7 @@ tests: libraries.cmsis_dsp.support: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -12,7 +12,7 @@ tests: min_ram: 128 libraries.cmsis_dsp.support.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 diff --git a/tests/lib/cmsis_dsp/svm/prj.conf b/tests/lib/cmsis_dsp/svm/prj.conf index 18b34694a5f..b2e3d9799b8 100644 --- a/tests/lib/cmsis_dsp/svm/prj.conf +++ b/tests/lib/cmsis_dsp/svm/prj.conf @@ -1,5 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_CMSIS_DSP=y -CONFIG_CMSIS_DSP_SVM=y diff --git a/tests/lib/cmsis_dsp/svm/testcase.yaml b/tests/lib/cmsis_dsp/svm/testcase.yaml index 61d14b9777f..c107678e449 100644 --- a/tests/lib/cmsis_dsp/svm/testcase.yaml +++ b/tests/lib/cmsis_dsp/svm/testcase.yaml @@ -1,7 +1,7 @@ tests: libraries.cmsis_dsp.svm: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -12,7 +12,7 @@ tests: min_ram: 64 libraries.cmsis_dsp.svm.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 diff --git a/tests/lib/cmsis_dsp/transform/prj.conf b/tests/lib/cmsis_dsp/transform/prj.conf index 9889f3b9aed..5eaeb1a352f 100644 --- a/tests/lib/cmsis_dsp/transform/prj.conf +++ b/tests/lib/cmsis_dsp/transform/prj.conf @@ -1,8 +1,6 @@ CONFIG_ZTEST=y -CONFIG_NEWLIB_LIBC=y -CONFIG_ZTEST_NEW_API=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_CMSIS_DSP=y -CONFIG_CMSIS_DSP_TRANSFORM=y # Test Options CONFIG_CMSIS_DSP_TEST_TRANSFORM_CQ15=y diff --git a/tests/lib/cmsis_dsp/transform/prj_base.conf b/tests/lib/cmsis_dsp/transform/prj_base.conf index 40e0627c4ff..b2e3d9799b8 100644 --- a/tests/lib/cmsis_dsp/transform/prj_base.conf +++ b/tests/lib/cmsis_dsp/transform/prj_base.conf @@ -1,5 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_CMSIS_DSP=y -CONFIG_CMSIS_DSP_TRANSFORM=y diff --git a/tests/lib/cmsis_dsp/transform/testcase.yaml b/tests/lib/cmsis_dsp/transform/testcase.yaml index 3c0904ea875..030eb5b2f77 100644 --- a/tests/lib/cmsis_dsp/transform/testcase.yaml +++ b/tests/lib/cmsis_dsp/transform/testcase.yaml @@ -1,12 +1,12 @@ tests: libraries.cmsis_dsp.transform: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX tags: cmsis_dsp skip: true libraries.cmsis_dsp.transform.cq15: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -20,7 +20,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_TRANSFORM_CQ15=y libraries.cmsis_dsp.transform.cq15.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps3_an547 tags: @@ -33,8 +33,8 @@ tests: - CONFIG_CMSIS_DSP_TEST_TRANSFORM_CQ15=y - CONFIG_FPU=y libraries.cmsis_dsp.transform.rq15: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -48,7 +48,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_TRANSFORM_RQ15=y libraries.cmsis_dsp.transform.rq15.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps3_an547 tags: @@ -61,8 +61,8 @@ tests: - CONFIG_CMSIS_DSP_TEST_TRANSFORM_RQ15=y - CONFIG_FPU=y libraries.cmsis_dsp.transform.cq31: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -76,7 +76,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_TRANSFORM_CQ31=y libraries.cmsis_dsp.transform.cq31.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX tags: - cmsis_dsp - fpu @@ -87,8 +87,8 @@ tests: - CONFIG_CMSIS_DSP_TEST_TRANSFORM_CQ31=y - CONFIG_FPU=y libraries.cmsis_dsp.transform.rq31: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -102,7 +102,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_TRANSFORM_RQ31=y libraries.cmsis_dsp.transform.rq31.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX tags: - cmsis_dsp - fpu @@ -114,7 +114,7 @@ tests: - CONFIG_FPU=y libraries.cmsis_dsp.transform.cf16: filter: (CMSIS_DSP_FLOAT16 and (CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) - and TOOLCHAIN_HAS_NEWLIB == 1) + and CONFIG_FULL_LIBC_SUPPORTED) integration_platforms: - frdm_k64f - sam_e70_xplained @@ -127,7 +127,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_TRANSFORM_CF16=y libraries.cmsis_dsp.transform.cf16.fpu: filter: (CMSIS_DSP_FLOAT16 and (CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) - and CONFIG_CPU_HAS_FPU and TOOLCHAIN_HAS_NEWLIB == 1) + and CONFIG_CPU_HAS_FPU and CONFIG_FULL_LIBC_SUPPORTED) integration_platforms: - mps3_an547 tags: @@ -141,7 +141,7 @@ tests: - CONFIG_FPU=y libraries.cmsis_dsp.transform.rf16: filter: (CMSIS_DSP_FLOAT16 and (CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) - and TOOLCHAIN_HAS_NEWLIB == 1) + and CONFIG_FULL_LIBC_SUPPORTED) integration_platforms: - frdm_k64f - sam_e70_xplained @@ -154,7 +154,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_TRANSFORM_RF16=y libraries.cmsis_dsp.transform.rf16.fpu: filter: (CMSIS_DSP_FLOAT16 and (CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) - and CONFIG_CPU_HAS_FPU and TOOLCHAIN_HAS_NEWLIB == 1) + and CONFIG_CPU_HAS_FPU and CONFIG_FULL_LIBC_SUPPORTED) integration_platforms: - mps3_an547 tags: @@ -167,8 +167,8 @@ tests: - CONFIG_CMSIS_DSP_TEST_TRANSFORM_RF16=y - CONFIG_FPU=y libraries.cmsis_dsp.transform.cf32: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -182,7 +182,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_TRANSFORM_CF32=y libraries.cmsis_dsp.transform.cf32.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX tags: - cmsis_dsp - fpu @@ -193,8 +193,8 @@ tests: - CONFIG_CMSIS_DSP_TEST_TRANSFORM_CF32=y - CONFIG_FPU=y libraries.cmsis_dsp.transform.rf32: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -208,7 +208,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_TRANSFORM_RF32=y libraries.cmsis_dsp.transform.rf32.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps3_an547 tags: @@ -221,8 +221,8 @@ tests: - CONFIG_CMSIS_DSP_TEST_TRANSFORM_RF32=y - CONFIG_FPU=y libraries.cmsis_dsp.transform.cf64: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -236,7 +236,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_TRANSFORM_CF64=y libraries.cmsis_dsp.transform.cf64.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX tags: - cmsis_dsp - fpu @@ -247,8 +247,8 @@ tests: - CONFIG_CMSIS_DSP_TEST_TRANSFORM_CF64=y - CONFIG_FPU=y libraries.cmsis_dsp.transform.rf64: - filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and TOOLCHAIN_HAS_NEWLIB - == 1) or CONFIG_ARCH_POSIX + filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_FULL_LIBC_SUPPORTED + ) or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -262,7 +262,7 @@ tests: - CONFIG_CMSIS_DSP_TEST_TRANSFORM_RF64=y libraries.cmsis_dsp.transform.rf64.fpu: filter: ((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU - and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX tags: - cmsis_dsp - fpu diff --git a/tests/lib/cmsis_nn/prj.conf b/tests/lib/cmsis_nn/prj.conf index 6614e4a9fba..557435173ad 100644 --- a/tests/lib/cmsis_nn/prj.conf +++ b/tests/lib/cmsis_nn/prj.conf @@ -1,6 +1,5 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_CMSIS_DSP=y CONFIG_CMSIS_NN=y CONFIG_CMSIS_NN_ACTIVATION=y diff --git a/tests/lib/cmsis_nn/src/main.c b/tests/lib/cmsis_nn/src/main.c index f653d5a6aaf..3eb7c200590 100644 --- a/tests/lib/cmsis_nn/src/main.c +++ b/tests/lib/cmsis_nn/src/main.c @@ -18,41 +18,39 @@ #define REPEAT_NUM 3 -#define AVGPOOLING_2_OUT_CH 5 -#define AVGPOOLING_2_IN_CH 5 -#define AVGPOOLING_2_INPUT_W 12 -#define AVGPOOLING_2_INPUT_H 1 -#define AVGPOOLING_2_DST_SIZE 60 -#define AVGPOOLING_2_INPUT_SIZE 60 +#define AVGPOOLING_2_OUT_CH 5 +#define AVGPOOLING_2_IN_CH 5 +#define AVGPOOLING_2_INPUT_W 12 +#define AVGPOOLING_2_INPUT_H 1 +#define AVGPOOLING_2_DST_SIZE 60 +#define AVGPOOLING_2_INPUT_SIZE 60 #define AVGPOOLING_2_OUT_ACTIVATION_MIN -128 #define AVGPOOLING_2_OUT_ACTIVATION_MAX 127 -#define AVGPOOLING_2_INPUT_BATCHES 1 -#define AVGPOOLING_2_FILTER_X 3 -#define AVGPOOLING_2_FILTER_Y 1 -#define AVGPOOLING_2_STRIDE_X 1 -#define AVGPOOLING_2_STRIDE_Y 2 -#define AVGPOOLING_2_PAD_X 1 -#define AVGPOOLING_2_PAD_Y 0 -#define AVGPOOLING_2_OUTPUT_W 12 -#define AVGPOOLING_2_OUTPUT_H 1 +#define AVGPOOLING_2_INPUT_BATCHES 1 +#define AVGPOOLING_2_FILTER_X 3 +#define AVGPOOLING_2_FILTER_Y 1 +#define AVGPOOLING_2_STRIDE_X 1 +#define AVGPOOLING_2_STRIDE_Y 2 +#define AVGPOOLING_2_PAD_X 1 +#define AVGPOOLING_2_PAD_Y 0 +#define AVGPOOLING_2_OUTPUT_W 12 +#define AVGPOOLING_2_OUTPUT_H 1 const int8_t avgpooling_2_input[60] = { - 80, 16, -80, -96, 96, -64, -112, -112, 48, 16, -80, -80, 80, 64, -80, - 16, 48, -112, 0, 48, 96, -80, -112, -64, -32, -16, -112, -64, -64, 80, - -96, -112, -16, -80, -80, -112, -64, -48, 16, 64, 32, 48, 16, 64, 16, - -48, -64, -32, -80, 64, -48, -32, -32, -112, 32, 32, -112, -96, -96, 48 -}; + -82, -104, 10, -28, -52, -51, -66, 52, 124, -74, -21, 4, 37, -7, -33, + 102, 110, 24, 52, 121, 13, -55, -79, -92, -35, -103, 86, 95, 46, 32, + -24, -123, 120, 29, -77, -97, -69, -68, 58, 38, 3, 3, 79, -47, 112, + -52, -113, -46, 107, 68, 83, -70, 91, 14, 113, 74, 73, -103, -98, 25}; const int8_t avgpooling_2_output_ref[60] = { - 8, -48, -96, -24, 56, -21, -59, -37, 5, 11, -43, -48, -48, 37, -5, - 11, -37, -48, 0, -21, 32, -48, -96, -43, 32, -5, -101, -64, -69, -11, - -75, -96, -43, -43, 21, -59, -43, -16, 0, 0, -43, -27, -21, 0, 48, - -21, -16, -16, -43, 37, -21, -69, -53, -96, 48, -8, -72, -64, -104, 40 -}; + -67, -85, 31, 48, -63, -51, -55, 33, 30, -53, 10, 16, 38, 56, 5, + 31, 20, -6, -16, 18, 4, 47, 13, 2, 39, -38, -31, 45, -6, -27, + -75, -35, 49, 44, -2, -39, -63, 44, 13, 24, -49, -60, -12, 39, 73, + 11, -60, 41, 25, 98, 35, -37, -19, 8, 69, 79, 2, -6, -42, 69}; ZTEST(cmsis_nn, test_avgpool) { - q7_t output[AVGPOOLING_2_DST_SIZE] = { 0 }; + int8_t output[AVGPOOLING_2_DST_SIZE] = {0}; cmsis_nn_context ctx; cmsis_nn_pool_params pool_params; @@ -81,74 +79,78 @@ ZTEST(cmsis_nn, test_avgpool) ctx.size = arm_avgpool_s8_get_buffer_size(AVGPOOLING_2_OUTPUT_W, AVGPOOLING_2_IN_CH); ctx.buf = malloc(ctx.size); - arm_status result = arm_avgpool_s8(&ctx, &pool_params, &input_dims, avgpooling_2_input, - &filter_dims, &output_dims, output); + arm_cmsis_nn_status result = arm_avgpool_s8(&ctx, + &pool_params, + &input_dims, + avgpooling_2_input, + &filter_dims, + &output_dims, + output); free(ctx.buf); - zassert_equal(ARM_MATH_SUCCESS, result, ""); + zassert_equal(ARM_CMSIS_NN_SUCCESS, result, ""); zassert_mem_equal(avgpooling_2_output_ref, output, sizeof(output), ""); } -#define CONV_4_OUT_CH 3 -#define CONV_4_IN_CH 3 -#define CONV_4_INPUT_W 5 -#define CONV_4_INPUT_H 5 -#define CONV_4_DST_SIZE 36 -#define CONV_4_INPUT_SIZE 75 -#define CONV_4_OUT_ACTIVATION_MIN -128 -#define CONV_4_OUT_ACTIVATION_MAX 127 -#define CONV_4_INPUT_BATCHES 3 -#define CONV_4_INPUT_OFFSET 0 -#define CONV_4_OUTPUT_OFFSET 0 -#define CONV_4_FILTER_X 2 -#define CONV_4_FILTER_Y 3 -#define CONV_4_STRIDE_X 2 -#define CONV_4_STRIDE_Y 2 -#define CONV_4_PAD_X 0 -#define CONV_4_PAD_Y 0 -#define CONV_4_OUTPUT_W 2 -#define CONV_4_OUTPUT_H 2 - -const int32_t conv_4_biases[3] = { 2699, -5398, -2699 }; - -const q7_t conv_4_weights[54] = { - -127, 64, 64, -64, 0, 0, 64, -64, 0, -64, 64, 64, 64, -127, - 64, 0, -127, -64, 64, 64, -64, -64, -64, -64, -64, 0, 0, 64, - 64, 64, 0, 0, 0, -127, -64, -127, -127, 0, 0, 0, 0, -127, - -127, -127, -127, 64, -127, 64, 64, 0, 0, -64, -127, 64 +#define CONV_4_OUT_CH 3 +#define CONV_4_IN_CH 3 +#define CONV_4_INPUT_W 5 +#define CONV_4_INPUT_H 5 +#define CONV_4_DST_SIZE 36 +#define CONV_4_INPUT_SIZE 75 +#define CONV_4_OUT_ACTIVATION_MIN -109 +#define CONV_4_OUT_ACTIVATION_MAX 127 +#define CONV_4_INPUT_BATCHES 3 +#define CONV_4_FILTER_X 2 +#define CONV_4_FILTER_Y 3 +#define CONV_4_STRIDE_X 2 +#define CONV_4_STRIDE_Y 2 +#define CONV_4_PAD_X 0 +#define CONV_4_PAD_Y 0 +#define CONV_4_OUTPUT_W 2 +#define CONV_4_OUTPUT_H 2 +#define CONV_4_INPUT_OFFSET 128 +#define CONV_4_OUTPUT_OFFSET -128 +#define CONV_4_DILATION_X 1 +#define CONV_4_DILATION_Y 1 + +const int32_t conv_4_biases[3] = {13175, 9050, 18215}; + +const int8_t conv_4_weights[54] = { + -25, -83, -74, 105, 30, 118, -32, 127, 34, 127, -112, 39, -43, 104, 41, -124, 115, 5, + 42, -48, -119, 93, 17, 57, 41, -41, -42, 23, 127, 18, 70, -99, 71, 67, 83, 76, + -50, 98, 66, 64, 127, -6, -77, -48, -26, 45, 77, 1, 81, 27, 124, -103, 37, 36}; + +const int8_t conv_4_input[225] = { + 82, 120, -97, -44, -118, 73, 4, -84, -53, -122, -15, 77, 83, 43, 37, + 85, -11, 103, 45, -69, -12, -8, 21, 6, -68, -83, -15, -99, 90, -62, + 95, 62, -38, -32, -35, -105, -53, 70, 112, 14, -4, -33, -26, -93, -98, + 22, -5, 22, -104, 57, -92, 30, -62, 0, -43, -82, 60, 99, -83, 32, + 94, 49, 10, 112, -71, -27, -91, -79, 52, -92, -71, 86, -79, -15, -80, + -74, -4, 76, -119, 91, -23, -12, -111, -72, 26, 11, 64, 116, 38, 99, + 125, 17, 6, -4, 46, 119, 113, -116, -125, 80, -57, 122, 75, 119, -117, + 87, -121, -70, -75, -127, 16, -124, -110, 10, 71, 29, 27, 37, -24, 52, + 28, -100, 86, -75, 117, -31, -115, -86, -122, 121, -96, -118, 32, 111, 25, + -90, -8, 110, 37, 35, 124, -123, 94, -122, -114, 37, 85, -36, 53, -40, + 73, -99, 27, 10, 37, 41, 64, -97, -123, 75, 0, -107, -72, 58, -100, + 17, 77, 114, 120, -83, -96, 75, -12, -27, 3, 35, 85, 4, 119, -20, + 28, 99, 104, -78, -51, -82, -92, -40, -116, 35, -107, 39, 9, -120, -50, + -102, -114, 25, -77, 25, 7, 64, 110, 80, -93, -20, 34, 115, 75, 37, + 47, 16, 6, -92, -25, 37, 69, 82, -61, -100, -85, -51, 6, -95, 58 }; -const q7_t conv_4_input[225] = { - 42, -85, -85, 0, 42, 42, -42, -42, -42, -85, 42, 42, -42, -42, -85, - 0, -85, 0, 42, -42, 0, -42, 42, -42, -42, 42, -42, 42, -85, -42, - -85, -42, 0, -42, -42, -42, 42, -85, -42, -42, -42, 0, -42, 0, 0, - 0, 42, -42, 42, 0, -42, 0, 0, -85, 0, 42, 42, 0, 42, 42, -85, 42, - 42, -85, -42, 0, -85, 42, -42, -85, -42, -85, 42, 42, -85, -85, 42, - 42, 42, -85, 42, -85, -42, -42, 0, -42, -85, -85, 42, -85, 0, -85, - 42, 42, 0, 42, 42, 42, 42, -85, 42, -85, -42, 0, 42, 0, 0, -85, -42, - 0, -85, 0, 42, -85, -42, 0, -42, 0, 42, -42, -42, -85, 0, -85, -42, - -85, 0, 42, -85, -85, -85, -85, 0, -85, 42, 42, 0, -42, -85, -85, 0, - -42, 0, 0, -85, -85, -42, 42, -85, -42, -42, 42, -85, 0, 42, 0, -85, - 0, 0, 42, 42, -85, -85, -85, 0, 42, 0, 0, 42, -85, -85, 42, -85, -42, - -42, 0, -85, -85, 42, -85, 0, -85, -42, -85, 42, 0, 42, 42, 0, -85, - 0, 0, 0, 0, 0, -42, -85, 42, 0, -85, -42, 0, -42, 42, 42, -85, 0, - 42, 42, 0, -42, -85, -42, -85, 0, 42, -85, -85, -42, 42, -42, -42, - -42, -42, 42 -}; +const int32_t conv_4_output_mult[3] = {2039209398, 2005068758, 2023002003}; -const int32_t conv_4_output_mult[3] = { 1629660588, 1629660588, 1629660588 }; +const int32_t conv_4_output_shift[3] = {-9, -9, -9}; -const int32_t conv_4_output_shift[3] = { -11, -11, -11 }; - -const q7_t conv_4_output_ref[36] = { - -2, 2, 2, 8, 0, 1, 1, 3, 7, -2, 11, 0, 8, 4, 4, 1, -1, -5, - 4, 5, 14, 2, 5, 7, -1, -2, 2, 5, -4, 11, -1, -2, 8, 4, 2, 0 -}; +const int8_t conv_4_output_ref[36] = {-5, -39, -31, 20, -37, -26, -109, -7, -10, -51, -58, 48, + -100, -32, 24, 4, 69, -38, -64, 65, -34, 95, -55, 39, + 95, -54, 27, -49, 25, -68, -109, -66, 72, 38, -44, -40}; ZTEST(cmsis_nn, test_convolve) { - q7_t output[CONV_4_DST_SIZE] = { 0 }; + int8_t output[CONV_4_DST_SIZE] = {0}; cmsis_nn_context ctx; cmsis_nn_conv_params conv_params; @@ -158,9 +160,9 @@ ZTEST(cmsis_nn, test_convolve) cmsis_nn_dims bias_dims; cmsis_nn_dims output_dims; - const q31_t *bias_data = conv_4_biases; - const q7_t *kernel_data = conv_4_weights; - const q7_t *input_data = conv_4_input; + const int32_t *bias_data = conv_4_biases; + const int8_t *kernel_data = conv_4_weights; + const int8_t *input_data = conv_4_input; input_dims.n = CONV_4_INPUT_BATCHES; input_dims.w = CONV_4_INPUT_W; @@ -176,6 +178,8 @@ ZTEST(cmsis_nn, test_convolve) conv_params.padding.h = CONV_4_PAD_Y; conv_params.stride.w = CONV_4_STRIDE_X; conv_params.stride.h = CONV_4_STRIDE_Y; + conv_params.dilation.w = CONV_4_DILATION_X; + conv_params.dilation.h = CONV_4_DILATION_Y; conv_params.input_offset = CONV_4_INPUT_OFFSET; conv_params.output_offset = CONV_4_OUTPUT_OFFSET; @@ -189,7 +193,7 @@ ZTEST(cmsis_nn, test_convolve) ctx.buf = malloc(buf_size); ctx.size = 0; - arm_status result = arm_convolve_s8(&ctx, + arm_cmsis_nn_status result = arm_convolve_s8(&ctx, &conv_params, &quant_params, &input_dims, @@ -202,7 +206,7 @@ ZTEST(cmsis_nn, test_convolve) output); free(ctx.buf); - zassert_equal(ARM_MATH_SUCCESS, result, ""); + zassert_equal(ARM_CMSIS_NN_SUCCESS, result, ""); zassert_mem_equal(conv_4_output_ref, output, sizeof(output), ""); buf_size = arm_convolve_wrapper_s8_get_buffer_size(&conv_params, &input_dims, @@ -223,63 +227,63 @@ ZTEST(cmsis_nn, test_convolve) output); free(ctx.buf); - zassert_equal(ARM_MATH_SUCCESS, result, ""); + zassert_equal(ARM_CMSIS_NN_SUCCESS, result, ""); zassert_mem_equal(conv_4_output_ref, output, sizeof(output), ""); } -#define STRIDE2PAD1_OUT_CH 1 -#define STRIDE2PAD1_IN_CH 1 -#define STRIDE2PAD1_INPUT_W 7 -#define STRIDE2PAD1_INPUT_H 7 -#define STRIDE2PAD1_DST_SIZE 16 -#define STRIDE2PAD1_INPUT_SIZE 49 -#define STRIDE2PAD1_OUT_ACTIVATION_MIN -128 -#define STRIDE2PAD1_OUT_ACTIVATION_MAX 127 -#define STRIDE2PAD1_INPUT_BATCHES 1 -#define STRIDE2PAD1_INPUT_OFFSET 128 -#define STRIDE2PAD1_OUTPUT_OFFSET 0 -#define STRIDE2PAD1_FILTER_X 3 -#define STRIDE2PAD1_FILTER_Y 3 -#define STRIDE2PAD1_STRIDE_X 2 -#define STRIDE2PAD1_STRIDE_Y 2 -#define STRIDE2PAD1_PAD_X 1 -#define STRIDE2PAD1_PAD_Y 1 -#define STRIDE2PAD1_OUTPUT_W 4 -#define STRIDE2PAD1_OUTPUT_H 4 - -const int32_t stride2pad1_biases[1] = { 4318 }; - -const q7_t stride2pad1_weights[9] = { 42, 127, 127, 127, 42, 127, 85, 42, 85 }; - -const q7_t stride2pad1_input[49] = { - -26, -77, -26, -26, 25, -77, -77, -26, 25, -26, -77, -26, -26, -77, 25, -77, -26, - -26, -77, -26, -77, -26, -77, -26, 25, -77, -26, -26, -26, 25, -26, -77, -77, -77, - -26, 25, 25, -26, -77, -26, -26, -26, -26, -26, -77, -26, 25, -77, -26 -}; - -const int32_t stride2pad1_output_mult[1] = { 2037075735 }; - -const int32_t stride2pad1_output_shift[1] = { -11 }; - -const q7_t stride2pad1_output_ref[16] = { - 15, 23, 22, 11, 27, 35, 39, 20, 31, 42, 29, 21, 28, 27, 27, 15 -}; +#define STRIDE2PAD1_OUT_CH 1 +#define STRIDE2PAD1_IN_CH 1 +#define STRIDE2PAD1_INPUT_W 7 +#define STRIDE2PAD1_INPUT_H 7 +#define STRIDE2PAD1_DST_SIZE 16 +#define STRIDE2PAD1_INPUT_SIZE 49 +#define STRIDE2PAD1_OUT_ACTIVATION_MIN -128 +#define STRIDE2PAD1_OUT_ACTIVATION_MAX 127 +#define STRIDE2PAD1_INPUT_BATCHES 1 +#define STRIDE2PAD1_FILTER_X 3 +#define STRIDE2PAD1_FILTER_Y 3 +#define STRIDE2PAD1_STRIDE_X 2 +#define STRIDE2PAD1_STRIDE_Y 2 +#define STRIDE2PAD1_PAD_X 1 +#define STRIDE2PAD1_PAD_Y 1 +#define STRIDE2PAD1_OUTPUT_W 4 +#define STRIDE2PAD1_OUTPUT_H 4 +#define STRIDE2PAD1_INPUT_OFFSET 128 +#define STRIDE2PAD1_OUTPUT_OFFSET -20 +#define STRIDE2PAD1_DILATION_X 1 +#define STRIDE2PAD1_DILATION_Y 1 + +const int32_t stride2pad1_biases[1] = {-9794}; + +const int8_t stride2pad1_weights[9] = {-54, 57, -19, -127, 87, 70, 74, -110, 66}; + +const int8_t stride2pad1_input[49] = { + -91, -30, -57, -76, 32, -13, 14, -96, 108, -4, 41, 48, 107, -68, -101, 30, 95, + 95, 91, -66, -80, 114, -49, 7, -67, -35, -1, -88, -77, -56, -103, 5, -39, -118, + -24, -32, 67, 11, 38, -16, -124, 44, -46, -92, -24, 108, 80, -29, -3}; + +const int32_t stride2pad1_output_mult[1] = {2033801520}; + +const int32_t stride2pad1_output_shift[1] = {-8}; + +const int8_t stride2pad1_output_ref[16] = {26, -11, 33, -25, -96, -52, -78, -86, + 33, -2, -88, -113, -14, 0, -84, -27}; ZTEST(cmsis_nn, test_depthwise_convolve) { - q7_t output[STRIDE2PAD1_DST_SIZE] = { 0 }; + int8_t output[STRIDE2PAD1_DST_SIZE] = {0}; cmsis_nn_context ctx; cmsis_nn_dw_conv_params dw_conv_params; cmsis_nn_per_channel_quant_params quant_params; cmsis_nn_dims input_dims; cmsis_nn_dims filter_dims; - cmsis_nn_dims bias_dims = { 0 }; + cmsis_nn_dims bias_dims = {0}; cmsis_nn_dims output_dims; - const q31_t *bias_data = stride2pad1_biases; - const q7_t *kernel_data = stride2pad1_weights; - const q7_t *input_data = stride2pad1_input; + const int32_t *bias_data = stride2pad1_biases; + const int8_t *kernel_data = stride2pad1_weights; + const int8_t *input_data = stride2pad1_input; input_dims.n = STRIDE2PAD1_INPUT_BATCHES; input_dims.w = STRIDE2PAD1_INPUT_W; @@ -295,6 +299,9 @@ ZTEST(cmsis_nn, test_depthwise_convolve) dw_conv_params.padding.h = STRIDE2PAD1_PAD_Y; dw_conv_params.stride.w = STRIDE2PAD1_STRIDE_X; dw_conv_params.stride.h = STRIDE2PAD1_STRIDE_Y; + dw_conv_params.dilation.w = STRIDE2PAD1_DILATION_X; + dw_conv_params.dilation.h = STRIDE2PAD1_DILATION_Y; + dw_conv_params.ch_mult = 1; dw_conv_params.input_offset = STRIDE2PAD1_INPUT_OFFSET; @@ -307,7 +314,7 @@ ZTEST(cmsis_nn, test_depthwise_convolve) ctx.buf = NULL; ctx.size = 0; - arm_status result = arm_depthwise_conv_s8(&ctx, + arm_cmsis_nn_status result = arm_depthwise_conv_s8(&ctx, &dw_conv_params, &quant_params, &input_dims, @@ -320,46 +327,47 @@ ZTEST(cmsis_nn, test_depthwise_convolve) output); free(ctx.buf); - zassert_equal(ARM_MATH_SUCCESS, result, ""); + zassert_equal(ARM_CMSIS_NN_SUCCESS, result, ""); zassert_mem_equal(stride2pad1_output_ref, output, sizeof(output), ""); } -#define FULLY_CONNECTED_MVE_0_OUT_CH 9 -#define FULLY_CONNECTED_MVE_0_IN_CH 16 -#define FULLY_CONNECTED_MVE_0_INPUT_W 1 -#define FULLY_CONNECTED_MVE_0_INPUT_H 1 -#define FULLY_CONNECTED_MVE_0_DST_SIZE 9 -#define FULLY_CONNECTED_MVE_0_INPUT_SIZE 16 -#define FULLY_CONNECTED_MVE_0_OUT_ACTIVATION_MIN -128 -#define FULLY_CONNECTED_MVE_0_OUT_ACTIVATION_MAX 127 -#define FULLY_CONNECTED_MVE_0_INPUT_BATCHES 1 -#define FULLY_CONNECTED_MVE_0_INPUT_OFFSET 3 -#define FULLY_CONNECTED_MVE_0_OUTPUT_OFFSET -2 -#define FULLY_CONNECTED_MVE_0_OUTPUT_MULTIPLIER 1073741824 -#define FULLY_CONNECTED_MVE_0_OUTPUT_SHIFT 1 -#define FULLY_CONNECTED_MVE_0_ACCUMULATION_DEPTH 16 - -const int32_t fully_connected_mve_0_biases[9] = { -1, 0, 0, 2, -1, -1, 1, -3, -4 }; - -const q7_t fully_connected_mve_0_input[16] = { - -5, -3, -5, -3, -3, -6, -1, -5, -4, -3, -2, 0, -2, -1, -2, -6 -}; - -const q7_t fully_connected_mve_0_output_ref[9] = { 0, -29, 33, -5, 28, -5, 19, -7, 16 }; - -const q7_t fully_connected_mve_0_weights[144] = { - 1, 0, -1, -3, -4, -3, 3, -2, 3, 3, 1, 2, -2, -4, -4, 2, 3, 2, 3, -1, -2, 2, - -4, 0, 1, -3, -3, -3, 1, 1, -3, -4, -3, 3, 2, 3, 1, -4, 3, -3, -1, 3, 1, -2, - 2, 3, -4, -3, 2, -4, 0, 3, 0, -2, 0, -1, -2, 0, 3, -3, -1, -2, -3, -1, -4, - 1, 2, -1, -4, -4, 1, -3, -3, 2, 3, 1, -3, -2, -4, -3, -2, 2, 1, 1, 1, -2, 0, - 3, -3, -2, -1, -4, -2, 2, 1, -1, -4, 2, 2, 3, 3, 2, 0, -3, 2, 3, 0, 3, 3, -1, - -4, -4, 0, 1, -4, -1, -3, 3, 2, 3, 2, -3, -1, -3, 0, 3, -2, -3, -2, 3, -4, 3, - -1, -4, 2, 2, 3, 1, -1, 1, 0, -4, -2, -3 -}; +#define FULLY_CONNECTED_MVE_0_OUT_CH 9 +#define FULLY_CONNECTED_MVE_0_IN_CH 16 +#define FULLY_CONNECTED_MVE_0_INPUT_W 1 +#define FULLY_CONNECTED_MVE_0_INPUT_H 1 +#define FULLY_CONNECTED_MVE_0_DST_SIZE 9 +#define FULLY_CONNECTED_MVE_0_INPUT_SIZE 16 +#define FULLY_CONNECTED_MVE_0_OUT_ACTIVATION_MIN -128 +#define FULLY_CONNECTED_MVE_0_OUT_ACTIVATION_MAX 127 +#define FULLY_CONNECTED_MVE_0_INPUT_BATCHES 1 +#define FULLY_CONNECTED_MVE_0_OUTPUT_MULTIPLIER 1244038257 +#define FULLY_CONNECTED_MVE_0_OUTPUT_SHIFT -9 +#define FULLY_CONNECTED_MVE_0_ACCUMULATION_DEPTH 16 +#define FULLY_CONNECTED_MVE_0_INPUT_OFFSET 128 +#define FULLY_CONNECTED_MVE_0_OUTPUT_OFFSET -26 + +const int32_t fully_connected_mve_0_biases[9] = {11295, -30752, -3196, 10489, -5120, + 18598, 27393, 29746, 22967}; + +const int8_t fully_connected_mve_0_input[16] = {-43, 68, 79, -12, -119, -56, -102, -46, + 107, -65, -109, -7, 92, -99, -80, -29}; + +const int8_t fully_connected_mve_0_output_ref[9] = {-9, -3, 26, 8, 3, -88, 75, 34, 5}; + +const int8_t fully_connected_mve_0_weights[144] = { + 37, -46, 75, -33, -52, -82, -94, 64, 71, 65, 64, 16, -66, -5, -65, -44, + 82, 42, 84, 105, 18, 79, -103, -75, -95, 65, 87, 103, 43, -25, -66, 75, + 125, 40, -34, 24, 9, -79, 4, 73, 98, -75, 42, 81, 18, -58, -119, 92, + 0, -72, 48, 23, -69, 11, -95, -103, 66, 117, 107, -96, 114, -29, 75, -93, + 118, 66, -19, 83, -14, 86, -110, 44, 37, -9, 17, -107, 50, -116, -116, -27, + -84, -126, -108, -127, -71, 8, 81, 108, -61, 126, 69, -45, 37, -78, -102, -55, + 116, 112, -111, -89, -57, 82, -47, 22, 125, -84, 97, -9, 88, 74, -15, 118, + -95, 112, 89, 44, -17, -112, -71, -94, 1, -117, 112, -92, 52, 57, -22, 80, + -60, 95, -106, -1, -27, 105, 6, 123, 6, 96, 126, -65, -29, 103, 19, -45}; ZTEST(cmsis_nn, test_fully_connected) { - q7_t output[FULLY_CONNECTED_MVE_0_DST_SIZE] = { 0 }; + int8_t output[FULLY_CONNECTED_MVE_0_DST_SIZE] = {0}; cmsis_nn_context ctx; cmsis_nn_fc_params fc_params; @@ -369,9 +377,9 @@ ZTEST(cmsis_nn, test_fully_connected) cmsis_nn_dims bias_dims; cmsis_nn_dims output_dims; - const q31_t *bias_data = fully_connected_mve_0_biases; - const q7_t *kernel_data = fully_connected_mve_0_weights; - const q7_t *input_data = fully_connected_mve_0_input; + const int32_t *bias_data = fully_connected_mve_0_biases; + const int8_t *kernel_data = fully_connected_mve_0_weights; + const int8_t *input_data = fully_connected_mve_0_input; input_dims.n = FULLY_CONNECTED_MVE_0_INPUT_BATCHES; input_dims.w = FULLY_CONNECTED_MVE_0_INPUT_W; @@ -395,7 +403,7 @@ ZTEST(cmsis_nn, test_fully_connected) ctx.buf = malloc(buf_size); ctx.size = buf_size; - arm_status result = arm_fully_connected_s8(&ctx, + arm_cmsis_nn_status result = arm_fully_connected_s8(&ctx, &fc_params, &quant_params, &input_dims, @@ -408,45 +416,43 @@ ZTEST(cmsis_nn, test_fully_connected) output); free(ctx.buf); - zassert_equal(ARM_MATH_SUCCESS, result, ""); + zassert_equal(ARM_CMSIS_NN_SUCCESS, result, ""); zassert_mem_equal(fully_connected_mve_0_output_ref, output, sizeof(output), ""); } -#define MAXPOOLING_2_OUT_CH 5 -#define MAXPOOLING_2_IN_CH 5 -#define MAXPOOLING_2_INPUT_W 12 -#define MAXPOOLING_2_INPUT_H 1 -#define MAXPOOLING_2_DST_SIZE 60 -#define MAXPOOLING_2_INPUT_SIZE 60 +#define MAXPOOLING_2_OUT_CH 5 +#define MAXPOOLING_2_IN_CH 5 +#define MAXPOOLING_2_INPUT_W 12 +#define MAXPOOLING_2_INPUT_H 1 +#define MAXPOOLING_2_DST_SIZE 60 +#define MAXPOOLING_2_INPUT_SIZE 60 #define MAXPOOLING_2_OUT_ACTIVATION_MIN -128 #define MAXPOOLING_2_OUT_ACTIVATION_MAX 127 -#define MAXPOOLING_2_INPUT_BATCHES 1 -#define MAXPOOLING_2_FILTER_X 3 -#define MAXPOOLING_2_FILTER_Y 1 -#define MAXPOOLING_2_STRIDE_X 1 -#define MAXPOOLING_2_STRIDE_Y 2 -#define MAXPOOLING_2_PAD_X 1 -#define MAXPOOLING_2_PAD_Y 0 -#define MAXPOOLING_2_OUTPUT_W 12 -#define MAXPOOLING_2_OUTPUT_H 1 +#define MAXPOOLING_2_INPUT_BATCHES 1 +#define MAXPOOLING_2_FILTER_X 3 +#define MAXPOOLING_2_FILTER_Y 1 +#define MAXPOOLING_2_STRIDE_X 1 +#define MAXPOOLING_2_STRIDE_Y 2 +#define MAXPOOLING_2_PAD_X 1 +#define MAXPOOLING_2_PAD_Y 0 +#define MAXPOOLING_2_OUTPUT_W 12 +#define MAXPOOLING_2_OUTPUT_H 1 const int8_t maxpooling_2_input[60] = { - -16, 32, -16, -48, -16, 16, 64, 0, -112, 80, -64, 48, -64, 80, -16, - -80, -96, 48, 32, 96, 64, 80, 16, -96, 32, -112, -16, -80, -48, 32, - -64, -32, -16, 80, 48, -80, 96, -96, 64, -64, -112, 32, 96, -16, -16, - 96, 0, -16, -16, -32, 64, -96, 96, 96, -48, -64, -16, 32, 16, 64 -}; + 75, -52, -42, -30, 56, 64, 106, -36, 120, -3, 34, -105, 69, 75, -39, + 15, 93, -71, 39, 34, -11, 65, 22, 59, 106, 105, 45, -116, -75, 123, + -65, 75, -61, 13, -25, -123, 59, 110, -65, 86, -108, -107, -17, 38, 27, + -1, -115, -123, 75, -75, 68, 52, 12, -35, 116, -68, 22, 15, 76, -81}; const int8_t maxpooling_2_output_ref[60] = { - 16, 64, 0, -48, 80, 16, 64, 0, 80, 80, 16, 64, 48, 80, 96, - 64, 80, 48, 80, 96, 64, 80, 48, 32, 96, 64, 80, 16, 80, 48, - -64, 96, -16, 80, 48, -64, 96, 96, 80, 48, 96, 96, 96, 64, -16, - 96, 32, 96, 96, -16, 96, 0, 96, 96, 64, 64, -16, 96, 96, 64 -}; + 75, 106, -36, 120, 56, 75, 106, 69, 120, 56, 64, 106, 69, 120, 34, + 34, 93, 69, 75, 106, 105, 93, 22, 59, 123, 105, 75, 22, 59, 123, + 105, 75, 110, 13, 123, -65, 75, 110, 38, 86, -1, 59, 110, 75, 86, + 68, 52, 12, 75, 116, 68, 52, 15, 76, 116, 68, 52, 15, 76, 116}; ZTEST(cmsis_nn, test_max_pool) { - q7_t output[MAXPOOLING_2_DST_SIZE] = { 0 }; + int8_t output[MAXPOOLING_2_DST_SIZE] = {0}; cmsis_nn_context ctx; cmsis_nn_pool_params pool_params; @@ -454,7 +460,7 @@ ZTEST(cmsis_nn, test_max_pool) cmsis_nn_dims filter_dims; cmsis_nn_dims output_dims; - const q7_t *input_data = maxpooling_2_input; + const int8_t *input_data = maxpooling_2_input; input_dims.n = MAXPOOLING_2_INPUT_BATCHES; input_dims.w = MAXPOOLING_2_INPUT_W; @@ -475,24 +481,25 @@ ZTEST(cmsis_nn, test_max_pool) pool_params.activation.max = MAXPOOLING_2_OUT_ACTIVATION_MAX; for (int i = 0; i < REPEAT_NUM; i++) { - arm_status result = arm_max_pool_s8(&ctx, &pool_params, &input_dims, input_data, - &filter_dims, &output_dims, output); + arm_cmsis_nn_status result = + arm_max_pool_s8(&ctx, &pool_params, &input_dims, input_data, &filter_dims, + &output_dims, output); - zassert_equal(ARM_MATH_SUCCESS, result, ""); + zassert_equal(ARM_CMSIS_NN_SUCCESS, result, ""); zassert_mem_equal(maxpooling_2_output_ref, output, sizeof(output), ""); } } -#define SOFTMAX_NUM_ROWS 1 -#define SOFTMAX_ROW_SIZE 5 -#define SOFTMAX_INPUT_MULT 1077952576 -#define SOFTMAX_INPUT_LEFT_SHIFT 23 -#define SOFTMAX_DIFF_MIN -248 -#define SOFTMAX_DST_SIZE 5 +#define SOFTMAX_NUM_ROWS 2 +#define SOFTMAX_ROW_SIZE 5 +#define SOFTMAX_INPUT_MULT 1077952640 +#define SOFTMAX_INPUT_LEFT_SHIFT 19 +#define SOFTMAX_DIFF_MIN -3968 +#define SOFTMAX_DST_SIZE 10 -const q7_t softmax_input[5] = { -80, -48, 16, 0, -96 }; +const int8_t softmax_input[10] = {101, 49, 6, -34, -75, -79, -38, 120, -55, 115}; -const q7_t softmax_output_ref[5] = { -128, -125, 56, -60, -128 }; +const int8_t softmax_output_ref[10] = {-57, -70, -79, -86, -92, -94, -88, -54, -91, -56}; ZTEST(cmsis_nn, test_softmax) { @@ -501,7 +508,7 @@ ZTEST(cmsis_nn, test_softmax) const int32_t mult = SOFTMAX_INPUT_MULT; const int32_t shift = SOFTMAX_INPUT_LEFT_SHIFT; const int32_t diff_min = SOFTMAX_DIFF_MIN; - const q7_t *input_data = softmax_input; + const int8_t *input_data = softmax_input; int8_t output[SOFTMAX_DST_SIZE]; for (int i = 0; i < REPEAT_NUM; i++) { @@ -510,52 +517,46 @@ ZTEST(cmsis_nn, test_softmax) } } -#define SVDF_2_INPUT_OFFSET 0 -#define SVDF_2_OUTPUT_OFFSET 0 -#define SVDF_2_MULTIPLIER_IN 1347440720 -#define SVDF_2_MULTIPLIER_OUT 1073741824 -#define SVDF_2_SHIFT_1 -4 -#define SVDF_2_SHIFT_2 1 -#define SVDF_2_IN_ACTIVATION_MIN -32767 -#define SVDF_2_IN_ACTIVATION_MAX 32767 -#define SVDF_2_RANK 2 -#define SVDF_2_FEATURE_BATCHES 10 -#define SVDF_2_TIME_BATCHES 2 -#define SVDF_2_INPUT_SIZE 7 -#define SVDF_2_DST_SIZE 15 -#define SVDF_2_OUT_ACTIVATION_MIN -128 -#define SVDF_2_OUT_ACTIVATION_MAX 127 -#define SVDF_2_INPUT_BATCHES 3 - -const int32_t svdf_2_biases[5] = { 0, 0, 0, 0, 0 }; - - -const q15_t svdf_2_state[60] = { - 3, 1, -1, 2, 1, 4, 3, 2, 2, 1, 4, -1, -3, 3, 4, 3, 1, -1, 3, 2, - 0, -2, -1, -2, -1, -3, 0, -3, 4, 3, -1, 4, -4, -1, 2, 3, -4, -3, -2, 1, - 1, 4, 3, -2, -3, -2, 4, 0, -2, 1, -2, -3, -4, 2, 0, -2, -3, 0, -1, 0 -}; - -const q7_t svdf_2_weights_feature[70] = { - -4, 0, 2, -2, 1, 1, -1, 0, -1, 2, -1, 1, 1, 3, -3, -2, -2, 3, - 3, -3, 1, 2, 1, -4, 0, 2, -2, -1, 3, 1, 0, 0, 1, -2, 0, 2, - 1, 0, -1, 2, 3, -1, 3, -1, -1, -2, -4, -3, 1, 1, 2, -3, 3, -3, - 0, 0, 2, 0, 2, -1, -1, -3, -3, 1, 2, 2, 3, -2, 3, 1 -}; - -const q15_t svdf_2_weights_time[20] = { - -4, 3, 0, -3, -2, 0, 3, 0, -3, -2, 2, 1, -4, 3, 1, 0, 3, -2, 1, 1 -}; - -const q7_t svdf_2_input_sequence[42] = { - -51, 0, -26, 76, -102, -102, -76, 0, -51, -26, -51, -26, 51, 0, - 51, -102, 51, -102, -76, 51, 76, -26, 26, -51, -76, -26, -102, -76, - -26, 26, 0, 51, 76, 0, 0, 26, -26, 76, -26, 76, 76, 26 -}; - -const q7_t svdf_2_output_ref[15] = { - 80, -19, -61, 17, -17, -3, 6, 30, -84, -4, -24, -11, 35, -128, 19 -}; +#define SVDF_2_MULTIPLIER_IN 1717987072 +#define SVDF_2_MULTIPLIER_OUT 1099511552 +#define SVDF_2_SHIFT_1 -3 +#define SVDF_2_SHIFT_2 -11 +#define SVDF_2_IN_ACTIVATION_MIN -32768 +#define SVDF_2_IN_ACTIVATION_MAX 32767 +#define SVDF_2_RANK 2 +#define SVDF_2_FEATURE_BATCHES 10 +#define SVDF_2_TIME_BATCHES 2 +#define SVDF_2_INPUT_SIZE 7 +#define SVDF_2_DST_SIZE 15 +#define SVDF_2_OUT_ACTIVATION_MIN -128 +#define SVDF_2_OUT_ACTIVATION_MAX 127 +#define SVDF_2_INPUT_BATCHES 3 +#define SVDF_2_INPUT_OFFSET 0 +#define SVDF_2_OUTPUT_OFFSET 0 + +const int32_t svdf_2_biases[5] = {0, 0, 0, 0, 0}; + +const int16_t svdf_2_state[60] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +const int8_t svdf_2_weights_feature[70] = { + 27, 82, -108, -127, 85, 3, -51, 32, 110, -6, -14, -16, 31, 101, + -122, 19, 76, 74, -80, 12, -22, -17, 10, -28, 55, 109, 2, -107, + -4, 72, -65, -59, 36, -69, 105, -97, 25, 38, 110, -121, -88, -126, + -14, 16, -88, -66, 3, -93, 69, -64, 44, 103, 95, -95, 68, -46, + 106, -31, -63, 23, -38, 36, -95, -43, 93, 77, 91, -26, 33, 59}; + +const int16_t svdf_2_weights_time[20] = {-31, -88, -10, -72, -119, -6, -70, 63, -10, 93, + 5, 42, -6, 22, 6, 51, 37, -38, 5, 117}; + +const int8_t svdf_2_input_sequence[42] = { + 29, 81, -38, 17, -116, 43, 119, -127, 74, 115, 9, 118, 7, -56, + -53, -14, -98, 60, -128, 10, 28, -18, 12, -28, -126, 87, -115, -44, + -123, -109, -59, -87, -69, 121, -128, -95, -70, 2, 81, -119, 84, -122}; + +const int8_t svdf_2_output_ref[15] = {-53, 45, 27, -24, -53, 26, -82, -38, + 11, -85, 94, -16, -32, 31, 4}; static bool check_null_bias(const int32_t *bias, int32_t size) { @@ -585,8 +586,8 @@ ZTEST(cmsis_nn, test_svdf) cmsis_nn_per_tensor_quant_params output_quant_params; int8_t output_data[SVDF_2_DST_SIZE]; - const q7_t *weights_feature_data = svdf_2_weights_feature; - const q15_t *weights_time_data = svdf_2_weights_time; + const int8_t *weights_feature_data = svdf_2_weights_feature; + const int16_t *weights_time_data = svdf_2_weights_time; input_dims.n = SVDF_2_INPUT_BATCHES; input_dims.h = SVDF_2_INPUT_SIZE; @@ -616,7 +617,7 @@ ZTEST(cmsis_nn, test_svdf) output_ctx.buf = malloc(scratch_size_out); int8_t *input_data = malloc(input_round_size); - q15_t *state_data = malloc(sizeof(svdf_2_state)); + int16_t *state_data = malloc(sizeof(svdf_2_state)); const bool null_bias = check_null_bias(svdf_2_biases, SVDF_2_DST_SIZE / SVDF_2_INPUT_BATCHES); @@ -625,7 +626,7 @@ ZTEST(cmsis_nn, test_svdf) for (int j = 0; j < number_inputs; j++) { memcpy(input_data, svdf_2_input_sequence + j * input_round_size, input_round_size); - arm_status result = arm_svdf_s8(&input_ctx, + arm_cmsis_nn_status result = arm_svdf_state_s16_s8(&input_ctx, &output_ctx, &svdf_2_params, &input_quant_params, @@ -642,7 +643,7 @@ ZTEST(cmsis_nn, test_svdf) null_bias == true ? NULL : svdf_2_biases, &output_dims, output_data); - zassert_equal(ARM_MATH_SUCCESS, result, ""); + zassert_equal(ARM_CMSIS_NN_SUCCESS, result, ""); } zassert_mem_equal(svdf_2_output_ref, output_data, sizeof(output_data), ""); diff --git a/tests/lib/cmsis_nn/testcase.yaml b/tests/lib/cmsis_nn/testcase.yaml index 0cb8036b186..438c267ef5c 100644 --- a/tests/lib/cmsis_nn/testcase.yaml +++ b/tests/lib/cmsis_nn/testcase.yaml @@ -1,6 +1,6 @@ tests: libraries.cmsis_nn: - filter: CONFIG_CPU_CORTEX_M and TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_CPU_CORTEX_M and CONFIG_FULL_LIBC_SUPPORTED integration_platforms: - frdm_k64f - sam_e70_xplained diff --git a/tests/lib/cpp/cxx/prj.conf b/tests/lib/cpp/cxx/prj.conf index 70945ee8a6e..15ae9ce1ebd 100644 --- a/tests/lib/cpp/cxx/prj.conf +++ b/tests/lib/cpp/cxx/prj.conf @@ -3,7 +3,6 @@ CONFIG_NET_BUF=y CONFIG_ZTEST=y CONFIG_ZTEST_STACK_SIZE=2048 CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=128 -CONFIG_ZTEST_NEW_API=y CONFIG_CRC=y # RTIO diff --git a/tests/lib/cpp/cxx/src/main.cpp b/tests/lib/cpp/cxx/src/main.cpp index 02f7f767efe..43bc14f65ac 100644 --- a/tests/lib/cpp/cxx/src/main.cpp +++ b/tests/lib/cpp/cxx/src/main.cpp @@ -43,7 +43,6 @@ /* drivers/espi_saf.h requires SoC specific header */ #include #include -#include #include #include #include diff --git a/tests/lib/cpp/libcxx/prj.conf b/tests/lib/cpp/libcxx/prj.conf index fff9acb3adc..f6c6a2a9db4 100644 --- a/tests/lib/cpp/libcxx/prj.conf +++ b/tests/lib/cpp/libcxx/prj.conf @@ -3,4 +3,3 @@ CONFIG_STD_CPP17=y CONFIG_ZTEST=y CONFIG_ZTEST_STACK_SIZE=5120 CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=32768 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/lib/devicetree/api/app.overlay b/tests/lib/devicetree/api/app.overlay index 508d84b39b4..64010f0c8ef 100644 --- a/tests/lib/devicetree/api/app.overlay +++ b/tests/lib/devicetree/api/app.overlay @@ -415,6 +415,7 @@ reg = <0xbbbbcccc 0x1000>; interrupt-controller; #interrupt-cells = <2>; + interrupts = <11 0>; }; /* there should only be one of these */ @@ -422,6 +423,7 @@ compatible = "vnd,interrupt-holder"; status = "okay"; interrupts = <30 3 40 5 60 7>; + interrupt-parent = <&test_intc>; interrupt-names = "err", "stat", "done"; }; @@ -483,7 +485,6 @@ test_can0: can@55553333 { compatible = "vnd,can-controller"; reg = < 0x55553333 0x1000 >; - sjw = <1>; sample-point = <875>; bus-speed = <125000>; status = "okay"; @@ -493,7 +494,6 @@ test_can1: can@55554444 { compatible = "vnd,can-controller"; reg = < 0x55554444 0x1000 >; - sjw = <1>; sample-point = <875>; bus-speed = <125000>; status = "okay"; @@ -645,18 +645,6 @@ val = "XA XPLUS XB", "XC XPLUS XD", "XA XMINUS XB", "XC XMINUS XD"; }; - test_mem_ram: memory@aabbccdd { - compatible = "vnd,memory-attr"; - reg = < 0xaabbccdd 0x4000 >; - zephyr,memory-attr = "RAM"; - }; - - test_mem_ram_nocache: memory@44332211 { - compatible = "vnd,memory-attr"; - reg = < 0x44332211 0x2000 >; - zephyr,memory-attr = "RAM_NOCACHE"; - }; - test-mtd@ffeeddcc { reg = < 0x0 0x1000 >; #address-cells = < 1 >; diff --git a/tests/lib/devicetree/api/prj.conf b/tests/lib/devicetree/api/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/lib/devicetree/api/prj.conf +++ b/tests/lib/devicetree/api/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/lib/devicetree/api/src/main.c b/tests/lib/devicetree/api/src/main.c index 906907a0ea1..019f5845a38 100644 --- a/tests/lib/devicetree/api/src/main.c +++ b/tests/lib/devicetree/api/src/main.c @@ -482,18 +482,18 @@ ZTEST(devicetree_api, test_bus) #undef DT_DRV_COMPAT /* - * Make sure the underlying DT_COMPAT_ON_BUS_INTERNAL used by + * Make sure the underlying DT_HAS_COMPAT_ON_BUS_STATUS_OKAY used by * DT_ANY_INST_ON_BUS works without DT_DRV_COMPAT defined. */ - zassert_equal(DT_COMPAT_ON_BUS_INTERNAL(vnd_spi_device, spi), 1); - zassert_equal(DT_COMPAT_ON_BUS_INTERNAL(vnd_spi_device, i2c), 0); + zassert_equal(DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(vnd_spi_device, spi), 1); + zassert_equal(DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(vnd_spi_device, i2c), 0); - zassert_equal(DT_COMPAT_ON_BUS_INTERNAL(vnd_i2c_device, i2c), 1); - zassert_equal(DT_COMPAT_ON_BUS_INTERNAL(vnd_i2c_device, spi), 0); + zassert_equal(DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(vnd_i2c_device, i2c), 1); + zassert_equal(DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(vnd_i2c_device, spi), 0); - zassert_equal(DT_COMPAT_ON_BUS_INTERNAL(vnd_gpio_expander, i2c), 1, + zassert_equal(DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(vnd_gpio_expander, i2c), 1, NULL); - zassert_equal(DT_COMPAT_ON_BUS_INTERNAL(vnd_gpio_expander, spi), 1, + zassert_equal(DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(vnd_gpio_expander, spi), 1, NULL); } @@ -707,6 +707,26 @@ ZTEST(devicetree_api, test_irq) /* DT_IRQN */ zassert_equal(DT_IRQN(TEST_I2C_BUS), 6, ""); + #ifndef CONFIG_MULTI_LEVEL_INTERRUPTS + zassert_equal(DT_IRQN(DT_INST(0, DT_DRV_COMPAT)), 30, ""); + #else + zassert_equal(DT_IRQN(DT_INST(0, DT_DRV_COMPAT)), + ((30 + 1) << CONFIG_1ST_LEVEL_INTERRUPT_BITS) | 11, ""); + #endif + + /* DT_IRQN_BY_IDX */ +#ifndef CONFIG_MULTI_LEVEL_INTERRUPTS + zassert_equal(DT_IRQN_BY_IDX(DT_INST(0, DT_DRV_COMPAT), 0), 30, ""); + zassert_equal(DT_IRQN_BY_IDX(DT_INST(0, DT_DRV_COMPAT), 1), 40, ""); + zassert_equal(DT_IRQN_BY_IDX(DT_INST(0, DT_DRV_COMPAT), 2), 60, ""); +#else + zassert_equal(DT_IRQN_BY_IDX(DT_INST(0, DT_DRV_COMPAT), 0), + ((30 + 1) << CONFIG_1ST_LEVEL_INTERRUPT_BITS) | 11, ""); + zassert_equal(DT_IRQN_BY_IDX(DT_INST(0, DT_DRV_COMPAT), 1), + ((40 + 1) << CONFIG_1ST_LEVEL_INTERRUPT_BITS) | 11, ""); + zassert_equal(DT_IRQN_BY_IDX(DT_INST(0, DT_DRV_COMPAT), 2), + ((60 + 1) << CONFIG_1ST_LEVEL_INTERRUPT_BITS) | 11, ""); +#endif /* DT_INST */ zassert_equal(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT), 1, ""); @@ -738,7 +758,25 @@ ZTEST(devicetree_api, test_irq) zassert_equal(DT_INST_IRQ(0, priority), 3, ""); /* DT_INST_IRQN */ +#ifndef CONFIG_MULTI_LEVEL_INTERRUPTS zassert_equal(DT_INST_IRQN(0), 30, ""); +#else + zassert_equal(DT_INST_IRQN(0), ((30 + 1) << CONFIG_1ST_LEVEL_INTERRUPT_BITS) | 11, ""); +#endif + + /* DT_INST_IRQN_BY_IDX */ +#ifndef CONFIG_MULTI_LEVEL_INTERRUPTS + zassert_equal(DT_INST_IRQN_BY_IDX(0, 0), 30, ""); + zassert_equal(DT_INST_IRQN_BY_IDX(0, 1), 40, ""); + zassert_equal(DT_INST_IRQN_BY_IDX(0, 2), 60, ""); +#else + zassert_equal(DT_INST_IRQN_BY_IDX(0, 0), + ((30 + 1) << CONFIG_1ST_LEVEL_INTERRUPT_BITS) | 11, ""); + zassert_equal(DT_INST_IRQN_BY_IDX(0, 1), + ((40 + 1) << CONFIG_1ST_LEVEL_INTERRUPT_BITS) | 11, ""); + zassert_equal(DT_INST_IRQN_BY_IDX(0, 2), + ((60 + 1) << CONFIG_1ST_LEVEL_INTERRUPT_BITS) | 11, ""); +#endif /* DT_INST_IRQ_HAS_CELL_AT_IDX */ zassert_true(DT_INST_IRQ_HAS_CELL_AT_IDX(0, 0, irq), ""); @@ -2717,70 +2755,6 @@ ZTEST(devicetree_api, test_mbox) DT_NODELABEL(test_mbox_zero_cell)), ""); } -ZTEST(devicetree_api, test_memory_attr) -{ - #define REGION_RAM_ATTR (0xDEDE) - #define REGION_RAM_NOCACHE_ATTR (0xCACA) - - #define TEST_FUNC(p_name, p_base, p_size, p_attr) \ - { .name = (p_name), \ - .base = (p_base), \ - .size = (p_size), \ - .attr = (p_attr), \ - } - - struct vnd_memory_binding { - char *name; - uintptr_t base; - size_t size; - unsigned int attr; - }; - - struct vnd_memory_binding val_apply[] = { - DT_MEMORY_ATTR_APPLY(TEST_FUNC) - }; - - zassert_true(!strcmp(val_apply[0].name, "memory@aabbccdd"), ""); - zassert_equal(val_apply[0].base, 0xaabbccdd, ""); - zassert_equal(val_apply[0].size, 0x4000, ""); - zassert_equal(val_apply[0].attr, 0xDEDE, ""); - - zassert_true(!strcmp(val_apply[1].name, "memory@44332211"), ""); - zassert_equal(val_apply[1].base, 0x44332211, ""); - zassert_equal(val_apply[1].size, 0x2000, ""); - zassert_equal(val_apply[1].attr, 0xCACA, ""); - - #undef TEST_FUNC - #undef REGION_RAM_ATTR - #undef REGION_RAM_NOCACHE_ATTR - - #define TEST_FUNC(node_id) DT_NODE_FULL_NAME(node_id), - - static const char * const val_func[] = { - DT_MEMORY_ATTR_FOREACH_NODE(TEST_FUNC) - }; - - zassert_true(!strcmp(val_func[0], "memory@aabbccdd"), ""); - zassert_true(!strcmp(val_func[1], "memory@44332211"), ""); - - #undef TEST_FUNC - - #define TEST_FUNC(node_id) \ - COND_CODE_1(DT_ENUM_HAS_VALUE(node_id, \ - zephyr_memory_attr, \ - RAM_NOCACHE), \ - (DT_REG_ADDR(node_id)), \ - ()) - - uintptr_t val_filt[] = { - DT_MEMORY_ATTR_FOREACH_NODE(TEST_FUNC) - }; - - zassert_equal(val_filt[0], 0x44332211, ""); - - #undef TEST_FUNC -} - ZTEST(devicetree_api, test_fixed_partitions) { /* Test finding fixed partitions by the 'label' property. */ diff --git a/tests/lib/devicetree/api/testcase.yaml b/tests/lib/devicetree/api/testcase.yaml index d8418201cc4..105f7c73ebf 100644 --- a/tests/lib/devicetree/api/testcase.yaml +++ b/tests/lib/devicetree/api/testcase.yaml @@ -8,5 +8,6 @@ tests: - qemu_x86 - qemu_x86_64 - qemu_cortex_m3 + - qemu_riscv32 integration_platforms: - native_posix diff --git a/tests/lib/devicetree/api_ext/prj.conf b/tests/lib/devicetree/api_ext/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/lib/devicetree/api_ext/prj.conf +++ b/tests/lib/devicetree/api_ext/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/lib/devicetree/devices/prj.conf b/tests/lib/devicetree/devices/prj.conf index fc3755cc035..fa50f0de8c6 100644 --- a/tests/lib/devicetree/devices/prj.conf +++ b/tests/lib/devicetree/devices/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y CONFIG_I2C=n -CONFIG_ZTEST_NEW_API=y CONFIG_DEVICE_DEPS=y CONFIG_CHECK_INIT_PRIORITIES=n diff --git a/tests/lib/devicetree/devices/testcase.yaml b/tests/lib/devicetree/devices/testcase.yaml index 673e2319702..07c99fcdb62 100644 --- a/tests/lib/devicetree/devices/testcase.yaml +++ b/tests/lib/devicetree/devices/testcase.yaml @@ -14,6 +14,7 @@ tests: - bt610 - bl5340_dvk_cpuapp - bl5340_dvk_cpuapp_ns + - m5stack_core2 - mimxrt595_evk_cm33 - nrf9131ek_nrf9131 - nrf9131ek_nrf9131_ns diff --git a/tests/lib/devicetree/memory_region/prj.conf b/tests/lib/devicetree/memory_region/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/lib/devicetree/memory_region/prj.conf +++ b/tests/lib/devicetree/memory_region/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/lib/fdtable/prj.conf b/tests/lib/fdtable/prj.conf index a6c7e5f1d54..90f6fec41c8 100644 --- a/tests/lib/fdtable/prj.conf +++ b/tests/lib/fdtable/prj.conf @@ -1,3 +1,3 @@ CONFIG_ZTEST=y CONFIG_POSIX_API=y -CONFIG_ZTEST_NEW_API=y +CONFIG_FDTABLE=y diff --git a/tests/lib/fdtable/src/main.c b/tests/lib/fdtable/src/main.c index 8a43bd84a3d..f10a4ef115a 100644 --- a/tests/lib/fdtable/src/main.c +++ b/tests/lib/fdtable/src/main.c @@ -133,9 +133,12 @@ ZTEST(fdtable, test_z_free_fd) zassert_equal_ptr(obj, NULL, "obj is not NULL after freeing"); } -static void test_cb(void *fd_ptr) +static void test_cb(void *p1, void *p2, void *p3) { - int fd = POINTER_TO_INT(fd_ptr); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + int fd = POINTER_TO_INT(p1); const struct fd_op_vtable *vtable; int *obj; @@ -163,7 +166,7 @@ ZTEST(fdtable, test_z_fd_multiple_access) k_thread_create(&fd_thread, fd_thread_stack, K_THREAD_STACK_SIZEOF(fd_thread_stack), - (k_thread_entry_t)test_cb, + test_cb, INT_TO_POINTER(shared_fd), NULL, NULL, CONFIG_ZTEST_THREAD_PRIORITY, 0, K_NO_WAIT); diff --git a/tests/lib/fdtable/testcase.yaml b/tests/lib/fdtable/testcase.yaml index 4380327353b..0cc9df820c7 100644 --- a/tests/lib/fdtable/testcase.yaml +++ b/tests/lib/fdtable/testcase.yaml @@ -1,5 +1,5 @@ tests: - libraries.os.fdtable: + libraries.fdtable: tags: fdtable integration_platforms: - qemu_x86 diff --git a/tests/lib/gui/lvgl/prj.conf b/tests/lib/gui/lvgl/prj.conf index 6a784fd28cd..92668655692 100644 --- a/tests/lib/gui/lvgl/prj.conf +++ b/tests/lib/gui/lvgl/prj.conf @@ -1,6 +1,5 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_DISPLAY=y CONFIG_SDL_DISPLAY=n CONFIG_DUMMY_DISPLAY=y @@ -13,7 +12,7 @@ CONFIG_FILE_SYSTEM=y CONFIG_FILE_SYSTEM_LITTLEFS=y CONFIG_LVGL=y -CONFIG_LV_Z_MEM_POOL_NUMBER_BLOCKS=8 +CONFIG_LV_Z_MEM_POOL_SIZE=16384 CONFIG_LV_Z_USE_FILESYSTEM=y CONFIG_LV_MEM_CUSTOM=y CONFIG_LV_USE_LOG=y diff --git a/tests/lib/gui/lvgl/testcase.yaml b/tests/lib/gui/lvgl/testcase.yaml index a2e7cc3e841..4b35bcb7d10 100644 --- a/tests/lib/gui/lvgl/testcase.yaml +++ b/tests/lib/gui/lvgl/testcase.yaml @@ -5,13 +5,13 @@ tests: - gui platform_allow: native_posix_64 libraries.gui.lvgl.dynamic.heap.libc: - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED tags: - display - gui platform_allow: native_posix_64 extra_configs: - - CONFIG_NEWLIB_LIBC=y + - CONFIG_REQUIRES_FULL_LIBC=y - CONFIG_LV_Z_BUFFER_ALLOC_DYNAMIC=y - CONFIG_LV_Z_MEM_POOL_HEAP_LIB_C=y libraries.gui.lvgl.dynamic.pool.sys_heap: @@ -22,8 +22,7 @@ tests: extra_configs: - CONFIG_LV_Z_BUFFER_ALLOC_DYNAMIC=y - CONFIG_LV_Z_MEM_POOL_SYS_HEAP=y - - CONFIG_LV_Z_MEM_POOL_NUMBER_BLOCKS=3 - - CONFIG_LV_Z_MEM_POOL_MAX_SIZE=32768 + - CONFIG_LV_Z_MEM_POOL_SIZE=98304 libraries.gui.lvgl.16bit: tags: - display diff --git a/tests/lib/hash_function/prj.conf b/tests/lib/hash_function/prj.conf index d165fcfc36b..cdf1925fc15 100644 --- a/tests/lib/hash_function/prj.conf +++ b/tests/lib/hash_function/prj.conf @@ -3,7 +3,6 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SYS_HASH_FUNC32=y diff --git a/tests/lib/hash_function/src/main.c b/tests/lib/hash_function/src/main.c index f793b9c72eb..510bd42e4be 100644 --- a/tests/lib/hash_function/src/main.c +++ b/tests/lib/hash_function/src/main.c @@ -6,7 +6,7 @@ #include -#include +#include #include #include diff --git a/tests/lib/hash_map/prj.conf b/tests/lib/hash_map/prj.conf index 3b37f590afb..d7c68435fca 100644 --- a/tests/lib/hash_map/prj.conf +++ b/tests/lib/hash_map/prj.conf @@ -3,10 +3,6 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y - -CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=8192 -CONFIG_NEWLIB_LIBC_MIN_REQUIRED_HEAP_SIZE=8192 CONFIG_SYS_HASH_FUNC32=y CONFIG_SYS_HASH_MAP=y diff --git a/tests/lib/hash_map/testcase.yaml b/tests/lib/hash_map/testcase.yaml index f0540430069..d952bb28887 100644 --- a/tests/lib/hash_map/testcase.yaml +++ b/tests/lib/hash_map/testcase.yaml @@ -10,14 +10,17 @@ common: tests: libraries.hash_map.separate_chaining.djb2: extra_configs: + - CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=8192 - CONFIG_SYS_HASH_MAP_CHOICE_SC=y - CONFIG_SYS_HASH_FUNC32_CHOICE_DJB2=y libraries.hash_map.open_addressing.djb2: extra_configs: + - CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=8192 - CONFIG_SYS_HASH_MAP_CHOICE_OA_LP=y - CONFIG_SYS_HASH_FUNC32_CHOICE_DJB2=y libraries.hash_map.cxx.djb2: - # need newlib for the c++ runtime - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBCPP_SUPPORTED extra_configs: + - CONFIG_NEWLIB_LIBC_MIN_REQUIRED_HEAP_SIZE=8192 + - CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=8192 - CONFIG_SYS_HASH_MAP_CHOICE_CXX=y diff --git a/tests/lib/heap/prj.conf b/tests/lib/heap/prj.conf index 7d81866b9a9..036a06f8b0a 100644 --- a/tests/lib/heap/prj.conf +++ b/tests/lib/heap/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SYS_HEAP_VALIDATE=y CONFIG_SYS_HEAP_RUNTIME_STATS=y CONFIG_SYS_HEAP_LISTENER=y diff --git a/tests/lib/heap/testcase.yaml b/tests/lib/heap/testcase.yaml index b9ded829fa7..8f8a282f09c 100644 --- a/tests/lib/heap/testcase.yaml +++ b/tests/lib/heap/testcase.yaml @@ -12,6 +12,7 @@ tests: - m2gl025_miv - qemu_xtensa - esp32s2_saola + - esp32s2_lolin_mini - esp32s3_devkitm filter: not CONFIG_SOC_NSIM timeout: 480 diff --git a/tests/lib/heap_align/prj.conf b/tests/lib/heap_align/prj.conf index d46d6c74ecf..dd9186e6a50 100644 --- a/tests/lib/heap_align/prj.conf +++ b/tests/lib/heap_align/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SYS_HEAP_VALIDATE=y CONFIG_SYS_HEAP_RUNTIME_STATS=y diff --git a/tests/lib/json/prj.conf b/tests/lib/json/prj.conf index 1242eef6daf..700ea224bba 100644 --- a/tests/lib/json/prj.conf +++ b/tests/lib/json/prj.conf @@ -1,4 +1,3 @@ CONFIG_JSON_LIBRARY=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST=y CONFIG_ZTEST_STACK_SIZE=2048 diff --git a/tests/lib/linear_range/prj.conf b/tests/lib/linear_range/prj.conf index 947f5c96234..bc9922291f5 100644 --- a/tests/lib/linear_range/prj.conf +++ b/tests/lib/linear_range/prj.conf @@ -2,4 +2,3 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/lib/mem_alloc/prj.conf b/tests/lib/mem_alloc/prj.conf index d8d148b1144..73573f7377e 100644 --- a/tests/lib/mem_alloc/prj.conf +++ b/tests/lib/mem_alloc/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=2048 CONFIG_TEST_USERSPACE=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/lib/mem_alloc/prj_negative_testing.conf b/tests/lib/mem_alloc/prj_negative_testing.conf index 780ea37adc2..23ff207b374 100644 --- a/tests/lib/mem_alloc/prj_negative_testing.conf +++ b/tests/lib/mem_alloc/prj_negative_testing.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 CONFIG_TEST_USERSPACE=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/lib/mem_alloc/prj_newlib.conf b/tests/lib/mem_alloc/prj_newlib.conf index c9f0c2eb271..c24854dd3d1 100644 --- a/tests/lib/mem_alloc/prj_newlib.conf +++ b/tests/lib/mem_alloc/prj_newlib.conf @@ -2,4 +2,3 @@ CONFIG_ZTEST=y CONFIG_NEWLIB_LIBC=y CONFIG_NEWLIB_LIBC_ALIGNED_HEAP_SIZE=8192 CONFIG_TEST_USERSPACE=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/lib/mem_alloc/prj_newlibnano.conf b/tests/lib/mem_alloc/prj_newlibnano.conf index 6817a695b5a..74f3bd7d344 100644 --- a/tests/lib/mem_alloc/prj_newlibnano.conf +++ b/tests/lib/mem_alloc/prj_newlibnano.conf @@ -3,4 +3,3 @@ CONFIG_NEWLIB_LIBC=y CONFIG_NEWLIB_LIBC_NANO=y CONFIG_NEWLIB_LIBC_ALIGNED_HEAP_SIZE=2048 CONFIG_TEST_USERSPACE=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/lib/mem_alloc/prj_picolibc.conf b/tests/lib/mem_alloc/prj_picolibc.conf index 090aa34134f..5c6133017c6 100644 --- a/tests/lib/mem_alloc/prj_picolibc.conf +++ b/tests/lib/mem_alloc/prj_picolibc.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y CONFIG_PICOLIBC=y CONFIG_TEST_USERSPACE=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/lib/mem_blocks/prj.conf b/tests/lib/mem_blocks/prj.conf index 9ae9394ba4d..5d303066504 100644 --- a/tests/lib/mem_blocks/prj.conf +++ b/tests/lib/mem_blocks/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SYS_MEM_BLOCKS=y CONFIG_SYS_MEM_BLOCKS_LISTENER=y diff --git a/tests/lib/mem_blocks/src/main.c b/tests/lib/mem_blocks/src/main.c index d7351a12058..4641a6db643 100644 --- a/tests/lib/mem_blocks/src/main.c +++ b/tests/lib/mem_blocks/src/main.c @@ -61,7 +61,8 @@ static bool check_buffer_bound(sys_mem_blocks_t *mem_block, void *ptr) uint8_t *start, *end, *ptr_u8; start = mem_block->buffer; - end = start + (BIT(mem_block->blk_sz_shift) * mem_block->num_blocks); + end = start + (BIT(mem_block->info.blk_sz_shift) * + mem_block->info.num_blocks); ptr_u8 = (uint8_t *)ptr; @@ -155,9 +156,11 @@ static void alloc_free(sys_mem_blocks_t *mem_block, zassert_equal(listener_mem[i], blocks[i][0], "Heap allocated pointer mismatched: %p != %p", listener_mem[i], blocks[i][0]); - zassert_equal(listener_size[i], BIT(mem_block->blk_sz_shift), + zassert_equal(listener_size[i], + BIT(mem_block->info.blk_sz_shift), "Heap allocated sized: %u != %u", - listener_size[i], BIT(mem_block->blk_sz_shift)); + listener_size[i], + BIT(mem_block->info.blk_sz_shift)); #endif } @@ -190,9 +193,11 @@ static void alloc_free(sys_mem_blocks_t *mem_block, zassert_equal(listener_mem[i], blocks[i][0], "Heap allocated pointer mismatched: %p != %p", listener_mem[i], blocks[i][0]); - zassert_equal(listener_size[i], BIT(mem_block->blk_sz_shift), + zassert_equal(listener_size[i], + BIT(mem_block->info.blk_sz_shift), "Heap allocated sized: %u != %u", - listener_size[i], BIT(mem_block->blk_sz_shift)); + listener_size[i], + BIT(mem_block->info.blk_sz_shift)); #endif } } @@ -701,7 +706,8 @@ ZTEST(lib_mem_block, test_mem_block_invalid_params) /* Fake a pointer */ blocks[0] = mem_block_01.buffer + - (BIT(mem_block_01.blk_sz_shift) * mem_block_01.num_blocks); + (BIT(mem_block_01.info.blk_sz_shift) * + mem_block_01.info.num_blocks); ret = sys_mem_blocks_free(&mem_block_01, 1, blocks); zassert_equal(ret, -EFAULT, "sys_mem_blocks_free should fail with -EFAULT but not"); @@ -791,7 +797,8 @@ ZTEST(lib_mem_block, test_multi_mem_block_invalid_params) /* Fake a pointer */ blocks[0] = mem_block_01.buffer + - (BIT(mem_block_01.blk_sz_shift) * mem_block_01.num_blocks); + (BIT(mem_block_01.info.blk_sz_shift) * + mem_block_01.info.num_blocks); ret = sys_multi_mem_blocks_free(&alloc_group, 1, blocks); zassert_equal(ret, -EINVAL, "sys_multi_mem_blocks_free should fail with -EINVAL but not"); diff --git a/tests/lib/mem_blocks_stats/prj.conf b/tests/lib/mem_blocks_stats/prj.conf index 21b9227a8ef..e63280b8eb3 100644 --- a/tests/lib/mem_blocks_stats/prj.conf +++ b/tests/lib/mem_blocks_stats/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SYS_MEM_BLOCKS=y CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS=y diff --git a/tests/lib/mpsc_pbuf/prj.conf b/tests/lib/mpsc_pbuf/prj.conf index c801dcd30a7..92aebaf000c 100644 --- a/tests/lib/mpsc_pbuf/prj.conf +++ b/tests/lib/mpsc_pbuf/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTRESS=y CONFIG_ZTRESS_MAX_THREADS=4 CONFIG_MPSC_PBUF=y diff --git a/tests/lib/mpsc_pbuf/src/concurrent.c b/tests/lib/mpsc_pbuf/src/concurrent.c index f23560785e9..313278d1f61 100644 --- a/tests/lib/mpsc_pbuf/src/concurrent.c +++ b/tests/lib/mpsc_pbuf/src/concurrent.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include LOG_MODULE_REGISTER(test); diff --git a/tests/lib/mpsc_pbuf/src/main.c b/tests/lib/mpsc_pbuf/src/main.c index 2f45903feaf..201eced47f9 100644 --- a/tests/lib/mpsc_pbuf/src/main.c +++ b/tests/lib/mpsc_pbuf/src/main.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #define PUT_EXT_LEN \ ((sizeof(union mpsc_pbuf_generic) + sizeof(void *)) / sizeof(uint32_t)) diff --git a/tests/lib/mpsc_pbuf/testcase.yaml b/tests/lib/mpsc_pbuf/testcase.yaml index 4a9cb29028c..df896168fdf 100644 --- a/tests/lib/mpsc_pbuf/testcase.yaml +++ b/tests/lib/mpsc_pbuf/testcase.yaml @@ -19,7 +19,7 @@ tests: integration_platforms: - native_posix - libraries.mpsc_pbuf_concurrent: + libraries.mpsc_pbuf.concurrent: tags: mpsc_pbuf platform_allow: - qemu_cortex_m3 diff --git a/tests/lib/newlib/heap_listener/prj.conf b/tests/lib/newlib/heap_listener/prj.conf index 8d8ebf99baf..7282777ff1c 100644 --- a/tests/lib/newlib/heap_listener/prj.conf +++ b/tests/lib/newlib/heap_listener/prj.conf @@ -2,4 +2,3 @@ CONFIG_ZTEST=y CONFIG_NEWLIB_LIBC=y CONFIG_NEWLIB_LIBC_NANO=n CONFIG_NEWLIB_LIBC_HEAP_LISTENER=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/lib/newlib/heap_listener/testcase.yaml b/tests/lib/newlib/heap_listener/testcase.yaml index f0aebfe29c8..a4620e464cc 100644 --- a/tests/lib/newlib/heap_listener/testcase.yaml +++ b/tests/lib/newlib/heap_listener/testcase.yaml @@ -4,6 +4,7 @@ tests: - clib - newlib filter: TOOLCHAIN_HAS_NEWLIB == 1 + arch_exclude: posix integration_platforms: - mps2_an385 - qemu_x86 diff --git a/tests/lib/newlib/thread_safety/prj.conf b/tests/lib/newlib/thread_safety/prj.conf index dda7c274a81..3ccbeaa4562 100644 --- a/tests/lib/newlib/thread_safety/prj.conf +++ b/tests/lib/newlib/thread_safety/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NEWLIB_LIBC=y CONFIG_NEWLIB_LIBC_MIN_REQUIRED_HEAP_SIZE=0 CONFIG_TIMESLICE_SIZE=1 diff --git a/tests/lib/newlib/thread_safety/prj_userspace.conf b/tests/lib/newlib/thread_safety/prj_userspace.conf index 89a95db2e72..a2cc6243c39 100644 --- a/tests/lib/newlib/thread_safety/prj_userspace.conf +++ b/tests/lib/newlib/thread_safety/prj_userspace.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NEWLIB_LIBC=y CONFIG_NEWLIB_LIBC_MIN_REQUIRED_HEAP_SIZE=0 CONFIG_TIMESLICE_SIZE=1 diff --git a/tests/lib/newlib/thread_safety/testcase.yaml b/tests/lib/newlib/thread_safety/testcase.yaml index 334e8568eba..91b5d650083 100644 --- a/tests/lib/newlib/thread_safety/testcase.yaml +++ b/tests/lib/newlib/thread_safety/testcase.yaml @@ -1,5 +1,6 @@ common: filter: TOOLCHAIN_HAS_NEWLIB == 1 + arch_exclude: posix tags: - clib - newlib @@ -31,6 +32,7 @@ tests: - userspace min_ram: 192 timeout: 120 + platform_exclude: acrn_ehl_crb # See #61129 libraries.libc.newlib_nano.thread_safety: extra_configs: - CONFIG_NEWLIB_LIBC_NANO=y diff --git a/tests/lib/notify/prj.conf b/tests/lib/notify/prj.conf index ef6676e85d1..a1274832e0e 100644 --- a/tests/lib/notify/prj.conf +++ b/tests/lib/notify/prj.conf @@ -1,4 +1,3 @@ CONFIG_POLL=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NOTIFY=y diff --git a/tests/lib/onoff/prj.conf b/tests/lib/onoff/prj.conf index 4f28b8914ad..73e55c9d3de 100644 --- a/tests/lib/onoff/prj.conf +++ b/tests/lib/onoff/prj.conf @@ -1,4 +1,3 @@ CONFIG_POLL=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ONOFF=y diff --git a/tests/lib/p4workq/prj.conf b/tests/lib/p4workq/prj.conf index 7687c980c2f..3e0283ee446 100644 --- a/tests/lib/p4workq/prj.conf +++ b/tests/lib/p4workq/prj.conf @@ -5,4 +5,3 @@ CONFIG_LOG_DEFAULT_LEVEL=1 # Test whiteboxes the wait_q and expects it to be a dlist CONFIG_WAITQ_SCALABLE=n CONFIG_WAITQ_DUMB=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/lib/p4workq/src/main.c b/tests/lib/p4workq/src/main.c index 5730d2863ac..9567acd5def 100644 --- a/tests/lib/p4workq/src/main.c +++ b/tests/lib/p4workq/src/main.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ #include -#include +#include #include #include diff --git a/tests/lib/ringbuffer/prj.conf b/tests/lib/ringbuffer/prj.conf index 7f65d54518a..f66202abb23 100644 --- a/tests/lib/ringbuffer/prj.conf +++ b/tests/lib/ringbuffer/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTRESS=y CONFIG_TEST_EXTRA_STACK_SIZE=1024 CONFIG_IRQ_OFFLOAD=y diff --git a/tests/lib/ringbuffer/src/concurrent.c b/tests/lib/ringbuffer/src/concurrent.c index b0d221ff95c..60e9aa1c263 100644 --- a/tests/lib/ringbuffer/src/concurrent.c +++ b/tests/lib/ringbuffer/src/concurrent.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include /** diff --git a/tests/lib/ringbuffer/testcase.yaml b/tests/lib/ringbuffer/testcase.yaml index 9314885599d..b2f11681616 100644 --- a/tests/lib/ringbuffer/testcase.yaml +++ b/tests/lib/ringbuffer/testcase.yaml @@ -10,7 +10,7 @@ tests: - native_posix - native_posix_64 - libraries.ring_buffer_concurrent: + libraries.ring_buffer.concurrent: platform_allow: qemu_x86 extra_configs: - CONFIG_SYS_CLOCK_TICKS_PER_SEC=100000 diff --git a/tests/lib/smf/prj.conf b/tests/lib/smf/prj.conf index ad39299c8b9..59f26ef31fe 100644 --- a/tests/lib/smf/prj.conf +++ b/tests/lib/smf/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_LOG=y CONFIG_SMF=y diff --git a/tests/lib/sprintf/prj.conf b/tests/lib/sprintf/prj.conf index 34bba7f359e..084dd06744f 100644 --- a/tests/lib/sprintf/prj.conf +++ b/tests/lib/sprintf/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_FPU=y CONFIG_TEST_USERSPACE=y CONFIG_ZTEST_FATAL_HOOK=y diff --git a/tests/lib/sprintf/prj_new.conf b/tests/lib/sprintf/prj_new.conf index eee90586e22..36945d2c956 100644 --- a/tests/lib/sprintf/prj_new.conf +++ b/tests/lib/sprintf/prj_new.conf @@ -1,6 +1,5 @@ CONFIG_STDOUT_CONSOLE=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_FPU=y CONFIG_TEST_USERSPACE=y CONFIG_ZTEST_FATAL_HOOK=y diff --git a/tests/lib/sprintf/prj_picolibc.conf b/tests/lib/sprintf/prj_picolibc.conf index 205e6bef3c9..2d5cdd1fc8f 100644 --- a/tests/lib/sprintf/prj_picolibc.conf +++ b/tests/lib/sprintf/prj_picolibc.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_PICOLIBC=y CONFIG_PICOLIBC_IO_FLOAT=y CONFIG_ZTEST_STACK_SIZE=2048 diff --git a/tests/lib/sprintf/prj_picolibc_new.conf b/tests/lib/sprintf/prj_picolibc_new.conf index 458e98c26f0..b9490e6301d 100644 --- a/tests/lib/sprintf/prj_picolibc_new.conf +++ b/tests/lib/sprintf/prj_picolibc_new.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_PICOLIBC=y CONFIG_PICOLIBC_IO_FLOAT=y CONFIG_STDOUT_CONSOLE=n diff --git a/tests/lib/spsc_pbuf/prj.conf b/tests/lib/spsc_pbuf/prj.conf index a5478a0e775..8710f041f32 100644 --- a/tests/lib/spsc_pbuf/prj.conf +++ b/tests/lib/spsc_pbuf/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTRESS=y CONFIG_SPSC_PBUF=y diff --git a/tests/lib/spsc_pbuf/src/main.c b/tests/lib/spsc_pbuf/src/main.c index 00332d673ea..55edbc65ede 100644 --- a/tests/lib/spsc_pbuf/src/main.c +++ b/tests/lib/spsc_pbuf/src/main.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #define HDR_LEN sizeof(uint32_t) #define TLEN(len) ROUND_UP(HDR_LEN + len, sizeof(uint32_t)) diff --git a/tests/lib/spsc_pbuf/testcase.yaml b/tests/lib/spsc_pbuf/testcase.yaml index 8dd63eb1b3f..daff2fc46f2 100644 --- a/tests/lib/spsc_pbuf/testcase.yaml +++ b/tests/lib/spsc_pbuf/testcase.yaml @@ -6,7 +6,7 @@ tests: platform_exclude: ast1030_evb timeout: 120 - libraries.spsc_pbuf_cache: + libraries.spsc_pbuf.cache: integration_platforms: - native_posix # Exclude platform which does not link with cache functions @@ -15,7 +15,7 @@ tests: extra_configs: - CONFIG_SPSC_PBUF_CACHE_ALWAYS=y - libraries.spsc_pbuf_nocache: + libraries.spsc_pbuf.nocache.: integration_platforms: - native_posix # Exclude platform which does not link with cache functions @@ -24,7 +24,7 @@ tests: extra_configs: - CONFIG_SPSC_PBUF_CACHE_NEVER=y - libraries.spsc_pbuf_utilization: + libraries.spsc_pbuf.utilization: integration_platforms: - native_posix # Exclude platform which does not link with cache functions @@ -33,7 +33,7 @@ tests: extra_configs: - CONFIG_SPSC_PBUF_UTILIZATION=y - libraries.spsc_pbuf_stress: + libraries.spsc_pbuf.stress: platform_allow: qemu_x86 timeout: 120 extra_configs: diff --git a/tests/lib/sys_util/prj.conf b/tests/lib/sys_util/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/lib/sys_util/prj.conf +++ b/tests/lib/sys_util/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/lib/thrift/ThriftTest/prj.conf b/tests/lib/thrift/ThriftTest/prj.conf index 4d2b145b13c..6619fb8295d 100755 --- a/tests/lib/thrift/ThriftTest/prj.conf +++ b/tests/lib/thrift/ThriftTest/prj.conf @@ -1,5 +1,5 @@ -CONFIG_NEWLIB_LIBC=y -CONFIG_NEWLIB_LIBC_NANO=n +CONFIG_REQUIRES_FULL_LIBC=y +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=65536 # CONFIG_THRIFT Dependencies CONFIG_CPP=y @@ -18,11 +18,11 @@ CONFIG_THRIFT=y # Test dependencies CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_NET_TEST=y CONFIG_NET_DRIVERS=y CONFIG_NET_LOOPBACK=y +CONFIG_NET_TCP_TIME_WAIT_DELAY=100 # Some platforms require relatively large stack sizes. # This can be tuned per-board. diff --git a/tests/lib/thrift/ThriftTest/src/main.cpp b/tests/lib/thrift/ThriftTest/src/main.cpp index b903f3c8a9b..654f74a309b 100644 --- a/tests/lib/thrift/ThriftTest/src/main.cpp +++ b/tests/lib/thrift/ThriftTest/src/main.cpp @@ -141,6 +141,9 @@ static void thrift_test_before(void *data) rv = pthread_create(&context.server_thread, attrp, server_func, nullptr); zassert_equal(0, rv, "pthread_create failed: %d", rv); + /* Give the server thread a chance to start and prepare the socket */ + k_msleep(50); + // set up client context.client = setup_client(); } @@ -160,6 +163,8 @@ static void thrift_test_after(void *data) context.client.reset(); context.server.reset(); + + k_msleep(CONFIG_NET_TCP_TIME_WAIT_DELAY); } ZTEST_SUITE(thrift, NULL, thrift_test_setup, thrift_test_before, thrift_test_after, NULL); diff --git a/tests/lib/thrift/ThriftTest/testcase.yaml b/tests/lib/thrift/ThriftTest/testcase.yaml index 642f76a92e2..cc92bef771e 100644 --- a/tests/lib/thrift/ThriftTest/testcase.yaml +++ b/tests/lib/thrift/ThriftTest/testcase.yaml @@ -2,10 +2,9 @@ common: tags: - thrift - cpp - - newlib modules: - thrift - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED # qemu_x86 exluded due to missing long double functions in SDK # See https://github.com/zephyrproject-rtos/sdk-ng/issues/603 platform_allow: diff --git a/tests/lib/time/prj.conf b/tests/lib/time/prj.conf index 2f34cdff296..aac2e48e364 100644 --- a/tests/lib/time/prj.conf +++ b/tests/lib/time/prj.conf @@ -1,3 +1,3 @@ CONFIG_ZTEST=y CONFIG_POSIX_CLOCK=y -CONFIG_ZTEST_NEW_API=y +CONFIG_PICOLIBC=y diff --git a/tests/lib/time/testcase.yaml b/tests/lib/time/testcase.yaml index d70430fe987..f4e8d91ec1b 100644 --- a/tests/lib/time/testcase.yaml +++ b/tests/lib/time/testcase.yaml @@ -1,7 +1,9 @@ tests: libraries.libc.time: tags: libc - filter: not CONFIG_ARCH_POSIX or CONFIG_NATIVE_POSIX_SLOWDOWN_TO_REAL_TIME timeout: 180 integration_platforms: - mps2_an385 + platform_exclude: + - native_posix + - native_posix_64 diff --git a/tests/misc/check_init_priorities/CMakeLists.txt b/tests/misc/check_init_priorities/CMakeLists.txt index c5e9fec4071..8803b2fa651 100644 --- a/tests/misc/check_init_priorities/CMakeLists.txt +++ b/tests/misc/check_init_priorities/CMakeLists.txt @@ -5,21 +5,20 @@ find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) set(output_file ${PROJECT_BINARY_DIR}/check_init_priorities_output.txt) -add_custom_target( - check_init_priorities_output +add_custom_command( COMMENT "Running check_init_priorities.py" + OUTPUT ${output_file} + DEPENDS ${BYPRODUCT_KERNEL_ELF_NAME} COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/build/check_init_priorities.py --verbose - --build-dir ${PROJECT_BINARY_DIR}/.. + --elf-file=${ZEPHYR_BINARY_DIR}/${KERNEL_ELF_NAME} --output ${output_file} --always-succeed COMMAND ${PYTHON_EXECUTABLE} ${APPLICATION_SOURCE_DIR}/validate_check_init_priorities_output.py ${output_file} - DEPENDS zephyr_pre0 ) -if (TARGET zephyr_pre1) - add_dependencies(zephyr_pre1 check_init_priorities_output) -endif() + +add_custom_target(check_init_priorities_output ALL DEPENDS ${output_file}) project(check_init_priorities) diff --git a/tests/misc/check_init_priorities/boards/native_posix.overlay b/tests/misc/check_init_priorities/boards/native_posix.overlay index d279a6d3f26..0f32c8121a8 100644 --- a/tests/misc/check_init_priorities/boards/native_posix.overlay +++ b/tests/misc/check_init_priorities/boards/native_posix.overlay @@ -34,12 +34,5 @@ reg = <0x11>; supply-gpios = <&test_gpio_0 2 0>; }; - - test_dev_c: test-i2c-dev@12 { - compatible = "vnd,i2c-device"; - status = "okay"; - reg = <0x12>; - supply-gpios = <&test_gpio_0 3 0>; - }; }; }; diff --git a/tests/misc/check_init_priorities/prj.conf b/tests/misc/check_init_priorities/prj.conf index bad7dc092f3..6709862e8d4 100644 --- a/tests/misc/check_init_priorities/prj.conf +++ b/tests/misc/check_init_priorities/prj.conf @@ -1,4 +1 @@ -# Required to force 2 stage linking -CONFIG_DEVICE_DEPS=y - CONFIG_CHECK_INIT_PRIORITIES=n diff --git a/tests/misc/check_init_priorities/src/main.c b/tests/misc/check_init_priorities/src/main.c index a0d9e625a01..a9cf1c472cc 100644 --- a/tests/misc/check_init_priorities/src/main.c +++ b/tests/misc/check_init_priorities/src/main.c @@ -6,19 +6,12 @@ #include -static int device_init(const struct device *dev) -{ - return 0; -} - -DEVICE_DT_DEFINE(DT_INST(0, vnd_gpio_device), device_init, NULL, NULL, NULL, +DEVICE_DT_DEFINE(DT_INST(0, vnd_gpio_device), NULL, NULL, NULL, NULL, PRE_KERNEL_1, 50, NULL); -DEVICE_DT_DEFINE(DT_INST(0, vnd_i2c), device_init, NULL, NULL, NULL, +DEVICE_DT_DEFINE(DT_INST(0, vnd_i2c), NULL, NULL, NULL, NULL, PRE_KERNEL_1, 50, NULL); -DEVICE_DT_DEFINE(DT_INST(0, vnd_i2c_device), device_init, NULL, NULL, NULL, +DEVICE_DT_DEFINE(DT_INST(0, vnd_i2c_device), NULL, NULL, NULL, NULL, PRE_KERNEL_1, 49, NULL); -DEVICE_DT_DEFINE(DT_INST(1, vnd_i2c_device), device_init, NULL, NULL, NULL, +DEVICE_DT_DEFINE(DT_INST(1, vnd_i2c_device), NULL, NULL, NULL, NULL, PRE_KERNEL_1, 50, NULL); -DEVICE_DT_DEFINE(DT_INST(2, vnd_i2c_device), device_init, NULL, NULL, NULL, - PRE_KERNEL_1, 51, NULL); diff --git a/tests/misc/check_init_priorities/validate_check_init_priorities_output.py b/tests/misc/check_init_priorities/validate_check_init_priorities_output.py index 96d98954469..714976e1a09 100755 --- a/tests/misc/check_init_priorities/validate_check_init_priorities_output.py +++ b/tests/misc/check_init_priorities/validate_check_init_priorities_output.py @@ -8,12 +8,11 @@ import sys REFERENCE_OUTPUT = [ - "ERROR: /i2c@11112222/test-i2c-dev@10 PRE_KERNEL_1 49 31 < /gpio@ffff PRE_KERNEL_1 50 29", - "ERROR: /i2c@11112222/test-i2c-dev@10 PRE_KERNEL_1 49 31 < /i2c@11112222 PRE_KERNEL_1 50 30", - "INFO: /i2c@11112222/test-i2c-dev@11 PRE_KERNEL_1 50 32 > /gpio@ffff PRE_KERNEL_1 50 29", - "INFO: /i2c@11112222/test-i2c-dev@11 PRE_KERNEL_1 50 32 > /i2c@11112222 PRE_KERNEL_1 50 30", - "INFO: /i2c@11112222/test-i2c-dev@12 PRE_KERNEL_1 51 33 > /gpio@ffff PRE_KERNEL_1 50 29", - "INFO: /i2c@11112222/test-i2c-dev@12 PRE_KERNEL_1 51 33 > /i2c@11112222 PRE_KERNEL_1 50 30" + "ERROR: Device initialization priority validation failed, the sequence of initialization calls does not match the devicetree dependencies.", + "ERROR: /i2c@11112222/test-i2c-dev@10 is initialized before its dependency /gpio@ffff (PRE_KERNEL_1+0 < PRE_KERNEL_1+1)", + "ERROR: /i2c@11112222/test-i2c-dev@10 is initialized before its dependency /i2c@11112222 (PRE_KERNEL_1+0 < PRE_KERNEL_1+2)", + "INFO: /i2c@11112222/test-i2c-dev@11 PRE_KERNEL_1+3 > /gpio@ffff PRE_KERNEL_1+1", + "INFO: /i2c@11112222/test-i2c-dev@11 PRE_KERNEL_1+3 > /i2c@11112222 PRE_KERNEL_1+2", ] if len(sys.argv) != 2: @@ -23,7 +22,7 @@ output = [] with open(sys.argv[1], "r") as file: for line in file: - if line.startswith("INFO: check_init_priorities build_dir:"): + if line.startswith("INFO: check_init_priorities"): continue output.append(line.strip()) diff --git a/tests/misc/iterable_sections/prj.conf b/tests/misc/iterable_sections/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/misc/iterable_sections/prj.conf +++ b/tests/misc/iterable_sections/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/misc/kconfigoptions/prj.conf b/tests/misc/kconfigoptions/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/misc/kconfigoptions/prj.conf +++ b/tests/misc/kconfigoptions/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/modules/nanopb/CMakeLists.txt b/tests/modules/nanopb/CMakeLists.txt new file mode 100644 index 00000000000..bbe95de0bf2 --- /dev/null +++ b/tests/modules/nanopb/CMakeLists.txt @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(nanopb_tests) + +list(APPEND CMAKE_MODULE_PATH ${ZEPHYR_BASE}/modules/nanopb) +include(nanopb) + +zephyr_nanopb_sources(app proto/simple.proto) + +zephyr_nanopb_sources(app + proto/complex.proto + proto/sub/nested.proto +) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/modules/nanopb/prj.conf b/tests/modules/nanopb/prj.conf new file mode 100644 index 00000000000..139d6ef66fc --- /dev/null +++ b/tests/modules/nanopb/prj.conf @@ -0,0 +1,3 @@ +CONFIG_ZTEST=y + +CONFIG_NANOPB=y diff --git a/tests/modules/nanopb/proto/complex.proto b/tests/modules/nanopb/proto/complex.proto new file mode 100644 index 00000000000..fde97aeeeab --- /dev/null +++ b/tests/modules/nanopb/proto/complex.proto @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 Basalte bv + * + * SPDX-License-Identifier: Apache-2.0 + */ + +syntax = "proto3"; + +import "sub/nested.proto"; + +message ComplexMessage { + NestedMessage nested = 1; +}; diff --git a/tests/modules/nanopb/proto/simple.options b/tests/modules/nanopb/proto/simple.options new file mode 100644 index 00000000000..47c1f05de08 --- /dev/null +++ b/tests/modules/nanopb/proto/simple.options @@ -0,0 +1 @@ +SimpleMessage.buffer max_size:8 fixed_length:true diff --git a/tests/modules/nanopb/proto/simple.proto b/tests/modules/nanopb/proto/simple.proto new file mode 100644 index 00000000000..ff192f8f87a --- /dev/null +++ b/tests/modules/nanopb/proto/simple.proto @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2023 Basalte bv + * + * SPDX-License-Identifier: Apache-2.0 + */ + +syntax = "proto3"; + +message SimpleMessage { + bytes buffer = 1; +}; diff --git a/tests/modules/nanopb/proto/sub/nested.options b/tests/modules/nanopb/proto/sub/nested.options new file mode 100644 index 00000000000..967f27485fe --- /dev/null +++ b/tests/modules/nanopb/proto/sub/nested.options @@ -0,0 +1 @@ +NestedMessage.name max_size:32 diff --git a/tests/modules/nanopb/proto/sub/nested.proto b/tests/modules/nanopb/proto/sub/nested.proto new file mode 100644 index 00000000000..01790b55fa0 --- /dev/null +++ b/tests/modules/nanopb/proto/sub/nested.proto @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Basalte bv + * + * SPDX-License-Identifier: Apache-2.0 + */ + +syntax = "proto3"; + +message NestedMessage { + uint32 id = 1; + string name = 2; +}; diff --git a/tests/modules/nanopb/src/main.c b/tests/modules/nanopb/src/main.c new file mode 100644 index 00000000000..cd68298960e --- /dev/null +++ b/tests/modules/nanopb/src/main.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2023 Basalte bv + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +#include + +#include +#include + +ZTEST(nanopb_tests, test_nanopb_simple) +{ + uint8_t buffer[SimpleMessage_size]; + SimpleMessage msg = SimpleMessage_init_zero; + + for (size_t i = 0; i < sizeof(msg.buffer); ++i) { + msg.buffer[i] = i; + } + + pb_ostream_t ostream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + + zassert_true(pb_encode(&ostream, SimpleMessage_fields, &msg), + "Encoding failed: %s", PB_GET_ERROR(&ostream)); + + /* Sanity check, clear data */ + memset(&msg, 0, sizeof(SimpleMessage)); + + pb_istream_t istream = pb_istream_from_buffer(buffer, ostream.bytes_written); + + zassert_true(pb_decode(&istream, SimpleMessage_fields, &msg), + "Decoding failed: %s", PB_GET_ERROR(&ostream)); + + for (size_t i = 0; i < sizeof(msg.buffer); ++i) { + zassert_equal(msg.buffer[i], i); + } +} + +ZTEST(nanopb_tests, test_nanopb_nested) +{ + uint8_t buffer[ComplexMessage_size]; + ComplexMessage msg = ComplexMessage_init_zero; + + msg.has_nested = true; + msg.nested.id = 42; + strcpy(msg.nested.name, "Test name"); + + pb_ostream_t ostream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + + zassert_true(pb_encode(&ostream, ComplexMessage_fields, &msg), + "Encoding failed: %s", PB_GET_ERROR(&ostream)); + + /* Sanity check, clear data */ + memset(&msg, 0, sizeof(ComplexMessage)); + + pb_istream_t istream = pb_istream_from_buffer(buffer, ostream.bytes_written); + + zassert_true(pb_decode(&istream, ComplexMessage_fields, &msg), + "Decoding failed: %s", PB_GET_ERROR(&istream)); + + zassert_equal(42, msg.nested.id); + zassert_true(msg.has_nested); + zassert_equal(0, strcmp(msg.nested.name, "Test name")); +} + +ZTEST_SUITE(nanopb_tests, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/modules/nanopb/testcase.yaml b/tests/modules/nanopb/testcase.yaml new file mode 100644 index 00000000000..23956de2091 --- /dev/null +++ b/tests/modules/nanopb/testcase.yaml @@ -0,0 +1,9 @@ +tests: + libraries.nanopb: + modules: + - nanopb + tags: + - nanopb + integration_platforms: + - native_posix + - native_posix_64 diff --git a/tests/modules/uoscore/prj.conf b/tests/modules/uoscore/prj.conf index 406324798ea..0282e87b3bb 100644 --- a/tests/modules/uoscore/prj.conf +++ b/tests/modules/uoscore/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=16384 CONFIG_ENTROPY_GENERATOR=y diff --git a/tests/net/6lo/prj.conf b/tests/net/6lo/prj.conf index b52665d1864..ed070a9ce85 100644 --- a/tests/net/6lo/prj.conf +++ b/tests/net/6lo/prj.conf @@ -21,4 +21,3 @@ CONFIG_NET_6LO_CONTEXT=y #Before modifying this value, add respective code in src/main.c CONFIG_NET_MAX_6LO_CONTEXTS=2 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/net/all/prj.conf b/tests/net/all/prj.conf index bb40e71fca1..3538a834048 100644 --- a/tests/net/all/prj.conf +++ b/tests/net/all/prj.conf @@ -7,7 +7,6 @@ CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_LOG_DEFAULT_LEVEL=4 CONFIG_MAX_THREAD_BYTES=4 diff --git a/tests/net/arp/prj.conf b/tests/net/arp/prj.conf index 01ea831dfc2..4e5827b5dbd 100644 --- a/tests/net/arp/prj.conf +++ b/tests/net/arp/prj.conf @@ -15,5 +15,4 @@ CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=3 CONFIG_NET_IPV6=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NET_IF_MAX_IPV4_COUNT=2 diff --git a/tests/net/arp/src/main.c b/tests/net/arp/src/main.c index 79965812286..a196599214f 100644 --- a/tests/net/arp/src/main.c +++ b/tests/net/arp/src/main.c @@ -25,7 +25,7 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_ARP_LOG_LEVEL); #include #include #include -#include +#include #include "arp.h" diff --git a/tests/net/bridge/prj.conf b/tests/net/bridge/prj.conf index 2bc1e019fc2..60457ce7ec4 100644 --- a/tests/net/bridge/prj.conf +++ b/tests/net/bridge/prj.conf @@ -10,4 +10,3 @@ CONFIG_NET_PKT_RX_COUNT=20 CONFIG_NET_BUF_RX_COUNT=20 CONFIG_NET_BUF_TX_COUNT=20 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/net/bridge/src/main.c b/tests/net/bridge/src/main.c index 121c2683273..5bd533fe11b 100644 --- a/tests/net/bridge/src/main.c +++ b/tests/net/bridge/src/main.c @@ -183,8 +183,8 @@ static void get_free_packet_count(void) struct k_mem_slab *rx, *tx; net_pkt_get_info(&rx, &tx, NULL, NULL); - orig_rx_num_blocks = rx->num_blocks; - orig_tx_num_blocks = tx->num_blocks; + orig_rx_num_blocks = rx->info.num_blocks; + orig_tx_num_blocks = tx->info.num_blocks; } static void check_free_packet_count(void) @@ -192,8 +192,8 @@ static void check_free_packet_count(void) struct k_mem_slab *rx, *tx; net_pkt_get_info(&rx, &tx, NULL, NULL); - zassert_equal(rx->num_blocks, orig_rx_num_blocks, ""); - zassert_equal(tx->num_blocks, orig_tx_num_blocks, ""); + zassert_equal(rx->info.num_blocks, orig_rx_num_blocks, ""); + zassert_equal(tx->info.num_blocks, orig_tx_num_blocks, ""); } static void test_iface_setup(void) diff --git a/tests/net/buf/prj.conf b/tests/net/buf/prj.conf index 2a62a683cc4..47e462402b3 100644 --- a/tests/net/buf/prj.conf +++ b/tests/net/buf/prj.conf @@ -4,4 +4,3 @@ CONFIG_HEAP_MEM_POOL_SIZE=4096 #CONFIG_NET_BUF_LOG=y #CONFIG_NET_BUF_LOG_LEVEL_DBG=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/net/buf/src/main.c b/tests/net/buf/src/main.c index 88ec644d4e6..a96c6fe83e2 100644 --- a/tests/net/buf/src/main.c +++ b/tests/net/buf/src/main.c @@ -150,6 +150,8 @@ ZTEST(net_buf_tests, test_net_buf_2) static void test_3_thread(void *arg1, void *arg2, void *arg3) { + ARG_UNUSED(arg3); + struct k_fifo *fifo = (struct k_fifo *)arg1; struct k_sem *sema = (struct k_sem *)arg2; struct net_buf *buf; @@ -192,7 +194,7 @@ ZTEST(net_buf_tests, test_net_buf_3) k_thread_create(&test_3_thread_data, test_3_thread_stack, K_THREAD_STACK_SIZEOF(test_3_thread_stack), - (k_thread_entry_t) test_3_thread, &fifo, &sema, NULL, + test_3_thread, &fifo, &sema, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); zassert_true(k_sem_take(&sema, TEST_TIMEOUT) == 0, diff --git a/tests/net/buf_simple/prj.conf b/tests/net/buf_simple/prj.conf index 2d34630767b..a437510f8d9 100644 --- a/tests/net/buf_simple/prj.conf +++ b/tests/net/buf_simple/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 CONFIG_ASSERT_VERBOSE=y diff --git a/tests/net/checksum_offload/prj.conf b/tests/net/checksum_offload/prj.conf index 41bfa3e27cc..fb86bf9dfac 100644 --- a/tests/net/checksum_offload/prj.conf +++ b/tests/net/checksum_offload/prj.conf @@ -1,9 +1,11 @@ CONFIG_NETWORKING=y CONFIG_NET_TEST=y CONFIG_NET_IPV6=y +CONFIG_NET_IPV6_FRAGMENT=y CONFIG_NET_UDP=y CONFIG_NET_TCP=y CONFIG_NET_IPV4=y +CONFIG_NET_IPV4_FRAGMENT=y CONFIG_NET_ARP=n CONFIG_NET_MAX_CONTEXTS=4 CONFIG_NET_L2_ETHERNET=y @@ -14,14 +16,13 @@ CONFIG_NET_IPV6_DAD=n CONFIG_NET_IPV6_MLD=n CONFIG_NET_PKT_TX_COUNT=15 CONFIG_NET_PKT_RX_COUNT=15 -CONFIG_NET_BUF_RX_COUNT=15 -CONFIG_NET_BUF_TX_COUNT=15 +CONFIG_NET_BUF_RX_COUNT=40 +CONFIG_NET_BUF_TX_COUNT=40 CONFIG_NET_IF_MAX_IPV6_COUNT=2 CONFIG_NET_IF_MAX_IPV4_COUNT=2 CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6 CONFIG_NET_IPV6_ND=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NET_CONFIG_SETTINGS=n CONFIG_NET_SHELL=n diff --git a/tests/net/checksum_offload/src/main.c b/tests/net/checksum_offload/src/main.c index 90beb4deb3c..e9c59695602 100644 --- a/tests/net/checksum_offload/src/main.c +++ b/tests/net/checksum_offload/src/main.c @@ -18,7 +18,7 @@ LOG_MODULE_REGISTER(net_test, NET_LOG_LEVEL); #include #include #include -#include +#include #include @@ -43,6 +43,8 @@ LOG_MODULE_REGISTER(net_test, NET_LOG_LEVEL); #define TEST_PORT 9999 static char *test_data = "Test data to be sent"; +static uint8_t test_data_large[2000]; +static uint8_t verify_buf[2000]; /* Interface 1 addresses */ static struct in6_addr my_addr1 = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0, @@ -52,9 +54,13 @@ static struct in6_addr my_addr1 = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0, static struct in6_addr my_addr2 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1 } } }; -/* Destination address for test packets */ -static struct in6_addr dst_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x2 } } }; +/* Destination address for test packets (interface 1) */ +static struct in6_addr dst_addr1 = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0x2 } } }; + +/* Destination address for test packets (interface 2) */ +static struct in6_addr dst_addr2 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0x2 } } }; /* Extra address is assigned to ll_addr */ static struct in6_addr ll_addr = { { { 0xfe, 0x80, 0x43, 0xb8, 0, 0, 0, 0, @@ -62,8 +68,9 @@ static struct in6_addr ll_addr = { { { 0xfe, 0x80, 0x43, 0xb8, 0, 0, 0, 0, 0x04 } } }; static struct in_addr in4addr_my = { { { 192, 0, 2, 1 } } }; -static struct in_addr in4addr_dst = { { { 192, 168, 1, 1 } } }; +static struct in_addr in4addr_dst = { { { 192, 0, 2, 2 } } }; static struct in_addr in4addr_my2 = { { { 192, 0, 42, 1 } } }; +static struct in_addr in4addr_dst2 = { { { 192, 0, 42, 2 } } }; /* Keep track of all ethernet interfaces. For native_posix board, we need * to increase the count as it has one extra network interface defined in @@ -71,18 +78,19 @@ static struct in_addr in4addr_my2 = { { { 192, 0, 42, 1 } } }; */ static struct net_if *eth_interfaces[2 + IS_ENABLED(CONFIG_ETH_NATIVE_POSIX)]; -static struct net_context *udp_v6_ctx_1; -static struct net_context *udp_v6_ctx_2; -static struct net_context *udp_v4_ctx_1; -static struct net_context *udp_v4_ctx_2; - static bool test_failed; static bool test_started; +static int test_proto; +static bool verify_fragment; static bool start_receiving; +static bool change_chksum; +static int fragment_count; +static int fragment_offset; -static K_SEM_DEFINE(wait_data, 0, UINT_MAX); +static K_SEM_DEFINE(wait_data_off, 0, UINT_MAX); +static K_SEM_DEFINE(wait_data_nonoff, 0, UINT_MAX); -#define WAIT_TIME K_SECONDS(1) +#define WAIT_TIME K_MSEC(100) struct eth_context { struct net_if *iface; @@ -94,6 +102,15 @@ struct eth_context { static struct eth_context eth_context_offloading_disabled; static struct eth_context eth_context_offloading_enabled; +static void verify_test_data_large(uint8_t *buf, size_t offset, size_t len) +{ + zassert(offset + len <= sizeof(test_data_large), "Out of bound data"); + + for (size_t i = 0; i < len; i++) { + zassert_equal(buf[i], test_data_large[offset + i], "Invalid data"); + } +} + static void eth_iface_init(struct net_if *iface) { const struct device *dev = net_if_get_device(iface); @@ -136,6 +153,179 @@ static uint16_t get_udp_chksum(struct net_pkt *pkt) return udp_hdr->chksum; } +static uint16_t get_icmp_chksum(struct net_pkt *pkt) +{ + NET_PKT_DATA_ACCESS_DEFINE(icmp_access, struct net_icmp_hdr); + struct net_icmp_hdr *icmp_hdr; + struct net_pkt_cursor backup; + + net_pkt_set_overwrite(pkt, true); + net_pkt_cursor_backup(pkt, &backup); + net_pkt_cursor_init(pkt); + + /* Move the cursor to the ICMP header */ + if (net_pkt_skip(pkt, sizeof(struct net_eth_hdr) + + net_pkt_ip_hdr_len(pkt) + + net_pkt_ipv6_ext_len(pkt))) { + return 0; + } + + icmp_hdr = (struct net_icmp_hdr *)net_pkt_get_data(pkt, &icmp_access); + if (!icmp_hdr) { + return 0; + } + + net_pkt_cursor_restore(pkt, &backup); + + return icmp_hdr->chksum; +} + +static void test_receiving(struct net_pkt *pkt) +{ + uint16_t port; + uint8_t lladdr[6]; + + DBG("Packet %p received\n", pkt); + + memcpy(lladdr, ((struct net_eth_hdr *)net_pkt_data(pkt))->src.addr, + sizeof(lladdr)); + memcpy(((struct net_eth_hdr *)net_pkt_data(pkt))->src.addr, + ((struct net_eth_hdr *)net_pkt_data(pkt))->dst.addr, + sizeof(lladdr)); + memcpy(((struct net_eth_hdr *)net_pkt_data(pkt))->dst.addr, + lladdr, sizeof(lladdr)); + + net_pkt_skip(pkt, sizeof(struct net_eth_hdr)); + + /* Swap IP src and destination address so that we can receive + * the packet and the stack will not reject it. + */ + if (net_pkt_family(pkt) == AF_INET6) { + NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv6_access, + struct net_ipv6_hdr); + struct net_ipv6_hdr *ipv6_hdr; + struct in6_addr addr; + + ipv6_hdr = (struct net_ipv6_hdr *) + net_pkt_get_data(pkt, &ipv6_access); + zassert_not_null(ipv6_hdr, "Can't access IPv6 header"); + + net_ipv6_addr_copy_raw((uint8_t *)&addr, ipv6_hdr->src); + net_ipv6_addr_copy_raw(ipv6_hdr->src, ipv6_hdr->dst); + net_ipv6_addr_copy_raw(ipv6_hdr->dst, (uint8_t *)&addr); + } else { + NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv4_access, + struct net_ipv4_hdr); + struct net_ipv4_hdr *ipv4_hdr; + struct in_addr addr; + + ipv4_hdr = (struct net_ipv4_hdr *) + net_pkt_get_data(pkt, &ipv4_access); + zassert_not_null(ipv4_hdr, "Can't access IPv4 header"); + + net_ipv4_addr_copy_raw((uint8_t *)&addr, ipv4_hdr->src); + net_ipv4_addr_copy_raw(ipv4_hdr->src, ipv4_hdr->dst); + net_ipv4_addr_copy_raw(ipv4_hdr->dst, (uint8_t *)&addr); + } + + if (!verify_fragment || fragment_count == 1) { + net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) + net_pkt_ip_opts_len(pkt)); + if (test_proto == IPPROTO_UDP) { + NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE( + udp_access, struct net_udp_hdr); + struct net_udp_hdr *udp_hdr; + + udp_hdr = (struct net_udp_hdr *) + net_pkt_get_data(pkt, &udp_access); + zassert_not_null(udp_hdr, "Can't access UDP header"); + + port = udp_hdr->src_port; + udp_hdr->src_port = udp_hdr->dst_port; + udp_hdr->dst_port = port; + + if (change_chksum) { + udp_hdr->chksum++; + } + } else if (test_proto == IPPROTO_ICMP || + test_proto == IPPROTO_ICMPV6) { + NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE( + icmp_access, struct net_icmp_hdr); + struct net_icmp_hdr *icmp_hdr; + + icmp_hdr = (struct net_icmp_hdr *) + net_pkt_get_data(pkt, &icmp_access); + zassert_not_null(icmp_hdr, "Can't access ICMP header"); + + if (change_chksum) { + icmp_hdr->chksum++; + } + } + } + + net_pkt_cursor_init(pkt); + + if (net_recv_data(net_pkt_iface(pkt), + net_pkt_rx_clone(pkt, K_NO_WAIT)) < 0) { + test_failed = true; + zassert_true(false, "Packet %p receive failed\n", pkt); + } +} + +static void test_fragment(struct net_pkt *pkt, bool offloaded) +{ + uint16_t chksum = 0; + size_t data_len; + size_t hdr_offset = sizeof(struct net_eth_hdr) + + net_pkt_ip_hdr_len(pkt) + + net_pkt_ip_opts_len(pkt); + + fragment_count++; + + net_pkt_set_overwrite(pkt, true); + net_pkt_cursor_init(pkt); + + if (start_receiving) { + test_receiving(pkt); + return; + } + + if (fragment_count == 1) { + if (test_proto == IPPROTO_UDP) { + chksum = get_udp_chksum(pkt); + hdr_offset += sizeof(struct net_udp_hdr); + } else if (test_proto == IPPROTO_ICMP || + test_proto == IPPROTO_ICMPV6) { + chksum = get_icmp_chksum(pkt); + hdr_offset += sizeof(struct net_icmp_hdr) + + sizeof(struct net_icmpv6_echo_req); + } + + /* Fragmented packet should have checksum set regardless of + * checksum offloading + */ + zassert_not_equal(chksum, 0, "Checksum missing"); + } + + zassert_true(net_pkt_is_chksum_done(pkt), + "Checksum should me marked as ready on net_pkt"); + + /* Verify that payload has not been altered. */ + data_len = net_pkt_get_len(pkt) - hdr_offset; + net_pkt_skip(pkt, hdr_offset); + net_pkt_read(pkt, verify_buf, data_len); + + verify_test_data_large(verify_buf, fragment_offset, data_len); + fragment_offset += data_len; + + if (fragment_count > 1) { + if (offloaded) { + k_sem_give(&wait_data_off); + } else { + k_sem_give(&wait_data_nonoff); + } + } +} + static int eth_tx_offloading_disabled(const struct device *dev, struct net_pkt *pkt) { @@ -150,67 +340,31 @@ static int eth_tx_offloading_disabled(const struct device *dev, return -ENODATA; } - if (start_receiving) { - struct net_udp_hdr hdr, *udp_hdr; - uint16_t port; - uint8_t lladdr[6]; - - DBG("Packet %p received\n", pkt); - - /* Swap IP src and destination address so that we can receive - * the packet and the stack will not reject it. - */ - if (net_pkt_family(pkt) == AF_INET6) { - struct in6_addr addr; - - net_ipv6_addr_copy_raw((uint8_t *)&addr, NET_IPV6_HDR(pkt)->src); - net_ipv6_addr_copy_raw(NET_IPV6_HDR(pkt)->src, - NET_IPV6_HDR(pkt)->dst); - net_ipv6_addr_copy_raw(NET_IPV6_HDR(pkt)->dst, (uint8_t *)&addr); - } else { - struct in_addr addr; - - net_ipv4_addr_copy_raw((uint8_t *)&addr, NET_IPV4_HDR(pkt)->src); - net_ipv4_addr_copy_raw(NET_IPV4_HDR(pkt)->src, - NET_IPV4_HDR(pkt)->dst); - net_ipv4_addr_copy_raw(NET_IPV4_HDR(pkt)->dst, (uint8_t *)&addr); - } - - udp_hdr = net_udp_get_hdr(pkt, &hdr); - zassert_not_null(udp_hdr, "UDP header missing"); - - port = udp_hdr->src_port; - udp_hdr->src_port = udp_hdr->dst_port; - udp_hdr->dst_port = port; - - memcpy(lladdr, - ((struct net_eth_hdr *)net_pkt_data(pkt))->src.addr, - sizeof(lladdr)); - memcpy(((struct net_eth_hdr *)net_pkt_data(pkt))->src.addr, - ((struct net_eth_hdr *)net_pkt_data(pkt))->dst.addr, - sizeof(lladdr)); - memcpy(((struct net_eth_hdr *)net_pkt_data(pkt))->dst.addr, - lladdr, sizeof(lladdr)); - - if (net_recv_data(net_pkt_iface(pkt), - net_pkt_clone(pkt, K_NO_WAIT)) < 0) { - test_failed = true; - zassert_true(false, "Packet %p receive failed\n", pkt); - } + if (verify_fragment) { + test_fragment(pkt, false); + return 0; + } + if (start_receiving) { + test_receiving(pkt); return 0; } if (test_started) { - uint16_t chksum; + uint16_t chksum = 0; - chksum = get_udp_chksum(pkt); + if (test_proto == IPPROTO_UDP) { + chksum = get_udp_chksum(pkt); + } else if (test_proto == IPPROTO_ICMP || + test_proto == IPPROTO_ICMPV6) { + chksum = get_icmp_chksum(pkt); + } DBG("Chksum 0x%x offloading disabled\n", chksum); - zassert_not_equal(chksum, 0, "Checksum calculated"); + zassert_not_equal(chksum, 0, "Checksum not calculated"); - k_sem_give(&wait_data); + k_sem_give(&wait_data_nonoff); } return 0; @@ -230,16 +384,30 @@ static int eth_tx_offloading_enabled(const struct device *dev, return -ENODATA; } + if (verify_fragment) { + test_fragment(pkt, true); + return 0; + } + + if (start_receiving) { + test_receiving(pkt); + } + if (test_started) { - uint16_t chksum; + uint16_t chksum = 0; - chksum = get_udp_chksum(pkt); + if (test_proto == IPPROTO_UDP) { + chksum = get_udp_chksum(pkt); + } else if (test_proto == IPPROTO_ICMP || + test_proto == IPPROTO_ICMPV6) { + chksum = get_icmp_chksum(pkt); + } DBG("Chksum 0x%x offloading enabled\n", chksum); zassert_equal(chksum, 0, "Checksum calculated"); - k_sem_give(&wait_data); + k_sem_give(&wait_data_off); } return 0; @@ -375,6 +543,7 @@ static void test_eth_setup(void) static void test_address_setup(void) { + struct in_addr netmask = { { { 255, 255, 255, 0 } } }; struct net_if_addr *ifaddr; struct net_if *iface1, *iface2; @@ -409,6 +578,8 @@ static void test_address_setup(void) NET_ADDR_MANUAL, 0); zassert_not_null(ifaddr, "Cannot add IPv4 address"); + net_if_ipv4_set_netmask(iface1, &netmask); + ifaddr = net_if_ipv6_addr_add(iface2, &my_addr2, NET_ADDR_MANUAL, 0); if (!ifaddr) { @@ -423,6 +594,8 @@ static void test_address_setup(void) NET_ADDR_MANUAL, 0); zassert_not_null(ifaddr, "Cannot add IPv4 address"); + net_if_ipv4_set_netmask(iface2, &netmask); + net_if_up(iface1); net_if_up(iface2); @@ -433,7 +606,7 @@ static void test_address_setup(void) test_failed = false; } -static bool add_neighbor(struct net_if *iface, struct in6_addr *addr) +static void add_neighbor(struct net_if *iface, struct in6_addr *addr) { struct net_linkaddr_storage llstorage; struct net_linkaddr lladdr; @@ -455,214 +628,312 @@ static bool add_neighbor(struct net_if *iface, struct in6_addr *addr) if (!nbr) { DBG("Cannot add dst %s to neighbor cache\n", net_sprint_ipv6_addr(addr)); - return false; } - - return true; } -static void test_tx_chksum_offload_disabled_test_v6(void) +static struct net_context *test_udp_context_prepare(sa_family_t family, + bool offloaded, + struct sockaddr *dst_addr) { + struct net_context *net_ctx; struct eth_context *ctx; /* This is interface context */ + struct sockaddr src_addr; + socklen_t addrlen; struct net_if *iface; - int ret, len; - struct sockaddr_in6 dst_addr6 = { - .sin6_family = AF_INET6, - .sin6_port = htons(TEST_PORT), - }; - struct sockaddr_in6 src_addr6 = { - .sin6_family = AF_INET6, - .sin6_port = 0, - }; - - ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, - &udp_v6_ctx_1); - zassert_equal(ret, 0, "Create IPv6 UDP context failed"); - - memcpy(&src_addr6.sin6_addr, &my_addr1, sizeof(struct in6_addr)); - memcpy(&dst_addr6.sin6_addr, &dst_addr, sizeof(struct in6_addr)); - - ret = net_context_bind(udp_v6_ctx_1, (struct sockaddr *)&src_addr6, - sizeof(struct sockaddr_in6)); + int ret; + + if (family == AF_INET6) { + struct sockaddr_in6 *dst_addr6 = + (struct sockaddr_in6 *)dst_addr; + struct sockaddr_in6 *src_addr6 = + (struct sockaddr_in6 *)&src_addr; + + dst_addr6->sin6_family = AF_INET6; + dst_addr6->sin6_port = htons(TEST_PORT); + src_addr6->sin6_family = AF_INET6; + src_addr6->sin6_port = 0; + + if (offloaded) { + memcpy(&src_addr6->sin6_addr, &my_addr2, + sizeof(struct in6_addr)); + memcpy(&dst_addr6->sin6_addr, &dst_addr2, + sizeof(struct in6_addr)); + } else { + memcpy(&src_addr6->sin6_addr, &my_addr1, + sizeof(struct in6_addr)); + memcpy(&dst_addr6->sin6_addr, &dst_addr1, + sizeof(struct in6_addr)); + } + + addrlen = sizeof(struct sockaddr_in6); + } else { + struct sockaddr_in *dst_addr4 = + (struct sockaddr_in *)dst_addr; + struct sockaddr_in *src_addr4 = + (struct sockaddr_in *)&src_addr; + + dst_addr4->sin_family = AF_INET; + dst_addr4->sin_port = htons(TEST_PORT); + src_addr4->sin_family = AF_INET; + src_addr4->sin_port = 0; + + if (offloaded) { + memcpy(&src_addr4->sin_addr, &in4addr_my2, + sizeof(struct in_addr)); + memcpy(&dst_addr4->sin_addr, &in4addr_dst2, + sizeof(struct in_addr)); + } else { + memcpy(&src_addr4->sin_addr, &in4addr_my, + sizeof(struct in_addr)); + memcpy(&dst_addr4->sin_addr, &in4addr_dst, + sizeof(struct in_addr)); + } + + addrlen = sizeof(struct sockaddr_in6); + } + + ret = net_context_get(family, SOCK_DGRAM, IPPROTO_UDP, &net_ctx); + zassert_equal(ret, 0, "Create %s UDP context failed", + family == AF_INET6 ? "IPv6" : "IPv4"); + + ret = net_context_bind(net_ctx, &src_addr, addrlen); zassert_equal(ret, 0, "Context bind failure test failed"); - iface = eth_interfaces[0]; - ctx = net_if_get_device(iface)->data; - zassert_equal_ptr(ð_context_offloading_disabled, ctx, - "eth context mismatch"); + /* Verify iface data */ + if (offloaded) { + iface = eth_interfaces[1]; + ctx = net_if_get_device(iface)->data; + zassert_equal_ptr(ð_context_offloading_enabled, ctx, + "eth context mismatch"); + } else { + iface = eth_interfaces[0]; + ctx = net_if_get_device(iface)->data; + zassert_equal_ptr(ð_context_offloading_disabled, ctx, + "eth context mismatch"); + } - test_started = true; + return net_ctx; +} + +static void test_tx_chksum(sa_family_t family, bool offloaded) +{ + struct k_sem *wait_data = offloaded ? &wait_data_off : &wait_data_nonoff; + socklen_t addrlen = (family == AF_INET6) ? sizeof(struct sockaddr_in6) : + sizeof(struct sockaddr_in); + struct net_context *net_ctx; + struct sockaddr dst_addr; + int ret, len; - ret = add_neighbor(iface, &dst_addr); - zassert_true(ret, "Cannot add neighbor"); + net_ctx = test_udp_context_prepare(family, offloaded, &dst_addr); + zassert_not_null(net_ctx, "Failed to obtain net_ctx"); - len = strlen(test_data); + test_started = true; + test_proto = IPPROTO_UDP; - ret = net_context_sendto(udp_v6_ctx_1, test_data, len, - (struct sockaddr *)&dst_addr6, - sizeof(struct sockaddr_in6), - NULL, K_FOREVER, NULL); + len = strlen(test_data); + ret = net_context_sendto(net_ctx, test_data, len, &dst_addr, + addrlen, NULL, K_FOREVER, NULL); zassert_equal(ret, len, "Send UDP pkt failed (%d)\n", ret); - if (k_sem_take(&wait_data, WAIT_TIME)) { + if (k_sem_take(wait_data, WAIT_TIME)) { DBG("Timeout while waiting interface data\n"); zassert_false(true, "Timeout"); } - net_context_unref(udp_v6_ctx_1); + net_context_unref(net_ctx); } -static void test_tx_chksum_offload_disabled_test_v4(void) +ZTEST(net_chksum_offload, test_tx_chksum_offload_disabled_test_v6) { - struct eth_context *ctx; /* This is interface context */ - struct net_if *iface; - int ret, len; - struct sockaddr_in dst_addr4 = { - .sin_family = AF_INET, - .sin_port = htons(TEST_PORT), - }; - struct sockaddr_in src_addr4 = { - .sin_family = AF_INET, - .sin_port = 0, - }; - - ret = net_context_get(AF_INET, SOCK_DGRAM, IPPROTO_UDP, - &udp_v4_ctx_1); - zassert_equal(ret, 0, "Create IPv4 UDP context failed"); - - memcpy(&src_addr4.sin_addr, &in4addr_my, sizeof(struct in_addr)); - memcpy(&dst_addr4.sin_addr, &in4addr_dst, sizeof(struct in_addr)); - - ret = net_context_bind(udp_v4_ctx_1, (struct sockaddr *)&src_addr4, - sizeof(struct sockaddr_in)); - zassert_equal(ret, 0, "Context bind failure test failed"); + test_tx_chksum(AF_INET6, false); +} - iface = eth_interfaces[0]; - ctx = net_if_get_device(iface)->data; - zassert_equal_ptr(ð_context_offloading_disabled, ctx, - "eth context mismatch"); +ZTEST(net_chksum_offload, test_tx_chksum_offload_disabled_test_v4) +{ + test_tx_chksum(AF_INET, false); +} - len = strlen(test_data); +ZTEST(net_chksum_offload, test_tx_chksum_offload_enabled_test_v6) +{ + test_tx_chksum(AF_INET6, true); +} - test_started = true; +ZTEST(net_chksum_offload, test_tx_chksum_offload_enabled_test_v4) +{ + test_tx_chksum(AF_INET, true); +} + +static void test_tx_chksum_udp_frag(sa_family_t family, bool offloaded) +{ + struct k_sem *wait_data = offloaded ? &wait_data_off : &wait_data_nonoff; + socklen_t addrlen = (family == AF_INET6) ? sizeof(struct sockaddr_in6) : + sizeof(struct sockaddr_in); + struct net_context *net_ctx; + struct sockaddr dst_addr; + int ret, len; + + net_ctx = test_udp_context_prepare(family, offloaded, &dst_addr); + zassert_not_null(net_ctx, "Failed to obtain net_ctx"); - ret = add_neighbor(iface, &dst_addr); - zassert_true(ret, "Cannot add neighbor"); + test_started = true; + test_proto = IPPROTO_UDP; + verify_fragment = true; - ret = net_context_sendto(udp_v4_ctx_1, test_data, len, - (struct sockaddr *)&dst_addr4, - sizeof(struct sockaddr_in), - NULL, K_FOREVER, NULL); + len = sizeof(test_data_large); + ret = net_context_sendto(net_ctx, test_data_large, len, &dst_addr, + addrlen, NULL, K_FOREVER, NULL); zassert_equal(ret, len, "Send UDP pkt failed (%d)\n", ret); - if (k_sem_take(&wait_data, WAIT_TIME)) { + if (k_sem_take(wait_data, WAIT_TIME)) { DBG("Timeout while waiting interface data\n"); zassert_false(true, "Timeout"); } - net_context_unref(udp_v4_ctx_1); + net_context_unref(net_ctx); } -static void test_tx_chksum_offload_enabled_test_v6(void) +ZTEST(net_chksum_offload, test_tx_chksum_offload_disabled_test_v6_udp_frag) { - struct eth_context *ctx; /* This is interface context */ - struct net_if *iface; - int ret, len; - struct sockaddr_in6 dst_addr6 = { - .sin6_family = AF_INET6, - .sin6_port = htons(TEST_PORT), - }; - struct sockaddr_in6 src_addr6 = { - .sin6_family = AF_INET6, - .sin6_port = 0, - }; - - ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, - &udp_v6_ctx_2); - zassert_equal(ret, 0, "Create IPv6 UDP context failed"); - - memcpy(&src_addr6.sin6_addr, &my_addr2, sizeof(struct in6_addr)); - memcpy(&dst_addr6.sin6_addr, &dst_addr, sizeof(struct in6_addr)); - - ret = net_context_bind(udp_v6_ctx_2, (struct sockaddr *)&src_addr6, - sizeof(struct sockaddr_in6)); - zassert_equal(ret, 0, "Context bind failure test failed"); + test_tx_chksum_udp_frag(AF_INET6, false); +} - iface = eth_interfaces[1]; - ctx = net_if_get_device(iface)->data; - zassert_equal_ptr(ð_context_offloading_enabled, ctx, - "eth context mismatch"); +ZTEST(net_chksum_offload, test_tx_chksum_offload_disabled_test_v4_udp_frag) +{ + test_tx_chksum_udp_frag(AF_INET, false); +} - len = strlen(test_data); +ZTEST(net_chksum_offload, test_tx_chksum_offload_enabled_test_v6_udp_frag) +{ + test_tx_chksum_udp_frag(AF_INET6, true); +} - test_started = true; +ZTEST(net_chksum_offload, test_tx_chksum_offload_enabled_test_v4_udp_frag) +{ + test_tx_chksum_udp_frag(AF_INET, true); +} - ret = add_neighbor(iface, &dst_addr); - zassert_true(ret, "Cannot add neighbor"); +static int dummy_icmp_handler(struct net_icmp_ctx *ctx, + struct net_pkt *pkt, + struct net_icmp_ip_hdr *hdr, + struct net_icmp_hdr *icmp_hdr, + void *user_data) +{ + ARG_UNUSED(ctx); + ARG_UNUSED(pkt); + ARG_UNUSED(hdr); + ARG_UNUSED(icmp_hdr); + ARG_UNUSED(user_data); - ret = net_context_sendto(udp_v6_ctx_2, test_data, len, - (struct sockaddr *)&dst_addr6, - sizeof(struct sockaddr_in6), - NULL, K_FOREVER, NULL); - zassert_equal(ret, len, "Send UDP pkt failed (%d)\n", ret); + return 0; +} - if (k_sem_take(&wait_data, WAIT_TIME)) { - DBG("Timeout while waiting interface data\n"); - zassert_false(true, "Timeout"); +static void test_icmp_init(sa_family_t family, bool offloaded, + struct sockaddr *dst_addr, struct net_if **iface) +{ + if (family == AF_INET6) { + struct sockaddr_in6 *dst_addr6 = + (struct sockaddr_in6 *)dst_addr; + + dst_addr6->sin6_family = AF_INET6; + + if (offloaded) { + memcpy(&dst_addr6->sin6_addr, &dst_addr2, + sizeof(struct in6_addr)); + } else { + memcpy(&dst_addr6->sin6_addr, &dst_addr1, + sizeof(struct in6_addr)); + } + } else { + struct sockaddr_in *dst_addr4 = + (struct sockaddr_in *)dst_addr; + + dst_addr4->sin_family = AF_INET; + + if (offloaded) { + memcpy(&dst_addr4->sin_addr, &in4addr_dst2, + sizeof(struct in_addr)); + } else { + memcpy(&dst_addr4->sin_addr, &in4addr_dst, + sizeof(struct in_addr)); + } } - net_context_unref(udp_v6_ctx_2); + if (offloaded) { + *iface = eth_interfaces[1]; + } else { + *iface = eth_interfaces[0]; + } } -static void test_tx_chksum_offload_enabled_test_v4(void) +static void test_tx_chksum_icmp_frag(sa_family_t family, bool offloaded) { - struct eth_context *ctx; /* This is interface context */ + struct k_sem *wait_data = offloaded ? &wait_data_off : &wait_data_nonoff; + struct net_icmp_ping_params params = { 0 }; + struct net_icmp_ctx ctx; + struct sockaddr dst_addr; struct net_if *iface; - int ret, len; - struct sockaddr_in dst_addr4 = { - .sin_family = AF_INET, - .sin_port = htons(TEST_PORT), - }; - struct sockaddr_in src_addr4 = { - .sin_family = AF_INET, - .sin_port = 0, - }; - - ret = net_context_get(AF_INET, SOCK_DGRAM, IPPROTO_UDP, - &udp_v4_ctx_2); - zassert_equal(ret, 0, "Create IPv4 UDP context failed"); - - memcpy(&src_addr4.sin_addr, &in4addr_my2, sizeof(struct in_addr)); - memcpy(&dst_addr4.sin_addr, &in4addr_dst, sizeof(struct in_addr)); - - ret = net_context_bind(udp_v4_ctx_2, (struct sockaddr *)&src_addr4, - sizeof(struct sockaddr_in)); - zassert_equal(ret, 0, "Context bind failure test failed"); + int ret; - iface = eth_interfaces[1]; - ctx = net_if_get_device(iface)->data; - zassert_equal_ptr(ð_context_offloading_enabled, ctx, - "eth context mismatch"); + test_icmp_init(family, offloaded, &dst_addr, &iface); - len = strlen(test_data); + ret = net_icmp_init_ctx(&ctx, 0, 0, dummy_icmp_handler); + zassert_equal(ret, 0, "Cannot init ICMP (%d)", ret); test_started = true; + test_proto = (family == AF_INET6) ? IPPROTO_ICMPV6 : IPPROTO_ICMP; + verify_fragment = true; - ret = add_neighbor(iface, &dst_addr); - zassert_true(ret, "Cannot add neighbor"); + params.data = test_data_large; + params.data_size = sizeof(test_data_large); + ret = net_icmp_send_echo_request(&ctx, iface, &dst_addr, ¶ms, NULL); + zassert_equal(ret, 0, "Cannot send ICMP Echo-Request (%d)", ret); - ret = net_context_sendto(udp_v4_ctx_2, test_data, len, - (struct sockaddr *)&dst_addr4, - sizeof(struct sockaddr_in), - NULL, K_FOREVER, NULL); - zassert_equal(ret, len, "Send UDP pkt failed (%d)\n", ret); - - if (k_sem_take(&wait_data, WAIT_TIME)) { + if (k_sem_take(wait_data, WAIT_TIME)) { DBG("Timeout while waiting interface data\n"); zassert_false(true, "Timeout"); } - net_context_unref(udp_v4_ctx_2); + ret = net_icmp_cleanup_ctx(&ctx); + zassert_equal(ret, 0, "Cannot cleanup ICMP (%d)", ret); +} + +ZTEST(net_chksum_offload, test_tx_chksum_offload_disabled_test_v6_icmp_frag) +{ + test_tx_chksum_icmp_frag(AF_INET6, false); +} + +ZTEST(net_chksum_offload, test_tx_chksum_offload_disabled_test_v4_icmp_frag) +{ + test_tx_chksum_icmp_frag(AF_INET, false); +} + +ZTEST(net_chksum_offload, test_tx_chksum_offload_enabled_test_v6_icmp_frag) +{ + test_tx_chksum_icmp_frag(AF_INET6, true); +} + +ZTEST(net_chksum_offload, test_tx_chksum_offload_enabled_test_v4_icmp_frag) +{ + test_tx_chksum_icmp_frag(AF_INET, true); +} + +static void test_fragment_rx_udp(struct net_pkt *pkt, + union net_proto_header *proto_hdr) +{ + size_t hdr_offset = net_pkt_ip_hdr_len(pkt) + + net_pkt_ip_opts_len(pkt) + + sizeof(struct net_udp_hdr); + size_t data_len = net_pkt_get_len(pkt) - hdr_offset; + + /* In case of fragmented packets, checksum shall be present/verified + * regardless. + */ + zassert_not_equal(proto_hdr->udp->chksum, 0, "Checksum is not set"); + zassert_equal(net_calc_verify_chksum_udp(pkt), 0, "Incorrect checksum"); + + /* Verify that packet content has not been altered */ + net_pkt_read(pkt, verify_buf, data_len); + verify_test_data_large(verify_buf, 0, data_len); } static void recv_cb_offload_disabled(struct net_context *context, @@ -673,7 +944,13 @@ static void recv_cb_offload_disabled(struct net_context *context, void *user_data) { zassert_not_null(proto_hdr->udp, "UDP header missing"); - zassert_not_equal(proto_hdr->udp->chksum, 0, "Checksum is not set"); + + if (verify_fragment) { + test_fragment_rx_udp(pkt, proto_hdr); + } else { + zassert_not_equal(proto_hdr->udp->chksum, 0, "Checksum is not set"); + zassert_equal(net_calc_verify_chksum_udp(pkt), 0, "Incorrect checksum"); + } if (net_pkt_family(pkt) == AF_INET) { struct net_ipv4_hdr *ipv4 = NET_IPV4_HDR(pkt); @@ -682,7 +959,7 @@ static void recv_cb_offload_disabled(struct net_context *context, "IPv4 checksum is not set"); } - k_sem_give(&wait_data); + k_sem_give(&wait_data_nonoff); net_pkt_unref(pkt); } @@ -695,268 +972,383 @@ static void recv_cb_offload_enabled(struct net_context *context, void *user_data) { zassert_not_null(proto_hdr->udp, "UDP header missing"); - zassert_equal(proto_hdr->udp->chksum, 0, "Checksum is set"); - if (net_pkt_family(pkt) == AF_INET) { - struct net_ipv4_hdr *ipv4 = NET_IPV4_HDR(pkt); + if (verify_fragment) { + test_fragment_rx_udp(pkt, proto_hdr); + } else { + zassert_equal(proto_hdr->udp->chksum, 0, "Checksum is set"); - zassert_equal(ipv4->chksum, 0, "IPv4 checksum is set"); + if (net_pkt_family(pkt) == AF_INET) { + struct net_ipv4_hdr *ipv4 = NET_IPV4_HDR(pkt); + + zassert_equal(ipv4->chksum, 0, "IPv4 checksum is set"); + } } - k_sem_give(&wait_data); + k_sem_give(&wait_data_off); net_pkt_unref(pkt); } -static void test_rx_chksum_offload_disabled_test_v6(void) +static void test_rx_chksum(sa_family_t family, bool offloaded) { - struct eth_context *ctx; /* This is interface context */ - struct net_if *iface; + struct k_sem *wait_data = offloaded ? &wait_data_off : &wait_data_nonoff; + net_context_recv_cb_t cb = offloaded ? recv_cb_offload_enabled : + recv_cb_offload_disabled; + socklen_t addrlen = (family == AF_INET6) ? sizeof(struct sockaddr_in6) : + sizeof(struct sockaddr_in); + struct net_context *net_ctx; + struct sockaddr dst_addr; int ret, len; - struct sockaddr_in6 dst_addr6 = { - .sin6_family = AF_INET6, - .sin6_port = htons(TEST_PORT), - }; - struct sockaddr_in6 src_addr6 = { - .sin6_family = AF_INET6, - .sin6_port = 0, - }; - - ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, - &udp_v6_ctx_1); - zassert_equal(ret, 0, "Create IPv6 UDP context failed"); - - memcpy(&src_addr6.sin6_addr, &my_addr1, sizeof(struct in6_addr)); - memcpy(&dst_addr6.sin6_addr, &dst_addr, sizeof(struct in6_addr)); - - ret = net_context_bind(udp_v6_ctx_1, (struct sockaddr *)&src_addr6, - sizeof(struct sockaddr_in6)); - zassert_equal(ret, 0, "Context bind failure test failed"); - iface = eth_interfaces[0]; - ctx = net_if_get_device(iface)->data; - zassert_equal_ptr(ð_context_offloading_disabled, ctx, - "eth context mismatch"); - - len = strlen(test_data); + net_ctx = test_udp_context_prepare(family, offloaded, &dst_addr); + zassert_not_null(net_ctx, "Failed to obtain net_ctx"); test_started = true; + test_proto = IPPROTO_UDP; start_receiving = true; - ret = net_context_recv(udp_v6_ctx_1, recv_cb_offload_disabled, - K_NO_WAIT, NULL); + ret = net_context_recv(net_ctx, cb, K_NO_WAIT, NULL); zassert_equal(ret, 0, "Recv UDP failed (%d)\n", ret); - start_receiving = false; - - ret = net_context_sendto(udp_v6_ctx_1, test_data, len, - (struct sockaddr *)&dst_addr6, - sizeof(struct sockaddr_in6), - NULL, K_FOREVER, NULL); + len = strlen(test_data); + ret = net_context_sendto(net_ctx, test_data, len, &dst_addr, + addrlen, NULL, K_FOREVER, NULL); zassert_equal(ret, len, "Send UDP pkt failed (%d)\n", ret); - if (k_sem_take(&wait_data, WAIT_TIME)) { + if (k_sem_take(wait_data, WAIT_TIME)) { DBG("Timeout while waiting interface data\n"); zassert_false(true, "Timeout"); } /* Let the receiver to receive the packets */ k_sleep(K_MSEC(10)); + + net_context_unref(net_ctx); } -static void test_rx_chksum_offload_disabled_test_v4(void) +ZTEST(net_chksum_offload, test_rx_chksum_offload_disabled_test_v6) { - struct eth_context *ctx; /* This is interface context */ - struct net_if *iface; - int ret, len; - struct sockaddr_in dst_addr4 = { - .sin_family = AF_INET, - .sin_port = htons(TEST_PORT), - }; - struct sockaddr_in src_addr4 = { - .sin_family = AF_INET, - .sin_port = 0, - }; - - ret = net_context_get(AF_INET, SOCK_DGRAM, IPPROTO_UDP, - &udp_v4_ctx_1); - zassert_equal(ret, 0, "Create IPv4 UDP context failed"); - - memcpy(&src_addr4.sin_addr, &in4addr_my, sizeof(struct in_addr)); - memcpy(&dst_addr4.sin_addr, &in4addr_dst, sizeof(struct in_addr)); - - ret = net_context_bind(udp_v4_ctx_1, (struct sockaddr *)&src_addr4, - sizeof(struct sockaddr_in)); - zassert_equal(ret, 0, "Context bind failure test failed"); + test_rx_chksum(AF_INET6, false); +} + +ZTEST(net_chksum_offload, test_rx_chksum_offload_disabled_test_v4) +{ + test_rx_chksum(AF_INET, false); +} - iface = eth_interfaces[0]; - ctx = net_if_get_device(iface)->data; - zassert_equal_ptr(ð_context_offloading_disabled, ctx, - "eth context mismatch"); +ZTEST(net_chksum_offload, test_rx_chksum_offload_enabled_test_v6) +{ + test_rx_chksum(AF_INET6, true); +} - len = strlen(test_data); +ZTEST(net_chksum_offload, test_rx_chksum_offload_enabled_test_v4) +{ + test_rx_chksum(AF_INET, true); +} + +static void test_rx_chksum_udp_frag(sa_family_t family, bool offloaded) +{ + struct k_sem *wait_data = offloaded ? &wait_data_off : &wait_data_nonoff; + net_context_recv_cb_t cb = offloaded ? recv_cb_offload_enabled : + recv_cb_offload_disabled; + socklen_t addrlen = (family == AF_INET6) ? sizeof(struct sockaddr_in6) : + sizeof(struct sockaddr_in); + struct net_context *net_ctx; + struct sockaddr dst_addr; + int ret, len; + + net_ctx = test_udp_context_prepare(family, offloaded, &dst_addr); + zassert_not_null(net_ctx, "Failed to obtain net_ctx"); test_started = true; + test_proto = IPPROTO_UDP; start_receiving = true; + verify_fragment = true; - ret = net_context_recv(udp_v4_ctx_1, recv_cb_offload_disabled, - K_NO_WAIT, NULL); + ret = net_context_recv(net_ctx, cb, K_NO_WAIT, NULL); zassert_equal(ret, 0, "Recv UDP failed (%d)\n", ret); - start_receiving = false; - - ret = net_context_sendto(udp_v4_ctx_1, test_data, len, - (struct sockaddr *)&dst_addr4, - sizeof(struct sockaddr_in), - NULL, K_FOREVER, NULL); + len = sizeof(test_data_large); + ret = net_context_sendto(net_ctx, test_data_large, len, &dst_addr, + addrlen, NULL, K_FOREVER, NULL); zassert_equal(ret, len, "Send UDP pkt failed (%d)\n", ret); - if (k_sem_take(&wait_data, WAIT_TIME)) { + if (k_sem_take(wait_data, WAIT_TIME)) { DBG("Timeout while waiting interface data\n"); zassert_false(true, "Timeout"); } /* Let the receiver to receive the packets */ k_sleep(K_MSEC(10)); + + net_context_unref(net_ctx); } -static void test_rx_chksum_offload_enabled_test_v6(void) +ZTEST(net_chksum_offload, test_rx_chksum_offload_disabled_test_v6_udp_frag) { - struct eth_context *ctx; /* This is interface context */ - struct net_if *iface; - int ret, len; - struct sockaddr_in6 dst_addr6 = { - .sin6_family = AF_INET6, - .sin6_port = htons(TEST_PORT), - }; - struct sockaddr_in6 src_addr6 = { - .sin6_family = AF_INET6, - .sin6_port = 0, - }; - - ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, - &udp_v6_ctx_2); - zassert_equal(ret, 0, "Create IPv6 UDP context failed"); - - memcpy(&src_addr6.sin6_addr, &my_addr2, sizeof(struct in6_addr)); - memcpy(&dst_addr6.sin6_addr, &dst_addr, sizeof(struct in6_addr)); - - ret = net_context_bind(udp_v6_ctx_2, (struct sockaddr *)&src_addr6, - sizeof(struct sockaddr_in6)); - zassert_equal(ret, 0, "Context bind failure test failed"); + test_rx_chksum_udp_frag(AF_INET6, false); +} - iface = net_if_ipv6_select_src_iface(&dst_addr6.sin6_addr); - ctx = net_if_get_device(iface)->data; - zassert_equal_ptr(ð_context_offloading_enabled, ctx, - "eth context mismatch"); +ZTEST(net_chksum_offload, test_rx_chksum_offload_disabled_test_v4_udp_frag) +{ + test_rx_chksum_udp_frag(AF_INET, false); +} - len = strlen(test_data); +ZTEST(net_chksum_offload, test_rx_chksum_offload_enabled_test_v6_udp_frag) +{ + test_rx_chksum_udp_frag(AF_INET6, true); +} + +ZTEST(net_chksum_offload, test_rx_chksum_offload_enabled_test_v4_udp_frag) +{ + test_rx_chksum_udp_frag(AF_INET, true); +} + +static void test_rx_chksum_udp_frag_bad(sa_family_t family, bool offloaded) +{ + struct k_sem *wait_data = offloaded ? &wait_data_off : &wait_data_nonoff; + net_context_recv_cb_t cb = offloaded ? recv_cb_offload_enabled : + recv_cb_offload_disabled; + socklen_t addrlen = (family == AF_INET6) ? sizeof(struct sockaddr_in6) : + sizeof(struct sockaddr_in); + struct net_context *net_ctx; + struct sockaddr dst_addr; + int ret, len; + + net_ctx = test_udp_context_prepare(family, offloaded, &dst_addr); + zassert_not_null(net_ctx, "Failed to obtain net_ctx"); test_started = true; + test_proto = IPPROTO_UDP; start_receiving = true; + verify_fragment = true; + change_chksum = true; - ret = net_context_recv(udp_v6_ctx_2, recv_cb_offload_enabled, - K_NO_WAIT, NULL); + ret = net_context_recv(net_ctx, cb, K_NO_WAIT, NULL); zassert_equal(ret, 0, "Recv UDP failed (%d)\n", ret); - ret = net_context_sendto(udp_v6_ctx_2, test_data, len, - (struct sockaddr *)&dst_addr6, - sizeof(struct sockaddr_in6), - NULL, K_FOREVER, NULL); + len = sizeof(test_data_large); + ret = net_context_sendto(net_ctx, test_data_large, len, &dst_addr, + addrlen, NULL, K_FOREVER, NULL); zassert_equal(ret, len, "Send UDP pkt failed (%d)\n", ret); - if (k_sem_take(&wait_data, WAIT_TIME)) { - DBG("Timeout while waiting interface data\n"); - zassert_false(true, "Timeout"); + if (k_sem_take(wait_data, WAIT_TIME) == 0) { + DBG("Packet with bad chksum should be dropped\n"); + zassert_false(true, "Packet received"); } /* Let the receiver to receive the packets */ k_sleep(K_MSEC(10)); + + net_context_unref(net_ctx); } -static void test_rx_chksum_offload_enabled_test_v4(void) +ZTEST(net_chksum_offload, test_tx_chksum_offload_disabled_test_v6_udp_frag_bad) { - struct eth_context *ctx; /* This is interface context */ + test_rx_chksum_udp_frag_bad(AF_INET6, false); +} + +ZTEST(net_chksum_offload, test_tx_chksum_offload_disabled_test_v4_udp_frag_bad) +{ + test_rx_chksum_udp_frag_bad(AF_INET, false); +} + +ZTEST(net_chksum_offload, test_tx_chksum_offload_enabled_test_v6_udp_frag_bad) +{ + test_rx_chksum_udp_frag_bad(AF_INET6, true); +} + +ZTEST(net_chksum_offload, test_tx_chksum_offload_enabled_test_v4_udp_frag_bad) +{ + test_rx_chksum_udp_frag_bad(AF_INET, true); +} + +static int icmp_handler(struct net_icmp_ctx *ctx, + struct net_pkt *pkt, + struct net_icmp_ip_hdr *hdr, + struct net_icmp_hdr *icmp_hdr, + void *user_data) +{ + struct k_sem *wait_data = user_data; + + size_t hdr_offset = net_pkt_ip_hdr_len(pkt) + + net_pkt_ip_opts_len(pkt) + + sizeof(struct net_icmp_hdr) + + sizeof(struct net_icmpv6_echo_req); + size_t data_len = net_pkt_get_len(pkt) - hdr_offset; + + /* In case of fragmented packets, checksum shall be present/verified + * regardless. + */ + zassert_not_equal(icmp_hdr->chksum, 0, "Checksum is not set"); + + if (test_proto == IPPROTO_ICMPV6) { + zassert_equal(net_calc_chksum_icmpv6(pkt), 0, "Incorrect checksum"); + } else { + zassert_equal(net_calc_chksum_icmpv4(pkt), 0, "Incorrect checksum"); + } + + /* Verify that packet content has not been altered */ + net_pkt_set_overwrite(pkt, true); + net_pkt_cursor_init(pkt); + net_pkt_skip(pkt, hdr_offset); + net_pkt_read(pkt, verify_buf, data_len); + verify_test_data_large(verify_buf, 0, data_len); + + k_sem_give(wait_data); + + return 0; +} + +static void test_rx_chksum_icmp_frag(sa_family_t family, bool offloaded) +{ + struct k_sem *wait_data = offloaded ? &wait_data_off : &wait_data_nonoff; + struct net_icmp_ping_params params = { 0 }; + struct net_icmp_ctx ctx; + struct sockaddr dst_addr; struct net_if *iface; - int ret, len; - struct sockaddr_in dst_addr4 = { - .sin_family = AF_INET, - .sin_port = htons(TEST_PORT), - }; - struct sockaddr_in src_addr4 = { - .sin_family = AF_INET, - .sin_port = 0, - }; - - ret = net_context_get(AF_INET, SOCK_DGRAM, IPPROTO_UDP, - &udp_v4_ctx_2); - zassert_equal(ret, 0, "Create IPv4 UDP context failed"); - - memcpy(&src_addr4.sin_addr, &in4addr_my2, sizeof(struct in_addr)); - memcpy(&dst_addr4.sin_addr, &in4addr_dst, sizeof(struct in_addr)); - - ret = net_context_bind(udp_v4_ctx_2, (struct sockaddr *)&src_addr4, - sizeof(struct sockaddr_in)); - zassert_equal(ret, 0, "Context bind failure test failed"); + int ret; - iface = eth_interfaces[1]; - ctx = net_if_get_device(iface)->data; - zassert_equal_ptr(ð_context_offloading_enabled, ctx, - "eth context mismatch"); + test_icmp_init(family, offloaded, &dst_addr, &iface); - len = strlen(test_data); + ret = net_icmp_init_ctx(&ctx, + family == AF_INET6 ? NET_ICMPV6_ECHO_REPLY : + NET_ICMPV4_ECHO_REPLY, + 0, icmp_handler); + zassert_equal(ret, 0, "Cannot init ICMP (%d)", ret); test_started = true; + test_proto = (family == AF_INET6) ? IPPROTO_ICMPV6 : IPPROTO_ICMP; start_receiving = true; + verify_fragment = true; - ret = net_context_recv(udp_v4_ctx_2, recv_cb_offload_enabled, - K_NO_WAIT, NULL); - zassert_equal(ret, 0, "Recv UDP failed (%d)\n", ret); - - ret = net_context_sendto(udp_v4_ctx_2, test_data, len, - (struct sockaddr *)&dst_addr4, - sizeof(struct sockaddr_in), - NULL, K_FOREVER, NULL); - zassert_equal(ret, len, "Send UDP pkt failed (%d)\n", ret); + params.data = test_data_large; + params.data_size = sizeof(test_data_large); + ret = net_icmp_send_echo_request(&ctx, iface, &dst_addr, ¶ms, + wait_data); + zassert_equal(ret, 0, "Cannot send ICMP Echo-Request (%d)", ret); - if (k_sem_take(&wait_data, WAIT_TIME)) { + if (k_sem_take(wait_data, WAIT_TIME)) { DBG("Timeout while waiting interface data\n"); zassert_false(true, "Timeout"); } - /* Let the receiver to receive the packets */ - k_sleep(K_MSEC(10)); + ret = net_icmp_cleanup_ctx(&ctx); + zassert_equal(ret, 0, "Cannot cleanup ICMP (%d)", ret); } -static void *net_chksum_offload_tests_setup(void) +ZTEST(net_chksum_offload, test_rx_chksum_offload_disabled_test_v6_icmp_frag) { - test_eth_setup(); - test_address_setup(); - return NULL; + test_rx_chksum_icmp_frag(AF_INET6, false); } -ZTEST(net_chksum_offload, test_chksum_offload_disabled_v4) +ZTEST(net_chksum_offload, test_rx_chksum_offload_disabled_test_v4_icmp_frag) { - test_tx_chksum_offload_disabled_test_v4(); - test_rx_chksum_offload_disabled_test_v4(); + test_rx_chksum_icmp_frag(AF_INET, false); } -ZTEST(net_chksum_offload, test_chksum_offload_enabled_v4) +ZTEST(net_chksum_offload, test_rx_chksum_offload_enabled_test_v6_icmp_frag) { - test_tx_chksum_offload_enabled_test_v4(); - test_rx_chksum_offload_enabled_test_v4(); + test_rx_chksum_icmp_frag(AF_INET6, true); } -ZTEST(net_chksum_offload, test_chksum_offload_disabled_v6) +ZTEST(net_chksum_offload, test_rx_chksum_offload_enabled_test_v4_icmp_frag) { - test_tx_chksum_offload_disabled_test_v6(); - test_rx_chksum_offload_disabled_test_v6(); + test_rx_chksum_icmp_frag(AF_INET, true); } -ZTEST(net_chksum_offload, test_chksum_offload_enabled_v6) +static void test_rx_chksum_icmp_frag_bad(sa_family_t family, bool offloaded) { - test_tx_chksum_offload_enabled_test_v6(); - test_rx_chksum_offload_enabled_test_v6(); + struct k_sem *wait_data = offloaded ? &wait_data_off : &wait_data_nonoff; + struct net_icmp_ping_params params = { 0 }; + struct net_icmp_ctx ctx; + struct sockaddr dst_addr; + struct net_if *iface; + int ret; + + test_icmp_init(family, offloaded, &dst_addr, &iface); + + ret = net_icmp_init_ctx(&ctx, + family == AF_INET6 ? NET_ICMPV6_ECHO_REPLY : + NET_ICMPV4_ECHO_REPLY, + 0, icmp_handler); + zassert_equal(ret, 0, "Cannot init ICMP (%d)", ret); + + test_started = true; + test_proto = (family == AF_INET6) ? IPPROTO_ICMPV6 : IPPROTO_ICMP; + start_receiving = true; + verify_fragment = true; + change_chksum = true; + + params.data = test_data_large; + params.data_size = sizeof(test_data_large); + ret = net_icmp_send_echo_request(&ctx, iface, &dst_addr, ¶ms, + wait_data); + zassert_equal(ret, 0, "Cannot send ICMP Echo-Request (%d)", ret); + + if (k_sem_take(wait_data, WAIT_TIME) == 0) { + DBG("Packet with bad chksum should be dropped\n"); + zassert_false(true, "Packet received"); + } + + ret = net_icmp_cleanup_ctx(&ctx); + zassert_equal(ret, 0, "Cannot cleanup ICMP (%d)", ret); +} + +ZTEST(net_chksum_offload, test_rx_chksum_offload_disabled_test_v6_icmp_frag_bad) +{ + test_rx_chksum_icmp_frag_bad(AF_INET6, false); +} + +ZTEST(net_chksum_offload, test_rx_chksum_offload_disabled_test_v4_icmp_frag_bad) +{ + test_rx_chksum_icmp_frag_bad(AF_INET, false); +} + +ZTEST(net_chksum_offload, test_rx_chksum_offload_enabled_test_v6_icmp_frag_bad) +{ + test_rx_chksum_icmp_frag_bad(AF_INET6, true); +} + +ZTEST(net_chksum_offload, test_rx_chksum_offload_enabled_test_v4_icmp_frag_bad) +{ + test_rx_chksum_icmp_frag_bad(AF_INET, true); +} + +static void *net_chksum_offload_tests_setup(void) +{ + test_eth_setup(); + test_address_setup(); + + add_neighbor(eth_interfaces[0], &dst_addr1); + add_neighbor(eth_interfaces[1], &dst_addr2); + + for (size_t i = 0; i < sizeof(test_data_large); i++) { + test_data_large[i] = (uint8_t)i; + } + + return NULL; +} + +static void net_chksum_offload_tests_before(void *fixture) +{ + ARG_UNUSED(fixture); + + k_sem_reset(&wait_data_off); + k_sem_reset(&wait_data_nonoff); + + test_failed = false; + test_started = false; + start_receiving = false; + verify_fragment = false; + change_chksum = false; + fragment_count = 0; + fragment_offset = 0; + test_proto = 0; + + memset(verify_buf, 0, sizeof(verify_buf)); } -ZTEST_SUITE(net_chksum_offload, NULL, net_chksum_offload_tests_setup, NULL, NULL, NULL); +ZTEST_SUITE(net_chksum_offload, NULL, net_chksum_offload_tests_setup, + net_chksum_offload_tests_before, NULL, NULL); diff --git a/tests/net/conn_mgr_conn/prj.conf b/tests/net/conn_mgr_conn/prj.conf index ec6b62f6be3..cc845d23a6f 100644 --- a/tests/net/conn_mgr_conn/prj.conf +++ b/tests/net/conn_mgr_conn/prj.conf @@ -20,7 +20,6 @@ CONFIG_NET_MAX_NEXTHOPS=8 CONFIG_NET_IPV6_MAX_NEIGHBORS=8 CONFIG_NET_IPV6_ND=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NET_IF_MAX_IPV4_COUNT=6 CONFIG_NET_IF_MAX_IPV6_COUNT=6 CONFIG_TEST_USERSPACE=y diff --git a/tests/net/conn_mgr_conn/testcase.yaml b/tests/net/conn_mgr_conn/testcase.yaml index 07bb325cb0a..ff78e1dc721 100644 --- a/tests/net/conn_mgr_conn/testcase.yaml +++ b/tests/net/conn_mgr_conn/testcase.yaml @@ -2,7 +2,7 @@ common: min_ram: 16 depends_on: netif tests: - net.conn_mgr_conn: + net.conn_mgr.conn: tags: - net - iface diff --git a/tests/net/conn_mgr_monitor/prj.conf b/tests/net/conn_mgr_monitor/prj.conf index 1e60d8327ed..376150b993e 100644 --- a/tests/net/conn_mgr_monitor/prj.conf +++ b/tests/net/conn_mgr_monitor/prj.conf @@ -19,10 +19,10 @@ CONFIG_NET_MAX_NEXTHOPS=8 CONFIG_NET_IPV6_MAX_NEIGHBORS=8 CONFIG_NET_IPV6_ND=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NET_IF_MAX_IPV4_COUNT=6 CONFIG_NET_IF_MAX_IPV6_COUNT=6 CONFIG_TEST_USERSPACE=y +CONFIG_NET_MGMT_EVENT_STACK_SIZE=1024 # Enable for help debugging this test suite: # CONFIG_NET_LOG=y diff --git a/tests/net/conn_mgr_monitor/testcase.yaml b/tests/net/conn_mgr_monitor/testcase.yaml index 64ce1efacec..ac6b5ad3c61 100644 --- a/tests/net/conn_mgr_monitor/testcase.yaml +++ b/tests/net/conn_mgr_monitor/testcase.yaml @@ -3,9 +3,9 @@ common: depends_on: netif tags: net iface tests: - net.conn_mgr_nodad: + net.conn_mgr.nodad: extra_configs: - CONFIG_NET_IPV6_DAD=n - net.conn_mgr_dad: + net.conn_mgr.dad: extra_configs: - CONFIG_NET_IPV6_DAD=y diff --git a/tests/net/context/prj.conf b/tests/net/context/prj.conf index 241bb9f0ade..0b8954cda5d 100644 --- a/tests/net/context/prj.conf +++ b/tests/net/context/prj.conf @@ -21,4 +21,3 @@ CONFIG_NET_PKT_RX_COUNT=5 CONFIG_NET_BUF_RX_COUNT=10 CONFIG_NET_BUF_TX_COUNT=10 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/net/context/src/main.c b/tests/net/context/src/main.c index e6f69f00bd6..e3596f236c8 100644 --- a/tests/net/context/src/main.c +++ b/tests/net/context/src/main.c @@ -17,7 +17,7 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_CONTEXT_LOG_LEVEL); #include #include #include -#include +#include #include @@ -789,10 +789,11 @@ static void recv_cb_timeout(struct net_context *context, net_pkt_unref(pkt); } -void timeout_thread(struct net_context *ctx, void *param2, void *param3) +void timeout_thread(void *p1, void *p2, void *p3) { - int family = POINTER_TO_INT(param2); - int32_t timeout = POINTER_TO_INT(param3); + struct net_context *ctx = p1; + int family = POINTER_TO_INT(p2); + int32_t timeout = POINTER_TO_INT(p3); int ret; ret = net_context_recv(ctx, recv_cb_timeout, K_MSEC(timeout), @@ -818,7 +819,7 @@ void timeout_thread(struct net_context *ctx, void *param2, void *param3) static k_tid_t start_timeout_v6_thread(int32_t timeout) { return k_thread_create(&thread_data, thread_stack, STACKSIZE, - (k_thread_entry_t)timeout_thread, + timeout_thread, udp_v6_ctx, INT_TO_POINTER(AF_INET6), INT_TO_POINTER(timeout), K_PRIO_COOP(7), 0, K_NO_WAIT); @@ -827,7 +828,7 @@ static k_tid_t start_timeout_v6_thread(int32_t timeout) static k_tid_t start_timeout_v4_thread(int32_t timeout) { return k_thread_create(&thread_data, thread_stack, STACKSIZE, - (k_thread_entry_t)timeout_thread, + timeout_thread, udp_v4_ctx, INT_TO_POINTER(AF_INET), INT_TO_POINTER(timeout), K_PRIO_COOP(7), 0, K_NO_WAIT); diff --git a/tests/net/dhcpv4/prj.conf b/tests/net/dhcpv4/prj.conf index cb83ac03418..5b126f90a14 100644 --- a/tests/net/dhcpv4/prj.conf +++ b/tests/net/dhcpv4/prj.conf @@ -26,7 +26,6 @@ CONFIG_NET_UDP_CHECKSUM=n CONFIG_MAIN_STACK_SIZE=3072 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NET_DHCPV4_INITIAL_DELAY_MAX=2 diff --git a/tests/net/dhcpv6/CMakeLists.txt b/tests/net/dhcpv6/CMakeLists.txt new file mode 100644 index 00000000000..82400500ea7 --- /dev/null +++ b/tests/net/dhcpv6/CMakeLists.txt @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(dhcpv6) + +target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/net/ip) +target_sources(app PRIVATE src/main.c) + +zephyr_compile_definitions(CONFIG_NET_DHCPV6) +zephyr_compile_definitions(CONFIG_NET_DHCPV6_LOG_LEVEL=LOG_LEVEL_ERR) diff --git a/tests/net/dhcpv6/prj.conf b/tests/net/dhcpv6/prj.conf new file mode 100644 index 00000000000..0c7e5c319ea --- /dev/null +++ b/tests/net/dhcpv6/prj.conf @@ -0,0 +1,17 @@ +CONFIG_NET_TEST=y +CONFIG_ZTEST=y + +CONFIG_ENTROPY_GENERATOR=y +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_NETWORKING=y +CONFIG_NET_L2_DUMMY=y +CONFIG_NET_IPV6=y +CONFIG_NET_IPV6_ND=n +CONFIG_NET_IPV6_DAD=n +CONFIG_NET_IPV6_MLD=n +CONFIG_NET_UDP=y +CONFIG_NET_TC_TX_COUNT=1 + +CONFIG_NET_MGMT=y +CONFIG_NET_MGMT_EVENT=y +CONFIG_NET_MGMT_EVENT_INFO=y diff --git a/tests/net/dhcpv6/src/main.c b/tests/net/dhcpv6/src/main.c new file mode 100644 index 00000000000..80046c96ec9 --- /dev/null +++ b/tests/net/dhcpv6/src/main.c @@ -0,0 +1,1267 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "../../../subsys/net/ip/dhcpv6.c" + +static struct in6_addr test_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0x1 } } }; +static struct in6_addr test_prefix = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 } } }; +static uint8_t test_prefix_len = 64; +static uint8_t test_preference; +static struct net_dhcpv6_duid_storage test_serverid; + +typedef void (*test_dhcpv6_pkt_fn_t)(struct net_if *iface, + struct net_pkt *pkt); + +typedef int (*test_dhcpv6_options_fn_t)(struct net_if *iface, + struct net_pkt *pkt, + enum dhcpv6_msg_type msg_type); + +struct test_dhcpv6_context { + uint8_t mac[sizeof(struct net_eth_addr)]; + struct net_if *iface; + test_dhcpv6_pkt_fn_t test_fn; + struct k_sem tx_sem; + struct k_sem exchange_complete_sem; + bool reset_dhcpv6; +}; + +struct test_dhcpv6_context test_ctx; + +static void test_iface_init(struct net_if *iface) +{ + struct test_dhcpv6_context *ctx = net_if_get_device(iface)->data; + + /* Generate and assign MAC. */ + /* 00-00-5E-00-53-xx Documentation RFC 7042 */ + ctx->mac[0] = 0x00; + ctx->mac[1] = 0x00; + ctx->mac[2] = 0x5E; + ctx->mac[3] = 0x00; + ctx->mac[4] = 0x53; + ctx->mac[5] = 0x00; + + net_if_set_link_addr(iface, ctx->mac, sizeof(ctx->mac), NET_LINK_ETHERNET); +} + +static int test_send(const struct device *dev, struct net_pkt *pkt) +{ + struct test_dhcpv6_context *ctx = dev->data; + + if (ctx->test_fn != NULL) { + ctx->test_fn(net_pkt_iface(pkt), pkt); + } + + k_sem_give(&ctx->tx_sem); + + return 0; +} + +static struct dummy_api test_if_api = { + .iface_api.init = test_iface_init, + .send = test_send, +}; + +NET_DEVICE_INIT(test_dhcpv6, "test_dhcpv6", NULL, NULL, &test_ctx, NULL, + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &test_if_api, + DUMMY_L2, NET_L2_GET_CTX_TYPE(DUMMY_L2), NET_IPV6_MTU); + +static void set_dhcpv6_test_fn(test_dhcpv6_pkt_fn_t test_fn) +{ + test_ctx.test_fn = test_fn; +} + +static void set_test_addr_on_iface(struct net_if *iface) +{ + memcpy(&test_ctx.iface->config.dhcpv6.addr, &test_addr, + sizeof(test_ctx.iface->config.dhcpv6.addr)); + memcpy(&test_ctx.iface->config.dhcpv6.prefix, &test_prefix, + sizeof(test_ctx.iface->config.dhcpv6.prefix)); + test_ctx.iface->config.dhcpv6.prefix_len = test_prefix_len; +} + +static void clear_test_addr_on_iface(struct net_if *iface) +{ + memset(&test_ctx.iface->config.dhcpv6.addr, 0, + sizeof(test_ctx.iface->config.dhcpv6.addr)); + memset(&test_ctx.iface->config.dhcpv6.prefix, 0, + sizeof(test_ctx.iface->config.dhcpv6.prefix)); + test_ctx.iface->config.dhcpv6.prefix_len = 0; +} + +static void generate_fake_server_duid(void) +{ + struct net_dhcpv6_duid_storage *serverid = &test_serverid; + struct dhcpv6_duid_ll *duid_ll = + (struct dhcpv6_duid_ll *)&serverid->duid.buf; + uint8_t fake_mac[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; + + memset(serverid, 0, sizeof(*serverid)); + + UNALIGNED_PUT(htons(DHCPV6_DUID_TYPE_LL), &serverid->duid.type); + UNALIGNED_PUT(htons(DHCPV6_HARDWARE_ETHERNET_TYPE), &duid_ll->hw_type); + memcpy(duid_ll->ll_addr, fake_mac, sizeof(fake_mac)); + + serverid->length = DHCPV6_DUID_LL_HEADER_SIZE + sizeof(fake_mac); +} + +static void set_fake_server_duid(struct net_if *iface) +{ + memcpy(&iface->config.dhcpv6.serverid, &test_serverid, + sizeof(test_serverid)); +} + +#define TEST_MSG_SIZE 256 + +static struct net_pkt *test_dhcpv6_create_message( + struct net_if *iface, enum dhcpv6_msg_type msg_type, + test_dhcpv6_options_fn_t set_options_fn) +{ + struct in6_addr *local_addr; + struct net_pkt *pkt; + + local_addr = net_if_ipv6_get_ll(iface, NET_ADDR_ANY_STATE); + if (local_addr == NULL) { + return NULL; + } + + pkt = net_pkt_alloc_with_buffer(iface, TEST_MSG_SIZE, AF_INET6, + IPPROTO_UDP, K_FOREVER); + if (pkt == NULL) { + return NULL; + } + + if (net_ipv6_create(pkt, local_addr, local_addr) < 0 || + net_udp_create(pkt, htons(DHCPV6_SERVER_PORT), + htons(DHCPV6_CLIENT_PORT)) < 0) { + goto fail; + } + + dhcpv6_generate_tid(iface); + + if (dhcpv6_add_header(pkt, msg_type, iface->config.dhcpv6.tid) < 0) { + goto fail; + } + + if (set_options_fn(iface, pkt, msg_type) < 0) { + goto fail; + } + + net_pkt_cursor_init(pkt); + net_ipv6_finalize(pkt, IPPROTO_UDP); + net_pkt_cursor_init(pkt); + + return pkt; + +fail: + net_pkt_unref(pkt); + + return NULL; +} + +static void *dhcpv6_tests_setup(void) +{ + struct in6_addr lladdr; + + test_ctx.iface = net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY)); + + net_ipv6_addr_create_iid(&lladdr, net_if_get_link_addr(test_ctx.iface)); + (void)net_if_ipv6_addr_add(test_ctx.iface, &lladdr, NET_ADDR_AUTOCONF, 0); + + k_sem_init(&test_ctx.tx_sem, 0, 1); + k_sem_init(&test_ctx.exchange_complete_sem, 0, 1); + + generate_fake_server_duid(); + + return NULL; +} + +static void dhcpv6_tests_before(void *fixture) +{ + ARG_UNUSED(fixture); + + test_ctx.reset_dhcpv6 = false; + + set_dhcpv6_test_fn(NULL); + k_sem_reset(&test_ctx.tx_sem); + k_sem_reset(&test_ctx.exchange_complete_sem); + + memset(&test_ctx.iface->config.dhcpv6, 0, + sizeof(test_ctx.iface->config.dhcpv6)); + + dhcpv6_generate_client_duid(test_ctx.iface); + test_ctx.iface->config.dhcpv6.state = NET_DHCPV6_DISABLED; + test_ctx.iface->config.dhcpv6.addr_iaid = 10; + test_ctx.iface->config.dhcpv6.prefix_iaid = 20; + test_ctx.iface->config.dhcpv6.exchange_start = k_uptime_get(); + test_ctx.iface->config.dhcpv6.params = (struct net_dhcpv6_params){ + .request_addr = true, + .request_prefix = true, + }; + + test_preference = 100; + + net_if_ipv6_addr_rm(test_ctx.iface, &test_addr); + net_if_ipv6_prefix_rm(test_ctx.iface, &test_prefix, test_prefix_len); +} + +static void dhcpv6_tests_after(void *fixture) +{ + ARG_UNUSED(fixture); + + set_dhcpv6_test_fn(NULL); + + if (test_ctx.reset_dhcpv6) { + net_dhcpv6_stop(test_ctx.iface); + } +} + +static void verify_dhcpv6_header(struct net_if *iface, struct net_pkt *pkt, + enum dhcpv6_msg_type msg_type) +{ + uint8_t tid[DHCPV6_TID_SIZE]; + uint8_t type; + int ret; + + (void)net_pkt_skip(pkt, NET_IPV6UDPH_LEN); + + ret = net_pkt_read_u8(pkt, &type); + zassert_ok(ret, "DHCPv6 header incomplete (type)"); + zassert_equal(type, msg_type, "Invalid message type"); + + ret = net_pkt_read(pkt, tid, sizeof(tid)); + zassert_ok(ret, "DHCPv6 header incomplete (tid)"); + zassert_mem_equal(tid, iface->config.dhcpv6.tid, sizeof(tid), + "Transaction ID doesn't match ID of the current exchange"); +} + +static void verify_dhcpv6_clientid(struct net_if *iface, struct net_pkt *pkt) +{ + struct net_dhcpv6_duid_storage duid; + int ret; + + ret = dhcpv6_find_clientid(pkt, &duid); + zassert_ok(ret, "Missing Client ID option"); + zassert_equal(duid.length, iface->config.dhcpv6.clientid.length, + "Invalid Client ID length"); + zassert_mem_equal(&duid.duid, &iface->config.dhcpv6.clientid.duid, + duid.length, "Invalid Client ID value"); +} + +static void verify_dhcpv6_serverid(struct net_if *iface, struct net_pkt *pkt) +{ + struct net_dhcpv6_duid_storage duid; + int ret; + + ret = dhcpv6_find_serverid(pkt, &duid); + zassert_ok(ret, "Missing Server ID option"); + zassert_equal(duid.length, iface->config.dhcpv6.serverid.length, + "Invalid Server ID length"); + zassert_mem_equal(&duid.duid, &iface->config.dhcpv6.serverid.duid, + duid.length, "Invalid Server ID value"); +} + +static void verify_dhcpv6_no_serverid(struct net_if *iface, struct net_pkt *pkt) +{ + struct net_dhcpv6_duid_storage duid; + int ret; + + ret = dhcpv6_find_serverid(pkt, &duid); + zassert_not_equal(ret, 0, "Server ID option should not be present"); +} + +static void verify_dhcpv6_elapsed_time(struct net_if *iface, struct net_pkt *pkt, + uint16_t min_accepted, uint16_t max_accepted) +{ + struct net_pkt_cursor backup; + uint16_t elapsed_time; + uint16_t length; + int ret; + + net_pkt_cursor_backup(pkt, &backup); + + ret = dhcpv6_find_option(pkt, DHCPV6_OPTION_CODE_ELAPSED_TIME, &length); + zassert_ok(ret, "Missing Elapsed time option"); + zassert_equal(length, sizeof(uint16_t), "Invalid Elapsed time length"); + + ret = net_pkt_read_be16(pkt, &elapsed_time); + zassert_ok(ret, "Failed to read Elapsed time option"); + zassert_between_inclusive(elapsed_time, min_accepted, max_accepted, + "Elapsed time not in accepted range"); + + net_pkt_cursor_restore(pkt, &backup); +} + +static void verify_dhcpv6_ia_na(struct net_if *iface, struct net_pkt *pkt, + struct in6_addr *addr) +{ + struct dhcpv6_ia_na ia_na; + int ret; + + ret = dhcpv6_find_ia_na(pkt, &ia_na); + zassert_ok(ret, "Missing IA NA option"); + zassert_equal(ia_na.iaid, iface->config.dhcpv6.addr_iaid, + "Incorrect IA NA IAID"); + zassert_equal(ia_na.t1, 0, "T1 should be set to 0 by the client"); + zassert_equal(ia_na.t2, 0, "T2 should be set to 0 by the client"); + + if (addr == NULL) { + zassert_equal(ia_na.iaaddr.status, DHCPV6_STATUS_NO_ADDR_AVAIL, + "Adddress should not be present"); + return; + } + + zassert_equal(ia_na.iaaddr.status, DHCPV6_STATUS_SUCCESS, "Invalid status"); + zassert_equal(ia_na.iaaddr.preferred_lifetime, 0, + "Preferred lifetime should be set to 0 by the client"); + zassert_equal(ia_na.iaaddr.valid_lifetime, 0, + "Valid lifetime should be set to 0 by the client"); + zassert_mem_equal(&ia_na.iaaddr.addr, addr, sizeof(ia_na.iaaddr.addr), + "Incorrect address"); +} + +static void verify_dhcpv6_ia_pd(struct net_if *iface, struct net_pkt *pkt, + struct in6_addr *prefix, uint8_t prefix_len) +{ + struct dhcpv6_ia_pd ia_pd; + int ret; + + ret = dhcpv6_find_ia_pd(pkt, &ia_pd); + zassert_ok(ret, "Missing IA PD option"); + zassert_equal(ia_pd.iaid, iface->config.dhcpv6.prefix_iaid, + "Incorrect IA PD IAID"); + zassert_equal(ia_pd.t1, 0, "T1 should be set to 0 by the client"); + zassert_equal(ia_pd.t2, 0, "T2 should be set to 0 by the client"); + + if (prefix == NULL) { + zassert_equal(ia_pd.iaprefix.status, DHCPV6_STATUS_NO_PREFIX_AVAIL, + "Prefix should not be present"); + return; + } + + zassert_equal(ia_pd.iaprefix.status, DHCPV6_STATUS_SUCCESS, "Invalid status"); + zassert_equal(ia_pd.iaprefix.preferred_lifetime, 0, + "Preferred lifetime should be set to 0 by the client"); + zassert_equal(ia_pd.iaprefix.valid_lifetime, 0, + "Valid lifetime should be set to 0 by the client"); + zassert_equal(ia_pd.iaprefix.prefix_len, prefix_len, + "Incorrect prefix length"); + zassert_mem_equal(&ia_pd.iaprefix.prefix, prefix, + sizeof(ia_pd.iaprefix.prefix), "Incorrect prefix"); +} + +static void verify_dhcpv6_no_reconfigure_accept(struct net_if *iface, + struct net_pkt *pkt) +{ + struct net_pkt_cursor backup; + uint16_t length; + int ret; + + net_pkt_cursor_backup(pkt, &backup); + + ret = dhcpv6_find_option(pkt, DHCPV6_OPTION_CODE_RECONF_ACCEPT, &length); + zassert_not_equal(ret, 0, "Reconfigure accept option should not be present"); + + net_pkt_cursor_restore(pkt, &backup); +} + +static void verify_dhcpv6_oro_sol_max_rt(struct net_if *iface, + struct net_pkt *pkt) +{ + struct net_pkt_cursor backup; + uint16_t length; + uint16_t oro; + int ret; + + net_pkt_cursor_backup(pkt, &backup); + + ret = dhcpv6_find_option(pkt, DHCPV6_OPTION_CODE_ORO, &length); + zassert_ok(ret, 0, "ORO option not found"); + zassert_true(length >= sizeof(uint16_t) && length % sizeof(uint16_t) == 0, + "Invalid ORO length"); + + while (length >= sizeof(uint16_t)) { + ret = net_pkt_read_be16(pkt, &oro); + zassert_ok(ret, 0, "ORO read error"); + length -= sizeof(uint16_t); + + if (oro == DHCPV6_OPTION_CODE_SOL_MAX_RT) { + break; + } + } + + zassert_equal(oro, DHCPV6_OPTION_CODE_SOL_MAX_RT, + "No SOL_MAX_RT option request present"); + + net_pkt_cursor_restore(pkt, &backup); +} + +static void verify_solicit_message(struct net_if *iface, struct net_pkt *pkt) +{ + /* Verify header */ + verify_dhcpv6_header(iface, pkt, DHCPV6_MSG_TYPE_SOLICIT); + + /* Verify options */ + verify_dhcpv6_clientid(iface, pkt); + verify_dhcpv6_no_serverid(iface, pkt); + verify_dhcpv6_elapsed_time(iface, pkt, 0, 10); + verify_dhcpv6_ia_na(iface, pkt, NULL); + verify_dhcpv6_ia_pd(iface, pkt, NULL, 0); + verify_dhcpv6_no_reconfigure_accept(iface, pkt); + verify_dhcpv6_oro_sol_max_rt(iface, pkt); +} + +/* Verify that outgoing DHCPv6 Solicit has a valid format and includes all + * mandatory options. + */ +ZTEST(dhcpv6_tests, test_solicit_message_format) +{ + int ret; + + set_dhcpv6_test_fn(verify_solicit_message); + + ret = dhcpv6_send_solicit(test_ctx.iface); + zassert_ok(ret, "dhcpv6_send_solicit failed"); + + ret = k_sem_take(&test_ctx.tx_sem, K_SECONDS(1)); + zassert_ok(ret, "Packet not transmitted"); +} + +static void verify_request_message(struct net_if *iface, struct net_pkt *pkt) +{ + /* Verify header */ + verify_dhcpv6_header(iface, pkt, DHCPV6_MSG_TYPE_REQUEST); + + /* Verify options */ + verify_dhcpv6_clientid(iface, pkt); + verify_dhcpv6_serverid(iface, pkt); + verify_dhcpv6_elapsed_time(iface, pkt, 0, 10); + verify_dhcpv6_ia_na(iface, pkt, NULL); + verify_dhcpv6_ia_pd(iface, pkt, NULL, 0); + verify_dhcpv6_no_reconfigure_accept(iface, pkt); + verify_dhcpv6_oro_sol_max_rt(iface, pkt); +} + +/* Verify that outgoing DHCPv6 Request has a valid format and includes all + * mandatory options. + */ +ZTEST(dhcpv6_tests, test_request_message_format) +{ + int ret; + + set_fake_server_duid(test_ctx.iface); + set_dhcpv6_test_fn(verify_request_message); + + ret = dhcpv6_send_request(test_ctx.iface); + zassert_ok(ret, "dhcpv6_send_request failed"); + + ret = k_sem_take(&test_ctx.tx_sem, K_SECONDS(1)); + zassert_ok(ret, "Packet not transmitted"); +} + +static void verify_confirm_message(struct net_if *iface, struct net_pkt *pkt) +{ + /* Verify header */ + verify_dhcpv6_header(iface, pkt, DHCPV6_MSG_TYPE_CONFIRM); + + /* Verify options */ + verify_dhcpv6_clientid(iface, pkt); + verify_dhcpv6_no_serverid(iface, pkt); + verify_dhcpv6_elapsed_time(iface, pkt, 0, 10); + verify_dhcpv6_ia_na(iface, pkt, &test_addr); +} + +/* Verify that outgoing DHCPv6 Confirm has a valid format and includes all + * mandatory options. + */ +ZTEST(dhcpv6_tests, test_confirm_message_format) +{ + int ret; + + set_test_addr_on_iface(test_ctx.iface); + set_dhcpv6_test_fn(verify_confirm_message); + + ret = dhcpv6_send_confirm(test_ctx.iface); + zassert_ok(ret, "dhcpv6_send_confirm failed"); + + ret = k_sem_take(&test_ctx.tx_sem, K_SECONDS(1)); + zassert_ok(ret, "Packet not transmitted"); +} + +void verify_renew_message(struct net_if *iface, struct net_pkt *pkt) +{ + /* Verify header */ + verify_dhcpv6_header(iface, pkt, DHCPV6_MSG_TYPE_RENEW); + + /* Verify options */ + verify_dhcpv6_clientid(iface, pkt); + verify_dhcpv6_serverid(iface, pkt); + verify_dhcpv6_elapsed_time(iface, pkt, 0, 10); + verify_dhcpv6_ia_na(iface, pkt, &test_addr); + verify_dhcpv6_ia_pd(iface, pkt, &test_prefix, test_prefix_len); + verify_dhcpv6_oro_sol_max_rt(iface, pkt); +} + +/* Verify that outgoing DHCPv6 Renew has a valid format and includes all + * mandatory options. + */ +ZTEST(dhcpv6_tests, test_renew_message_format) +{ + int ret; + + set_test_addr_on_iface(test_ctx.iface); + set_fake_server_duid(test_ctx.iface); + set_dhcpv6_test_fn(verify_renew_message); + + ret = dhcpv6_send_renew(test_ctx.iface); + zassert_ok(ret, "dhcpv6_send_renew failed"); + + ret = k_sem_take(&test_ctx.tx_sem, K_SECONDS(1)); + zassert_ok(ret, "Packet not transmitted"); +} + +static void verify_rebind_message(struct net_if *iface, struct net_pkt *pkt) +{ + /* Verify header */ + verify_dhcpv6_header(iface, pkt, DHCPV6_MSG_TYPE_REBIND); + + /* Verify options */ + verify_dhcpv6_clientid(iface, pkt); + verify_dhcpv6_no_serverid(iface, pkt); + verify_dhcpv6_elapsed_time(iface, pkt, 0, 10); + verify_dhcpv6_ia_na(iface, pkt, &test_addr); + verify_dhcpv6_ia_pd(iface, pkt, &test_prefix, test_prefix_len); + verify_dhcpv6_oro_sol_max_rt(iface, pkt); +} + +/* Verify that outgoing DHCPv6 Rebind has a valid format and includes all + * mandatory options. + */ +ZTEST(dhcpv6_tests, test_rebind_message_format) +{ + int ret; + + set_test_addr_on_iface(test_ctx.iface); + set_dhcpv6_test_fn(verify_rebind_message); + + ret = dhcpv6_send_rebind(test_ctx.iface); + zassert_ok(ret, "dhcpv6_send_rebind failed"); + + ret = k_sem_take(&test_ctx.tx_sem, K_SECONDS(1)); + zassert_ok(ret, "Packet not transmitted"); +} + +static int set_generic_client_options(struct net_if *iface, struct net_pkt *pkt, + enum dhcpv6_msg_type msg_type) +{ + int ret; + + /* Simulate a minimum subset of valid options */ + ret = dhcpv6_add_option_clientid(pkt, &iface->config.dhcpv6.clientid); + if (ret < 0) { + return ret; + } + + if (msg_type == DHCPV6_MSG_TYPE_REQUEST || + msg_type == DHCPV6_MSG_TYPE_RENEW || + msg_type == DHCPV6_MSG_TYPE_RELEASE || + msg_type == DHCPV6_MSG_TYPE_DECLINE) { + ret = dhcpv6_add_option_serverid(pkt, &test_serverid); + if (ret < 0) { + return ret; + } + } + + return 0; +} + +/* Verify that DHCPv6 client rejects all messages other than Advertise, Reply + * and Reconfigure. + */ +ZTEST(dhcpv6_tests, test_input_reject_client_initiated_messages) +{ + + enum dhcpv6_msg_type type; + enum net_verdict result; + struct net_pkt *pkt; + + test_ctx.iface->config.dhcpv6.state = NET_DHCPV6_INIT; + + for (type = DHCPV6_MSG_TYPE_SOLICIT; + type <= DHCPV6_MSG_TYPE_RELAY_REPL; type++) { + if (type == DHCPV6_MSG_TYPE_ADVERTISE || + type == DHCPV6_MSG_TYPE_REPLY || + type == DHCPV6_MSG_TYPE_RECONFIGURE) { + continue; + } + + pkt = test_dhcpv6_create_message(test_ctx.iface, type, + set_generic_client_options); + zassert_not_null(pkt, "Failed to create fake pkt"); + + result = net_ipv6_input(pkt, false); + zassert_equal(result, NET_DROP, "Should've drop the message"); + + net_pkt_unref(pkt); + } +} + +static int set_advertise_options(struct net_if *iface, struct net_pkt *pkt, + enum dhcpv6_msg_type msg_type) +{ + struct dhcpv6_ia_na test_ia_na = { + .iaid = iface->config.dhcpv6.addr_iaid, + .t1 = 60, + .t2 = 120, + .iaaddr.addr = test_addr, + .iaaddr.preferred_lifetime = 120, + .iaaddr.valid_lifetime = 240, + }; + struct dhcpv6_ia_pd test_ia_pd = { + .iaid = iface->config.dhcpv6.prefix_iaid, + .t1 = 60, + .t2 = 120, + .iaprefix.prefix = test_prefix, + .iaprefix.prefix_len = test_prefix_len, + .iaprefix.preferred_lifetime = 120, + .iaprefix.valid_lifetime = 240, + }; + int ret; + + ret = dhcpv6_add_option_clientid(pkt, &iface->config.dhcpv6.clientid); + if (ret < 0) { + return ret; + } + + ret = dhcpv6_add_option_serverid(pkt, &test_serverid); + if (ret < 0) { + return ret; + } + + if (test_ctx.iface->config.dhcpv6.params.request_addr) { + ret = dhcpv6_add_option_ia_na(pkt, &test_ia_na, true); + if (ret < 0) { + return ret; + } + } + + if (test_ctx.iface->config.dhcpv6.params.request_prefix) { + ret = dhcpv6_add_option_ia_pd(pkt, &test_ia_pd, true); + if (ret < 0) { + return ret; + } + } + + /* Server specific options */ + ret = dhcpv6_add_option_header(pkt, DHCPV6_OPTION_CODE_PREFERENCE, + DHCPV6_OPTION_PREFERENCE_SIZE); + if (ret < 0) { + return ret; + } + + ret = net_pkt_write_u8(pkt, test_preference); + if (ret < 0) { + return ret; + } + + return 0; +} + +/* Verify that DHCPv6 client only accepts Advertise messages in Soliciting state */ +ZTEST(dhcpv6_tests, test_input_advertise) +{ + enum net_verdict result; + struct net_pkt *pkt; + enum net_dhcpv6_state state; + + for (state = NET_DHCPV6_DISABLED; state <= NET_DHCPV6_BOUND; state++) { + test_ctx.iface->config.dhcpv6.state = state; + + pkt = test_dhcpv6_create_message(test_ctx.iface, + DHCPV6_MSG_TYPE_ADVERTISE, + set_advertise_options); + zassert_not_null(pkt, "Failed to create pkt"); + + result = net_ipv6_input(pkt, false); + + switch (state) { + case NET_DHCPV6_SOLICITING: + zassert_equal(result, NET_OK, "Message should've been processed"); + + /* Verify that Advertise actually updated DHPCv6 context. */ + zassert_equal(test_ctx.iface->config.dhcpv6.server_preference, + test_preference, "Preference not set"); + zassert_equal(test_ctx.iface->config.dhcpv6.serverid.length, + test_serverid.length, "Invalid Server ID length"); + zassert_mem_equal(&test_ctx.iface->config.dhcpv6.serverid.duid, + &test_serverid.duid, test_serverid.length, + "Invalid Server ID value"); + + break; + default: + zassert_equal(result, NET_DROP, "Should've drop the message"); + break; + + } + + net_pkt_unref(pkt); + } +} + +static int set_reply_options(struct net_if *iface, struct net_pkt *pkt, + enum dhcpv6_msg_type msg_type) +{ + struct dhcpv6_ia_na test_ia_na = { + .iaid = iface->config.dhcpv6.addr_iaid, + .t1 = 60, + .t2 = 120, + .iaaddr.addr = test_addr, + .iaaddr.preferred_lifetime = 120, + .iaaddr.valid_lifetime = 240, + }; + struct dhcpv6_ia_pd test_ia_pd = { + .iaid = iface->config.dhcpv6.prefix_iaid, + .t1 = 60, + .t2 = 120, + .iaprefix.prefix = test_prefix, + .iaprefix.prefix_len = test_prefix_len, + .iaprefix.preferred_lifetime = 120, + .iaprefix.valid_lifetime = 240, + }; + int ret; + + ret = dhcpv6_add_option_clientid(pkt, &iface->config.dhcpv6.clientid); + if (ret < 0) { + return ret; + } + + ret = dhcpv6_add_option_serverid(pkt, &test_serverid); + if (ret < 0) { + return ret; + } + + if (iface->config.dhcpv6.state == NET_DHCPV6_CONFIRMING) { + ret = dhcpv6_add_option_header( + pkt, DHCPV6_OPTION_CODE_STATUS_CODE, + DHCPV6_OPTION_STATUS_CODE_HEADER_SIZE); + if (ret < 0) { + return ret; + } + + ret = net_pkt_write_be16(pkt, DHCPV6_STATUS_SUCCESS); + if (ret < 0) { + return ret; + } + + return 0; + } + + ret = dhcpv6_add_option_ia_na(pkt, &test_ia_na, true); + if (ret < 0) { + return ret; + } + + ret = dhcpv6_add_option_ia_pd(pkt, &test_ia_pd, true); + if (ret < 0) { + return ret; + } + + return 0; +} + +/* Verify that DHCPv6 client accepts Reply messages in Requesting, Confirming, + * Renewing and Rebinding states + */ +ZTEST(dhcpv6_tests, test_input_reply) +{ + enum net_verdict result; + struct net_pkt *pkt; + enum net_dhcpv6_state state; + + for (state = NET_DHCPV6_DISABLED; state <= NET_DHCPV6_BOUND; state++) { + test_ctx.iface->config.dhcpv6.state = state; + + set_fake_server_duid(test_ctx.iface); + clear_test_addr_on_iface(test_ctx.iface); + + pkt = test_dhcpv6_create_message(test_ctx.iface, + DHCPV6_MSG_TYPE_REPLY, + set_reply_options); + zassert_not_null(pkt, "Failed to create pkt"); + + result = net_ipv6_input(pkt, false); + + switch (state) { + case NET_DHCPV6_CONFIRMING: + case NET_DHCPV6_REQUESTING: + case NET_DHCPV6_RENEWING: + case NET_DHCPV6_REBINDING: + zassert_equal(result, NET_OK, "Message should've been processed"); + + /* Confirm is an exception, as it does not update + * address on an interface (only status OK is expected). + */ + if (state == NET_DHCPV6_CONFIRMING) { + break; + } + + /* Verify that Reply actually updated DHPCv6 context. */ + zassert_mem_equal(&test_ctx.iface->config.dhcpv6.addr, + &test_addr, sizeof(test_addr), + "Invalid address (state %s)", + net_dhcpv6_state_name(state)); + zassert_mem_equal(&test_ctx.iface->config.dhcpv6.prefix, + &test_prefix, sizeof(test_prefix), + "Invalid prefix (state %s)", + net_dhcpv6_state_name(state)); + zassert_equal(test_ctx.iface->config.dhcpv6.prefix_len, + test_prefix_len, "Invalid prefix len (state %s)", + net_dhcpv6_state_name(state)); + + break; + default: + zassert_equal(result, NET_DROP, "Should've drop the message"); + break; + + } + + net_pkt_unref(pkt); + } +} + +static void test_solicit_expect_request_send_reply(struct net_if *iface, + struct net_pkt *pkt) +{ + struct net_pkt *reply; + int result; + + /* Verify header */ + verify_dhcpv6_header(iface, pkt, DHCPV6_MSG_TYPE_REQUEST); + + /* Verify options */ + verify_dhcpv6_clientid(iface, pkt); + verify_dhcpv6_serverid(iface, pkt); + verify_dhcpv6_ia_na(iface, pkt, NULL); + verify_dhcpv6_ia_pd(iface, pkt, NULL, 0); + + /* Verify client state */ + zassert_equal(iface->config.dhcpv6.state, NET_DHCPV6_REQUESTING, + "Invalid state"); + + /* Reply with Reply message */ + reply = test_dhcpv6_create_message(test_ctx.iface, + DHCPV6_MSG_TYPE_REPLY, + set_reply_options); + zassert_not_null(reply, "Failed to create pkt"); + + result = net_ipv6_input(reply, false); + zassert_equal(result, NET_OK, "Message should've been processed"); + + /* Verify client state */ + zassert_equal(iface->config.dhcpv6.state, NET_DHCPV6_BOUND, + "Invalid state"); + zassert_mem_equal(&test_ctx.iface->config.dhcpv6.addr, + &test_addr, sizeof(test_addr), "Invalid address"); + zassert_mem_equal(&test_ctx.iface->config.dhcpv6.prefix, + &test_prefix, sizeof(test_prefix), "Invalid prefix"); + zassert_equal(test_ctx.iface->config.dhcpv6.prefix_len, + test_prefix_len, "Invalid prefix len"); + + k_sem_give(&test_ctx.exchange_complete_sem); +} + +static void test_solicit_expect_solicit_send_advertise(struct net_if *iface, + struct net_pkt *pkt) +{ + struct net_pkt *reply; + int result; + + /* Verify header */ + verify_dhcpv6_header(iface, pkt, DHCPV6_MSG_TYPE_SOLICIT); + + /* Verify options */ + verify_dhcpv6_clientid(iface, pkt); + verify_dhcpv6_ia_na(iface, pkt, NULL); + verify_dhcpv6_ia_pd(iface, pkt, NULL, 0); + + /* Verify client state */ + zassert_equal(iface->config.dhcpv6.state, NET_DHCPV6_SOLICITING, + "Invalid state"); + zassert_equal(iface->config.dhcpv6.server_preference, -1, + "Invalid initial preference"); + + /* Update next expected packet handler */ + set_dhcpv6_test_fn(test_solicit_expect_request_send_reply); + + /* Reply with Advertise message */ + reply = test_dhcpv6_create_message(test_ctx.iface, + DHCPV6_MSG_TYPE_ADVERTISE, + set_advertise_options); + zassert_not_null(reply, "Failed to create pkt"); + + result = net_ipv6_input(reply, false); + zassert_equal(result, NET_OK, "Message should've been processed"); + + /* Verify client state */ + zassert_equal(iface->config.dhcpv6.state, NET_DHCPV6_SOLICITING, + "Invalid state"); + zassert_equal(iface->config.dhcpv6.server_preference, test_preference, + "Invalid initial preference"); + zassert_equal(test_serverid.length, iface->config.dhcpv6.serverid.length, + "Invalid Server ID length"); + zassert_mem_equal(&test_serverid.duid, &iface->config.dhcpv6.serverid.duid, + test_serverid.length, "Invalid Server ID value"); +} + +/* Verify that DHCPv6 client can handle standard exchange (Solicit/Request) */ +ZTEST(dhcpv6_tests, test_solicit_exchange) +{ + struct net_dhcpv6_params params = { + .request_addr = true, + .request_prefix = true, + }; + struct net_if_ipv6_prefix *prefix; + struct net_if_addr *addr; + int ret; + + test_ctx.reset_dhcpv6 = true; + memset(&test_ctx.iface->config.dhcpv6, 0, + sizeof(test_ctx.iface->config.dhcpv6)); + + set_dhcpv6_test_fn(test_solicit_expect_solicit_send_advertise); + + net_dhcpv6_start(test_ctx.iface, ¶ms); + + ret = k_sem_take(&test_ctx.exchange_complete_sem, K_SECONDS(2)); + zassert_ok(ret, "Exchange not completed in required time"); + + addr = net_if_ipv6_addr_lookup_by_iface(test_ctx.iface, &test_addr); + prefix = net_if_ipv6_prefix_lookup(test_ctx.iface, &test_prefix, + test_prefix_len); + zassert_not_null(addr, "Address not configured on the interface"); + zassert_not_null(prefix, "Prefix not configured on the interface"); +} + +static void expect_request_send_reply(struct net_if *iface, struct net_pkt *pkt) +{ + struct net_pkt *reply; + int result; + + verify_dhcpv6_header(iface, pkt, DHCPV6_MSG_TYPE_REQUEST); + set_dhcpv6_test_fn(NULL); + + /* Reply with Reply message */ + reply = test_dhcpv6_create_message(test_ctx.iface, + DHCPV6_MSG_TYPE_REPLY, + set_reply_options); + zassert_not_null(reply, "Failed to create pkt"); + + result = net_ipv6_input(reply, false); + zassert_equal(result, NET_OK, "Message should've been processed"); + + k_sem_give(&test_ctx.exchange_complete_sem); +} + +static void expect_solicit_send_advertise(struct net_if *iface, struct net_pkt *pkt) +{ + struct net_pkt *reply; + int result; + + verify_dhcpv6_header(iface, pkt, DHCPV6_MSG_TYPE_SOLICIT); + set_dhcpv6_test_fn(expect_request_send_reply); + + /* Reply with Advertise message */ + reply = test_dhcpv6_create_message(test_ctx.iface, + DHCPV6_MSG_TYPE_ADVERTISE, + set_advertise_options); + zassert_not_null(reply, "Failed to create pkt"); + + result = net_ipv6_input(reply, false); + zassert_equal(result, NET_OK, "Message should've been processed"); +} + +static void test_dhcpv6_start_and_enter_bound(struct net_dhcpv6_params *params) +{ + int ret; + + /* Set maximum preference to speed up the process. */ + test_preference = DHCPV6_MAX_SERVER_PREFERENCE; + + set_dhcpv6_test_fn(expect_solicit_send_advertise); + net_dhcpv6_start(test_ctx.iface, params); + + ret = k_sem_take(&test_ctx.exchange_complete_sem, K_SECONDS(2)); + zassert_ok(ret, "Exchange not completed in required time"); + zassert_equal(test_ctx.iface->config.dhcpv6.state, NET_DHCPV6_BOUND, + "Invalid state"); +} + +static void test_confirm_expect_confirm_send_reply(struct net_if *iface, + struct net_pkt *pkt) +{ + struct net_pkt *reply; + int result; + + /* Verify header */ + verify_dhcpv6_header(iface, pkt, DHCPV6_MSG_TYPE_CONFIRM); + + /* Verify options */ + verify_dhcpv6_clientid(iface, pkt); + verify_dhcpv6_ia_na(iface, pkt, &test_addr); + + /* Verify client state */ + zassert_equal(iface->config.dhcpv6.state, NET_DHCPV6_CONFIRMING, + "Invalid state"); + + set_dhcpv6_test_fn(NULL); + + /* Reply with Advertise message */ + reply = test_dhcpv6_create_message(test_ctx.iface, + DHCPV6_MSG_TYPE_REPLY, + set_reply_options); + zassert_not_null(reply, "Failed to create pkt"); + + result = net_ipv6_input(reply, false); + zassert_equal(result, NET_OK, "Message should've been processed"); + + /* Verify client state */ + zassert_equal(iface->config.dhcpv6.state, NET_DHCPV6_BOUND, + "Invalid state"); + zassert_equal(test_serverid.length, iface->config.dhcpv6.serverid.length, + "Invalid Server ID length"); + zassert_mem_equal(&test_serverid.duid, &iface->config.dhcpv6.serverid.duid, + test_serverid.length, "Invalid Server ID value"); + + k_sem_give(&test_ctx.exchange_complete_sem); +} + +/* Verify that DHCPv6 client starts with Confirm when interface goes down and + * up again (no prefix). + */ +ZTEST(dhcpv6_tests, test_confirm_exchange_after_iface_down) +{ + struct net_dhcpv6_params params = { + .request_addr = true, + .request_prefix = false, + }; + struct net_if_addr *addr; + int ret; + + test_ctx.reset_dhcpv6 = true; + memset(&test_ctx.iface->config.dhcpv6, 0, + sizeof(test_ctx.iface->config.dhcpv6)); + + test_dhcpv6_start_and_enter_bound(¶ms); + set_dhcpv6_test_fn(test_confirm_expect_confirm_send_reply); + + net_if_down(test_ctx.iface); + net_if_up(test_ctx.iface); + + ret = k_sem_take(&test_ctx.exchange_complete_sem, K_SECONDS(2)); + zassert_ok(ret, "Exchange not completed in required time"); + + addr = net_if_ipv6_addr_lookup_by_iface(test_ctx.iface, &test_addr); + zassert_not_null(addr, "Address not configured on the interface"); +} + +static void test_rebind_expect_rebind_send_reply(struct net_if *iface, + struct net_pkt *pkt) +{ + struct net_pkt *reply; + int result; + + /* Verify header */ + verify_dhcpv6_header(iface, pkt, DHCPV6_MSG_TYPE_REBIND); + + /* Verify options */ + verify_dhcpv6_clientid(iface, pkt); + verify_dhcpv6_ia_na(iface, pkt, &test_addr); + verify_dhcpv6_ia_pd(iface, pkt, &test_prefix, test_prefix_len); + + /* Verify client state */ + zassert_equal(iface->config.dhcpv6.state, NET_DHCPV6_REBINDING, + "Invalid state"); + + set_dhcpv6_test_fn(NULL); + + /* Reply with Advertise message */ + reply = test_dhcpv6_create_message(test_ctx.iface, + DHCPV6_MSG_TYPE_REPLY, + set_reply_options); + zassert_not_null(reply, "Failed to create pkt"); + + result = net_ipv6_input(reply, false); + zassert_equal(result, NET_OK, "Message should've been processed"); + + /* Verify client state */ + zassert_equal(iface->config.dhcpv6.state, NET_DHCPV6_BOUND, + "Invalid state"); + zassert_equal(test_serverid.length, iface->config.dhcpv6.serverid.length, + "Invalid Server ID length"); + zassert_mem_equal(&test_serverid.duid, &iface->config.dhcpv6.serverid.duid, + test_serverid.length, "Invalid Server ID value"); + + k_sem_give(&test_ctx.exchange_complete_sem); +} + +/* Verify that DHCPv6 client starts with Rebind when interface goes down and + * up again (w/ prefix). + */ +ZTEST(dhcpv6_tests, test_rebind_exchange_after_iface_down) +{ + struct net_dhcpv6_params params = { + .request_addr = true, + .request_prefix = true, + }; + struct net_if_ipv6_prefix *prefix; + struct net_if_addr *addr; + int ret; + + test_ctx.reset_dhcpv6 = true; + memset(&test_ctx.iface->config.dhcpv6, 0, + sizeof(test_ctx.iface->config.dhcpv6)); + + test_dhcpv6_start_and_enter_bound(¶ms); + set_dhcpv6_test_fn(test_rebind_expect_rebind_send_reply); + + net_if_down(test_ctx.iface); + net_if_up(test_ctx.iface); + + ret = k_sem_take(&test_ctx.exchange_complete_sem, K_SECONDS(2)); + zassert_ok(ret, "Exchange not completed in required time"); + + addr = net_if_ipv6_addr_lookup_by_iface(test_ctx.iface, &test_addr); + prefix = net_if_ipv6_prefix_lookup(test_ctx.iface, &test_prefix, + test_prefix_len); + zassert_not_null(addr, "Address not configured on the interface"); + zassert_not_null(prefix, "Prefix not configured on the interface"); +} + +static void test_renew_expect_renew_send_reply(struct net_if *iface, + struct net_pkt *pkt) +{ + struct net_pkt *reply; + int result; + + /* Verify header */ + verify_dhcpv6_header(iface, pkt, DHCPV6_MSG_TYPE_RENEW); + + /* Verify options */ + verify_dhcpv6_clientid(iface, pkt); + verify_dhcpv6_serverid(iface, pkt); + verify_dhcpv6_ia_na(iface, pkt, &test_addr); + verify_dhcpv6_ia_pd(iface, pkt, &test_prefix, test_prefix_len); + + /* Verify client state */ + zassert_equal(iface->config.dhcpv6.state, NET_DHCPV6_RENEWING, + "Invalid state"); + + set_dhcpv6_test_fn(NULL); + + /* Reply with Advertise message */ + reply = test_dhcpv6_create_message(test_ctx.iface, + DHCPV6_MSG_TYPE_REPLY, + set_reply_options); + zassert_not_null(reply, "Failed to create pkt"); + + result = net_ipv6_input(reply, false); + zassert_equal(result, NET_OK, "Message should've been processed"); + + /* Verify client state */ + zassert_equal(iface->config.dhcpv6.state, NET_DHCPV6_BOUND, + "Invalid state"); + zassert_equal(test_serverid.length, iface->config.dhcpv6.serverid.length, + "Invalid Server ID length"); + zassert_mem_equal(&test_serverid.duid, &iface->config.dhcpv6.serverid.duid, + test_serverid.length, "Invalid Server ID value"); + + k_sem_give(&test_ctx.exchange_complete_sem); +} + +/* Verify that DHCPv6 client proceeds with Renew when T1 timeout expires. */ +ZTEST(dhcpv6_tests, test_renew_exchange_after_t1) +{ + struct net_dhcpv6_params params = { + .request_addr = true, + .request_prefix = true, + }; + struct net_if_ipv6_prefix *prefix; + struct net_if_addr *addr; + int ret; + + test_ctx.reset_dhcpv6 = true; + memset(&test_ctx.iface->config.dhcpv6, 0, + sizeof(test_ctx.iface->config.dhcpv6)); + + test_dhcpv6_start_and_enter_bound(¶ms); + set_dhcpv6_test_fn(test_renew_expect_renew_send_reply); + + /* Simulate T1 timeout */ + test_ctx.iface->config.dhcpv6.t1 = k_uptime_get(); + test_ctx.iface->config.dhcpv6.timeout = test_ctx.iface->config.dhcpv6.t1; + dhcpv6_reschedule(); + + ret = k_sem_take(&test_ctx.exchange_complete_sem, K_SECONDS(2)); + zassert_ok(ret, "Exchange not completed in required time"); + + addr = net_if_ipv6_addr_lookup_by_iface(test_ctx.iface, &test_addr); + prefix = net_if_ipv6_prefix_lookup(test_ctx.iface, &test_prefix, + test_prefix_len); + zassert_not_null(addr, "Address not configured on the interface"); + zassert_not_null(prefix, "Prefix not configured on the interface"); +} + +/* Verify that DHCPv6 client proceeds with Rebind when T2 timeout expires. */ +ZTEST(dhcpv6_tests, test_rebind_exchange_after_t2) +{ + struct net_dhcpv6_params params = { + .request_addr = true, + .request_prefix = true, + }; + struct net_if_ipv6_prefix *prefix; + struct net_if_addr *addr; + int ret; + + test_ctx.reset_dhcpv6 = true; + memset(&test_ctx.iface->config.dhcpv6, 0, + sizeof(test_ctx.iface->config.dhcpv6)); + + test_dhcpv6_start_and_enter_bound(¶ms); + set_dhcpv6_test_fn(NULL); + + /* Simulate T1 timeout */ + test_ctx.iface->config.dhcpv6.t1 = k_uptime_get(); + test_ctx.iface->config.dhcpv6.timeout = test_ctx.iface->config.dhcpv6.t1; + dhcpv6_reschedule(); + + /* Give a state machine a chance to run, we ignore Renew message. */ + k_msleep(10); + + set_dhcpv6_test_fn(test_rebind_expect_rebind_send_reply); + + /* Simulate T2 timeout */ + test_ctx.iface->config.dhcpv6.t2 = k_uptime_get(); + test_ctx.iface->config.dhcpv6.timeout = test_ctx.iface->config.dhcpv6.t2; + dhcpv6_reschedule(); + + ret = k_sem_take(&test_ctx.exchange_complete_sem, K_SECONDS(2)); + zassert_ok(ret, "Exchange not completed in required time"); + + addr = net_if_ipv6_addr_lookup_by_iface(test_ctx.iface, &test_addr); + prefix = net_if_ipv6_prefix_lookup(test_ctx.iface, &test_prefix, + test_prefix_len); + zassert_not_null(addr, "Address not configured on the interface"); + zassert_not_null(prefix, "Prefix not configured on the interface"); +} + +ZTEST_SUITE(dhcpv6_tests, NULL, dhcpv6_tests_setup, dhcpv6_tests_before, + dhcpv6_tests_after, NULL); diff --git a/tests/net/dhcpv6/testcase.yaml b/tests/net/dhcpv6/testcase.yaml new file mode 100644 index 00000000000..faf9c67de06 --- /dev/null +++ b/tests/net/dhcpv6/testcase.yaml @@ -0,0 +1,10 @@ +common: + depends_on: netif + tags: net dhcpv6 +tests: + net.dhcpv6: + extra_configs: + - CONFIG_NET_TC_THREAD_COOPERATIVE=y + net.dhcpv6.preempt: + extra_configs: + - CONFIG_NET_TC_THREAD_PREEMPTIVE=y diff --git a/tests/net/ethernet_mgmt/prj.conf b/tests/net/ethernet_mgmt/prj.conf index dd0ade07970..73acc1e32e5 100644 --- a/tests/net/ethernet_mgmt/prj.conf +++ b/tests/net/ethernet_mgmt/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=2048 CONFIG_MAIN_STACK_SIZE=2048 CONFIG_NETWORKING=y diff --git a/tests/net/hostname/prj.conf b/tests/net/hostname/prj.conf index e7419db995f..1b174c35c0e 100644 --- a/tests/net/hostname/prj.conf +++ b/tests/net/hostname/prj.conf @@ -20,7 +20,6 @@ CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6 CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=2 CONFIG_NET_IPV6_ND=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NET_IF_MAX_IPV4_COUNT=4 CONFIG_NET_IF_MAX_IPV6_COUNT=4 CONFIG_NET_HOSTNAME_ENABLE=y diff --git a/tests/net/hostname/src/main.c b/tests/net/hostname/src/main.c index 3a5ad644f42..d2a56ca2782 100644 --- a/tests/net/hostname/src/main.c +++ b/tests/net/hostname/src/main.c @@ -16,7 +16,7 @@ LOG_MODULE_REGISTER(net_test, NET_LOG_LEVEL); #include #include #include -#include +#include #include #include diff --git a/tests/net/icmp/CMakeLists.txt b/tests/net/icmp/CMakeLists.txt new file mode 100644 index 00000000000..a05c45522aa --- /dev/null +++ b/tests/net/icmp/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(icmp) + +target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/net/ip) +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/net/icmp/prj.conf b/tests/net/icmp/prj.conf new file mode 100644 index 00000000000..2d365ff44fb --- /dev/null +++ b/tests/net/icmp/prj.conf @@ -0,0 +1,20 @@ +CONFIG_NETWORKING=y +CONFIG_NET_TEST=y +CONFIG_NET_IPV6=y +CONFIG_NET_IPV4=y +CONFIG_NET_BUF=y +CONFIG_ZTEST_STACK_SIZE=1024 +CONFIG_NET_PKT_RX_COUNT=2 +CONFIG_NET_PKT_TX_COUNT=5 +CONFIG_NET_BUF_RX_COUNT=5 +CONFIG_NET_BUF_TX_COUNT=10 +CONFIG_NET_LOG=y +CONFIG_ENTROPY_GENERATOR=y +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_ZTEST=y +CONFIG_MAIN_STACK_SIZE=1280 +CONFIG_NET_L2_DUMMY=y +CONFIG_NET_IPV6_NBR_CACHE=n +CONFIG_NET_IPV6_ND=n +CONFIG_NET_IPV6_DAD=n +CONFIG_NET_IPV6_MLD=n diff --git a/tests/net/icmp/src/main.c b/tests/net/icmp/src/main.c new file mode 100644 index 00000000000..61a749c27ef --- /dev/null +++ b/tests/net/icmp/src/main.c @@ -0,0 +1,687 @@ +/* main.c - Application main entry point */ + +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Use highest log level if both IPv4 and IPv6 are defined */ +#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_IPV6) + +#if CONFIG_NET_ICMPV4_LOG_LEVEL > CONFIG_NET_ICMPV6_LOG_LEVEL +#define ICMP_LOG_LEVEL CONFIG_NET_ICMPV4_LOG_LEVEL +#else +#define ICMP_LOG_LEVEL CONFIG_NET_ICMPV6_LOG_LEVEL +#endif + +#elif defined(CONFIG_NET_IPV4) +#define ICMP_LOG_LEVEL CONFIG_NET_ICMPV4_LOG_LEVEL +#elif defined(CONFIG_NET_IPV6) +#define ICMP_LOG_LEVEL CONFIG_NET_ICMPV6_LOG_LEVEL +#else +#define ICMP_LOG_LEVEL LOG_LEVEL_INF +#endif + +#include +LOG_MODULE_REGISTER(net_test, ICMP_LOG_LEVEL); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "net_private.h" +#include "icmpv4.h" +#include "icmpv6.h" +#include "ipv4.h" +#include "ipv6.h" + +#define PKT_WAIT_TIME K_SECONDS(1) +#define SEM_WAIT_TIME K_SECONDS(1) +#define TEST_DATA "dummy test data" + +static struct in6_addr send_addr_6 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0x1 } } }; +static struct in6_addr recv_addr_6 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0x2 } } }; +static struct in_addr send_addr_4 = { { { 192, 0, 2, 1 } } }; +static struct in_addr recv_addr_4 = { { { 192, 0, 2, 2 } } }; + +static struct net_if *sender, *receiver; + +static struct test_icmp_context { + uint8_t mac[sizeof(struct net_eth_addr)]; + struct net_if *iface; + uint8_t test_data[sizeof(TEST_DATA)]; + struct k_sem tx_sem; + bool req_received; +} send_ctx, recv_ctx; + +#if defined(CONFIG_NET_OFFLOADING_SUPPORT) +static struct test_icmp_context offload_ctx; +static struct net_if *offload_sender; + +static struct in6_addr offload_send_addr_6 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0x3 } } }; +static struct in6_addr offload_recv_addr_6 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0x4 } } }; +static struct in_addr offload_send_addr_4 = { { { 192, 0, 2, 3 } } }; +static struct in_addr offload_recv_addr_4 = { { { 192, 0, 2, 4 } } }; +#endif + +static void test_iface_init(struct net_if *iface) +{ + struct test_icmp_context *ctx = net_if_get_device(iface)->data; + static int counter; + + /* Generate and assign MAC. */ + /* 00-00-5E-00-53-xx Documentation RFC 7042 */ + ctx->mac[0] = 0x00; + ctx->mac[1] = 0x00; + ctx->mac[2] = 0x5E; + ctx->mac[3] = 0x00; + ctx->mac[4] = 0x53; + ctx->mac[5] = ++counter; + + net_if_set_link_addr(iface, ctx->mac, sizeof(ctx->mac), NET_LINK_ETHERNET); + + ctx->iface = iface; +} + +static int test_sender(const struct device *dev, struct net_pkt *pkt) +{ + struct net_pkt *send_pkt; + + send_pkt = net_pkt_clone(pkt, PKT_WAIT_TIME); + + net_pkt_set_iface(send_pkt, recv_ctx.iface); + + (void)net_recv_data(recv_ctx.iface, send_pkt); + + net_pkt_unref(pkt); + + return 0; +} + +static int test_receiver(const struct device *dev, struct net_pkt *pkt) +{ + struct net_pkt *send_pkt; + + send_pkt = net_pkt_clone(pkt, PKT_WAIT_TIME); + + net_pkt_set_iface(send_pkt, send_ctx.iface); + + (void)net_recv_data(send_ctx.iface, send_pkt); + + net_pkt_unref(pkt); + + return 0; +} + +static struct dummy_api send_if_api = { + .iface_api.init = test_iface_init, + .send = test_sender, +}; + +static struct dummy_api recv_if_api = { + .iface_api.init = test_iface_init, + .send = test_receiver, +}; + +NET_DEVICE_INIT(test_sender_icmp, "test_sender_icmp", NULL, NULL, &send_ctx, NULL, + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &send_if_api, + DUMMY_L2, NET_L2_GET_CTX_TYPE(DUMMY_L2), NET_IPV6_MTU); + +NET_DEVICE_INIT(test_receiver_icmp, "test_receiver_icmp", NULL, NULL, &recv_ctx, NULL, + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &recv_if_api, + DUMMY_L2, NET_L2_GET_CTX_TYPE(DUMMY_L2), NET_IPV6_MTU); + +#if defined(CONFIG_NET_OFFLOADING_SUPPORT) +static int offload_dummy_get(sa_family_t family, + enum net_sock_type type, + enum net_ip_protocol ip_proto, + struct net_context **context) +{ + return -1; +} + +/* Placeholders, until Zephyr IP stack updated to handle a NULL net_offload */ +static struct net_offload offload_dummy = { + .get = offload_dummy_get, + .bind = NULL, + .listen = NULL, + .connect = NULL, + .accept = NULL, + .send = NULL, + .sendto = NULL, + .recv = NULL, + .put = NULL, +}; + +static struct net_icmp_offload offload_data; + +#if defined(CONFIG_NET_IPV4) +static int get_ipv4_reply(struct net_if *iface, + struct sockaddr *dst, + struct net_icmp_ping_params *params, + struct net_pkt **reply_pkt, + struct net_ipv4_hdr **hdr_ipv4, + struct net_icmp_hdr **hdr_icmp) +{ + struct net_ipv4_hdr *ipv4_hdr = NULL; + struct net_icmp_hdr *icmp_hdr; + const struct in_addr *dest4; + struct net_pkt *reply; + struct in_addr *src4; + int ret; + + /* The code below should not be used in real life scenarios + * as it is missing filling the ICMP params etc. We just create + * a basic IPv4 header here in order to pass sanity checks + * in IP packet parsing. + */ + reply = net_pkt_alloc_with_buffer(iface, sizeof(struct net_ipv4_hdr) + + sizeof(struct net_icmp_hdr) + + params->data_size, + AF_INET, IPPROTO_ICMP, + PKT_WAIT_TIME); + if (!reply) { + NET_DBG("No buffer"); + return -ENOMEM; + } + + dest4 = &offload_send_addr_4; + src4 = &net_sin(dst)->sin_addr; + + ipv4_hdr = net_pkt_cursor_get_pos(reply); + *hdr_ipv4 = ipv4_hdr; + + ret = net_ipv4_create_full(reply, src4, dest4, params->tc_tos, + params->identifier, 0, 0, 1); + if (ret < 0) { + LOG_ERR("Cannot create IPv4 pkt (%d)", ret); + return ret; + } + + icmp_hdr = net_pkt_cursor_get_pos(reply); + *hdr_icmp = icmp_hdr; + + ret = net_icmpv4_create(reply, NET_ICMPV4_ECHO_REPLY, 0); + if (ret < 0) { + LOG_ERR("Cannot create ICMPv4 pkt (%d)", ret); + return ret; + } + + ret = net_pkt_write(reply, params->data, params->data_size); + if (ret < 0) { + LOG_ERR("Cannot write payload (%d)", ret); + return ret; + } + + net_pkt_cursor_init(reply); + net_ipv4_finalize(reply, IPPROTO_ICMP); + + *reply_pkt = reply; + + return 0; +} +#else +static int get_ipv4_reply(struct net_if *iface, + struct sockaddr *dst, + struct net_icmp_ping_params *params, + struct net_pkt **reply_pkt, + struct net_ipv4_hdr **hdr_ipv4, + struct net_icmp_hdr **hdr_icmp) +{ + return -ENOTSUP; +} +#endif + +#if defined(CONFIG_NET_IPV6) +static int get_ipv6_reply(struct net_if *iface, + struct sockaddr *dst, + struct net_icmp_ping_params *params, + struct net_pkt **reply_pkt, + struct net_ipv6_hdr **hdr_ipv6, + struct net_icmp_hdr **hdr_icmp) +{ + struct net_ipv6_hdr *ipv6_hdr = NULL; + struct net_icmp_hdr *icmp_hdr; + const struct in6_addr *dest6; + struct net_pkt *reply; + struct in6_addr *src6; + int ret; + + reply = net_pkt_alloc_with_buffer(iface, sizeof(struct net_ipv6_hdr) + + sizeof(struct net_icmp_hdr) + + params->data_size, + AF_INET6, IPPROTO_ICMP, + PKT_WAIT_TIME); + if (!reply) { + NET_DBG("No buffer"); + return -ENOMEM; + } + + dest6 = &offload_send_addr_6; + src6 = &net_sin6(dst)->sin6_addr; + + ipv6_hdr = net_pkt_cursor_get_pos(reply); + *hdr_ipv6 = ipv6_hdr; + + ret = net_ipv6_create(reply, src6, dest6); + if (ret < 0) { + LOG_ERR("Cannot create IPv6 pkt (%d)", ret); + return ret; + } + + icmp_hdr = net_pkt_cursor_get_pos(reply); + *hdr_icmp = icmp_hdr; + + ret = net_icmpv6_create(reply, NET_ICMPV6_ECHO_REPLY, 0); + if (ret < 0) { + LOG_ERR("Cannot create ICMPv6 pkt (%d)", ret); + return ret; + } + + ret = net_pkt_write(reply, params->data, params->data_size); + if (ret < 0) { + LOG_ERR("Cannot write payload (%d)", ret); + return ret; + } + + net_pkt_cursor_init(reply); + net_ipv6_finalize(reply, IPPROTO_ICMP); + + *reply_pkt = reply; + + return 0; +} +#else +static int get_ipv6_reply(struct net_if *iface, + struct sockaddr *dst, + struct net_icmp_ping_params *params, + struct net_pkt **reply_pkt, + struct net_ipv6_hdr **hdr_ipv6, + struct net_icmp_hdr **hdr_icmp) +{ + return -ENOTSUP; +} +#endif + +static int offload_ping_handler(struct net_icmp_ctx *ctx, + struct net_if *iface, + struct sockaddr *dst, + struct net_icmp_ping_params *params, + void *user_data) +{ + struct net_icmp_offload *icmp_offload_ctx = &offload_data; + struct net_icmp_hdr *icmp_hdr = NULL; + struct net_pkt *reply = NULL; + struct net_icmp_ip_hdr ip_hdr; + struct net_ipv4_hdr *ipv4_hdr; + struct net_ipv6_hdr *ipv6_hdr; + net_icmp_handler_t resp_handler; + int ret; + + ret = net_icmp_get_offload_rsp_handler(icmp_offload_ctx, &resp_handler); + if (ret < 0) { + LOG_ERR("Cannot get offload response handler."); + return -ENOENT; + } + + /* So in real life scenario, we should here send a Echo-Request via + * some offloaded way to peer. When the response is received, we + * should then return that information to the ping caller by + * calling the response handler function. + * Here we just simulate a reply as there is no need to actually + * send anything anywhere. + */ + if (IS_ENABLED(CONFIG_NET_IPV4) && dst->sa_family == AF_INET) { + ret = get_ipv4_reply(iface, dst, params, &reply, + &ipv4_hdr, &icmp_hdr); + if (ret < 0) { + LOG_ERR("Cannot create reply pkt (%d)", ret); + return ret; + } + + ip_hdr.family = AF_INET; + ip_hdr.ipv4 = ipv4_hdr; + } + + if (IS_ENABLED(CONFIG_NET_IPV6) && dst->sa_family == AF_INET6) { + ret = get_ipv6_reply(iface, dst, params, &reply, + &ipv6_hdr, &icmp_hdr); + if (ret < 0) { + LOG_ERR("Cannot create reply pkt (%d)", ret); + return ret; + } + + ip_hdr.family = AF_INET6; + ip_hdr.ipv6 = ipv6_hdr; + } + + ret = resp_handler(ctx, reply, &ip_hdr, icmp_hdr, user_data); + if (ret < 0) { + LOG_ERR("Cannot send response (%d)", ret); + } + + return ret; +} + +static void offload_iface_init(struct net_if *iface) +{ + struct test_icmp_context *ctx = net_if_get_device(iface)->data; + int ret; + + /* Generate and assign MAC. */ + /* 00-00-5E-00-53-xx Documentation RFC 7042 */ + ctx->mac[0] = 0x00; + ctx->mac[1] = 0x00; + ctx->mac[2] = 0x5E; + ctx->mac[3] = 0x00; + ctx->mac[4] = 0x53; + ctx->mac[5] = 0xF0; + + net_if_set_link_addr(iface, ctx->mac, sizeof(ctx->mac), NET_LINK_ETHERNET); + + /* A dummy placeholder to allow network stack to pass offloaded data to our interface */ + iface->if_dev->offload = &offload_dummy; + + /* This will cause ping requests to be re-directed to our offload handler */ + ret = net_icmp_register_offload_ping(&offload_data, iface, offload_ping_handler); + if (ret < 0) { + LOG_ERR("Cannot register offload ping handler (%d)", ret); + } + + ctx->iface = iface; +} + +static enum offloaded_net_if_types offload_get_type(void) +{ + return L2_OFFLOADED_NET_IF_TYPE_WIFI; +} + +static const struct net_wifi_mgmt_offload offload_api = { + .wifi_iface.iface_api.init = offload_iface_init, + .wifi_iface.get_type = offload_get_type, +}; + +NET_DEVICE_OFFLOAD_INIT(test_offload, "test_offload", NULL, NULL, &offload_ctx, NULL, + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &offload_api, 1500); +#endif /* CONFIG_NET_OFFLOADING_SUPPORT */ + +static int icmp_handler(struct net_icmp_ctx *ctx, + struct net_pkt *pkt, + struct net_icmp_ip_hdr *hdr, + struct net_icmp_hdr *icmp_hdr, + void *user_data) +{ + struct test_icmp_context *test = user_data; + + if (hdr->family == AF_INET) { + struct net_ipv4_hdr *ip_hdr = hdr->ipv4; + + NET_DBG("Received Echo reply from %s to %s", + net_sprint_ipv4_addr(&ip_hdr->src), + net_sprint_ipv4_addr(&ip_hdr->dst)); + + } else if (hdr->family == AF_INET6) { + struct net_ipv6_hdr *ip_hdr = hdr->ipv6; + + NET_DBG("Received Echo Reply from %s to %s", + net_sprint_ipv6_addr(&ip_hdr->src), + net_sprint_ipv6_addr(&ip_hdr->dst)); + } else { + return -ENOENT; + } + + test->req_received = true; + k_sem_give(&test->tx_sem); + + return 0; +} + +ZTEST(icmp_tests, test_icmpv6_echo_request) +{ + struct sockaddr_in6 dst6 = { 0 }; + struct net_icmp_ping_params params; + struct net_icmp_ctx ctx; + int ret; + + if (!IS_ENABLED(CONFIG_NET_IPV6)) { + return; + } + + ret = net_icmp_init_ctx(&ctx, NET_ICMPV6_ECHO_REPLY, 0, icmp_handler); + zassert_equal(ret, 0, "Cannot init ICMP (%d)", ret); + + dst6.sin6_family = AF_INET6; + +#if defined(CONFIG_NET_IPV6) + memcpy(&dst6.sin6_addr, &recv_addr_6, sizeof(recv_addr_6)); +#endif + + params.identifier = 1234; + params.sequence = 5678; + params.tc_tos = 1; + params.priority = 2; + params.data = send_ctx.test_data; + params.data_size = sizeof(send_ctx.test_data); + + ret = net_icmp_send_echo_request(&ctx, sender, + (struct sockaddr *)&dst6, + ¶ms, + &send_ctx); + zassert_equal(ret, 0, "Cannot send ICMP Echo-Request (%d)", ret); + + k_sem_take(&send_ctx.tx_sem, SEM_WAIT_TIME); + + zassert_true(send_ctx.req_received, "Did not receive Echo-Request"); + + ret = net_icmp_cleanup_ctx(&ctx); + zassert_equal(ret, 0, "Cannot cleanup ICMP (%d)", ret); + + send_ctx.req_received = false; +} + +ZTEST(icmp_tests, test_icmpv4_echo_request) +{ + struct sockaddr_in dst4 = { 0 }; + struct net_icmp_ping_params params; + struct net_icmp_ctx ctx; + int ret; + + if (!IS_ENABLED(CONFIG_NET_IPV4)) { + return; + } + + ret = net_icmp_init_ctx(&ctx, NET_ICMPV4_ECHO_REPLY, 0, icmp_handler); + zassert_equal(ret, 0, "Cannot init ICMP (%d)", ret); + + dst4.sin_family = AF_INET; + +#if defined(CONFIG_NET_IPV4) + memcpy(&dst4.sin_addr, &recv_addr_4, sizeof(recv_addr_4)); +#endif + + params.identifier = 1234; + params.sequence = 5678; + params.tc_tos = 1; + params.priority = 2; + params.data = send_ctx.test_data; + params.data_size = sizeof(send_ctx.test_data); + + ret = net_icmp_send_echo_request(&ctx, sender, + (struct sockaddr *)&dst4, + ¶ms, + &send_ctx); + zassert_equal(ret, 0, "Cannot send ICMP Echo-Request (%d)", ret); + + k_sem_take(&send_ctx.tx_sem, SEM_WAIT_TIME); + + zassert_true(send_ctx.req_received, "Did not receive Echo-Request"); + + ret = net_icmp_cleanup_ctx(&ctx); + zassert_equal(ret, 0, "Cannot cleanup ICMP (%d)", ret); + + send_ctx.req_received = false; +} + +#if defined(CONFIG_NET_OFFLOADING_SUPPORT) +#if defined(CONFIG_NET_IPV4) +ZTEST(icmp_tests, test_offload_icmpv4_echo_request) +{ + struct sockaddr_in dst4 = { 0 }; + struct net_icmp_ping_params params; + struct net_icmp_ctx ctx; + int ret; + + ret = net_icmp_init_ctx(&ctx, NET_ICMPV4_ECHO_REPLY, 0, icmp_handler); + zassert_equal(ret, 0, "Cannot init ICMP (%d)", ret); + + dst4.sin_family = AF_INET; + + memcpy(&dst4.sin_addr, &offload_recv_addr_4, sizeof(offload_recv_addr_4)); + + params.identifier = 1234; + params.sequence = 5678; + params.tc_tos = 1; + params.priority = 2; + params.data = offload_ctx.test_data; + params.data_size = sizeof(offload_ctx.test_data); + + ret = net_icmp_send_echo_request(&ctx, offload_sender, + (struct sockaddr *)&dst4, + ¶ms, + &offload_ctx); + zassert_equal(ret, 0, "Cannot send ICMP Echo-Request (%d)", ret); + + k_sem_take(&offload_ctx.tx_sem, SEM_WAIT_TIME); + + zassert_true(offload_ctx.req_received, "Did not receive Echo-Request"); + + ret = net_icmp_cleanup_ctx(&ctx); + zassert_equal(ret, 0, "Cannot cleanup ICMP (%d)", ret); + + offload_ctx.req_received = false; +} +#endif + +#if defined(CONFIG_NET_IPV6) +ZTEST(icmp_tests, test_offload_icmpv6_echo_request) +{ + struct sockaddr_in6 dst6 = { 0 }; + struct net_icmp_ping_params params; + struct net_icmp_ctx ctx; + int ret; + + ret = net_icmp_init_ctx(&ctx, NET_ICMPV6_ECHO_REPLY, 0, icmp_handler); + zassert_equal(ret, 0, "Cannot init ICMP (%d)", ret); + + dst6.sin6_family = AF_INET6; + + memcpy(&dst6.sin6_addr, &offload_recv_addr_6, sizeof(offload_recv_addr_6)); + + params.identifier = 1234; + params.sequence = 5678; + params.tc_tos = 1; + params.priority = 2; + params.data = offload_ctx.test_data; + params.data_size = sizeof(offload_ctx.test_data); + + ret = net_icmp_send_echo_request(&ctx, offload_sender, + (struct sockaddr *)&dst6, + ¶ms, + &offload_ctx); + zassert_equal(ret, 0, "Cannot send ICMP Echo-Request (%d)", ret); + + k_sem_take(&offload_ctx.tx_sem, SEM_WAIT_TIME); + + zassert_true(offload_ctx.req_received, "Did not receive Echo-Request"); + + ret = net_icmp_cleanup_ctx(&ctx); + zassert_equal(ret, 0, "Cannot cleanup ICMP (%d)", ret); + + offload_ctx.req_received = false; +} +#endif +#endif /* CONFIG_NET_OFFLOADING_SUPPORT */ + +static void *setup(void) +{ + if (IS_ENABLED(CONFIG_NET_TC_THREAD_COOPERATIVE)) { + k_thread_priority_set(k_current_get(), + K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1)); + } else { + k_thread_priority_set(k_current_get(), K_PRIO_PREEMPT(9)); + } + +#if defined(CONFIG_NET_IPV6) + (void)net_if_ipv6_addr_add(send_ctx.iface, &send_addr_6, NET_ADDR_MANUAL, 0); + (void)net_if_ipv6_addr_add(recv_ctx.iface, &recv_addr_6, NET_ADDR_MANUAL, 0); +#else + ARG_UNUSED(send_addr_6); + ARG_UNUSED(recv_addr_6); +#endif + +#if defined(CONFIG_NET_IPV4) + (void)net_if_ipv4_addr_add(send_ctx.iface, &send_addr_4, NET_ADDR_MANUAL, 0); + (void)net_if_ipv4_addr_add(recv_ctx.iface, &recv_addr_4, NET_ADDR_MANUAL, 0); +#else + ARG_UNUSED(send_addr_4); + ARG_UNUSED(recv_addr_4); +#endif + + memcpy(send_ctx.test_data, &(TEST_DATA), sizeof(TEST_DATA)); + memcpy(recv_ctx.test_data, &(TEST_DATA), sizeof(TEST_DATA)); + + k_sem_init(&send_ctx.tx_sem, 0, 1); + k_sem_init(&recv_ctx.tx_sem, 0, 1); + + sender = net_if_lookup_by_dev(DEVICE_GET(test_sender_icmp)); + zassert_equal(sender, send_ctx.iface, "Invalid interface (%p vs %p)", + sender, send_ctx.iface); + + receiver = net_if_lookup_by_dev(DEVICE_GET(test_receiver_icmp)); + zassert_equal(receiver, recv_ctx.iface, "Invalid interface (%p vs %p)", + receiver, recv_ctx.iface); + +#if defined(CONFIG_NET_OFFLOADING_SUPPORT) + +#if defined(CONFIG_NET_IPV6) + (void)net_if_ipv6_addr_add(offload_ctx.iface, &offload_send_addr_6, NET_ADDR_MANUAL, 0); +#else + ARG_UNUSED(offload_send_addr_6); + ARG_UNUSED(offload_recv_addr_6); +#endif + +#if defined(CONFIG_NET_IPV4) + (void)net_if_ipv4_addr_add(offload_ctx.iface, &offload_send_addr_4, NET_ADDR_MANUAL, 0); +#else + ARG_UNUSED(offload_send_addr_4); + ARG_UNUSED(offload_recv_addr_4); +#endif + + memcpy(offload_ctx.test_data, &(TEST_DATA), sizeof(TEST_DATA)); + k_sem_init(&offload_ctx.tx_sem, 0, 1); + + offload_sender = net_if_lookup_by_dev(DEVICE_GET(test_offload)); + zassert_equal(offload_sender, offload_ctx.iface, "Invalid interface (%p vs %p)", + offload_sender, offload_ctx.iface); +#endif + + return NULL; +} + +ZTEST_SUITE(icmp_tests, NULL, setup, NULL, NULL, NULL); diff --git a/tests/net/icmp/testcase.yaml b/tests/net/icmp/testcase.yaml new file mode 100644 index 00000000000..f0e23579911 --- /dev/null +++ b/tests/net/icmp/testcase.yaml @@ -0,0 +1,32 @@ +common: + depends_on: netif + tags: net icmp +tests: + net.icmp.offloaded: + extra_configs: + - CONFIG_NET_OFFLOAD=y + - CONFIG_NET_IF_MAX_IPV6_COUNT=2 + - CONFIG_NET_IF_MAX_IPV4_COUNT=2 + net.icmp.socket_offloaded: + extra_configs: + - CONFIG_NET_SOCKETS_OFFLOAD=y + - CONFIG_NET_IF_MAX_IPV6_COUNT=2 + - CONFIG_NET_IF_MAX_IPV4_COUNT=2 + net.icmp.coop: + extra_configs: + - CONFIG_NET_TC_THREAD_COOPERATIVE=y + - CONFIG_NET_IF_MAX_IPV6_COUNT=2 + - CONFIG_NET_IF_MAX_IPV4_COUNT=2 + net.icmp.preempt: + extra_configs: + - CONFIG_NET_TC_THREAD_PREEMPTIVE=y + - CONFIG_NET_IF_MAX_IPV6_COUNT=2 + - CONFIG_NET_IF_MAX_IPV4_COUNT=2 + net.icmp.no_ipv4: + extra_configs: + - CONFIG_NET_IPV4=n + - CONFIG_NET_IF_MAX_IPV6_COUNT=2 + net.icmp.no_ipv6: + extra_configs: + - CONFIG_NET_IPV6=n + - CONFIG_NET_IF_MAX_IPV4_COUNT=2 diff --git a/tests/net/icmpv4/prj.conf b/tests/net/icmpv4/prj.conf index e12e61ddb84..202ad498a50 100644 --- a/tests/net/icmpv4/prj.conf +++ b/tests/net/icmpv4/prj.conf @@ -13,6 +13,5 @@ CONFIG_NET_LOG=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MAIN_STACK_SIZE=1280 CONFIG_NET_IPV4_HDR_OPTIONS=y diff --git a/tests/net/icmpv4/src/main.c b/tests/net/icmpv4/src/main.c index b063b752462..c48e480a769 100644 --- a/tests/net/icmpv4/src/main.c +++ b/tests/net/icmpv4/src/main.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2019 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -21,6 +22,7 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_ICMPV4_LOG_LEVEL); #include #include #include +#include #include "net_private.h" #include "icmpv4.h" @@ -114,24 +116,24 @@ static uint8_t current = TEST_ICMPV4_UNKNOWN; static struct in_addr my_addr = { { { 192, 0, 2, 1 } } }; static struct net_if *net_iface; -static enum net_verdict handle_reply_msg(struct net_pkt *pkt, - struct net_ipv4_hdr *ip_hdr, - struct net_icmp_hdr *icmp_hdr) +static int handle_reply_msg(struct net_icmp_ctx *ctx, + struct net_pkt *pkt, + struct net_icmp_ip_hdr *hdr, + struct net_icmp_hdr *icmp_hdr, + void *user_data) { + ARG_UNUSED(ctx); + ARG_UNUSED(hdr); + ARG_UNUSED(icmp_hdr); + ARG_UNUSED(user_data); + if (net_pkt_get_len(pkt) != sizeof(icmpv4_echo_rep)) { - return NET_DROP; + return -ENOMSG; } - net_pkt_unref(pkt); - return NET_OK; + return 0; } -static struct net_icmpv4_handler echo_rep_handler = { - .type = NET_ICMPV4_ECHO_REPLY, - .code = 0, - .handler = handle_reply_msg, -}; - struct net_icmpv4_context { uint8_t mac_addr[sizeof(struct net_eth_addr)]; struct net_linkaddr ll_addr; @@ -458,9 +460,14 @@ static void icmpv4_send_echo_req(void) static void icmpv4_send_echo_rep(void) { + static struct net_icmp_ctx ctx; struct net_pkt *pkt; + int ret; - net_icmpv4_register_handler(&echo_rep_handler); + ret = net_icmp_init_ctx(&ctx, NET_ICMPV4_ECHO_REPLY, + 0, handle_reply_msg); + zassert_equal(ret, 0, "Cannot register %s handler (%d)", + STRINGIFY(NET_ICMPV4_ECHO_REPLY), ret); pkt = prepare_echo_reply(net_iface); if (!pkt) { @@ -471,7 +478,9 @@ static void icmpv4_send_echo_rep(void) net_pkt_unref(pkt); zassert_true(false, "Failed to send"); } - net_icmpv4_unregister_handler(&echo_rep_handler); + + ret = net_icmp_cleanup_ctx(&ctx); + zassert_equal(ret, 0, "Cannot unregister handler (%d)", ret); } ZTEST(net_icmpv4, test_icmpv4_send_echo_req_opt) diff --git a/tests/net/icmpv6/prj.conf b/tests/net/icmpv6/prj.conf index a803a29637d..90ffdd82a96 100644 --- a/tests/net/icmpv6/prj.conf +++ b/tests/net/icmpv6/prj.conf @@ -1,7 +1,7 @@ CONFIG_NETWORKING=y CONFIG_NET_TEST=y CONFIG_NET_IPV6=y -CONFIG_NET_IPV4=y +CONFIG_NET_IPV4=n CONFIG_NET_BUF=y CONFIG_ZTEST_STACK_SIZE=1024 CONFIG_NET_PKT_RX_COUNT=2 @@ -12,6 +12,10 @@ CONFIG_NET_LOG=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MAIN_STACK_SIZE=1280 CONFIG_NET_L2_ETHERNET=n +CONFIG_NET_L2_DUMMY=y +CONFIG_NET_IPV6_NBR_CACHE=n +CONFIG_NET_IPV6_ND=n +CONFIG_NET_IPV6_DAD=n +CONFIG_NET_IPV6_MLD=n diff --git a/tests/net/icmpv6/src/main.c b/tests/net/icmpv6/src/main.c index 5546e0ff724..8594f628fc2 100644 --- a/tests/net/icmpv6/src/main.c +++ b/tests/net/icmpv6/src/main.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,10 +20,16 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_ICMPV6_LOG_LEVEL); #include #include +#include +#include +#include +#include "ipv6.h" +#include "net_private.h" #include "icmpv6.h" #include +static struct net_if *test_iface; static int handler_called; static int handler_status; @@ -30,7 +37,7 @@ static int handler_status; #define ICMPV6_MSG_SIZE 104 -static char icmpv6_echo_req[] = +static uint8_t icmpv6_echo_req[] = "\x60\x02\xea\x12\x00\x40\x3a\x40\xfe\x80\x00\x00\x00\x00\x00\x00" \ "\xda\xcb\x8a\xff\xfe\x34\xc8\xf3\xfe\x80\x00\x00\x00\x00\x00\x00" \ "\xec\x88\x2d\x63\xfd\x67\x31\x66\x80\x00\xa4\x24\x0b\x95\x00\x01" \ @@ -39,7 +46,7 @@ static char icmpv6_echo_req[] = "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" \ "\x30\x31\x32\x33\x34\x35\x36\x37"; -static char icmpv6_echo_rep[] = +static uint8_t icmpv6_echo_rep[] = "\x60\x09\x23\xa0\x00\x40\x3a\x40\xfe\x80\x00\x00\x00\x00\x00\x00" \ "\xec\x88\x2d\x63\xfd\x67\x31\x66\xfe\x80\x00\x00\x00\x00\x00\x00" \ "\xda\xcb\x8a\xff\xfe\x34\xc8\xf3\x81\x00\xa3\x24\x0b\x95\x00\x01" \ @@ -48,7 +55,7 @@ static char icmpv6_echo_rep[] = "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" \ "\x30\x31\x32\x33\x34\x35\x36\x37"; -static char icmpv6_inval_chksum[] = +static uint8_t icmpv6_inval_chksum[] = "\x60\x09\x23\xa0\x00\x40\x3a\x40\xfe\x80\x00\x00\x00\x00\x00\x00" \ "\xec\x88\x2d\x63\xfd\x67\x31\x66\xfe\x80\x00\x00\x00\x00\x00\x00" \ "\xda\xcb\x8a\xff\xfe\x34\xc8\xf3\x00\x00\xa3\x24\x0b\x95\x00\x01" \ @@ -57,19 +64,84 @@ static char icmpv6_inval_chksum[] = "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" \ "\x30\x31\x32\x33\x34\x35\x36\x37"; -static enum net_verdict handle_test_msg(struct net_pkt *pkt, - struct net_ipv6_hdr *ip_hdr, - struct net_icmp_hdr *icmp_hdr) +struct net_icmpv6_context { + uint8_t mac_addr[sizeof(struct net_eth_addr)]; + struct net_linkaddr ll_addr; +}; + +static struct net_icmpv6_context net_icmpv6_context_data; + +static int net_icmpv6_dev_init(const struct device *dev) +{ + struct net_icmpv6_context *net_icmpv6_context = dev->data; + + net_icmpv6_context = net_icmpv6_context; + + return 0; +} + +static uint8_t *net_icmpv6_get_mac(const struct device *dev) +{ + struct net_icmpv6_context *context = dev->data; + + if (context->mac_addr[2] == 0x00) { + /* 00-00-5E-00-53-xx Documentation RFC 7042 */ + context->mac_addr[0] = 0x00; + context->mac_addr[1] = 0x00; + context->mac_addr[2] = 0x5E; + context->mac_addr[3] = 0x00; + context->mac_addr[4] = 0x53; + context->mac_addr[5] = 0x01; + } + + return context->mac_addr; +} + +static void net_icmpv6_iface_init(struct net_if *iface) +{ + uint8_t *mac = net_icmpv6_get_mac(net_if_get_device(iface)); + + net_if_set_link_addr(iface, mac, 6, NET_LINK_ETHERNET); +} + +static int tester_send(const struct device *dev, struct net_pkt *pkt) +{ + net_pkt_unref(pkt); + return 0; +} + +static struct dummy_api net_icmpv6_if_api = { + .iface_api.init = net_icmpv6_iface_init, + .send = tester_send, +}; + +NET_DEVICE_INIT(net_icmpv6_test, "net_icmpv6_test", + net_icmpv6_dev_init, NULL, + &net_icmpv6_context_data, NULL, + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, + &net_icmpv6_if_api, DUMMY_L2, + NET_L2_GET_CTX_TYPE(DUMMY_L2), 127); + +static int handle_test_msg(struct net_icmp_ctx *ctx, + struct net_pkt *pkt, + struct net_icmp_ip_hdr *hdr, + struct net_icmp_hdr *icmp_hdr, + void *user_data) { + ARG_UNUSED(ctx); + ARG_UNUSED(hdr); + ARG_UNUSED(icmp_hdr); + ARG_UNUSED(user_data); + struct net_buf *last = net_buf_frag_last(pkt->buffer); - enum net_verdict ret; + int ret; if (last->len != ICMPV6_MSG_SIZE) { handler_status = -EINVAL; - ret = NET_DROP; + ret = -EINVAL; } else { handler_status = 0; - ret = NET_OK; + ret = 0; } handler_called++; @@ -77,47 +149,52 @@ static enum net_verdict handle_test_msg(struct net_pkt *pkt, return ret; } -static struct net_icmpv6_handler test_handler1 = { - .type = NET_ICMPV6_ECHO_REPLY, - .code = 0, - .handler = handle_test_msg, -}; - -static struct net_icmpv6_handler test_handler2 = { - .type = NET_ICMPV6_ECHO_REQUEST, - .code = 0, - .handler = handle_test_msg, -}; - -ZTEST(icmpv6_fn, test_icmpv6) +static struct net_pkt *create_pkt(uint8_t *data, int len, + struct net_ipv6_hdr **hdr) { - if (IS_ENABLED(CONFIG_NET_TC_THREAD_COOPERATIVE)) { - k_thread_priority_set(k_current_get(), - K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1)); - } else { - k_thread_priority_set(k_current_get(), K_PRIO_PREEMPT(9)); - } - - struct net_ipv6_hdr *hdr; struct net_pkt *pkt; - int ret; - - net_icmpv6_register_handler(&test_handler1); - net_icmpv6_register_handler(&test_handler2); pkt = net_pkt_alloc_with_buffer(NULL, ICMPV6_MSG_SIZE, AF_UNSPEC, 0, K_SECONDS(1)); zassert_not_null(pkt, "Allocation failed"); + net_pkt_set_iface(pkt, test_iface); + net_pkt_set_family(pkt, AF_INET6); net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr)); - net_pkt_write(pkt, icmpv6_inval_chksum, ICMPV6_MSG_SIZE); + net_pkt_write(pkt, data, len); - hdr = (struct net_ipv6_hdr *)pkt->buffer->data; net_pkt_cursor_init(pkt); + *hdr = net_pkt_cursor_get_pos(pkt); net_pkt_set_overwrite(pkt, true); net_pkt_skip(pkt, sizeof(struct net_ipv6_hdr)); + /* The cursor should be at the start of the ICMPv6 header */ + + return pkt; +} + +ZTEST(icmpv6_fn, test_icmpv6) +{ + struct net_icmp_ctx ctx1; + struct net_icmp_ctx ctx2; + struct net_ipv6_hdr *hdr; + struct net_pkt *pkt; + int ret; + + ret = net_icmp_init_ctx(&ctx1, NET_ICMPV6_ECHO_REPLY, + 0, handle_test_msg); + zassert_equal(ret, 0, "Cannot register %s handler (%d)", + STRINGIFY(NET_ICMPV6_ECHO_REPLY), ret); + + ret = net_icmp_init_ctx(&ctx2, NET_ICMPV6_ECHO_REQUEST, + 0, handle_test_msg); + zassert_equal(ret, 0, "Cannot register %s handler (%d)", + STRINGIFY(NET_ICMPV6_ECHO_REQUEST), ret); + + pkt = create_pkt(icmpv6_inval_chksum, ICMPV6_MSG_SIZE, &hdr); + zassert_not_null(pkt, "Cannot create pkt"); + ret = net_icmpv6_input(pkt, hdr); /**TESTPOINT: Check input*/ @@ -125,16 +202,8 @@ ZTEST(icmpv6_fn, test_icmpv6) handler_status = -1; - net_pkt_cursor_init(pkt); - net_pkt_set_overwrite(pkt, false); - pkt->buffer->len = 0; - - net_pkt_write(pkt, icmpv6_echo_rep, ICMPV6_MSG_SIZE); - - hdr = (struct net_ipv6_hdr *)pkt->buffer->data; - net_pkt_cursor_init(pkt); - net_pkt_set_overwrite(pkt, true); - net_pkt_skip(pkt, sizeof(struct net_ipv6_hdr)); + pkt = create_pkt(icmpv6_echo_rep, ICMPV6_MSG_SIZE, &hdr); + zassert_not_null(pkt, "Cannot create pkt"); ret = net_icmpv6_input(pkt, hdr); @@ -144,16 +213,8 @@ ZTEST(icmpv6_fn, test_icmpv6) handler_status = -1; - net_pkt_cursor_init(pkt); - net_pkt_set_overwrite(pkt, false); - pkt->buffer->len = 0; - - net_pkt_write(pkt, icmpv6_echo_req, ICMPV6_MSG_SIZE); - - hdr = (struct net_ipv6_hdr *)pkt->buffer->data; - net_pkt_cursor_init(pkt); - net_pkt_set_overwrite(pkt, true); - net_pkt_skip(pkt, sizeof(struct net_ipv6_hdr)); + pkt = create_pkt(icmpv6_echo_req, ICMPV6_MSG_SIZE, &hdr); + zassert_not_null(pkt, "Cannot create pkt"); ret = net_icmpv6_input(pkt, hdr); @@ -163,7 +224,27 @@ ZTEST(icmpv6_fn, test_icmpv6) /**TESTPOINT: Check input*/ zassert_true(!(handler_called != 2), "Callbacks not called properly"); + + ret = net_icmp_cleanup_ctx(&ctx1); + zassert_equal(ret, 0, "Cannot unregister handler (%d)", ret); + + ret = net_icmp_cleanup_ctx(&ctx2); + zassert_equal(ret, 0, "Cannot unregister handler (%d)", ret); +} + +static void *setup(void) +{ + if (IS_ENABLED(CONFIG_NET_TC_THREAD_COOPERATIVE)) { + k_thread_priority_set(k_current_get(), + K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1)); + } else { + k_thread_priority_set(k_current_get(), K_PRIO_PREEMPT(9)); + } + + test_iface = net_if_lookup_by_dev(DEVICE_GET(net_icmpv6_test)); + + return NULL; } /**test case main entry*/ -ZTEST_SUITE(icmpv6_fn, NULL, NULL, NULL, NULL, NULL); +ZTEST_SUITE(icmpv6_fn, NULL, setup, NULL, NULL, NULL); diff --git a/tests/net/ieee802154/6lo_fragment/prj.conf b/tests/net/ieee802154/6lo_fragment/prj.conf index 5e1ae744fff..7f2727a8588 100644 --- a/tests/net/ieee802154/6lo_fragment/prj.conf +++ b/tests/net/ieee802154/6lo_fragment/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NETWORKING=y CONFIG_NET_TEST=y CONFIG_NET_L2_DUMMY=y diff --git a/tests/net/ieee802154/6lo_fragment/testcase.yaml b/tests/net/ieee802154/6lo_fragment/testcase.yaml index 547a34c3a62..dad5d24d7b2 100644 --- a/tests/net/ieee802154/6lo_fragment/testcase.yaml +++ b/tests/net/ieee802154/6lo_fragment/testcase.yaml @@ -3,8 +3,10 @@ tests: platform_allow: - native_posix - native_posix_64 + - native_sim + - native_sim_64 integration_platforms: - - native_posix + - native_sim tags: - net - ieee802154 diff --git a/tests/net/ieee802154/custom_l2/prj.conf b/tests/net/ieee802154/custom_l2/prj.conf index e9fa365d3d1..b12cc61c0f8 100644 --- a/tests/net/ieee802154/custom_l2/prj.conf +++ b/tests/net/ieee802154/custom_l2/prj.conf @@ -9,4 +9,3 @@ CONFIG_NET_TEST=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/net/ieee802154/custom_l2/testcase.yaml b/tests/net/ieee802154/custom_l2/testcase.yaml index 4a289e924d8..97c58a16ba1 100644 --- a/tests/net/ieee802154/custom_l2/testcase.yaml +++ b/tests/net/ieee802154/custom_l2/testcase.yaml @@ -3,8 +3,10 @@ tests: platform_allow: - native_posix - native_posix_64 + - native_sim + - native_sim_64 integration_platforms: - - native_posix + - native_sim tags: - net - ieee802154 diff --git a/tests/net/ieee802154/l2/prj.conf b/tests/net/ieee802154/l2/prj.conf index 7d6dbc936b6..f5b77b6c6e2 100644 --- a/tests/net/ieee802154/l2/prj.conf +++ b/tests/net/ieee802154/l2/prj.conf @@ -33,7 +33,6 @@ CONFIG_MAIN_STACK_SIZE=2048 CONFIG_ZTEST_STACK_SIZE=3072 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SHELL=y CONFIG_SHELL_BACKEND_SERIAL=n diff --git a/tests/net/ieee802154/l2/src/ieee802154_fake_driver.c b/tests/net/ieee802154/l2/src/ieee802154_fake_driver.c index 0d3d15d6c69..ab6509ef0a6 100644 --- a/tests/net/ieee802154/l2/src/ieee802154_fake_driver.c +++ b/tests/net/ieee802154/l2/src/ieee802154_fake_driver.c @@ -26,7 +26,7 @@ uint8_t mock_ext_addr_be[8] = {0x00, 0x12, 0x4b, 0x00, 0x00, 0x9e, 0xa3, 0xc2}; static enum ieee802154_hw_caps fake_get_capabilities(const struct device *dev) { - return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ; + return IEEE802154_HW_FCS; } static int fake_cca(const struct device *dev) @@ -119,6 +119,20 @@ static int fake_stop(const struct device *dev) return 0; } +/* driver-allocated attribute memory - constant across all driver instances */ +IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26); + +/* API implementation: attr_get */ +static int fake_attr_get(const struct device *dev, enum ieee802154_attr attr, + struct ieee802154_attr_value *value) +{ + ARG_UNUSED(dev); + + return ieee802154_attr_get_channel_page_and_range( + attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915, + &drv_attr.phy_supported_channels, value); +} + static void fake_iface_init(struct net_if *iface) { struct ieee802154_context *ctx = net_if_l2_data(iface); @@ -152,6 +166,7 @@ static struct ieee802154_radio_api fake_radio_api = { .start = fake_start, .stop = fake_stop, .tx = fake_tx, + .attr_get = fake_attr_get, }; NET_DEVICE_INIT(fake, "fake_ieee802154", diff --git a/tests/net/ieee802154/l2/src/ieee802154_test.c b/tests/net/ieee802154/l2/src/ieee802154_test.c index 7347969d21a..7b4ff21dc52 100644 --- a/tests/net/ieee802154/l2/src/ieee802154_test.c +++ b/tests/net/ieee802154/l2/src/ieee802154_test.c @@ -216,7 +216,7 @@ static int disassociate(struct net_if *iface, struct ieee802154_context *ctx) &short_addr_not_associated, sizeof(short_addr_not_associated)); if (ret) { - NET_ERR("*** Failed to %s.\n", __func__); + NET_ERR("*** Failed to %s.", __func__); return ret; } @@ -235,14 +235,14 @@ static int associate(struct net_if *iface, struct ieee802154_context *ctx, uint1 ret = net_mgmt(NET_REQUEST_IEEE802154_SET_PAN_ID, iface, &mock_pan_id, sizeof(mock_pan_id)); if (ret) { - NET_ERR("*** Failed to set PAN ID in %s.\n", __func__); + NET_ERR("*** Failed to set PAN ID in %s.", __func__); return ret; } ret = net_mgmt(NET_REQUEST_IEEE802154_SET_SHORT_ADDR, iface, &short_addr, sizeof(short_addr)); if (ret) { - NET_ERR("*** Failed to set short addr in %s.\n", __func__); + NET_ERR("*** Failed to set short addr in %s.", __func__); return ret; } @@ -320,7 +320,7 @@ static struct net_pkt *get_data_pkt_with_ar(void) pkt = net_pkt_rx_alloc_with_buffer(net_iface, sizeof(data_pkt_with_ar), AF_UNSPEC, 0, K_FOREVER); if (!pkt) { - NET_ERR("*** No buffer to allocate\n"); + NET_ERR("*** No buffer to allocate"); return NULL; } @@ -354,7 +354,7 @@ static bool set_up_security(uint8_t security_level) if (net_mgmt(NET_REQUEST_IEEE802154_SET_SECURITY_SETTINGS, net_iface, ¶ms, sizeof(struct ieee802154_security_params))) { - NET_ERR("*** Failed to set security settings\n"); + NET_ERR("*** Failed to set security settings"); return false; } @@ -380,7 +380,7 @@ static bool tear_down_security(void) if (net_mgmt(NET_REQUEST_IEEE802154_SET_SECURITY_SETTINGS, net_iface, ¶ms, sizeof(struct ieee802154_security_params))) { - NET_ERR("*** Failed to tear down security settings\n"); + NET_ERR("*** Failed to tear down security settings"); return false; } @@ -407,17 +407,17 @@ static int set_up_recv_socket(enum net_sock_type socket_type) fd = socket(AF_PACKET, socket_type, ETH_P_IEEE802154); if (fd < 0) { - NET_ERR("*** Failed to create recv socket : %d\n", errno); + NET_ERR("*** Failed to create recv socket : %d", errno); return fd; } if (bind(fd, (const struct sockaddr *)&socket_sll, sizeof(struct sockaddr_ll))) { - NET_ERR("*** Failed to bind packet socket : %d\n", errno); + NET_ERR("*** Failed to bind packet socket : %d", errno); goto release_fd; } if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeo_optval, sizeof(timeo_optval))) { - NET_ERR("*** Failed to set reception timeout on packet socket : %d\n", errno); + NET_ERR("*** Failed to set reception timeout on packet socket : %d", errno); goto release_fd; } @@ -433,32 +433,31 @@ static bool test_packet_parsing(struct ieee802154_pkt_test *t) { struct ieee802154_mpdu mpdu = {0}; - NET_INFO("- Parsing packet 0x%p of frame %s\n", t->pkt, t->name); + NET_INFO("- Parsing packet 0x%p of frame %s", t->pkt, t->name); if (!ieee802154_validate_frame(t->pkt, t->length, &mpdu)) { - NET_ERR("*** Could not validate frame %s\n", t->name); + NET_ERR("*** Could not validate frame %s", t->name); return false; } if (mpdu.mhr.fs != t->mhr_check.fc_seq || mpdu.mhr.dst_addr != t->mhr_check.dst_addr || mpdu.mhr.src_addr != t->mhr_check.src_addr) { - NET_INFO("d: %p vs %p -- s: %p vs %p\n", + NET_INFO("d: %p vs %p -- s: %p vs %p", mpdu.mhr.dst_addr, t->mhr_check.dst_addr, mpdu.mhr.src_addr, t->mhr_check.src_addr); - NET_ERR("*** Wrong MPDU information on frame %s\n", - t->name); + NET_ERR("*** Wrong MPDU information on frame %s", t->name); return false; } if (mpdu.mhr.fs->sequence != t->sequence) { - NET_ERR("*** Invalid sequence number\n", t->name); + NET_ERR("*** Invalid sequence number for frame %s", t->name); return false; } if (mpdu.payload_length != t->payload_length) { - NET_ERR("*** Invalid payload length\n", t->name); + NET_ERR("*** Invalid payload length for frame %s", t->name); return false; } @@ -471,7 +470,7 @@ static bool test_ns_sending(struct ieee802154_pkt_test *t, bool with_short_addr) struct ieee802154_mpdu mpdu; bool result = false; - NET_INFO("- Sending NS packet\n"); + NET_INFO("- Sending NS packet"); /* ensure reproducible results */ ctx->sequence = t->sequence; @@ -481,7 +480,7 @@ static bool test_ns_sending(struct ieee802154_pkt_test *t, bool with_short_addr) } if (net_ipv6_send_ns(net_iface, NULL, &t->src, &t->dst, &t->dst, false)) { - NET_ERR("*** Could not create IPv6 NS packet\n"); + NET_ERR("*** Could not create IPv6 NS packet"); tear_down_short_addr(net_iface, ctx); goto out; } @@ -492,7 +491,7 @@ static bool test_ns_sending(struct ieee802154_pkt_test *t, bool with_short_addr) k_sem_take(&driver_lock, K_SECONDS(1)); if (!current_pkt->frags) { - NET_ERR("*** Could not send IPv6 NS packet\n"); + NET_ERR("*** Could not send IPv6 NS packet"); goto out; } @@ -501,14 +500,14 @@ static bool test_ns_sending(struct ieee802154_pkt_test *t, bool with_short_addr) if (!with_short_addr) { if (net_pkt_get_len(current_pkt) != t->length || memcmp(net_pkt_data(current_pkt), t->pkt, t->length)) { - NET_ERR("*** Sent packet deviates from expected packet\n"); + NET_ERR("*** Sent packet deviates from expected packet"); goto release_frag; } } if (!ieee802154_validate_frame(net_pkt_data(current_pkt), net_pkt_get_len(current_pkt), &mpdu)) { - NET_ERR("*** Sent packet is not valid\n"); + NET_ERR("*** Sent packet is not valid"); goto release_frag; } @@ -529,7 +528,7 @@ static bool test_wait_for_ack(struct ieee802154_pkt_test *t) bool result = false; bool ack_required; - NET_INFO("- Waiting for ACK reply when sending a data packet\n"); + NET_INFO("- Waiting for ACK reply when sending a data packet"); tx_pkt = get_data_pkt_with_ar(); if (!tx_pkt) { @@ -538,36 +537,36 @@ static bool test_wait_for_ack(struct ieee802154_pkt_test *t) ack_required = ieee802154_prepare_for_ack(net_iface, tx_pkt, tx_pkt->frags); if (!ack_required) { - NET_ERR("*** Expected AR flag to be set\n"); + NET_ERR("*** Expected AR flag to be set"); goto release_tx_pkt; } if (!ieee802154_validate_frame(net_pkt_data(tx_pkt), net_pkt_get_len(tx_pkt), &mpdu)) { - NET_ERR("*** Could not parse data pkt.\n"); + NET_ERR("*** Could not parse data pkt."); goto release_tx_pkt; } one_ack_pkt = net_pkt_rx_alloc_with_buffer(net_iface, IEEE802154_ACK_PKT_LENGTH, AF_UNSPEC, 0, K_FOREVER); if (!one_ack_pkt) { - NET_ERR("*** Could not allocate ack pkt.\n"); + NET_ERR("*** Could not allocate ack pkt."); goto release_tx_pkt; } if (!ieee802154_create_ack_frame(net_iface, one_ack_pkt, mpdu.mhr.fs->sequence)) { - NET_ERR("*** Could not create ack frame.\n"); + NET_ERR("*** Could not create ack frame."); goto release_tx_pkt; } pkt_hexdump(net_pkt_data(one_ack_pkt), net_pkt_get_len(one_ack_pkt)); if (ieee802154_handle_ack(net_iface, one_ack_pkt) != NET_OK) { - NET_ERR("*** Ack frame was not handled.\n"); + NET_ERR("*** Ack frame was not handled."); goto release_ack_pkt; } if (ieee802154_wait_for_ack(net_iface, ack_required) != 0) { - NET_ERR("*** Ack frame was not recorded.\n"); + NET_ERR("*** Ack frame was not recorded."); goto release_ack_pkt; } @@ -586,11 +585,11 @@ static bool test_packet_cloning_with_cb(void) struct net_pkt *pkt; struct net_pkt *cloned_pkt; - NET_INFO("- Cloning packet\n"); + NET_INFO("- Cloning packet"); pkt = net_pkt_rx_alloc_with_buffer(net_iface, 64, AF_UNSPEC, 0, K_NO_WAIT); if (!pkt) { - NET_ERR("*** No buffer to allocate\n"); + NET_ERR("*** No buffer to allocate"); return false; } @@ -604,7 +603,6 @@ static bool test_packet_cloning_with_cb(void) zassert_true(net_pkt_ieee802154_ack_fpb(cloned_pkt)); zassert_true(net_pkt_ieee802154_frame_secured(cloned_pkt)); - zassert_false(net_pkt_ieee802154_arb(cloned_pkt)); zassert_false(net_pkt_ieee802154_mac_hdr_rdy(cloned_pkt)); zassert_equal(net_pkt_ieee802154_lqi(cloned_pkt), 50U); zassert_equal(net_pkt_ieee802154_rssi(cloned_pkt), 0U); @@ -621,11 +619,11 @@ static bool test_packet_rssi_conversion(void) int8_t signed_rssi_dbm; struct net_pkt *pkt; - NET_INFO("- RSSI conversion between unsigned and signed representation\n"); + NET_INFO("- RSSI conversion between unsigned and signed representation"); pkt = net_pkt_rx_alloc_on_iface(net_iface, K_NO_WAIT); if (!pkt) { - NET_ERR("*** No pkt to allocate\n"); + NET_ERR("*** No pkt to allocate"); return false; } @@ -698,10 +696,10 @@ static bool test_dgram_packet_sending(void *dst_sll, uint8_t dst_sll_halen, uint goto out; } - NET_INFO("- Sending DGRAM packet via AF_PACKET socket\n"); + NET_INFO("- Sending DGRAM packet via AF_PACKET socket"); fd = socket(AF_PACKET, SOCK_DGRAM, ETH_P_IEEE802154); if (fd < 0) { - NET_ERR("*** Failed to create DGRAM socket : %d\n", errno); + NET_ERR("*** Failed to create DGRAM socket : %d", errno); goto reset_security; } @@ -718,13 +716,13 @@ static bool test_dgram_packet_sending(void *dst_sll, uint8_t dst_sll_halen, uint } if (bind(fd, (const struct sockaddr *)&socket_sll, sizeof(struct sockaddr_ll))) { - NET_ERR("*** Failed to bind packet socket : %d\n", errno); + NET_ERR("*** Failed to bind packet socket : %d", errno); goto release_fd; } if (sendto(fd, payload, sizeof(payload), 0, (const struct sockaddr *)&pkt_dst_sll, sizeof(struct sockaddr_ll)) != sizeof(payload)) { - NET_ERR("*** Failed to send, errno %d\n", errno); + NET_ERR("*** Failed to send, errno %d", errno); goto release_fd; } @@ -732,7 +730,7 @@ static bool test_dgram_packet_sending(void *dst_sll, uint8_t dst_sll_halen, uint k_sem_take(&driver_lock, K_SECONDS(1)); if (!current_pkt->frags) { - NET_ERR("*** Could not send DGRAM packet\n"); + NET_ERR("*** Could not send DGRAM packet"); goto release_fd; } @@ -740,7 +738,7 @@ static bool test_dgram_packet_sending(void *dst_sll, uint8_t dst_sll_halen, uint if (!ieee802154_validate_frame(net_pkt_data(current_pkt), net_pkt_get_len(current_pkt), &mpdu)) { - NET_ERR("*** Sent packet is not valid\n"); + NET_ERR("*** Sent packet is not valid"); goto release_frag; } @@ -748,12 +746,12 @@ static bool test_dgram_packet_sending(void *dst_sll, uint8_t dst_sll_halen, uint net_pkt_lladdr_src(current_pkt)->len = net_if_get_link_addr(net_iface)->len; if (!ieee802154_decipher_data_frame(net_iface, current_pkt, &mpdu)) { - NET_ERR("*** Cannot decipher/authenticate packet\n"); + NET_ERR("*** Cannot decipher/authenticate packet"); goto release_frag; } if (memcmp(mpdu.payload, payload, sizeof(payload)) != 0) { - NET_ERR("*** Payload of sent packet is incorrect\n"); + NET_ERR("*** Payload of sent packet is incorrect"); goto release_frag; } @@ -798,7 +796,7 @@ static bool test_dgram_packet_reception(void *src_ll_addr, uint8_t src_ll_addr_l goto out; } - NET_INFO("- Receiving DGRAM packet via AF_PACKET socket\n"); + NET_INFO("- Receiving DGRAM packet via AF_PACKET socket"); fd = set_up_recv_socket(SOCK_DGRAM); if (fd < 0) { @@ -807,7 +805,7 @@ static bool test_dgram_packet_reception(void *src_ll_addr, uint8_t src_ll_addr_l pkt = net_pkt_rx_alloc(K_FOREVER); if (!pkt) { - NET_ERR("*** Failed to allocate net pkt.\n"); + NET_ERR("*** Failed to allocate net pkt."); goto release_fd; } @@ -819,14 +817,14 @@ static bool test_dgram_packet_reception(void *src_ll_addr, uint8_t src_ll_addr_l src_ll_addr_len == IEEE802154_EXT_ADDR_LENGTH) { pkt->lladdr_src.addr = src_ll_addr; } else { - NET_ERR("*** Illegal L2 source address length.\n"); + NET_ERR("*** Illegal L2 source address length."); goto release_pkt; } pkt->lladdr_src.len = src_ll_addr_len; frame_buf = net_pkt_get_frag(pkt, IEEE802154_MTU, K_FOREVER); if (!frame_buf) { - NET_ERR("*** Failed to allocate net pkt frag.\n"); + NET_ERR("*** Failed to allocate net pkt frag."); goto release_pkt; } @@ -846,7 +844,7 @@ static bool test_dgram_packet_reception(void *src_ll_addr, uint8_t src_ll_addr_l } else if (src_ll_addr_len == IEEE802154_EXT_ADDR_LENGTH) { sys_memcpy_swap(ctx->ext_addr, src_ll_addr, sizeof(ctx->ext_addr)); } else { - NET_ERR("*** Illegal L2 source address length.\n"); + NET_ERR("*** Illegal L2 source address length."); goto release_pkt; } @@ -860,19 +858,19 @@ static bool test_dgram_packet_reception(void *src_ll_addr, uint8_t src_ll_addr_l } if (!frame_result) { - NET_ERR("*** Error while creating data frame.\n"); + NET_ERR("*** Error while creating data frame."); goto release_pkt; }; net_pkt_frag_add(pkt, frame_buf); if (net_recv_data(net_iface, pkt)) { - NET_ERR("*** Error while processing packet.\n"); + NET_ERR("*** Error while processing packet."); goto release_pkt; } if (current_pkt->frags) { - NET_ERR("*** Generated unexpected (ACK?) packet when processing packet.\n"); + NET_ERR("*** Generated unexpected (ACK?) packet when processing packet."); net_pkt_frag_unref(current_pkt->frags); current_pkt->frags = NULL; goto release_pkt; @@ -882,14 +880,14 @@ static bool test_dgram_packet_reception(void *src_ll_addr, uint8_t src_ll_addr_l received_len = recvfrom(fd, received_payload, sizeof(received_payload), 0, (struct sockaddr *)&recv_src_sll, &recv_src_sll_len); if (received_len < 0) { - NET_ERR("*** Failed to receive packet, errno %d\n", errno); + NET_ERR("*** Failed to receive packet, errno %d", errno); goto release_pkt; } pkt_hexdump(received_payload, received_len); if (received_len != sizeof(payload) || memcmp(received_payload, payload, sizeof(payload))) { - NET_ERR("*** Payload of received packet is incorrect\n"); + NET_ERR("*** Payload of received packet is incorrect"); goto release_pkt; } @@ -898,7 +896,7 @@ static bool test_dgram_packet_reception(void *src_ll_addr, uint8_t src_ll_addr_l recv_src_sll.sll_ifindex != net_if_get_by_iface(net_iface) || recv_src_sll.sll_halen != src_ll_addr_len || memcmp(recv_src_sll.sll_addr, src_ll_addr, src_ll_addr_len)) { - NET_ERR("*** Source L2 address of received packet is incorrect\n"); + NET_ERR("*** Source L2 address of received packet is incorrect"); goto release_pkt; } @@ -924,11 +922,11 @@ static bool test_raw_packet_sending(void) bool result = false; int fd; - NET_INFO("- Sending RAW packet via AF_PACKET socket\n"); + NET_INFO("- Sending RAW packet via AF_PACKET socket"); fd = socket(AF_PACKET, SOCK_RAW, ETH_P_IEEE802154); if (fd < 0) { - NET_ERR("*** Failed to create RAW socket : %d\n", errno); + NET_ERR("*** Failed to create RAW socket : %d", errno); goto out; } @@ -937,7 +935,7 @@ static bool test_raw_packet_sending(void) socket_sll.sll_protocol = ETH_P_IEEE802154; if (bind(fd, (const struct sockaddr *)&socket_sll, sizeof(struct sockaddr_ll))) { - NET_ERR("*** Failed to bind packet socket : %d\n", errno); + NET_ERR("*** Failed to bind packet socket : %d", errno); goto release_fd; } @@ -947,7 +945,7 @@ static bool test_raw_packet_sending(void) msg.msg_iovlen = 1; if (sendmsg(fd, &msg, 0) != sizeof(raw_payload)) { - NET_ERR("*** Failed to send, errno %d\n", errno); + NET_ERR("*** Failed to send, errno %d", errno); goto release_fd; } @@ -955,7 +953,7 @@ static bool test_raw_packet_sending(void) k_sem_take(&driver_lock, K_SECONDS(1)); if (!current_pkt->frags) { - NET_ERR("*** Could not send RAW packet\n"); + NET_ERR("*** Could not send RAW packet"); goto release_fd; } @@ -963,13 +961,13 @@ static bool test_raw_packet_sending(void) if (!ieee802154_validate_frame(net_pkt_data(current_pkt), net_pkt_get_len(current_pkt), &mpdu)) { - NET_ERR("*** Sent packet is not valid\n"); + NET_ERR("*** Sent packet is not valid"); goto release_frag; } if (memcmp(mpdu.payload, &raw_payload[RAW_MAC_PAYLOAD_START_INDEX], RAW_MAC_PAYLOAD_LENGTH) != 0) { - NET_ERR("*** Payload of sent packet is incorrect\n"); + NET_ERR("*** Payload of sent packet is incorrect"); goto release_frag; } @@ -995,7 +993,7 @@ static bool test_raw_packet_reception(void) result = false; - NET_INFO("- Receiving RAW packet via AF_PACKET socket\n"); + NET_INFO("- Receiving RAW packet via AF_PACKET socket"); fd = set_up_recv_socket(SOCK_RAW); if (fd < 0) { @@ -1004,13 +1002,13 @@ static bool test_raw_packet_reception(void) pkt = net_pkt_rx_alloc(K_FOREVER); if (!pkt) { - NET_ERR("*** Failed to allocate net pkt.\n"); + NET_ERR("*** Failed to allocate net pkt."); goto release_fd; } frame_buf = net_pkt_get_frag(pkt, sizeof(raw_payload), K_FOREVER); if (!frame_buf) { - NET_ERR("*** Failed to allocate net pkt frag.\n"); + NET_ERR("*** Failed to allocate net pkt frag."); goto release_pkt; } @@ -1018,12 +1016,12 @@ static bool test_raw_packet_reception(void) net_pkt_frag_add(pkt, frame_buf); if (net_recv_data(net_iface, pkt)) { - NET_ERR("*** Error while processing packet.\n"); + NET_ERR("*** Error while processing packet."); goto release_pkt; } if (current_pkt->frags) { - NET_ERR("*** Generated unexpected packet when processing packet.\n"); + NET_ERR("*** Generated unexpected packet when processing packet."); net_pkt_frag_unref(current_pkt->frags); current_pkt->frags = NULL; goto release_pkt; @@ -1035,7 +1033,7 @@ static bool test_raw_packet_reception(void) */ received_len = recv(fd, received_payload, sizeof(received_payload), 0); if (received_len < 0) { - NET_ERR("*** Failed to receive packet, errno %d\n", errno); + NET_ERR("*** Failed to receive packet, errno %d", errno); goto release_pkt; } @@ -1051,7 +1049,7 @@ static bool test_raw_packet_reception(void) */ if (received_len != sizeof(raw_payload) || memcmp(received_payload, raw_payload, sizeof(raw_payload))) { - NET_ERR("*** Payload of received packet is incorrect\n"); + NET_ERR("*** Payload of received packet is incorrect"); goto release_pkt; } @@ -1108,21 +1106,21 @@ static bool test_recv_and_send_ack_reply(struct ieee802154_pkt_test *t) int received_len; int fd; - NET_INFO("- Sending ACK reply to a data packet\n"); + NET_INFO("- Sending ACK reply to a data packet"); fd = socket(AF_PACKET, SOCK_DGRAM, ETH_P_IEEE802154); if (fd < 0) { - NET_ERR("*** Failed to create DGRAM socket : %d\n", errno); + NET_ERR("*** Failed to create DGRAM socket : %d", errno); goto out; } if (bind(fd, (const struct sockaddr *)&socket_sll, sizeof(struct sockaddr_ll))) { - NET_ERR("*** Failed to bind packet socket : %d\n", errno); + NET_ERR("*** Failed to bind packet socket : %d", errno); goto release_fd; } if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeo_optval, sizeof(timeo_optval))) { - NET_ERR("*** Failed to set reception timeout on packet socket : %d\n", errno); + NET_ERR("*** Failed to set reception timeout on packet socket : %d", errno); goto release_fd; } @@ -1144,7 +1142,7 @@ static bool test_recv_and_send_ack_reply(struct ieee802154_pkt_test *t) received_len = recvfrom(fd, received_payload, sizeof(received_payload), 0, (struct sockaddr *)&recv_src_sll, &recv_src_sll_len); if (received_len < 0) { - NET_ERR("*** Failed to receive packet, errno %d\n", errno); + NET_ERR("*** Failed to receive packet, errno %d", errno); goto release_rx_pkt; } @@ -1154,7 +1152,7 @@ static bool test_recv_and_send_ack_reply(struct ieee802154_pkt_test *t) recv_src_sll.sll_family != AF_PACKET || recv_src_sll.sll_protocol != ETH_P_IEEE802154 || recv_src_sll.sll_halen != IEEE802154_EXT_ADDR_LENGTH || memcmp(recv_src_sll.sll_addr, mac_be, IEEE802154_EXT_ADDR_LENGTH)) { - NET_ERR("*** Received socket address does not compare\n", errno); + NET_ERR("*** Received socket address does not compare", errno); goto release_rx_pkt; } @@ -1162,7 +1160,7 @@ static bool test_recv_and_send_ack_reply(struct ieee802154_pkt_test *t) if (memcmp(expected_rx_pkt, received_payload, sizeof(expected_rx_pkt))) { - NET_ERR("*** Received uncompressed IPv6 payload does not compare\n"); + NET_ERR("*** Received uncompressed IPv6 payload does not compare"); goto release_rx_pkt; } @@ -1171,7 +1169,7 @@ static bool test_recv_and_send_ack_reply(struct ieee802154_pkt_test *t) /* an ACK packet should be in current_pkt */ if (!current_pkt->frags) { - NET_ERR("*** No ACK reply sent\n"); + NET_ERR("*** No ACK reply sent"); goto release_rx_pkt; } @@ -1179,18 +1177,18 @@ static bool test_recv_and_send_ack_reply(struct ieee802154_pkt_test *t) if (!ieee802154_validate_frame(net_pkt_data(current_pkt), net_pkt_get_len(current_pkt), &mpdu)) { - NET_ERR("*** ACK Reply is invalid\n"); + NET_ERR("*** ACK Reply is invalid"); goto release_tx_frag; } if (memcmp(mpdu.mhr.fs, t->mhr_check.fc_seq, sizeof(struct ieee802154_fcf_seq))) { - NET_ERR("*** ACK Reply does not compare\n"); + NET_ERR("*** ACK Reply does not compare"); goto release_tx_frag; } if (mpdu.mhr.fs->sequence != t->sequence) { - NET_ERR("*** Sequence number invalid\n"); + NET_ERR("*** Sequence number invalid"); goto release_tx_frag; } @@ -1219,29 +1217,29 @@ static bool initialize_test_environment(void) current_pkt = net_pkt_rx_alloc(K_FOREVER); if (!current_pkt) { - NET_ERR("*** No buffer to allocate\n"); + NET_ERR("*** No buffer to allocate"); return false; } dev = device_get_binding("fake_ieee802154"); if (!dev) { - NET_ERR("*** Could not get fake device\n"); + NET_ERR("*** Could not get fake device"); goto release_pkt; } net_iface = net_if_lookup_by_dev(dev); if (!net_iface) { - NET_ERR("*** Could not get fake iface\n"); + NET_ERR("*** Could not get fake iface"); goto release_pkt; } if (net_mgmt(NET_REQUEST_IEEE802154_SET_PAN_ID, net_iface, &mock_pan_id, sizeof(mock_pan_id))) { - NET_ERR("*** Failed to set PAN ID in %s.\n", __func__); + NET_ERR("*** Failed to set PAN ID in %s.", __func__); goto release_pkt; } - NET_INFO("Fake IEEE 802.15.4 network interface ready\n"); + NET_INFO("Fake IEEE 802.15.4 network interface ready"); ieee_addr_hexdump(net_if_get_link_addr(net_iface)->addr, 8); diff --git a/tests/net/ieee802154/l2/testcase.yaml b/tests/net/ieee802154/l2/testcase.yaml index 2be38d93d24..795bd13304c 100644 --- a/tests/net/ieee802154/l2/testcase.yaml +++ b/tests/net/ieee802154/l2/testcase.yaml @@ -2,8 +2,10 @@ common: platform_allow: - native_posix - native_posix_64 + - native_sim + - native_sim_64 integration_platforms: - - native_posix + - native_sim tags: - net - ieee802154 diff --git a/tests/net/iface/prj.conf b/tests/net/iface/prj.conf index 6b024cd84d7..71b3f4dfcf8 100644 --- a/tests/net/iface/prj.conf +++ b/tests/net/iface/prj.conf @@ -25,7 +25,6 @@ CONFIG_NET_MAX_NEXTHOPS=8 CONFIG_NET_IPV6_MAX_NEIGHBORS=8 CONFIG_NET_IPV6_ND=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NET_IF_MAX_IPV4_COUNT=4 CONFIG_NET_IF_MAX_IPV6_COUNT=4 CONFIG_TEST_USERSPACE=y diff --git a/tests/net/iface/src/main.c b/tests/net/iface/src/main.c index 2c12e5e15bb..b33845608d6 100644 --- a/tests/net/iface/src/main.c +++ b/tests/net/iface/src/main.c @@ -19,7 +19,7 @@ LOG_MODULE_REGISTER(net_test, NET_LOG_LEVEL); #include #include #include -#include +#include #include @@ -776,8 +776,12 @@ ZTEST(net_iface, test_v4_addr_add_rm) #define MY_ADDR_V4_USER { { { 10, 0, 0, 2 } } } #define UNKNOWN_ADDR_V4_USER { { { 5, 6, 7, 8 } } } -static void v4_addr_add_user(void) +static void v4_addr_add_user(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct in_addr my_addr = MY_ADDR_V4_USER; bool ret; @@ -788,7 +792,7 @@ static void v4_addr_add_user(void) static void v4_addr_add_user_from_userspace(void) { k_thread_access_grant(k_current_get(), net_if_get_by_index(1)); - k_thread_user_mode_enter((k_thread_entry_t)v4_addr_add_user, NULL, + k_thread_user_mode_enter(v4_addr_add_user, NULL, NULL, NULL); } @@ -805,8 +809,12 @@ static void v4_addr_lookup_user(void) zassert_equal(ret, 0, "IPv4 address found"); } -static void v4_addr_rm_user(void) +static void v4_addr_rm_user(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct in_addr my_addr = MY_ADDR_V4_USER; bool ret; @@ -817,7 +825,7 @@ static void v4_addr_rm_user(void) static void v4_addr_rm_user_from_userspace(void) { k_thread_access_grant(k_current_get(), net_if_get_by_index(1)); - k_thread_user_mode_enter((k_thread_entry_t)v4_addr_rm_user, NULL, + k_thread_user_mode_enter(v4_addr_rm_user, NULL, NULL, NULL); } @@ -940,8 +948,12 @@ ZTEST(net_iface, test_v6_addr_add_rm_solicited) #define UNKNOWN_ADDR_V6_USER { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0x66 } } } -static void v6_addr_add_user(void) +static void v6_addr_add_user(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct in6_addr my_addr = MY_ADDR_V6_USER; bool ret; @@ -952,7 +964,7 @@ static void v6_addr_add_user(void) static void v6_addr_add_user_from_userspace(void) { k_thread_access_grant(k_current_get(), net_if_get_by_index(1)); - k_thread_user_mode_enter((k_thread_entry_t)v6_addr_add_user, NULL, + k_thread_user_mode_enter(v6_addr_add_user, NULL, NULL, NULL); } @@ -969,8 +981,12 @@ static void v6_addr_lookup_user(void) zassert_equal(ret, 0, "IPv6 address found"); } -static void v6_addr_rm_user(void) +static void v6_addr_rm_user(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct in6_addr my_addr = MY_ADDR_V6_USER; bool ret; @@ -984,7 +1000,7 @@ static void v6_addr_rm_user(void) static void v6_addr_rm_user_from_userspace(void) { k_thread_access_grant(k_current_get(), net_if_get_by_index(1)); - k_thread_user_mode_enter((k_thread_entry_t)v6_addr_rm_user, NULL, + k_thread_user_mode_enter(v6_addr_rm_user, NULL, NULL, NULL); } @@ -995,8 +1011,12 @@ ZTEST(net_iface, test_v6_addr_add_rm_user_from_userspace) v6_addr_rm_user_from_userspace(); } -static void netmask_addr_add(void) +static void netmask_addr_add(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct in_addr my_netmask = { { { 255, 255, 255, 0 } } }; bool ret; @@ -1006,13 +1026,13 @@ static void netmask_addr_add(void) ZTEST(net_iface, test_netmask_addr_add) { - netmask_addr_add(); + netmask_addr_add(NULL, NULL, NULL); } static void netmask_addr_add_from_userspace(void) { k_thread_access_grant(k_current_get(), net_if_get_by_index(1)); - k_thread_user_mode_enter((k_thread_entry_t)netmask_addr_add, NULL, + k_thread_user_mode_enter(netmask_addr_add, NULL, NULL, NULL); } @@ -1021,8 +1041,12 @@ ZTEST(net_iface, test_netmask_addr_add_from_userspace) netmask_addr_add_from_userspace(); } -static void gw_addr_add(void) +static void gw_addr_add(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct in_addr my_gw = { { { 192, 0, 2, 254 } } }; bool ret; @@ -1032,13 +1056,13 @@ static void gw_addr_add(void) ZTEST(net_iface, test_gw_addr_add) { - gw_addr_add(); + gw_addr_add(NULL, NULL, NULL); } static void gw_addr_add_from_userspace(void) { k_thread_access_grant(k_current_get(), net_if_get_by_index(1)); - k_thread_user_mode_enter((k_thread_entry_t)gw_addr_add, NULL, + k_thread_user_mode_enter(gw_addr_add, NULL, NULL, NULL); } @@ -1047,21 +1071,25 @@ ZTEST(net_iface, test_gw_addr_add_from_userspace) gw_addr_add_from_userspace(); } -static void get_by_index(void) +static void get_by_index(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + zassert_not_null(net_if_get_by_index(1), "Cannot get interface at index 1"); } ZTEST(net_iface, test_get_by_index) { - get_by_index(); + get_by_index(NULL, NULL, NULL); } static void get_by_index_from_userspace(void) { k_thread_access_grant(k_current_get(), net_if_get_by_index(1)); - k_thread_user_mode_enter((k_thread_entry_t)get_by_index, NULL, + k_thread_user_mode_enter(get_by_index, NULL, NULL, NULL); } @@ -1157,7 +1185,7 @@ ZTEST(net_iface, test_interface_name) ret = net_if_set_name(iface, name); zassert_equal(ret, -ENAMETOOLONG, "Unexpected value (%d) returned", ret); - name = "eth0"; + name = "abc0"; ret = net_if_set_name(iface, name); zassert_equal(ret, 0, "Unexpected value (%d) returned", ret); diff --git a/tests/net/igmp/prj.conf b/tests/net/igmp/prj.conf index aaa47ade92c..b9119257232 100644 --- a/tests/net/igmp/prj.conf +++ b/tests/net/igmp/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MAIN_STACK_SIZE=2048 CONFIG_NET_TEST=y CONFIG_NETWORKING=y diff --git a/tests/net/igmp/src/main.c b/tests/net/igmp/src/main.c index 99e591e1d8a..473b66d3241 100644 --- a/tests/net/igmp/src/main.c +++ b/tests/net/igmp/src/main.c @@ -28,7 +28,7 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_IPV4_LOG_LEVEL); #include #include -#include +#include #include "ipv4.h" diff --git a/tests/net/ip-addr/prj.conf b/tests/net/ip-addr/prj.conf index 131a96a458d..3f718037e91 100644 --- a/tests/net/ip-addr/prj.conf +++ b/tests/net/ip-addr/prj.conf @@ -19,4 +19,3 @@ CONFIG_NET_IF_MCAST_IPV4_ADDR_COUNT=3 CONFIG_NET_L2_DUMMY=y CONFIG_NET_L2_ETHERNET=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/net/ip-addr/src/main.c b/tests/net/ip-addr/src/main.c index f3e37b29e29..23f8d4b6437 100644 --- a/tests/net/ip-addr/src/main.c +++ b/tests/net/ip-addr/src/main.c @@ -16,7 +16,7 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_IPV6_LOG_LEVEL); #include #include #include -#include +#include #include diff --git a/tests/net/ipv4_fragment/prj.conf b/tests/net/ipv4_fragment/prj.conf index 546f866ccd7..d8c4d1ff534 100644 --- a/tests/net/ipv4_fragment/prj.conf +++ b/tests/net/ipv4_fragment/prj.conf @@ -22,7 +22,6 @@ CONFIG_NET_UDP_CHECKSUM=y CONFIG_NET_TCP_CHECKSUM=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=2048 CONFIG_INIT_STACKS=y diff --git a/tests/net/ipv4_fragment/src/main.c b/tests/net/ipv4_fragment/src/main.c index 5ebe3817330..7375aab17aa 100644 --- a/tests/net/ipv4_fragment/src/main.c +++ b/tests/net/ipv4_fragment/src/main.c @@ -13,7 +13,7 @@ LOG_MODULE_REGISTER(net_ipv4_test, CONFIG_NET_IPV4_LOG_LEVEL); #include #include #include -#include +#include #include #include #include @@ -636,7 +636,7 @@ ZTEST(net_ipv4_fragment, test_udp) net_pkt_cursor_init(pkt); net_pkt_set_overwrite(pkt, true); net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt)); - net_udp_finalize(pkt); + net_udp_finalize(pkt, false); pkt_recv_expected_size = net_pkt_get_len(pkt); @@ -706,7 +706,7 @@ ZTEST(net_ipv4_fragment, test_tcp) net_pkt_set_overwrite(pkt, true); net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt)); - net_tcp_finalize(pkt); + net_tcp_finalize(pkt, false); pkt_recv_expected_size = net_pkt_get_len(pkt); @@ -849,7 +849,7 @@ ZTEST(net_ipv4_fragment, test_do_not_fragment) net_pkt_cursor_init(pkt); net_pkt_set_overwrite(pkt, true); net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt)); - net_udp_finalize(pkt); + net_udp_finalize(pkt, false); pkt_recv_expected_size = net_pkt_get_len(pkt); diff --git a/tests/net/ipv6/prj.conf b/tests/net/ipv6/prj.conf index 4051207d88c..c2f80f6ead4 100644 --- a/tests/net/ipv6/prj.conf +++ b/tests/net/ipv6/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y #CONFIG_ZTEST_STACK_SIZE=4096 CONFIG_MAIN_STACK_SIZE=2048 CONFIG_NETWORKING=y diff --git a/tests/net/ipv6/src/main.c b/tests/net/ipv6/src/main.c index f9dd456cdca..6d8a1a5deee 100644 --- a/tests/net/ipv6/src/main.c +++ b/tests/net/ipv6/src/main.c @@ -15,7 +15,7 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_IPV6_LOG_LEVEL); #include #include #include -#include +#include #include diff --git a/tests/net/ipv6_fragment/prj.conf b/tests/net/ipv6_fragment/prj.conf index c7c62ce972f..e8a68b913b6 100644 --- a/tests/net/ipv6_fragment/prj.conf +++ b/tests/net/ipv6_fragment/prj.conf @@ -25,7 +25,6 @@ CONFIG_NET_UDP_CHECKSUM=y CONFIG_NET_IF_MAX_IPV6_COUNT=2 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=2048 CONFIG_INIT_STACKS=y diff --git a/tests/net/ipv6_fragment/src/main.c b/tests/net/ipv6_fragment/src/main.c index bcf78a48285..adb8652bdc1 100644 --- a/tests/net/ipv6_fragment/src/main.c +++ b/tests/net/ipv6_fragment/src/main.c @@ -16,7 +16,7 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_IPV6_LOG_LEVEL); #include #include #include -#include +#include #include @@ -2015,7 +2015,7 @@ ZTEST(net_ipv6_fragment, test_send_ipv6_fragment) net_pkt_set_overwrite(pkt, true); net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) + net_pkt_ipv6_ext_len(pkt)); - net_udp_finalize(pkt); + net_udp_finalize(pkt, false); test_failed = false; test_complete = false; @@ -2175,7 +2175,7 @@ ZTEST(net_ipv6_fragment, test_send_ipv6_fragment_udp_loopback) net_pkt_set_overwrite(pkt, true); net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) + net_pkt_ipv6_ext_len(pkt)); - net_udp_finalize(pkt); + net_udp_finalize(pkt, false); test_failed = false; test_complete = false; @@ -2217,9 +2217,11 @@ static uint8_t ipv6_reass_frag2[] = { static uint16_t test_recv_payload_len = 1300U; -static enum net_verdict handle_ipv6_echo_reply(struct net_pkt *pkt, - struct net_ipv6_hdr *ip_hdr, - struct net_icmp_hdr *icmp_hdr) +static int handle_ipv6_echo_reply(struct net_icmp_ctx *ctx, + struct net_pkt *pkt, + struct net_icmp_ip_hdr *ip_hdr, + struct net_icmp_hdr *icmp_hdr, + void *user_data) { const struct net_ipv6_hdr *hdr = NET_IPV6_HDR(pkt); uint8_t verify_buf[NET_IPV6H_LEN]; @@ -2228,6 +2230,11 @@ static enum net_verdict handle_ipv6_echo_reply(struct net_pkt *pkt, uint16_t i; uint8_t expected_data = 0; + ARG_UNUSED(ctx); + ARG_UNUSED(ip_hdr); + ARG_UNUSED(icmp_hdr); + ARG_UNUSED(user_data); + NET_DBG("Data %p received", pkt); zassert_equal(net_pkt_get_len(pkt), expected_pkt_length, "Invalid packet length"); @@ -2275,8 +2282,6 @@ static enum net_verdict handle_ipv6_echo_reply(struct net_pkt *pkt, i++; } - net_pkt_unref(pkt); - k_sem_give(&wait_data); return NET_OK; @@ -2292,13 +2297,12 @@ ZTEST(net_ipv6_fragment, test_recv_ipv6_fragment) uint16_t payload2_len; uint8_t data; int ret; - static struct net_icmpv6_handler ping6_handler = { - .type = NET_ICMPV6_ECHO_REPLY, - .code = 0, - .handler = handle_ipv6_echo_reply, - }; + struct net_icmp_ctx ctx; - net_icmpv6_register_handler(&ping6_handler); + ret = net_icmp_init_ctx(&ctx, NET_ICMPV6_ECHO_REPLY, + 0, handle_ipv6_echo_reply); + zassert_equal(ret, 0, "Cannot register %s handler (%d)", + STRINGIFY(NET_ICMPV6_ECHO_REPLY), ret); /* Fragment 1 */ data = 0U; @@ -2387,7 +2391,7 @@ ZTEST(net_ipv6_fragment, test_recv_ipv6_fragment) zassert_true(false, "Timeout"); } - net_icmpv6_unregister_handler(&ping6_handler); + net_icmp_cleanup_ctx(&ctx); } ZTEST_SUITE(net_ipv6_fragment, NULL, test_setup, NULL, NULL, NULL); diff --git a/tests/net/lib/coap/prj.conf b/tests/net/lib/coap/prj.conf index 854a3320b36..63f863843fd 100644 --- a/tests/net/lib/coap/prj.conf +++ b/tests/net/lib/coap/prj.conf @@ -1,7 +1,6 @@ #Testing CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NET_TEST=y # Generic networking options diff --git a/tests/net/lib/coap/testcase.yaml b/tests/net/lib/coap/testcase.yaml index d3d4d6162b9..add02ecf992 100644 --- a/tests/net/lib/coap/testcase.yaml +++ b/tests/net/lib/coap/testcase.yaml @@ -1,5 +1,3 @@ -common: - filter: TOOLCHAIN_HAS_NEWLIB == 1 tests: net.coap.simple: min_ram: 16 diff --git a/tests/net/lib/coap_client/CMakeLists.txt b/tests/net/lib/coap_client/CMakeLists.txt index 9486b914706..2e94112f0b0 100644 --- a/tests/net/lib/coap_client/CMakeLists.txt +++ b/tests/net/lib/coap_client/CMakeLists.txt @@ -24,6 +24,6 @@ add_compile_definitions(CONFIG_COAP_CLIENT_MESSAGE_HEADER_SIZE=48) add_compile_definitions(CONFIG_COAP_CLIENT_STACK_SIZE=1024) add_compile_definitions(CONFIG_COAP_CLIENT_THREAD_PRIORITY=10) add_compile_definitions(CONFIG_COAP_LOG_LEVEL=4) -add_compile_definitions(CONFIG_COAP_INIT_ACK_TIMEOUT_MS=2000) +add_compile_definitions(CONFIG_COAP_INIT_ACK_TIMEOUT_MS=200) add_compile_definitions(CONFIG_COAP_CLIENT_MAX_REQUESTS=2) add_compile_definitions(CONFIG_COAP_CLIENT_MAX_INSTANCES=2) diff --git a/tests/net/lib/coap_client/prj.conf b/tests/net/lib/coap_client/prj.conf index d185b3e493c..c7265029a21 100644 --- a/tests/net/lib/coap_client/prj.conf +++ b/tests/net/lib/coap_client/prj.conf @@ -1,4 +1,3 @@ #Testing CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=4096 diff --git a/tests/net/lib/coap_client/src/main.c b/tests/net/lib/coap_client/src/main.c index bb9d9fc38c5..e1240c5e2ed 100644 --- a/tests/net/lib/coap_client/src/main.c +++ b/tests/net/lib/coap_client/src/main.c @@ -15,7 +15,7 @@ LOG_MODULE_REGISTER(coap_client_test); DEFINE_FFF_GLOBALS; #define FFF_FAKES_LIST(FAKE) -static uint8_t last_response_code; +static int16_t last_response_code; static const char *test_path = "test"; static uint16_t messages_needing_response[2]; @@ -75,6 +75,89 @@ static ssize_t z_impl_zsock_sendto_custom_fake(int sock, void *buf, size_t len, last_response_code = ((uint8_t *) buf)[1]; LOG_INF("Latest message ID: %d", last_message_id); + + return 1; +} + +static ssize_t z_impl_zsock_sendto_custom_fake_echo(int sock, void *buf, size_t len, + int flags, const struct sockaddr *dest_addr, + socklen_t addrlen) +{ + uint16_t last_message_id = 0; + struct coap_packet response = {0}; + struct coap_option option = {0}; + + last_message_id |= ((uint8_t *) buf)[2] << 8; + last_message_id |= ((uint8_t *) buf)[3]; + + if (messages_needing_response[0] == 0) { + messages_needing_response[0] = last_message_id; + } else { + messages_needing_response[1] = last_message_id; + } + + last_response_code = ((uint8_t *) buf)[1]; + + LOG_INF("Latest message ID: %d", last_message_id); + + int ret = coap_packet_parse(&response, buf, len, NULL, 0); + + if (ret < 0) { + LOG_ERR("Invalid data received"); + } + + ret = coap_find_options(&response, COAP_OPTION_ECHO, &option, 1); + + zassert_equal(ret, 1, "Coap echo option not found, %d", ret); + zassert_mem_equal(option.value, "echo_value", option.len, "Incorrect echo data"); + + z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake; + + return 1; +} + +static ssize_t z_impl_zsock_sendto_custom_fake_echo_next_req(int sock, void *buf, size_t len, + int flags, const struct sockaddr *dest_addr, + socklen_t addrlen) +{ + uint16_t last_message_id = 0; + struct coap_packet response = {0}; + struct coap_option option = {0}; + + last_message_id |= ((uint8_t *) buf)[2] << 8; + last_message_id |= ((uint8_t *) buf)[3]; + + if (messages_needing_response[0] == 0) { + messages_needing_response[0] = last_message_id; + } else { + messages_needing_response[1] = last_message_id; + } + + last_response_code = ((uint8_t *) buf)[1]; + + LOG_INF("Latest message ID: %d", last_message_id); + + int ret = coap_packet_parse(&response, buf, len, NULL, 0); + + if (ret < 0) { + LOG_ERR("Invalid data received"); + } + + ret = coap_header_get_code(&response); + zassert_equal(ret, COAP_METHOD_POST, "Incorrect method, %d", ret); + + uint16_t payload_len; + + const uint8_t *payload = coap_packet_get_payload(&response, &payload_len); + + zassert_mem_equal(payload, "echo testing", payload_len, "Incorrect payload"); + + ret = coap_find_options(&response, COAP_OPTION_ECHO, &option, 1); + zassert_equal(ret, 1, "Coap echo option not found, %d", ret); + zassert_mem_equal(option.value, "echo_value", option.len, "Incorrect echo data"); + + z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake; + return 1; } @@ -104,6 +187,34 @@ static ssize_t z_impl_zsock_recvfrom_custom_fake_response(int sock, void *buf, s return sizeof(ack_data); } +static ssize_t z_impl_zsock_recvfrom_custom_fake_delayed_response(int sock, void *buf, + size_t max_len, int flags, + struct sockaddr *src_addr, + socklen_t *addrlen) +{ + uint16_t last_message_id = 0; + + static uint8_t ack_data[] = { + 0x68, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + if (messages_needing_response[0] != 0) { + last_message_id = messages_needing_response[0]; + messages_needing_response[0] = 0; + } else { + last_message_id = messages_needing_response[1]; + messages_needing_response[1] = 0; + } + + ack_data[2] = (uint8_t) (last_message_id >> 8); + ack_data[3] = (uint8_t) last_message_id; + + memcpy(buf, ack_data, sizeof(ack_data)); + k_sleep(K_MSEC(10)); + + return sizeof(ack_data); +} + static ssize_t z_impl_zsock_recvfrom_custom_fake_empty_ack(int sock, void *buf, size_t max_len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) @@ -158,6 +269,66 @@ static ssize_t z_impl_zsock_recvfrom_custom_fake_unmatching(int sock, void *buf, return sizeof(ack_data); } +static ssize_t z_impl_zsock_recvfrom_custom_fake_echo(int sock, void *buf, size_t max_len, + int flags, struct sockaddr *src_addr, + socklen_t *addrlen) +{ + uint16_t last_message_id = 0; + + LOG_INF("Recvfrom"); + uint8_t ack_data[] = {0x68, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xda, 0xef, 'e', 'c', + 'h', 'o', '_', 'v', 'a', 'l', 'u', 'e'}; + + if (messages_needing_response[0] != 0) { + last_message_id = messages_needing_response[0]; + messages_needing_response[0] = 0; + } else { + last_message_id = messages_needing_response[1]; + messages_needing_response[1] = 0; + } + + ack_data[2] = (uint8_t) (last_message_id >> 8); + ack_data[3] = (uint8_t) last_message_id; + + memcpy(buf, ack_data, sizeof(ack_data)); + + z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_response; + z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_echo; + + return sizeof(ack_data); +} + +static ssize_t z_impl_zsock_recvfrom_custom_fake_echo_next_req(int sock, void *buf, size_t max_len, + int flags, struct sockaddr *src_addr, + socklen_t *addrlen) +{ + uint16_t last_message_id = 0; + + LOG_INF("Recvfrom"); + uint8_t ack_data[] = {0x68, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xda, 0xef, 'e', 'c', + 'h', 'o', '_', 'v', 'a', 'l', 'u', 'e'}; + + if (messages_needing_response[0] != 0) { + last_message_id = messages_needing_response[0]; + messages_needing_response[0] = 0; + } else { + last_message_id = messages_needing_response[1]; + messages_needing_response[1] = 0; + } + + ack_data[2] = (uint8_t) (last_message_id >> 8); + ack_data[3] = (uint8_t) last_message_id; + + memcpy(buf, ack_data, sizeof(ack_data)); + + z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_response; + z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_echo_next_req; + + return sizeof(ack_data); +} + static void *suite_setup(void) { coap_client_init(&client, NULL); @@ -174,6 +345,8 @@ static void test_setup(void *data) z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake; z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake; + messages_needing_response[0] = 0; + messages_needing_response[1] = 0; } void coap_callback(int16_t code, size_t offset, const uint8_t *payload, size_t len, bool last_block, @@ -210,7 +383,116 @@ ZTEST(coap_client, test_get_request) set_socket_events(ZSOCK_POLLIN); k_sleep(K_MSEC(5)); - k_sleep(K_MSEC(1000)); + k_sleep(K_MSEC(100)); + zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response"); +} + +ZTEST(coap_client, test_resend_request) +{ + int ret = 0; + struct sockaddr address = {0}; + struct coap_client_request client_request = { + .method = COAP_METHOD_GET, + .confirmable = true, + .path = test_path, + .fmt = COAP_CONTENT_FORMAT_TEXT_PLAIN, + .cb = coap_callback, + .payload = NULL, + .len = 0 + }; + + client_request.payload = short_payload; + client_request.len = strlen(short_payload); + + z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_delayed_response; + + k_sleep(K_MSEC(1)); + + LOG_INF("Send request"); + ret = coap_client_req(&client, 0, &address, &client_request, -1); + zassert_true(ret >= 0, "Sending request failed, %d", ret); + k_sleep(K_MSEC(300)); + set_socket_events(ZSOCK_POLLIN); + + k_sleep(K_MSEC(100)); + zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response"); + zassert_equal(z_impl_zsock_sendto_fake.call_count, 2); +} + +ZTEST(coap_client, test_echo_option) +{ + int ret = 0; + struct sockaddr address = {0}; + struct coap_client_request client_request = { + .method = COAP_METHOD_GET, + .confirmable = true, + .path = test_path, + .fmt = COAP_CONTENT_FORMAT_TEXT_PLAIN, + .cb = coap_callback, + .payload = NULL, + .len = 0 + }; + + client_request.payload = short_payload; + client_request.len = strlen(short_payload); + + z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_echo; + + k_sleep(K_MSEC(1)); + + LOG_INF("Send request"); + ret = coap_client_req(&client, 0, &address, &client_request, -1); + zassert_true(ret >= 0, "Sending request failed, %d", ret); + set_socket_events(ZSOCK_POLLIN); + + k_sleep(K_MSEC(5)); + k_sleep(K_MSEC(100)); + zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response"); +} + +ZTEST(coap_client, test_echo_option_next_req) +{ + int ret = 0; + struct sockaddr address = {0}; + struct coap_client_request client_request = { + .method = COAP_METHOD_GET, + .confirmable = true, + .path = test_path, + .fmt = COAP_CONTENT_FORMAT_TEXT_PLAIN, + .cb = coap_callback, + .payload = NULL, + .len = 0 + }; + + client_request.payload = short_payload; + client_request.len = strlen(short_payload); + + z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_echo_next_req; + + k_sleep(K_MSEC(1)); + + LOG_INF("Send request"); + ret = coap_client_req(&client, 0, &address, &client_request, -1); + zassert_true(ret >= 0, "Sending request failed, %d", ret); + set_socket_events(ZSOCK_POLLIN); + + k_sleep(K_MSEC(5)); + k_sleep(K_MSEC(100)); + zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response"); + + char *payload = "echo testing"; + + client_request.method = COAP_METHOD_POST; + client_request.payload = payload; + client_request.len = strlen(payload); + + LOG_INF("Send next request"); + ret = coap_client_req(&client, 0, &address, &client_request, -1); + zassert_true(ret >= 0, "Sending request failed, %d", ret); + set_socket_events(ZSOCK_POLLIN); + + k_sleep(K_MSEC(5)); + k_sleep(K_MSEC(100)); zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response"); } @@ -264,7 +546,7 @@ ZTEST(coap_client, test_send_large_data) set_socket_events(ZSOCK_POLLIN); k_sleep(K_MSEC(5)); - k_sleep(K_MSEC(1000)); + k_sleep(K_MSEC(100)); zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response"); } @@ -292,7 +574,9 @@ ZTEST(coap_client, test_no_response) ret = coap_client_req(&client, 0, &address, &client_request, 0); zassert_true(ret >= 0, "Sending request failed, %d", ret); - k_sleep(K_MSEC(1000)); + k_sleep(K_MSEC(300)); + + zassert_equal(last_response_code, -ETIMEDOUT, "Unexpected response"); } ZTEST(coap_client, test_separate_response) @@ -322,9 +606,7 @@ ZTEST(coap_client, test_separate_response) set_socket_events(ZSOCK_POLLIN); k_sleep(K_MSEC(5)); - k_sleep(K_MSEC(1000)); - - k_sleep(K_MSEC(1000)); + k_sleep(K_MSEC(100)); zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response"); } @@ -357,11 +639,11 @@ ZTEST(coap_client, test_multiple_requests) zassert_true(ret >= 0, "Sending request failed, %d", ret); k_sleep(K_MSEC(5)); - k_sleep(K_MSEC(1000)); + k_sleep(K_MSEC(100)); zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response"); k_sleep(K_MSEC(5)); - k_sleep(K_MSEC(1000)); + k_sleep(K_MSEC(100)); zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response"); } @@ -392,5 +674,5 @@ ZTEST(coap_client, test_unmatching_tokens) k_sleep(K_MSEC(1)); k_sleep(K_MSEC(1)); clear_socket_events(); - k_sleep(K_MSEC(1000)); + k_sleep(K_MSEC(500)); } diff --git a/tests/net/lib/coap_client/testcase.yaml b/tests/net/lib/coap_client/testcase.yaml index 923e1380f01..18e64f08df5 100644 --- a/tests/net/lib/coap_client/testcase.yaml +++ b/tests/net/lib/coap_client/testcase.yaml @@ -2,5 +2,7 @@ common: depends_on: netif tests: net.coap.client: - platform_allow: native_posix + platform_allow: + - native_posix + - native_sim tags: coap net diff --git a/tests/net/lib/coap_server/common/CMakeLists.txt b/tests/net/lib/coap_server/common/CMakeLists.txt new file mode 100644 index 00000000000..6607ada6948 --- /dev/null +++ b/tests/net/lib/coap_server/common/CMakeLists.txt @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(coap_service_defines) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) + +zephyr_linker_sources(DATA_SECTIONS sections-ram.ld) diff --git a/tests/net/lib/coap_server/common/prj.conf b/tests/net/lib/coap_server/common/prj.conf new file mode 100644 index 00000000000..07cf69355fc --- /dev/null +++ b/tests/net/lib/coap_server/common/prj.conf @@ -0,0 +1,9 @@ +CONFIG_ZTEST=y + +CONFIG_NETWORKING=y +CONFIG_NET_TEST=y +CONFIG_ENTROPY_GENERATOR=y +CONFIG_TEST_RANDOM_GENERATOR=y + +CONFIG_COAP=y +CONFIG_COAP_SERVER=y diff --git a/tests/net/lib/coap_server/common/sections-ram.ld b/tests/net/lib/coap_server/common/sections-ram.ld new file mode 100644 index 00000000000..d435ffbddd4 --- /dev/null +++ b/tests/net/lib/coap_server/common/sections-ram.ld @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include + +ITERABLE_SECTION_RAM(coap_resource_service_A, 4) +ITERABLE_SECTION_RAM(coap_resource_service_B, 4) +ITERABLE_SECTION_RAM(coap_resource_service_C, 4) diff --git a/tests/net/lib/coap_server/common/src/main.c b/tests/net/lib/coap_server/common/src/main.c new file mode 100644 index 00000000000..7af940c5360 --- /dev/null +++ b/tests/net/lib/coap_server/common/src/main.c @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2023 Basalte bv + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include + +static int coap_method1(struct coap_resource *resource, struct coap_packet *request, + struct sockaddr *addr, socklen_t addr_len) +{ + ARG_UNUSED(resource); + ARG_UNUSED(request); + ARG_UNUSED(addr); + ARG_UNUSED(addr_len); + + return -ENOSYS; +} + +static int coap_method2(struct coap_resource *resource, struct coap_packet *request, + struct sockaddr *addr, socklen_t addr_len) +{ + ARG_UNUSED(resource); + ARG_UNUSED(request); + ARG_UNUSED(addr); + ARG_UNUSED(addr_len); + + return -ENOSYS; +} + +static const uint16_t service_A_port = 4242; +COAP_SERVICE_DEFINE(service_A, "a.service.com", &service_A_port, COAP_SERVICE_AUTOSTART); + +static const char * const resource_0_path[] = { "res0", NULL }; +COAP_RESOURCE_DEFINE(resource_0, service_A, { + .path = resource_0_path, + .get = coap_method1, + .put = coap_method2, +}); + +static const char * const resource_1_path[] = { "res1", NULL }; +COAP_RESOURCE_DEFINE(resource_1, service_A, { + .path = resource_1_path, + .post = coap_method1, +}); + +static uint16_t service_B_port; +COAP_SERVICE_DEFINE(service_B, "b.service.com", &service_B_port, COAP_SERVICE_AUTOSTART); + +static const char * const resource_2_path[] = { "res2", "sub", NULL }; +COAP_RESOURCE_DEFINE(resource_2, service_B, { + .path = resource_2_path, + .get = coap_method2, + .put = coap_method1, +}); + +static const char * const resource_3_path[] = { "res3", "+", NULL }; +COAP_RESOURCE_DEFINE(resource_3, service_B, { + .path = resource_3_path, + .post = coap_method2, +}); + +static const uint16_t service_C_port = 5959; +COAP_SERVICE_DEFINE(service_C, "192.168.1.1", &service_C_port, 0); + +static const char * const resource_4_path[] = { "res4", "*", NULL }; +COAP_RESOURCE_DEFINE(resource_4, service_C, { + .path = resource_4_path, + .get = coap_method1, +}); + +ZTEST(coap_service, test_COAP_SERVICE_DEFINE) +{ + zassert_ok(strcmp(service_A.host, "a.service.com")); + zassert_equal(service_A.port, &service_A_port); + zassert_equal(*service_A.port, 4242); + + zassert_ok(strcmp(service_B.host, "b.service.com")); + zassert_equal(service_B.port, &service_B_port); + zassert_equal(*service_B.port, 0); + + zassert_ok(strcmp(service_C.host, "192.168.1.1")); + zassert_equal(service_C.port, &service_C_port); + zassert_equal(*service_C.port, 5959); +} + +ZTEST(coap_service, test_COAP_SERVICE_COUNT) +{ + size_t n_svc; + + n_svc = 4273; + COAP_SERVICE_COUNT(&n_svc); + zassert_equal(n_svc, 3); +} + +ZTEST(coap_service, test_COAP_SERVICE_RESOURCE_COUNT) +{ + zassert_equal(COAP_SERVICE_RESOURCE_COUNT(&service_A), 2); + zassert_equal(COAP_SERVICE_RESOURCE_COUNT(&service_B), 2); + zassert_equal(COAP_SERVICE_RESOURCE_COUNT(&service_C), 1); +} + +ZTEST(coap_service, test_COAP_SERVICE_HAS_RESOURCE) +{ + zassert_true(COAP_SERVICE_HAS_RESOURCE(&service_A, &resource_0)); + zassert_true(COAP_SERVICE_HAS_RESOURCE(&service_A, &resource_1)); + zassert_false(COAP_SERVICE_HAS_RESOURCE(&service_A, &resource_2)); + zassert_false(COAP_SERVICE_HAS_RESOURCE(&service_A, &resource_3)); + + zassert_false(COAP_SERVICE_HAS_RESOURCE(&service_B, &resource_0)); + zassert_false(COAP_SERVICE_HAS_RESOURCE(&service_B, &resource_1)); + zassert_true(COAP_SERVICE_HAS_RESOURCE(&service_B, &resource_2)); + zassert_true(COAP_SERVICE_HAS_RESOURCE(&service_B, &resource_3)); + + zassert_false(COAP_SERVICE_HAS_RESOURCE(&service_C, &resource_0)); + zassert_true(COAP_SERVICE_HAS_RESOURCE(&service_C, &resource_4)); +} + +ZTEST(coap_service, test_COAP_SERVICE_FOREACH) +{ + size_t n_svc = 0; + size_t have_service_A = 0; + size_t have_service_B = 0; + size_t have_service_C = 0; + + COAP_SERVICE_FOREACH(svc) { + if (svc == &service_A) { + have_service_A = 1; + zassert_equal(svc->flags & COAP_SERVICE_AUTOSTART, COAP_SERVICE_AUTOSTART); + } else if (svc == &service_B) { + have_service_B = 1; + zassert_equal(svc->flags & COAP_SERVICE_AUTOSTART, COAP_SERVICE_AUTOSTART); + } else if (svc == &service_C) { + have_service_C = 1; + zassert_equal(svc->flags & COAP_SERVICE_AUTOSTART, 0); + } else { + zassert_unreachable("svc (%p) not equal to &service_A (%p), &service_B " + "(%p), or &service_C (%p)", + svc, &service_A, &service_B, &service_C); + } + + n_svc++; + } + + zassert_equal(n_svc, 3); + zassert_equal(have_service_A + have_service_B + have_service_C, n_svc); +} + +ZTEST(coap_service, test_COAP_RESOURCE_FOREACH) +{ + size_t first_res, second_res, n_res; + + n_res = 0; + first_res = 0; + second_res = 0; + COAP_RESOURCE_FOREACH(service_A, res) { + if (res == &resource_0) { + first_res = 1; + } else if (res == &resource_1) { + second_res = 1; + } else { + zassert_unreachable( + "res (%p) not equal to &resource_0 (%p) or &resource_1 (%p)", res, + &resource_0, &resource_1); + } + + n_res++; + } + + zassert_equal(n_res, 2); + zassert_equal(first_res + second_res, n_res); + + n_res = 0; + first_res = 0; + second_res = 0; + COAP_RESOURCE_FOREACH(service_B, res) { + if (res == &resource_2) { + first_res = 1; + } else if (res == &resource_3) { + second_res = 1; + } else { + zassert_unreachable( + "res (%p) not equal to &resource_2 (%p) or &resource_3 (%p)", res, + &resource_2, &resource_3); + } + + n_res++; + } + + zassert_equal(n_res, 2); + zassert_equal(first_res + second_res, n_res); + + n_res = 0; + first_res = 0; + second_res = 0; + COAP_RESOURCE_FOREACH(service_C, res) { + if (res == &resource_4) { + first_res = 1; + } else { + zassert_unreachable( + "res (%p) not equal to &resource_4 (%p)", res, &resource_4); + } + n_res++; + } + + zassert_equal(n_res, 1); + zassert_equal(first_res + second_res, n_res); +} + +ZTEST(coap_service, test_COAP_SERVICE_FOREACH_RESOURCE) +{ + size_t first_res, second_res, n_res; + + n_res = 0; + first_res = 0; + second_res = 0; + COAP_SERVICE_FOREACH_RESOURCE(&service_A, res) { + if (res == &resource_0) { + first_res = 1; + } else if (res == &resource_1) { + second_res = 1; + } else { + zassert_unreachable( + "res (%p) not equal to &resource_0 (%p) or &resource_1 (%p)", res, + &resource_0, &resource_1); + } + + n_res++; + } + + zassert_equal(n_res, 2); + zassert_equal(first_res + second_res, n_res); + + n_res = 0; + first_res = 0; + second_res = 0; + COAP_SERVICE_FOREACH_RESOURCE(&service_B, res) { + if (res == &resource_2) { + first_res = 1; + } else if (res == &resource_3) { + second_res = 1; + } else { + zassert_unreachable( + "res (%p) not equal to &resource_2 (%p) or &resource_3 (%p)", res, + &resource_2, &resource_3); + } + + n_res++; + } + + zassert_equal(n_res, 2); + zassert_equal(first_res + second_res, n_res); + + n_res = 0; + first_res = 0; + second_res = 0; + COAP_SERVICE_FOREACH_RESOURCE(&service_C, res) { + if (res == &resource_4) { + first_res = 1; + } else { + zassert_unreachable( + "res (%p) not equal to &resource_4 (%p)", res, &resource_4); + } + n_res++; + } + + zassert_equal(n_res, 1); + zassert_equal(first_res + second_res, n_res); +} + +ZTEST(coap_service, test_COAP_RESOURCE_DEFINE) +{ + COAP_SERVICE_FOREACH_RESOURCE(&service_A, res) { + if (res == &resource_0) { + zassert_ok(strcmp(res->path[0], "res0")); + zassert_equal(res->get, coap_method1); + zassert_equal(res->put, coap_method2); + } else if (res == &resource_1) { + zassert_ok(strcmp(res->path[0], "res1")); + zassert_equal(res->post, coap_method1); + } else { + zassert_unreachable( + "res (%p) not equal to &resource_0 (%p) or &resource_1 (%p)", res, + &resource_0, &resource_1); + } + } + + COAP_SERVICE_FOREACH_RESOURCE(&service_B, res) { + if (res == &resource_2) { + zassert_ok(strcmp(res->path[0], "res2")); + zassert_ok(strcmp(res->path[1], "sub")); + zassert_equal(res->get, coap_method2); + zassert_equal(res->put, coap_method1); + } else if (res == &resource_3) { + zassert_ok(strcmp(res->path[0], "res3")); + zassert_ok(strcmp(res->path[1], "+")); + zassert_equal(res->post, coap_method2); + } else { + zassert_unreachable( + "res (%p) not equal to &resource_2 (%p) or &resource_3 (%p)", res, + &resource_2, &resource_3); + } + } + + COAP_SERVICE_FOREACH_RESOURCE(&service_C, res) { + if (res == &resource_4) { + zassert_ok(strcmp(res->path[0], "res4")); + zassert_ok(strcmp(res->path[1], "*")); + zassert_equal(res->get, coap_method1); + zassert_equal(res->put, NULL); + } else { + zassert_unreachable( + "res (%p) not equal to &resource_4 (%p)", res, &resource_4); + } + } +} + +ZTEST_SUITE(coap_service, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/net/lib/coap_server/common/testcase.yaml b/tests/net/lib/coap_server/common/testcase.yaml new file mode 100644 index 00000000000..513d3c4a0e4 --- /dev/null +++ b/tests/net/lib/coap_server/common/testcase.yaml @@ -0,0 +1,11 @@ +common: + min_ram: 16 + tags: + - net + - coap + - server + integration_platforms: + - native_sim + +tests: + net.coap.server.common: {} diff --git a/tests/net/lib/dns_addremove/prj.conf b/tests/net/lib/dns_addremove/prj.conf index 2d7d81b1341..db691377acd 100644 --- a/tests/net/lib/dns_addremove/prj.conf +++ b/tests/net/lib/dns_addremove/prj.conf @@ -16,5 +16,4 @@ CONFIG_NET_IPV6=y CONFIG_NET_ARP=n CONFIG_PRINTK=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MAIN_STACK_SIZE=2048 diff --git a/tests/net/lib/dns_addremove/src/main.c b/tests/net/lib/dns_addremove/src/main.c index 9e0394ba819..6d992776800 100644 --- a/tests/net/lib/dns_addremove/src/main.c +++ b/tests/net/lib/dns_addremove/src/main.c @@ -13,7 +13,7 @@ LOG_MODULE_REGISTER(net_test, CONFIG_DNS_RESOLVER_LOG_LEVEL); #include #include #include -#include +#include #include diff --git a/tests/net/lib/dns_packet/prj.conf b/tests/net/lib/dns_packet/prj.conf index c757cbeca69..5a15eeb1ac8 100644 --- a/tests/net/lib/dns_packet/prj.conf +++ b/tests/net/lib/dns_packet/prj.conf @@ -11,7 +11,6 @@ CONFIG_DNS_RESOLVER=y CONFIG_PRINTK=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MAIN_STACK_SIZE=1280 CONFIG_CRC=y diff --git a/tests/net/lib/dns_resolve/prj-no-ipv6.conf b/tests/net/lib/dns_resolve/prj-no-ipv6.conf index d980676230e..d7b7c5f8c1e 100644 --- a/tests/net/lib/dns_resolve/prj-no-ipv6.conf +++ b/tests/net/lib/dns_resolve/prj-no-ipv6.conf @@ -25,6 +25,5 @@ CONFIG_NET_ARP=n CONFIG_PRINTK=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MAIN_STACK_SIZE=1344 diff --git a/tests/net/lib/dns_resolve/prj.conf b/tests/net/lib/dns_resolve/prj.conf index 954eb867861..c43911ac3cd 100644 --- a/tests/net/lib/dns_resolve/prj.conf +++ b/tests/net/lib/dns_resolve/prj.conf @@ -27,6 +27,5 @@ CONFIG_NET_ARP=n CONFIG_PRINTK=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MAIN_STACK_SIZE=1344 diff --git a/tests/net/lib/dns_resolve/src/main.c b/tests/net/lib/dns_resolve/src/main.c index 18ff9e42070..39e7d286dfb 100644 --- a/tests/net/lib/dns_resolve/src/main.c +++ b/tests/net/lib/dns_resolve/src/main.c @@ -13,7 +13,7 @@ LOG_MODULE_REGISTER(net_test, CONFIG_DNS_RESOLVER_LOG_LEVEL); #include #include #include -#include +#include #include diff --git a/tests/net/lib/dns_sd/prj-no-ipv6.conf b/tests/net/lib/dns_sd/prj-no-ipv6.conf index 2e31b260076..d973914fa47 100644 --- a/tests/net/lib/dns_sd/prj-no-ipv6.conf +++ b/tests/net/lib/dns_sd/prj-no-ipv6.conf @@ -22,7 +22,6 @@ CONFIG_DNS_SD=y CONFIG_DNS_SD_LOG_LEVEL_DBG=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=2048 # Maybe avoid stack overflow on mps2_an385? diff --git a/tests/net/lib/dns_sd/prj.conf b/tests/net/lib/dns_sd/prj.conf index 02d34005774..52c1916e210 100644 --- a/tests/net/lib/dns_sd/prj.conf +++ b/tests/net/lib/dns_sd/prj.conf @@ -15,7 +15,6 @@ CONFIG_DNS_SD=y CONFIG_DNS_SD_LOG_LEVEL_DBG=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=2048 # Maybe avoid stack overflow on mps2_an385? diff --git a/tests/net/lib/http_header_fields/prj.conf b/tests/net/lib/http_header_fields/prj.conf index 7edaa3b1a5b..a8dba22a09c 100644 --- a/tests/net/lib/http_header_fields/prj.conf +++ b/tests/net/lib/http_header_fields/prj.conf @@ -5,7 +5,6 @@ CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_ZTEST_STACK_SIZE=1024 CONFIG_HTTP_PARSER=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MAIN_STACK_SIZE=1280 # Enable strict parser by uncommenting the following line # CONFIG_HTTP_PARSER_STRICT=y diff --git a/tests/net/lib/http_server/common/prj.conf b/tests/net/lib/http_server/common/prj.conf index 4422a170d58..7fa5d3d6dd0 100644 --- a/tests/net/lib/http_server/common/prj.conf +++ b/tests/net/lib/http_server/common/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NETWORKING=y CONFIG_NET_TEST=y diff --git a/tests/net/lib/http_server/common/src/main.c b/tests/net/lib/http_server/common/src/main.c index c0aee694c84..b85940e8e21 100644 --- a/tests/net/lib/http_server/common/src/main.c +++ b/tests/net/lib/http_server/common/src/main.c @@ -240,8 +240,8 @@ ZTEST(http_service, test_HTTP_RESOURCE_DEFINE) zassert_equal(res->detail, RES(3)); } else { zassert_unreachable( - "res (%p) not equal to &resource_0 (%p) or &resource_1 (%p)", res, - &resource_0, &resource_1); + "res (%p) not equal to &resource_2 (%p) or &resource_3 (%p)", res, + &resource_2, &resource_3); } } } diff --git a/tests/net/lib/http_server/common/testcase.yaml b/tests/net/lib/http_server/common/testcase.yaml index 951f5d7c582..b86f2dc0c95 100644 --- a/tests/net/lib/http_server/common/testcase.yaml +++ b/tests/net/lib/http_server/common/testcase.yaml @@ -5,7 +5,7 @@ common: - http - server integration_platforms: - - native_posix + - native_sim tests: net.http.server.common: {} diff --git a/tests/net/lib/lwm2m/block_transfer/prj.conf b/tests/net/lib/lwm2m/block_transfer/prj.conf index f88f71b4d5d..ea874ac5925 100644 --- a/tests/net/lib/lwm2m/block_transfer/prj.conf +++ b/tests/net/lib/lwm2m/block_transfer/prj.conf @@ -1,7 +1,6 @@ CONFIG_NETWORKING=y CONFIG_NET_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/net/lib/lwm2m/block_transfer/testcase.yaml b/tests/net/lib/lwm2m/block_transfer/testcase.yaml index 66f145fd18f..4ad71f29ef0 100644 --- a/tests/net/lib/lwm2m/block_transfer/testcase.yaml +++ b/tests/net/lib/lwm2m/block_transfer/testcase.yaml @@ -6,4 +6,4 @@ tests: - lwm2m - net integration_platforms: - - native_posix + - native_sim diff --git a/tests/net/lib/lwm2m/content_json/prj.conf b/tests/net/lib/lwm2m/content_json/prj.conf index 7ff07df9897..b660af21e1d 100644 --- a/tests/net/lib/lwm2m/content_json/prj.conf +++ b/tests/net/lib/lwm2m/content_json/prj.conf @@ -1,7 +1,6 @@ CONFIG_NETWORKING=y CONFIG_NET_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/net/lib/lwm2m/content_json/testcase.yaml b/tests/net/lib/lwm2m/content_json/testcase.yaml index a283ce908ef..f933ec6d684 100644 --- a/tests/net/lib/lwm2m/content_json/testcase.yaml +++ b/tests/net/lib/lwm2m/content_json/testcase.yaml @@ -6,4 +6,4 @@ tests: - lwm2m - net integration_platforms: - - native_posix + - native_sim diff --git a/tests/net/lib/lwm2m/content_link_format/prj.conf b/tests/net/lib/lwm2m/content_link_format/prj.conf index 952b54a4566..e7e630f91f1 100644 --- a/tests/net/lib/lwm2m/content_link_format/prj.conf +++ b/tests/net/lib/lwm2m/content_link_format/prj.conf @@ -1,7 +1,6 @@ CONFIG_NETWORKING=y CONFIG_NET_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/net/lib/lwm2m/content_link_format/src/main.c b/tests/net/lib/lwm2m/content_link_format/src/main.c index 76429b78f98..3b0189ddbe7 100644 --- a/tests/net/lib/lwm2m/content_link_format/src/main.c +++ b/tests/net/lib/lwm2m/content_link_format/src/main.c @@ -156,7 +156,7 @@ ZTEST(net_content_link_format, test_put_begin_bs_discovery) ZTEST(net_content_link_format, test_put_begin_register) { int ret; - const char *expected_payload = ";rt=\"oma.lwm2m\";ct=11543"; + const char *expected_payload = ";ct=11543"; test_formatter_data.mode = LINK_FORMAT_MODE_REGISTER; diff --git a/tests/net/lib/lwm2m/content_link_format/testcase.yaml b/tests/net/lib/lwm2m/content_link_format/testcase.yaml index 5448cf68fd0..0b7d965d0f0 100644 --- a/tests/net/lib/lwm2m/content_link_format/testcase.yaml +++ b/tests/net/lib/lwm2m/content_link_format/testcase.yaml @@ -6,4 +6,4 @@ tests: - lwm2m - net integration_platforms: - - native_posix + - native_sim diff --git a/tests/net/lib/lwm2m/content_oma_tlv/prj.conf b/tests/net/lib/lwm2m/content_oma_tlv/prj.conf index 6041addad83..8dc442cb035 100644 --- a/tests/net/lib/lwm2m/content_oma_tlv/prj.conf +++ b/tests/net/lib/lwm2m/content_oma_tlv/prj.conf @@ -1,7 +1,6 @@ CONFIG_NETWORKING=y CONFIG_NET_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/net/lib/lwm2m/content_oma_tlv/testcase.yaml b/tests/net/lib/lwm2m/content_oma_tlv/testcase.yaml index 2bf877f7353..dee42fcc503 100644 --- a/tests/net/lib/lwm2m/content_oma_tlv/testcase.yaml +++ b/tests/net/lib/lwm2m/content_oma_tlv/testcase.yaml @@ -6,4 +6,4 @@ tests: - lwm2m - net integration_platforms: - - native_posix + - native_sim diff --git a/tests/net/lib/lwm2m/content_plain_text/prj.conf b/tests/net/lib/lwm2m/content_plain_text/prj.conf index 877c969958f..79338ed1f31 100644 --- a/tests/net/lib/lwm2m/content_plain_text/prj.conf +++ b/tests/net/lib/lwm2m/content_plain_text/prj.conf @@ -1,7 +1,6 @@ CONFIG_NETWORKING=y CONFIG_NET_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/net/lib/lwm2m/content_plain_text/testcase.yaml b/tests/net/lib/lwm2m/content_plain_text/testcase.yaml index bd70dd790b3..96fc1726794 100644 --- a/tests/net/lib/lwm2m/content_plain_text/testcase.yaml +++ b/tests/net/lib/lwm2m/content_plain_text/testcase.yaml @@ -6,4 +6,4 @@ tests: - lwm2m - net integration_platforms: - - native_posix + - native_sim diff --git a/tests/net/lib/lwm2m/content_raw_cbor/prj.conf b/tests/net/lib/lwm2m/content_raw_cbor/prj.conf index 64ab6f89d22..6a29c438cab 100644 --- a/tests/net/lib/lwm2m/content_raw_cbor/prj.conf +++ b/tests/net/lib/lwm2m/content_raw_cbor/prj.conf @@ -1,7 +1,6 @@ CONFIG_NETWORKING=y CONFIG_NET_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/net/lib/lwm2m/content_raw_cbor/testcase.yaml b/tests/net/lib/lwm2m/content_raw_cbor/testcase.yaml index 9fc90f109bc..4580a2538ca 100644 --- a/tests/net/lib/lwm2m/content_raw_cbor/testcase.yaml +++ b/tests/net/lib/lwm2m/content_raw_cbor/testcase.yaml @@ -6,4 +6,4 @@ tests: - lwm2m - net integration_platforms: - - native_posix + - native_sim diff --git a/tests/net/lib/lwm2m/content_senml_cbor/prj.conf b/tests/net/lib/lwm2m/content_senml_cbor/prj.conf index 27a8364af58..e2f6bdb952f 100644 --- a/tests/net/lib/lwm2m/content_senml_cbor/prj.conf +++ b/tests/net/lib/lwm2m/content_senml_cbor/prj.conf @@ -1,7 +1,6 @@ CONFIG_NETWORKING=y CONFIG_NET_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/net/lib/lwm2m/content_senml_cbor/testcase.yaml b/tests/net/lib/lwm2m/content_senml_cbor/testcase.yaml index 55cd89a9f51..1bca0ca15eb 100644 --- a/tests/net/lib/lwm2m/content_senml_cbor/testcase.yaml +++ b/tests/net/lib/lwm2m/content_senml_cbor/testcase.yaml @@ -6,4 +6,4 @@ tests: - lwm2m - net integration_platforms: - - native_posix + - native_sim diff --git a/tests/net/lib/lwm2m/engine/prj.conf b/tests/net/lib/lwm2m/engine/prj.conf index 4477075056a..ad804ff4f1c 100644 --- a/tests/net/lib/lwm2m/engine/prj.conf +++ b/tests/net/lib/lwm2m/engine/prj.conf @@ -1,7 +1,6 @@ CONFIG_NETWORKING=y CONFIG_NET_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/net/lib/lwm2m/engine/testcase.yaml b/tests/net/lib/lwm2m/engine/testcase.yaml index 3263441b418..b13ecef4753 100644 --- a/tests/net/lib/lwm2m/engine/testcase.yaml +++ b/tests/net/lib/lwm2m/engine/testcase.yaml @@ -6,4 +6,4 @@ tests: - lwm2m - net integration_platforms: - - native_posix + - native_sim diff --git a/tests/net/lib/lwm2m/interop/README.md b/tests/net/lib/lwm2m/interop/README.md index 858f5007f64..bda38924d26 100644 --- a/tests/net/lib/lwm2m/interop/README.md +++ b/tests/net/lib/lwm2m/interop/README.md @@ -15,7 +15,39 @@ running Zephyr is using address `192.0.2.1`. Follow [Networking with the host system](https://docs.zephyrproject.org/latest/connectivity/networking/networking_with_host.html#networking-with-the-host-system) from Zephyr's documentation how to set it up, or follow [Create NAT and routing for Zephyr native network on Linux](https://github.com/zephyrproject-rtos/net-tools/blob/master/README%20NAT.md). -### Leshan server setup + +### Run Lehan server from net-tools Docker container + +Zephyr's net-tools Docker container already contains Leshan, so if you don't want to set the environment up manually, +use the pre-made docker. + +First, build the docker container. You only need to do this one, or when you update the container. +``` +cd tools/net-tools/docker +docker build -t net-tools . +``` + +Start the docker networking +``` +cd tools/net-tools/ +sudo ./net-setup.sh --config docker.conf start +``` + +Start the docker container and run leshan +``` +docker run --hostname=net-tools --name=net-tools --ip=192.0.2.2 --ip6=2001:db8::2 -p 8080:8080 -p 8081:8081 -p 5683:5683/udp --rm -dit --network=net-tools0 net-tools +docker container exec net-tools /net-tools/start-leshan.sh +``` + +### Stop Leshan, docker and networking + +``` +cd tools/net-tools/ +docker kill net-tools +sudo ./net-setup.sh --config docker.conf stop +docker network rm net-tools0 +``` +### Leshan server setup (manual) * Leshan server must be reachable from the device using IP address `192.0.2.2`. Configure the port forwarding, if you use Docker to run Leshan. @@ -74,30 +106,83 @@ Install with `pip install CoAPthon3` ``` twister -p native_posix -vv --enable-slow -T tests/net/lib/lwm2m/interop -`````` +``` + +Or use the Docker based testing + +``` +./scripts/net/run-sample-tests.sh tests/net/lib/lwm2m/interop +``` ## Test specification Tests are written from test spec; [OMA Enabler Test Specification (Interoperability) for Lightweight M2M](https://www.openmobilealliance.org/release/LightweightM2M/ETS/OMA-ETS-LightweightM2M-V1_1-20190912-D.pdf) -Following tests are implemented: -* LightweightM2M-1.1-int-0 – Client Initiated Bootstrap -* LightweightM2M-1.1-int-1 – Client Initiated Bootstrap Full (PSK) -* LightweightM2M-1.1-int-101 – Initial Registration -* LightweightM2M-1.1-int-102 – Registration Update -* LightweightM2M-1.1-int-104 – Registration Update Trigge -* LightweightM2M-1.1-int-105 - Discarded Register Update -* LightweightM2M-1.1-int-107 – Extending the lifetime of a registration -* LightweightM2M-1.1-int-108 – Turn on Queue Mode -* LightweightM2M-1.1-int-109 – Behavior in Queue Mode -* LightweightM2M-1.1-int-201 – Querying basic information in Plain Text -* LightweightM2M-1.1-int-203 – Querying basic information in TLV format -* LightweightM2M-1.1-int-204 – Querying basic information in JSON format -* LightweightM2M-1.1-int-205 – Setting basic information in Plain Text -* LightweightM2M-1.1-int-211 – Querying basic information in CBOR format -* LightweightM2M-1.1-int-212 – Setting basic information in CBOR format -* LightweightM2M-1.1-int-215 – Setting basic information in TLV format -* LightweightM2M-1.1-int-220 – Setting basic information in JSON format -* LightweightM2M-1.1-int-221 – Attempt to perform operations on Security -* LightweightM2M-1.1-int-401 – UDP Channel Security – PSK Mode +## Current status + +|Test case|Status|Notes| +|---------|------|-----| +|LightweightM2M-1.1-int-0 - Client Initiated Bootstrap |:white_check_mark:| | +|LightweightM2M-1.1-int-1 - Client Initiated Bootstrap Full (PSK) |:white_check_mark:| | +|LightweightM2M-1.1-int-101 - Initial Registration |:white_check_mark:| | +|LightweightM2M-1.1-int-102 - Registration Update |:white_check_mark:| | +|LightweightM2M-1.1-int-103 - Deregistration |:large_orange_diamond:|We don't have "disabled" functionality in server object| +|LightweightM2M-1.1-int-104 - Registration Update Trigge |:white_check_mark:| | +|LightweightM2M-1.1-int-105 - Discarded Register Update |:white_check_mark:| | +|LightweightM2M-1.1-int-107 - Extending the lifetime of a registration |:white_check_mark:| | +|LightweightM2M-1.1-int-108 - Turn on Queue Mode |:white_check_mark:| | +|LightweightM2M-1.1-int-109 - Behavior in Queue Mode |:white_check_mark:| | +|LightweightM2M-1.1-int-201 - Querying basic information in Plain Text |:white_check_mark:| | +|LightweightM2M-1.1-int-203 - Querying basic information in TLV format |:white_check_mark:| | +|LightweightM2M-1.1-int-204 - Querying basic information in JSON format |:white_check_mark:| | +|LightweightM2M-1.1-int-205 - Setting basic information in Plain Text |:white_check_mark:| | +|LightweightM2M-1.1-int-211 - Querying basic information in CBOR format |:white_check_mark:| | +|LightweightM2M-1.1-int-212 - Setting basic information in CBOR format |:white_check_mark:| | +|LightweightM2M-1.1-int-215 - Setting basic information in TLV format |:white_check_mark:| | +|LightweightM2M-1.1-int-220 - Setting basic information in JSON format |:white_check_mark:| | +|LightweightM2M-1.1-int-221 - Attempt to perform operations on Security |:white_check_mark:| | +|LightweightM2M-1.1-int-222 - Read on Object |:white_check_mark:| | +|LightweightM2M-1.1-int-223 - Read on Object Instance |:white_check_mark:| | +|LightweightM2M-1.1-int-224 - Read on Resource |:white_check_mark:| | +|LightweightM2M-1.1-int-225 - Read on Resource Instance |:white_check_mark:| | +|LightweightM2M-1.1-int-226 - Write (Partial Update) on Object Instance |:white_check_mark:| | +|LightweightM2M-1.1-int-222 - Read on Object |:white_check_mark:| | +|LightweightM2M-1.1-int-223 - Read on Object Instance |:white_check_mark:| | +|LightweightM2M-1.1-int-224 - Read on Resource |:white_check_mark:| | +|LightweightM2M-1.1-int-225 - Read on Resource Instance |:white_check_mark:| | +|LightweightM2M-1.1-int-226 - Write (Partial Update) on Object Instance |:white_check_mark:| | +|LightweightM2M-1.1-int-227 - Write (replace) on Resource |:white_check_mark:| | +|LightweightM2M-1.1-int-228 - Write on Resource Instance |:white_check_mark:|[~~#64011~~](https://github.com/zephyrproject-rtos/zephyr/issues/64011) | +|LightweightM2M-1.1-int-229 - Read-Composite Operation|:white_check_mark:|[~~#64012~~](https://github.com/zephyrproject-rtos/zephyr/issues/64012) [~~#64189~~](https://github.com/zephyrproject-rtos/zephyr/issues/64189) | +|LightweightM2M-1.1-int-230 - Write-Composite Operation|:white_check_mark:| | +|LightweightM2M-1.1-int-231 - Querying basic information in SenML JSON format|:white_check_mark:| | +|LightweightM2M-1.1-int-232 - Querying basic information in SenML CBOR format|:white_check_mark:| | +|LightweightM2M-1.1-int-233 - Setting basic information in SenML CBOR format|:white_check_mark:| | +|LightweightM2M-1.1-int-234 - Setting basic information in SenML JSON format|:white_check_mark:| | +|LightweightM2M-1.1-int-235 - Read-Composite Operation on root path|:large_orange_diamond:|Root Path is not yet supported by Leshan.| +|LightweightM2M-1.1-int-236 - Read-Composite - Partial Presence|:white_check_mark:| | +|LightweightM2M-1.1-int-237 - Read on Object without specifying Content-Type|:white_check_mark:| | +|LightweightM2M-1.1-int-241 - Executable Resource: Rebooting the device|:white_check_mark:| | +|LightweightM2M-1.1-int-256 - Write Operation Failure|:white_check_mark:| | +|LightweightM2M-1.1-int-257 - Write-Composite Operation|:white_check_mark:| | +|LightweightM2M-1.1-int-260 - Discover Command|:white_check_mark:| | +|LightweightM2M-1.1-int-261 - Write-Attribute Operation on a multiple resource|:large_orange_diamond:|Leshan don't allow writing attributes to resource instance| +|LightweightM2M-1.1-int-280 - Successful Read-Composite Operation|:white_check_mark:| | +|LightweightM2M-1.1-int-281 - Partially Successful Read-Composite Operation|:white_check_mark:| | +|LightweightM2M-1.1-int-301 - Observation and Notification of parameter values|:white_check_mark:| | +|LightweightM2M-1.1-int-302 - Cancel Observations using Reset Operation|:white_check_mark:| | +|LightweightM2M-1.1-int-303 - Cancel observations using Observe with Cancel parameter|:large_orange_diamond:|Leshan only supports passive cancelling| +|LightweightM2M-1.1-int-304 - Observe-Composite Operation|:white_check_mark:| | +|LightweightM2M-1.1-int-305 - Cancel Observation-Composite Operation|:large_orange_diamond:|Leshan only supports passive cancelling| +|LightweightM2M-1.1-int-306 – Send Operation|:white_check_mark:|[~~#64290~~](https://github.com/zephyrproject-rtos/zephyr/issues/64290)| +|LightweightM2M-1.1-int-307 – Muting Send|:white_check_mark:| | +|LightweightM2M-1.1-int-308 - Observe-Composite and Creating Object Instance|:white_check_mark:|[~~#64634~~](https://github.com/zephyrproject-rtos/zephyr/issues/64634)| +|LightweightM2M-1.1-int-309 - Observe-Composite and Deleting Object Instance|:white_check_mark:|[~~#64634~~](https://github.com/zephyrproject-rtos/zephyr/issues/64634)| +|LightweightM2M-1.1-int-310 - Observe-Composite and modification of parameter values|:white_check_mark:| | +|LightweightM2M-1.1-int-311 - Send command|:white_check_mark:| | +|LightweightM2M-1.1-int-401 - UDP Channel Security - PSK Mode |:white_check_mark:| | + +* :white_check_mark: Working OK. +* :large_orange_diamond: Feature or operation not implemented. +* :red_circle: Broken diff --git a/tests/net/lib/lwm2m/interop/boards/native_posix.conf b/tests/net/lib/lwm2m/interop/boards/native_posix.conf deleted file mode 100644 index 44346db12ed..00000000000 --- a/tests/net/lib/lwm2m/interop/boards/native_posix.conf +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG_DNS_RESOLVER=y -CONFIG_DNS_SERVER_IP_ADDRESSES=y -CONFIG_DNS_SERVER1="192.0.2.2" -CONFIG_LWM2M_DNS_SUPPORT=y -CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2" -CONFIG_NATIVE_POSIX_SLOWDOWN_TO_REAL_TIME=y -CONFIG_NATIVE_UART_0_ON_STDINOUT=y diff --git a/tests/net/lib/lwm2m/interop/boards/native_sim.conf b/tests/net/lib/lwm2m/interop/boards/native_sim.conf new file mode 100644 index 00000000000..2dc86f3d484 --- /dev/null +++ b/tests/net/lib/lwm2m/interop/boards/native_sim.conf @@ -0,0 +1,8 @@ +CONFIG_DNS_RESOLVER=y +CONFIG_DNS_SERVER_IP_ADDRESSES=y +CONFIG_DNS_SERVER1="192.0.2.2" +CONFIG_LWM2M_DNS_SUPPORT=y +CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2" +CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME=y +CONFIG_NATIVE_UART_0_ON_STDINOUT=y +CONFIG_ASAN=y diff --git a/tests/net/lib/lwm2m/interop/boards/qemu_cortex_m3.conf b/tests/net/lib/lwm2m/interop/boards/qemu_cortex_m3.conf index 7a3fd344e50..44263f885a4 100644 --- a/tests/net/lib/lwm2m/interop/boards/qemu_cortex_m3.conf +++ b/tests/net/lib/lwm2m/interop/boards/qemu_cortex_m3.conf @@ -5,16 +5,14 @@ CONFIG_NET_QEMU_ETHERNET=y # RAM/ROM tuning CONFIG_IDLE_STACK_SIZE=128 -CONFIG_MBEDTLS_HEAP_SIZE=7000 CONFIG_ISR_STACK_SIZE=512 -CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=1024 -CONFIG_LWM2M_ENGINE_STACK_SIZE=2000 CONFIG_LWM2M_LOG_LEVEL_INF=y -CONFIG_LWM2M_ENGINE_MAX_MESSAGES=3 -CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE=0 -CONFIG_LWM2M_ENGINE_MAX_OBSERVER=5 -CONFIG_LWM2M_SECURITY_DTLS_TLS_CIPHERSUITE_MAX=3 -CONFIG_LWM2M_DEVICE_PWRSRC_MAX=2 -CONFIG_LWM2M_DEVICE_ERROR_CODE_MAX=5 -CONFIG_LWM2M_DEVICE_EXT_DEV_INFO_MAX=2 -CONFIG_LWM2M_NUM_ATTR=10 +CONFIG_LOG_BUFFER_SIZE=512 + +# qemu_cortex_m3 have smaller memory so simulate a small +# device and small network where max CoAP packet is 256+headers. +# This excercises the outgoing block-wise module intentionally. +CONFIG_LWM2M_COAP_MAX_MSG_SIZE=256 +CONFIG_LWM2M_COAP_BLOCK_SIZE=256 +CONFIG_LWM2M_COAP_BLOCK_TRANSFER=y +CONFIG_LWM2M_COAP_ENCODE_BUFFER_SIZE=2048 diff --git a/tests/net/lib/lwm2m/interop/boards/qemu_x86.conf b/tests/net/lib/lwm2m/interop/boards/qemu_x86.conf new file mode 100644 index 00000000000..18e513dffd1 --- /dev/null +++ b/tests/net/lib/lwm2m/interop/boards/qemu_x86.conf @@ -0,0 +1,4 @@ +CONFIG_FPU=y +CONFIG_NET_L2_ETHERNET=y +CONFIG_NET_QEMU_ETHERNET=y +CONFIG_PCIE=y diff --git a/tests/net/lib/lwm2m/interop/docker-test.sh b/tests/net/lib/lwm2m/interop/docker-test.sh new file mode 100644 index 00000000000..9184461aec4 --- /dev/null +++ b/tests/net/lib/lwm2m/interop/docker-test.sh @@ -0,0 +1,20 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if [ -z "$RUNNING_FROM_MAIN_SCRIPT" ]; then + echo "Do not run this script directly!" + echo "Run $ZEPHYR_BASE/scripts/net/run-sample-tests.sh instead." + exit 1 +fi + +IP="--ip=192.0.2.2 --ip6=2001:db8::2" +FWD="-p 8080:8080 -p 8081:8081 -p 5683:5683/udp" + +start_configuration "$IP $FWD" || return $? +start_docker "/net-tools/start-leshan.sh" || return $? + +twister -p native_posix -T ./ --enable-slow -vv + +result=$? + +stop_docker diff --git a/tests/net/lib/lwm2m/interop/prj.conf b/tests/net/lib/lwm2m/interop/prj.conf index 66d6334264f..07bd9a0535d 100644 --- a/tests/net/lib/lwm2m/interop/prj.conf +++ b/tests/net/lib/lwm2m/interop/prj.conf @@ -1,36 +1,22 @@ CONFIG_NETWORKING=y CONFIG_LOG=y -CONFIG_LWM2M_LOG_LEVEL_DBG=y CONFIG_TEST_RANDOM_GENERATOR=y -CONFIG_NET_IPV6=y -CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3 -CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=2 CONFIG_NET_IPV4=y +CONFIG_NET_IPV6=n CONFIG_NET_DHCPV4=n -CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=3 -CONFIG_NET_IF_MCAST_IPV4_ADDR_COUNT=2 -CONFIG_PRINTK=y -CONFIG_NET_PKT_RX_COUNT=10 -CONFIG_NET_PKT_TX_COUNT=10 -CONFIG_NET_BUF_RX_COUNT=10 -CONFIG_NET_BUF_TX_COUNT=10 -CONFIG_NET_MAX_CONTEXTS=5 -CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1" -CONFIG_NET_CONFIG_PEER_IPV6_ADDR="2001:db8::2" +CONFIG_NET_PKT_RX_COUNT=4 +CONFIG_NET_PKT_TX_COUNT=4 +CONFIG_NET_BUF_RX_COUNT=8 +CONFIG_NET_BUF_TX_COUNT=8 +CONFIG_NET_MAX_CONTEXTS=4 CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1" CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2" - -CONFIG_NET_LOG=y - -CONFIG_NET_CONFIG_NEED_IPV6=y CONFIG_NET_CONFIG_NEED_IPV4=y CONFIG_NET_CONFIG_SETTINGS=y CONFIG_LWM2M=y -CONFIG_LWM2M_COAP_BLOCK_SIZE=512 CONFIG_LWM2M_IPSO_SUPPORT=y CONFIG_LWM2M_SHELL=y -CONFIG_LWM2M_ACCESS_CONTROL_ENABLE=n #Enable Portfolio object CONFIG_LWM2M_PORTFOLIO_OBJ_SUPPORT=y @@ -47,7 +33,7 @@ CONFIG_LWM2M_RW_SENML_JSON_SUPPORT=y #Enable SenML CBOR content format CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT=y -CONFIG_LWM2M_RW_SENML_CBOR_RECORDS=60 +CONFIG_LWM2M_RW_SENML_CBOR_RECORDS=40 CONFIG_ZCBOR_CANONICAL=y #Enable legacy content formats @@ -62,7 +48,7 @@ CONFIG_COAP_EXTENDED_OPTIONS_LEN_VALUE=40 CONFIG_LWM2M_QUEUE_MODE_ENABLED=y CONFIG_LWM2M_QUEUE_MODE_UPTIME=20 CONFIG_LWM2M_UPDATE_PERIOD=30 -CONFIG_LWM2M_SECONDS_TO_UPDATE_EARLY=10 +CONFIG_LWM2M_RD_CLIENT_STOP_POLLING_AT_IDLE=y # LwM2M configuration as OMA-ETS-LightweightM2M_INT-V1_1-20190912-D Configuration 3 CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME=30 @@ -74,19 +60,46 @@ CONFIG_MBEDTLS_TLS_VERSION_1_2=y # Special MbedTLS changes CONFIG_MBEDTLS_ENABLE_HEAP=y -CONFIG_MBEDTLS_HEAP_SIZE=8192 -CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=1500 +# MTU - IPv6 header - UDP header - DTLS header +# 1280 - 40 - 8 - 21 +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=1211 +CONFIG_MBEDTLS_HEAP_SIZE=7168 CONFIG_MBEDTLS_CIPHER_CCM_ENABLED=y - # Disable RSA, we don't parse certs: saves flash/memory CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_ENABLED=n # Enable PSK instead CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED=y +CONFIG_LWM2M_SECURITY_DTLS_TLS_CIPHERSUITE_MAX=3 CONFIG_NET_SOCKETS_SOCKOPT_TLS=y -CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=4 +# For testing purposes, limit DTLS contexts to one, +# LwM2M engine should not use more than one on any given time. +CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=1 CONFIG_NET_SOCKETS_ENABLE_DTLS=y - -# MbedTLS needs a larger stack -CONFIG_MAIN_STACK_SIZE=2048 -CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 +CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID=y + +# Assume that IPv6 minimum MTU is accepted +# MTU - IPv6 header - UDP header - DTLS header - CoAP header room +# 1280 - 40 - 8 - 21 - 48 +CONFIG_LWM2M_COAP_MAX_MSG_SIZE=1163 +CONFIG_LWM2M_COAP_BLOCK_SIZE=1024 +CONFIG_LWM2M_COAP_BLOCK_TRANSFER=y +CONFIG_LWM2M_COAP_ENCODE_BUFFER_SIZE=4096 +CONFIG_LWM2M_NUM_OUTPUT_BLOCK_CONTEXT=1 +CONFIG_LWM2M_NUM_BLOCK1_CONTEXT=1 +CONFIG_SYS_HASH_FUNC32=y +CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE=0 +CONFIG_LWM2M_ENGINE_MAX_PENDING=2 +CONFIG_LWM2M_ENGINE_MAX_REPLIES=2 +CONFIG_LWM2M_ENGINE_MAX_MESSAGES=3 +CONFIG_LWM2M_ENGINE_MAX_OBSERVER=5 +CONFIG_LWM2M_DEVICE_PWRSRC_MAX=2 +CONFIG_LWM2M_DEVICE_ERROR_CODE_MAX=2 +CONFIG_LWM2M_DEVICE_EXT_DEV_INFO_MAX=2 +CONFIG_LWM2M_NUM_ATTR=20 + +# Configure stack sizes +CONFIG_MAIN_STACK_SIZE=1024 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512 +CONFIG_SHELL_STACK_SIZE=1536 +CONFIG_LWM2M_ENGINE_STACK_SIZE=2048 diff --git a/tests/net/lib/lwm2m/interop/pytest/conftest.py b/tests/net/lib/lwm2m/interop/pytest/conftest.py new file mode 100644 index 00000000000..9ca971b85c7 --- /dev/null +++ b/tests/net/lib/lwm2m/interop/pytest/conftest.py @@ -0,0 +1,148 @@ +""" +Common test fixtures +#################### + +Copyright (c) 2023 Nordic Semiconductor ASA + +SPDX-License-Identifier: Apache-2.0 + +""" + +import time +import logging +import os +import binascii +import random +import string +import pytest +from leshan import Leshan + +from twister_harness import Shell +from twister_harness import DeviceAdapter + +LESHAN_IP: str = '192.0.2.2' +COAP_PORT: int = 5683 +COAPS_PORT: int = 5684 +BOOTSTRAP_COAPS_PORT: int = 5784 + +logger = logging.getLogger(__name__) + +@pytest.fixture(scope='session') +def leshan() -> Leshan: + """ + Fixture that returns a Leshan object for interacting with the Leshan server. + + :return: The Leshan object. + :rtype: Leshan + """ + try: + return Leshan("http://localhost:8080/api") + except RuntimeError: + pytest.skip('Leshan server not available') + +@pytest.fixture(scope='session') +def leshan_bootstrap() -> Leshan: + """ + Fixture that returns a Leshan object for interacting with the Bootstrap Leshan server. + + :return: The Leshan object. + :rtype: Leshan + """ + try: + return Leshan("http://localhost:8081/api") + except RuntimeError: + pytest.skip('Leshan Bootstrap server not available') + +@pytest.fixture(scope='module') +def helperclient() -> object: + """ + Fixture that returns a helper client object for testing. + + :return: The helper client object. + :rtype: object + """ + try: + from coapthon.client.helperclient import HelperClient + except ModuleNotFoundError: + pytest.skip('CoAPthon3 package not installed') + return HelperClient(server=('127.0.0.1', COAP_PORT)) + + +@pytest.fixture(scope='module') +def endpoint_nosec(shell: Shell, dut: DeviceAdapter, leshan: Leshan) -> str: + """Fixture that returns an endpoint that starts on no-secure mode""" + # Allow engine to start & stop once. + time.sleep(2) + + # Generate randon device id and password (PSK key) + ep = 'client_' + binascii.b2a_hex(os.urandom(1)).decode() + + # + # Registration Interface test cases (using Non-secure mode) + # + shell.exec_command(f'lwm2m write 0/0/0 -s coap://{LESHAN_IP}:{COAP_PORT}') + shell.exec_command('lwm2m write 0/0/1 -b 0') + shell.exec_command('lwm2m write 0/0/2 -u8 3') + shell.exec_command(f'lwm2m write 0/0/3 -s {ep}') + shell.exec_command('lwm2m create 1/0') + shell.exec_command('lwm2m write 0/0/10 -u16 1') + shell.exec_command('lwm2m write 1/0/0 -u16 1') + shell.exec_command('lwm2m write 1/0/1 -u32 86400') + shell.exec_command(f'lwm2m start {ep} -b 0') + dut.readlines_until(regex=f"RD Client started with endpoint '{ep}'", timeout=10.0) + + yield ep + + # All done + shell.exec_command('lwm2m stop') + dut.readlines_until(regex=r'.*Deregistration success', timeout=10.0) + +@pytest.fixture(scope='module') +def endpoint_bootstrap(shell: Shell, dut: DeviceAdapter, leshan: Leshan, leshan_bootstrap: Leshan) -> str: + """Fixture that returns an endpoint that starts the bootstrap.""" + try: + # Generate randon device id and password (PSK key) + ep = 'client_' + binascii.b2a_hex(os.urandom(1)).decode() + bs_passwd = ''.join(random.choice(string.ascii_lowercase) for i in range(16)) + passwd = ''.join(random.choice(string.ascii_lowercase) for i in range(16)) + + logger.debug('Endpoint: %s', ep) + logger.debug('Boostrap PSK: %s', binascii.b2a_hex(bs_passwd.encode()).decode()) + logger.debug('PSK: %s', binascii.b2a_hex(passwd.encode()).decode()) + + # Create device entries in Leshan and Bootstrap server + leshan_bootstrap.create_bs_device(ep, f'coaps://{LESHAN_IP}:{COAPS_PORT}', bs_passwd, passwd) + leshan.create_psk_device(ep, passwd) + + # Allow engine to start & stop once. + time.sleep(2) + + # Write bootsrap server information and PSK keys + shell.exec_command(f'lwm2m write 0/0/0 -s coaps://{LESHAN_IP}:{BOOTSTRAP_COAPS_PORT}') + shell.exec_command('lwm2m write 0/0/1 -b 1') + shell.exec_command('lwm2m write 0/0/2 -u8 0') + shell.exec_command(f'lwm2m write 0/0/3 -s {ep}') + shell.exec_command(f'lwm2m write 0/0/5 -s {bs_passwd}') + shell.exec_command(f'lwm2m start {ep} -b 1') + + yield ep + + shell.exec_command('lwm2m stop') + dut.readlines_until(regex=r'.*Deregistration success', timeout=10.0) + + finally: + # Remove device and bootstrap information + # Leshan does not accept non-secure connection if device information is provided with PSK + leshan.delete_device(ep) + leshan_bootstrap.delete_bs_device(ep) + +@pytest.fixture(scope='module') +def endpoint_registered(endpoint_bootstrap, shell: Shell, dut: DeviceAdapter) -> str: + """Fixture that returns an endpoint that is registered.""" + dut.readlines_until(regex='.*Registration Done', timeout=5.0) + return endpoint_bootstrap + +@pytest.fixture(scope='module') +def endpoint(endpoint_registered) -> str: + """Fixture that returns an endpoint that is registered.""" + return endpoint_registered diff --git a/tests/net/lib/lwm2m/interop/pytest/leshan.py b/tests/net/lib/lwm2m/interop/pytest/leshan.py index 4d69a3a977f..7240aae2baf 100644 --- a/tests/net/lib/lwm2m/interop/pytest/leshan.py +++ b/tests/net/lib/lwm2m/interop/pytest/leshan.py @@ -1,104 +1,438 @@ -# Copyright (c) 2023 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 +""" +REST client for Leshan demo server +################################## + +Copyright (c) 2023 Nordic Semiconductor ASA + +SPDX-License-Identifier: Apache-2.0 + +""" from __future__ import annotations import json -import requests import binascii +import time +from datetime import datetime +from contextlib import contextmanager +import requests class Leshan: + """This class represents a Leshan client that interacts with demo server's REAT API""" def __init__(self, url: str): + """Initialize Leshan client and check if server is available""" self.api_url = url self.timeout = 10 - self.format = 'TLV' - # self.format = "SENML_CBOR" + #self.format = 'TLV' + self.format = "SENML_CBOR" + self._s = requests.Session() try: resp = self.get('/security/clients') if not isinstance(resp, list): raise RuntimeError('Did not receive list of endpoints') - except requests.exceptions.ConnectionError: - raise RuntimeError('Leshan not responding') + except requests.exceptions.ConnectionError as exc: + raise RuntimeError('Leshan not responding') from exc @staticmethod def handle_response(resp: requests.models.Response): - """Generic response handler for all queries""" + """ + Handle the response received from the server. + + Parameters: + - response: The response object received from the server. + + Returns: + - dict: The parsed JSON response as a dictionary. + + Raises: + - Exception: If the response indicates an error condition. + """ if resp.status_code >= 300 or resp.status_code < 200: raise RuntimeError(f'Error {resp.status_code}: {resp.text}') if len(resp.text): obj = json.loads(resp.text) return obj - else: - return None + return None def get(self, path: str): - """Send HTTP GET query""" - resp = requests.get(f'{self.api_url}{path}?timeout={self.timeout}&format={self.format}') + """Send HTTP GET query with typical parameters""" + params = {'timeout': self.timeout} + if self.format is not None: + params['format'] = self.format + resp = self._s.get(f'{self.api_url}{path}', params=params, timeout=self.timeout) return Leshan.handle_response(resp) def put_raw(self, path: str, data: str | dict | None = None, headers: dict | None = None): - resp = requests.put(f'{self.api_url}{path}', data=data, headers=headers) + """Send HTTP PUT query without any default parameters""" + resp = self._s.put(f'{self.api_url}{path}', data=data, headers=headers, timeout=self.timeout) return Leshan.handle_response(resp) def put(self, path: str, data: str | dict, uri_options: str = ''): + """Send HTTP PUT query with typical parameters""" if isinstance(data, dict): data = json.dumps(data) return self.put_raw(f'{path}?timeout={self.timeout}&format={self.format}' + uri_options, data=data, headers={'content-type': 'application/json'}) def post(self, path: str, data: str | dict | None = None): - resp = requests.post(f'{self.api_url}{path}', data=data, headers={'content-type': 'application/json'}) + """Send HTTP POST query""" + if isinstance(data, dict): + data = json.dumps(data) + if data is not None: + headers={'content-type': 'application/json'} + uri_options = f'?timeout={self.timeout}&format={self.format}' + else: + headers=None + uri_options = '' + resp = self._s.post(f'{self.api_url}{path}' + uri_options, data=data, headers=headers, timeout=self.timeout) return Leshan.handle_response(resp) - def delete(self, path: str): - resp = requests.delete(f'{self.api_url}{path}') + def delete_raw(self, path: str): + """Send HTTP DELETE query""" + resp = self._s.delete(f'{self.api_url}{path}', timeout=self.timeout) return Leshan.handle_response(resp) + def delete(self, endpoint: str, path: str): + """Send LwM2M DELETE command""" + return self.delete_raw(f'/clients/{endpoint}/{path}') + def execute(self, endpoint: str, path: str): + """Send LwM2M EXECUTE command""" return self.post(f'/clients/{endpoint}/{path}') def write(self, endpoint: str, path: str, value: bool | int | str): + """Send LwM2M WRITE command to a single resource or resource instance""" + if len(path.split('/')) == 3: + kind = 'singleResource' + else: + kind = 'resourceInstance' + rid = path.split('/')[-1] + return self.put(f'/clients/{endpoint}/{path}', self._define_resource(rid, value, kind)) + + def update_obj_instance(self, endpoint: str, path: str, resources: dict): + """Update object instance""" + data = self._define_obj_inst(path, resources) + return self.put(f'/clients/{endpoint}/{path}', data, uri_options='&replace=false') + + def replace_obj_instance(self, endpoint: str, path: str, resources: dict): + """Replace object instance""" + data = self._define_obj_inst(path, resources) + return self.put(f'/clients/{endpoint}/{path}', data, uri_options='&replace=true') + + def create_obj_instance(self, endpoint: str, path: str, resources: dict): + """Send LwM2M CREATE command""" + data = self._define_obj_inst(path, resources) + path = '/'.join(path.split('/')[:-1]) # Create call should not have instance ID in path + return self.post(f'/clients/{endpoint}/{path}', data) + + @classmethod + def _type_to_string(cls, value): + """ + Convert a Python value to its corresponding Leshan representation. + + Parameters: + - value: The value to be converted. + + Returns: + - str: The string representation of the value. + """ if isinstance(value, bool): - type = 'boolean' - value = "true" if value else "false" - elif isinstance(value, int): - type = 'integer' - value = str(value) - elif isinstance(value, str): - type = 'string' - value = '"' + value + '"' - id = path.split('/')[2] - return self.put(f'/clients/{endpoint}/{path}', f'{{"id":{id},"kind":"singleResource","value":{value},"type":"{type}"}}') + return 'boolean' + if isinstance(value, int): + return 'integer' + if isinstance(value, datetime): + return 'time' + return 'string' + + @classmethod + def _convert_type(cls, value): + """Wrapper for special types that are not understood by Json""" + if isinstance(value, datetime): + return int(value.timestamp()) + else: + return value + + @classmethod + def _define_obj_inst(cls, path: str, resources: dict): + """Define an object instance for Leshan""" + data = { + "kind": "instance", + "id": int(path.split('/')[-1]), # ID is last element of path + "resources": [] + } + for key, value in resources.items(): + if isinstance(value, dict): + kind = 'multiResource' + else: + kind = 'singleResource' + data['resources'].append(cls._define_resource(key, value, kind)) + return data + + @classmethod + def _define_resource(cls, rid, value, kind='singleResource'): + """Define a resource for Leshan""" + if kind in ('singleResource', 'resourceInstance'): + return { + "id": rid, + "kind": kind, + "value": cls._convert_type(value), + "type": cls._type_to_string(value) + } + if kind == 'multiResource': + return { + "id": rid, + "kind": kind, + "values": value, + "type": cls._type_to_string(list(value.values())[0]) + } + raise RuntimeError(f'Unhandled type {kind}') + + @classmethod + def _decode_value(cls, val_type: str, value: str): + """ + Decode the Leshan representation of a value back to a Python value. + """ + if val_type == 'BOOLEAN': + return bool(value) + if val_type == 'INTEGER': + return int(value) + return value + + @classmethod + def _decode_resource(cls, content: dict): + """ + Decode the Leshan representation of a resource back to a Python dictionary. + """ + if content['kind'] == 'singleResource' or content['kind'] == 'resourceInstance': + return {content['id']: cls._decode_value(content['type'], content['value'])} + elif content['kind'] == 'multiResource': + values = {} + for riid, value in content['values'].items(): + values.update({int(riid): cls._decode_value(content['type'], value)}) + return {content['id']: values} + raise RuntimeError(f'Unhandled type {content["kind"]}') + + @classmethod + def _decode_obj_inst(cls, content): + """ + Decode the Leshan representation of an object instance back to a Python dictionary. + """ + resources = {} + for resource in content['resources']: + resources.update(cls._decode_resource(resource)) + return {content['id']: resources} + + @classmethod + def _decode_obj(cls, content): + """ + Decode the Leshan representation of an object back to a Python dictionary. + """ + instances = {} + for instance in content['instances']: + instances.update(cls._decode_obj_inst(instance)) + return {content['id']: instances} def read(self, endpoint: str, path: str): + """Send LwM2M READ command and decode the response to a Python dictionary""" resp = self.get(f'/clients/{endpoint}/{path}') if not resp['success']: return resp content = resp['content'] - if content['kind'] == 'instance': - return content['resources'] - elif content['kind'] == 'singleResource': - return content['value'] + if content['kind'] == 'obj': + return self._decode_obj(content) + elif content['kind'] == 'instance': + return self._decode_obj_inst(content) + elif content['kind'] == 'singleResource' or content['kind'] == 'resourceInstance': + return self._decode_value(content['type'], content['value']) elif content['kind'] == 'multiResource': - return content['values'] + return self._decode_resource(content) raise RuntimeError(f'Unhandled type {content["kind"]}') + @classmethod + def parse_composite(cls, payload: dict): + """Decode the Leshan's response to composite query back to a Python dictionary""" + data = {} + if 'status' in payload: + if payload['status'] != 'CONTENT(205)' or 'content' not in payload: + raise RuntimeError(f'No content received') + payload = payload['content'] + for path, content in payload.items(): + keys = [int(key) for key in path.lstrip("/").split('/')] + if len(keys) == 1: + data.update(cls._decode_obj(content)) + elif len(keys) == 2: + if keys[0] not in data: + data[keys[0]] = {} + data[keys[0]].update(cls._decode_obj_inst(content)) + elif len(keys) == 3: + if keys[0] not in data: + data[keys[0]] = {} + if keys[1] not in data[keys[0]]: + data[keys[0]][keys[1]] = {} + data[keys[0]][keys[1]].update(cls._decode_resource(content)) + elif len(keys) == 4: + if keys[0] not in data: + data[keys[0]] = {} + if keys[1] not in data[keys[0]]: + data[keys[0]][keys[1]] = {} + if keys[2] not in data[keys[0]][keys[1]]: + data[keys[0]][keys[1]][keys[2]] = {} + data[keys[0]][keys[1]][keys[2]].update(cls._decode_resource(content)) + else: + raise RuntimeError(f'Unhandled path {path}') + return data + + def _composite_params(self, paths: list[str] | None = None): + """Common URI parameters for composite query""" + parameters = { + 'pathformat': self.format, + 'nodeformat': self.format, + 'timeout': self.timeout + } + if paths is not None: + paths = [path if path.startswith('/') else '/' + path for path in paths] + parameters['paths'] = ','.join(paths) + + return parameters + + def composite_read(self, endpoint: str, paths: list[str]): + """Send LwM2M Composite-Read command and decode the response to a Python dictionary""" + parameters = self._composite_params(paths) + resp = self._s.get(f'{self.api_url}/clients/{endpoint}/composite', params=parameters, timeout=self.timeout) + payload = Leshan.handle_response(resp) + return self.parse_composite(payload) + + def composite_write(self, endpoint: str, resources: dict): + """ + Send LwM2m Composite-Write operation. + + Targeted resources are defined as a dictionary with the following structure: + { + "/1/0/1": 60, + "/1/0/6": True, + "/16/0/0": { + "0": "aa", + "1": "bb", + "2": "cc", + "3": "dd" + } + } + + Objects or object instances cannot be targeted. + """ + data = { } + parameters = self._composite_params() + for path, value in resources.items(): + path = path if path.startswith('/') else '/' + path + level = len(path.split('/')) - 1 + rid = int(path.split('/')[-1]) + if level == 3: + if isinstance(value, dict): + value = self._define_resource(rid, value, kind='multiResource') + else: + value = self._define_resource(rid, value) + elif level == 4: + value = self._define_resource(rid, value, kind='resourceInstance') + else: + raise RuntimeError(f'Unhandled path {path}') + data[path] = value + + resp = self._s.put(f'{self.api_url}/clients/{endpoint}/composite', params=parameters, json=data, timeout=self.timeout) + return Leshan.handle_response(resp) + + def discover(self, endpoint: str, path: str): + resp = self.handle_response(self._s.get(f'{self.api_url}/clients/{endpoint}/{path}/discover', timeout=self.timeout)) + data = {} + for obj in resp['objectLinks']: + data[obj['url']] = obj['attributes'] + return data + def create_psk_device(self, endpoint: str, passwd: str): psk = binascii.b2a_hex(passwd.encode()).decode() self.put('/security/clients/', f'{{"endpoint":"{endpoint}","tls":{{"mode":"psk","details":{{"identity":"{endpoint}","key":"{psk}"}} }} }}') def delete_device(self, endpoint: str): - self.delete(f'/security/clients/{endpoint}') + self.delete_raw(f'/security/clients/{endpoint}') - def create_bs_device(self, endpoint: str, server_uri: str, passwd: str): - psk = binascii.b2a_hex(passwd.encode()).decode() + def create_bs_device(self, endpoint: str, server_uri: str, bs_passwd: str, passwd: str): + psk = binascii.b2a_hex(bs_passwd.encode()).decode() data = f'{{"tls":{{"mode":"psk","details":{{"identity":"{endpoint}","key":"{psk}"}}}},"endpoint":"{endpoint}"}}' self.put('/security/clients/', data) - id = str([ord(n) for n in endpoint]) + ep = str([ord(n) for n in endpoint]) key = str([ord(n) for n in passwd]) - content = '{"servers":{"0":{"binding":"U","defaultMinPeriod":1,"lifetime":86400,"notifIfDisabled":false,"shortId":1}},"security":{"1":{"bootstrapServer":false,"clientOldOffTime":1,"publicKeyOrId":' + id + ',"secretKey":' + key + ',"securityMode":"PSK","serverId":1,"serverSmsNumber":"","smsBindingKeyParam":[],"smsBindingKeySecret":[],"smsSecurityMode":"NO_SEC","uri":"'+server_uri+'"}},"oscore":{},"toDelete":["/0","/1"]}' + content = '{"servers":{"0":{"binding":"U","defaultMinPeriod":1,"lifetime":86400,"notifIfDisabled":false,"shortId":1}},"security":{"1":{"bootstrapServer":false,"clientOldOffTime":1,"publicKeyOrId":' + ep + ',"secretKey":' + key + ',"securityMode":"PSK","serverId":1,"serverSmsNumber":"","smsBindingKeyParam":[],"smsBindingKeySecret":[],"smsSecurityMode":"NO_SEC","uri":"'+server_uri+'"}},"oscore":{},"toDelete":["/0","/1"]}' self.post(f'/bootstrap/{endpoint}', content) def delete_bs_device(self, endpoint: str): - self.delete(f'/security/clients/{endpoint}') - self.delete(f'/bootstrap/{endpoint}') + self.delete_raw(f'/security/clients/{endpoint}') + self.delete_raw(f'/bootstrap/{endpoint}') + + def observe(self, endpoint: str, path: str): + return self.post(f'/clients/{endpoint}/{path}/observe', data="") + + def cancel_observe(self, endpoint: str, path: str): + return self.delete_raw(f'/clients/{endpoint}/{path}/observe') + + def composite_observe(self, endpoint: str, paths: list[str]): + parameters = self._composite_params(paths) + resp = self._s.post(f'{self.api_url}/clients/{endpoint}/composite/observe', params=parameters, timeout=self.timeout) + payload = Leshan.handle_response(resp) + return self.parse_composite(payload) + + def cancel_composite_observe(self, endpoint: str, paths: list[str]): + paths = [path if path.startswith('/') else '/' + path for path in paths] + return self.delete_raw(f'/clients/{endpoint}/composite/observe?paths=' + ','.join(paths)) + + @contextmanager + def get_event_stream(self, endpoint: str, timeout: int = None): + """ + Get stream of events regarding the given endpoint. + + Events are notifications, updates and sends. + + The event stream must be closed after the use, so this must be used in 'with' statement like this: + with leshan.get_event_stream('native_posix') as events: + data = events.next_event('SEND') + + If timeout happens, the event streams returns None. + """ + if timeout is None: + timeout = self.timeout + r = requests.get(f'{self.api_url}/event?{endpoint}', stream=True, headers={'Accept': 'text/event-stream'}, timeout=timeout) + if r.encoding is None: + r.encoding = 'utf-8' + try: + yield LeshanEventsIterator(r, timeout) + finally: + r.close() + +class LeshanEventsIterator: + """Iterator for Leshan event stream""" + def __init__(self, req: requests.Response, timeout: int): + """Initialize the iterator in line mode""" + self._it = req.iter_lines(chunk_size=1, decode_unicode=True) + self._timeout = timeout + + def next_event(self, event: str): + """ + Finds the next occurrence of a specific event in the stream. + + If timeout happens, the returns None. + """ + timeout = time.time() + self._timeout + try: + for line in self._it: + if line == f'event: {event}': + for line in self._it: + if not line.startswith('data: '): + continue + data = json.loads(line.lstrip('data: ')) + if event == 'SEND' or (event == 'NOTIFICATION' and data['kind'] == 'composite'): + return Leshan.parse_composite(data['val']) + if event == 'NOTIFICATION': + d = {data['res']: data['val']} + return Leshan.parse_composite(d) + return data + if time.time() > timeout: + return None + except requests.exceptions.Timeout: + return None diff --git a/tests/net/lib/lwm2m/interop/pytest/test_bootstrap.py b/tests/net/lib/lwm2m/interop/pytest/test_bootstrap.py new file mode 100644 index 00000000000..65561db0676 --- /dev/null +++ b/tests/net/lib/lwm2m/interop/pytest/test_bootstrap.py @@ -0,0 +1,58 @@ +""" +LwM2M Bootstrap interface tests +############################### + +Copyright (c) 2023 Nordic Semiconductor ASA + +SPDX-License-Identifier: Apache-2.0 + +Test specification: +=================== +https://www.openmobilealliance.org/release/LightweightM2M/ETS/OMA-ETS-LightweightM2M-V1_1-20190912-D.pdf + + +This module contains only testcases that verify the bootstrap. +""" + +import logging +from leshan import Leshan +from twister_harness import Shell +from twister_harness import DeviceAdapter + +logger = logging.getLogger(__name__) + + +# +# Test specification: +# https://www.openmobilealliance.org/release/LightweightM2M/ETS/OMA-ETS-LightweightM2M-V1_1-20190912-D.pdf +# +# Bootstrap Interface: [0-99] +# + +def verify_LightweightM2M_1_1_int_0(shell: Shell, dut: DeviceAdapter): + """LightweightM2M-1.1-int-0 - Client Initiated Bootstrap""" + dut.readlines_until(regex='.*Bootstrap started with endpoint', timeout=5.0) + dut.readlines_until(regex='.*Bootstrap registration done', timeout=5.0) + dut.readlines_until(regex='.*Bootstrap data transfer done', timeout=5.0) + +def test_LightweightM2M_1_1_int_1(shell: Shell, dut: DeviceAdapter, leshan: Leshan, endpoint_bootstrap: str): + """LightweightM2M-1.1-int-1 - Client Initiated Bootstrap Full (PSK)""" + verify_LightweightM2M_1_1_int_0(shell, dut) + verify_LightweightM2M_1_1_int_101(shell, dut, leshan, endpoint_bootstrap) + verify_LightweightM2M_1_1_int_401(shell, leshan, endpoint_bootstrap) + +def verify_LightweightM2M_1_1_int_101(shell: Shell, dut: DeviceAdapter, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-101 - Initial Registration""" + dut.readlines_until(regex='.*Registration Done', timeout=5.0) + assert leshan.get(f'/clients/{endpoint}') + +def verify_LightweightM2M_1_1_int_401(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-401 - UDP Channel Security - Pre-shared Key Mode""" + lines = shell.get_filtered_output(shell.exec_command('lwm2m read 0/0/0 -s')) + host = lines[0] + assert 'coaps://' in host + lines = shell.get_filtered_output(shell.exec_command('lwm2m read 0/0/2 -u8')) + mode = int(lines[0]) + assert mode == 0 + resp = leshan.get(f'/clients/{endpoint}') + assert resp["secure"] diff --git a/tests/net/lib/lwm2m/interop/pytest/test_lwm2m.py b/tests/net/lib/lwm2m/interop/pytest/test_lwm2m.py index 21ed51ef1e6..8f3acd69c7e 100644 --- a/tests/net/lib/lwm2m/interop/pytest/test_lwm2m.py +++ b/tests/net/lib/lwm2m/interop/pytest/test_lwm2m.py @@ -1,252 +1,161 @@ -# Copyright (c) 2023 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 +""" +Various LwM2M interoperability tests +#################################### + +Copyright (c) 2023 Nordic Semiconductor ASA + +SPDX-License-Identifier: Apache-2.0 + +Test specification: +=================== +https://www.openmobilealliance.org/release/LightweightM2M/ETS/OMA-ETS-LightweightM2M-V1_1-20190912-D.pdf + + +This module contains testcases for + * Registration Interface [100-199] + * Device management & Service Enablement Interface [200-299] + * Information Reporting Interface [300-399] + +""" import time import logging +from datetime import datetime import pytest from leshan import Leshan -import os -import binascii -import random -import string from twister_harness import Shell - -LESHAN_IP: str = '192.0.2.2' -COAP_PORT: int = 5683 -COAPS_PORT: int = 5684 -BOOTSTRAP_COAPS_PORT: int = 5784 +from twister_harness import DeviceAdapter logger = logging.getLogger(__name__) -@pytest.fixture(scope='module') -def helperclient() -> object: - try: - from coapthon.client.helperclient import HelperClient - except ModuleNotFoundError: - pytest.skip('CoAPthon3 package not installed') - return HelperClient(server=('127.0.0.1', COAP_PORT)) - -@pytest.fixture(scope='session') -def leshan() -> Leshan: - try: - return Leshan("http://localhost:8080/api") - except RuntimeError: - pytest.skip('Leshan server not available') - -@pytest.fixture(scope='session') -def leshan_bootstrap() -> Leshan: - try: - return Leshan("http://localhost:8081/api") - except RuntimeError: - pytest.skip('Leshan Bootstrap server not available') -# -# Test specification: -# https://www.openmobilealliance.org/release/LightweightM2M/ETS/OMA-ETS-LightweightM2M-V1_1-20190912-D.pdf -# - -def verify_LightweightM2M_1_1_int_0(shell: Shell): - logger.info("LightweightM2M-1.1-int-0 - Client Initiated Bootstrap") - shell._device.readlines_until(regex='.*Bootstrap started with endpoint', timeout=5.0) - shell._device.readlines_until(regex='.*Bootstrap registration done', timeout=5.0) - shell._device.readlines_until(regex='.*Bootstrap data transfer done', timeout=5.0) - -def verify_LightweightM2M_1_1_int_1(shell: Shell, leshan: Leshan, endpoint: str): - logger.info("LightweightM2M-1.1-int-1 - Client Initiated Bootstrap Full (PSK)") - verify_LightweightM2M_1_1_int_0(shell) - verify_LightweightM2M_1_1_int_101(shell, leshan, endpoint) - verify_LightweightM2M_1_1_int_401(shell, leshan, endpoint) - -def verify_LightweightM2M_1_1_int_101(shell: Shell, leshan: Leshan, endpoint: str): - logger.info("LightweightM2M-1.1-int-101 - Initial Registration") - shell._device.readlines_until(regex='.*Registration Done', timeout=5.0) - assert leshan.get(f'/clients/{endpoint}') - -def verify_LightweightM2M_1_1_int_102(shell: Shell, leshan: Leshan, endpoint: str): - logger.info("LightweightM2M-1.1-int-102 - Registration Update") +def test_LightweightM2M_1_1_int_102(shell: Shell, dut: DeviceAdapter, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-102 - Registration Update""" lines = shell.get_filtered_output(shell.exec_command('lwm2m read 1/0/1 -u32')) - litetime = int(lines[0]) - lifetime = litetime + 10 + lifetime = int(lines[0]) + lifetime = lifetime + 10 start_time = time.time() * 1000 leshan.write(endpoint, '1/0/1', lifetime) - shell._device.readlines_until(regex='.*net_lwm2m_rd_client: Update Done', timeout=5.0) + dut.readlines_until(regex='.*net_lwm2m_rd_client: Update Done', timeout=5.0) latest = leshan.get(f'/clients/{endpoint}') assert latest["lastUpdate"] > start_time assert latest["lastUpdate"] <= time.time()*1000 assert latest["lifetime"] == lifetime shell.exec_command('lwm2m write 1/0/1 -u32 86400') -def verify_LightweightM2M_1_1_int_103(): - """LightweightM2M-1.1-int-103 - Deregistration""" - # Unsupported. We don't have "disabled" functionality in server object - -def verify_LightweightM2M_1_1_int_104(shell: Shell, leshan: Leshan, endpoint: str): - logger.info("LightweightM2M-1.1-int-104 - Registration Update Trigger") +def test_LightweightM2M_1_1_int_104(shell: Shell, dut: DeviceAdapter, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-104 - Registration Update Trigger""" shell.exec_command('lwm2m update') - shell._device.readlines_until(regex='.*net_lwm2m_rd_client: Update Done', timeout=5.0) + dut.readlines_until(regex='.*net_lwm2m_rd_client: Update Done', timeout=5.0) leshan.execute(endpoint, '1/0/8') - shell._device.readlines_until(regex='.*net_lwm2m_rd_client: Update Done', timeout=5.0) - -def verify_LightweightM2M_1_1_int_105(shell: Shell, leshan: Leshan, endpoint: str, helperclient: object): - logger.info("LightweightM2M-1.1-int-105 - Discarded Register Update") - status = leshan.get(f'/clients/{endpoint}') - if status["secure"]: - logger.debug("Skip, requires non-secure connection") - return - id = status["registrationId"] - assert id - # Fake unregister message - helperclient.delete(f'rd/{id}', timeout=0.1) - helperclient.stop() - time.sleep(1) - shell.exec_command('lwm2m update') - shell._device.readlines_until(regex=r'.*Failed with code 4\.4', timeout=5.0) - shell._device.readlines_until(regex='.*Registration Done', timeout=10.0) + dut.readlines_until(regex='.*net_lwm2m_rd_client: Update Done', timeout=5.0) -def verify_LightweightM2M_1_1_int_107(shell: Shell, leshan: Leshan, endpoint: str): - logger.info("LightweightM2M-1.1-int-107 - Extending the lifetime of a registration") +def test_LightweightM2M_1_1_int_107(shell: Shell, dut: DeviceAdapter, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-107 - Extending the lifetime of a registration""" leshan.write(endpoint, '1/0/1', 120) - shell._device.readlines_until(regex='.*net_lwm2m_rd_client: Update Done', timeout=5.0) + dut.readlines_until(regex='.*net_lwm2m_rd_client: Update Done', timeout=5.0) lines = shell.get_filtered_output(shell.exec_command('lwm2m read 1/0/1 -u32')) lifetime = int(lines[0]) assert lifetime == 120 - logger.debug(f'sleeping for {lifetime} s') - shell._device.readlines_until(regex='.*net_lwm2m_rd_client: Update Done', timeout=lifetime) + logger.debug(f'Wait for update, max {lifetime} s') + dut.readlines_until(regex='.*net_lwm2m_rd_client: Update Done', timeout=lifetime) assert leshan.get(f'/clients/{endpoint}') -def verify_LightweightM2M_1_1_int_108(leshan, endpoint): - logger.info("LightweightM2M-1.1-int-108 - Turn on Queue Mode") +def test_LightweightM2M_1_1_int_108(leshan, endpoint): + """LightweightM2M-1.1-int-108 - Turn on Queue Mode""" assert leshan.get(f'/clients/{endpoint}')["queuemode"] -def verify_LightweightM2M_1_1_int_109(shell: Shell, leshan: Leshan, endpoint: str): - logger.info("LightweightM2M-1.1-int-109 - Behavior in Queue Mode") - verify_LightweightM2M_1_1_int_107(shell, leshan, endpoint) - shell._device.readlines_until(regex='.*Queue mode RX window closed', timeout=120) +def test_LightweightM2M_1_1_int_109(shell: Shell, dut: DeviceAdapter, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-109 - Behavior in Queue Mode""" + logger.debug('Wait for Queue RX OFF') + dut.readlines_until(regex='.*Queue mode RX window closed', timeout=120) # Restore previous value shell.exec_command('lwm2m write 1/0/1 -u32 86400') - shell._device.readlines_until(regex='.*Registration update complete', timeout=10) - -def verify_LightweightM2M_1_1_int_201(shell: Shell, leshan: Leshan, endpoint: str): + dut.readlines_until(regex='.*Registration update complete', timeout=10) - logger.info("LightweightM2M-1.1-int-201 - Querying basic information in Plain Text format") +def test_LightweightM2M_1_1_int_201(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-201 - Querying basic information in Plain Text format""" fmt = leshan.format leshan.format = 'TEXT' - assert leshan.get(f'/clients/{endpoint}/3/0/0')['content']['value'] == 'Zephyr' - assert leshan.get(f'/clients/{endpoint}/3/0/1')['content']['value'] == 'client-1' - assert leshan.get(f'/clients/{endpoint}/3/0/2')['content']['value'] == 'serial-1' + assert leshan.read(endpoint, '3/0/0') == 'Zephyr' + assert leshan.read(endpoint, '3/0/1') == 'client-1' + assert leshan.read(endpoint, '3/0/2') == 'serial-1' leshan.format = fmt def verify_device_object(resp): ''' Verify that Device object match Configuration 3 ''' - assert resp['valid'] is True - found = 0 - for res in resp['content']['resources']: - if res['id'] == 0: - assert res['value'] == 'Zephyr' - found += 1 - elif res['id'] == 1: - assert res['value'] == 'client-1' - found += 1 - elif res['id'] == 2: - assert res['value'] == 'serial-1' - found += 1 - elif res['id'] == 3: - assert res['value'] == '1.2.3' - found += 1 - elif res['id'] == 11: - assert res['kind'] == 'multiResource' - assert res['values']['0'] == '0' - found += 1 - elif res['id'] == 16: - assert res['value'] == 'U' - found += 1 - assert found == 6 + assert resp[0][0] == 'Zephyr' + assert resp[0][1] == 'client-1' + assert resp[0][2] == 'serial-1' + assert resp[0][3] == '1.2.3' + assert resp[0][11][0] == 0 + assert resp[0][16] == 'U' def verify_server_object(obj): ''' Verify that server object match Configuration 3 ''' - found = 0 - for res in obj['resources']: - if res['id'] == 0: - assert res['value'] == '1' - found += 1 - elif res['id'] == 1: - assert res['value'] == '86400' - found += 1 - elif res['id'] == 2: - assert res['value'] == '1' - found += 1 - elif res['id'] == 3: - assert res['value'] == '10' - found += 1 - elif res['id'] == 5: - assert res['value'] == '86400' - found += 1 - elif res['id'] == 6: - assert res['value'] is False - found += 1 - elif res['id'] == 7: - assert res['value'] == 'U' - found += 1 - assert found == 7 - -def verify_LightweightM2M_1_1_int_203(shell: Shell, leshan: Leshan, endpoint: str): - shell.exec_command('lwm2m update') - logger.info('LightweightM2M-1.1-int-203 - Querying basic information in TLV format') + assert obj[0][0] == 1 + assert obj[0][1] == 86400 + assert obj[0][2] == 1 + assert obj[0][3] == 10 + assert obj[0][5] == 86400 + assert obj[0][6] is False + assert obj[0][7] == 'U' + +def test_LightweightM2M_1_1_int_203(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-203 - Querying basic information in TLV format""" fmt = leshan.format leshan.format = 'TLV' - resp = leshan.get(f'/clients/{endpoint}/3/0') + resp = leshan.read(endpoint,'3/0') verify_device_object(resp) leshan.format = fmt -def verify_LightweightM2M_1_1_int_204(shell: Shell, leshan: Leshan, endpoint: str): - shell.exec_command('lwm2m update') - logger.info('LightweightM2M-1.1-int-204 - Querying basic information in JSON format') +def test_LightweightM2M_1_1_int_204(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-204 - Querying basic information in JSON format""" fmt = leshan.format leshan.format = 'JSON' - resp = leshan.get(f'/clients/{endpoint}/3/0') + resp = leshan.read(endpoint, '3/0') verify_device_object(resp) leshan.format = fmt -def verify_LightweightM2M_1_1_int_205(shell: Shell, leshan: Leshan, endpoint: str): - logger.info('LightweightM2M-1.1-int-205 - Setting basic information in Plain Text format') +def test_LightweightM2M_1_1_int_205(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-205 - Setting basic information in Plain Text format""" fmt = leshan.format leshan.format = 'TEXT' leshan.write(endpoint, '1/0/2', 101) leshan.write(endpoint, '1/0/3', 1010) leshan.write(endpoint, '1/0/5', 2000) - assert leshan.read(endpoint, '1/0/2') == '101' - assert leshan.read(endpoint, '1/0/3') == '1010' - assert leshan.read(endpoint, '1/0/5') == '2000' + assert leshan.read(endpoint, '1/0/2') == 101 + assert leshan.read(endpoint, '1/0/3') == 1010 + assert leshan.read(endpoint, '1/0/5') == 2000 leshan.write(endpoint, '1/0/2', 1) leshan.write(endpoint, '1/0/3', 10) leshan.write(endpoint, '1/0/5', 86400) - assert leshan.read(endpoint, '1/0/2') == '1' - assert leshan.read(endpoint, '1/0/3') == '10' - assert leshan.read(endpoint, '1/0/5') == '86400' + assert leshan.read(endpoint, '1/0/2') == 1 + assert leshan.read(endpoint, '1/0/3') == 10 + assert leshan.read(endpoint, '1/0/5') == 86400 leshan.format = fmt -def verify_LightweightM2M_1_1_int_211(shell: Shell, leshan: Leshan, endpoint: str): - logger.info('LightweightM2M-1.1-int-211 - Querying basic information in CBOR format') +def test_LightweightM2M_1_1_int_211(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-211 - Querying basic information in CBOR format""" fmt = leshan.format leshan.format = 'CBOR' lines = shell.get_filtered_output(shell.exec_command('lwm2m read 1/0/0 -u16')) - id = lines[0] - assert leshan.read(endpoint, '1/0/0') == id + short_id = int(lines[0]) + assert leshan.read(endpoint, '1/0/0') == short_id assert leshan.read(endpoint, '1/0/6') is False assert leshan.read(endpoint, '1/0/7') == 'U' leshan.format = fmt -def verify_LightweightM2M_1_1_int_212(shell: Shell, leshan: Leshan, endpoint: str): - logger.info('LightweightM2M-1.1-int-212 - Setting basic information in CBOR format') +def test_LightweightM2M_1_1_int_212(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-212 - Setting basic information in CBOR format""" fmt = leshan.format leshan.format = 'CBOR' leshan.write(endpoint, '1/0/2', 101) leshan.write(endpoint, '1/0/3', 1010) leshan.write(endpoint, '1/0/6', True) - assert leshan.read(endpoint, '1/0/2') == '101' - assert leshan.read(endpoint, '1/0/3') == '1010' + assert leshan.read(endpoint, '1/0/2') == 101 + assert leshan.read(endpoint, '1/0/3') == 1010 assert leshan.read(endpoint, '1/0/6') is True leshan.write(endpoint, '1/0/2', 1) leshan.write(endpoint, '1/0/3', 10) @@ -256,191 +165,540 @@ def verify_LightweightM2M_1_1_int_212(shell: Shell, leshan: Leshan, endpoint: st def verify_setting_basic_in_format(shell, leshan, endpoint, format): fmt = leshan.format leshan.format = format - server_obj = leshan.get(f'/clients/{endpoint}/1/0')['content'] + server_obj = leshan.read(endpoint, '1/0') verify_server_object(server_obj) # Remove Read-Only resources, so we don't end up writing those - for res in server_obj['resources']: - if res['id'] in (0, 11, 12): - server_obj['resources'].remove(res) - data = '''{ - "kind": "instance", - "id": 0, - "resources": [ - { - "id": 2, - "kind": "singleResource", - "value": "101", - "type": "integer" - }, - { - "id": 3, - "kind": "singleResource", - "value": "1010", - "type": "integer" - }, - { - "id": 5, - "kind": "singleResource", - "value": "2000", - "type": "integer" - }, - { - "id": 6, - "kind": "singleResource", - "value": true, - "type": "boolean" - }, - { - "id": 7, - "kind": "singleResource", - "value": "U", - "type": "string" - } - ] - }''' - assert leshan.put(f'/clients/{endpoint}/1/0', data, uri_options = '&replace=false')['status'] == 'CHANGED(204)' - resp = leshan.get(f'/clients/{endpoint}/1/0') - assert resp['valid'] is True - found = 0 - for res in resp['content']['resources']: - if res['id'] == 2: - assert res['value'] == '101' - found += 1 - elif res['id'] == 3: - assert res['value'] == '1010' - found += 1 - elif res['id'] == 5: - assert res['value'] == '2000' - found += 1 - elif res['id'] == 6: - assert res['value'] is True - found += 1 - elif res['id'] == 7: - assert res['value'] == 'U' - found += 1 - assert found == 5 - assert leshan.put(f'/clients/{endpoint}/1/0', data = server_obj, uri_options = '&replace=true')['status'] == 'CHANGED(204)' - server_obj = leshan.get(f'/clients/{endpoint}/1/0')['content'] + del server_obj[0][0] + data = { + 2: 101, + 3: 1010, + 5: 2000, + 6: True, + 7: 'U' + } + assert leshan.update_obj_instance(endpoint, '1/0', data)['status'] == 'CHANGED(204)' + resp = leshan.read(endpoint, '1/0') + assert resp[0][2] == 101 + assert resp[0][3] == 1010 + assert resp[0][5] == 2000 + assert resp[0][6] is True + assert resp[0][7] == 'U' + assert leshan.replace_obj_instance(endpoint, '1/0', server_obj[0])['status'] == 'CHANGED(204)' + server_obj = leshan.read(endpoint, '1/0') verify_server_object(server_obj) leshan.format = fmt -def verify_LightweightM2M_1_1_int_215(shell: Shell, leshan: Leshan, endpoint: str): - logger.info('LightweightM2M-1.1-int-215 - Setting basic information in TLV format') +def test_LightweightM2M_1_1_int_215(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-215 - Setting basic information in TLV format""" verify_setting_basic_in_format(shell, leshan, endpoint, 'TLV') -def verify_LightweightM2M_1_1_int_220(shell: Shell, leshan: Leshan, endpoint: str): - logger.info('LightweightM2M-1.1-int-220 - Setting basic information in JSON format') +def test_LightweightM2M_1_1_int_220(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-220 - Setting basic information in JSON format""" verify_setting_basic_in_format(shell, leshan, endpoint, 'JSON') -def verify_LightweightM2M_1_1_int_221(shell: Shell, leshan: Leshan, endpoint: str): - logger.info('LightweightM2M-1.1-int-221 - Attempt to perform operations on Security') +def test_LightweightM2M_1_1_int_221(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-221 - Attempt to perform operations on Security""" assert leshan.read(endpoint, '0/0')['status'] == 'UNAUTHORIZED(401)' assert leshan.write(endpoint, '0/0/0', 'coap://localhost')['status'] == 'UNAUTHORIZED(401)' assert leshan.put_raw(f'/clients/{endpoint}/0/attributes?pmin=10')['status'] == 'UNAUTHORIZED(401)' -def verify_LightweightM2M_1_1_int_401(shell: Shell, leshan: Leshan, endpoint: str): - logger.info("LightweightM2M-1.1-int-401 - UDP Channel Security - Pre-shared Key Mode") - lines = shell.get_filtered_output(shell.exec_command('lwm2m read 0/0/0 -s')) - host = lines[0] - assert 'coaps://' in host - lines = shell.get_filtered_output(shell.exec_command('lwm2m read 0/0/2 -u8')) - mode = int(lines[0]) - assert mode == 0 - resp = leshan.get(f'/clients/{endpoint}') - assert resp["secure"] - -def test_lwm2m_bootstrap_psk(shell: Shell, leshan, leshan_bootstrap): - try: - # Generate randon device id and password (PSK key) - endpoint = 'client_' + binascii.b2a_hex(os.urandom(1)).decode() - passwd = ''.join(random.choice(string.ascii_lowercase) for i in range(16)) - - - # Create device entries in Leshan and Bootstrap server - leshan_bootstrap.create_bs_device(endpoint, f'coaps://{LESHAN_IP}:{COAPS_PORT}', passwd) - leshan.create_psk_device(endpoint, passwd) - - # Allow engine to start & stop once. - time.sleep(2) - - # - # Verify PSK security using Bootstrap - # - - # Write bootsrap server information and PSK keys - shell.exec_command(f'lwm2m write 0/0/0 -s coaps://{LESHAN_IP}:{BOOTSTRAP_COAPS_PORT}') - shell.exec_command('lwm2m write 0/0/1 -b 1') - shell.exec_command('lwm2m write 0/0/2 -u8 0') - shell.exec_command(f'lwm2m write 0/0/3 -s {endpoint}') - shell.exec_command(f'lwm2m write 0/0/5 -s {passwd}') - shell.exec_command(f'lwm2m start {endpoint} -b 1') - - - # - # Bootstrap Interface test cases - # LightweightM2M-1.1-int-0 (included) - # LightweightM2M-1.1-int-401 (included) - verify_LightweightM2M_1_1_int_1(shell, leshan, endpoint) - - # - # Registration Interface test cases (using PSK security) - # - verify_LightweightM2M_1_1_int_102(shell, leshan, endpoint) - # skip, not implemented verify_LightweightM2M_1_1_int_103() - verify_LightweightM2M_1_1_int_104(shell, leshan, endpoint) - # skip, included in 109: verify_LightweightM2M_1_1_int_107(shell, leshan, endpoint) - verify_LightweightM2M_1_1_int_108(leshan, endpoint) - verify_LightweightM2M_1_1_int_109(shell, leshan, endpoint) - - # - # Device management & Service Enablement Interface test cases - # - verify_LightweightM2M_1_1_int_201(shell, leshan, endpoint) - verify_LightweightM2M_1_1_int_203(shell, leshan, endpoint) - verify_LightweightM2M_1_1_int_204(shell, leshan, endpoint) - verify_LightweightM2M_1_1_int_205(shell, leshan, endpoint) - verify_LightweightM2M_1_1_int_211(shell, leshan, endpoint) - verify_LightweightM2M_1_1_int_212(shell, leshan, endpoint) - verify_LightweightM2M_1_1_int_215(shell, leshan, endpoint) - - shell.exec_command('lwm2m stop') - shell._device.readlines_until(regex=r'.*Deregistration success', timeout=10.0) - - finally: - # Remove device and bootstrap information - # Leshan does not accept non-secure connection if device information is provided with PSK - leshan.delete_device(endpoint) - leshan_bootstrap.delete_bs_device(endpoint) - - -def test_lwm2m_nosecure(shell: Shell, leshan, helperclient): - - # Allow engine to start & stop once. - time.sleep(2) - - # Generate randon device id and password (PSK key) - endpoint = 'client_' + binascii.b2a_hex(os.urandom(1)).decode() - - # - # Registration Interface test cases (using Non-secure mode) - # - shell.exec_command(f'lwm2m write 0/0/0 -s coap://{LESHAN_IP}:{COAP_PORT}') - shell.exec_command('lwm2m write 0/0/1 -b 0') - shell.exec_command('lwm2m write 0/0/2 -u8 3') - shell.exec_command(f'lwm2m write 0/0/3 -s {endpoint}') - shell.exec_command('lwm2m create 1/0') - shell.exec_command('lwm2m write 0/0/10 -u16 1') - shell.exec_command('lwm2m write 1/0/0 -u16 1') - shell.exec_command('lwm2m write 1/0/1 -u32 86400') +def test_LightweightM2M_1_1_int_222(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-222 - Read on Object""" + resp = leshan.read(endpoint, '1') + assert len(resp) == 1 + assert len(resp[1][0]) == 9 + resp = leshan.read(endpoint, '3') + assert len(resp) == 1 + assert len(resp[3]) == 1 + assert len(resp[3][0]) == 15 + assert resp[3][0][0] == 'Zephyr' + +def test_LightweightM2M_1_1_int_223(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-223 - Read on Object Instance""" + resp = leshan.read(endpoint, '1/0') + assert len(resp[0]) == 9 + resp = leshan.read(endpoint, '3/0') + assert len(resp[0]) == 15 + assert resp[0][0] == 'Zephyr' + +def test_LightweightM2M_1_1_int_224(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-224 - Read on Resource""" + assert leshan.read(endpoint, '1/0/0') == 1 + assert leshan.read(endpoint, '1/0/1') == 86400 + assert leshan.read(endpoint, '1/0/6') is False + assert leshan.read(endpoint, '1/0/7') == 'U' + +def test_LightweightM2M_1_1_int_225(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-225 - Read on Resource Instance""" + assert leshan.read(endpoint, '3/0/11/0') == 0 + +def test_LightweightM2M_1_1_int_226(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-226 - Write (Partial Update) on Object Instance""" + lines = shell.get_filtered_output(shell.exec_command('lwm2m read 1/0/1 -u32')) + lifetime = int(lines[0]) + resources = { + 1: 60, + 6: True + } + assert leshan.update_obj_instance(endpoint, '1/0', resources)['status'] == 'CHANGED(204)' + assert leshan.read(endpoint, '1/0/1') == 60 + assert leshan.read(endpoint, '1/0/6') is True + resources = { + 1: lifetime, + 6: False + } + assert leshan.update_obj_instance(endpoint, '1/0', resources)['status'] == 'CHANGED(204)' + +def test_LightweightM2M_1_1_int_227(shell: Shell, dut: DeviceAdapter, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-227 - Write (replace) on Resource""" + lines = shell.get_filtered_output(shell.exec_command('lwm2m read 1/0/1 -u32')) + lifetime = int(lines[0]) + assert leshan.write(endpoint, '1/0/1', int(63))['status'] == 'CHANGED(204)' + dut.readlines_until(regex='.*net_lwm2m_rd_client: Update Done', timeout=5.0) + latest = leshan.get(f'/clients/{endpoint}') + assert latest["lifetime"] == 63 + assert leshan.read(endpoint, '1/0/1') == 63 + assert leshan.write(endpoint, '1/0/1', lifetime)['status'] == 'CHANGED(204)' + +def test_LightweightM2M_1_1_int_228(shell: Shell, dut: DeviceAdapter, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-228 - Write on Resource Instance""" + resources = { + 0: {0: 'a', 1: 'b'} + } + assert leshan.create_obj_instance(endpoint, '16/0', resources)['status'] == 'CREATED(201)' + dut.readlines_until(regex='.*net_lwm2m_rd_client: Update Done', timeout=5.0) + assert leshan.write(endpoint, '16/0/0/0', 'test')['status'] == 'CHANGED(204)' + assert leshan.read(endpoint, '16/0/0/0') == 'test' + +def test_LightweightM2M_1_1_int_229(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-229 - Read-Composite Operation""" + old_fmt = leshan.format + for fmt in ['SENML_JSON', 'SENML_CBOR']: + leshan.format = fmt + resp = leshan.composite_read(endpoint, ['/3', '1/0']) + assert len(resp.keys()) == 2 + assert resp[3] is not None + assert resp[1][0] is not None + assert len(resp[3][0]) == 15 + assert len(resp[1][0]) == 9 + + resp = leshan.composite_read(endpoint, ['1/0/1', '/3/0/11/0']) + logger.debug(resp) + assert len(resp.keys()) == 2 + assert resp[1][0][1] is not None + assert resp[3][0][11][0] is not None + leshan.format = old_fmt + +def test_LightweightM2M_1_1_int_230(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-230 - Write-Composite Operation""" + resources = { + "/1/0/1": 60, + "/1/0/6": True, + "/16/0/0": { + "0": "aa", + "1": "bb", + "2": "cc", + "3": "dd" + } + } + old_fmt = leshan.format + for fmt in ['SENML_JSON', 'SENML_CBOR']: + leshan.format = fmt + assert leshan.composite_write(endpoint, resources)['status'] == 'CHANGED(204)' + resp = leshan.read(endpoint, '1/0') + assert resp[0][1] == 60 + assert resp[0][6] is True + resp = leshan.read(endpoint, '16/0/0') + assert resp[0][0] == "aa" + assert resp[0][1] == "bb" + assert resp[0][2] == "cc" + assert resp[0][3] == "dd" + # Return to default + shell.exec_command('lwm2m write /1/0/1 -u32 86400') + shell.exec_command('lwm2m write /1/0/6 -u8 0') + leshan.format = old_fmt + +def query_basic_in_senml(leshan: Leshan, endpoint: str, fmt: str): + """Querying basic information in one of the SenML formats""" + old_fmt = leshan.format + leshan.format = fmt + verify_server_object(leshan.read(endpoint, '1')[1]) + verify_device_object(leshan.read(endpoint, '3/0')) + assert leshan.read(endpoint, '3/0/16') == 'U' + assert leshan.read(endpoint, '3/0/11/0') == 0 + leshan.format = old_fmt + +def test_LightweightM2M_1_1_int_231(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-231 - Querying basic information in SenML JSON format""" + query_basic_in_senml(leshan, endpoint, 'SENML_JSON') + +def test_LightweightM2M_1_1_int_232(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-232 - Querying basic information in SenML CBOR format""" + query_basic_in_senml(leshan, endpoint, 'SENML_CBOR') + +def setting_basic_senml(shell: Shell, leshan: Leshan, endpoint: str, fmt: str): + """Setting basic information in one of the SenML formats""" + old_fmt = leshan.format + leshan.format = fmt + resources = { + 1: 61, + 6: True, + } + assert leshan.update_obj_instance(endpoint, '1/0', resources)['status'] == 'CHANGED(204)' + srv_obj = leshan.read(endpoint, '1/0') + assert srv_obj[0][1] == 61 + assert srv_obj[0][6] is True + assert leshan.write(endpoint, '16/0/0/0', 'test_value')['status'] == 'CHANGED(204)' + portfolio = leshan.read(endpoint, '16') + assert portfolio[16][0][0][0] == 'test_value' + assert leshan.write(endpoint, '1/0/1', 63)['status'] == 'CHANGED(204)' + assert leshan.read(endpoint, '1/0/1') == 63 + shell.exec_command('lwm2m write /1/0/1 -u32 86400') + shell.exec_command('lwm2m write /1/0/6 -u8 0') + leshan.format = old_fmt + +def test_LightweightM2M_1_1_int_233(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-233 - Setting basic information in SenML CBOR format""" + setting_basic_senml(shell, leshan, endpoint, 'SENML_CBOR') + +def test_LightweightM2M_1_1_int_234(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-234 - Setting basic information in SenML JSON format""" + setting_basic_senml(shell, leshan, endpoint, 'SENML_JSON') + +@pytest.mark.skip("Leshan does not allow reading root path") +def test_LightweightM2M_1_1_int_235(): + """LightweightM2M-1.1-int-235 - Read-Composite Operation on root path""" + +def test_LightweightM2M_1_1_int_236(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-236 - Read-Composite - Partial Presence""" + resp = leshan.composite_read(endpoint, ['1/0', '/3/0/11/0', '/3339/0/5522', '/3353/0/6030']) + assert resp[1][0][1] is not None + assert resp[3][0][11][0] is not None + assert len(resp) == 2 + +def test_LightweightM2M_1_1_int_237(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-237 - Read on Object without specifying Content-Type""" + old_fmt = leshan.format + leshan.format = None + assert leshan.read(endpoint, '1')[1][0][1] is not None + assert leshan.read(endpoint, '3')[3][0][0] == 'Zephyr' + leshan.format = old_fmt + +def test_LightweightM2M_1_1_int_241(shell: Shell, dut: DeviceAdapter, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-241 - Executable Resource: Rebooting the device""" + leshan.execute(endpoint, '3/0/4') + dut.readlines_until(regex='.*DEVICE: REBOOT', timeout=5.0) + dut.readlines_until(regex='.*rd_client_event: Disconnected', timeout=5.0) shell.exec_command(f'lwm2m start {endpoint} -b 0') - shell._device.readlines_until(regex=f"RD Client started with endpoint '{endpoint}'", timeout=10.0) + dut.readlines_until(regex='.*Registration Done', timeout=5.0) + assert leshan.get(f'/clients/{endpoint}') - verify_LightweightM2M_1_1_int_101(shell, leshan, endpoint) - verify_LightweightM2M_1_1_int_105(shell, leshan, endpoint, helperclient) # needs no-security - verify_LightweightM2M_1_1_int_215(shell, leshan, endpoint) - verify_LightweightM2M_1_1_int_220(shell, leshan, endpoint) - verify_LightweightM2M_1_1_int_221(shell, leshan, endpoint) +def test_LightweightM2M_1_1_int_256(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-256 - Write Operation Failure""" + lines = shell.get_filtered_output(shell.exec_command('lwm2m read 1/0/0 -u16')) + short_id = int(lines[0]) + assert leshan.write(endpoint, '1/0/0', 123)['status'] == 'METHOD_NOT_ALLOWED(405)' + assert leshan.read(endpoint, '1/0/0') == short_id + +def test_LightweightM2M_1_1_int_257(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-257 - Write-Composite Operation""" + resources = { + "/1/0/2": 102, + "/1/0/6": True, + "/3/0/13": datetime.fromtimestamp(0) + } + old_fmt = leshan.format + for fmt in ['SENML_JSON', 'SENML_CBOR']: + leshan.format = fmt + assert leshan.composite_write(endpoint, resources)['status'] == 'CHANGED(204)' + assert leshan.read(endpoint, '1/0/2') == 102 + assert leshan.read(endpoint, '1/0/6') is True + # Cannot verify the /3/0/13, it is a timestamp that moves forward. + + # Return to default + shell.exec_command(f'lwm2m write /3/0/13 -u32 {int(datetime.now().timestamp())}') + shell.exec_command('lwm2m write /1/0/6 -u8 0') + shell.exec_command('lwm2m write /1/0/2 -u32 1') + leshan.format = old_fmt + +def test_LightweightM2M_1_1_int_260(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-260 - Discover Command""" + resp = leshan.discover(endpoint, '3') + expected_keys = ['/3', '/3/0', '/3/0/1', '/3/0/2', '/3/0/3', '/3/0/4', '/3/0/6', '/3/0/7', '/3/0/8', '/3/0/9', '/3/0/11', '/3/0/16'] + missing_keys = [key for key in expected_keys if key not in resp.keys()] + assert len(missing_keys) == 0 + assert leshan.put_raw(f'/clients/{endpoint}/3/attributes?pmin=10')['status'] == 'CHANGED(204)' + assert leshan.put_raw(f'/clients/{endpoint}/3/attributes?pmax=200')['status'] == 'CHANGED(204)' + resp = leshan.discover(endpoint, '3/0') + assert int(resp['/3/0/6']['dim']) == 2 + assert int(resp['/3/0/7']['dim']) == 2 + assert int(resp['/3/0/8']['dim']) == 2 + assert leshan.put_raw(f'/clients/{endpoint}/3/0/7/attributes?lt=1')['status'] == 'CHANGED(204)' + assert leshan.put_raw(f'/clients/{endpoint}/3/0/7/attributes?gt=6')['status'] == 'CHANGED(204)' + assert leshan.put_raw(f'/clients/{endpoint}/3/0/7/attributes?st=1')['status'] == 'CHANGED(204)' + resp = leshan.discover(endpoint, '3/0') + expected_keys = ['/3/0', '/3/0/1', '/3/0/2', '/3/0/3', '/3/0/4', '/3/0/6', '/3/0/7', '/3/0/8', '/3/0/9', '/3/0/11', '/3/0/16'] + missing_keys = [key for key in expected_keys if key not in resp.keys()] + assert len(missing_keys) == 0 + assert int(resp['/3/0/7']['dim']) == 2 + assert float(resp['/3/0/7']['lt']) == 1.0 + assert float(resp['/3/0/7']['gt']) == 6.0 + assert float(resp['/3/0/7']['st']) == 1.0 + resp = leshan.discover(endpoint, '3/0/7') + expected_keys = ['/3/0/7', '/3/0/7/0', '/3/0/7/1'] + missing_keys = [key for key in expected_keys if key not in resp.keys()] + assert len(missing_keys) == 0 + assert len(resp) == len(expected_keys) + +@pytest.mark.skip(reason="Leshan don't allow writing attributes to resource instance") +def test_LightweightM2M_1_1_int_261(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-261 - Write-Attribute Operation on a multiple resource""" + resp = leshan.discover(endpoint, '3/0/11') + logger.debug(resp) + expected_keys = ['/3/0/11', '/3/0/11/0'] + missing_keys = [key for key in expected_keys if key not in resp.keys()] + assert len(missing_keys) == 0 + assert len(resp) == len(expected_keys) + assert int(resp['/3/0/11']['dim']) == 1 + assert leshan.put_raw(f'/clients/{endpoint}/3/attributes?pmin=10')['status'] == 'CHANGED(204)' + assert leshan.put_raw(f'/clients/{endpoint}/3/attributes?pmax=200')['status'] == 'CHANGED(204)' + assert leshan.put_raw(f'/clients/{endpoint}/3/0/attributes?pmax=320')['status'] == 'CHANGED(204)' + assert leshan.put_raw(f'/clients/{endpoint}/3/0/11/0/attributes?pmax=100')['status'] == 'CHANGED(204)' + assert leshan.put_raw(f'/clients/{endpoint}/3/0/11/0/attributes?epmin=1')['status'] == 'CHANGED(204)' + assert leshan.put_raw(f'/clients/{endpoint}/3/0/11/0/attributes?epmax=20')['status'] == 'CHANGED(204)' + resp = leshan.discover(endpoint, '3/0/11') + logger.debug(resp) + assert int(resp['/3/0/11']['pmin']) == 10 + assert int(resp['/3/0/11']['pmax']) == 320 + assert int(resp['/3/0/11/0']['pmax']) == 100 + assert int(resp['/3/0/11/0']['epmin']) == 1 + assert int(resp['/3/0/11/0']['epmax']) == 20 + +def test_LightweightM2M_1_1_int_280(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-280 - Successful Read-Composite Operation""" + resp = leshan.composite_read(endpoint, ['/3/0/16', '/3/0/11/0', '/1/0']) + logger.debug(resp) + assert len(resp) == 2 + assert len(resp[3]) == 1 + assert len(resp[3][0]) == 2 # No extra resources + assert resp[3][0][11][0] == 0 + assert resp[3][0][16] == 'U' + assert resp[1][0][0] == 1 + assert resp[1][0][1] == 86400 + assert resp[1][0][6] is False + assert resp[1][0][7] == 'U' + +def test_LightweightM2M_1_1_int_281(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-281 - Partially Successful Read-Composite Operation""" + resp = leshan.composite_read(endpoint, ['/1/0/1', '/1/0/7', '/1/0/8']) + assert len(resp) == 1 + assert len(resp[1][0]) == 2 # /1/0/8 should not be there + assert resp[1][0][1] == 86400 + assert resp[1][0][7] == 'U' + +# +# Information Reporting Interface [300-399] +# - # All done - shell.exec_command('lwm2m stop') - shell._device.readlines_until(regex=r'.*Deregistration success', timeout=10.0) +def test_LightweightM2M_1_1_int_301(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-301 - Observation and Notification of parameter values""" + pwr_src = leshan.read(endpoint, '3/0/6') + logger.debug(pwr_src) + assert pwr_src[6][0] == 1 + assert pwr_src[6][1] == 5 + assert leshan.put_raw(f'/clients/{endpoint}/3/0/7/attributes?pmin=5')['status'] == 'CHANGED(204)' + assert leshan.put_raw(f'/clients/{endpoint}/3/0/7/attributes?pmax=10')['status'] == 'CHANGED(204)' + leshan.observe(endpoint, '3/0/7') + with leshan.get_event_stream(endpoint, timeout=30) as events: + shell.exec_command('lwm2m write /3/0/7/0 -u32 3000') + data = events.next_event('NOTIFICATION') + assert data is not None + assert data[3][0][7][0] == 3000 + # Ensure that we don't get new data before pMin + start = time.time() + shell.exec_command('lwm2m write /3/0/7/0 -u32 3500') + data = events.next_event('NOTIFICATION') + assert data[3][0][7][0] == 3500 + assert (start + 5) < time.time() + 0.5 # Allow 0.5 second diff + assert (start + 5) > time.time() - 0.5 + # Ensure that we get update when pMax expires + data = events.next_event('NOTIFICATION') + assert data[3][0][7][0] == 3500 + assert (start + 15) <= time.time() + 1 # Allow 1 second slack. (pMinx + pMax=15) + leshan.cancel_observe(endpoint, '3/0/7') + +def test_LightweightM2M_1_1_int_302(shell: Shell, dut: DeviceAdapter, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-302 - Cancel Observations using Reset Operation""" + leshan.observe(endpoint, '3/0/7') + leshan.observe(endpoint, '3/0/8') + with leshan.get_event_stream(endpoint) as events: + shell.exec_command('lwm2m write /3/0/7/0 -u32 4000') + data = events.next_event('NOTIFICATION') + assert data[3][0][7][0] == 4000 + leshan.cancel_observe(endpoint, '3/0/7') + shell.exec_command('lwm2m write /3/0/7/0 -u32 3000') + dut.readlines_until(regex=r'.*Observer removed for 3/0/7') + with leshan.get_event_stream(endpoint) as events: + shell.exec_command('lwm2m write /3/0/8/0 -u32 100') + data = events.next_event('NOTIFICATION') + assert data[3][0][8][0] == 100 + leshan.cancel_observe(endpoint, '3/0/8') + shell.exec_command('lwm2m write /3/0/8/0 -u32 50') + dut.readlines_until(regex=r'.*Observer removed for 3/0/8') + +def test_LightweightM2M_1_1_int_304(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-304 - Observe-Composite Operation""" + assert leshan.put_raw(f'/clients/{endpoint}/1/0/1/attributes?pmin=30')['status'] == 'CHANGED(204)' + assert leshan.put_raw(f'/clients/{endpoint}/1/0/1/attributes?pmax=45')['status'] == 'CHANGED(204)' + data = leshan.composite_observe(endpoint, ['/1/0/1', '/3/0/11/0', '/3/0/16']) + assert data[1][0][1] is not None + assert data[3][0][11][0] is not None + assert data[3][0][16] == 'U' + assert len(data) == 2 + assert len(data[1]) == 1 + assert len(data[3][0]) == 2 + start = time.time() + with leshan.get_event_stream(endpoint, timeout=50) as events: + data = events.next_event('NOTIFICATION') + logger.debug(data) + assert data[1][0][1] is not None + assert data[3][0][11][0] is not None + assert data[3][0][16] == 'U' + assert len(data) == 2 + assert len(data[1]) == 1 + assert len(data[3][0]) == 2 + assert (start + 30) < time.time() + assert (start + 45) > time.time() - 1 + leshan.cancel_composite_observe(endpoint, ['/1/0/1', '/3/0/11/0', '/3/0/16']) + +def test_LightweightM2M_1_1_int_306(shell: Shell, dut: DeviceAdapter, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-306 - Send Operation""" + with leshan.get_event_stream(endpoint) as events: + shell.exec_command('lwm2m send /1 /3') + dut.readlines_until(regex=r'.*SEND status: 0', timeout=5.0) + data = events.next_event('SEND') + assert data is not None + verify_server_object(data[1]) + verify_device_object(data[3]) + +def test_LightweightM2M_1_1_int_307(shell: Shell, dut: DeviceAdapter, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-307 - Muting Send""" + leshan.write(endpoint, '1/0/23', True) + lines = shell.get_filtered_output(shell.exec_command('lwm2m send /3/0')) + assert any("can't do send operation" in line for line in lines) + leshan.write(endpoint, '1/0/23', False) + shell.exec_command('lwm2m send /3/0') + dut.readlines_until(regex=r'.*SEND status: 0', timeout=5.0) + +def test_LightweightM2M_1_1_int_308(shell: Shell, dut: DeviceAdapter, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-308 - Observe-Composite and Creating Object Instance""" + shell.exec_command('lwm2m delete /16/0') + shell.exec_command('lwm2m delete /16/1') + # Need to use Configuration C.1 + shell.exec_command('lwm2m write 1/0/2 -u32 0') + shell.exec_command('lwm2m write 1/0/3 -u32 0') + resources_a = { + 0: {0: 'aa', + 1: 'bb', + 2: 'cc', + 3: 'dd'} + } + content_one = {16: {0: resources_a}} + resources_b = { + 0: {0: '11', + 1: '22', + 2: '33', + 3: '44'} + } + content_both = {16: {0: resources_a, 1: resources_b}} + assert leshan.create_obj_instance(endpoint, '16/0', resources_a)['status'] == 'CREATED(201)' + dut.readlines_until(regex='.*net_lwm2m_rd_client: Update Done', timeout=5.0) + assert leshan.put_raw(f'/clients/{endpoint}/16/0/attributes?pmin=30')['status'] == 'CHANGED(204)' + assert leshan.put_raw(f'/clients/{endpoint}/16/0/attributes?pmax=45')['status'] == 'CHANGED(204)' + data = leshan.composite_observe(endpoint, ['/16/0', '/16/1']) + assert data == content_one + with leshan.get_event_stream(endpoint, timeout=50) as events: + data = events.next_event('NOTIFICATION') + start = time.time() + assert data == content_one + assert leshan.create_obj_instance(endpoint, '16/1', resources_b)['status'] == 'CREATED(201)' + data = events.next_event('NOTIFICATION') + assert (start + 30) < time.time() + 2 + assert (start + 45) > time.time() - 2 + assert data == content_both + leshan.cancel_composite_observe(endpoint, ['/16/0', '/16/1']) + # Restore configuration C.3 + shell.exec_command('lwm2m write 1/0/2 -u32 1') + shell.exec_command('lwm2m write 1/0/3 -u32 10') + +def test_LightweightM2M_1_1_int_309(shell: Shell, dut: DeviceAdapter, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-309 - Observe-Composite and Deleting Object Instance""" + shell.exec_command('lwm2m delete /16/0') + shell.exec_command('lwm2m delete /16/1') + # Need to use Configuration C.1 + shell.exec_command('lwm2m write 1/0/2 -u32 0') + shell.exec_command('lwm2m write 1/0/3 -u32 0') + resources_a = { + 0: {0: 'aa', + 1: 'bb', + 2: 'cc', + 3: 'dd'} + } + content_one = {16: {0: resources_a}} + resources_b = { + 0: {0: '11', + 1: '22', + 2: '33', + 3: '44'} + } + content_both = {16: {0: resources_a, 1: resources_b}} + assert leshan.create_obj_instance(endpoint, '16/0', resources_a)['status'] == 'CREATED(201)' + assert leshan.create_obj_instance(endpoint, '16/1', resources_b)['status'] == 'CREATED(201)' + dut.readlines_until(regex='.*net_lwm2m_rd_client: Update Done', timeout=5.0) + assert leshan.put_raw(f'/clients/{endpoint}/16/0/attributes?pmin=30')['status'] == 'CHANGED(204)' + assert leshan.put_raw(f'/clients/{endpoint}/16/0/attributes?pmax=45')['status'] == 'CHANGED(204)' + data = leshan.composite_observe(endpoint, ['/16/0', '/16/1']) + assert data == content_both + with leshan.get_event_stream(endpoint, timeout=50) as events: + data = events.next_event('NOTIFICATION') + start = time.time() + assert data == content_both + assert leshan.delete(endpoint, '16/1')['status'] == 'DELETED(202)' + data = events.next_event('NOTIFICATION') + assert (start + 30) < time.time() + 2 + assert (start + 45) > time.time() - 2 + assert data == content_one + leshan.cancel_composite_observe(endpoint, ['/16/0', '/16/1']) + # Restore configuration C.3 + shell.exec_command('lwm2m write 1/0/2 -u32 1') + shell.exec_command('lwm2m write 1/0/3 -u32 10') + +def test_LightweightM2M_1_1_int_310(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-310 - Observe-Composite and modification of parameter values""" + # Need to use Configuration C.1 + shell.exec_command('lwm2m write 1/0/2 -u32 0') + shell.exec_command('lwm2m write 1/0/3 -u32 0') + # Ensure that our previous attributes are not conflicting + assert leshan.put_raw(f'/clients/{endpoint}/3/attributes?pmin=0')['status'] == 'CHANGED(204)' + leshan.composite_observe(endpoint, ['/1/0/1', '/3/0']) + with leshan.get_event_stream(endpoint, timeout=50) as events: + assert leshan.put_raw(f'/clients/{endpoint}/3/attributes?pmax=5')['status'] == 'CHANGED(204)' + start = time.time() + data = events.next_event('NOTIFICATION') + assert data[3][0][0] == 'Zephyr' + assert data[1] == {0: {1: 86400}} + assert (start + 5) > time.time() - 1 + start = time.time() + data = events.next_event('NOTIFICATION') + assert (start + 5) > time.time() - 1 + leshan.cancel_composite_observe(endpoint, ['/1/0/1', '/3/0']) + # Restore configuration C.3 + shell.exec_command('lwm2m write 1/0/2 -u32 1') + shell.exec_command('lwm2m write 1/0/3 -u32 10') + +def test_LightweightM2M_1_1_int_311(shell: Shell, leshan: Leshan, endpoint: str): + """LightweightM2M-1.1-int-311 - Send command""" + with leshan.get_event_stream(endpoint, timeout=50) as events: + shell.exec_command('lwm2m send /1/0/1 /3/0/11') + data = events.next_event('SEND') + assert data == {3: {0: {11: {0: 0}}}, 1: {0: {1: 86400}}} diff --git a/tests/net/lib/lwm2m/interop/pytest/test_nosec.py b/tests/net/lib/lwm2m/interop/pytest/test_nosec.py new file mode 100644 index 00000000000..15ac98f2d1a --- /dev/null +++ b/tests/net/lib/lwm2m/interop/pytest/test_nosec.py @@ -0,0 +1,53 @@ +""" +Tests for No-security mode +########################## + +Copyright (c) 2023 Nordic Semiconductor ASA + +SPDX-License-Identifier: Apache-2.0 + +Test specification: +=================== +https://www.openmobilealliance.org/release/LightweightM2M/ETS/OMA-ETS-LightweightM2M-V1_1-20190912-D.pdf + + +This module contains only testcases that are able to run on non-secure mode. +""" + +import time +import logging +from leshan import Leshan + +from twister_harness import Shell +from twister_harness import DeviceAdapter + +logger = logging.getLogger(__name__) + +def test_LightweightM2M_1_1_int_101(shell: Shell, dut: DeviceAdapter, leshan: Leshan, endpoint_nosec: str): + """ + Verify that the client is registered. + Note that this MUST be the first testcase executed, otherwise it will fail to get the + correct log output. + """ + logger.info("LightweightM2M-1.1-int-101 - Initial Registration") + dut.readlines_until(regex='.*Registration Done', timeout=5.0) + assert leshan.get(f'/clients/{endpoint_nosec}') + +def test_LightweightM2M_1_1_int_105(shell: Shell, dut: DeviceAdapter, leshan: Leshan, endpoint_nosec: str, helperclient: object): + """ + Run testcase LightweightM2M-1.1-int-105 - Discarded Register Update + """ + logger.info("LightweightM2M-1.1-int-105 - Discarded Register Update") + status = leshan.get(f'/clients/{endpoint_nosec}') + if status["secure"]: + logger.debug("Skip, requires non-secure connection") + return + regid = status["registrationId"] + assert regid + # Fake unregister message + helperclient.delete(f'rd/{regid}', timeout=0.1) + helperclient.stop() + time.sleep(1) + shell.exec_command('lwm2m update') + dut.readlines_until(regex=r'.*Failed with code 4\.4', timeout=5.0) + dut.readlines_until(regex='.*Registration Done', timeout=10.0) diff --git a/tests/net/lib/lwm2m/interop/src/lwm2m-client.c b/tests/net/lib/lwm2m/interop/src/lwm2m-client.c index 983fea79f3e..706091659a5 100644 --- a/tests/net/lib/lwm2m/interop/src/lwm2m-client.c +++ b/tests/net/lib/lwm2m/interop/src/lwm2m-client.c @@ -11,11 +11,11 @@ #include LOG_MODULE_REGISTER(LOG_MODULE_NAME); #include -#include #include #include #include #include +#include #define APP_BANNER "Run LWM2M client" @@ -28,14 +28,54 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #define VERSION "1.2.3" static struct lwm2m_ctx client; +static void rd_client_event(struct lwm2m_ctx *client, + enum lwm2m_rd_client_event client_event); +static void observe_cb(enum lwm2m_observe_event event, + struct lwm2m_obj_path *path, void *user_data); + +static uint8_t bat_idx = LWM2M_DEVICE_PWR_SRC_TYPE_BAT_INT; +static int bat_mv = 3800; +static int bat_ma = 125; +static uint8_t usb_idx = LWM2M_DEVICE_PWR_SRC_TYPE_USB; +static int usb_mv = 5000; +static int usb_ma = 900; + +static void reboot_handler(struct k_work *work) +{ + /* I cannot really restart the client, as we don't know + * the endpoint name. Testcase sets that on a command line. + * So we only stop. + */ + lwm2m_rd_client_stop(&client, rd_client_event, true); +} + +K_WORK_DEFINE(reboot_work, reboot_handler); static int device_reboot_cb(uint16_t obj_inst_id, uint8_t *args, uint16_t args_len) { LOG_INF("DEVICE: REBOOT"); + k_work_submit(&reboot_work); return 0; } +int set_socketoptions(struct lwm2m_ctx *ctx) +{ + if (IS_ENABLED(CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID) && ctx->use_dtls) { + int ret; + + /* Enable CID */ + int cid = TLS_DTLS_CID_ENABLED; + + ret = zsock_setsockopt(ctx->sock_fd, SOL_TLS, TLS_DTLS_CID, &cid, + sizeof(cid)); + if (ret) { + ret = -errno; + LOG_ERR("Failed to enable TLS_DTLS_CID: %d", ret); + } + } + return lwm2m_set_default_sockopt(ctx); +} static int lwm2m_setup(void) { @@ -53,6 +93,20 @@ static int lwm2m_setup(void) lwm2m_set_res_buf(&LWM2M_OBJ(3, 0, 17), CONFIG_BOARD, sizeof(CONFIG_BOARD), sizeof(CONFIG_BOARD), LWM2M_RES_DATA_FLAG_RO); + /* add power source resource instances */ + lwm2m_create_res_inst(&LWM2M_OBJ(3, 0, 6, 0)); + lwm2m_set_res_buf(&LWM2M_OBJ(3, 0, 6, 0), &bat_idx, sizeof(bat_idx), sizeof(bat_idx), 0); + lwm2m_create_res_inst(&LWM2M_OBJ(3, 0, 7, 0)); + lwm2m_set_res_buf(&LWM2M_OBJ(3, 0, 7, 0), &bat_mv, sizeof(bat_mv), sizeof(bat_mv), 0); + lwm2m_create_res_inst(&LWM2M_OBJ(3, 0, 8, 0)); + lwm2m_set_res_buf(&LWM2M_OBJ(3, 0, 8, 0), &bat_ma, sizeof(bat_ma), sizeof(bat_ma), 0); + lwm2m_create_res_inst(&LWM2M_OBJ(3, 0, 6, 1)); + lwm2m_set_res_buf(&LWM2M_OBJ(3, 0, 6, 1), &usb_idx, sizeof(usb_idx), sizeof(usb_idx), 0); + lwm2m_create_res_inst(&LWM2M_OBJ(3, 0, 7, 1)); + lwm2m_set_res_buf(&LWM2M_OBJ(3, 0, 7, 1), &usb_mv, sizeof(usb_mv), sizeof(usb_mv), 0); + lwm2m_create_res_inst(&LWM2M_OBJ(3, 0, 8, 1)); + lwm2m_set_res_buf(&LWM2M_OBJ(3, 0, 8, 1), &usb_ma, sizeof(usb_ma), sizeof(usb_ma), 0); + return 0; } @@ -166,6 +220,7 @@ int main(void) } client.tls_tag = 1; + client.set_socketoptions = set_socketoptions; lwm2m_rd_client_start(&client, CONFIG_BOARD, 0, rd_client_event, observe_cb); lwm2m_rd_client_stop(&client, rd_client_event, false); diff --git a/tests/net/lib/lwm2m/interop/testcase.yaml b/tests/net/lib/lwm2m/interop/testcase.yaml index aeba64748df..06390472269 100644 --- a/tests/net/lib/lwm2m/interop/testcase.yaml +++ b/tests/net/lib/lwm2m/interop/testcase.yaml @@ -1,13 +1,17 @@ tests: net.lwm2m.interop: harness: pytest - timeout: 300 + timeout: 600 slow: true + harness_config: + pytest_dut_scope: module + pytest_args: [] integration_platforms: - - native_posix + - native_sim platform_allow: - - native_posix + - native_sim - qemu_cortex_m3 + - qemu_x86 tags: - testing - pytest diff --git a/tests/net/lib/lwm2m/lwm2m_engine/boards/native_posix.conf b/tests/net/lib/lwm2m/lwm2m_engine/boards/native_posix.conf deleted file mode 100644 index eb56d825c96..00000000000 --- a/tests/net/lib/lwm2m/lwm2m_engine/boards/native_posix.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_NATIVE_POSIX_SLOWDOWN_TO_REAL_TIME=y diff --git a/tests/net/lib/lwm2m/lwm2m_engine/boards/native_sim.conf b/tests/net/lib/lwm2m/lwm2m_engine/boards/native_sim.conf new file mode 100644 index 00000000000..0843e94acbd --- /dev/null +++ b/tests/net/lib/lwm2m/lwm2m_engine/boards/native_sim.conf @@ -0,0 +1 @@ +CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME=y diff --git a/tests/net/lib/lwm2m/lwm2m_engine/prj.conf b/tests/net/lib/lwm2m/lwm2m_engine/prj.conf index e051abf4191..775cea846a1 100644 --- a/tests/net/lib/lwm2m/lwm2m_engine/prj.conf +++ b/tests/net/lib/lwm2m/lwm2m_engine/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=4096 CONFIG_MP_MAX_NUM_CPUS=1 diff --git a/tests/net/lib/lwm2m/lwm2m_engine/src/main.c b/tests/net/lib/lwm2m/lwm2m_engine/src/main.c index bd1d21983dd..ed26380eccd 100644 --- a/tests/net/lib/lwm2m/lwm2m_engine/src/main.c +++ b/tests/net/lib/lwm2m/lwm2m_engine/src/main.c @@ -238,7 +238,7 @@ ZTEST(lwm2m_engine, test_check_notifications) obs.last_timestamp = k_uptime_get(); obs.event_timestamp = k_uptime_get() + 1000U; obs.resource_update = false; - obs.active_tx_operation = false; + obs.active_notify = NULL; sys_slist_append(&ctx.observer, &obs.node); diff --git a/tests/net/lib/lwm2m/lwm2m_engine/testcase.yaml b/tests/net/lib/lwm2m/lwm2m_engine/testcase.yaml index a7f628405eb..2f765ac0dc1 100644 --- a/tests/net/lib/lwm2m/lwm2m_engine/testcase.yaml +++ b/tests/net/lib/lwm2m/lwm2m_engine/testcase.yaml @@ -6,4 +6,4 @@ tests: - lwm2m - net integration_platforms: - - native_posix + - native_sim diff --git a/tests/net/lib/lwm2m/lwm2m_rd_client/boards/native_posix.conf b/tests/net/lib/lwm2m/lwm2m_rd_client/boards/native_posix.conf deleted file mode 100644 index eb56d825c96..00000000000 --- a/tests/net/lib/lwm2m/lwm2m_rd_client/boards/native_posix.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_NATIVE_POSIX_SLOWDOWN_TO_REAL_TIME=y diff --git a/tests/net/lib/lwm2m/lwm2m_rd_client/boards/native_sim.conf b/tests/net/lib/lwm2m/lwm2m_rd_client/boards/native_sim.conf new file mode 100644 index 00000000000..0843e94acbd --- /dev/null +++ b/tests/net/lib/lwm2m/lwm2m_rd_client/boards/native_sim.conf @@ -0,0 +1 @@ +CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME=y diff --git a/tests/net/lib/lwm2m/lwm2m_rd_client/prj.conf b/tests/net/lib/lwm2m/lwm2m_rd_client/prj.conf index e051abf4191..775cea846a1 100644 --- a/tests/net/lib/lwm2m/lwm2m_rd_client/prj.conf +++ b/tests/net/lib/lwm2m/lwm2m_rd_client/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=4096 CONFIG_MP_MAX_NUM_CPUS=1 diff --git a/tests/net/lib/lwm2m/lwm2m_rd_client/src/main.c b/tests/net/lib/lwm2m/lwm2m_rd_client/src/main.c index 03d0dce7f49..931f6f15904 100644 --- a/tests/net/lib/lwm2m/lwm2m_rd_client/src/main.c +++ b/tests/net/lib/lwm2m/lwm2m_rd_client/src/main.c @@ -9,8 +9,8 @@ #include #include #include -#if defined(CONFIG_NATIVE_POSIX_SLOWDOWN_TO_REAL_TIME) -#include "timer_model.h" +#if defined(CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME) +#include "nsi_timer_model.h" #endif #include @@ -141,7 +141,7 @@ static void lwm2m_observe_cb(enum lwm2m_observe_event event, struct lwm2m_obj_pa static void my_suite_before(void *data) { -#if defined(CONFIG_NATIVE_POSIX_SLOWDOWN_TO_REAL_TIME) +#if defined(CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME) /* It is enough that some slow-down is happening on sleeps, it does not have to be * real time */ diff --git a/tests/net/lib/lwm2m/lwm2m_rd_client/testcase.yaml b/tests/net/lib/lwm2m/lwm2m_rd_client/testcase.yaml index 80c5bee1131..df49b3c7342 100644 --- a/tests/net/lib/lwm2m/lwm2m_rd_client/testcase.yaml +++ b/tests/net/lib/lwm2m/lwm2m_rd_client/testcase.yaml @@ -5,7 +5,7 @@ common: - lwm2m - net platform_allow: - - native_posix + - native_sim tests: net.lwm2m.lwm2m_rd_client: extra_args: EXTRA_CFLAGS="" diff --git a/tests/net/lib/lwm2m/lwm2m_registry/prj.conf b/tests/net/lib/lwm2m/lwm2m_registry/prj.conf index 4d5e497fe8d..223f97a0762 100644 --- a/tests/net/lib/lwm2m/lwm2m_registry/prj.conf +++ b/tests/net/lib/lwm2m/lwm2m_registry/prj.conf @@ -1,7 +1,6 @@ CONFIG_NETWORKING=y CONFIG_NET_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y @@ -14,3 +13,4 @@ CONFIG_LWM2M_IPSO_TEMP_SENSOR_VERSION_1_1=y CONFIG_LWM2M_IPSO_TEMP_SENSOR_INSTANCE_COUNT=4 CONFIG_LWM2M_CONN_MON_OBJ_SUPPORT=y CONFIG_LWM2M_CONNMON_OBJECT_VERSION_1_2=y +CONFIG_LWM2M_PORTFOLIO_OBJ_SUPPORT=y diff --git a/tests/net/lib/lwm2m/lwm2m_registry/src/lwm2m_registry.c b/tests/net/lib/lwm2m/lwm2m_registry/src/lwm2m_registry.c index d847b5a35cd..d4c0a7757a6 100644 --- a/tests/net/lib/lwm2m/lwm2m_registry/src/lwm2m_registry.c +++ b/tests/net/lib/lwm2m/lwm2m_registry/src/lwm2m_registry.c @@ -285,6 +285,42 @@ ZTEST(lwm2m_registry, test_resource_instance_creation_and_deletion) zassert_equal(ret, 0); } +ZTEST(lwm2m_registry, test_resource_instance_strings) +{ + int ret; + char buf[256] = {0}; + static const char string_a[] = "Hello"; + static const char string_b[] = "World"; + struct lwm2m_obj_path path_a = LWM2M_OBJ(16, 0, 0, 0); + struct lwm2m_obj_path path_b = LWM2M_OBJ(16, 0, 0, 1); + + ret = lwm2m_create_object_inst(&LWM2M_OBJ(16, 0)); + zassert_equal(ret, 0); + + ret = lwm2m_create_res_inst(&path_a); + zassert_equal(ret, 0); + + ret = lwm2m_create_res_inst(&path_b); + zassert_equal(ret, 0); + + ret = lwm2m_set_string(&path_a, string_a); + zassert_equal(ret, 0); + + ret = lwm2m_set_string(&path_b, string_b); + zassert_equal(ret, 0); + + ret = lwm2m_get_string(&path_a, buf, sizeof(buf)); + zassert_equal(ret, 0); + zassert_equal(0, memcmp(buf, string_a, sizeof(string_a))); + + ret = lwm2m_get_string(&path_b, buf, sizeof(buf)); + zassert_equal(ret, 0); + zassert_equal(0, memcmp(buf, string_b, sizeof(string_b))); + + ret = lwm2m_delete_object_inst(&LWM2M_OBJ(16, 0)); + zassert_equal(ret, 0); +} + ZTEST(lwm2m_registry, test_callbacks) { int ret; diff --git a/tests/net/lib/lwm2m/lwm2m_registry/testcase.yaml b/tests/net/lib/lwm2m/lwm2m_registry/testcase.yaml index ca0f06f58b5..a994dd72ad8 100644 --- a/tests/net/lib/lwm2m/lwm2m_registry/testcase.yaml +++ b/tests/net/lib/lwm2m/lwm2m_registry/testcase.yaml @@ -6,4 +6,4 @@ tests: - lwm2m - net integration_platforms: - - native_posix + - native_sim diff --git a/tests/net/lib/mqtt_packet/prj.conf b/tests/net/lib/mqtt_packet/prj.conf index 883a38d2d9b..1c4a907a155 100644 --- a/tests/net/lib/mqtt_packet/prj.conf +++ b/tests/net/lib/mqtt_packet/prj.conf @@ -9,6 +9,5 @@ CONFIG_TEST_RANDOM_GENERATOR=y # enable the MQTT lib CONFIG_MQTT_LIB=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y CONFIG_MAIN_STACK_SIZE=1280 diff --git a/tests/net/lib/mqtt_publisher/prj.conf b/tests/net/lib/mqtt_publisher/prj.conf index 32ad6f7cfd8..c9342459893 100644 --- a/tests/net/lib/mqtt_publisher/prj.conf +++ b/tests/net/lib/mqtt_publisher/prj.conf @@ -32,4 +32,3 @@ CONFIG_MAIN_STACK_SIZE=2048 CONFIG_NET_BUF_DATA_SIZE=256 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/net/lib/mqtt_publisher/prj_tls.conf b/tests/net/lib/mqtt_publisher/prj_tls.conf index 9e575d1bc07..2cae0098472 100644 --- a/tests/net/lib/mqtt_publisher/prj_tls.conf +++ b/tests/net/lib/mqtt_publisher/prj_tls.conf @@ -48,4 +48,3 @@ CONFIG_MBEDTLS_HEAP_SIZE=30000 # for tls_entropy_func CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/net/lib/mqtt_publisher/src/test_mqtt_publish.c b/tests/net/lib/mqtt_publisher/src/test_mqtt_publish.c index 8e0a98c5feb..32dda35a78c 100644 --- a/tests/net/lib/mqtt_publisher/src/test_mqtt_publish.c +++ b/tests/net/lib/mqtt_publisher/src/test_mqtt_publish.c @@ -14,7 +14,7 @@ LOG_MODULE_REGISTER(net_test, LOG_LEVEL_WRN); #include #include -#include +#include #include "config.h" diff --git a/tests/net/lib/mqtt_pubsub/prj.conf b/tests/net/lib/mqtt_pubsub/prj.conf index 26ff5f835ac..368a9c283dd 100644 --- a/tests/net/lib/mqtt_pubsub/prj.conf +++ b/tests/net/lib/mqtt_pubsub/prj.conf @@ -32,4 +32,3 @@ CONFIG_MAIN_STACK_SIZE=2048 CONFIG_NET_BUF_DATA_SIZE=256 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/net/lib/mqtt_pubsub/src/test_mqtt_pubsub.c b/tests/net/lib/mqtt_pubsub/src/test_mqtt_pubsub.c index 8887ef01ba4..606ab78a0ba 100644 --- a/tests/net/lib/mqtt_pubsub/src/test_mqtt_pubsub.c +++ b/tests/net/lib/mqtt_pubsub/src/test_mqtt_pubsub.c @@ -10,7 +10,7 @@ LOG_MODULE_REGISTER(net_test, LOG_LEVEL_WRN); #include #include #include -#include +#include #include #include diff --git a/tests/net/lib/mqtt_sn_client/prj.conf b/tests/net/lib/mqtt_sn_client/prj.conf index 8ddc1c24880..636d6248748 100644 --- a/tests/net/lib/mqtt_sn_client/prj.conf +++ b/tests/net/lib/mqtt_sn_client/prj.conf @@ -6,7 +6,6 @@ CONFIG_NET_TEST=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y -CONFIG_LOG_DEFAULT_LEVEL=4 CONFIG_NET_LOG=y CONFIG_MQTT_SN_LOG_LEVEL_DBG=y @@ -19,4 +18,3 @@ CONFIG_ZTEST_STACK_SIZE=8192 CONFIG_STACK_USAGE=y CONFIG_STACK_SENTINEL=y CONFIG_DEBUG=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/net/lib/mqtt_sn_packet/prj.conf b/tests/net/lib/mqtt_sn_packet/prj.conf index 6fa328dcd0e..afb67dc24da 100644 --- a/tests/net/lib/mqtt_sn_packet/prj.conf +++ b/tests/net/lib/mqtt_sn_packet/prj.conf @@ -6,7 +6,6 @@ CONFIG_NET_TEST=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y -CONFIG_LOG_DEFAULT_LEVEL=4 CONFIG_NET_LOG=y CONFIG_MQTT_SN_LOG_LEVEL_DBG=y CONFIG_NET_BUF_LOG_LEVEL_DBG=y @@ -15,4 +14,3 @@ CONFIG_NET_BUF_LOG_LEVEL_DBG=y CONFIG_MQTT_SN_LIB=y CONFIG_ZTEST=y CONFIG_MAIN_STACK_SIZE=1280 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/net/lib/mqtt_subscriber/prj.conf b/tests/net/lib/mqtt_subscriber/prj.conf index 26ff5f835ac..368a9c283dd 100644 --- a/tests/net/lib/mqtt_subscriber/prj.conf +++ b/tests/net/lib/mqtt_subscriber/prj.conf @@ -32,4 +32,3 @@ CONFIG_MAIN_STACK_SIZE=2048 CONFIG_NET_BUF_DATA_SIZE=256 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/net/lib/mqtt_subscriber/src/test_mqtt_subscribe.c b/tests/net/lib/mqtt_subscriber/src/test_mqtt_subscribe.c index 974c4e153fb..ad09e8ecd96 100644 --- a/tests/net/lib/mqtt_subscriber/src/test_mqtt_subscribe.c +++ b/tests/net/lib/mqtt_subscriber/src/test_mqtt_subscribe.c @@ -10,7 +10,7 @@ LOG_MODULE_REGISTER(net_test, LOG_LEVEL_WRN); #include #include #include -#include +#include #include #include diff --git a/tests/net/lib/tls_credentials/prj.conf b/tests/net/lib/tls_credentials/prj.conf index c173e530849..91424b1715d 100644 --- a/tests/net/lib/tls_credentials/prj.conf +++ b/tests/net/lib/tls_credentials/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NET_TEST=y CONFIG_NETWORKING=y CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/net/mgmt/prj.conf b/tests/net/mgmt/prj.conf index 90ecd17868c..3d41dd4d851 100644 --- a/tests/net/mgmt/prj.conf +++ b/tests/net/mgmt/prj.conf @@ -18,4 +18,3 @@ CONFIG_NET_IPV6=y CONFIG_NET_L2_DUMMY=y CONFIG_NET_L2_ETHERNET=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/net/mgmt/src/mgmt.c b/tests/net/mgmt/src/mgmt.c index 23edc1a6a69..52be33eb3dc 100644 --- a/tests/net/mgmt/src/mgmt.c +++ b/tests/net/mgmt/src/mgmt.c @@ -105,8 +105,12 @@ void test_requesting_nm(void) "Requesting Net MGMT failed"); } -static void thrower_thread(void) +static void thrower_thread(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + while (1) { k_sem_take(&thrower_lock, K_FOREVER); @@ -253,7 +257,7 @@ static void initialize_event_tests(void) k_thread_create(&thrower_thread_data, thrower_stack, K_THREAD_STACK_SIZEOF(thrower_stack), - (k_thread_entry_t)thrower_thread, + thrower_thread, NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); } diff --git a/tests/net/mld/prj.conf b/tests/net/mld/prj.conf index 59d326f15cd..5eeab7f81ec 100644 --- a/tests/net/mld/prj.conf +++ b/tests/net/mld/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MAIN_STACK_SIZE=2048 CONFIG_NET_TEST=y CONFIG_NETWORKING=y diff --git a/tests/net/mld/src/main.c b/tests/net/mld/src/main.c index 513fc3107c3..d374b207cbd 100644 --- a/tests/net/mld/src/main.c +++ b/tests/net/mld/src/main.c @@ -27,7 +27,7 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_IPV6_LOG_LEVEL); #include #include -#include +#include #include "icmpv6.h" #include "ipv6.h" @@ -429,10 +429,18 @@ static void leave_mldv2_capable_routers_group(void) } /* We are not really interested to parse the query at this point */ -static enum net_verdict handle_mld_query(struct net_pkt *pkt, - struct net_ipv6_hdr *ip_hdr, - struct net_icmp_hdr *icmp_hdr) +static int handle_mld_query(struct net_icmp_ctx *ctx, + struct net_pkt *pkt, + struct net_icmp_ip_hdr *hdr, + struct net_icmp_hdr *icmp_hdr, + void *user_data) { + ARG_UNUSED(ctx); + ARG_UNUSED(pkt); + ARG_UNUSED(hdr); + ARG_UNUSED(icmp_hdr); + ARG_UNUSED(user_data); + is_query_received = true; NET_DBG("Handling MLD query"); @@ -440,19 +448,19 @@ static enum net_verdict handle_mld_query(struct net_pkt *pkt, return NET_DROP; } -static struct net_icmpv6_handler mld_query_input_handler = { - .type = NET_ICMPV6_MLD_QUERY, - .code = 0, - .handler = handle_mld_query, -}; - static void test_catch_query(void) { + struct net_icmp_ctx ctx; + int ret; + join_mldv2_capable_routers_group(); is_query_received = false; - net_icmpv6_register_handler(&mld_query_input_handler); + ret = net_icmp_init_ctx(&ctx, NET_ICMPV6_MLD_QUERY, + 0, handle_mld_query); + zassert_equal(ret, 0, "Cannot register %s handler (%d)", + STRINGIFY(NET_ICMPV6_MLD_QUERY), ret); send_query(net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY))); @@ -468,9 +476,9 @@ static void test_catch_query(void) is_query_received = false; - net_icmpv6_unregister_handler(&mld_query_input_handler); - leave_mldv2_capable_routers_group(); + + net_icmp_cleanup_ctx(&ctx); } static void test_verify_send_report(void) diff --git a/tests/net/neighbor/prj.conf b/tests/net/neighbor/prj.conf index ff1299a29f3..0116a6e1011 100644 --- a/tests/net/neighbor/prj.conf +++ b/tests/net/neighbor/prj.conf @@ -14,5 +14,4 @@ CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=3 CONFIG_NET_IPV6_MAX_NEIGHBORS=4 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NET_L2_ETHERNET=n diff --git a/tests/net/net_pkt/prj.conf b/tests/net/net_pkt/prj.conf index 15d778a4ef7..b1902d33c71 100644 --- a/tests/net/net_pkt/prj.conf +++ b/tests/net/net_pkt/prj.conf @@ -1,6 +1,5 @@ CONFIG_NET_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NETWORKING=y CONFIG_NET_L2_ETHERNET=y CONFIG_NET_IPV4=y @@ -12,3 +11,4 @@ CONFIG_NET_LOG=y CONFIG_NET_BUF_POOL_USAGE=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_NET_ETHERNET_BRIDGE=y diff --git a/tests/net/net_pkt/src/main.c b/tests/net/net_pkt/src/main.c index f9bc52e3638..29f5ba1080a 100644 --- a/tests/net/net_pkt/src/main.c +++ b/tests/net/net_pkt/src/main.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include @@ -814,6 +814,16 @@ ZTEST(net_pkt_test_suite, test_net_pkt_clone) net_pkt_lladdr_dst(pkt)->type = NET_LINK_ETHERNET; zassert_mem_equal(net_pkt_lladdr_dst(pkt)->addr, &buf[6], NET_LINK_ADDR_MAX_LENGTH); + net_pkt_set_family(pkt, AF_INET6); + net_pkt_set_captured(pkt, true); + net_pkt_set_eof(pkt, true); + net_pkt_set_ptp(pkt, true); + net_pkt_set_forwarding(pkt, true); + + net_pkt_set_l2_bridged(pkt, true); + net_pkt_set_l2_processed(pkt, true); + net_pkt_set_ll_proto_type(pkt, ETH_P_IEEE802154); + net_pkt_set_overwrite(pkt, false); cloned_pkt = net_pkt_clone(pkt, K_NO_WAIT); zassert_true(cloned_pkt != NULL, "Pkt not cloned"); @@ -833,6 +843,27 @@ ZTEST(net_pkt_test_suite, test_net_pkt_clone) zassert_false(net_pkt_is_being_overwritten(pkt), "Pkt overwrite flag not restored"); + zassert_equal(net_pkt_family(cloned_pkt), AF_INET6, + "Address family value mismatch"); + + zassert_true(net_pkt_is_captured(cloned_pkt), + "Cloned pkt captured flag mismatch"); + + zassert_true(net_pkt_eof(cloned_pkt), + "Cloned pkt eof flag mismatch"); + + zassert_true(net_pkt_is_ptp(cloned_pkt), + "Cloned pkt ptp_pkt flag mismatch"); + + zassert_true(net_pkt_forwarding(cloned_pkt), + "Cloned pkt forwarding flag mismatch"); + + zassert_true(net_pkt_is_l2_bridged(cloned_pkt), + "Cloned pkt l2_bridged flag mismatch"); + + zassert_true(net_pkt_is_l2_processed(cloned_pkt), + "Cloned pkt l2_processed flag mismatch"); + zassert_mem_equal(net_pkt_lladdr_src(cloned_pkt)->addr, buf, NET_LINK_ADDR_MAX_LENGTH); zassert_true(net_pkt_lladdr_src(cloned_pkt)->addr == cloned_pkt->buffer->data, "Cloned pkt ll src addr mismatch"); @@ -841,6 +872,9 @@ ZTEST(net_pkt_test_suite, test_net_pkt_clone) zassert_true(net_pkt_lladdr_dst(cloned_pkt)->addr == net_pkt_cursor_get_pos(cloned_pkt), "Cloned pkt ll dst addr mismatch"); + zassert_equal(net_pkt_ll_proto_type(cloned_pkt), ETH_P_IEEE802154, + "Address ll_proto_type value mismatch"); + net_pkt_unref(pkt); net_pkt_unref(cloned_pkt); } diff --git a/tests/net/npf/prj.conf b/tests/net/npf/prj.conf index 57d62213090..a5b746ea3dc 100644 --- a/tests/net/npf/prj.conf +++ b/tests/net/npf/prj.conf @@ -10,7 +10,6 @@ CONFIG_NET_PKT_RX_COUNT=20 CONFIG_NET_BUF_RX_COUNT=20 CONFIG_NET_BUF_TX_COUNT=20 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_COMPILER_COLOR_DIAGNOSTICS=n CONFIG_NET_IPV4=y CONFIG_NET_PKT_FILTER_IPV4_HOOK=y diff --git a/tests/net/offloaded_netdev/prj.conf b/tests/net/offloaded_netdev/prj.conf index 8bdc82930bb..ad92b9bec28 100644 --- a/tests/net/offloaded_netdev/prj.conf +++ b/tests/net/offloaded_netdev/prj.conf @@ -4,7 +4,6 @@ CONFIG_NET_SOCKETS=y CONFIG_NET_SOCKETS_OFFLOAD=y CONFIG_NET_LOG=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y CONFIG_NET_OFFLOAD=y CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/net/pm/prj.conf b/tests/net/pm/prj.conf index e7dae2dd227..5650693d56c 100644 --- a/tests/net/pm/prj.conf +++ b/tests/net/pm/prj.conf @@ -16,4 +16,3 @@ CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=2 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/net/pm/src/main.c b/tests/net/pm/src/main.c index 5831bdf28e5..4aa7bffff7d 100644 --- a/tests/net/pm/src/main.c +++ b/tests/net/pm/src/main.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include diff --git a/tests/net/ppp/driver/prj.conf b/tests/net/ppp/driver/prj.conf index 02f619cf24f..25ceb368947 100644 --- a/tests/net/ppp/driver/prj.conf +++ b/tests/net/ppp/driver/prj.conf @@ -23,6 +23,5 @@ CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6 CONFIG_NET_IPV6_ND=n CONFIG_NET_CONFIG_AUTO_INIT=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y #CONFIG_NET_PPP_LOG_LEVEL_DBG=y CONFIG_CRC=y diff --git a/tests/net/promiscuous/prj.conf b/tests/net/promiscuous/prj.conf index 3c210710af5..5f56de6e98e 100644 --- a/tests/net/promiscuous/prj.conf +++ b/tests/net/promiscuous/prj.conf @@ -22,4 +22,3 @@ CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6 CONFIG_NET_IPV6_MAX_NEIGHBORS=1 CONFIG_NET_IPV6_ND=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/net/promiscuous/src/main.c b/tests/net/promiscuous/src/main.c index 0b6e6a47957..9bedd9773b9 100644 --- a/tests/net/promiscuous/src/main.c +++ b/tests/net/promiscuous/src/main.c @@ -352,6 +352,8 @@ static void _recv_data(struct net_if *iface, struct net_pkt **pkt) *pkt = net_pkt_rx_alloc_with_buffer(iface, sizeof(data), AF_UNSPEC, 0, K_FOREVER); + net_pkt_ref(*pkt); + net_pkt_write(*pkt, data, sizeof(data)); ret = net_recv_data(iface, *pkt); @@ -372,11 +374,25 @@ static void test_verify_data(void) struct net_pkt *pkt; pkt = net_promisc_mode_wait_data(K_SECONDS(1)); - zassert_equal_ptr(pkt, pkt1, "pkt %p != %p", pkt, pkt1); + zassert_not_null(pkt, "pkt"); + zassert_not_null(pkt->buffer, "pkt->buffer"); + zassert_not_null(pkt1, "pkt1"); + zassert_not_null(pkt1->buffer, "pkt1->buffer"); + zassert_equal(pkt->buffer->len, pkt1->buffer->len, "packet length differs"); + zassert_not_null(pkt->buffer->data, "pkt->buffer->data"); + zassert_not_null(pkt1->buffer->data, "pkt1->buffer->data"); + zassert_mem_equal(pkt->buffer->data, pkt1->buffer->data, pkt1->buffer->len); net_pkt_unref(pkt); pkt = net_promisc_mode_wait_data(K_SECONDS(1)); - zassert_equal_ptr(pkt, pkt2, "pkt %p != %p", pkt, pkt2); + zassert_not_null(pkt, "pkt"); + zassert_not_null(pkt->buffer, "pkt->buffer"); + zassert_not_null(pkt2, "pkt2"); + zassert_not_null(pkt2->buffer, "pkt2->buffer"); + zassert_equal(pkt->buffer->len, pkt2->buffer->len, "packet length differs"); + zassert_not_null(pkt->buffer->data, "pkt->buffer->data"); + zassert_not_null(pkt2->buffer->data, "pkt2->buffer->data"); + zassert_mem_equal(pkt->buffer->data, pkt2->buffer->data, pkt2->buffer->len); net_pkt_unref(pkt); } diff --git a/tests/net/ptp/clock/prj.conf b/tests/net/ptp/clock/prj.conf index 1cfee2add56..71efa260d7c 100644 --- a/tests/net/ptp/clock/prj.conf +++ b/tests/net/ptp/clock/prj.conf @@ -19,7 +19,6 @@ CONFIG_NET_IF_MAX_IPV6_COUNT=6 CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6 CONFIG_NET_IPV6_ND=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NET_CONFIG_SETTINGS=n CONFIG_NET_SHELL=n CONFIG_PTP_CLOCK=y diff --git a/tests/net/ptp/clock/src/main.c b/tests/net/ptp/clock/src/main.c index 34cb6e19f3c..a00f3e0c540 100644 --- a/tests/net/ptp/clock/src/main.c +++ b/tests/net/ptp/clock/src/main.c @@ -31,7 +31,7 @@ LOG_MODULE_REGISTER(net_test, NET_LOG_LEVEL); #include #include -#include +#include #define NET_LOG_ENABLED 1 #include "net_private.h" diff --git a/tests/net/ptp/clock/testcase.yaml b/tests/net/ptp/clock/testcase.yaml index d37134a9301..1d724695337 100644 --- a/tests/net/ptp/clock/testcase.yaml +++ b/tests/net/ptp/clock/testcase.yaml @@ -5,8 +5,9 @@ common: - frdm_k64f - sam_e70_xplained - native_posix + - native_sim integration_platforms: - - native_posix + - native_sim tests: net.ptp.clock: min_ram: 32 diff --git a/tests/net/route/prj.conf b/tests/net/route/prj.conf index 05a1ad8c84b..0ce002a9f65 100644 --- a/tests/net/route/prj.conf +++ b/tests/net/route/prj.conf @@ -21,4 +21,3 @@ CONFIG_NET_MAX_ROUTES=4 CONFIG_NET_MAX_NEXTHOPS=8 CONFIG_NET_IPV6_MAX_NEIGHBORS=8 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/net/route/src/main.c b/tests/net/route/src/main.c index da0c8d64d5b..1a48dd2ebc3 100644 --- a/tests/net/route/src/main.c +++ b/tests/net/route/src/main.c @@ -17,7 +17,7 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_ROUTE_LOG_LEVEL); #include #include #include -#include +#include #include diff --git a/tests/net/route_mcast/prj.conf b/tests/net/route_mcast/prj.conf index 3c0eb6107d6..c655d805cdb 100644 --- a/tests/net/route_mcast/prj.conf +++ b/tests/net/route_mcast/prj.conf @@ -21,6 +21,5 @@ CONFIG_NET_MAX_ROUTES=4 CONFIG_NET_MAX_NEXTHOPS=8 CONFIG_NET_IPV6_MAX_NEIGHBORS=8 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NET_MAX_MCAST_ROUTES=10 CONFIG_NET_ROUTE_MCAST=y diff --git a/tests/net/route_mcast/src/main.c b/tests/net/route_mcast/src/main.c index cb10b830fa9..3db8a05fc0b 100644 --- a/tests/net/route_mcast/src/main.c +++ b/tests/net/route_mcast/src/main.c @@ -17,7 +17,7 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_ROUTE_LOG_LEVEL); #include #include #include -#include +#include #include diff --git a/tests/net/shell/prj.conf b/tests/net/shell/prj.conf index 082cee7758d..f6aef9e72c2 100644 --- a/tests/net/shell/prj.conf +++ b/tests/net/shell/prj.conf @@ -17,7 +17,6 @@ CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=2 CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=2 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NET_SHELL=y CONFIG_LOG_PRINTK=n CONFIG_SHELL_BACKEND_DUMMY=y diff --git a/tests/net/shell/src/main.c b/tests/net/shell/src/main.c index 86d3ba1b45a..528958698f8 100644 --- a/tests/net/shell/src/main.c +++ b/tests/net/shell/src/main.c @@ -29,7 +29,7 @@ LOG_MODULE_REGISTER(net_test, NET_LOG_LEVEL); #include #include #include -#include +#include #include "ipv4.h" #include "ipv6.h" diff --git a/tests/net/socket/af_packet/prj.conf b/tests/net/socket/af_packet/prj.conf index 8636ac9c5cf..c73bd698d18 100644 --- a/tests/net/socket/af_packet/prj.conf +++ b/tests/net/socket/af_packet/prj.conf @@ -17,7 +17,6 @@ CONFIG_ETH_DRIVER=n CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NET_TEST=y CONFIG_NET_LOG=y CONFIG_TEST_USERSPACE=y diff --git a/tests/net/socket/af_packet_ipproto_raw/prj.conf b/tests/net/socket/af_packet_ipproto_raw/prj.conf index bd6399ab152..57c66491ea1 100644 --- a/tests/net/socket/af_packet_ipproto_raw/prj.conf +++ b/tests/net/socket/af_packet_ipproto_raw/prj.conf @@ -19,7 +19,6 @@ CONFIG_NET_L2_DUMMY=y CONFIG_NET_IF_MAX_IPV4_COUNT=4 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NET_TEST=y CONFIG_NET_LOG=y CONFIG_TEST_USERSPACE=y diff --git a/tests/net/socket/af_packet_ipproto_raw/src/main.c b/tests/net/socket/af_packet_ipproto_raw/src/main.c index 840a1be25d4..95852262df7 100644 --- a/tests/net/socket/af_packet_ipproto_raw/src/main.c +++ b/tests/net/socket/af_packet_ipproto_raw/src/main.c @@ -10,7 +10,7 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_SOCKETS_LOG_LEVEL); #include #include #include -#include +#include #include diff --git a/tests/net/socket/can/prj.conf b/tests/net/socket/can/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/net/socket/can/prj.conf +++ b/tests/net/socket/can/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/net/socket/can/src/main.c b/tests/net/socket/can/src/main.c index d4021fbf170..02d209c022e 100644 --- a/tests/net/socket/can/src/main.c +++ b/tests/net/socket/can/src/main.c @@ -23,13 +23,14 @@ ZTEST(socket_can, test_socketcan_frame_to_can_frame) const uint8_t data[SOCKETCAN_MAX_DLEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; - sframe.can_id = BIT(31) | BIT(30) | 1234; + sframe.can_id = BIT(31) | 1234; sframe.len = sizeof(data); memcpy(sframe.data, data, sizeof(sframe.data)); - expected.flags = CAN_FRAME_IDE | CAN_FRAME_RTR; + expected.flags = CAN_FRAME_IDE; expected.id = 1234U; - expected.dlc = sizeof(data); + expected.dlc = can_bytes_to_dlc(sizeof(data)); + memcpy(expected.data, data, sizeof(data)); socketcan_to_can_frame(&sframe, &zframe); @@ -40,6 +41,17 @@ ZTEST(socket_can, test_socketcan_frame_to_can_frame) zassert_equal(zframe.flags, expected.flags, "Flags not equal"); zassert_equal(zframe.id, expected.id, "CAN id invalid"); zassert_equal(zframe.dlc, expected.dlc, "Msg length invalid"); + zassert_mem_equal(&zframe.data, &expected.data, can_dlc_to_bytes(expected.dlc), + "CAN data not same"); + + /* Test RTR flag conversion after comparing data payload */ + sframe.can_id |= BIT(30); + expected.flags |= CAN_FRAME_RTR; + + socketcan_to_can_frame(&sframe, &zframe); + + zassert_equal(zframe.flags, expected.flags, "Flags not equal"); + zassert_equal(zframe.id, expected.id, "CAN id invalid"); } /** @@ -53,13 +65,13 @@ ZTEST(socket_can, test_can_frame_to_socketcan_frame) const uint8_t data[SOCKETCAN_MAX_DLEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; - expected.can_id = BIT(31) | BIT(30) | 1234; + expected.can_id = BIT(31) | 1234; expected.len = sizeof(data); memcpy(expected.data, data, sizeof(expected.data)); - zframe.flags = CAN_FRAME_IDE | CAN_FRAME_RTR; + zframe.flags = CAN_FRAME_IDE; zframe.id = 1234U; - zframe.dlc = sizeof(data); + zframe.dlc = can_bytes_to_dlc(sizeof(data)); memcpy(zframe.data, data, sizeof(data)); socketcan_from_can_frame(&zframe, &sframe); @@ -69,10 +81,15 @@ ZTEST(socket_can, test_can_frame_to_socketcan_frame) LOG_HEXDUMP_DBG((const uint8_t *)&expected, sizeof(expected), "expected"); zassert_equal(sframe.can_id, expected.can_id, "CAN ID not same"); - zassert_mem_equal(&sframe.data, &expected.data, sizeof(sframe.data), - "CAN data not same"); - zassert_equal(sframe.len, expected.len, - "CAN msg length not same"); + zassert_equal(sframe.len, expected.len, "CAN msg length not same"); + zassert_mem_equal(&sframe.data, &expected.data, sizeof(sframe.data), "CAN data not same"); + + /* Test RTR flag conversion after comparing data payload */ + expected.can_id |= BIT(30); + zframe.flags |= CAN_FRAME_RTR; + + socketcan_from_can_frame(&zframe, &sframe); + zassert_equal(sframe.can_id, expected.can_id, "CAN ID not same"); } /** diff --git a/tests/net/socket/can/testcase.yaml b/tests/net/socket/can/testcase.yaml index 251c541c0c2..6d5a2a495da 100644 --- a/tests/net/socket/can/testcase.yaml +++ b/tests/net/socket/can/testcase.yaml @@ -1,8 +1,8 @@ tests: net.socket.can: integration_platforms: - - native_posix - - native_posix_64 + - native_sim + - native_sim_64 tags: - net - can diff --git a/tests/net/socket/getaddrinfo/prj.conf b/tests/net/socket/getaddrinfo/prj.conf index f42658a1d92..e0430061b1e 100644 --- a/tests/net/socket/getaddrinfo/prj.conf +++ b/tests/net/socket/getaddrinfo/prj.conf @@ -1,6 +1,5 @@ # General config -CONFIG_NEWLIB_LIBC=y -CONFIG_NEWLIB_LIBC_NANO=y +CONFIG_REQUIRES_FULL_LIBC=y # Networking config CONFIG_NETWORKING=y @@ -26,12 +25,10 @@ CONFIG_DNS_SERVER2="127.0.0.1:15353" CONFIG_MAIN_STACK_SIZE=2048 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y # User mode requirements CONFIG_TEST_USERSPACE=y CONFIG_HEAP_MEM_POOL_SIZE=128 -CONFIG_NEWLIB_LIBC_ALIGNED_HEAP_SIZE=2048 # We do not need neighbor discovery etc for this test CONFIG_NET_IPV6_DAD=n diff --git a/tests/net/socket/getaddrinfo/testcase.yaml b/tests/net/socket/getaddrinfo/testcase.yaml index 6cecbe452bf..b22bc2a1661 100644 --- a/tests/net/socket/getaddrinfo/testcase.yaml +++ b/tests/net/socket/getaddrinfo/testcase.yaml @@ -1,6 +1,6 @@ common: depends_on: netif - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED tests: net.socket.get_addr_info: min_ram: 21 diff --git a/tests/net/socket/getnameinfo/prj.conf b/tests/net/socket/getnameinfo/prj.conf index eb7851f76fc..adc83076810 100644 --- a/tests/net/socket/getnameinfo/prj.conf +++ b/tests/net/socket/getnameinfo/prj.conf @@ -1,5 +1,5 @@ # General config -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y # Networking config CONFIG_NETWORKING=y @@ -24,7 +24,6 @@ CONFIG_DNS_SERVER2="192.0.2.2:15353" CONFIG_MAIN_STACK_SIZE=2048 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y # User mode requirements CONFIG_TEST_USERSPACE=y diff --git a/tests/net/socket/getnameinfo/testcase.yaml b/tests/net/socket/getnameinfo/testcase.yaml index 2a8522d79ce..9edc6b2502e 100644 --- a/tests/net/socket/getnameinfo/testcase.yaml +++ b/tests/net/socket/getnameinfo/testcase.yaml @@ -1,6 +1,6 @@ common: depends_on: netif - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED tests: net.socket.get_name_info: min_ram: 21 diff --git a/tests/net/socket/misc/CMakeLists.txt b/tests/net/socket/misc/CMakeLists.txt index 00b96b355a3..80fbd4a769d 100644 --- a/tests/net/socket/misc/CMakeLists.txt +++ b/tests/net/socket/misc/CMakeLists.txt @@ -4,5 +4,6 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(socket-misc) +target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/net/ip) FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) diff --git a/tests/net/socket/misc/prj.conf b/tests/net/socket/misc/prj.conf index b71231f2705..8e7bd8459cd 100644 --- a/tests/net/socket/misc/prj.conf +++ b/tests/net/socket/misc/prj.conf @@ -1,5 +1,5 @@ # General config -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y # Networking config CONFIG_NETWORKING=y @@ -28,8 +28,8 @@ CONFIG_NET_IF_MAX_IPV6_COUNT=3 CONFIG_NET_IF_MAX_IPV4_COUNT=3 CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_ZTEST_STACK_SIZE=2048 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y # TCP handshake requires more packets CONFIG_NET_PKT_TX_COUNT=10 diff --git a/tests/net/socket/misc/src/main.c b/tests/net/socket/misc/src/main.c index c8f31435fd8..06a9d8e625d 100644 --- a/tests/net/socket/misc/src/main.c +++ b/tests/net/socket/misc/src/main.c @@ -14,6 +14,8 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_SOCKETS_LOG_LEVEL); #include #include +#include "net_private.h" + #include "../../socket_helpers.h" ZTEST_USER(socket_misc_test_suite, test_gethostname) @@ -94,9 +96,8 @@ static int dummy_send(const struct device *dev, struct net_pkt *pkt) int ret; ARG_UNUSED(dev); - ARG_UNUSED(pkt); - NET_DBG("Sending data (%zd bytes) to iface %d\n", + NET_DBG("Sending data (%zd bytes) to iface %d", net_pkt_get_len(pkt), net_if_get_by_iface(net_pkt_iface(pkt))); current_dev = dev; @@ -112,6 +113,8 @@ static int dummy_send(const struct device *dev, struct net_pkt *pkt) ret = net_recv_data(net_pkt_iface(recv_pkt), recv_pkt); zassert_equal(ret, 0, "Cannot receive data (%d)", ret); + net_pkt_unref(pkt); + return 0; } @@ -286,6 +289,8 @@ void test_so_bindtodevice(int sock_c, int sock_s, struct sockaddr *peer_addr, zassert_equal(ret, 0, "close failed, %d", errno); ret = close(sock_s); zassert_equal(ret, 0, "close failed, %d", errno); + + k_sleep(K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY)); } void test_ipv4_so_bindtodevice(void) @@ -423,7 +428,7 @@ void test_getpeername(int family) ret = close(sock_s); zassert_equal(ret, 0, "close failed, %d", errno); - k_sleep(K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY)); + k_sleep(K_MSEC(2 * CONFIG_NET_TCP_TIME_WAIT_DELAY)); } @@ -570,6 +575,265 @@ void test_getsockname_udp(int family) zassert_equal(ret, 0, "close failed, %d", errno); } +#define MAPPING_PORT 4244 + +void test_ipv4_mapped_to_ipv6_disabled(void) +{ + int ret; + int sock_s4, sock_s6; + struct sockaddr srv_addr4 = { 0 }; + struct sockaddr srv_addr6 = { 0 }; + + if (IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6)) { + return; + } + + srv_addr4.sa_family = AF_INET; + net_sin(&srv_addr4)->sin_port = htons(MAPPING_PORT); + ret = inet_pton(AF_INET, TEST_MY_IPV4_ADDR, + &net_sin(&srv_addr4)->sin_addr); + zassert_equal(ret, 1, "inet_pton failed"); + + srv_addr6.sa_family = AF_INET6; + net_sin6(&srv_addr6)->sin6_port = htons(MAPPING_PORT); + ret = inet_pton(AF_INET6, TEST_MY_IPV6_ADDR, + &net_sin6(&srv_addr6)->sin6_addr); + zassert_equal(ret, 1, "inet_pton failed"); + + sock_s4 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + zassert_true(sock_s4 >= 0, "socket open failed"); + + ret = bind(sock_s4, &srv_addr4, ADDR_SIZE(AF_INET)); + zassert_equal(ret, 0, "bind failed, %d", errno); + + ret = listen(sock_s4, 1); + zassert_equal(ret, 0, "listen failed, %d", errno); + + sock_s6 = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); + zassert_true(sock_s6 >= 0, "socket open failed"); + + ret = bind(sock_s6, &srv_addr6, ADDR_SIZE(AF_INET6)); + zassert_equal(ret, 0, "bind failed, %d", errno); + + ret = close(sock_s4); + zassert_equal(ret, 0, "close failed, %d", errno); + ret = close(sock_s6); + zassert_equal(ret, 0, "close failed, %d", errno); +} + +void test_ipv4_mapped_to_ipv6_enabled(void) +{ + socklen_t optlen = sizeof(int); + int off = 0; + int ret; + int sock_s4, sock_s6; + struct sockaddr srv_addr4 = { 0 }; + struct sockaddr srv_addr6 = { 0 }; + + if (!IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6)) { + return; + } + + /* We must have bound to ANY address so that the + * v4-mapping-to-v6 works as expected. + */ + srv_addr4.sa_family = AF_INET; + net_sin(&srv_addr4)->sin_port = htons(MAPPING_PORT); + ret = inet_pton(AF_INET, "0.0.0.0", + &net_sin(&srv_addr4)->sin_addr); + zassert_equal(ret, 1, "inet_pton failed"); + + srv_addr6.sa_family = AF_INET6; + net_sin6(&srv_addr6)->sin6_port = htons(MAPPING_PORT); + ret = inet_pton(AF_INET6, "::", + &net_sin6(&srv_addr6)->sin6_addr); + zassert_equal(ret, 1, "inet_pton failed"); + + /* First create IPv6 socket */ + sock_s6 = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); + zassert_true(sock_s6 >= 0, "socket open failed"); + + ret = bind(sock_s6, &srv_addr6, ADDR_SIZE(AF_INET6)); + zassert_equal(ret, 0, "bind failed, %d", errno); + + ret = listen(sock_s6, 1); + zassert_equal(ret, 0, "listen failed, %d", errno); + + /* Then try to create IPv4 socket to the same port */ + sock_s4 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + zassert_true(sock_s4 >= 0, "socket open failed"); + + /* Initially the IPV6_V6ONLY is set so the next bind is ok */ + ret = bind(sock_s4, &srv_addr4, ADDR_SIZE(AF_INET)); + zassert_equal(ret, 0, "bind failed, %d", errno); + + ret = close(sock_s4); + zassert_equal(ret, 0, "close failed, %d", errno); + + /* Then we turn off IPV6_V6ONLY which means that IPv4 and IPv6 + * will have same port space and the next bind should fail. + */ + ret = setsockopt(sock_s6, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off)); + zassert_equal(ret, 0, "setsockopt failed, %d", errno); + + ret = getsockopt(sock_s6, IPPROTO_IPV6, IPV6_V6ONLY, &off, &optlen); + zassert_equal(ret, 0, "getsockopt failed, %d", errno); + zassert_equal(off, 0, "IPV6_V6ONLY option setting failed"); + + sock_s4 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + zassert_true(sock_s4 >= 0, "socket open failed"); + + /* Now v4 bind should fail */ + ret = bind(sock_s4, &srv_addr4, ADDR_SIZE(AF_INET)); + zassert_equal(ret, -1, "bind failed, %d", errno); + zassert_equal(errno, EADDRINUSE, "bind failed"); + + ret = close(sock_s4); + zassert_equal(ret, 0, "close failed, %d", errno); + ret = close(sock_s6); + zassert_equal(ret, 0, "close failed, %d", errno); +} + +void test_ipv4_mapped_to_ipv6_server(void) +{ + socklen_t optlen = sizeof(int); + int off; + int ret, len; + int sock_c4, sock_c6, sock_s6, new_sock; + struct sockaddr srv_addr6 = { 0 }; + struct sockaddr srv_addr = { 0 }; + struct sockaddr connect_addr6 = { 0 }; + struct sockaddr addr = { 0 }; + socklen_t addrlen = sizeof(addr); + struct sockaddr_in6 mapped; + +#define MAX_BUF_SIZE 16 + char buf[MAX_BUF_SIZE]; + + if (!IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6)) { + return; + } + + len = strlen("foobar"); + + /* Create a server socket and try to connect IPv4 + * socket to it. If v4-mapping-to-v6 is enabled, + * this will work and we should be bound internally + * to ::ffff:a.b.c.d IPv6 address. + */ + srv_addr.sa_family = AF_INET; + net_sin(&srv_addr)->sin_port = htons(MAPPING_PORT); + ret = inet_pton(AF_INET, "192.0.2.1", + &net_sin(&srv_addr)->sin_addr); + zassert_equal(ret, 1, "inet_pton failed"); + + connect_addr6.sa_family = AF_INET6; + net_sin6(&connect_addr6)->sin6_port = htons(MAPPING_PORT); + ret = inet_pton(AF_INET6, TEST_PEER_IPV6_ADDR, + &net_sin6(&connect_addr6)->sin6_addr); + zassert_equal(ret, 1, "inet_pton failed"); + + net_ipv6_addr_create_v4_mapped(&net_sin(&srv_addr)->sin_addr, + &mapped.sin6_addr); + + /* We must have bound to ANY address so that the + * v4-mapping-to-v6 works as expected. + */ + srv_addr6.sa_family = AF_INET6; + net_sin6(&srv_addr6)->sin6_port = htons(MAPPING_PORT); + ret = inet_pton(AF_INET6, "::", + &net_sin6(&srv_addr6)->sin6_addr); + zassert_equal(ret, 1, "inet_pton failed"); + + /* First create IPv6 socket */ + sock_s6 = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); + zassert_true(sock_s6 >= 0, "socket open failed"); + + /* Verify that by default the IPV6_V6ONLY option is set */ + ret = getsockopt(sock_s6, IPPROTO_IPV6, IPV6_V6ONLY, &off, &optlen); + zassert_equal(ret, 0, "getsockopt failed, %d", errno); + zassert_not_equal(off, 0, "IPV6_V6ONLY option setting failed"); + + /* Then we turn off IPV6_V6ONLY which means that IPv4 and IPv6 + * will have same port space. + */ + off = 0; + ret = setsockopt(sock_s6, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off)); + zassert_equal(ret, 0, "setsockopt failed, %d", errno); + + ret = getsockopt(sock_s6, IPPROTO_IPV6, IPV6_V6ONLY, &off, &optlen); + zassert_equal(ret, 0, "getsockopt failed, %d", errno); + zassert_equal(off, 0, "IPV6_V6ONLY option setting failed, %d", off); + + ret = bind(sock_s6, &srv_addr6, ADDR_SIZE(AF_INET6)); + zassert_equal(ret, 0, "bind failed, %d", errno); + + ret = listen(sock_s6, 1); + zassert_equal(ret, 0, "listen failed, %d", errno); + + /* Then create IPv4 socket and connect to the IPv6 port */ + sock_c4 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + zassert_true(sock_c4 >= 0, "socket open failed"); + + ret = connect(sock_c4, &srv_addr, ADDR_SIZE(AF_INET)); + zassert_equal(ret, 0, "connect failed"); + + new_sock = accept(sock_s6, &addr, &addrlen); + zassert_true(new_sock >= 0, "accept failed, %d", errno); + + /* Note that we should get IPv6 address here (mapped from IPv4) */ + zassert_equal(addr.sa_family, AF_INET6, "wrong family"); + zassert_equal(addrlen, sizeof(struct sockaddr_in6), + "wrong addrlen (%d, expecting %d)", addrlen, + sizeof(struct sockaddr_in6)); + zassert_mem_equal(&mapped.sin6_addr, &net_sin6(&addr)->sin6_addr, + sizeof(struct in6_addr), + "wrong address (%s, expecting %s)", + net_sprint_ipv6_addr(&mapped.sin6_addr), + net_sprint_ipv6_addr(&net_sin6(&addr)->sin6_addr)); + + /* Send data back to IPv4 client from IPv6 socket */ + ret = send(new_sock, "foobar", len, 0); + zassert_equal(ret, len, "cannot send (%d vs %d), errno %d", ret, len, errno); + + addrlen = sizeof(struct sockaddr_in); + ret = recv(sock_c4, buf, sizeof(buf), 0); + zassert_equal(ret, strlen("foobar"), "cannot recv"); + + ret = close(sock_c4); + zassert_equal(ret, 0, "close failed, %d", errno); + + (void)close(new_sock); + + /* Let the system stabilize and cleanup itself */ + k_sleep(K_MSEC(200)); + + /* Then create IPv6 socket and make sure it works ok too */ + sock_c6 = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); + zassert_true(sock_c6 >= 0, "socket open failed"); + + ret = connect(sock_c6, &connect_addr6, ADDR_SIZE(AF_INET6)); + zassert_equal(ret, 0, "connect failed, %d", errno); + + new_sock = accept(sock_s6, &addr, &addrlen); + zassert_true(new_sock >= 0, "accept failed, %d", errno); + + ret = send(new_sock, "foobar", len, 0); + zassert_equal(ret, len, "cannot send (%d vs %d), errno %d", ret, len, errno); + + addrlen = sizeof(struct sockaddr_in); + ret = recv(sock_c6, buf, sizeof(buf), 0); + zassert_equal(ret, strlen("foobar"), "cannot recv"); + + ret = close(sock_c6); + zassert_equal(ret, 0, "close failed, %d", errno); + + ret = close(sock_s6); + zassert_equal(ret, 0, "close failed, %d", errno); + ret = close(new_sock); + zassert_equal(ret, 0, "close failed, %d", errno); +} + ZTEST_USER(socket_misc_test_suite, test_ipv4_getsockname_tcp) { test_getsockname_tcp(AF_INET); @@ -608,4 +872,19 @@ ZTEST_USER(socket_misc_test_suite, test_ipv6) test_ipv6_getpeername(); } +ZTEST_USER(socket_misc_test_suite, test_ipv4_mapped_to_ipv6_disabled) +{ + test_ipv4_mapped_to_ipv6_disabled(); +} + +ZTEST_USER(socket_misc_test_suite, test_ipv4_mapped_to_ipv6_enabled) +{ + test_ipv4_mapped_to_ipv6_enabled(); +} + +ZTEST(socket_misc_test_suite, test_ipv4_mapped_to_ipv6_server) +{ + test_ipv4_mapped_to_ipv6_server(); +} + ZTEST_SUITE(socket_misc_test_suite, NULL, setup, NULL, NULL, NULL); diff --git a/tests/net/socket/misc/testcase.yaml b/tests/net/socket/misc/testcase.yaml index 0cb289659f9..db8acadcd62 100644 --- a/tests/net/socket/misc/testcase.yaml +++ b/tests/net/socket/misc/testcase.yaml @@ -1,6 +1,6 @@ common: depends_on: netif - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED min_ram: 21 tags: - net @@ -13,3 +13,9 @@ tests: net.socket.misc.userspace: extra_configs: - CONFIG_TEST_USERSPACE=y + net.socket.misc.v4_mapping_to_v6_enabled: + extra_configs: + - CONFIG_NET_IPV4_MAPPING_TO_IPV6=y + net.socket.misc.v4_mapping_to_v6_disabled: + extra_configs: + - CONFIG_NET_IPV4_MAPPING_TO_IPV6=n diff --git a/tests/net/socket/net_mgmt/prj.conf b/tests/net/socket/net_mgmt/prj.conf index 58b4fc6ce75..d5c337242aa 100644 --- a/tests/net/socket/net_mgmt/prj.conf +++ b/tests/net/socket/net_mgmt/prj.conf @@ -20,7 +20,6 @@ CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_MAIN_STACK_SIZE=2048 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y # User mode requirements CONFIG_TEST_USERSPACE=y diff --git a/tests/net/socket/net_mgmt/src/main.c b/tests/net/socket/net_mgmt/src/main.c index a13f4537206..0f5bec63462 100644 --- a/tests/net/socket/net_mgmt/src/main.c +++ b/tests/net/socket/net_mgmt/src/main.c @@ -457,6 +457,34 @@ ZTEST_USER(net_socket_net_mgmt, test_net_mgmt_catch_user) test_net_mgmt_catch_events(); } +static void test_net_mgmt_catch_events_failure(void) +{ +#define SMALL_BUF_LEN 16 + struct sockaddr_nm event_addr; + socklen_t event_addr_len; + uint8_t buf[SMALL_BUF_LEN]; + int ret; + + memset(buf, 0, sizeof(buf)); + event_addr_len = sizeof(event_addr); + + ret = recvfrom(fd, buf, sizeof(buf), 0, + (struct sockaddr *)&event_addr, + &event_addr_len); + zassert_equal(ret, -1, "Msg check failed, %d", errno); + zassert_equal(errno, EMSGSIZE, "Msg check failed, errno %d", errno); +} + +ZTEST(net_socket_net_mgmt, test_net_mgmt_catch_failure_kernel) +{ + test_net_mgmt_catch_events_failure(); +} + +ZTEST_USER(net_socket_net_mgmt, test_net_mgmt_catch_failure_user) +{ + test_net_mgmt_catch_events_failure(); +} + ZTEST(net_socket_net_mgmt, test_net_mgmt_cleanup) { k_thread_abort(trigger_events_thread_id); diff --git a/tests/net/socket/offload_dispatcher/prj.conf b/tests/net/socket/offload_dispatcher/prj.conf index 0d185939cec..2ba9d78fed7 100644 --- a/tests/net/socket/offload_dispatcher/prj.conf +++ b/tests/net/socket/offload_dispatcher/prj.conf @@ -1,6 +1,5 @@ CONFIG_NET_TEST=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=2048 # Networking config diff --git a/tests/net/socket/poll/prj.conf b/tests/net/socket/poll/prj.conf index 709f46062d9..fb9b598e32c 100644 --- a/tests/net/socket/poll/prj.conf +++ b/tests/net/socket/poll/prj.conf @@ -20,7 +20,6 @@ CONFIG_ZTEST_STACK_SIZE=1280 CONFIG_NET_TCP_INIT_RETRANSMISSION_TIMEOUT=100 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NET_TEST=y CONFIG_NET_DRIVERS=y diff --git a/tests/net/socket/register/prj.conf b/tests/net/socket/register/prj.conf index 36da34741ce..d2b3e01b6c0 100644 --- a/tests/net/socket/register/prj.conf +++ b/tests/net/socket/register/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NETWORKING=y CONFIG_NET_TEST=y CONFIG_NET_DRIVERS=y diff --git a/tests/net/socket/reuseaddr_reuseport/CMakeLists.txt b/tests/net/socket/reuseaddr_reuseport/CMakeLists.txt new file mode 100644 index 00000000000..eaa76e6a460 --- /dev/null +++ b/tests/net/socket/reuseaddr_reuseport/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(socket-reuseaddr_reuseport) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/net/socket/reuseaddr_reuseport/prj.conf b/tests/net/socket/reuseaddr_reuseport/prj.conf new file mode 100644 index 00000000000..f78a1bea312 --- /dev/null +++ b/tests/net/socket/reuseaddr_reuseport/prj.conf @@ -0,0 +1,56 @@ +# General config +CONFIG_REQUIRES_FULL_LIBC=y + +# Networking config +CONFIG_NETWORKING=y +CONFIG_NET_TEST=y +CONFIG_NET_DRIVERS=y +CONFIG_NET_LOOPBACK=y +CONFIG_NET_IPV4=y +CONFIG_NET_IPV6=y +CONFIG_NET_UDP=y +CONFIG_NET_TCP=y +CONFIG_NET_SOCKETS=y +CONFIG_NET_SOCKETS_POSIX_NAMES=y +CONFIG_NET_L2_DUMMY=y +CONFIG_NET_IPV6_DAD=n +CONFIG_NET_IPV6_MLD=n +CONFIG_NET_IPV6_ND=n +CONFIG_NET_ARP=n + +CONFIG_NET_PKT_RX_COUNT=16 +CONFIG_NET_PKT_TX_COUNT=16 +CONFIG_NET_BUF_RX_COUNT=64 +CONFIG_NET_BUF_TX_COUNT=64 + +CONFIG_NET_CONTEXT_REUSEADDR=y +CONFIG_NET_CONTEXT_REUSEPORT=y + +CONFIG_NET_HOSTNAME_ENABLE=y +CONFIG_NET_HOSTNAME="ztest_hostname" + +CONFIG_POSIX_MAX_FDS=8 +CONFIG_NET_MAX_CONN=10 +CONFIG_NET_MAX_CONTEXTS=10 + +# Network driver config +CONFIG_TEST_RANDOM_GENERATOR=y + +# Reduce the retry count, so the close always finishes within a second +CONFIG_NET_TCP_RETRY_COUNT=3 +CONFIG_NET_TCP_INIT_RETRANSMISSION_TIMEOUT=120 +CONFIG_NET_TCP_TIME_WAIT_DELAY=200 + +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_ZTEST=y +CONFIG_ZTEST_STACK_SIZE=4096 + +# User mode requirements +CONFIG_TEST_USERSPACE=y +CONFIG_HEAP_MEM_POOL_SIZE=8192 + +# If you want to debug the tests, you can get logging using these statements +# CONFIG_LOG=y +# CONFIG_LOG_MODE_DEFERRED=y +# CONFIG_NET_LOG=y +# CONFIG_NET_TCP_LOG_LEVEL_DBG=y diff --git a/tests/net/socket/reuseaddr_reuseport/src/main.c b/tests/net/socket/reuseaddr_reuseport/src/main.c new file mode 100644 index 00000000000..1ab9be96e9a --- /dev/null +++ b/tests/net/socket/reuseaddr_reuseport/src/main.c @@ -0,0 +1,960 @@ +/* + * Copyright (c) 2019 Linaro Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_REGISTER(net_test, CONFIG_NET_SOCKETS_LOG_LEVEL); + +#include +#include +#include +#include + +#include +#include + +#include "../../socket_helpers.h" + +#define TEST_IPV4_ANY_ADDR "0.0.0.0" +#define TEST_MY_IPV4_ADDR "192.0.2.1" +#define TEST_MY_IPV4_ADDR2 "192.0.2.2" + +#define TEST_IPV6_ANY_ADDR "::" +#define TEST_MY_IPV6_ADDR "2001:db8::1" +#define TEST_MY_IPV6_ADDR2 "2001:db8::2" + +#define LOCAL_PORT 4242 + +#define TCP_TEARDOWN_TIMEOUT K_SECONDS(3) + +#define SHOULD_SUCCEED true +#define SHOULD_FAIL false + +static void test_add_local_ip_address(sa_family_t family, const char *ip) +{ + if (family == AF_INET) { + struct sockaddr_in addr; + + zsock_inet_pton(AF_INET, ip, &addr.sin_addr); + + zassert_not_null(net_if_ipv4_addr_add(net_if_get_default(), + &addr.sin_addr, + NET_ADDR_MANUAL, + 0), + "Cannot add IPv4 address %s", ip); + } else if (family == AF_INET6) { + struct sockaddr_in6 addr; + + zsock_inet_pton(AF_INET6, ip, &addr.sin6_addr); + + zassert_not_null(net_if_ipv6_addr_add(net_if_get_default(), + &addr.sin6_addr, + NET_ADDR_MANUAL, + 0), + "Cannot add IPv6 address %s", ip); + } +} + +static void *setup(void) +{ + /* Make sure that both the specified IPv4 and IPv6 addresses are + * added to the network interface. + */ + test_add_local_ip_address(AF_INET, TEST_MY_IPV4_ADDR); + test_add_local_ip_address(AF_INET6, TEST_MY_IPV6_ADDR); + + return NULL; +} + +static inline void prepare_sock_tcp(sa_family_t family, const char *ip, uint16_t port, + int *sock, struct sockaddr *addr) +{ + if (family == AF_INET) { + prepare_sock_tcp_v4(ip, + port, + sock, + (struct sockaddr_in *) addr); + } else if (family == AF_INET6) { + prepare_sock_tcp_v6(ip, + port, + sock, + (struct sockaddr_in6 *) addr); + } +} + +static inline void prepare_sock_udp(sa_family_t family, const char *ip, uint16_t port, + int *sock, struct sockaddr *addr) +{ + if (family == AF_INET) { + prepare_sock_udp_v4(ip, + port, + sock, + (struct sockaddr_in *) addr); + } else if (family == AF_INET6) { + prepare_sock_udp_v6(ip, + port, + sock, + (struct sockaddr_in6 *) addr); + } +} + +static void test_getsocketopt_reuseaddr(int sock, void *optval, socklen_t *optlen) +{ + zassert_equal(getsockopt(sock, SOL_SOCKET, SO_REUSEADDR, optval, optlen), + 0, + "getsocketopt() failed with error %d", errno); +} + +static void test_setsocketopt_reuseaddr(int sock, void *optval, socklen_t optlen) +{ + zassert_equal(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, optval, optlen), + 0, + "setsocketopt() failed with error %d", errno); +} + +static void test_enable_reuseaddr(int sock) +{ + int value = 1; + + test_setsocketopt_reuseaddr(sock, &value, sizeof(value)); +} + +static void test_getsocketopt_reuseport(int sock, void *optval, socklen_t *optlen) +{ + zassert_equal(getsockopt(sock, SOL_SOCKET, SO_REUSEPORT, optval, optlen), + 0, + "getsocketopt() failed with error %d", errno); +} + +static void test_setsocketopt_reuseport(int sock, void *optval, socklen_t optlen) +{ + zassert_equal(setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, optval, optlen), + 0, + "setsocketopt() failed with error %d", errno); +} + +static void test_enable_reuseport(int sock) +{ + int value = 1; + + test_setsocketopt_reuseport(sock, &value, sizeof(value)); +} + +static void test_bind_success(int sock, const struct sockaddr *addr, socklen_t addrlen) +{ + zassert_equal(bind(sock, addr, addrlen), + 0, + "bind() failed with error %d", errno); +} + +static void test_bind_fail(int sock, const struct sockaddr *addr, socklen_t addrlen) +{ + zassert_equal(bind(sock, addr, addrlen), + -1, + "bind() succeeded incorrectly"); + + zassert_equal(errno, EADDRINUSE, "bind() returned unexpected errno (%d)", errno); +} + +static void test_listen(int sock) +{ + zassert_equal(listen(sock, 0), + 0, + "listen() failed with error %d", errno); +} + +static void test_connect_success(int sock, const struct sockaddr *addr, socklen_t addrlen) +{ + zassert_equal(connect(sock, addr, addrlen), + 0, + "connect() failed with error %d", errno); + + if (IS_ENABLED(CONFIG_NET_TC_THREAD_PREEMPTIVE)) { + /* Let the connection proceed */ + k_msleep(50); + } +} + +static void test_connect_fail(int sock, const struct sockaddr *addr, socklen_t addrlen) +{ + zassert_equal(connect(sock, addr, addrlen), + -1, + "connect() succeeded incorrectly"); + + zassert_equal(errno, EADDRINUSE, "connect() returned unexpected errno (%d)", errno); +} + +static int test_accept(int sock, struct sockaddr *addr, socklen_t *addrlen) +{ + int new_sock = accept(sock, addr, addrlen); + + zassert_not_equal(new_sock, -1, "accept() failed with error %d", errno); + + return new_sock; +} + +static void test_sendto(int sock, const void *buf, size_t len, int flags, + const struct sockaddr *dest_addr, socklen_t addrlen) +{ + zassert_equal(sendto(sock, buf, len, flags, dest_addr, addrlen), + len, + "sendto failed with error %d", errno); +} + +static void test_recvfrom_success(int sock, void *buf, size_t max_len, int flags, + struct sockaddr *src_addr, socklen_t *addrlen) +{ + zassert_equal(recvfrom(sock, buf, max_len, flags, src_addr, addrlen), + max_len, + "recvfrom failed with error %d", errno); +} + +static void test_recvfrom_fail(int sock, void *buf, size_t max_len, int flags, + struct sockaddr *src_addr, socklen_t *addrlen) +{ + zassert_equal(recvfrom(sock, buf, max_len, flags, src_addr, addrlen), + -1, + "recvfrom succeeded incorrectly"); + + zassert_equal(errno, EAGAIN, "recvfrom() returned unexpected errno (%d)", errno); +} + +static void test_recv_success(int sock, void *buf, size_t max_len, int flags) +{ + zassert_equal(recv(sock, buf, max_len, flags), + max_len, + "recv failed with error %d", errno); +} + +static void test_recv_fail(int sock, void *buf, size_t max_len, int flags) +{ + zassert_equal(recv(sock, buf, max_len, flags), + -1, + "recvfrom succeeded incorrectly"); + + zassert_equal(errno, EAGAIN, "recvfrom() returned unexpected errno (%d)", errno); +} + +ZTEST_USER(socket_reuseaddr_test_suite, test_enable_disable) +{ + int server_sock = -1; + int value = -1; + socklen_t value_size = sizeof(int); + + server_sock = zsock_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + zassert_true(server_sock >= 0, "socket open failed"); + + /* Read initial value */ + test_getsocketopt_reuseaddr(server_sock, (void *)&value, &value_size); + zassert_equal(value_size, sizeof(int), "incorrect value size returned by getsocketopt()"); + zassert_equal(value, (int) false, "SO_REUSEADDR incorrectly set (expected false)"); + + /* Enable option */ + value = 1; + test_setsocketopt_reuseaddr(server_sock, (void *)&value, sizeof(value)); + test_getsocketopt_reuseaddr(server_sock, (void *)&value, &value_size); + zassert_equal(value, (int) true, "SO_REUSEADDR not correctly set, returned %d", value); + + /* Enable option (with other value as linux takes any int here) */ + value = 2; + test_setsocketopt_reuseaddr(server_sock, (void *)&value, sizeof(value)); + test_getsocketopt_reuseaddr(server_sock, (void *)&value, &value_size); + zassert_equal(value, (int) true, "SO_REUSEADDR not correctly set, returned %d", value); + + /* Enable option (with other value as linux takes any int here) */ + value = 0x100; + test_setsocketopt_reuseaddr(server_sock, (void *)&value, sizeof(value)); + test_getsocketopt_reuseaddr(server_sock, (void *)&value, &value_size); + zassert_equal(value, (int) true, "SO_REUSEADDR not correctly set, returned %d", value); + + /* Enable option (with other value as linux takes any int here) */ + value = -1; + test_setsocketopt_reuseaddr(server_sock, (void *)&value, sizeof(value)); + test_getsocketopt_reuseaddr(server_sock, (void *)&value, &value_size); + zassert_equal(value, (int) true, "SO_REUSEADDR not correctly set, returned %d", value); + + close(server_sock); +} + + +static void test_reuseaddr_unspecified_specified_common(sa_family_t family, + char const *first_ip, + char const *second_ip, + bool should_succeed) +{ + int server_sock1 = -1; + int server_sock2 = -1; + + struct sockaddr bind_addr1; + struct sockaddr bind_addr2; + + /* Create the sockets */ + prepare_sock_tcp(family, first_ip, LOCAL_PORT, &server_sock1, &bind_addr1); + prepare_sock_tcp(family, second_ip, LOCAL_PORT, &server_sock2, &bind_addr2); + + /* Bind the first socket */ + test_bind_success(server_sock1, &bind_addr1, sizeof(bind_addr1)); + + /* Try to bind the second socket, should fail */ + test_bind_fail(server_sock2, &bind_addr2, sizeof(bind_addr2)); + + /* Enable SO_REUSEADDR option for the second socket */ + test_enable_reuseaddr(server_sock2); + + /* Try to bind the second socket again */ + if (should_succeed) { + test_bind_success(server_sock2, &bind_addr2, sizeof(bind_addr2)); + } else { + test_bind_fail(server_sock2, &bind_addr2, sizeof(bind_addr2)); + } + + close(server_sock1); + close(server_sock2); +} + +ZTEST_USER(socket_reuseaddr_test_suite, test_ipv4_first_unspecified) +{ + test_reuseaddr_unspecified_specified_common(AF_INET, + TEST_IPV4_ANY_ADDR, + TEST_MY_IPV4_ADDR, + SHOULD_SUCCEED); +} + +ZTEST_USER(socket_reuseaddr_test_suite, test_ipv6_first_unspecified) +{ + test_reuseaddr_unspecified_specified_common(AF_INET6, + TEST_IPV6_ANY_ADDR, + TEST_MY_IPV6_ADDR, + SHOULD_SUCCEED); +} + +ZTEST_USER(socket_reuseaddr_test_suite, test_ipv4_second_unspecified) +{ + test_reuseaddr_unspecified_specified_common(AF_INET, + TEST_MY_IPV4_ADDR, + TEST_IPV4_ANY_ADDR, + SHOULD_SUCCEED); +} + +ZTEST_USER(socket_reuseaddr_test_suite, test_ipv6_second_unspecified) +{ + test_reuseaddr_unspecified_specified_common(AF_INET6, + TEST_MY_IPV6_ADDR, + TEST_IPV6_ANY_ADDR, + SHOULD_SUCCEED); +} + +ZTEST_USER(socket_reuseaddr_test_suite, test_ipv4_both_unspecified) +{ + test_reuseaddr_unspecified_specified_common(AF_INET, + TEST_IPV4_ANY_ADDR, + TEST_IPV4_ANY_ADDR, + SHOULD_FAIL); +} + +ZTEST_USER(socket_reuseaddr_test_suite, test_ipv6_both_unspecified) +{ + test_reuseaddr_unspecified_specified_common(AF_INET6, + TEST_IPV6_ANY_ADDR, + TEST_IPV6_ANY_ADDR, + SHOULD_FAIL); +} + + +static void test_reuseaddr_tcp_listening_common(sa_family_t family, + char const *first_ip, + char const *second_ip) +{ + int server_sock1 = -1; + int server_sock2 = -1; + + struct sockaddr bind_addr1; + struct sockaddr bind_addr2; + + /* Create the sockets */ + prepare_sock_tcp(family, first_ip, LOCAL_PORT, &server_sock1, &bind_addr1); + prepare_sock_tcp(family, second_ip, LOCAL_PORT, &server_sock2, &bind_addr2); + + /* Bind the first socket */ + test_bind_success(server_sock1, &bind_addr1, sizeof(bind_addr1)); + + /* Set the first socket to LISTEN state */ + test_listen(server_sock1); + + /* Enable SO_REUSEADDR option for the second socket */ + test_enable_reuseaddr(server_sock2); + + /* Try to bind the second socket, should fail */ + test_bind_fail(server_sock2, (struct sockaddr *) &bind_addr2, sizeof(bind_addr2)); + + close(server_sock1); + close(server_sock2); +} + +ZTEST_USER(socket_reuseaddr_test_suite, test_ipv4_tcp_unspecified_listening) +{ + test_reuseaddr_tcp_listening_common(AF_INET, + TEST_IPV4_ANY_ADDR, + TEST_MY_IPV4_ADDR); +} + +ZTEST_USER(socket_reuseaddr_test_suite, test_ipv6_tcp_unspecified_listening) +{ + test_reuseaddr_tcp_listening_common(AF_INET6, + TEST_IPV6_ANY_ADDR, + TEST_MY_IPV6_ADDR); +} + +ZTEST_USER(socket_reuseaddr_test_suite, test_ipv4_tcp_specified_listening) +{ + test_reuseaddr_tcp_listening_common(AF_INET, + TEST_MY_IPV4_ADDR, + TEST_IPV4_ANY_ADDR); +} + +ZTEST_USER(socket_reuseaddr_test_suite, test_ipv6_tcp_specified_listening) +{ + test_reuseaddr_tcp_listening_common(AF_INET6, + TEST_MY_IPV6_ADDR, + TEST_IPV6_ANY_ADDR); +} + + +static void test_reuseaddr_tcp_tcp_time_wait_common(sa_family_t family, + char const *first_ip, + char const *second_ip) +{ + int server_sock = -1; + int client_sock = -1; + int accept_sock = -1; + + struct sockaddr bind_addr; + struct sockaddr conn_addr; + + struct sockaddr accept_addr; + socklen_t accept_addrlen = sizeof(accept_addr); + + prepare_sock_tcp(family, first_ip, LOCAL_PORT, &server_sock, &bind_addr); + prepare_sock_tcp(family, second_ip, LOCAL_PORT, &client_sock, &conn_addr); + + /* Bind the server socket */ + test_bind_success(server_sock, (struct sockaddr *) &bind_addr, sizeof(bind_addr)); + + /* Start listening on the server socket */ + test_listen(server_sock); + + /* Connect the client */ + test_connect_success(client_sock, &conn_addr, sizeof(conn_addr)); + + /* Accept the client */ + accept_sock = test_accept(server_sock, &accept_addr, &accept_addrlen); + + /* Close the server socket */ + close(server_sock); + + /* Close the accepted socket */ + close(accept_sock); + + /* Wait a short time for the accept socket to enter TIME_WAIT state*/ + k_msleep(50); + + /* Recreate the server socket */ + prepare_sock_tcp(family, first_ip, LOCAL_PORT, &server_sock, &bind_addr); + + /* Bind the server socket, should fail */ + test_bind_fail(server_sock, (struct sockaddr *) &bind_addr, sizeof(bind_addr)); + + /* Enable SO_REUSEADDR option for the new server socket */ + test_enable_reuseaddr(server_sock); + + /* Try to bind the new server socket again, should work now */ + test_bind_success(server_sock, (struct sockaddr *) &bind_addr, sizeof(bind_addr)); + + close(client_sock); + close(server_sock); + + /* Connection is in TIME_WAIT state, context will be released + * after K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY), so wait for it. + */ + k_sleep(K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY)); +} + +ZTEST_USER(socket_reuseaddr_test_suite, test_ipv4_tcp_time_wait_unspecified) +{ + test_reuseaddr_tcp_tcp_time_wait_common(AF_INET, + TEST_IPV4_ANY_ADDR, + TEST_MY_IPV4_ADDR); +} + +ZTEST_USER(socket_reuseaddr_test_suite, test_ipv6_tcp_time_wait_unspecified) +{ + test_reuseaddr_tcp_tcp_time_wait_common(AF_INET6, + TEST_IPV6_ANY_ADDR, + TEST_MY_IPV6_ADDR); +} + +ZTEST_USER(socket_reuseaddr_test_suite, test_ipv4_tcp_time_wait_specified) +{ + test_reuseaddr_tcp_tcp_time_wait_common(AF_INET, + TEST_MY_IPV4_ADDR, + TEST_MY_IPV4_ADDR); +} + +ZTEST_USER(socket_reuseaddr_test_suite, test_ipv6_tcp_time_wait_specified) +{ + test_reuseaddr_tcp_tcp_time_wait_common(AF_INET6, + TEST_MY_IPV6_ADDR, + TEST_MY_IPV6_ADDR); +} + + +ZTEST_SUITE(socket_reuseaddr_test_suite, NULL, setup, NULL, NULL, NULL); + + +ZTEST_USER(socket_reuseport_test_suite, test_enable_disable) +{ + int server_sock = -1; + + int value = -1; + socklen_t value_size = sizeof(int); + + server_sock = zsock_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + zassert_true(server_sock >= 0, "socket open failed"); + + /* Read initial value */ + test_getsocketopt_reuseport(server_sock, (void *)&value, &value_size); + zassert_equal(value_size, sizeof(int), "incorrect value size returned by getsocketopt()"); + zassert_equal(value, (int) false, "SO_REUSEPORT incorrectly set (expected false)"); + + /* Enable option */ + value = 1; + test_setsocketopt_reuseport(server_sock, (void *)&value, sizeof(value)); + test_getsocketopt_reuseport(server_sock, (void *)&value, &value_size); + zassert_equal(value, (int) true, "SO_REUSEPORT not correctly set, returned %d", value); + + /* Enable option (with other value as linux takes any int here) */ + value = 2; + test_setsocketopt_reuseport(server_sock, (void *)&value, sizeof(value)); + test_getsocketopt_reuseport(server_sock, (void *)&value, &value_size); + zassert_equal(value, (int) true, "SO_REUSEPORT not correctly set, returned %d", value); + + /* Enable option (with other value as linux takes any int here) */ + value = 0x100; + test_setsocketopt_reuseport(server_sock, (void *)&value, sizeof(value)); + test_getsocketopt_reuseport(server_sock, (void *)&value, &value_size); + zassert_equal(value, (int) true, "SO_REUSEPORT not correctly set, returned %d", value); + + /* Enable option (with other value as linux takes any int here) */ + value = -1; + test_setsocketopt_reuseport(server_sock, (void *)&value, sizeof(value)); + test_getsocketopt_reuseport(server_sock, (void *)&value, &value_size); + zassert_equal(value, (int) true, "SO_REUSEPORT not correctly set, returned %d", value); + + close(server_sock); +} + + +static void test_reuseport_unspecified_specified_common(sa_family_t family, + char const *first_ip, + char const *second_ip, + bool should_succeed) +{ + int server_sock1 = -1; + int server_sock2 = -1; + + struct sockaddr bind_addr1; + struct sockaddr bind_addr2; + + /* Create the sockets */ + prepare_sock_tcp(family, first_ip, LOCAL_PORT, &server_sock1, &bind_addr1); + prepare_sock_tcp(family, second_ip, LOCAL_PORT, &server_sock2, &bind_addr2); + + /* Depending on the expected result, we enable SO_REUSEPORT for the first socket */ + if (should_succeed) { + test_enable_reuseport(server_sock1); + } + + /* Bind the first socket */ + test_bind_success(server_sock1, &bind_addr1, sizeof(bind_addr1)); + + /* Try to bind the second socket, should fail */ + test_bind_fail(server_sock2, &bind_addr2, sizeof(bind_addr2)); + + /* Enable SO_REUSEPORT option for the second socket */ + test_enable_reuseport(server_sock2); + + /* Try to bind the second socket again */ + if (should_succeed) { + test_bind_success(server_sock2, &bind_addr2, sizeof(bind_addr2)); + } else { + test_bind_fail(server_sock2, &bind_addr2, sizeof(bind_addr2)); + } + + close(server_sock1); + close(server_sock2); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv4_both_unspecified_bad) +{ + test_reuseport_unspecified_specified_common(AF_INET, + TEST_IPV4_ANY_ADDR, + TEST_IPV4_ANY_ADDR, + SHOULD_FAIL); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv6_both_unspecified_bad) +{ + test_reuseport_unspecified_specified_common(AF_INET6, + TEST_IPV6_ANY_ADDR, + TEST_IPV6_ANY_ADDR, + SHOULD_FAIL); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv4_both_unspecified_good) +{ + test_reuseport_unspecified_specified_common(AF_INET, + TEST_IPV4_ANY_ADDR, + TEST_IPV4_ANY_ADDR, + SHOULD_SUCCEED); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv6_both_unspecified_good) +{ + test_reuseport_unspecified_specified_common(AF_INET6, + TEST_IPV6_ANY_ADDR, + TEST_IPV6_ANY_ADDR, + SHOULD_SUCCEED); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv4_both_specified_bad) +{ + test_reuseport_unspecified_specified_common(AF_INET, + TEST_MY_IPV4_ADDR, + TEST_MY_IPV4_ADDR, + SHOULD_FAIL); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv6_both_specified_bad) +{ + test_reuseport_unspecified_specified_common(AF_INET6, + TEST_MY_IPV6_ADDR, + TEST_MY_IPV6_ADDR, + SHOULD_FAIL); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv4_both_specified_good) +{ + test_reuseport_unspecified_specified_common(AF_INET, + TEST_MY_IPV4_ADDR, + TEST_MY_IPV4_ADDR, + SHOULD_SUCCEED); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv6_both_specified_good) +{ + test_reuseport_unspecified_specified_common(AF_INET6, + TEST_MY_IPV6_ADDR, + TEST_MY_IPV6_ADDR, + SHOULD_SUCCEED); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv4_first_unspecified_bad) +{ + test_reuseport_unspecified_specified_common(AF_INET, + TEST_IPV4_ANY_ADDR, + TEST_MY_IPV4_ADDR, + SHOULD_FAIL); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv6_first_unspecified_bad) +{ + test_reuseport_unspecified_specified_common(AF_INET6, + TEST_IPV6_ANY_ADDR, + TEST_MY_IPV6_ADDR, + SHOULD_FAIL); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv4_first_unspecified_good) +{ + test_reuseport_unspecified_specified_common(AF_INET, + TEST_IPV4_ANY_ADDR, + TEST_MY_IPV4_ADDR, + SHOULD_SUCCEED); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv6_first_unspecified_good) +{ + test_reuseport_unspecified_specified_common(AF_INET6, + TEST_IPV6_ANY_ADDR, + TEST_MY_IPV6_ADDR, + SHOULD_SUCCEED); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv4_second_unspecified_bad) +{ + test_reuseport_unspecified_specified_common(AF_INET, + TEST_MY_IPV4_ADDR, + TEST_IPV4_ANY_ADDR, + SHOULD_FAIL); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv6_second_unspecified_bad) +{ + test_reuseport_unspecified_specified_common(AF_INET6, + TEST_MY_IPV6_ADDR, + TEST_IPV6_ANY_ADDR, + SHOULD_FAIL); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv4_second_unspecified_good) +{ + test_reuseport_unspecified_specified_common(AF_INET, + TEST_MY_IPV4_ADDR, + TEST_IPV4_ANY_ADDR, + SHOULD_SUCCEED); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv6_second_unspecified_good) +{ + test_reuseport_unspecified_specified_common(AF_INET6, + TEST_MY_IPV6_ADDR, + TEST_IPV6_ANY_ADDR, + SHOULD_SUCCEED); +} + + +enum sockets_reuseport_enabled { + NONE_SET = 0, + FIRST_SET, + SECOND_SET, + BOTH_SET +}; + +static void test_reuseport_udp_server_client_common(sa_family_t family, + char const *ip, + enum sockets_reuseport_enabled setup) +{ + int server_sock = -1; + int client_sock = -1; + int accept_sock = 1; + + struct sockaddr server_addr; + struct sockaddr client_addr; + + struct sockaddr accept_addr; + socklen_t accept_addr_len = sizeof(accept_addr); + + char tx_buf = 0x55; + char rx_buf; + + /* Create sockets */ + prepare_sock_udp(family, ip, LOCAL_PORT, &server_sock, &server_addr); + prepare_sock_udp(family, ip, 0, &client_sock, &client_addr); + + /* Make sure we can bind to the address:port */ + if (setup == FIRST_SET || setup == BOTH_SET) { + test_enable_reuseport(server_sock); + } + + /* Bind server socket */ + test_bind_success(server_sock, (struct sockaddr *) &server_addr, sizeof(server_addr)); + + /* Bind client socket (on a random port) */ + test_bind_success(client_sock, (struct sockaddr *) &client_addr, sizeof(client_addr)); + + /* Send message from client to server */ + test_sendto(client_sock, &tx_buf, sizeof(tx_buf), 0, &server_addr, sizeof(server_addr)); + + /* Give the packet a chance to go through the net stack */ + k_msleep(50); + + /* Receive data from the client */ + rx_buf = 0; + test_recvfrom_success(server_sock, &rx_buf, sizeof(rx_buf), MSG_DONTWAIT, + &accept_addr, &accept_addr_len); + zassert_equal(rx_buf, tx_buf, "wrong data"); + + /* Create a more specific socket to have a direct connection to the new client */ + accept_sock = socket(family, SOCK_DGRAM, IPPROTO_UDP); + zassert_true(accept_sock >= 0, "socket open failed"); + + /* Make sure we can bind to the address:port */ + if (setup == SECOND_SET || setup == BOTH_SET) { + test_enable_reuseport(accept_sock); + } + + /* Try to bind new client socket */ + if (setup == BOTH_SET) { + /* Should succeed */ + test_bind_success(accept_sock, (struct sockaddr *) &server_addr, + sizeof(server_addr)); + } else { + /* Should fail */ + test_bind_fail(accept_sock, (struct sockaddr *) &server_addr, + sizeof(server_addr)); + } + + /* Connect the client to set remote address and remote port */ + test_connect_success(accept_sock, &accept_addr, sizeof(accept_addr)); + + /* Send another message from client to server */ + test_sendto(client_sock, &tx_buf, sizeof(tx_buf), 0, &server_addr, sizeof(server_addr)); + + /* Give the packet a chance to go through the net stack */ + k_msleep(50); + + /* Receive the data */ + if (setup == BOTH_SET) { + /* We should receive data on the new specific socket, not on the general one */ + rx_buf = 0; + test_recvfrom_fail(server_sock, &rx_buf, sizeof(rx_buf), MSG_DONTWAIT, + &accept_addr, &accept_addr_len); + + rx_buf = 0; + test_recv_success(accept_sock, &rx_buf, sizeof(rx_buf), MSG_DONTWAIT); + } else { + /* We should receive data on the general server socket */ + rx_buf = 0; + test_recvfrom_success(server_sock, &rx_buf, sizeof(rx_buf), MSG_DONTWAIT, + &accept_addr, &accept_addr_len); + + rx_buf = 0; + test_recv_fail(accept_sock, &rx_buf, sizeof(rx_buf), MSG_DONTWAIT); + } + + close(accept_sock); + close(client_sock); + close(server_sock); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv4_udp_bad_both_not_set) +{ + test_reuseport_udp_server_client_common(AF_INET, + TEST_MY_IPV4_ADDR, + NONE_SET); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv6_udp_bad_both_not_set) +{ + test_reuseport_udp_server_client_common(AF_INET6, + TEST_MY_IPV6_ADDR, + NONE_SET); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv4_udp_bad_first_not_set) +{ + test_reuseport_udp_server_client_common(AF_INET, + TEST_MY_IPV4_ADDR, + SECOND_SET); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv6_udp_bad_first_not_set) +{ + test_reuseport_udp_server_client_common(AF_INET6, + TEST_MY_IPV6_ADDR, + SECOND_SET); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv4_udp_bad_second_not_set) +{ + test_reuseport_udp_server_client_common(AF_INET, + TEST_MY_IPV4_ADDR, + FIRST_SET); +} + + +ZTEST_USER(socket_reuseport_test_suite, test_ipv6_udp_bad_second_not_set) +{ + test_reuseport_udp_server_client_common(AF_INET6, + TEST_MY_IPV6_ADDR, + FIRST_SET); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv4_udp_good) +{ + test_reuseport_udp_server_client_common(AF_INET, + TEST_MY_IPV4_ADDR, + BOTH_SET); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv6_udp_good) +{ + test_reuseport_udp_server_client_common(AF_INET6, + TEST_MY_IPV6_ADDR, + BOTH_SET); +} + + +static void test_reuseport_tcp_identical_clients_common(sa_family_t family, + char const *server_ip, + char const *client_ip) +{ + int server_sock = -1; + int client_sock1 = -1; + int client_sock2 = -1; + int accept_sock = 1; + + struct sockaddr server_addr; + struct sockaddr client_addr; + struct sockaddr connect_addr; + + struct sockaddr accept_addr; + socklen_t accept_addr_len = sizeof(accept_addr); + + /* Create sockets */ + prepare_sock_tcp(family, server_ip, LOCAL_PORT, &server_sock, &server_addr); + prepare_sock_tcp(family, client_ip, LOCAL_PORT + 1, &client_sock1, &client_addr); + prepare_sock_tcp(family, client_ip, LOCAL_PORT, &client_sock2, &connect_addr); + + /* Enable SO_REUSEPORT option for the two sockets */ + test_enable_reuseport(client_sock1); + test_enable_reuseport(client_sock2); + + /* Bind server socket */ + test_bind_success(server_sock, &server_addr, sizeof(server_addr)); + + /* Start listening on the server socket */ + test_listen(server_sock); + + /* Bind the client sockets */ + test_bind_success(client_sock1, &client_addr, sizeof(client_addr)); + test_bind_success(client_sock2, &client_addr, sizeof(client_addr)); + + /* Connect the first client */ + test_connect_success(client_sock1, &connect_addr, sizeof(connect_addr)); + + /* Accept the first client */ + accept_sock = test_accept(server_sock, &accept_addr, &accept_addr_len); + + /* Connect the second client, should fail */ + test_connect_fail(client_sock2, (struct sockaddr *)&connect_addr, sizeof(connect_addr)); + + close(accept_sock); + close(client_sock1); + close(client_sock2); + close(server_sock); + + /* Connection is in TIME_WAIT state, context will be released + * after K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY), so wait for it. + */ + k_sleep(K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY)); +} + +ZTEST_USER(socket_reuseport_test_suite, test_ipv4_tcp_identical_clients) +{ + test_reuseport_tcp_identical_clients_common(AF_INET, + TEST_IPV4_ANY_ADDR, + TEST_MY_IPV4_ADDR); +} + + +ZTEST_USER(socket_reuseport_test_suite, test_ipv6_tcp_identical_clients) +{ + test_reuseport_tcp_identical_clients_common(AF_INET6, + TEST_IPV6_ANY_ADDR, + TEST_MY_IPV6_ADDR); +} + +ZTEST_SUITE(socket_reuseport_test_suite, NULL, setup, NULL, NULL, NULL); diff --git a/tests/net/socket/reuseaddr_reuseport/testcase.yaml b/tests/net/socket/reuseaddr_reuseport/testcase.yaml new file mode 100644 index 00000000000..c1a4808d1d3 --- /dev/null +++ b/tests/net/socket/reuseaddr_reuseport/testcase.yaml @@ -0,0 +1,18 @@ +common: + depends_on: netif + filter: CONFIG_FULL_LIBC_SUPPORTED + min_ram: 31 + tags: + - net + - socket + # FIXME: This test fails very frequently on mps2_an385 due to the system + # timer stability issues, so keep it disabled until the root cause + # is fixed (GitHub issue zephyrproject-rtos/zephyr#48608). + platform_exclude: mps2_an385 +tests: + net.socket.reuseaddr_reuseport: + extra_configs: + - CONFIG_TEST_USERSPACE=n + net.socket.reuseaddr_reuseport.userspace: + extra_configs: + - CONFIG_TEST_USERSPACE=y diff --git a/tests/net/socket/select/prj.conf b/tests/net/socket/select/prj.conf index 2641350a25d..cd642566971 100644 --- a/tests/net/socket/select/prj.conf +++ b/tests/net/socket/select/prj.conf @@ -1,5 +1,5 @@ # General config -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y # Networking config CONFIG_NETWORKING=y @@ -18,7 +18,6 @@ CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_MAIN_STACK_SIZE=2048 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NET_TCP_INIT_RETRANSMISSION_TIMEOUT=100 diff --git a/tests/net/socket/select/testcase.yaml b/tests/net/socket/select/testcase.yaml index af82a6ae51c..eaae57ab9ef 100644 --- a/tests/net/socket/select/testcase.yaml +++ b/tests/net/socket/select/testcase.yaml @@ -5,7 +5,7 @@ common: - net - socket - userspace - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED # FIXME: This test fails very frequently on mps2_an385 due to the system # timer stability issues, so keep it disabled until the root cause # is fixed (GitHub issue zephyrproject-rtos/zephyr#48608). diff --git a/tests/net/socket/socketpair/prj.conf b/tests/net/socket/socketpair/prj.conf index 83ecd35957e..9789809556c 100644 --- a/tests/net/socket/socketpair/prj.conf +++ b/tests/net/socket/socketpair/prj.conf @@ -14,7 +14,6 @@ CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_MAIN_STACK_SIZE=2048 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y # User mode requirements CONFIG_TEST_USERSPACE=y diff --git a/tests/net/socket/socketpair/testcase.yaml b/tests/net/socket/socketpair/testcase.yaml index d2b4462ce2d..5410f938376 100644 --- a/tests/net/socket/socketpair/testcase.yaml +++ b/tests/net/socket/socketpair/testcase.yaml @@ -9,9 +9,9 @@ tests: net.socket.socketpair: platform_exclude: vmu_rt1170 mimxrt1160_evk_cm7 # See #61246 net.socket.socketpair.newlib: - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED extra_configs: - - CONFIG_NEWLIB_LIBC=y + - CONFIG_REQUIRES_FULL_LIBC=y platform_exclude: vmu_rt1170 mimxrt1160_evk_cm7 # See #61246 net.socket.socketpair.picolibc: filter: CONFIG_PICOLIBC_SUPPORTED diff --git a/tests/net/socket/tcp/prj.conf b/tests/net/socket/tcp/prj.conf index 45695703542..9f9534aec4c 100644 --- a/tests/net/socket/tcp/prj.conf +++ b/tests/net/socket/tcp/prj.conf @@ -2,7 +2,7 @@ CONFIG_NET_TEST=y # General config -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y # Networking config CONFIG_NETWORKING=y @@ -40,7 +40,6 @@ CONFIG_NET_TCP_RETRY_COUNT=3 CONFIG_NET_TCP_INIT_RETRANSMISSION_TIMEOUT=120 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=2048 CONFIG_NET_CONTEXT_RCVTIMEO=y diff --git a/tests/net/socket/tcp/src/main.c b/tests/net/socket/tcp/src/main.c index 38ba5ae81ad..c96ecb029a2 100644 --- a/tests/net/socket/tcp/src/main.c +++ b/tests/net/socket/tcp/src/main.c @@ -31,21 +31,21 @@ static void test_bind(int sock, struct sockaddr *addr, socklen_t addrlen) { zassert_equal(bind(sock, addr, addrlen), 0, - "bind failed"); + "bind failed with error %d", errno); } static void test_listen(int sock) { zassert_equal(listen(sock, MAX_CONNS), 0, - "listen failed"); + "listen failed with error %d", errno); } static void test_connect(int sock, struct sockaddr *addr, socklen_t addrlen) { zassert_equal(connect(sock, addr, addrlen), 0, - "connect failed"); + "connect failed with error %d", errno); if (IS_ENABLED(CONFIG_NET_TC_THREAD_PREEMPTIVE)) { /* Let the connection proceed */ @@ -554,6 +554,8 @@ ZTEST(net_socket_tcp, test_v4_broken_link) test_close(s_sock); restore_packet_loss_ratio(); + + k_sleep(TCP_TEARDOWN_TIMEOUT); } ZTEST_USER(net_socket_tcp, test_v4_sendto_recvfrom) @@ -931,11 +933,18 @@ ZTEST(net_socket_tcp, test_connect_timeout) test_close(c_sock); + /* If we have preemptive option set, then sleep here in order to allow + * other part of the system to run and update itself. + */ + if (IS_ENABLED(CONFIG_NET_TC_THREAD_PREEMPTIVE)) { + k_sleep(K_MSEC(10)); + } + /* After the client socket closing, the context count should be 0 */ net_context_foreach(calc_net_context, &count_after); zassert_equal(count_after, 0, - "net_context still in use"); + "net_context %d still in use", count_after); restore_packet_loss_ratio(); } @@ -2066,6 +2075,138 @@ ZTEST(net_socket_tcp, test_ioctl_fionread_v6) test_ioctl_fionread_common(AF_INET6); } +/* Connect to peer which is not listening the test port and + * make sure select() returns proper error for the closed + * connection. + */ +ZTEST(net_socket_tcp, test_connect_and_wait_for_v4_select) +{ + struct sockaddr_in addr = { 0 }; + struct in_addr v4addr; + int fd, flags, ret, optval; + socklen_t optlen = sizeof(optval); + + fd = socket(AF_INET, SOCK_STREAM, 0); + + flags = fcntl(fd, F_GETFL, 0); + fcntl(fd, F_SETFL, flags | O_NONBLOCK); + + inet_pton(AF_INET, "127.0.0.1", (void *)&v4addr); + + addr.sin_family = AF_INET; + net_ipaddr_copy(&addr.sin_addr, &v4addr); + + /* There should be nobody serving this port */ + addr.sin_port = htons(8088); + + ret = connect(fd, (const struct sockaddr *)&addr, sizeof(addr)); + zassert_equal(ret, -1, "connect succeed, %d", errno); + zassert_equal(errno, EINPROGRESS, "connect succeed, %d", errno); + + /* Wait for the connection (this should fail eventually) */ + while (1) { + fd_set wfds; + struct timeval tv = { + .tv_sec = 1, + .tv_usec = 0 + }; + + FD_ZERO(&wfds); + FD_SET(fd, &wfds); + + /* Check if the connection is there, this should timeout */ + ret = select(fd + 1, NULL, &wfds, NULL, &tv); + if (ret < 0) { + break; + } + + if (ret > 0) { + if (FD_ISSET(fd, &wfds)) { + break; + } + } + } + + zassert_true(ret > 0, "select failed, %d", errno); + + /* Get the reason for the connect */ + ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &optval, &optlen); + zassert_equal(ret, 0, "getsockopt failed, %d", errno); + + /* If SO_ERROR is 0, then it means that connect succeed. Any + * other value (errno) means that it failed. + */ + zassert_equal(optval, ECONNREFUSED, "unexpected connect status, %d", optval); + + ret = close(fd); + zassert_equal(ret, 0, "close failed, %d", errno); +} + +/* Connect to peer which is not listening the test port and + * make sure poll() returns proper error for the closed + * connection. + */ +ZTEST(net_socket_tcp, test_connect_and_wait_for_v4_poll) +{ + struct sockaddr_in addr = { 0 }; + struct pollfd fds[1]; + struct in_addr v4addr; + int fd, flags, ret, optval; + bool closed = false; + socklen_t optlen = sizeof(optval); + + fd = socket(AF_INET, SOCK_STREAM, 0); + + flags = fcntl(fd, F_GETFL, 0); + fcntl(fd, F_SETFL, flags | O_NONBLOCK); + + inet_pton(AF_INET, "127.0.0.1", (void *)&v4addr); + + addr.sin_family = AF_INET; + net_ipaddr_copy(&addr.sin_addr, &v4addr); + + /* There should be nobody serving this port */ + addr.sin_port = htons(8088); + + ret = connect(fd, (const struct sockaddr *)&addr, sizeof(addr)); + zassert_equal(ret, -1, "connect succeed, %d", errno); + zassert_equal(errno, EINPROGRESS, "connect succeed, %d", errno); + + /* Wait for the connection (this should fail eventually) */ + while (1) { + memset(fds, 0, sizeof(fds)); + fds[0].fd = fd; + fds[0].events = POLLOUT; + + /* Check if the connection is there, this should timeout */ + ret = poll(fds, 1, 10); + if (ret < 0) { + break; + } + + if (fds[0].revents > 0) { + if (fds[0].revents & POLLERR) { + closed = true; + break; + } + } + } + + zassert_true(closed, "poll failed, %d", errno); + + /* Get the reason for the connect */ + ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &optval, &optlen); + zassert_equal(ret, 0, "getsockopt failed, %d", errno); + + /* If SO_ERROR is 0, then it means that connect succeed. Any + * other value (errno) means that it failed. + */ + zassert_equal(optval, ECONNREFUSED, "unexpected connect status, %d", optval); + + ret = close(fd); + zassert_equal(ret, 0, "close failed, %d", errno); +} + static void after(void *arg) { ARG_UNUSED(arg); diff --git a/tests/net/socket/tcp/testcase.yaml b/tests/net/socket/tcp/testcase.yaml index 37158751cae..cff7591d938 100644 --- a/tests/net/socket/tcp/testcase.yaml +++ b/tests/net/socket/tcp/testcase.yaml @@ -5,7 +5,7 @@ common: - net - socket - userspace - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED timeout: 180 # FIXME: This test fails very frequently on mps2_an385 due to the system # timer stability issues, so keep it disabled until the root cause diff --git a/tests/net/socket/tls/prj.conf b/tests/net/socket/tls/prj.conf index 6186a518624..d67e0a2d5f8 100644 --- a/tests/net/socket/tls/prj.conf +++ b/tests/net/socket/tls/prj.conf @@ -3,7 +3,7 @@ CONFIG_SMP=n CONFIG_NET_TEST=y # General config -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y # Networking config CONFIG_NETWORKING=y @@ -36,9 +36,8 @@ CONFIG_NET_BUF_TX_COUNT=32 CONFIG_NET_BUF_RX_COUNT=32 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=3072 CONFIG_MBEDTLS_ENABLE_HEAP=y -CONFIG_MBEDTLS_HEAP_SIZE=16000 +CONFIG_MBEDTLS_HEAP_SIZE=18000 CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED=y diff --git a/tests/net/socket/tls/testcase.yaml b/tests/net/socket/tls/testcase.yaml index 6554fed5cb5..fd9d615335d 100644 --- a/tests/net/socket/tls/testcase.yaml +++ b/tests/net/socket/tls/testcase.yaml @@ -6,7 +6,7 @@ common: - net - socket - tls - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED integration_platforms: - qemu_x86 tests: diff --git a/tests/net/socket/tls_ext/prj.conf b/tests/net/socket/tls_ext/prj.conf index 5d8e65e8c70..b2e360bb4db 100644 --- a/tests/net/socket/tls_ext/prj.conf +++ b/tests/net/socket/tls_ext/prj.conf @@ -1,7 +1,6 @@ # General config CONFIG_SMP=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y # Networking config CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/net/socket/udp/prj.conf b/tests/net/socket/udp/prj.conf index e80eafaed3f..4f7779fd049 100644 --- a/tests/net/socket/udp/prj.conf +++ b/tests/net/socket/udp/prj.conf @@ -1,5 +1,5 @@ # General config -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y # Networking config CONFIG_NETWORKING=y @@ -24,7 +24,6 @@ CONFIG_MAIN_STACK_SIZE=2048 CONFIG_HEAP_MEM_POOL_SIZE=256 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NET_TEST=y CONFIG_TEST_USERSPACE=y diff --git a/tests/net/socket/udp/src/main.c b/tests/net/socket/udp/src/main.c index 310f130d5d8..31c1fba43f5 100644 --- a/tests/net/socket/udp/src/main.c +++ b/tests/net/socket/udp/src/main.c @@ -974,7 +974,7 @@ static int eth_fake_send(const struct device *dev, struct net_pkt *pkt) return 0; } - txtime = net_ptp_time_to_ns(net_pkt_timestamp(pkt)); + txtime = net_pkt_timestamp_ns(pkt); if (txtime != TEST_TXTIME) { test_failed = true; } else { diff --git a/tests/net/socket/udp/testcase.yaml b/tests/net/socket/udp/testcase.yaml index 16b3ec9cdb2..253d5698b21 100644 --- a/tests/net/socket/udp/testcase.yaml +++ b/tests/net/socket/udp/testcase.yaml @@ -5,7 +5,7 @@ common: - socket - udp min_ram: 21 - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED tests: net.socket.udp: extra_configs: diff --git a/tests/net/socket/websocket/prj.conf b/tests/net/socket/websocket/prj.conf index 65058f79843..edf128a7df0 100644 --- a/tests/net/socket/websocket/prj.conf +++ b/tests/net/socket/websocket/prj.conf @@ -32,5 +32,4 @@ CONFIG_HEAP_MEM_POOL_SIZE=1500 # Test options CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=2048 diff --git a/tests/net/tcp/prj.conf b/tests/net/tcp/prj.conf index 810ce77b545..86f972f043d 100644 --- a/tests/net/tcp/prj.conf +++ b/tests/net/tcp/prj.conf @@ -36,7 +36,6 @@ CONFIG_NET_IPV6_NBR_CACHE=n CONFIG_NET_IPV6_MLD=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=3072 CONFIG_HEAP_MEM_POOL_SIZE=8192 diff --git a/tests/net/tcp/src/main.c b/tests/net/tcp/src/main.c index e076f0d8a47..aafa3937ce0 100644 --- a/tests/net/tcp/src/main.c +++ b/tests/net/tcp/src/main.c @@ -111,7 +111,8 @@ enum test_state { T_FIN_ACK, T_FIN_1, T_FIN_2, - T_CLOSING + T_CLOSING, + T_RST, }; static enum test_state t_state; @@ -124,11 +125,15 @@ static int tester_send(const struct device *dev, struct net_pkt *pkt); static void handle_client_test(sa_family_t af, struct tcphdr *th); static void handle_server_test(sa_family_t af, struct tcphdr *th); static void handle_syn_resend(void); +static void handle_syn_rst_ack(sa_family_t af, struct tcphdr *th); static void handle_client_fin_wait_2_test(sa_family_t af, struct tcphdr *th); static void handle_client_closing_test(sa_family_t af, struct tcphdr *th); static void handle_data_fin1_test(sa_family_t af, struct tcphdr *th); static void handle_data_during_fin1_test(sa_family_t af, struct tcphdr *th); static void handle_server_recv_out_of_order(struct net_pkt *pkt); +static void handle_server_rst_on_closed_port(sa_family_t af, struct tcphdr *th); +static void handle_server_rst_on_listening_port(sa_family_t af, struct tcphdr *th); +static void handle_syn_invalid_ack(sa_family_t af, struct tcphdr *th); static void verify_flags(struct tcphdr *th, uint8_t flags, const char *fun, int line) @@ -333,6 +338,13 @@ static struct net_pkt *prepare_syn_ack_packet(sa_family_t af, uint16_t src_port, NULL, 0U); } +static struct net_pkt *prepare_rst_ack_packet(sa_family_t af, uint16_t src_port, + uint16_t dst_port) +{ + return tester_prepare_tcp_pkt(af, src_port, dst_port, RST | ACK, + NULL, 0U); +} + static struct net_pkt *prepare_ack_packet(sa_family_t af, uint16_t src_port, uint16_t dst_port) { @@ -367,6 +379,15 @@ static struct net_pkt *prepare_rst_packet(sa_family_t af, uint16_t src_port, return tester_prepare_tcp_pkt(af, src_port, dst_port, RST, NULL, 0U); } +static bool is_icmp_pkt(struct net_pkt *pkt) +{ + if (net_pkt_family(pkt) == AF_INET) { + return NET_IPV4_HDR(pkt)->proto == IPPROTO_ICMP; + } else { + return NET_IPV6_HDR(pkt)->nexthdr == IPPROTO_ICMPV6; + } +} + static int read_tcp_header(struct net_pkt *pkt, struct tcphdr *th) { int ret; @@ -397,6 +418,11 @@ static int tester_send(const struct device *dev, struct net_pkt *pkt) struct tcphdr th; int ret; + /* Ignore ICMP explicitly */ + if (is_icmp_pkt(pkt)) { + return 0; + } + ret = read_tcp_header(pkt, &th); if (ret < 0) { goto fail; @@ -430,6 +456,19 @@ static int tester_send(const struct device *dev, struct net_pkt *pkt) case 11: handle_data_during_fin1_test(net_pkt_family(pkt), &th); break; + case 12: + handle_syn_rst_ack(net_pkt_family(pkt), &th); + break; + case 13: + handle_server_rst_on_closed_port(net_pkt_family(pkt), &th); + break; + case 14: + handle_server_rst_on_listening_port(net_pkt_family(pkt), &th); + break; + case 15: + handle_syn_invalid_ack(net_pkt_family(pkt), &th); + break; + default: zassert_true(false, "Undefined test case"); } @@ -703,7 +742,8 @@ static void handle_server_test(sa_family_t af, struct tcphdr *th) static void test_server_timeout(struct k_work *work) { - if (test_case_no == 3 || test_case_no == 4) { + if (test_case_no == 3 || test_case_no == 4 || test_case_no == 13 || + test_case_no == 14) { handle_server_test(AF_INET, NULL); } else if (test_case_no == 5) { handle_server_test(AF_INET6, NULL); @@ -1003,6 +1043,68 @@ ZTEST(net_tcp, test_client_syn_resend) net_context_put(ctx); } +static void handle_syn_rst_ack(sa_family_t af, struct tcphdr *th) +{ + struct net_pkt *reply; + int ret; + + switch (t_state) { + case T_SYN: + test_verify_flags(th, SYN); + seq = 0U; + ack = ntohl(th->th_seq) + 1U; + reply = prepare_rst_ack_packet(af, htons(MY_PORT), + th->th_sport); + t_state = T_CLOSING; + break; + default: + return; + } + + ret = net_recv_data(net_iface, reply); + if (ret < 0) { + goto fail; + } + + return; +fail: + zassert_true(false, "%s failed", __func__); +} + +/* Test case scenario IPv4 + * send SYN, + * peer replies RST+ACK, + * net_context_connect should report an error + */ +ZTEST(net_tcp, test_client_syn_rst_ack) +{ + struct net_context *ctx; + int ret; + + t_state = T_SYN; + test_case_no = 12; + seq = ack = 0; + + ret = net_context_get(AF_INET, SOCK_STREAM, IPPROTO_TCP, &ctx); + if (ret < 0) { + zassert_true(false, "Failed to get net_context"); + } + + net_context_ref(ctx); + + ret = net_context_connect(ctx, (struct sockaddr *)&peer_addr_s, + sizeof(struct sockaddr_in), + NULL, + K_MSEC(1000), NULL); + + zassert_true(ret < 0, "Connect successful on RST+ACK"); + zassert_not_equal(net_context_get_state(ctx), NET_CONTEXT_CONNECTED, + "Context should not be connected"); + + net_context_put(ctx); +} + + static void handle_client_fin_wait_2_test(sa_family_t af, struct tcphdr *th) { struct net_pkt *reply; @@ -1811,4 +1913,218 @@ ZTEST(net_tcp, test_server_out_of_order_data) test_server_timeout_out_of_order_data(); } +static void handle_server_rst_on_closed_port(sa_family_t af, struct tcphdr *th) +{ + switch (t_state) { + case T_SYN_ACK: + /* Port was closed so expect RST instead of SYN */ + test_verify_flags(th, RST | ACK); + zassert_equal(ntohl(th->th_seq), 0, "Invalid SEQ value"); + zassert_equal(ntohl(th->th_ack), seq, "Invalid ACK value"); + t_state = T_CLOSING; + test_sem_give(); + break; + default: + return; + } +} + +/* Test case scenario + * Send SYN + * expect RST ACK (closed port) + * any failures cause test case to fail. + */ +ZTEST(net_tcp, test_server_rst_on_closed_port) +{ + t_state = T_SYN; + test_case_no = 13; + seq = ack = 0; + + k_sem_reset(&test_sem); + + /* Trigger the peer to send SYN */ + k_work_reschedule(&test_server, K_NO_WAIT); + + /* Peer will release the semaphore after it receives RST */ + test_sem_take(K_MSEC(100), __LINE__); +} + +static void handle_server_rst_on_listening_port(sa_family_t af, struct tcphdr *th) +{ + switch (t_state) { + case T_DATA_ACK: + /* No active connection so expect RST instead of ACK */ + test_verify_flags(th, RST); + zassert_equal(ntohl(th->th_seq), ack, "Invalid SEQ value"); + t_state = T_CLOSING; + test_sem_give(); + break; + default: + return; + } +} + +static void dummy_accept_cb(struct net_context *ctx, struct sockaddr *addr, + socklen_t addrlen, int status, void *user_data) +{ + /* Should not ever be called. */ + zassert_unreachable("Should not have called dummy accept cb"); +} + +/* Test case scenario + * Open listening port + * Send DATA packet to the listening port + * expect RST (no matching connection) + * any failures cause test case to fail. + */ +ZTEST(net_tcp, test_server_rst_on_listening_port_no_active_connection) +{ + struct net_context *ctx; + int ret; + + t_state = T_DATA; + test_case_no = 14; + seq = ack = 200; + + k_sem_reset(&test_sem); + + ret = net_context_get(AF_INET, SOCK_STREAM, IPPROTO_TCP, &ctx); + if (ret < 0) { + zassert_true(false, "Failed to get net_context"); + } + + net_context_ref(ctx); + + ret = net_context_bind(ctx, (struct sockaddr *)&my_addr_s, + sizeof(struct sockaddr_in)); + if (ret < 0) { + zassert_true(false, "Failed to bind net_context"); + } + + ret = net_context_listen(ctx, 1); + if (ret < 0) { + zassert_true(false, "Failed to listen on net_context"); + } + + ret = net_context_accept(ctx, dummy_accept_cb, K_NO_WAIT, NULL); + if (ret < 0) { + zassert_true(false, "Failed to set accept on net_context"); + } + + /* Trigger the peer to send data to the listening port w/o active connection */ + k_work_reschedule(&test_server, K_NO_WAIT); + + /* Peer will release the semaphore after it receives RST */ + test_sem_take(K_MSEC(100), __LINE__); + + net_context_put(ctx); +} + +/* Test case scenario + * Expect SYN + * Send ACK (wrong ACK number), + * expect RST, + * expect SYN (retransmission), + * send SYN ACK, + * expect ACK (handshake success), + * expect FIN, + * send FIN ACK, + * expect ACK. + * any failures cause test case to fail. + */ +static void handle_syn_invalid_ack(sa_family_t af, struct tcphdr *th) +{ + static bool invalid_ack = true; + struct net_pkt *reply; + int ret; + + + switch (t_state) { + case T_SYN: + test_verify_flags(th, SYN); + if (invalid_ack) { + ack = ntohl(th->th_seq) + 1000U; + reply = prepare_ack_packet(af, htons(MY_PORT), + th->th_sport); + /* Expect RST now. */ + t_state = T_RST; + invalid_ack = false; + } else { + ack = ntohl(th->th_seq) + 1U; + reply = prepare_syn_ack_packet(af, htons(MY_PORT), + th->th_sport); + /* Proceed with the handshake on second attempt. */ + t_state = T_SYN_ACK; + } + + break; + case T_SYN_ACK: + test_verify_flags(th, ACK); + /* connection is successful */ + t_state = T_FIN; + return; + case T_FIN: + test_verify_flags(th, FIN | ACK); + seq++; + ack++; + t_state = T_FIN_ACK; + reply = prepare_fin_ack_packet(af, htons(MY_PORT), + th->th_sport); + break; + case T_FIN_ACK: + test_verify_flags(th, ACK); + test_sem_give(); + return; + case T_RST: + test_verify_flags(th, RST); + zassert_equal(ntohl(th->th_seq), ack, "Invalid SEQ value"); + + /* Wait for SYN retransmission. */ + t_state = T_SYN; + return; + default: + return; + } + + ret = net_recv_data(net_iface, reply); + if (ret < 0) { + goto fail; + } + + return; +fail: + zassert_true(false, "%s failed", __func__); +} + +ZTEST(net_tcp, test_client_rst_on_unexpected_ack_on_syn) +{ + struct net_context *ctx; + int ret; + + t_state = T_SYN; + test_case_no = 15; + seq = ack = 0; + + ret = net_context_get(AF_INET, SOCK_STREAM, IPPROTO_TCP, &ctx); + if (ret < 0) { + zassert_true(false, "Failed to get net_context"); + } + + net_context_ref(ctx); + + ret = net_context_connect(ctx, (struct sockaddr *)&peer_addr_s, + sizeof(struct sockaddr_in), + NULL, K_MSEC(1000), NULL); + + zassert_equal(ret, 0, "Connect failed"); + zassert_equal(net_context_get_state(ctx), NET_CONTEXT_CONNECTED, + "Context should be connected"); + + /* Just wait for the connection teardown. */ + net_context_put(ctx); + + /* Peer will release the semaphore after it receives final ACK */ + test_sem_take(K_MSEC(100), __LINE__); +} + ZTEST_SUITE(net_tcp, NULL, presetup, NULL, NULL, NULL); diff --git a/tests/net/traffic_class/prj.conf b/tests/net/traffic_class/prj.conf index 6da597ef366..41ff756bdf9 100644 --- a/tests/net/traffic_class/prj.conf +++ b/tests/net/traffic_class/prj.conf @@ -27,6 +27,5 @@ CONFIG_NET_CONTEXT_PRIORITY=y CONFIG_NET_TC_TX_COUNT=8 CONFIG_NET_TC_RX_COUNT=8 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NET_CONFIG_SETTINGS=n CONFIG_NET_SHELL=n diff --git a/tests/net/traffic_class/src/main.c b/tests/net/traffic_class/src/main.c index b48bb3db166..6187e124401 100644 --- a/tests/net/traffic_class/src/main.c +++ b/tests/net/traffic_class/src/main.c @@ -18,7 +18,7 @@ LOG_MODULE_REGISTER(net_test, NET_LOG_LEVEL); #include #include #include -#include +#include #include diff --git a/tests/net/traffic_class/testcase.yaml b/tests/net/traffic_class/testcase.yaml index b8a56acbb27..a69fe29edcb 100644 --- a/tests/net/traffic_class/testcase.yaml +++ b/tests/net/traffic_class/testcase.yaml @@ -2,8 +2,10 @@ common: platform_allow: - native_posix - native_posix_64 + - native_sim + - native_sim_64 integration_platforms: - - native_posix_64 + - native_sim_64 tags: - net - traffic_class diff --git a/tests/net/trickle/prj.conf b/tests/net/trickle/prj.conf index 1066b87eb6a..267aa020c0c 100644 --- a/tests/net/trickle/prj.conf +++ b/tests/net/trickle/prj.conf @@ -15,7 +15,6 @@ CONFIG_NET_BUF_RX_COUNT=5 CONFIG_NET_BUF_TX_COUNT=5 CONFIG_NET_TRICKLE=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=1024 CONFIG_NET_DRIVERS=y CONFIG_NET_LOOPBACK=y diff --git a/tests/net/tx_timestamp/prj.conf b/tests/net/tx_timestamp/prj.conf index e739c0688ed..7f028d9390a 100644 --- a/tests/net/tx_timestamp/prj.conf +++ b/tests/net/tx_timestamp/prj.conf @@ -23,4 +23,3 @@ CONFIG_NET_CONFIG_SETTINGS=n CONFIG_NET_SHELL=n CONFIG_NET_PKT_TIMESTAMP=y CONFIG_NET_PKT_TIMESTAMP_THREAD=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/net/tx_timestamp/src/main.c b/tests/net/tx_timestamp/src/main.c index c07bbb3246e..13561c53730 100644 --- a/tests/net/tx_timestamp/src/main.c +++ b/tests/net/tx_timestamp/src/main.c @@ -18,7 +18,7 @@ LOG_MODULE_REGISTER(net_test, NET_LOG_LEVEL); #include #include #include -#include +#include #include diff --git a/tests/net/udp/prj.conf b/tests/net/udp/prj.conf index a70f51e23e5..3782275cca8 100644 --- a/tests/net/udp/prj.conf +++ b/tests/net/udp/prj.conf @@ -23,4 +23,3 @@ CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=2 # Turn off UDP checksum checking as the test fails otherwise. CONFIG_NET_UDP_CHECKSUM=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/net/udp/src/main.c b/tests/net/udp/src/main.c index 0457d38828a..0de851fffff 100644 --- a/tests/net/udp/src/main.c +++ b/tests/net/udp/src/main.c @@ -29,7 +29,7 @@ LOG_MODULE_REGISTER(net_test, NET_LOG_LEVEL); #include #include #include -#include +#include #include "ipv4.h" #include "ipv6.h" diff --git a/tests/net/utils/prj.conf b/tests/net/utils/prj.conf index 404cfcdb48a..f63c6c8f05d 100644 --- a/tests/net/utils/prj.conf +++ b/tests/net/utils/prj.conf @@ -17,4 +17,3 @@ CONFIG_NET_UDP=y CONFIG_ZTEST=y CONFIG_MAIN_STACK_SIZE=1280 CONFIG_TEST_USERSPACE=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/net/virtual/prj.conf b/tests/net/virtual/prj.conf index d9279fa4f8a..76683036a53 100644 --- a/tests/net/virtual/prj.conf +++ b/tests/net/virtual/prj.conf @@ -41,6 +41,5 @@ CONFIG_NET_IF_MAX_IPV6_COUNT=6 CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6 CONFIG_NET_IPV6_ND=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NET_CONFIG_SETTINGS=n CONFIG_NET_SHELL=n diff --git a/tests/net/virtual/src/main.c b/tests/net/virtual/src/main.c index 9d9cef4ec99..be0ba1715b6 100644 --- a/tests/net/virtual/src/main.c +++ b/tests/net/virtual/src/main.c @@ -17,7 +17,7 @@ LOG_MODULE_REGISTER(net_test, NET_LOG_LEVEL); #include #include #include -#include +#include #include diff --git a/tests/net/vlan/prj.conf b/tests/net/vlan/prj.conf index 92f107cd131..48fa390cded 100644 --- a/tests/net/vlan/prj.conf +++ b/tests/net/vlan/prj.conf @@ -23,7 +23,6 @@ CONFIG_NET_VLAN=y CONFIG_NET_VLAN_COUNT=4 CONFIG_NET_CONTEXT_PRIORITY=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_NET_CONFIG_SETTINGS=n CONFIG_NET_SHELL=n diff --git a/tests/net/vlan/src/main.c b/tests/net/vlan/src/main.c index 9ada9ff5b84..cfcab203193 100644 --- a/tests/net/vlan/src/main.c +++ b/tests/net/vlan/src/main.c @@ -18,7 +18,7 @@ LOG_MODULE_REGISTER(net_test, NET_LOG_LEVEL); #include #include #include -#include +#include #include diff --git a/tests/net/wifi/wifi_nm/prj.conf b/tests/net/wifi/wifi_nm/prj.conf index abeb08fca4f..aab25c2a734 100644 --- a/tests/net/wifi/wifi_nm/prj.conf +++ b/tests/net/wifi/wifi_nm/prj.conf @@ -12,7 +12,6 @@ CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y # Disable internal ethernet drivers as the test is self contained # and does not need the on board driver to function. diff --git a/tests/net/wifi/wifi_nm/src/main.c b/tests/net/wifi/wifi_nm/src/main.c index 0ca9e633553..43fcee530ec 100644 --- a/tests/net/wifi/wifi_nm/src/main.c +++ b/tests/net/wifi/wifi_nm/src/main.c @@ -18,7 +18,7 @@ LOG_MODULE_REGISTER(net_test, NET_LOG_LEVEL); #include #include #include -#include +#include #include diff --git a/tests/posix/common/prj.conf b/tests/posix/common/prj.conf index a1904b507d0..6c0b9153b6a 100644 --- a/tests/posix/common/prj.conf +++ b/tests/posix/common/prj.conf @@ -2,10 +2,12 @@ CONFIG_PTHREAD_IPC=y CONFIG_POSIX_API=y CONFIG_MAX_PTHREAD_COUNT=10 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SEM_VALUE_MAX=32767 CONFIG_POSIX_MQUEUE=y CONFIG_HEAP_MEM_POOL_SIZE=4096 CONFIG_MAX_THREAD_BYTES=4 CONFIG_THREAD_NAME=y CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_DYNAMIC_THREAD=y +CONFIG_THREAD_STACK_INFO=y +CONFIG_DYNAMIC_THREAD_POOL_SIZE=4 diff --git a/tests/posix/common/src/_main.c b/tests/posix/common/src/_main.c index 264b2e403fd..cfec4adbd44 100644 --- a/tests/posix/common/src/_main.c +++ b/tests/posix/common/src/_main.c @@ -4,8 +4,18 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include - #include -ZTEST_SUITE(posix_apis, NULL, NULL, NULL, NULL, NULL); +extern bool fdtable_fd_is_initialized(int fd); + +static void *setup(void) +{ + /* ensure that the the stdin, stdout, and stderr fdtable entries are initialized */ + zassert_true(fdtable_fd_is_initialized(0)); + zassert_true(fdtable_fd_is_initialized(1)); + zassert_true(fdtable_fd_is_initialized(2)); + + return NULL; +} + +ZTEST_SUITE(posix_apis, NULL, setup, NULL, NULL, NULL); diff --git a/tests/posix/common/src/nanosleep.c b/tests/posix/common/src/nanosleep.c index 5e4d3bcf88d..7820f823eb0 100644 --- a/tests/posix/common/src/nanosleep.c +++ b/tests/posix/common/src/nanosleep.c @@ -23,6 +23,15 @@ static inline int select_nanosleep(int selection, clockid_t clock_id, int flags, return clock_nanosleep(clock_id, flags, rqtp, rmtp); } +static inline uint64_t cycle_get_64(void) +{ + if (IS_ENABLED(CONFIG_TIMER_HAS_64BIT_CYCLE_COUNTER)) { + return k_cycle_get_64(); + } else { + return k_cycle_get_32(); + } +} + static void common_errors(int selection, clockid_t clock_id, int flags) { struct timespec rem = {}; @@ -120,21 +129,37 @@ ZTEST(posix_apis, test_clock_nanosleep_errors_errno) zassert_equal(rem.tv_nsec, 0, "actual: %d expected: %d", rem.tv_nsec, 0); } +/** + * @brief Check that a call to nanosleep has yielded executiuon for some minimum time. + * + * Check that the actual time slept is >= the total time specified by @p s (in seconds) and + * @p ns (in nanoseconds). + * + * @note The time specified by @p s and @p ns is assumed to be absolute (i.e. a time-point) + * when @p selection is set to @ref SELECT_CLOCK_NANOSLEEP. The time is assumed to be relative + * when @p selection is set to @ref SELECT_NANOSLEEP. + * + * @param selection Either @ref SELECT_CLOCK_NANOSLEEP or @ref SELECT_NANOSLEEP + * @param clock_id The clock to test (e.g. @ref CLOCK_MONOTONIC or @ref CLOCK_REALTIME) + * @param flags Flags to pass to @ref clock_nanosleep + * @param s Partial lower bound for yielded time (in seconds) + * @param ns Partial lower bound for yielded time (in nanoseconds) + */ static void common_lower_bound_check(int selection, clockid_t clock_id, int flags, const uint32_t s, uint32_t ns) { int r; uint64_t actual_ns; uint64_t exp_ns; - uint32_t now; - uint32_t then; + uint64_t now; + uint64_t then; struct timespec rem = {0, 0}; struct timespec req = {s, ns}; errno = 0; - then = k_cycle_get_32(); + then = cycle_get_64(); r = select_nanosleep(selection, clock_id, flags, &req, &rem); - now = k_cycle_get_32(); + now = cycle_get_64(); zassert_equal(r, 0, "actual: %d expected: %d", r, 0); zassert_equal(errno, 0, "actual: %d expected: %d", errno, 0); @@ -143,14 +168,34 @@ static void common_lower_bound_check(int selection, clockid_t clock_id, int flag zassert_equal(rem.tv_sec, 0, "actual: %d expected: %d", rem.tv_sec, 0); zassert_equal(rem.tv_nsec, 0, "actual: %d expected: %d", rem.tv_nsec, 0); - actual_ns = k_cyc_to_ns_ceil64((now - then * selection)); + switch (selection) { + case SELECT_NANOSLEEP: + /* exp_ns and actual_ns are relative (i.e. durations) */ + actual_ns = k_cyc_to_ns_ceil64(now + then); + break; + case SELECT_CLOCK_NANOSLEEP: + /* exp_ns and actual_ns are absolute (i.e. time-points) */ + actual_ns = k_cyc_to_ns_ceil64(now); + break; + default: + zassert_unreachable(); + break; + } exp_ns = (uint64_t)s * NSEC_PER_SEC + ns; /* round up to the nearest microsecond for k_busy_wait() */ exp_ns = DIV_ROUND_UP(exp_ns, NSEC_PER_USEC) * NSEC_PER_USEC; + /* The comparison may be incorrect if counter wrap happened. In case of ARC HSDK platforms + * we have high counter clock frequency (500MHz or 1GHz) so counter wrap quite likely to + * happen if we wait long enough. As in some test cases we wait more than 1 second, there + * are significant chances to get false-positive assertion. + * TODO: switch test for k_cycle_get_64 usage where available. + */ +#if !defined(CONFIG_SOC_ARC_HSDK) && !defined(CONFIG_SOC_ARC_HSDK4XD) /* lower bounds check */ zassert_true(actual_ns >= exp_ns, "actual: %llu expected: %llu", actual_ns, exp_ns); +#endif /* TODO: Upper bounds check when hr timers are available */ } diff --git a/tests/posix/common/src/timer.c b/tests/posix/common/src/timer.c index 0b5f07f8fb9..1a1f7e718de 100644 --- a/tests/posix/common/src/timer.c +++ b/tests/posix/common/src/timer.c @@ -23,20 +23,25 @@ void handler(union sigval val) ++exp_count); } -ZTEST(posix_apis, test_timer) +void test_timer(int sigev_notify) { int ret; struct sigevent sig = { 0 }; timer_t timerid; struct itimerspec value, ovalue; struct timespec ts, te; - int64_t nsecs_elapsed, secs_elapsed, total_secs_timer; + int64_t nsecs_elapsed, secs_elapsed; - sig.sigev_notify = SIGEV_SIGNAL; + exp_count = 0; + sig.sigev_notify = sigev_notify; sig.sigev_notify_function = handler; sig.sigev_value.sival_int = 20; - printk("POSIX timer test\n"); + if (sigev_notify == SIGEV_SIGNAL) + printk("POSIX timer test SIGEV_SIGNAL\n"); + else + printk("POSIX timer test SIGEV_THREAD\n"); + ret = timer_create(CLOCK_MONOTONIC, &sig, &timerid); /*TESTPOINT: Check if timer is created successfully*/ @@ -79,15 +84,21 @@ ZTEST(posix_apis, test_timer) secs_elapsed = (te.tv_sec - ts.tv_sec - 1); } - total_secs_timer = (value.it_value.tv_sec * NSEC_PER_SEC + - value.it_value.tv_nsec + (uint64_t) exp_count * - (value.it_interval.tv_sec * NSEC_PER_SEC + - value.it_interval.tv_nsec)) / NSEC_PER_SEC; - + uint64_t elapsed = secs_elapsed*NSEC_PER_SEC + nsecs_elapsed; + uint64_t first_sig = value.it_value.tv_sec * NSEC_PER_SEC + value.it_value.tv_nsec; + uint64_t sig_interval = value.it_interval.tv_sec * NSEC_PER_SEC + value.it_interval.tv_nsec; + int expected_signal_count = (elapsed - first_sig) / sig_interval + 1; /*TESTPOINT: Check if POSIX timer test passed*/ - zassert_equal(total_secs_timer, secs_elapsed, - "POSIX timer test has failed"); + zassert_within(exp_count, expected_signal_count, 1, + "POSIX timer test has failed %i != %i", + exp_count, expected_signal_count); +} + +ZTEST(posix_apis, test_timer) +{ + test_timer(SIGEV_SIGNAL); + test_timer(SIGEV_THREAD); } ZTEST(posix_apis, test_timer_overrun) diff --git a/tests/posix/common/testcase.yaml b/tests/posix/common/testcase.yaml index 949fd839f4c..cb48095c67c 100644 --- a/tests/posix/common/testcase.yaml +++ b/tests/posix/common/testcase.yaml @@ -2,7 +2,10 @@ common: filter: not (CONFIG_NATIVE_BUILD and CONFIG_EXTERNAL_LIBC) # FIXME: qemu_leon3 is excluded because of the alignment-related failure # reported in the GitHub issue zephyrproject-rtos/zephyr#48992. - platform_exclude: qemu_leon3 + platform_exclude: + - qemu_leon3 + - native_posix + - native_posix_64 tags: posix min_ram: 64 timeout: 240 @@ -23,6 +26,8 @@ tests: filter: TOOLCHAIN_HAS_NEWLIB == 1 extra_configs: - CONFIG_NEWLIB_LIBC=y + arch_exclude: + - posix integration_platforms: - qemu_x86 portability.posix.common.armclang_std_libc: @@ -50,6 +55,8 @@ tests: - lpcxpresso55s06 filter: TOOLCHAIN_HAS_NEWLIB == 1 and CONFIG_ARCH_HAS_THREAD_LOCAL_STORAGE and CONFIG_TOOLCHAIN_SUPPORTS_THREAD_LOCAL_STORAGE + arch_exclude: + - posix integration_platforms: - qemu_x86 extra_configs: diff --git a/tests/posix/eventfd/prj.conf b/tests/posix/eventfd/prj.conf index ac1dcf7c06a..4fcab370408 100644 --- a/tests/posix/eventfd/prj.conf +++ b/tests/posix/eventfd/prj.conf @@ -7,7 +7,6 @@ CONFIG_NET_SOCKETS=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_POSIX_API=y CONFIG_EVENTFD=y diff --git a/tests/posix/eventfd/src/blocking.c b/tests/posix/eventfd/src/blocking.c index 4c5ce5b982a..6ff4decd0c4 100644 --- a/tests/posix/eventfd/src/blocking.c +++ b/tests/posix/eventfd/src/blocking.c @@ -72,6 +72,7 @@ ZTEST_F(eventfd, test_unset_poll_event_block) } K_THREAD_STACK_DEFINE(thread_stack, CONFIG_TEST_STACK_SIZE); +static struct k_thread thread; static void thread_eventfd_read_42(void *arg1, void *arg2, void *arg3) { @@ -84,8 +85,6 @@ static void thread_eventfd_read_42(void *arg1, void *arg2, void *arg3) ZTEST_F(eventfd, test_read_then_write_block) { - struct k_thread thread; - k_thread_create(&thread, thread_stack, K_THREAD_STACK_SIZEOF(thread_stack), thread_eventfd_read_42, fixture, NULL, NULL, 0, 0, K_NO_WAIT); @@ -107,7 +106,6 @@ static void thread_eventfd_write(void *arg1, void *arg2, void *arg3) ZTEST_F(eventfd, test_write_while_pollin) { - struct k_thread thread; struct zsock_pollfd fds[] = { { .fd = fixture->fd, @@ -143,7 +141,6 @@ static void thread_eventfd_read(void *arg1, void *arg2, void *arg3) ZTEST_F(eventfd, test_read_while_pollout) { - struct k_thread thread; struct zsock_pollfd fds[] = { { .fd = fixture->fd, diff --git a/tests/posix/eventfd/src/stress.c b/tests/posix/eventfd/src/stress.c index f16f3c7f2df..40d55671521 100644 --- a/tests/posix/eventfd/src/stress.c +++ b/tests/posix/eventfd/src/stress.c @@ -78,6 +78,7 @@ static void th_fun(void *arg1, void *arg2, void *arg3) report += report_ms; } } + Z_SPIN_DELAY(10); } printk("avg: %zu %s/s\n", (size_t)((count[id] * MSEC_PER_SEC) / end_ms), msg[id]); diff --git a/tests/posix/fs/app.overlay b/tests/posix/fs/app.overlay new file mode 100644 index 00000000000..87ae21b1e64 --- /dev/null +++ b/tests/posix/fs/app.overlay @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + ramdisk0 { + compatible = "zephyr,ram-disk"; + disk-name = "RAM"; + sector-size = <512>; + sector-count = <160>; + }; +}; diff --git a/tests/posix/fs/prj.conf b/tests/posix/fs/prj.conf index 27758bc609e..bb6d36b836e 100644 --- a/tests/posix/fs/prj.conf +++ b/tests/posix/fs/prj.conf @@ -1,11 +1,8 @@ CONFIG_FILE_SYSTEM=y CONFIG_LOG=y CONFIG_FAT_FILESYSTEM_ELM=y -CONFIG_DISK_DRIVER_RAM=y -CONFIG_DISK_RAM_VOLUME_SIZE=80 CONFIG_POSIX_API=y CONFIG_POSIX_FS=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MAIN_STACK_SIZE=4096 CONFIG_EVENTFD=n diff --git a/tests/posix/fs/testcase.yaml b/tests/posix/fs/testcase.yaml index 9f3dec62cba..5274053dad4 100644 --- a/tests/posix/fs/testcase.yaml +++ b/tests/posix/fs/testcase.yaml @@ -2,6 +2,9 @@ common: filter: not (CONFIG_NATIVE_BUILD and CONFIG_EXTERNAL_LIBC) arch_exclude: - nios2 + platform_exclude: + - native_posix + - native_posix_64 tags: - posix - filesystem @@ -17,6 +20,8 @@ tests: - qemu_x86 portability.posix.fs.newlib: filter: TOOLCHAIN_HAS_NEWLIB == 1 + arch_exclude: + - posix extra_configs: - CONFIG_NEWLIB_LIBC=y integration_platforms: @@ -31,6 +36,8 @@ tests: portability.posix.fs.tls.newlib: filter: TOOLCHAIN_HAS_NEWLIB == 1 and CONFIG_ARCH_HAS_THREAD_LOCAL_STORAGE and CONFIG_TOOLCHAIN_SUPPORTS_THREAD_LOCAL_STORAGE + arch_exclude: + - posix extra_configs: - CONFIG_NEWLIB_LIBC=y - CONFIG_THREAD_LOCAL_STORAGE=y diff --git a/tests/posix/getopt/prj.conf b/tests/posix/getopt/prj.conf index bcf51234f2a..034ce191ddf 100644 --- a/tests/posix/getopt/prj.conf +++ b/tests/posix/getopt/prj.conf @@ -2,5 +2,4 @@ CONFIG_GETOPT=y CONFIG_GETOPT_LONG=y CONFIG_LOG=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_LOGGING_DEFAULTS=n diff --git a/tests/posix/getopt/src/main.c b/tests/posix/getopt/src/main.c index b18aee1569a..158d0dd085e 100644 --- a/tests/posix/getopt/src/main.c +++ b/tests/posix/getopt/src/main.c @@ -12,11 +12,7 @@ #include #include #include -#ifdef CONFIG_ARCH_POSIX -#include -#else #include -#endif #include ZTEST_SUITE(getopt_test_suite, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/posix/headers/prj.conf b/tests/posix/headers/prj.conf index 43b6bc147c4..e64b889585a 100644 --- a/tests/posix/headers/prj.conf +++ b/tests/posix/headers/prj.conf @@ -1,6 +1,5 @@ CONFIG_POSIX_API=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y # for POSIX_FS CONFIG_FILE_SYSTEM=y diff --git a/tests/posix/pthread_pressure/Kconfig b/tests/posix/pthread_pressure/Kconfig index 70154447d7b..2bbdfcc2110 100644 --- a/tests/posix/pthread_pressure/Kconfig +++ b/tests/posix/pthread_pressure/Kconfig @@ -6,8 +6,8 @@ source "Kconfig.zephyr" config TEST_NUM_CPUS int "Number of CPUs to use in parallel" - range 1 MP_NUM_CPUS - default MP_NUM_CPUS + range 1 MP_MAX_NUM_CPUS + default MP_MAX_NUM_CPUS help The number of parallel threads to run during the test. @@ -27,6 +27,7 @@ config TEST_DELAY_US config TEST_STACK_SIZE int "Size of each thread stack in this test" default 1024 if 64BIT + default 1024 if SPARC default 512 help The minimal stack size required to run a minimal thread. diff --git a/tests/posix/pthread_pressure/prj.conf b/tests/posix/pthread_pressure/prj.conf index 9499b191c2d..ba9a5f8487a 100644 --- a/tests/posix/pthread_pressure/prj.conf +++ b/tests/posix/pthread_pressure/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_POSIX_API=y ## Note: for benchmarking purposes, uncomment the Kconfig below diff --git a/tests/posix/pthread_pressure/src/main.c b/tests/posix/pthread_pressure/src/main.c index adab1ba7ff7..c7881de4e6f 100644 --- a/tests/posix/pthread_pressure/src/main.c +++ b/tests/posix/pthread_pressure/src/main.c @@ -122,6 +122,7 @@ static void test_create_join_common(const char *tag, create_fn create, join_fn j print_stats(now_ms, end_ms); } + Z_SPIN_DELAY(100); } while (end_ms > now_ms); print_stats(now_ms, end_ms); diff --git a/tests/posix/pthread_pressure/testcase.yaml b/tests/posix/pthread_pressure/testcase.yaml index 273757f73ab..73a8fa34e23 100644 --- a/tests/posix/pthread_pressure/testcase.yaml +++ b/tests/posix/pthread_pressure/testcase.yaml @@ -5,8 +5,6 @@ common: - posix integration_platforms: - qemu_riscv64_smp - platform_exclude: - - qemu_leon3 tests: portability.posix.pthread_pressure: extra_configs: diff --git a/tests/subsys/bindesc/definition/CMakeLists.txt b/tests/subsys/bindesc/definition/CMakeLists.txt new file mode 100644 index 00000000000..4a1a0136fed --- /dev/null +++ b/tests/subsys/bindesc/definition/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright 2023 Yonatan Schachter +# +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(bindesc) + +target_sources(app PRIVATE src/main.c) diff --git a/tests/subsys/bindesc/definition/prj.conf b/tests/subsys/bindesc/definition/prj.conf new file mode 100644 index 00000000000..80bd7e861c6 --- /dev/null +++ b/tests/subsys/bindesc/definition/prj.conf @@ -0,0 +1,11 @@ +# Copyright 2023 Yonatan Schachter +# +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_ZTEST=y + +CONFIG_BINDESC=y +CONFIG_BINDESC_DEFINE=y + +CONFIG_BINDESC_DEFINE_VERSION=y +CONFIG_BINDESC_KERNEL_VERSION_NUMBER=y diff --git a/tests/subsys/bindesc/definition/src/main.c b/tests/subsys/bindesc/definition/src/main.c new file mode 100644 index 00000000000..487fa186790 --- /dev/null +++ b/tests/subsys/bindesc/definition/src/main.c @@ -0,0 +1,49 @@ +/* + * Copyright 2023 Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#define STR_ID 1 +#define UINT_ID 2 +#define BYTES_ID 3 + +#define STR_DATA "Hello world!" +#define UINT_DATA 5 +#define BYTES_DATA {1, 2, 3, 4} + +BINDESC_STR_DEFINE(bindesc_string, STR_ID, STR_DATA); +BINDESC_UINT_DEFINE(bindesc_uint, UINT_ID, UINT_DATA); +BINDESC_BYTES_DEFINE(bindesc_bytes, BYTES_ID, (BYTES_DATA)); + +ZTEST(bindesc_define, test_version_number) +{ + zassert_equal(BINDESC_GET_UINT(kernel_version_number), KERNEL_VERSION_NUMBER, + "bindesc kernel version number is incorrect"); +} + +ZTEST(bindesc_define, test_custom_bindesc_str) +{ + zassert_equal(BINDESC_GET_SIZE(bindesc_string), sizeof(STR_DATA)); + zassert_mem_equal(BINDESC_GET_STR(bindesc_string), STR_DATA, sizeof(STR_DATA)); +} + +ZTEST(bindesc_define, test_custom_bindesc_uint) +{ + zassert_equal(BINDESC_GET_SIZE(bindesc_uint), 4); + zassert_equal(BINDESC_GET_UINT(bindesc_uint), UINT_DATA); +} + +ZTEST(bindesc_define, test_custom_bindesc_bytes) +{ + uint8_t expected_data[] = BYTES_DATA; + + zassert_equal(BINDESC_GET_SIZE(bindesc_bytes), 4); + zassert_mem_equal(BINDESC_GET_STR(bindesc_bytes), expected_data, 4); +} + +ZTEST_SUITE(bindesc_define, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/subsys/bindesc/definition/testcase.yaml b/tests/subsys/bindesc/definition/testcase.yaml new file mode 100644 index 00000000000..72ede27a059 --- /dev/null +++ b/tests/subsys/bindesc/definition/testcase.yaml @@ -0,0 +1,31 @@ +tests: + bindesc.define: + tags: bindesc + platform_allow: > + native_posix qemu_x86 qemu_cortex_m0 qemu_cortex_m3 + qemu_cortex_r5 qemu_arc_em qemu_arc_hs qemu_arc_hs5x + qemu_arc_hs6x qemu_riscv32 qemu_riscv32e qemu_riscv64 + bindesc.define.c99: + platform_allow: native_posix + tags: bindesc + extra_args: CSTD="c99" + bindesc.define.c11: + platform_allow: native_posix + tags: bindesc + extra_args: CSTD="c11" + bindesc.define.c17: + platform_allow: native_posix + tags: bindesc + extra_args: CSTD="c17" + bindesc.define.gnu99: + platform_allow: native_posix + tags: bindesc + extra_args: CSTD="gnu99" + bindesc.define.gnu11: + platform_allow: native_posix + tags: bindesc + extra_args: CSTD="gnu11" + bindesc.define.gnu17: + platform_allow: native_posix + tags: bindesc + extra_args: CSTD="gnu17" diff --git a/tests/subsys/canbus/isotp/conformance/Kconfig b/tests/subsys/canbus/isotp/conformance/Kconfig new file mode 100644 index 00000000000..cdc8ac501f3 --- /dev/null +++ b/tests/subsys/canbus/isotp/conformance/Kconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: Apache-2.0 + +config TEST_USE_CAN_FD_MODE + bool "Use CAN FD" + select CAN_FD_MODE + +config TEST_ISOTP_TX_DL + int "TX_DL to be used" + default 8 + help + ISO-TP TX_DL value. + Valid values are 8, 12, 16, 20, 24, 32, 48 and 64. + +source "Kconfig.zephyr" diff --git a/tests/subsys/canbus/isotp/conformance/prj.conf b/tests/subsys/canbus/isotp/conformance/prj.conf index 56adfe9dc42..c85ac09f025 100644 --- a/tests/subsys/canbus/isotp/conformance/prj.conf +++ b/tests/subsys/canbus/isotp/conformance/prj.conf @@ -1,9 +1,10 @@ CONFIG_CAN=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ISOTP=y CONFIG_ISOTP_USE_TX_BUF=y CONFIG_ISOTP_ENABLE_CONTEXT_BUFFERS=y CONFIG_ISOTP_RX_BUF_COUNT=6 CONFIG_ISOTP_RX_BUF_SIZE=128 CONFIG_ISOTP_RX_SF_FF_BUF_COUNT=2 +# some tests may be skipped if CAN FD should be used, but is not supported by the controller +CONFIG_ZTEST_VERIFY_RUN_ALL=n diff --git a/tests/subsys/canbus/isotp/conformance/src/main.c b/tests/subsys/canbus/isotp/conformance/src/main.c index 0993ef52d7d..ba3e0890c7b 100644 --- a/tests/subsys/canbus/isotp/conformance/src/main.c +++ b/tests/subsys/canbus/isotp/conformance/src/main.c @@ -10,18 +10,35 @@ #include #include "random_data.h" -#define PCI_TYPE_POS 4 +#if !defined(CONFIG_TEST_USE_CAN_FD_MODE) || CONFIG_TEST_ISOTP_TX_DL == 8 #define DATA_SIZE_SF 7 #define DATA_SIZE_CF 7 #define DATA_SIZE_SF_EXT 6 #define DATA_SIZE_FF 6 -#define DATA_SIZE_FC 3 -#define CAN_DL 8 +#define TX_DL 8 #define DATA_SEND_LENGTH 272 -#define SF_PCI_TYPE 0 #define SF_PCI_BYTE_1 ((SF_PCI_TYPE << PCI_TYPE_POS) | DATA_SIZE_SF) #define SF_PCI_BYTE_2_EXT ((SF_PCI_TYPE << PCI_TYPE_POS) | DATA_SIZE_SF_EXT) #define SF_PCI_BYTE_LEN_8 ((SF_PCI_TYPE << PCI_TYPE_POS) | (DATA_SIZE_SF + 1)) +#else +#define DATA_SIZE_SF (TX_DL - 2) +#define DATA_SIZE_CF (TX_DL - 1) +#define DATA_SIZE_SF_EXT (TX_DL - 3) +#define DATA_SIZE_FF (TX_DL - 2) +#define TX_DL CONFIG_TEST_ISOTP_TX_DL +/* Send length must be larger than FF + (8 * CF). + * But not so big that the remainder cannot fit into the buffers. + */ +#define DATA_SEND_LENGTH (100 + DATA_SIZE_FF + (8 * DATA_SIZE_CF)) +#define SF_PCI_BYTE_1 (SF_PCI_TYPE << PCI_TYPE_POS) +#define SF_PCI_BYTE_2 DATA_SIZE_SF +#define SF_PCI_BYTE_2_EXT (SF_PCI_TYPE << PCI_TYPE_POS) +#define SF_PCI_BYTE_3_EXT DATA_SIZE_SF_EXT +#endif + +#define DATA_SIZE_FC 3 +#define PCI_TYPE_POS 4 +#define SF_PCI_TYPE 0 #define EXT_ADDR 5 #define FF_PCI_TYPE 1 #define FF_PCI_BYTE_1(dl) ((FF_PCI_TYPE << PCI_TYPE_POS) | ((dl) >> 8)) @@ -56,7 +73,7 @@ */ struct frame_desired { - uint8_t data[8]; + uint8_t data[CAN_MAX_DLEN]; uint8_t length; }; @@ -72,51 +89,70 @@ const struct isotp_fc_opts fc_opts_single = { .bs = 0, .stmin = 0 }; + const struct isotp_msg_id rx_addr = { .std_id = 0x10, - .ide = 0, - .use_ext_addr = 0 +#ifdef CONFIG_TEST_USE_CAN_FD_MODE + .dl = CONFIG_TEST_ISOTP_TX_DL, + .flags = ISOTP_MSG_FDF | ISOTP_MSG_BRS, +#endif }; const struct isotp_msg_id tx_addr = { .std_id = 0x11, - .ide = 0, - .use_ext_addr = 0 +#ifdef CONFIG_TEST_USE_CAN_FD_MODE + .dl = CONFIG_TEST_ISOTP_TX_DL, + .flags = ISOTP_MSG_FDF | ISOTP_MSG_BRS, +#endif }; const struct isotp_msg_id rx_addr_ext = { .std_id = 0x10, - .ide = 0, - .use_ext_addr = 1, - .ext_addr = EXT_ADDR + .ext_addr = EXT_ADDR, +#ifdef CONFIG_TEST_USE_CAN_FD_MODE + .dl = CONFIG_TEST_ISOTP_TX_DL, + .flags = ISOTP_MSG_EXT_ADDR | ISOTP_MSG_FDF | ISOTP_MSG_BRS, +#else + .flags = ISOTP_MSG_EXT_ADDR, +#endif }; const struct isotp_msg_id tx_addr_ext = { .std_id = 0x11, - .ide = 0, - .use_ext_addr = 1, - .ext_addr = EXT_ADDR + .ext_addr = EXT_ADDR, +#ifdef CONFIG_TEST_USE_CAN_FD_MODE + .dl = CONFIG_TEST_ISOTP_TX_DL, + .flags = ISOTP_MSG_EXT_ADDR | ISOTP_MSG_FDF | ISOTP_MSG_BRS, +#else + .flags = ISOTP_MSG_EXT_ADDR, +#endif }; const struct isotp_msg_id rx_addr_fixed = { .ext_id = 0x18DA0201, - .ide = 1, - .use_ext_addr = 0, - .use_fixed_addr = 1 +#ifdef CONFIG_TEST_USE_CAN_FD_MODE + .dl = CONFIG_TEST_ISOTP_TX_DL, + .flags = ISOTP_MSG_FIXED_ADDR | ISOTP_MSG_IDE | ISOTP_MSG_FDF | ISOTP_MSG_BRS, +#else + .flags = ISOTP_MSG_FIXED_ADDR | ISOTP_MSG_IDE, +#endif }; const struct isotp_msg_id tx_addr_fixed = { .ext_id = 0x18DA0102, - .ide = 1, - .use_ext_addr = 0, - .use_fixed_addr = 1 +#ifdef CONFIG_TEST_USE_CAN_FD_MODE + .dl = CONFIG_TEST_ISOTP_TX_DL, + .flags = ISOTP_MSG_FIXED_ADDR | ISOTP_MSG_IDE | ISOTP_MSG_FDF | ISOTP_MSG_BRS, +#else + .flags = ISOTP_MSG_FIXED_ADDR | ISOTP_MSG_IDE, +#endif }; -const struct device *const can_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus)); -struct isotp_recv_ctx recv_ctx; -struct isotp_send_ctx send_ctx; -uint8_t data_buf[128]; +static const struct device *const can_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus)); +static struct isotp_recv_ctx recv_ctx; +static struct isotp_send_ctx send_ctx; +static uint8_t data_buf[128]; CAN_MSGQ_DEFINE(frame_msgq, 10); -struct k_sem send_compl_sem; +static struct k_sem send_compl_sem; void send_complete_cb(int error_nr, void *arg) { @@ -225,13 +261,15 @@ static void send_frame_series(struct frame_desired *frames, size_t length, { int i, ret; struct can_frame frame = { - .flags = (id > 0x7FF) ? CAN_FRAME_IDE : 0, + .flags = ((id > 0x7FF) ? CAN_FRAME_IDE : 0) | + (IS_ENABLED(CONFIG_TEST_USE_CAN_FD_MODE) ? + CAN_FRAME_FDF | CAN_FRAME_BRS : 0), .id = id }; struct frame_desired *desired = frames; for (i = 0; i < length; i++) { - frame.dlc = desired->length; + frame.dlc = can_bytes_to_dlc(desired->length); memcpy(frame.data, desired->data, desired->length); ret = can_send(can_dev, &frame, K_MSEC(500), NULL, NULL); zassert_equal(ret, 0, "Sending msg %d failed.", i); @@ -251,9 +289,9 @@ static void check_frame_series(struct frame_desired *frames, size_t length, zassert_equal(ret, 0, "Timeout waiting for msg nr %d. ret: %d", i, ret); - zassert_equal(frame.dlc, desired->length, + zassert_equal(frame.dlc, can_bytes_to_dlc(desired->length), "DLC of frame nr %d differ. Desired: %d, Got: %d", - i, desired->length, frame.dlc); + i, can_bytes_to_dlc(desired->length), frame.dlc); ret = check_data(frame.data, desired->data, desired->length); zassert_equal(ret, 0, "Data differ"); @@ -268,7 +306,8 @@ static int add_rx_msgq(uint32_t id, uint32_t mask) { int filter_id; struct can_filter filter = { - .flags = CAN_FILTER_DATA | ((id > 0x7FF) ? CAN_FILTER_IDE : 0), + .flags = CAN_FILTER_DATA | ((id > 0x7FF) ? CAN_FILTER_IDE : 0) | + (IS_ENABLED(CONFIG_TEST_USE_CAN_FD_MODE) ? CAN_FILTER_FDF : 0), .id = id, .mask = mask }; @@ -289,13 +328,40 @@ static void prepare_fc_frame(struct frame_desired *frame, uint8_t st, frame->data[2] = FC_PCI_BYTE_3(opts->stmin); if ((IS_ENABLED(CONFIG_ISOTP_ENABLE_TX_PADDING) && tx) || (IS_ENABLED(CONFIG_ISOTP_REQUIRE_RX_PADDING) && !tx)) { - memset(&frame->data[DATA_SIZE_FC], 0xCC, CAN_DL - DATA_SIZE_FC); - frame->length = CAN_DL; + memset(&frame->data[DATA_SIZE_FC], 0xCC, 8 - DATA_SIZE_FC); + frame->length = 8; } else { frame->length = DATA_SIZE_FC; } } +static void prepare_sf_frame(struct frame_desired *frame, const uint8_t *data) +{ + frame->data[0] = SF_PCI_BYTE_1; +#ifdef SF_PCI_BYTE_2 + frame->data[1] = SF_PCI_BYTE_2; + memcpy(&frame->data[2], data, DATA_SIZE_SF); + frame->length = DATA_SIZE_SF + 2; +#else + memcpy(&frame->data[1], data, DATA_SIZE_SF); + frame->length = DATA_SIZE_SF + 1; +#endif +} + +static void prepare_sf_ext_frame(struct frame_desired *frame, const uint8_t *data) +{ + frame->data[0] = rx_addr_ext.ext_addr; + frame->data[1] = SF_PCI_BYTE_2_EXT; +#ifdef SF_PCI_BYTE_3_EXT + frame->data[2] = SF_PCI_BYTE_3_EXT; + memcpy(&frame->data[3], data, DATA_SIZE_SF_EXT); + frame->length = DATA_SIZE_SF_EXT + 3; +#else + memcpy(&frame->data[2], data, DATA_SIZE_SF_EXT); + frame->length = DATA_SIZE_SF_EXT + 2; +#endif +} + static void prepare_cf_frames(struct frame_desired *frames, size_t frames_cnt, const uint8_t *data, size_t data_len, bool tx) { @@ -305,14 +371,18 @@ static void prepare_cf_frames(struct frame_desired *frames, size_t frames_cnt, for (i = 0; i < frames_cnt && remaining_length; i++) { frames[i].data[0] = CF_PCI_BYTE_1 | ((i+1) & 0x0F); - frames[i].length = CAN_DL; - memcpy(&des_frames[i].data[1], data_ptr, DATA_SIZE_CF); + frames[i].length = TX_DL; + memcpy(&frames[i].data[1], data_ptr, DATA_SIZE_CF); if (remaining_length < DATA_SIZE_CF) { if ((IS_ENABLED(CONFIG_ISOTP_ENABLE_TX_PADDING) && tx) || (IS_ENABLED(CONFIG_ISOTP_REQUIRE_RX_PADDING) && !tx)) { - memset(&des_frames[i].data[remaining_length + 1], 0xCC, - CAN_DL - remaining_length - 1); + uint8_t padded_dlc = can_bytes_to_dlc(MAX(8, remaining_length + 1)); + uint8_t padded_len = can_dlc_to_bytes(padded_dlc); + + memset(&frames[i].data[remaining_length + 1], 0xCC, + padded_len - remaining_length - 1); + frames[i].length = padded_len; } else { frames[i].length = remaining_length + 1; } @@ -329,9 +399,7 @@ ZTEST(isotp_conformance, test_send_sf) int filter_id; struct frame_desired des_frame; - des_frame.data[0] = SF_PCI_BYTE_1; - memcpy(&des_frame.data[1], random_data, DATA_SIZE_SF); - des_frame.length = DATA_SIZE_SF + 1; + prepare_sf_frame(&des_frame, random_data); filter_id = add_rx_msgq(rx_addr.std_id, CAN_STD_ID_MASK); zassert_true((filter_id >= 0), "Negative filter number [%d]", @@ -349,9 +417,7 @@ ZTEST(isotp_conformance, test_receive_sf) int ret; struct frame_desired single_frame; - single_frame.data[0] = SF_PCI_BYTE_1; - memcpy(&single_frame.data[1], random_data, DATA_SIZE_SF); - single_frame.length = DATA_SIZE_SF + 1; + prepare_sf_frame(&single_frame, random_data); ret = isotp_bind(&recv_ctx, can_dev, &rx_addr, &tx_addr, &fc_opts_single, K_NO_WAIT); @@ -361,8 +427,14 @@ ZTEST(isotp_conformance, test_receive_sf) get_sf(DATA_SIZE_SF); + /* Frame size too big should be ignored/dropped */ + #ifdef SF_PCI_BYTE_2 + single_frame.data[1]++; + #else single_frame.data[0] = SF_PCI_BYTE_LEN_8; + #endif send_frame_series(&single_frame, 1, rx_addr.std_id); + get_sf_ignore(); #ifdef CONFIG_ISOTP_REQUIRE_RX_PADDING single_frame.data[0] = SF_PCI_BYTE_1; @@ -380,10 +452,7 @@ ZTEST(isotp_conformance, test_send_sf_ext) int filter_id, ret; struct frame_desired des_frame; - des_frame.data[0] = rx_addr_ext.ext_addr; - des_frame.data[1] = SF_PCI_BYTE_2_EXT; - memcpy(&des_frame.data[2], random_data, DATA_SIZE_SF_EXT); - des_frame.length = DATA_SIZE_SF_EXT + 2; + prepare_sf_ext_frame(&des_frame, random_data); filter_id = add_rx_msgq(rx_addr_ext.std_id, CAN_STD_ID_MASK); zassert_true((filter_id >= 0), "Negative filter number [%d]", @@ -404,10 +473,7 @@ ZTEST(isotp_conformance, test_receive_sf_ext) int ret; struct frame_desired single_frame; - single_frame.data[0] = EXT_ADDR; - single_frame.data[1] = SF_PCI_BYTE_2_EXT; - memcpy(&single_frame.data[2], random_data, DATA_SIZE_SF_EXT); - single_frame.length = DATA_SIZE_SF_EXT + 2; + prepare_sf_ext_frame(&single_frame, random_data); ret = isotp_bind(&recv_ctx, can_dev, &rx_addr_ext, &tx_addr, &fc_opts_single, K_NO_WAIT); @@ -417,8 +483,14 @@ ZTEST(isotp_conformance, test_receive_sf_ext) get_sf(DATA_SIZE_SF_EXT); + /* Frame size too big should be ignored/dropped */ + #ifdef SF_PCI_BYTE_2 + single_frame.data[2]++; + #else single_frame.data[1] = SF_PCI_BYTE_1; + #endif send_frame_series(&single_frame, 1, rx_addr.std_id); + get_sf_ignore(); #ifdef CONFIG_ISOTP_REQUIRE_RX_PADDING single_frame.data[1] = SF_PCI_BYTE_2_EXT; @@ -436,9 +508,7 @@ ZTEST(isotp_conformance, test_send_sf_fixed) int filter_id, ret; struct frame_desired des_frame; - des_frame.data[0] = SF_PCI_BYTE_1; - memcpy(&des_frame.data[1], random_data, DATA_SIZE_SF); - des_frame.length = DATA_SIZE_SF + 1; + prepare_sf_frame(&des_frame, random_data); /* mask to allow any priority and source address (SA) */ filter_id = add_rx_msgq(rx_addr_fixed.ext_id, 0x03FFFF00); @@ -460,9 +530,7 @@ ZTEST(isotp_conformance, test_receive_sf_fixed) int ret; struct frame_desired single_frame; - single_frame.data[0] = SF_PCI_BYTE_1; - memcpy(&single_frame.data[1], random_data, DATA_SIZE_SF); - single_frame.length = DATA_SIZE_SF + 1; + prepare_sf_frame(&single_frame, random_data); ret = isotp_bind(&recv_ctx, can_dev, &rx_addr_fixed, &tx_addr_fixed, &fc_opts_single, K_NO_WAIT); @@ -497,7 +565,7 @@ ZTEST(isotp_conformance, test_send_data) ff_frame.data[0] = FF_PCI_BYTE_1(DATA_SEND_LENGTH); ff_frame.data[1] = FF_PCI_BYTE_2(DATA_SEND_LENGTH); memcpy(&ff_frame.data[2], data_ptr, DATA_SIZE_FF); - ff_frame.length = CAN_DL; + ff_frame.length = TX_DL; data_ptr += DATA_SIZE_FF; remaining_length -= DATA_SIZE_FF; @@ -594,7 +662,7 @@ ZTEST(isotp_conformance, test_receive_data) ff_frame.data[0] = FF_PCI_BYTE_1(DATA_SEND_LENGTH); ff_frame.data[1] = FF_PCI_BYTE_2(DATA_SEND_LENGTH); memcpy(&ff_frame.data[2], data_ptr, DATA_SIZE_FF); - ff_frame.length = CAN_DL; + ff_frame.length = TX_DL; data_ptr += DATA_SIZE_FF; remaining_length -= DATA_SIZE_FF; @@ -949,8 +1017,114 @@ ZTEST(isotp_conformance, test_sender_fc_errors) can_remove_rx_filter(can_dev, filter_id); } +ZTEST(isotp_conformance, test_canfd_mandatory_padding) +{ + /* Mandatory padding of CAN FD frames (TX_DL > 8). + * Must be padded with 0xCC up to the nearest DLC. + */ +#if TX_DL < 12 + ztest_test_skip(); +#else + /* Input a single frame packet of 10 bytes */ + uint8_t data_size_sf = 10 - 2; + int filter_id, ret; + struct can_frame frame = {}; + const uint8_t expected_padding[] = { 0xCC, 0xCC }; + + filter_id = add_rx_msgq(rx_addr.std_id, CAN_STD_ID_MASK); + + ret = isotp_send(&send_ctx, can_dev, random_data, data_size_sf, + &rx_addr, &tx_addr, send_complete_cb, INT_TO_POINTER(ISOTP_N_OK)); + zassert_equal(ret, 0, "Send returned %d", ret); + + ret = k_msgq_get(&frame_msgq, &frame, K_MSEC(500)); + zassert_equal(ret, 0, "Timeout waiting for msg. ret: %d", ret); + + /* The output frame should be 12 bytes, with the last two bytes being 0xCC */ + zassert_equal(can_dlc_to_bytes(frame.dlc), 12, "Incorrect DLC"); + zassert_mem_equal(&frame.data[10], expected_padding, sizeof(expected_padding)); -void *isotp_conformance_setup(void) + can_remove_rx_filter(can_dev, filter_id); +#endif +} + +ZTEST(isotp_conformance, test_canfd_rx_dl_validation) +{ + /* First frame defines the RX data length, consecutive frames + * must have the same length (except the last frame) + */ +#if TX_DL < 16 + ztest_test_skip(); +#else + + uint8_t data_size_ff = 16 - 2; + uint8_t data_size_cf = 12 - 1; + uint8_t data_send_length = data_size_ff + 2 * data_size_cf; + const uint8_t *data_ptr = random_data; + int filter_id, ret; + struct frame_desired fc_frame, ff_frame; + + /* FF uses a TX_DL of 16 */ + ff_frame.data[0] = FF_PCI_BYTE_1(data_send_length); + ff_frame.data[1] = FF_PCI_BYTE_2(data_send_length); + memcpy(&ff_frame.data[2], data_ptr, data_size_ff); + ff_frame.length = data_size_ff + 2; + data_ptr += data_size_ff; + + prepare_fc_frame(&fc_frame, FC_PCI_CTS, &fc_opts_single, true); + + /* Two CF frames using a TX_DL of 12 */ + des_frames[0].data[0] = CF_PCI_BYTE_1 | (1 & 0x0F); + des_frames[0].length = data_size_cf + 1; + memcpy(&des_frames[0].data[1], data_ptr, data_size_cf); + data_ptr += data_size_cf; + + des_frames[1].data[0] = CF_PCI_BYTE_1 | (2 & 0x0F); + des_frames[1].length = data_size_cf + 1; + memcpy(&des_frames[1].data[1], data_ptr, data_size_cf); + data_ptr += data_size_cf; + + filter_id = add_rx_msgq(tx_addr.std_id, CAN_STD_ID_MASK); + + ret = isotp_bind(&recv_ctx, can_dev, &rx_addr, &tx_addr, + &fc_opts_single, K_NO_WAIT); + zassert_equal(ret, ISOTP_N_OK, "Binding failed [%d]", ret); + + send_frame_series(&ff_frame, 1, rx_addr.std_id); + + check_frame_series(&fc_frame, 1, &frame_msgq); + + send_frame_series(des_frames, 2, rx_addr.std_id); + + /* Assert that the packet was dropped and an error returned */ + ret = isotp_recv(&recv_ctx, data_buf, sizeof(data_buf), K_MSEC(200)); + zassert_equal(ret, ISOTP_N_ERROR, "recv returned %d", ret); + + can_remove_rx_filter(can_dev, filter_id); + isotp_unbind(&recv_ctx); +#endif +} + +static bool canfd_predicate(const void *state) +{ + ARG_UNUSED(state); + +#ifdef CONFIG_TEST_USE_CAN_FD_MODE + can_mode_t cap; + int err; + + err = can_get_capabilities(can_dev, &cap); + zassert_equal(err, 0, "failed to get CAN controller capabilities (err %d)", err); + + if ((cap & CAN_MODE_FD) == 0) { + return false; + } +#endif + + return true; +} + +static void *isotp_conformance_setup(void) { int ret; @@ -959,8 +1133,11 @@ void *isotp_conformance_setup(void) zassert_true(device_is_ready(can_dev), "CAN device not ready"); - ret = can_set_mode(can_dev, CAN_MODE_LOOPBACK); - zassert_equal(ret, 0, "Failed to set loopback mode [%d]", ret); + (void)can_stop(can_dev); + + ret = can_set_mode(can_dev, CAN_MODE_LOOPBACK | + (IS_ENABLED(CONFIG_TEST_USE_CAN_FD_MODE) ? CAN_MODE_FD : 0)); + zassert_equal(ret, 0, "Failed to set mode [%d]", ret); ret = can_start(can_dev); zassert_equal(ret, 0, "Failed to start CAN controller [%d]", ret); @@ -970,4 +1147,4 @@ void *isotp_conformance_setup(void) return NULL; } -ZTEST_SUITE(isotp_conformance, NULL, isotp_conformance_setup, NULL, NULL, NULL); +ZTEST_SUITE(isotp_conformance, canfd_predicate, isotp_conformance_setup, NULL, NULL, NULL); diff --git a/tests/subsys/canbus/isotp/conformance/src/mode_check.c b/tests/subsys/canbus/isotp/conformance/src/mode_check.c new file mode 100644 index 00000000000..1fa872c5c39 --- /dev/null +++ b/tests/subsys/canbus/isotp/conformance/src/mode_check.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2023 Libre Solar Technologies GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * This test suite checks that correct errors are returned when trying to use the ISO-TP + * protocol with CAN FD mode even though the controller does not support CAN FD. + */ + +#include +#include + +static const struct device *const can_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus)); +static struct isotp_recv_ctx recv_ctx; +static struct isotp_send_ctx send_ctx; +static bool canfd_capable; + +static const struct isotp_fc_opts fc_opts = { + .bs = 0, + .stmin = 0 +}; + +static const struct isotp_msg_id rx_addr = { + .std_id = 0x20, +#ifdef CONFIG_TEST_USE_CAN_FD_MODE + .dl = CONFIG_TEST_ISOTP_TX_DL, + .flags = ISOTP_MSG_FDF | ISOTP_MSG_BRS, +#endif +}; + +static const struct isotp_msg_id tx_addr = { + .std_id = 0x21, +#ifdef CONFIG_TEST_USE_CAN_FD_MODE + .dl = CONFIG_TEST_ISOTP_TX_DL, + .flags = ISOTP_MSG_FDF | ISOTP_MSG_BRS, +#endif +}; + +ZTEST(isotp_conformance_mode_check, test_bind) +{ + int err; + + err = isotp_bind(&recv_ctx, can_dev, &rx_addr, &tx_addr, &fc_opts, K_NO_WAIT); + if (IS_ENABLED(CONFIG_TEST_USE_CAN_FD_MODE) && !canfd_capable) { + zassert_equal(err, ISOTP_N_ERROR); + } else { + zassert_equal(err, ISOTP_N_OK); + } + + isotp_unbind(&recv_ctx); +} + +ZTEST(isotp_conformance_mode_check, test_send) +{ + uint8_t buf[] = { 1, 2, 3 }; + int err; + + err = isotp_send(&send_ctx, can_dev, buf, sizeof(buf), &rx_addr, &tx_addr, NULL, NULL); + if (IS_ENABLED(CONFIG_TEST_USE_CAN_FD_MODE) && !canfd_capable) { + zassert_equal(err, ISOTP_N_ERROR); + } else { + zassert_equal(err, ISOTP_N_OK); + } +} + +static void *isotp_conformance_mode_check_setup(void) +{ + can_mode_t cap; + int err; + + zassert_true(device_is_ready(can_dev), "CAN device not ready"); + + err = can_get_capabilities(can_dev, &cap); + zassert_equal(err, 0, "failed to get CAN controller capabilities (err %d)", err); + + canfd_capable = (cap & CAN_MODE_FD) != 0; + + (void)can_stop(can_dev); + + err = can_set_mode(can_dev, CAN_MODE_LOOPBACK | (canfd_capable ? CAN_MODE_FD : 0)); + zassert_equal(err, 0, "Failed to set mode [%d]", err); + + err = can_start(can_dev); + zassert_equal(err, 0, "Failed to start CAN controller [%d]", err); + + return NULL; +} + +ZTEST_SUITE(isotp_conformance_mode_check, NULL, isotp_conformance_mode_check_setup, NULL, NULL, + NULL); diff --git a/tests/subsys/canbus/isotp/conformance/testcase.yaml b/tests/subsys/canbus/isotp/conformance/testcase.yaml index 04962aa08d8..ce9c838ab97 100644 --- a/tests/subsys/canbus/isotp/conformance/testcase.yaml +++ b/tests/subsys/canbus/isotp/conformance/testcase.yaml @@ -1,7 +1,54 @@ +# +# There are 4 different test cases that have to be considered: +# +# | Case # | Controller type | Selected mode | Example board | +# +--------+------------------------+----------------------+----------------+ +# | 1 | Classical CAN only | CONFIG_CAN_FD_MODE=n | nucleo_f072 | +# | 2 | Classical CAN only | CONFIG_CAN_FD_MODE=y | nucleo_f072 | +# | 3 | Classical CAN + CAN FD | CONFIG_CAN_FD_MODE=n | native_posix | +# | 4 | Classical CAN + CAN FD | CONFIG_CAN_FD_MODE=y | native_posix | +# +# The test-specific CONFIG_TEST_USE_CAN_FD_MODE is used to decide if the test should use +# CAN FD independent of CONFIG_CAN_FD_MODE configuration. +# + tests: + # cases 1, 3 canbus.isotp.conformance: tags: - can - isotp depends_on: can filter: dt_chosen_enabled("zephyr,canbus") and not dt_compat_enabled("kvaser,pcican") + # case 2 + canbus.isotp.conformance.fd.unused: + tags: + - can + - isotp + extra_configs: + - CONFIG_TEST_USE_CAN_FD_MODE=n + - CONFIG_CAN_FD_MODE=y + depends_on: can + filter: dt_chosen_enabled("zephyr,canbus") and not dt_compat_enabled("kvaser,pcican") + # case 4 + canbus.isotp.conformance.fd.txdl_32: + tags: + - can + - isotp + extra_configs: + - CONFIG_TEST_USE_CAN_FD_MODE=y + - CONFIG_TEST_ISOTP_TX_DL=32 + - CONFIG_CAN_FD_MODE=y + depends_on: can + filter: dt_chosen_enabled("zephyr,canbus") and not dt_compat_enabled("kvaser,pcican") + # case 4 + canbus.isotp.conformance.fd.txdl_64: + tags: + - can + - isotp + extra_configs: + - CONFIG_TEST_USE_CAN_FD_MODE=y + - CONFIG_TEST_ISOTP_TX_DL=64 + - CONFIG_CAN_FD_MODE=y + depends_on: can + filter: dt_chosen_enabled("zephyr,canbus") and not dt_compat_enabled("kvaser,pcican") diff --git a/tests/subsys/canbus/isotp/implementation/prj.conf b/tests/subsys/canbus/isotp/implementation/prj.conf index 4ab0fe51d38..648acdbf209 100644 --- a/tests/subsys/canbus/isotp/implementation/prj.conf +++ b/tests/subsys/canbus/isotp/implementation/prj.conf @@ -1,6 +1,5 @@ CONFIG_CAN=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ISOTP=y CONFIG_ISOTP_USE_TX_BUF=y CONFIG_ISOTP_ENABLE_CONTEXT_BUFFERS=y diff --git a/tests/subsys/canbus/isotp/implementation/src/main.c b/tests/subsys/canbus/isotp/implementation/src/main.c index 1c597f64ec7..bbc2cadb6ce 100644 --- a/tests/subsys/canbus/isotp/implementation/src/main.c +++ b/tests/subsys/canbus/isotp/implementation/src/main.c @@ -35,15 +35,12 @@ const struct isotp_fc_opts fc_opts_single = { .bs = 0, .stmin = 1 }; + const struct isotp_msg_id rx_addr = { .std_id = 0x10, - .ide = 0, - .use_ext_addr = 0 }; const struct isotp_msg_id tx_addr = { .std_id = 0x11, - .ide = 0, - .use_ext_addr = 0 }; struct isotp_recv_ctx recv_ctx; diff --git a/tests/subsys/debug/coredump/CMakeLists.txt b/tests/subsys/debug/coredump/CMakeLists.txt index ecb7d24bb8f..2ed92da99af 100644 --- a/tests/subsys/debug/coredump/CMakeLists.txt +++ b/tests/subsys/debug/coredump/CMakeLists.txt @@ -3,6 +3,6 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(hello_world) +project(debug_coredump) target_sources(app PRIVATE src/main.c) diff --git a/tests/subsys/debug/coredump/src/main.c b/tests/subsys/debug/coredump/src/main.c index ace12f8a296..d5e11f2148d 100644 --- a/tests/subsys/debug/coredump/src/main.c +++ b/tests/subsys/debug/coredump/src/main.c @@ -8,12 +8,30 @@ #include #include +#ifdef CONFIG_COVERAGE_DUMP +#include +#endif + + +void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +{ + ARG_UNUSED(pEsf); + + printk("%s is expected; reason = %u; halting ...\n", __func__, reason); + +#ifdef CONFIG_COVERAGE_DUMP + gcov_coverage_dump(); /* LCOV_EXCL_LINE */ +#endif + k_fatal_halt(reason); +} + void func_3(uint32_t *addr) { #if defined(CONFIG_BOARD_M2GL025_MIV) || \ defined(CONFIG_BOARD_HIFIVE1) || \ defined(CONFIG_BOARD_LONGAN_NANO) || \ defined(CONFIG_BOARD_LONGAN_NANO_LITE) || \ + defined(CONFIG_BOARD_QEMU_XTENSA) || \ defined(CONFIG_SOC_FAMILY_INTEL_ADSP) ARG_UNUSED(addr); /* Call k_panic() directly so Renode doesn't pause execution. diff --git a/tests/subsys/debug/coredump/testcase.yaml b/tests/subsys/debug/coredump/testcase.yaml index 55e181216e0..150c07600a1 100644 --- a/tests/subsys/debug/coredump/testcase.yaml +++ b/tests/subsys/debug/coredump/testcase.yaml @@ -5,6 +5,9 @@ tests: ignore_qemu_crash: true filter: CONFIG_ARCH_SUPPORTS_COREDUMP platform_exclude: acrn_ehl_crb + arch_exclude: + - posix + - xtensa integration_platforms: - qemu_x86 harness: console @@ -12,8 +15,34 @@ tests: type: multi_line regex: - "Coredump: (.*)" + - ">>> ZEPHYR FATAL ERROR " - "E: #CD:BEGIN#" - "E: #CD:5([aA])45([0-9a-fA-F]+)" - "E: #CD:41([0-9a-fA-F]+)" - "E: #CD:4([dD])([0-9a-fA-F]+)" + - "E: #CD:4([dD])([0-9a-fA-F]+)" + - "E: #CD:END#" + - "k_sys_fatal_error_handler" + + debug.coredump.logging_backend_xtensa: + tags: coredump + ignore_faults: true + ignore_qemu_crash: true + filter: CONFIG_ARCH_SUPPORTS_COREDUMP + arch_allow: + - xtensa + integration_platforms: + - qemu_xtensa + harness: console + harness_config: + type: multi_line + regex: + - "Coredump: (.*)" + - "E: #CD:BEGIN#" + - "E: #CD:5([aA])45([0-9a-fA-F]+)" + - "E: #CD:41([0-9a-fA-F]+)" + - "E: #CD:4([dD])([0-9a-fA-F]+)" + - "E: #CD:4([dD])([0-9a-fA-F]+)" - "E: #CD:END#" + - ">>> ZEPHYR FATAL ERROR " + - "k_sys_fatal_error_handler" diff --git a/tests/subsys/debug/coredump_backends/CMakeLists.txt b/tests/subsys/debug/coredump_backends/CMakeLists.txt index a7d48d53d4f..5ae2b1f792c 100644 --- a/tests/subsys/debug/coredump_backends/CMakeLists.txt +++ b/tests/subsys/debug/coredump_backends/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(hello_world) +project(debug_coredump_backends) target_sources(app PRIVATE src/main.c) diff --git a/tests/subsys/debug/coredump_backends/Kconfig b/tests/subsys/debug/coredump_backends/Kconfig new file mode 100644 index 00000000000..dc02b1341a2 --- /dev/null +++ b/tests/subsys/debug/coredump_backends/Kconfig @@ -0,0 +1,17 @@ +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +source "Kconfig.zephyr" + +config TEST_STORED_COREDUMP + bool "Expected backend has coredump storage." + help + Set if the test expects coredump backend with storage. + +config TEST_STORED_DUMP_SIZE + int "Expected backend's coredump storage size." + default 0 + help + Test expects coredump backend storage with the size given. + If zero, then it is ignored and not compared with the actual size. diff --git a/tests/subsys/debug/coredump_backends/boards/esp32c3_luatos_core.overlay b/tests/subsys/debug/coredump_backends/boards/esp32c3_luatos_core.overlay new file mode 100644 index 00000000000..eb707ee7221 --- /dev/null +++ b/tests/subsys/debug/coredump_backends/boards/esp32c3_luatos_core.overlay @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&flash0 { + partitions { + /* + * Reduce storage_partition to make space for + * coredump_partition + */ + + storage_partition: partition@250000 { + label = "storage"; + reg = <0x00250000 0x00005000>; + }; + + coredump_partition: partition@255000 { + label = "coredump-partition"; + reg = <0x255000 DT_SIZE_K(4)>; + }; + + }; +}; diff --git a/tests/subsys/debug/coredump_backends/boards/esp32c3_luatos_core_usb.overlay b/tests/subsys/debug/coredump_backends/boards/esp32c3_luatos_core_usb.overlay new file mode 100644 index 00000000000..eb707ee7221 --- /dev/null +++ b/tests/subsys/debug/coredump_backends/boards/esp32c3_luatos_core_usb.overlay @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&flash0 { + partitions { + /* + * Reduce storage_partition to make space for + * coredump_partition + */ + + storage_partition: partition@250000 { + label = "storage"; + reg = <0x00250000 0x00005000>; + }; + + coredump_partition: partition@255000 { + label = "coredump-partition"; + reg = <0x255000 DT_SIZE_K(4)>; + }; + + }; +}; diff --git a/tests/subsys/debug/coredump_backends/boards/esp32s3_luatos_core.overlay b/tests/subsys/debug/coredump_backends/boards/esp32s3_luatos_core.overlay new file mode 100644 index 00000000000..eb707ee7221 --- /dev/null +++ b/tests/subsys/debug/coredump_backends/boards/esp32s3_luatos_core.overlay @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&flash0 { + partitions { + /* + * Reduce storage_partition to make space for + * coredump_partition + */ + + storage_partition: partition@250000 { + label = "storage"; + reg = <0x00250000 0x00005000>; + }; + + coredump_partition: partition@255000 { + label = "coredump-partition"; + reg = <0x255000 DT_SIZE_K(4)>; + }; + + }; +}; diff --git a/tests/subsys/debug/coredump_backends/boards/esp32s3_luatos_core_usb.overlay b/tests/subsys/debug/coredump_backends/boards/esp32s3_luatos_core_usb.overlay new file mode 100644 index 00000000000..eb707ee7221 --- /dev/null +++ b/tests/subsys/debug/coredump_backends/boards/esp32s3_luatos_core_usb.overlay @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&flash0 { + partitions { + /* + * Reduce storage_partition to make space for + * coredump_partition + */ + + storage_partition: partition@250000 { + label = "storage"; + reg = <0x00250000 0x00005000>; + }; + + coredump_partition: partition@255000 { + label = "coredump-partition"; + reg = <0x255000 DT_SIZE_K(4)>; + }; + + }; +}; diff --git a/tests/subsys/debug/coredump_backends/prj.conf b/tests/subsys/debug/coredump_backends/prj.conf index dc18b00328a..dae6fd98be5 100644 --- a/tests/subsys/debug/coredump_backends/prj.conf +++ b/tests/subsys/debug/coredump_backends/prj.conf @@ -6,4 +6,3 @@ CONFIG_DEBUG_COREDUMP_BACKEND_LOGGING=y CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN=y CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_LINKER_RAM=n -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/debug/coredump_backends/prj_backend_other.conf b/tests/subsys/debug/coredump_backends/prj_backend_other.conf index fd1dc6213cc..7b902485c10 100644 --- a/tests/subsys/debug/coredump_backends/prj_backend_other.conf +++ b/tests/subsys/debug/coredump_backends/prj_backend_other.conf @@ -4,4 +4,3 @@ CONFIG_DEBUG_COREDUMP_BACKEND_OTHER=y CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN=y CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_LINKER_RAM=n -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/debug/coredump_backends/prj_flash_partition.conf b/tests/subsys/debug/coredump_backends/prj_flash_partition.conf index bd45af4cdd7..71e3eea70fe 100644 --- a/tests/subsys/debug/coredump_backends/prj_flash_partition.conf +++ b/tests/subsys/debug/coredump_backends/prj_flash_partition.conf @@ -7,4 +7,3 @@ CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_FLASH=y CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN=y CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_LINKER_RAM=n -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/debug/coredump_backends/src/coredump_backend_empty.c b/tests/subsys/debug/coredump_backends/src/coredump_backend_empty.c index 82cee0b70d9..ce3229bbeba 100644 --- a/tests/subsys/debug/coredump_backends/src/coredump_backend_empty.c +++ b/tests/subsys/debug/coredump_backends/src/coredump_backend_empty.c @@ -42,6 +42,9 @@ static int coredump_empty_backend_query(enum coredump_query_id query_id, ret = 1; } break; + case COREDUMP_QUERY_GET_STORED_DUMP_SIZE: + ret = 0; + break; default: ret = -ENOTSUP; break; @@ -66,6 +69,14 @@ static int coredump_empty_backend_cmd(enum coredump_cmd_id cmd_id, ret = 1; } break; + case COREDUMP_CMD_INVALIDATE_STORED_DUMP: + is_valid = false; + ret = 0; + break; + case COREDUMP_CMD_ERASE_STORED_DUMP: + is_valid = false; + ret = 0; + break; default: ret = -ENOTSUP; break; diff --git a/tests/subsys/debug/coredump_backends/src/main.c b/tests/subsys/debug/coredump_backends/src/main.c index f855d047751..8b7636edbd9 100644 --- a/tests/subsys/debug/coredump_backends/src/main.c +++ b/tests/subsys/debug/coredump_backends/src/main.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2014 Wind River Systems, Inc. + * Copyright (c) 2020-2023, Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 */ @@ -34,7 +35,7 @@ void dump_entry(void *p1, void *p2, void *p3) irq_unlock(key); } -static void check_errors(void) +void check_error(void) { int ret; @@ -45,10 +46,23 @@ static void check_errors(void) } } -void test_coredump(void) +void clear_error(void) +{ + int ret; + + /* Clear backend error if backend supports this query */ + ret = coredump_cmd(COREDUMP_CMD_CLEAR_ERROR, NULL); + if (ret != -ENOTSUP) { + zassert_equal(ret, 0, "Error encountered! (%d)", ret); + } +} + +static void *raise_coredump(void) { k_tid_t tid; + clear_error(); + /* Create a thread that crashes */ tid = k_thread_create(&dump_thread, dump_stack, K_THREAD_STACK_SIZEOF(dump_stack), @@ -57,28 +71,46 @@ void test_coredump(void) k_thread_join(tid, K_FOREVER); - check_errors(); + return &dump_thread; } -void test_query_stored_dump(void) +void test_has_stored_dump(bool is_expected) { int ret; /* Cannot proceed with previous errors */ - check_errors(); + check_error(); /* There should be a stored coredump now if backend has storage */ ret = coredump_query(COREDUMP_QUERY_HAS_STORED_DUMP, NULL); if (ret == -ENOTSUP) { +#ifdef CONFIG_TEST_STORED_COREDUMP + TC_ERROR("Can't query stored dump: unexpectedly not supported.\n"); + ztest_test_fail(); +#else + TC_PRINT("Can't query stored dump: expectedly not supported.\n"); ztest_test_skip(); +#endif } else if (ret == 1) { - check_errors(); +#ifdef CONFIG_TEST_STORED_COREDUMP + check_error(); + zassert_true(is_expected, "Unexpected coredump found.\n"); ztest_test_pass(); +#else + TC_ERROR("Can't have a stored dump: not supported.\n"); + ztest_test_fail(); +#endif } else if (ret == 0) { - TC_PRINT("Should have stored dump!\n"); +#ifdef CONFIG_TEST_STORED_COREDUMP + check_error(); + zassert_false(is_expected, "Should have stored dump!\n"); + ztest_test_pass(); +#else + TC_ERROR("Can't have an empty stored dump: not supported.\n"); ztest_test_fail(); +#endif } else { - TC_PRINT("Error reading stored dump! (%d)\n", ret); + TC_ERROR("Error reading stored dump! (%d)\n", ret); ztest_test_fail(); } } @@ -88,28 +120,162 @@ void test_verify_stored_dump(void) int ret; /* Cannot proceed with previous errors */ - check_errors(); + check_error(); /* There should be a stored coredump now if backend has storage */ ret = coredump_cmd(COREDUMP_CMD_VERIFY_STORED_DUMP, NULL); if (ret == -ENOTSUP) { +#ifdef CONFIG_TEST_STORED_COREDUMP + TC_ERROR("Can't verify stored dump: unexpectedly not supported.\n"); + ztest_test_fail(); +#else + TC_PRINT("Can't verify stored dump: expectedly not supported.\n"); ztest_test_skip(); +#endif } else if (ret == 1) { - check_errors(); +#ifdef CONFIG_TEST_STORED_COREDUMP + check_error(); ztest_test_pass(); +#else + TC_ERROR("Can't have a stored dump: not supported.\n"); + ztest_test_fail(); +#endif + } else if (ret == 0) { +#ifdef CONFIG_TEST_STORED_COREDUMP + TC_ERROR("Verification of stored dump failed!\n"); + ztest_test_fail(); +#else + TC_ERROR("Can't have a stored dump: not supported.\n"); + ztest_test_fail(); +#endif + } else { + TC_ERROR("Error reading stored dump! (%d)\n", ret); + ztest_test_fail(); + } +} + +void test_invalidate_stored_dump(void) +{ + int ret; + + /* Cannot proceed with previous errors */ + check_error(); + + /* There should be a stored coredump now if backend has storage */ + ret = coredump_cmd(COREDUMP_CMD_INVALIDATE_STORED_DUMP, NULL); + if (ret == -ENOTSUP) { +#ifdef CONFIG_TEST_STORED_COREDUMP + TC_ERROR("Can't invalidate stored dump: unexpectedly not supported.\n"); + ztest_test_fail(); +#else + TC_PRINT("Can't invalidate stored dump: expectedly not supported.\n"); + ztest_test_skip(); +#endif } else if (ret == 0) { - TC_PRINT("Verification of stored dump failed!\n"); +#ifdef CONFIG_TEST_STORED_COREDUMP + check_error(); + ztest_test_pass(); +#else + TC_ERROR("Can't invalidate the stored dump: not supported.\n"); ztest_test_fail(); +#endif } else { - TC_PRINT("Error reading stored dump! (%d)\n", ret); + TC_ERROR("Error invalidating stored dump! (%d)\n", ret); ztest_test_fail(); } } -ZTEST(coredump_backends, test_coredump_backend) { - test_coredump(); - test_query_stored_dump(); +void test_erase_stored_dump(void) +{ + int ret; + + /* Cannot proceed with previous errors */ + check_error(); + + /* There should be a stored coredump now if backend has storage */ + ret = coredump_cmd(COREDUMP_CMD_ERASE_STORED_DUMP, NULL); + if (ret == -ENOTSUP) { +#ifdef CONFIG_TEST_STORED_COREDUMP + TC_ERROR("Can't erase stored dump: unexpectedly not supported.\n"); + ztest_test_fail(); +#else + TC_PRINT("Can't erase stored dump: expectedly not supported.\n"); + ztest_test_skip(); +#endif + } else if (ret == 0) { +#ifdef CONFIG_TEST_STORED_COREDUMP + check_error(); + ztest_test_pass(); +#else + TC_ERROR("Can't erase the stored dump: not supported.\n"); + ztest_test_fail(); +#endif + } else { + TC_ERROR("Error erasing stored dump! (%d)\n", ret); + ztest_test_fail(); + } +} + +void test_get_stored_dump_size(int size_expected) +{ + int ret; + + /* Cannot proceed with previous errors */ + check_error(); + + ret = coredump_query(COREDUMP_QUERY_GET_STORED_DUMP_SIZE, NULL); + if (ret == -ENOTSUP) { +#ifdef CONFIG_TEST_STORED_COREDUMP + TC_ERROR("Can't query stored dump size: unexpectedly not supported.\n"); + ztest_test_fail(); +#else + TC_PRINT("Can't query stored dump size: expectedly not supported.\n"); + ztest_test_skip(); +#endif + } else if (ret >= 0) { +#ifdef CONFIG_TEST_STORED_COREDUMP + check_error(); + if (size_expected > 0) { + zassert_equal(ret, size_expected, + "Coredump size %d != %d size expected.\n", + ret, size_expected); + } + ztest_test_pass(); +#else + TC_ERROR("Can't have a stored dump: not supported.\n"); + ztest_test_fail(); +#endif + } else { + TC_ERROR("Error reading stored dump size! (%d)\n", ret); + ztest_test_fail(); + } +} + +/* Excecute tests in exact sequence with the stored core dump. */ + +ZTEST(coredump_backends, test_coredump_0_ready) { + check_error(); + ztest_test_pass(); +} + +ZTEST(coredump_backends, test_coredump_1_stored) { + test_has_stored_dump(true); +} + +ZTEST(coredump_backends, test_coredump_2_size) { + test_get_stored_dump_size(CONFIG_TEST_STORED_DUMP_SIZE); +} + +ZTEST(coredump_backends, test_coredump_3_verify) { test_verify_stored_dump(); } -ZTEST_SUITE(coredump_backends, NULL, NULL, NULL, NULL, NULL); +ZTEST(coredump_backends, test_coredump_4_invalidate) { + test_invalidate_stored_dump(); +} + +ZTEST(coredump_backends, test_coredump_5_erase) { + test_erase_stored_dump(); +} + +ZTEST_SUITE(coredump_backends, NULL, raise_coredump, NULL, NULL, NULL); diff --git a/tests/subsys/debug/coredump_backends/testcase.yaml b/tests/subsys/debug/coredump_backends/testcase.yaml index d7c8fccdaa9..d7b5f722f37 100644 --- a/tests/subsys/debug/coredump_backends/testcase.yaml +++ b/tests/subsys/debug/coredump_backends/testcase.yaml @@ -2,22 +2,21 @@ common: tags: coredump ignore_faults: true ignore_qemu_crash: true + arch_exclude: + - posix integration_platforms: - qemu_x86 tests: debug.coredump.backends.logging: filter: CONFIG_ARCH_SUPPORTS_COREDUMP platform_exclude: acrn_ehl_crb - harness: console - harness_config: - type: multi_line - regex: - - "E: #CD:BEGIN#" - - "E: #CD:5([aA])45([0-9a-fA-F]+)" - - "E: #CD:END#" + extra_configs: + - CONFIG_TEST_STORED_COREDUMP=n debug.coredump.backends.flash: filter: CONFIG_ARCH_SUPPORTS_COREDUMP extra_args: CONF_FILE=prj_flash_partition.conf + extra_configs: + - CONFIG_TEST_STORED_COREDUMP=y platform_allow: - qemu_x86 - esp32_devkitc_wroom @@ -28,4 +27,6 @@ tests: debug.coredump.backends.other: filter: CONFIG_ARCH_SUPPORTS_COREDUMP extra_args: CONF_FILE=prj_backend_other.conf + extra_configs: + - CONFIG_TEST_STORED_COREDUMP=y platform_exclude: acrn_ehl_crb diff --git a/tests/subsys/debug/gdbstub/CMakeLists.txt b/tests/subsys/debug/gdbstub/CMakeLists.txt new file mode 100644 index 00000000000..69377e717f5 --- /dev/null +++ b/tests/subsys/debug/gdbstub/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(debug_gdbstub) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/subsys/debug/gdbstub/boards/qemu_x86.overlay b/tests/subsys/debug/gdbstub/boards/qemu_x86.overlay similarity index 100% rename from samples/subsys/debug/gdbstub/boards/qemu_x86.overlay rename to tests/subsys/debug/gdbstub/boards/qemu_x86.overlay diff --git a/tests/subsys/debug/gdbstub/prj.conf b/tests/subsys/debug/gdbstub/prj.conf new file mode 100644 index 00000000000..8b490380226 --- /dev/null +++ b/tests/subsys/debug/gdbstub/prj.conf @@ -0,0 +1,5 @@ +CONFIG_GDBSTUB=y +CONFIG_GDBSTUB_SERIAL_BACKEND=y +CONFIG_NO_OPTIMIZATIONS=y +CONFIG_USERSPACE=y +CONFIG_KOBJECT_TEXT_AREA=4096 diff --git a/tests/subsys/debug/gdbstub/pytest/conftest.py b/tests/subsys/debug/gdbstub/pytest/conftest.py new file mode 100644 index 00000000000..12d5ced7590 --- /dev/null +++ b/tests/subsys/debug/gdbstub/pytest/conftest.py @@ -0,0 +1,25 @@ +# +# Copyright (c) 2023 intel Corporation. +# +# SPDX-License-Identifier: Apache-2.0 +# + +import pytest + +def pytest_addoption(parser): + parser.addoption('--gdb_target_remote') + parser.addoption('--gdb_timeout') + parser.addoption('--gdb_script') + +@pytest.fixture() +def gdb_script(request): + return request.config.getoption('--gdb_script') + +@pytest.fixture() +def gdb_timeout(request): + return int(request.config.getoption('--gdb_timeout', default=60)) + +@pytest.fixture() +def gdb_target_remote(request): + return request.config.getoption('--gdb_target_remote', default=":5678") +# diff --git a/tests/subsys/debug/gdbstub/pytest/test_gdbstub.py b/tests/subsys/debug/gdbstub/pytest/test_gdbstub.py new file mode 100755 index 00000000000..fe063905df7 --- /dev/null +++ b/tests/subsys/debug/gdbstub/pytest/test_gdbstub.py @@ -0,0 +1,83 @@ +# Copyright (c) 2023 Intel Corporation. +# +# SPDX-License-Identifier: Apache-2.0 + +import os +import subprocess +import sys +import logging +import shlex +import re +import pytest +from twister_harness import DeviceAdapter + +ZEPHYR_BASE = os.getenv("ZEPHYR_BASE") +sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts", "pylib", "twister")) +from twisterlib.cmakecache import CMakeCache + +logger = logging.getLogger(__name__) + +@pytest.fixture() +def gdb_process(dut: DeviceAdapter, gdb_script, gdb_timeout, gdb_target_remote) -> subprocess.CompletedProcess: + build_dir = dut.device_config.build_dir + cmake_cache = CMakeCache.from_file(os.path.join(build_dir, 'CMakeCache.txt')) + gdb_exec = cmake_cache.get('CMAKE_GDB', None) + assert gdb_exec + source_dir = cmake_cache.get('APPLICATION_SOURCE_DIR', None) + assert source_dir + build_image = cmake_cache.get('BYPRODUCT_KERNEL_ELF_NAME', None) + assert build_image + gdb_log_file = os.path.join(build_dir, 'gdb.log') + cmd = [gdb_exec, '-batch', + '-ex', f'set pagination off', + '-ex', f'set trace-commands on', + '-ex', f'set logging file {gdb_log_file}', + '-ex', f'set logging enabled on', + '-ex', f'target remote {gdb_target_remote}', + '-x', f'{source_dir}/{gdb_script}', build_image] + logger.info(f'Run GDB: {shlex.join(cmd)}') + result = subprocess.run(cmd, capture_output=True, text=True, timeout=gdb_timeout) + logger.info(f'GDB ends rc={result.returncode}') + return result +# + +@pytest.fixture(scope="module") +def expected_app(): + return [ + re.compile(r"Booting from ROM"), + re.compile(r"Booting Zephyr OS build"), + re.compile(r"main\(\):enter"), + ] + +@pytest.fixture(scope="module") +def expected_gdb(): + return [ + re.compile(r'Breakpoint 1 at 0x'), + re.compile(r'Breakpoint 2 at 0x'), + re.compile(r'Breakpoint 1, test '), + re.compile(r'Breakpoint 2, main '), + re.compile(r'GDB:PASSED'), + ] + +@pytest.fixture(scope="module") +def expected_gdb_detach(): + return [ + re.compile(r'Inferior.*will be killed'), # Zephyr gdbstub + re.compile(r'Inferior.*detached') # QEMU gdbstub + ] + + +def test_gdbstub(dut: DeviceAdapter, gdb_process, expected_app, expected_gdb, expected_gdb_detach): + """ + Test gdbstub feature using a GDB script. We connect to the DUT, run the + GDB script then evaluate return code and expected patterns at the GDB + and Test Applicaiton outputs. + """ + logger.debug(f"GDB output:\n{gdb_process.stdout}\n") + assert gdb_process.returncode == 0 + assert all([ex_re.search(gdb_process.stdout, re.MULTILINE) for ex_re in expected_gdb]), 'No expected GDB output' + assert any([ex_re.search(gdb_process.stdout, re.MULTILINE) for ex_re in expected_gdb_detach]), 'No expected GDB quit' + app_output = '\n'.join(dut.readlines(print_output = False)) + logger.debug(f"App output:\n{app_output}\n") + assert all([ex_re.search(app_output, re.MULTILINE) for ex_re in expected_app]), 'No expected Application output' +# diff --git a/tests/subsys/debug/gdbstub/src/main.c b/tests/subsys/debug/gdbstub/src/main.c new file mode 100644 index 00000000000..4d54f6b2ff9 --- /dev/null +++ b/tests/subsys/debug/gdbstub/src/main.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#define STACKSIZE 512 + +static int test(void) +{ + int a; + int b; + + a = 10; + b = a * 2; + + return a + b; +} + +int main(void) +{ + int ret; + + printk("%s():enter\n", __func__); + ret = test(); + printk("ret=%d\n", ret); + return 0; +} diff --git a/tests/subsys/debug/gdbstub/test_breakpoints.gdbinit b/tests/subsys/debug/gdbstub/test_breakpoints.gdbinit new file mode 100644 index 00000000000..d79e1aa5f28 --- /dev/null +++ b/tests/subsys/debug/gdbstub/test_breakpoints.gdbinit @@ -0,0 +1,17 @@ +b test +b main.c:29 +c + +# break at test() +s +set var a = 2 +c + +# break at main() +if ret == 6 + printf "GDB:PASSED\n" + quit 0 +else + printf "GDB:FAILED\n" + quit 1 +end diff --git a/tests/subsys/debug/gdbstub/testcase.yaml b/tests/subsys/debug/gdbstub/testcase.yaml new file mode 100644 index 00000000000..adb259b4122 --- /dev/null +++ b/tests/subsys/debug/gdbstub/testcase.yaml @@ -0,0 +1,59 @@ +# +# Copyright (c) 2020, 2023 intel Corporation. +# +# SPDX-License-Identifier: Apache-2.0 +# + +tests: + # Connect to Zephyr gdbstub and run a simple GDB script + debug.gdbstub.breakpoints: + platform_allow: qemu_x86 + harness: pytest + harness_config: + pytest_root: + - "pytest/test_gdbstub.py" + pytest_args: + - "--gdb_timeout" + - "20" + - "--gdb_script" + - "test_breakpoints.gdbinit" + - "--gdb_target_remote" + - "tcp::5678" + tags: + - debug + - gdbstub + extra_configs: + # Make sure the gdbstub port chosen is unique for this test to avoid conflicts + # when Twister runs tests in parallel on the same host. + - CONFIG_QEMU_EXTRA_FLAGS="-serial tcp::5678,server" + + # Connect to QEMU gdbstub backend and run the same GDB test script + # to check it against a reference RDP backend implementation expecting + # similar behavior as for Zephyr's gdbstub. + # Use non-default QEMU gdbstub port 1235 for this test to avoid conflicts + # with some other test on QEMU running in parallel. + debug.gdbstub_qemu.breakpoints: + platform_allow: qemu_x86 + harness: pytest + harness_config: + pytest_root: + - "pytest/test_gdbstub.py" + pytest_args: + - "--gdb_timeout" + - "20" + - "--gdb_script" + - "test_breakpoints.gdbinit" + - "--gdb_target_remote" + - "tcp::1235" + tags: + - debug + - gdbstub + extra_configs: + # Turn off Zephyr's gdbstub for this test case. + - CONFIG_GDBSTUB=n + - CONFIG_GDBSTUB_SERIAL_BACKEND=n + # Make sure the gdbstub port chosen is unique for this test to avoid conflicts + # when Twister runs tests in parallel on the same host. + - CONFIG_QEMU_EXTRA_FLAGS="-S -gdb tcp::1235" + # Clear QEMU default 'tcp::1234' + - CONFIG_QEMU_GDBSERVER_LISTEN_DEV="" diff --git a/tests/subsys/dfu/img_util/prj.conf b/tests/subsys/dfu/img_util/prj.conf index b8183095aaf..6beb6b102a0 100644 --- a/tests/subsys/dfu/img_util/prj.conf +++ b/tests/subsys/dfu/img_util/prj.conf @@ -7,4 +7,3 @@ CONFIG_IMG_MANAGER=y CONFIG_IMG_ENABLE_IMAGE_CHECK=y CONFIG_MCUBOOT_IMG_MANAGER=y CONFIG_IMG_BLOCK_BUF_SIZE=512 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/dfu/mcuboot/prj.conf b/tests/subsys/dfu/mcuboot/prj.conf index ebef72eb7e8..ddd227b82ca 100644 --- a/tests/subsys/dfu/mcuboot/prj.conf +++ b/tests/subsys/dfu/mcuboot/prj.conf @@ -6,4 +6,3 @@ CONFIG_STREAM_FLASH=y CONFIG_IMG_MANAGER=y CONFIG_MCUBOOT_IMG_MANAGER=y CONFIG_IMG_BLOCK_BUF_SIZE=512 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/dfu/mcuboot_multi/prj.conf b/tests/subsys/dfu/mcuboot_multi/prj.conf index 2ec75613572..672058b3a26 100644 --- a/tests/subsys/dfu/mcuboot_multi/prj.conf +++ b/tests/subsys/dfu/mcuboot_multi/prj.conf @@ -7,4 +7,3 @@ CONFIG_IMG_MANAGER=y CONFIG_MCUBOOT_IMG_MANAGER=y CONFIG_IMG_BLOCK_BUF_SIZE=512 CONFIG_UPDATEABLE_IMAGE_NUMBER=2 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/dsp/basicmath/prj.conf b/tests/subsys/dsp/basicmath/prj.conf index 912a703fd9e..11333398dee 100644 --- a/tests/subsys/dsp/basicmath/prj.conf +++ b/tests/subsys/dsp/basicmath/prj.conf @@ -1,7 +1,5 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y -CONFIG_NEWLIB_LIBC=y +CONFIG_REQUIRES_FULL_LIBC=y CONFIG_DSP=y CONFIG_CMSIS_DSP=y -CONFIG_CMSIS_DSP_BASICMATH=y CONFIG_DSP_BACKEND_CMSIS=y diff --git a/tests/subsys/dsp/basicmath/prj_arc.conf b/tests/subsys/dsp/basicmath/prj_arc.conf index c84bec1f3d9..e0558196361 100644 --- a/tests/subsys/dsp/basicmath/prj_arc.conf +++ b/tests/subsys/dsp/basicmath/prj_arc.conf @@ -1,8 +1,6 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ARCMWDT_LIBC=y CONFIG_CPLUSPLUS=y CONFIG_DSP=y CONFIG_CMSIS_DSP=y -CONFIG_CMSIS_DSP_BASICMATH=y CONFIG_DSP_BACKEND_ARCMWDT=y diff --git a/tests/subsys/dsp/basicmath/testcase.yaml b/tests/subsys/dsp/basicmath/testcase.yaml index e99c6d09a0c..ef0996a4b38 100644 --- a/tests/subsys/dsp/basicmath/testcase.yaml +++ b/tests/subsys/dsp/basicmath/testcase.yaml @@ -1,6 +1,6 @@ tests: zdsp.basicmath: - filter: TOOLCHAIN_HAS_NEWLIB == 1 or CONFIG_ARCH_POSIX + filter: CONFIG_FULL_LIBC_SUPPORTED or CONFIG_ARCH_POSIX integration_platforms: - frdm_k64f - sam_e70_xplained @@ -10,7 +10,7 @@ tests: min_flash: 128 min_ram: 64 zdsp.basicmath.fpu: - filter: (CONFIG_CPU_HAS_FPU and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX + filter: (CONFIG_CPU_HAS_FPU and CONFIG_FULL_LIBC_SUPPORTED) or CONFIG_ARCH_POSIX integration_platforms: - mps2_an521_remote - mps3_an547 diff --git a/tests/subsys/dsp/print_format/CMakeLists.txt b/tests/subsys/dsp/print_format/CMakeLists.txt new file mode 100644 index 00000000000..08878fc0c41 --- /dev/null +++ b/tests/subsys/dsp/print_format/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(zdsp_conversions) + +target_sources(app PRIVATE src/main.c) diff --git a/tests/subsys/dsp/print_format/prj.conf b/tests/subsys/dsp/print_format/prj.conf new file mode 100644 index 00000000000..a957f807430 --- /dev/null +++ b/tests/subsys/dsp/print_format/prj.conf @@ -0,0 +1,4 @@ +CONFIG_ZTEST=y +CONFIG_REQUIRES_FULL_LIBC=y +CONFIG_DSP=y +CONFIG_CMSIS_DSP=y diff --git a/tests/subsys/dsp/print_format/src/main.c b/tests/subsys/dsp/print_format/src/main.c new file mode 100644 index 00000000000..fcaff86113a --- /dev/null +++ b/tests/subsys/dsp/print_format/src/main.c @@ -0,0 +1,161 @@ +/* Copyright (c) 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#define float_multiplier(type) ((INT64_C(1) << (8 * sizeof(type) - 1)) - 1) + +#define assert_strings(expected, actual) \ + zexpect_equal(strlen(expected), strlen(actual), "Expected %d(%s), got %d(%s)", \ + strlen(expected), expected, strlen(actual), actual); \ + zexpect_mem_equal(expected, actual, MIN(strlen(expected), strlen(actual)), \ + "Expected '%s', got '%s'", expected, actual) + +ZTEST_SUITE(zdsp_print_format, NULL, NULL, NULL, NULL, NULL); + +ZTEST(zdsp_print_format, test_print_q31_precision_positive) +{ + char buffer[256]; + q31_t q = (q31_t)0x0f5c28f0; /* 0.119999997 */ + + snprintf(buffer, 256, "%" PRIq(6), PRIq_arg(q, 6, 0)); + assert_strings("0.119999", buffer); + + snprintf(buffer, 256, "%" PRIq(6), PRIq_arg(q, 6, 1)); + assert_strings("0.239999", buffer); + + snprintf(buffer, 256, "%" PRIq(6), PRIq_arg(q, 6, -2)); + assert_strings("0.029999", buffer); + + snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, 0)); + assert_strings("0.1199", buffer); + + snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, 1)); + assert_strings("0.2399", buffer); + + snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, -2)); + assert_strings("0.0299", buffer); +} + +ZTEST(zdsp_print_format, test_print_q31_precision_negative) +{ + char buffer[256]; + q31_t q = (q31_t)0x83d70a00; /* -0.970000029 */ + + snprintf(buffer, 256, "%" PRIq(6), PRIq_arg(q, 6, 0)); + assert_strings("-0.970000", buffer); + + snprintf(buffer, 256, "%" PRIq(6), PRIq_arg(q, 6, 1)); + assert_strings("-1.940000", buffer); + + snprintf(buffer, 256, "%" PRIq(6), PRIq_arg(q, 6, -2)); + assert_strings("-0.242500", buffer); + + snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, 0)); + assert_strings("-0.9700", buffer); + + snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, 1)); + assert_strings("-1.9400", buffer); + + snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, -2)); + assert_strings("-0.2425", buffer); +} + +ZTEST(zdsp_print_format, test_print_q15_precision_positive) +{ + char buffer[256]; + q15_t q = (q15_t)0x28f5; /* 0.319986672 */ + + snprintf(buffer, 256, "%" PRIq(5), PRIq_arg(q, 5, 0)); + assert_strings("0.31997", buffer); + + snprintf(buffer, 256, "%" PRIq(5), PRIq_arg(q, 5, 1)); + assert_strings("0.63995", buffer); + + snprintf(buffer, 256, "%" PRIq(5), PRIq_arg(q, 5, -2)); + assert_strings("0.07999", buffer); + + snprintf(buffer, 256, "%" PRIq(3), PRIq_arg(q, 3, 0)); + assert_strings("0.319", buffer); + + snprintf(buffer, 256, "%" PRIq(3), PRIq_arg(q, 3, 1)); + assert_strings("0.639", buffer); + + snprintf(buffer, 256, "%" PRIq(3), PRIq_arg(q, 3, -2)); + assert_strings("0.079", buffer); +} + +ZTEST(zdsp_print_format, test_print_q15_precision_negative) +{ + char buffer[256]; + q15_t q = (q15_t)0xc4bd; /* -0.462965789 */ + + snprintf(buffer, 256, "%" PRIq(5), PRIq_arg(q, 5, 0)); + assert_strings("-0.46298", buffer); + + snprintf(buffer, 256, "%" PRIq(5), PRIq_arg(q, 5, 1)); + assert_strings("-0.92596", buffer); + + snprintf(buffer, 256, "%" PRIq(5), PRIq_arg(q, 5, -2)); + assert_strings("-0.11574", buffer); + + snprintf(buffer, 256, "%" PRIq(3), PRIq_arg(q, 3, 0)); + assert_strings("-0.462", buffer); + + snprintf(buffer, 256, "%" PRIq(3), PRIq_arg(q, 3, 1)); + assert_strings("-0.925", buffer); + + snprintf(buffer, 256, "%" PRIq(3), PRIq_arg(q, 3, -2)); + assert_strings("-0.115", buffer); +} + +ZTEST(zdsp_print_format, test_print_q7_precision_positive) +{ + char buffer[256]; + q7_t q = (q7_t)0x01; /* 0.007874016 */ + + snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, 0)); + assert_strings("0.0078", buffer); + + snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, 1)); + assert_strings("0.0156", buffer); + + snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, -2)); + assert_strings("0.0019", buffer); + + snprintf(buffer, 256, "%" PRIq(2), PRIq_arg(q, 2, 0)); + assert_strings("0.00", buffer); + + snprintf(buffer, 256, "%" PRIq(2), PRIq_arg(q, 2, 1)); + assert_strings("0.01", buffer); + + snprintf(buffer, 256, "%" PRIq(2), PRIq_arg(q, 2, -2)); + assert_strings("0.00", buffer); +} + +ZTEST(zdsp_print_format, test_print_q7_precision_negative) +{ + char buffer[256]; + q7_t q = (q7_t)0xe2; /* -0.228346457 */ + + snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, 0)); + assert_strings("-0.2343", buffer); + + snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, 1)); + assert_strings("-0.4687", buffer); + + snprintf(buffer, 256, "%" PRIq(4), PRIq_arg(q, 4, -2)); + assert_strings("-0.0585", buffer); + + snprintf(buffer, 256, "%" PRIq(2), PRIq_arg(q, 2, 0)); + assert_strings("-0.23", buffer); + + snprintf(buffer, 256, "%" PRIq(2), PRIq_arg(q, 2, 1)); + assert_strings("-0.46", buffer); + + snprintf(buffer, 256, "%" PRIq(2), PRIq_arg(q, 2, -2)); + assert_strings("-0.05", buffer); +} diff --git a/tests/subsys/dsp/print_format/testcase.yaml b/tests/subsys/dsp/print_format/testcase.yaml new file mode 100644 index 00000000000..910e92119b0 --- /dev/null +++ b/tests/subsys/dsp/print_format/testcase.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 +tests: + zdsp.print_format: + filter: CONFIG_FULL_LIBC_SUPPORTED or CONFIG_ARCH_POSIX + tags: zdsp + min_flash: 128 + min_ram: 64 diff --git a/tests/subsys/edac/ibecc/README.rst b/tests/subsys/edac/ibecc/README.rst index 52f4e16cf78..b6f4ff11ead 100644 --- a/tests/subsys/edac/ibecc/README.rst +++ b/tests/subsys/edac/ibecc/README.rst @@ -3,8 +3,7 @@ Testing Error Detection and Correction ###################################### -Tests verify API and use error injection method to inject -errors. +Tests verify API and use error injection method to inject errors. Prerequisites ************* @@ -12,11 +11,11 @@ Prerequisites IBECC should be enabled in BIOS. This is usually enabled in the default BIOS configuration. Verify following is enabled:: - Intel Advanced Menu -> Memory Configuration -> In-Band ECC -> +:menuselection:`Intel Advanced Menu --> Memory Configuration --> In-Band ECC --> Enabled` Verify also operational mode with:: - Intel Advanced Menu -> Memory Configuration -> In-Band ECC Operation Mode -> 2 +:menuselection:`Intel Advanced Menu --> Memory Configuration --> In-Band ECC Operation Mode --> 2` For injection test Error Injection should be enabled. @@ -31,7 +30,7 @@ In order to use Error Injection user need to use BIOS Boot Guard 0 profile. Additionally Error Injection need to be enabled in the following BIOS menu:: - Intel Advanced Menu -> Memory Configuration -> In-Band ECC Error -> +:menuselection:`Intel Advanced Menu --> Memory Configuration --> In-Band ECC Error --> Enabled` .. note:: @@ -43,7 +42,7 @@ Additionally Error Injection need to be enabled in the following BIOS menu:: Building and Running ******************** -This project can be built as follows: +This project can be built as follows for the :ref:`intel_ehl_crb` board: .. zephyr-app-commands:: :zephyr-app: tests/subsys/edac/ibecc diff --git a/tests/subsys/edac/ibecc/prj.conf b/tests/subsys/edac/ibecc/prj.conf index 6dd0980fead..e82a8f1c952 100644 --- a/tests/subsys/edac/ibecc/prj.conf +++ b/tests/subsys/edac/ibecc/prj.conf @@ -2,4 +2,3 @@ CONFIG_ZTEST=y CONFIG_EDAC=y CONFIG_EDAC_IBECC=y CONFIG_LOG=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/edac/ibecc/src/ibecc.c b/tests/subsys/edac/ibecc/src/ibecc.c index 3b6c3c347f6..57e12ee5d1a 100644 --- a/tests/subsys/edac/ibecc/src/ibecc.c +++ b/tests/subsys/edac/ibecc/src/ibecc.c @@ -262,8 +262,10 @@ static void test_inject(const struct device *dev, uint64_t addr, uint64_t mask, zassert_equal(ret, 0, "Error setting ctrl"); } -static int check_values(void *p1, void *p2, void *p3) +static void check_values(void *p1, void *p2, void *p3) { + ARG_UNUSED(p3); + intptr_t address = (intptr_t)p1; intptr_t type = (intptr_t)p2; intptr_t addr, errtype; @@ -280,8 +282,6 @@ static int check_values(void *p1, void *p2, void *p3) /* Verify page address and error type */ zassert_equal(addr, address, "Error address wrong"); zassert_equal(errtype, type, "Error type wrong"); - - return 0; } static void ibecc_error_inject_test(uint64_t addr, uint64_t mask, uint64_t type) @@ -299,7 +299,7 @@ static void ibecc_error_inject_test(uint64_t addr, uint64_t mask, uint64_t type) test_inject(dev, addr, mask, type); #if defined(CONFIG_USERSPACE) - k_thread_user_mode_enter((k_thread_entry_t)check_values, + k_thread_user_mode_enter(check_values, (void *)addr, (void *)type, NULL); diff --git a/tests/subsys/edac/ibecc_cov/prj.conf b/tests/subsys/edac/ibecc_cov/prj.conf index f205f0515e0..9707ccfa2df 100644 --- a/tests/subsys/edac/ibecc_cov/prj.conf +++ b/tests/subsys/edac/ibecc_cov/prj.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y CONFIG_LOG=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/emul/prj.conf b/tests/subsys/emul/prj.conf index 452d3c4f157..81a9aca7dbd 100644 --- a/tests/subsys/emul/prj.conf +++ b/tests/subsys/emul/prj.conf @@ -3,6 +3,5 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SENSOR=y CONFIG_BMI160_TRIGGER_NONE=y diff --git a/tests/subsys/emul/src/main.c b/tests/subsys/emul/src/main.c index 7c18b6000f8..6ac1091827d 100644 --- a/tests/subsys/emul/src/main.c +++ b/tests/subsys/emul/src/main.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #define TEST_ACCEL DT_NODELABEL(test_bmi) diff --git a/tests/subsys/fs/ext2/prj.conf b/tests/subsys/fs/ext2/prj.conf index 8661fc9969e..8b965329f6b 100644 --- a/tests/subsys/fs/ext2/prj.conf +++ b/tests/subsys/fs/ext2/prj.conf @@ -4,10 +4,8 @@ CONFIG_FILE_SYSTEM_MKFS=y CONFIG_DISK_ACCESS=y CONFIG_DISK_DRIVER_RAM=y -CONFIG_DISK_RAM_VOLUME_SIZE=200 CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=4096 diff --git a/tests/subsys/fs/ext2/prj_big.conf b/tests/subsys/fs/ext2/prj_big.conf index 1a108557b47..1463ebfa8cc 100644 --- a/tests/subsys/fs/ext2/prj_big.conf +++ b/tests/subsys/fs/ext2/prj_big.conf @@ -4,14 +4,12 @@ CONFIG_FILE_SYSTEM_MKFS=y CONFIG_DISK_ACCESS=y CONFIG_DISK_DRIVER_RAM=y -CONFIG_DISK_RAM_VOLUME_SIZE=9000 CONFIG_EXT2_MAX_BLOCK_COUNT=20 CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=4096 CONFIG_APP_TEST_BIG=y diff --git a/tests/subsys/fs/ext2/prj_flash.conf b/tests/subsys/fs/ext2/prj_flash.conf index 741f45771af..ada4707349b 100644 --- a/tests/subsys/fs/ext2/prj_flash.conf +++ b/tests/subsys/fs/ext2/prj_flash.conf @@ -8,5 +8,4 @@ CONFIG_DISK_DRIVER_FLASH=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=4096 diff --git a/tests/subsys/fs/ext2/prj_sdcard.conf b/tests/subsys/fs/ext2/prj_sdcard.conf index 6089edf67c0..dcc472b4081 100644 --- a/tests/subsys/fs/ext2/prj_sdcard.conf +++ b/tests/subsys/fs/ext2/prj_sdcard.conf @@ -12,5 +12,4 @@ CONFIG_EXT2_DISK_STARTING_SECTOR=34 CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=4096 diff --git a/tests/subsys/fs/ext2/ramdisk_big.overlay b/tests/subsys/fs/ext2/ramdisk_big.overlay new file mode 100644 index 00000000000..0f0422c8fa4 --- /dev/null +++ b/tests/subsys/fs/ext2/ramdisk_big.overlay @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + ramdisk0 { + compatible = "zephyr,ram-disk"; + disk-name = "RAM"; + sector-size = <512>; + sector-count = <18000>; + }; +}; diff --git a/tests/subsys/fs/ext2/ramdisk_small.overlay b/tests/subsys/fs/ext2/ramdisk_small.overlay new file mode 100644 index 00000000000..8a4d7708a80 --- /dev/null +++ b/tests/subsys/fs/ext2/ramdisk_small.overlay @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + ramdisk0 { + compatible = "zephyr,ram-disk"; + disk-name = "RAM"; + sector-size = <512>; + sector-count = <400>; + }; +}; diff --git a/tests/subsys/fs/ext2/testcase.yaml b/tests/subsys/fs/ext2/testcase.yaml index 14654c83d0a..21615994ba6 100644 --- a/tests/subsys/fs/ext2/testcase.yaml +++ b/tests/subsys/fs/ext2/testcase.yaml @@ -3,10 +3,14 @@ common: tests: filesystem.ext2.default: platform_allow: native_posix native_posix_64 hifive_unmatched bl5340_dvk_cpuapp + extra_args: + - EXTRA_DTC_OVERLAY_FILE="ramdisk_small.overlay" filesystem.ext2.big: platform_allow: native_posix native_posix_64 - extra_args: CONF_FILE=prj_big.conf + extra_args: + - CONF_FILE=prj_big.conf + - EXTRA_DTC_OVERLAY_FILE="ramdisk_big.overlay" filesystem.ext2.sdcard: platform_allow: hifive_unmatched bl5340_dvk_cpuapp diff --git a/tests/subsys/fs/fat_fs_api/prj.conf b/tests/subsys/fs/fat_fs_api/prj.conf index 3a46ae26ed6..5e22d035728 100644 --- a/tests/subsys/fs/fat_fs_api/prj.conf +++ b/tests/subsys/fs/fat_fs_api/prj.conf @@ -4,6 +4,5 @@ CONFIG_LOG=y CONFIG_FAT_FILESYSTEM_ELM=y CONFIG_DISK_DRIVER_FLASH=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_FLASH=y CONFIG_FLASH_MAP=y diff --git a/tests/subsys/fs/fat_fs_api/prj_lfn.conf b/tests/subsys/fs/fat_fs_api/prj_lfn.conf index 6058670cdf6..eaa76d5d695 100644 --- a/tests/subsys/fs/fat_fs_api/prj_lfn.conf +++ b/tests/subsys/fs/fat_fs_api/prj_lfn.conf @@ -5,6 +5,5 @@ CONFIG_FAT_FILESYSTEM_ELM=y CONFIG_FS_FATFS_LFN=y CONFIG_DISK_DRIVER_FLASH=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_FLASH=y CONFIG_FLASH_MAP=y diff --git a/tests/subsys/fs/fat_fs_api/prj_mmc.conf b/tests/subsys/fs/fat_fs_api/prj_mmc.conf index 62e1d08de4d..e3e903f5a89 100644 --- a/tests/subsys/fs/fat_fs_api/prj_mmc.conf +++ b/tests/subsys/fs/fat_fs_api/prj_mmc.conf @@ -4,6 +4,5 @@ CONFIG_FAT_FILESYSTEM_ELM=y CONFIG_SPI=y CONFIG_GPIO=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MMC_VOLUME_NAME="NAND" CONFIG_MAIN_STACK_SIZE=4096 diff --git a/tests/subsys/fs/fat_fs_api/prj_native_posix_ram.conf b/tests/subsys/fs/fat_fs_api/prj_native_posix_ram.conf index 231fb7cf364..a7b02e5bce1 100644 --- a/tests/subsys/fs/fat_fs_api/prj_native_posix_ram.conf +++ b/tests/subsys/fs/fat_fs_api/prj_native_posix_ram.conf @@ -2,8 +2,6 @@ CONFIG_FILE_SYSTEM=y CONFIG_FILE_SYSTEM_MKFS=y CONFIG_LOG=y CONFIG_FAT_FILESYSTEM_ELM=y -CONFIG_DISK_DRIVER_RAM=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_FLASH=y CONFIG_FLASH_MAP=y diff --git a/tests/subsys/fs/fat_fs_api/ramdisk.overlay b/tests/subsys/fs/fat_fs_api/ramdisk.overlay new file mode 100644 index 00000000000..b76a5ef6161 --- /dev/null +++ b/tests/subsys/fs/fat_fs_api/ramdisk.overlay @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + ramdisk0 { + compatible = "zephyr,ram-disk"; + disk-name = "RAM"; + sector-size = <512>; + sector-count = <128>; + }; +}; diff --git a/tests/subsys/fs/fat_fs_api/src/test_fat.h b/tests/subsys/fs/fat_fs_api/src/test_fat.h index 9c168b4bccf..8048ef084cf 100644 --- a/tests/subsys/fs/fat_fs_api/src/test_fat.h +++ b/tests/subsys/fs/fat_fs_api/src/test_fat.h @@ -12,7 +12,7 @@ #include #ifdef CONFIG_DISK_DRIVER_RAM -#define DISK_NAME CONFIG_DISK_RAM_VOLUME_NAME +#define DISK_NAME "RAM" #elif defined(CONFIG_DISK_DRIVER_FLASH) #define DISK_NAME DT_PROP(DT_NODELABEL(test_disk), disk_name) #elif defined(CONFIG_DISK_DRIVER_SDMMC) diff --git a/tests/subsys/fs/fat_fs_api/testcase.yaml b/tests/subsys/fs/fat_fs_api/testcase.yaml index c6557e6f230..bc3927def92 100644 --- a/tests/subsys/fs/fat_fs_api/testcase.yaml +++ b/tests/subsys/fs/fat_fs_api/testcase.yaml @@ -15,7 +15,9 @@ tests: filter: dt_compat_enabled("zephyr,mmc-disk") filesystem.fat.ram.api: platform_allow: native_posix - extra_args: CONF_FILE="prj_native_posix_ram.conf" + extra_args: + - CONF_FILE="prj_native_posix_ram.conf" + - EXTRA_DTC_OVERLAY_FILE="ramdisk.overlay" filesystem.fat.api.reentrant: platform_allow: native_posix extra_configs: diff --git a/tests/subsys/fs/fat_fs_dual_drive/app.overlay b/tests/subsys/fs/fat_fs_dual_drive/app.overlay new file mode 100644 index 00000000000..59e564f8829 --- /dev/null +++ b/tests/subsys/fs/fat_fs_dual_drive/app.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + ramdisk0 { + compatible = "zephyr,ram-disk"; + disk-name = "RAM"; + sector-size = <512>; + sector-count = <160>; + }; + + ramdisk1 { + compatible = "zephyr,ram-disk"; + disk-name = "CF"; + sector-size = <512>; + sector-count = <160>; + }; +}; diff --git a/tests/subsys/fs/fat_fs_dual_drive/prj.conf b/tests/subsys/fs/fat_fs_dual_drive/prj.conf index 7ac2ebe96cc..1d31e8beb3b 100644 --- a/tests/subsys/fs/fat_fs_dual_drive/prj.conf +++ b/tests/subsys/fs/fat_fs_dual_drive/prj.conf @@ -3,7 +3,5 @@ CONFIG_LOG=y CONFIG_FAT_FILESYSTEM_ELM=y CONFIG_FS_FATFS_NUM_FILES=8 CONFIG_FS_FATFS_NUM_DIRS=8 -CONFIG_DISK_DRIVER_RAM=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MAIN_STACK_SIZE=2048 diff --git a/tests/subsys/fs/fat_fs_dual_drive/src/disk_access_test_drv.c b/tests/subsys/fs/fat_fs_dual_drive/src/disk_access_test_drv.c deleted file mode 100644 index 8af0f07a3ed..00000000000 --- a/tests/subsys/fs/fat_fs_dual_drive/src/disk_access_test_drv.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2018 Intel Corporation. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include -#include - -#define RAMDISK_SECTOR_SIZE 512 - -/* A 96KB RAM Disk, which meets ELM FAT fs's minimum block requirement. Fit for - * qemu testing (as it may exceed target's RAM limits). - */ -#define RAMDISK_VOLUME_SIZE (192 * RAMDISK_SECTOR_SIZE) -static uint8_t ramdisk_buf[RAMDISK_VOLUME_SIZE]; - -static void *lba_to_address(uint32_t lba) -{ - __ASSERT(((lba * RAMDISK_SECTOR_SIZE) < RAMDISK_VOLUME_SIZE), - "FS bound error"); - - return &ramdisk_buf[(lba * RAMDISK_SECTOR_SIZE)]; -} - -static int disk_ram_access_status(struct disk_info *disk) -{ - return DISK_STATUS_OK; -} - -static int disk_ram_access_init(struct disk_info *disk) -{ - return 0; -} - -static int disk_ram_access_read(struct disk_info *disk, uint8_t *buff, - uint32_t sector, uint32_t count) -{ - memcpy(buff, lba_to_address(sector), count * RAMDISK_SECTOR_SIZE); - - return 0; -} - -static int disk_ram_access_write(struct disk_info *disk, const uint8_t *buff, - uint32_t sector, uint32_t count) -{ - memcpy(lba_to_address(sector), buff, count * RAMDISK_SECTOR_SIZE); - - return 0; -} - -static int disk_ram_access_ioctl(struct disk_info *disk, uint8_t cmd, void *buff) -{ - switch (cmd) { - case DISK_IOCTL_CTRL_SYNC: - break; - case DISK_IOCTL_GET_SECTOR_COUNT: - *(uint32_t *)buff = RAMDISK_VOLUME_SIZE / RAMDISK_SECTOR_SIZE; - break; - case DISK_IOCTL_GET_SECTOR_SIZE: - *(uint32_t *)buff = RAMDISK_SECTOR_SIZE; - break; - case DISK_IOCTL_GET_ERASE_BLOCK_SZ: - *(uint32_t *)buff = 1U; - break; - default: - return -EINVAL; - } - - return 0; -} - -static struct disk_operations ram_disk_ops = { - .init = disk_ram_access_init, - .status = disk_ram_access_status, - .read = disk_ram_access_read, - .write = disk_ram_access_write, - .ioctl = disk_ram_access_ioctl, -}; - -static struct disk_info ram_disk = { - .name = "CF", - .ops = &ram_disk_ops, -}; - -static int disk_ram_test_init(void) -{ - - return disk_access_register(&ram_disk); -} - -SYS_INIT(disk_ram_test_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/tests/subsys/fs/fcb/prj.conf b/tests/subsys/fs/fcb/prj.conf index e41051fb35a..c30a352a0e4 100644 --- a/tests/subsys/fs/fcb/prj.conf +++ b/tests/subsys/fs/fcb/prj.conf @@ -5,4 +5,3 @@ CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_FLASH_MAP=y CONFIG_FCB=y CONFIG_FCB_ALLOW_FIXED_ENDMARKER=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/fs/fcb/testcase.yaml b/tests/subsys/fs/fcb/testcase.yaml index 4902bfa2a65..0d5d1938b25 100644 --- a/tests/subsys/fs/fcb/testcase.yaml +++ b/tests/subsys/fs/fcb/testcase.yaml @@ -10,9 +10,9 @@ tests: tags: flash_circural_buffer integration_platforms: - nrf52840dk_nrf52840 - filesystem.native_posix.fcb_0x00: + filesystem.fcb.native_posix.fcb_0x00: extra_args: DTC_OVERLAY_FILE=boards/native_posix_ev_0x00.overlay platform_allow: native_posix - filesystem.qemu_x86.fcb_0x00: + filesystem.fcb.qemu_x86.fcb_0x00: extra_args: DTC_OVERLAY_FILE=boards/qemu_x86_ev_0x00.overlay platform_allow: qemu_x86 diff --git a/tests/subsys/fs/fs_api/prj.conf b/tests/subsys/fs/fs_api/prj.conf index d5feeed8bff..47eb9e2362c 100644 --- a/tests/subsys/fs/fs_api/prj.conf +++ b/tests/subsys/fs/fs_api/prj.conf @@ -1,3 +1,2 @@ CONFIG_FILE_SYSTEM=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/fs/littlefs/prj.conf b/tests/subsys/fs/littlefs/prj.conf index 9ccaa0d4589..de33b272ae6 100644 --- a/tests/subsys/fs/littlefs/prj.conf +++ b/tests/subsys/fs/littlefs/prj.conf @@ -1,7 +1,6 @@ CONFIG_FILE_SYSTEM=y CONFIG_FILE_SYSTEM_MKFS=y CONFIG_FILE_SYSTEM_LITTLEFS=y -CONFIG_ZTEST_NEW_API=y CONFIG_MAIN_STACK_SIZE=4096 # Performance tests need custom buffer allocation diff --git a/tests/subsys/fs/multi-fs/prj.conf b/tests/subsys/fs/multi-fs/prj.conf index 179e66c9378..287f0363dca 100644 --- a/tests/subsys/fs/multi-fs/prj.conf +++ b/tests/subsys/fs/multi-fs/prj.conf @@ -6,11 +6,8 @@ CONFIG_FILE_SYSTEM_LITTLEFS=y CONFIG_LOG=y CONFIG_FS_LITTLEFS_FC_HEAP_SIZE=16384 CONFIG_FAT_FILESYSTEM_ELM=y -CONFIG_DISK_DRIVER_RAM=y -CONFIG_DISK_RAM_VOLUME_SIZE=80 CONFIG_HEAP_MEM_POOL_SIZE=4096 CONFIG_MAIN_STACK_SIZE=4096 CONFIG_ZTEST_STACK_SIZE=4096 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MAIN_STACK_SIZE=2048 diff --git a/tests/subsys/fs/multi-fs/prj_fs_shell.conf b/tests/subsys/fs/multi-fs/prj_fs_shell.conf index 8a0e59b1ffc..327e2b4f2fb 100644 --- a/tests/subsys/fs/multi-fs/prj_fs_shell.conf +++ b/tests/subsys/fs/multi-fs/prj_fs_shell.conf @@ -10,11 +10,8 @@ CONFIG_SHELL_BACKEND_DUMMY=y CONFIG_SHELL_CMD_BUFF_SIZE=90 CONFIG_FILE_SYSTEM_SHELL=y CONFIG_FAT_FILESYSTEM_ELM=y -CONFIG_DISK_DRIVER_RAM=y -CONFIG_DISK_RAM_VOLUME_SIZE=80 CONFIG_HEAP_MEM_POOL_SIZE=1024 CONFIG_MAIN_STACK_SIZE=1024 CONFIG_ZTEST_STACK_SIZE=4096 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_MAIN_STACK_SIZE=2048 diff --git a/tests/subsys/fs/multi-fs/ramdisk.overlay b/tests/subsys/fs/multi-fs/ramdisk.overlay new file mode 100644 index 00000000000..87ae21b1e64 --- /dev/null +++ b/tests/subsys/fs/multi-fs/ramdisk.overlay @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + ramdisk0 { + compatible = "zephyr,ram-disk"; + disk-name = "RAM"; + sector-size = <512>; + sector-count = <160>; + }; +}; diff --git a/tests/subsys/fs/multi-fs/testcase.yaml b/tests/subsys/fs/multi-fs/testcase.yaml index 07f543d64a4..b4c1e49d195 100644 --- a/tests/subsys/fs/multi-fs/testcase.yaml +++ b/tests/subsys/fs/multi-fs/testcase.yaml @@ -8,13 +8,17 @@ common: - littlefs tests: filesystem.multifs: + extra_args: + - EXTRA_DTC_OVERLAY_FILE="ramdisk.overlay" platform_allow: - native_posix - qemu_x86 integration_platforms: - native_posix filesystem.fs_shell: - extra_args: CONF_FILE="prj_fs_shell.conf" + extra_args: + - CONF_FILE="prj_fs_shell.conf" + - EXTRA_DTC_OVERLAY_FILE="ramdisk.overlay" platform_allow: - native_posix - qemu_x86 diff --git a/tests/subsys/fs/nvs/prj.conf b/tests/subsys/fs/nvs/prj.conf index b4b850229e7..7d7f4aec2e9 100644 --- a/tests/subsys/fs/nvs/prj.conf +++ b/tests/subsys/fs/nvs/prj.conf @@ -1,6 +1,5 @@ CONFIG_ZTEST=y CONFIG_ZTEST_STACK_SIZE=4096 -CONFIG_ZTEST_NEW_API=y CONFIG_STDOUT_CONSOLE=y CONFIG_FLASH=y diff --git a/tests/subsys/fs/nvs/testcase.yaml b/tests/subsys/fs/nvs/testcase.yaml index 83ae545ab22..fd8386ffbd7 100644 --- a/tests/subsys/fs/nvs/testcase.yaml +++ b/tests/subsys/fs/nvs/testcase.yaml @@ -3,10 +3,10 @@ common: tests: filesystem.nvs: platform_allow: qemu_x86 - filesystem.nvs_0x00: + filesystem.nvs.0x00: extra_args: DTC_OVERLAY_FILE=boards/qemu_x86_ev_0x00.overlay platform_allow: qemu_x86 - filesystem.nvs_cache: + filesystem.nvs.cache: extra_args: - CONFIG_NVS_LOOKUP_CACHE=y - CONFIG_NVS_LOOKUP_CACHE_SIZE=64 diff --git a/tests/subsys/input/api/prj.conf b/tests/subsys/input/api/prj.conf index bd3dc1ced37..dff5c3dc7f6 100644 --- a/tests/subsys/input/api/prj.conf +++ b/tests/subsys/input/api/prj.conf @@ -1,5 +1,4 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_INPUT=y diff --git a/tests/subsys/input/input_longpress/prj.conf b/tests/subsys/input/input_longpress/prj.conf index b101f410c69..bc713698bbf 100644 --- a/tests/subsys/input/input_longpress/prj.conf +++ b/tests/subsys/input/input_longpress/prj.conf @@ -1,6 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_INPUT=y CONFIG_INPUT_MODE_SYNCHRONOUS=y diff --git a/tests/subsys/ipc/ipc_service/prj.conf b/tests/subsys/ipc/ipc_service/prj.conf index 67befb6214a..01e20c4e9b9 100644 --- a/tests/subsys/ipc/ipc_service/prj.conf +++ b/tests/subsys/ipc/ipc_service/prj.conf @@ -4,4 +4,3 @@ CONFIG_ZTEST=y CONFIG_MMU=y CONFIG_IPC_SERVICE=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/ipc/pbuf/CMakeLists.txt b/tests/subsys/ipc/pbuf/CMakeLists.txt new file mode 100644 index 00000000000..9d12b21862b --- /dev/null +++ b/tests/subsys/ipc/pbuf/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(ipc_pbuf) + +FILE(GLOB app_sources src/main.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/subsys/ipc/pbuf/prj.conf b/tests/subsys/ipc/pbuf/prj.conf new file mode 100644 index 00000000000..8580c4f26a5 --- /dev/null +++ b/tests/subsys/ipc/pbuf/prj.conf @@ -0,0 +1,7 @@ +CONFIG_ZTEST=y +CONFIG_ZTRESS=y +CONFIG_ZTEST_SHUFFLE=y + +CONFIG_IPC_SERVICE=y +CONFIG_IPC_SERVICE_ICMSG=y +CONFIG_PBUF=y diff --git a/tests/subsys/ipc/pbuf/src/main.c b/tests/subsys/ipc/pbuf/src/main.c new file mode 100644 index 00000000000..7a20fc9bdd6 --- /dev/null +++ b/tests/subsys/ipc/pbuf/src/main.c @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + + +#define MEM_AREA_SZ 256 +#define MPS 240 +#define MSGA_SZ 11 +#define MSGB_SZ 25 + +static char memory_area[MEM_AREA_SZ] __aligned(32); + +static void print_pbuf_info(struct pbuf *pb) +{ + printk("----------stats start-----------\n"); + printk("cfg->rd_idx_loc: %p, val: %u\n", pb->cfg->rd_idx_loc, *(pb->cfg->rd_idx_loc)); + printk("cfg->wr_idx_loc: %p, val: %u\n", pb->cfg->wr_idx_loc, *(pb->cfg->wr_idx_loc)); + printk("cfg->data_loc: %p\n", pb->cfg->data_loc); + printk("cfg->len: %u\n", pb->cfg->len); + printk("cfg->dcache_alignment: %u\n", pb->cfg->dcache_alignment); + + printk("data.rd_idx: %u\n", pb->data.rd_idx); + printk("data.wr_idx: %u\n", pb->data.wr_idx); + printk("-----------stats end------------\n"); +} + +/* Read/write tests. */ +ZTEST(test_pbuf, test_rw) +{ + uint8_t read_buf[MEM_AREA_SZ] = {0}; + uint8_t write_buf[MEM_AREA_SZ]; + int ret; + + BUILD_ASSERT(MSGA_SZ < MEM_AREA_SZ); + BUILD_ASSERT(MSGB_SZ < MEM_AREA_SZ); + BUILD_ASSERT(MPS < MEM_AREA_SZ); + + /* TODO: Use PBUF_DEFINE(). + * The user should use PBUF_DEFINE() macro to define the buffer, + * however for the purpose of this test PBUF_CFG_INIT() is used in + * order to avoid clang complains about memory_area not being constant + * expression. + */ + static const struct pbuf_cfg cfg = PBUF_CFG_INIT(memory_area, MEM_AREA_SZ, 0); + + static struct pbuf pb = { + .cfg = &cfg, + }; + + for (size_t i = 0; i < MEM_AREA_SZ; i++) { + write_buf[i] = i+1; + } + + zassert_equal(pbuf_init(&pb), 0); + + /* Write MSGA_SZ bytes packet. */ + ret = pbuf_write(&pb, write_buf, MSGA_SZ); + zassert_equal(ret, MSGA_SZ); + + /* Write MSGB_SZ bytes packet. */ + ret = pbuf_write(&pb, write_buf+MSGA_SZ, MSGB_SZ); + zassert_equal(ret, MSGB_SZ); + + /* Get the number of bytes stored. */ + ret = pbuf_read(&pb, NULL, 0); + zassert_equal(ret, MSGA_SZ); + /* Attempt to read with too small read buffer. */ + ret = pbuf_read(&pb, read_buf, ret-1); + zassert_equal(ret, -ENOMEM); + /* Read the packet. */ + ret = pbuf_read(&pb, read_buf, ret); + zassert_equal(ret, MSGA_SZ); + /* Check data corectness. */ + zassert_mem_equal(read_buf, write_buf, ret); + + /* Get the number of bytes stored. */ + ret = pbuf_read(&pb, NULL, 0); + zassert_equal(ret, MSGB_SZ); + /* Read the packet. */ + ret = pbuf_read(&pb, read_buf, ret); + zassert_equal(ret, MSGB_SZ); + /* Check data corectness. */ + zassert_mem_equal(read_buf, write_buf+MSGA_SZ, ret); + + /* Get the number of bytes stored. */ + ret = pbuf_read(&pb, NULL, 0); + zassert_equal(ret, 0); + + /* Write max packet size with wrapping around. */ + ret = pbuf_write(&pb, write_buf, MPS); + zassert_equal(ret, MPS); + /* Get the number of bytes stored. */ + ret = pbuf_read(&pb, NULL, 0); + zassert_equal(ret, MPS); + /* Read max packet size with wrapp around. */ + ret = pbuf_read(&pb, read_buf, ret); + zassert_equal(ret, MPS); + /* Check data corectness. */ + zassert_mem_equal(write_buf, read_buf, MPS); +} + +/* API ret codes tests. */ +ZTEST(test_pbuf, test_retcodes) +{ + /* TODO: Use PBUF_DEFINE(). + * The user should use PBUF_DEFINE() macro to define the buffer, + * however for the purpose of this test PBUF_CFG_INIT() is used in + * order to avoid clang complains about memory_area not being constant + * expression. + */ + static const struct pbuf_cfg cfg0 = PBUF_CFG_INIT(memory_area, MEM_AREA_SZ, 32); + static const struct pbuf_cfg cfg1 = PBUF_CFG_INIT(memory_area, MEM_AREA_SZ, 0); + static const struct pbuf_cfg cfg2 = PBUF_CFG_INIT(memory_area, 20, 4); + + static struct pbuf pb0 = { + .cfg = &cfg0, + }; + + static struct pbuf pb1 = { + .cfg = &cfg1, + }; + + static struct pbuf pb2 = { + .cfg = &cfg2, + }; + + /* Initialize buffers. */ + zassert_equal(pbuf_init(&pb0), 0); + zassert_equal(pbuf_init(&pb1), 0); + zassert_equal(pbuf_init(&pb2), 0); + + print_pbuf_info(&pb0); + print_pbuf_info(&pb1); + print_pbuf_info(&pb2); + + uint8_t read_buf[MEM_AREA_SZ]; + uint8_t write_buf[MEM_AREA_SZ]; + + for (size_t i = 0; i < MEM_AREA_SZ; i++) { + write_buf[i] = i+1; + } + + /* pbuf_write incorrect params tests. */ + zassert_equal(pbuf_write(NULL, write_buf, 10), -EINVAL); + zassert_equal(pbuf_write(&pb2, NULL, 10), -EINVAL); + zassert_equal(pbuf_write(&pb2, write_buf, 0), -EINVAL); + zassert_equal(pbuf_read(NULL, read_buf, 10), -EINVAL); + + /* Attempt to write more than the buffer can fit. */ + zassert_equal(pbuf_write(&pb2, write_buf, 5), -ENOMEM); + + /* Write maximal amount, the buffer fit. */ + zassert_equal(pbuf_write(&pb2, write_buf, 4), 4); + + /* Attempt to write to full buffer. */ + zassert_equal(pbuf_write(&pb2, write_buf, 1), -ENOMEM); + + /* Get the bytes stored. */ + zassert_equal(pbuf_read(&pb2, NULL, 1), 4); + + /* Attempt to read with too small read buffer. */ + zassert_equal(pbuf_read(&pb2, read_buf, 1), -ENOMEM); + + /* Get the bytes stored. */ + zassert_equal(pbuf_read(&pb2, NULL, 0), 4); + + /* Read the data with correct buffer size. */ + zassert_equal(pbuf_read(&pb2, read_buf, 4), 4); + + /* Check data correctness. */ + zassert_mem_equal(read_buf, write_buf, 4); + + /* Read from empty buffer. */ + zassert_equal(pbuf_read(&pb2, read_buf, 10), 0); + zassert_equal(pbuf_read(&pb2, read_buf, 10), 0); + zassert_equal(pbuf_read(&pb2, read_buf, 10), 0); +} + +#define STRESS_LEN_MOD (44) +#define STRESS_LEN_MIN (20) +#define STRESS_LEN_MAX (STRESS_LEN_MIN + STRESS_LEN_MOD) + +struct stress_data { + struct pbuf *pbuf; + uint32_t wr_cnt; + uint32_t rd_cnt; + uint32_t wr_err; +}; + +/* Check if buffer of len contains exp values. */ +static int check_buffer(char *buf, uint16_t len, char exp) +{ + for (uint16_t i = 0; i < len; i++) { + if (buf[i] != exp) { + return -EINVAL; + } + } + + return 0; +} + +bool stress_read(void *user_data, uint32_t cnt, bool last, int prio) +{ + struct stress_data *ctx = (struct stress_data *)user_data; + char buf[STRESS_LEN_MAX]; + int len; + int rpt = (sys_rand32_get() & 3) + 1; + + for (int i = 0; i < rpt; i++) { + len = pbuf_read(ctx->pbuf, buf, (uint16_t)sizeof(buf)); + if (len == 0) { + return true; + } + + if (len < 0) { + zassert_true(false, "Unexpected error: %d, cnt:%d", len, ctx->rd_cnt); + } + + zassert_ok(check_buffer(buf, len, ctx->rd_cnt)); + ctx->rd_cnt++; + } + + return true; +} + +bool stress_write(void *user_data, uint32_t cnt, bool last, int prio) +{ + struct stress_data *ctx = (struct stress_data *)user_data; + char buf[STRESS_LEN_MAX]; + + uint16_t len = STRESS_LEN_MIN + (sys_rand32_get() % STRESS_LEN_MOD); + int rpt = (sys_rand32_get() & 1) + 1; + + zassert_true(len < sizeof(buf)); + + for (int i = 0; i < rpt; i++) { + memset(buf, (uint8_t)ctx->wr_cnt, len); + int ret = pbuf_write(ctx->pbuf, buf, len); + + if (ret == len) { + ctx->wr_cnt++; + } else if (ret == -ENOMEM) { + ctx->wr_err++; + } else { + zassert_unreachable(); + } + } + + return true; +} + +ZTEST(test_pbuf, test_stress) +{ + static uint8_t buffer[MEM_AREA_SZ] __aligned(32); + static struct stress_data ctx = {}; + uint32_t repeat = 0; + + /* TODO: Use PBUF_DEFINE(). + * The user should use PBUF_DEFINE() macro to define the buffer, + * however for the purpose of this test PBUF_CFG_INIT() is used in + * order to avoid clang complains about buffer not being constant + * expression. + */ + static const struct pbuf_cfg cfg = PBUF_CFG_INIT(buffer, MEM_AREA_SZ, 4); + + static struct pbuf pb = { + .cfg = &cfg, + }; + + zassert_equal(pbuf_init(&pb), 0); + ctx.pbuf = &pb; + ctx.wr_cnt = 0; + ctx.rd_cnt = 0; + + ztress_set_timeout(K_MSEC(1500)); + TC_PRINT("Reading from an interrupt, writing from a thread\n"); + ZTRESS_EXECUTE(ZTRESS_TIMER(stress_read, &ctx, repeat, Z_TIMEOUT_TICKS(4)), + ZTRESS_THREAD(stress_write, &ctx, repeat, 2000, Z_TIMEOUT_TICKS(4))); + TC_PRINT("Writes:%d unsuccessful: %d\n", ctx.wr_cnt, ctx.wr_err); + + TC_PRINT("Writing from an interrupt, reading from a thread\n"); + ZTRESS_EXECUTE(ZTRESS_TIMER(stress_write, &ctx, repeat, Z_TIMEOUT_TICKS(4)), + ZTRESS_THREAD(stress_read, &ctx, repeat, 1000, Z_TIMEOUT_TICKS(4))); + TC_PRINT("Writes:%d unsuccessful: %d\n", ctx.wr_cnt, ctx.wr_err); +} + +ZTEST_SUITE(test_pbuf, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/subsys/ipc/pbuf/testcase.yaml b/tests/subsys/ipc/pbuf/testcase.yaml new file mode 100644 index 00000000000..4113335403a --- /dev/null +++ b/tests/subsys/ipc/pbuf/testcase.yaml @@ -0,0 +1,5 @@ +tests: + ipc.icmsg_pbuf: + integration_platforms: + - native_posix + timeout: 120 diff --git a/tests/subsys/jwt/prj.conf b/tests/subsys/jwt/prj.conf index fe632553ea3..6ac5548143d 100644 --- a/tests/subsys/jwt/prj.conf +++ b/tests/subsys/jwt/prj.conf @@ -19,6 +19,4 @@ CONFIG_MBEDTLS_USER_CONFIG_FILE="user-tls-conf.h" CONFIG_NET_SOCKETS=y -CONFIG_NEWLIB_LIBC=y - -CONFIG_ZTEST_NEW_API=y +CONFIG_REQUIRES_FULL_LIBC=y diff --git a/tests/subsys/jwt/testcase.yaml b/tests/subsys/jwt/testcase.yaml index a09a34a898c..f31beee498a 100644 --- a/tests/subsys/jwt/testcase.yaml +++ b/tests/subsys/jwt/testcase.yaml @@ -1,5 +1,5 @@ common: - filter: TOOLCHAIN_HAS_NEWLIB == 1 + filter: CONFIG_FULL_LIBC_SUPPORTED tests: libraries.encoding.jwt: min_ram: 96 diff --git a/tests/subsys/llext/CMakeLists.txt b/tests/subsys/llext/CMakeLists.txt new file mode 100644 index 00000000000..adb199761dd --- /dev/null +++ b/tests/subsys/llext/CMakeLists.txt @@ -0,0 +1,26 @@ +# Copyright (c) 2023 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(llext_test) + +add_subdirectory(hello_world) + +target_sources(app PRIVATE src/test_llext_simple.c) + +target_include_directories(app PRIVATE + ${ZEPHYR_BASE}/include + ${ZEPHYR_BASE}/kernel/include + ${ZEPHYR_BASE}/arch/${ARCH}/include + ) + +set(gen_dir ${ZEPHYR_BINARY_DIR}/include/generated/) + +generate_inc_file_for_target( + app + ${HELLO_WORLD_LLEXT} + ${gen_dir}/hello_world.inc + ) + +add_dependencies(app hello_world) diff --git a/tests/subsys/llext/hello_world/CMakeLists.txt b/tests/subsys/llext/hello_world/CMakeLists.txt new file mode 100644 index 00000000000..6519075e2f4 --- /dev/null +++ b/tests/subsys/llext/hello_world/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright (c) 2023 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(hello_world) + +# TODO check which architecture is being used +if(CONFIG_ARM) + set(CMAKE_C_FLAGS "-mlong-calls" "-mthumb") + + add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/hello_world.llext + COMMAND ${CMAKE_C_COMPILER} ${CMAKE_C_FLAGS} -c + -o ${PROJECT_BINARY_DIR}/hello_world.llext + ${PROJECT_SOURCE_DIR}/hello_world.c + ) +elseif(CONFIG_XTENSA) + set(CMAKE_C_FLAGS "-shared" "-fPIC" "-nostdlib" "-nodefaultlibs") + + add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/hello_world.llext + COMMAND ${CMAKE_C_COMPILER} ${CMAKE_C_FLAGS} + -o ${PROJECT_BINARY_DIR}/hello_world.pre.llext + ${PROJECT_SOURCE_DIR}/hello_world.c + COMMAND ${CROSS_COMPILE}strip -R .xt.* + -o ${PROJECT_BINARY_DIR}/hello_world.llext + ${PROJECT_BINARY_DIR}/hello_world.pre.llext + ) +endif() + +set(HELLO_WORLD_LLEXT ${PROJECT_BINARY_DIR}/hello_world.llext PARENT_SCOPE) + +add_custom_target(hello_world DEPENDS ${PROJECT_BINARY_DIR}/hello_world.llext) diff --git a/tests/subsys/llext/hello_world/hello_world.c b/tests/subsys/llext/hello_world/hello_world.c new file mode 100644 index 00000000000..93d55ed5422 --- /dev/null +++ b/tests/subsys/llext/hello_world/hello_world.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * This very simple hello world C code can be used as a test case for building + * probably the simplest loadable extension. It requires a single symbol be + * linked, section relocation support, and the ability to export and call out to + * a function. + */ + +#include + +extern void printk(char *fmt, ...); + +static const uint32_t number = 42; + +extern void hello_world(void) +{ + printk("hello world\n"); + printk("A number is %lu\n", number); +} diff --git a/tests/subsys/llext/prj.conf b/tests/subsys/llext/prj.conf new file mode 100644 index 00000000000..ed104f56b08 --- /dev/null +++ b/tests/subsys/llext/prj.conf @@ -0,0 +1,7 @@ +CONFIG_ZTEST=y +CONFIG_ZTEST_STACK_SIZE=8192 +CONFIG_LOG=y +CONFIG_LOG_MODE_IMMEDIATE=y +CONFIG_LLEXT=y +CONFIG_LLEXT_HEAP_SIZE=32 +CONFIG_LLEXT_LOG_LEVEL_DBG=y diff --git a/tests/subsys/llext/src/test_llext_simple.c b/tests/subsys/llext/src/test_llext_simple.c new file mode 100644 index 00000000000..557697f576c --- /dev/null +++ b/tests/subsys/llext/src/test_llext_simple.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#if defined(CONFIG_ARM) /* ARMV7 */ || defined(CONFIG_XTENSA) +#ifndef CONFIG_LLEXT_STORAGE_WRITABLE +const +#endif +static uint8_t hello_world_elf[] __aligned(4) = { +#include "hello_world.inc" +}; +#endif + +/** + * Attempt to load, list, list symbols, call a fn, and unload a + * hello world extension for each supported architecture + * + * This requires a single linked symbol (printk) and a single + * exported symbol from the extension ( void hello_world(void)) + */ +ZTEST(llext, test_llext_simple) +{ + const char name[16] = "hello"; + struct llext_buf_loader buf_loader = + LLEXT_BUF_LOADER(hello_world_elf, ARRAY_SIZE(hello_world_elf)); + struct llext_loader *loader = &buf_loader.loader; + struct llext *ext; + const void * const printk_fn = llext_find_sym(NULL, "printk"); + + zassert_equal(printk_fn, printk, "printk should be an exported symbol"); + + int res = llext_load(loader, name, &ext); + + zassert_ok(res, "load should succeed"); + + const void * const hello_world_fn = llext_find_sym(&ext->sym_tab, "hello_world"); + + zassert_not_null(hello_world_fn, "hello_world should be an exported symbol"); + + res = llext_call_fn(ext, "hello_world"); + + zassert_ok(res, "calling hello world should succeed"); + + llext_unload(ext); +} + +ZTEST_SUITE(llext, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/subsys/llext/testcase.yaml b/tests/subsys/llext/testcase.yaml new file mode 100644 index 00000000000..2747edf8d0c --- /dev/null +++ b/tests/subsys/llext/testcase.yaml @@ -0,0 +1,18 @@ +common: + tags: llext +tests: + llext.simple.arm: + filter: not CONFIG_CPU_HAS_MMU and not CONFIG_SOC_SERIES_S32ZE_R52 + arch_allow: arm + extra_configs: + - CONFIG_ARM_MPU=n + # Broken platforms + platform_exclude: + - nuvoton_pfm_m487 # See #63167 + llext.simple.xtensa: + arch_allow: xtensa + extra_configs: + - CONFIG_LLEXT_STORAGE_WRITABLE=y + # Broken platforms + platform_exclude: + - qemu_xtensa_mmu # ELF sections are read-only, and without peek() .text copy isn't executable diff --git a/tests/subsys/logging/log_api/prj.conf b/tests/subsys/logging/log_api/prj.conf index b28665151be..c46ee4c1886 100644 --- a/tests/subsys/logging/log_api/prj.conf +++ b/tests/subsys/logging/log_api/prj.conf @@ -1,6 +1,5 @@ CONFIG_MAIN_THREAD_PRIORITY=5 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y CONFIG_TEST_LOGGING_DEFAULTS=n CONFIG_LOG=y diff --git a/tests/subsys/logging/log_api/testcase.yaml b/tests/subsys/logging/log_api/testcase.yaml index 36727d8d346..2b389d01073 100644 --- a/tests/subsys/logging/log_api/testcase.yaml +++ b/tests/subsys/logging/log_api/testcase.yaml @@ -12,28 +12,28 @@ common: - native_posix min_ram: 32 tests: - logging.log_api_deferred_overflow_rt_filter: + logging.deferred.api.overflow_rt_filter: extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_LOG_MODE_OVERFLOW=y - CONFIG_LOG_RUNTIME_FILTERING=y - logging.log_api_deferred_overflow: + logging.deferred.api.overflow: extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_LOG_MODE_OVERFLOW=y - logging.log_api_deferred_no_overflow: + logging.deferred.api.no_overflow: extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_LOG_MODE_OVERFLOW=n - logging.log_api_deferred_static_filter: + logging.deferred.api.static_filter: extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_SAMPLE_MODULE_LOG_LEVEL_DBG=y - logging.log_api_deferred_printk: + logging.deferred.api.printk: extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_SAMPLE_MODULE_LOG_LEVEL_DBG=y @@ -41,18 +41,18 @@ tests: # When LOG_PRINTK is enabled, thread must process otherwise test output would be lost. - CONFIG_LOG_PROCESS_THREAD=y - logging.log_api_deferred_func_prefix: + logging.deferred.api.func_prefix: extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_SAMPLE_MODULE_LOG_LEVEL_DBG=y - CONFIG_LOG_FUNC_NAME_PREFIX_DBG=y - logging.log_api_deferred_64b_timestamp: + logging.deferred.api.64b_timestamp: extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_LOG_TIMESTAMP_64BIT=y - logging.log_api_deferred_override_level: + logging.deferred.api.override_level: # Testing on selected platforms as it enables all logs in the application # and it cannot be handled on many platforms. platform_allow: @@ -63,47 +63,47 @@ tests: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_LOG_OVERRIDE_LEVEL=4 - logging.log_api_immediate: + logging.immediate.api: extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y - logging.log_api_immediate_printk: + logging.immediate.api.printk: extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y - CONFIG_LOG_PRINTK=y - logging.log_api_immediate_rt_filter: + logging.immediate.api.rt_filter: extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y - CONFIG_LOG_RUNTIME_FILTERING=y - logging.log_api_immediate_static_filter: + logging.immediate.api.static_filter: extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y - CONFIG_SAMPLE_MODULE_LOG_LEVEL_DBG=y - logging.log_api_immediate_64b_timestamp: + logging.immediate.api.64b_timestamp: extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y - CONFIG_LOG_TIMESTAMP_64BIT=y - logging.log_api_frontend_dbg: + logging.frontend.dbg: extra_configs: - CONFIG_LOG_FRONTEND=y - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_SAMPLE_MODULE_LOG_LEVEL_DBG=y - logging.log_api_frontend: + logging.frontend: extra_configs: - CONFIG_LOG_FRONTEND=y - CONFIG_LOG_MODE_DEFERRED=y - logging.log_api_frontend_immediate: + logging.frontend.immediate: extra_configs: - CONFIG_LOG_FRONTEND=y - CONFIG_LOG_MODE_IMMEDIATE=y - logging.log_api_frontend_immediate_override_level: + logging.frontend.immediate_override_level: # Testing on selected platforms as it enables all logs in the application # and it cannot be handled on many platforms. platform_allow: @@ -115,7 +115,7 @@ tests: - CONFIG_LOG_MODE_IMMEDIATE=y - CONFIG_LOG_OVERRIDE_LEVEL=4 - logging.log_api_deferred_override_level_rt_filtering: + logging.deferred.api.override_level_rt_filtering: # Testing on selected platforms as it enables all logs in the application # and it cannot be handled on many platforms. platform_allow: @@ -127,12 +127,12 @@ tests: - CONFIG_LOG_RUNTIME_FILTERING=y - CONFIG_LOG_OVERRIDE_LEVEL=4 - logging.log_api_frontend_only: + logging.frontend.only: extra_configs: - CONFIG_LOG_FRONTEND=y - CONFIG_LOG_FRONTEND_ONLY=y - logging.log_api_frontend_no_backends: + logging.frontend.no_backends: extra_configs: - CONFIG_LOG_FRONTEND=y - CONFIG_LOG_FRONTEND_ONLY=y @@ -142,32 +142,32 @@ tests: - CONFIG_LOG_BACKEND_XTENSA_SIM=n extra_args: EXTRA_CPPFLAGS=-DNO_BACKENDS=1 - logging.log_api_deferred_overflow_rt_filter_cpp: + logging.deferred.api.overflow_rt_filter_cpp: extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_LOG_MODE_OVERFLOW=y - CONFIG_LOG_RUNTIME_FILTERING=y - CONFIG_CPP=y - logging.log_api_deferred_overflow_cpp: + logging.deferred.api.overflow_cpp: extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_LOG_MODE_OVERFLOW=y - CONFIG_CPP=y - logging.log_api_deferred_no_overflow_cpp: + logging.deferred.api.no_overflowcpp: extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_LOG_MODE_OVERFLOW=n - CONFIG_CPP=y - logging.log_api_deferred_static_filter_cpp: + logging.deferred.api.static_filter_cpp: extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_SAMPLE_MODULE_LOG_LEVEL_DBG=y - CONFIG_CPP=y - logging.log_api_deferred_printk_cpp: + logging.deferred.api.printk_cpp: extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_SAMPLE_MODULE_LOG_LEVEL_DBG=y @@ -176,74 +176,74 @@ tests: - CONFIG_LOG_PROCESS_THREAD=y - CONFIG_CPP=y - logging.log_api_deferred_func_prefix_cpp: + logging.deferred.api.func_prefix_cpp: extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_SAMPLE_MODULE_LOG_LEVEL_DBG=y - CONFIG_LOG_FUNC_NAME_PREFIX_DBG=y - CONFIG_CPP=y - logging.log_api_deferred_64b_timestamp_cpp: + logging.deferred.api.64b_timestamp_cpp: extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_LOG_TIMESTAMP_64BIT=y - CONFIG_CPP=y - logging.log_api_immediate_cpp: + logging.immediate.api.cpp: extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y - CONFIG_CPP=y - logging.log_api_immediate_printk_cpp: + logging.immediate.api.printk_cpp: extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y - CONFIG_LOG_PRINTK=y - CONFIG_CPP=y - logging.log_api_immediate_rt_filter_cpp: + logging.immediate.api.rt_filter_cpp: extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y - CONFIG_LOG_RUNTIME_FILTERING=y - CONFIG_CPP=y - logging.log_api_immediate_static_filter_cpp: + logging.immediate.api.static_filter_cpp: extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y - CONFIG_SAMPLE_MODULE_LOG_LEVEL_DBG=y - CONFIG_CPP=y - logging.log_api_immediate_64b_timestamp_cpp: + logging.immediate.api.64b_timestamp_cpp: extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y - CONFIG_LOG_TIMESTAMP_64BIT=y - CONFIG_CPP=y - logging.log_api_frontend_dbg_cpp: + logging.frontend.dbg_cpp: extra_configs: - CONFIG_LOG_FRONTEND=y - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_SAMPLE_MODULE_LOG_LEVEL_DBG=y - CONFIG_CPP=y - logging.log_api_frontend_cpp: + logging.frontend.cpp: extra_configs: - CONFIG_LOG_FRONTEND=y - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_CPP=y - logging.log_api_frontend_immediate_cpp: + logging.frontend.immediate_cpp: extra_configs: - CONFIG_LOG_FRONTEND=y - CONFIG_LOG_MODE_IMMEDIATE=y - CONFIG_CPP=y - logging.log_api_frontend_only_cpp: + logging.frontend.only_cpp: extra_configs: - CONFIG_LOG_FRONTEND=y - CONFIG_LOG_FRONTEND_ONLY=y - CONFIG_CPP=y - logging.log_api_frontend_no_backends_cpp: + logging.frontend.no_backends_cpp: extra_configs: - CONFIG_LOG_FRONTEND=y - CONFIG_LOG_FRONTEND_ONLY=y @@ -254,7 +254,7 @@ tests: - CONFIG_CPP=y extra_args: EXTRA_CPPFLAGS=-DNO_BACKENDS=1 - logging.log_api_deferred_overflow_rt_filter.tagged_args: + logging.deferred.api.overflow_rt_filter.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_DEFERRED=y @@ -262,28 +262,28 @@ tests: - CONFIG_LOG_RUNTIME_FILTERING=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_deferred_overflow.tagged_args: + logging.deferred.api.overflow.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_LOG_MODE_OVERFLOW=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_deferred_no_overflow.tagged_args: + logging.deferred.api.no_overflowtagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_LOG_MODE_OVERFLOW=n - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_deferred_static_filter.tagged_args: + logging.deferred.api.static_filter.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_SAMPLE_MODULE_LOG_LEVEL_DBG=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_deferred_printk.tagged_args: + logging.deferred.api.printk.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_DEFERRED=y @@ -293,7 +293,7 @@ tests: - CONFIG_LOG_PROCESS_THREAD=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_deferred_func_prefix.tagged_args: + logging.deferred.api.func_prefix.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_DEFERRED=y @@ -301,14 +301,14 @@ tests: - CONFIG_LOG_FUNC_NAME_PREFIX_DBG=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_deferred_64b_timestamp.tagged_args: + logging.deferred.api.64b_timestamp.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_LOG_TIMESTAMP_64BIT=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_deferred_override_level.tagged_args: + logging.deferred.api.override_level.tagged_args: # Testing on selected platforms as it enables all logs in the application # and it cannot be handled on many platforms. platform_allow: @@ -321,7 +321,7 @@ tests: - CONFIG_LOG_OVERRIDE_LEVEL=4 - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_deferred_override_level_rt_filtering.tagged_args: + logging.deferred.api.override_level_rt_filtering.tagged_args: # Testing on selected platforms as it enables all logs in the application # and it cannot be handled on many platforms. platform_allow: @@ -335,41 +335,41 @@ tests: - CONFIG_LOG_OVERRIDE_LEVEL=4 - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_immediate.tagged_args: + logging.immediate.api.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_immediate_printk.tagged_args: + logging.immediate.api.printk.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y - CONFIG_LOG_PRINTK=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_immediate_rt_filter.tagged_args: + logging.immediate.api.rt_filter.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y - CONFIG_LOG_RUNTIME_FILTERING=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_immediate_static_filter.tagged_args: + logging.immediate.api.static_filter.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y - CONFIG_SAMPLE_MODULE_LOG_LEVEL_DBG=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_immediate_64b_timestamp.tagged_args: + logging.immediate.api.64b_timestamp.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y - CONFIG_LOG_TIMESTAMP_64BIT=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_deferred_overflow_rt_filter_cpp.tagged_args: + logging.deferred.api.overflow_rt_filter_cpp.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_DEFERRED=y @@ -378,7 +378,7 @@ tests: - CONFIG_CPP=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_deferred_overflow_cpp.tagged_args: + logging.deferred.api.overflow_cpp.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_DEFERRED=y @@ -386,7 +386,7 @@ tests: - CONFIG_CPP=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_deferred_no_overflow_cpp.tagged_args: + logging.deferred.api.no_overflowcpp.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_DEFERRED=y @@ -394,7 +394,7 @@ tests: - CONFIG_CPP=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_deferred_static_filter_cpp.tagged_args: + logging.deferred.api.static_filter_cpp.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_DEFERRED=y @@ -402,7 +402,7 @@ tests: - CONFIG_CPP=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_deferred_printk_cpp.tagged_args: + logging.deferred.api.printk_cpp.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_DEFERRED=y @@ -413,7 +413,7 @@ tests: - CONFIG_CPP=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_deferred_func_prefix_cpp.tagged_args: + logging.deferred.api.func_prefix_cpp.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_DEFERRED=y @@ -422,7 +422,7 @@ tests: - CONFIG_CPP=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_deferred_64b_timestamp_cpp.tagged_args: + logging.deferred.api.64b_timestamp_cpp.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_DEFERRED=y @@ -430,14 +430,14 @@ tests: - CONFIG_CPP=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_immediate_cpp.tagged_args: + logging.immediate.api.cpp.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y - CONFIG_CPP=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_immediate_printk_cpp.tagged_args: + logging.immediate.api.printk_cpp.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y @@ -445,7 +445,7 @@ tests: - CONFIG_CPP=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_immediate_rt_filter_cpp.tagged_args: + logging.immediate.api.rt_filter_cpp.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y @@ -453,7 +453,7 @@ tests: - CONFIG_CPP=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_immediate_static_filter_cpp.tagged_args: + logging.immediate.api.static_filter_cpp.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y @@ -461,7 +461,7 @@ tests: - CONFIG_CPP=y - CONFIG_LOG_USE_TAGGED_ARGUMENTS=y - logging.log_api_immediate_64b_timestamp_cpp.tagged_args: + logging.immediate.api.64b_timestamp_cpp.tagged_args: toolchain_exclude: xcc extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y diff --git a/tests/subsys/logging/log_backend_fs/prj.conf b/tests/subsys/logging/log_backend_fs/prj.conf index 4f0984364c4..6ea2195cd8f 100644 --- a/tests/subsys/logging/log_backend_fs/prj.conf +++ b/tests/subsys/logging/log_backend_fs/prj.conf @@ -1,7 +1,6 @@ CONFIG_ZTEST=y CONFIG_ASSERT=y CONFIG_TEST_LOGGING_DEFAULTS=n -CONFIG_ZTEST_NEW_API=y CONFIG_LOG=y CONFIG_LOG_BACKEND_FS=y diff --git a/tests/subsys/logging/log_backend_fs/testcase.yaml b/tests/subsys/logging/log_backend_fs/testcase.yaml index 99213286cb2..f372776f10f 100644 --- a/tests/subsys/logging/log_backend_fs/testcase.yaml +++ b/tests/subsys/logging/log_backend_fs/testcase.yaml @@ -8,7 +8,7 @@ common: - fs - littlefs tests: - logging.log_backend_fs.automounted: + logging.backend.fs.automounted: platform_allow: - native_posix - native_posix_64 @@ -16,21 +16,21 @@ tests: - mr_canhubk3 integration_platforms: - native_posix - logging.log_backend_fs.manualmounted.native_posix: + logging.backend.fs.manualmounted.native_posix: platform_allow: native_posix extra_args: DTC_OVERLAY_FILE="./boards/native_posix.overlay;./boards/automount.overlay" integration_platforms: - native_posix - logging.log_backend_fs.manualmounted.native_posix_64: + logging.backend.fs.manualmounted.native_posix_64: platform_allow: native_posix_64 extra_args: DTC_OVERLAY_FILE="./boards/native_posix_64.overlay;./boards/automount.overlay" integration_platforms: - native_posix_64 - logging.log_backend_fs.manualmounted.nrf5840dk: + logging.backend.fs.manualmounted.nrf5840dk: platform_allow: nrf52840dk_nrf52840 extra_args: DTC_OVERLAY_FILE="./boards/nrf52840dk_nrf52840.overlay;./boards/automount.overlay" integration_platforms: - nrf52840dk_nrf52840 - logging.log_backend_fs.manualmounted.mr_canhubk3: + logging.backend.fs.manualmounted.mr_canhubk3: platform_allow: mr_canhubk3 extra_args: DTC_OVERLAY_FILE="./boards/mr_canhubk3.overlay;./boards/automount.overlay" diff --git a/tests/subsys/logging/log_backend_init/prj.conf b/tests/subsys/logging/log_backend_init/prj.conf index cbb5cf0b4b2..f28ddfb8fc3 100644 --- a/tests/subsys/logging/log_backend_init/prj.conf +++ b/tests/subsys/logging/log_backend_init/prj.conf @@ -1,6 +1,5 @@ CONFIG_MAIN_THREAD_PRIORITY=5 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_LOGGING_DEFAULTS=n CONFIG_LOG=y CONFIG_LOG_PRINTK=n diff --git a/tests/subsys/logging/log_backend_init/testcase.yaml b/tests/subsys/logging/log_backend_init/testcase.yaml index a8f9144f7ec..b9d7c79dcd1 100644 --- a/tests/subsys/logging/log_backend_init/testcase.yaml +++ b/tests/subsys/logging/log_backend_init/testcase.yaml @@ -1,5 +1,5 @@ tests: - logging.log_backend_initialization: + logging.backend.initialization: integration_platforms: - qemu_x86 tags: diff --git a/tests/subsys/logging/log_backend_uart/CMakeLists.txt b/tests/subsys/logging/log_backend_uart/CMakeLists.txt new file mode 100644 index 00000000000..055b71fd748 --- /dev/null +++ b/tests/subsys/logging/log_backend_uart/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Meta +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(log_backend_uart_test) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/subsys/logging/log_backend_uart/Kconfig b/tests/subsys/logging/log_backend_uart/Kconfig new file mode 100644 index 00000000000..89a0fefa76f --- /dev/null +++ b/tests/subsys/logging/log_backend_uart/Kconfig @@ -0,0 +1,8 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +module = SAMPLE_MODULE +module-str = Test logging API +source "subsys/logging/Kconfig.template.log_config" + +source "Kconfig.zephyr" diff --git a/tests/subsys/logging/log_backend_uart/multi.overlay b/tests/subsys/logging/log_backend_uart/multi.overlay new file mode 100644 index 00000000000..799a4602cf9 --- /dev/null +++ b/tests/subsys/logging/log_backend_uart/multi.overlay @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + zephyr,log-uart = &log_uarts; + }; + + log_uarts: log_uarts { + compatible = "zephyr,log-uart"; + uarts = <&euart0 &euart1>; + }; + + euart0: uart-emul0 { + compatible = "zephyr,uart-emul"; + status = "okay"; + current-speed = <0>; + rx-fifo-size = <256>; + tx-fifo-size = <256>; + }; + + euart1: uart-emul1 { + compatible = "zephyr,uart-emul"; + status = "okay"; + current-speed = <0>; + rx-fifo-size = <256>; + tx-fifo-size = <256>; + }; +}; diff --git a/tests/subsys/logging/log_backend_uart/prj.conf b/tests/subsys/logging/log_backend_uart/prj.conf new file mode 100644 index 00000000000..c8615a65adb --- /dev/null +++ b/tests/subsys/logging/log_backend_uart/prj.conf @@ -0,0 +1,16 @@ +# Copyright (c) 2023 Meta +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_ZTEST=y +CONFIG_ASSERT=y +CONFIG_TEST_LOGGING_DEFAULTS=n + +CONFIG_LOG=y +CONFIG_LOG_BACKEND_UART=y +CONFIG_LOG_MODE_IMMEDIATE=y +CONFIG_LOG_PRINTK=n +# +# Disable all potential other default backends +CONFIG_LOG_BACKEND_NATIVE_POSIX=n +CONFIG_LOG_BACKEND_RTT=n +CONFIG_LOG_BACKEND_XTENSA_SIM=n diff --git a/tests/subsys/logging/log_backend_uart/single.overlay b/tests/subsys/logging/log_backend_uart/single.overlay new file mode 100644 index 00000000000..3bdcff1c882 --- /dev/null +++ b/tests/subsys/logging/log_backend_uart/single.overlay @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + zephyr,log-uart = &log_uarts; + }; + + log_uarts: log_uarts { + compatible = "zephyr,log-uart"; + uarts = <&euart0>; + }; + + euart0: uart-emul0 { + compatible = "zephyr,uart-emul"; + status = "okay"; + current-speed = <0>; + rx-fifo-size = <256>; + tx-fifo-size = <256>; + }; +}; diff --git a/tests/subsys/logging/log_backend_uart/src/main.c b/tests/subsys/logging/log_backend_uart/src/main.c new file mode 100644 index 00000000000..078d2e02f63 --- /dev/null +++ b/tests/subsys/logging/log_backend_uart/src/main.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(test, CONFIG_SAMPLE_MODULE_LOG_LEVEL); + +#define EMUL_UART_NUM DT_NUM_INST_STATUS_OKAY(zephyr_uart_emul) +#define EMUL_UART_NODE(i) DT_NODELABEL(euart##i) +#define EMUL_UART_DEV_INIT(i, _) DEVICE_DT_GET(EMUL_UART_NODE(i)) +#define EMUL_UART_TX_FIFO_SIZE(i) DT_PROP(EMUL_UART_NODE(i), tx_fifo_size) +#define SAMPLE_DATA_SIZE EMUL_UART_TX_FIFO_SIZE(0) + +#define TEST_DATA "0123456789ABCDEF" +BUILD_ASSERT(strlen(TEST_DATA) < SAMPLE_DATA_SIZE); + +struct log_backend_uart_fixture { + const struct device *dev[EMUL_UART_NUM]; +}; + +static void *uart_emul_setup(void) +{ + static struct log_backend_uart_fixture fixture = { + .dev = {LISTIFY(EMUL_UART_NUM, EMUL_UART_DEV_INIT, (,))}}; + + for (size_t i = 0; i < EMUL_UART_NUM; i++) { + zassert_not_null(fixture.dev[i]); + } + + return &fixture; +} + +static void uart_emul_before(void *f) +{ + struct log_backend_uart_fixture *fixture = f; + + for (size_t i = 0; i < EMUL_UART_NUM; i++) { + uart_irq_tx_disable(fixture->dev[i]); + uart_irq_rx_disable(fixture->dev[i]); + + uart_emul_flush_rx_data(fixture->dev[i]); + uart_emul_flush_tx_data(fixture->dev[i]); + + uart_err_check(fixture->dev[i]); + } +} + +ZTEST_F(log_backend_uart, test_log_backend_uart_multi_instance) +{ + zassert_equal(log_backend_count_get(), EMUL_UART_NUM, "Unexpected number of instance(s)"); + + LOG_RAW(TEST_DATA); + + for (size_t i = 0; i < EMUL_UART_NUM; i++) { + uint8_t tx_content[SAMPLE_DATA_SIZE] = {0}; + size_t tx_len; + + tx_len = uart_emul_get_tx_data(fixture->dev[i], tx_content, sizeof(tx_content)); + zassert_equal(tx_len, strlen(TEST_DATA), + "%d: TX buffer length does not match. Expected %d, got %d", + i, strlen(TEST_DATA), tx_len); + zassert_mem_equal(tx_content, TEST_DATA, strlen(tx_content)); + } +} + +ZTEST_SUITE(log_backend_uart, NULL, uart_emul_setup, uart_emul_before, NULL, NULL); diff --git a/tests/subsys/logging/log_backend_uart/testcase.yaml b/tests/subsys/logging/log_backend_uart/testcase.yaml new file mode 100644 index 00000000000..05a4626ba62 --- /dev/null +++ b/tests/subsys/logging/log_backend_uart/testcase.yaml @@ -0,0 +1,16 @@ +# Copyright (c) 2023 Meta +# SPDX-License-Identifier: Apache-2.0 + +common: + tags: + - logging + - backend + - uart + filter: CONFIG_UART_CONSOLE + integration_platforms: + - qemu_x86 +tests: + logging.backend.uart.single: + extra_args: DTC_OVERLAY_FILE="./single.overlay" + logging.backend.uart.multi: + extra_args: DTC_OVERLAY_FILE="./multi.overlay" diff --git a/tests/subsys/logging/log_benchmark/prj.conf b/tests/subsys/logging/log_benchmark/prj.conf index 9e5cb801ccf..858c9ec0f95 100644 --- a/tests/subsys/logging/log_benchmark/prj.conf +++ b/tests/subsys/logging/log_benchmark/prj.conf @@ -1,6 +1,5 @@ CONFIG_MAIN_THREAD_PRIORITY=5 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_LOGGING_DEFAULTS=n CONFIG_LOG=y CONFIG_LOG_PRINTK=n diff --git a/tests/subsys/logging/log_benchmark/testcase.yaml b/tests/subsys/logging/log_benchmark/testcase.yaml index b11171bb0ea..b530895ba54 100644 --- a/tests/subsys/logging/log_benchmark/testcase.yaml +++ b/tests/subsys/logging/log_benchmark/testcase.yaml @@ -1,5 +1,5 @@ tests: - logging.log_benchmark: + logging.benchmark: integration_platforms: - native_posix tags: logging @@ -7,7 +7,7 @@ tests: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_CBPRINTF_COMPLETE=y - logging.log_benchmark_speed: + logging.benchmark_speed: integration_platforms: - native_posix tags: logging @@ -16,9 +16,9 @@ tests: - CONFIG_CBPRINTF_COMPLETE=y - CONFIG_LOG_SPEED=y - logging.log_benchmark_user: + logging.benchmark_user: integration_platforms: - - native_posix + - qemu_x86 tags: logging platform_allow: - qemu_x86 diff --git a/tests/subsys/logging/log_cache/prj.conf b/tests/subsys/logging/log_cache/prj.conf index 49146d8df2e..2bba192e203 100644 --- a/tests/subsys/logging/log_cache/prj.conf +++ b/tests/subsys/logging/log_cache/prj.conf @@ -1,6 +1,5 @@ CONFIG_MAIN_THREAD_PRIORITY=5 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_LOGGING_DEFAULTS=n CONFIG_LOG=y CONFIG_LOG_PRINTK=n diff --git a/tests/subsys/logging/log_cache/testcase.yaml b/tests/subsys/logging/log_cache/testcase.yaml index 4d14cc1de1e..65aa2fa388e 100644 --- a/tests/subsys/logging/log_cache/testcase.yaml +++ b/tests/subsys/logging/log_cache/testcase.yaml @@ -3,7 +3,7 @@ common: - native_posix tests: - logging.log_cache: + logging.cache: tags: - log_cache - logging diff --git a/tests/subsys/logging/log_core_additional/log_sync.conf b/tests/subsys/logging/log_core_additional/log_sync.conf index c9894d82dd7..9e8b101f546 100644 --- a/tests/subsys/logging/log_core_additional/log_sync.conf +++ b/tests/subsys/logging/log_core_additional/log_sync.conf @@ -1,6 +1,5 @@ CONFIG_MAIN_THREAD_PRIORITY=5 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_LOGGING_DEFAULTS=n CONFIG_LOG=y CONFIG_LOG_OUTPUT=y diff --git a/tests/subsys/logging/log_core_additional/log_user.conf b/tests/subsys/logging/log_core_additional/log_user.conf index 4922dfbb411..ae3240c0e21 100644 --- a/tests/subsys/logging/log_core_additional/log_user.conf +++ b/tests/subsys/logging/log_core_additional/log_user.conf @@ -1,6 +1,5 @@ CONFIG_MAIN_THREAD_PRIORITY=5 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y CONFIG_TEST_LOGGING_DEFAULTS=n CONFIG_LOG=y diff --git a/tests/subsys/logging/log_core_additional/prj.conf b/tests/subsys/logging/log_core_additional/prj.conf index a2bacab3cf5..cd3008f3bcc 100644 --- a/tests/subsys/logging/log_core_additional/prj.conf +++ b/tests/subsys/logging/log_core_additional/prj.conf @@ -1,6 +1,5 @@ CONFIG_MAIN_THREAD_PRIORITY=5 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_LOGGING_DEFAULTS=n CONFIG_LOG=y CONFIG_LOG_OUTPUT=y diff --git a/tests/subsys/logging/log_core_additional/testcase.yaml b/tests/subsys/logging/log_core_additional/testcase.yaml index a4919fc8ad6..7fc508440ee 100644 --- a/tests/subsys/logging/log_core_additional/testcase.yaml +++ b/tests/subsys/logging/log_core_additional/testcase.yaml @@ -1,15 +1,15 @@ tests: - logging.add.async: + logging.async: tags: logging extra_args: CONF_FILE=prj.conf integration_platforms: - native_posix - logging.add.sync: + logging.sync: tags: logging extra_args: CONF_FILE=log_sync.conf integration_platforms: - native_posix - logging.add.log_user: + logging.log_user: tags: logging filter: CONFIG_USERSPACE extra_args: diff --git a/tests/subsys/logging/log_custom_header/prj.conf b/tests/subsys/logging/log_custom_header/prj.conf index f905dd515d2..49d484e56cb 100644 --- a/tests/subsys/logging/log_custom_header/prj.conf +++ b/tests/subsys/logging/log_custom_header/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_LOG=y CONFIG_LOG_OUTPUT=y CONFIG_LOG_PRINTK=n diff --git a/tests/subsys/logging/log_immediate/prj.conf b/tests/subsys/logging/log_immediate/prj.conf index a6a56e16dce..63b835d6c16 100644 --- a/tests/subsys/logging/log_immediate/prj.conf +++ b/tests/subsys/logging/log_immediate/prj.conf @@ -1,5 +1,4 @@ CONFIG_MAIN_THREAD_PRIORITY=5 -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST=y CONFIG_TEST_LOGGING_DEFAULTS=n CONFIG_LOG=y diff --git a/tests/subsys/logging/log_immediate/testcase.yaml b/tests/subsys/logging/log_immediate/testcase.yaml index 676b283149f..dd63de3c17f 100644 --- a/tests/subsys/logging/log_immediate/testcase.yaml +++ b/tests/subsys/logging/log_immediate/testcase.yaml @@ -3,7 +3,7 @@ common: - native_posix tests: - logging.log_immediate: + logging.immediate: tags: - log_core - logging @@ -13,7 +13,7 @@ tests: - nucleo_f030r8 - stm32f0_disco - nrf52_bsim - logging.log_immediate.clean_output: + logging.immediate.clean_output: extra_args: CONFIG_LOG_IMMEDIATE_CLEAN_OUTPUT=y tags: - log_core diff --git a/tests/subsys/logging/log_link_order/prj.conf b/tests/subsys/logging/log_link_order/prj.conf index c44f1e61558..205868ec699 100644 --- a/tests/subsys/logging/log_link_order/prj.conf +++ b/tests/subsys/logging/log_link_order/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_EXTRA_STACK_SIZE=2048 CONFIG_TEST_LOGGING_DEFAULTS=n diff --git a/tests/subsys/logging/log_links/prj.conf b/tests/subsys/logging/log_links/prj.conf index 38052819354..1a83e45c08e 100644 --- a/tests/subsys/logging/log_links/prj.conf +++ b/tests/subsys/logging/log_links/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_LOGGING_DEFAULTS=n CONFIG_LOG=y diff --git a/tests/subsys/logging/log_msg/prj.conf b/tests/subsys/logging/log_msg/prj.conf index be567582f34..e1248e780d1 100644 --- a/tests/subsys/logging/log_msg/prj.conf +++ b/tests/subsys/logging/log_msg/prj.conf @@ -1,5 +1,4 @@ CONFIG_MAIN_THREAD_PRIORITY=5 -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST=y CONFIG_TEST_LOGGING_DEFAULTS=n CONFIG_LOG=y diff --git a/tests/subsys/logging/log_msg/testcase.yaml b/tests/subsys/logging/log_msg/testcase.yaml index 6ab444d6592..543eb046630 100644 --- a/tests/subsys/logging/log_msg/testcase.yaml +++ b/tests/subsys/logging/log_msg/testcase.yaml @@ -9,25 +9,25 @@ common: - native_posix filter: not CONFIG_LOG_ALWAYS_RUNTIME tests: - logging.log_msg: + logging.message: extra_configs: - CONFIG_CBPRINTF_COMPLETE=y - logging.log_msg_no_overflow: + logging.message.no_overflow: extra_configs: - CONFIG_LOG_MODE_OVERFLOW=n - logging.log_msg_64b_timestamp: + logging.message.64b_timestamp: extra_configs: - CONFIG_CBPRINTF_COMPLETE=y - CONFIG_LOG_TIMESTAMP_64BIT=y - logging.log_msg_fp: + logging.message.fp: extra_configs: - CONFIG_CBPRINTF_COMPLETE=y - CONFIG_CBPRINTF_FP_SUPPORT=y - logging.log_msg_fp_64b_timestamp: + logging.message.fp_64b_timestamp: extra_configs: - CONFIG_CBPRINTF_COMPLETE=y - CONFIG_CBPRINTF_FP_SUPPORT=y diff --git a/tests/subsys/logging/log_output/prj.conf b/tests/subsys/logging/log_output/prj.conf index 77447af2010..b02eb949445 100644 --- a/tests/subsys/logging/log_output/prj.conf +++ b/tests/subsys/logging/log_output/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_LOGGING_DEFAULTS=n CONFIG_LOG=y CONFIG_LOG_OUTPUT=y diff --git a/tests/subsys/logging/log_output/testcase.yaml b/tests/subsys/logging/log_output/testcase.yaml index 66b8f675089..cb265420276 100644 --- a/tests/subsys/logging/log_output/testcase.yaml +++ b/tests/subsys/logging/log_output/testcase.yaml @@ -3,19 +3,19 @@ common: - native_posix tests: - logging.log_output: + logging.output: tags: - log_output - logging extra_configs: - CONFIG_LOG_TIMESTAMP_64BIT=n - logging.log_output_ts64: + logging.output.ts64: tags: - log_output - logging extra_configs: - CONFIG_LOG_TIMESTAMP_64BIT=y - logging.log_output.thread_id: + logging.output.thread_id: tags: - log_output - logging diff --git a/tests/subsys/logging/log_stack/prj.conf b/tests/subsys/logging/log_stack/prj.conf index 21779201fdf..c323d2513c3 100644 --- a/tests/subsys/logging/log_stack/prj.conf +++ b/tests/subsys/logging/log_stack/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_TEST_LOGGING_DEFAULTS=n diff --git a/tests/subsys/logging/log_stack/testcase.yaml b/tests/subsys/logging/log_stack/testcase.yaml index 25ead504276..92534b65ab0 100644 --- a/tests/subsys/logging/log_stack/testcase.yaml +++ b/tests/subsys/logging/log_stack/testcase.yaml @@ -8,42 +8,42 @@ common: integration_platforms: - qemu_x86 tests: - logging.log_stack_deferred: + logging.stack.deferred: extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - logging.log_stack_deferred_no_opt: + logging.stack.deferred_no_opt: filter: not CONFIG_MIPS extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_NO_OPTIMIZATIONS=y - CONFIG_ZTEST_WARN_NO_OPTIMIZATIONS=n - CONFIG_IDLE_STACK_SIZE=2048 - logging.log_stack_immediate: + logging.stack.immediate: extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y - logging.log_stack_immediate_no_opt: + logging.stack.immediate_no_opt: filter: not CONFIG_MIPS extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y - CONFIG_NO_OPTIMIZATIONS=y - CONFIG_ZTEST_WARN_NO_OPTIMIZATIONS=n - CONFIG_IDLE_STACK_SIZE=2048 - logging.log_stack_deferred_cpp: + logging.stack.deferred_cpp: extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_CPP=y - logging.log_stack_deferred_cpp_no_opt: + logging.stack.deferred_cpp_no_opt: filter: not CONFIG_MIPS extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_NO_OPTIMIZATIONS=y - CONFIG_ZTEST_WARN_NO_OPTIMIZATIONS=n - CONFIG_CPP=y - logging.log_stack_immediate_cpp: + logging.stack.immediate_cpp: extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y - CONFIG_CPP=y - logging.log_stack_immediate_cpp_no_opt: + logging.stack.immediate_cpp_no_opt: filter: not CONFIG_MIPS extra_configs: - CONFIG_LOG_MODE_IMMEDIATE=y diff --git a/tests/subsys/logging/log_stress/prj.conf b/tests/subsys/logging/log_stress/prj.conf index 7724dc95051..57f0e43212b 100644 --- a/tests/subsys/logging/log_stress/prj.conf +++ b/tests/subsys/logging/log_stress/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTRESS=y CONFIG_TEST_LOGGING_DEFAULTS=n diff --git a/tests/subsys/logging/log_stress/src/main.c b/tests/subsys/logging/log_stress/src/main.c index bf979b2d4c7..8ca43f47b3d 100644 --- a/tests/subsys/logging/log_stress/src/main.c +++ b/tests/subsys/logging/log_stress/src/main.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/tests/subsys/logging/log_stress/testcase.yaml b/tests/subsys/logging/log_stress/testcase.yaml index bc074dbc5b0..3f6843760a8 100644 --- a/tests/subsys/logging/log_stress/testcase.yaml +++ b/tests/subsys/logging/log_stress/testcase.yaml @@ -6,11 +6,11 @@ common: integration_platforms: - qemu_x86 tests: - logging.log_stress_light: + logging.stress.light: extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_LOG_MODE_OVERFLOW=y - logging.log_stress_light_no_overflow: + logging.stress.light_no_overflow: extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_LOG_MODE_OVERFLOW=n @@ -23,7 +23,7 @@ tests: - qemu_x86 - qemu_cortex_a9 - qemu_x86_64 - logging.log_stress_no_overflow: + logging.stress.no_overflow: extra_configs: - CONFIG_LOG_MODE_DEFERRED=y - CONFIG_LOG_MODE_OVERFLOW=n diff --git a/tests/subsys/logging/log_switch_format/prj.conf b/tests/subsys/logging/log_switch_format/prj.conf index 1660a619226..a071c6e27e9 100644 --- a/tests/subsys/logging/log_switch_format/prj.conf +++ b/tests/subsys/logging/log_switch_format/prj.conf @@ -1,5 +1,4 @@ CONFIG_LOG=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=n CONFIG_ZTEST=y CONFIG_LOG_MIPI_SYST_ENABLE=y diff --git a/tests/subsys/logging/log_switch_format/testcase.yaml b/tests/subsys/logging/log_switch_format/testcase.yaml index bd0e3a4a0e1..911c8e2c178 100644 --- a/tests/subsys/logging/log_switch_format/testcase.yaml +++ b/tests/subsys/logging/log_switch_format/testcase.yaml @@ -11,7 +11,7 @@ common: - sparc filter: not CONFIG_64BIT tests: - logging.log_switch_format.deferred: + logging.format.switch.deferred: integration_platforms: - mps2_an385 - qemu_x86 @@ -25,7 +25,7 @@ tests: filter: CONFIG_FULL_LIBC_SUPPORTED extra_configs: - CONFIG_REQUIRES_FULL_LIBC=y - logging.log_switch_format.immediate: + logging.format.switch.immediate: extra_args: OVERLAY_CONFIG=overlay_immediate.conf integration_platforms: - mps2_an385 @@ -33,7 +33,7 @@ tests: filter: CONFIG_FULL_LIBC_SUPPORTED extra_configs: - CONFIG_REQUIRES_FULL_LIBC=y - logging.log_switch_format.custom_output: + logging.format.switch.custom_output: extra_args: OVERLAY_CONFIG=overlay_custom_output.conf integration_platforms: - mps2_an385 diff --git a/tests/subsys/logging/log_syst/prj.conf b/tests/subsys/logging/log_syst/prj.conf index 53dc2bce553..13c5e464e2c 100644 --- a/tests/subsys/logging/log_syst/prj.conf +++ b/tests/subsys/logging/log_syst/prj.conf @@ -1,5 +1,4 @@ CONFIG_LOG=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=n CONFIG_ZTEST=y CONFIG_LOG_BACKEND_MOCK=y diff --git a/tests/subsys/logging/log_syst/src/main.c b/tests/subsys/logging/log_syst/src/main.c index 45b7f34bf1a..bc0e6b2c556 100644 --- a/tests/subsys/logging/log_syst/src/main.c +++ b/tests/subsys/logging/log_syst/src/main.c @@ -152,7 +152,7 @@ static void after(void *unused) if (backend == &log_backend_mock) { log_backend_disable(backend); } else { - log_backend_enable(backend, NULL, 4); + log_backend_enable(backend, backend->cb->ctx, 4); } } } diff --git a/tests/subsys/logging/log_syst/testcase.yaml b/tests/subsys/logging/log_syst/testcase.yaml index 18f4a7cc273..db2160b60f0 100644 --- a/tests/subsys/logging/log_syst/testcase.yaml +++ b/tests/subsys/logging/log_syst/testcase.yaml @@ -1,7 +1,7 @@ common: filter: not CONFIG_64BIT tests: - logging.log_syst.mipi_syst: + logging.mipi_syst: tags: - log_syst - logging @@ -25,7 +25,7 @@ tests: - CONFIG_LOG_MIPI_SYST_ENABLE=y - CONFIG_LOG_BACKEND_MOCK_OUTPUT_SYST=y - CONFIG_REQUIRES_FULL_LIBC=y - logging.log_syst.text: + logging.mipi_syst.text: tags: - log_syst - logging diff --git a/tests/subsys/logging/log_timestamp/prj.conf b/tests/subsys/logging/log_timestamp/prj.conf index 77447af2010..b02eb949445 100644 --- a/tests/subsys/logging/log_timestamp/prj.conf +++ b/tests/subsys/logging/log_timestamp/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_LOGGING_DEFAULTS=n CONFIG_LOG=y CONFIG_LOG_OUTPUT=y diff --git a/tests/subsys/logging/log_timestamp/testcase.yaml b/tests/subsys/logging/log_timestamp/testcase.yaml index 973bb04eb47..6173e67c1d2 100644 --- a/tests/subsys/logging/log_timestamp/testcase.yaml +++ b/tests/subsys/logging/log_timestamp/testcase.yaml @@ -3,12 +3,12 @@ common: - native_posix tests: - logging.log_output_default_timestamp: + logging.output.default_timestamp: tags: - log_output - logging - timestamp - logging.log_output_custom_timestamp: + logging.output.custom_timestamp: tags: - log_output - logging diff --git a/tests/subsys/mem_mgmt/mem_attr/CMakeLists.txt b/tests/subsys/mem_mgmt/mem_attr/CMakeLists.txt new file mode 100644 index 00000000000..7b1f9a77f89 --- /dev/null +++ b/tests/subsys/mem_mgmt/mem_attr/CMakeLists.txt @@ -0,0 +1,8 @@ +#SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(test_mem_attr) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/subsys/mem_mgmt/mem_attr/app.overlay b/tests/subsys/mem_mgmt/mem_attr/app.overlay new file mode 100644 index 00000000000..26773fe2345 --- /dev/null +++ b/tests/subsys/mem_mgmt/mem_attr/app.overlay @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Carlo Caione + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + mem_ram: memory@10000000 { + compatible = "vnd,memory-attr"; + reg = <0x10000000 0x1000>; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_FLASH) | DT_MEM_NON_VOLATILE )>; + }; + + mem_ram_nocache: memory@20000000 { + compatible = "vnd,memory-attr"; + reg = <0x20000000 0x2000>; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) )>; + }; + + mem_ram_disabled: memory@30000000 { + compatible = "vnd,memory-attr"; + reg = <0x30000000 0x3000>; + zephyr,memory-attr = <( DT_MEM_CACHEABLE | DT_MEM_OOO )>; + status = "disabled"; + }; +}; diff --git a/tests/subsys/mem_mgmt/mem_attr/prj.conf b/tests/subsys/mem_mgmt/mem_attr/prj.conf new file mode 100644 index 00000000000..6c71044ec51 --- /dev/null +++ b/tests/subsys/mem_mgmt/mem_attr/prj.conf @@ -0,0 +1,2 @@ +CONFIG_ZTEST=y +CONFIG_MEM_ATTR=y diff --git a/tests/subsys/mem_mgmt/mem_attr/src/main.c b/tests/subsys/mem_mgmt/mem_attr/src/main.c new file mode 100644 index 00000000000..a05ea6dab20 --- /dev/null +++ b/tests/subsys/mem_mgmt/mem_attr/src/main.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2023 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +ZTEST(mem_attr, test_mem_attr) +{ + const struct mem_attr_region_t *region; + size_t num_regions; + + num_regions = mem_attr_get_regions(®ion); + zassert_equal(num_regions, 2, "No regions returned"); + + /* + * Check the data in the regions + */ + for (size_t idx = 0; idx < num_regions; idx++) { + if (region[idx].dt_size == 0x1000) { + zassert_equal(region[idx].dt_addr, 0x10000000, "Wrong region address"); + zassert_equal(region[idx].dt_size, 0x1000, "Wrong region size"); + zassert_equal(region[idx].dt_attr, DT_MEM_ARM_MPU_FLASH | + DT_MEM_NON_VOLATILE, + "Wrong region address"); + zassert_true((strcmp(region[idx].dt_name, "memory@10000000") == 0), + "Wrong name"); + } else { + zassert_equal(region[idx].dt_addr, 0x20000000, "Wrong region address"); + zassert_equal(region[idx].dt_size, 0x2000, "Wrong region size"); + zassert_equal(region[idx].dt_attr, DT_MEM_ARM_MPU_RAM_NOCACHE, + "Wrong region address"); + zassert_true((strcmp(region[idx].dt_name, "memory@20000000") == 0), + "Wrong name"); + } + } + + /* + * Check the input sanitization + */ + zassert_equal(mem_attr_check_buf((void *) 0x10000000, 0x0, DT_MEM_NON_VOLATILE), + -ENOTSUP, "Unexpected return value"); + + /* + * Check a buffer with the correct properties + */ + zassert_equal(mem_attr_check_buf((void *) 0x10000100, 0x100, + DT_MEM_ARM_MPU_FLASH | DT_MEM_NON_VOLATILE), + 0, "Unexpected return value"); + zassert_equal(mem_attr_check_buf((void *) 0x20000000, 0x2000, DT_MEM_ARM_MPU_RAM_NOCACHE), + 0, "Unexpected return value"); + + /* + * Check partial attributes + */ + zassert_equal(mem_attr_check_buf((void *) 0x10000100, 0x100, DT_MEM_NON_VOLATILE), + 0, "Unexpected return value"); + + /* + * Check a buffer with the wrong attribute + */ + zassert_equal(mem_attr_check_buf((void *) 0x20000000, 0x2000, DT_MEM_OOO), + -EINVAL, "Unexpected return value"); + + /* + * Check a buffer outsize the regions + */ + zassert_equal(mem_attr_check_buf((void *) 0x40000000, 0x1000, DT_MEM_NON_VOLATILE), + -ENOBUFS, "Unexpected return value"); + + /* + * Check a buffer too big for the region + */ + zassert_equal(mem_attr_check_buf((void *) 0x10000000, 0x2000, DT_MEM_NON_VOLATILE), + -ENOSPC, "Unexpected return value"); + + /* + * Check a buffer in a disabled region + */ + zassert_equal(mem_attr_check_buf((void *) 0x30000000, 0x1000, DT_MEM_OOO), + -ENOBUFS, "Unexpected return value"); +} + +ZTEST_SUITE(mem_attr, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/subsys/mem_mgmt/mem_attr/testcase.yaml b/tests/subsys/mem_mgmt/mem_attr/testcase.yaml new file mode 100644 index 00000000000..ecb445a077e --- /dev/null +++ b/tests/subsys/mem_mgmt/mem_attr/testcase.yaml @@ -0,0 +1,8 @@ +common: + platform_allow: + - native_posix + - native_posix_64 + integration_platforms: + - native_posix +tests: + mem_mgmt.mem_attr.default: {} diff --git a/tests/subsys/mgmt/ec_host_cmd/simulator/prj.conf b/tests/subsys/mgmt/ec_host_cmd/simulator/prj.conf index 317978c0814..2bad8038ea3 100644 --- a/tests/subsys/mgmt/ec_host_cmd/simulator/prj.conf +++ b/tests/subsys/mgmt/ec_host_cmd/simulator/prj.conf @@ -2,4 +2,3 @@ CONFIG_EC_HOST_CMD=y CONFIG_EC_HOST_CMD_BACKEND_SIMULATOR=y CONFIG_EC_HOST_CMD_DEDICATED_THREAD=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/mgmt/ec_host_cmd/uart/prj.conf b/tests/subsys/mgmt/ec_host_cmd/uart/prj.conf index f543a8d267f..550872463ac 100644 --- a/tests/subsys/mgmt/ec_host_cmd/uart/prj.conf +++ b/tests/subsys/mgmt/ec_host_cmd/uart/prj.conf @@ -2,7 +2,6 @@ CONFIG_EC_HOST_CMD=y CONFIG_EC_HOST_CMD_BACKEND_UART=y CONFIG_EC_HOST_CMD_DEDICATED_THREAD=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_MOCKING=y CONFIG_SERIAL=y CONFIG_UART_ASYNC_API=y diff --git a/tests/subsys/mgmt/mcumgr/all_options/prj.conf b/tests/subsys/mgmt/mcumgr/all_options/prj.conf index d3eb5c39aca..42ce2e03c86 100644 --- a/tests/subsys/mgmt/mcumgr/all_options/prj.conf +++ b/tests/subsys/mgmt/mcumgr/all_options/prj.conf @@ -4,7 +4,6 @@ # SPDX-License-Identifier: Apache-2.0 # CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TINYCRYPT=y CONFIG_TINYCRYPT_SHA256=y CONFIG_FILE_SYSTEM=y diff --git a/tests/subsys/mgmt/mcumgr/cb_notifications/prj.conf b/tests/subsys/mgmt/mcumgr/cb_notifications/prj.conf index b9cdf93a5c1..f668a2f0f73 100644 --- a/tests/subsys/mgmt/mcumgr/cb_notifications/prj.conf +++ b/tests/subsys/mgmt/mcumgr/cb_notifications/prj.conf @@ -14,5 +14,4 @@ CONFIG_MCUMGR_TRANSPORT_DUMMY_RX_BUF_SIZE=256 CONFIG_MCUMGR_GRP_OS=y CONFIG_MCUMGR_MGMT_NOTIFICATION_HOOKS=y CONFIG_MCUMGR_SMP_COMMAND_STATUS_HOOKS=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=2048 diff --git a/tests/subsys/mgmt/mcumgr/cb_notifications/testcase.yaml b/tests/subsys/mgmt/mcumgr/cb_notifications/testcase.yaml index 96503b2acea..4208556288b 100644 --- a/tests/subsys/mgmt/mcumgr/cb_notifications/testcase.yaml +++ b/tests/subsys/mgmt/mcumgr/cb_notifications/testcase.yaml @@ -4,7 +4,7 @@ # SPDX-License-Identifier: Apache-2.0 # tests: - cb.notifications: + mgmt.mcumgr.cb.notifications: platform_allow: - qemu_cortex_m3 - native_posix diff --git a/tests/subsys/mgmt/mcumgr/fs_mgmt_hash_supported/prj.conf b/tests/subsys/mgmt/mcumgr/fs_mgmt_hash_supported/prj.conf index b4e5aac0d27..ef6c180ce9f 100644 --- a/tests/subsys/mgmt/mcumgr/fs_mgmt_hash_supported/prj.conf +++ b/tests/subsys/mgmt/mcumgr/fs_mgmt_hash_supported/prj.conf @@ -17,4 +17,3 @@ CONFIG_MCUMGR_GRP_FS=y CONFIG_MCUMGR_GRP_FS_FILE_STATUS=n CONFIG_MCUMGR_GRP_FS_CHECKSUM_HASH=y CONFIG_MCUMGR_GRP_FS_CHECKSUM_HASH_SUPPORTED_CMD=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/mgmt/mcumgr/mcumgr_client/prj.conf b/tests/subsys/mgmt/mcumgr/mcumgr_client/prj.conf index 461a0ec9477..c9a88a391ee 100644 --- a/tests/subsys/mgmt/mcumgr/mcumgr_client/prj.conf +++ b/tests/subsys/mgmt/mcumgr/mcumgr_client/prj.conf @@ -5,7 +5,6 @@ # # ZTEST config CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=2048 CONFIG_NET_BUF=y diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/CMakeLists.txt b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/CMakeLists.txt new file mode 100644 index 00000000000..5f75eeb5bfa --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/CMakeLists.txt @@ -0,0 +1,17 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(os_mgmt_info) + +FILE(GLOB app_sources + src/*.c +) + +target_sources(app PRIVATE ${app_sources}) +target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/mgmt/mcumgr/transport/include/mgmt/mcumgr/transport/) +target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/mgmt/mcumgr/grp/os_mgmt/include/) diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/native_posix.overlay b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/native_posix.overlay new file mode 100644 index 00000000000..4021ce2ae86 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/native_posix.overlay @@ -0,0 +1,14 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; + + rtc: rtc { + status = "okay"; + compatible = "zephyr,rtc-emul"; + }; +}; diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_arc_hs6x.overlay b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_arc_hs6x.overlay new file mode 100644 index 00000000000..4021ce2ae86 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_arc_hs6x.overlay @@ -0,0 +1,14 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; + + rtc: rtc { + status = "okay"; + compatible = "zephyr,rtc-emul"; + }; +}; diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_cortex_m0.overlay b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_cortex_m0.overlay new file mode 100644 index 00000000000..4021ce2ae86 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_cortex_m0.overlay @@ -0,0 +1,14 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; + + rtc: rtc { + status = "okay"; + compatible = "zephyr,rtc-emul"; + }; +}; diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_leon3.overlay b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_leon3.overlay new file mode 100644 index 00000000000..4021ce2ae86 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_leon3.overlay @@ -0,0 +1,14 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; + + rtc: rtc { + status = "okay"; + compatible = "zephyr,rtc-emul"; + }; +}; diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_malta.overlay b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_malta.overlay new file mode 100644 index 00000000000..4021ce2ae86 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_malta.overlay @@ -0,0 +1,14 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; + + rtc: rtc { + status = "okay"; + compatible = "zephyr,rtc-emul"; + }; +}; diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_riscv64.conf b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_riscv64.conf new file mode 100644 index 00000000000..1ede042960b --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_riscv64.conf @@ -0,0 +1 @@ +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_riscv64.overlay b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_riscv64.overlay new file mode 100644 index 00000000000..4021ce2ae86 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_riscv64.overlay @@ -0,0 +1,14 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; + + rtc: rtc { + status = "okay"; + compatible = "zephyr,rtc-emul"; + }; +}; diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_riscv64_smp.conf b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_riscv64_smp.conf new file mode 100644 index 00000000000..1ede042960b --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_riscv64_smp.conf @@ -0,0 +1 @@ +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_riscv64_smp.overlay b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_riscv64_smp.overlay new file mode 100644 index 00000000000..4021ce2ae86 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/boards/qemu_riscv64_smp.overlay @@ -0,0 +1,14 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; + + rtc: rtc { + status = "okay"; + compatible = "zephyr,rtc-emul"; + }; +}; diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/prj.conf b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/prj.conf new file mode 100644 index 00000000000..0cf01e6335b --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/prj.conf @@ -0,0 +1,21 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_ZTEST=y +CONFIG_RTC=y +CONFIG_NET_BUF=y +CONFIG_BASE64=y +CONFIG_ZCBOR=y +CONFIG_CRC=y +CONFIG_MCUMGR=y +CONFIG_MCUMGR_TRANSPORT_DUMMY=y +CONFIG_MCUMGR_TRANSPORT_DUMMY_RX_BUF_SIZE=256 +CONFIG_MCUMGR_GRP_OS=y +CONFIG_MCUMGR_GRP_OS_ECHO=n +CONFIG_MCUMGR_GRP_OS_DATETIME=y +CONFIG_MCUMGR_GRP_OS_DATETIME_HOOK=y +CONFIG_MCUMGR_MGMT_NOTIFICATION_HOOKS=y +CONFIG_ZTEST_STACK_SIZE=2048 +CONFIG_REBOOT=n diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/src/main.c b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/src/main.c new file mode 100644 index 00000000000..c387c3b4812 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/src/main.c @@ -0,0 +1,1495 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * Copyright (c) 2023 Jamie M. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "smp_test_util.h" + +#define SMP_RESPONSE_WAIT_TIME 3 +#define ZCBOR_BUFFER_SIZE 256 +#define OUTPUT_BUFFER_SIZE 256 +#define ZCBOR_HISTORY_ARRAY_SIZE 4 + +/* Test sets */ +enum { + OS_MGMT_DATETIME_TEST_SET_TIME_NOT_SET = 0, + OS_MGMT_DATETIME_TEST_SET_TIME_SET, +#ifdef CONFIG_MCUMGR_GRP_OS_DATETIME_HOOK + OS_MGMT_DATETIME_TEST_SET_HOOKS, +#endif + + OS_MGMT_DATETIME_TEST_SET_COUNT +}; + +static struct net_buf *nb; + +struct state { + uint8_t test_set; +}; + +static struct state test_state = { + .test_set = 0, +}; + +static struct rtc_time valid_time = { + .tm_sec = 13, + .tm_min = 40, + .tm_hour = 4, + .tm_mday = 4, + .tm_mon = 8, + .tm_year = 2023, +}; + +static struct rtc_time valid_time2 = { + .tm_sec = 5, + .tm_min = 4, + .tm_hour = 3, + .tm_mday = 2, + .tm_mon = 1, + .tm_year = 2001, +}; + +static const char valid_time_string[] = "2023-08-04T04:40:13"; +static const char valid_time2_string[] = "2001-01-02T03:04:05"; +static const char invalid_time_string[] = "abcdefghij"; +static const char invalid_time2_string[] = "20a1-b1-aTbb:dd:qq"; +static const char invalid_time3_string[] = "1820-01-02T03:04:05"; + +struct group_error { + uint16_t group; + uint16_t rc; + bool found; +}; + +#ifdef CONFIG_MCUMGR_GRP_OS_DATETIME_HOOK +static bool hook_get_ran; +static bool hook_set_ran; +static bool hook_other_ran; +static uint8_t hook_set_data_size; +static uint8_t hook_set_data[64]; +#endif + +static void cleanup_test(void *p); + +static bool mcumgr_ret_decode(zcbor_state_t *state, struct group_error *result) +{ + bool ok; + size_t decoded; + uint32_t tmp_group; + uint32_t tmp_rc; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_DECODER("group", zcbor_uint32_decode, &tmp_group), + ZCBOR_MAP_DECODE_KEY_DECODER("rc", zcbor_uint32_decode, &tmp_rc), + }; + + result->found = false; + + ok = zcbor_map_decode_bulk(state, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + if (ok && + zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), "group") && + zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), "rc")) { + result->group = (uint16_t)tmp_group; + result->rc = (uint16_t)tmp_rc; + result->found = true; + } + + return ok; +} + +#ifdef CONFIG_MCUMGR_GRP_OS_DATETIME_HOOK +static enum mgmt_cb_return os_mgmt_datetime_callback(uint32_t event, + enum mgmt_cb_return prev_status, int32_t *rc, + uint16_t *group, bool *abort_more, + void *data, size_t data_size) +{ + if (event == MGMT_EVT_OP_OS_MGMT_DATETIME_GET) { + hook_get_ran = true; + + *rc = MGMT_ERR_EBUSY; + return MGMT_CB_ERROR_RC; + } else if (event == MGMT_EVT_OP_OS_MGMT_DATETIME_SET) { + hook_set_ran = true; + hook_set_data_size = data_size; + memcpy(hook_set_data, data, data_size); + + *rc = MGMT_ERR_EACCESSDENIED; + return MGMT_CB_ERROR_RC; + } + + hook_other_ran = true; + return MGMT_CB_OK; +} + +static struct mgmt_callback os_datetime_callbacks = { + .callback = os_mgmt_datetime_callback, + .event_id = (MGMT_EVT_OP_OS_MGMT_DATETIME_GET | MGMT_EVT_OP_OS_MGMT_DATETIME_SET), +}; +#endif + +ZTEST(os_mgmt_datetime_not_set, test_datetime_get_not_set_v1) +{ + uint8_t buffer[ZCBOR_BUFFER_SIZE]; + uint8_t buffer_out[OUTPUT_BUFFER_SIZE]; + bool ok; + uint16_t buffer_size; + zcbor_state_t zse[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + zcbor_state_t zsd[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + bool received; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + struct group_error group_error; + int rc; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_DECODER("datetime", zcbor_tstr_decode, &output), + ZCBOR_MAP_DECODE_KEY_DECODER("rc", zcbor_int32_decode, &rc), + ZCBOR_MAP_DECODE_KEY_DECODER("err", mcumgr_ret_decode, &group_error), + }; + + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + + zcbor_new_encode_state(zse, 2, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_get_packet(zse, false, buffer, buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Did not expect to receive datetime element"); + zassert_true(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Did not expect to receive rc element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Expected to receive err element"); + zassert_equal(rc, MGMT_ERR_ENOENT, "Expected 'rc' to be no entity"); +} + +ZTEST(os_mgmt_datetime_not_set, test_datetime_get_not_set_v2) +{ + uint8_t buffer[ZCBOR_BUFFER_SIZE]; + uint8_t buffer_out[OUTPUT_BUFFER_SIZE]; + bool ok; + uint16_t buffer_size; + zcbor_state_t zse[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + zcbor_state_t zsd[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + bool received; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + struct group_error group_error; + int rc; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_DECODER("datetime", zcbor_tstr_decode, &output), + ZCBOR_MAP_DECODE_KEY_DECODER("rc", zcbor_int32_decode, &rc), + ZCBOR_MAP_DECODE_KEY_DECODER("err", mcumgr_ret_decode, &group_error), + }; + + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + + zcbor_new_encode_state(zse, 2, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_get_packet(zse, true, buffer, buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Did not expect to receive datetime element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Did not expect to receive rc element"); + zassert_true(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Expected to receive err element"); + zassert_equal(group_error.group, MGMT_GROUP_ID_OS, "Expected 'err' -> 'group' to be OS"); + zassert_equal(group_error.rc, OS_MGMT_ERR_RTC_NOT_SET, + "Expected 'err' -> 'rc' to be RTC not set"); +} + +ZTEST(os_mgmt_datetime_not_set, test_datetime_set_invalid_v1_1) +{ + uint8_t buffer[ZCBOR_BUFFER_SIZE]; + uint8_t buffer_out[OUTPUT_BUFFER_SIZE]; + bool ok; + uint16_t buffer_size; + zcbor_state_t zse[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + zcbor_state_t zsd[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + bool received; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + struct group_error group_error; + int rc; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_DECODER("datetime", zcbor_tstr_decode, &output), + ZCBOR_MAP_DECODE_KEY_DECODER("rc", zcbor_int32_decode, &rc), + ZCBOR_MAP_DECODE_KEY_DECODER("err", mcumgr_ret_decode, &group_error), + }; + + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + + zcbor_new_encode_state(zse, 4, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_set_packet_str(zse, false, invalid_time_string, buffer, + buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Did not expect to receive datetime element"); + zassert_true(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Expected to receive rc element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Did not expect to receive err element"); + zassert_equal(rc, MGMT_ERR_EINVAL, "Expected 'rc' to be invalid value"); + + /* Clean up test */ + cleanup_test(NULL); + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + output_decode[0].found = false; + output_decode[1].found = false; + output_decode[2].found = false; + + /* Query time and ensure it is not set */ + zcbor_new_encode_state(zse, 2, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_get_packet(zse, false, buffer, buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Did not expect to receive datetime element"); + zassert_true(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Did not expect to receive rc element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Expected to receive err element"); + zassert_equal(rc, MGMT_ERR_ENOENT, "Expected 'rc' to be no entity"); +} + +ZTEST(os_mgmt_datetime_not_set, test_datetime_set_invalid_v1_2) +{ + uint8_t buffer[ZCBOR_BUFFER_SIZE]; + uint8_t buffer_out[OUTPUT_BUFFER_SIZE]; + bool ok; + uint16_t buffer_size; + zcbor_state_t zse[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + zcbor_state_t zsd[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + bool received; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + struct group_error group_error; + int rc; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_DECODER("datetime", zcbor_tstr_decode, &output), + ZCBOR_MAP_DECODE_KEY_DECODER("rc", zcbor_int32_decode, &rc), + ZCBOR_MAP_DECODE_KEY_DECODER("err", mcumgr_ret_decode, &group_error), + }; + + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + + zcbor_new_encode_state(zse, 4, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_set_packet_str(zse, false, invalid_time2_string, buffer, + buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Did not expect to receive datetime element"); + zassert_true(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Expected to receive rc element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Did not expect to receive err element"); + zassert_equal(rc, MGMT_ERR_EINVAL, "Expected 'rc' to be invalid value"); + + /* Clean up test */ + cleanup_test(NULL); + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + output_decode[0].found = false; + output_decode[1].found = false; + output_decode[2].found = false; + + /* Query time and ensure it is not set */ + zcbor_new_encode_state(zse, 2, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_get_packet(zse, false, buffer, buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Did not expect to receive datetime element"); + zassert_true(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Did not expect to receive rc element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Expected to receive err element"); + zassert_equal(rc, MGMT_ERR_ENOENT, "Expected 'rc' to be no entity"); +} + +ZTEST(os_mgmt_datetime_not_set, test_datetime_set_invalid_v1_3) +{ + uint8_t buffer[ZCBOR_BUFFER_SIZE]; + uint8_t buffer_out[OUTPUT_BUFFER_SIZE]; + bool ok; + uint16_t buffer_size; + zcbor_state_t zse[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + zcbor_state_t zsd[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + bool received; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + struct group_error group_error; + int rc; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_DECODER("datetime", zcbor_tstr_decode, &output), + ZCBOR_MAP_DECODE_KEY_DECODER("rc", zcbor_int32_decode, &rc), + ZCBOR_MAP_DECODE_KEY_DECODER("err", mcumgr_ret_decode, &group_error), + }; + + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + + zcbor_new_encode_state(zse, 4, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_set_packet_str(zse, false, invalid_time3_string, buffer, + buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Did not expect to receive datetime element"); + zassert_true(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Expected to receive rc element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Did not expect to receive err element"); + zassert_equal(rc, MGMT_ERR_EINVAL, "Expected 'rc' to be invalid value"); + + /* Clean up test */ + cleanup_test(NULL); + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + output_decode[0].found = false; + output_decode[1].found = false; + output_decode[2].found = false; + + /* Query time and ensure it is not set */ + zcbor_new_encode_state(zse, 2, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_get_packet(zse, false, buffer, buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Did not expect to receive datetime element"); + zassert_true(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Did not expect to receive rc element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Expected to receive err element"); + zassert_equal(rc, MGMT_ERR_ENOENT, "Expected 'rc' to be no entity"); +} + +ZTEST(os_mgmt_datetime_not_set, test_datetime_set_invalid_v2_1) +{ + uint8_t buffer[ZCBOR_BUFFER_SIZE]; + uint8_t buffer_out[OUTPUT_BUFFER_SIZE]; + bool ok; + uint16_t buffer_size; + zcbor_state_t zse[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + zcbor_state_t zsd[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + bool received; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + struct group_error group_error; + int rc; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_DECODER("datetime", zcbor_tstr_decode, &output), + ZCBOR_MAP_DECODE_KEY_DECODER("rc", zcbor_int32_decode, &rc), + ZCBOR_MAP_DECODE_KEY_DECODER("err", mcumgr_ret_decode, &group_error), + }; + + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + + zcbor_new_encode_state(zse, 4, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_set_packet_str(zse, true, invalid_time2_string, buffer, + buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Did not expect to receive datetime element"); + zassert_true(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Expected to receive rc element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Did not expect to receive err element"); + zassert_equal(rc, MGMT_ERR_EINVAL, "Expected 'rc' to be invalid value"); + + /* Clean up test */ + cleanup_test(NULL); + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + output_decode[0].found = false; + output_decode[1].found = false; + output_decode[2].found = false; + + /* Query time and ensure it is not set */ + zcbor_new_encode_state(zse, 2, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_get_packet(zse, true, buffer, buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Did not expect to receive datetime element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Did not expect to receive rc element"); + zassert_true(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Expected to receive err element"); + zassert_equal(group_error.group, MGMT_GROUP_ID_OS, "Expected 'err' -> 'group' to be OS"); + zassert_equal(group_error.rc, OS_MGMT_ERR_RTC_NOT_SET, + "Expected 'err' -> 'rc' to be RTC not set"); +} + +ZTEST(os_mgmt_datetime_not_set, test_datetime_set_invalid_v2_2) +{ + uint8_t buffer[ZCBOR_BUFFER_SIZE]; + uint8_t buffer_out[OUTPUT_BUFFER_SIZE]; + bool ok; + uint16_t buffer_size; + zcbor_state_t zse[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + zcbor_state_t zsd[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + bool received; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + struct group_error group_error; + int rc; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_DECODER("datetime", zcbor_tstr_decode, &output), + ZCBOR_MAP_DECODE_KEY_DECODER("rc", zcbor_int32_decode, &rc), + ZCBOR_MAP_DECODE_KEY_DECODER("err", mcumgr_ret_decode, &group_error), + }; + + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + + zcbor_new_encode_state(zse, 4, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_set_packet_str(zse, true, invalid_time2_string, buffer, + buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Did not expect to receive datetime element"); + zassert_true(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Expected to receive rc element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Did not expect to receive err element"); + zassert_equal(rc, MGMT_ERR_EINVAL, "Expected 'rc' to be invalid value"); + + /* Clean up test */ + cleanup_test(NULL); + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + output_decode[0].found = false; + output_decode[1].found = false; + output_decode[2].found = false; + + /* Query time and ensure it is not set */ + zcbor_new_encode_state(zse, 2, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_get_packet(zse, true, buffer, buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Did not expect to receive datetime element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Did not expect to receive rc element"); + zassert_true(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Expected to receive err element"); + zassert_equal(group_error.group, MGMT_GROUP_ID_OS, "Expected 'err' -> 'group' to be OS"); + zassert_equal(group_error.rc, OS_MGMT_ERR_RTC_NOT_SET, + "Expected 'err' -> 'rc' to be RTC not set"); +} + +ZTEST(os_mgmt_datetime_not_set, test_datetime_set_invalid_v2_3) +{ + uint8_t buffer[ZCBOR_BUFFER_SIZE]; + uint8_t buffer_out[OUTPUT_BUFFER_SIZE]; + bool ok; + uint16_t buffer_size; + zcbor_state_t zse[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + zcbor_state_t zsd[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + bool received; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + struct group_error group_error; + int rc; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_DECODER("datetime", zcbor_tstr_decode, &output), + ZCBOR_MAP_DECODE_KEY_DECODER("rc", zcbor_int32_decode, &rc), + ZCBOR_MAP_DECODE_KEY_DECODER("err", mcumgr_ret_decode, &group_error), + }; + + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + + zcbor_new_encode_state(zse, 4, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_set_packet_str(zse, true, invalid_time3_string, buffer, + buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Did not expect to receive datetime element"); + zassert_true(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Expected to receive rc element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Did not expect to receive err element"); + zassert_equal(rc, MGMT_ERR_EINVAL, "Expected 'rc' to be invalid value"); + + /* Clean up test */ + cleanup_test(NULL); + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + output_decode[0].found = false; + output_decode[1].found = false; + output_decode[2].found = false; + + /* Query time and ensure it is not set */ + zcbor_new_encode_state(zse, 2, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_get_packet(zse, true, buffer, buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Did not expect to receive datetime element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Did not expect to receive rc element"); + zassert_true(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Expected to receive err element"); + zassert_equal(group_error.group, MGMT_GROUP_ID_OS, "Expected 'err' -> 'group' to be OS"); + zassert_equal(group_error.rc, OS_MGMT_ERR_RTC_NOT_SET, + "Expected 'err' -> 'rc' to be RTC not set"); +} + +ZTEST(os_mgmt_datetime_set, test_datetime_set_v1) +{ + uint8_t buffer[ZCBOR_BUFFER_SIZE]; + uint8_t buffer_out[OUTPUT_BUFFER_SIZE]; + bool ok; + uint16_t buffer_size; + zcbor_state_t zse[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + zcbor_state_t zsd[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + bool received; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + struct group_error group_error; + int rc; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_DECODER("datetime", zcbor_tstr_decode, &output), + ZCBOR_MAP_DECODE_KEY_DECODER("rc", zcbor_int32_decode, &rc), + ZCBOR_MAP_DECODE_KEY_DECODER("err", mcumgr_ret_decode, &group_error), + }; + + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + + zcbor_new_encode_state(zse, 4, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_set_packet(zse, false, &valid_time, buffer, buffer_out, + &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 0, "Did not expect to receive any decoded zcbor element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Did not expect to receive datetime element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Did not expect to receive rc element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Did not expect to receive err element"); + + /* Clean up test */ + cleanup_test(NULL); + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + output_decode[0].found = false; + output_decode[1].found = false; + output_decode[2].found = false; + + /* Query time and ensure it is set */ + zcbor_new_encode_state(zse, 2, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_get_packet(zse, false, buffer, buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element"); + zassert_true(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Expected to receive datetime element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Did not expect to receive rc element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Did not expected to receive err element"); + + /* Check that the date/time is as expected */ + zassert_equal(output.len, strlen(valid_time_string), + "Expected received datetime length mismatch"); + zassert_mem_equal(output.value, valid_time_string, strlen(valid_time_string), + "Expected received datetime value mismatch"); +} + +ZTEST(os_mgmt_datetime_set, test_datetime_set_v2) +{ + uint8_t buffer[ZCBOR_BUFFER_SIZE]; + uint8_t buffer_out[OUTPUT_BUFFER_SIZE]; + bool ok; + uint16_t buffer_size; + zcbor_state_t zse[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + zcbor_state_t zsd[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + bool received; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + struct group_error group_error; + int rc; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_DECODER("datetime", zcbor_tstr_decode, &output), + ZCBOR_MAP_DECODE_KEY_DECODER("rc", zcbor_int32_decode, &rc), + ZCBOR_MAP_DECODE_KEY_DECODER("err", mcumgr_ret_decode, &group_error), + }; + + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + + zcbor_new_encode_state(zse, 4, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_set_packet(zse, true, &valid_time2, buffer, buffer_out, + &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 0, "Did not expect to receive any decoded zcbor element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Did not expect to receive datetime element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Did not expect to receive rc element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Did not expect to receive err element"); + + /* Clean up test */ + cleanup_test(NULL); + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + output_decode[0].found = false; + output_decode[1].found = false; + output_decode[2].found = false; + + /* Query time and ensure it is set */ + zcbor_new_encode_state(zse, 2, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_get_packet(zse, false, buffer, buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element"); + zassert_true(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Expected to receive datetime element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Did not expect to receive rc element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Did not expected to receive err element"); + + /* Check that the date/time is as expected */ + zassert_equal(output.len, strlen(valid_time2_string), + "Expected received datetime length mismatch"); + zassert_mem_equal(output.value, valid_time2_string, strlen(valid_time2_string), + "Expected received datetime value mismatch"); +} + +#ifdef CONFIG_MCUMGR_GRP_OS_DATETIME_HOOK +static void *setup_os_datetime_callbacks(void) +{ + mgmt_callback_register(&os_datetime_callbacks); + return NULL; +} + +static void destroy_os_datetime_callbacks(void *p) +{ + mgmt_callback_unregister(&os_datetime_callbacks); +} + +ZTEST(os_mgmt_datetime_hook, test_datetime_set_valid_hook_v1) +{ + uint8_t buffer[ZCBOR_BUFFER_SIZE]; + uint8_t buffer_out[OUTPUT_BUFFER_SIZE]; + bool ok; + uint16_t buffer_size; + zcbor_state_t zse[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + zcbor_state_t zsd[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + bool received; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + struct group_error group_error; + int rc; + struct rtc_time *hook_data; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_DECODER("datetime", zcbor_tstr_decode, &output), + ZCBOR_MAP_DECODE_KEY_DECODER("rc", zcbor_int32_decode, &rc), + ZCBOR_MAP_DECODE_KEY_DECODER("err", mcumgr_ret_decode, &group_error), + }; + + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + + zcbor_new_encode_state(zse, 4, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_set_packet(zse, false, &valid_time2, buffer, buffer_out, + &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Did not expect to receive datetime element"); + zassert_true(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Expected to receive rc element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Did not expect to receive err element"); + zassert_equal(rc, MGMT_ERR_EACCESSDENIED, "Expected 'rc' to be access denied"); + + /* Check hook actions are as expected */ + hook_data = (struct rtc_time *)hook_set_data; + zassert_false(hook_get_ran, "Did not expect get hook to run"); + zassert_true(hook_set_ran, "Expected set hook to run"); + zassert_false(hook_other_ran, "Did not expect other hooks to run"); + zassert_equal(hook_set_data_size, sizeof(valid_time2), + "Expected data size to match time struct size"); + zassert_equal(valid_time2.tm_sec, hook_data->tm_sec, "Expected value mismatch"); + zassert_equal(valid_time2.tm_min, hook_data->tm_min, "Expected value mismatch"); + zassert_equal(valid_time2.tm_hour, hook_data->tm_hour, "Expected value mismatch"); + zassert_equal(valid_time2.tm_mday, hook_data->tm_mday, "Expected value mismatch"); + zassert_equal(valid_time2.tm_mon, (hook_data->tm_mon + 1), "Expected value mismatch"); + zassert_equal(valid_time2.tm_year, (hook_data->tm_year + 1900), + "Expected value mismatch"); + + /* Clean up test */ + cleanup_test(NULL); + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + output_decode[0].found = false; + output_decode[1].found = false; + output_decode[2].found = false; + + /* Query time and ensure it is not set */ + zcbor_new_encode_state(zse, 2, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_get_packet(zse, false, buffer, buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Did not expect to receive datetime element"); + zassert_true(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Expected to receive rc element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Did not expect to receive err element"); + zassert_equal(rc, MGMT_ERR_EBUSY, "Expected 'rc' to be busy"); + + /* Check hook actions are as expected */ + zassert_true(hook_get_ran, "Expected get hook to run"); + zassert_false(hook_set_ran, "Did not expect set hook to run"); + zassert_false(hook_other_ran, "Did not expect other hooks to run"); + zassert_equal(hook_set_data_size, 0, "Expected data size to be 0"); +} + +ZTEST(os_mgmt_datetime_hook, test_datetime_set_valid_hook_v2) +{ + uint8_t buffer[ZCBOR_BUFFER_SIZE]; + uint8_t buffer_out[OUTPUT_BUFFER_SIZE]; + bool ok; + uint16_t buffer_size; + zcbor_state_t zse[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + zcbor_state_t zsd[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + bool received; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + struct group_error group_error; + int rc; + struct rtc_time *hook_data; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_DECODER("datetime", zcbor_tstr_decode, &output), + ZCBOR_MAP_DECODE_KEY_DECODER("rc", zcbor_int32_decode, &rc), + ZCBOR_MAP_DECODE_KEY_DECODER("err", mcumgr_ret_decode, &group_error), + }; + + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + + zcbor_new_encode_state(zse, 4, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_set_packet(zse, true, &valid_time2, buffer, buffer_out, + &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Did not expect to receive datetime element"); + zassert_true(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Expected to receive rc element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Did not expect to receive err element"); + zassert_equal(rc, MGMT_ERR_EACCESSDENIED, "Expected 'rc' to be access denied"); + + /* Check hook actions are as expected */ + hook_data = (struct rtc_time *)hook_set_data; + zassert_false(hook_get_ran, "Did not expect get hook to run"); + zassert_true(hook_set_ran, "Expected set hook to run"); + zassert_false(hook_other_ran, "Did not expect other hooks to run"); + zassert_equal(hook_set_data_size, sizeof(valid_time2), + "Expected data size to match time struct size"); + zassert_equal(valid_time2.tm_sec, hook_data->tm_sec, "Expected value mismatch"); + zassert_equal(valid_time2.tm_min, hook_data->tm_min, "Expected value mismatch"); + zassert_equal(valid_time2.tm_hour, hook_data->tm_hour, "Expected value mismatch"); + zassert_equal(valid_time2.tm_mday, hook_data->tm_mday, "Expected value mismatch"); + zassert_equal(valid_time2.tm_mon, (hook_data->tm_mon + 1), "Expected value mismatch"); + zassert_equal(valid_time2.tm_year, (hook_data->tm_year + 1900), "Expected value mismatch"); + + /* Clean up test */ + cleanup_test(NULL); + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + output_decode[0].found = false; + output_decode[1].found = false; + output_decode[2].found = false; + + /* Query time and ensure it is not set */ + zcbor_new_encode_state(zse, 2, buffer, ARRAY_SIZE(buffer), 0); + ok = create_mcumgr_datetime_get_packet(zse, true, buffer, buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + zassert_true(received, "Expected to receive data but timed out"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + zassert_true(ok, "Expected decode to be successful"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "datetime"), "Did not expect to receive datetime element"); + zassert_true(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "rc"), "Expected to receive rc element"); + zassert_false(zcbor_map_decode_bulk_key_found(output_decode, ARRAY_SIZE(output_decode), + "err"), "Did not expect to receive err element"); + zassert_equal(rc, MGMT_ERR_EBUSY, "Expected 'rc' to be busy"); + + /* Check hook actions are as expected */ + zassert_true(hook_get_ran, "Expected get hook to run"); + zassert_false(hook_set_ran, "Did not expect set hook to run"); + zassert_false(hook_other_ran, "Did not expect other hooks to run"); + zassert_equal(hook_set_data_size, 0, "Expected data size to be 0"); +} +#endif + +static void cleanup_test(void *p) +{ + if (nb != NULL) { + net_buf_unref(nb); + nb = NULL; + } + +#ifdef CONFIG_MCUMGR_GRP_OS_DATETIME_HOOK + hook_get_ran = false; + hook_set_ran = false; + hook_other_ran = false; + hook_set_data_size = 0; + hook_set_data[0] = 0; +#endif +} + +void test_main(void) +{ + while (test_state.test_set < OS_MGMT_DATETIME_TEST_SET_COUNT) { + ztest_run_all(&test_state); + ++test_state.test_set; + } + + ztest_verify_all_test_suites_ran(); +} + +static bool time_not_set_predicate(const void *state) +{ + return ((struct state *)state)->test_set == OS_MGMT_DATETIME_TEST_SET_TIME_NOT_SET; +} + +static bool time_set_predicate(const void *state) +{ + return ((struct state *)state)->test_set == OS_MGMT_DATETIME_TEST_SET_TIME_SET; +} + +#ifdef CONFIG_MCUMGR_GRP_OS_DATETIME_HOOK +static bool hooks_predicate(const void *state) +{ + return ((struct state *)state)->test_set == OS_MGMT_DATETIME_TEST_SET_HOOKS; +} +#endif + +/* Time not set test set */ +ZTEST_SUITE(os_mgmt_datetime_not_set, time_not_set_predicate, NULL, NULL, cleanup_test, NULL); + +#ifdef CONFIG_MCUMGR_GRP_OS_DATETIME_HOOK +/* Hook test set */ +ZTEST_SUITE(os_mgmt_datetime_hook, hooks_predicate, setup_os_datetime_callbacks, NULL, + cleanup_test, destroy_os_datetime_callbacks); +#endif + +/* Time set test set */ +ZTEST_SUITE(os_mgmt_datetime_set, time_set_predicate, NULL, NULL, cleanup_test, NULL); diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/src/smp_test_util.c b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/src/smp_test_util.c new file mode 100644 index 00000000000..927089c3ee3 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/src/smp_test_util.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * Copyright (c) 2023 Jamie M. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "smp_test_util.h" +#include +#include +#include +#include + +/* SMP header function for generating os_mgmt datetime command header with sequence number set + * to 1 + */ +void smp_make_hdr(struct smp_hdr *rsp_hdr, size_t len, bool version2, bool write) +{ + *rsp_hdr = (struct smp_hdr) { + .nh_len = sys_cpu_to_be16(len), + .nh_flags = 0, + .nh_version = (version2 == true ? SMP_MCUMGR_VERSION_2 : SMP_MCUMGR_VERSION_1), + .nh_op = (write == true ? MGMT_OP_WRITE : MGMT_OP_READ), + .nh_group = sys_cpu_to_be16(MGMT_GROUP_ID_OS), + .nh_seq = 1, + .nh_id = OS_MGMT_ID_DATETIME_STR, + }; +} + +/* Function for creating an os_mgmt datetime get command */ +bool create_mcumgr_datetime_get_packet(zcbor_state_t *zse, bool version2, uint8_t *buffer, + uint8_t *output_buffer, uint16_t *buffer_size) +{ + bool ok; + + ok = zcbor_map_start_encode(zse, 2) && + zcbor_map_end_encode(zse, 2); + + *buffer_size = (zse->payload_mut - buffer); + smp_make_hdr((struct smp_hdr *)output_buffer, *buffer_size, version2, false); + memcpy(&output_buffer[sizeof(struct smp_hdr)], buffer, *buffer_size); + *buffer_size += sizeof(struct smp_hdr); + + return ok; +} + +/* Functions for creating an os_mgmt datetime set command */ +bool create_mcumgr_datetime_set_packet_str(zcbor_state_t *zse, bool version2, const char *data, + uint8_t *buffer, uint8_t *output_buffer, + uint16_t *buffer_size) +{ + bool ok = zcbor_map_start_encode(zse, 2) && + zcbor_tstr_put_lit(zse, "datetime") && + zcbor_tstr_put_term(zse, data) && + zcbor_map_end_encode(zse, 2); + + *buffer_size = (zse->payload_mut - buffer); + smp_make_hdr((struct smp_hdr *)output_buffer, *buffer_size, version2, true); + memcpy(&output_buffer[sizeof(struct smp_hdr)], buffer, *buffer_size); + *buffer_size += sizeof(struct smp_hdr); + + return ok; +} + +bool create_mcumgr_datetime_set_packet(zcbor_state_t *zse, bool version2, struct rtc_time *a_time, + uint8_t *buffer, uint8_t *output_buffer, + uint16_t *buffer_size) +{ + char tmp_str[32]; + + sprintf(tmp_str, "%4d-%02d-%02dT%02d:%02d:%02d", (uint16_t)a_time->tm_year, + (uint8_t)a_time->tm_mon, (uint8_t)a_time->tm_mday, (uint8_t)a_time->tm_hour, + (uint8_t)a_time->tm_min, (uint8_t)a_time->tm_sec); + + return create_mcumgr_datetime_set_packet_str(zse, version2, tmp_str, buffer, + output_buffer, buffer_size); +} diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/src/smp_test_util.h b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/src/smp_test_util.h new file mode 100644 index 00000000000..958ccfdd5ad --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/src/smp_test_util.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * Copyright (c) 2023 Jamie M. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef H_SMP_TEST_UTIL_ +#define H_SMP_TEST_UTIL_ + +#include +#include +#include +#include +#include + +/* SMP header function for generating os_mgmt datetime command header with sequence number set + * to 1 + */ +void smp_make_hdr(struct smp_hdr *rsp_hdr, size_t len, bool version2, bool write); + +/* Function for creating an os_mgmt datetime get command */ +bool create_mcumgr_datetime_get_packet(zcbor_state_t *zse, bool version2, uint8_t *buffer, + uint8_t *output_buffer, uint16_t *buffer_size); + +/* Function for creating an os_mgmt datetime set command */ +bool create_mcumgr_datetime_set_packet_str(zcbor_state_t *zse, bool version2, const char *data, + uint8_t *buffer, uint8_t *output_buffer, + uint16_t *buffer_size); + +bool create_mcumgr_datetime_set_packet(zcbor_state_t *zse, bool version2, struct rtc_time *a_time, + uint8_t *buffer, uint8_t *output_buffer, + uint16_t *buffer_size); + +#endif diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/testcase.yaml b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/testcase.yaml new file mode 100644 index 00000000000..013a371c9a0 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/testcase.yaml @@ -0,0 +1,19 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +common: + tags: + - mcumgr + - os_mgmt_datetime + platform_allow: + - native_posix + - qemu_cortex_m0 + - qemu_riscv64 + - qemu_riscv64_smp + - qemu_malta + - qemu_arc_hs6x + - qemu_leon3 +tests: + mgmt.mcumgr.os.datetime: {} diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_echo/prj.conf b/tests/subsys/mgmt/mcumgr/os_mgmt_echo/prj.conf index 69cbe9882f6..ff4475a4f2e 100644 --- a/tests/subsys/mgmt/mcumgr/os_mgmt_echo/prj.conf +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_echo/prj.conf @@ -13,4 +13,3 @@ CONFIG_MCUMGR_TRANSPORT_DUMMY=y CONFIG_MCUMGR_TRANSPORT_DUMMY_RX_BUF_SIZE=256 CONFIG_MCUMGR_GRP_OS=y CONFIG_MCUMGR_GRP_OS_ECHO=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_info/prj.conf b/tests/subsys/mgmt/mcumgr/os_mgmt_info/prj.conf index 0aa68bbfc49..ec21be76e91 100644 --- a/tests/subsys/mgmt/mcumgr/os_mgmt_info/prj.conf +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_info/prj.conf @@ -15,5 +15,4 @@ CONFIG_MCUMGR_GRP_OS=y CONFIG_MCUMGR_GRP_OS_INFO=y CONFIG_MCUMGR_GRP_OS_INFO_CUSTOM_HOOKS=y CONFIG_MCUMGR_MGMT_NOTIFICATION_HOOKS=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=2048 diff --git a/tests/subsys/mgmt/mcumgr/settings_mgmt/prj.conf b/tests/subsys/mgmt/mcumgr/settings_mgmt/prj.conf index e570c43b7dd..403a318ac1a 100644 --- a/tests/subsys/mgmt/mcumgr/settings_mgmt/prj.conf +++ b/tests/subsys/mgmt/mcumgr/settings_mgmt/prj.conf @@ -14,7 +14,6 @@ CONFIG_MCUMGR_TRANSPORT_DUMMY_RX_BUF_SIZE=256 CONFIG_MCUMGR_GRP_SETTINGS=y CONFIG_MCUMGR_MGMT_NOTIFICATION_HOOKS=y CONFIG_MCUMGR_GRP_SETTINGS_ACCESS_HOOK=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=2048 CONFIG_SETTINGS=y CONFIG_SETTINGS_RUNTIME=y diff --git a/tests/subsys/mgmt/mcumgr/smp_client/prj.conf b/tests/subsys/mgmt/mcumgr/smp_client/prj.conf index 22740657b78..fa9a90cfd54 100644 --- a/tests/subsys/mgmt/mcumgr/smp_client/prj.conf +++ b/tests/subsys/mgmt/mcumgr/smp_client/prj.conf @@ -5,7 +5,6 @@ # # ZTEST config CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=2048 CONFIG_NET_BUF=y diff --git a/tests/subsys/mgmt/mcumgr/smp_reassembly/prj.conf b/tests/subsys/mgmt/mcumgr/smp_reassembly/prj.conf index f30eed7221b..8e9962d9a04 100644 --- a/tests/subsys/mgmt/mcumgr/smp_reassembly/prj.conf +++ b/tests/subsys/mgmt/mcumgr/smp_reassembly/prj.conf @@ -10,4 +10,3 @@ CONFIG_ZCBOR=y CONFIG_CRC=y CONFIG_MCUMGR=y CONFIG_MCUMGR_TRANSPORT_NETBUF_COUNT=1 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/mgmt/mcumgr/smp_version/prj.conf b/tests/subsys/mgmt/mcumgr/smp_version/prj.conf index fb9a0c91c5c..2573d131822 100644 --- a/tests/subsys/mgmt/mcumgr/smp_version/prj.conf +++ b/tests/subsys/mgmt/mcumgr/smp_version/prj.conf @@ -13,6 +13,5 @@ CONFIG_MCUMGR_TRANSPORT_DUMMY=y CONFIG_MCUMGR_TRANSPORT_DUMMY_RX_BUF_SIZE=256 CONFIG_MCUMGR_GRP_OS=y CONFIG_MCUMGR_GRP_OS_INFO=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=2048 CONFIG_REBOOT=n diff --git a/tests/subsys/mgmt/mcumgr/smp_version/testcase.yaml b/tests/subsys/mgmt/mcumgr/smp_version/testcase.yaml index 57ba9712512..cc7c8888dc7 100644 --- a/tests/subsys/mgmt/mcumgr/smp_version/testcase.yaml +++ b/tests/subsys/mgmt/mcumgr/smp_version/testcase.yaml @@ -4,19 +4,18 @@ # SPDX-License-Identifier: Apache-2.0 # tests: - smp.version: + mgmt.mcumgr.smp.version: tags: - smp_version - mcumgr # FIXME: Exclude systems whereby the processor type is not known and emits a warning arch_exclude: - nios2 - - sparc - mips - posix platform_exclude: - qemu_kvm_arm64 - smp.version_no_legacy: + mgmt.mcumgr.smp.version_no_legacy: tags: - smp_version - mcumgr @@ -25,7 +24,6 @@ tests: # FIXME: Exclude systems whereby the processor type is not known and emits a warning arch_exclude: - nios2 - - sparc - mips - posix platform_exclude: diff --git a/tests/subsys/mgmt/mcumgr/zcbor_bulk/prj.conf b/tests/subsys/mgmt/mcumgr/zcbor_bulk/prj.conf index 892964fae7c..eca7db02abd 100644 --- a/tests/subsys/mgmt/mcumgr/zcbor_bulk/prj.conf +++ b/tests/subsys/mgmt/mcumgr/zcbor_bulk/prj.conf @@ -5,5 +5,4 @@ # CONFIG_ZTEST=y CONFIG_ZCBOR=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=4096 diff --git a/tests/subsys/modbus/prj.conf b/tests/subsys/modbus/prj.conf index 1118316b304..06166d17f9b 100644 --- a/tests/subsys/modbus/prj.conf +++ b/tests/subsys/modbus/prj.conf @@ -3,7 +3,6 @@ CONFIG_LOG=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_SERIAL=y CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_UART_LINE_CTRL=n diff --git a/tests/subsys/modem/backends/tty/prj.conf b/tests/subsys/modem/backends/tty/prj.conf index 16c2f0b73cc..236f7804cf8 100644 --- a/tests/subsys/modem/backends/tty/prj.conf +++ b/tests/subsys/modem/backends/tty/prj.conf @@ -7,6 +7,5 @@ CONFIG_MODEM_MODULES=y CONFIG_MODEM_BACKEND_TTY=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_LOG=y diff --git a/tests/subsys/modem/backends/tty/src/main.c b/tests/subsys/modem/backends/tty/src/main.c index bd9f7494eed..49a1841486a 100644 --- a/tests/subsys/modem/backends/tty/src/main.c +++ b/tests/subsys/modem/backends/tty/src/main.c @@ -122,10 +122,10 @@ static void test_modem_backend_tty_teardown(void *f) /*************************************************************************************************/ ZTEST(modem_backend_tty_suite, test_close_open) { - zassert_true(modem_pipe_close(tty_pipe) == 0, "Failed to close pipe"); - zassert_true(modem_pipe_close(tty_pipe) == -EALREADY, "Pipe should already be closed"); - zassert_true(modem_pipe_open(tty_pipe) == 0, "Failed to open pipe"); - zassert_true(modem_pipe_open(tty_pipe) == -EALREADY, "Pipe should already be open"); + zassert_ok(modem_pipe_close(tty_pipe), "Failed to close pipe"); + zassert_ok(modem_pipe_close(tty_pipe), "Pipe should already be closed"); + zassert_ok(modem_pipe_open(tty_pipe), "Failed to open pipe"); + zassert_ok(modem_pipe_open(tty_pipe), "Pipe should already be open"); } ZTEST(modem_backend_tty_suite, test_receive_ready_event_not_raised) diff --git a/tests/subsys/modem/backends/uart/CMakeLists.txt b/tests/subsys/modem/backends/uart/CMakeLists.txt new file mode 100644 index 00000000000..c5e208dfd74 --- /dev/null +++ b/tests/subsys/modem/backends/uart/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2023 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(modem_backend_uart_test) + +target_sources(app PRIVATE src/main.c) diff --git a/tests/subsys/modem/backends/uart/boards/b_u585i_iot02a.overlay b/tests/subsys/modem/backends/uart/boards/b_u585i_iot02a.overlay new file mode 100644 index 00000000000..30402e6e9d2 --- /dev/null +++ b/tests/subsys/modem/backends/uart/boards/b_u585i_iot02a.overlay @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/* + * The Arduino D0 and D1 must be connected to each other to loopback RX/TX. + */ + +dut: &usart3 { + dmas = <&gpdma1 0 29 STM32_DMA_PERIPH_TX + &gpdma1 1 28 STM32_DMA_PERIPH_RX>; + dma-names = "tx", "rx"; +}; diff --git a/tests/subsys/modem/backends/uart/boards/nrf5340dk_nrf5340_cpuapp.overlay b/tests/subsys/modem/backends/uart/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000..777aebd8d3b --- /dev/null +++ b/tests/subsys/modem/backends/uart/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/* + * Pins P0.4 and P0.5 must be connected to each other to loopback RX/TX. + */ + +&pinctrl { + uart1_default_alt: uart1_default_alt { + group1 { + psels = , + ; + }; + }; + + uart1_sleep_alt: uart1_sleep_alt { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +dut: &uart1 { + compatible = "nordic,nrf-uarte"; + current-speed = <115200>; + status = "okay"; + pinctrl-0 = <&uart1_default_alt>; + pinctrl-1 = <&uart1_sleep_alt>; + pinctrl-names = "default", "sleep"; +}; diff --git a/tests/subsys/modem/backends/uart/prj.conf b/tests/subsys/modem/backends/uart/prj.conf new file mode 100644 index 00000000000..fd93accbb08 --- /dev/null +++ b/tests/subsys/modem/backends/uart/prj.conf @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_MODEM_MODULES=y +CONFIG_MODEM_BACKEND_UART=y +CONFIG_SERIAL=y +CONFIG_ZTEST=y +CONFIG_LOG=y +CONFIG_ZTEST_SHUFFLE=y +CONFIG_ZTEST_SHUFFLE_TEST_REPEAT_COUNT=3 diff --git a/tests/subsys/modem/backends/uart/src/main.c b/tests/subsys/modem/backends/uart/src/main.c new file mode 100644 index 00000000000..dffc203bb21 --- /dev/null +++ b/tests/subsys/modem/backends/uart/src/main.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2023 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * This test suite sets up a modem_backend_uart instance connected to a UART which has its + * RX and TX pins wired together to provide loopback functionality. A large number of bytes + * containing a sequence of pseudo random numbers are then transmitted, received, and validated. + * + * The test suite repeats three times, opening and clsoing the modem_pipe attached to the + * modem_backend_uart instance before and after the tests respectively. + */ + +/*************************************************************************************************/ +/* Dependencies */ +/*************************************************************************************************/ +#include +#include +#include +#include + +#include +#include +#include + +/*************************************************************************************************/ +/* Mock pipe */ +/*************************************************************************************************/ +static const struct device *uart = DEVICE_DT_GET(DT_NODELABEL(dut)); +static struct modem_backend_uart uart_backend; +static struct modem_pipe *pipe; +K_SEM_DEFINE(receive_ready_sem, 0, 1); + +/*************************************************************************************************/ +/* Buffers */ +/*************************************************************************************************/ +static uint8_t backend_receive_buffer[4096]; +static uint8_t backend_transmit_buffer[4096]; +RING_BUF_DECLARE(transmit_ring_buf, 4096); +static uint8_t receive_buffer[4096]; + +/*************************************************************************************************/ +/* Modem pipe callback */ +/*************************************************************************************************/ +static void modem_pipe_callback_handler(struct modem_pipe *pipe, enum modem_pipe_event event, + void *user_data) +{ + switch (event) { + case MODEM_PIPE_EVENT_RECEIVE_READY: + k_sem_give(&receive_ready_sem); + break; + default: + break; + } +} + +/*************************************************************************************************/ +/* Helpers */ +/*************************************************************************************************/ +static uint32_t transmit_prng_state = 1234; +static uint32_t receive_prng_state = 1234; +static uint32_t transmit_size_prng_state; + +static uint8_t transmit_prng_random(void) +{ + transmit_prng_state = ((1103515245 * transmit_prng_state) + 12345) % (1U << 31); + return (uint8_t)(transmit_prng_state & 0xFF); +} + +static uint8_t receive_prng_random(void) +{ + receive_prng_state = ((1103515245 * receive_prng_state) + 12345) % (1U << 31); + return (uint8_t)(receive_prng_state & 0xFF); +} + +static void prng_reset(void) +{ + transmit_prng_state = 1234; + receive_prng_state = 1234; + transmit_size_prng_state = 0; +} + +static void fill_transmit_ring_buf(void) +{ + uint32_t space = ring_buf_space_get(&transmit_ring_buf); + uint8_t data; + + for (uint32_t i = 0; i < space; i++) { + data = transmit_prng_random(); + ring_buf_put(&transmit_ring_buf, &data, 1); + } +} + +static uint32_t transmit_size_prng_random(void) +{ + uint32_t size = 1; + + for (uint8_t i = 0; i < transmit_size_prng_state; i++) { + size = size * 2; + } + + transmit_size_prng_state = transmit_size_prng_state == 11 + ? 0 + : transmit_size_prng_state + 1; + + return size; +} + +static int transmit_prng(uint32_t remaining) +{ + uint8_t *reserved; + uint32_t reserved_size; + uint32_t transmit_size; + int ret; + + fill_transmit_ring_buf(); + reserved_size = ring_buf_get_claim(&transmit_ring_buf, &reserved, UINT32_MAX); + transmit_size = MIN(transmit_size_prng_random(), reserved_size); + transmit_size = MIN(remaining, transmit_size); + ret = modem_pipe_transmit(pipe, reserved, transmit_size); + if (ret < 0) { + return ret; + } + printk("TX: %u,%u\n", transmit_size, (uint32_t)ret); + __ASSERT(ret <= remaining, "Impossible number of bytes sent %u", (uint32_t)ret); + ring_buf_get_finish(&transmit_ring_buf, ret); + return ret; +} + +static int receive_prng(void) +{ + int ret = 0; + + if (k_sem_take(&receive_ready_sem, K_NO_WAIT) == 0) { + ret = modem_pipe_receive(pipe, receive_buffer, sizeof(receive_buffer)); + if (ret < 0) { + return -EFAULT; + } + for (uint32_t i = 0; i < (uint32_t)ret; i++) { + if (receive_prng_random() != receive_buffer[i]) { + return -EFAULT; + } + } + printk("RX: %u\n", (uint32_t)ret); + } + + return ret; +} + +/*************************************************************************************************/ +/* Test setup */ +/*************************************************************************************************/ +static void *test_modem_backend_uart_setup(void) +{ + const struct modem_backend_uart_config config = { + .uart = uart, + .receive_buf = backend_receive_buffer, + .receive_buf_size = 1024, + .transmit_buf = backend_transmit_buffer, + .transmit_buf_size = 1024, + }; + + pipe = modem_backend_uart_init(&uart_backend, &config); + modem_pipe_attach(pipe, modem_pipe_callback_handler, NULL); + return NULL; +} + +static void test_modem_backend_uart_before(void *f) +{ + prng_reset(); + ring_buf_reset(&transmit_ring_buf); + k_sem_reset(&receive_ready_sem); + __ASSERT_NO_MSG(modem_pipe_open(pipe) == 0); +} + +static void test_modem_backend_uart_after(void *f) +{ + __ASSERT_NO_MSG(modem_pipe_close(pipe) == 0); +} + +/*************************************************************************************************/ +/* Tests */ +/*************************************************************************************************/ +ZTEST(modem_backend_uart_suite, test_transmit_receive) +{ + int32_t remaining = 8192; + uint32_t received = 0; + uint32_t transmitted = 0; + int ret; + + while ((remaining != 0) || (received < 8192)) { + ret = transmit_prng(remaining); + zassert(ret > -1, "Failed to transmit data"); + remaining -= (uint32_t)ret; + transmitted += (uint32_t)ret; + printk("TX ACC: %u\n", transmitted); + + while (received < transmitted) { + ret = receive_prng(); + zassert(ret > -1, "Received data is corrupted"); + received += (uint32_t)ret; + k_yield(); + } + } +} + +ZTEST_SUITE(modem_backend_uart_suite, NULL, test_modem_backend_uart_setup, + test_modem_backend_uart_before, test_modem_backend_uart_after, NULL); diff --git a/tests/subsys/modem/backends/uart/testcase.yaml b/tests/subsys/modem/backends/uart/testcase.yaml new file mode 100644 index 00000000000..54d8a6b9470 --- /dev/null +++ b/tests/subsys/modem/backends/uart/testcase.yaml @@ -0,0 +1,19 @@ +# Copyright (c) 2023 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +common: + harness: ztest + harness_config: + fixture: gpio_loopback + platform_allow: + - b_u585i_iot02a + - nrf5340dk_nrf5340_cpuapp + +tests: + modem.backends.uart.async: + extra_configs: + - CONFIG_UART_ASYNC_API=y + + modem.backends.uart.isr: + extra_configs: + - CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/tests/subsys/modem/modem_chat/prj.conf b/tests/subsys/modem/modem_chat/prj.conf index 7937ad4f546..d93100a74c9 100644 --- a/tests/subsys/modem/modem_chat/prj.conf +++ b/tests/subsys/modem/modem_chat/prj.conf @@ -7,4 +7,3 @@ CONFIG_MODEM_MODULES=y CONFIG_MODEM_CHAT=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/modem/modem_chat/src/main.c b/tests/subsys/modem/modem_chat/src/main.c index c078119d241..3f1ef57754d 100644 --- a/tests/subsys/modem/modem_chat/src/main.c +++ b/tests/subsys/modem/modem_chat/src/main.c @@ -42,6 +42,8 @@ static struct modem_pipe *mock_pipe; #define MODEM_CHAT_UTEST_ON_APP_RDY_CALLED_BIT (7) #define MODEM_CHAT_UTEST_ON_NORMAL_POWER_DOWN_CALLED_BIT (8) #define MODEM_CHAT_UTEST_ON_SCRIPT_CALLBACK_BIT (9) +#define MODEM_CHAT_UTEST_ON_CMGL_PARTIAL_CALLED_BIT (10) +#define MODEM_CHAT_UTEST_ON_CMGL_PARTIAL_ANY_CALLED_BIT (11) static atomic_t callback_called; @@ -119,6 +121,19 @@ static void on_normal_power_down(struct modem_chat *cmd, char **argv, uint16_t a clone_args(argv, argc); } +static void on_cmgl_partial(struct modem_chat *cmd, char **argv, uint16_t argc, void *user_data) +{ + atomic_set_bit(&callback_called, MODEM_CHAT_UTEST_ON_CMGL_PARTIAL_CALLED_BIT); + clone_args(argv, argc); +} + +static void on_cmgl_any_partial(struct modem_chat *cmd, char **argv, uint16_t argc, + void *user_data) +{ + atomic_set_bit(&callback_called, MODEM_CHAT_UTEST_ON_CMGL_PARTIAL_ANY_CALLED_BIT); + clone_args(argv, argc); +} + /*************************************************************************************************/ /* Script callback */ /*************************************************************************************************/ @@ -161,6 +176,51 @@ MODEM_CHAT_MATCHES_DEFINE(abort_matches, MODEM_CHAT_MATCH("NO CARRIER", "", on_n MODEM_CHAT_SCRIPT_DEFINE(script, script_cmds, abort_matches, on_script_result, 4); +/*************************************************************************************************/ +/* Script implementing partial matches */ +/*************************************************************************************************/ +MODEM_CHAT_MATCHES_DEFINE( + cmgl_matches, + MODEM_CHAT_MATCH_INITIALIZER("+CMGL: ", ",", on_cmgl_partial, false, true), + MODEM_CHAT_MATCH_INITIALIZER("", "", on_cmgl_any_partial, false, true), + MODEM_CHAT_MATCH_INITIALIZER("OK", "", NULL, false, false) +); + +MODEM_CHAT_SCRIPT_CMDS_DEFINE( + script_partial_cmds, + MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CMGL=4", cmgl_matches), +); + +MODEM_CHAT_SCRIPT_DEFINE(script_partial, script_partial_cmds, abort_matches, on_script_result, 4); + +/*************************************************************************************************/ +/* Small echo script and mock transactions */ +/*************************************************************************************************/ +static const uint8_t at_echo_data[] = {'A', 'T', '\r', '\n'}; +static const struct modem_backend_mock_transaction at_echo_transaction = { + .get = at_echo_data, + .get_size = sizeof(at_echo_data), + .put = at_echo_data, + .put_size = sizeof(at_echo_data), +}; + +static const uint8_t at_echo_error_data[] = {'E', 'R', 'R', 'O', 'R', ' ', '1', '\r', '\n'}; +static const struct modem_backend_mock_transaction at_echo_error_transaction = { + .get = at_echo_data, + .get_size = sizeof(at_echo_data), + .put = at_echo_error_data, + .put_size = sizeof(at_echo_error_data), +}; + +MODEM_CHAT_MATCH_DEFINE(at_match, "AT", "", NULL); + +MODEM_CHAT_SCRIPT_CMDS_DEFINE( + script_echo_cmds, + MODEM_CHAT_SCRIPT_CMD_RESP("AT", at_match), +); + +MODEM_CHAT_SCRIPT_DEFINE(script_echo, script_echo_cmds, abort_matches, on_script_result, 4); + /*************************************************************************************************/ /* Script responses */ /*************************************************************************************************/ @@ -174,6 +234,9 @@ static const char qeng_servinc_cell_response[] = "+QENG: \"servingcell\",\"NOCON ",03,E182,AEAD,52,32,2,-68,255,255,0,38,38,1,," ",,,,,,,,\r\n"; +static const char cmgl_response_0[] = "+CMGL: 1,1,,50\r\n"; +static const char cmgl_response_1[] = "07911326060032F064A9542954\r\n"; + /*************************************************************************************************/ /* Test setup */ /*************************************************************************************************/ @@ -416,6 +479,138 @@ ZTEST(modem_chat, test_start_script_then_time_out) "Script result callback user data is incorrect"); } +ZTEST(modem_chat, test_script_with_partial_matches) +{ + bool called; + + zassert_true(modem_chat_script_run(&cmd, &script_partial) == 0, "Failed to start script"); + k_msleep(100); + + /* + * Script sends "AT+CMGL=4\r"; + */ + + modem_backend_mock_get(&mock, buffer, ARRAY_SIZE(buffer)); + zassert_true(memcmp(buffer, "AT+CMGL=4\r", sizeof("AT+CMGL=4\r") - 1) == 0, + "Request not sent as expected"); + + /* + * Modem will return the following sequence 3 times + * "+CMGL: 1,1,,50\r"; + * "07911326060032F064A9542954\r" + */ + + for (uint8_t i = 0; i < 3; i++) { + atomic_set(&callback_called, 0); + modem_backend_mock_put(&mock, cmgl_response_0, sizeof(cmgl_response_0) - 1); + k_msleep(100); + + called = atomic_test_bit(&callback_called, + MODEM_CHAT_UTEST_ON_CMGL_PARTIAL_CALLED_BIT); + zassert_equal(called, true, "Match callback not called"); + zassert_equal(argc_buffers, 5, "Incorrect number of args"); + zassert_equal(strcmp(argv_buffers[0], "+CMGL: "), 0, "Incorrect argv received"); + zassert_equal(strcmp(argv_buffers[1], "1"), 0, "Incorrect argv received"); + zassert_equal(strcmp(argv_buffers[2], "1"), 0, "Incorrect argv received"); + zassert_equal(strcmp(argv_buffers[3], ""), 0, "Incorrect argv received"); + zassert_equal(strcmp(argv_buffers[4], "50"), 0, "Incorrect argv received"); + + atomic_set(&callback_called, 0); + modem_backend_mock_put(&mock, cmgl_response_1, sizeof(cmgl_response_1) - 1); + k_msleep(100); + + called = atomic_test_bit(&callback_called, + MODEM_CHAT_UTEST_ON_CMGL_PARTIAL_ANY_CALLED_BIT); + zassert_equal(called, true, "Match callback not called"); + zassert_equal(argc_buffers, 2, "Incorrect number of args"); + zassert_equal(strcmp(argv_buffers[0], ""), 0, "Incorrect argv received"); + zassert_equal(strcmp(argv_buffers[1], "07911326060032F064A9542954"), 0, + "Incorrect argv received"); + } + + atomic_set(&callback_called, 0); + modem_backend_mock_put(&mock, ok_response, sizeof(ok_response) - 1); + k_msleep(100); + + /* + * Modem returns "OK\r" + * Script terminates + */ + + called = atomic_test_bit(&callback_called, MODEM_CHAT_UTEST_ON_SCRIPT_CALLBACK_BIT); + zassert_true(called == true, "Script callback should have been called"); + zassert_equal(script_result, MODEM_CHAT_SCRIPT_RESULT_SUCCESS, + "Script should have stopped with success"); + + /* Assert no data was sent except the request */ + zassert_equal(modem_backend_mock_get(&mock, buffer, ARRAY_SIZE(buffer)), 0, + "Script sent too many requests"); +} + +ZTEST(modem_chat, test_script_run_sync_complete) +{ + modem_backend_mock_prime(&mock, &at_echo_transaction); + zassert_ok(modem_chat_run_script(&cmd, &script_echo), "Failed to run echo script"); +} + +ZTEST(modem_chat, test_script_run_sync_timeout) +{ + zassert_equal(modem_chat_run_script(&cmd, &script_echo), -EAGAIN, + "Failed to run echo script"); +} + +ZTEST(modem_chat, test_script_run_sync_abort) +{ + modem_backend_mock_prime(&mock, &at_echo_error_transaction); + zassert_equal(modem_chat_run_script(&cmd, &script_echo), -EAGAIN, + "Echo script should time out and return -EAGAIN"); +} + +ZTEST(modem_chat, test_script_run_dynamic_script_sync) +{ + char match[] = "AT"; + char separators[] = ","; + char request[] = "AT"; + char name[] = "Dynamic"; + + struct modem_chat_match stack_response_match = { + .match = NULL, + .match_size = 0, + .separators = NULL, + .separators_size = 0, + .wildcards = false, + .partial = false, + .callback = NULL, + }; + + struct modem_chat_script_chat stack_script_chat = { + .request = NULL, + .response_matches = &stack_response_match, + .response_matches_size = 1, + .timeout = 0, + }; + + struct modem_chat_script stack_script = { + .name = name, + .script_chats = &stack_script_chat, + .script_chats_size = 1, + .abort_matches = NULL, + .abort_matches_size = 0, + .callback = NULL, + .timeout = 1, + }; + + stack_response_match.match = match; + stack_response_match.match_size = strlen(match); + stack_response_match.separators = separators; + stack_response_match.separators_size = strlen(match); + stack_script_chat.request = request; + stack_script_chat.request_size = strlen(request); + + modem_backend_mock_prime(&mock, &at_echo_transaction); + zassert_ok(modem_chat_run_script(&cmd, &stack_script), "Failed to run script"); +} + /*************************************************************************************************/ /* Test suite */ /*************************************************************************************************/ diff --git a/tests/subsys/modem/modem_cmux/prj.conf b/tests/subsys/modem/modem_cmux/prj.conf index daa8bc7f0ff..905fe8235d6 100644 --- a/tests/subsys/modem/modem_cmux/prj.conf +++ b/tests/subsys/modem/modem_cmux/prj.conf @@ -7,4 +7,3 @@ CONFIG_MODEM_MODULES=y CONFIG_MODEM_CMUX=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/modem/modem_cmux/src/main.c b/tests/subsys/modem/modem_cmux/src/main.c index 13422641b9c..9df6837efc5 100644 --- a/tests/subsys/modem/modem_cmux/src/main.c +++ b/tests/subsys/modem/modem_cmux/src/main.c @@ -100,11 +100,11 @@ static uint8_t cmux_frame_dlci2_sabm_cmd[] = {0xF9, 0x0B, 0x3F, 0x01, 0x59, 0xF9 static uint8_t cmux_frame_dlci2_sabm_ack[] = {0xF9, 0x0B, 0x73, 0x01, 0x92, 0xF9}; static uint8_t cmux_frame_dlci2_disc_cmd[] = {0xF9, 0x0B, 0x53, 0x01, 0xB8, 0xF9}; static uint8_t cmux_frame_dlci2_ua_ack[] = {0xF9, 0x0B, 0x73, 0x01, 0x92, 0xF9}; -static uint8_t cmux_frame_control_msc_cmd[] = {0xF9, 0x01, 0xFF, 0x09, 0xE3, - 0x05, 0x0B, 0x09, 0x8F, 0xF9}; +static uint8_t cmux_frame_control_msc_cmd[] = {0xF9, 0x01, 0xFF, 0x0B, 0xE3, + 0x07, 0x0B, 0x09, 0x01, 0x6C, 0xF9}; -static uint8_t cmux_frame_control_msc_ack[] = {0xF9, 0x01, 0xFF, 0x09, 0xE1, - 0x05, 0x0B, 0x09, 0x8F, 0xF9}; +static uint8_t cmux_frame_control_msc_ack[] = {0xF9, 0x01, 0xFF, 0x0B, 0xE1, + 0x07, 0x0B, 0x09, 0x01, 0x6C, 0xF9}; static uint8_t cmux_frame_control_fcon_cmd[] = {0xF9, 0x01, 0xFF, 0x05, 0xA3, 0x01, 0x86, 0xF9}; static uint8_t cmux_frame_control_fcon_ack[] = {0xF9, 0x01, 0xFF, 0x05, 0xA1, 0x01, 0x86, 0xF9}; @@ -150,10 +150,10 @@ static uint8_t cmux_frame_resync[] = {0xF9, 0xF9, 0xF9}; /* DLCI2 PPP CMUX frames */ /*************************************************************************************************/ static uint8_t cmux_frame_dlci2_ppp_52[] = { - 0xF9, 0x09, 0xEF, 0x69, 0x7E, 0xFF, 0x7D, 0x23, 0xC0, 0x21, 0x7D, 0x21, 0x7D, 0x20, 0x7D, + 0xF9, 0x0B, 0xEF, 0x69, 0x7E, 0xFF, 0x7D, 0x23, 0xC0, 0x21, 0x7D, 0x21, 0x7D, 0x20, 0x7D, 0x20, 0x7D, 0x38, 0x7D, 0x22, 0x7D, 0x26, 0x7D, 0x20, 0x7D, 0x20, 0x7D, 0x20, 0x7D, 0x20, 0x7D, 0x23, 0x7D, 0x24, 0xC0, 0x23, 0x7D, 0x25, 0x7D, 0x26, 0x53, 0x96, 0x7D, 0x38, 0xAA, - 0x7D, 0x27, 0x7D, 0x22, 0x7D, 0x28, 0x7D, 0x22, 0xD5, 0xA8, 0x7E, 0x97, 0xF9}; + 0x7D, 0x27, 0x7D, 0x22, 0x7D, 0x28, 0x7D, 0x22, 0xD5, 0xA8, 0x7E, 0xF6, 0xF9}; static uint8_t cmux_frame_data_dlci2_ppp_52[] = { 0x7E, 0xFF, 0x7D, 0x23, 0xC0, 0x21, 0x7D, 0x21, 0x7D, 0x20, 0x7D, 0x20, 0x7D, @@ -161,9 +161,9 @@ static uint8_t cmux_frame_data_dlci2_ppp_52[] = { 0x7D, 0x23, 0x7D, 0x24, 0xC0, 0x23, 0x7D, 0x25, 0x7D, 0x26, 0x53, 0x96, 0x7D, 0x38, 0xAA, 0x7D, 0x27, 0x7D, 0x22, 0x7D, 0x28, 0x7D, 0x22, 0xD5, 0xA8, 0x7E}; -static uint8_t cmux_frame_dlci2_ppp_18[] = {0xF9, 0x09, 0xEF, 0x25, 0x7E, 0xFF, 0x7D, 0x23, +static uint8_t cmux_frame_dlci2_ppp_18[] = {0xF9, 0x0B, 0xEF, 0x25, 0x7E, 0xFF, 0x7D, 0x23, 0xC0, 0x21, 0x7D, 0x22, 0x7D, 0x21, 0x7D, 0x20, - 0x7D, 0x24, 0x7D, 0x3C, 0x90, 0x7E, 0xEE, 0xF9}; + 0x7D, 0x24, 0x7D, 0x3C, 0x90, 0x7E, 0x8F, 0xF9}; static uint8_t cmux_frame_data_dlci2_ppp_18[] = {0x7E, 0xFF, 0x7D, 0x23, 0xC0, 0x21, 0x7D, 0x22, 0x7D, 0x21, 0x7D, 0x20, @@ -265,32 +265,26 @@ static void *test_modem_cmux_setup(void) }; bus_mock_pipe = modem_backend_mock_init(&bus_mock, &bus_mock_config); - __ASSERT_NO_MSG(modem_pipe_open_async(bus_mock_pipe) == 0); + __ASSERT_NO_MSG(modem_pipe_open(bus_mock_pipe) == 0); /* Connect CMUX */ __ASSERT_NO_MSG(modem_cmux_attach(&cmux, bus_mock_pipe) == 0); + modem_backend_mock_prime(&bus_mock, &transaction_control_sabm); __ASSERT_NO_MSG(modem_cmux_connect_async(&cmux) == 0); - modem_backend_mock_put(&bus_mock, cmux_frame_control_sabm_ack, - sizeof(cmux_frame_control_sabm_ack)); - events = k_event_wait(&cmux_event, EVENT_CMUX_CONNECTED, false, K_MSEC(100)); __ASSERT_NO_MSG(events == EVENT_CMUX_CONNECTED); /* Open DLCI channels */ modem_pipe_attach(dlci1_pipe, test_modem_dlci1_pipe_callback, NULL); - modem_pipe_attach(dlci2_pipe, test_modem_dlci2_pipe_callback, NULL); + modem_backend_mock_prime(&bus_mock, &transaction_dlci1_sabm); __ASSERT_NO_MSG(modem_pipe_open_async(dlci1_pipe) == 0); - __ASSERT_NO_MSG(modem_pipe_open_async(dlci2_pipe) == 0); - modem_backend_mock_put(&bus_mock, cmux_frame_dlci1_sabm_ack, - sizeof(cmux_frame_dlci1_sabm_ack)); - - modem_backend_mock_put(&bus_mock, cmux_frame_dlci2_sabm_ack, - sizeof(cmux_frame_dlci2_sabm_ack)); - - events = k_event_wait_all(&cmux_event, (EVENT_CMUX_DLCI1_OPEN | EVENT_CMUX_DLCI2_OPEN), - false, K_MSEC(100)); - + events = k_event_wait(&cmux_event, EVENT_CMUX_DLCI1_OPEN, false, K_MSEC(100)); __ASSERT_NO_MSG((events & EVENT_CMUX_DLCI1_OPEN)); + + modem_pipe_attach(dlci2_pipe, test_modem_dlci2_pipe_callback, NULL); + modem_backend_mock_prime(&bus_mock, &transaction_dlci2_sabm); + __ASSERT_NO_MSG(modem_pipe_open_async(dlci2_pipe) == 0); + events = k_event_wait(&cmux_event, EVENT_CMUX_DLCI2_OPEN, false, K_MSEC(100)); __ASSERT_NO_MSG((events & EVENT_CMUX_DLCI2_OPEN)); return NULL; diff --git a/tests/subsys/modem/modem_ppp/prj.conf b/tests/subsys/modem/modem_ppp/prj.conf index 4221f36a610..ac0366608dd 100644 --- a/tests/subsys/modem/modem_ppp/prj.conf +++ b/tests/subsys/modem/modem_ppp/prj.conf @@ -10,7 +10,6 @@ CONFIG_NET_L2_PPP=y CONFIG_ETH_NATIVE_POSIX=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_LOG=y CONFIG_LOG_DEFAULT_LEVEL=4 diff --git a/tests/subsys/modem/modem_ppp/src/main.c b/tests/subsys/modem/modem_ppp/src/main.c index ee60385163c..27fe6bf64d5 100644 --- a/tests/subsys/modem/modem_ppp/src/main.c +++ b/tests/subsys/modem/modem_ppp/src/main.c @@ -11,8 +11,8 @@ #include #include #include -#include "zephyr/net/net_l2.h" -#include "zephyr/net/ppp.h" +#include +#include #include #include diff --git a/tests/subsys/openthread/prj.conf b/tests/subsys/openthread/prj.conf index c3fdba67ef0..cee7218f847 100644 --- a/tests/subsys/openthread/prj.conf +++ b/tests/subsys/openthread/prj.conf @@ -1,6 +1,5 @@ CONFIG_SHELL=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_IEEE802154=y CONFIG_NETWORKING=y diff --git a/tests/subsys/openthread/radio_test.c b/tests/subsys/openthread/radio_test.c index 87a7013a0d5..8c7a9fcb79e 100644 --- a/tests/subsys/openthread/radio_test.c +++ b/tests/subsys/openthread/radio_test.c @@ -68,9 +68,6 @@ static struct ieee802154_radio_api rapi = {.get_capabilities = get_capabilities, .start = start_mock, .stop = stop_mock, .configure = configure_mock, -#ifdef CONFIG_NET_L2_IEEE802154_SUB_GHZ - .get_subg_channel_count = NULL, -#endif /* CONFIG_NET_L2_IEEE802154_SUB_GHZ */ .ed_scan = scan_mock}; #define DT_DRV_COMPAT vnd_ieee802154 @@ -126,8 +123,8 @@ static enum ieee802154_hw_caps get_capabilities(const struct device *dev) zassert_equal(dev, radio, "Device handle incorrect."); - caps = IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_TX_RX_ACK | - IEEE802154_HW_FILTER | IEEE802154_HW_ENERGY_SCAN | IEEE802154_HW_SLEEP_TO_TX; + caps = IEEE802154_HW_FCS | IEEE802154_HW_TX_RX_ACK | IEEE802154_HW_FILTER | + IEEE802154_HW_ENERGY_SCAN | IEEE802154_HW_SLEEP_TO_TX; if (IS_ENABLED(CONFIG_NET_PKT_TXTIME)) { caps |= IEEE802154_HW_TXTIME; } @@ -323,8 +320,7 @@ ZTEST(openthread_radio, test_tx_test) zassert_equal(power, set_txpower_mock_fake.arg1_val); zassert_equal(1, tx_mock_fake.call_count); zassert_equal_ptr(frm->mPsdu, tx_mock_fake.arg3_val->data, NULL); - zassert_equal(expected_target_time, - net_ptp_time_to_ns(net_pkt_timestamp(tx_mock_fake.arg2_val))); + zassert_equal(expected_target_time, net_pkt_timestamp_ns(tx_mock_fake.arg2_val)); zassert_equal(IS_ENABLED(CONFIG_NET_PKT_TXTIME) ? IEEE802154_TX_MODE_TXTIME_CCA : IEEE802154_TX_MODE_DIRECT, tx_mock_fake.arg1_val); @@ -542,7 +538,6 @@ ZTEST(openthread_radio, test_promiscuous_mode_set_test) * @brief Test of proper radio to OT capabilities mapping * Tests if different radio capabilities map for their corresponding OpenThread * capability - * */ ZTEST(openthread_radio, test_get_caps_test) { @@ -555,12 +550,6 @@ ZTEST(openthread_radio, test_get_caps_test) /* not used by OT */ get_capabilities_caps_mock_fake.return_val = IEEE802154_HW_FCS; - zassert_equal(otPlatRadioGetCaps(ot), OT_RADIO_CAPS_NONE, - "Incorrect capabilities returned."); - get_capabilities_caps_mock_fake.return_val = IEEE802154_HW_2_4_GHZ; - zassert_equal(otPlatRadioGetCaps(ot), OT_RADIO_CAPS_NONE, - "Incorrect capabilities returned."); - get_capabilities_caps_mock_fake.return_val = IEEE802154_HW_SUB_GHZ; zassert_equal(otPlatRadioGetCaps(ot), OT_RADIO_CAPS_NONE, "Incorrect capabilities returned."); @@ -595,9 +584,8 @@ ZTEST(openthread_radio, test_get_caps_test) /* all at once */ get_capabilities_caps_mock_fake.return_val = IEEE802154_HW_FCS | IEEE802154_HW_PROMISC | IEEE802154_HW_FILTER | - IEEE802154_HW_CSMA | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_TX_RX_ACK | - IEEE802154_HW_SUB_GHZ | IEEE802154_HW_ENERGY_SCAN | IEEE802154_HW_TXTIME | - IEEE802154_HW_SLEEP_TO_TX; + IEEE802154_HW_CSMA | IEEE802154_HW_TX_RX_ACK | IEEE802154_HW_ENERGY_SCAN | + IEEE802154_HW_TXTIME | IEEE802154_HW_SLEEP_TO_TX; zassert_equal( otPlatRadioGetCaps(ot), OT_RADIO_CAPS_CSMA_BACKOFF | OT_RADIO_CAPS_ENERGY_SCAN | OT_RADIO_CAPS_ACK_TIMEOUT | @@ -913,8 +901,8 @@ static int custom_configure_csl_rx_time(const struct device *dev, const struct ieee802154_config *config) { zassert_equal(dev, radio, "Device handle incorrect."); - zassert_equal(type, IEEE802154_CONFIG_CSL_RX_TIME, "Config type incorrect."); - custom_configure_csl_rx_time_mock_csl_rx_time = config->csl_rx_time; + zassert_equal(type, IEEE802154_CONFIG_EXPECTED_RX_TIME, "Config type incorrect."); + custom_configure_csl_rx_time_mock_csl_rx_time = config->expected_rx_time; return 0; } @@ -922,11 +910,13 @@ static int custom_configure_csl_rx_time(const struct device *dev, ZTEST(openthread_radio, test_csl_receiver_sample_time) { uint32_t sample_time = 50U; + uint32_t phr_duration = 32U; configure_mock_fake.custom_fake = custom_configure_csl_rx_time; otPlatRadioUpdateCslSampleTime(NULL, sample_time); zassert_equal(1, configure_mock_fake.call_count); - zassert_equal(sample_time * NSEC_PER_USEC, custom_configure_csl_rx_time_mock_csl_rx_time); + zassert_equal((sample_time - phr_duration) * NSEC_PER_USEC, + custom_configure_csl_rx_time_mock_csl_rx_time); } diff --git a/tests/subsys/pm/device_driver_init/prj.conf b/tests/subsys/pm/device_driver_init/prj.conf index e6d05f591ac..a911722adb1 100644 --- a/tests/subsys/pm/device_driver_init/prj.conf +++ b/tests/subsys/pm/device_driver_init/prj.conf @@ -6,4 +6,3 @@ CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_GPIO=y CONFIG_GPIO_GET_CONFIG=y CONFIG_POWER_DOMAIN=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/pm/device_driver_init/src/main.c b/tests/subsys/pm/device_driver_init/src/main.c index e59b130e182..f423b1d683c 100644 --- a/tests/subsys/pm/device_driver_init/src/main.c +++ b/tests/subsys/pm/device_driver_init/src/main.c @@ -27,7 +27,7 @@ zassert_equal(rc, 0, "Device state retrieval failed"); \ zassert_equal(state, value, "Unexpected device state"); -ZTEST(device_driver_init, test_demo) +ZTEST(device_driver_init, test_device_driver_init) { #if IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME) enum pm_device_state state; diff --git a/tests/subsys/pm/device_driver_init/testcase.yaml b/tests/subsys/pm/device_driver_init/testcase.yaml index e3e35d97841..8920e38741b 100644 --- a/tests/subsys/pm/device_driver_init/testcase.yaml +++ b/tests/subsys/pm/device_driver_init/testcase.yaml @@ -1,16 +1,15 @@ +common: + platform_allow: + - native_posix + tags: + - pm tests: - pm.device_driver_init: - tags: pm - platform_allow: qemu_cortex_m3 + pm.device_driver_init: {} pm.device_driver_init.pm: - tags: pm - platform_allow: qemu_cortex_m3 extra_configs: - CONFIG_PM_DEVICE=y - CONFIG_PM_DEVICE_POWER_DOMAIN=y pm.device_driver_init.pm_device_runtime: - tags: pm - platform_allow: qemu_cortex_m3 extra_configs: - CONFIG_PM_DEVICE=y - CONFIG_PM_DEVICE_POWER_DOMAIN=y diff --git a/tests/subsys/pm/device_power_domains/prj.conf b/tests/subsys/pm/device_power_domains/prj.conf index 967291a394d..e003169ea99 100644 --- a/tests/subsys/pm/device_power_domains/prj.conf +++ b/tests/subsys/pm/device_power_domains/prj.conf @@ -9,4 +9,3 @@ CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_GPIO=y CONFIG_POWER_DOMAIN=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/pm/device_power_domains/src/main.c b/tests/subsys/pm/device_power_domains/src/main.c index 50726bcef19..6123a8a5f54 100644 --- a/tests/subsys/pm/device_power_domains/src/main.c +++ b/tests/subsys/pm/device_power_domains/src/main.c @@ -29,7 +29,7 @@ PM_DEVICE_DT_DEFINE(DT_NODELABEL(test_dev), dev_pm_control); DEVICE_DT_DEFINE(DT_NODELABEL(test_dev), dev_init, PM_DEVICE_DT_GET(DT_NODELABEL(test_dev)), NULL, NULL, POST_KERNEL, 80, NULL); -ZTEST(device_power_domain, test_demo) +ZTEST(device_power_domain, test_device_power_domain) { const struct device *const reg_0 = DEVICE_DT_GET(DT_NODELABEL(test_reg_0)); const struct device *const reg_1 = DEVICE_DT_GET(DT_NODELABEL(test_reg_1)); diff --git a/tests/subsys/pm/device_power_domains/testcase.yaml b/tests/subsys/pm/device_power_domains/testcase.yaml index cc661ae8561..11b00299f5c 100644 --- a/tests/subsys/pm/device_power_domains/testcase.yaml +++ b/tests/subsys/pm/device_power_domains/testcase.yaml @@ -1,4 +1,6 @@ tests: pm.power_domain.device: - tags: pm - platform_allow: qemu_cortex_m3 + tags: + - pm + platform_allow: + - native_posix diff --git a/tests/subsys/pm/device_runtime_api/prj.conf b/tests/subsys/pm/device_runtime_api/prj.conf index 99fb0f9e62e..5708c297e9d 100644 --- a/tests/subsys/pm/device_runtime_api/prj.conf +++ b/tests/subsys/pm/device_runtime_api/prj.conf @@ -3,4 +3,3 @@ CONFIG_PM=y CONFIG_PM_DEVICE=y CONFIG_PM_DEVICE_RUNTIME=y CONFIG_MP_MAX_NUM_CPUS=1 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/pm/device_runtime_api/src/main.c b/tests/subsys/pm/device_runtime_api/src/main.c index acda0aa822f..57fd7d8bcc8 100644 --- a/tests/subsys/pm/device_runtime_api/src/main.c +++ b/tests/subsys/pm/device_runtime_api/src/main.c @@ -218,7 +218,7 @@ ZTEST(device_runtime_api, test_api) } DEVICE_DEFINE(pm_unsupported_device, "PM Unsupported", NULL, NULL, NULL, NULL, - APPLICATION, 0, NULL); + POST_KERNEL, 0, NULL); ZTEST(device_runtime_api, test_unsupported) { diff --git a/tests/subsys/pm/device_wakeup_api/prj.conf b/tests/subsys/pm/device_wakeup_api/prj.conf index 15d773b235b..edd5b915dd8 100644 --- a/tests/subsys/pm/device_wakeup_api/prj.conf +++ b/tests/subsys/pm/device_wakeup_api/prj.conf @@ -4,4 +4,3 @@ CONFIG_PM=y CONFIG_PM_POLICY_CUSTOM=y CONFIG_GPIO=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/pm/policy_api/prj.conf b/tests/subsys/pm/policy_api/prj.conf index 7cf9b06a2c2..cf84b4d2dd4 100644 --- a/tests/subsys/pm/policy_api/prj.conf +++ b/tests/subsys/pm/policy_api/prj.conf @@ -3,4 +3,3 @@ CONFIG_ZTEST=y CONFIG_PM=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/pm/power_domain/prj.conf b/tests/subsys/pm/power_domain/prj.conf index a6880b99dfc..06b480e7ecb 100644 --- a/tests/subsys/pm/power_domain/prj.conf +++ b/tests/subsys/pm/power_domain/prj.conf @@ -7,4 +7,3 @@ CONFIG_POWER_DOMAIN=y CONFIG_PM_DEVICE_POWER_DOMAIN_DYNAMIC=y CONFIG_PM_DEVICE_RUNTIME=y CONFIG_MP_MAX_NUM_CPUS=1 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/pm/power_domain/src/main.c b/tests/subsys/pm/power_domain/src/main.c index 0f9f44e5837..5088d1b37bf 100644 --- a/tests/subsys/pm/power_domain/src/main.c +++ b/tests/subsys/pm/power_domain/src/main.c @@ -105,8 +105,7 @@ DEVICE_DT_DEFINE(TEST_DEVB, NULL, PM_DEVICE_DT_GET(TEST_DEVB), PM_DEVICE_DEFINE(devc, deva_pm_action); DEVICE_DEFINE(devc, "devc", NULL, PM_DEVICE_GET(devc), - NULL, NULL, - APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, NULL); + NULL, NULL, POST_KERNEL, 40, NULL); /** * @brief Test the power domain behavior @@ -280,5 +279,23 @@ ZTEST(power_domain_1cpu, test_power_domain_device_balanced) zassert_equal(state, PM_DEVICE_STATE_ACTIVE); } +ZTEST(power_domain_1cpu, test_on_power_domain) +{ + zassert_true(device_is_ready(domain), "Device is not ready!"); + zassert_true(device_is_ready(deva), "Device is not ready!"); + devc = DEVICE_GET(devc); + zassert_true(device_is_ready(devc), "Device is not ready!"); + + pm_device_power_domain_remove(deva, domain); + zassert_false(pm_device_on_power_domain(deva), "deva is in the power domain."); + pm_device_power_domain_add(deva, domain); + zassert_true(pm_device_on_power_domain(deva), "deva is not in the power domain."); + + pm_device_power_domain_add(devc, domain); + zassert_true(pm_device_on_power_domain(devc), "devc is not in the power domain."); + pm_device_power_domain_remove(devc, domain); + zassert_false(pm_device_on_power_domain(devc), "devc in in the power domain."); +} + ZTEST_SUITE(power_domain_1cpu, NULL, NULL, ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL); diff --git a/tests/subsys/pm/power_mgmt/prj.conf b/tests/subsys/pm/power_mgmt/prj.conf index 3dbc21b5b56..81edc8f7e26 100644 --- a/tests/subsys/pm/power_mgmt/prj.conf +++ b/tests/subsys/pm/power_mgmt/prj.conf @@ -5,4 +5,3 @@ CONFIG_PM_DEVICE_RUNTIME=y CONFIG_PM_POLICY_CUSTOM=y CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE=n -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/pm/power_mgmt/src/dummy_driver.c b/tests/subsys/pm/power_mgmt/src/dummy_driver.c index f33722c30a1..81a053ce1d3 100644 --- a/tests/subsys/pm/power_mgmt/src/dummy_driver.c +++ b/tests/subsys/pm/power_mgmt/src/dummy_driver.c @@ -39,5 +39,5 @@ int dummy_init(const struct device *dev) PM_DEVICE_DEFINE(dummy_driver, dummy_device_pm_action); DEVICE_DEFINE(dummy_driver, DUMMY_DRIVER_NAME, &dummy_init, - PM_DEVICE_GET(dummy_driver), NULL, NULL, APPLICATION, + PM_DEVICE_GET(dummy_driver), NULL, NULL, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &funcs); diff --git a/tests/subsys/pm/power_mgmt_multicore/prj.conf b/tests/subsys/pm/power_mgmt_multicore/prj.conf index 6a259c68bbe..f0b806ca389 100644 --- a/tests/subsys/pm/power_mgmt_multicore/prj.conf +++ b/tests/subsys/pm/power_mgmt_multicore/prj.conf @@ -2,4 +2,3 @@ CONFIG_ZTEST=y CONFIG_PM=y CONFIG_PM_POLICY_CUSTOM=y CONFIG_MP_MAX_NUM_CPUS=2 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/pm/power_mgmt_soc/boards/nucleo_f429zi.overlay b/tests/subsys/pm/power_mgmt_soc/boards/nucleo_f429zi.overlay new file mode 100644 index 00000000000..859c69df414 --- /dev/null +++ b/tests/subsys/pm/power_mgmt_soc/boards/nucleo_f429zi.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + zephyr,cortex-m-idle-timer = &rtc; + }; +}; diff --git a/tests/subsys/pm/power_mgmt_soc/prj.conf b/tests/subsys/pm/power_mgmt_soc/prj.conf index 278c555ad07..bb30385a3df 100644 --- a/tests/subsys/pm/power_mgmt_soc/prj.conf +++ b/tests/subsys/pm/power_mgmt_soc/prj.conf @@ -5,4 +5,3 @@ CONFIG_THREAD_NAME=y CONFIG_STATS=y CONFIG_PM_STATS=y CONFIG_IDLE_STACK_SIZE=640 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/pm/power_mgmt_soc/testcase.yaml b/tests/subsys/pm/power_mgmt_soc/testcase.yaml index 5d160d70b91..8fe974f0bfa 100644 --- a/tests/subsys/pm/power_mgmt_soc/testcase.yaml +++ b/tests/subsys/pm/power_mgmt_soc/testcase.yaml @@ -5,6 +5,7 @@ tests: - cc1352r1_launchxl - mec15xxevb_assy6853 - mec1501modular_assy6885 + - nucleo_f429zi - nucleo_wb55rg - nucleo_l476rg - twr_ke18f diff --git a/tests/subsys/pm/power_states_api/Kconfig b/tests/subsys/pm/power_states_api/Kconfig new file mode 100644 index 00000000000..71c7b510f4d --- /dev/null +++ b/tests/subsys/pm/power_states_api/Kconfig @@ -0,0 +1,11 @@ +# Copyright (c) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +menu "Zephyr" +source "Kconfig.zephyr" +endmenu + +config TEST_PROVIDE_PM_HOOKS + bool "Provide PM hooks for test purposes" + default y + select HAS_PM diff --git a/tests/subsys/pm/power_states_api/prj.conf b/tests/subsys/pm/power_states_api/prj.conf index 9228251051e..e623494111a 100644 --- a/tests/subsys/pm/power_states_api/prj.conf +++ b/tests/subsys/pm/power_states_api/prj.conf @@ -1,2 +1,2 @@ +CONFIG_PM=y CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/pm/power_states_api/src/main.c b/tests/subsys/pm/power_states_api/src/main.c index a7e76117815..3699bc0d3ff 100644 --- a/tests/subsys/pm/power_states_api/src/main.c +++ b/tests/subsys/pm/power_states_api/src/main.c @@ -18,8 +18,24 @@ static enum pm_state states[] = {PM_STATE_SUSPEND_TO_IDLE, static enum pm_state wrong_states[] = {PM_STATE_SUSPEND_TO_DISK, PM_STATE_SUSPEND_TO_RAM, PM_STATE_SUSPEND_TO_RAM}; +void pm_state_set(enum pm_state state, uint8_t substate_id) +{ + ARG_UNUSED(substate_id); + ARG_UNUSED(state); +} + +void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) +{ + ARG_UNUSED(state); + ARG_UNUSED(substate_id); + + irq_unlock(0); +} + ZTEST(power_states_1cpu, test_power_states) { + uint8_t ret; + const struct pm_state_info *cpu_states; enum pm_state dts_states[] = PM_STATE_LIST_FROM_DT_CPU(DT_NODELABEL(cpu0)); struct pm_state_info dts_infos[] = @@ -36,6 +52,15 @@ ZTEST(power_states_1cpu, test_power_states) zassert_false(memcmp(wrong_states, dts_states, sizeof(dts_states)) == 0, "Invalid pm-states array"); + + ret = pm_state_cpu_get_all(CONFIG_MP_MAX_NUM_CPUS + 1, &cpu_states); + zassert_true(ret == 0, "Invalid pm_state_cpu_get_all return"); + + ret = pm_state_cpu_get_all(0U, &cpu_states); + zassert_true(ret == dts_states_len, + "Invalid number of pm states"); + zassert_true(memcmp(cpu_states, dts_infos, sizeof(dts_infos)) == 0, + "Invalid pm_state_info array"); } ZTEST_SUITE(power_states_1cpu, NULL, NULL, ztest_simple_1cpu_before, diff --git a/tests/subsys/portability/cmsis_rtos_v1/prj.conf b/tests/subsys/portability/cmsis_rtos_v1/prj.conf index 4a0cb1c2a20..f08e6d07ca4 100644 --- a/tests/subsys/portability/cmsis_rtos_v1/prj.conf +++ b/tests/subsys/portability/cmsis_rtos_v1/prj.conf @@ -7,4 +7,3 @@ CONFIG_IRQ_OFFLOAD=y CONFIG_CMSIS_THREAD_MAX_STACK_SIZE=2048 CONFIG_SMP=n CONFIG_THREAD_STACK_INFO=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/portability/cmsis_rtos_v2/prj.conf b/tests/subsys/portability/cmsis_rtos_v2/prj.conf index 8df8cf48aba..282d8c4ebcd 100644 --- a/tests/subsys/portability/cmsis_rtos_v2/prj.conf +++ b/tests/subsys/portability/cmsis_rtos_v2/prj.conf @@ -17,4 +17,3 @@ CONFIG_TIMEOUT_64BIT=n CONFIG_CMSIS_V2_THREAD_MAX_STACK_SIZE=1024 CONFIG_CMSIS_V2_THREAD_DYNAMIC_STACK_SIZE=1024 CONFIG_MP_MAX_NUM_CPUS=1 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/rtio/rtio_api/prj.conf b/tests/subsys/rtio/rtio_api/prj.conf index babe8800f3a..b19c123d100 100644 --- a/tests/subsys/rtio/rtio_api/prj.conf +++ b/tests/subsys/rtio/rtio_api/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_LOG=y CONFIG_RTIO=y CONFIG_RTIO_SYS_MEM_BLOCKS=y diff --git a/tests/subsys/rtio/rtio_api/src/test_rtio_mpsc.c b/tests/subsys/rtio/rtio_api/src/test_rtio_mpsc.c index 705170798c8..a656c119b9e 100644 --- a/tests/subsys/rtio/rtio_api/src/test_rtio_mpsc.c +++ b/tests/subsys/rtio/rtio_api/src/test_rtio_mpsc.c @@ -102,6 +102,10 @@ static struct rtio_mpsc mpsc_q; static void mpsc_consumer(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct rtio_mpsc_node *n; struct mpsc_node *nn; @@ -124,6 +128,10 @@ static void mpsc_consumer(void *p1, void *p2, void *p3) static void mpsc_producer(void *p1, void *p2, void *p3) { + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct mpsc_node *n; uint32_t id = (uint32_t)(uintptr_t)p1; @@ -163,7 +171,7 @@ ZTEST(rtio_mpsc, test_mpsc_threaded) TC_PRINT("starting consumer\n"); mpsc_tinfo[0].tid = k_thread_create(&mpsc_thread[0], mpsc_stack[0], MPSC_STACK_SIZE, - (k_thread_entry_t)mpsc_consumer, + mpsc_consumer, NULL, NULL, NULL, K_PRIO_PREEMPT(5), K_INHERIT_PERMS, K_NO_WAIT); @@ -172,7 +180,7 @@ ZTEST(rtio_mpsc, test_mpsc_threaded) TC_PRINT("starting producer %i\n", i); mpsc_tinfo[i].tid = k_thread_create(&mpsc_thread[i], mpsc_stack[i], MPSC_STACK_SIZE, - (k_thread_entry_t)mpsc_producer, + mpsc_producer, (void *)(uintptr_t)i, NULL, NULL, K_PRIO_PREEMPT(5), K_INHERIT_PERMS, K_NO_WAIT); diff --git a/tests/subsys/rtio/rtio_api/src/test_rtio_spsc.c b/tests/subsys/rtio/rtio_api/src/test_rtio_spsc.c index a161b9fab07..12fe9476f3f 100644 --- a/tests/subsys/rtio/rtio_api/src/test_rtio_spsc.c +++ b/tests/subsys/rtio/rtio_api/src/test_rtio_spsc.c @@ -141,6 +141,9 @@ RTIO_SPSC_DEFINE(spsc, uint32_t, 4); static void t1_consume(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct rtio_spsc_spsc *ezspsc = p1; uint32_t retries = 0; uint32_t *val = NULL; @@ -162,6 +165,9 @@ static void t1_consume(void *p1, void *p2, void *p3) static void t2_produce(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + struct rtio_spsc_spsc *ezspsc = p1; uint32_t retries = 0; uint32_t *val = NULL; @@ -201,13 +207,13 @@ ZTEST(rtio_spsc, test_spsc_threaded) tinfo[0].tid = k_thread_create(&tthread[0], tstack[0], STACK_SIZE, - (k_thread_entry_t)t1_consume, + t1_consume, &spsc, NULL, NULL, K_PRIO_PREEMPT(5), K_INHERIT_PERMS, K_NO_WAIT); tinfo[1].tid = k_thread_create(&tthread[1], tstack[1], STACK_SIZE, - (k_thread_entry_t)t2_produce, + t2_produce, &spsc, NULL, NULL, K_PRIO_PREEMPT(5), K_INHERIT_PERMS, K_NO_WAIT); diff --git a/tests/subsys/rtio/rtio_api/testcase.yaml b/tests/subsys/rtio/rtio_api/testcase.yaml index 7f9f7b9028f..2eb29026efa 100644 --- a/tests/subsys/rtio/rtio_api/testcase.yaml +++ b/tests/subsys/rtio/rtio_api/testcase.yaml @@ -20,6 +20,8 @@ tests: filter: CONFIG_ARCH_HAS_USERSPACE extra_configs: - CONFIG_USERSPACE=y + arch_exclude: + - posix tags: - rtio - userspace @@ -30,6 +32,8 @@ tests: extra_configs: - CONFIG_USERSPACE=y - CONFIG_RTIO_SUBMIT_SEM=y + arch_exclude: + - posix tags: - rtio - userspace diff --git a/tests/subsys/sd/mmc/prj.conf b/tests/subsys/sd/mmc/prj.conf index 9f06d497b52..fbd9f184dbf 100644 --- a/tests/subsys/sd/mmc/prj.conf +++ b/tests/subsys/sd/mmc/prj.conf @@ -2,4 +2,3 @@ CONFIG_TEST=y CONFIG_ZTEST=y CONFIG_MMC_STACK=y CONFIG_LOG=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/sd/sdio/CMakeLists.txt b/tests/subsys/sd/sdio/CMakeLists.txt new file mode 100644 index 00000000000..1a5c25efd91 --- /dev/null +++ b/tests/subsys/sd/sdio/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(sdmmc_subsys_test) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/subsys/sd/sdio/README.txt b/tests/subsys/sd/sdio/README.txt new file mode 100644 index 00000000000..f037480c4e7 --- /dev/null +++ b/tests/subsys/sd/sdio/README.txt @@ -0,0 +1,18 @@ +SDIO Subsystem Test +################## + +This test is designed to verify the SD subsystem stack implementation for SDIO +devices. Note that this test will only perform basic reads from the SDIO card +after initialization, as most registers present on the card will be vendor +specific. It requires an SDIO card be connected to the board to pass. +The test has the following phases: + +* Init test: verify the SD host controller can detect card presence, and + test the initialization flow of the SDIO subsystem to verify that the stack + can correctly initialize an SDIO card. + +* Read test: verify that a read from the SDIO common card register area returns + valid data. + +* Configuration test: verify that the SD stack reports a valid configuration + for this card after initialization. diff --git a/tests/subsys/sd/sdio/prj.conf b/tests/subsys/sd/sdio/prj.conf new file mode 100644 index 00000000000..7c1034503df --- /dev/null +++ b/tests/subsys/sd/sdio/prj.conf @@ -0,0 +1,5 @@ +CONFIG_TEST=y +CONFIG_ZTEST=y +CONFIG_SDHC=y +CONFIG_SDIO_STACK=y +CONFIG_LOG=y diff --git a/tests/subsys/sd/sdio/src/main.c b/tests/subsys/sd/sdio/src/main.c new file mode 100644 index 00000000000..ad311904b4e --- /dev/null +++ b/tests/subsys/sd/sdio/src/main.c @@ -0,0 +1,114 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + + +static const struct device *sdhc_dev = DEVICE_DT_GET(DT_ALIAS(sdhc0)); +static struct sd_card card; + +/* + * Verify that SD stack can initialize an SDIO card. + * This test must run first, to ensure the card is initialized. + */ +ZTEST(sd_stack, test_0_init) +{ + int ret; + + zassert_true(device_is_ready(sdhc_dev), "SDHC device is not ready"); + + ret = sd_is_card_present(sdhc_dev); + zassert_equal(ret, 1, "SD card not present in slot"); + + ret = sd_init(sdhc_dev, &card); + zassert_equal(ret, 0, "Card initialization failed"); +} + +/* + * Verify that a register read works. Given the custom nature of SDIO devices, + * we just read from the card common I/O area. + */ +ZTEST(sd_stack, test_read) +{ + int ret; + uint8_t reg = 0xFF; + + /* Read from card common I/O area. */ + ret = sdio_read_byte(&card.func0, SDIO_CCCR_CCCR, ®); + zassert_equal(ret, 0, "SD card read failed"); + /* Check to make sure CCCR read actually returned valid data */ + zassert_not_equal(reg, 0xFF, "CCCR read returned invalid data"); +} + +/* Simply dump the card configuration. */ +ZTEST(sd_stack, test_card_config) +{ + switch (card.card_voltage) { + case SD_VOL_1_2_V: + TC_PRINT("Card voltage: 1.2V\n"); + break; + case SD_VOL_1_8_V: + TC_PRINT("Card voltage: 1.8V\n"); + break; + case SD_VOL_3_0_V: + TC_PRINT("Card voltage: 3.0V\n"); + break; + case SD_VOL_3_3_V: + TC_PRINT("Card voltage: 3.3V\n"); + break; + default: + zassert_unreachable("Card voltage is not known value"); + } + zassert_equal(card.status, CARD_INITIALIZED, "Card status is not OK"); + switch (card.card_speed) { + case SD_TIMING_SDR12: + TC_PRINT("Card timing: SDR12\n"); + break; + case SD_TIMING_SDR25: + TC_PRINT("Card timing: SDR25\n"); + break; + case SD_TIMING_SDR50: + TC_PRINT("Card timing: SDR50\n"); + break; + case SD_TIMING_SDR104: + TC_PRINT("Card timing: SDR104\n"); + break; + case SD_TIMING_DDR50: + TC_PRINT("Card timing: DDR50\n"); + break; + default: + zassert_unreachable("Card timing is not known value"); + } + switch (card.type) { + case CARD_SDIO: + TC_PRINT("Card type: SDIO\n"); + break; + case CARD_SDMMC: + TC_PRINT("Card type: SDMMC\n"); + break; + case CARD_COMBO: + TC_PRINT("Card type: combo card\n"); + break; + default: + zassert_unreachable("Card type is not known value"); + } + if (card.sd_version >= SD_SPEC_VER3_0) { + TC_PRINT("Card spec: 3.0\n"); + } else if (card.sd_version >= SD_SPEC_VER2_0) { + TC_PRINT("Card spec: 2.0\n"); + } else if (card.sd_version >= SD_SPEC_VER1_1) { + TC_PRINT("Card spec: 1.1\n"); + } else if (card.sd_version >= SD_SPEC_VER1_0) { + TC_PRINT("Card spec: 1.0\n"); + } else { + zassert_unreachable("Card spec is unknown value"); + } +} + +ZTEST_SUITE(sd_stack, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/subsys/sd/sdio/testcase.yaml b/tests/subsys/sd/sdio/testcase.yaml new file mode 100644 index 00000000000..a19e17dab4c --- /dev/null +++ b/tests/subsys/sd/sdio/testcase.yaml @@ -0,0 +1,13 @@ +common: + depends_on: sdhc + tags: drivers sdhc +tests: + sd.sdio: + harness: ztest + harness_config: + fixture: fixture_sdhc + filter: dt_alias_exists("sdhc0") + tags: sdhc + min_ram: 32 + integration_platforms: + - mimxrt1064_evk diff --git a/tests/subsys/sd/sdmmc/prj.conf b/tests/subsys/sd/sdmmc/prj.conf index 186a5632a62..b5c81cd5aaf 100644 --- a/tests/subsys/sd/sdmmc/prj.conf +++ b/tests/subsys/sd/sdmmc/prj.conf @@ -2,4 +2,3 @@ CONFIG_TEST=y CONFIG_ZTEST=y CONFIG_SDMMC_STACK=y CONFIG_LOG=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/settings/fcb/prj.conf b/tests/subsys/settings/fcb/prj.conf index 67d8855910e..c0091de22ed 100644 --- a/tests/subsys/settings/fcb/prj.conf +++ b/tests/subsys/settings/fcb/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=2048 CONFIG_FLASH=y diff --git a/tests/subsys/settings/fcb/testcase.yaml b/tests/subsys/settings/fcb/testcase.yaml index 15d286e565d..dd000db1c09 100644 --- a/tests/subsys/settings/fcb/testcase.yaml +++ b/tests/subsys/settings/fcb/testcase.yaml @@ -1,5 +1,5 @@ tests: - system.settings.fcb.raw: + settings.fcb.raw: platform_allow: - nrf52840dk_nrf52840 - nrf52dk_nrf52832 @@ -9,4 +9,6 @@ tests: integration_platforms: - nrf52840dk_nrf52840 - native_posix - tags: settings_fcb + tags: + - settings + - fcb diff --git a/tests/subsys/settings/fcb_init/prj.conf b/tests/subsys/settings/fcb_init/prj.conf index 68c33bdc68c..46c1ab88ff3 100644 --- a/tests/subsys/settings/fcb_init/prj.conf +++ b/tests/subsys/settings/fcb_init/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_FLASH=y CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_FLASH_MAP=y diff --git a/tests/subsys/settings/fcb_init/testcase.yaml b/tests/subsys/settings/fcb_init/testcase.yaml index 5db96cf101b..fd0d0209c71 100644 --- a/tests/subsys/settings/fcb_init/testcase.yaml +++ b/tests/subsys/settings/fcb_init/testcase.yaml @@ -1,8 +1,10 @@ tests: - system.settings.fcb: + settings.fcb: platform_allow: - nrf52840dk_nrf52840 - nrf52dk_nrf52832 integration_platforms: - nrf52840dk_nrf52840 - tags: settings_intialization_fcb + tags: + - settings + - fcb diff --git a/tests/subsys/settings/file/prj.conf b/tests/subsys/settings/file/prj.conf index 425f48aaf6b..07e79b3233e 100644 --- a/tests/subsys/settings/file/prj.conf +++ b/tests/subsys/settings/file/prj.conf @@ -2,7 +2,6 @@ # Copyright (c) 2019 Nordic Semiconductor ASA CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_FLASH=y CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_FLASH_MAP=y diff --git a/tests/subsys/settings/file/testcase.yaml b/tests/subsys/settings/file/testcase.yaml index 2d1e2635873..68add10790b 100644 --- a/tests/subsys/settings/file/testcase.yaml +++ b/tests/subsys/settings/file/testcase.yaml @@ -2,12 +2,13 @@ # Copyright (c) 2019 Nordic Semiconductor ASA tests: - system.settings.file.raw: + settings.file.raw: platform_allow: - nrf52840dk_nrf52840 - native_posix - native_posix_64 - mr_canhubk3 tags: - - settings_file - - settings_file_littlefs + - settings + - file + - littlefs diff --git a/tests/subsys/settings/functional/fcb/prj.conf b/tests/subsys/settings/functional/fcb/prj.conf index f6a8bd83ff5..795a225d7fd 100644 --- a/tests/subsys/settings/functional/fcb/prj.conf +++ b/tests/subsys/settings/functional/fcb/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_FLASH=y CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_FLASH_MAP=y diff --git a/tests/subsys/settings/functional/fcb/testcase.yaml b/tests/subsys/settings/functional/fcb/testcase.yaml index 5d02f3c701b..fb484e210b1 100644 --- a/tests/subsys/settings/functional/fcb/testcase.yaml +++ b/tests/subsys/settings/functional/fcb/testcase.yaml @@ -1,5 +1,5 @@ tests: - system.settings.functional.fcb: + settings.functional.fcb: platform_allow: - nrf52840dk_nrf52840 - nrf52dk_nrf52832 @@ -8,8 +8,10 @@ tests: - mr_canhubk3 integration_platforms: - nrf52840dk_nrf52840 - tags: settings_fcb - system.settings.functional.fcb.chosen: + tags: + - settings + - fcb + settings.functional.fcb.chosen: extra_args: DTC_OVERLAY_FILE=./chosen.overlay platform_allow: - native_posix @@ -17,4 +19,6 @@ tests: - mr_canhubk3 integration_platforms: - native_posix - tags: settings_fcb + tags: + - settings + - fcb diff --git a/tests/subsys/settings/functional/file/prj.conf b/tests/subsys/settings/functional/file/prj.conf index ed4862e065d..fe506f01d99 100644 --- a/tests/subsys/settings/functional/file/prj.conf +++ b/tests/subsys/settings/functional/file/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_STACK_SIZE=2048 CONFIG_FLASH=y diff --git a/tests/subsys/settings/functional/file/testcase.yaml b/tests/subsys/settings/functional/file/testcase.yaml index 49c3e4c32af..7a28a2f41bc 100644 --- a/tests/subsys/settings/functional/file/testcase.yaml +++ b/tests/subsys/settings/functional/file/testcase.yaml @@ -1,5 +1,5 @@ tests: - system.settings.file: + settings.file: platform_allow: - nrf52840dk_nrf52840 - nrf52dk_nrf52832 @@ -8,4 +8,6 @@ tests: - mr_canhubk3 integration_platforms: - native_posix - tags: settings_file + tags: + - settings + - file diff --git a/tests/subsys/settings/functional/nvs/prj.conf b/tests/subsys/settings/functional/nvs/prj.conf index 75036ef6953..2466686f555 100644 --- a/tests/subsys/settings/functional/nvs/prj.conf +++ b/tests/subsys/settings/functional/nvs/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_FLASH=y CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_FLASH_MAP=y diff --git a/tests/subsys/settings/functional/nvs/testcase.yaml b/tests/subsys/settings/functional/nvs/testcase.yaml index 94ec6ffa082..6f2be71a86f 100644 --- a/tests/subsys/settings/functional/nvs/testcase.yaml +++ b/tests/subsys/settings/functional/nvs/testcase.yaml @@ -1,21 +1,27 @@ tests: - system.settings.functional.nvs: + settings.functional.nvs: platform_allow: - qemu_x86 - native_posix - native_posix_64 - tags: settings_nvs - system.settings.functional.nvs.chosen: + tags: + - settings + - nvs + settings.functional.nvs.chosen: extra_args: DTC_OVERLAY_FILE=./chosen.overlay platform_allow: - native_posix - native_posix_64 - tags: settings_nvs - system.settings.functional.nvs.dk: + tags: + - settings + - nvs + settings.functional.nvs.dk: extra_args: OVERLAY_CONFIG=mpu.conf platform_allow: - nrf52840dk_nrf52840 - nrf52dk_nrf52832 integration_platforms: - nrf52840dk_nrf52840 - tags: settings_nvs + tags: + - settings + - nvs diff --git a/tests/subsys/settings/nvs/prj.conf b/tests/subsys/settings/nvs/prj.conf index 75036ef6953..2466686f555 100644 --- a/tests/subsys/settings/nvs/prj.conf +++ b/tests/subsys/settings/nvs/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_FLASH=y CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_FLASH_MAP=y diff --git a/tests/subsys/settings/nvs/testcase.yaml b/tests/subsys/settings/nvs/testcase.yaml index fa1673a8307..c78bd712826 100644 --- a/tests/subsys/settings/nvs/testcase.yaml +++ b/tests/subsys/settings/nvs/testcase.yaml @@ -1,5 +1,7 @@ tests: - system.settings.nvs: + settings.nvs: depends_on: nvs min_ram: 32 - tags: settings_nvs + tags: + - settings + - nvs diff --git a/tests/subsys/shell/shell/prj.conf b/tests/subsys/shell/shell/prj.conf index e6e92e28185..e254a3bc4ca 100644 --- a/tests/subsys/shell/shell/prj.conf +++ b/tests/subsys/shell/shell/prj.conf @@ -8,4 +8,3 @@ CONFIG_SHELL_METAKEYS=n CONFIG_LOG=n CONFIG_ZTEST=y CONFIG_TEST_LOGGING_DEFAULTS=n -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/shell/shell/shell_min.conf b/tests/subsys/shell/shell/shell_min.conf index 2fa40eb9ee0..8b5c618e02c 100644 --- a/tests/subsys/shell/shell/shell_min.conf +++ b/tests/subsys/shell/shell/shell_min.conf @@ -12,4 +12,3 @@ CONFIG_LOG=n CONFIG_THREAD_MONITOR=n CONFIG_INIT_STACKS=y CONFIG_BOOT_BANNER=n -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/shell/shell/shell_min_cmds.conf b/tests/subsys/shell/shell/shell_min_cmds.conf index da3364238ad..351b6fb4e60 100644 --- a/tests/subsys/shell/shell/shell_min_cmds.conf +++ b/tests/subsys/shell/shell/shell_min_cmds.conf @@ -6,7 +6,6 @@ CONFIG_SHELL_BACKEND_DUMMY=y CONFIG_SHELL_BACKEND_SERIAL=n CONFIG_THREAD_NAME=y CONFIG_SHELL_STACK_SIZE=2048 -CONFIG_ZTEST_NEW_API=y #using CBPRINTF_NANO decreases significantly Flash usage. CONFIG_CBPRINTF_NANO=y diff --git a/tests/subsys/shell/shell/shell_min_cmds_all.conf b/tests/subsys/shell/shell/shell_min_cmds_all.conf index 957320695ad..f81b9abd6f0 100644 --- a/tests/subsys/shell/shell/shell_min_cmds_all.conf +++ b/tests/subsys/shell/shell/shell_min_cmds_all.conf @@ -1,6 +1,5 @@ CONFIG_ZTEST=y CONFIG_TEST_LOGGING_DEFAULTS=n -CONFIG_ZTEST_NEW_API=y CONFIG_SHELL=y CONFIG_SHELL_MINIMAL=y diff --git a/tests/subsys/shell/shell/shell_min_cmds_resize.conf b/tests/subsys/shell/shell/shell_min_cmds_resize.conf index 35e1fc3086f..2ab8fdbe521 100644 --- a/tests/subsys/shell/shell/shell_min_cmds_resize.conf +++ b/tests/subsys/shell/shell/shell_min_cmds_resize.conf @@ -1,6 +1,5 @@ CONFIG_ZTEST=y CONFIG_TEST_LOGGING_DEFAULTS=n -CONFIG_ZTEST_NEW_API=y CONFIG_SHELL=y CONFIG_SHELL_MINIMAL=y diff --git a/tests/subsys/shell/shell/shell_min_cmds_select.conf b/tests/subsys/shell/shell/shell_min_cmds_select.conf index 71a7e8e36d6..ae4f9b5ea7a 100644 --- a/tests/subsys/shell/shell/shell_min_cmds_select.conf +++ b/tests/subsys/shell/shell/shell_min_cmds_select.conf @@ -1,6 +1,5 @@ CONFIG_ZTEST=y CONFIG_TEST_LOGGING_DEFAULTS=n -CONFIG_ZTEST_NEW_API=y CONFIG_SHELL=y CONFIG_SHELL_MINIMAL=y diff --git a/tests/subsys/shell/shell/shell_min_colors.conf b/tests/subsys/shell/shell/shell_min_colors.conf index 8b0777f7c09..3281032781f 100644 --- a/tests/subsys/shell/shell/shell_min_colors.conf +++ b/tests/subsys/shell/shell/shell_min_colors.conf @@ -1,6 +1,5 @@ CONFIG_ZTEST=y CONFIG_TEST_LOGGING_DEFAULTS=n -CONFIG_ZTEST_NEW_API=y CONFIG_SHELL=y CONFIG_SHELL_MINIMAL=y diff --git a/tests/subsys/shell/shell/shell_min_help.conf b/tests/subsys/shell/shell/shell_min_help.conf index 345755a08fc..1e10b709b34 100644 --- a/tests/subsys/shell/shell/shell_min_help.conf +++ b/tests/subsys/shell/shell/shell_min_help.conf @@ -1,6 +1,5 @@ CONFIG_ZTEST=y CONFIG_TEST_LOGGING_DEFAULTS=n -CONFIG_ZTEST_NEW_API=y CONFIG_SHELL=y CONFIG_SHELL_MINIMAL=y diff --git a/tests/subsys/shell/shell/shell_min_help_all.conf b/tests/subsys/shell/shell/shell_min_help_all.conf index d67faeecf40..d2c1802e263 100644 --- a/tests/subsys/shell/shell/shell_min_help_all.conf +++ b/tests/subsys/shell/shell/shell_min_help_all.conf @@ -1,6 +1,5 @@ CONFIG_ZTEST=y CONFIG_TEST_LOGGING_DEFAULTS=n -CONFIG_ZTEST_NEW_API=y CONFIG_SHELL=y CONFIG_SHELL_MINIMAL=y diff --git a/tests/subsys/shell/shell/shell_min_history.conf b/tests/subsys/shell/shell/shell_min_history.conf index 46e6b188b7e..03ad3188414 100644 --- a/tests/subsys/shell/shell/shell_min_history.conf +++ b/tests/subsys/shell/shell/shell_min_history.conf @@ -1,6 +1,5 @@ CONFIG_ZTEST=y CONFIG_TEST_LOGGING_DEFAULTS=n -CONFIG_ZTEST_NEW_API=y CONFIG_SHELL=y CONFIG_SHELL_MINIMAL=y diff --git a/tests/subsys/shell/shell/shell_min_log_backend.conf b/tests/subsys/shell/shell/shell_min_log_backend.conf index 918085c37b7..2dfaac9a9dc 100644 --- a/tests/subsys/shell/shell/shell_min_log_backend.conf +++ b/tests/subsys/shell/shell/shell_min_log_backend.conf @@ -1,6 +1,5 @@ CONFIG_ZTEST=y CONFIG_TEST_LOGGING_DEFAULTS=n -CONFIG_ZTEST_NEW_API=y CONFIG_SHELL=y CONFIG_SHELL_MINIMAL=y diff --git a/tests/subsys/shell/shell/shell_min_metakeys.conf b/tests/subsys/shell/shell/shell_min_metakeys.conf index 3eb36ab96be..5141e01d971 100644 --- a/tests/subsys/shell/shell/shell_min_metakeys.conf +++ b/tests/subsys/shell/shell/shell_min_metakeys.conf @@ -1,6 +1,5 @@ CONFIG_ZTEST=y CONFIG_TEST_LOGGING_DEFAULTS=n -CONFIG_ZTEST_NEW_API=y CONFIG_SHELL=y CONFIG_SHELL_MINIMAL=y diff --git a/tests/subsys/shell/shell/shell_min_tab.conf b/tests/subsys/shell/shell/shell_min_tab.conf index 8a459f0e2d7..b265e191869 100644 --- a/tests/subsys/shell/shell/shell_min_tab.conf +++ b/tests/subsys/shell/shell/shell_min_tab.conf @@ -1,6 +1,5 @@ CONFIG_ZTEST=y CONFIG_TEST_LOGGING_DEFAULTS=n -CONFIG_ZTEST_NEW_API=y CONFIG_SHELL=y CONFIG_SHELL_MINIMAL=y diff --git a/tests/subsys/shell/shell/shell_min_tab_auto.conf b/tests/subsys/shell/shell/shell_min_tab_auto.conf index 90d731fcb56..4bac7c7b6fa 100644 --- a/tests/subsys/shell/shell/shell_min_tab_auto.conf +++ b/tests/subsys/shell/shell/shell_min_tab_auto.conf @@ -1,6 +1,5 @@ CONFIG_ZTEST=y CONFIG_TEST_LOGGING_DEFAULTS=n -CONFIG_ZTEST_NEW_API=y CONFIG_SHELL=y CONFIG_SHELL_MINIMAL=y diff --git a/tests/subsys/shell/shell/shell_min_wildcards.conf b/tests/subsys/shell/shell/shell_min_wildcards.conf index 29352b41671..e3fb21bd726 100644 --- a/tests/subsys/shell/shell/shell_min_wildcards.conf +++ b/tests/subsys/shell/shell/shell_min_wildcards.conf @@ -1,6 +1,5 @@ CONFIG_ZTEST=y CONFIG_TEST_LOGGING_DEFAULTS=n -CONFIG_ZTEST_NEW_API=y CONFIG_SHELL=y CONFIG_SHELL_MINIMAL=y diff --git a/tests/subsys/shell/shell_backend/CMakeLists.txt b/tests/subsys/shell/shell_backend/CMakeLists.txt new file mode 100644 index 00000000000..a8fae2b9931 --- /dev/null +++ b/tests/subsys/shell/shell_backend/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(shell) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/subsys/shell/shell_backend/prj.conf b/tests/subsys/shell/shell_backend/prj.conf new file mode 100644 index 00000000000..ccaddfdeb1e --- /dev/null +++ b/tests/subsys/shell/shell_backend/prj.conf @@ -0,0 +1,8 @@ +CONFIG_SHELL=y +CONFIG_SHELL_BACKEND_DUMMY=y +CONFIG_SHELL_BACKEND_SERIAL=y +CONFIG_SHELL_CMD_BUFF_SIZE=90 +CONFIG_SHELL_PRINTF_BUFF_SIZE=15 +CONFIG_SHELL_METAKEYS=n +CONFIG_LOG=n +CONFIG_ZTEST=y diff --git a/tests/subsys/shell/shell_backend/src/shell_backend_test.c b/tests/subsys/shell/shell_backend/src/shell_backend_test.c new file mode 100644 index 00000000000..935c0902088 --- /dev/null +++ b/tests/subsys/shell/shell_backend/src/shell_backend_test.c @@ -0,0 +1,41 @@ +/* + * Copyright 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include +#include + +ZTEST(shell_backend, test_backend_apis) +{ + const struct shell *sh_dummy = shell_backend_get_by_name("shell_dummy"); + const struct shell *sh_uart = shell_backend_get_by_name("shell_uart"); + + zassert_equal(shell_backend_count_get(), 2, "Expecting 2, got %d", + shell_backend_count_get()); + + zassert_equal_ptr(sh_dummy, shell_backend_dummy_get_ptr(), + "Unexpected shell_dummy backend"); + zassert_equal_ptr(sh_uart, shell_backend_uart_get_ptr(), "Unexpected shell_uart backend"); + zassert_equal_ptr(shell_backend_get_by_name("blah"), NULL, "Should be NULL if not found"); + + zassert_equal_ptr(shell_backend_get(0), sh_dummy < sh_uart ? sh_dummy : sh_uart, + "Unexpected backend at index 0"); + zassert_equal_ptr(shell_backend_get(1), sh_dummy < sh_uart ? sh_uart : sh_dummy, + "Unexpected backend at index 1"); +} + +static void *shell_setup(void) +{ + /* Let the shell backend initialize. */ + k_usleep(10); + return NULL; +} + +ZTEST_SUITE(shell_backend, NULL, shell_setup, NULL, NULL, NULL); diff --git a/tests/subsys/shell/shell_backend/testcase.yaml b/tests/subsys/shell/shell_backend/testcase.yaml new file mode 100644 index 00000000000..eb9e9d2a314 --- /dev/null +++ b/tests/subsys/shell/shell_backend/testcase.yaml @@ -0,0 +1,10 @@ +tests: + shell.backend: + min_flash: 64 + min_ram: 32 + tags: + - shell + filter: ( CONFIG_SHELL ) + platform_allow: + - qemu_x86 + - qemu_riscv32 diff --git a/tests/subsys/shell/shell_flash/prj.conf b/tests/subsys/shell/shell_flash/prj.conf index 5d68b90f48a..c78ce7b6143 100644 --- a/tests/subsys/shell/shell_flash/prj.conf +++ b/tests/subsys/shell/shell_flash/prj.conf @@ -9,4 +9,3 @@ CONFIG_SHELL_PRINTF_BUFF_SIZE=15 CONFIG_SHELL_METAKEYS=n CONFIG_LOG=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/shell/shell_history/prj.conf b/tests/subsys/shell/shell_history/prj.conf index 79a361c4dc9..dd6a985d9bc 100644 --- a/tests/subsys/shell/shell_history/prj.conf +++ b/tests/subsys/shell/shell_history/prj.conf @@ -7,4 +7,3 @@ CONFIG_SHELL_METAKEYS=n CONFIG_SHELL_HISTORY=y CONFIG_LOG=n CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/sip_svc/CMakeLists.txt b/tests/subsys/sip_svc/CMakeLists.txt new file mode 100644 index 00000000000..a24518d44a8 --- /dev/null +++ b/tests/subsys/sip_svc/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2023, Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(integration) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/subsys/sip_svc/Kconfig b/tests/subsys/sip_svc/Kconfig new file mode 100644 index 00000000000..bb6e047a801 --- /dev/null +++ b/tests/subsys/sip_svc/Kconfig @@ -0,0 +1,20 @@ +# Private config options for sip svc stress test app + +# Copyright (c) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +mainmenu "Intel Agilex SiP SVC stress test" + +config PACKETS_PER_ITERATION + int + default 3 + help + Number of SYNC and ASYNC packets to be sent per iteration + +config ITERATIONS + int + default 7 + help + Number of iterations to be performed. + +source "Kconfig.zephyr" diff --git a/tests/subsys/sip_svc/boards/intel_socfpga_agilex5_socdk.overlay b/tests/subsys/sip_svc/boards/intel_socfpga_agilex5_socdk.overlay new file mode 100644 index 00000000000..0598c9b1de4 --- /dev/null +++ b/tests/subsys/sip_svc/boards/intel_socfpga_agilex5_socdk.overlay @@ -0,0 +1,11 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (C) 2023, Intel Corporation + * + */ + +&sip_smc { + status = "okay"; + zephyr,num-clients = <16>; +}; diff --git a/tests/subsys/sip_svc/boards/intel_socfpga_agilex_socdk.overlay b/tests/subsys/sip_svc/boards/intel_socfpga_agilex_socdk.overlay new file mode 100644 index 00000000000..0598c9b1de4 --- /dev/null +++ b/tests/subsys/sip_svc/boards/intel_socfpga_agilex_socdk.overlay @@ -0,0 +1,11 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (C) 2023, Intel Corporation + * + */ + +&sip_smc { + status = "okay"; + zephyr,num-clients = <16>; +}; diff --git a/tests/subsys/sip_svc/prj.conf b/tests/subsys/sip_svc/prj.conf new file mode 100644 index 00000000000..323ada791c3 --- /dev/null +++ b/tests/subsys/sip_svc/prj.conf @@ -0,0 +1,13 @@ +CONFIG_ZTEST=y +CONFIG_ZTRESS=y +CONFIG_ZTRESS_MAX_THREADS=16 +CONFIG_NUM_PREEMPT_PRIORITIES=18 +CONFIG_ZTRESS_REPORT_PROGRESS_MS=0 + +# SiP SVC Service +CONFIG_ARM_SIP_SVC_DRIVER=y +CONFIG_ARM_SIP_SVC_SUBSYS=y +CONFIG_ARM_SIP_SVC_SUBSYS_SINGLY_OPEN=y + +# Misc +CONFIG_HEAP_MEM_POOL_SIZE=16384 diff --git a/tests/subsys/sip_svc/src/main.c b/tests/subsys/sip_svc/src/main.c new file mode 100644 index 00000000000..49efc28028e --- /dev/null +++ b/tests/subsys/sip_svc/src/main.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2023, Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +ZTEST_SUITE(sip_svc_tests, NULL, NULL, NULL, NULL, NULL); + +#define SVC_METHOD "smc" +#define ECHO_CMD (0x01U) +#define TEST_VAL (0xDEADBEEFU) + +#define SIP_SVC_CLIENT_INSTANCES CONFIG_ZTRESS_MAX_THREADS + +struct private_data { + uint64_t time_start; + uint64_t time_end; + struct k_sem semaphore; +}; + +struct total_time { + uint64_t sync_time; + uint64_t async_time; +}; + +static void get_sync_callback(uint32_t c_token, struct sip_svc_response *response) +{ + if (response == NULL) { + return; + } + + struct private_data *priv = (struct private_data *)response->priv_data; + + priv->time_end = k_cycle_get_64(); + printk("sip_svc version in TFA is %2ld.%02ld\n", response->a2, response->a3); + + k_sem_give(&(priv->semaphore)); +} + +/** + * @brief send SYNC request + * + * @param token sip_svc token + */ +static void sip_svc_send_sync_request(uint32_t token) +{ + int err, trans_id; + void *ctrl; + uint64_t t = 0; + struct total_time *tot_time; + struct private_data priv; + struct sip_svc_request req = {0}; + + ctrl = sip_svc_get_controller(SVC_METHOD); + __ASSERT(ctrl != NULL, "couldn't get the controller"); + + tot_time = (struct total_time *)sip_svc_get_priv_data(ctrl, token); + __ASSERT(tot_time != NULL, "tot_time should not be NULL"); + + err = sip_svc_open(ctrl, token, K_FOREVER); + __ASSERT(err == 0, "couldn't open channel"); + + k_sem_init(&(priv.semaphore), 0, 1); + + req.header = SIP_SVC_PROTO_HEADER(SIP_SVC_PROTO_CMD_SYNC, 0); + req.a0 = SMC_FUNC_ID_GET_SVC_VERSION; + req.priv_data = (void *)&priv; + + priv.time_start = k_cycle_get_64(); + trans_id = sip_svc_send(ctrl, token, &req, get_sync_callback); + __ASSERT(trans_id >= 0, "error in sending request"); + + err = k_sem_take(&(priv.semaphore), K_FOREVER); + __ASSERT(err == 0, "Error in taking semaphore"); + + t = k_cyc_to_us_ceil64(priv.time_end - priv.time_start); + tot_time->sync_time += t; + + printk("In %s got SYNC response for id 0x%02x and time taken is %lldus\n", + k_thread_name_get(k_current_get()), trans_id, t); + + err = sip_svc_close(ctrl, token, NULL); + __ASSERT(err == 0, "error in closing channel"); +} + +static void get_async_callback(uint32_t c_token, struct sip_svc_response *response) +{ + if (response == NULL) { + return; + } + + struct private_data *priv = (struct private_data *)response->priv_data; + + priv->time_end = k_cycle_get_64(); + uint32_t *resp_data = (uint32_t *)response->resp_data_addr; + uint32_t resp_len = response->resp_data_size / sizeof(uint32_t); + + if (resp_data && resp_len) { + __ASSERT((resp_data[1] == TEST_VAL), "SDM response is not matching"); + } + + k_sem_give(&(priv->semaphore)); + k_free(resp_data); +} + +/** + * @brief send ASYNC request + * + * @param token sip_svc token + */ +static void sip_svc_send_async_request(uint32_t token) +{ + int err, trans_id; + /* size of mailbox command buffer, here we require 2 words */ + uint32_t cmd_size = (2 * sizeof(uint32_t)); + /* size of mailbox response buffer, here we require 2 words */ + uint32_t resp_size = (2 * sizeof(uint32_t)); + uint64_t t = 0; + uint32_t *cmd_addr, *resp_addr; + void *ctrl; + struct total_time *tot_time; + struct private_data priv; + struct sip_svc_request req = {0}; + + ctrl = sip_svc_get_controller(SVC_METHOD); + __ASSERT(ctrl != NULL, "couldn't get the controller"); + + err = sip_svc_open(ctrl, token, K_FOREVER); + __ASSERT(err == 0, "couldn't open channel"); + + tot_time = (struct total_time *)sip_svc_get_priv_data(ctrl, token); + __ASSERT(tot_time != NULL, "tot_time should not be NULL"); + + resp_addr = (uint32_t *)k_malloc(resp_size); + __ASSERT(resp_addr != NULL, "couldn' get memory"); + + k_sem_init(&(priv.semaphore), 0, 1); + + cmd_addr = (uint32_t *)k_malloc(cmd_size); + __ASSERT(cmd_addr != NULL, "couldn't get memory"); + + cmd_addr[0] = (1 << 12) | ECHO_CMD; + cmd_addr[1] = 0xDEADBEEF; + + req.header = SIP_SVC_PROTO_HEADER(SIP_SVC_PROTO_CMD_ASYNC, 0); + req.a0 = SMC_FUNC_ID_MAILBOX_SEND_COMMAND; + req.a2 = (uint64_t)cmd_addr; + req.a3 = (uint64_t)cmd_size; + req.resp_data_addr = (uint64_t)resp_addr; + req.resp_data_size = (uint64_t)resp_size; + req.priv_data = (void *)&priv; + + priv.time_start = k_cycle_get_64(); + trans_id = sip_svc_send(ctrl, token, &req, get_async_callback); + __ASSERT(trans_id >= 0, "error in sending request"); + + err = k_sem_take(&(priv.semaphore), K_FOREVER); + __ASSERT(err == 0, "Error in taking semaphore"); + + t = k_cyc_to_us_ceil64(priv.time_end - priv.time_start); + tot_time->async_time += t; + + printk("In %s got ASYNC response for id 0x%02x and time taken is %lldus\n", + k_thread_name_get(k_current_get()), trans_id, t); + + err = sip_svc_close(ctrl, token, NULL); + __ASSERT(err == 0, "error in closing channel"); +} + +static bool sip_svc_register_and_send(void *user_data, uint32_t cnt, bool last, int prio) +{ + int err, token; + void *ctrl; + + printk("\nIn %s and count is %d\n", k_thread_name_get(k_current_get()), cnt); + + ctrl = sip_svc_get_controller(SVC_METHOD); + if (ctrl == NULL) { + return false; + } + + token = sip_svc_register(ctrl, user_data); + if (token == SIP_SVC_ID_INVALID) { + return false; + } + + for (uint32_t i = 0; i < CONFIG_PACKETS_PER_ITERATION; i++) { + sip_svc_send_sync_request(token); + sip_svc_send_async_request(token); + } + + err = sip_svc_unregister(ctrl, token); + if (err < 0) { + return false; + } + + return true; +} + +ZTEST(sip_svc_tests, test_sip_stress) +{ + struct total_time t[SIP_SVC_CLIENT_INSTANCES] = {0}; + struct total_time average = {0}; + + ZTRESS_EXECUTE(ZTRESS_THREAD(sip_svc_register_and_send, &t[0], CONFIG_ITERATIONS, 0, + Z_TIMEOUT_TICKS(10)), + ZTRESS_THREAD(sip_svc_register_and_send, &t[1], CONFIG_ITERATIONS, 0, + Z_TIMEOUT_TICKS(10)), + ZTRESS_THREAD(sip_svc_register_and_send, &t[2], CONFIG_ITERATIONS, 0, + Z_TIMEOUT_TICKS(10)), + ZTRESS_THREAD(sip_svc_register_and_send, &t[3], CONFIG_ITERATIONS, 0, + Z_TIMEOUT_TICKS(10)), + ZTRESS_THREAD(sip_svc_register_and_send, &t[4], CONFIG_ITERATIONS, 0, + Z_TIMEOUT_TICKS(10)), + ZTRESS_THREAD(sip_svc_register_and_send, &t[5], CONFIG_ITERATIONS, 0, + Z_TIMEOUT_TICKS(10)), + ZTRESS_THREAD(sip_svc_register_and_send, &t[6], CONFIG_ITERATIONS, 0, + Z_TIMEOUT_TICKS(10)), + ZTRESS_THREAD(sip_svc_register_and_send, &t[7], CONFIG_ITERATIONS, 0, + Z_TIMEOUT_TICKS(10)), + ZTRESS_THREAD(sip_svc_register_and_send, &t[8], CONFIG_ITERATIONS, 0, + Z_TIMEOUT_TICKS(10)), + ZTRESS_THREAD(sip_svc_register_and_send, &t[9], CONFIG_ITERATIONS, 0, + Z_TIMEOUT_TICKS(10)), + ZTRESS_THREAD(sip_svc_register_and_send, &t[10], CONFIG_ITERATIONS, 0, + Z_TIMEOUT_TICKS(10)), + ZTRESS_THREAD(sip_svc_register_and_send, &t[11], CONFIG_ITERATIONS, 0, + Z_TIMEOUT_TICKS(10)), + ZTRESS_THREAD(sip_svc_register_and_send, &t[12], CONFIG_ITERATIONS, 0, + Z_TIMEOUT_TICKS(10)), + ZTRESS_THREAD(sip_svc_register_and_send, &t[13], CONFIG_ITERATIONS, 0, + Z_TIMEOUT_TICKS(10)), + ZTRESS_THREAD(sip_svc_register_and_send, &t[14], CONFIG_ITERATIONS, 0, + Z_TIMEOUT_TICKS(10)), + ZTRESS_THREAD(sip_svc_register_and_send, &t[15], CONFIG_ITERATIONS, 0, + Z_TIMEOUT_TICKS(10))); + + for (uint32_t i = 0; i < SIP_SVC_CLIENT_INSTANCES; i++) { + average.sync_time += t[i].sync_time; + average.async_time += t[i].async_time; + } + + average.sync_time = average.sync_time / (CONFIG_ITERATIONS * CONFIG_PACKETS_PER_ITERATION * + SIP_SVC_CLIENT_INSTANCES); + average.async_time = + average.async_time / + (CONFIG_ITERATIONS * CONFIG_PACKETS_PER_ITERATION * SIP_SVC_CLIENT_INSTANCES); + + printk("\n***************************************\n"); + printk("Average SYNC transaction time is %lldus\n", average.sync_time); + printk("Average ASYNC transaction time is %lldus\n", average.async_time); + printk("\n***************************************\n"); +} diff --git a/tests/subsys/sip_svc/testcase.yaml b/tests/subsys/sip_svc/testcase.yaml new file mode 100644 index 00000000000..3cd6a496b29 --- /dev/null +++ b/tests/subsys/sip_svc/testcase.yaml @@ -0,0 +1,11 @@ +# Copyright (c) 2022-2023, Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +tests: + sip_svc.stress_test.ztest: + build_only: true + platform_allow: intel_socfpga_agilex_socdk intel_socfpga_agilex5_socdk + integration_platforms: + - intel_socfpga_agilex_socdk + - intel_socfpga_agilex5_socdk + tags: sip_svc diff --git a/tests/subsys/storage/flash_map/prj.conf b/tests/subsys/storage/flash_map/prj.conf index f69cc81cd7a..fb9e5a0fd26 100644 --- a/tests/subsys/storage/flash_map/prj.conf +++ b/tests/subsys/storage/flash_map/prj.conf @@ -3,4 +3,3 @@ CONFIG_FLASH=y CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_FLASH_MAP=y CONFIG_FLASH_AREA_CHECK_INTEGRITY=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/storage/stream/stream_flash/prj.conf b/tests/subsys/storage/stream/stream_flash/prj.conf index 46737eefa75..6e5811b8fdc 100644 --- a/tests/subsys/storage/stream/stream_flash/prj.conf +++ b/tests/subsys/storage/stream/stream_flash/prj.conf @@ -14,4 +14,3 @@ CONFIG_SETTINGS=y CONFIG_STREAM_FLASH=y CONFIG_STREAM_FLASH_ERASE=y CONFIG_STREAM_FLASH_PROGRESS=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/testsuite/fff_fake_contexts/prj.conf b/tests/subsys/testsuite/fff_fake_contexts/prj.conf index b79d06d0c64..2dea28a5282 100644 --- a/tests/subsys/testsuite/fff_fake_contexts/prj.conf +++ b/tests/subsys/testsuite/fff_fake_contexts/prj.conf @@ -2,4 +2,3 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/tracing/tracing_api/prj.conf b/tests/subsys/tracing/tracing_api/prj.conf index cbdf717f9b9..af5be66675f 100644 --- a/tests/subsys/tracing/tracing_api/prj.conf +++ b/tests/subsys/tracing/tracing_api/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TRACING=y CONFIG_TRACING_TEST=y CONFIG_TRACING_BACKEND_UART=y diff --git a/tests/subsys/usb/bos/prj.conf b/tests/subsys/usb/bos/prj.conf index 41f0df927f0..147852c73ea 100644 --- a/tests/subsys/usb/bos/prj.conf +++ b/tests/subsys/usb/bos/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y CONFIG_USB_DEVICE_STACK=y CONFIG_USB_DEVICE_BOS=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/usb/desc_sections/prj.conf b/tests/subsys/usb/desc_sections/prj.conf index a7265e4f03c..07dbb1512d0 100644 --- a/tests/subsys/usb/desc_sections/prj.conf +++ b/tests/subsys/usb/desc_sections/prj.conf @@ -4,4 +4,3 @@ CONFIG_USB_DEVICE_LOG_LEVEL_DBG=y CONFIG_LOG=y CONFIG_LOG_BUFFER_SIZE=4096 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/usb/device/prj.conf b/tests/subsys/usb/device/prj.conf index f40596f6d9f..26a6935756d 100644 --- a/tests/subsys/usb/device/prj.conf +++ b/tests/subsys/usb/device/prj.conf @@ -5,4 +5,3 @@ CONFIG_USB_DEVICE_LOG_LEVEL_DBG=y CONFIG_USB_DRIVER_LOG_LEVEL_DBG=y CONFIG_USB_DEVICE_STACK=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/usb/device_next/CMakeLists.txt b/tests/subsys/usb/device_next/CMakeLists.txt new file mode 100644 index 00000000000..b9e9a6b4ea3 --- /dev/null +++ b/tests/subsys/usb/device_next/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(test_usb_device_next) + +target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/usb/host) + +target_sources(app PRIVATE src/main.c) diff --git a/tests/subsys/usb/device_next/boards/native_posix.overlay b/tests/subsys/usb/device_next/boards/native_posix.overlay new file mode 100644 index 00000000000..d352f555c8c --- /dev/null +++ b/tests/subsys/usb/device_next/boards/native_posix.overlay @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/delete-node/ &zephyr_udc0; + +/ { + zephyr_uhc0: uhc_vrt0 { + compatible = "zephyr,uhc-virtual"; + + zephyr_udc0: udc_vrt0 { + compatible = "zephyr,udc-virtual"; + num-bidir-endpoints = <8>; + maximum-speed = "high-speed"; + }; + }; +}; diff --git a/tests/subsys/usb/device_next/boards/qemu_cortex_m3.overlay b/tests/subsys/usb/device_next/boards/qemu_cortex_m3.overlay new file mode 100644 index 00000000000..4dd05c0fe99 --- /dev/null +++ b/tests/subsys/usb/device_next/boards/qemu_cortex_m3.overlay @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + zephyr_uhc0: uhc_vrt0 { + compatible = "zephyr,uhc-virtual"; + + zephyr_udc0: udc_vrt0 { + compatible = "zephyr,udc-virtual"; + num-bidir-endpoints = <8>; + maximum-speed = "high-speed"; + }; + }; +}; diff --git a/tests/subsys/usb/device_next/prj.conf b/tests/subsys/usb/device_next/prj.conf new file mode 100644 index 00000000000..54321edc952 --- /dev/null +++ b/tests/subsys/usb/device_next/prj.conf @@ -0,0 +1,11 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_LOG=y +CONFIG_ZTEST=y + +CONFIG_USB_DEVICE_STACK_NEXT=y +CONFIG_USBD_LOOPBACK_CLASS=y + +CONFIG_UHC_DRIVER=y +CONFIG_USB_HOST_STACK=y diff --git a/tests/subsys/usb/device_next/src/main.c b/tests/subsys/usb/device_next/src/main.c new file mode 100644 index 00000000000..50c20c2fbf3 --- /dev/null +++ b/tests/subsys/usb/device_next/src/main.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "usbh_ch9.h" +#include "usbh_device.h" + +#include +LOG_MODULE_REGISTER(usb_test, LOG_LEVEL_INF); + +#define TEST_DEFAULT_INTERFACE 0 +#define TEST_DEFAULT_ALTERNATE 1 + +USBD_CONFIGURATION_DEFINE(test_config, + USB_SCD_SELF_POWERED | USB_SCD_REMOTE_WAKEUP, + 200); + +USBD_DESC_LANG_DEFINE(test_lang); +USBD_DESC_STRING_DEFINE(test_mfg, "ZEPHYR", 1); +USBD_DESC_STRING_DEFINE(test_product, "Zephyr USB Test", 2); +USBD_DESC_STRING_DEFINE(test_sn, "0123456789ABCDEF", 3); + +USBD_DEVICE_DEFINE(test_usbd, + DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0)), + 0x2fe3, 0xffff); + +USBH_CONTROLLER_DEFINE(uhs_ctx, DEVICE_DT_GET(DT_NODELABEL(zephyr_uhc0))); + +/* Get Configuration request test */ +ZTEST(device_next, test_get_configuration) +{ + struct usb_device *udev; + uint8_t cfg = 0; + int err; + + udev = usbh_device_get_any(&uhs_ctx); + err = usbh_req_get_cfg(udev, &cfg); + + switch (udev->state) { + case USB_STATE_DEFAULT: + /* Not specified, expect protocol error */ + zassert_equal(err, -EPIPE, "Transfer status is not a protocol error"); + break; + case USB_STATE_ADDRESSED: + /* TODO: Expect zero value */ + zassert_equal(err, 0, "Transfer status is an error"); + zassert_equal(cfg, 0, "Device not in address state"); + break; + case USB_STATE_CONFIGURED: + /* TODO: Expect non-zero valid configuration value */ + zassert_equal(err, 0, "Transfer status is an error"); + zassert_not_equal(cfg, 0, "Device not in configured state"); + break; + default: + break; + } +} + +/* Set Interface request test */ +ZTEST(device_next, test_set_interface) +{ + struct usb_device *udev; + int err; + + udev = usbh_device_get_any(&uhs_ctx); + err = usbh_req_set_alt(udev, TEST_DEFAULT_INTERFACE, + TEST_DEFAULT_ALTERNATE); + + switch (udev->state) { + case USB_STATE_DEFAULT: + /* Not specified, expect protocol error */ + case USB_STATE_ADDRESSED: + /* Expect protocol error */ + zassert_equal(err, -EPIPE, "Transfer status is not a protocol error"); + break; + case USB_STATE_CONFIGURED: + /* TODO */ + default: + break; + } +} + +static void *usb_test_enable(void) +{ + struct usb_device *udev; + int err; + + err = usbh_init(&uhs_ctx); + zassert_equal(err, 0, "Failed to initialize USB host"); + + err = usbh_enable(&uhs_ctx); + zassert_equal(err, 0, "Failed to enable USB host"); + + err = uhc_bus_reset(uhs_ctx.dev); + zassert_equal(err, 0, "Failed to signal bus reset"); + + err = uhc_bus_resume(uhs_ctx.dev); + zassert_equal(err, 0, "Failed to signal bus resume"); + + err = uhc_sof_enable(uhs_ctx.dev); + zassert_equal(err, 0, "Failed to enable SoF generator"); + + LOG_INF("Host controller enabled"); + + err = usbd_add_descriptor(&test_usbd, &test_lang); + zassert_equal(err, 0, "Failed to initialize descriptor (%d)", err); + + err = usbd_add_descriptor(&test_usbd, &test_mfg); + zassert_equal(err, 0, "Failed to initialize descriptor (%d)", err); + + err = usbd_add_descriptor(&test_usbd, &test_product); + zassert_equal(err, 0, "Failed to initialize descriptor (%d)", err); + + err = usbd_add_descriptor(&test_usbd, &test_sn); + zassert_equal(err, 0, "Failed to initialize descriptor (%d)", err); + + err = usbd_add_configuration(&test_usbd, &test_config); + zassert_equal(err, 0, "Failed to add configuration (%d)"); + + err = usbd_register_class(&test_usbd, "loopback_0", 1); + zassert_equal(err, 0, "Failed to register loopback_0 class (%d)"); + + err = usbd_init(&test_usbd); + zassert_equal(err, 0, "Failed to initialize device support"); + + err = usbd_enable(&test_usbd); + zassert_equal(err, 0, "Failed to enable device support"); + + LOG_INF("Device support enabled"); + udev = usbh_device_get_any(&uhs_ctx); + udev->state = USB_STATE_DEFAULT; + + return NULL; +} + +static void usb_test_shutdown(void *f) +{ + int err; + + err = usbd_disable(&test_usbd); + zassert_equal(err, 0, "Failed to enable device support"); + + err = usbd_shutdown(&test_usbd); + zassert_equal(err, 0, "Failed to shutdown device support"); + + LOG_INF("Device support disabled"); + + err = usbh_disable(&uhs_ctx); + zassert_equal(err, 0, "Failed to disable USB host"); + + LOG_INF("Host controller disabled"); +} + +ZTEST_SUITE(device_next, NULL, usb_test_enable, NULL, NULL, usb_test_shutdown); diff --git a/tests/subsys/usb/device_next/testcase.yaml b/tests/subsys/usb/device_next/testcase.yaml new file mode 100644 index 00000000000..47e6aa3a0a1 --- /dev/null +++ b/tests/subsys/usb/device_next/testcase.yaml @@ -0,0 +1,9 @@ +tests: + usb.device_next: + depends_on: usb_device + tags: usb + platform_allow: + - native_posix + - qemu_cortex_m3 + integration_platforms: + - native_posix diff --git a/tests/subsys/usb/os_desc/prj.conf b/tests/subsys/usb/os_desc/prj.conf index edc74ced85f..508f4a0dd7f 100644 --- a/tests/subsys/usb/os_desc/prj.conf +++ b/tests/subsys/usb/os_desc/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y CONFIG_USB_DEVICE_STACK=y CONFIG_USB_DEVICE_OS_DESC=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/subsys/zbus/dyn_channel/prj.conf b/tests/subsys/zbus/dyn_channel/prj.conf index fcb4160678f..86b0b96dd38 100644 --- a/tests/subsys/zbus/dyn_channel/prj.conf +++ b/tests/subsys/zbus/dyn_channel/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_LOG=y CONFIG_HEAP_MEM_POOL_SIZE=256 diff --git a/tests/subsys/zbus/integration/prj.conf b/tests/subsys/zbus/integration/prj.conf index 4d2bd32315d..c911616e2db 100644 --- a/tests/subsys/zbus/integration/prj.conf +++ b/tests/subsys/zbus/integration/prj.conf @@ -1,7 +1,7 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=n CONFIG_LOG=y CONFIG_ZBUS=y -CONFIG_ZBUS_LOG_LEVEL_DBG=y CONFIG_ZBUS_CHANNEL_NAME=y +CONFIG_ZBUS_MSG_SUBSCRIBER=y +CONFIG_HEAP_MEM_POOL_SIZE=1024 diff --git a/tests/subsys/zbus/integration/src/channels.c b/tests/subsys/zbus/integration/src/channels.c index 82fe1e00bbb..a7197def47a 100644 --- a/tests/subsys/zbus/integration/src/channels.c +++ b/tests/subsys/zbus/integration/src/channels.c @@ -34,6 +34,15 @@ ZBUS_CHAN_DEFINE(net_pkt_chan, /* Name */ ZBUS_MSG_INIT(.total = 0) /* Initial value */ ); +ZBUS_CHAN_DEFINE(net_log_chan, /* Name */ + struct net_log_msg, /* Message type */ + + NULL, /* Validator */ + NULL, /* User data */ + ZBUS_OBSERVERS(net_log_sub), /* observers */ + ZBUS_MSG_INIT(0) /* Initial value */ +); + ZBUS_CHAN_DEFINE(start_measurement_chan, /* Name */ struct action_msg, /* Message type */ diff --git a/tests/subsys/zbus/integration/src/main.c b/tests/subsys/zbus/integration/src/main.c index 147c4e264ab..9539a0c7206 100644 --- a/tests/subsys/zbus/integration/src/main.c +++ b/tests/subsys/zbus/integration/src/main.c @@ -12,7 +12,8 @@ #include LOG_MODULE_DECLARE(zbus, CONFIG_ZBUS_LOG_LEVEL); -ZBUS_CHAN_DECLARE(version_chan, sensor_data_chan, net_pkt_chan, start_measurement_chan, busy_chan); +ZBUS_CHAN_DECLARE(version_chan, sensor_data_chan, net_pkt_chan, net_log_chan, + start_measurement_chan, busy_chan); static int count_callback; @@ -69,12 +70,38 @@ static void net_thread(void) zbus_chan_read(&net_pkt_chan, &pkt, K_NO_WAIT); LOG_DBG("[Net] Total %d", pkt.total); + + struct net_log_msg log_msg = {.count_net = count_net, + .pkt_total = pkt.total}; + + zbus_chan_pub(&net_log_chan, &log_msg, K_MSEC(500)); } } } K_THREAD_DEFINE(net_thread_id, 1024, net_thread, NULL, NULL, NULL, 3, 0, 0); +static int count_net_log; + +ZBUS_MSG_SUBSCRIBER_DEFINE(net_log_sub); + +static void net_log_thread(void) +{ + const struct zbus_channel *chan; + struct net_log_msg log_msg; + + while (1) { + if (!zbus_sub_wait_msg(&net_log_sub, &chan, &log_msg, K_FOREVER)) { + count_net_log++; + + LOG_DBG("[Net log]: count_net = %d, pkt.total = %d", log_msg.count_net, + log_msg.pkt_total); + } + } +} + +K_THREAD_DEFINE(net_log_thread_id, 1024, net_log_thread, NULL, NULL, NULL, 3, 0, 0); + static int a; static int b; static int count_peripheral; @@ -116,6 +143,7 @@ static void context_reset(void *f) count_callback = 0; count_core = 0; count_net = 0; + count_net_log = 0; count_peripheral = 0; pkt.total = 0; struct net_pkt_msg *p; @@ -134,15 +162,22 @@ static void context_reset(void *f) zbus_obs_set_enable(&critical_lis, true); zbus_obs_set_enable(&peripheral_sub, true); zbus_chan_claim(&start_measurement_chan, K_NO_WAIT); - struct action_msg *act = (struct action_msg *)start_measurement_chan.message; + struct action_msg *act = (struct action_msg *)zbus_chan_msg(&start_measurement_chan); act->status = false; zbus_chan_finish(&start_measurement_chan); + zbus_chan_claim(&net_log_chan, K_NO_WAIT); + struct net_log_msg *lm = (struct net_log_msg *)zbus_chan_msg(&net_log_chan); + + lm->count_net = 0; + lm->pkt_total = 0; + zbus_chan_finish(&net_log_chan); } ZTEST(integration, test_basic) { struct action_msg start = {true}; + struct net_log_msg *lm = (struct net_log_msg *)zbus_chan_const_msg(&net_log_chan); zassert_equal(0, zbus_chan_pub(&start_measurement_chan, &start, K_MSEC(200)), NULL); @@ -152,6 +187,8 @@ ZTEST(integration, test_basic) zassert_equal(count_core, 1, NULL); zassert_equal(count_net, 1, NULL); zassert_equal(count_peripheral, 1, NULL); + zassert_equal(count_net_log, 1, NULL); + zassert_equal(count_net, lm->count_net, NULL); zassert_equal(0, zbus_chan_pub(&start_measurement_chan, &start, K_MSEC(200)), NULL); @@ -161,6 +198,8 @@ ZTEST(integration, test_basic) zassert_equal(count_core, 2, NULL); zassert_equal(count_net, 2, NULL); zassert_equal(count_peripheral, 2, NULL); + zassert_equal(count_net_log, 2, NULL); + zassert_equal(count_net, lm->count_net, NULL); zassert_equal(0, zbus_chan_pub(&start_measurement_chan, &start, K_MSEC(200)), NULL); @@ -170,13 +209,17 @@ ZTEST(integration, test_basic) zassert_equal(count_core, 3, NULL); zassert_equal(count_net, 3, NULL); zassert_equal(count_peripheral, 3, NULL); + zassert_equal(count_net_log, 3, NULL); + zassert_equal(count_net, lm->count_net, NULL); zassert_equal(pkt.total, 6, "result was %d", pkt.total); + zassert_equal(pkt.total, lm->pkt_total, NULL); } ZTEST(integration, test_channel_set_enable) { struct action_msg start = {true}; + const struct net_log_msg *lm = zbus_chan_const_msg(&net_log_chan); zassert_equal(0, zbus_obs_set_enable(&critical_lis, false), NULL); zassert_equal(0, zbus_obs_set_enable(&peripheral_sub, false), NULL); @@ -186,8 +229,10 @@ ZTEST(integration, test_channel_set_enable) zassert_equal(count_callback, 0, NULL); zassert_equal(count_core, 0, NULL); - zassert_equal(count_net, 0, NULL); zassert_equal(count_peripheral, 0, NULL); + zassert_equal(count_net, 0, NULL); + zassert_equal(count_net_log, 0, NULL); + zassert_equal(count_net, lm->count_net, NULL); zassert_equal(0, zbus_obs_set_enable(&critical_lis, false), NULL); zassert_equal(0, zbus_obs_set_enable(&peripheral_sub, true), NULL); @@ -199,6 +244,8 @@ ZTEST(integration, test_channel_set_enable) zassert_equal(count_core, 1, NULL); zassert_equal(count_net, 1, NULL); zassert_equal(count_peripheral, 1, NULL); + zassert_equal(count_net_log, 1, NULL); + zassert_equal(count_net, lm->count_net, NULL); zassert_equal(0, zbus_obs_set_enable(&critical_lis, true), NULL); zassert_equal(0, zbus_obs_set_enable(&peripheral_sub, false), NULL); @@ -210,6 +257,8 @@ ZTEST(integration, test_channel_set_enable) zassert_equal(count_core, 1, NULL); zassert_equal(count_net, 1, NULL); zassert_equal(count_peripheral, 1, NULL); + zassert_equal(count_net_log, 1, NULL); + zassert_equal(count_net, lm->count_net, NULL); zassert_equal(0, zbus_obs_set_enable(&critical_lis, true), NULL); zassert_equal(0, zbus_obs_set_enable(&peripheral_sub, true), NULL); @@ -219,10 +268,13 @@ ZTEST(integration, test_channel_set_enable) zassert_equal(count_callback, 2, NULL); zassert_equal(count_core, 2, NULL); - zassert_equal(count_net, 2, NULL); zassert_equal(count_peripheral, 2, NULL); + zassert_equal(count_net, 2, NULL); + zassert_equal(count_net_log, 2, NULL); + zassert_equal(count_net, lm->count_net, NULL); zassert_equal(pkt.total, 4, "result was %d", pkt.total); + zassert_equal(pkt.total, lm->pkt_total, NULL); } static void greedy_thread_entry(void *p1, void *p2, void *p3) diff --git a/tests/subsys/zbus/integration/src/messages.h b/tests/subsys/zbus/integration/src/messages.h index aa80c1d7176..76f129246bd 100644 --- a/tests/subsys/zbus/integration/src/messages.h +++ b/tests/subsys/zbus/integration/src/messages.h @@ -26,4 +26,8 @@ struct action_msg { bool status; }; +struct net_log_msg { + int count_net; + int pkt_total; +}; #endif /* _ZBUS_MESSAGES_H_ */ diff --git a/tests/subsys/zbus/integration/testcase.yaml b/tests/subsys/zbus/integration/testcase.yaml index 2f36fa057c3..ae918fcfb0f 100644 --- a/tests/subsys/zbus/integration/testcase.yaml +++ b/tests/subsys/zbus/integration/testcase.yaml @@ -4,6 +4,7 @@ tests: - qemu_cortex_a9 - hifive_unleashed - fvp_base_revc_2xaemv8a_smp_ns + - fvp_baser_aemv8r_aarch32_smp tags: zbus integration_platforms: - native_posix diff --git a/tests/subsys/zbus/runtime_observers_registration/prj.conf b/tests/subsys/zbus/runtime_observers_registration/prj.conf index 6f074e22a27..741938a265c 100644 --- a/tests/subsys/zbus/runtime_observers_registration/prj.conf +++ b/tests/subsys/zbus/runtime_observers_registration/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_LOG=y CONFIG_ZBUS=y CONFIG_ZBUS_ASSERT_MOCK=y diff --git a/tests/subsys/zbus/unittests/prj.conf b/tests/subsys/zbus/unittests/prj.conf index 736b5ed68cc..c6d0cbd6068 100644 --- a/tests/subsys/zbus/unittests/prj.conf +++ b/tests/subsys/zbus/unittests/prj.conf @@ -1,11 +1,12 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_LOG=y CONFIG_ZBUS=y CONFIG_ZBUS_LOG_LEVEL_DBG=y CONFIG_ZBUS_ASSERT_MOCK=y CONFIG_IRQ_OFFLOAD=y +CONFIG_ZBUS_MSG_SUBSCRIBER=y +CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_SIZE=2 CONFIG_ZBUS_RUNTIME_OBSERVERS=y CONFIG_HEAP_MEM_POOL_SIZE=2048 CONFIG_ZBUS_CHANNEL_NAME=y diff --git a/tests/subsys/zbus/unittests/src/main.c b/tests/subsys/zbus/unittests/src/main.c index a6aeb2310a4..7c3ff76230a 100644 --- a/tests/subsys/zbus/unittests/src/main.c +++ b/tests/subsys/zbus/unittests/src/main.c @@ -86,6 +86,20 @@ ZBUS_CHAN_DEFINE(stuck_chan, /* Name */ ZBUS_MSG_INIT(0) /* Initial value major 0, minor 1, build 1023 */ ); +ZBUS_CHAN_DEFINE(msg_sub_fail_chan, /* Name */ + int, /* Message type */ + NULL, /* Validator */ + NULL, /* User data */ + ZBUS_OBSERVERS(foo_msg_sub, invalid_obs), /* observers */ + ZBUS_MSG_INIT(0) /* Initial value major 0, minor 1, build 1023 */ +); +ZBUS_CHAN_DEFINE(msg_sub_no_pool_chan, /* Name */ + int, /* Message type */ + NULL, /* Validator */ + NULL, /* User data */ + ZBUS_OBSERVERS(foo_msg_sub, foo2_msg_sub), /* observers */ + ZBUS_MSG_INIT(0) /* Initial value major 0, minor 1, build 1023 */ +); static int count_fast; static void callback(const struct zbus_channel *chan) @@ -207,6 +221,15 @@ static void wq_dh_cb(struct k_work *item) } ZBUS_SUBSCRIBER_DEFINE(sub1, 1); +ZBUS_MSG_SUBSCRIBER_DEFINE_WITH_ENABLE(foo_msg_sub, false); +ZBUS_MSG_SUBSCRIBER_DEFINE_WITH_ENABLE(foo2_msg_sub, false); +static K_FIFO_DEFINE(_zbus_observer_fifo_invalid_obs); +STRUCT_SECTION_ITERABLE(zbus_observer, invalid_obs) = { + ZBUS_OBSERVER_NAME_INIT(invalid_obs) /* Name field */ + .type = ZBUS_OBSERVER_MSG_SUBSCRIBER_TYPE + 10, + .enabled = false, + .message_fifo = &_zbus_observer_fifo_invalid_obs, +}; ZTEST(basic, test_specification_based__zbus_chan) { @@ -268,6 +291,14 @@ ZTEST(basic, test_specification_based__zbus_chan) zassert_equal(0, zbus_chan_finish(&aux2_chan), "It must finish correctly"); + int fail = 10; + + zbus_obs_set_enable(&invalid_obs, true); + int err = zbus_chan_pub(&msg_sub_fail_chan, &fail, K_MSEC(200)); + + zassert_equal(-EFAULT, err, "It must reach the default on the switch. Err %d", err); + zbus_obs_set_enable(&invalid_obs, false); + struct action_msg repeated = {.status = false}; zbus_chan_pub(&aux3_on_change_chan, &repeated, K_NO_WAIT); @@ -307,6 +338,19 @@ ZTEST(basic, test_specification_based__zbus_chan) ISR_OP(ADD_OBS_ISR_INVAL, -EFAULT); ISR_OP(RM_OBS_ISR, -EFAULT); ISR_OP(RM_OBS_ISR_INVAL, -EFAULT); + + int msg; + const struct zbus_channel *chan; + + zbus_obs_set_enable(&foo_msg_sub, true); + zbus_obs_set_enable(&foo2_msg_sub, true); + zassert_equal(-ENOMEM, zbus_chan_notify(&msg_sub_no_pool_chan, K_MSEC(200)), + "It must return an error, the pool only have 2 slots. For publishing to " + "MSG_SUBSCRIBERS it is necessary at least one per each and a spare one."); + + zassert_equal(0, zbus_sub_wait_msg(&foo_msg_sub, &chan, &msg, K_MSEC(500)), NULL); + zbus_obs_set_enable(&foo_msg_sub, false); + zbus_obs_set_enable(&foo2_msg_sub, false); } static bool always_true_chan_iterator(const struct zbus_channel *chan) @@ -353,9 +397,17 @@ static bool check_chan_iterator(const struct zbus_channel *chan, void *user_data zassert_mem_equal__(zbus_chan_name(chan), "hard_chan", 9, "Must be equal"); break; case 5: - zassert_mem_equal__(zbus_chan_name(chan), "stuck_chan", 10, "Must be equal"); + zassert_mem_equal__(zbus_chan_name(chan), "msg_sub_fail_chan", + sizeof("msg_sub_fail_chan"), "Must be equal"); break; case 6: + zassert_mem_equal__(zbus_chan_name(chan), "msg_sub_no_pool_chan", + sizeof("msg_sub_no_pool_chan"), "Must be equal"); + break; + case 7: + zassert_mem_equal__(zbus_chan_name(chan), "stuck_chan", 10, "Must be equal"); + break; + case 8: zassert_mem_equal__(zbus_chan_name(chan), "version_chan", 12, "Must be equal"); break; default: @@ -380,12 +432,31 @@ static bool check_obs_iterator(const struct zbus_observer *obs, void *user_data) zassert_mem_equal__(zbus_obs_name(obs), "fast_lis", 8, "Must be equal"); break; case 2: - zassert_mem_equal__(zbus_obs_name(obs), "foo_sub", 7, "Must be equal"); + zassert_mem_equal__(zbus_obs_name(obs), "foo2_msg_sub", sizeof("foo2_msg_sub"), + "Must be equal"); break; case 3: - zassert_mem_equal__(zbus_obs_name(obs), "rt_fast_lis", 11, "Must be equal"); + zassert_mem_equal__(zbus_obs_name(obs), "foo_msg_sub", 11, "Must be equal"); break; case 4: + zassert_mem_equal__(zbus_obs_name(obs), "foo_sub", 7, "Must be equal"); + break; + case 5: + zassert_mem_equal__(zbus_obs_name(obs), "invalid_obs", strlen("invalid_obs"), + "Must be equal"); + break; + case 6: + zassert_mem_equal__(zbus_obs_name(obs), "invalid_sub", strlen("invalid_sub"), + "Must be equal"); + break; + case 7: + zassert_mem_equal__(zbus_obs_name(obs), "not_observing_sub", + strlen("not_observing_sub"), "Must be equal"); + break; + case 8: + zassert_mem_equal__(zbus_obs_name(obs), "rt_fast_lis", 11, "Must be equal"); + break; + case 9: zassert_mem_equal__(zbus_obs_name(obs), "sub1", 4, "Must be equal"); break; default: @@ -570,9 +641,12 @@ ZTEST(basic, test_specification_based__zbus_obs_set_enable) zassert_equal(0, zbus_chan_rm_obs(&aux1_chan, &rt_fast_lis, K_MSEC(200)), NULL); } +ZBUS_SUBSCRIBER_DEFINE(not_observing_sub, 0); + ZTEST(basic, test_specification_based__zbus_obs_set_chan_notification_mask) { bool enabled = false; + bool masked = false; count_fast = 0; @@ -584,6 +658,24 @@ ZTEST(basic, test_specification_based__zbus_obs_set_chan_notification_mask) zassert_equal(-EFAULT, zbus_obs_set_chan_notification_mask(NULL, &aux1_chan, true), NULL); + zassert_equal(-ESRCH, + zbus_obs_set_chan_notification_mask(¬_observing_sub, &aux1_chan, true), + NULL); + + zassert_equal(-EFAULT, zbus_obs_is_chan_notification_masked(NULL, NULL, NULL), NULL); + + zassert_equal(-EFAULT, zbus_obs_is_chan_notification_masked(NULL, NULL, &masked), NULL); + + zassert_equal(-EFAULT, zbus_obs_is_chan_notification_masked(&fast_lis, NULL, &masked), + NULL); + + zassert_equal(-EFAULT, zbus_obs_is_chan_notification_masked(NULL, &aux1_chan, &masked), + NULL); + + zassert_equal(-ESRCH, + zbus_obs_is_chan_notification_masked(¬_observing_sub, &aux1_chan, &masked), + NULL); + zbus_obs_set_chan_notification_mask(&fast_lis, &aux1_chan, true); zbus_obs_is_chan_notification_masked(&fast_lis, &aux1_chan, &enabled); @@ -608,6 +700,10 @@ ZTEST(basic, test_specification_based__zbus_obs_set_chan_notification_mask) ZBUS_SUBSCRIBER_DEFINE(foo_sub, 1); +STRUCT_SECTION_ITERABLE(zbus_observer, + invalid_sub) = {ZBUS_OBSERVER_NAME_INIT(invalid_sub) /* Name field */ + .type = ZBUS_OBSERVER_SUBSCRIBER_TYPE, + .enabled = false, .queue = NULL}; static void isr_sub_wait(const void *operation) { const struct zbus_channel *chan; @@ -616,6 +712,7 @@ static void isr_sub_wait(const void *operation) zassert_equal(-EFAULT, zbus_sub_wait(NULL, NULL, K_NO_WAIT), NULL); zassert_equal(-EFAULT, zbus_sub_wait(&foo_sub, NULL, K_NO_WAIT), NULL); zassert_equal(-EFAULT, zbus_sub_wait(&foo_sub, &chan, K_NO_WAIT), NULL); + zassert_equal(-EFAULT, zbus_sub_wait(&invalid_sub, &chan, K_NO_WAIT), NULL); } ZTEST(basic, test_specification_based__zbus_sub_wait) @@ -625,11 +722,42 @@ ZTEST(basic, test_specification_based__zbus_sub_wait) zassert_equal(-EFAULT, zbus_sub_wait(NULL, NULL, K_NO_WAIT), NULL); zassert_equal(-EFAULT, zbus_sub_wait(&foo_sub, NULL, K_NO_WAIT), NULL); + zassert_equal(-EFAULT, zbus_sub_wait(&foo_msg_sub, NULL, K_NO_WAIT), NULL); /* It must run but return a -ENOMSG because of the K_NO_WAIT */ zassert_equal(-ENOMSG, zbus_sub_wait(&foo_sub, &chan, K_NO_WAIT), NULL); + zassert_equal(-EAGAIN, zbus_sub_wait(&foo_sub, &chan, K_MSEC(200)), NULL); irq_offload(isr_sub_wait, NULL); } +static void isr_sub_wait_msg(const void *operation) +{ + const struct zbus_channel *chan; + + /* All the calls must not work. Zbus cannot work in IRSs */ + zassert_equal(-EFAULT, zbus_sub_wait_msg(NULL, NULL, NULL, K_NO_WAIT), NULL); + zassert_equal(-EFAULT, zbus_sub_wait_msg(&foo_sub, NULL, NULL, K_NO_WAIT), NULL); + zassert_equal(-EFAULT, zbus_sub_wait(&foo_msg_sub, NULL, K_NO_WAIT), NULL); + int a = 0; + + zassert_equal(-EFAULT, zbus_sub_wait_msg(&foo_msg_sub, &chan, &a, K_NO_WAIT), NULL); +} +ZTEST(basic, test_specification_based__zbus_sub_wait_msg) +{ + count_fast = 0; + const struct zbus_channel *chan; + + zassert_equal(-EFAULT, zbus_sub_wait_msg(NULL, NULL, NULL, K_NO_WAIT), NULL); + zassert_equal(-EFAULT, zbus_sub_wait_msg(&foo_sub, NULL, NULL, K_NO_WAIT), NULL); + zassert_equal(-EFAULT, zbus_sub_wait_msg(&foo_msg_sub, NULL, NULL, K_NO_WAIT), NULL); + zassert_equal(-EFAULT, zbus_sub_wait_msg(&foo_msg_sub, &chan, NULL, K_NO_WAIT), NULL); + int a = 0; + + zassert_equal(-ENOMSG, zbus_sub_wait_msg(&foo_msg_sub, &chan, &a, K_NO_WAIT), NULL); + zassert_equal(-ENOMSG, zbus_sub_wait_msg(&foo_msg_sub, &chan, &a, K_MSEC(200)), NULL); + + irq_offload(isr_sub_wait_msg, NULL); +} + ZTEST_SUITE(basic, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/subsys/zbus/user_data/prj.conf b/tests/subsys/zbus/user_data/prj.conf index 5e78e1b452e..63a89fccd8d 100644 --- a/tests/subsys/zbus/user_data/prj.conf +++ b/tests/subsys/zbus/user_data/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ASSERT=y CONFIG_LOG=y CONFIG_ZBUS=y diff --git a/tests/unit/base64/prj.conf b/tests/unit/base64/prj.conf index 963087265ce..9467c292689 100644 --- a/tests/unit/base64/prj.conf +++ b/tests/unit/base64/prj.conf @@ -1 +1 @@ -CONFIG_ZTEST_NEW_API=y +CONFIG_ZTEST=y diff --git a/tests/unit/cbprintf/prj.conf b/tests/unit/cbprintf/prj.conf index 963087265ce..9467c292689 100644 --- a/tests/unit/cbprintf/prj.conf +++ b/tests/unit/cbprintf/prj.conf @@ -1 +1 @@ -CONFIG_ZTEST_NEW_API=y +CONFIG_ZTEST=y diff --git a/tests/unit/crc/prj.conf b/tests/unit/crc/prj.conf index fd4e42e2deb..3f282dbf061 100644 --- a/tests/unit/crc/prj.conf +++ b/tests/unit/crc/prj.conf @@ -1,2 +1 @@ -CONFIG_ZTEST_NEW_API=y CONFIG_CRC=y diff --git a/tests/unit/intmath/prj.conf b/tests/unit/intmath/prj.conf index 963087265ce..9467c292689 100644 --- a/tests/unit/intmath/prj.conf +++ b/tests/unit/intmath/prj.conf @@ -1 +1 @@ -CONFIG_ZTEST_NEW_API=y +CONFIG_ZTEST=y diff --git a/tests/unit/list/dlist.c b/tests/unit/list/dlist.c index dff44b8bb59..937355c13b5 100644 --- a/tests/unit/list/dlist.c +++ b/tests/unit/list/dlist.c @@ -39,6 +39,10 @@ static inline bool verify_emptyness(sys_dlist_t *list) return false; } + if (sys_dlist_len(list) != 0) { + return false; + } + count = 0; SYS_DLIST_FOR_EACH_NODE(list, node) { count++; @@ -97,6 +101,10 @@ static inline bool verify_content_amount(sys_dlist_t *list, int amount) return false; } + if (sys_dlist_len(list) != amount) { + return false; + } + count = 0; SYS_DLIST_FOR_EACH_NODE(list, node) { count++; diff --git a/tests/unit/list/prj.conf b/tests/unit/list/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/unit/list/prj.conf +++ b/tests/unit/list/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/unit/list/sflist.c b/tests/unit/list/sflist.c index e7d1ff4a199..c0162d00358 100644 --- a/tests/unit/list/sflist.c +++ b/tests/unit/list/sflist.c @@ -40,6 +40,10 @@ static inline bool verify_emptyness(sys_sflist_t *list) return false; } + if (sys_sflist_len(list) != 0) { + return false; + } + count = 0; SYS_SFLIST_FOR_EACH_NODE(list, node) { count++; @@ -98,6 +102,10 @@ static inline bool verify_content_amount(sys_sflist_t *list, int amount) return false; } + if (sys_sflist_len(list) != amount) { + return false; + } + count = 0; SYS_SFLIST_FOR_EACH_NODE(list, node) { count++; diff --git a/tests/unit/list/slist.c b/tests/unit/list/slist.c index 2df65dac4e2..49c4b8257b2 100644 --- a/tests/unit/list/slist.c +++ b/tests/unit/list/slist.c @@ -40,6 +40,10 @@ static inline bool verify_emptyness(sys_slist_t *list) return false; } + if (sys_slist_len(list) != 0) { + return false; + } + count = 0; SYS_SLIST_FOR_EACH_NODE(list, node) { count++; @@ -98,6 +102,10 @@ static inline bool verify_content_amount(sys_slist_t *list, int amount) return false; } + if (sys_slist_len(list) != amount) { + return false; + } + count = 0; SYS_SLIST_FOR_EACH_NODE(list, node) { count++; diff --git a/tests/unit/math_extras/prj.conf b/tests/unit/math_extras/prj.conf index 963087265ce..9467c292689 100644 --- a/tests/unit/math_extras/prj.conf +++ b/tests/unit/math_extras/prj.conf @@ -1 +1 @@ -CONFIG_ZTEST_NEW_API=y +CONFIG_ZTEST=y diff --git a/tests/unit/net_timeout/prj.conf b/tests/unit/net_timeout/prj.conf index 963087265ce..9467c292689 100644 --- a/tests/unit/net_timeout/prj.conf +++ b/tests/unit/net_timeout/prj.conf @@ -1 +1 @@ -CONFIG_ZTEST_NEW_API=y +CONFIG_ZTEST=y diff --git a/tests/unit/pot/prj.conf b/tests/unit/pot/prj.conf index 0d91a89b0ef..3aff91ca987 100644 --- a/tests/unit/pot/prj.conf +++ b/tests/unit/pot/prj.conf @@ -2,4 +2,3 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/unit/rbtree/prj.conf b/tests/unit/rbtree/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/unit/rbtree/prj.conf +++ b/tests/unit/rbtree/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/unit/time_units/prj.conf b/tests/unit/time_units/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/unit/time_units/prj.conf +++ b/tests/unit/time_units/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/unit/timeutil/prj.conf b/tests/unit/timeutil/prj.conf index 963087265ce..9467c292689 100644 --- a/tests/unit/timeutil/prj.conf +++ b/tests/unit/timeutil/prj.conf @@ -1 +1 @@ -CONFIG_ZTEST_NEW_API=y +CONFIG_ZTEST=y diff --git a/tests/unit/util/prj.conf b/tests/unit/util/prj.conf index 963087265ce..9467c292689 100644 --- a/tests/unit/util/prj.conf +++ b/tests/unit/util/prj.conf @@ -1 +1 @@ -CONFIG_ZTEST_NEW_API=y +CONFIG_ZTEST=y diff --git a/tests/unit/winstream/prj.conf b/tests/unit/winstream/prj.conf index 963087265ce..9467c292689 100644 --- a/tests/unit/winstream/prj.conf +++ b/tests/unit/winstream/prj.conf @@ -1 +1 @@ -CONFIG_ZTEST_NEW_API=y +CONFIG_ZTEST=y diff --git a/tests/ztest/base/prj.conf b/tests/ztest/base/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/ztest/base/prj.conf +++ b/tests/ztest/base/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/ztest/base/prj_cpp.conf b/tests/ztest/base/prj_cpp.conf index 34f5b636a52..de04b5070db 100644 --- a/tests/ztest/base/prj_cpp.conf +++ b/tests/ztest/base/prj_cpp.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_CPP=y diff --git a/tests/ztest/base/prj_verbose_0.conf b/tests/ztest/base/prj_verbose_0.conf index 4f00bd038ad..4a5ace8ad17 100644 --- a/tests/ztest/base/prj_verbose_0.conf +++ b/tests/ztest/base/prj_verbose_0.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_ASSERT_VERBOSE=0 CONFIG_ENTROPY_GENERATOR=y diff --git a/tests/ztest/base/prj_verbose_1.conf b/tests/ztest/base/prj_verbose_1.conf index b92787f41c7..885394fe918 100644 --- a/tests/ztest/base/prj_verbose_1.conf +++ b/tests/ztest/base/prj_verbose_1.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_ASSERT_VERBOSE=1 CONFIG_ZTEST_SHUFFLE=y diff --git a/tests/ztest/base/prj_verbose_2.conf b/tests/ztest/base/prj_verbose_2.conf index c995cf19ee0..0bda78a5b4f 100644 --- a/tests/ztest/base/prj_verbose_2.conf +++ b/tests/ztest/base/prj_verbose_2.conf @@ -1,3 +1,2 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTEST_ASSERT_VERBOSE=2 diff --git a/tests/ztest/base/src/main.c b/tests/ztest/base/src/main.c index 561b63ad5bc..5a18c15bab1 100644 --- a/tests/ztest/base/src/main.c +++ b/tests/ztest/base/src/main.c @@ -20,6 +20,7 @@ ZTEST(framework_tests, test_assert_tests) zassert_not_null("foo", NULL); zassert_equal(1, 1); zassert_equal_ptr(NULL, NULL, NULL); + zassert_not_ok(-EIO); } ZTEST(framework_tests, test_assert_mem_equal) diff --git a/tests/ztest/base/testcase.yaml b/tests/ztest/base/testcase.yaml index 4ac55a1dc55..ee566d5dd8a 100644 --- a/tests/ztest/base/testcase.yaml +++ b/tests/ztest/base/testcase.yaml @@ -6,11 +6,16 @@ tests: type: unit testing.ztest.base.cpp: extra_args: CONF_FILE=prj_cpp.conf - platform_allow: native_posix + platform_allow: + - native_posix + - native_sim + - native_sim_64 + integration_platforms: + - native_sim testing.ztest.base.verbose_0: extra_args: CONF_FILE=prj_verbose_0.conf integration_platforms: - - native_posix + - native_sim testing.ztest.base.verbose_0_userspace: filter: CONFIG_USERSPACE extra_args: CONF_FILE=prj_verbose_0.conf @@ -23,8 +28,8 @@ tests: testing.ztest.base.verbose_1: extra_args: CONF_FILE=prj_verbose_1.conf integration_platforms: - - native_posix + - native_sim testing.ztest.base.verbose_2: extra_args: CONF_FILE=prj_verbose_2.conf integration_platforms: - - native_posix + - native_sim diff --git a/tests/ztest/busy_sim/prj.conf b/tests/ztest/busy_sim/prj.conf index dc4e8293d29..c06383cada1 100644 --- a/tests/ztest/busy_sim/prj.conf +++ b/tests/ztest/busy_sim/prj.conf @@ -1,4 +1,3 @@ CONFIG_ZTEST=y CONFIG_TEST_BUSY_SIM=y CONFIG_ZTEST_THREAD_PRIORITY=1 -CONFIG_ZTEST_NEW_API=y diff --git a/tests/ztest/error_hook/README.txt b/tests/ztest/error_hook/README.txt index 5ca44e9e330..1304cce5ab0 100644 --- a/tests/ztest/error_hook/README.txt +++ b/tests/ztest/error_hook/README.txt @@ -80,7 +80,7 @@ test_catch_assert_in_isr test_catch_z_oops - Pass illegal address by syscall, then inside the syscall handler, the - Z_OOPS macro will trigger a fatal error that will get caught (as expected). + K_OOPS macro will trigger a fatal error that will get caught (as expected). diff --git a/tests/ztest/error_hook/prj.conf b/tests/ztest/error_hook/prj.conf index 421acadbe89..f0981ce3547 100644 --- a/tests/ztest/error_hook/prj.conf +++ b/tests/ztest/error_hook/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_TEST_USERSPACE=y CONFIG_IRQ_OFFLOAD=y CONFIG_ZTEST_FATAL_HOOK=y diff --git a/tests/ztest/error_hook/prj_no_userspace.conf b/tests/ztest/error_hook/prj_no_userspace.conf index 7bdd8519046..b76cc814b07 100644 --- a/tests/ztest/error_hook/prj_no_userspace.conf +++ b/tests/ztest/error_hook/prj_no_userspace.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_IRQ_OFFLOAD=y CONFIG_ZTEST_FATAL_HOOK=y CONFIG_ZTEST_ASSERT_HOOK=y diff --git a/tests/ztest/error_hook/src/main.c b/tests/ztest/error_hook/src/main.c index 7940f3c9009..e38b3111cf3 100644 --- a/tests/ztest/error_hook/src/main.c +++ b/tests/ztest/error_hook/src/main.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include @@ -31,7 +31,7 @@ enum { ZTEST_CATCH_FATAL_IN_ISR, ZTEST_CATCH_ASSERT_FAIL, ZTEST_CATCH_ASSERT_IN_ISR, - ZTEST_CATCH_USER_FATAL_Z_OOPS, + ZTEST_CATCH_USER_FATAL_K_OOPS, ZTEST_ERROR_MAX } error_case_type; @@ -115,14 +115,16 @@ __no_optimization static void trigger_fault_divide_zero(void) * For the Cortex-M0, M0+, M23 (CONFIG_ARMV6_M_ARMV8_M_BASELINE) * which does not include a divide instruction, the test is skipped, * and there will be no hardware exception for that. + * For ARMv8-R, divide by zero trapping is not supported in hardware. */ #if (defined(CONFIG_SOC_SERIES_MPS2) && defined(CONFIG_QEMU_TARGET)) || \ (defined(CONFIG_SOC_SERIES_MPS3) && defined(CONFIG_QEMU_TARGET)) || \ defined(CONFIG_BOARD_QEMU_CORTEX_A53) || defined(CONFIG_SOC_QEMU_ARC) || \ defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) || \ defined(CONFIG_BOARD_QEMU_CORTEX_R5) || \ - defined(CONFIG_BOARD_FVP_BASER_AEMV8R) || defined(CONFIG_BOARD_FVP_BASE_REVC_2XAEMV8A) || \ - defined(CONFIG_BOARD_FVP_BASER_AEMV8R_AARCH32) || defined(CONFIG_SOC_NSIM_EM11D) + defined(CONFIG_ARMV8_R) || defined(CONFIG_AARCH32_ARMV8_R) || \ + defined(CONFIG_BOARD_FVP_BASE_REVC_2XAEMV8A) || \ + defined(CONFIG_SOC_NSIM_EM11D) ztest_test_skip(); #endif } @@ -159,7 +161,7 @@ void ztest_post_fatal_error_hook(unsigned int reason, case ZTEST_CATCH_FATAL_DIVIDE_ZERO: case ZTEST_CATCH_FATAL_K_PANIC: case ZTEST_CATCH_FATAL_K_OOPS: - case ZTEST_CATCH_USER_FATAL_Z_OOPS: + case ZTEST_CATCH_USER_FATAL_K_OOPS: zassert_true(true); break; @@ -199,6 +201,9 @@ void ztest_post_assert_fail_hook(void) static void tThread_entry(void *p1, void *p2, void *p3) { + ARG_UNUSED(p2); + ARG_UNUSED(p3); + int sub_type = *(int *)p1; printk("case type is %d\n", case_type); @@ -247,7 +252,7 @@ static int run_trigger_thread(int i) } k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, - (k_thread_entry_t)tThread_entry, + tThread_entry, (void *)&case_type, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), perm, K_NO_WAIT); @@ -333,7 +338,7 @@ static void trigger_z_oops(void) /* Set up a dummy syscall frame, pointing to a valid area in memory. */ _current->syscall_frame = _image_ram_start; - Z_OOPS(true); + K_OOPS(true); } /** @@ -346,7 +351,7 @@ static void trigger_z_oops(void) */ ZTEST(error_hook_tests, test_catch_z_oops) { - case_type = ZTEST_CATCH_USER_FATAL_Z_OOPS; + case_type = ZTEST_CATCH_USER_FATAL_K_OOPS; ztest_set_fault_valid(true); trigger_z_oops(); diff --git a/tests/ztest/error_hook/testcase.yaml b/tests/ztest/error_hook/testcase.yaml index 13619ba99ca..db0f60f1714 100644 --- a/tests/ztest/error_hook/testcase.yaml +++ b/tests/ztest/error_hook/testcase.yaml @@ -4,6 +4,8 @@ common: tests: testing.ztest.error_hook: filter: CONFIG_ARCH_HAS_USERSPACE + arch_exclude: + - posix tags: - userspace ignore_faults: true diff --git a/tests/ztest/fail/CMakeLists.txt b/tests/ztest/fail/CMakeLists.txt index f7a07037774..c4a88639433 100644 --- a/tests/ztest/fail/CMakeLists.txt +++ b/tests/ztest/fail/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.20.0) include(ExternalProject) -# Add the sources and set up the build for either unit testing or native_posix +# Add the sources and set up the build for either unit testing or native_sim list(APPEND SOURCES src/main.cpp) if(BOARD STREQUAL unit_testing) find_package(Zephyr COMPONENTS unittest REQUIRED HINTS $ENV{ZEPHYR_BASE}) @@ -17,7 +17,7 @@ else() set(target app) # Set the target binary for the 'core' external project. The path to this must match the one set # below in ExternalProject_Add's CMAKE_INSTALL_PREFIX - add_compile_definitions(FAIL_TARGET_BINARY="${CMAKE_BINARY_DIR}/core/bin/zephyr.elf") + add_compile_definitions(FAIL_TARGET_BINARY="${CMAKE_BINARY_DIR}/core/bin/zephyr.exe") endif() # Create the project and set the sources for the target diff --git a/tests/ztest/fail/README.rst b/tests/ztest/fail/README.rst index 3ed70d5229a..ab5788ba821 100644 --- a/tests/ztest/fail/README.rst +++ b/tests/ztest/fail/README.rst @@ -7,8 +7,9 @@ Overview ******** In order to test the actual framework's failure cases, this test suite has to do something unique. -There's a subdirectory to this test called 'core'. This project builds a sample ``native_posix`` or -``unit_testing`` binary which is expected to fail by calling one of the following: +There's a subdirectory to this test called 'core'. This project builds a sample as a +:ref:`native_sim ` or `:ref:unit_testing ` +binary which is expected to fail by calling one of the following: - ``ztest_test_fail()`` during either the ``after`` or ``teardown`` phase of the test suite - ``ztest_test_skip()`` during either the ``after`` or ``teardown`` phase of the test suite - ``ztest_test_pass()`` during either the ``after`` or ``teardown`` phase of the test suite diff --git a/tests/ztest/fail/core/CMakeLists.txt b/tests/ztest/fail/core/CMakeLists.txt index cf56362b9ee..7ba86d28082 100644 --- a/tests/ztest/fail/core/CMakeLists.txt +++ b/tests/ztest/fail/core/CMakeLists.txt @@ -35,5 +35,9 @@ else() target_sources(app PRIVATE ${SOURCES}) target_include_directories(app PRIVATE include) - install(TARGETS ${logical_target_for_zephyr_elf}) + install(FILES ${APPLICATION_BINARY_DIR}/zephyr/${KERNEL_EXE_NAME} + DESTINATION bin/ + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ + WORLD_EXECUTE WORLD_READ + ) endif() diff --git a/tests/ztest/fail/core/prj.conf b/tests/ztest/fail/core/prj.conf index 3538526b3a7..84d6dc0cff5 100644 --- a/tests/ztest/fail/core/prj.conf +++ b/tests/ztest/fail/core/prj.conf @@ -2,6 +2,5 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_CPP=y diff --git a/tests/ztest/fail/prj.conf b/tests/ztest/fail/prj.conf index b10ffd701c3..cba949460e6 100644 --- a/tests/ztest/fail/prj.conf +++ b/tests/ztest/fail/prj.conf @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_CPP=y CONFIG_EXTERNAL_LIBCPP=y diff --git a/tests/ztest/fail/testcase.yaml b/tests/ztest/fail/testcase.yaml index 5295847a0cb..2a0820fa85e 100644 --- a/tests/ztest/fail/testcase.yaml +++ b/tests/ztest/fail/testcase.yaml @@ -5,7 +5,12 @@ common: tags: - test_framework # test has dependencies on host libc - platform_allow: native_posix + platform_allow: + - native_posix + - native_sim + - native_sim_64 + integration_platforms: + - native_sim tests: testing.fail.unit.assert_after: extra_configs: diff --git a/tests/ztest/summary/prj.conf b/tests/ztest/summary/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/ztest/summary/prj.conf +++ b/tests/ztest/summary/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/ztest/zexpect/prj.conf b/tests/ztest/zexpect/prj.conf index 9228251051e..9467c292689 100644 --- a/tests/ztest/zexpect/prj.conf +++ b/tests/ztest/zexpect/prj.conf @@ -1,2 +1 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y diff --git a/tests/ztest/zexpect/src/main.c b/tests/ztest/zexpect/src/main.c index 492257af749..fb05c944c6d 100644 --- a/tests/ztest/zexpect/src/main.c +++ b/tests/ztest/zexpect/src/main.c @@ -59,6 +59,17 @@ ZTEST(expect, test_fail_expect_ok) zexpect_ok(5); } +ZTEST(expect, test_expect_not_ok) +{ + zexpect_not_ok(-EIO); +} + +ZTEST_EXPECT_FAIL(expect, test_fail_expect_not_ok); +ZTEST(expect, test_fail_expect_not_ok) +{ + zexpect_not_ok(0); +} + ZTEST(expect, test_expect_is_null) { void *ptr = NULL; diff --git a/tests/ztest/zexpect/testcase.yaml b/tests/ztest/zexpect/testcase.yaml index f2679fb9a6f..6928a5f4198 100644 --- a/tests/ztest/zexpect/testcase.yaml +++ b/tests/ztest/zexpect/testcase.yaml @@ -3,17 +3,15 @@ common: integration_platforms: - - native_posix + - native_sim tags: - test_framework tests: testing.ztest.expect: integration_platforms: - - native_posix + - native_sim testing.ztest.expect_cpp: extra_configs: - CONFIG_CPLUSPLUS=y - integration_platforms: - - native_posix testing.ztest.expect.unit: type: unit diff --git a/tests/ztest/ztress/prj.conf b/tests/ztest/ztress/prj.conf index 7a560bc7187..219719d0fd6 100644 --- a/tests/ztest/ztress/prj.conf +++ b/tests/ztest/ztress/prj.conf @@ -1,5 +1,4 @@ CONFIG_ZTEST=y -CONFIG_ZTEST_NEW_API=y CONFIG_ZTRESS=y CONFIG_ZTRESS_MAX_THREADS=3 CONFIG_TEST_EXTRA_STACK_SIZE=2048 diff --git a/west.yml b/west.yml index 988343a9d10..c99118074eb 100644 --- a/west.yml +++ b/west.yml @@ -24,13 +24,13 @@ manifest: - name: babblesim url-base: https://github.com/BabbleSim - group-filter: [-babblesim] + group-filter: [-babblesim, -optional] # # Please add items below based on alphabetical order projects: - name: acpica - revision: f16a0b4d0f0edd7b78a332fcf507be2187fac21e + revision: 10ae1038e51eb9306f73c3bbcfc4fde954bb9625 path: modules/lib/acpica - name: bsim repo-path: babblesim-manifest @@ -115,17 +115,17 @@ manifest: revision: eed6d7038e839153e340bd333bc43541cb90ba64 groups: - babblesim - - name: canopennode - revision: dec12fa3f0d790cafa8414a4c2930ea71ab72ffd - path: modules/lib/canopennode - - name: chre - revision: b7955c27e50485b7dafdc3888d7d6afdc2ac6d96 - path: modules/lib/chre - name: cmsis - revision: 1abf29132e608826752e2edd1f4799a065db4031 + revision: 4b96cbb174678dcd3ca86e11e1f24bc5f8726da0 path: modules/hal/cmsis groups: - hal + - name: cmsis-dsp + revision: ff7b5fd1ea5f094665c090c343ec44e74dc0b193 + path: modules/lib/cmsis-dsp + - name: cmsis-nn + revision: 0c8669d81381ccf3b1a01d699f3b68b50134a99f + path: modules/lib/cmsis-nn - name: edtt revision: 64e5105ad82390164fb73fc654be3f73a608209a path: tools/edtt @@ -142,17 +142,17 @@ manifest: groups: - hal - name: hal_ambiq - revision: fbb1618df8b0946cc2abea817309dc85fe051c21 + revision: 0c5ea5749245c8ff6ce7aefbf0aa9981943c2857 path: modules/hal/ambiq groups: - hal - name: hal_atmel - revision: 5ab43007eda3f380c125f957f03638d2e8d1144d + revision: 942d664e48f7a2725933a93facc112b87b1de32b path: modules/hal/atmel groups: - hal - name: hal_espressif - revision: 80d910ca89eab9bce03f59a4ade33f1fc30ce0ad + revision: b3cb13f06586543ae1d156dc3e84b2fd3dc2f1fb path: modules/hal/espressif west-commands: west/west-commands.yml groups: @@ -168,12 +168,12 @@ manifest: groups: - hal - name: hal_infineon - revision: 815e84a5150f95627201f192779a0180d5052de7 + revision: 69c883d3bd9fac8a18dd8384624b8c472a68d06f path: modules/hal/infineon groups: - hal - name: hal_intel - revision: c72eea412d2563463043a2a6cfe41dc46e845d47 + revision: 7b4c25669f1513b0d6d6ee78ee42340d91958884 path: modules/hal/intel groups: - hal @@ -188,12 +188,12 @@ manifest: groups: - hal - name: hal_nuvoton - revision: 3e0a4c4d3328b2f72b164219add19d5308b53cb5 + revision: 584190e131655de1046088bd0d0735d83429ec7c path: modules/hal/nuvoton groups: - hal - name: hal_nxp - revision: b0274481021b6343740f1970ef167d65ea67d30b + revision: 69046233b7a7fac3138ae4dd5bcf6158e82529bb path: modules/hal/nxp groups: - hal @@ -210,26 +210,26 @@ manifest: - hal - name: hal_renesas path: modules/hal/renesas - revision: 61ea3505a470b4e739cad4359ec1401cc4b85805 + revision: 1471ed3cbf501434a5f3df2f9df520c3bd8e0258 groups: - hal - name: hal_rpi_pico path: modules/hal/rpi_pico - revision: b7801e4db6a62ea2d37bbef7880c3d056530c9bf + revision: fba7162cc7bee06d0149622bbcaac4e41062d368 groups: - hal - name: hal_silabs - revision: d184c2ccc0ec5a7189d6d5cb7645c7f9bd38c2b5 + revision: d191d981c4eb20c0c7445a4061fcdbcfa686113a path: modules/hal/silabs groups: - hal - name: hal_st - revision: 9b128caf3e7b2e750169b880e83f210ea2213473 + revision: fb8e79d1a261fd02aadff7c142729f1954163cf3 path: modules/hal/st groups: - hal - name: hal_stm32 - revision: 1bc72c299d0365c0ee2575a97918b22df0899e10 + revision: 89ef0a3383edebf661073073bcdf6e2836fe90ee path: modules/hal/stm32 groups: - hal @@ -239,7 +239,7 @@ manifest: groups: - hal - name: hal_ti - revision: ae1db23f32dde779cdfc4afaa9a60ea219310a64 + revision: b85f86e51fc4d47c4c383d320d64d52d4d371ae4 path: modules/hal/ti groups: - hal @@ -249,12 +249,16 @@ manifest: groups: - hal - name: hal_xtensa - revision: 86b7ddf984d54f34b79f52b328a4fecdae307956 + revision: 08325d6fb7190a105f5382d35e64ed2812c57cf4 path: modules/hal/xtensa groups: - hal + - name: hostap + repo-path: hostap + path: modules/lib/hostap + revision: 7adaff26baa48e26a32c576125e0a749a5239b12 - name: libmetal - revision: b91611a6f47dd29fb24c46e5621e797557f80ec6 + revision: 03140d7f4bd9ba474ebfbb6256e84a9089248e67 path: modules/hal/libmetal groups: - hal @@ -267,69 +271,56 @@ manifest: - fs revision: ca583fd297ceb48bced3c2548600dc615d67af24 - name: loramac-node - revision: 3029c9f304bf46a6e5205f3c8455dbc23108efec + revision: 842413c5fb98707eb5f26e619e8e792453877897 path: modules/lib/loramac-node - name: lvgl - revision: 8a6a2d1d29d17d1e4bdc94c243c146a39d635fdd + revision: 7c61a4cec26402d20c845c95dcad0e39dcd319f8 path: modules/lib/gui/lvgl - - name: lz4 - revision: 8e303c264fc21c2116dc612658003a22e933124d - path: modules/lib/lz4 - name: mbedtls - revision: c38dc78d9a8dcbe43b898cc1171ab33ba3e6fc26 + revision: 7053083b0cff8462464e3cbb826e87852fc03da6 path: modules/crypto/mbedtls groups: - crypto - name: mcuboot - revision: 11ecbf639d826c084973beed709a63d51d9b684e + revision: 0c0470e294dcfb52aab92299356a5f3caa0aa52b path: bootloader/mcuboot - name: mipi-sys-t path: modules/debug/mipi-sys-t groups: - debug revision: a819419603a2dfcb47f7f39092e1bc112e45d1ef - - name: nanopb - revision: 42fa8b211e946b90b9d968523fce7b1cfe27617e - path: modules/lib/nanopb - name: net-tools - revision: e0828aa9629b533644dc96ff6d1295c939bd713c + revision: d68ee9d17648a1bb3729c2023abfcb735dfe92fa path: tools/net-tools groups: - tools - name: nrf_hw_models - revision: 57b61a9a2da75c860f15ca79522b24d57992df2c + revision: a715dcc179f1a71f51c574165958b72fe932ae3f path: modules/bsim_hw_models/nrf_hw_models - name: open-amp - revision: 42b7c577714b8f22ce82a901e19c1814af4609a8 + revision: 214f9fc1539f8e5937c0474cb6ee29b6dcb2d4b8 path: modules/lib/open-amp - name: openthread revision: 4ed44bc7d58d9a98c6cca13a50d38129045ab3df path: modules/lib/openthread + - name: percepio + path: modules/debug/percepio + revision: 0fbc5b72aeab8a6434523a3a7bc8111c17f0bc73 + groups: + - debug - name: picolibc path: modules/lib/picolibc - revision: d07c38ff051386f8e09a143ea0a6c1d6d66dd1d8 + revision: 1a5c603b9f8e228f9459bdafedad15ea28efc700 - name: segger revision: 9d0191285956cef43daf411edc2f1a7788346def path: modules/debug/segger groups: - debug - - name: sof - revision: ee40f61b5725b6615f1abea4a78cc4d90ce144b8 - path: modules/audio/sof - - name: tflite-micro - revision: 9156d050927012da87079064db59d07f03b8baf6 - path: modules/lib/tflite-micro - repo-path: tflite-micro - name: tinycrypt revision: 3e9a49d2672ec01435ffbf0d788db6d95ef28de0 path: modules/crypto/tinycrypt groups: - crypto - - name: TraceRecorderSource - revision: 1ede7ce8e7ab226e9a84d95266241ba3f38d91d2 - path: modules/debug/TraceRecorder - groups: - - debug - name: trusted-firmware-m revision: 33c0f47bcb19721a5c33e6fe1eee9225d00bb5bc path: modules/tee/tf-m/trusted-firmware-m @@ -340,28 +331,12 @@ manifest: path: modules/tee/tf-a/trusted-firmware-a groups: - tee - - name: tf-m-tests - revision: a878426da78fbd1486dfc29d6c6b82be4ee79e72 - path: modules/tee/tf-m/tf-m-tests - groups: - - tee - - name: psa-arch-tests - revision: 6a17330e0dfb5f319730f974d5b05f7b7f04757b - path: modules/tee/tf-m/psa-arch-tests - groups: - - tee - name: uoscore-uedhoc revision: 5fe2cb613bd7e4590bd1b00c2adf181ac0229379 path: modules/lib/uoscore-uedhoc - name: zcbor revision: 67fd8bb88d3136738661fa8bb5f9989103f4599e path: modules/lib/zcbor - - name: zscilib - path: modules/lib/zscilib - revision: 34c3432e81085bb717e4871d21ca419ae0058ec5 - - name: thrift - path: modules/lib/thrift - revision: 10023645a0e6cb7ce23fcd7fd3dbac9f18df6234 self: path: zephyr